diff --git a/.gn b/.gn index ce525292541c06c1409596d46c58cfbb07117957..41187fd2f58acf8a4a0cc797decdec7d5b826cbc 100644 --- a/.gn +++ b/.gn @@ -8,8 +8,10 @@ secondary_source = "//build/secondary/" default_args = { v8_extra_library_files = [] v8_experimental_extra_library_files = [] - v8_enable_inspector = false # Turns on compiler optimizations in V8 in Debug build. v8_optimized_debug = true + + # PDFium does not want to switch to C++14 yet. + use_cxx11 = true } diff --git a/AUTHORS b/AUTHORS index 6c2a2959906052837e25999b37535f16a0ac7702..ee6fc932c17f35e497cd1b77913c373406e293e0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,8 +13,10 @@ Antonio Gomes Brett Wilson Bruce Dawson Chery Cherian +Claudio DeSouza Chris Palmer Dan Sinclair +Felix Kauselmann Finnur Thorarinsson GiWan Go Jiang Jiang @@ -25,6 +27,7 @@ Ke Liu Kostya Serebryany Lei Zhang Lucas Nihlen +Luật Nguyễn Matt Giuca Michael Doppler Miklos Vajna @@ -32,10 +35,15 @@ Nico Weber Peter Kasting Raymes Khoury Reid Kleckner +Ryan Wiley Robert Sesek Sam Clegg Thomas Sepez +Wang Qing +Collabora Ltd. <*@collabora.co.uk> DocsCorp Pty Ltd. <*@docscorp.com> Foxit Software Inc <*@foxitsoftware.com> Google Inc. <*@google.com> +LG Electronics, Inc. <*@lge.com> +Loongson Technology Corporation Limited. <*@loongson.cn> diff --git a/Android.bp b/Android.bp index 766ee3948e3640ba8c5a530cdb4261dfe8b2793a..d11b36ecb96e30332ddcd298d9c0f4762a930df5 100644 --- a/Android.bp +++ b/Android.bp @@ -1,5 +1,5 @@ cc_defaults { - name: "pdfium-defaults", + name: "pdfium-common", cflags: [ "-O3", "-fstrict-aliasing", @@ -10,7 +10,14 @@ cc_defaults { "-Wall", "-Wno-non-virtual-dtor", "-Wno-null-pointer-arithmetic", + "-Wno-unused-parameter", + "-Wno-sign-compare", + "-Wno-missing-field-initializers", "-Werror", + + "-DOPJ_STATIC", + "-DPNG_PREFIX", + "-DPNG_USE_READ_MACROS", ], arch: { @@ -19,14 +26,34 @@ cc_defaults { }, }, - header_libs: ["pdfium-headers"], + header_libs: [ + "pdfium-headers", + "pdfium-third-party-headers" + ], +} + +cc_defaults { + name: "pdfium-core", + cflags: [ + "-DV8_DEPRECATION_WARNINGS", + ], + + defaults: [ + "pdfium-common" + ] } + cc_library_headers { name: "pdfium-headers", export_include_dirs: ["."], } +cc_library_headers { + name: "pdfium-third-party-headers", + export_include_dirs: ["third_party"], +} + build = [ "pdfiumfdrm.bp", "pdfiumfpdfapi.bp", @@ -35,11 +62,10 @@ build = [ "pdfiumfxcodec.bp", "pdfiumfxcrt.bp", "pdfiumfxge.bp", - - "pdfiumjavascript.bp", + "pdfiumpwl.bp", "pdfiumformfiller.bp", - "pdfiumfxedit.bp", - "pdfiumpdfwindow.bp", + + "pdfiumfxjs.bp", "pdfium.bp", ] diff --git a/BUILD.gn b/BUILD.gn index de7f21b1302824687df8b705bce4d2bd4829cad8..c771b819103c08c217590cd33b496c0802c3ceb4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2,31 +2,30 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/freetype/freetype.gni") +import("//build/config/jumbo.gni") import("//testing/test.gni") import("pdfium.gni") +group("freetype_common") { + public_deps = [] + if (pdf_bundle_freetype) { + public_deps += [ "third_party:fx_freetype" ] + } else { + public_deps += [ "//build/config/freetype" ] + } +} + config("pdfium_common_config") { cflags = [] ldflags = [] - include_dirs = [ - ".", - "third_party/freetype/include", - "third_party/freetype/include/freetype", - ] + include_dirs = [ "." ] defines = [ "OPJ_STATIC", "PNG_PREFIX", "PNG_USE_READ_MACROS", ] - if (pdf_use_skia) { - defines += [ "_SKIA_SUPPORT_" ] - } - - if (pdf_use_skia_paths) { - defines += [ "_SKIA_SUPPORT_PATHS_" ] - } - if (pdf_enable_v8) { defines += [ "PDF_ENABLE_V8" ] } @@ -47,6 +46,14 @@ config("pdfium_common_config") { } } + if (pdf_use_skia) { + defines += [ "_SKIA_SUPPORT_" ] + } + + if (pdf_use_skia_paths) { + defines += [ "_SKIA_SUPPORT_PATHS_" ] + } + if (pdf_use_win32_gdi) { defines += [ "PDFIUM_PRINT_TEXT_WITH_GDI" ] } @@ -59,6 +66,11 @@ config("pdfium_common_config") { ] ldflags += [ "--coverage" ] } + + if (is_win) { + # Assume UTF-8 by default to avoid code page dependencies. + cflags += [ "/utf-8" ] + } } config("pdfium_core_config") { @@ -74,7 +86,11 @@ config("pdfium_core_config") { } } if (is_win) { - cflags += [ "/wd4267" ] + cflags += [ + "/wd4267", + "/wd4324", + "/wd4577", + ] } } @@ -85,7 +101,7 @@ config("xfa_warnings") { } } -static_library("pdfium") { +jumbo_static_library("pdfium") { sources = [ "fpdfsdk/cba_annotiterator.cpp", "fpdfsdk/cba_annotiterator.h", @@ -121,6 +137,9 @@ static_library("pdfium") { "fpdfsdk/fpdf_structtree.cpp", "fpdfsdk/fpdf_sysfontinfo.cpp", "fpdfsdk/fpdf_transformpage.cpp", + "fpdfsdk/fpdfannot.cpp", + "fpdfsdk/fpdfattachment.cpp", + "fpdfsdk/fpdfcatalog.cpp", "fpdfsdk/fpdfdoc.cpp", "fpdfsdk/fpdfeditimg.cpp", "fpdfsdk/fpdfeditpage.cpp", @@ -133,10 +152,16 @@ static_library("pdfium") { "fpdfsdk/fpdfview.cpp", "fpdfsdk/fsdk_actionhandler.cpp", "fpdfsdk/fsdk_actionhandler.h", + "fpdfsdk/fsdk_filewriteadapter.cpp", + "fpdfsdk/fsdk_filewriteadapter.h", "fpdfsdk/fsdk_pauseadapter.cpp", "fpdfsdk/fsdk_pauseadapter.h", "fpdfsdk/pdfsdk_fieldaction.cpp", "fpdfsdk/pdfsdk_fieldaction.h", + "public/cpp/fpdf_deleters.h", + "public/fpdf_annot.h", + "public/fpdf_attachment.h", + "public/fpdf_catalog.h", "public/fpdf_dataavail.h", "public/fpdf_doc.h", "public/fpdf_edit.h", @@ -166,10 +191,9 @@ static_library("pdfium") { ":fpdftext", ":fxcodec", ":fxcrt", - ":fxedit", ":fxge", - ":javascript", - ":pdfwindow", + ":fxjs", + ":pwl", "third_party:bigint", "third_party:pdfium_base", ] @@ -203,14 +227,12 @@ static_library("pdfium") { ] } - if (pdfium_bundle_freetype) { - deps += [ "third_party:fx_freetype" ] - } else { - libs += [ "freetype" ] + if (pdf_is_complete_lib) { + complete_static_lib = true } } -static_library("test_support") { +jumbo_static_library("test_support") { testonly = true sources = [ "testing/fx_string_testhelpers.cpp", @@ -243,6 +265,19 @@ static_library("test_support") { configs += [ ":pdfium_core_config" ] } +jumbo_static_library("image_diff") { + testonly = true + sources = [ + "testing/image_diff/image_diff_png.cpp", + "testing/image_diff/image_diff_png.h", + ] + configs += [ ":pdfium_core_config" ] + deps = [] + if (!pdf_enable_xfa) { + deps += [ "third_party:png" ] + } +} + # Targets below this are only visible within this file (and to the # top-level gn_visibility target used to help gn_all build everything). visibility = [ @@ -250,7 +285,7 @@ visibility = [ "//:gn_visibility", ] -static_library("fdrm") { +jumbo_static_library("fdrm") { sources = [ "core/fdrm/crypto/fx_crypt.cpp", "core/fdrm/crypto/fx_crypt.h", @@ -263,12 +298,10 @@ static_library("fdrm") { ] } -static_library("fpdfdoc") { +jumbo_static_library("fpdfdoc") { sources = [ "core/fpdfdoc/cline.cpp", "core/fpdfdoc/cline.h", - "core/fpdfdoc/clines.cpp", - "core/fpdfdoc/clines.h", "core/fpdfdoc/cpdf_aaction.cpp", "core/fpdfdoc/cpdf_aaction.h", "core/fpdfdoc/cpdf_action.cpp", @@ -315,14 +348,14 @@ static_library("fpdfdoc") { "core/fpdfdoc/cpdf_occontext.h", "core/fpdfdoc/cpdf_pagelabel.cpp", "core/fpdfdoc/cpdf_pagelabel.h", + "core/fpdfdoc/cpdf_structelement.cpp", + "core/fpdfdoc/cpdf_structelement.h", + "core/fpdfdoc/cpdf_structtree.cpp", + "core/fpdfdoc/cpdf_structtree.h", "core/fpdfdoc/cpdf_variabletext.cpp", "core/fpdfdoc/cpdf_variabletext.h", "core/fpdfdoc/cpdf_viewerpreferences.cpp", "core/fpdfdoc/cpdf_viewerpreferences.h", - "core/fpdfdoc/cpvt_arraytemplate.h", - "core/fpdfdoc/cpvt_color.cpp", - "core/fpdfdoc/cpvt_color.h", - "core/fpdfdoc/cpvt_dash.h", "core/fpdfdoc/cpvt_floatrect.h", "core/fpdfdoc/cpvt_fontmap.cpp", "core/fpdfdoc/cpvt_fontmap.h", @@ -330,25 +363,17 @@ static_library("fpdfdoc") { "core/fpdfdoc/cpvt_generateap.h", "core/fpdfdoc/cpvt_line.h", "core/fpdfdoc/cpvt_lineinfo.h", - "core/fpdfdoc/cpvt_secprops.h", - "core/fpdfdoc/cpvt_section.h", - "core/fpdfdoc/cpvt_sectioninfo.cpp", - "core/fpdfdoc/cpvt_sectioninfo.h", "core/fpdfdoc/cpvt_word.h", "core/fpdfdoc/cpvt_wordinfo.cpp", "core/fpdfdoc/cpvt_wordinfo.h", "core/fpdfdoc/cpvt_wordplace.h", - "core/fpdfdoc/cpvt_wordprops.h", "core/fpdfdoc/cpvt_wordrange.h", "core/fpdfdoc/csection.cpp", "core/fpdfdoc/csection.h", "core/fpdfdoc/ctypeset.cpp", "core/fpdfdoc/ctypeset.h", - "core/fpdfdoc/doc_tagged.cpp", - "core/fpdfdoc/fpdf_tagged.h", "core/fpdfdoc/ipdf_formnotify.h", "core/fpdfdoc/ipvt_fontmap.h", - "core/fpdfdoc/tagged_int.h", ] configs += [ ":pdfium_core_config" ] deps = [ @@ -356,7 +381,7 @@ static_library("fpdfdoc") { ] } -static_library("fpdfapi") { +jumbo_static_library("fpdfapi") { sources = [ "core/fpdfapi/cmaps/CNS1/Adobe-CNS1-UCS2_5.cpp", "core/fpdfapi/cmaps/CNS1/B5pc-H_0.cpp", @@ -425,19 +450,38 @@ static_library("fpdfapi") { "core/fpdfapi/cpdf_modulemgr.h", "core/fpdfapi/cpdf_pagerendercontext.cpp", "core/fpdfapi/cpdf_pagerendercontext.h", + "core/fpdfapi/edit/cpdf_creator.cpp", "core/fpdfapi/edit/cpdf_creator.h", + "core/fpdfapi/edit/cpdf_encryptor.cpp", + "core/fpdfapi/edit/cpdf_encryptor.h", + "core/fpdfapi/edit/cpdf_flateencoder.cpp", + "core/fpdfapi/edit/cpdf_flateencoder.h", "core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp", "core/fpdfapi/edit/cpdf_pagecontentgenerator.h", - "core/fpdfapi/edit/editint.h", - "core/fpdfapi/edit/fpdf_edit_create.cpp", + "core/fpdfapi/font/cfx_cttgsubtable.cpp", + "core/fpdfapi/font/cfx_cttgsubtable.h", + "core/fpdfapi/font/cfx_stockfontarray.cpp", + "core/fpdfapi/font/cfx_stockfontarray.h", + "core/fpdfapi/font/cpdf_cid2unicodemap.cpp", + "core/fpdfapi/font/cpdf_cid2unicodemap.h", "core/fpdfapi/font/cpdf_cidfont.cpp", "core/fpdfapi/font/cpdf_cidfont.h", + "core/fpdfapi/font/cpdf_cmap.cpp", + "core/fpdfapi/font/cpdf_cmap.h", + "core/fpdfapi/font/cpdf_cmapmanager.cpp", + "core/fpdfapi/font/cpdf_cmapmanager.h", + "core/fpdfapi/font/cpdf_cmapparser.cpp", + "core/fpdfapi/font/cpdf_cmapparser.h", "core/fpdfapi/font/cpdf_font.cpp", "core/fpdfapi/font/cpdf_font.h", "core/fpdfapi/font/cpdf_fontencoding.cpp", "core/fpdfapi/font/cpdf_fontencoding.h", + "core/fpdfapi/font/cpdf_fontglobals.cpp", + "core/fpdfapi/font/cpdf_fontglobals.h", "core/fpdfapi/font/cpdf_simplefont.cpp", "core/fpdfapi/font/cpdf_simplefont.h", + "core/fpdfapi/font/cpdf_tounicodemap.cpp", + "core/fpdfapi/font/cpdf_tounicodemap.h", "core/fpdfapi/font/cpdf_truetypefont.cpp", "core/fpdfapi/font/cpdf_truetypefont.h", "core/fpdfapi/font/cpdf_type1font.cpp", @@ -446,11 +490,6 @@ static_library("fpdfapi") { "core/fpdfapi/font/cpdf_type3char.h", "core/fpdfapi/font/cpdf_type3font.cpp", "core/fpdfapi/font/cpdf_type3font.h", - "core/fpdfapi/font/font_int.h", - "core/fpdfapi/font/fpdf_font.cpp", - "core/fpdfapi/font/fpdf_font_cid.cpp", - "core/fpdfapi/font/ttgsubtable.cpp", - "core/fpdfapi/font/ttgsubtable.h", "core/fpdfapi/page/cpdf_allstates.cpp", "core/fpdfapi/page/cpdf_allstates.h", "core/fpdfapi/page/cpdf_clippath.cpp", @@ -468,16 +507,24 @@ static_library("fpdfapi") { "core/fpdfapi/page/cpdf_contentparser.cpp", "core/fpdfapi/page/cpdf_contentparser.h", "core/fpdfapi/page/cpdf_countedobject.h", + "core/fpdfapi/page/cpdf_devicecs.cpp", + "core/fpdfapi/page/cpdf_devicecs.h", "core/fpdfapi/page/cpdf_docpagedata.cpp", "core/fpdfapi/page/cpdf_docpagedata.h", + "core/fpdfapi/page/cpdf_expintfunc.cpp", + "core/fpdfapi/page/cpdf_expintfunc.h", "core/fpdfapi/page/cpdf_form.cpp", "core/fpdfapi/page/cpdf_form.h", "core/fpdfapi/page/cpdf_formobject.cpp", "core/fpdfapi/page/cpdf_formobject.h", + "core/fpdfapi/page/cpdf_function.cpp", + "core/fpdfapi/page/cpdf_function.h", "core/fpdfapi/page/cpdf_generalstate.cpp", "core/fpdfapi/page/cpdf_generalstate.h", "core/fpdfapi/page/cpdf_graphicstates.cpp", "core/fpdfapi/page/cpdf_graphicstates.h", + "core/fpdfapi/page/cpdf_iccprofile.cpp", + "core/fpdfapi/page/cpdf_iccprofile.h", "core/fpdfapi/page/cpdf_image.cpp", "core/fpdfapi/page/cpdf_image.h", "core/fpdfapi/page/cpdf_imageobject.cpp", @@ -500,10 +547,20 @@ static_library("fpdfapi") { "core/fpdfapi/page/cpdf_pathobject.h", "core/fpdfapi/page/cpdf_pattern.cpp", "core/fpdfapi/page/cpdf_pattern.h", + "core/fpdfapi/page/cpdf_patterncs.cpp", + "core/fpdfapi/page/cpdf_patterncs.h", + "core/fpdfapi/page/cpdf_psengine.cpp", + "core/fpdfapi/page/cpdf_psengine.h", + "core/fpdfapi/page/cpdf_psfunc.cpp", + "core/fpdfapi/page/cpdf_psfunc.h", + "core/fpdfapi/page/cpdf_sampledfunc.cpp", + "core/fpdfapi/page/cpdf_sampledfunc.h", "core/fpdfapi/page/cpdf_shadingobject.cpp", "core/fpdfapi/page/cpdf_shadingobject.h", "core/fpdfapi/page/cpdf_shadingpattern.cpp", "core/fpdfapi/page/cpdf_shadingpattern.h", + "core/fpdfapi/page/cpdf_stitchfunc.cpp", + "core/fpdfapi/page/cpdf_stitchfunc.h", "core/fpdfapi/page/cpdf_streamcontentparser.cpp", "core/fpdfapi/page/cpdf_streamcontentparser.h", "core/fpdfapi/page/cpdf_streamparser.cpp", @@ -514,15 +571,14 @@ static_library("fpdfapi") { "core/fpdfapi/page/cpdf_textstate.h", "core/fpdfapi/page/cpdf_tilingpattern.cpp", "core/fpdfapi/page/cpdf_tilingpattern.h", - "core/fpdfapi/page/fpdf_page_colors.cpp", - "core/fpdfapi/page/fpdf_page_func.cpp", - "core/fpdfapi/page/pageint.h", "core/fpdfapi/parser/cfdf_document.cpp", "core/fpdfapi/parser/cfdf_document.h", "core/fpdfapi/parser/cpdf_array.cpp", "core/fpdfapi/parser/cpdf_array.h", "core/fpdfapi/parser/cpdf_boolean.cpp", "core/fpdfapi/parser/cpdf_boolean.h", + "core/fpdfapi/parser/cpdf_cross_ref_avail.cpp", + "core/fpdfapi/parser/cpdf_cross_ref_avail.h", "core/fpdfapi/parser/cpdf_crypto_handler.cpp", "core/fpdfapi/parser/cpdf_crypto_handler.h", "core/fpdfapi/parser/cpdf_data_avail.cpp", @@ -545,8 +601,16 @@ static_library("fpdfapi") { "core/fpdfapi/parser/cpdf_number.h", "core/fpdfapi/parser/cpdf_object.cpp", "core/fpdfapi/parser/cpdf_object.h", + "core/fpdfapi/parser/cpdf_object_avail.cpp", + "core/fpdfapi/parser/cpdf_object_avail.h", + "core/fpdfapi/parser/cpdf_object_walker.cpp", + "core/fpdfapi/parser/cpdf_object_walker.h", + "core/fpdfapi/parser/cpdf_page_object_avail.cpp", + "core/fpdfapi/parser/cpdf_page_object_avail.h", "core/fpdfapi/parser/cpdf_parser.cpp", "core/fpdfapi/parser/cpdf_parser.h", + "core/fpdfapi/parser/cpdf_read_validator.cpp", + "core/fpdfapi/parser/cpdf_read_validator.h", "core/fpdfapi/parser/cpdf_reference.cpp", "core/fpdfapi/parser/cpdf_reference.h", "core/fpdfapi/parser/cpdf_security_handler.cpp", @@ -605,10 +669,11 @@ static_library("fpdfapi") { configs += [ ":pdfium_core_config" ] deps = [ ":fxcrt", + "third_party:lcms2", ] } -static_library("fpdftext") { +jumbo_static_library("fpdftext") { sources = [ "core/fpdftext/cpdf_linkextract.cpp", "core/fpdftext/cpdf_linkextract.h", @@ -625,7 +690,7 @@ static_library("fpdftext") { ] } -static_library("fxcodec") { +jumbo_static_library("fxcodec") { sources = [ "core/fxcodec/JBig2_DocumentContext.h", "core/fxcodec/codec/ccodec_basicmodule.h", @@ -635,7 +700,9 @@ static_library("fxcodec") { "core/fxcodec/codec/ccodec_jbig2module.h", "core/fxcodec/codec/ccodec_jpegmodule.h", "core/fxcodec/codec/ccodec_jpxmodule.h", + "core/fxcodec/codec/ccodec_scanlinedecoder.cpp", "core/fxcodec/codec/ccodec_scanlinedecoder.h", + "core/fxcodec/codec/cjpx_decoder.h", "core/fxcodec/codec/codec_int.h", "core/fxcodec/codec/fx_codec.cpp", "core/fxcodec/codec/fx_codec_fax.cpp", @@ -659,8 +726,6 @@ static_library("fxcodec") { "core/fxcodec/jbig2/JBig2_GrdProc.h", "core/fxcodec/jbig2/JBig2_GrrdProc.cpp", "core/fxcodec/jbig2/JBig2_GrrdProc.h", - "core/fxcodec/jbig2/JBig2_GsidProc.cpp", - "core/fxcodec/jbig2/JBig2_GsidProc.h", "core/fxcodec/jbig2/JBig2_HtrdProc.cpp", "core/fxcodec/jbig2/JBig2_HtrdProc.h", "core/fxcodec/jbig2/JBig2_HuffmanDecoder.cpp", @@ -689,11 +754,9 @@ static_library("fxcodec") { include_dirs = [] deps = [ ":fxcrt", - "third_party:fx_lcms2", "third_party:fx_libopenjpeg", - "third_party:fx_zlib", - - # This is a generic JPEG library dependency. + "third_party:lcms2", + "third_party:zlib", "//third_party:jpeg", ] @@ -709,18 +772,18 @@ static_library("fxcodec") { "core/fxcodec/codec/ccodec_tiffmodule.cpp", "core/fxcodec/codec/ccodec_tiffmodule.h", "core/fxcodec/codec/fx_codec_progress.cpp", - "core/fxcodec/codec/icodec_bmpmodule.h", - "core/fxcodec/codec/icodec_gifmodule.h", - "core/fxcodec/codec/icodec_pngmodule.h", - "core/fxcodec/codec/icodec_tiffmodule.h", + "core/fxcodec/gif/cfx_gif.cpp", + "core/fxcodec/gif/cfx_gif.h", + "core/fxcodec/gif/cfx_gifcontext.cpp", + "core/fxcodec/gif/cfx_gifcontext.h", + "core/fxcodec/gif/cfx_lzwdecompressor.cpp", + "core/fxcodec/gif/cfx_lzwdecompressor.h", "core/fxcodec/lbmp/fx_bmp.cpp", "core/fxcodec/lbmp/fx_bmp.h", - "core/fxcodec/lgif/fx_gif.cpp", - "core/fxcodec/lgif/fx_gif.h", ] deps += [ - "third_party:fx_lpng", "third_party:fx_tiff", + "third_party:png", ] } if (is_posix) { @@ -739,49 +802,77 @@ config("fxge_warnings") { } } -static_library("fxcrt") { +jumbo_static_library("fxcrt") { sources = [ - "core/fxcrt/cfx_maybe_owned.h", - "core/fxcrt/cfx_observable.h", - "core/fxcrt/cfx_retain_ptr.h", - "core/fxcrt/cfx_shared_copy_on_write.h", - "core/fxcrt/cfx_string_c_template.h", - "core/fxcrt/cfx_string_data_template.h", - "core/fxcrt/cfx_string_pool_template.h", - "core/fxcrt/cfx_weak_ptr.h", - "core/fxcrt/extension.h", - "core/fxcrt/fx_basic.h", - "core/fxcrt/fx_basic_array.cpp", - "core/fxcrt/fx_basic_bstring.cpp", - "core/fxcrt/fx_basic_buffer.cpp", - "core/fxcrt/fx_basic_coords.cpp", - "core/fxcrt/fx_basic_gcc.cpp", - "core/fxcrt/fx_basic_memmgr.cpp", - "core/fxcrt/fx_basic_utf.cpp", - "core/fxcrt/fx_basic_util.cpp", - "core/fxcrt/fx_basic_wstring.cpp", + "core/fxcrt/autorestorer.h", + "core/fxcrt/bytestring.cpp", + "core/fxcrt/bytestring.h", + "core/fxcrt/cfx_binarybuf.cpp", + "core/fxcrt/cfx_binarybuf.h", + "core/fxcrt/cfx_bitstream.cpp", + "core/fxcrt/cfx_bitstream.h", + "core/fxcrt/cfx_datetime.cpp", + "core/fxcrt/cfx_datetime.h", + "core/fxcrt/cfx_fileaccess_posix.cpp", + "core/fxcrt/cfx_fileaccess_posix.h", + "core/fxcrt/cfx_fileaccess_windows.cpp", + "core/fxcrt/cfx_fileaccess_windows.h", + "core/fxcrt/cfx_fixedbufgrow.h", + "core/fxcrt/cfx_memorystream.cpp", + "core/fxcrt/cfx_memorystream.h", + "core/fxcrt/cfx_seekablemultistream.cpp", + "core/fxcrt/cfx_seekablemultistream.h", + "core/fxcrt/cfx_utf8decoder.cpp", + "core/fxcrt/cfx_utf8decoder.h", + "core/fxcrt/cfx_widetextbuf.cpp", + "core/fxcrt/cfx_widetextbuf.h", "core/fxcrt/fx_bidi.cpp", "core/fxcrt/fx_bidi.h", + "core/fxcrt/fx_codepage.h", + "core/fxcrt/fx_coordinates.cpp", "core/fxcrt/fx_coordinates.h", - "core/fxcrt/fx_ext.h", "core/fxcrt/fx_extension.cpp", + "core/fxcrt/fx_extension.h", + "core/fxcrt/fx_memory.cpp", "core/fxcrt/fx_memory.h", + "core/fxcrt/fx_random.cpp", + "core/fxcrt/fx_random.h", "core/fxcrt/fx_safe_types.h", + "core/fxcrt/fx_stream.cpp", "core/fxcrt/fx_stream.h", + "core/fxcrt/fx_string.cpp", "core/fxcrt/fx_string.h", + "core/fxcrt/fx_system.cpp", "core/fxcrt/fx_system.h", - "core/fxcrt/fx_ucd.h", "core/fxcrt/fx_ucddata.cpp", + "core/fxcrt/fx_ucddata.h", "core/fxcrt/fx_unicode.cpp", - "core/fxcrt/fx_xml.h", - "core/fxcrt/fx_xml_composer.cpp", - "core/fxcrt/fx_xml_parser.cpp", - "core/fxcrt/fxcrt_posix.cpp", - "core/fxcrt/fxcrt_posix.h", - "core/fxcrt/fxcrt_stream.cpp", - "core/fxcrt/fxcrt_windows.cpp", - "core/fxcrt/fxcrt_windows.h", - "core/fxcrt/xml_int.h", + "core/fxcrt/fx_unicode.h", + "core/fxcrt/ifx_fileaccess.h", + "core/fxcrt/ifx_pauseindicator.h", + "core/fxcrt/maybe_owned.h", + "core/fxcrt/observable.h", + "core/fxcrt/retain_ptr.h", + "core/fxcrt/shared_copy_on_write.h", + "core/fxcrt/string_data_template.h", + "core/fxcrt/string_pool_template.h", + "core/fxcrt/string_view_template.h", + "core/fxcrt/unowned_ptr.h", + "core/fxcrt/weak_ptr.h", + "core/fxcrt/widestring.cpp", + "core/fxcrt/widestring.h", + "core/fxcrt/xml/cxml_attritem.cpp", + "core/fxcrt/xml/cxml_attritem.h", + "core/fxcrt/xml/cxml_content.cpp", + "core/fxcrt/xml/cxml_content.h", + "core/fxcrt/xml/cxml_databufacc.cpp", + "core/fxcrt/xml/cxml_databufacc.h", + "core/fxcrt/xml/cxml_element.cpp", + "core/fxcrt/xml/cxml_element.h", + "core/fxcrt/xml/cxml_object.cpp", + "core/fxcrt/xml/cxml_object.h", + "core/fxcrt/xml/cxml_parser.cpp", + "core/fxcrt/xml/cxml_parser.h", ] configs += [ ":pdfium_core_config" ] visibility += [ "third_party:*" ] @@ -789,52 +880,170 @@ static_library("fxcrt") { "third_party:pdfium_base", ] public_deps = [ + ":freetype_common", "third_party:pdfium_base", ] if (pdf_enable_xfa) { sources += [ + "core/fxcrt/cfx_blockbuffer.cpp", + "core/fxcrt/cfx_blockbuffer.h", + "core/fxcrt/cfx_char.cpp", + "core/fxcrt/cfx_char.h", + "core/fxcrt/cfx_checksumcontext.cpp", + "core/fxcrt/cfx_checksumcontext.h", + "core/fxcrt/cfx_decimal.cpp", + "core/fxcrt/cfx_decimal.h", + "core/fxcrt/cfx_seekablestreamproxy.cpp", + "core/fxcrt/cfx_seekablestreamproxy.h", + "core/fxcrt/css/cfx_css.h", + "core/fxcrt/css/cfx_csscolorvalue.cpp", + "core/fxcrt/css/cfx_csscolorvalue.h", + "core/fxcrt/css/cfx_csscomputedstyle.cpp", + "core/fxcrt/css/cfx_csscomputedstyle.h", + "core/fxcrt/css/cfx_csscustomproperty.cpp", + "core/fxcrt/css/cfx_csscustomproperty.h", + "core/fxcrt/css/cfx_cssdatatable.cpp", + "core/fxcrt/css/cfx_cssdatatable.h", + "core/fxcrt/css/cfx_cssdeclaration.cpp", + "core/fxcrt/css/cfx_cssdeclaration.h", + "core/fxcrt/css/cfx_cssenumvalue.cpp", + "core/fxcrt/css/cfx_cssenumvalue.h", + "core/fxcrt/css/cfx_cssexttextbuf.cpp", + "core/fxcrt/css/cfx_cssexttextbuf.h", + "core/fxcrt/css/cfx_cssnumbervalue.cpp", + "core/fxcrt/css/cfx_cssnumbervalue.h", + "core/fxcrt/css/cfx_csspropertyholder.cpp", + "core/fxcrt/css/cfx_csspropertyholder.h", + "core/fxcrt/css/cfx_cssrulecollection.cpp", + "core/fxcrt/css/cfx_cssrulecollection.h", + "core/fxcrt/css/cfx_cssselector.cpp", + "core/fxcrt/css/cfx_cssselector.h", + "core/fxcrt/css/cfx_cssstringvalue.cpp", + "core/fxcrt/css/cfx_cssstringvalue.h", + "core/fxcrt/css/cfx_cssstylerule.cpp", + "core/fxcrt/css/cfx_cssstylerule.h", + "core/fxcrt/css/cfx_cssstyleselector.cpp", + "core/fxcrt/css/cfx_cssstyleselector.h", + "core/fxcrt/css/cfx_cssstylesheet.cpp", + "core/fxcrt/css/cfx_cssstylesheet.h", + "core/fxcrt/css/cfx_csssyntaxparser.cpp", + "core/fxcrt/css/cfx_csssyntaxparser.h", + "core/fxcrt/css/cfx_csstextbuf.cpp", + "core/fxcrt/css/cfx_csstextbuf.h", + "core/fxcrt/css/cfx_cssvalue.cpp", + "core/fxcrt/css/cfx_cssvalue.h", + "core/fxcrt/css/cfx_cssvaluelist.cpp", + "core/fxcrt/css/cfx_cssvaluelist.h", + "core/fxcrt/css/cfx_cssvaluelistparser.cpp", + "core/fxcrt/css/cfx_cssvaluelistparser.h", "core/fxcrt/fx_arabic.cpp", "core/fxcrt/fx_arabic.h", - "core/fxcrt/fx_arb.h", + "core/fxcrt/ifx_locale.h", + "core/fxcrt/xml/cfx_saxcontext.cpp", + "core/fxcrt/xml/cfx_saxcontext.h", + "core/fxcrt/xml/cfx_saxreader.cpp", + "core/fxcrt/xml/cfx_saxreader.h", + "core/fxcrt/xml/cfx_saxreaderhandler.cpp", + "core/fxcrt/xml/cfx_saxreaderhandler.h", + "core/fxcrt/xml/cfx_xmlattributenode.cpp", + "core/fxcrt/xml/cfx_xmlattributenode.h", + "core/fxcrt/xml/cfx_xmlchardata.cpp", + "core/fxcrt/xml/cfx_xmlchardata.h", + "core/fxcrt/xml/cfx_xmldoc.cpp", + "core/fxcrt/xml/cfx_xmldoc.h", + "core/fxcrt/xml/cfx_xmlelement.cpp", + "core/fxcrt/xml/cfx_xmlelement.h", + "core/fxcrt/xml/cfx_xmlinstruction.cpp", + "core/fxcrt/xml/cfx_xmlinstruction.h", + "core/fxcrt/xml/cfx_xmlnode.cpp", + "core/fxcrt/xml/cfx_xmlnode.h", + "core/fxcrt/xml/cfx_xmlparser.cpp", + "core/fxcrt/xml/cfx_xmlparser.h", + "core/fxcrt/xml/cfx_xmlsyntaxparser.cpp", + "core/fxcrt/xml/cfx_xmlsyntaxparser.h", + "core/fxcrt/xml/cfx_xmltext.cpp", + "core/fxcrt/xml/cfx_xmltext.h", ] } } -static_library("fxge") { +jumbo_static_library("fxge") { sources = [ + "core/fxge/android/cfpf_skiabufferfont.cpp", "core/fxge/android/cfpf_skiabufferfont.h", "core/fxge/android/cfpf_skiadevicemodule.cpp", "core/fxge/android/cfpf_skiadevicemodule.h", + "core/fxge/android/cfpf_skiafilefont.cpp", "core/fxge/android/cfpf_skiafilefont.h", "core/fxge/android/cfpf_skiafont.cpp", "core/fxge/android/cfpf_skiafont.h", + "core/fxge/android/cfpf_skiafontdescriptor.cpp", "core/fxge/android/cfpf_skiafontdescriptor.h", "core/fxge/android/cfpf_skiafontmgr.cpp", "core/fxge/android/cfpf_skiafontmgr.h", + "core/fxge/android/cfpf_skiapathfont.cpp", "core/fxge/android/cfpf_skiapathfont.h", "core/fxge/android/cfx_androidfontinfo.cpp", "core/fxge/android/cfx_androidfontinfo.h", "core/fxge/android/fx_android_imp.cpp", + "core/fxge/cfx_cliprgn.cpp", + "core/fxge/cfx_cliprgn.h", + "core/fxge/cfx_color.cpp", + "core/fxge/cfx_color.h", + "core/fxge/cfx_defaultrenderdevice.h", + "core/fxge/cfx_facecache.cpp", "core/fxge/cfx_facecache.h", + "core/fxge/cfx_folderfontinfo.cpp", + "core/fxge/cfx_folderfontinfo.h", + "core/fxge/cfx_font.cpp", + "core/fxge/cfx_fontcache.cpp", "core/fxge/cfx_fontcache.h", + "core/fxge/cfx_fontmapper.cpp", "core/fxge/cfx_fontmapper.h", + "core/fxge/cfx_fontmgr.cpp", "core/fxge/cfx_fontmgr.h", - "core/fxge/cfx_fxgedevice.h", + "core/fxge/cfx_gemodule.cpp", "core/fxge/cfx_gemodule.h", + "core/fxge/cfx_graphstate.cpp", "core/fxge/cfx_graphstate.h", + "core/fxge/cfx_graphstatedata.cpp", "core/fxge/cfx_graphstatedata.h", + "core/fxge/cfx_pathdata.cpp", "core/fxge/cfx_pathdata.h", + "core/fxge/cfx_renderdevice.cpp", "core/fxge/cfx_renderdevice.h", + "core/fxge/cfx_substfont.cpp", "core/fxge/cfx_substfont.h", + "core/fxge/cfx_unicodeencoding.cpp", "core/fxge/cfx_unicodeencoding.h", - "core/fxge/cfx_windowsdevice.h", - "core/fxge/dib/dib_int.h", - "core/fxge/dib/fx_dib_composite.cpp", - "core/fxge/dib/fx_dib_convert.cpp", - "core/fxge/dib/fx_dib_engine.cpp", + "core/fxge/cfx_windowsrenderdevice.h", + "core/fxge/cttfontdesc.cpp", + "core/fxge/cttfontdesc.h", + "core/fxge/dib/cfx_bitmapcomposer.cpp", + "core/fxge/dib/cfx_bitmapcomposer.h", + "core/fxge/dib/cfx_bitmapstorer.cpp", + "core/fxge/dib/cfx_bitmapstorer.h", + "core/fxge/dib/cfx_dibextractor.cpp", + "core/fxge/dib/cfx_dibextractor.h", + "core/fxge/dib/cfx_dibitmap.cpp", + "core/fxge/dib/cfx_dibitmap.h", + "core/fxge/dib/cfx_dibsource.cpp", + "core/fxge/dib/cfx_dibsource.h", + "core/fxge/dib/cfx_filtereddib.cpp", + "core/fxge/dib/cfx_filtereddib.h", + "core/fxge/dib/cfx_imagerenderer.cpp", + "core/fxge/dib/cfx_imagerenderer.h", + "core/fxge/dib/cfx_imagestretcher.cpp", + "core/fxge/dib/cfx_imagestretcher.h", + "core/fxge/dib/cfx_imagetransformer.cpp", + "core/fxge/dib/cfx_imagetransformer.h", + "core/fxge/dib/cfx_scanlinecompositor.cpp", + "core/fxge/dib/cfx_scanlinecompositor.h", + "core/fxge/dib/cstretchengine.cpp", + "core/fxge/dib/cstretchengine.h", "core/fxge/dib/fx_dib_main.cpp", - "core/fxge/dib/fx_dib_transform.cpp", + "core/fxge/dib/ifx_scanlinecomposer.h", "core/fxge/fontdata/chromefontdata/FoxitDingbats.cpp", "core/fxge/fontdata/chromefontdata/FoxitFixed.cpp", "core/fxge/fontdata/chromefontdata/FoxitFixedBold.cpp", @@ -856,28 +1065,9 @@ static_library("fxge") { "core/fxge/fx_dib.h", "core/fxge/fx_font.h", "core/fxge/fx_freetype.h", - "core/fxge/ge/cfx_cliprgn.cpp", - "core/fxge/ge/cfx_cliprgn.h", - "core/fxge/ge/cfx_facecache.cpp", - "core/fxge/ge/cfx_folderfontinfo.cpp", - "core/fxge/ge/cfx_folderfontinfo.h", - "core/fxge/ge/cfx_font.cpp", - "core/fxge/ge/cfx_fontcache.cpp", - "core/fxge/ge/cfx_fontmapper.cpp", - "core/fxge/ge/cfx_fontmgr.cpp", - "core/fxge/ge/cfx_gemodule.cpp", - "core/fxge/ge/cfx_graphstate.cpp", - "core/fxge/ge/cfx_graphstatedata.cpp", - "core/fxge/ge/cfx_pathdata.cpp", - "core/fxge/ge/cfx_renderdevice.cpp", - "core/fxge/ge/cfx_substfont.cpp", - "core/fxge/ge/cfx_unicodeencoding.cpp", - "core/fxge/ge/cttfontdesc.cpp", - "core/fxge/ge/cttfontdesc.h", - "core/fxge/ge/fx_ge_fontmap.cpp", - "core/fxge/ge/fx_ge_linux.cpp", - "core/fxge/ge/fx_ge_text.cpp", - "core/fxge/ge/fx_text_int.h", + "core/fxge/fx_ge_fontmap.cpp", + "core/fxge/fx_ge_linux.cpp", + "core/fxge/fx_ge_text.cpp", "core/fxge/ifx_renderdevicedriver.cpp", "core/fxge/ifx_renderdevicedriver.h", "core/fxge/ifx_systemfontinfo.h", @@ -893,10 +1083,17 @@ static_library("fxge") { ":fxcrt", ] + defines = [ "DEFINE_PS_TABLES" ] + if (is_component_build || use_system_freetype) { + # ft_adobe_glyph_list is not exported from the Freetype shared library so we + # need it defined in component builds and builds using system freetype. + defines += [ "DEFINE_PS_TABLES_DATA" ] + } + if (pdf_enable_xfa) { sources += [ + "core/fxge/cfx_unicodeencodingex.cpp", "core/fxge/cfx_unicodeencodingex.h", - "core/fxge/ge/cfx_unicodeencodingex.cpp", ] } @@ -909,10 +1106,10 @@ static_library("fxge") { "core/fxge/agg/fx_agg_driver.h", ] deps += [ "third_party:fx_agg" ] + } - if (is_mac) { - sources += [ "core/fxge/apple/fx_apple_platform.cpp" ] - } + if (is_mac) { + sources += [ "core/fxge/apple/fx_apple_platform.cpp" ] } if (is_win) { @@ -941,14 +1138,40 @@ static_library("fxge") { } } -static_library("fxedit") { +jumbo_static_library("pwl") { sources = [ - "fpdfsdk/fxedit/fx_edit.h", - "fpdfsdk/fxedit/fxet_ap.cpp", - "fpdfsdk/fxedit/fxet_edit.cpp", - "fpdfsdk/fxedit/fxet_edit.h", - "fpdfsdk/fxedit/fxet_list.cpp", - "fpdfsdk/fxedit/fxet_list.h", + "fpdfsdk/pwl/cpwl_appstream.cpp", + "fpdfsdk/pwl/cpwl_appstream.h", + "fpdfsdk/pwl/cpwl_button.cpp", + "fpdfsdk/pwl/cpwl_button.h", + "fpdfsdk/pwl/cpwl_caret.cpp", + "fpdfsdk/pwl/cpwl_caret.h", + "fpdfsdk/pwl/cpwl_combo_box.cpp", + "fpdfsdk/pwl/cpwl_combo_box.h", + "fpdfsdk/pwl/cpwl_edit.cpp", + "fpdfsdk/pwl/cpwl_edit.h", + "fpdfsdk/pwl/cpwl_edit_ctrl.cpp", + "fpdfsdk/pwl/cpwl_edit_ctrl.h", + "fpdfsdk/pwl/cpwl_edit_impl.cpp", + "fpdfsdk/pwl/cpwl_edit_impl.h", + "fpdfsdk/pwl/cpwl_font_map.cpp", + "fpdfsdk/pwl/cpwl_font_map.h", + "fpdfsdk/pwl/cpwl_icon.cpp", + "fpdfsdk/pwl/cpwl_icon.h", + "fpdfsdk/pwl/cpwl_list_box.cpp", + "fpdfsdk/pwl/cpwl_list_box.h", + "fpdfsdk/pwl/cpwl_list_impl.cpp", + "fpdfsdk/pwl/cpwl_list_impl.h", + "fpdfsdk/pwl/cpwl_scroll_bar.cpp", + "fpdfsdk/pwl/cpwl_scroll_bar.h", + "fpdfsdk/pwl/cpwl_special_button.cpp", + "fpdfsdk/pwl/cpwl_special_button.h", + "fpdfsdk/pwl/cpwl_timer.cpp", + "fpdfsdk/pwl/cpwl_timer.h", + "fpdfsdk/pwl/cpwl_timer_handler.cpp", + "fpdfsdk/pwl/cpwl_timer_handler.h", + "fpdfsdk/pwl/cpwl_wnd.cpp", + "fpdfsdk/pwl/cpwl_wnd.h", ] configs += [ ":pdfium_core_config" ] deps = [ @@ -956,45 +1179,10 @@ static_library("fxedit") { ] } -static_library("pdfwindow") { +jumbo_static_library("fxjs") { sources = [ - "fpdfsdk/pdfwindow/PWL_Button.cpp", - "fpdfsdk/pdfwindow/PWL_Button.h", - "fpdfsdk/pdfwindow/PWL_Caret.cpp", - "fpdfsdk/pdfwindow/PWL_Caret.h", - "fpdfsdk/pdfwindow/PWL_ComboBox.cpp", - "fpdfsdk/pdfwindow/PWL_ComboBox.h", - "fpdfsdk/pdfwindow/PWL_Edit.cpp", - "fpdfsdk/pdfwindow/PWL_Edit.h", - "fpdfsdk/pdfwindow/PWL_EditCtrl.cpp", - "fpdfsdk/pdfwindow/PWL_EditCtrl.h", - "fpdfsdk/pdfwindow/PWL_FontMap.cpp", - "fpdfsdk/pdfwindow/PWL_FontMap.h", - "fpdfsdk/pdfwindow/PWL_Icon.cpp", - "fpdfsdk/pdfwindow/PWL_Icon.h", - "fpdfsdk/pdfwindow/PWL_ListBox.cpp", - "fpdfsdk/pdfwindow/PWL_ListBox.h", - "fpdfsdk/pdfwindow/PWL_ScrollBar.cpp", - "fpdfsdk/pdfwindow/PWL_ScrollBar.h", - "fpdfsdk/pdfwindow/PWL_SpecialButton.cpp", - "fpdfsdk/pdfwindow/PWL_SpecialButton.h", - "fpdfsdk/pdfwindow/PWL_Utils.cpp", - "fpdfsdk/pdfwindow/PWL_Utils.h", - "fpdfsdk/pdfwindow/PWL_Wnd.cpp", - "fpdfsdk/pdfwindow/PWL_Wnd.h", - "fpdfsdk/pdfwindow/cpwl_color.cpp", - "fpdfsdk/pdfwindow/cpwl_color.h", - ] - configs += [ ":pdfium_core_config" ] - deps = [ - ":fxcrt", - ] -} - -static_library("javascript") { - sources = [ - "fpdfsdk/javascript/ijs_event_context.h", - "fpdfsdk/javascript/ijs_runtime.h", + "fxjs/ijs_event_context.h", + "fxjs/ijs_runtime.h", ] configs += [ ":pdfium_core_config" ] deps = [ @@ -1003,96 +1191,94 @@ static_library("javascript") { if (pdf_enable_v8) { sources += [ - "fpdfsdk/javascript/Annot.cpp", - "fpdfsdk/javascript/Annot.h", - "fpdfsdk/javascript/Consts.cpp", - "fpdfsdk/javascript/Consts.h", - "fpdfsdk/javascript/Document.cpp", - "fpdfsdk/javascript/Document.h", - "fpdfsdk/javascript/Field.cpp", - "fpdfsdk/javascript/Field.h", - "fpdfsdk/javascript/Icon.cpp", - "fpdfsdk/javascript/Icon.h", - "fpdfsdk/javascript/JS_Define.h", - "fpdfsdk/javascript/JS_EventHandler.cpp", - "fpdfsdk/javascript/JS_EventHandler.h", - "fpdfsdk/javascript/JS_GlobalData.cpp", - "fpdfsdk/javascript/JS_GlobalData.h", - "fpdfsdk/javascript/JS_KeyValue.cpp", - "fpdfsdk/javascript/JS_KeyValue.h", - "fpdfsdk/javascript/JS_Object.cpp", - "fpdfsdk/javascript/JS_Object.h", - "fpdfsdk/javascript/JS_Value.cpp", - "fpdfsdk/javascript/JS_Value.h", - "fpdfsdk/javascript/PublicMethods.cpp", - "fpdfsdk/javascript/PublicMethods.h", - "fpdfsdk/javascript/app.cpp", - "fpdfsdk/javascript/app.h", - "fpdfsdk/javascript/cjs_event_context.cpp", - "fpdfsdk/javascript/cjs_event_context.h", - "fpdfsdk/javascript/cjs_runtime.cpp", - "fpdfsdk/javascript/cjs_runtime.h", - "fpdfsdk/javascript/color.cpp", - "fpdfsdk/javascript/color.h", - "fpdfsdk/javascript/console.cpp", - "fpdfsdk/javascript/console.h", - "fpdfsdk/javascript/event.cpp", - "fpdfsdk/javascript/event.h", - "fpdfsdk/javascript/global.cpp", - "fpdfsdk/javascript/global.h", - "fpdfsdk/javascript/report.cpp", - "fpdfsdk/javascript/report.h", - "fpdfsdk/javascript/resource.cpp", - "fpdfsdk/javascript/resource.h", - "fpdfsdk/javascript/util.cpp", - "fpdfsdk/javascript/util.h", - ] - deps += [ ":fxjs" ] - configs += [ "//v8:external_startup_data" ] - } else { - sources += [ "fpdfsdk/javascript/JS_Runtime_Stub.cpp" ] - } -} - -static_library("formfiller") { - sources = [ - "fpdfsdk/formfiller/cba_fontmap.cpp", - "fpdfsdk/formfiller/cba_fontmap.h", - "fpdfsdk/formfiller/cffl_checkbox.cpp", - "fpdfsdk/formfiller/cffl_checkbox.h", - "fpdfsdk/formfiller/cffl_combobox.cpp", - "fpdfsdk/formfiller/cffl_combobox.h", - "fpdfsdk/formfiller/cffl_formfiller.cpp", - "fpdfsdk/formfiller/cffl_formfiller.h", - "fpdfsdk/formfiller/cffl_interactiveformfiller.cpp", - "fpdfsdk/formfiller/cffl_interactiveformfiller.h", - "fpdfsdk/formfiller/cffl_listbox.cpp", - "fpdfsdk/formfiller/cffl_listbox.h", - "fpdfsdk/formfiller/cffl_pushbutton.cpp", - "fpdfsdk/formfiller/cffl_pushbutton.h", - "fpdfsdk/formfiller/cffl_radiobutton.cpp", - "fpdfsdk/formfiller/cffl_radiobutton.h", - "fpdfsdk/formfiller/cffl_textfield.cpp", - "fpdfsdk/formfiller/cffl_textfield.h", - ] - configs += [ ":pdfium_core_config" ] - deps = [ - ":fxcrt", - ] -} - -if (pdf_enable_v8) { - static_library("fxjs") { - sources = [ + "fxjs/CJX_Define.h", + "fxjs/JS_Define.cpp", + "fxjs/JS_Define.h", + "fxjs/cjs_annot.cpp", + "fxjs/cjs_annot.h", + "fxjs/cjs_app.cpp", + "fxjs/cjs_app.h", + "fxjs/cjs_border.cpp", + "fxjs/cjs_border.h", + "fxjs/cjs_color.cpp", + "fxjs/cjs_color.h", + "fxjs/cjs_console.cpp", + "fxjs/cjs_console.h", + "fxjs/cjs_delaydata.cpp", + "fxjs/cjs_delaydata.h", + "fxjs/cjs_display.cpp", + "fxjs/cjs_display.h", + "fxjs/cjs_document.cpp", + "fxjs/cjs_document.h", + "fxjs/cjs_embedobj.cpp", + "fxjs/cjs_embedobj.h", + "fxjs/cjs_event.cpp", + "fxjs/cjs_event.h", + "fxjs/cjs_event_context.cpp", + "fxjs/cjs_event_context.h", + "fxjs/cjs_eventhandler.cpp", + "fxjs/cjs_eventhandler.h", + "fxjs/cjs_field.cpp", + "fxjs/cjs_field.h", + "fxjs/cjs_font.cpp", + "fxjs/cjs_font.h", + "fxjs/cjs_global.cpp", + "fxjs/cjs_global.h", + "fxjs/cjs_globalarrays.cpp", + "fxjs/cjs_globalarrays.h", + "fxjs/cjs_globalconsts.cpp", + "fxjs/cjs_globalconsts.h", + "fxjs/cjs_globaldata.cpp", + "fxjs/cjs_globaldata.h", + "fxjs/cjs_globalvariablearray.cpp", + "fxjs/cjs_globalvariablearray.h", + "fxjs/cjs_highlight.cpp", + "fxjs/cjs_highlight.h", + "fxjs/cjs_icon.cpp", + "fxjs/cjs_icon.h", + "fxjs/cjs_keyvalue.cpp", + "fxjs/cjs_keyvalue.h", + "fxjs/cjs_object.cpp", + "fxjs/cjs_object.h", + "fxjs/cjs_position.cpp", + "fxjs/cjs_position.h", + "fxjs/cjs_printparamsobj.cpp", + "fxjs/cjs_printparamsobj.h", + "fxjs/cjs_publicmethods.cpp", + "fxjs/cjs_publicmethods.h", + "fxjs/cjs_report.cpp", + "fxjs/cjs_report.h", + "fxjs/cjs_return.cpp", + "fxjs/cjs_return.h", + "fxjs/cjs_runtime.cpp", + "fxjs/cjs_runtime.h", + "fxjs/cjs_scalehow.cpp", + "fxjs/cjs_scalehow.h", + "fxjs/cjs_scalewhen.cpp", + "fxjs/cjs_scalewhen.h", + "fxjs/cjs_style.cpp", + "fxjs/cjs_style.h", + "fxjs/cjs_timerobj.cpp", + "fxjs/cjs_timerobj.h", + "fxjs/cjs_util.cpp", + "fxjs/cjs_util.h", + "fxjs/cjs_v8.cpp", + "fxjs/cjs_v8.h", + "fxjs/cjs_zoomtype.cpp", + "fxjs/cjs_zoomtype.h", "fxjs/fxjs_v8.cpp", "fxjs/fxjs_v8.h", + "fxjs/global_timer.cpp", + "fxjs/global_timer.h", + "fxjs/js_resources.cpp", + "fxjs/js_resources.h", ] - configs += [ ":pdfium_core_config" ] - deps = [ + deps += [ ":fxcrt", "//v8", "//v8:v8_libplatform", ] + configs += [ "//v8:external_startup_data" ] include_dirs = [ "//v8", "//v8/include", @@ -1109,20 +1295,362 @@ if (pdf_enable_v8) { "fxjs/cfxjse_class.h", "fxjs/cfxjse_context.cpp", "fxjs/cfxjse_context.h", - "fxjs/cfxjse_isolatetracker.cpp", + "fxjs/cfxjse_engine.cpp", + "fxjs/cfxjse_engine.h", + "fxjs/cfxjse_formcalc_context.cpp", + "fxjs/cfxjse_formcalc_context.h", "fxjs/cfxjse_isolatetracker.h", + "fxjs/cfxjse_resolveprocessor.cpp", + "fxjs/cfxjse_resolveprocessor.h", "fxjs/cfxjse_runtimedata.cpp", "fxjs/cfxjse_runtimedata.h", "fxjs/cfxjse_value.cpp", "fxjs/cfxjse_value.h", "fxjs/fxjse.h", + "fxjs/xfa/cjx_arc.cpp", + "fxjs/xfa/cjx_arc.h", + "fxjs/xfa/cjx_area.cpp", + "fxjs/xfa/cjx_area.h", + "fxjs/xfa/cjx_assist.cpp", + "fxjs/xfa/cjx_assist.h", + "fxjs/xfa/cjx_barcode.cpp", + "fxjs/xfa/cjx_barcode.h", + "fxjs/xfa/cjx_bind.cpp", + "fxjs/xfa/cjx_bind.h", + "fxjs/xfa/cjx_binditems.cpp", + "fxjs/xfa/cjx_binditems.h", + "fxjs/xfa/cjx_bookend.cpp", + "fxjs/xfa/cjx_bookend.h", + "fxjs/xfa/cjx_boolean.cpp", + "fxjs/xfa/cjx_boolean.h", + "fxjs/xfa/cjx_border.cpp", + "fxjs/xfa/cjx_border.h", + "fxjs/xfa/cjx_break.cpp", + "fxjs/xfa/cjx_break.h", + "fxjs/xfa/cjx_breakafter.cpp", + "fxjs/xfa/cjx_breakafter.h", + "fxjs/xfa/cjx_breakbefore.cpp", + "fxjs/xfa/cjx_breakbefore.h", + "fxjs/xfa/cjx_button.cpp", + "fxjs/xfa/cjx_button.h", + "fxjs/xfa/cjx_calculate.cpp", + "fxjs/xfa/cjx_calculate.h", + "fxjs/xfa/cjx_caption.cpp", + "fxjs/xfa/cjx_caption.h", + "fxjs/xfa/cjx_certificate.cpp", + "fxjs/xfa/cjx_certificate.h", + "fxjs/xfa/cjx_certificates.cpp", + "fxjs/xfa/cjx_certificates.h", + "fxjs/xfa/cjx_checkbutton.cpp", + "fxjs/xfa/cjx_checkbutton.h", + "fxjs/xfa/cjx_choicelist.cpp", + "fxjs/xfa/cjx_choicelist.h", + "fxjs/xfa/cjx_color.cpp", + "fxjs/xfa/cjx_color.h", + "fxjs/xfa/cjx_comb.cpp", + "fxjs/xfa/cjx_comb.h", + "fxjs/xfa/cjx_command.cpp", + "fxjs/xfa/cjx_command.h", + "fxjs/xfa/cjx_connect.cpp", + "fxjs/xfa/cjx_connect.h", + "fxjs/xfa/cjx_connectstring.cpp", + "fxjs/xfa/cjx_connectstring.h", + "fxjs/xfa/cjx_container.cpp", + "fxjs/xfa/cjx_container.h", + "fxjs/xfa/cjx_content.cpp", + "fxjs/xfa/cjx_content.h", + "fxjs/xfa/cjx_contentarea.cpp", + "fxjs/xfa/cjx_contentarea.h", + "fxjs/xfa/cjx_corner.cpp", + "fxjs/xfa/cjx_corner.h", + "fxjs/xfa/cjx_datavalue.cpp", + "fxjs/xfa/cjx_datavalue.h", + "fxjs/xfa/cjx_datawindow.cpp", + "fxjs/xfa/cjx_datawindow.h", + "fxjs/xfa/cjx_date.cpp", + "fxjs/xfa/cjx_date.h", + "fxjs/xfa/cjx_datetime.cpp", + "fxjs/xfa/cjx_datetime.h", + "fxjs/xfa/cjx_datetimeedit.cpp", + "fxjs/xfa/cjx_datetimeedit.h", + "fxjs/xfa/cjx_decimal.cpp", + "fxjs/xfa/cjx_decimal.h", + "fxjs/xfa/cjx_defaultui.cpp", + "fxjs/xfa/cjx_defaultui.h", + "fxjs/xfa/cjx_delete.cpp", + "fxjs/xfa/cjx_delete.h", + "fxjs/xfa/cjx_delta.cpp", + "fxjs/xfa/cjx_delta.h", + "fxjs/xfa/cjx_deltas.cpp", + "fxjs/xfa/cjx_deltas.h", + "fxjs/xfa/cjx_desc.cpp", + "fxjs/xfa/cjx_desc.h", + "fxjs/xfa/cjx_digestmethod.cpp", + "fxjs/xfa/cjx_digestmethod.h", + "fxjs/xfa/cjx_digestmethods.cpp", + "fxjs/xfa/cjx_digestmethods.h", + "fxjs/xfa/cjx_draw.cpp", + "fxjs/xfa/cjx_draw.h", + "fxjs/xfa/cjx_edge.cpp", + "fxjs/xfa/cjx_edge.h", + "fxjs/xfa/cjx_encoding.cpp", + "fxjs/xfa/cjx_encoding.h", + "fxjs/xfa/cjx_encodings.cpp", + "fxjs/xfa/cjx_encodings.h", + "fxjs/xfa/cjx_encrypt.cpp", + "fxjs/xfa/cjx_encrypt.h", + "fxjs/xfa/cjx_event.cpp", + "fxjs/xfa/cjx_event.h", + "fxjs/xfa/cjx_eventpseudomodel.cpp", + "fxjs/xfa/cjx_eventpseudomodel.h", + "fxjs/xfa/cjx_exclgroup.cpp", + "fxjs/xfa/cjx_exclgroup.h", + "fxjs/xfa/cjx_exdata.cpp", + "fxjs/xfa/cjx_exdata.h", + "fxjs/xfa/cjx_execute.cpp", + "fxjs/xfa/cjx_execute.h", + "fxjs/xfa/cjx_exobject.cpp", + "fxjs/xfa/cjx_exobject.h", + "fxjs/xfa/cjx_extras.cpp", + "fxjs/xfa/cjx_extras.h", + "fxjs/xfa/cjx_field.cpp", + "fxjs/xfa/cjx_field.h", + "fxjs/xfa/cjx_fill.cpp", + "fxjs/xfa/cjx_fill.h", + "fxjs/xfa/cjx_filter.cpp", + "fxjs/xfa/cjx_filter.h", + "fxjs/xfa/cjx_float.cpp", + "fxjs/xfa/cjx_float.h", + "fxjs/xfa/cjx_font.cpp", + "fxjs/xfa/cjx_font.h", + "fxjs/xfa/cjx_form.cpp", + "fxjs/xfa/cjx_form.h", + "fxjs/xfa/cjx_format.cpp", + "fxjs/xfa/cjx_format.h", + "fxjs/xfa/cjx_handler.cpp", + "fxjs/xfa/cjx_handler.h", + "fxjs/xfa/cjx_hostpseudomodel.cpp", + "fxjs/xfa/cjx_hostpseudomodel.h", + "fxjs/xfa/cjx_image.cpp", + "fxjs/xfa/cjx_image.h", + "fxjs/xfa/cjx_imageedit.cpp", + "fxjs/xfa/cjx_imageedit.h", + "fxjs/xfa/cjx_insert.cpp", + "fxjs/xfa/cjx_insert.h", + "fxjs/xfa/cjx_instancemanager.cpp", + "fxjs/xfa/cjx_instancemanager.h", + "fxjs/xfa/cjx_integer.cpp", + "fxjs/xfa/cjx_integer.h", + "fxjs/xfa/cjx_issuers.cpp", + "fxjs/xfa/cjx_issuers.h", + "fxjs/xfa/cjx_items.cpp", + "fxjs/xfa/cjx_items.h", + "fxjs/xfa/cjx_keep.cpp", + "fxjs/xfa/cjx_keep.h", + "fxjs/xfa/cjx_keyusage.cpp", + "fxjs/xfa/cjx_keyusage.h", + "fxjs/xfa/cjx_layoutpseudomodel.cpp", + "fxjs/xfa/cjx_layoutpseudomodel.h", + "fxjs/xfa/cjx_line.cpp", + "fxjs/xfa/cjx_line.h", + "fxjs/xfa/cjx_linear.cpp", + "fxjs/xfa/cjx_linear.h", + "fxjs/xfa/cjx_list.cpp", + "fxjs/xfa/cjx_list.h", + "fxjs/xfa/cjx_logpseudomodel.cpp", + "fxjs/xfa/cjx_logpseudomodel.h", + "fxjs/xfa/cjx_manifest.cpp", + "fxjs/xfa/cjx_manifest.h", + "fxjs/xfa/cjx_map.cpp", + "fxjs/xfa/cjx_map.h", + "fxjs/xfa/cjx_margin.cpp", + "fxjs/xfa/cjx_margin.h", + "fxjs/xfa/cjx_mdp.cpp", + "fxjs/xfa/cjx_mdp.h", + "fxjs/xfa/cjx_medium.cpp", + "fxjs/xfa/cjx_medium.h", + "fxjs/xfa/cjx_message.cpp", + "fxjs/xfa/cjx_message.h", + "fxjs/xfa/cjx_model.cpp", + "fxjs/xfa/cjx_model.h", + "fxjs/xfa/cjx_node.cpp", + "fxjs/xfa/cjx_node.h", + "fxjs/xfa/cjx_numericedit.cpp", + "fxjs/xfa/cjx_numericedit.h", + "fxjs/xfa/cjx_object.cpp", + "fxjs/xfa/cjx_object.h", + "fxjs/xfa/cjx_occur.cpp", + "fxjs/xfa/cjx_occur.h", + "fxjs/xfa/cjx_oid.cpp", + "fxjs/xfa/cjx_oid.h", + "fxjs/xfa/cjx_oids.cpp", + "fxjs/xfa/cjx_oids.h", + "fxjs/xfa/cjx_operation.cpp", + "fxjs/xfa/cjx_operation.h", + "fxjs/xfa/cjx_overflow.cpp", + "fxjs/xfa/cjx_overflow.h", + "fxjs/xfa/cjx_packet.cpp", + "fxjs/xfa/cjx_packet.h", + "fxjs/xfa/cjx_pagearea.cpp", + "fxjs/xfa/cjx_pagearea.h", + "fxjs/xfa/cjx_pageset.cpp", + "fxjs/xfa/cjx_pageset.h", + "fxjs/xfa/cjx_para.cpp", + "fxjs/xfa/cjx_para.h", + "fxjs/xfa/cjx_password.cpp", + "fxjs/xfa/cjx_password.h", + "fxjs/xfa/cjx_passwordedit.cpp", + "fxjs/xfa/cjx_passwordedit.h", + "fxjs/xfa/cjx_pattern.cpp", + "fxjs/xfa/cjx_pattern.h", + "fxjs/xfa/cjx_picture.cpp", + "fxjs/xfa/cjx_picture.h", + "fxjs/xfa/cjx_query.cpp", + "fxjs/xfa/cjx_query.h", + "fxjs/xfa/cjx_radial.cpp", + "fxjs/xfa/cjx_radial.h", + "fxjs/xfa/cjx_reason.cpp", + "fxjs/xfa/cjx_reason.h", + "fxjs/xfa/cjx_reasons.cpp", + "fxjs/xfa/cjx_reasons.h", + "fxjs/xfa/cjx_recordset.cpp", + "fxjs/xfa/cjx_recordset.h", + "fxjs/xfa/cjx_rectangle.cpp", + "fxjs/xfa/cjx_rectangle.h", + "fxjs/xfa/cjx_ref.cpp", + "fxjs/xfa/cjx_ref.h", + "fxjs/xfa/cjx_rootelement.cpp", + "fxjs/xfa/cjx_rootelement.h", + "fxjs/xfa/cjx_script.cpp", + "fxjs/xfa/cjx_script.h", + "fxjs/xfa/cjx_select.cpp", + "fxjs/xfa/cjx_select.h", + "fxjs/xfa/cjx_setproperty.cpp", + "fxjs/xfa/cjx_setproperty.h", + "fxjs/xfa/cjx_signature.cpp", + "fxjs/xfa/cjx_signature.h", + "fxjs/xfa/cjx_signatureproperties.cpp", + "fxjs/xfa/cjx_signatureproperties.h", + "fxjs/xfa/cjx_signaturepseudomodel.cpp", + "fxjs/xfa/cjx_signaturepseudomodel.h", + "fxjs/xfa/cjx_signdata.cpp", + "fxjs/xfa/cjx_signdata.h", + "fxjs/xfa/cjx_signing.cpp", + "fxjs/xfa/cjx_signing.h", + "fxjs/xfa/cjx_soapaction.cpp", + "fxjs/xfa/cjx_soapaction.h", + "fxjs/xfa/cjx_soapaddress.cpp", + "fxjs/xfa/cjx_soapaddress.h", + "fxjs/xfa/cjx_solid.cpp", + "fxjs/xfa/cjx_solid.h", + "fxjs/xfa/cjx_source.cpp", + "fxjs/xfa/cjx_source.h", + "fxjs/xfa/cjx_sourceset.cpp", + "fxjs/xfa/cjx_sourceset.h", + "fxjs/xfa/cjx_speak.cpp", + "fxjs/xfa/cjx_speak.h", + "fxjs/xfa/cjx_stipple.cpp", + "fxjs/xfa/cjx_stipple.h", + "fxjs/xfa/cjx_subform.cpp", + "fxjs/xfa/cjx_subform.h", + "fxjs/xfa/cjx_subformset.cpp", + "fxjs/xfa/cjx_subformset.h", + "fxjs/xfa/cjx_subjectdn.cpp", + "fxjs/xfa/cjx_subjectdn.h", + "fxjs/xfa/cjx_subjectdns.cpp", + "fxjs/xfa/cjx_subjectdns.h", + "fxjs/xfa/cjx_submit.cpp", + "fxjs/xfa/cjx_submit.h", + "fxjs/xfa/cjx_template.cpp", + "fxjs/xfa/cjx_template.h", + "fxjs/xfa/cjx_text.cpp", + "fxjs/xfa/cjx_text.h", + "fxjs/xfa/cjx_textedit.cpp", + "fxjs/xfa/cjx_textedit.h", + "fxjs/xfa/cjx_textnode.cpp", + "fxjs/xfa/cjx_textnode.h", + "fxjs/xfa/cjx_time.cpp", + "fxjs/xfa/cjx_time.h", + "fxjs/xfa/cjx_timestamp.cpp", + "fxjs/xfa/cjx_timestamp.h", + "fxjs/xfa/cjx_tooltip.cpp", + "fxjs/xfa/cjx_tooltip.h", + "fxjs/xfa/cjx_traversal.cpp", + "fxjs/xfa/cjx_traversal.h", + "fxjs/xfa/cjx_traverse.cpp", + "fxjs/xfa/cjx_traverse.h", + "fxjs/xfa/cjx_tree.cpp", + "fxjs/xfa/cjx_tree.h", + "fxjs/xfa/cjx_treelist.cpp", + "fxjs/xfa/cjx_treelist.h", + "fxjs/xfa/cjx_ui.cpp", + "fxjs/xfa/cjx_ui.h", + "fxjs/xfa/cjx_update.cpp", + "fxjs/xfa/cjx_update.h", + "fxjs/xfa/cjx_uri.cpp", + "fxjs/xfa/cjx_uri.h", + "fxjs/xfa/cjx_user.cpp", + "fxjs/xfa/cjx_user.h", + "fxjs/xfa/cjx_validate.cpp", + "fxjs/xfa/cjx_validate.h", + "fxjs/xfa/cjx_value.cpp", + "fxjs/xfa/cjx_value.h", + "fxjs/xfa/cjx_variables.cpp", + "fxjs/xfa/cjx_variables.h", + "fxjs/xfa/cjx_wsdladdress.cpp", + "fxjs/xfa/cjx_wsdladdress.h", + "fxjs/xfa/cjx_wsdlconnection.cpp", + "fxjs/xfa/cjx_wsdlconnection.h", + "fxjs/xfa/cjx_xfa.cpp", + "fxjs/xfa/cjx_xfa.h", + "fxjs/xfa/cjx_xmlconnection.cpp", + "fxjs/xfa/cjx_xmlconnection.h", + "fxjs/xfa/cjx_xsdconnection.cpp", + "fxjs/xfa/cjx_xsdconnection.h", ] } + } else { + sources += [ + "fxjs/cjs_event_context_stub.cpp", + "fxjs/cjs_event_context_stub.h", + "fxjs/cjs_runtimestub.cpp", + ] } } +jumbo_static_library("formfiller") { + sources = [ + "fpdfsdk/formfiller/cba_fontmap.cpp", + "fpdfsdk/formfiller/cba_fontmap.h", + "fpdfsdk/formfiller/cffl_button.cpp", + "fpdfsdk/formfiller/cffl_button.h", + "fpdfsdk/formfiller/cffl_checkbox.cpp", + "fpdfsdk/formfiller/cffl_checkbox.h", + "fpdfsdk/formfiller/cffl_combobox.cpp", + "fpdfsdk/formfiller/cffl_combobox.h", + "fpdfsdk/formfiller/cffl_formfiller.cpp", + "fpdfsdk/formfiller/cffl_formfiller.h", + "fpdfsdk/formfiller/cffl_interactiveformfiller.cpp", + "fpdfsdk/formfiller/cffl_interactiveformfiller.h", + "fpdfsdk/formfiller/cffl_listbox.cpp", + "fpdfsdk/formfiller/cffl_listbox.h", + "fpdfsdk/formfiller/cffl_pushbutton.cpp", + "fpdfsdk/formfiller/cffl_pushbutton.h", + "fpdfsdk/formfiller/cffl_radiobutton.cpp", + "fpdfsdk/formfiller/cffl_radiobutton.h", + "fpdfsdk/formfiller/cffl_textfield.cpp", + "fpdfsdk/formfiller/cffl_textfield.h", + "fpdfsdk/formfiller/cffl_textobject.cpp", + "fpdfsdk/formfiller/cffl_textobject.h", + ] + configs += [ ":pdfium_core_config" ] + deps = [ + ":fxcrt", + ] +} + if (pdf_enable_xfa) { - static_library("fpdfxfa") { + jumbo_static_library("fpdfxfa") { sources = [ "fpdfsdk/fpdfxfa/cpdfxfa_context.cpp", "fpdfsdk/fpdfxfa/cpdfxfa_context.h", @@ -1141,108 +1669,176 @@ if (pdf_enable_xfa) { configs += [ ":pdfium_core_config" ] } + jumbo_static_library("fxbarcode") { + sources = [ + "fxbarcode/BC_Library.cpp", + "fxbarcode/BC_Library.h", + "fxbarcode/BC_TwoDimWriter.cpp", + "fxbarcode/BC_TwoDimWriter.h", + "fxbarcode/BC_UtilCodingConvert.cpp", + "fxbarcode/BC_UtilCodingConvert.h", + "fxbarcode/BC_Utils.cpp", + "fxbarcode/BC_Writer.cpp", + "fxbarcode/BC_Writer.h", + "fxbarcode/cbc_codabar.cpp", + "fxbarcode/cbc_codabar.h", + "fxbarcode/cbc_code128.cpp", + "fxbarcode/cbc_code128.h", + "fxbarcode/cbc_code39.cpp", + "fxbarcode/cbc_code39.h", + "fxbarcode/cbc_codebase.cpp", + "fxbarcode/cbc_codebase.h", + "fxbarcode/cbc_datamatrix.cpp", + "fxbarcode/cbc_datamatrix.h", + "fxbarcode/cbc_ean13.cpp", + "fxbarcode/cbc_ean13.h", + "fxbarcode/cbc_ean8.cpp", + "fxbarcode/cbc_ean8.h", + "fxbarcode/cbc_onecode.cpp", + "fxbarcode/cbc_onecode.h", + "fxbarcode/cbc_pdf417i.cpp", + "fxbarcode/cbc_pdf417i.h", + "fxbarcode/cbc_qrcode.cpp", + "fxbarcode/cbc_qrcode.h", + "fxbarcode/cbc_upca.cpp", + "fxbarcode/cbc_upca.h", + "fxbarcode/common/BC_CommonBitArray.cpp", + "fxbarcode/common/BC_CommonBitArray.h", + "fxbarcode/common/BC_CommonBitMatrix.cpp", + "fxbarcode/common/BC_CommonBitMatrix.h", + "fxbarcode/common/BC_CommonByteArray.cpp", + "fxbarcode/common/BC_CommonByteArray.h", + "fxbarcode/common/BC_CommonByteMatrix.cpp", + "fxbarcode/common/BC_CommonByteMatrix.h", + "fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp", + "fxbarcode/common/reedsolomon/BC_ReedSolomon.h", + "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp", + "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h", + "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp", + "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h", + "fxbarcode/datamatrix/BC_ASCIIEncoder.cpp", + "fxbarcode/datamatrix/BC_ASCIIEncoder.h", + "fxbarcode/datamatrix/BC_Base256Encoder.cpp", + "fxbarcode/datamatrix/BC_Base256Encoder.h", + "fxbarcode/datamatrix/BC_C40Encoder.cpp", + "fxbarcode/datamatrix/BC_C40Encoder.h", + "fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp", + "fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h", + "fxbarcode/datamatrix/BC_DataMatrixWriter.cpp", + "fxbarcode/datamatrix/BC_DataMatrixWriter.h", + "fxbarcode/datamatrix/BC_DefaultPlacement.cpp", + "fxbarcode/datamatrix/BC_DefaultPlacement.h", + "fxbarcode/datamatrix/BC_EdifactEncoder.cpp", + "fxbarcode/datamatrix/BC_EdifactEncoder.h", + "fxbarcode/datamatrix/BC_Encoder.cpp", + "fxbarcode/datamatrix/BC_Encoder.h", + "fxbarcode/datamatrix/BC_EncoderContext.cpp", + "fxbarcode/datamatrix/BC_EncoderContext.h", + "fxbarcode/datamatrix/BC_ErrorCorrection.cpp", + "fxbarcode/datamatrix/BC_ErrorCorrection.h", + "fxbarcode/datamatrix/BC_HighLevelEncoder.cpp", + "fxbarcode/datamatrix/BC_HighLevelEncoder.h", + "fxbarcode/datamatrix/BC_SymbolInfo.cpp", + "fxbarcode/datamatrix/BC_SymbolInfo.h", + "fxbarcode/datamatrix/BC_TextEncoder.cpp", + "fxbarcode/datamatrix/BC_TextEncoder.h", + "fxbarcode/datamatrix/BC_X12Encoder.cpp", + "fxbarcode/datamatrix/BC_X12Encoder.h", + "fxbarcode/oned/BC_OneDimWriter.cpp", + "fxbarcode/oned/BC_OneDimWriter.h", + "fxbarcode/oned/BC_OnedCodaBarWriter.cpp", + "fxbarcode/oned/BC_OnedCodaBarWriter.h", + "fxbarcode/oned/BC_OnedCode128Writer.cpp", + "fxbarcode/oned/BC_OnedCode128Writer.h", + "fxbarcode/oned/BC_OnedCode39Writer.cpp", + "fxbarcode/oned/BC_OnedCode39Writer.h", + "fxbarcode/oned/BC_OnedEAN13Writer.cpp", + "fxbarcode/oned/BC_OnedEAN13Writer.h", + "fxbarcode/oned/BC_OnedEAN8Writer.cpp", + "fxbarcode/oned/BC_OnedEAN8Writer.h", + "fxbarcode/oned/BC_OnedEANChecksum.cpp", + "fxbarcode/oned/BC_OnedEANChecksum.h", + "fxbarcode/oned/BC_OnedUPCAWriter.cpp", + "fxbarcode/oned/BC_OnedUPCAWriter.h", + "fxbarcode/pdf417/BC_PDF417.cpp", + "fxbarcode/pdf417/BC_PDF417.h", + "fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp", + "fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h", + "fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp", + "fxbarcode/pdf417/BC_PDF417BarcodeRow.h", + "fxbarcode/pdf417/BC_PDF417Compaction.cpp", + "fxbarcode/pdf417/BC_PDF417Compaction.h", + "fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp", + "fxbarcode/pdf417/BC_PDF417ErrorCorrection.h", + "fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp", + "fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h", + "fxbarcode/pdf417/BC_PDF417Writer.cpp", + "fxbarcode/pdf417/BC_PDF417Writer.h", + "fxbarcode/qrcode/BC_QRCodeWriter.cpp", + "fxbarcode/qrcode/BC_QRCodeWriter.h", + "fxbarcode/qrcode/BC_QRCoder.cpp", + "fxbarcode/qrcode/BC_QRCoder.h", + "fxbarcode/qrcode/BC_QRCoderBitVector.cpp", + "fxbarcode/qrcode/BC_QRCoderBitVector.h", + "fxbarcode/qrcode/BC_QRCoderBlockPair.cpp", + "fxbarcode/qrcode/BC_QRCoderBlockPair.h", + "fxbarcode/qrcode/BC_QRCoderECBlocks.cpp", + "fxbarcode/qrcode/BC_QRCoderECBlocks.h", + "fxbarcode/qrcode/BC_QRCoderECBlocksData.cpp", + "fxbarcode/qrcode/BC_QRCoderECBlocksData.h", + "fxbarcode/qrcode/BC_QRCoderEncoder.cpp", + "fxbarcode/qrcode/BC_QRCoderEncoder.h", + "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp", + "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h", + "fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp", + "fxbarcode/qrcode/BC_QRCoderMaskUtil.h", + "fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp", + "fxbarcode/qrcode/BC_QRCoderMatrixUtil.h", + "fxbarcode/qrcode/BC_QRCoderMode.cpp", + "fxbarcode/qrcode/BC_QRCoderMode.h", + "fxbarcode/qrcode/BC_QRCoderVersion.cpp", + "fxbarcode/qrcode/BC_QRCoderVersion.h", + "fxbarcode/utils.h", + ] + deps = [ + ":fxcrt", + ] + configs += [ ":pdfium_core_config" ] + } + + # TODO(crbug.com/pdfium/964): Support jumbo builds. static_library("xfa") { sources = [ - "xfa/fde/cfde_path.cpp", - "xfa/fde/cfde_path.h", - "xfa/fde/cfde_txtedtbuf.cpp", - "xfa/fde/cfde_txtedtbuf.h", - "xfa/fde/cfde_txtedtdorecord_deleterange.cpp", - "xfa/fde/cfde_txtedtdorecord_deleterange.h", - "xfa/fde/cfde_txtedtdorecord_insert.cpp", - "xfa/fde/cfde_txtedtdorecord_insert.h", - "xfa/fde/cfde_txtedtengine.cpp", - "xfa/fde/cfde_txtedtengine.h", - "xfa/fde/cfde_txtedtpage.cpp", - "xfa/fde/cfde_txtedtpage.h", - "xfa/fde/cfde_txtedtparag.cpp", - "xfa/fde/cfde_txtedtparag.h", - "xfa/fde/cfde_txtedttextset.cpp", - "xfa/fde/cfde_txtedttextset.h", - "xfa/fde/cfx_chariter.cpp", - "xfa/fde/cfx_chariter.h", - "xfa/fde/cfx_wordbreak.cpp", - "xfa/fde/cfx_wordbreak.h", - "xfa/fde/css/cfde_csscolorvalue.cpp", - "xfa/fde/css/cfde_csscolorvalue.h", - "xfa/fde/css/cfde_csscomputedstyle.cpp", - "xfa/fde/css/cfde_csscomputedstyle.h", - "xfa/fde/css/cfde_csscustomproperty.cpp", - "xfa/fde/css/cfde_csscustomproperty.h", - "xfa/fde/css/cfde_cssdeclaration.cpp", - "xfa/fde/css/cfde_cssdeclaration.h", - "xfa/fde/css/cfde_cssenumvalue.cpp", - "xfa/fde/css/cfde_cssenumvalue.h", - "xfa/fde/css/cfde_cssnumbervalue.cpp", - "xfa/fde/css/cfde_cssnumbervalue.h", - "xfa/fde/css/cfde_csspropertyholder.cpp", - "xfa/fde/css/cfde_csspropertyholder.h", - "xfa/fde/css/cfde_cssrulecollection.cpp", - "xfa/fde/css/cfde_cssrulecollection.h", - "xfa/fde/css/cfde_cssselector.cpp", - "xfa/fde/css/cfde_cssselector.h", - "xfa/fde/css/cfde_cssstringvalue.cpp", - "xfa/fde/css/cfde_cssstringvalue.h", - "xfa/fde/css/cfde_cssstylerule.cpp", - "xfa/fde/css/cfde_cssstylerule.h", - "xfa/fde/css/cfde_cssstyleselector.cpp", - "xfa/fde/css/cfde_cssstyleselector.h", - "xfa/fde/css/cfde_cssstylesheet.cpp", - "xfa/fde/css/cfde_cssstylesheet.h", - "xfa/fde/css/cfde_csssyntaxparser.cpp", - "xfa/fde/css/cfde_csssyntaxparser.h", - "xfa/fde/css/cfde_csstextbuf.cpp", - "xfa/fde/css/cfde_csstextbuf.h", - "xfa/fde/css/cfde_cssvalue.cpp", - "xfa/fde/css/cfde_cssvalue.h", - "xfa/fde/css/cfde_cssvaluelist.cpp", - "xfa/fde/css/cfde_cssvaluelist.h", - "xfa/fde/css/cfde_cssvaluelistparser.cpp", - "xfa/fde/css/cfde_cssvaluelistparser.h", - "xfa/fde/css/fde_css.h", - "xfa/fde/css/fde_cssdatatable.cpp", - "xfa/fde/css/fde_cssdatatable.h", - "xfa/fde/fde_gedevice.cpp", - "xfa/fde/fde_iterator.cpp", - "xfa/fde/fde_iterator.h", - "xfa/fde/fde_object.h", - "xfa/fde/fde_render.cpp", - "xfa/fde/fde_render.h", - "xfa/fde/ifde_txtedtdorecord.h", - "xfa/fde/ifde_txtedtengine.h", - "xfa/fde/ifde_txtedtpage.h", - "xfa/fde/ifx_chariter.h", - "xfa/fde/tto/fde_textout.cpp", - "xfa/fde/tto/fde_textout.h", - "xfa/fde/xml/cfx_saxreader.cpp", - "xfa/fde/xml/cfx_saxreader.h", - "xfa/fde/xml/fde_xml.h", - "xfa/fde/xml/fde_xml_imp.cpp", - "xfa/fde/xml/fde_xml_imp.h", - "xfa/fgas/crt/fgas_codepage.cpp", - "xfa/fgas/crt/fgas_codepage.h", - "xfa/fgas/crt/fgas_language.h", - "xfa/fgas/crt/fgas_stream.cpp", - "xfa/fgas/crt/fgas_stream.h", - "xfa/fgas/crt/fgas_utils.cpp", - "xfa/fgas/crt/fgas_utils.h", + "xfa/fde/cfde_texteditengine.cpp", + "xfa/fde/cfde_texteditengine.h", + "xfa/fde/cfde_textout.cpp", + "xfa/fde/cfde_textout.h", + "xfa/fde/cfde_wordbreak_data.cpp", + "xfa/fde/cfde_wordbreak_data.h", + "xfa/fgas/crt/cfgas_formatstring.cpp", + "xfa/fgas/crt/cfgas_formatstring.h", + "xfa/fgas/font/cfgas_defaultfontmanager.cpp", + "xfa/fgas/font/cfgas_defaultfontmanager.h", "xfa/fgas/font/cfgas_fontmgr.cpp", "xfa/fgas/font/cfgas_fontmgr.h", "xfa/fgas/font/cfgas_gefont.cpp", "xfa/fgas/font/cfgas_gefont.h", + "xfa/fgas/font/cfgas_pdffontmgr.cpp", + "xfa/fgas/font/cfgas_pdffontmgr.h", "xfa/fgas/font/fgas_fontutils.cpp", "xfa/fgas/font/fgas_fontutils.h", - "xfa/fgas/layout/fgas_linebreak.cpp", - "xfa/fgas/layout/fgas_linebreak.h", - "xfa/fgas/layout/fgas_rtfbreak.cpp", - "xfa/fgas/layout/fgas_rtfbreak.h", - "xfa/fgas/layout/fgas_textbreak.cpp", - "xfa/fgas/layout/fgas_textbreak.h", - "xfa/fgas/localization/fgas_datetime.cpp", - "xfa/fgas/localization/fgas_datetime.h", - "xfa/fgas/localization/fgas_locale.cpp", - "xfa/fgas/localization/fgas_locale.h", - "xfa/fgas/localization/fgas_localeimp.h", + "xfa/fgas/layout/cfx_break.cpp", + "xfa/fgas/layout/cfx_break.h", + "xfa/fgas/layout/cfx_breakline.cpp", + "xfa/fgas/layout/cfx_breakline.h", + "xfa/fgas/layout/cfx_breakpiece.cpp", + "xfa/fgas/layout/cfx_breakpiece.h", + "xfa/fgas/layout/cfx_linebreak.cpp", + "xfa/fgas/layout/cfx_linebreak.h", + "xfa/fgas/layout/cfx_rtfbreak.cpp", + "xfa/fgas/layout/cfx_rtfbreak.h", + "xfa/fgas/layout/cfx_txtbreak.cpp", + "xfa/fgas/layout/cfx_txtbreak.h", "xfa/fwl/cfwl_app.cpp", "xfa/fwl/cfwl_app.h", "xfa/fwl/cfwl_barcode.cpp", @@ -1313,8 +1909,6 @@ if (pdf_enable_xfa) { "xfa/fwl/cfwl_pushbutton.h", "xfa/fwl/cfwl_scrollbar.cpp", "xfa/fwl/cfwl_scrollbar.h", - "xfa/fwl/cfwl_spinbutton.cpp", - "xfa/fwl/cfwl_spinbutton.h", "xfa/fwl/cfwl_themebackground.h", "xfa/fwl/cfwl_themepart.cpp", "xfa/fwl/cfwl_themepart.h", @@ -1336,7 +1930,6 @@ if (pdf_enable_xfa) { "xfa/fwl/ifwl_adaptertimermgr.h", "xfa/fwl/ifwl_themeprovider.h", "xfa/fwl/ifwl_widgetdelegate.h", - "xfa/fwl/ifwl_widgetmgrdelegate.h", "xfa/fwl/theme/cfwl_barcodetp.cpp", "xfa/fwl/theme/cfwl_barcodetp.h", "xfa/fwl/theme/cfwl_carettp.cpp", @@ -1362,221 +1955,108 @@ if (pdf_enable_xfa) { "xfa/fwl/theme/cfwl_utils.h", "xfa/fwl/theme/cfwl_widgettp.cpp", "xfa/fwl/theme/cfwl_widgettp.h", - "xfa/fxbarcode/BC_Dimension.cpp", - "xfa/fxbarcode/BC_Dimension.h", - "xfa/fxbarcode/BC_Library.cpp", - "xfa/fxbarcode/BC_Library.h", - "xfa/fxbarcode/BC_TwoDimWriter.cpp", - "xfa/fxbarcode/BC_TwoDimWriter.h", - "xfa/fxbarcode/BC_UtilCodingConvert.cpp", - "xfa/fxbarcode/BC_UtilCodingConvert.h", - "xfa/fxbarcode/BC_Utils.cpp", - "xfa/fxbarcode/BC_Writer.cpp", - "xfa/fxbarcode/BC_Writer.h", - "xfa/fxbarcode/cbc_codabar.cpp", - "xfa/fxbarcode/cbc_codabar.h", - "xfa/fxbarcode/cbc_code128.cpp", - "xfa/fxbarcode/cbc_code128.h", - "xfa/fxbarcode/cbc_code39.cpp", - "xfa/fxbarcode/cbc_code39.h", - "xfa/fxbarcode/cbc_codebase.cpp", - "xfa/fxbarcode/cbc_codebase.h", - "xfa/fxbarcode/cbc_datamatrix.cpp", - "xfa/fxbarcode/cbc_datamatrix.h", - "xfa/fxbarcode/cbc_ean13.cpp", - "xfa/fxbarcode/cbc_ean13.h", - "xfa/fxbarcode/cbc_ean8.cpp", - "xfa/fxbarcode/cbc_ean8.h", - "xfa/fxbarcode/cbc_onecode.cpp", - "xfa/fxbarcode/cbc_onecode.h", - "xfa/fxbarcode/cbc_pdf417i.cpp", - "xfa/fxbarcode/cbc_pdf417i.h", - "xfa/fxbarcode/cbc_qrcode.cpp", - "xfa/fxbarcode/cbc_qrcode.h", - "xfa/fxbarcode/cbc_upca.cpp", - "xfa/fxbarcode/cbc_upca.h", - "xfa/fxbarcode/common/BC_CommonBitArray.cpp", - "xfa/fxbarcode/common/BC_CommonBitArray.h", - "xfa/fxbarcode/common/BC_CommonBitMatrix.cpp", - "xfa/fxbarcode/common/BC_CommonBitMatrix.h", - "xfa/fxbarcode/common/BC_CommonByteArray.cpp", - "xfa/fxbarcode/common/BC_CommonByteArray.h", - "xfa/fxbarcode/common/BC_CommonByteMatrix.cpp", - "xfa/fxbarcode/common/BC_CommonByteMatrix.h", - "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp", - "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.h", - "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp", - "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h", - "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp", - "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h", - "xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp", - "xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h", - "xfa/fxbarcode/datamatrix/BC_Base256Encoder.cpp", - "xfa/fxbarcode/datamatrix/BC_Base256Encoder.h", - "xfa/fxbarcode/datamatrix/BC_C40Encoder.cpp", - "xfa/fxbarcode/datamatrix/BC_C40Encoder.h", - "xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp", - "xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h", - "xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp", - "xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.h", - "xfa/fxbarcode/datamatrix/BC_DefaultPlacement.cpp", - "xfa/fxbarcode/datamatrix/BC_DefaultPlacement.h", - "xfa/fxbarcode/datamatrix/BC_EdifactEncoder.cpp", - "xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h", - "xfa/fxbarcode/datamatrix/BC_Encoder.cpp", - "xfa/fxbarcode/datamatrix/BC_Encoder.h", - "xfa/fxbarcode/datamatrix/BC_EncoderContext.cpp", - "xfa/fxbarcode/datamatrix/BC_EncoderContext.h", - "xfa/fxbarcode/datamatrix/BC_ErrorCorrection.cpp", - "xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h", - "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp", - "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h", - "xfa/fxbarcode/datamatrix/BC_SymbolInfo.cpp", - "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h", - "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.cpp", - "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h", - "xfa/fxbarcode/datamatrix/BC_TextEncoder.cpp", - "xfa/fxbarcode/datamatrix/BC_TextEncoder.h", - "xfa/fxbarcode/datamatrix/BC_X12Encoder.cpp", - "xfa/fxbarcode/datamatrix/BC_X12Encoder.h", - "xfa/fxbarcode/oned/BC_OneDimWriter.cpp", - "xfa/fxbarcode/oned/BC_OneDimWriter.h", - "xfa/fxbarcode/oned/BC_OnedCodaBarWriter.cpp", - "xfa/fxbarcode/oned/BC_OnedCodaBarWriter.h", - "xfa/fxbarcode/oned/BC_OnedCode128Writer.cpp", - "xfa/fxbarcode/oned/BC_OnedCode128Writer.h", - "xfa/fxbarcode/oned/BC_OnedCode39Writer.cpp", - "xfa/fxbarcode/oned/BC_OnedCode39Writer.h", - "xfa/fxbarcode/oned/BC_OnedEAN13Writer.cpp", - "xfa/fxbarcode/oned/BC_OnedEAN13Writer.h", - "xfa/fxbarcode/oned/BC_OnedEAN8Writer.cpp", - "xfa/fxbarcode/oned/BC_OnedEAN8Writer.h", - "xfa/fxbarcode/oned/BC_OnedUPCAWriter.cpp", - "xfa/fxbarcode/oned/BC_OnedUPCAWriter.h", - "xfa/fxbarcode/pdf417/BC_PDF417.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417.h", - "xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h", - "xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h", - "xfa/fxbarcode/pdf417/BC_PDF417Compaction.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h", - "xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h", - "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h", - "xfa/fxbarcode/pdf417/BC_PDF417Writer.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417Writer.h", - "xfa/fxbarcode/qrcode/BC_QRCodeWriter.cpp", - "xfa/fxbarcode/qrcode/BC_QRCodeWriter.h", - "xfa/fxbarcode/qrcode/BC_QRCoder.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoder.h", - "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h", - "xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.h", - "xfa/fxbarcode/qrcode/BC_QRCoderECB.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderECB.h", - "xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h", - "xfa/fxbarcode/qrcode/BC_QRCoderEncoder.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderEncoder.h", - "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h", - "xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h", - "xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h", - "xfa/fxbarcode/qrcode/BC_QRCoderMode.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderMode.h", - "xfa/fxbarcode/qrcode/BC_QRCoderVersion.cpp", - "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h", - "xfa/fxbarcode/utils.h", - "xfa/fxfa/app/cxfa_csstagprovider.cpp", - "xfa/fxfa/app/cxfa_csstagprovider.h", - "xfa/fxfa/app/cxfa_eventparam.cpp", - "xfa/fxfa/app/cxfa_linkuserdata.cpp", - "xfa/fxfa/app/cxfa_linkuserdata.h", - "xfa/fxfa/app/cxfa_loadercontext.cpp", - "xfa/fxfa/app/cxfa_loadercontext.h", - "xfa/fxfa/app/cxfa_pieceline.cpp", - "xfa/fxfa/app/cxfa_pieceline.h", - "xfa/fxfa/app/cxfa_textlayout.cpp", - "xfa/fxfa/app/cxfa_textlayout.h", - "xfa/fxfa/app/cxfa_textparsecontext.cpp", - "xfa/fxfa/app/cxfa_textparsecontext.h", - "xfa/fxfa/app/cxfa_textparser.cpp", - "xfa/fxfa/app/cxfa_textparser.h", - "xfa/fxfa/app/cxfa_texttabstopscontext.cpp", - "xfa/fxfa/app/cxfa_texttabstopscontext.h", - "xfa/fxfa/app/cxfa_textuserdata.cpp", - "xfa/fxfa/app/cxfa_textuserdata.h", - "xfa/fxfa/app/xfa_checksum.cpp", - "xfa/fxfa/app/xfa_ffapp.cpp", - "xfa/fxfa/app/xfa_ffbarcode.cpp", - "xfa/fxfa/app/xfa_ffbarcode.h", - "xfa/fxfa/app/xfa_ffcheckbutton.cpp", - "xfa/fxfa/app/xfa_ffcheckbutton.h", - "xfa/fxfa/app/xfa_ffchoicelist.cpp", - "xfa/fxfa/app/xfa_ffchoicelist.h", - "xfa/fxfa/app/xfa_ffdoc.cpp", - "xfa/fxfa/app/xfa_ffdochandler.cpp", - "xfa/fxfa/app/xfa_ffdocview.cpp", - "xfa/fxfa/app/xfa_ffdraw.cpp", - "xfa/fxfa/app/xfa_ffdraw.h", - "xfa/fxfa/app/xfa_ffexclgroup.cpp", - "xfa/fxfa/app/xfa_ffexclgroup.h", - "xfa/fxfa/app/xfa_fffield.cpp", - "xfa/fxfa/app/xfa_fffield.h", - "xfa/fxfa/app/xfa_ffimage.cpp", - "xfa/fxfa/app/xfa_ffimage.h", - "xfa/fxfa/app/xfa_ffimageedit.cpp", - "xfa/fxfa/app/xfa_ffimageedit.h", - "xfa/fxfa/app/xfa_ffnotify.cpp", - "xfa/fxfa/app/xfa_ffnotify.h", - "xfa/fxfa/app/xfa_ffpageview.cpp", - "xfa/fxfa/app/xfa_ffpath.cpp", - "xfa/fxfa/app/xfa_ffpath.h", - "xfa/fxfa/app/xfa_ffpushbutton.cpp", - "xfa/fxfa/app/xfa_ffpushbutton.h", - "xfa/fxfa/app/xfa_ffsignature.cpp", - "xfa/fxfa/app/xfa_ffsignature.h", - "xfa/fxfa/app/xfa_ffsubform.cpp", - "xfa/fxfa/app/xfa_ffsubform.h", - "xfa/fxfa/app/xfa_fftext.cpp", - "xfa/fxfa/app/xfa_fftext.h", - "xfa/fxfa/app/xfa_fftextedit.cpp", - "xfa/fxfa/app/xfa_fftextedit.h", - "xfa/fxfa/app/xfa_ffwidget.cpp", - "xfa/fxfa/app/xfa_ffwidgetacc.cpp", - "xfa/fxfa/app/xfa_ffwidgetacc.h", - "xfa/fxfa/app/xfa_ffwidgethandler.cpp", - "xfa/fxfa/app/xfa_fontmgr.cpp", - "xfa/fxfa/app/xfa_fwladapter.cpp", - "xfa/fxfa/app/xfa_fwladapter.h", - "xfa/fxfa/app/xfa_fwltheme.cpp", - "xfa/fxfa/app/xfa_fwltheme.h", - "xfa/fxfa/app/xfa_rendercontext.cpp", - "xfa/fxfa/app/xfa_textpiece.cpp", - "xfa/fxfa/app/xfa_textpiece.h", + "xfa/fxfa/cxfa_eventparam.cpp", "xfa/fxfa/cxfa_eventparam.h", - "xfa/fxfa/fm2js/xfa_error.cpp", - "xfa/fxfa/fm2js/xfa_error.h", - "xfa/fxfa/fm2js/xfa_expression.cpp", - "xfa/fxfa/fm2js/xfa_expression.h", - "xfa/fxfa/fm2js/xfa_fm2jscontext.cpp", - "xfa/fxfa/fm2js/xfa_fm2jscontext.h", - "xfa/fxfa/fm2js/xfa_fmparse.cpp", - "xfa/fxfa/fm2js/xfa_fmparse.h", - "xfa/fxfa/fm2js/xfa_lexer.cpp", - "xfa/fxfa/fm2js/xfa_lexer.h", - "xfa/fxfa/fm2js/xfa_program.cpp", - "xfa/fxfa/fm2js/xfa_program.h", - "xfa/fxfa/fm2js/xfa_simpleexpression.cpp", - "xfa/fxfa/fm2js/xfa_simpleexpression.h", + "xfa/fxfa/cxfa_ffapp.cpp", + "xfa/fxfa/cxfa_ffapp.h", + "xfa/fxfa/cxfa_ffarc.cpp", + "xfa/fxfa/cxfa_ffarc.h", + "xfa/fxfa/cxfa_ffbarcode.cpp", + "xfa/fxfa/cxfa_ffbarcode.h", + "xfa/fxfa/cxfa_ffcheckbutton.cpp", + "xfa/fxfa/cxfa_ffcheckbutton.h", + "xfa/fxfa/cxfa_ffcombobox.cpp", + "xfa/fxfa/cxfa_ffcombobox.h", + "xfa/fxfa/cxfa_ffdatetimeedit.cpp", + "xfa/fxfa/cxfa_ffdatetimeedit.h", + "xfa/fxfa/cxfa_ffdoc.cpp", + "xfa/fxfa/cxfa_ffdoc.h", + "xfa/fxfa/cxfa_ffdocview.cpp", + "xfa/fxfa/cxfa_ffdocview.h", + "xfa/fxfa/cxfa_ffdraw.cpp", + "xfa/fxfa/cxfa_ffdraw.h", + "xfa/fxfa/cxfa_ffexclgroup.cpp", + "xfa/fxfa/cxfa_ffexclgroup.h", + "xfa/fxfa/cxfa_fffield.cpp", + "xfa/fxfa/cxfa_fffield.h", + "xfa/fxfa/cxfa_ffimage.cpp", + "xfa/fxfa/cxfa_ffimage.h", + "xfa/fxfa/cxfa_ffimageedit.cpp", + "xfa/fxfa/cxfa_ffimageedit.h", + "xfa/fxfa/cxfa_ffline.cpp", + "xfa/fxfa/cxfa_ffline.h", + "xfa/fxfa/cxfa_fflistbox.cpp", + "xfa/fxfa/cxfa_fflistbox.h", + "xfa/fxfa/cxfa_ffnotify.cpp", + "xfa/fxfa/cxfa_ffnotify.h", + "xfa/fxfa/cxfa_ffnumericedit.cpp", + "xfa/fxfa/cxfa_ffnumericedit.h", + "xfa/fxfa/cxfa_ffpageview.cpp", + "xfa/fxfa/cxfa_ffpageview.h", + "xfa/fxfa/cxfa_ffpasswordedit.cpp", + "xfa/fxfa/cxfa_ffpasswordedit.h", + "xfa/fxfa/cxfa_ffpushbutton.cpp", + "xfa/fxfa/cxfa_ffpushbutton.h", + "xfa/fxfa/cxfa_ffrectangle.cpp", + "xfa/fxfa/cxfa_ffrectangle.h", + "xfa/fxfa/cxfa_ffsignature.cpp", + "xfa/fxfa/cxfa_ffsignature.h", + "xfa/fxfa/cxfa_ffsubform.cpp", + "xfa/fxfa/cxfa_ffsubform.h", + "xfa/fxfa/cxfa_fftext.cpp", + "xfa/fxfa/cxfa_fftext.h", + "xfa/fxfa/cxfa_fftextedit.cpp", + "xfa/fxfa/cxfa_fftextedit.h", + "xfa/fxfa/cxfa_ffwidget.cpp", + "xfa/fxfa/cxfa_ffwidget.h", + "xfa/fxfa/cxfa_ffwidgethandler.cpp", + "xfa/fxfa/cxfa_ffwidgethandler.h", + "xfa/fxfa/cxfa_fontmgr.cpp", + "xfa/fxfa/cxfa_fontmgr.h", + "xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp", + "xfa/fxfa/cxfa_fwladapterwidgetmgr.h", + "xfa/fxfa/cxfa_fwltheme.cpp", + "xfa/fxfa/cxfa_fwltheme.h", + "xfa/fxfa/cxfa_imagerenderer.cpp", + "xfa/fxfa/cxfa_imagerenderer.h", + "xfa/fxfa/cxfa_linkuserdata.cpp", + "xfa/fxfa/cxfa_linkuserdata.h", + "xfa/fxfa/cxfa_loadercontext.cpp", + "xfa/fxfa/cxfa_loadercontext.h", + "xfa/fxfa/cxfa_pieceline.cpp", + "xfa/fxfa/cxfa_pieceline.h", + "xfa/fxfa/cxfa_rendercontext.cpp", + "xfa/fxfa/cxfa_rendercontext.h", + "xfa/fxfa/cxfa_textlayout.cpp", + "xfa/fxfa/cxfa_textlayout.h", + "xfa/fxfa/cxfa_textparsecontext.cpp", + "xfa/fxfa/cxfa_textparsecontext.h", + "xfa/fxfa/cxfa_textparser.cpp", + "xfa/fxfa/cxfa_textparser.h", + "xfa/fxfa/cxfa_textpiece.cpp", + "xfa/fxfa/cxfa_textpiece.h", + "xfa/fxfa/cxfa_textprovider.cpp", + "xfa/fxfa/cxfa_textprovider.h", + "xfa/fxfa/cxfa_texttabstopscontext.cpp", + "xfa/fxfa/cxfa_texttabstopscontext.h", + "xfa/fxfa/cxfa_textuserdata.cpp", + "xfa/fxfa/cxfa_textuserdata.h", + "xfa/fxfa/cxfa_widgetacc.cpp", + "xfa/fxfa/cxfa_widgetacc.h", + "xfa/fxfa/cxfa_widgetacciterator.cpp", + "xfa/fxfa/cxfa_widgetacciterator.h", + "xfa/fxfa/fm2js/cxfa_fmexpression.cpp", + "xfa/fxfa/fm2js/cxfa_fmexpression.h", + "xfa/fxfa/fm2js/cxfa_fmlexer.cpp", + "xfa/fxfa/fm2js/cxfa_fmlexer.h", + "xfa/fxfa/fm2js/cxfa_fmparser.cpp", + "xfa/fxfa/fm2js/cxfa_fmparser.h", + "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp", + "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h", + "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.cpp", + "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h", "xfa/fxfa/fxfa.h", "xfa/fxfa/fxfa_basic.h", - "xfa/fxfa/fxfa_widget.h", "xfa/fxfa/parser/cscript_datawindow.cpp", "xfa/fxfa/parser/cscript_datawindow.h", "xfa/fxfa/parser/cscript_eventpseudomodel.cpp", @@ -1589,147 +2069,698 @@ if (pdf_enable_xfa) { "xfa/fxfa/parser/cscript_logpseudomodel.h", "xfa/fxfa/parser/cscript_signaturepseudomodel.cpp", "xfa/fxfa/parser/cscript_signaturepseudomodel.h", + "xfa/fxfa/parser/cxfa_accessiblecontent.cpp", + "xfa/fxfa/parser/cxfa_accessiblecontent.h", + "xfa/fxfa/parser/cxfa_acrobat.cpp", + "xfa/fxfa/parser/cxfa_acrobat.h", + "xfa/fxfa/parser/cxfa_acrobat7.cpp", + "xfa/fxfa/parser/cxfa_acrobat7.h", + "xfa/fxfa/parser/cxfa_adbe_jsconsole.cpp", + "xfa/fxfa/parser/cxfa_adbe_jsconsole.h", + "xfa/fxfa/parser/cxfa_adbe_jsdebugger.cpp", + "xfa/fxfa/parser/cxfa_adbe_jsdebugger.h", + "xfa/fxfa/parser/cxfa_addsilentprint.cpp", + "xfa/fxfa/parser/cxfa_addsilentprint.h", + "xfa/fxfa/parser/cxfa_addviewerpreferences.cpp", + "xfa/fxfa/parser/cxfa_addviewerpreferences.h", + "xfa/fxfa/parser/cxfa_adjustdata.cpp", + "xfa/fxfa/parser/cxfa_adjustdata.h", + "xfa/fxfa/parser/cxfa_adobeextensionlevel.cpp", + "xfa/fxfa/parser/cxfa_adobeextensionlevel.h", + "xfa/fxfa/parser/cxfa_agent.cpp", + "xfa/fxfa/parser/cxfa_agent.h", + "xfa/fxfa/parser/cxfa_alwaysembed.cpp", + "xfa/fxfa/parser/cxfa_alwaysembed.h", + "xfa/fxfa/parser/cxfa_amd.cpp", + "xfa/fxfa/parser/cxfa_amd.h", + "xfa/fxfa/parser/cxfa_appearancefilter.cpp", + "xfa/fxfa/parser/cxfa_appearancefilter.h", + "xfa/fxfa/parser/cxfa_arc.cpp", "xfa/fxfa/parser/cxfa_arc.h", + "xfa/fxfa/parser/cxfa_area.cpp", + "xfa/fxfa/parser/cxfa_area.h", "xfa/fxfa/parser/cxfa_arraynodelist.cpp", + "xfa/fxfa/parser/cxfa_arraynodelist.h", "xfa/fxfa/parser/cxfa_assist.cpp", "xfa/fxfa/parser/cxfa_assist.h", "xfa/fxfa/parser/cxfa_attachnodelist.cpp", + "xfa/fxfa/parser/cxfa_attachnodelist.h", + "xfa/fxfa/parser/cxfa_attributes.cpp", + "xfa/fxfa/parser/cxfa_attributes.h", + "xfa/fxfa/parser/cxfa_autosave.cpp", + "xfa/fxfa/parser/cxfa_autosave.h", + "xfa/fxfa/parser/cxfa_barcode.cpp", + "xfa/fxfa/parser/cxfa_barcode.h", + "xfa/fxfa/parser/cxfa_base.cpp", + "xfa/fxfa/parser/cxfa_base.h", + "xfa/fxfa/parser/cxfa_batchoutput.cpp", + "xfa/fxfa/parser/cxfa_batchoutput.h", + "xfa/fxfa/parser/cxfa_behavioroverride.cpp", + "xfa/fxfa/parser/cxfa_behavioroverride.h", "xfa/fxfa/parser/cxfa_bind.cpp", "xfa/fxfa/parser/cxfa_bind.h", "xfa/fxfa/parser/cxfa_binditems.cpp", "xfa/fxfa/parser/cxfa_binditems.h", + "xfa/fxfa/parser/cxfa_bookend.cpp", + "xfa/fxfa/parser/cxfa_bookend.h", + "xfa/fxfa/parser/cxfa_boolean.cpp", + "xfa/fxfa/parser/cxfa_boolean.h", + "xfa/fxfa/parser/cxfa_border.cpp", "xfa/fxfa/parser/cxfa_border.h", "xfa/fxfa/parser/cxfa_box.cpp", "xfa/fxfa/parser/cxfa_box.h", + "xfa/fxfa/parser/cxfa_break.cpp", + "xfa/fxfa/parser/cxfa_break.h", + "xfa/fxfa/parser/cxfa_breakafter.cpp", + "xfa/fxfa/parser/cxfa_breakafter.h", + "xfa/fxfa/parser/cxfa_breakbefore.cpp", + "xfa/fxfa/parser/cxfa_breakbefore.h", + "xfa/fxfa/parser/cxfa_button.cpp", + "xfa/fxfa/parser/cxfa_button.h", + "xfa/fxfa/parser/cxfa_cache.cpp", + "xfa/fxfa/parser/cxfa_cache.h", "xfa/fxfa/parser/cxfa_calculate.cpp", "xfa/fxfa/parser/cxfa_calculate.h", + "xfa/fxfa/parser/cxfa_calendarsymbols.cpp", + "xfa/fxfa/parser/cxfa_calendarsymbols.h", "xfa/fxfa/parser/cxfa_caption.cpp", "xfa/fxfa/parser/cxfa_caption.h", + "xfa/fxfa/parser/cxfa_certificate.cpp", + "xfa/fxfa/parser/cxfa_certificate.h", + "xfa/fxfa/parser/cxfa_certificates.cpp", + "xfa/fxfa/parser/cxfa_certificates.h", + "xfa/fxfa/parser/cxfa_change.cpp", + "xfa/fxfa/parser/cxfa_change.h", + "xfa/fxfa/parser/cxfa_checkbutton.cpp", + "xfa/fxfa/parser/cxfa_checkbutton.h", + "xfa/fxfa/parser/cxfa_choicelist.cpp", + "xfa/fxfa/parser/cxfa_choicelist.h", + "xfa/fxfa/parser/cxfa_color.cpp", + "xfa/fxfa/parser/cxfa_color.h", + "xfa/fxfa/parser/cxfa_comb.cpp", + "xfa/fxfa/parser/cxfa_comb.h", + "xfa/fxfa/parser/cxfa_command.cpp", + "xfa/fxfa/parser/cxfa_command.h", + "xfa/fxfa/parser/cxfa_common.cpp", + "xfa/fxfa/parser/cxfa_common.h", + "xfa/fxfa/parser/cxfa_compress.cpp", + "xfa/fxfa/parser/cxfa_compress.h", + "xfa/fxfa/parser/cxfa_compression.cpp", + "xfa/fxfa/parser/cxfa_compression.h", + "xfa/fxfa/parser/cxfa_compresslogicalstructure.cpp", + "xfa/fxfa/parser/cxfa_compresslogicalstructure.h", + "xfa/fxfa/parser/cxfa_compressobjectstream.cpp", + "xfa/fxfa/parser/cxfa_compressobjectstream.h", + "xfa/fxfa/parser/cxfa_config.cpp", + "xfa/fxfa/parser/cxfa_config.h", + "xfa/fxfa/parser/cxfa_conformance.cpp", + "xfa/fxfa/parser/cxfa_conformance.h", + "xfa/fxfa/parser/cxfa_connect.cpp", + "xfa/fxfa/parser/cxfa_connect.h", + "xfa/fxfa/parser/cxfa_connectionset.cpp", + "xfa/fxfa/parser/cxfa_connectionset.h", + "xfa/fxfa/parser/cxfa_connectstring.cpp", + "xfa/fxfa/parser/cxfa_connectstring.h", "xfa/fxfa/parser/cxfa_containerlayoutitem.cpp", "xfa/fxfa/parser/cxfa_containerlayoutitem.h", + "xfa/fxfa/parser/cxfa_contentarea.cpp", + "xfa/fxfa/parser/cxfa_contentarea.h", + "xfa/fxfa/parser/cxfa_contentcopy.cpp", + "xfa/fxfa/parser/cxfa_contentcopy.h", "xfa/fxfa/parser/cxfa_contentlayoutitem.cpp", "xfa/fxfa/parser/cxfa_contentlayoutitem.h", + "xfa/fxfa/parser/cxfa_copies.cpp", + "xfa/fxfa/parser/cxfa_copies.h", + "xfa/fxfa/parser/cxfa_corner.cpp", "xfa/fxfa/parser/cxfa_corner.h", + "xfa/fxfa/parser/cxfa_creator.cpp", + "xfa/fxfa/parser/cxfa_creator.h", + "xfa/fxfa/parser/cxfa_currencysymbol.cpp", + "xfa/fxfa/parser/cxfa_currencysymbol.h", + "xfa/fxfa/parser/cxfa_currencysymbols.cpp", + "xfa/fxfa/parser/cxfa_currencysymbols.h", + "xfa/fxfa/parser/cxfa_currentpage.cpp", + "xfa/fxfa/parser/cxfa_currentpage.h", "xfa/fxfa/parser/cxfa_data.cpp", "xfa/fxfa/parser/cxfa_data.h", "xfa/fxfa/parser/cxfa_dataexporter.cpp", "xfa/fxfa/parser/cxfa_dataexporter.h", + "xfa/fxfa/parser/cxfa_datagroup.cpp", + "xfa/fxfa/parser/cxfa_datagroup.h", "xfa/fxfa/parser/cxfa_dataimporter.cpp", "xfa/fxfa/parser/cxfa_dataimporter.h", + "xfa/fxfa/parser/cxfa_datamodel.cpp", + "xfa/fxfa/parser/cxfa_datamodel.h", + "xfa/fxfa/parser/cxfa_datavalue.cpp", + "xfa/fxfa/parser/cxfa_datavalue.h", + "xfa/fxfa/parser/cxfa_date.cpp", + "xfa/fxfa/parser/cxfa_date.h", + "xfa/fxfa/parser/cxfa_datepattern.cpp", + "xfa/fxfa/parser/cxfa_datepattern.h", + "xfa/fxfa/parser/cxfa_datepatterns.cpp", + "xfa/fxfa/parser/cxfa_datepatterns.h", + "xfa/fxfa/parser/cxfa_datetime.cpp", + "xfa/fxfa/parser/cxfa_datetime.h", + "xfa/fxfa/parser/cxfa_datetimeedit.cpp", + "xfa/fxfa/parser/cxfa_datetimeedit.h", + "xfa/fxfa/parser/cxfa_datetimesymbols.cpp", + "xfa/fxfa/parser/cxfa_datetimesymbols.h", + "xfa/fxfa/parser/cxfa_day.cpp", + "xfa/fxfa/parser/cxfa_day.h", + "xfa/fxfa/parser/cxfa_daynames.cpp", + "xfa/fxfa/parser/cxfa_daynames.h", + "xfa/fxfa/parser/cxfa_debug.cpp", + "xfa/fxfa/parser/cxfa_debug.h", + "xfa/fxfa/parser/cxfa_decimal.cpp", + "xfa/fxfa/parser/cxfa_decimal.h", + "xfa/fxfa/parser/cxfa_defaulttypeface.cpp", + "xfa/fxfa/parser/cxfa_defaulttypeface.h", + "xfa/fxfa/parser/cxfa_defaultui.cpp", + "xfa/fxfa/parser/cxfa_defaultui.h", + "xfa/fxfa/parser/cxfa_delete.cpp", + "xfa/fxfa/parser/cxfa_delete.h", + "xfa/fxfa/parser/cxfa_delta.cpp", + "xfa/fxfa/parser/cxfa_delta.h", + "xfa/fxfa/parser/cxfa_deltas.cpp", + "xfa/fxfa/parser/cxfa_deltas.h", + "xfa/fxfa/parser/cxfa_desc.cpp", + "xfa/fxfa/parser/cxfa_desc.h", + "xfa/fxfa/parser/cxfa_destination.cpp", + "xfa/fxfa/parser/cxfa_destination.h", + "xfa/fxfa/parser/cxfa_digestmethod.cpp", + "xfa/fxfa/parser/cxfa_digestmethod.h", + "xfa/fxfa/parser/cxfa_digestmethods.cpp", + "xfa/fxfa/parser/cxfa_digestmethods.h", "xfa/fxfa/parser/cxfa_document.cpp", "xfa/fxfa/parser/cxfa_document.h", "xfa/fxfa/parser/cxfa_document_parser.cpp", "xfa/fxfa/parser/cxfa_document_parser.h", + "xfa/fxfa/parser/cxfa_documentassembly.cpp", + "xfa/fxfa/parser/cxfa_documentassembly.h", + "xfa/fxfa/parser/cxfa_draw.cpp", + "xfa/fxfa/parser/cxfa_draw.h", + "xfa/fxfa/parser/cxfa_driver.cpp", + "xfa/fxfa/parser/cxfa_driver.h", + "xfa/fxfa/parser/cxfa_dsigdata.cpp", + "xfa/fxfa/parser/cxfa_dsigdata.h", + "xfa/fxfa/parser/cxfa_duplexoption.cpp", + "xfa/fxfa/parser/cxfa_duplexoption.h", + "xfa/fxfa/parser/cxfa_dynamicrender.cpp", + "xfa/fxfa/parser/cxfa_dynamicrender.h", + "xfa/fxfa/parser/cxfa_edge.cpp", "xfa/fxfa/parser/cxfa_edge.h", + "xfa/fxfa/parser/cxfa_effectiveinputpolicy.cpp", + "xfa/fxfa/parser/cxfa_effectiveinputpolicy.h", + "xfa/fxfa/parser/cxfa_effectiveoutputpolicy.cpp", + "xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h", + "xfa/fxfa/parser/cxfa_embed.cpp", + "xfa/fxfa/parser/cxfa_embed.h", + "xfa/fxfa/parser/cxfa_encoding.cpp", + "xfa/fxfa/parser/cxfa_encoding.h", + "xfa/fxfa/parser/cxfa_encodings.cpp", + "xfa/fxfa/parser/cxfa_encodings.h", + "xfa/fxfa/parser/cxfa_encrypt.cpp", + "xfa/fxfa/parser/cxfa_encrypt.h", + "xfa/fxfa/parser/cxfa_encryption.cpp", + "xfa/fxfa/parser/cxfa_encryption.h", + "xfa/fxfa/parser/cxfa_encryptionlevel.cpp", + "xfa/fxfa/parser/cxfa_encryptionlevel.h", + "xfa/fxfa/parser/cxfa_encryptionmethod.cpp", + "xfa/fxfa/parser/cxfa_encryptionmethod.h", + "xfa/fxfa/parser/cxfa_encryptionmethods.cpp", + "xfa/fxfa/parser/cxfa_encryptionmethods.h", + "xfa/fxfa/parser/cxfa_enforce.cpp", + "xfa/fxfa/parser/cxfa_enforce.h", + "xfa/fxfa/parser/cxfa_equate.cpp", + "xfa/fxfa/parser/cxfa_equate.h", + "xfa/fxfa/parser/cxfa_equaterange.cpp", + "xfa/fxfa/parser/cxfa_equaterange.h", + "xfa/fxfa/parser/cxfa_era.cpp", + "xfa/fxfa/parser/cxfa_era.h", + "xfa/fxfa/parser/cxfa_eranames.cpp", + "xfa/fxfa/parser/cxfa_eranames.h", "xfa/fxfa/parser/cxfa_event.cpp", "xfa/fxfa/parser/cxfa_event.h", + "xfa/fxfa/parser/cxfa_exclgroup.cpp", + "xfa/fxfa/parser/cxfa_exclgroup.h", + "xfa/fxfa/parser/cxfa_exclude.cpp", + "xfa/fxfa/parser/cxfa_exclude.h", + "xfa/fxfa/parser/cxfa_excludens.cpp", + "xfa/fxfa/parser/cxfa_excludens.h", "xfa/fxfa/parser/cxfa_exdata.cpp", "xfa/fxfa/parser/cxfa_exdata.h", + "xfa/fxfa/parser/cxfa_execute.cpp", + "xfa/fxfa/parser/cxfa_execute.h", + "xfa/fxfa/parser/cxfa_exobject.cpp", + "xfa/fxfa/parser/cxfa_exobject.h", + "xfa/fxfa/parser/cxfa_extras.cpp", + "xfa/fxfa/parser/cxfa_extras.h", + "xfa/fxfa/parser/cxfa_field.cpp", + "xfa/fxfa/parser/cxfa_field.h", "xfa/fxfa/parser/cxfa_fill.cpp", "xfa/fxfa/parser/cxfa_fill.h", + "xfa/fxfa/parser/cxfa_filter.cpp", + "xfa/fxfa/parser/cxfa_filter.h", + "xfa/fxfa/parser/cxfa_fliplabel.cpp", + "xfa/fxfa/parser/cxfa_fliplabel.h", + "xfa/fxfa/parser/cxfa_float.cpp", + "xfa/fxfa/parser/cxfa_float.h", "xfa/fxfa/parser/cxfa_font.cpp", "xfa/fxfa/parser/cxfa_font.h", + "xfa/fxfa/parser/cxfa_fontinfo.cpp", + "xfa/fxfa/parser/cxfa_fontinfo.h", + "xfa/fxfa/parser/cxfa_form.cpp", + "xfa/fxfa/parser/cxfa_form.h", + "xfa/fxfa/parser/cxfa_format.cpp", + "xfa/fxfa/parser/cxfa_format.h", + "xfa/fxfa/parser/cxfa_formfieldfilling.cpp", + "xfa/fxfa/parser/cxfa_formfieldfilling.h", + "xfa/fxfa/parser/cxfa_groupparent.cpp", + "xfa/fxfa/parser/cxfa_groupparent.h", + "xfa/fxfa/parser/cxfa_handler.cpp", + "xfa/fxfa/parser/cxfa_handler.h", + "xfa/fxfa/parser/cxfa_hyphenation.cpp", + "xfa/fxfa/parser/cxfa_hyphenation.h", + "xfa/fxfa/parser/cxfa_ifempty.cpp", + "xfa/fxfa/parser/cxfa_ifempty.h", "xfa/fxfa/parser/cxfa_image.cpp", "xfa/fxfa/parser/cxfa_image.h", + "xfa/fxfa/parser/cxfa_imageedit.cpp", + "xfa/fxfa/parser/cxfa_imageedit.h", + "xfa/fxfa/parser/cxfa_includexdpcontent.cpp", + "xfa/fxfa/parser/cxfa_includexdpcontent.h", + "xfa/fxfa/parser/cxfa_incrementalload.cpp", + "xfa/fxfa/parser/cxfa_incrementalload.h", + "xfa/fxfa/parser/cxfa_incrementalmerge.cpp", + "xfa/fxfa/parser/cxfa_incrementalmerge.h", + "xfa/fxfa/parser/cxfa_insert.cpp", + "xfa/fxfa/parser/cxfa_insert.h", + "xfa/fxfa/parser/cxfa_instancemanager.cpp", + "xfa/fxfa/parser/cxfa_instancemanager.h", + "xfa/fxfa/parser/cxfa_integer.cpp", + "xfa/fxfa/parser/cxfa_integer.h", + "xfa/fxfa/parser/cxfa_interactive.cpp", + "xfa/fxfa/parser/cxfa_interactive.h", + "xfa/fxfa/parser/cxfa_issuers.cpp", + "xfa/fxfa/parser/cxfa_issuers.h", + "xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp", + "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h", + "xfa/fxfa/parser/cxfa_items.cpp", + "xfa/fxfa/parser/cxfa_items.h", + "xfa/fxfa/parser/cxfa_jog.cpp", + "xfa/fxfa/parser/cxfa_jog.h", + "xfa/fxfa/parser/cxfa_keep.cpp", + "xfa/fxfa/parser/cxfa_keep.h", + "xfa/fxfa/parser/cxfa_keyusage.cpp", + "xfa/fxfa/parser/cxfa_keyusage.h", + "xfa/fxfa/parser/cxfa_labelprinter.cpp", + "xfa/fxfa/parser/cxfa_labelprinter.h", + "xfa/fxfa/parser/cxfa_layout.cpp", + "xfa/fxfa/parser/cxfa_layout.h", + "xfa/fxfa/parser/cxfa_layoutcontext.h", "xfa/fxfa/parser/cxfa_layoutitem.cpp", "xfa/fxfa/parser/cxfa_layoutitem.h", "xfa/fxfa/parser/cxfa_layoutpagemgr.cpp", "xfa/fxfa/parser/cxfa_layoutpagemgr.h", "xfa/fxfa/parser/cxfa_layoutprocessor.cpp", "xfa/fxfa/parser/cxfa_layoutprocessor.h", + "xfa/fxfa/parser/cxfa_level.cpp", + "xfa/fxfa/parser/cxfa_level.h", "xfa/fxfa/parser/cxfa_line.cpp", "xfa/fxfa/parser/cxfa_line.h", + "xfa/fxfa/parser/cxfa_linear.cpp", + "xfa/fxfa/parser/cxfa_linear.h", + "xfa/fxfa/parser/cxfa_linearized.cpp", + "xfa/fxfa/parser/cxfa_linearized.h", + "xfa/fxfa/parser/cxfa_list.cpp", + "xfa/fxfa/parser/cxfa_list.h", + "xfa/fxfa/parser/cxfa_locale.cpp", + "xfa/fxfa/parser/cxfa_locale.h", + "xfa/fxfa/parser/cxfa_localemgr.cpp", + "xfa/fxfa/parser/cxfa_localemgr.h", + "xfa/fxfa/parser/cxfa_localeset.cpp", + "xfa/fxfa/parser/cxfa_localeset.h", + "xfa/fxfa/parser/cxfa_localevalue.cpp", + "xfa/fxfa/parser/cxfa_localevalue.h", + "xfa/fxfa/parser/cxfa_lockdocument.cpp", + "xfa/fxfa/parser/cxfa_lockdocument.h", + "xfa/fxfa/parser/cxfa_log.cpp", + "xfa/fxfa/parser/cxfa_log.h", + "xfa/fxfa/parser/cxfa_manifest.cpp", + "xfa/fxfa/parser/cxfa_manifest.h", + "xfa/fxfa/parser/cxfa_map.cpp", + "xfa/fxfa/parser/cxfa_map.h", "xfa/fxfa/parser/cxfa_margin.cpp", "xfa/fxfa/parser/cxfa_margin.h", + "xfa/fxfa/parser/cxfa_mdp.cpp", + "xfa/fxfa/parser/cxfa_mdp.h", "xfa/fxfa/parser/cxfa_measurement.cpp", "xfa/fxfa/parser/cxfa_measurement.h", + "xfa/fxfa/parser/cxfa_medium.cpp", + "xfa/fxfa/parser/cxfa_medium.h", + "xfa/fxfa/parser/cxfa_mediuminfo.cpp", + "xfa/fxfa/parser/cxfa_mediuminfo.h", + "xfa/fxfa/parser/cxfa_meridiem.cpp", + "xfa/fxfa/parser/cxfa_meridiem.h", + "xfa/fxfa/parser/cxfa_meridiemnames.cpp", + "xfa/fxfa/parser/cxfa_meridiemnames.h", + "xfa/fxfa/parser/cxfa_message.cpp", + "xfa/fxfa/parser/cxfa_message.h", + "xfa/fxfa/parser/cxfa_messaging.cpp", + "xfa/fxfa/parser/cxfa_messaging.h", + "xfa/fxfa/parser/cxfa_mode.cpp", + "xfa/fxfa/parser/cxfa_mode.h", + "xfa/fxfa/parser/cxfa_modifyannots.cpp", + "xfa/fxfa/parser/cxfa_modifyannots.h", + "xfa/fxfa/parser/cxfa_month.cpp", + "xfa/fxfa/parser/cxfa_month.h", + "xfa/fxfa/parser/cxfa_monthnames.cpp", + "xfa/fxfa/parser/cxfa_monthnames.h", + "xfa/fxfa/parser/cxfa_msgid.cpp", + "xfa/fxfa/parser/cxfa_msgid.h", + "xfa/fxfa/parser/cxfa_nameattr.cpp", + "xfa/fxfa/parser/cxfa_nameattr.h", + "xfa/fxfa/parser/cxfa_neverembed.cpp", + "xfa/fxfa/parser/cxfa_neverembed.h", "xfa/fxfa/parser/cxfa_node.cpp", + "xfa/fxfa/parser/cxfa_node.h", + "xfa/fxfa/parser/cxfa_node_statics.cpp", "xfa/fxfa/parser/cxfa_nodehelper.cpp", "xfa/fxfa/parser/cxfa_nodehelper.h", - "xfa/fxfa/parser/cxfa_nodelist.cpp", + "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h", + "xfa/fxfa/parser/cxfa_nodelocale.cpp", + "xfa/fxfa/parser/cxfa_nodelocale.h", + "xfa/fxfa/parser/cxfa_numberofcopies.cpp", + "xfa/fxfa/parser/cxfa_numberofcopies.h", + "xfa/fxfa/parser/cxfa_numberpattern.cpp", + "xfa/fxfa/parser/cxfa_numberpattern.h", + "xfa/fxfa/parser/cxfa_numberpatterns.cpp", + "xfa/fxfa/parser/cxfa_numberpatterns.h", + "xfa/fxfa/parser/cxfa_numbersymbol.cpp", + "xfa/fxfa/parser/cxfa_numbersymbol.h", + "xfa/fxfa/parser/cxfa_numbersymbols.cpp", + "xfa/fxfa/parser/cxfa_numbersymbols.h", + "xfa/fxfa/parser/cxfa_numericedit.cpp", + "xfa/fxfa/parser/cxfa_numericedit.h", "xfa/fxfa/parser/cxfa_object.cpp", + "xfa/fxfa/parser/cxfa_object.h", "xfa/fxfa/parser/cxfa_occur.cpp", "xfa/fxfa/parser/cxfa_occur.h", + "xfa/fxfa/parser/cxfa_oid.cpp", + "xfa/fxfa/parser/cxfa_oid.h", + "xfa/fxfa/parser/cxfa_oids.cpp", + "xfa/fxfa/parser/cxfa_oids.h", + "xfa/fxfa/parser/cxfa_openaction.cpp", + "xfa/fxfa/parser/cxfa_openaction.h", + "xfa/fxfa/parser/cxfa_operation.cpp", + "xfa/fxfa/parser/cxfa_operation.h", + "xfa/fxfa/parser/cxfa_output.cpp", + "xfa/fxfa/parser/cxfa_output.h", + "xfa/fxfa/parser/cxfa_outputbin.cpp", + "xfa/fxfa/parser/cxfa_outputbin.h", + "xfa/fxfa/parser/cxfa_outputxsl.cpp", + "xfa/fxfa/parser/cxfa_outputxsl.h", + "xfa/fxfa/parser/cxfa_overflow.cpp", + "xfa/fxfa/parser/cxfa_overflow.h", + "xfa/fxfa/parser/cxfa_overprint.cpp", + "xfa/fxfa/parser/cxfa_overprint.h", + "xfa/fxfa/parser/cxfa_packet.cpp", + "xfa/fxfa/parser/cxfa_packet.h", + "xfa/fxfa/parser/cxfa_packets.cpp", + "xfa/fxfa/parser/cxfa_packets.h", + "xfa/fxfa/parser/cxfa_pagearea.cpp", + "xfa/fxfa/parser/cxfa_pagearea.h", + "xfa/fxfa/parser/cxfa_pageoffset.cpp", + "xfa/fxfa/parser/cxfa_pageoffset.h", + "xfa/fxfa/parser/cxfa_pagerange.cpp", + "xfa/fxfa/parser/cxfa_pagerange.h", + "xfa/fxfa/parser/cxfa_pageset.cpp", + "xfa/fxfa/parser/cxfa_pageset.h", + "xfa/fxfa/parser/cxfa_pagination.cpp", + "xfa/fxfa/parser/cxfa_pagination.h", + "xfa/fxfa/parser/cxfa_paginationoverride.cpp", + "xfa/fxfa/parser/cxfa_paginationoverride.h", "xfa/fxfa/parser/cxfa_para.cpp", "xfa/fxfa/parser/cxfa_para.h", + "xfa/fxfa/parser/cxfa_part.cpp", + "xfa/fxfa/parser/cxfa_part.h", + "xfa/fxfa/parser/cxfa_password.cpp", + "xfa/fxfa/parser/cxfa_password.h", + "xfa/fxfa/parser/cxfa_passwordedit.cpp", + "xfa/fxfa/parser/cxfa_passwordedit.h", + "xfa/fxfa/parser/cxfa_pattern.cpp", + "xfa/fxfa/parser/cxfa_pattern.h", + "xfa/fxfa/parser/cxfa_pcl.cpp", + "xfa/fxfa/parser/cxfa_pcl.h", + "xfa/fxfa/parser/cxfa_pdf.cpp", + "xfa/fxfa/parser/cxfa_pdf.h", + "xfa/fxfa/parser/cxfa_pdfa.cpp", + "xfa/fxfa/parser/cxfa_pdfa.h", + "xfa/fxfa/parser/cxfa_permissions.cpp", + "xfa/fxfa/parser/cxfa_permissions.h", + "xfa/fxfa/parser/cxfa_picktraybypdfsize.cpp", + "xfa/fxfa/parser/cxfa_picktraybypdfsize.h", + "xfa/fxfa/parser/cxfa_picture.cpp", + "xfa/fxfa/parser/cxfa_picture.h", + "xfa/fxfa/parser/cxfa_plaintextmetadata.cpp", + "xfa/fxfa/parser/cxfa_plaintextmetadata.h", + "xfa/fxfa/parser/cxfa_presence.cpp", + "xfa/fxfa/parser/cxfa_presence.h", + "xfa/fxfa/parser/cxfa_present.cpp", + "xfa/fxfa/parser/cxfa_present.h", + "xfa/fxfa/parser/cxfa_print.cpp", + "xfa/fxfa/parser/cxfa_print.h", + "xfa/fxfa/parser/cxfa_printername.cpp", + "xfa/fxfa/parser/cxfa_printername.h", + "xfa/fxfa/parser/cxfa_printhighquality.cpp", + "xfa/fxfa/parser/cxfa_printhighquality.h", + "xfa/fxfa/parser/cxfa_printscaling.cpp", + "xfa/fxfa/parser/cxfa_printscaling.h", + "xfa/fxfa/parser/cxfa_producer.cpp", + "xfa/fxfa/parser/cxfa_producer.h", + "xfa/fxfa/parser/cxfa_proto.cpp", + "xfa/fxfa/parser/cxfa_proto.h", + "xfa/fxfa/parser/cxfa_ps.cpp", + "xfa/fxfa/parser/cxfa_ps.h", + "xfa/fxfa/parser/cxfa_psmap.cpp", + "xfa/fxfa/parser/cxfa_psmap.h", + "xfa/fxfa/parser/cxfa_query.cpp", + "xfa/fxfa/parser/cxfa_query.h", + "xfa/fxfa/parser/cxfa_radial.cpp", + "xfa/fxfa/parser/cxfa_radial.h", + "xfa/fxfa/parser/cxfa_range.cpp", + "xfa/fxfa/parser/cxfa_range.h", + "xfa/fxfa/parser/cxfa_reason.cpp", + "xfa/fxfa/parser/cxfa_reason.h", + "xfa/fxfa/parser/cxfa_reasons.cpp", + "xfa/fxfa/parser/cxfa_reasons.h", + "xfa/fxfa/parser/cxfa_record.cpp", + "xfa/fxfa/parser/cxfa_record.h", + "xfa/fxfa/parser/cxfa_recordset.cpp", + "xfa/fxfa/parser/cxfa_recordset.h", + "xfa/fxfa/parser/cxfa_rectangle.cpp", "xfa/fxfa/parser/cxfa_rectangle.h", - "xfa/fxfa/parser/cxfa_resolveprocessor.cpp", - "xfa/fxfa/parser/cxfa_resolveprocessor.h", + "xfa/fxfa/parser/cxfa_ref.cpp", + "xfa/fxfa/parser/cxfa_ref.h", + "xfa/fxfa/parser/cxfa_relevant.cpp", + "xfa/fxfa/parser/cxfa_relevant.h", + "xfa/fxfa/parser/cxfa_rename.cpp", + "xfa/fxfa/parser/cxfa_rename.h", + "xfa/fxfa/parser/cxfa_renderpolicy.cpp", + "xfa/fxfa/parser/cxfa_renderpolicy.h", + "xfa/fxfa/parser/cxfa_rootelement.cpp", + "xfa/fxfa/parser/cxfa_rootelement.h", + "xfa/fxfa/parser/cxfa_runscripts.cpp", + "xfa/fxfa/parser/cxfa_runscripts.h", "xfa/fxfa/parser/cxfa_script.cpp", "xfa/fxfa/parser/cxfa_script.h", - "xfa/fxfa/parser/cxfa_scriptcontext.cpp", - "xfa/fxfa/parser/cxfa_scriptcontext.h", + "xfa/fxfa/parser/cxfa_scriptmodel.cpp", + "xfa/fxfa/parser/cxfa_scriptmodel.h", + "xfa/fxfa/parser/cxfa_select.cpp", + "xfa/fxfa/parser/cxfa_select.h", + "xfa/fxfa/parser/cxfa_setproperty.cpp", + "xfa/fxfa/parser/cxfa_setproperty.h", + "xfa/fxfa/parser/cxfa_severity.cpp", + "xfa/fxfa/parser/cxfa_severity.h", + "xfa/fxfa/parser/cxfa_sharptext.cpp", + "xfa/fxfa/parser/cxfa_sharptext.h", + "xfa/fxfa/parser/cxfa_sharpxhtml.cpp", + "xfa/fxfa/parser/cxfa_sharpxhtml.h", + "xfa/fxfa/parser/cxfa_sharpxml.cpp", + "xfa/fxfa/parser/cxfa_sharpxml.h", + "xfa/fxfa/parser/cxfa_signature.cpp", + "xfa/fxfa/parser/cxfa_signature.h", + "xfa/fxfa/parser/cxfa_signatureproperties.cpp", + "xfa/fxfa/parser/cxfa_signatureproperties.h", + "xfa/fxfa/parser/cxfa_signdata.cpp", + "xfa/fxfa/parser/cxfa_signdata.h", + "xfa/fxfa/parser/cxfa_signing.cpp", + "xfa/fxfa/parser/cxfa_signing.h", + "xfa/fxfa/parser/cxfa_silentprint.cpp", + "xfa/fxfa/parser/cxfa_silentprint.h", "xfa/fxfa/parser/cxfa_simple_parser.cpp", "xfa/fxfa/parser/cxfa_simple_parser.h", + "xfa/fxfa/parser/cxfa_soapaction.cpp", + "xfa/fxfa/parser/cxfa_soapaction.h", + "xfa/fxfa/parser/cxfa_soapaddress.cpp", + "xfa/fxfa/parser/cxfa_soapaddress.h", + "xfa/fxfa/parser/cxfa_solid.cpp", + "xfa/fxfa/parser/cxfa_solid.h", + "xfa/fxfa/parser/cxfa_source.cpp", + "xfa/fxfa/parser/cxfa_source.h", + "xfa/fxfa/parser/cxfa_sourceset.cpp", + "xfa/fxfa/parser/cxfa_sourceset.h", + "xfa/fxfa/parser/cxfa_speak.cpp", + "xfa/fxfa/parser/cxfa_speak.h", + "xfa/fxfa/parser/cxfa_staple.cpp", + "xfa/fxfa/parser/cxfa_staple.h", + "xfa/fxfa/parser/cxfa_startnode.cpp", + "xfa/fxfa/parser/cxfa_startnode.h", + "xfa/fxfa/parser/cxfa_startpage.cpp", + "xfa/fxfa/parser/cxfa_startpage.h", + "xfa/fxfa/parser/cxfa_stipple.cpp", + "xfa/fxfa/parser/cxfa_stipple.h", "xfa/fxfa/parser/cxfa_stroke.cpp", "xfa/fxfa/parser/cxfa_stroke.h", + "xfa/fxfa/parser/cxfa_subform.cpp", + "xfa/fxfa/parser/cxfa_subform.h", + "xfa/fxfa/parser/cxfa_subformset.cpp", + "xfa/fxfa/parser/cxfa_subformset.h", + "xfa/fxfa/parser/cxfa_subjectdn.cpp", + "xfa/fxfa/parser/cxfa_subjectdn.h", + "xfa/fxfa/parser/cxfa_subjectdns.cpp", + "xfa/fxfa/parser/cxfa_subjectdns.h", "xfa/fxfa/parser/cxfa_submit.cpp", "xfa/fxfa/parser/cxfa_submit.h", + "xfa/fxfa/parser/cxfa_submitformat.cpp", + "xfa/fxfa/parser/cxfa_submitformat.h", + "xfa/fxfa/parser/cxfa_submiturl.cpp", + "xfa/fxfa/parser/cxfa_submiturl.h", + "xfa/fxfa/parser/cxfa_subsetbelow.cpp", + "xfa/fxfa/parser/cxfa_subsetbelow.h", + "xfa/fxfa/parser/cxfa_suppressbanner.cpp", + "xfa/fxfa/parser/cxfa_suppressbanner.h", + "xfa/fxfa/parser/cxfa_tagged.cpp", + "xfa/fxfa/parser/cxfa_tagged.h", + "xfa/fxfa/parser/cxfa_template.cpp", + "xfa/fxfa/parser/cxfa_template.h", + "xfa/fxfa/parser/cxfa_templatecache.cpp", + "xfa/fxfa/parser/cxfa_templatecache.h", "xfa/fxfa/parser/cxfa_text.cpp", "xfa/fxfa/parser/cxfa_text.h", + "xfa/fxfa/parser/cxfa_textedit.cpp", + "xfa/fxfa/parser/cxfa_textedit.h", "xfa/fxfa/parser/cxfa_thisproxy.cpp", + "xfa/fxfa/parser/cxfa_thisproxy.h", + "xfa/fxfa/parser/cxfa_threshold.cpp", + "xfa/fxfa/parser/cxfa_threshold.h", + "xfa/fxfa/parser/cxfa_time.cpp", + "xfa/fxfa/parser/cxfa_time.h", + "xfa/fxfa/parser/cxfa_timepattern.cpp", + "xfa/fxfa/parser/cxfa_timepattern.h", + "xfa/fxfa/parser/cxfa_timepatterns.cpp", + "xfa/fxfa/parser/cxfa_timepatterns.h", + "xfa/fxfa/parser/cxfa_timestamp.cpp", + "xfa/fxfa/parser/cxfa_timestamp.h", + "xfa/fxfa/parser/cxfa_timezoneprovider.cpp", + "xfa/fxfa/parser/cxfa_timezoneprovider.h", + "xfa/fxfa/parser/cxfa_to.cpp", + "xfa/fxfa/parser/cxfa_to.h", "xfa/fxfa/parser/cxfa_tooltip.cpp", "xfa/fxfa/parser/cxfa_tooltip.h", + "xfa/fxfa/parser/cxfa_trace.cpp", + "xfa/fxfa/parser/cxfa_trace.h", + "xfa/fxfa/parser/cxfa_transform.cpp", + "xfa/fxfa/parser/cxfa_transform.h", + "xfa/fxfa/parser/cxfa_traversal.cpp", + "xfa/fxfa/parser/cxfa_traversal.h", + "xfa/fxfa/parser/cxfa_traverse.cpp", + "xfa/fxfa/parser/cxfa_traverse.h", "xfa/fxfa/parser/cxfa_traversestrategy_contentareacontainerlayoutitem.h", "xfa/fxfa/parser/cxfa_traversestrategy_contentlayoutitem.h", "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h", + "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h", + "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h", + "xfa/fxfa/parser/cxfa_treelist.cpp", + "xfa/fxfa/parser/cxfa_treelist.h", + "xfa/fxfa/parser/cxfa_type.cpp", + "xfa/fxfa/parser/cxfa_type.h", + "xfa/fxfa/parser/cxfa_typeface.cpp", + "xfa/fxfa/parser/cxfa_typeface.h", + "xfa/fxfa/parser/cxfa_typefaces.cpp", + "xfa/fxfa/parser/cxfa_typefaces.h", + "xfa/fxfa/parser/cxfa_ui.cpp", + "xfa/fxfa/parser/cxfa_ui.h", + "xfa/fxfa/parser/cxfa_update.cpp", + "xfa/fxfa/parser/cxfa_update.h", + "xfa/fxfa/parser/cxfa_uri.cpp", + "xfa/fxfa/parser/cxfa_uri.h", + "xfa/fxfa/parser/cxfa_user.cpp", + "xfa/fxfa/parser/cxfa_user.h", "xfa/fxfa/parser/cxfa_validate.cpp", "xfa/fxfa/parser/cxfa_validate.h", + "xfa/fxfa/parser/cxfa_validateapprovalsignatures.cpp", + "xfa/fxfa/parser/cxfa_validateapprovalsignatures.h", + "xfa/fxfa/parser/cxfa_validationmessaging.cpp", + "xfa/fxfa/parser/cxfa_validationmessaging.h", "xfa/fxfa/parser/cxfa_value.cpp", "xfa/fxfa/parser/cxfa_value.h", - "xfa/fxfa/parser/cxfa_valuearray.cpp", - "xfa/fxfa/parser/cxfa_valuearray.h", - "xfa/fxfa/parser/cxfa_widetextread.cpp", - "xfa/fxfa/parser/cxfa_widetextread.h", - "xfa/fxfa/parser/cxfa_widgetdata.cpp", - "xfa/fxfa/parser/cxfa_widgetdata.h", - "xfa/fxfa/parser/cxfa_xml_parser.cpp", - "xfa/fxfa/parser/cxfa_xml_parser.h", - "xfa/fxfa/parser/xfa_basic_data.cpp", + "xfa/fxfa/parser/cxfa_variables.cpp", + "xfa/fxfa/parser/cxfa_variables.h", + "xfa/fxfa/parser/cxfa_version.cpp", + "xfa/fxfa/parser/cxfa_version.h", + "xfa/fxfa/parser/cxfa_versioncontrol.cpp", + "xfa/fxfa/parser/cxfa_versioncontrol.h", + "xfa/fxfa/parser/cxfa_viewerpreferences.cpp", + "xfa/fxfa/parser/cxfa_viewerpreferences.h", + "xfa/fxfa/parser/cxfa_webclient.cpp", + "xfa/fxfa/parser/cxfa_webclient.h", + "xfa/fxfa/parser/cxfa_whitespace.cpp", + "xfa/fxfa/parser/cxfa_whitespace.h", + "xfa/fxfa/parser/cxfa_window.cpp", + "xfa/fxfa/parser/cxfa_window.h", + "xfa/fxfa/parser/cxfa_wsdladdress.cpp", + "xfa/fxfa/parser/cxfa_wsdladdress.h", + "xfa/fxfa/parser/cxfa_wsdlconnection.cpp", + "xfa/fxfa/parser/cxfa_wsdlconnection.h", + "xfa/fxfa/parser/cxfa_xdc.cpp", + "xfa/fxfa/parser/cxfa_xdc.h", + "xfa/fxfa/parser/cxfa_xdp.cpp", + "xfa/fxfa/parser/cxfa_xdp.h", + "xfa/fxfa/parser/cxfa_xfa.cpp", + "xfa/fxfa/parser/cxfa_xfa.h", + "xfa/fxfa/parser/cxfa_xmlconnection.cpp", + "xfa/fxfa/parser/cxfa_xmlconnection.h", + "xfa/fxfa/parser/cxfa_xmllocale.cpp", + "xfa/fxfa/parser/cxfa_xmllocale.h", + "xfa/fxfa/parser/cxfa_xsdconnection.cpp", + "xfa/fxfa/parser/cxfa_xsdconnection.h", + "xfa/fxfa/parser/cxfa_xsl.cpp", + "xfa/fxfa/parser/cxfa_xsl.h", + "xfa/fxfa/parser/cxfa_zpl.cpp", + "xfa/fxfa/parser/cxfa_zpl.h", "xfa/fxfa/parser/xfa_basic_data.h", - "xfa/fxfa/parser/xfa_basic_data_attributes.cpp", - "xfa/fxfa/parser/xfa_basic_data_element_attributes.cpp", - "xfa/fxfa/parser/xfa_basic_data_element_properties.cpp", "xfa/fxfa/parser/xfa_basic_data_element_script.cpp", "xfa/fxfa/parser/xfa_basic_data_enum.cpp", - "xfa/fxfa/parser/xfa_basic_data_packets.cpp", "xfa/fxfa/parser/xfa_document_datamerger_imp.cpp", "xfa/fxfa/parser/xfa_document_datamerger_imp.h", - "xfa/fxfa/parser/xfa_layout_itemlayout.cpp", - "xfa/fxfa/parser/xfa_layout_itemlayout.h", - "xfa/fxfa/parser/xfa_locale.cpp", - "xfa/fxfa/parser/xfa_locale.h", - "xfa/fxfa/parser/xfa_localemgr.cpp", - "xfa/fxfa/parser/xfa_localemgr.h", - "xfa/fxfa/parser/xfa_localevalue.cpp", - "xfa/fxfa/parser/xfa_localevalue.h", - "xfa/fxfa/parser/xfa_object.h", "xfa/fxfa/parser/xfa_resolvenode_rs.h", "xfa/fxfa/parser/xfa_utils.cpp", "xfa/fxfa/parser/xfa_utils.h", - "xfa/fxfa/xfa_checksum.h", - "xfa/fxfa/xfa_ffapp.h", - "xfa/fxfa/xfa_ffdoc.h", - "xfa/fxfa/xfa_ffdochandler.h", - "xfa/fxfa/xfa_ffdocview.h", - "xfa/fxfa/xfa_ffpageview.h", - "xfa/fxfa/xfa_ffwidget.h", - "xfa/fxfa/xfa_ffwidgethandler.h", - "xfa/fxfa/xfa_fontmgr.h", - "xfa/fxfa/xfa_rendercontext.h", - "xfa/fxgraphics/cfx_color.cpp", - "xfa/fxgraphics/cfx_color.h", - "xfa/fxgraphics/cfx_graphics.cpp", - "xfa/fxgraphics/cfx_graphics.h", - "xfa/fxgraphics/cfx_path.cpp", - "xfa/fxgraphics/cfx_path.h", - "xfa/fxgraphics/cfx_pattern.cpp", - "xfa/fxgraphics/cfx_pattern.h", - "xfa/fxgraphics/cfx_shading.cpp", - "xfa/fxgraphics/cfx_shading.h", + "xfa/fxgraphics/cxfa_gecolor.cpp", + "xfa/fxgraphics/cxfa_gecolor.h", + "xfa/fxgraphics/cxfa_gepath.cpp", + "xfa/fxgraphics/cxfa_gepath.h", + "xfa/fxgraphics/cxfa_gepattern.cpp", + "xfa/fxgraphics/cxfa_gepattern.h", + "xfa/fxgraphics/cxfa_geshading.cpp", + "xfa/fxgraphics/cxfa_geshading.h", + "xfa/fxgraphics/cxfa_graphics.cpp", + "xfa/fxgraphics/cxfa_graphics.h", ] include_dirs = [ "." ] deps = [ + ":fxbarcode", ":fxcrt", ":fxjs", ] @@ -1744,62 +2775,93 @@ test("pdfium_unittests") { sources = [ "core/fdrm/crypto/fx_crypt_unittest.cpp", "core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp", - "core/fpdfapi/font/fpdf_font_cid_unittest.cpp", - "core/fpdfapi/font/fpdf_font_unittest.cpp", + "core/fpdfapi/font/cpdf_cmapparser_unittest.cpp", + "core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp", + "core/fpdfapi/page/cpdf_devicecs_unittest.cpp", + "core/fpdfapi/page/cpdf_psengine_unittest.cpp", "core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp", "core/fpdfapi/page/cpdf_streamparser_unittest.cpp", "core/fpdfapi/parser/cpdf_array_unittest.cpp", + "core/fpdfapi/parser/cpdf_cross_ref_avail_unittest.cpp", "core/fpdfapi/parser/cpdf_document_unittest.cpp", + "core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp", + "core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp", + "core/fpdfapi/parser/cpdf_object_avail_unittest.cpp", "core/fpdfapi/parser/cpdf_object_unittest.cpp", + "core/fpdfapi/parser/cpdf_object_walker_unittest.cpp", + "core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp", "core/fpdfapi/parser/cpdf_parser_unittest.cpp", + "core/fpdfapi/parser/cpdf_read_validator_unittest.cpp", "core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp", "core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp", "core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp", "core/fpdfdoc/cpdf_dest_unittest.cpp", "core/fpdfdoc/cpdf_filespec_unittest.cpp", "core/fpdfdoc/cpdf_formfield_unittest.cpp", - "core/fpdftext/fpdf_text_int_unittest.cpp", + "core/fpdfdoc/cpdf_nametree_unittest.cpp", + "core/fpdftext/cpdf_linkextract_unittest.cpp", "core/fxcodec/codec/fx_codec_a85_unittest.cpp", "core/fxcodec/codec/fx_codec_jpx_unittest.cpp", "core/fxcodec/codec/fx_codec_rle_unittest.cpp", + "core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp", "core/fxcodec/jbig2/JBig2_Image_unittest.cpp", - "core/fxcrt/cfx_maybe_owned_unittest.cpp", - "core/fxcrt/cfx_observable_unittest.cpp", - "core/fxcrt/cfx_retain_ptr_unittest.cpp", - "core/fxcrt/cfx_shared_copy_on_write_unittest.cpp", - "core/fxcrt/cfx_string_pool_template_unittest.cpp", - "core/fxcrt/cfx_weak_ptr_unittest.cpp", - "core/fxcrt/fx_basic_bstring_unittest.cpp", - "core/fxcrt/fx_basic_gcc_unittest.cpp", - "core/fxcrt/fx_basic_memmgr_unittest.cpp", - "core/fxcrt/fx_basic_util_unittest.cpp", - "core/fxcrt/fx_basic_wstring_unittest.cpp", + "core/fxcrt/bytestring_unittest.cpp", + "core/fxcrt/cfx_seekablemultistream_unittest.cpp", "core/fxcrt/fx_bidi_unittest.cpp", + "core/fxcrt/fx_coordinates_unittest.cpp", "core/fxcrt/fx_extension_unittest.cpp", + "core/fxcrt/fx_memory_unittest.cpp", + "core/fxcrt/fx_random_unittest.cpp", + "core/fxcrt/fx_string_unittest.cpp", "core/fxcrt/fx_system_unittest.cpp", - "core/fxge/dib/fx_dib_engine_unittest.cpp", + "core/fxcrt/maybe_owned_unittest.cpp", + "core/fxcrt/observable_unittest.cpp", + "core/fxcrt/retain_ptr_unittest.cpp", + "core/fxcrt/shared_copy_on_write_unittest.cpp", + "core/fxcrt/string_pool_template_unittest.cpp", + "core/fxcrt/unowned_ptr_unittest.cpp", + "core/fxcrt/weak_ptr_unittest.cpp", + "core/fxcrt/widestring_unittest.cpp", + "core/fxge/dib/cstretchengine_unittest.cpp", + "fpdfsdk/fpdfcatalog_unittest.cpp", "fpdfsdk/fpdfdoc_unittest.cpp", "fpdfsdk/fpdfeditimg_unittest.cpp", - "fpdfsdk/fpdfview_unittest.cpp", + "testing/unit_test_main.cpp", ] deps = [ ":pdfium", ":test_support", + "//testing/gmock", "//testing/gtest", - "//testing/gtest:gtest_main", ] include_dirs = [] if (pdf_enable_xfa) { sources += [ - "xfa/fde/cfde_txtedtbuf_unittest.cpp", - "xfa/fde/css/cfde_cssdeclaration_unittest.cpp", - "xfa/fde/css/cfde_cssstylesheet_unittest.cpp", - "xfa/fde/css/cfde_cssvaluelistparser_unittest.cpp", - "xfa/fde/xml/fde_xml_imp_unittest.cpp", - "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp", - "xfa/fxfa/app/cxfa_textparser_unittest.cpp", - "xfa/fxfa/app/xfa_ffapp_unittest.cpp", - "xfa/fxfa/fm2js/xfa_simpleexpression_unittest.cpp", + "core/fxcodec/gif/cfx_gifcontext_unittest.cpp", + "core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp", + "core/fxcrt/css/cfx_cssdeclaration_unittest.cpp", + "core/fxcrt/css/cfx_cssstylesheet_unittest.cpp", + "core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp", + "core/fxcrt/xml/cfx_saxreader_unittest.cpp", + "core/fxcrt/xml/cfx_xmlsyntaxparser_unittest.cpp", + "fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp", + "fxbarcode/oned/BC_OnedCode128Writer_unittest.cpp", + "fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp", + "fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp", + "fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp", + "fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp", + "fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp", + "xfa/fde/cfde_texteditengine_unittest.cpp", + "xfa/fgas/crt/cfgas_formatstring_unittest.cpp", + "xfa/fgas/layout/cfx_rtfbreak_unittest.cpp", + "xfa/fwl/cfx_barcode_unittest.cpp", + "xfa/fxfa/cxfa_ffbarcode_unittest.cpp", + "xfa/fxfa/cxfa_textparser_unittest.cpp", + "xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp", + "xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp", + "xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp", + "xfa/fxfa/parser/cxfa_node_unittest.cpp", + "xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp", "xfa/fxfa/parser/xfa_utils_unittest.cpp", ] } @@ -1808,7 +2870,10 @@ test("pdfium_unittests") { deps += [ "//skia" ] } if (pdf_enable_v8) { - sources += [ "fpdfsdk/javascript/public_methods_unittest.cpp" ] + sources += [ + "fxjs/cjs_publicmethods_unittest.cpp", + "fxjs/cjs_util_unittest.cpp", + ] include_dirs += [ "//v8", "//v8/include", @@ -1822,19 +2887,23 @@ test("pdfium_unittests") { test("pdfium_embeddertests") { sources = [ - "core/fpdfapi/page/fpdf_page_func_embeddertest.cpp", + "core/fpdfapi/edit/cpdf_creator_embeddertest.cpp", + "core/fpdfapi/page/cpdf_stitchfunc_embeddertest.cpp", "core/fpdfapi/parser/cpdf_parser_embeddertest.cpp", "core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp", "core/fpdfapi/parser/fpdf_parser_decode_embeddertest.cpp", "core/fpdfapi/render/fpdf_render_loadimage_embeddertest.cpp", "core/fpdfapi/render/fpdf_render_pattern_embeddertest.cpp", "core/fxcodec/codec/fx_codec_embeddertest.cpp", - "core/fxge/ge/fx_ge_text_embeddertest.cpp", + "core/fxge/fx_ge_text_embeddertest.cpp", "fpdfsdk/fpdf_dataavail_embeddertest.cpp", "fpdfsdk/fpdf_flatten_embeddertest.cpp", "fpdfsdk/fpdf_structtree_embeddertest.cpp", + "fpdfsdk/fpdfannot_embeddertest.cpp", + "fpdfsdk/fpdfattachment_embeddertest.cpp", "fpdfsdk/fpdfdoc_embeddertest.cpp", "fpdfsdk/fpdfedit_embeddertest.cpp", + "fpdfsdk/fpdfeditpath_embeddertest.cpp", "fpdfsdk/fpdfext_embeddertest.cpp", "fpdfsdk/fpdfformfill_embeddertest.cpp", "fpdfsdk/fpdfppo_embeddertest.cpp", @@ -1844,13 +2913,20 @@ test("pdfium_embeddertests") { "fpdfsdk/fpdfview_c_api_test.h", "fpdfsdk/fpdfview_embeddertest.cpp", "fpdfsdk/fsdk_baseform_embeddertest.cpp", + "fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp", + "fpdfsdk/pwl/cpwl_edit_embeddertest.cpp", "testing/embedder_test.cpp", "testing/embedder_test.h", + "testing/embedder_test_main.cpp", "testing/embedder_test_mock_delegate.h", "testing/embedder_test_timer_handling_delegate.h", - "xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp", + "testing/fake_file_access.cpp", + "testing/fake_file_access.h", + "testing/range_set.cpp", + "testing/range_set.h", ] deps = [ + ":image_diff", ":pdfium", ":test_support", "//testing/gmock", @@ -1861,7 +2937,7 @@ test("pdfium_embeddertests") { if (pdf_enable_v8) { sources += [ - "fpdfsdk/javascript/public_methods_embeddertest.cpp", + "fxjs/cjs_publicmethods_embeddertest.cpp", "fxjs/fxjs_v8_embeddertest.cpp", "testing/js_embedder_test.cpp", "testing/js_embedder_test.h", @@ -1869,6 +2945,15 @@ test("pdfium_embeddertests") { deps += [ ":fxjs" ] configs += [ "//v8:external_startup_data" ] } + if (pdf_enable_xfa) { + sources += [ + "fxjs/cfxjse_formcalc_context_embeddertest.cpp", + "testing/xfa_js_embedder_test.cpp", + "testing/xfa_js_embedder_test.h", + "xfa/fwl/cfwl_edit_embeddertest.cpp", + "xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp", + ] + } if (is_android) { ignore_all_data_deps = true use_raw_android_executable = true @@ -1882,6 +2967,23 @@ if (pdf_is_standalone) { "//samples", ] } + + executable("pdfium_diff") { + testonly = true + sources = [ + "testing/image_diff/image_diff.cpp", + ] + deps = [ + ":image_diff", + ":pdfium", + "//build/config:exe_and_shlib_deps", + "//build/win:default_exe_manifest", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ ":pdfium_core_config" ] + } + group("fuzzers") { testonly = true deps = [ @@ -1889,3 +2991,18 @@ if (pdf_is_standalone) { ] } } + +group("pdfium_all") { + testonly = true + deps = [ + ":pdfium_embeddertests", + ":pdfium_unittests", + ] + if (pdf_is_standalone) { + deps += [ + ":fuzzers", + ":pdfium_diff", + ":samples", + ] + } +} diff --git a/DEPS b/DEPS index 7ebf412cdb61e517075e60419cb9d7fbdb9e6f22..7abc60f16e48155e4fd7ff275ceef99a6abf625d 100644 --- a/DEPS +++ b/DEPS @@ -1,25 +1,41 @@ use_relative_paths = True vars = { + # By default, we should check out everything needed to run on the main + # chromium waterfalls. This var can be also be set to "small", in order + # to skip things are not strictly needed to build chromium for development + # purposes. + 'checkout_configuration': 'default', + + # TODO(dpranke): change to != "small" once != is supported. + 'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"', + 'chromium_git': 'https://chromium.googlesource.com', 'pdfium_git': 'https://pdfium.googlesource.com', - 'android_ndk_revision': '26d93ec07f3ce2ec2cdfeae1b21ee6f12ff868d8', - 'build_revision': 'dd795a26b9e43ff3a0d761bfd509c2fa67a3a7a1', - 'buildtools_revision': 'cf493f8b1ae59611b19b000d7af922559b6ae92a', - 'catapult_revision': '86352b966b0245d6883e5f7df27687856978b6d7', - 'clang_revision': '37d701b87a10a2bdee1a5c3523f754ebf64a7e66', + 'android_ndk_revision': 'd57523210239b867fa4fb9d05c2aacc3f1802fe0', + 'binutils_revision': 'e146228c20af6af922887d0be2d3641cbffb33c5', + 'build_revision': '097c79babc9b2ce40b61c3e33da1c6681acf837c', + 'buildtools_revision': 'b36c7b60ed73919b157c7d23ec5fce2aa69ab05e', + 'catapult_revision': 'd624b3ced2c81d4fb4ea98a8dbb4532272cc1e0a', + 'clang_revision': 'ac1e5f78c39dc2a262af149404dd36c140eecdc1', 'cygwin_revision': 'c89e446b273697fadf3a10ff1007a97c0b7de6df', - 'gen_library_loader_revision': '916d4acd8b2cde67a390737dfba90b3c37de23a1', + 'depot_tools_revision': '2e8d8348b8574f06c26dbf3ef959b5df11ba5148', + 'freetype_revision': '2c048a8a622e9f44f255aa3316026f124ac9ecbc', 'gmock_revision': '29763965ab52f24565299976b936d1265cb6a271', 'gtest_revision': '8245545b6dc9c4703e6496d1efd19e975ad2b038', - 'icu_revision': '73e24736676b4b438270fda44e5b2c83b49fdd80', - 'instrumented_lib_revision': '45f5814b1543e41ea0be54c771e3840ea52cca4a', - 'pdfium_tests_revision': 'd25a422ab03d6c3109370bc454c629575e969329', - 'skia_revision': '90e3cd78991ef337dbd0023efb30ece864694308', + 'icu_revision': 'e3b480d3be4446ea17011c0cdc9c4cd380a5c58f', + 'instrumented_lib_revision': '28417458ac4dc79f68915079d0f283f682504cc0', + 'jinja2_revision': 'd34383206fa42d52faa10bb9931d6d538f3a57e0', + 'jpeg_turbo_revision': '7260e4d8b8e1e40b17f03fafdf1cd83296900f76', + 'markupsafe_revision': '8f45f5cfa0009d2a70589bcda0349b8cb2b72783', + 'pdfium_tests_revision': '3d6228da656a3974d72223a702e6804df494703e', + 'skia_revision': '40ca2087ef0752d78fd2e0995471102fe96fe9fe', 'tools_memory_revision': '427f10475e1a8d72424c29d00bf689122b738e5d', - 'trace_event_revision': '06294c8a4a6f744ef284cd63cfe54dbf61eea290', - 'v8_revision': '7a634798302b4ab1f1525a9a881629519c0c2a99', + 'trace_event_revision': '0e9a47d74970bee1bbfc063c47215406f8918699', + 'v8_revision': '0c287882ea233f299a91f6b72b56d8faaecf52c0', + 'yasm_source_revision': 'b98114e18d8b9b84586b10d24353ab8616d4c5fc', + 'zlib_revision': '91155b5d0737713fc7f0499cf0ba2c4f2af24014', } deps = { @@ -31,7 +47,8 @@ deps = { Var('chromium_git') + "/chromium/src/build.git@" + Var('build_revision'), "buildtools": - Var('chromium_git') + "/chromium/buildtools.git@" + Var('buildtools_revision'), + Var('chromium_git') + "/chromium/buildtools.git@" + + Var('buildtools_revision'), "testing/corpus": Var('pdfium_git') + "/pdfium_tests@" + Var('pdfium_tests_revision'), @@ -42,25 +59,56 @@ deps = { "testing/gtest": Var('chromium_git') + "/external/googletest.git@" + Var('gtest_revision'), + "third_party/binutils": + Var('chromium_git') + "/chromium/src/third_party/binutils.git@" + + Var('binutils_revision'), + + 'third_party/depot_tools': + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + + Var('depot_tools_revision'), + + "third_party/freetype/src": + Var('chromium_git') + '/chromium/src/third_party/freetype2.git@' + + Var('freetype_revision'), + "third_party/icu": Var('chromium_git') + "/chromium/deps/icu.git@" + Var('icu_revision'), "third_party/instrumented_libraries": - Var('chromium_git') + "/chromium/src/third_party/instrumented_libraries.git@" + Var('instrumented_lib_revision'), + Var('chromium_git') + + "/chromium/src/third_party/instrumented_libraries.git@" + + Var('instrumented_lib_revision'), + + "third_party/jinja2": + Var('chromium_git') + "/chromium/src/third_party/jinja2.git@" + + Var('jinja2_revision'), + + "third_party/markupsafe": + Var('chromium_git') + "/chromium/src/third_party/markupsafe.git@" + + Var('markupsafe_revision'), + + "third_party/libjpeg_turbo": + Var('chromium_git') + "/chromium/deps/libjpeg_turbo.git@" + + Var('jpeg_turbo_revision'), "third_party/skia": - Var('chromium_git') + '/skia.git' + '@' + Var('skia_revision'), + Var('chromium_git') + '/skia.git@' + Var('skia_revision'), + + "third_party/zlib": + Var('chromium_git') + "/chromium/src/third_party/zlib.git@" + + Var('zlib_revision'), + + 'third_party/yasm/source/patched-yasm': + Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git@' + + Var('yasm_source_revision'), "tools/clang": Var('chromium_git') + "/chromium/src/tools/clang@" + Var('clang_revision'), - "tools/generate_library_loader": - Var('chromium_git') + "/chromium/src/tools/generate_library_loader@" + - Var('gen_library_loader_revision'), - # TODO(GYP): Remove this when no tools rely on GYP anymore. "tools/gyp": - Var('chromium_git') + '/external/gyp.git' + '@' + 'c61b0b35c8396bfd59efc6cfc11401d912b0f510', + Var('chromium_git') + '/external/gyp.git@' + + 'eb296f67da078ec01f5e3a9ea9cdc6d26d680161', "tools/memory": Var('chromium_git') + "/chromium/src/tools/memory@" + @@ -75,7 +123,9 @@ deps_os = { "third_party/android_ndk": Var('chromium_git') + "/android_ndk.git@" + Var('android_ndk_revision'), "third_party/catapult": - Var('chromium_git') + "/external/github.com/catapult-project/catapult.git@" + Var('catapult_revision'), + Var('chromium_git') + + "/external/github.com/catapult-project/catapult.git@" + + Var('catapult_revision'), }, "win": { "v8/third_party/cygwin": @@ -103,7 +153,6 @@ specific_include_rules = { } hooks = [ - # Pull GN binaries. This needs to be before running GYP below. { 'name': 'gn_win', 'action': [ 'download_from_google_storage', @@ -178,11 +227,30 @@ hooks = [ 'pdfium/tools/clang/scripts/update.py' ], }, + { + 'name': 'binutils', + 'pattern': 'src/third_party/binutils', + 'condition': 'host_os == "linux"', + 'action': [ + 'python', + 'pdfium/third_party/binutils/download.py', + ], + }, + { + # Downloads the current stable linux sysroot to build/linux/ if needed. + # This sysroot updates at about the same rate that the chrome build deps + # change. + 'name': 'sysroot', + 'pattern': '.', + 'action': ['python', 'pdfium/build/linux/sysroot_scripts/install-sysroot.py', + '--running-as-hook'], + }, { # Update the Windows toolchain if necessary. 'name': 'win_toolchain', 'pattern': '.', - 'action': ['python', 'pdfium/build/vs_toolchain.py', 'update'], + 'condition': 'checkout_win', + 'action': ['vpython', 'pdfium/build/vs_toolchain.py', 'update', '--force'], }, { # Update the Mac toolchain if necessary. @@ -191,11 +259,27 @@ hooks = [ 'action': ['python', 'pdfium/build/mac_toolchain.py'], }, { - # Pull sanitizer-instrumented third-party libraries if requested via - # GYP_DEFINES. - 'name': 'instrumented_libraries', - 'pattern': '\\.sha1', - 'action': ['python', 'pdfium/third_party/instrumented_libraries/scripts/download_binaries.py'], + 'name': 'msan_chained_origins', + 'pattern': '.', + 'condition': 'checkout_instrumented_libraries', + 'action': [ 'python', + 'pdfium/third_party/depot_tools/download_from_google_storage.py', + "--no_resume", + "--no_auth", + "--bucket", "chromium-instrumented-libraries", + "-s", "pdfium/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1", + ], + }, + { + 'name': 'msan_no_origins', + 'pattern': '.', + 'condition': 'checkout_instrumented_libraries', + 'action': [ 'python', + 'pdfium/third_party/depot_tools/download_from_google_storage.py', + "--no_resume", + "--no_auth", + "--bucket", "chromium-instrumented-libraries", + "-s", "pdfium/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1", + ], }, - ] diff --git a/PRESUBMIT.py b/PRESUBMIT.py index db1bf00eb3c6cfadd21d0e809b699d95b933283a..a7db1230d4c60060fa97eec2c58de61639542bd7 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -249,6 +249,48 @@ def _CheckIncludeOrder(input_api, output_api): warnings)) return results +def _CheckTestDuplicates(input_api, output_api): + """Checks that pixel and javascript tests don't contain duplicates. + We use .in and .pdf files, having both can cause race conditions on the bots, + which run the tests in parallel. + """ + tests_added = [] + results = [] + for f in input_api.AffectedFiles(): + if not f.LocalPath().startswith(('testing/resources/pixel/', + 'testing/resources/javascript/')): + continue + end_len = 0 + if f.LocalPath().endswith('.in'): + end_len = 3 + elif f.LocalPath().endswith('.pdf'): + end_len = 4 + else: + continue + path = f.LocalPath()[:-end_len] + if path in tests_added: + results.append(output_api.PresubmitError( + 'Remove %s to prevent shadowing %s' % (path + '.pdf', + path + '.in'))) + else: + tests_added.append(path) + return results + +def _CheckPNGFormat(input_api, output_api): + """Checks that .png files have a format that will be considered valid by our + test runners. If a file ends with .png, then it must be of the form + NAME_expected(_(win|mac|linux))?.pdf.#.png""" + expected_pattern = input_api.re.compile( + r'.+_expected(_(win|mac|linux))?\.pdf\.\d+.png') + results = [] + for f in input_api.AffectedFiles(include_deletes=False): + if not f.LocalPath().endswith('.png'): + continue + if expected_pattern.match(f.LocalPath()): + continue + results.append(output_api.PresubmitError( + 'PNG file %s does not have the correct format' % f.LocalPath())) + return results def CheckChangeOnUpload(input_api, output_api): results = [] @@ -257,5 +299,7 @@ def CheckChangeOnUpload(input_api, output_api): results += input_api.canned_checks.CheckChangeLintsClean( input_api, output_api, None, LINT_FILTERS) results += _CheckIncludeOrder(input_api, output_api) + results += _CheckTestDuplicates(input_api, output_api) + results += _CheckPNGFormat(input_api, output_api) return results diff --git a/README.md b/README.md index 8e1fbcb93a0e322128e693e6574f8cf175de28f4..62efdbc0330a43ae9570d0f0b475e687ca77bbb2 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,11 @@ Also install Python, Subversion, and Git and make sure they're in your path. ### Windows development -PDFium uses a similar Windows toolchain as Chromium: +PDFium uses the same build tool as Chromium: #### Open source contributors -Visual Studio 2015 Update 2 or later is highly recommended. +Please refer to [Chromium's Visual Studio set up](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#visual-studio) +for requirements and instructions on build environment configuration. Run `set DEPOT_TOOLS_WIN_TOOLCHAIN=0`, or set that variable in your global environment. @@ -28,6 +29,9 @@ The default architecture for Windows, Linux, and Mac is "`x64`". On Windows, override the default value. If you specify Android build, the default CPU architecture will be "`arm`". +It is expected that there are still some places lurking in the code which will +not function properly on big-endian architectures. Bugs and/or patches are +welcome, however providing this support is **not** a priority at this time. #### Google employees @@ -36,7 +40,7 @@ authentication instructions. **Note that you must authenticate with your @google.com credentials**. Enter "0" if asked for a project-id. Once you've done this, the toolchain will be installed automatically for -you in [the step](#GenBuild) below. +you in the [Generate the build files](#GenBuild) step below. The toolchain will be in `depot_tools\win_toolchain\vs_files\`, and windbg can be found in `depot_tools\win_toolchain\vs_files\\win_sdk\Debuggers`. @@ -58,16 +62,19 @@ gclient sync cd pdfium ``` -## Generate the build files - -We use GN to generate the build files and -[Ninja](http://martine.github.io/ninja/) (also included with the depot\_tools -checkout) to execute the build files. +Additional build dependencies need to be installed by running: ``` -gn gen +./build/install-build-deps.sh ``` +## Generate the build files + +We use GN to generate the build files and +[Ninja](http://martine.github.io/ninja/) +to execute the build files. Both of these are included with the +depot\_tools checkout. + ### Selecting build configuration PDFium may be built either with or without JavaScript support, and with @@ -76,9 +83,10 @@ default. Also note that the XFA feature requires JavaScript. Configuration is done by executing `gn args ` to configure the build. This will launch an editor in which you can set the following arguments. +A typical `` name is `out/Debug`. ``` -use_goma = true # Googlers only. +use_goma = true # Googlers only. Make sure goma is installed and running first. is_debug = true # Enable debugging features. pdf_use_skia = false # Set true to enable experimental skia backend. @@ -90,19 +98,21 @@ pdf_is_standalone = true # Set for a non-embedded build. is_component_build = false # Disable component build (must be false) clang_use_chrome_plugins = false # Currently must be false. -use_sysroot = false # Currently must be false on Linux. ``` Note, you must set `pdf_is_standalone = true` if you want the sample applications like `pdfium_test` to build. -When complete the arguments will be stored in `/args.gn`. +When complete the arguments will be stored in `/args.gn`, and +GN will automatically use the new arguments to generate build files. +Should your files fail to generate, please double-check that you have set +use\_sysroot as indicated above. ## Building the code -If you used Ninja, you can build the sample program by: -`ninja -C /pdfium_test` You can build the entire product (which -includes a few unit tests) by: `ninja -C `. +You can build the sample program by running: `ninja -C pdfium_test` +You can build the entire product (which includes a few unit tests) by running: +`ninja -C pdfium_all`. ## Running the sample program @@ -126,6 +136,11 @@ differences on the various platforms. These tests are reliable on the bots. If you see failures, it can be a good idea to run the tests on the tip-of-tree checkout to see if the same failures appear. +## Code Coverage + +Code coverage reports for PDFium can be generated in Linux development +environments. Details can be found [here](/docs/code-coverage.md). + ## Waterfall The current health of the source tree can be found at @@ -153,7 +168,10 @@ and add the "Cr-Internals-Plugins-PDF" label. For contributing code, we will follow [Chromium's process](http://dev.chromium.org/developers/contributing-code) -as much as possible. The main exceptions is: +as much as possible. The main exceptions are: 1. Code has to conform to the existing style and not Chromium/Google style. - +2. PDFium uses a different tool for code reviews, and credentials for +the tool need to be generated before uploading a CL. +3. PDFium is currently holding at C++11 compatibility, rejecting features that +are only present in C++14 (onto which Chromium is now slowly moving). diff --git a/build_overrides/README.md b/build_overrides/README.md index cc0efbf407558bba352d7a3a758f60f3dd74e6f1..69a38d4ab8a6cf003561801f3b19acb84c186c84 100644 --- a/build_overrides/README.md +++ b/build_overrides/README.md @@ -16,7 +16,7 @@ create its own build_overrides/v8.gni file, and in it set `build_standalone_d8 = false`. The two files should define the same set of variables, but the values may -vary as appropriate to suit the the needs of the two different builds. +vary as appropriate to suit the needs of the two different builds. The build.gni file provides a way for projects to override defaults for variables used in //build itself (which we want to be shareable between diff --git a/build_overrides/pdfium.gni b/build_overrides/pdfium.gni index 18e6a8739944e12983a9b0d9d34b8db41a65eba0..ab89cd997bda5ee039b460db8bcd2879448809f2 100644 --- a/build_overrides/pdfium.gni +++ b/build_overrides/pdfium.gni @@ -4,17 +4,29 @@ # This file contains PDFium-related build overrides. +# Build PDFium either using a bundled FreeType library, or using the FreeType +# target defined in //build/config/freetype. +# Default: Use a bundled FreeType. +pdf_bundle_freetype_override = true + # Build PDFium either with or without v8 support. +# Default: With V8 support. pdf_enable_v8_override = true # Build PDFium either with or without XFA Forms support. +# Default: Without XFA support. pdf_enable_xfa_override = false -# Build PDFium against skia (experimental) rather than agg, replacing all PDFium graphics. +# Build PDFium against skia (experimental) rather than agg, replacing all PDFium +# graphics. +# Default: Use agg. pdf_use_skia_override = false -# Build PDFium against skia (experimental) rather than agg, adding only path support. +# Build PDFium against skia (experimental) rather than agg, adding only path +# support. +# Default: Use agg. pdf_use_skia_paths_override = false # Build PDFium either with or without experimental win32 GDI APIs. +# Default: Without experimental win32 GDI APIs. pdf_use_win32_gdi_override = false diff --git a/core/fdrm/crypto/fx_crypt.cpp b/core/fdrm/crypto/fx_crypt.cpp index 4010ff49eeb04dab5487120b938a5be0af6583c2..d53fa6ba7aec522af2f5f45fd74f5da61e1d4ac6 100644 --- a/core/fdrm/crypto/fx_crypt.cpp +++ b/core/fdrm/crypto/fx_crypt.cpp @@ -6,59 +6,7 @@ #include "core/fdrm/crypto/fx_crypt.h" -#ifdef __cplusplus -extern "C" { -#endif - -void CRYPT_ArcFourSetup(CRYPT_rc4_context* s, - const uint8_t* key, - uint32_t length) { - int i, j, k, *m, a; - s->x = 0; - s->y = 0; - m = s->m; - for (i = 0; i < 256; i++) { - m[i] = i; - } - j = k = 0; - for (i = 0; i < 256; i++) { - a = m[i]; - j = (j + a + key[k]) & 0xFF; - m[i] = m[j]; - m[j] = a; - if (++k >= (int)length) { - k = 0; - } - } -} - -void CRYPT_ArcFourCrypt(CRYPT_rc4_context* s, - unsigned char* data, - uint32_t length) { - int i, x, y, *m, a, b; - x = s->x; - y = s->y; - m = s->m; - for (i = 0; i < (int)length; i++) { - x = (x + 1) & 0xFF; - a = m[x]; - y = (y + a) & 0xFF; - m[x] = b = m[y]; - m[y] = a; - data[i] ^= m[(a + b) & 0xFF]; - } - s->x = x; - s->y = y; -} - -void CRYPT_ArcFourCryptBlock(uint8_t* pData, - uint32_t size, - const uint8_t* key, - uint32_t keylen) { - CRYPT_rc4_context s; - CRYPT_ArcFourSetup(&s, key, keylen); - CRYPT_ArcFourCrypt(&s, pData, size); -} +#include #define GET_UINT32(n, b, i) \ { \ @@ -75,6 +23,13 @@ void CRYPT_ArcFourCryptBlock(uint8_t* pData, (((uint8_t*)b)[(i) + 3]) = (uint8_t)(((n) >> 24) & 0xFF); \ } +namespace { + +const uint8_t md5_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + void md5_process(CRYPT_md5_context* ctx, const uint8_t data[64]) { uint32_t A, B, C, D, X[16]; GET_UINT32(X[0], data, 0); @@ -181,6 +136,41 @@ void md5_process(CRYPT_md5_context* ctx, const uint8_t data[64]) { ctx->state[3] += D; } +} // namespace + +void CRYPT_ArcFourSetup(CRYPT_rc4_context* s, + const uint8_t* key, + uint32_t length) { + s->x = 0; + s->y = 0; + for (int i = 0; i < kRC4ContextPermutationLength; ++i) + s->m[i] = i; + + int j = 0; + for (int i = 0; i < kRC4ContextPermutationLength; ++i) { + j = (j + s->m[i] + (length ? key[i % length] : 0)) & 0xFF; + std::swap(s->m[i], s->m[j]); + } +} + +void CRYPT_ArcFourCrypt(CRYPT_rc4_context* s, uint8_t* data, uint32_t length) { + for (uint32_t i = 0; i < length; ++i) { + s->x = (s->x + 1) & 0xFF; + s->y = (s->y + s->m[s->x]) & 0xFF; + std::swap(s->m[s->x], s->m[s->y]); + data[i] ^= s->m[(s->m[s->x] + s->m[s->y]) & 0xFF]; + } +} + +void CRYPT_ArcFourCryptBlock(uint8_t* pData, + uint32_t size, + const uint8_t* key, + uint32_t keylen) { + CRYPT_rc4_context s; + CRYPT_ArcFourSetup(&s, key, keylen); + CRYPT_ArcFourCrypt(&s, pData, size); +} + void CRYPT_MD5Start(CRYPT_md5_context* ctx) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -204,7 +194,7 @@ void CRYPT_MD5Update(CRYPT_md5_context* ctx, ctx->total[0] &= 0xFFFFFFFF; ctx->total[1] += ctx->total[0] < length << 3; if (left && length >= fill) { - FXSYS_memcpy((void*)(ctx->buffer + left), (void*)input, fill); + memcpy(ctx->buffer + left, input, fill); md5_process(ctx, ctx->buffer); length -= fill; input += fill; @@ -216,15 +206,10 @@ void CRYPT_MD5Update(CRYPT_md5_context* ctx, input += 64; } if (length) { - FXSYS_memcpy((void*)(ctx->buffer + left), (void*)input, length); + memcpy(ctx->buffer + left, input, length); } } -const uint8_t md5_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - void CRYPT_MD5Finish(CRYPT_md5_context* ctx, uint8_t digest[16]) { uint32_t last, padn; uint8_t msglen[8]; @@ -248,7 +233,3 @@ void CRYPT_MD5Generate(const uint8_t* input, CRYPT_MD5Update(&ctx, input, length); CRYPT_MD5Finish(&ctx, digest); } - -#ifdef __cplusplus -}; -#endif diff --git a/core/fdrm/crypto/fx_crypt.h b/core/fdrm/crypto/fx_crypt.h index a498f4e19ba32350ec83c5d79a53a88d5e781ba1..4f6717fed8d5266aa72753f37305c07214b58a08 100644 --- a/core/fdrm/crypto/fx_crypt.h +++ b/core/fdrm/crypto/fx_crypt.h @@ -9,41 +9,44 @@ #include "core/fxcrt/fx_system.h" -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { +constexpr int32_t kRC4ContextPermutationLength = 256; +struct CRYPT_rc4_context { int32_t x; int32_t y; - int32_t m[256]; -} CRYPT_rc4_context; + int32_t m[kRC4ContextPermutationLength]; +}; + +#define MAX_NR 14 +#define MAX_NB 8 +struct CRYPT_aes_context { + void (*encrypt)(CRYPT_aes_context* ctx, unsigned int* block); + void (*decrypt)(CRYPT_aes_context* ctx, unsigned int* block); + int Nb; + int Nr; + unsigned int keysched[(MAX_NR + 1) * MAX_NB]; + unsigned int invkeysched[(MAX_NR + 1) * MAX_NB]; + unsigned int iv[MAX_NB]; +}; -typedef struct { +struct CRYPT_md5_context { uint32_t total[2]; uint32_t state[4]; uint8_t buffer[64]; -} CRYPT_md5_context; +}; -typedef struct { +struct CRYPT_sha1_context { unsigned int h[5]; unsigned char block[64]; int blkused; unsigned int lenhi; unsigned int lenlo; -} CRYPT_sha1_context; - -typedef struct { - uint32_t total[2]; - uint32_t state[8]; - uint8_t buffer[64]; -} CRYPT_sha256_context; +}; -typedef struct { +struct CRYPT_sha2_context { uint64_t total[2]; uint64_t state[8]; uint8_t buffer[128]; -} CRYPT_sha384_context; +}; void CRYPT_ArcFourCryptBlock(uint8_t* data, uint32_t size, @@ -56,17 +59,17 @@ void CRYPT_ArcFourCrypt(CRYPT_rc4_context* context, uint8_t* data, uint32_t size); -void CRYPT_AESSetKey(void* context, +void CRYPT_AESSetKey(CRYPT_aes_context* context, uint32_t blocklen, const uint8_t* key, uint32_t keylen, bool bEncrypt); -void CRYPT_AESSetIV(void* context, const uint8_t* iv); -void CRYPT_AESDecrypt(void* context, +void CRYPT_AESSetIV(CRYPT_aes_context* context, const uint8_t* iv); +void CRYPT_AESDecrypt(CRYPT_aes_context* context, uint8_t* dest, const uint8_t* src, uint32_t size); -void CRYPT_AESEncrypt(void* context, +void CRYPT_AESEncrypt(CRYPT_aes_context* context, uint8_t* dest, const uint8_t* src, uint32_t size); @@ -85,32 +88,31 @@ void CRYPT_SHA1Update(CRYPT_sha1_context* context, void CRYPT_SHA1Finish(CRYPT_sha1_context* context, uint8_t digest[20]); void CRYPT_SHA1Generate(const uint8_t* data, uint32_t size, uint8_t digest[20]); -void CRYPT_SHA256Start(CRYPT_sha256_context* context); -void CRYPT_SHA256Update(CRYPT_sha256_context* context, +void CRYPT_SHA256Start(CRYPT_sha2_context* context); +void CRYPT_SHA256Update(CRYPT_sha2_context* context, const uint8_t* data, uint32_t size); -void CRYPT_SHA256Finish(CRYPT_sha256_context* context, uint8_t digest[32]); +void CRYPT_SHA256Finish(CRYPT_sha2_context* context, uint8_t digest[32]); void CRYPT_SHA256Generate(const uint8_t* data, uint32_t size, uint8_t digest[32]); -void CRYPT_SHA384Start(CRYPT_sha384_context* context); -void CRYPT_SHA384Update(CRYPT_sha384_context* context, +void CRYPT_SHA384Start(CRYPT_sha2_context* context); +void CRYPT_SHA384Update(CRYPT_sha2_context* context, const uint8_t* data, uint32_t size); -void CRYPT_SHA384Finish(CRYPT_sha384_context* context, uint8_t digest[48]); +void CRYPT_SHA384Finish(CRYPT_sha2_context* context, uint8_t digest[48]); void CRYPT_SHA384Generate(const uint8_t* data, uint32_t size, uint8_t digest[48]); -void CRYPT_SHA512Start(void* context); -void CRYPT_SHA512Update(void* context, const uint8_t* data, uint32_t size); -void CRYPT_SHA512Finish(void* context, uint8_t digest[64]); +void CRYPT_SHA512Start(CRYPT_sha2_context* context); +void CRYPT_SHA512Update(CRYPT_sha2_context* context, + const uint8_t* data, + uint32_t size); +void CRYPT_SHA512Finish(CRYPT_sha2_context* context, uint8_t digest[64]); void CRYPT_SHA512Generate(const uint8_t* data, uint32_t size, uint8_t digest[64]); -#ifdef __cplusplus -}; -#endif #endif // CORE_FDRM_CRYPTO_FX_CRYPT_H_ diff --git a/core/fdrm/crypto/fx_crypt_aes.cpp b/core/fdrm/crypto/fx_crypt_aes.cpp index 8484b6f4a5062a6973c92005cf52c2326e785581..94d66d09566830b5716f09e354b7a01639e95de0 100644 --- a/core/fdrm/crypto/fx_crypt_aes.cpp +++ b/core/fdrm/crypto/fx_crypt_aes.cpp @@ -6,12 +6,6 @@ #include "core/fdrm/crypto/fx_crypt.h" -#ifdef __cplusplus -extern "C" { -#endif -#define MAX_NR 14 -#define MAX_NK 8 -#define MAX_NB 8 #define mulby2(x) (((x & 0x7F) << 1) ^ (x & 0x80 ? 0x1B : 0)) #define GET_32BIT_MSB_FIRST(cp) \ (((unsigned long)(unsigned char)(cp)[3]) | \ @@ -25,15 +19,10 @@ extern "C" { (cp)[1] = (value) >> 16; \ (cp)[0] = (value) >> 24; \ } while (0) -struct AESContext { - unsigned int keysched[(MAX_NR + 1) * MAX_NB]; - unsigned int invkeysched[(MAX_NR + 1) * MAX_NB]; - void (*encrypt)(AESContext* ctx, unsigned int* block); - void (*decrypt)(AESContext* ctx, unsigned int* block); - unsigned int iv[MAX_NB]; - int Nb, Nr; -}; -static const unsigned char Sbox[256] = { + +namespace { + +const unsigned char Sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, @@ -56,7 +45,7 @@ static const unsigned char Sbox[256] = { 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; -static const unsigned char Sboxinv[256] = { +const unsigned char Sboxinv[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, @@ -79,7 +68,7 @@ static const unsigned char Sboxinv[256] = { 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; -static const unsigned int E0[256] = { +const unsigned int E0[256] = { 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, @@ -124,7 +113,7 @@ static const unsigned int E0[256] = { 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, }; -static const unsigned int E1[256] = { +const unsigned int E1[256] = { 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, @@ -169,7 +158,7 @@ static const unsigned int E1[256] = { 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, }; -static const unsigned int E2[256] = { +const unsigned int E2[256] = { 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, @@ -214,7 +203,7 @@ static const unsigned int E2[256] = { 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, }; -static const unsigned int E3[256] = { +const unsigned int E3[256] = { 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, @@ -259,7 +248,7 @@ static const unsigned int E3[256] = { 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, }; -static const unsigned int D0[256] = { +const unsigned int D0[256] = { 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, @@ -304,7 +293,7 @@ static const unsigned int D0[256] = { 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, }; -static const unsigned int D1[256] = { +const unsigned int D1[256] = { 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, @@ -349,7 +338,7 @@ static const unsigned int D1[256] = { 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, }; -static const unsigned int D2[256] = { +const unsigned int D2[256] = { 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, @@ -394,7 +383,7 @@ static const unsigned int D2[256] = { 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, }; -static const unsigned int D3[256] = { +const unsigned int D3[256] = { 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, @@ -461,9 +450,10 @@ static const unsigned int D3[256] = { (Sbox[(block[(i + C1) % Nb] >> 16) & 0xFF] << 16) | \ (Sbox[(block[(i + C2) % Nb] >> 8) & 0xFF] << 8) | \ (Sbox[(block[(i + C3) % Nb]) & 0xFF])) -static void aes_encrypt_nb_4(AESContext* ctx, unsigned int* block) { + +void aes_encrypt_nb_4(CRYPT_aes_context* ctx, unsigned int* block) { int i; - static const int C1 = 1, C2 = 2, C3 = 3, Nb = 4; + const int C1 = 1, C2 = 2, C3 = 3, Nb = 4; unsigned int* keysched = ctx->keysched; unsigned int newstate[4]; for (i = 0; i < ctx->Nr - 1; i++) { @@ -488,9 +478,10 @@ static void aes_encrypt_nb_4(AESContext* ctx, unsigned int* block) { MOVEWORD(3); ADD_ROUND_KEY_4; } -static void aes_encrypt_nb_6(AESContext* ctx, unsigned int* block) { + +void aes_encrypt_nb_6(CRYPT_aes_context* ctx, unsigned int* block) { int i; - static const int C1 = 1, C2 = 2, C3 = 3, Nb = 6; + const int C1 = 1, C2 = 2, C3 = 3, Nb = 6; unsigned int* keysched = ctx->keysched; unsigned int newstate[6]; for (i = 0; i < ctx->Nr - 1; i++) { @@ -523,9 +514,10 @@ static void aes_encrypt_nb_6(AESContext* ctx, unsigned int* block) { MOVEWORD(5); ADD_ROUND_KEY_6; } -static void aes_encrypt_nb_8(AESContext* ctx, unsigned int* block) { + +void aes_encrypt_nb_8(CRYPT_aes_context* ctx, unsigned int* block) { int i; - static const int C1 = 1, C2 = 3, C3 = 4, Nb = 8; + const int C1 = 1, C2 = 3, C3 = 4, Nb = 8; unsigned int* keysched = ctx->keysched; unsigned int newstate[8]; for (i = 0; i < ctx->Nr - 1; i++) { @@ -578,9 +570,10 @@ static void aes_encrypt_nb_8(AESContext* ctx, unsigned int* block) { (Sboxinv[(block[(i + C1) % Nb] >> 16) & 0xFF] << 16) | \ (Sboxinv[(block[(i + C2) % Nb] >> 8) & 0xFF] << 8) | \ (Sboxinv[(block[(i + C3) % Nb]) & 0xFF])) -static void aes_decrypt_nb_4(AESContext* ctx, unsigned int* block) { + +void aes_decrypt_nb_4(CRYPT_aes_context* ctx, unsigned int* block) { int i; - static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3, Nb = 4; + const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3, Nb = 4; unsigned int* keysched = ctx->invkeysched; unsigned int newstate[4]; for (i = 0; i < ctx->Nr - 1; i++) { @@ -605,9 +598,10 @@ static void aes_decrypt_nb_4(AESContext* ctx, unsigned int* block) { MOVEWORD(3); ADD_ROUND_KEY_4; } -static void aes_decrypt_nb_6(AESContext* ctx, unsigned int* block) { + +void aes_decrypt_nb_6(CRYPT_aes_context* ctx, unsigned int* block) { int i; - static const int C1 = 6 - 1, C2 = 6 - 2, C3 = 6 - 3, Nb = 6; + const int C1 = 6 - 1, C2 = 6 - 2, C3 = 6 - 3, Nb = 6; unsigned int* keysched = ctx->invkeysched; unsigned int newstate[6]; for (i = 0; i < ctx->Nr - 1; i++) { @@ -640,9 +634,10 @@ static void aes_decrypt_nb_6(AESContext* ctx, unsigned int* block) { MOVEWORD(5); ADD_ROUND_KEY_6; } -static void aes_decrypt_nb_8(AESContext* ctx, unsigned int* block) { + +void aes_decrypt_nb_8(CRYPT_aes_context* ctx, unsigned int* block) { int i; - static const int C1 = 8 - 1, C2 = 8 - 3, C3 = 8 - 4, Nb = 8; + const int C1 = 8 - 1, C2 = 8 - 3, C3 = 8 - 4, Nb = 8; unsigned int* keysched = ctx->invkeysched; unsigned int newstate[8]; for (i = 0; i < ctx->Nr - 1; i++) { @@ -685,10 +680,10 @@ static void aes_decrypt_nb_8(AESContext* ctx, unsigned int* block) { } #undef MAKEWORD #undef LASTWORD -static void aes_setup(AESContext* ctx, - int blocklen, - const unsigned char* key, - int keylen) { +void aes_setup(CRYPT_aes_context* ctx, + int blocklen, + const unsigned char* key, + int keylen) { int i, j, Nk, rconst; ASSERT(blocklen == 16 || blocklen == 24 || blocklen == 32); ASSERT(keylen == 16 || keylen == 24 || keylen == 32); @@ -752,17 +747,17 @@ static void aes_setup(AESContext* ctx, } } } -static void aes_decrypt(AESContext* ctx, unsigned int* block) { +void aes_decrypt(CRYPT_aes_context* ctx, unsigned int* block) { ctx->decrypt(ctx, block); } -static void aes_decrypt_cbc(unsigned char* dest, - const unsigned char* src, - int len, - AESContext* ctx) { +void aes_decrypt_cbc(unsigned char* dest, + const unsigned char* src, + int len, + CRYPT_aes_context* ctx) { unsigned int iv[4], x[4], ct[4]; int i; ASSERT((len & 15) == 0); - FXSYS_memcpy(iv, ctx->iv, sizeof(iv)); + memcpy(iv, ctx->iv, sizeof(iv)); while (len > 0) { for (i = 0; i < 4; i++) { x[i] = ct[i] = GET_32BIT_MSB_FIRST(src + 4 * i); @@ -776,19 +771,21 @@ static void aes_decrypt_cbc(unsigned char* dest, src += 16; len -= 16; } - FXSYS_memcpy(ctx->iv, iv, sizeof(iv)); + memcpy(ctx->iv, iv, sizeof(iv)); } -static void aes_encrypt(AESContext* ctx, unsigned int* block) { + +void aes_encrypt(CRYPT_aes_context* ctx, unsigned int* block) { ctx->encrypt(ctx, block); } -static void aes_encrypt_cbc(unsigned char* dest, - const unsigned char* src, - int len, - AESContext* ctx) { + +void aes_encrypt_cbc(unsigned char* dest, + const unsigned char* src, + int len, + CRYPT_aes_context* ctx) { unsigned int iv[4]; int i; ASSERT((len & 15) == 0); - FXSYS_memcpy(iv, ctx->iv, sizeof(iv)); + memcpy(iv, ctx->iv, sizeof(iv)); while (len > 0) { for (i = 0; i < 4; i++) { iv[i] ^= GET_32BIT_MSB_FIRST(src + 4 * i); @@ -801,33 +798,34 @@ static void aes_encrypt_cbc(unsigned char* dest, src += 16; len -= 16; } - FXSYS_memcpy(ctx->iv, iv, sizeof(iv)); + memcpy(ctx->iv, iv, sizeof(iv)); } -void CRYPT_AESSetKey(void* context, + +} // namespace + +void CRYPT_AESSetKey(CRYPT_aes_context* context, uint32_t blocklen, const uint8_t* key, uint32_t keylen, bool bEncrypt) { - aes_setup((AESContext*)context, blocklen, key, keylen); + aes_setup(context, blocklen, key, keylen); } -void CRYPT_AESSetIV(void* context, const uint8_t* iv) { - int i; - for (i = 0; i < ((AESContext*)context)->Nb; i++) { - ((AESContext*)context)->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i); - } + +void CRYPT_AESSetIV(CRYPT_aes_context* context, const uint8_t* iv) { + for (int i = 0; i < context->Nb; i++) + context->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i); } -void CRYPT_AESDecrypt(void* context, + +void CRYPT_AESDecrypt(CRYPT_aes_context* context, uint8_t* dest, const uint8_t* src, uint32_t len) { - aes_decrypt_cbc(dest, src, len, (AESContext*)context); + aes_decrypt_cbc(dest, src, len, context); } -void CRYPT_AESEncrypt(void* context, + +void CRYPT_AESEncrypt(CRYPT_aes_context* context, uint8_t* dest, const uint8_t* src, uint32_t len) { - aes_encrypt_cbc(dest, src, len, (AESContext*)context); + aes_encrypt_cbc(dest, src, len, context); } -#ifdef __cplusplus -}; -#endif diff --git a/core/fdrm/crypto/fx_crypt_sha.cpp b/core/fdrm/crypto/fx_crypt_sha.cpp index 79ff503334f1b018f37abc83dedf16e12111639f..55b885db75875116d2a24a257e8a040912c638d1 100644 --- a/core/fdrm/crypto/fx_crypt_sha.cpp +++ b/core/fdrm/crypto/fx_crypt_sha.cpp @@ -6,18 +6,89 @@ #include "core/fdrm/crypto/fx_crypt.h" -#ifdef __cplusplus -extern "C" { -#endif #define rol(x, y) (((x) << (y)) | (((unsigned int)x) >> (32 - y))) -static void SHA_Core_Init(unsigned int h[5]) { + +#define SHA_GET_UINT32(n, b, i) \ + { \ + (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | \ + ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \ + } +#define SHA_PUT_UINT32(n, b, i) \ + { \ + (b)[(i)] = (uint8_t)((n) >> 24); \ + (b)[(i) + 1] = (uint8_t)((n) >> 16); \ + (b)[(i) + 2] = (uint8_t)((n) >> 8); \ + (b)[(i) + 3] = (uint8_t)((n)); \ + } + +#define SHA384_F0(x, y, z) ((x & y) | (z & (x | y))) +#define SHA384_F1(x, y, z) (z ^ (x & (y ^ z))) +#define SHA384_SHR(x, n) (x >> n) +#define SHA384_ROTR(x, n) (SHA384_SHR(x, n) | x << (64 - n)) +#define SHA384_S0(x) (SHA384_ROTR(x, 1) ^ SHA384_ROTR(x, 8) ^ SHA384_SHR(x, 7)) +#define SHA384_S1(x) \ + (SHA384_ROTR(x, 19) ^ SHA384_ROTR(x, 61) ^ SHA384_SHR(x, 6)) +#define SHA384_S2(x) \ + (SHA384_ROTR(x, 28) ^ SHA384_ROTR(x, 34) ^ SHA384_ROTR(x, 39)) +#define SHA384_S3(x) \ + (SHA384_ROTR(x, 14) ^ SHA384_ROTR(x, 18) ^ SHA384_ROTR(x, 41)) +#define SHA384_P(a, b, c, d, e, f, g, h, x, K) \ + { \ + temp1 = h + SHA384_S3(e) + SHA384_F1(e, f, g) + K + x; \ + temp2 = SHA384_S2(a) + SHA384_F0(a, b, c); \ + d += temp1; \ + h = temp1 + temp2; \ + } +#define SHA384_R(t) \ + (W[t] = SHA384_S1(W[t - 2]) + W[t - 7] + SHA384_S0(W[t - 15]) + W[t - 16]) + +#define GET_FX_64WORD(n, b, i) \ + { \ + (n) = ((uint64_t)(b)[(i)] << 56) | ((uint64_t)(b)[(i) + 1] << 48) | \ + ((uint64_t)(b)[(i) + 2] << 40) | ((uint64_t)(b)[(i) + 3] << 32) | \ + ((uint64_t)(b)[(i) + 4] << 24) | ((uint64_t)(b)[(i) + 5] << 16) | \ + ((uint64_t)(b)[(i) + 6] << 8) | ((uint64_t)(b)[(i) + 7]); \ + } +#define PUT_UINT64(n, b, i) \ + { \ + (b)[(i)] = (uint8_t)((n) >> 56); \ + (b)[(i) + 1] = (uint8_t)((n) >> 48); \ + (b)[(i) + 2] = (uint8_t)((n) >> 40); \ + (b)[(i) + 3] = (uint8_t)((n) >> 32); \ + (b)[(i) + 4] = (uint8_t)((n) >> 24); \ + (b)[(i) + 5] = (uint8_t)((n) >> 16); \ + (b)[(i) + 6] = (uint8_t)((n) >> 8); \ + (b)[(i) + 7] = (uint8_t)((n)); \ + } + +#define SHR(x, n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x, n) (SHR(x, n) | (x << (32 - n))) +#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) +#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define F0(x, y, z) ((x & y) | (z & (x | y))) +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define R(t) (W[t] = S1(W[t - 2]) + W[t - 7] + S0(W[t - 15]) + W[t - 16]) +#define PS(a, b, c, d, e, f, g, h, x, K) \ + { \ + temp1 = h + S3(e) + F1(e, f, g) + K + x; \ + temp2 = S2(a) + F0(a, b, c); \ + d += temp1; \ + h = temp1 + temp2; \ + } + +namespace { + +void SHA_Core_Init(unsigned int h[5]) { h[0] = 0x67452301; h[1] = 0xefcdab89; h[2] = 0x98badcfe; h[3] = 0x10325476; h[4] = 0xc3d2e1f0; } -static void SHATransform(unsigned int* digest, unsigned int* block) { + +void SHATransform(unsigned int* digest, unsigned int* block) { unsigned int w[80]; unsigned int a, b, c, d, e; int t; @@ -73,6 +144,223 @@ static void SHATransform(unsigned int* digest, unsigned int* block) { digest[4] += e; } +void sha256_process(CRYPT_sha2_context* ctx, const uint8_t data[64]) { + uint32_t W[64]; + SHA_GET_UINT32(W[0], data, 0); + SHA_GET_UINT32(W[1], data, 4); + SHA_GET_UINT32(W[2], data, 8); + SHA_GET_UINT32(W[3], data, 12); + SHA_GET_UINT32(W[4], data, 16); + SHA_GET_UINT32(W[5], data, 20); + SHA_GET_UINT32(W[6], data, 24); + SHA_GET_UINT32(W[7], data, 28); + SHA_GET_UINT32(W[8], data, 32); + SHA_GET_UINT32(W[9], data, 36); + SHA_GET_UINT32(W[10], data, 40); + SHA_GET_UINT32(W[11], data, 44); + SHA_GET_UINT32(W[12], data, 48); + SHA_GET_UINT32(W[13], data, 52); + SHA_GET_UINT32(W[14], data, 56); + SHA_GET_UINT32(W[15], data, 60); + + uint32_t temp1; + uint32_t temp2; + uint32_t A = ctx->state[0]; + uint32_t B = ctx->state[1]; + uint32_t C = ctx->state[2]; + uint32_t D = ctx->state[3]; + uint32_t E = ctx->state[4]; + uint32_t F = ctx->state[5]; + uint32_t G = ctx->state[6]; + uint32_t H = ctx->state[7]; + PS(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); + PS(H, A, B, C, D, E, F, G, W[1], 0x71374491); + PS(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); + PS(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); + PS(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); + PS(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); + PS(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); + PS(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); + PS(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); + PS(H, A, B, C, D, E, F, G, W[9], 0x12835B01); + PS(G, H, A, B, C, D, E, F, W[10], 0x243185BE); + PS(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); + PS(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); + PS(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); + PS(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); + PS(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); + PS(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); + PS(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); + PS(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); + PS(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); + PS(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); + PS(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); + PS(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); + PS(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); + PS(A, B, C, D, E, F, G, H, R(24), 0x983E5152); + PS(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); + PS(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); + PS(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); + PS(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); + PS(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); + PS(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); + PS(B, C, D, E, F, G, H, A, R(31), 0x14292967); + PS(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); + PS(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); + PS(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); + PS(F, G, H, A, B, C, D, E, R(35), 0x53380D13); + PS(E, F, G, H, A, B, C, D, R(36), 0x650A7354); + PS(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); + PS(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); + PS(B, C, D, E, F, G, H, A, R(39), 0x92722C85); + PS(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); + PS(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); + PS(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); + PS(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); + PS(E, F, G, H, A, B, C, D, R(44), 0xD192E819); + PS(D, E, F, G, H, A, B, C, R(45), 0xD6990624); + PS(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); + PS(B, C, D, E, F, G, H, A, R(47), 0x106AA070); + PS(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); + PS(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); + PS(G, H, A, B, C, D, E, F, R(50), 0x2748774C); + PS(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); + PS(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); + PS(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); + PS(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); + PS(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); + PS(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); + PS(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); + PS(G, H, A, B, C, D, E, F, R(58), 0x84C87814); + PS(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); + PS(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); + PS(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); + PS(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); + PS(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +const uint8_t sha256_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +const uint8_t sha384_padding[128] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +uint64_t const constants[] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +void sha384_process(CRYPT_sha2_context* ctx, const uint8_t data[128]) { + uint64_t temp1, temp2; + uint64_t A, B, C, D, E, F, G, H; + uint64_t W[80]; + GET_FX_64WORD(W[0], data, 0); + GET_FX_64WORD(W[1], data, 8); + GET_FX_64WORD(W[2], data, 16); + GET_FX_64WORD(W[3], data, 24); + GET_FX_64WORD(W[4], data, 32); + GET_FX_64WORD(W[5], data, 40); + GET_FX_64WORD(W[6], data, 48); + GET_FX_64WORD(W[7], data, 56); + GET_FX_64WORD(W[8], data, 64); + GET_FX_64WORD(W[9], data, 72); + GET_FX_64WORD(W[10], data, 80); + GET_FX_64WORD(W[11], data, 88); + GET_FX_64WORD(W[12], data, 96); + GET_FX_64WORD(W[13], data, 104); + GET_FX_64WORD(W[14], data, 112); + GET_FX_64WORD(W[15], data, 120); + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + for (int i = 0; i < 10; ++i) { + uint64_t temp[8]; + if (i < 2) { + temp[0] = W[i * 8]; + temp[1] = W[i * 8 + 1]; + temp[2] = W[i * 8 + 2]; + temp[3] = W[i * 8 + 3]; + temp[4] = W[i * 8 + 4]; + temp[5] = W[i * 8 + 5]; + temp[6] = W[i * 8 + 6]; + temp[7] = W[i * 8 + 7]; + } else { + temp[0] = SHA384_R(i * 8); + temp[1] = SHA384_R(i * 8 + 1); + temp[2] = SHA384_R(i * 8 + 2); + temp[3] = SHA384_R(i * 8 + 3); + temp[4] = SHA384_R(i * 8 + 4); + temp[5] = SHA384_R(i * 8 + 5); + temp[6] = SHA384_R(i * 8 + 6); + temp[7] = SHA384_R(i * 8 + 7); + } + SHA384_P(A, B, C, D, E, F, G, H, temp[0], constants[i * 8]); + SHA384_P(H, A, B, C, D, E, F, G, temp[1], constants[i * 8 + 1]); + SHA384_P(G, H, A, B, C, D, E, F, temp[2], constants[i * 8 + 2]); + SHA384_P(F, G, H, A, B, C, D, E, temp[3], constants[i * 8 + 3]); + SHA384_P(E, F, G, H, A, B, C, D, temp[4], constants[i * 8 + 4]); + SHA384_P(D, E, F, G, H, A, B, C, temp[5], constants[i * 8 + 5]); + SHA384_P(C, D, E, F, G, H, A, B, temp[6], constants[i * 8 + 6]); + SHA384_P(B, C, D, E, F, G, H, A, temp[7], constants[i * 8 + 7]); + } + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +} // namespace + void CRYPT_SHA1Start(CRYPT_sha1_context* s) { SHA_Core_Init(s->h); s->blkused = 0; @@ -90,11 +378,11 @@ void CRYPT_SHA1Update(CRYPT_sha1_context* s, s->lenlo += lenw; s->lenhi += (s->lenlo < lenw); if (s->blkused && s->blkused + len < 64) { - FXSYS_memcpy(s->block + s->blkused, q, len); + memcpy(s->block + s->blkused, q, len); s->blkused += len; } else { while (s->blkused + len >= 64) { - FXSYS_memcpy(s->block + s->blkused, q, 64 - s->blkused); + memcpy(s->block + s->blkused, q, 64 - s->blkused); q += 64 - s->blkused; len -= 64 - s->blkused; for (i = 0; i < 16; i++) { @@ -106,7 +394,7 @@ void CRYPT_SHA1Update(CRYPT_sha1_context* s, SHATransform(s->h, wordblock); s->blkused = 0; } - FXSYS_memcpy(s->block, q, len); + memcpy(s->block, q, len); s->blkused = len; } } @@ -123,7 +411,7 @@ void CRYPT_SHA1Finish(CRYPT_sha1_context* s, uint8_t digest[20]) { } lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3)); lenlo = (s->lenlo << 3); - FXSYS_memset(c, 0, pad); + memset(c, 0, pad); c[0] = 0x80; CRYPT_SHA1Update(s, c, pad); c[0] = (lenhi >> 24) & 0xFF; @@ -150,20 +438,7 @@ void CRYPT_SHA1Generate(const uint8_t* data, CRYPT_SHA1Update(&s, data, size); CRYPT_SHA1Finish(&s, digest); } -#define GET_UINT32(n, b, i) \ - { \ - (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | \ - ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \ - } -#define PUT_UINT32(n, b, i) \ - { \ - (b)[(i)] = (uint8_t)((n) >> 24); \ - (b)[(i) + 1] = (uint8_t)((n) >> 16); \ - (b)[(i) + 2] = (uint8_t)((n) >> 8); \ - (b)[(i) + 3] = (uint8_t)((n)); \ - } - -void CRYPT_SHA256Start(CRYPT_sha256_context* ctx) { +void CRYPT_SHA256Start(CRYPT_sha2_context* ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x6A09E667; @@ -176,124 +451,7 @@ void CRYPT_SHA256Start(CRYPT_sha256_context* ctx) { ctx->state[7] = 0x5BE0CD19; } -static void sha256_process(CRYPT_sha256_context* ctx, const uint8_t data[64]) { - uint32_t temp1, temp2, W[64]; - uint32_t A, B, C, D, E, F, G, H; - GET_UINT32(W[0], data, 0); - GET_UINT32(W[1], data, 4); - GET_UINT32(W[2], data, 8); - GET_UINT32(W[3], data, 12); - GET_UINT32(W[4], data, 16); - GET_UINT32(W[5], data, 20); - GET_UINT32(W[6], data, 24); - GET_UINT32(W[7], data, 28); - GET_UINT32(W[8], data, 32); - GET_UINT32(W[9], data, 36); - GET_UINT32(W[10], data, 40); - GET_UINT32(W[11], data, 44); - GET_UINT32(W[12], data, 48); - GET_UINT32(W[13], data, 52); - GET_UINT32(W[14], data, 56); - GET_UINT32(W[15], data, 60); -#define SHR(x, n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x, n) (SHR(x, n) | (x << (32 - n))) -#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) -#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) -#define F0(x, y, z) ((x & y) | (z & (x | y))) -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define R(t) (W[t] = S1(W[t - 2]) + W[t - 7] + S0(W[t - 15]) + W[t - 16]) -#define P(a, b, c, d, e, f, g, h, x, K) \ - { \ - temp1 = h + S3(e) + F1(e, f, g) + K + x; \ - temp2 = S2(a) + F0(a, b, c); \ - d += temp1; \ - h = temp1 + temp2; \ - } - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); - P(H, A, B, C, D, E, F, G, W[1], 0x71374491); - P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); - P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); - P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); - P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); - P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); - P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); - P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); - P(H, A, B, C, D, E, F, G, W[9], 0x12835B01); - P(G, H, A, B, C, D, E, F, W[10], 0x243185BE); - P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); - P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); - P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); - P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); - P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); - P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); - P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); - P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); - P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); - P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); - P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); - P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); - P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); - P(A, B, C, D, E, F, G, H, R(24), 0x983E5152); - P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); - P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); - P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); - P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); - P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); - P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); - P(B, C, D, E, F, G, H, A, R(31), 0x14292967); - P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); - P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); - P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); - P(F, G, H, A, B, C, D, E, R(35), 0x53380D13); - P(E, F, G, H, A, B, C, D, R(36), 0x650A7354); - P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); - P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); - P(B, C, D, E, F, G, H, A, R(39), 0x92722C85); - P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); - P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); - P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); - P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); - P(E, F, G, H, A, B, C, D, R(44), 0xD192E819); - P(D, E, F, G, H, A, B, C, R(45), 0xD6990624); - P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); - P(B, C, D, E, F, G, H, A, R(47), 0x106AA070); - P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); - P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); - P(G, H, A, B, C, D, E, F, R(50), 0x2748774C); - P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); - P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); - P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); - P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); - P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); - P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); - P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); - P(G, H, A, B, C, D, E, F, R(58), 0x84C87814); - P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); - P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); - P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); - P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); - P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} - -void CRYPT_SHA256Update(CRYPT_sha256_context* ctx, +void CRYPT_SHA256Update(CRYPT_sha2_context* ctx, const uint8_t* input, uint32_t length) { if (!length) @@ -303,11 +461,11 @@ void CRYPT_SHA256Update(CRYPT_sha256_context* ctx, uint32_t fill = 64 - left; ctx->total[0] += length; ctx->total[0] &= 0xFFFFFFFF; - if (ctx->total[0] < length) { + if (ctx->total[0] < length) ctx->total[1]++; - } + if (left && length >= fill) { - FXSYS_memcpy((void*)(ctx->buffer + left), (void*)input, fill); + memcpy(ctx->buffer + left, input, fill); sha256_process(ctx, ctx->buffer); length -= fill; input += fill; @@ -318,245 +476,68 @@ void CRYPT_SHA256Update(CRYPT_sha256_context* ctx, length -= 64; input += 64; } - if (length) { - FXSYS_memcpy((void*)(ctx->buffer + left), (void*)input, length); - } + if (length) + memcpy(ctx->buffer + left, input, length); } -static const uint8_t sha256_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -void CRYPT_SHA256Finish(CRYPT_sha256_context* ctx, uint8_t digest[32]) { - uint32_t last, padn; - uint32_t high, low; +void CRYPT_SHA256Finish(CRYPT_sha2_context* ctx, uint8_t digest[32]) { uint8_t msglen[8]; - high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); - low = (ctx->total[0] << 3); - PUT_UINT32(high, msglen, 0); - PUT_UINT32(low, msglen, 4); - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); + uint32_t high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); + uint32_t low = (ctx->total[0] << 3); + SHA_PUT_UINT32(high, msglen, 0); + SHA_PUT_UINT32(low, msglen, 4); + uint32_t last = ctx->total[0] & 0x3F; + uint32_t padn = (last < 56) ? (56 - last) : (120 - last); CRYPT_SHA256Update(ctx, sha256_padding, padn); CRYPT_SHA256Update(ctx, msglen, 8); - PUT_UINT32(ctx->state[0], digest, 0); - PUT_UINT32(ctx->state[1], digest, 4); - PUT_UINT32(ctx->state[2], digest, 8); - PUT_UINT32(ctx->state[3], digest, 12); - PUT_UINT32(ctx->state[4], digest, 16); - PUT_UINT32(ctx->state[5], digest, 20); - PUT_UINT32(ctx->state[6], digest, 24); - PUT_UINT32(ctx->state[7], digest, 28); + SHA_PUT_UINT32(ctx->state[0], digest, 0); + SHA_PUT_UINT32(ctx->state[1], digest, 4); + SHA_PUT_UINT32(ctx->state[2], digest, 8); + SHA_PUT_UINT32(ctx->state[3], digest, 12); + SHA_PUT_UINT32(ctx->state[4], digest, 16); + SHA_PUT_UINT32(ctx->state[5], digest, 20); + SHA_PUT_UINT32(ctx->state[6], digest, 24); + SHA_PUT_UINT32(ctx->state[7], digest, 28); } void CRYPT_SHA256Generate(const uint8_t* data, uint32_t size, uint8_t digest[32]) { - CRYPT_sha256_context ctx; + CRYPT_sha2_context ctx; CRYPT_SHA256Start(&ctx); CRYPT_SHA256Update(&ctx, data, size); CRYPT_SHA256Finish(&ctx, digest); } -uint64_t FX_ato64i(const FX_CHAR* str) { - ASSERT(str); - uint64_t ret = 0; - int len = (int)FXSYS_strlen(str); - len = len > 16 ? 16 : len; - for (int i = 0; i < len; ++i) { - if (i) { - ret <<= 4; - } - if (str[i] >= '0' && str[i] <= '9') { - ret |= (str[i] - '0') & 0xFF; - } else if (str[i] >= 'a' && str[i] <= 'f') { - ret |= (str[i] - 'a' + 10) & 0xFF; - } else if (str[i] >= 'A' && str[i] <= 'F') { - ret |= (str[i] - 'A' + 10) & 0xFF; - } else { - ASSERT(false); - } - } - return ret; -} - -void CRYPT_SHA384Start(CRYPT_sha384_context* ctx) { +void CRYPT_SHA384Start(CRYPT_sha2_context* ctx) { if (!ctx) return; - FXSYS_memset(ctx, 0, sizeof(CRYPT_sha384_context)); - ctx->state[0] = FX_ato64i("cbbb9d5dc1059ed8"); - ctx->state[1] = FX_ato64i("629a292a367cd507"); - ctx->state[2] = FX_ato64i("9159015a3070dd17"); - ctx->state[3] = FX_ato64i("152fecd8f70e5939"); - ctx->state[4] = FX_ato64i("67332667ffc00b31"); - ctx->state[5] = FX_ato64i("8eb44a8768581511"); - ctx->state[6] = FX_ato64i("db0c2e0d64f98fa7"); - ctx->state[7] = FX_ato64i("47b5481dbefa4fa4"); + memset(ctx, 0, sizeof(CRYPT_sha2_context)); + ctx->state[0] = 0xcbbb9d5dc1059ed8ULL; + ctx->state[1] = 0x629a292a367cd507ULL; + ctx->state[2] = 0x9159015a3070dd17ULL; + ctx->state[3] = 0x152fecd8f70e5939ULL; + ctx->state[4] = 0x67332667ffc00b31ULL; + ctx->state[5] = 0x8eb44a8768581511ULL; + ctx->state[6] = 0xdb0c2e0d64f98fa7ULL; + ctx->state[7] = 0x47b5481dbefa4fa4ULL; } -#define SHA384_F0(x, y, z) ((x & y) | (z & (x | y))) -#define SHA384_F1(x, y, z) (z ^ (x & (y ^ z))) -#define SHA384_SHR(x, n) (x >> n) -#define SHA384_ROTR(x, n) (SHA384_SHR(x, n) | x << (64 - n)) -#define SHA384_S0(x) (SHA384_ROTR(x, 1) ^ SHA384_ROTR(x, 8) ^ SHA384_SHR(x, 7)) -#define SHA384_S1(x) \ - (SHA384_ROTR(x, 19) ^ SHA384_ROTR(x, 61) ^ SHA384_SHR(x, 6)) -#define SHA384_S2(x) \ - (SHA384_ROTR(x, 28) ^ SHA384_ROTR(x, 34) ^ SHA384_ROTR(x, 39)) -#define SHA384_S3(x) \ - (SHA384_ROTR(x, 14) ^ SHA384_ROTR(x, 18) ^ SHA384_ROTR(x, 41)) -#define SHA384_P(a, b, c, d, e, f, g, h, x, K) \ - { \ - temp1 = h + SHA384_S3(e) + SHA384_F1(e, f, g) + K + x; \ - temp2 = SHA384_S2(a) + SHA384_F0(a, b, c); \ - d += temp1; \ - h = temp1 + temp2; \ - } -#define SHA384_R(t) \ - (W[t] = SHA384_S1(W[t - 2]) + W[t - 7] + SHA384_S0(W[t - 15]) + W[t - 16]) - -static const uint8_t sha384_padding[128] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const FX_CHAR* constants[] = { - "428a2f98d728ae22", "7137449123ef65cd", "b5c0fbcfec4d3b2f", - "e9b5dba58189dbbc", "3956c25bf348b538", "59f111f1b605d019", - "923f82a4af194f9b", "ab1c5ed5da6d8118", "d807aa98a3030242", - "12835b0145706fbe", "243185be4ee4b28c", "550c7dc3d5ffb4e2", - "72be5d74f27b896f", "80deb1fe3b1696b1", "9bdc06a725c71235", - "c19bf174cf692694", "e49b69c19ef14ad2", "efbe4786384f25e3", - "0fc19dc68b8cd5b5", "240ca1cc77ac9c65", "2de92c6f592b0275", - "4a7484aa6ea6e483", "5cb0a9dcbd41fbd4", "76f988da831153b5", - "983e5152ee66dfab", "a831c66d2db43210", "b00327c898fb213f", - "bf597fc7beef0ee4", "c6e00bf33da88fc2", "d5a79147930aa725", - "06ca6351e003826f", "142929670a0e6e70", "27b70a8546d22ffc", - "2e1b21385c26c926", "4d2c6dfc5ac42aed", "53380d139d95b3df", - "650a73548baf63de", "766a0abb3c77b2a8", "81c2c92e47edaee6", - "92722c851482353b", "a2bfe8a14cf10364", "a81a664bbc423001", - "c24b8b70d0f89791", "c76c51a30654be30", "d192e819d6ef5218", - "d69906245565a910", "f40e35855771202a", "106aa07032bbd1b8", - "19a4c116b8d2d0c8", "1e376c085141ab53", "2748774cdf8eeb99", - "34b0bcb5e19b48a8", "391c0cb3c5c95a63", "4ed8aa4ae3418acb", - "5b9cca4f7763e373", "682e6ff3d6b2b8a3", "748f82ee5defb2fc", - "78a5636f43172f60", "84c87814a1f0ab72", "8cc702081a6439ec", - "90befffa23631e28", "a4506cebde82bde9", "bef9a3f7b2c67915", - "c67178f2e372532b", "ca273eceea26619c", "d186b8c721c0c207", - "eada7dd6cde0eb1e", "f57d4f7fee6ed178", "06f067aa72176fba", - "0a637dc5a2c898a6", "113f9804bef90dae", "1b710b35131c471b", - "28db77f523047d84", "32caab7b40c72493", "3c9ebe0a15c9bebc", - "431d67c49c100d4c", "4cc5d4becb3e42b6", "597f299cfc657e2a", - "5fcb6fab3ad6faec", "6c44198c4a475817", -}; -#define GET_FX_64WORD(n, b, i) \ - { \ - (n) = ((uint64_t)(b)[(i)] << 56) | ((uint64_t)(b)[(i) + 1] << 48) | \ - ((uint64_t)(b)[(i) + 2] << 40) | ((uint64_t)(b)[(i) + 3] << 32) | \ - ((uint64_t)(b)[(i) + 4] << 24) | ((uint64_t)(b)[(i) + 5] << 16) | \ - ((uint64_t)(b)[(i) + 6] << 8) | ((uint64_t)(b)[(i) + 7]); \ - } -#define PUT_UINT64(n, b, i) \ - { \ - (b)[(i)] = (uint8_t)((n) >> 56); \ - (b)[(i) + 1] = (uint8_t)((n) >> 48); \ - (b)[(i) + 2] = (uint8_t)((n) >> 40); \ - (b)[(i) + 3] = (uint8_t)((n) >> 32); \ - (b)[(i) + 4] = (uint8_t)((n) >> 24); \ - (b)[(i) + 5] = (uint8_t)((n) >> 16); \ - (b)[(i) + 6] = (uint8_t)((n) >> 8); \ - (b)[(i) + 7] = (uint8_t)((n)); \ - } - -static void sha384_process(CRYPT_sha384_context* ctx, const uint8_t data[128]) { - uint64_t temp1, temp2; - uint64_t A, B, C, D, E, F, G, H; - uint64_t W[80]; - GET_FX_64WORD(W[0], data, 0); - GET_FX_64WORD(W[1], data, 8); - GET_FX_64WORD(W[2], data, 16); - GET_FX_64WORD(W[3], data, 24); - GET_FX_64WORD(W[4], data, 32); - GET_FX_64WORD(W[5], data, 40); - GET_FX_64WORD(W[6], data, 48); - GET_FX_64WORD(W[7], data, 56); - GET_FX_64WORD(W[8], data, 64); - GET_FX_64WORD(W[9], data, 72); - GET_FX_64WORD(W[10], data, 80); - GET_FX_64WORD(W[11], data, 88); - GET_FX_64WORD(W[12], data, 96); - GET_FX_64WORD(W[13], data, 104); - GET_FX_64WORD(W[14], data, 112); - GET_FX_64WORD(W[15], data, 120); - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - for (int i = 0; i < 10; ++i) { - uint64_t temp[8]; - if (i < 2) { - temp[0] = W[i * 8]; - temp[1] = W[i * 8 + 1]; - temp[2] = W[i * 8 + 2]; - temp[3] = W[i * 8 + 3]; - temp[4] = W[i * 8 + 4]; - temp[5] = W[i * 8 + 5]; - temp[6] = W[i * 8 + 6]; - temp[7] = W[i * 8 + 7]; - } else { - temp[0] = SHA384_R(i * 8); - temp[1] = SHA384_R(i * 8 + 1); - temp[2] = SHA384_R(i * 8 + 2); - temp[3] = SHA384_R(i * 8 + 3); - temp[4] = SHA384_R(i * 8 + 4); - temp[5] = SHA384_R(i * 8 + 5); - temp[6] = SHA384_R(i * 8 + 6); - temp[7] = SHA384_R(i * 8 + 7); - } - SHA384_P(A, B, C, D, E, F, G, H, temp[0], FX_ato64i(constants[i * 8])); - SHA384_P(H, A, B, C, D, E, F, G, temp[1], FX_ato64i(constants[i * 8 + 1])); - SHA384_P(G, H, A, B, C, D, E, F, temp[2], FX_ato64i(constants[i * 8 + 2])); - SHA384_P(F, G, H, A, B, C, D, E, temp[3], FX_ato64i(constants[i * 8 + 3])); - SHA384_P(E, F, G, H, A, B, C, D, temp[4], FX_ato64i(constants[i * 8 + 4])); - SHA384_P(D, E, F, G, H, A, B, C, temp[5], FX_ato64i(constants[i * 8 + 5])); - SHA384_P(C, D, E, F, G, H, A, B, temp[6], FX_ato64i(constants[i * 8 + 6])); - SHA384_P(B, C, D, E, F, G, H, A, temp[7], FX_ato64i(constants[i * 8 + 7])); - } - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} - -void CRYPT_SHA384Update(CRYPT_sha384_context* ctx, +void CRYPT_SHA384Update(CRYPT_sha2_context* ctx, const uint8_t* input, uint32_t length) { - uint32_t left, fill; - if (!length) { + if (!length) return; - } - left = (uint32_t)ctx->total[0] & 0x7F; - fill = 128 - left; + + uint32_t left = static_cast(ctx->total[0]) & 0x7F; + uint32_t fill = 128 - left; ctx->total[0] += length; - if (ctx->total[0] < length) { + if (ctx->total[0] < length) ctx->total[1]++; - } + if (left && length >= fill) { - FXSYS_memcpy((void*)(ctx->buffer + left), (void*)input, fill); + memcpy(ctx->buffer + left, input, fill); sha384_process(ctx, ctx->buffer); length -= fill; input += fill; @@ -567,15 +548,14 @@ void CRYPT_SHA384Update(CRYPT_sha384_context* ctx, length -= 128; input += 128; } - if (length) { - FXSYS_memcpy((void*)(ctx->buffer + left), (void*)input, length); - } + if (length) + memcpy(ctx->buffer + left, input, length); } -void CRYPT_SHA384Finish(CRYPT_sha384_context* ctx, uint8_t digest[48]) { +void CRYPT_SHA384Finish(CRYPT_sha2_context* ctx, uint8_t digest[48]) { uint32_t last, padn; uint8_t msglen[16]; - FXSYS_memset(msglen, 0, 16); + memset(msglen, 0, 16); uint64_t high, low; high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); @@ -596,38 +576,37 @@ void CRYPT_SHA384Finish(CRYPT_sha384_context* ctx, uint8_t digest[48]) { void CRYPT_SHA384Generate(const uint8_t* data, uint32_t size, uint8_t digest[64]) { - CRYPT_sha384_context context; + CRYPT_sha2_context context; CRYPT_SHA384Start(&context); CRYPT_SHA384Update(&context, data, size); CRYPT_SHA384Finish(&context, digest); } -void CRYPT_SHA512Start(void* context) { - if (!context) { +void CRYPT_SHA512Start(CRYPT_sha2_context* ctx) { + if (!ctx) return; - } - CRYPT_sha384_context* ctx = (CRYPT_sha384_context*)context; - FXSYS_memset(ctx, 0, sizeof(CRYPT_sha384_context)); - ctx->state[0] = FX_ato64i("6a09e667f3bcc908"); - ctx->state[1] = FX_ato64i("bb67ae8584caa73b"); - ctx->state[2] = FX_ato64i("3c6ef372fe94f82b"); - ctx->state[3] = FX_ato64i("a54ff53a5f1d36f1"); - ctx->state[4] = FX_ato64i("510e527fade682d1"); - ctx->state[5] = FX_ato64i("9b05688c2b3e6c1f"); - ctx->state[6] = FX_ato64i("1f83d9abfb41bd6b"); - ctx->state[7] = FX_ato64i("5be0cd19137e2179"); + + memset(ctx, 0, sizeof(CRYPT_sha2_context)); + ctx->state[0] = 0x6a09e667f3bcc908ULL; + ctx->state[1] = 0xbb67ae8584caa73bULL; + ctx->state[2] = 0x3c6ef372fe94f82bULL; + ctx->state[3] = 0xa54ff53a5f1d36f1ULL; + ctx->state[4] = 0x510e527fade682d1ULL; + ctx->state[5] = 0x9b05688c2b3e6c1fULL; + ctx->state[6] = 0x1f83d9abfb41bd6bULL; + ctx->state[7] = 0x5be0cd19137e2179ULL; } -void CRYPT_SHA512Update(void* context, const uint8_t* data, uint32_t size) { - CRYPT_sha384_context* ctx = (CRYPT_sha384_context*)context; +void CRYPT_SHA512Update(CRYPT_sha2_context* ctx, + const uint8_t* data, + uint32_t size) { CRYPT_SHA384Update(ctx, data, size); } -void CRYPT_SHA512Finish(void* context, uint8_t digest[64]) { - CRYPT_sha384_context* ctx = (CRYPT_sha384_context*)context; +void CRYPT_SHA512Finish(CRYPT_sha2_context* ctx, uint8_t digest[64]) { uint32_t last, padn; uint8_t msglen[16]; - FXSYS_memset(msglen, 0, 16); + memset(msglen, 0, 16); uint64_t high, low; high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); @@ -650,12 +629,8 @@ void CRYPT_SHA512Finish(void* context, uint8_t digest[64]) { void CRYPT_SHA512Generate(const uint8_t* data, uint32_t size, uint8_t digest[64]) { - CRYPT_sha384_context context; + CRYPT_sha2_context context; CRYPT_SHA512Start(&context); CRYPT_SHA512Update(&context, data, size); CRYPT_SHA512Finish(&context, digest); } - -#ifdef __cplusplus -}; -#endif diff --git a/core/fdrm/crypto/fx_crypt_unittest.cpp b/core/fdrm/crypto/fx_crypt_unittest.cpp index 4e3da6e1863877fece7a4cc29040c365d5ade344..e7f05b29392213369fe2fe5ce57d301a1ccb28e7 100644 --- a/core/fdrm/crypto/fx_crypt_unittest.cpp +++ b/core/fdrm/crypto/fx_crypt_unittest.cpp @@ -9,36 +9,33 @@ #include #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_memory.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" namespace { -std::string CRYPT_ToBase16(const uint8_t* digest) { - static char const zEncode[] = "0123456789abcdef"; - std::string ret; - ret.resize(32); - for (int i = 0, j = 0; i < 16; i++, j += 2) { - uint8_t a = digest[i]; - ret[j] = zEncode[(a >> 4) & 0xf]; - ret[j + 1] = zEncode[a & 0xf]; - } - return ret; +std::string CRYPT_MD5String(const char* str) { + return GenerateMD5Base16(reinterpret_cast(str), strlen(str)); } -std::string CRYPT_MD5String(const char* str) { - uint8_t digest[16]; - CRYPT_MD5Generate(reinterpret_cast(str), strlen(str), digest); - return CRYPT_ToBase16(digest); +void CheckArcFourContext(const CRYPT_rc4_context& context, + int32_t expected_x, + int32_t expected_y, + const uint8_t* expected_permutation) { + EXPECT_EQ(expected_x, context.x); + EXPECT_EQ(expected_y, context.y); + for (int32_t i = 0; i < kRC4ContextPermutationLength; ++i) + EXPECT_EQ(expected_permutation[i], context.m[i]) << i; } } // namespace -TEST(FXCRYPT, CRYPT_ToBase16) { +TEST(FXCRYPT, CryptToBase16) { uint8_t data[] = {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e}; - std::string actual = CRYPT_ToBase16(data); + std::string actual = CryptToBase16(data); std::string expected = "d41d8cd98f00b204e9800998ecf8427e"; EXPECT_EQ(expected, actual); @@ -194,7 +191,7 @@ TEST(FXCRYPT, ContextWithStringData) { uint8_t digest[16]; CRYPT_MD5Finish(&ctx, digest); - std::string actual = CRYPT_ToBase16(digest); + std::string actual = CryptToBase16(digest); std::string expected = "900150983cd24fb0d6963f7d28e17f72"; EXPECT_EQ(expected, actual); } @@ -227,3 +224,280 @@ TEST(FXCRYPT, Sha256TestB2) { for (size_t i = 0; i < 32; ++i) EXPECT_EQ(expected[i], actual[i]) << " at byte " << i; } + +TEST(FXCRYPT, CRYPT_ArcFourSetup) { + { + const uint8_t kNullPermutation[kRC4ContextPermutationLength] = { + 0, 35, 3, 43, 9, 11, 65, 229, 32, 36, 134, 98, 59, 34, + 173, 153, 214, 200, 64, 161, 191, 62, 6, 25, 56, 234, 49, 246, + 69, 133, 203, 194, 10, 42, 228, 198, 195, 245, 236, 91, 206, 23, + 235, 27, 138, 18, 143, 250, 244, 76, 123, 217, 132, 249, 72, 127, + 94, 151, 33, 60, 248, 85, 177, 210, 142, 83, 110, 140, 41, 135, + 196, 238, 156, 242, 141, 67, 5, 185, 131, 63, 137, 37, 172, 121, + 70, 144, 237, 130, 17, 44, 253, 166, 78, 201, 12, 119, 215, 7, + 126, 114, 97, 192, 53, 4, 254, 45, 102, 122, 230, 88, 193, 129, + 160, 124, 84, 108, 239, 189, 152, 120, 115, 207, 50, 176, 86, 157, + 164, 187, 71, 1, 15, 58, 29, 21, 46, 145, 247, 162, 95, 183, + 13, 226, 159, 175, 221, 100, 96, 202, 101, 178, 154, 47, 205, 106, + 148, 104, 93, 112, 26, 165, 128, 186, 146, 218, 66, 211, 171, 90, + 252, 19, 40, 99, 223, 174, 255, 51, 77, 227, 48, 220, 168, 118, + 224, 103, 75, 105, 125, 199, 73, 82, 57, 181, 81, 149, 68, 52, + 232, 22, 2, 216, 113, 30, 109, 163, 92, 61, 14, 8, 38, 225, + 79, 231, 170, 240, 20, 219, 204, 150, 180, 188, 116, 190, 241, 197, + 179, 87, 74, 147, 80, 54, 212, 16, 167, 222, 136, 213, 55, 182, + 139, 24, 209, 251, 208, 28, 111, 89, 158, 155, 243, 107, 233, 169, + 117, 184, 31, 39}; + CRYPT_rc4_context context; + CRYPT_ArcFourSetup(&context, nullptr, 0); + CheckArcFourContext(context, 0, 0, kNullPermutation); + } + { + const uint8_t kFoobarPermutation[kRC4ContextPermutationLength] = { + 102, 214, 39, 49, 17, 132, 244, 106, 114, 76, 183, 212, 116, 73, + 42, 103, 128, 246, 139, 199, 31, 234, 25, 109, 48, 19, 121, 4, + 20, 54, 134, 77, 163, 38, 61, 101, 145, 78, 215, 96, 92, 80, + 224, 168, 243, 210, 82, 252, 113, 56, 217, 62, 218, 129, 125, 33, + 99, 9, 153, 59, 43, 13, 206, 124, 131, 18, 213, 118, 173, 122, + 193, 172, 177, 105, 148, 207, 186, 5, 85, 32, 68, 220, 79, 84, + 169, 209, 150, 7, 133, 63, 147, 93, 26, 130, 60, 117, 250, 57, + 24, 247, 200, 127, 136, 66, 112, 107, 140, 154, 70, 170, 185, 138, + 248, 236, 88, 86, 44, 216, 241, 35, 100, 151, 156, 74, 119, 55, + 245, 46, 227, 208, 229, 16, 249, 149, 53, 157, 201, 75, 58, 28, + 142, 238, 182, 180, 179, 144, 12, 6, 176, 10, 90, 239, 104, 40, + 181, 194, 137, 69, 221, 205, 165, 188, 191, 87, 1, 91, 2, 171, + 232, 34, 162, 166, 160, 126, 225, 167, 123, 197, 223, 195, 22, 203, + 189, 237, 37, 27, 222, 175, 23, 143, 152, 192, 21, 231, 228, 141, + 30, 204, 158, 240, 120, 98, 89, 83, 135, 251, 81, 196, 161, 3, + 8, 230, 52, 219, 41, 242, 36, 97, 15, 155, 65, 187, 254, 64, + 159, 67, 211, 108, 178, 146, 202, 11, 164, 226, 184, 50, 190, 174, + 71, 233, 235, 198, 95, 51, 110, 255, 253, 72, 115, 0, 47, 94, + 29, 45, 14, 111}; + CRYPT_rc4_context context; + const uint8_t kFooBar[] = "foobar"; + CRYPT_ArcFourSetup(&context, kFooBar, FX_ArraySize(kFooBar) - 1); + CheckArcFourContext(context, 0, 0, kFoobarPermutation); + } +} + +TEST(FXCRYPT, CRYPT_ArcFourCrypt) { + const uint8_t kDataShort[] = "The Quick Fox Jumped Over The Lazy Brown Dog."; + const uint8_t kDataLong[] = + "The Quick Fox Jumped Over The Lazy Brown Dog.\n" + "1234567890123456789012345678901234567890123456789012345678901234567890\n" + "1234567890123456789012345678901234567890123456789012345678901234567890\n" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n" + "!@#$%^&*()[]{};':\",.<>/?\\|\r\t\n"; + { + CRYPT_rc4_context context; + CRYPT_ArcFourSetup(&context, nullptr, 0); + + uint8_t data_short[FX_ArraySize(kDataShort)]; + memcpy(data_short, kDataShort, FX_ArraySize(kDataShort)); + const uint8_t kExpectedEncryptedDataShort[] = { + 138, 112, 236, 97, 242, 66, 52, 89, 225, 38, 88, 8, + 47, 78, 216, 24, 170, 106, 26, 199, 208, 131, 157, 242, + 55, 11, 25, 90, 66, 182, 19, 255, 210, 181, 85, 69, + 31, 240, 206, 171, 97, 62, 202, 172, 30, 252}; + static_assert( + FX_ArraySize(kExpectedEncryptedDataShort) == FX_ArraySize(data_short), + "data_short mismatch"); + CRYPT_ArcFourCrypt(&context, data_short, FX_ArraySize(data_short)); + for (size_t i = 0; i < FX_ArraySize(data_short); ++i) + EXPECT_EQ(kExpectedEncryptedDataShort[i], data_short[i]) << i; + + const uint8_t kPermutation[kRC4ContextPermutationLength] = { + 0, 198, 10, 37, 253, 192, 171, 183, 99, 8, 144, 103, 208, 191, + 149, 9, 228, 243, 94, 150, 169, 151, 210, 206, 221, 235, 32, 186, + 212, 122, 72, 200, 236, 138, 244, 217, 158, 213, 139, 242, 17, 143, + 50, 132, 12, 160, 145, 250, 214, 76, 123, 35, 27, 249, 203, 127, + 64, 62, 33, 60, 248, 85, 177, 6, 142, 83, 110, 140, 41, 135, + 196, 238, 156, 91, 141, 67, 5, 185, 131, 63, 137, 43, 172, 121, + 70, 134, 237, 130, 25, 44, 153, 166, 78, 201, 42, 119, 215, 7, + 126, 114, 97, 11, 53, 4, 254, 45, 102, 133, 230, 88, 193, 129, + 18, 124, 84, 108, 239, 189, 152, 120, 115, 207, 234, 176, 86, 157, + 164, 187, 71, 1, 15, 58, 29, 21, 46, 23, 247, 162, 95, 229, + 13, 226, 159, 175, 56, 100, 96, 202, 101, 178, 154, 47, 205, 106, + 148, 104, 93, 112, 26, 165, 128, 246, 146, 218, 66, 211, 65, 90, + 252, 19, 40, 49, 223, 174, 255, 51, 77, 227, 48, 220, 168, 118, + 224, 98, 75, 105, 125, 199, 73, 82, 57, 181, 81, 173, 68, 52, + 232, 22, 2, 216, 113, 30, 109, 163, 92, 61, 14, 36, 38, 225, + 79, 231, 170, 240, 20, 219, 204, 161, 180, 188, 116, 190, 241, 197, + 179, 87, 74, 147, 80, 54, 69, 16, 167, 222, 136, 245, 55, 182, + 3, 24, 209, 251, 59, 28, 111, 89, 195, 155, 194, 107, 233, 34, + 117, 184, 31, 39}; + CheckArcFourContext(context, 46, 135, kPermutation); + } + { + CRYPT_rc4_context context; + CRYPT_ArcFourSetup(&context, nullptr, 0); + + uint8_t data_long[FX_ArraySize(kDataLong)]; + memcpy(data_long, kDataLong, FX_ArraySize(kDataLong)); + const uint8_t kExpectedEncryptedDataLong[] = { + 138, 112, 236, 97, 242, 66, 52, 89, 225, 38, 88, 8, 47, 78, + 216, 24, 170, 106, 26, 199, 208, 131, 157, 242, 55, 11, 25, 90, + 66, 182, 19, 255, 210, 181, 85, 69, 31, 240, 206, 171, 97, 62, + 202, 172, 30, 246, 19, 43, 184, 0, 173, 27, 140, 90, 167, 240, + 122, 125, 184, 49, 149, 71, 63, 104, 171, 144, 242, 106, 121, 124, + 209, 149, 61, 1, 66, 186, 252, 47, 51, 170, 253, 75, 95, 41, + 203, 28, 197, 174, 144, 209, 166, 98, 142, 125, 44, 5, 147, 42, + 73, 178, 119, 90, 253, 69, 103, 178, 15, 136, 51, 112, 39, 81, + 37, 111, 129, 232, 106, 159, 126, 142, 120, 124, 48, 140, 253, 12, + 223, 208, 106, 76, 60, 238, 5, 162, 100, 226, 251, 156, 169, 35, + 193, 10, 242, 210, 20, 96, 37, 84, 99, 183, 179, 203, 62, 122, + 54, 6, 51, 239, 142, 250, 238, 41, 223, 58, 48, 101, 29, 187, + 43, 235, 3, 5, 176, 33, 14, 171, 36, 26, 234, 207, 105, 79, + 69, 126, 82, 183, 105, 228, 31, 173, 8, 240, 99, 5, 147, 206, + 215, 140, 48, 190, 165, 50, 41, 232, 29, 105, 156, 64, 229, 165, + 12, 64, 163, 255, 146, 108, 212, 125, 142, 101, 13, 99, 174, 10, + 160, 68, 196, 120, 110, 201, 254, 158, 97, 215, 0, 207, 90, 23, + 208, 161, 105, 226, 164, 114, 80, 137, 58, 107, 109, 42, 110, 100, + 202, 170, 224, 89, 28, 5, 138, 19, 253, 105, 220, 105, 24, 187, + 109, 89, 205, 89, 202}; + static_assert( + FX_ArraySize(kExpectedEncryptedDataLong) == FX_ArraySize(data_long), + "data_long mismatch"); + static_assert(FX_ArraySize(data_long) > 256, "too short"); + CRYPT_ArcFourCrypt(&context, data_long, FX_ArraySize(data_long)); + for (size_t i = 0; i < FX_ArraySize(data_long); ++i) + EXPECT_EQ(kExpectedEncryptedDataLong[i], data_long[i]) << i; + + const uint8_t kPermutation[kRC4ContextPermutationLength] = { + 172, 59, 196, 72, 101, 21, 215, 210, 212, 52, 243, 73, 47, 213, + 211, 50, 228, 144, 66, 93, 169, 31, 237, 206, 221, 235, 222, 250, + 97, 87, 174, 164, 190, 111, 27, 217, 173, 189, 65, 11, 115, 171, + 104, 132, 12, 170, 205, 114, 7, 105, 37, 83, 78, 134, 236, 70, + 197, 122, 177, 202, 39, 195, 30, 3, 86, 127, 74, 106, 68, 91, + 110, 121, 208, 25, 56, 6, 28, 225, 163, 193, 166, 244, 119, 34, + 23, 88, 108, 123, 162, 159, 242, 61, 230, 227, 254, 14, 4, 156, + 161, 44, 58, 153, 33, 143, 129, 232, 182, 152, 76, 168, 238, 239, + 185, 219, 233, 16, 188, 45, 40, 35, 103, 99, 89, 157, 241, 245, + 192, 180, 248, 8, 85, 231, 146, 154, 252, 181, 107, 126, 98, 80, + 102, 165, 199, 94, 49, 255, 18, 204, 216, 77, 20, 187, 145, 125, + 1, 247, 79, 26, 207, 81, 117, 179, 186, 38, 175, 19, 139, 138, + 149, 54, 64, 109, 249, 135, 142, 118, 17, 13, 201, 184, 55, 224, + 209, 155, 113, 218, 82, 131, 178, 253, 140, 226, 43, 42, 24, 29, + 229, 200, 137, 240, 203, 167, 95, 148, 15, 176, 60, 75, 53, 41, + 150, 112, 160, 96, 22, 10, 234, 116, 130, 158, 214, 36, 9, 67, + 198, 194, 191, 100, 124, 147, 32, 183, 120, 246, 51, 141, 46, 251, + 92, 223, 133, 63, 0, 71, 48, 128, 220, 90, 62, 136, 2, 5, + 69, 57, 151, 84}; + CheckArcFourContext(context, 15, 222, kPermutation); + } + { + CRYPT_rc4_context context; + const uint8_t kFooBar[] = "foobar"; + CRYPT_ArcFourSetup(&context, kFooBar, FX_ArraySize(kFooBar) - 1); + + uint8_t data_short[FX_ArraySize(kDataShort)]; + memcpy(data_short, kDataShort, FX_ArraySize(kDataShort)); + const uint8_t kExpectedEncryptedDataShort[] = { + 59, 193, 117, 206, 167, 54, 218, 7, 229, 214, 188, 55, + 90, 205, 196, 25, 36, 114, 199, 218, 161, 107, 122, 119, + 106, 167, 44, 175, 240, 123, 192, 102, 174, 167, 105, 187, + 202, 70, 121, 81, 17, 30, 5, 138, 116, 166}; + static_assert( + FX_ArraySize(kExpectedEncryptedDataShort) == FX_ArraySize(data_short), + "data_short mismatch"); + CRYPT_ArcFourCrypt(&context, data_short, FX_ArraySize(data_short)); + for (size_t i = 0; i < FX_ArraySize(data_short); ++i) + EXPECT_EQ(kExpectedEncryptedDataShort[i], data_short[i]) << i; + + const uint8_t kPermutation[kRC4ContextPermutationLength] = { + 102, 41, 45, 82, 124, 141, 237, 38, 6, 64, 90, 140, 254, 96, + 220, 109, 99, 49, 27, 227, 205, 75, 191, 37, 17, 54, 83, 196, + 108, 79, 31, 190, 180, 0, 125, 194, 243, 156, 224, 246, 253, 193, + 42, 81, 117, 56, 181, 252, 113, 210, 217, 62, 218, 129, 61, 33, + 128, 9, 153, 59, 43, 13, 206, 48, 131, 18, 213, 118, 173, 122, + 80, 172, 177, 105, 148, 207, 186, 5, 85, 32, 68, 215, 19, 84, + 169, 209, 150, 7, 133, 63, 147, 93, 26, 130, 60, 145, 250, 57, + 24, 247, 200, 127, 136, 66, 112, 107, 212, 154, 70, 170, 185, 138, + 248, 236, 88, 86, 44, 216, 241, 35, 100, 151, 78, 74, 119, 55, + 245, 46, 199, 208, 229, 16, 249, 149, 53, 157, 201, 234, 58, 28, + 142, 238, 182, 163, 179, 144, 12, 114, 176, 10, 183, 239, 104, 40, + 73, 101, 137, 69, 221, 134, 165, 188, 25, 87, 1, 91, 2, 171, + 232, 34, 162, 166, 160, 126, 225, 167, 123, 197, 223, 195, 22, 203, + 189, 244, 103, 139, 222, 175, 23, 143, 152, 192, 21, 231, 228, 132, + 30, 204, 158, 240, 120, 98, 89, 121, 135, 251, 168, 4, 161, 3, + 8, 230, 52, 219, 214, 242, 36, 97, 15, 155, 65, 187, 116, 76, + 159, 67, 211, 20, 178, 146, 202, 11, 164, 226, 184, 50, 77, 174, + 71, 233, 235, 198, 95, 51, 110, 255, 92, 72, 115, 106, 47, 94, + 29, 39, 14, 111}; + CheckArcFourContext(context, 46, 39, kPermutation); + } + { + CRYPT_rc4_context context; + const uint8_t kFooBar[] = "foobar"; + CRYPT_ArcFourSetup(&context, kFooBar, FX_ArraySize(kFooBar) - 1); + + uint8_t data_long[FX_ArraySize(kDataLong)]; + memcpy(data_long, kDataLong, FX_ArraySize(kDataLong)); + const uint8_t kExpectedEncryptedDataLong[] = { + 59, 193, 117, 206, 167, 54, 218, 7, 229, 214, 188, 55, 90, 205, + 196, 25, 36, 114, 199, 218, 161, 107, 122, 119, 106, 167, 44, 175, + 240, 123, 192, 102, 174, 167, 105, 187, 202, 70, 121, 81, 17, 30, + 5, 138, 116, 172, 169, 50, 160, 116, 237, 117, 108, 241, 127, 61, + 83, 45, 77, 176, 0, 106, 191, 221, 132, 143, 219, 94, 2, 235, + 204, 166, 201, 139, 140, 163, 104, 115, 48, 37, 18, 114, 168, 49, + 235, 163, 179, 131, 182, 218, 120, 200, 9, 90, 60, 47, 55, 235, + 135, 37, 21, 170, 48, 112, 185, 169, 43, 233, 88, 134, 117, 126, + 248, 40, 176, 248, 30, 131, 108, 43, 139, 68, 232, 219, 7, 39, + 223, 45, 199, 243, 54, 171, 31, 37, 161, 24, 38, 251, 13, 144, + 106, 215, 179, 203, 5, 253, 25, 32, 25, 146, 109, 193, 143, 141, + 177, 226, 134, 222, 95, 79, 156, 202, 240, 34, 153, 145, 169, 150, + 231, 63, 113, 242, 156, 39, 136, 249, 108, 50, 181, 22, 22, 180, + 57, 76, 69, 62, 254, 47, 141, 249, 235, 90, 25, 34, 40, 194, + 66, 86, 110, 192, 235, 191, 205, 133, 91, 32, 104, 65, 43, 36, + 140, 36, 228, 156, 105, 251, 169, 168, 203, 189, 238, 221, 64, 200, + 68, 137, 153, 9, 183, 84, 153, 140, 239, 0, 15, 50, 126, 145, + 22, 110, 43, 56, 94, 127, 48, 96, 47, 172, 3, 31, 130, 249, + 243, 73, 206, 89, 9, 93, 156, 167, 205, 166, 75, 227, 36, 34, + 81, 124, 195, 246, 152}; + static_assert( + FX_ArraySize(kExpectedEncryptedDataLong) == FX_ArraySize(data_long), + "data_long mismatch"); + static_assert(FX_ArraySize(data_long) > 256, "too short"); + CRYPT_ArcFourCrypt(&context, data_long, FX_ArraySize(data_long)); + for (size_t i = 0; i < FX_ArraySize(data_long); ++i) + EXPECT_EQ(kExpectedEncryptedDataLong[i], data_long[i]) << i; + + const uint8_t kPermutation[kRC4ContextPermutationLength] = { + 188, 12, 81, 130, 228, 58, 124, 218, 72, 210, 50, 70, 166, 38, + 110, 111, 73, 49, 27, 227, 249, 21, 1, 226, 17, 54, 53, 16, + 108, 51, 31, 123, 221, 23, 125, 148, 5, 200, 208, 246, 253, 193, + 42, 45, 236, 56, 230, 194, 178, 213, 120, 116, 7, 164, 33, 107, + 189, 20, 133, 114, 173, 161, 59, 128, 3, 238, 65, 69, 144, 179, + 44, 35, 8, 163, 252, 195, 160, 197, 204, 28, 34, 129, 67, 89, + 22, 149, 199, 131, 182, 46, 250, 222, 155, 104, 10, 32, 139, 245, + 90, 41, 132, 224, 83, 242, 135, 75, 74, 61, 62, 141, 43, 127, + 255, 91, 170, 78, 157, 101, 243, 216, 254, 156, 229, 118, 174, 147, + 103, 76, 196, 145, 134, 94, 205, 146, 202, 98, 100, 106, 232, 177, + 187, 13, 80, 137, 151, 11, 82, 40, 167, 175, 25, 219, 168, 240, + 99, 55, 4, 19, 180, 2, 203, 18, 171, 154, 113, 117, 6, 185, + 172, 186, 237, 223, 233, 244, 217, 191, 190, 198, 97, 165, 220, 9, + 214, 150, 184, 143, 206, 24, 209, 207, 36, 142, 87, 15, 159, 71, + 84, 162, 169, 86, 48, 47, 140, 215, 241, 235, 158, 14, 26, 248, + 138, 119, 212, 39, 88, 121, 96, 109, 29, 66, 136, 102, 225, 92, + 201, 126, 122, 192, 60, 0, 64, 239, 183, 37, 57, 63, 234, 181, + 153, 52, 176, 112, 93, 79, 77, 115, 231, 30, 95, 251, 211, 68, + 105, 85, 247, 152}; + CheckArcFourContext(context, 15, 68, kPermutation); + } +} + +TEST(FXCRYPT, Sha512Test) { + const char* const input = + "This is a simple test. To see whether it is getting correct value."; + const uint8_t expected[64] = { + 0x86, 0xB5, 0x05, 0x63, 0xA2, 0x6F, 0xD6, 0xFA, 0xEB, 0x9B, 0xC3, + 0xBB, 0x9E, 0xB7, 0x03, 0x82, 0xB6, 0x50, 0x55, 0x6B, 0x90, 0x69, + 0xD0, 0xA7, 0x53, 0x0A, 0x34, 0xDD, 0xEA, 0x11, 0xCC, 0x91, 0x5C, + 0xC7, 0x93, 0xCA, 0xAE, 0x30, 0xD1, 0x96, 0xBE, 0xD0, 0x35, 0x21, + 0x4A, 0xC6, 0x42, 0x56, 0x0C, 0xA3, 0x00, 0x69, 0x44, 0x77, 0xCC, + 0x3E, 0xD4, 0xD6, 0x10, 0x31, 0xC6, 0xC0, 0x58, 0xCF}; + uint8_t actual[64]; + CRYPT_SHA512Generate(reinterpret_cast(input), strlen(input), + actual); + for (size_t i = 0; i < 64; ++i) + EXPECT_EQ(expected[i], actual[i]) << " at byte " << i; +} diff --git a/core/fpdfapi/cmaps/CNS1/CNS-EUC-H_0.cpp b/core/fpdfapi/cmaps/CNS1/CNS-EUC-H_0.cpp index efbe352257d00fba91ba6092ddb7dad06b7c8e43..9d0cee8c6e7040c28cd84cda2c6b598c67e97aed 100644 --- a/core/fpdfapi/cmaps/CNS1/CNS-EUC-H_0.cpp +++ b/core/fpdfapi/cmaps/CNS1/CNS-EUC-H_0.cpp @@ -62,111 +62,124 @@ const uint16_t g_FXCMAP_CNS_EUC_H_0[157 * 3] = { 0xFDA1, 0xFDCB, 0x1741, }; -const uint16_t g_FXCMAP_CNS_EUC_H_0_DWord[238 * 4] = { - 0x8EA1, 0xA1A1, 0xA1FE, 0x0063, 0x8EA1, 0xA2A1, 0xA2FE, 0x00C1, 0x8EA1, - 0xA3A1, 0xA3CE, 0x011F, 0x8EA1, 0xA4A1, 0xA4FE, 0x014D, 0x8EA1, 0xA5A1, - 0xA5EC, 0x01AB, 0x8EA1, 0xA5EE, 0xA5F0, 0x01F7, 0x8EA1, 0xA6A1, 0xA6BE, - 0x01FA, 0x8EA1, 0xA7A1, 0xA7A1, 0x0253, 0x8EA1, 0xA7A2, 0xA7A4, 0x0218, - 0x8EA1, 0xA7A5, 0xA7A5, 0x0254, 0x8EA1, 0xA7A6, 0xA7A6, 0x021B, 0x8EA1, - 0xA7A7, 0xA7A7, 0x025A, 0x8EA1, 0xA7A8, 0xA7A8, 0x021C, 0x8EA1, 0xA7A9, - 0xA7AC, 0x025B, 0x8EA1, 0xA7AD, 0xA7AF, 0x021D, 0x8EA1, 0xA7B0, 0xA7B0, - 0x025F, 0x8EA1, 0xA7B1, 0xA7B1, 0x176E, 0x8EA1, 0xA7B2, 0xA7B2, 0x0260, - 0x8EA1, 0xA7B3, 0xA7B3, 0x0262, 0x8EA1, 0xA7B4, 0xA7B4, 0x0220, 0x8EA1, - 0xA7B5, 0xA7B5, 0x0263, 0x8EA1, 0xA7B6, 0xA7B6, 0x176F, 0x8EA1, 0xA7B7, - 0xA7B7, 0x0221, 0x8EA1, 0xA7B8, 0xA7B9, 0x0264, 0x8EA1, 0xA7BA, 0xA7BA, - 0x0222, 0x8EA1, 0xA7BB, 0xA7BB, 0x1770, 0x8EA1, 0xA7BC, 0xA7BC, 0x0223, - 0x8EA1, 0xA7BD, 0xA7BD, 0x0266, 0x8EA1, 0xA7BE, 0xA7BE, 0x0279, 0x8EA1, - 0xA7BF, 0xA7BF, 0x1775, 0x8EA1, 0xA7C0, 0xA7C1, 0x027A, 0x8EA1, 0xA7C2, - 0xA7C2, 0x0224, 0x8EA1, 0xA7C3, 0xA7C6, 0x027C, 0x8EA1, 0xA7C7, 0xA7C7, - 0x0225, 0x8EA1, 0xA7C8, 0xA7CB, 0x0282, 0x8EA1, 0xA7CC, 0xA7CC, 0x1776, - 0x8EA1, 0xA7CD, 0xA7CD, 0x0286, 0x8EA1, 0xA7CE, 0xA7CE, 0x0226, 0x8EA1, - 0xA7CF, 0xA7D0, 0x0288, 0x8EA1, 0xA7D1, 0xA7D2, 0x028C, 0x8EA1, 0xA7D3, - 0xA7D5, 0x0227, 0x8EA1, 0xA7D6, 0xA7D8, 0x028E, 0x8EA1, 0xA7D9, 0xA7DA, - 0x022A, 0x8EA1, 0xA7DB, 0xA7DB, 0x1777, 0x8EA1, 0xA7DC, 0xA7DF, 0x02D0, - 0x8EA1, 0xA7E0, 0xA7E0, 0x02D5, 0x8EA1, 0xA7E1, 0xA7E1, 0x022C, 0x8EA1, - 0xA7E2, 0xA7E5, 0x02D6, 0x8EA1, 0xA7E6, 0xA7E6, 0x022D, 0x8EA1, 0xA7E7, - 0xA7ED, 0x02DA, 0x8EA1, 0xA7EE, 0xA7EE, 0x178A, 0x8EA1, 0xA7EF, 0xA7F2, - 0x02E1, 0x8EA1, 0xA7F3, 0xA7F3, 0x178C, 0x8EA1, 0xA7F4, 0xA7F8, 0x02E5, - 0x8EA1, 0xA7F9, 0xA7F9, 0x178D, 0x8EA1, 0xA7FA, 0xA7FD, 0x02EA, 0x8EA1, - 0xA7FE, 0xA7FE, 0x0356, 0x8EA1, 0xA8A1, 0xA8A6, 0x0357, 0x8EA1, 0xA8A7, - 0xA8A7, 0x035E, 0x8EA1, 0xA8A8, 0xA8A8, 0x0362, 0x8EA1, 0xA8A9, 0xA8AA, - 0x022E, 0x8EA1, 0xA8AB, 0xA8B2, 0x0363, 0x8EA1, 0xA8B3, 0xA8B3, 0x17B2, - 0x8EA1, 0xA8B4, 0xA8B6, 0x036B, 0x8EA1, 0xA8B7, 0xA8BA, 0x03F6, 0x8EA1, - 0xA8BB, 0xA8BB, 0x1812, 0x8EA1, 0xA8BC, 0xA8BE, 0x03FA, 0x8EA1, 0xA8BF, - 0xA8C3, 0x03FE, 0x8EA1, 0xA8C4, 0xA8CC, 0x0405, 0x8EA1, 0xA8CD, 0xA8CD, - 0x1813, 0x8EA1, 0xA8CE, 0xA8CE, 0x1818, 0x8EA1, 0xA8CF, 0xA8D2, 0x040F, - 0x8EA1, 0xA8D3, 0xA8D3, 0x1819, 0x8EA1, 0xA8D4, 0xA8D9, 0x0508, 0x8EA1, - 0xA8DA, 0xA8DA, 0x18E7, 0x8EA1, 0xA8DB, 0xA8E2, 0x050E, 0x8EA1, 0xA8E3, - 0xA8E3, 0x0230, 0x8EA1, 0xA8E4, 0xA8E4, 0x051B, 0x8EA1, 0xA8E5, 0xA8E7, - 0x0520, 0x8EA1, 0xA8E8, 0xA8EB, 0x0696, 0x8EA1, 0xA8EC, 0xA8EC, 0x0231, - 0x8EA1, 0xA8ED, 0xA8F0, 0x069F, 0x8EA1, 0xA8F1, 0xA8FB, 0x0826, 0x8EA1, - 0xA8FC, 0xA8FE, 0x09F5, 0x8EA1, 0xA9A1, 0xA9A1, 0x1E33, 0x8EA1, 0xA9A2, - 0xA9A2, 0x09F8, 0x8EA1, 0xA9A3, 0xA9A3, 0x1E34, 0x8EA1, 0xA9A4, 0xA9A5, - 0x09F9, 0x8EA1, 0xA9A6, 0xA9AB, 0x0BE1, 0x8EA1, 0xA9AC, 0xA9AE, 0x0DBB, - 0x8EA1, 0xA9AF, 0xA9AF, 0x2360, 0x8EA1, 0xA9B0, 0xA9B0, 0x2612, 0x8EA1, - 0xA9B1, 0xA9B3, 0x0F7B, 0x8EA1, 0xA9B4, 0xA9B5, 0x1100, 0x8EA1, 0xA9B6, - 0xA9B6, 0x1289, 0x8EA1, 0xA9B7, 0xA9B8, 0x13B2, 0x8EA1, 0xA9B9, 0xA9B9, - 0x2F0D, 0x8EA1, 0xC2A1, 0xC2C1, 0x0232, 0x8EA1, 0xC4A1, 0xC4FE, 0x0253, - 0x8EA1, 0xC5A1, 0xC5FE, 0x02B1, 0x8EA1, 0xC6A1, 0xC6FE, 0x030F, 0x8EA1, - 0xC7A1, 0xC7FE, 0x036D, 0x8EA1, 0xC8A1, 0xC8FE, 0x03CB, 0x8EA1, 0xC9A1, - 0xC9FE, 0x0429, 0x8EA1, 0xCAA1, 0xCAFE, 0x0487, 0x8EA1, 0xCBA1, 0xCBFE, - 0x04E5, 0x8EA1, 0xCCA1, 0xCCFE, 0x0543, 0x8EA1, 0xCDA1, 0xCDFE, 0x05A1, - 0x8EA1, 0xCEA1, 0xCEFE, 0x05FF, 0x8EA1, 0xCFA1, 0xCFFE, 0x065D, 0x8EA1, - 0xD0A1, 0xD0FE, 0x06BB, 0x8EA1, 0xD1A1, 0xD1FE, 0x0719, 0x8EA1, 0xD2A1, - 0xD2FE, 0x0777, 0x8EA1, 0xD3A1, 0xD3FE, 0x07D5, 0x8EA1, 0xD4A1, 0xD4FE, - 0x0833, 0x8EA1, 0xD5A1, 0xD5FE, 0x0891, 0x8EA1, 0xD6A1, 0xD6FE, 0x08EF, - 0x8EA1, 0xD7A1, 0xD7FE, 0x094D, 0x8EA1, 0xD8A1, 0xD8FE, 0x09AB, 0x8EA1, - 0xD9A1, 0xD9FE, 0x0A09, 0x8EA1, 0xDAA1, 0xDAFE, 0x0A67, 0x8EA1, 0xDBA1, - 0xDBFE, 0x0AC5, 0x8EA1, 0xDCA1, 0xDCFE, 0x0B23, 0x8EA1, 0xDDA1, 0xDDFE, - 0x0B81, 0x8EA1, 0xDEA1, 0xDEFE, 0x0BDF, 0x8EA1, 0xDFA1, 0xDFFE, 0x0C3D, - 0x8EA1, 0xE0A1, 0xE0FE, 0x0C9B, 0x8EA1, 0xE1A1, 0xE1FE, 0x0CF9, 0x8EA1, - 0xE2A1, 0xE2FE, 0x0D57, 0x8EA1, 0xE3A1, 0xE3FE, 0x0DB5, 0x8EA1, 0xE4A1, - 0xE4FE, 0x0E13, 0x8EA1, 0xE5A1, 0xE5FE, 0x0E71, 0x8EA1, 0xE6A1, 0xE6FE, - 0x0ECF, 0x8EA1, 0xE7A1, 0xE7FE, 0x0F2D, 0x8EA1, 0xE8A1, 0xE8FE, 0x0F8B, - 0x8EA1, 0xE9A1, 0xE9FE, 0x0FE9, 0x8EA1, 0xEAA1, 0xEAFE, 0x1047, 0x8EA1, - 0xEBA1, 0xEBFE, 0x10A5, 0x8EA1, 0xECA1, 0xECFE, 0x1103, 0x8EA1, 0xEDA1, - 0xEDFE, 0x1161, 0x8EA1, 0xEEA1, 0xEEFE, 0x11BF, 0x8EA1, 0xEFA1, 0xEFFE, - 0x121D, 0x8EA1, 0xF0A1, 0xF0FE, 0x127B, 0x8EA1, 0xF1A1, 0xF1FE, 0x12D9, - 0x8EA1, 0xF2A1, 0xF2FE, 0x1337, 0x8EA1, 0xF3A1, 0xF3FE, 0x1395, 0x8EA1, - 0xF4A1, 0xF4FE, 0x13F3, 0x8EA1, 0xF5A1, 0xF5FE, 0x1451, 0x8EA1, 0xF6A1, - 0xF6FE, 0x14AF, 0x8EA1, 0xF7A1, 0xF7FE, 0x150D, 0x8EA1, 0xF8A1, 0xF8FE, - 0x156B, 0x8EA1, 0xF9A1, 0xF9FE, 0x15C9, 0x8EA1, 0xFAA1, 0xFAFE, 0x1627, - 0x8EA1, 0xFBA1, 0xFBFE, 0x1685, 0x8EA1, 0xFCA1, 0xFCFE, 0x16E3, 0x8EA1, - 0xFDA1, 0xFDCB, 0x1741, 0x8EA2, 0xA1A1, 0xA1FE, 0x176C, 0x8EA2, 0xA2A1, - 0xA2FE, 0x17CA, 0x8EA2, 0xA3A1, 0xA3FE, 0x1828, 0x8EA2, 0xA4A1, 0xA4FE, - 0x1886, 0x8EA2, 0xA5A1, 0xA5FE, 0x18E4, 0x8EA2, 0xA6A1, 0xA6FE, 0x1942, - 0x8EA2, 0xA7A1, 0xA7FE, 0x19A0, 0x8EA2, 0xA8A1, 0xA8FE, 0x19FE, 0x8EA2, - 0xA9A1, 0xA9FE, 0x1A5C, 0x8EA2, 0xAAA1, 0xAAFE, 0x1ABA, 0x8EA2, 0xABA1, - 0xABFE, 0x1B18, 0x8EA2, 0xACA1, 0xACFE, 0x1B76, 0x8EA2, 0xADA1, 0xADFE, - 0x1BD4, 0x8EA2, 0xAEA1, 0xAEFE, 0x1C32, 0x8EA2, 0xAFA1, 0xAFFE, 0x1C90, - 0x8EA2, 0xB0A1, 0xB0FE, 0x1CEE, 0x8EA2, 0xB1A1, 0xB1FE, 0x1D4C, 0x8EA2, - 0xB2A1, 0xB2FE, 0x1DAA, 0x8EA2, 0xB3A1, 0xB3FE, 0x1E08, 0x8EA2, 0xB4A1, - 0xB4FE, 0x1E66, 0x8EA2, 0xB5A1, 0xB5FE, 0x1EC4, 0x8EA2, 0xB6A1, 0xB6FE, - 0x1F22, 0x8EA2, 0xB7A1, 0xB7FE, 0x1F80, 0x8EA2, 0xB8A1, 0xB8FE, 0x1FDE, - 0x8EA2, 0xB9A1, 0xB9FE, 0x203C, 0x8EA2, 0xBAA1, 0xBAFE, 0x209A, 0x8EA2, - 0xBBA1, 0xBBFE, 0x20F8, 0x8EA2, 0xBCA1, 0xBCFE, 0x2156, 0x8EA2, 0xBDA1, - 0xBDFE, 0x21B4, 0x8EA2, 0xBEA1, 0xBEFE, 0x2212, 0x8EA2, 0xBFA1, 0xBFFE, - 0x2270, 0x8EA2, 0xC0A1, 0xC0FE, 0x22CE, 0x8EA2, 0xC1A1, 0xC1FE, 0x232C, - 0x8EA2, 0xC2A1, 0xC2FE, 0x238A, 0x8EA2, 0xC3A1, 0xC3FE, 0x23E8, 0x8EA2, - 0xC4A1, 0xC4FE, 0x2446, 0x8EA2, 0xC5A1, 0xC5FE, 0x24A4, 0x8EA2, 0xC6A1, - 0xC6FE, 0x2502, 0x8EA2, 0xC7A1, 0xC7FE, 0x2560, 0x8EA2, 0xC8A1, 0xC8FE, - 0x25BE, 0x8EA2, 0xC9A1, 0xC9FE, 0x261C, 0x8EA2, 0xCAA1, 0xCAFE, 0x267A, - 0x8EA2, 0xCBA1, 0xCBFE, 0x26D8, 0x8EA2, 0xCCA1, 0xCCFE, 0x2736, 0x8EA2, - 0xCDA1, 0xCDFE, 0x2794, 0x8EA2, 0xCEA1, 0xCEFE, 0x27F2, 0x8EA2, 0xCFA1, - 0xCFFE, 0x2850, 0x8EA2, 0xD0A1, 0xD0FE, 0x28AE, 0x8EA2, 0xD1A1, 0xD1FE, - 0x290C, 0x8EA2, 0xD2A1, 0xD2FE, 0x296A, 0x8EA2, 0xD3A1, 0xD3FE, 0x29C8, - 0x8EA2, 0xD4A1, 0xD4FE, 0x2A26, 0x8EA2, 0xD5A1, 0xD5FE, 0x2A84, 0x8EA2, - 0xD6A1, 0xD6FE, 0x2AE2, 0x8EA2, 0xD7A1, 0xD7FE, 0x2B40, 0x8EA2, 0xD8A1, - 0xD8FE, 0x2B9E, 0x8EA2, 0xD9A1, 0xD9FE, 0x2BFC, 0x8EA2, 0xDAA1, 0xDAFE, - 0x2C5A, 0x8EA2, 0xDBA1, 0xDBFE, 0x2CB8, 0x8EA2, 0xDCA1, 0xDCFE, 0x2D16, - 0x8EA2, 0xDDA1, 0xDDFE, 0x2D74, 0x8EA2, 0xDEA1, 0xDEFE, 0x2DD2, 0x8EA2, - 0xDFA1, 0xDFFE, 0x2E30, 0x8EA2, 0xE0A1, 0xE0FE, 0x2E8E, 0x8EA2, 0xE1A1, - 0xE1FE, 0x2EEC, 0x8EA2, 0xE2A1, 0xE2FE, 0x2F4A, 0x8EA2, 0xE3A1, 0xE3FE, - 0x2FA8, 0x8EA2, 0xE4A1, 0xE4FE, 0x3006, 0x8EA2, 0xE5A1, 0xE5FE, 0x3064, - 0x8EA2, 0xE6A1, 0xE6FE, 0x30C2, 0x8EA2, 0xE7A1, 0xE7FE, 0x3120, 0x8EA2, - 0xE8A1, 0xE8FE, 0x317E, 0x8EA2, 0xE9A1, 0xE9FE, 0x31DC, 0x8EA2, 0xEAA1, - 0xEAFE, 0x323A, 0x8EA2, 0xEBA1, 0xEBFE, 0x3298, 0x8EA2, 0xECA1, 0xECFE, - 0x32F6, 0x8EA2, 0xEDA1, 0xEDFE, 0x3354, 0x8EA2, 0xEEA1, 0xEEFE, 0x33B2, - 0x8EA2, 0xEFA1, 0xEFFE, 0x3410, 0x8EA2, 0xF0A1, 0xF0FE, 0x346E, 0x8EA2, - 0xF1A1, 0xF1FE, 0x34CC, 0x8EA2, 0xF2A1, 0xF2C4, 0x352A, +const FXCMAP_DWordCIDMap g_FXCMAP_CNS_EUC_H_0_DWord[238] = { + {0x8EA1, 0xA1A1, 0xA1FE, 0x0063}, {0x8EA1, 0xA2A1, 0xA2FE, 0x00C1}, + {0x8EA1, 0xA3A1, 0xA3CE, 0x011F}, {0x8EA1, 0xA4A1, 0xA4FE, 0x014D}, + {0x8EA1, 0xA5A1, 0xA5EC, 0x01AB}, {0x8EA1, 0xA5EE, 0xA5F0, 0x01F7}, + {0x8EA1, 0xA6A1, 0xA6BE, 0x01FA}, {0x8EA1, 0xA7A1, 0xA7A1, 0x0253}, + {0x8EA1, 0xA7A2, 0xA7A4, 0x0218}, {0x8EA1, 0xA7A5, 0xA7A5, 0x0254}, + {0x8EA1, 0xA7A6, 0xA7A6, 0x021B}, {0x8EA1, 0xA7A7, 0xA7A7, 0x025A}, + {0x8EA1, 0xA7A8, 0xA7A8, 0x021C}, {0x8EA1, 0xA7A9, 0xA7AC, 0x025B}, + {0x8EA1, 0xA7AD, 0xA7AF, 0x021D}, {0x8EA1, 0xA7B0, 0xA7B0, 0x025F}, + {0x8EA1, 0xA7B1, 0xA7B1, 0x176E}, {0x8EA1, 0xA7B2, 0xA7B2, 0x0260}, + {0x8EA1, 0xA7B3, 0xA7B3, 0x0262}, {0x8EA1, 0xA7B4, 0xA7B4, 0x0220}, + {0x8EA1, 0xA7B5, 0xA7B5, 0x0263}, {0x8EA1, 0xA7B6, 0xA7B6, 0x176F}, + {0x8EA1, 0xA7B7, 0xA7B7, 0x0221}, {0x8EA1, 0xA7B8, 0xA7B9, 0x0264}, + {0x8EA1, 0xA7BA, 0xA7BA, 0x0222}, {0x8EA1, 0xA7BB, 0xA7BB, 0x1770}, + {0x8EA1, 0xA7BC, 0xA7BC, 0x0223}, {0x8EA1, 0xA7BD, 0xA7BD, 0x0266}, + {0x8EA1, 0xA7BE, 0xA7BE, 0x0279}, {0x8EA1, 0xA7BF, 0xA7BF, 0x1775}, + {0x8EA1, 0xA7C0, 0xA7C1, 0x027A}, {0x8EA1, 0xA7C2, 0xA7C2, 0x0224}, + {0x8EA1, 0xA7C3, 0xA7C6, 0x027C}, {0x8EA1, 0xA7C7, 0xA7C7, 0x0225}, + {0x8EA1, 0xA7C8, 0xA7CB, 0x0282}, {0x8EA1, 0xA7CC, 0xA7CC, 0x1776}, + {0x8EA1, 0xA7CD, 0xA7CD, 0x0286}, {0x8EA1, 0xA7CE, 0xA7CE, 0x0226}, + {0x8EA1, 0xA7CF, 0xA7D0, 0x0288}, {0x8EA1, 0xA7D1, 0xA7D2, 0x028C}, + {0x8EA1, 0xA7D3, 0xA7D5, 0x0227}, {0x8EA1, 0xA7D6, 0xA7D8, 0x028E}, + {0x8EA1, 0xA7D9, 0xA7DA, 0x022A}, {0x8EA1, 0xA7DB, 0xA7DB, 0x1777}, + {0x8EA1, 0xA7DC, 0xA7DF, 0x02D0}, {0x8EA1, 0xA7E0, 0xA7E0, 0x02D5}, + {0x8EA1, 0xA7E1, 0xA7E1, 0x022C}, {0x8EA1, 0xA7E2, 0xA7E5, 0x02D6}, + {0x8EA1, 0xA7E6, 0xA7E6, 0x022D}, {0x8EA1, 0xA7E7, 0xA7ED, 0x02DA}, + {0x8EA1, 0xA7EE, 0xA7EE, 0x178A}, {0x8EA1, 0xA7EF, 0xA7F2, 0x02E1}, + {0x8EA1, 0xA7F3, 0xA7F3, 0x178C}, {0x8EA1, 0xA7F4, 0xA7F8, 0x02E5}, + {0x8EA1, 0xA7F9, 0xA7F9, 0x178D}, {0x8EA1, 0xA7FA, 0xA7FD, 0x02EA}, + {0x8EA1, 0xA7FE, 0xA7FE, 0x0356}, {0x8EA1, 0xA8A1, 0xA8A6, 0x0357}, + {0x8EA1, 0xA8A7, 0xA8A7, 0x035E}, {0x8EA1, 0xA8A8, 0xA8A8, 0x0362}, + {0x8EA1, 0xA8A9, 0xA8AA, 0x022E}, {0x8EA1, 0xA8AB, 0xA8B2, 0x0363}, + {0x8EA1, 0xA8B3, 0xA8B3, 0x17B2}, {0x8EA1, 0xA8B4, 0xA8B6, 0x036B}, + {0x8EA1, 0xA8B7, 0xA8BA, 0x03F6}, {0x8EA1, 0xA8BB, 0xA8BB, 0x1812}, + {0x8EA1, 0xA8BC, 0xA8BE, 0x03FA}, {0x8EA1, 0xA8BF, 0xA8C3, 0x03FE}, + {0x8EA1, 0xA8C4, 0xA8CC, 0x0405}, {0x8EA1, 0xA8CD, 0xA8CD, 0x1813}, + {0x8EA1, 0xA8CE, 0xA8CE, 0x1818}, {0x8EA1, 0xA8CF, 0xA8D2, 0x040F}, + {0x8EA1, 0xA8D3, 0xA8D3, 0x1819}, {0x8EA1, 0xA8D4, 0xA8D9, 0x0508}, + {0x8EA1, 0xA8DA, 0xA8DA, 0x18E7}, {0x8EA1, 0xA8DB, 0xA8E2, 0x050E}, + {0x8EA1, 0xA8E3, 0xA8E3, 0x0230}, {0x8EA1, 0xA8E4, 0xA8E4, 0x051B}, + {0x8EA1, 0xA8E5, 0xA8E7, 0x0520}, {0x8EA1, 0xA8E8, 0xA8EB, 0x0696}, + {0x8EA1, 0xA8EC, 0xA8EC, 0x0231}, {0x8EA1, 0xA8ED, 0xA8F0, 0x069F}, + {0x8EA1, 0xA8F1, 0xA8FB, 0x0826}, {0x8EA1, 0xA8FC, 0xA8FE, 0x09F5}, + {0x8EA1, 0xA9A1, 0xA9A1, 0x1E33}, {0x8EA1, 0xA9A2, 0xA9A2, 0x09F8}, + {0x8EA1, 0xA9A3, 0xA9A3, 0x1E34}, {0x8EA1, 0xA9A4, 0xA9A5, 0x09F9}, + {0x8EA1, 0xA9A6, 0xA9AB, 0x0BE1}, {0x8EA1, 0xA9AC, 0xA9AE, 0x0DBB}, + {0x8EA1, 0xA9AF, 0xA9AF, 0x2360}, {0x8EA1, 0xA9B0, 0xA9B0, 0x2612}, + {0x8EA1, 0xA9B1, 0xA9B3, 0x0F7B}, {0x8EA1, 0xA9B4, 0xA9B5, 0x1100}, + {0x8EA1, 0xA9B6, 0xA9B6, 0x1289}, {0x8EA1, 0xA9B7, 0xA9B8, 0x13B2}, + {0x8EA1, 0xA9B9, 0xA9B9, 0x2F0D}, {0x8EA1, 0xC2A1, 0xC2C1, 0x0232}, + {0x8EA1, 0xC4A1, 0xC4FE, 0x0253}, {0x8EA1, 0xC5A1, 0xC5FE, 0x02B1}, + {0x8EA1, 0xC6A1, 0xC6FE, 0x030F}, {0x8EA1, 0xC7A1, 0xC7FE, 0x036D}, + {0x8EA1, 0xC8A1, 0xC8FE, 0x03CB}, {0x8EA1, 0xC9A1, 0xC9FE, 0x0429}, + {0x8EA1, 0xCAA1, 0xCAFE, 0x0487}, {0x8EA1, 0xCBA1, 0xCBFE, 0x04E5}, + {0x8EA1, 0xCCA1, 0xCCFE, 0x0543}, {0x8EA1, 0xCDA1, 0xCDFE, 0x05A1}, + {0x8EA1, 0xCEA1, 0xCEFE, 0x05FF}, {0x8EA1, 0xCFA1, 0xCFFE, 0x065D}, + {0x8EA1, 0xD0A1, 0xD0FE, 0x06BB}, {0x8EA1, 0xD1A1, 0xD1FE, 0x0719}, + {0x8EA1, 0xD2A1, 0xD2FE, 0x0777}, {0x8EA1, 0xD3A1, 0xD3FE, 0x07D5}, + {0x8EA1, 0xD4A1, 0xD4FE, 0x0833}, {0x8EA1, 0xD5A1, 0xD5FE, 0x0891}, + {0x8EA1, 0xD6A1, 0xD6FE, 0x08EF}, {0x8EA1, 0xD7A1, 0xD7FE, 0x094D}, + {0x8EA1, 0xD8A1, 0xD8FE, 0x09AB}, {0x8EA1, 0xD9A1, 0xD9FE, 0x0A09}, + {0x8EA1, 0xDAA1, 0xDAFE, 0x0A67}, {0x8EA1, 0xDBA1, 0xDBFE, 0x0AC5}, + {0x8EA1, 0xDCA1, 0xDCFE, 0x0B23}, {0x8EA1, 0xDDA1, 0xDDFE, 0x0B81}, + {0x8EA1, 0xDEA1, 0xDEFE, 0x0BDF}, {0x8EA1, 0xDFA1, 0xDFFE, 0x0C3D}, + {0x8EA1, 0xE0A1, 0xE0FE, 0x0C9B}, {0x8EA1, 0xE1A1, 0xE1FE, 0x0CF9}, + {0x8EA1, 0xE2A1, 0xE2FE, 0x0D57}, {0x8EA1, 0xE3A1, 0xE3FE, 0x0DB5}, + {0x8EA1, 0xE4A1, 0xE4FE, 0x0E13}, {0x8EA1, 0xE5A1, 0xE5FE, 0x0E71}, + {0x8EA1, 0xE6A1, 0xE6FE, 0x0ECF}, {0x8EA1, 0xE7A1, 0xE7FE, 0x0F2D}, + {0x8EA1, 0xE8A1, 0xE8FE, 0x0F8B}, {0x8EA1, 0xE9A1, 0xE9FE, 0x0FE9}, + {0x8EA1, 0xEAA1, 0xEAFE, 0x1047}, {0x8EA1, 0xEBA1, 0xEBFE, 0x10A5}, + {0x8EA1, 0xECA1, 0xECFE, 0x1103}, {0x8EA1, 0xEDA1, 0xEDFE, 0x1161}, + {0x8EA1, 0xEEA1, 0xEEFE, 0x11BF}, {0x8EA1, 0xEFA1, 0xEFFE, 0x121D}, + {0x8EA1, 0xF0A1, 0xF0FE, 0x127B}, {0x8EA1, 0xF1A1, 0xF1FE, 0x12D9}, + {0x8EA1, 0xF2A1, 0xF2FE, 0x1337}, {0x8EA1, 0xF3A1, 0xF3FE, 0x1395}, + {0x8EA1, 0xF4A1, 0xF4FE, 0x13F3}, {0x8EA1, 0xF5A1, 0xF5FE, 0x1451}, + {0x8EA1, 0xF6A1, 0xF6FE, 0x14AF}, {0x8EA1, 0xF7A1, 0xF7FE, 0x150D}, + {0x8EA1, 0xF8A1, 0xF8FE, 0x156B}, {0x8EA1, 0xF9A1, 0xF9FE, 0x15C9}, + {0x8EA1, 0xFAA1, 0xFAFE, 0x1627}, {0x8EA1, 0xFBA1, 0xFBFE, 0x1685}, + {0x8EA1, 0xFCA1, 0xFCFE, 0x16E3}, {0x8EA1, 0xFDA1, 0xFDCB, 0x1741}, + {0x8EA2, 0xA1A1, 0xA1FE, 0x176C}, {0x8EA2, 0xA2A1, 0xA2FE, 0x17CA}, + {0x8EA2, 0xA3A1, 0xA3FE, 0x1828}, {0x8EA2, 0xA4A1, 0xA4FE, 0x1886}, + {0x8EA2, 0xA5A1, 0xA5FE, 0x18E4}, {0x8EA2, 0xA6A1, 0xA6FE, 0x1942}, + {0x8EA2, 0xA7A1, 0xA7FE, 0x19A0}, {0x8EA2, 0xA8A1, 0xA8FE, 0x19FE}, + {0x8EA2, 0xA9A1, 0xA9FE, 0x1A5C}, {0x8EA2, 0xAAA1, 0xAAFE, 0x1ABA}, + {0x8EA2, 0xABA1, 0xABFE, 0x1B18}, {0x8EA2, 0xACA1, 0xACFE, 0x1B76}, + {0x8EA2, 0xADA1, 0xADFE, 0x1BD4}, {0x8EA2, 0xAEA1, 0xAEFE, 0x1C32}, + {0x8EA2, 0xAFA1, 0xAFFE, 0x1C90}, {0x8EA2, 0xB0A1, 0xB0FE, 0x1CEE}, + {0x8EA2, 0xB1A1, 0xB1FE, 0x1D4C}, {0x8EA2, 0xB2A1, 0xB2FE, 0x1DAA}, + {0x8EA2, 0xB3A1, 0xB3FE, 0x1E08}, {0x8EA2, 0xB4A1, 0xB4FE, 0x1E66}, + {0x8EA2, 0xB5A1, 0xB5FE, 0x1EC4}, {0x8EA2, 0xB6A1, 0xB6FE, 0x1F22}, + {0x8EA2, 0xB7A1, 0xB7FE, 0x1F80}, {0x8EA2, 0xB8A1, 0xB8FE, 0x1FDE}, + {0x8EA2, 0xB9A1, 0xB9FE, 0x203C}, {0x8EA2, 0xBAA1, 0xBAFE, 0x209A}, + {0x8EA2, 0xBBA1, 0xBBFE, 0x20F8}, {0x8EA2, 0xBCA1, 0xBCFE, 0x2156}, + {0x8EA2, 0xBDA1, 0xBDFE, 0x21B4}, {0x8EA2, 0xBEA1, 0xBEFE, 0x2212}, + {0x8EA2, 0xBFA1, 0xBFFE, 0x2270}, {0x8EA2, 0xC0A1, 0xC0FE, 0x22CE}, + {0x8EA2, 0xC1A1, 0xC1FE, 0x232C}, {0x8EA2, 0xC2A1, 0xC2FE, 0x238A}, + {0x8EA2, 0xC3A1, 0xC3FE, 0x23E8}, {0x8EA2, 0xC4A1, 0xC4FE, 0x2446}, + {0x8EA2, 0xC5A1, 0xC5FE, 0x24A4}, {0x8EA2, 0xC6A1, 0xC6FE, 0x2502}, + {0x8EA2, 0xC7A1, 0xC7FE, 0x2560}, {0x8EA2, 0xC8A1, 0xC8FE, 0x25BE}, + {0x8EA2, 0xC9A1, 0xC9FE, 0x261C}, {0x8EA2, 0xCAA1, 0xCAFE, 0x267A}, + {0x8EA2, 0xCBA1, 0xCBFE, 0x26D8}, {0x8EA2, 0xCCA1, 0xCCFE, 0x2736}, + {0x8EA2, 0xCDA1, 0xCDFE, 0x2794}, {0x8EA2, 0xCEA1, 0xCEFE, 0x27F2}, + {0x8EA2, 0xCFA1, 0xCFFE, 0x2850}, {0x8EA2, 0xD0A1, 0xD0FE, 0x28AE}, + {0x8EA2, 0xD1A1, 0xD1FE, 0x290C}, {0x8EA2, 0xD2A1, 0xD2FE, 0x296A}, + {0x8EA2, 0xD3A1, 0xD3FE, 0x29C8}, {0x8EA2, 0xD4A1, 0xD4FE, 0x2A26}, + {0x8EA2, 0xD5A1, 0xD5FE, 0x2A84}, {0x8EA2, 0xD6A1, 0xD6FE, 0x2AE2}, + {0x8EA2, 0xD7A1, 0xD7FE, 0x2B40}, {0x8EA2, 0xD8A1, 0xD8FE, 0x2B9E}, + {0x8EA2, 0xD9A1, 0xD9FE, 0x2BFC}, {0x8EA2, 0xDAA1, 0xDAFE, 0x2C5A}, + {0x8EA2, 0xDBA1, 0xDBFE, 0x2CB8}, {0x8EA2, 0xDCA1, 0xDCFE, 0x2D16}, + {0x8EA2, 0xDDA1, 0xDDFE, 0x2D74}, {0x8EA2, 0xDEA1, 0xDEFE, 0x2DD2}, + {0x8EA2, 0xDFA1, 0xDFFE, 0x2E30}, {0x8EA2, 0xE0A1, 0xE0FE, 0x2E8E}, + {0x8EA2, 0xE1A1, 0xE1FE, 0x2EEC}, {0x8EA2, 0xE2A1, 0xE2FE, 0x2F4A}, + {0x8EA2, 0xE3A1, 0xE3FE, 0x2FA8}, {0x8EA2, 0xE4A1, 0xE4FE, 0x3006}, + {0x8EA2, 0xE5A1, 0xE5FE, 0x3064}, {0x8EA2, 0xE6A1, 0xE6FE, 0x30C2}, + {0x8EA2, 0xE7A1, 0xE7FE, 0x3120}, {0x8EA2, 0xE8A1, 0xE8FE, 0x317E}, + {0x8EA2, 0xE9A1, 0xE9FE, 0x31DC}, {0x8EA2, 0xEAA1, 0xEAFE, 0x323A}, + {0x8EA2, 0xEBA1, 0xEBFE, 0x3298}, {0x8EA2, 0xECA1, 0xECFE, 0x32F6}, + {0x8EA2, 0xEDA1, 0xEDFE, 0x3354}, {0x8EA2, 0xEEA1, 0xEEFE, 0x33B2}, + {0x8EA2, 0xEFA1, 0xEFFE, 0x3410}, {0x8EA2, 0xF0A1, 0xF0FE, 0x346E}, + {0x8EA2, 0xF1A1, 0xF1FE, 0x34CC}, {0x8EA2, 0xF2A1, 0xF2C4, 0x352A}, }; diff --git a/core/fpdfapi/cmaps/CNS1/CNS-EUC-V_0.cpp b/core/fpdfapi/cmaps/CNS1/CNS-EUC-V_0.cpp index 2090969e79216abaed80040ae9dee343bcfffbc1..16981068ada01a2ae0cf948db2d06819506c3333 100644 --- a/core/fpdfapi/cmaps/CNS1/CNS-EUC-V_0.cpp +++ b/core/fpdfapi/cmaps/CNS1/CNS-EUC-V_0.cpp @@ -69,121 +69,136 @@ const uint16_t g_FXCMAP_CNS_EUC_V_0[180 * 3] = { 0xFBA1, 0xFBFE, 0x1685, 0xFCA1, 0xFCFE, 0x16E3, 0xFDA1, 0xFDCB, 0x1741, }; -const uint16_t g_FXCMAP_CNS_EUC_V_0_DWord[261 * 4] = { - 0x8EA1, 0xA1A1, 0xA1AB, 0x0063, 0x8EA1, 0xA1AC, 0xA1AC, 0x354E, 0x8EA1, - 0xA1AD, 0xA1BA, 0x006F, 0x8EA1, 0xA1BB, 0xA1BB, 0x007C, 0x8EA1, 0xA1BC, - 0xA1BC, 0x007E, 0x8EA1, 0xA1BD, 0xA1BD, 0x007E, 0x8EA1, 0xA1BE, 0xA1BF, - 0x0082, 0x8EA1, 0xA1C0, 0xA1C1, 0x0082, 0x8EA1, 0xA1C2, 0xA1C3, 0x0086, - 0x8EA1, 0xA1C4, 0xA1C5, 0x0086, 0x8EA1, 0xA1C6, 0xA1C7, 0x008A, 0x8EA1, - 0xA1C8, 0xA1C9, 0x008A, 0x8EA1, 0xA1CA, 0xA1CB, 0x008E, 0x8EA1, 0xA1CC, - 0xA1CD, 0x008E, 0x8EA1, 0xA1CE, 0xA1CF, 0x0092, 0x8EA1, 0xA1D0, 0xA1D1, - 0x0092, 0x8EA1, 0xA1D2, 0xA1D3, 0x0096, 0x8EA1, 0xA1D4, 0xA1D5, 0x0096, - 0x8EA1, 0xA1D6, 0xA1D7, 0x009A, 0x8EA1, 0xA1D8, 0xA1D9, 0x009A, 0x8EA1, - 0xA1DA, 0xA1DB, 0x009E, 0x8EA1, 0xA1DC, 0xA1FE, 0x009E, 0x8EA1, 0xA2A1, - 0xA2C3, 0x00C1, 0x8EA1, 0xA2C4, 0xA2C4, 0x354F, 0x8EA1, 0xA2C5, 0xA2FE, - 0x00E5, 0x8EA1, 0xA3A1, 0xA3CE, 0x011F, 0x8EA1, 0xA4A1, 0xA4FE, 0x014D, - 0x8EA1, 0xA5A1, 0xA5EC, 0x01AB, 0x8EA1, 0xA5EE, 0xA5F0, 0x01F7, 0x8EA1, - 0xA6A1, 0xA6BE, 0x01FA, 0x8EA1, 0xA7A1, 0xA7A1, 0x0253, 0x8EA1, 0xA7A2, - 0xA7A4, 0x0218, 0x8EA1, 0xA7A5, 0xA7A5, 0x0254, 0x8EA1, 0xA7A6, 0xA7A6, - 0x021B, 0x8EA1, 0xA7A7, 0xA7A7, 0x025A, 0x8EA1, 0xA7A8, 0xA7A8, 0x021C, - 0x8EA1, 0xA7A9, 0xA7AC, 0x025B, 0x8EA1, 0xA7AD, 0xA7AF, 0x021D, 0x8EA1, - 0xA7B0, 0xA7B0, 0x025F, 0x8EA1, 0xA7B1, 0xA7B1, 0x176E, 0x8EA1, 0xA7B2, - 0xA7B2, 0x0260, 0x8EA1, 0xA7B3, 0xA7B3, 0x0262, 0x8EA1, 0xA7B4, 0xA7B4, - 0x0220, 0x8EA1, 0xA7B5, 0xA7B5, 0x0263, 0x8EA1, 0xA7B6, 0xA7B6, 0x176F, - 0x8EA1, 0xA7B7, 0xA7B7, 0x0221, 0x8EA1, 0xA7B8, 0xA7B9, 0x0264, 0x8EA1, - 0xA7BA, 0xA7BA, 0x0222, 0x8EA1, 0xA7BB, 0xA7BB, 0x1770, 0x8EA1, 0xA7BC, - 0xA7BC, 0x0223, 0x8EA1, 0xA7BD, 0xA7BD, 0x0266, 0x8EA1, 0xA7BE, 0xA7BE, - 0x0279, 0x8EA1, 0xA7BF, 0xA7BF, 0x1775, 0x8EA1, 0xA7C0, 0xA7C1, 0x027A, - 0x8EA1, 0xA7C2, 0xA7C2, 0x0224, 0x8EA1, 0xA7C3, 0xA7C6, 0x027C, 0x8EA1, - 0xA7C7, 0xA7C7, 0x0225, 0x8EA1, 0xA7C8, 0xA7CB, 0x0282, 0x8EA1, 0xA7CC, - 0xA7CC, 0x1776, 0x8EA1, 0xA7CD, 0xA7CD, 0x0286, 0x8EA1, 0xA7CE, 0xA7CE, - 0x0226, 0x8EA1, 0xA7CF, 0xA7D0, 0x0288, 0x8EA1, 0xA7D1, 0xA7D2, 0x028C, - 0x8EA1, 0xA7D3, 0xA7D5, 0x0227, 0x8EA1, 0xA7D6, 0xA7D8, 0x028E, 0x8EA1, - 0xA7D9, 0xA7DA, 0x022A, 0x8EA1, 0xA7DB, 0xA7DB, 0x1777, 0x8EA1, 0xA7DC, - 0xA7DF, 0x02D0, 0x8EA1, 0xA7E0, 0xA7E0, 0x02D5, 0x8EA1, 0xA7E1, 0xA7E1, - 0x022C, 0x8EA1, 0xA7E2, 0xA7E5, 0x02D6, 0x8EA1, 0xA7E6, 0xA7E6, 0x022D, - 0x8EA1, 0xA7E7, 0xA7ED, 0x02DA, 0x8EA1, 0xA7EE, 0xA7EE, 0x178A, 0x8EA1, - 0xA7EF, 0xA7F2, 0x02E1, 0x8EA1, 0xA7F3, 0xA7F3, 0x178C, 0x8EA1, 0xA7F4, - 0xA7F8, 0x02E5, 0x8EA1, 0xA7F9, 0xA7F9, 0x178D, 0x8EA1, 0xA7FA, 0xA7FD, - 0x02EA, 0x8EA1, 0xA7FE, 0xA7FE, 0x0356, 0x8EA1, 0xA8A1, 0xA8A6, 0x0357, - 0x8EA1, 0xA8A7, 0xA8A7, 0x035E, 0x8EA1, 0xA8A8, 0xA8A8, 0x0362, 0x8EA1, - 0xA8A9, 0xA8AA, 0x022E, 0x8EA1, 0xA8AB, 0xA8B2, 0x0363, 0x8EA1, 0xA8B3, - 0xA8B3, 0x17B2, 0x8EA1, 0xA8B4, 0xA8B6, 0x036B, 0x8EA1, 0xA8B7, 0xA8BA, - 0x03F6, 0x8EA1, 0xA8BB, 0xA8BB, 0x1812, 0x8EA1, 0xA8BC, 0xA8BE, 0x03FA, - 0x8EA1, 0xA8BF, 0xA8C3, 0x03FE, 0x8EA1, 0xA8C4, 0xA8CC, 0x0405, 0x8EA1, - 0xA8CD, 0xA8CD, 0x1813, 0x8EA1, 0xA8CE, 0xA8CE, 0x1818, 0x8EA1, 0xA8CF, - 0xA8D2, 0x040F, 0x8EA1, 0xA8D3, 0xA8D3, 0x1819, 0x8EA1, 0xA8D4, 0xA8D9, - 0x0508, 0x8EA1, 0xA8DA, 0xA8DA, 0x18E7, 0x8EA1, 0xA8DB, 0xA8E2, 0x050E, - 0x8EA1, 0xA8E3, 0xA8E3, 0x0230, 0x8EA1, 0xA8E4, 0xA8E4, 0x051B, 0x8EA1, - 0xA8E5, 0xA8E7, 0x0520, 0x8EA1, 0xA8E8, 0xA8EB, 0x0696, 0x8EA1, 0xA8EC, - 0xA8EC, 0x0231, 0x8EA1, 0xA8ED, 0xA8F0, 0x069F, 0x8EA1, 0xA8F1, 0xA8FB, - 0x0826, 0x8EA1, 0xA8FC, 0xA8FE, 0x09F5, 0x8EA1, 0xA9A1, 0xA9A1, 0x1E33, - 0x8EA1, 0xA9A2, 0xA9A2, 0x09F8, 0x8EA1, 0xA9A3, 0xA9A3, 0x1E34, 0x8EA1, - 0xA9A4, 0xA9A5, 0x09F9, 0x8EA1, 0xA9A6, 0xA9AB, 0x0BE1, 0x8EA1, 0xA9AC, - 0xA9AE, 0x0DBB, 0x8EA1, 0xA9AF, 0xA9AF, 0x2360, 0x8EA1, 0xA9B0, 0xA9B0, - 0x2612, 0x8EA1, 0xA9B1, 0xA9B3, 0x0F7B, 0x8EA1, 0xA9B4, 0xA9B5, 0x1100, - 0x8EA1, 0xA9B6, 0xA9B6, 0x1289, 0x8EA1, 0xA9B7, 0xA9B8, 0x13B2, 0x8EA1, - 0xA9B9, 0xA9B9, 0x2F0D, 0x8EA1, 0xC2A1, 0xC2C1, 0x0232, 0x8EA1, 0xC4A1, - 0xC4FE, 0x0253, 0x8EA1, 0xC5A1, 0xC5FE, 0x02B1, 0x8EA1, 0xC6A1, 0xC6FE, - 0x030F, 0x8EA1, 0xC7A1, 0xC7FE, 0x036D, 0x8EA1, 0xC8A1, 0xC8FE, 0x03CB, - 0x8EA1, 0xC9A1, 0xC9FE, 0x0429, 0x8EA1, 0xCAA1, 0xCAFE, 0x0487, 0x8EA1, - 0xCBA1, 0xCBFE, 0x04E5, 0x8EA1, 0xCCA1, 0xCCFE, 0x0543, 0x8EA1, 0xCDA1, - 0xCDFE, 0x05A1, 0x8EA1, 0xCEA1, 0xCEFE, 0x05FF, 0x8EA1, 0xCFA1, 0xCFFE, - 0x065D, 0x8EA1, 0xD0A1, 0xD0FE, 0x06BB, 0x8EA1, 0xD1A1, 0xD1FE, 0x0719, - 0x8EA1, 0xD2A1, 0xD2FE, 0x0777, 0x8EA1, 0xD3A1, 0xD3FE, 0x07D5, 0x8EA1, - 0xD4A1, 0xD4FE, 0x0833, 0x8EA1, 0xD5A1, 0xD5FE, 0x0891, 0x8EA1, 0xD6A1, - 0xD6FE, 0x08EF, 0x8EA1, 0xD7A1, 0xD7FE, 0x094D, 0x8EA1, 0xD8A1, 0xD8FE, - 0x09AB, 0x8EA1, 0xD9A1, 0xD9FE, 0x0A09, 0x8EA1, 0xDAA1, 0xDAFE, 0x0A67, - 0x8EA1, 0xDBA1, 0xDBFE, 0x0AC5, 0x8EA1, 0xDCA1, 0xDCFE, 0x0B23, 0x8EA1, - 0xDDA1, 0xDDFE, 0x0B81, 0x8EA1, 0xDEA1, 0xDEFE, 0x0BDF, 0x8EA1, 0xDFA1, - 0xDFFE, 0x0C3D, 0x8EA1, 0xE0A1, 0xE0FE, 0x0C9B, 0x8EA1, 0xE1A1, 0xE1FE, - 0x0CF9, 0x8EA1, 0xE2A1, 0xE2FE, 0x0D57, 0x8EA1, 0xE3A1, 0xE3FE, 0x0DB5, - 0x8EA1, 0xE4A1, 0xE4FE, 0x0E13, 0x8EA1, 0xE5A1, 0xE5FE, 0x0E71, 0x8EA1, - 0xE6A1, 0xE6FE, 0x0ECF, 0x8EA1, 0xE7A1, 0xE7FE, 0x0F2D, 0x8EA1, 0xE8A1, - 0xE8FE, 0x0F8B, 0x8EA1, 0xE9A1, 0xE9FE, 0x0FE9, 0x8EA1, 0xEAA1, 0xEAFE, - 0x1047, 0x8EA1, 0xEBA1, 0xEBFE, 0x10A5, 0x8EA1, 0xECA1, 0xECFE, 0x1103, - 0x8EA1, 0xEDA1, 0xEDFE, 0x1161, 0x8EA1, 0xEEA1, 0xEEFE, 0x11BF, 0x8EA1, - 0xEFA1, 0xEFFE, 0x121D, 0x8EA1, 0xF0A1, 0xF0FE, 0x127B, 0x8EA1, 0xF1A1, - 0xF1FE, 0x12D9, 0x8EA1, 0xF2A1, 0xF2FE, 0x1337, 0x8EA1, 0xF3A1, 0xF3FE, - 0x1395, 0x8EA1, 0xF4A1, 0xF4FE, 0x13F3, 0x8EA1, 0xF5A1, 0xF5FE, 0x1451, - 0x8EA1, 0xF6A1, 0xF6FE, 0x14AF, 0x8EA1, 0xF7A1, 0xF7FE, 0x150D, 0x8EA1, - 0xF8A1, 0xF8FE, 0x156B, 0x8EA1, 0xF9A1, 0xF9FE, 0x15C9, 0x8EA1, 0xFAA1, - 0xFAFE, 0x1627, 0x8EA1, 0xFBA1, 0xFBFE, 0x1685, 0x8EA1, 0xFCA1, 0xFCFE, - 0x16E3, 0x8EA1, 0xFDA1, 0xFDCB, 0x1741, 0x8EA2, 0xA1A1, 0xA1FE, 0x176C, - 0x8EA2, 0xA2A1, 0xA2FE, 0x17CA, 0x8EA2, 0xA3A1, 0xA3FE, 0x1828, 0x8EA2, - 0xA4A1, 0xA4FE, 0x1886, 0x8EA2, 0xA5A1, 0xA5FE, 0x18E4, 0x8EA2, 0xA6A1, - 0xA6FE, 0x1942, 0x8EA2, 0xA7A1, 0xA7FE, 0x19A0, 0x8EA2, 0xA8A1, 0xA8FE, - 0x19FE, 0x8EA2, 0xA9A1, 0xA9FE, 0x1A5C, 0x8EA2, 0xAAA1, 0xAAFE, 0x1ABA, - 0x8EA2, 0xABA1, 0xABFE, 0x1B18, 0x8EA2, 0xACA1, 0xACFE, 0x1B76, 0x8EA2, - 0xADA1, 0xADFE, 0x1BD4, 0x8EA2, 0xAEA1, 0xAEFE, 0x1C32, 0x8EA2, 0xAFA1, - 0xAFFE, 0x1C90, 0x8EA2, 0xB0A1, 0xB0FE, 0x1CEE, 0x8EA2, 0xB1A1, 0xB1FE, - 0x1D4C, 0x8EA2, 0xB2A1, 0xB2FE, 0x1DAA, 0x8EA2, 0xB3A1, 0xB3FE, 0x1E08, - 0x8EA2, 0xB4A1, 0xB4FE, 0x1E66, 0x8EA2, 0xB5A1, 0xB5FE, 0x1EC4, 0x8EA2, - 0xB6A1, 0xB6FE, 0x1F22, 0x8EA2, 0xB7A1, 0xB7FE, 0x1F80, 0x8EA2, 0xB8A1, - 0xB8FE, 0x1FDE, 0x8EA2, 0xB9A1, 0xB9FE, 0x203C, 0x8EA2, 0xBAA1, 0xBAFE, - 0x209A, 0x8EA2, 0xBBA1, 0xBBFE, 0x20F8, 0x8EA2, 0xBCA1, 0xBCFE, 0x2156, - 0x8EA2, 0xBDA1, 0xBDFE, 0x21B4, 0x8EA2, 0xBEA1, 0xBEFE, 0x2212, 0x8EA2, - 0xBFA1, 0xBFFE, 0x2270, 0x8EA2, 0xC0A1, 0xC0FE, 0x22CE, 0x8EA2, 0xC1A1, - 0xC1FE, 0x232C, 0x8EA2, 0xC2A1, 0xC2FE, 0x238A, 0x8EA2, 0xC3A1, 0xC3FE, - 0x23E8, 0x8EA2, 0xC4A1, 0xC4FE, 0x2446, 0x8EA2, 0xC5A1, 0xC5FE, 0x24A4, - 0x8EA2, 0xC6A1, 0xC6FE, 0x2502, 0x8EA2, 0xC7A1, 0xC7FE, 0x2560, 0x8EA2, - 0xC8A1, 0xC8FE, 0x25BE, 0x8EA2, 0xC9A1, 0xC9FE, 0x261C, 0x8EA2, 0xCAA1, - 0xCAFE, 0x267A, 0x8EA2, 0xCBA1, 0xCBFE, 0x26D8, 0x8EA2, 0xCCA1, 0xCCFE, - 0x2736, 0x8EA2, 0xCDA1, 0xCDFE, 0x2794, 0x8EA2, 0xCEA1, 0xCEFE, 0x27F2, - 0x8EA2, 0xCFA1, 0xCFFE, 0x2850, 0x8EA2, 0xD0A1, 0xD0FE, 0x28AE, 0x8EA2, - 0xD1A1, 0xD1FE, 0x290C, 0x8EA2, 0xD2A1, 0xD2FE, 0x296A, 0x8EA2, 0xD3A1, - 0xD3FE, 0x29C8, 0x8EA2, 0xD4A1, 0xD4FE, 0x2A26, 0x8EA2, 0xD5A1, 0xD5FE, - 0x2A84, 0x8EA2, 0xD6A1, 0xD6FE, 0x2AE2, 0x8EA2, 0xD7A1, 0xD7FE, 0x2B40, - 0x8EA2, 0xD8A1, 0xD8FE, 0x2B9E, 0x8EA2, 0xD9A1, 0xD9FE, 0x2BFC, 0x8EA2, - 0xDAA1, 0xDAFE, 0x2C5A, 0x8EA2, 0xDBA1, 0xDBFE, 0x2CB8, 0x8EA2, 0xDCA1, - 0xDCFE, 0x2D16, 0x8EA2, 0xDDA1, 0xDDFE, 0x2D74, 0x8EA2, 0xDEA1, 0xDEFE, - 0x2DD2, 0x8EA2, 0xDFA1, 0xDFFE, 0x2E30, 0x8EA2, 0xE0A1, 0xE0FE, 0x2E8E, - 0x8EA2, 0xE1A1, 0xE1FE, 0x2EEC, 0x8EA2, 0xE2A1, 0xE2FE, 0x2F4A, 0x8EA2, - 0xE3A1, 0xE3FE, 0x2FA8, 0x8EA2, 0xE4A1, 0xE4FE, 0x3006, 0x8EA2, 0xE5A1, - 0xE5FE, 0x3064, 0x8EA2, 0xE6A1, 0xE6FE, 0x30C2, 0x8EA2, 0xE7A1, 0xE7FE, - 0x3120, 0x8EA2, 0xE8A1, 0xE8FE, 0x317E, 0x8EA2, 0xE9A1, 0xE9FE, 0x31DC, - 0x8EA2, 0xEAA1, 0xEAFE, 0x323A, 0x8EA2, 0xEBA1, 0xEBFE, 0x3298, 0x8EA2, - 0xECA1, 0xECFE, 0x32F6, 0x8EA2, 0xEDA1, 0xEDFE, 0x3354, 0x8EA2, 0xEEA1, - 0xEEFE, 0x33B2, 0x8EA2, 0xEFA1, 0xEFFE, 0x3410, 0x8EA2, 0xF0A1, 0xF0FE, - 0x346E, 0x8EA2, 0xF1A1, 0xF1FE, 0x34CC, 0x8EA2, 0xF2A1, 0xF2C4, 0x352A, +const FXCMAP_DWordCIDMap g_FXCMAP_CNS_EUC_V_0_DWord[261] = { + {0x8EA1, 0xA1A1, 0xA1AB, 0x0063}, {0x8EA1, 0xA1AC, 0xA1AC, 0x354E}, + {0x8EA1, 0xA1AD, 0xA1BA, 0x006F}, {0x8EA1, 0xA1BB, 0xA1BB, 0x007C}, + {0x8EA1, 0xA1BC, 0xA1BC, 0x007E}, {0x8EA1, 0xA1BD, 0xA1BD, 0x007E}, + {0x8EA1, 0xA1BE, 0xA1BF, 0x0082}, {0x8EA1, 0xA1C0, 0xA1C1, 0x0082}, + {0x8EA1, 0xA1C2, 0xA1C3, 0x0086}, {0x8EA1, 0xA1C4, 0xA1C5, 0x0086}, + {0x8EA1, 0xA1C6, 0xA1C7, 0x008A}, {0x8EA1, 0xA1C8, 0xA1C9, 0x008A}, + {0x8EA1, 0xA1CA, 0xA1CB, 0x008E}, {0x8EA1, 0xA1CC, 0xA1CD, 0x008E}, + {0x8EA1, 0xA1CE, 0xA1CF, 0x0092}, {0x8EA1, 0xA1D0, 0xA1D1, 0x0092}, + {0x8EA1, 0xA1D2, 0xA1D3, 0x0096}, {0x8EA1, 0xA1D4, 0xA1D5, 0x0096}, + {0x8EA1, 0xA1D6, 0xA1D7, 0x009A}, {0x8EA1, 0xA1D8, 0xA1D9, 0x009A}, + {0x8EA1, 0xA1DA, 0xA1DB, 0x009E}, {0x8EA1, 0xA1DC, 0xA1FE, 0x009E}, + {0x8EA1, 0xA2A1, 0xA2C3, 0x00C1}, {0x8EA1, 0xA2C4, 0xA2C4, 0x354F}, + {0x8EA1, 0xA2C5, 0xA2FE, 0x00E5}, {0x8EA1, 0xA3A1, 0xA3CE, 0x011F}, + {0x8EA1, 0xA4A1, 0xA4FE, 0x014D}, {0x8EA1, 0xA5A1, 0xA5EC, 0x01AB}, + {0x8EA1, 0xA5EE, 0xA5F0, 0x01F7}, {0x8EA1, 0xA6A1, 0xA6BE, 0x01FA}, + {0x8EA1, 0xA7A1, 0xA7A1, 0x0253}, {0x8EA1, 0xA7A2, 0xA7A4, 0x0218}, + {0x8EA1, 0xA7A5, 0xA7A5, 0x0254}, {0x8EA1, 0xA7A6, 0xA7A6, 0x021B}, + {0x8EA1, 0xA7A7, 0xA7A7, 0x025A}, {0x8EA1, 0xA7A8, 0xA7A8, 0x021C}, + {0x8EA1, 0xA7A9, 0xA7AC, 0x025B}, {0x8EA1, 0xA7AD, 0xA7AF, 0x021D}, + {0x8EA1, 0xA7B0, 0xA7B0, 0x025F}, {0x8EA1, 0xA7B1, 0xA7B1, 0x176E}, + {0x8EA1, 0xA7B2, 0xA7B2, 0x0260}, {0x8EA1, 0xA7B3, 0xA7B3, 0x0262}, + {0x8EA1, 0xA7B4, 0xA7B4, 0x0220}, {0x8EA1, 0xA7B5, 0xA7B5, 0x0263}, + {0x8EA1, 0xA7B6, 0xA7B6, 0x176F}, {0x8EA1, 0xA7B7, 0xA7B7, 0x0221}, + {0x8EA1, 0xA7B8, 0xA7B9, 0x0264}, {0x8EA1, 0xA7BA, 0xA7BA, 0x0222}, + {0x8EA1, 0xA7BB, 0xA7BB, 0x1770}, {0x8EA1, 0xA7BC, 0xA7BC, 0x0223}, + {0x8EA1, 0xA7BD, 0xA7BD, 0x0266}, {0x8EA1, 0xA7BE, 0xA7BE, 0x0279}, + {0x8EA1, 0xA7BF, 0xA7BF, 0x1775}, {0x8EA1, 0xA7C0, 0xA7C1, 0x027A}, + {0x8EA1, 0xA7C2, 0xA7C2, 0x0224}, {0x8EA1, 0xA7C3, 0xA7C6, 0x027C}, + {0x8EA1, 0xA7C7, 0xA7C7, 0x0225}, {0x8EA1, 0xA7C8, 0xA7CB, 0x0282}, + {0x8EA1, 0xA7CC, 0xA7CC, 0x1776}, {0x8EA1, 0xA7CD, 0xA7CD, 0x0286}, + {0x8EA1, 0xA7CE, 0xA7CE, 0x0226}, {0x8EA1, 0xA7CF, 0xA7D0, 0x0288}, + {0x8EA1, 0xA7D1, 0xA7D2, 0x028C}, {0x8EA1, 0xA7D3, 0xA7D5, 0x0227}, + {0x8EA1, 0xA7D6, 0xA7D8, 0x028E}, {0x8EA1, 0xA7D9, 0xA7DA, 0x022A}, + {0x8EA1, 0xA7DB, 0xA7DB, 0x1777}, {0x8EA1, 0xA7DC, 0xA7DF, 0x02D0}, + {0x8EA1, 0xA7E0, 0xA7E0, 0x02D5}, {0x8EA1, 0xA7E1, 0xA7E1, 0x022C}, + {0x8EA1, 0xA7E2, 0xA7E5, 0x02D6}, {0x8EA1, 0xA7E6, 0xA7E6, 0x022D}, + {0x8EA1, 0xA7E7, 0xA7ED, 0x02DA}, {0x8EA1, 0xA7EE, 0xA7EE, 0x178A}, + {0x8EA1, 0xA7EF, 0xA7F2, 0x02E1}, {0x8EA1, 0xA7F3, 0xA7F3, 0x178C}, + {0x8EA1, 0xA7F4, 0xA7F8, 0x02E5}, {0x8EA1, 0xA7F9, 0xA7F9, 0x178D}, + {0x8EA1, 0xA7FA, 0xA7FD, 0x02EA}, {0x8EA1, 0xA7FE, 0xA7FE, 0x0356}, + {0x8EA1, 0xA8A1, 0xA8A6, 0x0357}, {0x8EA1, 0xA8A7, 0xA8A7, 0x035E}, + {0x8EA1, 0xA8A8, 0xA8A8, 0x0362}, {0x8EA1, 0xA8A9, 0xA8AA, 0x022E}, + {0x8EA1, 0xA8AB, 0xA8B2, 0x0363}, {0x8EA1, 0xA8B3, 0xA8B3, 0x17B2}, + {0x8EA1, 0xA8B4, 0xA8B6, 0x036B}, {0x8EA1, 0xA8B7, 0xA8BA, 0x03F6}, + {0x8EA1, 0xA8BB, 0xA8BB, 0x1812}, {0x8EA1, 0xA8BC, 0xA8BE, 0x03FA}, + {0x8EA1, 0xA8BF, 0xA8C3, 0x03FE}, {0x8EA1, 0xA8C4, 0xA8CC, 0x0405}, + {0x8EA1, 0xA8CD, 0xA8CD, 0x1813}, {0x8EA1, 0xA8CE, 0xA8CE, 0x1818}, + {0x8EA1, 0xA8CF, 0xA8D2, 0x040F}, {0x8EA1, 0xA8D3, 0xA8D3, 0x1819}, + {0x8EA1, 0xA8D4, 0xA8D9, 0x0508}, {0x8EA1, 0xA8DA, 0xA8DA, 0x18E7}, + {0x8EA1, 0xA8DB, 0xA8E2, 0x050E}, {0x8EA1, 0xA8E3, 0xA8E3, 0x0230}, + {0x8EA1, 0xA8E4, 0xA8E4, 0x051B}, {0x8EA1, 0xA8E5, 0xA8E7, 0x0520}, + {0x8EA1, 0xA8E8, 0xA8EB, 0x0696}, {0x8EA1, 0xA8EC, 0xA8EC, 0x0231}, + {0x8EA1, 0xA8ED, 0xA8F0, 0x069F}, {0x8EA1, 0xA8F1, 0xA8FB, 0x0826}, + {0x8EA1, 0xA8FC, 0xA8FE, 0x09F5}, {0x8EA1, 0xA9A1, 0xA9A1, 0x1E33}, + {0x8EA1, 0xA9A2, 0xA9A2, 0x09F8}, {0x8EA1, 0xA9A3, 0xA9A3, 0x1E34}, + {0x8EA1, 0xA9A4, 0xA9A5, 0x09F9}, {0x8EA1, 0xA9A6, 0xA9AB, 0x0BE1}, + {0x8EA1, 0xA9AC, 0xA9AE, 0x0DBB}, {0x8EA1, 0xA9AF, 0xA9AF, 0x2360}, + {0x8EA1, 0xA9B0, 0xA9B0, 0x2612}, {0x8EA1, 0xA9B1, 0xA9B3, 0x0F7B}, + {0x8EA1, 0xA9B4, 0xA9B5, 0x1100}, {0x8EA1, 0xA9B6, 0xA9B6, 0x1289}, + {0x8EA1, 0xA9B7, 0xA9B8, 0x13B2}, {0x8EA1, 0xA9B9, 0xA9B9, 0x2F0D}, + {0x8EA1, 0xC2A1, 0xC2C1, 0x0232}, {0x8EA1, 0xC4A1, 0xC4FE, 0x0253}, + {0x8EA1, 0xC5A1, 0xC5FE, 0x02B1}, {0x8EA1, 0xC6A1, 0xC6FE, 0x030F}, + {0x8EA1, 0xC7A1, 0xC7FE, 0x036D}, {0x8EA1, 0xC8A1, 0xC8FE, 0x03CB}, + {0x8EA1, 0xC9A1, 0xC9FE, 0x0429}, {0x8EA1, 0xCAA1, 0xCAFE, 0x0487}, + {0x8EA1, 0xCBA1, 0xCBFE, 0x04E5}, {0x8EA1, 0xCCA1, 0xCCFE, 0x0543}, + {0x8EA1, 0xCDA1, 0xCDFE, 0x05A1}, {0x8EA1, 0xCEA1, 0xCEFE, 0x05FF}, + {0x8EA1, 0xCFA1, 0xCFFE, 0x065D}, {0x8EA1, 0xD0A1, 0xD0FE, 0x06BB}, + {0x8EA1, 0xD1A1, 0xD1FE, 0x0719}, {0x8EA1, 0xD2A1, 0xD2FE, 0x0777}, + {0x8EA1, 0xD3A1, 0xD3FE, 0x07D5}, {0x8EA1, 0xD4A1, 0xD4FE, 0x0833}, + {0x8EA1, 0xD5A1, 0xD5FE, 0x0891}, {0x8EA1, 0xD6A1, 0xD6FE, 0x08EF}, + {0x8EA1, 0xD7A1, 0xD7FE, 0x094D}, {0x8EA1, 0xD8A1, 0xD8FE, 0x09AB}, + {0x8EA1, 0xD9A1, 0xD9FE, 0x0A09}, {0x8EA1, 0xDAA1, 0xDAFE, 0x0A67}, + {0x8EA1, 0xDBA1, 0xDBFE, 0x0AC5}, {0x8EA1, 0xDCA1, 0xDCFE, 0x0B23}, + {0x8EA1, 0xDDA1, 0xDDFE, 0x0B81}, {0x8EA1, 0xDEA1, 0xDEFE, 0x0BDF}, + {0x8EA1, 0xDFA1, 0xDFFE, 0x0C3D}, {0x8EA1, 0xE0A1, 0xE0FE, 0x0C9B}, + {0x8EA1, 0xE1A1, 0xE1FE, 0x0CF9}, {0x8EA1, 0xE2A1, 0xE2FE, 0x0D57}, + {0x8EA1, 0xE3A1, 0xE3FE, 0x0DB5}, {0x8EA1, 0xE4A1, 0xE4FE, 0x0E13}, + {0x8EA1, 0xE5A1, 0xE5FE, 0x0E71}, {0x8EA1, 0xE6A1, 0xE6FE, 0x0ECF}, + {0x8EA1, 0xE7A1, 0xE7FE, 0x0F2D}, {0x8EA1, 0xE8A1, 0xE8FE, 0x0F8B}, + {0x8EA1, 0xE9A1, 0xE9FE, 0x0FE9}, {0x8EA1, 0xEAA1, 0xEAFE, 0x1047}, + {0x8EA1, 0xEBA1, 0xEBFE, 0x10A5}, {0x8EA1, 0xECA1, 0xECFE, 0x1103}, + {0x8EA1, 0xEDA1, 0xEDFE, 0x1161}, {0x8EA1, 0xEEA1, 0xEEFE, 0x11BF}, + {0x8EA1, 0xEFA1, 0xEFFE, 0x121D}, {0x8EA1, 0xF0A1, 0xF0FE, 0x127B}, + {0x8EA1, 0xF1A1, 0xF1FE, 0x12D9}, {0x8EA1, 0xF2A1, 0xF2FE, 0x1337}, + {0x8EA1, 0xF3A1, 0xF3FE, 0x1395}, {0x8EA1, 0xF4A1, 0xF4FE, 0x13F3}, + {0x8EA1, 0xF5A1, 0xF5FE, 0x1451}, {0x8EA1, 0xF6A1, 0xF6FE, 0x14AF}, + {0x8EA1, 0xF7A1, 0xF7FE, 0x150D}, {0x8EA1, 0xF8A1, 0xF8FE, 0x156B}, + {0x8EA1, 0xF9A1, 0xF9FE, 0x15C9}, {0x8EA1, 0xFAA1, 0xFAFE, 0x1627}, + {0x8EA1, 0xFBA1, 0xFBFE, 0x1685}, {0x8EA1, 0xFCA1, 0xFCFE, 0x16E3}, + {0x8EA1, 0xFDA1, 0xFDCB, 0x1741}, {0x8EA2, 0xA1A1, 0xA1FE, 0x176C}, + {0x8EA2, 0xA2A1, 0xA2FE, 0x17CA}, {0x8EA2, 0xA3A1, 0xA3FE, 0x1828}, + {0x8EA2, 0xA4A1, 0xA4FE, 0x1886}, {0x8EA2, 0xA5A1, 0xA5FE, 0x18E4}, + {0x8EA2, 0xA6A1, 0xA6FE, 0x1942}, {0x8EA2, 0xA7A1, 0xA7FE, 0x19A0}, + {0x8EA2, 0xA8A1, 0xA8FE, 0x19FE}, {0x8EA2, 0xA9A1, 0xA9FE, 0x1A5C}, + {0x8EA2, 0xAAA1, 0xAAFE, 0x1ABA}, {0x8EA2, 0xABA1, 0xABFE, 0x1B18}, + {0x8EA2, 0xACA1, 0xACFE, 0x1B76}, {0x8EA2, 0xADA1, 0xADFE, 0x1BD4}, + {0x8EA2, 0xAEA1, 0xAEFE, 0x1C32}, {0x8EA2, 0xAFA1, 0xAFFE, 0x1C90}, + {0x8EA2, 0xB0A1, 0xB0FE, 0x1CEE}, {0x8EA2, 0xB1A1, 0xB1FE, 0x1D4C}, + {0x8EA2, 0xB2A1, 0xB2FE, 0x1DAA}, {0x8EA2, 0xB3A1, 0xB3FE, 0x1E08}, + {0x8EA2, 0xB4A1, 0xB4FE, 0x1E66}, {0x8EA2, 0xB5A1, 0xB5FE, 0x1EC4}, + {0x8EA2, 0xB6A1, 0xB6FE, 0x1F22}, {0x8EA2, 0xB7A1, 0xB7FE, 0x1F80}, + {0x8EA2, 0xB8A1, 0xB8FE, 0x1FDE}, {0x8EA2, 0xB9A1, 0xB9FE, 0x203C}, + {0x8EA2, 0xBAA1, 0xBAFE, 0x209A}, {0x8EA2, 0xBBA1, 0xBBFE, 0x20F8}, + {0x8EA2, 0xBCA1, 0xBCFE, 0x2156}, {0x8EA2, 0xBDA1, 0xBDFE, 0x21B4}, + {0x8EA2, 0xBEA1, 0xBEFE, 0x2212}, {0x8EA2, 0xBFA1, 0xBFFE, 0x2270}, + {0x8EA2, 0xC0A1, 0xC0FE, 0x22CE}, {0x8EA2, 0xC1A1, 0xC1FE, 0x232C}, + {0x8EA2, 0xC2A1, 0xC2FE, 0x238A}, {0x8EA2, 0xC3A1, 0xC3FE, 0x23E8}, + {0x8EA2, 0xC4A1, 0xC4FE, 0x2446}, {0x8EA2, 0xC5A1, 0xC5FE, 0x24A4}, + {0x8EA2, 0xC6A1, 0xC6FE, 0x2502}, {0x8EA2, 0xC7A1, 0xC7FE, 0x2560}, + {0x8EA2, 0xC8A1, 0xC8FE, 0x25BE}, {0x8EA2, 0xC9A1, 0xC9FE, 0x261C}, + {0x8EA2, 0xCAA1, 0xCAFE, 0x267A}, {0x8EA2, 0xCBA1, 0xCBFE, 0x26D8}, + {0x8EA2, 0xCCA1, 0xCCFE, 0x2736}, {0x8EA2, 0xCDA1, 0xCDFE, 0x2794}, + {0x8EA2, 0xCEA1, 0xCEFE, 0x27F2}, {0x8EA2, 0xCFA1, 0xCFFE, 0x2850}, + {0x8EA2, 0xD0A1, 0xD0FE, 0x28AE}, {0x8EA2, 0xD1A1, 0xD1FE, 0x290C}, + {0x8EA2, 0xD2A1, 0xD2FE, 0x296A}, {0x8EA2, 0xD3A1, 0xD3FE, 0x29C8}, + {0x8EA2, 0xD4A1, 0xD4FE, 0x2A26}, {0x8EA2, 0xD5A1, 0xD5FE, 0x2A84}, + {0x8EA2, 0xD6A1, 0xD6FE, 0x2AE2}, {0x8EA2, 0xD7A1, 0xD7FE, 0x2B40}, + {0x8EA2, 0xD8A1, 0xD8FE, 0x2B9E}, {0x8EA2, 0xD9A1, 0xD9FE, 0x2BFC}, + {0x8EA2, 0xDAA1, 0xDAFE, 0x2C5A}, {0x8EA2, 0xDBA1, 0xDBFE, 0x2CB8}, + {0x8EA2, 0xDCA1, 0xDCFE, 0x2D16}, {0x8EA2, 0xDDA1, 0xDDFE, 0x2D74}, + {0x8EA2, 0xDEA1, 0xDEFE, 0x2DD2}, {0x8EA2, 0xDFA1, 0xDFFE, 0x2E30}, + {0x8EA2, 0xE0A1, 0xE0FE, 0x2E8E}, {0x8EA2, 0xE1A1, 0xE1FE, 0x2EEC}, + {0x8EA2, 0xE2A1, 0xE2FE, 0x2F4A}, {0x8EA2, 0xE3A1, 0xE3FE, 0x2FA8}, + {0x8EA2, 0xE4A1, 0xE4FE, 0x3006}, {0x8EA2, 0xE5A1, 0xE5FE, 0x3064}, + {0x8EA2, 0xE6A1, 0xE6FE, 0x30C2}, {0x8EA2, 0xE7A1, 0xE7FE, 0x3120}, + {0x8EA2, 0xE8A1, 0xE8FE, 0x317E}, {0x8EA2, 0xE9A1, 0xE9FE, 0x31DC}, + {0x8EA2, 0xEAA1, 0xEAFE, 0x323A}, {0x8EA2, 0xEBA1, 0xEBFE, 0x3298}, + {0x8EA2, 0xECA1, 0xECFE, 0x32F6}, {0x8EA2, 0xEDA1, 0xEDFE, 0x3354}, + {0x8EA2, 0xEEA1, 0xEEFE, 0x33B2}, {0x8EA2, 0xEFA1, 0xEFFE, 0x3410}, + {0x8EA2, 0xF0A1, 0xF0FE, 0x346E}, {0x8EA2, 0xF1A1, 0xF1FE, 0x34CC}, + {0x8EA2, 0xF2A1, 0xF2C4, 0x352A}, }; diff --git a/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp b/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp index a1bbefc1ab872d45126ffe39d0c21f5747260173..5076fcdd8814436296b71745fc1693ce2a2dadbd 100644 --- a/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp +++ b/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp @@ -8,49 +8,41 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fxcrt/fx_basic.h" static const FXCMAP_CMap g_FXCMAP_CNS1_cmaps[] = { - {"B5pc-H", FXCMAP_CMap::Range, g_FXCMAP_B5pc_H_0, 247, FXCMAP_CMap::None, - nullptr, 0, 0}, - {"B5pc-V", FXCMAP_CMap::Range, g_FXCMAP_B5pc_V_0, 12, FXCMAP_CMap::None, - nullptr, 0, -1}, - {"HKscs-B5-H", FXCMAP_CMap::Range, g_FXCMAP_HKscs_B5_H_5, 1210, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"HKscs-B5-V", FXCMAP_CMap::Range, g_FXCMAP_HKscs_B5_V_5, 13, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"ETen-B5-H", FXCMAP_CMap::Range, g_FXCMAP_ETen_B5_H_0, 254, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"ETen-B5-V", FXCMAP_CMap::Range, g_FXCMAP_ETen_B5_V_0, 13, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"ETenms-B5-H", FXCMAP_CMap::Range, g_FXCMAP_ETenms_B5_H_0, 1, - FXCMAP_CMap::None, nullptr, 0, -2}, - {"ETenms-B5-V", FXCMAP_CMap::Range, g_FXCMAP_ETenms_B5_V_0, 18, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"CNS-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_CNS_EUC_H_0, 157, - FXCMAP_CMap::Range, g_FXCMAP_CNS_EUC_H_0_DWord, 238, 0}, - {"CNS-EUC-V", FXCMAP_CMap::Range, g_FXCMAP_CNS_EUC_V_0, 180, - FXCMAP_CMap::Range, g_FXCMAP_CNS_EUC_V_0_DWord, 261, 0}, - {"UniCNS-UCS2-H", FXCMAP_CMap::Range, g_FXCMAP_UniCNS_UCS2_H_3, 16418, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniCNS-UCS2-V", FXCMAP_CMap::Range, g_FXCMAP_UniCNS_UCS2_V_3, 13, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"UniCNS-UTF16-H", FXCMAP_CMap::Single, g_FXCMAP_UniCNS_UTF16_H_0, 14557, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniCNS-UTF16-V", FXCMAP_CMap::Range, g_FXCMAP_UniCNS_UCS2_V_3, 13, - FXCMAP_CMap::None, nullptr, 0, -1}, + {"B5pc-H", g_FXCMAP_B5pc_H_0, nullptr, 247, 0, FXCMAP_CMap::Range, 0}, + {"B5pc-V", g_FXCMAP_B5pc_V_0, nullptr, 12, 0, FXCMAP_CMap::Range, -1}, + {"HKscs-B5-H", g_FXCMAP_HKscs_B5_H_5, nullptr, 1210, 0, FXCMAP_CMap::Range, + 0}, + {"HKscs-B5-V", g_FXCMAP_HKscs_B5_V_5, nullptr, 13, 0, FXCMAP_CMap::Range, + -1}, + {"ETen-B5-H", g_FXCMAP_ETen_B5_H_0, nullptr, 254, 0, FXCMAP_CMap::Range, 0}, + {"ETen-B5-V", g_FXCMAP_ETen_B5_V_0, nullptr, 13, 0, FXCMAP_CMap::Range, -1}, + {"ETenms-B5-H", g_FXCMAP_ETenms_B5_H_0, nullptr, 1, 0, FXCMAP_CMap::Range, + -2}, + {"ETenms-B5-V", g_FXCMAP_ETenms_B5_V_0, nullptr, 18, 0, FXCMAP_CMap::Range, + -1}, + {"CNS-EUC-H", g_FXCMAP_CNS_EUC_H_0, g_FXCMAP_CNS_EUC_H_0_DWord, 157, 238, + FXCMAP_CMap::Range, 0}, + {"CNS-EUC-V", g_FXCMAP_CNS_EUC_V_0, g_FXCMAP_CNS_EUC_V_0_DWord, 180, 261, + FXCMAP_CMap::Range, 0}, + {"UniCNS-UCS2-H", g_FXCMAP_UniCNS_UCS2_H_3, nullptr, 16418, 0, + FXCMAP_CMap::Range, 0}, + {"UniCNS-UCS2-V", g_FXCMAP_UniCNS_UCS2_V_3, nullptr, 13, 0, + FXCMAP_CMap::Range, -1}, + {"UniCNS-UTF16-H", g_FXCMAP_UniCNS_UTF16_H_0, nullptr, 14557, 0, + FXCMAP_CMap::Single, 0}, + {"UniCNS-UTF16-V", g_FXCMAP_UniCNS_UCS2_V_3, nullptr, 13, 0, + FXCMAP_CMap::Range, -1}, }; void CPDF_ModuleMgr::LoadEmbeddedCNS1CMaps() { CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - pFontGlobals->m_EmbeddedCharsets[CIDSET_CNS1].m_pMapList = - g_FXCMAP_CNS1_cmaps; - pFontGlobals->m_EmbeddedCharsets[CIDSET_CNS1].m_Count = - FX_ArraySize(g_FXCMAP_CNS1_cmaps); - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_CNS1].m_pMap = - g_FXCMAP_CNS1CID2Unicode_5; - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_CNS1].m_Count = 19088; + pFontGlobals->SetEmbeddedCharset(CIDSET_CNS1, g_FXCMAP_CNS1_cmaps, + FX_ArraySize(g_FXCMAP_CNS1_cmaps)); + pFontGlobals->SetEmbeddedToUnicode(CIDSET_CNS1, g_FXCMAP_CNS1CID2Unicode_5, + 19088); } diff --git a/core/fpdfapi/cmaps/CNS1/cmaps_cns1.h b/core/fpdfapi/cmaps/CNS1/cmaps_cns1.h index a87a47fca307822e9c8ff6ca95449ba4fc4c94e4..627feb7bed94442e1cb240a9054a777b43cf5cda 100644 --- a/core/fpdfapi/cmaps/CNS1/cmaps_cns1.h +++ b/core/fpdfapi/cmaps/CNS1/cmaps_cns1.h @@ -9,6 +9,8 @@ #include +#include "core/fpdfapi/cmaps/cmap_int.h" + extern const uint16_t g_FXCMAP_B5pc_H_0[]; extern const uint16_t g_FXCMAP_B5pc_V_0[]; extern const uint16_t g_FXCMAP_HKscs_B5_H_5[]; @@ -18,9 +20,9 @@ extern const uint16_t g_FXCMAP_ETen_B5_V_0[]; extern const uint16_t g_FXCMAP_ETenms_B5_H_0[]; extern const uint16_t g_FXCMAP_ETenms_B5_V_0[]; extern const uint16_t g_FXCMAP_CNS_EUC_H_0[]; -extern const uint16_t g_FXCMAP_CNS_EUC_H_0_DWord[]; +extern const FXCMAP_DWordCIDMap g_FXCMAP_CNS_EUC_H_0_DWord[]; extern const uint16_t g_FXCMAP_CNS_EUC_V_0[]; -extern const uint16_t g_FXCMAP_CNS_EUC_V_0_DWord[]; +extern const FXCMAP_DWordCIDMap g_FXCMAP_CNS_EUC_V_0_DWord[]; extern const uint16_t g_FXCMAP_UniCNS_UCS2_H_3[]; extern const uint16_t g_FXCMAP_UniCNS_UCS2_V_3[]; extern const uint16_t g_FXCMAP_UniCNS_UTF16_H_0[]; diff --git a/core/fpdfapi/cmaps/GB1/GBK2K-H_5.cpp b/core/fpdfapi/cmaps/GB1/GBK2K-H_5.cpp index 37b8803cc27f918d200835face00f9e156261b92..7d7b48acd6f6b5f15bf0475f30dd3d3006ba3cec 100644 --- a/core/fpdfapi/cmaps/GB1/GBK2K-H_5.cpp +++ b/core/fpdfapi/cmaps/GB1/GBK2K-H_5.cpp @@ -1366,457 +1366,514 @@ const uint16_t g_FXCMAP_GBK2K_H_5[4071 * 3] = { 0xFE40, 0xFE40, 0x1259, 0xFE41, 0xFE7E, 0x5610, 0xFE80, 0xFEA0, 0x564E, }; -const uint16_t g_FXCMAP_GBK2K_H_5_DWord[1017 * 4] = { - 0x8130, 0x8436, 0x8436, 0x5752, 0x8138, 0xFD38, 0xFD39, 0x579C, 0x8138, - 0xFE30, 0xFE39, 0x579E, 0x8139, 0x8130, 0x8137, 0x57A8, 0x8139, 0x8139, - 0x8139, 0x57B0, 0x8139, 0x8230, 0x8239, 0x57B1, 0x8139, 0x8330, 0x8339, - 0x57BB, 0x8139, 0x8430, 0x8439, 0x57C5, 0x8139, 0x8530, 0x8539, 0x57CF, - 0x8139, 0x8630, 0x8639, 0x57D9, 0x8139, 0x8730, 0x8739, 0x57E3, 0x8139, - 0x8830, 0x8839, 0x57ED, 0x8139, 0x8930, 0x8939, 0x57F7, 0x8139, 0x8B32, - 0x8B32, 0x1042, 0x8139, 0x8B33, 0x8B33, 0x1263, 0x8139, 0x8B34, 0x8B34, - 0x1272, 0x8139, 0x8B35, 0x8B35, 0x1265, 0x8139, 0x8B36, 0x8B36, 0x1059, - 0x8139, 0x8B37, 0x8B37, 0x2793, 0x8139, 0x8B38, 0x8B38, 0x063D, 0x8139, - 0x8B39, 0x8B39, 0x1303, 0x8139, 0x8C30, 0x8C30, 0x0CA6, 0x8139, 0x8C31, - 0x8C31, 0x0638, 0x8139, 0x8C32, 0x8C32, 0x0CC6, 0x8139, 0x8C33, 0x8C33, - 0x03D6, 0x8139, 0x8C34, 0x8C34, 0x129D, 0x8139, 0x8C35, 0x8C35, 0x1314, - 0x8139, 0x8C36, 0x8C36, 0x130F, 0x8139, 0x8C37, 0x8C37, 0x082B, 0x8139, - 0x8C38, 0x8C38, 0x1399, 0x8139, 0x8C39, 0x8C39, 0x0597, 0x8139, 0x8D30, - 0x8D30, 0x09EF, 0x8139, 0x8D31, 0x8D31, 0x12FC, 0x8139, 0x8D32, 0x8D32, - 0x1266, 0x8139, 0x8D33, 0x8D33, 0x1284, 0x8139, 0x8D34, 0x8D34, 0x2A1A, - 0x8139, 0x8D35, 0x8D35, 0x0D45, 0x8139, 0x8D36, 0x8D36, 0x047E, 0x8139, - 0x8D37, 0x8D37, 0x1352, 0x8139, 0x8D38, 0x8D38, 0x04CC, 0x8139, 0x8D39, - 0x8D39, 0x139C, 0x8139, 0x8E30, 0x8E30, 0x10BB, 0x8139, 0x8E31, 0x8E31, - 0x0967, 0x8139, 0x8E32, 0x8E32, 0x1593, 0x8139, 0x8E33, 0x8E33, 0x0E72, - 0x8139, 0x8E34, 0x8E34, 0x0D56, 0x8139, 0x8E35, 0x8E35, 0x161C, 0x8139, - 0x8E36, 0x8E36, 0x2D2D, 0x8139, 0x8E37, 0x8E37, 0x0F13, 0x8139, 0x8E38, - 0x8E38, 0x0576, 0x8139, 0x8E39, 0x8E39, 0x0B6F, 0x8139, 0x8F30, 0x8F30, - 0x1230, 0x8139, 0x8F31, 0x8F31, 0x172E, 0x8139, 0x8F32, 0x8F32, 0x056A, - 0x8139, 0x8F33, 0x8F33, 0x0F6C, 0x8139, 0x8F34, 0x8F34, 0x14B6, 0x8139, - 0x8F35, 0x8F35, 0x0D43, 0x8139, 0x8F36, 0x8F36, 0x1774, 0x8139, 0x8F37, - 0x8F37, 0x0CF6, 0x8139, 0x8F38, 0x8F38, 0x1815, 0x8139, 0x8F39, 0x8F39, - 0x06FD, 0x8139, 0x9030, 0x9030, 0x082D, 0x8139, 0x9031, 0x9031, 0x08BE, - 0x8139, 0x9032, 0x9032, 0x06C4, 0x8139, 0x9033, 0x9033, 0x1813, 0x8139, - 0x9034, 0x9034, 0x073C, 0x8139, 0x9035, 0x9035, 0x1398, 0x8139, 0x9036, - 0x9036, 0x14AD, 0x8139, 0x9037, 0x9037, 0x14F6, 0x8139, 0x9038, 0x9038, - 0x0706, 0x8139, 0x9039, 0x9039, 0x1762, 0x8139, 0x9130, 0x9130, 0x15EE, - 0x8139, 0x9131, 0x9131, 0x15E0, 0x8139, 0x9132, 0x9132, 0x0F8F, 0x8139, - 0x9133, 0x9133, 0x06E5, 0x8139, 0x9134, 0x9134, 0x3292, 0x8139, 0x9135, - 0x9135, 0x0D6D, 0x8139, 0x9136, 0x9136, 0x11A6, 0x8139, 0x9137, 0x9137, - 0x1909, 0x8139, 0x9138, 0x9138, 0x0ED3, 0x8139, 0x9139, 0x9139, 0x05F6, - 0x8139, 0x9230, 0x9230, 0x08C0, 0x8139, 0x9231, 0x9231, 0x065A, 0x8139, - 0x9232, 0x9232, 0x0EED, 0x8139, 0x9233, 0x9233, 0x0CB0, 0x8139, 0x9234, - 0x9234, 0x10FE, 0x8139, 0x9235, 0x9235, 0x1105, 0x8139, 0x9236, 0x9236, - 0x0B21, 0x8139, 0x9237, 0x9237, 0x0C34, 0x8139, 0x9238, 0x9238, 0x11B8, - 0x8139, 0x9239, 0x9239, 0x0578, 0x8139, 0x9330, 0x9330, 0x19BD, 0x8139, - 0x9331, 0x9331, 0x0EF2, 0x8139, 0x9332, 0x9332, 0x0431, 0x8139, 0x9333, - 0x9333, 0x0AB0, 0x8139, 0x9334, 0x9334, 0x0D66, 0x8139, 0x9335, 0x9335, - 0x0C17, 0x8139, 0x9336, 0x9336, 0x0DA3, 0x8139, 0x9337, 0x9337, 0x0805, - 0x8139, 0x9338, 0x9338, 0x1203, 0x8139, 0x9339, 0x9339, 0x06B3, 0x8139, - 0x9430, 0x9430, 0x1269, 0x8139, 0x9431, 0x9431, 0x169D, 0x8139, 0x9432, - 0x9432, 0x0BCB, 0x8139, 0x9433, 0x9433, 0x0FE9, 0x8139, 0x9434, 0x9434, - 0x0B64, 0x8139, 0x9435, 0x9435, 0x0C89, 0x8139, 0x9436, 0x9436, 0x0FC9, - 0x8139, 0x9437, 0x9437, 0x10D6, 0x8139, 0x9438, 0x9438, 0x0728, 0x8139, - 0x9439, 0x9439, 0x0E90, 0x8139, 0x9530, 0x9530, 0x06C5, 0x8139, 0x9531, - 0x9531, 0x0D33, 0x8139, 0x9532, 0x9532, 0x10A8, 0x8139, 0x9533, 0x9533, - 0x0E42, 0x8139, 0x9534, 0x9534, 0x1BC6, 0x8139, 0x9535, 0x9535, 0x1B60, - 0x8139, 0x9536, 0x9536, 0x3EBF, 0x8139, 0x9537, 0x9537, 0x03E2, 0x8139, - 0x9538, 0x9538, 0x0BC3, 0x8139, 0x9539, 0x9539, 0x0AF8, 0x8139, 0x9630, - 0x9630, 0x0B22, 0x8139, 0x9631, 0x9631, 0x0AB1, 0x8139, 0x9632, 0x9632, - 0x0D4F, 0x8139, 0x9633, 0x9633, 0x0D46, 0x8139, 0x9634, 0x9634, 0x0D55, - 0x8139, 0x9635, 0x9635, 0x40CB, 0x8139, 0x9636, 0x9636, 0x0783, 0x8139, - 0x9637, 0x9637, 0x0FD1, 0x8139, 0x9638, 0x9638, 0x09EB, 0x8139, 0x9639, - 0x9639, 0x11F0, 0x8139, 0x9730, 0x9730, 0x0ADC, 0x8139, 0x9731, 0x9731, - 0x1CE7, 0x8139, 0x9732, 0x9732, 0x1C5E, 0x8139, 0x9733, 0x9733, 0x0EA9, - 0x8139, 0x9734, 0x9734, 0x101B, 0x8139, 0x9735, 0x9735, 0x10D5, 0x8139, - 0x9736, 0x9736, 0x09BA, 0x8139, 0x9737, 0x9737, 0x0637, 0x8139, 0x9738, - 0x9738, 0x1BCB, 0x8139, 0x9739, 0x9739, 0x0639, 0x8139, 0x9830, 0x9830, - 0x1A1E, 0x8139, 0x9831, 0x9831, 0x0CBD, 0x8139, 0x9832, 0x9832, 0x04E1, - 0x8139, 0x9833, 0x9833, 0x1231, 0x8139, 0x9834, 0x9834, 0x11C0, 0x8139, - 0x9835, 0x9835, 0x08F9, 0x8139, 0x9836, 0x9836, 0x0D19, 0x8139, 0x9837, - 0x9837, 0x1618, 0x8139, 0x9838, 0x9838, 0x11DA, 0x8139, 0x9839, 0x9839, - 0x1CDC, 0x8139, 0x9930, 0x9930, 0x0CE4, 0x8139, 0x9931, 0x9931, 0x45A2, - 0x8139, 0x9932, 0x9932, 0x1BF0, 0x8139, 0x9933, 0x9933, 0x050B, 0x8139, - 0x9934, 0x9934, 0x0FD3, 0x8139, 0x9935, 0x9935, 0x0F9B, 0x8139, 0x9936, - 0x9936, 0x1049, 0x8139, 0x9937, 0x9937, 0x49DC, 0x8139, 0x9938, 0x9938, - 0x1F96, 0x8139, 0x9939, 0x9939, 0x0898, 0x8139, 0x9A30, 0x9A30, 0x0FFD, - 0x8139, 0x9A31, 0x9A31, 0x0721, 0x8139, 0x9A32, 0x9A32, 0x05F8, 0x8139, - 0x9A33, 0x9A33, 0x1D15, 0x8139, 0x9A34, 0x9A34, 0x1D50, 0x8139, 0x9A35, - 0x9A35, 0x1E3B, 0x8139, 0x9A36, 0x9A36, 0x0505, 0x8139, 0x9A37, 0x9A37, - 0x123C, 0x8139, 0x9A38, 0x9A38, 0x1240, 0x8139, 0x9A39, 0x9A39, 0x0D26, - 0x8139, 0x9B30, 0x9B30, 0x1E7B, 0x8139, 0x9B31, 0x9B31, 0x0F8C, 0x8139, - 0x9B32, 0x9B32, 0x04E2, 0x8139, 0x9B33, 0x9B33, 0x4D13, 0x8139, 0x9B34, - 0x9B34, 0x105F, 0x8139, 0x9B35, 0x9B35, 0x10B4, 0x8139, 0x9B36, 0x9B36, - 0x4E18, 0x8139, 0x9B37, 0x9B37, 0x09DA, 0x8139, 0x9B38, 0x9B38, 0x08C1, - 0x8139, 0x9B39, 0x9B39, 0x1E75, 0x8139, 0x9C30, 0x9C30, 0x207D, 0x8139, - 0x9C31, 0x9C31, 0x06B2, 0x8139, 0x9C32, 0x9C32, 0x09EE, 0x8139, 0x9C33, - 0x9C33, 0x1D79, 0x8139, 0x9C34, 0x9C34, 0x10CF, 0x8139, 0x9C35, 0x9C35, - 0x50EA, 0x8139, 0x9C36, 0x9C36, 0x0664, 0x8139, 0x9C37, 0x9C37, 0x0AEB, - 0x8139, 0x9C38, 0x9C38, 0x06EA, 0x8139, 0x9C39, 0x9C39, 0x218D, 0x8139, - 0x9D30, 0x9D30, 0x08F1, 0x8139, 0x9D31, 0x9D31, 0x107B, 0x8139, 0x9D32, - 0x9D32, 0x2209, 0x8139, 0x9D33, 0x9D33, 0x1F00, 0x8139, 0x9D34, 0x9D34, - 0x1EF4, 0x8139, 0x9D35, 0x9D35, 0x0D4A, 0x8139, 0x9D36, 0x9D36, 0x0D6E, - 0x8139, 0x9D37, 0x9D37, 0x0F50, 0x8139, 0x9D38, 0x9D38, 0x206D, 0x8139, - 0x9D39, 0x9D39, 0x0720, 0x8139, 0x9E30, 0x9E30, 0x06DA, 0x8139, 0x9E31, - 0x9E31, 0x1DEC, 0x8139, 0x9E32, 0x9E32, 0x1ED0, 0x8139, 0x9E33, 0x9E33, - 0x139B, 0x8139, 0x9E34, 0x9E34, 0x1260, 0x8139, 0x9E35, 0x9E35, 0x0746, - 0x8139, 0x9E36, 0x9E36, 0x2239, 0x8139, 0x9E37, 0x9E37, 0x209C, 0x8139, - 0x9E38, 0x9E38, 0x2688, 0x8139, 0x9E39, 0x9E39, 0x0A60, 0x8139, 0x9F30, - 0x9F30, 0x2071, 0x8139, 0x9F31, 0x9F31, 0x0A90, 0x8139, 0x9F32, 0x9F32, - 0x5586, 0x8139, 0x9F33, 0x9F33, 0x0D89, 0x8139, 0x9F34, 0x9F34, 0x0791, - 0x8139, 0x9F35, 0x9F35, 0x1A55, 0x8139, 0x9F36, 0x9F36, 0x2618, 0x8139, - 0x9F37, 0x9F37, 0x05E5, 0x8139, 0x9F38, 0x9F38, 0x071D, 0x8139, 0x9F39, - 0x9F39, 0x0D8A, 0x8139, 0xA030, 0xA030, 0x0430, 0x8139, 0xA031, 0xA031, - 0x20C6, 0x8139, 0xA032, 0xA032, 0x1E86, 0x8139, 0xA033, 0xA033, 0x2037, - 0x8139, 0xA034, 0xA034, 0x1F34, 0x8139, 0xA035, 0xA035, 0x12F3, 0x8139, - 0xA533, 0xA535, 0x577B, 0x8139, 0xA538, 0xA539, 0x577E, 0x8139, 0xA630, - 0xA630, 0x5780, 0x8139, 0xA634, 0xA634, 0x5755, 0x8139, 0xA636, 0xA636, - 0x5767, 0x8139, 0xA735, 0xA735, 0x5776, 0x8139, 0xA736, 0xA736, 0x5778, - 0x8139, 0xA737, 0xA737, 0x5777, 0x8139, 0xA738, 0xA738, 0x5779, 0x8139, - 0xA836, 0xA838, 0x5781, 0x8139, 0xB434, 0xB439, 0x5784, 0x8139, 0xB530, - 0xB539, 0x578A, 0x8139, 0xB630, 0xB637, 0x5794, 0x8139, 0xEE39, 0xEE39, - 0x5801, 0x8139, 0xEF30, 0xEF39, 0x5802, 0x8139, 0xF030, 0xF039, 0x580C, - 0x8139, 0xF130, 0xF139, 0x5816, 0x8139, 0xF230, 0xF239, 0x5820, 0x8139, - 0xF330, 0xF339, 0x582A, 0x8139, 0xF430, 0xF439, 0x5834, 0x8139, 0xF530, - 0xF539, 0x583E, 0x8139, 0xF630, 0xF639, 0x5848, 0x8139, 0xF730, 0xF739, - 0x5852, 0x8139, 0xF830, 0xF839, 0x585C, 0x8139, 0xF930, 0xF939, 0x5866, - 0x8139, 0xFA30, 0xFA39, 0x5870, 0x8139, 0xFB30, 0xFB39, 0x587A, 0x8139, - 0xFC30, 0xFC39, 0x5884, 0x8139, 0xFD30, 0xFD39, 0x588E, 0x8139, 0xFE30, - 0xFE39, 0x5898, 0x8230, 0x8130, 0x8139, 0x58A2, 0x8230, 0x8230, 0x8239, - 0x58AC, 0x8230, 0x8330, 0x8339, 0x58B6, 0x8230, 0x8430, 0x8439, 0x58C0, - 0x8230, 0x8530, 0x8539, 0x58CA, 0x8230, 0x8630, 0x8639, 0x58D4, 0x8230, - 0x8730, 0x8739, 0x58DE, 0x8230, 0x8830, 0x8839, 0x58E8, 0x8230, 0x8930, - 0x8939, 0x58F2, 0x8230, 0x8A30, 0x8A39, 0x58FC, 0x8230, 0x8B30, 0x8B39, - 0x5906, 0x8230, 0x8C30, 0x8C39, 0x5910, 0x8230, 0x8D30, 0x8D39, 0x591A, - 0x8230, 0x8E30, 0x8E39, 0x5924, 0x8230, 0x8F30, 0x8F39, 0x592E, 0x8230, - 0x9030, 0x9039, 0x5938, 0x8230, 0x9130, 0x9139, 0x5942, 0x8230, 0x9230, - 0x9239, 0x594C, 0x8230, 0x9330, 0x9339, 0x5956, 0x8230, 0x9430, 0x9439, - 0x5960, 0x8230, 0x9530, 0x9539, 0x596A, 0x8230, 0x9630, 0x9639, 0x5974, - 0x8230, 0x9730, 0x9739, 0x597E, 0x8230, 0x9830, 0x9839, 0x5988, 0x8230, - 0x9930, 0x9939, 0x5992, 0x8230, 0x9A30, 0x9A39, 0x599C, 0x8230, 0x9B30, - 0x9B39, 0x59A6, 0x8230, 0x9C30, 0x9C39, 0x59B0, 0x8230, 0x9D30, 0x9D39, - 0x59BA, 0x8230, 0x9E30, 0x9E39, 0x59C4, 0x8230, 0x9F30, 0x9F39, 0x59CE, - 0x8230, 0xA030, 0xA039, 0x59D8, 0x8230, 0xA130, 0xA139, 0x59E2, 0x8230, - 0xA230, 0xA239, 0x59EC, 0x8230, 0xA330, 0xA339, 0x59F6, 0x8230, 0xA430, - 0xA439, 0x5A00, 0x8230, 0xA530, 0xA539, 0x5A0A, 0x8230, 0xA630, 0xA639, - 0x5A14, 0x8230, 0xA730, 0xA739, 0x5A1E, 0x8230, 0xA830, 0xA839, 0x5A28, - 0x8230, 0xA930, 0xA939, 0x5A32, 0x8230, 0xAA30, 0xAA39, 0x5A3C, 0x8230, - 0xAB30, 0xAB39, 0x5A46, 0x8230, 0xAC30, 0xAC39, 0x5A50, 0x8230, 0xAD30, - 0xAD39, 0x5A5A, 0x8230, 0xAE30, 0xAE39, 0x5A64, 0x8230, 0xAF30, 0xAF39, - 0x5A6E, 0x8230, 0xB030, 0xB039, 0x5A78, 0x8230, 0xB130, 0xB139, 0x5A82, - 0x8230, 0xB230, 0xB239, 0x5A8C, 0x8230, 0xB330, 0xB339, 0x5A96, 0x8230, - 0xB430, 0xB439, 0x5AA0, 0x8230, 0xB530, 0xB539, 0x5AAA, 0x8230, 0xB630, - 0xB639, 0x5AB4, 0x8230, 0xB730, 0xB739, 0x5ABE, 0x8230, 0xB830, 0xB839, - 0x5AC8, 0x8230, 0xB930, 0xB939, 0x5AD2, 0x8230, 0xBA30, 0xBA39, 0x5ADC, - 0x8230, 0xBB30, 0xBB39, 0x5AE6, 0x8230, 0xBC30, 0xBC39, 0x5AF0, 0x8230, - 0xBD30, 0xBD39, 0x5AFA, 0x8230, 0xBE30, 0xBE39, 0x5B04, 0x8230, 0xBF30, - 0xBF39, 0x5B0E, 0x8230, 0xC030, 0xC039, 0x5B18, 0x8230, 0xC130, 0xC139, - 0x5B22, 0x8230, 0xC230, 0xC239, 0x5B2C, 0x8230, 0xC330, 0xC339, 0x5B36, - 0x8230, 0xC430, 0xC439, 0x5B40, 0x8230, 0xC530, 0xC539, 0x5B4A, 0x8230, - 0xC630, 0xC639, 0x5B54, 0x8230, 0xC730, 0xC739, 0x5B5E, 0x8230, 0xC830, - 0xC839, 0x5B68, 0x8230, 0xC930, 0xC939, 0x5B72, 0x8230, 0xCA30, 0xCA39, - 0x5B7C, 0x8230, 0xCB30, 0xCB39, 0x5B86, 0x8230, 0xCC30, 0xCC39, 0x5B90, - 0x8230, 0xCD30, 0xCD39, 0x5B9A, 0x8230, 0xCE30, 0xCE39, 0x5BA4, 0x8230, - 0xCF30, 0xCF39, 0x5BAE, 0x8230, 0xD030, 0xD039, 0x5BB8, 0x8230, 0xD130, - 0xD139, 0x5BC2, 0x8230, 0xD230, 0xD239, 0x5BCC, 0x8230, 0xD330, 0xD339, - 0x5BD6, 0x8230, 0xD430, 0xD439, 0x5BE0, 0x8230, 0xD530, 0xD539, 0x5BEA, - 0x8230, 0xD630, 0xD639, 0x5BF4, 0x8230, 0xD730, 0xD739, 0x5BFE, 0x8230, - 0xD830, 0xD839, 0x5C08, 0x8230, 0xD930, 0xD939, 0x5C12, 0x8230, 0xDA30, - 0xDA39, 0x5C1C, 0x8230, 0xDB30, 0xDB39, 0x5C26, 0x8230, 0xDC30, 0xDC39, - 0x5C30, 0x8230, 0xDD30, 0xDD39, 0x5C3A, 0x8230, 0xDE30, 0xDE39, 0x5C44, - 0x8230, 0xDF30, 0xDF39, 0x5C4E, 0x8230, 0xE030, 0xE039, 0x5C58, 0x8230, - 0xE130, 0xE139, 0x5C62, 0x8230, 0xE230, 0xE239, 0x5C6C, 0x8230, 0xE330, - 0xE339, 0x5C76, 0x8230, 0xE430, 0xE439, 0x5C80, 0x8230, 0xE530, 0xE539, - 0x5C8A, 0x8230, 0xE630, 0xE639, 0x5C94, 0x8230, 0xE730, 0xE739, 0x5C9E, - 0x8230, 0xE830, 0xE839, 0x5CA8, 0x8230, 0xE930, 0xE939, 0x5CB2, 0x8230, - 0xEA30, 0xEA39, 0x5CBC, 0x8230, 0xEB30, 0xEB39, 0x5CC6, 0x8230, 0xEC30, - 0xEC39, 0x5CD0, 0x8230, 0xED30, 0xED39, 0x5CDA, 0x8230, 0xEE30, 0xEE39, - 0x5CE4, 0x8230, 0xEF30, 0xEF39, 0x5CEE, 0x8230, 0xF030, 0xF039, 0x5CF8, - 0x8230, 0xF130, 0xF139, 0x5D02, 0x8230, 0xF230, 0xF239, 0x5D0C, 0x8230, - 0xF330, 0xF339, 0x5D16, 0x8230, 0xF430, 0xF439, 0x5D20, 0x8230, 0xF530, - 0xF539, 0x5D2A, 0x8230, 0xF630, 0xF639, 0x5D34, 0x8230, 0xF730, 0xF739, - 0x5D3E, 0x8230, 0xF830, 0xF839, 0x5D48, 0x8230, 0xF930, 0xF939, 0x5D52, - 0x8230, 0xFA30, 0xFA39, 0x5D5C, 0x8230, 0xFB30, 0xFB39, 0x5D66, 0x8230, - 0xFC30, 0xFC39, 0x5D70, 0x8230, 0xFD30, 0xFD39, 0x5D7A, 0x8230, 0xFE30, - 0xFE39, 0x5D84, 0x8231, 0x8130, 0x8139, 0x5D8E, 0x8231, 0x8230, 0x8239, - 0x5D98, 0x8231, 0x8330, 0x8339, 0x5DA2, 0x8231, 0x8430, 0x8439, 0x5DAC, - 0x8231, 0x8530, 0x8539, 0x5DB6, 0x8231, 0x8630, 0x8639, 0x5DC0, 0x8231, - 0x8730, 0x8739, 0x5DCA, 0x8231, 0x8830, 0x8839, 0x5DD4, 0x8231, 0x8930, - 0x8939, 0x5DDE, 0x8231, 0x8A30, 0x8A39, 0x5DE8, 0x8231, 0x8B30, 0x8B39, - 0x5DF2, 0x8231, 0x8C30, 0x8C39, 0x5DFC, 0x8231, 0x8D30, 0x8D39, 0x5E06, - 0x8231, 0x8E30, 0x8E39, 0x5E10, 0x8231, 0x8F30, 0x8F39, 0x5E1A, 0x8231, - 0x9030, 0x9039, 0x5E24, 0x8231, 0x9130, 0x9139, 0x5E2E, 0x8231, 0x9230, - 0x9239, 0x5E38, 0x8231, 0x9330, 0x9339, 0x5E42, 0x8231, 0x9430, 0x9439, - 0x5E4C, 0x8231, 0x9530, 0x9539, 0x5E56, 0x8231, 0x9630, 0x9639, 0x5E60, - 0x8231, 0x9730, 0x9739, 0x5E6A, 0x8231, 0x9830, 0x9839, 0x5E74, 0x8231, - 0x9930, 0x9939, 0x5E7E, 0x8231, 0x9A30, 0x9A39, 0x5E88, 0x8231, 0x9B30, - 0x9B39, 0x5E92, 0x8231, 0x9C30, 0x9C39, 0x5E9C, 0x8231, 0x9D30, 0x9D39, - 0x5EA6, 0x8231, 0x9E30, 0x9E39, 0x5EB0, 0x8231, 0x9F30, 0x9F39, 0x5EBA, - 0x8231, 0xA030, 0xA039, 0x5EC4, 0x8231, 0xA130, 0xA139, 0x5ECE, 0x8231, - 0xA230, 0xA239, 0x5ED8, 0x8231, 0xA330, 0xA339, 0x5EE2, 0x8231, 0xA430, - 0xA439, 0x5EEC, 0x8231, 0xA530, 0xA539, 0x5EF6, 0x8231, 0xA630, 0xA639, - 0x5F00, 0x8231, 0xA730, 0xA739, 0x5F0A, 0x8231, 0xA830, 0xA839, 0x5F14, - 0x8231, 0xA930, 0xA939, 0x5F1E, 0x8231, 0xAA30, 0xAA39, 0x5F28, 0x8231, - 0xAB30, 0xAB39, 0x5F32, 0x8231, 0xAC30, 0xAC39, 0x5F3C, 0x8231, 0xAD30, - 0xAD39, 0x5F46, 0x8231, 0xAE30, 0xAE39, 0x5F50, 0x8231, 0xAF30, 0xAF39, - 0x5F5A, 0x8231, 0xB030, 0xB039, 0x5F64, 0x8231, 0xB130, 0xB139, 0x5F6E, - 0x8231, 0xB230, 0xB239, 0x5F78, 0x8231, 0xB330, 0xB339, 0x5F82, 0x8231, - 0xB430, 0xB439, 0x5F8C, 0x8231, 0xB530, 0xB539, 0x5F96, 0x8231, 0xB630, - 0xB639, 0x5FA0, 0x8231, 0xB730, 0xB739, 0x5FAA, 0x8231, 0xB830, 0xB839, - 0x5FB4, 0x8231, 0xB930, 0xB939, 0x5FBE, 0x8231, 0xBA30, 0xBA39, 0x5FC8, - 0x8231, 0xBB30, 0xBB39, 0x5FD2, 0x8231, 0xBC30, 0xBC39, 0x5FDC, 0x8231, - 0xBD30, 0xBD39, 0x5FE6, 0x8231, 0xBE30, 0xBE39, 0x5FF0, 0x8231, 0xBF30, - 0xBF39, 0x5FFA, 0x8231, 0xC030, 0xC039, 0x6004, 0x8231, 0xC130, 0xC139, - 0x600E, 0x8231, 0xC230, 0xC239, 0x6018, 0x8231, 0xC330, 0xC339, 0x6022, - 0x8231, 0xC430, 0xC439, 0x602C, 0x8231, 0xC530, 0xC539, 0x6036, 0x8231, - 0xC630, 0xC639, 0x6040, 0x8231, 0xC730, 0xC739, 0x604A, 0x8231, 0xC830, - 0xC839, 0x6054, 0x8231, 0xC930, 0xC939, 0x605E, 0x8231, 0xCA30, 0xCA39, - 0x6068, 0x8231, 0xCB30, 0xCB39, 0x6072, 0x8231, 0xCC30, 0xCC39, 0x607C, - 0x8231, 0xCD30, 0xCD39, 0x6086, 0x8231, 0xCE30, 0xCE39, 0x6090, 0x8231, - 0xCF30, 0xCF39, 0x609A, 0x8231, 0xD030, 0xD039, 0x60A4, 0x8231, 0xD130, - 0xD139, 0x60AE, 0x8231, 0xD230, 0xD239, 0x60B8, 0x8231, 0xD330, 0xD339, - 0x60C2, 0x8231, 0xD430, 0xD439, 0x60CC, 0x8231, 0xD530, 0xD539, 0x60D6, - 0x8231, 0xD630, 0xD639, 0x60E0, 0x8231, 0xD730, 0xD739, 0x60EA, 0x8231, - 0xD830, 0xD839, 0x60F4, 0x8231, 0xD930, 0xD939, 0x60FE, 0x8231, 0xDA30, - 0xDA39, 0x6108, 0x8231, 0xDB30, 0xDB39, 0x6112, 0x8231, 0xDC30, 0xDC39, - 0x611C, 0x8231, 0xDD30, 0xDD39, 0x6126, 0x8231, 0xDE30, 0xDE39, 0x6130, - 0x8231, 0xDF30, 0xDF39, 0x613A, 0x8231, 0xE030, 0xE039, 0x6144, 0x8231, - 0xE130, 0xE139, 0x614E, 0x8231, 0xE230, 0xE239, 0x6158, 0x8231, 0xE330, - 0xE339, 0x6162, 0x8231, 0xE430, 0xE439, 0x616C, 0x8231, 0xE530, 0xE539, - 0x6176, 0x8231, 0xE630, 0xE639, 0x6180, 0x8231, 0xE730, 0xE739, 0x618A, - 0x8231, 0xE830, 0xE839, 0x6194, 0x8231, 0xE930, 0xE939, 0x619E, 0x8231, - 0xEA30, 0xEA39, 0x61A8, 0x8231, 0xEB30, 0xEB39, 0x61B2, 0x8231, 0xEC30, - 0xEC39, 0x61BC, 0x8231, 0xED30, 0xED39, 0x61C6, 0x8231, 0xEE30, 0xEE39, - 0x61D0, 0x8231, 0xEF30, 0xEF39, 0x61DA, 0x8231, 0xF030, 0xF039, 0x61E4, - 0x8231, 0xF130, 0xF139, 0x61EE, 0x8231, 0xF230, 0xF239, 0x61F8, 0x8231, - 0xF330, 0xF339, 0x6202, 0x8231, 0xF430, 0xF439, 0x620C, 0x8231, 0xF530, - 0xF539, 0x6216, 0x8231, 0xF630, 0xF639, 0x6220, 0x8231, 0xF730, 0xF739, - 0x622A, 0x8231, 0xF830, 0xF839, 0x6234, 0x8231, 0xF930, 0xF939, 0x623E, - 0x8231, 0xFA30, 0xFA39, 0x6248, 0x8231, 0xFB30, 0xFB39, 0x6252, 0x8231, - 0xFC30, 0xFC39, 0x625C, 0x8231, 0xFD30, 0xFD39, 0x6266, 0x8231, 0xFE30, - 0xFE39, 0x6270, 0x8232, 0x8130, 0x8139, 0x627A, 0x8232, 0x8230, 0x8239, - 0x6284, 0x8232, 0x8330, 0x8339, 0x628E, 0x8232, 0x8430, 0x8439, 0x6298, - 0x8232, 0x8530, 0x8539, 0x62A2, 0x8232, 0x8630, 0x8639, 0x62AC, 0x8232, - 0x8730, 0x8739, 0x62B6, 0x8232, 0x8830, 0x8839, 0x62C0, 0x8232, 0x8930, - 0x8939, 0x62CA, 0x8232, 0x8A30, 0x8A39, 0x62D4, 0x8232, 0x8B30, 0x8B39, - 0x62DE, 0x8232, 0x8C30, 0x8C39, 0x62E8, 0x8232, 0x8D30, 0x8D39, 0x62F2, - 0x8232, 0x8E30, 0x8E39, 0x62FC, 0x8232, 0x8F30, 0x8F39, 0x6306, 0x8232, - 0x9030, 0x9039, 0x6310, 0x8232, 0x9130, 0x9139, 0x631A, 0x8232, 0x9230, - 0x9239, 0x6324, 0x8232, 0x9330, 0x9339, 0x632E, 0x8232, 0x9430, 0x9439, - 0x6338, 0x8232, 0x9530, 0x9539, 0x6342, 0x8232, 0x9630, 0x9639, 0x634C, - 0x8232, 0x9730, 0x9739, 0x6356, 0x8232, 0x9830, 0x9839, 0x6360, 0x8232, - 0x9930, 0x9939, 0x636A, 0x8232, 0x9A30, 0x9A39, 0x6374, 0x8232, 0x9B30, - 0x9B39, 0x637E, 0x8232, 0x9C30, 0x9C39, 0x6388, 0x8232, 0x9D30, 0x9D39, - 0x6392, 0x8232, 0x9E30, 0x9E39, 0x639C, 0x8232, 0x9F30, 0x9F39, 0x63A6, - 0x8232, 0xA030, 0xA039, 0x63B0, 0x8232, 0xA130, 0xA139, 0x63BA, 0x8232, - 0xA230, 0xA239, 0x63C4, 0x8232, 0xA330, 0xA339, 0x63CE, 0x8232, 0xA430, - 0xA439, 0x63D8, 0x8232, 0xA530, 0xA539, 0x63E2, 0x8232, 0xA630, 0xA639, - 0x63EC, 0x8232, 0xA730, 0xA739, 0x63F6, 0x8232, 0xA830, 0xA839, 0x6400, - 0x8232, 0xA930, 0xA939, 0x640A, 0x8232, 0xAA30, 0xAA39, 0x6414, 0x8232, - 0xAB30, 0xAB39, 0x641E, 0x8232, 0xAC30, 0xAC39, 0x6428, 0x8232, 0xAD30, - 0xAD39, 0x6432, 0x8232, 0xAE30, 0xAE39, 0x643C, 0x8232, 0xAF30, 0xAF39, - 0x6446, 0x8232, 0xB030, 0xB039, 0x6450, 0x8232, 0xB130, 0xB139, 0x645A, - 0x8232, 0xB230, 0xB239, 0x6464, 0x8232, 0xB330, 0xB339, 0x646E, 0x8232, - 0xB430, 0xB439, 0x6478, 0x8232, 0xB530, 0xB539, 0x6482, 0x8232, 0xB630, - 0xB639, 0x648C, 0x8232, 0xB730, 0xB739, 0x6496, 0x8232, 0xB830, 0xB839, - 0x64A0, 0x8232, 0xB930, 0xB939, 0x64AA, 0x8232, 0xBA30, 0xBA39, 0x64B4, - 0x8232, 0xBB30, 0xBB39, 0x64BE, 0x8232, 0xBC30, 0xBC39, 0x64C8, 0x8232, - 0xBD30, 0xBD39, 0x64D2, 0x8232, 0xBE30, 0xBE39, 0x64DC, 0x8232, 0xBF30, - 0xBF39, 0x64E6, 0x8232, 0xC030, 0xC039, 0x64F0, 0x8232, 0xC130, 0xC139, - 0x64FA, 0x8232, 0xC230, 0xC239, 0x6504, 0x8232, 0xC330, 0xC339, 0x650E, - 0x8232, 0xC430, 0xC439, 0x6518, 0x8232, 0xC530, 0xC539, 0x6522, 0x8232, - 0xC630, 0xC639, 0x652C, 0x8232, 0xC730, 0xC739, 0x6536, 0x8232, 0xC830, - 0xC839, 0x6540, 0x8232, 0xC930, 0xC939, 0x654A, 0x8232, 0xCA30, 0xCA39, - 0x6554, 0x8232, 0xCB30, 0xCB39, 0x655E, 0x8232, 0xCC30, 0xCC39, 0x6568, - 0x8232, 0xCD30, 0xCD39, 0x6572, 0x8232, 0xCE30, 0xCE39, 0x657C, 0x8232, - 0xCF30, 0xCF39, 0x6586, 0x8232, 0xD030, 0xD039, 0x6590, 0x8232, 0xD130, - 0xD139, 0x659A, 0x8232, 0xD230, 0xD239, 0x65A4, 0x8232, 0xD330, 0xD339, - 0x65AE, 0x8232, 0xD430, 0xD439, 0x65B8, 0x8232, 0xD530, 0xD539, 0x65C2, - 0x8232, 0xD630, 0xD639, 0x65CC, 0x8232, 0xD730, 0xD739, 0x65D6, 0x8232, - 0xD830, 0xD839, 0x65E0, 0x8232, 0xD930, 0xD939, 0x65EA, 0x8232, 0xDA30, - 0xDA39, 0x65F4, 0x8232, 0xDB30, 0xDB39, 0x65FE, 0x8232, 0xDC30, 0xDC39, - 0x6608, 0x8232, 0xDD30, 0xDD39, 0x6612, 0x8232, 0xDE30, 0xDE39, 0x661C, - 0x8232, 0xDF30, 0xDF39, 0x6626, 0x8232, 0xE030, 0xE039, 0x6630, 0x8232, - 0xE130, 0xE139, 0x663A, 0x8232, 0xE230, 0xE239, 0x6644, 0x8232, 0xE330, - 0xE339, 0x664E, 0x8232, 0xE430, 0xE439, 0x6658, 0x8232, 0xE530, 0xE539, - 0x6662, 0x8232, 0xE630, 0xE639, 0x666C, 0x8232, 0xE730, 0xE739, 0x6676, - 0x8232, 0xE830, 0xE839, 0x6680, 0x8232, 0xE930, 0xE939, 0x668A, 0x8232, - 0xEA30, 0xEA39, 0x6694, 0x8232, 0xEB30, 0xEB39, 0x669E, 0x8232, 0xEC30, - 0xEC39, 0x66A8, 0x8232, 0xED30, 0xED39, 0x66B2, 0x8232, 0xEE30, 0xEE39, - 0x66BC, 0x8232, 0xEF30, 0xEF39, 0x66C6, 0x8232, 0xF030, 0xF039, 0x66D0, - 0x8232, 0xF130, 0xF139, 0x66DA, 0x8232, 0xF230, 0xF239, 0x66E4, 0x8232, - 0xF330, 0xF339, 0x66EE, 0x8232, 0xF430, 0xF439, 0x66F8, 0x8232, 0xF530, - 0xF539, 0x6702, 0x8232, 0xF630, 0xF639, 0x670C, 0x8232, 0xF730, 0xF739, - 0x6716, 0x8232, 0xF830, 0xF839, 0x6720, 0x8232, 0xF930, 0xF939, 0x672A, - 0x8232, 0xFA30, 0xFA39, 0x6734, 0x8232, 0xFB30, 0xFB39, 0x673E, 0x8232, - 0xFC30, 0xFC39, 0x6748, 0x8232, 0xFD30, 0xFD39, 0x6752, 0x8232, 0xFE30, - 0xFE39, 0x675C, 0x8233, 0x8130, 0x8139, 0x6766, 0x8233, 0x8230, 0x8239, - 0x6770, 0x8233, 0x8330, 0x8339, 0x677A, 0x8233, 0x8430, 0x8439, 0x6784, - 0x8233, 0x8530, 0x8539, 0x678E, 0x8233, 0x8630, 0x8639, 0x6798, 0x8233, - 0x8730, 0x8739, 0x67A2, 0x8233, 0x8830, 0x8839, 0x67AC, 0x8233, 0x8930, - 0x8939, 0x67B6, 0x8233, 0x8A30, 0x8A39, 0x67C0, 0x8233, 0x8B30, 0x8B39, - 0x67CA, 0x8233, 0x8C30, 0x8C39, 0x67D4, 0x8233, 0x8D30, 0x8D39, 0x67DE, - 0x8233, 0x8E30, 0x8E39, 0x67E8, 0x8233, 0x8F30, 0x8F39, 0x67F2, 0x8233, - 0x9030, 0x9039, 0x67FC, 0x8233, 0x9130, 0x9139, 0x6806, 0x8233, 0x9230, - 0x9239, 0x6810, 0x8233, 0x9330, 0x9339, 0x681A, 0x8233, 0x9430, 0x9439, - 0x6824, 0x8233, 0x9530, 0x9539, 0x682E, 0x8233, 0x9630, 0x9639, 0x6838, - 0x8233, 0x9730, 0x9739, 0x6842, 0x8233, 0x9830, 0x9839, 0x684C, 0x8233, - 0x9930, 0x9939, 0x6856, 0x8233, 0x9A30, 0x9A39, 0x6860, 0x8233, 0x9B30, - 0x9B39, 0x686A, 0x8233, 0x9C30, 0x9C39, 0x6874, 0x8233, 0x9D30, 0x9D39, - 0x687E, 0x8233, 0x9E30, 0x9E39, 0x6888, 0x8233, 0x9F30, 0x9F39, 0x6892, - 0x8233, 0xA030, 0xA039, 0x689C, 0x8233, 0xA130, 0xA139, 0x68A6, 0x8233, - 0xA230, 0xA239, 0x68B0, 0x8233, 0xA330, 0xA339, 0x68BA, 0x8233, 0xA430, - 0xA439, 0x68C4, 0x8233, 0xA530, 0xA539, 0x68CE, 0x8233, 0xA630, 0xA639, - 0x68D8, 0x8233, 0xA730, 0xA739, 0x68E2, 0x8233, 0xA830, 0xA839, 0x68EC, - 0x8233, 0xA930, 0xA939, 0x68F6, 0x8233, 0xAA30, 0xAA39, 0x6900, 0x8233, - 0xAB30, 0xAB39, 0x690A, 0x8233, 0xAC30, 0xAC39, 0x6914, 0x8233, 0xAD30, - 0xAD39, 0x691E, 0x8233, 0xAE30, 0xAE39, 0x6928, 0x8233, 0xAF30, 0xAF39, - 0x6932, 0x8233, 0xB030, 0xB039, 0x693C, 0x8233, 0xB130, 0xB139, 0x6946, - 0x8233, 0xB230, 0xB239, 0x6950, 0x8233, 0xB330, 0xB339, 0x695A, 0x8233, - 0xB430, 0xB439, 0x6964, 0x8233, 0xB530, 0xB539, 0x696E, 0x8233, 0xB630, - 0xB639, 0x6978, 0x8233, 0xB730, 0xB739, 0x6982, 0x8233, 0xB830, 0xB839, - 0x698C, 0x8233, 0xB930, 0xB939, 0x6996, 0x8233, 0xBA30, 0xBA39, 0x69A0, - 0x8233, 0xBB30, 0xBB39, 0x69AA, 0x8233, 0xBC30, 0xBC39, 0x69B4, 0x8233, - 0xBD30, 0xBD39, 0x69BE, 0x8233, 0xBE30, 0xBE39, 0x69C8, 0x8233, 0xBF30, - 0xBF39, 0x69D2, 0x8233, 0xC030, 0xC039, 0x69DC, 0x8233, 0xC130, 0xC139, - 0x69E6, 0x8233, 0xC230, 0xC239, 0x69F0, 0x8233, 0xC330, 0xC339, 0x69FA, - 0x8233, 0xC430, 0xC439, 0x6A04, 0x8233, 0xC530, 0xC539, 0x6A0E, 0x8233, - 0xC630, 0xC639, 0x6A18, 0x8233, 0xC730, 0xC739, 0x6A22, 0x8233, 0xC830, - 0xC839, 0x6A2C, 0x8233, 0xC930, 0xC939, 0x6A36, 0x8233, 0xCA30, 0xCA39, - 0x6A40, 0x8233, 0xCB30, 0xCB39, 0x6A4A, 0x8233, 0xCC30, 0xCC39, 0x6A54, - 0x8233, 0xCD30, 0xCD39, 0x6A5E, 0x8233, 0xCE30, 0xCE39, 0x6A68, 0x8233, - 0xCF30, 0xCF39, 0x6A72, 0x8233, 0xD030, 0xD039, 0x6A7C, 0x8233, 0xD130, - 0xD139, 0x6A86, 0x8233, 0xD230, 0xD239, 0x6A90, 0x8233, 0xD330, 0xD339, - 0x6A9A, 0x8233, 0xD430, 0xD439, 0x6AA4, 0x8233, 0xD530, 0xD539, 0x6AAE, - 0x8233, 0xD630, 0xD639, 0x6AB8, 0x8233, 0xD730, 0xD739, 0x6AC2, 0x8233, - 0xD830, 0xD839, 0x6ACC, 0x8233, 0xD930, 0xD939, 0x6AD6, 0x8233, 0xDA30, - 0xDA39, 0x6AE0, 0x8233, 0xDB30, 0xDB39, 0x6AEA, 0x8233, 0xDC30, 0xDC39, - 0x6AF4, 0x8233, 0xDD30, 0xDD39, 0x6AFE, 0x8233, 0xDE30, 0xDE39, 0x6B08, - 0x8233, 0xDF30, 0xDF39, 0x6B12, 0x8233, 0xE030, 0xE039, 0x6B1C, 0x8233, - 0xE130, 0xE139, 0x6B26, 0x8233, 0xE230, 0xE239, 0x6B30, 0x8233, 0xE330, - 0xE339, 0x6B3A, 0x8233, 0xE430, 0xE439, 0x6B44, 0x8233, 0xE530, 0xE539, - 0x6B4E, 0x8233, 0xE630, 0xE639, 0x6B58, 0x8233, 0xE730, 0xE739, 0x6B62, - 0x8233, 0xE830, 0xE839, 0x6B6C, 0x8233, 0xE930, 0xE939, 0x6B76, 0x8233, - 0xEA30, 0xEA39, 0x6B80, 0x8233, 0xEB30, 0xEB39, 0x6B8A, 0x8233, 0xEC30, - 0xEC39, 0x6B94, 0x8233, 0xED30, 0xED39, 0x6B9E, 0x8233, 0xEE30, 0xEE39, - 0x6BA8, 0x8233, 0xEF30, 0xEF39, 0x6BB2, 0x8233, 0xF030, 0xF039, 0x6BBC, - 0x8233, 0xF130, 0xF139, 0x6BC6, 0x8233, 0xF230, 0xF239, 0x6BD0, 0x8233, - 0xF330, 0xF339, 0x6BDA, 0x8233, 0xF430, 0xF439, 0x6BE4, 0x8233, 0xF530, - 0xF539, 0x6BEE, 0x8233, 0xF630, 0xF639, 0x6BF8, 0x8233, 0xF730, 0xF739, - 0x6C02, 0x8233, 0xF830, 0xF839, 0x6C0C, 0x8233, 0xF930, 0xF939, 0x6C16, - 0x8233, 0xFA30, 0xFA39, 0x6C20, 0x8233, 0xFB30, 0xFB39, 0x6C2A, 0x8233, - 0xFC30, 0xFC39, 0x6C34, 0x8233, 0xFD30, 0xFD39, 0x6C3E, 0x8233, 0xFE30, - 0xFE39, 0x6C48, 0x8234, 0x8130, 0x8139, 0x6C52, 0x8234, 0x8230, 0x8239, - 0x6C5C, 0x8234, 0x8330, 0x8339, 0x6C66, 0x8234, 0x8430, 0x8439, 0x6C70, - 0x8234, 0x8530, 0x8539, 0x6C7A, 0x8234, 0x8630, 0x8639, 0x6C84, 0x8234, - 0x8730, 0x8739, 0x6C8E, 0x8234, 0x8830, 0x8839, 0x6C98, 0x8234, 0x8930, - 0x8939, 0x6CA2, 0x8234, 0x8A30, 0x8A39, 0x6CAC, 0x8234, 0x8B30, 0x8B39, - 0x6CB6, 0x8234, 0x8C30, 0x8C39, 0x6CC0, 0x8234, 0x8D30, 0x8D39, 0x6CCA, - 0x8234, 0x8E30, 0x8E39, 0x6CD4, 0x8234, 0x8F30, 0x8F39, 0x6CDE, 0x8234, - 0x9030, 0x9039, 0x6CE8, 0x8234, 0x9130, 0x9139, 0x6CF2, 0x8234, 0x9230, - 0x9239, 0x6CFC, 0x8234, 0x9330, 0x9339, 0x6D06, 0x8234, 0x9430, 0x9439, - 0x6D10, 0x8234, 0x9530, 0x9539, 0x6D1A, 0x8234, 0x9630, 0x9639, 0x6D24, - 0x8234, 0x9730, 0x9739, 0x6D2E, 0x8234, 0x9830, 0x9839, 0x6D38, 0x8234, - 0x9930, 0x9939, 0x6D42, 0x8234, 0x9A30, 0x9A39, 0x6D4C, 0x8234, 0x9B30, - 0x9B39, 0x6D56, 0x8234, 0x9C30, 0x9C39, 0x6D60, 0x8234, 0x9D30, 0x9D39, - 0x6D6A, 0x8234, 0x9E30, 0x9E39, 0x6D74, 0x8234, 0x9F30, 0x9F39, 0x6D7E, - 0x8234, 0xA030, 0xA039, 0x6D88, 0x8234, 0xA130, 0xA139, 0x6D92, 0x8234, - 0xA230, 0xA239, 0x6D9C, 0x8234, 0xA330, 0xA339, 0x6DA6, 0x8234, 0xA430, - 0xA439, 0x6DB0, 0x8234, 0xA530, 0xA539, 0x6DBA, 0x8234, 0xA630, 0xA639, - 0x6DC4, 0x8234, 0xA730, 0xA739, 0x6DCE, 0x8234, 0xA830, 0xA839, 0x6DD8, - 0x8234, 0xA930, 0xA939, 0x6DE2, 0x8234, 0xAA30, 0xAA39, 0x6DEC, 0x8234, - 0xAB30, 0xAB39, 0x6DF6, 0x8234, 0xAC30, 0xAC39, 0x6E00, 0x8234, 0xAD30, - 0xAD39, 0x6E0A, 0x8234, 0xAE30, 0xAE39, 0x6E14, 0x8234, 0xAF30, 0xAF39, - 0x6E1E, 0x8234, 0xB030, 0xB039, 0x6E28, 0x8234, 0xB130, 0xB139, 0x6E32, - 0x8234, 0xB230, 0xB239, 0x6E3C, 0x8234, 0xB330, 0xB339, 0x6E46, 0x8234, - 0xB430, 0xB439, 0x6E50, 0x8234, 0xB530, 0xB539, 0x6E5A, 0x8234, 0xB630, - 0xB639, 0x6E64, 0x8234, 0xB730, 0xB739, 0x6E6E, 0x8234, 0xB830, 0xB839, - 0x6E78, 0x8234, 0xB930, 0xB939, 0x6E82, 0x8234, 0xBA30, 0xBA39, 0x6E8C, - 0x8234, 0xBB30, 0xBB39, 0x6E96, 0x8234, 0xBC30, 0xBC39, 0x6EA0, 0x8234, - 0xBD30, 0xBD39, 0x6EAA, 0x8234, 0xBE30, 0xBE39, 0x6EB4, 0x8234, 0xBF30, - 0xBF39, 0x6EBE, 0x8234, 0xC030, 0xC039, 0x6EC8, 0x8234, 0xC130, 0xC139, - 0x6ED2, 0x8234, 0xC230, 0xC239, 0x6EDC, 0x8234, 0xC330, 0xC339, 0x6EE6, - 0x8234, 0xC430, 0xC439, 0x6EF0, 0x8234, 0xC530, 0xC539, 0x6EFA, 0x8234, - 0xC630, 0xC639, 0x6F04, 0x8234, 0xC730, 0xC739, 0x6F0E, 0x8234, 0xC830, - 0xC839, 0x6F18, 0x8234, 0xC930, 0xC939, 0x6F22, 0x8234, 0xCA30, 0xCA39, - 0x6F2C, 0x8234, 0xCB30, 0xCB39, 0x6F36, 0x8234, 0xCC30, 0xCC39, 0x6F40, - 0x8234, 0xCD30, 0xCD39, 0x6F4A, 0x8234, 0xCE30, 0xCE39, 0x6F54, 0x8234, - 0xCF30, 0xCF39, 0x6F5E, 0x8234, 0xD030, 0xD039, 0x6F68, 0x8234, 0xD130, - 0xD139, 0x6F72, 0x8234, 0xD230, 0xD239, 0x6F7C, 0x8234, 0xD330, 0xD339, - 0x6F86, 0x8234, 0xD430, 0xD439, 0x6F90, 0x8234, 0xD530, 0xD539, 0x6F9A, - 0x8234, 0xD630, 0xD639, 0x6FA4, 0x8234, 0xD730, 0xD739, 0x6FAE, 0x8234, - 0xD830, 0xD839, 0x6FB8, 0x8234, 0xD930, 0xD939, 0x6FC2, 0x8234, 0xDA30, - 0xDA39, 0x6FCC, 0x8234, 0xDB30, 0xDB39, 0x6FD6, 0x8234, 0xDC30, 0xDC39, - 0x6FE0, 0x8234, 0xDD30, 0xDD39, 0x6FEA, 0x8234, 0xDE30, 0xDE39, 0x6FF4, - 0x8234, 0xDF30, 0xDF39, 0x6FFE, 0x8234, 0xE030, 0xE039, 0x7008, 0x8234, - 0xE130, 0xE139, 0x7012, 0x8234, 0xE230, 0xE239, 0x701C, 0x8234, 0xE330, - 0xE339, 0x7026, 0x8234, 0xE430, 0xE439, 0x7030, 0x8234, 0xE530, 0xE539, - 0x703A, 0x8234, 0xE630, 0xE639, 0x7044, 0x8234, 0xE730, 0xE739, 0x704E, - 0x8234, 0xE830, 0xE839, 0x7058, 0x8234, 0xE930, 0xE939, 0x7062, 0x8234, - 0xEA30, 0xEA39, 0x706C, 0x8234, 0xEB30, 0xEB39, 0x7076, 0x8234, 0xEC30, - 0xEC39, 0x7080, 0x8234, 0xED30, 0xED39, 0x708A, 0x8234, 0xEE30, 0xEE39, - 0x7094, 0x8234, 0xEF30, 0xEF39, 0x709E, 0x8234, 0xF030, 0xF039, 0x70A8, - 0x8234, 0xF130, 0xF139, 0x70B2, 0x8234, 0xF230, 0xF239, 0x70BC, 0x8234, - 0xF330, 0xF339, 0x70C6, 0x8234, 0xF430, 0xF439, 0x70D0, 0x8234, 0xF530, - 0xF539, 0x70DA, 0x8234, 0xF630, 0xF639, 0x70E4, 0x8234, 0xF730, 0xF739, - 0x70EE, 0x8234, 0xF830, 0xF839, 0x70F8, 0x8234, 0xF930, 0xF939, 0x7102, - 0x8234, 0xFA30, 0xFA39, 0x710C, 0x8234, 0xFB30, 0xFB39, 0x7116, 0x8234, - 0xFC30, 0xFC39, 0x7120, 0x8234, 0xFD30, 0xFD39, 0x712A, 0x8234, 0xFE30, - 0xFE39, 0x7134, 0x8235, 0x8130, 0x8139, 0x713E, 0x8235, 0x8230, 0x8239, - 0x7148, 0x8235, 0x8330, 0x8339, 0x7152, 0x8235, 0x8430, 0x8439, 0x715C, - 0x8235, 0x8530, 0x8539, 0x7166, 0x8235, 0x8630, 0x8639, 0x7170, 0x8235, - 0x8730, 0x8738, 0x717A, 0x8235, 0x9833, 0x9839, 0x7188, 0x8235, 0x9930, - 0x9939, 0x718F, 0x8235, 0x9A30, 0x9A39, 0x7199, 0x8235, 0x9B30, 0x9B39, - 0x71A3, 0x8235, 0x9C30, 0x9C39, 0x71AD, 0x8235, 0x9D30, 0x9D39, 0x71B7, - 0x8235, 0x9E30, 0x9E39, 0x71C1, 0x8235, 0x9F30, 0x9F39, 0x71CB, 0x8235, - 0xA030, 0xA039, 0x71D5, 0x8235, 0xA130, 0xA139, 0x71DF, 0x8235, 0xA230, - 0xA239, 0x71E9, 0x8235, 0xA330, 0xA339, 0x71F3, 0x8235, 0xA430, 0xA439, - 0x71FD, 0x8235, 0xA530, 0xA539, 0x7207, 0x8235, 0xA630, 0xA639, 0x7211, - 0x8235, 0xA730, 0xA739, 0x721B, 0x8235, 0xA830, 0xA839, 0x7225, 0x8235, - 0xA930, 0xA939, 0x722F, 0x8235, 0xAA30, 0xAA39, 0x7239, 0x8235, 0xAB30, - 0xAB39, 0x7243, 0x8235, 0xAC30, 0xAC39, 0x724D, 0x8235, 0xAD30, 0xAD39, - 0x7257, 0x8235, 0xAE30, 0xAE39, 0x7261, 0x8235, 0xAF30, 0xAF39, 0x726B, - 0x8235, 0xB030, 0xB039, 0x7275, 0x8235, 0xB130, 0xB139, 0x727F, 0x8235, - 0xB230, 0xB239, 0x7289, 0x8235, 0xB330, 0xB339, 0x7293, 0x8235, 0xB430, - 0xB439, 0x729D, 0x8235, 0xB530, 0xB539, 0x72A7, 0x8235, 0xB630, 0xB639, - 0x72B1, 0x8235, 0xB730, 0xB739, 0x72BB, 0x8235, 0xB830, 0xB839, 0x72C5, - 0x8235, 0xB930, 0xB939, 0x72CF, 0x8235, 0xBA30, 0xBA39, 0x72D9, 0x8235, - 0xBB30, 0xBB39, 0x72E3, 0x8235, 0xBC30, 0xBC39, 0x72ED, 0x8235, 0xBD30, - 0xBD39, 0x72F7, 0x8235, 0xBE30, 0xBE39, 0x7301, 0x8235, 0xBF30, 0xBF39, - 0x730B, 0x8235, 0xC030, 0xC039, 0x7315, 0x8235, 0xC130, 0xC139, 0x731F, - 0x8235, 0xC230, 0xC239, 0x7329, 0x8235, 0xC330, 0xC339, 0x7333, 0x8235, - 0xC430, 0xC439, 0x733D, 0x8235, 0xC530, 0xC539, 0x7347, 0x8235, 0xC630, - 0xC639, 0x7351, 0x8235, 0xC730, 0xC739, 0x735B, 0x8235, 0xC830, 0xC839, - 0x7365, 0x8235, 0xC930, 0xC939, 0x736F, 0x8235, 0xCA30, 0xCA39, 0x7379, - 0x8235, 0xCB30, 0xCB39, 0x7383, 0x8235, 0xCC30, 0xCC39, 0x738D, 0x8235, - 0xCD30, 0xCD39, 0x7397, 0x8235, 0xCE30, 0xCE39, 0x73A1, 0x8235, 0xCF30, - 0xCF39, 0x73AB, 0x8235, 0xD030, 0xD039, 0x73B5, 0x8235, 0xD130, 0xD139, - 0x73BF, 0x8235, 0xD230, 0xD239, 0x73C9, 0x8235, 0xD330, 0xD339, 0x73D3, - 0x8235, 0xD430, 0xD439, 0x73DD, 0x8235, 0xD530, 0xD539, 0x73E7, 0x8235, - 0xD630, 0xD639, 0x73F1, 0x8235, 0xD730, 0xD739, 0x73FB, 0x8235, 0xD830, - 0xD839, 0x7405, 0x8235, 0xD930, 0xD939, 0x740F, 0x8235, 0xDA30, 0xDA39, - 0x7419, 0x8235, 0xDB30, 0xDB39, 0x7423, 0x8235, 0xDC30, 0xDC39, 0x742D, - 0x8235, 0xDD30, 0xDD39, 0x7437, 0x8235, 0xDE30, 0xDE39, 0x7441, 0x8235, - 0xDF30, 0xDF39, 0x744B, 0x8235, 0xE030, 0xE039, 0x7455, 0x8235, 0xE130, - 0xE139, 0x745F, 0x8235, 0xE230, 0xE239, 0x7469, 0x8235, 0xE330, 0xE339, - 0x7473, 0x8235, 0xE430, 0xE439, 0x747D, 0x8235, 0xE530, 0xE539, 0x7487, - 0x8235, 0xE630, 0xE639, 0x7491, 0x8235, 0xE730, 0xE739, 0x749B, 0x8235, - 0xE830, 0xE839, 0x74A5, 0x8235, 0xE930, 0xE939, 0x74AF, 0x8235, 0xEA30, - 0xEA39, 0x74B9, 0x8235, 0xEB30, 0xEB39, 0x74C3, 0x8235, 0xEC30, 0xEC39, - 0x74CD, 0x8235, 0xED30, 0xED39, 0x74D7, 0x8235, 0xEE30, 0xEE39, 0x74E1, - 0x8235, 0xEF30, 0xEF39, 0x74EB, 0x8235, 0xF030, 0xF039, 0x74F5, 0x8235, - 0xF130, 0xF139, 0x74FF, 0x8235, 0xF230, 0xF239, 0x7509, 0x8235, 0xF330, - 0xF339, 0x7513, 0x8235, 0xF430, 0xF439, 0x751D, 0x8235, 0xF530, 0xF539, - 0x7527, 0x8235, 0xF630, 0xF639, 0x7531, 0x8235, 0xF730, 0xF739, 0x753B, - 0x8235, 0xF830, 0xF839, 0x7545, 0x8235, 0xF930, 0xF939, 0x754F, 0x8235, - 0xFA30, 0xFA39, 0x7559, 0x8235, 0xFB30, 0xFB39, 0x7563, 0x8235, 0xFC30, - 0xFC39, 0x756D, 0x8235, 0xFD30, 0xFD39, 0x7577, 0x8235, 0xFE30, 0xFE39, - 0x7581, 0x8236, 0x8130, 0x8139, 0x758B, 0x8236, 0x8230, 0x8239, 0x7595, - 0x8236, 0x8330, 0x8339, 0x759F, 0x8236, 0x8430, 0x8439, 0x75A9, 0x8236, - 0x8530, 0x8539, 0x75B3, 0x8236, 0x8630, 0x8639, 0x75BD, 0x8236, 0x8730, - 0x8739, 0x75C7, 0x8236, 0x8830, 0x8839, 0x75D1, 0x8236, 0x8930, 0x8939, - 0x75DB, 0x8236, 0x8A30, 0x8A39, 0x75E5, 0x8236, 0x8B30, 0x8B39, 0x75EF, - 0x8236, 0x8C30, 0x8C39, 0x75F9, 0x8236, 0x8D30, 0x8D39, 0x7603, 0x8236, - 0x8E30, 0x8E37, 0x760D, 0x8236, 0x8F31, 0x8F39, 0x7615, 0x8236, 0x9030, - 0x9039, 0x761E, 0x8236, 0x9130, 0x9139, 0x7628, 0x8236, 0x9230, 0x9239, - 0x7632, 0x8236, 0x9330, 0x9339, 0x763C, 0x8236, 0x9430, 0x9435, 0x7646, +const FXCMAP_DWordCIDMap g_FXCMAP_GBK2K_H_5_DWord[1017] = { + {0x8130, 0x8436, 0x8436, 0x5752}, {0x8138, 0xFD38, 0xFD39, 0x579C}, + {0x8138, 0xFE30, 0xFE39, 0x579E}, {0x8139, 0x8130, 0x8137, 0x57A8}, + {0x8139, 0x8139, 0x8139, 0x57B0}, {0x8139, 0x8230, 0x8239, 0x57B1}, + {0x8139, 0x8330, 0x8339, 0x57BB}, {0x8139, 0x8430, 0x8439, 0x57C5}, + {0x8139, 0x8530, 0x8539, 0x57CF}, {0x8139, 0x8630, 0x8639, 0x57D9}, + {0x8139, 0x8730, 0x8739, 0x57E3}, {0x8139, 0x8830, 0x8839, 0x57ED}, + {0x8139, 0x8930, 0x8939, 0x57F7}, {0x8139, 0x8B32, 0x8B32, 0x1042}, + {0x8139, 0x8B33, 0x8B33, 0x1263}, {0x8139, 0x8B34, 0x8B34, 0x1272}, + {0x8139, 0x8B35, 0x8B35, 0x1265}, {0x8139, 0x8B36, 0x8B36, 0x1059}, + {0x8139, 0x8B37, 0x8B37, 0x2793}, {0x8139, 0x8B38, 0x8B38, 0x063D}, + {0x8139, 0x8B39, 0x8B39, 0x1303}, {0x8139, 0x8C30, 0x8C30, 0x0CA6}, + {0x8139, 0x8C31, 0x8C31, 0x0638}, {0x8139, 0x8C32, 0x8C32, 0x0CC6}, + {0x8139, 0x8C33, 0x8C33, 0x03D6}, {0x8139, 0x8C34, 0x8C34, 0x129D}, + {0x8139, 0x8C35, 0x8C35, 0x1314}, {0x8139, 0x8C36, 0x8C36, 0x130F}, + {0x8139, 0x8C37, 0x8C37, 0x082B}, {0x8139, 0x8C38, 0x8C38, 0x1399}, + {0x8139, 0x8C39, 0x8C39, 0x0597}, {0x8139, 0x8D30, 0x8D30, 0x09EF}, + {0x8139, 0x8D31, 0x8D31, 0x12FC}, {0x8139, 0x8D32, 0x8D32, 0x1266}, + {0x8139, 0x8D33, 0x8D33, 0x1284}, {0x8139, 0x8D34, 0x8D34, 0x2A1A}, + {0x8139, 0x8D35, 0x8D35, 0x0D45}, {0x8139, 0x8D36, 0x8D36, 0x047E}, + {0x8139, 0x8D37, 0x8D37, 0x1352}, {0x8139, 0x8D38, 0x8D38, 0x04CC}, + {0x8139, 0x8D39, 0x8D39, 0x139C}, {0x8139, 0x8E30, 0x8E30, 0x10BB}, + {0x8139, 0x8E31, 0x8E31, 0x0967}, {0x8139, 0x8E32, 0x8E32, 0x1593}, + {0x8139, 0x8E33, 0x8E33, 0x0E72}, {0x8139, 0x8E34, 0x8E34, 0x0D56}, + {0x8139, 0x8E35, 0x8E35, 0x161C}, {0x8139, 0x8E36, 0x8E36, 0x2D2D}, + {0x8139, 0x8E37, 0x8E37, 0x0F13}, {0x8139, 0x8E38, 0x8E38, 0x0576}, + {0x8139, 0x8E39, 0x8E39, 0x0B6F}, {0x8139, 0x8F30, 0x8F30, 0x1230}, + {0x8139, 0x8F31, 0x8F31, 0x172E}, {0x8139, 0x8F32, 0x8F32, 0x056A}, + {0x8139, 0x8F33, 0x8F33, 0x0F6C}, {0x8139, 0x8F34, 0x8F34, 0x14B6}, + {0x8139, 0x8F35, 0x8F35, 0x0D43}, {0x8139, 0x8F36, 0x8F36, 0x1774}, + {0x8139, 0x8F37, 0x8F37, 0x0CF6}, {0x8139, 0x8F38, 0x8F38, 0x1815}, + {0x8139, 0x8F39, 0x8F39, 0x06FD}, {0x8139, 0x9030, 0x9030, 0x082D}, + {0x8139, 0x9031, 0x9031, 0x08BE}, {0x8139, 0x9032, 0x9032, 0x06C4}, + {0x8139, 0x9033, 0x9033, 0x1813}, {0x8139, 0x9034, 0x9034, 0x073C}, + {0x8139, 0x9035, 0x9035, 0x1398}, {0x8139, 0x9036, 0x9036, 0x14AD}, + {0x8139, 0x9037, 0x9037, 0x14F6}, {0x8139, 0x9038, 0x9038, 0x0706}, + {0x8139, 0x9039, 0x9039, 0x1762}, {0x8139, 0x9130, 0x9130, 0x15EE}, + {0x8139, 0x9131, 0x9131, 0x15E0}, {0x8139, 0x9132, 0x9132, 0x0F8F}, + {0x8139, 0x9133, 0x9133, 0x06E5}, {0x8139, 0x9134, 0x9134, 0x3292}, + {0x8139, 0x9135, 0x9135, 0x0D6D}, {0x8139, 0x9136, 0x9136, 0x11A6}, + {0x8139, 0x9137, 0x9137, 0x1909}, {0x8139, 0x9138, 0x9138, 0x0ED3}, + {0x8139, 0x9139, 0x9139, 0x05F6}, {0x8139, 0x9230, 0x9230, 0x08C0}, + {0x8139, 0x9231, 0x9231, 0x065A}, {0x8139, 0x9232, 0x9232, 0x0EED}, + {0x8139, 0x9233, 0x9233, 0x0CB0}, {0x8139, 0x9234, 0x9234, 0x10FE}, + {0x8139, 0x9235, 0x9235, 0x1105}, {0x8139, 0x9236, 0x9236, 0x0B21}, + {0x8139, 0x9237, 0x9237, 0x0C34}, {0x8139, 0x9238, 0x9238, 0x11B8}, + {0x8139, 0x9239, 0x9239, 0x0578}, {0x8139, 0x9330, 0x9330, 0x19BD}, + {0x8139, 0x9331, 0x9331, 0x0EF2}, {0x8139, 0x9332, 0x9332, 0x0431}, + {0x8139, 0x9333, 0x9333, 0x0AB0}, {0x8139, 0x9334, 0x9334, 0x0D66}, + {0x8139, 0x9335, 0x9335, 0x0C17}, {0x8139, 0x9336, 0x9336, 0x0DA3}, + {0x8139, 0x9337, 0x9337, 0x0805}, {0x8139, 0x9338, 0x9338, 0x1203}, + {0x8139, 0x9339, 0x9339, 0x06B3}, {0x8139, 0x9430, 0x9430, 0x1269}, + {0x8139, 0x9431, 0x9431, 0x169D}, {0x8139, 0x9432, 0x9432, 0x0BCB}, + {0x8139, 0x9433, 0x9433, 0x0FE9}, {0x8139, 0x9434, 0x9434, 0x0B64}, + {0x8139, 0x9435, 0x9435, 0x0C89}, {0x8139, 0x9436, 0x9436, 0x0FC9}, + {0x8139, 0x9437, 0x9437, 0x10D6}, {0x8139, 0x9438, 0x9438, 0x0728}, + {0x8139, 0x9439, 0x9439, 0x0E90}, {0x8139, 0x9530, 0x9530, 0x06C5}, + {0x8139, 0x9531, 0x9531, 0x0D33}, {0x8139, 0x9532, 0x9532, 0x10A8}, + {0x8139, 0x9533, 0x9533, 0x0E42}, {0x8139, 0x9534, 0x9534, 0x1BC6}, + {0x8139, 0x9535, 0x9535, 0x1B60}, {0x8139, 0x9536, 0x9536, 0x3EBF}, + {0x8139, 0x9537, 0x9537, 0x03E2}, {0x8139, 0x9538, 0x9538, 0x0BC3}, + {0x8139, 0x9539, 0x9539, 0x0AF8}, {0x8139, 0x9630, 0x9630, 0x0B22}, + {0x8139, 0x9631, 0x9631, 0x0AB1}, {0x8139, 0x9632, 0x9632, 0x0D4F}, + {0x8139, 0x9633, 0x9633, 0x0D46}, {0x8139, 0x9634, 0x9634, 0x0D55}, + {0x8139, 0x9635, 0x9635, 0x40CB}, {0x8139, 0x9636, 0x9636, 0x0783}, + {0x8139, 0x9637, 0x9637, 0x0FD1}, {0x8139, 0x9638, 0x9638, 0x09EB}, + {0x8139, 0x9639, 0x9639, 0x11F0}, {0x8139, 0x9730, 0x9730, 0x0ADC}, + {0x8139, 0x9731, 0x9731, 0x1CE7}, {0x8139, 0x9732, 0x9732, 0x1C5E}, + {0x8139, 0x9733, 0x9733, 0x0EA9}, {0x8139, 0x9734, 0x9734, 0x101B}, + {0x8139, 0x9735, 0x9735, 0x10D5}, {0x8139, 0x9736, 0x9736, 0x09BA}, + {0x8139, 0x9737, 0x9737, 0x0637}, {0x8139, 0x9738, 0x9738, 0x1BCB}, + {0x8139, 0x9739, 0x9739, 0x0639}, {0x8139, 0x9830, 0x9830, 0x1A1E}, + {0x8139, 0x9831, 0x9831, 0x0CBD}, {0x8139, 0x9832, 0x9832, 0x04E1}, + {0x8139, 0x9833, 0x9833, 0x1231}, {0x8139, 0x9834, 0x9834, 0x11C0}, + {0x8139, 0x9835, 0x9835, 0x08F9}, {0x8139, 0x9836, 0x9836, 0x0D19}, + {0x8139, 0x9837, 0x9837, 0x1618}, {0x8139, 0x9838, 0x9838, 0x11DA}, + {0x8139, 0x9839, 0x9839, 0x1CDC}, {0x8139, 0x9930, 0x9930, 0x0CE4}, + {0x8139, 0x9931, 0x9931, 0x45A2}, {0x8139, 0x9932, 0x9932, 0x1BF0}, + {0x8139, 0x9933, 0x9933, 0x050B}, {0x8139, 0x9934, 0x9934, 0x0FD3}, + {0x8139, 0x9935, 0x9935, 0x0F9B}, {0x8139, 0x9936, 0x9936, 0x1049}, + {0x8139, 0x9937, 0x9937, 0x49DC}, {0x8139, 0x9938, 0x9938, 0x1F96}, + {0x8139, 0x9939, 0x9939, 0x0898}, {0x8139, 0x9A30, 0x9A30, 0x0FFD}, + {0x8139, 0x9A31, 0x9A31, 0x0721}, {0x8139, 0x9A32, 0x9A32, 0x05F8}, + {0x8139, 0x9A33, 0x9A33, 0x1D15}, {0x8139, 0x9A34, 0x9A34, 0x1D50}, + {0x8139, 0x9A35, 0x9A35, 0x1E3B}, {0x8139, 0x9A36, 0x9A36, 0x0505}, + {0x8139, 0x9A37, 0x9A37, 0x123C}, {0x8139, 0x9A38, 0x9A38, 0x1240}, + {0x8139, 0x9A39, 0x9A39, 0x0D26}, {0x8139, 0x9B30, 0x9B30, 0x1E7B}, + {0x8139, 0x9B31, 0x9B31, 0x0F8C}, {0x8139, 0x9B32, 0x9B32, 0x04E2}, + {0x8139, 0x9B33, 0x9B33, 0x4D13}, {0x8139, 0x9B34, 0x9B34, 0x105F}, + {0x8139, 0x9B35, 0x9B35, 0x10B4}, {0x8139, 0x9B36, 0x9B36, 0x4E18}, + {0x8139, 0x9B37, 0x9B37, 0x09DA}, {0x8139, 0x9B38, 0x9B38, 0x08C1}, + {0x8139, 0x9B39, 0x9B39, 0x1E75}, {0x8139, 0x9C30, 0x9C30, 0x207D}, + {0x8139, 0x9C31, 0x9C31, 0x06B2}, {0x8139, 0x9C32, 0x9C32, 0x09EE}, + {0x8139, 0x9C33, 0x9C33, 0x1D79}, {0x8139, 0x9C34, 0x9C34, 0x10CF}, + {0x8139, 0x9C35, 0x9C35, 0x50EA}, {0x8139, 0x9C36, 0x9C36, 0x0664}, + {0x8139, 0x9C37, 0x9C37, 0x0AEB}, {0x8139, 0x9C38, 0x9C38, 0x06EA}, + {0x8139, 0x9C39, 0x9C39, 0x218D}, {0x8139, 0x9D30, 0x9D30, 0x08F1}, + {0x8139, 0x9D31, 0x9D31, 0x107B}, {0x8139, 0x9D32, 0x9D32, 0x2209}, + {0x8139, 0x9D33, 0x9D33, 0x1F00}, {0x8139, 0x9D34, 0x9D34, 0x1EF4}, + {0x8139, 0x9D35, 0x9D35, 0x0D4A}, {0x8139, 0x9D36, 0x9D36, 0x0D6E}, + {0x8139, 0x9D37, 0x9D37, 0x0F50}, {0x8139, 0x9D38, 0x9D38, 0x206D}, + {0x8139, 0x9D39, 0x9D39, 0x0720}, {0x8139, 0x9E30, 0x9E30, 0x06DA}, + {0x8139, 0x9E31, 0x9E31, 0x1DEC}, {0x8139, 0x9E32, 0x9E32, 0x1ED0}, + {0x8139, 0x9E33, 0x9E33, 0x139B}, {0x8139, 0x9E34, 0x9E34, 0x1260}, + {0x8139, 0x9E35, 0x9E35, 0x0746}, {0x8139, 0x9E36, 0x9E36, 0x2239}, + {0x8139, 0x9E37, 0x9E37, 0x209C}, {0x8139, 0x9E38, 0x9E38, 0x2688}, + {0x8139, 0x9E39, 0x9E39, 0x0A60}, {0x8139, 0x9F30, 0x9F30, 0x2071}, + {0x8139, 0x9F31, 0x9F31, 0x0A90}, {0x8139, 0x9F32, 0x9F32, 0x5586}, + {0x8139, 0x9F33, 0x9F33, 0x0D89}, {0x8139, 0x9F34, 0x9F34, 0x0791}, + {0x8139, 0x9F35, 0x9F35, 0x1A55}, {0x8139, 0x9F36, 0x9F36, 0x2618}, + {0x8139, 0x9F37, 0x9F37, 0x05E5}, {0x8139, 0x9F38, 0x9F38, 0x071D}, + {0x8139, 0x9F39, 0x9F39, 0x0D8A}, {0x8139, 0xA030, 0xA030, 0x0430}, + {0x8139, 0xA031, 0xA031, 0x20C6}, {0x8139, 0xA032, 0xA032, 0x1E86}, + {0x8139, 0xA033, 0xA033, 0x2037}, {0x8139, 0xA034, 0xA034, 0x1F34}, + {0x8139, 0xA035, 0xA035, 0x12F3}, {0x8139, 0xA533, 0xA535, 0x577B}, + {0x8139, 0xA538, 0xA539, 0x577E}, {0x8139, 0xA630, 0xA630, 0x5780}, + {0x8139, 0xA634, 0xA634, 0x5755}, {0x8139, 0xA636, 0xA636, 0x5767}, + {0x8139, 0xA735, 0xA735, 0x5776}, {0x8139, 0xA736, 0xA736, 0x5778}, + {0x8139, 0xA737, 0xA737, 0x5777}, {0x8139, 0xA738, 0xA738, 0x5779}, + {0x8139, 0xA836, 0xA838, 0x5781}, {0x8139, 0xB434, 0xB439, 0x5784}, + {0x8139, 0xB530, 0xB539, 0x578A}, {0x8139, 0xB630, 0xB637, 0x5794}, + {0x8139, 0xEE39, 0xEE39, 0x5801}, {0x8139, 0xEF30, 0xEF39, 0x5802}, + {0x8139, 0xF030, 0xF039, 0x580C}, {0x8139, 0xF130, 0xF139, 0x5816}, + {0x8139, 0xF230, 0xF239, 0x5820}, {0x8139, 0xF330, 0xF339, 0x582A}, + {0x8139, 0xF430, 0xF439, 0x5834}, {0x8139, 0xF530, 0xF539, 0x583E}, + {0x8139, 0xF630, 0xF639, 0x5848}, {0x8139, 0xF730, 0xF739, 0x5852}, + {0x8139, 0xF830, 0xF839, 0x585C}, {0x8139, 0xF930, 0xF939, 0x5866}, + {0x8139, 0xFA30, 0xFA39, 0x5870}, {0x8139, 0xFB30, 0xFB39, 0x587A}, + {0x8139, 0xFC30, 0xFC39, 0x5884}, {0x8139, 0xFD30, 0xFD39, 0x588E}, + {0x8139, 0xFE30, 0xFE39, 0x5898}, {0x8230, 0x8130, 0x8139, 0x58A2}, + {0x8230, 0x8230, 0x8239, 0x58AC}, {0x8230, 0x8330, 0x8339, 0x58B6}, + {0x8230, 0x8430, 0x8439, 0x58C0}, {0x8230, 0x8530, 0x8539, 0x58CA}, + {0x8230, 0x8630, 0x8639, 0x58D4}, {0x8230, 0x8730, 0x8739, 0x58DE}, + {0x8230, 0x8830, 0x8839, 0x58E8}, {0x8230, 0x8930, 0x8939, 0x58F2}, + {0x8230, 0x8A30, 0x8A39, 0x58FC}, {0x8230, 0x8B30, 0x8B39, 0x5906}, + {0x8230, 0x8C30, 0x8C39, 0x5910}, {0x8230, 0x8D30, 0x8D39, 0x591A}, + {0x8230, 0x8E30, 0x8E39, 0x5924}, {0x8230, 0x8F30, 0x8F39, 0x592E}, + {0x8230, 0x9030, 0x9039, 0x5938}, {0x8230, 0x9130, 0x9139, 0x5942}, + {0x8230, 0x9230, 0x9239, 0x594C}, {0x8230, 0x9330, 0x9339, 0x5956}, + {0x8230, 0x9430, 0x9439, 0x5960}, {0x8230, 0x9530, 0x9539, 0x596A}, + {0x8230, 0x9630, 0x9639, 0x5974}, {0x8230, 0x9730, 0x9739, 0x597E}, + {0x8230, 0x9830, 0x9839, 0x5988}, {0x8230, 0x9930, 0x9939, 0x5992}, + {0x8230, 0x9A30, 0x9A39, 0x599C}, {0x8230, 0x9B30, 0x9B39, 0x59A6}, + {0x8230, 0x9C30, 0x9C39, 0x59B0}, {0x8230, 0x9D30, 0x9D39, 0x59BA}, + {0x8230, 0x9E30, 0x9E39, 0x59C4}, {0x8230, 0x9F30, 0x9F39, 0x59CE}, + {0x8230, 0xA030, 0xA039, 0x59D8}, {0x8230, 0xA130, 0xA139, 0x59E2}, + {0x8230, 0xA230, 0xA239, 0x59EC}, {0x8230, 0xA330, 0xA339, 0x59F6}, + {0x8230, 0xA430, 0xA439, 0x5A00}, {0x8230, 0xA530, 0xA539, 0x5A0A}, + {0x8230, 0xA630, 0xA639, 0x5A14}, {0x8230, 0xA730, 0xA739, 0x5A1E}, + {0x8230, 0xA830, 0xA839, 0x5A28}, {0x8230, 0xA930, 0xA939, 0x5A32}, + {0x8230, 0xAA30, 0xAA39, 0x5A3C}, {0x8230, 0xAB30, 0xAB39, 0x5A46}, + {0x8230, 0xAC30, 0xAC39, 0x5A50}, {0x8230, 0xAD30, 0xAD39, 0x5A5A}, + {0x8230, 0xAE30, 0xAE39, 0x5A64}, {0x8230, 0xAF30, 0xAF39, 0x5A6E}, + {0x8230, 0xB030, 0xB039, 0x5A78}, {0x8230, 0xB130, 0xB139, 0x5A82}, + {0x8230, 0xB230, 0xB239, 0x5A8C}, {0x8230, 0xB330, 0xB339, 0x5A96}, + {0x8230, 0xB430, 0xB439, 0x5AA0}, {0x8230, 0xB530, 0xB539, 0x5AAA}, + {0x8230, 0xB630, 0xB639, 0x5AB4}, {0x8230, 0xB730, 0xB739, 0x5ABE}, + {0x8230, 0xB830, 0xB839, 0x5AC8}, {0x8230, 0xB930, 0xB939, 0x5AD2}, + {0x8230, 0xBA30, 0xBA39, 0x5ADC}, {0x8230, 0xBB30, 0xBB39, 0x5AE6}, + {0x8230, 0xBC30, 0xBC39, 0x5AF0}, {0x8230, 0xBD30, 0xBD39, 0x5AFA}, + {0x8230, 0xBE30, 0xBE39, 0x5B04}, {0x8230, 0xBF30, 0xBF39, 0x5B0E}, + {0x8230, 0xC030, 0xC039, 0x5B18}, {0x8230, 0xC130, 0xC139, 0x5B22}, + {0x8230, 0xC230, 0xC239, 0x5B2C}, {0x8230, 0xC330, 0xC339, 0x5B36}, + {0x8230, 0xC430, 0xC439, 0x5B40}, {0x8230, 0xC530, 0xC539, 0x5B4A}, + {0x8230, 0xC630, 0xC639, 0x5B54}, {0x8230, 0xC730, 0xC739, 0x5B5E}, + {0x8230, 0xC830, 0xC839, 0x5B68}, {0x8230, 0xC930, 0xC939, 0x5B72}, + {0x8230, 0xCA30, 0xCA39, 0x5B7C}, {0x8230, 0xCB30, 0xCB39, 0x5B86}, + {0x8230, 0xCC30, 0xCC39, 0x5B90}, {0x8230, 0xCD30, 0xCD39, 0x5B9A}, + {0x8230, 0xCE30, 0xCE39, 0x5BA4}, {0x8230, 0xCF30, 0xCF39, 0x5BAE}, + {0x8230, 0xD030, 0xD039, 0x5BB8}, {0x8230, 0xD130, 0xD139, 0x5BC2}, + {0x8230, 0xD230, 0xD239, 0x5BCC}, {0x8230, 0xD330, 0xD339, 0x5BD6}, + {0x8230, 0xD430, 0xD439, 0x5BE0}, {0x8230, 0xD530, 0xD539, 0x5BEA}, + {0x8230, 0xD630, 0xD639, 0x5BF4}, {0x8230, 0xD730, 0xD739, 0x5BFE}, + {0x8230, 0xD830, 0xD839, 0x5C08}, {0x8230, 0xD930, 0xD939, 0x5C12}, + {0x8230, 0xDA30, 0xDA39, 0x5C1C}, {0x8230, 0xDB30, 0xDB39, 0x5C26}, + {0x8230, 0xDC30, 0xDC39, 0x5C30}, {0x8230, 0xDD30, 0xDD39, 0x5C3A}, + {0x8230, 0xDE30, 0xDE39, 0x5C44}, {0x8230, 0xDF30, 0xDF39, 0x5C4E}, + {0x8230, 0xE030, 0xE039, 0x5C58}, {0x8230, 0xE130, 0xE139, 0x5C62}, + {0x8230, 0xE230, 0xE239, 0x5C6C}, {0x8230, 0xE330, 0xE339, 0x5C76}, + {0x8230, 0xE430, 0xE439, 0x5C80}, {0x8230, 0xE530, 0xE539, 0x5C8A}, + {0x8230, 0xE630, 0xE639, 0x5C94}, {0x8230, 0xE730, 0xE739, 0x5C9E}, + {0x8230, 0xE830, 0xE839, 0x5CA8}, {0x8230, 0xE930, 0xE939, 0x5CB2}, + {0x8230, 0xEA30, 0xEA39, 0x5CBC}, {0x8230, 0xEB30, 0xEB39, 0x5CC6}, + {0x8230, 0xEC30, 0xEC39, 0x5CD0}, {0x8230, 0xED30, 0xED39, 0x5CDA}, + {0x8230, 0xEE30, 0xEE39, 0x5CE4}, {0x8230, 0xEF30, 0xEF39, 0x5CEE}, + {0x8230, 0xF030, 0xF039, 0x5CF8}, {0x8230, 0xF130, 0xF139, 0x5D02}, + {0x8230, 0xF230, 0xF239, 0x5D0C}, {0x8230, 0xF330, 0xF339, 0x5D16}, + {0x8230, 0xF430, 0xF439, 0x5D20}, {0x8230, 0xF530, 0xF539, 0x5D2A}, + {0x8230, 0xF630, 0xF639, 0x5D34}, {0x8230, 0xF730, 0xF739, 0x5D3E}, + {0x8230, 0xF830, 0xF839, 0x5D48}, {0x8230, 0xF930, 0xF939, 0x5D52}, + {0x8230, 0xFA30, 0xFA39, 0x5D5C}, {0x8230, 0xFB30, 0xFB39, 0x5D66}, + {0x8230, 0xFC30, 0xFC39, 0x5D70}, {0x8230, 0xFD30, 0xFD39, 0x5D7A}, + {0x8230, 0xFE30, 0xFE39, 0x5D84}, {0x8231, 0x8130, 0x8139, 0x5D8E}, + {0x8231, 0x8230, 0x8239, 0x5D98}, {0x8231, 0x8330, 0x8339, 0x5DA2}, + {0x8231, 0x8430, 0x8439, 0x5DAC}, {0x8231, 0x8530, 0x8539, 0x5DB6}, + {0x8231, 0x8630, 0x8639, 0x5DC0}, {0x8231, 0x8730, 0x8739, 0x5DCA}, + {0x8231, 0x8830, 0x8839, 0x5DD4}, {0x8231, 0x8930, 0x8939, 0x5DDE}, + {0x8231, 0x8A30, 0x8A39, 0x5DE8}, {0x8231, 0x8B30, 0x8B39, 0x5DF2}, + {0x8231, 0x8C30, 0x8C39, 0x5DFC}, {0x8231, 0x8D30, 0x8D39, 0x5E06}, + {0x8231, 0x8E30, 0x8E39, 0x5E10}, {0x8231, 0x8F30, 0x8F39, 0x5E1A}, + {0x8231, 0x9030, 0x9039, 0x5E24}, {0x8231, 0x9130, 0x9139, 0x5E2E}, + {0x8231, 0x9230, 0x9239, 0x5E38}, {0x8231, 0x9330, 0x9339, 0x5E42}, + {0x8231, 0x9430, 0x9439, 0x5E4C}, {0x8231, 0x9530, 0x9539, 0x5E56}, + {0x8231, 0x9630, 0x9639, 0x5E60}, {0x8231, 0x9730, 0x9739, 0x5E6A}, + {0x8231, 0x9830, 0x9839, 0x5E74}, {0x8231, 0x9930, 0x9939, 0x5E7E}, + {0x8231, 0x9A30, 0x9A39, 0x5E88}, {0x8231, 0x9B30, 0x9B39, 0x5E92}, + {0x8231, 0x9C30, 0x9C39, 0x5E9C}, {0x8231, 0x9D30, 0x9D39, 0x5EA6}, + {0x8231, 0x9E30, 0x9E39, 0x5EB0}, {0x8231, 0x9F30, 0x9F39, 0x5EBA}, + {0x8231, 0xA030, 0xA039, 0x5EC4}, {0x8231, 0xA130, 0xA139, 0x5ECE}, + {0x8231, 0xA230, 0xA239, 0x5ED8}, {0x8231, 0xA330, 0xA339, 0x5EE2}, + {0x8231, 0xA430, 0xA439, 0x5EEC}, {0x8231, 0xA530, 0xA539, 0x5EF6}, + {0x8231, 0xA630, 0xA639, 0x5F00}, {0x8231, 0xA730, 0xA739, 0x5F0A}, + {0x8231, 0xA830, 0xA839, 0x5F14}, {0x8231, 0xA930, 0xA939, 0x5F1E}, + {0x8231, 0xAA30, 0xAA39, 0x5F28}, {0x8231, 0xAB30, 0xAB39, 0x5F32}, + {0x8231, 0xAC30, 0xAC39, 0x5F3C}, {0x8231, 0xAD30, 0xAD39, 0x5F46}, + {0x8231, 0xAE30, 0xAE39, 0x5F50}, {0x8231, 0xAF30, 0xAF39, 0x5F5A}, + {0x8231, 0xB030, 0xB039, 0x5F64}, {0x8231, 0xB130, 0xB139, 0x5F6E}, + {0x8231, 0xB230, 0xB239, 0x5F78}, {0x8231, 0xB330, 0xB339, 0x5F82}, + {0x8231, 0xB430, 0xB439, 0x5F8C}, {0x8231, 0xB530, 0xB539, 0x5F96}, + {0x8231, 0xB630, 0xB639, 0x5FA0}, {0x8231, 0xB730, 0xB739, 0x5FAA}, + {0x8231, 0xB830, 0xB839, 0x5FB4}, {0x8231, 0xB930, 0xB939, 0x5FBE}, + {0x8231, 0xBA30, 0xBA39, 0x5FC8}, {0x8231, 0xBB30, 0xBB39, 0x5FD2}, + {0x8231, 0xBC30, 0xBC39, 0x5FDC}, {0x8231, 0xBD30, 0xBD39, 0x5FE6}, + {0x8231, 0xBE30, 0xBE39, 0x5FF0}, {0x8231, 0xBF30, 0xBF39, 0x5FFA}, + {0x8231, 0xC030, 0xC039, 0x6004}, {0x8231, 0xC130, 0xC139, 0x600E}, + {0x8231, 0xC230, 0xC239, 0x6018}, {0x8231, 0xC330, 0xC339, 0x6022}, + {0x8231, 0xC430, 0xC439, 0x602C}, {0x8231, 0xC530, 0xC539, 0x6036}, + {0x8231, 0xC630, 0xC639, 0x6040}, {0x8231, 0xC730, 0xC739, 0x604A}, + {0x8231, 0xC830, 0xC839, 0x6054}, {0x8231, 0xC930, 0xC939, 0x605E}, + {0x8231, 0xCA30, 0xCA39, 0x6068}, {0x8231, 0xCB30, 0xCB39, 0x6072}, + {0x8231, 0xCC30, 0xCC39, 0x607C}, {0x8231, 0xCD30, 0xCD39, 0x6086}, + {0x8231, 0xCE30, 0xCE39, 0x6090}, {0x8231, 0xCF30, 0xCF39, 0x609A}, + {0x8231, 0xD030, 0xD039, 0x60A4}, {0x8231, 0xD130, 0xD139, 0x60AE}, + {0x8231, 0xD230, 0xD239, 0x60B8}, {0x8231, 0xD330, 0xD339, 0x60C2}, + {0x8231, 0xD430, 0xD439, 0x60CC}, {0x8231, 0xD530, 0xD539, 0x60D6}, + {0x8231, 0xD630, 0xD639, 0x60E0}, {0x8231, 0xD730, 0xD739, 0x60EA}, + {0x8231, 0xD830, 0xD839, 0x60F4}, {0x8231, 0xD930, 0xD939, 0x60FE}, + {0x8231, 0xDA30, 0xDA39, 0x6108}, {0x8231, 0xDB30, 0xDB39, 0x6112}, + {0x8231, 0xDC30, 0xDC39, 0x611C}, {0x8231, 0xDD30, 0xDD39, 0x6126}, + {0x8231, 0xDE30, 0xDE39, 0x6130}, {0x8231, 0xDF30, 0xDF39, 0x613A}, + {0x8231, 0xE030, 0xE039, 0x6144}, {0x8231, 0xE130, 0xE139, 0x614E}, + {0x8231, 0xE230, 0xE239, 0x6158}, {0x8231, 0xE330, 0xE339, 0x6162}, + {0x8231, 0xE430, 0xE439, 0x616C}, {0x8231, 0xE530, 0xE539, 0x6176}, + {0x8231, 0xE630, 0xE639, 0x6180}, {0x8231, 0xE730, 0xE739, 0x618A}, + {0x8231, 0xE830, 0xE839, 0x6194}, {0x8231, 0xE930, 0xE939, 0x619E}, + {0x8231, 0xEA30, 0xEA39, 0x61A8}, {0x8231, 0xEB30, 0xEB39, 0x61B2}, + {0x8231, 0xEC30, 0xEC39, 0x61BC}, {0x8231, 0xED30, 0xED39, 0x61C6}, + {0x8231, 0xEE30, 0xEE39, 0x61D0}, {0x8231, 0xEF30, 0xEF39, 0x61DA}, + {0x8231, 0xF030, 0xF039, 0x61E4}, {0x8231, 0xF130, 0xF139, 0x61EE}, + {0x8231, 0xF230, 0xF239, 0x61F8}, {0x8231, 0xF330, 0xF339, 0x6202}, + {0x8231, 0xF430, 0xF439, 0x620C}, {0x8231, 0xF530, 0xF539, 0x6216}, + {0x8231, 0xF630, 0xF639, 0x6220}, {0x8231, 0xF730, 0xF739, 0x622A}, + {0x8231, 0xF830, 0xF839, 0x6234}, {0x8231, 0xF930, 0xF939, 0x623E}, + {0x8231, 0xFA30, 0xFA39, 0x6248}, {0x8231, 0xFB30, 0xFB39, 0x6252}, + {0x8231, 0xFC30, 0xFC39, 0x625C}, {0x8231, 0xFD30, 0xFD39, 0x6266}, + {0x8231, 0xFE30, 0xFE39, 0x6270}, {0x8232, 0x8130, 0x8139, 0x627A}, + {0x8232, 0x8230, 0x8239, 0x6284}, {0x8232, 0x8330, 0x8339, 0x628E}, + {0x8232, 0x8430, 0x8439, 0x6298}, {0x8232, 0x8530, 0x8539, 0x62A2}, + {0x8232, 0x8630, 0x8639, 0x62AC}, {0x8232, 0x8730, 0x8739, 0x62B6}, + {0x8232, 0x8830, 0x8839, 0x62C0}, {0x8232, 0x8930, 0x8939, 0x62CA}, + {0x8232, 0x8A30, 0x8A39, 0x62D4}, {0x8232, 0x8B30, 0x8B39, 0x62DE}, + {0x8232, 0x8C30, 0x8C39, 0x62E8}, {0x8232, 0x8D30, 0x8D39, 0x62F2}, + {0x8232, 0x8E30, 0x8E39, 0x62FC}, {0x8232, 0x8F30, 0x8F39, 0x6306}, + {0x8232, 0x9030, 0x9039, 0x6310}, {0x8232, 0x9130, 0x9139, 0x631A}, + {0x8232, 0x9230, 0x9239, 0x6324}, {0x8232, 0x9330, 0x9339, 0x632E}, + {0x8232, 0x9430, 0x9439, 0x6338}, {0x8232, 0x9530, 0x9539, 0x6342}, + {0x8232, 0x9630, 0x9639, 0x634C}, {0x8232, 0x9730, 0x9739, 0x6356}, + {0x8232, 0x9830, 0x9839, 0x6360}, {0x8232, 0x9930, 0x9939, 0x636A}, + {0x8232, 0x9A30, 0x9A39, 0x6374}, {0x8232, 0x9B30, 0x9B39, 0x637E}, + {0x8232, 0x9C30, 0x9C39, 0x6388}, {0x8232, 0x9D30, 0x9D39, 0x6392}, + {0x8232, 0x9E30, 0x9E39, 0x639C}, {0x8232, 0x9F30, 0x9F39, 0x63A6}, + {0x8232, 0xA030, 0xA039, 0x63B0}, {0x8232, 0xA130, 0xA139, 0x63BA}, + {0x8232, 0xA230, 0xA239, 0x63C4}, {0x8232, 0xA330, 0xA339, 0x63CE}, + {0x8232, 0xA430, 0xA439, 0x63D8}, {0x8232, 0xA530, 0xA539, 0x63E2}, + {0x8232, 0xA630, 0xA639, 0x63EC}, {0x8232, 0xA730, 0xA739, 0x63F6}, + {0x8232, 0xA830, 0xA839, 0x6400}, {0x8232, 0xA930, 0xA939, 0x640A}, + {0x8232, 0xAA30, 0xAA39, 0x6414}, {0x8232, 0xAB30, 0xAB39, 0x641E}, + {0x8232, 0xAC30, 0xAC39, 0x6428}, {0x8232, 0xAD30, 0xAD39, 0x6432}, + {0x8232, 0xAE30, 0xAE39, 0x643C}, {0x8232, 0xAF30, 0xAF39, 0x6446}, + {0x8232, 0xB030, 0xB039, 0x6450}, {0x8232, 0xB130, 0xB139, 0x645A}, + {0x8232, 0xB230, 0xB239, 0x6464}, {0x8232, 0xB330, 0xB339, 0x646E}, + {0x8232, 0xB430, 0xB439, 0x6478}, {0x8232, 0xB530, 0xB539, 0x6482}, + {0x8232, 0xB630, 0xB639, 0x648C}, {0x8232, 0xB730, 0xB739, 0x6496}, + {0x8232, 0xB830, 0xB839, 0x64A0}, {0x8232, 0xB930, 0xB939, 0x64AA}, + {0x8232, 0xBA30, 0xBA39, 0x64B4}, {0x8232, 0xBB30, 0xBB39, 0x64BE}, + {0x8232, 0xBC30, 0xBC39, 0x64C8}, {0x8232, 0xBD30, 0xBD39, 0x64D2}, + {0x8232, 0xBE30, 0xBE39, 0x64DC}, {0x8232, 0xBF30, 0xBF39, 0x64E6}, + {0x8232, 0xC030, 0xC039, 0x64F0}, {0x8232, 0xC130, 0xC139, 0x64FA}, + {0x8232, 0xC230, 0xC239, 0x6504}, {0x8232, 0xC330, 0xC339, 0x650E}, + {0x8232, 0xC430, 0xC439, 0x6518}, {0x8232, 0xC530, 0xC539, 0x6522}, + {0x8232, 0xC630, 0xC639, 0x652C}, {0x8232, 0xC730, 0xC739, 0x6536}, + {0x8232, 0xC830, 0xC839, 0x6540}, {0x8232, 0xC930, 0xC939, 0x654A}, + {0x8232, 0xCA30, 0xCA39, 0x6554}, {0x8232, 0xCB30, 0xCB39, 0x655E}, + {0x8232, 0xCC30, 0xCC39, 0x6568}, {0x8232, 0xCD30, 0xCD39, 0x6572}, + {0x8232, 0xCE30, 0xCE39, 0x657C}, {0x8232, 0xCF30, 0xCF39, 0x6586}, + {0x8232, 0xD030, 0xD039, 0x6590}, {0x8232, 0xD130, 0xD139, 0x659A}, + {0x8232, 0xD230, 0xD239, 0x65A4}, {0x8232, 0xD330, 0xD339, 0x65AE}, + {0x8232, 0xD430, 0xD439, 0x65B8}, {0x8232, 0xD530, 0xD539, 0x65C2}, + {0x8232, 0xD630, 0xD639, 0x65CC}, {0x8232, 0xD730, 0xD739, 0x65D6}, + {0x8232, 0xD830, 0xD839, 0x65E0}, {0x8232, 0xD930, 0xD939, 0x65EA}, + {0x8232, 0xDA30, 0xDA39, 0x65F4}, {0x8232, 0xDB30, 0xDB39, 0x65FE}, + {0x8232, 0xDC30, 0xDC39, 0x6608}, {0x8232, 0xDD30, 0xDD39, 0x6612}, + {0x8232, 0xDE30, 0xDE39, 0x661C}, {0x8232, 0xDF30, 0xDF39, 0x6626}, + {0x8232, 0xE030, 0xE039, 0x6630}, {0x8232, 0xE130, 0xE139, 0x663A}, + {0x8232, 0xE230, 0xE239, 0x6644}, {0x8232, 0xE330, 0xE339, 0x664E}, + {0x8232, 0xE430, 0xE439, 0x6658}, {0x8232, 0xE530, 0xE539, 0x6662}, + {0x8232, 0xE630, 0xE639, 0x666C}, {0x8232, 0xE730, 0xE739, 0x6676}, + {0x8232, 0xE830, 0xE839, 0x6680}, {0x8232, 0xE930, 0xE939, 0x668A}, + {0x8232, 0xEA30, 0xEA39, 0x6694}, {0x8232, 0xEB30, 0xEB39, 0x669E}, + {0x8232, 0xEC30, 0xEC39, 0x66A8}, {0x8232, 0xED30, 0xED39, 0x66B2}, + {0x8232, 0xEE30, 0xEE39, 0x66BC}, {0x8232, 0xEF30, 0xEF39, 0x66C6}, + {0x8232, 0xF030, 0xF039, 0x66D0}, {0x8232, 0xF130, 0xF139, 0x66DA}, + {0x8232, 0xF230, 0xF239, 0x66E4}, {0x8232, 0xF330, 0xF339, 0x66EE}, + {0x8232, 0xF430, 0xF439, 0x66F8}, {0x8232, 0xF530, 0xF539, 0x6702}, + {0x8232, 0xF630, 0xF639, 0x670C}, {0x8232, 0xF730, 0xF739, 0x6716}, + {0x8232, 0xF830, 0xF839, 0x6720}, {0x8232, 0xF930, 0xF939, 0x672A}, + {0x8232, 0xFA30, 0xFA39, 0x6734}, {0x8232, 0xFB30, 0xFB39, 0x673E}, + {0x8232, 0xFC30, 0xFC39, 0x6748}, {0x8232, 0xFD30, 0xFD39, 0x6752}, + {0x8232, 0xFE30, 0xFE39, 0x675C}, {0x8233, 0x8130, 0x8139, 0x6766}, + {0x8233, 0x8230, 0x8239, 0x6770}, {0x8233, 0x8330, 0x8339, 0x677A}, + {0x8233, 0x8430, 0x8439, 0x6784}, {0x8233, 0x8530, 0x8539, 0x678E}, + {0x8233, 0x8630, 0x8639, 0x6798}, {0x8233, 0x8730, 0x8739, 0x67A2}, + {0x8233, 0x8830, 0x8839, 0x67AC}, {0x8233, 0x8930, 0x8939, 0x67B6}, + {0x8233, 0x8A30, 0x8A39, 0x67C0}, {0x8233, 0x8B30, 0x8B39, 0x67CA}, + {0x8233, 0x8C30, 0x8C39, 0x67D4}, {0x8233, 0x8D30, 0x8D39, 0x67DE}, + {0x8233, 0x8E30, 0x8E39, 0x67E8}, {0x8233, 0x8F30, 0x8F39, 0x67F2}, + {0x8233, 0x9030, 0x9039, 0x67FC}, {0x8233, 0x9130, 0x9139, 0x6806}, + {0x8233, 0x9230, 0x9239, 0x6810}, {0x8233, 0x9330, 0x9339, 0x681A}, + {0x8233, 0x9430, 0x9439, 0x6824}, {0x8233, 0x9530, 0x9539, 0x682E}, + {0x8233, 0x9630, 0x9639, 0x6838}, {0x8233, 0x9730, 0x9739, 0x6842}, + {0x8233, 0x9830, 0x9839, 0x684C}, {0x8233, 0x9930, 0x9939, 0x6856}, + {0x8233, 0x9A30, 0x9A39, 0x6860}, {0x8233, 0x9B30, 0x9B39, 0x686A}, + {0x8233, 0x9C30, 0x9C39, 0x6874}, {0x8233, 0x9D30, 0x9D39, 0x687E}, + {0x8233, 0x9E30, 0x9E39, 0x6888}, {0x8233, 0x9F30, 0x9F39, 0x6892}, + {0x8233, 0xA030, 0xA039, 0x689C}, {0x8233, 0xA130, 0xA139, 0x68A6}, + {0x8233, 0xA230, 0xA239, 0x68B0}, {0x8233, 0xA330, 0xA339, 0x68BA}, + {0x8233, 0xA430, 0xA439, 0x68C4}, {0x8233, 0xA530, 0xA539, 0x68CE}, + {0x8233, 0xA630, 0xA639, 0x68D8}, {0x8233, 0xA730, 0xA739, 0x68E2}, + {0x8233, 0xA830, 0xA839, 0x68EC}, {0x8233, 0xA930, 0xA939, 0x68F6}, + {0x8233, 0xAA30, 0xAA39, 0x6900}, {0x8233, 0xAB30, 0xAB39, 0x690A}, + {0x8233, 0xAC30, 0xAC39, 0x6914}, {0x8233, 0xAD30, 0xAD39, 0x691E}, + {0x8233, 0xAE30, 0xAE39, 0x6928}, {0x8233, 0xAF30, 0xAF39, 0x6932}, + {0x8233, 0xB030, 0xB039, 0x693C}, {0x8233, 0xB130, 0xB139, 0x6946}, + {0x8233, 0xB230, 0xB239, 0x6950}, {0x8233, 0xB330, 0xB339, 0x695A}, + {0x8233, 0xB430, 0xB439, 0x6964}, {0x8233, 0xB530, 0xB539, 0x696E}, + {0x8233, 0xB630, 0xB639, 0x6978}, {0x8233, 0xB730, 0xB739, 0x6982}, + {0x8233, 0xB830, 0xB839, 0x698C}, {0x8233, 0xB930, 0xB939, 0x6996}, + {0x8233, 0xBA30, 0xBA39, 0x69A0}, {0x8233, 0xBB30, 0xBB39, 0x69AA}, + {0x8233, 0xBC30, 0xBC39, 0x69B4}, {0x8233, 0xBD30, 0xBD39, 0x69BE}, + {0x8233, 0xBE30, 0xBE39, 0x69C8}, {0x8233, 0xBF30, 0xBF39, 0x69D2}, + {0x8233, 0xC030, 0xC039, 0x69DC}, {0x8233, 0xC130, 0xC139, 0x69E6}, + {0x8233, 0xC230, 0xC239, 0x69F0}, {0x8233, 0xC330, 0xC339, 0x69FA}, + {0x8233, 0xC430, 0xC439, 0x6A04}, {0x8233, 0xC530, 0xC539, 0x6A0E}, + {0x8233, 0xC630, 0xC639, 0x6A18}, {0x8233, 0xC730, 0xC739, 0x6A22}, + {0x8233, 0xC830, 0xC839, 0x6A2C}, {0x8233, 0xC930, 0xC939, 0x6A36}, + {0x8233, 0xCA30, 0xCA39, 0x6A40}, {0x8233, 0xCB30, 0xCB39, 0x6A4A}, + {0x8233, 0xCC30, 0xCC39, 0x6A54}, {0x8233, 0xCD30, 0xCD39, 0x6A5E}, + {0x8233, 0xCE30, 0xCE39, 0x6A68}, {0x8233, 0xCF30, 0xCF39, 0x6A72}, + {0x8233, 0xD030, 0xD039, 0x6A7C}, {0x8233, 0xD130, 0xD139, 0x6A86}, + {0x8233, 0xD230, 0xD239, 0x6A90}, {0x8233, 0xD330, 0xD339, 0x6A9A}, + {0x8233, 0xD430, 0xD439, 0x6AA4}, {0x8233, 0xD530, 0xD539, 0x6AAE}, + {0x8233, 0xD630, 0xD639, 0x6AB8}, {0x8233, 0xD730, 0xD739, 0x6AC2}, + {0x8233, 0xD830, 0xD839, 0x6ACC}, {0x8233, 0xD930, 0xD939, 0x6AD6}, + {0x8233, 0xDA30, 0xDA39, 0x6AE0}, {0x8233, 0xDB30, 0xDB39, 0x6AEA}, + {0x8233, 0xDC30, 0xDC39, 0x6AF4}, {0x8233, 0xDD30, 0xDD39, 0x6AFE}, + {0x8233, 0xDE30, 0xDE39, 0x6B08}, {0x8233, 0xDF30, 0xDF39, 0x6B12}, + {0x8233, 0xE030, 0xE039, 0x6B1C}, {0x8233, 0xE130, 0xE139, 0x6B26}, + {0x8233, 0xE230, 0xE239, 0x6B30}, {0x8233, 0xE330, 0xE339, 0x6B3A}, + {0x8233, 0xE430, 0xE439, 0x6B44}, {0x8233, 0xE530, 0xE539, 0x6B4E}, + {0x8233, 0xE630, 0xE639, 0x6B58}, {0x8233, 0xE730, 0xE739, 0x6B62}, + {0x8233, 0xE830, 0xE839, 0x6B6C}, {0x8233, 0xE930, 0xE939, 0x6B76}, + {0x8233, 0xEA30, 0xEA39, 0x6B80}, {0x8233, 0xEB30, 0xEB39, 0x6B8A}, + {0x8233, 0xEC30, 0xEC39, 0x6B94}, {0x8233, 0xED30, 0xED39, 0x6B9E}, + {0x8233, 0xEE30, 0xEE39, 0x6BA8}, {0x8233, 0xEF30, 0xEF39, 0x6BB2}, + {0x8233, 0xF030, 0xF039, 0x6BBC}, {0x8233, 0xF130, 0xF139, 0x6BC6}, + {0x8233, 0xF230, 0xF239, 0x6BD0}, {0x8233, 0xF330, 0xF339, 0x6BDA}, + {0x8233, 0xF430, 0xF439, 0x6BE4}, {0x8233, 0xF530, 0xF539, 0x6BEE}, + {0x8233, 0xF630, 0xF639, 0x6BF8}, {0x8233, 0xF730, 0xF739, 0x6C02}, + {0x8233, 0xF830, 0xF839, 0x6C0C}, {0x8233, 0xF930, 0xF939, 0x6C16}, + {0x8233, 0xFA30, 0xFA39, 0x6C20}, {0x8233, 0xFB30, 0xFB39, 0x6C2A}, + {0x8233, 0xFC30, 0xFC39, 0x6C34}, {0x8233, 0xFD30, 0xFD39, 0x6C3E}, + {0x8233, 0xFE30, 0xFE39, 0x6C48}, {0x8234, 0x8130, 0x8139, 0x6C52}, + {0x8234, 0x8230, 0x8239, 0x6C5C}, {0x8234, 0x8330, 0x8339, 0x6C66}, + {0x8234, 0x8430, 0x8439, 0x6C70}, {0x8234, 0x8530, 0x8539, 0x6C7A}, + {0x8234, 0x8630, 0x8639, 0x6C84}, {0x8234, 0x8730, 0x8739, 0x6C8E}, + {0x8234, 0x8830, 0x8839, 0x6C98}, {0x8234, 0x8930, 0x8939, 0x6CA2}, + {0x8234, 0x8A30, 0x8A39, 0x6CAC}, {0x8234, 0x8B30, 0x8B39, 0x6CB6}, + {0x8234, 0x8C30, 0x8C39, 0x6CC0}, {0x8234, 0x8D30, 0x8D39, 0x6CCA}, + {0x8234, 0x8E30, 0x8E39, 0x6CD4}, {0x8234, 0x8F30, 0x8F39, 0x6CDE}, + {0x8234, 0x9030, 0x9039, 0x6CE8}, {0x8234, 0x9130, 0x9139, 0x6CF2}, + {0x8234, 0x9230, 0x9239, 0x6CFC}, {0x8234, 0x9330, 0x9339, 0x6D06}, + {0x8234, 0x9430, 0x9439, 0x6D10}, {0x8234, 0x9530, 0x9539, 0x6D1A}, + {0x8234, 0x9630, 0x9639, 0x6D24}, {0x8234, 0x9730, 0x9739, 0x6D2E}, + {0x8234, 0x9830, 0x9839, 0x6D38}, {0x8234, 0x9930, 0x9939, 0x6D42}, + {0x8234, 0x9A30, 0x9A39, 0x6D4C}, {0x8234, 0x9B30, 0x9B39, 0x6D56}, + {0x8234, 0x9C30, 0x9C39, 0x6D60}, {0x8234, 0x9D30, 0x9D39, 0x6D6A}, + {0x8234, 0x9E30, 0x9E39, 0x6D74}, {0x8234, 0x9F30, 0x9F39, 0x6D7E}, + {0x8234, 0xA030, 0xA039, 0x6D88}, {0x8234, 0xA130, 0xA139, 0x6D92}, + {0x8234, 0xA230, 0xA239, 0x6D9C}, {0x8234, 0xA330, 0xA339, 0x6DA6}, + {0x8234, 0xA430, 0xA439, 0x6DB0}, {0x8234, 0xA530, 0xA539, 0x6DBA}, + {0x8234, 0xA630, 0xA639, 0x6DC4}, {0x8234, 0xA730, 0xA739, 0x6DCE}, + {0x8234, 0xA830, 0xA839, 0x6DD8}, {0x8234, 0xA930, 0xA939, 0x6DE2}, + {0x8234, 0xAA30, 0xAA39, 0x6DEC}, {0x8234, 0xAB30, 0xAB39, 0x6DF6}, + {0x8234, 0xAC30, 0xAC39, 0x6E00}, {0x8234, 0xAD30, 0xAD39, 0x6E0A}, + {0x8234, 0xAE30, 0xAE39, 0x6E14}, {0x8234, 0xAF30, 0xAF39, 0x6E1E}, + {0x8234, 0xB030, 0xB039, 0x6E28}, {0x8234, 0xB130, 0xB139, 0x6E32}, + {0x8234, 0xB230, 0xB239, 0x6E3C}, {0x8234, 0xB330, 0xB339, 0x6E46}, + {0x8234, 0xB430, 0xB439, 0x6E50}, {0x8234, 0xB530, 0xB539, 0x6E5A}, + {0x8234, 0xB630, 0xB639, 0x6E64}, {0x8234, 0xB730, 0xB739, 0x6E6E}, + {0x8234, 0xB830, 0xB839, 0x6E78}, {0x8234, 0xB930, 0xB939, 0x6E82}, + {0x8234, 0xBA30, 0xBA39, 0x6E8C}, {0x8234, 0xBB30, 0xBB39, 0x6E96}, + {0x8234, 0xBC30, 0xBC39, 0x6EA0}, {0x8234, 0xBD30, 0xBD39, 0x6EAA}, + {0x8234, 0xBE30, 0xBE39, 0x6EB4}, {0x8234, 0xBF30, 0xBF39, 0x6EBE}, + {0x8234, 0xC030, 0xC039, 0x6EC8}, {0x8234, 0xC130, 0xC139, 0x6ED2}, + {0x8234, 0xC230, 0xC239, 0x6EDC}, {0x8234, 0xC330, 0xC339, 0x6EE6}, + {0x8234, 0xC430, 0xC439, 0x6EF0}, {0x8234, 0xC530, 0xC539, 0x6EFA}, + {0x8234, 0xC630, 0xC639, 0x6F04}, {0x8234, 0xC730, 0xC739, 0x6F0E}, + {0x8234, 0xC830, 0xC839, 0x6F18}, {0x8234, 0xC930, 0xC939, 0x6F22}, + {0x8234, 0xCA30, 0xCA39, 0x6F2C}, {0x8234, 0xCB30, 0xCB39, 0x6F36}, + {0x8234, 0xCC30, 0xCC39, 0x6F40}, {0x8234, 0xCD30, 0xCD39, 0x6F4A}, + {0x8234, 0xCE30, 0xCE39, 0x6F54}, {0x8234, 0xCF30, 0xCF39, 0x6F5E}, + {0x8234, 0xD030, 0xD039, 0x6F68}, {0x8234, 0xD130, 0xD139, 0x6F72}, + {0x8234, 0xD230, 0xD239, 0x6F7C}, {0x8234, 0xD330, 0xD339, 0x6F86}, + {0x8234, 0xD430, 0xD439, 0x6F90}, {0x8234, 0xD530, 0xD539, 0x6F9A}, + {0x8234, 0xD630, 0xD639, 0x6FA4}, {0x8234, 0xD730, 0xD739, 0x6FAE}, + {0x8234, 0xD830, 0xD839, 0x6FB8}, {0x8234, 0xD930, 0xD939, 0x6FC2}, + {0x8234, 0xDA30, 0xDA39, 0x6FCC}, {0x8234, 0xDB30, 0xDB39, 0x6FD6}, + {0x8234, 0xDC30, 0xDC39, 0x6FE0}, {0x8234, 0xDD30, 0xDD39, 0x6FEA}, + {0x8234, 0xDE30, 0xDE39, 0x6FF4}, {0x8234, 0xDF30, 0xDF39, 0x6FFE}, + {0x8234, 0xE030, 0xE039, 0x7008}, {0x8234, 0xE130, 0xE139, 0x7012}, + {0x8234, 0xE230, 0xE239, 0x701C}, {0x8234, 0xE330, 0xE339, 0x7026}, + {0x8234, 0xE430, 0xE439, 0x7030}, {0x8234, 0xE530, 0xE539, 0x703A}, + {0x8234, 0xE630, 0xE639, 0x7044}, {0x8234, 0xE730, 0xE739, 0x704E}, + {0x8234, 0xE830, 0xE839, 0x7058}, {0x8234, 0xE930, 0xE939, 0x7062}, + {0x8234, 0xEA30, 0xEA39, 0x706C}, {0x8234, 0xEB30, 0xEB39, 0x7076}, + {0x8234, 0xEC30, 0xEC39, 0x7080}, {0x8234, 0xED30, 0xED39, 0x708A}, + {0x8234, 0xEE30, 0xEE39, 0x7094}, {0x8234, 0xEF30, 0xEF39, 0x709E}, + {0x8234, 0xF030, 0xF039, 0x70A8}, {0x8234, 0xF130, 0xF139, 0x70B2}, + {0x8234, 0xF230, 0xF239, 0x70BC}, {0x8234, 0xF330, 0xF339, 0x70C6}, + {0x8234, 0xF430, 0xF439, 0x70D0}, {0x8234, 0xF530, 0xF539, 0x70DA}, + {0x8234, 0xF630, 0xF639, 0x70E4}, {0x8234, 0xF730, 0xF739, 0x70EE}, + {0x8234, 0xF830, 0xF839, 0x70F8}, {0x8234, 0xF930, 0xF939, 0x7102}, + {0x8234, 0xFA30, 0xFA39, 0x710C}, {0x8234, 0xFB30, 0xFB39, 0x7116}, + {0x8234, 0xFC30, 0xFC39, 0x7120}, {0x8234, 0xFD30, 0xFD39, 0x712A}, + {0x8234, 0xFE30, 0xFE39, 0x7134}, {0x8235, 0x8130, 0x8139, 0x713E}, + {0x8235, 0x8230, 0x8239, 0x7148}, {0x8235, 0x8330, 0x8339, 0x7152}, + {0x8235, 0x8430, 0x8439, 0x715C}, {0x8235, 0x8530, 0x8539, 0x7166}, + {0x8235, 0x8630, 0x8639, 0x7170}, {0x8235, 0x8730, 0x8738, 0x717A}, + {0x8235, 0x9833, 0x9839, 0x7188}, {0x8235, 0x9930, 0x9939, 0x718F}, + {0x8235, 0x9A30, 0x9A39, 0x7199}, {0x8235, 0x9B30, 0x9B39, 0x71A3}, + {0x8235, 0x9C30, 0x9C39, 0x71AD}, {0x8235, 0x9D30, 0x9D39, 0x71B7}, + {0x8235, 0x9E30, 0x9E39, 0x71C1}, {0x8235, 0x9F30, 0x9F39, 0x71CB}, + {0x8235, 0xA030, 0xA039, 0x71D5}, {0x8235, 0xA130, 0xA139, 0x71DF}, + {0x8235, 0xA230, 0xA239, 0x71E9}, {0x8235, 0xA330, 0xA339, 0x71F3}, + {0x8235, 0xA430, 0xA439, 0x71FD}, {0x8235, 0xA530, 0xA539, 0x7207}, + {0x8235, 0xA630, 0xA639, 0x7211}, {0x8235, 0xA730, 0xA739, 0x721B}, + {0x8235, 0xA830, 0xA839, 0x7225}, {0x8235, 0xA930, 0xA939, 0x722F}, + {0x8235, 0xAA30, 0xAA39, 0x7239}, {0x8235, 0xAB30, 0xAB39, 0x7243}, + {0x8235, 0xAC30, 0xAC39, 0x724D}, {0x8235, 0xAD30, 0xAD39, 0x7257}, + {0x8235, 0xAE30, 0xAE39, 0x7261}, {0x8235, 0xAF30, 0xAF39, 0x726B}, + {0x8235, 0xB030, 0xB039, 0x7275}, {0x8235, 0xB130, 0xB139, 0x727F}, + {0x8235, 0xB230, 0xB239, 0x7289}, {0x8235, 0xB330, 0xB339, 0x7293}, + {0x8235, 0xB430, 0xB439, 0x729D}, {0x8235, 0xB530, 0xB539, 0x72A7}, + {0x8235, 0xB630, 0xB639, 0x72B1}, {0x8235, 0xB730, 0xB739, 0x72BB}, + {0x8235, 0xB830, 0xB839, 0x72C5}, {0x8235, 0xB930, 0xB939, 0x72CF}, + {0x8235, 0xBA30, 0xBA39, 0x72D9}, {0x8235, 0xBB30, 0xBB39, 0x72E3}, + {0x8235, 0xBC30, 0xBC39, 0x72ED}, {0x8235, 0xBD30, 0xBD39, 0x72F7}, + {0x8235, 0xBE30, 0xBE39, 0x7301}, {0x8235, 0xBF30, 0xBF39, 0x730B}, + {0x8235, 0xC030, 0xC039, 0x7315}, {0x8235, 0xC130, 0xC139, 0x731F}, + {0x8235, 0xC230, 0xC239, 0x7329}, {0x8235, 0xC330, 0xC339, 0x7333}, + {0x8235, 0xC430, 0xC439, 0x733D}, {0x8235, 0xC530, 0xC539, 0x7347}, + {0x8235, 0xC630, 0xC639, 0x7351}, {0x8235, 0xC730, 0xC739, 0x735B}, + {0x8235, 0xC830, 0xC839, 0x7365}, {0x8235, 0xC930, 0xC939, 0x736F}, + {0x8235, 0xCA30, 0xCA39, 0x7379}, {0x8235, 0xCB30, 0xCB39, 0x7383}, + {0x8235, 0xCC30, 0xCC39, 0x738D}, {0x8235, 0xCD30, 0xCD39, 0x7397}, + {0x8235, 0xCE30, 0xCE39, 0x73A1}, {0x8235, 0xCF30, 0xCF39, 0x73AB}, + {0x8235, 0xD030, 0xD039, 0x73B5}, {0x8235, 0xD130, 0xD139, 0x73BF}, + {0x8235, 0xD230, 0xD239, 0x73C9}, {0x8235, 0xD330, 0xD339, 0x73D3}, + {0x8235, 0xD430, 0xD439, 0x73DD}, {0x8235, 0xD530, 0xD539, 0x73E7}, + {0x8235, 0xD630, 0xD639, 0x73F1}, {0x8235, 0xD730, 0xD739, 0x73FB}, + {0x8235, 0xD830, 0xD839, 0x7405}, {0x8235, 0xD930, 0xD939, 0x740F}, + {0x8235, 0xDA30, 0xDA39, 0x7419}, {0x8235, 0xDB30, 0xDB39, 0x7423}, + {0x8235, 0xDC30, 0xDC39, 0x742D}, {0x8235, 0xDD30, 0xDD39, 0x7437}, + {0x8235, 0xDE30, 0xDE39, 0x7441}, {0x8235, 0xDF30, 0xDF39, 0x744B}, + {0x8235, 0xE030, 0xE039, 0x7455}, {0x8235, 0xE130, 0xE139, 0x745F}, + {0x8235, 0xE230, 0xE239, 0x7469}, {0x8235, 0xE330, 0xE339, 0x7473}, + {0x8235, 0xE430, 0xE439, 0x747D}, {0x8235, 0xE530, 0xE539, 0x7487}, + {0x8235, 0xE630, 0xE639, 0x7491}, {0x8235, 0xE730, 0xE739, 0x749B}, + {0x8235, 0xE830, 0xE839, 0x74A5}, {0x8235, 0xE930, 0xE939, 0x74AF}, + {0x8235, 0xEA30, 0xEA39, 0x74B9}, {0x8235, 0xEB30, 0xEB39, 0x74C3}, + {0x8235, 0xEC30, 0xEC39, 0x74CD}, {0x8235, 0xED30, 0xED39, 0x74D7}, + {0x8235, 0xEE30, 0xEE39, 0x74E1}, {0x8235, 0xEF30, 0xEF39, 0x74EB}, + {0x8235, 0xF030, 0xF039, 0x74F5}, {0x8235, 0xF130, 0xF139, 0x74FF}, + {0x8235, 0xF230, 0xF239, 0x7509}, {0x8235, 0xF330, 0xF339, 0x7513}, + {0x8235, 0xF430, 0xF439, 0x751D}, {0x8235, 0xF530, 0xF539, 0x7527}, + {0x8235, 0xF630, 0xF639, 0x7531}, {0x8235, 0xF730, 0xF739, 0x753B}, + {0x8235, 0xF830, 0xF839, 0x7545}, {0x8235, 0xF930, 0xF939, 0x754F}, + {0x8235, 0xFA30, 0xFA39, 0x7559}, {0x8235, 0xFB30, 0xFB39, 0x7563}, + {0x8235, 0xFC30, 0xFC39, 0x756D}, {0x8235, 0xFD30, 0xFD39, 0x7577}, + {0x8235, 0xFE30, 0xFE39, 0x7581}, {0x8236, 0x8130, 0x8139, 0x758B}, + {0x8236, 0x8230, 0x8239, 0x7595}, {0x8236, 0x8330, 0x8339, 0x759F}, + {0x8236, 0x8430, 0x8439, 0x75A9}, {0x8236, 0x8530, 0x8539, 0x75B3}, + {0x8236, 0x8630, 0x8639, 0x75BD}, {0x8236, 0x8730, 0x8739, 0x75C7}, + {0x8236, 0x8830, 0x8839, 0x75D1}, {0x8236, 0x8930, 0x8939, 0x75DB}, + {0x8236, 0x8A30, 0x8A39, 0x75E5}, {0x8236, 0x8B30, 0x8B39, 0x75EF}, + {0x8236, 0x8C30, 0x8C39, 0x75F9}, {0x8236, 0x8D30, 0x8D39, 0x7603}, + {0x8236, 0x8E30, 0x8E37, 0x760D}, {0x8236, 0x8F31, 0x8F39, 0x7615}, + {0x8236, 0x9030, 0x9039, 0x761E}, {0x8236, 0x9130, 0x9139, 0x7628}, + {0x8236, 0x9230, 0x9239, 0x7632}, {0x8236, 0x9330, 0x9339, 0x763C}, + {0x8236, 0x9430, 0x9435, 0x7646}, }; diff --git a/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp b/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp index 9d15271e7e1fb9628803efad5ec04bd4ba6065d7..f35161ab9790522ae1d6674e984639e89c8faae3 100644 --- a/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp +++ b/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp @@ -8,48 +8,41 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fxcrt/fx_basic.h" static const FXCMAP_CMap g_FXCMAP_GB1_cmaps[] = { - {"GB-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_GB_EUC_H_0, 90, FXCMAP_CMap::None, - nullptr, 0, 0}, - {"GB-EUC-V", FXCMAP_CMap::Range, g_FXCMAP_GB_EUC_V_0, 20, FXCMAP_CMap::None, - nullptr, 0, -1}, - {"GBpc-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_GBpc_EUC_H_0, 91, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"GBpc-EUC-V", FXCMAP_CMap::Range, g_FXCMAP_GBpc_EUC_V_0, 20, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"GBK-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_GBK_EUC_H_2, 4071, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"GBK-EUC-V", FXCMAP_CMap::Range, g_FXCMAP_GBK_EUC_V_2, 20, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"GBKp-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_GBKp_EUC_H_2, 4070, - FXCMAP_CMap::None, nullptr, 0, -2}, - {"GBKp-EUC-V", FXCMAP_CMap::Range, g_FXCMAP_GBKp_EUC_V_2, 20, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"GBK2K-H", FXCMAP_CMap::Range, g_FXCMAP_GBK2K_H_5, 4071, - FXCMAP_CMap::Single, g_FXCMAP_GBK2K_H_5_DWord, 1017, -4}, - {"GBK2K-V", FXCMAP_CMap::Range, g_FXCMAP_GBK2K_V_5, 41, FXCMAP_CMap::None, - nullptr, 0, -1}, - {"UniGB-UCS2-H", FXCMAP_CMap::Range, g_FXCMAP_UniGB_UCS2_H_4, 13825, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniGB-UCS2-V", FXCMAP_CMap::Range, g_FXCMAP_UniGB_UCS2_V_4, 24, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"UniGB-UTF16-H", FXCMAP_CMap::Range, g_FXCMAP_UniGB_UCS2_H_4, 13825, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniGB-UTF16-V", FXCMAP_CMap::Range, g_FXCMAP_UniGB_UCS2_V_4, 24, - FXCMAP_CMap::None, nullptr, 0, -1}, + {"GB-EUC-H", g_FXCMAP_GB_EUC_H_0, nullptr, 90, 0, FXCMAP_CMap::Range, 0}, + {"GB-EUC-V", g_FXCMAP_GB_EUC_V_0, nullptr, 20, 0, FXCMAP_CMap::Range, -1}, + {"GBpc-EUC-H", g_FXCMAP_GBpc_EUC_H_0, nullptr, 91, 0, FXCMAP_CMap::Range, + 0}, + {"GBpc-EUC-V", g_FXCMAP_GBpc_EUC_V_0, nullptr, 20, 0, FXCMAP_CMap::Range, + -1}, + {"GBK-EUC-H", g_FXCMAP_GBK_EUC_H_2, nullptr, 4071, 0, FXCMAP_CMap::Range, + 0}, + {"GBK-EUC-V", g_FXCMAP_GBK_EUC_V_2, nullptr, 20, 0, FXCMAP_CMap::Range, -1}, + {"GBKp-EUC-H", g_FXCMAP_GBKp_EUC_H_2, nullptr, 4070, 0, FXCMAP_CMap::Range, + -2}, + {"GBKp-EUC-V", g_FXCMAP_GBKp_EUC_V_2, nullptr, 20, 0, FXCMAP_CMap::Range, + -1}, + {"GBK2K-H", g_FXCMAP_GBK2K_H_5, g_FXCMAP_GBK2K_H_5_DWord, 4071, 1017, + FXCMAP_CMap::Range, -4}, + {"GBK2K-V", g_FXCMAP_GBK2K_V_5, nullptr, 41, 0, FXCMAP_CMap::Range, -1}, + {"UniGB-UCS2-H", g_FXCMAP_UniGB_UCS2_H_4, nullptr, 13825, 0, + FXCMAP_CMap::Range, 0}, + {"UniGB-UCS2-V", g_FXCMAP_UniGB_UCS2_V_4, nullptr, 24, 0, + FXCMAP_CMap::Range, -1}, + {"UniGB-UTF16-H", g_FXCMAP_UniGB_UCS2_H_4, nullptr, 13825, 0, + FXCMAP_CMap::Range, 0}, + {"UniGB-UTF16-V", g_FXCMAP_UniGB_UCS2_V_4, nullptr, 24, 0, + FXCMAP_CMap::Range, -1}, }; void CPDF_ModuleMgr::LoadEmbeddedGB1CMaps() { CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - pFontGlobals->m_EmbeddedCharsets[CIDSET_GB1].m_pMapList = g_FXCMAP_GB1_cmaps; - pFontGlobals->m_EmbeddedCharsets[CIDSET_GB1].m_Count = - FX_ArraySize(g_FXCMAP_GB1_cmaps); - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_GB1].m_pMap = - g_FXCMAP_GB1CID2Unicode_5; - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_GB1].m_Count = 30284; + pFontGlobals->SetEmbeddedCharset(CIDSET_GB1, g_FXCMAP_GB1_cmaps, + FX_ArraySize(g_FXCMAP_GB1_cmaps)); + pFontGlobals->SetEmbeddedToUnicode(CIDSET_GB1, g_FXCMAP_GB1CID2Unicode_5, + 30284); } diff --git a/core/fpdfapi/cmaps/GB1/cmaps_gb1.h b/core/fpdfapi/cmaps/GB1/cmaps_gb1.h index 0b8a3505f38778a08928f94d3c5bbb8ae74e22fd..a475af156832d5d5dd993f49b0435ffea8e48a96 100644 --- a/core/fpdfapi/cmaps/GB1/cmaps_gb1.h +++ b/core/fpdfapi/cmaps/GB1/cmaps_gb1.h @@ -9,6 +9,8 @@ #include +#include "core/fpdfapi/cmaps/cmap_int.h" + extern const uint16_t g_FXCMAP_GB_EUC_H_0[]; extern const uint16_t g_FXCMAP_GB_EUC_V_0[]; extern const uint16_t g_FXCMAP_GBpc_EUC_H_0[]; @@ -18,7 +20,7 @@ extern const uint16_t g_FXCMAP_GBK_EUC_V_2[]; extern const uint16_t g_FXCMAP_GBKp_EUC_H_2[]; extern const uint16_t g_FXCMAP_GBKp_EUC_V_2[]; extern const uint16_t g_FXCMAP_GBK2K_H_5[]; -extern const uint16_t g_FXCMAP_GBK2K_H_5_DWord[]; +extern const FXCMAP_DWordCIDMap g_FXCMAP_GBK2K_H_5_DWord[]; extern const uint16_t g_FXCMAP_GBK2K_V_5[]; extern const uint16_t g_FXCMAP_UniGB_UCS2_H_4[]; extern const uint16_t g_FXCMAP_UniGB_UCS2_V_4[]; diff --git a/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp b/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp index bdf65595ad4951c9b0eb018ba5fe51de88d61093..f640fdd5979d9fd62cf82e8d665a826267ab388c 100644 --- a/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp +++ b/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp @@ -8,61 +8,53 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fxcrt/fx_basic.h" static const FXCMAP_CMap g_FXCMAP_Japan1_cmaps[] = { - {"83pv-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_83pv_RKSJ_H_1, 222, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"90ms-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_90ms_RKSJ_H_2, 171, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"90ms-RKSJ-V", FXCMAP_CMap::Range, g_FXCMAP_90ms_RKSJ_V_2, 78, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"90msp-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_90msp_RKSJ_H_2, 170, - FXCMAP_CMap::None, nullptr, 0, -2}, - {"90msp-RKSJ-V", FXCMAP_CMap::Range, g_FXCMAP_90msp_RKSJ_V_2, 78, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"90pv-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_90pv_RKSJ_H_1, 263, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"Add-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_Add_RKSJ_H_1, 635, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"Add-RKSJ-V", FXCMAP_CMap::Range, g_FXCMAP_Add_RKSJ_V_1, 57, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"EUC-H", FXCMAP_CMap::Range, g_FXCMAP_EUC_H_1, 120, FXCMAP_CMap::None, - nullptr, 0, 0}, - {"EUC-V", FXCMAP_CMap::Range, g_FXCMAP_EUC_V_1, 27, FXCMAP_CMap::None, - nullptr, 0, -1}, - {"Ext-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_Ext_RKSJ_H_2, 665, - FXCMAP_CMap::None, nullptr, 0, -4}, - {"Ext-RKSJ-V", FXCMAP_CMap::Range, g_FXCMAP_Ext_RKSJ_V_2, 39, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"H", FXCMAP_CMap::Range, g_FXCMAP_H_1, 118, FXCMAP_CMap::None, nullptr, 0, + {"83pv-RKSJ-H", g_FXCMAP_83pv_RKSJ_H_1, nullptr, 222, 0, FXCMAP_CMap::Range, 0}, - {"V", FXCMAP_CMap::Range, g_FXCMAP_V_1, 27, FXCMAP_CMap::None, nullptr, 0, + {"90ms-RKSJ-H", g_FXCMAP_90ms_RKSJ_H_2, nullptr, 171, 0, FXCMAP_CMap::Range, + 0}, + {"90ms-RKSJ-V", g_FXCMAP_90ms_RKSJ_V_2, nullptr, 78, 0, FXCMAP_CMap::Range, + -1}, + {"90msp-RKSJ-H", g_FXCMAP_90msp_RKSJ_H_2, nullptr, 170, 0, + FXCMAP_CMap::Range, -2}, + {"90msp-RKSJ-V", g_FXCMAP_90msp_RKSJ_V_2, nullptr, 78, 0, + FXCMAP_CMap::Range, -1}, + {"90pv-RKSJ-H", g_FXCMAP_90pv_RKSJ_H_1, nullptr, 263, 0, FXCMAP_CMap::Range, + 0}, + {"Add-RKSJ-H", g_FXCMAP_Add_RKSJ_H_1, nullptr, 635, 0, FXCMAP_CMap::Range, + 0}, + {"Add-RKSJ-V", g_FXCMAP_Add_RKSJ_V_1, nullptr, 57, 0, FXCMAP_CMap::Range, + -1}, + {"EUC-H", g_FXCMAP_EUC_H_1, nullptr, 120, 0, FXCMAP_CMap::Range, 0}, + {"EUC-V", g_FXCMAP_EUC_V_1, nullptr, 27, 0, FXCMAP_CMap::Range, -1}, + {"Ext-RKSJ-H", g_FXCMAP_Ext_RKSJ_H_2, nullptr, 665, 0, FXCMAP_CMap::Range, + -4}, + {"Ext-RKSJ-V", g_FXCMAP_Ext_RKSJ_V_2, nullptr, 39, 0, FXCMAP_CMap::Range, -1}, - {"UniJIS-UCS2-H", FXCMAP_CMap::Single, g_FXCMAP_UniJIS_UCS2_H_4, 9772, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniJIS-UCS2-V", FXCMAP_CMap::Single, g_FXCMAP_UniJIS_UCS2_V_4, 251, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"UniJIS-UCS2-HW-H", FXCMAP_CMap::Range, g_FXCMAP_UniJIS_UCS2_HW_H_4, 4, - FXCMAP_CMap::None, nullptr, 0, -2}, - {"UniJIS-UCS2-HW-V", FXCMAP_CMap::Range, g_FXCMAP_UniJIS_UCS2_HW_V_4, 199, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"UniJIS-UTF16-H", FXCMAP_CMap::Single, g_FXCMAP_UniJIS_UCS2_H_4, 9772, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniJIS-UTF16-V", FXCMAP_CMap::Single, g_FXCMAP_UniJIS_UCS2_V_4, 251, - FXCMAP_CMap::None, nullptr, 0, -1}, + {"H", g_FXCMAP_H_1, nullptr, 118, 0, FXCMAP_CMap::Range, 0}, + {"V", g_FXCMAP_V_1, nullptr, 27, 0, FXCMAP_CMap::Range, -1}, + {"UniJIS-UCS2-H", g_FXCMAP_UniJIS_UCS2_H_4, nullptr, 9772, 0, + FXCMAP_CMap::Single, 0}, + {"UniJIS-UCS2-V", g_FXCMAP_UniJIS_UCS2_V_4, nullptr, 251, 0, + FXCMAP_CMap::Single, -1}, + {"UniJIS-UCS2-HW-H", g_FXCMAP_UniJIS_UCS2_HW_H_4, nullptr, 4, 0, + FXCMAP_CMap::Range, -2}, + {"UniJIS-UCS2-HW-V", g_FXCMAP_UniJIS_UCS2_HW_V_4, nullptr, 199, 0, + FXCMAP_CMap::Range, -1}, + {"UniJIS-UTF16-H", g_FXCMAP_UniJIS_UCS2_H_4, nullptr, 9772, 0, + FXCMAP_CMap::Single, 0}, + {"UniJIS-UTF16-V", g_FXCMAP_UniJIS_UCS2_V_4, nullptr, 251, 0, + FXCMAP_CMap::Single, -1}, }; void CPDF_ModuleMgr::LoadEmbeddedJapan1CMaps() { CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - pFontGlobals->m_EmbeddedCharsets[CIDSET_JAPAN1].m_pMapList = - g_FXCMAP_Japan1_cmaps; - pFontGlobals->m_EmbeddedCharsets[CIDSET_JAPAN1].m_Count = - FX_ArraySize(g_FXCMAP_Japan1_cmaps); - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_JAPAN1].m_pMap = - g_FXCMAP_Japan1CID2Unicode_4; - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_JAPAN1].m_Count = 15444; + pFontGlobals->SetEmbeddedCharset(CIDSET_JAPAN1, g_FXCMAP_Japan1_cmaps, + FX_ArraySize(g_FXCMAP_Japan1_cmaps)); + pFontGlobals->SetEmbeddedToUnicode(CIDSET_JAPAN1, + g_FXCMAP_Japan1CID2Unicode_4, 15444); } diff --git a/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp b/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp index 5e88b3ba17fbc2fcf9deb0e8caa55740c50b337b..daec8259e9a158552217a6bf63d2284c3468b245 100644 --- a/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp +++ b/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp @@ -8,43 +8,37 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fxcrt/fx_basic.h" static const FXCMAP_CMap g_FXCMAP_Korea1_cmaps[] = { - {"KSC-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_KSC_EUC_H_0, 467, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"KSC-EUC-V", FXCMAP_CMap::Range, g_FXCMAP_KSC_EUC_V_0, 16, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"KSCms-UHC-H", FXCMAP_CMap::Range, g_FXCMAP_KSCms_UHC_H_1, 675, - FXCMAP_CMap::None, nullptr, 0, -2}, - {"KSCms-UHC-V", FXCMAP_CMap::Range, g_FXCMAP_KSCms_UHC_V_1, 16, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"KSCms-UHC-HW-H", FXCMAP_CMap::Range, g_FXCMAP_KSCms_UHC_HW_H_1, 675, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"KSCms-UHC-HW-V", FXCMAP_CMap::Range, g_FXCMAP_KSCms_UHC_HW_V_1, 16, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"KSCpc-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_KSCpc_EUC_H_0, 509, - FXCMAP_CMap::None, nullptr, 0, -6}, - {"UniKS-UCS2-H", FXCMAP_CMap::Range, g_FXCMAP_UniKS_UCS2_H_1, 8394, - FXCMAP_CMap::None, nullptr, 0, 0}, - {"UniKS-UCS2-V", FXCMAP_CMap::Range, g_FXCMAP_UniKS_UCS2_V_1, 18, - FXCMAP_CMap::None, nullptr, 0, -1}, - {"UniKS-UTF16-H", FXCMAP_CMap::Single, g_FXCMAP_UniKS_UTF16_H_0, 158, - FXCMAP_CMap::None, nullptr, 0, -2}, - {"UniKS-UTF16-V", FXCMAP_CMap::Range, g_FXCMAP_UniKS_UCS2_V_1, 18, - FXCMAP_CMap::None, nullptr, 0, -1}, + {"KSC-EUC-H", g_FXCMAP_KSC_EUC_H_0, nullptr, 467, 0, FXCMAP_CMap::Range, 0}, + {"KSC-EUC-V", g_FXCMAP_KSC_EUC_V_0, nullptr, 16, 0, FXCMAP_CMap::Range, -1}, + {"KSCms-UHC-H", g_FXCMAP_KSCms_UHC_H_1, nullptr, 675, 0, FXCMAP_CMap::Range, + -2}, + {"KSCms-UHC-V", g_FXCMAP_KSCms_UHC_V_1, nullptr, 16, 0, FXCMAP_CMap::Range, + -1}, + {"KSCms-UHC-HW-H", g_FXCMAP_KSCms_UHC_HW_H_1, nullptr, 675, 0, + FXCMAP_CMap::Range, 0}, + {"KSCms-UHC-HW-V", g_FXCMAP_KSCms_UHC_HW_V_1, nullptr, 16, 0, + FXCMAP_CMap::Range, -1}, + {"KSCpc-EUC-H", g_FXCMAP_KSCpc_EUC_H_0, nullptr, 509, 0, FXCMAP_CMap::Range, + -6}, + {"UniKS-UCS2-H", g_FXCMAP_UniKS_UCS2_H_1, nullptr, 8394, 0, + FXCMAP_CMap::Range, 0}, + {"UniKS-UCS2-V", g_FXCMAP_UniKS_UCS2_V_1, nullptr, 18, 0, + FXCMAP_CMap::Range, -1}, + {"UniKS-UTF16-H", g_FXCMAP_UniKS_UTF16_H_0, nullptr, 158, 0, + FXCMAP_CMap::Single, -2}, + {"UniKS-UTF16-V", g_FXCMAP_UniKS_UCS2_V_1, nullptr, 18, 0, + FXCMAP_CMap::Range, -1}, }; void CPDF_ModuleMgr::LoadEmbeddedKorea1CMaps() { CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - pFontGlobals->m_EmbeddedCharsets[CIDSET_KOREA1].m_pMapList = - g_FXCMAP_Korea1_cmaps; - pFontGlobals->m_EmbeddedCharsets[CIDSET_KOREA1].m_Count = - FX_ArraySize(g_FXCMAP_Korea1_cmaps); - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_KOREA1].m_pMap = - g_FXCMAP_Korea1CID2Unicode_2; - pFontGlobals->m_EmbeddedToUnicodes[CIDSET_KOREA1].m_Count = 18352; + pFontGlobals->SetEmbeddedCharset(CIDSET_KOREA1, g_FXCMAP_Korea1_cmaps, + FX_ArraySize(g_FXCMAP_Korea1_cmaps)); + pFontGlobals->SetEmbeddedToUnicode(CIDSET_KOREA1, + g_FXCMAP_Korea1CID2Unicode_2, 18352); } diff --git a/core/fpdfapi/cmaps/cmap_int.h b/core/fpdfapi/cmaps/cmap_int.h index e84dc11e5ab58681b2669f05bbdcc4b5db4abb20..27f9617ed6a0c10f57e742267f55e333c93b4c18 100644 --- a/core/fpdfapi/cmaps/cmap_int.h +++ b/core/fpdfapi/cmaps/cmap_int.h @@ -10,23 +10,28 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +struct FXCMAP_DWordCIDMap { + uint16_t m_HiWord; + uint16_t m_LoWordLow; + uint16_t m_LoWordHigh; + uint16_t m_CID; +}; + struct FXCMAP_CMap { - enum MapType { None, Single, Range, Reverse }; + enum MapType : uint8_t { Single, Range }; const char* m_Name; - MapType m_WordMapType; const uint16_t* m_pWordMap; - int m_WordCount; - MapType m_DWordMapType; - const uint16_t* m_pDWordMap; - int m_DWordCount; - int m_UseOffset; + const FXCMAP_DWordCIDMap* m_pDWordMap; + uint16_t m_WordCount; + uint16_t m_DWordCount; + MapType m_WordMapType; + int8_t m_UseOffset; }; -void FPDFAPI_FindEmbeddedCMap(const CFX_ByteString& name, - int charset, - int coding, - const FXCMAP_CMap*& pMap); +const FXCMAP_CMap* FPDFAPI_FindEmbeddedCMap(const ByteString& name, + int charset, + int coding); uint16_t FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, uint32_t charcode); uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid); diff --git a/core/fpdfapi/cmaps/fpdf_cmaps.cpp b/core/fpdfapi/cmaps/fpdf_cmaps.cpp index ca01d431f4da862a1d329398359b1faa231604a2..bba8d2173d21836cf67544c380b550a95ed4d092 100644 --- a/core/fpdfapi/cmaps/fpdf_cmaps.cpp +++ b/core/fpdfapi/cmaps/fpdf_cmaps.cpp @@ -6,116 +6,95 @@ #include "core/fpdfapi/cmaps/cmap_int.h" +#include + #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" -extern "C" { - -static int compareWord(const void* p1, const void* p2) { - return (*(uint16_t*)p1) - (*(uint16_t*)p2); -} - -static int compareWordRange(const void* key, const void* element) { - if (*(uint16_t*)key < *(uint16_t*)element) - return -1; - if (*(uint16_t*)key > ((uint16_t*)element)[1]) - return 1; - return 0; -} +namespace { -static int compareDWordRange(const void* p1, const void* p2) { - uint32_t key = *(uint32_t*)p1; - uint16_t hiword = (uint16_t)(key >> 16); - uint16_t* element = (uint16_t*)p2; - if (hiword < element[0]) - return -1; - if (hiword > element[0]) - return 1; - - uint16_t loword = (uint16_t)key; - if (loword < element[1]) - return -1; - if (loword > element[2]) - return 1; - return 0; -} - -static int compareDWordSingle(const void* p1, const void* p2) { - uint32_t key = *(uint32_t*)p1; - uint32_t value = ((*(uint16_t*)p2) << 16) | ((uint16_t*)p2)[1]; - if (key < value) - return -1; - if (key > value) - return 1; - return 0; +const FXCMAP_CMap* FindNextCMap(const FXCMAP_CMap* pMap) { + return pMap->m_UseOffset ? pMap + pMap->m_UseOffset : nullptr; } -}; // extern "C" +} // namespace -void FPDFAPI_FindEmbeddedCMap(const CFX_ByteString& bsName, - int charset, - int coding, - const FXCMAP_CMap*& pMap) { - pMap = nullptr; +const FXCMAP_CMap* FPDFAPI_FindEmbeddedCMap(const ByteString& bsName, + int charset, + int coding) { CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - const FXCMAP_CMap* pCMaps = - pFontGlobals->m_EmbeddedCharsets[charset].m_pMapList; - for (uint32_t i = 0; i < pFontGlobals->m_EmbeddedCharsets[charset].m_Count; - i++) { - if (bsName == pCMaps[i].m_Name) { - pMap = &pCMaps[i]; - break; - } + + const FXCMAP_CMap* pCMaps; + uint32_t count; + std::tie(count, pCMaps) = pFontGlobals->GetEmbeddedCharset(charset); + for (uint32_t i = 0; i < count; i++) { + if (bsName == pCMaps[i].m_Name) + return &pCMaps[i]; } + return nullptr; } uint16_t FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, uint32_t charcode) { + ASSERT(pMap); + const uint16_t loword = static_cast(charcode); if (charcode >> 16) { - while (1) { - if (pMap->m_DWordMapType == FXCMAP_CMap::Range) { - uint16_t* found = static_cast( - FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 8, - compareDWordRange)); - if (found) - return found[3] + (uint16_t)charcode - found[1]; - - } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) { - uint16_t* found = static_cast( - FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 6, - compareDWordSingle)); - if (found) - return found[2]; + while (pMap) { + if (pMap->m_pDWordMap) { + const FXCMAP_DWordCIDMap* begin = pMap->m_pDWordMap; + const auto* end = begin + pMap->m_DWordCount; + const auto* found = std::lower_bound( + begin, end, charcode, + [](const FXCMAP_DWordCIDMap& element, uint32_t charcode) { + uint16_t hiword = static_cast(charcode >> 16); + if (element.m_HiWord != hiword) + return element.m_HiWord < hiword; + return element.m_LoWordHigh < static_cast(charcode); + }); + if (found != end && loword >= found->m_LoWordLow && + loword <= found->m_LoWordHigh) { + return found->m_CID + loword - found->m_LoWordLow; + } } - if (pMap->m_UseOffset == 0) - return 0; - - pMap = pMap + pMap->m_UseOffset; + pMap = FindNextCMap(pMap); } return 0; } - uint16_t code = (uint16_t)charcode; - while (1) { + while (pMap) { if (!pMap->m_pWordMap) return 0; if (pMap->m_WordMapType == FXCMAP_CMap::Single) { - uint16_t* found = static_cast(FXSYS_bsearch( - &code, pMap->m_pWordMap, pMap->m_WordCount, 4, compareWord)); - if (found) - return found[1]; - - } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) { - uint16_t* found = static_cast(FXSYS_bsearch( - &code, pMap->m_pWordMap, pMap->m_WordCount, 6, compareWordRange)); - if (found) - return found[2] + code - found[0]; + struct SingleCmap { + uint16_t code; + uint16_t cid; + }; + const auto* begin = reinterpret_cast(pMap->m_pWordMap); + const auto* end = begin + pMap->m_WordCount; + const auto* found = std::lower_bound( + begin, end, loword, [](const SingleCmap& element, uint16_t code) { + return element.code < code; + }); + if (found != end && found->code == loword) + return found->cid; + } else { + ASSERT(pMap->m_WordMapType == FXCMAP_CMap::Range); + struct RangeCmap { + uint16_t low; + uint16_t high; + uint16_t cid; + }; + const auto* begin = reinterpret_cast(pMap->m_pWordMap); + const auto* end = begin + pMap->m_WordCount; + const auto* found = std::lower_bound( + begin, end, loword, [](const RangeCmap& element, uint16_t code) { + return element.high < code; + }); + if (found != end && loword >= found->low && loword <= found->high) + return found->cid + loword - found->low; } - if (pMap->m_UseOffset == 0) - return 0; - - pMap = pMap + pMap->m_UseOffset; + pMap = FindNextCMap(pMap); } return 0; } @@ -126,7 +105,8 @@ uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid) { // the first always returns. Investigate and determine how this should // really be working. (https://codereview.chromium.org/2235743003 removed the // second while loop.) - while (1) { + ASSERT(pMap); + while (pMap) { if (pMap->m_WordMapType == FXCMAP_CMap::Single) { const uint16_t* pCur = pMap->m_pWordMap; const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 2; @@ -136,7 +116,8 @@ uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid) { pCur += 2; } - } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) { + } else { + ASSERT(pMap->m_WordMapType == FXCMAP_CMap::Range); const uint16_t* pCur = pMap->m_pWordMap; const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 3; while (pCur < pEnd) { @@ -146,9 +127,7 @@ uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid) { pCur += 3; } } - if (pMap->m_UseOffset == 0) - return 0; - - pMap = pMap + pMap->m_UseOffset; + pMap = FindNextCMap(pMap); } + return 0; } diff --git a/core/fpdfapi/cpdf_modulemgr.cpp b/core/fpdfapi/cpdf_modulemgr.cpp index ac28b3666398e1e5e422d19d35183ff93a071536..678997a8c9a197b6098419fd648f7e029ec2dcbe 100644 --- a/core/fpdfapi/cpdf_modulemgr.cpp +++ b/core/fpdfapi/cpdf_modulemgr.cpp @@ -10,6 +10,22 @@ #include "core/fxcodec/fx_codec.h" #include "third_party/base/ptr_util.h" +#ifdef PDF_ENABLE_XFA_BMP +#include "core/fxcodec/codec/ccodec_bmpmodule.h" +#endif + +#ifdef PDF_ENABLE_XFA_GIF +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#endif + +#ifdef PDF_ENABLE_XFA_PNG +#include "core/fxcodec/codec/ccodec_pngmodule.h" +#endif + +#ifdef PDF_ENABLE_XFA_TIFF +#include "core/fxcodec/codec/ccodec_tiffmodule.h" +#endif + namespace { CPDF_ModuleMgr* g_pDefaultMgr = nullptr; @@ -29,34 +45,70 @@ void CPDF_ModuleMgr::Destroy() { g_pDefaultMgr = nullptr; } -CPDF_ModuleMgr::CPDF_ModuleMgr() : m_pCodecModule(nullptr) {} +CPDF_ModuleMgr::CPDF_ModuleMgr() {} CPDF_ModuleMgr::~CPDF_ModuleMgr() {} +void CPDF_ModuleMgr::Init() { + InitCodecModule(); + InitPageModule(); + LoadEmbeddedMaps(); + LoadCodecModules(); +} + +void CPDF_ModuleMgr::LoadEmbeddedMaps() { + LoadEmbeddedGB1CMaps(); + LoadEmbeddedJapan1CMaps(); + LoadEmbeddedCNS1CMaps(); + LoadEmbeddedKorea1CMaps(); +} + +void CPDF_ModuleMgr::LoadCodecModules() { +#ifdef PDF_ENABLE_XFA_BMP + m_pCodecModule->SetBmpModule(pdfium::MakeUnique()); +#endif + +#ifdef PDF_ENABLE_XFA_GIF + m_pCodecModule->SetGifModule(pdfium::MakeUnique()); +#endif + +#ifdef PDF_ENABLE_XFA_PNG + m_pCodecModule->SetPngModule(pdfium::MakeUnique()); +#endif + +#ifdef PDF_ENABLE_XFA_TIFF + m_pCodecModule->SetTiffModule(pdfium::MakeUnique()); +#endif +} + +void CPDF_ModuleMgr::InitCodecModule() { + m_pCodecModule = pdfium::MakeUnique(); +} + void CPDF_ModuleMgr::InitPageModule() { m_pPageModule = pdfium::MakeUnique(); } CCodec_FaxModule* CPDF_ModuleMgr::GetFaxModule() { - return m_pCodecModule ? m_pCodecModule->GetFaxModule() : nullptr; + return m_pCodecModule->GetFaxModule(); } CCodec_JpegModule* CPDF_ModuleMgr::GetJpegModule() { - return m_pCodecModule ? m_pCodecModule->GetJpegModule() : nullptr; + return m_pCodecModule->GetJpegModule(); } CCodec_JpxModule* CPDF_ModuleMgr::GetJpxModule() { - return m_pCodecModule ? m_pCodecModule->GetJpxModule() : nullptr; + return m_pCodecModule->GetJpxModule(); } CCodec_Jbig2Module* CPDF_ModuleMgr::GetJbig2Module() { - return m_pCodecModule ? m_pCodecModule->GetJbig2Module() : nullptr; + return m_pCodecModule->GetJbig2Module(); } CCodec_IccModule* CPDF_ModuleMgr::GetIccModule() { - return m_pCodecModule ? m_pCodecModule->GetIccModule() : nullptr; + return m_pCodecModule->GetIccModule(); } CCodec_FlateModule* CPDF_ModuleMgr::GetFlateModule() { - return m_pCodecModule ? m_pCodecModule->GetFlateModule() : nullptr; + return m_pCodecModule->GetFlateModule(); } diff --git a/core/fpdfapi/cpdf_modulemgr.h b/core/fpdfapi/cpdf_modulemgr.h index d31ffd5256152fef00f5c0e787f3610b02093352..6b83bc755d369771e17942417491c0751c30b535 100644 --- a/core/fpdfapi/cpdf_modulemgr.h +++ b/core/fpdfapi/cpdf_modulemgr.h @@ -10,8 +10,6 @@ #include #include -#include "core/fxcrt/fx_basic.h" - class CCodec_FaxModule; class CCodec_FlateModule; class CCodec_IccModule; @@ -38,11 +36,7 @@ class CPDF_ModuleMgr { static void Destroy(); static const int kFileBufSize = 512; - void SetCodecModule(CCodec_ModuleMgr* pModule) { m_pCodecModule = pModule; } - CCodec_ModuleMgr* GetCodecModule() { return m_pCodecModule; } - - void InitPageModule(); - CPDF_PageModule* GetPageModule() const { return m_pPageModule.get(); } + void Init(); void SetUnsupportInfoAdapter( std::unique_ptr pAdapter) { @@ -52,10 +46,8 @@ class CPDF_ModuleMgr { return m_pUnsupportInfoAdapter.get(); } - void LoadEmbeddedGB1CMaps(); - void LoadEmbeddedCNS1CMaps(); - void LoadEmbeddedJapan1CMaps(); - void LoadEmbeddedKorea1CMaps(); + CCodec_ModuleMgr* GetCodecModule() const { return m_pCodecModule.get(); } + CPDF_PageModule* GetPageModule() const { return m_pPageModule.get(); } CCodec_FaxModule* GetFaxModule(); CCodec_JpegModule* GetJpegModule(); @@ -68,7 +60,17 @@ class CPDF_ModuleMgr { CPDF_ModuleMgr(); ~CPDF_ModuleMgr(); - CCodec_ModuleMgr* m_pCodecModule; + void InitCodecModule(); + void InitPageModule(); + void LoadEmbeddedMaps(); + void LoadCodecModules(); + + void LoadEmbeddedGB1CMaps(); + void LoadEmbeddedCNS1CMaps(); + void LoadEmbeddedJapan1CMaps(); + void LoadEmbeddedKorea1CMaps(); + + std::unique_ptr m_pCodecModule; std::unique_ptr m_pPageModule; std::unique_ptr m_pUnsupportInfoAdapter; }; diff --git a/core/fpdfapi/cpdf_pagerendercontext.h b/core/fpdfapi/cpdf_pagerendercontext.h index 27244e7fc3a32718139935d7adf1dd63045407c2..5cbcdb77593e27ccb1a1fb76c51fdd8c582675eb 100644 --- a/core/fpdfapi/cpdf_pagerendercontext.h +++ b/core/fpdfapi/cpdf_pagerendercontext.h @@ -21,11 +21,12 @@ class CPDF_PageRenderContext { CPDF_PageRenderContext(); ~CPDF_PageRenderContext(); + // Specific destruction order required. std::unique_ptr m_pAnnots; + std::unique_ptr m_pOptions; std::unique_ptr m_pDevice; std::unique_ptr m_pContext; std::unique_ptr m_pRenderer; - std::unique_ptr m_pOptions; }; #endif // CORE_FPDFAPI_CPDF_PAGERENDERCONTEXT_H_ diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e31da13a4d3f3ac05d336ac85f875631d8c2e7a3 --- /dev/null +++ b/core/fpdfapi/edit/cpdf_creator.cpp @@ -0,0 +1,852 @@ +// 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 "core/fpdfapi/edit/cpdf_creator.h" + +#include + +#include "core/fpdfapi/edit/cpdf_encryptor.h" +#include "core/fpdfapi/edit/cpdf_flateencoder.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_crypto_handler.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_parser.h" +#include "core/fpdfapi/parser/cpdf_security_handler.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_random.h" + +namespace { + +const size_t kArchiveBufferSize = 32768; + +class CFX_FileBufferArchive : public IFX_ArchiveStream { + public: + explicit CFX_FileBufferArchive(const RetainPtr& archive); + ~CFX_FileBufferArchive() override; + + bool WriteBlock(const void* pBuf, size_t size) override; + bool WriteByte(uint8_t byte) override; + bool WriteDWord(uint32_t i) override; + bool WriteString(const ByteStringView& str) override; + + FX_FILESIZE CurrentOffset() const override { return offset_; } + + private: + bool Flush(); + + FX_FILESIZE offset_; + size_t current_length_; + std::vector buffer_; + RetainPtr backing_file_; +}; + +CFX_FileBufferArchive::CFX_FileBufferArchive( + const RetainPtr& file) + : offset_(0), + current_length_(0), + buffer_(kArchiveBufferSize), + backing_file_(file) { + ASSERT(file); +} + +CFX_FileBufferArchive::~CFX_FileBufferArchive() { + Flush(); +} + +bool CFX_FileBufferArchive::Flush() { + size_t nRemaining = current_length_; + current_length_ = 0; + if (!backing_file_) + return false; + if (!nRemaining) + return true; + return backing_file_->WriteBlock(buffer_.data(), nRemaining); +} + +bool CFX_FileBufferArchive::WriteBlock(const void* pBuf, size_t size) { + ASSERT(pBuf && size > 0); + + const uint8_t* buffer = reinterpret_cast(pBuf); + size_t temp_size = size; + while (temp_size) { + size_t buf_size = std::min(kArchiveBufferSize - current_length_, temp_size); + memcpy(buffer_.data() + current_length_, buffer, buf_size); + + current_length_ += buf_size; + if (current_length_ == kArchiveBufferSize && !Flush()) + return false; + + temp_size -= buf_size; + buffer += buf_size; + } + + pdfium::base::CheckedNumeric safe_offset = offset_; + safe_offset += size; + if (!safe_offset.IsValid()) + return false; + + offset_ = safe_offset.ValueOrDie(); + return true; +} + +bool CFX_FileBufferArchive::WriteByte(uint8_t byte) { + return WriteBlock(&byte, 1); +} + +bool CFX_FileBufferArchive::WriteDWord(uint32_t i) { + char buf[32]; + FXSYS_itoa(i, buf, 10); + return WriteBlock(buf, strlen(buf)); +} + +bool CFX_FileBufferArchive::WriteString(const ByteStringView& str) { + return WriteBlock(str.raw_str(), str.GetLength()); +} + +std::vector GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) { + std::vector buffer(sizeof(uint32_t) * 4); + uint32_t* pBuffer = reinterpret_cast(buffer.data()); + void* pContext = FX_Random_MT_Start(dwSeed1); + for (int i = 0; i < 2; ++i) + *pBuffer++ = FX_Random_MT_Generate(pContext); + + FX_Random_MT_Close(pContext); + pContext = FX_Random_MT_Start(dwSeed2); + for (int i = 0; i < 2; ++i) + *pBuffer++ = FX_Random_MT_Generate(pContext); + + FX_Random_MT_Close(pContext); + return buffer; +} + +int32_t OutputIndex(IFX_ArchiveStream* archive, FX_FILESIZE offset) { + if (!archive->WriteByte(static_cast(offset >> 24)) || + !archive->WriteByte(static_cast(offset >> 16)) || + !archive->WriteByte(static_cast(offset >> 8)) || + !archive->WriteByte(static_cast(offset)) || + !archive->WriteByte(0)) { + return -1; + } + return 0; +} + +} // namespace + +CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc, + const RetainPtr& archive) + : m_pDocument(pDoc), + m_pParser(pDoc->GetParser()), + m_bSecurityChanged(false), + m_pEncryptDict(m_pParser ? m_pParser->GetEncryptDict() : nullptr), + m_dwEncryptObjNum(0), + m_pSecurityHandler(m_pParser ? m_pParser->GetSecurityHandler() : nullptr), + m_pMetadata(nullptr), + m_dwLastObjNum(m_pDocument->GetLastObjNum()), + m_Archive(pdfium::MakeUnique(archive)), + m_SavedOffset(0), + m_iStage(-1), + m_dwFlags(0), + m_CurObjNum(0), + m_XrefStart(0), + m_pIDArray(nullptr), + m_FileVersion(0) {} + +CPDF_Creator::~CPDF_Creator() {} + +bool CPDF_Creator::WriteStream(const CPDF_Object* pStream, + uint32_t objnum, + CPDF_CryptoHandler* pCrypto) { + CPDF_FlateEncoder encoder(const_cast(pStream->AsStream()), + pStream != m_pMetadata); + CPDF_Encryptor encryptor(pCrypto, objnum, encoder.GetData(), + encoder.GetSize()); + if (static_cast(encoder.GetDict()->GetIntegerFor("Length")) != + encryptor.GetSize()) { + encoder.CloneDict(); + encoder.GetDict()->SetNewFor( + "Length", static_cast(encryptor.GetSize())); + } + + if (!WriteDirectObj(objnum, encoder.GetDict(), true) || + !m_Archive->WriteString("stream\r\n")) { + return false; + } + + // Allow for empty streams. + if (encryptor.GetSize() > 0 && + !m_Archive->WriteBlock(encryptor.GetData(), encryptor.GetSize())) { + return false; + } + + return m_Archive->WriteString("\r\nendstream"); +} + +bool CPDF_Creator::WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj) { + if (!m_Archive->WriteDWord(objnum) || !m_Archive->WriteString(" 0 obj\r\n")) + return false; + + if (pObj->IsStream()) { + CPDF_CryptoHandler* pHandler = + pObj != m_pMetadata ? GetCryptoHandler() : nullptr; + if (!WriteStream(pObj, objnum, pHandler)) + return false; + } else if (!WriteDirectObj(objnum, pObj, true)) { + return false; + } + + return m_Archive->WriteString("\r\nendobj\r\n"); +} + +bool CPDF_Creator::WriteDirectObj(uint32_t objnum, + const CPDF_Object* pObj, + bool bEncrypt) { + switch (pObj->GetType()) { + case CPDF_Object::BOOLEAN: + case CPDF_Object::NAME: + case CPDF_Object::NULLOBJ: + case CPDF_Object::NUMBER: + case CPDF_Object::REFERENCE: + if (!pObj->WriteTo(m_Archive.get())) + return false; + break; + + case CPDF_Object::STRING: { + ByteString str = pObj->GetString(); + bool bHex = pObj->AsString()->IsHex(); + if (!GetCryptoHandler() || !bEncrypt) { + if (!pObj->WriteTo(m_Archive.get())) + return false; + break; + } + CPDF_Encryptor encryptor(GetCryptoHandler(), objnum, + (uint8_t*)str.c_str(), str.GetLength()); + ByteString content = PDF_EncodeString( + ByteString(encryptor.GetData(), encryptor.GetSize()), bHex); + if (!m_Archive->WriteString(content.AsStringView())) + return false; + break; + } + case CPDF_Object::STREAM: { + CPDF_FlateEncoder encoder(const_cast(pObj->AsStream()), + true); + CPDF_Encryptor encryptor(GetCryptoHandler(), objnum, encoder.GetData(), + encoder.GetSize()); + if (static_cast(encoder.GetDict()->GetIntegerFor("Length")) != + encryptor.GetSize()) { + encoder.CloneDict(); + encoder.GetDict()->SetNewFor( + "Length", static_cast(encryptor.GetSize())); + } + if (!WriteDirectObj(objnum, encoder.GetDict(), true) || + !m_Archive->WriteString("stream\r\n") || + !m_Archive->WriteBlock(encryptor.GetData(), encryptor.GetSize()) || + !m_Archive->WriteString("\r\nendstream")) { + return false; + } + + break; + } + case CPDF_Object::ARRAY: { + if (!m_Archive->WriteString("[")) + return false; + + const CPDF_Array* p = pObj->AsArray(); + for (size_t i = 0; i < p->GetCount(); i++) { + CPDF_Object* pElement = p->GetObjectAt(i); + if (!pElement->IsInline()) { + if (!m_Archive->WriteString(" ") || + !m_Archive->WriteDWord(pElement->GetObjNum()) || + !m_Archive->WriteString(" 0 R")) { + return false; + } + } else if (!WriteDirectObj(objnum, pElement, true)) { + return false; + } + } + if (!m_Archive->WriteString("]")) + return false; + break; + } + case CPDF_Object::DICTIONARY: { + if (!GetCryptoHandler() || pObj == m_pEncryptDict) { + if (!pObj->WriteTo(m_Archive.get())) + return false; + break; + } + + if (!m_Archive->WriteString("<<")) + return false; + + const CPDF_Dictionary* p = pObj->AsDictionary(); + bool bSignDict = p->IsSignatureDict(); + for (const auto& it : *p) { + bool bSignValue = false; + const ByteString& key = it.first; + CPDF_Object* pValue = it.second.get(); + if (!m_Archive->WriteString("/") || + !m_Archive->WriteString(PDF_NameEncode(key).AsStringView())) { + return false; + } + + if (bSignDict && key == "Contents") + bSignValue = true; + if (!pValue->IsInline()) { + if (!m_Archive->WriteString(" ") || + !m_Archive->WriteDWord(pValue->GetObjNum()) || + !m_Archive->WriteString(" 0 R ")) { + return false; + } + } else if (!WriteDirectObj(objnum, pValue, !bSignValue)) { + return false; + } + } + if (!m_Archive->WriteString(">>")) + return false; + break; + } + } + return true; +} + +bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { + if (m_pParser->IsObjectFreeOrNull(objnum)) + return true; + + m_ObjectOffsets[objnum] = m_Archive->CurrentOffset(); + + bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum); + CPDF_Object* pObj = m_pDocument->GetOrParseIndirectObject(objnum); + if (!pObj) { + m_ObjectOffsets.erase(objnum); + return true; + } + if (!WriteIndirectObj(pObj->GetObjNum(), pObj)) + return false; + if (!bExistInMap) + m_pDocument->DeleteIndirectObject(objnum); + return true; +} + +bool CPDF_Creator::WriteOldObjs() { + uint32_t nLastObjNum = m_pParser->GetLastObjNum(); + if (!m_pParser->IsValidObjectNumber(nLastObjNum)) + return true; + + for (uint32_t objnum = m_CurObjNum; objnum <= nLastObjNum; ++objnum) { + if (!WriteOldIndirectObject(objnum)) + return false; + } + return true; +} + +bool CPDF_Creator::WriteNewObjs() { + for (size_t i = m_CurObjNum; i < m_NewObjNumArray.size(); ++i) { + uint32_t objnum = m_NewObjNumArray[i]; + CPDF_Object* pObj = m_pDocument->GetIndirectObject(objnum); + if (!pObj) + continue; + + m_ObjectOffsets[objnum] = m_Archive->CurrentOffset(); + if (!WriteIndirectObj(pObj->GetObjNum(), pObj)) + return false; + } + return true; +} + +void CPDF_Creator::InitOldObjNumOffsets() { + if (!m_pParser) + return; + + uint32_t dwStart = 0; + uint32_t dwEnd = m_pParser->GetLastObjNum(); + while (dwStart <= dwEnd) { + while (dwStart <= dwEnd && m_pParser->IsObjectFreeOrNull(dwStart)) + dwStart++; + + if (dwStart > dwEnd) + break; + + uint32_t j = dwStart; + while (j <= dwEnd && !m_pParser->IsObjectFreeOrNull(j)) + j++; + + dwStart = j; + } +} + +void CPDF_Creator::InitNewObjNumOffsets() { + for (const auto& pair : *m_pDocument) { + const uint32_t objnum = pair.first; + if (IsIncremental() || + pair.second->GetObjNum() == CPDF_Object::kInvalidObjNum) { + continue; + } + if (m_pParser && m_pParser->IsValidObjectNumber(objnum) && + !m_pParser->IsObjectFree(objnum)) { + continue; + } + m_NewObjNumArray.insert(std::lower_bound(m_NewObjNumArray.begin(), + m_NewObjNumArray.end(), objnum), + objnum); + } +} + +int32_t CPDF_Creator::WriteDoc_Stage1() { + ASSERT(m_iStage > -1 || m_iStage < 20); + if (m_iStage == 0) { + if (!m_pParser) + m_dwFlags &= ~FPDFCREATE_INCREMENTAL; + if (m_bSecurityChanged && IsOriginal()) + m_dwFlags &= ~FPDFCREATE_INCREMENTAL; + + const CPDF_Dictionary* pDict = m_pDocument->GetRoot(); + m_pMetadata = pDict ? pDict->GetDirectObjectFor("Metadata") : nullptr; + m_iStage = 10; + } + if (m_iStage == 10) { + if (!IsIncremental()) { + if (!m_Archive->WriteString("%PDF-1.")) + return -1; + + int32_t version = 7; + if (m_FileVersion) + version = m_FileVersion; + else if (m_pParser) + version = m_pParser->GetFileVersion(); + + if (!m_Archive->WriteDWord(version % 10) || + !m_Archive->WriteString("\r\n%\xA1\xB3\xC5\xD7\r\n")) { + return -1; + } + + InitOldObjNumOffsets(); + m_iStage = 20; + } else { + m_SavedOffset = m_pParser->GetFileAccess()->GetSize(); + m_iStage = 15; + } + } + if (m_iStage == 15) { + if (IsOriginal() && m_SavedOffset > 0) { + RetainPtr pSrcFile = m_pParser->GetFileAccess(); + std::vector buffer(4096); + FX_FILESIZE src_size = m_SavedOffset; + while (src_size) { + uint32_t block_size = src_size > 4096 ? 4096 : src_size; + if (!pSrcFile->ReadBlock(buffer.data(), + m_Archive->CurrentOffset() - src_size, + block_size)) { + return -1; + } + if (!m_Archive->WriteBlock(buffer.data(), block_size)) + return -1; + + src_size -= block_size; + } + } + if (IsOriginal() && m_pParser->GetLastXRefOffset() == 0) { + InitOldObjNumOffsets(); + + for (uint32_t num = 0; num <= m_pParser->GetLastObjNum(); ++num) { + if (m_pParser->IsObjectFreeOrNull(num)) + continue; + + m_ObjectOffsets[num] = m_pParser->GetObjectPositionOrZero(num); + } + } + m_iStage = 20; + } + InitNewObjNumOffsets(); + return m_iStage; +} + +int32_t CPDF_Creator::WriteDoc_Stage2() { + ASSERT(m_iStage >= 20 || m_iStage < 30); + if (m_iStage == 20) { + if (!IsIncremental() && m_pParser) { + m_CurObjNum = 0; + m_iStage = 21; + } else { + m_iStage = 25; + } + } + if (m_iStage == 21) { + if (!WriteOldObjs()) + return -1; + + m_iStage = 25; + } + if (m_iStage == 25) { + m_CurObjNum = 0; + m_iStage = 26; + } + if (m_iStage == 26) { + if (!WriteNewObjs()) + return -1; + + m_iStage = 27; + } + if (m_iStage == 27) { + if (m_pEncryptDict && m_pEncryptDict->IsInline()) { + m_dwLastObjNum += 1; + FX_FILESIZE saveOffset = m_Archive->CurrentOffset(); + if (!WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict.Get())) + return -1; + + m_ObjectOffsets[m_dwLastObjNum] = saveOffset; + m_dwEncryptObjNum = m_dwLastObjNum; + if (IsIncremental()) + m_NewObjNumArray.push_back(m_dwLastObjNum); + } + m_iStage = 80; + } + return m_iStage; +} + +int32_t CPDF_Creator::WriteDoc_Stage3() { + ASSERT(m_iStage >= 80 || m_iStage < 90); + + uint32_t dwLastObjNum = m_dwLastObjNum; + if (m_iStage == 80) { + m_XrefStart = m_Archive->CurrentOffset(); + if (!IsIncremental() || !m_pParser->IsXRefStream()) { + if (!IsIncremental() || m_pParser->GetLastXRefOffset() == 0) { + ByteString str; + str = pdfium::ContainsKey(m_ObjectOffsets, 1) + ? "xref\r\n" + : "xref\r\n0 1\r\n0000000000 65535 f\r\n"; + if (!m_Archive->WriteString(str.AsStringView())) + return -1; + + m_CurObjNum = 1; + m_iStage = 81; + } else { + if (!m_Archive->WriteString("xref\r\n")) + return -1; + + m_CurObjNum = 0; + m_iStage = 82; + } + } else { + m_iStage = 90; + } + } + if (m_iStage == 81) { + ByteString str; + uint32_t i = m_CurObjNum; + uint32_t j; + while (i <= dwLastObjNum) { + while (i <= dwLastObjNum && !pdfium::ContainsKey(m_ObjectOffsets, i)) + i++; + + if (i > dwLastObjNum) + break; + + j = i; + while (j <= dwLastObjNum && pdfium::ContainsKey(m_ObjectOffsets, j)) + j++; + + if (i == 1) + str = ByteString::Format("0 %d\r\n0000000000 65535 f\r\n", j); + else + str = ByteString::Format("%d %d\r\n", i, j - i); + + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) + return -1; + + while (i < j) { + str = ByteString::Format("%010d 00000 n\r\n", m_ObjectOffsets[i++]); + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) + return -1; + } + if (i > dwLastObjNum) + break; + } + m_iStage = 90; + } + if (m_iStage == 82) { + ByteString str; + uint32_t iCount = pdfium::CollectionSize(m_NewObjNumArray); + uint32_t i = m_CurObjNum; + while (i < iCount) { + size_t j = i; + uint32_t objnum = m_NewObjNumArray[i]; + while (j < iCount) { + if (++j == iCount) + break; + uint32_t dwCurrent = m_NewObjNumArray[j]; + if (dwCurrent - objnum > 1) + break; + objnum = dwCurrent; + } + objnum = m_NewObjNumArray[i]; + if (objnum == 1) + str = ByteString::Format("0 %d\r\n0000000000 65535 f\r\n", j - i + 1); + else + str = ByteString::Format("%d %d\r\n", objnum, j - i); + + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) + return -1; + + while (i < j) { + objnum = m_NewObjNumArray[i++]; + str = ByteString::Format("%010d 00000 n\r\n", m_ObjectOffsets[objnum]); + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) + return -1; + } + } + m_iStage = 90; + } + return m_iStage; +} + +int32_t CPDF_Creator::WriteDoc_Stage4() { + ASSERT(m_iStage >= 90); + + bool bXRefStream = IsIncremental() && m_pParser->IsXRefStream(); + if (!bXRefStream) { + if (!m_Archive->WriteString("trailer\r\n<<")) + return -1; + } else { + if (!m_Archive->WriteDWord(m_pDocument->GetLastObjNum() + 1) || + !m_Archive->WriteString(" 0 obj <<")) { + return -1; + } + } + + if (m_pParser) { + std::unique_ptr p = m_pParser->GetCombinedTrailer(); + for (const auto& it : *p) { + const ByteString& key = it.first; + CPDF_Object* pValue = it.second.get(); + if (key == "Encrypt" || key == "Size" || key == "Filter" || + key == "Index" || key == "Length" || key == "Prev" || key == "W" || + key == "XRefStm" || key == "ID") { + continue; + } + if (!m_Archive->WriteString(("/")) || + !m_Archive->WriteString(PDF_NameEncode(key).AsStringView())) { + return -1; + } + if (!pValue->IsInline()) { + if (!m_Archive->WriteString(" ") || + !m_Archive->WriteDWord(pValue->GetObjNum()) || + !m_Archive->WriteString(" 0 R ")) { + return -1; + } + } else if (!pValue->WriteTo(m_Archive.get())) { + return -1; + } + } + } else { + if (!m_Archive->WriteString("\r\n/Root ") || + !m_Archive->WriteDWord(m_pDocument->GetRoot()->GetObjNum()) || + !m_Archive->WriteString(" 0 R\r\n")) { + return -1; + } + if (m_pDocument->GetInfo()) { + if (!m_Archive->WriteString("/Info ") || + !m_Archive->WriteDWord(m_pDocument->GetInfo()->GetObjNum()) || + !m_Archive->WriteString(" 0 R\r\n")) { + return -1; + } + } + } + if (m_pEncryptDict) { + if (!m_Archive->WriteString("/Encrypt")) + return -1; + + uint32_t dwObjNum = m_pEncryptDict->GetObjNum(); + if (dwObjNum == 0) + dwObjNum = m_pDocument->GetLastObjNum() + 1; + if (!m_Archive->WriteString(" ") || !m_Archive->WriteDWord(dwObjNum) || + !m_Archive->WriteString(" 0 R ")) { + return -1; + } + } + + if (!m_Archive->WriteString("/Size ") || + !m_Archive->WriteDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1))) { + return -1; + } + if (IsIncremental()) { + FX_FILESIZE prev = m_pParser->GetLastXRefOffset(); + if (prev) { + if (!m_Archive->WriteString("/Prev ")) + return -1; + + char offset_buf[20]; + memset(offset_buf, 0, sizeof(offset_buf)); + FXSYS_i64toa(prev, offset_buf, 10); + if (!m_Archive->WriteBlock(offset_buf, strlen(offset_buf))) + return -1; + } + } + if (m_pIDArray) { + if (!m_Archive->WriteString(("/ID")) || + !m_pIDArray->WriteTo(m_Archive.get())) { + return -1; + } + } + if (!bXRefStream) { + if (!m_Archive->WriteString(">>")) + return -1; + } else { + if (!m_Archive->WriteString("/W[0 4 1]/Index[")) + return -1; + if (IsIncremental() && m_pParser && m_pParser->GetLastXRefOffset() == 0) { + uint32_t i = 0; + for (i = 0; i < m_dwLastObjNum; i++) { + if (!pdfium::ContainsKey(m_ObjectOffsets, i)) + continue; + if (!m_Archive->WriteDWord(i) || !m_Archive->WriteString(" 1 ")) + return -1; + } + if (!m_Archive->WriteString("]/Length ") || + !m_Archive->WriteDWord(m_dwLastObjNum * 5) || + !m_Archive->WriteString(">>stream\r\n")) { + return -1; + } + for (i = 0; i < m_dwLastObjNum; i++) { + auto it = m_ObjectOffsets.find(i); + if (it == m_ObjectOffsets.end()) + continue; + OutputIndex(m_Archive.get(), it->second); + } + } else { + size_t count = m_NewObjNumArray.size(); + size_t i = 0; + for (i = 0; i < count; i++) { + if (!m_Archive->WriteDWord(m_NewObjNumArray[i]) || + !m_Archive->WriteString(" 1 ")) { + return -1; + } + } + if (!m_Archive->WriteString("]/Length ") || + !m_Archive->WriteDWord(count * 5) || + !m_Archive->WriteString(">>stream\r\n")) { + return -1; + } + for (i = 0; i < count; ++i) + OutputIndex(m_Archive.get(), m_ObjectOffsets[m_NewObjNumArray[i]]); + } + if (!m_Archive->WriteString("\r\nendstream")) + return -1; + } + + if (!m_Archive->WriteString("\r\nstartxref\r\n")) + return -1; + + char offset_buf[20]; + memset(offset_buf, 0, sizeof(offset_buf)); + FXSYS_i64toa(m_XrefStart, offset_buf, 10); + if (!m_Archive->WriteBlock(offset_buf, strlen(offset_buf)) || + !m_Archive->WriteString("\r\n%%EOF\r\n")) { + return -1; + } + + m_iStage = 100; + return m_iStage; +} + +bool CPDF_Creator::Create(uint32_t flags) { + m_dwFlags = flags; + m_iStage = 0; + m_dwLastObjNum = m_pDocument->GetLastObjNum(); + m_ObjectOffsets.clear(); + m_NewObjNumArray.clear(); + + InitID(); + return Continue() > -1; +} + +void CPDF_Creator::InitID() { + const CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : nullptr; + + bool idArrayPreExisting = !!m_pIDArray; + if (!idArrayPreExisting) { + m_pIDArray = pdfium::MakeUnique(); + CPDF_Object* pID1 = pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr; + if (pID1) { + m_pIDArray->Add(pID1->Clone()); + } else { + std::vector buffer = + GenerateFileID((uint32_t)(uintptr_t)this, m_dwLastObjNum); + ByteString bsBuffer(buffer.data(), buffer.size()); + m_pIDArray->AddNew(bsBuffer, true); + } + } + + if (pOldIDArray) { + CPDF_Object* pID2 = pOldIDArray->GetObjectAt(1); + if (IsIncremental() && m_pEncryptDict && pID2) { + m_pIDArray->Add(pID2->Clone()); + return; + } + std::vector buffer = + GenerateFileID((uint32_t)(uintptr_t)this, m_dwLastObjNum); + ByteString bsBuffer(buffer.data(), buffer.size()); + m_pIDArray->AddNew(bsBuffer, true); + return; + } + + m_pIDArray->Add(m_pIDArray->GetObjectAt(0)->Clone()); + if (m_pEncryptDict && !pOldIDArray && m_pParser && !idArrayPreExisting) { + if (m_pEncryptDict->GetStringFor("Filter") == "Standard") { + ByteString user_pass = m_pParser->GetPassword(); + m_pSecurityHandler = pdfium::MakeUnique(); + m_pSecurityHandler->OnCreate(m_pEncryptDict.Get(), m_pIDArray.get(), + user_pass); + m_bSecurityChanged = true; + } + } +} + +int32_t CPDF_Creator::Continue() { + if (m_iStage < 0) + return m_iStage; + + int32_t iRet = 0; + while (m_iStage < 100) { + if (m_iStage < 20) + iRet = WriteDoc_Stage1(); + else if (m_iStage < 30) + iRet = WriteDoc_Stage2(); + else if (m_iStage < 90) + iRet = WriteDoc_Stage3(); + else + iRet = WriteDoc_Stage4(); + + if (iRet < m_iStage) + break; + } + + if (iRet < 1 || m_iStage == 100) { + m_iStage = -1; + return iRet > 99 ? 0 : (iRet < 1 ? -1 : iRet); + } + return m_iStage; +} + +bool CPDF_Creator::SetFileVersion(int32_t fileVersion) { + if (fileVersion < 10 || fileVersion > 17) + return false; + m_FileVersion = fileVersion; + return true; +} + +void CPDF_Creator::RemoveSecurity() { + m_pSecurityHandler.Reset(); + m_bSecurityChanged = true; + m_pEncryptDict = nullptr; +} + +CPDF_CryptoHandler* CPDF_Creator::GetCryptoHandler() { + return m_pSecurityHandler ? m_pSecurityHandler->GetCryptoHandler() : nullptr; +} diff --git a/core/fpdfapi/edit/cpdf_creator.h b/core/fpdfapi/edit/cpdf_creator.h index 0840e4b7a6546678938859e3ee80eabc45f6ee3e..4c1d0f1800e6676f7c67a6e28250d26bce6c3571 100644 --- a/core/fpdfapi/edit/cpdf_creator.h +++ b/core/fpdfapi/edit/cpdf_creator.h @@ -7,94 +7,96 @@ #ifndef CORE_FPDFAPI_EDIT_CPDF_CREATOR_H_ #define CORE_FPDFAPI_EDIT_CPDF_CREATOR_H_ +#include #include #include -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Array; class CPDF_CryptoHandler; +class CPDF_SecurityHandler; class CPDF_Dictionary; class CPDF_Document; class CPDF_Object; class CPDF_Parser; -class CPDF_XRefStream; #define FPDFCREATE_INCREMENTAL 1 #define FPDFCREATE_NO_ORIGINAL 2 -#define FPDFCREATE_PROGRESSIVE 4 -#define FPDFCREATE_OBJECTSTREAM 8 - -CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj); class CPDF_Creator { public: - explicit CPDF_Creator(CPDF_Document* pDoc); + explicit CPDF_Creator(CPDF_Document* pDoc, + const RetainPtr& archive); ~CPDF_Creator(); void RemoveSecurity(); - bool Create(const CFX_RetainPtr& pFile, uint32_t flags = 0); - int32_t Continue(IFX_Pause* pPause = nullptr); - bool SetFileVersion(int32_t fileVersion = 17); + bool Create(uint32_t flags); + int32_t Continue(); + bool SetFileVersion(int32_t fileVersion); + + IFX_ArchiveStream* GetArchive() { return m_Archive.get(); } + + uint32_t GetNextObjectNumber() { return ++m_dwLastObjNum; } + uint32_t GetLastObjectNumber() const { return m_dwLastObjNum; } + CPDF_CryptoHandler* GetCryptoHandler(); + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } + CPDF_Array* GetIDArray() const { return m_pIDArray.get(); } + CPDF_Dictionary* GetEncryptDict() const { return m_pEncryptDict.Get(); } + uint32_t GetEncryptObjectNumber() const { return m_dwEncryptObjNum; } + + uint32_t GetObjectOffset(uint32_t objnum) { return m_ObjectOffsets[objnum]; } + bool HasObjectNumber(uint32_t objnum) { + return m_ObjectOffsets.find(objnum) != m_ObjectOffsets.end(); + } + void SetObjectOffset(uint32_t objnum, FX_FILESIZE offset) { + m_ObjectOffsets[objnum] = offset; + } + bool IsIncremental() const { return !!(m_dwFlags & FPDFCREATE_INCREMENTAL); } + bool IsOriginal() const { return !(m_dwFlags & FPDFCREATE_NO_ORIGINAL); } private: - friend class CPDF_ObjectStream; - friend class CPDF_XRefStream; - - bool Create(uint32_t flags); - void ResetStandardSecurity(); void Clear(); void InitOldObjNumOffsets(); void InitNewObjNumOffsets(); - void InitID(bool bDefault = true); - - void AppendNewObjNum(uint32_t objbum); - int32_t AppendObjectNumberToXRef(uint32_t objnum); - - int32_t WriteDoc_Stage1(IFX_Pause* pPause); - int32_t WriteDoc_Stage2(IFX_Pause* pPause); - int32_t WriteDoc_Stage3(IFX_Pause* pPause); - int32_t WriteDoc_Stage4(IFX_Pause* pPause); - - int32_t WriteOldIndirectObject(uint32_t objnum); - int32_t WriteOldObjs(IFX_Pause* pPause); - int32_t WriteNewObjs(bool bIncremental, IFX_Pause* pPause); - int32_t WriteIndirectObj(const CPDF_Object* pObj); - int32_t WriteDirectObj(uint32_t objnum, - const CPDF_Object* pObj, - bool bEncrypt = true); - int32_t WriteIndirectObjectToStream(const CPDF_Object* pObj); - int32_t WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj); - int32_t WriteIndirectObjectToStream(uint32_t objnum, - const uint8_t* pBuffer, - uint32_t dwSize); - - int32_t WriteStream(const CPDF_Object* pStream, - uint32_t objnum, - CPDF_CryptoHandler* pCrypto); - - CPDF_Document* const m_pDocument; - CPDF_Parser* const m_pParser; + void InitID(); + + int32_t WriteDoc_Stage1(); + int32_t WriteDoc_Stage2(); + int32_t WriteDoc_Stage3(); + int32_t WriteDoc_Stage4(); + + bool WriteOldIndirectObject(uint32_t objnum); + bool WriteOldObjs(); + bool WriteNewObjs(); + bool WriteDirectObj(uint32_t objnum, const CPDF_Object* pObj, bool bEncrypt); + bool WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj); + + bool WriteStream(const CPDF_Object* pStream, + uint32_t objnum, + CPDF_CryptoHandler* pCrypto); + + bool IsXRefNeedEnd(); + + UnownedPtr const m_pDocument; + UnownedPtr const m_pParser; bool m_bSecurityChanged; - CPDF_Dictionary* m_pEncryptDict; + UnownedPtr m_pEncryptDict; uint32_t m_dwEncryptObjNum; - bool m_bEncryptCloned; - CPDF_CryptoHandler* m_pCryptoHandler; - // Whether this owns the crypto handler |m_pCryptoHandler|. - bool m_bLocalCryptoHandler; - CPDF_Object* m_pMetadata; - std::unique_ptr m_pXRefStream; - int32_t m_ObjectStreamSize; + fxcrt::MaybeOwned m_pSecurityHandler; + UnownedPtr m_pMetadata; uint32_t m_dwLastObjNum; - CFX_FileBufferArchive m_File; - FX_FILESIZE m_Offset; + std::unique_ptr m_Archive; + FX_FILESIZE m_SavedOffset; int32_t m_iStage; uint32_t m_dwFlags; - FX_POSITION m_Pos; + uint32_t m_CurObjNum; FX_FILESIZE m_XrefStart; - CFX_FileSizeListArray m_ObjectOffset; + std::map m_ObjectOffsets; std::vector m_NewObjNumArray; // Sorted, ascending. std::unique_ptr m_pIDArray; int32_t m_FileVersion; diff --git a/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..def7d50a9740927c61f199b6d4548efbf992f99b --- /dev/null +++ b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "public/fpdf_annot.h" +#include "public/fpdf_edit.h" +#include "public/fpdfview.h" +#include "testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CPDF_CreatorEmbedderTest : public EmbedderTest {}; + +TEST_F(CPDF_CreatorEmbedderTest, SavedDocsAreEqualAfterParse) { + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + // Save without additional data reading. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + const std::string saved_doc_1 = GetString(); + ClearString(); + + { + // Do some read only operations. + ASSERT_GE(1, FPDF_GetPageCount(document())); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + FPDF_BITMAP new_bitmap = + RenderPageWithFlags(page, form_handle(), FPDF_ANNOT); + FPDFBitmap_Destroy(new_bitmap); + UnloadPage(page); + } + + // Save when we have additional loaded data. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + const std::string saved_doc_2 = GetString(); + ClearString(); + + // The sizes of saved docs should be equal. + EXPECT_EQ(saved_doc_1.size(), saved_doc_2.size()); +} diff --git a/core/fpdfapi/edit/cpdf_encryptor.cpp b/core/fpdfapi/edit/cpdf_encryptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..858b5b63691a749de2112a6610a00ba2304959ce --- /dev/null +++ b/core/fpdfapi/edit/cpdf_encryptor.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/edit/cpdf_encryptor.h" +#include "core/fpdfapi/parser/cpdf_crypto_handler.h" + +CPDF_Encryptor::CPDF_Encryptor(CPDF_CryptoHandler* pHandler, + int objnum, + uint8_t* src_data, + uint32_t src_size) + : m_pData(nullptr), m_dwSize(0), m_bNewBuf(false) { + if (src_size == 0) + return; + + if (!pHandler) { + m_pData = (uint8_t*)src_data; + m_dwSize = src_size; + return; + } + m_dwSize = pHandler->EncryptGetSize(objnum, 0, src_data, src_size); + m_pData = FX_Alloc(uint8_t, m_dwSize); + pHandler->EncryptContent(objnum, 0, src_data, src_size, m_pData, m_dwSize); + m_bNewBuf = true; +} + +CPDF_Encryptor::~CPDF_Encryptor() { + if (m_bNewBuf) + FX_Free(m_pData); +} diff --git a/core/fpdfapi/edit/cpdf_encryptor.h b/core/fpdfapi/edit/cpdf_encryptor.h new file mode 100644 index 0000000000000000000000000000000000000000..00c9337eb3445246f1a15d8b36f565cdd07a4ed6 --- /dev/null +++ b/core/fpdfapi/edit/cpdf_encryptor.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_EDIT_CPDF_ENCRYPTOR_H_ +#define CORE_FPDFAPI_EDIT_CPDF_ENCRYPTOR_H_ + +#include + +class CPDF_CryptoHandler; + +class CPDF_Encryptor { + public: + CPDF_Encryptor(CPDF_CryptoHandler* pHandler, + int objnum, + uint8_t* src_data, + uint32_t src_size); + ~CPDF_Encryptor(); + + uint32_t GetSize() const { return m_dwSize; } + uint8_t* GetData() const { return m_pData; } + + private: + uint8_t* m_pData; + uint32_t m_dwSize; + bool m_bNewBuf; +}; + +#endif // CORE_FPDFAPI_EDIT_CPDF_ENCRYPTOR_H_ diff --git a/core/fpdfapi/edit/cpdf_flateencoder.cpp b/core/fpdfapi/edit/cpdf_flateencoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..555da84244700bc5095d6f62583b9d80faa8ce93 --- /dev/null +++ b/core/fpdfapi/edit/cpdf_flateencoder.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/edit/cpdf_flateencoder.h" + +#include + +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" + +CPDF_FlateEncoder::CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode) + : m_dwSize(0), m_pAcc(pdfium::MakeRetain(pStream)) { + m_pAcc->LoadAllDataRaw(); + + bool bHasFilter = pStream && pStream->HasFilter(); + if (bHasFilter && !bFlateEncode) { + auto pDestAcc = pdfium::MakeRetain(pStream); + pDestAcc->LoadAllDataFiltered(); + + m_dwSize = pDestAcc->GetSize(); + m_pData = pDestAcc->DetachData(); + m_pDict = ToDictionary(pStream->GetDict()->Clone()); + m_pDict->RemoveFor("Filter"); + return; + } + if (bHasFilter || !bFlateEncode) { + m_pData = const_cast(m_pAcc->GetData()); + m_dwSize = m_pAcc->GetSize(); + m_pDict = pStream->GetDict(); + return; + } + + // TODO(thestig): Move to Init() and check return value. + uint8_t* buffer = nullptr; + ::FlateEncode(m_pAcc->GetData(), m_pAcc->GetSize(), &buffer, &m_dwSize); + + m_pData = std::unique_ptr(buffer); + m_pDict = ToDictionary(pStream->GetDict()->Clone()); + m_pDict->SetNewFor("Length", static_cast(m_dwSize)); + m_pDict->SetNewFor("Filter", "FlateDecode"); + m_pDict->RemoveFor("DecodeParms"); +} + +CPDF_FlateEncoder::~CPDF_FlateEncoder() {} + +void CPDF_FlateEncoder::CloneDict() { + if (m_pDict.IsOwned()) + return; + + m_pDict = ToDictionary(m_pDict->Clone()); + ASSERT(m_pDict.IsOwned()); +} diff --git a/core/fpdfapi/edit/cpdf_flateencoder.h b/core/fpdfapi/edit/cpdf_flateencoder.h new file mode 100644 index 0000000000000000000000000000000000000000..887816c1a173abd048d9562da27ee8ff96defb4c --- /dev/null +++ b/core/fpdfapi/edit/cpdf_flateencoder.h @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_EDIT_CPDF_FLATEENCODER_H_ +#define CORE_FPDFAPI_EDIT_CPDF_FLATEENCODER_H_ + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxcrt/retain_ptr.h" + +class CPDF_Stream; + +class CPDF_FlateEncoder { + public: + CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode); + ~CPDF_FlateEncoder(); + + void CloneDict(); + + uint32_t GetSize() const { return m_dwSize; } + uint8_t* GetData() const { return m_pData.Get(); } + + CPDF_Dictionary* GetDict() { return m_pDict.Get(); } + + private: + uint32_t m_dwSize; + MaybeOwned m_pData; + MaybeOwned m_pDict; + RetainPtr m_pAcc; +}; + +#endif // CORE_FPDFAPI_EDIT_CPDF_FLATEENCODER_H_ diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index 35595b3e1f642b8f5d3b088440690131467c1129..8a08a849cccdd675fce226ad846c2168435da31a 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp @@ -17,6 +17,7 @@ #include "core/fpdfapi/page/cpdf_path.h" #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/page/cpdf_textobject.h" +#include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" @@ -27,17 +28,17 @@ namespace { -CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& ar, const CFX_Matrix& matrix) { +std::ostream& operator<<(std::ostream& ar, const CFX_Matrix& matrix) { ar << matrix.a << " " << matrix.b << " " << matrix.c << " " << matrix.d << " " << matrix.e << " " << matrix.f; return ar; } -bool GetColor(const CPDF_Color* pColor, FX_FLOAT* rgb) { +bool GetColor(const CPDF_Color* pColor, float* rgb) { int intRGB[3]; if (!pColor || pColor->GetColorSpace() != CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB) || - !pColor->GetRGB(intRGB[0], intRGB[1], intRGB[2])) { + !pColor->GetRGB(&intRGB[0], &intRGB[1], &intRGB[2])) { return false; } rgb[0] = intRGB[0] / 255.0f; @@ -48,65 +49,125 @@ bool GetColor(const CPDF_Color* pColor, FX_FLOAT* rgb) { } // namespace -CPDF_PageContentGenerator::CPDF_PageContentGenerator(CPDF_Page* pPage) - : m_pPage(pPage), m_pDocument(m_pPage->m_pDocument) { - for (const auto& pObj : *pPage->GetPageObjectList()) { +CPDF_PageContentGenerator::CPDF_PageContentGenerator( + CPDF_PageObjectHolder* pObjHolder) + : m_pObjHolder(pObjHolder), m_pDocument(pObjHolder->m_pDocument.Get()) { + for (const auto& pObj : *pObjHolder->GetPageObjectList()) { if (pObj) - m_pageObjects.push_back(pObj.get()); + m_pageObjects.emplace_back(pObj.get()); } } CPDF_PageContentGenerator::~CPDF_PageContentGenerator() {} void CPDF_PageContentGenerator::GenerateContent() { - CFX_ByteTextBuf buf; - for (CPDF_PageObject* pPageObj : m_pageObjects) { - if (CPDF_ImageObject* pImageObject = pPageObj->AsImage()) - ProcessImage(&buf, pImageObject); - else if (CPDF_PathObject* pPathObj = pPageObj->AsPath()) - ProcessPath(&buf, pPathObj); - else if (CPDF_TextObject* pTextObj = pPageObj->AsText()) - ProcessText(&buf, pTextObj); - } - CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict; - CPDF_Object* pContent = - pPageDict ? pPageDict->GetDirectObjectFor("Contents") : nullptr; - if (pContent) - pPageDict->RemoveFor("Contents"); + ASSERT(m_pObjHolder->IsPage()); + + CPDF_Document* pDoc = m_pDocument.Get(); + std::ostringstream buf; - CPDF_Stream* pStream = m_pDocument->NewIndirect(); - pStream->SetData(buf.GetBuffer(), buf.GetLength()); - pPageDict->SetNewFor("Contents", m_pDocument, + // Set the default graphic state values + buf << "q\n"; + if (!m_pObjHolder->GetLastCTM().IsIdentity()) + buf << m_pObjHolder->GetLastCTM().GetInverse() << " cm\n"; + ProcessDefaultGraphics(&buf); + + // Process the page objects + if (!ProcessPageObjects(&buf)) + return; + + // Return graphics to original state + buf << "Q\n"; + + // Add buffer to a stream in page's 'Contents' + CPDF_Dictionary* pPageDict = m_pObjHolder->m_pFormDict.Get(); + CPDF_Object* pContent = + pPageDict ? pPageDict->GetObjectFor("Contents") : nullptr; + CPDF_Stream* pStream = pDoc->NewIndirect(); + pStream->SetData(&buf); + if (pContent) { + CPDF_Array* pArray = ToArray(pContent); + if (pArray) { + pArray->AddNew(pDoc, pStream->GetObjNum()); + return; + } + CPDF_Reference* pReference = ToReference(pContent); + if (!pReference) { + pPageDict->SetNewFor("Contents", m_pDocument.Get(), + pStream->GetObjNum()); + return; + } + CPDF_Object* pDirectObj = pReference->GetDirect(); + if (!pDirectObj) { + pPageDict->SetNewFor("Contents", m_pDocument.Get(), + pStream->GetObjNum()); + return; + } + CPDF_Array* pObjArray = pDirectObj->AsArray(); + if (pObjArray) { + pObjArray->AddNew(pDoc, pStream->GetObjNum()); + return; + } + if (pDirectObj->IsStream()) { + CPDF_Array* pContentArray = pDoc->NewIndirect(); + pContentArray->AddNew(pDoc, pDirectObj->GetObjNum()); + pContentArray->AddNew(pDoc, pStream->GetObjNum()); + pPageDict->SetNewFor("Contents", pDoc, + pContentArray->GetObjNum()); + return; + } + } + pPageDict->SetNewFor("Contents", m_pDocument.Get(), pStream->GetObjNum()); } -CFX_ByteString CPDF_PageContentGenerator::RealizeResource( +ByteString CPDF_PageContentGenerator::RealizeResource( uint32_t dwResourceObjNum, - const CFX_ByteString& bsType) { + const ByteString& bsType) { ASSERT(dwResourceObjNum); - if (!m_pPage->m_pResources) { - m_pPage->m_pResources = m_pDocument->NewIndirect(); - m_pPage->m_pFormDict->SetNewFor( - "Resources", m_pDocument, m_pPage->m_pResources->GetObjNum()); + if (!m_pObjHolder->m_pResources) { + m_pObjHolder->m_pResources = m_pDocument->NewIndirect(); + m_pObjHolder->m_pFormDict->SetNewFor( + "Resources", m_pDocument.Get(), + m_pObjHolder->m_pResources->GetObjNum()); } - CPDF_Dictionary* pResList = m_pPage->m_pResources->GetDictFor(bsType); + CPDF_Dictionary* pResList = m_pObjHolder->m_pResources->GetDictFor(bsType); if (!pResList) - pResList = m_pPage->m_pResources->SetNewFor(bsType); + pResList = m_pObjHolder->m_pResources->SetNewFor(bsType); - CFX_ByteString name; + ByteString name; int idnum = 1; while (1) { - name.Format("FX%c%d", bsType[0], idnum); - if (!pResList->KeyExist(name)) { + name = ByteString::Format("FX%c%d", bsType[0], idnum); + if (!pResList->KeyExist(name)) break; - } + idnum++; } - pResList->SetNewFor(name, m_pDocument, dwResourceObjNum); + pResList->SetNewFor(name, m_pDocument.Get(), + dwResourceObjNum); return name; } -void CPDF_PageContentGenerator::ProcessImage(CFX_ByteTextBuf* buf, +bool CPDF_PageContentGenerator::ProcessPageObjects(std::ostringstream* buf) { + bool bDirty = false; + for (auto& pPageObj : m_pageObjects) { + if (m_pObjHolder->IsPage() && !pPageObj->IsDirty()) + continue; + + bDirty = true; + if (CPDF_ImageObject* pImageObject = pPageObj->AsImage()) + ProcessImage(buf, pImageObject); + else if (CPDF_PathObject* pPathObj = pPageObj->AsPath()) + ProcessPath(buf, pPathObj); + else if (CPDF_TextObject* pTextObj = pPageObj->AsText()) + ProcessText(buf, pTextObj); + pPageObj->SetDirty(false); + } + return bDirty; +} + +void CPDF_PageContentGenerator::ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj) { if ((pImageObj->matrix().a == 0 && pImageObj->matrix().b == 0) || (pImageObj->matrix().c == 0 && pImageObj->matrix().d == 0)) { @@ -114,7 +175,7 @@ void CPDF_PageContentGenerator::ProcessImage(CFX_ByteTextBuf* buf, } *buf << "q " << pImageObj->matrix() << " cm "; - CPDF_Image* pImage = pImageObj->GetImage(); + RetainPtr pImage = pImageObj->GetImage(); if (pImage->IsInline()) return; @@ -127,9 +188,9 @@ void CPDF_PageContentGenerator::ProcessImage(CFX_ByteTextBuf* buf, pImage->ConvertStreamToIndirectObject(); uint32_t dwObjNum = pStream->GetObjNum(); - CFX_ByteString name = RealizeResource(dwObjNum, "XObject"); + ByteString name = RealizeResource(dwObjNum, "XObject"); if (bWasInline) - pImageObj->SetUnownedImage(m_pDocument->GetPageData()->GetImage(dwObjNum)); + pImageObj->SetImage(m_pDocument->GetPageData()->GetImage(dwObjNum)); *buf << "/" << PDF_NameEncode(name) << " Do Q\n"; } @@ -145,9 +206,12 @@ void CPDF_PageContentGenerator::ProcessImage(CFX_ByteTextBuf* buf, // Path painting operators: "S", "n", "B", "f", "B*", "f*", depending on // the filling mode and whether we want stroking the path or not. // "Q" restores the graphics state imposed by the ProcessGraphics method. -void CPDF_PageContentGenerator::ProcessPath(CFX_ByteTextBuf* buf, +void CPDF_PageContentGenerator::ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj) { ProcessGraphics(buf, pPathObj); + + *buf << pPathObj->m_Matrix << " cm "; + auto& pPoints = pPathObj->m_Path.GetPoints(); if (pPathObj->m_Path.IsRect()) { CFX_PointF diff = pPoints[2].m_Point - pPoints[0].m_Point; @@ -198,79 +262,136 @@ void CPDF_PageContentGenerator::ProcessPath(CFX_ByteTextBuf* buf, // "w" sets the stroke line width. // "ca" sets the fill alpha, "CA" sets the stroke alpha. // "q" saves the graphics state, so that the settings can later be reversed -void CPDF_PageContentGenerator::ProcessGraphics(CFX_ByteTextBuf* buf, +void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj) { *buf << "q "; - FX_FLOAT fillColor[3]; + float fillColor[3]; if (GetColor(pPageObj->m_ColorState.GetFillColor(), fillColor)) { *buf << fillColor[0] << " " << fillColor[1] << " " << fillColor[2] << " rg "; } - FX_FLOAT strokeColor[3]; + float strokeColor[3]; if (GetColor(pPageObj->m_ColorState.GetStrokeColor(), strokeColor)) { *buf << strokeColor[0] << " " << strokeColor[1] << " " << strokeColor[2] << " RG "; } - FX_FLOAT lineWidth = pPageObj->m_GraphState.GetLineWidth(); + float lineWidth = pPageObj->m_GraphState.GetLineWidth(); if (lineWidth != 1.0f) *buf << lineWidth << " w "; + CFX_GraphStateData::LineCap lineCap = pPageObj->m_GraphState.GetLineCap(); + if (lineCap != CFX_GraphStateData::LineCapButt) + *buf << static_cast(lineCap) << " J "; + CFX_GraphStateData::LineJoin lineJoin = pPageObj->m_GraphState.GetLineJoin(); + if (lineJoin != CFX_GraphStateData::LineJoinMiter) + *buf << static_cast(lineJoin) << " j "; GraphicsData graphD; graphD.fillAlpha = pPageObj->m_GeneralState.GetFillAlpha(); graphD.strokeAlpha = pPageObj->m_GeneralState.GetStrokeAlpha(); - if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f) + graphD.blendType = pPageObj->m_GeneralState.GetBlendType(); + if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f && + (graphD.blendType == FXDIB_BLEND_UNSUPPORTED || + graphD.blendType == FXDIB_BLEND_NORMAL)) { return; + } - CFX_ByteString name; - auto it = m_pPage->m_GraphicsMap.find(graphD); - if (it != m_pPage->m_GraphicsMap.end()) { + ByteString name; + auto it = m_pObjHolder->m_GraphicsMap.find(graphD); + if (it != m_pObjHolder->m_GraphicsMap.end()) { name = it->second; } else { auto gsDict = pdfium::MakeUnique(); - gsDict->SetNewFor("ca", graphD.fillAlpha); - gsDict->SetNewFor("CA", graphD.strokeAlpha); + if (graphD.fillAlpha != 1.0f) + gsDict->SetNewFor("ca", graphD.fillAlpha); + + if (graphD.strokeAlpha != 1.0f) + gsDict->SetNewFor("CA", graphD.strokeAlpha); + + if (graphD.blendType != FXDIB_BLEND_UNSUPPORTED && + graphD.blendType != FXDIB_BLEND_NORMAL) { + gsDict->SetNewFor("BM", + pPageObj->m_GeneralState.GetBlendMode()); + } CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict)); uint32_t dwObjNum = pDict->GetObjNum(); name = RealizeResource(dwObjNum, "ExtGState"); - m_pPage->m_GraphicsMap[graphD] = name; + m_pObjHolder->m_GraphicsMap[graphD] = name; } *buf << "/" << PDF_NameEncode(name) << " gs "; } +void CPDF_PageContentGenerator::ProcessDefaultGraphics( + std::ostringstream* buf) { + *buf << "0 0 0 RG 0 0 0 rg 1 w " + << static_cast(CFX_GraphStateData::LineCapButt) << " J " + << static_cast(CFX_GraphStateData::LineJoinMiter) << " j\n"; + GraphicsData defaultGraphics; + defaultGraphics.fillAlpha = 1.0f; + defaultGraphics.strokeAlpha = 1.0f; + defaultGraphics.blendType = FXDIB_BLEND_NORMAL; + auto it = m_pObjHolder->m_GraphicsMap.find(defaultGraphics); + ByteString name; + if (it != m_pObjHolder->m_GraphicsMap.end()) { + name = it->second; + } else { + auto gsDict = pdfium::MakeUnique(); + gsDict->SetNewFor("ca", defaultGraphics.fillAlpha); + gsDict->SetNewFor("CA", defaultGraphics.strokeAlpha); + gsDict->SetNewFor("BM", "Normal"); + CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict)); + uint32_t dwObjNum = pDict->GetObjNum(); + name = RealizeResource(dwObjNum, "ExtGState"); + m_pObjHolder->m_GraphicsMap[defaultGraphics] = name; + } + *buf << "/" << PDF_NameEncode(name).c_str() << " gs "; +} + // This method adds text to the buffer, BT begins the text object, ET ends it. // Tm sets the text matrix (allows positioning and transforming text). // Tf sets the font name (from Font in Resources) and font size. // Tj sets the actual text, <####...> is used when specifying charcodes. -void CPDF_PageContentGenerator::ProcessText(CFX_ByteTextBuf* buf, +void CPDF_PageContentGenerator::ProcessText(std::ostringstream* buf, CPDF_TextObject* pTextObj) { - // TODO(npm): Add support for something other than standard type1 fonts. + ProcessGraphics(buf, pTextObj); *buf << "BT " << pTextObj->GetTextMatrix() << " Tm "; CPDF_Font* pFont = pTextObj->GetFont(); if (!pFont) - pFont = CPDF_Font::GetStockFont(m_pDocument, "Helvetica"); + pFont = CPDF_Font::GetStockFont(m_pDocument.Get(), "Helvetica"); FontData fontD; + if (pFont->IsType1Font()) + fontD.type = "Type1"; + else if (pFont->IsTrueTypeFont()) + fontD.type = "TrueType"; + else if (pFont->IsCIDFont()) + fontD.type = "Type0"; + else + return; fontD.baseFont = pFont->GetBaseFont(); - auto it = m_pPage->m_FontsMap.find(fontD); - CFX_ByteString dictName; - if (it != m_pPage->m_FontsMap.end()) { + auto it = m_pObjHolder->m_FontsMap.find(fontD); + ByteString dictName; + if (it != m_pObjHolder->m_FontsMap.end()) { dictName = it->second; } else { - auto fontDict = pdfium::MakeUnique(); - fontDict->SetNewFor("Type", "Font"); - fontDict->SetNewFor("Subtype", "Type1"); - fontDict->SetNewFor("BaseFont", fontD.baseFont); - CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(fontDict)); - uint32_t dwObjNum = pDict->GetObjNum(); + uint32_t dwObjNum = pFont->GetFontDict()->GetObjNum(); + if (!dwObjNum) { + // In this case we assume it must be a standard font + auto fontDict = pdfium::MakeUnique(); + fontDict->SetNewFor("Type", "Font"); + fontDict->SetNewFor("Subtype", fontD.type); + fontDict->SetNewFor("BaseFont", fontD.baseFont); + CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(fontDict)); + dwObjNum = pDict->GetObjNum(); + } dictName = RealizeResource(dwObjNum, "Font"); - m_pPage->m_FontsMap[fontD] = dictName; + m_pObjHolder->m_FontsMap[fontD] = dictName; } *buf << "/" << PDF_NameEncode(dictName) << " " << pTextObj->GetFontSize() << " Tf "; - CFX_ByteString text; - for (uint32_t charcode : pTextObj->m_CharCodes) { - if (charcode == CPDF_Font::kInvalidCharCode) - continue; - pFont->AppendChar(text, charcode); + ByteString text; + for (uint32_t charcode : pTextObj->GetCharCodes()) { + if (charcode != CPDF_Font::kInvalidCharCode) + pFont->AppendChar(&text, charcode); } - *buf << PDF_EncodeString(text, true) << " Tj ET\n"; + *buf << PDF_EncodeString(text, true) << " Tj ET"; + *buf << " Q\n"; } diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h index 73e75187e45291189927c3b2fc6e11e1c4706a2d..efc5739c4bce7cec2cab2d61b43c6804018e48f5 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h @@ -7,38 +7,42 @@ #ifndef CORE_FPDFAPI_EDIT_CPDF_PAGECONTENTGENERATOR_H_ #define CORE_FPDFAPI_EDIT_CPDF_PAGECONTENTGENERATOR_H_ +#include #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_ImageObject; -class CPDF_Page; class CPDF_PageObject; +class CPDF_PageObjectHolder; class CPDF_PathObject; class CPDF_TextObject; class CPDF_PageContentGenerator { public: - explicit CPDF_PageContentGenerator(CPDF_Page* pPage); + explicit CPDF_PageContentGenerator(CPDF_PageObjectHolder* pObjHolder); ~CPDF_PageContentGenerator(); void GenerateContent(); + bool ProcessPageObjects(std::ostringstream* buf); private: friend class CPDF_PageContentGeneratorTest; - void ProcessPath(CFX_ByteTextBuf* buf, CPDF_PathObject* pPathObj); - void ProcessImage(CFX_ByteTextBuf* buf, CPDF_ImageObject* pImageObj); - void ProcessGraphics(CFX_ByteTextBuf* buf, CPDF_PageObject* pPageObj); - void ProcessText(CFX_ByteTextBuf* buf, CPDF_TextObject* pTextObj); - CFX_ByteString RealizeResource(uint32_t dwResourceObjNum, - const CFX_ByteString& bsType); - - CPDF_Page* const m_pPage; - CPDF_Document* const m_pDocument; - std::vector m_pageObjects; + void ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj); + void ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj); + void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj); + void ProcessDefaultGraphics(std::ostringstream* buf); + void ProcessText(std::ostringstream* buf, CPDF_TextObject* pTextObj); + ByteString RealizeResource(uint32_t dwResourceObjNum, + const ByteString& bsType); + + UnownedPtr const m_pObjHolder; + UnownedPtr const m_pDocument; + std::vector> m_pageObjects; }; #endif // CORE_FPDFAPI_EDIT_CPDF_PAGECONTENTGENERATOR_H_ diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp index d8813ba30fa36ac1c232d83ba6b0e644b7cd4cd2..a0db869410c44994dee53d328f53a12070ea193d 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp @@ -4,36 +4,45 @@ #include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h" +#include +#include + #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/page/cpdf_form.h" #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/page/cpdf_textobject.h" #include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_parser.h" +#include "core/fpdfapi/parser/cpdf_reference.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" #include "third_party/base/ptr_util.h" class CPDF_PageContentGeneratorTest : public testing::Test { protected: - void SetUp() override { CPDF_ModuleMgr::Get()->InitPageModule(); } + void SetUp() override { CPDF_ModuleMgr::Get()->Init(); } - void TearDown() override { CPDF_ModuleMgr::Destroy(); } + void TearDown() override { + CPDF_ModuleMgr::Destroy(); + } void TestProcessPath(CPDF_PageContentGenerator* pGen, - CFX_ByteTextBuf* buf, + std::ostringstream* buf, CPDF_PathObject* pPathObj) { pGen->ProcessPath(buf, pPathObj); } CPDF_Dictionary* TestGetResource(CPDF_PageContentGenerator* pGen, - const CFX_ByteString& type, - const CFX_ByteString& name) { - return pGen->m_pPage->m_pResources->GetDictFor(type)->GetDictFor(name); + const ByteString& type, + const ByteString& name) { + return pGen->m_pObjHolder->m_pResources->GetDictFor(type)->GetDictFor(name); } void TestProcessText(CPDF_PageContentGenerator* pGen, - CFX_ByteTextBuf* buf, + std::ostringstream* buf, CPDF_TextObject* pTextObj) { pGen->ProcessText(buf, pTextObj); } @@ -47,9 +56,9 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessRect) { auto pTestPage = pdfium::MakeUnique(nullptr, nullptr, false); CPDF_PageContentGenerator generator(pTestPage.get()); - CFX_ByteTextBuf buf; + std::ostringstream buf; TestProcessPath(&generator, &buf, pPathObj.get()); - EXPECT_EQ("q 10 5 3 25 re B* Q\n", buf.MakeString()); + EXPECT_EQ("q 1 0 0 1 0 0 cm 10 5 3 25 re B* Q\n", ByteString(buf)); pPathObj = pdfium::MakeUnique(); pPathObj->m_Path.AppendPoint(CFX_PointF(0, 0), FXPT_TYPE::MoveTo, false); @@ -59,10 +68,10 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessRect) { pPathObj->m_Path.AppendPoint(CFX_PointF(0, 3.78f), FXPT_TYPE::LineTo, true); pPathObj->m_FillType = 0; pPathObj->m_bStroke = false; - buf.Clear(); + buf.str(""); TestProcessPath(&generator, &buf, pPathObj.get()); - EXPECT_EQ("q 0 0 5.2 3.78 re n Q\n", buf.MakeString()); + EXPECT_EQ("q 1 0 0 1 0 0 cm 0 0 5.2 3.78 re n Q\n", ByteString(buf)); } TEST_F(CPDF_PageContentGeneratorTest, ProcessPath) { @@ -91,12 +100,12 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessPath) { auto pTestPage = pdfium::MakeUnique(nullptr, nullptr, false); CPDF_PageContentGenerator generator(pTestPage.get()); - CFX_ByteTextBuf buf; + std::ostringstream buf; TestProcessPath(&generator, &buf, pPathObj.get()); EXPECT_EQ( - "q 3.102 4.67 m 5.45 0.29 l 4.24 3.15 4.65 2.98 3.456 0.24 c 10.6 11.15 " - "l 11 12.5 l 11.46 12.67 11.84 12.96 12 13.64 c h f Q\n", - buf.MakeString()); + "q 1 0 0 1 0 0 cm 3.102 4.67 m 5.45 0.29 l 4.24 3.15 4.65 2.98 3.456 0.24" + " c 10.6 11.15 l 11 12.5 l 11.46 12.67 11.84 12.96 12 13.64 c h f Q\n", + ByteString(buf)); } TEST_F(CPDF_PageContentGeneratorTest, ProcessGraphics) { @@ -107,11 +116,11 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessGraphics) { pPathObj->m_FillType = FXFILL_WINDING; pPathObj->m_bStroke = true; - FX_FLOAT rgb[3] = {0.5f, 0.7f, 0.35f}; + float rgb[3] = {0.5f, 0.7f, 0.35f}; CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); pPathObj->m_ColorState.SetFillColor(pCS, rgb, 3); - FX_FLOAT rgb2[3] = {1, 0.9f, 0}; + float rgb2[3] = {1, 0.9f, 0}; pPathObj->m_ColorState.SetStrokeColor(pCS, rgb2, 3); pPathObj->m_GeneralState.SetFillAlpha(0.5f); pPathObj->m_GeneralState.SetStrokeAlpha(0.8f); @@ -121,29 +130,31 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessGraphics) { CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); auto pTestPage = pdfium::MakeUnique(pDoc.get(), pPageDict, false); CPDF_PageContentGenerator generator(pTestPage.get()); - CFX_ByteTextBuf buf; + std::ostringstream buf; TestProcessPath(&generator, &buf, pPathObj.get()); - CFX_ByteString pathString = buf.MakeString(); + ByteString pathString(buf); // Color RGB values used are integers divided by 255. EXPECT_EQ("q 0.501961 0.701961 0.34902 rg 1 0.901961 0 RG /", pathString.Left(48)); - EXPECT_EQ(" gs 1 2 m 3 4 l 5 6 l h B Q\n", pathString.Right(28)); - ASSERT_TRUE(pathString.GetLength() > 76); + EXPECT_EQ(" gs 1 0 0 1 0 0 cm 1 2 m 3 4 l 5 6 l h B Q\n", + pathString.Right(43)); + ASSERT_TRUE(pathString.GetLength() > 91); CPDF_Dictionary* externalGS = TestGetResource( - &generator, "ExtGState", pathString.Mid(48, pathString.GetLength() - 76)); + &generator, "ExtGState", pathString.Mid(48, pathString.GetLength() - 91)); ASSERT_TRUE(externalGS); EXPECT_EQ(0.5f, externalGS->GetNumberFor("ca")); EXPECT_EQ(0.8f, externalGS->GetNumberFor("CA")); // Same path, now with a stroke. pPathObj->m_GraphState.SetLineWidth(10.5f); - buf.Clear(); + buf.str(""); TestProcessPath(&generator, &buf, pPathObj.get()); - CFX_ByteString pathString2 = buf.MakeString(); + ByteString pathString2(buf); EXPECT_EQ("q 0.501961 0.701961 0.34902 rg 1 0.901961 0 RG 10.5 w /", pathString2.Left(55)); - EXPECT_EQ(" gs 1 2 m 3 4 l 5 6 l h B Q\n", pathString2.Right(28)); + EXPECT_EQ(" gs 1 0 0 1 0 0 cm 1 2 m 3 4 l 5 6 l h B Q\n", + pathString2.Right(43)); // Compare with the previous (should use same dictionary for gs) EXPECT_EQ(pathString.GetLength() + 7, pathString2.GetLength()); @@ -151,7 +162,8 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessGraphics) { pathString2.Mid(55, pathString2.GetLength() - 83)); } -TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { +TEST_F(CPDF_PageContentGeneratorTest, ProcessStandardText) { + // Checking font whose font dictionary is not yet indirect object. auto pDoc = pdfium::MakeUnique(nullptr); pDoc->CreateNewDoc(); CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); @@ -161,18 +173,161 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Times-Roman"); pTextObj->m_TextState.SetFont(pFont); pTextObj->m_TextState.SetFontSize(10.0f); + float rgb[3] = {0.5f, 0.7f, 0.35f}; + CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); + pTextObj->m_ColorState.SetFillColor(pCS, rgb, 3); + + float rgb2[3] = {1, 0.9f, 0}; + pTextObj->m_ColorState.SetStrokeColor(pCS, rgb2, 3); + pTextObj->m_GeneralState.SetFillAlpha(0.5f); + pTextObj->m_GeneralState.SetStrokeAlpha(0.8f); pTextObj->Transform(CFX_Matrix(1, 0, 0, 1, 100, 100)); pTextObj->SetText("Hello World"); - CFX_ByteTextBuf buf; + std::ostringstream buf; TestProcessText(&generator, &buf, pTextObj.get()); - CFX_ByteString textString = buf.MakeString(); - EXPECT_LT(61, textString.GetLength()); - EXPECT_EQ("BT 1 0 0 1 100 100 Tm /", textString.Left(23)); - EXPECT_EQ(" 10 Tf <48656C6C6F20576F726C64> Tj ET\n", textString.Right(38)); + ByteString textString(buf); + auto firstResourceAt = textString.Find('/'); + ASSERT_TRUE(firstResourceAt.has_value()); + firstResourceAt = firstResourceAt.value() + 1; + auto secondResourceAt = textString.ReverseFind('/'); + ASSERT_TRUE(secondResourceAt.has_value()); + secondResourceAt = secondResourceAt.value() + 1; + ByteString firstString = textString.Left(firstResourceAt.value()); + ByteString midString = + textString.Mid(firstResourceAt.value(), + secondResourceAt.value() - firstResourceAt.value()); + ByteString lastString = + textString.Right(textString.GetLength() - secondResourceAt.value()); + // q and Q must be outside the BT .. ET operations + ByteString compareString1 = + "q 0.501961 0.701961 0.34902 rg 1 0.901961 0 RG /"; + // Color RGB values used are integers divided by 255. + ByteString compareString2 = " gs BT 1 0 0 1 100 100 Tm /"; + ByteString compareString3 = " 10 Tf <48656C6C6F20576F726C64> Tj ET Q\n"; + EXPECT_LT(compareString1.GetLength() + compareString2.GetLength() + + compareString3.GetLength(), + textString.GetLength()); + EXPECT_EQ(compareString1, firstString.Left(compareString1.GetLength())); + EXPECT_EQ(compareString2, midString.Right(compareString2.GetLength())); + EXPECT_EQ(compareString3, lastString.Right(compareString3.GetLength())); + CPDF_Dictionary* externalGS = TestGetResource( + &generator, "ExtGState", + midString.Left(midString.GetLength() - compareString2.GetLength())); + ASSERT_TRUE(externalGS); + EXPECT_EQ(0.5f, externalGS->GetNumberFor("ca")); + EXPECT_EQ(0.8f, externalGS->GetNumberFor("CA")); CPDF_Dictionary* fontDict = TestGetResource( - &generator, "Font", textString.Mid(23, textString.GetLength() - 61)); + &generator, "Font", + lastString.Left(lastString.GetLength() - compareString3.GetLength())); ASSERT_TRUE(fontDict); EXPECT_EQ("Font", fontDict->GetStringFor("Type")); EXPECT_EQ("Type1", fontDict->GetStringFor("Subtype")); EXPECT_EQ("Times-Roman", fontDict->GetStringFor("BaseFont")); } + +TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { + // Checking font whose font dictionary is already an indirect object. + auto pDoc = pdfium::MakeUnique(nullptr); + pDoc->CreateNewDoc(); + CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); + auto pTestPage = pdfium::MakeUnique(pDoc.get(), pPageDict, false); + CPDF_PageContentGenerator generator(pTestPage.get()); + + std::ostringstream buf; + { + // Set the text object font and text + auto pTextObj = pdfium::MakeUnique(); + CPDF_Dictionary* pDict = pDoc->NewIndirect(); + pDict->SetNewFor("Type", "Font"); + pDict->SetNewFor("Subtype", "TrueType"); + CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Arial"); + pDict->SetNewFor("BaseFont", pFont->GetBaseFont()); + + CPDF_Dictionary* pDesc = pDoc->NewIndirect(); + pDesc->SetNewFor("Type", "FontDescriptor"); + pDesc->SetNewFor("FontName", pFont->GetBaseFont()); + pDict->SetNewFor("FontDescriptor", pDoc.get(), + pDesc->GetObjNum()); + + CPDF_Font* loadedFont = pDoc->LoadFont(pDict); + pTextObj->m_TextState.SetFont(loadedFont); + pTextObj->m_TextState.SetFontSize(15.5f); + pTextObj->SetText("I am indirect"); + + TestProcessText(&generator, &buf, pTextObj.get()); + } + + ByteString textString(buf); + auto firstResourceAt = textString.Find('/'); + ASSERT_TRUE(firstResourceAt.has_value()); + firstResourceAt = firstResourceAt.value() + 1; + ByteString firstString = textString.Left(firstResourceAt.value()); + ByteString lastString = + textString.Right(textString.GetLength() - firstResourceAt.value()); + // q and Q must be outside the BT .. ET operations + ByteString compareString1 = "q BT 1 0 0 1 0 0 Tm /"; + ByteString compareString2 = " 15.5 Tf <4920616D20696E646972656374> Tj ET Q\n"; + EXPECT_LT(compareString1.GetLength() + compareString2.GetLength(), + textString.GetLength()); + EXPECT_EQ(compareString1, textString.Left(compareString1.GetLength())); + EXPECT_EQ(compareString2, textString.Right(compareString2.GetLength())); + CPDF_Dictionary* fontDict = TestGetResource( + &generator, "Font", + textString.Mid(compareString1.GetLength(), + textString.GetLength() - compareString1.GetLength() - + compareString2.GetLength())); + ASSERT_TRUE(fontDict); + EXPECT_TRUE(fontDict->GetObjNum()); + EXPECT_EQ("Font", fontDict->GetStringFor("Type")); + EXPECT_EQ("TrueType", fontDict->GetStringFor("Subtype")); + EXPECT_EQ("Helvetica", fontDict->GetStringFor("BaseFont")); + CPDF_Dictionary* fontDesc = fontDict->GetDictFor("FontDescriptor"); + ASSERT_TRUE(fontDesc); + EXPECT_TRUE(fontDesc->GetObjNum()); + EXPECT_EQ("FontDescriptor", fontDesc->GetStringFor("Type")); + EXPECT_EQ("Helvetica", fontDesc->GetStringFor("FontName")); +} + +TEST_F(CPDF_PageContentGeneratorTest, ProcessEmptyForm) { + auto pDoc = pdfium::MakeUnique(nullptr); + pDoc->CreateNewDoc(); + auto pDict = pdfium::MakeUnique(); + auto pStream = pdfium::MakeUnique(nullptr, 0, std::move(pDict)); + + // Create an empty form. + auto pTestForm = + pdfium::MakeUnique(pDoc.get(), nullptr, pStream.get()); + pTestForm->ParseContent(); + ASSERT_TRUE(pTestForm->IsParsed()); + + // The generated stream for the empty form should be an empty string. + CPDF_PageContentGenerator generator(pTestForm.get()); + std::ostringstream buf; + generator.ProcessPageObjects(&buf); + EXPECT_EQ("", ByteString(buf)); +} + +TEST_F(CPDF_PageContentGeneratorTest, ProcessFormWithPath) { + auto pDoc = pdfium::MakeUnique(nullptr); + pDoc->CreateNewDoc(); + auto pDict = pdfium::MakeUnique(); + const char content[] = + "q 1 0 0 1 0 0 cm 3.102 4.67 m 5.45 0.29 l 4.24 3.15 4.65 2.98 3.456 " + "0.24 c 3.102 4.67 l h f Q\n"; + size_t buf_len = FX_ArraySize(content); + std::unique_ptr buf(FX_Alloc(uint8_t, buf_len)); + memcpy(buf.get(), content, buf_len); + auto pStream = pdfium::MakeUnique(std::move(buf), buf_len, + std::move(pDict)); + + // Create a form with a non-empty stream. + auto pTestForm = + pdfium::MakeUnique(pDoc.get(), nullptr, pStream.get()); + pTestForm->ParseContent(); + ASSERT_TRUE(pTestForm->IsParsed()); + + CPDF_PageContentGenerator generator(pTestForm.get()); + std::ostringstream process_buf; + generator.ProcessPageObjects(&process_buf); + EXPECT_EQ(content, ByteString(process_buf)); +} diff --git a/core/fpdfapi/edit/editint.h b/core/fpdfapi/edit/editint.h deleted file mode 100644 index 881c2cca36ff4b093f43d5f2541e4453463c656d..0000000000000000000000000000000000000000 --- a/core/fpdfapi/edit/editint.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FPDFAPI_EDIT_EDITINT_H_ -#define CORE_FPDFAPI_EDIT_EDITINT_H_ - -#include - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_stream.h" -#include "core/fxcrt/fx_system.h" - -class CPDF_Creator; -class CPDF_Object; - -class CPDF_ObjectStream { - public: - struct Item { - uint32_t objnum; - FX_STRSIZE offset; - }; - - CPDF_ObjectStream(); - ~CPDF_ObjectStream(); - - void Start(); - FX_FILESIZE End(CPDF_Creator* pCreator); - void CompressIndirectObject(uint32_t dwObjNum, const CPDF_Object* pObj); - void CompressIndirectObject(uint32_t dwObjNum, - const uint8_t* pBuffer, - uint32_t dwSize); - - std::vector m_Items; - CFX_ByteTextBuf m_Buffer; - uint32_t m_dwObjNum; - int32_t m_index; -}; - -class CPDF_XRefStream { - public: - struct Index { - uint32_t objnum; - uint32_t count; - }; - - CPDF_XRefStream(); - ~CPDF_XRefStream(); - - bool Start(); - int32_t CompressIndirectObject(uint32_t dwObjNum, - const CPDF_Object* pObj, - CPDF_Creator* pCreator); - int32_t CompressIndirectObject(uint32_t dwObjNum, - const uint8_t* pBuffer, - uint32_t dwSize, - CPDF_Creator* pCreator); - bool End(CPDF_Creator* pCreator, bool bEOF = false); - void AddObjectNumberToIndexArray(uint32_t objnum); - bool EndXRefStream(CPDF_Creator* pCreator); - - std::vector m_IndexArray; - FX_FILESIZE m_PrevOffset; - uint32_t m_dwTempObjNum; - - protected: - int32_t EndObjectStream(CPDF_Creator* pCreator, bool bEOF = true); - bool GenerateXRefStream(CPDF_Creator* pCreator, bool bEOF); - - size_t m_iSeg; - CPDF_ObjectStream m_ObjStream; - CFX_ByteTextBuf m_Buffer; -}; - -#endif // CORE_FPDFAPI_EDIT_EDITINT_H_ diff --git a/core/fpdfapi/edit/fpdf_edit_create.cpp b/core/fpdfapi/edit/fpdf_edit_create.cpp deleted file mode 100644 index fec0de95123fa07d0e8a0dca29bd1024a2ebdcdc..0000000000000000000000000000000000000000 --- a/core/fpdfapi/edit/fpdf_edit_create.cpp +++ /dev/null @@ -1,1995 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/edit/editint.h" - -#include -#include - -#include "core/fpdfapi/edit/cpdf_creator.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_crypto_handler.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_name.h" -#include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_parser.h" -#include "core/fpdfapi/parser/cpdf_reference.h" -#include "core/fpdfapi/parser/cpdf_security_handler.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fpdfapi/parser/cpdf_string.h" -#include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fxcrt/cfx_maybe_owned.h" -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -#define PDF_OBJECTSTREAM_MAXLENGTH (256 * 1024) -#define PDF_XREFSTREAM_MAXSIZE 10000 - -#define FX_GETBYTEOFFSET32(a) 0 -#define FX_GETBYTEOFFSET40(a) 0 -#define FX_GETBYTEOFFSET48(a) 0 -#define FX_GETBYTEOFFSET56(a) 0 -#define FX_GETBYTEOFFSET24(a) ((uint8_t)(a >> 24)) -#define FX_GETBYTEOFFSET16(a) ((uint8_t)(a >> 16)) -#define FX_GETBYTEOFFSET8(a) ((uint8_t)(a >> 8)) -#define FX_GETBYTEOFFSET0(a) ((uint8_t)(a)) - -// TODO(ochang): Make helper for appending "objnum 0 R ". - -namespace { - -int32_t PDF_CreatorAppendObject(const CPDF_Object* pObj, - CFX_FileBufferArchive* pFile, - FX_FILESIZE& offset) { - int32_t len = 0; - if (!pObj) { - if (pFile->AppendString(" null") < 0) { - return -1; - } - offset += 5; - return 1; - } - switch (pObj->GetType()) { - case CPDF_Object::NULLOBJ: - if (pFile->AppendString(" null") < 0) { - return -1; - } - offset += 5; - break; - case CPDF_Object::BOOLEAN: - case CPDF_Object::NUMBER: - if (pFile->AppendString(" ") < 0) { - return -1; - } - if ((len = pFile->AppendString(pObj->GetString().AsStringC())) < 0) { - return -1; - } - offset += len + 1; - break; - case CPDF_Object::STRING: { - CFX_ByteString str = pObj->GetString(); - bool bHex = pObj->AsString()->IsHex(); - if ((len = pFile->AppendString(PDF_EncodeString(str, bHex).AsStringC())) < - 0) { - return -1; - } - offset += len; - break; - } - case CPDF_Object::NAME: { - if (pFile->AppendString("/") < 0) { - return -1; - } - CFX_ByteString str = pObj->GetString(); - if ((len = pFile->AppendString(PDF_NameEncode(str).AsStringC())) < 0) { - return -1; - } - offset += len + 1; - break; - } - case CPDF_Object::REFERENCE: { - if (pFile->AppendString(" ") < 0) - return -1; - if ((len = pFile->AppendDWord(pObj->AsReference()->GetRefObjNum())) < 0) - return -1; - if (pFile->AppendString(" 0 R ") < 0) - return -1; - offset += len + 6; - break; - } - case CPDF_Object::ARRAY: { - if (pFile->AppendString("[") < 0) { - return -1; - } - offset += 1; - const CPDF_Array* p = pObj->AsArray(); - for (size_t i = 0; i < p->GetCount(); i++) { - CPDF_Object* pElement = p->GetObjectAt(i); - if (!pElement->IsInline()) { - if (pFile->AppendString(" ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord(pElement->GetObjNum())) < 0) { - return -1; - } - if (pFile->AppendString(" 0 R") < 0) { - return -1; - } - offset += len + 5; - } else { - if (PDF_CreatorAppendObject(pElement, pFile, offset) < 0) { - return -1; - } - } - } - if (pFile->AppendString("]") < 0) { - return -1; - } - offset += 1; - break; - } - case CPDF_Object::DICTIONARY: { - if (pFile->AppendString("<<") < 0) { - return -1; - } - offset += 2; - const CPDF_Dictionary* p = pObj->AsDictionary(); - for (const auto& it : *p) { - const CFX_ByteString& key = it.first; - CPDF_Object* pValue = it.second.get(); - if (pFile->AppendString("/") < 0) { - return -1; - } - if ((len = pFile->AppendString(PDF_NameEncode(key).AsStringC())) < 0) { - return -1; - } - offset += len + 1; - if (!pValue->IsInline()) { - if (pFile->AppendString(" ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) { - return -1; - } - if (pFile->AppendString(" 0 R") < 0) { - return -1; - } - offset += len + 5; - } else { - if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) { - return -1; - } - } - } - if (pFile->AppendString(">>") < 0) { - return -1; - } - offset += 2; - break; - } - case CPDF_Object::STREAM: { - const CPDF_Stream* p = pObj->AsStream(); - if (PDF_CreatorAppendObject(p->GetDict(), pFile, offset) < 0) { - return -1; - } - if (pFile->AppendString("stream\r\n") < 0) { - return -1; - } - offset += 8; - CPDF_StreamAcc acc; - acc.LoadAllData(p, true); - if (pFile->AppendBlock(acc.GetData(), acc.GetSize()) < 0) { - return -1; - } - offset += acc.GetSize(); - if ((len = pFile->AppendString("\r\nendstream")) < 0) { - return -1; - } - offset += len; - break; - } - default: - ASSERT(false); - break; - } - return 1; -} - -int32_t PDF_CreatorWriteTrailer(CPDF_Document* pDocument, - CFX_FileBufferArchive* pFile, - CPDF_Array* pIDArray) { - FX_FILESIZE offset = 0; - int32_t len = 0; - CPDF_Parser* pParser = pDocument->GetParser(); - if (pParser) { - CPDF_Dictionary* p = pParser->GetTrailer(); - for (const auto& it : *p) { - const CFX_ByteString& key = it.first; - CPDF_Object* pValue = it.second.get(); - if (key == "Encrypt" || key == "Size" || key == "Filter" || - key == "Index" || key == "Length" || key == "Prev" || key == "W" || - key == "XRefStm" || key == "Type" || key == "ID") { - continue; - } - if (key == "DecodeParms") - continue; - - if (pFile->AppendString(("/")) < 0) { - return -1; - } - if ((len = pFile->AppendString(PDF_NameEncode(key).AsStringC())) < 0) { - return -1; - } - offset += len + 1; - if (!pValue->IsInline()) { - if (pFile->AppendString(" ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) { - return -1; - } - if (pFile->AppendString(" 0 R ") < 0) { - return -1; - } - offset += len + 6; - } else { - if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) { - return -1; - } - } - } - if (pIDArray) { - if (pFile->AppendString(("/ID")) < 0) { - return -1; - } - offset += 3; - if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) { - return -1; - } - } - return offset; - } - if (pFile->AppendString("\r\n/Root ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord(pDocument->GetRoot()->GetObjNum())) < 0) { - return -1; - } - if (pFile->AppendString(" 0 R\r\n") < 0) { - return -1; - } - offset += len + 14; - if (pDocument->GetInfo()) { - if (pFile->AppendString("/Info ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord(pDocument->GetInfo()->GetObjNum())) < 0) { - return -1; - } - if (pFile->AppendString(" 0 R\r\n") < 0) { - return -1; - } - offset += len + 12; - } - if (pIDArray) { - if (pFile->AppendString(("/ID")) < 0) { - return -1; - } - offset += 3; - if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) { - return -1; - } - } - return offset; -} - -int32_t PDF_CreatorWriteEncrypt(const CPDF_Dictionary* pEncryptDict, - uint32_t dwObjNum, - CFX_FileBufferArchive* pFile) { - if (!pEncryptDict) { - return 0; - } - ASSERT(pFile); - FX_FILESIZE offset = 0; - int32_t len = 0; - if (pFile->AppendString("/Encrypt") < 0) { - return -1; - } - offset += 8; - if (pFile->AppendString(" ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord(dwObjNum)) < 0) { - return -1; - } - if (pFile->AppendString(" 0 R ") < 0) { - return -1; - } - offset += len + 6; - return offset; -} - -std::vector PDF_GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) { - std::vector buffer(sizeof(uint32_t) * 4); - uint32_t* pBuffer = reinterpret_cast(buffer.data()); - void* pContext = FX_Random_MT_Start(dwSeed1); - for (int i = 0; i < 2; ++i) - *pBuffer++ = FX_Random_MT_Generate(pContext); - FX_Random_MT_Close(pContext); - pContext = FX_Random_MT_Start(dwSeed2); - for (int i = 0; i < 2; ++i) - *pBuffer++ = FX_Random_MT_Generate(pContext); - FX_Random_MT_Close(pContext); - return buffer; -} - -void AppendIndex0(CFX_ByteTextBuf& buffer, bool bFirstObject) { - buffer.AppendByte(0); - buffer.AppendByte(0); - buffer.AppendByte(0); - buffer.AppendByte(0); - buffer.AppendByte(0); - const uint8_t byte = bFirstObject ? 0xFF : 0; - buffer.AppendByte(byte); - buffer.AppendByte(byte); -} - -void AppendIndex1(CFX_ByteTextBuf& buffer, FX_FILESIZE offset) { - buffer.AppendByte(1); - buffer.AppendByte(FX_GETBYTEOFFSET24(offset)); - buffer.AppendByte(FX_GETBYTEOFFSET16(offset)); - buffer.AppendByte(FX_GETBYTEOFFSET8(offset)); - buffer.AppendByte(FX_GETBYTEOFFSET0(offset)); - buffer.AppendByte(0); - buffer.AppendByte(0); -} - -void AppendIndex2(CFX_ByteTextBuf& buffer, uint32_t objnum, int32_t index) { - buffer.AppendByte(2); - buffer.AppendByte(FX_GETBYTEOFFSET24(objnum)); - buffer.AppendByte(FX_GETBYTEOFFSET16(objnum)); - buffer.AppendByte(FX_GETBYTEOFFSET8(objnum)); - buffer.AppendByte(FX_GETBYTEOFFSET0(objnum)); - buffer.AppendByte(FX_GETBYTEOFFSET8(index)); - buffer.AppendByte(FX_GETBYTEOFFSET0(index)); -} - -bool IsXRefNeedEnd(CPDF_XRefStream* pXRef, uint32_t flag) { - if (!(flag & FPDFCREATE_INCREMENTAL)) - return false; - - uint32_t iCount = 0; - for (const auto& pair : pXRef->m_IndexArray) - iCount += pair.count; - - return iCount >= PDF_XREFSTREAM_MAXSIZE; -} - -int32_t OutputIndex(CFX_FileBufferArchive* pFile, FX_FILESIZE offset) { - if (sizeof(offset) > 4) { - if (FX_GETBYTEOFFSET32(offset)) { - if (pFile->AppendByte(FX_GETBYTEOFFSET56(offset)) < 0) - return -1; - if (pFile->AppendByte(FX_GETBYTEOFFSET48(offset)) < 0) - return -1; - if (pFile->AppendByte(FX_GETBYTEOFFSET40(offset)) < 0) - return -1; - if (pFile->AppendByte(FX_GETBYTEOFFSET32(offset)) < 0) - return -1; - } - } - if (pFile->AppendByte(FX_GETBYTEOFFSET24(offset)) < 0) - return -1; - if (pFile->AppendByte(FX_GETBYTEOFFSET16(offset)) < 0) - return -1; - if (pFile->AppendByte(FX_GETBYTEOFFSET8(offset)) < 0) - return -1; - if (pFile->AppendByte(FX_GETBYTEOFFSET0(offset)) < 0) - return -1; - if (pFile->AppendByte(0) < 0) - return -1; - return 0; -} - -class CPDF_FlateEncoder { - public: - CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode); - CPDF_FlateEncoder(const uint8_t* pBuffer, - uint32_t size, - bool bFlateEncode, - bool bXRefStream); - ~CPDF_FlateEncoder(); - - void CloneDict(); - - uint32_t m_dwSize; - CFX_MaybeOwned m_pData; - CFX_MaybeOwned m_pDict; - CPDF_StreamAcc m_Acc; -}; - -void CPDF_FlateEncoder::CloneDict() { - if (m_pDict.IsOwned()) - return; - m_pDict = ToDictionary(m_pDict->Clone()); - ASSERT(m_pDict.IsOwned()); -} - -CPDF_FlateEncoder::CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode) - : m_dwSize(0) { - m_Acc.LoadAllData(pStream, true); - bool bHasFilter = pStream && pStream->HasFilter(); - if (bHasFilter && !bFlateEncode) { - CPDF_StreamAcc destAcc; - destAcc.LoadAllData(pStream); - m_dwSize = destAcc.GetSize(); - m_pData = destAcc.DetachData(); - m_pDict = ToDictionary(pStream->GetDict()->Clone()); - m_pDict->RemoveFor("Filter"); - return; - } - if (bHasFilter || !bFlateEncode) { - m_pData = const_cast(m_Acc.GetData()); - m_dwSize = m_Acc.GetSize(); - m_pDict = pStream->GetDict(); - return; - } - // TODO(thestig): Move to Init() and check return value. - uint8_t* buffer = nullptr; - ::FlateEncode(m_Acc.GetData(), m_Acc.GetSize(), &buffer, &m_dwSize); - m_pData = std::unique_ptr(buffer); - m_pDict = ToDictionary(pStream->GetDict()->Clone()); - m_pDict->SetNewFor("Length", static_cast(m_dwSize)); - m_pDict->SetNewFor("Filter", "FlateDecode"); - m_pDict->RemoveFor("DecodeParms"); -} - -CPDF_FlateEncoder::CPDF_FlateEncoder(const uint8_t* pBuffer, - uint32_t size, - bool bFlateEncode, - bool bXRefStream) - : m_dwSize(0) { - if (!bFlateEncode) { - m_pData = const_cast(pBuffer); - m_dwSize = size; - return; - } - uint8_t* buffer = nullptr; - // TODO(thestig): Move to Init() and check return value. - if (bXRefStream) - ::PngEncode(pBuffer, size, &buffer, &m_dwSize); - else - ::FlateEncode(pBuffer, size, &buffer, &m_dwSize); - m_pData = std::unique_ptr(buffer); -} - -CPDF_FlateEncoder::~CPDF_FlateEncoder() {} - -class CPDF_Encryptor { - public: - CPDF_Encryptor(CPDF_CryptoHandler* pHandler, - int objnum, - uint8_t* src_data, - uint32_t src_size); - ~CPDF_Encryptor(); - - uint8_t* m_pData; - uint32_t m_dwSize; - bool m_bNewBuf; -}; - -CPDF_Encryptor::CPDF_Encryptor(CPDF_CryptoHandler* pHandler, - int objnum, - uint8_t* src_data, - uint32_t src_size) - : m_pData(nullptr), m_dwSize(0), m_bNewBuf(false) { - if (src_size == 0) - return; - - if (!pHandler) { - m_pData = (uint8_t*)src_data; - m_dwSize = src_size; - return; - } - m_dwSize = pHandler->EncryptGetSize(objnum, 0, src_data, src_size); - m_pData = FX_Alloc(uint8_t, m_dwSize); - pHandler->EncryptContent(objnum, 0, src_data, src_size, m_pData, m_dwSize); - m_bNewBuf = true; -} - -CPDF_Encryptor::~CPDF_Encryptor() { - if (m_bNewBuf) - FX_Free(m_pData); -} - -} // namespace - -CPDF_ObjectStream::CPDF_ObjectStream() : m_dwObjNum(0), m_index(0) {} - -CPDF_ObjectStream::~CPDF_ObjectStream() {} - -void CPDF_ObjectStream::Start() { - m_Items.clear(); - m_Buffer.Clear(); - m_dwObjNum = 0; - m_index = 0; -} - -void CPDF_ObjectStream::CompressIndirectObject(uint32_t dwObjNum, - const CPDF_Object* pObj) { - m_Items.push_back({dwObjNum, m_Buffer.GetLength()}); - m_Buffer << pObj; -} - -void CPDF_ObjectStream::CompressIndirectObject(uint32_t dwObjNum, - const uint8_t* pBuffer, - uint32_t dwSize) { - m_Items.push_back({dwObjNum, m_Buffer.GetLength()}); - m_Buffer.AppendBlock(pBuffer, dwSize); -} - -FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) { - ASSERT(pCreator); - if (m_Items.empty()) - return 0; - - CFX_FileBufferArchive* pFile = &pCreator->m_File; - FX_FILESIZE ObjOffset = pCreator->m_Offset; - if (!m_dwObjNum) { - m_dwObjNum = ++pCreator->m_dwLastObjNum; - } - CFX_ByteTextBuf tempBuffer; - for (const auto& pair : m_Items) - tempBuffer << pair.objnum << " " << pair.offset << " "; - - FX_FILESIZE& offset = pCreator->m_Offset; - int32_t len = pFile->AppendDWord(m_dwObjNum); - if (len < 0) { - return -1; - } - offset += len; - if ((len = pFile->AppendString(" 0 obj\r\n<(m_Items); - if ((len = pFile->AppendDWord(iCount)) < 0) { - return -1; - } - offset += len; - if (pFile->AppendString("/First ") < 0) { - return -1; - } - if ((len = pFile->AppendDWord((uint32_t)tempBuffer.GetLength())) < 0) { - return -1; - } - if (pFile->AppendString("/Length ") < 0) { - return -1; - } - offset += len + 15; - - tempBuffer << m_Buffer; - CPDF_FlateEncoder encoder(tempBuffer.GetBuffer(), tempBuffer.GetLength(), - true, false); - CPDF_Encryptor encryptor(pCreator->m_pCryptoHandler, m_dwObjNum, - encoder.m_pData.Get(), encoder.m_dwSize); - if ((len = pFile->AppendDWord(encryptor.m_dwSize)) < 0) { - return -1; - } - offset += len; - if (pFile->AppendString("/Filter /FlateDecode") < 0) { - return -1; - } - offset += 20; - if ((len = pFile->AppendString(">>stream\r\n")) < 0) { - return -1; - } - if (pFile->AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) { - return -1; - } - offset += len + encryptor.m_dwSize; - if ((len = pFile->AppendString("\r\nendstream\r\nendobj\r\n")) < 0) { - return -1; - } - offset += len; - return ObjOffset; -} - -CPDF_XRefStream::CPDF_XRefStream() - : m_PrevOffset(0), m_dwTempObjNum(0), m_iSeg(0) {} - -CPDF_XRefStream::~CPDF_XRefStream() {} - -bool CPDF_XRefStream::Start() { - m_IndexArray.clear(); - m_Buffer.Clear(); - m_iSeg = 0; - return true; -} -int32_t CPDF_XRefStream::CompressIndirectObject(uint32_t dwObjNum, - const CPDF_Object* pObj, - CPDF_Creator* pCreator) { - if (!pCreator) - return 0; - - m_ObjStream.CompressIndirectObject(dwObjNum, pObj); - if (pdfium::CollectionSize(m_ObjStream.m_Items) < - pCreator->m_ObjectStreamSize && - m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) { - return 1; - } - return EndObjectStream(pCreator); -} -int32_t CPDF_XRefStream::CompressIndirectObject(uint32_t dwObjNum, - const uint8_t* pBuffer, - uint32_t dwSize, - CPDF_Creator* pCreator) { - if (!pCreator) - return 0; - - m_ObjStream.CompressIndirectObject(dwObjNum, pBuffer, dwSize); - if (pdfium::CollectionSize(m_ObjStream.m_Items) < - pCreator->m_ObjectStreamSize && - m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) { - return 1; - } - return EndObjectStream(pCreator); -} - -int32_t CPDF_XRefStream::EndObjectStream(CPDF_Creator* pCreator, bool bEOF) { - FX_FILESIZE objOffset = 0; - if (bEOF) { - objOffset = m_ObjStream.End(pCreator); - if (objOffset < 0) { - return -1; - } - } - uint32_t& dwObjStmNum = m_ObjStream.m_dwObjNum; - if (!dwObjStmNum) { - dwObjStmNum = ++pCreator->m_dwLastObjNum; - } - int32_t iSize = pdfium::CollectionSize(m_ObjStream.m_Items); - size_t iSeg = m_IndexArray.size(); - if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) { - if (m_dwTempObjNum == 0) { - AppendIndex0(m_Buffer, true); - m_dwTempObjNum++; - } - uint32_t end_num = m_IndexArray.back().objnum + m_IndexArray.back().count; - int index = 0; - for (; m_dwTempObjNum < end_num; m_dwTempObjNum++) { - FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum); - if (offset) { - if (index >= iSize || - m_dwTempObjNum != m_ObjStream.m_Items[index].objnum) { - AppendIndex1(m_Buffer, *offset); - } else { - AppendIndex2(m_Buffer, dwObjStmNum, index++); - } - } else { - AppendIndex0(m_Buffer, false); - } - } - if (iSize > 0 && bEOF) { - pCreator->m_ObjectOffset.Add(dwObjStmNum, 1); - pCreator->m_ObjectOffset[dwObjStmNum] = objOffset; - } - m_iSeg = iSeg; - if (bEOF) { - m_ObjStream.Start(); - } - return 1; - } - for (auto it = m_IndexArray.begin() + m_iSeg; it != m_IndexArray.end(); - ++it) { - for (uint32_t m = it->objnum; m < it->objnum + it->count; ++m) { - if (m_ObjStream.m_index >= iSize || - m != m_ObjStream.m_Items[it - m_IndexArray.begin()].objnum) { - AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[m]); - } else { - AppendIndex2(m_Buffer, dwObjStmNum, m_ObjStream.m_index++); - } - } - } - if (iSize > 0 && bEOF) { - AppendIndex1(m_Buffer, objOffset); - m_IndexArray.push_back({dwObjStmNum, 1}); - iSeg += 1; - } - m_iSeg = iSeg; - if (bEOF) { - m_ObjStream.Start(); - } - return 1; -} -bool CPDF_XRefStream::GenerateXRefStream(CPDF_Creator* pCreator, bool bEOF) { - FX_FILESIZE offset_tmp = pCreator->m_Offset; - uint32_t objnum = ++pCreator->m_dwLastObjNum; - CFX_FileBufferArchive* pFile = &pCreator->m_File; - bool bIncremental = (pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL) != 0; - if (bIncremental) { - AddObjectNumberToIndexArray(objnum); - } else { - for (; m_dwTempObjNum < pCreator->m_dwLastObjNum; m_dwTempObjNum++) { - FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum); - if (offset) { - AppendIndex1(m_Buffer, *offset); - } else { - AppendIndex0(m_Buffer, false); - } - } - } - AppendIndex1(m_Buffer, offset_tmp); - FX_FILESIZE& offset = pCreator->m_Offset; - int32_t len = pFile->AppendDWord(objnum); - if (len < 0) { - return false; - } - offset += len; - if ((len = pFile->AppendString(" 0 obj\r\n<AppendDWord(0)) < 0) { - return false; - } - if ((len = pFile->AppendString(" ")) < 0) { - return false; - } - offset += len + 1; - if ((len = pFile->AppendDWord(objnum + 1)) < 0) { - return false; - } - offset += len; - } else { - for (const auto& pair : m_IndexArray) { - if ((len = pFile->AppendDWord(pair.objnum)) < 0) { - return false; - } - if (pFile->AppendString(" ") < 0) { - return false; - } - offset += len + 1; - if ((len = pFile->AppendDWord(pair.count)) < 0) { - return false; - } - if (pFile->AppendString(" ") < 0) { - return false; - } - offset += len + 1; - } - } - if (pFile->AppendString("]/Size ") < 0) { - return false; - } - if ((len = pFile->AppendDWord(objnum + 1)) < 0) { - return false; - } - offset += len + 7; - if (m_PrevOffset > 0) { - if (pFile->AppendString("/Prev ") < 0) { - return false; - } - FX_CHAR offset_buf[20]; - FXSYS_memset(offset_buf, 0, sizeof(offset_buf)); - FXSYS_i64toa(m_PrevOffset, offset_buf, 10); - int32_t offset_len = (int32_t)FXSYS_strlen(offset_buf); - if (pFile->AppendBlock(offset_buf, offset_len) < 0) { - return false; - } - offset += offset_len + 6; - } - CPDF_FlateEncoder encoder(m_Buffer.GetBuffer(), m_Buffer.GetLength(), true, - true); - if (pFile->AppendString("/Filter /FlateDecode") < 0) - return false; - - offset += 20; - if ((len = pFile->AppendString("/DecodeParms<>")) < - 0) { - return false; - } - - offset += len; - if (pFile->AppendString("/Length ") < 0) - return false; - - if ((len = pFile->AppendDWord(encoder.m_dwSize)) < 0) - return false; - - offset += len + 8; - if (bEOF) { - if ((len = PDF_CreatorWriteTrailer(pCreator->m_pDocument, pFile, - pCreator->m_pIDArray.get())) < 0) { - return false; - } - offset += len; - if (pCreator->m_pEncryptDict) { - uint32_t dwEncryptObjNum = pCreator->m_pEncryptDict->GetObjNum(); - if (dwEncryptObjNum == 0) { - dwEncryptObjNum = pCreator->m_dwEncryptObjNum; - } - if ((len = PDF_CreatorWriteEncrypt(pCreator->m_pEncryptDict, - dwEncryptObjNum, pFile)) < 0) { - return false; - } - offset += len; - } - } - if ((len = pFile->AppendString(">>stream\r\n")) < 0) - return false; - - offset += len; - if (pFile->AppendBlock(encoder.m_pData.Get(), encoder.m_dwSize) < 0) - return false; - - if ((len = pFile->AppendString("\r\nendstream\r\nendobj\r\n")) < 0) - return false; - - offset += encoder.m_dwSize + len; - m_PrevOffset = offset_tmp; - return true; -} - -bool CPDF_XRefStream::End(CPDF_Creator* pCreator, bool bEOF) { - if (EndObjectStream(pCreator, bEOF) < 0) { - return false; - } - return GenerateXRefStream(pCreator, bEOF); -} -bool CPDF_XRefStream::EndXRefStream(CPDF_Creator* pCreator) { - if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) { - AppendIndex0(m_Buffer, true); - for (uint32_t i = 1; i < pCreator->m_dwLastObjNum + 1; i++) { - FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(i); - if (offset) { - AppendIndex1(m_Buffer, *offset); - } else { - AppendIndex0(m_Buffer, false); - } - } - } else { - for (const auto& pair : m_IndexArray) { - for (uint32_t j = pair.objnum; j < pair.objnum + pair.count; ++j) - AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[j]); - } - } - return GenerateXRefStream(pCreator, false); -} -void CPDF_XRefStream::AddObjectNumberToIndexArray(uint32_t objnum) { - if (m_IndexArray.empty()) { - m_IndexArray.push_back({objnum, 1}); - return; - } - uint32_t next_objnum = m_IndexArray.back().objnum + m_IndexArray.back().count; - if (objnum == next_objnum) - m_IndexArray.back().count += 1; - else - m_IndexArray.push_back({objnum, 1}); -} - -CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc) - : m_pDocument(pDoc), - m_pParser(pDoc->GetParser()), - m_bSecurityChanged(false), - m_pEncryptDict(m_pParser ? m_pParser->GetEncryptDict() : nullptr), - m_dwEncryptObjNum(0), - m_bEncryptCloned(false), - m_pCryptoHandler(m_pParser ? m_pParser->GetCryptoHandler() : nullptr), - m_bLocalCryptoHandler(false), - m_pMetadata(nullptr), - m_ObjectStreamSize(200), - m_dwLastObjNum(m_pDocument->GetLastObjNum()), - m_Offset(0), - m_iStage(-1), - m_dwFlags(0), - m_Pos(nullptr), - m_XrefStart(0), - m_pIDArray(nullptr), - m_FileVersion(0) {} - -CPDF_Creator::~CPDF_Creator() { - ResetStandardSecurity(); - if (m_bEncryptCloned) { - delete m_pEncryptDict; - m_pEncryptDict = nullptr; - } - Clear(); -} - -int32_t CPDF_Creator::WriteIndirectObjectToStream(const CPDF_Object* pObj) { - if (!m_pXRefStream) - return 1; - - uint32_t objnum = pObj->GetObjNum(); - if (m_pParser && m_pParser->GetObjectGenNum(objnum) > 0) - return 1; - - if (pObj->IsNumber()) - return 1; - - CPDF_Dictionary* pDict = pObj->GetDict(); - if (pObj->IsStream()) { - if (pDict && pDict->GetStringFor("Type") == "XRef") - return 0; - return 1; - } - - if (pDict) { - if (pDict == m_pDocument->GetRoot() || pDict == m_pEncryptDict) - return 1; - if (pDict->IsSignatureDict()) - return 1; - if (pDict->GetStringFor("Type") == "Page") - return 1; - } - - m_pXRefStream->AddObjectNumberToIndexArray(objnum); - if (m_pXRefStream->CompressIndirectObject(objnum, pObj, this) < 0) - return -1; - if (!IsXRefNeedEnd(m_pXRefStream.get(), m_dwFlags)) - return 0; - if (!m_pXRefStream->End(this)) - return -1; - if (!m_pXRefStream->Start()) - return -1; - return 0; -} -int32_t CPDF_Creator::WriteIndirectObjectToStream(uint32_t objnum, - const uint8_t* pBuffer, - uint32_t dwSize) { - if (!m_pXRefStream) { - return 1; - } - m_pXRefStream->AddObjectNumberToIndexArray(objnum); - int32_t iRet = - m_pXRefStream->CompressIndirectObject(objnum, pBuffer, dwSize, this); - if (iRet < 1) { - return iRet; - } - if (!IsXRefNeedEnd(m_pXRefStream.get(), m_dwFlags)) { - return 0; - } - if (!m_pXRefStream->End(this)) { - return -1; - } - if (!m_pXRefStream->Start()) { - return -1; - } - return 0; -} -int32_t CPDF_Creator::AppendObjectNumberToXRef(uint32_t objnum) { - if (!m_pXRefStream) { - return 1; - } - m_pXRefStream->AddObjectNumberToIndexArray(objnum); - if (!IsXRefNeedEnd(m_pXRefStream.get(), m_dwFlags)) { - return 0; - } - if (!m_pXRefStream->End(this)) { - return -1; - } - if (!m_pXRefStream->Start()) { - return -1; - } - return 0; -} -int32_t CPDF_Creator::WriteStream(const CPDF_Object* pStream, - uint32_t objnum, - CPDF_CryptoHandler* pCrypto) { - CPDF_FlateEncoder encoder(const_cast(pStream->AsStream()), - pStream != m_pMetadata); - CPDF_Encryptor encryptor(pCrypto, objnum, encoder.m_pData.Get(), - encoder.m_dwSize); - if (static_cast(encoder.m_pDict->GetIntegerFor("Length")) != - encryptor.m_dwSize) { - encoder.CloneDict(); - encoder.m_pDict->SetNewFor( - "Length", static_cast(encryptor.m_dwSize)); - } - if (WriteDirectObj(objnum, encoder.m_pDict.Get()) < 0) - return -1; - - int len = m_File.AppendString("stream\r\n"); - if (len < 0) - return -1; - - m_Offset += len; - if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) - return -1; - - m_Offset += encryptor.m_dwSize; - if ((len = m_File.AppendString("\r\nendstream")) < 0) - return -1; - - m_Offset += len; - return 1; -} -int32_t CPDF_Creator::WriteIndirectObj(uint32_t objnum, - const CPDF_Object* pObj) { - int32_t len = m_File.AppendDWord(objnum); - if (len < 0) - return -1; - - m_Offset += len; - if ((len = m_File.AppendString(" 0 obj\r\n")) < 0) - return -1; - - m_Offset += len; - if (pObj->IsStream()) { - CPDF_CryptoHandler* pHandler = - pObj != m_pMetadata ? m_pCryptoHandler : nullptr; - if (WriteStream(pObj, objnum, pHandler) < 0) - return -1; - } else { - if (WriteDirectObj(objnum, pObj) < 0) - return -1; - } - if ((len = m_File.AppendString("\r\nendobj\r\n")) < 0) - return -1; - - m_Offset += len; - if (AppendObjectNumberToXRef(objnum) < 0) - return -1; - return 0; -} -int32_t CPDF_Creator::WriteIndirectObj(const CPDF_Object* pObj) { - int32_t iRet = WriteIndirectObjectToStream(pObj); - if (iRet < 1) { - return iRet; - } - return WriteIndirectObj(pObj->GetObjNum(), pObj); -} -int32_t CPDF_Creator::WriteDirectObj(uint32_t objnum, - const CPDF_Object* pObj, - bool bEncrypt) { - int32_t len = 0; - if (!pObj) { - if (m_File.AppendString(" null") < 0) { - return -1; - } - m_Offset += 5; - return 1; - } - switch (pObj->GetType()) { - case CPDF_Object::NULLOBJ: - if (m_File.AppendString(" null") < 0) { - return -1; - } - m_Offset += 5; - break; - case CPDF_Object::BOOLEAN: - case CPDF_Object::NUMBER: - if (m_File.AppendString(" ") < 0) { - return -1; - } - if ((len = m_File.AppendString(pObj->GetString().AsStringC())) < 0) { - return -1; - } - m_Offset += len + 1; - break; - case CPDF_Object::STRING: { - CFX_ByteString str = pObj->GetString(); - bool bHex = pObj->AsString()->IsHex(); - if (!m_pCryptoHandler || !bEncrypt) { - CFX_ByteString content = PDF_EncodeString(str, bHex); - if ((len = m_File.AppendString(content.AsStringC())) < 0) { - return -1; - } - m_Offset += len; - break; - } - CPDF_Encryptor encryptor(m_pCryptoHandler, objnum, (uint8_t*)str.c_str(), - str.GetLength()); - CFX_ByteString content = PDF_EncodeString( - CFX_ByteString((const FX_CHAR*)encryptor.m_pData, encryptor.m_dwSize), - bHex); - if ((len = m_File.AppendString(content.AsStringC())) < 0) { - return -1; - } - m_Offset += len; - break; - } - case CPDF_Object::STREAM: { - CPDF_FlateEncoder encoder(const_cast(pObj->AsStream()), - true); - CPDF_Encryptor encryptor(m_pCryptoHandler, objnum, encoder.m_pData.Get(), - encoder.m_dwSize); - if (static_cast(encoder.m_pDict->GetIntegerFor("Length")) != - encryptor.m_dwSize) { - encoder.CloneDict(); - encoder.m_pDict->SetNewFor( - "Length", static_cast(encryptor.m_dwSize)); - } - if (WriteDirectObj(objnum, encoder.m_pDict.Get()) < 0) - return -1; - - if ((len = m_File.AppendString("stream\r\n")) < 0) - return -1; - - m_Offset += len; - if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) - return -1; - - m_Offset += encryptor.m_dwSize; - if ((len = m_File.AppendString("\r\nendstream")) < 0) - return -1; - - m_Offset += len; - break; - } - case CPDF_Object::NAME: { - if (m_File.AppendString("/") < 0) { - return -1; - } - CFX_ByteString str = pObj->GetString(); - if ((len = m_File.AppendString(PDF_NameEncode(str).AsStringC())) < 0) { - return -1; - } - m_Offset += len + 1; - break; - } - case CPDF_Object::REFERENCE: { - if (m_File.AppendString(" ") < 0) - return -1; - if ((len = m_File.AppendDWord(pObj->AsReference()->GetRefObjNum())) < 0) - return -1; - if (m_File.AppendString(" 0 R") < 0) - return -1; - m_Offset += len + 5; - break; - } - case CPDF_Object::ARRAY: { - if (m_File.AppendString("[") < 0) { - return -1; - } - m_Offset += 1; - const CPDF_Array* p = pObj->AsArray(); - for (size_t i = 0; i < p->GetCount(); i++) { - CPDF_Object* pElement = p->GetObjectAt(i); - if (!pElement->IsInline()) { - if (m_File.AppendString(" ") < 0) { - return -1; - } - if ((len = m_File.AppendDWord(pElement->GetObjNum())) < 0) { - return -1; - } - if (m_File.AppendString(" 0 R") < 0) { - return -1; - } - m_Offset += len + 5; - } else { - if (WriteDirectObj(objnum, pElement) < 0) { - return -1; - } - } - } - if (m_File.AppendString("]") < 0) { - return -1; - } - m_Offset += 1; - break; - } - case CPDF_Object::DICTIONARY: { - if (!m_pCryptoHandler || pObj == m_pEncryptDict) - return PDF_CreatorAppendObject(pObj, &m_File, m_Offset); - if (m_File.AppendString("<<") < 0) - return -1; - - m_Offset += 2; - const CPDF_Dictionary* p = pObj->AsDictionary(); - bool bSignDict = p->IsSignatureDict(); - for (const auto& it : *p) { - bool bSignValue = false; - const CFX_ByteString& key = it.first; - CPDF_Object* pValue = it.second.get(); - if (m_File.AppendString("/") < 0) { - return -1; - } - if ((len = m_File.AppendString(PDF_NameEncode(key).AsStringC())) < 0) { - return -1; - } - m_Offset += len + 1; - if (bSignDict && key == "Contents") { - bSignValue = true; - } - if (!pValue->IsInline()) { - if (m_File.AppendString(" ") < 0) { - return -1; - } - if ((len = m_File.AppendDWord(pValue->GetObjNum())) < 0) { - return -1; - } - if (m_File.AppendString(" 0 R ") < 0) { - return -1; - } - m_Offset += len + 6; - } else { - if (WriteDirectObj(objnum, pValue, !bSignValue) < 0) { - return -1; - } - } - } - if (m_File.AppendString(">>") < 0) { - return -1; - } - m_Offset += 2; - break; - } - } - return 1; -} -int32_t CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { - if (m_pParser->IsObjectFreeOrNull(objnum)) - return 0; - - m_ObjectOffset[objnum] = m_Offset; - bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum); - const uint8_t object_type = m_pParser->GetObjectType(objnum); - bool bObjStm = (object_type == 2) && m_pEncryptDict && !m_pXRefStream; - if (m_pParser->IsVersionUpdated() || m_bSecurityChanged || bExistInMap || - bObjStm) { - CPDF_Object* pObj = m_pDocument->GetOrParseIndirectObject(objnum); - if (!pObj) { - m_ObjectOffset[objnum] = 0; - return 0; - } - if (WriteIndirectObj(pObj)) { - return -1; - } - if (!bExistInMap) { - m_pDocument->DeleteIndirectObject(objnum); - } - } else { - uint8_t* pBuffer; - uint32_t size; - m_pParser->GetIndirectBinary(objnum, pBuffer, size); - if (!pBuffer) { - return 0; - } - if (object_type == 2) { - if (m_pXRefStream) { - if (WriteIndirectObjectToStream(objnum, pBuffer, size) < 0) { - FX_Free(pBuffer); - return -1; - } - } else { - int32_t len = m_File.AppendDWord(objnum); - if (len < 0) { - return -1; - } - if (m_File.AppendString(" 0 obj ") < 0) { - return -1; - } - m_Offset += len + 7; - if (m_File.AppendBlock(pBuffer, size) < 0) { - return -1; - } - m_Offset += size; - if (m_File.AppendString("\r\nendobj\r\n") < 0) { - return -1; - } - m_Offset += 10; - } - } else { - if (m_File.AppendBlock(pBuffer, size) < 0) { - return -1; - } - m_Offset += size; - if (AppendObjectNumberToXRef(objnum) < 0) { - return -1; - } - } - FX_Free(pBuffer); - } - return 1; -} -int32_t CPDF_Creator::WriteOldObjs(IFX_Pause* pPause) { - uint32_t nLastObjNum = m_pParser->GetLastObjNum(); - if (!m_pParser->IsValidObjectNumber(nLastObjNum)) - return 0; - - uint32_t objnum = (uint32_t)(uintptr_t)m_Pos; - for (; objnum <= nLastObjNum; ++objnum) { - int32_t iRet = WriteOldIndirectObject(objnum); - if (iRet < 0) - return iRet; - - if (!iRet) - continue; - - if (pPause && pPause->NeedToPauseNow()) { - m_Pos = (void*)(uintptr_t)(objnum + 1); - return 1; - } - } - return 0; -} - -int32_t CPDF_Creator::WriteNewObjs(bool bIncremental, IFX_Pause* pPause) { - size_t iCount = m_NewObjNumArray.size(); - size_t index = (size_t)(uintptr_t)m_Pos; - while (index < iCount) { - uint32_t objnum = m_NewObjNumArray[index]; - CPDF_Object* pObj = m_pDocument->GetIndirectObject(objnum); - if (!pObj) { - ++index; - continue; - } - m_ObjectOffset[objnum] = m_Offset; - if (WriteIndirectObj(pObj)) - return -1; - - index++; - if (pPause && pPause->NeedToPauseNow()) { - m_Pos = (FX_POSITION)(uintptr_t)index; - return 1; - } - } - return 0; -} - -void CPDF_Creator::InitOldObjNumOffsets() { - if (!m_pParser) { - return; - } - uint32_t j = 0; - uint32_t dwStart = 0; - uint32_t dwEnd = m_pParser->GetLastObjNum(); - while (dwStart <= dwEnd) { - while (dwStart <= dwEnd && m_pParser->IsObjectFreeOrNull(dwStart)) - dwStart++; - - if (dwStart > dwEnd) - break; - - j = dwStart; - while (j <= dwEnd && !m_pParser->IsObjectFreeOrNull(j)) - j++; - - m_ObjectOffset.Add(dwStart, j - dwStart); - dwStart = j; - } -} - -void CPDF_Creator::InitNewObjNumOffsets() { - bool bIncremental = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0; - bool bNoOriginal = (m_dwFlags & FPDFCREATE_NO_ORIGINAL) != 0; - for (const auto& pair : *m_pDocument) { - const uint32_t objnum = pair.first; - const CPDF_Object* pObj = pair.second.get(); - if (bIncremental || pObj->GetObjNum() == CPDF_Object::kInvalidObjNum) - continue; - if (m_pParser && m_pParser->IsValidObjectNumber(objnum) && - m_pParser->GetObjectType(objnum)) { - continue; - } - AppendNewObjNum(objnum); - } - - size_t iCount = m_NewObjNumArray.size(); - if (iCount == 0) - return; - - size_t i = 0; - uint32_t dwStartObjNum = 0; - bool bCrossRefValid = m_pParser && m_pParser->GetLastXRefOffset() > 0; - while (i < iCount) { - dwStartObjNum = m_NewObjNumArray[i]; - if ((bIncremental && (bNoOriginal || bCrossRefValid)) || - !m_ObjectOffset.GetPtrAt(dwStartObjNum)) { - break; - } - i++; - } - if (i >= iCount) - return; - - uint32_t dwLastObjNum = dwStartObjNum; - i++; - bool bNewStart = false; - for (; i < iCount; i++) { - uint32_t dwCurObjNum = m_NewObjNumArray[i]; - bool bExist = m_pParser && m_pParser->IsValidObjectNumber(dwCurObjNum) && - m_ObjectOffset.GetPtrAt(dwCurObjNum); - if (bExist || dwCurObjNum - dwLastObjNum > 1) { - if (!bNewStart) - m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1); - dwStartObjNum = dwCurObjNum; - } - if (bNewStart) - dwStartObjNum = dwCurObjNum; - - bNewStart = bExist; - dwLastObjNum = dwCurObjNum; - } - m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1); -} - -void CPDF_Creator::AppendNewObjNum(uint32_t objnum) { - m_NewObjNumArray.insert(std::lower_bound(m_NewObjNumArray.begin(), - m_NewObjNumArray.end(), objnum), - objnum); -} - -int32_t CPDF_Creator::WriteDoc_Stage1(IFX_Pause* pPause) { - ASSERT(m_iStage > -1 || m_iStage < 20); - if (m_iStage == 0) { - if (!m_pParser) { - m_dwFlags &= ~FPDFCREATE_INCREMENTAL; - } - if (m_bSecurityChanged && (m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0) { - m_dwFlags &= ~FPDFCREATE_INCREMENTAL; - } - CPDF_Dictionary* pDict = m_pDocument->GetRoot(); - m_pMetadata = pDict ? pDict->GetDirectObjectFor("Metadata") : nullptr; - if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) { - m_pXRefStream = pdfium::MakeUnique(); - m_pXRefStream->Start(); - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser) { - FX_FILESIZE prev = m_pParser->GetLastXRefOffset(); - m_pXRefStream->m_PrevOffset = prev; - } - } - m_iStage = 10; - } - if (m_iStage == 10) { - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0) { - if (m_File.AppendString("%PDF-1.") < 0) { - return -1; - } - m_Offset += 7; - int32_t version = 7; - if (m_FileVersion) { - version = m_FileVersion; - } else if (m_pParser) { - version = m_pParser->GetFileVersion(); - } - int32_t len = m_File.AppendDWord(version % 10); - if (len < 0) { - return -1; - } - m_Offset += len; - if ((len = m_File.AppendString("\r\n%\xA1\xB3\xC5\xD7\r\n")) < 0) { - return -1; - } - m_Offset += len; - InitOldObjNumOffsets(); - m_iStage = 20; - } else { - CFX_RetainPtr pSrcFile = - m_pParser->GetFileAccess(); - m_Offset = pSrcFile->GetSize(); - m_Pos = (void*)(uintptr_t)m_Offset; - m_iStage = 15; - } - } - if (m_iStage == 15) { - if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && m_Pos) { - CFX_RetainPtr pSrcFile = - m_pParser->GetFileAccess(); - uint8_t buffer[4096]; // TODO(tsepez): don't stack allocate. - uint32_t src_size = (uint32_t)(uintptr_t)m_Pos; - while (src_size) { - uint32_t block_size = src_size > 4096 ? 4096 : src_size; - if (!pSrcFile->ReadBlock(buffer, m_Offset - src_size, block_size)) { - return -1; - } - if (m_File.AppendBlock(buffer, block_size) < 0) { - return -1; - } - src_size -= block_size; - if (pPause && pPause->NeedToPauseNow()) { - m_Pos = (void*)(uintptr_t)src_size; - return 1; - } - } - } - if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && - m_pParser->GetLastXRefOffset() == 0) { - InitOldObjNumOffsets(); - uint32_t dwEnd = m_pParser->GetLastObjNum(); - bool bObjStm = (m_dwFlags & FPDFCREATE_OBJECTSTREAM) != 0; - for (uint32_t objnum = 0; objnum <= dwEnd; objnum++) { - if (m_pParser->IsObjectFreeOrNull(objnum)) - continue; - - m_ObjectOffset[objnum] = m_pParser->GetObjectPositionOrZero(objnum); - if (bObjStm) { - m_pXRefStream->AddObjectNumberToIndexArray(objnum); - } - } - if (bObjStm) { - m_pXRefStream->EndXRefStream(this); - m_pXRefStream->Start(); - } - } - m_iStage = 20; - } - InitNewObjNumOffsets(); - return m_iStage; -} -int32_t CPDF_Creator::WriteDoc_Stage2(IFX_Pause* pPause) { - ASSERT(m_iStage >= 20 || m_iStage < 30); - if (m_iStage == 20) { - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 && m_pParser) { - m_Pos = (void*)(uintptr_t)0; - m_iStage = 21; - } else { - m_iStage = 25; - } - } - if (m_iStage == 21) { - int32_t iRet = WriteOldObjs(pPause); - if (iRet) { - return iRet; - } - m_iStage = 25; - } - if (m_iStage == 25) { - m_Pos = (void*)(uintptr_t)0; - m_iStage = 26; - } - if (m_iStage == 26) { - int32_t iRet = - WriteNewObjs((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0, pPause); - if (iRet) { - return iRet; - } - m_iStage = 27; - } - if (m_iStage == 27) { - if (m_pEncryptDict && m_pEncryptDict->IsInline()) { - m_dwLastObjNum += 1; - FX_FILESIZE saveOffset = m_Offset; - if (WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict) < 0) - return -1; - - m_ObjectOffset.Add(m_dwLastObjNum, 1); - m_ObjectOffset[m_dwLastObjNum] = saveOffset; - m_dwEncryptObjNum = m_dwLastObjNum; - if (m_dwFlags & FPDFCREATE_INCREMENTAL) - m_NewObjNumArray.push_back(m_dwLastObjNum); - } - m_iStage = 80; - } - return m_iStage; -} -int32_t CPDF_Creator::WriteDoc_Stage3(IFX_Pause* pPause) { - ASSERT(m_iStage >= 80 || m_iStage < 90); - uint32_t dwLastObjNum = m_dwLastObjNum; - if (m_iStage == 80) { - m_XrefStart = m_Offset; - if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) { - m_pXRefStream->End(this, true); - m_XrefStart = m_pXRefStream->m_PrevOffset; - m_iStage = 90; - } else if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 || - !m_pParser->IsXRefStream()) { - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 || - m_pParser->GetLastXRefOffset() == 0) { - CFX_ByteString str; - str = m_ObjectOffset.GetPtrAt(1) - ? "xref\r\n" - : "xref\r\n0 1\r\n0000000000 65535 f\r\n"; - if (m_File.AppendString(str.AsStringC()) < 0) { - return -1; - } - m_Pos = (void*)(uintptr_t)1; - m_iStage = 81; - } else { - if (m_File.AppendString("xref\r\n") < 0) { - return -1; - } - m_Pos = (void*)(uintptr_t)0; - m_iStage = 82; - } - } else { - m_iStage = 90; - } - } - if (m_iStage == 81) { - CFX_ByteString str; - uint32_t i = (uint32_t)(uintptr_t)m_Pos, j; - while (i <= dwLastObjNum) { - while (i <= dwLastObjNum && !m_ObjectOffset.GetPtrAt(i)) { - i++; - } - if (i > dwLastObjNum) { - break; - } - j = i; - while (j <= dwLastObjNum && m_ObjectOffset.GetPtrAt(j)) { - j++; - } - if (i == 1) { - str.Format("0 %d\r\n0000000000 65535 f\r\n", j); - } else { - str.Format("%d %d\r\n", i, j - i); - } - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) { - return -1; - } - while (i < j) { - str.Format("%010d 00000 n\r\n", m_ObjectOffset[i++]); - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) { - return -1; - } - } - if (i > dwLastObjNum) { - break; - } - if (pPause && pPause->NeedToPauseNow()) { - m_Pos = (void*)(uintptr_t)i; - return 1; - } - } - m_iStage = 90; - } - if (m_iStage == 82) { - CFX_ByteString str; - size_t iCount = m_NewObjNumArray.size(); - size_t i = (size_t)(uintptr_t)m_Pos; - while (i < iCount) { - size_t j = i; - uint32_t objnum = m_NewObjNumArray[i]; - while (j < iCount) { - if (++j == iCount) - break; - uint32_t dwCurrent = m_NewObjNumArray[j]; - if (dwCurrent - objnum > 1) - break; - objnum = dwCurrent; - } - objnum = m_NewObjNumArray[i]; - if (objnum == 1) { - str.Format("0 %d\r\n0000000000 65535 f\r\n", j - i + 1); - } else { - str.Format("%d %d\r\n", objnum, j - i); - } - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) { - return -1; - } - while (i < j) { - objnum = m_NewObjNumArray[i++]; - str.Format("%010d 00000 n\r\n", m_ObjectOffset[objnum]); - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) - return -1; - } - if (pPause && (i % 100) == 0 && pPause->NeedToPauseNow()) { - m_Pos = (void*)(uintptr_t)i; - return 1; - } - } - m_iStage = 90; - } - return m_iStage; -} - -int32_t CPDF_Creator::WriteDoc_Stage4(IFX_Pause* pPause) { - ASSERT(m_iStage >= 90); - if ((m_dwFlags & FPDFCREATE_OBJECTSTREAM) == 0) { - bool bXRefStream = - (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser->IsXRefStream(); - if (!bXRefStream) { - if (m_File.AppendString("trailer\r\n<<") < 0) { - return -1; - } - } else { - if (m_File.AppendDWord(m_pDocument->GetLastObjNum() + 1) < 0) { - return -1; - } - if (m_File.AppendString(" 0 obj <<") < 0) { - return -1; - } - } - if (m_pParser) { - CPDF_Dictionary* p = m_pParser->GetTrailer(); - for (const auto& it : *p) { - const CFX_ByteString& key = it.first; - CPDF_Object* pValue = it.second.get(); - // TODO(ochang): Consolidate with similar check in - // PDF_CreatorWriteTrailer. - if (key == "Encrypt" || key == "Size" || key == "Filter" || - key == "Index" || key == "Length" || key == "Prev" || key == "W" || - key == "XRefStm" || key == "ID") { - continue; - } - if (m_File.AppendString(("/")) < 0) { - return -1; - } - if (m_File.AppendString(PDF_NameEncode(key).AsStringC()) < 0) { - return -1; - } - if (!pValue->IsInline()) { - if (m_File.AppendString(" ") < 0) { - return -1; - } - if (m_File.AppendDWord(pValue->GetObjNum()) < 0) { - return -1; - } - if (m_File.AppendString(" 0 R ") < 0) { - return -1; - } - } else { - FX_FILESIZE offset = 0; - if (PDF_CreatorAppendObject(pValue, &m_File, offset) < 0) { - return -1; - } - } - } - } else { - if (m_File.AppendString("\r\n/Root ") < 0) { - return -1; - } - if (m_File.AppendDWord(m_pDocument->GetRoot()->GetObjNum()) < 0) { - return -1; - } - if (m_File.AppendString(" 0 R\r\n") < 0) { - return -1; - } - if (m_pDocument->GetInfo()) { - if (m_File.AppendString("/Info ") < 0) { - return -1; - } - if (m_File.AppendDWord(m_pDocument->GetInfo()->GetObjNum()) < 0) { - return -1; - } - if (m_File.AppendString(" 0 R\r\n") < 0) { - return -1; - } - } - } - if (m_pEncryptDict) { - if (m_File.AppendString("/Encrypt") < 0) { - return -1; - } - uint32_t dwObjNum = m_pEncryptDict->GetObjNum(); - if (dwObjNum == 0) { - dwObjNum = m_pDocument->GetLastObjNum() + 1; - } - if (m_File.AppendString(" ") < 0) { - return -1; - } - if (m_File.AppendDWord(dwObjNum) < 0) { - return -1; - } - if (m_File.AppendString(" 0 R ") < 0) { - return -1; - } - } - if (m_File.AppendString("/Size ") < 0) { - return -1; - } - if (m_File.AppendDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1)) < 0) { - return -1; - } - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0) { - FX_FILESIZE prev = m_pParser->GetLastXRefOffset(); - if (prev) { - if (m_File.AppendString("/Prev ") < 0) { - return -1; - } - FX_CHAR offset_buf[20]; - FXSYS_memset(offset_buf, 0, sizeof(offset_buf)); - FXSYS_i64toa(prev, offset_buf, 10); - if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) { - return -1; - } - } - } - if (m_pIDArray) { - if (m_File.AppendString(("/ID")) < 0) { - return -1; - } - FX_FILESIZE offset = 0; - if (PDF_CreatorAppendObject(m_pIDArray.get(), &m_File, offset) < 0) { - return -1; - } - } - if (!bXRefStream) { - if (m_File.AppendString(">>") < 0) { - return -1; - } - } else { - if (m_File.AppendString("/W[0 4 1]/Index[") < 0) { - return -1; - } - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser && - m_pParser->GetLastXRefOffset() == 0) { - uint32_t i = 0; - for (i = 0; i < m_dwLastObjNum; i++) { - if (!m_ObjectOffset.GetPtrAt(i)) { - continue; - } - if (m_File.AppendDWord(i) < 0) { - return -1; - } - if (m_File.AppendString(" 1 ") < 0) { - return -1; - } - } - if (m_File.AppendString("]/Length ") < 0) { - return -1; - } - if (m_File.AppendDWord(m_dwLastObjNum * 5) < 0) { - return -1; - } - if (m_File.AppendString(">>stream\r\n") < 0) { - return -1; - } - for (i = 0; i < m_dwLastObjNum; i++) { - FX_FILESIZE* offset = m_ObjectOffset.GetPtrAt(i); - if (!offset) - continue; - OutputIndex(&m_File, *offset); - } - } else { - size_t count = m_NewObjNumArray.size(); - size_t i = 0; - for (i = 0; i < count; i++) { - if (m_File.AppendDWord(m_NewObjNumArray[i]) < 0) - return -1; - if (m_File.AppendString(" 1 ") < 0) - return -1; - } - if (m_File.AppendString("]/Length ") < 0) - return -1; - if (m_File.AppendDWord(count * 5) < 0) - return -1; - if (m_File.AppendString(">>stream\r\n") < 0) - return -1; - for (i = 0; i < count; i++) { - uint32_t objnum = m_NewObjNumArray[i]; - FX_FILESIZE offset = m_ObjectOffset[objnum]; - OutputIndex(&m_File, offset); - } - } - if (m_File.AppendString("\r\nendstream") < 0) - return -1; - } - } - if (m_File.AppendString("\r\nstartxref\r\n") < 0) { - return -1; - } - FX_CHAR offset_buf[20]; - FXSYS_memset(offset_buf, 0, sizeof(offset_buf)); - FXSYS_i64toa(m_XrefStart, offset_buf, 10); - if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) { - return -1; - } - if (m_File.AppendString("\r\n%%EOF\r\n") < 0) { - return -1; - } - m_File.Flush(); - return m_iStage = 100; -} - -void CPDF_Creator::Clear() { - m_pXRefStream.reset(); - m_File.Clear(); - m_NewObjNumArray.clear(); - m_pIDArray.reset(); -} - -bool CPDF_Creator::Create(const CFX_RetainPtr& pFile, - uint32_t flags) { - m_File.AttachFile(pFile); - return Create(flags); -} - -bool CPDF_Creator::Create(uint32_t flags) { - m_dwFlags = flags; - m_iStage = 0; - m_Offset = 0; - m_dwLastObjNum = m_pDocument->GetLastObjNum(); - m_ObjectOffset.Clear(); - m_NewObjNumArray.clear(); - InitID(); - if (flags & FPDFCREATE_PROGRESSIVE) - return true; - return Continue(nullptr) > -1; -} - -void CPDF_Creator::InitID(bool bDefault) { - CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : nullptr; - bool bNewId = !m_pIDArray; - if (bNewId) { - m_pIDArray = pdfium::MakeUnique(); - CPDF_Object* pID1 = pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr; - if (pID1) { - m_pIDArray->Add(pID1->Clone()); - } else { - std::vector buffer = - PDF_GenerateFileID((uint32_t)(uintptr_t) this, m_dwLastObjNum); - CFX_ByteString bsBuffer(buffer.data(), buffer.size()); - m_pIDArray->AddNew(bsBuffer, true); - } - } - if (!bDefault) { - return; - } - if (pOldIDArray) { - CPDF_Object* pID2 = pOldIDArray->GetObjectAt(1); - if ((m_dwFlags & FPDFCREATE_INCREMENTAL) && m_pEncryptDict && pID2) { - m_pIDArray->Add(pID2->Clone()); - return; - } - std::vector buffer = - PDF_GenerateFileID((uint32_t)(uintptr_t) this, m_dwLastObjNum); - CFX_ByteString bsBuffer(buffer.data(), buffer.size()); - m_pIDArray->AddNew(bsBuffer, true); - return; - } - m_pIDArray->Add(m_pIDArray->GetObjectAt(0)->Clone()); - if (m_pEncryptDict && !pOldIDArray && m_pParser && bNewId) { - if (m_pEncryptDict->GetStringFor("Filter") == "Standard") { - CFX_ByteString user_pass = m_pParser->GetPassword(); - uint32_t flag = PDF_ENCRYPT_CONTENT; - CPDF_SecurityHandler handler; - handler.OnCreate(m_pEncryptDict, m_pIDArray.get(), user_pass.raw_str(), - user_pass.GetLength(), flag); - if (m_bLocalCryptoHandler) - delete m_pCryptoHandler; - m_pCryptoHandler = new CPDF_CryptoHandler; - m_pCryptoHandler->Init(m_pEncryptDict, &handler); - m_bLocalCryptoHandler = true; - m_bSecurityChanged = true; - } - } -} -int32_t CPDF_Creator::Continue(IFX_Pause* pPause) { - if (m_iStage < 0) { - return m_iStage; - } - int32_t iRet = 0; - while (m_iStage < 100) { - if (m_iStage < 20) { - iRet = WriteDoc_Stage1(pPause); - } else if (m_iStage < 30) { - iRet = WriteDoc_Stage2(pPause); - } else if (m_iStage < 90) { - iRet = WriteDoc_Stage3(pPause); - } else { - iRet = WriteDoc_Stage4(pPause); - } - if (iRet < m_iStage) { - break; - } - } - if (iRet < 1 || m_iStage == 100) { - m_iStage = -1; - Clear(); - return iRet > 99 ? 0 : (iRet < 1 ? -1 : iRet); - } - return m_iStage; -} -bool CPDF_Creator::SetFileVersion(int32_t fileVersion) { - if (fileVersion < 10 || fileVersion > 17) { - return false; - } - m_FileVersion = fileVersion; - return true; -} -void CPDF_Creator::RemoveSecurity() { - ResetStandardSecurity(); - m_bSecurityChanged = true; - m_pEncryptDict = nullptr; - m_pCryptoHandler = nullptr; -} -void CPDF_Creator::ResetStandardSecurity() { - if (!m_bLocalCryptoHandler) - return; - - delete m_pCryptoHandler; - m_pCryptoHandler = nullptr; - m_bLocalCryptoHandler = false; -} diff --git a/core/fpdfapi/font/cfx_cttgsubtable.cpp b/core/fpdfapi/font/cfx_cttgsubtable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae868ca5ab152d33ebd89c1fae51bb6a7477c12c --- /dev/null +++ b/core/fpdfapi/font/cfx_cttgsubtable.cpp @@ -0,0 +1,359 @@ +// 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 "core/fpdfapi/font/cfx_cttgsubtable.h" + +#include + +#include "core/fxge/fx_freetype.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CFX_CTTGSUBTable::CFX_CTTGSUBTable() : m_bFeautureMapLoad(false) {} + +CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {} + +bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) { + if ((gsub[0] << 24u | gsub[1] << 16u | gsub[2] << 8u | gsub[3]) != 0x00010000) + return false; + + return Parse(&gsub[gsub[4] << 8 | gsub[5]], &gsub[gsub[6] << 8 | gsub[7]], + &gsub[gsub[8] << 8 | gsub[9]]); +} + +bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum, + uint32_t* vglyphnum) { + uint32_t tag[] = { + (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 | + (uint8_t)'2', + (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 | + (uint8_t)'t', + }; + if (!m_bFeautureMapLoad) { + for (const TScriptRecord& script : ScriptList) { + for (const auto& record : script.LangSysRecords) { + for (const auto& index : record.FeatureIndices) { + if (FeatureList[index].FeatureTag == tag[0] || + FeatureList[index].FeatureTag == tag[1]) { + m_featureSet.insert(index); + } + } + } + } + if (m_featureSet.empty()) { + int i = 0; + for (const TFeatureRecord& feature : FeatureList) { + if (feature.FeatureTag == tag[0] || feature.FeatureTag == tag[1]) + m_featureSet.insert(i); + ++i; + } + } + m_bFeautureMapLoad = true; + } + for (const auto& item : m_featureSet) { + if (GetVerticalGlyphSub(glyphnum, vglyphnum, &FeatureList[item])) { + return true; + } + } + return false; +} + +bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum, + uint32_t* vglyphnum, + TFeatureRecord* Feature) { + for (int index : Feature->LookupListIndices) { + if (!pdfium::IndexInBounds(LookupList, index)) + continue; + if (LookupList[index].LookupType == 1 && + GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList[index])) { + return true; + } + } + return false; +} + +bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum, + uint32_t* vglyphnum, + TLookup* Lookup) { + for (const auto& subTable : Lookup->SubTables) { + switch (subTable->SubstFormat) { + case 1: { + auto* tbl1 = static_cast(subTable.get()); + if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) { + *vglyphnum = glyphnum + tbl1->DeltaGlyphID; + return true; + } + break; + } + case 2: { + auto* tbl2 = static_cast(subTable.get()); + int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum); + if (pdfium::IndexInBounds(tbl2->Substitutes, index)) { + *vglyphnum = tbl2->Substitutes[index]; + return true; + } + break; + } + } + } + return false; +} + +int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage, + uint32_t g) const { + if (!Coverage) + return -1; + + switch (Coverage->CoverageFormat) { + case 1: { + int i = 0; + TCoverageFormat1* c1 = static_cast(Coverage); + for (const auto& glyph : c1->GlyphArray) { + if (static_cast(glyph) == g) + return i; + ++i; + } + return -1; + } + case 2: { + TCoverageFormat2* c2 = static_cast(Coverage); + for (const auto& rangeRec : c2->RangeRecords) { + uint32_t s = rangeRec.Start; + uint32_t e = rangeRec.End; + uint32_t si = rangeRec.StartCoverageIndex; + if (s <= g && g <= e) + return si + g - s; + } + return -1; + } + } + return -1; +} + +uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const { + uint8_t ret = p[0]; + p += 1; + return ret; +} + +int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const { + uint16_t ret = p[0] << 8 | p[1]; + p += 2; + return *(int16_t*)&ret; +} + +uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const { + uint16_t ret = p[0] << 8 | p[1]; + p += 2; + return ret; +} + +int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const { + uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + p += 4; + return *(int32_t*)&ret; +} + +uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const { + uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + p += 4; + return ret; +} + +bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist, + FT_Bytes featurelist, + FT_Bytes lookuplist) { + ParseScriptList(scriptlist); + ParseFeatureList(featurelist); + ParseLookupList(lookuplist); + return true; +} + +void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw) { + FT_Bytes sp = raw; + ScriptList = std::vector(GetUInt16(sp)); + for (auto& scriptRec : ScriptList) { + scriptRec.ScriptTag = GetUInt32(sp); + ParseScript(&raw[GetUInt16(sp)], &scriptRec); + } +} + +void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScriptRecord* rec) { + FT_Bytes sp = raw; + rec->DefaultLangSys = GetUInt16(sp); + rec->LangSysRecords = std::vector(GetUInt16(sp)); + for (auto& sysRecord : rec->LangSysRecords) { + sysRecord.LangSysTag = GetUInt32(sp); + ParseLangSys(&raw[GetUInt16(sp)], &sysRecord); + } +} + +void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSysRecord* rec) { + FT_Bytes sp = raw; + rec->LookupOrder = GetUInt16(sp); + rec->ReqFeatureIndex = GetUInt16(sp); + rec->FeatureIndices = std::vector(GetUInt16(sp)); + for (auto& element : rec->FeatureIndices) + element = GetUInt16(sp); +} + +void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw) { + FT_Bytes sp = raw; + FeatureList = std::vector(GetUInt16(sp)); + for (auto& featureRec : FeatureList) { + featureRec.FeatureTag = GetUInt32(sp); + ParseFeature(&raw[GetUInt16(sp)], &featureRec); + } +} + +void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeatureRecord* rec) { + FT_Bytes sp = raw; + rec->FeatureParams = GetUInt16(sp); + rec->LookupListIndices = std::vector(GetUInt16(sp)); + for (auto& listIndex : rec->LookupListIndices) + listIndex = GetUInt16(sp); +} + +void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw) { + FT_Bytes sp = raw; + LookupList = std::vector(GetUInt16(sp)); + for (auto& lookup : LookupList) + ParseLookup(&raw[GetUInt16(sp)], &lookup); +} + +void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) { + FT_Bytes sp = raw; + rec->LookupType = GetUInt16(sp); + rec->LookupFlag = GetUInt16(sp); + rec->SubTables = std::vector>(GetUInt16(sp)); + if (rec->LookupType != 1) + return; + + for (auto& subTable : rec->SubTables) + ParseSingleSubst(&raw[GetUInt16(sp)], &subTable); +} + +std::unique_ptr +CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw) { + FT_Bytes sp = raw; + uint16_t format = GetUInt16(sp); + if (format == 1) { + auto rec = pdfium::MakeUnique(); + ParseCoverageFormat1(raw, rec.get()); + return std::move(rec); + } + if (format == 2) { + auto rec = pdfium::MakeUnique(); + ParseCoverageFormat2(raw, rec.get()); + return std::move(rec); + } + return nullptr; +} + +void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw, + TCoverageFormat1* rec) { + FT_Bytes sp = raw; + (void)GetUInt16(sp); + rec->GlyphArray = std::vector(GetUInt16(sp)); + for (auto& glyph : rec->GlyphArray) + glyph = GetUInt16(sp); +} + +void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw, + TCoverageFormat2* rec) { + FT_Bytes sp = raw; + (void)GetUInt16(sp); + rec->RangeRecords = std::vector(GetUInt16(sp)); + for (auto& rangeRec : rec->RangeRecords) { + rangeRec.Start = GetUInt16(sp); + rangeRec.End = GetUInt16(sp); + rangeRec.StartCoverageIndex = GetUInt16(sp); + } +} + +void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, + std::unique_ptr* rec) { + FT_Bytes sp = raw; + uint16_t Format = GetUInt16(sp); + switch (Format) { + case 1: + *rec = pdfium::MakeUnique(); + ParseSingleSubstFormat1(raw, static_cast(rec->get())); + break; + case 2: + *rec = pdfium::MakeUnique(); + ParseSingleSubstFormat2(raw, static_cast(rec->get())); + break; + } +} + +void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw, TSubTable1* rec) { + FT_Bytes sp = raw; + GetUInt16(sp); + uint16_t offset = GetUInt16(sp); + rec->Coverage = ParseCoverage(&raw[offset]); + rec->DeltaGlyphID = GetInt16(sp); +} + +void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw, TSubTable2* rec) { + FT_Bytes sp = raw; + (void)GetUInt16(sp); + uint16_t offset = GetUInt16(sp); + rec->Coverage = ParseCoverage(&raw[offset]); + rec->Substitutes = std::vector(GetUInt16(sp)); + for (auto& substitute : rec->Substitutes) + substitute = GetUInt16(sp); +} + +CFX_CTTGSUBTable::TLangSysRecord::TLangSysRecord() + : LangSysTag(0), LookupOrder(0), ReqFeatureIndex(0) {} + +CFX_CTTGSUBTable::TLangSysRecord::~TLangSysRecord() {} + +CFX_CTTGSUBTable::TScriptRecord::TScriptRecord() + : ScriptTag(0), DefaultLangSys(0) {} + +CFX_CTTGSUBTable::TScriptRecord::~TScriptRecord() {} + +CFX_CTTGSUBTable::TFeatureRecord::TFeatureRecord() + : FeatureTag(0), FeatureParams(0) {} + +CFX_CTTGSUBTable::TFeatureRecord::~TFeatureRecord() {} + +CFX_CTTGSUBTable::TRangeRecord::TRangeRecord() + : Start(0), End(0), StartCoverageIndex(0) {} + +CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1() { + CoverageFormat = 1; +} + +CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {} + +CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2() { + CoverageFormat = 2; +} + +CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {} + +CFX_CTTGSUBTable::TSubTableBase::TSubTableBase() {} + +CFX_CTTGSUBTable::TSubTableBase::~TSubTableBase() {} + +CFX_CTTGSUBTable::TSubTable1::TSubTable1() { + SubstFormat = 1; +} + +CFX_CTTGSUBTable::TSubTable1::~TSubTable1() {} + +CFX_CTTGSUBTable::TSubTable2::TSubTable2() { + SubstFormat = 2; +} + +CFX_CTTGSUBTable::TSubTable2::~TSubTable2() {} + +CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {} + +CFX_CTTGSUBTable::TLookup::~TLookup() {} diff --git a/core/fpdfapi/font/cfx_cttgsubtable.h b/core/fpdfapi/font/cfx_cttgsubtable.h new file mode 100644 index 0000000000000000000000000000000000000000..fc1caf5ef2f6662f17210e7b03abf0e0f4635644 --- /dev/null +++ b/core/fpdfapi/font/cfx_cttgsubtable.h @@ -0,0 +1,157 @@ +// 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 CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_ +#define CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_ + +#include + +#include +#include +#include + +#include "core/fxge/fx_freetype.h" + +class CFX_CTTGSUBTable { + public: + CFX_CTTGSUBTable(); + ~CFX_CTTGSUBTable(); + + bool LoadGSUBTable(FT_Bytes gsub); + bool GetVerticalGlyph(uint32_t glyphnum, uint32_t* vglyphnum); + + private: + struct TLangSysRecord { + TLangSysRecord(); + ~TLangSysRecord(); + + uint32_t LangSysTag; + uint16_t LookupOrder; + uint16_t ReqFeatureIndex; + std::vector FeatureIndices; + }; + + struct TScriptRecord { + TScriptRecord(); + ~TScriptRecord(); + + uint32_t ScriptTag; + uint16_t DefaultLangSys; + std::vector LangSysRecords; + }; + + struct TFeatureRecord { + TFeatureRecord(); + ~TFeatureRecord(); + + uint32_t FeatureTag; + uint16_t FeatureParams; + std::vector LookupListIndices; + }; + + struct TRangeRecord { + TRangeRecord(); + + uint16_t Start; + uint16_t End; + uint16_t StartCoverageIndex; + }; + + struct TCoverageFormatBase { + virtual ~TCoverageFormatBase() {} + uint16_t CoverageFormat; + }; + + struct TCoverageFormat1 : public TCoverageFormatBase { + TCoverageFormat1(); + ~TCoverageFormat1() override; + + std::vector GlyphArray; + }; + + struct TCoverageFormat2 : public TCoverageFormatBase { + TCoverageFormat2(); + ~TCoverageFormat2() override; + + std::vector RangeRecords; + }; + + struct TDevice { + TDevice() : StartSize(0), EndSize(0), DeltaFormat(0) {} + + uint16_t StartSize; + uint16_t EndSize; + uint16_t DeltaFormat; + }; + + struct TSubTableBase { + TSubTableBase(); + virtual ~TSubTableBase(); + + std::unique_ptr Coverage; + uint16_t SubstFormat; + }; + + struct TSubTable1 : public TSubTableBase { + TSubTable1(); + ~TSubTable1() override; + + int16_t DeltaGlyphID; + }; + + struct TSubTable2 : public TSubTableBase { + TSubTable2(); + ~TSubTable2() override; + + std::vector Substitutes; + }; + + struct TLookup { + TLookup(); + ~TLookup(); + + uint16_t LookupType; + uint16_t LookupFlag; + std::vector> SubTables; + }; + + bool Parse(FT_Bytes scriptlist, FT_Bytes featurelist, FT_Bytes lookuplist); + void ParseScriptList(FT_Bytes raw); + void ParseScript(FT_Bytes raw, TScriptRecord* rec); + void ParseLangSys(FT_Bytes raw, TLangSysRecord* rec); + void ParseFeatureList(FT_Bytes raw); + void ParseFeature(FT_Bytes raw, TFeatureRecord* rec); + void ParseLookupList(FT_Bytes raw); + void ParseLookup(FT_Bytes raw, TLookup* rec); + std::unique_ptr ParseCoverage(FT_Bytes raw); + void ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1* rec); + void ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2* rec); + void ParseSingleSubst(FT_Bytes raw, std::unique_ptr* rec); + void ParseSingleSubstFormat1(FT_Bytes raw, TSubTable1* rec); + void ParseSingleSubstFormat2(FT_Bytes raw, TSubTable2* rec); + + bool GetVerticalGlyphSub(uint32_t glyphnum, + uint32_t* vglyphnum, + TFeatureRecord* Feature); + bool GetVerticalGlyphSub2(uint32_t glyphnum, + uint32_t* vglyphnum, + TLookup* Lookup); + int GetCoverageIndex(TCoverageFormatBase* Coverage, uint32_t g) const; + + uint8_t GetUInt8(FT_Bytes& p) const; + int16_t GetInt16(FT_Bytes& p) const; + uint16_t GetUInt16(FT_Bytes& p) const; + int32_t GetInt32(FT_Bytes& p) const; + uint32_t GetUInt32(FT_Bytes& p) const; + + std::set m_featureSet; + bool m_bFeautureMapLoad; + std::vector ScriptList; + std::vector FeatureList; + std::vector LookupList; +}; + +#endif // CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_ diff --git a/core/fpdfapi/font/cfx_stockfontarray.cpp b/core/fpdfapi/font/cfx_stockfontarray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0808471c82b92ab632ebd9a1515b84a4d54bedf2 --- /dev/null +++ b/core/fpdfapi/font/cfx_stockfontarray.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/font/cfx_stockfontarray.h" + +#include +#include + +#include "core/fxcrt/fx_memory.h" + +CFX_StockFontArray::CFX_StockFontArray() {} + +CFX_StockFontArray::~CFX_StockFontArray() { + for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) { + if (m_StockFonts[i]) + delete m_StockFonts[i]->GetFontDict(); + } +} + +CPDF_Font* CFX_StockFontArray::GetFont(uint32_t index) const { + if (index >= FX_ArraySize(m_StockFonts)) + return nullptr; + return m_StockFonts[index].get(); +} + +CPDF_Font* CFX_StockFontArray::SetFont(uint32_t index, + std::unique_ptr pFont) { + CPDF_Font* result = pFont.get(); + if (index < FX_ArraySize(m_StockFonts)) + m_StockFonts[index] = std::move(pFont); + return result; +} diff --git a/core/fpdfapi/font/cfx_stockfontarray.h b/core/fpdfapi/font/cfx_stockfontarray.h new file mode 100644 index 0000000000000000000000000000000000000000..50a13c167fa139889c1f7e3666c2c5197b75ac27 --- /dev/null +++ b/core/fpdfapi/font/cfx_stockfontarray.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CFX_STOCKFONTARRAY_H_ +#define CORE_FPDFAPI_FONT_CFX_STOCKFONTARRAY_H_ + +#include + +#include "core/fpdfapi/font/cpdf_font.h" + +class CFX_StockFontArray { + public: + CFX_StockFontArray(); + ~CFX_StockFontArray(); + + // Takes ownership of |pFont|, returns unowned pointer to it. + CPDF_Font* SetFont(uint32_t index, std::unique_ptr pFont); + CPDF_Font* GetFont(uint32_t index) const; + + private: + std::unique_ptr m_StockFonts[14]; +}; + +#endif // CORE_FPDFAPI_FONT_CFX_STOCKFONTARRAY_H_ diff --git a/core/fpdfapi/font/cpdf_cid2unicodemap.cpp b/core/fpdfapi/font/cpdf_cid2unicodemap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..650856419af21b206eba4412c7622830ad87fd7b --- /dev/null +++ b/core/fpdfapi/font/cpdf_cid2unicodemap.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cpdf_cmapmanager.h" +#include "core/fpdfapi/page/cpdf_pagemodule.h" + +CPDF_CID2UnicodeMap::CPDF_CID2UnicodeMap() { + m_EmbeddedCount = 0; +} + +CPDF_CID2UnicodeMap::~CPDF_CID2UnicodeMap() {} + +bool CPDF_CID2UnicodeMap::IsLoaded() { + return m_EmbeddedCount != 0; +} + +wchar_t CPDF_CID2UnicodeMap::UnicodeFromCID(uint16_t CID) { + if (m_Charset == CIDSET_UNICODE) { + return CID; + } + if (CID < m_EmbeddedCount) { + return m_pEmbeddedMap[CID]; + } + return 0; +} + +void CPDF_CID2UnicodeMap::Load(CPDF_CMapManager* pMgr, + CIDSet charset, + bool bPromptCJK) { + m_Charset = charset; + + CPDF_FontGlobals* pFontGlobals = + CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); + std::tie(m_EmbeddedCount, m_pEmbeddedMap) = + pFontGlobals->GetEmbeddedToUnicode(charset); +} diff --git a/core/fpdfapi/font/cpdf_cid2unicodemap.h b/core/fpdfapi/font/cpdf_cid2unicodemap.h new file mode 100644 index 0000000000000000000000000000000000000000..2c3fe5b7aac8a4aeeaf55f2c9407171c948827fc --- /dev/null +++ b/core/fpdfapi/font/cpdf_cid2unicodemap.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_ +#define CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_ + +#include "core/fpdfapi/font/cpdf_cidfont.h" + +class CPDF_CMapManager; + +class CPDF_CID2UnicodeMap { + public: + CPDF_CID2UnicodeMap(); + ~CPDF_CID2UnicodeMap(); + + bool IsLoaded(); + void Load(CPDF_CMapManager* pMgr, CIDSet charset, bool bPromptCJK); + wchar_t UnicodeFromCID(uint16_t CID); + + private: + CIDSet m_Charset; + const uint16_t* m_pEmbeddedMap; + uint32_t m_EmbeddedCount; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_ diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp index 6d01538f54486a45fadd0530bf42982af2041df7..21f8addf8ff464014c7fcdbdeab8c1d981d4c5be 100644 --- a/core/fpdfapi/font/cpdf_cidfont.cpp +++ b/core/fpdfapi/font/cpdf_cidfont.cpp @@ -7,19 +7,23 @@ #include "core/fpdfapi/font/cpdf_cidfont.h" #include +#include #include #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cfx_cttgsubtable.h" +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "core/fpdfapi/font/cpdf_cmapparser.h" #include "core/fpdfapi/font/cpdf_fontencoding.h" -#include "core/fpdfapi/font/font_int.h" -#include "core/fpdfapi/font/ttgsubtable.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "third_party/base/numerics/safe_math.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" namespace { @@ -113,11 +117,15 @@ const struct CIDTransform { {8818, 0, 129, 127, 0, 19, 114}, {8819, 0, 129, 127, 0, 218, 108}, }; +// Boundary values to avoid integer overflow when multiplied by 1000. +const long kMinCBox = -2147483; +const long kMaxCBox = 2147483; + CPDF_FontGlobals* GetFontGlobals() { return CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); } -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) { switch (charset) { @@ -132,41 +140,47 @@ bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) { } } -FX_WCHAR EmbeddedUnicodeFromCharcode(const FXCMAP_CMap* pEmbedMap, - CIDSet charset, - uint32_t charcode) { +wchar_t EmbeddedUnicodeFromCharcode(const FXCMAP_CMap* pEmbedMap, + CIDSet charset, + uint32_t charcode) { if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset)) return 0; uint16_t cid = FPDFAPI_CIDFromCharCode(pEmbedMap, charcode); - const auto& codes = GetFontGlobals()->m_EmbeddedToUnicodes[charset]; - if (codes.m_pMap && cid && cid < codes.m_Count) - return codes.m_pMap[cid]; + if (!cid) + return 0; + + const uint16_t* map; + uint32_t count; + std::tie(count, map) = GetFontGlobals()->GetEmbeddedToUnicode(charset); + if (map && cid < count) + return map[cid]; return 0; } uint32_t EmbeddedCharcodeFromUnicode(const FXCMAP_CMap* pEmbedMap, CIDSet charset, - FX_WCHAR unicode) { + wchar_t unicode) { if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset)) return 0; - const auto& codes = GetFontGlobals()->m_EmbeddedToUnicodes[charset]; - const uint16_t* pCodes = codes.m_pMap; - if (!pCodes) + const uint16_t* map; + uint32_t count; + std::tie(count, map) = GetFontGlobals()->GetEmbeddedToUnicode(charset); + if (!map) return 0; - for (uint32_t i = 0; i < codes.m_Count; ++i) { - if (pCodes[i] == unicode) { - uint32_t CharCode = FPDFAPI_CharCodeFromCID(pEmbedMap, i); - if (CharCode) - return CharCode; + for (uint32_t i = 0; i < count; ++i) { + if (map[i] == unicode) { + uint32_t charCode = FPDFAPI_CharCodeFromCID(pEmbedMap, i); + if (charCode) + return charCode; } } return 0; } -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ void FT_UseCIDCharmap(FXFT_Face face, int coding) { int encoding; @@ -231,19 +245,19 @@ bool CPDF_CIDFont::IsVertWriting() const { return m_pCMap && m_pCMap->IsVertWriting(); } -CFX_WideString CPDF_CIDFont::UnicodeFromCharCode(uint32_t charcode) const { - CFX_WideString str = CPDF_Font::UnicodeFromCharCode(charcode); +WideString CPDF_CIDFont::UnicodeFromCharCode(uint32_t charcode) const { + WideString str = CPDF_Font::UnicodeFromCharCode(charcode); if (!str.IsEmpty()) return str; - FX_WCHAR ret = GetUnicodeFromCharCode(charcode); - return ret ? ret : CFX_WideString(); + wchar_t ret = GetUnicodeFromCharCode(charcode); + return ret ? ret : WideString(); } -FX_WCHAR CPDF_CIDFont::GetUnicodeFromCharCode(uint32_t charcode) const { - switch (m_pCMap->m_Coding) { +wchar_t CPDF_CIDFont::GetUnicodeFromCharCode(uint32_t charcode) const { + switch (m_pCMap->GetCoding()) { case CIDCODING_UCS2: case CIDCODING_UTF16: - return static_cast(charcode); + return static_cast(charcode); case CIDCODING_CID: if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) return 0; @@ -252,30 +266,30 @@ FX_WCHAR CPDF_CIDFont::GetUnicodeFromCharCode(uint32_t charcode) const { if (m_pCID2UnicodeMap && m_pCID2UnicodeMap->IsLoaded() && m_pCMap->IsLoaded()) return m_pCID2UnicodeMap->UnicodeFromCID(CIDFromCharCode(charcode)); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - FX_WCHAR unicode; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + wchar_t unicode; int charsize = 1; if (charcode > 255) { charcode = (charcode % 256) * 256 + (charcode / 256); charsize = 2; } - int ret = FXSYS_MultiByteToWideChar( - g_CharsetCPs[m_pCMap->m_Coding], 0, - reinterpret_cast(&charcode), charsize, &unicode, 1); + int ret = FXSYS_MultiByteToWideChar(g_CharsetCPs[m_pCMap->GetCoding()], 0, + reinterpret_cast(&charcode), + charsize, &unicode, 1); return ret == 1 ? unicode : 0; #else - if (!m_pCMap->m_pEmbedMap) + if (!m_pCMap->GetEmbedMap()) return 0; - return EmbeddedUnicodeFromCharcode(m_pCMap->m_pEmbedMap, m_pCMap->m_Charset, - charcode); + return EmbeddedUnicodeFromCharcode(m_pCMap->GetEmbedMap(), + m_pCMap->GetCharset(), charcode); #endif } -uint32_t CPDF_CIDFont::CharCodeFromUnicode(FX_WCHAR unicode) const { +uint32_t CPDF_CIDFont::CharCodeFromUnicode(wchar_t unicode) const { uint32_t charcode = CPDF_Font::CharCodeFromUnicode(unicode); if (charcode) return charcode; - switch (m_pCMap->m_Coding) { + switch (m_pCMap->GetCoding()) { case CIDCODING_UNKNOWN: return 0; case CIDCODING_UCS2: @@ -286,7 +300,7 @@ uint32_t CPDF_CIDFont::CharCodeFromUnicode(FX_WCHAR unicode) const { return 0; uint32_t CID = 0; while (CID < 65536) { - FX_WCHAR this_unicode = + wchar_t this_unicode = m_pCID2UnicodeMap->UnicodeFromCID(static_cast(CID)); if (this_unicode == unicode) return CID; @@ -298,21 +312,21 @@ uint32_t CPDF_CIDFont::CharCodeFromUnicode(FX_WCHAR unicode) const { if (unicode < 0x80) return static_cast(unicode); - if (m_pCMap->m_Coding == CIDCODING_CID) + if (m_pCMap->GetCoding() == CIDCODING_CID) return 0; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ uint8_t buffer[32]; int ret = FXSYS_WideCharToMultiByte( - g_CharsetCPs[m_pCMap->m_Coding], 0, &unicode, 1, + g_CharsetCPs[m_pCMap->GetCoding()], 0, &unicode, 1, reinterpret_cast(buffer), 4, nullptr, nullptr); if (ret == 1) return buffer[0]; if (ret == 2) return buffer[0] * 256 + buffer[1]; #else - if (m_pCMap->m_pEmbedMap) { - return EmbeddedCharcodeFromUnicode(m_pCMap->m_pEmbedMap, m_pCMap->m_Charset, - unicode); + if (m_pCMap->GetEmbedMap()) { + return EmbeddedCharcodeFromUnicode(m_pCMap->GetEmbedMap(), + m_pCMap->GetCharset(), unicode); } #endif return 0; @@ -348,43 +362,43 @@ bool CPDF_CIDFont::Load() { if (!pEncoding) return false; - CFX_ByteString subtype = pCIDFontDict->GetStringFor("Subtype"); + ByteString subtype = pCIDFontDict->GetStringFor("Subtype"); m_bType1 = (subtype == "CIDFontType0"); - CPDF_CMapManager& manager = GetFontGlobals()->m_CMapManager; + CPDF_CMapManager* manager = GetFontGlobals()->GetCMapManager(); if (pEncoding->IsName()) { - CFX_ByteString cmap = pEncoding->GetString(); + ByteString cmap = pEncoding->GetString(); bool bPromptCJK = m_pFontFile && m_bType1; - m_pCMap = manager.GetPredefinedCMap(cmap, bPromptCJK); + m_pCMap = manager->GetPredefinedCMap(cmap, bPromptCJK); if (!m_pCMap) return false; } else if (CPDF_Stream* pStream = pEncoding->AsStream()) { - m_pCMap = pdfium::MakeUnique(); - CPDF_StreamAcc acc; - acc.LoadAllData(pStream, false); - m_pCMap->LoadEmbedded(acc.GetData(), acc.GetSize()); + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllDataFiltered(); + m_pCMap = pdfium::MakeRetain(); + m_pCMap->LoadEmbedded(pAcc->GetData(), pAcc->GetSize()); } else { return false; } - m_Charset = m_pCMap->m_Charset; + m_Charset = m_pCMap->GetCharset(); if (m_Charset == CIDSET_UNKNOWN) { CPDF_Dictionary* pCIDInfo = pCIDFontDict->GetDictFor("CIDSystemInfo"); if (pCIDInfo) { - m_Charset = - CharsetFromOrdering(pCIDInfo->GetStringFor("Ordering").AsStringC()); + m_Charset = CPDF_CMapParser::CharsetFromOrdering( + pCIDInfo->GetStringFor("Ordering").AsStringView()); } } if (m_Charset != CIDSET_UNKNOWN) { - bool bPromptCJK = !m_pFontFile && (m_pCMap->m_Coding == CIDCODING_CID || + bool bPromptCJK = !m_pFontFile && (m_pCMap->GetCoding() == CIDCODING_CID || pCIDFontDict->KeyExist("W")); - m_pCID2UnicodeMap = manager.GetCID2UnicodeMap(m_Charset, bPromptCJK); + m_pCID2UnicodeMap = manager->GetCID2UnicodeMap(m_Charset, bPromptCJK); } if (m_Font.GetFace()) { if (m_bType1) FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE); else - FT_UseCIDCharmap(m_Font.GetFace(), m_pCMap->m_Coding); + FT_UseCIDCharmap(m_Font.GetFace(), m_pCMap->GetCoding()); } m_DefaultWidth = pCIDFontDict->GetIntegerFor("DW", 1000); CPDF_Array* pWidthArray = pCIDFontDict->GetArrayFor("W"); @@ -393,14 +407,14 @@ bool CPDF_CIDFont::Load() { if (!IsEmbedded()) LoadSubstFont(); - if (m_pFontFile || (GetSubstFont()->m_SubstFlags & FXFONT_SUBST_EXACT)) { + if (m_pFontFile) { CPDF_Object* pmap = pCIDFontDict->GetDirectObjectFor("CIDToGIDMap"); if (pmap) { if (CPDF_Stream* pStream = pmap->AsStream()) { - m_pStreamAcc = pdfium::MakeUnique(); - m_pStreamAcc->LoadAllData(pStream, false); + m_pStreamAcc = pdfium::MakeRetain(pStream); + m_pStreamAcc->LoadAllDataFiltered(); } else if (pmap->GetString() == "Identity") { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (m_pFontFile) m_bCIDIsGID = true; #else @@ -440,11 +454,15 @@ FX_RECT CPDF_CIDFont::GetCharBBox(uint32_t charcode) { int err = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if (!err) { - FXFT_BBox cbox; FXFT_Glyph glyph; err = FXFT_Get_Glyph(((FXFT_Face)face)->glyph, &glyph); if (!err) { + FXFT_BBox cbox; FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); + cbox.xMin = pdfium::clamp(cbox.xMin, kMinCBox, kMaxCBox); + cbox.xMax = pdfium::clamp(cbox.xMax, kMinCBox, kMaxCBox); + cbox.yMin = pdfium::clamp(cbox.yMin, kMinCBox, kMaxCBox); + cbox.yMax = pdfium::clamp(cbox.yMax, kMinCBox, kMaxCBox); int pixel_size_x = ((FXFT_Face)face)->size->metrics.x_ppem; int pixel_size_y = ((FXFT_Face)face)->size->metrics.y_ppem; if (pixel_size_x == 0 || pixel_size_y == 0) { @@ -487,9 +505,7 @@ FX_RECT CPDF_CIDFont::GetCharBBox(uint32_t charcode) { CIDTransformToFloat(pTransform[3]), CIDTransformToFloat(pTransform[4]) * 1000, CIDTransformToFloat(pTransform[5]) * 1000); - CFX_FloatRect rect_f(rect); - matrix.TransformRect(rect_f); - rect = rect_f.GetOuterRect(); + rect = matrix.TransformRect(CFX_FloatRect(rect)).GetOuterRect(); } } if (charcode < 256) @@ -603,19 +619,19 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { if (!m_pFontFile && !m_pStreamAcc) { uint16_t cid = CIDFromCharCode(charcode); - FX_WCHAR unicode = 0; + wchar_t unicode = 0; if (m_bCIDIsGID) { -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ return cid; #else - if (m_Flags & FXFONT_SYMBOLIC) + if (FontStyleIsSymbolic(m_Flags)) return cid; - CFX_WideString uni_str = UnicodeFromCharCode(charcode); + WideString uni_str = UnicodeFromCharCode(charcode); if (uni_str.IsEmpty()) return cid; - unicode = uni_str.GetAt(0); + unicode = uni_str[0]; #endif } else { if (cid && m_pCID2UnicodeMap && m_pCID2UnicodeMap->IsLoaded()) @@ -623,9 +639,9 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { if (unicode == 0) unicode = GetUnicodeFromCharCode(charcode); if (unicode == 0) { - CFX_WideString unicode_str = UnicodeFromCharCode(charcode); + WideString unicode_str = UnicodeFromCharCode(charcode); if (!unicode_str.IsEmpty()) - unicode = unicode_str.GetAt(0); + unicode = unicode_str[0]; } } FXFT_Face face = m_Font.GetFace(); @@ -641,8 +657,8 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { iBaseEncoding = PDFFONT_ENCODING_WINANSI; else if (bMacRoman) iBaseEncoding = PDFFONT_ENCODING_MACROMAN; - const FX_CHAR* name = GetAdobeCharName( - iBaseEncoding, std::vector(), charcode); + const char* name = + GetAdobeCharName(iBaseEncoding, std::vector(), charcode); if (!name) return charcode ? static_cast(charcode) : -1; @@ -670,7 +686,7 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { if (m_Charset == CIDSET_JAPAN1) { if (unicode == '\\') { unicode = '/'; -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ } else if (unicode == 0xa5) { unicode = 0x5c; #endif @@ -685,16 +701,16 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { for (i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) { uint32_t ret = FT_CharCodeFromUnicode( FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i]), - static_cast(charcode)); + static_cast(charcode)); if (ret == 0) continue; FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[i]); - unicode = static_cast(ret); + unicode = static_cast(ret); break; } if (i == FXFT_Get_Face_CharmapCount(face) && i) { FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]); - unicode = static_cast(charcode); + unicode = static_cast(charcode); } } if (FXFT_Get_Face_Charmap(face)) { @@ -711,20 +727,19 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { if (!m_pStreamAcc) { if (m_bType1) return cid; - - if (m_pFontFile && !m_pCMap->m_pMapping) + if (m_pFontFile && m_pCMap->IsDirectCharcodeToCIDTableIsEmpty()) return cid; - if (m_pCMap->m_Coding == CIDCODING_UNKNOWN || + if (m_pCMap->GetCoding() == CIDCODING_UNKNOWN || !FXFT_Get_Face_Charmap(m_Font.GetFace())) { return cid; } if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmap(m_Font.GetFace())) == FXFT_ENCODING_UNICODE) { - CFX_WideString unicode_str = UnicodeFromCharCode(charcode); + WideString unicode_str = UnicodeFromCharCode(charcode); if (unicode_str.IsEmpty()) return -1; - charcode = unicode_str.GetAt(0); + charcode = unicode_str[0]; } return GetGlyphIndex(charcode, pVertGlyph); } @@ -736,7 +751,7 @@ int CPDF_CIDFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { return pdata[0] * 256 + pdata[1]; } -uint32_t CPDF_CIDFont::GetNextChar(const FX_CHAR* pString, +uint32_t CPDF_CIDFont::GetNextChar(const char* pString, int nStrLen, int& offset) const { return m_pCMap->GetNextChar(pString, nStrLen, offset); @@ -746,18 +761,18 @@ int CPDF_CIDFont::GetCharSize(uint32_t charcode) const { return m_pCMap->GetCharSize(charcode); } -int CPDF_CIDFont::CountChar(const FX_CHAR* pString, int size) const { +int CPDF_CIDFont::CountChar(const char* pString, int size) const { return m_pCMap->CountChar(pString, size); } -int CPDF_CIDFont::AppendChar(FX_CHAR* str, uint32_t charcode) const { +int CPDF_CIDFont::AppendChar(char* str, uint32_t charcode) const { return m_pCMap->AppendChar(str, charcode); } bool CPDF_CIDFont::IsUnicodeCompatible() const { if (m_pCID2UnicodeMap && m_pCID2UnicodeMap->IsLoaded() && m_pCMap->IsLoaded()) return true; - return m_pCMap->m_Coding != CIDCODING_UNKNOWN; + return m_pCMap->GetCoding() != CIDCODING_UNKNOWN; } void CPDF_CIDFont::LoadSubstFont() { @@ -773,8 +788,8 @@ void CPDF_CIDFont::LoadMetricsArray(CPDF_Array* pArray, int nElements) { int width_status = 0; int iCurElement = 0; - int first_code = 0; - int last_code = 0; + uint32_t first_code = 0; + uint32_t last_code = 0; for (size_t i = 0; i < pArray->GetCount(); i++) { CPDF_Object* pObj = pArray->GetDirectObjectAt(i); if (!pObj) @@ -783,6 +798,11 @@ void CPDF_CIDFont::LoadMetricsArray(CPDF_Array* pArray, if (CPDF_Array* pObjArray = pObj->AsArray()) { if (width_status != 1) return; + if (first_code > + std::numeric_limits::max() - pObjArray->GetCount()) { + width_status = 0; + continue; + } for (size_t j = 0; j < pObjArray->GetCount(); j += nElements) { result->push_back(first_code); @@ -815,7 +835,7 @@ void CPDF_CIDFont::LoadMetricsArray(CPDF_Array* pArray, } // static -FX_FLOAT CPDF_CIDFont::CIDTransformToFloat(uint8_t ch) { +float CPDF_CIDFont::CIDTransformToFloat(uint8_t ch) { return (ch < 128 ? ch : ch - 255) * (1.0f / 127); } @@ -827,9 +847,10 @@ void CPDF_CIDFont::LoadGB2312() { m_Charset = CIDSET_GB1; m_bType1 = false; - CPDF_CMapManager& manager = GetFontGlobals()->m_CMapManager; - m_pCMap = manager.GetPredefinedCMap("GBK-EUC-H", false); - m_pCID2UnicodeMap = manager.GetCID2UnicodeMap(m_Charset, false); + + CPDF_CMapManager* manager = GetFontGlobals()->GetCMapManager(); + m_pCMap = manager->GetPredefinedCMap("GBK-EUC-H", false); + m_pCID2UnicodeMap = manager->GetCID2UnicodeMap(m_Charset, false); if (!IsEmbedded()) LoadSubstFont(); diff --git a/core/fpdfapi/font/cpdf_cidfont.h b/core/fpdfapi/font/cpdf_cidfont.h index 79ec7cbb350c299c04dbc82a27e6fab099436d01..f6ff83d8fa01d16fcc0aa650157b08389c4587a9 100644 --- a/core/fpdfapi/font/cpdf_cidfont.h +++ b/core/fpdfapi/font/cpdf_cidfont.h @@ -11,11 +11,12 @@ #include #include "core/fpdfapi/font/cpdf_font.h" -#include "core/fxcrt/cfx_maybe_owned.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" -enum CIDSet { +enum CIDSet : uint8_t { CIDSET_UNKNOWN, CIDSET_GB1, CIDSET_CNS1, @@ -36,7 +37,7 @@ class CPDF_CIDFont : public CPDF_Font { CPDF_CIDFont(); ~CPDF_CIDFont() override; - static FX_FLOAT CIDTransformToFloat(uint8_t ch); + static float CIDTransformToFloat(uint8_t ch); // CPDF_Font: bool IsCIDFont() const override; @@ -45,16 +46,16 @@ class CPDF_CIDFont : public CPDF_Font { int GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) override; int GetCharWidthF(uint32_t charcode) override; FX_RECT GetCharBBox(uint32_t charcode) override; - uint32_t GetNextChar(const FX_CHAR* pString, + uint32_t GetNextChar(const char* pString, int nStrLen, int& offset) const override; - int CountChar(const FX_CHAR* pString, int size) const override; - int AppendChar(FX_CHAR* str, uint32_t charcode) const override; + int CountChar(const char* pString, int size) const override; + int AppendChar(char* str, uint32_t charcode) const override; bool IsVertWriting() const override; bool IsUnicodeCompatible() const override; bool Load() override; - CFX_WideString UnicodeFromCharCode(uint32_t charcode) const override; - uint32_t CharCodeFromUnicode(FX_WCHAR Unicode) const override; + WideString UnicodeFromCharCode(uint32_t charcode) const override; + uint32_t CharCodeFromUnicode(wchar_t Unicode) const override; uint16_t CIDFromCharCode(uint32_t charcode) const; const uint8_t* GetCIDTransform(uint16_t CID) const; @@ -70,15 +71,15 @@ class CPDF_CIDFont : public CPDF_Font { std::vector* result, int nElements); void LoadSubstFont(); - FX_WCHAR GetUnicodeFromCharCode(uint32_t charcode) const; + wchar_t GetUnicodeFromCharCode(uint32_t charcode) const; - CFX_MaybeOwned m_pCMap; - CPDF_CID2UnicodeMap* m_pCID2UnicodeMap; + RetainPtr m_pCMap; + UnownedPtr m_pCID2UnicodeMap; CIDSet m_Charset; bool m_bType1; bool m_bCIDIsGID; uint16_t m_DefaultWidth; - std::unique_ptr m_pStreamAcc; + RetainPtr m_pStreamAcc; bool m_bAnsiWidthsFixed; FX_RECT m_CharBBox[256]; std::vector m_WidthList; diff --git a/core/fpdfapi/font/cpdf_cmap.cpp b/core/fpdfapi/font/cpdf_cmap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a654fcced3733963df840999f84fb962df518df5 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmap.cpp @@ -0,0 +1,480 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/font/cpdf_cmap.h" + +#include +#include +#include + +#include "core/fpdfapi/cmaps/cmap_int.h" +#include "core/fpdfapi/font/cpdf_cmapmanager.h" +#include "core/fpdfapi/font/cpdf_cmapparser.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" + +namespace { + +struct ByteRange { + uint8_t m_First; + uint8_t m_Last; // Inclusive. +}; + +struct PredefinedCMap { + const char* m_pName; + CIDSet m_Charset; + CIDCoding m_Coding; + CPDF_CMap::CodingScheme m_CodingScheme; + uint8_t m_LeadingSegCount; + ByteRange m_LeadingSegs[2]; +}; + +const PredefinedCMap g_PredefinedCMaps[] = { + {"GB-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"GBpc-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfc}}}, + {"GBK-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"GBKp-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"GBK2K-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"GBK2K", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"UniGB-UCS2", CIDSET_GB1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniGB-UTF16", CIDSET_GB1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, + {"B5pc", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfc}}}, + {"HKscs-B5", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x88, 0xfe}}}, + {"ETen-B5", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"ETenms-B5", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"UniCNS-UCS2", CIDSET_CNS1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniCNS-UTF16", CIDSET_CNS1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, + {"83pv-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"90ms-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"90msp-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"90pv-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"Add-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"EUC", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x8e, 0x8e}, {0xa1, 0xfe}}}, + {"H", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {{0x21, 0x7e}}}, + {"V", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {{0x21, 0x7e}}}, + {"Ext-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"UniJIS-UCS2", CIDSET_JAPAN1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniJIS-UCS2-HW", + CIDSET_JAPAN1, + CIDCODING_UCS2, + CPDF_CMap::TwoBytes, + 0, + {}}, + {"UniJIS-UTF16", + CIDSET_JAPAN1, + CIDCODING_UTF16, + CPDF_CMap::TwoBytes, + 0, + {}}, + {"KSC-EUC", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"KSCms-UHC", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"KSCms-UHC-HW", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"KSCpc-EUC", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfd}}}, + {"UniKS-UCS2", CIDSET_KOREA1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniKS-UTF16", CIDSET_KOREA1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, +}; + +int CheckFourByteCodeRange(uint8_t* codes, + size_t size, + const std::vector& ranges) { + for (size_t i = ranges.size(); i > 0; i--) { + size_t seg = i - 1; + if (ranges[seg].m_CharSize < size) + continue; + size_t iChar = 0; + while (iChar < size) { + if (codes[iChar] < ranges[seg].m_Lower[iChar] || + codes[iChar] > ranges[seg].m_Upper[iChar]) { + break; + } + ++iChar; + } + if (iChar == ranges[seg].m_CharSize) + return 2; + if (iChar) + return (size == ranges[seg].m_CharSize) ? 2 : 1; + } + return 0; +} + +size_t GetFourByteCharSizeImpl( + uint32_t charcode, + const std::vector& ranges) { + if (ranges.empty()) + return 1; + + uint8_t codes[4]; + codes[0] = codes[1] = 0x00; + codes[2] = static_cast(charcode >> 8 & 0xFF); + codes[3] = static_cast(charcode); + for (size_t offset = 0; offset < 4; offset++) { + size_t size = 4 - offset; + for (size_t j = 0; j < ranges.size(); j++) { + size_t iSeg = (ranges.size() - 1) - j; + if (ranges[iSeg].m_CharSize < size) + continue; + size_t iChar = 0; + while (iChar < size) { + if (codes[offset + iChar] < ranges[iSeg].m_Lower[iChar] || + codes[offset + iChar] > ranges[iSeg].m_Upper[iChar]) { + break; + } + ++iChar; + } + if (iChar == ranges[iSeg].m_CharSize) + return size; + } + } + return 1; +} + +} // namespace + +CPDF_CMap::CPDF_CMap() + : m_bLoaded(false), + m_bVertical(false), + m_Charset(CIDSET_UNKNOWN), + m_CodingScheme(TwoBytes), + m_Coding(CIDCODING_UNKNOWN), + m_pEmbedMap(nullptr) {} + +CPDF_CMap::~CPDF_CMap() {} + +void CPDF_CMap::LoadPredefined(CPDF_CMapManager* pMgr, + const ByteString& bsName, + bool bPromptCJK) { + m_PredefinedCMap = bsName; + if (m_PredefinedCMap == "Identity-H" || m_PredefinedCMap == "Identity-V") { + m_Coding = CIDCODING_CID; + m_bVertical = bsName.Last() == 'V'; + m_bLoaded = true; + return; + } + ByteString cmapid = m_PredefinedCMap; + m_bVertical = cmapid.Last() == 'V'; + if (cmapid.GetLength() > 2) { + cmapid = cmapid.Left(cmapid.GetLength() - 2); + } + const PredefinedCMap* map = nullptr; + for (size_t i = 0; i < FX_ArraySize(g_PredefinedCMaps); ++i) { + if (cmapid == ByteStringView(g_PredefinedCMaps[i].m_pName)) { + map = &g_PredefinedCMaps[i]; + break; + } + } + if (!map) + return; + + m_Charset = map->m_Charset; + m_Coding = map->m_Coding; + m_CodingScheme = map->m_CodingScheme; + if (m_CodingScheme == MixedTwoBytes) { + m_MixedTwoByteLeadingBytes = std::vector(256); + for (uint32_t i = 0; i < map->m_LeadingSegCount; ++i) { + const ByteRange& seg = map->m_LeadingSegs[i]; + for (int b = seg.m_First; b <= seg.m_Last; ++b) + m_MixedTwoByteLeadingBytes[b] = true; + } + } + m_pEmbedMap = FPDFAPI_FindEmbeddedCMap(bsName, m_Charset, m_Coding); + if (!m_pEmbedMap) + return; + + m_bLoaded = true; +} + +void CPDF_CMap::LoadEmbedded(const uint8_t* pData, uint32_t size) { + m_DirectCharcodeToCIDTable = std::vector(65536); + CPDF_CMapParser parser(this); + CPDF_SimpleParser syntax(pData, size); + while (1) { + ByteStringView word = syntax.GetWord(); + if (word.IsEmpty()) { + break; + } + parser.ParseWord(word); + } + if (m_CodingScheme == MixedFourBytes && parser.HasAdditionalMappings()) { + m_AdditionalCharcodeToCIDMappings = parser.TakeAdditionalMappings(); + std::sort( + m_AdditionalCharcodeToCIDMappings.begin(), + m_AdditionalCharcodeToCIDMappings.end(), + [](const CPDF_CMap::CIDRange& arg1, const CPDF_CMap::CIDRange& arg2) { + return arg1.m_EndCode < arg2.m_EndCode; + }); + } +} + +uint16_t CPDF_CMap::CIDFromCharCode(uint32_t charcode) const { + if (m_Coding == CIDCODING_CID) + return static_cast(charcode); + + if (m_pEmbedMap) + return FPDFAPI_CIDFromCharCode(m_pEmbedMap, charcode); + + if (m_DirectCharcodeToCIDTable.empty()) + return static_cast(charcode); + + if (charcode < 0x10000) + return m_DirectCharcodeToCIDTable[charcode]; + + auto it = std::lower_bound(m_AdditionalCharcodeToCIDMappings.begin(), + m_AdditionalCharcodeToCIDMappings.end(), charcode, + [](const CPDF_CMap::CIDRange& arg, uint32_t val) { + return arg.m_EndCode < val; + }); + if (it == m_AdditionalCharcodeToCIDMappings.end() || + it->m_StartCode > charcode) { + return 0; + } + return it->m_StartCID + charcode - it->m_StartCode; +} + +uint32_t CPDF_CMap::GetNextChar(const char* pString, + int nStrLen, + int& offset) const { + auto* pBytes = reinterpret_cast(pString); + switch (m_CodingScheme) { + case OneByte: { + return pBytes[offset++]; + } + case TwoBytes: { + uint8_t byte1 = pBytes[offset++]; + return 256 * byte1 + pBytes[offset++]; + } + case MixedTwoBytes: { + uint8_t byte1 = pBytes[offset++]; + if (!m_MixedTwoByteLeadingBytes[byte1]) + return byte1; + return 256 * byte1 + pBytes[offset++]; + } + case MixedFourBytes: { + uint8_t codes[4]; + int char_size = 1; + codes[0] = pBytes[offset++]; + while (1) { + int ret = CheckFourByteCodeRange(codes, char_size, + m_MixedFourByteLeadingRanges); + if (ret == 0) + return 0; + if (ret == 2) { + uint32_t charcode = 0; + for (int i = 0; i < char_size; i++) + charcode = (charcode << 8) + codes[i]; + return charcode; + } + if (char_size == 4 || offset == nStrLen) + return 0; + codes[char_size++] = pBytes[offset++]; + } + break; + } + } + return 0; +} + +int CPDF_CMap::GetCharSize(uint32_t charcode) const { + switch (m_CodingScheme) { + case OneByte: + return 1; + case TwoBytes: + return 2; + case MixedTwoBytes: + if (charcode < 0x100) + return 1; + return 2; + case MixedFourBytes: + if (charcode < 0x100) + return 1; + if (charcode < 0x10000) + return 2; + if (charcode < 0x1000000) + return 3; + return 4; + } + return 1; +} + +int CPDF_CMap::CountChar(const char* pString, int size) const { + switch (m_CodingScheme) { + case OneByte: + return size; + case TwoBytes: + return (size + 1) / 2; + case MixedTwoBytes: { + int count = 0; + for (int i = 0; i < size; i++) { + count++; + if (m_MixedTwoByteLeadingBytes[reinterpret_cast( + pString)[i]]) { + i++; + } + } + return count; + } + case MixedFourBytes: { + int count = 0, offset = 0; + while (offset < size) { + GetNextChar(pString, size, offset); + count++; + } + return count; + } + } + return size; +} + +int CPDF_CMap::AppendChar(char* str, uint32_t charcode) const { + switch (m_CodingScheme) { + case OneByte: + str[0] = static_cast(charcode); + return 1; + case TwoBytes: + str[0] = static_cast(charcode / 256); + str[1] = static_cast(charcode % 256); + return 2; + case MixedTwoBytes: + if (charcode < 0x100 && !m_MixedTwoByteLeadingBytes[charcode]) { + str[0] = static_cast(charcode); + return 1; + } + str[0] = static_cast(charcode >> 8); + str[1] = static_cast(charcode); + return 2; + case MixedFourBytes: + if (charcode < 0x100) { + int iSize = static_cast( + GetFourByteCharSizeImpl(charcode, m_MixedFourByteLeadingRanges)); + if (iSize == 0) + iSize = 1; + str[iSize - 1] = static_cast(charcode); + if (iSize > 1) + memset(str, 0, iSize - 1); + return iSize; + } + if (charcode < 0x10000) { + str[0] = static_cast(charcode >> 8); + str[1] = static_cast(charcode); + return 2; + } + if (charcode < 0x1000000) { + str[0] = static_cast(charcode >> 16); + str[1] = static_cast(charcode >> 8); + str[2] = static_cast(charcode); + return 3; + } + str[0] = static_cast(charcode >> 24); + str[1] = static_cast(charcode >> 16); + str[2] = static_cast(charcode >> 8); + str[3] = static_cast(charcode); + return 4; + } + return 0; +} diff --git a/core/fpdfapi/font/cpdf_cmap.h b/core/fpdfapi/font/cpdf_cmap.h new file mode 100644 index 0000000000000000000000000000000000000000..98a77286d0dd4d57bc170b9f5eb79789926899f4 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmap.h @@ -0,0 +1,103 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CPDF_CMAP_H_ +#define CORE_FPDFAPI_FONT_CPDF_CMAP_H_ + +#include + +#include "core/fpdfapi/font/cpdf_cidfont.h" +#include "core/fxcrt/retain_ptr.h" + +class CPDF_CMapManager; +struct FXCMAP_CMap; + +enum CIDCoding : uint8_t { + CIDCODING_UNKNOWN = 0, + CIDCODING_GB, + CIDCODING_BIG5, + CIDCODING_JIS, + CIDCODING_KOREA, + CIDCODING_UCS2, + CIDCODING_CID, + CIDCODING_UTF16, +}; + +class CPDF_CMap : public Retainable { + public: + enum CodingScheme : uint8_t { + OneByte, + TwoBytes, + MixedTwoBytes, + MixedFourBytes + }; + + struct CodeRange { + size_t m_CharSize; + uint8_t m_Lower[4]; + uint8_t m_Upper[4]; + }; + + struct CIDRange { + uint32_t m_StartCode; + uint32_t m_EndCode; + uint16_t m_StartCID; + }; + + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + void LoadPredefined(CPDF_CMapManager* pMgr, + const ByteString& name, + bool bPromptCJK); + void LoadEmbedded(const uint8_t* pData, uint32_t dwSize); + + bool IsLoaded() const { return m_bLoaded; } + bool IsVertWriting() const { return m_bVertical; } + + uint16_t CIDFromCharCode(uint32_t charcode) const; + + int GetCharSize(uint32_t charcode) const; + uint32_t GetNextChar(const char* pString, int nStrLen, int& offset) const; + int CountChar(const char* pString, int size) const; + int AppendChar(char* str, uint32_t charcode) const; + + void SetVertical(bool vert) { m_bVertical = vert; } + void SetCodingScheme(CodingScheme scheme) { m_CodingScheme = scheme; } + void SetMixedFourByteLeadingRanges(std::vector range) { + m_MixedFourByteLeadingRanges = range; + } + + int GetCoding() const { return m_Coding; } + const FXCMAP_CMap* GetEmbedMap() const { return m_pEmbedMap; } + CIDSet GetCharset() const { return m_Charset; } + void SetCharset(CIDSet set) { m_Charset = set; } + + void SetDirectCharcodeToCIDTable(size_t idx, uint16_t val) { + m_DirectCharcodeToCIDTable[idx] = val; + } + bool IsDirectCharcodeToCIDTableIsEmpty() const { + return m_DirectCharcodeToCIDTable.empty(); + } + + private: + CPDF_CMap(); + ~CPDF_CMap() override; + + ByteString m_PredefinedCMap; + bool m_bLoaded; + bool m_bVertical; + CIDSet m_Charset; + CodingScheme m_CodingScheme; + int m_Coding; + std::vector m_MixedTwoByteLeadingBytes; + std::vector m_MixedFourByteLeadingRanges; + std::vector m_DirectCharcodeToCIDTable; + std::vector m_AdditionalCharcodeToCIDMappings; + const FXCMAP_CMap* m_pEmbedMap; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CMAP_H_ diff --git a/core/fpdfapi/font/cpdf_cmapmanager.cpp b/core/fpdfapi/font/cpdf_cmapmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53183af3405dcbb926aeccd7ea91a92fe42c10fa --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapmanager.cpp @@ -0,0 +1,58 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/font/cpdf_cmapmanager.h" + +#include + +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "third_party/base/stl_util.h" + +CPDF_CMapManager::CPDF_CMapManager() {} + +CPDF_CMapManager::~CPDF_CMapManager() {} + +RetainPtr CPDF_CMapManager::GetPredefinedCMap(const ByteString& name, + bool bPromptCJK) { + auto it = m_CMaps.find(name); + if (it != m_CMaps.end()) + return it->second; + + RetainPtr pCMap = LoadPredefinedCMap(name, bPromptCJK); + if (!name.IsEmpty()) + m_CMaps[name] = pCMap; + + return pCMap; +} + +RetainPtr CPDF_CMapManager::LoadPredefinedCMap( + const ByteString& name, + bool bPromptCJK) { + const char* pname = name.c_str(); + if (*pname == '/') + pname++; + + auto pCMap = pdfium::MakeRetain(); + pCMap->LoadPredefined(this, pname, bPromptCJK); + return pCMap; +} + +CPDF_CID2UnicodeMap* CPDF_CMapManager::GetCID2UnicodeMap(CIDSet charset, + bool bPromptCJK) { + if (!m_CID2UnicodeMaps[charset]) + m_CID2UnicodeMaps[charset] = LoadCID2UnicodeMap(charset, bPromptCJK); + + return m_CID2UnicodeMaps[charset].get(); +} + +std::unique_ptr CPDF_CMapManager::LoadCID2UnicodeMap( + CIDSet charset, + bool bPromptCJK) { + auto pMap = pdfium::MakeUnique(); + pMap->Load(this, charset, bPromptCJK); + return pMap; +} diff --git a/core/fpdfapi/font/cpdf_cmapmanager.h b/core/fpdfapi/font/cpdf_cmapmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..089eb3d7057d7e25b2a9a4919e5b58808a6443af --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapmanager.h @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CPDF_CMAPMANAGER_H_ +#define CORE_FPDFAPI_FONT_CPDF_CMAPMANAGER_H_ + +#include +#include + +#include "core/fpdfapi/font/cpdf_cidfont.h" +#include "core/fxcrt/bytestring.h" +#include "core/fxcrt/retain_ptr.h" + +class CPDF_CMapManager { + public: + CPDF_CMapManager(); + ~CPDF_CMapManager(); + + RetainPtr GetPredefinedCMap(const ByteString& name, + bool bPromptCJK); + CPDF_CID2UnicodeMap* GetCID2UnicodeMap(CIDSet charset, bool bPromptCJK); + + private: + RetainPtr LoadPredefinedCMap(const ByteString& name, + bool bPromptCJK); + std::unique_ptr LoadCID2UnicodeMap(CIDSet charset, + bool bPromptCJK); + + std::map> m_CMaps; + std::unique_ptr m_CID2UnicodeMaps[6]; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CMAPMANAGER_H_ diff --git a/core/fpdfapi/font/cpdf_cmapparser.cpp b/core/fpdfapi/font/cpdf_cmapparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a88448c5bd116d76dd6c86a4fd217193752758a8 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapparser.cpp @@ -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 + +#include "core/fpdfapi/font/cpdf_cmapparser.h" + +#include + +#include "core/fpdfapi/cmaps/cmap_int.h" +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/page/cpdf_pagemodule.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxge/fx_freetype.h" +#include "third_party/base/logging.h" + +namespace { + +const char* const g_CharsetNames[CIDSET_NUM_SETS] = {nullptr, "GB1", "CNS1", + "Japan1", "Korea1", "UCS"}; + +CIDSet CIDSetFromSizeT(size_t index) { + if (index >= CIDSET_NUM_SETS) { + NOTREACHED(); + return CIDSET_UNKNOWN; + } + return static_cast(index); +} + +ByteStringView CMap_GetString(const ByteStringView& word) { + if (word.GetLength() <= 2) + return ByteStringView(); + return word.Right(word.GetLength() - 2); +} + +} // namespace + +CPDF_CMapParser::CPDF_CMapParser(CPDF_CMap* pCMap) + : m_pCMap(pCMap), m_Status(0), m_CodeSeq(0) {} + +CPDF_CMapParser::~CPDF_CMapParser() {} + +void CPDF_CMapParser::ParseWord(const ByteStringView& word) { + if (word.IsEmpty()) { + return; + } + if (word == "begincidchar") { + m_Status = 1; + m_CodeSeq = 0; + } else if (word == "begincidrange") { + m_Status = 2; + m_CodeSeq = 0; + } else if (word == "endcidrange" || word == "endcidchar") { + m_Status = 0; + } else if (word == "/WMode") { + m_Status = 6; + } else if (word == "/Registry") { + m_Status = 3; + } else if (word == "/Ordering") { + m_Status = 4; + } else if (word == "/Supplement") { + m_Status = 5; + } else if (word == "begincodespacerange") { + m_Status = 7; + m_CodeSeq = 0; + } else if (word == "usecmap") { + } else if (m_Status == 1 || m_Status == 2) { + m_CodePoints[m_CodeSeq] = GetCode(word); + m_CodeSeq++; + uint32_t StartCode, EndCode; + uint16_t StartCID; + if (m_Status == 1) { + if (m_CodeSeq < 2) { + return; + } + EndCode = StartCode = m_CodePoints[0]; + StartCID = (uint16_t)m_CodePoints[1]; + } else { + if (m_CodeSeq < 3) { + return; + } + StartCode = m_CodePoints[0]; + EndCode = m_CodePoints[1]; + StartCID = (uint16_t)m_CodePoints[2]; + } + if (EndCode < 0x10000) { + for (uint32_t code = StartCode; code <= EndCode; code++) { + m_pCMap->SetDirectCharcodeToCIDTable( + code, static_cast(StartCID + code - StartCode)); + } + } else { + m_AdditionalCharcodeToCIDMappings.push_back( + {StartCode, EndCode, StartCID}); + } + m_CodeSeq = 0; + } else if (m_Status == 3) { + m_Status = 0; + } else if (m_Status == 4) { + m_pCMap->SetCharset(CharsetFromOrdering(CMap_GetString(word))); + m_Status = 0; + } else if (m_Status == 5) { + m_Status = 0; + } else if (m_Status == 6) { + m_pCMap->SetVertical(GetCode(word) != 0); + m_Status = 0; + } else if (m_Status == 7) { + if (word == "endcodespacerange") { + size_t nSegs = m_CodeRanges.size(); + if (nSegs == 1) { + m_pCMap->SetCodingScheme((m_CodeRanges[0].m_CharSize == 2) + ? CPDF_CMap::TwoBytes + : CPDF_CMap::OneByte); + } else if (nSegs > 1) { + m_pCMap->SetCodingScheme(CPDF_CMap::MixedFourBytes); + m_pCMap->SetMixedFourByteLeadingRanges(m_CodeRanges); + } + m_Status = 0; + } else { + if (word.GetLength() == 0 || word[0] != '<') { + return; + } + if (m_CodeSeq % 2) { + CPDF_CMap::CodeRange range; + if (GetCodeRange(range, m_LastWord.AsStringView(), word)) + m_CodeRanges.push_back(range); + } + m_CodeSeq++; + } + } + m_LastWord = word; +} + +uint32_t CPDF_CMapParser::GetCode(const ByteStringView& word) const { + if (word.IsEmpty()) + return 0; + + pdfium::base::CheckedNumeric num = 0; + if (word[0] == '<') { + for (size_t i = 1; i < word.GetLength() && std::isxdigit(word[i]); ++i) { + num = num * 16 + FXSYS_HexCharToInt(word[i]); + if (!num.IsValid()) + return 0; + } + return num.ValueOrDie(); + } + + for (size_t i = 0; i < word.GetLength() && std::isdigit(word[i]); ++i) { + num = num * 10 + FXSYS_DecimalCharToInt(static_cast(word[i])); + if (!num.IsValid()) + return 0; + } + return num.ValueOrDie(); +} + +bool CPDF_CMapParser::GetCodeRange(CPDF_CMap::CodeRange& range, + const ByteStringView& first, + const ByteStringView& second) const { + if (first.GetLength() == 0 || first[0] != '<') + return false; + + size_t i; + for (i = 1; i < first.GetLength(); ++i) { + if (first[i] == '>') { + break; + } + } + range.m_CharSize = (i - 1) / 2; + if (range.m_CharSize > 4) + return false; + + for (i = 0; i < range.m_CharSize; ++i) { + uint8_t digit1 = first[i * 2 + 1]; + uint8_t digit2 = first[i * 2 + 2]; + range.m_Lower[i] = + FXSYS_HexCharToInt(digit1) * 16 + FXSYS_HexCharToInt(digit2); + } + + size_t size = second.GetLength(); + for (i = 0; i < range.m_CharSize; ++i) { + uint8_t digit1 = (i * 2 + 1 < size) ? second[i * 2 + 1] : '0'; + uint8_t digit2 = (i * 2 + 2 < size) ? second[i * 2 + 2] : '0'; + range.m_Upper[i] = + FXSYS_HexCharToInt(digit1) * 16 + FXSYS_HexCharToInt(digit2); + } + return true; +} + +// static +CIDSet CPDF_CMapParser::CharsetFromOrdering(const ByteStringView& ordering) { + for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) { + if (ordering == g_CharsetNames[charset]) + return CIDSetFromSizeT(charset); + } + return CIDSET_UNKNOWN; +} diff --git a/core/fpdfapi/font/cpdf_cmapparser.h b/core/fpdfapi/font/cpdf_cmapparser.h new file mode 100644 index 0000000000000000000000000000000000000000..fc46c58f72ea495905a837ae5e152688976f5d7d --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapparser.h @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CPDF_CMAPPARSER_H_ +#define CORE_FPDFAPI_FONT_CPDF_CMAPPARSER_H_ + +#include +#include +#include + +#include "core/fpdfapi/font/cpdf_cidfont.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPDF_CMapParser { + public: + explicit CPDF_CMapParser(CPDF_CMap* pMap); + ~CPDF_CMapParser(); + + void ParseWord(const ByteStringView& str); + bool HasAdditionalMappings() const { + return !m_AdditionalCharcodeToCIDMappings.empty(); + } + std::vector TakeAdditionalMappings() { + return std::move(m_AdditionalCharcodeToCIDMappings); + } + + uint32_t GetCode(const ByteStringView& word) const; + bool GetCodeRange(CPDF_CMap::CodeRange& range, + const ByteStringView& first, + const ByteStringView& second) const; + + static CIDSet CharsetFromOrdering(const ByteStringView& ordering); + + private: + + UnownedPtr const m_pCMap; + int m_Status; + int m_CodeSeq; + uint32_t m_CodePoints[4]; + std::vector m_CodeRanges; + std::vector m_AdditionalCharcodeToCIDMappings; + ByteString m_LastWord; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CMAPPARSER_H_ diff --git a/core/fpdfapi/font/cpdf_cmapparser_unittest.cpp b/core/fpdfapi/font/cpdf_cmapparser_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a36eb79ac2e16d5dbecd0d2f33744953b8963fa --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapparser_unittest.cpp @@ -0,0 +1,73 @@ +// Copyright 2015 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. + +#include "core/fpdfapi/font/cpdf_cmapparser.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +bool uint_ranges_equal(uint8_t* a, uint8_t* b, size_t count) { + for (size_t i = 0; i < count; ++i) { + if (a[i] != b[i]) + return false; + } + return true; +} + +} // namespace + +TEST(cpdf_cmapparser, GetCode) { + CPDF_CMapParser parser(nullptr); + + EXPECT_EQ(0u, parser.GetCode("")); + EXPECT_EQ(0u, parser.GetCode("<")); + EXPECT_EQ(194u, parser.GetCode("", "")); + EXPECT_EQ(5u, range.m_CharSize); + + EXPECT_TRUE(parser.GetCodeRange(range, "<12345678>", "<87654321>")); + EXPECT_EQ(4u, range.m_CharSize); + { + uint8_t lower[4] = {18, 52, 86, 120}; + uint8_t upper[4] = {135, 101, 67, 33}; + EXPECT_TRUE(uint_ranges_equal(lower, range.m_Lower, range.m_CharSize)); + EXPECT_TRUE(uint_ranges_equal(upper, range.m_Upper, range.m_CharSize)); + } + + // Hex characters + EXPECT_TRUE(parser.GetCodeRange(range, "", "")); + EXPECT_EQ(1u, range.m_CharSize); + EXPECT_EQ(161, range.m_Lower[0]); + EXPECT_EQ(243, range.m_Upper[0]); + + // The second string should return 0's if it is shorter + EXPECT_TRUE(parser.GetCodeRange(range, "", "")); + EXPECT_EQ(1u, range.m_CharSize); + EXPECT_EQ(161, range.m_Lower[0]); + EXPECT_EQ(0, range.m_Upper[0]); +} diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp index 36d7d6aeeb4a21cd0304b373cb20a3473bd67bb5..8d35739d78fbf61560f473bb1fe39b52da155364 100644 --- a/core/fpdfapi/font/cpdf_font.cpp +++ b/core/fpdfapi/font/cpdf_font.cpp @@ -6,6 +6,7 @@ #include "core/fpdfapi/font/cpdf_font.h" +#include #include #include #include @@ -15,7 +16,6 @@ #include "core/fpdfapi/font/cpdf_truetypefont.h" #include "core/fpdfapi/font/cpdf_type1font.h" #include "core/fpdfapi/font/cpdf_type3font.h" -#include "core/fpdfapi/font/font_int.h" #include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fpdfapi/parser/cpdf_array.h" @@ -25,6 +25,7 @@ #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fxcrt/fx_memory.h" #include "core/fxge/fx_freetype.h" +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" @@ -36,7 +37,7 @@ const uint8_t kChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00}, {0xB7, 0xC2, 0xCB, 0xCE, 0x00}, {0xD0, 0xC2, 0xCB, 0xCE, 0x00}}; -void GetPredefinedEncoding(const CFX_ByteString& value, int* basemap) { +void GetPredefinedEncoding(const ByteString& value, int* basemap) { if (value == "WinAnsiEncoding") *basemap = PDFFONT_ENCODING_WINANSI; else if (value == "MacRomanEncoding") @@ -61,8 +62,11 @@ CPDF_Font::CPDF_Font() CPDF_Font::~CPDF_Font() { if (m_pFontFile) { - m_pDocument->GetPageData()->ReleaseFontFileStreamAcc( - m_pFontFile->GetStream()->AsStream()); + auto* pPageData = m_pDocument->GetPageData(); + if (pPageData) { + pPageData->MaybePurgeFontFileStreamAcc( + m_pFontFile->GetStream()->AsStream()); + } } } @@ -118,7 +122,7 @@ bool CPDF_Font::IsUnicodeCompatible() const { return false; } -int CPDF_Font::CountChar(const FX_CHAR* pString, int size) const { +int CPDF_Font::CountChar(const char* pString, int size) const { return size; } @@ -131,35 +135,35 @@ bool CPDF_Font::IsVertWriting() const { return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical(); } -int CPDF_Font::AppendChar(FX_CHAR* buf, uint32_t charcode) const { - *buf = static_cast(charcode); +int CPDF_Font::AppendChar(char* buf, uint32_t charcode) const { + *buf = static_cast(charcode); return 1; } -void CPDF_Font::AppendChar(CFX_ByteString& str, uint32_t charcode) const { +void CPDF_Font::AppendChar(ByteString* str, uint32_t charcode) const { char buf[4]; int len = AppendChar(buf, charcode); - if (len == 1) { - str += buf[0]; - } else { - str += CFX_ByteString(buf, len); - } + *str += ByteStringView(buf, len); } -CFX_WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const { +WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const { if (!m_bToUnicodeLoaded) LoadUnicodeMap(); - return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : CFX_WideString(); + return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : WideString(); } -uint32_t CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const { +uint32_t CPDF_Font::CharCodeFromUnicode(wchar_t unicode) const { if (!m_bToUnicodeLoaded) LoadUnicodeMap(); return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0; } +bool CPDF_Font::HasFontWidths() const { + return true; +} + void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) { m_Flags = pFontDesc->GetIntegerFor("Flags", FXFONT_NONSYMBOLIC); int ItalicAngle = 0; @@ -219,7 +223,7 @@ void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) { const uint8_t* pFontData = m_pFontFile->GetData(); uint32_t dwFontSize = m_pFontFile->GetSize(); if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) { - m_pDocument->GetPageData()->ReleaseFontFileStreamAcc( + m_pDocument->GetPageData()->MaybePurgeFontFileStreamAcc( m_pFontFile->GetStream()->AsStream()); m_pFontFile = nullptr; } @@ -281,7 +285,7 @@ void CPDF_Font::LoadUnicodeMap() const { m_pToUnicodeMap->Load(pStream); } -int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) { +int CPDF_Font::GetStringWidth(const char* pString, int size) { int offset = 0; int width = 0; while (offset < size) { @@ -291,9 +295,10 @@ int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) { return width; } +// static CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc, - const CFX_ByteStringC& name) { - CFX_ByteString fontname(name); + const ByteStringView& name) { + ByteString fontname(name); int font_id = PDF_GetStandardFontName(&fontname); if (font_id < 0) return nullptr; @@ -314,12 +319,12 @@ CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc, std::unique_ptr CPDF_Font::Create(CPDF_Document* pDoc, CPDF_Dictionary* pFontDict) { - CFX_ByteString type = pFontDict->GetStringFor("Subtype"); + ByteString type = pFontDict->GetStringFor("Subtype"); std::unique_ptr pFont; if (type == "TrueType") { - CFX_ByteString tag = pFontDict->GetStringFor("BaseFont").Left(4); + ByteString tag = pFontDict->GetStringFor("BaseFont").Left(4); for (size_t i = 0; i < FX_ArraySize(kChineseFontNames); ++i) { - if (tag == CFX_ByteString(kChineseFontNames[i], 4)) { + if (tag == ByteString(kChineseFontNames[i], 4)) { CPDF_Dictionary* pFontDesc = pFontDict->GetDictFor("FontDescriptor"); if (!pFontDesc || !pFontDesc->KeyExist("FontFile2")) pFont = pdfium::MakeUnique(); @@ -341,7 +346,7 @@ std::unique_ptr CPDF_Font::Create(CPDF_Document* pDoc, return pFont->Load() ? std::move(pFont) : nullptr; } -uint32_t CPDF_Font::GetNextChar(const FX_CHAR* pString, +uint32_t CPDF_Font::GetNextChar(const char* pString, int nStrLen, int& offset) const { if (offset < 0 || nStrLen < 1) { @@ -353,7 +358,7 @@ uint32_t CPDF_Font::GetNextChar(const FX_CHAR* pString, void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding, int& iBaseEncoding, - std::vector* pCharNames, + std::vector* pCharNames, bool bEmbedded, bool bTrueType) { if (!pEncoding) { @@ -370,12 +375,12 @@ void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding, iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) { return; } - if ((m_Flags & FXFONT_SYMBOLIC) && m_BaseFont == "Symbol") { + if (FontStyleIsSymbolic(m_Flags) && m_BaseFont == "Symbol") { if (!bTrueType) iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL; return; } - CFX_ByteString bsEncoding = pEncoding->GetString(); + ByteString bsEncoding = pEncoding->GetString(); if (bsEncoding.Compare("MacExpertEncoding") == 0) { bsEncoding = "WinAnsiEncoding"; } @@ -389,10 +394,9 @@ void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding, if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL && iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) { - CFX_ByteString bsEncoding = pDict->GetStringFor("BaseEncoding"); - if (bsEncoding.Compare("MacExpertEncoding") == 0 && bTrueType) { + ByteString bsEncoding = pDict->GetStringFor("BaseEncoding"); + if (bTrueType && bsEncoding.Compare("MacExpertEncoding") == 0) bsEncoding = "WinAnsiEncoding"; - } GetPredefinedEncoding(bsEncoding, &iBaseEncoding); } if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) @@ -429,19 +433,19 @@ bool CPDF_Font::IsStandardFont() const { return true; } -const FX_CHAR* CPDF_Font::GetAdobeCharName( +const char* CPDF_Font::GetAdobeCharName( int iBaseEncoding, - const std::vector& charnames, + const std::vector& charnames, int charcode) { if (charcode < 0 || charcode >= 256) { - ASSERT(false); + NOTREACHED(); return nullptr; } if (!charnames.empty() && !charnames[charcode].IsEmpty()) return charnames[charcode].c_str(); - const FX_CHAR* name = nullptr; + const char* name = nullptr; if (iBaseEncoding) name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode); return name && name[0] ? name : nullptr; @@ -458,13 +462,48 @@ uint32_t CPDF_Font::FallbackFontFromCharcode(uint32_t charcode) { } int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) { - if (fallbackFont < 0 || - fallbackFont >= pdfium::CollectionSize(m_FontFallbacks)) { + if (!pdfium::IndexInBounds(m_FontFallbacks, fallbackFont)) return -1; - } + + WideString str = UnicodeFromCharCode(charcode); + uint32_t unicode = !str.IsEmpty() ? str[0] : charcode; int glyph = - FXFT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFace(), charcode); - if (glyph == 0 || glyph == 0xffff) + FXFT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFace(), unicode); + if (glyph == 0) return -1; + return glyph; } + +CFX_Font* CPDF_Font::GetFontFallback(int position) { + if (position < 0 || static_cast(position) >= m_FontFallbacks.size()) + return nullptr; + return m_FontFallbacks[position].get(); +} + +// static +int CPDF_Font::TT2PDF(int m, FXFT_Face face) { + int upm = FXFT_Get_Face_UnitsPerEM(face); + if (upm == 0) + return m; + + return static_cast( + pdfium::clamp((m * 1000.0 + upm / 2) / upm, + static_cast(std::numeric_limits::min()), + static_cast(std::numeric_limits::max()))); +} + +// static +bool CPDF_Font::FT_UseTTCharmap(FXFT_Face face, + int platform_id, + int encoding_id) { + auto** pCharMap = FXFT_Get_Face_Charmaps(face); + for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) { + if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id && + FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) { + FXFT_Set_Charmap(face, pCharMap[i]); + return true; + } + } + return false; +} diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h index 6025a82d7a81449fcc2e619a7c1c950d20035584..0468bcb32ac5ce9dbe1f7db04a9b90f0493f21c0 100644 --- a/core/fpdfapi/font/cpdf_font.h +++ b/core/fpdfapi/font/cpdf_font.h @@ -10,8 +10,12 @@ #include #include +#include "core/fpdfapi/font/cpdf_tounicodemap.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/fx_font.h" class CFX_SubstFont; @@ -19,7 +23,6 @@ class CPDF_CIDFont; class CPDF_Dictionary; class CPDF_Document; class CPDF_Object; -class CPDF_StreamAcc; class CPDF_TrueTypeFont; class CPDF_Type1Font; class CPDF_Type3Font; @@ -30,7 +33,7 @@ class CPDF_Font { static std::unique_ptr Create(CPDF_Document* pDoc, CPDF_Dictionary* pFontDict); static CPDF_Font* GetStockFont(CPDF_Document* pDoc, - const CFX_ByteStringC& fontname); + const ByteStringView& fontname); static const uint32_t kInvalidCharCode = static_cast(-1); virtual ~CPDF_Font(); @@ -50,58 +53,66 @@ class CPDF_Font { virtual bool IsVertWriting() const; virtual bool IsUnicodeCompatible() const; - virtual uint32_t GetNextChar(const FX_CHAR* pString, + virtual uint32_t GetNextChar(const char* pString, int nStrLen, int& offset) const; - virtual int CountChar(const FX_CHAR* pString, int size) const; - virtual int AppendChar(FX_CHAR* buf, uint32_t charcode) const; + virtual int CountChar(const char* pString, int size) const; + virtual int AppendChar(char* buf, uint32_t charcode) const; virtual int GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) = 0; virtual int GlyphFromCharCodeExt(uint32_t charcode); - virtual CFX_WideString UnicodeFromCharCode(uint32_t charcode) const; - virtual uint32_t CharCodeFromUnicode(FX_WCHAR Unicode) const; + virtual WideString UnicodeFromCharCode(uint32_t charcode) const; + virtual uint32_t CharCodeFromUnicode(wchar_t Unicode) const; + virtual bool HasFontWidths() const; - const CFX_ByteString& GetBaseFont() const { return m_BaseFont; } + const ByteString& GetBaseFont() const { return m_BaseFont; } CFX_SubstFont* GetSubstFont() const { return m_Font.GetSubstFont(); } bool IsEmbedded() const { return IsType3Font() || m_pFontFile != nullptr; } CPDF_Dictionary* GetFontDict() const { return m_pFontDict; } bool IsStandardFont() const; FXFT_Face GetFace() const { return m_Font.GetFace(); } - void AppendChar(CFX_ByteString& str, uint32_t charcode) const; + void AppendChar(ByteString* str, uint32_t charcode) const; void GetFontBBox(FX_RECT& rect) const { rect = m_FontBBox; } int GetTypeAscent() const { return m_Ascent; } int GetTypeDescent() const { return m_Descent; } - int GetStringWidth(const FX_CHAR* pString, int size); + int GetStringWidth(const char* pString, int size); uint32_t FallbackFontFromCharcode(uint32_t charcode); int FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode); virtual int GetCharWidthF(uint32_t charcode) = 0; virtual FX_RECT GetCharBBox(uint32_t charcode) = 0; - CPDF_Document* m_pDocument; - CFX_Font m_Font; - std::vector> m_FontFallbacks; + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } + CFX_Font* GetFont() { return &m_Font; } + const CFX_Font* GetFont() const { return &m_Font; } + CFX_Font* GetFontFallback(int position); protected: CPDF_Font(); + static int TT2PDF(int m, FXFT_Face face); + static bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id); + virtual bool Load() = 0; void LoadUnicodeMap() const; // logically const only. void LoadPDFEncoding(CPDF_Object* pEncoding, int& iBaseEncoding, - std::vector* pCharNames, + std::vector* pCharNames, bool bEmbedded, bool bTrueType); void LoadFontDescriptor(CPDF_Dictionary* pDict); void CheckFontMetrics(); - const FX_CHAR* GetAdobeCharName(int iBaseEncoding, - const std::vector& charnames, - int charcode); + const char* GetAdobeCharName(int iBaseEncoding, + const std::vector& charnames, + int charcode); - CFX_ByteString m_BaseFont; - CPDF_StreamAcc* m_pFontFile; + UnownedPtr m_pDocument; + CFX_Font m_Font; + std::vector> m_FontFallbacks; + ByteString m_BaseFont; + RetainPtr m_pFontFile; CPDF_Dictionary* m_pFontDict; mutable std::unique_ptr m_pToUnicodeMap; mutable bool m_bToUnicodeLoaded; diff --git a/core/fpdfapi/font/cpdf_fontencoding.cpp b/core/fpdfapi/font/cpdf_fontencoding.cpp index 88b2c8d6a53dab86dae535634249ef172c943737..921d5842b8aeba2990406d1c4287740923e3c8ba 100644 --- a/core/fpdfapi/font/cpdf_fontencoding.cpp +++ b/core/fpdfapi/font/cpdf_fontencoding.cpp @@ -236,7 +236,7 @@ const uint16_t ZapfEncoding[256] = { 0x27BC, 0x27BD, 0x27BE, 0x0000, }; -const FX_CHAR* const StandardEncodingNames[224] = { +const char* const StandardEncodingNames[224] = { "space", "exclam", "quotedbl", @@ -463,7 +463,7 @@ const FX_CHAR* const StandardEncodingNames[224] = { nullptr, }; -const FX_CHAR* const AdobeWinAnsiEncodingNames[224] = { +const char* const AdobeWinAnsiEncodingNames[224] = { "space", "exclam", "quotedbl", @@ -690,7 +690,7 @@ const FX_CHAR* const AdobeWinAnsiEncodingNames[224] = { "ydieresis", }; -const FX_CHAR* const MacRomanEncodingNames[224] = { +const char* const MacRomanEncodingNames[224] = { "space", "exclam", "quotedbl", @@ -917,7 +917,7 @@ const FX_CHAR* const MacRomanEncodingNames[224] = { "caron", }; -const FX_CHAR* const MacExpertEncodingNames[224] = { +const char* const MacExpertEncodingNames[224] = { "space", "exclamsmall", "Hungarumlautsmall", @@ -1144,7 +1144,7 @@ const FX_CHAR* const MacExpertEncodingNames[224] = { nullptr, }; -const FX_CHAR* const PDFDocEncodingNames[232] = { +const char* const PDFDocEncodingNames[232] = { "breve", "caron", "circumflex", @@ -1379,7 +1379,7 @@ const FX_CHAR* const PDFDocEncodingNames[232] = { "ydieresis", }; -const FX_CHAR* const AdobeSymbolEncodingNames[224] = { +const char* const AdobeSymbolEncodingNames[224] = { "space", "exclam", "universal", @@ -1606,7 +1606,7 @@ const FX_CHAR* const AdobeSymbolEncodingNames[224] = { nullptr, }; -const FX_CHAR* const ZapfEncodingNames[224] = { +const char* const ZapfEncodingNames[224] = { "space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117", "a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19", "a20", "a21", "a22", "a23", @@ -1646,10 +1646,10 @@ uint32_t PDF_FindCode(const uint16_t* pCodes, uint16_t unicode) { } // namespace CPDF_FontEncoding::CPDF_FontEncoding() { - FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes)); + memset(m_Unicodes, 0, sizeof(m_Unicodes)); } -int CPDF_FontEncoding::CharCodeFromUnicode(FX_WCHAR unicode) const { +int CPDF_FontEncoding::CharCodeFromUnicode(wchar_t unicode) const { for (int i = 0; i < 256; i++) if (m_Unicodes[i] == unicode) { return i; @@ -1660,7 +1660,7 @@ int CPDF_FontEncoding::CharCodeFromUnicode(FX_WCHAR unicode) const { CPDF_FontEncoding::CPDF_FontEncoding(int PredefinedEncoding) { const uint16_t* pSrc = PDF_UnicodesForPredefinedCharSet(PredefinedEncoding); if (!pSrc) { - FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes)); + memset(m_Unicodes, 0, sizeof(m_Unicodes)); } else { for (int i = 0; i < 256; i++) m_Unicodes[i] = pSrc[i]; @@ -1668,12 +1668,11 @@ CPDF_FontEncoding::CPDF_FontEncoding(int PredefinedEncoding) { } bool CPDF_FontEncoding::IsIdentical(CPDF_FontEncoding* pAnother) const { - return FXSYS_memcmp(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) == - 0; + return memcmp(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) == 0; } std::unique_ptr CPDF_FontEncoding::Realize( - CFX_WeakPtr pPool) { + WeakPtr pPool) { int predefined = 0; for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS; cs++) { @@ -1717,7 +1716,7 @@ std::unique_ptr CPDF_FontEncoding::Realize( return std::move(pDict); } -uint32_t FT_CharCodeFromUnicode(int encoding, FX_WCHAR unicode) { +uint32_t FT_CharCodeFromUnicode(int encoding, wchar_t unicode) { switch (encoding) { case FXFT_ENCODING_UNICODE: return unicode; @@ -1758,18 +1757,17 @@ const uint16_t* PDF_UnicodesForPredefinedCharSet(int encoding) { return nullptr; } -FX_WCHAR PDF_UnicodeFromAdobeName(const FX_CHAR* name) { - return (FX_WCHAR)(FXFT_unicode_from_adobe_name(name) & 0x7FFFFFFF); +wchar_t PDF_UnicodeFromAdobeName(const char* name) { + return (wchar_t)(FXFT_unicode_from_adobe_name(name) & 0x7FFFFFFF); } -CFX_ByteString PDF_AdobeNameFromUnicode(FX_WCHAR unicode) { +ByteString PDF_AdobeNameFromUnicode(wchar_t unicode) { char glyph_name[64]; FXFT_adobe_name_from_unicode(glyph_name, unicode); - return CFX_ByteString(glyph_name); + return ByteString(glyph_name); } -const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding, - uint8_t charcode) { +const char* PDF_CharNameFromPredefinedCharSet(int encoding, uint8_t charcode) { if (encoding == PDFFONT_ENCODING_PDFDOC) { if (charcode < 24) return nullptr; @@ -1800,7 +1798,7 @@ const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding, return nullptr; } -FX_WCHAR FT_UnicodeFromCharCode(int encoding, uint32_t charcode) { +wchar_t FT_UnicodeFromCharCode(int encoding, uint32_t charcode) { switch (encoding) { case FXFT_ENCODING_UNICODE: return (uint16_t)charcode; diff --git a/core/fpdfapi/font/cpdf_fontencoding.h b/core/fpdfapi/font/cpdf_fontencoding.h index 6c0de909e1209d69c821642e5c2f95f44be8b9f3..040708f55481d22b6b94eb00ea6c4c1d97cba646 100644 --- a/core/fpdfapi/font/cpdf_fontencoding.h +++ b/core/fpdfapi/font/cpdf_fontencoding.h @@ -9,9 +9,9 @@ #include -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" #define PDFFONT_ENCODING_BUILTIN 0 #define PDFFONT_ENCODING_WINANSI 1 @@ -22,17 +22,15 @@ #define PDFFONT_ENCODING_ZAPFDINGBATS 6 #define PDFFONT_ENCODING_PDFDOC 7 #define PDFFONT_ENCODING_MS_SYMBOL 8 -#define PDFFONT_ENCODING_UNICODE 9 -uint32_t FT_CharCodeFromUnicode(int encoding, FX_WCHAR unicode); -FX_WCHAR FT_UnicodeFromCharCode(int encoding, uint32_t charcode); +uint32_t FT_CharCodeFromUnicode(int encoding, wchar_t unicode); +wchar_t FT_UnicodeFromCharCode(int encoding, uint32_t charcode); -FX_WCHAR PDF_UnicodeFromAdobeName(const FX_CHAR* name); -CFX_ByteString PDF_AdobeNameFromUnicode(FX_WCHAR unicode); +wchar_t PDF_UnicodeFromAdobeName(const char* name); +ByteString PDF_AdobeNameFromUnicode(wchar_t unicode); const uint16_t* PDF_UnicodesForPredefinedCharSet(int encoding); -const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding, - uint8_t charcode); +const char* PDF_CharNameFromPredefinedCharSet(int encoding, uint8_t charcode); class CPDF_Object; @@ -45,19 +43,19 @@ class CPDF_FontEncoding { bool IsIdentical(CPDF_FontEncoding* pAnother) const; - FX_WCHAR UnicodeFromCharCode(uint8_t charcode) const { + wchar_t UnicodeFromCharCode(uint8_t charcode) const { return m_Unicodes[charcode]; } - int CharCodeFromUnicode(FX_WCHAR unicode) const; + int CharCodeFromUnicode(wchar_t unicode) const; - void SetUnicode(uint8_t charcode, FX_WCHAR unicode) { + void SetUnicode(uint8_t charcode, wchar_t unicode) { m_Unicodes[charcode] = unicode; } - std::unique_ptr Realize(CFX_WeakPtr pPool); + std::unique_ptr Realize(WeakPtr pPool); public: - FX_WCHAR m_Unicodes[256]; + wchar_t m_Unicodes[256]; }; #endif // CORE_FPDFAPI_FONT_CPDF_FONTENCODING_H_ diff --git a/core/fpdfapi/font/cpdf_fontglobals.cpp b/core/fpdfapi/font/cpdf_fontglobals.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddf87b1c09b191418d8d7e468b32699a1938df44 --- /dev/null +++ b/core/fpdfapi/font/cpdf_fontglobals.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/font/cpdf_fontglobals.h" + +#include + +#include "core/fpdfapi/parser/cpdf_document.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CPDF_FontGlobals::CPDF_FontGlobals() { + memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets)); + memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes)); +} + +CPDF_FontGlobals::~CPDF_FontGlobals() {} + +CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) { + auto it = m_StockMap.find(pDoc); + if (it == m_StockMap.end()) + return nullptr; + return it->second ? it->second->GetFont(index) : nullptr; +} + +CPDF_Font* CPDF_FontGlobals::Set(CPDF_Document* pDoc, + uint32_t index, + std::unique_ptr pFont) { + if (!pdfium::ContainsKey(m_StockMap, pDoc)) + m_StockMap[pDoc] = pdfium::MakeUnique(); + return m_StockMap[pDoc]->SetFont(index, std::move(pFont)); +} + +void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) { + m_StockMap.erase(pDoc); +} diff --git a/core/fpdfapi/font/cpdf_fontglobals.h b/core/fpdfapi/font/cpdf_fontglobals.h new file mode 100644 index 0000000000000000000000000000000000000000..a47dfa13d07f2ae089f1ee7e3b01bbf58d7330fd --- /dev/null +++ b/core/fpdfapi/font/cpdf_fontglobals.h @@ -0,0 +1,64 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_ +#define CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_ + +#include +#include +#include + +#include "core/fpdfapi/cmaps/cmap_int.h" +#include "core/fpdfapi/font/cfx_stockfontarray.h" +#include "core/fpdfapi/font/cpdf_cmapmanager.h" + +class CPDF_FontGlobals { + public: + CPDF_FontGlobals(); + ~CPDF_FontGlobals(); + + void Clear(CPDF_Document* pDoc); + CPDF_Font* Find(CPDF_Document* pDoc, uint32_t index); + + // Takes ownership of |pFont|, returns unowned pointer to it. + CPDF_Font* Set(CPDF_Document* key, + uint32_t index, + std::unique_ptr pFont); + + void SetEmbeddedCharset(size_t idx, const FXCMAP_CMap* map, uint32_t count) { + m_EmbeddedCharsets[idx].m_pMapList = map; + m_EmbeddedCharsets[idx].m_Count = count; + } + std::pair GetEmbeddedCharset(size_t idx) const { + return {m_EmbeddedCharsets[idx].m_Count, + m_EmbeddedCharsets[idx].m_pMapList.Get()}; + } + void SetEmbeddedToUnicode(size_t idx, const uint16_t* map, uint32_t count) { + m_EmbeddedToUnicodes[idx].m_pMap = map; + m_EmbeddedToUnicodes[idx].m_Count = count; + } + std::pair GetEmbeddedToUnicode(size_t idx) { + return {m_EmbeddedToUnicodes[idx].m_Count, + m_EmbeddedToUnicodes[idx].m_pMap}; + } + + CPDF_CMapManager* GetCMapManager() { return &m_CMapManager; } + + private: + CPDF_CMapManager m_CMapManager; + struct { + UnownedPtr m_pMapList; + uint32_t m_Count; + } m_EmbeddedCharsets[CIDSET_NUM_SETS]; + struct { + const uint16_t* m_pMap; + uint32_t m_Count; + } m_EmbeddedToUnicodes[CIDSET_NUM_SETS]; + + std::map> m_StockMap; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_ diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp index c41427006867a7f25b26610b203515bcc90da449..92965b0948e24cde2a943ac540d3e879091cd741 100644 --- a/core/fpdfapi/font/cpdf_simplefont.cpp +++ b/core/fpdfapi/font/cpdf_simplefont.cpp @@ -6,16 +6,15 @@ #include "core/fpdfapi/font/cpdf_simplefont.h" -#include "core/fpdfapi/font/font_int.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fxge/fx_freetype.h" #include "third_party/base/numerics/safe_math.h" CPDF_SimpleFont::CPDF_SimpleFont() : m_BaseEncoding(PDFFONT_ENCODING_BUILTIN) { - FXSYS_memset(m_CharWidth, 0xff, sizeof(m_CharWidth)); - FXSYS_memset(m_GlyphIndex, 0xff, sizeof(m_GlyphIndex)); - FXSYS_memset(m_ExtGID, 0xff, sizeof(m_ExtGID)); + memset(m_CharWidth, 0xff, sizeof(m_CharWidth)); + memset(m_GlyphIndex, 0xff, sizeof(m_GlyphIndex)); + memset(m_ExtGID, 0xff, sizeof(m_ExtGID)); for (size_t i = 0; i < FX_ArraySize(m_CharBBox); ++i) m_CharBBox[i] = FX_RECT(-1, -1, -1, -1); } @@ -29,8 +28,11 @@ int CPDF_SimpleFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { if (charcode > 0xff) return -1; - int index = m_GlyphIndex[(uint8_t)charcode]; - return index != 0xffff ? index : -1; + int index = m_GlyphIndex[charcode]; + if (index == 0xffff || (index == 0 && IsTrueTypeFont())) + return -1; + + return index; } void CPDF_SimpleFont::LoadCharMetrics(int charcode) { @@ -128,11 +130,11 @@ bool CPDF_SimpleFont::LoadCommon() { } if (m_pFontFile) { if (m_BaseFont.GetLength() > 8 && m_BaseFont[7] == '+') - m_BaseFont = m_BaseFont.Mid(8); + m_BaseFont = m_BaseFont.Right(m_BaseFont.GetLength() - 8); } else { LoadSubstFont(); } - if (!(m_Flags & FXFONT_SYMBOLIC)) + if (!FontStyleIsSymbolic(m_Flags)) m_BaseEncoding = PDFFONT_ENCODING_STANDARD; CPDF_Object* pEncoding = m_pFontDict->GetDirectObjectFor("Encoding"); LoadPDFEncoding(pEncoding, m_BaseEncoding, &m_CharNames, !!m_pFontFile, @@ -142,7 +144,7 @@ bool CPDF_SimpleFont::LoadCommon() { if (!m_Font.GetFace()) return true; - if (m_Flags & FXFONT_ALLCAP) { + if (FontStyleIsAllCaps(m_Flags)) { unsigned char kLowercases[][2] = {{'a', 'z'}, {0xe0, 0xf6}, {0xf8, 0xfd}}; for (size_t range = 0; range < FX_ArraySize(kLowercases); ++range) { const auto& lower = kLowercases[range]; @@ -164,7 +166,7 @@ bool CPDF_SimpleFont::LoadCommon() { } void CPDF_SimpleFont::LoadSubstFont() { - if (!m_bUseFontWidth && !(m_Flags & FXFONT_FIXED_PITCH)) { + if (!m_bUseFontWidth && !FontStyleIsFixedPitch(m_Flags)) { int width = 0, i; for (i = 0; i < 256; i++) { if (m_CharWidth[i] == 0 || m_CharWidth[i] == 0xffff) @@ -194,19 +196,23 @@ bool CPDF_SimpleFont::IsUnicodeCompatible() const { m_BaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS; } -CFX_WideString CPDF_SimpleFont::UnicodeFromCharCode(uint32_t charcode) const { - CFX_WideString unicode = CPDF_Font::UnicodeFromCharCode(charcode); +WideString CPDF_SimpleFont::UnicodeFromCharCode(uint32_t charcode) const { + WideString unicode = CPDF_Font::UnicodeFromCharCode(charcode); if (!unicode.IsEmpty()) return unicode; - FX_WCHAR ret = m_Encoding.UnicodeFromCharCode((uint8_t)charcode); + wchar_t ret = m_Encoding.UnicodeFromCharCode((uint8_t)charcode); if (ret == 0) - return CFX_WideString(); + return WideString(); return ret; } -uint32_t CPDF_SimpleFont::CharCodeFromUnicode(FX_WCHAR unicode) const { +uint32_t CPDF_SimpleFont::CharCodeFromUnicode(wchar_t unicode) const { uint32_t ret = CPDF_Font::CharCodeFromUnicode(unicode); if (ret) return ret; return m_Encoding.CharCodeFromUnicode(unicode); } + +bool CPDF_SimpleFont::HasFontWidths() const { + return !m_bUseFontWidth; +} diff --git a/core/fpdfapi/font/cpdf_simplefont.h b/core/fpdfapi/font/cpdf_simplefont.h index 592290b99b45b8d3d46c03efa78a0154bd86b519..5291211b244c0334fe031bcf225a396b13e9f4cb 100644 --- a/core/fpdfapi/font/cpdf_simplefont.h +++ b/core/fpdfapi/font/cpdf_simplefont.h @@ -24,11 +24,13 @@ class CPDF_SimpleFont : public CPDF_Font { FX_RECT GetCharBBox(uint32_t charcode) override; int GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) override; bool IsUnicodeCompatible() const override; - CFX_WideString UnicodeFromCharCode(uint32_t charcode) const override; - uint32_t CharCodeFromUnicode(FX_WCHAR Unicode) const override; + WideString UnicodeFromCharCode(uint32_t charcode) const override; + uint32_t CharCodeFromUnicode(wchar_t Unicode) const override; CPDF_FontEncoding* GetEncoding() { return &m_Encoding; } + bool HasFontWidths() const override; + protected: virtual void LoadGlyphMap() = 0; @@ -39,7 +41,7 @@ class CPDF_SimpleFont : public CPDF_Font { CPDF_FontEncoding m_Encoding; uint16_t m_GlyphIndex[256]; uint16_t m_ExtGID[256]; - std::vector m_CharNames; + std::vector m_CharNames; int m_BaseEncoding; uint16_t m_CharWidth[256]; FX_RECT m_CharBBox[256]; diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b746d7bfc0661fb0d6bd739095a5d9ea05a2fdf --- /dev/null +++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp @@ -0,0 +1,232 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/font/cpdf_tounicodemap.h" + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" +#include "core/fpdfapi/page/cpdf_pagemodule.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" +#include "third_party/base/numerics/safe_conversions.h" + +WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const { + auto it = m_Map.find(charcode); + if (it != m_Map.end()) { + uint32_t value = it->second; + wchar_t unicode = (wchar_t)(value & 0xffff); + if (unicode != 0xffff) { + return unicode; + } + const wchar_t* buf = m_MultiCharBuf.GetBuffer(); + uint32_t buf_len = m_MultiCharBuf.GetLength(); + if (!buf || buf_len == 0) { + return WideString(); + } + uint32_t index = value >> 16; + if (index >= buf_len) { + return WideString(); + } + uint32_t len = buf[index]; + if (index + len < index || index + len >= buf_len) { + return WideString(); + } + return WideString(buf + index + 1, len); + } + if (m_pBaseMap) { + return m_pBaseMap->UnicodeFromCID((uint16_t)charcode); + } + return WideString(); +} + +uint32_t CPDF_ToUnicodeMap::ReverseLookup(wchar_t unicode) const { + for (const auto& pair : m_Map) { + if (pair.second == static_cast(unicode)) + return pair.first; + } + return 0; +} + +// Static. +uint32_t CPDF_ToUnicodeMap::StringToCode(const ByteStringView& str) { + int len = str.GetLength(); + if (len == 0) + return 0; + + uint32_t result = 0; + if (str[0] == '<') { + for (int i = 1; i < len && std::isxdigit(str[i]); ++i) + result = result * 16 + FXSYS_HexCharToInt(str.CharAt(i)); + return result; + } + + for (int i = 0; i < len && std::isdigit(str[i]); ++i) + result = result * 10 + FXSYS_DecimalCharToInt(str.CharAt(i)); + + return result; +} + +static WideString StringDataAdd(WideString str) { + WideString ret; + int len = str.GetLength(); + wchar_t value = 1; + for (int i = len - 1; i >= 0; --i) { + wchar_t ch = str[i] + value; + if (ch < str[i]) { + ret.InsertAtFront(0); + } else { + ret.InsertAtFront(ch); + value = 0; + } + } + if (value) + ret.InsertAtFront(value); + return ret; +} + +// Static. +WideString CPDF_ToUnicodeMap::StringToWideString(const ByteStringView& str) { + int len = str.GetLength(); + if (len == 0) + return WideString(); + + WideString result; + if (str[0] == '<') { + int byte_pos = 0; + wchar_t ch = 0; + for (int i = 1; i < len && std::isxdigit(str[i]); ++i) { + ch = ch * 16 + FXSYS_HexCharToInt(str[i]); + byte_pos++; + if (byte_pos == 4) { + result += ch; + byte_pos = 0; + ch = 0; + } + } + return result; + } + return result; +} + +CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {} + +CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {} + +uint32_t CPDF_ToUnicodeMap::GetUnicode() { + FX_SAFE_UINT32 uni = m_MultiCharBuf.GetLength(); + uni = uni * 0x10000 + 0xffff; + return uni.ValueOrDefault(0); +} + +void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) { + CIDSet cid_set = CIDSET_UNKNOWN; + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllDataFiltered(); + CPDF_SimpleParser parser(pAcc->GetData(), pAcc->GetSize()); + while (1) { + ByteStringView word = parser.GetWord(); + if (word.IsEmpty()) { + break; + } + if (word == "beginbfchar") { + while (1) { + word = parser.GetWord(); + if (word.IsEmpty() || word == "endbfchar") { + break; + } + uint32_t srccode = StringToCode(word); + word = parser.GetWord(); + WideString destcode = StringToWideString(word); + int len = destcode.GetLength(); + if (len == 0) { + continue; + } + if (len == 1) { + m_Map[srccode] = destcode[0]; + } else { + m_Map[srccode] = GetUnicode(); + m_MultiCharBuf.AppendChar(destcode.GetLength()); + m_MultiCharBuf << destcode; + } + } + } else if (word == "beginbfrange") { + while (1) { + ByteString low, high; + low = parser.GetWord(); + if (low.IsEmpty() || low == "endbfrange") { + break; + } + high = parser.GetWord(); + uint32_t lowcode = StringToCode(low.AsStringView()); + uint32_t highcode = + (lowcode & 0xffffff00) | (StringToCode(high.AsStringView()) & 0xff); + if (highcode == (uint32_t)-1) { + break; + } + ByteString start(parser.GetWord()); + if (start == "[") { + for (uint32_t code = lowcode; code <= highcode; code++) { + ByteString dest(parser.GetWord()); + WideString destcode = StringToWideString(dest.AsStringView()); + int len = destcode.GetLength(); + if (len == 0) { + continue; + } + if (len == 1) { + m_Map[code] = destcode[0]; + } else { + m_Map[code] = GetUnicode(); + m_MultiCharBuf.AppendChar(destcode.GetLength()); + m_MultiCharBuf << destcode; + } + } + parser.GetWord(); + } else { + WideString destcode = StringToWideString(start.AsStringView()); + int len = destcode.GetLength(); + uint32_t value = 0; + if (len == 1) { + value = StringToCode(start.AsStringView()); + for (uint32_t code = lowcode; code <= highcode; code++) { + m_Map[code] = value++; + } + } else { + for (uint32_t code = lowcode; code <= highcode; code++) { + WideString retcode; + if (code == lowcode) { + retcode = destcode; + } else { + retcode = StringDataAdd(destcode); + } + m_Map[code] = GetUnicode(); + m_MultiCharBuf.AppendChar(retcode.GetLength()); + m_MultiCharBuf << retcode; + destcode = retcode; + } + } + } + } + } else if (word == "/Adobe-Korea1-UCS2") { + cid_set = CIDSET_KOREA1; + } else if (word == "/Adobe-Japan1-UCS2") { + cid_set = CIDSET_JAPAN1; + } else if (word == "/Adobe-CNS1-UCS2") { + cid_set = CIDSET_CNS1; + } else if (word == "/Adobe-GB1-UCS2") { + cid_set = CIDSET_GB1; + } + } + if (cid_set) { + m_pBaseMap = CPDF_ModuleMgr::Get() + ->GetPageModule() + ->GetFontGlobals() + ->GetCMapManager() + ->GetCID2UnicodeMap(cid_set, false); + } else { + m_pBaseMap = nullptr; + } +} diff --git a/core/fpdfapi/font/cpdf_tounicodemap.h b/core/fpdfapi/font/cpdf_tounicodemap.h new file mode 100644 index 0000000000000000000000000000000000000000..62fc470c98c962cc26adc9db36bde89cc4a5be6f --- /dev/null +++ b/core/fpdfapi/font/cpdf_tounicodemap.h @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ +#define CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ + +#include + +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPDF_CID2UnicodeMap; + +class CPDF_ToUnicodeMap { + public: + CPDF_ToUnicodeMap(); + ~CPDF_ToUnicodeMap(); + + void Load(CPDF_Stream* pStream); + + WideString Lookup(uint32_t charcode) const; + uint32_t ReverseLookup(wchar_t unicode) const; + + private: + friend class cpdf_tounicodemap_StringToCode_Test; + friend class cpdf_tounicodemap_StringToWideString_Test; + + static uint32_t StringToCode(const ByteStringView& str); + static WideString StringToWideString(const ByteStringView& str); + + uint32_t GetUnicode(); + + std::map m_Map; + UnownedPtr m_pBaseMap; + CFX_WideTextBuf m_MultiCharBuf; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a5dc25a4c1f7d89e3356abfd306329174ee1ac9 --- /dev/null +++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp @@ -0,0 +1,31 @@ +// Copyright 2015 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. + +#include "core/fpdfapi/font/cpdf_tounicodemap.h" + +#include "testing/gtest/include/gtest/gtest.h" + +TEST(cpdf_tounicodemap, StringToCode) { + EXPECT_EQ(0u, CPDF_ToUnicodeMap::StringToCode("")); + EXPECT_EQ(194u, CPDF_ToUnicodeMap::StringToCode("num_charmaps > 0 && (baseEncoding == PDFFONT_ENCODING_MACROMAN || baseEncoding == PDFFONT_ENCODING_WINANSI) && - (m_Flags & FXFONT_SYMBOLIC)) { + FontStyleIsSymbolic(m_Flags)) { bool bSupportWin = false; bool bSupportMac = false; for (int i = 0; i < FXFT_Get_Face_CharmapCount(m_Font.GetFace()); i++) { @@ -65,7 +64,7 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { if (((baseEncoding == PDFFONT_ENCODING_MACROMAN || baseEncoding == PDFFONT_ENCODING_WINANSI) && m_CharNames.empty()) || - (m_Flags & FXFONT_NONSYMBOLIC)) { + FontStyleIsNonSymbolic(m_Flags)) { if (!FXFT_Has_Glyph_Names(m_Font.GetFace()) && (!m_Font.GetFace()->num_charmaps || !m_Font.GetFace()->charmaps)) { int nStartChar = m_pFontDict->GetIntegerFor("FirstChar"); @@ -73,20 +72,18 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { return; int charcode = 0; - for (; charcode < nStartChar; charcode++) { + for (; charcode < nStartChar; charcode++) m_GlyphIndex[charcode] = 0; - } uint16_t nGlyph = charcode - nStartChar + 3; - for (; charcode < 256; charcode++, nGlyph++) { + for (; charcode < 256; charcode++, nGlyph++) m_GlyphIndex[charcode] = nGlyph; - } return; } bool bMSUnicode = FT_UseTTCharmap(m_Font.GetFace(), 3, 1); bool bMacRoman = false; bool bMSSymbol = false; if (!bMSUnicode) { - if (m_Flags & FXFONT_NONSYMBOLIC) { + if (FontStyleIsNonSymbolic(m_Flags)) { bMacRoman = FT_UseTTCharmap(m_Font.GetFace(), 1, 0); bMSSymbol = !bMacRoman && FT_UseTTCharmap(m_Font.GetFace(), 3, 0); } else { @@ -96,8 +93,7 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { } bool bToUnicode = m_pFontDict->KeyExist("ToUnicode"); for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = - GetAdobeCharName(baseEncoding, m_CharNames, charcode); + const char* name = GetAdobeCharName(baseEncoding, m_CharNames, charcode); if (!name) { m_GlyphIndex[charcode] = m_pFontFile ? FXFT_Get_Char_Index(m_Font.GetFace(), charcode) : -1; @@ -109,9 +105,8 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { uint16_t unicode = kPrefix[j] * 256 + charcode; m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), unicode); - if (m_GlyphIndex[charcode]) { + if (m_GlyphIndex[charcode]) break; - } } } else if (m_Encoding.m_Unicodes[charcode]) { if (bMSUnicode) { @@ -129,28 +124,24 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { } } } - if ((m_GlyphIndex[charcode] == 0 || m_GlyphIndex[charcode] == 0xffff) && - name) { - if (name[0] == '.' && FXSYS_strcmp(name, ".notdef") == 0) { - m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 32); - } else { - m_GlyphIndex[charcode] = - FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); - if (m_GlyphIndex[charcode] == 0) { - if (bToUnicode) { - CFX_WideString wsUnicode = UnicodeFromCharCode(charcode); - if (!wsUnicode.IsEmpty()) { - m_GlyphIndex[charcode] = - FXFT_Get_Char_Index(m_Font.GetFace(), wsUnicode[0]); - m_Encoding.m_Unicodes[charcode] = wsUnicode[0]; - } - } - if (m_GlyphIndex[charcode] == 0) { - m_GlyphIndex[charcode] = - FXFT_Get_Char_Index(m_Font.GetFace(), charcode); - } - } - } + if ((m_GlyphIndex[charcode] != 0 && m_GlyphIndex[charcode] != 0xffff) || + !name) { + continue; + } + if (strcmp(name, ".notdef") == 0) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 32); + continue; + } + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + if (m_GlyphIndex[charcode] != 0 || !bToUnicode) + continue; + + WideString wsUnicode = UnicodeFromCharCode(charcode); + if (!wsUnicode.IsEmpty()) { + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), wsUnicode[0]); + m_Encoding.m_Unicodes[charcode] = wsUnicode[0]; } } return; @@ -170,7 +161,7 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { if (bFound) { if (baseEncoding != PDFFONT_ENCODING_BUILTIN) { for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = + const char* name = GetAdobeCharName(baseEncoding, m_CharNames, charcode); if (name) m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); @@ -204,7 +195,7 @@ void CPDF_TrueTypeFont::LoadGlyphMap() { if (m_pFontFile) { m_Encoding.m_Unicodes[charcode] = charcode; } else { - const FX_CHAR* name = GetAdobeCharName(0, m_CharNames, charcode); + const char* name = GetAdobeCharName(0, m_CharNames, charcode); if (name) m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); else if (pUnicodes) diff --git a/core/fpdfapi/font/cpdf_type1font.cpp b/core/fpdfapi/font/cpdf_type1font.cpp index 1a37555a509767fc2cba24ada8275715c190cbb6..77987bb5dcfcc21ca0732fb2a52d582a0e7688dd 100644 --- a/core/fpdfapi/font/cpdf_type1font.cpp +++ b/core/fpdfapi/font/cpdf_type1font.cpp @@ -6,21 +6,22 @@ #include "core/fpdfapi/font/cpdf_type1font.h" -#include "core/fpdfapi/font/font_int.h" +#include + #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/fx_freetype.h" -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ #include "core/fxge/apple/apple_int.h" #endif namespace { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ struct GlyphNameMap { - const FX_CHAR* m_pStrAdobe; - const FX_CHAR* m_pStrUnicode; + const char* m_pStrAdobe; + const char* m_pStrUnicode; }; const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"}, @@ -29,19 +30,15 @@ const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"}, {"fi", "uniFB01"}, {"fl", "uniFB02"}}; -int compareString(const void* key, const void* element) { - return FXSYS_stricmp(static_cast(key), - static_cast(element)->m_pStrAdobe); -} - -const FX_CHAR* GlyphNameRemap(const FX_CHAR* pStrAdobe) { - const GlyphNameMap* found = static_cast(FXSYS_bsearch( - pStrAdobe, g_GlyphNameSubsts, FX_ArraySize(g_GlyphNameSubsts), - sizeof(GlyphNameMap), compareString)); - return found ? found->m_pStrUnicode : nullptr; +const char* GlyphNameRemap(const char* pStrAdobe) { + for (const auto& element : g_GlyphNameSubsts) { + if (!FXSYS_stricmp(element.m_pStrAdobe, pStrAdobe)) + return element.m_pStrUnicode; + } + return nullptr; } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ bool FT_UseType1Charmap(FXFT_Face face) { if (FXFT_Get_Face_CharmapCount(face) == 0) { @@ -94,7 +91,7 @@ bool CPDF_Type1Font::Load() { m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL; else if (m_Base14Font == 13) m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS; - else if (m_Flags & FXFONT_NONSYMBOLIC) + else if (FontStyleIsNonSymbolic(m_Flags)) m_BaseEncoding = PDFFONT_ENCODING_STANDARD; } return LoadCommon(); @@ -115,7 +112,7 @@ void CPDF_Type1Font::LoadGlyphMap() { if (!m_Font.GetFace()) return; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ bool bCoreText = true; CQuartz2D& quartz2d = static_cast(CFX_GEModule::Get()->GetPlatformData()) @@ -139,7 +136,7 @@ void CPDF_Type1Font::LoadGlyphMap() { uint16_t unicode = prefix[j] * 256 + charcode; m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), unicode); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ CalcExtGID(charcode); #endif if (m_GlyphIndex[charcode]) { @@ -149,19 +146,19 @@ void CPDF_Type1Font::LoadGlyphMap() { } } if (bGotOne) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (!bCoreText) - FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + memcpy(m_ExtGID, m_GlyphIndex, 256); #endif return; } } FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE); - if (m_BaseEncoding == 0) { + if (m_BaseEncoding == 0) m_BaseEncoding = PDFFONT_ENCODING_STANDARD; - } + for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = + const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); if (!name) continue; @@ -169,161 +166,158 @@ void CPDF_Type1Font::LoadGlyphMap() { m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); m_GlyphIndex[charcode] = FXFT_Get_Char_Index( m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ CalcExtGID(charcode); #endif - if (m_GlyphIndex[charcode] == 0 && FXSYS_strcmp(name, ".notdef") == 0) { + if (m_GlyphIndex[charcode] == 0 && strcmp(name, ".notdef") == 0) { m_Encoding.m_Unicodes[charcode] = 0x20; m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 0x20); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ CalcExtGID(charcode); #endif } } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (!bCoreText) - FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + memcpy(m_ExtGID, m_GlyphIndex, 256); #endif return; } FT_UseType1Charmap(m_Font.GetFace()); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (bCoreText) { - if (m_Flags & FXFONT_SYMBOLIC) { + if (FontStyleIsSymbolic(m_Flags)) { for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = + const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); if (name) { m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); m_GlyphIndex[charcode] = - FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + FXFT_Get_Name_Index(m_Font.GetFace(), const_cast(name)); SetExtGID(name, charcode); } else { m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), charcode); - FX_WCHAR unicode = 0; + wchar_t unicode = 0; if (m_GlyphIndex[charcode]) { unicode = FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode); } - FX_CHAR name_glyph[256]; - FXSYS_memset(name_glyph, 0, sizeof(name_glyph)); + char name_glyph[256]; + memset(name_glyph, 0, sizeof(name_glyph)); FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph, 256); name_glyph[255] = 0; - if (unicode == 0 && name_glyph[0] != 0) { + if (unicode == 0 && name_glyph[0] != 0) unicode = PDF_UnicodeFromAdobeName(name_glyph); - } + m_Encoding.m_Unicodes[charcode] = unicode; SetExtGID(name_glyph, charcode); } } return; } - bool bUnicode = false; - if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) { - bUnicode = true; - } + + bool bUnicode = + FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE) == 0; for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = + const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); - if (!name) { + if (!name) continue; - } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); - const FX_CHAR* pStrUnicode = GlyphNameRemap(name); + const char* pStrUnicode = GlyphNameRemap(name); if (pStrUnicode && - 0 == FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name)) { + FXFT_Get_Name_Index(m_Font.GetFace(), const_cast(name)) == 0) { name = pStrUnicode; } m_GlyphIndex[charcode] = - FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + FXFT_Get_Name_Index(m_Font.GetFace(), const_cast(name)); SetExtGID(name, charcode); - if (m_GlyphIndex[charcode] == 0) { - if (FXSYS_strcmp(name, ".notdef") != 0 && - FXSYS_strcmp(name, "space") != 0) { - m_GlyphIndex[charcode] = FXFT_Get_Char_Index( - m_Font.GetFace(), - bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode); - CalcExtGID(charcode); - } else { - m_Encoding.m_Unicodes[charcode] = 0x20; - m_GlyphIndex[charcode] = - bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff; - CalcExtGID(charcode); - } + if (m_GlyphIndex[charcode] != 0) + continue; + + if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), + bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode); + CalcExtGID(charcode); + } else { + m_Encoding.m_Unicodes[charcode] = 0x20; + m_GlyphIndex[charcode] = + bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff; + CalcExtGID(charcode); } } return; } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (m_Flags & FXFONT_SYMBOLIC) { +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + if (FontStyleIsSymbolic(m_Flags)) { for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = + const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); if (name) { m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); m_GlyphIndex[charcode] = - FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + FXFT_Get_Name_Index(m_Font.GetFace(), const_cast(name)); } else { m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), charcode); if (m_GlyphIndex[charcode]) { - FX_WCHAR unicode = + wchar_t unicode = FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode); if (unicode == 0) { - FX_CHAR name_glyph[256]; - FXSYS_memset(name_glyph, 0, sizeof(name_glyph)); + char name_glyph[256]; + memset(name_glyph, 0, sizeof(name_glyph)); FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph, 256); name_glyph[255] = 0; - if (name_glyph[0] != 0) { + if (name_glyph[0] != 0) unicode = PDF_UnicodeFromAdobeName(name_glyph); - } } m_Encoding.m_Unicodes[charcode] = unicode; } } } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (!bCoreText) - FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + memcpy(m_ExtGID, m_GlyphIndex, 256); #endif return; } - bool bUnicode = false; - if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) { - bUnicode = true; - } + + bool bUnicode = + FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE) == 0; for (int charcode = 0; charcode < 256; charcode++) { - const FX_CHAR* name = - GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); - if (!name) { + const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); + if (!name) continue; - } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); - m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); - if (m_GlyphIndex[charcode] == 0) { - if (FXSYS_strcmp(name, ".notdef") != 0 && - FXSYS_strcmp(name, "space") != 0) { - m_GlyphIndex[charcode] = FXFT_Get_Char_Index( - m_Font.GetFace(), - bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode); - } else { - m_Encoding.m_Unicodes[charcode] = 0x20; - m_GlyphIndex[charcode] = 0xffff; - } + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), const_cast(name)); + if (m_GlyphIndex[charcode] != 0) + continue; + + if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), + bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode); + } else { + m_Encoding.m_Unicodes[charcode] = 0x20; + m_GlyphIndex[charcode] = 0xffff; } } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (!bCoreText) - FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + memcpy(m_ExtGID, m_GlyphIndex, 256); #endif } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ -void CPDF_Type1Font::SetExtGID(const FX_CHAR* name, int charcode) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ +void CPDF_Type1Font::SetExtGID(const char* name, int charcode) { CFStringRef name_ct = CFStringCreateWithCStringNoCopy( kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull); m_ExtGID[charcode] = @@ -333,10 +327,10 @@ void CPDF_Type1Font::SetExtGID(const FX_CHAR* name, int charcode) { } void CPDF_Type1Font::CalcExtGID(int charcode) { - FX_CHAR name_glyph[256]; + char name_glyph[256]; FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph, 256); name_glyph[255] = 0; SetExtGID(name_glyph, charcode); } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ diff --git a/core/fpdfapi/font/cpdf_type1font.h b/core/fpdfapi/font/cpdf_type1font.h index f5f378561d101e9cf10c0d5866c0f4486dc73ff3..76c4962ecb26681ebdf4f3fbdc5bdf269c846f91 100644 --- a/core/fpdfapi/font/cpdf_type1font.h +++ b/core/fpdfapi/font/cpdf_type1font.h @@ -29,8 +29,8 @@ class CPDF_Type1Font : public CPDF_SimpleFont { // CPDF_SimpleFont: void LoadGlyphMap() override; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - void SetExtGID(const FX_CHAR* name, int charcode); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + void SetExtGID(const char* name, int charcode); void CalcExtGID(int charcode); #endif diff --git a/core/fpdfapi/font/cpdf_type3char.cpp b/core/fpdfapi/font/cpdf_type3char.cpp index 5eb12c175260228a90cc8a673b3be202c3fffbe2..8a89582b00a8e15b85abf37a1ed217a3e68673e0 100644 --- a/core/fpdfapi/font/cpdf_type3char.cpp +++ b/core/fpdfapi/font/cpdf_type3char.cpp @@ -6,17 +6,36 @@ #include "core/fpdfapi/font/cpdf_type3char.h" +#include + #include "core/fpdfapi/page/cpdf_form.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_imageobject.h" #include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" -CPDF_Type3Char::CPDF_Type3Char(CPDF_Form* pForm) - : m_pForm(pForm), m_bColored(false) {} +namespace { + +constexpr float kTextUnitInGlyphUnit = 1000.0f; + +} // namespace + +CPDF_Type3Char::CPDF_Type3Char(std::unique_ptr pForm) + : m_pForm(std::move(pForm)) {} CPDF_Type3Char::~CPDF_Type3Char() {} +// static +float CPDF_Type3Char::TextUnitToGlyphUnit(float fTextUnit) { + return fTextUnit * kTextUnitInGlyphUnit; +} + +// static +void CPDF_Type3Char::TextUnitRectToGlyphUnitRect(CFX_FloatRect* pRect) { + pRect->Scale(kTextUnitInGlyphUnit); +} + bool CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext) { if (m_pBitmap || !m_pForm) return true; @@ -29,10 +48,57 @@ bool CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext) { return false; m_ImageMatrix = pPageObj->AsImage()->matrix(); - std::unique_ptr pSource = - pPageObj->AsImage()->GetImage()->LoadDIBSource(); - if (pSource) - m_pBitmap = pSource->Clone(); + { + // |pSource| actually gets assigned a CPDF_DIBSource, which has pointers + // into objects owned by |m_pForm|. Make sure it is out of scope before + // clearing the form. + RetainPtr pSource = + pPageObj->AsImage()->GetImage()->LoadDIBSource(); + + // Clone() is non-virtual, and can't be overloaded by CPDF_DIBSource to + // return a clone of the subclass as one would typically expect from a + // such a method. Instead, it only clones the CFX_DIBSource, none of whose + // members point to objects owned by the form. As a result, |m_pBitmap| + // may outlive |m_pForm|. + if (pSource) + m_pBitmap = pSource->Clone(nullptr); + } m_pForm.reset(); return true; } + +void CPDF_Type3Char::InitializeFromStreamData(bool bColored, + const float* pData) { + m_bColored = bColored; + m_Width = FXSYS_round(TextUnitToGlyphUnit(pData[0])); + m_BBox.left = FXSYS_round(TextUnitToGlyphUnit(pData[2])); + m_BBox.bottom = FXSYS_round(TextUnitToGlyphUnit(pData[3])); + m_BBox.right = FXSYS_round(TextUnitToGlyphUnit(pData[4])); + m_BBox.top = FXSYS_round(TextUnitToGlyphUnit(pData[5])); +} + +void CPDF_Type3Char::Transform(const CFX_Matrix& matrix) { + m_Width = m_Width * matrix.GetXUnit() + 0.5f; + + CFX_FloatRect char_rect; + if (m_BBox.right <= m_BBox.left || m_BBox.bottom >= m_BBox.top) { + char_rect = form()->CalcBoundingBox(); + TextUnitRectToGlyphUnitRect(&char_rect); + } else { + char_rect = CFX_FloatRect(m_BBox); + } + + m_BBox = matrix.TransformRect(char_rect).ToRoundedFxRect(); +} + +void CPDF_Type3Char::ResetForm() { + m_pForm.reset(); +} + +RetainPtr CPDF_Type3Char::GetBitmap() { + return m_pBitmap; +} + +const RetainPtr& CPDF_Type3Char::GetBitmap() const { + return m_pBitmap; +} diff --git a/core/fpdfapi/font/cpdf_type3char.h b/core/fpdfapi/font/cpdf_type3char.h index 549f49e3da3dd213d453c31d0b8ae993b394d4a4..c9c5555cf41d9a29391a82fcd002310fa386b7d4 100644 --- a/core/fpdfapi/font/cpdf_type3char.h +++ b/core/fpdfapi/font/cpdf_type3char.h @@ -11,6 +11,7 @@ #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" class CFX_DIBitmap; class CPDF_Form; @@ -18,16 +19,34 @@ class CPDF_RenderContext; class CPDF_Type3Char { public: - // Takes ownership of |pForm|. - explicit CPDF_Type3Char(CPDF_Form* pForm); + explicit CPDF_Type3Char(std::unique_ptr pForm); ~CPDF_Type3Char(); + static float TextUnitToGlyphUnit(float fTextUnit); + static void TextUnitRectToGlyphUnitRect(CFX_FloatRect* pRect); + bool LoadBitmap(CPDF_RenderContext* pContext); + void InitializeFromStreamData(bool bColored, const float* pData); + void Transform(const CFX_Matrix& matrix); + void ResetForm(); + + RetainPtr GetBitmap(); + const RetainPtr& GetBitmap() const; + + const CPDF_Form* form() const { return m_pForm.get(); } + CPDF_Form* form() { return m_pForm.get(); } + + bool colored() const { return m_bColored; } + int width() const { return m_Width; } + const CFX_Matrix& matrix() const { return m_ImageMatrix; } + const FX_RECT& bbox() const { return m_BBox; } + + private: std::unique_ptr m_pForm; - std::unique_ptr m_pBitmap; - bool m_bColored; - int m_Width; + RetainPtr m_pBitmap; + bool m_bColored = false; + int m_Width = 0; CFX_Matrix m_ImageMatrix; FX_RECT m_BBox; }; diff --git a/core/fpdfapi/font/cpdf_type3font.cpp b/core/fpdfapi/font/cpdf_type3font.cpp index f6cd6ecf26325753a60ea2e00bc8eb35d4fa4675..c328c1020da28759fc992fc3ee3687aa33f605ab 100644 --- a/core/fpdfapi/font/cpdf_type3font.cpp +++ b/core/fpdfapi/font/cpdf_type3font.cpp @@ -6,25 +6,25 @@ #include "core/fpdfapi/font/cpdf_type3font.h" +#include #include #include "core/fpdfapi/font/cpdf_type3char.h" #include "core/fpdfapi/page/cpdf_form.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fxcrt/fx_system.h" #include "third_party/base/stl_util.h" -#define FPDF_MAX_TYPE3_FORM_LEVEL 4 +namespace { -CPDF_Type3Font::CPDF_Type3Font() - : m_pCharProcs(nullptr), - m_pPageResources(nullptr), - m_pFontResources(nullptr), - m_CharLoadingDepth(0) { - FXSYS_memset(m_CharWidthL, 0, sizeof(m_CharWidthL)); +constexpr int kMaxType3FormLevel = 4; + +} // namespace + +CPDF_Type3Font::CPDF_Type3Font() { + memset(m_CharWidthL, 0, sizeof(m_CharWidthL)); } CPDF_Type3Font::~CPDF_Type3Font() {} @@ -44,30 +44,35 @@ CPDF_Type3Font* CPDF_Type3Font::AsType3Font() { bool CPDF_Type3Font::Load() { m_pFontResources = m_pFontDict->GetDictFor("Resources"); CPDF_Array* pMatrix = m_pFontDict->GetArrayFor("FontMatrix"); - FX_FLOAT xscale = 1.0f, yscale = 1.0f; + float xscale = 1.0f; + float yscale = 1.0f; if (pMatrix) { m_FontMatrix = pMatrix->GetMatrix(); xscale = m_FontMatrix.a; yscale = m_FontMatrix.d; } + CPDF_Array* pBBox = m_pFontDict->GetArrayFor("FontBBox"); if (pBBox) { - m_FontBBox.left = (int32_t)(pBBox->GetNumberAt(0) * xscale * 1000); - m_FontBBox.bottom = (int32_t)(pBBox->GetNumberAt(1) * yscale * 1000); - m_FontBBox.right = (int32_t)(pBBox->GetNumberAt(2) * xscale * 1000); - m_FontBBox.top = (int32_t)(pBBox->GetNumberAt(3) * yscale * 1000); + CFX_FloatRect box( + pBBox->GetNumberAt(0) * xscale, pBBox->GetNumberAt(1) * yscale, + pBBox->GetNumberAt(2) * xscale, pBBox->GetNumberAt(3) * yscale); + CPDF_Type3Char::TextUnitRectToGlyphUnitRect(&box); + m_FontBBox = box.ToFxRect(); } + + static constexpr size_t kCharLimit = FX_ArraySize(m_CharWidthL); int StartChar = m_pFontDict->GetIntegerFor("FirstChar"); - CPDF_Array* pWidthArray = m_pFontDict->GetArrayFor("Widths"); - if (pWidthArray && (StartChar >= 0 && StartChar < 256)) { - size_t count = pWidthArray->GetCount(); - if (count > 256) - count = 256; - if (StartChar + count > 256) - count = 256 - StartChar; - for (size_t i = 0; i < count; i++) { - m_CharWidthL[StartChar + i] = - FXSYS_round(pWidthArray->GetNumberAt(i) * xscale * 1000); + if (StartChar >= 0 && static_cast(StartChar) < kCharLimit) { + CPDF_Array* pWidthArray = m_pFontDict->GetArrayFor("Widths"); + if (pWidthArray) { + size_t count = std::min(pWidthArray->GetCount(), kCharLimit); + count = std::min(count, kCharLimit - StartChar); + for (size_t i = 0; i < count; i++) { + m_CharWidthL[StartChar + i] = + FXSYS_round(CPDF_Type3Char::TextUnitToGlyphUnit( + pWidthArray->GetNumberAt(i) * xscale)); + } } } m_pCharProcs = m_pFontDict->GetDictFor("CharProcs"); @@ -77,19 +82,21 @@ bool CPDF_Type3Font::Load() { return true; } +void CPDF_Type3Font::LoadGlyphMap() {} + void CPDF_Type3Font::CheckType3FontMetrics() { CheckFontMetrics(); } CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode) { - if (m_CharLoadingDepth >= FPDF_MAX_TYPE3_FORM_LEVEL) + if (m_CharLoadingDepth >= kMaxType3FormLevel) return nullptr; auto it = m_CacheMap.find(charcode); if (it != m_CacheMap.end()) return it->second.get(); - const FX_CHAR* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); + const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode); if (!name) return nullptr; @@ -98,40 +105,27 @@ CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode) { if (!pStream) return nullptr; - std::unique_ptr pNewChar(new CPDF_Type3Char(new CPDF_Form( - m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources, - pStream, nullptr))); + auto pNewChar = + pdfium::MakeUnique(pdfium::MakeUnique( + m_pDocument.Get(), + m_pFontResources ? m_pFontResources.Get() : m_pPageResources.Get(), + pStream, nullptr)); // This can trigger recursion into this method. The content of |m_CacheMap| // can change as a result. Thus after it returns, check the cache again for // a cache hit. m_CharLoadingDepth++; - pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get()); + pNewChar->form()->ParseContentWithParams(nullptr, nullptr, pNewChar.get(), 0); m_CharLoadingDepth--; it = m_CacheMap.find(charcode); if (it != m_CacheMap.end()) return it->second.get(); - FX_FLOAT scale = m_FontMatrix.GetXUnit(); - pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f); - FX_RECT& rcBBox = pNewChar->m_BBox; - CFX_FloatRect char_rect( - (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f, - (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f); - if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top) - char_rect = pNewChar->m_pForm->CalcBoundingBox(); - - m_FontMatrix.TransformRect(char_rect); - rcBBox.left = FXSYS_round(char_rect.left * 1000); - rcBBox.right = FXSYS_round(char_rect.right * 1000); - rcBBox.top = FXSYS_round(char_rect.top * 1000); - rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000); - - ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode)); + pNewChar->Transform(m_FontMatrix); m_CacheMap[charcode] = std::move(pNewChar); CPDF_Type3Char* pCachedChar = m_CacheMap[charcode].get(); - if (pCachedChar->m_pForm->GetPageObjectList()->empty()) - pCachedChar->m_pForm.reset(); + if (pCachedChar->form()->GetPageObjectList()->empty()) + pCachedChar->ResetForm(); return pCachedChar; } @@ -143,10 +137,13 @@ int CPDF_Type3Font::GetCharWidthF(uint32_t charcode) { return m_CharWidthL[charcode]; const CPDF_Type3Char* pChar = LoadChar(charcode); - return pChar ? pChar->m_Width : 0; + return pChar ? pChar->width() : 0; } FX_RECT CPDF_Type3Font::GetCharBBox(uint32_t charcode) { + FX_RECT ret; const CPDF_Type3Char* pChar = LoadChar(charcode); - return pChar ? pChar->m_BBox : FX_RECT(); + if (pChar) + ret = pChar->bbox(); + return ret; } diff --git a/core/fpdfapi/font/cpdf_type3font.h b/core/fpdfapi/font/cpdf_type3font.h index 0bae192d611bf5e52ee44f527cf1e395e7a8ce40..3f2e018c88b66dffb8517926e78fd4f4251897de 100644 --- a/core/fpdfapi/font/cpdf_type3font.h +++ b/core/fpdfapi/font/cpdf_type3font.h @@ -45,15 +45,15 @@ class CPDF_Type3Font : public CPDF_SimpleFont { bool Load() override; // CPDF_SimpleFont: - void LoadGlyphMap() override {} + void LoadGlyphMap() override; int m_CharWidthL[256]; - CPDF_Dictionary* m_pCharProcs; - CPDF_Dictionary* m_pPageResources; - CPDF_Dictionary* m_pFontResources; + UnownedPtr m_pCharProcs; + UnownedPtr m_pPageResources; + UnownedPtr m_pFontResources; std::map> m_CacheMap; // The depth char loading is in, to avoid recurive calling LoadChar(). - int m_CharLoadingDepth; + int m_CharLoadingDepth = 0; }; #endif // CORE_FPDFAPI_FONT_CPDF_TYPE3FONT_H_ diff --git a/core/fpdfapi/font/font_int.h b/core/fpdfapi/font/font_int.h deleted file mode 100644 index 41d821ec81fa6ff04d0436d3a957aa825978f42b..0000000000000000000000000000000000000000 --- a/core/fpdfapi/font/font_int.h +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FPDFAPI_FONT_FONT_INT_H_ -#define CORE_FPDFAPI_FONT_FONT_INT_H_ - -#include -#include -#include - -#include "core/fpdfapi/font/cpdf_cidfont.h" -#include "core/fxcrt/cfx_maybe_owned.h" -#include "core/fxcrt/fx_basic.h" - -class CPDF_CID2UnicodeMap; -class CPDF_CMap; -class CPDF_Font; -class CPDF_Stream; - -using FXFT_Library = void*; - -int TT2PDF(int m, FXFT_Face face); -bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id); -CIDSet CharsetFromOrdering(const CFX_ByteStringC& ordering); - -class CPDF_CMapManager { - public: - CPDF_CMapManager(); - ~CPDF_CMapManager(); - - CFX_MaybeOwned GetPredefinedCMap(const CFX_ByteString& name, - bool bPromptCJK); - CPDF_CID2UnicodeMap* GetCID2UnicodeMap(CIDSet charset, bool bPromptCJK); - - private: - std::unique_ptr LoadPredefinedCMap(const CFX_ByteString& name, - bool bPromptCJK); - std::unique_ptr LoadCID2UnicodeMap(CIDSet charset, - bool bPromptCJK); - - std::map> m_CMaps; - std::unique_ptr m_CID2UnicodeMaps[6]; -}; - -class CFX_StockFontArray { - public: - CFX_StockFontArray(); - ~CFX_StockFontArray(); - - // Takes ownership of |pFont|, returns unowned pointer to it. - CPDF_Font* SetFont(uint32_t index, std::unique_ptr pFont); - CPDF_Font* GetFont(uint32_t index) const; - - private: - std::unique_ptr m_StockFonts[14]; -}; - -class CPDF_FontGlobals { - public: - CPDF_FontGlobals(); - ~CPDF_FontGlobals(); - - void Clear(CPDF_Document* pDoc); - CPDF_Font* Find(CPDF_Document* pDoc, uint32_t index); - - // Takes ownership of |pFont|, returns unowned pointer to it. - CPDF_Font* Set(CPDF_Document* key, - uint32_t index, - std::unique_ptr pFont); - - CPDF_CMapManager m_CMapManager; - struct { - const struct FXCMAP_CMap* m_pMapList; - uint32_t m_Count; - } m_EmbeddedCharsets[CIDSET_NUM_SETS]; - struct { - const uint16_t* m_pMap; - uint32_t m_Count; - } m_EmbeddedToUnicodes[CIDSET_NUM_SETS]; - - private: - std::map> m_StockMap; -}; - -struct CMap_CodeRange { - int m_CharSize; - uint8_t m_Lower[4]; - uint8_t m_Upper[4]; -}; - -class CPDF_CMapParser { - public: - CPDF_CMapParser(); - ~CPDF_CMapParser(); - void Initialize(CPDF_CMap* pMap); - void ParseWord(const CFX_ByteStringC& str); - CFX_BinaryBuf m_AddMaps; - - private: - friend class fpdf_font_cid_CMap_GetCode_Test; - friend class fpdf_font_cid_CMap_GetCodeRange_Test; - - static uint32_t CMap_GetCode(const CFX_ByteStringC& word); - static bool CMap_GetCodeRange(CMap_CodeRange& range, - const CFX_ByteStringC& first, - const CFX_ByteStringC& second); - - CPDF_CMap* m_pCMap; - int m_Status; - int m_CodeSeq; - uint32_t m_CodePoints[4]; - std::vector m_CodeRanges; - CFX_ByteString m_LastWord; -}; - -enum CIDCoding : uint8_t { - CIDCODING_UNKNOWN = 0, - CIDCODING_GB, - CIDCODING_BIG5, - CIDCODING_JIS, - CIDCODING_KOREA, - CIDCODING_UCS2, - CIDCODING_CID, - CIDCODING_UTF16, -}; - -class CPDF_CMap { - public: - enum CodingScheme : uint8_t { - OneByte, - TwoBytes, - MixedTwoBytes, - MixedFourBytes - }; - - CPDF_CMap(); - ~CPDF_CMap(); - - void LoadPredefined(CPDF_CMapManager* pMgr, - const CFX_ByteString& name, - bool bPromptCJK); - void LoadEmbedded(const uint8_t* pData, uint32_t dwSize); - - bool IsLoaded() const; - bool IsVertWriting() const; - uint16_t CIDFromCharCode(uint32_t charcode) const; - int GetCharSize(uint32_t charcode) const; - uint32_t GetNextChar(const FX_CHAR* pString, int nStrLen, int& offset) const; - int CountChar(const FX_CHAR* pString, int size) const; - int AppendChar(FX_CHAR* str, uint32_t charcode) const; - - private: - friend class CPDF_CMapParser; - friend class CPDF_CIDFont; - - CFX_ByteString m_PredefinedCMap; - bool m_bVertical; - CIDSet m_Charset; - int m_Coding; - CodingScheme m_CodingScheme; - int m_nCodeRanges; - uint8_t* m_pLeadingBytes; - uint16_t* m_pMapping; - uint8_t* m_pAddMapping; - bool m_bLoaded; - const FXCMAP_CMap* m_pEmbedMap; -}; - -class CPDF_CID2UnicodeMap { - public: - CPDF_CID2UnicodeMap(); - ~CPDF_CID2UnicodeMap(); - - bool IsLoaded(); - void Load(CPDF_CMapManager* pMgr, CIDSet charset, bool bPromptCJK); - FX_WCHAR UnicodeFromCID(uint16_t CID); - - private: - CIDSet m_Charset; - const uint16_t* m_pEmbeddedMap; - uint32_t m_EmbeddedCount; -}; - -class CPDF_ToUnicodeMap { - public: - CPDF_ToUnicodeMap(); - ~CPDF_ToUnicodeMap(); - - void Load(CPDF_Stream* pStream); - - CFX_WideString Lookup(uint32_t charcode) const; - uint32_t ReverseLookup(FX_WCHAR unicode) const; - - private: - friend class fpdf_font_StringToCode_Test; - friend class fpdf_font_StringToWideString_Test; - - static uint32_t StringToCode(const CFX_ByteStringC& str); - static CFX_WideString StringToWideString(const CFX_ByteStringC& str); - - uint32_t GetUnicode(); - - std::map m_Map; - CPDF_CID2UnicodeMap* m_pBaseMap; - CFX_WideTextBuf m_MultiCharBuf; -}; - -#endif // CORE_FPDFAPI_FONT_FONT_INT_H_ diff --git a/core/fpdfapi/font/fpdf_font.cpp b/core/fpdfapi/font/fpdf_font.cpp deleted file mode 100644 index 7bbd63717789ab853ec812fc15428ef49a7754c5..0000000000000000000000000000000000000000 --- a/core/fpdfapi/font/fpdf_font.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/font/font_int.h" - -#include -#include - -#include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/page/cpdf_form.h" -#include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fpdfapi/page/pageint.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_name.h" -#include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" -#include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/fx_freetype.h" -#include "third_party/base/numerics/safe_conversions.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -int TT2PDF(int m, FXFT_Face face) { - int upm = FXFT_Get_Face_UnitsPerEM(face); - if (upm == 0) - return m; - return pdfium::base::checked_cast( - (static_cast(m) * 1000 + upm / 2) / upm); -} - -bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id) { - auto* pCharMap = FXFT_Get_Face_Charmaps(face); - for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) { - if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id && - FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) { - FXFT_Set_Charmap(face, pCharMap[i]); - return true; - } - } - return false; -} - -CFX_StockFontArray::CFX_StockFontArray() {} - -CFX_StockFontArray::~CFX_StockFontArray() { - for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) { - if (m_StockFonts[i]) - delete m_StockFonts[i]->GetFontDict(); - } -} - -CPDF_Font* CFX_StockFontArray::GetFont(uint32_t index) const { - if (index >= FX_ArraySize(m_StockFonts)) - return nullptr; - return m_StockFonts[index].get(); -} - -CPDF_Font* CFX_StockFontArray::SetFont(uint32_t index, - std::unique_ptr pFont) { - CPDF_Font* result = pFont.get(); - if (index < FX_ArraySize(m_StockFonts)) - m_StockFonts[index] = std::move(pFont); - return result; -} - -CPDF_FontGlobals::CPDF_FontGlobals() { - FXSYS_memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets)); - FXSYS_memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes)); -} - -CPDF_FontGlobals::~CPDF_FontGlobals() {} - -CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) { - auto it = m_StockMap.find(pDoc); - if (it == m_StockMap.end()) - return nullptr; - return it->second ? it->second->GetFont(index) : nullptr; -} - -CPDF_Font* CPDF_FontGlobals::Set(CPDF_Document* pDoc, - uint32_t index, - std::unique_ptr pFont) { - if (!pdfium::ContainsKey(m_StockMap, pDoc)) - m_StockMap[pDoc] = pdfium::MakeUnique(); - return m_StockMap[pDoc]->SetFont(index, std::move(pFont)); -} - -void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) { - m_StockMap.erase(pDoc); -} - -CFX_WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const { - auto it = m_Map.find(charcode); - if (it != m_Map.end()) { - uint32_t value = it->second; - FX_WCHAR unicode = (FX_WCHAR)(value & 0xffff); - if (unicode != 0xffff) { - return unicode; - } - const FX_WCHAR* buf = m_MultiCharBuf.GetBuffer(); - uint32_t buf_len = m_MultiCharBuf.GetLength(); - if (!buf || buf_len == 0) { - return CFX_WideString(); - } - uint32_t index = value >> 16; - if (index >= buf_len) { - return CFX_WideString(); - } - uint32_t len = buf[index]; - if (index + len < index || index + len >= buf_len) { - return CFX_WideString(); - } - return CFX_WideString(buf + index + 1, len); - } - if (m_pBaseMap) { - return m_pBaseMap->UnicodeFromCID((uint16_t)charcode); - } - return CFX_WideString(); -} - -uint32_t CPDF_ToUnicodeMap::ReverseLookup(FX_WCHAR unicode) const { - for (const auto& pair : m_Map) { - if (pair.second == static_cast(unicode)) - return pair.first; - } - return 0; -} - -// Static. -uint32_t CPDF_ToUnicodeMap::StringToCode(const CFX_ByteStringC& str) { - int len = str.GetLength(); - if (len == 0) - return 0; - - uint32_t result = 0; - if (str[0] == '<') { - for (int i = 1; i < len && std::isxdigit(str[i]); ++i) - result = result * 16 + FXSYS_toHexDigit(str.CharAt(i)); - return result; - } - - for (int i = 0; i < len && std::isdigit(str[i]); ++i) - result = result * 10 + FXSYS_toDecimalDigit(str.CharAt(i)); - - return result; -} - -static CFX_WideString StringDataAdd(CFX_WideString str) { - CFX_WideString ret; - int len = str.GetLength(); - FX_WCHAR value = 1; - for (int i = len - 1; i >= 0; --i) { - FX_WCHAR ch = str[i] + value; - if (ch < str[i]) { - ret.Insert(0, 0); - } else { - ret.Insert(0, ch); - value = 0; - } - } - if (value) { - ret.Insert(0, value); - } - return ret; -} - -// Static. -CFX_WideString CPDF_ToUnicodeMap::StringToWideString( - const CFX_ByteStringC& str) { - int len = str.GetLength(); - if (len == 0) - return CFX_WideString(); - - CFX_WideString result; - if (str[0] == '<') { - int byte_pos = 0; - FX_WCHAR ch = 0; - for (int i = 1; i < len && std::isxdigit(str[i]); ++i) { - ch = ch * 16 + FXSYS_toHexDigit(str[i]); - byte_pos++; - if (byte_pos == 4) { - result += ch; - byte_pos = 0; - ch = 0; - } - } - return result; - } - return result; -} - -CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {} - -CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {} - -uint32_t CPDF_ToUnicodeMap::GetUnicode() { - FX_SAFE_UINT32 uni = m_MultiCharBuf.GetLength(); - uni = uni * 0x10000 + 0xffff; - return uni.ValueOrDefault(0); -} - -void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) { - CIDSet cid_set = CIDSET_UNKNOWN; - CPDF_StreamAcc stream; - stream.LoadAllData(pStream, false); - CPDF_SimpleParser parser(stream.GetData(), stream.GetSize()); - while (1) { - CFX_ByteStringC word = parser.GetWord(); - if (word.IsEmpty()) { - break; - } - if (word == "beginbfchar") { - while (1) { - word = parser.GetWord(); - if (word.IsEmpty() || word == "endbfchar") { - break; - } - uint32_t srccode = StringToCode(word); - word = parser.GetWord(); - CFX_WideString destcode = StringToWideString(word); - int len = destcode.GetLength(); - if (len == 0) { - continue; - } - if (len == 1) { - m_Map[srccode] = destcode.GetAt(0); - } else { - m_Map[srccode] = GetUnicode(); - m_MultiCharBuf.AppendChar(destcode.GetLength()); - m_MultiCharBuf << destcode; - } - } - } else if (word == "beginbfrange") { - while (1) { - CFX_ByteString low, high; - low = parser.GetWord(); - if (low.IsEmpty() || low == "endbfrange") { - break; - } - high = parser.GetWord(); - uint32_t lowcode = StringToCode(low.AsStringC()); - uint32_t highcode = - (lowcode & 0xffffff00) | (StringToCode(high.AsStringC()) & 0xff); - if (highcode == (uint32_t)-1) { - break; - } - CFX_ByteString start(parser.GetWord()); - if (start == "[") { - for (uint32_t code = lowcode; code <= highcode; code++) { - CFX_ByteString dest(parser.GetWord()); - CFX_WideString destcode = StringToWideString(dest.AsStringC()); - int len = destcode.GetLength(); - if (len == 0) { - continue; - } - if (len == 1) { - m_Map[code] = destcode.GetAt(0); - } else { - m_Map[code] = GetUnicode(); - m_MultiCharBuf.AppendChar(destcode.GetLength()); - m_MultiCharBuf << destcode; - } - } - parser.GetWord(); - } else { - CFX_WideString destcode = StringToWideString(start.AsStringC()); - int len = destcode.GetLength(); - uint32_t value = 0; - if (len == 1) { - value = StringToCode(start.AsStringC()); - for (uint32_t code = lowcode; code <= highcode; code++) { - m_Map[code] = value++; - } - } else { - for (uint32_t code = lowcode; code <= highcode; code++) { - CFX_WideString retcode; - if (code == lowcode) { - retcode = destcode; - } else { - retcode = StringDataAdd(destcode); - } - m_Map[code] = GetUnicode(); - m_MultiCharBuf.AppendChar(retcode.GetLength()); - m_MultiCharBuf << retcode; - destcode = retcode; - } - } - } - } - } else if (word == "/Adobe-Korea1-UCS2") { - cid_set = CIDSET_KOREA1; - } else if (word == "/Adobe-Japan1-UCS2") { - cid_set = CIDSET_JAPAN1; - } else if (word == "/Adobe-CNS1-UCS2") { - cid_set = CIDSET_CNS1; - } else if (word == "/Adobe-GB1-UCS2") { - cid_set = CIDSET_GB1; - } - } - if (cid_set) { - m_pBaseMap = CPDF_ModuleMgr::Get() - ->GetPageModule() - ->GetFontGlobals() - ->m_CMapManager.GetCID2UnicodeMap(cid_set, false); - } else { - m_pBaseMap = nullptr; - } -} diff --git a/core/fpdfapi/font/fpdf_font_cid.cpp b/core/fpdfapi/font/fpdf_font_cid.cpp deleted file mode 100644 index afb186d0706b736829b388da7aac6dee6a3e4dc3..0000000000000000000000000000000000000000 --- a/core/fpdfapi/font/fpdf_font_cid.cpp +++ /dev/null @@ -1,787 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/font/font_int.h" - -#include -#include - -#include "core/fpdfapi/cmaps/cmap_int.h" -#include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/ttgsubtable.h" -#include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" -#include "core/fxcrt/fx_ext.h" -#include "core/fxge/fx_freetype.h" -#include "third_party/base/logging.h" -#include "third_party/base/stl_util.h" - -namespace { - -const FX_CHAR* const g_CharsetNames[CIDSET_NUM_SETS] = { - nullptr, "GB1", "CNS1", "Japan1", "Korea1", "UCS"}; - -class CPDF_PredefinedCMap { - public: - const FX_CHAR* m_pName; - CIDSet m_Charset; - CIDCoding m_Coding; - CPDF_CMap::CodingScheme m_CodingScheme; - uint8_t m_LeadingSegCount; - uint8_t m_LeadingSegs[4]; -}; - -const CPDF_PredefinedCMap g_PredefinedCMaps[] = { - {"GB-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfe}}, - {"GBpc-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfc}}, - {"GBK-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {0x81, 0xfe}}, - {"GBKp-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {0x81, 0xfe}}, - {"GBK2K-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {0x81, 0xfe}}, - {"GBK2K", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {0x81, 0xfe}}, - {"UniGB-UCS2", CIDSET_GB1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniGB-UTF16", CIDSET_GB1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, - {"B5pc", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfc}}, - {"HKscs-B5", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {0x88, 0xfe}}, - {"ETen-B5", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfe}}, - {"ETenms-B5", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfe}}, - {"UniCNS-UCS2", CIDSET_CNS1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniCNS-UTF16", CIDSET_CNS1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, - {"83pv-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x81, 0x9f, 0xe0, 0xfc}}, - {"90ms-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x81, 0x9f, 0xe0, 0xfc}}, - {"90msp-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x81, 0x9f, 0xe0, 0xfc}}, - {"90pv-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x81, 0x9f, 0xe0, 0xfc}}, - {"Add-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x81, 0x9f, 0xe0, 0xfc}}, - {"EUC", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x8e, 0x8e, 0xa1, 0xfe}}, - {"H", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {0x21, 0x7e}}, - {"V", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {0x21, 0x7e}}, - {"Ext-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {0x81, 0x9f, 0xe0, 0xfc}}, - {"UniJIS-UCS2", CIDSET_JAPAN1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniJIS-UCS2-HW", - CIDSET_JAPAN1, - CIDCODING_UCS2, - CPDF_CMap::TwoBytes, - 0, - {}}, - {"UniJIS-UTF16", - CIDSET_JAPAN1, - CIDCODING_UTF16, - CPDF_CMap::TwoBytes, - 0, - {}}, - {"KSC-EUC", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfe}}, - {"KSCms-UHC", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {0x81, 0xfe}}, - {"KSCms-UHC-HW", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {0x81, 0xfe}}, - {"KSCpc-EUC", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {0xa1, 0xfd}}, - {"UniKS-UCS2", CIDSET_KOREA1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniKS-UTF16", CIDSET_KOREA1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, -}; - -CIDSet CIDSetFromSizeT(size_t index) { - if (index >= CIDSET_NUM_SETS) { - NOTREACHED(); - return CIDSET_UNKNOWN; - } - return static_cast(index); -} - -CFX_ByteStringC CMap_GetString(const CFX_ByteStringC& word) { - if (word.GetLength() <= 2) - return CFX_ByteStringC(); - return CFX_ByteStringC(&word[1], word.GetLength() - 2); -} - -int CompareDWORD(const void* data1, const void* data2) { - return (*(uint32_t*)data1) - (*(uint32_t*)data2); -} - -int CompareCID(const void* key, const void* element) { - if ((*(uint32_t*)key) < (*(uint32_t*)element)) { - return -1; - } - if ((*(uint32_t*)key) > - (*(uint32_t*)element) + ((uint32_t*)element)[1] / 65536) { - return 1; - } - return 0; -} - -int CheckCodeRange(uint8_t* codes, - int size, - CMap_CodeRange* pRanges, - int nRanges) { - int iSeg = nRanges - 1; - while (iSeg >= 0) { - if (pRanges[iSeg].m_CharSize < size) { - --iSeg; - continue; - } - int iChar = 0; - while (iChar < size) { - if (codes[iChar] < pRanges[iSeg].m_Lower[iChar] || - codes[iChar] > pRanges[iSeg].m_Upper[iChar]) { - break; - } - ++iChar; - } - if (iChar == pRanges[iSeg].m_CharSize) - return 2; - - if (iChar) - return (size == pRanges[iSeg].m_CharSize) ? 2 : 1; - iSeg--; - } - return 0; -} - -int GetCharSizeImpl(uint32_t charcode, - CMap_CodeRange* pRanges, - int iRangesSize) { - if (!iRangesSize) - return 1; - - uint8_t codes[4]; - codes[0] = codes[1] = 0x00; - codes[2] = (uint8_t)(charcode >> 8 & 0xFF); - codes[3] = (uint8_t)charcode; - int offset = 0; - int size = 4; - for (int i = 0; i < 4; ++i) { - int iSeg = iRangesSize - 1; - while (iSeg >= 0) { - if (pRanges[iSeg].m_CharSize < size) { - --iSeg; - continue; - } - int iChar = 0; - while (iChar < size) { - if (codes[offset + iChar] < pRanges[iSeg].m_Lower[iChar] || - codes[offset + iChar] > pRanges[iSeg].m_Upper[iChar]) { - break; - } - ++iChar; - } - if (iChar == pRanges[iSeg].m_CharSize) - return size; - --iSeg; - } - --size; - ++offset; - } - return 1; -} - -} // namespace - -CPDF_CMapManager::CPDF_CMapManager() {} - -CPDF_CMapManager::~CPDF_CMapManager() {} - -CFX_MaybeOwned CPDF_CMapManager::GetPredefinedCMap( - const CFX_ByteString& name, - bool bPromptCJK) { - auto it = m_CMaps.find(name); - if (it != m_CMaps.end()) - return CFX_MaybeOwned(it->second.get()); // Unowned. - - std::unique_ptr pCMap = LoadPredefinedCMap(name, bPromptCJK); - if (name.IsEmpty()) - return CFX_MaybeOwned(std::move(pCMap)); // Owned. - - CPDF_CMap* pUnowned = pCMap.get(); - m_CMaps[name] = std::move(pCMap); - return CFX_MaybeOwned(pUnowned); // Unowned. -} - -std::unique_ptr CPDF_CMapManager::LoadPredefinedCMap( - const CFX_ByteString& name, - bool bPromptCJK) { - auto pCMap = pdfium::MakeUnique(); - const FX_CHAR* pname = name.c_str(); - if (*pname == '/') - pname++; - - pCMap->LoadPredefined(this, pname, bPromptCJK); - return pCMap; -} - -CPDF_CID2UnicodeMap* CPDF_CMapManager::GetCID2UnicodeMap(CIDSet charset, - bool bPromptCJK) { - if (!m_CID2UnicodeMaps[charset]) - m_CID2UnicodeMaps[charset] = LoadCID2UnicodeMap(charset, bPromptCJK); - - return m_CID2UnicodeMaps[charset].get(); -} - -std::unique_ptr CPDF_CMapManager::LoadCID2UnicodeMap( - CIDSet charset, - bool bPromptCJK) { - auto pMap = pdfium::MakeUnique(); - pMap->Load(this, charset, bPromptCJK); - return pMap; -} - -CPDF_CMapParser::CPDF_CMapParser() - : m_pCMap(nullptr), m_Status(0), m_CodeSeq(0) {} - -CPDF_CMapParser::~CPDF_CMapParser() {} - -void CPDF_CMapParser::Initialize(CPDF_CMap* pCMap) { - m_pCMap = pCMap; - m_Status = 0; - m_CodeSeq = 0; - m_AddMaps.EstimateSize(0, 10240); -} - -void CPDF_CMapParser::ParseWord(const CFX_ByteStringC& word) { - if (word.IsEmpty()) { - return; - } - if (word == "begincidchar") { - m_Status = 1; - m_CodeSeq = 0; - } else if (word == "begincidrange") { - m_Status = 2; - m_CodeSeq = 0; - } else if (word == "endcidrange" || word == "endcidchar") { - m_Status = 0; - } else if (word == "/WMode") { - m_Status = 6; - } else if (word == "/Registry") { - m_Status = 3; - } else if (word == "/Ordering") { - m_Status = 4; - } else if (word == "/Supplement") { - m_Status = 5; - } else if (word == "begincodespacerange") { - m_Status = 7; - m_CodeSeq = 0; - } else if (word == "usecmap") { - } else if (m_Status == 1 || m_Status == 2) { - m_CodePoints[m_CodeSeq] = CMap_GetCode(word); - m_CodeSeq++; - uint32_t StartCode, EndCode; - uint16_t StartCID; - if (m_Status == 1) { - if (m_CodeSeq < 2) { - return; - } - EndCode = StartCode = m_CodePoints[0]; - StartCID = (uint16_t)m_CodePoints[1]; - } else { - if (m_CodeSeq < 3) { - return; - } - StartCode = m_CodePoints[0]; - EndCode = m_CodePoints[1]; - StartCID = (uint16_t)m_CodePoints[2]; - } - if (EndCode < 0x10000) { - for (uint32_t code = StartCode; code <= EndCode; code++) { - m_pCMap->m_pMapping[code] = (uint16_t)(StartCID + code - StartCode); - } - } else { - uint32_t buf[2]; - buf[0] = StartCode; - buf[1] = ((EndCode - StartCode) << 16) + StartCID; - m_AddMaps.AppendBlock(buf, sizeof buf); - } - m_CodeSeq = 0; - } else if (m_Status == 3) { - m_Status = 0; - } else if (m_Status == 4) { - m_pCMap->m_Charset = CharsetFromOrdering(CMap_GetString(word)); - m_Status = 0; - } else if (m_Status == 5) { - m_Status = 0; - } else if (m_Status == 6) { - m_pCMap->m_bVertical = CMap_GetCode(word) != 0; - m_Status = 0; - } else if (m_Status == 7) { - if (word == "endcodespacerange") { - uint32_t nSegs = pdfium::CollectionSize(m_CodeRanges); - if (nSegs > 1) { - m_pCMap->m_CodingScheme = CPDF_CMap::MixedFourBytes; - m_pCMap->m_nCodeRanges = nSegs; - FX_Free(m_pCMap->m_pLeadingBytes); - m_pCMap->m_pLeadingBytes = - FX_Alloc2D(uint8_t, nSegs, sizeof(CMap_CodeRange)); - FXSYS_memcpy(m_pCMap->m_pLeadingBytes, m_CodeRanges.data(), - nSegs * sizeof(CMap_CodeRange)); - } else if (nSegs == 1) { - m_pCMap->m_CodingScheme = (m_CodeRanges[0].m_CharSize == 2) - ? CPDF_CMap::TwoBytes - : CPDF_CMap::OneByte; - } - m_Status = 0; - } else { - if (word.GetLength() == 0 || word.GetAt(0) != '<') { - return; - } - if (m_CodeSeq % 2) { - CMap_CodeRange range; - if (CMap_GetCodeRange(range, m_LastWord.AsStringC(), word)) - m_CodeRanges.push_back(range); - } - m_CodeSeq++; - } - } - m_LastWord = word; -} - -// Static. -uint32_t CPDF_CMapParser::CMap_GetCode(const CFX_ByteStringC& word) { - pdfium::base::CheckedNumeric num = 0; - if (word.GetAt(0) == '<') { - for (int i = 1; i < word.GetLength() && std::isxdigit(word.GetAt(i)); ++i) { - num = num * 16 + FXSYS_toHexDigit(word.GetAt(i)); - if (!num.IsValid()) - return 0; - } - return num.ValueOrDie(); - } - - for (int i = 0; i < word.GetLength() && std::isdigit(word.GetAt(i)); ++i) { - num = num * 10 + FXSYS_toDecimalDigit(static_cast(word.GetAt(i))); - if (!num.IsValid()) - return 0; - } - return num.ValueOrDie(); -} - -// Static. -bool CPDF_CMapParser::CMap_GetCodeRange(CMap_CodeRange& range, - const CFX_ByteStringC& first, - const CFX_ByteStringC& second) { - if (first.GetLength() == 0 || first.GetAt(0) != '<') - return false; - - int i; - for (i = 1; i < first.GetLength(); ++i) { - if (first.GetAt(i) == '>') { - break; - } - } - range.m_CharSize = (i - 1) / 2; - if (range.m_CharSize > 4) - return false; - - for (i = 0; i < range.m_CharSize; ++i) { - uint8_t digit1 = first.GetAt(i * 2 + 1); - uint8_t digit2 = first.GetAt(i * 2 + 2); - range.m_Lower[i] = FXSYS_toHexDigit(digit1) * 16 + FXSYS_toHexDigit(digit2); - } - - uint32_t size = second.GetLength(); - for (i = 0; i < range.m_CharSize; ++i) { - uint8_t digit1 = ((uint32_t)i * 2 + 1 < size) - ? second.GetAt((FX_STRSIZE)i * 2 + 1) - : '0'; - uint8_t digit2 = ((uint32_t)i * 2 + 2 < size) - ? second.GetAt((FX_STRSIZE)i * 2 + 2) - : '0'; - range.m_Upper[i] = FXSYS_toHexDigit(digit1) * 16 + FXSYS_toHexDigit(digit2); - } - return true; -} - -CPDF_CMap::CPDF_CMap() { - m_Charset = CIDSET_UNKNOWN; - m_Coding = CIDCODING_UNKNOWN; - m_CodingScheme = TwoBytes; - m_bVertical = false; - m_bLoaded = false; - m_pMapping = nullptr; - m_pLeadingBytes = nullptr; - m_pAddMapping = nullptr; - m_pEmbedMap = nullptr; - m_nCodeRanges = 0; -} -CPDF_CMap::~CPDF_CMap() { - FX_Free(m_pMapping); - FX_Free(m_pAddMapping); - FX_Free(m_pLeadingBytes); -} - -bool CPDF_CMap::IsLoaded() const { - return m_bLoaded; -} - -bool CPDF_CMap::IsVertWriting() const { - return m_bVertical; -} - -void CPDF_CMap::LoadPredefined(CPDF_CMapManager* pMgr, - const CFX_ByteString& bsName, - bool bPromptCJK) { - m_PredefinedCMap = bsName; - if (m_PredefinedCMap == "Identity-H" || m_PredefinedCMap == "Identity-V") { - m_Coding = CIDCODING_CID; - m_bVertical = bsName[9] == 'V'; - m_bLoaded = true; - return; - } - CFX_ByteString cmapid = m_PredefinedCMap; - m_bVertical = cmapid.Right(1) == "V"; - if (cmapid.GetLength() > 2) { - cmapid = cmapid.Left(cmapid.GetLength() - 2); - } - const CPDF_PredefinedCMap* map = nullptr; - for (size_t i = 0; i < FX_ArraySize(g_PredefinedCMaps); ++i) { - if (cmapid == CFX_ByteStringC(g_PredefinedCMaps[i].m_pName)) { - map = &g_PredefinedCMaps[i]; - break; - } - } - if (!map) - return; - - m_Charset = map->m_Charset; - m_Coding = map->m_Coding; - m_CodingScheme = map->m_CodingScheme; - if (m_CodingScheme == MixedTwoBytes) { - m_pLeadingBytes = FX_Alloc(uint8_t, 256); - for (uint32_t i = 0; i < map->m_LeadingSegCount; ++i) { - const uint8_t* segs = map->m_LeadingSegs; - for (int b = segs[i * 2]; b <= segs[i * 2 + 1]; ++b) { - m_pLeadingBytes[b] = 1; - } - } - } - FPDFAPI_FindEmbeddedCMap(bsName, m_Charset, m_Coding, m_pEmbedMap); - if (!m_pEmbedMap) - return; - - m_bLoaded = true; -} - -void CPDF_CMap::LoadEmbedded(const uint8_t* pData, uint32_t size) { - m_pMapping = FX_Alloc(uint16_t, 65536); - CPDF_CMapParser parser; - parser.Initialize(this); - CPDF_SimpleParser syntax(pData, size); - while (1) { - CFX_ByteStringC word = syntax.GetWord(); - if (word.IsEmpty()) { - break; - } - parser.ParseWord(word); - } - if (m_CodingScheme == MixedFourBytes && parser.m_AddMaps.GetSize()) { - m_pAddMapping = FX_Alloc(uint8_t, parser.m_AddMaps.GetSize() + 4); - *(uint32_t*)m_pAddMapping = parser.m_AddMaps.GetSize() / 8; - FXSYS_memcpy(m_pAddMapping + 4, parser.m_AddMaps.GetBuffer(), - parser.m_AddMaps.GetSize()); - FXSYS_qsort(m_pAddMapping + 4, parser.m_AddMaps.GetSize() / 8, 8, - CompareDWORD); - } -} - -uint16_t CPDF_CMap::CIDFromCharCode(uint32_t charcode) const { - if (m_Coding == CIDCODING_CID) { - return (uint16_t)charcode; - } - if (m_pEmbedMap) { - return FPDFAPI_CIDFromCharCode(m_pEmbedMap, charcode); - } - if (!m_pMapping) { - return (uint16_t)charcode; - } - if (charcode >> 16) { - if (m_pAddMapping) { - void* found = FXSYS_bsearch(&charcode, m_pAddMapping + 4, - *(uint32_t*)m_pAddMapping, 8, CompareCID); - if (!found) - return 0; - return (uint16_t)(((uint32_t*)found)[1] % 65536 + charcode - - *(uint32_t*)found); - } - return 0; - } - return m_pMapping[charcode]; -} - -uint32_t CPDF_CMap::GetNextChar(const FX_CHAR* pString, - int nStrLen, - int& offset) const { - switch (m_CodingScheme) { - case OneByte: - return ((uint8_t*)pString)[offset++]; - case TwoBytes: - offset += 2; - return ((uint8_t*)pString)[offset - 2] * 256 + - ((uint8_t*)pString)[offset - 1]; - case MixedTwoBytes: { - uint8_t byte1 = ((uint8_t*)pString)[offset++]; - if (!m_pLeadingBytes[byte1]) { - return byte1; - } - uint8_t byte2 = ((uint8_t*)pString)[offset++]; - return byte1 * 256 + byte2; - } - case MixedFourBytes: { - uint8_t codes[4]; - int char_size = 1; - codes[0] = ((uint8_t*)pString)[offset++]; - CMap_CodeRange* pRanges = (CMap_CodeRange*)m_pLeadingBytes; - while (1) { - int ret = CheckCodeRange(codes, char_size, pRanges, m_nCodeRanges); - if (ret == 0) { - return 0; - } - if (ret == 2) { - uint32_t charcode = 0; - for (int i = 0; i < char_size; i++) { - charcode = (charcode << 8) + codes[i]; - } - return charcode; - } - if (char_size == 4 || offset == nStrLen) { - return 0; - } - codes[char_size++] = ((uint8_t*)pString)[offset++]; - } - break; - } - } - return 0; -} -int CPDF_CMap::GetCharSize(uint32_t charcode) const { - switch (m_CodingScheme) { - case OneByte: - return 1; - case TwoBytes: - return 2; - case MixedTwoBytes: - case MixedFourBytes: - if (charcode < 0x100) { - return 1; - } - if (charcode < 0x10000) { - return 2; - } - if (charcode < 0x1000000) { - return 3; - } - return 4; - } - return 1; -} -int CPDF_CMap::CountChar(const FX_CHAR* pString, int size) const { - switch (m_CodingScheme) { - case OneByte: - return size; - case TwoBytes: - return (size + 1) / 2; - case MixedTwoBytes: { - int count = 0; - for (int i = 0; i < size; i++) { - count++; - if (m_pLeadingBytes[((uint8_t*)pString)[i]]) { - i++; - } - } - return count; - } - case MixedFourBytes: { - int count = 0, offset = 0; - while (offset < size) { - GetNextChar(pString, size, offset); - count++; - } - return count; - } - } - return size; -} - -int CPDF_CMap::AppendChar(FX_CHAR* str, uint32_t charcode) const { - switch (m_CodingScheme) { - case OneByte: - str[0] = (uint8_t)charcode; - return 1; - case TwoBytes: - str[0] = (uint8_t)(charcode / 256); - str[1] = (uint8_t)(charcode % 256); - return 2; - case MixedTwoBytes: - case MixedFourBytes: - if (charcode < 0x100) { - CMap_CodeRange* pRanges = (CMap_CodeRange*)m_pLeadingBytes; - int iSize = GetCharSizeImpl(charcode, pRanges, m_nCodeRanges); - if (iSize == 0) { - iSize = 1; - } - if (iSize > 1) { - FXSYS_memset(str, 0, sizeof(uint8_t) * iSize); - } - str[iSize - 1] = (uint8_t)charcode; - return iSize; - } - if (charcode < 0x10000) { - str[0] = (uint8_t)(charcode >> 8); - str[1] = (uint8_t)charcode; - return 2; - } - if (charcode < 0x1000000) { - str[0] = (uint8_t)(charcode >> 16); - str[1] = (uint8_t)(charcode >> 8); - str[2] = (uint8_t)charcode; - return 3; - } - str[0] = (uint8_t)(charcode >> 24); - str[1] = (uint8_t)(charcode >> 16); - str[2] = (uint8_t)(charcode >> 8); - str[3] = (uint8_t)charcode; - return 4; - } - return 0; -} - -CPDF_CID2UnicodeMap::CPDF_CID2UnicodeMap() { - m_EmbeddedCount = 0; -} - -CPDF_CID2UnicodeMap::~CPDF_CID2UnicodeMap() {} - -bool CPDF_CID2UnicodeMap::IsLoaded() { - return m_EmbeddedCount != 0; -} - -FX_WCHAR CPDF_CID2UnicodeMap::UnicodeFromCID(uint16_t CID) { - if (m_Charset == CIDSET_UNICODE) { - return CID; - } - if (CID < m_EmbeddedCount) { - return m_pEmbeddedMap[CID]; - } - return 0; -} - -void CPDF_CID2UnicodeMap::Load(CPDF_CMapManager* pMgr, - CIDSet charset, - bool bPromptCJK) { - m_Charset = charset; - - CPDF_FontGlobals* pFontGlobals = - CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - m_pEmbeddedMap = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap; - m_EmbeddedCount = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count; -} - -CIDSet CharsetFromOrdering(const CFX_ByteStringC& ordering) { - for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) { - if (ordering == g_CharsetNames[charset]) - return CIDSetFromSizeT(charset); - } - return CIDSET_UNKNOWN; -} diff --git a/core/fpdfapi/font/fpdf_font_cid_unittest.cpp b/core/fpdfapi/font/fpdf_font_cid_unittest.cpp deleted file mode 100644 index 53f5e47f925df06a485bf689fe12855fdde56fec..0000000000000000000000000000000000000000 --- a/core/fpdfapi/font/fpdf_font_cid_unittest.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2015 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. - -#include "core/fpdfapi/font/font_int.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -bool uint_ranges_equal(uint8_t* a, uint8_t* b, size_t count) { - for (size_t i = 0; i < count; ++i) { - if (a[i] != b[i]) - return false; - } - return true; -} - -} // namespace - -TEST(fpdf_font_cid, CMap_GetCode) { - EXPECT_EQ(0u, CPDF_CMapParser::CMap_GetCode("")); - EXPECT_EQ(0u, CPDF_CMapParser::CMap_GetCode("<")); - EXPECT_EQ(194u, CPDF_CMapParser::CMap_GetCode("", "")); - EXPECT_EQ(5, range.m_CharSize); - - EXPECT_TRUE( - CPDF_CMapParser::CMap_GetCodeRange(range, "<12345678>", "<87654321>")); - EXPECT_EQ(4, range.m_CharSize); - { - uint8_t lower[4] = {18, 52, 86, 120}; - uint8_t upper[4] = {135, 101, 67, 33}; - EXPECT_TRUE(uint_ranges_equal(lower, range.m_Lower, range.m_CharSize)); - EXPECT_TRUE(uint_ranges_equal(upper, range.m_Upper, range.m_CharSize)); - } - - // Hex characters - EXPECT_TRUE(CPDF_CMapParser::CMap_GetCodeRange(range, "", "")); - EXPECT_EQ(1, range.m_CharSize); - EXPECT_EQ(161, range.m_Lower[0]); - EXPECT_EQ(243, range.m_Upper[0]); - - // The second string should return 0's if it is shorter - EXPECT_TRUE(CPDF_CMapParser::CMap_GetCodeRange(range, "", "")); - EXPECT_EQ(1, range.m_CharSize); - EXPECT_EQ(161, range.m_Lower[0]); - EXPECT_EQ(0, range.m_Upper[0]); -} diff --git a/core/fpdfapi/font/fpdf_font_unittest.cpp b/core/fpdfapi/font/fpdf_font_unittest.cpp deleted file mode 100644 index 977ae8a3bb03b57d5d476ca838ad37f107af027e..0000000000000000000000000000000000000000 --- a/core/fpdfapi/font/fpdf_font_unittest.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015 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. - -#include "core/fpdfapi/font/font_int.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fpdf_font, StringToCode) { - EXPECT_EQ(0u, CPDF_ToUnicodeMap::StringToCode("")); - EXPECT_EQ(194u, CPDF_ToUnicodeMap::StringToCode(" buf[count - 1].key) { - m_Buffer.AppendBlock(&pair, sizeof(_IntPair)); - return; - } - int low = 0, high = count - 1; - while (low <= high) { - int mid = (low + high) / 2; - if (buf[mid].key < key) { - low = mid + 1; - } else if (buf[mid].key > key) { - high = mid - 1; - } else { - buf[mid].value = value; - return; - } - } - m_Buffer.InsertBlock(low * sizeof(_IntPair), &pair, sizeof(_IntPair)); -} - -bool CFX_GlyphMap::Lookup(int key, int& value) { - void* pResult = FXSYS_bsearch(&key, m_Buffer.GetBuffer(), - m_Buffer.GetSize() / sizeof(_IntPair), - sizeof(_IntPair), _CompareInt); - if (!pResult) { - return false; - } - value = ((uint32_t*)pResult)[1]; - return true; -} - -CFX_CTTGSUBTable::CFX_CTTGSUBTable() - : m_bFeautureMapLoad(false), loaded(false) {} - -CFX_CTTGSUBTable::CFX_CTTGSUBTable(FT_Bytes gsub) - : m_bFeautureMapLoad(false), loaded(false) { - LoadGSUBTable(gsub); -} - -CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {} - -bool CFX_CTTGSUBTable::IsOk() const { - return loaded; -} - -bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) { - header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3]; - if (header.Version != 0x00010000) { - return false; - } - header.ScriptList = gsub[4] << 8 | gsub[5]; - header.FeatureList = gsub[6] << 8 | gsub[7]; - header.LookupList = gsub[8] << 8 | gsub[9]; - return Parse(&gsub[header.ScriptList], &gsub[header.FeatureList], - &gsub[header.LookupList]); -} - -bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum, - uint32_t* vglyphnum) { - uint32_t tag[] = { - (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 | - (uint8_t)'2', - (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 | - (uint8_t)'t', - }; - if (!m_bFeautureMapLoad) { - for (const auto& script : ScriptList.ScriptRecords) { - for (const auto& record : script.Script.LangSysRecords) { - for (const auto& index : record.LangSys.FeatureIndices) { - if (FeatureList.FeatureRecords[index].FeatureTag == tag[0] || - FeatureList.FeatureRecords[index].FeatureTag == tag[1]) { - m_featureSet.insert(index); - } - } - } - } - if (m_featureSet.empty()) { - int i = 0; - for (const auto& feature : FeatureList.FeatureRecords) { - if (feature.FeatureTag == tag[0] || feature.FeatureTag == tag[1]) - m_featureSet.insert(i); - ++i; - } - } - m_bFeautureMapLoad = true; - } - for (const auto& item : m_featureSet) { - if (GetVerticalGlyphSub(glyphnum, vglyphnum, - &FeatureList.FeatureRecords[item].Feature)) { - return true; - } - } - return false; -} - -bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum, - uint32_t* vglyphnum, - TFeature* Feature) { - for (int index : Feature->LookupListIndices) { - if (index < 0 || index >= pdfium::CollectionSize(LookupList.Lookups)) - continue; - - if (LookupList.Lookups[index].LookupType == 1 && - GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList.Lookups[index])) { - return true; - } - } - return false; -} - -bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum, - uint32_t* vglyphnum, - TLookup* Lookup) { - for (const auto& subTable : Lookup->SubTables) { - switch (subTable->SubstFormat) { - case 1: { - auto tbl1 = static_cast(subTable.get()); - if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) { - *vglyphnum = glyphnum + tbl1->DeltaGlyphID; - return true; - } - break; - } - case 2: { - auto tbl2 = static_cast(subTable.get()); - int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum); - if (index >= 0 && - index < pdfium::CollectionSize(tbl2->Substitutes)) { - *vglyphnum = tbl2->Substitutes[index]; - return true; - } - break; - } - } - } - return false; -} - -int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage, - uint32_t g) const { - if (!Coverage) - return -1; - - switch (Coverage->CoverageFormat) { - case 1: { - int i = 0; - TCoverageFormat1* c1 = (TCoverageFormat1*)Coverage; - for (const auto& glyph : c1->GlyphArray) { - if (static_cast(glyph) == g) - return i; - ++i; - } - return -1; - } - case 2: { - TCoverageFormat2* c2 = (TCoverageFormat2*)Coverage; - for (const auto& rangeRec : c2->RangeRecords) { - uint32_t s = rangeRec.Start; - uint32_t e = rangeRec.End; - uint32_t si = rangeRec.StartCoverageIndex; - if (s <= g && g <= e) - return si + g - s; - } - return -1; - } - } - return -1; -} - -uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const { - uint8_t ret = p[0]; - p += 1; - return ret; -} - -int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const { - uint16_t ret = p[0] << 8 | p[1]; - p += 2; - return *(int16_t*)&ret; -} - -uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const { - uint16_t ret = p[0] << 8 | p[1]; - p += 2; - return ret; -} - -int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const { - uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; - p += 4; - return *(int32_t*)&ret; -} - -uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const { - uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; - p += 4; - return ret; -} - -bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist, - FT_Bytes featurelist, - FT_Bytes lookuplist) { - ParseScriptList(scriptlist, &ScriptList); - ParseFeatureList(featurelist, &FeatureList); - ParseLookupList(lookuplist, &LookupList); - return true; -} - -void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw, TScriptList* rec) { - FT_Bytes sp = raw; - rec->ScriptRecords = std::vector(GetUInt16(sp)); - for (auto& scriptRec : rec->ScriptRecords) { - scriptRec.ScriptTag = GetUInt32(sp); - ParseScript(&raw[GetUInt16(sp)], &scriptRec.Script); - } -} - -void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScript* rec) { - FT_Bytes sp = raw; - rec->DefaultLangSys = GetUInt16(sp); - rec->LangSysRecords = std::vector(GetUInt16(sp)); - for (auto& sysRecord : rec->LangSysRecords) { - sysRecord.LangSysTag = GetUInt32(sp); - ParseLangSys(&raw[GetUInt16(sp)], &sysRecord.LangSys); - } -} - -void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSys* rec) { - FT_Bytes sp = raw; - rec->LookupOrder = GetUInt16(sp); - rec->ReqFeatureIndex = GetUInt16(sp); - rec->FeatureIndices = std::vector(GetUInt16(sp)); - for (auto& element : rec->FeatureIndices) - element = GetUInt16(sp); -} - -void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList* rec) { - FT_Bytes sp = raw; - rec->FeatureRecords = std::vector(GetUInt16(sp)); - for (auto& featureRec : rec->FeatureRecords) { - featureRec.FeatureTag = GetUInt32(sp); - ParseFeature(&raw[GetUInt16(sp)], &featureRec.Feature); - } -} - -void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature* rec) { - FT_Bytes sp = raw; - rec->FeatureParams = GetUInt16(sp); - rec->LookupListIndices = std::vector(GetUInt16(sp)); - for (auto& listIndex : rec->LookupListIndices) - listIndex = GetUInt16(sp); -} - -void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList* rec) { - FT_Bytes sp = raw; - rec->Lookups = std::vector(GetUInt16(sp)); - for (auto& lookup : rec->Lookups) - ParseLookup(&raw[GetUInt16(sp)], &lookup); -} - -void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) { - FT_Bytes sp = raw; - rec->LookupType = GetUInt16(sp); - rec->LookupFlag = GetUInt16(sp); - rec->SubTables = std::vector>(GetUInt16(sp)); - if (rec->LookupType != 1) - return; - - for (auto& subTable : rec->SubTables) - ParseSingleSubst(&raw[GetUInt16(sp)], &subTable); -} - -CFX_CTTGSUBTable::TCoverageFormatBase* CFX_CTTGSUBTable::ParseCoverage( - FT_Bytes raw) { - FT_Bytes sp = raw; - uint16_t format = GetUInt16(sp); - TCoverageFormatBase* rec = nullptr; - if (format == 1) { - rec = new TCoverageFormat1(); - ParseCoverageFormat1(raw, static_cast(rec)); - } else if (format == 2) { - rec = new TCoverageFormat2(); - ParseCoverageFormat2(raw, static_cast(rec)); - } - return rec; -} - -void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw, - TCoverageFormat1* rec) { - FT_Bytes sp = raw; - (void)GetUInt16(sp); - rec->GlyphArray = std::vector(GetUInt16(sp)); - for (auto& glyph : rec->GlyphArray) - glyph = GetUInt16(sp); -} - -void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw, - TCoverageFormat2* rec) { - FT_Bytes sp = raw; - (void)GetUInt16(sp); - rec->RangeRecords = std::vector(GetUInt16(sp)); - for (auto& rangeRec : rec->RangeRecords) { - rangeRec.Start = GetUInt16(sp); - rangeRec.End = GetUInt16(sp); - rangeRec.StartCoverageIndex = GetUInt16(sp); - } -} - -void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, - std::unique_ptr* rec) { - FT_Bytes sp = raw; - uint16_t Format = GetUInt16(sp); - switch (Format) { - case 1: - *rec = pdfium::MakeUnique(); - ParseSingleSubstFormat1(raw, - static_cast(rec->get())); - break; - case 2: - *rec = pdfium::MakeUnique(); - ParseSingleSubstFormat2(raw, - static_cast(rec->get())); - break; - } -} - -void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw, - TSingleSubstFormat1* rec) { - FT_Bytes sp = raw; - GetUInt16(sp); - uint16_t offset = GetUInt16(sp); - rec->Coverage.reset(ParseCoverage(&raw[offset])); - rec->DeltaGlyphID = GetInt16(sp); -} - -void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw, - TSingleSubstFormat2* rec) { - FT_Bytes sp = raw; - (void)GetUInt16(sp); - uint16_t offset = GetUInt16(sp); - rec->Coverage.reset(ParseCoverage(&raw[offset])); - rec->Substitutes = std::vector(GetUInt16(sp)); - for (auto& substitute : rec->Substitutes) - substitute = GetUInt16(sp); -} - -CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1() - : TCoverageFormatBase(1) {} - -CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {} - -CFX_CTTGSUBTable::TRangeRecord::TRangeRecord() - : Start(0), End(0), StartCoverageIndex(0) {} - -CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2() - : TCoverageFormatBase(2) {} - -CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {} - -CFX_CTTGSUBTable::TSingleSubstFormat1::TSingleSubstFormat1() - : TSubTableBase(1), DeltaGlyphID(0) {} - -CFX_CTTGSUBTable::TSingleSubstFormat1::~TSingleSubstFormat1() {} - -CFX_CTTGSUBTable::TSingleSubstFormat2::TSingleSubstFormat2() - : TSubTableBase(2) {} - -CFX_CTTGSUBTable::TSingleSubstFormat2::~TSingleSubstFormat2() {} - -CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {} - -CFX_CTTGSUBTable::TLookup::~TLookup() {} - -CFX_CTTGSUBTable::TScript::TScript() : DefaultLangSys(0) {} - -CFX_CTTGSUBTable::TScript::~TScript() {} - -CFX_CTTGSUBTable::TScriptList::TScriptList() {} - -CFX_CTTGSUBTable::TScriptList::~TScriptList() {} - -CFX_CTTGSUBTable::TFeature::TFeature() : FeatureParams(0) {} - -CFX_CTTGSUBTable::TFeature::~TFeature() {} - -CFX_CTTGSUBTable::TFeatureList::TFeatureList() {} - -CFX_CTTGSUBTable::TFeatureList::~TFeatureList() {} - -CFX_CTTGSUBTable::TLookupList::TLookupList() {} - -CFX_CTTGSUBTable::TLookupList::~TLookupList() {} - -CFX_CTTGSUBTable::TLangSys::TLangSys() : LookupOrder(0), ReqFeatureIndex(0) {} - -CFX_CTTGSUBTable::TLangSys::~TLangSys() {} diff --git a/core/fpdfapi/font/ttgsubtable.h b/core/fpdfapi/font/ttgsubtable.h deleted file mode 100644 index f92726954078710dfdd4597ea8dc171b52bfa1e4..0000000000000000000000000000000000000000 --- a/core/fpdfapi/font/ttgsubtable.h +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FPDFAPI_FONT_TTGSUBTABLE_H_ -#define CORE_FPDFAPI_FONT_TTGSUBTABLE_H_ - -#include - -#include -#include -#include - -#include "core/fxcrt/fx_basic.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" - -class CFX_GlyphMap { - public: - CFX_GlyphMap(); - ~CFX_GlyphMap(); - - void SetAt(int key, int value); - bool Lookup(int key, int& value); - - protected: - CFX_BinaryBuf m_Buffer; -}; - -class CFX_CTTGSUBTable { - public: - CFX_CTTGSUBTable(); - explicit CFX_CTTGSUBTable(FT_Bytes gsub); - virtual ~CFX_CTTGSUBTable(); - - bool IsOk() const; - bool LoadGSUBTable(FT_Bytes gsub); - bool GetVerticalGlyph(uint32_t glyphnum, uint32_t* vglyphnum); - - private: - struct tt_gsub_header { - uint32_t Version; - uint16_t ScriptList; - uint16_t FeatureList; - uint16_t LookupList; - }; - - struct TLangSys { - TLangSys(); - ~TLangSys(); - - uint16_t LookupOrder; - uint16_t ReqFeatureIndex; - std::vector FeatureIndices; - - private: - TLangSys(const TLangSys&) = delete; - TLangSys& operator=(const TLangSys&) = delete; - }; - - struct TLangSysRecord { - TLangSysRecord() : LangSysTag(0) {} - - uint32_t LangSysTag; - TLangSys LangSys; - - private: - TLangSysRecord(const TLangSysRecord&) = delete; - TLangSysRecord& operator=(const TLangSysRecord&) = delete; - }; - - struct TScript { - TScript(); - ~TScript(); - - uint16_t DefaultLangSys; - std::vector LangSysRecords; - - private: - TScript(const TScript&) = delete; - TScript& operator=(const TScript&) = delete; - }; - - struct TScriptRecord { - TScriptRecord() : ScriptTag(0) {} - - uint32_t ScriptTag; - TScript Script; - - private: - TScriptRecord(const TScriptRecord&) = delete; - TScriptRecord& operator=(const TScriptRecord&) = delete; - }; - - struct TScriptList { - TScriptList(); - ~TScriptList(); - - std::vector ScriptRecords; - - private: - TScriptList(const TScriptList&) = delete; - TScriptList& operator=(const TScriptList&) = delete; - }; - - struct TFeature { - TFeature(); - ~TFeature(); - - uint16_t FeatureParams; - std::vector LookupListIndices; - - private: - TFeature(const TFeature&) = delete; - TFeature& operator=(const TFeature&) = delete; - }; - - struct TFeatureRecord { - TFeatureRecord() : FeatureTag(0) {} - - uint32_t FeatureTag; - TFeature Feature; - - private: - TFeatureRecord(const TFeatureRecord&) = delete; - TFeatureRecord& operator=(const TFeatureRecord&) = delete; - }; - - struct TFeatureList { - TFeatureList(); - ~TFeatureList(); - - std::vector FeatureRecords; - - private: - TFeatureList(const TFeatureList&) = delete; - TFeatureList& operator=(const TFeatureList&) = delete; - }; - - enum TLookupFlag { - LOOKUPFLAG_RightToLeft = 0x0001, - LOOKUPFLAG_IgnoreBaseGlyphs = 0x0002, - LOOKUPFLAG_IgnoreLigatures = 0x0004, - LOOKUPFLAG_IgnoreMarks = 0x0008, - LOOKUPFLAG_Reserved = 0x00F0, - LOOKUPFLAG_MarkAttachmentType = 0xFF00, - }; - - struct TCoverageFormatBase { - TCoverageFormatBase() : CoverageFormat(0) {} - explicit TCoverageFormatBase(uint16_t format) : CoverageFormat(format) {} - virtual ~TCoverageFormatBase() {} - - uint16_t CoverageFormat; - CFX_GlyphMap m_glyphMap; - - private: - TCoverageFormatBase(const TCoverageFormatBase&); - TCoverageFormatBase& operator=(const TCoverageFormatBase&); - }; - - struct TCoverageFormat1 : public TCoverageFormatBase { - TCoverageFormat1(); - ~TCoverageFormat1() override; - - std::vector GlyphArray; - - private: - TCoverageFormat1(const TCoverageFormat1&) = delete; - TCoverageFormat1& operator=(const TCoverageFormat1&) = delete; - }; - - struct TRangeRecord { - TRangeRecord(); - - friend bool operator>(const TRangeRecord& r1, const TRangeRecord& r2) { - return r1.Start > r2.Start; - } - - uint16_t Start; - uint16_t End; - uint16_t StartCoverageIndex; - - private: - TRangeRecord(const TRangeRecord&) = delete; - }; - - struct TCoverageFormat2 : public TCoverageFormatBase { - TCoverageFormat2(); - ~TCoverageFormat2() override; - - std::vector RangeRecords; - - private: - TCoverageFormat2(const TCoverageFormat2&) = delete; - TCoverageFormat2& operator=(const TCoverageFormat2&) = delete; - }; - - struct TDevice { - TDevice() : StartSize(0), EndSize(0), DeltaFormat(0) {} - - uint16_t StartSize; - uint16_t EndSize; - uint16_t DeltaFormat; - - private: - TDevice(const TDevice&) = delete; - TDevice& operator=(const TDevice&) = delete; - }; - - struct TSubTableBase { - TSubTableBase() : SubstFormat(0) {} - explicit TSubTableBase(uint16_t format) : SubstFormat(format) {} - virtual ~TSubTableBase() {} - - uint16_t SubstFormat; - - private: - TSubTableBase(const TSubTableBase&) = delete; - TSubTableBase& operator=(const TSubTableBase&) = delete; - }; - - struct TSingleSubstFormat1 : public TSubTableBase { - TSingleSubstFormat1(); - ~TSingleSubstFormat1() override; - - std::unique_ptr Coverage; - int16_t DeltaGlyphID; - - private: - TSingleSubstFormat1(const TSingleSubstFormat1&) = delete; - TSingleSubstFormat1& operator=(const TSingleSubstFormat1&) = delete; - }; - - struct TSingleSubstFormat2 : public TSubTableBase { - TSingleSubstFormat2(); - ~TSingleSubstFormat2() override; - - std::unique_ptr Coverage; - std::vector Substitutes; - - private: - TSingleSubstFormat2(const TSingleSubstFormat2&) = delete; - TSingleSubstFormat2& operator=(const TSingleSubstFormat2&) = delete; - }; - - struct TLookup { - TLookup(); - ~TLookup(); - - uint16_t LookupType; - uint16_t LookupFlag; - std::vector> SubTables; - - private: - TLookup(const TLookup&) = delete; - TLookup& operator=(const TLookup&) = delete; - }; - - struct TLookupList { - TLookupList(); - ~TLookupList(); - - std::vector Lookups; - - private: - TLookupList(const TLookupList&) = delete; - TLookupList& operator=(const TLookupList&) = delete; - }; - - bool Parse(FT_Bytes scriptlist, FT_Bytes featurelist, FT_Bytes lookuplist); - void ParseScriptList(FT_Bytes raw, TScriptList* rec); - void ParseScript(FT_Bytes raw, TScript* rec); - void ParseLangSys(FT_Bytes raw, TLangSys* rec); - void ParseFeatureList(FT_Bytes raw, TFeatureList* rec); - void ParseFeature(FT_Bytes raw, TFeature* rec); - void ParseLookupList(FT_Bytes raw, TLookupList* rec); - void ParseLookup(FT_Bytes raw, TLookup* rec); - TCoverageFormatBase* ParseCoverage(FT_Bytes raw); - void ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1* rec); - void ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2* rec); - void ParseSingleSubst(FT_Bytes raw, std::unique_ptr* rec); - void ParseSingleSubstFormat1(FT_Bytes raw, TSingleSubstFormat1* rec); - void ParseSingleSubstFormat2(FT_Bytes raw, TSingleSubstFormat2* rec); - - bool GetVerticalGlyphSub(uint32_t glyphnum, - uint32_t* vglyphnum, - TFeature* Feature); - bool GetVerticalGlyphSub2(uint32_t glyphnum, - uint32_t* vglyphnum, - TLookup* Lookup); - int GetCoverageIndex(TCoverageFormatBase* Coverage, uint32_t g) const; - - uint8_t GetUInt8(FT_Bytes& p) const; - int16_t GetInt16(FT_Bytes& p) const; - uint16_t GetUInt16(FT_Bytes& p) const; - int32_t GetInt32(FT_Bytes& p) const; - uint32_t GetUInt32(FT_Bytes& p) const; - - std::set m_featureSet; - bool m_bFeautureMapLoad; - bool loaded; - tt_gsub_header header; - TScriptList ScriptList; - TFeatureList FeatureList; - TLookupList LookupList; -}; - -#endif // CORE_FPDFAPI_FONT_TTGSUBTABLE_H_ diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp index 282a47fe29edd79b4a598dec4254cc6c49fb4914..afc87a2b5aac358de1a3a071de3cd364132d3ec9 100644 --- a/core/fpdfapi/page/cpdf_allstates.cpp +++ b/core/fpdfapi/page/cpdf_allstates.cpp @@ -10,18 +10,10 @@ #include "core/fpdfapi/page/cpdf_pageobjectholder.h" #include "core/fpdfapi/page/cpdf_streamcontentparser.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fxge/cfx_graphstatedata.h" - -namespace { - -FX_FLOAT ClipFloat(FX_FLOAT f) { - return std::max(0.0f, std::min(1.0f, f)); -} - -} // namespace +#include "third_party/base/stl_util.h" CPDF_AllStates::CPDF_AllStates() : m_TextLeading(0), m_TextRise(0), m_TextHorzScale(1.0f) {} @@ -40,16 +32,14 @@ void CPDF_AllStates::Copy(const CPDF_AllStates& src) { m_TextHorzScale = src.m_TextHorzScale; } -void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, - FX_FLOAT phase, - FX_FLOAT scale) { +void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, float phase, float scale) { m_GraphState.SetLineDash(pArray, phase, scale); } void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS, CPDF_StreamContentParser* pParser) { for (const auto& it : *pGS) { - const CFX_ByteString& key_str = it.first; + const ByteString& key_str = it.first; CPDF_Object* pElement = it.second.get(); CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr; if (!pObject) @@ -119,10 +109,12 @@ void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS, } break; case FXBSTR_ID('C', 'A', 0, 0): - m_GeneralState.SetStrokeAlpha(ClipFloat(pObject->GetNumber())); + m_GeneralState.SetStrokeAlpha( + pdfium::clamp(pObject->GetNumber(), 0.0f, 1.0f)); break; case FXBSTR_ID('c', 'a', 0, 0): - m_GeneralState.SetFillAlpha(ClipFloat(pObject->GetNumber())); + m_GeneralState.SetFillAlpha( + pdfium::clamp(pObject->GetNumber(), 0.0f, 1.0f)); break; case FXBSTR_ID('O', 'P', 0, 0): m_GeneralState.SetStrokeOP(!!pObject->GetInteger()); diff --git a/core/fpdfapi/page/cpdf_allstates.h b/core/fpdfapi/page/cpdf_allstates.h index dad1b8502bae929c2e224d588981339898b03b83..730003a96a3065d1802b9d3530dd60312b02b162 100644 --- a/core/fpdfapi/page/cpdf_allstates.h +++ b/core/fpdfapi/page/cpdf_allstates.h @@ -22,16 +22,16 @@ class CPDF_AllStates : public CPDF_GraphicStates { void Copy(const CPDF_AllStates& src); void ProcessExtGS(CPDF_Dictionary* pGS, CPDF_StreamContentParser* pParser); - void SetLineDash(CPDF_Array*, FX_FLOAT, FX_FLOAT scale); + void SetLineDash(CPDF_Array*, float, float scale); CFX_Matrix m_TextMatrix; CFX_Matrix m_CTM; CFX_Matrix m_ParentMatrix; CFX_PointF m_TextPos; CFX_PointF m_TextLinePos; - FX_FLOAT m_TextLeading; - FX_FLOAT m_TextRise; - FX_FLOAT m_TextHorzScale; + float m_TextLeading; + float m_TextRise; + float m_TextHorzScale; }; #endif // CORE_FPDFAPI_PAGE_CPDF_ALLSTATES_H_ diff --git a/core/fpdfapi/page/cpdf_clippath.cpp b/core/fpdfapi/page/cpdf_clippath.cpp index 714b56bff3bd3b2affa2f4bf077b606d5a50e1e3..465a2d35498ed670d1df859fd318786eb5022768 100644 --- a/core/fpdfapi/page/cpdf_clippath.cpp +++ b/core/fpdfapi/page/cpdf_clippath.cpp @@ -10,7 +10,6 @@ #include "core/fpdfapi/page/cpdf_path.h" #include "core/fpdfapi/page/cpdf_textobject.h" -#include "third_party/base/stl_util.h" #define FPDF_CLIPPATH_MAX_TEXTS 1024 @@ -20,8 +19,8 @@ CPDF_ClipPath::CPDF_ClipPath(const CPDF_ClipPath& that) : m_Ref(that.m_Ref) {} CPDF_ClipPath::~CPDF_ClipPath() {} -uint32_t CPDF_ClipPath::GetPathCount() const { - return pdfium::CollectionSize(m_Ref.GetObject()->m_PathAndTypeList); +size_t CPDF_ClipPath::GetPathCount() const { + return m_Ref.GetObject()->m_PathAndTypeList.size(); } CPDF_Path CPDF_ClipPath::GetPath(size_t i) const { @@ -32,8 +31,8 @@ uint8_t CPDF_ClipPath::GetClipType(size_t i) const { return m_Ref.GetObject()->m_PathAndTypeList[i].second; } -uint32_t CPDF_ClipPath::GetTextCount() const { - return pdfium::CollectionSize(m_Ref.GetObject()->m_TextList); +size_t CPDF_ClipPath::GetTextCount() const { + return m_Ref.GetObject()->m_TextList.size(); } CPDF_TextObject* CPDF_ClipPath::GetText(size_t i) const { @@ -43,36 +42,33 @@ CPDF_TextObject* CPDF_ClipPath::GetText(size_t i) const { CFX_FloatRect CPDF_ClipPath::GetClipBox() const { CFX_FloatRect rect; bool bStarted = false; - int count = GetPathCount(); - if (count) { + if (GetPathCount() > 0) { rect = GetPath(0).GetBoundingBox(); - for (int i = 1; i < count; i++) { + for (size_t i = 1; i < GetPathCount(); ++i) { CFX_FloatRect path_rect = GetPath(i).GetBoundingBox(); rect.Intersect(path_rect); } bStarted = true; } - count = GetTextCount(); - if (count) { - CFX_FloatRect layer_rect; - bool bLayerStarted = false; - for (int i = 0; i < count; i++) { - CPDF_TextObject* pTextObj = GetText(i); - if (!pTextObj) { - if (!bStarted) { - rect = layer_rect; - bStarted = true; - } else { - rect.Intersect(layer_rect); - } - bLayerStarted = false; + + CFX_FloatRect layer_rect; + bool bLayerStarted = false; + for (size_t i = 0; i < GetTextCount(); ++i) { + CPDF_TextObject* pTextObj = GetText(i); + if (!pTextObj) { + if (!bStarted) { + rect = layer_rect; + bStarted = true; + } else { + rect.Intersect(layer_rect); + } + bLayerStarted = false; + } else { + if (!bLayerStarted) { + layer_rect = CFX_FloatRect(pTextObj->GetBBox(nullptr)); + bLayerStarted = true; } else { - if (!bLayerStarted) { - layer_rect = CFX_FloatRect(pTextObj->GetBBox(nullptr)); - bLayerStarted = true; - } else { - layer_rect.Union(CFX_FloatRect(pTextObj->GetBBox(nullptr))); - } + layer_rect.Union(CFX_FloatRect(pTextObj->GetBBox(nullptr))); } } } diff --git a/core/fpdfapi/page/cpdf_clippath.h b/core/fpdfapi/page/cpdf_clippath.h index dd44cb250e969c8506ca7b78e005e27c86d45c71..91a25cda1a4e26b7ec723edfe70dacc23fda6b0b 100644 --- a/core/fpdfapi/page/cpdf_clippath.h +++ b/core/fpdfapi/page/cpdf_clippath.h @@ -12,9 +12,8 @@ #include #include "core/fpdfapi/page/cpdf_path.h" -#include "core/fxcrt/cfx_shared_copy_on_write.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/shared_copy_on_write.h" class CPDF_Path; class CPDF_TextObject; @@ -28,16 +27,16 @@ class CPDF_ClipPath { void Emplace() { m_Ref.Emplace(); } void SetNull() { m_Ref.SetNull(); } - explicit operator bool() const { return !!m_Ref; } + bool HasRef() const { return !!m_Ref; } bool operator==(const CPDF_ClipPath& that) const { return m_Ref == that.m_Ref; } bool operator!=(const CPDF_ClipPath& that) const { return !(*this == that); } - uint32_t GetPathCount() const; + size_t GetPathCount() const; CPDF_Path GetPath(size_t i) const; uint8_t GetClipType(size_t i) const; - uint32_t GetTextCount() const; + size_t GetTextCount() const; CPDF_TextObject* GetText(size_t i) const; CFX_FloatRect GetClipBox() const; void AppendPath(CPDF_Path path, uint8_t type, bool bAutoMerge); @@ -45,19 +44,19 @@ class CPDF_ClipPath { void Transform(const CFX_Matrix& matrix); private: - class PathData { + class PathData : public Retainable { public: using PathAndTypeData = std::pair; PathData(); PathData(const PathData& that); - ~PathData(); + ~PathData() override; std::vector m_PathAndTypeList; std::vector> m_TextList; }; - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; #endif // CORE_FPDFAPI_PAGE_CPDF_CLIPPATH_H_ diff --git a/core/fpdfapi/page/cpdf_color.cpp b/core/fpdfapi/page/cpdf_color.cpp index 4ba28ce3140f5d62307fae6f17854c316bf39578..d364e8e82292d4d0da7f6e7309628e2df947c55c 100644 --- a/core/fpdfapi/page/cpdf_color.cpp +++ b/core/fpdfapi/page/cpdf_color.cpp @@ -7,12 +7,11 @@ #include "core/fpdfapi/page/cpdf_color.h" #include "core/fpdfapi/page/cpdf_docpagedata.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fxcrt/fx_system.h" -CPDF_Color::CPDF_Color() : m_pCS(nullptr), m_pBuffer(nullptr) {} +CPDF_Color::CPDF_Color() {} CPDF_Color::~CPDF_Color() { ReleaseBuffer(); @@ -20,18 +19,18 @@ CPDF_Color::~CPDF_Color() { } bool CPDF_Color::IsPattern() const { - return m_pCS && m_pCS->GetFamily() == PDFCS_PATTERN; + return m_pCS && IsPatternInternal(); } void CPDF_Color::ReleaseBuffer() { if (!m_pBuffer) return; - if (m_pCS->GetFamily() == PDFCS_PATTERN) { - PatternValue* pvalue = (PatternValue*)m_pBuffer; + if (IsPatternInternal()) { + PatternValue* pvalue = reinterpret_cast(m_pBuffer); CPDF_Pattern* pPattern = pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->get() : nullptr; - if (pPattern && pPattern->document()) { + if (pPattern) { CPDF_DocPageData* pPageData = pPattern->document()->GetPageData(); if (pPageData) pPageData->ReleasePattern(pPattern->pattern_obj()); @@ -42,10 +41,22 @@ void CPDF_Color::ReleaseBuffer() { } void CPDF_Color::ReleaseColorSpace() { - if (m_pCS && m_pCS->m_pDocument) { - m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray()); - m_pCS = nullptr; - } + if (!m_pCS) + return; + + CPDF_Document* pDoc = m_pCS->GetDocument(); + if (!pDoc) + return; + + auto* pPageData = pDoc->GetPageData(); + if (pPageData) + pPageData->ReleaseColorSpace(m_pCS->GetArray()); + + m_pCS = nullptr; +} + +bool CPDF_Color::IsPatternInternal() const { + return m_pCS->GetFamily() == PDFCS_PATTERN; } void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS) { @@ -61,21 +72,23 @@ void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS) { ReleaseColorSpace(); m_pCS = pCS; - if (m_pCS) { + if (pCS) { m_pBuffer = pCS->CreateBuf(); pCS->GetDefaultColor(m_pBuffer); } } -void CPDF_Color::SetValue(FX_FLOAT* comps) { +void CPDF_Color::SetValue(const float* comps) { if (!m_pBuffer) return; - if (m_pCS->GetFamily() != PDFCS_PATTERN) - FXSYS_memcpy(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT)); + if (!IsPatternInternal()) + memcpy(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(float)); } -void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps) { - if (ncomps > MAX_PATTERN_COLORCOMPS) +void CPDF_Color::SetValue(CPDF_Pattern* pPattern, + const float* comps, + uint32_t ncomps) { + if (ncomps > kMaxPatternColorComps) return; if (!IsPattern()) { @@ -85,19 +98,18 @@ void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps) { } CPDF_DocPageData* pDocPageData = nullptr; - PatternValue* pvalue = (PatternValue*)m_pBuffer; - if (pvalue->m_pPattern && pvalue->m_pPattern->document()) { + PatternValue* pvalue = reinterpret_cast(m_pBuffer); + if (pvalue->m_pPattern) { pDocPageData = pvalue->m_pPattern->document()->GetPageData(); - if (pDocPageData) - pDocPageData->ReleasePattern(pvalue->m_pPattern->pattern_obj()); + pDocPageData->ReleasePattern(pvalue->m_pPattern->pattern_obj()); } pvalue->m_nComps = ncomps; pvalue->m_pPattern = pPattern; if (ncomps) - FXSYS_memcpy(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT)); + memcpy(pvalue->m_Comps, comps, ncomps * sizeof(float)); pvalue->m_pCountedPattern = nullptr; - if (pPattern && pPattern->document()) { + if (pPattern) { if (!pDocPageData) pDocPageData = pPattern->document()->GetPageData(); @@ -109,47 +121,51 @@ void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps) { void CPDF_Color::Copy(const CPDF_Color* pSrc) { ReleaseBuffer(); ReleaseColorSpace(); - m_pCS = pSrc->m_pCS; - if (m_pCS && m_pCS->m_pDocument) { - CPDF_Array* pArray = m_pCS->GetArray(); - if (pArray) - m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray); - } if (!m_pCS) return; + CPDF_Document* pDoc = m_pCS->GetDocument(); + CPDF_Array* pArray = m_pCS->GetArray(); + if (pDoc && pArray) { + m_pCS = pDoc->GetPageData()->GetCopiedColorSpace(pArray); + if (!m_pCS) + return; + } m_pBuffer = m_pCS->CreateBuf(); - FXSYS_memcpy(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize()); - if (m_pCS->GetFamily() != PDFCS_PATTERN) + memcpy(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize()); + if (!IsPatternInternal()) return; PatternValue* pValue = reinterpret_cast(m_pBuffer); CPDF_Pattern* pPattern = pValue->m_pPattern; - if (pPattern && pPattern->document()) { - pValue->m_pPattern = pPattern->document()->GetPageData()->GetPattern( - pPattern->pattern_obj(), false, pPattern->parent_matrix()); - } + if (!pPattern) + return; + + pValue->m_pPattern = pPattern->document()->GetPageData()->GetPattern( + pPattern->pattern_obj(), false, pPattern->parent_matrix()); } -bool CPDF_Color::GetRGB(int& R, int& G, int& B) const { +bool CPDF_Color::GetRGB(int* R, int* G, int* B) const { if (!m_pCS || !m_pBuffer) return false; - FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f; - if (!m_pCS->GetRGB(m_pBuffer, r, g, b)) + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + if (!m_pCS->GetRGB(m_pBuffer, &r, &g, &b)) return false; - R = (int32_t)(r * 255 + 0.5f); - G = (int32_t)(g * 255 + 0.5f); - B = (int32_t)(b * 255 + 0.5f); + *R = static_cast(r * 255 + 0.5f); + *G = static_cast(g * 255 + 0.5f); + *B = static_cast(b * 255 + 0.5f); return true; } CPDF_Pattern* CPDF_Color::GetPattern() const { - if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN) + if (!m_pBuffer || !IsPatternInternal()) return nullptr; - PatternValue* pvalue = (PatternValue*)m_pBuffer; + PatternValue* pvalue = reinterpret_cast(m_pBuffer); return pvalue->m_pPattern; } diff --git a/core/fpdfapi/page/cpdf_color.h b/core/fpdfapi/page/cpdf_color.h index e81b53105504a7fe184d8bb2ac97b0ec0a363701..2eac7cfacb479721b337d0246cb7e7d99821c0fe 100644 --- a/core/fpdfapi/page/cpdf_color.h +++ b/core/fpdfapi/page/cpdf_color.h @@ -23,19 +23,23 @@ class CPDF_Color { void Copy(const CPDF_Color* pSrc); void SetColorSpace(CPDF_ColorSpace* pCS); - void SetValue(FX_FLOAT* comp); - void SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comp, int ncomps); + void SetValue(const float* comp); + void SetValue(CPDF_Pattern* pPattern, const float* comp, uint32_t ncomps); - bool GetRGB(int& R, int& G, int& B) const; + bool GetRGB(int* R, int* G, int* B) const; CPDF_Pattern* GetPattern() const; const CPDF_ColorSpace* GetColorSpace() const { return m_pCS; } protected: void ReleaseBuffer(); void ReleaseColorSpace(); + bool IsPatternInternal() const; - CPDF_ColorSpace* m_pCS; - FX_FLOAT* m_pBuffer; + // TODO(thestig): Convert this to a smart pointer or vector. + // |m_pBuffer| is created by |m_pCS|, so if it is non-null, then so is + // |m_pCS|. + float* m_pBuffer = nullptr; + CPDF_ColorSpace* m_pCS = nullptr; }; #endif // CORE_FPDFAPI_PAGE_CPDF_COLOR_H_ diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp index 6cd0075e8e7fdd7a27f8ce487277795e3fad9d44..fde0ed4dad9e7f136417e808be11cf176f390fe5 100644 --- a/core/fpdfapi/page/cpdf_colorspace.cpp +++ b/core/fpdfapi/page/cpdf_colorspace.cpp @@ -6,12 +6,20 @@ #include "core/fpdfapi/page/cpdf_colorspace.h" +#include +#include #include #include +#include #include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/page/cpdf_devicecs.h" #include "core/fpdfapi/page/cpdf_docpagedata.h" +#include "core/fpdfapi/page/cpdf_function.h" +#include "core/fpdfapi/page/cpdf_iccprofile.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" +#include "core/fpdfapi/page/cpdf_pattern.h" +#include "core/fpdfapi/page/cpdf_patterncs.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" @@ -20,9 +28,13 @@ #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfdoc/cpdf_action.h" +#include "core/fxcodec/codec/ccodec_iccmodule.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" +#include "core/fxcrt/cfx_fixedbufgrow.h" #include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/maybe_owned.h" +#include "third_party/base/stl_util.h" namespace { @@ -62,57 +74,48 @@ const uint8_t g_sRGBSamples2[] = { class CPDF_CalGray : public CPDF_ColorSpace { public: explicit CPDF_CalGray(CPDF_Document* pDoc); + ~CPDF_CalGray() override {} - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; - - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - bool SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const override; - + // CPDF_ColorSpace: + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, int image_width, int image_height, - bool bTransMask = false) const override; + bool bTransMask) const override; private: - FX_FLOAT m_WhitePoint[3]; - FX_FLOAT m_BlackPoint[3]; - FX_FLOAT m_Gamma; + float m_WhitePoint[3]; + float m_BlackPoint[3]; + float m_Gamma; }; class CPDF_CalRGB : public CPDF_ColorSpace { public: explicit CPDF_CalRGB(CPDF_Document* pDoc); + ~CPDF_CalRGB() override {} - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - bool SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, int image_width, int image_height, - bool bTransMask = false) const override; + bool bTransMask) const override; - FX_FLOAT m_WhitePoint[3]; - FX_FLOAT m_BlackPoint[3]; - FX_FLOAT m_Gamma[3]; - FX_FLOAT m_Matrix[9]; + float m_WhitePoint[3]; + float m_BlackPoint[3]; + float m_Gamma[3]; + float m_Matrix[9]; bool m_bGamma; bool m_bMatrix; }; @@ -120,32 +123,28 @@ class CPDF_CalRGB : public CPDF_ColorSpace { class CPDF_LabCS : public CPDF_ColorSpace { public: explicit CPDF_LabCS(CPDF_Document* pDoc); + ~CPDF_LabCS() override {} - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; void GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const override; - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - bool SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const override; + float* value, + float* min, + float* max) const override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, int image_width, int image_height, - bool bTransMask = false) const override; + bool bTransMask) const override; - FX_FLOAT m_WhitePoint[3]; - FX_FLOAT m_BlackPoint[3]; - FX_FLOAT m_Ranges[4]; + float m_WhitePoint[3]; + float m_BlackPoint[3]; + float m_Ranges[4]; }; class CPDF_ICCBasedCS : public CPDF_ColorSpace { @@ -153,35 +152,36 @@ class CPDF_ICCBasedCS : public CPDF_ColorSpace { explicit CPDF_ICCBasedCS(CPDF_Document* pDoc); ~CPDF_ICCBasedCS() override; - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; - - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - bool SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const override; - - bool v_GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const override; - + // CPDF_ColorSpace: + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void EnableStdConversion(bool bEnabled) override; void TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, int image_width, int image_height, - bool bTransMask = false) const override; + bool bTransMask) const override; - CFX_MaybeOwned m_pAlterCS; - CPDF_IccProfile* m_pProfile; - uint8_t* m_pCache; - FX_FLOAT* m_pRanges; + bool IsSRGB() const { return m_pProfile->IsSRGB(); } + + private: + // If no valid ICC profile or using sRGB, try looking for an alternate. + bool FindAlternateProfile(CPDF_Document* pDoc, + CPDF_Dictionary* pDict, + std::set* pVisited, + uint32_t nExpectedComponents); + static CPDF_ColorSpace* GetStockAlternateProfile(uint32_t nComponents); + static bool IsValidComponents(int32_t nComps); + static std::vector GetRanges(CPDF_Dictionary* pDict, + uint32_t nComponents); + + MaybeOwned m_pAlterCS; + RetainPtr m_pProfile; + mutable std::unique_ptr m_pCache; + std::vector m_pRanges; }; class CPDF_IndexedCS : public CPDF_ColorSpace { @@ -189,22 +189,20 @@ class CPDF_IndexedCS : public CPDF_ColorSpace { explicit CPDF_IndexedCS(CPDF_Document* pDoc); ~CPDF_IndexedCS() override; - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - CPDF_ColorSpace* GetBaseCS() const override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void EnableStdConversion(bool bEnabled) override; - CPDF_ColorSpace* m_pBaseCS; - CPDF_CountedColorSpace* m_pCountedBaseCS; - int m_nBaseComponents; - int m_MaxIndex; - CFX_ByteString m_Table; - FX_FLOAT* m_pCompMinMax; + CPDF_ColorSpace* m_pBaseCS = nullptr; + UnownedPtr m_pCountedBaseCS; + uint32_t m_nBaseComponents = 0; + int m_MaxIndex = 0; + ByteString m_Table; + float* m_pCompMinMax = nullptr; }; class CPDF_SeparationCS : public CPDF_ColorSpace { @@ -214,14 +212,13 @@ class CPDF_SeparationCS : public CPDF_ColorSpace { // CPDF_ColorSpace: void GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const override; - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; + float* value, + float* min, + float* max) const override; + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void EnableStdConversion(bool bEnabled) override; std::unique_ptr m_pAltCS; @@ -236,86 +233,142 @@ class CPDF_DeviceNCS : public CPDF_ColorSpace { // CPDF_ColorSpace: void GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const override; - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; + float* value, + float* min, + float* max) const override; + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; void EnableStdConversion(bool bEnabled) override; std::unique_ptr m_pAltCS; std::unique_ptr m_pFunc; }; -FX_FLOAT RGB_Conversion(FX_FLOAT colorComponent) { - if (colorComponent > 1) - colorComponent = 1; - if (colorComponent < 0) - colorComponent = 0; +class Vector_3by1 { + public: + Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {} + + Vector_3by1(float a1, float b1, float c1) : a(a1), b(b1), c(c1) {} + + float a; + float b; + float c; +}; - int scale = (int)(colorComponent * 1023); - if (scale < 0) - scale = 0; +class Matrix_3by3 { + public: + Matrix_3by3() + : a(0.0f), + b(0.0f), + c(0.0f), + d(0.0f), + e(0.0f), + f(0.0f), + g(0.0f), + h(0.0f), + i(0.0f) {} + + Matrix_3by3(float a1, + float b1, + float c1, + float d1, + float e1, + float f1, + float g1, + float h1, + float i1) + : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1) {} + + Matrix_3by3 Inverse() { + float det = a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g); + if (fabs(det) < std::numeric_limits::epsilon()) + return Matrix_3by3(); + + return Matrix_3by3( + (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det, + -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det, + (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det); + } + + Matrix_3by3 Multiply(const Matrix_3by3& m) { + return Matrix_3by3(a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h, + a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g, + d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i, + g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h, + g * m.c + h * m.f + i * m.i); + } + + Vector_3by1 TransformVector(const Vector_3by1& v) { + return Vector_3by1(a * v.a + b * v.b + c * v.c, d * v.a + e * v.b + f * v.c, + g * v.a + h * v.b + i * v.c); + } + + float a; + float b; + float c; + float d; + float e; + float f; + float g; + float h; + float i; +}; + +float RGB_Conversion(float colorComponent) { + colorComponent = pdfium::clamp(colorComponent, 0.0f, 1.0f); + int scale = std::max(static_cast(colorComponent * 1023), 0); if (scale < 192) - colorComponent = (g_sRGBSamples1[scale] / 255.0f); - else - colorComponent = (g_sRGBSamples2[scale / 4 - 48] / 255.0f); - return colorComponent; + return g_sRGBSamples1[scale] / 255.0f; + return g_sRGBSamples2[scale / 4 - 48] / 255.0f; } -void XYZ_to_sRGB(FX_FLOAT X, - FX_FLOAT Y, - FX_FLOAT Z, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) { - FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z; - FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z; - FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z; - - R = RGB_Conversion(R1); - G = RGB_Conversion(G1); - B = RGB_Conversion(B1); +void XYZ_to_sRGB(float X, float Y, float Z, float* R, float* G, float* B) { + float R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z; + float G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z; + float B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z; + + *R = RGB_Conversion(R1); + *G = RGB_Conversion(G1); + *B = RGB_Conversion(B1); } -void XYZ_to_sRGB_WhitePoint(FX_FLOAT X, - FX_FLOAT Y, - FX_FLOAT Z, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B, - FX_FLOAT Xw, - FX_FLOAT Yw, - FX_FLOAT Zw) { +void XYZ_to_sRGB_WhitePoint(float X, + float Y, + float Z, + float Xw, + float Yw, + float Zw, + float* R, + float* G, + float* B) { // The following RGB_xyz is based on // sRGB value {Rx,Ry}={0.64, 0.33}, {Gx,Gy}={0.30, 0.60}, {Bx,By}={0.15, 0.06} - FX_FLOAT Rx = 0.64f, Ry = 0.33f; - FX_FLOAT Gx = 0.30f, Gy = 0.60f; - FX_FLOAT Bx = 0.15f, By = 0.06f; - CFX_Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy, - 1 - Bx - By); - CFX_Vector_3by1 whitePoint(Xw, Yw, Zw); - CFX_Vector_3by1 XYZ(X, Y, Z); - - CFX_Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint); - CFX_Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0, - 0, RGB_Sum_XYZ.c); - CFX_Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG); - CFX_Vector_3by1 RGB = M.Inverse().TransformVector(XYZ); - - R = RGB_Conversion(RGB.a); - G = RGB_Conversion(RGB.b); - B = RGB_Conversion(RGB.c); + float Rx = 0.64f, Ry = 0.33f; + float Gx = 0.30f, Gy = 0.60f; + float Bx = 0.15f, By = 0.06f; + Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy, + 1 - Bx - By); + Vector_3by1 whitePoint(Xw, Yw, Zw); + Vector_3by1 XYZ(X, Y, Z); + + Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint); + Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0, 0, + RGB_Sum_XYZ.c); + Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG); + Vector_3by1 RGB = M.Inverse().TransformVector(XYZ); + + *R = RGB_Conversion(RGB.a); + *G = RGB_Conversion(RGB.b); + *B = RGB_Conversion(RGB.c); } } // namespace -CPDF_ColorSpace* CPDF_ColorSpace::ColorspaceFromName( - const CFX_ByteString& name) { +// static +CPDF_ColorSpace* CPDF_ColorSpace::ColorspaceFromName(const ByteString& name) { if (name == "DeviceRGB" || name == "RGB") return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); if (name == "DeviceGray" || name == "G") @@ -327,12 +380,23 @@ CPDF_ColorSpace* CPDF_ColorSpace::ColorspaceFromName( return nullptr; } +// static CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family) { return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family); } +// static std::unique_ptr CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj) { + std::set visited; + return Load(pDoc, pObj, &visited); +} + +// static +std::unique_ptr CPDF_ColorSpace::Load( + CPDF_Document* pDoc, + CPDF_Object* pObj, + std::set* pVisited) { if (!pObj) return nullptr; @@ -364,34 +428,43 @@ std::unique_ptr CPDF_ColorSpace::Load(CPDF_Document* pDoc, if (!pFamilyObj) return nullptr; - CFX_ByteString familyname = pFamilyObj->GetString(); + ByteString familyname = pFamilyObj->GetString(); if (pArray->GetCount() == 1) return std::unique_ptr(ColorspaceFromName(familyname)); std::unique_ptr pCS; - uint32_t id = familyname.GetID(); - if (id == FXBSTR_ID('C', 'a', 'l', 'G')) { - pCS.reset(new CPDF_CalGray(pDoc)); - } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) { - pCS.reset(new CPDF_CalRGB(pDoc)); - } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) { - pCS.reset(new CPDF_LabCS(pDoc)); - } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) { - pCS.reset(new CPDF_ICCBasedCS(pDoc)); - } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || - id == FXBSTR_ID('I', 0, 0, 0)) { - pCS.reset(new CPDF_IndexedCS(pDoc)); - } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) { - pCS.reset(new CPDF_SeparationCS(pDoc)); - } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) { - pCS.reset(new CPDF_DeviceNCS(pDoc)); - } else if (id == FXBSTR_ID('P', 'a', 't', 't')) { - pCS.reset(new CPDF_PatternCS(pDoc)); - } else { - return nullptr; + switch (familyname.GetID()) { + case FXBSTR_ID('C', 'a', 'l', 'G'): + pCS.reset(new CPDF_CalGray(pDoc)); + break; + case FXBSTR_ID('C', 'a', 'l', 'R'): + pCS.reset(new CPDF_CalRGB(pDoc)); + break; + case FXBSTR_ID('L', 'a', 'b', 0): + pCS.reset(new CPDF_LabCS(pDoc)); + break; + case FXBSTR_ID('I', 'C', 'C', 'B'): + pCS.reset(new CPDF_ICCBasedCS(pDoc)); + break; + case FXBSTR_ID('I', 'n', 'd', 'e'): + case FXBSTR_ID('I', 0, 0, 0): + pCS.reset(new CPDF_IndexedCS(pDoc)); + break; + case FXBSTR_ID('S', 'e', 'p', 'a'): + pCS.reset(new CPDF_SeparationCS(pDoc)); + break; + case FXBSTR_ID('D', 'e', 'v', 'i'): + pCS.reset(new CPDF_DeviceNCS(pDoc)); + break; + case FXBSTR_ID('P', 'a', 't', 't'): + pCS.reset(new CPDF_PatternCS(pDoc)); + break; + default: + return nullptr; } pCS->m_pArray = pArray; - if (!pCS->v_Load(pDoc, pArray)) + pCS->m_nComponents = pCS->v_Load(pDoc, pArray, pVisited); + if (pCS->m_nComponents == 0) return nullptr; return pCS; @@ -408,73 +481,24 @@ void CPDF_ColorSpace::Release() { } int CPDF_ColorSpace::GetBufSize() const { - if (m_Family == PDFCS_PATTERN) { + if (m_Family == PDFCS_PATTERN) return sizeof(PatternValue); - } - return m_nComponents * sizeof(FX_FLOAT); + return m_nComponents * sizeof(float); } -FX_FLOAT* CPDF_ColorSpace::CreateBuf() { +float* CPDF_ColorSpace::CreateBuf() { int size = GetBufSize(); - uint8_t* pBuf = FX_Alloc(uint8_t, size); - return (FX_FLOAT*)pBuf; -} - -bool CPDF_ColorSpace::sRGB() const { - if (m_Family == PDFCS_DEVICERGB) { - return true; - } - if (m_Family != PDFCS_ICCBASED) { - return false; - } - CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this; - return pCS->m_pProfile->m_bsRGB; -} - -bool CPDF_ColorSpace::SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const { - return false; -} - -bool CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const { - if (v_GetCMYK(pBuf, c, m, y, k)) { - return true; - } - FX_FLOAT R, G, B; - if (!GetRGB(pBuf, R, G, B)) { - return false; - } - sRGB_to_AdobeCMYK(R, G, B, c, m, y, k); - return true; -} - -bool CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf, - FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k) const { - if (v_SetCMYK(pBuf, c, m, y, k)) { - return true; - } - FX_FLOAT R, G, B; - AdobeCMYK_to_sRGB(c, m, y, k, R, G, B); - return SetRGB(pBuf, R, G, B); + return reinterpret_cast(FX_Alloc(uint8_t, size)); } -void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const { - if (!buf || m_Family == PDFCS_PATTERN) { +void CPDF_ColorSpace::GetDefaultColor(float* buf) const { + if (!buf || m_Family == PDFCS_PATTERN) return; - } - FX_FLOAT min, max; - for (uint32_t i = 0; i < m_nComponents; i++) { - GetDefaultValue(i, buf[i], min, max); - } + + float min; + float max; + for (uint32_t i = 0; i < m_nComponents; i++) + GetDefaultValue(i, &buf[i], &min, &max); } uint32_t CPDF_ColorSpace::CountComponents() const { @@ -482,12 +506,12 @@ uint32_t CPDF_ColorSpace::CountComponents() const { } void CPDF_ColorSpace::GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const { - value = 0; - min = 0; - max = 1.0f; + float* value, + float* min, + float* max) const { + *value = 0.0f; + *min = 0.0f; + *max = 1.0f; } void CPDF_ColorSpace::TranslateImageLine(uint8_t* dest_buf, @@ -496,27 +520,22 @@ void CPDF_ColorSpace::TranslateImageLine(uint8_t* dest_buf, int image_width, int image_height, bool bTransMask) const { - CFX_FixedBufGrow srcbuf(m_nComponents); - FX_FLOAT* src = srcbuf; - FX_FLOAT R, G, B; + CFX_FixedBufGrow srcbuf(m_nComponents); + float* src = srcbuf; + float R; + float G; + float B; + const int divisor = m_Family != PDFCS_INDEXED ? 255 : 1; for (int i = 0; i < pixels; i++) { for (uint32_t j = 0; j < m_nComponents; j++) - if (m_Family == PDFCS_INDEXED) { - src[j] = (FX_FLOAT)(*src_buf++); - } else { - src[j] = (FX_FLOAT)(*src_buf++) / 255; - } - GetRGB(src, R, G, B); - *dest_buf++ = (int32_t)(B * 255); - *dest_buf++ = (int32_t)(G * 255); - *dest_buf++ = (int32_t)(R * 255); + src[j] = static_cast(*src_buf++) / divisor; + GetRGB(src, &R, &G, &B); + *dest_buf++ = static_cast(B * 255); + *dest_buf++ = static_cast(G * 255); + *dest_buf++ = static_cast(R * 255); } } -CPDF_ColorSpace* CPDF_ColorSpace::GetBaseCS() const { - return nullptr; -} - void CPDF_ColorSpace::EnableStdConversion(bool bEnabled) { if (bEnabled) m_dwStdConversion++; @@ -524,79 +543,47 @@ void CPDF_ColorSpace::EnableStdConversion(bool bEnabled) { m_dwStdConversion--; } -CPDF_ColorSpace::CPDF_ColorSpace(CPDF_Document* pDoc, - int family, - uint32_t nComponents) - : m_pDocument(pDoc), - m_Family(family), - m_nComponents(nComponents), - m_pArray(nullptr), - m_dwStdConversion(0) {} +CPDF_ColorSpace::CPDF_ColorSpace(CPDF_Document* pDoc, int family) + : m_pDocument(pDoc), m_Family(family) {} CPDF_ColorSpace::~CPDF_ColorSpace() {} -bool CPDF_ColorSpace::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { - return true; -} - -bool CPDF_ColorSpace::v_GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const { - return false; -} - -bool CPDF_ColorSpace::v_SetCMYK(FX_FLOAT* pBuf, - FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k) const { - return false; +void CPDF_ColorSpace::SetComponentsForStockCS(uint32_t nComponents) { + ASSERT(!m_pDocument); // Stock colorspace is not associated with a document. + m_nComponents = nComponents; } CPDF_CalGray::CPDF_CalGray(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_CALGRAY, 1) {} + : CPDF_ColorSpace(pDoc, PDFCS_CALGRAY) {} -bool CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { +uint32_t CPDF_CalGray::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { CPDF_Dictionary* pDict = pArray->GetDictAt(1); if (!pDict) - return false; + return 0; CPDF_Array* pParam = pDict->GetArrayFor("WhitePoint"); - int i; - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0; pParam = pDict->GetArrayFor("BlackPoint"); - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0; m_Gamma = pDict->GetNumberFor("Gamma"); if (m_Gamma == 0) m_Gamma = 1.0f; - return true; + return 1; } -bool CPDF_CalGray::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - R = G = B = *pBuf; +bool CPDF_CalGray::GetRGB(float* pBuf, float* R, float* G, float* B) const { + *R = *pBuf; + *G = *pBuf; + *B = *pBuf; return true; } -bool CPDF_CalGray::SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const { - if (R == G && R == B) { - *pBuf = R; - return true; - } - return false; -} - void CPDF_CalGray::TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, @@ -611,26 +598,27 @@ void CPDF_CalGray::TranslateImageLine(uint8_t* pDestBuf, } CPDF_CalRGB::CPDF_CalRGB(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_CALRGB, 3) {} + : CPDF_ColorSpace(pDoc, PDFCS_CALRGB) {} -bool CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { +uint32_t CPDF_CalRGB::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { CPDF_Dictionary* pDict = pArray->GetDictAt(1); if (!pDict) - return false; + return 0; CPDF_Array* pParam = pDict->GetArrayFor("WhitePoint"); - int i; - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0; pParam = pDict->GetArrayFor("BlackPoint"); - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0; pParam = pDict->GetArrayFor("Gamma"); if (pParam) { m_bGamma = true; - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_Gamma[i] = pParam->GetNumberAt(i); } else { m_bGamma = false; @@ -639,30 +627,27 @@ bool CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { pParam = pDict->GetArrayFor("Matrix"); if (pParam) { m_bMatrix = true; - for (i = 0; i < 9; i++) + for (int i = 0; i < 9; i++) m_Matrix[i] = pParam->GetNumberAt(i); } else { m_bMatrix = false; } - return true; + return 3; } -bool CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - FX_FLOAT A_ = pBuf[0]; - FX_FLOAT B_ = pBuf[1]; - FX_FLOAT C_ = pBuf[2]; +bool CPDF_CalRGB::GetRGB(float* pBuf, float* R, float* G, float* B) const { + float A_ = pBuf[0]; + float B_ = pBuf[1]; + float C_ = pBuf[2]; if (m_bGamma) { - A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]); - B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]); - C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]); + A_ = FXSYS_pow(A_, m_Gamma[0]); + B_ = FXSYS_pow(B_, m_Gamma[1]); + C_ = FXSYS_pow(C_, m_Gamma[2]); } - FX_FLOAT X; - FX_FLOAT Y; - FX_FLOAT Z; + float X; + float Y; + float Z; if (m_bMatrix) { X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_; Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_; @@ -672,18 +657,8 @@ bool CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, Y = B_; Z = C_; } - XYZ_to_sRGB_WhitePoint(X, Y, Z, R, G, B, m_WhitePoint[0], m_WhitePoint[1], - m_WhitePoint[2]); - return true; -} - -bool CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const { - pBuf[0] = R; - pBuf[1] = G; - pBuf[2] = B; + XYZ_to_sRGB_WhitePoint(X, Y, Z, m_WhitePoint[0], m_WhitePoint[1], + m_WhitePoint[2], R, G, B); return true; } @@ -694,15 +669,15 @@ void CPDF_CalRGB::TranslateImageLine(uint8_t* pDestBuf, int image_height, bool bTransMask) const { if (bTransMask) { - FX_FLOAT Cal[3]; - FX_FLOAT R; - FX_FLOAT G; - FX_FLOAT B; + float Cal[3]; + float R; + float G; + float B; for (int i = 0; i < pixels; i++) { - Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255; - Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255; - Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255; - GetRGB(Cal, R, G, B); + Cal[0] = static_cast(pSrcBuf[2]) / 255; + Cal[1] = static_cast(pSrcBuf[1]) / 255; + Cal[2] = static_cast(pSrcBuf[0]) / 255; + GetRGB(Cal, &R, &G, &B); pDestBuf[0] = FXSYS_round(B * 255); pDestBuf[1] = FXSYS_round(G * 255); pDestBuf[2] = FXSYS_round(R * 255); @@ -714,60 +689,57 @@ void CPDF_CalRGB::TranslateImageLine(uint8_t* pDestBuf, } CPDF_LabCS::CPDF_LabCS(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_LAB, 3) {} + : CPDF_ColorSpace(pDoc, PDFCS_LAB) {} void CPDF_LabCS::GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const { + float* value, + float* min, + float* max) const { ASSERT(iComponent < 3); - value = 0; if (iComponent == 0) { - min = 0; - max = 100 * 1.0f; - } else { - min = m_Ranges[iComponent * 2 - 2]; - max = m_Ranges[iComponent * 2 - 1]; - if (value < min) - value = min; - else if (value > max) - value = max; + *min = 0.0f; + *max = 100 * 1.0f; + *value = 0.0f; + return; } + + *min = m_Ranges[iComponent * 2 - 2]; + *max = m_Ranges[iComponent * 2 - 1]; + *value = pdfium::clamp(0.0f, *min, *max); } -bool CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { +uint32_t CPDF_LabCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { CPDF_Dictionary* pDict = pArray->GetDictAt(1); if (!pDict) - return false; + return 0; CPDF_Array* pParam = pDict->GetArrayFor("WhitePoint"); - int i; - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0; pParam = pDict->GetArrayFor("BlackPoint"); - for (i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0; pParam = pDict->GetArrayFor("Range"); - const FX_FLOAT def_ranges[4] = {-100 * 1.0f, 100 * 1.0f, -100 * 1.0f, - 100 * 1.0f}; - for (i = 0; i < 4; i++) - m_Ranges[i] = pParam ? pParam->GetNumberAt(i) : def_ranges[i]; - return true; + const float kDefaultRanges[4] = {-100.0f, 100.0f, -100.0f, 100.0f}; + for (size_t i = 0; i < FX_ArraySize(kDefaultRanges); i++) + m_Ranges[i] = pParam ? pParam->GetNumberAt(i) : kDefaultRanges[i]; + return 3; } -bool CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - FX_FLOAT Lstar = pBuf[0]; - FX_FLOAT astar = pBuf[1]; - FX_FLOAT bstar = pBuf[2]; - FX_FLOAT M = (Lstar + 16.0f) / 116.0f; - FX_FLOAT L = M + astar / 500.0f; - FX_FLOAT N = M - bstar / 200.0f; - FX_FLOAT X, Y, Z; +bool CPDF_LabCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { + float Lstar = pBuf[0]; + float astar = pBuf[1]; + float bstar = pBuf[2]; + float M = (Lstar + 16.0f) / 116.0f; + float L = M + astar / 500.0f; + float N = M - bstar / 200.0f; + float X; + float Y; + float Z; if (L < 0.2069f) X = 0.957f * 0.12842f * (L - 0.1379f); else @@ -787,13 +759,6 @@ bool CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, return true; } -bool CPDF_LabCS::SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const { - return false; -} - void CPDF_LabCS::TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, @@ -801,140 +766,103 @@ void CPDF_LabCS::TranslateImageLine(uint8_t* pDestBuf, int image_height, bool bTransMask) const { for (int i = 0; i < pixels; i++) { - FX_FLOAT lab[3]; - FX_FLOAT R, G, B; - lab[0] = (pSrcBuf[0] * 100 / 255.0f); - lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128); - lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128); - GetRGB(lab, R, G, B); - pDestBuf[0] = (int32_t)(B * 255); - pDestBuf[1] = (int32_t)(G * 255); - pDestBuf[2] = (int32_t)(R * 255); + float lab[3]; + lab[0] = pSrcBuf[0] * 100 / 255.0f; + lab[1] = pSrcBuf[1] - 128; + lab[2] = pSrcBuf[2] - 128; + + float R; + float G; + float B; + GetRGB(lab, &R, &G, &B); + pDestBuf[0] = static_cast(B * 255); + pDestBuf[1] = static_cast(G * 255); + pDestBuf[2] = static_cast(R * 255); pDestBuf += 3; pSrcBuf += 3; } } CPDF_ICCBasedCS::CPDF_ICCBasedCS(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_ICCBASED, 0), - m_pProfile(nullptr), - m_pCache(nullptr), - m_pRanges(nullptr) {} + : CPDF_ColorSpace(pDoc, PDFCS_ICCBASED) {} CPDF_ICCBasedCS::~CPDF_ICCBasedCS() { - FX_Free(m_pCache); - FX_Free(m_pRanges); - if (m_pProfile && m_pDocument) - m_pDocument->GetPageData()->ReleaseIccProfile(m_pProfile); + if (m_pProfile && m_pDocument) { + CPDF_Stream* pStream = m_pProfile->GetStream(); + m_pProfile.Reset(); // Give up our reference first. + auto* pPageData = m_pDocument->GetPageData(); + if (pPageData) + pPageData->MaybePurgeIccProfile(pStream); + } } -bool CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { +uint32_t CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { CPDF_Stream* pStream = pArray->GetStreamAt(1); if (!pStream) - return false; + return 0; + // The PDF 1.7 spec says the number of components must be valid. While some + // PDF viewers tolerate invalid values, Acrobat does not, so be consistent + // with Acrobat and reject bad values. + CPDF_Dictionary* pDict = pStream->GetDict(); + int32_t nDictComponents = pDict ? pDict->GetIntegerFor("N") : 0; + if (!IsValidComponents(nDictComponents)) + return 0; + + uint32_t nComponents = static_cast(nDictComponents); m_pProfile = pDoc->LoadIccProfile(pStream); if (!m_pProfile) - return false; - - // Try using the |nComponents| from ICC profile - m_nComponents = m_pProfile->GetComponents(); - CPDF_Dictionary* pDict = pStream->GetDict(); - if (!m_pProfile->m_pTransform) { // No valid ICC profile or using sRGB - CPDF_Object* pAlterCSObj = - pDict ? pDict->GetDirectObjectFor("Alternate") : nullptr; - if (pAlterCSObj) { - std::unique_ptr pAlterCS = - CPDF_ColorSpace::Load(pDoc, pAlterCSObj); - if (pAlterCS) { - if (m_nComponents == 0) { // NO valid ICC profile - if (pAlterCS->CountComponents() > 0) { // Use Alternative colorspace - m_nComponents = pAlterCS->CountComponents(); - m_pAlterCS = std::move(pAlterCS); - } else { // No valid alternative colorspace - int32_t nDictComponents = pDict ? pDict->GetIntegerFor("N") : 0; - if (nDictComponents != 1 && nDictComponents != 3 && - nDictComponents != 4) { - return false; - } - m_nComponents = nDictComponents; - } - } else { // Using sRGB - if (pAlterCS->CountComponents() == m_nComponents) - m_pAlterCS = std::move(pAlterCS); - } - } - } - if (!m_pAlterCS) { - if (m_nComponents == 1) - m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY); - else if (m_nComponents == 3) - m_pAlterCS = GetStockCS(PDFCS_DEVICERGB); - else if (m_nComponents == 4) - m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK); - } - } - CPDF_Array* pRanges = pDict->GetArrayFor("Range"); - m_pRanges = FX_Alloc2D(FX_FLOAT, m_nComponents, 2); - for (uint32_t i = 0; i < m_nComponents * 2; i++) { - if (pRanges) - m_pRanges[i] = pRanges->GetNumberAt(i); - else if (i % 2) - m_pRanges[i] = 1.0f; - else - m_pRanges[i] = 0; + return 0; + + // The PDF 1.7 spec also says the number of components in the ICC profile + // must match the N value. However, that assumes the viewer actually + // understands the ICC profile. + // If the valid ICC profile has a mismatch, fail. + if (m_pProfile->IsValid() && m_pProfile->GetComponents() != nComponents) + return 0; + + // If PDFium does not understand the ICC profile format at all, or if it's + // SRGB, a profile PDFium recognizes but does not support well, then try the + // alternate profile. + if (!m_pProfile->IsSupported() && + !FindAlternateProfile(pDoc, pDict, pVisited, nComponents)) { + // If there is no alternate profile, use a stock profile as mentioned in + // the PDF 1.7 spec in table 4.16 in the "Alternate" key description. + ASSERT(!m_pAlterCS); + m_pAlterCS = GetStockAlternateProfile(nComponents); } - return true; + + m_pRanges = GetRanges(pDict, nComponents); + return nComponents; } -bool CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - if (m_pProfile && m_pProfile->m_bsRGB) { - R = pBuf[0]; - G = pBuf[1]; - B = pBuf[2]; +bool CPDF_ICCBasedCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { + ASSERT(m_pProfile); + if (IsSRGB()) { + *R = pBuf[0]; + *G = pBuf[1]; + *B = pBuf[2]; return true; } - CCodec_IccModule* pIccModule = CPDF_ModuleMgr::Get()->GetIccModule(); - if (!m_pProfile->m_pTransform || !pIccModule) { - if (m_pAlterCS) - return m_pAlterCS->GetRGB(pBuf, R, G, B); - - R = 0.0f; - G = 0.0f; - B = 0.0f; + if (m_pProfile->transform()) { + float rgb[3]; + CCodec_IccModule* pIccModule = CPDF_ModuleMgr::Get()->GetIccModule(); + pIccModule->SetComponents(CountComponents()); + pIccModule->Translate(m_pProfile->transform(), pBuf, rgb); + *R = rgb[0]; + *G = rgb[1]; + *B = rgb[2]; return true; } - FX_FLOAT rgb[3]; - pIccModule->SetComponents(m_nComponents); - pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb); - R = rgb[0]; - G = rgb[1]; - B = rgb[2]; - return true; -} -bool CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const { - return false; -} - -bool CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const { - if (m_nComponents != 4) - return false; + if (m_pAlterCS) + return m_pAlterCS->GetRGB(pBuf, R, G, B); - c = pBuf[0]; - m = pBuf[1]; - y = pBuf[2]; - k = pBuf[3]; + *R = 0.0f; + *G = 0.0f; + *B = 0.0f; return true; } @@ -950,123 +878,209 @@ void CPDF_ICCBasedCS::TranslateImageLine(uint8_t* pDestBuf, int image_width, int image_height, bool bTransMask) const { - if (m_pProfile->m_bsRGB) { + if (IsSRGB()) { ReverseRGB(pDestBuf, pSrcBuf, pixels); - } else if (m_pProfile->m_pTransform) { - int nMaxColors = 1; - for (uint32_t i = 0; i < m_nComponents; i++) { - nMaxColors *= 52; + return; + } + if (!m_pProfile->transform()) { + if (m_pAlterCS) { + m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, + image_height, false); } - if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) { - CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( - m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels); - } else { - if (!m_pCache) { - ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc2D(uint8_t, nMaxColors, 3); - uint8_t* temp_src = FX_Alloc2D(uint8_t, nMaxColors, m_nComponents); - uint8_t* pSrc = temp_src; - for (int i = 0; i < nMaxColors; i++) { - uint32_t color = i; - uint32_t order = nMaxColors / 52; - for (uint32_t c = 0; c < m_nComponents; c++) { - *pSrc++ = (uint8_t)(color / order * 5); - color %= order; - order /= 52; - } - } - CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( - m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors); - FX_Free(temp_src); - } - for (int i = 0; i < pixels; i++) { - int index = 0; - for (uint32_t c = 0; c < m_nComponents; c++) { - index = index * 52 + (*pSrcBuf) / 5; - pSrcBuf++; - } - index *= 3; - *pDestBuf++ = m_pCache[index]; - *pDestBuf++ = m_pCache[index + 1]; - *pDestBuf++ = m_pCache[index + 2]; + return; + } + + // |nMaxColors| will not overflow since |nComponents| is limited in size. + const uint32_t nComponents = CountComponents(); + ASSERT(IsValidComponents(nComponents)); + int nMaxColors = 1; + for (uint32_t i = 0; i < nComponents; i++) + nMaxColors *= 52; + + bool bTranslate = nComponents > 3; + if (!bTranslate) { + FX_SAFE_INT32 nPixelCount = image_width; + nPixelCount *= image_height; + if (nPixelCount.IsValid()) + bTranslate = nPixelCount.ValueOrDie() < nMaxColors * 3 / 2; + } + if (bTranslate) { + CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( + m_pProfile->transform(), pDestBuf, pSrcBuf, pixels); + return; + } + + if (!m_pCache) { + m_pCache.reset(FX_Alloc2D(uint8_t, nMaxColors, 3)); + std::unique_ptr temp_src( + FX_Alloc2D(uint8_t, nMaxColors, nComponents)); + uint8_t* pSrc = temp_src.get(); + for (int i = 0; i < nMaxColors; i++) { + uint32_t color = i; + uint32_t order = nMaxColors / 52; + for (uint32_t c = 0; c < nComponents; c++) { + *pSrc++ = static_cast(color / order * 5); + color %= order; + order /= 52; } } - } else if (m_pAlterCS) { - m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, - image_height); + CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( + m_pProfile->transform(), m_pCache.get(), temp_src.get(), nMaxColors); + } + uint8_t* pCachePtr = m_pCache.get(); + for (int i = 0; i < pixels; i++) { + int index = 0; + for (uint32_t c = 0; c < nComponents; c++) { + index = index * 52 + (*pSrcBuf) / 5; + pSrcBuf++; + } + index *= 3; + *pDestBuf++ = pCachePtr[index]; + *pDestBuf++ = pCachePtr[index + 1]; + *pDestBuf++ = pCachePtr[index + 2]; } } +bool CPDF_ICCBasedCS::FindAlternateProfile(CPDF_Document* pDoc, + CPDF_Dictionary* pDict, + std::set* pVisited, + uint32_t nExpectedComponents) { + CPDF_Object* pAlterCSObj = pDict->GetDirectObjectFor("Alternate"); + if (!pAlterCSObj) + return false; + + auto pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj, pVisited); + if (!pAlterCS) + return false; + + if (pAlterCS->GetFamily() == PDFCS_PATTERN) + return false; + + if (pAlterCS->CountComponents() != nExpectedComponents) + return false; + + m_pAlterCS = std::move(pAlterCS); + return true; +} + +// static +CPDF_ColorSpace* CPDF_ICCBasedCS::GetStockAlternateProfile( + uint32_t nComponents) { + if (nComponents == 1) + return GetStockCS(PDFCS_DEVICEGRAY); + if (nComponents == 3) + return GetStockCS(PDFCS_DEVICERGB); + if (nComponents == 4) + return GetStockCS(PDFCS_DEVICECMYK); + NOTREACHED(); + return nullptr; +} + +// static +bool CPDF_ICCBasedCS::IsValidComponents(int32_t nComps) { + return nComps == 1 || nComps == 3 || nComps == 4; +} + +// static +std::vector CPDF_ICCBasedCS::GetRanges(CPDF_Dictionary* pDict, + uint32_t nComponents) { + ASSERT(IsValidComponents(nComponents)); + + std::vector ranges; + ranges.reserve(nComponents * 2); + CPDF_Array* pRanges = pDict->GetArrayFor("Range"); + if (pRanges) { + for (uint32_t i = 0; i < nComponents * 2; i++) { + ranges.push_back(pRanges->GetNumberAt(i)); + } + } else { + for (uint32_t i = 0; i < nComponents; i++) { + ranges.push_back(0.0f); + ranges.push_back(1.0f); + } + } + return ranges; +} + CPDF_IndexedCS::CPDF_IndexedCS(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_INDEXED, 1), - m_pBaseCS(nullptr), - m_pCountedBaseCS(nullptr), - m_pCompMinMax(nullptr) {} + : CPDF_ColorSpace(pDoc, PDFCS_INDEXED) {} CPDF_IndexedCS::~CPDF_IndexedCS() { FX_Free(m_pCompMinMax); CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : nullptr; if (pCS && m_pDocument) { - m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); + auto* pPageData = m_pDocument->GetPageData(); + if (pPageData) + pPageData->ReleaseColorSpace(pCS->GetArray()); } } -bool CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { - if (pArray->GetCount() < 4) { - return false; - } +uint32_t CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { + if (pArray->GetCount() < 4) + return 0; + CPDF_Object* pBaseObj = pArray->GetDirectObjectAt(1); - if (pBaseObj == m_pArray) { - return false; - } + if (pBaseObj == m_pArray) + return 0; + CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); - m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, nullptr); - if (!m_pBaseCS) { - return false; - } + m_pBaseCS = pDocPageData->GetColorSpaceGuarded(pBaseObj, nullptr, pVisited); + if (!m_pBaseCS) + return 0; + + // The base color space cannot be a Pattern or Indexed space, according to the + // PDF 1.7 spec, page 263. + int family = m_pBaseCS->GetFamily(); + if (family == PDFCS_INDEXED || family == PDFCS_PATTERN) + return 0; + m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray()); m_nBaseComponents = m_pBaseCS->CountComponents(); - m_pCompMinMax = FX_Alloc2D(FX_FLOAT, m_nBaseComponents, 2); - FX_FLOAT defvalue; - for (int i = 0; i < m_nBaseComponents; i++) { - m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], - m_pCompMinMax[i * 2 + 1]); + m_pCompMinMax = FX_Alloc2D(float, m_nBaseComponents, 2); + float defvalue; + for (uint32_t i = 0; i < m_nBaseComponents; i++) { + m_pBaseCS->GetDefaultValue(i, &defvalue, &m_pCompMinMax[i * 2], + &m_pCompMinMax[i * 2 + 1]); m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2]; } m_MaxIndex = pArray->GetIntegerAt(2); CPDF_Object* pTableObj = pArray->GetDirectObjectAt(3); if (!pTableObj) - return false; + return 0; if (CPDF_String* pString = pTableObj->AsString()) { m_Table = pString->GetString(); } else if (CPDF_Stream* pStream = pTableObj->AsStream()) { - CPDF_StreamAcc acc; - acc.LoadAllData(pStream, false); - m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize()); + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllDataFiltered(); + m_Table = ByteStringView(pAcc->GetData(), pAcc->GetSize()); } - return true; + return 1; } -bool CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - int index = (int32_t)(*pBuf); - if (index < 0 || index > m_MaxIndex) { +bool CPDF_IndexedCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { + int32_t index = static_cast(*pBuf); + if (index < 0 || index > m_MaxIndex) return false; - } + if (m_nBaseComponents) { - if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents || - (index + 1) * m_nBaseComponents > (int)m_Table.GetLength()) { - R = G = B = 0; + FX_SAFE_SIZE_T length = index; + length += 1; + length *= m_nBaseComponents; + if (!length.IsValid() || length.ValueOrDie() > m_Table.GetLength()) { + *R = 0; + *G = 0; + *B = 0; return false; } } - CFX_FixedBufGrow Comps(m_nBaseComponents); - FX_FLOAT* comps = Comps; + CFX_FixedBufGrow Comps(m_nBaseComponents); + float* comps = Comps; const uint8_t* pTable = m_Table.raw_str(); - for (int i = 0; i < m_nBaseComponents; i++) { + for (uint32_t i = 0; i < m_nBaseComponents; i++) { comps[i] = m_pCompMinMax[i * 2] + m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255; @@ -1074,113 +1088,60 @@ bool CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, return m_pBaseCS->GetRGB(comps, R, G, B); } -CPDF_ColorSpace* CPDF_IndexedCS::GetBaseCS() const { - return m_pBaseCS; -} - void CPDF_IndexedCS::EnableStdConversion(bool bEnabled) { CPDF_ColorSpace::EnableStdConversion(bEnabled); - if (m_pBaseCS) { + if (m_pBaseCS) m_pBaseCS->EnableStdConversion(bEnabled); - } -} - -CPDF_PatternCS::CPDF_PatternCS(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_PATTERN, 1), - m_pBaseCS(nullptr), - m_pCountedBaseCS(nullptr) {} - -CPDF_PatternCS::~CPDF_PatternCS() { - CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : nullptr; - if (pCS && m_pDocument) { - m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); - } -} - -bool CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { - CPDF_Object* pBaseCS = pArray->GetDirectObjectAt(1); - if (pBaseCS == m_pArray) { - return false; - } - CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); - m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, nullptr); - if (m_pBaseCS) { - if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) { - return false; - } - m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray()); - m_nComponents = m_pBaseCS->CountComponents() + 1; - if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) { - return false; - } - } else { - m_nComponents = 1; - } - return true; -} - -bool CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - if (m_pBaseCS) { - ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN); - PatternValue* pvalue = (PatternValue*)pBuf; - if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) { - return true; - } - } - R = G = B = 0.75f; - return false; -} - -CPDF_ColorSpace* CPDF_PatternCS::GetBaseCS() const { - return m_pBaseCS; } CPDF_SeparationCS::CPDF_SeparationCS(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_SEPARATION, 1) {} + : CPDF_ColorSpace(pDoc, PDFCS_SEPARATION) {} CPDF_SeparationCS::~CPDF_SeparationCS() {} void CPDF_SeparationCS::GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const { - value = 1.0f; - min = 0; - max = 1.0f; + float* value, + float* min, + float* max) const { + *value = 1.0f; + *min = 0; + *max = 1.0f; } -bool CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { - CFX_ByteString name = pArray->GetStringAt(1); +uint32_t CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { + ByteString name = pArray->GetStringAt(1); if (name == "None") { m_Type = None; - return true; + return 1; } m_Type = Colorant; CPDF_Object* pAltCS = pArray->GetDirectObjectAt(2); if (pAltCS == m_pArray) - return false; + return 0; - m_pAltCS = Load(pDoc, pAltCS); + m_pAltCS = Load(pDoc, pAltCS, pVisited); if (!m_pAltCS) - return false; + return 0; - CPDF_Object* pFuncObj = pArray->GetDirectObjectAt(3); - if (pFuncObj && !pFuncObj->IsName()) - m_pFunc = CPDF_Function::Load(pFuncObj); + if (m_pAltCS->IsSpecial()) + return 0; - if (m_pFunc && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) - m_pFunc.reset(); - return true; + CPDF_Object* pFuncObj = pArray->GetDirectObjectAt(3); + if (pFuncObj && !pFuncObj->IsName()) { + auto pFunc = CPDF_Function::Load(pFuncObj); + if (pFunc && pFunc->CountOutputs() >= m_pAltCS->CountComponents()) + m_pFunc = std::move(pFunc); + } + return 1; } -bool CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { +bool CPDF_SeparationCS::GetRGB(float* pBuf, + float* R, + float* G, + float* B) const { if (m_Type == None) return false; @@ -1189,15 +1150,15 @@ bool CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, return false; int nComps = m_pAltCS->CountComponents(); - CFX_FixedBufGrow results(nComps); + CFX_FixedBufGrow results(nComps); for (int i = 0; i < nComps; i++) results[i] = *pBuf; return m_pAltCS->GetRGB(results, R, G, B); } - CFX_FixedBufGrow results(m_pFunc->CountOutputs()); + CFX_FixedBufGrow results(m_pFunc->CountOutputs()); int nresults = 0; - m_pFunc->Call(pBuf, 1, results, nresults); + m_pFunc->Call(pBuf, 1, results, &nresults); if (nresults == 0) return false; @@ -1217,47 +1178,51 @@ void CPDF_SeparationCS::EnableStdConversion(bool bEnabled) { } CPDF_DeviceNCS::CPDF_DeviceNCS(CPDF_Document* pDoc) - : CPDF_ColorSpace(pDoc, PDFCS_DEVICEN, 0) {} + : CPDF_ColorSpace(pDoc, PDFCS_DEVICEN) {} CPDF_DeviceNCS::~CPDF_DeviceNCS() {} void CPDF_DeviceNCS::GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const { - value = 1.0f; - min = 0; - max = 1.0f; + float* value, + float* min, + float* max) const { + *value = 1.0f; + *min = 0; + *max = 1.0f; } -bool CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { +uint32_t CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { CPDF_Array* pObj = ToArray(pArray->GetDirectObjectAt(1)); if (!pObj) - return false; + return 0; - m_nComponents = pObj->GetCount(); CPDF_Object* pAltCS = pArray->GetDirectObjectAt(2); if (!pAltCS || pAltCS == m_pArray) - return false; + return 0; - m_pAltCS = Load(pDoc, pAltCS); + m_pAltCS = Load(pDoc, pAltCS, pVisited); m_pFunc = CPDF_Function::Load(pArray->GetDirectObjectAt(3)); if (!m_pAltCS || !m_pFunc) - return false; + return 0; + + if (m_pAltCS->IsSpecial()) + return 0; + + if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) + return 0; - return m_pFunc->CountOutputs() >= m_pAltCS->CountComponents(); + return pObj->GetCount(); } -bool CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { +bool CPDF_DeviceNCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { if (!m_pFunc) return false; - CFX_FixedBufGrow results(m_pFunc->CountOutputs()); + CFX_FixedBufGrow results(m_pFunc->CountOutputs()); int nresults = 0; - m_pFunc->Call(pBuf, m_nComponents, results, nresults); + m_pFunc->Call(pBuf, CountComponents(), results, &nresults); if (nresults == 0) return false; diff --git a/core/fpdfapi/page/cpdf_colorspace.h b/core/fpdfapi/page/cpdf_colorspace.h index c4d62ed8493369dd324fabd485c1b8178e590d46..7f3a739d8fe575c095b5b016f5d5f3412480f5e0 100644 --- a/core/fpdfapi/page/cpdf_colorspace.h +++ b/core/fpdfapi/page/cpdf_colorspace.h @@ -8,9 +8,12 @@ #define CORE_FPDFAPI_PAGE_CPDF_COLORSPACE_H_ #include +#include +#include "core/fpdfapi/page/cpdf_pattern.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #define PDFCS_DEVICEGRAY 1 #define PDFCS_DEVICERGB 2 @@ -28,78 +31,78 @@ class CPDF_Array; class CPDF_Document; class CPDF_Object; +constexpr size_t kMaxPatternColorComps = 16; + +struct PatternValue { + CPDF_Pattern* m_pPattern; + CPDF_CountedPattern* m_pCountedPattern; + int m_nComps; + float m_Comps[kMaxPatternColorComps]; +}; + class CPDF_ColorSpace { public: static CPDF_ColorSpace* GetStockCS(int Family); - static CPDF_ColorSpace* ColorspaceFromName(const CFX_ByteString& name); + static CPDF_ColorSpace* ColorspaceFromName(const ByteString& name); static std::unique_ptr Load(CPDF_Document* pDoc, CPDF_Object* pCSObj); + static std::unique_ptr Load( + CPDF_Document* pDoc, + CPDF_Object* pCSObj, + std::set* pVisited); void Release(); int GetBufSize() const; - FX_FLOAT* CreateBuf(); - void GetDefaultColor(FX_FLOAT* buf) const; + float* CreateBuf(); + void GetDefaultColor(float* buf) const; uint32_t CountComponents() const; int GetFamily() const { return m_Family; } + bool IsSpecial() const { + return GetFamily() == PDFCS_SEPARATION || GetFamily() == PDFCS_DEVICEN || + GetFamily() == PDFCS_INDEXED || GetFamily() == PDFCS_PATTERN; + } + virtual void GetDefaultValue(int iComponent, - FX_FLOAT& value, - FX_FLOAT& min, - FX_FLOAT& max) const; - - bool sRGB() const; - virtual bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const = 0; - virtual bool SetRGB(FX_FLOAT* pBuf, FX_FLOAT R, FX_FLOAT G, FX_FLOAT B) const; - - bool GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const; - bool SetCMYK(FX_FLOAT* pBuf, - FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k) const; + float* value, + float* min, + float* max) const; + + virtual bool GetRGB(float* pBuf, float* R, float* G, float* B) const = 0; virtual void TranslateImageLine(uint8_t* dest_buf, const uint8_t* src_buf, int pixels, int image_width, int image_height, - bool bTransMask = false) const; - - CPDF_Array*& GetArray() { return m_pArray; } - virtual CPDF_ColorSpace* GetBaseCS() const; - + bool bTransMask) const; virtual void EnableStdConversion(bool bEnabled); - CPDF_Document* const m_pDocument; + CPDF_Array* GetArray() const { return m_pArray.Get(); } + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } protected: - CPDF_ColorSpace(CPDF_Document* pDoc, int family, uint32_t nComponents); + CPDF_ColorSpace(CPDF_Document* pDoc, int family); virtual ~CPDF_ColorSpace(); - virtual bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray); - virtual bool v_GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const; - virtual bool v_SetCMYK(FX_FLOAT* pBuf, - FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k) const; - - int m_Family; - uint32_t m_nComponents; - CPDF_Array* m_pArray; - uint32_t m_dwStdConversion; + // Returns the number of components, or 0 on failure. + virtual uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) = 0; + + // Stock colorspaces are not loaded normally. This initializes their + // components count. + void SetComponentsForStockCS(uint32_t nComponents); + + UnownedPtr const m_pDocument; + UnownedPtr m_pArray; + const int m_Family; + uint32_t m_dwStdConversion = 0; + + private: + uint32_t m_nComponents = 0; }; +using CPDF_CountedColorSpace = CPDF_CountedObject; namespace std { diff --git a/core/fpdfapi/page/cpdf_colorstate.cpp b/core/fpdfapi/page/cpdf_colorstate.cpp index c43a331c64f190ee41c815e77fd83807a109a838..693fcf1a932c9f65b4cdc0a8eb81ae06ea6f152d 100644 --- a/core/fpdfapi/page/cpdf_colorstate.cpp +++ b/core/fpdfapi/page/cpdf_colorstate.cpp @@ -70,42 +70,46 @@ bool CPDF_ColorState::HasStrokeColor() const { } void CPDF_ColorState::SetFillColor(CPDF_ColorSpace* pCS, - FX_FLOAT* pValue, + float* pValue, uint32_t nValues) { ColorData* pData = m_Ref.GetPrivateCopy(); SetColor(pData->m_FillColor, pData->m_FillRGB, pCS, pValue, nValues); } void CPDF_ColorState::SetStrokeColor(CPDF_ColorSpace* pCS, - FX_FLOAT* pValue, + float* pValue, uint32_t nValues) { ColorData* pData = m_Ref.GetPrivateCopy(); SetColor(pData->m_StrokeColor, pData->m_StrokeRGB, pCS, pValue, nValues); } void CPDF_ColorState::SetFillPattern(CPDF_Pattern* pPattern, - FX_FLOAT* pValue, + float* pValue, uint32_t nValues) { ColorData* pData = m_Ref.GetPrivateCopy(); pData->m_FillColor.SetValue(pPattern, pValue, nValues); - int R, G, B; - bool ret = pData->m_FillColor.GetRGB(R, G, B); + int R; + int G; + int B; + bool ret = pData->m_FillColor.GetRGB(&R, &G, &B); if (CPDF_TilingPattern* pTilingPattern = pPattern->AsTilingPattern()) { if (!ret && pTilingPattern->colored()) { pData->m_FillRGB = 0x00BFBFBF; return; } } - pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : (uint32_t)-1; + pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : 0xFFFFFFFF; } void CPDF_ColorState::SetStrokePattern(CPDF_Pattern* pPattern, - FX_FLOAT* pValue, + float* pValue, uint32_t nValues) { ColorData* pData = m_Ref.GetPrivateCopy(); pData->m_StrokeColor.SetValue(pPattern, pValue, nValues); - int R, G, B; - bool ret = pData->m_StrokeColor.GetRGB(R, G, B); + int R; + int G; + int B; + bool ret = pData->m_StrokeColor.GetRGB(&R, &G, &B); if (CPDF_TilingPattern* pTilingPattern = pPattern->AsTilingPattern()) { if (!ret && pTilingPattern->colored()) { pData->m_StrokeRGB = 0x00BFBFBF; @@ -113,13 +117,13 @@ void CPDF_ColorState::SetStrokePattern(CPDF_Pattern* pPattern, } } pData->m_StrokeRGB = - pData->m_StrokeColor.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (uint32_t)-1; + pData->m_StrokeColor.GetRGB(&R, &G, &B) ? FXSYS_RGB(R, G, B) : 0xFFFFFFFF; } void CPDF_ColorState::SetColor(CPDF_Color& color, uint32_t& rgb, CPDF_ColorSpace* pCS, - FX_FLOAT* pValue, + float* pValue, uint32_t nValues) { if (pCS) color.SetColorSpace(pCS); @@ -133,7 +137,7 @@ void CPDF_ColorState::SetColor(CPDF_Color& color, int R; int G; int B; - rgb = color.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (uint32_t)-1; + rgb = color.GetRGB(&R, &G, &B) ? FXSYS_RGB(R, G, B) : 0xFFFFFFFF; } CPDF_ColorState::ColorData::ColorData() : m_FillRGB(0), m_StrokeRGB(0) {} diff --git a/core/fpdfapi/page/cpdf_colorstate.h b/core/fpdfapi/page/cpdf_colorstate.h index 49c71b66f90207b184b9adc8060038d9ffb9f387..9619051e2cfc6087398f0714de3070c536cd7e14 100644 --- a/core/fpdfapi/page/cpdf_colorstate.h +++ b/core/fpdfapi/page/cpdf_colorstate.h @@ -8,9 +8,8 @@ #define CORE_FPDFAPI_PAGE_CPDF_COLORSTATE_H_ #include "core/fpdfapi/page/cpdf_color.h" -#include "core/fxcrt/cfx_shared_copy_on_write.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/shared_copy_on_write.h" class CPDF_Color; class CPDF_ColorSpace; @@ -39,23 +38,19 @@ class CPDF_ColorState { CPDF_Color* GetMutableStrokeColor(); bool HasStrokeColor() const; - void SetFillColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, uint32_t nValues); - void SetStrokeColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, uint32_t nValues); - void SetFillPattern(CPDF_Pattern* pattern, - FX_FLOAT* pValue, - uint32_t nValues); - void SetStrokePattern(CPDF_Pattern* pattern, - FX_FLOAT* pValue, - uint32_t nValues); + void SetFillColor(CPDF_ColorSpace* pCS, float* pValue, uint32_t nValues); + void SetStrokeColor(CPDF_ColorSpace* pCS, float* pValue, uint32_t nValues); + void SetFillPattern(CPDF_Pattern* pattern, float* pValue, uint32_t nValues); + void SetStrokePattern(CPDF_Pattern* pattern, float* pValue, uint32_t nValues); - explicit operator bool() const { return !!m_Ref; } + bool HasRef() const { return !!m_Ref; } private: - class ColorData { + class ColorData : public Retainable { public: ColorData(); ColorData(const ColorData& src); - ~ColorData(); + ~ColorData() override; void SetDefault(); @@ -68,10 +63,10 @@ class CPDF_ColorState { void SetColor(CPDF_Color& color, uint32_t& rgb, CPDF_ColorSpace* pCS, - FX_FLOAT* pValue, + float* pValue, uint32_t nValues); - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; #endif // CORE_FPDFAPI_PAGE_CPDF_COLORSTATE_H_ diff --git a/core/fpdfapi/page/cpdf_contentmark.cpp b/core/fpdfapi/page/cpdf_contentmark.cpp index 07f0bd931d73528a626a49d2211bd80864214a58..c54ef55b1fc18df8e7578634774f4ff4afae74da 100644 --- a/core/fpdfapi/page/cpdf_contentmark.cpp +++ b/core/fpdfapi/page/cpdf_contentmark.cpp @@ -6,11 +6,9 @@ #include "core/fpdfapi/page/cpdf_contentmark.h" -#include #include #include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "third_party/base/stl_util.h" CPDF_ContentMark::CPDF_ContentMark() {} @@ -19,24 +17,20 @@ CPDF_ContentMark::CPDF_ContentMark(const CPDF_ContentMark& that) CPDF_ContentMark::~CPDF_ContentMark() {} -void CPDF_ContentMark::SetNull() { - m_Ref.SetNull(); -} - -int CPDF_ContentMark::CountItems() const { +size_t CPDF_ContentMark::CountItems() const { return m_Ref.GetObject()->CountItems(); } -const CPDF_ContentMarkItem& CPDF_ContentMark::GetItem(int i) const { +const CPDF_ContentMarkItem& CPDF_ContentMark::GetItem(size_t i) const { return m_Ref.GetObject()->GetItem(i); } -int CPDF_ContentMark::GetMCID() const { +int CPDF_ContentMark::GetMarkedContentID() const { const MarkData* pData = m_Ref.GetObject(); - return pData ? pData->GetMCID() : -1; + return pData ? pData->GetMarkedContentID() : -1; } -void CPDF_ContentMark::AddMark(const CFX_ByteString& name, +void CPDF_ContentMark::AddMark(const ByteString& name, CPDF_Dictionary* pDict, bool bDirect) { m_Ref.GetPrivateCopy()->AddMark(name, pDict, bDirect); @@ -48,34 +42,6 @@ void CPDF_ContentMark::DeleteLastMark() { m_Ref.SetNull(); } -bool CPDF_ContentMark::HasMark(const CFX_ByteStringC& mark) const { - const MarkData* pData = m_Ref.GetObject(); - if (!pData) - return false; - - for (int i = 0; i < pData->CountItems(); i++) { - if (pData->GetItem(i).GetName() == mark) - return true; - } - return false; -} - -bool CPDF_ContentMark::LookupMark(const CFX_ByteStringC& mark, - CPDF_Dictionary*& pDict) const { - const MarkData* pData = m_Ref.GetObject(); - if (!pData) - return false; - - for (int i = 0; i < pData->CountItems(); i++) { - const CPDF_ContentMarkItem& item = pData->GetItem(i); - if (item.GetName() == mark) { - pDict = item.GetParam(); - return true; - } - } - return false; -} - CPDF_ContentMark::MarkData::MarkData() {} CPDF_ContentMark::MarkData::MarkData(const MarkData& src) @@ -83,40 +49,34 @@ CPDF_ContentMark::MarkData::MarkData(const MarkData& src) CPDF_ContentMark::MarkData::~MarkData() {} -int CPDF_ContentMark::MarkData::CountItems() const { - return pdfium::CollectionSize(m_Marks); -} - -CPDF_ContentMarkItem& CPDF_ContentMark::MarkData::GetItem(int index) { - return m_Marks[index]; +size_t CPDF_ContentMark::MarkData::CountItems() const { + return m_Marks.size(); } const CPDF_ContentMarkItem& CPDF_ContentMark::MarkData::GetItem( - int index) const { + size_t index) const { return m_Marks[index]; } -int CPDF_ContentMark::MarkData::GetMCID() const { +int CPDF_ContentMark::MarkData::GetMarkedContentID() const { for (const auto& mark : m_Marks) { - CPDF_Dictionary* pDict = mark.GetParam(); + const CPDF_Dictionary* pDict = mark.GetParam(); if (pDict && pDict->KeyExist("MCID")) return pDict->GetIntegerFor("MCID"); } return -1; } -void CPDF_ContentMark::MarkData::AddMark(const CFX_ByteString& name, +void CPDF_ContentMark::MarkData::AddMark(const ByteString& name, CPDF_Dictionary* pDict, bool bDirect) { CPDF_ContentMarkItem item; item.SetName(name); if (pDict) { - if (bDirect) { - item.SetDirectDict( - std::unique_ptr(ToDictionary(pDict->Clone()))); - } else { + if (bDirect) + item.SetDirectDict(ToDictionary(pDict->Clone())); + else item.SetPropertiesDict(pDict); - } } m_Marks.push_back(std::move(item)); } diff --git a/core/fpdfapi/page/cpdf_contentmark.h b/core/fpdfapi/page/cpdf_contentmark.h index 154f19d529692e1ad52fd502f92ce8ef278a2565..78a948697e2c5f7da4dcf0f91e5b585efccc4da1 100644 --- a/core/fpdfapi/page/cpdf_contentmark.h +++ b/core/fpdfapi/page/cpdf_contentmark.h @@ -10,9 +10,8 @@ #include #include "core/fpdfapi/page/cpdf_contentmarkitem.h" -#include "core/fxcrt/cfx_shared_copy_on_write.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/shared_copy_on_write.h" class CPDF_Dictionary; @@ -22,34 +21,27 @@ class CPDF_ContentMark { CPDF_ContentMark(const CPDF_ContentMark& that); ~CPDF_ContentMark(); - void SetNull(); + int GetMarkedContentID() const; + size_t CountItems() const; + const CPDF_ContentMarkItem& GetItem(size_t i) const; - int GetMCID() const; - int CountItems() const; - const CPDF_ContentMarkItem& GetItem(int i) const; - - bool HasMark(const CFX_ByteStringC& mark) const; - bool LookupMark(const CFX_ByteStringC& mark, CPDF_Dictionary*& pDict) const; - void AddMark(const CFX_ByteString& name, - CPDF_Dictionary* pDict, - bool bDirect); + void AddMark(const ByteString& name, CPDF_Dictionary* pDict, bool bDirect); void DeleteLastMark(); - explicit operator bool() const { return !!m_Ref; } + bool HasRef() const { return !!m_Ref; } private: - class MarkData { + class MarkData : public Retainable { public: MarkData(); MarkData(const MarkData& src); - ~MarkData(); + ~MarkData() override; - int CountItems() const; - CPDF_ContentMarkItem& GetItem(int index); - const CPDF_ContentMarkItem& GetItem(int index) const; + size_t CountItems() const; + const CPDF_ContentMarkItem& GetItem(size_t index) const; - int GetMCID() const; - void AddMark(const CFX_ByteString& name, + int GetMarkedContentID() const; + void AddMark(const ByteString& name, CPDF_Dictionary* pDict, bool bDictNeedClone); void DeleteLastMark(); @@ -58,7 +50,7 @@ class CPDF_ContentMark { std::vector m_Marks; }; - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; #endif // CORE_FPDFAPI_PAGE_CPDF_CONTENTMARK_H_ diff --git a/core/fpdfapi/page/cpdf_contentmarkitem.cpp b/core/fpdfapi/page/cpdf_contentmarkitem.cpp index 2c370141e2ae8832f78fb686f35ccb577d3f3678..de720b39fcbb6895a500b9079069a502880a0716 100644 --- a/core/fpdfapi/page/cpdf_contentmarkitem.cpp +++ b/core/fpdfapi/page/cpdf_contentmarkitem.cpp @@ -26,7 +26,7 @@ CPDF_ContentMarkItem::~CPDF_ContentMarkItem() {} CPDF_Dictionary* CPDF_ContentMarkItem::GetParam() const { switch (m_ParamType) { case PropertiesDict: - return m_pPropertiesDict; + return m_pPropertiesDict.Get(); case DirectDict: return m_pDirectDict.get(); case None: diff --git a/core/fpdfapi/page/cpdf_contentmarkitem.h b/core/fpdfapi/page/cpdf_contentmarkitem.h index ed2737111be7ce595c1347aa3fd16685b2ab74a9..ea89606816ed1f14567b14ef9425512c51f20d48 100644 --- a/core/fpdfapi/page/cpdf_contentmarkitem.h +++ b/core/fpdfapi/page/cpdf_contentmarkitem.h @@ -12,6 +12,7 @@ #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; @@ -25,19 +26,19 @@ class CPDF_ContentMarkItem { CPDF_ContentMarkItem& operator=(CPDF_ContentMarkItem&& other) = default; - CFX_ByteString GetName() const { return m_MarkName; } + ByteString GetName() const { return m_MarkName; } ParamType GetParamType() const { return m_ParamType; } CPDF_Dictionary* GetParam() const; bool HasMCID() const; - void SetName(const CFX_ByteString& name) { m_MarkName = name; } + void SetName(const ByteString& name) { m_MarkName = name; } void SetDirectDict(std::unique_ptr pDict); void SetPropertiesDict(CPDF_Dictionary* pDict); private: - CFX_ByteString m_MarkName; + ByteString m_MarkName; ParamType m_ParamType; - CPDF_Dictionary* m_pPropertiesDict; // not owned. + UnownedPtr m_pPropertiesDict; std::unique_ptr m_pDirectDict; }; diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp index 7ceb509348a08cd8e46f819de8a1be6207cb7ea6..93151af3053b588a658420e318e8ddb40ed524f2 100644 --- a/core/fpdfapi/page/cpdf_contentparser.cpp +++ b/core/fpdfapi/page/cpdf_contentparser.cpp @@ -17,68 +17,54 @@ #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/ifx_pauseindicator.h" #include "third_party/base/ptr_util.h" #define PARSE_STEP_LIMIT 100 -CPDF_ContentParser::CPDF_ContentParser() - : m_Status(Ready), - m_InternalStage(STAGE_GETCONTENT), - m_pObjectHolder(nullptr), - m_bForm(false), - m_pType3Char(nullptr), - m_pData(nullptr), - m_Size(0), - m_CurrentOffset(0) {} - -CPDF_ContentParser::~CPDF_ContentParser() { - if (!m_pSingleStream) - FX_Free(m_pData); -} - -void CPDF_ContentParser::Start(CPDF_Page* pPage) { - if (m_Status != Ready || !pPage || !pPage->m_pDocument || - !pPage->m_pFormDict) { - m_Status = Done; +CPDF_ContentParser::CPDF_ContentParser(CPDF_Page* pPage) + : m_InternalStage(STAGE_GETCONTENT), m_pObjectHolder(pPage) { + if (!pPage || !pPage->m_pDocument || !pPage->m_pFormDict) { + m_bIsDone = true; return; } - m_pObjectHolder = pPage; - m_bForm = false; - m_Status = ToBeContinued; - m_InternalStage = STAGE_GETCONTENT; - m_CurrentOffset = 0; CPDF_Object* pContent = pPage->m_pFormDict->GetDirectObjectFor("Contents"); if (!pContent) { - m_Status = Done; + m_bIsDone = true; + return; + } + CPDF_Stream* pStream = pContent->AsStream(); + if (pStream) { + m_pSingleStream = pdfium::MakeRetain(pStream); + m_pSingleStream->LoadAllDataFiltered(); + return; + } + CPDF_Array* pArray = pContent->AsArray(); + if (!pArray) { + m_bIsDone = true; return; } - if (CPDF_Stream* pStream = pContent->AsStream()) { - m_nStreams = 0; - m_pSingleStream = pdfium::MakeUnique(); - m_pSingleStream->LoadAllData(pStream, false); - } else if (CPDF_Array* pArray = pContent->AsArray()) { - m_nStreams = pArray->GetCount(); - if (m_nStreams) - m_StreamArray.resize(m_nStreams); - else - m_Status = Done; - } else { - m_Status = Done; + m_nStreams = pArray->GetCount(); + if (!m_nStreams) { + m_bIsDone = true; + return; } + m_StreamArray.resize(m_nStreams); } -void CPDF_ContentParser::Start(CPDF_Form* pForm, - CPDF_AllStates* pGraphicStates, - const CFX_Matrix* pParentMatrix, - CPDF_Type3Char* pType3Char, - int level) { - m_pType3Char = pType3Char; - m_pObjectHolder = pForm; - m_bForm = true; +CPDF_ContentParser::CPDF_ContentParser(CPDF_Form* pForm, + CPDF_AllStates* pGraphicStates, + const CFX_Matrix* pParentMatrix, + CPDF_Type3Char* pType3Char, + std::set* parsedSet) + : m_InternalStage(STAGE_PARSE), + m_pObjectHolder(pForm), + m_pType3Char(pType3Char) { CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixFor("Matrix"); if (pGraphicStates) form_matrix.Concat(pGraphicStates->m_CTM); + CPDF_Array* pBBox = pForm->m_pFormDict->GetArrayFor("BBox"); CFX_FloatRect form_bbox; CPDF_Path ClipPath; @@ -91,41 +77,43 @@ void CPDF_ContentParser::Start(CPDF_Form* pForm, if (pParentMatrix) ClipPath.Transform(pParentMatrix); - form_matrix.TransformRect(form_bbox); + form_bbox = form_matrix.TransformRect(form_bbox); if (pParentMatrix) - pParentMatrix->TransformRect(form_bbox); + form_bbox = pParentMatrix->TransformRect(form_bbox); } CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDictFor("Resources"); m_pParser = pdfium::MakeUnique( - pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources, - pParentMatrix, pForm, pResources, &form_bbox, pGraphicStates, level); + pForm->m_pDocument.Get(), pForm->m_pPageResources.Get(), + pForm->m_pResources.Get(), pParentMatrix, pForm, pResources, form_bbox, + pGraphicStates, parsedSet); m_pParser->GetCurStates()->m_CTM = form_matrix; m_pParser->GetCurStates()->m_ParentMatrix = form_matrix; - if (ClipPath) { + if (ClipPath.HasRef()) { m_pParser->GetCurStates()->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, true); } - if (pForm->m_Transparency & PDFTRANS_GROUP) { + if (pForm->m_iTransparency & PDFTRANS_GROUP) { CPDF_GeneralState* pState = &m_pParser->GetCurStates()->m_GeneralState; pState->SetBlendType(FXDIB_BLEND_NORMAL); pState->SetStrokeAlpha(1.0f); pState->SetFillAlpha(1.0f); pState->SetSoftMask(nullptr); } - m_nStreams = 0; - m_pSingleStream = pdfium::MakeUnique(); - m_pSingleStream->LoadAllData(pForm->m_pFormStream, false); - m_pData = (uint8_t*)m_pSingleStream->GetData(); + m_pSingleStream = + pdfium::MakeRetain(pForm->m_pFormStream.Get()); + m_pSingleStream->LoadAllDataFiltered(); + m_pData.Reset(m_pSingleStream->GetData()); m_Size = m_pSingleStream->GetSize(); - m_Status = ToBeContinued; - m_InternalStage = STAGE_PARSE; - m_CurrentOffset = 0; } -void CPDF_ContentParser::Continue(IFX_Pause* pPause) { - int steps = 0; - while (m_Status == ToBeContinued) { +CPDF_ContentParser::~CPDF_ContentParser() {} + +bool CPDF_ContentParser::Continue(IFX_PauseIndicator* pPause) { + if (m_bIsDone) + return false; + + while (!m_bIsDone) { if (m_InternalStage == STAGE_GETCONTENT) { if (m_CurrentOffset == m_nStreams) { if (!m_StreamArray.empty()) { @@ -135,20 +123,21 @@ void CPDF_ContentParser::Continue(IFX_Pause* pPause) { safeSize += 1; } if (!safeSize.IsValid()) { - m_Status = Done; - return; + m_bIsDone = true; + return false; } m_Size = safeSize.ValueOrDie(); - m_pData = FX_Alloc(uint8_t, m_Size); + m_pData.Reset(std::unique_ptr( + FX_Alloc(uint8_t, m_Size))); uint32_t pos = 0; for (const auto& stream : m_StreamArray) { - FXSYS_memcpy(m_pData + pos, stream->GetData(), stream->GetSize()); + memcpy(m_pData.Get() + pos, stream->GetData(), stream->GetSize()); pos += stream->GetSize(); - m_pData[pos++] = ' '; + m_pData.Get()[pos++] = ' '; } m_StreamArray.clear(); } else { - m_pData = (uint8_t*)m_pSingleStream->GetData(); + m_pData.Reset(m_pSingleStream->GetData()); m_Size = m_pSingleStream->GetSize(); } m_InternalStage = STAGE_PARSE; @@ -156,50 +145,46 @@ void CPDF_ContentParser::Continue(IFX_Pause* pPause) { } else { CPDF_Array* pContent = m_pObjectHolder->m_pFormDict->GetArrayFor("Contents"); - m_StreamArray[m_CurrentOffset] = pdfium::MakeUnique(); CPDF_Stream* pStreamObj = ToStream( pContent ? pContent->GetDirectObjectAt(m_CurrentOffset) : nullptr); - m_StreamArray[m_CurrentOffset]->LoadAllData(pStreamObj, false); + m_StreamArray[m_CurrentOffset] = + pdfium::MakeRetain(pStreamObj); + m_StreamArray[m_CurrentOffset]->LoadAllDataFiltered(); m_CurrentOffset++; } } if (m_InternalStage == STAGE_PARSE) { if (!m_pParser) { + m_parsedSet = pdfium::MakeUnique>(); m_pParser = pdfium::MakeUnique( - m_pObjectHolder->m_pDocument, m_pObjectHolder->m_pPageResources, - nullptr, nullptr, m_pObjectHolder, m_pObjectHolder->m_pResources, - &m_pObjectHolder->m_BBox, nullptr, 0); + m_pObjectHolder->m_pDocument.Get(), + m_pObjectHolder->m_pPageResources.Get(), nullptr, nullptr, + m_pObjectHolder.Get(), m_pObjectHolder->m_pResources.Get(), + m_pObjectHolder->m_BBox, nullptr, m_parsedSet.get()); m_pParser->GetCurStates()->m_ColorState.SetDefault(); } if (m_CurrentOffset >= m_Size) { m_InternalStage = STAGE_CHECKCLIP; } else { m_CurrentOffset += - m_pParser->Parse(m_pData + m_CurrentOffset, + m_pParser->Parse(m_pData.Get() + m_CurrentOffset, m_Size - m_CurrentOffset, PARSE_STEP_LIMIT); } } if (m_InternalStage == STAGE_CHECKCLIP) { if (m_pType3Char) { - m_pType3Char->m_bColored = m_pParser->IsColored(); - m_pType3Char->m_Width = - FXSYS_round(m_pParser->GetType3Data()[0] * 1000); - m_pType3Char->m_BBox.left = - FXSYS_round(m_pParser->GetType3Data()[2] * 1000); - m_pType3Char->m_BBox.bottom = - FXSYS_round(m_pParser->GetType3Data()[3] * 1000); - m_pType3Char->m_BBox.right = - FXSYS_round(m_pParser->GetType3Data()[4] * 1000); - m_pType3Char->m_BBox.top = - FXSYS_round(m_pParser->GetType3Data()[5] * 1000); + m_pType3Char->InitializeFromStreamData(m_pParser->IsColored(), + m_pParser->GetType3Data()); } + for (auto& pObj : *m_pObjectHolder->GetPageObjectList()) { - if (!pObj->m_ClipPath) + if (!pObj->m_ClipPath.HasRef()) continue; if (pObj->m_ClipPath.GetPathCount() != 1) continue; - if (pObj->m_ClipPath.GetTextCount()) + if (pObj->m_ClipPath.GetTextCount() > 0) continue; + CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0); if (!ClipPath.IsRect() || pObj->IsShading()) continue; @@ -212,11 +197,11 @@ void CPDF_ContentParser::Continue(IFX_Pause* pPause) { if (old_rect.Contains(obj_rect)) pObj->m_ClipPath.SetNull(); } - m_Status = Done; - return; + m_bIsDone = true; + return false; } - steps++; if (pPause && pPause->NeedToPauseNow()) break; } + return true; } diff --git a/core/fpdfapi/page/cpdf_contentparser.h b/core/fpdfapi/page/cpdf_contentparser.h index 5fd11f6c0b41f297cc3ec51bbe1489f73bc9ae68..c65da6da55f59a135bb302fcd93ddbfd2ebb9982 100644 --- a/core/fpdfapi/page/cpdf_contentparser.h +++ b/core/fpdfapi/page/cpdf_contentparser.h @@ -8,10 +8,14 @@ #define CORE_FPDFAPI_PAGE_CPDF_CONTENTPARSER_H_ #include +#include #include #include "core/fpdfapi/page/cpdf_pageobjectholder.h" #include "core/fpdfapi/page/cpdf_streamcontentparser.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_AllStates; class CPDF_Form; @@ -21,19 +25,19 @@ class CPDF_Type3Char; class CPDF_ContentParser { public: - enum ParseStatus { Ready, ToBeContinued, Done }; - - CPDF_ContentParser(); + explicit CPDF_ContentParser(CPDF_Page* pPage); + CPDF_ContentParser(CPDF_Form* pForm, + CPDF_AllStates* pGraphicStates, + const CFX_Matrix* pParentMatrix, + CPDF_Type3Char* pType3Char, + std::set* parsedSet); ~CPDF_ContentParser(); - ParseStatus GetStatus() const { return m_Status; } - void Start(CPDF_Page* pPage); - void Start(CPDF_Form* pForm, - CPDF_AllStates* pGraphicStates, - const CFX_Matrix* pParentMatrix, - CPDF_Type3Char* pType3Char, - int level); - void Continue(IFX_Pause* pPause); + const CPDF_AllStates* GetCurStates() const { + return m_pParser ? m_pParser->GetCurStates() : nullptr; + } + // Returns whether to continue or not. + bool Continue(IFX_PauseIndicator* pPause); private: enum InternalStage { @@ -42,17 +46,22 @@ class CPDF_ContentParser { STAGE_CHECKCLIP, }; - ParseStatus m_Status; + bool m_bIsDone = false; InternalStage m_InternalStage; - CPDF_PageObjectHolder* m_pObjectHolder; - bool m_bForm; - CPDF_Type3Char* m_pType3Char; - uint32_t m_nStreams; - std::unique_ptr m_pSingleStream; - std::vector> m_StreamArray; - uint8_t* m_pData; - uint32_t m_Size; - uint32_t m_CurrentOffset; + UnownedPtr const m_pObjectHolder; + UnownedPtr m_pType3Char; // Only used when parsing forms. + uint32_t m_nStreams = 0; + RetainPtr m_pSingleStream; + std::vector> m_StreamArray; + MaybeOwned m_pData; + uint32_t m_Size = 0; + uint32_t m_CurrentOffset = 0; + + // Only used when parsing pages. + std::unique_ptr> m_parsedSet; + + // |m_pParser| has a reference to |m_parsedSet|, so must be below and thus + // destroyed first. std::unique_ptr m_pParser; }; diff --git a/core/fpdfapi/page/cpdf_countedobject.h b/core/fpdfapi/page/cpdf_countedobject.h index 64f936c52c4b0026bd3f5cb69a2f5cfa7ea85878..cb39616f2bbfe151ac8f627b85488a42d61090bb 100644 --- a/core/fpdfapi/page/cpdf_countedobject.h +++ b/core/fpdfapi/page/cpdf_countedobject.h @@ -9,8 +9,6 @@ #include -#include "core/fpdfapi/page/cpdf_colorspace.h" -#include "core/fpdfapi/page/cpdf_pattern.h" #include "core/fxcrt/fx_system.h" template @@ -44,7 +42,5 @@ class CPDF_CountedObject { size_t m_nCount; T* m_pObj; }; -using CPDF_CountedColorSpace = CPDF_CountedObject; -using CPDF_CountedPattern = CPDF_CountedObject; #endif // CORE_FPDFAPI_PAGE_CPDF_COUNTEDOBJECT_H_ diff --git a/core/fpdfapi/page/cpdf_devicecs.cpp b/core/fpdfapi/page/cpdf_devicecs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9eb4123b255b82a3c1f760786a7a3681ff1d2089 --- /dev/null +++ b/core/fpdfapi/page/cpdf_devicecs.cpp @@ -0,0 +1,152 @@ +// 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 "core/fpdfapi/page/cpdf_devicecs.h" + +#include + +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fxcodec/fx_codec.h" +#include "third_party/base/logging.h" +#include "third_party/base/stl_util.h" + +namespace { + +float NormalizeChannel(float fVal) { + return pdfium::clamp(fVal, 0.0f, 1.0f); +} + +} // namespace + +uint32_t ComponentsForFamily(int family) { + if (family == PDFCS_DEVICERGB) + return 3; + if (family == PDFCS_DEVICEGRAY) + return 1; + ASSERT(family == PDFCS_DEVICECMYK); + return 4; +} + +void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels) { + if (pDestBuf == pSrcBuf) { + for (int i = 0; i < pixels; i++) { + uint8_t temp = pDestBuf[2]; + pDestBuf[2] = pDestBuf[0]; + pDestBuf[0] = temp; + pDestBuf += 3; + } + } else { + for (int i = 0; i < pixels; i++) { + *pDestBuf++ = pSrcBuf[2]; + *pDestBuf++ = pSrcBuf[1]; + *pDestBuf++ = pSrcBuf[0]; + pSrcBuf += 3; + } + } +} + +CPDF_DeviceCS::CPDF_DeviceCS(int family) : CPDF_ColorSpace(nullptr, family) { + ASSERT(family == PDFCS_DEVICEGRAY || family == PDFCS_DEVICERGB || + family == PDFCS_DEVICECMYK); + SetComponentsForStockCS(ComponentsForFamily(GetFamily())); +} + +CPDF_DeviceCS::~CPDF_DeviceCS() {} + +uint32_t CPDF_DeviceCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { + // Unlike other classes that inherit from CPDF_ColorSpace, CPDF_DeviceCS is + // never loaded by CPDF_ColorSpace. + NOTREACHED(); + return 0; +} + +bool CPDF_DeviceCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { + switch (m_Family) { + case PDFCS_DEVICEGRAY: + *R = NormalizeChannel(*pBuf); + *G = *R; + *B = *R; + return true; + case PDFCS_DEVICERGB: + *R = NormalizeChannel(pBuf[0]); + *G = NormalizeChannel(pBuf[1]); + *B = NormalizeChannel(pBuf[2]); + return true; + case PDFCS_DEVICECMYK: + if (m_dwStdConversion) { + float k = pBuf[3]; + *R = 1.0f - std::min(1.0f, pBuf[0] + k); + *G = 1.0f - std::min(1.0f, pBuf[1] + k); + *B = 1.0f - std::min(1.0f, pBuf[2] + k); + } else { + std::tie(*R, *G, *B) = AdobeCMYK_to_sRGB( + NormalizeChannel(pBuf[0]), NormalizeChannel(pBuf[1]), + NormalizeChannel(pBuf[2]), NormalizeChannel(pBuf[3])); + } + return true; + default: + NOTREACHED(); + return false; + } +} + +void CPDF_DeviceCS::TranslateImageLine(uint8_t* pDestBuf, + const uint8_t* pSrcBuf, + int pixels, + int image_width, + int image_height, + bool bTransMask) const { + switch (m_Family) { + case PDFCS_DEVICEGRAY: + for (int i = 0; i < pixels; i++) { + *pDestBuf++ = pSrcBuf[i]; + *pDestBuf++ = pSrcBuf[i]; + *pDestBuf++ = pSrcBuf[i]; + } + break; + case PDFCS_DEVICERGB: + ReverseRGB(pDestBuf, pSrcBuf, pixels); + break; + case PDFCS_DEVICECMYK: + if (bTransMask) { + for (int i = 0; i < pixels; i++) { + int k = 255 - pSrcBuf[3]; + pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255; + pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255; + pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255; + pDestBuf += 3; + pSrcBuf += 4; + } + } else { + for (int i = 0; i < pixels; i++) { + if (m_dwStdConversion) { + uint8_t k = pSrcBuf[3]; + pDestBuf[2] = 255 - std::min(255, pSrcBuf[0] + k); + pDestBuf[1] = 255 - std::min(255, pSrcBuf[1] + k); + pDestBuf[0] = 255 - std::min(255, pSrcBuf[2] + k); + } else { + std::tie(pDestBuf[2], pDestBuf[1], pDestBuf[0]) = + AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2], + pSrcBuf[3]); + } + pSrcBuf += 4; + pDestBuf += 3; + } + } + break; + default: + NOTREACHED(); + break; + } +} diff --git a/core/fpdfapi/page/cpdf_devicecs.h b/core/fpdfapi/page/cpdf_devicecs.h new file mode 100644 index 0000000000000000000000000000000000000000..65e8ec8bd9a89264ff46fcf163d00df8fa8770f2 --- /dev/null +++ b/core/fpdfapi/page/cpdf_devicecs.h @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_DEVICECS_H_ +#define CORE_FPDFAPI_PAGE_CPDF_DEVICECS_H_ + +#include + +#include "core/fpdfapi/page/cpdf_colorspace.h" + +class CPDF_DeviceCS : public CPDF_ColorSpace { + public: + explicit CPDF_DeviceCS(int family); + ~CPDF_DeviceCS() override; + + // CPDF_ColorSpace: + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; + void TranslateImageLine(uint8_t* pDestBuf, + const uint8_t* pSrcBuf, + int pixels, + int image_width, + int image_height, + bool bTransMask) const override; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_DEVICECS_H_ diff --git a/core/fpdfapi/page/cpdf_devicecs_unittest.cpp b/core/fpdfapi/page/cpdf_devicecs_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a171d01f590ef0e812e8fccc18bd0119755309b4 --- /dev/null +++ b/core/fpdfapi/page/cpdf_devicecs_unittest.cpp @@ -0,0 +1,114 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_devicecs.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(CPDF_DeviceCSTest, GetRGBFromGray) { + float R; + float G; + float B; + CPDF_DeviceCS device_gray(PDFCS_DEVICEGRAY); + + // Test normal values. For gray, only first value from buf should be used. + float buf[3] = {0.43f, 0.11f, 0.34f}; + ASSERT_TRUE(device_gray.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.43f, R); + EXPECT_FLOAT_EQ(0.43f, G); + EXPECT_FLOAT_EQ(0.43f, B); + buf[0] = 0.872f; + ASSERT_TRUE(device_gray.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.872f, R); + EXPECT_FLOAT_EQ(0.872f, G); + EXPECT_FLOAT_EQ(0.872f, B); + + // Test boundary values + buf[0] = {0.0f}; + ASSERT_TRUE(device_gray.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.0f, R); + EXPECT_FLOAT_EQ(0.0f, G); + EXPECT_FLOAT_EQ(0.0f, B); + buf[0] = 1.0f; + ASSERT_TRUE(device_gray.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(1.0f, R); + EXPECT_FLOAT_EQ(1.0f, G); + EXPECT_FLOAT_EQ(1.0f, B); + + // Test out of range values + buf[0] = -0.01f; + ASSERT_TRUE(device_gray.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.0f, R); + EXPECT_FLOAT_EQ(0.0f, G); + EXPECT_FLOAT_EQ(0.0f, B); + buf[0] = 12.5f; + ASSERT_TRUE(device_gray.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(1.0f, R); + EXPECT_FLOAT_EQ(1.0f, G); + EXPECT_FLOAT_EQ(1.0f, B); +} + +TEST(CPDF_DeviceCSTest, GetRGBFromRGB) { + float R; + float G; + float B; + CPDF_DeviceCS device_rgb(PDFCS_DEVICERGB); + + // Test normal values + float buf[3] = {0.13f, 1.0f, 0.652f}; + ASSERT_TRUE(device_rgb.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.13f, R); + EXPECT_FLOAT_EQ(1.0f, G); + EXPECT_FLOAT_EQ(0.652f, B); + buf[0] = 0.0f; + buf[1] = 0.52f; + buf[2] = 0.78f; + ASSERT_TRUE(device_rgb.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.0f, R); + EXPECT_FLOAT_EQ(0.52f, G); + EXPECT_FLOAT_EQ(0.78f, B); + + // Test out of range values + buf[0] = -10.5f; + buf[1] = 100.0f; + ASSERT_TRUE(device_rgb.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.0f, R); + EXPECT_FLOAT_EQ(1.0f, G); + EXPECT_FLOAT_EQ(0.78f, B); +} + +TEST(CPDF_DeviceCSTest, GetRGBFromCMYK) { + float R; + float G; + float B; + CPDF_DeviceCS device_cmyk(PDFCS_DEVICECMYK); + + // Test normal values + float buf[4] = {0.6f, 0.5f, 0.3f, 0.9f}; + ASSERT_TRUE(device_cmyk.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.0627451f, R); + EXPECT_FLOAT_EQ(0.0627451f, G); + EXPECT_FLOAT_EQ(0.10588236f, B); + buf[0] = 0.15f; + buf[2] = 0.0f; + ASSERT_TRUE(device_cmyk.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.2f, R); + EXPECT_FLOAT_EQ(0.0862745f, G); + EXPECT_FLOAT_EQ(0.16470589f, B); + buf[2] = 1.0f; + buf[3] = 0.0f; + ASSERT_TRUE(device_cmyk.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.85098046f, R); + EXPECT_FLOAT_EQ(0.552941f, G); + EXPECT_FLOAT_EQ(0.15686275f, B); + + // Test out of range values + buf[2] = 1.5f; + buf[3] = -0.6f; + ASSERT_TRUE(device_cmyk.GetRGB(buf, &R, &G, &B)); + EXPECT_FLOAT_EQ(0.85098046f, R); + EXPECT_FLOAT_EQ(0.552941f, G); + EXPECT_FLOAT_EQ(0.15686275f, B); +} diff --git a/core/fpdfapi/page/cpdf_docpagedata.cpp b/core/fpdfapi/page/cpdf_docpagedata.cpp index af2618286e5b1ee683780fc548145788d4900a02..0d2a9189b6babe0e60127dbc2e6df27a805fb97a 100644 --- a/core/fpdfapi/page/cpdf_docpagedata.cpp +++ b/core/fpdfapi/page/cpdf_docpagedata.cpp @@ -14,7 +14,7 @@ #include "core/fdrm/crypto/fx_crypt.h" #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/font/cpdf_type1font.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/page/cpdf_iccprofile.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fpdfapi/page/cpdf_pattern.h" @@ -28,7 +28,9 @@ #include "third_party/base/stl_util.h" CPDF_DocPageData::CPDF_DocPageData(CPDF_Document* pPDFDoc) - : m_pPDFDoc(pPDFDoc), m_bForceClear(false) {} + : m_bForceClear(false), m_pPDFDoc(pPDFDoc) { + assert(m_pPDFDoc); +} CPDF_DocPageData::~CPDF_DocPageData() { Clear(false); @@ -50,11 +52,26 @@ CPDF_DocPageData::~CPDF_DocPageData() { void CPDF_DocPageData::Clear(bool bForceRelease) { m_bForceClear = bForceRelease; + // This is needed because if |bForceRelease| is true we will destroy any + // pattern we see regardless of the ref-count. The tiling pattern owns a + // Form object which owns a ShadingObject. The ShadingObject has an unowned + // pointer to a ShadingPattern. The ShadingPattern is owned by the + // DocPageData. So, we loop through and clear any tiling patterns before we + // do the same for any shading patterns, otherwise we may free the + // ShadingPattern before the ShadingObject and trigger an unowned pointer + // probe warning. for (auto& it : m_PatternMap) { CPDF_CountedPattern* ptData = it.second; - if (!ptData->get()) + if (!ptData->get() || !ptData->get()->AsTilingPattern()) continue; + if (bForceRelease || ptData->use_count() < 2) + ptData->clear(); + } + for (auto& it : m_PatternMap) { + CPDF_CountedPattern* ptData = it.second; + if (!ptData->get()) + continue; if (bForceRelease || ptData->use_count() < 2) ptData->clear(); } @@ -63,7 +80,6 @@ void CPDF_DocPageData::Clear(bool bForceRelease) { CPDF_CountedFont* fontData = it.second; if (!fontData->get()) continue; - if (bForceRelease || fontData->use_count() < 2) { fontData->clear(); } @@ -73,7 +89,6 @@ void CPDF_DocPageData::Clear(bool bForceRelease) { CPDF_CountedColorSpace* csData = it.second; if (!csData->get()) continue; - if (bForceRelease || csData->use_count() < 2) { csData->get()->Release(); csData->reset(nullptr); @@ -82,11 +97,7 @@ void CPDF_DocPageData::Clear(bool bForceRelease) { for (auto it = m_IccProfileMap.begin(); it != m_IccProfileMap.end();) { auto curr_it = it++; - CPDF_CountedIccProfile* ipData = curr_it->second; - if (!ipData->get()) - continue; - - if (bForceRelease || ipData->use_count() < 2) { + if (bForceRelease || curr_it->second->HasOneRef()) { for (auto hash_it = m_HashProfileMap.begin(); hash_it != m_HashProfileMap.end(); ++hash_it) { if (curr_it->first == hash_it->second) { @@ -94,37 +105,17 @@ void CPDF_DocPageData::Clear(bool bForceRelease) { break; } } - delete ipData->get(); - delete ipData; m_IccProfileMap.erase(curr_it); } } for (auto it = m_FontFileMap.begin(); it != m_FontFileMap.end();) { auto curr_it = it++; - CPDF_CountedStreamAcc* pCountedFont = curr_it->second; - if (!pCountedFont->get()) - continue; - - if (bForceRelease || pCountedFont->use_count() < 2) { - delete pCountedFont->get(); - delete pCountedFont; + if (bForceRelease || curr_it->second->HasOneRef()) m_FontFileMap.erase(curr_it); - } } - for (auto it = m_ImageMap.begin(); it != m_ImageMap.end();) { - auto curr_it = it++; - CPDF_CountedImage* pCountedImage = curr_it->second; - if (!pCountedImage->get()) - continue; - - if (bForceRelease || pCountedImage->use_count() < 2) { - delete pCountedImage->get(); - delete pCountedImage; - m_ImageMap.erase(curr_it); - } - } + m_ImageMap.clear(); } CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict) { @@ -139,7 +130,8 @@ CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict) { return pFontData->AddRef(); } } - std::unique_ptr pFont = CPDF_Font::Create(m_pPDFDoc, pFontDict); + std::unique_ptr pFont = + CPDF_Font::Create(m_pPDFDoc.Get(), pFontDict); if (!pFont) return nullptr; @@ -152,7 +144,7 @@ CPDF_Font* CPDF_DocPageData::GetFont(CPDF_Dictionary* pFontDict) { return pFontData->AddRef(); } -CPDF_Font* CPDF_DocPageData::GetStandardFont(const CFX_ByteString& fontName, +CPDF_Font* CPDF_DocPageData::GetStandardFont(const ByteString& fontName, CPDF_FontEncoding* pEncoding) { if (fontName.IsEmpty()) return nullptr; @@ -187,7 +179,7 @@ CPDF_Font* CPDF_DocPageData::GetStandardFont(const CFX_ByteString& fontName, pEncoding->Realize(m_pPDFDoc->GetByteStringPool())); } - std::unique_ptr pFont = CPDF_Font::Create(m_pPDFDoc, pDict); + std::unique_ptr pFont = CPDF_Font::Create(m_pPDFDoc.Get(), pDict); if (!pFont) return nullptr; @@ -220,10 +212,10 @@ CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace( CPDF_Object* pCSObj, const CPDF_Dictionary* pResources) { std::set visited; - return GetColorSpaceImpl(pCSObj, pResources, &visited); + return GetColorSpaceGuarded(pCSObj, pResources, &visited); } -CPDF_ColorSpace* CPDF_DocPageData::GetColorSpaceImpl( +CPDF_ColorSpace* CPDF_DocPageData::GetColorSpaceGuarded( CPDF_Object* pCSObj, const CPDF_Dictionary* pResources, std::set* pVisited) { @@ -233,15 +225,16 @@ CPDF_ColorSpace* CPDF_DocPageData::GetColorSpaceImpl( if (pdfium::ContainsKey(*pVisited, pCSObj)) return nullptr; + pdfium::ScopedSetInsertion insertion(pVisited, pCSObj); + if (pCSObj->IsName()) { - CFX_ByteString name = pCSObj->GetString(); + ByteString name = pCSObj->GetString(); CPDF_ColorSpace* pCS = CPDF_ColorSpace::ColorspaceFromName(name); if (!pCS && pResources) { CPDF_Dictionary* pList = pResources->GetDictFor("ColorSpace"); if (pList) { - pdfium::ScopedSetInsertion insertion(pVisited, pCSObj); - return GetColorSpaceImpl(pList->GetDirectObjectFor(name), nullptr, - pVisited); + return GetColorSpaceGuarded(pList->GetDirectObjectFor(name), nullptr, + pVisited); } } if (!pCS || !pResources) @@ -266,8 +259,7 @@ CPDF_ColorSpace* CPDF_DocPageData::GetColorSpaceImpl( if (!pDefaultCS) return pCS; - pdfium::ScopedSetInsertion insertion(pVisited, pCSObj); - return GetColorSpaceImpl(pDefaultCS, nullptr, pVisited); + return GetColorSpaceGuarded(pDefaultCS, nullptr, pVisited); } CPDF_Array* pArray = pCSObj->AsArray(); @@ -275,9 +267,8 @@ CPDF_ColorSpace* CPDF_DocPageData::GetColorSpaceImpl( return nullptr; if (pArray->GetCount() == 1) { - pdfium::ScopedSetInsertion insertion(pVisited, pCSObj); - return GetColorSpaceImpl(pArray->GetDirectObjectAt(0), pResources, - pVisited); + return GetColorSpaceGuarded(pArray->GetDirectObjectAt(0), pResources, + pVisited); } CPDF_CountedColorSpace* csData = nullptr; @@ -290,7 +281,7 @@ CPDF_ColorSpace* CPDF_DocPageData::GetColorSpaceImpl( } std::unique_ptr pCS = - CPDF_ColorSpace::Load(m_pPDFDoc, pArray); + CPDF_ColorSpace::Load(m_pPDFDoc.Get(), pArray, pVisited); if (!pCS) return nullptr; @@ -351,23 +342,24 @@ CPDF_Pattern* CPDF_DocPageData::GetPattern(CPDF_Object* pPatternObj, } std::unique_ptr pPattern; if (bShading) { - pPattern = pdfium::MakeUnique(m_pPDFDoc, pPatternObj, - true, matrix); + pPattern = pdfium::MakeUnique( + m_pPDFDoc.Get(), pPatternObj, true, matrix); } else { - CPDF_Dictionary* pDict = pPatternObj ? pPatternObj->GetDict() : nullptr; - if (pDict) { - int type = pDict->GetIntegerFor("PatternType"); - if (type == CPDF_Pattern::TILING) { - pPattern = pdfium::MakeUnique(m_pPDFDoc, - pPatternObj, matrix); - } else if (type == CPDF_Pattern::SHADING) { - pPattern = pdfium::MakeUnique( - m_pPDFDoc, pPatternObj, false, matrix); - } + CPDF_Dictionary* pDict = pPatternObj->GetDict(); + if (!pDict) + return nullptr; + + int type = pDict->GetIntegerFor("PatternType"); + if (type == CPDF_Pattern::TILING) { + pPattern = pdfium::MakeUnique(m_pPDFDoc.Get(), + pPatternObj, matrix); + } else if (type == CPDF_Pattern::SHADING) { + pPattern = pdfium::MakeUnique( + m_pPDFDoc.Get(), pPatternObj, false, matrix); + } else { + return nullptr; } } - if (!pPattern) - return nullptr; if (ptData) { ptData->reset(std::move(pPattern)); @@ -398,91 +390,66 @@ void CPDF_DocPageData::ReleasePattern(const CPDF_Object* pPatternObj) { pPattern->clear(); } -CPDF_Image* CPDF_DocPageData::GetImage(uint32_t dwStreamObjNum) { +RetainPtr CPDF_DocPageData::GetImage(uint32_t dwStreamObjNum) { ASSERT(dwStreamObjNum); auto it = m_ImageMap.find(dwStreamObjNum); if (it != m_ImageMap.end()) - return it->second->AddRef(); + return it->second; - CPDF_CountedImage* pCountedImage = new CPDF_CountedImage( - pdfium::MakeUnique(m_pPDFDoc, dwStreamObjNum)); - m_ImageMap[dwStreamObjNum] = pCountedImage; - return pCountedImage->AddRef(); + auto pImage = pdfium::MakeRetain(m_pPDFDoc.Get(), dwStreamObjNum); + m_ImageMap[dwStreamObjNum] = pImage; + return pImage; } -void CPDF_DocPageData::ReleaseImage(uint32_t dwStreamObjNum) { +void CPDF_DocPageData::MaybePurgeImage(uint32_t dwStreamObjNum) { ASSERT(dwStreamObjNum); auto it = m_ImageMap.find(dwStreamObjNum); - if (it == m_ImageMap.end()) - return; - - CPDF_CountedImage* pCountedImage = it->second; - if (!pCountedImage) - return; - - pCountedImage->RemoveRef(); - if (pCountedImage->use_count() > 1) - return; - - // We have item only in m_ImageMap cache. Clean it. - delete pCountedImage->get(); - delete pCountedImage; - m_ImageMap.erase(it); + if (it != m_ImageMap.end() && it->second->HasOneRef()) + m_ImageMap.erase(it); } -CPDF_IccProfile* CPDF_DocPageData::GetIccProfile( - CPDF_Stream* pIccProfileStream) { - if (!pIccProfileStream) +RetainPtr CPDF_DocPageData::GetIccProfile( + CPDF_Stream* pProfileStream) { + if (!pProfileStream) return nullptr; - auto it = m_IccProfileMap.find(pIccProfileStream); + auto it = m_IccProfileMap.find(pProfileStream); if (it != m_IccProfileMap.end()) - return it->second->AddRef(); + return it->second; + + auto pAccessor = pdfium::MakeRetain(pProfileStream); + pAccessor->LoadAllDataFiltered(); - CPDF_StreamAcc stream; - stream.LoadAllData(pIccProfileStream, false); uint8_t digest[20]; - CRYPT_SHA1Generate(stream.GetData(), stream.GetSize(), digest); - CFX_ByteString bsDigest(digest, 20); + CRYPT_SHA1Generate(pAccessor->GetData(), pAccessor->GetSize(), digest); + + ByteString bsDigest(digest, 20); auto hash_it = m_HashProfileMap.find(bsDigest); if (hash_it != m_HashProfileMap.end()) { auto it_copied_stream = m_IccProfileMap.find(hash_it->second); if (it_copied_stream != m_IccProfileMap.end()) - return it_copied_stream->second->AddRef(); + return it_copied_stream->second; } - CPDF_CountedIccProfile* ipData = new CPDF_CountedIccProfile( - pdfium::MakeUnique(stream.GetData(), stream.GetSize())); - m_IccProfileMap[pIccProfileStream] = ipData; - m_HashProfileMap[bsDigest] = pIccProfileStream; - return ipData->AddRef(); + auto pProfile = pdfium::MakeRetain( + pProfileStream, pAccessor->GetData(), pAccessor->GetSize()); + m_IccProfileMap[pProfileStream] = pProfile; + m_HashProfileMap[bsDigest] = pProfileStream; + return pProfile; } -void CPDF_DocPageData::ReleaseIccProfile(const CPDF_IccProfile* pIccProfile) { - ASSERT(pIccProfile); - - for (auto it = m_IccProfileMap.begin(); it != m_IccProfileMap.end(); ++it) { - CPDF_CountedIccProfile* profile = it->second; - if (profile->get() != pIccProfile) - continue; - - profile->RemoveRef(); - if (profile->use_count() > 1) - continue; - // We have item only in m_IccProfileMap cache. Clean it. - delete profile->get(); - delete profile; +void CPDF_DocPageData::MaybePurgeIccProfile(CPDF_Stream* pProfileStream) { + ASSERT(pProfileStream); + auto it = m_IccProfileMap.find(pProfileStream); + if (it != m_IccProfileMap.end() && it->second->HasOneRef()) m_IccProfileMap.erase(it); - return; - } } -CPDF_StreamAcc* CPDF_DocPageData::GetFontFileStreamAcc( +RetainPtr CPDF_DocPageData::GetFontFileStreamAcc( CPDF_Stream* pFontStream) { ASSERT(pFontStream); - auto it = m_FontFileMap.find(pFontStream); if (it != m_FontFileMap.end()) - return it->second->AddRef(); + return it->second; CPDF_Dictionary* pFontDict = pFontStream->GetDict(); int32_t org_size = pFontDict->GetIntegerFor("Length1") + @@ -490,36 +457,20 @@ CPDF_StreamAcc* CPDF_DocPageData::GetFontFileStreamAcc( pFontDict->GetIntegerFor("Length3"); org_size = std::max(org_size, 0); - auto pFontAcc = pdfium::MakeUnique(); - pFontAcc->LoadAllData(pFontStream, false, org_size); - - CPDF_CountedStreamAcc* pCountedFont = - new CPDF_CountedStreamAcc(std::move(pFontAcc)); - m_FontFileMap[pFontStream] = pCountedFont; - return pCountedFont->AddRef(); + auto pFontAcc = pdfium::MakeRetain(pFontStream); + pFontAcc->LoadAllData(false, org_size, false); + m_FontFileMap[pFontStream] = pFontAcc; + return pFontAcc; } -void CPDF_DocPageData::ReleaseFontFileStreamAcc( +void CPDF_DocPageData::MaybePurgeFontFileStreamAcc( const CPDF_Stream* pFontStream) { if (!pFontStream) return; auto it = m_FontFileMap.find(pFontStream); - if (it == m_FontFileMap.end()) - return; - - CPDF_CountedStreamAcc* pCountedStream = it->second; - if (!pCountedStream) - return; - - pCountedStream->RemoveRef(); - if (pCountedStream->use_count() > 1) - return; - - // We have item only in m_FontFileMap cache. Clean it. - delete pCountedStream->get(); - delete pCountedStream; - m_FontFileMap.erase(it); + if (it != m_FontFileMap.end() && it->second->HasOneRef()) + m_FontFileMap.erase(it); } CPDF_CountedColorSpace* CPDF_DocPageData::FindColorSpacePtr( diff --git a/core/fpdfapi/page/cpdf_docpagedata.h b/core/fpdfapi/page/cpdf_docpagedata.h index 37538eb3298d0d2b9bbfefa2a96b3e8c583cb7c7..02107aa2bbad493945470fdd6c845b88cda3839e 100644 --- a/core/fpdfapi/page/cpdf_docpagedata.h +++ b/core/fpdfapi/page/cpdf_docpagedata.h @@ -10,9 +10,10 @@ #include #include -#include "core/fpdfapi/page/cpdf_countedobject.h" +#include "core/fpdfapi/page/cpdf_colorspace.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; class CPDF_Document; @@ -21,6 +22,7 @@ class CPDF_FontEncoding; class CPDF_IccProfile; class CPDF_Image; class CPDF_Object; +class CPDF_Pattern; class CPDF_Stream; class CPDF_StreamAcc; @@ -30,56 +32,51 @@ class CPDF_DocPageData { ~CPDF_DocPageData(); void Clear(bool bRelease = false); + bool IsForceClear() const { return m_bForceClear; } + CPDF_Font* GetFont(CPDF_Dictionary* pFontDict); - CPDF_Font* GetStandardFont(const CFX_ByteString& fontName, + CPDF_Font* GetStandardFont(const ByteString& fontName, CPDF_FontEncoding* pEncoding); void ReleaseFont(const CPDF_Dictionary* pFontDict); + CPDF_ColorSpace* GetColorSpace(CPDF_Object* pCSObj, const CPDF_Dictionary* pResources); + CPDF_ColorSpace* GetColorSpaceGuarded(CPDF_Object* pCSObj, + const CPDF_Dictionary* pResources, + std::set* pVisited); + CPDF_ColorSpace* GetCopiedColorSpace(CPDF_Object* pCSObj); void ReleaseColorSpace(const CPDF_Object* pColorSpace); + CPDF_Pattern* GetPattern(CPDF_Object* pPatternObj, bool bShading, const CFX_Matrix& matrix); void ReleasePattern(const CPDF_Object* pPatternObj); - CPDF_Image* GetImage(uint32_t dwStreamObjNum); - void ReleaseImage(uint32_t dwStreamObjNum); - CPDF_IccProfile* GetIccProfile(CPDF_Stream* pIccProfileStream); - void ReleaseIccProfile(const CPDF_IccProfile* pIccProfile); - CPDF_StreamAcc* GetFontFileStreamAcc(CPDF_Stream* pFontStream); - void ReleaseFontFileStreamAcc(const CPDF_Stream* pFontStream); - bool IsForceClear() const { return m_bForceClear; } + + RetainPtr GetImage(uint32_t dwStreamObjNum); + void MaybePurgeImage(uint32_t dwStreamObjNum); + + RetainPtr GetIccProfile(CPDF_Stream* pProfileStream); + void MaybePurgeIccProfile(CPDF_Stream* pProfileStream); + + RetainPtr GetFontFileStreamAcc(CPDF_Stream* pFontStream); + void MaybePurgeFontFileStreamAcc(const CPDF_Stream* pFontStream); + CPDF_CountedColorSpace* FindColorSpacePtr(CPDF_Object* pCSObj) const; CPDF_CountedPattern* FindPatternPtr(CPDF_Object* pPatternObj) const; private: using CPDF_CountedFont = CPDF_CountedObject; - using CPDF_CountedIccProfile = CPDF_CountedObject; - using CPDF_CountedImage = CPDF_CountedObject; - using CPDF_CountedStreamAcc = CPDF_CountedObject; - - using CPDF_ColorSpaceMap = - std::map; - using CPDF_FontFileMap = std::map; - using CPDF_FontMap = std::map; - using CPDF_IccProfileMap = - std::map; - using CPDF_ImageMap = std::map; - using CPDF_PatternMap = std::map; - - CPDF_ColorSpace* GetColorSpaceImpl(CPDF_Object* pCSObj, - const CPDF_Dictionary* pResources, - std::set* pVisited); - - CPDF_Document* const m_pPDFDoc; + bool m_bForceClear; - std::map m_HashProfileMap; - CPDF_ColorSpaceMap m_ColorSpaceMap; - CPDF_FontFileMap m_FontFileMap; - CPDF_FontMap m_FontMap; - CPDF_IccProfileMap m_IccProfileMap; - CPDF_ImageMap m_ImageMap; - CPDF_PatternMap m_PatternMap; + UnownedPtr const m_pPDFDoc; + std::map m_HashProfileMap; + std::map m_ColorSpaceMap; + std::map> m_FontFileMap; + std::map m_FontMap; + std::map> m_IccProfileMap; + std::map> m_ImageMap; + std::map m_PatternMap; }; #endif // CORE_FPDFAPI_PAGE_CPDF_DOCPAGEDATA_H_ diff --git a/core/fpdfapi/page/cpdf_expintfunc.cpp b/core/fpdfapi/page/cpdf_expintfunc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d1213131bbebe58b7fe1260b4420cf551aafb15 --- /dev/null +++ b/core/fpdfapi/page/cpdf_expintfunc.cpp @@ -0,0 +1,60 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_expintfunc.h" + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fxcrt/fx_memory.h" + +CPDF_ExpIntFunc::CPDF_ExpIntFunc() + : CPDF_Function(Type::kType2ExpotentialInterpolation), + m_pBeginValues(nullptr), + m_pEndValues(nullptr) {} + +CPDF_ExpIntFunc::~CPDF_ExpIntFunc() { + FX_Free(m_pBeginValues); + FX_Free(m_pEndValues); +} + +bool CPDF_ExpIntFunc::v_Init(CPDF_Object* pObj) { + CPDF_Dictionary* pDict = pObj->GetDict(); + if (!pDict) + return false; + + CPDF_Array* pArray0 = pDict->GetArrayFor("C0"); + if (m_nOutputs == 0) { + m_nOutputs = 1; + if (pArray0) + m_nOutputs = pArray0->GetCount(); + } + + CPDF_Array* pArray1 = pDict->GetArrayFor("C1"); + m_pBeginValues = FX_Alloc2D(float, m_nOutputs, 2); + m_pEndValues = FX_Alloc2D(float, m_nOutputs, 2); + for (uint32_t i = 0; i < m_nOutputs; i++) { + m_pBeginValues[i] = pArray0 ? pArray0->GetFloatAt(i) : 0.0f; + m_pEndValues[i] = pArray1 ? pArray1->GetFloatAt(i) : 1.0f; + } + + m_Exponent = pDict->GetFloatFor("N"); + m_nOrigOutputs = m_nOutputs; + if (m_nOutputs && m_nInputs > INT_MAX / m_nOutputs) + return false; + + m_nOutputs *= m_nInputs; + return true; +} + +bool CPDF_ExpIntFunc::v_Call(float* inputs, float* results) const { + for (uint32_t i = 0; i < m_nInputs; i++) + for (uint32_t j = 0; j < m_nOrigOutputs; j++) { + results[i * m_nOrigOutputs + j] = + m_pBeginValues[j] + FXSYS_pow(inputs[i], m_Exponent) * + (m_pEndValues[j] - m_pBeginValues[j]); + } + return true; +} diff --git a/core/fpdfapi/page/cpdf_expintfunc.h b/core/fpdfapi/page/cpdf_expintfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..867d2fa265329d943d1da0c99604d58a8236e2b2 --- /dev/null +++ b/core/fpdfapi/page/cpdf_expintfunc.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_EXPINTFUNC_H_ +#define CORE_FPDFAPI_PAGE_CPDF_EXPINTFUNC_H_ + +#include "core/fpdfapi/page/cpdf_function.h" + +class CPDF_ExpIntFunc : public CPDF_Function { + public: + CPDF_ExpIntFunc(); + ~CPDF_ExpIntFunc() override; + + // CPDF_Function + bool v_Init(CPDF_Object* pObj) override; + bool v_Call(float* inputs, float* results) const override; + + uint32_t m_nOrigOutputs; + float m_Exponent; + float* m_pBeginValues; + float* m_pEndValues; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_EXPINTFUNC_H_ diff --git a/core/fpdfapi/page/cpdf_form.cpp b/core/fpdfapi/page/cpdf_form.cpp index b3f2b372e331278f4557019c846d31f7a1e0d633..bb06cbfe6f2ba3cd2ea0bb852a6bcea240bb99c3 100644 --- a/core/fpdfapi/page/cpdf_form.cpp +++ b/core/fpdfapi/page/cpdf_form.cpp @@ -9,7 +9,6 @@ #include "core/fpdfapi/page/cpdf_contentparser.h" #include "core/fpdfapi/page/cpdf_pageobject.h" #include "core/fpdfapi/page/cpdf_pageobjectholder.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "third_party/base/ptr_util.h" @@ -17,17 +16,16 @@ CPDF_Form::CPDF_Form(CPDF_Document* pDoc, CPDF_Dictionary* pPageResources, CPDF_Stream* pFormStream, - CPDF_Dictionary* pParentResources) { - m_pDocument = pDoc; + CPDF_Dictionary* pParentResources) + : CPDF_PageObjectHolder(pDoc, pFormStream->GetDict()) { m_pFormStream = pFormStream; - m_pFormDict = pFormStream ? pFormStream->GetDict() : nullptr; m_pResources = m_pFormDict->GetDictFor("Resources"); m_pPageResources = pPageResources; if (!m_pResources) m_pResources = pParentResources; if (!m_pResources) m_pResources = pPageResources; - m_Transparency = 0; + m_iTransparency = 0; LoadTransInfo(); } @@ -36,19 +34,29 @@ CPDF_Form::~CPDF_Form() {} void CPDF_Form::StartParse(CPDF_AllStates* pGraphicStates, const CFX_Matrix* pParentMatrix, CPDF_Type3Char* pType3Char, - int level) { + std::set* parsedSet) { if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) return; - m_pParser = pdfium::MakeUnique(); - m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, level); + if (!parsedSet) { + if (!m_ParsedSet) + m_ParsedSet = pdfium::MakeUnique>(); + parsedSet = m_ParsedSet.get(); + } + + m_pParser = pdfium::MakeUnique( + this, pGraphicStates, pParentMatrix, pType3Char, parsedSet); m_ParseState = CONTENT_PARSING; } -void CPDF_Form::ParseContent(CPDF_AllStates* pGraphicStates, - const CFX_Matrix* pParentMatrix, - CPDF_Type3Char* pType3Char, - int level) { - StartParse(pGraphicStates, pParentMatrix, pType3Char, level); +void CPDF_Form::ParseContent() { + ParseContentWithParams(nullptr, nullptr, nullptr, nullptr); +} + +void CPDF_Form::ParseContentWithParams(CPDF_AllStates* pGraphicStates, + const CFX_Matrix* pParentMatrix, + CPDF_Type3Char* pType3Char, + std::set* parsedSet) { + StartParse(pGraphicStates, pParentMatrix, pType3Char, parsedSet); ContinueParse(nullptr); } diff --git a/core/fpdfapi/page/cpdf_form.h b/core/fpdfapi/page/cpdf_form.h index 910f38fd0818f5d3914c496ec756c185ef9932a6..c5285a1d019188c59aa78df6d8b4de8c79852b84 100644 --- a/core/fpdfapi/page/cpdf_form.h +++ b/core/fpdfapi/page/cpdf_form.h @@ -7,6 +7,9 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_FORM_H_ #define CORE_FPDFAPI_PAGE_CPDF_FORM_H_ +#include +#include + #include "core/fpdfapi/page/cpdf_pageobjectholder.h" class CPDF_Document; @@ -24,16 +27,19 @@ class CPDF_Form : public CPDF_PageObjectHolder { CPDF_Dictionary* pParentResources = nullptr); ~CPDF_Form() override; - void ParseContent(CPDF_AllStates* pGraphicStates, - const CFX_Matrix* pParentMatrix, - CPDF_Type3Char* pType3Char, - int level = 0); + void ParseContent(); + void ParseContentWithParams(CPDF_AllStates* pGraphicStates, + const CFX_Matrix* pParentMatrix, + CPDF_Type3Char* pType3Char, + std::set* parsedSet); private: void StartParse(CPDF_AllStates* pGraphicStates, const CFX_Matrix* pParentMatrix, CPDF_Type3Char* pType3Char, - int level = 0); + std::set* parsedSet); + + std::unique_ptr> m_ParsedSet; }; #endif // CORE_FPDFAPI_PAGE_CPDF_FORM_H_ diff --git a/core/fpdfapi/page/cpdf_formobject.cpp b/core/fpdfapi/page/cpdf_formobject.cpp index 5642a5dd01c5e572ed1bd534fd3a1fafab939cdf..eca92ca0ffe02e7794d743003781d2776e5685f3 100644 --- a/core/fpdfapi/page/cpdf_formobject.cpp +++ b/core/fpdfapi/page/cpdf_formobject.cpp @@ -6,9 +6,13 @@ #include "core/fpdfapi/page/cpdf_formobject.h" +#include + #include "core/fpdfapi/page/cpdf_form.h" -CPDF_FormObject::CPDF_FormObject() {} +CPDF_FormObject::CPDF_FormObject(std::unique_ptr pForm, + const CFX_Matrix& matrix) + : m_pForm(std::move(pForm)), m_FormMatrix(matrix) {} CPDF_FormObject::~CPDF_FormObject() {} @@ -34,8 +38,8 @@ CPDF_PageObject::Type CPDF_FormObject::GetType() const { } void CPDF_FormObject::CalcBoundingBox() { - CFX_FloatRect form_rect = m_pForm->CalcBoundingBox(); - m_FormMatrix.TransformRect(form_rect); + CFX_FloatRect form_rect = + m_FormMatrix.TransformRect(m_pForm->CalcBoundingBox()); m_Left = form_rect.left; m_Bottom = form_rect.bottom; m_Right = form_rect.right; diff --git a/core/fpdfapi/page/cpdf_formobject.h b/core/fpdfapi/page/cpdf_formobject.h index b13cb5fbe4c56f7bba766389d203cc38a78187c0..c723cc0eafe413fc37120b2bb357240601ee6e84 100644 --- a/core/fpdfapi/page/cpdf_formobject.h +++ b/core/fpdfapi/page/cpdf_formobject.h @@ -16,7 +16,7 @@ class CPDF_Form; class CPDF_FormObject : public CPDF_PageObject { public: - CPDF_FormObject(); + CPDF_FormObject(std::unique_ptr pForm, const CFX_Matrix& matrix); ~CPDF_FormObject() override; // CPDF_PageObject: @@ -28,8 +28,10 @@ class CPDF_FormObject : public CPDF_PageObject { void CalcBoundingBox(); const CPDF_Form* form() const { return m_pForm.get(); } + const CFX_Matrix& form_matrix() const { return m_FormMatrix; } - std::unique_ptr m_pForm; + private: + const std::unique_ptr m_pForm; CFX_Matrix m_FormMatrix; }; diff --git a/core/fpdfapi/page/cpdf_function.cpp b/core/fpdfapi/page/cpdf_function.cpp new file mode 100644 index 0000000000000000000000000000000000000000..635c53a95fd9fdcd0c5d2d843a159d899de74ce0 --- /dev/null +++ b/core/fpdfapi/page/cpdf_function.cpp @@ -0,0 +1,153 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_function.h" + +#include "core/fpdfapi/page/cpdf_expintfunc.h" +#include "core/fpdfapi/page/cpdf_psfunc.h" +#include "core/fpdfapi/page/cpdf_sampledfunc.h" +#include "core/fpdfapi/page/cpdf_stitchfunc.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "third_party/base/ptr_util.h" + +// static +std::unique_ptr CPDF_Function::Load(CPDF_Object* pFuncObj) { + std::unique_ptr pFunc; + if (!pFuncObj) + return pFunc; + + int iType = -1; + if (CPDF_Stream* pStream = pFuncObj->AsStream()) + iType = pStream->GetDict()->GetIntegerFor("FunctionType"); + else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary()) + iType = pDict->GetIntegerFor("FunctionType"); + + Type type = IntegerToFunctionType(iType); + if (type == Type::kType0Sampled) + pFunc = pdfium::MakeUnique(); + else if (type == Type::kType2ExpotentialInterpolation) + pFunc = pdfium::MakeUnique(); + else if (type == Type::kType3Stitching) + pFunc = pdfium::MakeUnique(); + else if (type == Type::kType4PostScript) + pFunc = pdfium::MakeUnique(); + + if (!pFunc || !pFunc->Init(pFuncObj)) + return nullptr; + + return pFunc; +} + +// static +CPDF_Function::Type CPDF_Function::IntegerToFunctionType(int iType) { + switch (iType) { + case 0: + case 2: + case 3: + case 4: + return static_cast(iType); + default: + return Type::kTypeInvalid; + } +} + +CPDF_Function::CPDF_Function(Type type) + : m_pDomains(nullptr), m_pRanges(nullptr), m_Type(type) {} + +CPDF_Function::~CPDF_Function() { + FX_Free(m_pDomains); + FX_Free(m_pRanges); +} + +bool CPDF_Function::Init(CPDF_Object* pObj) { + CPDF_Stream* pStream = pObj->AsStream(); + CPDF_Dictionary* pDict = pStream ? pStream->GetDict() : pObj->AsDictionary(); + + CPDF_Array* pDomains = pDict->GetArrayFor("Domain"); + if (!pDomains) + return false; + + m_nInputs = pDomains->GetCount() / 2; + if (m_nInputs == 0) + return false; + + m_pDomains = FX_Alloc2D(float, m_nInputs, 2); + for (uint32_t i = 0; i < m_nInputs * 2; i++) { + m_pDomains[i] = pDomains->GetFloatAt(i); + } + CPDF_Array* pRanges = pDict->GetArrayFor("Range"); + m_nOutputs = 0; + if (pRanges) { + m_nOutputs = pRanges->GetCount() / 2; + m_pRanges = FX_Alloc2D(float, m_nOutputs, 2); + for (uint32_t i = 0; i < m_nOutputs * 2; i++) + m_pRanges[i] = pRanges->GetFloatAt(i); + } + uint32_t old_outputs = m_nOutputs; + if (!v_Init(pObj)) + return false; + if (m_pRanges && m_nOutputs > old_outputs) { + m_pRanges = FX_Realloc(float, m_pRanges, m_nOutputs * 2); + if (m_pRanges) { + memset(m_pRanges + (old_outputs * 2), 0, + sizeof(float) * (m_nOutputs - old_outputs) * 2); + } + } + return true; +} + +bool CPDF_Function::Call(float* inputs, + uint32_t ninputs, + float* results, + int* nresults) const { + if (m_nInputs != ninputs) + return false; + + *nresults = m_nOutputs; + for (uint32_t i = 0; i < m_nInputs; i++) { + inputs[i] = + pdfium::clamp(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1]); + } + v_Call(inputs, results); + if (!m_pRanges) + return true; + + for (uint32_t i = 0; i < m_nOutputs; i++) { + results[i] = + pdfium::clamp(results[i], m_pRanges[i * 2], m_pRanges[i * 2 + 1]); + } + return true; +} + +// See PDF Reference 1.7, page 170. +float CPDF_Function::Interpolate(float x, + float xmin, + float xmax, + float ymin, + float ymax) const { + float divisor = xmax - xmin; + return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0); +} + +const CPDF_SampledFunc* CPDF_Function::ToSampledFunc() const { + return m_Type == Type::kType0Sampled + ? static_cast(this) + : nullptr; +} + +const CPDF_ExpIntFunc* CPDF_Function::ToExpIntFunc() const { + return m_Type == Type::kType2ExpotentialInterpolation + ? static_cast(this) + : nullptr; +} + +const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const { + return m_Type == Type::kType3Stitching + ? static_cast(this) + : nullptr; +} diff --git a/core/fpdfapi/page/cpdf_function.h b/core/fpdfapi/page/cpdf_function.h new file mode 100644 index 0000000000000000000000000000000000000000..ff7cf847d2be07411bb7fdf60879140e6cad37bd --- /dev/null +++ b/core/fpdfapi/page/cpdf_function.h @@ -0,0 +1,64 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_FUNCTION_H_ +#define CORE_FPDFAPI_PAGE_CPDF_FUNCTION_H_ + +#include + +class CPDF_ExpIntFunc; +class CPDF_Object; +class CPDF_SampledFunc; +class CPDF_StitchFunc; + +class CPDF_Function { + public: + enum class Type { + kTypeInvalid = -1, + kType0Sampled = 0, + kType2ExpotentialInterpolation = 2, + kType3Stitching = 3, + kType4PostScript = 4, + }; + + static std::unique_ptr Load(CPDF_Object* pFuncObj); + static Type IntegerToFunctionType(int iType); + + virtual ~CPDF_Function(); + + bool Call(float* inputs, + uint32_t ninputs, + float* results, + int* nresults) const; + uint32_t CountInputs() const { return m_nInputs; } + uint32_t CountOutputs() const { return m_nOutputs; } + float GetDomain(int i) const { return m_pDomains[i]; } + float GetRange(int i) const { return m_pRanges[i]; } + float Interpolate(float x, + float xmin, + float xmax, + float ymin, + float ymax) const; + + const CPDF_SampledFunc* ToSampledFunc() const; + const CPDF_ExpIntFunc* ToExpIntFunc() const; + const CPDF_StitchFunc* ToStitchFunc() const; + + protected: + explicit CPDF_Function(Type type); + + bool Init(CPDF_Object* pObj); + virtual bool v_Init(CPDF_Object* pObj) = 0; + virtual bool v_Call(float* inputs, float* results) const = 0; + + uint32_t m_nInputs; + uint32_t m_nOutputs; + float* m_pDomains; + float* m_pRanges; + const Type m_Type; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_FUNCTION_H_ diff --git a/core/fpdfapi/page/cpdf_generalstate.cpp b/core/fpdfapi/page/cpdf_generalstate.cpp index 4edd9b2a3c6fd8222bde2d634883e6368932a9f4..845cedd4963eddaa41d3a2682c0acfa672974f95 100644 --- a/core/fpdfapi/page/cpdf_generalstate.cpp +++ b/core/fpdfapi/page/cpdf_generalstate.cpp @@ -13,7 +13,7 @@ namespace { -int RI_StringToId(const CFX_ByteString& ri) { +int RI_StringToId(const ByteString& ri) { uint32_t id = ri.GetID(); if (id == FXBSTR_ID('A', 'b', 's', 'o')) return 1; @@ -27,7 +27,7 @@ int RI_StringToId(const CFX_ByteString& ri) { return 0; } -int GetBlendTypeInternal(const CFX_ByteString& mode) { +int GetBlendTypeInternal(const ByteString& mode) { switch (mode.GetID()) { case FXBSTR_ID('N', 'o', 'r', 'm'): case FXBSTR_ID('C', 'o', 'm', 'p'): @@ -75,9 +75,46 @@ CPDF_GeneralState::CPDF_GeneralState(const CPDF_GeneralState& that) CPDF_GeneralState::~CPDF_GeneralState() {} -void CPDF_GeneralState::SetRenderIntent(const CFX_ByteString& ri) { +void CPDF_GeneralState::SetRenderIntent(const ByteString& ri) { m_Ref.GetPrivateCopy()->m_RenderIntent = RI_StringToId(ri); } +ByteString CPDF_GeneralState::GetBlendMode() const { + switch (GetBlendType()) { + case FXDIB_BLEND_NORMAL: + return ByteString("Normal"); + case FXDIB_BLEND_MULTIPLY: + return ByteString("Multiply"); + case FXDIB_BLEND_SCREEN: + return ByteString("Screen"); + case FXDIB_BLEND_OVERLAY: + return ByteString("Overlay"); + case FXDIB_BLEND_DARKEN: + return ByteString("Darken"); + case FXDIB_BLEND_LIGHTEN: + return ByteString("Lighten"); + case FXDIB_BLEND_COLORDODGE: + return ByteString("ColorDodge"); + case FXDIB_BLEND_COLORBURN: + return ByteString("ColorBurn"); + case FXDIB_BLEND_HARDLIGHT: + return ByteString("HardLight"); + case FXDIB_BLEND_SOFTLIGHT: + return ByteString("SoftLight"); + case FXDIB_BLEND_DIFFERENCE: + return ByteString("Difference"); + case FXDIB_BLEND_EXCLUSION: + return ByteString("Exclusion"); + case FXDIB_BLEND_HUE: + return ByteString("Hue"); + case FXDIB_BLEND_SATURATION: + return ByteString("Saturation"); + case FXDIB_BLEND_COLOR: + return ByteString("Color"); + case FXDIB_BLEND_LUMINOSITY: + return ByteString("Luminosity"); + } + return ByteString("Normal"); +} int CPDF_GeneralState::GetBlendType() const { const StateData* pData = m_Ref.GetObject(); @@ -88,27 +125,27 @@ void CPDF_GeneralState::SetBlendType(int type) { m_Ref.GetPrivateCopy()->m_BlendType = type; } -FX_FLOAT CPDF_GeneralState::GetFillAlpha() const { +float CPDF_GeneralState::GetFillAlpha() const { const StateData* pData = m_Ref.GetObject(); return pData ? pData->m_FillAlpha : 1.0f; } -void CPDF_GeneralState::SetFillAlpha(FX_FLOAT alpha) { +void CPDF_GeneralState::SetFillAlpha(float alpha) { m_Ref.GetPrivateCopy()->m_FillAlpha = alpha; } -FX_FLOAT CPDF_GeneralState::GetStrokeAlpha() const { +float CPDF_GeneralState::GetStrokeAlpha() const { const StateData* pData = m_Ref.GetObject(); return pData ? pData->m_StrokeAlpha : 1.0f; } -void CPDF_GeneralState::SetStrokeAlpha(FX_FLOAT alpha) { +void CPDF_GeneralState::SetStrokeAlpha(float alpha) { m_Ref.GetPrivateCopy()->m_StrokeAlpha = alpha; } CPDF_Object* CPDF_GeneralState::GetSoftMask() const { const StateData* pData = m_Ref.GetObject(); - return pData ? pData->m_pSoftMask : nullptr; + return pData ? pData->m_pSoftMask.Get() : nullptr; } void CPDF_GeneralState::SetSoftMask(CPDF_Object* pObject) { @@ -117,23 +154,24 @@ void CPDF_GeneralState::SetSoftMask(CPDF_Object* pObject) { CPDF_Object* CPDF_GeneralState::GetTR() const { const StateData* pData = m_Ref.GetObject(); - return pData ? pData->m_pTR : nullptr; + return pData ? pData->m_pTR.Get() : nullptr; } void CPDF_GeneralState::SetTR(CPDF_Object* pObject) { m_Ref.GetPrivateCopy()->m_pTR = pObject; } -CPDF_TransferFunc* CPDF_GeneralState::GetTransferFunc() const { +RetainPtr CPDF_GeneralState::GetTransferFunc() const { const StateData* pData = m_Ref.GetObject(); return pData ? pData->m_pTransferFunc : nullptr; } -void CPDF_GeneralState::SetTransferFunc(CPDF_TransferFunc* pFunc) { +void CPDF_GeneralState::SetTransferFunc( + const RetainPtr& pFunc) { m_Ref.GetPrivateCopy()->m_pTransferFunc = pFunc; } -void CPDF_GeneralState::SetBlendMode(const CFX_ByteString& mode) { +void CPDF_GeneralState::SetBlendMode(const ByteString& mode) { StateData* pData = m_Ref.GetPrivateCopy(); pData->m_BlendMode = mode; pData->m_BlendType = GetBlendTypeInternal(mode); @@ -186,11 +224,11 @@ void CPDF_GeneralState::SetHT(CPDF_Object* pObject) { m_Ref.GetPrivateCopy()->m_pHT = pObject; } -void CPDF_GeneralState::SetFlatness(FX_FLOAT flatness) { +void CPDF_GeneralState::SetFlatness(float flatness) { m_Ref.GetPrivateCopy()->m_Flatness = flatness; } -void CPDF_GeneralState::SetSmoothness(FX_FLOAT smoothness) { +void CPDF_GeneralState::SetSmoothness(float smoothness) { m_Ref.GetPrivateCopy()->m_Smoothness = smoothness; } @@ -266,18 +304,21 @@ CPDF_GeneralState::StateData::StateData(const StateData& that) m_Matrix = that.m_Matrix; m_SMaskMatrix = that.m_SMaskMatrix; - if (that.m_pTransferFunc && that.m_pTransferFunc->m_pPDFDoc) { + if (that.m_pTransferFunc && that.m_pTransferFunc->GetDocument()) { CPDF_DocRenderData* pDocCache = - that.m_pTransferFunc->m_pPDFDoc->GetRenderData(); + that.m_pTransferFunc->GetDocument()->GetRenderData(); if (pDocCache) - m_pTransferFunc = pDocCache->GetTransferFunc(m_pTR); + m_pTransferFunc = pDocCache->GetTransferFunc(m_pTR.Get()); } } CPDF_GeneralState::StateData::~StateData() { - if (m_pTransferFunc && m_pTransferFunc->m_pPDFDoc) { - CPDF_DocRenderData* pDocCache = m_pTransferFunc->m_pPDFDoc->GetRenderData(); - if (pDocCache) - pDocCache->ReleaseTransferFunc(m_pTR); + if (m_pTransferFunc && m_pTransferFunc->GetDocument()) { + CPDF_DocRenderData* pDocCache = + m_pTransferFunc->GetDocument()->GetRenderData(); + if (pDocCache) { + m_pTransferFunc.Reset(); // Give up our reference first. + pDocCache->MaybePurgeTransferFunc(m_pTR.Get()); + } } } diff --git a/core/fpdfapi/page/cpdf_generalstate.h b/core/fpdfapi/page/cpdf_generalstate.h index 5211c52e5bd29759f41fe4aa8dc58570b963b8f7..5d6d5dc5528cdc36165129303009b314a62e1eed 100644 --- a/core/fpdfapi/page/cpdf_generalstate.h +++ b/core/fpdfapi/page/cpdf_generalstate.h @@ -7,8 +7,10 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_GENERALSTATE_H_ #define CORE_FPDFAPI_PAGE_CPDF_GENERALSTATE_H_ -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/shared_copy_on_write.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" class CPDF_Object; @@ -21,18 +23,19 @@ class CPDF_GeneralState { ~CPDF_GeneralState(); void Emplace() { m_Ref.Emplace(); } - explicit operator bool() const { return !!m_Ref; } + bool HasRef() const { return !!m_Ref; } - void SetRenderIntent(const CFX_ByteString& ri); + void SetRenderIntent(const ByteString& ri); + ByteString GetBlendMode() const; int GetBlendType() const; void SetBlendType(int type); - FX_FLOAT GetFillAlpha() const; - void SetFillAlpha(FX_FLOAT alpha); + float GetFillAlpha() const; + void SetFillAlpha(float alpha); - FX_FLOAT GetStrokeAlpha() const; - void SetStrokeAlpha(FX_FLOAT alpha); + float GetStrokeAlpha() const; + void SetStrokeAlpha(float alpha); CPDF_Object* GetSoftMask() const; void SetSoftMask(CPDF_Object* pObject); @@ -40,10 +43,10 @@ class CPDF_GeneralState { CPDF_Object* GetTR() const; void SetTR(CPDF_Object* pObject); - CPDF_TransferFunc* GetTransferFunc() const; - void SetTransferFunc(CPDF_TransferFunc* pFunc); + RetainPtr GetTransferFunc() const; + void SetTransferFunc(const RetainPtr& pFunc); - void SetBlendMode(const CFX_ByteString& mode); + void SetBlendMode(const ByteString& mode); const CFX_Matrix* GetSMaskMatrix() const; void SetSMaskMatrix(const CFX_Matrix& matrix); @@ -61,8 +64,8 @@ class CPDF_GeneralState { void SetUCR(CPDF_Object* pObject); void SetHT(CPDF_Object* pObject); - void SetFlatness(FX_FLOAT flatness); - void SetSmoothness(FX_FLOAT smoothness); + void SetFlatness(float flatness); + void SetSmoothness(float smoothness); bool GetStrokeAdjust() const; void SetStrokeAdjust(bool adjust); @@ -74,20 +77,20 @@ class CPDF_GeneralState { CFX_Matrix* GetMutableMatrix(); private: - class StateData { + class StateData : public Retainable { public: StateData(); StateData(const StateData& that); - ~StateData(); + ~StateData() override; - CFX_ByteString m_BlendMode; + ByteString m_BlendMode; int m_BlendType; - CPDF_Object* m_pSoftMask; + UnownedPtr m_pSoftMask; CFX_Matrix m_SMaskMatrix; - FX_FLOAT m_StrokeAlpha; - FX_FLOAT m_FillAlpha; - CPDF_Object* m_pTR; - CPDF_TransferFunc* m_pTransferFunc; + float m_StrokeAlpha; + float m_FillAlpha; + UnownedPtr m_pTR; + RetainPtr m_pTransferFunc; CFX_Matrix m_Matrix; int m_RenderIntent; bool m_StrokeAdjust; @@ -96,14 +99,14 @@ class CPDF_GeneralState { bool m_StrokeOP; bool m_FillOP; int m_OPMode; - CPDF_Object* m_pBG; - CPDF_Object* m_pUCR; - CPDF_Object* m_pHT; - FX_FLOAT m_Flatness; - FX_FLOAT m_Smoothness; + UnownedPtr m_pBG; + UnownedPtr m_pUCR; + UnownedPtr m_pHT; + float m_Flatness; + float m_Smoothness; }; - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; #endif // CORE_FPDFAPI_PAGE_CPDF_GENERALSTATE_H_ diff --git a/core/fpdfapi/page/cpdf_iccprofile.cpp b/core/fpdfapi/page/cpdf_iccprofile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..144f530a2c218e7d8c32adbb47dddb08908d606f --- /dev/null +++ b/core/fpdfapi/page/cpdf_iccprofile.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_iccprofile.h" + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fxcodec/codec/ccodec_iccmodule.h" + +namespace { + +bool DetectSRGB(const uint8_t* pData, uint32_t dwSize) { + return dwSize == 3144 && memcmp(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0; +} + +} // namespace + +CPDF_IccProfile::CPDF_IccProfile(CPDF_Stream* pStream, + const uint8_t* pData, + uint32_t dwSize) + : m_bsRGB(DetectSRGB(pData, dwSize)), m_pStream(pStream) { + if (m_bsRGB) { + m_nSrcComponents = 3; + return; + } + + uint32_t nSrcComps = 0; + auto* pIccModule = CPDF_ModuleMgr::Get()->GetIccModule(); + m_Transform = pIccModule->CreateTransform_sRGB(pData, dwSize, &nSrcComps); + if (m_Transform) + m_nSrcComponents = nSrcComps; +} + +CPDF_IccProfile::~CPDF_IccProfile() {} diff --git a/core/fpdfapi/page/cpdf_iccprofile.h b/core/fpdfapi/page/cpdf_iccprofile.h new file mode 100644 index 0000000000000000000000000000000000000000..1bc498aa1f9ea1be5b6ed03ba1f3b6ab391a665e --- /dev/null +++ b/core/fpdfapi/page/cpdf_iccprofile.h @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_ICCPROFILE_H_ +#define CORE_FPDFAPI_PAGE_CPDF_ICCPROFILE_H_ + +#include + +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" + +class CLcmsCmm; +class CPDF_Stream; + +class CPDF_IccProfile : public Retainable { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + CPDF_Stream* GetStream() const { return m_pStream.Get(); } + bool IsValid() const { return IsSRGB() || IsSupported(); } + bool IsSRGB() const { return m_bsRGB; } + bool IsSupported() const { return !!m_Transform; } + CLcmsCmm* transform() { return m_Transform.get(); } + uint32_t GetComponents() const { return m_nSrcComponents; } + + private: + CPDF_IccProfile(CPDF_Stream* pStream, const uint8_t* pData, uint32_t dwSize); + ~CPDF_IccProfile() override; + + const bool m_bsRGB; + UnownedPtr const m_pStream; + std::unique_ptr m_Transform; + uint32_t m_nSrcComponents = 0; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_ICCPROFILE_H_ diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp index 6b0bfd7d6d12386b0766e43600069d9b1ee061e4..65ca78e08ef39cf50424d89f4ba0bed599d1a549 100644 --- a/core/fpdfapi/page/cpdf_image.cpp +++ b/core/fpdfapi/page/cpdf_image.cpp @@ -24,7 +24,9 @@ #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/render/cpdf_dibsource.h" #include "core/fpdfapi/render/cpdf_pagerendercache.h" -#include "core/fxcodec/fx_codec.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" #include "third_party/base/numerics/safe_conversions.h" #include "third_party/base/ptr_util.h" @@ -70,6 +72,10 @@ void CPDF_Image::ConvertStreamToIndirectObject() { m_pDocument->AddIndirectObject(m_pStream.Release()); } +CPDF_Dictionary* CPDF_Image::GetDict() const { + return m_pStream ? m_pStream->GetDict() : nullptr; +} + std::unique_ptr CPDF_Image::InitJPEG(uint8_t* pData, uint32_t size) { int32_t width; @@ -88,7 +94,7 @@ std::unique_ptr CPDF_Image::InitJPEG(uint8_t* pData, pDict->SetNewFor("Subtype", "Image"); pDict->SetNewFor("Width", width); pDict->SetNewFor("Height", height); - const FX_CHAR* csname = nullptr; + const char* csname = nullptr; if (num_comps == 1) { csname = "DeviceGray"; } else if (num_comps == 3) { @@ -116,8 +122,7 @@ std::unique_ptr CPDF_Image::InitJPEG(uint8_t* pData, return pDict; } -void CPDF_Image::SetJpegImage( - const CFX_RetainPtr& pFile) { +void CPDF_Image::SetJpegImage(const RetainPtr& pFile) { uint32_t size = pdfium::base::checked_cast(pFile->GetSize()); if (!size) return; @@ -141,7 +146,7 @@ void CPDF_Image::SetJpegImage( } void CPDF_Image::SetJpegImageInline( - const CFX_RetainPtr& pFile) { + const RetainPtr& pFile) { uint32_t size = pdfium::base::checked_cast(pFile->GetSize()); if (!size) return; @@ -157,7 +162,7 @@ void CPDF_Image::SetJpegImageInline( m_pStream->InitStream(&(data[0]), size, std::move(pDict)); } -void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { +void CPDF_Image::SetImage(const RetainPtr& pBitmap) { int32_t BitmapWidth = pBitmap->GetWidth(); int32_t BitmapHeight = pBitmap->GetHeight(); if (BitmapWidth < 1 || BitmapHeight < 1) @@ -171,7 +176,7 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { pDict->SetNewFor("Height", BitmapHeight); const int32_t bpp = pBitmap->GetBPP(); - FX_STRSIZE dest_pitch = 0; + size_t dest_pitch = 0; bool bCopyWithoutAlpha = true; if (bpp == 1) { int32_t reset_a = 0; @@ -183,9 +188,10 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { int32_t set_g = 0; int32_t set_b = 0; if (!pBitmap->IsAlphaMask()) { - ArgbDecode(pBitmap->GetPaletteArgb(0), reset_a, reset_r, reset_g, - reset_b); - ArgbDecode(pBitmap->GetPaletteArgb(1), set_a, set_r, set_g, set_b); + std::tie(reset_a, reset_r, reset_g, reset_b) = + ArgbDecode(pBitmap->GetPaletteArgb(0)); + std::tie(set_a, set_r, set_g, set_b) = + ArgbDecode(pBitmap->GetPaletteArgb(1)); } if (set_a == 0 || reset_a == 0) { pDict->SetNewFor("ImageMask", true); @@ -199,14 +205,14 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { pCS->AddNew("Indexed"); pCS->AddNew("DeviceRGB"); pCS->AddNew(1); - CFX_ByteString ct; - FX_CHAR* pBuf = ct.GetBuffer(6); - pBuf[0] = (FX_CHAR)reset_r; - pBuf[1] = (FX_CHAR)reset_g; - pBuf[2] = (FX_CHAR)reset_b; - pBuf[3] = (FX_CHAR)set_r; - pBuf[4] = (FX_CHAR)set_g; - pBuf[5] = (FX_CHAR)set_b; + ByteString ct; + char* pBuf = ct.GetBuffer(6); + pBuf[0] = (char)reset_r; + pBuf[1] = (char)reset_g; + pBuf[2] = (char)reset_b; + pBuf[3] = (char)set_r; + pBuf[4] = (char)set_g; + pBuf[5] = (char)set_b; ct.ReleaseBuffer(6); pCS->AddNew(ct, true); } @@ -233,8 +239,8 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { pdfium::MakeUnique(m_pDocument->GetByteStringPool()); CPDF_Stream* pCTS = m_pDocument->NewIndirect( std::move(pColorTable), iPalette * 3, std::move(pNewDict)); - pCS->AddNew(m_pDocument, pCTS->GetObjNum()); - pDict->SetNewFor("ColorSpace", m_pDocument, + pCS->AddNew(m_pDocument.Get(), pCTS->GetObjNum()); + pDict->SetNewFor("ColorSpace", m_pDocument.Get(), pCS->GetObjNum()); } else { pDict->SetNewFor("ColorSpace", "DeviceGray"); @@ -248,7 +254,7 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { bCopyWithoutAlpha = false; } - std::unique_ptr pMaskBitmap; + RetainPtr pMaskBitmap; if (pBitmap->HasAlpha()) pMaskBitmap = pBitmap->CloneAlphaMask(); @@ -256,7 +262,7 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { int32_t maskWidth = pMaskBitmap->GetWidth(); int32_t maskHeight = pMaskBitmap->GetHeight(); std::unique_ptr mask_buf; - FX_STRSIZE mask_size = 0; + int32_t mask_size = 0; auto pMaskDict = pdfium::MakeUnique(m_pDocument->GetByteStringPool()); pMaskDict->SetNewFor("Type", "XObject"); @@ -269,14 +275,14 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { mask_buf.reset(FX_Alloc2D(uint8_t, maskHeight, maskWidth)); mask_size = maskHeight * maskWidth; // Safe since checked alloc returned. for (int32_t a = 0; a < maskHeight; a++) { - FXSYS_memcpy(mask_buf.get() + a * maskWidth, - pMaskBitmap->GetScanline(a), maskWidth); + memcpy(mask_buf.get() + a * maskWidth, pMaskBitmap->GetScanline(a), + maskWidth); } } pMaskDict->SetNewFor("Length", mask_size); CPDF_Stream* pNewStream = m_pDocument->NewIndirect( std::move(mask_buf), mask_size, std::move(pMaskDict)); - pDict->SetNewFor("SMask", m_pDocument, + pDict->SetNewFor("SMask", m_pDocument.Get(), pNewStream->GetObjNum()); } @@ -284,11 +290,11 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { int32_t src_pitch = pBitmap->GetPitch(); uint8_t* dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight); // Safe as checked alloc returned. - FX_STRSIZE dest_size = dest_pitch * BitmapHeight; + size_t dest_size = dest_pitch * BitmapHeight; uint8_t* pDest = dest_buf; if (bCopyWithoutAlpha) { for (int32_t i = 0; i < BitmapHeight; i++) { - FXSYS_memcpy(pDest, src_buf, dest_pitch); + memcpy(pDest, src_buf, dest_pitch); pDest += dest_pitch; src_buf += src_pitch; } @@ -298,7 +304,7 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { for (int32_t row = 0; row < BitmapHeight; row++) { src_offset = row * src_pitch; for (int32_t column = 0; column < BitmapWidth; column++) { - FX_FLOAT alpha = 1; + float alpha = 1; pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha); pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alpha); pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha); @@ -320,28 +326,26 @@ void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap) { FX_Free(dest_buf); } -void CPDF_Image::ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pBitmap) { - pPage->GetRenderCache()->ResetBitmap(m_pStream.Get(), pBitmap); +void CPDF_Image::ResetCache(CPDF_Page* pPage, + const RetainPtr& pBitmap) { + RetainPtr pHolder(this); + pPage->GetRenderCache()->ResetBitmap(pHolder, pBitmap); } -std::unique_ptr CPDF_Image::LoadDIBSource() const { - auto source = pdfium::MakeUnique(); - if (!source->Load(m_pDocument, m_pStream.Get())) +RetainPtr CPDF_Image::LoadDIBSource() const { + auto source = pdfium::MakeRetain(); + if (!source->Load(m_pDocument.Get(), m_pStream.Get())) return nullptr; - return std::move(source); + return source; } -CFX_DIBSource* CPDF_Image::DetachBitmap() { - CFX_DIBSource* pBitmap = m_pDIBSource; - m_pDIBSource = nullptr; - return pBitmap; +RetainPtr CPDF_Image::DetachBitmap() { + return std::move(m_pDIBSource); } -CFX_DIBSource* CPDF_Image::DetachMask() { - CFX_DIBSource* pBitmap = m_pMask; - m_pMask = nullptr; - return pBitmap; +RetainPtr CPDF_Image::DetachMask() { + return std::move(m_pMask); } bool CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource, @@ -349,35 +353,33 @@ bool CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource, bool bStdCS, uint32_t GroupFamily, bool bLoadMask) { - auto source = pdfium::MakeUnique(); - int ret = source->StartLoadDIBSource(m_pDocument, m_pStream.Get(), true, + auto source = pdfium::MakeRetain(); + int ret = source->StartLoadDIBSource(m_pDocument.Get(), m_pStream.Get(), true, pFormResource, pPageResource, bStdCS, GroupFamily, bLoadMask); - if (ret == 2) { - m_pDIBSource = source.release(); - return true; - } if (!ret) { - m_pDIBSource = nullptr; + m_pDIBSource.Reset(); return false; } + m_pDIBSource = source; + if (ret == 2) + return true; + m_pMask = source->DetachMask(); m_MatteColor = source->GetMatteColor(); - m_pDIBSource = source.release(); return false; } -bool CPDF_Image::Continue(IFX_Pause* pPause) { - CPDF_DIBSource* pSource = static_cast(m_pDIBSource); +bool CPDF_Image::Continue(IFX_PauseIndicator* pPause) { + RetainPtr pSource = m_pDIBSource.As(); int ret = pSource->ContinueLoadDIBSource(pPause); - if (ret == 2) { - return true; - } if (!ret) { - delete m_pDIBSource; - m_pDIBSource = nullptr; + m_pDIBSource.Reset(); return false; } + if (ret == 2) + return true; + m_pMask = pSource->DetachMask(); m_MatteColor = pSource->GetMatteColor(); return false; diff --git a/core/fpdfapi/page/cpdf_image.h b/core/fpdfapi/page/cpdf_image.h index 1909498102696412baf9568e736fc3a13a2a5a1a..23864bbf6cbfa91c7317d95dcecb788d5212c6f2 100644 --- a/core/fpdfapi/page/cpdf_image.h +++ b/core/fpdfapi/page/cpdf_image.h @@ -10,32 +10,30 @@ #include #include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fxcrt/cfx_maybe_owned.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CFX_DIBSource; class CFX_DIBitmap; class CPDF_Document; class CPDF_Page; -class IFX_Pause; +class IFX_PauseIndicator; class IFX_SeekableReadStream; -class CPDF_Image { +class CPDF_Image : public Retainable { public: - explicit CPDF_Image(CPDF_Document* pDoc); - CPDF_Image(CPDF_Document* pDoc, std::unique_ptr pStream); - CPDF_Image(CPDF_Document* pDoc, uint32_t dwStreamObjNum); - ~CPDF_Image(); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); void ConvertStreamToIndirectObject(); CPDF_Dictionary* GetInlineDict() const { return m_pDict.Get(); } CPDF_Stream* GetStream() const { return m_pStream.Get(); } - CPDF_Dictionary* GetDict() const { - return m_pStream ? m_pStream->GetDict() : nullptr; - } - CPDF_Dictionary* GetOC() const { return m_pOC; } - CPDF_Document* GetDocument() const { return m_pDocument; } + CPDF_Dictionary* GetDict() const; + CPDF_Dictionary* GetOC() const { return m_pOC.Get(); } + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } int32_t GetPixelHeight() const { return m_Height; } int32_t GetPixelWidth() const { return m_Width; } @@ -44,28 +42,32 @@ class CPDF_Image { bool IsMask() const { return m_bIsMask; } bool IsInterpol() const { return m_bInterpolate; } - std::unique_ptr LoadDIBSource() const; - - void SetImage(const CFX_DIBitmap* pDIBitmap); - void SetJpegImage(const CFX_RetainPtr& pFile); - void SetJpegImageInline(const CFX_RetainPtr& pFile); + RetainPtr LoadDIBSource() const; - void ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pDIBitmap); + void SetImage(const RetainPtr& pDIBitmap); + void SetJpegImage(const RetainPtr& pFile); + void SetJpegImageInline(const RetainPtr& pFile); + void ResetCache(CPDF_Page* pPage, const RetainPtr& pDIBitmap); bool StartLoadDIBSource(CPDF_Dictionary* pFormResource, CPDF_Dictionary* pPageResource, bool bStdCS = false, uint32_t GroupFamily = 0, bool bLoadMask = false); - bool Continue(IFX_Pause* pPause); - CFX_DIBSource* DetachBitmap(); - CFX_DIBSource* DetachMask(); + bool Continue(IFX_PauseIndicator* pPause); + RetainPtr DetachBitmap(); + RetainPtr DetachMask(); - CFX_DIBSource* m_pDIBSource = nullptr; - CFX_DIBSource* m_pMask = nullptr; + RetainPtr m_pDIBSource; + RetainPtr m_pMask; uint32_t m_MatteColor = 0; private: + explicit CPDF_Image(CPDF_Document* pDoc); + CPDF_Image(CPDF_Document* pDoc, std::unique_ptr pStream); + CPDF_Image(CPDF_Document* pDoc, uint32_t dwStreamObjNum); + ~CPDF_Image() override; + void FinishInitialization(); std::unique_ptr InitJPEG(uint8_t* pData, uint32_t size); @@ -74,10 +76,10 @@ class CPDF_Image { bool m_bIsInline = false; bool m_bIsMask = false; bool m_bInterpolate = false; - CPDF_Document* const m_pDocument; - CFX_MaybeOwned m_pStream; - CFX_MaybeOwned m_pDict; - CPDF_Dictionary* m_pOC = nullptr; + UnownedPtr const m_pDocument; + MaybeOwned m_pStream; + MaybeOwned m_pDict; + UnownedPtr m_pOC; }; #endif // CORE_FPDFAPI_PAGE_CPDF_IMAGE_H_ diff --git a/core/fpdfapi/page/cpdf_imageobject.cpp b/core/fpdfapi/page/cpdf_imageobject.cpp index 01d2df742173aeffcdfeb77e551e912bfd4ca5e0..3b5a740155658757ddde09ba8fd080b32c3e6796 100644 --- a/core/fpdfapi/page/cpdf_imageobject.cpp +++ b/core/fpdfapi/page/cpdf_imageobject.cpp @@ -12,11 +12,10 @@ #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/parser/cpdf_document.h" -CPDF_ImageObject::CPDF_ImageObject() - : m_pImage(nullptr), m_pImageOwned(false) {} +CPDF_ImageObject::CPDF_ImageObject() {} CPDF_ImageObject::~CPDF_ImageObject() { - Release(); + MaybePurgeCache(); } CPDF_PageObject::Type CPDF_ImageObject::GetType() const { @@ -26,6 +25,7 @@ CPDF_PageObject::Type CPDF_ImageObject::GetType() const { void CPDF_ImageObject::Transform(const CFX_Matrix& matrix) { m_Matrix.Concat(matrix); CalcBoundingBox(); + SetDirty(true); } bool CPDF_ImageObject::IsImage() const { @@ -41,37 +41,35 @@ const CPDF_ImageObject* CPDF_ImageObject::AsImage() const { } void CPDF_ImageObject::CalcBoundingBox() { - m_Left = 0; - m_Bottom = 0; - m_Right = 1.0f; - m_Top = 1.0f; - m_Matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); + std::tie(m_Left, m_Right, m_Top, m_Bottom) = + m_Matrix.TransformRect(0.f, 1.f, 1.f, 0.f); } -void CPDF_ImageObject::SetOwnedImage(std::unique_ptr pImage) { - Release(); - m_pImage = pImage.release(); - m_pImageOwned = true; -} - -void CPDF_ImageObject::SetUnownedImage(CPDF_Image* pImage) { - Release(); +void CPDF_ImageObject::SetImage(const RetainPtr& pImage) { + MaybePurgeCache(); m_pImage = pImage; - m_pImageOwned = false; } -void CPDF_ImageObject::Release() { - if (m_pImageOwned) { - delete m_pImage; - m_pImage = nullptr; - m_pImageOwned = false; +void CPDF_ImageObject::MaybePurgeCache() { + if (!m_pImage) return; - } - if (!m_pImage) + CPDF_Document* pDocument = m_pImage->GetDocument(); + if (!pDocument) + return; + + CPDF_DocPageData* pPageData = pDocument->GetPageData(); + if (!pPageData) + return; + + CPDF_Stream* pStream = m_pImage->GetStream(); + if (!pStream) + return; + + uint32_t objnum = pStream->GetObjNum(); + if (!objnum) return; - CPDF_DocPageData* pPageData = m_pImage->GetDocument()->GetPageData(); - pPageData->ReleaseImage(m_pImage->GetStream()->GetObjNum()); - m_pImage = nullptr; + m_pImage.Reset(); // Clear my reference before asking the cache. + pPageData->MaybePurgeImage(objnum); } diff --git a/core/fpdfapi/page/cpdf_imageobject.h b/core/fpdfapi/page/cpdf_imageobject.h index 1bbfc0509cd2384edeb0b1b5bd4a27f459912f40..16a506e537aa8c783f2d92ac03856e386ba2bc0e 100644 --- a/core/fpdfapi/page/cpdf_imageobject.h +++ b/core/fpdfapi/page/cpdf_imageobject.h @@ -27,19 +27,16 @@ class CPDF_ImageObject : public CPDF_PageObject { const CPDF_ImageObject* AsImage() const override; void CalcBoundingBox(); - CPDF_Image* GetImage() const { return m_pImage; } - void SetOwnedImage(std::unique_ptr pImage); - void SetUnownedImage(CPDF_Image* pImage); - + RetainPtr GetImage() const { return m_pImage; } + void SetImage(const RetainPtr& pImage); void set_matrix(const CFX_Matrix& matrix) { m_Matrix = matrix; } const CFX_Matrix& matrix() const { return m_Matrix; } private: - void Release(); + void MaybePurgeCache(); CFX_Matrix m_Matrix; - CPDF_Image* m_pImage; - bool m_pImageOwned; + RetainPtr m_pImage; }; #endif // CORE_FPDFAPI_PAGE_CPDF_IMAGEOBJECT_H_ diff --git a/core/fpdfapi/page/cpdf_meshstream.cpp b/core/fpdfapi/page/cpdf_meshstream.cpp index 24ef9b271e22a6afe41e192bd3b2cfd4e13552c4..083acce68ac590b8488cb71509d37106a54d1a4c 100644 --- a/core/fpdfapi/page/cpdf_meshstream.cpp +++ b/core/fpdfapi/page/cpdf_meshstream.cpp @@ -7,7 +7,7 @@ #include "core/fpdfapi/page/cpdf_meshstream.h" #include "core/fpdfapi/page/cpdf_colorspace.h" -#include "core/fpdfapi/page/pageint.h" +#include "core/fpdfapi/page/cpdf_function.h" #include "core/fpdfapi/parser/cpdf_array.h" namespace { @@ -107,14 +107,18 @@ CPDF_MeshStream::CPDF_MeshStream( m_xmin(0), m_xmax(0), m_ymin(0), - m_ymax(0) { + m_ymax(0), + m_pStream(pdfium::MakeRetain(pShadingStream)) { memset(&m_ColorMin, 0, sizeof(m_ColorMin)); memset(&m_ColorMax, 0, sizeof(m_ColorMax)); } +CPDF_MeshStream::~CPDF_MeshStream() {} + bool CPDF_MeshStream::Load() { - m_Stream.LoadAllData(m_pShadingStream); - m_BitStream.Init(m_Stream.GetData(), m_Stream.GetSize()); + m_pStream->LoadAllDataFiltered(); + m_BitStream = pdfium::MakeUnique(m_pStream->GetData(), + m_pStream->GetSize()); CPDF_Dictionary* pDict = m_pShadingStream->GetDict(); m_nCoordBits = pDict->GetIntegerFor("BitsPerCoordinate"); m_nComponentBits = pDict->GetIntegerFor("BitsPerComponent"); @@ -155,20 +159,20 @@ bool CPDF_MeshStream::Load() { } bool CPDF_MeshStream::CanReadFlag() const { - return m_BitStream.BitsRemaining() >= m_nFlagBits; + return m_BitStream->BitsRemaining() >= m_nFlagBits; } bool CPDF_MeshStream::CanReadCoords() const { - return m_BitStream.BitsRemaining() / 2 >= m_nCoordBits; + return m_BitStream->BitsRemaining() / 2 >= m_nCoordBits; } bool CPDF_MeshStream::CanReadColor() const { - return m_BitStream.BitsRemaining() / m_nComponentBits >= m_nComponents; + return m_BitStream->BitsRemaining() / m_nComponentBits >= m_nComponents; } uint32_t CPDF_MeshStream::ReadFlag() { ASSERT(ShouldCheckBitsPerFlag(m_type)); - return m_BitStream.GetBits(m_nFlagBits) & 0x03; + return m_BitStream->GetBits(m_nFlagBits) & 0x03; } CFX_PointF CPDF_MeshStream::ReadCoords() { @@ -176,49 +180,47 @@ CFX_PointF CPDF_MeshStream::ReadCoords() { CFX_PointF pos; if (m_nCoordBits == 32) { - pos.x = m_xmin + - m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / - static_cast(m_CoordMax); - pos.y = m_ymin + - m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / - static_cast(m_CoordMax); + pos.x = m_xmin + m_BitStream->GetBits(m_nCoordBits) * (m_xmax - m_xmin) / + static_cast(m_CoordMax); + pos.y = m_ymin + m_BitStream->GetBits(m_nCoordBits) * (m_ymax - m_ymin) / + static_cast(m_CoordMax); } else { pos.x = m_xmin + - m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax; + m_BitStream->GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax; pos.y = m_ymin + - m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax; + m_BitStream->GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax; } return pos; } -std::tuple CPDF_MeshStream::ReadColor() { +std::tuple CPDF_MeshStream::ReadColor() { ASSERT(ShouldCheckBPC(m_type)); - FX_FLOAT color_value[kMaxComponents]; + float color_value[kMaxComponents]; for (uint32_t i = 0; i < m_nComponents; ++i) { - color_value[i] = m_ColorMin[i] + - m_BitStream.GetBits(m_nComponentBits) * - (m_ColorMax[i] - m_ColorMin[i]) / m_ComponentMax; + color_value[i] = m_ColorMin[i] + m_BitStream->GetBits(m_nComponentBits) * + (m_ColorMax[i] - m_ColorMin[i]) / + m_ComponentMax; } - FX_FLOAT r; - FX_FLOAT g; - FX_FLOAT b; + float r = 0.0; + float g = 0.0; + float b = 0.0; if (m_funcs.empty()) { - m_pCS->GetRGB(color_value, r, g, b); - return std::tuple(r, g, b); + m_pCS->GetRGB(color_value, &r, &g, &b); + return std::tuple(r, g, b); } - FX_FLOAT result[kMaxComponents]; - FXSYS_memset(result, 0, sizeof(result)); + float result[kMaxComponents]; + memset(result, 0, sizeof(result)); int nResults; for (const auto& func : m_funcs) { if (func && func->CountOutputs() <= kMaxComponents) - func->Call(color_value, 1, result, nResults); + func->Call(color_value, 1, result, &nResults); } - m_pCS->GetRGB(result, r, g, b); - return std::tuple(r, g, b); + m_pCS->GetRGB(result, &r, &g, &b); + return std::tuple(r, g, b); } bool CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap, @@ -235,23 +237,26 @@ bool CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap, if (!CanReadColor()) return false; std::tie(vertex->r, vertex->g, vertex->b) = ReadColor(); - m_BitStream.ByteAlign(); + m_BitStream->ByteAlign(); return true; } -bool CPDF_MeshStream::ReadVertexRow(const CFX_Matrix& pObject2Bitmap, - int count, - CPDF_MeshVertex* vertex) { - for (int i = 0; i < count; i++) { - if (m_BitStream.IsEOF() || !CanReadCoords()) - return false; - - vertex[i].position = pObject2Bitmap.Transform(ReadCoords()); +std::vector CPDF_MeshStream::ReadVertexRow( + const CFX_Matrix& pObject2Bitmap, + int count) { + std::vector vertices; + for (int i = 0; i < count; ++i) { + if (m_BitStream->IsEOF() || !CanReadCoords()) + return std::vector(); + + vertices.push_back(CPDF_MeshVertex()); + CPDF_MeshVertex& vertex = vertices.back(); + vertex.position = pObject2Bitmap.Transform(ReadCoords()); if (!CanReadColor()) - return false; + return std::vector(); - std::tie(vertex[i].r, vertex[i].g, vertex[i].b) = ReadColor(); - m_BitStream.ByteAlign(); + std::tie(vertex.r, vertex.g, vertex.b) = ReadColor(); + m_BitStream->ByteAlign(); } - return true; + return vertices; } diff --git a/core/fpdfapi/page/cpdf_meshstream.h b/core/fpdfapi/page/cpdf_meshstream.h index d40de4a013d23e80b2e7203ba45ededb4fe7ca96..7c34b251854dfcf07ec4e5b143ab61a912d28ff8 100644 --- a/core/fpdfapi/page/cpdf_meshstream.h +++ b/core/fpdfapi/page/cpdf_meshstream.h @@ -13,7 +13,7 @@ #include "core/fpdfapi/page/cpdf_shadingpattern.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/cfx_bitstream.h" #include "core/fxcrt/fx_system.h" class CPDF_MeshVertex { @@ -23,9 +23,9 @@ class CPDF_MeshVertex { ~CPDF_MeshVertex(); CFX_PointF position; - FX_FLOAT r; - FX_FLOAT g; - FX_FLOAT b; + float r; + float g; + float b; }; class CFX_Matrix; @@ -39,6 +39,7 @@ class CPDF_MeshStream { const std::vector>& funcs, CPDF_Stream* pShadingStream, CPDF_ColorSpace* pCS); + ~CPDF_MeshStream(); bool Load(); @@ -48,16 +49,15 @@ class CPDF_MeshStream { uint32_t ReadFlag(); CFX_PointF ReadCoords(); - std::tuple ReadColor(); + std::tuple ReadColor(); bool ReadVertex(const CFX_Matrix& pObject2Bitmap, CPDF_MeshVertex* vertex, uint32_t* flag); - bool ReadVertexRow(const CFX_Matrix& pObject2Bitmap, - int count, - CPDF_MeshVertex* vertex); + std::vector ReadVertexRow(const CFX_Matrix& pObject2Bitmap, + int count); - CFX_BitStream* BitStream() { return &m_BitStream; } + CFX_BitStream* BitStream() { return m_BitStream.get(); } uint32_t ComponentBits() const { return m_nComponentBits; } uint32_t Components() const { return m_nComponents; } @@ -66,22 +66,22 @@ class CPDF_MeshStream { const ShadingType m_type; const std::vector>& m_funcs; - CPDF_Stream* const m_pShadingStream; - CPDF_ColorSpace* const m_pCS; + UnownedPtr const m_pShadingStream; + UnownedPtr const m_pCS; uint32_t m_nCoordBits; uint32_t m_nComponentBits; uint32_t m_nFlagBits; uint32_t m_nComponents; uint32_t m_CoordMax; uint32_t m_ComponentMax; - FX_FLOAT m_xmin; - FX_FLOAT m_xmax; - FX_FLOAT m_ymin; - FX_FLOAT m_ymax; - FX_FLOAT m_ColorMin[kMaxComponents]; - FX_FLOAT m_ColorMax[kMaxComponents]; - CPDF_StreamAcc m_Stream; - CFX_BitStream m_BitStream; + float m_xmin; + float m_xmax; + float m_ymin; + float m_ymax; + float m_ColorMin[kMaxComponents]; + float m_ColorMax[kMaxComponents]; + RetainPtr m_pStream; + std::unique_ptr m_BitStream; }; #endif // CORE_FPDFAPI_PAGE_CPDF_MESHSTREAM_H_ diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp index 46123ab42ebffcd1006cbe44fb62e50179b2067f..ee7b5d408a9fa8dc0f3256c01300fed60fe8e6f8 100644 --- a/core/fpdfapi/page/cpdf_page.cpp +++ b/core/fpdfapi/page/cpdf_page.cpp @@ -12,7 +12,6 @@ #include "core/fpdfapi/cpdf_pagerendercontext.h" #include "core/fpdfapi/page/cpdf_contentparser.h" #include "core/fpdfapi/page/cpdf_pageobject.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_object.h" @@ -23,44 +22,33 @@ CPDF_Page::CPDF_Page(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict, bool bPageCache) - : m_PageWidth(100), + : CPDF_PageObjectHolder(pDocument, pPageDict), + m_PageWidth(100), m_PageHeight(100), - m_pView(nullptr), - m_pPageRender(bPageCache ? new CPDF_PageRenderCache(this) : nullptr) { - m_pFormDict = pPageDict; - m_pDocument = pDocument; + m_pView(nullptr) { + if (bPageCache) + m_pPageRender = pdfium::MakeUnique(this); if (!pPageDict) return; - CPDF_Object* pageAttr = GetPageAttr("Resources"); - m_pResources = pageAttr ? pageAttr->GetDict() : nullptr; + CPDF_Object* pPageAttr = GetPageAttr("Resources"); + m_pResources = pPageAttr ? pPageAttr->GetDict() : nullptr; m_pPageResources = m_pResources; - CPDF_Object* pRotate = GetPageAttr("Rotate"); - int rotate = pRotate ? pRotate->GetInteger() / 90 % 4 : 0; - if (rotate < 0) - rotate += 4; - - CPDF_Array* pMediaBox = ToArray(GetPageAttr("MediaBox")); - CFX_FloatRect mediabox; - if (pMediaBox) { - mediabox = pMediaBox->GetRect(); - mediabox.Normalize(); - } + + CFX_FloatRect mediabox = GetBox("MediaBox"); if (mediabox.IsEmpty()) mediabox = CFX_FloatRect(0, 0, 612, 792); - CPDF_Array* pCropBox = ToArray(GetPageAttr("CropBox")); - if (pCropBox) { - m_BBox = pCropBox->GetRect(); - m_BBox.Normalize(); - } + m_BBox = GetBox("CropBox"); if (m_BBox.IsEmpty()) m_BBox = mediabox; else m_BBox.Intersect(mediabox); - m_PageWidth = m_BBox.right - m_BBox.left; - m_PageHeight = m_BBox.top - m_BBox.bottom; + m_PageWidth = m_BBox.Width(); + m_PageHeight = m_BBox.Height(); + + int rotate = GetPageRotation(); if (rotate % 2) std::swap(m_PageWidth, m_PageHeight); @@ -80,18 +68,21 @@ CPDF_Page::CPDF_Page(CPDF_Document* pDocument, break; } - m_Transparency = PDFTRANS_ISOLATED; + m_iTransparency = PDFTRANS_ISOLATED; LoadTransInfo(); } CPDF_Page::~CPDF_Page() {} +bool CPDF_Page::IsPage() const { + return true; +} + void CPDF_Page::StartParse() { if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) return; - m_pParser = pdfium::MakeUnique(); - m_pParser->Start(this); + m_pParser = pdfium::MakeUnique(this); m_ParseState = CONTENT_PARSING; } @@ -105,8 +96,8 @@ void CPDF_Page::SetRenderContext( m_pRenderContext = std::move(pContext); } -CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteString& name) const { - CPDF_Dictionary* pPageDict = m_pFormDict; +CPDF_Object* CPDF_Page::GetPageAttr(const ByteString& name) const { + CPDF_Dictionary* pPageDict = m_pFormDict.Get(); std::set visited; while (1) { visited.insert(pPageDict); @@ -120,6 +111,16 @@ CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteString& name) const { return nullptr; } +CFX_FloatRect CPDF_Page::GetBox(const ByteString& name) const { + CFX_FloatRect box; + CPDF_Array* pBox = ToArray(GetPageAttr(name)); + if (pBox) { + box = pBox->GetRect(); + box.Normalize(); + } + return box; +} + CFX_Matrix CPDF_Page::GetDisplayMatrix(int xPos, int yPos, int xSize, @@ -176,12 +177,22 @@ CFX_Matrix CPDF_Page::GetDisplayMatrix(int xPos, return matrix; } +int CPDF_Page::GetPageRotation() const { + CPDF_Object* pRotate = GetPageAttr("Rotate"); + int rotate = pRotate ? (pRotate->GetInteger() / 90) % 4 : 0; + return (rotate < 0) ? (rotate + 4) : rotate; +} + bool GraphicsData::operator<(const GraphicsData& other) const { if (fillAlpha != other.fillAlpha) return fillAlpha < other.fillAlpha; - return strokeAlpha < other.strokeAlpha; + if (strokeAlpha != other.strokeAlpha) + return strokeAlpha < other.strokeAlpha; + return blendType < other.blendType; } bool FontData::operator<(const FontData& other) const { - return baseFont < other.baseFont; + if (baseFont != other.baseFont) + return baseFont < other.baseFont; + return type < other.type; } diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h index 9e303562c6db7c3a55068037a395e4610e4700f6..e1b5bcfa4442d0195c4d460abcd7727b26360823 100644 --- a/core/fpdfapi/page/cpdf_page.h +++ b/core/fpdfapi/page/cpdf_page.h @@ -7,11 +7,9 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_PAGE_H_ #define CORE_FPDFAPI_PAGE_CPDF_PAGE_H_ -#include #include #include "core/fpdfapi/page/cpdf_pageobjectholder.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" @@ -21,19 +19,6 @@ class CPDF_Object; class CPDF_PageRenderCache; class CPDF_PageRenderContext; -// These structs are used to keep track of resources that have already been -// generated in the page. -struct GraphicsData { - FX_FLOAT fillAlpha; - FX_FLOAT strokeAlpha; - bool operator<(const GraphicsData& other) const; -}; - -struct FontData { - CFX_ByteString baseFont; - bool operator<(const FontData& other) const; -}; - class CPDF_Page : public CPDF_PageObjectHolder { public: class View {}; // Caller implements as desired, empty here due to layering. @@ -43,6 +28,9 @@ class CPDF_Page : public CPDF_PageObjectHolder { bool bPageCache); ~CPDF_Page() override; + // CPDF_PageObjectHolder + bool IsPage() const override; + void ParseContent(); CFX_Matrix GetDisplayMatrix(int xPos, @@ -51,11 +39,10 @@ class CPDF_Page : public CPDF_PageObjectHolder { int ySize, int iRotate) const; - FX_FLOAT GetPageWidth() const { return m_PageWidth; } - FX_FLOAT GetPageHeight() const { return m_PageHeight; } + float GetPageWidth() const { return m_PageWidth; } + float GetPageHeight() const { return m_PageHeight; } CFX_FloatRect GetPageBBox() const { return m_BBox; } - const CFX_Matrix& GetPageMatrix() const { return m_PageMatrix; } - CPDF_Object* GetPageAttr(const CFX_ByteString& name) const; + int GetPageRotation() const; CPDF_PageRenderCache* GetRenderCache() const { return m_pPageRender.get(); } CPDF_PageRenderContext* GetRenderContext() const { @@ -66,14 +53,14 @@ class CPDF_Page : public CPDF_PageObjectHolder { View* GetView() const { return m_pView; } void SetView(View* pView) { m_pView = pView; } - std::map m_GraphicsMap; - std::map m_FontsMap; - - protected: + private: void StartParse(); - FX_FLOAT m_PageWidth; - FX_FLOAT m_PageHeight; + CPDF_Object* GetPageAttr(const ByteString& name) const; + CFX_FloatRect GetBox(const ByteString& name) const; + + float m_PageWidth; + float m_PageHeight; CFX_Matrix m_PageMatrix; View* m_pView; std::unique_ptr m_pPageRender; diff --git a/core/fpdfapi/page/cpdf_pagemodule.cpp b/core/fpdfapi/page/cpdf_pagemodule.cpp index 80edf2cdd0bc6ff792cc2af0d80b2852f70d98f8..3b18aceb6e1fb0e5b5ccd01e055198ce7c5ef408 100644 --- a/core/fpdfapi/page/cpdf_pagemodule.cpp +++ b/core/fpdfapi/page/cpdf_pagemodule.cpp @@ -7,10 +7,12 @@ #include "core/fpdfapi/page/cpdf_pagemodule.h" CPDF_PageModule::CPDF_PageModule() - : m_StockGrayCS(nullptr, PDFCS_DEVICEGRAY), - m_StockRGBCS(nullptr, PDFCS_DEVICERGB), - m_StockCMYKCS(nullptr, PDFCS_DEVICECMYK), - m_StockPatternCS(nullptr) {} + : m_StockGrayCS(PDFCS_DEVICEGRAY), + m_StockRGBCS(PDFCS_DEVICERGB), + m_StockCMYKCS(PDFCS_DEVICECMYK), + m_StockPatternCS(nullptr) { + m_StockPatternCS.InitializeStockPattern(); +} CPDF_PageModule::~CPDF_PageModule() {} diff --git a/core/fpdfapi/page/cpdf_pagemodule.h b/core/fpdfapi/page/cpdf_pagemodule.h index 4aa19da2bb6df66079886e158764d7f6e3b5183a..720ee854643f411d51578627dd085bc3511deb51 100644 --- a/core/fpdfapi/page/cpdf_pagemodule.h +++ b/core/fpdfapi/page/cpdf_pagemodule.h @@ -7,9 +7,10 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_PAGEMODULE_H_ #define CORE_FPDFAPI_PAGE_CPDF_PAGEMODULE_H_ -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_colorspace.h" -#include "core/fpdfapi/page/pageint.h" +#include "core/fpdfapi/page/cpdf_devicecs.h" +#include "core/fpdfapi/page/cpdf_patterncs.h" class CPDF_Document; diff --git a/core/fpdfapi/page/cpdf_pageobject.cpp b/core/fpdfapi/page/cpdf_pageobject.cpp index c0e031e7ed8053536de574d52daab384d1c254e9..8bb5bf5978a57259d6275003ec7ea78a937a4119 100644 --- a/core/fpdfapi/page/cpdf_pageobject.cpp +++ b/core/fpdfapi/page/cpdf_pageobject.cpp @@ -6,7 +6,7 @@ #include "core/fpdfapi/page/cpdf_pageobject.h" -CPDF_PageObject::CPDF_PageObject() {} +CPDF_PageObject::CPDF_PageObject() : m_bDirty(false) {} CPDF_PageObject::~CPDF_PageObject() {} @@ -76,24 +76,27 @@ void CPDF_PageObject::CopyData(const CPDF_PageObject* pSrc) { m_Right = pSrc->m_Right; m_Top = pSrc->m_Top; m_Bottom = pSrc->m_Bottom; + m_bDirty = true; } void CPDF_PageObject::TransformClipPath(CFX_Matrix& matrix) { - if (!m_ClipPath) + if (!m_ClipPath.HasRef()) return; m_ClipPath.Transform(matrix); + SetDirty(true); } void CPDF_PageObject::TransformGeneralState(CFX_Matrix& matrix) { - if (!m_GeneralState) + if (!m_GeneralState.HasRef()) return; m_GeneralState.GetMutableMatrix()->Concat(matrix); + SetDirty(true); } FX_RECT CPDF_PageObject::GetBBox(const CFX_Matrix* pMatrix) const { CFX_FloatRect rect(m_Left, m_Bottom, m_Right, m_Top); - if (pMatrix) { - pMatrix->TransformRect(rect); - } + if (pMatrix) + rect = pMatrix->TransformRect(rect); + return rect.GetOuterRect(); } diff --git a/core/fpdfapi/page/cpdf_pageobject.h b/core/fpdfapi/page/cpdf_pageobject.h index d2b84a5d40bf1f4fb2699cd768b690d0f97b12f8..d23cd971f80cd6b51fd7c4a9bdfecfa7d6c145e0 100644 --- a/core/fpdfapi/page/cpdf_pageobject.h +++ b/core/fpdfapi/page/cpdf_pageobject.h @@ -49,6 +49,8 @@ class CPDF_PageObject : public CPDF_GraphicStates { virtual CPDF_FormObject* AsForm(); virtual const CPDF_FormObject* AsForm() const; + void SetDirty(bool value) { m_bDirty = value; } + bool IsDirty() const { return m_bDirty; } void TransformClipPath(CFX_Matrix& matrix); void TransformGeneralState(CFX_Matrix& matrix); @@ -57,10 +59,10 @@ class CPDF_PageObject : public CPDF_GraphicStates { } FX_RECT GetBBox(const CFX_Matrix* pMatrix) const; - FX_FLOAT m_Left; - FX_FLOAT m_Right; - FX_FLOAT m_Top; - FX_FLOAT m_Bottom; + float m_Left; + float m_Right; + float m_Top; + float m_Bottom; CPDF_ContentMark m_ContentMark; protected: @@ -69,6 +71,8 @@ class CPDF_PageObject : public CPDF_GraphicStates { private: CPDF_PageObject(const CPDF_PageObject& src) = delete; void operator=(const CPDF_PageObject& src) = delete; + + bool m_bDirty; }; #endif // CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECT_H_ diff --git a/core/fpdfapi/page/cpdf_pageobjectholder.cpp b/core/fpdfapi/page/cpdf_pageobjectholder.cpp index 3304d4eec4cb49ac3a215f389f7a6046b674738b..51a67e8a15fd3895bb2f00c273c4ef1a0d98ce17 100644 --- a/core/fpdfapi/page/cpdf_pageobjectholder.cpp +++ b/core/fpdfapi/page/cpdf_pageobjectholder.cpp @@ -8,33 +8,46 @@ #include +#include "core/fpdfapi/page/cpdf_allstates.h" #include "core/fpdfapi/page/cpdf_contentparser.h" #include "core/fpdfapi/page/cpdf_pageobject.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" -CPDF_PageObjectHolder::CPDF_PageObjectHolder() - : m_pFormDict(nullptr), +CPDF_PageObjectHolder::CPDF_PageObjectHolder(CPDF_Document* pDoc, + CPDF_Dictionary* pFormDict) + : m_pFormDict(pFormDict), m_pFormStream(nullptr), - m_pDocument(nullptr), + m_pDocument(pDoc), m_pPageResources(nullptr), m_pResources(nullptr), - m_Transparency(0), + m_iTransparency(0), m_bBackgroundAlphaNeeded(false), - m_bHasImageMask(false), - m_ParseState(CONTENT_NOT_PARSED) {} + m_ParseState(CONTENT_NOT_PARSED) { + // TODO(thestig): Check if |m_pFormDict| is never a nullptr and simplify + // callers that checks for that. +} CPDF_PageObjectHolder::~CPDF_PageObjectHolder() {} -void CPDF_PageObjectHolder::ContinueParse(IFX_Pause* pPause) { - if (!m_pParser) { +bool CPDF_PageObjectHolder::IsPage() const { + return false; +} + +void CPDF_PageObjectHolder::ContinueParse(IFX_PauseIndicator* pPause) { + if (!m_pParser) return; - } - m_pParser->Continue(pPause); - if (m_pParser->GetStatus() == CPDF_ContentParser::Done) { - m_ParseState = CONTENT_PARSED; - m_pParser.reset(); - } + + if (m_pParser->Continue(pPause)) + return; + + m_ParseState = CONTENT_PARSED; + if (m_pParser->GetCurStates()) + m_LastCTM = m_pParser->GetCurStates()->m_CTM; + m_pParser.reset(); +} + +void CPDF_PageObjectHolder::AddImageMaskBoundingBox(const CFX_FloatRect& box) { + m_MaskBoundingBoxes.push_back(box); } void CPDF_PageObjectHolder::Transform(const CFX_Matrix& matrix) { @@ -44,12 +57,12 @@ void CPDF_PageObjectHolder::Transform(const CFX_Matrix& matrix) { CFX_FloatRect CPDF_PageObjectHolder::CalcBoundingBox() const { if (m_PageObjectList.empty()) - return CFX_FloatRect(0, 0, 0, 0); + return CFX_FloatRect(); - FX_FLOAT left = 1000000.0f; - FX_FLOAT right = -1000000.0f; - FX_FLOAT bottom = 1000000.0f; - FX_FLOAT top = -1000000.0f; + float left = 1000000.0f; + float right = -1000000.0f; + float bottom = 1000000.0f; + float top = -1000000.0f; for (const auto& pObj : m_PageObjectList) { left = std::min(left, pObj->m_Left); right = std::max(right, pObj->m_Right); @@ -70,11 +83,11 @@ void CPDF_PageObjectHolder::LoadTransInfo() { if (pGroup->GetStringFor("S") != "Transparency") { return; } - m_Transparency |= PDFTRANS_GROUP; + m_iTransparency |= PDFTRANS_GROUP; if (pGroup->GetIntegerFor("I")) { - m_Transparency |= PDFTRANS_ISOLATED; + m_iTransparency |= PDFTRANS_ISOLATED; } if (pGroup->GetIntegerFor("K")) { - m_Transparency |= PDFTRANS_KNOCKOUT; + m_iTransparency |= PDFTRANS_KNOCKOUT; } } diff --git a/core/fpdfapi/page/cpdf_pageobjectholder.h b/core/fpdfapi/page/cpdf_pageobjectholder.h index aee7617c1f93fa0f8b5529faf0af560330ee89c6..f649ef7b62f51b9c082d77aae4a35e62824cab4c 100644 --- a/core/fpdfapi/page/cpdf_pageobjectholder.h +++ b/core/fpdfapi/page/cpdf_pageobjectholder.h @@ -7,13 +7,17 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECTHOLDER_H_ #define CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECTHOLDER_H_ +#include #include +#include #include "core/fpdfapi/page/cpdf_pageobjectlist.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" -class IFX_Pause; +class IFX_PauseIndicator; class CPDF_Dictionary; class CPDF_Stream; class CPDF_Document; @@ -23,37 +27,59 @@ class CPDF_ContentParser; #define PDFTRANS_ISOLATED 0x0200 #define PDFTRANS_KNOCKOUT 0x0400 +// These structs are used to keep track of resources that have already been +// generated in the page object holder. +struct GraphicsData { + float fillAlpha; + float strokeAlpha; + int blendType; + bool operator<(const GraphicsData& other) const; +}; + +struct FontData { + ByteString baseFont; + ByteString type; + bool operator<(const FontData& other) const; +}; + class CPDF_PageObjectHolder { public: - CPDF_PageObjectHolder(); + CPDF_PageObjectHolder(CPDF_Document* pDoc, CPDF_Dictionary* pFormDict); virtual ~CPDF_PageObjectHolder(); - void ContinueParse(IFX_Pause* pPause); + virtual bool IsPage() const; + + void ContinueParse(IFX_PauseIndicator* pPause); bool IsParsed() const { return m_ParseState == CONTENT_PARSED; } CPDF_PageObjectList* GetPageObjectList() { return &m_PageObjectList; } const CPDF_PageObjectList* GetPageObjectList() const { return &m_PageObjectList; } + const CFX_Matrix& GetLastCTM() const { return m_LastCTM; } bool BackgroundAlphaNeeded() const { return m_bBackgroundAlphaNeeded; } void SetBackgroundAlphaNeeded(bool needed) { m_bBackgroundAlphaNeeded = needed; } - bool HasImageMask() const { return m_bHasImageMask; } - void SetHasImageMask(bool value) { m_bHasImageMask = value; } - + bool HasImageMask() const { return !m_MaskBoundingBoxes.empty(); } + const std::vector& GetMaskBoundingBoxes() const { + return m_MaskBoundingBoxes; + } + void AddImageMaskBoundingBox(const CFX_FloatRect& box); void Transform(const CFX_Matrix& matrix); CFX_FloatRect CalcBoundingBox() const; - CPDF_Dictionary* m_pFormDict; - CPDF_Stream* m_pFormStream; - CPDF_Document* m_pDocument; - CPDF_Dictionary* m_pPageResources; - CPDF_Dictionary* m_pResources; + const UnownedPtr m_pFormDict; + UnownedPtr m_pFormStream; + UnownedPtr m_pDocument; + UnownedPtr m_pPageResources; + UnownedPtr m_pResources; + std::map m_GraphicsMap; + std::map m_FontsMap; CFX_FloatRect m_BBox; - int m_Transparency; + int m_iTransparency; protected: enum ParseState { CONTENT_NOT_PARSED, CONTENT_PARSING, CONTENT_PARSED }; @@ -61,10 +87,11 @@ class CPDF_PageObjectHolder { void LoadTransInfo(); bool m_bBackgroundAlphaNeeded; - bool m_bHasImageMask; + std::vector m_MaskBoundingBoxes; ParseState m_ParseState; std::unique_ptr m_pParser; CPDF_PageObjectList m_PageObjectList; + CFX_Matrix m_LastCTM; }; #endif // CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECTHOLDER_H_ diff --git a/core/fpdfapi/page/cpdf_pageobjectlist.cpp b/core/fpdfapi/page/cpdf_pageobjectlist.cpp index 02b590e4139305a3cb9ad783e84c22e360b27f0b..afd2c98536fefb01c45870f0756652059f9a675e 100644 --- a/core/fpdfapi/page/cpdf_pageobjectlist.cpp +++ b/core/fpdfapi/page/cpdf_pageobjectlist.cpp @@ -6,11 +6,8 @@ #include "core/fpdfapi/page/cpdf_pageobjectlist.h" -#include "core/fpdfapi/page/pageint.h" #include "third_party/base/stl_util.h" CPDF_PageObject* CPDF_PageObjectList::GetPageObjectByIndex(int index) { - if (index < 0 || index >= pdfium::CollectionSize(*this)) - return nullptr; - return (*this)[index].get(); + return pdfium::IndexInBounds(*this, index) ? (*this)[index].get() : nullptr; } diff --git a/core/fpdfapi/page/cpdf_path.cpp b/core/fpdfapi/page/cpdf_path.cpp index ddc6bbd1d6fea41c6e6efc81a1b4e7c7ad02d7ab..b56249cd62217d41fd8077038cc2530d54a2143a 100644 --- a/core/fpdfapi/page/cpdf_path.cpp +++ b/core/fpdfapi/page/cpdf_path.cpp @@ -28,8 +28,8 @@ CFX_FloatRect CPDF_Path::GetBoundingBox() const { return m_Ref.GetObject()->GetBoundingBox(); } -CFX_FloatRect CPDF_Path::GetBoundingBox(FX_FLOAT line_width, - FX_FLOAT miter_limit) const { +CFX_FloatRect CPDF_Path::GetBoundingBox(float line_width, + float miter_limit) const { return m_Ref.GetObject()->GetBoundingBox(line_width, miter_limit); } @@ -49,10 +49,7 @@ void CPDF_Path::Append(const CFX_PathData* pData, const CFX_Matrix* pMatrix) { m_Ref.GetPrivateCopy()->Append(pData, pMatrix); } -void CPDF_Path::AppendRect(FX_FLOAT left, - FX_FLOAT bottom, - FX_FLOAT right, - FX_FLOAT top) { +void CPDF_Path::AppendRect(float left, float bottom, float right, float top) { m_Ref.GetPrivateCopy()->AppendRect(left, bottom, right, top); } diff --git a/core/fpdfapi/page/cpdf_path.h b/core/fpdfapi/page/cpdf_path.h index b0c5a68a444e87975bc1d866d7d1e5420cfeb11a..613d715b033371df24f4c787de1ac3a5f39c1f1c 100644 --- a/core/fpdfapi/page/cpdf_path.h +++ b/core/fpdfapi/page/cpdf_path.h @@ -9,9 +9,9 @@ #include -#include "core/fxcrt/cfx_shared_copy_on_write.h" #include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxcrt/shared_copy_on_write.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" @@ -22,28 +22,28 @@ class CPDF_Path { ~CPDF_Path(); void Emplace() { m_Ref.Emplace(); } - explicit operator bool() const { return !!m_Ref; } + bool HasRef() const { return !!m_Ref; } const std::vector& GetPoints() const; void ClosePath(); CFX_PointF GetPoint(int index) const; CFX_FloatRect GetBoundingBox() const; - CFX_FloatRect GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const; + CFX_FloatRect GetBoundingBox(float line_width, float miter_limit) const; bool IsRect() const; void Transform(const CFX_Matrix* pMatrix); void Append(const CPDF_Path& other, const CFX_Matrix* pMatrix); void Append(const CFX_PathData* pData, const CFX_Matrix* pMatrix); - void AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top); + void AppendRect(float left, float bottom, float right, float top); void AppendPoint(const CFX_PointF& point, FXPT_TYPE type, bool close); // TODO(tsepez): Remove when all access thru this class. const CFX_PathData* GetObject() const { return m_Ref.GetObject(); } private: - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; #endif // CORE_FPDFAPI_PAGE_CPDF_PATH_H_ diff --git a/core/fpdfapi/page/cpdf_pathobject.cpp b/core/fpdfapi/page/cpdf_pathobject.cpp index b5bb89390ce9b5c43fe84994d17149c0bb983bf1..d8c2cb8741b5ef5af29b6bbbe0cdc965539aa0b7 100644 --- a/core/fpdfapi/page/cpdf_pathobject.cpp +++ b/core/fpdfapi/page/cpdf_pathobject.cpp @@ -6,7 +6,7 @@ #include "core/fpdfapi/page/cpdf_pathobject.h" -CPDF_PathObject::CPDF_PathObject() {} +CPDF_PathObject::CPDF_PathObject() : m_FillType(0), m_bStroke(false) {} CPDF_PathObject::~CPDF_PathObject() {} @@ -17,6 +17,7 @@ CPDF_PageObject::Type CPDF_PathObject::GetType() const { void CPDF_PathObject::Transform(const CFX_Matrix& matrix) { m_Matrix.Concat(matrix); CalcBoundingBox(); + SetDirty(true); } bool CPDF_PathObject::IsPath() const { @@ -32,16 +33,16 @@ const CPDF_PathObject* CPDF_PathObject::AsPath() const { } void CPDF_PathObject::CalcBoundingBox() { - if (!m_Path) + if (!m_Path.HasRef()) return; CFX_FloatRect rect; - FX_FLOAT width = m_GraphState.GetLineWidth(); + float width = m_GraphState.GetLineWidth(); if (m_bStroke && width != 0) { rect = m_Path.GetBoundingBox(width, m_GraphState.GetMiterLimit()); } else { rect = m_Path.GetBoundingBox(); } - m_Matrix.TransformRect(rect); + rect = m_Matrix.TransformRect(rect); if (width == 0 && m_bStroke) { rect.left += -0.5f; diff --git a/core/fpdfapi/page/cpdf_pattern.cpp b/core/fpdfapi/page/cpdf_pattern.cpp index b0a2d81bca25c91e51cf0ecadb10eb28229a8ed8..88e5dee35c1613f2fdbebb2ab43c3d17b9b904c6 100644 --- a/core/fpdfapi/page/cpdf_pattern.cpp +++ b/core/fpdfapi/page/cpdf_pattern.cpp @@ -6,13 +6,17 @@ #include "core/fpdfapi/page/cpdf_pattern.h" -CPDF_Pattern::CPDF_Pattern(PatternType type, - CPDF_Document* pDoc, +#include "core/fpdfapi/parser/cpdf_dictionary.h" + +CPDF_Pattern::CPDF_Pattern(CPDF_Document* pDoc, CPDF_Object* pObj, const CFX_Matrix& parentMatrix) - : m_PatternType(type), - m_pDocument(pDoc), - m_pPatternObj(pObj), - m_ParentMatrix(parentMatrix) {} + : m_pDocument(pDoc), m_pPatternObj(pObj), m_ParentMatrix(parentMatrix) {} CPDF_Pattern::~CPDF_Pattern() {} + +void CPDF_Pattern::SetPatternToFormMatrix() { + CPDF_Dictionary* pDict = pattern_obj()->GetDict(); + m_Pattern2Form = pDict->GetMatrixFor("Matrix"); + m_Pattern2Form.Concat(m_ParentMatrix); +} diff --git a/core/fpdfapi/page/cpdf_pattern.h b/core/fpdfapi/page/cpdf_pattern.h index d44965ff16119253ccd52a4bf369574197a6e8ca..307c67777529e11c677b2f3b2d3837993fa81f6a 100644 --- a/core/fpdfapi/page/cpdf_pattern.h +++ b/core/fpdfapi/page/cpdf_pattern.h @@ -7,8 +7,10 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_PATTERN_H_ #define CORE_FPDFAPI_PAGE_CPDF_PATTERN_H_ +#include "core/fpdfapi/page/cpdf_countedobject.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_Object; @@ -24,22 +26,25 @@ class CPDF_Pattern { virtual CPDF_TilingPattern* AsTilingPattern() = 0; virtual CPDF_ShadingPattern* AsShadingPattern() = 0; - CPDF_Document* document() { return m_pDocument; } - CPDF_Object* pattern_obj() { return m_pPatternObj; } + // All the getters that return pointers return non-NULL pointers. + CPDF_Document* document() const { return m_pDocument.Get(); } + CPDF_Object* pattern_obj() const { return m_pPatternObj.Get(); } CFX_Matrix* pattern_to_form() { return &m_Pattern2Form; } const CFX_Matrix& parent_matrix() const { return m_ParentMatrix; } protected: - CPDF_Pattern(PatternType type, - CPDF_Document* pDoc, + CPDF_Pattern(CPDF_Document* pDoc, CPDF_Object* pObj, const CFX_Matrix& parentMatrix); - const PatternType m_PatternType; - CPDF_Document* const m_pDocument; - CPDF_Object* const m_pPatternObj; + void SetPatternToFormMatrix(); + + private: + UnownedPtr const m_pDocument; + UnownedPtr const m_pPatternObj; CFX_Matrix m_Pattern2Form; const CFX_Matrix m_ParentMatrix; }; +using CPDF_CountedPattern = CPDF_CountedObject; #endif // CORE_FPDFAPI_PAGE_CPDF_PATTERN_H_ diff --git a/core/fpdfapi/page/cpdf_patterncs.cpp b/core/fpdfapi/page/cpdf_patterncs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4b680f0263a50b494512ddda89699813e06d4b1 --- /dev/null +++ b/core/fpdfapi/page/cpdf_patterncs.cpp @@ -0,0 +1,64 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_patterncs.h" + +#include "core/fpdfapi/page/cpdf_docpagedata.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_document.h" + +CPDF_PatternCS::CPDF_PatternCS(CPDF_Document* pDoc) + : CPDF_ColorSpace(pDoc, PDFCS_PATTERN), + m_pBaseCS(nullptr), + m_pCountedBaseCS(nullptr) {} + +CPDF_PatternCS::~CPDF_PatternCS() { + CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : nullptr; + if (pCS && m_pDocument) { + auto* pPageData = m_pDocument->GetPageData(); + if (pPageData) + pPageData->ReleaseColorSpace(pCS->GetArray()); + } +} + +void CPDF_PatternCS::InitializeStockPattern() { + SetComponentsForStockCS(1); +} + +uint32_t CPDF_PatternCS::v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) { + CPDF_Object* pBaseCS = pArray->GetDirectObjectAt(1); + if (pBaseCS == m_pArray) + return 0; + + CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); + m_pBaseCS = pDocPageData->GetColorSpaceGuarded(pBaseCS, nullptr, pVisited); + if (!m_pBaseCS) + return 1; + + if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) + return 0; + + m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray()); + if (m_pBaseCS->CountComponents() > kMaxPatternColorComps) + return 0; + + return m_pBaseCS->CountComponents() + 1; +} + +bool CPDF_PatternCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { + if (m_pBaseCS) { + ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN); + PatternValue* pvalue = reinterpret_cast(pBuf); + if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) + return true; + } + *R = 0.75f; + *G = 0.75f; + *B = 0.75f; + return false; +} diff --git a/core/fpdfapi/page/cpdf_patterncs.h b/core/fpdfapi/page/cpdf_patterncs.h new file mode 100644 index 0000000000000000000000000000000000000000..d1d0d48c1e9a38c2422743470bc843478d556906 --- /dev/null +++ b/core/fpdfapi/page/cpdf_patterncs.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_PATTERNCS_H_ +#define CORE_FPDFAPI_PAGE_CPDF_PATTERNCS_H_ + +#include + +#include "core/fpdfapi/page/cpdf_colorspace.h" + +class CPDF_Document; + +class CPDF_PatternCS : public CPDF_ColorSpace { + public: + explicit CPDF_PatternCS(CPDF_Document* pDoc); + ~CPDF_PatternCS() override; + + // Called for the stock pattern, since it is initialized via Load(). + void InitializeStockPattern(); + + // CPDF_ColorSpace: + uint32_t v_Load(CPDF_Document* pDoc, + CPDF_Array* pArray, + std::set* pVisited) override; + bool GetRGB(float* pBuf, float* R, float* G, float* B) const override; + + private: + CPDF_ColorSpace* m_pBaseCS; + CPDF_CountedColorSpace* m_pCountedBaseCS; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_PATTERNCS_H_ diff --git a/core/fpdfapi/page/cpdf_psengine.cpp b/core/fpdfapi/page/cpdf_psengine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ce3a604a1185f36712b7db2fa4bed992fd4b681 --- /dev/null +++ b/core/fpdfapi/page/cpdf_psengine.cpp @@ -0,0 +1,432 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_psengine.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/fx_string.h" +#include "third_party/base/logging.h" +#include "third_party/base/ptr_util.h" + +namespace { + +struct PDF_PSOpName { + const char* name; + PDF_PSOP op; +}; + +constexpr PDF_PSOpName kPsOpNames[] = { + {"abs", PSOP_ABS}, + {"add", PSOP_ADD}, + {"and", PSOP_AND}, + {"atan", PSOP_ATAN}, + {"bitshift", PSOP_BITSHIFT}, + {"ceiling", PSOP_CEILING}, + {"copy", PSOP_COPY}, + {"cos", PSOP_COS}, + {"cvi", PSOP_CVI}, + {"cvr", PSOP_CVR}, + {"div", PSOP_DIV}, + {"dup", PSOP_DUP}, + {"eq", PSOP_EQ}, + {"exch", PSOP_EXCH}, + {"exp", PSOP_EXP}, + {"false", PSOP_FALSE}, + {"floor", PSOP_FLOOR}, + {"ge", PSOP_GE}, + {"gt", PSOP_GT}, + {"idiv", PSOP_IDIV}, + {"if", PSOP_IF}, + {"ifelse", PSOP_IFELSE}, + {"index", PSOP_INDEX}, + {"le", PSOP_LE}, + {"ln", PSOP_LN}, + {"log", PSOP_LOG}, + {"lt", PSOP_LT}, + {"mod", PSOP_MOD}, + {"mul", PSOP_MUL}, + {"ne", PSOP_NE}, + {"neg", PSOP_NEG}, + {"not", PSOP_NOT}, + {"or", PSOP_OR}, + {"pop", PSOP_POP}, + {"roll", PSOP_ROLL}, + {"round", PSOP_ROUND}, + {"sin", PSOP_SIN}, + {"sqrt", PSOP_SQRT}, + {"sub", PSOP_SUB}, + {"true", PSOP_TRUE}, + {"truncate", PSOP_TRUNCATE}, + {"xor", PSOP_XOR}, +}; + +} // namespace + +CPDF_PSOP::CPDF_PSOP() + : m_op(PSOP_PROC), m_value(0), m_proc(pdfium::MakeUnique()) {} + +CPDF_PSOP::CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { + ASSERT(m_op != PSOP_CONST); + ASSERT(m_op != PSOP_PROC); +} + +CPDF_PSOP::CPDF_PSOP(float value) : m_op(PSOP_CONST), m_value(value) {} + +CPDF_PSOP::~CPDF_PSOP() {} + +float CPDF_PSOP::GetFloatValue() const { + if (m_op == PSOP_CONST) + return m_value; + + NOTREACHED(); + return 0; +} + +CPDF_PSProc* CPDF_PSOP::GetProc() const { + if (m_op == PSOP_PROC) + return m_proc.get(); + NOTREACHED(); + return nullptr; +} + +bool CPDF_PSEngine::Execute() { + return m_MainProc.Execute(this); +} + +CPDF_PSProc::CPDF_PSProc() {} +CPDF_PSProc::~CPDF_PSProc() {} + +bool CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { + if (depth > kMaxDepth) + return false; + + while (1) { + ByteStringView word = parser->GetWord(); + if (word.IsEmpty()) + return false; + + if (word == "}") + return true; + + if (word == "{") { + m_Operators.push_back(pdfium::MakeUnique()); + if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1)) + return false; + continue; + } + + AddOperator(word); + } +} + +bool CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) { + for (size_t i = 0; i < m_Operators.size(); ++i) { + const PDF_PSOP op = m_Operators[i]->GetOp(); + if (op == PSOP_PROC) + continue; + + if (op == PSOP_CONST) { + pEngine->Push(m_Operators[i]->GetFloatValue()); + continue; + } + + if (op == PSOP_IF) { + if (i == 0 || m_Operators[i - 1]->GetOp() != PSOP_PROC) + return false; + + if (pEngine->PopInt()) + m_Operators[i - 1]->GetProc()->Execute(pEngine); + } else if (op == PSOP_IFELSE) { + if (i < 2 || m_Operators[i - 1]->GetOp() != PSOP_PROC || + m_Operators[i - 2]->GetOp() != PSOP_PROC) { + return false; + } + size_t offset = pEngine->PopInt() ? 2 : 1; + m_Operators[i - offset]->GetProc()->Execute(pEngine); + } else { + pEngine->DoOperator(op); + } + } + return true; +} + +void CPDF_PSProc::AddOperatorForTesting(const ByteStringView& word) { + AddOperator(word); +} + +void CPDF_PSProc::AddOperator(const ByteStringView& word) { + const auto* pFound = std::lower_bound( + std::begin(kPsOpNames), std::end(kPsOpNames), word, + [](const PDF_PSOpName& name, const ByteStringView& word) { + return name.name < word; + }); + if (pFound != std::end(kPsOpNames) && pFound->name == word) + m_Operators.push_back(pdfium::MakeUnique(pFound->op)); + else + m_Operators.push_back(pdfium::MakeUnique(FX_atof(word))); +} + +CPDF_PSEngine::CPDF_PSEngine() : m_StackCount(0) {} + +CPDF_PSEngine::~CPDF_PSEngine() {} + +void CPDF_PSEngine::Push(float v) { + if (m_StackCount < kPSEngineStackSize) + m_Stack[m_StackCount++] = v; +} + +float CPDF_PSEngine::Pop() { + return m_StackCount > 0 ? m_Stack[--m_StackCount] : 0; +} + +int CPDF_PSEngine::PopInt() { + return static_cast(Pop()); +} + +bool CPDF_PSEngine::Parse(const char* str, int size) { + CPDF_SimpleParser parser(reinterpret_cast(str), size); + ByteStringView word = parser.GetWord(); + return word == "{" ? m_MainProc.Parse(&parser, 0) : false; +} + +bool CPDF_PSEngine::DoOperator(PDF_PSOP op) { + int i1; + int i2; + float d1; + float d2; + FX_SAFE_INT32 result; + switch (op) { + case PSOP_ADD: + d1 = Pop(); + d2 = Pop(); + Push(d1 + d2); + break; + case PSOP_SUB: + d2 = Pop(); + d1 = Pop(); + Push(d1 - d2); + break; + case PSOP_MUL: + d1 = Pop(); + d2 = Pop(); + Push(d1 * d2); + break; + case PSOP_DIV: + d2 = Pop(); + d1 = Pop(); + Push(d1 / d2); + break; + case PSOP_IDIV: + i2 = PopInt(); + i1 = PopInt(); + if (i2) { + result = i1; + result /= i2; + Push(result.ValueOrDefault(0)); + } else { + Push(0); + } + break; + case PSOP_MOD: + i2 = PopInt(); + i1 = PopInt(); + if (i2) { + result = i1; + result %= i2; + Push(result.ValueOrDefault(0)); + } else { + Push(0); + } + break; + case PSOP_NEG: + d1 = Pop(); + Push(-d1); + break; + case PSOP_ABS: + d1 = Pop(); + Push(fabs(d1)); + break; + case PSOP_CEILING: + d1 = Pop(); + Push(ceil(d1)); + break; + case PSOP_FLOOR: + d1 = Pop(); + Push(floor(d1)); + break; + case PSOP_ROUND: + d1 = Pop(); + Push(FXSYS_round(d1)); + break; + case PSOP_TRUNCATE: + i1 = PopInt(); + Push(i1); + break; + case PSOP_SQRT: + d1 = Pop(); + Push(sqrt(d1)); + break; + case PSOP_SIN: + d1 = Pop(); + Push(sin(d1 * FX_PI / 180.0f)); + break; + case PSOP_COS: + d1 = Pop(); + Push(cos(d1 * FX_PI / 180.0f)); + break; + case PSOP_ATAN: + d2 = Pop(); + d1 = Pop(); + d1 = atan2(d1, d2) * 180.0 / FX_PI; + if (d1 < 0) { + d1 += 360; + } + Push(d1); + break; + case PSOP_EXP: + d2 = Pop(); + d1 = Pop(); + Push(FXSYS_pow(d1, d2)); + break; + case PSOP_LN: + d1 = Pop(); + Push(log(d1)); + break; + case PSOP_LOG: + d1 = Pop(); + Push(log10(d1)); + break; + case PSOP_CVI: + i1 = PopInt(); + Push(i1); + break; + case PSOP_CVR: + break; + case PSOP_EQ: + d2 = Pop(); + d1 = Pop(); + Push(d1 == d2); + break; + case PSOP_NE: + d2 = Pop(); + d1 = Pop(); + Push(d1 != d2); + break; + case PSOP_GT: + d2 = Pop(); + d1 = Pop(); + Push(d1 > d2); + break; + case PSOP_GE: + d2 = Pop(); + d1 = Pop(); + Push(d1 >= d2); + break; + case PSOP_LT: + d2 = Pop(); + d1 = Pop(); + Push(d1 < d2); + break; + case PSOP_LE: + d2 = Pop(); + d1 = Pop(); + Push(d1 <= d2); + break; + case PSOP_AND: + i1 = PopInt(); + i2 = PopInt(); + Push(i1 & i2); + break; + case PSOP_OR: + i1 = PopInt(); + i2 = PopInt(); + Push(i1 | i2); + break; + case PSOP_XOR: + i1 = PopInt(); + i2 = PopInt(); + Push(i1 ^ i2); + break; + case PSOP_NOT: + i1 = PopInt(); + Push(!i1); + break; + case PSOP_BITSHIFT: { + int shift = PopInt(); + result = PopInt(); + if (shift > 0) { + result <<= shift; + } else { + // Avoids unsafe negation of INT_MIN. + FX_SAFE_INT32 safe_shift = shift; + result >>= (-safe_shift).ValueOrDefault(0); + } + Push(result.ValueOrDefault(0)); + break; + } + case PSOP_TRUE: + Push(1); + break; + case PSOP_FALSE: + Push(0); + break; + case PSOP_POP: + Pop(); + break; + case PSOP_EXCH: + d2 = Pop(); + d1 = Pop(); + Push(d2); + Push(d1); + break; + case PSOP_DUP: + d1 = Pop(); + Push(d1); + Push(d1); + break; + case PSOP_COPY: { + int n = PopInt(); + if (n < 0 || m_StackCount + n > kPSEngineStackSize || + n > static_cast(m_StackCount)) + break; + for (int i = 0; i < n; i++) + m_Stack[m_StackCount + i] = m_Stack[m_StackCount + i - n]; + m_StackCount += n; + break; + } + case PSOP_INDEX: { + int n = PopInt(); + if (n < 0 || n >= static_cast(m_StackCount)) + break; + Push(m_Stack[m_StackCount - n - 1]); + break; + } + case PSOP_ROLL: { + int j = PopInt(); + int n = PopInt(); + if (j == 0 || n == 0 || m_StackCount == 0) + break; + if (n < 0 || n > static_cast(m_StackCount)) + break; + + j %= n; + if (j > 0) + j -= n; + auto* begin_it = std::begin(m_Stack) + m_StackCount - n; + auto* middle_it = begin_it - j; + auto* end_it = std::begin(m_Stack) + m_StackCount; + std::rotate(begin_it, middle_it, end_it); + break; + } + default: + break; + } + return true; +} diff --git a/core/fpdfapi/page/cpdf_psengine.h b/core/fpdfapi/page/cpdf_psengine.h index 659ca82f6b8cf8aba26db8ad1cf41ce174ae2fbf..63d91d0757043011e87bf360acab6c9dcca65b57 100644 --- a/core/fpdfapi/page/cpdf_psengine.h +++ b/core/fpdfapi/page/cpdf_psengine.h @@ -10,13 +10,14 @@ #include #include +#include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" class CPDF_PSEngine; -class CPDF_PSOP; +class CPDF_PSProc; class CPDF_SimpleParser; -enum PDF_PSOP { +enum PDF_PSOP : uint8_t { PSOP_ADD, PSOP_SUB, PSOP_MUL, @@ -63,7 +64,22 @@ enum PDF_PSOP { PSOP_CONST }; -constexpr uint32_t PSENGINE_STACKSIZE = 100; +class CPDF_PSOP { + public: + CPDF_PSOP(); + explicit CPDF_PSOP(PDF_PSOP op); + explicit CPDF_PSOP(float value); + ~CPDF_PSOP(); + + float GetFloatValue() const; + CPDF_PSProc* GetProc() const; + PDF_PSOP GetOp() const { return m_op; } + + private: + const PDF_PSOP m_op; + const float m_value; + std::unique_ptr m_proc; +}; class CPDF_PSProc { public: @@ -73,8 +89,18 @@ class CPDF_PSProc { bool Parse(CPDF_SimpleParser* parser, int depth); bool Execute(CPDF_PSEngine* pEngine); + // These methods are exposed for testing. + void AddOperatorForTesting(const ByteStringView& word); + size_t num_operators() const { return m_Operators.size(); } + const std::unique_ptr& last_operator() { + return m_Operators.back(); + } + private: static const int kMaxDepth = 128; + + void AddOperator(const ByteStringView& word); + std::vector> m_Operators; }; @@ -83,16 +109,18 @@ class CPDF_PSEngine { CPDF_PSEngine(); ~CPDF_PSEngine(); - bool Parse(const FX_CHAR* str, int size); + bool Parse(const char* str, int size); bool Execute(); bool DoOperator(PDF_PSOP op); void Reset() { m_StackCount = 0; } - void Push(FX_FLOAT value); - FX_FLOAT Pop(); + void Push(float value); + float Pop(); + int PopInt(); uint32_t GetStackSize() const { return m_StackCount; } private: - FX_FLOAT m_Stack[PSENGINE_STACKSIZE]; + static constexpr uint32_t kPSEngineStackSize = 100; + float m_Stack[kPSEngineStackSize]; uint32_t m_StackCount; CPDF_PSProc m_MainProc; }; diff --git a/core/fpdfapi/page/cpdf_psengine_unittest.cpp b/core/fpdfapi/page/cpdf_psengine_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f966c3aced48493f8899e64d399d8bbd68745f35 --- /dev/null +++ b/core/fpdfapi/page/cpdf_psengine_unittest.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/page/cpdf_psengine.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(CPDF_PSProc, AddOperator) { + static const struct { + const char* name; + PDF_PSOP op; + } kTestData[] = { + {"add", PSOP_ADD}, {"sub", PSOP_SUB}, + {"mul", PSOP_MUL}, {"div", PSOP_DIV}, + {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD}, + {"neg", PSOP_NEG}, {"abs", PSOP_ABS}, + {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR}, + {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE}, + {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN}, + {"cos", PSOP_COS}, {"atan", PSOP_ATAN}, + {"exp", PSOP_EXP}, {"ln", PSOP_LN}, + {"log", PSOP_LOG}, {"cvi", PSOP_CVI}, + {"cvr", PSOP_CVR}, {"eq", PSOP_EQ}, + {"ne", PSOP_NE}, {"gt", PSOP_GT}, + {"ge", PSOP_GE}, {"lt", PSOP_LT}, + {"le", PSOP_LE}, {"and", PSOP_AND}, + {"or", PSOP_OR}, {"xor", PSOP_XOR}, + {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT}, + {"true", PSOP_TRUE}, {"false", PSOP_FALSE}, + {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE}, + {"pop", PSOP_POP}, {"exch", PSOP_EXCH}, + {"dup", PSOP_DUP}, {"copy", PSOP_COPY}, + {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}, + {"55", PSOP_CONST}, {"123.4", PSOP_CONST}, + {"-5", PSOP_CONST}, {"invalid", PSOP_CONST}, + }; + + CPDF_PSProc proc; + EXPECT_EQ(0U, proc.num_operators()); + for (size_t i = 0; i < FX_ArraySize(kTestData); ++i) { + ByteStringView word(kTestData[i].name); + proc.AddOperatorForTesting(word); + ASSERT_EQ(i + 1, proc.num_operators()); + const std::unique_ptr& new_psop = proc.last_operator(); + ASSERT_TRUE(new_psop); + PDF_PSOP new_op = new_psop->GetOp(); + EXPECT_EQ(kTestData[i].op, new_op); + if (new_op == PSOP_CONST) { + float fv = new_psop->GetFloatValue(); + if (word == "invalid") + EXPECT_FLOAT_EQ(0, fv); + else + EXPECT_EQ(word, ByteString::FormatFloat(fv)); + } + } +} diff --git a/core/fpdfapi/page/cpdf_psfunc.cpp b/core/fpdfapi/page/cpdf_psfunc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f101eb91b8d1b4b9086acf8271e4e6b42058d20 --- /dev/null +++ b/core/fpdfapi/page/cpdf_psfunc.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_psfunc.h" + +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "third_party/base/ptr_util.h" + +CPDF_PSFunc::CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} + +CPDF_PSFunc::~CPDF_PSFunc() {} + +bool CPDF_PSFunc::v_Init(CPDF_Object* pObj) { + auto pAcc = pdfium::MakeRetain(pObj->AsStream()); + pAcc->LoadAllDataFiltered(); + return m_PS.Parse(reinterpret_cast(pAcc->GetData()), + pAcc->GetSize()); +} + +bool CPDF_PSFunc::v_Call(float* inputs, float* results) const { + CPDF_PSEngine& PS = const_cast(m_PS); + PS.Reset(); + for (uint32_t i = 0; i < m_nInputs; i++) + PS.Push(inputs[i]); + PS.Execute(); + if (PS.GetStackSize() < m_nOutputs) + return false; + for (uint32_t i = 0; i < m_nOutputs; i++) + results[m_nOutputs - i - 1] = PS.Pop(); + return true; +} diff --git a/core/fpdfapi/page/cpdf_psfunc.h b/core/fpdfapi/page/cpdf_psfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..b8c18c94721a7cca111a078bb01329a07044807c --- /dev/null +++ b/core/fpdfapi/page/cpdf_psfunc.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_PSFUNC_H_ +#define CORE_FPDFAPI_PAGE_CPDF_PSFUNC_H_ + +#include "core/fpdfapi/page/cpdf_function.h" +#include "core/fpdfapi/page/cpdf_psengine.h" + +class CPDF_Object; + +class CPDF_PSFunc : public CPDF_Function { + public: + CPDF_PSFunc(); + ~CPDF_PSFunc() override; + + // CPDF_Function + bool v_Init(CPDF_Object* pObj) override; + bool v_Call(float* inputs, float* results) const override; + + private: + CPDF_PSEngine m_PS; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_PSFUNC_H_ diff --git a/core/fpdfapi/page/cpdf_sampledfunc.cpp b/core/fpdfapi/page/cpdf_sampledfunc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98e1fd03e09e85b24ecf4feed26340f9b0575099 --- /dev/null +++ b/core/fpdfapi/page/cpdf_sampledfunc.cpp @@ -0,0 +1,158 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_sampledfunc.h" + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fxcrt/cfx_fixedbufgrow.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" + +namespace { + +// See PDF Reference 1.7, page 170, table 3.36. +bool IsValidBitsPerSample(uint32_t x) { + switch (x) { + case 1: + case 2: + case 4: + case 8: + case 12: + case 16: + case 24: + case 32: + return true; + default: + return false; + } +} + +} // namespace + +CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} + +CPDF_SampledFunc::~CPDF_SampledFunc() {} + +bool CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { + CPDF_Stream* pStream = pObj->AsStream(); + if (!pStream) + return false; + + CPDF_Dictionary* pDict = pStream->GetDict(); + CPDF_Array* pSize = pDict->GetArrayFor("Size"); + CPDF_Array* pEncode = pDict->GetArrayFor("Encode"); + CPDF_Array* pDecode = pDict->GetArrayFor("Decode"); + m_nBitsPerSample = pDict->GetIntegerFor("BitsPerSample"); + if (!IsValidBitsPerSample(m_nBitsPerSample)) + return false; + + m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample); + m_pSampleStream = pdfium::MakeRetain(pStream); + m_pSampleStream->LoadAllDataFiltered(); + FX_SAFE_UINT32 nTotalSampleBits = 1; + m_EncodeInfo.resize(m_nInputs); + for (uint32_t i = 0; i < m_nInputs; i++) { + m_EncodeInfo[i].sizes = pSize ? pSize->GetIntegerAt(i) : 0; + if (!pSize && i == 0) + m_EncodeInfo[i].sizes = pDict->GetIntegerFor("Size"); + nTotalSampleBits *= m_EncodeInfo[i].sizes; + if (pEncode) { + m_EncodeInfo[i].encode_min = pEncode->GetFloatAt(i * 2); + m_EncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1); + } else { + m_EncodeInfo[i].encode_min = 0; + m_EncodeInfo[i].encode_max = + m_EncodeInfo[i].sizes == 1 ? 1 : (float)m_EncodeInfo[i].sizes - 1; + } + } + nTotalSampleBits *= m_nBitsPerSample; + nTotalSampleBits *= m_nOutputs; + FX_SAFE_UINT32 nTotalSampleBytes = nTotalSampleBits; + nTotalSampleBytes += 7; + nTotalSampleBytes /= 8; + if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0 || + nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) { + return false; + } + m_DecodeInfo.resize(m_nOutputs); + for (uint32_t i = 0; i < m_nOutputs; i++) { + if (pDecode) { + m_DecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i); + m_DecodeInfo[i].decode_max = pDecode->GetFloatAt(2 * i + 1); + } else { + m_DecodeInfo[i].decode_min = m_pRanges[i * 2]; + m_DecodeInfo[i].decode_max = m_pRanges[i * 2 + 1]; + } + } + return true; +} + +bool CPDF_SampledFunc::v_Call(float* inputs, float* results) const { + int pos = 0; + CFX_FixedBufGrow encoded_input_buf(m_nInputs); + float* encoded_input = encoded_input_buf; + CFX_FixedBufGrow int_buf(m_nInputs * 2); + uint32_t* index = int_buf; + uint32_t* blocksize = index + m_nInputs; + for (uint32_t i = 0; i < m_nInputs; i++) { + if (i == 0) + blocksize[i] = 1; + else + blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes; + encoded_input[i] = + Interpolate(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1], + m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max); + index[i] = pdfium::clamp(static_cast(encoded_input[i]), 0U, + m_EncodeInfo[i].sizes - 1); + pos += index[i] * blocksize[i]; + } + FX_SAFE_INT32 bits_to_output = m_nOutputs; + bits_to_output *= m_nBitsPerSample; + if (!bits_to_output.IsValid()) + return false; + + FX_SAFE_INT32 bitpos = pos; + bitpos *= bits_to_output.ValueOrDie(); + if (!bitpos.IsValid()) + return false; + + FX_SAFE_INT32 range_check = bitpos; + range_check += bits_to_output.ValueOrDie(); + if (!range_check.IsValid()) + return false; + + const uint8_t* pSampleData = m_pSampleStream->GetData(); + if (!pSampleData) + return false; + + for (uint32_t j = 0; j < m_nOutputs; j++, bitpos += m_nBitsPerSample) { + uint32_t sample = + GetBits32(pSampleData, bitpos.ValueOrDie(), m_nBitsPerSample); + float encoded = (float)sample; + for (uint32_t i = 0; i < m_nInputs; i++) { + if (index[i] == m_EncodeInfo[i].sizes - 1) { + if (index[i] == 0) + encoded = encoded_input[i] * (float)sample; + } else { + FX_SAFE_INT32 bitpos2 = blocksize[i]; + bitpos2 += pos; + bitpos2 *= m_nOutputs; + bitpos2 += j; + bitpos2 *= m_nBitsPerSample; + if (!bitpos2.IsValid()) + return false; + uint32_t sample1 = + GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample); + encoded += + (encoded_input[i] - index[i]) * ((float)sample1 - (float)sample); + } + } + results[j] = + Interpolate(encoded, 0, (float)m_SampleMax, m_DecodeInfo[j].decode_min, + m_DecodeInfo[j].decode_max); + } + return true; +} diff --git a/core/fpdfapi/page/cpdf_sampledfunc.h b/core/fpdfapi/page/cpdf_sampledfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..d6dfed575fc14c38334fe9fdeeccf8d07301bbab --- /dev/null +++ b/core/fpdfapi/page/cpdf_sampledfunc.h @@ -0,0 +1,50 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_SAMPLEDFUNC_H_ +#define CORE_FPDFAPI_PAGE_CPDF_SAMPLEDFUNC_H_ + +#include + +#include "core/fpdfapi/page/cpdf_function.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcrt/retain_ptr.h" + +class CPDF_SampledFunc : public CPDF_Function { + public: + struct SampleEncodeInfo { + float encode_max; + float encode_min; + uint32_t sizes; + }; + + struct SampleDecodeInfo { + float decode_max; + float decode_min; + }; + + CPDF_SampledFunc(); + ~CPDF_SampledFunc() override; + + // CPDF_Function + bool v_Init(CPDF_Object* pObj) override; + bool v_Call(float* inputs, float* results) const override; + + const std::vector& GetEncodeInfo() const { + return m_EncodeInfo; + } + uint32_t GetBitsPerSample() const { return m_nBitsPerSample; } + RetainPtr GetSampleStream() const { return m_pSampleStream; } + + private: + std::vector m_EncodeInfo; + std::vector m_DecodeInfo; + uint32_t m_nBitsPerSample; + uint32_t m_SampleMax; + RetainPtr m_pSampleStream; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_SAMPLEDFUNC_H_ diff --git a/core/fpdfapi/page/cpdf_shadingobject.cpp b/core/fpdfapi/page/cpdf_shadingobject.cpp index 928b0af47ecc4f42d64b57c274933a0cd9a93d09..1b16ac4862fbe2ee8f92a3dd7d0d6c9dd0cc08e9 100644 --- a/core/fpdfapi/page/cpdf_shadingobject.cpp +++ b/core/fpdfapi/page/cpdf_shadingobject.cpp @@ -6,11 +6,12 @@ #include "core/fpdfapi/page/cpdf_shadingobject.h" -#include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_shadingpattern.h" #include "core/fpdfapi/parser/cpdf_document.h" -CPDF_ShadingObject::CPDF_ShadingObject() : m_pShading(nullptr) {} +CPDF_ShadingObject::CPDF_ShadingObject(CPDF_ShadingPattern* pattern, + const CFX_Matrix& matrix) + : m_pShading(pattern), m_Matrix(matrix) {} CPDF_ShadingObject::~CPDF_ShadingObject() {} @@ -19,14 +20,15 @@ CPDF_PageObject::Type CPDF_ShadingObject::GetType() const { } void CPDF_ShadingObject::Transform(const CFX_Matrix& matrix) { - if (m_ClipPath) + if (m_ClipPath.HasRef()) m_ClipPath.Transform(matrix); m_Matrix.Concat(matrix); - if (m_ClipPath) { + if (m_ClipPath.HasRef()) { CalcBoundingBox(); } else { - matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); + std::tie(m_Left, m_Right, m_Top, m_Bottom) = + matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); } } @@ -43,7 +45,7 @@ const CPDF_ShadingObject* CPDF_ShadingObject::AsShading() const { } void CPDF_ShadingObject::CalcBoundingBox() { - if (!m_ClipPath) + if (!m_ClipPath.HasRef()) return; CFX_FloatRect rect = m_ClipPath.GetClipBox(); m_Left = rect.left; diff --git a/core/fpdfapi/page/cpdf_shadingobject.h b/core/fpdfapi/page/cpdf_shadingobject.h index ffd622379eba97c63d7ebca3a9e71a3f61fd4b0c..80e062c729c984659eb76c3b4d5b51a09aa05c55 100644 --- a/core/fpdfapi/page/cpdf_shadingobject.h +++ b/core/fpdfapi/page/cpdf_shadingobject.h @@ -9,15 +9,16 @@ #include "core/fpdfapi/page/cpdf_pageobject.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_ShadingPattern; class CPDF_ShadingObject : public CPDF_PageObject { public: - CPDF_ShadingObject(); + CPDF_ShadingObject(CPDF_ShadingPattern* pattern, const CFX_Matrix& matrix); ~CPDF_ShadingObject() override; - // CPDF_PageObject + // CPDF_PageObject: Type GetType() const override; void Transform(const CFX_Matrix& matrix) override; bool IsShading() const override; @@ -26,7 +27,11 @@ class CPDF_ShadingObject : public CPDF_PageObject { void CalcBoundingBox(); - CPDF_ShadingPattern* m_pShading; + const CPDF_ShadingPattern* pattern() const { return m_pShading.Get(); } + const CFX_Matrix& matrix() const { return m_Matrix; } + + private: + UnownedPtr m_pShading; CFX_Matrix m_Matrix; }; diff --git a/core/fpdfapi/page/cpdf_shadingpattern.cpp b/core/fpdfapi/page/cpdf_shadingpattern.cpp index e19ffaf0c47c05afe984fe40d32cac4d52758d9d..f1e75b726a60284a57f455eee96a56daf5115d27 100644 --- a/core/fpdfapi/page/cpdf_shadingpattern.cpp +++ b/core/fpdfapi/page/cpdf_shadingpattern.cpp @@ -9,7 +9,7 @@ #include #include "core/fpdfapi/page/cpdf_docpagedata.h" -#include "core/fpdfapi/page/pageint.h" +#include "core/fpdfapi/page/cpdf_function.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" @@ -31,27 +31,28 @@ CPDF_ShadingPattern::CPDF_ShadingPattern(CPDF_Document* pDoc, CPDF_Object* pPatternObj, bool bShading, const CFX_Matrix& parentMatrix) - : CPDF_Pattern(SHADING, - pDoc, - bShading ? nullptr : pPatternObj, - parentMatrix), + : CPDF_Pattern(pDoc, bShading ? nullptr : pPatternObj, parentMatrix), m_ShadingType(kInvalidShading), m_bShadingObj(bShading), m_pShadingObj(pPatternObj), m_pCS(nullptr), m_pCountedCS(nullptr) { + assert(document()); if (!bShading) { - CPDF_Dictionary* pDict = m_pPatternObj->GetDict(); - m_Pattern2Form = pDict->GetMatrixFor("Matrix"); - m_pShadingObj = pDict->GetDirectObjectFor("Shading"); - m_Pattern2Form.Concat(parentMatrix); + m_pShadingObj = pattern_obj()->GetDict()->GetDirectObjectFor("Shading"); + SetPatternToFormMatrix(); } } CPDF_ShadingPattern::~CPDF_ShadingPattern() { - CPDF_ColorSpace* pCS = m_pCountedCS ? m_pCountedCS->get() : nullptr; - if (pCS && m_pDocument) - m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); + CPDF_ColorSpace* pCountedCS = m_pCountedCS ? m_pCountedCS->get() : nullptr; + if (pCountedCS) { + auto* pPageData = document()->GetPageData(); + if (pPageData) { + m_pCS.Release(); // Give up unowned reference first. + pPageData->ReleaseColorSpace(pCountedCS->GetArray()); + } + } } CPDF_TilingPattern* CPDF_ShadingPattern::AsTilingPattern() { @@ -86,16 +87,110 @@ bool CPDF_ShadingPattern::Load() { if (!pCSObj) return false; - CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData(); + CPDF_DocPageData* pDocPageData = document()->GetPageData(); m_pCS = pDocPageData->GetColorSpace(pCSObj, nullptr); - if (m_pCS) - m_pCountedCS = pDocPageData->FindColorSpacePtr(m_pCS->GetArray()); + + // The color space is required and cannot be a Pattern space, according to the + // PDF 1.7 spec, page 305. + if (!m_pCS || m_pCS->GetFamily() == PDFCS_PATTERN) + return false; + + m_pCountedCS = pDocPageData->FindColorSpacePtr(m_pCS->GetArray()); m_ShadingType = ToShadingType(pShadingDict->GetIntegerFor("ShadingType")); + return Validate(); +} + +bool CPDF_ShadingPattern::Validate() const { + if (m_ShadingType == kInvalidShading) + return false; + // We expect to have a stream if our shading type is a mesh. - if (IsMeshShading() && !ToStream(m_pShadingObj)) + if (IsMeshShading() && !ToStream(m_pShadingObj.Get())) return false; + // Validate color space + switch (m_ShadingType) { + case kFunctionBasedShading: + case kAxialShading: + case kRadialShading: { + if (m_pCS->GetFamily() == PDFCS_INDEXED) + return false; + break; + } + case kFreeFormGouraudTriangleMeshShading: + case kLatticeFormGouraudTriangleMeshShading: + case kCoonsPatchMeshShading: + case kTensorProductPatchMeshShading: { + if (!m_pFunctions.empty() && m_pCS->GetFamily() == PDFCS_INDEXED) + return false; + break; + } + default: { + NOTREACHED(); + return false; + } + } + + uint32_t nNumColorSpaceComponents = m_pCS->CountComponents(); + switch (m_ShadingType) { + case kFunctionBasedShading: { + // Either one 2-to-N function or N 2-to-1 functions. + if (!ValidateFunctions(1, 2, nNumColorSpaceComponents) && + !ValidateFunctions(nNumColorSpaceComponents, 2, 1)) { + return false; + } + break; + } + case kAxialShading: + case kRadialShading: { + // Either one 1-to-N function or N 1-to-1 functions. + if (!ValidateFunctions(1, 1, nNumColorSpaceComponents) && + !ValidateFunctions(nNumColorSpaceComponents, 1, 1)) { + return false; + } + break; + } + case kFreeFormGouraudTriangleMeshShading: + case kLatticeFormGouraudTriangleMeshShading: + case kCoonsPatchMeshShading: + case kTensorProductPatchMeshShading: { + // Either no function, one 1-to-N function, or N 1-to-1 functions. + if (!m_pFunctions.empty() && + !ValidateFunctions(1, 1, nNumColorSpaceComponents) && + !ValidateFunctions(nNumColorSpaceComponents, 1, 1)) { + return false; + } + break; + } + default: { + NOTREACHED(); + return false; + } + } return true; } + +bool CPDF_ShadingPattern::ValidateFunctions( + uint32_t nExpectedNumFunctions, + uint32_t nExpectedNumInputs, + uint32_t nExpectedNumOutputs) const { + if (m_pFunctions.size() != nExpectedNumFunctions) + return false; + + pdfium::base::CheckedNumeric nTotalOutputs = 0; + for (const auto& function : m_pFunctions) { + if (!function) + return false; + + if (function->CountInputs() != nExpectedNumInputs || + function->CountOutputs() != nExpectedNumOutputs) { + return false; + } + + nTotalOutputs += function->CountOutputs(); + } + + return nTotalOutputs.IsValid(); +} diff --git a/core/fpdfapi/page/cpdf_shadingpattern.h b/core/fpdfapi/page/cpdf_shadingpattern.h index 136153d4a033aba063dfdccbcf760c6fbec47822..17b6e4bb8c8d60ee64016466c18526645418d5ea 100644 --- a/core/fpdfapi/page/cpdf_shadingpattern.h +++ b/core/fpdfapi/page/cpdf_shadingpattern.h @@ -10,9 +10,10 @@ #include #include -#include "core/fpdfapi/page/cpdf_countedobject.h" +#include "core/fpdfapi/page/cpdf_colorspace.h" #include "core/fpdfapi/page/cpdf_pattern.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" enum ShadingType { kInvalidShading = 0, @@ -53,22 +54,28 @@ class CPDF_ShadingPattern : public CPDF_Pattern { ShadingType GetShadingType() const { return m_ShadingType; } bool IsShadingObject() const { return m_bShadingObj; } - CPDF_Object* GetShadingObject() const { return m_pShadingObj; } - CPDF_ColorSpace* GetCS() const { return m_pCS; } + CPDF_Object* GetShadingObject() const { return m_pShadingObj.Get(); } + CPDF_ColorSpace* GetCS() const { return m_pCS.Get(); } const std::vector>& GetFuncs() const { return m_pFunctions; } private: + // Constraints in PDF 1.7 spec, 4.6.3 Shading Patterns, pages 308-331. + bool Validate() const; + bool ValidateFunctions(uint32_t nExpectedNumFunctions, + uint32_t nExpectedNumInputs, + uint32_t nExpectedNumOutputs) const; + ShadingType m_ShadingType; bool m_bShadingObj; - CPDF_Object* m_pShadingObj; + UnownedPtr m_pShadingObj; // Still keep |m_pCS| as some CPDF_ColorSpace (name object) are not managed // as counted objects. Refer to CPDF_DocPageData::GetColorSpace. - CPDF_ColorSpace* m_pCS; + UnownedPtr m_pCS; - CPDF_CountedColorSpace* m_pCountedCS; + UnownedPtr m_pCountedCS; std::vector> m_pFunctions; }; diff --git a/core/fpdfapi/page/cpdf_stitchfunc.cpp b/core/fpdfapi/page/cpdf_stitchfunc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..336c74bf5cced1c26dd2de06742f68707cd2ab3a --- /dev/null +++ b/core/fpdfapi/page/cpdf_stitchfunc.cpp @@ -0,0 +1,91 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfapi/page/cpdf_stitchfunc.h" + +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fxcrt/fx_memory.h" + +CPDF_StitchFunc::CPDF_StitchFunc() + : CPDF_Function(Type::kType3Stitching), + m_pBounds(nullptr), + m_pEncode(nullptr) {} + +CPDF_StitchFunc::~CPDF_StitchFunc() { + FX_Free(m_pBounds); + FX_Free(m_pEncode); +} + +bool CPDF_StitchFunc::v_Init(CPDF_Object* pObj) { + CPDF_Dictionary* pDict = pObj->GetDict(); + if (!pDict) { + return false; + } + if (m_nInputs != kRequiredNumInputs) { + return false; + } + CPDF_Array* pArray = pDict->GetArrayFor("Functions"); + if (!pArray) { + return false; + } + uint32_t nSubs = pArray->GetCount(); + if (nSubs == 0) + return false; + m_nOutputs = 0; + for (uint32_t i = 0; i < nSubs; i++) { + CPDF_Object* pSub = pArray->GetDirectObjectAt(i); + if (pSub == pObj) + return false; + std::unique_ptr pFunc(CPDF_Function::Load(pSub)); + if (!pFunc) + return false; + // Check that the input dimensionality is 1, and that all output + // dimensionalities are the same. + if (pFunc->CountInputs() != kRequiredNumInputs) + return false; + if (pFunc->CountOutputs() != m_nOutputs) { + if (m_nOutputs) + return false; + + m_nOutputs = pFunc->CountOutputs(); + } + + m_pSubFunctions.push_back(std::move(pFunc)); + } + m_pBounds = FX_Alloc(float, nSubs + 1); + m_pBounds[0] = m_pDomains[0]; + pArray = pDict->GetArrayFor("Bounds"); + if (!pArray) + return false; + for (uint32_t i = 0; i < nSubs - 1; i++) + m_pBounds[i + 1] = pArray->GetFloatAt(i); + m_pBounds[nSubs] = m_pDomains[1]; + m_pEncode = FX_Alloc2D(float, nSubs, 2); + pArray = pDict->GetArrayFor("Encode"); + if (!pArray) + return false; + + for (uint32_t i = 0; i < nSubs * 2; i++) + m_pEncode[i] = pArray->GetFloatAt(i); + return true; +} + +bool CPDF_StitchFunc::v_Call(float* inputs, float* outputs) const { + float input = inputs[0]; + size_t i; + for (i = 0; i < m_pSubFunctions.size() - 1; i++) { + if (input < m_pBounds[i + 1]) + break; + } + input = Interpolate(input, m_pBounds[i], m_pBounds[i + 1], m_pEncode[i * 2], + m_pEncode[i * 2 + 1]); + int nresults; + m_pSubFunctions[i]->Call(&input, kRequiredNumInputs, outputs, &nresults); + return true; +} diff --git a/core/fpdfapi/page/cpdf_stitchfunc.h b/core/fpdfapi/page/cpdf_stitchfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..69e5e410417cba7fe67f3ab685a3d491c8c127a5 --- /dev/null +++ b/core/fpdfapi/page/cpdf_stitchfunc.h @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_PAGE_CPDF_STITCHFUNC_H_ +#define CORE_FPDFAPI_PAGE_CPDF_STITCHFUNC_H_ + +#include +#include + +#include "core/fpdfapi/page/cpdf_function.h" + +class CPDF_StitchFunc : public CPDF_Function { + public: + CPDF_StitchFunc(); + ~CPDF_StitchFunc() override; + + // CPDF_Function + bool v_Init(CPDF_Object* pObj) override; + bool v_Call(float* inputs, float* results) const override; + + const std::vector>& GetSubFunctions() const { + return m_pSubFunctions; + } + float GetBound(size_t i) const { return m_pBounds[i]; } + + private: + std::vector> m_pSubFunctions; + float* m_pBounds; + float* m_pEncode; + + static const uint32_t kRequiredNumInputs = 1; +}; + +#endif // CORE_FPDFAPI_PAGE_CPDF_STITCHFUNC_H_ diff --git a/core/fpdfapi/page/fpdf_page_func_embeddertest.cpp b/core/fpdfapi/page/cpdf_stitchfunc_embeddertest.cpp similarity index 100% rename from core/fpdfapi/page/fpdf_page_func_embeddertest.cpp rename to core/fpdfapi/page/cpdf_stitchfunc_embeddertest.cpp diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp index 6211b6a4dd3feb053cded8280a3c79f26b26e123..4e3857bf85cc1d40d0dbecd30df402dee6f17ed4 100644 --- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp +++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp @@ -25,7 +25,6 @@ #include "core/fpdfapi/page/cpdf_shadingpattern.h" #include "core/fpdfapi/page/cpdf_streamparser.h" #include "core/fpdfapi/page/cpdf_textobject.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" @@ -36,7 +35,9 @@ #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxge/cfx_graphstatedata.h" +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" namespace { @@ -75,11 +76,11 @@ CFX_FloatRect GetShadingBBox(CPDF_ShadingPattern* pShading, CPDF_Stream* pStream = ToStream(pShading->GetShadingObject()); CPDF_ColorSpace* pCS = pShading->GetCS(); if (!pStream || !pCS) - return CFX_FloatRect(0, 0, 0, 0); + return CFX_FloatRect(); CPDF_MeshStream stream(type, pShading->GetFuncs(), pStream, pCS); if (!stream.Load()) - return CFX_FloatRect(0, 0, 0, 0); + return CFX_FloatRect(); CFX_FloatRect rect; bool bStarted = false; @@ -114,9 +115,9 @@ CFX_FloatRect GetShadingBBox(CPDF_ShadingPattern* pShading, break; CFX_PointF origin = stream.ReadCoords(); if (bStarted) { - rect.UpdateRect(origin.x, origin.y); + rect.UpdateRect(origin); } else { - rect.InitRect(origin.x, origin.y); + rect.InitRect(origin); bStarted = true; } } @@ -130,13 +131,12 @@ CFX_FloatRect GetShadingBBox(CPDF_ShadingPattern* pShading, if (bGouraud) stream.BitStream()->ByteAlign(); } - matrix.TransformRect(rect); - return rect; + return matrix.TransformRect(rect); } struct AbbrPair { - const FX_CHAR* abbr; - const FX_CHAR* full_name; + const char* abbr; + const char* full_name; }; const AbbrPair InlineKeyAbbr[] = { @@ -156,18 +156,17 @@ const AbbrPair InlineValueAbbr[] = { struct AbbrReplacementOp { bool is_replace_key; - CFX_ByteString key; - CFX_ByteStringC replacement; + ByteString key; + ByteStringView replacement; }; -CFX_ByteStringC FindFullName(const AbbrPair* table, - size_t count, - const CFX_ByteStringC& abbr) { - auto it = std::find_if(table, table + count, [abbr](const AbbrPair& pair) { +ByteStringView FindFullName(const AbbrPair* table, + size_t count, + const ByteStringView& abbr) { + auto* it = std::find_if(table, table + count, [abbr](const AbbrPair& pair) { return pair.abbr == abbr; }); - return it != table + count ? CFX_ByteStringC(it->full_name) - : CFX_ByteStringC(); + return it != table + count ? ByteStringView(it->full_name) : ByteStringView(); } void ReplaceAbbr(CPDF_Object* pObj) { @@ -176,10 +175,10 @@ void ReplaceAbbr(CPDF_Object* pObj) { CPDF_Dictionary* pDict = pObj->AsDictionary(); std::vector replacements; for (const auto& it : *pDict) { - CFX_ByteString key = it.first; + ByteString key = it.first; CPDF_Object* value = it.second.get(); - CFX_ByteStringC fullname = FindFullName( - InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), key.AsStringC()); + ByteStringView fullname = FindFullName( + InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), key.AsStringView()); if (!fullname.IsEmpty()) { AbbrReplacementOp op; op.is_replace_key = true; @@ -190,9 +189,10 @@ void ReplaceAbbr(CPDF_Object* pObj) { } if (value->IsName()) { - CFX_ByteString name = value->GetString(); - fullname = FindFullName( - InlineValueAbbr, FX_ArraySize(InlineValueAbbr), name.AsStringC()); + ByteString name = value->GetString(); + fullname = + FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr), + name.AsStringView()); if (!fullname.IsEmpty()) { AbbrReplacementOp op; op.is_replace_key = false; @@ -206,9 +206,9 @@ void ReplaceAbbr(CPDF_Object* pObj) { } for (const auto& op : replacements) { if (op.is_replace_key) - pDict->ReplaceKey(op.key, CFX_ByteString(op.replacement)); + pDict->ReplaceKey(op.key, ByteString(op.replacement)); else - pDict->SetNewFor(op.key, CFX_ByteString(op.replacement)); + pDict->SetNewFor(op.key, ByteString(op.replacement)); } break; } @@ -217,11 +217,12 @@ void ReplaceAbbr(CPDF_Object* pObj) { for (size_t i = 0; i < pArray->GetCount(); i++) { CPDF_Object* pElement = pArray->GetObjectAt(i); if (pElement->IsName()) { - CFX_ByteString name = pElement->GetString(); - CFX_ByteStringC fullname = FindFullName( - InlineValueAbbr, FX_ArraySize(InlineValueAbbr), name.AsStringC()); + ByteString name = pElement->GetString(); + ByteStringView fullname = + FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr), + name.AsStringView()); if (!fullname.IsEmpty()) - pArray->SetNewAt(i, CFX_ByteString(fullname)); + pArray->SetNewAt(i, ByteString(fullname)); } else { ReplaceAbbr(pElement); } @@ -235,15 +236,6 @@ void ReplaceAbbr(CPDF_Object* pObj) { } // namespace -CFX_ByteStringC PDF_FindKeyAbbreviationForTesting(const CFX_ByteStringC& abbr) { - return FindFullName(InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), abbr); -} - -CFX_ByteStringC PDF_FindValueAbbreviationForTesting( - const CFX_ByteStringC& abbr) { - return FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr), abbr); -} - CPDF_StreamContentParser::CPDF_StreamContentParser( CPDF_Document* pDocument, CPDF_Dictionary* pPageResources, @@ -251,29 +243,25 @@ CPDF_StreamContentParser::CPDF_StreamContentParser( const CFX_Matrix* pmtContentToUser, CPDF_PageObjectHolder* pObjHolder, CPDF_Dictionary* pResources, - CFX_FloatRect* pBBox, + const CFX_FloatRect& rcBBox, CPDF_AllStates* pStates, - int level) + std::set* parsedSet) : m_pDocument(pDocument), m_pPageResources(pPageResources), m_pParentResources(pParentResources), m_pResources(pResources), m_pObjectHolder(pObjHolder), - m_Level(level), + m_ParsedSet(parsedSet), + m_BBox(rcBBox), m_ParamStartPos(0), m_ParamCount(0), - m_pCurStates(new CPDF_AllStates), - m_pLastTextObject(nullptr), + m_pCurStates(pdfium::MakeUnique()), m_DefFontSize(0), - m_pPathPoints(nullptr), - m_PathPointCount(0), - m_PathAllocSize(0), m_PathStartX(0.0f), m_PathStartY(0.0f), m_PathCurrentX(0.0f), m_PathCurrentY(0.0f), m_PathClipType(0), - m_pLastImage(nullptr), m_bColored(false), m_bResourceMissing(false) { if (pmtContentToUser) @@ -282,8 +270,6 @@ CPDF_StreamContentParser::CPDF_StreamContentParser( m_pResources = m_pParentResources; if (!m_pResources) m_pResources = m_pPageResources; - if (pBBox) - m_BBox = *pBBox; if (pStates) { m_pCurStates->Copy(*pStates); } else { @@ -299,7 +285,6 @@ CPDF_StreamContentParser::CPDF_StreamContentParser( CPDF_StreamContentParser::~CPDF_StreamContentParser() { ClearAllParams(); - FX_Free(m_pPathPoints); } int CPDF_StreamContentParser::GetNextParamPos() { @@ -321,7 +306,7 @@ int CPDF_StreamContentParser::GetNextParamPos() { return index; } -void CPDF_StreamContentParser::AddNameParam(const CFX_ByteStringC& bsName) { +void CPDF_StreamContentParser::AddNameParam(const ByteStringView& bsName) { ContentParam& param = m_ParamBuf[GetNextParamPos()]; if (bsName.GetLength() > 32) { param.m_Type = ContentParam::OBJECT; @@ -329,18 +314,18 @@ void CPDF_StreamContentParser::AddNameParam(const CFX_ByteStringC& bsName) { m_pDocument->GetByteStringPool(), PDF_NameDecode(bsName)); } else { param.m_Type = ContentParam::NAME; - if (bsName.Find('#') == -1) { - FXSYS_memcpy(param.m_Name.m_Buffer, bsName.raw_str(), bsName.GetLength()); - param.m_Name.m_Len = bsName.GetLength(); - } else { - CFX_ByteString str = PDF_NameDecode(bsName); - FXSYS_memcpy(param.m_Name.m_Buffer, str.c_str(), str.GetLength()); + if (bsName.Contains('#')) { + ByteString str = PDF_NameDecode(bsName); + memcpy(param.m_Name.m_Buffer, str.c_str(), str.GetLength()); param.m_Name.m_Len = str.GetLength(); + } else { + memcpy(param.m_Name.m_Buffer, bsName.raw_str(), bsName.GetLength()); + param.m_Name.m_Len = bsName.GetLength(); } } } -void CPDF_StreamContentParser::AddNumberParam(const CFX_ByteStringC& str) { +void CPDF_StreamContentParser::AddNumberParam(const ByteStringView& str) { ContentParam& param = m_ParamBuf[GetNextParamPos()]; param.m_Type = ContentParam::NUMBER; param.m_Number.m_bInteger = FX_atonum(str, ¶m.m_Number.m_Integer); @@ -387,19 +372,19 @@ CPDF_Object* CPDF_StreamContentParser::GetObject(uint32_t index) { param.m_Type = ContentParam::OBJECT; param.m_pObject = pdfium::MakeUnique( m_pDocument->GetByteStringPool(), - CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len)); + ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len)); return param.m_pObject.get(); } if (param.m_Type == ContentParam::OBJECT) return param.m_pObject.get(); - ASSERT(false); + NOTREACHED(); return nullptr; } -CFX_ByteString CPDF_StreamContentParser::GetString(uint32_t index) { +ByteString CPDF_StreamContentParser::GetString(uint32_t index) { if (index >= m_ParamCount) { - return CFX_ByteString(); + return ByteString(); } int real_index = m_ParamStartPos + m_ParamCount - index - 1; if (real_index >= kParamBufSize) { @@ -407,15 +392,15 @@ CFX_ByteString CPDF_StreamContentParser::GetString(uint32_t index) { } ContentParam& param = m_ParamBuf[real_index]; if (param.m_Type == ContentParam::NAME) { - return CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len); + return ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len); } if (param.m_Type == 0 && param.m_pObject) { return param.m_pObject->GetString(); } - return CFX_ByteString(); + return ByteString(); } -FX_FLOAT CPDF_StreamContentParser::GetNumber(uint32_t index) { +float CPDF_StreamContentParser::GetNumber(uint32_t index) { if (index >= m_ParamCount) { return 0; } @@ -425,12 +410,12 @@ FX_FLOAT CPDF_StreamContentParser::GetNumber(uint32_t index) { } ContentParam& param = m_ParamBuf[real_index]; if (param.m_Type == ContentParam::NUMBER) { - return param.m_Number.m_bInteger ? (FX_FLOAT)param.m_Number.m_Integer - : param.m_Number.m_Float; + return param.m_Number.m_bInteger + ? static_cast(param.m_Number.m_Integer) + : param.m_Number.m_Float; } - if (param.m_Type == 0 && param.m_pObject) { + if (param.m_Type == 0 && param.m_pObject) return param.m_pObject->GetNumber(); - } return 0; } @@ -573,7 +558,7 @@ CPDF_StreamContentParser::InitializeOpCodes() { }); } -void CPDF_StreamContentParser::OnOperator(const CFX_ByteStringC& op) { +void CPDF_StreamContentParser::OnOperator(const ByteStringView& op) { static const OpCodes s_OpCodes = InitializeOpCodes(); auto it = s_OpCodes.find(op.GetID()); @@ -600,7 +585,7 @@ void CPDF_StreamContentParser::Handle_EOFillStrokePath() { } void CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary() { - CFX_ByteString tag = GetString(1); + ByteString tag = GetString(1); CPDF_Object* pProperty = GetObject(0); if (!pProperty) { return; @@ -632,12 +617,13 @@ void CPDF_StreamContentParser::Handle_BeginImage() { if (type != CPDF_StreamParser::Name) { break; } - CFX_ByteString key(m_pSyntax->GetWord().Mid(1)); + auto word = m_pSyntax->GetWord(); + ByteString key(word.Right(word.GetLength() - 1)); auto pObj = m_pSyntax->ReadNextObject(false, false, 0); if (!key.IsEmpty()) { uint32_t dwObjNum = pObj ? pObj->GetObjNum() : 0; if (dwObjNum) - pDict->SetNewFor(key, m_pDocument, dwObjNum); + pDict->SetNewFor(key, m_pDocument.Get(), dwObjNum); else pDict->SetFor(key, std::move(pObj)); } @@ -647,7 +633,7 @@ void CPDF_StreamContentParser::Handle_BeginImage() { if (pDict->KeyExist("ColorSpace")) { pCSObj = pDict->GetDirectObjectFor("ColorSpace"); if (pCSObj->IsName()) { - CFX_ByteString name = pCSObj->GetString(); + ByteString name = pCSObj->GetString(); if (name != "DeviceRGB" && name != "DeviceGray" && name != "DeviceCMYK") { pCSObj = FindResourceObj("ColorSpace", name); if (pCSObj && pCSObj->IsInline()) @@ -657,7 +643,7 @@ void CPDF_StreamContentParser::Handle_BeginImage() { } pDict->SetNewFor("Subtype", "Image"); std::unique_ptr pStream = - m_pSyntax->ReadInlineStream(m_pDocument, std::move(pDict), pCSObj); + m_pSyntax->ReadInlineStream(m_pDocument.Get(), std::move(pDict), pCSObj); while (1) { CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); if (type == CPDF_StreamParser::EndOfData) { @@ -670,7 +656,11 @@ void CPDF_StreamContentParser::Handle_BeginImage() { break; } } - AddImage(std::move(pStream)); + CPDF_ImageObject* pObj = AddImage(std::move(pStream)); + // Record the bounding box of this image, so rendering code can draw it + // properly. + if (pObj && pObj->GetImage()->IsMask()) + m_pObjectHolder->AddImageMaskBoundingBox(pObj->GetRect()); } void CPDF_StreamContentParser::Handle_BeginMarkedContent() { @@ -736,10 +726,14 @@ void CPDF_StreamContentParser::Handle_SetCachedDevice() { } void CPDF_StreamContentParser::Handle_ExecuteXObject() { - CFX_ByteString name = GetString(0); + ByteString name = GetString(0); if (name == m_LastImageName && m_pLastImage && m_pLastImage->GetStream() && m_pLastImage->GetStream()->GetObjNum()) { - AddImage(m_pLastImage); + CPDF_ImageObject* pObj = AddImage(m_pLastImage); + // Record the bounding box of this image, so rendering code can draw it + // properly. + if (pObj && pObj->GetImage()->IsMask()) + m_pObjectHolder->AddImageMaskBoundingBox(pObj->GetRect()); return; } @@ -749,7 +743,7 @@ void CPDF_StreamContentParser::Handle_ExecuteXObject() { return; } - CFX_ByteString type; + ByteString type; if (pXObject->GetDict()) type = pXObject->GetDict()->GetStringFor("Subtype"); @@ -760,28 +754,32 @@ void CPDF_StreamContentParser::Handle_ExecuteXObject() { : AddImage(pXObject->GetObjNum()); m_LastImageName = name; - m_pLastImage = pObj->GetImage(); - if (!m_pObjectHolder->HasImageMask()) - m_pObjectHolder->SetHasImageMask(m_pLastImage->IsMask()); + if (pObj) { + m_pLastImage = pObj->GetImage(); + if (m_pLastImage->IsMask()) + m_pObjectHolder->AddImageMaskBoundingBox(pObj->GetRect()); + } } else if (type == "Form") { AddForm(pXObject); } } void CPDF_StreamContentParser::AddForm(CPDF_Stream* pStream) { - std::unique_ptr pFormObj(new CPDF_FormObject); - pFormObj->m_pForm.reset( - new CPDF_Form(m_pDocument, m_pPageResources, pStream, m_pResources)); - pFormObj->m_FormMatrix = m_pCurStates->m_CTM; - pFormObj->m_FormMatrix.Concat(m_mtContentToUser); CPDF_AllStates status; status.m_GeneralState = m_pCurStates->m_GeneralState; status.m_GraphState = m_pCurStates->m_GraphState; status.m_ColorState = m_pCurStates->m_ColorState; status.m_TextState = m_pCurStates->m_TextState; - pFormObj->m_pForm->ParseContent(&status, nullptr, nullptr, m_Level + 1); + auto form = pdfium::MakeUnique( + m_pDocument.Get(), m_pPageResources.Get(), pStream, m_pResources.Get()); + form->ParseContentWithParams(&status, nullptr, nullptr, m_ParsedSet.Get()); + + CFX_Matrix matrix = m_pCurStates->m_CTM; + matrix.Concat(m_mtContentToUser); + + auto pFormObj = pdfium::MakeUnique(std::move(form), matrix); if (!m_pObjectHolder->BackgroundAlphaNeeded() && - pFormObj->m_pForm->BackgroundAlphaNeeded()) { + pFormObj->form()->BackgroundAlphaNeeded()) { m_pObjectHolder->SetBackgroundAlphaNeeded(true); } pFormObj->CalcBoundingBox(); @@ -795,23 +793,24 @@ CPDF_ImageObject* CPDF_StreamContentParser::AddImage( return nullptr; auto pImageObj = pdfium::MakeUnique(); - pImageObj->SetOwnedImage( - pdfium::MakeUnique(m_pDocument, std::move(pStream))); + pImageObj->SetImage( + pdfium::MakeRetain(m_pDocument.Get(), std::move(pStream))); return AddImageObject(std::move(pImageObj)); } CPDF_ImageObject* CPDF_StreamContentParser::AddImage(uint32_t streamObjNum) { auto pImageObj = pdfium::MakeUnique(); - pImageObj->SetUnownedImage(m_pDocument->LoadImageFromPageData(streamObjNum)); + pImageObj->SetImage(m_pDocument->LoadImageFromPageData(streamObjNum)); return AddImageObject(std::move(pImageObj)); } -CPDF_ImageObject* CPDF_StreamContentParser::AddImage(CPDF_Image* pImage) { +CPDF_ImageObject* CPDF_StreamContentParser::AddImage( + const RetainPtr& pImage) { if (!pImage) return nullptr; auto pImageObj = pdfium::MakeUnique(); - pImageObj->SetUnownedImage( + pImageObj->SetImage( m_pDocument->GetPageData()->GetImage(pImage->GetStream()->GetObjNum())); return AddImageObject(std::move(pImageObj)); @@ -837,7 +836,7 @@ void CPDF_StreamContentParser::Handle_MarkPlace_Dictionary() {} void CPDF_StreamContentParser::Handle_EndImage() {} void CPDF_StreamContentParser::Handle_EndMarkedContent() { - if (m_CurContentMark) + if (m_CurContentMark.HasRef()) m_CurContentMark.DeleteLastMark(); } @@ -864,19 +863,19 @@ void CPDF_StreamContentParser::Handle_EOFillPath() { } void CPDF_StreamContentParser::Handle_SetGray_Fill() { - FX_FLOAT value = GetNumber(0); + float value = GetNumber(0); CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); m_pCurStates->m_ColorState.SetFillColor(pCS, &value, 1); } void CPDF_StreamContentParser::Handle_SetGray_Stroke() { - FX_FLOAT value = GetNumber(0); + float value = GetNumber(0); CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); m_pCurStates->m_ColorState.SetStrokeColor(pCS, &value, 1); } void CPDF_StreamContentParser::Handle_SetExtendGraphState() { - CFX_ByteString name = GetString(0); + ByteString name = GetString(0); CPDF_Dictionary* pGS = ToDictionary(FindResourceObj("ExtGState", name)); if (!pGS) { m_bResourceMissing = true; @@ -886,14 +885,13 @@ void CPDF_StreamContentParser::Handle_SetExtendGraphState() { } void CPDF_StreamContentParser::Handle_ClosePath() { - if (m_PathPointCount == 0) { + if (m_PathPoints.empty()) return; - } - if (m_PathStartX != m_PathCurrentX || m_PathStartY != m_PathCurrentY) { + + if (m_PathStartX != m_PathCurrentX || m_PathStartY != m_PathCurrentY) AddPathPoint(m_PathStartX, m_PathStartY, FXPT_TYPE::LineTo, true); - } else if (m_pPathPoints[m_PathPointCount - 1].m_Type != FXPT_TYPE::MoveTo) { - m_pPathPoints[m_PathPointCount - 1].m_CloseFigure = true; - } + else if (m_PathPoints.back().m_Type != FXPT_TYPE::MoveTo) + m_PathPoints.back().m_CloseFigure = true; } void CPDF_StreamContentParser::Handle_SetFlat() { @@ -916,7 +914,7 @@ void CPDF_StreamContentParser::Handle_SetCMYKColor_Fill() { if (m_ParamCount != 4) return; - FX_FLOAT values[4]; + float values[4]; for (int i = 0; i < 4; i++) { values[i] = GetNumber(3 - i); } @@ -928,7 +926,7 @@ void CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke() { if (m_ParamCount != 4) return; - FX_FLOAT values[4]; + float values[4]; for (int i = 0; i < 4; i++) { values[i] = GetNumber(3 - i); } @@ -962,7 +960,7 @@ void CPDF_StreamContentParser::Handle_EndPath() { } void CPDF_StreamContentParser::Handle_SaveGraphState() { - std::unique_ptr pStates(new CPDF_AllStates); + auto pStates = pdfium::MakeUnique(); pStates->Copy(*m_pCurStates); m_StateStack.push_back(std::move(pStates)); } @@ -976,15 +974,12 @@ void CPDF_StreamContentParser::Handle_RestoreGraphState() { } void CPDF_StreamContentParser::Handle_Rectangle() { - FX_FLOAT x = GetNumber(3), y = GetNumber(2); - FX_FLOAT w = GetNumber(1), h = GetNumber(0); + float x = GetNumber(3), y = GetNumber(2); + float w = GetNumber(1), h = GetNumber(0); AddPathRect(x, y, w, h); } -void CPDF_StreamContentParser::AddPathRect(FX_FLOAT x, - FX_FLOAT y, - FX_FLOAT w, - FX_FLOAT h) { +void CPDF_StreamContentParser::AddPathRect(float x, float y, float w, float h) { AddPathPoint(x, y, FXPT_TYPE::MoveTo, false); AddPathPoint(x + w, y, FXPT_TYPE::LineTo, false); AddPathPoint(x + w, y + h, FXPT_TYPE::LineTo, false); @@ -996,7 +991,7 @@ void CPDF_StreamContentParser::Handle_SetRGBColor_Fill() { if (m_ParamCount != 3) return; - FX_FLOAT values[3]; + float values[3]; for (int i = 0; i < 3; i++) { values[i] = GetNumber(2 - i); } @@ -1008,7 +1003,7 @@ void CPDF_StreamContentParser::Handle_SetRGBColor_Stroke() { if (m_ParamCount != 3) return; - FX_FLOAT values[3]; + float values[3]; for (int i = 0; i < 3; i++) { values[i] = GetNumber(2 - i); } @@ -1028,7 +1023,7 @@ void CPDF_StreamContentParser::Handle_StrokePath() { } void CPDF_StreamContentParser::Handle_SetColor_Fill() { - FX_FLOAT values[4]; + float values[4]; int nargs = m_ParamCount; if (nargs > 4) { nargs = 4; @@ -1040,7 +1035,7 @@ void CPDF_StreamContentParser::Handle_SetColor_Fill() { } void CPDF_StreamContentParser::Handle_SetColor_Stroke() { - FX_FLOAT values[4]; + float values[4]; int nargs = m_ParamCount; if (nargs > 4) { nargs = 4; @@ -1060,9 +1055,9 @@ void CPDF_StreamContentParser::Handle_SetColorPS_Fill() { uint32_t nvalues = nargs; if (pLastParam->IsName()) nvalues--; - FX_FLOAT* values = nullptr; + float* values = nullptr; if (nvalues) { - values = FX_Alloc(FX_FLOAT, nvalues); + values = FX_Alloc(float, nvalues); for (uint32_t i = 0; i < nvalues; i++) { values[i] = GetNumber(nargs - i - 1); } @@ -1088,9 +1083,9 @@ void CPDF_StreamContentParser::Handle_SetColorPS_Stroke() { if (pLastParam->IsName()) nvalues--; - FX_FLOAT* values = nullptr; + float* values = nullptr; if (nvalues) { - values = FX_Alloc(FX_FLOAT, nvalues); + values = FX_Alloc(float, nvalues); for (int i = 0; i < nvalues; i++) { values[i] = GetNumber(nargs - i - 1); } @@ -1118,15 +1113,14 @@ void CPDF_StreamContentParser::Handle_ShadeFill() { if (!pShading->IsShadingObject() || !pShading->Load()) return; - std::unique_ptr pObj(new CPDF_ShadingObject); - pObj->m_pShading = pShading; + CFX_Matrix matrix = m_pCurStates->m_CTM; + matrix.Concat(m_mtContentToUser); + auto pObj = pdfium::MakeUnique(pShading, matrix); SetGraphicStates(pObj.get(), false, false, false); - pObj->m_Matrix = m_pCurStates->m_CTM; - pObj->m_Matrix.Concat(m_mtContentToUser); CFX_FloatRect bbox = - pObj->m_ClipPath ? pObj->m_ClipPath.GetClipBox() : m_BBox; + pObj->m_ClipPath.HasRef() ? pObj->m_ClipPath.GetClipBox() : m_BBox; if (pShading->IsMeshShading()) - bbox.Intersect(GetShadingBBox(pShading, pObj->m_Matrix)); + bbox.Intersect(GetShadingBBox(pShading, pObj->matrix())); pObj->m_Left = bbox.left; pObj->m_Right = bbox.right; pObj->m_Top = bbox.top; @@ -1149,7 +1143,7 @@ void CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading() { } void CPDF_StreamContentParser::Handle_SetFont() { - FX_FLOAT fs = GetNumber(0); + float fs = GetNumber(0); if (fs == 0) { fs = m_DefFontSize; } @@ -1160,9 +1154,8 @@ void CPDF_StreamContentParser::Handle_SetFont() { } } -CPDF_Object* CPDF_StreamContentParser::FindResourceObj( - const CFX_ByteString& type, - const CFX_ByteString& name) { +CPDF_Object* CPDF_StreamContentParser::FindResourceObj(const ByteString& type, + const ByteString& name) { if (!m_pResources) return nullptr; CPDF_Dictionary* pDict = m_pResources->GetDictFor(type); @@ -1175,29 +1168,29 @@ CPDF_Object* CPDF_StreamContentParser::FindResourceObj( return pPageDict ? pPageDict->GetDirectObjectFor(name) : nullptr; } -CPDF_Font* CPDF_StreamContentParser::FindFont(const CFX_ByteString& name) { +CPDF_Font* CPDF_StreamContentParser::FindFont(const ByteString& name) { CPDF_Dictionary* pFontDict = ToDictionary(FindResourceObj("Font", name)); if (!pFontDict) { m_bResourceMissing = true; - return CPDF_Font::GetStockFont(m_pDocument, "Helvetica"); + return CPDF_Font::GetStockFont(m_pDocument.Get(), "Helvetica"); } CPDF_Font* pFont = m_pDocument->LoadFont(pFontDict); if (pFont && pFont->IsType3Font()) { - pFont->AsType3Font()->SetPageResources(m_pResources); + pFont->AsType3Font()->SetPageResources(m_pResources.Get()); pFont->AsType3Font()->CheckType3FontMetrics(); } return pFont; } CPDF_ColorSpace* CPDF_StreamContentParser::FindColorSpace( - const CFX_ByteString& name) { + const ByteString& name) { if (name == "Pattern") { return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN); } if (name == "DeviceGray" || name == "DeviceCMYK" || name == "DeviceRGB") { - CFX_ByteString defname = "Default"; - defname += name.Mid(7); + ByteString defname = "Default"; + defname += name.Right(name.GetLength() - 7); CPDF_Object* pDefObj = FindResourceObj("ColorSpace", defname); if (!pDefObj) { if (name == "DeviceGray") { @@ -1218,7 +1211,7 @@ CPDF_ColorSpace* CPDF_StreamContentParser::FindColorSpace( return m_pDocument->LoadColorSpace(pCSObj); } -CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const CFX_ByteString& name, +CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const ByteString& name, bool bShading) { CPDF_Object* pPattern = FindResourceObj(bShading ? "Shading" : "Pattern", name); @@ -1230,9 +1223,9 @@ CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const CFX_ByteString& name, m_pCurStates->m_ParentMatrix); } -void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs, - FX_FLOAT fInitKerning, - FX_FLOAT* pKerning, +void CPDF_StreamContentParser::AddTextObject(ByteString* pStrs, + float fInitKerning, + float* pKerning, int nsegs) { CPDF_Font* pFont = m_pCurStates->m_TextState.GetFont(); if (!pFont) { @@ -1256,21 +1249,22 @@ void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs, pFont->IsType3Font() ? TextRenderingMode::MODE_FILL : m_pCurStates->m_TextState.GetTextMode(); { - std::unique_ptr pText(new CPDF_TextObject); + auto pText = pdfium::MakeUnique(); m_pLastTextObject = pText.get(); - SetGraphicStates(m_pLastTextObject, true, true, true); + SetGraphicStates(m_pLastTextObject.Get(), true, true, true); if (TextRenderingModeIsStrokeMode(text_mode)) { - FX_FLOAT* pCTM = pText->m_TextState.GetMutableCTM(); + float* pCTM = pText->m_TextState.GetMutableCTM(); pCTM[0] = m_pCurStates->m_CTM.a; pCTM[1] = m_pCurStates->m_CTM.c; pCTM[2] = m_pCurStates->m_CTM.b; pCTM[3] = m_pCurStates->m_CTM.d; } pText->SetSegments(pStrs, pKerning, nsegs); - pText->m_Pos = m_mtContentToUser.Transform( - m_pCurStates->m_CTM.Transform(m_pCurStates->m_TextMatrix.Transform( - CFX_PointF(m_pCurStates->m_TextPos.x, - m_pCurStates->m_TextPos.y + m_pCurStates->m_TextRise)))); + pText->SetPosition( + m_mtContentToUser.Transform(m_pCurStates->m_CTM.Transform( + m_pCurStates->m_TextMatrix.Transform(CFX_PointF( + m_pCurStates->m_TextPos.x, + m_pCurStates->m_TextPos.y + m_pCurStates->m_TextRise))))); m_pCurStates->m_TextPos += pText->CalcPositionData(m_pCurStates->m_TextHorzScale); @@ -1295,7 +1289,7 @@ void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs, } void CPDF_StreamContentParser::Handle_ShowText() { - CFX_ByteString str = GetString(0); + ByteString str = GetString(0); if (str.IsEmpty()) { return; } @@ -1322,31 +1316,27 @@ void CPDF_StreamContentParser::Handle_ShowText_Positioning() { } return; } - CFX_ByteString* pStrs = new CFX_ByteString[nsegs]; - FX_FLOAT* pKerning = FX_Alloc(FX_FLOAT, nsegs); + std::vector strs(nsegs); + std::vector kernings(nsegs); size_t iSegment = 0; - FX_FLOAT fInitKerning = 0; + float fInitKerning = 0; for (size_t i = 0; i < n; i++) { CPDF_Object* pObj = pArray->GetDirectObjectAt(i); if (pObj->IsString()) { - CFX_ByteString str = pObj->GetString(); - if (str.IsEmpty()) { + ByteString str = pObj->GetString(); + if (str.IsEmpty()) continue; - } - pStrs[iSegment] = str; - pKerning[iSegment++] = 0; + strs[iSegment] = str; + kernings[iSegment++] = 0; } else { - FX_FLOAT num = pObj ? pObj->GetNumber() : 0; - if (iSegment == 0) { + float num = pObj->GetNumber(); + if (iSegment == 0) fInitKerning += num; - } else { - pKerning[iSegment - 1] += num; - } + else + kernings[iSegment - 1] += num; } } - AddTextObject(pStrs, fInitKerning, pKerning, iSegment); - delete[] pStrs; - FX_Free(pKerning); + AddTextObject(strs.data(), fInitKerning, kernings.data(), iSegment); } void CPDF_StreamContentParser::Handle_SetTextLeading() { @@ -1368,7 +1358,7 @@ void CPDF_StreamContentParser::OnChangeTextMatrix() { text_matrix.Concat(m_pCurStates->m_TextMatrix); text_matrix.Concat(m_pCurStates->m_CTM); text_matrix.Concat(m_mtContentToUser); - FX_FLOAT* pTextMatrix = m_pCurStates->m_TextState.GetMutableMatrix(); + float* pTextMatrix = m_pCurStates->m_TextState.GetMutableMatrix(); pTextMatrix[0] = text_matrix.a; pTextMatrix[1] = text_matrix.c; pTextMatrix[2] = text_matrix.b; @@ -1439,68 +1429,64 @@ void CPDF_StreamContentParser::Handle_NextLineShowText_Space() { void CPDF_StreamContentParser::Handle_Invalid() {} -void CPDF_StreamContentParser::AddPathPoint(FX_FLOAT x, - FX_FLOAT y, +void CPDF_StreamContentParser::AddPathPoint(float x, + float y, FXPT_TYPE type, bool close) { + // If the path point is the same move as the previous one and neither of them + // closes the path, then just skip it. + if (!close && type == FXPT_TYPE::MoveTo && !m_PathPoints.empty() && + !m_PathPoints.back().m_CloseFigure && + m_PathPoints.back().m_Type == type && m_PathCurrentX == x && + m_PathCurrentY == y) { + return; + } + m_PathCurrentX = x; m_PathCurrentY = y; if (type == FXPT_TYPE::MoveTo && !close) { m_PathStartX = x; m_PathStartY = y; - if (m_PathPointCount && - m_pPathPoints[m_PathPointCount - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { - m_pPathPoints[m_PathPointCount - 1].m_Point = CFX_PointF(x, y); + if (!m_PathPoints.empty() && + m_PathPoints.back().IsTypeAndOpen(FXPT_TYPE::MoveTo)) { + m_PathPoints.back().m_Point = CFX_PointF(x, y); return; } - } else if (m_PathPointCount == 0) { + } else if (m_PathPoints.empty()) { return; } - m_PathPointCount++; - if (m_PathPointCount > m_PathAllocSize) { - int newsize = m_PathPointCount + 256; - FX_PATHPOINT* pNewPoints = FX_Alloc(FX_PATHPOINT, newsize); - if (m_PathAllocSize) { - FXSYS_memcpy(pNewPoints, m_pPathPoints, - m_PathAllocSize * sizeof(FX_PATHPOINT)); - FX_Free(m_pPathPoints); - } - m_pPathPoints = pNewPoints; - m_PathAllocSize = newsize; - } - m_pPathPoints[m_PathPointCount - 1].m_Type = type; - m_pPathPoints[m_PathPointCount - 1].m_CloseFigure = close; - m_pPathPoints[m_PathPointCount - 1].m_Point = CFX_PointF(x, y); + m_PathPoints.push_back(FX_PATHPOINT(CFX_PointF(x, y), type, close)); } void CPDF_StreamContentParser::AddPathObject(int FillType, bool bStroke) { - int PathPointCount = m_PathPointCount; + std::vector PathPoints; + PathPoints.swap(m_PathPoints); uint8_t PathClipType = m_PathClipType; - m_PathPointCount = 0; m_PathClipType = 0; - if (PathPointCount <= 1) { - if (PathPointCount && PathClipType) { + + if (PathPoints.empty()) + return; + + if (PathPoints.size() == 1) { + if (PathClipType) { CPDF_Path path; path.AppendRect(0, 0, 0, 0); m_pCurStates->m_ClipPath.AppendPath(path, FXFILL_WINDING, true); } return; } - if (PathPointCount && - m_pPathPoints[PathPointCount - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { - PathPointCount--; - } + + if (PathPoints.back().IsTypeAndOpen(FXPT_TYPE::MoveTo)) + PathPoints.pop_back(); CPDF_Path Path; - for (int i = 0; i < PathPointCount; i++) { - FX_PATHPOINT& point = m_pPathPoints[i]; + for (const auto& point : PathPoints) Path.AppendPoint(point.m_Point, point.m_Type, point.m_CloseFigure); - } CFX_Matrix matrix = m_pCurStates->m_CTM; matrix.Concat(m_mtContentToUser); if (bStroke || FillType) { - std::unique_ptr pPathObj(new CPDF_PathObject); + auto pPathObj = pdfium::MakeUnique(); pPathObj->m_bStroke = bStroke; pPathObj->m_FillType = FillType; pPathObj->m_Path = Path; @@ -1521,9 +1507,13 @@ void CPDF_StreamContentParser::AddPathObject(int FillType, bool bStroke) { uint32_t CPDF_StreamContentParser::Parse(const uint8_t* pData, uint32_t dwSize, uint32_t max_cost) { - if (m_Level > kMaxFormLevel) + if (m_ParsedSet->size() > kMaxFormLevel || + pdfium::ContainsKey(*m_ParsedSet, pData)) return dwSize; + pdfium::ScopedSetInsertion scopedInsert(m_ParsedSet.Get(), + pData); + uint32_t InitObjCount = m_pObjectHolder->GetPageObjectList()->size(); CPDF_StreamParser syntax(pData, dwSize, m_pDocument->GetByteStringPool()); CPDF_StreamParserAutoClearer auto_clearer(&m_pSyntax, &syntax); @@ -1542,9 +1532,11 @@ uint32_t CPDF_StreamContentParser::Parse(const uint8_t* pData, case CPDF_StreamParser::Number: AddNumberParam(syntax.GetWord()); break; - case CPDF_StreamParser::Name: - AddNameParam(syntax.GetWord().Mid(1)); + case CPDF_StreamParser::Name: { + auto word = syntax.GetWord(); + AddNameParam(word.Right(word.GetLength() - 1)); break; + } default: AddObjectParam(syntax.GetObject()); } @@ -1553,7 +1545,7 @@ uint32_t CPDF_StreamContentParser::Parse(const uint8_t* pData, } void CPDF_StreamContentParser::ParsePathObject() { - FX_FLOAT params[6] = {}; + float params[6] = {}; int nParams = 0; int last_pos = m_pSyntax->GetPos(); while (1) { @@ -1563,7 +1555,7 @@ void CPDF_StreamContentParser::ParsePathObject() { case CPDF_StreamParser::EndOfData: return; case CPDF_StreamParser::Keyword: { - CFX_ByteStringC strc = m_pSyntax->GetWord(); + ByteStringView strc = m_pSyntax->GetWord(); int len = strc.GetLength(); if (len == 1) { switch (strc[0]) { @@ -1624,7 +1616,8 @@ void CPDF_StreamContentParser::ParsePathObject() { int value; bool bInteger = FX_atonum(m_pSyntax->GetWord(), &value); - params[nParams++] = bInteger ? (FX_FLOAT)value : *(FX_FLOAT*)&value; + params[nParams++] = bInteger ? static_cast(value) + : *reinterpret_cast(&value); break; } default: @@ -1637,6 +1630,18 @@ void CPDF_StreamContentParser::ParsePathObject() { } } +// static +ByteStringView CPDF_StreamContentParser::FindKeyAbbreviationForTesting( + const ByteStringView& abbr) { + return FindFullName(InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), abbr); +} + +// static +ByteStringView CPDF_StreamContentParser::FindValueAbbreviationForTesting( + const ByteStringView& abbr) { + return FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr), abbr); +} + CPDF_StreamContentParser::ContentParam::ContentParam() {} CPDF_StreamContentParser::ContentParam::~ContentParam() {} diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.h b/core/fpdfapi/page/cpdf_streamcontentparser.h index cd41990b0a7222e1e27bba66e194eed5ffb138db..de4a92fc99528098bfd4f1488bb3c2405e8bdce8 100644 --- a/core/fpdfapi/page/cpdf_streamcontentparser.h +++ b/core/fpdfapi/page/cpdf_streamcontentparser.h @@ -7,8 +7,9 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_STREAMCONTENTPARSER_H_ #define CORE_FPDFAPI_PAGE_CPDF_STREAMCONTENTPARSER_H_ +#include #include -#include +#include #include #include "core/fpdfapi/page/cpdf_contentmark.h" @@ -37,17 +38,24 @@ class CPDF_StreamContentParser { const CFX_Matrix* pmtContentToUser, CPDF_PageObjectHolder* pObjectHolder, CPDF_Dictionary* pResources, - CFX_FloatRect* pBBox, + const CFX_FloatRect& rcBBox, CPDF_AllStates* pAllStates, - int level); + std::set* parsedSet); ~CPDF_StreamContentParser(); uint32_t Parse(const uint8_t* pData, uint32_t dwSize, uint32_t max_cost); - CPDF_PageObjectHolder* GetPageObjectHolder() const { return m_pObjectHolder; } + CPDF_PageObjectHolder* GetPageObjectHolder() const { + return m_pObjectHolder.Get(); + } CPDF_AllStates* GetCurStates() const { return m_pCurStates.get(); } bool IsColored() const { return m_bColored; } - const FX_FLOAT* GetType3Data() const { return m_Type3Data; } - CPDF_Font* FindFont(const CFX_ByteString& name); + const float* GetType3Data() const { return m_Type3Data; } + CPDF_Font* FindFont(const ByteString& name); + + static ByteStringView FindKeyAbbreviationForTesting( + const ByteStringView& abbr); + static ByteStringView FindValueAbbreviationForTesting( + const ByteStringView& abbr); private: struct ContentParam { @@ -62,7 +70,7 @@ class CPDF_StreamContentParser { bool m_bInteger; union { int m_Integer; - FX_FLOAT m_Float; + float m_Float; }; } m_Number; struct { @@ -73,43 +81,41 @@ class CPDF_StreamContentParser { static const int kParamBufSize = 16; - using OpCodes = - std::unordered_map; + using OpCodes = std::map; static OpCodes InitializeOpCodes(); - void AddNameParam(const CFX_ByteStringC& str); - void AddNumberParam(const CFX_ByteStringC& str); + void AddNameParam(const ByteStringView& str); + void AddNumberParam(const ByteStringView& str); void AddObjectParam(std::unique_ptr pObj); int GetNextParamPos(); void ClearAllParams(); CPDF_Object* GetObject(uint32_t index); - CFX_ByteString GetString(uint32_t index); - FX_FLOAT GetNumber(uint32_t index); + ByteString GetString(uint32_t index); + float GetNumber(uint32_t index); int GetInteger(uint32_t index) { return (int32_t)(GetNumber(index)); } - void OnOperator(const CFX_ByteStringC& op); - void AddTextObject(CFX_ByteString* pText, - FX_FLOAT fInitKerning, - FX_FLOAT* pKerning, + void OnOperator(const ByteStringView& op); + void AddTextObject(ByteString* pText, + float fInitKerning, + float* pKerning, int count); void OnChangeTextMatrix(); void ParsePathObject(); - void AddPathPoint(FX_FLOAT x, FX_FLOAT y, FXPT_TYPE type, bool close); - void AddPathRect(FX_FLOAT x, FX_FLOAT y, FX_FLOAT w, FX_FLOAT h); + void AddPathPoint(float x, float y, FXPT_TYPE type, bool close); + void AddPathRect(float x, float y, float w, float h); void AddPathObject(int FillType, bool bStroke); CPDF_ImageObject* AddImage(std::unique_ptr pStream); CPDF_ImageObject* AddImage(uint32_t streamObjNum); - CPDF_ImageObject* AddImage(CPDF_Image* pImage); + CPDF_ImageObject* AddImage(const RetainPtr& pImage); void AddForm(CPDF_Stream* pStream); void SetGraphicStates(CPDF_PageObject* pObj, bool bColor, bool bText, bool bGraph); - CPDF_ColorSpace* FindColorSpace(const CFX_ByteString& name); - CPDF_Pattern* FindPattern(const CFX_ByteString& name, bool bShading); - CPDF_Object* FindResourceObj(const CFX_ByteString& type, - const CFX_ByteString& name); + CPDF_ColorSpace* FindColorSpace(const ByteString& name); + CPDF_Pattern* FindPattern(const ByteString& name, bool bShading); + CPDF_Object* FindResourceObj(const ByteString& type, const ByteString& name); // Takes ownership of |pImageObj|, returns unowned pointer to it. CPDF_ImageObject* AddImageObject(std::unique_ptr pImageObj); @@ -187,14 +193,14 @@ class CPDF_StreamContentParser { void Handle_NextLineShowText_Space(); void Handle_Invalid(); - CPDF_Document* const m_pDocument; - CPDF_Dictionary* m_pPageResources; - CPDF_Dictionary* m_pParentResources; - CPDF_Dictionary* m_pResources; - CPDF_PageObjectHolder* m_pObjectHolder; - int m_Level; + UnownedPtr const m_pDocument; + UnownedPtr const m_pPageResources; + UnownedPtr const m_pParentResources; + UnownedPtr m_pResources; + UnownedPtr const m_pObjectHolder; + UnownedPtr> const m_ParsedSet; CFX_Matrix m_mtContentToUser; - CFX_FloatRect m_BBox; + const CFX_FloatRect m_BBox; ContentParam m_ParamBuf[kParamBufSize]; uint32_t m_ParamStartPos; uint32_t m_ParamCount; @@ -202,20 +208,18 @@ class CPDF_StreamContentParser { std::unique_ptr m_pCurStates; CPDF_ContentMark m_CurContentMark; std::vector> m_ClipTextList; - CPDF_TextObject* m_pLastTextObject; - FX_FLOAT m_DefFontSize; - FX_PATHPOINT* m_pPathPoints; - int m_PathPointCount; - int m_PathAllocSize; - FX_FLOAT m_PathStartX; - FX_FLOAT m_PathStartY; - FX_FLOAT m_PathCurrentX; - FX_FLOAT m_PathCurrentY; + UnownedPtr m_pLastTextObject; + float m_DefFontSize; + std::vector m_PathPoints; + float m_PathStartX; + float m_PathStartY; + float m_PathCurrentX; + float m_PathCurrentY; uint8_t m_PathClipType; - CFX_ByteString m_LastImageName; - CPDF_Image* m_pLastImage; + ByteString m_LastImageName; + RetainPtr m_pLastImage; bool m_bColored; - FX_FLOAT m_Type3Data[6]; + float m_Type3Data[6]; bool m_bResourceMissing; std::vector> m_StateStack; }; diff --git a/core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp b/core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp index be2fcb09e430d92537d50f49a49a4ee355f6b91d..0f4fc1e87a8d8f0040209c1a88041ecf368fb362 100644 --- a/core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp +++ b/core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp @@ -2,33 +2,43 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "core/fpdfapi/page/pageint.h" +#include "core/fpdfapi/page/cpdf_streamcontentparser.h" #include "testing/gtest/include/gtest/gtest.h" TEST(cpdf_streamcontentparser, PDF_FindKeyAbbreviation) { - EXPECT_EQ(CFX_ByteStringC("BitsPerComponent"), - PDF_FindKeyAbbreviationForTesting(CFX_ByteStringC("BPC"))); - EXPECT_EQ(CFX_ByteStringC("Width"), - PDF_FindKeyAbbreviationForTesting(CFX_ByteStringC("W"))); - EXPECT_EQ(CFX_ByteStringC(""), - PDF_FindKeyAbbreviationForTesting(CFX_ByteStringC(""))); - EXPECT_EQ(CFX_ByteStringC(""), - PDF_FindKeyAbbreviationForTesting(CFX_ByteStringC("NoInList"))); + EXPECT_EQ(ByteStringView("BitsPerComponent"), + CPDF_StreamContentParser::FindKeyAbbreviationForTesting( + ByteStringView("BPC"))); + EXPECT_EQ(ByteStringView("Width"), + CPDF_StreamContentParser::FindKeyAbbreviationForTesting( + ByteStringView("W"))); + EXPECT_EQ(ByteStringView(""), + CPDF_StreamContentParser::FindKeyAbbreviationForTesting( + ByteStringView(""))); + EXPECT_EQ(ByteStringView(""), + CPDF_StreamContentParser::FindKeyAbbreviationForTesting( + ByteStringView("NoInList"))); // Prefix should not match. - EXPECT_EQ(CFX_ByteStringC(""), - PDF_FindKeyAbbreviationForTesting(CFX_ByteStringC("WW"))); + EXPECT_EQ(ByteStringView(""), + CPDF_StreamContentParser::FindKeyAbbreviationForTesting( + ByteStringView("WW"))); } TEST(cpdf_streamcontentparser, PDF_FindValueAbbreviation) { - EXPECT_EQ(CFX_ByteStringC("DeviceGray"), - PDF_FindValueAbbreviationForTesting(CFX_ByteStringC("G"))); - EXPECT_EQ(CFX_ByteStringC("DCTDecode"), - PDF_FindValueAbbreviationForTesting(CFX_ByteStringC("DCT"))); - EXPECT_EQ(CFX_ByteStringC(""), - PDF_FindValueAbbreviationForTesting(CFX_ByteStringC(""))); - EXPECT_EQ(CFX_ByteStringC(""), - PDF_FindValueAbbreviationForTesting(CFX_ByteStringC("NoInList"))); + EXPECT_EQ(ByteStringView("DeviceGray"), + CPDF_StreamContentParser::FindValueAbbreviationForTesting( + ByteStringView("G"))); + EXPECT_EQ(ByteStringView("DCTDecode"), + CPDF_StreamContentParser::FindValueAbbreviationForTesting( + ByteStringView("DCT"))); + EXPECT_EQ(ByteStringView(""), + CPDF_StreamContentParser::FindValueAbbreviationForTesting( + ByteStringView(""))); + EXPECT_EQ(ByteStringView(""), + CPDF_StreamContentParser::FindValueAbbreviationForTesting( + ByteStringView("NoInList"))); // Prefix should not match. - EXPECT_EQ(CFX_ByteStringC(""), - PDF_FindValueAbbreviationForTesting(CFX_ByteStringC("II"))); + EXPECT_EQ(ByteStringView(""), + CPDF_StreamContentParser::FindValueAbbreviationForTesting( + ByteStringView("II"))); } diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp index 294d72c9506f1157bab725397e37eaea464ba5f9..2c7e0256f53fbf9c2d525206ee083d4cdbeb283f 100644 --- a/core/fpdfapi/page/cpdf_streamparser.cpp +++ b/core/fpdfapi/page/cpdf_streamparser.cpp @@ -8,7 +8,9 @@ #include +#include #include +#include #include #include "core/fpdfapi/cpdf_modulemgr.h" @@ -24,18 +26,19 @@ #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfapi/parser/fpdf_parser_utility.h" -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" +#include "core/fxcrt/fx_extension.h" namespace { const uint32_t kMaxNestedParsingLevel = 512; const uint32_t kMaxWordBuffer = 256; -const FX_STRSIZE kMaxStringLength = 32767; +const size_t kMaxStringLength = 32767; uint32_t DecodeAllScanlines(std::unique_ptr pDecoder, - uint8_t*& dest_buf, - uint32_t& dest_size) { + uint8_t** dest_buf, + uint32_t* dest_size) { if (!pDecoder) return FX_INVALID_OFFSET; int ncomps = pDecoder->CountComps(); @@ -46,26 +49,26 @@ uint32_t DecodeAllScanlines(std::unique_ptr pDecoder, if (height == 0 || pitch > (1 << 30) / height) return FX_INVALID_OFFSET; - dest_buf = FX_Alloc2D(uint8_t, pitch, height); - dest_size = pitch * height; // Safe since checked alloc returned. - for (int row = 0; row < height; row++) { + *dest_buf = FX_Alloc2D(uint8_t, pitch, height); + *dest_size = pitch * height; // Safe since checked alloc returned. + for (int row = 0; row < height; ++row) { const uint8_t* pLine = pDecoder->GetScanline(row); if (!pLine) break; - FXSYS_memcpy(dest_buf + row * pitch, pLine, pitch); + memcpy(*dest_buf + row * pitch, pLine, pitch); } return pDecoder->GetSrcOffset(); } -uint32_t PDF_DecodeInlineStream(const uint8_t* src_buf, - uint32_t limit, - int width, - int height, - CFX_ByteString& decoder, - CPDF_Dictionary* pParam, - uint8_t*& dest_buf, - uint32_t& dest_size) { +uint32_t DecodeInlineStream(const uint8_t* src_buf, + uint32_t limit, + int width, + int height, + const ByteString& decoder, + CPDF_Dictionary* pParam, + uint8_t** dest_buf, + uint32_t* dest_size) { if (decoder == "CCITTFaxDecode" || decoder == "CCF") { std::unique_ptr pDecoder = FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam); @@ -76,7 +79,7 @@ uint32_t PDF_DecodeInlineStream(const uint8_t* src_buf, if (decoder == "ASCIIHexDecode" || decoder == "AHx") return HexDecode(src_buf, limit, dest_buf, dest_size); if (decoder == "FlateDecode" || decoder == "Fl") { - return FPDFAPI_FlateOrLZWDecode(false, src_buf, limit, pParam, dest_size, + return FPDFAPI_FlateOrLZWDecode(false, src_buf, limit, pParam, *dest_size, dest_buf, dest_size); } if (decoder == "LZWDecode" || decoder == "LZW") { @@ -92,27 +95,20 @@ uint32_t PDF_DecodeInlineStream(const uint8_t* src_buf, } if (decoder == "RunLengthDecode" || decoder == "RL") return RunLengthDecode(src_buf, limit, dest_buf, dest_size); - dest_size = 0; - dest_buf = 0; - return (uint32_t)-1; + *dest_size = 0; + *dest_buf = 0; + return 0xFFFFFFFF; } } // namespace CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize) - : m_pBuf(pData), - m_Size(dwSize), - m_Pos(0), - m_pPool(nullptr) {} - -CPDF_StreamParser::CPDF_StreamParser( - const uint8_t* pData, - uint32_t dwSize, - const CFX_WeakPtr& pPool) - : m_pBuf(pData), - m_Size(dwSize), - m_Pos(0), - m_pPool(pPool) {} + : m_pBuf(pData), m_Size(dwSize), m_Pos(0), m_pPool(nullptr) {} + +CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, + uint32_t dwSize, + const WeakPtr& pPool) + : m_pBuf(pData), m_Size(dwSize), m_Pos(0), m_pPool(pPool) {} CPDF_StreamParser::~CPDF_StreamParser() {} @@ -126,7 +122,7 @@ std::unique_ptr CPDF_StreamParser::ReadInlineStream( if (PDFCharIsWhitespace(m_pBuf[m_Pos])) m_Pos++; - CFX_ByteString Decoder; + ByteString Decoder; CPDF_Dictionary* pParam = nullptr; CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter"); if (pFilter) { @@ -184,15 +180,15 @@ std::unique_ptr CPDF_StreamParser::ReadInlineStream( if (OrigSize > m_Size - m_Pos) OrigSize = m_Size - m_Pos; pData.reset(FX_Alloc(uint8_t, OrigSize)); - FXSYS_memcpy(pData.get(), m_pBuf + m_Pos, OrigSize); + memcpy(pData.get(), m_pBuf + m_Pos, OrigSize); dwStreamSize = OrigSize; m_Pos += OrigSize; } else { uint8_t* pIgnore = nullptr; uint32_t dwDestSize = OrigSize; dwStreamSize = - PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, - Decoder, pParam, pIgnore, dwDestSize); + DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, + Decoder, pParam, &pIgnore, &dwDestSize); FX_Free(pIgnore); if (static_cast(dwStreamSize) < 0) return nullptr; @@ -217,10 +213,10 @@ std::unique_ptr CPDF_StreamParser::ReadInlineStream( } m_Pos = dwSavePos; pData.reset(FX_Alloc(uint8_t, dwStreamSize)); - FXSYS_memcpy(pData.get(), m_pBuf + m_Pos, dwStreamSize); + memcpy(pData.get(), m_pBuf + m_Pos, dwStreamSize); m_Pos += dwStreamSize; } - pDict->SetNewFor("Length", (int)dwStreamSize); + pDict->SetNewFor("Length", static_cast(dwStreamSize)); return pdfium::MakeUnique(std::move(pData), dwStreamSize, std::move(pDict)); } @@ -316,18 +312,18 @@ std::unique_ptr CPDF_StreamParser::ReadNextObject( if (bIsNumber) { m_WordBuffer[m_WordSize] = 0; return pdfium::MakeUnique( - CFX_ByteStringC(m_WordBuffer, m_WordSize)); + ByteStringView(m_WordBuffer, m_WordSize)); } int first_char = m_WordBuffer[0]; if (first_char == '/') { - CFX_ByteString name = - PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)); + ByteString name = + PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1)); return pdfium::MakeUnique(m_pPool, name); } if (first_char == '(') { - CFX_ByteString str = ReadString(); + ByteString str = ReadString(); return pdfium::MakeUnique(m_pPool, str, false); } @@ -344,8 +340,8 @@ std::unique_ptr CPDF_StreamParser::ReadNextObject( if (!m_WordSize || m_WordBuffer[0] != '/') return nullptr; - CFX_ByteString key = - PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)); + ByteString key = + PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1)); std::unique_ptr pObj = ReadNextObject(true, bInArray, dwRecursionLevel + 1); if (!pObj) @@ -468,12 +464,12 @@ void CPDF_StreamParser::GetNextWord(bool& bIsNumber) { } } -CFX_ByteString CPDF_StreamParser::ReadString() { +ByteString CPDF_StreamParser::ReadString() { if (!PositionIsInBounds()) - return CFX_ByteString(); + return ByteString(); uint8_t ch = m_pBuf[m_Pos++]; - CFX_ByteTextBuf buf; + std::ostringstream buf; int parlevel = 0; int status = 0; int iEscCode = 0; @@ -482,54 +478,55 @@ CFX_ByteString CPDF_StreamParser::ReadString() { case 0: if (ch == ')') { if (parlevel == 0) { - if (buf.GetLength() > kMaxStringLength) { - return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); - } - return buf.MakeString(); + return ByteString( + buf.str().c_str(), + std::min(static_cast(buf.tellp()), kMaxStringLength)); } parlevel--; - buf.AppendChar(')'); + buf << ')'; } else if (ch == '(') { parlevel++; - buf.AppendChar('('); + buf << '('; } else if (ch == '\\') { status = 1; } else { - buf.AppendChar((char)ch); + buf << static_cast(ch); } break; case 1: if (ch >= '0' && ch <= '7') { - iEscCode = FXSYS_toDecimalDigit(static_cast(ch)); + iEscCode = FXSYS_DecimalCharToInt(static_cast(ch)); status = 2; break; } - if (ch == 'n') { - buf.AppendChar('\n'); + if (ch == '\r') { + status = 4; + break; + } + if (ch == '\n') { + // Do nothing. + } else if (ch == 'n') { + buf << '\n'; } else if (ch == 'r') { - buf.AppendChar('\r'); + buf << '\r'; } else if (ch == 't') { - buf.AppendChar('\t'); + buf << '\t'; } else if (ch == 'b') { - buf.AppendChar('\b'); + buf << '\b'; } else if (ch == 'f') { - buf.AppendChar('\f'); - } else if (ch == '\r') { - status = 4; - break; - } else if (ch == '\n') { + buf << '\f'; } else { - buf.AppendChar(ch); + buf << static_cast(ch); } status = 0; break; case 2: if (ch >= '0' && ch <= '7') { iEscCode = - iEscCode * 8 + FXSYS_toDecimalDigit(static_cast(ch)); + iEscCode * 8 + FXSYS_DecimalCharToInt(static_cast(ch)); status = 3; } else { - buf.AppendChar(iEscCode); + buf << static_cast(iEscCode); status = 0; continue; } @@ -537,20 +534,19 @@ CFX_ByteString CPDF_StreamParser::ReadString() { case 3: if (ch >= '0' && ch <= '7') { iEscCode = - iEscCode * 8 + FXSYS_toDecimalDigit(static_cast(ch)); - buf.AppendChar(iEscCode); + iEscCode * 8 + FXSYS_DecimalCharToInt(static_cast(ch)); + buf << static_cast(iEscCode); status = 0; } else { - buf.AppendChar(iEscCode); + buf << static_cast(iEscCode); status = 0; continue; } break; case 4: status = 0; - if (ch != '\n') { + if (ch != '\n') continue; - } break; } if (!PositionIsInBounds()) @@ -561,17 +557,16 @@ CFX_ByteString CPDF_StreamParser::ReadString() { if (PositionIsInBounds()) ++m_Pos; - if (buf.GetLength() > kMaxStringLength) { - return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); - } - return buf.MakeString(); + return ByteString( + buf.str().c_str(), + std::min(static_cast(buf.tellp()), kMaxStringLength)); } -CFX_ByteString CPDF_StreamParser::ReadHexString() { +ByteString CPDF_StreamParser::ReadHexString() { if (!PositionIsInBounds()) - return CFX_ByteString(); + return ByteString(); - CFX_ByteTextBuf buf; + std::ostringstream buf; bool bFirst = true; int code = 0; while (PositionIsInBounds()) { @@ -583,22 +578,21 @@ CFX_ByteString CPDF_StreamParser::ReadHexString() { if (!std::isxdigit(ch)) continue; - int val = FXSYS_toHexDigit(ch); + int val = FXSYS_HexCharToInt(ch); if (bFirst) { code = val * 16; } else { code += val; - buf.AppendByte((uint8_t)code); + buf << static_cast(code); } bFirst = !bFirst; } if (!bFirst) - buf.AppendChar((char)code); - - if (buf.GetLength() > kMaxStringLength) - return CFX_ByteString(buf.GetBuffer(), kMaxStringLength); + buf << static_cast(code); - return buf.MakeString(); + return ByteString( + buf.str().c_str(), + std::min(static_cast(buf.tellp()), kMaxStringLength)); } bool CPDF_StreamParser::PositionIsInBounds() const { diff --git a/core/fpdfapi/page/cpdf_streamparser.h b/core/fpdfapi/page/cpdf_streamparser.h index fdc418c634bd4628f65ae9dfdc9cdc6518bde48f..158726b026bb496b4ffb51bd7242a62c5b00fa64 100644 --- a/core/fpdfapi/page/cpdf_streamparser.h +++ b/core/fpdfapi/page/cpdf_streamparser.h @@ -14,8 +14,8 @@ #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_object.h" #include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" class CPDF_StreamParser { public: @@ -24,12 +24,12 @@ class CPDF_StreamParser { CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize); CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize, - const CFX_WeakPtr& pPool); + const WeakPtr& pPool); ~CPDF_StreamParser(); SyntaxType ParseNextElement(); - CFX_ByteStringC GetWord() const { - return CFX_ByteStringC(m_WordBuffer, m_WordSize); + ByteStringView GetWord() const { + return ByteStringView(m_WordBuffer, m_WordSize); } uint32_t GetPos() const { return m_Pos; } void SetPos(uint32_t pos) { m_Pos = pos; } @@ -46,8 +46,8 @@ class CPDF_StreamParser { friend class cpdf_streamparser_ReadHexString_Test; void GetNextWord(bool& bIsNumber); - CFX_ByteString ReadString(); - CFX_ByteString ReadHexString(); + ByteString ReadString(); + ByteString ReadHexString(); bool PositionIsInBounds() const; const uint8_t* m_pBuf; @@ -56,7 +56,7 @@ class CPDF_StreamParser { uint8_t m_WordBuffer[256]; uint32_t m_WordSize; std::unique_ptr m_pLastObj; - CFX_WeakPtr m_pPool; + WeakPtr m_pPool; }; #endif // CORE_FPDFAPI_PAGE_CPDF_STREAMPARSER_H_ diff --git a/core/fpdfapi/page/cpdf_textobject.cpp b/core/fpdfapi/page/cpdf_textobject.cpp index da69de8ce1a55b1abcaa7f5274a8a75de995bda0..0d60d50e2c8975bbdb9ce4224f0719cdabde51a8 100644 --- a/core/fpdfapi/page/cpdf_textobject.cpp +++ b/core/fpdfapi/page/cpdf_textobject.cpp @@ -7,6 +7,7 @@ #include "core/fpdfapi/page/cpdf_textobject.h" #include +#include #include "core/fpdfapi/font/cpdf_cidfont.h" #include "core/fpdfapi/font/cpdf_font.h" @@ -19,15 +20,20 @@ CPDF_TextObjectItem::~CPDF_TextObjectItem() = default; CPDF_TextObject::CPDF_TextObject() {} -CPDF_TextObject::~CPDF_TextObject() {} +CPDF_TextObject::~CPDF_TextObject() { + // Move m_CharCodes to a local variable so it will be captured in crash dumps, + // to help with investigating crbug.com/782215. + auto char_codes_copy = std::move(m_CharCodes); +} -int CPDF_TextObject::CountItems() const { - return pdfium::CollectionSize(m_CharCodes); +size_t CPDF_TextObject::CountItems() const { + return m_CharCodes.size(); } -void CPDF_TextObject::GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const { +void CPDF_TextObject::GetItemInfo(size_t index, + CPDF_TextObjectItem* pInfo) const { pInfo->m_CharCode = m_CharCodes[index]; - pInfo->m_Origin = CFX_PointF(index ? m_CharPos[index - 1] : 0, 0); + pInfo->m_Origin = CFX_PointF(index > 0 ? m_CharPos[index - 1] : 0, 0); if (pInfo->m_CharCode == CPDF_Font::kInvalidCharCode) return; @@ -44,24 +50,24 @@ void CPDF_TextObject::GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const { short vy; pFont->AsCIDFont()->GetVertOrigin(CID, vx, vy); - FX_FLOAT fontsize = m_TextState.GetFontSize(); + float fontsize = m_TextState.GetFontSize(); pInfo->m_Origin.x -= fontsize * vx / 1000; pInfo->m_Origin.y -= fontsize * vy / 1000; } -int CPDF_TextObject::CountChars() const { - int count = 0; +size_t CPDF_TextObject::CountChars() const { + size_t count = 0; for (uint32_t charcode : m_CharCodes) { if (charcode != CPDF_Font::kInvalidCharCode) - count++; + ++count; } return count; } -void CPDF_TextObject::GetCharInfo(int index, +void CPDF_TextObject::GetCharInfo(size_t index, uint32_t* charcode, - FX_FLOAT* kerning) const { - int count = 0; + float* kerning) const { + size_t count = 0; for (size_t i = 0; i < m_CharCodes.size(); ++i) { if (m_CharCodes[i] == CPDF_Font::kInvalidCharCode) continue; @@ -78,9 +84,10 @@ void CPDF_TextObject::GetCharInfo(int index, } } -void CPDF_TextObject::GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const { - int count = 0; - for (int i = 0; i < pdfium::CollectionSize(m_CharCodes); ++i) { +void CPDF_TextObject::GetCharInfo(size_t index, + CPDF_TextObjectItem* pInfo) const { + size_t count = 0; + for (size_t i = 0; i < m_CharCodes.size(); ++i) { uint32_t charcode = m_CharCodes[i]; if (charcode == CPDF_Font::kInvalidCharCode) continue; @@ -108,13 +115,14 @@ void CPDF_TextObject::Transform(const CFX_Matrix& matrix) { CFX_Matrix text_matrix = GetTextMatrix(); text_matrix.Concat(matrix); - FX_FLOAT* pTextMatrix = m_TextState.GetMutableMatrix(); + float* pTextMatrix = m_TextState.GetMutableMatrix(); pTextMatrix[0] = text_matrix.a; pTextMatrix[1] = text_matrix.c; pTextMatrix[2] = text_matrix.b; pTextMatrix[3] = text_matrix.d; m_Pos = CFX_PointF(text_matrix.e, text_matrix.f); CalcPositionData(0); + SetDirty(true); } bool CPDF_TextObject::IsText() const { @@ -130,13 +138,13 @@ const CPDF_TextObject* CPDF_TextObject::AsText() const { } CFX_Matrix CPDF_TextObject::GetTextMatrix() const { - const FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); + const float* pTextMatrix = m_TextState.GetMatrix(); return CFX_Matrix(pTextMatrix[0], pTextMatrix[2], pTextMatrix[1], pTextMatrix[3], m_Pos.x, m_Pos.y); } -void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs, - const FX_FLOAT* pKerning, +void CPDF_TextObject::SetSegments(const ByteString* pStrs, + const float* pKerning, int nsegs) { m_CharCodes.clear(); m_CharPos.clear(); @@ -149,7 +157,7 @@ void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs, m_CharPos.resize(nChars - 1); int index = 0; for (int i = 0; i < nsegs; ++i) { - const FX_CHAR* segment = pStrs[i].c_str(); + const char* segment = pStrs[i].c_str(); int len = pStrs[i].GetLength(); int offset = 0; while (offset < len) @@ -161,13 +169,14 @@ void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs, } } -void CPDF_TextObject::SetText(const CFX_ByteString& str) { +void CPDF_TextObject::SetText(const ByteString& str) { SetSegments(&str, nullptr, 1); RecalcPositionData(); + SetDirty(true); } -FX_FLOAT CPDF_TextObject::GetCharWidth(uint32_t charcode) const { - FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; +float CPDF_TextObject::GetCharWidth(uint32_t charcode) const { + float fontsize = m_TextState.GetFontSize() / 1000; CPDF_Font* pFont = m_TextState.GetFont(); bool bVertWriting = false; CPDF_CIDFont* pCIDFont = pFont->AsCIDFont(); @@ -184,24 +193,24 @@ CPDF_Font* CPDF_TextObject::GetFont() const { return m_TextState.GetFont(); } -FX_FLOAT CPDF_TextObject::GetFontSize() const { +float CPDF_TextObject::GetFontSize() const { return m_TextState.GetFontSize(); } -CFX_PointF CPDF_TextObject::CalcPositionData(FX_FLOAT horz_scale) { - FX_FLOAT curpos = 0; - FX_FLOAT min_x = 10000 * 1.0f; - FX_FLOAT max_x = -10000 * 1.0f; - FX_FLOAT min_y = 10000 * 1.0f; - FX_FLOAT max_y = -10000 * 1.0f; +CFX_PointF CPDF_TextObject::CalcPositionData(float horz_scale) { + float curpos = 0; + float min_x = 10000 * 1.0f; + float max_x = -10000 * 1.0f; + float min_y = 10000 * 1.0f; + float max_y = -10000 * 1.0f; CPDF_Font* pFont = m_TextState.GetFont(); bool bVertWriting = false; CPDF_CIDFont* pCIDFont = pFont->AsCIDFont(); if (pCIDFont) bVertWriting = pCIDFont->IsVertWriting(); - FX_FLOAT fontsize = m_TextState.GetFontSize(); - for (int i = 0; i < pdfium::CollectionSize(m_CharCodes); ++i) { + float fontsize = m_TextState.GetFontSize(); + for (size_t i = 0; i < m_CharCodes.size(); ++i) { uint32_t charcode = m_CharCodes[i]; if (i > 0) { if (charcode == CPDF_Font::kInvalidCharCode) { @@ -212,14 +221,14 @@ CFX_PointF CPDF_TextObject::CalcPositionData(FX_FLOAT horz_scale) { } FX_RECT char_rect = pFont->GetCharBBox(charcode); - FX_FLOAT charwidth; + float charwidth; if (!bVertWriting) { - min_y = std::min(min_y, static_cast( - std::min(char_rect.top, char_rect.bottom))); - max_y = std::max(max_y, static_cast( - std::max(char_rect.top, char_rect.bottom))); - FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000; - FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000; + min_y = std::min( + min_y, static_cast(std::min(char_rect.top, char_rect.bottom))); + max_y = std::max( + max_y, static_cast(std::max(char_rect.top, char_rect.bottom))); + float char_left = curpos + char_rect.left * fontsize / 1000; + float char_right = curpos + char_rect.right * fontsize / 1000; min_x = std::min(min_x, std::min(char_left, char_right)); max_x = std::max(max_x, std::max(char_left, char_right)); charwidth = pFont->GetCharWidthF(charcode) * fontsize / 1000; @@ -232,12 +241,12 @@ CFX_PointF CPDF_TextObject::CalcPositionData(FX_FLOAT horz_scale) { char_rect.right -= vx; char_rect.top -= vy; char_rect.bottom -= vy; - min_x = std::min(min_x, static_cast( - std::min(char_rect.left, char_rect.right))); - max_x = std::max(max_x, static_cast( - std::max(char_rect.left, char_rect.right))); - FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000; - FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000; + min_x = std::min( + min_x, static_cast(std::min(char_rect.left, char_rect.right))); + max_x = std::max( + max_x, static_cast(std::max(char_rect.left, char_rect.right))); + float char_top = curpos + char_rect.top * fontsize / 1000; + float char_bottom = curpos + char_rect.bottom * fontsize / 1000; min_y = std::min(min_y, std::min(char_top, char_bottom)); max_y = std::max(max_y, std::max(char_top, char_bottom)); charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; @@ -259,17 +268,13 @@ CFX_PointF CPDF_TextObject::CalcPositionData(FX_FLOAT horz_scale) { min_y = min_y * fontsize / 1000; max_y = max_y * fontsize / 1000; } - - m_Left = min_x; - m_Right = max_x; - m_Bottom = min_y; - m_Top = max_y; - GetTextMatrix().TransformRect(m_Left, m_Right, m_Top, m_Bottom); + std::tie(m_Left, m_Right, m_Top, m_Bottom) = + GetTextMatrix().TransformRect(min_x, max_x, max_y, min_y); if (!TextRenderingModeIsStrokeMode(m_TextState.GetTextMode())) return ret; - FX_FLOAT half_width = m_GraphState.GetLineWidth() / 2; + float half_width = m_GraphState.GetLineWidth() / 2; m_Left -= half_width; m_Right += half_width; m_Top += half_width; @@ -278,9 +283,9 @@ CFX_PointF CPDF_TextObject::CalcPositionData(FX_FLOAT horz_scale) { return ret; } -void CPDF_TextObject::SetPosition(FX_FLOAT x, FX_FLOAT y) { - FX_FLOAT dx = x - m_Pos.x; - FX_FLOAT dy = y - m_Pos.y; +void CPDF_TextObject::SetPosition(float x, float y) { + float dx = x - m_Pos.x; + float dy = y - m_Pos.y; m_Pos.x = x; m_Pos.y = y; m_Left += dx; diff --git a/core/fpdfapi/page/cpdf_textobject.h b/core/fpdfapi/page/cpdf_textobject.h index 59da718f629ea127e4de181412f81c9e18fd1ae7..a6fc62369c14e7dc87252fc8aa59fbbf4abbd913 100644 --- a/core/fpdfapi/page/cpdf_textobject.h +++ b/core/fpdfapi/page/cpdf_textobject.h @@ -36,37 +36,36 @@ class CPDF_TextObject : public CPDF_PageObject { const CPDF_TextObject* AsText() const override; std::unique_ptr Clone() const; - int CountItems() const; - void GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const; - int CountChars() const; - void GetCharInfo(int index, uint32_t* charcode, FX_FLOAT* kerning) const; - void GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const; - FX_FLOAT GetCharWidth(uint32_t charcode) const; + + size_t CountItems() const; + void GetItemInfo(size_t index, CPDF_TextObjectItem* pInfo) const; + + size_t CountChars() const; + void GetCharInfo(size_t index, uint32_t* charcode, float* kerning) const; + void GetCharInfo(size_t index, CPDF_TextObjectItem* pInfo) const; + float GetCharWidth(uint32_t charcode) const; + CFX_PointF GetPos() const { return m_Pos; } CFX_Matrix GetTextMatrix() const; CPDF_Font* GetFont() const; - FX_FLOAT GetFontSize() const; + float GetFontSize() const; - void SetText(const CFX_ByteString& text); - void SetPosition(FX_FLOAT x, FX_FLOAT y); + void SetText(const ByteString& text); + void SetPosition(CFX_PointF pos) { m_Pos = pos; } + void SetPosition(float x, float y); void RecalcPositionData(); - private: - friend class CPDF_RenderStatus; - friend class CPDF_StreamContentParser; - friend class CPDF_TextRenderer; - friend class CPDF_PageContentGenerator; - - void SetSegments(const CFX_ByteString* pStrs, - const FX_FLOAT* pKerning, - int nSegs); + const std::vector& GetCharCodes() const { return m_CharCodes; } + const std::vector& GetCharPositions() const { return m_CharPos; } - CFX_PointF CalcPositionData(FX_FLOAT horz_scale); + void SetSegments(const ByteString* pStrs, const float* pKerning, int nSegs); + CFX_PointF CalcPositionData(float horz_scale); + private: CFX_PointF m_Pos; std::vector m_CharCodes; - std::vector m_CharPos; + std::vector m_CharPos; }; #endif // CORE_FPDFAPI_PAGE_CPDF_TEXTOBJECT_H_ diff --git a/core/fpdfapi/page/cpdf_textstate.cpp b/core/fpdfapi/page/cpdf_textstate.cpp index 990c9cc31128bd9998a8650b702c13edecb8f42e..bd236a2f28d0c64452841b5e1fa8dd62c91a1349 100644 --- a/core/fpdfapi/page/cpdf_textstate.cpp +++ b/core/fpdfapi/page/cpdf_textstate.cpp @@ -25,51 +25,51 @@ void CPDF_TextState::SetFont(CPDF_Font* pFont) { m_Ref.GetPrivateCopy()->SetFont(pFont); } -FX_FLOAT CPDF_TextState::GetFontSize() const { +float CPDF_TextState::GetFontSize() const { return m_Ref.GetObject()->m_FontSize; } -void CPDF_TextState::SetFontSize(FX_FLOAT size) { +void CPDF_TextState::SetFontSize(float size) { m_Ref.GetPrivateCopy()->m_FontSize = size; } -const FX_FLOAT* CPDF_TextState::GetMatrix() const { +const float* CPDF_TextState::GetMatrix() const { return m_Ref.GetObject()->m_Matrix; } -FX_FLOAT* CPDF_TextState::GetMutableMatrix() { +float* CPDF_TextState::GetMutableMatrix() { return m_Ref.GetPrivateCopy()->m_Matrix; } -FX_FLOAT CPDF_TextState::GetCharSpace() const { +float CPDF_TextState::GetCharSpace() const { return m_Ref.GetObject()->m_CharSpace; } -void CPDF_TextState::SetCharSpace(FX_FLOAT sp) { +void CPDF_TextState::SetCharSpace(float sp) { m_Ref.GetPrivateCopy()->m_CharSpace = sp; } -FX_FLOAT CPDF_TextState::GetWordSpace() const { +float CPDF_TextState::GetWordSpace() const { return m_Ref.GetObject()->m_WordSpace; } -void CPDF_TextState::SetWordSpace(FX_FLOAT sp) { +void CPDF_TextState::SetWordSpace(float sp) { m_Ref.GetPrivateCopy()->m_WordSpace = sp; } -FX_FLOAT CPDF_TextState::GetFontSizeV() const { +float CPDF_TextState::GetFontSizeV() const { return m_Ref.GetObject()->GetFontSizeV(); } -FX_FLOAT CPDF_TextState::GetFontSizeH() const { +float CPDF_TextState::GetFontSizeH() const { return m_Ref.GetObject()->GetFontSizeH(); } -FX_FLOAT CPDF_TextState::GetBaselineAngle() const { +float CPDF_TextState::GetBaselineAngle() const { return m_Ref.GetObject()->GetBaselineAngle(); } -FX_FLOAT CPDF_TextState::GetShearAngle() const { +float CPDF_TextState::GetShearAngle() const { return m_Ref.GetObject()->GetShearAngle(); } @@ -81,11 +81,11 @@ void CPDF_TextState::SetTextMode(TextRenderingMode mode) { m_Ref.GetPrivateCopy()->m_TextMode = mode; } -const FX_FLOAT* CPDF_TextState::GetCTM() const { +const float* CPDF_TextState::GetCTM() const { return m_Ref.GetObject()->m_CTM; } -FX_FLOAT* CPDF_TextState::GetMutableCTM() { +float* CPDF_TextState::GetMutableCTM() { return m_Ref.GetPrivateCopy()->m_CTM; } @@ -115,43 +115,43 @@ CPDF_TextState::TextData::TextData(const TextData& that) for (int i = 0; i < 4; ++i) m_CTM[i] = that.m_CTM[i]; - if (m_pDocument && m_pFont) { + if (m_pDocument && m_pFont) m_pFont = m_pDocument->GetPageData()->GetFont(m_pFont->GetFontDict()); - } } CPDF_TextState::TextData::~TextData() { - if (m_pDocument && m_pFont) { - CPDF_DocPageData* pPageData = m_pDocument->GetPageData(); - if (pPageData && !pPageData->IsForceClear()) - pPageData->ReleaseFont(m_pFont->GetFontDict()); - } + ReleaseFont(); } void CPDF_TextState::TextData::SetFont(CPDF_Font* pFont) { - CPDF_Document* pDoc = m_pDocument; - CPDF_DocPageData* pPageData = pDoc ? pDoc->GetPageData() : nullptr; - if (pPageData && m_pFont && !pPageData->IsForceClear()) - pPageData->ReleaseFont(m_pFont->GetFontDict()); - - m_pDocument = pFont ? pFont->m_pDocument : nullptr; + ReleaseFont(); + m_pDocument = pFont ? pFont->GetDocument() : nullptr; m_pFont = pFont; } -FX_FLOAT CPDF_TextState::TextData::GetFontSizeV() const { - return FXSYS_fabs(FXSYS_sqrt2(m_Matrix[1], m_Matrix[3]) * m_FontSize); +float CPDF_TextState::TextData::GetFontSizeV() const { + return fabs(FXSYS_sqrt2(m_Matrix[1], m_Matrix[3]) * m_FontSize); } -FX_FLOAT CPDF_TextState::TextData::GetFontSizeH() const { - return FXSYS_fabs(FXSYS_sqrt2(m_Matrix[0], m_Matrix[2]) * m_FontSize); +float CPDF_TextState::TextData::GetFontSizeH() const { + return fabs(FXSYS_sqrt2(m_Matrix[0], m_Matrix[2]) * m_FontSize); } -FX_FLOAT CPDF_TextState::TextData::GetBaselineAngle() const { - return FXSYS_atan2(m_Matrix[2], m_Matrix[0]); +float CPDF_TextState::TextData::GetBaselineAngle() const { + return atan2(m_Matrix[2], m_Matrix[0]); } -FX_FLOAT CPDF_TextState::TextData::GetShearAngle() const { - return GetBaselineAngle() + FXSYS_atan2(m_Matrix[1], m_Matrix[3]); +float CPDF_TextState::TextData::GetShearAngle() const { + return GetBaselineAngle() + atan2(m_Matrix[1], m_Matrix[3]); +} + +void CPDF_TextState::TextData::ReleaseFont() { + if (!m_pDocument || !m_pFont) + return; + + CPDF_DocPageData* pPageData = m_pDocument->GetPageData(); + if (pPageData && !pPageData->IsForceClear()) + pPageData->ReleaseFont(m_pFont->GetFontDict()); } bool SetTextRenderingModeFromInt(int iMode, TextRenderingMode* mode) { diff --git a/core/fpdfapi/page/cpdf_textstate.h b/core/fpdfapi/page/cpdf_textstate.h index 4723469fd9664ecba0a161dfdf856d0e9f658024..aa128072b69a04939a9fe4b8ee2280bf39bf6f3c 100644 --- a/core/fpdfapi/page/cpdf_textstate.h +++ b/core/fpdfapi/page/cpdf_textstate.h @@ -7,8 +7,8 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_TEXTSTATE_H_ #define CORE_FPDFAPI_PAGE_CPDF_TEXTSTATE_H_ -#include "core/fxcrt/cfx_shared_copy_on_write.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/shared_copy_on_write.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_Font; @@ -35,53 +35,56 @@ class CPDF_TextState { CPDF_Font* GetFont() const; void SetFont(CPDF_Font* pFont); - FX_FLOAT GetFontSize() const; - void SetFontSize(FX_FLOAT size); + float GetFontSize() const; + void SetFontSize(float size); - const FX_FLOAT* GetMatrix() const; - FX_FLOAT* GetMutableMatrix(); + const float* GetMatrix() const; + float* GetMutableMatrix(); - FX_FLOAT GetCharSpace() const; - void SetCharSpace(FX_FLOAT sp); + float GetCharSpace() const; + void SetCharSpace(float sp); - FX_FLOAT GetWordSpace() const; - void SetWordSpace(FX_FLOAT sp); + float GetWordSpace() const; + void SetWordSpace(float sp); - FX_FLOAT GetFontSizeV() const; - FX_FLOAT GetFontSizeH() const; - FX_FLOAT GetBaselineAngle() const; - FX_FLOAT GetShearAngle() const; + float GetFontSizeV() const; + float GetFontSizeH() const; + float GetBaselineAngle() const; + float GetShearAngle() const; TextRenderingMode GetTextMode() const; void SetTextMode(TextRenderingMode mode); - const FX_FLOAT* GetCTM() const; - FX_FLOAT* GetMutableCTM(); + const float* GetCTM() const; + float* GetMutableCTM(); private: - class TextData { + class TextData : public Retainable { public: TextData(); TextData(const TextData& src); - ~TextData(); + ~TextData() override; void SetFont(CPDF_Font* pFont); - FX_FLOAT GetFontSizeV() const; - FX_FLOAT GetFontSizeH() const; - FX_FLOAT GetBaselineAngle() const; - FX_FLOAT GetShearAngle() const; + float GetFontSizeV() const; + float GetFontSizeH() const; + float GetBaselineAngle() const; + float GetShearAngle() const; CPDF_Font* m_pFont; - CPDF_Document* m_pDocument; - FX_FLOAT m_FontSize; - FX_FLOAT m_CharSpace; - FX_FLOAT m_WordSpace; + UnownedPtr m_pDocument; + float m_FontSize; + float m_CharSpace; + float m_WordSpace; TextRenderingMode m_TextMode; - FX_FLOAT m_Matrix[4]; - FX_FLOAT m_CTM[4]; + float m_Matrix[4]; + float m_CTM[4]; + + private: + void ReleaseFont(); }; - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; bool SetTextRenderingModeFromInt(int iMode, TextRenderingMode* mode); diff --git a/core/fpdfapi/page/cpdf_tilingpattern.cpp b/core/fpdfapi/page/cpdf_tilingpattern.cpp index a041f3807495d3b19b8e5e146cb27e6a908fa6c9..a5252578a54dba8c7bf925d63f86650298caba24 100644 --- a/core/fpdfapi/page/cpdf_tilingpattern.cpp +++ b/core/fpdfapi/page/cpdf_tilingpattern.cpp @@ -15,11 +15,10 @@ CPDF_TilingPattern::CPDF_TilingPattern(CPDF_Document* pDoc, CPDF_Object* pPatternObj, const CFX_Matrix& parentMatrix) - : CPDF_Pattern(TILING, pDoc, pPatternObj, parentMatrix) { - CPDF_Dictionary* pDict = m_pPatternObj->GetDict(); - m_Pattern2Form = pDict->GetMatrixFor("Matrix"); - m_bColored = pDict->GetIntegerFor("PaintType") == 1; - m_Pattern2Form.Concat(parentMatrix); + : CPDF_Pattern(pDoc, pPatternObj, parentMatrix) { + assert(document()); + m_bColored = pattern_obj()->GetDict()->GetIntegerFor("PaintType") == 1; + SetPatternToFormMatrix(); } CPDF_TilingPattern::~CPDF_TilingPattern() {} @@ -36,20 +35,21 @@ bool CPDF_TilingPattern::Load() { if (m_pForm) return true; - CPDF_Dictionary* pDict = m_pPatternObj->GetDict(); + CPDF_Dictionary* pDict = pattern_obj()->GetDict(); if (!pDict) return false; m_bColored = pDict->GetIntegerFor("PaintType") == 1; - m_XStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumberFor("XStep")); - m_YStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumberFor("YStep")); + m_XStep = static_cast(fabs(pDict->GetNumberFor("XStep"))); + m_YStep = static_cast(fabs(pDict->GetNumberFor("YStep"))); - CPDF_Stream* pStream = m_pPatternObj->AsStream(); + CPDF_Stream* pStream = pattern_obj()->AsStream(); if (!pStream) return false; - m_pForm = pdfium::MakeUnique(m_pDocument, nullptr, pStream); - m_pForm->ParseContent(nullptr, &m_ParentMatrix, nullptr); + const CFX_Matrix& matrix = parent_matrix(); + m_pForm = pdfium::MakeUnique(document(), nullptr, pStream); + m_pForm->ParseContentWithParams(nullptr, &matrix, nullptr, 0); m_BBox = pDict->GetRectFor("BBox"); return true; } diff --git a/core/fpdfapi/page/cpdf_tilingpattern.h b/core/fpdfapi/page/cpdf_tilingpattern.h index 3f0851aa7eade59610c7d1a8df074dfffdc9e217..d9450d7c2f4ea6ed9cfedaea6eac0bc93d5af6ae 100644 --- a/core/fpdfapi/page/cpdf_tilingpattern.h +++ b/core/fpdfapi/page/cpdf_tilingpattern.h @@ -31,15 +31,15 @@ class CPDF_TilingPattern : public CPDF_Pattern { bool colored() const { return m_bColored; } const CFX_FloatRect& bbox() const { return m_BBox; } - FX_FLOAT x_step() const { return m_XStep; } - FX_FLOAT y_step() const { return m_YStep; } + float x_step() const { return m_XStep; } + float y_step() const { return m_YStep; } CPDF_Form* form() const { return m_pForm.get(); } private: bool m_bColored; CFX_FloatRect m_BBox; - FX_FLOAT m_XStep; - FX_FLOAT m_YStep; + float m_XStep; + float m_YStep; std::unique_ptr m_pForm; }; diff --git a/core/fpdfapi/page/fpdf_page_colors.cpp b/core/fpdfapi/page/fpdf_page_colors.cpp deleted file mode 100644 index 69129e4f2b121d03a1547acc2905b11fd2f1cff4..0000000000000000000000000000000000000000 --- a/core/fpdfapi/page/fpdf_page_colors.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/page/pageint.h" - -#include - -#include - -#include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fpdfapi/parser/cpdf_string.h" -#include "core/fxcodec/fx_codec.h" - -namespace { - -FX_FLOAT NormalizeChannel(FX_FLOAT fVal) { - return std::min(std::max(fVal, 0.0f), 1.0f); -} - -} // namespace - -uint32_t ComponentsForFamily(int family) { - if (family == PDFCS_DEVICERGB) - return 3; - if (family == PDFCS_DEVICEGRAY) - return 1; - ASSERT(family == PDFCS_DEVICECMYK); - return 4; -} - -void sRGB_to_AdobeCMYK(FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) { - c = 1.0f - R; - m = 1.0f - G; - y = 1.0f - B; - k = c; - if (m < k) { - k = m; - } - if (y < k) { - k = y; - } -} - -void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels) { - if (pDestBuf == pSrcBuf) { - for (int i = 0; i < pixels; i++) { - uint8_t temp = pDestBuf[2]; - pDestBuf[2] = pDestBuf[0]; - pDestBuf[0] = temp; - pDestBuf += 3; - } - } else { - for (int i = 0; i < pixels; i++) { - *pDestBuf++ = pSrcBuf[2]; - *pDestBuf++ = pSrcBuf[1]; - *pDestBuf++ = pSrcBuf[0]; - pSrcBuf += 3; - } - } -} - -CPDF_DeviceCS::CPDF_DeviceCS(CPDF_Document* pDoc, int family) - : CPDF_ColorSpace(pDoc, family, ComponentsForFamily(family)) { - ASSERT(family == PDFCS_DEVICEGRAY || family == PDFCS_DEVICERGB || - family == PDFCS_DEVICECMYK); -} - -bool CPDF_DeviceCS::GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const { - switch (m_Family) { - case PDFCS_DEVICEGRAY: - R = NormalizeChannel(*pBuf); - G = R; - B = R; - break; - case PDFCS_DEVICERGB: - R = NormalizeChannel(pBuf[0]); - G = NormalizeChannel(pBuf[1]); - B = NormalizeChannel(pBuf[2]); - break; - case PDFCS_DEVICECMYK: - if (m_dwStdConversion) { - FX_FLOAT k = pBuf[3]; - R = 1.0f - std::min(1.0f, pBuf[0] + k); - G = 1.0f - std::min(1.0f, pBuf[1] + k); - B = 1.0f - std::min(1.0f, pBuf[2] + k); - } else { - AdobeCMYK_to_sRGB(pBuf[0], pBuf[1], pBuf[2], pBuf[3], R, G, B); - } - break; - default: - ASSERT(false); - return false; - } - return true; -} - -bool CPDF_DeviceCS::v_GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const { - if (m_Family != PDFCS_DEVICECMYK) - return false; - - c = pBuf[0]; - m = pBuf[1]; - y = pBuf[2]; - k = pBuf[3]; - return true; -} - -bool CPDF_DeviceCS::SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const { - switch (m_Family) { - case PDFCS_DEVICEGRAY: - if (R != G || R != B) - return false; - *pBuf = R; - return true; - case PDFCS_DEVICERGB: - pBuf[0] = R; - pBuf[1] = G; - pBuf[2] = B; - return true; - case PDFCS_DEVICECMYK: - sRGB_to_AdobeCMYK(R, G, B, pBuf[0], pBuf[1], pBuf[2], pBuf[3]); - return true; - default: - ASSERT(false); - return false; - } -} - -bool CPDF_DeviceCS::v_SetCMYK(FX_FLOAT* pBuf, - FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k) const { - switch (m_Family) { - case PDFCS_DEVICEGRAY: - return false; - case PDFCS_DEVICERGB: - AdobeCMYK_to_sRGB(c, m, y, k, pBuf[0], pBuf[1], pBuf[2]); - return true; - case PDFCS_DEVICECMYK: - pBuf[0] = c; - pBuf[1] = m; - pBuf[2] = y; - pBuf[3] = k; - return true; - default: - ASSERT(false); - return false; - } -} - -void CPDF_DeviceCS::TranslateImageLine(uint8_t* pDestBuf, - const uint8_t* pSrcBuf, - int pixels, - int image_width, - int image_height, - bool bTransMask) const { - switch (m_Family) { - case PDFCS_DEVICEGRAY: - for (int i = 0; i < pixels; i++) { - *pDestBuf++ = pSrcBuf[i]; - *pDestBuf++ = pSrcBuf[i]; - *pDestBuf++ = pSrcBuf[i]; - } - break; - case PDFCS_DEVICERGB: - ReverseRGB(pDestBuf, pSrcBuf, pixels); - break; - case PDFCS_DEVICECMYK: - if (bTransMask) { - for (int i = 0; i < pixels; i++) { - int k = 255 - pSrcBuf[3]; - pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255; - pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255; - pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255; - pDestBuf += 3; - pSrcBuf += 4; - } - } else { - for (int i = 0; i < pixels; i++) { - if (m_dwStdConversion) { - uint8_t k = pSrcBuf[3]; - pDestBuf[2] = 255 - std::min(255, pSrcBuf[0] + k); - pDestBuf[1] = 255 - std::min(255, pSrcBuf[1] + k); - pDestBuf[0] = 255 - std::min(255, pSrcBuf[2] + k); - } else { - AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2], pSrcBuf[3], - pDestBuf[2], pDestBuf[1], pDestBuf[0]); - } - pSrcBuf += 4; - pDestBuf += 3; - } - } - break; - default: - ASSERT(false); - break; - } -} - -CPDF_IccProfile::CPDF_IccProfile(const uint8_t* pData, uint32_t dwSize) - : m_bsRGB(false), m_pTransform(nullptr), m_nSrcComponents(0) { - if (dwSize == 3144 && - FXSYS_memcmp(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0) { - m_bsRGB = true; - m_nSrcComponents = 3; - } else if (CPDF_ModuleMgr::Get()->GetIccModule()) { - m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB( - pData, dwSize, m_nSrcComponents); - } -} -CPDF_IccProfile::~CPDF_IccProfile() { - if (m_pTransform) { - CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform); - } -} diff --git a/core/fpdfapi/page/fpdf_page_func.cpp b/core/fpdfapi/page/fpdf_page_func.cpp deleted file mode 100644 index 916641f05dfa7e100c4b409bdf5a853771da8455..0000000000000000000000000000000000000000 --- a/core/fpdfapi/page/fpdf_page_func.cpp +++ /dev/null @@ -1,862 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/page/pageint.h" - -#include - -#include -#include -#include -#include - -#include "core/fpdfapi/page/cpdf_psengine.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcrt/fx_safe_types.h" -#include "third_party/base/ptr_util.h" - -namespace { - -struct PDF_PSOpName { - const FX_CHAR* name; - PDF_PSOP op; -}; - -const PDF_PSOpName kPsOpNames[] = { - {"add", PSOP_ADD}, {"sub", PSOP_SUB}, - {"mul", PSOP_MUL}, {"div", PSOP_DIV}, - {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD}, - {"neg", PSOP_NEG}, {"abs", PSOP_ABS}, - {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR}, - {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE}, - {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN}, - {"cos", PSOP_COS}, {"atan", PSOP_ATAN}, - {"exp", PSOP_EXP}, {"ln", PSOP_LN}, - {"log", PSOP_LOG}, {"cvi", PSOP_CVI}, - {"cvr", PSOP_CVR}, {"eq", PSOP_EQ}, - {"ne", PSOP_NE}, {"gt", PSOP_GT}, - {"ge", PSOP_GE}, {"lt", PSOP_LT}, - {"le", PSOP_LE}, {"and", PSOP_AND}, - {"or", PSOP_OR}, {"xor", PSOP_XOR}, - {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT}, - {"true", PSOP_TRUE}, {"false", PSOP_FALSE}, - {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE}, - {"pop", PSOP_POP}, {"exch", PSOP_EXCH}, - {"dup", PSOP_DUP}, {"copy", PSOP_COPY}, - {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}}; - -// See PDF Reference 1.7, page 170, table 3.36. -bool IsValidBitsPerSample(uint32_t x) { - switch (x) { - case 1: - case 2: - case 4: - case 8: - case 12: - case 16: - case 24: - case 32: - return true; - default: - return false; - } -} - -// See PDF Reference 1.7, page 170. -FX_FLOAT PDF_Interpolate(FX_FLOAT x, - FX_FLOAT xmin, - FX_FLOAT xmax, - FX_FLOAT ymin, - FX_FLOAT ymax) { - FX_FLOAT divisor = xmax - xmin; - return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0); -} - -class CPDF_PSFunc : public CPDF_Function { - public: - CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} - ~CPDF_PSFunc() override {} - - // CPDF_Function - bool v_Init(CPDF_Object* pObj) override; - bool v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - - private: - CPDF_PSEngine m_PS; -}; - -bool CPDF_PSFunc::v_Init(CPDF_Object* pObj) { - CPDF_StreamAcc acc; - acc.LoadAllData(pObj->AsStream(), false); - return m_PS.Parse(reinterpret_cast(acc.GetData()), - acc.GetSize()); -} - -bool CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { - CPDF_PSEngine& PS = const_cast(m_PS); - PS.Reset(); - for (uint32_t i = 0; i < m_nInputs; i++) - PS.Push(inputs[i]); - PS.Execute(); - if (PS.GetStackSize() < m_nOutputs) - return false; - for (uint32_t i = 0; i < m_nOutputs; i++) - results[m_nOutputs - i - 1] = PS.Pop(); - return true; -} - -} // namespace - -class CPDF_PSOP { - public: - explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { - ASSERT(m_op != PSOP_CONST); - ASSERT(m_op != PSOP_PROC); - } - explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {} - explicit CPDF_PSOP(std::unique_ptr proc) - : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {} - - FX_FLOAT GetFloatValue() const { - if (m_op == PSOP_CONST) - return m_value; - - ASSERT(false); - return 0; - } - CPDF_PSProc* GetProc() const { - if (m_op == PSOP_PROC) - return m_proc.get(); - ASSERT(false); - return nullptr; - } - - PDF_PSOP GetOp() const { return m_op; } - - private: - const PDF_PSOP m_op; - const FX_FLOAT m_value; - std::unique_ptr m_proc; -}; - -bool CPDF_PSEngine::Execute() { - return m_MainProc.Execute(this); -} - -CPDF_PSProc::CPDF_PSProc() {} -CPDF_PSProc::~CPDF_PSProc() {} - -bool CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) { - for (size_t i = 0; i < m_Operators.size(); ++i) { - const PDF_PSOP op = m_Operators[i]->GetOp(); - if (op == PSOP_PROC) - continue; - - if (op == PSOP_CONST) { - pEngine->Push(m_Operators[i]->GetFloatValue()); - continue; - } - - if (op == PSOP_IF) { - if (i == 0 || m_Operators[i - 1]->GetOp() != PSOP_PROC) - return false; - - if (static_cast(pEngine->Pop())) - m_Operators[i - 1]->GetProc()->Execute(pEngine); - } else if (op == PSOP_IFELSE) { - if (i < 2 || m_Operators[i - 1]->GetOp() != PSOP_PROC || - m_Operators[i - 2]->GetOp() != PSOP_PROC) { - return false; - } - size_t offset = static_cast(pEngine->Pop()) ? 2 : 1; - m_Operators[i - offset]->GetProc()->Execute(pEngine); - } else { - pEngine->DoOperator(op); - } - } - return true; -} - -CPDF_PSEngine::CPDF_PSEngine() { - m_StackCount = 0; -} -CPDF_PSEngine::~CPDF_PSEngine() {} -void CPDF_PSEngine::Push(FX_FLOAT v) { - if (m_StackCount == PSENGINE_STACKSIZE) { - return; - } - m_Stack[m_StackCount++] = v; -} -FX_FLOAT CPDF_PSEngine::Pop() { - if (m_StackCount == 0) { - return 0; - } - return m_Stack[--m_StackCount]; -} -bool CPDF_PSEngine::Parse(const FX_CHAR* str, int size) { - CPDF_SimpleParser parser((uint8_t*)str, size); - CFX_ByteStringC word = parser.GetWord(); - if (word != "{") { - return false; - } - return m_MainProc.Parse(&parser, 0); -} - -bool CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { - if (depth > kMaxDepth) - return false; - - while (1) { - CFX_ByteStringC word = parser->GetWord(); - if (word.IsEmpty()) { - return false; - } - if (word == "}") { - return true; - } - if (word == "{") { - std::unique_ptr proc(new CPDF_PSProc); - std::unique_ptr op(new CPDF_PSOP(std::move(proc))); - m_Operators.push_back(std::move(op)); - if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1)) { - return false; - } - } else { - bool found = false; - for (const PDF_PSOpName& op_name : kPsOpNames) { - if (word == CFX_ByteStringC(op_name.name)) { - std::unique_ptr op(new CPDF_PSOP(op_name.op)); - m_Operators.push_back(std::move(op)); - found = true; - break; - } - } - if (!found) { - std::unique_ptr op(new CPDF_PSOP(FX_atof(word))); - m_Operators.push_back(std::move(op)); - } - } - } -} - -bool CPDF_PSEngine::DoOperator(PDF_PSOP op) { - int i1; - int i2; - FX_FLOAT d1; - FX_FLOAT d2; - FX_SAFE_INT32 result; - switch (op) { - case PSOP_ADD: - d1 = Pop(); - d2 = Pop(); - Push(d1 + d2); - break; - case PSOP_SUB: - d2 = Pop(); - d1 = Pop(); - Push(d1 - d2); - break; - case PSOP_MUL: - d1 = Pop(); - d2 = Pop(); - Push(d1 * d2); - break; - case PSOP_DIV: - d2 = Pop(); - d1 = Pop(); - Push(d1 / d2); - break; - case PSOP_IDIV: - i2 = static_cast(Pop()); - i1 = static_cast(Pop()); - if (i2) { - result = i1; - result /= i2; - Push(result.ValueOrDefault(0)); - } else { - Push(0); - } - break; - case PSOP_MOD: - i2 = static_cast(Pop()); - i1 = static_cast(Pop()); - if (i2) { - result = i1; - result %= i2; - Push(result.ValueOrDefault(0)); - } else { - Push(0); - } - break; - case PSOP_NEG: - d1 = Pop(); - Push(-d1); - break; - case PSOP_ABS: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_fabs(d1)); - break; - case PSOP_CEILING: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_ceil(d1)); - break; - case PSOP_FLOOR: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_floor(d1)); - break; - case PSOP_ROUND: - d1 = Pop(); - Push(FXSYS_round(d1)); - break; - case PSOP_TRUNCATE: - i1 = (int)Pop(); - Push(i1); - break; - case PSOP_SQRT: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_sqrt(d1)); - break; - case PSOP_SIN: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_sin(d1 * FX_PI / 180.0f)); - break; - case PSOP_COS: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_cos(d1 * FX_PI / 180.0f)); - break; - case PSOP_ATAN: - d2 = Pop(); - d1 = Pop(); - d1 = (FX_FLOAT)(FXSYS_atan2(d1, d2) * 180.0 / FX_PI); - if (d1 < 0) { - d1 += 360; - } - Push(d1); - break; - case PSOP_EXP: - d2 = Pop(); - d1 = Pop(); - Push((FX_FLOAT)FXSYS_pow(d1, d2)); - break; - case PSOP_LN: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_log(d1)); - break; - case PSOP_LOG: - d1 = Pop(); - Push((FX_FLOAT)FXSYS_log10(d1)); - break; - case PSOP_CVI: - i1 = (int)Pop(); - Push(i1); - break; - case PSOP_CVR: - break; - case PSOP_EQ: - d2 = Pop(); - d1 = Pop(); - Push((int)(d1 == d2)); - break; - case PSOP_NE: - d2 = Pop(); - d1 = Pop(); - Push((int)(d1 != d2)); - break; - case PSOP_GT: - d2 = Pop(); - d1 = Pop(); - Push((int)(d1 > d2)); - break; - case PSOP_GE: - d2 = Pop(); - d1 = Pop(); - Push((int)(d1 >= d2)); - break; - case PSOP_LT: - d2 = Pop(); - d1 = Pop(); - Push((int)(d1 < d2)); - break; - case PSOP_LE: - d2 = Pop(); - d1 = Pop(); - Push((int)(d1 <= d2)); - break; - case PSOP_AND: - i1 = (int)Pop(); - i2 = (int)Pop(); - Push(i1 & i2); - break; - case PSOP_OR: - i1 = (int)Pop(); - i2 = (int)Pop(); - Push(i1 | i2); - break; - case PSOP_XOR: - i1 = (int)Pop(); - i2 = (int)Pop(); - Push(i1 ^ i2); - break; - case PSOP_NOT: - i1 = (int)Pop(); - Push((int)!i1); - break; - case PSOP_BITSHIFT: { - int shift = (int)Pop(); - result = (int)Pop(); - if (shift > 0) { - result <<= shift; - } else { - // Avoids unsafe negation of INT_MIN. - FX_SAFE_INT32 safe_shift = shift; - result >>= (-safe_shift).ValueOrDefault(0); - } - Push(result.ValueOrDefault(0)); - break; - } - case PSOP_TRUE: - Push(1); - break; - case PSOP_FALSE: - Push(0); - break; - case PSOP_POP: - Pop(); - break; - case PSOP_EXCH: - d2 = Pop(); - d1 = Pop(); - Push(d2); - Push(d1); - break; - case PSOP_DUP: - d1 = Pop(); - Push(d1); - Push(d1); - break; - case PSOP_COPY: { - int n = static_cast(Pop()); - if (n < 0 || m_StackCount + n > PSENGINE_STACKSIZE || - n > static_cast(m_StackCount)) - break; - for (int i = 0; i < n; i++) - m_Stack[m_StackCount + i] = m_Stack[m_StackCount + i - n]; - m_StackCount += n; - break; - } - case PSOP_INDEX: { - int n = static_cast(Pop()); - if (n < 0 || n >= static_cast(m_StackCount)) - break; - Push(m_Stack[m_StackCount - n - 1]); - break; - } - case PSOP_ROLL: { - int j = static_cast(Pop()); - int n = static_cast(Pop()); - if (j == 0 || n == 0 || m_StackCount == 0) - break; - if (n < 0 || n > static_cast(m_StackCount)) - break; - - j %= n; - if (j > 0) - j -= n; - auto begin_it = std::begin(m_Stack) + m_StackCount - n; - auto middle_it = begin_it - j; - auto end_it = std::begin(m_Stack) + m_StackCount; - std::rotate(begin_it, middle_it, end_it); - break; - } - default: - break; - } - return true; -} - -CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} - -CPDF_SampledFunc::~CPDF_SampledFunc() {} - -bool CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { - CPDF_Stream* pStream = pObj->AsStream(); - if (!pStream) - return false; - - CPDF_Dictionary* pDict = pStream->GetDict(); - CPDF_Array* pSize = pDict->GetArrayFor("Size"); - CPDF_Array* pEncode = pDict->GetArrayFor("Encode"); - CPDF_Array* pDecode = pDict->GetArrayFor("Decode"); - m_nBitsPerSample = pDict->GetIntegerFor("BitsPerSample"); - if (!IsValidBitsPerSample(m_nBitsPerSample)) - return false; - - m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample); - m_pSampleStream = pdfium::MakeUnique(); - m_pSampleStream->LoadAllData(pStream, false); - FX_SAFE_UINT32 nTotalSampleBits = 1; - m_EncodeInfo.resize(m_nInputs); - for (uint32_t i = 0; i < m_nInputs; i++) { - m_EncodeInfo[i].sizes = pSize ? pSize->GetIntegerAt(i) : 0; - if (!pSize && i == 0) - m_EncodeInfo[i].sizes = pDict->GetIntegerFor("Size"); - nTotalSampleBits *= m_EncodeInfo[i].sizes; - if (pEncode) { - m_EncodeInfo[i].encode_min = pEncode->GetFloatAt(i * 2); - m_EncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1); - } else { - m_EncodeInfo[i].encode_min = 0; - m_EncodeInfo[i].encode_max = - m_EncodeInfo[i].sizes == 1 ? 1 : (FX_FLOAT)m_EncodeInfo[i].sizes - 1; - } - } - nTotalSampleBits *= m_nBitsPerSample; - nTotalSampleBits *= m_nOutputs; - FX_SAFE_UINT32 nTotalSampleBytes = nTotalSampleBits; - nTotalSampleBytes += 7; - nTotalSampleBytes /= 8; - if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0 || - nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) { - return false; - } - m_DecodeInfo.resize(m_nOutputs); - for (uint32_t i = 0; i < m_nOutputs; i++) { - if (pDecode) { - m_DecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i); - m_DecodeInfo[i].decode_max = pDecode->GetFloatAt(2 * i + 1); - } else { - m_DecodeInfo[i].decode_min = m_pRanges[i * 2]; - m_DecodeInfo[i].decode_max = m_pRanges[i * 2 + 1]; - } - } - return true; -} - -bool CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { - int pos = 0; - CFX_FixedBufGrow encoded_input_buf(m_nInputs); - FX_FLOAT* encoded_input = encoded_input_buf; - CFX_FixedBufGrow int_buf(m_nInputs * 2); - uint32_t* index = int_buf; - uint32_t* blocksize = index + m_nInputs; - for (uint32_t i = 0; i < m_nInputs; i++) { - if (i == 0) - blocksize[i] = 1; - else - blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes; - encoded_input[i] = - PDF_Interpolate(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1], - m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max); - index[i] = std::min((uint32_t)std::max(0.f, encoded_input[i]), - m_EncodeInfo[i].sizes - 1); - pos += index[i] * blocksize[i]; - } - FX_SAFE_INT32 bits_to_output = m_nOutputs; - bits_to_output *= m_nBitsPerSample; - if (!bits_to_output.IsValid()) - return false; - - FX_SAFE_INT32 bitpos = pos; - bitpos *= bits_to_output.ValueOrDie(); - if (!bitpos.IsValid()) - return false; - - FX_SAFE_INT32 range_check = bitpos; - range_check += bits_to_output.ValueOrDie(); - if (!range_check.IsValid()) - return false; - - const uint8_t* pSampleData = m_pSampleStream->GetData(); - if (!pSampleData) - return false; - - for (uint32_t j = 0; j < m_nOutputs; j++, bitpos += m_nBitsPerSample) { - uint32_t sample = - GetBits32(pSampleData, bitpos.ValueOrDie(), m_nBitsPerSample); - FX_FLOAT encoded = (FX_FLOAT)sample; - for (uint32_t i = 0; i < m_nInputs; i++) { - if (index[i] == m_EncodeInfo[i].sizes - 1) { - if (index[i] == 0) - encoded = encoded_input[i] * (FX_FLOAT)sample; - } else { - FX_SAFE_INT32 bitpos2 = blocksize[i]; - bitpos2 += pos; - bitpos2 *= m_nOutputs; - bitpos2 += j; - bitpos2 *= m_nBitsPerSample; - if (!bitpos2.IsValid()) - return false; - uint32_t sample1 = - GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample); - encoded += (encoded_input[i] - index[i]) * - ((FX_FLOAT)sample1 - (FX_FLOAT)sample); - } - } - results[j] = - PDF_Interpolate(encoded, 0, (FX_FLOAT)m_SampleMax, - m_DecodeInfo[j].decode_min, m_DecodeInfo[j].decode_max); - } - return true; -} - -CPDF_ExpIntFunc::CPDF_ExpIntFunc() - : CPDF_Function(Type::kType2ExpotentialInterpolation), - m_pBeginValues(nullptr), - m_pEndValues(nullptr) {} - -CPDF_ExpIntFunc::~CPDF_ExpIntFunc() { - FX_Free(m_pBeginValues); - FX_Free(m_pEndValues); -} -bool CPDF_ExpIntFunc::v_Init(CPDF_Object* pObj) { - CPDF_Dictionary* pDict = pObj->GetDict(); - if (!pDict) { - return false; - } - CPDF_Array* pArray0 = pDict->GetArrayFor("C0"); - if (m_nOutputs == 0) { - m_nOutputs = 1; - if (pArray0) { - m_nOutputs = pArray0->GetCount(); - } - } - CPDF_Array* pArray1 = pDict->GetArrayFor("C1"); - m_pBeginValues = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2); - m_pEndValues = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2); - for (uint32_t i = 0; i < m_nOutputs; i++) { - m_pBeginValues[i] = pArray0 ? pArray0->GetFloatAt(i) : 0.0f; - m_pEndValues[i] = pArray1 ? pArray1->GetFloatAt(i) : 1.0f; - } - m_Exponent = pDict->GetFloatFor("N"); - m_nOrigOutputs = m_nOutputs; - if (m_nOutputs && m_nInputs > INT_MAX / m_nOutputs) { - return false; - } - m_nOutputs *= m_nInputs; - return true; -} -bool CPDF_ExpIntFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { - for (uint32_t i = 0; i < m_nInputs; i++) - for (uint32_t j = 0; j < m_nOrigOutputs; j++) { - results[i * m_nOrigOutputs + j] = - m_pBeginValues[j] + - (FX_FLOAT)FXSYS_pow(inputs[i], m_Exponent) * - (m_pEndValues[j] - m_pBeginValues[j]); - } - return true; -} - -CPDF_StitchFunc::CPDF_StitchFunc() - : CPDF_Function(Type::kType3Stitching), - m_pBounds(nullptr), - m_pEncode(nullptr) {} - -CPDF_StitchFunc::~CPDF_StitchFunc() { - FX_Free(m_pBounds); - FX_Free(m_pEncode); -} - -bool CPDF_StitchFunc::v_Init(CPDF_Object* pObj) { - CPDF_Dictionary* pDict = pObj->GetDict(); - if (!pDict) { - return false; - } - if (m_nInputs != kRequiredNumInputs) { - return false; - } - CPDF_Array* pArray = pDict->GetArrayFor("Functions"); - if (!pArray) { - return false; - } - uint32_t nSubs = pArray->GetCount(); - if (nSubs == 0) - return false; - m_nOutputs = 0; - for (uint32_t i = 0; i < nSubs; i++) { - CPDF_Object* pSub = pArray->GetDirectObjectAt(i); - if (pSub == pObj) - return false; - std::unique_ptr pFunc(CPDF_Function::Load(pSub)); - if (!pFunc) - return false; - // Check that the input dimensionality is 1, and that all output - // dimensionalities are the same. - if (pFunc->CountInputs() != kRequiredNumInputs) - return false; - if (pFunc->CountOutputs() != m_nOutputs) { - if (m_nOutputs) - return false; - - m_nOutputs = pFunc->CountOutputs(); - } - - m_pSubFunctions.push_back(std::move(pFunc)); - } - m_pBounds = FX_Alloc(FX_FLOAT, nSubs + 1); - m_pBounds[0] = m_pDomains[0]; - pArray = pDict->GetArrayFor("Bounds"); - if (!pArray) - return false; - for (uint32_t i = 0; i < nSubs - 1; i++) - m_pBounds[i + 1] = pArray->GetFloatAt(i); - m_pBounds[nSubs] = m_pDomains[1]; - m_pEncode = FX_Alloc2D(FX_FLOAT, nSubs, 2); - pArray = pDict->GetArrayFor("Encode"); - if (!pArray) - return false; - - for (uint32_t i = 0; i < nSubs * 2; i++) - m_pEncode[i] = pArray->GetFloatAt(i); - return true; -} - -bool CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const { - FX_FLOAT input = inputs[0]; - size_t i; - for (i = 0; i < m_pSubFunctions.size() - 1; i++) { - if (input < m_pBounds[i + 1]) - break; - } - input = PDF_Interpolate(input, m_pBounds[i], m_pBounds[i + 1], - m_pEncode[i * 2], m_pEncode[i * 2 + 1]); - int nresults; - m_pSubFunctions[i]->Call(&input, kRequiredNumInputs, outputs, nresults); - return true; -} - -// static -std::unique_ptr CPDF_Function::Load(CPDF_Object* pFuncObj) { - std::unique_ptr pFunc; - if (!pFuncObj) - return pFunc; - - int iType = -1; - if (CPDF_Stream* pStream = pFuncObj->AsStream()) - iType = pStream->GetDict()->GetIntegerFor("FunctionType"); - else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary()) - iType = pDict->GetIntegerFor("FunctionType"); - - Type type = IntegerToFunctionType(iType); - if (type == Type::kType0Sampled) - pFunc = pdfium::MakeUnique(); - else if (type == Type::kType2ExpotentialInterpolation) - pFunc = pdfium::MakeUnique(); - else if (type == Type::kType3Stitching) - pFunc = pdfium::MakeUnique(); - else if (type == Type::kType4PostScript) - pFunc = pdfium::MakeUnique(); - - if (!pFunc || !pFunc->Init(pFuncObj)) - return nullptr; - - return pFunc; -} - -// static -CPDF_Function::Type CPDF_Function::IntegerToFunctionType(int iType) { - switch (iType) { - case 0: - case 2: - case 3: - case 4: - return static_cast(iType); - default: - return Type::kTypeInvalid; - } -} - -CPDF_Function::CPDF_Function(Type type) - : m_pDomains(nullptr), m_pRanges(nullptr), m_Type(type) {} - -CPDF_Function::~CPDF_Function() { - FX_Free(m_pDomains); - FX_Free(m_pRanges); -} - -bool CPDF_Function::Init(CPDF_Object* pObj) { - CPDF_Stream* pStream = pObj->AsStream(); - CPDF_Dictionary* pDict = pStream ? pStream->GetDict() : pObj->AsDictionary(); - - CPDF_Array* pDomains = pDict->GetArrayFor("Domain"); - if (!pDomains) - return false; - - m_nInputs = pDomains->GetCount() / 2; - if (m_nInputs == 0) - return false; - - m_pDomains = FX_Alloc2D(FX_FLOAT, m_nInputs, 2); - for (uint32_t i = 0; i < m_nInputs * 2; i++) { - m_pDomains[i] = pDomains->GetFloatAt(i); - } - CPDF_Array* pRanges = pDict->GetArrayFor("Range"); - m_nOutputs = 0; - if (pRanges) { - m_nOutputs = pRanges->GetCount() / 2; - m_pRanges = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2); - for (uint32_t i = 0; i < m_nOutputs * 2; i++) - m_pRanges[i] = pRanges->GetFloatAt(i); - } - uint32_t old_outputs = m_nOutputs; - if (!v_Init(pObj)) - return false; - if (m_pRanges && m_nOutputs > old_outputs) { - m_pRanges = FX_Realloc(FX_FLOAT, m_pRanges, m_nOutputs * 2); - if (m_pRanges) { - FXSYS_memset(m_pRanges + (old_outputs * 2), 0, - sizeof(FX_FLOAT) * (m_nOutputs - old_outputs) * 2); - } - } - return true; -} - -bool CPDF_Function::Call(FX_FLOAT* inputs, - uint32_t ninputs, - FX_FLOAT* results, - int& nresults) const { - if (m_nInputs != ninputs) { - return false; - } - nresults = m_nOutputs; - for (uint32_t i = 0; i < m_nInputs; i++) { - if (inputs[i] < m_pDomains[i * 2]) - inputs[i] = m_pDomains[i * 2]; - else if (inputs[i] > m_pDomains[i * 2 + 1]) - inputs[i] = m_pDomains[i * 2] + 1; - } - v_Call(inputs, results); - if (m_pRanges) { - for (uint32_t i = 0; i < m_nOutputs; i++) { - if (results[i] < m_pRanges[i * 2]) - results[i] = m_pRanges[i * 2]; - else if (results[i] > m_pRanges[i * 2 + 1]) - results[i] = m_pRanges[i * 2 + 1]; - } - } - return true; -} - -const CPDF_SampledFunc* CPDF_Function::ToSampledFunc() const { - return m_Type == Type::kType0Sampled - ? static_cast(this) - : nullptr; -} - -const CPDF_ExpIntFunc* CPDF_Function::ToExpIntFunc() const { - return m_Type == Type::kType2ExpotentialInterpolation - ? static_cast(this) - : nullptr; -} - -const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const { - return m_Type == Type::kType3Stitching - ? static_cast(this) - : nullptr; -} diff --git a/core/fpdfapi/page/pageint.h b/core/fpdfapi/page/pageint.h deleted file mode 100644 index 6700633604a58b0f4c72aa651eb374ad036666de..0000000000000000000000000000000000000000 --- a/core/fpdfapi/page/pageint.h +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FPDFAPI_PAGE_PAGEINT_H_ -#define CORE_FPDFAPI_PAGE_PAGEINT_H_ - -#include -#include - -#include "core/fpdfapi/page/cpdf_colorspace.h" -#include "core/fpdfapi/page/cpdf_countedobject.h" - -class CPDF_ExpIntFunc; -class CPDF_Pattern; -class CPDF_SampledFunc; -class CPDF_StitchFunc; -class CPDF_StreamAcc; - -class CPDF_Function { - public: - enum class Type { - kTypeInvalid = -1, - kType0Sampled = 0, - kType2ExpotentialInterpolation = 2, - kType3Stitching = 3, - kType4PostScript = 4, - }; - - static std::unique_ptr Load(CPDF_Object* pFuncObj); - static Type IntegerToFunctionType(int iType); - - virtual ~CPDF_Function(); - bool Call(FX_FLOAT* inputs, - uint32_t ninputs, - FX_FLOAT* results, - int& nresults) const; - uint32_t CountInputs() const { return m_nInputs; } - uint32_t CountOutputs() const { return m_nOutputs; } - FX_FLOAT GetDomain(int i) const { return m_pDomains[i]; } - FX_FLOAT GetRange(int i) const { return m_pRanges[i]; } - - const CPDF_SampledFunc* ToSampledFunc() const; - const CPDF_ExpIntFunc* ToExpIntFunc() const; - const CPDF_StitchFunc* ToStitchFunc() const; - - protected: - explicit CPDF_Function(Type type); - - bool Init(CPDF_Object* pObj); - virtual bool v_Init(CPDF_Object* pObj) = 0; - virtual bool v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const = 0; - - uint32_t m_nInputs; - uint32_t m_nOutputs; - FX_FLOAT* m_pDomains; - FX_FLOAT* m_pRanges; - const Type m_Type; -}; - -class CPDF_ExpIntFunc : public CPDF_Function { - public: - CPDF_ExpIntFunc(); - ~CPDF_ExpIntFunc() override; - - // CPDF_Function - bool v_Init(CPDF_Object* pObj) override; - bool v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - - uint32_t m_nOrigOutputs; - FX_FLOAT m_Exponent; - FX_FLOAT* m_pBeginValues; - FX_FLOAT* m_pEndValues; -}; - -class CPDF_SampledFunc : public CPDF_Function { - public: - struct SampleEncodeInfo { - FX_FLOAT encode_max; - FX_FLOAT encode_min; - uint32_t sizes; - }; - - struct SampleDecodeInfo { - FX_FLOAT decode_max; - FX_FLOAT decode_min; - }; - - CPDF_SampledFunc(); - ~CPDF_SampledFunc() override; - - // CPDF_Function - bool v_Init(CPDF_Object* pObj) override; - bool v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - - const std::vector& GetEncodeInfo() const { - return m_EncodeInfo; - } - uint32_t GetBitsPerSample() const { return m_nBitsPerSample; } - const CPDF_StreamAcc* GetSampleStream() const { - return m_pSampleStream.get(); - } - - private: - std::vector m_EncodeInfo; - std::vector m_DecodeInfo; - uint32_t m_nBitsPerSample; - uint32_t m_SampleMax; - std::unique_ptr m_pSampleStream; -}; - -class CPDF_StitchFunc : public CPDF_Function { - public: - CPDF_StitchFunc(); - ~CPDF_StitchFunc() override; - - // CPDF_Function - bool v_Init(CPDF_Object* pObj) override; - bool v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - - const std::vector>& GetSubFunctions() const { - return m_pSubFunctions; - } - FX_FLOAT GetBound(size_t i) const { return m_pBounds[i]; } - - private: - std::vector> m_pSubFunctions; - FX_FLOAT* m_pBounds; - FX_FLOAT* m_pEncode; - - static const uint32_t kRequiredNumInputs = 1; -}; - -class CPDF_IccProfile { - public: - CPDF_IccProfile(const uint8_t* pData, uint32_t dwSize); - ~CPDF_IccProfile(); - uint32_t GetComponents() const { return m_nSrcComponents; } - bool m_bsRGB; - void* m_pTransform; - - private: - uint32_t m_nSrcComponents; -}; - -class CPDF_DeviceCS : public CPDF_ColorSpace { - public: - CPDF_DeviceCS(CPDF_Document* pDoc, int family); - - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - bool SetRGB(FX_FLOAT* pBuf, - FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B) const override; - bool v_GetCMYK(FX_FLOAT* pBuf, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k) const override; - bool v_SetCMYK(FX_FLOAT* pBuf, - FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k) const override; - void TranslateImageLine(uint8_t* pDestBuf, - const uint8_t* pSrcBuf, - int pixels, - int image_width, - int image_height, - bool bTransMask = false) const override; -}; - -class CPDF_PatternCS : public CPDF_ColorSpace { - public: - explicit CPDF_PatternCS(CPDF_Document* pDoc); - ~CPDF_PatternCS() override; - bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; - bool GetRGB(FX_FLOAT* pBuf, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) const override; - CPDF_ColorSpace* GetBaseCS() const override; - - private: - CPDF_ColorSpace* m_pBaseCS; - CPDF_CountedColorSpace* m_pCountedBaseCS; -}; - -#define MAX_PATTERN_COLORCOMPS 16 -struct PatternValue { - CPDF_Pattern* m_pPattern; - CPDF_CountedPattern* m_pCountedPattern; - int m_nComps; - FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS]; -}; - -CFX_ByteStringC PDF_FindKeyAbbreviationForTesting(const CFX_ByteStringC& abbr); -CFX_ByteStringC PDF_FindValueAbbreviationForTesting( - const CFX_ByteStringC& abbr); - -#endif // CORE_FPDFAPI_PAGE_PAGEINT_H_ diff --git a/core/fpdfapi/parser/cfdf_document.cpp b/core/fpdfapi/parser/cfdf_document.cpp index 65755520c08d7c6cbb0eb24ef721bd560c98a4c7..f6af4546d707bf979b6ae1f6ef8c766f75941237 100644 --- a/core/fpdfapi/parser/cfdf_document.cpp +++ b/core/fpdfapi/parser/cfdf_document.cpp @@ -7,11 +7,14 @@ #include "core/fpdfapi/parser/cfdf_document.h" #include +#include #include #include "core/fpdfapi/edit/cpdf_creator.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_syntax_parser.h" +#include "core/fpdfapi/parser/fpdf_parser_utility.h" +#include "core/fxcrt/cfx_memorystream.h" #include "third_party/base/ptr_util.h" CFDF_Document::CFDF_Document() @@ -26,29 +29,21 @@ std::unique_ptr CFDF_Document::CreateNewDoc() { return pDoc; } -std::unique_ptr CFDF_Document::ParseFile( - const CFX_RetainPtr& pFile) { - if (!pFile) - return nullptr; - - auto pDoc = pdfium::MakeUnique(); - pDoc->ParseStream(pFile); - return pDoc->m_pRootDict ? std::move(pDoc) : nullptr; -} - std::unique_ptr CFDF_Document::ParseMemory(uint8_t* pData, uint32_t size) { - return CFDF_Document::ParseFile(IFX_MemoryStream::Create(pData, size)); + auto pDoc = pdfium::MakeUnique(); + pDoc->ParseStream(pdfium::MakeRetain(pData, size, false)); + return pDoc->m_pRootDict ? std::move(pDoc) : nullptr; } void CFDF_Document::ParseStream( - const CFX_RetainPtr& pFile) { + const RetainPtr& pFile) { m_pFile = pFile; CPDF_SyntaxParser parser; parser.InitParser(m_pFile, 0); while (1) { bool bNumber; - CFX_ByteString word = parser.GetNextWord(&bNumber); + ByteString word = parser.GetNextWord(&bNumber); if (bNumber) { uint32_t objnum = FXSYS_atoui(word.c_str()); if (!objnum) @@ -62,8 +57,7 @@ void CFDF_Document::ParseStream( if (word != "obj") break; - std::unique_ptr pObj = - parser.GetObject(this, objnum, 0, true); + std::unique_ptr pObj = parser.GetObjectBody(this); if (!pObj) break; @@ -76,7 +70,7 @@ void CFDF_Document::ParseStream( break; std::unique_ptr pMainDict = - ToDictionary(parser.GetObject(this, 0, 0, true)); + ToDictionary(parser.GetObjectBody(this)); if (pMainDict) m_pRootDict = pMainDict->GetDictFor("Root"); @@ -85,10 +79,11 @@ void CFDF_Document::ParseStream( } } -bool CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const { +ByteString CFDF_Document::WriteToString() const { if (!m_pRootDict) - return false; + return ByteString(); + std::ostringstream buf; buf << "%FDF-1.2\r\n"; for (const auto& pair : *this) buf << pair.first << " 0 obj\r\n" @@ -96,5 +91,6 @@ bool CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const { buf << "trailer\r\n<GetObjNum() << " 0 R>>\r\n%%EOF\r\n"; - return true; + + return ByteString(buf); } diff --git a/core/fpdfapi/parser/cfdf_document.h b/core/fpdfapi/parser/cfdf_document.h index f83adc1a30818653a720ede18ae8cee8752918a3..b2cbd5bae99fc477311f40e972e0fffeca606939 100644 --- a/core/fpdfapi/parser/cfdf_document.h +++ b/core/fpdfapi/parser/cfdf_document.h @@ -11,29 +11,28 @@ #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; +class IFX_SeekableReadStream; class CFDF_Document : public CPDF_IndirectObjectHolder { public: static std::unique_ptr CreateNewDoc(); - static std::unique_ptr ParseFile( - const CFX_RetainPtr& pFile); static std::unique_ptr ParseMemory(uint8_t* pData, uint32_t size); CFDF_Document(); ~CFDF_Document() override; - bool WriteBuf(CFX_ByteTextBuf& buf) const; - CPDF_Dictionary* GetRoot() const { return m_pRootDict; } + ByteString WriteToString() const; + CPDF_Dictionary* GetRoot() const { return m_pRootDict.Get(); } protected: - void ParseStream(const CFX_RetainPtr& pFile); + void ParseStream(const RetainPtr& pFile); - CPDF_Dictionary* m_pRootDict; - CFX_RetainPtr m_pFile; + UnownedPtr m_pRootDict; + RetainPtr m_pFile; }; #endif // CORE_FPDFAPI_PARSER_CFDF_DOCUMENT_H_ diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp index 05a93702f17f01b587e3901ea2b614b94241d1fd..5a5cdc9be040b00921e0ee60596d2888f4585a0f 100644 --- a/core/fpdfapi/parser/cpdf_array.cpp +++ b/core/fpdfapi/parser/cpdf_array.cpp @@ -14,13 +14,13 @@ #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/logging.h" #include "third_party/base/stl_util.h" CPDF_Array::CPDF_Array() {} -CPDF_Array::CPDF_Array(const CFX_WeakPtr& pPool) - : m_pPool(pPool) {} +CPDF_Array::CPDF_Array(const WeakPtr& pPool) : m_pPool(pPool) {} CPDF_Array::~CPDF_Array() { // Break cycles for cyclic references. @@ -57,8 +57,11 @@ std::unique_ptr CPDF_Array::CloneNonCyclic( pVisited->insert(this); auto pCopy = pdfium::MakeUnique(); for (const auto& pValue : m_Objects) { - if (!pdfium::ContainsKey(*pVisited, pValue.get())) - pCopy->m_Objects.push_back(pValue->CloneNonCyclic(bDirect, pVisited)); + if (!pdfium::ContainsKey(*pVisited, pValue.get())) { + std::set visited(*pVisited); + if (auto obj = pValue->CloneNonCyclic(bDirect, &visited)) + pCopy->m_Objects.push_back(std::move(obj)); + } } return std::move(pCopy); } @@ -96,19 +99,25 @@ CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t i) const { return m_Objects[i]->GetDirect(); } -CFX_ByteString CPDF_Array::GetStringAt(size_t i) const { +ByteString CPDF_Array::GetStringAt(size_t i) const { if (i >= m_Objects.size()) - return CFX_ByteString(); + return ByteString(); return m_Objects[i]->GetString(); } +WideString CPDF_Array::GetUnicodeTextAt(size_t i) const { + if (i >= m_Objects.size()) + return WideString(); + return m_Objects[i]->GetUnicodeText(); +} + int CPDF_Array::GetIntegerAt(size_t i) const { if (i >= m_Objects.size()) return 0; return m_Objects[i]->GetInteger(); } -FX_FLOAT CPDF_Array::GetNumberAt(size_t i) const { +float CPDF_Array::GetNumberAt(size_t i) const { if (i >= m_Objects.size()) return 0; return m_Objects[i]->GetNumber(); @@ -133,14 +142,13 @@ CPDF_Array* CPDF_Array::GetArrayAt(size_t i) const { return ToArray(GetDirectObjectAt(i)); } -void CPDF_Array::RemoveAt(size_t i, size_t nCount) { - if (i >= m_Objects.size()) - return; - - if (nCount <= 0 || nCount > m_Objects.size() - i) - return; +void CPDF_Array::Clear() { + m_Objects.clear(); +} - m_Objects.erase(m_Objects.begin() + i, m_Objects.begin() + i + nCount); +void CPDF_Array::RemoveAt(size_t i) { + if (i < m_Objects.size()) + m_Objects.erase(m_Objects.begin() + i); } void CPDF_Array::ConvertToIndirectObjectAt(size_t i, @@ -159,7 +167,7 @@ CPDF_Object* CPDF_Array::SetAt(size_t i, std::unique_ptr pObj) { ASSERT(IsArray()); ASSERT(!pObj || pObj->IsInline()); if (i >= m_Objects.size()) { - ASSERT(false); + NOTREACHED(); return nullptr; } CPDF_Object* pRet = pObj.get(); @@ -190,3 +198,22 @@ CPDF_Object* CPDF_Array::Add(std::unique_ptr pObj) { m_Objects.push_back(std::move(pObj)); return pRet; } + +bool CPDF_Array::WriteTo(IFX_ArchiveStream* archive) const { + if (!archive->WriteString("[")) + return false; + + for (size_t i = 0; i < GetCount(); ++i) { + CPDF_Object* pElement = GetObjectAt(i); + if (!pElement->IsInline()) { + if (!archive->WriteString(" ") || + !archive->WriteDWord(pElement->GetObjNum()) || + !archive->WriteString(" 0 R")) { + return false; + } + } else if (!pElement->WriteTo(archive)) { + return false; + } + } + return archive->WriteString("]"); +} diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h index 0b16f7f21b603448f7f2096a3f5b531603db727d..bf8cb426c49b051c06e0c298ffe81ae155534979 100644 --- a/core/fpdfapi/parser/cpdf_array.h +++ b/core/fpdfapi/parser/cpdf_array.h @@ -15,7 +15,6 @@ #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" #include "third_party/base/ptr_util.h" @@ -25,7 +24,7 @@ class CPDF_Array : public CPDF_Object { std::vector>::const_iterator; CPDF_Array(); - explicit CPDF_Array(const CFX_WeakPtr& pPool); + explicit CPDF_Array(const WeakPtr& pPool); ~CPDF_Array() override; // CPDF_Object: @@ -34,18 +33,20 @@ class CPDF_Array : public CPDF_Object { bool IsArray() const override; CPDF_Array* AsArray() override; const CPDF_Array* AsArray() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; bool IsEmpty() const { return m_Objects.empty(); } size_t GetCount() const { return m_Objects.size(); } CPDF_Object* GetObjectAt(size_t index) const; CPDF_Object* GetDirectObjectAt(size_t index) const; - CFX_ByteString GetStringAt(size_t index) const; + ByteString GetStringAt(size_t index) const; + WideString GetUnicodeTextAt(size_t index) const; int GetIntegerAt(size_t index) const; - FX_FLOAT GetNumberAt(size_t index) const; + float GetNumberAt(size_t index) const; CPDF_Dictionary* GetDictAt(size_t index) const; CPDF_Stream* GetStreamAt(size_t index) const; CPDF_Array* GetArrayAt(size_t index) const; - FX_FLOAT GetFloatAt(size_t index) const { return GetNumberAt(index); } + float GetFloatAt(size_t index) const { return GetNumberAt(index); } CFX_Matrix GetMatrix(); CFX_FloatRect GetRect(); @@ -98,7 +99,8 @@ class CPDF_Array : public CPDF_Object { index, pdfium::MakeUnique(m_pPool, std::forward(args)...))); } - void RemoveAt(size_t index, size_t nCount = 1); + void Clear(); + void RemoveAt(size_t index); void ConvertToIndirectObjectAt(size_t index, CPDF_IndirectObjectHolder* pDoc); const_iterator begin() const { return m_Objects.begin(); } @@ -110,7 +112,7 @@ class CPDF_Array : public CPDF_Object { std::set* pVisited) const override; std::vector> m_Objects; - CFX_WeakPtr m_pPool; + WeakPtr m_pPool; }; inline CPDF_Array* ToArray(CPDF_Object* obj) { diff --git a/core/fpdfapi/parser/cpdf_array_unittest.cpp b/core/fpdfapi/parser/cpdf_array_unittest.cpp index 46777289b53d8ef8e4ce8c2c871cbc0ee4b68943..4ce66dcadb6ac45b56f53ac17b1d6dd04733e94c 100644 --- a/core/fpdfapi/parser/cpdf_array_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_array_unittest.cpp @@ -14,52 +14,59 @@ TEST(cpdf_array, RemoveAt) { { - int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::unique_ptr arr(new CPDF_Array); + const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + auto arr = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(elems); ++i) arr->AddNew(elems[i]); - arr->RemoveAt(3, 3); - int expected[] = {1, 2, 3, 7, 8, 9, 10}; - EXPECT_EQ(FX_ArraySize(expected), arr->GetCount()); + for (size_t i = 0; i < 3; ++i) + arr->RemoveAt(3); + const int expected[] = {1, 2, 3, 7, 8, 9, 10}; + ASSERT_EQ(FX_ArraySize(expected), arr->GetCount()); for (size_t i = 0; i < FX_ArraySize(expected); ++i) EXPECT_EQ(expected[i], arr->GetIntegerAt(i)); - arr->RemoveAt(4, 2); - int expected2[] = {1, 2, 3, 7, 10}; - EXPECT_EQ(FX_ArraySize(expected2), arr->GetCount()); + arr->RemoveAt(4); + arr->RemoveAt(4); + const int expected2[] = {1, 2, 3, 7, 10}; + ASSERT_EQ(FX_ArraySize(expected2), arr->GetCount()); for (size_t i = 0; i < FX_ArraySize(expected2); ++i) EXPECT_EQ(expected2[i], arr->GetIntegerAt(i)); } { - // When the range is out of bound, RemoveAt has no effect. - int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::unique_ptr arr(new CPDF_Array); + // When the range is out of bound, RemoveAt() has no effect. + const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + auto arr = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(elems); ++i) arr->AddNew(elems[i]); - arr->RemoveAt(8, 5); - EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); - for (size_t i = 0; i < FX_ArraySize(elems); ++i) - EXPECT_EQ(elems[i], arr->GetIntegerAt(i)); - arr->RemoveAt(0, 12); - EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); - arr->RemoveAt(11, 1); + arr->RemoveAt(11); EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); } } +TEST(cpdf_array, Clear) { + const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + auto arr = pdfium::MakeUnique(); + EXPECT_EQ(0U, arr->GetCount()); + for (size_t i = 0; i < FX_ArraySize(elems); ++i) + arr->AddNew(elems[i]); + EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); + arr->Clear(); + EXPECT_EQ(0U, arr->GetCount()); +} + TEST(cpdf_array, InsertAt) { { - int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; auto arr = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(elems); ++i) arr->InsertNewAt(i, elems[i]); - EXPECT_EQ(FX_ArraySize(elems), arr->GetCount()); + ASSERT_EQ(FX_ArraySize(elems), arr->GetCount()); for (size_t i = 0; i < FX_ArraySize(elems); ++i) EXPECT_EQ(elems[i], arr->GetIntegerAt(i)); arr->InsertNewAt(3, 33); arr->InsertNewAt(6, 55); arr->InsertNewAt(12, 12); - int expected[] = {1, 2, 3, 33, 4, 5, 55, 6, 7, 8, 9, 10, 12}; - EXPECT_EQ(FX_ArraySize(expected), arr->GetCount()); + const int expected[] = {1, 2, 3, 33, 4, 5, 55, 6, 7, 8, 9, 10, 12}; + ASSERT_EQ(FX_ArraySize(expected), arr->GetCount()); for (size_t i = 0; i < FX_ArraySize(expected); ++i) EXPECT_EQ(expected[i], arr->GetIntegerAt(i)); } @@ -67,12 +74,12 @@ TEST(cpdf_array, InsertAt) { // When the position to insert is beyond the upper bound, // an element is inserted at that position while other unfilled // positions have nullptr. - int elems[] = {1, 2}; + const int elems[] = {1, 2}; auto arr = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(elems); ++i) arr->InsertNewAt(i, elems[i]); arr->InsertNewAt(10, 10); - EXPECT_EQ(11u, arr->GetCount()); + ASSERT_EQ(11u, arr->GetCount()); for (size_t i = 0; i < FX_ArraySize(elems); ++i) EXPECT_EQ(elems[i], arr->GetIntegerAt(i)); for (size_t i = FX_ArraySize(elems); i < 10; ++i) @@ -84,12 +91,12 @@ TEST(cpdf_array, InsertAt) { TEST(cpdf_array, Clone) { { // Basic case. - int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + const int elems[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; auto arr = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(elems); ++i) arr->InsertNewAt(i, elems[i]); std::unique_ptr arr2 = ToArray(arr->Clone()); - EXPECT_EQ(arr->GetCount(), arr2->GetCount()); + ASSERT_EQ(arr->GetCount(), arr2->GetCount()); for (size_t i = 0; i < FX_ArraySize(elems); ++i) { // Clone() always create new objects. EXPECT_NE(arr->GetObjectAt(i), arr2->GetObjectAt(i)); @@ -100,16 +107,15 @@ TEST(cpdf_array, Clone) { // Clone() with and without dereferencing reference objects. static const size_t kNumOfRows = 3; static const size_t kNumOfRowElems = 5; - int elems[kNumOfRows][kNumOfRowElems] = { + const int elems[kNumOfRows][kNumOfRowElems] = { {1, 2, 3, 4, 5}, {10, 9, 8, 7, 6}, {11, 12, 13, 14, 15}}; - std::unique_ptr arr(new CPDF_Array); + auto arr = pdfium::MakeUnique(); // Indirect references to indirect objects. - std::unique_ptr obj_holder( - new CPDF_IndirectObjectHolder()); + auto obj_holder = pdfium::MakeUnique(); for (size_t i = 0; i < kNumOfRows; ++i) { auto arr_elem = pdfium::MakeUnique(); for (size_t j = 0; j < kNumOfRowElems; ++j) { - std::unique_ptr obj(new CPDF_Number(elems[i][j])); + auto obj = pdfium::MakeUnique(elems[i][j]); // Starts object number from 1. int obj_num = i * kNumOfRowElems + j + 1; obj_holder->ReplaceIndirectObjectIfHigherGeneration(obj_num, @@ -122,10 +128,10 @@ TEST(cpdf_array, Clone) { // Not dereferencing reference objects means just creating new references // instead of new copies of direct objects. std::unique_ptr arr1 = ToArray(arr->Clone()); - EXPECT_EQ(arr->GetCount(), arr1->GetCount()); + ASSERT_EQ(arr->GetCount(), arr1->GetCount()); // Dereferencing reference objects creates new copies of direct objects. std::unique_ptr arr2 = ToArray(arr->CloneDirectObject()); - EXPECT_EQ(arr->GetCount(), arr2->GetCount()); + ASSERT_EQ(arr->GetCount(), arr2->GetCount()); for (size_t i = 0; i < kNumOfRows; ++i) { CPDF_Array* arr_elem = arr->GetObjectAt(i)->AsArray(); CPDF_Array* arr1_elem = arr1->GetObjectAt(i)->AsArray(); @@ -133,9 +139,9 @@ TEST(cpdf_array, Clone) { EXPECT_NE(arr_elem, arr1_elem); EXPECT_NE(arr_elem, arr2_elem); for (size_t j = 0; j < kNumOfRowElems; ++j) { - auto elem_obj = arr_elem->GetObjectAt(j); - auto elem_obj1 = arr1_elem->GetObjectAt(j); - auto elem_obj2 = arr2_elem->GetObjectAt(j); + auto* elem_obj = arr_elem->GetObjectAt(j); + auto* elem_obj1 = arr1_elem->GetObjectAt(j); + auto* elem_obj2 = arr2_elem->GetObjectAt(j); // Results from not deferencing reference objects. EXPECT_NE(elem_obj, elem_obj1); EXPECT_TRUE(elem_obj1->IsReference()); @@ -154,7 +160,7 @@ TEST(cpdf_array, Clone) { for (size_t i = 0; i < kNumOfRows; ++i) { for (size_t j = 0; j < kNumOfRowElems; ++j) { // Results from not deferencing reference objects. - auto elem_obj1 = arr1->GetObjectAt(i)->AsArray()->GetObjectAt(j); + auto* elem_obj1 = arr1->GetObjectAt(i)->AsArray()->GetObjectAt(j); EXPECT_TRUE(elem_obj1->IsReference()); EXPECT_EQ(elems[i][j], elem_obj1->GetInteger()); // Results from deferencing reference objects. @@ -166,12 +172,13 @@ TEST(cpdf_array, Clone) { } TEST(cpdf_array, Iterator) { - int elems[] = {-23, -11, 3, 455, 2345877, - 0, 7895330, -12564334, 10000, -100000}; - std::unique_ptr arr(new CPDF_Array); + const int elems[] = {-23, -11, 3, 455, 2345877, + 0, 7895330, -12564334, 10000, -100000}; + auto arr = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(elems); ++i) arr->InsertNewAt(i, elems[i]); size_t index = 0; for (const auto& it : *arr) EXPECT_EQ(elems[index++], it->AsNumber()->GetInteger()); + EXPECT_EQ(FX_ArraySize(elems), index); } diff --git a/core/fpdfapi/parser/cpdf_boolean.cpp b/core/fpdfapi/parser/cpdf_boolean.cpp index 0204fd9eb0c4659dc7f4bb4cd3adada11fbe70b8..a1dc450519d679f74208974c86fd2cc03e25c329 100644 --- a/core/fpdfapi/parser/cpdf_boolean.cpp +++ b/core/fpdfapi/parser/cpdf_boolean.cpp @@ -5,6 +5,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fpdfapi/parser/cpdf_boolean.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" CPDF_Boolean::CPDF_Boolean() : m_bValue(false) {} @@ -21,7 +22,7 @@ std::unique_ptr CPDF_Boolean::Clone() const { return pdfium::MakeUnique(m_bValue); } -CFX_ByteString CPDF_Boolean::GetString() const { +ByteString CPDF_Boolean::GetString() const { return m_bValue ? "true" : "false"; } @@ -29,7 +30,7 @@ int CPDF_Boolean::GetInteger() const { return m_bValue; } -void CPDF_Boolean::SetString(const CFX_ByteString& str) { +void CPDF_Boolean::SetString(const ByteString& str) { m_bValue = (str == "true"); } @@ -44,3 +45,8 @@ CPDF_Boolean* CPDF_Boolean::AsBoolean() { const CPDF_Boolean* CPDF_Boolean::AsBoolean() const { return this; } + +bool CPDF_Boolean::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" ") && + archive->WriteString(GetString().AsStringView()); +} diff --git a/core/fpdfapi/parser/cpdf_boolean.h b/core/fpdfapi/parser/cpdf_boolean.h index afebc29448cdd6e1c2e06b3d4f932736417887ce..c0a69d89320a2220464c63a8550b1b9ec442e515 100644 --- a/core/fpdfapi/parser/cpdf_boolean.h +++ b/core/fpdfapi/parser/cpdf_boolean.h @@ -22,12 +22,13 @@ class CPDF_Boolean : public CPDF_Object { // CPDF_Object: Type GetType() const override; std::unique_ptr Clone() const override; - CFX_ByteString GetString() const override; + ByteString GetString() const override; int GetInteger() const override; - void SetString(const CFX_ByteString& str) override; + void SetString(const ByteString& str) override; bool IsBoolean() const override; CPDF_Boolean* AsBoolean() override; const CPDF_Boolean* AsBoolean() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; protected: bool m_bValue; diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be9818ae210b0f6a220fc462485d7392299fd563 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp @@ -0,0 +1,211 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_cross_ref_avail.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_syntax_parser.h" +#include "core/fpdfapi/parser/fpdf_parser_utility.h" + +namespace { + +constexpr char kCrossRefKeyword[] = "xref"; +constexpr char kTrailerKeyword[] = "trailer"; +constexpr char kPrevCrossRefFieldKey[] = "Prev"; +constexpr char kTypeFieldKey[] = "Type"; +constexpr char kPrevCrossRefStreamOffsetFieldKey[] = "XRefStm"; +constexpr char kXRefKeyword[] = "XRef"; +constexpr char kEncryptKey[] = "Encrypt"; + +} // namespace + +CPDF_CrossRefAvail::CPDF_CrossRefAvail(CPDF_SyntaxParser* parser, + FX_FILESIZE last_crossref_offset) + : parser_(parser), last_crossref_offset_(last_crossref_offset) { + ASSERT(parser_); + AddCrossRefForCheck(last_crossref_offset); +} + +CPDF_CrossRefAvail::~CPDF_CrossRefAvail() {} + +CPDF_DataAvail::DocAvailStatus CPDF_CrossRefAvail::CheckAvail() { + if (current_status_ == CPDF_DataAvail::DataAvailable) + return CPDF_DataAvail::DataAvailable; + + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); + while (true) { + bool check_result = false; + switch (current_state_) { + case State::kCrossRefCheck: + check_result = CheckCrossRef(); + break; + case State::kCrossRefV4ItemCheck: + check_result = CheckCrossRefV4Item(); + break; + case State::kCrossRefV4TrailerCheck: + check_result = CheckCrossRefV4Trailer(); + break; + case State::kDone: + break; + default: { + current_status_ = CPDF_DataAvail::DataError; + NOTREACHED(); + break; + } + } + if (!check_result) + break; + + ASSERT(!GetValidator()->has_read_problems()); + } + return current_status_; +} + +bool CPDF_CrossRefAvail::CheckReadProblems() { + if (GetValidator()->read_error()) { + current_status_ = CPDF_DataAvail::DataError; + return true; + } + return GetValidator()->has_unavailable_data(); +} + +bool CPDF_CrossRefAvail::CheckCrossRef() { + if (cross_refs_for_check_.empty()) { + // All cross refs were checked. + current_state_ = State::kDone; + current_status_ = CPDF_DataAvail::DataAvailable; + return true; + } + parser_->SetPos(cross_refs_for_check_.front()); + + const ByteString first_word = parser_->PeekNextWord(nullptr); + if (CheckReadProblems()) + return false; + + const bool result = (first_word == kCrossRefKeyword) ? CheckCrossRefV4() + : CheckCrossRefStream(); + + if (result) + cross_refs_for_check_.pop(); + + return result; +} + +bool CPDF_CrossRefAvail::CheckCrossRefV4() { + const ByteString keyword = parser_->GetKeyword(); + if (CheckReadProblems()) + return false; + + if (keyword != kCrossRefKeyword) { + current_status_ = CPDF_DataAvail::DataError; + return false; + } + + current_state_ = State::kCrossRefV4ItemCheck; + current_offset_ = parser_->GetPos(); + return true; +} + +bool CPDF_CrossRefAvail::CheckCrossRefV4Item() { + parser_->SetPos(current_offset_); + const ByteString keyword = parser_->GetKeyword(); + if (CheckReadProblems()) + return false; + + if (keyword.IsEmpty()) { + current_status_ = CPDF_DataAvail::DataError; + return false; + } + + if (keyword == kTrailerKeyword) + current_state_ = State::kCrossRefV4TrailerCheck; + + // Go to next item. + current_offset_ = parser_->GetPos(); + return true; +} + +bool CPDF_CrossRefAvail::CheckCrossRefV4Trailer() { + parser_->SetPos(current_offset_); + + std::unique_ptr trailer = + ToDictionary(parser_->GetObjectBody(nullptr)); + if (CheckReadProblems()) + return false; + + if (!trailer) { + current_status_ = CPDF_DataAvail::DataError; + return false; + } + + if (ToReference(trailer->GetObjectFor(kEncryptKey))) { + current_status_ = CPDF_DataAvail::DataError; + return false; + } + + const int32_t xrefpos = + GetDirectInteger(trailer.get(), kPrevCrossRefFieldKey); + if (xrefpos && + pdfium::base::IsValueInRangeForNumericType(xrefpos)) + AddCrossRefForCheck(static_cast(xrefpos)); + + const int32_t stream_xref_offset = + GetDirectInteger(trailer.get(), kPrevCrossRefStreamOffsetFieldKey); + if (stream_xref_offset && + pdfium::base::IsValueInRangeForNumericType( + stream_xref_offset)) + AddCrossRefForCheck(static_cast(stream_xref_offset)); + + // Goto check next crossref + current_state_ = State::kCrossRefCheck; + return true; +} + +bool CPDF_CrossRefAvail::CheckCrossRefStream() { + auto cross_ref = + parser_->GetIndirectObject(nullptr, CPDF_SyntaxParser::ParseType::kLoose); + if (CheckReadProblems()) + return false; + + const CPDF_Dictionary* trailer = + cross_ref && cross_ref->IsStream() ? cross_ref->GetDict() : nullptr; + if (!trailer) { + current_status_ = CPDF_DataAvail::DataError; + return false; + } + + if (ToReference(trailer->GetObjectFor(kEncryptKey))) { + current_status_ = CPDF_DataAvail::DataError; + return false; + } + + CPDF_Name* type_name = ToName(trailer->GetObjectFor(kTypeFieldKey)); + if (type_name && type_name->GetString() == kXRefKeyword) { + const int32_t xrefpos = trailer->GetIntegerFor(kPrevCrossRefFieldKey); + if (xrefpos && + pdfium::base::IsValueInRangeForNumericType(xrefpos)) + AddCrossRefForCheck(static_cast(xrefpos)); + } + // Goto check next crossref + current_state_ = State::kCrossRefCheck; + return true; +} + +void CPDF_CrossRefAvail::AddCrossRefForCheck(FX_FILESIZE crossref_offset) { + if (registered_crossrefs_.count(crossref_offset)) + return; + + cross_refs_for_check_.push(crossref_offset); + registered_crossrefs_.insert(crossref_offset); +} + +fxcrt::RetainPtr CPDF_CrossRefAvail::GetValidator() { + return parser_->GetValidator(); +} diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.h b/core/fpdfapi/parser/cpdf_cross_ref_avail.h new file mode 100644 index 0000000000000000000000000000000000000000..aad58f35e70d09ea24d988715b57e90335e583ee --- /dev/null +++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.h @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FPDFAPI_PARSER_CPDF_CROSS_REF_AVAIL_H_ +#define CORE_FPDFAPI_PARSER_CPDF_CROSS_REF_AVAIL_H_ + +#include +#include +#include + +#include "core/fpdfapi/parser/cpdf_data_avail.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPDF_SyntaxParser; + +class CPDF_CrossRefAvail { + public: + CPDF_CrossRefAvail(CPDF_SyntaxParser* parser, + FX_FILESIZE last_crossref_offset); + ~CPDF_CrossRefAvail(); + + FX_FILESIZE last_crossref_offset() const { return last_crossref_offset_; } + + CPDF_DataAvail::DocAvailStatus CheckAvail(); + + private: + enum class State { + kCrossRefCheck, + kCrossRefV4ItemCheck, + kCrossRefV4TrailerCheck, + kDone, + }; + + bool CheckReadProblems(); + bool CheckCrossRef(); + bool CheckCrossRefV4(); + bool CheckCrossRefV4Item(); + bool CheckCrossRefV4Trailer(); + bool CheckCrossRefStream(); + + void AddCrossRefForCheck(FX_FILESIZE crossref_offset); + + fxcrt::RetainPtr GetValidator(); + + fxcrt::UnownedPtr parser_; + const FX_FILESIZE last_crossref_offset_ = 0; + CPDF_DataAvail::DocAvailStatus current_status_ = + CPDF_DataAvail::DataNotAvailable; + State current_state_ = State::kCrossRefCheck; + FX_FILESIZE current_offset_ = 0; + std::queue cross_refs_for_check_; + std::set registered_crossrefs_; +}; + +#endif // CORE_FPDFAPI_PARSER_CPDF_CROSS_REF_AVAIL_H_ diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b798e173773460c2ed474802b86e0b40cf64e31f --- /dev/null +++ b/core/fpdfapi/parser/cpdf_cross_ref_avail_unittest.cpp @@ -0,0 +1,339 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_cross_ref_avail.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_syntax_parser.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +namespace { + +std::unique_ptr MakeParserForBuffer( + const unsigned char* buffer, + size_t buffer_size) { + auto parser = pdfium::MakeUnique(); + parser->InitParser( + pdfium::MakeRetain(buffer, buffer_size), 0); + return parser; +} + +} // namespace + +TEST(CPDF_CrossRefAvailTest, CheckCrossRefV4) { + const unsigned char xref_table[] = + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "0000000017 00000 n \n" + "0000000081 00000 n \n" + "0000000000 00007 f \n" + "0000000331 00000 n \n" + "0000000409 00000 n \n" + "trailer\n" + "<<4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16>>"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(xref_table, FX_ArraySize(xref_table)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + + EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, CheckCrossRefStream) { + const unsigned char xref_stream[] = + "16 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA\n" + "endstream\n" + "endobj\n"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + + EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, IncorrectStartOffset) { + const unsigned char xref_stream[] = + "16 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA\n" + "endstream\n" + "endobj\n"; + + const FX_FILESIZE last_crossref_offset = 70000; + + auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, IncorrectPrevOffset) { + const unsigned char xref_stream[] = + "16 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA\n" + "endstream\n" + "endobj\n"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, IncorrectPrevStreamOffset) { + const unsigned char xref_table[] = + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "0000000017 00000 n \n" + "0000000081 00000 n \n" + "0000000000 00007 f \n" + "0000000331 00000 n \n" + "0000000409 00000 n \n" + "trailer\n" + "<<4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16 /XRefStm 70000>>"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(xref_table, FX_ArraySize(xref_table)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, IncorrectData) { + const unsigned char incorrect_data[] = + "fiajaoilf w9ifaoihwoiafhja wfijaofijoiaw fhj oiawhfoiah " + "wfoihoiwfghouiafghwoigahfi"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = + MakeParserForBuffer(incorrect_data, FX_ArraySize(incorrect_data)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, ThreeCrossRefV4) { + char int_buffer[100]; + int prev_offset = 0; + int cur_offset = 0; + std::string table = "pdf blah blah blah\n"; + prev_offset = cur_offset; + cur_offset = static_cast(table.size()); + table += + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "trailer\n" + "<<4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16>>\n"; + table += "Dummy Data jgwhughouiwbahng"; + prev_offset = cur_offset; + cur_offset = static_cast(table.size()); + table += std::string( + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "trailer\n" + "<<" + "4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16" + "/Prev ") + + FXSYS_itoa(prev_offset, int_buffer, 10) + ">>\n"; + table += "More Dummy Data jgwhughouiwbahng"; + prev_offset = cur_offset; + cur_offset = static_cast(table.size()); + table += std::string( + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "trailer\n" + "<<" + "4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16" + "/Prev ") + + FXSYS_itoa(prev_offset, int_buffer, 10) + ">>\n"; + const FX_FILESIZE last_crossref_offset = cur_offset; + + auto parser = MakeParserForBuffer( + reinterpret_cast(table.data()), table.size()); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, ThreeCrossRefV5) { + char int_buffer[100]; + int prev_offset = 0; + int cur_offset = 0; + std::string table = "pdf blah blah blah\n"; + prev_offset = cur_offset; + cur_offset = static_cast(table.size()); + table += + "16 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA ahfcuabfkuabfu\n" + "endstream\n" + "endobj\n"; + table += "Dummy Data jgwhughouiwbahng"; + + prev_offset = cur_offset; + cur_offset = static_cast(table.size()); + table += std::string( + "55 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA\n" + "endstream\n" + "endobj\n"; + table += "More Dummy Data jgwhughouiwbahng"; + prev_offset = cur_offset; + cur_offset = static_cast(table.size()); + table += std::string( + "88 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA favav\n" + "endstream\n" + "endobj\n"; + const FX_FILESIZE last_crossref_offset = cur_offset; + + auto parser = MakeParserForBuffer( + reinterpret_cast(table.data()), table.size()); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, Mixed) { + char int_buffer[100]; + std::string table = "pdf blah blah blah\n"; + + const int first_v5_table_offset = static_cast(table.size()); + table += + "16 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA ahfcuabfkuabfu\n" + "endstream\n" + "endobj\n"; + table += "Dummy Data jgwhughouiwbahng"; + + const int second_v4_table_offset = static_cast(table.size()); + table += std::string( + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "trailer\n" + "<<" + "4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16" + "/Prev ") + + FXSYS_itoa(first_v5_table_offset, int_buffer, 10) + ">>\n"; + table += "More Dummy Data jgwhughouiwbahng"; + + const int last_v4_table_offset = static_cast(table.size()); + table += std::string( + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "trailer\n" + "<<" + "4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Info 15 0 R/Size 16" + "/Prev ") + + FXSYS_itoa(second_v4_table_offset, int_buffer, 10) + " /XRefStm " + + FXSYS_itoa(first_v5_table_offset, int_buffer, 10) + ">>\n"; + const FX_FILESIZE last_crossref_offset = last_v4_table_offset; + + auto parser = MakeParserForBuffer( + reinterpret_cast(table.data()), table.size()); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, CrossRefV5IsNotStream) { + const unsigned char invalid_xref_stream[] = + "16 0 obj\n" + "[/array /object]\n" + "endstream\n" + "endobj\n"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(invalid_xref_stream, + FX_ArraySize(invalid_xref_stream)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, CrossRefV4WithEncryptRef) { + const unsigned char xref_table[] = + "xref \n" + "0 6 \n" + "0000000003 65535 f \n" + "0000000017 00000 n \n" + "0000000081 00000 n \n" + "0000000000 00007 f \n" + "0000000331 00000 n \n" + "0000000409 00000 n \n" + "trailer\n" + "<<4f9bb2e7978401808f8f1f2a75c322c8>]" + "/Encrypt 77 0 R" + "/Info 15 0 R/Size 16>>"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(xref_table, FX_ArraySize(xref_table)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} + +TEST(CPDF_CrossRefAvailTest, CrossRefStreamWithEncryptRef) { + const unsigned char xref_stream[] = + "16 0 obj\n" + "<>" + " stream \n" + "STREAM DATA STREAM DATA STREAM DATA\n" + "endstream\n" + "endobj\n"; + const FX_FILESIZE last_crossref_offset = 0; + + auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); + auto cross_ref_avail = pdfium::MakeUnique( + parser.get(), last_crossref_offset); + EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); +} diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.cpp b/core/fpdfapi/parser/cpdf_crypto_handler.cpp index 61f78c4ee5c9a0087c2c5ed2d9a2fdf04fd8daff..d963df48878bcc91249785375d337bd33f87c4a0 100644 --- a/core/fpdfapi/parser/cpdf_crypto_handler.cpp +++ b/core/fpdfapi/parser/cpdf_crypto_handler.cpp @@ -8,10 +8,42 @@ #include +#include +#include +#include + #include "core/fdrm/crypto/fx_crypt.h" +#include "core/fpdfapi/edit/cpdf_encryptor.h" +#include "core/fpdfapi/edit/cpdf_flateencoder.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_object_walker.h" #include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/cpdf_security_handler.h" #include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fpdfapi/parser/cpdf_string.h" + +namespace { + +constexpr char kContentsKey[] = "Contents"; +constexpr char kTypeKey[] = "Type"; +constexpr char kFTKey[] = "FT"; +constexpr char kSignTypeValue[] = "Sig"; + +} // namespace + +// static +bool CPDF_CryptoHandler::IsSignatureDictionary( + const CPDF_Dictionary* dictionary) { + if (!dictionary) + return false; + const CPDF_Object* type_obj = dictionary->GetDirectObjectFor(kTypeKey); + if (!type_obj) + type_obj = dictionary->GetDirectObjectFor(kFTKey); + return type_obj && type_obj->GetString() == kSignTypeValue; +} void CPDF_CryptoHandler::CryptBlock(bool bEncrypt, uint32_t objnum, @@ -21,7 +53,7 @@ void CPDF_CryptoHandler::CryptBlock(bool bEncrypt, uint8_t* dest_buf, uint32_t& dest_size) { if (m_Cipher == FXCIPHER_NONE) { - FXSYS_memcpy(dest_buf, src_buf, src_size); + memcpy(dest_buf, src_buf, src_size); return; } uint8_t realkey[16]; @@ -31,7 +63,7 @@ void CPDF_CryptoHandler::CryptBlock(bool bEncrypt, PopulateKey(objnum, gennum, key1); if (m_Cipher == FXCIPHER_AES) { - FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); + memcpy(key1 + m_KeyLen + 5, "sAlT", 4); } CRYPT_MD5Generate( key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); @@ -41,44 +73,46 @@ void CPDF_CryptoHandler::CryptBlock(bool bEncrypt, } } if (m_Cipher == FXCIPHER_AES) { - CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, - m_KeyLen, bEncrypt); + CRYPT_AESSetKey(m_pAESContext.get(), 16, + m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen, + bEncrypt); if (bEncrypt) { uint8_t iv[16]; for (int i = 0; i < 16; i++) { iv[i] = (uint8_t)rand(); } - CRYPT_AESSetIV(m_pAESContext, iv); - FXSYS_memcpy(dest_buf, iv, 16); + CRYPT_AESSetIV(m_pAESContext.get(), iv); + memcpy(dest_buf, iv, 16); int nblocks = src_size / 16; - CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); + CRYPT_AESEncrypt(m_pAESContext.get(), dest_buf + 16, src_buf, + nblocks * 16); uint8_t padding[16]; - FXSYS_memcpy(padding, src_buf + nblocks * 16, src_size % 16); - FXSYS_memset(padding + src_size % 16, 16 - src_size % 16, - 16 - src_size % 16); - CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, - 16); + memcpy(padding, src_buf + nblocks * 16, src_size % 16); + memset(padding + src_size % 16, 16 - src_size % 16, 16 - src_size % 16); + CRYPT_AESEncrypt(m_pAESContext.get(), dest_buf + nblocks * 16 + 16, + padding, 16); dest_size = 32 + nblocks * 16; } else { - CRYPT_AESSetIV(m_pAESContext, src_buf); - CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); + CRYPT_AESSetIV(m_pAESContext.get(), src_buf); + CRYPT_AESDecrypt(m_pAESContext.get(), dest_buf, src_buf + 16, + src_size - 16); dest_size = src_size - 16; dest_size -= dest_buf[dest_size - 1]; } } else { ASSERT(dest_size == src_size); if (dest_buf != src_buf) { - FXSYS_memcpy(dest_buf, src_buf, src_size); + memcpy(dest_buf, src_buf, src_size); } CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); } } struct AESCryptContext { - uint8_t m_Context[2048]; bool m_bIV; uint8_t m_Block[16]; uint32_t m_BlockOffset; + CRYPT_aes_context m_Context; }; void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, @@ -91,12 +125,12 @@ void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); pContext->m_bIV = true; pContext->m_BlockOffset = 0; - CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); + CRYPT_AESSetKey(&pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); if (bEncrypt) { for (int i = 0; i < 16; i++) { pContext->m_Block[i] = (uint8_t)rand(); } - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block); } return pContext; } @@ -104,7 +138,7 @@ void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, PopulateKey(objnum, gennum, key1); if (m_Cipher == FXCIPHER_AES) { - FXSYS_memcpy(key1 + m_KeyLen + 5, "sAlT", 4); + memcpy(key1 + m_KeyLen + 5, "sAlT", 4); } uint8_t realkey[16]; CRYPT_MD5Generate( @@ -117,12 +151,12 @@ void* CPDF_CryptoHandler::CryptStart(uint32_t objnum, AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); pContext->m_bIV = true; pContext->m_BlockOffset = 0; - CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); + CRYPT_AESSetKey(&pContext->m_Context, 16, realkey, 16, bEncrypt); if (bEncrypt) { for (int i = 0; i < 16; i++) { pContext->m_Block[i] = (uint8_t)rand(); } - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block); } return pContext; } @@ -162,23 +196,23 @@ bool CPDF_CryptoHandler::CryptStream(void* context, if (copy_size > src_left) { copy_size = src_left; } - FXSYS_memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, - copy_size); + memcpy(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, + copy_size); src_off += copy_size; src_left -= copy_size; pContext->m_BlockOffset += copy_size; if (pContext->m_BlockOffset == 16) { if (!bEncrypt && pContext->m_bIV) { - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + CRYPT_AESSetIV(&pContext->m_Context, pContext->m_Block); pContext->m_bIV = false; pContext->m_BlockOffset = 0; } else if (src_off < src_size) { uint8_t block_buf[16]; if (bEncrypt) { - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, + CRYPT_AESEncrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16); } else { - CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, + CRYPT_AESDecrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16); } dest_buf.AppendBlock(block_buf, 16); @@ -208,18 +242,18 @@ bool CPDF_CryptoHandler::CryptFinish(void* context, if (bEncrypt) { uint8_t block_buf[16]; if (pContext->m_BlockOffset == 16) { - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + CRYPT_AESEncrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16); dest_buf.AppendBlock(block_buf, 16); pContext->m_BlockOffset = 0; } - FXSYS_memset(pContext->m_Block + pContext->m_BlockOffset, - (uint8_t)(16 - pContext->m_BlockOffset), - 16 - pContext->m_BlockOffset); - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + memset(pContext->m_Block + pContext->m_BlockOffset, + (uint8_t)(16 - pContext->m_BlockOffset), + 16 - pContext->m_BlockOffset); + CRYPT_AESEncrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16); dest_buf.AppendBlock(block_buf, 16); } else if (pContext->m_BlockOffset == 16) { uint8_t block_buf[16]; - CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + CRYPT_AESDecrypt(&pContext->m_Context, block_buf, pContext->m_Block, 16); if (block_buf[15] <= 16) { dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); } @@ -228,14 +262,14 @@ bool CPDF_CryptoHandler::CryptFinish(void* context, return true; } -void CPDF_CryptoHandler::Decrypt(uint32_t objnum, - uint32_t gennum, - CFX_ByteString& str) { +ByteString CPDF_CryptoHandler::Decrypt(uint32_t objnum, + uint32_t gennum, + const ByteString& str) { CFX_BinaryBuf dest_buf; void* context = DecryptStart(objnum, gennum); DecryptStream(context, str.raw_str(), str.GetLength(), dest_buf); DecryptFinish(context, dest_buf); - str = CFX_ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); + return ByteString(dest_buf.GetBuffer(), dest_buf.GetSize()); } void* CPDF_CryptoHandler::DecryptStart(uint32_t objnum, uint32_t gennum) { @@ -245,61 +279,99 @@ uint32_t CPDF_CryptoHandler::DecryptGetSize(uint32_t src_size) { return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; } -bool CPDF_CryptoHandler::Init(CPDF_Dictionary* pEncryptDict, - CPDF_SecurityHandler* pSecurityHandler) { - const uint8_t* key; - if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) { - return false; - } - if (m_KeyLen > 32 || m_KeyLen < 0) { - return false; - } - if (m_Cipher != FXCIPHER_NONE) { - FXSYS_memcpy(m_EncryptKey, key, m_KeyLen); - } - if (m_Cipher == FXCIPHER_AES) { - m_pAESContext = FX_Alloc(uint8_t, 2048); - } - return true; +bool CPDF_CryptoHandler::IsCipherAES() const { + return m_Cipher == FXCIPHER_AES; } -bool CPDF_CryptoHandler::Init(int cipher, const uint8_t* key, int keylen) { - if (cipher == FXCIPHER_AES) { - switch (keylen) { - case 16: - case 24: - case 32: - break; - default: - return false; - } - } else if (cipher == FXCIPHER_AES2) { - if (keylen != 32) { - return false; - } - } else if (cipher == FXCIPHER_RC4) { - if (keylen < 5 || keylen > 16) { - return false; +std::unique_ptr CPDF_CryptoHandler::DecryptObjectTree( + std::unique_ptr object) { + if (!object) + return nullptr; + + struct MayBeSignature { + const CPDF_Dictionary* parent; + CPDF_Object* contents; + }; + + std::stack may_be_sign_dictionaries; + const uint32_t obj_num = object->GetObjNum(); + const uint32_t gen_num = object->GetGenNum(); + + CPDF_Object* object_to_decrypt = object.get(); + while (object_to_decrypt) { + CPDF_NonConstObjectWalker walker(object_to_decrypt); + object_to_decrypt = nullptr; + while (CPDF_Object* child = walker.GetNext()) { + const CPDF_Dictionary* parent_dict = + walker.GetParent() ? walker.GetParent()->GetDict() : nullptr; + if (walker.dictionary_key() == kContentsKey && + (parent_dict->KeyExist(kTypeKey) || parent_dict->KeyExist(kFTKey))) { + // This object may be contents of signature dictionary. + // But now values of 'Type' and 'FT' of dictionary keys are encrypted, + // and we can not check this. + // Temporary skip it, to prevent signature corruption. + // It will be decrypted on next interations, if this is not contents of + // signature dictionary. + may_be_sign_dictionaries.push(MayBeSignature({parent_dict, child})); + walker.SkipWalkIntoCurrentObject(); + continue; + } + // Strings decryption. + if (child->IsString()) { + // TODO(art-snake): Move decryption into the CPDF_String class. + CPDF_String* str = child->AsString(); + str->SetString(Decrypt(obj_num, gen_num, str->GetString())); + } + // Stream decryption. + if (child->IsStream()) { + // TODO(art-snake): Move decryption into the CPDF_Stream class. + CPDF_Stream* stream = child->AsStream(); + auto stream_access = pdfium::MakeRetain(stream); + stream_access->LoadAllDataRaw(); + + if (IsCipherAES() && stream_access->GetSize() < 16) { + stream->SetData(nullptr, 0); + continue; + } + + CFX_BinaryBuf decrypted_buf; + decrypted_buf.EstimateSize(DecryptGetSize(stream_access->GetSize())); + + void* context = DecryptStart(obj_num, gen_num); + bool decrypt_result = + DecryptStream(context, stream_access->GetData(), + stream_access->GetSize(), decrypted_buf); + decrypt_result &= DecryptFinish(context, decrypted_buf); + if (decrypt_result) { + const uint32_t decrypted_size = decrypted_buf.GetSize(); + stream->SetData(decrypted_buf.DetachBuffer(), decrypted_size); + } else { + // Decryption failed, set the stream to empty + stream->SetData(nullptr, 0); + } + } } - } else { - if (keylen > 32) { - keylen = 32; + // Signature dictionaries check. + while (!may_be_sign_dictionaries.empty()) { + auto dict_and_contents = std::move(may_be_sign_dictionaries.top()); + may_be_sign_dictionaries.pop(); + if (!IsSignatureDictionary(dict_and_contents.parent)) { + // This is not signature dictionary. Do decrypt its contents. + object_to_decrypt = dict_and_contents.contents; + break; + } } } - m_Cipher = cipher; - m_KeyLen = keylen; - FXSYS_memcpy(m_EncryptKey, key, keylen); - if (m_Cipher == FXCIPHER_AES) { - m_pAESContext = FX_Alloc(uint8_t, 2048); - } - return true; + return object; } + bool CPDF_CryptoHandler::DecryptStream(void* context, const uint8_t* src_buf, uint32_t src_size, CFX_BinaryBuf& dest_buf) { return CryptStream(context, src_buf, src_size, dest_buf, false); } + bool CPDF_CryptoHandler::DecryptFinish(void* context, CFX_BinaryBuf& dest_buf) { return CryptFinish(context, dest_buf, false); } @@ -312,6 +384,7 @@ uint32_t CPDF_CryptoHandler::EncryptGetSize(uint32_t objnum, } return src_size; } + bool CPDF_CryptoHandler::EncryptContent(uint32_t objnum, uint32_t gennum, const uint8_t* src_buf, @@ -321,19 +394,29 @@ bool CPDF_CryptoHandler::EncryptContent(uint32_t objnum, CryptBlock(true, objnum, gennum, src_buf, src_size, dest_buf, dest_size); return true; } -CPDF_CryptoHandler::CPDF_CryptoHandler() { - m_pAESContext = nullptr; - m_Cipher = FXCIPHER_NONE; - m_KeyLen = 0; -} -CPDF_CryptoHandler::~CPDF_CryptoHandler() { - FX_Free(m_pAESContext); + +CPDF_CryptoHandler::CPDF_CryptoHandler(int cipher, + const uint8_t* key, + int keylen) + : m_KeyLen(std::min(keylen, 32)), m_Cipher(cipher) { + ASSERT(cipher != FXCIPHER_AES || keylen == 16 || keylen == 24 || + keylen == 32); + ASSERT(cipher != FXCIPHER_AES2 || keylen == 32); + ASSERT(cipher != FXCIPHER_RC4 || (keylen >= 5 && keylen <= 16)); + + if (m_Cipher != FXCIPHER_NONE) + memcpy(m_EncryptKey, key, m_KeyLen); + + if (m_Cipher == FXCIPHER_AES) + m_pAESContext.reset(FX_Alloc(CRYPT_aes_context, 1)); } +CPDF_CryptoHandler::~CPDF_CryptoHandler() {} + void CPDF_CryptoHandler::PopulateKey(uint32_t objnum, uint32_t gennum, uint8_t* key) { - FXSYS_memcpy(key, m_EncryptKey, m_KeyLen); + memcpy(key, m_EncryptKey, m_KeyLen); key[m_KeyLen + 0] = (uint8_t)objnum; key[m_KeyLen + 1] = (uint8_t)(objnum >> 8); key[m_KeyLen + 2] = (uint8_t)(objnum >> 16); diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.h b/core/fpdfapi/parser/cpdf_crypto_handler.h index 63a259095052436af9a6784bad653ddc3c9f81ad..32eeaef4c907b3634a6023530b7acf99b15ef2ba 100644 --- a/core/fpdfapi/parser/cpdf_crypto_handler.h +++ b/core/fpdfapi/parser/cpdf_crypto_handler.h @@ -7,28 +7,29 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_CRYPTO_HANDLER_H_ #define CORE_FPDFAPI_PARSER_CPDF_CRYPTO_HANDLER_H_ -#include "core/fxcrt/fx_basic.h" +#include + +#include "core/fdrm/crypto/fx_crypt.h" +#include "core/fxcrt/cfx_binarybuf.h" +#include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" class CPDF_Dictionary; +class CPDF_Object; class CPDF_SecurityHandler; class CPDF_CryptoHandler { public: - CPDF_CryptoHandler(); + CPDF_CryptoHandler(int cipher, const uint8_t* key, int keylen); ~CPDF_CryptoHandler(); - bool Init(CPDF_Dictionary* pEncryptDict, - CPDF_SecurityHandler* pSecurityHandler); - uint32_t DecryptGetSize(uint32_t src_size); - void* DecryptStart(uint32_t objnum, uint32_t gennum); - void Decrypt(uint32_t objnum, uint32_t gennum, CFX_ByteString& str); - bool DecryptStream(void* context, - const uint8_t* src_buf, - uint32_t src_size, - CFX_BinaryBuf& dest_buf); - bool DecryptFinish(void* context, CFX_BinaryBuf& dest_buf); + static bool IsSignatureDictionary(const CPDF_Dictionary* dictionary); + + std::unique_ptr DecryptObjectTree( + std::unique_ptr object); + uint32_t EncryptGetSize(uint32_t objnum, uint32_t version, const uint8_t* src_buf, @@ -40,9 +41,19 @@ class CPDF_CryptoHandler { uint8_t* dest_buf, uint32_t& dest_size); - bool Init(int cipher, const uint8_t* key, int keylen); + bool IsCipherAES() const; - protected: + private: + uint32_t DecryptGetSize(uint32_t src_size); + void* DecryptStart(uint32_t objnum, uint32_t gennum); + ByteString Decrypt(uint32_t objnum, uint32_t gennum, const ByteString& str); + bool DecryptStream(void* context, + const uint8_t* src_buf, + uint32_t src_size, + CFX_BinaryBuf& dest_buf); + bool DecryptFinish(void* context, CFX_BinaryBuf& dest_buf); + + void PopulateKey(uint32_t objnum, uint32_t gennum, uint8_t* key); void CryptBlock(bool bEncrypt, uint32_t objnum, uint32_t gennum, @@ -61,10 +72,7 @@ class CPDF_CryptoHandler { uint8_t m_EncryptKey[32]; int m_KeyLen; int m_Cipher; - uint8_t* m_pAESContext; - - private: - void PopulateKey(uint32_t objnum, uint32_t gennum, uint8_t* key); + std::unique_ptr m_pAESContext; }; #endif // CORE_FPDFAPI_PARSER_CPDF_CRYPTO_HANDLER_H_ diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp index 64eaf2a43be2768d7cec32e6f9cf3dec67cfc759..af80fd96abe875204eeea2f3bbdf567a10e20a58 100644 --- a/core/fpdfapi/parser/cpdf_data_avail.cpp +++ b/core/fpdfapi/parser/cpdf_data_avail.cpp @@ -12,281 +12,125 @@ #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_cross_ref_avail.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_hint_tables.h" #include "core/fpdfapi/parser/cpdf_linearized_header.h" #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_page_object_avail.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/fpdf_parser_utility.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_safe_types.h" #include "third_party/base/numerics/safe_conversions.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -CPDF_DataAvail::FileAvail::~FileAvail() {} - -CPDF_DataAvail::DownloadHints::~DownloadHints() {} +namespace { // static -int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0; - -CPDF_DataAvail::CPDF_DataAvail( - FileAvail* pFileAvail, - const CFX_RetainPtr& pFileRead, - bool bSupportHintTable) - : m_pFileAvail(pFileAvail), m_pFileRead(pFileRead) { - m_Pos = 0; - m_dwFileLen = 0; - if (m_pFileRead) { - m_dwFileLen = (uint32_t)m_pFileRead->GetSize(); +const CPDF_Object* GetResourceObject(const CPDF_Dictionary* pDict) { + constexpr size_t kMaxHierarchyDepth = 64; + size_t depth = 0; + + const CPDF_Dictionary* dictionary_to_check = pDict; + while (dictionary_to_check) { + const CPDF_Object* result = dictionary_to_check->GetObjectFor("Resources"); + if (result) + return result; + const CPDF_Object* parent = dictionary_to_check->GetObjectFor("Parent"); + dictionary_to_check = parent ? parent->GetDict() : nullptr; + + if (++depth > kMaxHierarchyDepth) { + // We have cycle in parents hierarchy. + return nullptr; + } } - m_dwCurrentOffset = 0; - m_dwXRefOffset = 0; - m_dwTrailerOffset = 0; - m_bufferOffset = 0; - m_bufferSize = 0; - m_PagesObjNum = 0; - m_dwCurrentXRefSteam = 0; - m_dwAcroFormObjNum = 0; - m_dwInfoObjNum = 0; - m_pDocument = 0; - m_dwEncryptObjNum = 0; - m_dwPrevXRefOffset = 0; - m_dwLastXRefOffset = 0; - m_bDocAvail = false; - m_bMainXRefLoadTried = false; - m_bDocAvail = false; - m_bPagesLoad = false; - m_bPagesTreeLoad = false; - m_bMainXRefLoadedOK = false; - m_bAnnotsLoad = false; - m_bHaveAcroForm = false; - m_bAcroFormLoad = false; - m_bPageLoadedOK = false; - m_bNeedDownLoadResource = false; - m_bLinearizedFormParamLoad = false; - m_pTrailer = nullptr; - m_pCurrentParser = nullptr; - m_pAcroForm = nullptr; - m_pPageDict = nullptr; - m_pPageResource = nullptr; - m_docStatus = PDF_DATAAVAIL_HEADER; - m_bTotalLoadPageTree = false; - m_bCurPageDictLoadOK = false; - m_bLinearedDataOK = false; - m_bSupportHintTable = bSupportHintTable; + return nullptr; } -CPDF_DataAvail::~CPDF_DataAvail() { - m_pHintTables.reset(); - for (CPDF_Object* pObject : m_arrayAcroforms) - delete pObject; -} - -void CPDF_DataAvail::SetDocument(CPDF_Document* pDoc) { - m_pDocument = pDoc; -} - -uint32_t CPDF_DataAvail::GetObjectSize(uint32_t objnum, FX_FILESIZE& offset) { - CPDF_Parser* pParser = m_pDocument->GetParser(); - if (!pParser || !pParser->IsValidObjectNumber(objnum)) - return 0; - - if (pParser->GetObjectType(objnum) == 2) - objnum = pParser->GetObjectPositionOrZero(objnum); - - if (pParser->GetObjectType(objnum) != 1 && - pParser->GetObjectType(objnum) != 255) { - return 0; +class HintsScope { + public: + HintsScope(CPDF_ReadValidator* validator, + CPDF_DataAvail::DownloadHints* hints) + : validator_(validator) { + ASSERT(validator_); + validator_->SetDownloadHints(hints); } - offset = pParser->GetObjectPositionOrZero(objnum); - if (offset == 0) - return 0; + ~HintsScope() { validator_->SetDownloadHints(nullptr); } - auto it = pParser->m_SortedOffset.find(offset); - if (it == pParser->m_SortedOffset.end() || - ++it == pParser->m_SortedOffset.end()) { - return 0; - } - return *it - offset; -} + private: + UnownedPtr validator_; +}; -bool CPDF_DataAvail::AreObjectsAvailable(std::vector& obj_array, - bool bParsePage, - DownloadHints* pHints, - std::vector& ret_array) { - if (obj_array.empty()) - return true; +} // namespace - uint32_t count = 0; - std::vector new_obj_array; - for (CPDF_Object* pObj : obj_array) { - if (!pObj) - continue; - - int32_t type = pObj->GetType(); - switch (type) { - case CPDF_Object::ARRAY: { - CPDF_Array* pArray = pObj->AsArray(); - for (size_t k = 0; k < pArray->GetCount(); ++k) - new_obj_array.push_back(pArray->GetObjectAt(k)); - } break; - case CPDF_Object::STREAM: - pObj = pObj->GetDict(); - case CPDF_Object::DICTIONARY: { - CPDF_Dictionary* pDict = pObj->GetDict(); - if (pDict && pDict->GetStringFor("Type") == "Page" && !bParsePage) - continue; +CPDF_DataAvail::FileAvail::~FileAvail() {} - for (const auto& it : *pDict) { - if (it.first != "Parent") - new_obj_array.push_back(it.second.get()); - } - } break; - case CPDF_Object::REFERENCE: { - CPDF_Reference* pRef = pObj->AsReference(); - uint32_t dwNum = pRef->GetRefObjNum(); - - FX_FILESIZE offset; - uint32_t size = GetObjectSize(dwNum, offset); - if (size == 0 || offset < 0 || offset >= m_dwFileLen) - break; - - if (!IsDataAvail(offset, size, pHints)) { - ret_array.push_back(pObj); - count++; - } else if (!pdfium::ContainsKey(m_ObjectSet, dwNum)) { - m_ObjectSet.insert(dwNum); - CPDF_Object* pReferred = - m_pDocument->GetOrParseIndirectObject(pRef->GetRefObjNum()); - if (pReferred) - new_obj_array.push_back(pReferred); - } - } break; - } - } +CPDF_DataAvail::DownloadHints::~DownloadHints() {} - if (count > 0) { - for (CPDF_Object* pObj : new_obj_array) { - CPDF_Reference* pRef = pObj->AsReference(); - if (pRef && pdfium::ContainsKey(m_ObjectSet, pRef->GetRefObjNum())) - continue; - ret_array.push_back(pObj); - } - return false; - } +CPDF_DataAvail::CPDF_DataAvail( + FileAvail* pFileAvail, + const RetainPtr& pFileRead, + bool bSupportHintTable) + : m_pFileAvail(pFileAvail), + m_pFileRead( + pdfium::MakeRetain(pFileRead, m_pFileAvail)), + m_dwFileLen(m_pFileRead->GetSize()), + m_bSupportHintTable(bSupportHintTable) {} - obj_array = new_obj_array; - return AreObjectsAvailable(obj_array, false, pHints, ret_array); +CPDF_DataAvail::~CPDF_DataAvail() { + m_pHintTables.reset(); } CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsDocAvail( DownloadHints* pHints) { - if (!m_dwFileLen && m_pFileRead) { - m_dwFileLen = (uint32_t)m_pFileRead->GetSize(); - if (!m_dwFileLen) - return DataError; - } + if (!m_dwFileLen) + return DataError; + + const HintsScope hints_scope(m_pFileRead.Get(), pHints); while (!m_bDocAvail) { - if (!CheckDocStatus(pHints)) + if (!CheckDocStatus()) return DataNotAvailable; } return DataAvailable; } -bool CPDF_DataAvail::CheckAcroFormSubObject(DownloadHints* pHints) { - if (m_objs_array.empty()) { - m_ObjectSet.clear(); - std::vector obj_array = m_arrayAcroforms; - if (!AreObjectsAvailable(obj_array, false, pHints, m_objs_array)) - return false; - - m_objs_array.clear(); - return true; - } - - std::vector new_objs_array; - if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) { - m_objs_array = new_objs_array; - return false; - } - - for (CPDF_Object* pObject : m_arrayAcroforms) - delete pObject; - - m_arrayAcroforms.clear(); - return true; -} - -bool CPDF_DataAvail::CheckAcroForm(DownloadHints* pHints) { - bool bExist = false; - m_pAcroForm = GetObject(m_dwAcroFormObjNum, pHints, &bExist).release(); - if (!bExist) { - m_docStatus = PDF_DATAAVAIL_PAGETREE; - return true; - } - - if (!m_pAcroForm) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } - return false; - } - - m_arrayAcroforms.push_back(m_pAcroForm); - m_docStatus = PDF_DATAAVAIL_PAGETREE; - return true; -} - -bool CPDF_DataAvail::CheckDocStatus(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckDocStatus() { switch (m_docStatus) { case PDF_DATAAVAIL_HEADER: - return CheckHeader(pHints); + return CheckHeader(); case PDF_DATAAVAIL_FIRSTPAGE: - return CheckFirstPage(pHints); + return CheckFirstPage(); case PDF_DATAAVAIL_HINTTABLE: - return CheckHintTables(pHints); - case PDF_DATAAVAIL_END: - return CheckEnd(pHints); - case PDF_DATAAVAIL_CROSSREF: - return CheckCrossRef(pHints); - case PDF_DATAAVAIL_CROSSREF_ITEM: - return CheckCrossRefItem(pHints); - case PDF_DATAAVAIL_CROSSREF_STREAM: - return CheckAllCrossRefStream(pHints); - case PDF_DATAAVAIL_TRAILER: - return CheckTrailer(pHints); - case PDF_DATAAVAIL_TRAILER_APPEND: - return CheckTrailerAppend(pHints); + return CheckHintTables(); case PDF_DATAAVAIL_LOADALLCROSSREF: - return LoadAllXref(pHints); + return CheckAndLoadAllXref(); case PDF_DATAAVAIL_LOADALLFILE: - return LoadAllFile(pHints); + return LoadAllFile(); case PDF_DATAAVAIL_ROOT: - return CheckRoot(pHints); + return CheckRoot(); case PDF_DATAAVAIL_INFO: - return CheckInfo(pHints); - case PDF_DATAAVAIL_ACROFORM: - return CheckAcroForm(pHints); + return CheckInfo(); case PDF_DATAAVAIL_PAGETREE: if (m_bTotalLoadPageTree) - return CheckPages(pHints); - return LoadDocPages(pHints); + return CheckPages(); + return LoadDocPages(); case PDF_DATAAVAIL_PAGE: if (m_bTotalLoadPageTree) - return CheckPage(pHints); + return CheckPage(); m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD; return true; case PDF_DATAAVAIL_ERROR: - return LoadAllFile(pHints); + return LoadAllFile(); case PDF_DATAAVAIL_PAGE_LATERLOAD: m_docStatus = PDF_DATAAVAIL_PAGE; default: @@ -295,14 +139,14 @@ bool CPDF_DataAvail::CheckDocStatus(DownloadHints* pHints) { } } -bool CPDF_DataAvail::CheckPageStatus(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckPageStatus() { switch (m_docStatus) { case PDF_DATAAVAIL_PAGETREE: - return CheckPages(pHints); + return CheckPages(); case PDF_DATAAVAIL_PAGE: - return CheckPage(pHints); + return CheckPage(); case PDF_DATAAVAIL_ERROR: - return LoadAllFile(pHints); + return LoadAllFile(); default: m_bPagesTreeLoad = true; m_bPagesLoad = true; @@ -310,20 +154,45 @@ bool CPDF_DataAvail::CheckPageStatus(DownloadHints* pHints) { } } -bool CPDF_DataAvail::LoadAllFile(DownloadHints* pHints) { - if (m_pFileAvail->IsDataAvail(0, (uint32_t)m_dwFileLen)) { +bool CPDF_DataAvail::LoadAllFile() { + if (GetValidator()->CheckWholeFileAndRequestIfUnavailable()) { m_docStatus = PDF_DATAAVAIL_DONE; return true; } - - pHints->AddSegment(0, (uint32_t)m_dwFileLen); return false; } -bool CPDF_DataAvail::LoadAllXref(DownloadHints* pHints) { - m_parser.m_pSyntax->InitParser(m_pFileRead, (uint32_t)m_dwHeaderOffset); - if (!m_parser.LoadAllCrossRefV4(m_dwLastXRefOffset) && - !m_parser.LoadAllCrossRefV5(m_dwLastXRefOffset)) { +bool CPDF_DataAvail::CheckAndLoadAllXref() { + if (!m_pCrossRefAvail) { + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); + const FX_FILESIZE last_xref_offset = m_parser.ParseStartXRef(); + if (GetValidator()->has_read_problems()) + return false; + + if (last_xref_offset <= 0) { + m_docStatus = PDF_DATAAVAIL_ERROR; + return false; + } + + m_pCrossRefAvail = pdfium::MakeUnique(GetSyntaxParser(), + last_xref_offset); + } + + switch (m_pCrossRefAvail->CheckAvail()) { + case DocAvailStatus::DataAvailable: + break; + case DocAvailStatus::DataNotAvailable: + return false; + case DocAvailStatus::DataError: + m_docStatus = PDF_DATAAVAIL_ERROR; + return false; + default: + NOTREACHED(); + return false; + } + + if (!m_parser.LoadAllCrossRefV4(m_pCrossRefAvail->last_crossref_offset()) && + !m_parser.LoadAllCrossRefV5(m_pCrossRefAvail->last_crossref_offset())) { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return false; } @@ -336,30 +205,21 @@ bool CPDF_DataAvail::LoadAllXref(DownloadHints* pHints) { } std::unique_ptr CPDF_DataAvail::GetObject(uint32_t objnum, - DownloadHints* pHints, bool* pExistInFile) { - uint32_t size = 0; - FX_FILESIZE offset = 0; CPDF_Parser* pParser = nullptr; if (pExistInFile) *pExistInFile = true; - if (m_pDocument) { - size = GetObjectSize(objnum, offset); - pParser = m_pDocument->GetParser(); - } else { - size = (uint32_t)m_parser.GetObjectSize(objnum); - offset = m_parser.GetObjectOffset(objnum); - pParser = &m_parser; - } - - if (!IsDataAvail(offset, size, pHints)) - return nullptr; + pParser = m_pDocument ? m_pDocument->GetParser() : &m_parser; std::unique_ptr pRet; - if (pParser) + if (pParser) { + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); pRet = pParser->ParseIndirectObject(nullptr, objnum); + if (GetValidator()->has_read_problems()) + return nullptr; + } if (!pRet && pExistInFile) *pExistInFile = false; @@ -367,27 +227,23 @@ std::unique_ptr CPDF_DataAvail::GetObject(uint32_t objnum, return pRet; } -bool CPDF_DataAvail::CheckInfo(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckInfo() { bool bExist = false; - std::unique_ptr pInfo = - GetObject(m_dwInfoObjNum, pHints, &bExist); + std::unique_ptr pInfo = GetObject(m_dwInfoObjNum, &bExist); if (bExist && !pInfo) { if (m_docStatus == PDF_DATAAVAIL_ERROR) { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return true; } - if (m_Pos == m_dwFileLen) - m_docStatus = PDF_DATAAVAIL_ERROR; return false; } - m_docStatus = - m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE; + m_docStatus = PDF_DATAAVAIL_PAGETREE; return true; } -bool CPDF_DataAvail::CheckRoot(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckRoot() { bool bExist = false; - m_pRoot = GetObject(m_dwRootObjNum, pHints, &bExist); + m_pRoot = GetObject(m_dwRootObjNum, &bExist); if (!bExist) { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return true; @@ -414,24 +270,13 @@ bool CPDF_DataAvail::CheckRoot(DownloadHints* pHints) { } m_PagesObjNum = pRef->GetRefObjNum(); - CPDF_Reference* pAcroFormRef = - ToReference(m_pRoot->GetDict()->GetObjectFor("AcroForm")); - if (pAcroFormRef) { - m_bHaveAcroForm = true; - m_dwAcroFormObjNum = pAcroFormRef->GetRefObjNum(); - } - if (m_dwInfoObjNum) { - m_docStatus = PDF_DATAAVAIL_INFO; - } else { - m_docStatus = - m_bHaveAcroForm ? PDF_DATAAVAIL_ACROFORM : PDF_DATAAVAIL_PAGETREE; - } + m_docStatus = m_dwInfoObjNum ? PDF_DATAAVAIL_INFO : PDF_DATAAVAIL_PAGETREE; return true; } bool CPDF_DataAvail::PreparePageItem() { - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + const CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); CPDF_Reference* pRef = ToReference(pRoot ? pRoot->GetObjectFor("Pages") : nullptr); if (!pRef) { @@ -453,12 +298,11 @@ void CPDF_DataAvail::ResetFirstCheck(uint32_t dwPage) { m_pageMapCheckState.erase(dwPage); } -bool CPDF_DataAvail::CheckPage(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckPage() { std::vector UnavailObjList; for (uint32_t dwPageObjNum : m_PageObjList) { bool bExists = false; - std::unique_ptr pObj = - GetObject(dwPageObjNum, pHints, &bExists); + std::unique_ptr pObj = GetObject(dwPageObjNum, &bExists); if (!pObj) { if (bExists) UnavailObjList.push_back(dwPageObjNum); @@ -474,7 +318,7 @@ bool CPDF_DataAvail::CheckPage(DownloadHints* pHints) { if (!pObj->IsDictionary()) continue; - CFX_ByteString type = pObj->GetDict()->GetStringFor("Type"); + ByteString type = pObj->GetDict()->GetStringFor("Type"); if (type == "Pages") { m_PagesArray.push_back(std::move(pObj)); continue; @@ -522,7 +366,8 @@ bool CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) { if (CPDF_Reference* pRef = ToReference(pKidsArray->GetObjectAt(i))) m_PageObjList.push_back(pRef->GetRefObjNum()); } - } break; + break; + } default: m_docStatus = PDF_DATAAVAIL_ERROR; return false; @@ -530,10 +375,9 @@ bool CPDF_DataAvail::GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages) { return true; } -bool CPDF_DataAvail::CheckPages(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckPages() { bool bExists = false; - std::unique_ptr pPages = - GetObject(m_PagesObjNum, pHints, &bExists); + std::unique_ptr pPages = GetObject(m_PagesObjNum, &bExists); if (!bExists) { m_docStatus = PDF_DATAAVAIL_LOADALLFILE; return true; @@ -556,31 +400,27 @@ bool CPDF_DataAvail::CheckPages(DownloadHints* pHints) { return true; } -bool CPDF_DataAvail::CheckHeader(DownloadHints* pHints) { - ASSERT(m_dwFileLen >= 0); - const uint32_t kReqSize = std::min(static_cast(m_dwFileLen), 1024U); - - if (m_pFileAvail->IsDataAvail(0, kReqSize)) { - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, 0, kReqSize); - - if (IsLinearizedFile(buffer, kReqSize)) { - m_docStatus = PDF_DATAAVAIL_FIRSTPAGE; - } else { - if (m_docStatus == PDF_DATAAVAIL_ERROR) - return false; - m_docStatus = PDF_DATAAVAIL_END; - } - return true; +bool CPDF_DataAvail::CheckHeader() { + switch (CheckHeaderAndLinearized()) { + case DocAvailStatus::DataAvailable: + m_docStatus = m_pLinearized ? PDF_DATAAVAIL_FIRSTPAGE + : PDF_DATAAVAIL_LOADALLCROSSREF; + return true; + case DocAvailStatus::DataNotAvailable: + return false; + case DocAvailStatus::DataError: + m_docStatus = PDF_DATAAVAIL_ERROR; + return true; + default: + NOTREACHED(); + return false; } - - pHints->AddSegment(0, kReqSize); - return false; } -bool CPDF_DataAvail::CheckFirstPage(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckFirstPage() { if (!m_pLinearized->GetFirstPageEndOffset() || - !m_pLinearized->GetFileSize() || !m_pLinearized->GetLastXRefOffset()) { + !m_pLinearized->GetFileSize() || + !m_pLinearized->GetMainXRefTableFirstEntryOffset()) { m_docStatus = PDF_DATAAVAIL_ERROR; return false; } @@ -590,41 +430,18 @@ bool CPDF_DataAvail::CheckFirstPage(DownloadHints* pHints) { if ((FX_FILESIZE)dwEnd > m_dwFileLen) dwEnd = (uint32_t)m_dwFileLen; - int32_t iStartPos = (int32_t)(m_dwFileLen > 1024 ? 1024 : m_dwFileLen); - int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0; - if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) { - pHints->AddSegment(iStartPos, iSize); + const FX_FILESIZE start_pos = m_dwFileLen > 1024 ? 1024 : m_dwFileLen; + const size_t data_size = dwEnd > 1024 ? static_cast(dwEnd - 1024) : 0; + if (!GetValidator()->CheckDataRangeAndRequestIfUnavailable(start_pos, + data_size)) return false; - } m_docStatus = m_bSupportHintTable ? PDF_DATAAVAIL_HINTTABLE : PDF_DATAAVAIL_DONE; return true; } -bool CPDF_DataAvail::IsDataAvail(FX_FILESIZE offset, - uint32_t size, - DownloadHints* pHints) { - if (offset < 0 || offset > m_dwFileLen) - return true; - - FX_SAFE_FILESIZE safeSize = offset; - safeSize += size; - safeSize += 512; - if (!safeSize.IsValid() || safeSize.ValueOrDie() > m_dwFileLen) - size = m_dwFileLen - offset; - else - size += 512; - - if (!m_pFileAvail->IsDataAvail(offset, size)) { - if (pHints) - pHints->AddSegment(offset, size); - return false; - } - return true; -} - -bool CPDF_DataAvail::CheckHintTables(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckHintTables() { if (m_pLinearized->GetPageCount() <= 1) { m_docStatus = PDF_DATAAVAIL_DONE; return true; @@ -634,18 +451,17 @@ bool CPDF_DataAvail::CheckHintTables(DownloadHints* pHints) { return false; } - FX_FILESIZE szHintStart = m_pLinearized->GetHintStart(); - FX_FILESIZE szHintLength = m_pLinearized->GetHintLength(); + const FX_FILESIZE szHintStart = m_pLinearized->GetHintStart(); + const uint32_t szHintLength = m_pLinearized->GetHintLength(); - if (!IsDataAvail(szHintStart, szHintLength, pHints)) + if (!GetValidator()->CheckDataRangeAndRequestIfUnavailable(szHintStart, + szHintLength)) return false; - m_syntaxParser.InitParser(m_pFileRead, m_dwHeaderOffset); - - std::unique_ptr pHintTables( - new CPDF_HintTables(this, m_pLinearized.get())); - std::unique_ptr pHintStream( - ParseIndirectObjectAt(szHintStart, 0)); + auto pHintTables = pdfium::MakeUnique(GetValidator().Get(), + m_pLinearized.get()); + std::unique_ptr pHintStream = + ParseIndirectObjectAt(szHintStart, 0); CPDF_Stream* pStream = ToStream(pHintStream.get()); if (pStream && pHintTables->LoadHintStream(pStream)) m_pHintTables = std::move(pHintTables); @@ -658,452 +474,65 @@ std::unique_ptr CPDF_DataAvail::ParseIndirectObjectAt( FX_FILESIZE pos, uint32_t objnum, CPDF_IndirectObjectHolder* pObjList) { - FX_FILESIZE SavedPos = m_syntaxParser.SavePos(); - m_syntaxParser.RestorePos(pos); - - bool bIsNumber; - CFX_ByteString word = m_syntaxParser.GetNextWord(&bIsNumber); - if (!bIsNumber) - return nullptr; - - uint32_t parser_objnum = FXSYS_atoui(word.c_str()); - if (objnum && parser_objnum != objnum) - return nullptr; - - word = m_syntaxParser.GetNextWord(&bIsNumber); - if (!bIsNumber) - return nullptr; - - uint32_t gennum = FXSYS_atoui(word.c_str()); - if (m_syntaxParser.GetKeyword() != "obj") { - m_syntaxParser.RestorePos(SavedPos); - return nullptr; - } - - std::unique_ptr pObj = - m_syntaxParser.GetObject(pObjList, parser_objnum, gennum, true); - m_syntaxParser.RestorePos(SavedPos); - return pObj; + const FX_FILESIZE SavedPos = GetSyntaxParser()->GetPos(); + GetSyntaxParser()->SetPos(pos); + std::unique_ptr result = GetSyntaxParser()->GetIndirectObject( + pObjList, CPDF_SyntaxParser::ParseType::kLoose); + GetSyntaxParser()->SetPos(SavedPos); + return (result && (!objnum || result->GetObjNum() == objnum)) + ? std::move(result) + : nullptr; } CPDF_DataAvail::DocLinearizationStatus CPDF_DataAvail::IsLinearizedPDF() { - const uint32_t kReqSize = 1024; - if (!m_pFileAvail->IsDataAvail(0, kReqSize)) - return LinearizationUnknown; - - if (!m_pFileRead) - return NotLinearized; - - FX_FILESIZE dwSize = m_pFileRead->GetSize(); - if (dwSize < (FX_FILESIZE)kReqSize) - return LinearizationUnknown; - - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, 0, kReqSize); - if (IsLinearizedFile(buffer, kReqSize)) - return Linearized; - - return NotLinearized; -} - -bool CPDF_DataAvail::IsLinearized() { - return !!m_pLinearized; -} - -bool CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, uint32_t dwLen) { - if (m_pLinearized) - return true; - - CFX_RetainPtr file = - IFX_MemoryStream::Create(pData, (size_t)dwLen, false); - int32_t offset = GetHeaderOffset(file); - if (offset == -1) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; - } - - m_dwHeaderOffset = offset; - m_syntaxParser.InitParser(file, offset); - m_syntaxParser.RestorePos(m_syntaxParser.m_HeaderOffset + 9); - - bool bNumber; - CFX_ByteString wordObjNum = m_syntaxParser.GetNextWord(&bNumber); - if (!bNumber) - return false; - - uint32_t objnum = FXSYS_atoui(wordObjNum.c_str()); - m_pLinearized = CPDF_LinearizedHeader::CreateForObject( - ParseIndirectObjectAt(m_syntaxParser.m_HeaderOffset + 9, objnum)); - if (!m_pLinearized || - m_pLinearized->GetFileSize() != m_pFileRead->GetSize()) { - m_pLinearized.reset(); - return false; - } - return true; -} - -bool CPDF_DataAvail::CheckEnd(DownloadHints* pHints) { - uint32_t req_pos = (uint32_t)(m_dwFileLen > 1024 ? m_dwFileLen - 1024 : 0); - uint32_t dwSize = (uint32_t)(m_dwFileLen - req_pos); - - if (m_pFileAvail->IsDataAvail(req_pos, dwSize)) { - uint8_t buffer[1024]; - m_pFileRead->ReadBlock(buffer, req_pos, dwSize); - - CFX_RetainPtr file = - IFX_MemoryStream::Create(buffer, (size_t)dwSize, false); - m_syntaxParser.InitParser(file, 0); - m_syntaxParser.RestorePos(dwSize - 1); - - if (m_syntaxParser.SearchWord("startxref", true, false, dwSize)) { - m_syntaxParser.GetNextWord(nullptr); - - bool bNumber; - CFX_ByteString xrefpos_str = m_syntaxParser.GetNextWord(&bNumber); - if (!bNumber) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; - } - - m_dwXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str.c_str()); - if (!m_dwXRefOffset || m_dwXRefOffset > m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } - - m_dwLastXRefOffset = m_dwXRefOffset; - SetStartOffset(m_dwXRefOffset); - m_docStatus = PDF_DATAAVAIL_CROSSREF; - return true; - } - - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } - - pHints->AddSegment(req_pos, dwSize); - return false; -} - -int32_t CPDF_DataAvail::CheckCrossRefStream(DownloadHints* pHints, - FX_FILESIZE& xref_offset) { - xref_offset = 0; - uint32_t req_size = - (uint32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - - if (m_pFileAvail->IsDataAvail(m_Pos, req_size)) { - int32_t iSize = (int32_t)(m_Pos + req_size - m_dwCurrentXRefSteam); - CFX_BinaryBuf buf(iSize); - uint8_t* pBuf = buf.GetBuffer(); - - m_pFileRead->ReadBlock(pBuf, m_dwCurrentXRefSteam, iSize); - - CFX_RetainPtr file = - IFX_MemoryStream::Create(pBuf, (size_t)iSize, false); - m_parser.m_pSyntax->InitParser(file, 0); - - bool bNumber; - CFX_ByteString objnum = m_parser.m_pSyntax->GetNextWord(&bNumber); - if (!bNumber) - return -1; - - uint32_t objNum = FXSYS_atoui(objnum.c_str()); - std::unique_ptr pObj = - m_parser.ParseIndirectObjectAt(nullptr, 0, objNum); - - if (!pObj) { - m_Pos += m_parser.m_pSyntax->SavePos(); - return 0; - } - - CPDF_Dictionary* pDict = pObj->GetDict(); - CPDF_Name* pName = ToName(pDict ? pDict->GetObjectFor("Type") : nullptr); - if (pName && pName->GetString() == "XRef") { - m_Pos += m_parser.m_pSyntax->SavePos(); - xref_offset = pObj->GetDict()->GetIntegerFor("Prev"); - return 1; - } - return -1; - } - pHints->AddSegment(m_Pos, req_size); - return 0; -} - -void CPDF_DataAvail::SetStartOffset(FX_FILESIZE dwOffset) { - m_Pos = dwOffset; -} - -bool CPDF_DataAvail::GetNextToken(CFX_ByteString& token) { - uint8_t ch; - if (!GetNextChar(ch)) - return false; - - while (1) { - while (PDFCharIsWhitespace(ch)) { - if (!GetNextChar(ch)) - return false; - } - - if (ch != '%') - break; - - while (1) { - if (!GetNextChar(ch)) - return false; - if (PDFCharIsLineEnding(ch)) - break; - } - } - - uint8_t buffer[256]; - uint32_t index = 0; - if (PDFCharIsDelimiter(ch)) { - buffer[index++] = ch; - if (ch == '/') { - while (1) { - if (!GetNextChar(ch)) - return false; - - if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { - m_Pos--; - CFX_ByteString ret(buffer, index); - token = ret; - return true; - } - - if (index < sizeof(buffer)) - buffer[index++] = ch; - } - } else if (ch == '<') { - if (!GetNextChar(ch)) - return false; - - if (ch == '<') - buffer[index++] = ch; - else - m_Pos--; - } else if (ch == '>') { - if (!GetNextChar(ch)) - return false; - - if (ch == '>') - buffer[index++] = ch; - else - m_Pos--; - } - - CFX_ByteString ret(buffer, index); - token = ret; - return true; - } - - while (1) { - if (index < sizeof(buffer)) - buffer[index++] = ch; - - if (!GetNextChar(ch)) - return false; - - if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { - m_Pos--; - break; - } - } - - token = CFX_ByteString(buffer, index); - return true; -} - -bool CPDF_DataAvail::GetNextChar(uint8_t& ch) { - FX_FILESIZE pos = m_Pos; - if (pos >= m_dwFileLen) - return false; - - if (m_bufferOffset >= pos || - (FX_FILESIZE)(m_bufferOffset + m_bufferSize) <= pos) { - FX_FILESIZE read_pos = pos; - uint32_t read_size = 512; - if ((FX_FILESIZE)read_size > m_dwFileLen) - read_size = (uint32_t)m_dwFileLen; - - if ((FX_FILESIZE)(read_pos + read_size) > m_dwFileLen) - read_pos = m_dwFileLen - read_size; - - if (!m_pFileRead->ReadBlock(m_bufferData, read_pos, read_size)) - return false; - - m_bufferOffset = read_pos; - m_bufferSize = read_size; - } - ch = m_bufferData[pos - m_bufferOffset]; - m_Pos++; - return true; -} - -bool CPDF_DataAvail::CheckCrossRefItem(DownloadHints* pHints) { - int32_t iSize = 0; - CFX_ByteString token; - while (1) { - if (!GetNextToken(token)) { - iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); - return false; - } - - if (token == "trailer") { - m_dwTrailerOffset = m_Pos; - m_docStatus = PDF_DATAAVAIL_TRAILER; - return true; - } - } -} - -bool CPDF_DataAvail::CheckAllCrossRefStream(DownloadHints* pHints) { - FX_FILESIZE xref_offset = 0; - - int32_t nRet = CheckCrossRefStream(pHints, xref_offset); - if (nRet == 1) { - if (!xref_offset) { - m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF; - } else { - m_dwCurrentXRefSteam = xref_offset; - m_Pos = xref_offset; - } - return true; - } - - if (nRet == -1) - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; -} - -bool CPDF_DataAvail::CheckCrossRef(DownloadHints* pHints) { - int32_t iSize = 0; - CFX_ByteString token; - if (!GetNextToken(token)) { - iSize = (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); - return false; - } - - if (token == "xref") { - while (1) { - if (!GetNextToken(token)) { - iSize = - (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - pHints->AddSegment(m_Pos, iSize); - m_docStatus = PDF_DATAAVAIL_CROSSREF_ITEM; - return false; - } - - if (token == "trailer") { - m_dwTrailerOffset = m_Pos; - m_docStatus = PDF_DATAAVAIL_TRAILER; - return true; - } - } - } else { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } - return false; -} - -bool CPDF_DataAvail::CheckTrailerAppend(DownloadHints* pHints) { - if (m_Pos < m_dwFileLen) { - FX_FILESIZE dwAppendPos = m_Pos + m_syntaxParser.SavePos(); - int32_t iSize = (int32_t)( - dwAppendPos + 512 > m_dwFileLen ? m_dwFileLen - dwAppendPos : 512); - - if (!m_pFileAvail->IsDataAvail(dwAppendPos, iSize)) { - pHints->AddSegment(dwAppendPos, iSize); - return false; - } - } - - if (m_dwPrevXRefOffset) { - SetStartOffset(m_dwPrevXRefOffset); - m_docStatus = PDF_DATAAVAIL_CROSSREF; - } else { - m_docStatus = PDF_DATAAVAIL_LOADALLCROSSREF; + switch (CheckHeaderAndLinearized()) { + case DocAvailStatus::DataAvailable: + return m_pLinearized ? DocLinearizationStatus::Linearized + : DocLinearizationStatus::NotLinearized; + case DocAvailStatus::DataNotAvailable: + return DocLinearizationStatus::LinearizationUnknown; + case DocAvailStatus::DataError: + return DocLinearizationStatus::NotLinearized; + default: + NOTREACHED(); + return DocLinearizationStatus::LinearizationUnknown; } - return true; } -bool CPDF_DataAvail::CheckTrailer(DownloadHints* pHints) { - int32_t iTrailerSize = - (int32_t)(m_Pos + 512 > m_dwFileLen ? m_dwFileLen - m_Pos : 512); - if (m_pFileAvail->IsDataAvail(m_Pos, iTrailerSize)) { - int32_t iSize = (int32_t)(m_Pos + iTrailerSize - m_dwTrailerOffset); - CFX_BinaryBuf buf(iSize); - uint8_t* pBuf = buf.GetBuffer(); - if (!pBuf) { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; - } +CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckHeaderAndLinearized() { + if (m_bHeaderAvail) + return DocAvailStatus::DataAvailable; - if (!m_pFileRead->ReadBlock(pBuf, m_dwTrailerOffset, iSize)) - return false; + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); + const int32_t header_offset = GetHeaderOffset(GetValidator()); + if (GetValidator()->has_read_problems()) + return DocAvailStatus::DataNotAvailable; - CFX_RetainPtr file = - IFX_MemoryStream::Create(pBuf, (size_t)iSize, false); - m_syntaxParser.InitParser(file, 0); + if (header_offset == kInvalidHeaderOffset) + return DocAvailStatus::DataError; - std::unique_ptr pTrailer( - m_syntaxParser.GetObject(nullptr, 0, 0, true)); - if (!pTrailer) { - m_Pos += m_syntaxParser.SavePos(); - pHints->AddSegment(m_Pos, iTrailerSize); - return false; - } + m_parser.m_pSyntax->InitParserWithValidator(GetValidator(), header_offset); + m_pLinearized = m_parser.ParseLinearizedHeader(); + if (GetValidator()->has_read_problems()) + return DocAvailStatus::DataNotAvailable; - if (!pTrailer->IsDictionary()) - return false; - - CPDF_Dictionary* pTrailerDict = pTrailer->GetDict(); - CPDF_Object* pEncrypt = pTrailerDict->GetObjectFor("Encrypt"); - if (ToReference(pEncrypt)) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - return true; - } - - uint32_t xrefpos = GetDirectInteger(pTrailerDict, "Prev"); - if (xrefpos) { - m_dwPrevXRefOffset = GetDirectInteger(pTrailerDict, "XRefStm"); - if (m_dwPrevXRefOffset) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - } else { - m_dwPrevXRefOffset = xrefpos; - if (m_dwPrevXRefOffset >= m_dwFileLen) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; - } else { - SetStartOffset(m_dwPrevXRefOffset); - m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; - } - } - return true; - } - m_dwPrevXRefOffset = 0; - m_docStatus = PDF_DATAAVAIL_TRAILER_APPEND; - return true; - } - pHints->AddSegment(m_Pos, iTrailerSize); - return false; + m_bHeaderAvail = true; + return DocAvailStatus::DataAvailable; } -bool CPDF_DataAvail::CheckPage(uint32_t dwPage, DownloadHints* pHints) { +bool CPDF_DataAvail::CheckPage(uint32_t dwPage) { while (true) { switch (m_docStatus) { case PDF_DATAAVAIL_PAGETREE: - if (!LoadDocPages(pHints)) + if (!LoadDocPages()) return false; break; case PDF_DATAAVAIL_PAGE: - if (!LoadDocPage(dwPage, pHints)) + if (!LoadDocPage(dwPage)) return false; break; case PDF_DATAAVAIL_ERROR: - return LoadAllFile(pHints); + return LoadAllFile(); default: m_bPagesTreeLoad = true; m_bPagesLoad = true; @@ -1115,10 +544,9 @@ bool CPDF_DataAvail::CheckPage(uint32_t dwPage, DownloadHints* pHints) { } bool CPDF_DataAvail::CheckArrayPageNode(uint32_t dwPageNo, - PageNode* pPageNode, - DownloadHints* pHints) { + PageNode* pPageNode) { bool bExists = false; - std::unique_ptr pPages = GetObject(dwPageNo, pHints, &bExists); + std::unique_ptr pPages = GetObject(dwPageNo, &bExists); if (!bExists) { m_docStatus = PDF_DATAAVAIL_ERROR; return false; @@ -1147,10 +575,9 @@ bool CPDF_DataAvail::CheckArrayPageNode(uint32_t dwPageNo, } bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo, - PageNode* pPageNode, - DownloadHints* pHints) { + PageNode* pPageNode) { bool bExists = false; - std::unique_ptr pPage = GetObject(dwPageNo, pHints, &bExists); + std::unique_ptr pPage = GetObject(dwPageNo, &bExists); if (!bExists) { m_docStatus = PDF_DATAAVAIL_ERROR; return false; @@ -1172,42 +599,47 @@ bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo, pPageNode->m_dwPageNo = dwPageNo; CPDF_Dictionary* pDict = pPage->GetDict(); - CFX_ByteString type = pDict->GetStringFor("Type"); - if (type == "Pages") { - pPageNode->m_type = PDF_PAGENODE_PAGES; - CPDF_Object* pKids = pDict->GetObjectFor("Kids"); - if (!pKids) { - m_docStatus = PDF_DATAAVAIL_PAGE; - return true; + const ByteString type = pDict->GetStringFor("Type"); + if (type == "Page") { + pPageNode->m_type = PDF_PAGENODE_PAGE; + return true; + } + + if (type != "Pages") { + m_docStatus = PDF_DATAAVAIL_ERROR; + return false; + } + + pPageNode->m_type = PDF_PAGENODE_PAGES; + CPDF_Object* pKids = pDict->GetObjectFor("Kids"); + if (!pKids) { + m_docStatus = PDF_DATAAVAIL_PAGE; + return true; + } + + switch (pKids->GetType()) { + case CPDF_Object::REFERENCE: { + CPDF_Reference* pKid = pKids->AsReference(); + auto pNode = pdfium::MakeUnique(); + pNode->m_dwPageNo = pKid->GetRefObjNum(); + pPageNode->m_ChildNodes.push_back(std::move(pNode)); + break; } + case CPDF_Object::ARRAY: { + CPDF_Array* pKidsArray = pKids->AsArray(); + for (size_t i = 0; i < pKidsArray->GetCount(); ++i) { + CPDF_Reference* pKid = ToReference(pKidsArray->GetObjectAt(i)); + if (!pKid) + continue; - switch (pKids->GetType()) { - case CPDF_Object::REFERENCE: { - CPDF_Reference* pKid = pKids->AsReference(); auto pNode = pdfium::MakeUnique(); pNode->m_dwPageNo = pKid->GetRefObjNum(); pPageNode->m_ChildNodes.push_back(std::move(pNode)); - } break; - case CPDF_Object::ARRAY: { - CPDF_Array* pKidsArray = pKids->AsArray(); - for (size_t i = 0; i < pKidsArray->GetCount(); ++i) { - CPDF_Reference* pKid = ToReference(pKidsArray->GetObjectAt(i)); - if (!pKid) - continue; - - auto pNode = pdfium::MakeUnique(); - pNode->m_dwPageNo = pKid->GetRefObjNum(); - pPageNode->m_ChildNodes.push_back(std::move(pNode)); - } - } break; - default: - break; + } + break; } - } else if (type == "Page") { - pPageNode->m_type = PDF_PAGENODE_PAGE; - } else { - m_docStatus = PDF_DATAAVAIL_ERROR; - return false; + default: + break; } return true; } @@ -1215,7 +647,6 @@ bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo, bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, int32_t iPage, int32_t& iCount, - DownloadHints* pHints, int level) { if (level >= kMaxPageRecursionDepth) return false; @@ -1232,12 +663,12 @@ bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, if (pNode->m_type == PDF_PAGENODE_UNKNOWN) { // Updates the type for the unknown page node. - if (!CheckUnknownPageNode(pNode->m_dwPageNo, pNode, pHints)) + if (!CheckUnknownPageNode(pNode->m_dwPageNo, pNode)) return false; } if (pNode->m_type == PDF_PAGENODE_ARRAY) { // Updates a more specific type for the array page node. - if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode, pHints)) + if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode)) return false; } switch (pNode->m_type) { @@ -1247,7 +678,7 @@ bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, m_pDocument->SetPageObjNum(iPage, pNode->m_dwPageNo); break; case PDF_PAGENODE_PAGES: - if (!CheckPageNode(*pNode, iPage, iCount, pHints, level + 1)) + if (!CheckPageNode(*pNode, iPage, iCount, level + 1)) return false; break; case PDF_PAGENODE_UNKNOWN: @@ -1263,7 +694,7 @@ bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, return true; } -bool CPDF_DataAvail::LoadDocPage(uint32_t dwPage, DownloadHints* pHints) { +bool CPDF_DataAvail::LoadDocPage(uint32_t dwPage) { FX_SAFE_INT32 safePage = pdfium::base::checked_cast(dwPage); int32_t iPage = safePage.ValueOrDie(); if (m_pDocument->GetPageCount() <= iPage || @@ -1276,13 +707,12 @@ bool CPDF_DataAvail::LoadDocPage(uint32_t dwPage, DownloadHints* pHints) { return true; } int32_t iCount = -1; - return CheckPageNode(m_PageNode, iPage, iCount, pHints, 0); + return CheckPageNode(m_PageNode, iPage, iCount, 0); } -bool CPDF_DataAvail::CheckPageCount(DownloadHints* pHints) { +bool CPDF_DataAvail::CheckPageCount() { bool bExists = false; - std::unique_ptr pPages = - GetObject(m_PagesObjNum, pHints, &bExists); + std::unique_ptr pPages = GetObject(m_PagesObjNum, &bExists); if (!bExists) { m_docStatus = PDF_DATAAVAIL_ERROR; return false; @@ -1301,11 +731,11 @@ bool CPDF_DataAvail::CheckPageCount(DownloadHints* pHints) { return pPagesDict->GetIntegerFor("Count") > 0; } -bool CPDF_DataAvail::LoadDocPages(DownloadHints* pHints) { - if (!CheckUnknownPageNode(m_PagesObjNum, &m_PageNode, pHints)) +bool CPDF_DataAvail::LoadDocPages() { + if (!CheckUnknownPageNode(m_PagesObjNum, &m_PageNode)) return false; - if (CheckPageCount(pHints)) { + if (CheckPageCount()) { m_docStatus = PDF_DATAAVAIL_PAGE; return true; } @@ -1314,9 +744,9 @@ bool CPDF_DataAvail::LoadDocPages(DownloadHints* pHints) { return false; } -bool CPDF_DataAvail::LoadPages(DownloadHints* pHints) { +bool CPDF_DataAvail::LoadPages() { while (!m_bPagesTreeLoad) { - if (!CheckPageStatus(pHints)) + if (!CheckPageStatus()) return false; } @@ -1327,26 +757,32 @@ bool CPDF_DataAvail::LoadPages(DownloadHints* pHints) { return false; } -CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData( - DownloadHints* pHints) { +CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData() { if (m_bLinearedDataOK) return DataAvailable; ASSERT(m_pLinearized); - if (!m_pLinearized->GetLastXRefOffset()) + if (!m_pLinearized->GetMainXRefTableFirstEntryOffset() || !m_pDocument || + !m_pDocument->GetParser() || !m_pDocument->GetParser()->GetTrailer()) { return DataError; + } if (!m_bMainXRefLoadTried) { - FX_SAFE_UINT32 data_size = m_dwFileLen; - data_size -= m_pLinearized->GetLastXRefOffset(); + const FX_SAFE_FILESIZE main_xref_offset = + m_pDocument->GetParser()->GetTrailer()->GetIntegerFor("Prev"); + if (!main_xref_offset.IsValid()) + return DataError; + + if (main_xref_offset.ValueOrDie() == 0) + return DataAvailable; + + FX_SAFE_SIZE_T data_size = m_dwFileLen; + data_size -= main_xref_offset.ValueOrDie(); if (!data_size.IsValid()) return DataError; - if (!m_pFileAvail->IsDataAvail(m_pLinearized->GetLastXRefOffset(), - data_size.ValueOrDie())) { - pHints->AddSegment(m_pLinearized->GetLastXRefOffset(), - data_size.ValueOrDie()); + if (!GetValidator()->CheckDataRangeAndRequestIfUnavailable( + main_xref_offset.ValueOrDie(), data_size.ValueOrDie())) return DataNotAvailable; - } CPDF_Parser::Error eRet = m_pDocument->GetParser()->LoadLinearizedMainXRefTable(); @@ -1364,223 +800,139 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData( return m_bLinearedDataOK ? DataAvailable : DataNotAvailable; } -bool CPDF_DataAvail::CheckPageAnnots(uint32_t dwPage, DownloadHints* pHints) { - if (m_objs_array.empty()) { - m_ObjectSet.clear(); - - FX_SAFE_INT32 safePage = pdfium::base::checked_cast(dwPage); - CPDF_Dictionary* pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); - if (!pPageDict) - return true; - - CPDF_Object* pAnnots = pPageDict->GetObjectFor("Annots"); - if (!pAnnots) - return true; - - std::vector obj_array; - obj_array.push_back(pAnnots); - if (!AreObjectsAvailable(obj_array, false, pHints, m_objs_array)) - return false; - - m_objs_array.clear(); - return true; - } - - std::vector new_objs_array; - if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) { - m_objs_array = new_objs_array; - return false; - } - m_objs_array.clear(); - return true; -} - -CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedFirstPage( - uint32_t dwPage, - DownloadHints* pHints) { - if (!m_bAnnotsLoad) { - if (!CheckPageAnnots(dwPage, pHints)) - return DataNotAvailable; - m_bAnnotsLoad = true; - } - const bool is_page_valid = ValidatePage(dwPage); - (void)is_page_valid; - ASSERT(is_page_valid); - return DataAvailable; -} - -bool CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary* pDict) { - CFX_AutoRestorer restorer(&s_CurrentDataAvailRecursionDepth); - if (++s_CurrentDataAvailRecursionDepth > kMaxDataAvailRecursionDepth) - return false; - - CPDF_Object* pParent = pDict->GetObjectFor("Parent"); - if (!pParent) - return false; - - CPDF_Dictionary* pParentDict = pParent->GetDict(); - if (!pParentDict) - return false; - - CPDF_Object* pRet = pParentDict->GetObjectFor("Resources"); - if (pRet) { - m_pPageResource = pRet; - return true; - } - - return HaveResourceAncestor(pParentDict); -} - CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( uint32_t dwPage, DownloadHints* pHints) { if (!m_pDocument) return DataError; + const FX_SAFE_INT32 safePage = pdfium::base::checked_cast(dwPage); + if (!safePage.IsValid()) + return DataError; + + if (safePage.ValueOrDie() >= m_pDocument->GetPageCount()) { + // This is XFA page. + return DataAvailable; + } + if (IsFirstCheck(dwPage)) { m_bCurPageDictLoadOK = false; - m_bPageLoadedOK = false; - m_bAnnotsLoad = false; - m_bNeedDownLoadResource = false; - m_objs_array.clear(); - m_ObjectSet.clear(); } if (pdfium::ContainsKey(m_pagesLoadState, dwPage)) return DataAvailable; + const HintsScope hints_scope(GetValidator().Get(), pHints); + if (m_pLinearized) { if (dwPage == m_pLinearized->GetFirstPageNo()) { - DocAvailStatus nRet = CheckLinearizedFirstPage(dwPage, pHints); - if (nRet == DataAvailable) - m_pagesLoadState.insert(dwPage); - return nRet; + CPDF_Dictionary* pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); + if (!pPageDict) + return DataError; + + auto page_num_obj = std::make_pair( + dwPage, pdfium::MakeUnique( + GetValidator().Get(), m_pDocument, pPageDict)); + + CPDF_PageObjectAvail* page_obj_avail = + m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get(); + // TODO(art-snake): Check resources. + return page_obj_avail->CheckAvail(); } - DocAvailStatus nResult = CheckLinearizedData(pHints); + DocAvailStatus nResult = CheckLinearizedData(); if (nResult != DataAvailable) return nResult; if (m_pHintTables) { - nResult = m_pHintTables->CheckPage(dwPage, pHints); + nResult = m_pHintTables->CheckPage(dwPage); if (nResult != DataAvailable) return nResult; - m_pagesLoadState.insert(dwPage); - return GetPage(dwPage) ? DataAvailable : DataError; + if (GetPage(dwPage)) { + m_pagesLoadState.insert(dwPage); + return DataAvailable; + } } - if (m_bMainXRefLoadedOK) { - if (m_bTotalLoadPageTree) { - if (!LoadPages(pHints)) - return DataNotAvailable; - } else { - if (!m_bCurPageDictLoadOK && !CheckPage(dwPage, pHints)) - return DataNotAvailable; - } - } else { - if (!LoadAllFile(pHints)) + if (!m_bMainXRefLoadedOK) { + if (!LoadAllFile()) return DataNotAvailable; m_pDocument->GetParser()->RebuildCrossRef(); ResetFirstCheck(dwPage); return DataAvailable; } - } else { - if (!m_bTotalLoadPageTree && !m_bCurPageDictLoadOK && - !CheckPage(dwPage, pHints)) { - return DataNotAvailable; - } - } - - if (m_bHaveAcroForm && !m_bAcroFormLoad) { - if (!CheckAcroFormSubObject(pHints)) - return DataNotAvailable; - m_bAcroFormLoad = true; - } - - if (!m_bPageLoadedOK) { - if (m_objs_array.empty()) { - m_ObjectSet.clear(); - - FX_SAFE_INT32 safePage = pdfium::base::checked_cast(dwPage); - m_pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); - if (!m_pPageDict) { - ResetFirstCheck(dwPage); - // This is XFA page. - return DataAvailable; - } - - std::vector obj_array; - obj_array.push_back(m_pPageDict); - if (!AreObjectsAvailable(obj_array, true, pHints, m_objs_array)) + if (m_bTotalLoadPageTree) { + if (!LoadPages()) return DataNotAvailable; - - m_objs_array.clear(); } else { - std::vector new_objs_array; - if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) { - m_objs_array = new_objs_array; + if (!m_bCurPageDictLoadOK && !CheckPage(dwPage)) return DataNotAvailable; - } } - m_objs_array.clear(); - m_bPageLoadedOK = true; - } - - if (!m_bAnnotsLoad) { - if (!CheckPageAnnots(dwPage, pHints)) + } else { + if (!m_bTotalLoadPageTree && !m_bCurPageDictLoadOK && !CheckPage(dwPage)) { return DataNotAvailable; - m_bAnnotsLoad = true; + } } - if (m_pPageDict && !m_bNeedDownLoadResource) { - m_pPageResource = m_pPageDict->GetObjectFor("Resources"); - m_bNeedDownLoadResource = - m_pPageResource || HaveResourceAncestor(m_pPageDict); - } + if (CheckAcroForm() == DocFormStatus::FormNotAvailable) + return DataNotAvailable; - if (m_bNeedDownLoadResource) { - if (!CheckResources(pHints)) - return DataNotAvailable; - m_bNeedDownLoadResource = false; + CPDF_Dictionary* pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); + if (!pPageDict) + return DataError; + + { + auto page_num_obj = std::make_pair( + dwPage, pdfium::MakeUnique( + GetValidator().Get(), m_pDocument, pPageDict)); + CPDF_PageObjectAvail* page_obj_avail = + m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get(); + const DocAvailStatus status = page_obj_avail->CheckAvail(); + if (status != DocAvailStatus::DataAvailable) + return status; } - m_bPageLoadedOK = false; - m_bAnnotsLoad = false; - m_bCurPageDictLoadOK = false; + const DocAvailStatus resources_status = CheckResources(pPageDict); + if (resources_status != DocAvailStatus::DataAvailable) + return resources_status; + m_bCurPageDictLoadOK = false; ResetFirstCheck(dwPage); m_pagesLoadState.insert(dwPage); - const bool is_page_valid = ValidatePage(dwPage); - (void)is_page_valid; - ASSERT(is_page_valid); return DataAvailable; } -bool CPDF_DataAvail::CheckResources(DownloadHints* pHints) { - if (m_objs_array.empty()) { - std::vector obj_array; - obj_array.push_back(m_pPageResource); - if (!AreObjectsAvailable(obj_array, true, pHints, m_objs_array)) - return false; +CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckResources( + const CPDF_Dictionary* page) { + ASSERT(page); + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); + const CPDF_Object* resources = GetResourceObject(page); + if (GetValidator()->has_read_problems()) + return DocAvailStatus::DataNotAvailable; + + if (!resources) + return DocAvailStatus::DataAvailable; + + CPDF_PageObjectAvail* resource_avail = + m_PagesResourcesAvail + .insert(std::make_pair( + resources, pdfium::MakeUnique( + GetValidator().Get(), m_pDocument, resources))) + .first->second.get(); + return resource_avail->CheckAvail(); +} - m_objs_array.clear(); - return true; - } - std::vector new_objs_array; - if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) { - m_objs_array = new_objs_array; - return false; - } - m_objs_array.clear(); - return true; +RetainPtr CPDF_DataAvail::GetFileRead() const { + return m_pFileRead; +} + +RetainPtr CPDF_DataAvail::GetValidator() const { + return m_pFileRead; } -void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, - uint32_t* pSize) { - if (pPos) - *pPos = m_dwLastXRefOffset; - if (pSize) - *pSize = (uint32_t)(m_dwFileLen - m_dwLastXRefOffset); +CPDF_SyntaxParser* CPDF_DataAvail::GetSyntaxParser() const { + return m_pDocument ? m_pDocument->GetParser()->m_pSyntax.get() + : m_parser.m_pSyntax.get(); } int CPDF_DataAvail::GetPageCount() const { @@ -1611,31 +963,34 @@ CPDF_Dictionary* CPDF_DataAvail::GetPage(int index) { m_pDocument->SetPageObjNum(index, dwObjNum); // Page object already can be parsed in document. if (!m_pDocument->GetIndirectObject(dwObjNum)) { - m_syntaxParser.InitParser( - m_pFileRead, pdfium::base::checked_cast(szPageStartPos)); m_pDocument->ReplaceIndirectObjectIfHigherGeneration( - dwObjNum, ParseIndirectObjectAt(0, dwObjNum, m_pDocument)); + dwObjNum, ParseIndirectObjectAt(szPageStartPos, dwObjNum, m_pDocument)); } - const bool is_page_valid = ValidatePage(index); - (void)is_page_valid; - ASSERT(is_page_valid); + if (!ValidatePage(index)) + return nullptr; return m_pDocument->GetPage(index); } CPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( DownloadHints* pHints) { + const HintsScope hints_scope(GetValidator().Get(), pHints); + return CheckAcroForm(); +} + +CPDF_DataAvail::DocFormStatus CPDF_DataAvail::CheckAcroForm() { if (!m_pDocument) return FormAvailable; + if (m_pLinearized) { - DocAvailStatus nDocStatus = CheckLinearizedData(pHints); + DocAvailStatus nDocStatus = CheckLinearizedData(); if (nDocStatus == DataError) return FormError; if (nDocStatus == DataNotAvailable) return FormNotAvailable; } - if (!m_bLinearizedFormParamLoad) { - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + if (!m_pFormAvail) { + const CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); if (!pRoot) return FormAvailable; @@ -1643,21 +998,20 @@ CPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( if (!pAcroForm) return FormNotExist; - m_objs_array.push_back(pAcroForm->GetDict()); - m_bLinearizedFormParamLoad = true; + m_pFormAvail = pdfium::MakeUnique( + GetValidator().Get(), m_pDocument, pAcroForm); } - - std::vector new_objs_array; - if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) { - m_objs_array = new_objs_array; - return FormNotAvailable; + switch (m_pFormAvail->CheckAvail()) { + case DocAvailStatus::DataError: + return DocFormStatus::FormError; + case DocAvailStatus::DataNotAvailable: + return DocFormStatus::FormNotAvailable; + case DocAvailStatus::DataAvailable: + return DocFormStatus::FormAvailable; + default: + NOTREACHED(); } - - m_objs_array.clear(); - const bool is_form_valid = ValidateForm(); - (void)is_form_valid; - ASSERT(is_form_valid); - return FormAvailable; + return DocFormStatus::FormError; } bool CPDF_DataAvail::ValidatePage(uint32_t dwPage) { @@ -1665,23 +1019,35 @@ bool CPDF_DataAvail::ValidatePage(uint32_t dwPage) { CPDF_Dictionary* pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); if (!pPageDict) return false; - std::vector obj_array; - obj_array.push_back(pPageDict); - std::vector dummy; - return AreObjectsAvailable(obj_array, true, nullptr, dummy); + CPDF_PageObjectAvail obj_avail(GetValidator().Get(), m_pDocument, pPageDict); + return obj_avail.CheckAvail() == DocAvailStatus::DataAvailable; } -bool CPDF_DataAvail::ValidateForm() { - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); - if (!pRoot) - return true; - CPDF_Object* pAcroForm = pRoot->GetObjectFor("AcroForm"); - if (!pAcroForm) - return false; - std::vector obj_array; - obj_array.push_back(pAcroForm); - std::vector dummy; - return AreObjectsAvailable(obj_array, true, nullptr, dummy); +std::pair> +CPDF_DataAvail::ParseDocument(const char* password) { + if (m_pDocument) { + // We already returned parsed document. + return std::make_pair(CPDF_Parser::HANDLER_ERROR, nullptr); + } + auto parser = pdfium::MakeUnique(); + parser->SetPassword(password); + auto document = pdfium::MakeUnique(std::move(parser)); + + CPDF_ReadValidator::Session read_session(GetValidator().Get()); + CPDF_Parser::Error error = document->GetParser()->StartLinearizedParse( + GetFileRead(), document.get()); + + // Additional check, that all ok. + if (GetValidator()->has_read_problems()) { + NOTREACHED(); + return std::make_pair(CPDF_Parser::HANDLER_ERROR, nullptr); + } + + if (error != CPDF_Parser::SUCCESS) + return std::make_pair(error, nullptr); + + m_pDocument = document.get(); + return std::make_pair(CPDF_Parser::SUCCESS, std::move(document)); } CPDF_DataAvail::PageNode::PageNode() : m_type(PDF_PAGENODE_UNKNOWN) {} diff --git a/core/fpdfapi/parser/cpdf_data_avail.h b/core/fpdfapi/parser/cpdf_data_avail.h index 65638cff0b29aed373fa35b1022fd8bbb99358fd..dfb1f0cabf914a2c82e7e7b00bedb47c1afe5d81 100644 --- a/core/fpdfapi/parser/cpdf_data_avail.h +++ b/core/fpdfapi/parser/cpdf_data_avail.h @@ -7,34 +7,32 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_DATA_AVAIL_H_ #define CORE_FPDFAPI_PARSER_CPDF_DATA_AVAIL_H_ +#include #include #include +#include #include #include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/cpdf_syntax_parser.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/unowned_ptr.h" +class CPDF_CrossRefAvail; class CPDF_Dictionary; class CPDF_HintTables; class CPDF_IndirectObjectHolder; class CPDF_LinearizedHeader; +class CPDF_PageObjectAvail; class CPDF_Parser; +class CPDF_ReadValidator; enum PDF_DATAAVAIL_STATUS { PDF_DATAAVAIL_HEADER = 0, PDF_DATAAVAIL_FIRSTPAGE, PDF_DATAAVAIL_HINTTABLE, - PDF_DATAAVAIL_END, - PDF_DATAAVAIL_CROSSREF, - PDF_DATAAVAIL_CROSSREF_ITEM, - PDF_DATAAVAIL_CROSSREF_STREAM, - PDF_DATAAVAIL_TRAILER, PDF_DATAAVAIL_LOADALLCROSSREF, PDF_DATAAVAIL_ROOT, PDF_DATAAVAIL_INFO, - PDF_DATAAVAIL_ACROFORM, - PDF_DATAAVAIL_ACROFORM_SUBOBJECT, PDF_DATAAVAIL_PAGETREE, PDF_DATAAVAIL_PAGE, PDF_DATAAVAIL_PAGE_LATERLOAD, @@ -42,7 +40,6 @@ enum PDF_DATAAVAIL_STATUS { PDF_DATAAVAIL_DONE, PDF_DATAAVAIL_ERROR, PDF_DATAAVAIL_LOADALLFILE, - PDF_DATAAVAIL_TRAILER_APPEND }; enum PDF_PAGENODE_TYPE { @@ -85,33 +82,33 @@ class CPDF_DataAvail final { class FileAvail { public: virtual ~FileAvail(); - virtual bool IsDataAvail(FX_FILESIZE offset, uint32_t size) = 0; + virtual bool IsDataAvail(FX_FILESIZE offset, size_t size) = 0; }; class DownloadHints { public: virtual ~DownloadHints(); - virtual void AddSegment(FX_FILESIZE offset, uint32_t size) = 0; + virtual void AddSegment(FX_FILESIZE offset, size_t size) = 0; }; CPDF_DataAvail(FileAvail* pFileAvail, - const CFX_RetainPtr& pFileRead, + const RetainPtr& pFileRead, bool bSupportHintTable); ~CPDF_DataAvail(); - bool IsDataAvail(FX_FILESIZE offset, uint32_t size, DownloadHints* pHints); DocAvailStatus IsDocAvail(DownloadHints* pHints); - void SetDocument(CPDF_Document* pDoc); DocAvailStatus IsPageAvail(uint32_t dwPage, DownloadHints* pHints); DocFormStatus IsFormAvail(DownloadHints* pHints); DocLinearizationStatus IsLinearizedPDF(); - bool IsLinearized(); - void GetLinearizedMainXRefInfo(FX_FILESIZE* pPos, uint32_t* pSize); - CFX_RetainPtr GetFileRead() const { - return m_pFileRead; - } + RetainPtr GetFileRead() const; int GetPageCount() const; CPDF_Dictionary* GetPage(int index); + RetainPtr GetValidator() const; + + std::pair> ParseDocument( + const char* password); + + const CPDF_HintTables* GetHintTables() const { return m_pHintTables.get(); } protected: class PageNode { @@ -124,134 +121,84 @@ class CPDF_DataAvail final { std::vector> m_ChildNodes; }; - static const int kMaxDataAvailRecursionDepth = 64; - static int s_CurrentDataAvailRecursionDepth; static const int kMaxPageRecursionDepth = 1024; - uint32_t GetObjectSize(uint32_t objnum, FX_FILESIZE& offset); - bool AreObjectsAvailable(std::vector& obj_array, - bool bParsePage, - DownloadHints* pHints, - std::vector& ret_array); - bool CheckDocStatus(DownloadHints* pHints); - bool CheckHeader(DownloadHints* pHints); - bool CheckFirstPage(DownloadHints* pHints); - bool CheckHintTables(DownloadHints* pHints); - bool CheckEnd(DownloadHints* pHints); - bool CheckCrossRef(DownloadHints* pHints); - bool CheckCrossRefItem(DownloadHints* pHints); - bool CheckTrailer(DownloadHints* pHints); - bool CheckRoot(DownloadHints* pHints); - bool CheckInfo(DownloadHints* pHints); - bool CheckPages(DownloadHints* pHints); - bool CheckPage(DownloadHints* pHints); - bool CheckResources(DownloadHints* pHints); - bool CheckAnnots(DownloadHints* pHints); - bool CheckAcroForm(DownloadHints* pHints); - bool CheckAcroFormSubObject(DownloadHints* pHints); - bool CheckTrailerAppend(DownloadHints* pHints); - bool CheckPageStatus(DownloadHints* pHints); - bool CheckAllCrossRefStream(DownloadHints* pHints); - - int32_t CheckCrossRefStream(DownloadHints* pHints, FX_FILESIZE& xref_offset); - bool IsLinearizedFile(uint8_t* pData, uint32_t dwLen); - void SetStartOffset(FX_FILESIZE dwOffset); - bool GetNextToken(CFX_ByteString& token); - bool GetNextChar(uint8_t& ch); + bool CheckDocStatus(); + bool CheckHeader(); + bool CheckFirstPage(); + bool CheckHintTables(); + bool CheckRoot(); + bool CheckInfo(); + bool CheckPages(); + bool CheckPage(); + DocAvailStatus CheckResources(const CPDF_Dictionary* page); + DocFormStatus CheckAcroForm(); + bool CheckPageStatus(); + + DocAvailStatus CheckHeaderAndLinearized(); std::unique_ptr ParseIndirectObjectAt( FX_FILESIZE pos, uint32_t objnum, CPDF_IndirectObjectHolder* pObjList = nullptr); std::unique_ptr GetObject(uint32_t objnum, - DownloadHints* pHints, bool* pExistInFile); bool GetPageKids(CPDF_Parser* pParser, CPDF_Object* pPages); bool PreparePageItem(); - bool LoadPages(DownloadHints* pHints); - bool LoadAllXref(DownloadHints* pHints); - bool LoadAllFile(DownloadHints* pHints); - DocAvailStatus CheckLinearizedData(DownloadHints* pHints); - bool CheckPageAnnots(uint32_t dwPage, DownloadHints* pHints); - - DocAvailStatus CheckLinearizedFirstPage(uint32_t dwPage, - DownloadHints* pHints); - bool HaveResourceAncestor(CPDF_Dictionary* pDict); - bool CheckPage(uint32_t dwPage, DownloadHints* pHints); - bool LoadDocPages(DownloadHints* pHints); - bool LoadDocPage(uint32_t dwPage, DownloadHints* pHints); + bool LoadPages(); + bool CheckAndLoadAllXref(); + bool LoadAllFile(); + DocAvailStatus CheckLinearizedData(); + + bool CheckPage(uint32_t dwPage); + bool LoadDocPages(); + bool LoadDocPage(uint32_t dwPage); bool CheckPageNode(const PageNode& pageNode, int32_t iPage, int32_t& iCount, - DownloadHints* pHints, int level); - bool CheckUnknownPageNode(uint32_t dwPageNo, - PageNode* pPageNode, - DownloadHints* pHints); - bool CheckArrayPageNode(uint32_t dwPageNo, - PageNode* pPageNode, - DownloadHints* pHints); - bool CheckPageCount(DownloadHints* pHints); + bool CheckUnknownPageNode(uint32_t dwPageNo, PageNode* pPageNode); + bool CheckArrayPageNode(uint32_t dwPageNo, PageNode* pPageNode); + bool CheckPageCount(); bool IsFirstCheck(uint32_t dwPage); void ResetFirstCheck(uint32_t dwPage); bool ValidatePage(uint32_t dwPage); - bool ValidateForm(); + CPDF_SyntaxParser* GetSyntaxParser() const; FileAvail* const m_pFileAvail; - CFX_RetainPtr m_pFileRead; + RetainPtr m_pFileRead; CPDF_Parser m_parser; - CPDF_SyntaxParser m_syntaxParser; std::unique_ptr m_pRoot; - uint32_t m_dwRootObjNum; - uint32_t m_dwInfoObjNum; + uint32_t m_dwRootObjNum = 0; + uint32_t m_dwInfoObjNum = 0; std::unique_ptr m_pLinearized; - CPDF_Object* m_pTrailer; - bool m_bDocAvail; - FX_FILESIZE m_dwHeaderOffset; - FX_FILESIZE m_dwLastXRefOffset; - FX_FILESIZE m_dwXRefOffset; - FX_FILESIZE m_dwTrailerOffset; - FX_FILESIZE m_dwCurrentOffset; - PDF_DATAAVAIL_STATUS m_docStatus; - FX_FILESIZE m_dwFileLen; - CPDF_Document* m_pDocument; - std::set m_ObjectSet; - std::vector m_objs_array; - FX_FILESIZE m_Pos; - FX_FILESIZE m_bufferOffset; - uint32_t m_bufferSize; - CFX_ByteString m_WordBuf; - uint8_t m_bufferData[512]; - std::vector m_XRefStreamList; + bool m_bDocAvail = false; + std::unique_ptr m_pCrossRefAvail; + PDF_DATAAVAIL_STATUS m_docStatus = PDF_DATAAVAIL_HEADER; + const FX_FILESIZE m_dwFileLen; + CPDF_Document* m_pDocument = nullptr; std::vector m_PageObjList; - uint32_t m_PagesObjNum; - bool m_bLinearedDataOK; - bool m_bMainXRefLoadTried; - bool m_bMainXRefLoadedOK; - bool m_bPagesTreeLoad; - bool m_bPagesLoad; - CPDF_Parser* m_pCurrentParser; - FX_FILESIZE m_dwCurrentXRefSteam; - bool m_bAnnotsLoad; - bool m_bHaveAcroForm; - uint32_t m_dwAcroFormObjNum; - bool m_bAcroFormLoad; - CPDF_Object* m_pAcroForm; - std::vector m_arrayAcroforms; - CPDF_Dictionary* m_pPageDict; - CPDF_Object* m_pPageResource; - bool m_bNeedDownLoadResource; - bool m_bPageLoadedOK; - bool m_bLinearizedFormParamLoad; + uint32_t m_PagesObjNum = 0; + bool m_bLinearedDataOK = false; + bool m_bMainXRefLoadTried = false; + bool m_bMainXRefLoadedOK = false; + bool m_bPagesTreeLoad = false; + bool m_bPagesLoad = false; + CPDF_Parser* m_pCurrentParser = nullptr; + std::unique_ptr m_pFormAvail; std::vector> m_PagesArray; - uint32_t m_dwEncryptObjNum; - FX_FILESIZE m_dwPrevXRefOffset; - bool m_bTotalLoadPageTree; - bool m_bCurPageDictLoadOK; + uint32_t m_dwEncryptObjNum = 0; + bool m_bTotalLoadPageTree = false; + bool m_bCurPageDictLoadOK = false; PageNode m_PageNode; std::set m_pageMapCheckState; std::set m_pagesLoadState; + std::set m_SeenPrevPositions; std::unique_ptr m_pHintTables; - bool m_bSupportHintTable; + const bool m_bSupportHintTable; + std::map> m_PagesObjAvail; + std::map> + m_PagesResourcesAvail; + bool m_bHeaderAvail = false; }; #endif // CORE_FPDFAPI_PARSER_CPDF_DATA_AVAIL_H_ diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp index 40877539b53e23eda1561d5a78dc71133f88c54f..1e7f6a9a9b1dfe4f6e5753f1583a67f9f8aa5666 100644 --- a/core/fpdfapi/parser/cpdf_dictionary.cpp +++ b/core/fpdfapi/parser/cpdf_dictionary.cpp @@ -11,18 +11,21 @@ #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_boolean.h" +#include "core/fpdfapi/parser/cpdf_crypto_handler.h" #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/logging.h" #include "third_party/base/stl_util.h" CPDF_Dictionary::CPDF_Dictionary() - : CPDF_Dictionary(CFX_WeakPtr()) {} + : CPDF_Dictionary(WeakPtr()) {} -CPDF_Dictionary::CPDF_Dictionary(const CFX_WeakPtr& pPool) +CPDF_Dictionary::CPDF_Dictionary(const WeakPtr& pPool) : m_pPool(pPool) {} CPDF_Dictionary::~CPDF_Dictionary() { @@ -68,65 +71,64 @@ std::unique_ptr CPDF_Dictionary::CloneNonCyclic( auto pCopy = pdfium::MakeUnique(m_pPool); for (const auto& it : *this) { if (!pdfium::ContainsKey(*pVisited, it.second.get())) { - pCopy->m_Map.insert(std::make_pair( - it.first, it.second->CloneNonCyclic(bDirect, pVisited))); + std::set visited(*pVisited); + if (auto obj = it.second->CloneNonCyclic(bDirect, &visited)) + pCopy->m_Map.insert(std::make_pair(it.first, std::move(obj))); } } return std::move(pCopy); } -CPDF_Object* CPDF_Dictionary::GetObjectFor(const CFX_ByteString& key) const { +CPDF_Object* CPDF_Dictionary::GetObjectFor(const ByteString& key) const { auto it = m_Map.find(key); return it != m_Map.end() ? it->second.get() : nullptr; } -CPDF_Object* CPDF_Dictionary::GetDirectObjectFor( - const CFX_ByteString& key) const { +CPDF_Object* CPDF_Dictionary::GetDirectObjectFor(const ByteString& key) const { CPDF_Object* p = GetObjectFor(key); return p ? p->GetDirect() : nullptr; } -CFX_ByteString CPDF_Dictionary::GetStringFor(const CFX_ByteString& key) const { +ByteString CPDF_Dictionary::GetStringFor(const ByteString& key) const { CPDF_Object* p = GetObjectFor(key); - return p ? p->GetString() : CFX_ByteString(); + return p ? p->GetString() : ByteString(); } -CFX_WideString CPDF_Dictionary::GetUnicodeTextFor( - const CFX_ByteString& key) const { +WideString CPDF_Dictionary::GetUnicodeTextFor(const ByteString& key) const { CPDF_Object* p = GetObjectFor(key); if (CPDF_Reference* pRef = ToReference(p)) p = pRef->GetDirect(); - return p ? p->GetUnicodeText() : CFX_WideString(); + return p ? p->GetUnicodeText() : WideString(); } -CFX_ByteString CPDF_Dictionary::GetStringFor(const CFX_ByteString& key, - const CFX_ByteString& def) const { +ByteString CPDF_Dictionary::GetStringFor(const ByteString& key, + const ByteString& def) const { CPDF_Object* p = GetObjectFor(key); - return p ? p->GetString() : CFX_ByteString(def); + return p ? p->GetString() : ByteString(def); } -int CPDF_Dictionary::GetIntegerFor(const CFX_ByteString& key) const { +int CPDF_Dictionary::GetIntegerFor(const ByteString& key) const { CPDF_Object* p = GetObjectFor(key); return p ? p->GetInteger() : 0; } -int CPDF_Dictionary::GetIntegerFor(const CFX_ByteString& key, int def) const { +int CPDF_Dictionary::GetIntegerFor(const ByteString& key, int def) const { CPDF_Object* p = GetObjectFor(key); return p ? p->GetInteger() : def; } -FX_FLOAT CPDF_Dictionary::GetNumberFor(const CFX_ByteString& key) const { +float CPDF_Dictionary::GetNumberFor(const ByteString& key) const { CPDF_Object* p = GetObjectFor(key); return p ? p->GetNumber() : 0; } -bool CPDF_Dictionary::GetBooleanFor(const CFX_ByteString& key, +bool CPDF_Dictionary::GetBooleanFor(const ByteString& key, bool bDefault) const { CPDF_Object* p = GetObjectFor(key); return ToBoolean(p) ? p->GetInteger() != 0 : bDefault; } -CPDF_Dictionary* CPDF_Dictionary::GetDictFor(const CFX_ByteString& key) const { +CPDF_Dictionary* CPDF_Dictionary::GetDictFor(const ByteString& key) const { CPDF_Object* p = GetDirectObjectFor(key); if (!p) return nullptr; @@ -137,15 +139,15 @@ CPDF_Dictionary* CPDF_Dictionary::GetDictFor(const CFX_ByteString& key) const { return nullptr; } -CPDF_Array* CPDF_Dictionary::GetArrayFor(const CFX_ByteString& key) const { +CPDF_Array* CPDF_Dictionary::GetArrayFor(const ByteString& key) const { return ToArray(GetDirectObjectFor(key)); } -CPDF_Stream* CPDF_Dictionary::GetStreamFor(const CFX_ByteString& key) const { +CPDF_Stream* CPDF_Dictionary::GetStreamFor(const ByteString& key) const { return ToStream(GetDirectObjectFor(key)); } -CFX_FloatRect CPDF_Dictionary::GetRectFor(const CFX_ByteString& key) const { +CFX_FloatRect CPDF_Dictionary::GetRectFor(const ByteString& key) const { CFX_FloatRect rect; CPDF_Array* pArray = GetArrayFor(key); if (pArray) @@ -153,7 +155,7 @@ CFX_FloatRect CPDF_Dictionary::GetRectFor(const CFX_ByteString& key) const { return rect; } -CFX_Matrix CPDF_Dictionary::GetMatrixFor(const CFX_ByteString& key) const { +CFX_Matrix CPDF_Dictionary::GetMatrixFor(const ByteString& key) const { CFX_Matrix matrix; CPDF_Array* pArray = GetArrayFor(key); if (pArray) @@ -161,18 +163,15 @@ CFX_Matrix CPDF_Dictionary::GetMatrixFor(const CFX_ByteString& key) const { return matrix; } -bool CPDF_Dictionary::KeyExist(const CFX_ByteString& key) const { +bool CPDF_Dictionary::KeyExist(const ByteString& key) const { return pdfium::ContainsKey(m_Map, key); } bool CPDF_Dictionary::IsSignatureDict() const { - CPDF_Object* pType = GetDirectObjectFor("Type"); - if (!pType) - pType = GetDirectObjectFor("FT"); - return pType && pType->GetString() == "Sig"; + return CPDF_CryptoHandler::IsSignatureDictionary(this); } -CPDF_Object* CPDF_Dictionary::SetFor(const CFX_ByteString& key, +CPDF_Object* CPDF_Dictionary::SetFor(const ByteString& key, std::unique_ptr pObj) { if (!pObj) { m_Map.erase(key); @@ -185,7 +184,7 @@ CPDF_Object* CPDF_Dictionary::SetFor(const CFX_ByteString& key, } void CPDF_Dictionary::ConvertToIndirectObjectFor( - const CFX_ByteString& key, + const ByteString& key, CPDF_IndirectObjectHolder* pHolder) { auto it = m_Map.find(key); if (it == m_Map.end() || it->second->IsReference()) @@ -195,12 +194,18 @@ void CPDF_Dictionary::ConvertToIndirectObjectFor( it->second = pdfium::MakeUnique(pHolder, pObj->GetObjNum()); } -void CPDF_Dictionary::RemoveFor(const CFX_ByteString& key) { - m_Map.erase(key); +std::unique_ptr CPDF_Dictionary::RemoveFor(const ByteString& key) { + std::unique_ptr result; + auto it = m_Map.find(key); + if (it != m_Map.end()) { + result = std::move(it->second); + m_Map.erase(it); + } + return result; } -void CPDF_Dictionary::ReplaceKey(const CFX_ByteString& oldkey, - const CFX_ByteString& newkey) { +void CPDF_Dictionary::ReplaceKey(const ByteString& oldkey, + const ByteString& newkey) { auto old_it = m_Map.find(oldkey); if (old_it == m_Map.end()) return; @@ -213,7 +218,7 @@ void CPDF_Dictionary::ReplaceKey(const CFX_ByteString& oldkey, m_Map.erase(old_it); } -void CPDF_Dictionary::SetRectFor(const CFX_ByteString& key, +void CPDF_Dictionary::SetRectFor(const ByteString& key, const CFX_FloatRect& rect) { CPDF_Array* pArray = SetNewFor(key); pArray->AddNew(rect.left); @@ -222,7 +227,7 @@ void CPDF_Dictionary::SetRectFor(const CFX_ByteString& key, pArray->AddNew(rect.top); } -void CPDF_Dictionary::SetMatrixFor(const CFX_ByteString& key, +void CPDF_Dictionary::SetMatrixFor(const ByteString& key, const CFX_Matrix& matrix) { CPDF_Array* pArray = SetNewFor(key); pArray->AddNew(matrix.a); @@ -233,6 +238,31 @@ void CPDF_Dictionary::SetMatrixFor(const CFX_ByteString& key, pArray->AddNew(matrix.f); } -CFX_ByteString CPDF_Dictionary::MaybeIntern(const CFX_ByteString& str) { +ByteString CPDF_Dictionary::MaybeIntern(const ByteString& str) { return m_pPool ? m_pPool->Intern(str) : str; } + +bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive) const { + if (!archive->WriteString("<<")) + return false; + + for (const auto& it : *this) { + const ByteString& key = it.first; + CPDF_Object* pValue = it.second.get(); + if (!archive->WriteString("/") || + !archive->WriteString(PDF_NameEncode(key).AsStringView())) { + return false; + } + + if (!pValue->IsInline()) { + if (!archive->WriteString(" ") || + !archive->WriteDWord(pValue->GetObjNum()) || + !archive->WriteString(" 0 R")) { + return false; + } + } else if (!pValue->WriteTo(archive)) { + return false; + } + } + return archive->WriteString(">>"); +} diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h index 13cbdcf7ac99cd74b7172d587208b7181cec68ae..688e88e510db79f46d707ab9b8a2999aa2c3f6f4 100644 --- a/core/fpdfapi/parser/cpdf_dictionary.h +++ b/core/fpdfapi/parser/cpdf_dictionary.h @@ -13,10 +13,10 @@ #include #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" #include "third_party/base/ptr_util.h" class CPDF_IndirectObjectHolder; @@ -24,10 +24,10 @@ class CPDF_IndirectObjectHolder; class CPDF_Dictionary : public CPDF_Object { public: using const_iterator = - std::map>::const_iterator; + std::map>::const_iterator; CPDF_Dictionary(); - explicit CPDF_Dictionary(const CFX_WeakPtr& pPool); + explicit CPDF_Dictionary(const WeakPtr& pPool); ~CPDF_Dictionary() override; // CPDF_Object: @@ -37,78 +37,76 @@ class CPDF_Dictionary : public CPDF_Object { bool IsDictionary() const override; CPDF_Dictionary* AsDictionary() override; const CPDF_Dictionary* AsDictionary() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; size_t GetCount() const { return m_Map.size(); } - CPDF_Object* GetObjectFor(const CFX_ByteString& key) const; - CPDF_Object* GetDirectObjectFor(const CFX_ByteString& key) const; - CFX_ByteString GetStringFor(const CFX_ByteString& key) const; - CFX_ByteString GetStringFor(const CFX_ByteString& key, - const CFX_ByteString& default_str) const; - CFX_WideString GetUnicodeTextFor(const CFX_ByteString& key) const; - int GetIntegerFor(const CFX_ByteString& key) const; - int GetIntegerFor(const CFX_ByteString& key, int default_int) const; - bool GetBooleanFor(const CFX_ByteString& key, bool bDefault = false) const; - FX_FLOAT GetNumberFor(const CFX_ByteString& key) const; - CPDF_Dictionary* GetDictFor(const CFX_ByteString& key) const; - CPDF_Stream* GetStreamFor(const CFX_ByteString& key) const; - CPDF_Array* GetArrayFor(const CFX_ByteString& key) const; - CFX_FloatRect GetRectFor(const CFX_ByteString& key) const; - CFX_Matrix GetMatrixFor(const CFX_ByteString& key) const; - FX_FLOAT GetFloatFor(const CFX_ByteString& key) const { - return GetNumberFor(key); - } - - bool KeyExist(const CFX_ByteString& key) const; + CPDF_Object* GetObjectFor(const ByteString& key) const; + CPDF_Object* GetDirectObjectFor(const ByteString& key) const; + ByteString GetStringFor(const ByteString& key) const; + ByteString GetStringFor(const ByteString& key, + const ByteString& default_str) const; + WideString GetUnicodeTextFor(const ByteString& key) const; + int GetIntegerFor(const ByteString& key) const; + int GetIntegerFor(const ByteString& key, int default_int) const; + bool GetBooleanFor(const ByteString& key, bool bDefault = false) const; + float GetNumberFor(const ByteString& key) const; + CPDF_Dictionary* GetDictFor(const ByteString& key) const; + CPDF_Stream* GetStreamFor(const ByteString& key) const; + CPDF_Array* GetArrayFor(const ByteString& key) const; + CFX_FloatRect GetRectFor(const ByteString& key) const; + CFX_Matrix GetMatrixFor(const ByteString& key) const; + float GetFloatFor(const ByteString& key) const { return GetNumberFor(key); } + + bool KeyExist(const ByteString& key) const; bool IsSignatureDict() const; // Set* functions invalidate iterators for the element with the key |key|. // Takes ownership of |pObj|, returns an unowned pointer to it. - CPDF_Object* SetFor(const CFX_ByteString& key, - std::unique_ptr pObj); + CPDF_Object* SetFor(const ByteString& key, std::unique_ptr pObj); // Creates a new object owned by the dictionary and returns an unowned // pointer to it. template typename std::enable_if::value, T*>::type SetNewFor( - const CFX_ByteString& key, + const ByteString& key, Args&&... args) { return static_cast( SetFor(key, pdfium::MakeUnique(std::forward(args)...))); } template typename std::enable_if::value, T*>::type SetNewFor( - const CFX_ByteString& key, + const ByteString& key, Args&&... args) { return static_cast(SetFor( key, pdfium::MakeUnique(m_pPool, std::forward(args)...))); } // Convenience functions to convert native objects to array form. - void SetRectFor(const CFX_ByteString& key, const CFX_FloatRect& rect); - void SetMatrixFor(const CFX_ByteString& key, const CFX_Matrix& matrix); + void SetRectFor(const ByteString& key, const CFX_FloatRect& rect); + void SetMatrixFor(const ByteString& key, const CFX_Matrix& matrix); - void ConvertToIndirectObjectFor(const CFX_ByteString& key, + void ConvertToIndirectObjectFor(const ByteString& key, CPDF_IndirectObjectHolder* pHolder); // Invalidates iterators for the element with the key |key|. - void RemoveFor(const CFX_ByteString& key); + std::unique_ptr RemoveFor(const ByteString& key); // Invalidates iterators for the element with the key |oldkey|. - void ReplaceKey(const CFX_ByteString& oldkey, const CFX_ByteString& newkey); + void ReplaceKey(const ByteString& oldkey, const ByteString& newkey); const_iterator begin() const { return m_Map.begin(); } const_iterator end() const { return m_Map.end(); } - CFX_WeakPtr GetByteStringPool() const { return m_pPool; } + WeakPtr GetByteStringPool() const { return m_pPool; } protected: - CFX_ByteString MaybeIntern(const CFX_ByteString& str); + ByteString MaybeIntern(const ByteString& str); std::unique_ptr CloneNonCyclic( bool bDirect, std::set* visited) const override; - CFX_WeakPtr m_pPool; - std::map> m_Map; + WeakPtr m_pPool; + std::map> m_Map; }; inline CPDF_Dictionary* ToDictionary(CPDF_Object* obj) { diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp index 21eb61a9915edcd5e282a2434bc98908b806c64a..565886a3a5c5229402d2a8f39e845d1be62d9679 100644 --- a/core/fpdfapi/parser/cpdf_document.cpp +++ b/core/fpdfapi/parser/cpdf_document.cpp @@ -14,8 +14,8 @@ #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/font/cpdf_fontencoding.h" #include "core/fpdfapi/page/cpdf_docpagedata.h" +#include "core/fpdfapi/page/cpdf_iccprofile.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_linearized_header.h" @@ -28,6 +28,7 @@ #include "core/fpdfapi/render/cpdf_dibsource.h" #include "core/fpdfapi/render/cpdf_docrenderdata.h" #include "core/fxcodec/JBig2_DocumentContext.h" +#include "core/fxcrt/fx_codepage.h" #include "core/fxge/cfx_unicodeencoding.h" #include "core/fxge/fx_font.h" #include "third_party/base/ptr_util.h" @@ -37,7 +38,7 @@ namespace { const int FX_MAX_PAGE_LEVEL = 1024; -const uint16_t g_FX_CP874Unicodes[128] = { +const uint16_t g_FX_MSDOSThaiUnicodes[128] = { 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x0000, 0x0000, @@ -54,7 +55,7 @@ const uint16_t g_FX_CP874Unicodes[128] = { 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000, }; -const uint16_t g_FX_CP1250Unicodes[128] = { +const uint16_t g_FX_MSWinEasternEuropeanUnicodes[128] = { 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, @@ -71,7 +72,7 @@ const uint16_t g_FX_CP1250Unicodes[128] = { 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9, }; -const uint16_t g_FX_CP1251Unicodes[128] = { +const uint16_t g_FX_MSWinCyrillicUnicodes[128] = { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, @@ -88,7 +89,7 @@ const uint16_t g_FX_CP1251Unicodes[128] = { 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, }; -const uint16_t g_FX_CP1253Unicodes[128] = { +const uint16_t g_FX_MSWinGreekUnicodes[128] = { 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, @@ -105,7 +106,7 @@ const uint16_t g_FX_CP1253Unicodes[128] = { 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000, }; -const uint16_t g_FX_CP1254Unicodes[128] = { +const uint16_t g_FX_MSWinTurkishUnicodes[128] = { 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, @@ -122,7 +123,7 @@ const uint16_t g_FX_CP1254Unicodes[128] = { 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF, }; -const uint16_t g_FX_CP1255Unicodes[128] = { +const uint16_t g_FX_MSWinHebrewUnicodes[128] = { 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0000, @@ -139,7 +140,7 @@ const uint16_t g_FX_CP1255Unicodes[128] = { 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000, }; -const uint16_t g_FX_CP1256Unicodes[128] = { +const uint16_t g_FX_MSWinArabicUnicodes[128] = { 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691, @@ -156,7 +157,7 @@ const uint16_t g_FX_CP1256Unicodes[128] = { 0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2, }; -const uint16_t g_FX_CP1257Unicodes[128] = { +const uint16_t g_FX_MSWinBalticUnicodes[128] = { 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, @@ -180,14 +181,14 @@ struct FX_CharsetUnicodes { }; const FX_CharsetUnicodes g_FX_CharsetUnicodes[] = { - {FXFONT_THAI_CHARSET, g_FX_CP874Unicodes}, - {FXFONT_EASTEUROPE_CHARSET, g_FX_CP1250Unicodes}, - {FXFONT_RUSSIAN_CHARSET, g_FX_CP1251Unicodes}, - {FXFONT_GREEK_CHARSET, g_FX_CP1253Unicodes}, - {FXFONT_TURKISH_CHARSET, g_FX_CP1254Unicodes}, - {FXFONT_HEBREW_CHARSET, g_FX_CP1255Unicodes}, - {FXFONT_ARABIC_CHARSET, g_FX_CP1256Unicodes}, - {FXFONT_BALTIC_CHARSET, g_FX_CP1257Unicodes}, + {FX_CHARSET_Thai, g_FX_MSDOSThaiUnicodes}, + {FX_CHARSET_MSWin_EasternEuropean, g_FX_MSWinEasternEuropeanUnicodes}, + {FX_CHARSET_MSWin_Cyrillic, g_FX_MSWinCyrillicUnicodes}, + {FX_CHARSET_MSWin_Greek, g_FX_MSWinGreekUnicodes}, + {FX_CHARSET_MSWin_Turkish, g_FX_MSWinTurkishUnicodes}, + {FX_CHARSET_MSWin_Hebrew, g_FX_MSWinHebrewUnicodes}, + {FX_CHARSET_MSWin_Arabic, g_FX_MSWinArabicUnicodes}, + {FX_CHARSET_MSWin_Baltic, g_FX_MSWinBalticUnicodes}, }; void InsertWidthArrayImpl(int* widths, int size, CPDF_Array* pWidthArray) { @@ -208,7 +209,7 @@ void InsertWidthArrayImpl(int* widths, int size, CPDF_Array* pWidthArray) { FX_Free(widths); } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ void InsertWidthArray(HDC hDC, int start, int end, CPDF_Array* pWidthArray) { int size = end - start + 1; int* widths = FX_Alloc(int, size); @@ -216,8 +217,8 @@ void InsertWidthArray(HDC hDC, int start, int end, CPDF_Array* pWidthArray) { InsertWidthArrayImpl(widths, size, pWidthArray); } -CFX_ByteString FPDF_GetPSNameFromTT(HDC hDC) { - CFX_ByteString result; +ByteString FPDF_GetPSNameFromTT(HDC hDC) { + ByteString result; DWORD size = ::GetFontData(hDC, 'eman', 0, nullptr, 0); if (size != GDI_ERROR) { LPBYTE buffer = FX_Alloc(BYTE, size); @@ -227,12 +228,12 @@ CFX_ByteString FPDF_GetPSNameFromTT(HDC hDC) { } return result; } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ void InsertWidthArray1(CFX_Font* pFont, CFX_UnicodeEncoding* pEncoding, - FX_WCHAR start, - FX_WCHAR end, + wchar_t start, + wchar_t end, CPDF_Array* pWidthArray) { int size = end - start + 1; int* widths = FX_Alloc(int, size); @@ -298,7 +299,7 @@ int CalculateFlags(bool bold, void ProcessNonbCJK(CPDF_Dictionary* pBaseDict, bool bold, bool italic, - CFX_ByteString basefont, + ByteString basefont, std::unique_ptr pWidths) { if (bold && italic) basefont += ",BoldItalic"; @@ -315,7 +316,7 @@ void ProcessNonbCJK(CPDF_Dictionary* pBaseDict, std::unique_ptr CalculateFontDesc( CPDF_Document* pDoc, - CFX_ByteString basefont, + ByteString basefont, int flags, int italicangle, int ascend, @@ -341,20 +342,18 @@ CPDF_Document::CPDF_Document(std::unique_ptr pParser) : CPDF_IndirectObjectHolder(), m_pParser(std::move(pParser)), m_pRootDict(nullptr), - m_pInfoDict(nullptr), m_iNextPageToTraverse(0), m_bReachedMaxPageLevel(false), m_bLinearized(false), m_iFirstPageNo(0), m_dwFirstPageObjNum(0), - m_pDocPage(new CPDF_DocPageData(this)), - m_pDocRender(new CPDF_DocRenderData(this)) { + m_pDocPage(pdfium::MakeUnique(this)), + m_pDocRender(pdfium::MakeUnique(this)) { if (pParser) SetLastObjNum(m_pParser->GetLastObjNum()); } CPDF_Document::~CPDF_Document() { - delete m_pDocPage; CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this); } @@ -374,6 +373,13 @@ void CPDF_Document::LoadDocInternal() { if (!m_pRootDict) return; + LoadDocumentInfo(); +} + +void CPDF_Document::LoadDocumentInfo() { + if (!m_pParser) + return; + CPDF_Object* pInfoObj = GetOrParseIndirectObject(m_pParser->GetInfoObjNum()); if (pInfoObj) m_pInfoDict = pInfoObj->GetDict(); @@ -406,6 +412,7 @@ CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage, CPDF_Dictionary* pPages = m_pTreeTraversal[level].first; CPDF_Array* pKidList = pPages->GetArrayFor("Kids"); if (!pKidList) { + m_pTreeTraversal.pop_back(); if (*nPagesToGo != 1) return nullptr; m_PageList[iPage] = pPages->GetObjNum(); @@ -421,6 +428,7 @@ CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage, i++) { if (*nPagesToGo == 0) break; + pKidList->ConvertToIndirectObjectAt(i, this); CPDF_Dictionary* pKid = pKidList->GetDictAt(i); if (!pKid) { (*nPagesToGo)--; @@ -468,7 +476,7 @@ void CPDF_Document::ResetTraversal() { } CPDF_Dictionary* CPDF_Document::GetPagesDict() const { - CPDF_Dictionary* pRoot = GetRoot(); + const CPDF_Dictionary* pRoot = GetRoot(); return pRoot ? pRoot->GetDictFor("Pages") : nullptr; } @@ -477,10 +485,10 @@ bool CPDF_Document::IsPageLoaded(int iPage) const { } CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { - if (iPage < 0 || iPage >= pdfium::CollectionSize(m_PageList)) + if (!pdfium::IndexInBounds(m_PageList, iPage)) return nullptr; - if (m_bLinearized && (iPage == m_iFirstPageNo)) { + if (m_bLinearized && iPage == m_iFirstPageNo) { if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) { return pDict; @@ -494,18 +502,11 @@ CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { if (!pPages) return nullptr; - if (iPage - m_iNextPageToTraverse + 1 <= 0) { - // This can happen when the page does not have an object number. On repeated - // calls to this function for the same page index, this condition causes - // TraversePDFPages() to incorrectly return nullptr. - // Example "testing/corpus/fx/other/jetman_std.pdf" - // We should restart traversing in this case. - // TODO(art-snake): optimize this. + if (m_pTreeTraversal.empty()) { ResetTraversal(); + m_pTreeTraversal.push_back(std::make_pair(pPages, 0)); } int nPagesToGo = iPage - m_iNextPageToTraverse + 1; - if (m_pTreeTraversal.empty()) - m_pTreeTraversal.push_back(std::make_pair(pPages, 0)); CPDF_Dictionary* pPage = TraversePDFPages(iPage, &nPagesToGo, 0); m_iNextPageToTraverse = iPage + 1; return pPage; @@ -519,7 +520,7 @@ int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode, uint32_t* skip_count, uint32_t objnum, int* index, - int level) { + int level) const { if (!pNode->KeyExist("Kids")) { if (objnum == pNode->GetObjNum()) return *index; @@ -586,7 +587,7 @@ int CPDF_Document::GetPageIndex(uint32_t objnum) { int found_index = FindPageIndex(pPages, &skip_count, objnum, &start_index); // Corrupt page tree may yield out-of-range results. - if (found_index < 0 || found_index >= pdfium::CollectionSize(m_PageList)) + if (!pdfium::IndexInBounds(m_PageList, found_index)) return -1; m_PageList[found_index] = objnum; @@ -627,7 +628,7 @@ CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict) { return m_pDocPage->GetFont(pFontDict); } -CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream) { +RetainPtr CPDF_Document::LoadFontFile(CPDF_Stream* pStream) { return m_pDocPage->GetFontFileStreamAcc(pStream); } @@ -642,17 +643,19 @@ CPDF_Pattern* CPDF_Document::LoadPattern(CPDF_Object* pPatternObj, return m_pDocPage->GetPattern(pPatternObj, bShading, matrix); } -CPDF_IccProfile* CPDF_Document::LoadIccProfile(CPDF_Stream* pStream) { +RetainPtr CPDF_Document::LoadIccProfile(CPDF_Stream* pStream) { return m_pDocPage->GetIccProfile(pStream); } -CPDF_Image* CPDF_Document::LoadImageFromPageData(uint32_t dwStreamObjNum) { +RetainPtr CPDF_Document::LoadImageFromPageData( + uint32_t dwStreamObjNum) { ASSERT(dwStreamObjNum); return m_pDocPage->GetImage(dwStreamObjNum); } void CPDF_Document::CreateNewDoc() { - ASSERT(!m_pRootDict && !m_pInfoDict); + ASSERT(!m_pRootDict); + ASSERT(!m_pInfoDict); m_pRootDict = NewIndirect(); m_pRootDict->SetNewFor("Type", "Catalog"); @@ -723,7 +726,7 @@ bool CPDF_Document::InsertDeletePDFPage(CPDF_Dictionary* pPages, } bool CPDF_Document::InsertNewPage(int iPage, CPDF_Dictionary* pPageDict) { - CPDF_Dictionary* pRoot = GetRoot(); + const CPDF_Dictionary* pRoot = GetRoot(); CPDF_Dictionary* pPages = pRoot ? pRoot->GetDictFor("Pages") : nullptr; if (!pPages) return false; @@ -765,9 +768,9 @@ void CPDF_Document::DeletePage(int iPage) { m_PageList.erase(m_PageList.begin() + iPage); } -CPDF_Font* CPDF_Document::AddStandardFont(const FX_CHAR* font, +CPDF_Font* CPDF_Document::AddStandardFont(const char* font, CPDF_FontEncoding* pEncoding) { - CFX_ByteString name(font); + ByteString name(font); if (PDF_GetStandardFontName(&name) < 0) return nullptr; return GetPageData()->GetStandardFont(name, pEncoding); @@ -791,7 +794,7 @@ size_t CPDF_Document::CalculateEncodingDict(int charset, const uint16_t* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; for (int j = 0; j < 128; j++) { - CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); + ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); pArray->AddNew(name.IsEmpty() ? ".notdef" : name); } pBaseDict->SetNewFor("Encoding", this, @@ -803,22 +806,22 @@ CPDF_Dictionary* CPDF_Document::ProcessbCJK( CPDF_Dictionary* pBaseDict, int charset, bool bVert, - CFX_ByteString basefont, - std::function Insert) { + ByteString basefont, + std::function Insert) { CPDF_Dictionary* pFontDict = NewIndirect(); - CFX_ByteString cmap; - CFX_ByteString ordering; + ByteString cmap; + ByteString ordering; int supplement = 0; CPDF_Array* pWidthArray = pFontDict->SetNewFor("W"); switch (charset) { - case FXFONT_CHINESEBIG5_CHARSET: + case FX_CHARSET_ChineseTraditional: cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H"; ordering = "CNS1"; supplement = 4; pWidthArray->AddNew(1); Insert(0x20, 0x7e, pWidthArray); break; - case FXFONT_GB2312_CHARSET: + case FX_CHARSET_ChineseSimplified: cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H"; ordering = "GB1"; supplement = 2; @@ -827,14 +830,14 @@ CPDF_Dictionary* CPDF_Document::ProcessbCJK( pWidthArray->AddNew(814); Insert(0x21, 0x7e, pWidthArray); break; - case FXFONT_HANGUL_CHARSET: + case FX_CHARSET_Hangul: cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H"; ordering = "Korea1"; supplement = 2; pWidthArray->AddNew(1); Insert(0x20, 0x7e, pWidthArray); break; - case FXFONT_SHIFTJIS_CHARSET: + case FX_CHARSET_ShiftJIS: cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H"; ordering = "Japan1"; supplement = 5; @@ -870,20 +873,18 @@ CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, bool bVert) { if (!pFont) return nullptr; - bool bCJK = charset == FXFONT_CHINESEBIG5_CHARSET || - charset == FXFONT_GB2312_CHARSET || - charset == FXFONT_HANGUL_CHARSET || - charset == FXFONT_SHIFTJIS_CHARSET; - CFX_ByteString basefont = pFont->GetFamilyName(); + bool bCJK = charset == FX_CHARSET_ChineseTraditional || + charset == FX_CHARSET_ChineseSimplified || + charset == FX_CHARSET_Hangul || charset == FX_CHARSET_ShiftJIS; + ByteString basefont = pFont->GetFamilyName(); basefont.Replace(" ", ""); int flags = CalculateFlags(pFont->IsBold(), pFont->IsItalic(), pFont->IsFixedWidth(), - false, false, charset == FXFONT_SYMBOL_CHARSET); + false, false, charset == FX_CHARSET_Symbol); CPDF_Dictionary* pBaseDict = NewIndirect(); pBaseDict->SetNewFor("Type", "Font"); - std::unique_ptr pEncoding( - new CFX_UnicodeEncoding(pFont)); + auto pEncoding = pdfium::MakeUnique(pFont); CPDF_Dictionary* pFontDict = pBaseDict; if (!bCJK) { auto pWidths = pdfium::MakeUnique(); @@ -892,8 +893,8 @@ CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, bool bVert) { int char_width = pFont->GetGlyphWidth(glyph_index); pWidths->AddNew(char_width); } - if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET || - charset == FXFONT_SYMBOL_CHARSET) { + if (charset == FX_CHARSET_ANSI || charset == FX_CHARSET_Default || + charset == FX_CHARSET_Symbol) { pBaseDict->SetNewFor("Encoding", "WinAnsiEncoding"); for (int charcode = 128; charcode <= 255; charcode++) { int glyph_index = pEncoding->GlyphFromCharCode(charcode); @@ -914,12 +915,11 @@ CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, bool bVert) { ProcessNonbCJK(pBaseDict, pFont->IsBold(), pFont->IsItalic(), basefont, std::move(pWidths)); } else { - pFontDict = ProcessbCJK(pBaseDict, charset, bVert, basefont, - [pFont, &pEncoding](FX_WCHAR start, FX_WCHAR end, - CPDF_Array* widthArr) { - InsertWidthArray1(pFont, pEncoding.get(), start, - end, widthArr); - }); + pFontDict = ProcessbCJK( + pBaseDict, charset, bVert, basefont, + [pFont, &pEncoding](wchar_t start, wchar_t end, CPDF_Array* widthArr) { + InsertWidthArray1(pFont, pEncoding.get(), start, end, widthArr); + }); } int italicangle = pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0; @@ -934,7 +934,7 @@ CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, bool bVert) { if (pFont->GetSubstFont()) { nStemV = pFont->GetSubstFont()->m_Weight / 5; } else { - static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'}; + static const char stem_chars[] = {'i', 'I', '!', '1'}; const size_t count = FX_ArraySize(stem_chars); uint32_t glyph = pEncoding->GlyphFromCharCode(stem_chars[0]); nStemV = pFont->GetGlyphWidth(glyph); @@ -953,17 +953,18 @@ CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, bool bVert) { return LoadFont(pBaseDict); } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTW* pLogFont, bool bVert, bool bTranslateName) { LOGFONTA lfa; - FXSYS_memcpy(&lfa, pLogFont, (char*)lfa.lfFaceName - (char*)&lfa); - CFX_ByteString face = CFX_ByteString::FromUnicode(pLogFont->lfFaceName); + memcpy(&lfa, pLogFont, (char*)lfa.lfFaceName - (char*)&lfa); + ByteString face = ByteString::FromUnicode(pLogFont->lfFaceName); if (face.GetLength() >= LF_FACESIZE) return nullptr; - FXSYS_strcpy(lfa.lfFaceName, face.c_str()); + strncpy(lfa.lfFaceName, face.c_str(), + (face.GetLength() + 1) * sizeof(ByteString::CharType)); return AddWindowsFont(&lfa, bVert, bTranslateName); } @@ -990,13 +991,13 @@ CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont, (pLogFont->lfPitchAndFamily & 3) == FIXED_PITCH, (pLogFont->lfPitchAndFamily & 0xf8) == FF_ROMAN, (pLogFont->lfPitchAndFamily & 0xf8) == FF_SCRIPT, - pLogFont->lfCharSet == FXFONT_SYMBOL_CHARSET); + pLogFont->lfCharSet == FX_CHARSET_Symbol); - bool bCJK = pLogFont->lfCharSet == FXFONT_CHINESEBIG5_CHARSET || - pLogFont->lfCharSet == FXFONT_GB2312_CHARSET || - pLogFont->lfCharSet == FXFONT_HANGUL_CHARSET || - pLogFont->lfCharSet == FXFONT_SHIFTJIS_CHARSET; - CFX_ByteString basefont; + bool bCJK = pLogFont->lfCharSet == FX_CHARSET_ChineseTraditional || + pLogFont->lfCharSet == FX_CHARSET_ChineseSimplified || + pLogFont->lfCharSet == FX_CHARSET_Hangul || + pLogFont->lfCharSet == FX_CHARSET_ShiftJIS; + ByteString basefont; if (bTranslateName && bCJK) basefont = FPDF_GetPSNameFromTT(hDC); @@ -1015,9 +1016,9 @@ CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont, pBaseDict->SetNewFor("Type", "Font"); CPDF_Dictionary* pFontDict = pBaseDict; if (!bCJK) { - if (pLogFont->lfCharSet == FXFONT_ANSI_CHARSET || - pLogFont->lfCharSet == FXFONT_DEFAULT_CHARSET || - pLogFont->lfCharSet == FXFONT_SYMBOL_CHARSET) { + if (pLogFont->lfCharSet == FX_CHARSET_ANSI || + pLogFont->lfCharSet == FX_CHARSET_Default || + pLogFont->lfCharSet == FX_CHARSET_Symbol) { pBaseDict->SetNewFor("Encoding", "WinAnsiEncoding"); } else { CalculateEncodingDict(pLogFont->lfCharSet, pBaseDict); @@ -1032,7 +1033,7 @@ CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont, } else { pFontDict = ProcessbCJK(pBaseDict, pLogFont->lfCharSet, bVert, basefont, - [&hDC](FX_WCHAR start, FX_WCHAR end, CPDF_Array* widthArr) { + [&hDC](wchar_t start, wchar_t end, CPDF_Array* widthArr) { InsertWidthArray(hDC, start, end, widthArr); }); } @@ -1051,4 +1052,4 @@ CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont, DeleteDC(hDC); return LoadFont(pBaseDict); } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h index 3848ad622090558ffc1577a2edeb758fcb7afa3f..d73dbc1df9c2438bfd42a3a6520aa27a762c7900 100644 --- a/core/fpdfapi/parser/cpdf_document.h +++ b/core/fpdfapi/parser/cpdf_document.h @@ -13,10 +13,10 @@ #include #include +#include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" #include "core/fpdfapi/parser/cpdf_object.h" #include "core/fpdfdoc/cpdf_linklist.h" -#include "core/fxcrt/fx_basic.h" class CFX_Font; class CFX_Matrix; @@ -26,21 +26,17 @@ class CPDF_DocRenderData; class CPDF_Font; class CPDF_FontEncoding; class CPDF_IccProfile; -class CPDF_Image; class CPDF_LinearizedHeader; class CPDF_Parser; class CPDF_Pattern; class CPDF_StreamAcc; class JBig2_DocumentContext; -#define FPDFPERM_PRINT 0x0004 #define FPDFPERM_MODIFY 0x0008 -#define FPDFPERM_EXTRACT 0x0010 #define FPDFPERM_ANNOT_FORM 0x0020 #define FPDFPERM_FILL_FORM 0x0100 #define FPDFPERM_EXTRACT_ACCESS 0x0200 -#define FPDFPERM_ASSEMBLE 0x0400 -#define FPDFPERM_PRINT_HIGH 0x0800 + #define FPDF_PAGE_MAX_NUM 0xFFFFF class CPDF_Document : public CPDF_IndirectObjectHolder { @@ -49,8 +45,10 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { ~CPDF_Document() override; CPDF_Parser* GetParser() const { return m_pParser.get(); } - CPDF_Dictionary* GetRoot() const { return m_pRootDict; } - CPDF_Dictionary* GetInfo() const { return m_pInfoDict; } + const CPDF_Dictionary* GetRoot() const { return m_pRootDict; } + CPDF_Dictionary* GetRoot() { return m_pRootDict; } + const CPDF_Dictionary* GetInfo() const { return m_pInfoDict.Get(); } + CPDF_Dictionary* GetInfo() { return m_pInfoDict.Get(); } void DeletePage(int iPage); int GetPageCount() const; @@ -58,7 +56,9 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { CPDF_Dictionary* GetPage(int iPage); int GetPageIndex(uint32_t objnum); uint32_t GetUserPermissions() const; - CPDF_DocPageData* GetPageData() const { return m_pDocPage; } + + // Returns a valid pointer, unless it is called during destruction. + CPDF_DocPageData* GetPageData() const { return m_pDocPage.get(); } void SetPageObjNum(int iPage, uint32_t objNum); @@ -78,20 +78,21 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { bool bShading, const CFX_Matrix& matrix); - CPDF_Image* LoadImageFromPageData(uint32_t dwStreamObjNum); - CPDF_StreamAcc* LoadFontFile(CPDF_Stream* pStream); - CPDF_IccProfile* LoadIccProfile(CPDF_Stream* pStream); + RetainPtr LoadImageFromPageData(uint32_t dwStreamObjNum); + RetainPtr LoadFontFile(CPDF_Stream* pStream); + RetainPtr LoadIccProfile(CPDF_Stream* pStream); void LoadDoc(); void LoadLinearizedDoc(const CPDF_LinearizedHeader* pLinearizationParams); void LoadPages(); + void LoadDocumentInfo(); void CreateNewDoc(); CPDF_Dictionary* CreateNewPage(int iPage); - CPDF_Font* AddStandardFont(const FX_CHAR* font, CPDF_FontEncoding* pEncoding); + CPDF_Font* AddStandardFont(const char* font, CPDF_FontEncoding* pEncoding); CPDF_Font* AddFont(CFX_Font* pFont, int charset, bool bVert); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ CPDF_Font* AddWindowsFont(LOGFONTA* pLogFont, bool bVert, bool bTranslateName = false); @@ -109,7 +110,7 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { uint32_t* skip_count, uint32_t objnum, int* index, - int level = 0); + int level = 0) const; std::unique_ptr ParseIndirectObject(uint32_t objnum) override; void LoadDocInternal(); size_t CalculateEncodingDict(int charset, CPDF_Dictionary* pBaseDict); @@ -118,8 +119,8 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { CPDF_Dictionary* pBaseDict, int charset, bool bVert, - CFX_ByteString basefont, - std::function Insert); + ByteString basefont, + std::function Insert); bool InsertDeletePDFPage(CPDF_Dictionary* pPages, int nPagesToGo, CPDF_Dictionary* pPageDict, @@ -129,21 +130,25 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { void ResetTraversal(); std::unique_ptr m_pParser; - CPDF_Dictionary* m_pRootDict; - CPDF_Dictionary* m_pInfoDict; + + // TODO(tsepez): figure out why tests break if this is an UnownedPtr. + CPDF_Dictionary* m_pRootDict; // Not owned. + + UnownedPtr m_pInfoDict; + // Vector of pairs to know current position in the page tree. The index in the // vector corresponds to the level being described. The pair contains a // pointer to the dictionary being processed at the level, and an index of the // of the child being processed within the dictionary's /Kids array. std::vector> m_pTreeTraversal; + // Index of the next page that will be traversed from the page tree. int m_iNextPageToTraverse; bool m_bReachedMaxPageLevel; bool m_bLinearized; int m_iFirstPageNo; uint32_t m_dwFirstPageObjNum; - // TODO(thestig): Figure out why this cannot be a std::unique_ptr. - CPDF_DocPageData* m_pDocPage; + std::unique_ptr m_pDocPage; std::unique_ptr m_pDocRender; std::unique_ptr m_pCodecContext; std::unique_ptr m_pLinksContext; diff --git a/core/fpdfapi/parser/cpdf_document_unittest.cpp b/core/fpdfapi/parser/cpdf_document_unittest.cpp index 4815ffba520d369cb87d01223ba087340f6796cf..d1b8dce74a0b6cbd58beba5d4e0377ccd339d5a5 100644 --- a/core/fpdfapi/parser/cpdf_document_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_document_unittest.cpp @@ -12,6 +12,7 @@ #include "core/fpdfapi/parser/cpdf_boolean.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_linearized_header.h" +#include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/cpdf_reference.h" @@ -22,6 +23,8 @@ namespace { +const int kNumTestPages = 7; + CPDF_Dictionary* CreatePageTreeNode(std::unique_ptr kids, CPDF_Document* pDoc, int count) { @@ -82,13 +85,18 @@ class CPDF_TestDocumentForPages : public CPDF_Document { allPages->AddNew(this, branch3->GetObjNum()); allPages->AddNew(this, branch4->GetObjNum()); CPDF_Dictionary* pagesDict = - CreatePageTreeNode(std::move(allPages), this, 7); + CreatePageTreeNode(std::move(allPages), this, kNumTestPages); m_pOwnedRootDict = pdfium::MakeUnique(); m_pOwnedRootDict->SetNewFor("Pages", this, pagesDict->GetObjNum()); m_pRootDict = m_pOwnedRootDict.get(); - m_PageList.resize(7); + m_PageList.resize(kNumTestPages); + } + + void SetTreeSize(int size) { + m_pOwnedRootDict->SetNewFor("Count", size); + m_PageList.resize(size); } private: @@ -105,7 +113,7 @@ class CPDF_TestDocumentWithPageWithoutPageNum : public CPDF_Document { allPages->AddNew( this, AddIndirectObject(CreateNumberedPage(1))->GetObjNum()); // Page without pageNum. - allPages->Add(CreateNumberedPage(2)); + inlined_page_ = allPages->Add(CreateNumberedPage(2)); CPDF_Dictionary* pagesDict = CreatePageTreeNode(std::move(allPages), this, 3); m_pOwnedRootDict = pdfium::MakeUnique(); @@ -115,46 +123,62 @@ class CPDF_TestDocumentWithPageWithoutPageNum : public CPDF_Document { m_PageList.resize(3); } + const CPDF_Object* inlined_page() const { return inlined_page_; } + private: std::unique_ptr m_pOwnedRootDict; + const CPDF_Object* inlined_page_; }; class TestLinearized : public CPDF_LinearizedHeader { public: explicit TestLinearized(CPDF_Dictionary* dict) - : CPDF_LinearizedHeader(dict) {} + : CPDF_LinearizedHeader(dict, 0) {} +}; + +class CPDF_TestDocPagesWithoutKids : public CPDF_Document { + public: + CPDF_TestDocPagesWithoutKids() : CPDF_Document(nullptr) { + CPDF_Dictionary* pagesDict = NewIndirect(); + pagesDict->SetNewFor("Type", "Pages"); + pagesDict->SetNewFor("Count", 3); + m_PageList.resize(10); + m_pOwnedRootDict = pdfium::MakeUnique(); + m_pOwnedRootDict->SetNewFor("Pages", this, + pagesDict->GetObjNum()); + m_pRootDict = m_pOwnedRootDict.get(); + } + + private: + std::unique_ptr m_pOwnedRootDict; }; } // namespace class cpdf_document_test : public testing::Test { public: - void SetUp() override { - CPDF_ModuleMgr* module_mgr = CPDF_ModuleMgr::Get(); - module_mgr->InitPageModule(); - } + void SetUp() override { CPDF_ModuleMgr::Get()->Init(); } void TearDown() override { CPDF_ModuleMgr::Destroy(); } }; TEST_F(cpdf_document_test, GetPages) { std::unique_ptr document = pdfium::MakeUnique(); - for (int i = 0; i < 7; i++) { + for (int i = 0; i < kNumTestPages; i++) { CPDF_Dictionary* page = document->GetPage(i); ASSERT_TRUE(page); ASSERT_TRUE(page->KeyExist("PageNumbering")); EXPECT_EQ(i, page->GetIntegerFor("PageNumbering")); } - CPDF_Dictionary* page = document->GetPage(7); + CPDF_Dictionary* page = document->GetPage(kNumTestPages); EXPECT_FALSE(page); } TEST_F(cpdf_document_test, GetPageWithoutObjNumTwice) { - std::unique_ptr document = - pdfium::MakeUnique(); + auto document = pdfium::MakeUnique(); const CPDF_Dictionary* page = document->GetPage(2); ASSERT_TRUE(page); - // This is page without obj num. - ASSERT_EQ(0ul, page->GetObjNum()); + ASSERT_EQ(document->inlined_page(), page); + const CPDF_Dictionary* second_call_page = document->GetPage(2); EXPECT_TRUE(second_call_page); EXPECT_EQ(page, second_call_page); @@ -169,7 +193,7 @@ TEST_F(cpdf_document_test, GetPagesReverseOrder) { ASSERT_TRUE(page->KeyExist("PageNumbering")); EXPECT_EQ(i, page->GetIntegerFor("PageNumbering")); } - CPDF_Dictionary* page = document->GetPage(7); + CPDF_Dictionary* page = document->GetPage(kNumTestPages); EXPECT_FALSE(page); } @@ -187,7 +211,7 @@ TEST_F(cpdf_document_test, GetPagesInDisorder) { ASSERT_TRUE(page->KeyExist("PageNumbering")); EXPECT_EQ(3, page->GetIntegerFor("PageNumbering")); - page = document->GetPage(7); + page = document->GetPage(kNumTestPages); EXPECT_FALSE(page); page = document->GetPage(6); @@ -219,3 +243,25 @@ TEST_F(cpdf_document_test, UseCachedPageObjNumIfHaveNotPagesDict) { EXPECT_TRUE(document.IsPageLoaded(test_page_num)); EXPECT_EQ(page_stub, document.GetPage(test_page_num)); } + +TEST_F(cpdf_document_test, CountGreaterThanPageTree) { + std::unique_ptr document = + pdfium::MakeUnique(); + document->SetTreeSize(kNumTestPages + 3); + for (int i = 0; i < kNumTestPages; i++) + EXPECT_TRUE(document->GetPage(i)); + for (int i = kNumTestPages; i < kNumTestPages + 4; i++) + EXPECT_FALSE(document->GetPage(i)); + EXPECT_TRUE(document->GetPage(kNumTestPages - 1)); +} + +TEST_F(cpdf_document_test, PagesWithoutKids) { + // Set up a document with Pages dict without kids, and Count = 3 + auto pDoc = pdfium::MakeUnique(); + EXPECT_TRUE(pDoc->GetPage(0)); + // Test GetPage does not fetch pages out of range + for (int i = 1; i < 5; i++) + EXPECT_FALSE(pDoc->GetPage(i)); + + EXPECT_TRUE(pDoc->GetPage(0)); +} diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp index e000188e7d687c77759169b599c84dc46d3b9dec..c9123d4b9733f4827e6704a5c7c9f395dc9b8ac7 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables.cpp +++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp @@ -13,8 +13,10 @@ #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_linearized_header.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcrt/cfx_bitstream.h" #include "core/fxcrt/fx_safe_types.h" #include "third_party/base/numerics/safe_conversions.h" @@ -34,9 +36,9 @@ bool IsValidPageOffsetHintTableBitCount(uint32_t bits) { } // namespace -CPDF_HintTables::CPDF_HintTables(CPDF_DataAvail* pDataAvail, +CPDF_HintTables::CPDF_HintTables(CPDF_ReadValidator* pValidator, CPDF_LinearizedHeader* pLinearized) - : m_pDataAvail(pDataAvail), + : m_pValidator(pValidator), m_pLinearized(pLinearized), m_nFirstPageSharedObjs(0), m_szFirstPageObjOffset(0) { @@ -47,7 +49,7 @@ CPDF_HintTables::~CPDF_HintTables() {} uint32_t CPDF_HintTables::GetItemLength( uint32_t index, - const std::vector& szArray) { + const std::vector& szArray) const { if (szArray.size() < 2 || index > szArray.size() - 2 || szArray[index] > szArray[index + 1]) { return 0; @@ -290,6 +292,11 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, // greatest and least length of a shared object group, in bytes. uint32_t dwDeltaGroupLen = hStream->GetBits(16); + // Trying to decode more than 32 bits isn't going to work when we write into + // a uint32_t. + if (dwDeltaGroupLen > 31) + return false; + if (dwFirstSharedObjNum >= CPDF_Parser::kMaxObjectNumber || m_nFirstPageSharedObjs >= CPDF_Parser::kMaxObjectNumber || dwSharedObjTotal >= CPDF_Parser::kMaxObjectNumber) { @@ -366,7 +373,10 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, bool CPDF_HintTables::GetPagePos(uint32_t index, FX_FILESIZE* szPageStartPos, FX_FILESIZE* szPageLength, - uint32_t* dwObjNum) { + uint32_t* dwObjNum) const { + if (index >= m_pLinearized->GetPageCount()) + return false; + *szPageStartPos = m_szPageOffsetArray[index]; *szPageLength = GetItemLength(index, m_szPageOffsetArray); @@ -394,12 +404,7 @@ bool CPDF_HintTables::GetPagePos(uint32_t index, return true; } -CPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage( - uint32_t index, - CPDF_DataAvail::DownloadHints* pHints) { - if (!pHints) - return CPDF_DataAvail::DataError; - +CPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage(uint32_t index) { int nFirstPageNum = GetFirstPageNumber(); if (!pdfium::base::IsValueInRangeForNumericType(nFirstPageNum)) return CPDF_DataAvail::DataError; @@ -412,7 +417,8 @@ CPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage( if (!dwLength) return CPDF_DataAvail::DataError; - if (!m_pDataAvail->IsDataAvail(m_szPageOffsetArray[index], dwLength, pHints)) + if (!m_pValidator->CheckDataRangeAndRequestIfUnavailable( + m_szPageOffsetArray[index], dwLength)) return CPDF_DataAvail::DataNotAvailable; // Download data of shared objects in the page. @@ -443,8 +449,8 @@ CPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage( if (!dwLength) return CPDF_DataAvail::DataError; - if (!m_pDataAvail->IsDataAvail(m_szSharedObjOffsetArray[dwIndex], dwLength, - pHints)) { + if (!m_pValidator->CheckDataRangeAndRequestIfUnavailable( + m_szSharedObjOffsetArray[dwIndex], dwLength)) { return CPDF_DataAvail::DataNotAvailable; } } @@ -464,10 +470,10 @@ bool CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) { if (shared_hint_table_offset <= 0) return false; - CPDF_StreamAcc acc; - acc.LoadAllData(pHintStream); + auto pAcc = pdfium::MakeRetain(pHintStream); + pAcc->LoadAllDataFiltered(); - uint32_t size = acc.GetSize(); + uint32_t size = pAcc->GetSize(); // The header section of page offset hint table is 36 bytes. // The header section of shared object hint table is 24 bytes. // Hint table has at least 60 bytes. @@ -481,8 +487,7 @@ bool CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) { return false; } - CFX_BitStream bs; - bs.Init(acc.GetData(), size); + CFX_BitStream bs(pAcc->GetData(), size); return ReadPageHintTable(&bs) && ReadSharedObjHintTable(&bs, shared_hint_table_offset); } diff --git a/core/fpdfapi/parser/cpdf_hint_tables.h b/core/fpdfapi/parser/cpdf_hint_tables.h index e0bc6e075112d463d2690bb2f9a4a3004bf742f0..d5feb4638cc8aa78618347428db0fb43dd7a9f9e 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables.h +++ b/core/fpdfapi/parser/cpdf_hint_tables.h @@ -10,27 +10,26 @@ #include #include "core/fpdfapi/parser/cpdf_data_avail.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/unowned_ptr.h" class CFX_BitStream; class CPDF_LinearizedHeader; class CPDF_Stream; +class CPDF_ReadValidator; class CPDF_HintTables { public: - CPDF_HintTables(CPDF_DataAvail* pDataAvail, + CPDF_HintTables(CPDF_ReadValidator* pValidator, CPDF_LinearizedHeader* pLinearized); virtual ~CPDF_HintTables(); bool GetPagePos(uint32_t index, FX_FILESIZE* szPageStartPos, FX_FILESIZE* szPageLength, - uint32_t* dwObjNum); + uint32_t* dwObjNum) const; - CPDF_DataAvail::DocAvailStatus CheckPage( - uint32_t index, - CPDF_DataAvail::DownloadHints* pHints); + CPDF_DataAvail::DocAvailStatus CheckPage(uint32_t index); bool LoadHintStream(CPDF_Stream* pHintStream); @@ -48,13 +47,13 @@ class CPDF_HintTables { virtual int ReadPrimaryHintStreamLength() const; uint32_t GetItemLength(uint32_t index, - const std::vector& szArray); + const std::vector& szArray) const; - // Owner, outlives this object. - CPDF_DataAvail* const m_pDataAvail; + // Owned by |m_pDataAvail|. + UnownedPtr m_pValidator; // Owned by |m_pDataAvail|. - CPDF_LinearizedHeader* const m_pLinearized; + UnownedPtr const m_pLinearized; uint32_t m_nFirstPageSharedObjs; FX_FILESIZE m_szFirstPageObjOffset; diff --git a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e45722950e7fff9b983fa6f0ecfda452dde6807b --- /dev/null +++ b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp @@ -0,0 +1,69 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_hint_tables.h" + +#include +#include +#include + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/parser/cpdf_data_avail.h" +#include "core/fxcrt/fx_stream.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/utils/path_service.h" +#include "third_party/base/ptr_util.h" + +namespace { + +std::unique_ptr MakeDataAvailFromFile( + const std::string& file_name) { + std::string file_path; + if (!PathService::GetTestFilePath(file_name, &file_path)) + return nullptr; + return pdfium::MakeUnique( + nullptr, IFX_SeekableReadStream::CreateFromFilename(file_path.c_str()), + true); +} + +} // namespace + +class CPDF_HintTablesTest : public testing::Test { + public: + CPDF_HintTablesTest() { + // Needs for encoding Hint table stream. + CPDF_ModuleMgr::Get()->Init(); + } + + ~CPDF_HintTablesTest() override { CPDF_ModuleMgr::Destroy(); } +}; + +TEST_F(CPDF_HintTablesTest, Load) { + auto data_avail = MakeDataAvailFromFile("feature_linearized_loading.pdf"); + ASSERT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, + data_avail->IsDocAvail(nullptr)); + + ASSERT_TRUE(data_avail->GetHintTables()); + + const CPDF_HintTables* hint_tables = data_avail->GetHintTables(); + FX_FILESIZE page_start = 0; + FX_FILESIZE page_length = 0; + uint32_t page_obj_num = 0; + + ASSERT_TRUE( + hint_tables->GetPagePos(0, &page_start, &page_length, &page_obj_num)); + EXPECT_EQ(777, page_start); + EXPECT_EQ(4328, page_length); + EXPECT_EQ(39u, page_obj_num); + + ASSERT_TRUE( + hint_tables->GetPagePos(1, &page_start, &page_length, &page_obj_num)); + EXPECT_EQ(5105, page_start); + EXPECT_EQ(767, page_length); + EXPECT_EQ(1u, page_obj_num); + + ASSERT_FALSE( + hint_tables->GetPagePos(2, &page_start, &page_length, &page_obj_num)); +} diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp b/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp index 3037d0b9b5f877d3b9e485616ae2c4dc7eeb02e6..42e312ca64315c0c6499244c7faac7d546d9410e 100644 --- a/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp +++ b/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp @@ -13,9 +13,17 @@ #include "core/fpdfapi/parser/cpdf_parser.h" #include "third_party/base/logging.h" +namespace { + +CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) { + return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr; +} + +} // namespace + CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder() : m_LastObjNum(0), - m_pByteStringPool(pdfium::MakeUnique()) {} + m_pByteStringPool(pdfium::MakeUnique()) {} CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { m_pByteStringPool.DeleteObject(); // Make weak. @@ -24,26 +32,30 @@ CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject( uint32_t objnum) const { auto it = m_IndirectObjs.find(objnum); - return it != m_IndirectObjs.end() ? it->second.get() : nullptr; + return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.get()) + : nullptr; } CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObject( uint32_t objnum) { - if (objnum == 0) + if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum) return nullptr; - CPDF_Object* pObj = GetIndirectObject(objnum); - if (pObj) - return pObj->GetObjNum() != CPDF_Object::kInvalidObjNum ? pObj : nullptr; + // Add item anyway to prevent recursively parsing of same object. + auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr)); + if (!insert_result.second) + return FilterInvalidObjNum(insert_result.first->second.get()); std::unique_ptr pNewObj = ParseIndirectObject(objnum); - if (!pNewObj) + if (!pNewObj) { + m_IndirectObjs.erase(insert_result.first); return nullptr; + } - pNewObj->m_ObjNum = objnum; + pNewObj->SetObjNum(objnum); m_LastObjNum = std::max(m_LastObjNum, objnum); - m_IndirectObjs[objnum] = std::move(pNewObj); - return m_IndirectObjs[objnum].get(); + insert_result.first->second = std::move(pNewObj); + return insert_result.first->second.get(); } std::unique_ptr CPDF_IndirectObjectHolder::ParseIndirectObject( @@ -53,37 +65,42 @@ std::unique_ptr CPDF_IndirectObjectHolder::ParseIndirectObject( CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject( std::unique_ptr pObj) { - CHECK(!pObj->m_ObjNum); - CPDF_Object* pUnowned = pObj.get(); - pObj->m_ObjNum = ++m_LastObjNum; - if (m_IndirectObjs[m_LastObjNum]) - m_OrphanObjs.push_back(std::move(m_IndirectObjs[m_LastObjNum])); - - m_IndirectObjs[m_LastObjNum] = std::move(pObj); - return pUnowned; + CHECK(!pObj->GetObjNum()); + pObj->SetObjNum(++m_LastObjNum); + + auto& obj_holder = m_IndirectObjs[m_LastObjNum]; + if (obj_holder) + m_OrphanObjs.push_back(std::move(obj_holder)); + + obj_holder = std::move(pObj); + return obj_holder.get(); } bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration( uint32_t objnum, std::unique_ptr pObj) { ASSERT(objnum); - if (!pObj) + if (!pObj || objnum == CPDF_Object::kInvalidObjNum) return false; - CPDF_Object* pOldObj = GetIndirectObject(objnum); - if (pOldObj && pObj->GetGenNum() <= pOldObj->GetGenNum()) + auto& obj_holder = m_IndirectObjs[objnum]; + const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.get()); + if (old_object && pObj->GetGenNum() <= old_object->GetGenNum()) return false; - pObj->m_ObjNum = objnum; - m_IndirectObjs[objnum] = std::move(pObj); + pObj->SetObjNum(objnum); + if (obj_holder) + m_OrphanObjs.push_back(std::move(obj_holder)); + + obj_holder = std::move(pObj); m_LastObjNum = std::max(m_LastObjNum, objnum); return true; } void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) { - CPDF_Object* pObj = GetIndirectObject(objnum); - if (!pObj || pObj->GetObjNum() == CPDF_Object::kInvalidObjNum) + auto it = m_IndirectObjs.find(objnum); + if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.get())) return; - m_IndirectObjs.erase(objnum); + m_IndirectObjs.erase(it); } diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder.h b/core/fpdfapi/parser/cpdf_indirect_object_holder.h index b6d33a3cd54b21a24cdffb95e822066357663231..57374b9cc2317f6aa18f368359f1398cb298a346 100644 --- a/core/fpdfapi/parser/cpdf_indirect_object_holder.h +++ b/core/fpdfapi/parser/cpdf_indirect_object_holder.h @@ -14,9 +14,9 @@ #include #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" #include "third_party/base/ptr_util.h" class CPDF_IndirectObjectHolder { @@ -28,7 +28,7 @@ class CPDF_IndirectObjectHolder { virtual ~CPDF_IndirectObjectHolder(); CPDF_Object* GetIndirectObject(uint32_t objnum) const; - CPDF_Object* GetOrParseIndirectObject(uint32_t objnum); + virtual CPDF_Object* GetOrParseIndirectObject(uint32_t objnum); void DeleteIndirectObject(uint32_t objnum); // Creates and adds a new object owned by the indirect object holder, @@ -58,7 +58,7 @@ class CPDF_IndirectObjectHolder { uint32_t GetLastObjNum() const { return m_LastObjNum; } void SetLastObjNum(uint32_t objnum) { m_LastObjNum = objnum; } - CFX_WeakPtr GetByteStringPool() const { + WeakPtr GetByteStringPool() const { return m_pByteStringPool; } @@ -72,7 +72,7 @@ class CPDF_IndirectObjectHolder { uint32_t m_LastObjNum; std::map> m_IndirectObjs; std::vector> m_OrphanObjs; - CFX_WeakPtr m_pByteStringPool; + WeakPtr m_pByteStringPool; }; #endif // CORE_FPDFAPI_PARSER_CPDF_INDIRECT_OBJECT_HOLDER_H_ diff --git a/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp b/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..666264f50b8192bb5b7afb57721c8860bdea8ec1 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_indirect_object_holder_unittest.cpp @@ -0,0 +1,81 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_null.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +namespace { + +class MockIndirectObjectHolder : public CPDF_IndirectObjectHolder { + public: + MockIndirectObjectHolder() {} + ~MockIndirectObjectHolder() override {} + + MOCK_METHOD1(ParseIndirectObject, + std::unique_ptr(uint32_t objnum)); +}; + +} // namespace + +TEST(CPDF_IndirectObjectHolderTest, RecursiveParseOfSameObject) { + MockIndirectObjectHolder mock_holder; + // ParseIndirectObject should not be called again on recursively same object + // parse request. + EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)) + .WillOnce(::testing::WithArg<0>(::testing::Invoke( + [&mock_holder](uint32_t objnum) -> std::unique_ptr { + const CPDF_Object* same_parse = + mock_holder.GetOrParseIndirectObject(objnum); + CHECK(!same_parse); + return pdfium::MakeUnique(); + }))); + + EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(1000)); +} + +TEST(CPDF_IndirectObjectHolderTest, GetObjectMethods) { + static constexpr uint32_t kObjNum = 1000; + MockIndirectObjectHolder mock_holder; + + EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0); + EXPECT_FALSE(mock_holder.GetIndirectObject(kObjNum)); + ::testing::Mock::VerifyAndClearExpectations(&mock_holder); + + EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)) + .WillOnce(::testing::WithArg<0>(::testing::Invoke( + [](uint32_t objnum) -> std::unique_ptr { + return pdfium::MakeUnique(); + }))); + EXPECT_TRUE(mock_holder.GetOrParseIndirectObject(kObjNum)); + ::testing::Mock::VerifyAndClearExpectations(&mock_holder); + + EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0); + ASSERT_TRUE(mock_holder.GetIndirectObject(kObjNum)); + ::testing::Mock::VerifyAndClearExpectations(&mock_holder); + + EXPECT_EQ(kObjNum, mock_holder.GetIndirectObject(kObjNum)->GetObjNum()); +} + +TEST(CPDF_IndirectObjectHolderTest, ParseInvalidObjNum) { + MockIndirectObjectHolder mock_holder; + + EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0); + EXPECT_FALSE( + mock_holder.GetOrParseIndirectObject(CPDF_Object::kInvalidObjNum)); +} + +TEST(CPDF_IndirectObjectHolderTest, ReplaceObjectWithInvalidObjNum) { + MockIndirectObjectHolder mock_holder; + + EXPECT_CALL(mock_holder, ParseIndirectObject(::testing::_)).Times(0); + EXPECT_FALSE(mock_holder.ReplaceIndirectObjectIfHigherGeneration( + CPDF_Object::kInvalidObjNum, pdfium::MakeUnique())); +} diff --git a/core/fpdfapi/parser/cpdf_linearized_header.cpp b/core/fpdfapi/parser/cpdf_linearized_header.cpp index a56d64f2590f013b02c1e465830f794c4668ddd4..994d69f9b6fde8696f5f19daa35d2532327f4c90 100644 --- a/core/fpdfapi/parser/cpdf_linearized_header.cpp +++ b/core/fpdfapi/parser/cpdf_linearized_header.cpp @@ -7,15 +7,20 @@ #include "core/fpdfapi/parser/cpdf_linearized_header.h" #include +#include #include #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_syntax_parser.h" #include "third_party/base/ptr_util.h" namespace { +constexpr FX_FILESIZE kLinearizedHeaderOffset = 9; +constexpr size_t kMaxInt = static_cast(std::numeric_limits::max()); + template bool IsValidNumericDictionaryValue(const CPDF_Dictionary* pDict, const char* key, @@ -32,36 +37,70 @@ bool IsValidNumericDictionaryValue(const CPDF_Dictionary* pDict, return static_cast(raw_value) >= min_value; } +bool IsLinearizedHeaderValid(const CPDF_LinearizedHeader* header, + FX_FILESIZE file_size) { + ASSERT(header); + return header->GetFileSize() == file_size && + static_cast(header->GetFirstPageNo()) >= 0 && + header->GetFirstPageNo() < kMaxInt && + header->GetMainXRefTableFirstEntryOffset() < file_size && + header->GetPageCount() > 0 && + header->GetFirstPageEndOffset() < file_size && + header->GetLastXRefOffset() < file_size && + header->GetHintStart() < file_size; +} + } // namespace // static -std::unique_ptr CPDF_LinearizedHeader::CreateForObject( - std::unique_ptr pObj) { - auto pDict = ToDictionary(std::move(pObj)); +std::unique_ptr CPDF_LinearizedHeader::Parse( + CPDF_SyntaxParser* parser) { + parser->SetPos(kLinearizedHeaderOffset); + + const auto pDict = ToDictionary( + parser->GetIndirectObject(nullptr, CPDF_SyntaxParser::ParseType::kLoose)); + if (!pDict || !pDict->KeyExist("Linearized") || !IsValidNumericDictionaryValue(pDict.get(), "L", 1) || !IsValidNumericDictionaryValue(pDict.get(), "P", 0, false) || !IsValidNumericDictionaryValue(pDict.get(), "T", 1) || !IsValidNumericDictionaryValue(pDict.get(), "N", 0) || !IsValidNumericDictionaryValue(pDict.get(), "E", 1) || - !IsValidNumericDictionaryValue(pDict.get(), "O", 1)) + !IsValidNumericDictionaryValue(pDict.get(), "O", 1)) { return nullptr; - return pdfium::WrapUnique(new CPDF_LinearizedHeader(pDict.get())); + } + // Move parser to the start of the xref table for the documents first page. + // (skpping endobj keyword) + if (parser->GetNextWord(nullptr) != "endobj") + return nullptr; + + auto result = pdfium::WrapUnique( + new CPDF_LinearizedHeader(pDict.get(), parser->GetPos())); + + if (!IsLinearizedHeaderValid(result.get(), + parser->GetFileAccess()->GetSize())) { + return nullptr; + } + return result; } -CPDF_LinearizedHeader::CPDF_LinearizedHeader(const CPDF_Dictionary* pDict) { - m_szFileSize = pDict->GetIntegerFor("L"); - m_dwFirstPageNo = pDict->GetIntegerFor("P"); - m_szLastXRefOffset = pDict->GetIntegerFor("T"); - m_PageCount = pDict->GetIntegerFor("N"); - m_szFirstPageEndOffset = pDict->GetIntegerFor("E"); - m_FirstPageObjNum = pDict->GetIntegerFor("O"); +CPDF_LinearizedHeader::CPDF_LinearizedHeader(const CPDF_Dictionary* pDict, + FX_FILESIZE szLastXRefOffset) + : m_szFileSize(pDict->GetIntegerFor("L")), + m_dwFirstPageNo(pDict->GetIntegerFor("P")), + m_szMainXRefTableFirstEntryOffset(pDict->GetIntegerFor("T")), + m_PageCount(pDict->GetIntegerFor("N")), + m_szFirstPageEndOffset(pDict->GetIntegerFor("E")), + m_FirstPageObjNum(pDict->GetIntegerFor("O")), + m_szLastXRefOffset(szLastXRefOffset) { const CPDF_Array* pHintStreamRange = pDict->GetArrayFor("H"); const size_t nHintStreamSize = pHintStreamRange ? pHintStreamRange->GetCount() : 0; if (nHintStreamSize == 2 || nHintStreamSize == 4) { m_szHintStart = std::max(pHintStreamRange->GetIntegerAt(0), 0); - m_szHintLength = std::max(pHintStreamRange->GetIntegerAt(1), 0); + const FX_SAFE_UINT32 safe_hint_length = pHintStreamRange->GetIntegerAt(1); + if (safe_hint_length.IsValid()) + m_HintLength = safe_hint_length.ValueOrDie(); } } diff --git a/core/fpdfapi/parser/cpdf_linearized_header.h b/core/fpdfapi/parser/cpdf_linearized_header.h index 0d6d725f0050d2f1c73b660f86d695b947a43ed5..964ae26dfff95bed296f8489569efec50bd9fad2 100644 --- a/core/fpdfapi/parser/cpdf_linearized_header.h +++ b/core/fpdfapi/parser/cpdf_linearized_header.h @@ -14,42 +14,48 @@ class CPDF_Dictionary; class CPDF_Object; +class CPDF_SyntaxParser; class CPDF_LinearizedHeader { public: ~CPDF_LinearizedHeader(); - static std::unique_ptr CreateForObject( - std::unique_ptr pObj); + static std::unique_ptr Parse( + CPDF_SyntaxParser* parser); // Will only return values > 0. FX_FILESIZE GetFileSize() const { return m_szFileSize; } uint32_t GetFirstPageNo() const { return m_dwFirstPageNo; } // Will only return values > 0. - FX_FILESIZE GetLastXRefOffset() const { return m_szLastXRefOffset; } + FX_FILESIZE GetMainXRefTableFirstEntryOffset() const { + return m_szMainXRefTableFirstEntryOffset; + } uint32_t GetPageCount() const { return m_PageCount; } // Will only return values > 0. FX_FILESIZE GetFirstPageEndOffset() const { return m_szFirstPageEndOffset; } // Will only return values > 0. uint32_t GetFirstPageObjNum() const { return m_FirstPageObjNum; } + // Will only return values > 0. + FX_FILESIZE GetLastXRefOffset() const { return m_szLastXRefOffset; } bool HasHintTable() const; // Will only return values > 0. FX_FILESIZE GetHintStart() const { return m_szHintStart; } - // Will only return values > 0. - FX_FILESIZE GetHintLength() const { return m_szHintLength; } + uint32_t GetHintLength() const { return m_HintLength; } protected: - explicit CPDF_LinearizedHeader(const CPDF_Dictionary* pDict); + CPDF_LinearizedHeader(const CPDF_Dictionary* pDict, + FX_FILESIZE szLastXRefOffset); private: - FX_FILESIZE m_szFileSize = 0; - uint32_t m_dwFirstPageNo = 0; - FX_FILESIZE m_szLastXRefOffset = 0; - uint32_t m_PageCount = 0; - FX_FILESIZE m_szFirstPageEndOffset = 0; - uint32_t m_FirstPageObjNum = 0; + const FX_FILESIZE m_szFileSize; + const uint32_t m_dwFirstPageNo; + const FX_FILESIZE m_szMainXRefTableFirstEntryOffset; + const uint32_t m_PageCount; + const FX_FILESIZE m_szFirstPageEndOffset; + const uint32_t m_FirstPageObjNum; + const FX_FILESIZE m_szLastXRefOffset; FX_FILESIZE m_szHintStart = 0; - FX_FILESIZE m_szHintLength = 0; + uint32_t m_HintLength = 0; }; #endif // CORE_FPDFAPI_PARSER_CPDF_LINEARIZED_HEADER_H_ diff --git a/core/fpdfapi/parser/cpdf_name.cpp b/core/fpdfapi/parser/cpdf_name.cpp index 5be64d39d5875c82a13b08eef0f18b3a2e25be7e..0607a3034284345c8b07a59a252e7275940fa11b 100644 --- a/core/fpdfapi/parser/cpdf_name.cpp +++ b/core/fpdfapi/parser/cpdf_name.cpp @@ -7,10 +7,10 @@ #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" -CPDF_Name::CPDF_Name(CFX_WeakPtr pPool, - const CFX_ByteString& str) +CPDF_Name::CPDF_Name(WeakPtr pPool, const ByteString& str) : m_Name(str) { if (pPool) m_Name = pPool->Intern(m_Name); @@ -26,11 +26,11 @@ std::unique_ptr CPDF_Name::Clone() const { return pdfium::MakeUnique(nullptr, m_Name); } -CFX_ByteString CPDF_Name::GetString() const { +ByteString CPDF_Name::GetString() const { return m_Name; } -void CPDF_Name::SetString(const CFX_ByteString& str) { +void CPDF_Name::SetString(const ByteString& str) { m_Name = str; } @@ -46,6 +46,11 @@ const CPDF_Name* CPDF_Name::AsName() const { return this; } -CFX_WideString CPDF_Name::GetUnicodeText() const { +WideString CPDF_Name::GetUnicodeText() const { return PDF_DecodeText(m_Name); } + +bool CPDF_Name::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString("/") && + archive->WriteString(PDF_NameEncode(GetString()).AsStringView()); +} diff --git a/core/fpdfapi/parser/cpdf_name.h b/core/fpdfapi/parser/cpdf_name.h index 61318d4afbe1fe2625f238e11ca7c2a5af21eecb..880c10aedb0594590d4e6dfc8ea9ffc49ff1a4c1 100644 --- a/core/fpdfapi/parser/cpdf_name.h +++ b/core/fpdfapi/parser/cpdf_name.h @@ -10,26 +10,27 @@ #include #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" class CPDF_Name : public CPDF_Object { public: - CPDF_Name(CFX_WeakPtr pPool, const CFX_ByteString& str); + CPDF_Name(WeakPtr pPool, const ByteString& str); ~CPDF_Name() override; // CPDF_Object: Type GetType() const override; std::unique_ptr Clone() const override; - CFX_ByteString GetString() const override; - CFX_WideString GetUnicodeText() const override; - void SetString(const CFX_ByteString& str) override; + ByteString GetString() const override; + WideString GetUnicodeText() const override; + void SetString(const ByteString& str) override; bool IsName() const override; CPDF_Name* AsName() override; const CPDF_Name* AsName() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; protected: - CFX_ByteString m_Name; + ByteString m_Name; }; inline CPDF_Name* ToName(CPDF_Object* obj) { diff --git a/core/fpdfapi/parser/cpdf_null.cpp b/core/fpdfapi/parser/cpdf_null.cpp index 41478d7b4c00cbf225893eed6694edf68589622f..1074efd8635eceec73717f025fd129760decfdb5 100644 --- a/core/fpdfapi/parser/cpdf_null.cpp +++ b/core/fpdfapi/parser/cpdf_null.cpp @@ -5,6 +5,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fpdfapi/parser/cpdf_null.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" CPDF_Null::CPDF_Null() {} @@ -16,3 +17,11 @@ CPDF_Object::Type CPDF_Null::GetType() const { std::unique_ptr CPDF_Null::Clone() const { return pdfium::MakeUnique(); } + +bool CPDF_Null::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" null"); +} + +bool CPDF_Null::IsNull() const { + return true; +} diff --git a/core/fpdfapi/parser/cpdf_null.h b/core/fpdfapi/parser/cpdf_null.h index 4f8420f29dbdc10da234c8c88e149d2c558779d8..2ec05ec82ca51642f3de12f62916e5f2c2885424 100644 --- a/core/fpdfapi/parser/cpdf_null.h +++ b/core/fpdfapi/parser/cpdf_null.h @@ -18,6 +18,8 @@ class CPDF_Null : public CPDF_Object { // CPDF_Object. Type GetType() const override; std::unique_ptr Clone() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; + bool IsNull() const override; }; #endif // CORE_FPDFAPI_PARSER_CPDF_NULL_H_ diff --git a/core/fpdfapi/parser/cpdf_number.cpp b/core/fpdfapi/parser/cpdf_number.cpp index 24feb2a2e0584256cec2658e317b24217c753f91..dac1f40b7f33611a93709a66bfe9ef1008637b44 100644 --- a/core/fpdfapi/parser/cpdf_number.cpp +++ b/core/fpdfapi/parser/cpdf_number.cpp @@ -5,15 +5,16 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" CPDF_Number::CPDF_Number() : m_bInteger(true), m_Integer(0) {} CPDF_Number::CPDF_Number(int value) : m_bInteger(true), m_Integer(value) {} -CPDF_Number::CPDF_Number(FX_FLOAT value) : m_bInteger(false), m_Float(value) {} +CPDF_Number::CPDF_Number(float value) : m_bInteger(false), m_Float(value) {} -CPDF_Number::CPDF_Number(const CFX_ByteStringC& str) +CPDF_Number::CPDF_Number(const ByteStringView& str) : m_bInteger(FX_atonum(str, &m_Integer)) {} CPDF_Number::~CPDF_Number() {} @@ -27,8 +28,8 @@ std::unique_ptr CPDF_Number::Clone() const { : pdfium::MakeUnique(m_Float); } -FX_FLOAT CPDF_Number::GetNumber() const { - return m_bInteger ? static_cast(m_Integer) : m_Float; +float CPDF_Number::GetNumber() const { + return m_bInteger ? static_cast(m_Integer) : m_Float; } int CPDF_Number::GetInteger() const { @@ -47,11 +48,16 @@ const CPDF_Number* CPDF_Number::AsNumber() const { return this; } -void CPDF_Number::SetString(const CFX_ByteString& str) { - m_bInteger = FX_atonum(str.AsStringC(), &m_Integer); +void CPDF_Number::SetString(const ByteString& str) { + m_bInteger = FX_atonum(str.AsStringView(), &m_Integer); } -CFX_ByteString CPDF_Number::GetString() const { - return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED) - : CFX_ByteString::FormatFloat(m_Float); +ByteString CPDF_Number::GetString() const { + return m_bInteger ? ByteString::FormatInteger(m_Integer) + : ByteString::FormatFloat(m_Float); +} + +bool CPDF_Number::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" ") && + archive->WriteString(GetString().AsStringView()); } diff --git a/core/fpdfapi/parser/cpdf_number.h b/core/fpdfapi/parser/cpdf_number.h index 85a78e5f1a7070c362d75d9a5e9f278c773073dc..661177363bca799a4e3ec3304ecaeff0e16a8a95 100644 --- a/core/fpdfapi/parser/cpdf_number.h +++ b/core/fpdfapi/parser/cpdf_number.h @@ -17,20 +17,21 @@ class CPDF_Number : public CPDF_Object { public: CPDF_Number(); explicit CPDF_Number(int value); - explicit CPDF_Number(FX_FLOAT value); - explicit CPDF_Number(const CFX_ByteStringC& str); + explicit CPDF_Number(float value); + explicit CPDF_Number(const ByteStringView& str); ~CPDF_Number() override; // CPDF_Object: Type GetType() const override; std::unique_ptr Clone() const override; - CFX_ByteString GetString() const override; - FX_FLOAT GetNumber() const override; + ByteString GetString() const override; + float GetNumber() const override; int GetInteger() const override; - void SetString(const CFX_ByteString& str) override; + void SetString(const ByteString& str) override; bool IsNumber() const override; CPDF_Number* AsNumber() override; const CPDF_Number* AsNumber() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; bool IsInteger() const { return m_bInteger; } @@ -38,7 +39,7 @@ class CPDF_Number : public CPDF_Object { bool m_bInteger; union { int m_Integer; - FX_FLOAT m_Float; + float m_Float; }; }; diff --git a/core/fpdfapi/parser/cpdf_object.cpp b/core/fpdfapi/parser/cpdf_object.cpp index acda334c9ef9b340a716eb01b0985758dd3d491e..67632a040c56aeb3022fc35325faef1f3bb2ae27 100644 --- a/core/fpdfapi/parser/cpdf_object.cpp +++ b/core/fpdfapi/parser/cpdf_object.cpp @@ -14,6 +14,7 @@ #include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcrt/fx_string.h" +#include "third_party/base/logging.h" #include "third_party/base/stl_util.h" CPDF_Object::~CPDF_Object() {} @@ -38,15 +39,15 @@ std::unique_ptr CPDF_Object::CloneNonCyclic( return Clone(); } -CFX_ByteString CPDF_Object::GetString() const { - return CFX_ByteString(); +ByteString CPDF_Object::GetString() const { + return ByteString(); } -CFX_WideString CPDF_Object::GetUnicodeText() const { - return CFX_WideString(); +WideString CPDF_Object::GetUnicodeText() const { + return WideString(); } -FX_FLOAT CPDF_Object::GetNumber() const { +float CPDF_Object::GetNumber() const { return 0; } @@ -58,8 +59,8 @@ CPDF_Dictionary* CPDF_Object::GetDict() const { return nullptr; } -void CPDF_Object::SetString(const CFX_ByteString& str) { - ASSERT(false); +void CPDF_Object::SetString(const ByteString& str) { + NOTREACHED(); } bool CPDF_Object::IsArray() const { @@ -94,6 +95,10 @@ bool CPDF_Object::IsString() const { return false; } +bool CPDF_Object::IsNull() const { + return false; +} + CPDF_Array* CPDF_Object::AsArray() { return nullptr; } diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h index f6bc5b444f4cbac46d9a5ca68aad781dd3630790..7a14492d70d8ccccabec5ba296b0c0896e00d789 100644 --- a/core/fpdfapi/parser/cpdf_object.h +++ b/core/fpdfapi/parser/cpdf_object.h @@ -23,6 +23,7 @@ class CPDF_Number; class CPDF_Reference; class CPDF_Stream; class CPDF_String; +class IFX_ArchiveStream; class CPDF_Object { public: @@ -43,7 +44,9 @@ class CPDF_Object { virtual Type GetType() const = 0; uint32_t GetObjNum() const { return m_ObjNum; } + void SetObjNum(uint32_t objnum) { m_ObjNum = objnum; } uint32_t GetGenNum() const { return m_GenNum; } + void SetGenNum(uint32_t gennum) { m_GenNum = gennum; } bool IsInline() const { return m_ObjNum == 0; } // Create a deep copy of the object. @@ -54,13 +57,13 @@ class CPDF_Object { virtual std::unique_ptr CloneDirectObject() const; virtual CPDF_Object* GetDirect() const; - virtual CFX_ByteString GetString() const; - virtual CFX_WideString GetUnicodeText() const; - virtual FX_FLOAT GetNumber() const; + virtual ByteString GetString() const; + virtual WideString GetUnicodeText() const; + virtual float GetNumber() const; virtual int GetInteger() const; virtual CPDF_Dictionary* GetDict() const; - virtual void SetString(const CFX_ByteString& str); + virtual void SetString(const ByteString& str); virtual bool IsArray() const; virtual bool IsBoolean() const; @@ -70,6 +73,7 @@ class CPDF_Object { virtual bool IsReference() const; virtual bool IsStream() const; virtual bool IsString() const; + virtual bool IsNull() const; virtual CPDF_Array* AsArray(); virtual const CPDF_Array* AsArray() const; @@ -88,17 +92,7 @@ class CPDF_Object { virtual CPDF_String* AsString(); virtual const CPDF_String* AsString() const; - protected: - friend class CPDF_Array; - friend class CPDF_Dictionary; - friend class CPDF_IndirectObjectHolder; - friend class CPDF_Parser; - friend class CPDF_Reference; - friend class CPDF_Stream; - - CPDF_Object() : m_ObjNum(0), m_GenNum(0) {} - - std::unique_ptr CloneObjectNonCyclic(bool bDirect) const; + virtual bool WriteTo(IFX_ArchiveStream* archive) const = 0; // Create a deep copy of the object with the option to either // copy a reference object or directly copy the object it refers to @@ -110,11 +104,17 @@ class CPDF_Object { bool bDirect, std::set* pVisited) const; + protected: + CPDF_Object() : m_ObjNum(0), m_GenNum(0) {} + + std::unique_ptr CloneObjectNonCyclic(bool bDirect) const; + uint32_t m_ObjNum; - uint32_t m_GenNum; private: CPDF_Object(const CPDF_Object& src) {} + + uint32_t m_GenNum; }; template diff --git a/core/fpdfapi/parser/cpdf_object_avail.cpp b/core/fpdfapi/parser/cpdf_object_avail.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35e7f458509cae73f2d476589f6495712096ac1c --- /dev/null +++ b/core/fpdfapi/parser/cpdf_object_avail.cpp @@ -0,0 +1,148 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_object_avail.h" + +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" +#include "core/fpdfapi/parser/cpdf_object_walker.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" +#include "core/fpdfapi/parser/cpdf_reference.h" + +CPDF_ObjectAvail::CPDF_ObjectAvail(CPDF_ReadValidator* validator, + CPDF_IndirectObjectHolder* holder, + const CPDF_Object* root) + : validator_(validator), holder_(holder), root_(root) { + ASSERT(validator_); + ASSERT(holder); + ASSERT(root_); + if (!root_->IsInline()) + parsed_objnums_.insert(root_->GetObjNum()); +} + +CPDF_ObjectAvail::CPDF_ObjectAvail(CPDF_ReadValidator* validator, + CPDF_IndirectObjectHolder* holder, + uint32_t obj_num) + : validator_(validator), + holder_(holder), + root_(pdfium::MakeUnique(holder, obj_num)) { + ASSERT(validator_); + ASSERT(holder); +} + +CPDF_ObjectAvail::~CPDF_ObjectAvail() {} + +CPDF_DataAvail::DocAvailStatus CPDF_ObjectAvail::CheckAvail() { + if (!LoadRootObject()) + return CPDF_DataAvail::DocAvailStatus::DataNotAvailable; + + if (CheckObjects()) { + CleanMemory(); + return CPDF_DataAvail::DocAvailStatus::DataAvailable; + } + return CPDF_DataAvail::DocAvailStatus::DataNotAvailable; +} + +bool CPDF_ObjectAvail::LoadRootObject() { + if (!non_parsed_objects_.empty()) + return true; + + while (root_ && root_->IsReference()) { + const uint32_t ref_obj_num = root_->AsReference()->GetRefObjNum(); + if (HasObjectParsed(ref_obj_num)) { + root_ = nullptr; + return true; + } + + const CPDF_ReadValidator::Session parse_session(validator_.Get()); + const CPDF_Object* direct = holder_->GetOrParseIndirectObject(ref_obj_num); + if (validator_->has_read_problems()) + return false; + + parsed_objnums_.insert(ref_obj_num); + root_ = direct; + } + std::stack non_parsed_objects_in_root; + if (AppendObjectSubRefs(root_.Get(), &non_parsed_objects_in_root)) { + non_parsed_objects_ = std::move(non_parsed_objects_in_root); + return true; + } + return false; +} + +bool CPDF_ObjectAvail::CheckObjects() { + std::stack objects_to_check = std::move(non_parsed_objects_); + std::set checked_objects; + while (!objects_to_check.empty()) { + const uint32_t obj_num = objects_to_check.top(); + objects_to_check.pop(); + + if (HasObjectParsed(obj_num)) + continue; + + if (!checked_objects.insert(obj_num).second) + continue; + + const CPDF_ReadValidator::Session parse_session(validator_.Get()); + const CPDF_Object* direct = holder_->GetOrParseIndirectObject(obj_num); + if (direct == root_.Get()) + continue; + + if (validator_->has_read_problems() || + !AppendObjectSubRefs(direct, &objects_to_check)) { + non_parsed_objects_.push(obj_num); + continue; + } + parsed_objnums_.insert(obj_num); + } + return non_parsed_objects_.empty(); +} + +bool CPDF_ObjectAvail::AppendObjectSubRefs(const CPDF_Object* object, + std::stack* refs) const { + ASSERT(refs); + if (!object) + return true; + + CPDF_ObjectWalker walker(object); + while (const CPDF_Object* obj = walker.GetNext()) { + const CPDF_ReadValidator::Session parse_session(validator_.Get()); + + // Skip if this object if it's an inlined root, the parent object or + // explicitily excluded. + const bool skip = (walker.GetParent() && obj == root_.Get()) || + walker.dictionary_key() == "Parent" || + (obj != root_.Get() && ExcludeObject(obj)); + + // We need to parse the object before we can do the exclusion check. + // This is because the exclusion check may check against a referenced + // field of the object which we need to make sure is loaded. + if (validator_->has_read_problems()) + return false; + + if (skip) { + walker.SkipWalkIntoCurrentObject(); + continue; + } + + if (obj->IsReference()) + refs->push(obj->AsReference()->GetRefObjNum()); + } + return true; +} + +void CPDF_ObjectAvail::CleanMemory() { + root_.Reset(); + parsed_objnums_.clear(); +} + +bool CPDF_ObjectAvail::ExcludeObject(const CPDF_Object* object) const { + return false; +} + +bool CPDF_ObjectAvail::HasObjectParsed(uint32_t obj_num) const { + return parsed_objnums_.count(obj_num) > 0; +} diff --git a/core/fpdfapi/parser/cpdf_object_avail.h b/core/fpdfapi/parser/cpdf_object_avail.h new file mode 100644 index 0000000000000000000000000000000000000000..f593ea21590ef28f1010b9a87661771481571cd7 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_object_avail.h @@ -0,0 +1,53 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FPDFAPI_PARSER_CPDF_OBJECT_AVAIL_H_ +#define CORE_FPDFAPI_PARSER_CPDF_OBJECT_AVAIL_H_ + +#include +#include +#include + +#include "core/fpdfapi/parser/cpdf_data_avail.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPDF_Object; +class CPDF_Reference; +class CPDF_IndirectObjectHolder; +class CPDF_ReadValidator; + +// Helper for check availability of object tree. +class CPDF_ObjectAvail { + public: + CPDF_ObjectAvail(CPDF_ReadValidator* validator, + CPDF_IndirectObjectHolder* holder, + const CPDF_Object* root); + CPDF_ObjectAvail(CPDF_ReadValidator* validator, + CPDF_IndirectObjectHolder* holder, + uint32_t obj_num); + virtual ~CPDF_ObjectAvail(); + + CPDF_DataAvail::DocAvailStatus CheckAvail(); + + protected: + virtual bool ExcludeObject(const CPDF_Object* object) const; + + private: + bool LoadRootObject(); + bool CheckObjects(); + bool AppendObjectSubRefs(const CPDF_Object* object, + std::stack* refs) const; + void CleanMemory(); + bool HasObjectParsed(uint32_t obj_num) const; + + UnownedPtr validator_; + // TODO(art-snake): Make it UnownedPtr<, after fix document owning issue. + CPDF_IndirectObjectHolder* holder_; + MaybeOwned root_; + std::set parsed_objnums_; + std::stack non_parsed_objects_; +}; + +#endif // CORE_FPDFAPI_PARSER_CPDF_OBJECT_AVAIL_H_ diff --git a/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c3da70530a90b9ba6ee8f34dc073c828c6f17c5 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_object_avail_unittest.cpp @@ -0,0 +1,350 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_object_avail.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fxcrt/fx_stream.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +namespace { + +class TestReadValidator : public CPDF_ReadValidator { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + void SimulateReadError() { ReadBlock(nullptr, 0, 1); } + + protected: + TestReadValidator() + : CPDF_ReadValidator( + pdfium::MakeRetain(100), + nullptr) {} + ~TestReadValidator() override {} +}; + +class TestHolder : public CPDF_IndirectObjectHolder { + public: + enum class ObjectState { + Unavailable, + Available, + }; + TestHolder() : validator_(pdfium::MakeRetain()) {} + ~TestHolder() override {} + + // CPDF_IndirectObjectHolder overrides: + CPDF_Object* GetOrParseIndirectObject(uint32_t objnum) override { + auto it = objects_data_.find(objnum); + if (it == objects_data_.end()) + return nullptr; + + ObjectData& obj_data = it->second; + if (obj_data.state == ObjectState::Unavailable) { + validator_->SimulateReadError(); + return nullptr; + } + return obj_data.object.get(); + } + + RetainPtr GetValidator() { return validator_; } + + void AddObject(uint32_t objnum, + std::unique_ptr object, + ObjectState state) { + ObjectData object_data; + object_data.object = std::move(object); + object_data.state = state; + ASSERT(objects_data_.find(objnum) == objects_data_.end()); + objects_data_[objnum] = std::move(object_data); + } + + void SetObjectState(uint32_t objnum, ObjectState state) { + auto it = objects_data_.find(objnum); + ASSERT(it != objects_data_.end()); + ObjectData& obj_data = it->second; + obj_data.state = state; + } + + CPDF_Object* GetTestObject(uint32_t objnum) { + auto it = objects_data_.find(objnum); + if (it == objects_data_.end()) + return nullptr; + return it->second.object.get(); + } + + private: + struct ObjectData { + std::unique_ptr object; + ObjectState state = ObjectState::Unavailable; + }; + std::map objects_data_; + RetainPtr validator_; +}; + +class CPDF_ObjectAvailFailOnExclude : public CPDF_ObjectAvail { + public: + using CPDF_ObjectAvail::CPDF_ObjectAvail; + ~CPDF_ObjectAvailFailOnExclude() override {} + bool ExcludeObject(const CPDF_Object* object) const override { + NOTREACHED(); + return false; + } +}; + +class CPDF_ObjectAvailExcludeArray : public CPDF_ObjectAvail { + public: + using CPDF_ObjectAvail::CPDF_ObjectAvail; + ~CPDF_ObjectAvailExcludeArray() override {} + bool ExcludeObject(const CPDF_Object* object) const override { + return object->IsArray(); + } +}; + +class CPDF_ObjectAvailExcludeTypeKey : public CPDF_ObjectAvail { + public: + using CPDF_ObjectAvail::CPDF_ObjectAvail; + ~CPDF_ObjectAvailExcludeTypeKey() override {} + bool ExcludeObject(const CPDF_Object* object) const override { + // The value of "Type" may be reference, and if it is not available, we can + // incorrect filter objects. + // In this case CPDF_ObjectAvail should wait availability of this item and + // call ExcludeObject again. + return object->IsDictionary() && + object->GetDict()->GetStringFor("Type") == "Exclude me"; + } +}; + +} // namespace + +TEST(CPDF_ObjectAvailTest, OneObject) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(nullptr, "string", false), + TestHolder::ObjectState::Unavailable); + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + holder.SetObjectState(1, TestHolder::ObjectState::Available); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, OneReferencedObject) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(&holder, 2), + TestHolder::ObjectState::Unavailable); + holder.AddObject(2, pdfium::MakeUnique(nullptr, "string", false), + TestHolder::ObjectState::Unavailable); + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(1, TestHolder::ObjectState::Available); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(2, TestHolder::ObjectState::Available); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, CycledReferences) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(&holder, 2), + TestHolder::ObjectState::Unavailable); + holder.AddObject(2, pdfium::MakeUnique(&holder, 3), + TestHolder::ObjectState::Unavailable); + holder.AddObject(3, pdfium::MakeUnique(&holder, 1), + TestHolder::ObjectState::Unavailable); + + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(1, TestHolder::ObjectState::Available); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(2, TestHolder::ObjectState::Available); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(3, TestHolder::ObjectState::Available); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, DoNotCheckParent) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Unavailable); + holder.AddObject(2, pdfium::MakeUnique(), + TestHolder::ObjectState::Unavailable); + + holder.GetTestObject(2)->GetDict()->SetNewFor("Parent", + &holder, 1); + + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 2); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(2, TestHolder::ObjectState::Available); + // Object should be available in case when "Parent" object is unavailable. + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, Generic) { + TestHolder holder; + const uint32_t kDepth = 100; + for (uint32_t i = 1; i < kDepth; ++i) { + holder.AddObject(i, pdfium::MakeUnique(), + TestHolder::ObjectState::Unavailable); + // Add ref to next dictionary. + holder.GetTestObject(i)->GetDict()->SetNewFor( + "Child", &holder, i + 1); + } + // Add final object + holder.AddObject(kDepth, pdfium::MakeUnique(), + TestHolder::ObjectState::Unavailable); + + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + + for (uint32_t i = 1; i <= kDepth; ++i) { + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + holder.SetObjectState(i, TestHolder::ObjectState::Available); + } + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, NotExcludeRoot) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, NotExcludeReferedRoot) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(&holder, 2), + TestHolder::ObjectState::Available); + holder.AddObject(2, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + CPDF_ObjectAvailFailOnExclude avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, Exclude) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(1)->GetDict()->SetNewFor("ArrayRef", + &holder, 2); + holder.AddObject(2, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(2)->AsArray()->AddNew(&holder, 2); + + // Add string, which is refered by array item. It is should not be checked. + holder.AddObject( + 3, + pdfium::MakeUnique(nullptr, "Not available string", false), + TestHolder::ObjectState::Unavailable); + CPDF_ObjectAvailExcludeArray avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, ReadErrorOnExclude) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(1)->GetDict()->SetNewFor("DictRef", + &holder, 2); + holder.AddObject(2, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + + holder.GetTestObject(2)->GetDict()->SetNewFor("Type", &holder, + 3); + // The value of "Type" key is not available at start + holder.AddObject( + 3, pdfium::MakeUnique(nullptr, "Exclude me", false), + TestHolder::ObjectState::Unavailable); + + holder.GetTestObject(2)->GetDict()->SetNewFor("OtherData", + &holder, 4); + // Add string, which is refered by dictionary item. It is should not be + // checked, because the dictionary with it, should be skipped. + holder.AddObject( + 4, + pdfium::MakeUnique(nullptr, "Not available string", false), + TestHolder::ObjectState::Unavailable); + + CPDF_ObjectAvailExcludeTypeKey avail(holder.GetValidator().Get(), &holder, 1); + + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + // Make "Type" value object available. + holder.SetObjectState(3, TestHolder::ObjectState::Available); + + // Now object should be available, although the object '4' is not available, + // because it is in skipped dictionary. + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, IgnoreNotExistsObject) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(1)->GetDict()->SetNewFor( + "NotExistsObjRef", &holder, 2); + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + // Now object should be available, although the object '2' is not exists. But + // all exists in file related data are checked. + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, CheckTwice) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(nullptr, "string", false), + TestHolder::ObjectState::Unavailable); + + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + EXPECT_EQ(avail.CheckAvail(), avail.CheckAvail()); + + holder.SetObjectState(1, TestHolder::ObjectState::Available); + EXPECT_EQ(avail.CheckAvail(), avail.CheckAvail()); +} + +TEST(CPDF_ObjectAvailTest, SelfReferedInlinedObject) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + + holder.GetTestObject(1)->GetDict()->SetNewFor("Data", &holder, + 2); + auto* root = + holder.GetTestObject(1)->GetDict()->SetNewFor("Dict"); + + root->SetNewFor("Self", &holder, 1); + + holder.AddObject(2, pdfium::MakeUnique(nullptr, "Data", false), + TestHolder::ObjectState::Unavailable); + + CPDF_ObjectAvail avail(holder.GetValidator().Get(), &holder, root); + + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataNotAvailable, + avail.CheckAvail()); + + holder.SetObjectState(2, TestHolder::ObjectState::Available); + + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp index 927b1064745a294f2a91afcd71f1a7631ab32d97..4b16021069ae191bbbb9091549b7d020af2f3d23 100644 --- a/core/fpdfapi/parser/cpdf_object_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp @@ -2,23 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include +#include +#include +#include + #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_boolean.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_null.h" #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" - -#include -#include -#include -#include - -#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" -#include "core/fxcrt/fx_basic.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -82,7 +80,7 @@ class PDFObjectsTest : public testing::Test { // All direct objects. CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj, number_float_obj, str_reg_obj, str_spec_obj, - name_obj, m_ArrayObj, m_DictObj, + name_obj, m_ArrayObj.Get(), m_DictObj.Get(), stream_obj, null_obj}; m_DirectObjTypes = { CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, @@ -162,8 +160,8 @@ class PDFObjectsTest : public testing::Test { // streams need to be handled. if (!stream1->IsMemoryBased() || !stream2->IsMemoryBased()) return false; - return FXSYS_memcmp(stream1->GetRawData(), stream2->GetRawData(), - stream1->GetRawSize()) == 0; + return memcmp(stream1->GetRawData(), stream2->GetRawData(), + stream1->GetRawSize()) == 0; } case CPDF_Object::REFERENCE: return obj1->AsReference()->GetRefObjNum() == @@ -179,9 +177,9 @@ class PDFObjectsTest : public testing::Test { std::vector> m_DirectObjs; std::vector m_DirectObjTypes; std::vector> m_RefObjs; - CPDF_Dictionary* m_DictObj; - CPDF_Dictionary* m_StreamDictObj; - CPDF_Array* m_ArrayObj; + UnownedPtr m_DictObj; + UnownedPtr m_StreamDictObj; + UnownedPtr m_ArrayObj; std::vector m_IndirectObjs; }; @@ -218,14 +216,14 @@ TEST_F(PDFObjectsTest, GetUnicodeText) { } TEST_F(PDFObjectsTest, GetNumber) { - const FX_FLOAT direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0, - 0, 0, 0, 0, 0}; + const float direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0, + 0, 0, 0, 0, 0}; // Check for direct objects. for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetNumber()); // Check indirect references. - const FX_FLOAT indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0}; + const float indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0}; for (size_t i = 0; i < m_RefObjs.size(); ++i) EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetNumber()); } @@ -244,23 +242,29 @@ TEST_F(PDFObjectsTest, GetInteger) { TEST_F(PDFObjectsTest, GetDict) { const CPDF_Dictionary* const direct_obj_results[] = { - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr}; + nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, m_DictObj.Get(), m_StreamDictObj.Get(), + nullptr}; // Check for direct objects. for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict()); // Check indirect references. - const CPDF_Dictionary* const indirect_obj_results[] = { - nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj}; + const CPDF_Dictionary* const indirect_obj_results[] = {nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + m_DictObj.Get(), + m_StreamDictObj.Get()}; for (size_t i = 0; i < m_RefObjs.size(); ++i) EXPECT_TRUE(Equal(indirect_obj_results[i], m_RefObjs[i]->GetDict())); } TEST_F(PDFObjectsTest, GetArray) { const CPDF_Array* const direct_obj_results[] = { - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, m_ArrayObj, nullptr, nullptr, nullptr}; + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, m_ArrayObj.Get(), nullptr, nullptr, nullptr}; // Check for direct objects. for (size_t i = 0; i < m_DirectObjs.size(); ++i) EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray()); @@ -484,8 +488,8 @@ TEST(PDFArrayTest, GetTypeAt) { // String and name array const char* const vals[] = {"this", "adsde$%^", "\r\t", "\"012", ".", "EYREW", "It is a joke :)"}; - std::unique_ptr string_array(new CPDF_Array); - std::unique_ptr name_array(new CPDF_Array); + auto string_array = pdfium::MakeUnique(); + auto name_array = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(vals); ++i) { string_array->InsertNewAt(i, vals[i], false); name_array->InsertNewAt(i, vals[i]); @@ -693,10 +697,11 @@ TEST(PDFArrayTest, AddInteger) { } TEST(PDFArrayTest, AddStringAndName) { - const char* vals[] = {"", "a", "ehjhRIOYTTFdfcdnv", "122323", - "$#%^&**", " ", "This is a test.\r\n"}; - std::unique_ptr string_array(new CPDF_Array); - std::unique_ptr name_array(new CPDF_Array); + static constexpr const char* vals[] = { + "", "a", "ehjhRIOYTTFdfcdnv", "122323", + "$#%^&**", " ", "This is a test.\r\n"}; + auto string_array = pdfium::MakeUnique(); + auto name_array = pdfium::MakeUnique(); for (size_t i = 0; i < FX_ArraySize(vals); ++i) { string_array->AddNew(vals[i], false); name_array->AddNew(vals[i]); @@ -710,8 +715,7 @@ TEST(PDFArrayTest, AddStringAndName) { } TEST(PDFArrayTest, AddReferenceAndGetObjectAt) { - std::unique_ptr holder( - new CPDF_IndirectObjectHolder()); + auto holder = pdfium::MakeUnique(); CPDF_Boolean* boolean_obj = new CPDF_Boolean(true); CPDF_Number* int_obj = new CPDF_Number(-1234); CPDF_Number* float_obj = new CPDF_Number(2345.089f); @@ -723,7 +727,7 @@ TEST(PDFArrayTest, AddReferenceAndGetObjectAt) { str_obj, name_obj, null_obj}; unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1}; auto arr = pdfium::MakeUnique(); - std::unique_ptr arr1(new CPDF_Array); + auto arr1 = pdfium::MakeUnique(); // Create two arrays of references by different AddReference() APIs. for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) { holder->ReplaceIndirectObjectIfHigherGeneration( @@ -748,7 +752,7 @@ TEST(PDFArrayTest, AddReferenceAndGetObjectAt) { TEST(PDFArrayTest, CloneDirectObject) { CPDF_IndirectObjectHolder objects_holder; - std::unique_ptr array(new CPDF_Array); + auto array = pdfium::MakeUnique(); array->AddNew(&objects_holder, 1234); ASSERT_EQ(1U, array->GetCount()); CPDF_Object* obj = array->GetObjectAt(0); @@ -761,7 +765,7 @@ TEST(PDFArrayTest, CloneDirectObject) { std::unique_ptr cloned_array = ToArray(std::move(cloned_array_object)); - ASSERT_EQ(1U, cloned_array->GetCount()); + ASSERT_EQ(0U, cloned_array->GetCount()); CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0); EXPECT_FALSE(cloned_obj); } @@ -780,9 +784,78 @@ TEST(PDFArrayTest, ConvertIndirect) { EXPECT_EQ(42, array->GetIntegerAt(0)); } +TEST(PDFStreamTest, SetData) { + std::vector data(100); + auto stream = pdfium::MakeUnique(); + stream->InitStream(data.data(), data.size(), + pdfium::MakeUnique()); + EXPECT_EQ(static_cast(data.size()), + stream->GetDict()->GetIntegerFor("Length")); + + stream->GetDict()->SetNewFor("Filter", L"SomeFilter"); + stream->GetDict()->SetNewFor("DecodeParms", L"SomeParams"); + + std::vector new_data(data.size() * 2); + stream->SetData(new_data.data(), new_data.size()); + + // The "Length" field should be updated for new data size. + EXPECT_EQ(static_cast(new_data.size()), + stream->GetDict()->GetIntegerFor("Length")); + + // The "Filter" and "DecodeParms" fields should not be changed. + EXPECT_EQ(stream->GetDict()->GetUnicodeTextFor("Filter"), L"SomeFilter"); + EXPECT_EQ(stream->GetDict()->GetUnicodeTextFor("DecodeParms"), L"SomeParams"); +} + +TEST(PDFStreamTest, SetDataAndRemoveFilter) { + std::vector data(100); + auto stream = pdfium::MakeUnique(); + stream->InitStream(data.data(), data.size(), + pdfium::MakeUnique()); + EXPECT_EQ(static_cast(data.size()), + stream->GetDict()->GetIntegerFor("Length")); + + stream->GetDict()->SetNewFor("Filter", L"SomeFilter"); + stream->GetDict()->SetNewFor("DecodeParms", L"SomeParams"); + + std::vector new_data(data.size() * 2); + stream->SetDataAndRemoveFilter(new_data.data(), new_data.size()); + // The "Length" field should be updated for new data size. + EXPECT_EQ(static_cast(new_data.size()), + stream->GetDict()->GetIntegerFor("Length")); + + // The "Filter" and "DecodeParms" should be removed. + EXPECT_FALSE(stream->GetDict()->KeyExist("Filter")); + EXPECT_FALSE(stream->GetDict()->KeyExist("DecodeParms")); +} + +TEST(PDFStreamTest, LengthInDictionaryOnCreate) { + static constexpr uint32_t kBufSize = 100; + // The length field should be created on stream create. + { + std::unique_ptr data; + data.reset(FX_Alloc(uint8_t, kBufSize)); + auto stream = pdfium::MakeUnique( + std::move(data), kBufSize, pdfium::MakeUnique()); + EXPECT_EQ(static_cast(kBufSize), + stream->GetDict()->GetIntegerFor("Length")); + } + // The length field should be corrected on stream create. + { + std::unique_ptr data; + data.reset(FX_Alloc(uint8_t, kBufSize)); + auto dict = pdfium::MakeUnique(); + dict->SetNewFor("Length", 30000); + auto stream = pdfium::MakeUnique(std::move(data), kBufSize, + std::move(dict)); + EXPECT_EQ(static_cast(kBufSize), + stream->GetDict()->GetIntegerFor("Length")); + } +} + TEST(PDFDictionaryTest, CloneDirectObject) { CPDF_IndirectObjectHolder objects_holder; - std::unique_ptr dict(new CPDF_Dictionary()); + auto dict = pdfium::MakeUnique(); dict->SetNewFor("foo", &objects_holder, 1234); ASSERT_EQ(1U, dict->GetCount()); CPDF_Object* obj = dict->GetObjectFor("foo"); @@ -795,7 +868,7 @@ TEST(PDFDictionaryTest, CloneDirectObject) { std::unique_ptr cloned_dict = ToDictionary(std::move(cloned_dict_object)); - ASSERT_EQ(1U, cloned_dict->GetCount()); + ASSERT_EQ(0U, cloned_dict->GetCount()); CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); EXPECT_FALSE(cloned_obj); } @@ -859,7 +932,7 @@ TEST(PDFObjectTest, CloneCheckLoop) { CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); ASSERT_TRUE(cloned_arr); ASSERT_TRUE(cloned_arr->IsArray()); - EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); + EXPECT_EQ(0U, cloned_arr->AsArray()->GetCount()); // Recursively referenced object is not cloned. EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); } @@ -867,7 +940,7 @@ TEST(PDFObjectTest, CloneCheckLoop) { TEST(PDFDictionaryTest, ConvertIndirect) { CPDF_IndirectObjectHolder objects_holder; - std::unique_ptr dict(new CPDF_Dictionary); + auto dict = pdfium::MakeUnique(); CPDF_Object* pObj = dict->SetNewFor("clams", 42); dict->ConvertToIndirectObjectFor("clams", &objects_holder); CPDF_Object* pRef = dict->GetObjectFor("clams"); @@ -878,3 +951,13 @@ TEST(PDFDictionaryTest, ConvertIndirect) { EXPECT_EQ(pObj, pNum); EXPECT_EQ(42, dict->GetIntegerFor("clams")); } + +TEST(PDFDictionaryTest, ExtractObjectOnRemove) { + auto dict = pdfium::MakeUnique(); + CPDF_Object* pObj = dict->SetNewFor("child", 42); + auto extracted_object = dict->RemoveFor("child"); + EXPECT_EQ(pObj, extracted_object.get()); + + extracted_object = dict->RemoveFor("non_exists_object"); + EXPECT_FALSE(extracted_object); +} diff --git a/core/fpdfapi/parser/cpdf_object_walker.cpp b/core/fpdfapi/parser/cpdf_object_walker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb59a05d06f5cf141bf6dcecf378956bc1fb3c5a --- /dev/null +++ b/core/fpdfapi/parser/cpdf_object_walker.cpp @@ -0,0 +1,165 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_object_walker.h" + +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_stream.h" + +namespace { + +class StreamIterator : public CPDF_ObjectWalker::SubobjectIterator { + public: + explicit StreamIterator(const CPDF_Stream* stream) + : SubobjectIterator(stream) {} + ~StreamIterator() override {} + + bool IsFinished() const override { return IsStarted() && is_finished_; } + + const CPDF_Object* IncrementImpl() override { + ASSERT(IsStarted()); + ASSERT(!IsFinished()); + is_finished_ = true; + return object()->GetDict(); + } + + void Start() override {} + + private: + bool is_finished_ = false; +}; + +class DictionaryIterator : public CPDF_ObjectWalker::SubobjectIterator { + public: + explicit DictionaryIterator(const CPDF_Dictionary* dictionary) + : SubobjectIterator(dictionary) {} + ~DictionaryIterator() override {} + + bool IsFinished() const override { + return IsStarted() && dict_iterator_ == object()->GetDict()->end(); + } + + const CPDF_Object* IncrementImpl() override { + ASSERT(IsStarted()); + ASSERT(!IsFinished()); + const CPDF_Object* result = dict_iterator_->second.get(); + dict_key_ = dict_iterator_->first; + ++dict_iterator_; + return result; + } + + void Start() override { + ASSERT(!IsStarted()); + dict_iterator_ = object()->GetDict()->begin(); + } + + const ByteString& dict_key() const { return dict_key_; } + + private: + CPDF_Dictionary::const_iterator dict_iterator_; + ByteString dict_key_; +}; + +class ArrayIterator : public CPDF_ObjectWalker::SubobjectIterator { + public: + explicit ArrayIterator(const CPDF_Array* array) : SubobjectIterator(array) {} + + ~ArrayIterator() override {} + + bool IsFinished() const override { + return IsStarted() && arr_iterator_ == object()->AsArray()->end(); + } + + const CPDF_Object* IncrementImpl() override { + ASSERT(IsStarted()); + ASSERT(!IsFinished()); + const CPDF_Object* result = arr_iterator_->get(); + ++arr_iterator_; + return result; + } + + void Start() override { arr_iterator_ = object()->AsArray()->begin(); } + + public: + CPDF_Array::const_iterator arr_iterator_; +}; + +} // namespace + +CPDF_ObjectWalker::SubobjectIterator::~SubobjectIterator() {} + +const CPDF_Object* CPDF_ObjectWalker::SubobjectIterator::Increment() { + if (!IsStarted()) { + Start(); + is_started_ = true; + } + while (!IsFinished()) { + const CPDF_Object* result = IncrementImpl(); + if (result) + return result; + } + return nullptr; +} + +CPDF_ObjectWalker::SubobjectIterator::SubobjectIterator( + const CPDF_Object* object) + : object_(object) { + ASSERT(object_); +} + +// static +std::unique_ptr +CPDF_ObjectWalker::MakeIterator(const CPDF_Object* object) { + if (object->IsStream()) + return pdfium::MakeUnique(object->AsStream()); + if (object->IsDictionary()) + return pdfium::MakeUnique(object->AsDictionary()); + if (object->IsArray()) + return pdfium::MakeUnique(object->AsArray()); + return nullptr; +} + +CPDF_ObjectWalker::CPDF_ObjectWalker(const CPDF_Object* root) + : next_object_(root), parent_object_(nullptr), current_depth_(0) {} + +CPDF_ObjectWalker::~CPDF_ObjectWalker() {} + +const CPDF_Object* CPDF_ObjectWalker::GetNext() { + while (!stack_.empty() || next_object_) { + if (next_object_) { + auto new_iterator = MakeIterator(next_object_); + if (new_iterator) { + // Schedule walk within composite objects. + stack_.push(std::move(new_iterator)); + } + auto* result = next_object_; + next_object_ = nullptr; + return result; + } + + SubobjectIterator* it = stack_.top().get(); + if (it->IsFinished()) { + stack_.pop(); + } else { + next_object_ = it->Increment(); + parent_object_ = it->object(); + dict_key_ = parent_object_->IsDictionary() + ? static_cast(it)->dict_key() + : ByteString(); + current_depth_ = stack_.size(); + } + } + dict_key_ = ByteString(); + current_depth_ = 0; + return nullptr; +} + +void CPDF_ObjectWalker::SkipWalkIntoCurrentObject() { + if (stack_.empty() || stack_.top()->IsStarted()) + return; + stack_.pop(); +} diff --git a/core/fpdfapi/parser/cpdf_object_walker.h b/core/fpdfapi/parser/cpdf_object_walker.h new file mode 100644 index 0000000000000000000000000000000000000000..8cad3c32f3ff29733b59b1174aa9430cd36a703b --- /dev/null +++ b/core/fpdfapi/parser/cpdf_object_walker.h @@ -0,0 +1,69 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FPDFAPI_PARSER_CPDF_OBJECT_WALKER_H_ +#define CORE_FPDFAPI_PARSER_CPDF_OBJECT_WALKER_H_ + +#include +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" + +// Walk on all non-null sub-objects in an object in depth, include itself, +// like in flat list. +class CPDF_ObjectWalker { + public: + class SubobjectIterator { + public: + virtual ~SubobjectIterator(); + bool IsStarted() const { return is_started_; } + bool virtual IsFinished() const = 0; + const CPDF_Object* Increment(); + const CPDF_Object* object() const { return object_; } + + protected: + explicit SubobjectIterator(const CPDF_Object* object); + + virtual const CPDF_Object* IncrementImpl() = 0; + virtual void Start() = 0; + + private: + const CPDF_Object* object_; + bool is_started_ = false; + }; + + explicit CPDF_ObjectWalker(const CPDF_Object* root); + ~CPDF_ObjectWalker(); + + const CPDF_Object* GetNext(); + void SkipWalkIntoCurrentObject(); + + size_t current_depth() const { return current_depth_; } + const CPDF_Object* GetParent() const { return parent_object_; } + const ByteString& dictionary_key() const { return dict_key_; } + + private: + static std::unique_ptr MakeIterator( + const CPDF_Object* object); + + const CPDF_Object* next_object_; + const CPDF_Object* parent_object_; + + ByteString dict_key_; + size_t current_depth_; + + std::stack> stack_; +}; + +class CPDF_NonConstObjectWalker : public CPDF_ObjectWalker { + public: + explicit CPDF_NonConstObjectWalker(CPDF_Object* root) + : CPDF_ObjectWalker(root) {} + + CPDF_Object* GetNext() { + return const_cast(CPDF_ObjectWalker::GetNext()); + } +}; + +#endif // CORE_FPDFAPI_PARSER_CPDF_OBJECT_WALKER_H_ diff --git a/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp b/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5ffe844ad91e799e877ab1836e8b0dab229dd75 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_object_walker_unittest.cpp @@ -0,0 +1,145 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_object_walker.h" + +#include +#include +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_boolean.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_null.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +namespace { + +std::string Walk(CPDF_Object* object) { + std::ostringstream result; + CPDF_ObjectWalker walker(object); + while (const CPDF_Object* obj = walker.GetNext()) { + if (obj->IsDictionary()) + result << " Dict"; + else if (obj->IsArray()) + result << " Arr"; + else if (obj->IsString()) + result << " Str"; + else if (obj->IsBoolean()) + result << " Bool"; + else if (obj->IsStream()) + result << " Stream"; + else if (obj->IsReference()) + result << " Ref"; + else if (obj->IsNumber()) + result << " Num"; + else if (obj->IsNull()) + result << " Null"; + else + result << " Unknown"; + } + std::string result_str = result.str(); + if (!result_str.empty()) { + result_str.erase(result_str.begin()); // remove start space + } + return result_str; +} + +} // namespace + +TEST(CPDF_ObjectWalkerTest, Simple) { + EXPECT_EQ(Walk(pdfium::MakeUnique().get()), "Null"); + EXPECT_EQ(Walk(pdfium::MakeUnique().get()), "Dict"); + EXPECT_EQ(Walk(pdfium::MakeUnique().get()), "Arr"); + EXPECT_EQ(Walk(pdfium::MakeUnique().get()), "Str"); + EXPECT_EQ(Walk(pdfium::MakeUnique().get()), "Bool"); + EXPECT_EQ(Walk(pdfium::MakeUnique().get()), "Stream"); + EXPECT_EQ(Walk(pdfium::MakeUnique(nullptr, 0).get()), "Ref"); +} + +TEST(CPDF_ObjectWalkerTest, CombinedObject) { + auto dict = pdfium::MakeUnique(); + dict->SetFor("1", pdfium::MakeUnique()); + dict->SetFor("2", pdfium::MakeUnique()); + auto array = pdfium::MakeUnique(); + array->Add(pdfium::MakeUnique(nullptr, 0)); + array->Add(pdfium::MakeUnique()); + array->Add(pdfium::MakeUnique( + nullptr, 0, pdfium::MakeUnique())); + dict->SetFor("3", std::move(array)); + // The last number for stream length. + EXPECT_EQ(Walk(dict.get()), "Dict Str Bool Arr Ref Null Stream Dict Num"); +} + +TEST(CPDF_ObjectWalkerTest, GetParent) { + auto level_4 = pdfium::MakeUnique(0); + auto level_3 = pdfium::MakeUnique(); + level_3->SetFor("Length", std::move(level_4)); + auto level_2 = + pdfium::MakeUnique(nullptr, 0, std::move(level_3)); + auto level_1 = pdfium::MakeUnique(); + level_1->Add(std::move(level_2)); + auto level_0 = pdfium::MakeUnique(); + level_0->SetFor("Array", std::move(level_1)); + + // We have <>) ]>> + // In this case each step will increase depth. + // And on each step the prev object should be parent for current. + const CPDF_Object* cur_parent = nullptr; + CPDF_ObjectWalker walker(level_0.get()); + while (const CPDF_Object* obj = walker.GetNext()) { + EXPECT_EQ(cur_parent, walker.GetParent()); + cur_parent = obj; + } +} + +TEST(CPDF_ObjectWalkerTest, SkipWalkIntoCurrentObject) { + auto root_array = pdfium::MakeUnique(); + // Add 2 null objects into |root_array|. [ null1, null2 ] + root_array->AddNew(); + root_array->AddNew(); + // |root_array| will contain 4 null objects after this. + // [ null1, null2, [ null3, null4 ] ] + root_array->Add(root_array->Clone()); + + int non_array_objects = 0; + CPDF_ObjectWalker walker(root_array.get()); + while (const CPDF_Object* obj = walker.GetNext()) { + if (obj != root_array.get() && obj->IsArray()) { + // skip other array except root. + walker.SkipWalkIntoCurrentObject(); + } + if (!obj->IsArray()) + ++non_array_objects; + } + // 2 objects from child array should be skipped. + EXPECT_EQ(2, non_array_objects); +} + +TEST(CPDF_ObjectWalkerTest, DictionaryKey) { + auto dict = pdfium::MakeUnique(); + dict->SetFor("1", pdfium::MakeUnique()); + dict->SetFor("2", pdfium::MakeUnique()); + dict->SetFor("3", pdfium::MakeUnique()); + dict->SetFor("4", pdfium::MakeUnique()); + dict->SetFor("5", pdfium::MakeUnique()); + + CPDF_ObjectWalker walker(dict.get()); + while (const CPDF_Object* obj = walker.GetNext()) { + if (obj == dict.get()) { + // Ignore root dictinary object + continue; + } + // Test that, dictionary key is correct. + EXPECT_EQ(walker.GetParent()->AsDictionary()->GetObjectFor( + walker.dictionary_key()), + obj); + } +} diff --git a/core/fpdfapi/parser/cpdf_page_object_avail.cpp b/core/fpdfapi/parser/cpdf_page_object_avail.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6673885f61f6c4b5a8d6ea6684b3346787d1ad34 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_page_object_avail.cpp @@ -0,0 +1,17 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_page_object_avail.h" + +#include "core/fpdfapi/parser/cpdf_dictionary.h" + +CPDF_PageObjectAvail::~CPDF_PageObjectAvail() {} + +bool CPDF_PageObjectAvail::ExcludeObject(const CPDF_Object* object) const { + if (CPDF_ObjectAvail::ExcludeObject(object)) + return true; + + return object->IsDictionary() && + object->GetDict()->GetStringFor("Type") == "Page"; +} diff --git a/core/fpdfapi/parser/cpdf_page_object_avail.h b/core/fpdfapi/parser/cpdf_page_object_avail.h new file mode 100644 index 0000000000000000000000000000000000000000..8c740ed0458701bd3bd25032cc0e47d20f49e9d3 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_page_object_avail.h @@ -0,0 +1,21 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FPDFAPI_PARSER_CPDF_PAGE_OBJECT_AVAIL_H_ +#define CORE_FPDFAPI_PARSER_CPDF_PAGE_OBJECT_AVAIL_H_ + +#include "core/fpdfapi/parser/cpdf_object_avail.h" + +// Helper for check availability of page's object tree. +// Exclude references to pages. +class CPDF_PageObjectAvail : public CPDF_ObjectAvail { + public: + using CPDF_ObjectAvail::CPDF_ObjectAvail; + ~CPDF_PageObjectAvail() override; + + protected: + bool ExcludeObject(const CPDF_Object* object) const override; +}; + +#endif // CORE_FPDFAPI_PARSER_CPDF_PAGE_OBJECT_AVAIL_H_ diff --git a/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14ba0e32733f7a84096f4d28761100c5896f70fe --- /dev/null +++ b/core/fpdfapi/parser/cpdf_page_object_avail_unittest.cpp @@ -0,0 +1,125 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_page_object_avail.h" + +#include +#include +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fxcrt/fx_stream.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +namespace { + + +class TestReadValidator : public CPDF_ReadValidator { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + void SimulateReadError() { ReadBlock(nullptr, 0, 1); } + + protected: + TestReadValidator() + : CPDF_ReadValidator( + pdfium::MakeRetain(100), + nullptr) {} + ~TestReadValidator() override {} +}; + +class TestHolder : public CPDF_IndirectObjectHolder { + public: + enum class ObjectState { + Unavailable, + Available, + }; + TestHolder() : validator_(pdfium::MakeRetain()) {} + ~TestHolder() override {} + + // CPDF_IndirectObjectHolder overrides: + CPDF_Object* GetOrParseIndirectObject(uint32_t objnum) override { + auto it = objects_data_.find(objnum); + if (it == objects_data_.end()) + return nullptr; + + ObjectData& obj_data = it->second; + if (obj_data.state == ObjectState::Unavailable) { + validator_->SimulateReadError(); + return nullptr; + } + return obj_data.object.get(); + } + + RetainPtr GetValidator() { return validator_; } + + void AddObject(uint32_t objnum, + std::unique_ptr object, + ObjectState state) { + ObjectData object_data; + object_data.object = std::move(object); + object_data.state = state; + ASSERT(objects_data_.find(objnum) == objects_data_.end()); + objects_data_[objnum] = std::move(object_data); + } + + void SetObjectState(uint32_t objnum, ObjectState state) { + auto it = objects_data_.find(objnum); + ASSERT(it != objects_data_.end()); + ObjectData& obj_data = it->second; + obj_data.state = state; + } + + CPDF_Object* GetTestObject(uint32_t objnum) { + auto it = objects_data_.find(objnum); + if (it == objects_data_.end()) + return nullptr; + return it->second.object.get(); + } + + private: + struct ObjectData { + std::unique_ptr object; + ObjectState state = ObjectState::Unavailable; + }; + std::map objects_data_; + RetainPtr validator_; +}; + +} // namespace + +TEST(CPDF_PageObjectAvailTest, ExcludePages) { + TestHolder holder; + holder.AddObject(1, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(1)->GetDict()->SetNewFor("Kids", &holder, + 2); + holder.AddObject(2, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(2)->AsArray()->AddNew(&holder, 3); + + holder.AddObject(3, pdfium::MakeUnique(), + TestHolder::ObjectState::Available); + holder.GetTestObject(3)->GetDict()->SetFor( + "Type", pdfium::MakeUnique(nullptr, "Page", false)); + holder.GetTestObject(3)->GetDict()->SetNewFor("OtherPageData", + &holder, 4); + // Add unavailable object related to other page. + holder.AddObject( + 4, pdfium::MakeUnique(nullptr, "Other page data", false), + TestHolder::ObjectState::Unavailable); + + CPDF_PageObjectAvail avail(holder.GetValidator().Get(), &holder, 1); + // Now object should be available, although the object '4' is not available, + // because it is in skipped other page. + EXPECT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, avail.CheckAvail()); +} diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index f9d9eb3a979ecd8b3c834567ddb86778f108d44f..0d1b02a5ce9067ebf5ff0019db929b4cf87b5d47 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -22,7 +22,9 @@ #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/cpdf_syntax_parser.h" #include "core/fpdfapi/parser/fpdf_parser_utility.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_safe_types.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" @@ -33,6 +35,8 @@ namespace { // this may be large enough in practice. const int32_t kMaxXRefSize = 1048576; +constexpr FX_FILESIZE kPDFHeaderSize = 9; + uint32_t GetVarInt(const uint8_t* p, int32_t n) { uint32_t result = 0; for (int32_t i = 0; i < n; ++i) @@ -40,30 +44,93 @@ uint32_t GetVarInt(const uint8_t* p, int32_t n) { return result; } -int32_t GetStreamNCount(CPDF_StreamAcc* pObjStream) { +int32_t GetStreamNCount(const RetainPtr& pObjStream) { return pObjStream->GetDict()->GetIntegerFor("N"); } -int32_t GetStreamFirst(CPDF_StreamAcc* pObjStream) { +int32_t GetStreamFirst(const RetainPtr& pObjStream) { return pObjStream->GetDict()->GetIntegerFor("First"); } } // namespace +class CPDF_Parser::TrailerData { + public: + TrailerData() {} + ~TrailerData() {} + + CPDF_Dictionary* GetMainTrailer() const { return main_trailer_.get(); } + + std::unique_ptr GetCombinedTrailer() const { + std::unique_ptr result = + ToDictionary(main_trailer_->Clone()); + + // Info is optional. + uint32_t info_obj_num = GetInfoObjNum(); + if (info_obj_num > 0) + result->SetNewFor("Info", nullptr, GetInfoObjNum()); + + // Root is required. + result->SetNewFor("Root", nullptr, GetRootObjNum()); + return result; + } + + void SetMainTrailer(std::unique_ptr trailer) { + ASSERT(trailer); + main_trailer_ = std::move(trailer); + ApplyTrailer(main_trailer_.get()); + } + + void AppendTrailer(std::unique_ptr trailer) { + ASSERT(trailer); + ApplyTrailer(trailer.get()); + } + + void Clear() { + main_trailer_.reset(); + last_info_obj_num_ = 0; + last_root_obj_num_ = 0; + } + + uint32_t GetInfoObjNum() const { + const CPDF_Reference* pRef = ToReference( + GetMainTrailer() ? GetMainTrailer()->GetObjectFor("Info") : nullptr); + return pRef ? pRef->GetRefObjNum() : last_info_obj_num_; + } + + uint32_t GetRootObjNum() const { + const CPDF_Reference* pRef = ToReference( + GetMainTrailer() ? GetMainTrailer()->GetObjectFor("Root") : nullptr); + return pRef ? pRef->GetRefObjNum() : last_root_obj_num_; + } + + private: + void ApplyTrailer(const CPDF_Dictionary* dict) { + // The most recent Info object number contained in last added trailer. + // See PDF 1.7 spec, section 3.4.5 - Incremental Updates. + const auto* pRef = ToReference(dict->GetObjectFor("Info")); + if (pRef) + last_info_obj_num_ = pRef->GetRefObjNum(); + + const auto* pRoot = ToReference(dict->GetObjectFor("Root")); + if (pRoot) + last_root_obj_num_ = pRoot->GetRefObjNum(); + } + + std::unique_ptr main_trailer_; + uint32_t last_info_obj_num_ = 0; + uint32_t last_root_obj_num_ = 0; +}; + CPDF_Parser::CPDF_Parser() - : m_pDocument(nullptr), + : m_pSyntax(pdfium::MakeUnique()), m_bHasParsed(false), m_bXRefStream(false), - m_bVersionUpdated(false), m_FileVersion(0), - m_pEncryptDict(nullptr), - m_dwXrefStartObjNum(0) { - m_pSyntax = pdfium::MakeUnique(); -} + m_TrailerData(pdfium::MakeUnique()) {} CPDF_Parser::~CPDF_Parser() { ReleaseEncryptHandler(); - SetEncryptDictionary(nullptr); } uint32_t CPDF_Parser::GetLastObjNum() const { @@ -79,10 +146,10 @@ FX_FILESIZE CPDF_Parser::GetObjectPositionOrZero(uint32_t objnum) const { return it != m_ObjectInfo.end() ? it->second.pos : 0; } -uint8_t CPDF_Parser::GetObjectType(uint32_t objnum) const { +CPDF_Parser::ObjectType CPDF_Parser::GetObjectType(uint32_t objnum) const { ASSERT(IsValidObjectNumber(objnum)); auto it = m_ObjectInfo.find(objnum); - return it != m_ObjectInfo.end() ? it->second.type : 0; + return it != m_ObjectInfo.end() ? it->second.type : ObjectType::kFree; } uint16_t CPDF_Parser::GetObjectGenNum(uint32_t objnum) const { @@ -92,20 +159,28 @@ uint16_t CPDF_Parser::GetObjectGenNum(uint32_t objnum) const { } bool CPDF_Parser::IsObjectFreeOrNull(uint32_t objnum) const { - uint8_t type = GetObjectType(objnum); - return type == 0 || type == 255; + switch (GetObjectType(objnum)) { + case ObjectType::kFree: + case ObjectType::kNull: + return true; + case ObjectType::kNotCompressed: + case ObjectType::kCompressed: + return false; + } + ASSERT(false); // NOTREACHED(); + return false; } -void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { - m_pEncryptDict = pDict; +bool CPDF_Parser::IsObjectFree(uint32_t objnum) const { + return GetObjectType(objnum) == ObjectType::kFree; } -CPDF_CryptoHandler* CPDF_Parser::GetCryptoHandler() { - return m_pSyntax->m_pCryptoHandler.get(); +void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { + m_pEncryptDict = pDict; } -CFX_RetainPtr CPDF_Parser::GetFileAccess() const { - return m_pSyntax->m_pFileAccess; +RetainPtr CPDF_Parser::GetFileAccess() const { + return m_pSyntax->GetFileAccess(); } void CPDF_Parser::ShrinkObjectMap(uint32_t objnum) { @@ -124,50 +199,55 @@ void CPDF_Parser::ShrinkObjectMap(uint32_t objnum) { m_ObjectInfo[objnum - 1].pos = 0; } -CPDF_Parser::Error CPDF_Parser::StartParse( - const CFX_RetainPtr& pFileAccess, - CPDF_Document* pDocument) { - ASSERT(!m_bHasParsed); - m_bHasParsed = true; - m_bXRefStream = false; - m_LastXRefOffset = 0; - - int32_t offset = GetHeaderOffset(pFileAccess); - if (offset == -1) - return FORMAT_ERROR; +bool CPDF_Parser::InitSyntaxParser( + const RetainPtr& file_access) { + const int32_t header_offset = GetHeaderOffset(file_access); + if (header_offset == kInvalidHeaderOffset) + return false; + if (file_access->GetSize() < header_offset + kPDFHeaderSize) + return false; - m_pSyntax->InitParser(pFileAccess, offset); + m_pSyntax->InitParser(file_access, header_offset); + return ParseFileVersion(); +} +bool CPDF_Parser::ParseFileVersion() { + m_FileVersion = 0; uint8_t ch; if (!m_pSyntax->GetCharAt(5, ch)) - return FORMAT_ERROR; + return false; if (std::isdigit(ch)) - m_FileVersion = FXSYS_toDecimalDigit(static_cast(ch)) * 10; + m_FileVersion = FXSYS_DecimalCharToInt(static_cast(ch)) * 10; if (!m_pSyntax->GetCharAt(7, ch)) - return FORMAT_ERROR; + return false; if (std::isdigit(ch)) - m_FileVersion += FXSYS_toDecimalDigit(static_cast(ch)); + m_FileVersion += FXSYS_DecimalCharToInt(static_cast(ch)); + return true; +} - if (m_pSyntax->m_FileLen < m_pSyntax->m_HeaderOffset + 9) +CPDF_Parser::Error CPDF_Parser::StartParse( + const RetainPtr& pFileAccess, + CPDF_Document* pDocument) { + if (!InitSyntaxParser(pFileAccess)) return FORMAT_ERROR; + return StartParseInternal(pDocument); +} + +CPDF_Parser::Error CPDF_Parser::StartParseInternal(CPDF_Document* pDocument) { + ASSERT(!m_bHasParsed); + m_bHasParsed = true; + m_bXRefStream = false; - m_pSyntax->RestorePos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - 9); m_pDocument = pDocument; bool bXRefRebuilt = false; - if (m_pSyntax->SearchWord("startxref", true, false, 4096)) { - m_SortedOffset.insert(m_pSyntax->SavePos()); - m_pSyntax->GetKeyword(); - bool bNumber; - CFX_ByteString xrefpos_str = m_pSyntax->GetNextWord(&bNumber); - if (!bNumber) - return FORMAT_ERROR; + m_LastXRefOffset = ParseStartXRef(); - m_LastXRefOffset = (FX_FILESIZE)FXSYS_atoi64(xrefpos_str.c_str()); + if (m_LastXRefOffset > 0) { if (!LoadAllCrossRefV4(m_LastXRefOffset) && !LoadAllCrossRefV5(m_LastXRefOffset)) { if (!RebuildCrossRef()) @@ -216,18 +296,40 @@ CPDF_Parser::Error CPDF_Parser::StartParse( CPDF_Reference* pMetadata = ToReference(m_pDocument->GetRoot()->GetObjectFor("Metadata")); if (pMetadata) - m_pSyntax->m_MetadataObjnum = pMetadata->GetRefObjNum(); + m_MetadataObjnum = pMetadata->GetRefObjNum(); } return SUCCESS; } + +FX_FILESIZE CPDF_Parser::ParseStartXRef() { + static constexpr char kStartXRefKeyword[] = "startxref"; + m_pSyntax->SetPos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - + strlen(kStartXRefKeyword)); + if (!m_pSyntax->BackwardsSearchToWord(kStartXRefKeyword, 4096)) + return 0; + + // Skip "startxref" keyword. + m_pSyntax->GetKeyword(); + + // Read XRef offset. + bool bNumber; + const ByteString xrefpos_str = m_pSyntax->GetNextWord(&bNumber); + if (!bNumber || xrefpos_str.IsEmpty()) + return 0; + + const FX_SAFE_FILESIZE result = FXSYS_atoi64(xrefpos_str.c_str()); + if (!result.IsValid() || result.ValueOrDie() >= GetFileAccess()->GetSize()) + return 0; + + return result.ValueOrDie(); +} + CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { ReleaseEncryptHandler(); - SetEncryptDictionary(nullptr); - - if (!m_pTrailer) + if (!GetTrailer()) return FORMAT_ERROR; - CPDF_Object* pEncryptObj = m_pTrailer->GetObjectFor("Encrypt"); + CPDF_Object* pEncryptObj = GetTrailer()->GetObjectFor("Encrypt"); if (pEncryptObj) { if (CPDF_Dictionary* pEncryptDict = pEncryptObj->AsDictionary()) { SetEncryptDictionary(pEncryptDict); @@ -239,42 +341,34 @@ CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { } if (m_pEncryptDict) { - CFX_ByteString filter = m_pEncryptDict->GetStringFor("Filter"); - std::unique_ptr pSecurityHandler; - Error err = HANDLER_ERROR; - if (filter == "Standard") { - pSecurityHandler = pdfium::MakeUnique(); - err = PASSWORD_ERROR; - } - if (!pSecurityHandler) + ByteString filter = m_pEncryptDict->GetStringFor("Filter"); + if (filter != "Standard") return HANDLER_ERROR; - if (!pSecurityHandler->OnInit(this, m_pEncryptDict)) - return err; + std::unique_ptr pSecurityHandler = + pdfium::MakeUnique(); + if (!pSecurityHandler->OnInit(m_pEncryptDict.Get(), GetIDArray(), + m_Password)) + return PASSWORD_ERROR; m_pSecurityHandler = std::move(pSecurityHandler); - std::unique_ptr pCryptoHandler( - m_pSecurityHandler->CreateCryptoHandler()); - if (!pCryptoHandler->Init(m_pEncryptDict, m_pSecurityHandler.get())) - return HANDLER_ERROR; - m_pSyntax->SetEncrypt(std::move(pCryptoHandler)); } return SUCCESS; } void CPDF_Parser::ReleaseEncryptHandler() { - m_pSyntax->m_pCryptoHandler.reset(); m_pSecurityHandler.reset(); + SetEncryptDictionary(nullptr); } FX_FILESIZE CPDF_Parser::GetObjectOffset(uint32_t objnum) const { if (!IsValidObjectNumber(objnum)) return 0; - if (GetObjectType(objnum) == 1) + if (GetObjectType(objnum) == ObjectType::kNotCompressed) return GetObjectPositionOrZero(objnum); - if (GetObjectType(objnum) == 2) { + if (GetObjectType(objnum) == ObjectType::kCompressed) { FX_FILESIZE pos = GetObjectPositionOrZero(objnum); return GetObjectPositionOrZero(pos); } @@ -290,32 +384,32 @@ bool CPDF_Parser::VerifyCrossRefV4() { if (it.second.pos == 0) continue; // Find the first non-zero position. - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(it.second.pos); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(it.second.pos); bool is_num = false; - CFX_ByteString num_str = m_pSyntax->GetNextWord(&is_num); - m_pSyntax->RestorePos(SavedPos); + ByteString num_str = m_pSyntax->GetNextWord(&is_num); + m_pSyntax->SetPos(SavedPos); if (!is_num || num_str.IsEmpty() || FXSYS_atoui(num_str.c_str()) != it.first) { // If the object number read doesn't match the one stored, // something is wrong with the cross reference table. return false; - } else { - return true; } + return true; } return true; } bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { - if (!LoadCrossRefV4(xrefpos, 0, true)) + if (!LoadCrossRefV4(xrefpos, true)) return false; - m_pTrailer = LoadTrailerV4(); - if (!m_pTrailer) + std::unique_ptr trailer = LoadTrailerV4(); + if (!trailer) return false; - int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size"); + m_TrailerData->SetMainTrailer(std::move(trailer)); + int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size"); if (xrefsize > 0 && xrefsize <= kMaxXRefSize) ShrinkObjectMap(xrefsize); @@ -324,12 +418,12 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { std::set seen_xrefpos; CrossRefList.push_back(xrefpos); - XRefStreamList.push_back(GetDirectInteger(m_pTrailer.get(), "XRefStm")); + XRefStreamList.push_back(GetDirectInteger(GetTrailer(), "XRefStm")); seen_xrefpos.insert(xrefpos); - // When |m_pTrailer| doesn't have Prev entry or Prev entry value is not + // When the trailer doesn't have Prev entry or Prev entry value is not // numerical, GetDirectInteger() returns 0. Loading will end. - xrefpos = GetDirectInteger(m_pTrailer.get(), "Prev"); + xrefpos = GetDirectInteger(GetTrailer(), "Prev"); while (xrefpos) { // Check for circular references. if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) @@ -339,7 +433,7 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { // SLOW ... CrossRefList.insert(CrossRefList.begin(), xrefpos); - LoadCrossRefV4(xrefpos, 0, true); + LoadCrossRefV4(xrefpos, true); std::unique_ptr pDict(LoadTrailerV4()); if (!pDict) @@ -350,28 +444,32 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { // SLOW ... XRefStreamList.insert(XRefStreamList.begin(), pDict->GetIntegerFor("XRefStm")); - m_Trailers.push_back(std::move(pDict)); + m_TrailerData->AppendTrailer(std::move(pDict)); } for (size_t i = 0; i < CrossRefList.size(); ++i) { - if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], false)) + if (!LoadCrossRefV4(CrossRefList[i], false)) return false; + + if (XRefStreamList[i] && !LoadCrossRefV5(&XRefStreamList[i], false)) + return false; + if (i == 0 && !VerifyCrossRefV4()) return false; } return true; } -bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, - uint32_t dwObjCount) { - if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) +bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos) { + if (!LoadCrossRefV4(xrefpos, false)) return false; - m_pTrailer = LoadTrailerV4(); - if (!m_pTrailer) + std::unique_ptr trailer = LoadTrailerV4(); + if (!trailer) return false; - int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size"); + m_TrailerData->SetMainTrailer(std::move(trailer)); + int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size"); if (xrefsize == 0) return false; @@ -380,10 +478,10 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, std::set seen_xrefpos; CrossRefList.push_back(xrefpos); - XRefStreamList.push_back(GetDirectInteger(m_pTrailer.get(), "XRefStm")); + XRefStreamList.push_back(GetDirectInteger(GetTrailer(), "XRefStm")); seen_xrefpos.insert(xrefpos); - xrefpos = GetDirectInteger(m_pTrailer.get(), "Prev"); + xrefpos = GetDirectInteger(GetTrailer(), "Prev"); while (xrefpos) { // Check for circular references. if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) @@ -393,7 +491,7 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, // SLOW ... CrossRefList.insert(CrossRefList.begin(), xrefpos); - LoadCrossRefV4(xrefpos, 0, true); + LoadCrossRefV4(xrefpos, true); std::unique_ptr pDict(LoadTrailerV4()); if (!pDict) @@ -404,95 +502,120 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, // SLOW ... XRefStreamList.insert(XRefStreamList.begin(), pDict->GetIntegerFor("XRefStm")); - m_Trailers.push_back(std::move(pDict)); + m_TrailerData->AppendTrailer(std::move(pDict)); } for (size_t i = 1; i < CrossRefList.size(); ++i) { - if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], false)) + if (!LoadCrossRefV4(CrossRefList[i], false)) + return false; + + if (XRefStreamList[i] && !LoadCrossRefV5(&XRefStreamList[i], false)) return false; } return true; } -bool CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, - uint32_t dwObjCount) { - FX_FILESIZE dwStartPos = pos - m_pSyntax->m_HeaderOffset; +bool CPDF_Parser::ParseAndAppendCrossRefSubsectionData( + uint32_t start_objnum, + uint32_t count, + std::vector* out_objects) { + // Each entry shall be exactly 20 byte. + // A sample entry looks like: + // "0000000000 00007 f\r\n" + static constexpr int32_t kEntryConstSize = 20; + + if (!out_objects) { + FX_SAFE_FILESIZE pos = count; + pos *= kEntryConstSize; + pos += m_pSyntax->GetPos(); + if (!pos.IsValid()) + return false; + m_pSyntax->SetPos(pos.ValueOrDie()); + return true; + } + const size_t start_obj_index = out_objects->size(); + FX_SAFE_SIZE_T new_size = start_obj_index; + new_size += count; + if (!new_size.IsValid()) + return false; - m_pSyntax->RestorePos(dwStartPos); - m_SortedOffset.insert(pos); + if (new_size.ValueOrDie() > kMaxXRefSize) + return false; + + const size_t max_entries_in_file = + m_pSyntax->GetFileAccess()->GetSize() / kEntryConstSize; + if (new_size.ValueOrDie() > max_entries_in_file) + return false; - uint32_t start_objnum = 0; - uint32_t count = dwObjCount; - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); + out_objects->resize(new_size.ValueOrDie()); - const int32_t recordsize = 20; - std::vector buf(1024 * recordsize + 1); - buf[1024 * recordsize] = '\0'; + std::vector buf(1024 * kEntryConstSize + 1); + buf.back() = '\0'; int32_t nBlocks = count / 1024 + 1; for (int32_t block = 0; block < nBlocks; block++) { int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; - uint32_t dwReadSize = block_size * recordsize; - if ((FX_FILESIZE)(dwStartPos + dwReadSize) > m_pSyntax->m_FileLen) - return false; - if (!m_pSyntax->ReadBlock(reinterpret_cast(buf.data()), - dwReadSize)) { + block_size * kEntryConstSize)) { return false; } for (int32_t i = 0; i < block_size; i++) { - uint32_t objnum = start_objnum + block * 1024 + i; - char* pEntry = &buf[i * recordsize]; + CrossRefObjData& obj_data = + (*out_objects)[start_obj_index + block * 1024 + i]; + + const uint32_t objnum = start_objnum + block * 1024 + i; + + obj_data.obj_num = objnum; + + ObjectInfo& info = obj_data.info; + + char* pEntry = &buf[i * kEntryConstSize]; if (pEntry[17] == 'f') { - m_ObjectInfo[objnum].pos = 0; - m_ObjectInfo[objnum].type = 0; + info.pos = 0; + info.type = ObjectType::kFree; } else { - int32_t offset = FXSYS_atoi(pEntry); - if (offset == 0) { + const FX_SAFE_FILESIZE offset = FXSYS_atoi64(pEntry); + if (!offset.IsValid()) + return false; + + if (offset.ValueOrDie() == 0) { for (int32_t c = 0; c < 10; c++) { if (!std::isdigit(pEntry[c])) return false; } } - m_ObjectInfo[objnum].pos = offset; - int32_t version = FXSYS_atoi(pEntry + 11); - if (version >= 1) - m_bVersionUpdated = true; + info.pos = offset.ValueOrDie(); - m_ObjectInfo[objnum].gennum = version; - if (m_ObjectInfo[objnum].pos < m_pSyntax->m_FileLen) - m_SortedOffset.insert(m_ObjectInfo[objnum].pos); - - m_ObjectInfo[objnum].type = 1; + // TODO(art-snake): The info.gennum is uint16_t, but version may be + // greated than max. Needs solve this issue. + const int32_t version = FXSYS_atoi(pEntry + 11); + info.gennum = version; + info.type = ObjectType::kNotCompressed; } } } - m_pSyntax->RestorePos(SavedPos + count * recordsize); return true; } -bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, - FX_FILESIZE streampos, - bool bSkip) { - m_pSyntax->RestorePos(pos); +bool CPDF_Parser::ParseCrossRefV4(std::vector* out_objects) { + if (out_objects) + out_objects->clear(); + if (m_pSyntax->GetKeyword() != "xref") return false; - - m_SortedOffset.insert(pos); - if (streampos) - m_SortedOffset.insert(streampos); - + std::vector result_objects; while (1) { - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); + FX_FILESIZE SavedPos = m_pSyntax->GetPos(); bool bIsNumber; - CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); - if (word.IsEmpty()) + ByteString word = m_pSyntax->GetNextWord(&bIsNumber); + if (word.IsEmpty()) { return false; + } if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); + m_pSyntax->SetPos(SavedPos); break; } @@ -502,52 +625,35 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, uint32_t count = m_pSyntax->GetDirectNum(); m_pSyntax->ToNextWord(); - SavedPos = m_pSyntax->SavePos(); - const int32_t recordsize = 20; - - m_dwXrefStartObjNum = start_objnum; - if (!bSkip) { - std::vector buf(1024 * recordsize + 1); - buf[1024 * recordsize] = '\0'; - - int32_t nBlocks = count / 1024 + 1; - for (int32_t block = 0; block < nBlocks; block++) { - int32_t block_size = block == nBlocks - 1 ? count % 1024 : 1024; - m_pSyntax->ReadBlock(reinterpret_cast(buf.data()), - block_size * recordsize); - - for (int32_t i = 0; i < block_size; i++) { - uint32_t objnum = start_objnum + block * 1024 + i; - char* pEntry = &buf[i * recordsize]; - if (pEntry[17] == 'f') { - m_ObjectInfo[objnum].pos = 0; - m_ObjectInfo[objnum].type = 0; - } else { - FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); - if (offset == 0) { - for (int32_t c = 0; c < 10; c++) { - if (!std::isdigit(pEntry[c])) - return false; - } - } + SavedPos = m_pSyntax->GetPos(); - m_ObjectInfo[objnum].pos = offset; - int32_t version = FXSYS_atoi(pEntry + 11); - if (version >= 1) - m_bVersionUpdated = true; + if (!ParseAndAppendCrossRefSubsectionData( + start_objnum, count, out_objects ? &result_objects : nullptr)) { + return false; + } + } + if (out_objects) + *out_objects = std::move(result_objects); + return true; +} - m_ObjectInfo[objnum].gennum = version; - if (m_ObjectInfo[objnum].pos < m_pSyntax->m_FileLen) - m_SortedOffset.insert(m_ObjectInfo[objnum].pos); +bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, + bool bSkip) { + m_pSyntax->SetPos(pos); + std::vector objects; + if (!ParseCrossRefV4(bSkip ? nullptr : &objects)) + return false; - m_ObjectInfo[objnum].type = 1; - } - } - } - } - m_pSyntax->RestorePos(SavedPos + count * recordsize); + MergeCrossRefObjectsData(objects); + + return true; +} + +void CPDF_Parser::MergeCrossRefObjectsData( + const std::vector& objects) { + for (const auto& obj : objects) { + m_ObjectInfo[obj.obj_num] = obj.info; } - return !streampos || LoadCrossRefV5(&streampos, false); } bool CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { @@ -571,8 +677,7 @@ bool CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { bool CPDF_Parser::RebuildCrossRef() { m_ObjectInfo.clear(); - m_SortedOffset.clear(); - m_pTrailer.reset(); + m_TrailerData->Clear(); ParserState state = ParserState::kDefault; int32_t inside_index = 0; @@ -594,7 +699,7 @@ bool CPDF_Parser::RebuildCrossRef() { bool bOverFlow = false; uint32_t size = std::min((uint32_t)(m_pSyntax->m_FileLen - pos), kBufferSize); - if (!m_pSyntax->m_pFileAccess->ReadBlock(buffer.data(), pos, size)) + if (!m_pSyntax->GetFileAccess()->ReadBlock(buffer.data(), pos, size)) break; for (uint32_t i = 0; i < size; i++) { @@ -627,7 +732,7 @@ bool CPDF_Parser::RebuildCrossRef() { if (std::isdigit(byte)) { start_pos = pos + i; state = ParserState::kObjNum; - objnum = FXSYS_toDecimalDigit(static_cast(byte)); + objnum = FXSYS_DecimalCharToInt(static_cast(byte)); } else if (byte == 't') { state = ParserState::kTrailer; inside_index = 1; @@ -642,8 +747,8 @@ bool CPDF_Parser::RebuildCrossRef() { case ParserState::kObjNum: if (std::isdigit(byte)) { - objnum = - objnum * 10 + FXSYS_toDecimalDigit(static_cast(byte)); + objnum = objnum * 10 + + FXSYS_DecimalCharToInt(static_cast(byte)); } else if (PDFCharIsWhitespace(byte)) { state = ParserState::kPostObjNum; } else { @@ -657,7 +762,7 @@ bool CPDF_Parser::RebuildCrossRef() { if (std::isdigit(byte)) { start_pos1 = pos + i; state = ParserState::kGenNum; - gennum = FXSYS_toDecimalDigit(static_cast(byte)); + gennum = FXSYS_DecimalCharToInt(static_cast(byte)); } else if (byte == 't') { state = ParserState::kTrailer; inside_index = 1; @@ -669,8 +774,8 @@ bool CPDF_Parser::RebuildCrossRef() { case ParserState::kGenNum: if (std::isdigit(byte)) { - gennum = - gennum * 10 + FXSYS_toDecimalDigit(static_cast(byte)); + gennum = gennum * 10 + + FXSYS_DecimalCharToInt(static_cast(byte)); } else if (PDFCharIsWhitespace(byte)) { state = ParserState::kPostGenNum; } else { @@ -685,7 +790,7 @@ bool CPDF_Parser::RebuildCrossRef() { inside_index = 1; } else if (std::isdigit(byte)) { objnum = gennum; - gennum = FXSYS_toDecimalDigit(static_cast(byte)); + gennum = FXSYS_DecimalCharToInt(static_cast(byte)); start_pos = start_pos1; start_pos1 = pos + i; state = ParserState::kGenNum; @@ -719,12 +824,11 @@ bool CPDF_Parser::RebuildCrossRef() { case 3: if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { FX_FILESIZE obj_pos = start_pos - m_pSyntax->m_HeaderOffset; - m_SortedOffset.insert(obj_pos); last_obj = start_pos; FX_FILESIZE obj_end = 0; std::unique_ptr pObject = - ParseIndirectObjectAtByStrict(m_pDocument, obj_pos, objnum, - &obj_end); + ParseIndirectObjectAtByStrict(m_pDocument.Get(), obj_pos, + objnum, &obj_end); if (CPDF_Stream* pStream = ToStream(pObject.get())) { if (CPDF_Dictionary* pDict = pStream->GetDict()) { if ((pDict->KeyExist("Type")) && @@ -733,14 +837,15 @@ bool CPDF_Parser::RebuildCrossRef() { CPDF_Object* pRoot = pDict->GetObjectFor("Root"); if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetObjectFor("Pages")) { - m_pTrailer = ToDictionary(pDict->Clone()); + m_TrailerData->SetMainTrailer( + ToDictionary(pDict->Clone())); } } } } FX_FILESIZE offset = 0; - m_pSyntax->RestorePos(obj_pos); + m_pSyntax->SetPos(obj_pos); offset = m_pSyntax->FindTag("obj", 0); if (offset == -1) offset = 0; @@ -758,15 +863,12 @@ bool CPDF_Parser::RebuildCrossRef() { if (!m_ObjectInfo.empty() && IsValidObjectNumber(objnum) && m_ObjectInfo[objnum].pos) { if (pObject) { - uint32_t oldgen = GetObjectGenNum(objnum); m_ObjectInfo[objnum].pos = obj_pos; m_ObjectInfo[objnum].gennum = gennum; - if (oldgen != gennum) - m_bVersionUpdated = true; } } else { m_ObjectInfo[objnum].pos = obj_pos; - m_ObjectInfo[objnum].type = 1; + m_ObjectInfo[objnum].type = ObjectType::kNotCompressed; m_ObjectInfo[objnum].gennum = gennum; } } @@ -780,16 +882,16 @@ bool CPDF_Parser::RebuildCrossRef() { if (inside_index == 7) { if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { last_trailer = pos + i - 7; - m_pSyntax->RestorePos(pos + i - m_pSyntax->m_HeaderOffset); + m_pSyntax->SetPos(pos + i - m_pSyntax->m_HeaderOffset); std::unique_ptr pObj = - m_pSyntax->GetObject(m_pDocument, 0, 0, true); + m_pSyntax->GetObjectBody(m_pDocument.Get()); if (pObj) { if (pObj->IsDictionary() || pObj->AsStream()) { CPDF_Stream* pStream = pObj->AsStream(); if (CPDF_Dictionary* pTrailer = pStream ? pStream->GetDict() : pObj->AsDictionary()) { - if (m_pTrailer) { + if (GetTrailer()) { CPDF_Object* pRoot = pTrailer->GetObjectFor("Root"); CPDF_Reference* pRef = ToReference(pRoot); if (!pRoot || @@ -797,36 +899,33 @@ bool CPDF_Parser::RebuildCrossRef() { m_ObjectInfo[pRef->GetRefObjNum()].pos != 0)) { auto it = pTrailer->begin(); while (it != pTrailer->end()) { - const CFX_ByteString& key = it->first; + const ByteString& key = it->first; CPDF_Object* pElement = it->second.get(); ++it; uint32_t dwObjNum = pElement ? pElement->GetObjNum() : 0; if (dwObjNum) { - m_pTrailer->SetNewFor( - key, m_pDocument, dwObjNum); + GetTrailer()->SetNewFor( + key, m_pDocument.Get(), dwObjNum); } else { - m_pTrailer->SetFor(key, pElement->Clone()); + GetTrailer()->SetFor(key, pElement->Clone()); } } } } else { - if (pObj->IsStream()) { - m_pTrailer = ToDictionary(pTrailer->Clone()); - } else { - m_pTrailer = ToDictionary(std::move(pObj)); - } + m_TrailerData->SetMainTrailer( + ToDictionary(pObj->IsStream() ? pTrailer->Clone() + : std::move(pObj))); - FX_FILESIZE dwSavePos = m_pSyntax->SavePos(); - CFX_ByteString strWord = m_pSyntax->GetKeyword(); + FX_FILESIZE dwSavePos = m_pSyntax->GetPos(); + ByteString strWord = m_pSyntax->GetKeyword(); if (!strWord.Compare("startxref")) { bool bNumber; - CFX_ByteString bsOffset = - m_pSyntax->GetNextWord(&bNumber); + ByteString bsOffset = m_pSyntax->GetNextWord(&bNumber); if (bNumber) m_LastXRefOffset = FXSYS_atoi(bsOffset.c_str()); } - m_pSyntax->RestorePos(dwSavePos); + m_pSyntax->SetPos(dwSavePos); } } } @@ -918,23 +1017,22 @@ bool CPDF_Parser::RebuildCrossRef() { else if (last_trailer == -1 || last_xref < last_obj) last_trailer = m_pSyntax->m_FileLen; - m_SortedOffset.insert(last_trailer - m_pSyntax->m_HeaderOffset); - return m_pTrailer && !m_ObjectInfo.empty(); + return GetTrailer() && !m_ObjectInfo.empty(); } bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { std::unique_ptr pObject( - ParseIndirectObjectAt(m_pDocument, *pos, 0)); + ParseIndirectObjectAt(m_pDocument.Get(), *pos, 0)); if (!pObject) return false; - uint32_t objnum = pObject->m_ObjNum; + uint32_t objnum = pObject->GetObjNum(); if (!objnum) return false; CPDF_Object* pUnownedObject = pObject.get(); if (m_pDocument) { - CPDF_Dictionary* pRootDict = m_pDocument->GetRoot(); + const CPDF_Dictionary* pRootDict = m_pDocument->GetRoot(); if (pRootDict && pRootDict->GetObjNum() == objnum) return false; if (!m_pDocument->ReplaceIndirectObjectIfHigherGeneration( @@ -955,12 +1053,12 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { std::unique_ptr pNewTrailer = ToDictionary(pDict->Clone()); if (bMainXRef) { - m_pTrailer = std::move(pNewTrailer); + m_TrailerData->SetMainTrailer(std::move(pNewTrailer)); ShrinkObjectMap(size); for (auto& it : m_ObjectInfo) - it.second.type = 0; + it.second.type = ObjectType::kFree; } else { - m_Trailers.push_back(std::move(pNewTrailer)); + m_TrailerData->AppendTrailer(std::move(pNewTrailer)); } std::vector> arrIndex; @@ -997,18 +1095,17 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { return false; uint32_t totalWidth = dwAccWidth.ValueOrDie(); - CPDF_StreamAcc acc; - acc.LoadAllData(pStream); + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllDataFiltered(); - const uint8_t* pData = acc.GetData(); - uint32_t dwTotalSize = acc.GetSize(); + const uint8_t* pData = pAcc->GetData(); + uint32_t dwTotalSize = pAcc->GetSize(); uint32_t segindex = 0; for (uint32_t i = 0; i < arrIndex.size(); i++) { int32_t startnum = arrIndex[i].first; if (startnum < 0) continue; - m_dwXrefStartObjNum = pdfium::base::checked_cast(startnum); uint32_t count = pdfium::base::checked_cast(arrIndex[i].second); FX_SAFE_UINT32 dwCaculatedSize = segindex; dwCaculatedSize += count; @@ -1026,35 +1123,41 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { continue; for (uint32_t j = 0; j < count; j++) { - int32_t type = 1; + ObjectType type = ObjectType::kNotCompressed; const uint8_t* entrystart = segstart + j * totalWidth; - if (WidthArray[0]) - type = GetVarInt(entrystart, WidthArray[0]); + if (WidthArray[0]) { + const int cross_ref_stream_obj_type = + GetVarInt(entrystart, WidthArray[0]); + type = GetObjectTypeFromCrossRefStreamType(cross_ref_stream_obj_type); + } - if (GetObjectType(startnum + j) == 255) { + if (GetObjectType(startnum + j) == ObjectType::kNull) { FX_FILESIZE offset = GetVarInt(entrystart + WidthArray[0], WidthArray[1]); m_ObjectInfo[startnum + j].pos = offset; - m_SortedOffset.insert(offset); continue; } - if (GetObjectType(startnum + j)) + if (GetObjectType(startnum + j) != ObjectType::kFree) continue; - m_ObjectInfo[startnum + j].type = type; - if (type == 0) { - m_ObjectInfo[startnum + j].pos = 0; + ObjectInfo& info = m_ObjectInfo[startnum + j]; + + info.type = type; + if (type == ObjectType::kFree) { + info.pos = 0; } else { - FX_FILESIZE offset = + const FX_FILESIZE entry_value = GetVarInt(entrystart + WidthArray[0], WidthArray[1]); - m_ObjectInfo[startnum + j].pos = offset; - if (type == 1) { - m_SortedOffset.insert(offset); + if (type == ObjectType::kNotCompressed) { + const auto object_offset = entry_value; + info.pos = object_offset; } else { - if (offset < 0 || !IsValidObjectNumber(offset)) + const auto archive_obj_num = entry_value; + info.archive_obj_num = archive_obj_num; + if (archive_obj_num < 0 || !IsValidObjectNumber(archive_obj_num)) return false; - m_ObjectInfo[offset].type = 255; + m_ObjectInfo[archive_obj_num].type = ObjectType::kNull; } } } @@ -1063,35 +1166,24 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { return true; } -CPDF_Array* CPDF_Parser::GetIDArray() { - if (!m_pTrailer) - return nullptr; - - CPDF_Object* pID = m_pTrailer->GetObjectFor("ID"); - if (!pID) - return nullptr; - - CPDF_Reference* pRef = pID->AsReference(); - if (!pRef) - return ToArray(pID); +const CPDF_Array* CPDF_Parser::GetIDArray() const { + return GetTrailer() ? GetTrailer()->GetArrayFor("ID") : nullptr; +} - std::unique_ptr pNewObj = - ParseIndirectObject(nullptr, pRef->GetRefObjNum()); - pID = pNewObj.get(); - m_pTrailer->SetFor("ID", std::move(pNewObj)); - return ToArray(pID); +CPDF_Dictionary* CPDF_Parser::GetTrailer() const { + return m_TrailerData->GetMainTrailer(); } -uint32_t CPDF_Parser::GetRootObjNum() { - CPDF_Reference* pRef = - ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Root") : nullptr); - return pRef ? pRef->GetRefObjNum() : 0; +std::unique_ptr CPDF_Parser::GetCombinedTrailer() const { + return m_TrailerData->GetCombinedTrailer(); } uint32_t CPDF_Parser::GetInfoObjNum() { - CPDF_Reference* pRef = - ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Info") : nullptr); - return pRef ? pRef->GetRefObjNum() : 0; + return m_TrailerData->GetInfoObjNum(); +} + +uint32_t CPDF_Parser::GetRootObjNum() { + return m_TrailerData->GetRootObjNum(); } std::unique_ptr CPDF_Parser::ParseIndirectObject( @@ -1105,21 +1197,24 @@ std::unique_ptr CPDF_Parser::ParseIndirectObject( return nullptr; pdfium::ScopedSetInsertion local_insert(&m_ParsingObjNums, objnum); - if (GetObjectType(objnum) == 1 || GetObjectType(objnum) == 255) { + if (GetObjectType(objnum) == ObjectType::kNotCompressed || + GetObjectType(objnum) == ObjectType::kNull) { FX_FILESIZE pos = m_ObjectInfo[objnum].pos; if (pos <= 0) return nullptr; return ParseIndirectObjectAt(pObjList, pos, objnum); } - if (GetObjectType(objnum) != 2) + if (GetObjectType(objnum) != ObjectType::kCompressed) return nullptr; - CPDF_StreamAcc* pObjStream = GetObjectStream(m_ObjectInfo[objnum].pos); + RetainPtr pObjStream = + GetObjectStream(m_ObjectInfo[objnum].pos); if (!pObjStream) return nullptr; - CFX_RetainPtr file = IFX_MemoryStream::Create( - (uint8_t*)pObjStream->GetData(), (size_t)pObjStream->GetSize(), false); + auto file = pdfium::MakeRetain( + const_cast(pObjStream->GetData()), + static_cast(pObjStream->GetSize()), false); CPDF_SyntaxParser syntax; syntax.InitParser(file, 0); const int32_t offset = GetStreamFirst(pObjStream); @@ -1137,14 +1232,14 @@ std::unique_ptr CPDF_Parser::ParseIndirectObject( if (it == m_ObjCache[pObjStream].end()) return nullptr; - syntax.RestorePos(offset + it->second); - return syntax.GetObject(pObjList, 0, 0, true); + syntax.SetPos(offset + it->second); + return syntax.GetObjectBody(pObjList); } -CPDF_StreamAcc* CPDF_Parser::GetObjectStream(uint32_t objnum) { +RetainPtr CPDF_Parser::GetObjectStream(uint32_t objnum) { auto it = m_ObjectStreamMap.find(objnum); if (it != m_ObjectStreamMap.end()) - return it->second.get(); + return it->second; if (!m_pDocument) return nullptr; @@ -1154,197 +1249,45 @@ CPDF_StreamAcc* CPDF_Parser::GetObjectStream(uint32_t objnum) { if (!pStream) return nullptr; - CPDF_StreamAcc* pStreamAcc = new CPDF_StreamAcc; - pStreamAcc->LoadAllData(pStream); - m_ObjectStreamMap[objnum].reset(pStreamAcc); + auto pStreamAcc = pdfium::MakeRetain(pStream); + pStreamAcc->LoadAllDataFiltered(); + m_ObjectStreamMap[objnum] = pStreamAcc; return pStreamAcc; } -FX_FILESIZE CPDF_Parser::GetObjectSize(uint32_t objnum) const { - if (!IsValidObjectNumber(objnum)) - return 0; - - if (GetObjectType(objnum) == 2) - objnum = GetObjectPositionOrZero(objnum); - - if (GetObjectType(objnum) != 1 && GetObjectType(objnum) != 255) - return 0; - - FX_FILESIZE offset = GetObjectPositionOrZero(objnum); - if (offset == 0) - return 0; - - auto it = m_SortedOffset.find(offset); - if (it == m_SortedOffset.end() || ++it == m_SortedOffset.end()) - return 0; - - return *it - offset; -} - -void CPDF_Parser::GetIndirectBinary(uint32_t objnum, - uint8_t*& pBuffer, - uint32_t& size) { - pBuffer = nullptr; - size = 0; - if (!IsValidObjectNumber(objnum)) - return; - - if (GetObjectType(objnum) == 2) { - CPDF_StreamAcc* pObjStream = GetObjectStream(m_ObjectInfo[objnum].pos); - if (!pObjStream) - return; - - int32_t offset = GetStreamFirst(pObjStream); - const uint8_t* pData = pObjStream->GetData(); - uint32_t totalsize = pObjStream->GetSize(); - CFX_RetainPtr file = - IFX_MemoryStream::Create((uint8_t*)pData, (size_t)totalsize, false); - CPDF_SyntaxParser syntax; - syntax.InitParser(file, 0); - - for (int i = GetStreamNCount(pObjStream); i > 0; --i) { - uint32_t thisnum = syntax.GetDirectNum(); - uint32_t thisoff = syntax.GetDirectNum(); - if (thisnum != objnum) - continue; - - if (i == 1) { - size = totalsize - (thisoff + offset); - } else { - syntax.GetDirectNum(); // Skip nextnum. - uint32_t nextoff = syntax.GetDirectNum(); - size = nextoff - thisoff; - } - - pBuffer = FX_Alloc(uint8_t, size); - FXSYS_memcpy(pBuffer, pData + thisoff + offset, size); - return; - } - return; - } - - if (GetObjectType(objnum) != 1) - return; - - FX_FILESIZE pos = m_ObjectInfo[objnum].pos; - if (pos == 0) - return; - - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(pos); - - bool bIsNumber; - CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); - return; - } - - uint32_t parser_objnum = FXSYS_atoui(word.c_str()); - if (parser_objnum && parser_objnum != objnum) { - m_pSyntax->RestorePos(SavedPos); - return; - } - - word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); - return; - } - - if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); - return; - } - - auto it = m_SortedOffset.find(pos); - if (it == m_SortedOffset.end() || ++it == m_SortedOffset.end()) { - m_pSyntax->RestorePos(SavedPos); - return; - } - - FX_FILESIZE nextoff = *it; - bool bNextOffValid = false; - if (nextoff != pos) { - m_pSyntax->RestorePos(nextoff); - word = m_pSyntax->GetNextWord(&bIsNumber); - if (word == "xref") { - bNextOffValid = true; - } else if (bIsNumber) { - word = m_pSyntax->GetNextWord(&bIsNumber); - if (bIsNumber && m_pSyntax->GetKeyword() == "obj") { - bNextOffValid = true; - } - } - } - - if (!bNextOffValid) { - m_pSyntax->RestorePos(pos); - while (1) { - if (m_pSyntax->GetKeyword() == "endobj") - break; - - if (m_pSyntax->SavePos() == m_pSyntax->m_FileLen) - break; - } - nextoff = m_pSyntax->SavePos(); - } - - size = (uint32_t)(nextoff - pos); - pBuffer = FX_Alloc(uint8_t, size); - m_pSyntax->RestorePos(pos); - m_pSyntax->ReadBlock(pBuffer, size); - m_pSyntax->RestorePos(SavedPos); -} - std::unique_ptr CPDF_Parser::ParseIndirectObjectAt( CPDF_IndirectObjectHolder* pObjList, FX_FILESIZE pos, uint32_t objnum) { - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(pos); - bool bIsNumber; - CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } + return ParseIndirectObjectAtInternal( + pObjList, pos, objnum, CPDF_SyntaxParser::ParseType::kLoose, nullptr); +} - FX_FILESIZE objOffset = m_pSyntax->SavePos(); - objOffset -= word.GetLength(); - uint32_t parser_objnum = FXSYS_atoui(word.c_str()); - if (objnum && parser_objnum != objnum) { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } +std::unique_ptr CPDF_Parser::ParseIndirectObjectAtInternal( + CPDF_IndirectObjectHolder* pObjList, + FX_FILESIZE pos, + uint32_t objnum, + CPDF_SyntaxParser::ParseType parse_type, + FX_FILESIZE* pResultPos) { + const FX_FILESIZE saved_pos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(pos); + auto result = m_pSyntax->GetIndirectObject(pObjList, parse_type); - word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } + if (pResultPos) + *pResultPos = m_pSyntax->GetPos(); + m_pSyntax->SetPos(saved_pos); - uint32_t parser_gennum = FXSYS_atoui(word.c_str()); - if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); + if (result && objnum && result->GetObjNum() != objnum) return nullptr; - } - - std::unique_ptr pObj = - m_pSyntax->GetObject(pObjList, objnum, parser_gennum, true); - m_pSyntax->SavePos(); - CFX_ByteString bsWord = m_pSyntax->GetKeyword(); - if (bsWord == "endobj") - m_pSyntax->SavePos(); + const bool should_decrypt = m_pSecurityHandler && + m_pSecurityHandler->GetCryptoHandler() && + objnum != m_MetadataObjnum; + if (should_decrypt) + result = m_pSecurityHandler->GetCryptoHandler()->DecryptObjectTree( + std::move(result)); - m_pSyntax->RestorePos(SavedPos); - if (pObj) { - if (!objnum) - pObj->m_ObjNum = parser_objnum; - pObj->m_GenNum = parser_gennum; - } - return pObj; + return result; } std::unique_ptr CPDF_Parser::ParseIndirectObjectAtByStrict( @@ -1352,42 +1295,8 @@ std::unique_ptr CPDF_Parser::ParseIndirectObjectAtByStrict( FX_FILESIZE pos, uint32_t objnum, FX_FILESIZE* pResultPos) { - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - m_pSyntax->RestorePos(pos); - - bool bIsNumber; - CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } - - uint32_t parser_objnum = FXSYS_atoui(word.c_str()); - if (objnum && parser_objnum != objnum) { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } - - word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } - - uint32_t gennum = FXSYS_atoui(word.c_str()); - if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); - return nullptr; - } - - std::unique_ptr pObj = - m_pSyntax->GetObjectForStrict(pObjList, objnum, gennum); - - if (pResultPos) - *pResultPos = m_pSyntax->m_Pos; - - m_pSyntax->RestorePos(SavedPos); - return pObj; + return ParseIndirectObjectAtInternal( + pObjList, pos, objnum, CPDF_SyntaxParser::ParseType::kStrict, pResultPos); } uint32_t CPDF_Parser::GetFirstPageNo() const { @@ -1398,7 +1307,7 @@ std::unique_ptr CPDF_Parser::LoadTrailerV4() { if (m_pSyntax->GetKeyword() != "trailer") return nullptr; - return ToDictionary(m_pSyntax->GetObject(m_pDocument, 0, 0, true)); + return ToDictionary(m_pSyntax->GetObjectBody(m_pDocument.Get())); } uint32_t CPDF_Parser::GetPermissions() const { @@ -1414,61 +1323,31 @@ uint32_t CPDF_Parser::GetPermissions() const { return dwPermission; } -bool CPDF_Parser::IsLinearizedFile( - const CFX_RetainPtr& pFileAccess, - uint32_t offset) { - m_pSyntax->InitParser(pFileAccess, offset); - m_pSyntax->RestorePos(m_pSyntax->m_HeaderOffset + 9); - - FX_FILESIZE SavedPos = m_pSyntax->SavePos(); - bool bIsNumber; - CFX_ByteString word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) - return false; - - uint32_t objnum = FXSYS_atoui(word.c_str()); - word = m_pSyntax->GetNextWord(&bIsNumber); - if (!bIsNumber) - return false; - - uint32_t gennum = FXSYS_atoui(word.c_str()); - if (m_pSyntax->GetKeyword() != "obj") { - m_pSyntax->RestorePos(SavedPos); - return false; - } - - m_pLinearized = CPDF_LinearizedHeader::CreateForObject( - m_pSyntax->GetObject(nullptr, objnum, gennum, true)); - if (!m_pLinearized) - return false; - - m_LastXRefOffset = m_pLinearized->GetLastXRefOffset(); - // Move parser onto first page xref table start. - m_pSyntax->GetNextWord(nullptr); - return true; +std::unique_ptr CPDF_Parser::ParseLinearizedHeader() { + return CPDF_LinearizedHeader::Parse(m_pSyntax.get()); } CPDF_Parser::Error CPDF_Parser::StartLinearizedParse( - const CFX_RetainPtr& pFileAccess, + const RetainPtr& pFileAccess, CPDF_Document* pDocument) { ASSERT(!m_bHasParsed); m_bXRefStream = false; m_LastXRefOffset = 0; - int32_t offset = GetHeaderOffset(pFileAccess); - if (offset == -1) + if (!InitSyntaxParser(pFileAccess)) return FORMAT_ERROR; - if (!IsLinearizedFile(pFileAccess, offset)) { - m_pSyntax->m_pFileAccess = nullptr; - return StartParse(pFileAccess, std::move(pDocument)); - } + m_pLinearized = ParseLinearizedHeader(); + if (!m_pLinearized) + return StartParseInternal(std::move(pDocument)); + m_bHasParsed = true; m_pDocument = pDocument; - FX_FILESIZE dwFirstXRefOffset = m_pSyntax->SavePos(); + m_LastXRefOffset = m_pLinearized->GetLastXRefOffset(); + FX_FILESIZE dwFirstXRefOffset = m_LastXRefOffset; bool bXRefRebuilt = false; - bool bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, false); + bool bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, false); if (!bLoadV4 && !LoadCrossRefV5(&dwFirstXRefOffset, true)) { if (!RebuildCrossRef()) return FORMAT_ERROR; @@ -1476,13 +1355,13 @@ CPDF_Parser::Error CPDF_Parser::StartLinearizedParse( bXRefRebuilt = true; m_LastXRefOffset = 0; } - if (bLoadV4) { - m_pTrailer = LoadTrailerV4(); - if (!m_pTrailer) + std::unique_ptr trailer = LoadTrailerV4(); + if (!trailer) return SUCCESS; - int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size"); + m_TrailerData->SetMainTrailer(std::move(trailer)); + int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size"); if (xrefsize > 0) ShrinkObjectMap(xrefsize); } @@ -1522,7 +1401,7 @@ CPDF_Parser::Error CPDF_Parser::StartLinearizedParse( if (m_pSecurityHandler && m_pSecurityHandler->IsMetadataEncrypted()) { if (CPDF_Reference* pMetadata = ToReference(m_pDocument->GetRoot()->GetObjectFor("Metadata"))) - m_pSyntax->m_MetadataObjnum = pMetadata->GetRefObjNum(); + m_MetadataObjnum = pMetadata->GetRefObjNum(); } return SUCCESS; } @@ -1547,33 +1426,37 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) { } CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { - uint32_t dwSaveMetadataObjnum = m_pSyntax->m_MetadataObjnum; - m_pSyntax->m_MetadataObjnum = 0; - m_pTrailer.reset(); - m_pSyntax->RestorePos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset); - - uint8_t ch = 0; - uint32_t dwCount = 0; - m_pSyntax->GetNextChar(ch); - while (PDFCharIsWhitespace(ch)) { - ++dwCount; - if (m_pSyntax->m_FileLen <= - (FX_FILESIZE)(m_pSyntax->SavePos() + m_pSyntax->m_HeaderOffset)) { - break; - } - m_pSyntax->GetNextChar(ch); - } - m_LastXRefOffset += dwCount; + const FX_SAFE_FILESIZE main_xref_offset = GetTrailer()->GetIntegerFor("Prev"); + if (!main_xref_offset.IsValid()) + return FORMAT_ERROR; + + if (main_xref_offset.ValueOrDie() == 0) + return SUCCESS; + + const AutoRestorer save_metadata_objnum(&m_MetadataObjnum); + m_MetadataObjnum = 0; m_ObjectStreamMap.clear(); m_ObjCache.clear(); - if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && - !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { + if (!LoadLinearizedAllCrossRefV4(main_xref_offset.ValueOrDie()) && + !LoadLinearizedAllCrossRefV5(main_xref_offset.ValueOrDie())) { m_LastXRefOffset = 0; - m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; return FORMAT_ERROR; } - m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; return SUCCESS; } + +CPDF_Parser::ObjectType CPDF_Parser::GetObjectTypeFromCrossRefStreamType( + int cross_ref_stream_type) const { + switch (cross_ref_stream_type) { + case 0: + return CPDF_Parser::ObjectType::kFree; + case 1: + return CPDF_Parser::ObjectType::kNotCompressed; + case 2: + return CPDF_Parser::ObjectType::kCompressed; + default: + return CPDF_Parser::ObjectType::kNull; + } +} diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h index f8ff7a17ec0394c37e53d27653497e374197dfbb..45b8cb9f2e357ee84e53487b162e974afe02ecd6 100644 --- a/core/fpdfapi/parser/cpdf_parser.h +++ b/core/fpdfapi/parser/cpdf_parser.h @@ -7,12 +7,17 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_PARSER_H_ #define CORE_FPDFAPI_PARSER_CPDF_PARSER_H_ +#include #include #include #include #include -#include "core/fxcrt/fx_basic.h" +#include "core/fpdfapi/parser/cpdf_syntax_parser.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Array; class CPDF_CryptoHandler; @@ -40,25 +45,33 @@ class CPDF_Parser { // are higher, but this may be large enough in practice. static const uint32_t kMaxObjectNumber = 1048576; + static const size_t kInvalidPos = std::numeric_limits::max(); + CPDF_Parser(); ~CPDF_Parser(); - Error StartParse(const CFX_RetainPtr& pFile, + Error StartParse(const RetainPtr& pFile, CPDF_Document* pDocument); - Error StartLinearizedParse(const CFX_RetainPtr& pFile, + Error StartLinearizedParse(const RetainPtr& pFile, CPDF_Document* pDocument); - void SetPassword(const FX_CHAR* password) { m_Password = password; } - CFX_ByteString GetPassword() { return m_Password; } - CPDF_Dictionary* GetTrailer() const { return m_pTrailer.get(); } + void SetPassword(const char* password) { m_Password = password; } + ByteString GetPassword() { return m_Password; } + + CPDF_Dictionary* GetTrailer() const; + + // Returns a new trailer which combines the last read trailer with the /Root + // and /Info from previous ones. + std::unique_ptr GetCombinedTrailer() const; + FX_FILESIZE GetLastXRefOffset() const { return m_LastXRefOffset; } uint32_t GetPermissions() const; uint32_t GetRootObjNum(); uint32_t GetInfoObjNum(); - CPDF_Array* GetIDArray(); + const CPDF_Array* GetIDArray() const; - CPDF_Dictionary* GetEncryptDict() const { return m_pEncryptDict; } + CPDF_Dictionary* GetEncryptDict() const { return m_pEncryptDict.Get(); } std::unique_ptr ParseIndirectObject( CPDF_IndirectObjectHolder* pObjList, @@ -67,17 +80,16 @@ class CPDF_Parser { uint32_t GetLastObjNum() const; bool IsValidObjectNumber(uint32_t objnum) const; FX_FILESIZE GetObjectPositionOrZero(uint32_t objnum) const; - uint8_t GetObjectType(uint32_t objnum) const; uint16_t GetObjectGenNum(uint32_t objnum) const; - bool IsVersionUpdated() const { return m_bVersionUpdated; } bool IsObjectFreeOrNull(uint32_t objnum) const; - CPDF_CryptoHandler* GetCryptoHandler(); - CFX_RetainPtr GetFileAccess() const; + CPDF_SecurityHandler* GetSecurityHandler() const { + return m_pSecurityHandler.get(); + } + RetainPtr GetFileAccess() const; + bool IsObjectFree(uint32_t objnum) const; FX_FILESIZE GetObjectOffset(uint32_t objnum) const; - FX_FILESIZE GetObjectSize(uint32_t objnum) const; - void GetIndirectBinary(uint32_t objnum, uint8_t*& pBuffer, uint32_t& size); int GetFileVersion() const { return m_FileVersion; } bool IsXRefStream() const { return m_bXRefStream; } @@ -95,23 +107,37 @@ class CPDF_Parser { uint32_t GetFirstPageNo() const; protected: - struct ObjectInfo { - ObjectInfo() : pos(0), type(0), gennum(0) {} + enum class ObjectType : uint8_t { + kFree = 0x00, + kNotCompressed = 0x01, + kCompressed = 0x02, + kNull = 0xFF, + }; - FX_FILESIZE pos; - uint8_t type; + struct ObjectInfo { + ObjectInfo() : pos(0), type(ObjectType::kFree), gennum(0) {} + // if type is ObjectType::kCompressed the archive_obj_num should be used. + // if type is ObjectType::kNotCompressed the pos should be used. + // In other cases its are unused. + union { + FX_FILESIZE pos; + FX_FILESIZE archive_obj_num; + }; + ObjectType type; uint16_t gennum; }; std::unique_ptr m_pSyntax; std::map m_ObjectInfo; - bool LoadCrossRefV4(FX_FILESIZE pos, FX_FILESIZE streampos, bool bSkip); + bool LoadCrossRefV4(FX_FILESIZE pos, bool bSkip); bool RebuildCrossRef(); private: friend class CPDF_DataAvail; + class TrailerData; + enum class ParserState { kDefault, kComment, @@ -129,44 +155,68 @@ class CPDF_Parser { kEndObj }; - CPDF_Object* ParseDirect(CPDF_Object* pObj); + struct CrossRefObjData { + uint32_t obj_num = 0; + ObjectInfo info; + }; + + Error StartParseInternal(CPDF_Document* pDocument); + FX_FILESIZE ParseStartXRef(); bool LoadAllCrossRefV4(FX_FILESIZE pos); bool LoadAllCrossRefV5(FX_FILESIZE pos); bool LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef); std::unique_ptr LoadTrailerV4(); Error SetEncryptHandler(); void ReleaseEncryptHandler(); - bool LoadLinearizedAllCrossRefV4(FX_FILESIZE pos, uint32_t dwObjCount); - bool LoadLinearizedCrossRefV4(FX_FILESIZE pos, uint32_t dwObjCount); + bool LoadLinearizedAllCrossRefV4(FX_FILESIZE pos); bool LoadLinearizedAllCrossRefV5(FX_FILESIZE pos); Error LoadLinearizedMainXRefTable(); - CPDF_StreamAcc* GetObjectStream(uint32_t number); - bool IsLinearizedFile( - const CFX_RetainPtr& pFileAccess, - uint32_t offset); + RetainPtr GetObjectStream(uint32_t number); + std::unique_ptr ParseLinearizedHeader(); void SetEncryptDictionary(CPDF_Dictionary* pDict); void ShrinkObjectMap(uint32_t size); // A simple check whether the cross reference table matches with // the objects. bool VerifyCrossRefV4(); - CPDF_Document* m_pDocument; // not owned + // If out_objects is null, the parser position will be moved to end subsection + // without additional validation. + bool ParseAndAppendCrossRefSubsectionData( + uint32_t start_objnum, + uint32_t count, + std::vector* out_objects); + bool ParseCrossRefV4(std::vector* out_objects); + void MergeCrossRefObjectsData(const std::vector& objects); + + std::unique_ptr ParseIndirectObjectAtInternal( + CPDF_IndirectObjectHolder* pObjList, + FX_FILESIZE pos, + uint32_t objnum, + CPDF_SyntaxParser::ParseType parse_type, + FX_FILESIZE* pResultPos); + + bool InitSyntaxParser(const RetainPtr& file_access); + bool ParseFileVersion(); + + UnownedPtr m_pDocument; + ObjectType GetObjectType(uint32_t objnum) const; + ObjectType GetObjectTypeFromCrossRefStreamType( + int cross_ref_stream_type) const; + bool m_bHasParsed; bool m_bXRefStream; - bool m_bVersionUpdated; int m_FileVersion; - CPDF_Dictionary* m_pEncryptDict; + // m_TrailerData must be destroyed after m_pSecurityHandler due to the + // ownership of the ID array data. + std::unique_ptr m_TrailerData; + UnownedPtr m_pEncryptDict; FX_FILESIZE m_LastXRefOffset; std::unique_ptr m_pSecurityHandler; - CFX_ByteString m_Password; - std::set m_SortedOffset; - std::unique_ptr m_pTrailer; - std::vector> m_Trailers; + ByteString m_Password; std::unique_ptr m_pLinearized; - uint32_t m_dwXrefStartObjNum; - // A map of object numbers to indirect streams. Map owns the streams. - std::map> m_ObjectStreamMap; + // A map of object numbers to indirect streams. + std::map> m_ObjectStreamMap; // Mapping of object numbers to offsets. The offsets are relative to the first // object in the stream. @@ -174,10 +224,12 @@ class CPDF_Parser { // Mapping of streams to their object caches. This is valid as long as the // streams in |m_ObjectStreamMap| are valid. - std::map m_ObjCache; + std::map, StreamObjectCache> m_ObjCache; // All indirect object numbers that are being parsed. std::set m_ParsingObjNums; + + uint32_t m_MetadataObjnum = 0; }; #endif // CORE_FPDFAPI_PARSER_CPDF_PARSER_H_ diff --git a/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp b/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp index f523d6b31b3aa571f606d0028aaf228e583380c4..4109715a9c9c946583b5882c043d2a7eeec5f7f2 100644 --- a/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp +++ b/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp @@ -31,10 +31,6 @@ TEST_F(CPDFParserEmbeddertest, Bug_544880) { (void)GetPageCount(); } -TEST_F(CPDFParserEmbeddertest, Feature_Linearized_Loading) { - EXPECT_TRUE(OpenDocument("feature_linearized_loading.pdf", nullptr, true)); -} - TEST_F(CPDFParserEmbeddertest, Bug_325a) { EXPECT_FALSE(OpenDocument("bug_325_a.pdf")); } @@ -57,3 +53,23 @@ TEST_F(CPDFParserEmbeddertest, Bug_602650) { FPDFText_ClosePage(text_page); UnloadPage(page); } + +TEST_F(CPDFParserEmbeddertest, Bug_757705) { + EXPECT_TRUE(OpenDocument("bug_757705.pdf")); +} + +TEST_F(CPDFParserEmbeddertest, LoadMainCrossRefTable) { + EXPECT_TRUE(OpenDocumentLinearized("feature_linearized_loading.pdf")); + // To check that main cross ref table is loaded correctly,will be enough to + // check that the second page was correctly loaded. Because it is contains + // crossrefs for second page. + EXPECT_EQ(2, GetPageCount()); + FPDF_PAGE page = LoadPage(1); + EXPECT_NE(nullptr, page); + FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page); + EXPECT_NE(nullptr, text_page); + // The page should not be blank. + EXPECT_LT(0, FPDFText_CountChars(text_page)); + FPDFText_ClosePage(text_page); + UnloadPage(page); +} diff --git a/core/fpdfapi/parser/cpdf_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_parser_unittest.cpp index 3518f7d16bf54a41084d6eba8606ab82d10fc205..555c35c7cb820187e51df9f6a296efabb9c68555 100644 --- a/core/fpdfapi/parser/cpdf_parser_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_parser_unittest.cpp @@ -7,41 +7,13 @@ #include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/cpdf_syntax_parser.h" -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/retain_ptr.h" +#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/utils/path_service.h" -// Provide a way to read test data from a buffer instead of a file. -class CFX_TestBufferRead : public IFX_SeekableReadStream { - public: - static CFX_RetainPtr Create( - const unsigned char* buffer_in, - size_t buf_size) { - return CFX_RetainPtr( - new CFX_TestBufferRead(buffer_in, buf_size)); - } - - // IFX_SeekableReadStream: - bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { - if (offset < 0 || offset + size > total_size_) - return false; - - memcpy(buffer, buffer_ + offset, size); - return true; - } - - FX_FILESIZE GetSize() override { return (FX_FILESIZE)total_size_; }; - - protected: - CFX_TestBufferRead(const unsigned char* buffer_in, size_t buf_size) - : buffer_(buffer_in), total_size_(buf_size) {} - - const unsigned char* buffer_; - size_t total_size_; -}; - // A wrapper class to help test member functions of CPDF_Parser. class CPDF_TestParser : public CPDF_Parser { public: @@ -49,8 +21,8 @@ class CPDF_TestParser : public CPDF_Parser { ~CPDF_TestParser() {} // Setup reading from a file and initial states. - bool InitTestFromFile(const FX_CHAR* path) { - CFX_RetainPtr pFileAccess = + bool InitTestFromFile(const char* path) { + RetainPtr pFileAccess = IFX_SeekableReadStream::CreateFromFilename(path); if (!pFileAccess) return false; @@ -62,11 +34,9 @@ class CPDF_TestParser : public CPDF_Parser { // Setup reading from a buffer and initial states. bool InitTestFromBuffer(const unsigned char* buffer, size_t len) { - CFX_RetainPtr buffer_reader = - CFX_TestBufferRead::Create(buffer, len); - // For the test file, the header is set at the beginning. - m_pSyntax->InitParser(buffer_reader, 0); + m_pSyntax->InitParser( + pdfium::MakeRetain(buffer, len), 0); return true; } @@ -122,9 +92,15 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE( parser.InitTestFromBuffer(xref_table, FX_ArraySize(xref_table))); - ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); + ASSERT_TRUE(parser.LoadCrossRefV4(0, false)); const FX_FILESIZE offsets[] = {0, 17, 81, 0, 331, 409}; - const uint8_t types[] = {0, 1, 1, 0, 1, 1}; + const CPDF_TestParser::ObjectType types[] = { + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); @@ -147,10 +123,23 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE( parser.InitTestFromBuffer(xref_table, FX_ArraySize(xref_table))); - ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); + ASSERT_TRUE(parser.LoadCrossRefV4(0, false)); const FX_FILESIZE offsets[] = {0, 0, 0, 25325, 0, 0, 0, 0, 25518, 25635, 0, 0, 25777}; - const uint8_t types[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1}; + const CPDF_TestParser::ObjectType types[] = { + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); @@ -173,10 +162,23 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE( parser.InitTestFromBuffer(xref_table, FX_ArraySize(xref_table))); - ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); + ASSERT_TRUE(parser.LoadCrossRefV4(0, false)); const FX_FILESIZE offsets[] = {0, 0, 0, 25325, 0, 0, 0, 0, 0, 25635, 0, 0, 25777}; - const uint8_t types[] = {0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1}; + const CPDF_TestParser::ObjectType types[] = { + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); @@ -198,9 +200,16 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE( parser.InitTestFromBuffer(xref_table, FX_ArraySize(xref_table))); - ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); + ASSERT_TRUE(parser.LoadCrossRefV4(0, false)); const FX_FILESIZE offsets[] = {0, 23, 0, 0, 0, 45, 179}; - const uint8_t types[] = {0, 1, 0, 0, 0, 1, 1}; + const CPDF_TestParser::ObjectType types[] = { + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kFree, + CPDF_TestParser::ObjectType::kNotCompressed, + CPDF_TestParser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); diff --git a/core/fpdfapi/parser/cpdf_read_validator.cpp b/core/fpdfapi/parser/cpdf_read_validator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d850561bd3bfe0f474894a49932315737eeacd27 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_read_validator.cpp @@ -0,0 +1,164 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_read_validator.h" + +#include + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "third_party/base/logging.h" + +namespace { + +constexpr FX_FILESIZE kAlignBlockValue = CPDF_ModuleMgr::kFileBufSize; + +FX_FILESIZE AlignDown(FX_FILESIZE offset) { + return offset > 0 ? (offset - offset % kAlignBlockValue) : 0; +} + +FX_FILESIZE AlignUp(FX_FILESIZE offset) { + FX_SAFE_FILESIZE safe_result = AlignDown(offset); + safe_result += kAlignBlockValue; + if (safe_result.IsValid()) + return safe_result.ValueOrDie(); + return offset; +} + +} // namespace + +CPDF_ReadValidator::Session::Session(CPDF_ReadValidator* validator) + : validator_(validator) { + ASSERT(validator_); + saved_read_error_ = validator_->read_error_; + saved_has_unavailable_data_ = validator_->has_unavailable_data_; + validator_->ResetErrors(); +} + +CPDF_ReadValidator::Session::~Session() { + validator_->read_error_ |= saved_read_error_; + validator_->has_unavailable_data_ |= saved_has_unavailable_data_; +} + +CPDF_ReadValidator::CPDF_ReadValidator( + const RetainPtr& file_read, + CPDF_DataAvail::FileAvail* file_avail) + : file_read_(file_read), + file_avail_(file_avail), + read_error_(false), + has_unavailable_data_(false), + whole_file_already_available_(false), + file_size_(file_read->GetSize()) {} + +CPDF_ReadValidator::~CPDF_ReadValidator() {} + +void CPDF_ReadValidator::ResetErrors() { + read_error_ = false; + has_unavailable_data_ = false; +} + +bool CPDF_ReadValidator::ReadBlock(void* buffer, + FX_FILESIZE offset, + size_t size) { + FX_SAFE_FILESIZE end_offset = offset; + end_offset += size; + if (!end_offset.IsValid() || end_offset.ValueOrDie() > file_size_) + return false; + + if (!IsDataRangeAvailable(offset, size)) { + ScheduleDownload(offset, size); + return false; + } + + if (file_read_->ReadBlock(buffer, offset, size)) + return true; + + read_error_ = true; + ScheduleDownload(offset, size); + return false; +} + +FX_FILESIZE CPDF_ReadValidator::GetSize() { + return file_size_; +} + +void CPDF_ReadValidator::ScheduleDownload(FX_FILESIZE offset, size_t size) { + has_unavailable_data_ = true; + if (!hints_ || size == 0) + return; + + const FX_FILESIZE start_segment_offset = AlignDown(offset); + FX_SAFE_FILESIZE end_segment_offset = offset; + end_segment_offset += size; + if (!end_segment_offset.IsValid()) { + NOTREACHED(); + return; + } + end_segment_offset = + std::min(file_size_, AlignUp(end_segment_offset.ValueOrDie())); + + FX_SAFE_SIZE_T segment_size = end_segment_offset; + segment_size -= start_segment_offset; + if (!segment_size.IsValid()) { + NOTREACHED(); + return; + } + hints_->AddSegment(start_segment_offset, segment_size.ValueOrDie()); +} + +bool CPDF_ReadValidator::IsDataRangeAvailable(FX_FILESIZE offset, + size_t size) const { + return whole_file_already_available_ || !file_avail_ || + file_avail_->IsDataAvail(offset, size); +} + +bool CPDF_ReadValidator::IsWholeFileAvailable() { + const FX_SAFE_SIZE_T safe_size = file_size_; + whole_file_already_available_ = + whole_file_already_available_ || + (safe_size.IsValid() ? IsDataRangeAvailable(0, safe_size.ValueOrDie()) + : false); + + return whole_file_already_available_; +} + +bool CPDF_ReadValidator::CheckDataRangeAndRequestIfUnavailable( + FX_FILESIZE offset, + size_t size) { + if (offset > file_size_) + return true; + + FX_SAFE_FILESIZE end_segment_offset = offset; + end_segment_offset += size; + // Increase checked range to allow CPDF_SyntaxParser read whole buffer. + end_segment_offset += CPDF_ModuleMgr::kFileBufSize; + if (!end_segment_offset.IsValid()) { + NOTREACHED(); + return false; + } + end_segment_offset = std::min( + file_size_, static_cast(end_segment_offset.ValueOrDie())); + FX_SAFE_SIZE_T segment_size = end_segment_offset; + segment_size -= offset; + if (!segment_size.IsValid()) { + NOTREACHED(); + return false; + } + + if (IsDataRangeAvailable(offset, segment_size.ValueOrDie())) + return true; + + ScheduleDownload(offset, segment_size.ValueOrDie()); + return false; +} + +bool CPDF_ReadValidator::CheckWholeFileAndRequestIfUnavailable() { + if (IsWholeFileAvailable()) + return true; + + const FX_SAFE_SIZE_T safe_size = file_size_; + if (safe_size.IsValid()) + ScheduleDownload(0, safe_size.ValueOrDie()); + + return false; +} diff --git a/core/fpdfapi/parser/cpdf_read_validator.h b/core/fpdfapi/parser/cpdf_read_validator.h new file mode 100644 index 0000000000000000000000000000000000000000..31c33fa36acfccd71cc85a1819660f2e4254f929 --- /dev/null +++ b/core/fpdfapi/parser/cpdf_read_validator.h @@ -0,0 +1,69 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FPDFAPI_PARSER_CPDF_READ_VALIDATOR_H_ +#define CORE_FPDFAPI_PARSER_CPDF_READ_VALIDATOR_H_ + +#include "core/fpdfapi/parser/cpdf_data_avail.h" +#include "core/fxcrt/fx_stream.h" + +class CPDF_ReadValidator : public IFX_SeekableReadStream { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + class Session { + public: + explicit Session(CPDF_ReadValidator* validator); + ~Session(); + + private: + UnownedPtr validator_; + bool saved_read_error_; + bool saved_has_unavailable_data_; + }; + + void SetDownloadHints(CPDF_DataAvail::DownloadHints* hints) { + hints_ = hints; + } + + bool read_error() const { return read_error_; } + bool has_unavailable_data() const { return has_unavailable_data_; } + + bool has_read_problems() const { + return read_error() || has_unavailable_data(); + } + + void ResetErrors(); + + bool IsWholeFileAvailable(); + + bool CheckDataRangeAndRequestIfUnavailable(FX_FILESIZE offset, size_t size); + bool CheckWholeFileAndRequestIfUnavailable(); + + // IFX_SeekableReadStream overrides: + bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; + FX_FILESIZE GetSize() override; + + protected: + CPDF_ReadValidator(const RetainPtr& file_read, + CPDF_DataAvail::FileAvail* file_avail); + ~CPDF_ReadValidator() override; + + private: + void ScheduleDownload(FX_FILESIZE offset, size_t size); + bool IsDataRangeAvailable(FX_FILESIZE offset, size_t size) const; + + RetainPtr file_read_; + UnownedPtr file_avail_; + + UnownedPtr hints_; + + bool read_error_; + bool has_unavailable_data_; + bool whole_file_already_available_; + const FX_FILESIZE file_size_; +}; + +#endif // CORE_FPDFAPI_PARSER_CPDF_READ_VALIDATOR_H_ diff --git a/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp b/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..247abaa9f4d45604c285a618226529b31faf633e --- /dev/null +++ b/core/fpdfapi/parser/cpdf_read_validator_unittest.cpp @@ -0,0 +1,301 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/parser/cpdf_read_validator.h" + +#include +#include +#include + +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_stream.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +constexpr uint32_t kTestDataSize = 64 * 1024 - 467; + +std::pair MakeRange(uint32_t start, uint32_t end) { + return std::pair(start, end); +} + +class MockFileAvail : public CPDF_DataAvail::FileAvail { + public: + MockFileAvail() : available_range_(0, 0) {} + ~MockFileAvail() override {} + + bool IsDataAvail(FX_FILESIZE offset, size_t size) override { + return available_range_.first <= offset && + available_range_.second >= static_cast(offset + size); + } + + void SetAvailableRange(const std::pair& range) { + available_range_ = range; + } + + void SetAvailableRange(uint32_t start, uint32_t end) { + SetAvailableRange(MakeRange(start, end)); + } + + private: + std::pair available_range_; +}; + +class MockDownloadHints : public CPDF_DataAvail::DownloadHints { + public: + MockDownloadHints() : last_requested_range_(0, 0) {} + ~MockDownloadHints() override {} + + void AddSegment(FX_FILESIZE offset, size_t size) override { + last_requested_range_.first = offset; + last_requested_range_.second = offset + size; + } + + const std::pair& GetLastRequstedRange() const { + return last_requested_range_; + } + + void Reset() { last_requested_range_ = MakeRange(0, 0); } + + private: + std::pair last_requested_range_; +}; + +} // namespace + +TEST(CPDF_ReadValidatorTest, UnavailableData) { + std::vector test_data(kTestDataSize); + auto file = pdfium::MakeRetain(test_data.data(), + test_data.size(), false); + MockFileAvail file_avail; + auto validator = pdfium::MakeRetain(file, &file_avail); + + std::vector read_buffer(100); + EXPECT_FALSE( + validator->ReadBlock(read_buffer.data(), 5000, read_buffer.size())); + + EXPECT_FALSE(validator->read_error()); + EXPECT_TRUE(validator->has_unavailable_data()); + + validator->ResetErrors(); + + file_avail.SetAvailableRange(5000, 5000 + read_buffer.size()); + + EXPECT_TRUE( + validator->ReadBlock(read_buffer.data(), 5000, read_buffer.size())); + EXPECT_FALSE(validator->read_error()); + EXPECT_FALSE(validator->has_unavailable_data()); +} + +TEST(CPDF_ReadValidatorTest, UnavailableDataWithHints) { + std::vector test_data(kTestDataSize); + auto file = pdfium::MakeRetain(test_data.data(), + test_data.size(), false); + MockFileAvail file_avail; + auto validator = pdfium::MakeRetain(file, &file_avail); + + MockDownloadHints hints; + validator->SetDownloadHints(&hints); + + std::vector read_buffer(100); + + EXPECT_FALSE( + validator->ReadBlock(read_buffer.data(), 5000, read_buffer.size())); + EXPECT_FALSE(validator->read_error()); + EXPECT_TRUE(validator->has_unavailable_data()); + + // Requested range should be enlarged and aligned. + EXPECT_EQ(MakeRange(4608, 5120), hints.GetLastRequstedRange()); + + file_avail.SetAvailableRange(hints.GetLastRequstedRange()); + hints.Reset(); + + validator->ResetErrors(); + EXPECT_TRUE( + validator->ReadBlock(read_buffer.data(), 5000, read_buffer.size())); + // No new request on already available data. + EXPECT_EQ(MakeRange(0, 0), hints.GetLastRequstedRange()); + EXPECT_FALSE(validator->read_error()); + EXPECT_FALSE(validator->has_unavailable_data()); + + validator->ResetErrors(); + // Try read unavailable data at file end. + EXPECT_FALSE(validator->ReadBlock(read_buffer.data(), + validator->GetSize() - read_buffer.size(), + read_buffer.size())); + // Should not enlarge request at file end. + EXPECT_EQ(validator->GetSize(), hints.GetLastRequstedRange().second); + EXPECT_FALSE(validator->read_error()); + EXPECT_TRUE(validator->has_unavailable_data()); + + validator->SetDownloadHints(nullptr); +} + +TEST(CPDF_ReadValidatorTest, ReadError) { + auto file = pdfium::MakeRetain(kTestDataSize); + auto validator = pdfium::MakeRetain(file, nullptr); + + static const uint32_t kBufferSize = 3 * 1000; + std::vector buffer(kBufferSize); + + EXPECT_FALSE(validator->ReadBlock(buffer.data(), 5000, 100)); + EXPECT_TRUE(validator->read_error()); + EXPECT_TRUE(validator->has_unavailable_data()); +} + +TEST(CPDF_ReadValidatorTest, IntOverflow) { + std::vector test_data(kTestDataSize); + auto file = pdfium::MakeRetain(test_data.data(), + test_data.size(), false); + MockFileAvail file_avail; + auto validator = pdfium::MakeRetain(file, &file_avail); + + std::vector read_buffer(100); + + // If we have int overflow, this is equal reading after file end. This is not + // read_error, and in this case we have not unavailable data. It is just error + // of input params. + EXPECT_FALSE(validator->ReadBlock(read_buffer.data(), + std::numeric_limits::max() - 1, + read_buffer.size())); + EXPECT_FALSE(validator->read_error()); + EXPECT_FALSE(validator->has_unavailable_data()); +} + +TEST(CPDF_ReadValidatorTest, Session) { + std::vector test_data(kTestDataSize); + + auto file = pdfium::MakeRetain(kTestDataSize); + MockFileAvail file_avail; + MockDownloadHints hints; + auto validator = pdfium::MakeRetain(file, &file_avail); + validator->SetDownloadHints(&hints); + + const CPDF_ReadValidator::Session read_session(validator.Get()); + ASSERT_FALSE(validator->has_read_problems()); + + // Data is unavailable + validator->ReadBlock(test_data.data(), 0, 100); + + EXPECT_TRUE(validator->has_read_problems()); + EXPECT_TRUE(validator->has_unavailable_data()); + EXPECT_FALSE(validator->read_error()); + + { + const CPDF_ReadValidator::Session read_subsession(validator.Get()); + // The read problems should be hidden. + EXPECT_FALSE(validator->has_read_problems()); + + file_avail.SetAvailableRange(0, 100); + // Read fail. + validator->ReadBlock(test_data.data(), 0, 100); + EXPECT_TRUE(validator->has_read_problems()); + EXPECT_TRUE(validator->has_unavailable_data()); + EXPECT_TRUE(validator->read_error()); + } + + // The problems should be merged + EXPECT_TRUE(validator->has_read_problems()); + EXPECT_TRUE(validator->has_unavailable_data()); + EXPECT_TRUE(validator->read_error()); +} + +TEST(CPDF_ReadValidatorTest, SessionReset) { + std::vector test_data(kTestDataSize); + + auto file = pdfium::MakeRetain(kTestDataSize); + MockFileAvail file_avail; + MockDownloadHints hints; + auto validator = pdfium::MakeRetain(file, &file_avail); + validator->SetDownloadHints(&hints); + + const CPDF_ReadValidator::Session read_session(validator.Get()); + ASSERT_FALSE(validator->has_read_problems()); + + // Data is unavailable + validator->ReadBlock(test_data.data(), 0, 100); + + EXPECT_TRUE(validator->has_read_problems()); + EXPECT_TRUE(validator->has_unavailable_data()); + EXPECT_FALSE(validator->read_error()); + + { + const CPDF_ReadValidator::Session read_subsession(validator.Get()); + // The read problems should be hidden. + EXPECT_FALSE(validator->has_read_problems()); + + file_avail.SetAvailableRange(0, 100); + // Read fail. + validator->ReadBlock(test_data.data(), 0, 100); + EXPECT_TRUE(validator->has_read_problems()); + EXPECT_TRUE(validator->has_unavailable_data()); + EXPECT_TRUE(validator->read_error()); + + // Reset session. + validator->ResetErrors(); + EXPECT_FALSE(validator->has_read_problems()); + } + + // The problems should be restored. + EXPECT_TRUE(validator->has_read_problems()); + EXPECT_TRUE(validator->has_unavailable_data()); + EXPECT_FALSE(validator->read_error()); +} + +TEST(CPDF_ReadValidatorTest, CheckDataRangeAndRequestIfUnavailable) { + std::vector test_data(kTestDataSize); + auto file = pdfium::MakeRetain(test_data.data(), + test_data.size(), false); + MockFileAvail file_avail; + auto validator = pdfium::MakeRetain(file, &file_avail); + + MockDownloadHints hints; + validator->SetDownloadHints(&hints); + + EXPECT_FALSE(validator->CheckDataRangeAndRequestIfUnavailable(5000, 100)); + EXPECT_FALSE(validator->read_error()); + EXPECT_TRUE(validator->has_unavailable_data()); + + // Requested range should be enlarged and aligned. + EXPECT_EQ(MakeRange(4608, 5632), hints.GetLastRequstedRange()); + + file_avail.SetAvailableRange(hints.GetLastRequstedRange()); + hints.Reset(); + + validator->ResetErrors(); + EXPECT_TRUE(validator->CheckDataRangeAndRequestIfUnavailable(5000, 100)); + // No new request on already available data. + EXPECT_EQ(MakeRange(0, 0), hints.GetLastRequstedRange()); + EXPECT_FALSE(validator->read_error()); + EXPECT_FALSE(validator->has_unavailable_data()); + + std::vector read_buffer(100); + EXPECT_TRUE( + validator->ReadBlock(read_buffer.data(), 5000, read_buffer.size())); + // No new request on already available data. + EXPECT_EQ(MakeRange(0, 0), hints.GetLastRequstedRange()); + EXPECT_FALSE(validator->read_error()); + EXPECT_FALSE(validator->has_unavailable_data()); + + validator->ResetErrors(); + // Try request unavailable data at file end. + EXPECT_FALSE(validator->CheckDataRangeAndRequestIfUnavailable( + validator->GetSize() - 100, 100)); + + // Should not enlarge request at file end. + EXPECT_EQ(validator->GetSize(), hints.GetLastRequstedRange().second); + EXPECT_FALSE(validator->read_error()); + EXPECT_TRUE(validator->has_unavailable_data()); + + validator->ResetErrors(); + // Offset > file size should yield |true| and not cause a fetch. + EXPECT_TRUE( + validator->CheckDataRangeAndRequestIfUnavailable(kTestDataSize + 1, 1)); + // No new request on already available data. + EXPECT_FALSE(validator->read_error()); + EXPECT_FALSE(validator->has_unavailable_data()); + + validator->SetDownloadHints(nullptr); +} diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp index 67b67c24dd1edbb0e1222dc2de0abf859df7e1a6..2ca0bddc4fbb64b71eaefd0e77507d80f5d268a0 100644 --- a/core/fpdfapi/parser/cpdf_reference.cpp +++ b/core/fpdfapi/parser/cpdf_reference.cpp @@ -7,6 +7,7 @@ #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" @@ -19,12 +20,12 @@ CPDF_Object::Type CPDF_Reference::GetType() const { return REFERENCE; } -CFX_ByteString CPDF_Reference::GetString() const { +ByteString CPDF_Reference::GetString() const { CPDF_Object* obj = SafeGetDirect(); - return obj ? obj->GetString() : CFX_ByteString(); + return obj ? obj->GetString() : ByteString(); } -FX_FLOAT CPDF_Reference::GetNumber() const { +float CPDF_Reference::GetNumber() const { CPDF_Object* obj = SafeGetDirect(); return obj ? obj->GetNumber() : 0; } @@ -65,7 +66,7 @@ std::unique_ptr CPDF_Reference::CloneNonCyclic( ? pDirect->CloneNonCyclic(true, pVisited) : nullptr; } - return pdfium::MakeUnique(m_pObjList, m_RefObjNum); + return pdfium::MakeUnique(m_pObjList.Get(), m_RefObjNum); } CPDF_Object* CPDF_Reference::SafeGetDirect() const { @@ -82,3 +83,8 @@ CPDF_Object* CPDF_Reference::GetDirect() const { return m_pObjList ? m_pObjList->GetOrParseIndirectObject(m_RefObjNum) : nullptr; } + +bool CPDF_Reference::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" ") && archive->WriteDWord(GetRefObjNum()) && + archive->WriteString(" 0 R "); +} diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h index be7f18478e96c0221d5870e014e243141f64df84..b472b4a3ac99d0d82c43654111cb266b6090e5a1 100644 --- a/core/fpdfapi/parser/cpdf_reference.h +++ b/core/fpdfapi/parser/cpdf_reference.h @@ -11,6 +11,7 @@ #include #include "core/fpdfapi/parser/cpdf_object.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_IndirectObjectHolder; @@ -23,17 +24,17 @@ class CPDF_Reference : public CPDF_Object { Type GetType() const override; std::unique_ptr Clone() const override; CPDF_Object* GetDirect() const override; - CFX_ByteString GetString() const override; - FX_FLOAT GetNumber() const override; + ByteString GetString() const override; + float GetNumber() const override; int GetInteger() const override; CPDF_Dictionary* GetDict() const override; bool IsReference() const override; CPDF_Reference* AsReference() override; const CPDF_Reference* AsReference() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; - CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList; } + CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList.Get(); } uint32_t GetRefObjNum() const { return m_RefObjNum; } - void SetRef(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum); protected: @@ -42,7 +43,7 @@ class CPDF_Reference : public CPDF_Object { std::set* pVisited) const override; CPDF_Object* SafeGetDirect() const; - CPDF_IndirectObjectHolder* m_pObjList; + UnownedPtr m_pObjList; uint32_t m_RefObjNum; }; diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp index 61834fca1334ae1d5474ee4014e7fc290faecdb0..7eb5c42f72d3452f4971eddd37b75239ff40a1de 100644 --- a/core/fpdfapi/parser/cpdf_security_handler.cpp +++ b/core/fpdfapi/parser/cpdf_security_handler.cpp @@ -17,7 +17,6 @@ #include "core/fpdfapi/parser/cpdf_crypto_handler.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/cpdf_string.h" namespace { @@ -27,47 +26,60 @@ const uint8_t defpasscode[32] = { 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a}; -void CalcEncryptKey(CPDF_Dictionary* pEncrypt, - const uint8_t* password, - uint32_t pass_size, +void CalcEncryptKey(const CPDF_Dictionary* pEncrypt, + const ByteString& password, uint8_t* key, int keylen, bool bIgnoreMeta, - CPDF_Array* pIdArray) { + const ByteString& fileId) { int revision = pEncrypt->GetIntegerFor("R"); uint8_t passcode[32]; for (uint32_t i = 0; i < 32; i++) { - passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size]; + passcode[i] = i < password.GetLength() + ? password[i] + : defpasscode[i - password.GetLength()]; } CRYPT_md5_context md5; CRYPT_MD5Start(&md5); CRYPT_MD5Update(&md5, passcode, 32); - CFX_ByteString okey = pEncrypt->GetStringFor("O"); + ByteString okey = pEncrypt->GetStringFor("O"); CRYPT_MD5Update(&md5, (uint8_t*)okey.c_str(), okey.GetLength()); uint32_t perm = pEncrypt->GetIntegerFor("P"); CRYPT_MD5Update(&md5, (uint8_t*)&perm, 4); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetStringAt(0); - CRYPT_MD5Update(&md5, (uint8_t*)id.c_str(), id.GetLength()); - } + if (!fileId.IsEmpty()) + CRYPT_MD5Update(&md5, (uint8_t*)fileId.c_str(), fileId.GetLength()); if (!bIgnoreMeta && revision >= 3 && !pEncrypt->GetIntegerFor("EncryptMetadata", 1)) { - uint32_t tag = (uint32_t)-1; + uint32_t tag = 0xFFFFFFFF; CRYPT_MD5Update(&md5, (uint8_t*)&tag, 4); } uint8_t digest[16]; CRYPT_MD5Finish(&md5, digest); uint32_t copy_len = keylen; - if (copy_len > sizeof(digest)) { + if (copy_len > sizeof(digest)) copy_len = sizeof(digest); - } if (revision >= 3) { - for (int i = 0; i < 50; i++) { + for (int i = 0; i < 50; i++) CRYPT_MD5Generate(digest, copy_len, digest); - } } - FXSYS_memset(key, 0, keylen); - FXSYS_memcpy(key, digest, copy_len); + memset(key, 0, keylen); + memcpy(key, digest, copy_len); +} + +bool IsValidKeyLengthForCipher(int cipher, int keylen) { + switch (cipher) { + case FXCIPHER_AES: + return keylen == 16 || keylen == 24 || keylen == 32; + case FXCIPHER_AES2: + return keylen == 32; + case FXCIPHER_RC4: + return keylen >= 5 && keylen <= 16; + case FXCIPHER_NONE: + return true; + default: + NOTREACHED(); + } + return false; } } // namespace @@ -75,8 +87,6 @@ void CalcEncryptKey(CPDF_Dictionary* pEncrypt, CPDF_SecurityHandler::CPDF_SecurityHandler() : m_Version(0), m_Revision(0), - m_pParser(nullptr), - m_pEncryptDict(nullptr), m_Permissions(0), m_Cipher(FXCIPHER_NONE), m_KeyLen(0), @@ -84,40 +94,36 @@ CPDF_SecurityHandler::CPDF_SecurityHandler() CPDF_SecurityHandler::~CPDF_SecurityHandler() {} -CPDF_CryptoHandler* CPDF_SecurityHandler::CreateCryptoHandler() { - return new CPDF_CryptoHandler; -} - -bool CPDF_SecurityHandler::OnInit(CPDF_Parser* pParser, - CPDF_Dictionary* pEncryptDict) { - m_pParser = pParser; - if (!LoadDict(pEncryptDict)) { +bool CPDF_SecurityHandler::OnInit(const CPDF_Dictionary* pEncryptDict, + const CPDF_Array* pIdArray, + const ByteString& password) { + m_FileId = pIdArray ? pIdArray->GetStringAt(0) : ""; + if (!LoadDict(pEncryptDict)) return false; - } - if (m_Cipher == FXCIPHER_NONE) { + if (m_Cipher == FXCIPHER_NONE) return true; - } - return CheckSecurity(m_KeyLen); + if (!CheckSecurity(password)) + return false; + + InitCryptoHandler(); + return true; } -bool CPDF_SecurityHandler::CheckSecurity(int32_t key_len) { - CFX_ByteString password = m_pParser->GetPassword(); +bool CPDF_SecurityHandler::CheckSecurity(const ByteString& password) { if (!password.IsEmpty() && - CheckPassword(password.raw_str(), password.GetLength(), true, - m_EncryptKey, key_len)) { + CheckPassword(password, true, m_EncryptKey, m_KeyLen)) { m_bOwnerUnlocked = true; return true; } - return CheckPassword(password.raw_str(), password.GetLength(), false, - m_EncryptKey, key_len); + return CheckPassword(password, false, m_EncryptKey, m_KeyLen); } -uint32_t CPDF_SecurityHandler::GetPermissions() { +uint32_t CPDF_SecurityHandler::GetPermissions() const { return m_bOwnerUnlocked ? 0xFFFFFFFF : m_Permissions; } -static bool LoadCryptInfo(CPDF_Dictionary* pEncryptDict, - const CFX_ByteString& name, +static bool LoadCryptInfo(const CPDF_Dictionary* pEncryptDict, + const ByteString& name, int& cipher, int& keylen) { int Version = pEncryptDict->GetIntegerFor("V"); @@ -148,7 +154,7 @@ static bool LoadCryptInfo(CPDF_Dictionary* pEncryptDict, nKeyBits *= 8; } keylen = nKeyBits / 8; - CFX_ByteString cipher_name = pDefFilter->GetStringFor("CFM"); + ByteString cipher_name = pDefFilter->GetStringFor("CFM"); if (cipher_name == "AESV2" || cipher_name == "AESV3") { cipher = FXCIPHER_AES; } @@ -159,27 +165,26 @@ static bool LoadCryptInfo(CPDF_Dictionary* pEncryptDict, if (keylen > 32 || keylen < 0) { return false; } - return true; + return IsValidKeyLengthForCipher(cipher, keylen); } -bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) { +bool CPDF_SecurityHandler::LoadDict(const CPDF_Dictionary* pEncryptDict) { m_pEncryptDict = pEncryptDict; m_Version = pEncryptDict->GetIntegerFor("V"); m_Revision = pEncryptDict->GetIntegerFor("R"); m_Permissions = pEncryptDict->GetIntegerFor("P", -1); if (m_Version < 4) - return LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen); + return LoadCryptInfo(pEncryptDict, ByteString(), m_Cipher, m_KeyLen); - CFX_ByteString stmf_name = pEncryptDict->GetStringFor("StmF"); - CFX_ByteString strf_name = pEncryptDict->GetStringFor("StrF"); + ByteString stmf_name = pEncryptDict->GetStringFor("StmF"); + ByteString strf_name = pEncryptDict->GetStringFor("StrF"); if (stmf_name != strf_name) return false; return LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen); } -bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, - uint32_t type, +bool CPDF_SecurityHandler::LoadDict(const CPDF_Dictionary* pEncryptDict, int& cipher, int& key_len) { m_pEncryptDict = pEncryptDict; @@ -187,8 +192,8 @@ bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, m_Revision = pEncryptDict->GetIntegerFor("R"); m_Permissions = pEncryptDict->GetIntegerFor("P", -1); - CFX_ByteString strf_name; - CFX_ByteString stmf_name; + ByteString strf_name; + ByteString stmf_name; if (m_Version >= 4) { stmf_name = pEncryptDict->GetStringFor("StmF"); strf_name = pEncryptDict->GetStringFor("StrF"); @@ -203,14 +208,6 @@ bool CPDF_SecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, return true; } -bool CPDF_SecurityHandler::GetCryptInfo(int& cipher, - const uint8_t*& buffer, - int& keylen) { - cipher = m_Cipher; - buffer = m_EncryptKey; - keylen = m_KeyLen; - return true; -} #define FX_GET_32WORD(n, b, i) \ { \ (n) = (uint32_t)( \ @@ -229,14 +226,13 @@ int BigOrder64BitsMod3(uint8_t* data) { return (int)ret; } -void Revision6_Hash(const uint8_t* password, - uint32_t size, +void Revision6_Hash(const ByteString& password, const uint8_t* salt, const uint8_t* vector, uint8_t* hash) { - CRYPT_sha256_context sha; + CRYPT_sha2_context sha; CRYPT_SHA256Start(&sha); - CRYPT_SHA256Update(&sha, password, size); + CRYPT_SHA256Update(&sha, password.raw_str(), password.GetLength()); CRYPT_SHA256Update(&sha, salt, 8); if (vector) CRYPT_SHA256Update(&sha, vector, 48); @@ -244,35 +240,37 @@ void Revision6_Hash(const uint8_t* password, uint8_t digest[32]; CRYPT_SHA256Finish(&sha, digest); - CFX_ByteTextBuf buf; + std::vector buf; uint8_t* input = digest; uint8_t* key = input; uint8_t* iv = input + 16; - uint8_t* E = buf.GetBuffer(); - int iBufLen = buf.GetLength(); - CFX_ByteTextBuf interDigest; + uint8_t* E = nullptr; + int iBufLen = 0; + std::vector interDigest; int i = 0; int iBlockSize = 32; - uint8_t* aes = FX_Alloc(uint8_t, 2048); + CRYPT_aes_context aes; + memset(&aes, 0, sizeof(aes)); while (i < 64 || i < E[iBufLen - 1] + 32) { - int iRoundSize = size + iBlockSize; + int iRoundSize = password.GetLength() + iBlockSize; if (vector) { iRoundSize += 48; } iBufLen = iRoundSize * 64; - buf.EstimateSize(iBufLen); - E = buf.GetBuffer(); - CFX_ByteTextBuf content; + buf.resize(iBufLen); + E = buf.data(); + std::vector content; for (int j = 0; j < 64; ++j) { - content.AppendBlock(password, size); - content.AppendBlock(input, iBlockSize); + content.insert(std::end(content), password.raw_str(), + password.raw_str() + password.GetLength()); + content.insert(std::end(content), input, input + iBlockSize); if (vector) { - content.AppendBlock(vector, 48); + content.insert(std::end(content), vector, vector + 48); } } - CRYPT_AESSetKey(aes, 16, key, 16, true); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen); + CRYPT_AESSetKey(&aes, 16, key, 16, true); + CRYPT_AESSetIV(&aes, iv); + CRYPT_AESEncrypt(&aes, E, content.data(), iBufLen); int iHash = 0; switch (BigOrder64BitsMod3(E)) { case 0: @@ -288,8 +286,8 @@ void Revision6_Hash(const uint8_t* password, iBlockSize = 64; break; } - interDigest.EstimateSize(iBlockSize); - input = interDigest.GetBuffer(); + interDigest.resize(iBlockSize); + input = interDigest.data(); if (iHash == 0) { CRYPT_SHA256Generate(E, iBufLen, input); } else if (iHash == 1) { @@ -301,85 +299,80 @@ void Revision6_Hash(const uint8_t* password, iv = input + 16; ++i; } - FX_Free(aes); if (hash) { - FXSYS_memcpy(hash, input, 32); + memcpy(hash, input, 32); } } -bool CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password, - uint32_t size, +bool CPDF_SecurityHandler::AES256_CheckPassword(const ByteString& password, bool bOwner, uint8_t* key) { if (!m_pEncryptDict) return false; - CFX_ByteString okey = m_pEncryptDict->GetStringFor("O"); + ByteString okey = m_pEncryptDict->GetStringFor("O"); if (okey.GetLength() < 48) return false; - CFX_ByteString ukey = m_pEncryptDict->GetStringFor("U"); + ByteString ukey = m_pEncryptDict->GetStringFor("U"); if (ukey.GetLength() < 48) return false; const uint8_t* pkey = bOwner ? okey.raw_str() : ukey.raw_str(); - CRYPT_sha256_context sha; + CRYPT_sha2_context sha; uint8_t digest[32]; if (m_Revision >= 6) { - Revision6_Hash(password, size, (const uint8_t*)pkey + 32, + Revision6_Hash(password, (const uint8_t*)pkey + 32, bOwner ? ukey.raw_str() : nullptr, digest); } else { CRYPT_SHA256Start(&sha); - CRYPT_SHA256Update(&sha, password, size); + CRYPT_SHA256Update(&sha, password.raw_str(), password.GetLength()); CRYPT_SHA256Update(&sha, pkey + 32, 8); if (bOwner) CRYPT_SHA256Update(&sha, ukey.raw_str(), 48); - CRYPT_SHA256Finish(&sha, digest); } - if (FXSYS_memcmp(digest, pkey, 32) != 0) + if (memcmp(digest, pkey, 32) != 0) return false; if (!key) return true; if (m_Revision >= 6) { - Revision6_Hash(password, size, (const uint8_t*)pkey + 40, + Revision6_Hash(password, (const uint8_t*)pkey + 40, bOwner ? ukey.raw_str() : nullptr, digest); } else { CRYPT_SHA256Start(&sha); - CRYPT_SHA256Update(&sha, password, size); + CRYPT_SHA256Update(&sha, password.raw_str(), password.GetLength()); CRYPT_SHA256Update(&sha, pkey + 40, 8); if (bOwner) CRYPT_SHA256Update(&sha, ukey.raw_str(), 48); - CRYPT_SHA256Finish(&sha, digest); } - CFX_ByteString ekey = m_pEncryptDict - ? m_pEncryptDict->GetStringFor(bOwner ? "OE" : "UE") - : CFX_ByteString(); + ByteString ekey = m_pEncryptDict->GetStringFor(bOwner ? "OE" : "UE"); if (ekey.GetLength() < 32) return false; - std::vector aes(2048); - CRYPT_AESSetKey(aes.data(), 16, digest, 32, false); + CRYPT_aes_context aes; + memset(&aes, 0, sizeof(aes)); + CRYPT_AESSetKey(&aes, 16, digest, 32, false); uint8_t iv[16]; - FXSYS_memset(iv, 0, 16); - CRYPT_AESSetIV(aes.data(), iv); - CRYPT_AESDecrypt(aes.data(), key, ekey.raw_str(), 32); - CRYPT_AESSetKey(aes.data(), 16, key, 32, false); - CRYPT_AESSetIV(aes.data(), iv); - CFX_ByteString perms = m_pEncryptDict->GetStringFor("Perms"); + memset(iv, 0, 16); + CRYPT_AESSetIV(&aes, iv); + CRYPT_AESDecrypt(&aes, key, ekey.raw_str(), 32); + CRYPT_AESSetKey(&aes, 16, key, 32, false); + CRYPT_AESSetIV(&aes, iv); + ByteString perms = m_pEncryptDict->GetStringFor("Perms"); if (perms.IsEmpty()) return false; uint8_t perms_buf[16]; - FXSYS_memset(perms_buf, 0, sizeof(perms_buf)); + memset(perms_buf, 0, sizeof(perms_buf)); size_t copy_len = std::min(sizeof(perms_buf), static_cast(perms.GetLength())); - FXSYS_memcpy(perms_buf, perms.raw_str(), copy_len); + memcpy(perms_buf, perms.raw_str(), copy_len); uint8_t buf[16]; - CRYPT_AESDecrypt(aes.data(), buf, perms_buf, 16); + CRYPT_AESDecrypt(&aes, buf, perms_buf, 16); if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') return false; @@ -393,39 +386,39 @@ bool CPDF_SecurityHandler::AES256_CheckPassword(const uint8_t* password, return buf[8] == 'F' || IsMetadataEncrypted(); } -bool CPDF_SecurityHandler::CheckPassword(const uint8_t* password, - uint32_t size, +bool CPDF_SecurityHandler::CheckPassword(const ByteString& password, bool bOwner, uint8_t* key, int32_t key_len) { if (m_Revision >= 5) - return AES256_CheckPassword(password, size, bOwner, key); + return AES256_CheckPassword(password, bOwner, key); uint8_t keybuf[32]; if (!key) key = keybuf; if (bOwner) - return CheckOwnerPassword(password, size, key, key_len); + return CheckOwnerPassword(password, key, key_len); - return CheckUserPassword(password, size, false, key, key_len) || - CheckUserPassword(password, size, true, key, key_len); + return CheckUserPassword(password, false, key, key_len) || + CheckUserPassword(password, true, key, key_len); } -bool CPDF_SecurityHandler::CheckUserPassword(const uint8_t* password, - uint32_t pass_size, + +bool CPDF_SecurityHandler::CheckUserPassword(const ByteString& password, bool bIgnoreEncryptMeta, uint8_t* key, int32_t key_len) { - CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, - bIgnoreEncryptMeta, m_pParser->GetIDArray()); - CFX_ByteString ukey = - m_pEncryptDict ? m_pEncryptDict->GetStringFor("U") : CFX_ByteString(); + CalcEncryptKey(m_pEncryptDict.Get(), password, key, key_len, + bIgnoreEncryptMeta, m_FileId); + ByteString ukey = + m_pEncryptDict ? m_pEncryptDict->GetStringFor("U") : ByteString(); if (ukey.GetLength() < 16) { return false; } + uint8_t ukeybuf[32]; if (m_Revision == 2) { - FXSYS_memcpy(ukeybuf, defpasscode, 32); + memcpy(ukeybuf, defpasscode, 32); CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len); } else { uint8_t test[32], tmpkey[32]; @@ -433,9 +426,9 @@ bool CPDF_SecurityHandler::CheckUserPassword(const uint8_t* password, if (copy_len > (uint32_t)ukey.GetLength()) { copy_len = ukey.GetLength(); } - FXSYS_memset(test, 0, sizeof(test)); - FXSYS_memset(tmpkey, 0, sizeof(tmpkey)); - FXSYS_memcpy(test, ukey.c_str(), copy_len); + memset(test, 0, sizeof(test)); + memset(tmpkey, 0, sizeof(tmpkey)); + memcpy(test, ukey.c_str(), copy_len); for (int32_t i = 19; i >= 0; i--) { for (int j = 0; j < key_len; j++) tmpkey[j] = key[j] ^ static_cast(i); @@ -444,26 +437,24 @@ bool CPDF_SecurityHandler::CheckUserPassword(const uint8_t* password, CRYPT_md5_context md5; CRYPT_MD5Start(&md5); CRYPT_MD5Update(&md5, defpasscode, 32); - CPDF_Array* pIdArray = m_pParser->GetIDArray(); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetStringAt(0); - CRYPT_MD5Update(&md5, (uint8_t*)id.c_str(), id.GetLength()); + if (!m_FileId.IsEmpty()) { + CRYPT_MD5Update(&md5, (uint8_t*)m_FileId.c_str(), m_FileId.GetLength()); } CRYPT_MD5Finish(&md5, ukeybuf); - return FXSYS_memcmp(test, ukeybuf, 16) == 0; + return memcmp(test, ukeybuf, 16) == 0; } - if (FXSYS_memcmp((void*)ukey.c_str(), ukeybuf, 16) == 0) { - return true; - } - return false; + return memcmp(ukey.c_str(), ukeybuf, 16) == 0; } -CFX_ByteString CPDF_SecurityHandler::GetUserPassword(const uint8_t* owner_pass, - uint32_t pass_size, - int32_t key_len) { - CFX_ByteString okey = m_pEncryptDict->GetStringFor("O"); + +ByteString CPDF_SecurityHandler::GetUserPassword( + const ByteString& owner_password, + int32_t key_len) const { + ByteString okey = m_pEncryptDict->GetStringFor("O"); uint8_t passcode[32]; for (uint32_t i = 0; i < 32; i++) { - passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size]; + passcode[i] = i < owner_password.GetLength() + ? owner_password[i] + : defpasscode[i - owner_password.GetLength()]; } uint8_t digest[16]; CRYPT_MD5Generate(passcode, 32, digest); @@ -473,25 +464,25 @@ CFX_ByteString CPDF_SecurityHandler::GetUserPassword(const uint8_t* owner_pass, } } uint8_t enckey[32]; - FXSYS_memset(enckey, 0, sizeof(enckey)); + memset(enckey, 0, sizeof(enckey)); uint32_t copy_len = key_len; if (copy_len > sizeof(digest)) { copy_len = sizeof(digest); } - FXSYS_memcpy(enckey, digest, copy_len); + memcpy(enckey, digest, copy_len); int okeylen = okey.GetLength(); if (okeylen > 32) { okeylen = 32; } uint8_t okeybuf[64]; - FXSYS_memset(okeybuf, 0, sizeof(okeybuf)); - FXSYS_memcpy(okeybuf, okey.c_str(), okeylen); + memset(okeybuf, 0, sizeof(okeybuf)); + memcpy(okeybuf, okey.c_str(), okeylen); if (m_Revision == 2) { CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len); } else { for (int32_t i = 19; i >= 0; i--) { uint8_t tempkey[32]; - FXSYS_memset(tempkey, 0, sizeof(tempkey)); + memset(tempkey, 0, sizeof(tempkey)); for (int j = 0; j < m_KeyLen; j++) tempkey[j] = enckey[j] ^ static_cast(i); CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len); @@ -501,53 +492,49 @@ CFX_ByteString CPDF_SecurityHandler::GetUserPassword(const uint8_t* owner_pass, while (len && defpasscode[len - 1] == okeybuf[len - 1]) { len--; } - return CFX_ByteString(okeybuf, len); + return ByteString(okeybuf, len); } -bool CPDF_SecurityHandler::CheckOwnerPassword(const uint8_t* password, - uint32_t pass_size, + +bool CPDF_SecurityHandler::CheckOwnerPassword(const ByteString& password, uint8_t* key, int32_t key_len) { - CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len); - if (CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), false, key, - key_len)) { + ByteString user_pass = GetUserPassword(password, key_len); + if (CheckUserPassword(user_pass, false, key, key_len)) return true; - } - return CheckUserPassword(user_pass.raw_str(), user_pass.GetLength(), true, - key, key_len); + return CheckUserPassword(user_pass, true, key, key_len); } bool CPDF_SecurityHandler::IsMetadataEncrypted() const { return m_pEncryptDict->GetBooleanFor("EncryptMetadata", true); } -void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - bool bDefault, - uint32_t type) { - int cipher = 0, key_len = 0; - if (!LoadDict(pEncryptDict, type, cipher, key_len)) { +void CPDF_SecurityHandler::OnCreateInternal(CPDF_Dictionary* pEncryptDict, + const CPDF_Array* pIdArray, + const ByteString& user_password, + const ByteString& owner_password, + bool bDefault) { + ASSERT(pEncryptDict); + + int cipher = 0; + int key_len = 0; + if (!LoadDict(pEncryptDict, cipher, key_len)) { return; } - if (bDefault && (!owner_pass || owner_size == 0)) { - owner_pass = user_pass; - owner_size = user_size; - } + ByteString owner_password_copy = owner_password; + if (bDefault && owner_password.IsEmpty()) + owner_password_copy = user_password; + if (m_Revision >= 5) { int t = (int)time(nullptr); - CRYPT_sha256_context sha; + CRYPT_sha2_context sha; CRYPT_SHA256Start(&sha); CRYPT_SHA256Update(&sha, (uint8_t*)&t, sizeof t); CRYPT_SHA256Update(&sha, m_EncryptKey, 32); CRYPT_SHA256Update(&sha, (uint8_t*)"there", 5); CRYPT_SHA256Finish(&sha, m_EncryptKey); - AES256_SetPassword(pEncryptDict, user_pass, user_size, false, m_EncryptKey); + AES256_SetPassword(pEncryptDict, user_password, false, m_EncryptKey); if (bDefault) { - AES256_SetPassword(pEncryptDict, owner_pass, owner_size, true, - m_EncryptKey); + AES256_SetPassword(pEncryptDict, owner_password_copy, true, m_EncryptKey); AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBooleanFor("EncryptMetadata", true), m_EncryptKey); @@ -557,8 +544,9 @@ void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, if (bDefault) { uint8_t passcode[32]; for (uint32_t i = 0; i < 32; i++) { - passcode[i] = - i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; + passcode[i] = i < owner_password_copy.GetLength() + ? owner_password_copy[i] + : defpasscode[i - owner_password_copy.GetLength()]; } uint8_t digest[16]; CRYPT_MD5Generate(passcode, 32, digest); @@ -567,9 +555,11 @@ void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CRYPT_MD5Generate(digest, 16, digest); } uint8_t enckey[32]; - FXSYS_memcpy(enckey, digest, key_len); + memcpy(enckey, digest, key_len); for (uint32_t i = 0; i < 32; i++) { - passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; + passcode[i] = i < user_password.GetLength() + ? user_password[i] + : defpasscode[i - user_password.GetLength()]; } CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); uint8_t tempkey[32]; @@ -580,24 +570,27 @@ void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); } } - pEncryptDict->SetNewFor("O", CFX_ByteString(passcode, 32), - false); + pEncryptDict->SetNewFor("O", ByteString(passcode, 32), false); + } + + ByteString fileId; + if (pIdArray) { + fileId = pIdArray->GetStringAt(0); } - CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey, - key_len, false, pIdArray); + + CalcEncryptKey(m_pEncryptDict.Get(), user_password, m_EncryptKey, key_len, + false, fileId); if (m_Revision < 3) { uint8_t tempbuf[32]; - FXSYS_memcpy(tempbuf, defpasscode, 32); + memcpy(tempbuf, defpasscode, 32); CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); - pEncryptDict->SetNewFor("U", CFX_ByteString(tempbuf, 32), - false); + pEncryptDict->SetNewFor("U", ByteString(tempbuf, 32), false); } else { CRYPT_md5_context md5; CRYPT_MD5Start(&md5); CRYPT_MD5Update(&md5, defpasscode, 32); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetStringAt(0); - CRYPT_MD5Update(&md5, (uint8_t*)id.c_str(), id.GetLength()); + if (!fileId.IsEmpty()) { + CRYPT_MD5Update(&md5, (uint8_t*)fileId.c_str(), fileId.GetLength()); } uint8_t digest[32]; CRYPT_MD5Finish(&md5, digest); @@ -610,31 +603,27 @@ void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); } CRYPT_MD5Generate(digest, 16, digest + 16); - pEncryptDict->SetNewFor("U", CFX_ByteString(digest, 32), - false); + pEncryptDict->SetNewFor("U", ByteString(digest, 32), false); } } + void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - uint32_t type) { - OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, - true, type); + const CPDF_Array* pIdArray, + const ByteString& user_password, + const ByteString& owner_password) { + OnCreateInternal(pEncryptDict, pIdArray, user_password, owner_password, true); + InitCryptoHandler(); } + void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - uint32_t type) { - OnCreate(pEncryptDict, pIdArray, user_pass, user_size, nullptr, 0, false, - type); + const CPDF_Array* pIdArray, + const ByteString& user_password) { + OnCreateInternal(pEncryptDict, pIdArray, user_password, ByteString(), false); + InitCryptoHandler(); } + void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, - const uint8_t* password, - uint32_t size, + const ByteString& password, bool bOwner, const uint8_t* key) { CRYPT_sha1_context sha; @@ -645,45 +634,45 @@ void CPDF_SecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, uint8_t digest[20]; CRYPT_SHA1Finish(&sha, digest); - CFX_ByteString ukey = pEncryptDict->GetStringFor("U"); - CRYPT_sha256_context sha2; + ByteString ukey = pEncryptDict->GetStringFor("U"); + CRYPT_sha2_context sha2; uint8_t digest1[48]; if (m_Revision >= 6) { - Revision6_Hash(password, size, digest, bOwner ? ukey.raw_str() : nullptr, + Revision6_Hash(password, digest, bOwner ? ukey.raw_str() : nullptr, digest1); } else { CRYPT_SHA256Start(&sha2); - CRYPT_SHA256Update(&sha2, password, size); + CRYPT_SHA256Update(&sha2, password.raw_str(), password.GetLength()); CRYPT_SHA256Update(&sha2, digest, 8); if (bOwner) { CRYPT_SHA256Update(&sha2, ukey.raw_str(), ukey.GetLength()); } CRYPT_SHA256Finish(&sha2, digest1); } - FXSYS_memcpy(digest1 + 32, digest, 16); + memcpy(digest1 + 32, digest, 16); pEncryptDict->SetNewFor(bOwner ? "O" : "U", - CFX_ByteString(digest1, 48), false); + ByteString(digest1, 48), false); if (m_Revision >= 6) { - Revision6_Hash(password, size, digest + 8, - bOwner ? ukey.raw_str() : nullptr, digest1); + Revision6_Hash(password, digest + 8, bOwner ? ukey.raw_str() : nullptr, + digest1); } else { CRYPT_SHA256Start(&sha2); - CRYPT_SHA256Update(&sha2, password, size); + CRYPT_SHA256Update(&sha2, password.raw_str(), password.GetLength()); CRYPT_SHA256Update(&sha2, digest + 8, 8); if (bOwner) { CRYPT_SHA256Update(&sha2, ukey.raw_str(), ukey.GetLength()); } CRYPT_SHA256Finish(&sha2, digest1); } - uint8_t* aes = FX_Alloc(uint8_t, 2048); - CRYPT_AESSetKey(aes, 16, digest1, 32, true); + CRYPT_aes_context aes; + memset(&aes, 0, sizeof(aes)); + CRYPT_AESSetKey(&aes, 16, digest1, 32, true); uint8_t iv[16]; - FXSYS_memset(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, digest1, key, 32); - FX_Free(aes); + memset(iv, 0, 16); + CRYPT_AESSetIV(&aes, iv); + CRYPT_AESEncrypt(&aes, digest1, key, 32); pEncryptDict->SetNewFor(bOwner ? "OE" : "UE", - CFX_ByteString(digest1, 32), false); + ByteString(digest1, 32), false); } void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, @@ -703,13 +692,21 @@ void CPDF_SecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, buf[9] = 'a'; buf[10] = 'd'; buf[11] = 'b'; - uint8_t* aes = FX_Alloc(uint8_t, 2048); - CRYPT_AESSetKey(aes, 16, key, 32, true); - uint8_t iv[16], buf1[16]; - FXSYS_memset(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, buf1, buf, 16); - FX_Free(aes); - pEncryptDict->SetNewFor("Perms", CFX_ByteString(buf1, 16), - false); + + CRYPT_aes_context aes; + memset(&aes, 0, sizeof(aes)); + CRYPT_AESSetKey(&aes, 16, key, 32, true); + + uint8_t iv[16]; + memset(iv, 0, 16); + CRYPT_AESSetIV(&aes, iv); + + uint8_t buf1[16]; + CRYPT_AESEncrypt(&aes, buf1, buf, 16); + pEncryptDict->SetNewFor("Perms", ByteString(buf1, 16), false); +} + +void CPDF_SecurityHandler::InitCryptoHandler() { + m_pCryptoHandler = + pdfium::MakeUnique(m_Cipher, m_EncryptKey, m_KeyLen); } diff --git a/core/fpdfapi/parser/cpdf_security_handler.h b/core/fpdfapi/parser/cpdf_security_handler.h index 1a41b67195e0e8cef1c8793d946f090bb55aa660..eb9574386e8177e70f94896efc125d0ca5f61e31 100644 --- a/core/fpdfapi/parser/cpdf_security_handler.h +++ b/core/fpdfapi/parser/cpdf_security_handler.h @@ -7,6 +7,8 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_SECURITY_HANDLER_H_ #define CORE_FPDFAPI_PARSER_CPDF_SECURITY_HANDLER_H_ +#include + #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" @@ -15,8 +17,6 @@ #define FXCIPHER_AES 2 #define FXCIPHER_AES2 3 -#define PDF_ENCRYPT_CONTENT 0 - class CPDF_Array; class CPDF_CryptoHandler; class CPDF_Dictionary; @@ -27,84 +27,75 @@ class CPDF_SecurityHandler { CPDF_SecurityHandler(); ~CPDF_SecurityHandler(); - bool OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict); - uint32_t GetPermissions(); - bool GetCryptInfo(int& cipher, const uint8_t*& buffer, int& keylen); - bool IsMetadataEncrypted() const; - CPDF_CryptoHandler* CreateCryptoHandler(); - + bool OnInit(const CPDF_Dictionary* pEncryptDict, + const CPDF_Array* pIdArray, + const ByteString& password); void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - uint32_t type = PDF_ENCRYPT_CONTENT); - + const CPDF_Array* pIdArray, + const ByteString& user_password, + const ByteString& owner_password); void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - uint32_t type = PDF_ENCRYPT_CONTENT); - - CFX_ByteString GetUserPassword(const uint8_t* owner_pass, - uint32_t pass_size, - int32_t key_len); - bool CheckPassword(const uint8_t* password, - uint32_t pass_size, + const CPDF_Array* pIdArray, + const ByteString& user_password); + + uint32_t GetPermissions() const; + bool IsMetadataEncrypted() const; + + ByteString GetUserPassword(const ByteString& owner_password, + int32_t key_len) const; + bool CheckPassword(const ByteString& user_password, bool bOwner, uint8_t* key, int key_len); + CPDF_CryptoHandler* GetCryptoHandler() const { + return m_pCryptoHandler.get(); + } + private: - bool LoadDict(CPDF_Dictionary* pEncryptDict); - bool LoadDict(CPDF_Dictionary* pEncryptDict, - uint32_t type, + bool LoadDict(const CPDF_Dictionary* pEncryptDict); + bool LoadDict(const CPDF_Dictionary* pEncryptDict, int& cipher, int& key_len); - bool CheckUserPassword(const uint8_t* password, - uint32_t pass_size, + bool CheckUserPassword(const ByteString& password, bool bIgnoreEncryptMeta, uint8_t* key, int32_t key_len); - bool CheckOwnerPassword(const uint8_t* password, - uint32_t pass_size, + bool CheckOwnerPassword(const ByteString& password, uint8_t* key, int32_t key_len); - bool AES256_CheckPassword(const uint8_t* password, - uint32_t size, + bool AES256_CheckPassword(const ByteString& password, bool bOwner, uint8_t* key); void AES256_SetPassword(CPDF_Dictionary* pEncryptDict, - const uint8_t* password, - uint32_t size, + const ByteString& password, bool bOwner, const uint8_t* key); void AES256_SetPerms(CPDF_Dictionary* pEncryptDict, uint32_t permission, bool bEncryptMetadata, const uint8_t* key); - void OnCreate(CPDF_Dictionary* pEncryptDict, - CPDF_Array* pIdArray, - const uint8_t* user_pass, - uint32_t user_size, - const uint8_t* owner_pass, - uint32_t owner_size, - bool bDefault, - uint32_t type); - bool CheckSecurity(int32_t key_len); + void OnCreateInternal(CPDF_Dictionary* pEncryptDict, + const CPDF_Array* pIdArray, + const ByteString& user_password, + const ByteString& owner_password, + bool bDefault); + bool CheckSecurity(const ByteString& password); + + void InitCryptoHandler(); int m_Version; int m_Revision; - CPDF_Parser* m_pParser; - CPDF_Dictionary* m_pEncryptDict; + UnownedPtr m_pEncryptDict; + ByteString m_FileId; uint32_t m_Permissions; int m_Cipher; uint8_t m_EncryptKey[32]; int m_KeyLen; bool m_bOwnerUnlocked; + std::unique_ptr m_pCryptoHandler; }; #endif // CORE_FPDFAPI_PARSER_CPDF_SECURITY_HANDLER_H_ diff --git a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp index c6c6217e2c730d719f72314cf79a8b62dcc628c7..a1d5fda510de9424762dff4bf437cddb3024626f 100644 --- a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp +++ b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp @@ -2,6 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + +#include "core/fxcrt/fx_system.h" +#include "public/fpdf_edit.h" +#include "public/fpdf_save.h" +#include "public/fpdfview.h" #include "testing/embedder_test.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,7 +19,7 @@ TEST_F(CPDFSecurityHandlerEmbeddertest, Unencrypted) { } TEST_F(CPDFSecurityHandlerEmbeddertest, UnencryptedWithPassword) { - ASSERT_TRUE(OpenDocument("about_blank.pdf", "foobar")); + ASSERT_TRUE(OpenDocumentWithPassword("about_blank.pdf", "foobar")); EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocPermissions(document())); } @@ -22,33 +28,82 @@ TEST_F(CPDFSecurityHandlerEmbeddertest, NoPassword) { } TEST_F(CPDFSecurityHandlerEmbeddertest, BadPassword) { - EXPECT_FALSE(OpenDocument("encrypted.pdf", "tiger")); + EXPECT_FALSE(OpenDocumentWithPassword("encrypted.pdf", "tiger")); } TEST_F(CPDFSecurityHandlerEmbeddertest, UserPassword) { - ASSERT_TRUE(OpenDocument("encrypted.pdf", "1234")); + ASSERT_TRUE(OpenDocumentWithPassword("encrypted.pdf", "1234")); EXPECT_EQ(0xFFFFF2C0, FPDF_GetDocPermissions(document())); } TEST_F(CPDFSecurityHandlerEmbeddertest, OwnerPassword) { - ASSERT_TRUE(OpenDocument("encrypted.pdf", "5678")); + ASSERT_TRUE(OpenDocumentWithPassword("encrypted.pdf", "5678")); EXPECT_EQ(0xFFFFFFFC, FPDF_GetDocPermissions(document())); } +TEST_F(CPDFSecurityHandlerEmbeddertest, PasswordAfterGenerateSave) { +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ + const char md5[] = "7048dca58e2ed8f93339008b91e4eb4e"; +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5[] = "6951b6c9891dfe0332a5b1983e484400"; +#else + const char md5[] = "a5dde3c6c37b8716b9b369a03752a728"; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ + { + ASSERT_TRUE(OpenDocumentWithOptions("encrypted.pdf", "5678", true)); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20); + ASSERT_TRUE(red_rect); + EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255)); + EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(page, red_rect); + FPDF_BITMAP page_bitmap = RenderPage(page); + CompareBitmap(page_bitmap, 612, 792, md5); + FPDFBitmap_Destroy(page_bitmap); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + SetWholeFileAvailable(); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + UnloadPage(page); + } + std::string new_file = GetString(); + FPDF_FILEACCESS file_access; + memset(&file_access, 0, sizeof(file_access)); + file_access.m_FileLen = new_file.size(); + file_access.m_GetBlock = GetBlockFromString; + file_access.m_Param = &new_file; + EXPECT_FALSE(FPDF_LoadCustomDocument(&file_access, nullptr)); + + struct { + const char* password; + const unsigned long permissions; + } tests[] = {{"1234", 0xFFFFF2C0}, {"5678", 0xFFFFFFFC}}; + + for (const auto& test : tests) { + OpenSavedDocument(test.password); + FPDF_PAGE page = LoadSavedPage(0); + VerifySavedRendering(page, 612, 792, md5); + EXPECT_EQ(test.permissions, FPDF_GetDocPermissions(m_SavedDocument)); + + CloseSavedPage(page); + CloseSavedDocument(); + } +} + TEST_F(CPDFSecurityHandlerEmbeddertest, NoPasswordVersion5) { ASSERT_FALSE(OpenDocument("bug_644.pdf")); } TEST_F(CPDFSecurityHandlerEmbeddertest, BadPasswordVersion5) { - ASSERT_FALSE(OpenDocument("bug_644.pdf", "tiger")); + ASSERT_FALSE(OpenDocumentWithPassword("bug_644.pdf", "tiger")); } TEST_F(CPDFSecurityHandlerEmbeddertest, OwnerPasswordVersion5) { - ASSERT_TRUE(OpenDocument("bug_644.pdf", "a")); + ASSERT_TRUE(OpenDocumentWithPassword("bug_644.pdf", "a")); EXPECT_EQ(0xFFFFFFFC, FPDF_GetDocPermissions(document())); } TEST_F(CPDFSecurityHandlerEmbeddertest, UserPasswordVersion5) { - ASSERT_TRUE(OpenDocument("bug_644.pdf", "b")); + ASSERT_TRUE(OpenDocumentWithPassword("bug_644.pdf", "b")); EXPECT_EQ(0xFFFFFFFC, FPDF_GetDocPermissions(document())); } diff --git a/core/fpdfapi/parser/cpdf_simple_parser.cpp b/core/fpdfapi/parser/cpdf_simple_parser.cpp index 650c216e0591931660f67fe9641419db4c463c2a..b49f8423c34f3af4bbbdeed24bbcf7b364f2ddd1 100644 --- a/core/fpdfapi/parser/cpdf_simple_parser.cpp +++ b/core/fpdfapi/parser/cpdf_simple_parser.cpp @@ -11,20 +11,20 @@ CPDF_SimpleParser::CPDF_SimpleParser(const uint8_t* pData, uint32_t dwSize) : m_pData(pData), m_dwSize(dwSize), m_dwCurPos(0) {} -CPDF_SimpleParser::CPDF_SimpleParser(const CFX_ByteStringC& str) +CPDF_SimpleParser::CPDF_SimpleParser(const ByteStringView& str) : m_pData(str.raw_str()), m_dwSize(str.GetLength()), m_dwCurPos(0) {} -void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& dwSize) { - pStart = nullptr; - dwSize = 0; +std::pair CPDF_SimpleParser::ParseWord() { + const uint8_t* pStart = nullptr; + uint8_t dwSize = 0; uint8_t ch; while (1) { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; while (PDFCharIsWhitespace(ch)) { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; } @@ -33,7 +33,7 @@ void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& dwSize) { while (1) { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; if (PDFCharIsLineEnding(ch)) break; @@ -46,19 +46,19 @@ void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& dwSize) { if (ch == '/') { while (1) { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { m_dwCurPos--; dwSize = m_dwCurPos - start_pos; - return; + return std::make_pair(pStart, dwSize); } } } else { dwSize = 1; if (ch == '<') { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; if (ch == '<') dwSize = 2; @@ -66,7 +66,7 @@ void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& dwSize) { m_dwCurPos--; } else if (ch == '>') { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; if (ch == '>') dwSize = 2; @@ -74,13 +74,13 @@ void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& dwSize) { m_dwCurPos--; } } - return; + return std::make_pair(pStart, dwSize); } dwSize = 1; while (1) { if (m_dwSize <= m_dwCurPos) - return; + return std::make_pair(pStart, dwSize); ch = m_pData[m_dwCurPos++]; if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { @@ -89,12 +89,13 @@ void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& dwSize) { } dwSize++; } + return std::make_pair(pStart, dwSize); } -CFX_ByteStringC CPDF_SimpleParser::GetWord() { +ByteStringView CPDF_SimpleParser::GetWord() { const uint8_t* pStart; uint32_t dwSize; - ParseWord(pStart, dwSize); + std::tie(pStart, dwSize) = ParseWord(); if (dwSize == 1 && pStart[0] == '<') { while (m_dwCurPos < m_dwSize && m_pData[m_dwCurPos] != '>') { m_dwCurPos++; @@ -102,8 +103,8 @@ CFX_ByteStringC CPDF_SimpleParser::GetWord() { if (m_dwCurPos < m_dwSize) { m_dwCurPos++; } - return CFX_ByteStringC(pStart, - (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); + return ByteStringView(pStart, + static_cast(m_dwCurPos - (pStart - m_pData))); } if (dwSize == 1 && pStart[0] == '(') { int level = 1; @@ -130,13 +131,13 @@ CFX_ByteStringC CPDF_SimpleParser::GetWord() { if (m_dwCurPos < m_dwSize) { m_dwCurPos++; } - return CFX_ByteStringC(pStart, - (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); + return ByteStringView(pStart, + static_cast(m_dwCurPos - (pStart - m_pData))); } - return CFX_ByteStringC(pStart, dwSize); + return ByteStringView(pStart, dwSize); } -bool CPDF_SimpleParser::FindTagParamFromStart(const CFX_ByteStringC& token, +bool CPDF_SimpleParser::FindTagParamFromStart(const ByteStringView& token, int nParams) { nParams++; uint32_t* pBuf = FX_Alloc(uint32_t, nParams); @@ -152,7 +153,7 @@ bool CPDF_SimpleParser::FindTagParamFromStart(const CFX_ByteStringC& token, if (buf_count > nParams) { buf_count = nParams; } - CFX_ByteStringC word = GetWord(); + ByteStringView word = GetWord(); if (word.IsEmpty()) { FX_Free(pBuf); return false; diff --git a/core/fpdfapi/parser/cpdf_simple_parser.h b/core/fpdfapi/parser/cpdf_simple_parser.h index 0ff698566087579d4b7ae81f01cd4ca24cb61414..659039e6fa84564e2ffcce2d1923f6f384c8c2fe 100644 --- a/core/fpdfapi/parser/cpdf_simple_parser.h +++ b/core/fpdfapi/parser/cpdf_simple_parser.h @@ -7,25 +7,27 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_SIMPLE_PARSER_H_ #define CORE_FPDFAPI_PARSER_CPDF_SIMPLE_PARSER_H_ +#include + #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" class CPDF_SimpleParser { public: CPDF_SimpleParser(const uint8_t* pData, uint32_t dwSize); - explicit CPDF_SimpleParser(const CFX_ByteStringC& str); + explicit CPDF_SimpleParser(const ByteStringView& str); - CFX_ByteStringC GetWord(); + ByteStringView GetWord(); // Find the token and its |nParams| parameters from the start of data, // and move the current position to the start of those parameters. - bool FindTagParamFromStart(const CFX_ByteStringC& token, int nParams); + bool FindTagParamFromStart(const ByteStringView& token, int nParams); // For testing only. uint32_t GetCurPos() const { return m_dwCurPos; } private: - void ParseWord(const uint8_t*& pStart, uint32_t& dwSize); + std::pair ParseWord(); const uint8_t* m_pData; uint32_t m_dwSize; diff --git a/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp index 5f56b948cd4904dc044ca6a31e7644f40deb5faa..e8d3b7142ac9235b43af93595d5b79a31ef75681 100644 --- a/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp @@ -7,12 +7,11 @@ #include #include "core/fpdfapi/parser/fpdf_parser_utility.h" -#include "core/fxcrt/fx_basic.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" TEST(SimpleParserTest, GetWord) { - pdfium::StrFuncTestData test_data[] = { + static const pdfium::StrFuncTestData test_data[] = { // Empty src string. STR_IN_OUT_CASE("", ""), // Content with whitespaces only. @@ -51,16 +50,18 @@ TEST(SimpleParserTest, GetWord) { for (size_t i = 0; i < FX_ArraySize(test_data); ++i) { const pdfium::StrFuncTestData& data = test_data[i]; CPDF_SimpleParser parser(data.input, data.input_size); - CFX_ByteStringC word = parser.GetWord(); - EXPECT_EQ(std::string(reinterpret_cast(data.expected), - data.expected_size), - std::string(word.c_str(), word.GetLength())) + ByteStringView word = parser.GetWord(); + EXPECT_EQ(data.expected_size, word.GetLength()) << " for case " << i; + if (data.expected_size != word.GetLength()) + continue; + EXPECT_EQ( + 0, memcmp(data.expected, word.unterminated_c_str(), data.expected_size)) << " for case " << i; } } TEST(SimpleParserTest, FindTagParamFromStart) { - struct FindTagTestStruct { + static const struct FindTagTestStruct { const unsigned char* input; unsigned int input_size; const char* token; diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp index d62b45641b33cf025a7d89a4b9aee5c3b76d9aad..074e747a7822c8b3d1154fa0c6dca67296553c59 100644 --- a/core/fpdfapi/parser/cpdf_stream.cpp +++ b/core/fpdfapi/parser/cpdf_stream.cpp @@ -12,6 +12,7 @@ #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/numerics/safe_conversions.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" @@ -21,7 +22,9 @@ CPDF_Stream::CPDF_Stream() {} CPDF_Stream::CPDF_Stream(std::unique_ptr pData, uint32_t size, std::unique_ptr pDict) - : m_dwSize(size), m_pDict(std::move(pDict)), m_pDataBuf(std::move(pData)) {} + : m_pDict(std::move(pDict)) { + SetData(std::move(pData), size); +} CPDF_Stream::~CPDF_Stream() { m_ObjNum = kInvalidObjNum; @@ -53,18 +56,11 @@ void CPDF_Stream::InitStream(const uint8_t* pData, uint32_t size, std::unique_ptr pDict) { m_pDict = std::move(pDict); - m_bMemoryBased = true; - m_pFile = nullptr; - m_pDataBuf.reset(FX_Alloc(uint8_t, size)); - if (pData) - FXSYS_memcpy(m_pDataBuf.get(), pData, size); - m_dwSize = size; - if (m_pDict) - m_pDict->SetNewFor("Length", static_cast(m_dwSize)); + SetData(pData, size); } void CPDF_Stream::InitStreamFromFile( - const CFX_RetainPtr& pFile, + const RetainPtr& pFile, std::unique_ptr pDict) { m_pDict = std::move(pDict); m_bMemoryBased = false; @@ -83,31 +79,54 @@ std::unique_ptr CPDF_Stream::CloneNonCyclic( bool bDirect, std::set* pVisited) const { pVisited->insert(this); - CPDF_StreamAcc acc; - acc.LoadAllData(this, true); + auto pAcc = pdfium::MakeRetain(this); + pAcc->LoadAllDataRaw(); - uint32_t streamSize = acc.GetSize(); + uint32_t streamSize = pAcc->GetSize(); CPDF_Dictionary* pDict = GetDict(); std::unique_ptr pNewDict; if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) { pNewDict = ToDictionary( static_cast(pDict)->CloneNonCyclic(bDirect, pVisited)); } - return pdfium::MakeUnique(acc.DetachData(), streamSize, + return pdfium::MakeUnique(pAcc->DetachData(), streamSize, std::move(pNewDict)); } +void CPDF_Stream::SetDataAndRemoveFilter(const uint8_t* pData, uint32_t size) { + SetData(pData, size); + m_pDict->RemoveFor("Filter"); + m_pDict->RemoveFor("DecodeParms"); +} + +void CPDF_Stream::SetDataAndRemoveFilter(std::ostringstream* stream) { + SetDataAndRemoveFilter( + reinterpret_cast(stream->str().c_str()), stream->tellp()); +} + void CPDF_Stream::SetData(const uint8_t* pData, uint32_t size) { + std::unique_ptr data_copy; + if (pData) { + data_copy.reset(FX_Alloc(uint8_t, size)); + memcpy(data_copy.get(), pData, size); + } + SetData(std::move(data_copy), size); +} + +void CPDF_Stream::SetData(std::unique_ptr pData, + uint32_t size) { m_bMemoryBased = true; - m_pDataBuf.reset(FX_Alloc(uint8_t, size)); - if (pData) - FXSYS_memcpy(m_pDataBuf.get(), pData, size); + m_pFile = nullptr; + m_pDataBuf = std::move(pData); m_dwSize = size; if (!m_pDict) m_pDict = pdfium::MakeUnique(); m_pDict->SetNewFor("Length", static_cast(size)); - m_pDict->RemoveFor("Filter"); - m_pDict->RemoveFor("DecodeParms"); +} + +void CPDF_Stream::SetData(std::ostringstream* stream) { + SetData(reinterpret_cast(stream->str().c_str()), + stream->tellp()); } bool CPDF_Stream::ReadRawData(FX_FILESIZE offset, @@ -117,7 +136,7 @@ bool CPDF_Stream::ReadRawData(FX_FILESIZE offset, return m_pFile->ReadBlock(buf, offset, size); if (m_pDataBuf) - FXSYS_memcpy(buf, m_pDataBuf.get() + offset, size); + memcpy(buf, m_pDataBuf.get() + offset, size); return true; } @@ -126,8 +145,18 @@ bool CPDF_Stream::HasFilter() const { return m_pDict && m_pDict->KeyExist("Filter"); } -CFX_WideString CPDF_Stream::GetUnicodeText() const { - CPDF_StreamAcc stream; - stream.LoadAllData(this, false); - return PDF_DecodeText(stream.GetData(), stream.GetSize()); +WideString CPDF_Stream::GetUnicodeText() const { + auto pAcc = pdfium::MakeRetain(this); + pAcc->LoadAllDataFiltered(); + return PDF_DecodeText(pAcc->GetData(), pAcc->GetSize()); +} + +bool CPDF_Stream::WriteTo(IFX_ArchiveStream* archive) const { + if (!GetDict()->WriteTo(archive) || !archive->WriteString("stream\r\n")) + return false; + + auto pAcc = pdfium::MakeRetain(this); + pAcc->LoadAllDataRaw(); + return archive->WriteBlock(pAcc->GetData(), pAcc->GetSize()) && + archive->WriteString("\r\nendstream"); } diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h index 902cd75365ce914cb67664b60290663c4e577c55..f8b09af7e2427f8a671845021dd9128cd5cc2049 100644 --- a/core/fpdfapi/parser/cpdf_stream.h +++ b/core/fpdfapi/parser/cpdf_stream.h @@ -9,10 +9,11 @@ #include #include +#include #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_stream.h" class CPDF_Stream : public CPDF_Object { public: @@ -29,21 +30,28 @@ class CPDF_Stream : public CPDF_Object { Type GetType() const override; std::unique_ptr Clone() const override; CPDF_Dictionary* GetDict() const override; - CFX_WideString GetUnicodeText() const override; + WideString GetUnicodeText() const override; bool IsStream() const override; CPDF_Stream* AsStream() override; const CPDF_Stream* AsStream() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; uint32_t GetRawSize() const { return m_dwSize; } uint8_t* GetRawData() const { return m_pDataBuf.get(); } - // Does not takes onwership of |pData|, copies into internally-owned buffer. + // Does not takes ownership of |pData|, copies into internally-owned buffer. void SetData(const uint8_t* pData, uint32_t size); + void SetData(std::unique_ptr pData, uint32_t size); + void SetData(std::ostringstream* stream); + // Set data and remove "Filter" and "DecodeParms" fields from stream + // dictionary. + void SetDataAndRemoveFilter(const uint8_t* pData, uint32_t size); + void SetDataAndRemoveFilter(std::ostringstream* stream); void InitStream(const uint8_t* pData, uint32_t size, std::unique_ptr pDict); - void InitStreamFromFile(const CFX_RetainPtr& pFile, + void InitStreamFromFile(const RetainPtr& pFile, std::unique_ptr pDict); bool ReadRawData(FX_FILESIZE start_pos, @@ -62,7 +70,7 @@ class CPDF_Stream : public CPDF_Object { uint32_t m_dwSize = 0; std::unique_ptr m_pDict; std::unique_ptr m_pDataBuf; - CFX_RetainPtr m_pFile; + RetainPtr m_pFile; }; inline CPDF_Stream* ToStream(CPDF_Object* obj) { diff --git a/core/fpdfapi/parser/cpdf_stream_acc.cpp b/core/fpdfapi/parser/cpdf_stream_acc.cpp index 423de7c571d05f05ee81e3f2d3326ecd6d4b6dbd..d115b48226aa63d5849b79e51c436926156e5148 100644 --- a/core/fpdfapi/parser/cpdf_stream_acc.cpp +++ b/core/fpdfapi/parser/cpdf_stream_acc.cpp @@ -8,64 +8,72 @@ #include "core/fpdfapi/parser/fpdf_parser_decode.h" -CPDF_StreamAcc::CPDF_StreamAcc() - : m_pData(nullptr), - m_dwSize(0), - m_bNewBuf(false), - m_pImageParam(nullptr), - m_pStream(nullptr), - m_pSrcData(nullptr) {} - -void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, - bool bRawAccess, +CPDF_StreamAcc::CPDF_StreamAcc(const CPDF_Stream* pStream) + : m_pStream(pStream) {} + +CPDF_StreamAcc::~CPDF_StreamAcc() { + if (m_bNewBuf) + FX_Free(m_pData); + FX_Free(m_pSrcData); +} + +void CPDF_StreamAcc::LoadAllData(bool bRawAccess, uint32_t estimated_size, bool bImageAcc) { - if (!pStream) + if (!m_pStream) return; - m_pStream = pStream; - if (pStream->IsMemoryBased() && (!pStream->HasFilter() || bRawAccess)) { - m_dwSize = pStream->GetRawSize(); - m_pData = pStream->GetRawData(); + bool bProcessRawData = bRawAccess || !m_pStream->HasFilter(); + if (bProcessRawData && m_pStream->IsMemoryBased()) { + m_dwSize = m_pStream->GetRawSize(); + m_pData = m_pStream->GetRawData(); return; } - uint32_t dwSrcSize = pStream->GetRawSize(); + uint32_t dwSrcSize = m_pStream->GetRawSize(); if (dwSrcSize == 0) return; uint8_t* pSrcData; - if (!pStream->IsMemoryBased()) { + if (m_pStream->IsMemoryBased()) { + pSrcData = m_pStream->GetRawData(); + } else { pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize); - if (!pStream->ReadRawData(0, pSrcData, dwSrcSize)) + if (!m_pStream->ReadRawData(0, pSrcData, dwSrcSize)) return; - } else { - pSrcData = pStream->GetRawData(); } - if (!pStream->HasFilter() || bRawAccess) { + if (bProcessRawData) { m_pData = pSrcData; m_dwSize = dwSrcSize; - } else if (!PDF_DataDecode(pSrcData, dwSrcSize, m_pStream->GetDict(), m_pData, - m_dwSize, m_ImageDecoder, m_pImageParam, - estimated_size, bImageAcc)) { + } else if (!PDF_DataDecode(pSrcData, dwSrcSize, m_pStream->GetDict(), + estimated_size, bImageAcc, &m_pData, &m_dwSize, + &m_ImageDecoder, &m_pImageParam)) { m_pData = pSrcData; m_dwSize = dwSrcSize; } - if (pSrcData != pStream->GetRawData() && pSrcData != m_pData) + if (pSrcData != m_pStream->GetRawData() && pSrcData != m_pData) FX_Free(pSrcData); m_pSrcData = nullptr; - m_bNewBuf = m_pData != pStream->GetRawData(); + m_bNewBuf = m_pData != m_pStream->GetRawData(); } -CPDF_StreamAcc::~CPDF_StreamAcc() { - if (m_bNewBuf) - FX_Free(m_pData); - FX_Free(m_pSrcData); +void CPDF_StreamAcc::LoadAllDataFiltered() { + LoadAllData(false, 0, false); +} + +void CPDF_StreamAcc::LoadAllDataRaw() { + LoadAllData(true, 0, false); +} + +CPDF_Dictionary* CPDF_StreamAcc::GetDict() const { + return m_pStream ? m_pStream->GetDict() : nullptr; } const uint8_t* CPDF_StreamAcc::GetData() const { - if (m_bNewBuf) - return m_pData; - return m_pStream ? m_pStream->GetRawData() : nullptr; + return GetDataHelper(); +} + +uint8_t* CPDF_StreamAcc::GetData() { + return GetDataHelper(); } uint32_t CPDF_StreamAcc::GetSize() const { @@ -82,6 +90,12 @@ std::unique_ptr CPDF_StreamAcc::DetachData() { return p; } std::unique_ptr p(FX_Alloc(uint8_t, m_dwSize)); - FXSYS_memcpy(p.get(), m_pData, m_dwSize); + memcpy(p.get(), m_pData, m_dwSize); return p; } + +uint8_t* CPDF_StreamAcc::GetDataHelper() const { + if (m_bNewBuf) + return m_pData; + return m_pStream ? m_pStream->GetRawData() : nullptr; +} diff --git a/core/fpdfapi/parser/cpdf_stream_acc.h b/core/fpdfapi/parser/cpdf_stream_acc.h index 51a8a183325de2216a96789bce15143dbe390462..d54e000097c9960d7fca606060d29f2e9ab64a64 100644 --- a/core/fpdfapi/parser/cpdf_stream_acc.h +++ b/core/fpdfapi/parser/cpdf_stream_acc.h @@ -13,39 +13,44 @@ #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" -class CPDF_StreamAcc { +class CPDF_StreamAcc : public Retainable { public: - CPDF_StreamAcc(); - ~CPDF_StreamAcc(); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); CPDF_StreamAcc(const CPDF_StreamAcc&) = delete; CPDF_StreamAcc& operator=(const CPDF_StreamAcc&) = delete; - void LoadAllData(const CPDF_Stream* pStream, - bool bRawAccess = false, - uint32_t estimated_size = 0, - bool bImageAcc = false); + void LoadAllData(bool bRawAccess, uint32_t estimated_size, bool bImageAcc); + void LoadAllDataFiltered(); + void LoadAllDataRaw(); - const CPDF_Stream* GetStream() const { return m_pStream; } - CPDF_Dictionary* GetDict() const { - return m_pStream ? m_pStream->GetDict() : nullptr; - } + const CPDF_Stream* GetStream() const { return m_pStream.Get(); } + CPDF_Dictionary* GetDict() const; const uint8_t* GetData() const; + uint8_t* GetData(); uint32_t GetSize() const; - const CFX_ByteString& GetImageDecoder() const { return m_ImageDecoder; } + const ByteString& GetImageDecoder() const { return m_ImageDecoder; } const CPDF_Dictionary* GetImageParam() const { return m_pImageParam; } std::unique_ptr DetachData(); protected: - uint8_t* m_pData; - uint32_t m_dwSize; - bool m_bNewBuf; - CFX_ByteString m_ImageDecoder; - CPDF_Dictionary* m_pImageParam; - const CPDF_Stream* m_pStream; - uint8_t* m_pSrcData; + explicit CPDF_StreamAcc(const CPDF_Stream* pStream); + ~CPDF_StreamAcc() override; + + private: + uint8_t* GetDataHelper() const; + + uint8_t* m_pData = nullptr; + uint32_t m_dwSize = 0; + bool m_bNewBuf = false; + ByteString m_ImageDecoder; + CPDF_Dictionary* m_pImageParam = nullptr; + UnownedPtr const m_pStream; + uint8_t* m_pSrcData = nullptr; }; #endif // CORE_FPDFAPI_PARSER_CPDF_STREAM_ACC_H_ diff --git a/core/fpdfapi/parser/cpdf_string.cpp b/core/fpdfapi/parser/cpdf_string.cpp index 06bae54916ed75f8a45f627a62a7f823ec86aa2b..851442e8b44fde3ea71ed956098b93248934ad36 100644 --- a/core/fpdfapi/parser/cpdf_string.cpp +++ b/core/fpdfapi/parser/cpdf_string.cpp @@ -9,20 +9,20 @@ #include #include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" CPDF_String::CPDF_String() : m_bHex(false) {} -CPDF_String::CPDF_String(CFX_WeakPtr pPool, - const CFX_ByteString& str, +CPDF_String::CPDF_String(WeakPtr pPool, + const ByteString& str, bool bHex) : m_String(str), m_bHex(bHex) { if (pPool) m_String = pPool->Intern(m_String); } -CPDF_String::CPDF_String(CFX_WeakPtr pPool, - const CFX_WideString& str) +CPDF_String::CPDF_String(WeakPtr pPool, const WideString& str) : m_String(PDF_EncodeText(str)), m_bHex(false) { if (pPool) m_String = pPool->Intern(m_String); @@ -41,11 +41,11 @@ std::unique_ptr CPDF_String::Clone() const { return std::move(pRet); } -CFX_ByteString CPDF_String::GetString() const { +ByteString CPDF_String::GetString() const { return m_String; } -void CPDF_String::SetString(const CFX_ByteString& str) { +void CPDF_String::SetString(const ByteString& str) { m_String = str; } @@ -61,6 +61,11 @@ const CPDF_String* CPDF_String::AsString() const { return this; } -CFX_WideString CPDF_String::GetUnicodeText() const { +WideString CPDF_String::GetUnicodeText() const { return PDF_DecodeText(m_String); } + +bool CPDF_String::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString( + PDF_EncodeString(GetString(), IsHex()).AsStringView()); +} diff --git a/core/fpdfapi/parser/cpdf_string.h b/core/fpdfapi/parser/cpdf_string.h index 6698d8c5be8dcbfcff9d4392b1e19ad7ab6eef80..b6aaacb043c8388b98ee2b414594686d75e75db8 100644 --- a/core/fpdfapi/parser/cpdf_string.h +++ b/core/fpdfapi/parser/cpdf_string.h @@ -10,34 +10,33 @@ #include #include "core/fpdfapi/parser/cpdf_object.h" -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" class CPDF_String : public CPDF_Object { public: CPDF_String(); - CPDF_String(CFX_WeakPtr pPool, - const CFX_ByteString& str, - bool bHex); - CPDF_String(CFX_WeakPtr pPool, const CFX_WideString& str); + CPDF_String(WeakPtr pPool, const ByteString& str, bool bHex); + CPDF_String(WeakPtr pPool, const WideString& str); ~CPDF_String() override; // CPDF_Object: Type GetType() const override; std::unique_ptr Clone() const override; - CFX_ByteString GetString() const override; - CFX_WideString GetUnicodeText() const override; - void SetString(const CFX_ByteString& str) override; + ByteString GetString() const override; + WideString GetUnicodeText() const override; + void SetString(const ByteString& str) override; bool IsString() const override; CPDF_String* AsString() override; const CPDF_String* AsString() const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; bool IsHex() const { return m_bHex; } protected: - CFX_ByteString m_String; + ByteString m_String; bool m_bHex; }; diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp index 1b81b98c96b939c58873c1225ce376bc2f0754a9..66ce1838f224e89aa51c08db5c40680cb35b75af 100644 --- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp +++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp @@ -7,6 +7,7 @@ #include "core/fpdfapi/parser/cpdf_syntax_parser.h" #include +#include #include #include @@ -18,12 +19,15 @@ #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_null.h" #include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_read_validator.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfapi/parser/fpdf_parser_utility.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/cfx_binarybuf.h" +#include "core/fxcrt/fx_extension.h" #include "third_party/base/numerics/safe_math.h" #include "third_party/base/ptr_util.h" @@ -37,37 +41,34 @@ enum class ReadStatus { Normal, Backslash, Octal, FinishOctal, CarriageReturn }; int CPDF_SyntaxParser::s_CurrentRecursionDepth = 0; CPDF_SyntaxParser::CPDF_SyntaxParser() - : CPDF_SyntaxParser(CFX_WeakPtr()) {} + : CPDF_SyntaxParser(WeakPtr()) {} -CPDF_SyntaxParser::CPDF_SyntaxParser( - const CFX_WeakPtr& pPool) - : m_MetadataObjnum(0), - m_pFileAccess(nullptr), - m_pFileBuf(nullptr), - m_BufSize(CPDF_ModuleMgr::kFileBufSize), - m_pPool(pPool) {} +CPDF_SyntaxParser::CPDF_SyntaxParser(const WeakPtr& pPool) + : m_pFileAccess(nullptr), m_pPool(pPool) {} CPDF_SyntaxParser::~CPDF_SyntaxParser() { - FX_Free(m_pFileBuf); } bool CPDF_SyntaxParser::GetCharAt(FX_FILESIZE pos, uint8_t& ch) { - CFX_AutoRestorer save_pos(&m_Pos); + AutoRestorer save_pos(&m_Pos); m_Pos = pos; return GetNextChar(ch); } -bool CPDF_SyntaxParser::ReadChar(FX_FILESIZE read_pos, uint32_t read_size) { - if (static_cast(read_pos + read_size) > m_FileLen) { - if (m_FileLen < static_cast(read_size)) { - read_pos = 0; - read_size = static_cast(m_FileLen); - } else { - read_pos = m_FileLen - read_size; - } - } - if (!m_pFileAccess->ReadBlock(m_pFileBuf, read_pos, read_size)) +bool CPDF_SyntaxParser::ReadBlockAt(FX_FILESIZE read_pos) { + if (read_pos >= m_FileLen) return false; + size_t read_size = CPDF_ModuleMgr::kFileBufSize; + FX_SAFE_FILESIZE safe_end = read_pos; + safe_end += read_size; + if (!safe_end.IsValid() || safe_end.ValueOrDie() > m_FileLen) + read_size = m_FileLen - read_pos; + + m_pFileBuf.resize(read_size); + if (!m_pFileAccess->ReadBlock(m_pFileBuf.data(), read_pos, read_size)) { + m_pFileBuf.clear(); + return false; + } m_BufOffset = read_pos; return true; @@ -78,34 +79,27 @@ bool CPDF_SyntaxParser::GetNextChar(uint8_t& ch) { if (pos >= m_FileLen) return false; - if (CheckPosition(pos)) { - FX_FILESIZE read_pos = pos; - uint32_t read_size = m_BufSize; - read_size = std::min(read_size, static_cast(m_FileLen)); - if (!ReadChar(read_pos, read_size)) - return false; - } + if (!IsPositionRead(pos) && !ReadBlockAt(pos)) + return false; + ch = m_pFileBuf[pos - m_BufOffset]; m_Pos++; return true; } -bool CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch) { +bool CPDF_SyntaxParser::GetCharAtBackward(FX_FILESIZE pos, uint8_t* ch) { pos += m_HeaderOffset; if (pos >= m_FileLen) return false; - if (CheckPosition(pos)) { - FX_FILESIZE read_pos; - if (pos < static_cast(m_BufSize)) - read_pos = 0; - else - read_pos = pos - m_BufSize + 1; - uint32_t read_size = m_BufSize; - if (!ReadChar(read_pos, read_size)) + if (!IsPositionRead(pos)) { + FX_FILESIZE block_start = 0; + if (pos >= CPDF_ModuleMgr::kFileBufSize) + block_start = pos - CPDF_ModuleMgr::kFileBufSize + 1; + if (!ReadBlockAt(block_start) || !IsPositionRead(pos)) return false; } - ch = m_pFileBuf[pos - m_BufOffset]; + *ch = m_pFileBuf[pos - m_BufOffset]; return true; } @@ -121,27 +115,11 @@ void CPDF_SyntaxParser::GetNextWordInternal(bool* bIsNumber) { if (bIsNumber) *bIsNumber = true; + ToNextWord(); uint8_t ch; if (!GetNextChar(ch)) return; - while (1) { - while (PDFCharIsWhitespace(ch)) { - if (!GetNextChar(ch)) - return; - } - - if (ch != '%') - break; - - while (1) { - if (!GetNextChar(ch)) - return; - if (PDFCharIsLineEnding(ch)) - break; - } - } - if (PDFCharIsDelimiter(ch)) { if (bIsNumber) *bIsNumber = false; @@ -199,12 +177,12 @@ void CPDF_SyntaxParser::GetNextWordInternal(bool* bIsNumber) { } } -CFX_ByteString CPDF_SyntaxParser::ReadString() { +ByteString CPDF_SyntaxParser::ReadString() { uint8_t ch; if (!GetNextChar(ch)) - return CFX_ByteString(); + return ByteString(); - CFX_ByteTextBuf buf; + std::ostringstream buf; int32_t parlevel = 0; ReadStatus status = ReadStatus::Normal; int32_t iEscCode = 0; @@ -213,7 +191,7 @@ CFX_ByteString CPDF_SyntaxParser::ReadString() { case ReadStatus::Normal: if (ch == ')') { if (parlevel == 0) - return buf.MakeString(); + return ByteString(buf); parlevel--; } else if (ch == '(') { parlevel++; @@ -221,40 +199,41 @@ CFX_ByteString CPDF_SyntaxParser::ReadString() { if (ch == '\\') status = ReadStatus::Backslash; else - buf.AppendChar(ch); + buf << static_cast(ch); break; case ReadStatus::Backslash: if (ch >= '0' && ch <= '7') { - iEscCode = FXSYS_toDecimalDigit(static_cast(ch)); + iEscCode = FXSYS_DecimalCharToInt(static_cast(ch)); status = ReadStatus::Octal; break; } + if (ch == '\r') { + status = ReadStatus::CarriageReturn; + break; + } if (ch == 'n') { - buf.AppendChar('\n'); + buf << '\n'; } else if (ch == 'r') { - buf.AppendChar('\r'); + buf << '\r'; } else if (ch == 't') { - buf.AppendChar('\t'); + buf << '\t'; } else if (ch == 'b') { - buf.AppendChar('\b'); + buf << '\b'; } else if (ch == 'f') { - buf.AppendChar('\f'); - } else if (ch == '\r') { - status = ReadStatus::CarriageReturn; - break; + buf << '\f'; } else if (ch != '\n') { - buf.AppendChar(ch); + buf << static_cast(ch); } status = ReadStatus::Normal; break; case ReadStatus::Octal: if (ch >= '0' && ch <= '7') { iEscCode = - iEscCode * 8 + FXSYS_toDecimalDigit(static_cast(ch)); + iEscCode * 8 + FXSYS_DecimalCharToInt(static_cast(ch)); status = ReadStatus::FinishOctal; } else { - buf.AppendChar(iEscCode); + buf << static_cast(iEscCode); status = ReadStatus::Normal; continue; } @@ -263,10 +242,10 @@ CFX_ByteString CPDF_SyntaxParser::ReadString() { status = ReadStatus::Normal; if (ch >= '0' && ch <= '7') { iEscCode = - iEscCode * 8 + FXSYS_toDecimalDigit(static_cast(ch)); - buf.AppendChar(iEscCode); + iEscCode * 8 + FXSYS_DecimalCharToInt(static_cast(ch)); + buf << static_cast(iEscCode); } else { - buf.AppendChar(iEscCode); + buf << static_cast(iEscCode); continue; } break; @@ -282,15 +261,15 @@ CFX_ByteString CPDF_SyntaxParser::ReadString() { } GetNextChar(ch); - return buf.MakeString(); + return ByteString(buf); } -CFX_ByteString CPDF_SyntaxParser::ReadHexString() { +ByteString CPDF_SyntaxParser::ReadHexString() { uint8_t ch; if (!GetNextChar(ch)) - return CFX_ByteString(); + return ByteString(); - CFX_ByteTextBuf buf; + std::ostringstream buf; bool bFirst = true; uint8_t code = 0; while (1) { @@ -298,12 +277,12 @@ CFX_ByteString CPDF_SyntaxParser::ReadHexString() { break; if (std::isxdigit(ch)) { - int val = FXSYS_toHexDigit(ch); + int val = FXSYS_HexCharToInt(ch); if (bFirst) { code = val * 16; } else { code += val; - buf.AppendByte(code); + buf << static_cast(code); } bFirst = !bFirst; } @@ -312,9 +291,9 @@ CFX_ByteString CPDF_SyntaxParser::ReadHexString() { break; } if (!bFirst) - buf.AppendByte(code); + buf << static_cast(code); - return buf.MakeString(); + return ByteString(buf); } void CPDF_SyntaxParser::ToNextLine() { @@ -356,44 +335,60 @@ void CPDF_SyntaxParser::ToNextWord() { m_Pos--; } -CFX_ByteString CPDF_SyntaxParser::GetNextWord(bool* bIsNumber) { +ByteString CPDF_SyntaxParser::GetNextWord(bool* bIsNumber) { + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); GetNextWordInternal(bIsNumber); - return CFX_ByteString((const FX_CHAR*)m_WordBuffer, m_WordSize); + ByteString ret; + if (!GetValidator()->has_read_problems()) + ret = ByteString(m_WordBuffer, m_WordSize); + return ret; } -CFX_ByteString CPDF_SyntaxParser::GetKeyword() { +ByteString CPDF_SyntaxParser::PeekNextWord(bool* bIsNumber) { + AutoRestorer save_pos(&m_Pos); + return GetNextWord(bIsNumber); +} + +ByteString CPDF_SyntaxParser::GetKeyword() { return GetNextWord(nullptr); } -std::unique_ptr CPDF_SyntaxParser::GetObject( +std::unique_ptr CPDF_SyntaxParser::GetObjectBody( + CPDF_IndirectObjectHolder* pObjList) { + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); + auto result = GetObjectBodyInternal(pObjList, ParseType::kLoose); + if (GetValidator()->has_read_problems()) + return nullptr; + return result; +} + +std::unique_ptr CPDF_SyntaxParser::GetObjectBodyInternal( CPDF_IndirectObjectHolder* pObjList, - uint32_t objnum, - uint32_t gennum, - bool bDecrypt) { - CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); + ParseType parse_type) { + AutoRestorer restorer(&s_CurrentRecursionDepth); if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) return nullptr; FX_FILESIZE SavedObjPos = m_Pos; bool bIsNumber; - CFX_ByteString word = GetNextWord(&bIsNumber); + ByteString word = GetNextWord(&bIsNumber); if (word.GetLength() == 0) return nullptr; if (bIsNumber) { FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString nextword = GetNextWord(&bIsNumber); + ByteString nextword = GetNextWord(&bIsNumber); if (bIsNumber) { - CFX_ByteString nextword2 = GetNextWord(nullptr); + ByteString nextword2 = GetNextWord(nullptr); if (nextword2 == "R") { - uint32_t objnum = FXSYS_atoui(word.c_str()); - if (objnum == CPDF_Object::kInvalidObjNum) + uint32_t refnum = FXSYS_atoui(word.c_str()); + if (refnum == CPDF_Object::kInvalidObjNum) return nullptr; - return pdfium::MakeUnique(pObjList, objnum); + return pdfium::MakeUnique(pObjList, refnum); } } m_Pos = SavedPos; - return pdfium::MakeUnique(word.AsStringC()); + return pdfium::MakeUnique(word.AsStringView()); } if (word == "true" || word == "false") @@ -403,37 +398,33 @@ std::unique_ptr CPDF_SyntaxParser::GetObject( return pdfium::MakeUnique(); if (word == "(") { - CFX_ByteString str = ReadString(); - if (m_pCryptoHandler && bDecrypt) - m_pCryptoHandler->Decrypt(objnum, gennum, str); + ByteString str = ReadString(); return pdfium::MakeUnique(m_pPool, str, false); } if (word == "<") { - CFX_ByteString str = ReadHexString(); - if (m_pCryptoHandler && bDecrypt) - m_pCryptoHandler->Decrypt(objnum, gennum, str); + ByteString str = ReadHexString(); return pdfium::MakeUnique(m_pPool, str, true); } if (word == "[") { - std::unique_ptr pArray = pdfium::MakeUnique(); + auto pArray = pdfium::MakeUnique(); while (std::unique_ptr pObj = - GetObject(pObjList, objnum, gennum, true)) { + GetObjectBodyInternal(pObjList, ParseType::kLoose)) { pArray->Add(std::move(pObj)); } - return std::move(pArray); + return (parse_type == ParseType::kLoose || m_WordBuffer[0] == ']') + ? std::move(pArray) + : nullptr; } if (word[0] == '/') { return pdfium::MakeUnique( m_pPool, - PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); + PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1))); } if (word == "<<") { - int32_t nKeys = 0; - FX_FILESIZE dwSignValuePos = 0; std::unique_ptr pDict = pdfium::MakeUnique(m_pPool); while (1) { - CFX_ByteString key = GetNextWord(nullptr); + ByteString key = GetNextWord(nullptr); if (key.IsEmpty()) return nullptr; @@ -448,38 +439,34 @@ std::unique_ptr CPDF_SyntaxParser::GetObject( if (key[0] != '/') continue; - ++nKeys; key = PDF_NameDecode(key); - if (key.IsEmpty()) - continue; - if (key == "/Contents") - dwSignValuePos = m_Pos; + if (key.IsEmpty() && parse_type == ParseType::kLoose) + continue; std::unique_ptr pObj = - GetObject(pObjList, objnum, gennum, true); - if (!pObj) - continue; + GetObjectBodyInternal(pObjList, ParseType::kLoose); + if (!pObj) { + if (parse_type == ParseType::kLoose) + continue; - CFX_ByteString keyNoSlash(key.raw_str() + 1, key.GetLength() - 1); - pDict->SetFor(keyNoSlash, std::move(pObj)); - } + ToNextLine(); + return nullptr; + } - // Only when this is a signature dictionary and has contents, we reset the - // contents to the un-decrypted form. - if (pDict->IsSignatureDict() && dwSignValuePos) { - CFX_AutoRestorer save_pos(&m_Pos); - m_Pos = dwSignValuePos; - pDict->SetFor("Contents", GetObject(pObjList, objnum, gennum, false)); + if (!key.IsEmpty()) { + ByteString keyNoSlash(key.raw_str() + 1, key.GetLength() - 1); + pDict->SetFor(keyNoSlash, std::move(pObj)); + } } FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString nextword = GetNextWord(nullptr); + ByteString nextword = GetNextWord(nullptr); if (nextword != "stream") { m_Pos = SavedPos; return std::move(pDict); } - return ReadStream(std::move(pDict), objnum, gennum); + return ReadStream(std::move(pDict)); } if (word == ">>") m_Pos = SavedObjPos; @@ -487,115 +474,39 @@ std::unique_ptr CPDF_SyntaxParser::GetObject( return nullptr; } -std::unique_ptr CPDF_SyntaxParser::GetObjectForStrict( +std::unique_ptr CPDF_SyntaxParser::GetIndirectObject( CPDF_IndirectObjectHolder* pObjList, - uint32_t objnum, - uint32_t gennum) { - CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); - if (++s_CurrentRecursionDepth > kParserMaxRecursionDepth) + ParseType parse_type) { + const CPDF_ReadValidator::Session read_session(GetValidator().Get()); + const FX_FILESIZE saved_pos = GetPos(); + bool is_number = false; + ByteString word = GetNextWord(&is_number); + if (!is_number || word.IsEmpty()) { + SetPos(saved_pos); return nullptr; + } + const uint32_t parser_objnum = FXSYS_atoui(word.c_str()); - FX_FILESIZE SavedObjPos = m_Pos; - bool bIsNumber; - CFX_ByteString word = GetNextWord(&bIsNumber); - if (word.GetLength() == 0) + word = GetNextWord(&is_number); + if (!is_number || word.IsEmpty()) { + SetPos(saved_pos); return nullptr; - - if (bIsNumber) { - FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString nextword = GetNextWord(&bIsNumber); - if (bIsNumber) { - CFX_ByteString nextword2 = GetNextWord(nullptr); - if (nextword2 == "R") { - uint32_t objnum = FXSYS_atoui(word.c_str()); - if (objnum == CPDF_Object::kInvalidObjNum) - return nullptr; - return pdfium::MakeUnique(pObjList, objnum); - } - } - m_Pos = SavedPos; - return pdfium::MakeUnique(word.AsStringC()); } + const uint32_t parser_gennum = FXSYS_atoui(word.c_str()); - if (word == "true" || word == "false") - return pdfium::MakeUnique(word == "true"); - - if (word == "null") - return pdfium::MakeUnique(); - - if (word == "(") { - CFX_ByteString str = ReadString(); - if (m_pCryptoHandler) - m_pCryptoHandler->Decrypt(objnum, gennum, str); - return pdfium::MakeUnique(m_pPool, str, false); - } - if (word == "<") { - CFX_ByteString str = ReadHexString(); - if (m_pCryptoHandler) - m_pCryptoHandler->Decrypt(objnum, gennum, str); - return pdfium::MakeUnique(m_pPool, str, true); - } - if (word == "[") { - std::unique_ptr pArray = pdfium::MakeUnique(); - while (std::unique_ptr pObj = - GetObject(pObjList, objnum, gennum, true)) { - pArray->Add(std::move(pObj)); - } - return m_WordBuffer[0] == ']' ? std::move(pArray) : nullptr; - } - if (word[0] == '/') { - return pdfium::MakeUnique( - m_pPool, - PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1))); + if (GetKeyword() != "obj") { + SetPos(saved_pos); + return nullptr; } - if (word == "<<") { - std::unique_ptr pDict = - pdfium::MakeUnique(m_pPool); - while (1) { - FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString key = GetNextWord(nullptr); - if (key.IsEmpty()) - return nullptr; - - if (key == ">>") - break; - - if (key == "endobj") { - m_Pos = SavedPos; - break; - } - if (key[0] != '/') - continue; - - key = PDF_NameDecode(key); - std::unique_ptr obj( - GetObject(pObjList, objnum, gennum, true)); - if (!obj) { - uint8_t ch; - while (GetNextChar(ch) && ch != 0x0A && ch != 0x0D) { - continue; - } - return nullptr; - } - - if (key.GetLength() > 1) { - pDict->SetFor(CFX_ByteString(key.c_str() + 1, key.GetLength() - 1), - std::move(obj)); - } - } - FX_FILESIZE SavedPos = m_Pos; - CFX_ByteString nextword = GetNextWord(nullptr); - if (nextword != "stream") { - m_Pos = SavedPos; - return std::move(pDict); - } - return ReadStream(std::move(pDict), objnum, gennum); + std::unique_ptr pObj = + GetObjectBodyInternal(pObjList, parse_type); + if (pObj) { + pObj->SetObjNum(parser_objnum); + pObj->SetGenNum(parser_gennum); } - if (word == ">>") - m_Pos = SavedObjPos; - return nullptr; + return GetValidator()->has_read_problems() ? nullptr : std::move(pObj); } unsigned int CPDF_SyntaxParser::ReadEOLMarkers(FX_FILESIZE pos) { @@ -615,28 +526,17 @@ unsigned int CPDF_SyntaxParser::ReadEOLMarkers(FX_FILESIZE pos) { } std::unique_ptr CPDF_SyntaxParser::ReadStream( - std::unique_ptr pDict, - uint32_t objnum, - uint32_t gennum) { - CPDF_Object* pLenObj = pDict->GetObjectFor("Length"); - FX_FILESIZE len = -1; - CPDF_Reference* pLenObjRef = ToReference(pLenObj); - - bool differingObjNum = !pLenObjRef || (pLenObjRef->GetObjList() && - pLenObjRef->GetRefObjNum() != objnum); - if (pLenObj && differingObjNum) - len = pLenObj->GetInteger(); + std::unique_ptr pDict) { + const CPDF_Number* pLenObj = ToNumber(pDict->GetDirectObjectFor("Length")); + FX_FILESIZE len = pLenObj ? pLenObj->GetInteger() : -1; // Locate the start of stream. ToNextLine(); FX_FILESIZE streamStartPos = m_Pos; - const CFX_ByteStringC kEndStreamStr("endstream"); - const CFX_ByteStringC kEndObjStr("endobj"); + const ByteStringView kEndStreamStr("endstream"); + const ByteStringView kEndObjStr("endobj"); - CPDF_CryptoHandler* pCryptoHandler = - objnum == m_MetadataObjnum ? nullptr : m_pCryptoHandler.get(); - if (!pCryptoHandler) { bool bSearchForKeyword = true; if (len >= 0) { pdfium::base::CheckedNumeric pos = m_Pos; @@ -645,13 +545,13 @@ std::unique_ptr CPDF_SyntaxParser::ReadStream( m_Pos = pos.ValueOrDie(); m_Pos += ReadEOLMarkers(m_Pos); - FXSYS_memset(m_WordBuffer, 0, kEndStreamStr.GetLength() + 1); + memset(m_WordBuffer, 0, kEndStreamStr.GetLength() + 1); GetNextWordInternal(nullptr); // Earlier version of PDF specification doesn't require EOL marker before // 'endstream' keyword. If keyword 'endstream' follows the bytes in // specified length, it signals the end of stream. - if (FXSYS_memcmp(m_WordBuffer, kEndStreamStr.raw_str(), - kEndStreamStr.GetLength()) == 0) { + if (memcmp(m_WordBuffer, kEndStreamStr.raw_str(), + kEndStreamStr.GetLength()) == 0) { bSearchForKeyword = false; } } @@ -723,7 +623,11 @@ std::unique_ptr CPDF_SyntaxParser::ReadStream( pDict->SetNewFor("Length", static_cast(len)); } m_Pos = streamStartPos; - } + + // Read up to the end of the buffer. Note, we allow zero length streams as + // we need to pass them through when we are importing pages into a new + // document. + len = std::min(len, m_FileLen - m_Pos - m_HeaderOffset); if (len < 0) return nullptr; @@ -731,47 +635,41 @@ std::unique_ptr CPDF_SyntaxParser::ReadStream( if (len > 0) { pData.reset(FX_Alloc(uint8_t, len)); ReadBlock(pData.get(), len); - if (pCryptoHandler) { - CFX_BinaryBuf dest_buf; - dest_buf.EstimateSize(pCryptoHandler->DecryptGetSize(len)); - - void* context = pCryptoHandler->DecryptStart(objnum, gennum); - pCryptoHandler->DecryptStream(context, pData.get(), len, dest_buf); - pCryptoHandler->DecryptFinish(context, dest_buf); - len = dest_buf.GetSize(); - pData = dest_buf.DetachBuffer(); - } } - auto pStream = pdfium::MakeUnique(std::move(pData), len, std::move(pDict)); streamStartPos = m_Pos; - FXSYS_memset(m_WordBuffer, 0, kEndObjStr.GetLength() + 1); + memset(m_WordBuffer, 0, kEndObjStr.GetLength() + 1); GetNextWordInternal(nullptr); int numMarkers = ReadEOLMarkers(m_Pos); if (m_WordSize == static_cast(kEndObjStr.GetLength()) && numMarkers != 0 && - FXSYS_memcmp(m_WordBuffer, kEndObjStr.raw_str(), - kEndObjStr.GetLength()) == 0) { + memcmp(m_WordBuffer, kEndObjStr.raw_str(), kEndObjStr.GetLength()) == 0) { m_Pos = streamStartPos; } return pStream; } void CPDF_SyntaxParser::InitParser( - const CFX_RetainPtr& pFileAccess, + const RetainPtr& pFileAccess, uint32_t HeaderOffset) { - FX_Free(m_pFileBuf); + ASSERT(pFileAccess); + return InitParserWithValidator( + pdfium::MakeRetain(pFileAccess, nullptr), + HeaderOffset); +} - m_pFileBuf = FX_Alloc(uint8_t, m_BufSize); +void CPDF_SyntaxParser::InitParserWithValidator( + const RetainPtr& validator, + uint32_t HeaderOffset) { + ASSERT(validator); + m_pFileBuf.clear(); m_HeaderOffset = HeaderOffset; - m_FileLen = pFileAccess->GetSize(); + m_FileLen = validator->GetSize(); m_Pos = 0; - m_pFileAccess = pFileAccess; + m_pFileAccess = validator; m_BufOffset = 0; - pFileAccess->ReadBlock(m_pFileBuf, 0, - std::min(m_BufSize, static_cast(m_FileLen))); } uint32_t CPDF_SyntaxParser::GetDirectNum() { @@ -781,12 +679,12 @@ uint32_t CPDF_SyntaxParser::GetDirectNum() { return 0; m_WordBuffer[m_WordSize] = 0; - return FXSYS_atoui(reinterpret_cast(m_WordBuffer)); + return FXSYS_atoui(reinterpret_cast(m_WordBuffer)); } bool CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, - const CFX_ByteStringC& tag, + const ByteStringView& tag, bool checkKeyword) { const uint32_t taglen = tag.GetLength(); @@ -812,77 +710,41 @@ bool CPDF_SyntaxParser::IsWholeWord(FX_FILESIZE startpos, return true; } -// TODO(dsinclair): Split into a SearchWordForward and SearchWordBackwards -// and drop the bool. -bool CPDF_SyntaxParser::SearchWord(const CFX_ByteStringC& tag, - bool bWholeWord, - bool bForward, - FX_FILESIZE limit) { +bool CPDF_SyntaxParser::BackwardsSearchToWord(const ByteStringView& tag, + FX_FILESIZE limit) { int32_t taglen = tag.GetLength(); if (taglen == 0) return false; FX_FILESIZE pos = m_Pos; - int32_t offset = 0; - if (!bForward) - offset = taglen - 1; - - const uint8_t* tag_data = tag.raw_str(); - uint8_t byte; + int32_t offset = taglen - 1; while (1) { - if (bForward) { - if (limit && pos >= m_Pos + limit) - return false; - - if (!GetCharAt(pos, byte)) - return false; - - } else { - if (limit && pos <= m_Pos - limit) - return false; + if (limit && pos <= m_Pos - limit) + return false; - if (!GetCharAtBackward(pos, byte)) - return false; - } + uint8_t byte; + if (!GetCharAtBackward(pos, &byte)) + return false; - if (byte == tag_data[offset]) { - if (bForward) { - offset++; - if (offset < taglen) { - pos++; - continue; - } - } else { - offset--; - if (offset >= 0) { - pos--; - continue; - } + if (byte == tag[offset]) { + offset--; + if (offset >= 0) { + pos--; + continue; } - - FX_FILESIZE startpos = bForward ? pos - taglen + 1 : pos; - if (!bWholeWord || IsWholeWord(startpos, limit, tag, false)) { - m_Pos = startpos; + if (IsWholeWord(pos, limit, tag, false)) { + m_Pos = pos; return true; } } - - if (bForward) { - offset = byte == tag_data[0] ? 1 : 0; - pos++; - } else { - offset = byte == tag_data[taglen - 1] ? taglen - 2 : taglen - 1; - pos--; - } - + offset = byte == tag[taglen - 1] ? taglen - 2 : taglen - 1; + pos--; if (pos < 0) return false; } - - return false; } -FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, +FX_FILESIZE CPDF_SyntaxParser::FindTag(const ByteStringView& tag, FX_FILESIZE limit) { int32_t taglen = tag.GetLength(); int32_t match = 0; @@ -908,7 +770,11 @@ FX_FILESIZE CPDF_SyntaxParser::FindTag(const CFX_ByteStringC& tag, return -1; } -void CPDF_SyntaxParser::SetEncrypt( - std::unique_ptr pCryptoHandler) { - m_pCryptoHandler = std::move(pCryptoHandler); +RetainPtr CPDF_SyntaxParser::GetFileAccess() const { + return m_pFileAccess; +} + +bool CPDF_SyntaxParser::IsPositionRead(FX_FILESIZE pos) const { + return m_BufOffset <= pos && + pos < static_cast(m_BufOffset + m_pFileBuf.size()); } diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.h b/core/fpdfapi/parser/cpdf_syntax_parser.h index 8dd9103f1b74e6d08ea5566f37dc441643340082..d3442880bce28a3f796978a55507585025157ff6 100644 --- a/core/fpdfapi/parser/cpdf_syntax_parser.h +++ b/core/fpdfapi/parser/cpdf_syntax_parser.h @@ -7,54 +7,60 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_SYNTAX_PARSER_H_ #define CORE_FPDFAPI_PARSER_CPDF_SYNTAX_PARSER_H_ +#include #include +#include -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/weak_ptr.h" class CPDF_CryptoHandler; class CPDF_Dictionary; class CPDF_IndirectObjectHolder; class CPDF_Object; +class CPDF_ReadValidator; class CPDF_Stream; class IFX_SeekableReadStream; class CPDF_SyntaxParser { public: + enum class ParseType { kStrict, kLoose }; + CPDF_SyntaxParser(); - explicit CPDF_SyntaxParser(const CFX_WeakPtr& pPool); + explicit CPDF_SyntaxParser(const WeakPtr& pPool); ~CPDF_SyntaxParser(); - void InitParser(const CFX_RetainPtr& pFileAccess, + void InitParser(const RetainPtr& pFileAccess, uint32_t HeaderOffset); - FX_FILESIZE SavePos() const { return m_Pos; } - void RestorePos(FX_FILESIZE pos) { m_Pos = pos; } + void InitParserWithValidator(const RetainPtr& pValidator, + uint32_t HeaderOffset); + + FX_FILESIZE GetPos() const { return m_Pos; } + void SetPos(FX_FILESIZE pos) { m_Pos = std::min(pos, m_FileLen); } - std::unique_ptr GetObject(CPDF_IndirectObjectHolder* pObjList, - uint32_t objnum, - uint32_t gennum, - bool bDecrypt); + std::unique_ptr GetObjectBody( + CPDF_IndirectObjectHolder* pObjList); - std::unique_ptr GetObjectForStrict( + std::unique_ptr GetIndirectObject( CPDF_IndirectObjectHolder* pObjList, - uint32_t objnum, - uint32_t gennum); + ParseType parse_type); - CFX_ByteString GetKeyword(); + ByteString GetKeyword(); void ToNextLine(); void ToNextWord(); - bool SearchWord(const CFX_ByteStringC& word, - bool bWholeWord, - bool bForward, - FX_FILESIZE limit); - - FX_FILESIZE FindTag(const CFX_ByteStringC& tag, FX_FILESIZE limit); - void SetEncrypt(std::unique_ptr pCryptoHandler); + bool BackwardsSearchToWord(const ByteStringView& word, FX_FILESIZE limit); + FX_FILESIZE FindTag(const ByteStringView& tag, FX_FILESIZE limit); bool ReadBlock(uint8_t* pBuf, uint32_t size); bool GetCharAt(FX_FILESIZE pos, uint8_t& ch); - CFX_ByteString GetNextWord(bool* bIsNumber); + ByteString GetNextWord(bool* bIsNumber); + ByteString PeekNextWord(bool* bIsNumber); + + RetainPtr GetFileAccess() const; + + const RetainPtr& GetValidator() const { + return m_pFileAccess; + } private: friend class CPDF_Parser; @@ -65,40 +71,36 @@ class CPDF_SyntaxParser { static int s_CurrentRecursionDepth; uint32_t GetDirectNum(); - bool ReadChar(FX_FILESIZE read_pos, uint32_t read_size); + bool ReadBlockAt(FX_FILESIZE read_pos); bool GetNextChar(uint8_t& ch); - bool GetCharAtBackward(FX_FILESIZE pos, uint8_t& ch); + bool GetCharAtBackward(FX_FILESIZE pos, uint8_t* ch); void GetNextWordInternal(bool* bIsNumber); bool IsWholeWord(FX_FILESIZE startpos, FX_FILESIZE limit, - const CFX_ByteStringC& tag, + const ByteStringView& tag, bool checkKeyword); - CFX_ByteString ReadString(); - CFX_ByteString ReadHexString(); + ByteString ReadString(); + ByteString ReadHexString(); unsigned int ReadEOLMarkers(FX_FILESIZE pos); std::unique_ptr ReadStream( - std::unique_ptr pDict, - uint32_t objnum, - uint32_t gennum); + std::unique_ptr pDict); - inline bool CheckPosition(FX_FILESIZE pos) { - return m_BufOffset >= pos || - static_cast(m_BufOffset + m_BufSize) <= pos; - } + bool IsPositionRead(FX_FILESIZE pos) const; + + std::unique_ptr GetObjectBodyInternal( + CPDF_IndirectObjectHolder* pObjList, + ParseType parse_type); FX_FILESIZE m_Pos; - uint32_t m_MetadataObjnum; - CFX_RetainPtr m_pFileAccess; + RetainPtr m_pFileAccess; FX_FILESIZE m_HeaderOffset; FX_FILESIZE m_FileLen; - uint8_t* m_pFileBuf; - uint32_t m_BufSize; + std::vector m_pFileBuf; FX_FILESIZE m_BufOffset; - std::unique_ptr m_pCryptoHandler; uint8_t m_WordBuffer[257]; uint32_t m_WordSize; - CFX_WeakPtr m_pPool; + WeakPtr m_pPool; }; #endif // CORE_FPDFAPI_PARSER_CPDF_SYNTAX_PARSER_H_ diff --git a/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp index 64c33ba9cda0747149650dd9e9684dccd64951ee..cb065eb4e2f81fff95091dfddca53f30d8a651f8 100644 --- a/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp @@ -8,7 +8,8 @@ #include "core/fpdfapi/parser/cpdf_object.h" #include "core/fpdfapi/parser/cpdf_parser.h" #include "core/fpdfapi/parser/cpdf_syntax_parser.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_stream.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/utils/path_service.h" @@ -18,84 +19,84 @@ TEST(cpdf_syntax_parser, ReadHexString) { // Empty string. uint8_t data[] = ""; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 0, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 0, false), 0); EXPECT_EQ("", parser.ReadHexString()); - EXPECT_EQ(0, parser.SavePos()); + EXPECT_EQ(0, parser.GetPos()); } { // Blank string. uint8_t data[] = " "; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 2, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 2, false), 0); EXPECT_EQ("", parser.ReadHexString()); - EXPECT_EQ(2, parser.SavePos()); + EXPECT_EQ(2, parser.GetPos()); } { // Skips unknown characters. uint8_t data[] = "z12b"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 4, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 4, false), 0); EXPECT_EQ("\x12\xb0", parser.ReadHexString()); - EXPECT_EQ(4, parser.SavePos()); + EXPECT_EQ(4, parser.GetPos()); } { // Skips unknown characters. uint8_t data[] = "*<&*#$^&@1"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 10, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 10, false), 0); EXPECT_EQ("\x10", parser.ReadHexString()); - EXPECT_EQ(10, parser.SavePos()); + EXPECT_EQ(10, parser.GetPos()); } { // Skips unknown characters. uint8_t data[] = "\x80zab"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 4, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 4, false), 0); EXPECT_EQ("\xab", parser.ReadHexString()); - EXPECT_EQ(4, parser.SavePos()); + EXPECT_EQ(4, parser.GetPos()); } { // Skips unknown characters. uint8_t data[] = "\xffzab"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 4, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 4, false), 0); EXPECT_EQ("\xab", parser.ReadHexString()); - EXPECT_EQ(4, parser.SavePos()); + EXPECT_EQ(4, parser.GetPos()); } { // Regular conversion. uint8_t data[] = "1A2b>abcd"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 9, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 9, false), 0); EXPECT_EQ("\x1a\x2b", parser.ReadHexString()); - EXPECT_EQ(5, parser.SavePos()); + EXPECT_EQ(5, parser.GetPos()); } { // Position out of bounds. uint8_t data[] = "12ab>"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 5, false), 0); - parser.RestorePos(5); + parser.InitParser(pdfium::MakeRetain(data, 5, false), 0); + parser.SetPos(5); EXPECT_EQ("", parser.ReadHexString()); - parser.RestorePos(6); + parser.SetPos(6); EXPECT_EQ("", parser.ReadHexString()); - parser.RestorePos(-1); + parser.SetPos(-1); EXPECT_EQ("", parser.ReadHexString()); - parser.RestorePos(std::numeric_limits::max()); + parser.SetPos(std::numeric_limits::max()); EXPECT_EQ("", parser.ReadHexString()); // Check string still parses when set to 0. - parser.RestorePos(0); + parser.SetPos(0); EXPECT_EQ("\x12\xab", parser.ReadHexString()); } @@ -103,45 +104,45 @@ TEST(cpdf_syntax_parser, ReadHexString) { // Missing ending >. uint8_t data[] = "1A2b"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 4, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 4, false), 0); EXPECT_EQ("\x1a\x2b", parser.ReadHexString()); - EXPECT_EQ(4, parser.SavePos()); + EXPECT_EQ(4, parser.GetPos()); } { // Missing ending >. uint8_t data[] = "12abz"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 5, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 5, false), 0); EXPECT_EQ("\x12\xab", parser.ReadHexString()); - EXPECT_EQ(5, parser.SavePos()); + EXPECT_EQ(5, parser.GetPos()); } { // Uneven number of bytes. uint8_t data[] = "1A2>asdf"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 8, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 8, false), 0); EXPECT_EQ("\x1a\x20", parser.ReadHexString()); - EXPECT_EQ(4, parser.SavePos()); + EXPECT_EQ(4, parser.GetPos()); } { // Uneven number of bytes. uint8_t data[] = "1A2zasdf"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 8, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 8, false), 0); EXPECT_EQ("\x1a\x2a\xdf", parser.ReadHexString()); - EXPECT_EQ(8, parser.SavePos()); + EXPECT_EQ(8, parser.GetPos()); } { // Just ending character. uint8_t data[] = ">"; CPDF_SyntaxParser parser; - parser.InitParser(IFX_MemoryStream::Create(data, 1, false), 0); + parser.InitParser(pdfium::MakeRetain(data, 1, false), 0); EXPECT_EQ("", parser.ReadHexString()); - EXPECT_EQ(1, parser.SavePos()); + EXPECT_EQ(1, parser.GetPos()); } } @@ -149,8 +150,16 @@ TEST(cpdf_syntax_parser, GetInvalidReference) { CPDF_SyntaxParser parser; // Data with a reference with number CPDF_Object::kInvalidObjNum uint8_t data[] = "4294967295 0 R"; - parser.InitParser(IFX_MemoryStream::Create(data, 14, false), 0); - std::unique_ptr ref = - parser.GetObject(nullptr, CPDF_Object::kInvalidObjNum, 0, false); + parser.InitParser(pdfium::MakeRetain(data, 14, false), 0); + std::unique_ptr ref = parser.GetObjectBody(nullptr); EXPECT_FALSE(ref); } + +TEST(cpdf_syntax_parser, PeekNextWord) { + CPDF_SyntaxParser parser; + uint8_t data[] = " WORD "; + parser.InitParser( + pdfium::MakeRetain(data, sizeof(data), false), 0); + EXPECT_EQ("WORD", parser.PeekNextWord(nullptr)); + EXPECT_EQ("WORD", parser.GetNextWord(nullptr)); +} diff --git a/core/fpdfapi/parser/fpdf_parser_decode.cpp b/core/fpdfapi/parser/fpdf_parser_decode.cpp index 480e2c111f4c0fba71a8b1e4c54e87bbf082b129..d7114b66c518aa6576d47ad7f1cd0117b6ab7869 100644 --- a/core/fpdfapi/parser/fpdf_parser_decode.cpp +++ b/core/fpdfapi/parser/fpdf_parser_decode.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -16,27 +17,32 @@ #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/fpdf_parser_utility.h" +#include "core/fxcodec/codec/ccodec_faxmodule.h" +#include "core/fxcodec/codec/ccodec_flatemodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/stl_util.h" +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/numerics/safe_math.h" namespace { const uint32_t kMaxStreamSize = 20 * 1024 * 1024; +uint16_t GetUnicodeFromBytes(const uint8_t* bytes, bool bBE) { + return bBE ? (bytes[0] << 8 | bytes[1]) : (bytes[1] << 8 | bytes[0]); +} + bool CheckFlateDecodeParams(int Colors, int BitsPerComponent, int Columns) { if (Colors < 0 || BitsPerComponent < 0 || Columns < 0) return false; - int check = Columns; - if (check > 0 && Colors > INT_MAX / check) - return false; - + pdfium::base::CheckedNumeric check = Columns; check *= Colors; - if (check > 0 && BitsPerComponent > INT_MAX / check) + check *= BitsPerComponent; + if (!check.IsValid()) return false; - return check * BitsPerComponent <= INT_MAX - 7; + return check.ValueOrDie() <= INT_MAX - 7; } } // namespace @@ -74,10 +80,10 @@ const uint16_t PDFDocEncoding[256] = { uint32_t A85Decode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size) { - dest_size = 0; - dest_buf = nullptr; + uint8_t** dest_buf, + uint32_t* dest_size) { + *dest_size = 0; + *dest_buf = nullptr; if (src_size == 0) return 0; @@ -101,68 +107,72 @@ uint32_t A85Decode(const uint8_t* src_buf, // Count the space needed to contain non-zero characters. The encoding ratio // of Ascii85 is 4:5. uint32_t space_for_non_zeroes = (pos - zcount) / 5 * 4 + 4; - if (zcount > (UINT_MAX - space_for_non_zeroes) / 4) { - return (uint32_t)-1; - } - dest_buf = FX_Alloc(uint8_t, zcount * 4 + space_for_non_zeroes); + if (zcount > (UINT_MAX - space_for_non_zeroes) / 4) + return FX_INVALID_OFFSET; + + *dest_buf = FX_Alloc(uint8_t, zcount * 4 + space_for_non_zeroes); size_t state = 0; uint32_t res = 0; - pos = dest_size = 0; + pos = 0; while (pos < src_size) { uint8_t ch = src_buf[pos++]; if (PDFCharIsLineEnding(ch) || ch == ' ' || ch == '\t') continue; if (ch == 'z') { - FXSYS_memset(dest_buf + dest_size, 0, 4); + memset(*dest_buf + *dest_size, 0, 4); state = 0; res = 0; - dest_size += 4; - } else if (ch >= '!' && ch <= 'u') { - res = res * 85 + ch - 33; - state++; - if (state == 5) { - for (size_t i = 0; i < 4; i++) { - dest_buf[dest_size++] = (uint8_t)(res >> (3 - i) * 8); - } - state = 0; - res = 0; - } - } else { - // The end or illegal character. + *dest_size += 4; + continue; + } + + // Check for the end or illegal character. + if (ch < '!' || ch > 'u') break; + + res = res * 85 + ch - 33; + if (state < 4) { + ++state; + continue; + } + + for (size_t i = 0; i < 4; ++i) { + (*dest_buf)[(*dest_size)++] = static_cast(res >> (3 - i) * 8); } + state = 0; + res = 0; } // Handle partial group. if (state) { - for (size_t i = state; i < 5; i++) + for (size_t i = state; i < 5; ++i) res = res * 85 + 84; - for (size_t i = 0; i < state - 1; i++) - dest_buf[dest_size++] = (uint8_t)(res >> (3 - i) * 8); + for (size_t i = 0; i < state - 1; ++i) + (*dest_buf)[(*dest_size)++] = static_cast(res >> (3 - i) * 8); } if (pos < src_size && src_buf[pos] == '>') - pos++; + ++pos; return pos; } uint32_t HexDecode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size) { - dest_size = 0; + uint8_t** dest_buf, + uint32_t* dest_size) { + *dest_size = 0; if (src_size == 0) { - dest_buf = nullptr; + *dest_buf = nullptr; return 0; } uint32_t i = 0; // Find the end of data. while (i < src_size && src_buf[i] != '>') - i++; + ++i; - dest_buf = FX_Alloc(uint8_t, i / 2 + 1); + *dest_buf = FX_Alloc(uint8_t, i / 2 + 1); bool bFirst = true; - for (i = 0; i < src_size; i++) { + for (i = 0; i < src_size; ++i) { uint8_t ch = src_buf[i]; if (PDFCharIsLineEnding(ch) || ch == ' ' || ch == '\t') continue; @@ -174,46 +184,45 @@ uint32_t HexDecode(const uint8_t* src_buf, if (!std::isxdigit(ch)) continue; - int digit = FXSYS_toHexDigit(ch); + int digit = FXSYS_HexCharToInt(ch); if (bFirst) - dest_buf[dest_size] = digit * 16; + (*dest_buf)[*dest_size] = digit * 16; else - dest_buf[dest_size++] += digit; - + (*dest_buf)[(*dest_size)++] += digit; bFirst = !bFirst; } if (!bFirst) - dest_size++; + ++(*dest_size); return i; } uint32_t RunLengthDecode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size) { + uint8_t** dest_buf, + uint32_t* dest_size) { uint32_t i = 0; - dest_size = 0; + *dest_size = 0; while (i < src_size) { if (src_buf[i] == 128) break; - uint32_t old = dest_size; + uint32_t old = *dest_size; if (src_buf[i] < 128) { - dest_size += src_buf[i] + 1; - if (dest_size < old) + *dest_size += src_buf[i] + 1; + if (*dest_size < old) return FX_INVALID_OFFSET; i += src_buf[i] + 2; } else { - dest_size += 257 - src_buf[i]; - if (dest_size < old) + *dest_size += 257 - src_buf[i]; + if (*dest_size < old) return FX_INVALID_OFFSET; i += 2; } } - if (dest_size >= kMaxStreamSize) + if (*dest_size >= kMaxStreamSize) return FX_INVALID_OFFSET; - dest_buf = FX_Alloc(uint8_t, dest_size); + *dest_buf = FX_Alloc(uint8_t, *dest_size); i = 0; int dest_count = 0; while (i < src_size) { @@ -226,22 +235,20 @@ uint32_t RunLengthDecode(const uint8_t* src_buf, if (buf_left < copy_len) { uint32_t delta = copy_len - buf_left; copy_len = buf_left; - FXSYS_memset(dest_buf + dest_count + copy_len, '\0', delta); + memset(*dest_buf + dest_count + copy_len, '\0', delta); } - FXSYS_memcpy(dest_buf + dest_count, src_buf + i + 1, copy_len); + memcpy(*dest_buf + dest_count, src_buf + i + 1, copy_len); dest_count += src_buf[i] + 1; i += src_buf[i] + 2; } else { int fill = 0; - if (i < src_size - 1) { + if (i < src_size - 1) fill = src_buf[i + 1]; - } - FXSYS_memset(dest_buf + dest_count, fill, 257 - src_buf[i]); + memset(*dest_buf + dest_count, fill, 257 - src_buf[i]); dest_count += 257 - src_buf[i]; i += 2; } } - return std::min(i + 1, src_size); } @@ -264,9 +271,8 @@ std::unique_ptr FPDFAPI_CreateFaxDecoder( BlackIs1 = !!pParams->GetIntegerFor("BlackIs1"); Columns = pParams->GetIntegerFor("Columns", 1728); Rows = pParams->GetIntegerFor("Rows"); - if (Rows > USHRT_MAX) { + if (Rows > USHRT_MAX) Rows = 0; - } } return CPDF_ModuleMgr::Get()->GetFaxModule()->CreateDecoder( src_buf, src_size, width, height, K, EndOfLine, ByteAlign, BlackIs1, @@ -282,7 +288,9 @@ std::unique_ptr FPDFAPI_CreateFlateDecoder( int bpc, const CPDF_Dictionary* pParams) { int predictor = 0; - int Colors = 0, BitsPerComponent = 0, Columns = 0; + int Colors = 0; + int BitsPerComponent = 0; + int Columns = 0; if (pParams) { predictor = pParams->GetIntegerFor("Predictor"); Colors = pParams->GetIntegerFor("Colors", 1); @@ -301,8 +309,8 @@ uint32_t FPDFAPI_FlateOrLZWDecode(bool bLZW, uint32_t src_size, CPDF_Dictionary* pParams, uint32_t estimated_size, - uint8_t*& dest_buf, - uint32_t& dest_size) { + uint8_t** dest_buf, + uint32_t* dest_size) { int predictor = 0; int Colors = 0; int BitsPerComponent = 0; @@ -315,7 +323,7 @@ uint32_t FPDFAPI_FlateOrLZWDecode(bool bLZW, BitsPerComponent = pParams->GetIntegerFor("BitsPerComponent", 8); Columns = pParams->GetIntegerFor("Columns", 1); if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns)) - return (uint32_t)-1; + return FX_INVALID_OFFSET; } return CPDF_ModuleMgr::Get()->GetFlateModule()->FlateOrLZWDecode( bLZW, src_buf, src_size, bEarlyChange, predictor, Colors, @@ -325,12 +333,12 @@ uint32_t FPDFAPI_FlateOrLZWDecode(bool bLZW, bool PDF_DataDecode(const uint8_t* src_buf, uint32_t src_size, const CPDF_Dictionary* pDict, - uint8_t*& dest_buf, - uint32_t& dest_size, - CFX_ByteString& ImageEncoding, - CPDF_Dictionary*& pImageParms, uint32_t last_estimated_size, - bool bImageAcc) { + bool bImageAcc, + uint8_t** dest_buf, + uint32_t* dest_size, + ByteString* ImageEncoding, + CPDF_Dictionary** pImageParms) { CPDF_Object* pDecoder = pDict ? pDict->GetDirectObjectFor("Filter") : nullptr; if (!pDecoder || (!pDecoder->IsArray() && !pDecoder->IsName())) return false; @@ -338,10 +346,10 @@ bool PDF_DataDecode(const uint8_t* src_buf, CPDF_Object* pParams = pDict ? pDict->GetDirectObjectFor("DecodeParms") : nullptr; - std::vector> DecoderArray; + std::vector> DecoderArray; if (CPDF_Array* pDecoders = pDecoder->AsArray()) { CPDF_Array* pParamsArray = ToArray(pParams); - for (size_t i = 0; i < pDecoders->GetCount(); i++) { + for (size_t i = 0; i < pDecoders->GetCount(); ++i) { DecoderArray.push_back( {pDecoders->GetStringAt(i), pParamsArray ? pParamsArray->GetDictAt(i) : nullptr}); @@ -352,141 +360,134 @@ bool PDF_DataDecode(const uint8_t* src_buf, } uint8_t* last_buf = const_cast(src_buf); uint32_t last_size = src_size; - int nSize = pdfium::CollectionSize(DecoderArray); - for (int i = 0; i < nSize; i++) { + size_t nSize = DecoderArray.size(); + for (size_t i = 0; i < nSize; ++i) { int estimated_size = i == nSize - 1 ? last_estimated_size : 0; - CFX_ByteString decoder = DecoderArray[i].first; + ByteString decoder = DecoderArray[i].first; CPDF_Dictionary* pParam = ToDictionary(DecoderArray[i].second); uint8_t* new_buf = nullptr; - uint32_t new_size = (uint32_t)-1; - int offset = -1; + uint32_t new_size = 0xFFFFFFFF; + uint32_t offset = FX_INVALID_OFFSET; + if (decoder == "Crypt") + continue; if (decoder == "FlateDecode" || decoder == "Fl") { if (bImageAcc && i == nSize - 1) { - ImageEncoding = "FlateDecode"; - dest_buf = (uint8_t*)last_buf; - dest_size = last_size; - pImageParms = pParam; + *ImageEncoding = "FlateDecode"; + *dest_buf = last_buf; + *dest_size = last_size; + *pImageParms = pParam; return true; } offset = FPDFAPI_FlateOrLZWDecode(false, last_buf, last_size, pParam, - estimated_size, new_buf, new_size); + estimated_size, &new_buf, &new_size); } else if (decoder == "LZWDecode" || decoder == "LZW") { offset = FPDFAPI_FlateOrLZWDecode(true, last_buf, last_size, pParam, - estimated_size, new_buf, new_size); + estimated_size, &new_buf, &new_size); } else if (decoder == "ASCII85Decode" || decoder == "A85") { - offset = A85Decode(last_buf, last_size, new_buf, new_size); + offset = A85Decode(last_buf, last_size, &new_buf, &new_size); } else if (decoder == "ASCIIHexDecode" || decoder == "AHx") { - offset = HexDecode(last_buf, last_size, new_buf, new_size); + offset = HexDecode(last_buf, last_size, &new_buf, &new_size); } else if (decoder == "RunLengthDecode" || decoder == "RL") { if (bImageAcc && i == nSize - 1) { - ImageEncoding = "RunLengthDecode"; - dest_buf = (uint8_t*)last_buf; - dest_size = last_size; - pImageParms = pParam; + *ImageEncoding = "RunLengthDecode"; + *dest_buf = last_buf; + *dest_size = last_size; + *pImageParms = pParam; return true; } - offset = RunLengthDecode(last_buf, last_size, new_buf, new_size); - } else if (decoder == "Crypt") { - continue; + offset = RunLengthDecode(last_buf, last_size, &new_buf, &new_size); } else { // If we get here, assume it's an image decoder. - if (decoder == "DCT") { + if (decoder == "DCT") decoder = "DCTDecode"; - } else if (decoder == "CCF") { + else if (decoder == "CCF") decoder = "CCITTFaxDecode"; - } - ImageEncoding = decoder; - pImageParms = pParam; - dest_buf = (uint8_t*)last_buf; - dest_size = last_size; - if (CPDF_Array* pDecoders = pDecoder->AsArray()) - pDecoders->RemoveAt(i + 1, pDecoders->GetCount() - i - 1); + *ImageEncoding = decoder; + *pImageParms = pParam; + *dest_buf = last_buf; + *dest_size = last_size; return true; } - if (last_buf != src_buf) { + if (last_buf != src_buf) FX_Free(last_buf); - } - if (offset == -1) { + if (offset == FX_INVALID_OFFSET) { FX_Free(new_buf); return false; } last_buf = new_buf; last_size = new_size; } - ImageEncoding = ""; - pImageParms = nullptr; - dest_buf = last_buf; - dest_size = last_size; + ImageEncoding->clear(); + *pImageParms = nullptr; + *dest_buf = last_buf; + *dest_size = last_size; return true; } -CFX_WideString PDF_DecodeText(const uint8_t* src_data, uint32_t src_len) { - CFX_WideString result; +WideString PDF_DecodeText(const uint8_t* src_data, uint32_t src_len) { + WideString result; if (src_len >= 2 && ((src_data[0] == 0xfe && src_data[1] == 0xff) || (src_data[0] == 0xff && src_data[1] == 0xfe))) { - bool bBE = src_data[0] == 0xfe; uint32_t max_chars = (src_len - 2) / 2; - if (!max_chars) { + if (!max_chars) return result; - } - if (src_data[0] == 0xff) { - bBE = !src_data[2]; - } - FX_WCHAR* dest_buf = result.GetBuffer(max_chars); + + bool bBE = src_data[0] == 0xfe || (src_data[0] == 0xff && !src_data[2]); + wchar_t* dest_buf = result.GetBuffer(max_chars); const uint8_t* uni_str = src_data + 2; int dest_pos = 0; for (uint32_t i = 0; i < max_chars * 2; i += 2) { - uint16_t unicode = bBE ? (uni_str[i] << 8 | uni_str[i + 1]) - : (uni_str[i + 1] << 8 | uni_str[i]); - if (unicode == 0x1b) { - i += 2; - while (i < max_chars * 2) { - uint16_t unicode2 = bBE ? (uni_str[i] << 8 | uni_str[i + 1]) - : (uni_str[i + 1] << 8 | uni_str[i]); - i += 2; - if (unicode2 == 0x1b) - break; - } - } else { + uint16_t unicode = GetUnicodeFromBytes(uni_str + i, bBE); + if (unicode != 0x1b) { dest_buf[dest_pos++] = unicode; + continue; + } + + i += 2; + while (i < max_chars * 2) { + uint16_t unicode2 = GetUnicodeFromBytes(uni_str + i, bBE); + i += 2; + if (unicode2 == 0x1b) + break; } } result.ReleaseBuffer(dest_pos); } else { - FX_WCHAR* dest_buf = result.GetBuffer(src_len); - for (uint32_t i = 0; i < src_len; i++) + wchar_t* dest_buf = result.GetBuffer(src_len); + for (uint32_t i = 0; i < src_len; ++i) dest_buf[i] = PDFDocEncoding[src_data[i]]; result.ReleaseBuffer(src_len); } return result; } -CFX_WideString PDF_DecodeText(const CFX_ByteString& bstr) { - return PDF_DecodeText((const uint8_t*)bstr.c_str(), bstr.GetLength()); +WideString PDF_DecodeText(const ByteString& bstr) { + return PDF_DecodeText(reinterpret_cast(bstr.c_str()), + bstr.GetLength()); } -CFX_ByteString PDF_EncodeText(const FX_WCHAR* pString, int len) { - if (len == -1) { - len = FXSYS_wcslen(pString); - } - CFX_ByteString result; - FX_CHAR* dest_buf1 = result.GetBuffer(len); +ByteString PDF_EncodeText(const wchar_t* pString, int len) { + if (len == -1) + len = wcslen(pString); + + ByteString result; + char* dest_buf1 = result.GetBuffer(len); int i; - for (i = 0; i < len; i++) { + for (i = 0; i < len; ++i) { int code; - for (code = 0; code < 256; code++) - if (PDFDocEncoding[code] == pString[i]) { + for (code = 0; code < 256; ++code) { + if (PDFDocEncoding[code] == pString[i]) break; - } - if (code == 256) { - break; } + + if (code == 256) + break; + dest_buf1[i] = code; } result.ReleaseBuffer(i); - if (i == len) { + if (i == len) return result; - } if (len > INT_MAX / 2 - 1) { result.ReleaseBuffer(0); @@ -495,36 +496,38 @@ CFX_ByteString PDF_EncodeText(const FX_WCHAR* pString, int len) { int encLen = len * 2 + 2; - uint8_t* dest_buf2 = (uint8_t*)result.GetBuffer(encLen); + uint8_t* dest_buf2 = reinterpret_cast(result.GetBuffer(encLen)); dest_buf2[0] = 0xfe; dest_buf2[1] = 0xff; dest_buf2 += 2; - for (int j = 0; j < len; j++) { + for (int j = 0; j < len; ++j) { *dest_buf2++ = pString[j] >> 8; - *dest_buf2++ = (uint8_t)pString[j]; + *dest_buf2++ = static_cast(pString[j]); } result.ReleaseBuffer(encLen); return result; } -CFX_ByteString PDF_EncodeText(const CFX_WideString& str) { +ByteString PDF_EncodeText(const WideString& str) { return PDF_EncodeText(str.c_str(), str.GetLength()); } -CFX_ByteString PDF_EncodeString(const CFX_ByteString& src, bool bHex) { - CFX_ByteTextBuf result; +ByteString PDF_EncodeString(const ByteString& src, bool bHex) { + std::ostringstream result; int srclen = src.GetLength(); if (bHex) { - result.AppendChar('<'); - for (int i = 0; i < srclen; i++) { - result.AppendChar("0123456789ABCDEF"[src[i] / 16]); - result.AppendChar("0123456789ABCDEF"[src[i] % 16]); + result << '<'; + for (int i = 0; i < srclen; ++i) { + char buf[2]; + FXSYS_IntToTwoHexChars(src[i], buf); + result << buf[0]; + result << buf[1]; } - result.AppendChar('>'); - return result.MakeString(); + result << '>'; + return ByteString(result); } - result.AppendChar('('); - for (int i = 0; i < srclen; i++) { + result << '('; + for (int i = 0; i < srclen; ++i) { uint8_t ch = src[i]; if (ch == 0x0a) { result << "\\n"; @@ -535,11 +538,11 @@ CFX_ByteString PDF_EncodeString(const CFX_ByteString& src, bool bHex) { continue; } if (ch == ')' || ch == '\\' || ch == '(') - result.AppendChar('\\'); - result.AppendChar(ch); + result << '\\'; + result << static_cast(ch); } - result.AppendChar(')'); - return result.MakeString(); + result << ')'; + return ByteString(result); } bool FlateEncode(const uint8_t* src_buf, @@ -547,8 +550,7 @@ bool FlateEncode(const uint8_t* src_buf, uint8_t** dest_buf, uint32_t* dest_size) { CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); - return pEncoders && - pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf, + return pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf, dest_size); } @@ -557,19 +559,15 @@ bool PngEncode(const uint8_t* src_buf, uint8_t** dest_buf, uint32_t* dest_size) { CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); - return pEncoders && - pEncoders->GetFlateModule()->PngEncode(src_buf, src_size, dest_buf, + return pEncoders->GetFlateModule()->PngEncode(src_buf, src_size, dest_buf, dest_size); } uint32_t FlateDecode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size) { + uint8_t** dest_buf, + uint32_t* dest_size) { CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); - if (pEncoders) { - return pEncoders->GetFlateModule()->FlateOrLZWDecode( - false, src_buf, src_size, false, 0, 0, 0, 0, 0, dest_buf, dest_size); - } - return 0; + return pEncoders->GetFlateModule()->FlateOrLZWDecode( + false, src_buf, src_size, false, 0, 0, 0, 0, 0, dest_buf, dest_size); } diff --git a/core/fpdfapi/parser/fpdf_parser_decode.h b/core/fpdfapi/parser/fpdf_parser_decode.h index dc8ecf0c9b56f069247160f1325f2c953d10ec76..6650b68c06f48c3ed0bd919fc1be358b054bcb78 100644 --- a/core/fpdfapi/parser/fpdf_parser_decode.h +++ b/core/fpdfapi/parser/fpdf_parser_decode.h @@ -9,7 +9,7 @@ #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_string.h" class CCodec_ScanlineDecoder; class CPDF_Dictionary; @@ -17,14 +17,14 @@ class CPDF_Dictionary; // Indexed by 8-bit char code, contains unicode code points. extern const uint16_t PDFDocEncoding[256]; -CFX_ByteString PDF_NameDecode(const CFX_ByteStringC& orig); -CFX_ByteString PDF_NameDecode(const CFX_ByteString& orig); -CFX_ByteString PDF_NameEncode(const CFX_ByteString& orig); -CFX_ByteString PDF_EncodeString(const CFX_ByteString& src, bool bHex = false); -CFX_WideString PDF_DecodeText(const uint8_t* pData, uint32_t size); -CFX_WideString PDF_DecodeText(const CFX_ByteString& bstr); -CFX_ByteString PDF_EncodeText(const FX_WCHAR* pString, int len = -1); -CFX_ByteString PDF_EncodeText(const CFX_WideString& str); +ByteString PDF_NameDecode(const ByteStringView& orig); +ByteString PDF_NameDecode(const ByteString& orig); +ByteString PDF_NameEncode(const ByteString& orig); +ByteString PDF_EncodeString(const ByteString& src, bool bHex); +WideString PDF_DecodeText(const uint8_t* pData, uint32_t size); +WideString PDF_DecodeText(const ByteString& bstr); +ByteString PDF_EncodeText(const wchar_t* pString, int len); +ByteString PDF_EncodeText(const WideString& str); bool FlateEncode(const uint8_t* src_buf, uint32_t src_size, @@ -41,12 +41,13 @@ bool PngEncode(const uint8_t* src_buf, uint32_t FlateDecode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size); + uint8_t** dest_buf, + uint32_t* dest_size); + uint32_t RunLengthDecode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size); + uint8_t** dest_buf, + uint32_t* dest_size); std::unique_ptr FPDFAPI_CreateFaxDecoder( const uint8_t* src_buf, @@ -64,32 +65,32 @@ std::unique_ptr FPDFAPI_CreateFlateDecoder( int bpc, const CPDF_Dictionary* pParams); -// Public for testing. uint32_t A85Decode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size); -// Public for testing. + uint8_t** dest_buf, + uint32_t* dest_size); + uint32_t HexDecode(const uint8_t* src_buf, uint32_t src_size, - uint8_t*& dest_buf, - uint32_t& dest_size); -// Public for testing. + uint8_t** dest_buf, + uint32_t* dest_size); + uint32_t FPDFAPI_FlateOrLZWDecode(bool bLZW, const uint8_t* src_buf, uint32_t src_size, CPDF_Dictionary* pParams, uint32_t estimated_size, - uint8_t*& dest_buf, - uint32_t& dest_size); + uint8_t** dest_buf, + uint32_t* dest_size); + bool PDF_DataDecode(const uint8_t* src_buf, uint32_t src_size, const CPDF_Dictionary* pDict, - uint8_t*& dest_buf, - uint32_t& dest_size, - CFX_ByteString& ImageEncoding, - CPDF_Dictionary*& pImageParms, uint32_t estimated_size, - bool bImageAcc); + bool bImageAcc, + uint8_t** dest_buf, + uint32_t* dest_size, + ByteString* ImageEncoding, + CPDF_Dictionary** pImageParms); #endif // CORE_FPDFAPI_PARSER_FPDF_PARSER_DECODE_H_ diff --git a/core/fpdfapi/parser/fpdf_parser_decode_embeddertest.cpp b/core/fpdfapi/parser/fpdf_parser_decode_embeddertest.cpp index 9dfc26e369f34ffdee460bda85e3535c5934b472..e95a4cc5951aa8c91be1398b7991b9ade4722dcb 100644 --- a/core/fpdfapi/parser/fpdf_parser_decode_embeddertest.cpp +++ b/core/fpdfapi/parser/fpdf_parser_decode_embeddertest.cpp @@ -7,19 +7,17 @@ #include #include -#include "core/fxcrt/fx_basic.h" #include "testing/embedder_test.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" -class FPDFParserDecodeEmbeddertest : public EmbedderTest {}; +using FPDFParserDecodeEmbeddertest = EmbedderTest; // NOTE: python's zlib.compress() and zlib.decompress() may be useful for // external validation of the FlateEncode/FlateDecode test cases. TEST_F(FPDFParserDecodeEmbeddertest, FlateEncode) { - pdfium::StrFuncTestData flate_encode_cases[] = { + static const pdfium::StrFuncTestData flate_encode_cases[] = { STR_IN_OUT_CASE("", "\x78\x9c\x03\x00\x00\x00\x00\x01"), STR_IN_OUT_CASE(" ", "\x78\x9c\x53\x00\x00\x00\x21\x00\x21"), STR_IN_OUT_CASE("123", "\x78\x9c\x33\x34\x32\x06\x00\01\x2d\x00\x97"), @@ -39,18 +37,20 @@ TEST_F(FPDFParserDecodeEmbeddertest, FlateEncode) { for (size_t i = 0; i < FX_ArraySize(flate_encode_cases); ++i) { const pdfium::StrFuncTestData& data = flate_encode_cases[i]; unsigned char* buf = nullptr; - unsigned int buf_size; + uint32_t buf_size; EXPECT_TRUE(FlateEncode(data.input, data.input_size, &buf, &buf_size)); ASSERT_TRUE(buf); - EXPECT_EQ(std::string((const char*)data.expected, data.expected_size), - std::string((const char*)buf, buf_size)) + EXPECT_EQ(data.expected_size, buf_size) << " for case " << i; + if (data.expected_size != buf_size) + continue; + EXPECT_EQ(0, memcmp(data.expected, buf, data.expected_size)) << " for case " << i; FX_Free(buf); } } TEST_F(FPDFParserDecodeEmbeddertest, FlateDecode) { - pdfium::DecodeTestData flate_decode_cases[] = { + static const pdfium::DecodeTestData flate_decode_cases[] = { STR_IN_OUT_CASE("", "", 0), STR_IN_OUT_CASE("preposterous nonsense", "", 2), STR_IN_OUT_CASE("\x78\x9c\x03\x00\x00\x00\x00\x01", "", 8), @@ -73,16 +73,18 @@ TEST_F(FPDFParserDecodeEmbeddertest, FlateDecode) { for (size_t i = 0; i < FX_ArraySize(flate_decode_cases); ++i) { const pdfium::DecodeTestData& data = flate_decode_cases[i]; - unsigned char* result = nullptr; - unsigned int result_size; + unsigned char* buf = nullptr; + uint32_t buf_size; EXPECT_EQ(data.processed_size, - FlateDecode(data.input, data.input_size, result, result_size)) + FlateDecode(data.input, data.input_size, &buf, &buf_size)) << " for case " << i; - ASSERT_TRUE(result); - EXPECT_EQ(std::string((const char*)data.expected, data.expected_size), - std::string((const char*)result, result_size)) + ASSERT_TRUE(buf); + EXPECT_EQ(data.expected_size, buf_size) << " for case " << i; + if (data.expected_size != buf_size) + continue; + EXPECT_EQ(0, memcmp(data.expected, buf, data.expected_size)) << " for case " << i; - FX_Free(result); + FX_Free(buf); } } @@ -114,11 +116,12 @@ TEST_F(FPDFParserDecodeEmbeddertest, Bug_455199) { EXPECT_TRUE(OpenDocument("bug_455199.pdf")); FPDF_PAGE page = LoadPage(0); FPDF_BITMAP bitmap = RenderPage(page); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - // Rendering on Mac is inconsistent, so skip this check. - const char* const kExpectedMd5sum = nullptr; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char kExpectedMd5sum[] = "b90475ca64d1348c3bf5e2b77ad9187a"; +#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const char kExpectedMd5sum[] = "e5a6fa28298db07484cd922f3e210c88"; #else - const char kExpectedMd5sum[] = "6f9f0fd903da177babb24dd50a806a56"; + const char kExpectedMd5sum[] = "2baa4c0e1758deba1b9c908e1fbd04ed"; #endif CompareBitmap(bitmap, 200, 200, kExpectedMd5sum); FPDFBitmap_Destroy(bitmap); diff --git a/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp b/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp index 30d30a433da972ec79aa7a5f5e9763ce9f5d78c2..9ab49588252218e4d886b50d717d835703bfd341 100644 --- a/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp +++ b/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp @@ -31,7 +31,7 @@ TEST(fpdf_parser_decode, A85Decode) { uint8_t* result = nullptr; uint32_t result_size = 0; EXPECT_EQ(ptr->processed_size, - A85Decode(ptr->input, ptr->input_size, result, result_size)) + A85Decode(ptr->input, ptr->input_size, &result, &result_size)) << "for case " << i; ASSERT_EQ(ptr->expected_size, result_size); for (size_t j = 0; j < result_size; ++j) { @@ -66,7 +66,7 @@ TEST(fpdf_parser_decode, HexDecode) { uint8_t* result = nullptr; uint32_t result_size = 0; EXPECT_EQ(ptr->processed_size, - HexDecode(ptr->input, ptr->input_size, result, result_size)) + HexDecode(ptr->input, ptr->input_size, &result, &result_size)) << "for case " << i; ASSERT_EQ(ptr->expected_size, result_size); for (size_t j = 0; j < result_size; ++j) { @@ -79,9 +79,9 @@ TEST(fpdf_parser_decode, HexDecode) { TEST(fpdf_parser_decode, EncodeText) { struct EncodeTestData { - const FX_WCHAR* input; - const FX_CHAR* expected_output; - FX_STRSIZE expected_length; + const wchar_t* input; + const char* expected_output; + size_t expected_length; } test_data[] = { // Empty src string. {L"", "", 0}, @@ -99,11 +99,11 @@ TEST(fpdf_parser_decode, EncodeText) { for (size_t i = 0; i < FX_ArraySize(test_data); ++i) { const auto& test_case = test_data[i]; - CFX_ByteString output = PDF_EncodeText(test_case.input); + ByteString output = PDF_EncodeText(test_case.input); ASSERT_EQ(test_case.expected_length, output.GetLength()) << "for case " << i; - const FX_CHAR* str_ptr = output.c_str(); - for (FX_STRSIZE j = 0; j < test_case.expected_length; ++j) { + const char* str_ptr = output.c_str(); + for (size_t j = 0; j < test_case.expected_length; ++j) { EXPECT_EQ(test_case.expected_output[j], str_ptr[j]) << "for case " << i << " char " << j; } diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp index 9583ea70bcb41c35acfe8a3a09f9f84c2661bbfa..45284a4ceb9d7f382d40677d35b560ae2996083f 100644 --- a/core/fpdfapi/parser/fpdf_parser_utility.cpp +++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp @@ -15,7 +15,9 @@ #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_stream.h" +#include "third_party/base/logging.h" // Indexed by 8-bit character code, contains either: // 'W' - for whitespace: NUL, TAB, CR, LF, FF, SPACE, 0x80, 0xff @@ -69,52 +71,50 @@ const char PDF_CharType[256] = { 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'W'}; -int32_t GetHeaderOffset(const CFX_RetainPtr& pFile) { +int32_t GetHeaderOffset(const RetainPtr& pFile) { const size_t kBufSize = 4; uint8_t buf[kBufSize]; for (int32_t offset = 0; offset <= 1024; ++offset) { if (!pFile->ReadBlock(buf, offset, kBufSize)) - return -1; + return kInvalidHeaderOffset; if (memcmp(buf, "%PDF", 4) == 0) return offset; } - return -1; + return kInvalidHeaderOffset; } -int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteString& key) { +int32_t GetDirectInteger(CPDF_Dictionary* pDict, const ByteString& key) { CPDF_Number* pObj = ToNumber(pDict->GetObjectFor(key)); return pObj ? pObj->GetInteger() : 0; } -CFX_ByteString PDF_NameDecode(const CFX_ByteStringC& bstr) { - if (bstr.Find('#') == -1) - return CFX_ByteString(bstr); +ByteString PDF_NameDecode(const ByteStringView& bstr) { + if (!bstr.Contains('#')) + return ByteString(bstr); int size = bstr.GetLength(); - CFX_ByteString result; - FX_CHAR* pDestStart = result.GetBuffer(size); - FX_CHAR* pDest = pDestStart; + ByteString result; + char* pDestStart = result.GetBuffer(size); + char* pDest = pDestStart; for (int i = 0; i < size; i++) { if (bstr[i] == '#' && i < size - 2) { - *pDest++ = - FXSYS_toHexDigit(bstr[i + 1]) * 16 + FXSYS_toHexDigit(bstr[i + 2]); + *pDest++ = FXSYS_HexCharToInt(bstr[i + 1]) * 16 + + FXSYS_HexCharToInt(bstr[i + 2]); i += 2; } else { *pDest++ = bstr[i]; } } - result.ReleaseBuffer((FX_STRSIZE)(pDest - pDestStart)); + result.ReleaseBuffer(static_cast(pDest - pDestStart)); return result; } -CFX_ByteString PDF_NameDecode(const CFX_ByteString& orig) { - if (orig.Find('#') == -1) - return orig; - return PDF_NameDecode(orig.AsStringC()); +ByteString PDF_NameDecode(const ByteString& orig) { + return orig.Contains("#") ? PDF_NameDecode(orig.AsStringView()) : orig; } -CFX_ByteString PDF_NameEncode(const CFX_ByteString& orig) { +ByteString PDF_NameEncode(const ByteString& orig) { uint8_t* src_buf = (uint8_t*)orig.c_str(); int src_len = orig.GetLength(); int dest_len = 0; @@ -131,26 +131,26 @@ CFX_ByteString PDF_NameEncode(const CFX_ByteString& orig) { if (dest_len == src_len) return orig; - CFX_ByteString res; - FX_CHAR* dest_buf = res.GetBuffer(dest_len); + ByteString res; + char* dest_buf = res.GetBuffer(dest_len); dest_len = 0; for (i = 0; i < src_len; i++) { uint8_t ch = src_buf[i]; if (ch >= 0x80 || PDFCharIsWhitespace(ch) || ch == '#' || PDFCharIsDelimiter(ch)) { dest_buf[dest_len++] = '#'; - dest_buf[dest_len++] = "0123456789ABCDEF"[ch / 16]; - dest_buf[dest_len++] = "0123456789ABCDEF"[ch % 16]; + FXSYS_IntToTwoHexChars(ch, dest_buf + dest_len); + dest_len += 2; } else { dest_buf[dest_len++] = ch; } } dest_buf[dest_len] = 0; - res.ReleaseBuffer(); + res.ReleaseBuffer(res.GetStringLength()); return res; } -CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj) { +std::ostream& operator<<(std::ostream& buf, const CPDF_Object* pObj) { if (!pObj) { buf << " null"; return buf; @@ -167,7 +167,7 @@ CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj) { buf << PDF_EncodeString(pObj->GetString(), pObj->AsString()->IsHex()); break; case CPDF_Object::NAME: { - CFX_ByteString str = pObj->GetString(); + ByteString str = pObj->GetString(); buf << "/" << PDF_NameEncode(str); break; } @@ -193,7 +193,7 @@ CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj) { const CPDF_Dictionary* p = pObj->AsDictionary(); buf << "<<"; for (const auto& it : *p) { - const CFX_ByteString& key = it.first; + const ByteString& key = it.first; CPDF_Object* pValue = it.second.get(); buf << "/" << PDF_NameEncode(key); if (pValue && !pValue->IsInline()) { @@ -208,14 +208,15 @@ CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj) { case CPDF_Object::STREAM: { const CPDF_Stream* p = pObj->AsStream(); buf << p->GetDict() << "stream\r\n"; - CPDF_StreamAcc acc; - acc.LoadAllData(p, true); - buf.AppendBlock(acc.GetData(), acc.GetSize()); + auto pAcc = pdfium::MakeRetain(p); + pAcc->LoadAllDataRaw(); + buf.write(reinterpret_cast(pAcc->GetData()), + pAcc->GetSize()); buf << "\r\nendstream"; break; } default: - ASSERT(false); + NOTREACHED(); break; } return buf; diff --git a/core/fpdfapi/parser/fpdf_parser_utility.h b/core/fpdfapi/parser/fpdf_parser_utility.h index 29f54ee853f5537ab5680d1b311951942c1ffd81..e4b922cad22fb018f044f21d67b8b46752817266 100644 --- a/core/fpdfapi/parser/fpdf_parser_utility.h +++ b/core/fpdfapi/parser/fpdf_parser_utility.h @@ -7,12 +7,12 @@ #ifndef CORE_FPDFAPI_PARSER_FPDF_PARSER_UTILITY_H_ #define CORE_FPDFAPI_PARSER_FPDF_PARSER_UTILITY_H_ -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" class IFX_SeekableReadStream; class CPDF_Dictionary; +class CPDF_Object; // Use the accessors below instead of directly accessing PDF_CharType. extern const char PDF_CharType[256]; @@ -34,7 +34,15 @@ inline bool PDFCharIsLineEnding(uint8_t c) { return c == '\r' || c == '\n'; } -int32_t GetHeaderOffset(const CFX_RetainPtr& pFile); -int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteString& key); +constexpr int32_t kInvalidHeaderOffset = -1; + +// On success, return a positive offset value to the PDF header.. If the header +// cannot be found, or if there is an error reading from |pFile|, then return +// |kInvalidHeaderOffset|. +int32_t GetHeaderOffset(const RetainPtr& pFile); + +int32_t GetDirectInteger(CPDF_Dictionary* pDict, const ByteString& key); + +std::ostream& operator<<(std::ostream& buf, const CPDF_Object* pObj); #endif // CORE_FPDFAPI_PARSER_FPDF_PARSER_UTILITY_H_ diff --git a/core/fpdfapi/render/cpdf_charposlist.cpp b/core/fpdfapi/render/cpdf_charposlist.cpp index 639bdcf17b456b8178a6c8da3b9cd9f012114832..c0c700c0cafdf072009ae8193a7e4dc8d50d7330 100644 --- a/core/fpdfapi/render/cpdf_charposlist.cpp +++ b/core/fpdfapi/render/cpdf_charposlist.cpp @@ -8,7 +8,6 @@ #include "core/fpdfapi/font/cpdf_cidfont.h" #include "core/fpdfapi/font/cpdf_font.h" -#include "third_party/base/stl_util.h" CPDF_CharPosList::CPDF_CharPosList() { m_pCharPos = nullptr; @@ -20,15 +19,14 @@ CPDF_CharPosList::~CPDF_CharPosList() { } void CPDF_CharPosList::Load(const std::vector& charCodes, - const std::vector& charPos, + const std::vector& charPos, CPDF_Font* pFont, - FX_FLOAT FontSize) { - int nChars = pdfium::CollectionSize(charCodes); - m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, nChars); + float FontSize) { + m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, charCodes.size()); m_nChars = 0; CPDF_CIDFont* pCIDFont = pFont->AsCIDFont(); bool bVertWriting = pCIDFont && pCIDFont->IsVertWriting(); - for (int iChar = 0; iChar < nChars; iChar++) { + for (size_t iChar = 0; iChar < charCodes.size(); ++iChar) { uint32_t CharCode = charCodes[iChar]; if (CharCode == static_cast(-1)) continue; @@ -37,28 +35,59 @@ void CPDF_CharPosList::Load(const std::vector& charCodes, FXTEXT_CHARPOS& charpos = m_pCharPos[m_nChars++]; if (pCIDFont) charpos.m_bFontStyle = true; - + WideString unicode = pFont->UnicodeFromCharCode(CharCode); + charpos.m_Unicode = !unicode.IsEmpty() ? unicode[0] : CharCode; charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert); - if (charpos.m_GlyphIndex != static_cast(-1)) { + uint32_t GlyphID = charpos.m_GlyphIndex; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode); + GlyphID = charpos.m_ExtGID; +#endif + CFX_Font* pCurrentFont; + if (GlyphID != static_cast(-1)) { charpos.m_FallbackFontPosition = -1; + pCurrentFont = pFont->GetFont(); } else { charpos.m_FallbackFontPosition = pFont->FallbackFontFromCharcode(CharCode); charpos.m_GlyphIndex = pFont->FallbackGlyphFromCharcode( charpos.m_FallbackFontPosition, CharCode); + pCurrentFont = pFont->GetFontFallback(charpos.m_FallbackFontPosition); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + charpos.m_ExtGID = charpos.m_GlyphIndex; +#endif } -// TODO(npm): Figure out how this affects m_ExtGID -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode); -#endif if (!pFont->IsEmbedded() && !pFont->IsCIDFont()) charpos.m_FontCharWidth = pFont->GetCharWidthF(CharCode); else charpos.m_FontCharWidth = 0; - charpos.m_Origin = CFX_PointF(iChar ? charPos[iChar - 1] : 0, 0); + charpos.m_Origin = CFX_PointF(iChar > 0 ? charPos[iChar - 1] : 0, 0); charpos.m_bGlyphAdjust = false; + + float scalingFactor = 1.0f; + if (!pFont->IsEmbedded() && pFont->HasFontWidths() && !bVertWriting && + !pCurrentFont->GetSubstFont()->m_bFlagMM) { + int pdfGlyphWidth = pFont->GetCharWidthF(CharCode); + int ftGlyphWidth = + pCurrentFont ? pCurrentFont->GetGlyphWidth(charpos.m_GlyphIndex) : 0; + if (ftGlyphWidth && pdfGlyphWidth > ftGlyphWidth + 1) { + // Move the initial x position by half of the excess (transformed to + // text space coordinates). + charpos.m_Origin.x += + (pdfGlyphWidth - ftGlyphWidth) * FontSize / 2000.0f; + } else if (pdfGlyphWidth && ftGlyphWidth && + pdfGlyphWidth < ftGlyphWidth) { + scalingFactor = static_cast(pdfGlyphWidth) / ftGlyphWidth; + ASSERT(scalingFactor >= 0.0f); + charpos.m_AdjustMatrix[0] = scalingFactor; + charpos.m_AdjustMatrix[1] = 0.0f; + charpos.m_AdjustMatrix[2] = 0.0f; + charpos.m_AdjustMatrix[3] = 1.0f; + charpos.m_bGlyphAdjust = true; + } + } if (!pCIDFont) continue; @@ -75,9 +104,11 @@ void CPDF_CharPosList::Load(const std::vector& charCodes, const uint8_t* pTransform = pCIDFont->GetCIDTransform(CID); if (pTransform && !bVert) { - charpos.m_AdjustMatrix[0] = pCIDFont->CIDTransformToFloat(pTransform[0]); + charpos.m_AdjustMatrix[0] = + pCIDFont->CIDTransformToFloat(pTransform[0]) * scalingFactor; + charpos.m_AdjustMatrix[1] = + pCIDFont->CIDTransformToFloat(pTransform[1]) * scalingFactor; charpos.m_AdjustMatrix[2] = pCIDFont->CIDTransformToFloat(pTransform[2]); - charpos.m_AdjustMatrix[1] = pCIDFont->CIDTransformToFloat(pTransform[1]); charpos.m_AdjustMatrix[3] = pCIDFont->CIDTransformToFloat(pTransform[3]); charpos.m_Origin.x += pCIDFont->CIDTransformToFloat(pTransform[4]) * FontSize; diff --git a/core/fpdfapi/render/cpdf_charposlist.h b/core/fpdfapi/render/cpdf_charposlist.h index 2f5a44dfa0d2a083521db6ba2ea5baeeb20ded62..c4636bca513b22dbf0898301b34e16077f7458ea 100644 --- a/core/fpdfapi/render/cpdf_charposlist.h +++ b/core/fpdfapi/render/cpdf_charposlist.h @@ -19,9 +19,9 @@ class CPDF_CharPosList { CPDF_CharPosList(); ~CPDF_CharPosList(); void Load(const std::vector& charCodes, - const std::vector& charPos, + const std::vector& charPos, CPDF_Font* pFont, - FX_FLOAT font_size); + float font_size); FXTEXT_CHARPOS* m_pCharPos; uint32_t m_nChars; }; diff --git a/core/fpdfapi/render/cpdf_devicebuffer.cpp b/core/fpdfapi/render/cpdf_devicebuffer.cpp index dec13433e42d496517886189f664a1bae671950d..b96d00208e2070dec7bd44eca9c0507d513e2e4b 100644 --- a/core/fpdfapi/render/cpdf_devicebuffer.cpp +++ b/core/fpdfapi/render/cpdf_devicebuffer.cpp @@ -9,13 +9,13 @@ #include "core/fpdfapi/page/cpdf_pageobject.h" #include "core/fpdfapi/render/cpdf_rendercontext.h" #include "core/fpdfapi/render/cpdf_renderoptions.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" #include "third_party/base/ptr_util.h" -CPDF_DeviceBuffer::CPDF_DeviceBuffer() - : m_pDevice(nullptr), m_pContext(nullptr), m_pObject(nullptr) {} +CPDF_DeviceBuffer::CPDF_DeviceBuffer() {} CPDF_DeviceBuffer::~CPDF_DeviceBuffer() {} @@ -29,7 +29,7 @@ bool CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, m_Rect = *pRect; m_pObject = pObj; m_Matrix.Translate(-pRect->left, -pRect->top); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE); int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE); if (horz_size && vert_size && max_dpi) { @@ -38,19 +38,17 @@ bool CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10); if (dpih > max_dpi) - m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f); + m_Matrix.Scale((float)(max_dpi) / dpih, 1.0f); if (dpiv > max_dpi) - m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv); + m_Matrix.Scale(1.0f, (float)(max_dpi) / (float)dpiv); } #endif CFX_Matrix ctm = m_pDevice->GetCTM(); - m_Matrix.Concat(CFX_Matrix(FXSYS_fabs(ctm.a), 0, 0, FXSYS_fabs(ctm.d), 0, 0)); + m_Matrix.Concat(CFX_Matrix(fabs(ctm.a), 0, 0, fabs(ctm.d), 0, 0)); - CFX_FloatRect rect(*pRect); - m_Matrix.TransformRect(rect); - - FX_RECT bitmap_rect = rect.GetOuterRect(); - m_pBitmap = pdfium::MakeUnique(); + FX_RECT bitmap_rect = + m_Matrix.TransformRect(CFX_FloatRect(*pRect)).GetOuterRect(); + m_pBitmap = pdfium::MakeRetain(); m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb); return true; } @@ -58,19 +56,19 @@ bool CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, void CPDF_DeviceBuffer::OutputToDevice() { if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) { if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) { - m_pDevice->SetDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top); + m_pDevice->SetDIBits(m_pBitmap, m_Rect.left, m_Rect.top); } else { - m_pDevice->StretchDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top, + m_pDevice->StretchDIBits(m_pBitmap, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); } return; } - CFX_DIBitmap buffer; - m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(), + auto pBuffer = pdfium::MakeRetain(); + m_pDevice->CreateCompatibleBitmap(pBuffer, m_pBitmap->GetWidth(), m_pBitmap->GetHeight()); - m_pContext->GetBackground(&buffer, m_pObject, nullptr, &m_Matrix); - buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(), - m_pBitmap.get(), 0, 0); - m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(), + m_pContext->GetBackground(pBuffer, m_pObject.Get(), nullptr, &m_Matrix); + pBuffer->CompositeBitmap(0, 0, pBuffer->GetWidth(), pBuffer->GetHeight(), + m_pBitmap, 0, 0); + m_pDevice->StretchDIBits(pBuffer, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); } diff --git a/core/fpdfapi/render/cpdf_devicebuffer.h b/core/fpdfapi/render/cpdf_devicebuffer.h index e5bbf1fcdf81429b0d2df9464750f7afb409ce71..854906e03c608d98955fca35f03977776e059daa 100644 --- a/core/fpdfapi/render/cpdf_devicebuffer.h +++ b/core/fpdfapi/render/cpdf_devicebuffer.h @@ -10,6 +10,8 @@ #include #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CFX_DIBitmap; class CFX_RenderDevice; @@ -20,21 +22,22 @@ class CPDF_DeviceBuffer { public: CPDF_DeviceBuffer(); ~CPDF_DeviceBuffer(); + bool Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect, const CPDF_PageObject* pObj, int max_dpi); void OutputToDevice(); - CFX_DIBitmap* GetBitmap() const { return m_pBitmap.get(); } + RetainPtr GetBitmap() const { return m_pBitmap; } const CFX_Matrix* GetMatrix() const { return &m_Matrix; } private: - CFX_RenderDevice* m_pDevice; - CPDF_RenderContext* m_pContext; + UnownedPtr m_pDevice; + UnownedPtr m_pContext; + UnownedPtr m_pObject; + RetainPtr m_pBitmap; FX_RECT m_Rect; - const CPDF_PageObject* m_pObject; - std::unique_ptr m_pBitmap; CFX_Matrix m_Matrix; }; diff --git a/core/fpdfapi/render/cpdf_dibsource.cpp b/core/fpdfapi/render/cpdf_dibsource.cpp index 33a8d930a538c41111d0a3b224b514f78444c1f6..c1b96073d941d66f53f6dfbb33cacef4d39bf69b 100644 --- a/core/fpdfapi/render/cpdf_dibsource.cpp +++ b/core/fpdfapi/render/cpdf_dibsource.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "core/fpdfapi/cpdf_modulemgr.h" @@ -20,8 +21,16 @@ #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfapi/render/cpdf_pagerendercache.h" #include "core/fpdfapi/render/cpdf_renderstatus.h" +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcodec/codec/ccodec_jbig2module.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" +#include "core/fxcodec/codec/ccodec_jpxmodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" +#include "core/fxcodec/codec/cjpx_decoder.h" #include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/cfx_fixedbufgrow.h" #include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "third_party/base/ptr_util.h" namespace { @@ -78,16 +87,17 @@ class JpxBitMapContext { explicit JpxBitMapContext(CCodec_JpxModule* jpx_module) : jpx_module_(jpx_module), decoder_(nullptr) {} - ~JpxBitMapContext() { jpx_module_->DestroyDecoder(decoder_); } + ~JpxBitMapContext() {} - // Takes ownership of |decoder|. - void set_decoder(CJPX_Decoder* decoder) { decoder_ = decoder; } + void set_decoder(std::unique_ptr decoder) { + decoder_ = std::move(decoder); + } - CJPX_Decoder* decoder() { return decoder_; } + CJPX_Decoder* decoder() { return decoder_.get(); } private: CCodec_JpxModule* const jpx_module_; // Weak pointer. - CJPX_Decoder* decoder_; // Decoder, owned. + std::unique_ptr decoder_; // Disallow evil constructors JpxBitMapContext(const JpxBitMapContext&); @@ -126,11 +136,12 @@ CPDF_DIBSource::CPDF_DIBSource() CPDF_DIBSource::~CPDF_DIBSource() { FX_Free(m_pMaskedLine); FX_Free(m_pLineBuf); - m_pCachedBitmap.reset(); + m_pCachedBitmap.Reset(); // TODO(tsepez): determine if required early here. FX_Free(m_pCompData); - CPDF_ColorSpace* pCS = m_pColorSpace; - if (pCS && m_pDocument) { - m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); + if (m_pColorSpace && m_pDocument) { + auto* pPageData = m_pDocument->GetPageData(); + if (pPageData) + pPageData->ReleaseColorSpace(m_pColorSpace->GetArray()); } } @@ -163,8 +174,8 @@ bool CPDF_DIBSource::Load(CPDF_Document* pDoc, const CPDF_Stream* pStream) { if (!src_size.IsValid()) return false; - m_pStreamAcc = pdfium::MakeUnique(); - m_pStreamAcc->LoadAllData(pStream, false, src_size.ValueOrDie(), true); + m_pStreamAcc = pdfium::MakeRetain(pStream); + m_pStreamAcc->LoadAllData(false, src_size.ValueOrDie(), true); if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData()) return false; @@ -202,7 +213,7 @@ bool CPDF_DIBSource::Load(CPDF_Document* pDoc, const CPDF_Stream* pStream) { return true; } -int CPDF_DIBSource::ContinueToLoadMask() { +bool CPDF_DIBSource::ContinueToLoadMask() { if (m_bImageMask) { m_bpp = 1; m_bpc = 1; @@ -216,12 +227,12 @@ int CPDF_DIBSource::ContinueToLoadMask() { m_bpp = 24; } if (!m_bpc || !m_nComponents) { - return 0; + return false; } FX_SAFE_UINT32 pitch = CalculatePitch32(m_bpp, m_Width); - if (!pitch.IsValid()) { - return 0; - } + if (!pitch.IsValid()) + return false; + m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie()); if (m_pColorSpace && m_bStdCS) { m_pColorSpace->EnableStdConversion(true); @@ -231,13 +242,12 @@ int CPDF_DIBSource::ContinueToLoadMask() { m_bpp = 32; m_AlphaFlag = 2; pitch = CalculatePitch32(m_bpp, m_Width); - if (!pitch.IsValid()) { - return 0; - } + if (!pitch.IsValid()) + return false; m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie()); } m_Pitch = pitch.ValueOrDie(); - return 1; + return true; } int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc, @@ -248,9 +258,9 @@ int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc, bool bStdCS, uint32_t GroupFamily, bool bLoadMask) { - if (!pStream) { + if (!pStream) return 0; - } + m_pDocument = pDoc; m_pDict = pStream->GetDict(); m_pStream = pStream; @@ -268,118 +278,88 @@ int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc, pPageResources)) { return 0; } - if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) { + if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) return 0; - } + FX_SAFE_UINT32 src_size = CalculatePitch8(m_bpc, m_nComponents, m_Width) * m_Height; - if (!src_size.IsValid()) { + if (!src_size.IsValid()) return 0; - } - m_pStreamAcc = pdfium::MakeUnique(); - m_pStreamAcc->LoadAllData(pStream, false, src_size.ValueOrDie(), true); - if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData()) { + + m_pStreamAcc = pdfium::MakeRetain(pStream); + m_pStreamAcc->LoadAllData(false, src_size.ValueOrDie(), true); + if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData()) return 0; - } - int ret = CreateDecoder(); - if (!ret) - return ret; - if (ret != 1) { - if (!ContinueToLoadMask()) { - return 0; - } - if (m_bHasMask) { - StratLoadMask(); - } - return ret; - } - if (!ContinueToLoadMask()) { + int iCreatedDecoder = CreateDecoder(); + if (!iCreatedDecoder) return 0; - } - if (m_bHasMask) { - ret = StratLoadMask(); - } - if (ret == 2) { - return ret; - } - if (m_pColorSpace && m_bStdCS) { + + if (!ContinueToLoadMask()) + return 0; + + int iLoadedMask = m_bHasMask ? StartLoadMask() : 1; + if (iCreatedDecoder == 2 || iLoadedMask == 2) + return 2; + + ASSERT(iCreatedDecoder == 1); + ASSERT(iLoadedMask == 1); + if (m_pColorSpace && m_bStdCS) m_pColorSpace->EnableStdConversion(false); - } - return ret; + return 1; } -int CPDF_DIBSource::ContinueLoadDIBSource(IFX_Pause* pPause) { - FXCODEC_STATUS ret; - if (m_Status == 1) { - const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); - if (decoder == "JPXDecode") { - return 0; - } - CCodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module(); - if (!m_pJbig2Context) { - m_pJbig2Context = pdfium::MakeUnique(); - if (m_pStreamAcc->GetImageParam()) { - CPDF_Stream* pGlobals = - m_pStreamAcc->GetImageParam()->GetStreamFor("JBIG2Globals"); - if (pGlobals) { - m_pGlobalStream = pdfium::MakeUnique(); - m_pGlobalStream->LoadAllData(pGlobals, false); - } - } - ret = pJbig2Module->StartDecode( - m_pJbig2Context.get(), m_pDocument->CodecContext(), m_Width, m_Height, - m_pStreamAcc.get(), m_pGlobalStream.get(), - m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), pPause); - if (ret < 0) { - m_pCachedBitmap.reset(); - m_pGlobalStream.reset(); - m_pJbig2Context.reset(); - return 0; - } - if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) { - return 2; - } - int ret1 = 1; - if (m_bHasMask) { - ret1 = ContinueLoadMaskDIB(pPause); - m_Status = 2; - } - if (ret1 == 2) { - return ret1; - } - if (m_pColorSpace && m_bStdCS) { - m_pColorSpace->EnableStdConversion(false); +int CPDF_DIBSource::ContinueLoadDIBSource(IFX_PauseIndicator* pPause) { + if (m_Status == 2) + return ContinueLoadMaskDIB(pPause); + + if (m_Status != 1) + return 0; + + const ByteString& decoder = m_pStreamAcc->GetImageDecoder(); + if (decoder == "JPXDecode") + return 0; + + FXCODEC_STATUS iDecodeStatus; + CCodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module(); + if (!m_pJbig2Context) { + m_pJbig2Context = pdfium::MakeUnique(); + if (m_pStreamAcc->GetImageParam()) { + CPDF_Stream* pGlobals = + m_pStreamAcc->GetImageParam()->GetStreamFor("JBIG2Globals"); + if (pGlobals) { + m_pGlobalStream = pdfium::MakeRetain(pGlobals); + m_pGlobalStream->LoadAllDataFiltered(); } - return ret1; } - ret = pJbig2Module->ContinueDecode(m_pJbig2Context.get(), pPause); - if (ret < 0) { - m_pCachedBitmap.reset(); - m_pGlobalStream.reset(); - m_pJbig2Context.reset(); - return 0; - } - if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) { - return 2; - } - int ret1 = 1; - if (m_bHasMask) { - ret1 = ContinueLoadMaskDIB(pPause); - m_Status = 2; - } - if (ret1 == 2) { - return ret1; - } - if (m_pColorSpace && m_bStdCS) { - m_pColorSpace->EnableStdConversion(false); - } - return ret1; + iDecodeStatus = pJbig2Module->StartDecode( + m_pJbig2Context.get(), m_pDocument->CodecContext(), m_Width, m_Height, + m_pStreamAcc, m_pGlobalStream, m_pCachedBitmap->GetBuffer(), + m_pCachedBitmap->GetPitch(), pPause); + } else { + iDecodeStatus = pJbig2Module->ContinueDecode(m_pJbig2Context.get(), pPause); } - if (m_Status == 2) { - return ContinueLoadMaskDIB(pPause); + + if (iDecodeStatus < 0) { + m_pCachedBitmap.Reset(); + m_pGlobalStream.Reset(); + m_pJbig2Context.reset(); + return 0; + } + if (iDecodeStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) + return 2; + + int iContinueStatus = 1; + if (m_bHasMask) { + iContinueStatus = ContinueLoadMaskDIB(pPause); + m_Status = 2; } - return 0; + if (iContinueStatus == 2) + return 2; + + if (m_pColorSpace && m_bStdCS) + m_pColorSpace->EnableStdConversion(false); + return iContinueStatus; } bool CPDF_DIBSource::LoadColorInfo(const CPDF_Dictionary* pFormResources, @@ -392,7 +372,7 @@ bool CPDF_DIBSource::LoadColorInfo(const CPDF_Dictionary* pFormResources, if (!m_bImageMask) { CPDF_Object* pFilter = m_pDict->GetDirectObjectFor("Filter"); if (pFilter) { - CFX_ByteString filter; + ByteString filter; if (pFilter->IsName()) { filter = pFilter->GetString(); } else if (CPDF_Array* pArray = pFilter->AsArray()) { @@ -427,78 +407,75 @@ bool CPDF_DIBSource::LoadColorInfo(const CPDF_Dictionary* pFormResources, m_Family = m_pColorSpace->GetFamily(); m_nComponents = m_pColorSpace->CountComponents(); if (m_Family == PDFCS_ICCBASED && pCSObj->IsName()) { - CFX_ByteString cs = pCSObj->GetString(); - if (cs == "DeviceGray") { + ByteString cs = pCSObj->GetString(); + if (cs == "DeviceGray") m_nComponents = 1; - } else if (cs == "DeviceRGB") { + else if (cs == "DeviceRGB") m_nComponents = 3; - } else if (cs == "DeviceCMYK") { + else if (cs == "DeviceCMYK") m_nComponents = 4; - } } ValidateDictParam(); - m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey); + m_pCompData = GetDecodeAndMaskArray(&m_bDefaultDecode, &m_bColorKey); return !!m_pCompData; } -DIB_COMP_DATA* CPDF_DIBSource::GetDecodeAndMaskArray(bool& bDefaultDecode, - bool& bColorKey) { - if (!m_pColorSpace) { +DIB_COMP_DATA* CPDF_DIBSource::GetDecodeAndMaskArray(bool* bDefaultDecode, + bool* bColorKey) { + if (!m_pColorSpace) return nullptr; - } - DIB_COMP_DATA* pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents); + + DIB_COMP_DATA* const pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents); int max_data = (1 << m_bpc) - 1; CPDF_Array* pDecode = m_pDict->GetArrayFor("Decode"); if (pDecode) { for (uint32_t i = 0; i < m_nComponents; i++) { pCompData[i].m_DecodeMin = pDecode->GetNumberAt(i * 2); - FX_FLOAT max = pDecode->GetNumberAt(i * 2 + 1); + float max = pDecode->GetNumberAt(i * 2 + 1); pCompData[i].m_DecodeStep = (max - pCompData[i].m_DecodeMin) / max_data; - FX_FLOAT def_value; - FX_FLOAT def_min; - FX_FLOAT def_max; - m_pColorSpace->GetDefaultValue(i, def_value, def_min, def_max); - if (m_Family == PDFCS_INDEXED) { + float def_value; + float def_min; + float def_max; + m_pColorSpace->GetDefaultValue(i, &def_value, &def_min, &def_max); + if (m_Family == PDFCS_INDEXED) def_max = max_data; - } - if (def_min != pCompData[i].m_DecodeMin || def_max != max) { - bDefaultDecode = false; - } + if (def_min != pCompData[i].m_DecodeMin || def_max != max) + *bDefaultDecode = false; } } else { for (uint32_t i = 0; i < m_nComponents; i++) { - FX_FLOAT def_value; - m_pColorSpace->GetDefaultValue(i, def_value, pCompData[i].m_DecodeMin, - pCompData[i].m_DecodeStep); - if (m_Family == PDFCS_INDEXED) { + float def_value; + m_pColorSpace->GetDefaultValue(i, &def_value, &pCompData[i].m_DecodeMin, + &pCompData[i].m_DecodeStep); + if (m_Family == PDFCS_INDEXED) pCompData[i].m_DecodeStep = max_data; - } pCompData[i].m_DecodeStep = (pCompData[i].m_DecodeStep - pCompData[i].m_DecodeMin) / max_data; } } - if (!m_pDict->KeyExist("SMask")) { - CPDF_Object* pMask = m_pDict->GetDirectObjectFor("Mask"); - if (!pMask) { - return pCompData; - } - if (CPDF_Array* pArray = pMask->AsArray()) { - if (pArray->GetCount() >= m_nComponents * 2) { - for (uint32_t i = 0; i < m_nComponents; i++) { - int min_num = pArray->GetIntegerAt(i * 2); - int max_num = pArray->GetIntegerAt(i * 2 + 1); - pCompData[i].m_ColorKeyMin = std::max(min_num, 0); - pCompData[i].m_ColorKeyMax = std::min(max_num, max_data); - } + if (m_pDict->KeyExist("SMask")) + return pCompData; + + CPDF_Object* pMask = m_pDict->GetDirectObjectFor("Mask"); + if (!pMask) + return pCompData; + + if (CPDF_Array* pArray = pMask->AsArray()) { + if (pArray->GetCount() >= m_nComponents * 2) { + for (uint32_t i = 0; i < m_nComponents; i++) { + int min_num = pArray->GetIntegerAt(i * 2); + int max_num = pArray->GetIntegerAt(i * 2 + 1); + pCompData[i].m_ColorKeyMin = std::max(min_num, 0); + pCompData[i].m_ColorKeyMax = std::min(max_num, max_data); } - bColorKey = true; } + *bColorKey = true; } return pCompData; } int CPDF_DIBSource::CreateDecoder() { - const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); + const ByteString& decoder = m_pStreamAcc->GetImageDecoder(); if (decoder.IsEmpty()) return 1; @@ -510,10 +487,10 @@ int CPDF_DIBSource::CreateDecoder() { return m_pCachedBitmap ? 1 : 0; } if (decoder == "JBIG2Decode") { - m_pCachedBitmap = pdfium::MakeUnique(); + m_pCachedBitmap = pdfium::MakeRetain(); if (!m_pCachedBitmap->Create( m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) { - m_pCachedBitmap.reset(); + m_pCachedBitmap.Reset(); return 0; } m_Status = 1; @@ -530,70 +507,12 @@ int CPDF_DIBSource::CreateDecoder() { m_pDecoder = FPDFAPI_CreateFlateDecoder( src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc, pParams); } else if (decoder == "RunLengthDecode") { - m_pDecoder = CPDF_ModuleMgr::Get() - ->GetCodecModule() - ->GetBasicModule() - ->CreateRunLengthDecoder(src_data, src_size, m_Width, - m_Height, m_nComponents, m_bpc); + CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); + m_pDecoder = pEncoders->GetBasicModule()->CreateRunLengthDecoder( + src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc); } else if (decoder == "DCTDecode") { - m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( - src_data, src_size, m_Width, m_Height, m_nComponents, - !pParams || pParams->GetIntegerFor("ColorTransform", 1)); - if (!m_pDecoder) { - bool bTransform = false; - int comps; - int bpc; - CCodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule(); - if (pJpegModule->LoadInfo(src_data, src_size, &m_Width, &m_Height, &comps, - &bpc, &bTransform)) { - if (m_nComponents != static_cast(comps)) { - FX_Free(m_pCompData); - m_pCompData = nullptr; - m_nComponents = static_cast(comps); - if (m_pColorSpace) { - switch (m_Family) { - case PDFCS_DEVICEGRAY: - case PDFCS_DEVICERGB: - case PDFCS_DEVICECMYK: { - uint32_t dwMinComps = ComponentsForFamily(m_Family); - if (m_pColorSpace->CountComponents() < dwMinComps || - m_nComponents < dwMinComps) { - return 0; - } - break; - } - case PDFCS_LAB: { - if (m_nComponents != 3 || m_pColorSpace->CountComponents() < 3) - return 0; - break; - } - case PDFCS_ICCBASED: { - if (!IsAllowedICCComponents(m_nComponents) || - !IsAllowedICCComponents(m_pColorSpace->CountComponents()) || - m_pColorSpace->CountComponents() < m_nComponents) { - return 0; - } - break; - } - default: { - if (m_pColorSpace->CountComponents() != m_nComponents) - return 0; - break; - } - } - } else { - if (m_Family == PDFCS_LAB && m_nComponents != 3) - return 0; - } - m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey); - if (!m_pCompData) - return 0; - } - m_bpc = bpc; - m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( - src_data, src_size, m_Width, m_Height, m_nComponents, bTransform); - } - } + if (!CreateDCTDecoder(src_data, src_size, pParams)) + return 0; } if (!m_pDecoder) return 0; @@ -611,12 +530,82 @@ int CPDF_DIBSource::CreateDecoder() { return 1; } +bool CPDF_DIBSource::CreateDCTDecoder(const uint8_t* src_data, + uint32_t src_size, + const CPDF_Dictionary* pParams) { + CCodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule(); + m_pDecoder = pJpegModule->CreateDecoder( + src_data, src_size, m_Width, m_Height, m_nComponents, + !pParams || pParams->GetIntegerFor("ColorTransform", 1)); + if (m_pDecoder) + return true; + + bool bTransform = false; + int comps; + int bpc; + if (!pJpegModule->LoadInfo(src_data, src_size, &m_Width, &m_Height, &comps, + &bpc, &bTransform)) { + return false; + } + + if (m_nComponents == static_cast(comps)) { + m_bpc = bpc; + m_pDecoder = pJpegModule->CreateDecoder( + src_data, src_size, m_Width, m_Height, m_nComponents, bTransform); + return true; + } + + m_nComponents = static_cast(comps); + FX_Free(m_pCompData); + m_pCompData = nullptr; + if (m_pColorSpace) { + switch (m_Family) { + case PDFCS_DEVICEGRAY: + case PDFCS_DEVICERGB: + case PDFCS_DEVICECMYK: { + uint32_t dwMinComps = ComponentsForFamily(m_Family); + if (m_pColorSpace->CountComponents() < dwMinComps || + m_nComponents < dwMinComps) { + return false; + } + break; + } + case PDFCS_LAB: { + if (m_nComponents != 3 || m_pColorSpace->CountComponents() < 3) + return false; + break; + } + case PDFCS_ICCBASED: { + if (!IsAllowedICCComponents(m_nComponents) || + !IsAllowedICCComponents(m_pColorSpace->CountComponents()) || + m_pColorSpace->CountComponents() < m_nComponents) { + return false; + } + break; + } + default: { + if (m_pColorSpace->CountComponents() != m_nComponents) + return false; + break; + } + } + } else { + if (m_Family == PDFCS_LAB && m_nComponents != 3) + return false; + } + m_pCompData = GetDecodeAndMaskArray(&m_bDefaultDecode, &m_bColorKey); + if (!m_pCompData) + return false; + + m_bpc = bpc; + m_pDecoder = pJpegModule->CreateDecoder(src_data, src_size, m_Width, m_Height, + m_nComponents, bTransform); + return true; +} + void CPDF_DIBSource::LoadJpxBitmap() { CCodec_JpxModule* pJpxModule = CPDF_ModuleMgr::Get()->GetJpxModule(); - if (!pJpxModule) - return; - - std::unique_ptr context(new JpxBitMapContext(pJpxModule)); + auto context = pdfium::MakeUnique(pJpxModule); context->set_decoder(pJpxModule->CreateDecoder( m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), m_pColorSpace)); if (!context->decoder()) @@ -659,9 +648,9 @@ void CPDF_DIBSource::LoadJpxBitmap() { format = FXDIB_Rgb; } - m_pCachedBitmap = pdfium::MakeUnique(); + m_pCachedBitmap = pdfium::MakeRetain(); if (!m_pCachedBitmap->Create(width, height, format)) { - m_pCachedBitmap.reset(); + m_pCachedBitmap.Reset(); return; } m_pCachedBitmap->Clear(0xFFFFFFFF); @@ -674,7 +663,7 @@ void CPDF_DIBSource::LoadJpxBitmap() { } if (!pJpxModule->Decode(context->decoder(), m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), output_offsets)) { - m_pCachedBitmap.reset(); + m_pCachedBitmap.Reset(); return; } if (m_pColorSpace && m_pColorSpace->GetFamily() == PDFCS_INDEXED && @@ -692,19 +681,19 @@ void CPDF_DIBSource::LoadJpxBitmap() { m_bpc = 8; } -int CPDF_DIBSource::StratLoadMask() { +int CPDF_DIBSource::StartLoadMask() { m_MatteColor = 0XFFFFFFFF; m_pMaskStream = m_pDict->GetStreamFor("SMask"); if (m_pMaskStream) { CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArrayFor("Matte"); if (pMatte && m_pColorSpace && m_pColorSpace->CountComponents() <= m_nComponents) { - FX_FLOAT R, G, B; - std::vector colors(m_nComponents); - for (uint32_t i = 0; i < m_nComponents; i++) { + float R, G, B; + std::vector colors(m_nComponents); + for (uint32_t i = 0; i < m_nComponents; i++) colors[i] = pMatte->GetFloatAt(i); - } - m_pColorSpace->GetRGB(colors.data(), R, G, B); + + m_pColorSpace->GetRGB(colors.data(), &R, &G, &B); m_MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); } @@ -715,43 +704,39 @@ int CPDF_DIBSource::StratLoadMask() { return m_pMaskStream ? StartLoadMaskDIB() : 1; } -int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_Pause* pPause) { - if (!m_pMask) { +int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_PauseIndicator* pPause) { + if (!m_pMask) return 1; - } + int ret = m_pMask->ContinueLoadDIBSource(pPause); - if (ret == 2) { - return ret; - } - if (m_pColorSpace && m_bStdCS) { + if (ret == 2) + return 2; + + if (m_pColorSpace && m_bStdCS) m_pColorSpace->EnableStdConversion(false); - } + if (!ret) { - delete m_pMask; - m_pMask = nullptr; - return ret; + m_pMask.Reset(); + return 0; } return 1; } -CPDF_DIBSource* CPDF_DIBSource::DetachMask() { - CPDF_DIBSource* pDIBSource = m_pMask; - m_pMask = nullptr; - return pDIBSource; +RetainPtr CPDF_DIBSource::DetachMask() { + return std::move(m_pMask); } int CPDF_DIBSource::StartLoadMaskDIB() { - m_pMask = new CPDF_DIBSource; - int ret = m_pMask->StartLoadDIBSource(m_pDocument, m_pMaskStream, false, - nullptr, nullptr, true); + m_pMask = pdfium::MakeRetain(); + int ret = m_pMask->StartLoadDIBSource(m_pDocument.Get(), m_pMaskStream.Get(), + false, nullptr, nullptr, true); if (ret == 2) { if (m_Status == 0) m_Status = 2; return 2; } if (!ret) { - delete m_pMask; - m_pMask = nullptr; + m_pMask.Reset(); return 1; } return 1; @@ -775,17 +760,17 @@ void CPDF_DIBSource::LoadPalette() { if (m_pColorSpace->CountComponents() > 3) { return; } - FX_FLOAT color_values[3]; + float color_values[3]; color_values[0] = m_pCompData[0].m_DecodeMin; color_values[1] = color_values[2] = color_values[0]; - FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; - m_pColorSpace->GetRGB(color_values, R, G, B); + float R = 0.0f, G = 0.0f, B = 0.0f; + m_pColorSpace->GetRGB(color_values, &R, &G, &B); FX_ARGB argb0 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); color_values[0] += m_pCompData[0].m_DecodeStep; color_values[1] += m_pCompData[0].m_DecodeStep; color_values[2] += m_pCompData[0].m_DecodeStep; - m_pColorSpace->GetRGB(color_values, R, G, B); + m_pColorSpace->GetRGB(color_values, &R, &G, &B); FX_ARGB argb1 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255)); if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) { @@ -798,8 +783,8 @@ void CPDF_DIBSource::LoadPalette() { m_bpc == 8 && m_bDefaultDecode) { } else { int palette_count = 1 << (m_bpc * m_nComponents); - CFX_FixedBufGrow color_values(m_nComponents); - FX_FLOAT* color_value = color_values; + CFX_FixedBufGrow color_values(m_nComponents); + float* color_value = color_values; for (int i = 0; i < palette_count; i++) { int color_data = i; for (uint32_t j = 0; j < m_nComponents; j++) { @@ -808,17 +793,17 @@ void CPDF_DIBSource::LoadPalette() { color_value[j] = m_pCompData[j].m_DecodeMin + m_pCompData[j].m_DecodeStep * encoded_component; } - FX_FLOAT R = 0, G = 0, B = 0; + float R = 0, G = 0, B = 0; if (m_nComponents == 1 && m_Family == PDFCS_ICCBASED && m_pColorSpace->CountComponents() > 1) { int nComponents = m_pColorSpace->CountComponents(); - std::vector temp_buf(nComponents); + std::vector temp_buf(nComponents); for (int k = 0; k < nComponents; k++) { temp_buf[k] = *color_value; } - m_pColorSpace->GetRGB(temp_buf.data(), R, G, B); + m_pColorSpace->GetRGB(temp_buf.data(), &R, &G, &B); } else { - m_pColorSpace->GetRGB(color_value, R, G, B); + m_pColorSpace->GetRGB(color_value, &R, &G, &B); } SetPaletteArgb(i, ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); @@ -831,7 +816,7 @@ void CPDF_DIBSource::ValidateDictParam() { CPDF_Object* pFilter = m_pDict->GetDirectObjectFor("Filter"); if (pFilter) { if (pFilter->IsName()) { - CFX_ByteString filter = pFilter->GetString(); + ByteString filter = pFilter->GetString(); if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") { m_bpc = 1; m_nComponents = 1; @@ -843,7 +828,7 @@ void CPDF_DIBSource::ValidateDictParam() { m_bpc = 8; } } else if (CPDF_Array* pArray = pFilter->AsArray()) { - CFX_ByteString filter = pArray->GetStringAt(pArray->GetCount() - 1); + ByteString filter = pArray->GetStringAt(pArray->GetCount() - 1); if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") { m_bpc = 1; m_nComponents = 1; @@ -861,9 +846,9 @@ void CPDF_DIBSource::ValidateDictParam() { void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, const uint8_t* src_scan) const { - if (m_bpc == 0) { + if (m_bpc == 0) return; - } + unsigned int max_data = (1 << m_bpc) - 1; if (m_bDefaultDecode) { if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) { @@ -872,14 +857,6 @@ void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, const uint8_t* src_pos = src_scan; switch (m_bpc) { - case 16: - for (int col = 0; col < m_Width; col++) { - *dest_scan++ = src_pos[4]; - *dest_scan++ = src_pos[2]; - *dest_scan++ = *src_pos; - src_pos += 6; - } - break; case 8: for (int column = 0; column < m_Width; column++) { *dest_scan++ = src_pos[2]; @@ -888,6 +865,14 @@ void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, src_pos += 3; } break; + case 16: + for (int col = 0; col < m_Width; col++) { + *dest_scan++ = src_pos[4]; + *dest_scan++ = src_pos[2]; + *dest_scan++ = *src_pos; + src_pos += 6; + } + break; default: uint64_t src_bit_pos = 0; size_t dest_byte_pos = 0; @@ -917,9 +902,12 @@ void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, return; } } - CFX_FixedBufGrow color_values1(m_nComponents); - FX_FLOAT* color_values = color_values1; - FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; + + CFX_FixedBufGrow color_values1(m_nComponents); + float* color_values = color_values1; + float R = 0.0f; + float G = 0.0f; + float B = 0.0f; if (m_bpc == 8) { uint64_t src_byte_pos = 0; size_t dest_byte_pos = 0; @@ -930,12 +918,12 @@ void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, m_pCompData[color].m_DecodeStep * data; } if (TransMask()) { - FX_FLOAT k = 1.0f - color_values[3]; + float k = 1.0f - color_values[3]; R = (1.0f - color_values[0]) * k; G = (1.0f - color_values[1]) * k; B = (1.0f - color_values[2]) * k; } else { - m_pColorSpace->GetRGB(color_values, R, G, B); + m_pColorSpace->GetRGB(color_values, &R, &G, &B); } R = ClampValue(R, 1.0f); G = ClampValue(G, 1.0f); @@ -956,12 +944,12 @@ void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, src_bit_pos += m_bpc; } if (TransMask()) { - FX_FLOAT k = 1.0f - color_values[3]; + float k = 1.0f - color_values[3]; R = (1.0f - color_values[0]) * k; G = (1.0f - color_values[1]) * k; B = (1.0f - color_values[2]) * k; } else { - m_pColorSpace->GetRGB(color_values, R, G, B); + m_pColorSpace->GetRGB(color_values, &R, &G, &B); } R = ClampValue(R, 1.0f); G = ClampValue(G, 1.0f); @@ -1001,7 +989,7 @@ const uint8_t* CPDF_DIBSource::GetScanline(int line) const { } if (!pSrcLine) { uint8_t* pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf; - FXSYS_memset(pLineBuf, 0xFF, m_Pitch); + memset(pLineBuf, 0xFF, m_Pitch); return pLineBuf; } if (m_bpc * m_nComponents == 1) { @@ -1032,13 +1020,13 @@ const uint8_t* CPDF_DIBSource::GetScanline(int line) const { } return m_pMaskedLine; } else { - FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value); + memcpy(m_pLineBuf, pSrcLine, src_pitch_value); } return m_pLineBuf; } if (m_bpc * m_nComponents <= 8) { if (m_bpc == 8) { - FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value); + memcpy(m_pLineBuf, pSrcLine, src_pitch_value); } else { uint64_t src_bit_pos = 0; for (int col = 0; col < m_Width; col++) { @@ -1051,29 +1039,29 @@ const uint8_t* CPDF_DIBSource::GetScanline(int line) const { m_pLineBuf[col] = color_index; } } - if (m_bColorKey) { - uint8_t* pDestPixel = m_pMaskedLine; - const uint8_t* pSrcPixel = m_pLineBuf; - for (int col = 0; col < m_Width; col++) { - uint8_t index = *pSrcPixel++; - if (m_pPalette) { - *pDestPixel++ = FXARGB_B(m_pPalette.get()[index]); - *pDestPixel++ = FXARGB_G(m_pPalette.get()[index]); - *pDestPixel++ = FXARGB_R(m_pPalette.get()[index]); - } else { - *pDestPixel++ = index; - *pDestPixel++ = index; - *pDestPixel++ = index; - } - *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || - index > m_pCompData[0].m_ColorKeyMax) - ? 0xFF - : 0; - pDestPixel++; + if (!m_bColorKey) + return m_pLineBuf; + + uint8_t* pDestPixel = m_pMaskedLine; + const uint8_t* pSrcPixel = m_pLineBuf; + for (int col = 0; col < m_Width; col++) { + uint8_t index = *pSrcPixel++; + if (m_pPalette) { + *pDestPixel++ = FXARGB_B(m_pPalette.get()[index]); + *pDestPixel++ = FXARGB_G(m_pPalette.get()[index]); + *pDestPixel++ = FXARGB_R(m_pPalette.get()[index]); + } else { + *pDestPixel++ = index; + *pDestPixel++ = index; + *pDestPixel++ = index; } - return m_pMaskedLine; + *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || + index > m_pCompData[0].m_ColorKeyMax) + ? 0xFF + : 0; + pDestPixel++; } - return m_pLineBuf; + return m_pMaskedLine; } if (m_bColorKey) { if (m_nComponents == 3 && m_bpc == 8) { @@ -1090,28 +1078,29 @@ const uint8_t* CPDF_DIBSource::GetScanline(int line) const { : 0; } } else { - FXSYS_memset(m_pMaskedLine, 0xFF, m_Pitch); + memset(m_pMaskedLine, 0xFF, m_Pitch); } } if (m_pColorSpace) { TranslateScanline24bpp(m_pLineBuf, pSrcLine); pSrcLine = m_pLineBuf; } - if (m_bColorKey) { - const uint8_t* pSrcPixel = pSrcLine; - uint8_t* pDestPixel = m_pMaskedLine; - for (int col = 0; col < m_Width; col++) { - *pDestPixel++ = *pSrcPixel++; - *pDestPixel++ = *pSrcPixel++; - *pDestPixel++ = *pSrcPixel++; - pDestPixel++; - } - return m_pMaskedLine; + if (!m_bColorKey) + return pSrcLine; + + const uint8_t* pSrcPixel = pSrcLine; + uint8_t* pDestPixel = m_pMaskedLine; + for (int col = 0; col < m_Width; col++) { + *pDestPixel++ = *pSrcPixel++; + *pDestPixel++ = *pSrcPixel++; + *pDestPixel++ = *pSrcPixel++; + pDestPixel++; } - return pSrcLine; + return m_pMaskedLine; } -bool CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const { +bool CPDF_DIBSource::SkipToScanline(int line, + IFX_PauseIndicator* pPause) const { return m_pDecoder && m_pDecoder->SkipToScanline(line, pPause); } @@ -1151,7 +1140,7 @@ void CPDF_DIBSource::DownSampleScanline(int line, int orig_Bpp = m_bpc * m_nComponents / 8; int dest_Bpp = dest_bpp / 8; if (!pSrcLine) { - FXSYS_memset(dest_scan, 0xFF, dest_Bpp * clip_width); + memset(dest_scan, 0xFF, dest_Bpp * clip_width); return; } @@ -1183,12 +1172,12 @@ void CPDF_DIBSource::DownSampleScanline1Bit(int orig_Bpp, bool bFlipX, int clip_left, int clip_width) const { - uint32_t set_argb = (uint32_t)-1; + uint32_t set_argb = 0xFFFFFFFF; uint32_t reset_argb = 0; if (m_bImageMask) { if (m_bDefaultDecode) { set_argb = 0; - reset_argb = (uint32_t)-1; + reset_argb = 0xFFFFFFFF; } } else if (m_bColorKey) { reset_argb = m_pPalette ? m_pPalette.get()[0] : 0xFF000000; @@ -1332,7 +1321,7 @@ void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp, // in [0, src_width). Set the initial value to be an invalid src_x value. uint32_t last_src_x = src_width; FX_ARGB last_argb = FXARGB_MAKE(0xFF, 0xFF, 0xFF, 0xFF); - FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1); + float unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1); for (int i = 0; i < clip_width; i++) { int dest_x = clip_left + i; uint32_t src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) * @@ -1344,7 +1333,7 @@ void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp, if (src_x == last_src_x) { argb = last_argb; } else { - CFX_FixedBufGrow extracted_components(m_nComponents); + CFX_FixedBufGrow extracted_components(m_nComponents); const uint8_t* pSrcPixel = nullptr; if (m_bpc % 8 != 0) { // No need to check for 32-bit overflow, as |src_x| is bounded by @@ -1371,24 +1360,20 @@ void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp, if (m_pColorSpace) { uint8_t color[4]; const bool bTransMask = TransMask(); - if (m_bDefaultDecode) { - m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0, - bTransMask); - } else { + if (!m_bDefaultDecode) { for (uint32_t j = 0; j < m_nComponents; ++j) { - FX_FLOAT component_value = - static_cast(extracted_components[j]); + float component_value = static_cast(pSrcPixel[j]); int color_value = static_cast( (m_pCompData[j].m_DecodeMin + m_pCompData[j].m_DecodeStep * component_value) * 255.0f + 0.5f); - extracted_components[j] = - color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value); + extracted_components[j] = pdfium::clamp(color_value, 0, 255); } - m_pColorSpace->TranslateImageLine(color, extracted_components, 1, 0, - 0, bTransMask); } + const uint8_t* pSrc = + m_bDefaultDecode ? pSrcPixel : extracted_components; + m_pColorSpace->TranslateImageLine(color, pSrc, 1, 0, 0, bTransMask); argb = FXARGB_MAKE(0xFF, color[2], color[1], color[0]); } else { argb = FXARGB_MAKE(0xFF, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]); diff --git a/core/fpdfapi/render/cpdf_dibsource.h b/core/fpdfapi/render/cpdf_dibsource.h index d5820d8bae7fb273f8f7eb0a6b3495979a34fec2..d3f65156c34003116c2a949843199c556a6c754b 100644 --- a/core/fpdfapi/render/cpdf_dibsource.h +++ b/core/fpdfapi/render/cpdf_dibsource.h @@ -18,8 +18,10 @@ #include "core/fpdfapi/render/cpdf_imageloader.h" #include "core/fpdfapi/render/cpdf_rendercontext.h" #include "core/fpdfapi/render/cpdf_renderoptions.h" -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_renderdevice.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/dib/cfx_dibsource.h" class CCodec_Jbig2Context; class CCodec_ScanlineDecoder; @@ -29,8 +31,8 @@ class CPDF_Document; class CPDF_Stream; typedef struct { - FX_FLOAT m_DecodeMin; - FX_FLOAT m_DecodeStep; + float m_DecodeMin; + float m_DecodeStep; int m_ColorKeyMin; int m_ColorKeyMax; } DIB_COMP_DATA; @@ -39,13 +41,15 @@ typedef struct { class CPDF_DIBSource : public CFX_DIBSource { public: - CPDF_DIBSource(); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + ~CPDF_DIBSource() override; bool Load(CPDF_Document* pDoc, const CPDF_Stream* pStream); // CFX_DIBSource - bool SkipToScanline(int line, IFX_Pause* pPause) const override; + bool SkipToScanline(int line, IFX_PauseIndicator* pPause) const override; uint8_t* GetBuffer() const override; const uint8_t* GetScanline(int line) const override; void DownSampleScanline(int line, @@ -56,6 +60,7 @@ class CPDF_DIBSource : public CFX_DIBSource { int clip_left, int clip_width) const override; + const CPDF_ColorSpace* GetColorSpace() const { return m_pColorSpace; } uint32_t GetMatteColor() const { return m_MatteColor; } int StartLoadDIBSource(CPDF_Document* pDoc, @@ -66,20 +71,25 @@ class CPDF_DIBSource : public CFX_DIBSource { bool bStdCS = false, uint32_t GroupFamily = 0, bool bLoadMask = false); - int ContinueLoadDIBSource(IFX_Pause* pPause); - int StratLoadMask(); + int ContinueLoadDIBSource(IFX_PauseIndicator* pPause); + int StartLoadMask(); int StartLoadMaskDIB(); - int ContinueLoadMaskDIB(IFX_Pause* pPause); - int ContinueToLoadMask(); - CPDF_DIBSource* DetachMask(); + int ContinueLoadMaskDIB(IFX_PauseIndicator* pPause); + bool ContinueToLoadMask(); + RetainPtr DetachMask(); private: + CPDF_DIBSource(); + bool LoadColorInfo(const CPDF_Dictionary* pFormResources, const CPDF_Dictionary* pPageResources); - DIB_COMP_DATA* GetDecodeAndMaskArray(bool& bDefaultDecode, bool& bColorKey); + DIB_COMP_DATA* GetDecodeAndMaskArray(bool* bDefaultDecode, bool* bColorKey); void LoadJpxBitmap(); void LoadPalette(); int CreateDecoder(); + bool CreateDCTDecoder(const uint8_t* src_data, + uint32_t src_size, + const CPDF_Dictionary* pParams); void TranslateScanline24bpp(uint8_t* dest_scan, const uint8_t* src_scan) const; void ValidateDictParam(); @@ -112,10 +122,10 @@ class CPDF_DIBSource : public CFX_DIBSource { int clip_width) const; bool TransMask() const; - CPDF_Document* m_pDocument; - const CPDF_Stream* m_pStream; - std::unique_ptr m_pStreamAcc; - const CPDF_Dictionary* m_pDict; + UnownedPtr m_pDocument; + UnownedPtr m_pStream; + UnownedPtr m_pDict; + RetainPtr m_pStreamAcc; CPDF_ColorSpace* m_pColorSpace; uint32_t m_Family; uint32_t m_bpc; @@ -133,12 +143,12 @@ class CPDF_DIBSource : public CFX_DIBSource { DIB_COMP_DATA* m_pCompData; uint8_t* m_pLineBuf; uint8_t* m_pMaskedLine; - std::unique_ptr m_pCachedBitmap; + RetainPtr m_pCachedBitmap; + RetainPtr m_pMask; + RetainPtr m_pGlobalStream; std::unique_ptr m_pDecoder; - CPDF_DIBSource* m_pMask; - std::unique_ptr m_pGlobalStream; std::unique_ptr m_pJbig2Context; - CPDF_Stream* m_pMaskStream; + UnownedPtr m_pMaskStream; int m_Status; }; diff --git a/core/fpdfapi/render/cpdf_dibtransferfunc.cpp b/core/fpdfapi/render/cpdf_dibtransferfunc.cpp index 41575fc8c21d4701319b19d2be806af36346805a..3b0e8b25a9fd37ec34f416af8c40c7055270e21b 100644 --- a/core/fpdfapi/render/cpdf_dibtransferfunc.cpp +++ b/core/fpdfapi/render/cpdf_dibtransferfunc.cpp @@ -12,10 +12,11 @@ #include "core/fpdfapi/render/cpdf_transferfunc.h" CPDF_DIBTransferFunc::CPDF_DIBTransferFunc( - const CPDF_TransferFunc* pTransferFunc) { - m_RampR = pTransferFunc->m_Samples; - m_RampG = &pTransferFunc->m_Samples[256]; - m_RampB = &pTransferFunc->m_Samples[512]; + const RetainPtr& pTransferFunc) + : m_pTransferFunc(pTransferFunc) { + m_RampR = pTransferFunc->GetSamples(); + m_RampG = &pTransferFunc->GetSamples()[256]; + m_RampB = &pTransferFunc->GetSamples()[512]; } CPDF_DIBTransferFunc::~CPDF_DIBTransferFunc() {} @@ -24,7 +25,7 @@ FXDIB_Format CPDF_DIBTransferFunc::GetDestFormat() { if (m_pSrc->IsAlphaMask()) return FXDIB_8bppMask; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb32; #else return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb; @@ -58,7 +59,7 @@ void CPDF_DIBTransferFunc::TranslateScanline( (*dest_buf)[index++] = g0; (*dest_buf)[index++] = r0; } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ index++; #endif } @@ -92,7 +93,7 @@ void CPDF_DIBTransferFunc::TranslateScanline( (*dest_buf)[index++] = m_RampR[src_byte]; } src_buf++; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ index++; #endif } @@ -110,7 +111,7 @@ void CPDF_DIBTransferFunc::TranslateScanline( (*dest_buf)[index++] = m_RampB[*(src_buf++)]; (*dest_buf)[index++] = m_RampG[*(src_buf++)]; (*dest_buf)[index++] = m_RampR[*(src_buf++)]; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ index++; #endif } @@ -126,7 +127,7 @@ void CPDF_DIBTransferFunc::TranslateScanline( (*dest_buf)[index++] = m_RampR[*(src_buf++)]; if (!bSkip) { (*dest_buf)[index++] = *src_buf; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ } else { index++; #endif @@ -154,7 +155,7 @@ void CPDF_DIBTransferFunc::TranslateDownSamples(uint8_t* dest_buf, *dest_buf++ = m_RampR[*(src_buf++)]; } } else { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ if (!m_pSrc->HasAlpha()) { for (int i = 0; i < pixels; i++) { *dest_buf++ = m_RampB[*(src_buf++)]; @@ -171,7 +172,7 @@ void CPDF_DIBTransferFunc::TranslateDownSamples(uint8_t* dest_buf, *dest_buf++ = m_RampR[*(src_buf++)]; *dest_buf++ = *(src_buf++); } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ } #endif } diff --git a/core/fpdfapi/render/cpdf_dibtransferfunc.h b/core/fpdfapi/render/cpdf_dibtransferfunc.h index d290c00d8adbc4907e96394f6e6dd9a098caf1ba..34f5bb1abe567ab6cc8b63e843ebd19e2aea43e9 100644 --- a/core/fpdfapi/render/cpdf_dibtransferfunc.h +++ b/core/fpdfapi/render/cpdf_dibtransferfunc.h @@ -9,13 +9,17 @@ #include +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/dib/cfx_filtereddib.h" #include "core/fxge/fx_dib.h" class CPDF_TransferFunc; class CPDF_DIBTransferFunc : public CFX_FilteredDIB { public: - explicit CPDF_DIBTransferFunc(const CPDF_TransferFunc* pTransferFunc); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + ~CPDF_DIBTransferFunc() override; // CFX_FilteredDIB @@ -29,6 +33,10 @@ class CPDF_DIBTransferFunc : public CFX_FilteredDIB { int Bpp) const override; private: + explicit CPDF_DIBTransferFunc( + const RetainPtr& pTransferFunc); + + RetainPtr m_pTransferFunc; const uint8_t* m_RampR; const uint8_t* m_RampG; const uint8_t* m_RampB; diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp index 0e6f2d07e5a0f11b33c4ae4afe8673032d6577c9..6480688f2116d93dd7e501d845afe0b45aab7fb1 100644 --- a/core/fpdfapi/render/cpdf_docrenderdata.cpp +++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp @@ -9,7 +9,7 @@ #include #include "core/fpdfapi/font/cpdf_type3font.h" -#include "core/fpdfapi/page/pageint.h" +#include "core/fpdfapi/page/cpdf_function.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/render/cpdf_dibsource.h" @@ -32,59 +32,43 @@ CPDF_DocRenderData::~CPDF_DocRenderData() { void CPDF_DocRenderData::Clear(bool bRelease) { for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) { auto curr_it = it++; - CPDF_CountedObject* cache = curr_it->second; - if (bRelease || cache->use_count() < 2) { - delete cache->get(); - delete cache; + if (bRelease || curr_it->second->HasOneRef()) { m_Type3FaceMap.erase(curr_it); } } for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) { auto curr_it = it++; - CPDF_CountedObject* value = curr_it->second; - if (bRelease || value->use_count() < 2) { - delete value->get(); - delete value; + if (bRelease || curr_it->second->HasOneRef()) m_TransferFuncMap.erase(curr_it); - } } } -CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) { - CPDF_CountedObject* pCache; +RetainPtr CPDF_DocRenderData::GetCachedType3( + CPDF_Type3Font* pFont) { auto it = m_Type3FaceMap.find(pFont); - if (it == m_Type3FaceMap.end()) { - pCache = new CPDF_CountedObject( - pdfium::MakeUnique(pFont)); - m_Type3FaceMap[pFont] = pCache; - } else { - pCache = it->second; - } - return pCache->AddRef(); + if (it != m_Type3FaceMap.end()) + return it->second; + + auto pCache = pdfium::MakeRetain(pFont); + m_Type3FaceMap[pFont] = pCache; + return pCache; } -void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) { +void CPDF_DocRenderData::MaybePurgeCachedType3(CPDF_Type3Font* pFont) { auto it = m_Type3FaceMap.find(pFont); - if (it != m_Type3FaceMap.end()) { - it->second->RemoveRef(); - if (it->second->use_count() < 2) { - delete it->second->get(); - delete it->second; - m_Type3FaceMap.erase(it); - } - } + if (it != m_Type3FaceMap.end() && it->second->HasOneRef()) + m_Type3FaceMap.erase(it); } -CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) { +RetainPtr CPDF_DocRenderData::GetTransferFunc( + CPDF_Object* pObj) { if (!pObj) return nullptr; auto it = m_TransferFuncMap.find(pObj); - if (it != m_TransferFuncMap.end()) { - CPDF_CountedObject* pTransferCounter = it->second; - return pTransferCounter->AddRef(); - } + if (it != m_TransferFuncMap.end()) + return it->second; std::unique_ptr pFuncs[3]; bool bUniTransfer = true; @@ -104,52 +88,44 @@ CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) { if (!pFuncs[0]) return nullptr; } - CPDF_CountedObject* pTransferCounter = - new CPDF_CountedObject( - pdfium::MakeUnique(m_pPDFDoc)); - CPDF_TransferFunc* pTransfer = pTransferCounter->get(); - m_TransferFuncMap[pObj] = pTransferCounter; - FX_FLOAT output[kMaxOutputs]; - FXSYS_memset(output, 0, sizeof(output)); - FX_FLOAT input; + auto pTransfer = pdfium::MakeRetain(m_pPDFDoc.Get()); + m_TransferFuncMap[pObj] = pTransfer; + + float input; int noutput; + float output[kMaxOutputs]; + memset(output, 0, sizeof(output)); for (int v = 0; v < 256; ++v) { - input = (FX_FLOAT)v / 255.0f; + input = (float)v / 255.0f; if (bUniTransfer) { if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs) - pFuncs[0]->Call(&input, 1, output, noutput); + pFuncs[0]->Call(&input, 1, output, &noutput); int o = FXSYS_round(output[0] * 255); if (o != v) bIdentity = false; for (int i = 0; i < 3; ++i) - pTransfer->m_Samples[i * 256 + v] = o; + pTransfer->GetSamples()[i * 256 + v] = o; continue; } for (int i = 0; i < 3; ++i) { if (!pFuncs[i] || pFuncs[i]->CountOutputs() > kMaxOutputs) { - pTransfer->m_Samples[i * 256 + v] = v; + pTransfer->GetSamples()[i * 256 + v] = v; continue; } - pFuncs[i]->Call(&input, 1, output, noutput); + pFuncs[i]->Call(&input, 1, output, &noutput); int o = FXSYS_round(output[0] * 255); if (o != v) bIdentity = false; - pTransfer->m_Samples[i * 256 + v] = o; + pTransfer->GetSamples()[i * 256 + v] = o; } } - pTransfer->m_bIdentity = bIdentity; - return pTransferCounter->AddRef(); + pTransfer->SetIdentity(bIdentity); + return pTransfer; } -void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) { +void CPDF_DocRenderData::MaybePurgeTransferFunc(CPDF_Object* pObj) { auto it = m_TransferFuncMap.find(pObj); - if (it != m_TransferFuncMap.end()) { - it->second->RemoveRef(); - if (it->second->use_count() < 2) { - delete it->second->get(); - delete it->second; - m_TransferFuncMap.erase(it); - } - } + if (it != m_TransferFuncMap.end() && it->second->HasOneRef()) + m_TransferFuncMap.erase(it); } diff --git a/core/fpdfapi/render/cpdf_docrenderdata.h b/core/fpdfapi/render/cpdf_docrenderdata.h index a8f4167a8d97064aa79ceab4257065f18fc4489f..7b3e0ed398f3519b27152232ad2d2d445f48ed66 100644 --- a/core/fpdfapi/render/cpdf_docrenderdata.h +++ b/core/fpdfapi/render/cpdf_docrenderdata.h @@ -10,11 +10,13 @@ #include #include "core/fpdfapi/page/cpdf_countedobject.h" +#include "core/fpdfapi/render/cpdf_transferfunc.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_Font; class CPDF_Object; -class CPDF_TransferFunc; class CPDF_Type3Cache; class CPDF_Type3Font; @@ -23,21 +25,18 @@ class CPDF_DocRenderData { explicit CPDF_DocRenderData(CPDF_Document* pPDFDoc); ~CPDF_DocRenderData(); - CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont); - void ReleaseCachedType3(CPDF_Type3Font* pFont); - CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObj); - void ReleaseTransferFunc(CPDF_Object* pObj); + RetainPtr GetCachedType3(CPDF_Type3Font* pFont); + void MaybePurgeCachedType3(CPDF_Type3Font* pFont); + + RetainPtr GetTransferFunc(CPDF_Object* pObj); + void MaybePurgeTransferFunc(CPDF_Object* pOb); + void Clear(bool bRelease); private: - using CPDF_Type3CacheMap = - std::map*>; - using CPDF_TransferFuncMap = - std::map*>; - - CPDF_Document* m_pPDFDoc; // Not Owned - CPDF_Type3CacheMap m_Type3FaceMap; - CPDF_TransferFuncMap m_TransferFuncMap; + UnownedPtr m_pPDFDoc; + std::map> m_Type3FaceMap; + std::map> m_TransferFuncMap; }; #endif // CORE_FPDFAPI_RENDER_CPDF_DOCRENDERDATA_H_ diff --git a/core/fpdfapi/render/cpdf_imagecacheentry.cpp b/core/fpdfapi/render/cpdf_imagecacheentry.cpp index f11cae888d9a3df5a8363fd633bbe4a4b9843431..f69bfdae687aa0cea9fe0e641e060cede7f0712e 100644 --- a/core/fpdfapi/render/cpdf_imagecacheentry.cpp +++ b/core/fpdfapi/render/cpdf_imagecacheentry.cpp @@ -17,109 +17,109 @@ #include "core/fpdfapi/render/cpdf_pagerendercache.h" #include "core/fpdfapi/render/cpdf_rendercontext.h" #include "core/fpdfapi/render/cpdf_renderstatus.h" +#include "core/fxge/dib/cfx_dibitmap.h" CPDF_ImageCacheEntry::CPDF_ImageCacheEntry(CPDF_Document* pDoc, - CPDF_Stream* pStream) + const RetainPtr& pImage) : m_dwTimeCount(0), m_MatteColor(0), - m_pRenderStatus(nullptr), m_pDocument(pDoc), - m_pStream(pStream), - m_pCurBitmap(nullptr), - m_pCurMask(nullptr), + m_pImage(pImage), m_dwCacheSize(0) {} CPDF_ImageCacheEntry::~CPDF_ImageCacheEntry() {} -void CPDF_ImageCacheEntry::Reset(const CFX_DIBitmap* pBitmap) { - m_pCachedBitmap.reset(); +void CPDF_ImageCacheEntry::Reset(const RetainPtr& pBitmap) { + m_pCachedBitmap.Reset(); if (pBitmap) - m_pCachedBitmap = pBitmap->Clone(); + m_pCachedBitmap = pBitmap->Clone(nullptr); CalcSize(); } -static uint32_t FPDF_ImageCache_EstimateImageSize(const CFX_DIBSource* pDIB) { +static uint32_t FPDF_ImageCache_EstimateImageSize( + const RetainPtr& pDIB) { return pDIB && pDIB->GetBuffer() ? (uint32_t)pDIB->GetHeight() * pDIB->GetPitch() + (uint32_t)pDIB->GetPaletteSize() * 4 : 0; } -CFX_DIBSource* CPDF_ImageCacheEntry::DetachBitmap() { - CFX_DIBSource* pDIBSource = m_pCurBitmap; - m_pCurBitmap = nullptr; - return pDIBSource; +RetainPtr CPDF_ImageCacheEntry::DetachBitmap() { + return std::move(m_pCurBitmap); } -CFX_DIBSource* CPDF_ImageCacheEntry::DetachMask() { - CFX_DIBSource* pDIBSource = m_pCurMask; - m_pCurMask = nullptr; - return pDIBSource; +RetainPtr CPDF_ImageCacheEntry::DetachMask() { + return std::move(m_pCurMask); } -int CPDF_ImageCacheEntry::StartGetCachedBitmap(CPDF_Dictionary* pFormResources, - CPDF_Dictionary* pPageResources, - bool bStdCS, - uint32_t GroupFamily, - bool bLoadMask, - CPDF_RenderStatus* pRenderStatus, - int32_t downsampleWidth, - int32_t downsampleHeight) { +int CPDF_ImageCacheEntry::StartGetCachedBitmap( + CPDF_Dictionary* pFormResources, + CPDF_Dictionary* pPageResources, + bool bStdCS, + uint32_t GroupFamily, + bool bLoadMask, + CPDF_RenderStatus* pRenderStatus) { + ASSERT(pRenderStatus); + if (m_pCachedBitmap) { - m_pCurBitmap = m_pCachedBitmap.get(); - m_pCurMask = m_pCachedMask.get(); + m_pCurBitmap = m_pCachedBitmap; + m_pCurMask = m_pCachedMask; return 1; } - if (!pRenderStatus) - return 0; - m_pRenderStatus = pRenderStatus; - m_pCurBitmap = new CPDF_DIBSource; - int ret = - ((CPDF_DIBSource*)m_pCurBitmap) - ->StartLoadDIBSource(m_pDocument, m_pStream, true, pFormResources, - pPageResources, bStdCS, GroupFamily, bLoadMask); + m_pCurBitmap = pdfium::MakeRetain(); + int ret = m_pCurBitmap.As()->StartLoadDIBSource( + m_pDocument.Get(), m_pImage->GetStream(), true, pFormResources, + pPageResources, bStdCS, GroupFamily, bLoadMask); if (ret == 2) return ret; if (!ret) { - delete m_pCurBitmap; - m_pCurBitmap = nullptr; + m_pCurBitmap.Reset(); return 0; } - ContinueGetCachedBitmap(); + ContinueGetCachedBitmap(pRenderStatus); return 0; } -void CPDF_ImageCacheEntry::ContinueGetCachedBitmap() { - m_MatteColor = ((CPDF_DIBSource*)m_pCurBitmap)->GetMatteColor(); - m_pCurMask = ((CPDF_DIBSource*)m_pCurBitmap)->DetachMask(); - CPDF_RenderContext* pContext = m_pRenderStatus->GetContext(); +void CPDF_ImageCacheEntry::ContinueGetCachedBitmap( + CPDF_RenderStatus* pRenderStatus) { + m_MatteColor = m_pCurBitmap.As()->GetMatteColor(); + m_pCurMask = m_pCurBitmap.As()->DetachMask(); + CPDF_RenderContext* pContext = pRenderStatus->GetContext(); CPDF_PageRenderCache* pPageRenderCache = pContext->GetPageCache(); m_dwTimeCount = pPageRenderCache->GetTimeCount(); - m_pCachedBitmap = pdfium::WrapUnique(m_pCurBitmap); - if (m_pCurMask) - m_pCachedMask = pdfium::WrapUnique(m_pCurMask); - else - m_pCurMask = m_pCachedMask.get(); + if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < + FPDF_HUGE_IMAGE_SIZE) { + m_pCachedBitmap = m_pCurBitmap->Clone(nullptr); + m_pCurBitmap.Reset(); + } else { + m_pCachedBitmap = m_pCurBitmap; + } + if (m_pCurMask) { + m_pCachedMask = m_pCurMask->Clone(nullptr); + m_pCurMask.Reset(); + } + m_pCurBitmap = m_pCachedBitmap; + m_pCurMask = m_pCachedMask; CalcSize(); } -int CPDF_ImageCacheEntry::Continue(IFX_Pause* pPause) { - int ret = ((CPDF_DIBSource*)m_pCurBitmap)->ContinueLoadDIBSource(pPause); - if (ret == 2) - return ret; - +int CPDF_ImageCacheEntry::Continue(IFX_PauseIndicator* pPause, + CPDF_RenderStatus* pRenderStatus) { + int ret = m_pCurBitmap.As()->ContinueLoadDIBSource(pPause); if (!ret) { - delete m_pCurBitmap; - m_pCurBitmap = nullptr; + m_pCurBitmap.Reset(); return 0; } - ContinueGetCachedBitmap(); + if (ret == 2) + return ret; + + ContinueGetCachedBitmap(pRenderStatus); return 0; } void CPDF_ImageCacheEntry::CalcSize() { - m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap.get()) + - FPDF_ImageCache_EstimateImageSize(m_pCachedMask.get()); + m_dwCacheSize = FPDF_ImageCache_EstimateImageSize(m_pCachedBitmap) + + FPDF_ImageCache_EstimateImageSize(m_pCachedMask); } diff --git a/core/fpdfapi/render/cpdf_imagecacheentry.h b/core/fpdfapi/render/cpdf_imagecacheentry.h index d11fe94c296bee19fc95ba223e951d40ed30e37c..2bede23e628d28b72affbe8c617dbaaf2c083a51 100644 --- a/core/fpdfapi/render/cpdf_imagecacheentry.h +++ b/core/fpdfapi/render/cpdf_imagecacheentry.h @@ -10,51 +10,50 @@ #include #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" -class CFX_DIBitmap; class CFX_DIBSource; +class CFX_DIBitmap; class CPDF_Dictionary; class CPDF_Document; +class CPDF_Image; class CPDF_RenderStatus; -class CPDF_Stream; -class IFX_Pause; +class IFX_PauseIndicator; class CPDF_ImageCacheEntry { public: - CPDF_ImageCacheEntry(CPDF_Document* pDoc, CPDF_Stream* pStream); + CPDF_ImageCacheEntry(CPDF_Document* pDoc, + const RetainPtr& pImage); ~CPDF_ImageCacheEntry(); - void Reset(const CFX_DIBitmap* pBitmap); + void Reset(const RetainPtr& pBitmap); uint32_t EstimateSize() const { return m_dwCacheSize; } uint32_t GetTimeCount() const { return m_dwTimeCount; } - CPDF_Stream* GetStream() const { return m_pStream; } - + CPDF_Image* GetImage() const { return m_pImage.Get(); } int StartGetCachedBitmap(CPDF_Dictionary* pFormResources, CPDF_Dictionary* pPageResources, bool bStdCS, uint32_t GroupFamily, bool bLoadMask, - CPDF_RenderStatus* pRenderStatus, - int32_t downsampleWidth, - int32_t downsampleHeight); - int Continue(IFX_Pause* pPause); - CFX_DIBSource* DetachBitmap(); - CFX_DIBSource* DetachMask(); + CPDF_RenderStatus* pRenderStatus); + int Continue(IFX_PauseIndicator* pPause, CPDF_RenderStatus* pRenderStatus); + RetainPtr DetachBitmap(); + RetainPtr DetachMask(); int m_dwTimeCount; uint32_t m_MatteColor; private: - void ContinueGetCachedBitmap(); + void ContinueGetCachedBitmap(CPDF_RenderStatus* pRenderStatus); void CalcSize(); - CPDF_RenderStatus* m_pRenderStatus; - CPDF_Document* m_pDocument; - CPDF_Stream* m_pStream; - CFX_DIBSource* m_pCurBitmap; - CFX_DIBSource* m_pCurMask; - std::unique_ptr m_pCachedBitmap; - std::unique_ptr m_pCachedMask; + UnownedPtr const m_pDocument; + RetainPtr const m_pImage; + RetainPtr m_pCurBitmap; + RetainPtr m_pCurMask; + RetainPtr m_pCachedBitmap; + RetainPtr m_pCachedMask; uint32_t m_dwCacheSize; }; diff --git a/core/fpdfapi/render/cpdf_imageloader.cpp b/core/fpdfapi/render/cpdf_imageloader.cpp index 18213ea6954910f109764998fc90bbd1e3b4d685..08aa5f1784127028665f2351f5841a1848df85cd 100644 --- a/core/fpdfapi/render/cpdf_imageloader.cpp +++ b/core/fpdfapi/render/cpdf_imageloader.cpp @@ -12,55 +12,41 @@ #include "core/fpdfapi/render/cpdf_imagecacheentry.h" #include "core/fpdfapi/render/cpdf_pagerendercache.h" #include "core/fpdfapi/render/cpdf_renderstatus.h" -#include "core/fxcrt/fx_basic.h" CPDF_ImageLoader::CPDF_ImageLoader() - : m_pBitmap(nullptr), - m_pMask(nullptr), - m_MatteColor(0), + : m_MatteColor(0), m_bCached(false), - m_nDownsampleWidth(0), - m_nDownsampleHeight(0), m_pCache(nullptr), - m_pImage(nullptr) {} + m_pImageObject(nullptr) {} -CPDF_ImageLoader::~CPDF_ImageLoader() { - if (!m_bCached) { - delete m_pBitmap; - delete m_pMask; - } -} +CPDF_ImageLoader::~CPDF_ImageLoader() {} bool CPDF_ImageLoader::Start(const CPDF_ImageObject* pImage, CPDF_PageRenderCache* pCache, bool bStdCS, uint32_t GroupFamily, bool bLoadMask, - CPDF_RenderStatus* pRenderStatus, - int32_t nDownsampleWidth, - int32_t nDownsampleHeight) { - m_nDownsampleWidth = nDownsampleWidth; - m_nDownsampleHeight = nDownsampleHeight; + CPDF_RenderStatus* pRenderStatus) { m_pCache = pCache; - m_pImage = const_cast(pImage); + m_pImageObject = const_cast(pImage); bool ret; if (pCache) { - ret = pCache->StartGetCachedBitmap( - m_pImage->GetImage()->GetStream(), bStdCS, GroupFamily, bLoadMask, - pRenderStatus, m_nDownsampleWidth, m_nDownsampleHeight); + ret = pCache->StartGetCachedBitmap(m_pImageObject->GetImage(), bStdCS, + GroupFamily, bLoadMask, pRenderStatus); } else { - ret = m_pImage->GetImage()->StartLoadDIBSource( - pRenderStatus->m_pFormResource, pRenderStatus->m_pPageResource, bStdCS, - GroupFamily, bLoadMask); + ret = m_pImageObject->GetImage()->StartLoadDIBSource( + pRenderStatus->GetFormResource(), pRenderStatus->GetPageResource(), + bStdCS, GroupFamily, bLoadMask); } if (!ret) HandleFailure(); return ret; } -bool CPDF_ImageLoader::Continue(IFX_Pause* pPause) { - bool ret = m_pCache ? m_pCache->Continue(pPause) - : m_pImage->GetImage()->Continue(pPause); +bool CPDF_ImageLoader::Continue(IFX_PauseIndicator* pPause, + CPDF_RenderStatus* pRenderStatus) { + bool ret = m_pCache ? m_pCache->Continue(pPause, pRenderStatus) + : m_pImageObject->GetImage()->Continue(pPause); if (!ret) HandleFailure(); return ret; @@ -75,7 +61,7 @@ void CPDF_ImageLoader::HandleFailure() { m_MatteColor = entry->m_MatteColor; return; } - CPDF_Image* pImage = m_pImage->GetImage(); + RetainPtr pImage = m_pImageObject->GetImage(); m_bCached = false; m_pBitmap = pImage->DetachBitmap(); m_pMask = pImage->DetachMask(); diff --git a/core/fpdfapi/render/cpdf_imageloader.h b/core/fpdfapi/render/cpdf_imageloader.h index a270c45bbfbd891e8e5b1f0fe39df47f269a3e78..497ef156daa750c9150837f94805919e2d1e5db4 100644 --- a/core/fpdfapi/render/cpdf_imageloader.h +++ b/core/fpdfapi/render/cpdf_imageloader.h @@ -9,12 +9,14 @@ #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" class CPDF_ImageObject; class CPDF_PageRenderCache; class CPDF_RenderStatus; +class IFX_PauseIndicator; class CPDF_ImageLoader { public: @@ -26,23 +28,19 @@ class CPDF_ImageLoader { bool bStdCS, uint32_t GroupFamily, bool bLoadMask, - CPDF_RenderStatus* pRenderStatus, - int32_t nDownsampleWidth, - int32_t nDownsampleHeight); - bool Continue(IFX_Pause* pPause); + CPDF_RenderStatus* pRenderStatus); + bool Continue(IFX_PauseIndicator* pPause, CPDF_RenderStatus* pRenderStatus); - CFX_DIBSource* m_pBitmap; - CFX_DIBSource* m_pMask; + RetainPtr m_pBitmap; + RetainPtr m_pMask; uint32_t m_MatteColor; bool m_bCached; private: void HandleFailure(); - int32_t m_nDownsampleWidth; - int32_t m_nDownsampleHeight; - CPDF_PageRenderCache* m_pCache; - CPDF_ImageObject* m_pImage; + UnownedPtr m_pCache; + UnownedPtr m_pImageObject; }; #endif // CORE_FPDFAPI_RENDER_CPDF_IMAGELOADER_H_ diff --git a/core/fpdfapi/render/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp index 358d13edd0c5a97838434317a851398db5810c14..135159727927226ce1455341ede35c2d183c632c 100644 --- a/core/fpdfapi/render/cpdf_imagerenderer.cpp +++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp @@ -25,33 +25,33 @@ #include "core/fpdfapi/render/cpdf_renderstatus.h" #include "core/fpdfapi/render/cpdf_transferfunc.h" #include "core/fpdfdoc/cpdf_occontext.h" -#include "core/fxcrt/cfx_maybe_owned.h" #include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_pathdata.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/cfx_dibsource.h" +#include "core/fxge/dib/cfx_imagestretcher.h" +#include "core/fxge/dib/cfx_imagetransformer.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" #ifdef _SKIA_SUPPORT_ #include "core/fxge/skia/fx_skia_device.h" #endif -CPDF_ImageRenderer::CPDF_ImageRenderer() { - m_pRenderStatus = nullptr; - m_pImageObject = nullptr; - m_Result = true; - m_Status = 0; - m_DeviceHandle = nullptr; - m_bStdCS = false; - m_bPatternColor = false; - m_BlendType = FXDIB_BLEND_NORMAL; - m_pPattern = nullptr; - m_pObj2Device = nullptr; -} +CPDF_ImageRenderer::CPDF_ImageRenderer() + : m_pRenderStatus(nullptr), + m_pImageObject(nullptr), + m_Status(0), + m_pObj2Device(nullptr), + m_bPatternColor(false), + m_pPattern(nullptr), + m_bStdCS(false), + m_BlendType(FXDIB_BLEND_NORMAL), + m_Result(true) {} -CPDF_ImageRenderer::~CPDF_ImageRenderer() { - if (m_DeviceHandle) - m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle); -} +CPDF_ImageRenderer::~CPDF_ImageRenderer() {} bool CPDF_ImageRenderer::StartLoadDIBSource() { CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); @@ -59,14 +59,10 @@ bool CPDF_ImageRenderer::StartLoadDIBSource() { if (!image_rect.Valid()) return false; - int dest_width = - m_ImageMatrix.a >= 0 ? image_rect.Width() : -image_rect.Width(); - int dest_height = - m_ImageMatrix.d <= 0 ? image_rect.Height() : -image_rect.Height(); - if (m_Loader.Start( - m_pImageObject, m_pRenderStatus->m_pContext->GetPageCache(), m_bStdCS, - m_pRenderStatus->m_GroupFamily, m_pRenderStatus->m_bLoadMask, - m_pRenderStatus, dest_width, dest_height)) { + if (m_Loader.Start(m_pImageObject.Get(), + m_pRenderStatus->GetContext()->GetPageCache(), m_bStdCS, + m_pRenderStatus->GetGroupFamily(), + m_pRenderStatus->GetLoadMask(), m_pRenderStatus.Get())) { m_Status = 4; return true; } @@ -77,26 +73,23 @@ bool CPDF_ImageRenderer::StartRenderDIBSource() { if (!m_Loader.m_pBitmap) return false; - m_BitmapAlpha = - FXSYS_round(255 * m_pImageObject->m_GeneralState.GetFillAlpha()); + CPDF_GeneralState& state = m_pImageObject->m_GeneralState; + m_BitmapAlpha = FXSYS_round(255 * state.GetFillAlpha()); m_pDIBSource = m_Loader.m_pBitmap; - if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA && + if (m_pRenderStatus->GetRenderOptions()->ColorModeIs( + CPDF_RenderOptions::kAlpha) && !m_Loader.m_pMask) { return StartBitmapAlpha(); } - if (m_pImageObject->m_GeneralState.GetTR()) { - if (!m_pImageObject->m_GeneralState.GetTransferFunc()) { - m_pImageObject->m_GeneralState.SetTransferFunc( - m_pRenderStatus->GetTransferFunc( - m_pImageObject->m_GeneralState.GetTR())); - } - if (m_pImageObject->m_GeneralState.GetTransferFunc() && - !m_pImageObject->m_GeneralState.GetTransferFunc()->m_bIdentity) { + if (state.GetTR()) { + if (!state.GetTransferFunc()) + state.SetTransferFunc(m_pRenderStatus->GetTransferFunc(state.GetTR())); + + if (state.GetTransferFunc() && !state.GetTransferFunc()->GetIdentity()) { m_pDIBSource = m_Loader.m_pBitmap = - m_pImageObject->m_GeneralState.GetTransferFunc()->TranslateImage( - m_Loader.m_pBitmap, !m_Loader.m_bCached); + state.GetTransferFunc()->TranslateImage(m_Loader.m_pBitmap); if (m_Loader.m_bCached && m_Loader.m_pMask) - m_Loader.m_pMask = m_Loader.m_pMask->Clone().release(); + m_Loader.m_pMask = m_Loader.m_pMask->Clone(nullptr); m_Loader.m_bCached = false; } } @@ -110,65 +103,51 @@ bool CPDF_ImageRenderer::StartRenderDIBSource() { if (m_pPattern) m_bPatternColor = true; } - m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject); - } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) { - m_pClone = m_pDIBSource->Clone(); - m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor, - m_pRenderStatus->m_Options.m_ForeColor); - m_pDIBSource = m_pClone.get(); + m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject.Get()); + } else if (m_pRenderStatus->GetRenderOptions()->ColorModeIs( + CPDF_RenderOptions::kGray)) { + RetainPtr pClone = m_pDIBSource->Clone(nullptr); + if (!pClone) + return false; + + pClone->ConvertColorScale(0xffffff, 0); + m_pDIBSource = pClone; } m_Flags = 0; - if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) + if (m_pRenderStatus->GetRenderOptions()->HasFlag(RENDER_FORCE_DOWNSAMPLE)) m_Flags |= RENDER_FORCE_DOWNSAMPLE; - else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) + else if (m_pRenderStatus->GetRenderOptions()->HasFlag(RENDER_FORCE_HALFTONE)) m_Flags |= RENDER_FORCE_HALFTONE; - if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) { - CPDF_Object* pFilters = - m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( - "Filter"); - if (pFilters) { - if (pFilters->IsName()) { - CFX_ByteString bsDecodeType = pFilters->GetString(); - if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") - m_Flags |= FXRENDER_IMAGE_LOSSY; - } else if (CPDF_Array* pArray = pFilters->AsArray()) { - for (size_t i = 0; i < pArray->GetCount(); i++) { - CFX_ByteString bsDecodeType = pArray->GetStringAt(i); - if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { - m_Flags |= FXRENDER_IMAGE_LOSSY; - break; - } - } - } - } - } - if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) + + if (m_pRenderStatus->GetRenderDevice()->GetDeviceClass() != FXDC_DISPLAY) + HandleFilters(); + + if (m_pRenderStatus->GetRenderOptions()->HasFlag(RENDER_NOIMAGESMOOTH)) m_Flags |= FXDIB_NOSMOOTH; else if (m_pImageObject->GetImage()->IsInterpol()) m_Flags |= FXDIB_INTERPOL; + if (m_Loader.m_pMask) return DrawMaskedImage(); if (m_bPatternColor) - return DrawPatternImage(m_pObj2Device); - - if (m_BitmapAlpha != 255 || !m_pImageObject->m_GeneralState || - !m_pImageObject->m_GeneralState.GetFillOP() || - m_pImageObject->m_GeneralState.GetOPMode() != 0 || - m_pImageObject->m_GeneralState.GetBlendType() != FXDIB_BLEND_NORMAL || - m_pImageObject->m_GeneralState.GetStrokeAlpha() != 1.0f || - m_pImageObject->m_GeneralState.GetFillAlpha() != 1.0f) { + return DrawPatternImage(m_pObj2Device.Get()); + + if (m_BitmapAlpha != 255 || !state.HasRef() || !state.GetFillOP() || + state.GetOPMode() != 0 || state.GetBlendType() != FXDIB_BLEND_NORMAL || + state.GetStrokeAlpha() != 1.0f || state.GetFillAlpha() != 1.0f) { return StartDIBSource(); } CPDF_Document* pDocument = nullptr; CPDF_Page* pPage = nullptr; - if (m_pRenderStatus->m_pContext->GetPageCache()) { - pPage = m_pRenderStatus->m_pContext->GetPageCache()->GetPage(); - pDocument = pPage->m_pDocument; + if (auto* pPageCache = m_pRenderStatus->GetContext()->GetPageCache()) { + pPage = pPageCache->GetPage(); + pDocument = pPage->m_pDocument.Get(); } else { pDocument = m_pImageObject->GetImage()->GetDocument(); } - CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr; + CPDF_Dictionary* pPageResources = + pPage ? pPage->m_pPageResources.Get() : nullptr; CPDF_Object* pCSObj = m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( "ColorSpace"); @@ -186,18 +165,20 @@ bool CPDF_ImageRenderer::StartRenderDIBSource() { } bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, - CPDF_PageObject* pObj, + CPDF_ImageObject* pImageObject, const CFX_Matrix* pObj2Device, bool bStdCS, int blendType) { + ASSERT(pImageObject); m_pRenderStatus = pStatus; m_bStdCS = bStdCS; - m_pImageObject = pObj->AsImage(); + m_pImageObject = pImageObject; m_BlendType = blendType; m_pObj2Device = pObj2Device; CPDF_Dictionary* pOC = m_pImageObject->GetImage()->GetOC(); - if (pOC && m_pRenderStatus->m_Options.m_pOCContext && - !m_pRenderStatus->m_Options.m_pOCContext->CheckOCGVisible(pOC)) { + if (pOC && m_pRenderStatus->GetRenderOptions()->GetOCContext() && + !m_pRenderStatus->GetRenderOptions()->GetOCContext()->CheckOCGVisible( + pOC)) { return false; } m_ImageMatrix = m_pImageObject->matrix(); @@ -208,7 +189,7 @@ bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, } bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, - const CFX_DIBSource* pDIBSource, + const RetainPtr& pDIBSource, FX_ARGB bitmap_argb, int bitmap_alpha, const CFX_Matrix* pImage2Device, @@ -227,13 +208,14 @@ bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, } bool CPDF_ImageRenderer::NotDrawing() const { - return m_pRenderStatus->m_bPrint && - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE); + return m_pRenderStatus->IsPrint() && + !(m_pRenderStatus->GetRenderDevice()->GetRenderCaps() & + FXRC_BLEND_MODE); } FX_RECT CPDF_ImageRenderer::GetDrawRect() const { FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); - rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); + rect.Intersect(m_pRenderStatus->GetRenderDevice()->GetClipBox()); return rect; } @@ -243,15 +225,16 @@ CFX_Matrix CPDF_ImageRenderer::GetDrawMatrix(const FX_RECT& rect) const { return new_matrix; } -void CPDF_ImageRenderer::CalculateDrawImage(CFX_FxgeDevice* pBitmapDevice1, - CFX_FxgeDevice* pBitmapDevice2, - const CFX_DIBSource* pDIBSource, - CFX_Matrix* pNewMatrix, - const FX_RECT& rect) const { +void CPDF_ImageRenderer::CalculateDrawImage( + CFX_DefaultRenderDevice* pBitmapDevice1, + CFX_DefaultRenderDevice* pBitmapDevice2, + const RetainPtr& pDIBSource, + CFX_Matrix* pNewMatrix, + const FX_RECT& rect) const { CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, pBitmapDevice2, nullptr, - nullptr, nullptr, nullptr, nullptr, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); + bitmap_render.Initialize(m_pRenderStatus->GetContext(), pBitmapDevice2, + nullptr, nullptr, nullptr, nullptr, nullptr, 0, + m_pRenderStatus->GetDropObjects(), nullptr, true); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, pDIBSource, 0xffffffff, 255, pNewMatrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { @@ -273,11 +256,11 @@ void CPDF_ImageRenderer::CalculateDrawImage(CFX_FxgeDevice* pBitmapDevice1, continue; } int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; - *dest_scan++ = std::min(std::max(orig, 0), 255); + *dest_scan++ = pdfium::clamp(orig, 0, 255); orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; - *dest_scan++ = std::min(std::max(orig, 0), 255); + *dest_scan++ = pdfium::clamp(orig, 0, 255); orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; - *dest_scan++ = std::min(std::max(orig, 0), 255); + *dest_scan++ = pdfium::clamp(orig, 0, 255); dest_scan++; } } @@ -294,28 +277,29 @@ bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { return false; CFX_Matrix new_matrix = GetDrawMatrix(rect); - CFX_FxgeDevice bitmap_device1; + CFX_DefaultRenderDevice bitmap_device1; if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) return true; bitmap_device1.GetBitmap()->Clear(0xffffff); CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, + bitmap_render.Initialize(m_pRenderStatus->GetContext(), &bitmap_device1, nullptr, nullptr, nullptr, nullptr, - &m_pRenderStatus->m_Options, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); + m_pRenderStatus->GetRenderOptions(), 0, + m_pRenderStatus->GetDropObjects(), nullptr, true); CFX_Matrix patternDevice = *pObj2Device; - patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top); + patternDevice.Translate(static_cast(-rect.left), + static_cast(-rect.top)); if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { - bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject, + bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject.Get(), &patternDevice, false); } else if (CPDF_ShadingPattern* pShadingPattern = m_pPattern->AsShadingPattern()) { - bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject, + bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject.Get(), &patternDevice, false); } - CFX_FxgeDevice bitmap_device2; + CFX_DefaultRenderDevice bitmap_device2; if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, nullptr)) { return true; @@ -326,7 +310,7 @@ bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); bitmap_device1.GetBitmap()->MultiplyAlpha(255); - m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( + m_pRenderStatus->GetRenderDevice()->SetDIBitsWithBlend( bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); return false; } @@ -342,7 +326,7 @@ bool CPDF_ImageRenderer::DrawMaskedImage() { return false; CFX_Matrix new_matrix = GetDrawMatrix(rect); - CFX_FxgeDevice bitmap_device1; + CFX_DefaultRenderDevice bitmap_device1; if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) return true; @@ -352,15 +336,15 @@ bool CPDF_ImageRenderer::DrawMaskedImage() { bitmap_device1.GetBitmap()->Clear(0xffffff); #endif CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, + bitmap_render.Initialize(m_pRenderStatus->GetContext(), &bitmap_device1, nullptr, nullptr, nullptr, nullptr, nullptr, 0, - m_pRenderStatus->m_bDropObjects, nullptr, true); + m_pRenderStatus->GetDropObjects(), nullptr, true); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { image_render.Continue(nullptr); } - CFX_FxgeDevice bitmap_device2; + CFX_DefaultRenderDevice bitmap_device2; if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, nullptr)) return true; @@ -373,7 +357,7 @@ bool CPDF_ImageRenderer::DrawMaskedImage() { CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_Loader.m_pMask, &new_matrix, rect); #ifdef _SKIA_SUPPORT_ - m_pRenderStatus->m_pDevice->SetBitsWithMask( + m_pRenderStatus->GetRenderDevice()->SetBitsWithMask( bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, rect.top, m_BitmapAlpha, m_BlendType); #else @@ -381,7 +365,7 @@ bool CPDF_ImageRenderer::DrawMaskedImage() { bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); if (m_BitmapAlpha < 255) bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); - m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( + m_pRenderStatus->GetRenderDevice()->SetDIBitsWithBlend( bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); #endif // _SKIA_SUPPORT_ return false; @@ -402,12 +386,12 @@ bool CPDF_ImageRenderer::StartDIBSource() { } } #ifdef _SKIA_SUPPORT_ - CFX_DIBitmap* premultiplied = m_pDIBSource->Clone().release(); + RetainPtr premultiplied = m_pDIBSource->Clone(nullptr); if (m_pDIBSource->HasAlpha()) CFX_SkiaDeviceDriver::PreMultiply(premultiplied); - if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( + if (m_pRenderStatus->GetRenderDevice()->StartDIBitsWithBlend( premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, - m_DeviceHandle, m_BlendType)) { + &m_DeviceHandle, m_BlendType)) { if (m_DeviceHandle) { m_Status = 3; return true; @@ -415,9 +399,9 @@ bool CPDF_ImageRenderer::StartDIBSource() { return false; } #else - if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( + if (m_pRenderStatus->GetRenderDevice()->StartDIBitsWithBlend( m_pDIBSource, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, - m_DeviceHandle, m_BlendType)) { + &m_DeviceHandle, m_BlendType)) { if (m_DeviceHandle) { m_Status = 3; return true; @@ -429,19 +413,18 @@ bool CPDF_ImageRenderer::StartDIBSource() { FX_RECT image_rect = image_rect_f.GetOuterRect(); int dest_width = image_rect.Width(); int dest_height = image_rect.Height(); - if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || - (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { + if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || + (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { if (NotDrawing()) { m_Result = false; return false; } - FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); + FX_RECT clip_box = m_pRenderStatus->GetRenderDevice()->GetClipBox(); clip_box.Intersect(image_rect); m_Status = 2; m_pTransformer = pdfium::MakeUnique( m_pDIBSource, &m_ImageMatrix, m_Flags, &clip_box); - m_pTransformer->Start(); return true; } if (m_ImageMatrix.a < 0) @@ -453,7 +436,7 @@ bool CPDF_ImageRenderer::StartDIBSource() { int dest_left = dest_width > 0 ? image_rect.left : image_rect.right; int dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { - if (m_pRenderStatus->m_pDevice->StretchDIBitsWithFlagsAndBlend( + if (m_pRenderStatus->GetRenderDevice()->StretchDIBitsWithFlagsAndBlend( m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags, m_BlendType)) { return false; @@ -462,7 +445,7 @@ bool CPDF_ImageRenderer::StartDIBSource() { if (m_pDIBSource->IsAlphaMask()) { if (m_BitmapAlpha != 255) m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); - if (m_pRenderStatus->m_pDevice->StretchBitMaskWithFlags( + if (m_pRenderStatus->GetRenderDevice()->StretchBitMaskWithFlags( m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_FillArgb, m_Flags)) { return false; @@ -473,16 +456,16 @@ bool CPDF_ImageRenderer::StartDIBSource() { return true; } - FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); + FX_RECT clip_box = m_pRenderStatus->GetRenderDevice()->GetClipBox(); FX_RECT dest_rect = clip_box; dest_rect.Intersect(image_rect); FX_RECT dest_clip( dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); - std::unique_ptr pStretched( - m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip)); + RetainPtr pStretched = + m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip); if (pStretched) { - m_pRenderStatus->CompositeDIBitmap(pStretched.get(), dest_rect.left, + m_pRenderStatus->CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb, m_BitmapAlpha, m_BlendType, false); } @@ -496,27 +479,26 @@ bool CPDF_ImageRenderer::StartBitmapAlpha() { path.Transform(&m_ImageMatrix); uint32_t fill_color = ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha); - m_pRenderStatus->m_pDevice->DrawPath(&path, nullptr, nullptr, fill_color, 0, - FXFILL_WINDING); + m_pRenderStatus->GetRenderDevice()->DrawPath(&path, nullptr, nullptr, + fill_color, 0, FXFILL_WINDING); return false; } - CFX_MaybeOwned pAlphaMask; + RetainPtr pAlphaMask; if (m_pDIBSource->IsAlphaMask()) - pAlphaMask = const_cast(m_pDIBSource); + pAlphaMask = m_pDIBSource; else pAlphaMask = m_pDIBSource->CloneAlphaMask(); - if (FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || - FXSYS_fabs(m_ImageMatrix.c) >= 0.5f) { + if (fabs(m_ImageMatrix.b) >= 0.5f || fabs(m_ImageMatrix.c) >= 0.5f) { int left; int top; - std::unique_ptr pTransformed = - pAlphaMask->TransformTo(&m_ImageMatrix, left, top); + RetainPtr pTransformed = + pAlphaMask->TransformTo(&m_ImageMatrix, &left, &top); if (!pTransformed) return true; - m_pRenderStatus->m_pDevice->SetBitMask( - pTransformed.get(), left, top, + m_pRenderStatus->GetRenderDevice()->SetBitMask( + pTransformed, left, top, ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); return false; } @@ -528,41 +510,43 @@ bool CPDF_ImageRenderer::StartBitmapAlpha() { m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height(); int left = dest_width > 0 ? image_rect.left : image_rect.right; int top = dest_height > 0 ? image_rect.top : image_rect.bottom; - m_pRenderStatus->m_pDevice->StretchBitMask( - pAlphaMask.Get(), left, top, dest_width, dest_height, + m_pRenderStatus->GetRenderDevice()->StretchBitMask( + pAlphaMask, left, top, dest_width, dest_height, ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); return false; } -bool CPDF_ImageRenderer::Continue(IFX_Pause* pPause) { +bool CPDF_ImageRenderer::Continue(IFX_PauseIndicator* pPause) { if (m_Status == 2) { if (m_pTransformer->Continue(pPause)) return true; - std::unique_ptr pBitmap(m_pTransformer->DetachBitmap()); + RetainPtr pBitmap = m_pTransformer->DetachBitmap(); if (!pBitmap) return false; if (pBitmap->IsAlphaMask()) { if (m_BitmapAlpha != 255) m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); - m_Result = m_pRenderStatus->m_pDevice->SetBitMask( - pBitmap.get(), m_pTransformer->result().left, - m_pTransformer->result().top, m_FillArgb); + m_Result = m_pRenderStatus->GetRenderDevice()->SetBitMask( + pBitmap, m_pTransformer->result().left, m_pTransformer->result().top, + m_FillArgb); } else { if (m_BitmapAlpha != 255) pBitmap->MultiplyAlpha(m_BitmapAlpha); - m_Result = m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( - pBitmap.get(), m_pTransformer->result().left, - m_pTransformer->result().top, m_BlendType); + m_Result = m_pRenderStatus->GetRenderDevice()->SetDIBitsWithBlend( + pBitmap, m_pTransformer->result().left, m_pTransformer->result().top, + m_BlendType); } return false; } - if (m_Status == 3) - return m_pRenderStatus->m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); + if (m_Status == 3) { + return m_pRenderStatus->GetRenderDevice()->ContinueDIBits( + m_DeviceHandle.get(), pPause); + } if (m_Status == 4) { - if (m_Loader.Continue(pPause)) + if (m_Loader.Continue(pPause, m_pRenderStatus.Get())) return true; if (StartRenderDIBSource()) @@ -570,3 +554,30 @@ bool CPDF_ImageRenderer::Continue(IFX_Pause* pPause) { } return false; } + +void CPDF_ImageRenderer::HandleFilters() { + CPDF_Object* pFilters = + m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( + "Filter"); + if (!pFilters) + return; + + if (pFilters->IsName()) { + ByteString bsDecodeType = pFilters->GetString(); + if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") + m_Flags |= FXRENDER_IMAGE_LOSSY; + return; + } + + CPDF_Array* pArray = pFilters->AsArray(); + if (!pArray) + return; + + for (size_t i = 0; i < pArray->GetCount(); i++) { + ByteString bsDecodeType = pArray->GetStringAt(i); + if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { + m_Flags |= FXRENDER_IMAGE_LOSSY; + break; + } + } +} diff --git a/core/fpdfapi/render/cpdf_imagerenderer.h b/core/fpdfapi/render/cpdf_imagerenderer.h index d358716e9feb1aee3694b3ac474d6e150eec69b6..a5d9ba769b90d5438c4b51969af2da854242b03d 100644 --- a/core/fpdfapi/render/cpdf_imagerenderer.h +++ b/core/fpdfapi/render/cpdf_imagerenderer.h @@ -10,8 +10,13 @@ #include #include "core/fpdfapi/render/cpdf_imageloader.h" +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/dib/cfx_imagerenderer.h" -class CFX_FxgeDevice; +class CFX_DIBitmap; +class CFX_DIBSource; +class CFX_DefaultRenderDevice; class CFX_ImageTransformer; class CPDF_ImageObject; class CPDF_PageObject; @@ -24,13 +29,13 @@ class CPDF_ImageRenderer { ~CPDF_ImageRenderer(); bool Start(CPDF_RenderStatus* pStatus, - CPDF_PageObject* pObj, + CPDF_ImageObject* pImageObject, const CFX_Matrix* pObj2Device, bool bStdCS, int blendType); bool Start(CPDF_RenderStatus* pStatus, - const CFX_DIBSource* pDIBSource, + const RetainPtr& pDIBSource, FX_ARGB bitmap_argb, int bitmap_alpha, const CFX_Matrix* pImage2Device, @@ -38,7 +43,7 @@ class CPDF_ImageRenderer { bool bStdCS, int blendType); - bool Continue(IFX_Pause* pPause); + bool Continue(IFX_PauseIndicator* pPause); bool GetResult() const { return m_Result; } private: @@ -51,27 +56,27 @@ class CPDF_ImageRenderer { bool NotDrawing() const; FX_RECT GetDrawRect() const; CFX_Matrix GetDrawMatrix(const FX_RECT& rect) const; - void CalculateDrawImage(CFX_FxgeDevice* bitmap_device1, - CFX_FxgeDevice* bitmap_device2, - const CFX_DIBSource* pDIBSource, + void CalculateDrawImage(CFX_DefaultRenderDevice* bitmap_device1, + CFX_DefaultRenderDevice* bitmap_device2, + const RetainPtr& pDIBSource, CFX_Matrix* pNewMatrix, const FX_RECT& rect) const; + void HandleFilters(); - CPDF_RenderStatus* m_pRenderStatus; - CPDF_ImageObject* m_pImageObject; + UnownedPtr m_pRenderStatus; + UnownedPtr m_pImageObject; int m_Status; - const CFX_Matrix* m_pObj2Device; + UnownedPtr m_pObj2Device; CFX_Matrix m_ImageMatrix; CPDF_ImageLoader m_Loader; - const CFX_DIBSource* m_pDIBSource; - std::unique_ptr m_pClone; + RetainPtr m_pDIBSource; int m_BitmapAlpha; bool m_bPatternColor; - CPDF_Pattern* m_pPattern; + UnownedPtr m_pPattern; FX_ARGB m_FillArgb; uint32_t m_Flags; std::unique_ptr m_pTransformer; - void* m_DeviceHandle; + std::unique_ptr m_DeviceHandle; bool m_bStdCS; int m_BlendType; bool m_Result; diff --git a/core/fpdfapi/render/cpdf_pagerendercache.cpp b/core/fpdfapi/render/cpdf_pagerendercache.cpp index faa9732f9b0e68716f2226da896d8377e8c49bfe..0d01589af3b322b655e2d0a99f9c5866b9fd1324 100644 --- a/core/fpdfapi/render/cpdf_pagerendercache.cpp +++ b/core/fpdfapi/render/cpdf_pagerendercache.cpp @@ -6,22 +6,24 @@ #include "core/fpdfapi/render/cpdf_pagerendercache.h" +#include +#include + +#include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/render/cpdf_imagecacheentry.h" #include "core/fpdfapi/render/cpdf_renderstatus.h" namespace { -struct CACHEINFO { +struct CacheInfo { + CacheInfo(uint32_t t, CPDF_Stream* stream) : time(t), pStream(stream) {} + uint32_t time; CPDF_Stream* pStream; -}; -extern "C" { -static int compare(const void* data1, const void* data2) { - return ((CACHEINFO*)data1)->time - ((CACHEINFO*)data2)->time; -} -} // extern "C" + bool operator<(const CacheInfo& other) const { return time < other.time; } +}; } // namespace @@ -42,31 +44,29 @@ void CPDF_PageRenderCache::CacheOptimization(int32_t dwLimitCacheSize) { return; size_t nCount = m_ImageCache.size(); - CACHEINFO* pCACHEINFO = FX_Alloc(CACHEINFO, nCount); - size_t i = 0; + std::vector cache_info; + cache_info.reserve(nCount); for (const auto& it : m_ImageCache) { - pCACHEINFO[i].time = it.second->GetTimeCount(); - pCACHEINFO[i++].pStream = it.second->GetStream(); + cache_info.emplace_back(it.second->GetTimeCount(), + it.second->GetImage()->GetStream()); } - FXSYS_qsort(pCACHEINFO, nCount, sizeof(CACHEINFO), compare); - uint32_t nTimeCount = m_nTimeCount; + std::sort(cache_info.begin(), cache_info.end()); // Check if time value is about to roll over and reset all entries. // The comparision is legal because uint32_t is an unsigned type. + uint32_t nTimeCount = m_nTimeCount; if (nTimeCount + 1 < nTimeCount) { - for (i = 0; i < nCount; i++) - m_ImageCache[pCACHEINFO[i].pStream]->m_dwTimeCount = i; + for (size_t i = 0; i < nCount; i++) + m_ImageCache[cache_info[i].pStream]->m_dwTimeCount = i; m_nTimeCount = nCount; } - i = 0; + size_t i = 0; while (i + 15 < nCount) - ClearImageCacheEntry(pCACHEINFO[i++].pStream); + ClearImageCacheEntry(cache_info[i++].pStream); while (i < nCount && m_nCacheSize > (uint32_t)dwLimitCacheSize) - ClearImageCacheEntry(pCACHEINFO[i++].pStream); - - FX_Free(pCACHEINFO); + ClearImageCacheEntry(cache_info[i++].pStream); } void CPDF_PageRenderCache::ClearImageCacheEntry(CPDF_Stream* pStream) { @@ -80,24 +80,23 @@ void CPDF_PageRenderCache::ClearImageCacheEntry(CPDF_Stream* pStream) { } bool CPDF_PageRenderCache::StartGetCachedBitmap( - CPDF_Stream* pStream, + const RetainPtr& pImage, bool bStdCS, uint32_t GroupFamily, bool bLoadMask, - CPDF_RenderStatus* pRenderStatus, - int32_t downsampleWidth, - int32_t downsampleHeight) { + CPDF_RenderStatus* pRenderStatus) { + CPDF_Stream* pStream = pImage->GetStream(); const auto it = m_ImageCache.find(pStream); m_bCurFindCache = it != m_ImageCache.end(); if (m_bCurFindCache) { m_pCurImageCacheEntry = it->second; } else { m_pCurImageCacheEntry = - new CPDF_ImageCacheEntry(m_pPage->m_pDocument, pStream); + new CPDF_ImageCacheEntry(m_pPage->m_pDocument.Get(), pImage); } int ret = m_pCurImageCacheEntry->StartGetCachedBitmap( - pRenderStatus->m_pFormResource, m_pPage->m_pPageResources, bStdCS, - GroupFamily, bLoadMask, pRenderStatus, downsampleWidth, downsampleHeight); + pRenderStatus->GetFormResource(), m_pPage->m_pPageResources.Get(), bStdCS, + GroupFamily, bLoadMask, pRenderStatus); if (ret == 2) return true; @@ -111,28 +110,32 @@ bool CPDF_PageRenderCache::StartGetCachedBitmap( return false; } -bool CPDF_PageRenderCache::Continue(IFX_Pause* pPause) { - int ret = m_pCurImageCacheEntry->Continue(pPause); +bool CPDF_PageRenderCache::Continue(IFX_PauseIndicator* pPause, + CPDF_RenderStatus* pRenderStatus) { + int ret = m_pCurImageCacheEntry->Continue(pPause, pRenderStatus); if (ret == 2) return true; m_nTimeCount++; - if (!m_bCurFindCache) - m_ImageCache[m_pCurImageCacheEntry->GetStream()] = m_pCurImageCacheEntry; + if (!m_bCurFindCache) { + m_ImageCache[m_pCurImageCacheEntry->GetImage()->GetStream()] = + m_pCurImageCacheEntry; + } if (!ret) m_nCacheSize += m_pCurImageCacheEntry->EstimateSize(); return false; } -void CPDF_PageRenderCache::ResetBitmap(CPDF_Stream* pStream, - const CFX_DIBitmap* pBitmap) { +void CPDF_PageRenderCache::ResetBitmap(const RetainPtr& pImage, + const RetainPtr& pBitmap) { CPDF_ImageCacheEntry* pEntry; + CPDF_Stream* pStream = pImage->GetStream(); const auto it = m_ImageCache.find(pStream); if (it == m_ImageCache.end()) { if (!pBitmap) return; - pEntry = new CPDF_ImageCacheEntry(m_pPage->m_pDocument, pStream); + pEntry = new CPDF_ImageCacheEntry(m_pPage->m_pDocument.Get(), pImage); m_ImageCache[pStream] = pEntry; } else { pEntry = it->second; diff --git a/core/fpdfapi/render/cpdf_pagerendercache.h b/core/fpdfapi/render/cpdf_pagerendercache.h index 6c9ed76911520fa6baa3cc403ef3a97ec6b9be4a..58f0bb7e32acbf142e1f64e1b4e86c8995c1a9b3 100644 --- a/core/fpdfapi/render/cpdf_pagerendercache.h +++ b/core/fpdfapi/render/cpdf_pagerendercache.h @@ -10,14 +10,16 @@ #include #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" -class CPDF_Stream; +class CFX_DIBitmap; +class CPDF_Image; class CPDF_ImageCacheEntry; class CPDF_Page; class CPDF_RenderStatus; -class CFX_DIBitmap; -class CFX_DIBSource; -class IFX_Pause; +class CPDF_Stream; +class IFX_PauseIndicator; class CPDF_PageRenderCache { public: @@ -26,27 +28,25 @@ class CPDF_PageRenderCache { void CacheOptimization(int32_t dwLimitCacheSize); uint32_t GetTimeCount() const { return m_nTimeCount; } - - void ResetBitmap(CPDF_Stream* pStream, const CFX_DIBitmap* pBitmap); - CPDF_Page* GetPage() const { return m_pPage; } + void ResetBitmap(const RetainPtr& pImage, + const RetainPtr& pBitmap); + CPDF_Page* GetPage() const { return m_pPage.Get(); } CPDF_ImageCacheEntry* GetCurImageCacheEntry() const { return m_pCurImageCacheEntry; } - bool StartGetCachedBitmap(CPDF_Stream* pStream, + bool StartGetCachedBitmap(const RetainPtr& pImage, bool bStdCS, uint32_t GroupFamily, bool bLoadMask, - CPDF_RenderStatus* pRenderStatus, - int32_t downsampleWidth, - int32_t downsampleHeight); + CPDF_RenderStatus* pRenderStatus); - bool Continue(IFX_Pause* pPause); + bool Continue(IFX_PauseIndicator* pPause, CPDF_RenderStatus* pRenderStatus); private: void ClearImageCacheEntry(CPDF_Stream* pStream); - CPDF_Page* const m_pPage; + UnownedPtr const m_pPage; CPDF_ImageCacheEntry* m_pCurImageCacheEntry; std::map m_ImageCache; uint32_t m_nTimeCount; diff --git a/core/fpdfapi/render/cpdf_progressiverenderer.cpp b/core/fpdfapi/render/cpdf_progressiverenderer.cpp index 6aa3b8a30982bd3f14fadd2c43a63f5e6f672cbd..e509a254404bc3fe3c13f04f94145d57111ee91e 100644 --- a/core/fpdfapi/render/cpdf_progressiverenderer.cpp +++ b/core/fpdfapi/render/cpdf_progressiverenderer.cpp @@ -6,11 +6,14 @@ #include "core/fpdfapi/render/cpdf_progressiverenderer.h" +#include "core/fpdfapi/page/cpdf_image.h" +#include "core/fpdfapi/page/cpdf_imageobject.h" #include "core/fpdfapi/page/cpdf_pageobject.h" #include "core/fpdfapi/page/cpdf_pageobjectholder.h" #include "core/fpdfapi/render/cpdf_pagerendercache.h" #include "core/fpdfapi/render/cpdf_renderoptions.h" #include "core/fpdfapi/render/cpdf_renderstatus.h" +#include "core/fxcrt/ifx_pauseindicator.h" #include "core/fxge/cfx_renderdevice.h" #include "third_party/base/ptr_util.h" @@ -26,11 +29,13 @@ CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer( m_pCurrentLayer(nullptr) {} CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() { - if (m_pRenderStatus) + if (m_pRenderStatus) { + m_pRenderStatus.reset(); // Release first. m_pDevice->RestoreState(false); + } } -void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause) { +void CPDF_ProgressiveRenderer::Start(IFX_PauseIndicator* pPause) { if (!m_pContext || !m_pDevice || m_Status != Ready) { m_Status = Failed; return; @@ -39,7 +44,7 @@ void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause) { Continue(pPause); } -void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) { +void CPDF_ProgressiveRenderer::Continue(IFX_PauseIndicator* pPause) { while (m_Status == ToBeContinued) { if (!m_pCurrentLayer) { if (m_LayerIndex >= m_pContext->CountLayers()) { @@ -51,13 +56,12 @@ void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) { m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end(); m_pRenderStatus = pdfium::MakeUnique(); m_pRenderStatus->Initialize( - m_pContext, m_pDevice, nullptr, nullptr, nullptr, nullptr, m_pOptions, - m_pCurrentLayer->m_pObjectHolder->m_Transparency, false, nullptr); + m_pContext.Get(), m_pDevice.Get(), nullptr, nullptr, nullptr, nullptr, + m_pOptions, m_pCurrentLayer->m_pObjectHolder->m_iTransparency, false, + nullptr); m_pDevice->SaveState(); - m_ClipRect = CFX_FloatRect(m_pDevice->GetClipBox()); - CFX_Matrix device2object; - device2object.SetReverse(m_pCurrentLayer->m_Matrix); - device2object.TransformRect(m_ClipRect); + m_ClipRect = m_pCurrentLayer->m_Matrix.GetInverse().TransformRect( + CFX_FloatRect(m_pDevice->GetClipBox())); } CPDF_PageObjectList::iterator iter; CPDF_PageObjectList::iterator iterEnd = @@ -69,20 +73,31 @@ void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) { iter = m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->begin(); } int nObjsToGo = kStepLimit; + bool is_mask = false; while (iter != iterEnd) { CPDF_PageObject* pCurObj = iter->get(); if (pCurObj && pCurObj->m_Left <= m_ClipRect.right && pCurObj->m_Right >= m_ClipRect.left && pCurObj->m_Bottom <= m_ClipRect.top && pCurObj->m_Top >= m_ClipRect.bottom) { + if (m_pOptions->HasFlag(RENDER_BREAKFORMASKS) && pCurObj->IsImage() && + pCurObj->AsImage()->GetImage()->IsMask()) { + if (m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { + m_LastObjectRendered = iter; + m_pRenderStatus->ProcessClipPath(pCurObj->m_ClipPath, + &m_pCurrentLayer->m_Matrix); + return; + } + is_mask = true; + } if (m_pRenderStatus->ContinueSingleObject( pCurObj, &m_pCurrentLayer->m_Matrix, pPause)) { return; } - if (pCurObj->IsImage() && - m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { + if (pCurObj->IsImage() && m_pRenderStatus->GetRenderOptions()->HasFlag( + RENDER_LIMITEDIMAGECACHE)) { m_pContext->GetPageCache()->CacheOptimization( - m_pRenderStatus->m_Options.m_dwLimitCacheSize); + m_pRenderStatus->GetRenderOptions()->GetCacheSizeLimit()); } if (pCurObj->IsForm() || pCurObj->IsShading()) nObjsToGo = 0; @@ -96,15 +111,19 @@ void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) { nObjsToGo = kStepLimit; } ++iter; + if (is_mask && iter != iterEnd) + return; } if (m_pCurrentLayer->m_pObjectHolder->IsParsed()) { m_pRenderStatus.reset(); m_pDevice->RestoreState(false); m_pCurrentLayer = nullptr; m_LayerIndex++; - if (pPause && pPause->NeedToPauseNow()) { + if (is_mask || (pPause && pPause->NeedToPauseNow())) { return; } + } else if (is_mask) { + return; } else { m_pCurrentLayer->m_pObjectHolder->ContinueParse(pPause); if (!m_pCurrentLayer->m_pObjectHolder->IsParsed()) diff --git a/core/fpdfapi/render/cpdf_progressiverenderer.h b/core/fpdfapi/render/cpdf_progressiverenderer.h index f0b15796019073e8d0a3c325ca92727f5619ae2d..ffd63a9aaf58cc7e1c89f0728fd28ab3b417dac6 100644 --- a/core/fpdfapi/render/cpdf_progressiverenderer.h +++ b/core/fpdfapi/render/cpdf_progressiverenderer.h @@ -17,7 +17,7 @@ class CPDF_RenderOptions; class CPDF_RenderStatus; class CFX_RenderDevice; -class IFX_Pause; +class IFX_PauseIndicator; class CPDF_ProgressiveRenderer { public: @@ -25,8 +25,8 @@ class CPDF_ProgressiveRenderer { // cannot #include that header. fpdfsdk/fpdf_progressive.cpp has // static_asserts to make sure the two sets of values match. enum Status { - Ready, // FPDF_RENDER_READER - ToBeContinued, // FPDF_RENDER_TOBECOUNTINUED + Ready, // FPDF_RENDER_READY + ToBeContinued, // FPDF_RENDER_TOBECONTINUED Done, // FPDF_RENDER_DONE Failed // FPDF_RENDER_FAILED }; @@ -39,16 +39,16 @@ class CPDF_ProgressiveRenderer { ~CPDF_ProgressiveRenderer(); Status GetStatus() const { return m_Status; } - void Start(IFX_Pause* pPause); - void Continue(IFX_Pause* pPause); + void Start(IFX_PauseIndicator* pPause); + void Continue(IFX_PauseIndicator* pPause); private: // Maximum page objects to render before checking for pause. static const int kStepLimit = 100; Status m_Status; - CPDF_RenderContext* const m_pContext; - CFX_RenderDevice* const m_pDevice; + UnownedPtr const m_pContext; + UnownedPtr const m_pDevice; const CPDF_RenderOptions* const m_pOptions; std::unique_ptr m_pRenderStatus; CFX_FloatRect m_ClipRect; diff --git a/core/fpdfapi/render/cpdf_rendercontext.cpp b/core/fpdfapi/render/cpdf_rendercontext.cpp index d74f72985860bb40e89f3c297504549606b6cfea..0656edda22445ce2c39a8a2cc5ad7333d0d703b8 100644 --- a/core/fpdfapi/render/cpdf_rendercontext.cpp +++ b/core/fpdfapi/render/cpdf_rendercontext.cpp @@ -17,11 +17,12 @@ #include "core/fpdfapi/render/cpdf_renderstatus.h" #include "core/fpdfapi/render/cpdf_textrenderer.h" #include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" CPDF_RenderContext::CPDF_RenderContext(CPDF_Page* pPage) - : m_pDocument(pPage->m_pDocument), - m_pPageResources(pPage->m_pPageResources), + : m_pDocument(pPage->m_pDocument.Get()), + m_pPageResources(pPage->m_pPageResources.Get()), m_pPageCache(pPage->GetRenderCache()) {} CPDF_RenderContext::CPDF_RenderContext(CPDF_Document* pDoc, @@ -30,11 +31,11 @@ CPDF_RenderContext::CPDF_RenderContext(CPDF_Document* pDoc, CPDF_RenderContext::~CPDF_RenderContext() {} -void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer, +void CPDF_RenderContext::GetBackground(const RetainPtr& pBuffer, const CPDF_PageObject* pObj, const CPDF_RenderOptions* pOptions, CFX_Matrix* pFinalMatrix) { - CFX_FxgeDevice device; + CFX_DefaultRenderDevice device; device.Attach(pBuffer, false, nullptr, false); FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight()); @@ -63,34 +64,32 @@ void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_RenderOptions* pOptions, const CFX_Matrix* pLastMatrix) { for (auto& layer : m_Layers) { - pDevice->SaveState(); + CFX_RenderDevice::StateRestorer restorer(pDevice); + CPDF_RenderStatus status; if (pLastMatrix) { CFX_Matrix FinalMatrix = layer.m_Matrix; FinalMatrix.Concat(*pLastMatrix); - CPDF_RenderStatus status; status.Initialize(this, pDevice, pLastMatrix, pStopObj, nullptr, nullptr, - pOptions, layer.m_pObjectHolder->m_Transparency, false, + pOptions, layer.m_pObjectHolder->m_iTransparency, false, nullptr); - status.RenderObjectList(layer.m_pObjectHolder, &FinalMatrix); - if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) - m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); - if (status.m_bStopped) { - pDevice->RestoreState(false); - break; - } + status.RenderObjectList(layer.m_pObjectHolder.Get(), &FinalMatrix); } else { - CPDF_RenderStatus status; status.Initialize(this, pDevice, nullptr, pStopObj, nullptr, nullptr, - pOptions, layer.m_pObjectHolder->m_Transparency, false, + pOptions, layer.m_pObjectHolder->m_iTransparency, false, nullptr); - status.RenderObjectList(layer.m_pObjectHolder, &layer.m_Matrix); - if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) - m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); - if (status.m_bStopped) { - pDevice->RestoreState(false); - break; - } + status.RenderObjectList(layer.m_pObjectHolder.Get(), &layer.m_Matrix); } - pDevice->RestoreState(false); + if (status.GetRenderOptions()->HasFlag(RENDER_LIMITEDIMAGECACHE)) { + m_pPageCache->CacheOptimization( + status.GetRenderOptions()->GetCacheSizeLimit()); + } + if (status.IsStopped()) + break; } } + +CPDF_RenderContext::Layer::Layer() {} + +CPDF_RenderContext::Layer::Layer(const Layer& that) = default; + +CPDF_RenderContext::Layer::~Layer() {} diff --git a/core/fpdfapi/render/cpdf_rendercontext.h b/core/fpdfapi/render/cpdf_rendercontext.h index a9fd2db78bac2a9ec9cb74f367ae43da10342a43..606e5b9b688ce3a69dfb37a801a46ea17ec59f4f 100644 --- a/core/fpdfapi/render/cpdf_rendercontext.h +++ b/core/fpdfapi/render/cpdf_rendercontext.h @@ -9,8 +9,9 @@ #include -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; class CPDF_Document; @@ -27,7 +28,11 @@ class CPDF_RenderContext { public: class Layer { public: - CPDF_PageObjectHolder* m_pObjectHolder; + Layer(); + Layer(const Layer& that); + ~Layer(); + + UnownedPtr m_pObjectHolder; CFX_Matrix m_Matrix; }; @@ -47,7 +52,7 @@ class CPDF_RenderContext { const CPDF_RenderOptions* pOptions, const CFX_Matrix* pFinalMatrix); - void GetBackground(CFX_DIBitmap* pBuffer, + void GetBackground(const RetainPtr& pBuffer, const CPDF_PageObject* pObj, const CPDF_RenderOptions* pOptions, CFX_Matrix* pFinalMatrix); @@ -55,14 +60,14 @@ class CPDF_RenderContext { size_t CountLayers() const { return m_Layers.size(); } Layer* GetLayer(uint32_t index) { return &m_Layers[index]; } - CPDF_Document* GetDocument() const { return m_pDocument; } - CPDF_Dictionary* GetPageResources() const { return m_pPageResources; } - CPDF_PageRenderCache* GetPageCache() const { return m_pPageCache; } + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } + CPDF_Dictionary* GetPageResources() const { return m_pPageResources.Get(); } + CPDF_PageRenderCache* GetPageCache() const { return m_pPageCache.Get(); } protected: - CPDF_Document* const m_pDocument; - CPDF_Dictionary* m_pPageResources; - CPDF_PageRenderCache* m_pPageCache; + UnownedPtr const m_pDocument; + UnownedPtr m_pPageResources; + UnownedPtr m_pPageCache; std::vector m_Layers; }; diff --git a/core/fpdfapi/render/cpdf_renderoptions.cpp b/core/fpdfapi/render/cpdf_renderoptions.cpp index 717e036feaf8fbea99639e3bf17b11103477bf8e..9af951137ed000f25ff88e6a7fe7dffb3e42c9c3 100644 --- a/core/fpdfapi/render/cpdf_renderoptions.cpp +++ b/core/fpdfapi/render/cpdf_renderoptions.cpp @@ -7,57 +7,31 @@ #include "core/fpdfapi/render/cpdf_renderoptions.h" CPDF_RenderOptions::CPDF_RenderOptions() - : m_ColorMode(RENDER_COLOR_NORMAL), + : m_ColorMode(kNormal), m_Flags(RENDER_CLEARTYPE), - m_Interpolation(0), - m_AddFlags(0), m_dwLimitCacheSize(1024 * 1024 * 100), - m_HalftoneLimit(-1), m_bDrawAnnots(false) {} CPDF_RenderOptions::CPDF_RenderOptions(const CPDF_RenderOptions& rhs) : m_ColorMode(rhs.m_ColorMode), - m_BackColor(rhs.m_BackColor), - m_ForeColor(rhs.m_ForeColor), m_Flags(rhs.m_Flags), - m_Interpolation(rhs.m_Interpolation), - m_AddFlags(rhs.m_AddFlags), m_dwLimitCacheSize(rhs.m_dwLimitCacheSize), - m_HalftoneLimit(rhs.m_HalftoneLimit), m_bDrawAnnots(rhs.m_bDrawAnnots), m_pOCContext(rhs.m_pOCContext) {} CPDF_RenderOptions::~CPDF_RenderOptions() {} FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const { - if (m_ColorMode == RENDER_COLOR_NORMAL) + if (ColorModeIs(kNormal)) return argb; - - if (m_ColorMode == RENDER_COLOR_ALPHA) + if (ColorModeIs(kAlpha)) return argb; - int a, r, g, b; - ArgbDecode(argb, a, r, g, b); + int a; + int r; + int g; + int b; + std::tie(a, r, g, b) = ArgbDecode(argb); int gray = FXRGB2GRAY(r, g, b); - if (m_ColorMode == RENDER_COLOR_TWOCOLOR) { - int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) + - (b - gray) * (b - gray); - if (gray < 35 && color < 20) - return ArgbEncode(a, m_ForeColor); - - if (gray > 221 && color < 20) - return ArgbEncode(a, m_BackColor); - - return argb; - } - int fr = FXSYS_GetRValue(m_ForeColor); - int fg = FXSYS_GetGValue(m_ForeColor); - int fb = FXSYS_GetBValue(m_ForeColor); - int br = FXSYS_GetRValue(m_BackColor); - int bg = FXSYS_GetGValue(m_BackColor); - int bb = FXSYS_GetBValue(m_BackColor); - r = (br - fr) * gray / 255 + fr; - g = (bg - fg) * gray / 255 + fg; - b = (bb - fb) * gray / 255 + fb; - return ArgbEncode(a, r, g, b); + return ArgbEncode(a, gray, gray, gray); } diff --git a/core/fpdfapi/render/cpdf_renderoptions.h b/core/fpdfapi/render/cpdf_renderoptions.h index b934941d00b339db3d20961843ef95d4eaa97aeb..9dca633f3f8a07fcecb75cacbc8368436ffaac43 100644 --- a/core/fpdfapi/render/cpdf_renderoptions.h +++ b/core/fpdfapi/render/cpdf_renderoptions.h @@ -8,14 +8,10 @@ #define CORE_FPDFAPI_RENDER_CPDF_RENDEROPTIONS_H_ #include "core/fpdfdoc/cpdf_occontext.h" -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" #include "core/fxge/fx_dib.h" -#define RENDER_COLOR_NORMAL 0 -#define RENDER_COLOR_GRAY 1 -#define RENDER_COLOR_TWOCOLOR 2 -#define RENDER_COLOR_ALPHA 3 #define RENDER_CLEARTYPE 0x00000001 #define RENDER_PRINTGRAPHICTEXT 0x00000002 #define RENDER_FORCE_DOWNSAMPLE 0x00000004 @@ -28,6 +24,7 @@ #define RENDER_PRINTIMAGETEXT 0x00000200 #define RENDER_OVERPRINT 0x00000400 #define RENDER_THINLINE 0x00000800 +#define RENDER_BREAKFORMASKS 0x00001000 #define RENDER_NOTEXTSMOOTH 0x10000000 #define RENDER_NOPATHSMOOTH 0x20000000 #define RENDER_NOIMAGESMOOTH 0x40000000 @@ -35,22 +32,37 @@ class CPDF_RenderOptions { public: + enum Type { kNormal = 0, kGray, kAlpha }; + CPDF_RenderOptions(); CPDF_RenderOptions(const CPDF_RenderOptions& rhs); ~CPDF_RenderOptions(); FX_ARGB TranslateColor(FX_ARGB argb) const; - int m_ColorMode; - FX_COLORREF m_BackColor; - FX_COLORREF m_ForeColor; + void SetColorMode(Type mode) { m_ColorMode = mode; } + bool ColorModeIs(Type mode) const { return m_ColorMode == mode; } + + bool HasFlag(uint32_t flag) const { return !!(m_Flags & flag); } + uint32_t GetFlags() const { return m_Flags; } + void SetFlags(uint32_t flags) { m_Flags = flags; } + + uint32_t GetCacheSizeLimit() const { return m_dwLimitCacheSize; } + + void SetDrawAnnots(bool draw) { m_bDrawAnnots = draw; } + bool GetDrawAnnots() const { return m_bDrawAnnots; } + + void SetOCContext(RetainPtr context) { + m_pOCContext = context; + } + CPDF_OCContext* GetOCContext() const { return m_pOCContext.Get(); } + + private: + Type m_ColorMode; uint32_t m_Flags; - int m_Interpolation; - uint32_t m_AddFlags; uint32_t m_dwLimitCacheSize; - int m_HalftoneLimit; bool m_bDrawAnnots; - CFX_RetainPtr m_pOCContext; + RetainPtr m_pOCContext; }; #endif // CORE_FPDFAPI_RENDER_CPDF_RENDEROPTIONS_H_ diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp index 9022212eccbeec38d86499bd08a05b016fed0493..88998673549359f55c80f8b1c12024cb33acd954 100644 --- a/core/fpdfapi/render/cpdf_renderstatus.cpp +++ b/core/fpdfapi/render/cpdf_renderstatus.cpp @@ -7,6 +7,8 @@ #include "core/fpdfapi/render/cpdf_renderstatus.h" #include +#include +#include #include #include #include @@ -17,6 +19,7 @@ #include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_form.h" #include "core/fpdfapi/page/cpdf_formobject.h" +#include "core/fpdfapi/page/cpdf_function.h" #include "core/fpdfapi/page/cpdf_graphicstates.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_imageobject.h" @@ -28,7 +31,6 @@ #include "core/fpdfapi/page/cpdf_shadingpattern.h" #include "core/fpdfapi/page/cpdf_textobject.h" #include "core/fpdfapi/page/cpdf_tilingpattern.h" -#include "core/fpdfapi/page/pageint.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" @@ -45,17 +47,18 @@ #include "core/fpdfapi/render/cpdf_transferfunc.h" #include "core/fpdfapi/render/cpdf_type3cache.h" #include "core/fpdfdoc/cpdf_occontext.h" -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/cfx_fixedbufgrow.h" #include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" #include "core/fxge/ifx_renderdevicedriver.h" +#include "third_party/base/logging.h" #include "third_party/base/numerics/safe_math.h" #include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" #ifdef _SKIA_SUPPORT_ #include "core/fxge/skia/fx_skia_device.h" @@ -66,11 +69,12 @@ namespace { void ReleaseCachedType3(CPDF_Type3Font* pFont) { - if (!pFont->m_pDocument) + CPDF_Document* pDoc = pFont->GetDocument(); + if (!pDoc) return; - pFont->m_pDocument->GetRenderData()->ReleaseCachedType3(pFont); - pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict()); + pDoc->GetRenderData()->MaybePurgeCachedType3(pFont); + pDoc->GetPageData()->ReleaseFont(pFont->GetFontDict()); } class CPDF_RefType3Cache { @@ -80,11 +84,11 @@ class CPDF_RefType3Cache { ~CPDF_RefType3Cache() { while (m_dwCount--) - ReleaseCachedType3(m_pType3Font); + ReleaseCachedType3(m_pType3Font.Get()); } uint32_t m_dwCount; - CPDF_Type3Font* const m_pType3Font; + UnownedPtr const m_pType3Font; }; uint32_t CountOutputs( @@ -97,7 +101,7 @@ uint32_t CountOutputs( return total; } -void DrawAxialShading(CFX_DIBitmap* pBitmap, +void DrawAxialShading(const RetainPtr& pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Dictionary* pDict, const std::vector>& funcs, @@ -108,12 +112,12 @@ void DrawAxialShading(CFX_DIBitmap* pBitmap, if (!pCoords) return; - FX_FLOAT start_x = pCoords->GetNumberAt(0); - FX_FLOAT start_y = pCoords->GetNumberAt(1); - FX_FLOAT end_x = pCoords->GetNumberAt(2); - FX_FLOAT end_y = pCoords->GetNumberAt(3); - FX_FLOAT t_min = 0; - FX_FLOAT t_max = 1.0f; + float start_x = pCoords->GetNumberAt(0); + float start_y = pCoords->GetNumberAt(1); + float end_x = pCoords->GetNumberAt(2); + float end_y = pCoords->GetNumberAt(3); + float t_min = 0; + float t_max = 1.0f; CPDF_Array* pArray = pDict->GetArrayFor("Domain"); if (pArray) { t_min = pArray->GetNumberAt(0); @@ -128,40 +132,41 @@ void DrawAxialShading(CFX_DIBitmap* pBitmap, } int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); - FX_FLOAT x_span = end_x - start_x; - FX_FLOAT y_span = end_y - start_y; - FX_FLOAT axis_len_square = (x_span * x_span) + (y_span * y_span); - CFX_Matrix matrix; - matrix.SetReverse(*pObject2Bitmap); + float x_span = end_x - start_x; + float y_span = end_y - start_y; + float axis_len_square = (x_span * x_span) + (y_span * y_span); uint32_t total_results = std::max(CountOutputs(funcs), pCS->CountComponents()); - CFX_FixedBufGrow result_array(total_results); - FX_FLOAT* pResults = result_array; - FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); + CFX_FixedBufGrow result_array(total_results); + float* pResults = result_array; + memset(pResults, 0, total_results * sizeof(float)); uint32_t rgb_array[SHADING_STEPS]; for (int i = 0; i < SHADING_STEPS; i++) { - FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; + float input = (t_max - t_min) * i / SHADING_STEPS + t_min; int offset = 0; for (const auto& func : funcs) { if (func) { int nresults = 0; - if (func->Call(&input, 1, pResults + offset, nresults)) + if (func->Call(&input, 1, pResults + offset, &nresults)) offset += nresults; } } - FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; - pCS->GetRGB(pResults, R, G, B); + float R = 0.0f; + float G = 0.0f; + float B = 0.0f; + pCS->GetRGB(pResults, &R, &G, &B); rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); } int pitch = pBitmap->GetPitch(); + CFX_Matrix matrix = pObject2Bitmap->GetInverse(); for (int row = 0; row < height; row++) { uint32_t* dib_buf = (uint32_t*)(pBitmap->GetBuffer() + row * pitch); for (int column = 0; column < width; column++) { - CFX_PointF pos = matrix.Transform(CFX_PointF( - static_cast(column), static_cast(row))); - FX_FLOAT scale = + CFX_PointF pos = matrix.Transform( + CFX_PointF(static_cast(column), static_cast(row))); + float scale = (((pos.x - start_x) * x_span) + ((pos.y - start_y) * y_span)) / axis_len_square; int index = (int32_t)(scale * (SHADING_STEPS - 1)); @@ -181,7 +186,7 @@ void DrawAxialShading(CFX_DIBitmap* pBitmap, } } -void DrawRadialShading(CFX_DIBitmap* pBitmap, +void DrawRadialShading(const RetainPtr& pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Dictionary* pDict, const std::vector>& funcs, @@ -192,16 +197,14 @@ void DrawRadialShading(CFX_DIBitmap* pBitmap, if (!pCoords) return; - FX_FLOAT start_x = pCoords->GetNumberAt(0); - FX_FLOAT start_y = pCoords->GetNumberAt(1); - FX_FLOAT start_r = pCoords->GetNumberAt(2); - FX_FLOAT end_x = pCoords->GetNumberAt(3); - FX_FLOAT end_y = pCoords->GetNumberAt(4); - FX_FLOAT end_r = pCoords->GetNumberAt(5); - CFX_Matrix matrix; - matrix.SetReverse(*pObject2Bitmap); - FX_FLOAT t_min = 0; - FX_FLOAT t_max = 1.0f; + float start_x = pCoords->GetNumberAt(0); + float start_y = pCoords->GetNumberAt(1); + float start_r = pCoords->GetNumberAt(2); + float end_x = pCoords->GetNumberAt(3); + float end_y = pCoords->GetNumberAt(4); + float end_r = pCoords->GetNumberAt(5); + float t_min = 0; + float t_max = 1.0f; CPDF_Array* pArray = pDict->GetArrayFor("Domain"); if (pArray) { t_min = pArray->GetNumberAt(0); @@ -216,61 +219,63 @@ void DrawRadialShading(CFX_DIBitmap* pBitmap, } uint32_t total_results = std::max(CountOutputs(funcs), pCS->CountComponents()); - CFX_FixedBufGrow result_array(total_results); - FX_FLOAT* pResults = result_array; - FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); + CFX_FixedBufGrow result_array(total_results); + float* pResults = result_array; + memset(pResults, 0, total_results * sizeof(float)); uint32_t rgb_array[SHADING_STEPS]; for (int i = 0; i < SHADING_STEPS; i++) { - FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; + float input = (t_max - t_min) * i / SHADING_STEPS + t_min; int offset = 0; for (const auto& func : funcs) { if (func) { int nresults; - if (func->Call(&input, 1, pResults + offset, nresults)) + if (func->Call(&input, 1, pResults + offset, &nresults)) offset += nresults; } } - FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; - pCS->GetRGB(pResults, R, G, B); + float R = 0.0f; + float G = 0.0f; + float B = 0.0f; + pCS->GetRGB(pResults, &R, &G, &B); rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); } - FX_FLOAT a = ((start_x - end_x) * (start_x - end_x)) + - ((start_y - end_y) * (start_y - end_y)) - - ((start_r - end_r) * (start_r - end_r)); + float a = ((start_x - end_x) * (start_x - end_x)) + + ((start_y - end_y) * (start_y - end_y)) - + ((start_r - end_r) * (start_r - end_r)); int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); int pitch = pBitmap->GetPitch(); bool bDecreasing = false; if (start_r > end_r) { - int length = (int)FXSYS_sqrt((((start_x - end_x) * (start_x - end_x)) + - ((start_y - end_y) * (start_y - end_y)))); + int length = (int)sqrt((((start_x - end_x) * (start_x - end_x)) + + ((start_y - end_y) * (start_y - end_y)))); if (length < start_r - end_r) { bDecreasing = true; } } + CFX_Matrix matrix = pObject2Bitmap->GetInverse(); for (int row = 0; row < height; row++) { uint32_t* dib_buf = (uint32_t*)(pBitmap->GetBuffer() + row * pitch); for (int column = 0; column < width; column++) { - CFX_PointF pos = matrix.Transform(CFX_PointF( - static_cast(column), static_cast(row))); - FX_FLOAT b = -2 * (((pos.x - start_x) * (end_x - start_x)) + - ((pos.y - start_y) * (end_y - start_y)) + - (start_r * (end_r - start_r))); - FX_FLOAT c = ((pos.x - start_x) * (pos.x - start_x)) + - ((pos.y - start_y) * (pos.y - start_y)) - - (start_r * start_r); - FX_FLOAT s; + CFX_PointF pos = matrix.Transform( + CFX_PointF(static_cast(column), static_cast(row))); + float b = -2 * (((pos.x - start_x) * (end_x - start_x)) + + ((pos.y - start_y) * (end_y - start_y)) + + (start_r * (end_r - start_r))); + float c = ((pos.x - start_x) * (pos.x - start_x)) + + ((pos.y - start_y) * (pos.y - start_y)) - (start_r * start_r); + float s; if (a == 0) { s = -c / b; } else { - FX_FLOAT b2_4ac = (b * b) - 4 * (a * c); + float b2_4ac = (b * b) - 4 * (a * c); if (b2_4ac < 0) { continue; } - FX_FLOAT root = FXSYS_sqrt(b2_4ac); - FX_FLOAT s1, s2; + float root = sqrt(b2_4ac); + float s1, s2; if (a > 0) { s1 = (-b - root) / (2 * a); s2 = (-b + root) / (2 * a); @@ -313,7 +318,7 @@ void DrawRadialShading(CFX_DIBitmap* pBitmap, } } -void DrawFuncShading(CFX_DIBitmap* pBitmap, +void DrawFuncShading(const RetainPtr& pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Dictionary* pDict, const std::vector>& funcs, @@ -321,7 +326,7 @@ void DrawFuncShading(CFX_DIBitmap* pBitmap, int alpha) { ASSERT(pBitmap->GetFormat() == FXDIB_Argb); CPDF_Array* pDomain = pDict->GetArrayFor("Domain"); - FX_FLOAT xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f; + float xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f; if (pDomain) { xmin = pDomain->GetNumberAt(0); xmax = pDomain->GetNumberAt(1); @@ -329,42 +334,38 @@ void DrawFuncShading(CFX_DIBitmap* pBitmap, ymax = pDomain->GetNumberAt(3); } CFX_Matrix mtDomain2Target = pDict->GetMatrixFor("Matrix"); - CFX_Matrix matrix; - matrix.SetReverse(*pObject2Bitmap); - - CFX_Matrix reverse_matrix; - reverse_matrix.SetReverse(mtDomain2Target); - matrix.Concat(reverse_matrix); + CFX_Matrix matrix = pObject2Bitmap->GetInverse(); + matrix.Concat(mtDomain2Target.GetInverse()); int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); int pitch = pBitmap->GetPitch(); uint32_t total_results = std::max(CountOutputs(funcs), pCS->CountComponents()); - CFX_FixedBufGrow result_array(total_results); - FX_FLOAT* pResults = result_array; - FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); + CFX_FixedBufGrow result_array(total_results); + float* pResults = result_array; + memset(pResults, 0, total_results * sizeof(float)); for (int row = 0; row < height; row++) { uint32_t* dib_buf = (uint32_t*)(pBitmap->GetBuffer() + row * pitch); for (int column = 0; column < width; column++) { - CFX_PointF pos = matrix.Transform(CFX_PointF( - static_cast(column), static_cast(row))); + CFX_PointF pos = matrix.Transform( + CFX_PointF(static_cast(column), static_cast(row))); if (pos.x < xmin || pos.x > xmax || pos.y < ymin || pos.y > ymax) continue; - FX_FLOAT input[] = {pos.x, pos.y}; + float input[] = {pos.x, pos.y}; int offset = 0; for (const auto& func : funcs) { if (func) { int nresults; - if (func->Call(input, 2, pResults + offset, nresults)) + if (func->Call(input, 2, pResults + offset, &nresults)) offset += nresults; } } - FX_FLOAT R = 0.0f; - FX_FLOAT G = 0.0f; - FX_FLOAT B = 0.0f; - pCS->GetRGB(pResults, R, G, B); + float R = 0.0f; + float G = 0.0f; + float B = 0.0f; + pCS->GetRGB(pResults, &R, &G, &B); dib_buf[column] = FXARGB_TODIB(FXARGB_MAKE( alpha, (int32_t)(R * 255), (int32_t)(G * 255), (int32_t)(B * 255))); } @@ -374,7 +375,7 @@ void DrawFuncShading(CFX_DIBitmap* pBitmap, bool GetScanlineIntersect(int y, const CFX_PointF& first, const CFX_PointF& second, - FX_FLOAT* x) { + float* x) { if (first.y == second.y) return false; @@ -388,11 +389,11 @@ bool GetScanlineIntersect(int y, return true; } -void DrawGouraud(CFX_DIBitmap* pBitmap, +void DrawGouraud(const RetainPtr& pBitmap, int alpha, CPDF_MeshVertex triangle[3]) { - FX_FLOAT min_y = triangle[0].position.y; - FX_FLOAT max_y = triangle[0].position.y; + float min_y = triangle[0].position.y; + float max_y = triangle[0].position.y; for (int i = 1; i < 3; i++) { min_y = std::min(min_y, triangle[i].position.y); max_y = std::max(max_y, triangle[i].position.y); @@ -400,18 +401,18 @@ void DrawGouraud(CFX_DIBitmap* pBitmap, if (min_y == max_y) return; - int min_yi = std::max(static_cast(FXSYS_floor(min_y)), 0); - int max_yi = static_cast(FXSYS_ceil(max_y)); + int min_yi = std::max(static_cast(floor(min_y)), 0); + int max_yi = static_cast(ceil(max_y)); if (max_yi >= pBitmap->GetHeight()) max_yi = pBitmap->GetHeight() - 1; for (int y = min_yi; y <= max_yi; y++) { int nIntersects = 0; - FX_FLOAT inter_x[3]; - FX_FLOAT r[3]; - FX_FLOAT g[3]; - FX_FLOAT b[3]; + float inter_x[3]; + float r[3]; + float g[3]; + float b[3]; for (int i = 0; i < 3; i++) { CPDF_MeshVertex& vertex1 = triangle[i]; CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3]; @@ -422,7 +423,7 @@ void DrawGouraud(CFX_DIBitmap* pBitmap, if (!bIntersect) continue; - FX_FLOAT y_dist = (y - position1.y) / (position2.y - position1.y); + float y_dist = (y - position1.y) / (position2.y - position1.y); r[nIntersects] = vertex1.r + ((vertex2.r - vertex1.r) * y_dist); g[nIntersects] = vertex1.g + ((vertex2.g - vertex1.g) * y_dist); b[nIntersects] = vertex1.b + ((vertex2.b - vertex1.b) * y_dist); @@ -433,13 +434,13 @@ void DrawGouraud(CFX_DIBitmap* pBitmap, int min_x, max_x, start_index, end_index; if (inter_x[0] < inter_x[1]) { - min_x = (int)FXSYS_floor(inter_x[0]); - max_x = (int)FXSYS_ceil(inter_x[1]); + min_x = (int)floor(inter_x[0]); + max_x = (int)ceil(inter_x[1]); start_index = 0; end_index = 1; } else { - min_x = (int)FXSYS_floor(inter_x[1]); - max_x = (int)FXSYS_ceil(inter_x[0]); + min_x = (int)floor(inter_x[1]); + max_x = (int)ceil(inter_x[0]); start_index = 1; end_index = 0; } @@ -451,12 +452,12 @@ void DrawGouraud(CFX_DIBitmap* pBitmap, uint8_t* dib_buf = pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4; - FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x); - FX_FLOAT g_unit = (g[end_index] - g[start_index]) / (max_x - min_x); - FX_FLOAT b_unit = (b[end_index] - b[start_index]) / (max_x - min_x); - FX_FLOAT R = r[start_index] + (start_x - min_x) * r_unit; - FX_FLOAT G = g[start_index] + (start_x - min_x) * g_unit; - FX_FLOAT B = b[start_index] + (start_x - min_x) * b_unit; + float r_unit = (r[end_index] - r[start_index]) / (max_x - min_x); + float g_unit = (g[end_index] - g[start_index]) / (max_x - min_x); + float b_unit = (b[end_index] - b[start_index]) / (max_x - min_x); + float R = r[start_index] + (start_x - min_x) * r_unit; + float G = g[start_index] + (start_x - min_x) * g_unit; + float B = b[start_index] + (start_x - min_x) * b_unit; for (int x = start_x; x < end_x; x++) { R += r_unit; G += g_unit; @@ -470,7 +471,7 @@ void DrawGouraud(CFX_DIBitmap* pBitmap, } void DrawFreeGouraudShading( - CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Stream* pShadingStream, const std::vector>& funcs, @@ -484,7 +485,7 @@ void DrawFreeGouraudShading( return; CPDF_MeshVertex triangle[3]; - FXSYS_memset(triangle, 0, sizeof(triangle)); + memset(triangle, 0, sizeof(triangle)); while (!stream.BitStream()->IsEOF()) { CPDF_MeshVertex vertex; @@ -511,7 +512,7 @@ void DrawFreeGouraudShading( } void DrawLatticeGouraudShading( - CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Stream* pShadingStream, const std::vector>& funcs, @@ -528,25 +529,24 @@ void DrawLatticeGouraudShading( if (!stream.Load()) return; - std::unique_ptr vertex( - FX_Alloc2D(CPDF_MeshVertex, row_verts, 2)); - if (!stream.ReadVertexRow(*pObject2Bitmap, row_verts, vertex.get())) + std::vector vertices[2]; + vertices[0] = stream.ReadVertexRow(*pObject2Bitmap, row_verts); + if (vertices[0].empty()) return; int last_index = 0; while (1) { - CPDF_MeshVertex* last_row = vertex.get() + last_index * row_verts; - CPDF_MeshVertex* this_row = vertex.get() + (1 - last_index) * row_verts; - if (!stream.ReadVertexRow(*pObject2Bitmap, row_verts, this_row)) + vertices[1 - last_index] = stream.ReadVertexRow(*pObject2Bitmap, row_verts); + if (vertices[1 - last_index].empty()) return; CPDF_MeshVertex triangle[3]; - for (int i = 1; i < row_verts; i++) { - triangle[0] = last_row[i]; - triangle[1] = this_row[i - 1]; - triangle[2] = last_row[i - 1]; + for (int i = 1; i < row_verts; ++i) { + triangle[0] = vertices[last_index][i]; + triangle[1] = vertices[1 - last_index][i - 1]; + triangle[2] = vertices[last_index][i - 1]; DrawGouraud(pBitmap, alpha, triangle); - triangle[2] = this_row[i]; + triangle[2] = vertices[1 - last_index][i]; DrawGouraud(pBitmap, alpha, triangle); } last_index = 1 - last_index; @@ -668,6 +668,17 @@ struct Coon_Bezier { float Distance() { return x.Distance() + y.Distance(); } }; +int Interpolate(int p1, int p2, int delta1, int delta2, bool* overflow) { + pdfium::base::CheckedNumeric p = p2; + p -= p1; + p *= delta1; + p /= delta2; + p += p1; + if (!p.IsValid()) + *overflow = true; + return p.ValueOrDefault(0); +} + int BiInterpolImpl(int c0, int c1, int c2, @@ -675,32 +686,35 @@ int BiInterpolImpl(int c0, int x, int y, int x_scale, - int y_scale) { - int x1 = c0 + (c3 - c0) * x / x_scale; - int x2 = c1 + (c2 - c1) * x / x_scale; - return x1 + (x2 - x1) * y / y_scale; + int y_scale, + bool* overflow) { + int x1 = Interpolate(c0, c3, x, x_scale, overflow); + int x2 = Interpolate(c1, c2, x, x_scale, overflow); + return Interpolate(x1, x2, y, y_scale, overflow); } struct Coon_Color { - Coon_Color() { FXSYS_memset(comp, 0, sizeof(int) * 3); } + Coon_Color() { memset(comp, 0, sizeof(int) * 3); } int comp[3]; - void BiInterpol(Coon_Color colors[4], + // Returns true if successful, false if overflow detected. + bool BiInterpol(Coon_Color colors[4], int x, int y, int x_scale, int y_scale) { + bool overflow = false; for (int i = 0; i < 3; i++) { comp[i] = BiInterpolImpl(colors[0].comp[i], colors[1].comp[i], colors[2].comp[i], colors[3].comp[i], x, y, - x_scale, y_scale); + x_scale, y_scale, &overflow); } + return !overflow; } int Distance(Coon_Color& o) { - return std::max({FXSYS_abs(comp[0] - o.comp[0]), - FXSYS_abs(comp[1] - o.comp[1]), - FXSYS_abs(comp[2] - o.comp[2])}); + return std::max({abs(comp[0] - o.comp[0]), abs(comp[1] - o.comp[1]), + abs(comp[2] - o.comp[2])}); } }; @@ -727,14 +741,23 @@ struct CPDF_PatchDrawer { int d_left = 0; int d_top = 0; int d_right = 0; - div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale); + if (!div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, + y_scale)) { + return; + } if (!bSmall) { - div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale, - y_scale); - div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale, - y_scale); - div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale, - y_scale); + if (!div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale, + y_scale)) { + return; + } + if (!div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale, + y_scale)) { + return; + } + if (!div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale, + y_scale)) { + return; + } d_bottom = div_colors[3].Distance(div_colors[0]); d_left = div_colors[1].Distance(div_colors[0]); d_top = div_colors[1].Distance(div_colors[2]); @@ -805,7 +828,7 @@ struct CPDF_PatchDrawer { void DrawCoonPatchMeshes( ShadingType type, - CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Stream* pShadingStream, const std::vector>& funcs, @@ -816,7 +839,7 @@ void DrawCoonPatchMeshes( ASSERT(type == kCoonsPatchMeshShading || type == kTensorProductPatchMeshShading); - CFX_FxgeDevice device; + CFX_DefaultRenderDevice device; device.Attach(pBitmap, false, nullptr, false); CPDF_MeshStream stream(type, funcs, pShadingStream, pCS); if (!stream.Load()) @@ -846,11 +869,11 @@ void DrawCoonPatchMeshes( for (i = 0; i < 4; i++) { tempCoords[i] = coords[(flag * 3 + i) % 12]; } - FXSYS_memcpy(coords, tempCoords, sizeof(tempCoords)); + memcpy(coords, tempCoords, sizeof(tempCoords)); Coon_Color tempColors[2]; tempColors[0] = patch.patch_colors[flag]; tempColors[1] = patch.patch_colors[(flag + 1) % 4]; - FXSYS_memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2); + memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2); } for (i = iStartPoint; i < point_count; i++) { if (!stream.CanReadCoords()) @@ -862,9 +885,9 @@ void DrawCoonPatchMeshes( if (!stream.CanReadColor()) break; - FX_FLOAT r; - FX_FLOAT g; - FX_FLOAT b; + float r; + float g; + float b; std::tie(r, g, b) = stream.ReadColor(); patch.patch_colors[i].comp[0] = (int32_t)(r * 255); @@ -872,8 +895,8 @@ void DrawCoonPatchMeshes( patch.patch_colors[i].comp[2] = (int32_t)(b * 255); } CFX_FloatRect bbox = CFX_FloatRect::GetBBox(coords, point_count); - if (bbox.right <= 0 || bbox.left >= (FX_FLOAT)pBitmap->GetWidth() || - bbox.top <= 0 || bbox.bottom >= (FX_FLOAT)pBitmap->GetHeight()) { + if (bbox.right <= 0 || bbox.left >= (float)pBitmap->GetWidth() || + bbox.top <= 0 || bbox.bottom >= (float)pBitmap->GetHeight()) { continue; } Coon_Bezier C1, C2, D1, D2; @@ -889,26 +912,25 @@ void DrawCoonPatchMeshes( } } -std::unique_ptr DrawPatternBitmap( - CPDF_Document* pDoc, - CPDF_PageRenderCache* pCache, - CPDF_TilingPattern* pPattern, - const CFX_Matrix* pObject2Device, - int width, - int height, - int flags) { - std::unique_ptr pBitmap(new CFX_DIBitmap); +RetainPtr DrawPatternBitmap(CPDF_Document* pDoc, + CPDF_PageRenderCache* pCache, + CPDF_TilingPattern* pPattern, + const CFX_Matrix* pObject2Device, + int width, + int height, + int flags) { + auto pBitmap = pdfium::MakeRetain(); if (!pBitmap->Create(width, height, pPattern->colored() ? FXDIB_Argb : FXDIB_8bppMask)) { return nullptr; } - CFX_FxgeDevice bitmap_device; - bitmap_device.Attach(pBitmap.get(), false, nullptr, false); + CFX_DefaultRenderDevice bitmap_device; + bitmap_device.Attach(pBitmap, false, nullptr, false); pBitmap->Clear(0); - CFX_FloatRect cell_bbox = pPattern->bbox(); - pPattern->pattern_to_form()->TransformRect(cell_bbox); - pObject2Device->TransformRect(cell_bbox); - CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height); + CFX_FloatRect cell_bbox = + pPattern->pattern_to_form()->TransformRect(pPattern->bbox()); + cell_bbox = pObject2Device->TransformRect(cell_bbox); + CFX_FloatRect bitmap_rect(0.0f, 0.0f, (float)width, (float)height); CFX_Matrix mtAdjust; mtAdjust.MatchRect(bitmap_rect, cell_bbox); @@ -916,15 +938,16 @@ std::unique_ptr DrawPatternBitmap( mtPattern2Bitmap.Concat(mtAdjust); CPDF_RenderOptions options; if (!pPattern->colored()) - options.m_ColorMode = RENDER_COLOR_ALPHA; + options.SetColorMode(CPDF_RenderOptions::kAlpha); flags |= RENDER_FORCE_HALFTONE; - options.m_Flags = flags; + options.SetFlags(flags); + CPDF_RenderContext context(pDoc, pCache); context.AppendLayer(pPattern->form(), &mtPattern2Bitmap); context.Render(&bitmap_device, &options, nullptr); #if defined _SKIA_SUPPORT_PATHS_ - bitmap_device.Flush(); + bitmap_device.Flush(true); pBitmap->UnPreMultiply(); #endif return pBitmap; @@ -940,6 +963,26 @@ bool IsAvailableMatrix(const CFX_Matrix& matrix) { return true; } +bool MissingFillColor(const CPDF_ColorState* pColorState) { + return !pColorState->HasRef() || pColorState->GetFillColor()->IsNull(); +} + +bool MissingStrokeColor(const CPDF_ColorState* pColorState) { + return !pColorState->HasRef() || pColorState->GetStrokeColor()->IsNull(); +} + +bool Type3CharMissingFillColor(const CPDF_Type3Char* pChar, + const CPDF_ColorState* pColorState) { + return pChar && (!pChar->colored() || + (pChar->colored() && MissingFillColor(pColorState))); +} + +bool Type3CharMissingStrokeColor(const CPDF_Type3Char* pChar, + const CPDF_ColorState* pColorState) { + return pChar && (!pChar->colored() || + (pChar->colored() && MissingStrokeColor(pColorState))); +} + } // namespace // static @@ -954,7 +997,7 @@ CPDF_RenderStatus::CPDF_RenderStatus() m_pCurObj(nullptr), m_pStopObj(nullptr), m_bPrint(false), - m_Transparency(0), + m_iTransparency(0), m_bDropObjects(false), m_bStdCS(false), m_GroupFamily(0), @@ -1018,7 +1061,7 @@ bool CPDF_RenderStatus::Initialize(CPDF_RenderContext* pContext, m_InitialStates.DefaultStates(); } m_pImageRenderer.reset(); - m_Transparency = transparency; + m_iTransparency = transparency; return true; } @@ -1028,11 +1071,8 @@ void CPDF_RenderStatus::RenderObjectList( #if defined _SKIA_SUPPORT_ DebugVerifyDeviceIsPreMultiplied(); #endif - CFX_FloatRect clip_rect(m_pDevice->GetClipBox()); - CFX_Matrix device2object; - device2object.SetReverse(*pObj2Device); - device2object.TransformRect(clip_rect); - + CFX_FloatRect clip_rect = pObj2Device->GetInverse().TransformRect( + CFX_FloatRect(m_pDevice->GetClipBox())); for (const auto& pCurObj : *pObjectHolder->GetPageObjectList()) { if (pCurObj.get() == m_pStopObj) { m_bStopped = true; @@ -1061,13 +1101,13 @@ void CPDF_RenderStatus::RenderSingleObject(CPDF_PageObject* pObj, #if defined _SKIA_SUPPORT_ DebugVerifyDeviceIsPreMultiplied(); #endif - CFX_AutoRestorer restorer(&s_CurrentRecursionDepth); + AutoRestorer restorer(&s_CurrentRecursionDepth); if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) { return; } m_pCurObj = pObj; - if (m_Options.m_pOCContext && pObj->m_ContentMark) { - if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) { + if (m_Options.GetOCContext() && pObj->m_ContentMark.HasRef()) { + if (!m_Options.GetOCContext()->CheckObjectVisible(pObj)) { return; } } @@ -1083,7 +1123,7 @@ void CPDF_RenderStatus::RenderSingleObject(CPDF_PageObject* pObj, bool CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { if (m_pImageRenderer) { if (m_pImageRenderer->Continue(pPause)) return true; @@ -1095,8 +1135,8 @@ bool CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj, } m_pCurObj = pObj; - if (m_Options.m_pOCContext && pObj->m_ContentMark && - !m_Options.m_pOCContext->CheckObjectVisible(pObj)) { + if (m_Options.GetOCContext() && pObj->m_ContentMark.HasRef() && + !m_Options.GetOCContext()->CheckObjectVisible(pObj)) { return false; } @@ -1104,20 +1144,20 @@ bool CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj, if (ProcessTransparency(pObj, pObj2Device)) return false; - if (pObj->IsImage()) { - m_pImageRenderer = pdfium::MakeUnique(); - if (!m_pImageRenderer->Start(this, pObj, pObj2Device, false, - FXDIB_BLEND_NORMAL)) { - if (!m_pImageRenderer->GetResult()) - DrawObjWithBackground(pObj, pObj2Device); - m_pImageRenderer.reset(); - return false; - } - return ContinueSingleObject(pObj, pObj2Device, pPause); + if (!pObj->IsImage()) { + ProcessObjectNoClip(pObj, pObj2Device); + return false; } - ProcessObjectNoClip(pObj, pObj2Device); - return false; + m_pImageRenderer = pdfium::MakeUnique(); + if (!m_pImageRenderer->Start(this, pObj->AsImage(), pObj2Device, false, + FXDIB_BLEND_NORMAL)) { + if (!m_pImageRenderer->GetResult()) + DrawObjWithBackground(pObj, pObj2Device); + m_pImageRenderer.reset(); + return false; + } + return ContinueSingleObject(pObj, pObj2Device, pPause); } bool CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, @@ -1128,15 +1168,13 @@ bool CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, FX_RECT rtClip = m_pDevice->GetClipBox(); if (!bLogical) { CFX_Matrix dCTM = m_pDevice->GetCTM(); - FX_FLOAT a = FXSYS_fabs(dCTM.a); - FX_FLOAT d = FXSYS_fabs(dCTM.d); + float a = fabs(dCTM.a); + float d = fabs(dCTM.d); if (a != 1.0f || d != 1.0f) { - rect.right = rect.left + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Width() * a); - rect.bottom = rect.top + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Height() * d); - rtClip.right = - rtClip.left + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a); - rtClip.bottom = - rtClip.top + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d); + rect.right = rect.left + (int32_t)ceil((float)rect.Width() * a); + rect.bottom = rect.top + (int32_t)ceil((float)rect.Height() * d); + rtClip.right = rtClip.left + (int32_t)ceil((float)rtClip.Width() * a); + rtClip.bottom = rtClip.top + (int32_t)ceil((float)rtClip.Height() * d); } } rect.Intersect(rtClip); @@ -1194,8 +1232,8 @@ bool CPDF_RenderStatus::DrawObjWithBlend(CPDF_PageObject* pObj, void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix& matrix) const { CFX_Matrix dCTM = m_pDevice->GetCTM(); - matrix.a *= FXSYS_fabs(dCTM.a); - matrix.d *= FXSYS_fabs(dCTM.d); + matrix.a *= fabs(dCTM.a); + matrix.d *= fabs(dCTM.d); } void CPDF_RenderStatus::DrawObjWithBackground(CPDF_PageObject* pObj, @@ -1210,22 +1248,23 @@ void CPDF_RenderStatus::DrawObjWithBackground(CPDF_PageObject* pObj, res = 0; } CPDF_ScaledRenderBuffer buffer; - if (!buffer.Initialize(m_pContext, m_pDevice, rect, pObj, &m_Options, res)) { + if (!buffer.Initialize(m_pContext.Get(), m_pDevice, rect, pObj, &m_Options, + res)) { return; } CFX_Matrix matrix = *pObj2Device; matrix.Concat(*buffer.GetMatrix()); GetScaledMatrix(matrix); CPDF_Dictionary* pFormResource = nullptr; - if (pObj->IsForm()) { - const CPDF_FormObject* pFormObj = pObj->AsForm(); - if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { - pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictFor("Resources"); - } + const CPDF_FormObject* pFormObj = pObj->AsForm(); + if (pFormObj) { + const auto& pFormDict = pFormObj->form()->m_pFormDict; + if (pFormDict) + pFormResource = pFormDict->GetDictFor("Resources"); } CPDF_RenderStatus status; - status.Initialize(m_pContext, buffer.GetDevice(), buffer.GetMatrix(), nullptr, - nullptr, nullptr, &m_Options, m_Transparency, + status.Initialize(m_pContext.Get(), buffer.GetDevice(), buffer.GetMatrix(), + nullptr, nullptr, nullptr, &m_Options, m_iTransparency, m_bDropObjects, pFormResource); status.RenderSingleObject(pObj, &matrix); buffer.OutputToDevice(); @@ -1236,26 +1275,26 @@ bool CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj, #if defined _SKIA_SUPPORT_ DebugVerifyDeviceIsPreMultiplied(); #endif - CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDictFor("OC"); - if (pOC && m_Options.m_pOCContext && - !m_Options.m_pOCContext->CheckOCGVisible(pOC)) { + CPDF_Dictionary* pOC = pFormObj->form()->m_pFormDict->GetDictFor("OC"); + if (pOC && m_Options.GetOCContext() && + !m_Options.GetOCContext()->CheckOCGVisible(pOC)) { return true; } - CFX_Matrix matrix = pFormObj->m_FormMatrix; + CFX_Matrix matrix = pFormObj->form_matrix(); matrix.Concat(*pObj2Device); - CPDF_Dictionary* pResources = nullptr; - if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { - pResources = pFormObj->m_pForm->m_pFormDict->GetDictFor("Resources"); - } + const auto& pFormDict = pFormObj->form()->m_pFormDict; + CPDF_Dictionary* pResources = + pFormDict ? pFormDict->GetDictFor("Resources") : nullptr; CPDF_RenderStatus status; - status.Initialize(m_pContext, m_pDevice, nullptr, m_pStopObj, this, pFormObj, - &m_Options, m_Transparency, m_bDropObjects, pResources, - false); + status.Initialize(m_pContext.Get(), m_pDevice, nullptr, m_pStopObj, this, + pFormObj, &m_Options, m_iTransparency, m_bDropObjects, + pResources, false); status.m_curBlend = m_curBlend; - m_pDevice->SaveState(); - status.RenderObjectList(pFormObj->m_pForm.get(), &matrix); - m_bStopped = status.m_bStopped; - m_pDevice->RestoreState(false); + { + CFX_RenderDevice::StateRestorer restorer(m_pDevice); + status.RenderObjectList(pFormObj->form(), &matrix); + m_bStopped = status.m_bStopped; + } #if defined _SKIA_SUPPORT_ DebugVerifyDeviceIsPreMultiplied(); #endif @@ -1277,11 +1316,11 @@ bool CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj, if (!IsAvailableMatrix(path_matrix)) return true; - if (FillType && (m_Options.m_Flags & RENDER_RECT_AA)) + if (FillType && (m_Options.HasFlag(RENDER_RECT_AA))) FillType |= FXFILL_RECT_AA; - if (m_Options.m_Flags & RENDER_FILL_FULLCOVER) + if (m_Options.HasFlag(RENDER_FILL_FULLCOVER)) FillType |= FXFILL_FULLCOVER; - if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) + if (m_Options.HasFlag(RENDER_NOPATHSMOOTH)) FillType |= FXFILL_NOPATHSMOOTH; if (bStroke) FillType |= FX_FILL_STROKE; @@ -1294,14 +1333,15 @@ bool CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj, FillType |= FX_FILL_TEXT_MODE; CFX_GraphState graphState = pPathObj->m_GraphState; - if (m_Options.m_Flags & RENDER_THINLINE) + if (m_Options.HasFlag(RENDER_THINLINE)) graphState.SetLineWidth(0); return m_pDevice->DrawPathWithBlend( pPathObj->m_Path.GetObject(), &path_matrix, graphState.GetObject(), fill_argb, stroke_argb, FillType, m_curBlend); } -CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const { +RetainPtr CPDF_RenderStatus::GetTransferFunc( + CPDF_Object* pObj) const { ASSERT(pObj); CPDF_DocRenderData* pDocCache = m_pContext->GetDocument()->GetRenderData(); return pDocCache ? pDocCache->GetTransferFunc(pObj) : nullptr; @@ -1310,13 +1350,10 @@ CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const { FX_ARGB CPDF_RenderStatus::GetFillArgb(CPDF_PageObject* pObj, bool bType3) const { const CPDF_ColorState* pColorState = &pObj->m_ColorState; - if (m_pType3Char && !bType3 && - (!m_pType3Char->m_bColored || - (m_pType3Char->m_bColored && - (!*pColorState || pColorState->GetFillColor()->IsNull())))) { + if (!bType3 && Type3CharMissingFillColor(m_pType3Char.Get(), pColorState)) return m_T3FillColor; - } - if (!*pColorState || pColorState->GetFillColor()->IsNull()) + + if (MissingFillColor(pColorState)) pColorState = &m_InitialStates.m_ColorState; FX_COLORREF rgb = pColorState->GetFillRGB(); @@ -1338,13 +1375,10 @@ FX_ARGB CPDF_RenderStatus::GetFillArgb(CPDF_PageObject* pObj, FX_ARGB CPDF_RenderStatus::GetStrokeArgb(CPDF_PageObject* pObj) const { const CPDF_ColorState* pColorState = &pObj->m_ColorState; - if (m_pType3Char && - (!m_pType3Char->m_bColored || - (m_pType3Char->m_bColored && - (!*pColorState || pColorState->GetStrokeColor()->IsNull())))) { + if (Type3CharMissingStrokeColor(m_pType3Char.Get(), pColorState)) return m_T3FillColor; - } - if (!*pColorState || pColorState->GetStrokeColor()->IsNull()) + + if (MissingStrokeColor(pColorState)) pColorState = &m_InitialStates.m_ColorState; FX_COLORREF rgb = pColorState->GetStrokeRGB(); @@ -1364,10 +1398,10 @@ FX_ARGB CPDF_RenderStatus::GetStrokeArgb(CPDF_PageObject* pObj) const { return m_Options.TranslateColor(ArgbEncode(alpha, rgb)); } -void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, +void CPDF_RenderStatus::ProcessClipPath(const CPDF_ClipPath& ClipPath, const CFX_Matrix* pObj2Device) { - if (!ClipPath) { - if (m_LastClipPath) { + if (!ClipPath.HasRef()) { + if (m_LastClipPath.HasRef()) { m_pDevice->RestoreState(true); m_LastClipPath.SetNull(); } @@ -1378,8 +1412,7 @@ void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, m_LastClipPath = ClipPath; m_pDevice->RestoreState(true); - int nClipPath = ClipPath.GetPathCount(); - for (int i = 0; i < nClipPath; ++i) { + for (size_t i = 0; i < ClipPath.GetPathCount(); ++i) { const CFX_PathData* pPathData = ClipPath.GetPath(i).GetObject(); if (!pPathData) continue; @@ -1387,15 +1420,14 @@ void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, if (pPathData->GetPoints().empty()) { CFX_PathData EmptyPath; EmptyPath.AppendRect(-1, -1, 0, 0); - int fill_mode = FXFILL_WINDING; - m_pDevice->SetClip_PathFill(&EmptyPath, nullptr, fill_mode); + m_pDevice->SetClip_PathFill(&EmptyPath, nullptr, FXFILL_WINDING); } else { - int ClipType = ClipPath.GetClipType(i); - m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType); + m_pDevice->SetClip_PathFill(pPathData, pObj2Device, + ClipPath.GetClipType(i)); } } - int textcount = ClipPath.GetTextCount(); - if (textcount == 0) + + if (ClipPath.GetTextCount() == 0) return; if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY && @@ -1404,7 +1436,7 @@ void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, } std::unique_ptr pTextClippingPath; - for (int i = 0; i < textcount; ++i) { + for (size_t i = 0; i < ClipPath.GetTextCount(); ++i) { CPDF_TextObject* pText = ClipPath.GetText(i); if (pText) { if (!pTextClippingPath) @@ -1417,7 +1449,7 @@ void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, continue; int fill_mode = FXFILL_WINDING; - if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) + if (m_Options.HasFlag(RENDER_NOTEXTSMOOTH)) fill_mode |= FXFILL_NOPATHSMOOTH; m_pDevice->SetClip_PathFill(pTextClippingPath.get(), nullptr, fill_mode); pTextClippingPath.reset(); @@ -1431,13 +1463,13 @@ bool CPDF_RenderStatus::SelectClipPath(const CPDF_PathObject* pPathObj, path_matrix.Concat(*pObj2Device); if (bStroke) { CFX_GraphState graphState = pPathObj->m_GraphState; - if (m_Options.m_Flags & RENDER_THINLINE) + if (m_Options.HasFlag(RENDER_THINLINE)) graphState.SetLineWidth(0); return m_pDevice->SetClip_PathStroke(pPathObj->m_Path.GetObject(), &path_matrix, graphState.GetObject()); } int fill_mode = pPathObj->m_FillType; - if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) { + if (m_Options.HasFlag(RENDER_NOPATHSMOOTH)) { fill_mode |= FXFILL_NOPATHSMOOTH; } return m_pDevice->SetClip_PathFill(pPathObj->m_Path.GetObject(), &path_matrix, @@ -1462,34 +1494,36 @@ bool CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj, } } CPDF_Dictionary* pFormResource = nullptr; - FX_FLOAT group_alpha = 1.0f; - int Transparency = m_Transparency; + float group_alpha = 1.0f; + int iTransparency = m_iTransparency; bool bGroupTransparent = false; - if (pPageObj->IsForm()) { - const CPDF_FormObject* pFormObj = pPageObj->AsForm(); + const CPDF_FormObject* pFormObj = pPageObj->AsForm(); + if (pFormObj) { group_alpha = pFormObj->m_GeneralState.GetFillAlpha(); - Transparency = pFormObj->m_pForm->m_Transparency; - bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED); - if (pFormObj->m_pForm->m_pFormDict) { - pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictFor("Resources"); - } + iTransparency = pFormObj->form()->m_iTransparency; + bGroupTransparent = !!(iTransparency & PDFTRANS_ISOLATED); + const auto& pFormDict = pFormObj->form()->m_pFormDict; + if (pFormDict) + pFormResource = pFormDict->GetDictFor("Resources"); } bool bTextClip = - (pPageObj->m_ClipPath && pPageObj->m_ClipPath.GetTextCount() && + (pPageObj->m_ClipPath.HasRef() && + pPageObj->m_ClipPath.GetTextCount() > 0 && m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)); - if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->IsImage() && + if ((m_Options.HasFlag(RENDER_OVERPRINT)) && pPageObj->IsImage() && pPageObj->m_GeneralState.GetFillOP() && pPageObj->m_GeneralState.GetStrokeOP()) { CPDF_Document* pDocument = nullptr; CPDF_Page* pPage = nullptr; if (m_pContext->GetPageCache()) { pPage = m_pContext->GetPageCache()->GetPage(); - pDocument = pPage->m_pDocument; + pDocument = pPage->m_pDocument.Get(); } else { pDocument = pPageObj->AsImage()->GetImage()->GetDocument(); } - CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr; + CPDF_Dictionary* pPageResources = + pPage ? pPage->m_pPageResources.Get() : nullptr; CPDF_Object* pCSObj = pPageObj->AsImage() ->GetImage() ->GetStream() @@ -1510,11 +1544,11 @@ bool CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj, !bTextClip && !bGroupTransparent) { return false; } - bool isolated = !!(Transparency & PDFTRANS_ISOLATED); + bool isolated = !!(iTransparency & PDFTRANS_ISOLATED); if (m_bPrint) { bool bRet = false; int rendCaps = m_pDevice->GetRenderCaps(); - if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) && + if (!((iTransparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) && (rendCaps & FXRC_BLEND_MODE)) { int oldBlend = m_curBlend; m_curBlend = blend_type; @@ -1528,113 +1562,116 @@ bool CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj, } FX_RECT rect = pPageObj->GetBBox(pObj2Device); rect.Intersect(m_pDevice->GetClipBox()); - if (rect.IsEmpty()) { + if (rect.IsEmpty()) return true; - } + CFX_Matrix deviceCTM = m_pDevice->GetCTM(); - FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a); - FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d); - int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX); - int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY); - CFX_FxgeDevice bitmap_device; - std::unique_ptr oriDevice; + float scaleX = fabs(deviceCTM.a); + float scaleY = fabs(deviceCTM.d); + int width = FXSYS_round((float)rect.Width() * scaleX); + int height = FXSYS_round((float)rect.Height() * scaleY); + CFX_DefaultRenderDevice bitmap_device; + RetainPtr oriDevice; if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { - oriDevice = pdfium::MakeUnique(); - if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height)) + oriDevice = pdfium::MakeRetain(); + if (!m_pDevice->CreateCompatibleBitmap(oriDevice, width, height)) return true; - m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top); + m_pDevice->GetDIBits(oriDevice, rect.left, rect.top); } - if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice.get())) + if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice)) return true; - CFX_DIBitmap* bitmap = bitmap_device.GetBitmap(); + + RetainPtr bitmap = bitmap_device.GetBitmap(); bitmap->Clear(0); + CFX_Matrix new_matrix = *pObj2Device; new_matrix.Translate(-rect.left, -rect.top); new_matrix.Scale(scaleX, scaleY); - std::unique_ptr pTextMask; + + RetainPtr pTextMask; if (bTextClip) { - pTextMask = pdfium::MakeUnique(); + pTextMask = pdfium::MakeRetain(); if (!pTextMask->Create(width, height, FXDIB_8bppMask)) return true; pTextMask->Clear(0); - CFX_FxgeDevice text_device; - text_device.Attach(pTextMask.get(), false, nullptr, false); - for (uint32_t i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) { + CFX_DefaultRenderDevice text_device; + text_device.Attach(pTextMask, false, nullptr, false); + for (size_t i = 0; i < pPageObj->m_ClipPath.GetTextCount(); ++i) { CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i); if (!textobj) break; CFX_Matrix text_matrix = textobj->GetTextMatrix(); CPDF_TextRenderer::DrawTextPath( - &text_device, textobj->m_CharCodes, textobj->m_CharPos, + &text_device, textobj->GetCharCodes(), textobj->GetCharPositions(), textobj->m_TextState.GetFont(), textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix, textobj->m_GraphState.GetObject(), (FX_ARGB)-1, 0, nullptr, 0); } } CPDF_RenderStatus bitmap_render; - bitmap_render.Initialize(m_pContext, &bitmap_device, nullptr, m_pStopObj, - nullptr, nullptr, &m_Options, 0, m_bDropObjects, - pFormResource, true); + bitmap_render.Initialize(m_pContext.Get(), &bitmap_device, nullptr, + m_pStopObj, nullptr, nullptr, &m_Options, 0, + m_bDropObjects, pFormResource, true); bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix); #if defined _SKIA_SUPPORT_PATHS_ - bitmap_device.Flush(); + bitmap_device.Flush(true); bitmap->UnPreMultiply(); #endif m_bStopped = bitmap_render.m_bStopped; if (pSMaskDict) { CFX_Matrix smask_matrix = *pPageObj->m_GeneralState.GetSMaskMatrix(); smask_matrix.Concat(*pObj2Device); - std::unique_ptr pSMaskSource = + RetainPtr pSMaskSource = LoadSMask(pSMaskDict, &rect, &smask_matrix); if (pSMaskSource) - bitmap->MultiplyAlpha(pSMaskSource.get()); + bitmap->MultiplyAlpha(pSMaskSource); } if (pTextMask) { - bitmap->MultiplyAlpha(pTextMask.get()); - pTextMask.reset(); + bitmap->MultiplyAlpha(pTextMask); + pTextMask.Reset(); } int32_t blitAlpha = 255; - if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) { + if (iTransparency & PDFTRANS_GROUP && group_alpha != 1.0f) { blitAlpha = (int32_t)(group_alpha * 255); #ifndef _SKIA_SUPPORT_ bitmap->MultiplyAlpha(blitAlpha); blitAlpha = 255; #endif } - Transparency = m_Transparency; + iTransparency = m_iTransparency; if (pPageObj->IsForm()) { - Transparency |= PDFTRANS_GROUP; + iTransparency |= PDFTRANS_GROUP; } CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type, - Transparency); + iTransparency); #if defined _SKIA_SUPPORT_ DebugVerifyDeviceIsPreMultiplied(); #endif return true; } -std::unique_ptr CPDF_RenderStatus::GetBackdrop( +RetainPtr CPDF_RenderStatus::GetBackdrop( const CPDF_PageObject* pObj, const FX_RECT& rect, - int& left, - int& top, - bool bBackAlphaRequired) { + bool bBackAlphaRequired, + int* left, + int* top) { FX_RECT bbox = rect; bbox.Intersect(m_pDevice->GetClipBox()); - left = bbox.left; - top = bbox.top; + *left = bbox.left; + *top = bbox.top; CFX_Matrix deviceCTM = m_pDevice->GetCTM(); - FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a); - FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d); + float scaleX = fabs(deviceCTM.a); + float scaleY = fabs(deviceCTM.d); int width = FXSYS_round(bbox.Width() * scaleX); int height = FXSYS_round(bbox.Height() * scaleY); - auto pBackdrop = pdfium::MakeUnique(); + auto pBackdrop = pdfium::MakeRetain(); if (bBackAlphaRequired && !m_bDropObjects) pBackdrop->Create(width, height, FXDIB_Argb); else - m_pDevice->CreateCompatibleBitmap(pBackdrop.get(), width, height); + m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height); if (!pBackdrop->GetBuffer()) return nullptr; @@ -1646,27 +1683,27 @@ std::unique_ptr CPDF_RenderStatus::GetBackdrop( bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS); if (!bNeedDraw) { - m_pDevice->GetDIBits(pBackdrop.get(), left, top); + m_pDevice->GetDIBits(pBackdrop, *left, *top); return pBackdrop; } - CFX_Matrix FinalMatrix = m_DeviceMatrix; - FinalMatrix.Translate(-left, -top); + FinalMatrix.Translate(-*left, -*top); FinalMatrix.Scale(scaleX, scaleY); pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff); - CFX_FxgeDevice device; - device.Attach(pBackdrop.get(), false, nullptr, false); + + CFX_DefaultRenderDevice device; + device.Attach(pBackdrop, false, nullptr, false); m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix); return pBackdrop; } -CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates( +std::unique_ptr CPDF_RenderStatus::CloneObjStates( const CPDF_GraphicStates* pSrcStates, bool bStroke) { if (!pSrcStates) return nullptr; - CPDF_GraphicStates* pStates = new CPDF_GraphicStates; + auto pStates = pdfium::MakeUnique(); pStates->CopyStates(*pSrcStates); const CPDF_Color* pObjColor = bStroke ? pSrcStates->m_ColorState.GetStrokeColor() @@ -1689,7 +1726,7 @@ void CPDF_RenderStatus::DebugVerifyDeviceIsPreMultiplied() const { bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj, const CFX_Matrix* pObj2Device, CFX_PathData* pClippingPath) { - if (textobj->m_CharCodes.empty()) + if (textobj->GetCharCodes().empty()) return true; const TextRenderingMode text_render_mode = textobj->m_TextState.GetTextMode(); @@ -1727,7 +1764,7 @@ bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj, case TextRenderingMode::MODE_INVISIBLE: // Already handled above, but the compiler is not smart enough to // realize it. Fall through. - ASSERT(false); + NOTREACHED(); case TextRenderingMode::MODE_CLIP: return true; } @@ -1753,7 +1790,7 @@ bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj, if (!IsAvailableMatrix(text_matrix)) return true; - FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); + float font_size = textobj->m_TextState.GetFontSize(); if (bPattern) { DrawTextPathWithPattern(textobj, pObj2Device, pFont, font_size, &text_matrix, bFill, bStroke); @@ -1763,7 +1800,7 @@ bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj, const CFX_Matrix* pDeviceMatrix = pObj2Device; CFX_Matrix device_matrix; if (bStroke) { - const FX_FLOAT* pCTM = textobj->m_TextState.GetCTM(); + const float* pCTM = textobj->m_TextState.GetCTM(); if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) { CFX_Matrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0); text_matrix.ConcatInverse(ctm); @@ -1779,25 +1816,28 @@ bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj, } if (textobj->m_GeneralState.GetStrokeAdjust()) flag |= FX_STROKE_ADJUST; - if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) + if (m_Options.HasFlag(RENDER_NOTEXTSMOOTH)) flag |= FXFILL_NOPATHSMOOTH; return CPDF_TextRenderer::DrawTextPath( - m_pDevice, textobj->m_CharCodes, textobj->m_CharPos, pFont, font_size, - &text_matrix, pDeviceMatrix, textobj->m_GraphState.GetObject(), - fill_argb, stroke_argb, pClippingPath, flag); + m_pDevice, textobj->GetCharCodes(), textobj->GetCharPositions(), pFont, + font_size, &text_matrix, pDeviceMatrix, + textobj->m_GraphState.GetObject(), fill_argb, stroke_argb, + pClippingPath, flag); } text_matrix.Concat(*pObj2Device); - return CPDF_TextRenderer::DrawNormalText(m_pDevice, textobj->m_CharCodes, - textobj->m_CharPos, pFont, font_size, - &text_matrix, fill_argb, &m_Options); + return CPDF_TextRenderer::DrawNormalText( + m_pDevice, textobj->GetCharCodes(), textobj->GetCharPositions(), pFont, + font_size, &text_matrix, fill_argb, &m_Options); } -CPDF_Type3Cache* CPDF_RenderStatus::GetCachedType3(CPDF_Type3Font* pFont) { - if (!pFont->m_pDocument) { +RetainPtr CPDF_RenderStatus::GetCachedType3( + CPDF_Type3Font* pFont) { + CPDF_Document* pDoc = pFont->GetDocument(); + if (!pDoc) return nullptr; - } - pFont->m_pDocument->GetPageData()->GetFont(pFont->GetFontDict()); - return pFont->m_pDocument->GetRenderData()->GetCachedType3(pFont); + + pDoc->GetPageData()->GetFont(pFont->GetFontDict()); + return pDoc->GetRenderData()->GetCachedType3(pFont); } // TODO(npm): Font fallback for type 3 fonts? (Completely separate code!!) @@ -1808,25 +1848,24 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, return true; CFX_Matrix dCTM = m_pDevice->GetCTM(); - FX_FLOAT sa = FXSYS_fabs(dCTM.a); - FX_FLOAT sd = FXSYS_fabs(dCTM.d); + float sa = fabs(dCTM.a); + float sd = fabs(dCTM.d); CFX_Matrix text_matrix = textobj->GetTextMatrix(); CFX_Matrix char_matrix = pType3Font->GetFontMatrix(); - FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); + float font_size = textobj->m_TextState.GetFontSize(); char_matrix.Scale(font_size, font_size); FX_ARGB fill_argb = GetFillArgb(textobj, true); int fill_alpha = FXARGB_A(fill_argb); int device_class = m_pDevice->GetDeviceClass(); std::vector glyphs; if (device_class == FXDC_DISPLAY) - glyphs.resize(textobj->m_CharCodes.size()); + glyphs.resize(textobj->GetCharCodes().size()); else if (fill_alpha < 255) return false; CPDF_RefType3Cache refTypeCache(pType3Font); - for (int iChar = 0; iChar < pdfium::CollectionSize(textobj->m_CharCodes); - iChar++) { - uint32_t charcode = textobj->m_CharCodes[iChar]; + for (size_t iChar = 0; iChar < textobj->GetCharCodes().size(); ++iChar) { + uint32_t charcode = textobj->GetCharCodes()[iChar]; if (charcode == static_cast(-1)) continue; @@ -1835,49 +1874,53 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, continue; CFX_Matrix matrix = char_matrix; - matrix.e += iChar ? textobj->m_CharPos[iChar - 1] : 0; + matrix.e += iChar > 0 ? textobj->GetCharPositions()[iChar - 1] : 0; matrix.Concat(text_matrix); matrix.Concat(*pObj2Device); - if (!pType3Char->LoadBitmap(m_pContext)) { + if (!pType3Char->LoadBitmap(m_pContext.Get())) { if (!glyphs.empty()) { - for (int i = 0; i < iChar; i++) { + for (size_t i = 0; i < iChar; ++i) { const FXTEXT_GLYPHPOS& glyph = glyphs[i]; if (!glyph.m_pGlyph) continue; - m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap, + m_pDevice->SetBitMask(glyph.m_pGlyph->m_pBitmap, glyph.m_Origin.x + glyph.m_pGlyph->m_Left, glyph.m_Origin.y - glyph.m_pGlyph->m_Top, fill_argb); } glyphs.clear(); } - CPDF_GraphicStates* pStates = CloneObjStates(textobj, false); - CPDF_RenderOptions Options = m_Options; - Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA; - Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE; + + std::unique_ptr pStates = + CloneObjStates(textobj, false); + CPDF_RenderOptions options = m_Options; + uint32_t option_flags = options.GetFlags(); + option_flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA; + option_flags &= ~RENDER_FORCE_DOWNSAMPLE; + options.SetFlags(option_flags); + CPDF_Dictionary* pFormResource = nullptr; - if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) { + if (pType3Char->form() && pType3Char->form()->m_pFormDict) { pFormResource = - pType3Char->m_pForm->m_pFormDict->GetDictFor("Resources"); + pType3Char->form()->m_pFormDict->GetDictFor("Resources"); } if (fill_alpha == 255) { CPDF_RenderStatus status; - status.Initialize(m_pContext, m_pDevice, nullptr, nullptr, this, - pStates, &Options, - pType3Char->m_pForm->m_Transparency, m_bDropObjects, + status.Initialize(m_pContext.Get(), m_pDevice, nullptr, nullptr, this, + pStates.get(), &options, + pType3Char->form()->m_iTransparency, m_bDropObjects, pFormResource, false, pType3Char, fill_argb); status.m_Type3FontCache = m_Type3FontCache; status.m_Type3FontCache.push_back(pType3Font); - m_pDevice->SaveState(); - status.RenderObjectList(pType3Char->m_pForm.get(), &matrix); - m_pDevice->RestoreState(false); - } else { - CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox(); - matrix.TransformRect(rect_f); - FX_RECT rect = rect_f.GetOuterRect(); - CFX_FxgeDevice bitmap_device; + CFX_RenderDevice::StateRestorer restorer(m_pDevice); + status.RenderObjectList(pType3Char->form(), &matrix); + } else { + FX_RECT rect = + matrix.TransformRect(pType3Char->form()->CalcBoundingBox()) + .GetOuterRect(); + CFX_DefaultRenderDevice bitmap_device; if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb, nullptr)) { @@ -1885,21 +1928,20 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, } bitmap_device.GetBitmap()->Clear(0); CPDF_RenderStatus status; - status.Initialize(m_pContext, &bitmap_device, nullptr, nullptr, this, - pStates, &Options, - pType3Char->m_pForm->m_Transparency, m_bDropObjects, + status.Initialize(m_pContext.Get(), &bitmap_device, nullptr, nullptr, + this, pStates.get(), &options, + pType3Char->form()->m_iTransparency, m_bDropObjects, pFormResource, false, pType3Char, fill_argb); status.m_Type3FontCache = m_Type3FontCache; status.m_Type3FontCache.push_back(pType3Font); matrix.Translate(-rect.left, -rect.top); matrix.Scale(sa, sd); - status.RenderObjectList(pType3Char->m_pForm.get(), &matrix); + status.RenderObjectList(pType3Char->form(), &matrix); m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top); } - delete pStates; - } else if (pType3Char->m_pBitmap) { + } else if (pType3Char->GetBitmap()) { if (device_class == FXDC_DISPLAY) { - CPDF_Type3Cache* pCache = GetCachedType3(pType3Font); + RetainPtr pCache = GetCachedType3(pType3Font); refTypeCache.m_dwCount++; CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd); if (!pBitmap) @@ -1907,17 +1949,17 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, CFX_Point origin(FXSYS_round(matrix.e), FXSYS_round(matrix.f)); if (glyphs.empty()) { - m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin.x + pBitmap->m_Left, + m_pDevice->SetBitMask(pBitmap->m_pBitmap, origin.x + pBitmap->m_Left, origin.y - pBitmap->m_Top, fill_argb); } else { glyphs[iChar].m_pGlyph = pBitmap; glyphs[iChar].m_Origin = origin; } } else { - CFX_Matrix image_matrix = pType3Char->m_ImageMatrix; + CFX_Matrix image_matrix = pType3Char->matrix(); image_matrix.Concat(matrix); CPDF_ImageRenderer renderer; - if (renderer.Start(this, pType3Char->m_pBitmap.get(), fill_argb, 255, + if (renderer.Start(this, pType3Char->GetBitmap(), fill_argb, 255, &image_matrix, 0, false, FXDIB_BLEND_NORMAL)) { renderer.Continue(nullptr); } @@ -1931,12 +1973,12 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, return true; FX_RECT rect = FXGE_GetGlyphsBBox(glyphs, 0, sa, sd); - CFX_DIBitmap bitmap; - if (!bitmap.Create(static_cast(rect.Width() * sa), - static_cast(rect.Height() * sd), FXDIB_8bppMask)) { + auto pBitmap = pdfium::MakeRetain(); + if (!pBitmap->Create(static_cast(rect.Width() * sa), + static_cast(rect.Height() * sd), FXDIB_8bppMask)) { return true; } - bitmap.Clear(0); + pBitmap->Clear(0); for (const FXTEXT_GLYPHPOS& glyph : glyphs) { if (!glyph.m_pGlyph) continue; @@ -1955,20 +1997,20 @@ bool CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj, if (!top.IsValid()) continue; - bitmap.CompositeMask(left.ValueOrDie(), top.ValueOrDie(), - glyph.m_pGlyph->m_Bitmap.GetWidth(), - glyph.m_pGlyph->m_Bitmap.GetHeight(), - &glyph.m_pGlyph->m_Bitmap, fill_argb, 0, 0, - FXDIB_BLEND_NORMAL, nullptr, false, 0, nullptr); + pBitmap->CompositeMask(left.ValueOrDie(), top.ValueOrDie(), + glyph.m_pGlyph->m_pBitmap->GetWidth(), + glyph.m_pGlyph->m_pBitmap->GetHeight(), + glyph.m_pGlyph->m_pBitmap, fill_argb, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, false, 0); } - m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb); + m_pDevice->SetBitMask(pBitmap, rect.left, rect.top, fill_argb); return true; } void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_Matrix* pObj2Device, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pTextMatrix, bool bFill, bool bStroke) { @@ -1990,13 +2032,13 @@ void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, return; } CPDF_CharPosList CharPosList; - CharPosList.Load(textobj->m_CharCodes, textobj->m_CharPos, pFont, font_size); + CharPosList.Load(textobj->GetCharCodes(), textobj->GetCharPositions(), pFont, + font_size); for (uint32_t i = 0; i < CharPosList.m_nChars; i++) { FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i]; - auto font = - charpos.m_FallbackFontPosition == -1 - ? &pFont->m_Font - : pFont->m_FontFallbacks[charpos.m_FallbackFontPosition].get(); + auto* font = charpos.m_FallbackFontPosition == -1 + ? pFont->GetFont() + : pFont->GetFontFallback(charpos.m_FallbackFontPosition); const CFX_PathData* pPath = font->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth); if (!pPath) @@ -2023,7 +2065,7 @@ void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, } } -void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, +void CPDF_RenderStatus::DrawShading(const CPDF_ShadingPattern* pPattern, CFX_Matrix* pMatrix, FX_RECT& clip_rect, int alpha, @@ -2039,19 +2081,20 @@ void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, CPDF_Array* pBackColor = pDict->GetArrayFor("Background"); if (pBackColor && pBackColor->GetCount() >= pColorSpace->CountComponents()) { - CFX_FixedBufGrow comps(pColorSpace->CountComponents()); + CFX_FixedBufGrow comps(pColorSpace->CountComponents()); for (uint32_t i = 0; i < pColorSpace->CountComponents(); i++) comps[i] = pBackColor->GetNumberAt(i); - FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; - pColorSpace->GetRGB(comps, R, G, B); + float R = 0.0f; + float G = 0.0f; + float B = 0.0f; + pColorSpace->GetRGB(comps, &R, &G, &B); background = ArgbEncode(255, (int32_t)(R * 255), (int32_t)(G * 255), (int32_t)(B * 255)); } } if (pDict->KeyExist("BBox")) { - CFX_FloatRect rect = pDict->GetRectFor("BBox"); - pMatrix->TransformRect(rect); - clip_rect.Intersect(rect.GetOuterRect()); + clip_rect.Intersect( + pMatrix->TransformRect(pDict->GetRectFor("BBox")).GetOuterRect()); } if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SHADING && m_pDevice->GetDeviceDriver()->DrawShading(pPattern, pMatrix, clip_rect, @@ -2059,15 +2102,14 @@ void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, return; } CPDF_DeviceBuffer buffer; - buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150); + buffer.Initialize(m_pContext.Get(), m_pDevice, &clip_rect, m_pCurObj, 150); CFX_Matrix FinalMatrix = *pMatrix; FinalMatrix.Concat(*buffer.GetMatrix()); - CFX_DIBitmap* pBitmap = buffer.GetBitmap(); + RetainPtr pBitmap = buffer.GetBitmap(); if (!pBitmap->GetBuffer()) return; pBitmap->Clear(background); - int fill_mode = m_Options.m_Flags; switch (pPattern->GetShadingType()) { case kInvalidShading: case kMaxShading: @@ -2104,15 +2146,16 @@ void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, // the case of dictionary at the moment. if (CPDF_Stream* pStream = ToStream(pPattern->GetShadingObject())) { DrawCoonPatchMeshes(pPattern->GetShadingType(), pBitmap, &FinalMatrix, - pStream, funcs, pColorSpace, fill_mode, alpha); + pStream, funcs, pColorSpace, m_Options.GetFlags(), + alpha); } } break; } if (bAlphaMode) pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha); - if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) - pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor); + if (m_Options.ColorModeIs(CPDF_RenderOptions::kGray)) + pBitmap->ConvertColorScale(0, 0xffffff); buffer.OutputToDevice(); } @@ -2123,22 +2166,19 @@ void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, if (!pattern->Load()) return; - m_pDevice->SaveState(); + CFX_RenderDevice::StateRestorer restorer(m_pDevice); if (pPageObj->IsPath()) { - if (!SelectClipPath(pPageObj->AsPath(), pObj2Device, bStroke)) { - m_pDevice->RestoreState(false); + if (!SelectClipPath(pPageObj->AsPath(), pObj2Device, bStroke)) return; - } } else if (pPageObj->IsImage()) { m_pDevice->SetClip_Rect(pPageObj->GetBBox(pObj2Device)); } else { return; } FX_RECT rect; - if (GetObjectClippedRect(pPageObj, pObj2Device, false, rect)) { - m_pDevice->RestoreState(false); + if (GetObjectClippedRect(pPageObj, pObj2Device, false, rect)) return; - } + CFX_Matrix matrix = *pattern->pattern_to_form(); matrix.Concat(*pObj2Device); GetScaledMatrix(matrix); @@ -2146,8 +2186,7 @@ void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, FXSYS_round(255 * (bStroke ? pPageObj->m_GeneralState.GetStrokeAlpha() : pPageObj->m_GeneralState.GetFillAlpha())); DrawShading(pattern, &matrix, rect, alpha, - m_Options.m_ColorMode == RENDER_COLOR_ALPHA); - m_pDevice->RestoreState(false); + m_Options.ColorModeIs(CPDF_RenderOptions::kAlpha)); } void CPDF_RenderStatus::ProcessShading(const CPDF_ShadingObject* pShadingObj, @@ -2158,155 +2197,156 @@ void CPDF_RenderStatus::ProcessShading(const CPDF_ShadingObject* pShadingObj, if (rect.IsEmpty()) return; - CFX_Matrix matrix = pShadingObj->m_Matrix; + CFX_Matrix matrix = pShadingObj->matrix(); matrix.Concat(*pObj2Device); - DrawShading(pShadingObj->m_pShading, &matrix, rect, + DrawShading(pShadingObj->pattern(), &matrix, rect, FXSYS_round(255 * pShadingObj->m_GeneralState.GetFillAlpha()), - m_Options.m_ColorMode == RENDER_COLOR_ALPHA); + m_Options.ColorModeIs(CPDF_RenderOptions::kAlpha)); } void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_Matrix* pObj2Device, bool bStroke) { - if (!pPattern->Load()) { + if (!pPattern->Load()) return; - } - m_pDevice->SaveState(); + + CFX_RenderDevice::StateRestorer restorer(m_pDevice); if (pPageObj->IsPath()) { - if (!SelectClipPath(pPageObj->AsPath(), pObj2Device, bStroke)) { - m_pDevice->RestoreState(false); + if (!SelectClipPath(pPageObj->AsPath(), pObj2Device, bStroke)) return; - } } else if (pPageObj->IsImage()) { m_pDevice->SetClip_Rect(pPageObj->GetBBox(pObj2Device)); } else { return; } + FX_RECT clip_box = m_pDevice->GetClipBox(); - if (clip_box.IsEmpty()) { - m_pDevice->RestoreState(false); + if (clip_box.IsEmpty()) return; - } + CFX_Matrix dCTM = m_pDevice->GetCTM(); - FX_FLOAT sa = FXSYS_fabs(dCTM.a); - FX_FLOAT sd = FXSYS_fabs(dCTM.d); - clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa); - clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd); + float sa = fabs(dCTM.a); + float sd = fabs(dCTM.d); + clip_box.right = clip_box.left + (int32_t)ceil(clip_box.Width() * sa); + clip_box.bottom = clip_box.top + (int32_t)ceil(clip_box.Height() * sd); + CFX_Matrix mtPattern2Device = *pPattern->pattern_to_form(); mtPattern2Device.Concat(*pObj2Device); GetScaledMatrix(mtPattern2Device); - bool bAligned = false; - if (pPattern->bbox().left == 0 && pPattern->bbox().bottom == 0 && + + bool bAligned = + pPattern->bbox().left == 0 && pPattern->bbox().bottom == 0 && pPattern->bbox().right == pPattern->x_step() && pPattern->bbox().top == pPattern->y_step() && - (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) { - bAligned = true; - } - CFX_FloatRect cell_bbox = pPattern->bbox(); - mtPattern2Device.TransformRect(cell_bbox); - int width = (int)FXSYS_ceil(cell_bbox.Width()); - int height = (int)FXSYS_ceil(cell_bbox.Height()); - if (width == 0) { - width = 1; - } - if (height == 0) { - height = 1; + (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated()); + + CFX_FloatRect cell_bbox = mtPattern2Device.TransformRect(pPattern->bbox()); + + float ceil_height = std::ceil(cell_bbox.Height()); + float ceil_width = std::ceil(cell_bbox.Width()); + + // Validate the float will fit into the int when the conversion is done. + if (!pdfium::base::IsValueInRangeForNumericType(ceil_height) || + !pdfium::base::IsValueInRangeForNumericType(ceil_width)) { + return; } - int min_col, max_col, min_row, max_row; - CFX_Matrix mtDevice2Pattern; - mtDevice2Pattern.SetReverse(mtPattern2Device); - CFX_FloatRect clip_box_p(clip_box); - mtDevice2Pattern.TransformRect(clip_box_p); + int width = static_cast(ceil_width); + int height = static_cast(ceil_height); + if (width <= 0) + width = 1; + if (height <= 0) + height = 1; - min_col = (int)FXSYS_ceil((clip_box_p.left - pPattern->bbox().right) / - pPattern->x_step()); - max_col = (int)FXSYS_floor((clip_box_p.right - pPattern->bbox().left) / - pPattern->x_step()); - min_row = (int)FXSYS_ceil((clip_box_p.bottom - pPattern->bbox().top) / - pPattern->y_step()); - max_row = (int)FXSYS_floor((clip_box_p.top - pPattern->bbox().bottom) / - pPattern->y_step()); + CFX_FloatRect clip_box_p = + mtPattern2Device.GetInverse().TransformRect(CFX_FloatRect(clip_box)); + int min_col = (int)ceil((clip_box_p.left - pPattern->bbox().right) / + pPattern->x_step()); + int max_col = (int)floor((clip_box_p.right - pPattern->bbox().left) / + pPattern->x_step()); + int min_row = (int)ceil((clip_box_p.bottom - pPattern->bbox().top) / + pPattern->y_step()); + int max_row = (int)floor((clip_box_p.top - pPattern->bbox().bottom) / + pPattern->y_step()); + + // Make sure we can fit the needed width * height into an int. + if (height > std::numeric_limits::max() / width) + return; if (width > clip_box.Width() || height > clip_box.Height() || width * height > clip_box.Width() * clip_box.Height()) { - CPDF_GraphicStates* pStates = nullptr; + std::unique_ptr pStates; if (!pPattern->colored()) pStates = CloneObjStates(pPageObj, bStroke); - CPDF_Dictionary* pFormResource = nullptr; - if (pPattern->form()->m_pFormDict) - pFormResource = pPattern->form()->m_pFormDict->GetDictFor("Resources"); - - for (int col = min_col; col <= max_col; col++) + auto& pFormDict = pPattern->form()->m_pFormDict; + CPDF_Dictionary* pFormResource = + pFormDict ? pFormDict->GetDictFor("Resources") : nullptr; + for (int col = min_col; col <= max_col; col++) { for (int row = min_row; row <= max_row; row++) { CFX_PointF original = mtPattern2Device.Transform( CFX_PointF(col * pPattern->x_step(), row * pPattern->y_step())); CFX_Matrix matrix = *pObj2Device; matrix.Translate(original.x - mtPattern2Device.e, original.y - mtPattern2Device.f); - m_pDevice->SaveState(); + CFX_RenderDevice::StateRestorer restorer2(m_pDevice); CPDF_RenderStatus status; - status.Initialize(m_pContext, m_pDevice, nullptr, nullptr, this, - pStates, &m_Options, pPattern->form()->m_Transparency, - m_bDropObjects, pFormResource); + status.Initialize(m_pContext.Get(), m_pDevice, nullptr, nullptr, this, + pStates.get(), &m_Options, + pPattern->form()->m_iTransparency, m_bDropObjects, + pFormResource); status.RenderObjectList(pPattern->form(), &matrix); - m_pDevice->RestoreState(false); } - m_pDevice->RestoreState(false); - delete pStates; + } return; } if (bAligned) { int orig_x = FXSYS_round(mtPattern2Device.e); int orig_y = FXSYS_round(mtPattern2Device.f); min_col = (clip_box.left - orig_x) / width; - if (clip_box.left < orig_x) { + if (clip_box.left < orig_x) min_col--; - } + max_col = (clip_box.right - orig_x) / width; - if (clip_box.right <= orig_x) { + if (clip_box.right <= orig_x) max_col--; - } + min_row = (clip_box.top - orig_y) / height; - if (clip_box.top < orig_y) { + if (clip_box.top < orig_y) min_row--; - } + max_row = (clip_box.bottom - orig_y) / height; - if (clip_box.bottom <= orig_y) { + if (clip_box.bottom <= orig_y) max_row--; - } } - FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e; - FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f; - std::unique_ptr pPatternBitmap; + float left_offset = cell_bbox.left - mtPattern2Device.e; + float top_offset = cell_bbox.bottom - mtPattern2Device.f; + RetainPtr pPatternBitmap; if (width * height < 16) { - std::unique_ptr pEnlargedBitmap = + RetainPtr pEnlargedBitmap = DrawPatternBitmap(m_pContext->GetDocument(), m_pContext->GetPageCache(), - pPattern, pObj2Device, 8, 8, m_Options.m_Flags); - pPatternBitmap = pEnlargedBitmap->StretchTo(width, height); + pPattern, pObj2Device, 8, 8, m_Options.GetFlags()); + pPatternBitmap = pEnlargedBitmap->StretchTo(width, height, 0, nullptr); } else { pPatternBitmap = DrawPatternBitmap( m_pContext->GetDocument(), m_pContext->GetPageCache(), pPattern, - pObj2Device, width, height, m_Options.m_Flags); + pObj2Device, width, height, m_Options.GetFlags()); } - if (!pPatternBitmap) { - m_pDevice->RestoreState(false); + if (!pPatternBitmap) return; - } - if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { - pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor, - m_Options.m_BackColor); - } + + if (m_Options.ColorModeIs(CPDF_RenderOptions::kGray)) + pPatternBitmap->ConvertColorScale(0, 0xffffff); + FX_ARGB fill_argb = GetFillArgb(pPageObj); int clip_width = clip_box.right - clip_box.left; int clip_height = clip_box.bottom - clip_box.top; - CFX_DIBitmap screen; - if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) { + auto pScreen = pdfium::MakeRetain(); + if (!pScreen->Create(clip_width, clip_height, FXDIB_Argb)) return; - } - screen.Clear(0); + + pScreen->Clear(0); uint32_t* src_buf = (uint32_t*)pPatternBitmap->GetBuffer(); for (int col = min_col; col <= max_col; col++) { for (int row = min_row; row <= max_row; row++) { @@ -2337,7 +2377,7 @@ void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, continue; } uint32_t* dest_buf = - (uint32_t*)(screen.GetBuffer() + screen.GetPitch() * start_y + + (uint32_t*)(pScreen->GetBuffer() + pScreen->GetPitch() * start_y + start_x * 4); if (pPattern->colored()) *dest_buf = *src_buf; @@ -2345,18 +2385,17 @@ void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffffff); } else { if (pPattern->colored()) { - screen.CompositeBitmap(start_x, start_y, width, height, - pPatternBitmap.get(), 0, 0); + pScreen->CompositeBitmap(start_x, start_y, width, height, + pPatternBitmap, 0, 0); } else { - screen.CompositeMask(start_x, start_y, width, height, - pPatternBitmap.get(), fill_argb, 0, 0); + pScreen->CompositeMask(start_x, start_y, width, height, + pPatternBitmap, fill_argb, 0, 0); } } } } - CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255, + CompositeDIBitmap(pScreen, clip_box.left, clip_box.top, 0, 255, FXDIB_BLEND_NORMAL, false); - m_pDevice->RestoreState(false); } void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj, @@ -2401,24 +2440,25 @@ bool CPDF_RenderStatus::ProcessImage(CPDF_ImageObject* pImageObj, return render.GetResult(); } -void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, - int left, - int top, - FX_ARGB mask_argb, - int bitmap_alpha, - int blend_mode, - int Transparency) { - if (!pDIBitmap) { +void CPDF_RenderStatus::CompositeDIBitmap( + const RetainPtr& pDIBitmap, + int left, + int top, + FX_ARGB mask_argb, + int bitmap_alpha, + int blend_mode, + int iTransparency) { + if (!pDIBitmap) return; - } + if (blend_mode == FXDIB_BLEND_NORMAL) { if (!pDIBitmap->IsAlphaMask()) { if (bitmap_alpha < 255) { #ifdef _SKIA_SUPPORT_ - void* dummy; + std::unique_ptr dummy; CFX_Matrix m(pDIBitmap->GetWidth(), 0, 0, -pDIBitmap->GetHeight(), left, top + pDIBitmap->GetHeight()); - m_pDevice->StartDIBits(pDIBitmap, bitmap_alpha, 0, &m, 0, dummy); + m_pDevice->StartDIBits(pDIBitmap, bitmap_alpha, 0, &m, 0, &dummy); return; #else pDIBitmap->MultiplyAlpha(bitmap_alpha); @@ -2433,16 +2473,16 @@ void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, } else { uint32_t fill_argb = m_Options.TranslateColor(mask_argb); if (bitmap_alpha < 255) { - ((uint8_t*)&fill_argb)[3] = - ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; + uint8_t* fill_argb8 = reinterpret_cast(&fill_argb); + fill_argb8[3] *= bitmap_alpha / 255; } if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { return; } } } - bool bIsolated = !!(Transparency & PDFTRANS_ISOLATED); - bool bGroup = !!(Transparency & PDFTRANS_GROUP); + bool bIsolated = !!(iTransparency & PDFTRANS_ISOLATED); + bool bGroup = !!(iTransparency & PDFTRANS_GROUP); bool bBackAlphaRequired = blend_mode && bIsolated && !m_bDropObjects; bool bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || @@ -2450,72 +2490,76 @@ void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); if (bGetBackGround) { if (bIsolated || !bGroup) { - if (pDIBitmap->IsAlphaMask()) { + if (!pDIBitmap->IsAlphaMask()) + m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode); + return; + } + + FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), + top + pDIBitmap->GetHeight()); + rect.Intersect(m_pDevice->GetClipBox()); + RetainPtr pClone; + if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { + pClone = m_pDevice->GetBackDrop()->Clone(&rect); + if (!pClone) return; - } - m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode); - } else { - FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), - top + pDIBitmap->GetHeight()); - rect.Intersect(m_pDevice->GetClipBox()); - CFX_MaybeOwned pClone; - if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { - pClone = m_pDevice->GetBackDrop()->Clone(&rect); - CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap(); - pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pForeBitmap, rect.left, rect.top); - left = left >= 0 ? 0 : left; - top = top >= 0 ? 0 : top; - if (!pDIBitmap->IsAlphaMask()) - pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pDIBitmap, left, top, blend_mode); - else - pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pDIBitmap, mask_argb, left, top, blend_mode); + + RetainPtr pForeBitmap = m_pDevice->GetBitmap(); + pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), + pForeBitmap, rect.left, rect.top); + left = std::min(left, 0); + top = std::min(top, 0); + if (pDIBitmap->IsAlphaMask()) { + pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), + pDIBitmap, mask_argb, left, top, blend_mode); } else { - pClone = pDIBitmap; + pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), + pDIBitmap, left, top, blend_mode); } - if (m_pDevice->GetBackDrop()) { - m_pDevice->SetDIBits(pClone.Get(), rect.left, rect.top); - } else { - if (pDIBitmap->IsAlphaMask()) - return; + } else { + pClone = pDIBitmap; + } + if (m_pDevice->GetBackDrop()) { + m_pDevice->SetDIBits(pClone, rect.left, rect.top); + } else { + if (!pDIBitmap->IsAlphaMask()) { m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top, blend_mode); } } return; } - int back_left, back_top; + int back_left; + int back_top; FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight()); - std::unique_ptr pBackdrop = - GetBackdrop(m_pCurObj, rect, back_left, back_top, - blend_mode > FXDIB_BLEND_NORMAL && bIsolated); + RetainPtr pBackdrop = + GetBackdrop(m_pCurObj, rect, blend_mode > FXDIB_BLEND_NORMAL && bIsolated, + &back_left, &back_top); if (!pBackdrop) return; - if (!pDIBitmap->IsAlphaMask()) { - pBackdrop->CompositeBitmap(left - back_left, top - back_top, - pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), - pDIBitmap, 0, 0, blend_mode); - } else { + if (pDIBitmap->IsAlphaMask()) { pBackdrop->CompositeMask(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap, mask_argb, 0, 0, blend_mode); + } else { + pBackdrop->CompositeBitmap(left - back_left, top - back_top, + pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), + pDIBitmap, 0, 0, blend_mode); } - auto pBackdrop1 = pdfium::MakeUnique(); + auto pBackdrop1 = pdfium::MakeRetain(); pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(), FXDIB_Rgb32); pBackdrop1->Clear((uint32_t)-1); pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(), - pBackdrop->GetHeight(), pBackdrop.get(), 0, 0); + pBackdrop->GetHeight(), pBackdrop, 0, 0); pBackdrop = std::move(pBackdrop1); - m_pDevice->SetDIBits(pBackdrop.get(), back_left, back_top); + m_pDevice->SetDIBits(pBackdrop, back_left, back_top); } -std::unique_ptr CPDF_RenderStatus::LoadSMask( +RetainPtr CPDF_RenderStatus::LoadSMask( CPDF_Dictionary* pSMaskDict, FX_RECT* pClipRect, const CFX_Matrix* pMatrix) { @@ -2536,14 +2580,14 @@ std::unique_ptr CPDF_RenderStatus::LoadSMask( CPDF_Form form(m_pContext->GetDocument(), m_pContext->GetPageResources(), pGroup); - form.ParseContent(nullptr, nullptr, nullptr); + form.ParseContent(); - CFX_FxgeDevice bitmap_device; + CFX_DefaultRenderDevice bitmap_device; bool bLuminosity = pSMaskDict->GetStringFor("S") != "Alpha"; int width = pClipRect->right - pClipRect->left; int height = pClipRect->bottom - pClipRect->top; FXDIB_Format format; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \ defined _SKIA_SUPPORT_PATHS_ format = bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask; #else @@ -2569,24 +2613,24 @@ std::unique_ptr CPDF_RenderStatus::LoadSMask( // Store Color Space Family to use in CPDF_RenderStatus::Initialize. color_space_family = pCS->GetFamily(); - FX_FLOAT R, G, B; + float R, G, B; uint32_t comps = 8; if (pCS->CountComponents() > comps) { comps = pCS->CountComponents(); } - CFX_FixedBufGrow float_array(comps); - FX_FLOAT* pFloats = float_array; + CFX_FixedBufGrow float_array(comps); + float* pFloats = float_array; FX_SAFE_UINT32 num_floats = comps; - num_floats *= sizeof(FX_FLOAT); + num_floats *= sizeof(float); if (!num_floats.IsValid()) { return nullptr; } - FXSYS_memset(pFloats, 0, num_floats.ValueOrDie()); + memset(pFloats, 0, num_floats.ValueOrDie()); size_t count = pBC->GetCount() > 8 ? 8 : pBC->GetCount(); for (size_t i = 0; i < count; i++) { pFloats[i] = pBC->GetNumberAt(i); } - pCS->GetRGB(pFloats, R, G, B); + pCS->GetRGB(pFloats, &R, &G, &B); back_color = 0xff000000 | ((int32_t)(R * 255) << 16) | ((int32_t)(G * 255) << 8) | (int32_t)(B * 255); m_pContext->GetDocument()->GetPageData()->ReleaseColorSpace(pCSObj); @@ -2601,14 +2645,15 @@ std::unique_ptr CPDF_RenderStatus::LoadSMask( pFormResource = form.m_pFormDict->GetDictFor("Resources"); } CPDF_RenderOptions options; - options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA; + options.SetColorMode(bLuminosity ? CPDF_RenderOptions::kNormal + : CPDF_RenderOptions::kAlpha); CPDF_RenderStatus status; - status.Initialize(m_pContext, &bitmap_device, nullptr, nullptr, nullptr, + status.Initialize(m_pContext.Get(), &bitmap_device, nullptr, nullptr, nullptr, nullptr, &options, 0, m_bDropObjects, pFormResource, true, nullptr, 0, color_space_family, bLuminosity); status.RenderObjectList(&form, &matrix); - auto pMask = pdfium::MakeUnique(); + auto pMask = pdfium::MakeRetain(); if (!pMask->Create(width, height, FXDIB_8bppMask)) return nullptr; @@ -2618,11 +2663,11 @@ std::unique_ptr CPDF_RenderStatus::LoadSMask( int src_pitch = bitmap.GetPitch(); std::vector transfers(256); if (pFunc) { - CFX_FixedBufGrow results(pFunc->CountOutputs()); + CFX_FixedBufGrow results(pFunc->CountOutputs()); for (int i = 0; i < 256; i++) { - FX_FLOAT input = (FX_FLOAT)i / 255.0f; + float input = (float)i / 255.0f; int nresult; - pFunc->Call(&input, 1, results, nresult); + pFunc->Call(&input, 1, results, &nresult); transfers[i] = FXSYS_round(results[0] * 255); } } else { @@ -2646,7 +2691,7 @@ std::unique_ptr CPDF_RenderStatus::LoadSMask( dest_buf[i] = transfers[src_buf[i]]; } } else { - FXSYS_memcpy(dest_buf, src_buf, dest_pitch * height); + memcpy(dest_buf, src_buf, dest_pitch * height); } return pMask; } diff --git a/core/fpdfapi/render/cpdf_renderstatus.h b/core/fpdfapi/render/cpdf_renderstatus.h index 25ddfb06c379400afe5e88ef15ad1b67f37a32c0..c8b7b0901791fdf3e46c95bcd7e592663ae7dd98 100644 --- a/core/fpdfapi/render/cpdf_renderstatus.h +++ b/core/fpdfapi/render/cpdf_renderstatus.h @@ -13,6 +13,7 @@ #include "core/fpdfapi/page/cpdf_clippath.h" #include "core/fpdfapi/page/cpdf_graphicstates.h" #include "core/fpdfapi/render/cpdf_renderoptions.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/cfx_renderdevice.h" class CFX_PathData; @@ -60,23 +61,44 @@ class CPDF_RenderStatus { void RenderSingleObject(CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device); bool ContinueSingleObject(CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device, - IFX_Pause* pPause); - CPDF_RenderContext* GetContext() { return m_pContext; } + IFX_PauseIndicator* pPause); + void ProcessClipPath(const CPDF_ClipPath& ClipPath, + const CFX_Matrix* pObj2Device); + + uint32_t GetGroupFamily() const { return m_GroupFamily; } + bool GetLoadMask() const { return m_bLoadMask; } + bool GetDropObjects() const { return m_bDropObjects; } + bool IsPrint() const { return m_bPrint; } + bool IsStopped() const { return m_bStopped; } + CPDF_RenderContext* GetContext() const { return m_pContext.Get(); } + CPDF_Dictionary* GetFormResource() const { return m_pFormResource.Get(); } + CPDF_Dictionary* GetPageResource() const { return m_pPageResource.Get(); } + CFX_RenderDevice* GetRenderDevice() const { return m_pDevice; } + const CPDF_RenderOptions* GetRenderOptions() const { return &m_Options; } #if defined _SKIA_SUPPORT_ void DebugVerifyDeviceIsPreMultiplied() const; #endif - CPDF_RenderOptions m_Options; - CPDF_Dictionary* m_pFormResource; - CPDF_Dictionary* m_pPageResource; - std::vector m_Type3FontCache; + RetainPtr GetTransferFunc(CPDF_Object* pObject) const; + FX_ARGB GetFillArgb(CPDF_PageObject* pObj, bool bType3 = false) const; + void DrawTilingPattern(CPDF_TilingPattern* pPattern, + CPDF_PageObject* pPageObj, + const CFX_Matrix* pObj2Device, + bool bStroke); + void DrawShadingPattern(CPDF_ShadingPattern* pPattern, + const CPDF_PageObject* pPageObj, + const CFX_Matrix* pObj2Device, + bool bStroke); + void CompositeDIBitmap(const RetainPtr& pDIBitmap, + int left, + int top, + FX_ARGB mask_argb, + int bitmap_alpha, + int blend_mode, + int iTransparency); private: - friend class CPDF_ImageRenderer; - friend class CPDF_RenderContext; - - void ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_Matrix* pObj2Device); bool ProcessTransparency(CPDF_PageObject* PageObj, const CFX_Matrix* pObj2Device); void ProcessObjectNoClip(CPDF_PageObject* PageObj, @@ -93,28 +115,13 @@ class CPDF_RenderStatus { const CFX_Matrix* pObj2Device, const CPDF_Color* pColor, bool bStroke); - void DrawTilingPattern(CPDF_TilingPattern* pPattern, - CPDF_PageObject* pPageObj, - const CFX_Matrix* pObj2Device, - bool bStroke); - void DrawShadingPattern(CPDF_ShadingPattern* pPattern, - const CPDF_PageObject* pPageObj, - const CFX_Matrix* pObj2Device, - bool bStroke); bool SelectClipPath(const CPDF_PathObject* pPathObj, const CFX_Matrix* pObj2Device, bool bStroke); bool ProcessImage(CPDF_ImageObject* pImageObj, const CFX_Matrix* pObj2Device); - void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, - int left, - int top, - FX_ARGB mask_argb, - int bitmap_alpha, - int blend_mode, - int bIsolated); void ProcessShading(const CPDF_ShadingObject* pShadingObj, const CFX_Matrix* pObj2Device); - void DrawShading(CPDF_ShadingPattern* pPattern, + void DrawShading(const CPDF_ShadingPattern* pPattern, CFX_Matrix* pMatrix, FX_RECT& clip_rect, int alpha, @@ -127,25 +134,24 @@ class CPDF_RenderStatus { void DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_Matrix* pObj2Device, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pTextMatrix, bool bFill, bool bStroke); bool ProcessForm(const CPDF_FormObject* pFormObj, const CFX_Matrix* pObj2Device); - std::unique_ptr GetBackdrop(const CPDF_PageObject* pObj, - const FX_RECT& rect, - int& left, - int& top, - bool bBackAlphaRequired); - std::unique_ptr LoadSMask(CPDF_Dictionary* pSMaskDict, - FX_RECT* pClipRect, - const CFX_Matrix* pMatrix); - static CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont); - static CPDF_GraphicStates* CloneObjStates(const CPDF_GraphicStates* pPathObj, - bool bStroke); - CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObject) const; - FX_ARGB GetFillArgb(CPDF_PageObject* pObj, bool bType3 = false) const; + RetainPtr GetBackdrop(const CPDF_PageObject* pObj, + const FX_RECT& rect, + bool bBackAlphaRequired, + int* left, + int* top); + RetainPtr LoadSMask(CPDF_Dictionary* pSMaskDict, + FX_RECT* pClipRect, + const CFX_Matrix* pMatrix); + static RetainPtr GetCachedType3(CPDF_Type3Font* pFont); + static std::unique_ptr CloneObjStates( + const CPDF_GraphicStates* pPathObj, + bool bStroke); FX_ARGB GetStrokeArgb(CPDF_PageObject* pObj) const; bool GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device, @@ -156,7 +162,11 @@ class CPDF_RenderStatus { static const int kRenderMaxRecursionDepth = 64; static int s_CurrentRecursionDepth; - CPDF_RenderContext* m_pContext; + CPDF_RenderOptions m_Options; + UnownedPtr m_pFormResource; + UnownedPtr m_pPageResource; + std::vector m_Type3FontCache; + UnownedPtr m_pContext; bool m_bStopped; CFX_RenderDevice* m_pDevice; CFX_Matrix m_DeviceMatrix; @@ -166,12 +176,12 @@ class CPDF_RenderStatus { CPDF_GraphicStates m_InitialStates; std::unique_ptr m_pImageRenderer; bool m_bPrint; - int m_Transparency; + int m_iTransparency; bool m_bDropObjects; bool m_bStdCS; uint32_t m_GroupFamily; bool m_bLoadMask; - CPDF_Type3Char* m_pType3Char; + UnownedPtr m_pType3Char; FX_ARGB m_T3FillColor; int m_curBlend; }; diff --git a/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp b/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp index de60e732bb25bf8e26b52b86742d674f1f9532bf..2d8602478730761b5def4efb4649e6647b0851c8 100644 --- a/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp +++ b/core/fpdfapi/render/cpdf_scaledrenderbuffer.cpp @@ -8,8 +8,8 @@ #include "core/fpdfapi/render/cpdf_rendercontext.h" #include "core/fpdfapi/render/cpdf_renderoptions.h" -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "third_party/base/ptr_util.h" #define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024) @@ -40,11 +40,11 @@ bool CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10); if (dpih > max_dpi) - m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f); + m_Matrix.Scale((float)(max_dpi) / dpih, 1.0f); if (dpiv > max_dpi) - m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv); + m_Matrix.Scale(1.0f, (float)(max_dpi) / (float)dpiv); } - m_pBitmapDevice = pdfium::MakeUnique(); + m_pBitmapDevice = pdfium::MakeUnique(); FXDIB_Format dibFormat = FXDIB_Rgb; int32_t bpp = 24; if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) { @@ -52,9 +52,8 @@ bool CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, bpp = 32; } while (1) { - CFX_FloatRect rect(pRect); - m_Matrix.TransformRect(rect); - FX_RECT bitmap_rect = rect.GetOuterRect(); + FX_RECT bitmap_rect = + m_Matrix.TransformRect(CFX_FloatRect(pRect)).GetOuterRect(); int32_t iWidth = bitmap_rect.Width(); int32_t iHeight = bitmap_rect.Height(); int32_t iPitch = (iWidth * bpp + 31) / 32 * 4; @@ -67,8 +66,8 @@ bool CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, } m_Matrix.Scale(0.5f, 0.5f); } - m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions, - &m_Matrix); + m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject.Get(), + pOptions, &m_Matrix); return true; } diff --git a/core/fpdfapi/render/cpdf_scaledrenderbuffer.h b/core/fpdfapi/render/cpdf_scaledrenderbuffer.h index f802349dcb968447205aaff4cca43eb68539d3f5..b77e4b63099611d1fa17f6d3d7bbf0dea220b46b 100644 --- a/core/fpdfapi/render/cpdf_scaledrenderbuffer.h +++ b/core/fpdfapi/render/cpdf_scaledrenderbuffer.h @@ -10,7 +10,8 @@ #include #include "core/fxcrt/fx_coordinates.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_defaultrenderdevice.h" class CFX_RenderDevice; class CPDF_PageObject; @@ -28,18 +29,19 @@ class CPDF_ScaledRenderBuffer { const CPDF_PageObject* pObj, const CPDF_RenderOptions* pOptions, int max_dpi); - CFX_RenderDevice* GetDevice() { - return m_pBitmapDevice ? m_pBitmapDevice.get() : m_pDevice; + + CFX_RenderDevice* GetDevice() const { + return m_pBitmapDevice ? m_pBitmapDevice.get() : m_pDevice.Get(); } CFX_Matrix* GetMatrix() { return &m_Matrix; } void OutputToDevice(); private: - CFX_RenderDevice* m_pDevice; - CPDF_RenderContext* m_pContext; + UnownedPtr m_pDevice; + UnownedPtr m_pContext; FX_RECT m_Rect; - const CPDF_PageObject* m_pObject; - std::unique_ptr m_pBitmapDevice; + UnownedPtr m_pObject; + std::unique_ptr m_pBitmapDevice; CFX_Matrix m_Matrix; }; diff --git a/core/fpdfapi/render/cpdf_textrenderer.cpp b/core/fpdfapi/render/cpdf_textrenderer.cpp index 95af863f7af7be2e27fc7971c687a74b7137a2a4..711dbfaf39c1df2cd76c1993cc0822241b88b51c 100644 --- a/core/fpdfapi/render/cpdf_textrenderer.cpp +++ b/core/fpdfapi/render/cpdf_textrenderer.cpp @@ -15,12 +15,20 @@ #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" +namespace { + +CFX_Font* GetFont(CPDF_Font* pFont, int32_t position) { + return position == -1 ? pFont->GetFont() : pFont->GetFontFallback(position); +} + +} // namespace + // static bool CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, const std::vector& charCodes, - const std::vector& charPos, + const std::vector& charPos, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pText2User, const CFX_Matrix* pUser2Device, const CFX_GraphStateData* pGraphState, @@ -40,9 +48,8 @@ bool CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition; if (fontPosition == curFontPosition) continue; - auto* font = fontPosition == -1 - ? &pFont->m_Font - : pFont->m_FontFallbacks[fontPosition].get(); + + CFX_Font* font = GetFont(pFont, fontPosition); if (!pDevice->DrawTextPath(i - startIndex, CharPosList.m_pCharPos + startIndex, font, font_size, pText2User, pUser2Device, pGraphState, @@ -52,8 +59,7 @@ bool CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, fontPosition = curFontPosition; startIndex = i; } - auto* font = fontPosition == -1 ? &pFont->m_Font - : pFont->m_FontFallbacks[fontPosition].get(); + CFX_Font* font = GetFont(pFont, fontPosition); if (!pDevice->DrawTextPath(CharPosList.m_nChars - startIndex, CharPosList.m_pCharPos + startIndex, font, font_size, pText2User, pUser2Device, pGraphState, @@ -65,12 +71,12 @@ bool CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, // static void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, - FX_FLOAT origin_x, - FX_FLOAT origin_y, + float origin_x, + float origin_y, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pMatrix, - const CFX_ByteString& str, + const ByteString& str, FX_ARGB fill_argb, const CFX_GraphStateData* pGraphState, const CPDF_RenderOptions* pOptions) { @@ -83,10 +89,10 @@ void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, int offset = 0; std::vector codes; - std::vector positions; + std::vector positions; codes.resize(nChars); positions.resize(nChars - 1); - FX_FLOAT cur_pos = 0; + float cur_pos = 0; for (int i = 0; i < nChars; i++) { codes[i] = pFont->GetNextChar(str.c_str(), str.GetLength(), offset); if (i) @@ -107,9 +113,9 @@ void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, // static bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, const std::vector& charCodes, - const std::vector& charPos, + const std::vector& charPos, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pText2Device, FX_ARGB fill_argb, const CPDF_RenderOptions* pOptions) { @@ -119,19 +125,18 @@ bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, return true; int FXGE_flags = 0; if (pOptions) { - uint32_t dwFlags = pOptions->m_Flags; - if (dwFlags & RENDER_CLEARTYPE) { + if (pOptions->HasFlag(RENDER_CLEARTYPE)) { FXGE_flags |= FXTEXT_CLEARTYPE; - if (dwFlags & RENDER_BGR_STRIPE) + if (pOptions->HasFlag(RENDER_BGR_STRIPE)) FXGE_flags |= FXTEXT_BGR_STRIPE; } - if (dwFlags & RENDER_NOTEXTSMOOTH) + if (pOptions->HasFlag(RENDER_NOTEXTSMOOTH)) FXGE_flags |= FXTEXT_NOSMOOTH; - if (dwFlags & RENDER_PRINTGRAPHICTEXT) + if (pOptions->HasFlag(RENDER_PRINTGRAPHICTEXT)) FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT; - if (dwFlags & RENDER_NO_NATIVETEXT) + if (pOptions->HasFlag(RENDER_NO_NATIVETEXT)) FXGE_flags |= FXTEXT_NO_NATIVETEXT; - if (dwFlags & RENDER_PRINTIMAGETEXT) + if (pOptions->HasFlag(RENDER_PRINTIMAGETEXT)) FXGE_flags |= FXTEXT_PRINTIMAGETEXT; } else { FXGE_flags = FXTEXT_CLEARTYPE; @@ -145,9 +150,8 @@ bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition; if (fontPosition == curFontPosition) continue; - auto* font = fontPosition == -1 - ? &pFont->m_Font - : pFont->m_FontFallbacks[fontPosition].get(); + + CFX_Font* font = GetFont(pFont, fontPosition); if (!pDevice->DrawNormalText( i - startIndex, CharPosList.m_pCharPos + startIndex, font, font_size, pText2Device, fill_argb, FXGE_flags)) { @@ -156,8 +160,7 @@ bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, fontPosition = curFontPosition; startIndex = i; } - auto* font = fontPosition == -1 ? &pFont->m_Font - : pFont->m_FontFallbacks[fontPosition].get(); + CFX_Font* font = GetFont(pFont, fontPosition); if (!pDevice->DrawNormalText(CharPosList.m_nChars - startIndex, CharPosList.m_pCharPos + startIndex, font, font_size, pText2Device, fill_argb, diff --git a/core/fpdfapi/render/cpdf_textrenderer.h b/core/fpdfapi/render/cpdf_textrenderer.h index 54e9d1bd054e380e35dd356177a5d99b993689a1..ac8c8c5568d9c03671c5945a62a4bbc4a0627b16 100644 --- a/core/fpdfapi/render/cpdf_textrenderer.h +++ b/core/fpdfapi/render/cpdf_textrenderer.h @@ -23,21 +23,21 @@ class CPDF_Font; class CPDF_TextRenderer { public: static void DrawTextString(CFX_RenderDevice* pDevice, - FX_FLOAT origin_x, - FX_FLOAT origin_y, + float origin_x, + float origin_y, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* matrix, - const CFX_ByteString& str, + const ByteString& str, FX_ARGB fill_argb, const CFX_GraphStateData* pGraphState, const CPDF_RenderOptions* pOptions); static bool DrawTextPath(CFX_RenderDevice* pDevice, const std::vector& charCodes, - const std::vector& charPos, + const std::vector& charPos, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pText2User, const CFX_Matrix* pUser2Device, const CFX_GraphStateData* pGraphState, @@ -48,9 +48,9 @@ class CPDF_TextRenderer { static bool DrawNormalText(CFX_RenderDevice* pDevice, const std::vector& charCodes, - const std::vector& charPos, + const std::vector& charPos, CPDF_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pText2Device, FX_ARGB fill_argb, const CPDF_RenderOptions* pOptions); diff --git a/core/fpdfapi/render/cpdf_transferfunc.cpp b/core/fpdfapi/render/cpdf_transferfunc.cpp index be4836d20ab497134c396d670334dc754775eb57..98528c3c14528a8e743d3dd079ed6e4b616b1f4e 100644 --- a/core/fpdfapi/render/cpdf_transferfunc.cpp +++ b/core/fpdfapi/render/cpdf_transferfunc.cpp @@ -8,18 +8,22 @@ #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/render/cpdf_dibtransferfunc.h" +#include "core/fxge/dib/cfx_dibsource.h" CPDF_TransferFunc::CPDF_TransferFunc(CPDF_Document* pDoc) : m_pPDFDoc(pDoc) {} +CPDF_TransferFunc::~CPDF_TransferFunc() {} + FX_COLORREF CPDF_TransferFunc::TranslateColor(FX_COLORREF rgb) const { return FXSYS_RGB(m_Samples[FXSYS_GetRValue(rgb)], m_Samples[256 + FXSYS_GetGValue(rgb)], m_Samples[512 + FXSYS_GetBValue(rgb)]); } -CFX_DIBSource* CPDF_TransferFunc::TranslateImage(const CFX_DIBSource* pSrc, - bool bAutoDropSrc) { - CPDF_DIBTransferFunc* pDest = new CPDF_DIBTransferFunc(this); - pDest->LoadSrc(pSrc, bAutoDropSrc); +RetainPtr CPDF_TransferFunc::TranslateImage( + const RetainPtr& pSrc) { + RetainPtr pHolder(this); + auto pDest = pdfium::MakeRetain(pHolder); + pDest->LoadSrc(pSrc); return pDest; } diff --git a/core/fpdfapi/render/cpdf_transferfunc.h b/core/fpdfapi/render/cpdf_transferfunc.h index 829b274d9b9e9f8f399de5e189a86f18c2e20795..d7e21fcfefb2ec7977131f0488d73703edb604aa 100644 --- a/core/fpdfapi/render/cpdf_transferfunc.h +++ b/core/fpdfapi/render/cpdf_transferfunc.h @@ -7,18 +7,34 @@ #ifndef CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_ #define CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_ +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" class CPDF_Document; +class CFX_DIBSource; -class CPDF_TransferFunc { +class CPDF_TransferFunc : public Retainable { public: - explicit CPDF_TransferFunc(CPDF_Document* pDoc); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); FX_COLORREF TranslateColor(FX_COLORREF src) const; - CFX_DIBSource* TranslateImage(const CFX_DIBSource* pSrc, bool bAutoDropSrc); + RetainPtr TranslateImage(const RetainPtr& pSrc); + + const CPDF_Document* GetDocument() const { return m_pPDFDoc.Get(); } + + const uint8_t* GetSamples() const { return m_Samples; } + uint8_t* GetSamples() { return m_Samples; } + + bool GetIdentity() const { return m_bIdentity; } + void SetIdentity(bool identity) { m_bIdentity = identity; } + + private: + explicit CPDF_TransferFunc(CPDF_Document* pDoc); + ~CPDF_TransferFunc() override; - CPDF_Document* const m_pPDFDoc; + UnownedPtr const m_pPDFDoc; bool m_bIdentity; uint8_t m_Samples[256 * 3]; }; diff --git a/core/fpdfapi/render/cpdf_type3cache.cpp b/core/fpdfapi/render/cpdf_type3cache.cpp index 63cc780d1d43a7a1df90097a6d353ca63679b74f..fe9dfbf9e04dc6ff7c86ff62e98080770ca9bf0b 100644 --- a/core/fpdfapi/render/cpdf_type3cache.cpp +++ b/core/fpdfapi/render/cpdf_type3cache.cpp @@ -8,18 +8,20 @@ #include #include +#include #include "core/fpdfapi/font/cpdf_type3char.h" #include "core/fpdfapi/font/cpdf_type3font.h" #include "core/fpdfapi/render/cpdf_type3glyphs.h" #include "core/fxge/fx_dib.h" #include "core/fxge/fx_font.h" +#include "third_party/base/ptr_util.h" namespace { struct CPDF_UniqueKeyGen { void Generate(int count, ...); - FX_CHAR m_Key[128]; + char m_Key[128]; int m_KeyLen; }; @@ -51,7 +53,7 @@ bool IsScanLine8bpp(uint8_t* pBuf, int width) { return false; } -int DetectFirstLastScan(const CFX_DIBitmap* pBitmap, bool bFirst) { +int DetectFirstLastScan(const RetainPtr& pBitmap, bool bFirst) { int height = pBitmap->GetHeight(); int pitch = pBitmap->GetPitch(); int width = pBitmap->GetWidth(); @@ -79,74 +81,75 @@ int DetectFirstLastScan(const CFX_DIBitmap* pBitmap, bool bFirst) { CPDF_Type3Cache::CPDF_Type3Cache(CPDF_Type3Font* pFont) : m_pFont(pFont) {} -CPDF_Type3Cache::~CPDF_Type3Cache() { - for (const auto& pair : m_SizeMap) - delete pair.second; - m_SizeMap.clear(); -} +CPDF_Type3Cache::~CPDF_Type3Cache() {} CFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(uint32_t charcode, const CFX_Matrix* pMatrix, - FX_FLOAT retinaScaleX, - FX_FLOAT retinaScaleY) { + float retinaScaleX, + float retinaScaleY) { CPDF_UniqueKeyGen keygen; keygen.Generate( 4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000), FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000)); - CFX_ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); + ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); CPDF_Type3Glyphs* pSizeCache; auto it = m_SizeMap.find(FaceGlyphsKey); if (it == m_SizeMap.end()) { - pSizeCache = new CPDF_Type3Glyphs; - m_SizeMap[FaceGlyphsKey] = pSizeCache; + auto pNew = pdfium::MakeUnique(); + pSizeCache = pNew.get(); + m_SizeMap[FaceGlyphsKey] = std::move(pNew); } else { - pSizeCache = it->second; + pSizeCache = it->second.get(); } auto it2 = pSizeCache->m_GlyphMap.find(charcode); if (it2 != pSizeCache->m_GlyphMap.end()) - return it2->second; + return it2->second.get(); - CFX_GlyphBitmap* pGlyphBitmap = + std::unique_ptr pNewBitmap = RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY); - pSizeCache->m_GlyphMap[charcode] = pGlyphBitmap; + CFX_GlyphBitmap* pGlyphBitmap = pNewBitmap.get(); + pSizeCache->m_GlyphMap[charcode] = std::move(pNewBitmap); return pGlyphBitmap; } -CFX_GlyphBitmap* CPDF_Type3Cache::RenderGlyph(CPDF_Type3Glyphs* pSize, - uint32_t charcode, - const CFX_Matrix* pMatrix, - FX_FLOAT retinaScaleX, - FX_FLOAT retinaScaleY) { +std::unique_ptr CPDF_Type3Cache::RenderGlyph( + CPDF_Type3Glyphs* pSize, + uint32_t charcode, + const CFX_Matrix* pMatrix, + float retinaScaleX, + float retinaScaleY) { const CPDF_Type3Char* pChar = m_pFont->LoadChar(charcode); - if (!pChar || !pChar->m_pBitmap) + if (!pChar || !pChar->GetBitmap()) return nullptr; - CFX_DIBitmap* pBitmap = pChar->m_pBitmap.get(); - CFX_Matrix image_matrix = pChar->m_ImageMatrix; CFX_Matrix text_matrix(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d, 0, 0); + CFX_Matrix image_matrix = pChar->matrix(); image_matrix.Concat(text_matrix); - std::unique_ptr pResBitmap; + RetainPtr pBitmap = pChar->GetBitmap(); + RetainPtr pResBitmap; int left = 0; int top = 0; - if (FXSYS_fabs(image_matrix.b) < FXSYS_fabs(image_matrix.a) / 100 && - FXSYS_fabs(image_matrix.c) < FXSYS_fabs(image_matrix.d) / 100) { + if (fabs(image_matrix.b) < fabs(image_matrix.a) / 100 && + fabs(image_matrix.c) < fabs(image_matrix.d) / 100) { int top_line = DetectFirstLastScan(pBitmap, true); int bottom_line = DetectFirstLastScan(pBitmap, false); if (top_line == 0 && bottom_line == pBitmap->GetHeight() - 1) { - FX_FLOAT top_y = image_matrix.d + image_matrix.f; - FX_FLOAT bottom_y = image_matrix.f; + float top_y = image_matrix.d + image_matrix.f; + float bottom_y = image_matrix.f; bool bFlipped = top_y > bottom_y; if (bFlipped) { - FX_FLOAT temp = top_y; + float temp = top_y; top_y = bottom_y; bottom_y = temp; } pSize->AdjustBlue(top_y, bottom_y, top_line, bottom_line); pResBitmap = pBitmap->StretchTo( - (int)(FXSYS_round(image_matrix.a) * retinaScaleX), - (int)((bFlipped ? top_line - bottom_line : bottom_line - top_line) * - retinaScaleY)); + static_cast(FXSYS_round(image_matrix.a) * retinaScaleX), + static_cast( + (bFlipped ? top_line - bottom_line : bottom_line - top_line) * + retinaScaleY), + 0, nullptr); top = top_line; if (image_matrix.a < 0) { image_matrix.Scale(retinaScaleX, retinaScaleY); @@ -158,14 +161,14 @@ CFX_GlyphBitmap* CPDF_Type3Cache::RenderGlyph(CPDF_Type3Glyphs* pSize, } if (!pResBitmap) { image_matrix.Scale(retinaScaleX, retinaScaleY); - pResBitmap = pBitmap->TransformTo(&image_matrix, left, top); + pResBitmap = pBitmap->TransformTo(&image_matrix, &left, &top); } if (!pResBitmap) return nullptr; - CFX_GlyphBitmap* pGlyph = new CFX_GlyphBitmap; + auto pGlyph = pdfium::MakeUnique(); pGlyph->m_Left = left; pGlyph->m_Top = -top; - pGlyph->m_Bitmap.TakeOver(pResBitmap.get()); + pGlyph->m_pBitmap->TakeOver(std::move(pResBitmap)); return pGlyph; } diff --git a/core/fpdfapi/render/cpdf_type3cache.h b/core/fpdfapi/render/cpdf_type3cache.h index f74a43acc5702d3fbe60c9ab99c1821ad31a2914..7911785ab13fb0931e4a44d16c7c5f8c2a1dd43b 100644 --- a/core/fpdfapi/render/cpdf_type3cache.h +++ b/core/fpdfapi/render/cpdf_type3cache.h @@ -8,33 +8,38 @@ #define CORE_FPDFAPI_RENDER_CPDF_TYPE3CACHE_H_ #include +#include #include "core/fpdfapi/font/cpdf_type3font.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" class CPDF_Type3Glyphs; -class CPDF_Type3Cache { +class CPDF_Type3Cache : public Retainable { public: - explicit CPDF_Type3Cache(CPDF_Type3Font* pFont); - ~CPDF_Type3Cache(); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); CFX_GlyphBitmap* LoadGlyph(uint32_t charcode, const CFX_Matrix* pMatrix, - FX_FLOAT retinaScaleX, - FX_FLOAT retinaScaleY); + float retinaScaleX, + float retinaScaleY); private: - CFX_GlyphBitmap* RenderGlyph(CPDF_Type3Glyphs* pSize, - uint32_t charcode, - const CFX_Matrix* pMatrix, - FX_FLOAT retinaScaleX, - FX_FLOAT retinaScaleY); - - CPDF_Type3Font* const m_pFont; - std::map m_SizeMap; + explicit CPDF_Type3Cache(CPDF_Type3Font* pFont); + ~CPDF_Type3Cache() override; + + std::unique_ptr RenderGlyph(CPDF_Type3Glyphs* pSize, + uint32_t charcode, + const CFX_Matrix* pMatrix, + float retinaScaleX, + float retinaScaleY); + + UnownedPtr const m_pFont; + std::map> m_SizeMap; }; #endif // CORE_FPDFAPI_RENDER_CPDF_TYPE3CACHE_H_ diff --git a/core/fpdfapi/render/cpdf_type3glyphs.cpp b/core/fpdfapi/render/cpdf_type3glyphs.cpp index 189fc2439d789e817e6f9b5469bfac5aa9079235..01b689f80fda2cdeca794b9ef987522ea6d185cd 100644 --- a/core/fpdfapi/render/cpdf_type3glyphs.cpp +++ b/core/fpdfapi/render/cpdf_type3glyphs.cpp @@ -13,16 +13,13 @@ CPDF_Type3Glyphs::CPDF_Type3Glyphs() : m_TopBlueCount(0), m_BottomBlueCount(0) {} -CPDF_Type3Glyphs::~CPDF_Type3Glyphs() { - for (const auto& pair : m_GlyphMap) - delete pair.second; -} +CPDF_Type3Glyphs::~CPDF_Type3Glyphs() {} -static int _AdjustBlue(FX_FLOAT pos, int& count, int blues[]) { - FX_FLOAT min_distance = 1000000.0f; +static int _AdjustBlue(float pos, int& count, int blues[]) { + float min_distance = 1000000.0f; int closest_pos = -1; for (int i = 0; i < count; i++) { - FX_FLOAT distance = FXSYS_fabs(pos - static_cast(blues[i])); + float distance = fabs(pos - static_cast(blues[i])); if (distance < 1.0f * 80.0f / 100.0f && distance < min_distance) { min_distance = distance; closest_pos = i; @@ -37,8 +34,8 @@ static int _AdjustBlue(FX_FLOAT pos, int& count, int blues[]) { return new_pos; } -void CPDF_Type3Glyphs::AdjustBlue(FX_FLOAT top, - FX_FLOAT bottom, +void CPDF_Type3Glyphs::AdjustBlue(float top, + float bottom, int& top_line, int& bottom_line) { top_line = _AdjustBlue(top, m_TopBlueCount, m_TopBlue); diff --git a/core/fpdfapi/render/cpdf_type3glyphs.h b/core/fpdfapi/render/cpdf_type3glyphs.h index 00814d5b3bfa2cbd3e045f20bb7523adf2193e6f..778b639642d6afb3405561770beed114b78a01e0 100644 --- a/core/fpdfapi/render/cpdf_type3glyphs.h +++ b/core/fpdfapi/render/cpdf_type3glyphs.h @@ -8,6 +8,7 @@ #define CORE_FPDFAPI_RENDER_CPDF_TYPE3GLYPHS_H_ #include +#include #include "core/fxcrt/fx_system.h" @@ -20,12 +21,9 @@ class CPDF_Type3Glyphs { CPDF_Type3Glyphs(); ~CPDF_Type3Glyphs(); - void AdjustBlue(FX_FLOAT top, - FX_FLOAT bottom, - int& top_line, - int& bottom_line); + void AdjustBlue(float top, float bottom, int& top_line, int& bottom_line); - std::map m_GlyphMap; + std::map> m_GlyphMap; int m_TopBlue[TYPE3_MAX_BLUES]; int m_BottomBlue[TYPE3_MAX_BLUES]; int m_TopBlueCount; diff --git a/core/fpdfdoc/cline.cpp b/core/fpdfdoc/cline.cpp index 2e8477cfe7214fe47fe228404bb6907724077c4e..a24b81950a2d7a973e53c7587c7dd64dcdfd3787 100644 --- a/core/fpdfdoc/cline.cpp +++ b/core/fpdfdoc/cline.cpp @@ -8,6 +8,8 @@ CLine::CLine() {} +CLine::CLine(const CPVT_LineInfo& lineinfo) : m_LineInfo(lineinfo) {} + CLine::~CLine() {} CPVT_WordPlace CLine::GetBeginWordPlace() const { diff --git a/core/fpdfdoc/cline.h b/core/fpdfdoc/cline.h index 6f95beb546ebc47bed39ce084cb186b9f25f601a..67bf06b649e8592f2cbb54e68051a4a98bb27e46 100644 --- a/core/fpdfdoc/cline.h +++ b/core/fpdfdoc/cline.h @@ -10,9 +10,10 @@ #include "core/fpdfdoc/cpvt_lineinfo.h" #include "core/fpdfdoc/cpvt_wordplace.h" -class CLine final { +class CLine { public: CLine(); + explicit CLine(const CPVT_LineInfo& lineinfo); ~CLine(); CPVT_WordPlace GetBeginWordPlace() const; diff --git a/core/fpdfdoc/clines.cpp b/core/fpdfdoc/clines.cpp deleted file mode 100644 index 1e425eab932b1351dc04c87a7ee3a0234c3574d8..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/clines.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 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 "core/fpdfdoc/clines.h" - -#include "core/fpdfdoc/cline.h" - -CLines::CLines() : m_nTotal(0) {} - -CLines::~CLines() { - RemoveAll(); -} - -int32_t CLines::GetSize() const { - return m_Lines.GetSize(); -} - -CLine* CLines::GetAt(int32_t nIndex) const { - return m_Lines.GetAt(nIndex); -} - -void CLines::Empty() { - m_nTotal = 0; -} - -void CLines::RemoveAll() { - for (int32_t i = 0, sz = GetSize(); i < sz; i++) - delete GetAt(i); - m_Lines.RemoveAll(); - m_nTotal = 0; -} - -int32_t CLines::Add(const CPVT_LineInfo& lineinfo) { - if (m_nTotal >= GetSize()) { - CLine* pLine = new CLine; - pLine->m_LineInfo = lineinfo; - m_Lines.Add(pLine); - } else if (CLine* pLine = GetAt(m_nTotal)) { - pLine->m_LineInfo = lineinfo; - } - return m_nTotal++; -} - -void CLines::Clear() { - for (int32_t i = GetSize() - 1; i >= m_nTotal; i--) { - delete GetAt(i); - m_Lines.RemoveAt(i); - } -} diff --git a/core/fpdfdoc/clines.h b/core/fpdfdoc/clines.h deleted file mode 100644 index b4db0e39666d71cebfe21cc413fb617d082d3b8d..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/clines.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CLINES_H_ -#define CORE_FPDFDOC_CLINES_H_ - -#include - -#include "core/fpdfdoc/cpvt_arraytemplate.h" -#include "core/fpdfdoc/cpvt_lineinfo.h" - -class CLine; - -class CLines final { - public: - CLines(); - ~CLines(); - - int32_t GetSize() const; - CLine* GetAt(int32_t nIndex) const; - - void Empty(); - void RemoveAll(); - int32_t Add(const CPVT_LineInfo& lineinfo); - void Clear(); - - private: - CPVT_ArrayTemplate m_Lines; - int32_t m_nTotal; -}; - -#endif // CORE_FPDFDOC_CLINES_H_ diff --git a/core/fpdfdoc/cpdf_aaction.cpp b/core/fpdfdoc/cpdf_aaction.cpp index 39120fcdb3336c00b28d3d948a52867717d33640..2628ca009e86dfc1b97d1b32235cb6f778faafd0 100644 --- a/core/fpdfdoc/cpdf_aaction.cpp +++ b/core/fpdfdoc/cpdf_aaction.cpp @@ -8,17 +8,47 @@ namespace { -const FX_CHAR* g_sAATypes[] = {"E", "X", "D", "U", "Fo", "Bl", "PO", "PC", - "PV", "PI", "O", "C", "K", "F", "V", "C", - "WC", "WS", "DS", "WP", "DP", ""}; +constexpr const char* g_sAATypes[] = { + "E", // CursorEnter + "X", // CursorExit + "D", // ButtonDown + "U", // ButtonUp + "Fo", // GetFocus + "Bl", // LoseFocus + "PO", // PageOpen + "PC", // PageClose + "PV", // PageVisible + "PI", // PageInvisible + "O", // OpenPage + "C", // ClosePage + "K", // KeyStroke + "F", // Format + "V", // Validate + "C", // Calculate + "WC", // CloseDocument + "WS", // SaveDocument + "DS", // DocumentSaved + "WP", // PrintDocument + "DP", // DocumentPrinted +}; + +// |g_sAATypes| should have as many elements as enum AActionType. +static_assert(FX_ArraySize(g_sAATypes) == CPDF_AAction::NumberOfActions, + "g_sAATypes count mismatch"); } // namespace +CPDF_AAction::CPDF_AAction(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + +CPDF_AAction::CPDF_AAction(const CPDF_AAction& that) = default; + +CPDF_AAction::~CPDF_AAction() {} + bool CPDF_AAction::ActionExist(AActionType eType) const { return m_pDict && m_pDict->KeyExist(g_sAATypes[eType]); } CPDF_Action CPDF_AAction::GetAction(AActionType eType) const { - return m_pDict ? CPDF_Action(m_pDict->GetDictFor(g_sAATypes[eType])) - : CPDF_Action(); + return CPDF_Action(m_pDict ? m_pDict->GetDictFor(g_sAATypes[eType]) + : nullptr); } diff --git a/core/fpdfdoc/cpdf_aaction.h b/core/fpdfdoc/cpdf_aaction.h index d615915ee348d31de0083ce3c49e0319c4cafbcf..a5b0d25525e6f02453d2afdf62d23623e08aea7f 100644 --- a/core/fpdfdoc/cpdf_aaction.h +++ b/core/fpdfdoc/cpdf_aaction.h @@ -34,18 +34,20 @@ class CPDF_AAction { SaveDocument, DocumentSaved, PrintDocument, - DocumentPrinted + DocumentPrinted, + NumberOfActions // Must be last. }; - CPDF_AAction() : m_pDict(nullptr) {} - explicit CPDF_AAction(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + explicit CPDF_AAction(CPDF_Dictionary* pDict); + CPDF_AAction(const CPDF_AAction& that); + ~CPDF_AAction(); bool ActionExist(AActionType eType) const; CPDF_Action GetAction(AActionType eType) const; - CPDF_Dictionary* GetDict() const { return m_pDict; } + CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } private: - CPDF_Dictionary* const m_pDict; + UnownedPtr const m_pDict; }; #endif // CORE_FPDFDOC_CPDF_AACTION_H_ diff --git a/core/fpdfdoc/cpdf_action.cpp b/core/fpdfdoc/cpdf_action.cpp index dabc0bb10280a8f6201c1960ed69e52bb82264cb..383f328b9fe163730f33bc85a38133e09c3bc230 100644 --- a/core/fpdfdoc/cpdf_action.cpp +++ b/core/fpdfdoc/cpdf_action.cpp @@ -13,7 +13,7 @@ namespace { -const FX_CHAR* const g_sATypes[] = { +const char* const g_sATypes[] = { "Unknown", "GoTo", "GoToR", "GoToE", "Launch", "Thread", "URI", "Sound", "Movie", "Hide", "Named", "SubmitForm", "ResetForm", "ImportData", "JavaScript", @@ -21,11 +21,17 @@ const FX_CHAR* const g_sATypes[] = { } // namespace +CPDF_Action::CPDF_Action(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + +CPDF_Action::CPDF_Action(const CPDF_Action& that) = default; + +CPDF_Action::~CPDF_Action() {} + CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const { if (!m_pDict) return CPDF_Dest(); - CFX_ByteString type = m_pDict->GetStringFor("S"); + ByteString type = m_pDict->GetStringFor("S"); if (type != "GoTo" && type != "GoToR") return CPDF_Dest(); @@ -34,7 +40,7 @@ CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const { return CPDF_Dest(); if (pDest->IsString() || pDest->IsName()) { CPDF_NameTree name_tree(pDoc, "Dests"); - return CPDF_Dest(name_tree.LookupNamedDest(pDoc, pDest->GetString())); + return CPDF_Dest(name_tree.LookupNamedDest(pDoc, pDest->GetUnicodeText())); } if (CPDF_Array* pArray = pDest->AsArray()) return CPDF_Dest(pArray); @@ -46,7 +52,7 @@ CPDF_Action::ActionType CPDF_Action::GetType() const { if (!m_pDict) return Unknown; - CFX_ByteString csType = m_pDict->GetStringFor("S"); + ByteString csType = m_pDict->GetStringFor("S"); if (csType.IsEmpty()) return Unknown; @@ -57,50 +63,46 @@ CPDF_Action::ActionType CPDF_Action::GetType() const { return Unknown; } -CFX_WideString CPDF_Action::GetFilePath() const { - CFX_ByteString type = m_pDict->GetStringFor("S"); +WideString CPDF_Action::GetFilePath() const { + ByteString type = m_pDict->GetStringFor("S"); if (type != "GoToR" && type != "Launch" && type != "SubmitForm" && type != "ImportData") { - return CFX_WideString(); + return WideString(); } CPDF_Object* pFile = m_pDict->GetDirectObjectFor("F"); - CFX_WideString path; - if (!pFile) { - if (type == "Launch") { - CPDF_Dictionary* pWinDict = m_pDict->GetDictFor("Win"); - if (pWinDict) { - return CFX_WideString::FromLocal( - pWinDict->GetStringFor("F").AsStringC()); - } + if (pFile) + return CPDF_FileSpec(pFile).GetFileName(); + + if (type == "Launch") { + CPDF_Dictionary* pWinDict = m_pDict->GetDictFor("Win"); + if (pWinDict) { + return WideString::FromLocal(pWinDict->GetStringFor("F").AsStringView()); } - return path; } - - CPDF_FileSpec filespec(pFile); - filespec.GetFileName(&path); - return path; + return WideString(); } -CFX_ByteString CPDF_Action::GetURI(CPDF_Document* pDoc) const { - CFX_ByteString csURI; +ByteString CPDF_Action::GetURI(const CPDF_Document* pDoc) const { + ByteString csURI; if (!m_pDict) return csURI; if (m_pDict->GetStringFor("S") != "URI") return csURI; csURI = m_pDict->GetStringFor("URI"); - CPDF_Dictionary* pRoot = pDoc->GetRoot(); + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); CPDF_Dictionary* pURI = pRoot->GetDictFor("URI"); if (pURI) { - if (csURI.Find(":", 0) < 1) + auto result = csURI.Find(":"); + if (!result.has_value() || result.value() == 0) csURI = pURI->GetStringFor("Base") + csURI; } return csURI; } -CFX_WideString CPDF_Action::GetJavaScript() const { - CFX_WideString csJS; +WideString CPDF_Action::GetJavaScript() const { + WideString csJS; if (!m_pDict) return csJS; @@ -124,14 +126,14 @@ size_t CPDF_Action::GetSubActionsCount() const { CPDF_Action CPDF_Action::GetSubAction(size_t iIndex) const { if (!m_pDict || !m_pDict->KeyExist("Next")) - return CPDF_Action(); + return CPDF_Action(nullptr); CPDF_Object* pNext = m_pDict->GetDirectObjectFor("Next"); + if (CPDF_Array* pArray = ToArray(pNext)) + return CPDF_Action(pArray->GetDictAt(iIndex)); if (CPDF_Dictionary* pDict = ToDictionary(pNext)) { if (iIndex == 0) return CPDF_Action(pDict); - } else if (CPDF_Array* pArray = ToArray(pNext)) { - return CPDF_Action(pArray->GetDictAt(iIndex)); } - return CPDF_Action(); + return CPDF_Action(nullptr); } diff --git a/core/fpdfdoc/cpdf_action.h b/core/fpdfdoc/cpdf_action.h index 426edb12e93c47f8281b0445152f1c357dc72f34..1d9b722f4015ce69eefb4128801930f006fb2c8f 100644 --- a/core/fpdfdoc/cpdf_action.h +++ b/core/fpdfdoc/cpdf_action.h @@ -37,23 +37,24 @@ class CPDF_Action { GoTo3DView }; - CPDF_Action() : m_pDict(nullptr) {} - explicit CPDF_Action(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + explicit CPDF_Action(CPDF_Dictionary* pDict); + CPDF_Action(const CPDF_Action& that); + ~CPDF_Action(); - CPDF_Dictionary* GetDict() const { return m_pDict; } + CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } ActionType GetType() const; CPDF_Dest GetDest(CPDF_Document* pDoc) const; - CFX_WideString GetFilePath() const; - CFX_ByteString GetURI(CPDF_Document* pDoc) const; + WideString GetFilePath() const; + ByteString GetURI(const CPDF_Document* pDoc) const; bool GetHideStatus() const { return m_pDict->GetBooleanFor("H", true); } - CFX_ByteString GetNamedAction() const { return m_pDict->GetStringFor("N"); } + ByteString GetNamedAction() const { return m_pDict->GetStringFor("N"); } uint32_t GetFlags() const { return m_pDict->GetIntegerFor("Flags"); } - CFX_WideString GetJavaScript() const; + WideString GetJavaScript() const; size_t GetSubActionsCount() const; CPDF_Action GetSubAction(size_t iIndex) const; private: - CPDF_Dictionary* const m_pDict; + UnownedPtr const m_pDict; }; #endif // CORE_FPDFDOC_CPDF_ACTION_H_ diff --git a/core/fpdfdoc/cpdf_actionfields.cpp b/core/fpdfdoc/cpdf_actionfields.cpp index 35ec92c1b870a0b21d802bc820110f3020421bf1..cee256d3fbc8a534bbef85db6e851fcfb27ef133 100644 --- a/core/fpdfdoc/cpdf_actionfields.cpp +++ b/core/fpdfdoc/cpdf_actionfields.cpp @@ -10,6 +10,11 @@ #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfdoc/cpdf_action.h" +CPDF_ActionFields::CPDF_ActionFields(const CPDF_Action* pAction) + : m_pAction(pAction) {} + +CPDF_ActionFields::~CPDF_ActionFields() {} + size_t CPDF_ActionFields::GetFieldsCount() const { if (!m_pAction) return 0; @@ -18,7 +23,7 @@ size_t CPDF_ActionFields::GetFieldsCount() const { if (!pDict) return 0; - CFX_ByteString csType = pDict->GetStringFor("S"); + ByteString csType = pDict->GetStringFor("S"); CPDF_Object* pFields = nullptr; if (csType == "Hide") pFields = pDict->GetDirectObjectFor("T"); @@ -45,7 +50,7 @@ std::vector CPDF_ActionFields::GetAllFields() const { if (!pDict) return fields; - CFX_ByteString csType = pDict->GetStringFor("S"); + ByteString csType = pDict->GetStringFor("S"); CPDF_Object* pFields; if (csType == "Hide") pFields = pDict->GetDirectObjectFor("T"); @@ -75,7 +80,7 @@ CPDF_Object* CPDF_ActionFields::GetField(size_t iIndex) const { if (!pDict) return nullptr; - CFX_ByteString csType = pDict->GetStringFor("S"); + ByteString csType = pDict->GetStringFor("S"); CPDF_Object* pFields = nullptr; if (csType == "Hide") pFields = pDict->GetDirectObjectFor("T"); diff --git a/core/fpdfdoc/cpdf_actionfields.h b/core/fpdfdoc/cpdf_actionfields.h index 9e0664cadb562e6348e191d96b2427ae14e22a7a..83c70f6375c092efd4d33a2dd7def58feb636d85 100644 --- a/core/fpdfdoc/cpdf_actionfields.h +++ b/core/fpdfdoc/cpdf_actionfields.h @@ -11,19 +11,22 @@ #include +#include "core/fxcrt/unowned_ptr.h" + class CPDF_Action; class CPDF_Object; class CPDF_ActionFields { public: - explicit CPDF_ActionFields(const CPDF_Action* pAction) : m_pAction(pAction) {} + explicit CPDF_ActionFields(const CPDF_Action* pAction); + ~CPDF_ActionFields(); size_t GetFieldsCount() const; std::vector GetAllFields() const; CPDF_Object* GetField(size_t iIndex) const; private: - const CPDF_Action* const m_pAction; + UnownedPtr const m_pAction; }; #endif // CORE_FPDFDOC_CPDF_ACTIONFIELDS_H_ diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp index 89c4785d982a3789f9676466c086cff6b6606bf3..02df3cff601a389ca708bc4221419e2341166755 100644 --- a/core/fpdfdoc/cpdf_annot.cpp +++ b/core/fpdfdoc/cpdf_annot.cpp @@ -34,9 +34,10 @@ bool IsTextMarkupAnnotation(CPDF_Annot::Subtype type) { } bool ShouldGenerateAPForAnnotation(CPDF_Dictionary* pAnnotDict) { - // If AP dictionary exists, we use the appearance defined in the - // existing AP dictionary. - if (pAnnotDict->KeyExist("AP")) + // If AP dictionary exists and defines an appearance for normal mode, we use + // the appearance defined in the existing AP dictionary. + CPDF_Dictionary* pAP = pAnnotDict->GetDictFor("AP"); + if (pAP && pAP->GetDictFor("N")) return false; return !CPDF_Annot::IsAnnotationHidden(pAnnotDict); @@ -51,14 +52,51 @@ CPDF_Form* AnnotGetMatrix(const CPDF_Page* pPage, if (!pForm) return nullptr; - CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRectFor("BBox"); CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrixFor("Matrix"); - form_matrix.TransformRect(form_bbox); + CFX_FloatRect form_bbox = + form_matrix.TransformRect(pForm->m_pFormDict->GetRectFor("BBox")); matrix->MatchRect(pAnnot->GetRect(), form_bbox); matrix->Concat(*pUser2Device); return pForm; } +CPDF_Stream* FPDFDOC_GetAnnotAPInternal(const CPDF_Dictionary* pAnnotDict, + CPDF_Annot::AppearanceMode eMode, + bool bFallbackToNormal) { + CPDF_Dictionary* pAP = pAnnotDict->GetDictFor("AP"); + if (!pAP) + return nullptr; + + const char* ap_entry = "N"; + if (eMode == CPDF_Annot::Down) + ap_entry = "D"; + else if (eMode == CPDF_Annot::Rollover) + ap_entry = "R"; + if (bFallbackToNormal && !pAP->KeyExist(ap_entry)) + ap_entry = "N"; + + CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry); + if (!psub) + return nullptr; + if (CPDF_Stream* pStream = psub->AsStream()) + return pStream; + + CPDF_Dictionary* pDict = psub->AsDictionary(); + if (!pDict) + return nullptr; + + ByteString as = pAnnotDict->GetStringFor("AS"); + if (as.IsEmpty()) { + ByteString value = pAnnotDict->GetStringFor("V"); + if (value.IsEmpty()) { + CPDF_Dictionary* pParentDict = pAnnotDict->GetDictFor("Parent"); + value = pParentDict ? pParentDict->GetStringFor("V") : ByteString(); + } + as = (!value.IsEmpty() && pDict->KeyExist(value)) ? value : "Off"; + } + return pDict->GetStreamFor(as); +} + } // namespace CPDF_Annot::CPDF_Annot(std::unique_ptr pDict, @@ -86,32 +124,13 @@ void CPDF_Annot::Init() { void CPDF_Annot::GenerateAPIfNeeded() { if (!ShouldGenerateAPForAnnotation(m_pAnnotDict.Get())) return; - - CPDF_Dictionary* pDict = m_pAnnotDict.Get(); - bool result = false; - if (m_nSubtype == CPDF_Annot::Subtype::CIRCLE) - result = CPVT_GenerateAP::GenerateCircleAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::HIGHLIGHT) - result = CPVT_GenerateAP::GenerateHighlightAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::INK) - result = CPVT_GenerateAP::GenerateInkAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::POPUP) - result = CPVT_GenerateAP::GeneratePopupAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::SQUARE) - result = CPVT_GenerateAP::GenerateSquareAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::SQUIGGLY) - result = CPVT_GenerateAP::GenerateSquigglyAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::STRIKEOUT) - result = CPVT_GenerateAP::GenerateStrikeOutAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::TEXT) - result = CPVT_GenerateAP::GenerateTextAP(m_pDocument, pDict); - else if (m_nSubtype == CPDF_Annot::Subtype::UNDERLINE) - result = CPVT_GenerateAP::GenerateUnderlineAP(m_pDocument, pDict); - - if (result) { - m_pAnnotDict->SetNewFor(kPDFiumKey_HasGeneratedAP, result); - m_bHasGeneratedAP = result; + if (!CPVT_GenerateAP::GenerateAnnotAP(m_nSubtype, m_pDocument.Get(), + m_pAnnotDict.Get())) { + return; } + + m_pAnnotDict->SetNewFor(kPDFiumKey_HasGeneratedAP, true); + m_bHasGeneratedAP = true; } bool CPDF_Annot::ShouldDrawAnnotation() { @@ -157,42 +176,14 @@ uint32_t CPDF_Annot::GetFlags() const { return m_pAnnotDict->GetIntegerFor("F"); } -CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, - CPDF_Annot::AppearanceMode mode) { - CPDF_Dictionary* pAP = pAnnotDict->GetDictFor("AP"); - if (!pAP) { - return nullptr; - } - const FX_CHAR* ap_entry = "N"; - if (mode == CPDF_Annot::Down) - ap_entry = "D"; - else if (mode == CPDF_Annot::Rollover) - ap_entry = "R"; - if (!pAP->KeyExist(ap_entry)) - ap_entry = "N"; - - CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry); - if (!psub) - return nullptr; - if (CPDF_Stream* pStream = psub->AsStream()) - return pStream; +CPDF_Stream* FPDFDOC_GetAnnotAP(const CPDF_Dictionary* pAnnotDict, + CPDF_Annot::AppearanceMode eMode) { + return FPDFDOC_GetAnnotAPInternal(pAnnotDict, eMode, true); +} - if (CPDF_Dictionary* pDict = psub->AsDictionary()) { - CFX_ByteString as = pAnnotDict->GetStringFor("AS"); - if (as.IsEmpty()) { - CFX_ByteString value = pAnnotDict->GetStringFor("V"); - if (value.IsEmpty()) { - CPDF_Dictionary* pParentDict = pAnnotDict->GetDictFor("Parent"); - value = pParentDict ? pParentDict->GetStringFor("V") : CFX_ByteString(); - } - if (value.IsEmpty() || !pDict->KeyExist(value)) - as = "Off"; - else - as = value; - } - return pDict->GetStreamFor(as); - } - return nullptr; +CPDF_Stream* FPDFDOC_GetAnnotAPNoFallback(const CPDF_Dictionary* pAnnotDict, + CPDF_Annot::AppearanceMode eMode) { + return FPDFDOC_GetAnnotAPInternal(pAnnotDict, eMode, false); } CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) { @@ -204,9 +195,9 @@ CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) { if (it != m_APMap.end()) return it->second.get(); - auto pNewForm = - pdfium::MakeUnique(m_pDocument, pPage->m_pResources, pStream); - pNewForm->ParseContent(nullptr, nullptr, nullptr); + auto pNewForm = pdfium::MakeUnique( + m_pDocument.Get(), pPage->m_pResources.Get(), pStream); + pNewForm->ParseContent(); CPDF_Form* pResult = pNewForm.get(); m_APMap[pStream] = std::move(pNewForm); @@ -240,7 +231,7 @@ bool CPDF_Annot::IsAnnotationHidden(CPDF_Dictionary* pAnnotDict) { // Static. CPDF_Annot::Subtype CPDF_Annot::StringToAnnotSubtype( - const CFX_ByteString& sSubtype) { + const ByteString& sSubtype) { if (sSubtype == "Text") return CPDF_Annot::Subtype::TEXT; if (sSubtype == "Link") @@ -299,7 +290,7 @@ CPDF_Annot::Subtype CPDF_Annot::StringToAnnotSubtype( } // Static. -CFX_ByteString CPDF_Annot::AnnotSubtypeToString(CPDF_Annot::Subtype nSubtype) { +ByteString CPDF_Annot::AnnotSubtypeToString(CPDF_Annot::Subtype nSubtype) { if (nSubtype == CPDF_Annot::Subtype::TEXT) return "Text"; if (nSubtype == CPDF_Annot::Subtype::LINK) @@ -359,7 +350,7 @@ CFX_ByteString CPDF_Annot::AnnotSubtypeToString(CPDF_Annot::Subtype nSubtype) { bool CPDF_Annot::DrawAppearance(CPDF_Page* pPage, CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, + const CFX_Matrix& mtUser2Device, AppearanceMode mode, const CPDF_RenderOptions* pOptions) { if (!ShouldDrawAnnotation()) @@ -373,7 +364,7 @@ bool CPDF_Annot::DrawAppearance(CPDF_Page* pPage, GenerateAPIfNeeded(); CFX_Matrix matrix; - CPDF_Form* pForm = AnnotGetMatrix(pPage, this, mode, pUser2Device, &matrix); + CPDF_Form* pForm = AnnotGetMatrix(pPage, this, mode, &mtUser2Device, &matrix); if (!pForm) return false; @@ -417,7 +408,7 @@ void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, return; } bool bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || - (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW)); + (pOptions && (pOptions->HasFlag(RENDER_PRINTPREVIEW))); if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { return; } @@ -426,7 +417,7 @@ void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, } CPDF_Dictionary* pBS = m_pAnnotDict->GetDictFor("BS"); char style_char; - FX_FLOAT width; + float width; CPDF_Array* pDashArray = nullptr; if (!pBS) { CPDF_Array* pBorderArray = m_pAnnotDict->GetArrayFor("Border"); @@ -455,7 +446,7 @@ void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, width = 1; } } else { - CFX_ByteString style = pBS->GetStringFor("S"); + ByteString style = pBS->GetStringFor("S"); pDashArray = pBS->GetArrayFor("D"); style_char = style[1]; width = pBS->GetNumberFor("W"); @@ -479,7 +470,7 @@ void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, if (dash_count % 2) { dash_count++; } - graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count); + graph_state.m_DashArray = FX_Alloc(float, dash_count); graph_state.m_DashCount = dash_count; size_t i; for (i = 0; i < pDashArray->GetCount(); ++i) { @@ -489,7 +480,7 @@ void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1]; } } else { - graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2); + graph_state.m_DashArray = FX_Alloc(float, 2); graph_state.m_DashCount = 2; graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f; } @@ -500,7 +491,7 @@ void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width, rect.top - width); int fill_type = 0; - if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) + if (pOptions && (pOptions->HasFlag(RENDER_NOPATHSMOOTH))) fill_type |= FXFILL_NOPATHSMOOTH; pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type); diff --git a/core/fpdfdoc/cpdf_annot.h b/core/fpdfdoc/cpdf_annot.h index 188106acdf681761a8e659112ee5c59c3cf7ca25..499c62dcba8976e841f917a4e09ad2c4e6859545 100644 --- a/core/fpdfdoc/cpdf_annot.h +++ b/core/fpdfdoc/cpdf_annot.h @@ -10,10 +10,10 @@ #include #include -#include "core/fxcrt/cfx_maybe_owned.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/maybe_owned.h" class CFX_RenderDevice; class CPDF_Dictionary; @@ -27,12 +27,7 @@ class CPDF_Stream; #define ANNOTFLAG_INVISIBLE 0x0001 #define ANNOTFLAG_HIDDEN 0x0002 #define ANNOTFLAG_PRINT 0x0004 -#define ANNOTFLAG_NOZOOM 0x0008 -#define ANNOTFLAG_NOROTATE 0x0010 #define ANNOTFLAG_NOVIEW 0x0020 -#define ANNOTFLAG_READONLY 0x0040 -#define ANNOTFLAG_LOCKED 0x0080 -#define ANNOTFLAG_TOGGLENOVIEW 0x0100 class CPDF_Annot { public: @@ -69,9 +64,8 @@ class CPDF_Annot { }; static bool IsAnnotationHidden(CPDF_Dictionary* pAnnotDict); - static CPDF_Annot::Subtype StringToAnnotSubtype( - const CFX_ByteString& sSubtype); - static CFX_ByteString AnnotSubtypeToString(CPDF_Annot::Subtype nSubtype); + static CPDF_Annot::Subtype StringToAnnotSubtype(const ByteString& sSubtype); + static ByteString AnnotSubtypeToString(CPDF_Annot::Subtype nSubtype); static CFX_FloatRect RectFromQuadPoints(CPDF_Dictionary* pAnnotDict); // The second constructor does not take ownership of the dictionary. @@ -82,12 +76,12 @@ class CPDF_Annot { CPDF_Annot::Subtype GetSubtype() const; uint32_t GetFlags() const; CFX_FloatRect GetRect() const; - CPDF_Document* GetDocument() const { return m_pDocument; } + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } CPDF_Dictionary* GetAnnotDict() const { return m_pAnnotDict.Get(); } bool DrawAppearance(CPDF_Page* pPage, CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, + const CFX_Matrix& mtUser2Device, AppearanceMode mode, const CPDF_RenderOptions* pOptions); bool DrawInContext(const CPDF_Page* pPage, @@ -111,8 +105,8 @@ class CPDF_Annot { CFX_FloatRect RectForDrawing() const; - CFX_MaybeOwned m_pAnnotDict; - CPDF_Document* const m_pDocument; + MaybeOwned m_pAnnotDict; + UnownedPtr const m_pDocument; CPDF_Annot::Subtype m_nSubtype; std::map> m_APMap; // |m_bOpenState| is only set for popup annotations. @@ -124,7 +118,15 @@ class CPDF_Annot { CPDF_Annot* m_pPopupAnnot = nullptr; }; -CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, - CPDF_Annot::AppearanceMode mode); +// Get the AP in an annotation dict for a given appearance mode. +// If |eMode| is not Normal and there is not AP for that mode, falls back to +// the Normal AP. +CPDF_Stream* FPDFDOC_GetAnnotAP(const CPDF_Dictionary* pAnnotDict, + CPDF_Annot::AppearanceMode eMode); + +// Get the AP in an annotation dict for a given appearance mode. +// No fallbacks to Normal like in FPDFDOC_GetAnnotAP. +CPDF_Stream* FPDFDOC_GetAnnotAPNoFallback(const CPDF_Dictionary* pAnnotDict, + CPDF_Annot::AppearanceMode eMode); #endif // CORE_FPDFDOC_CPDF_ANNOT_H_ diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp index ed1b60c287866d1d047ab0ea6e80f190c374c899..192649d4a437c6dd150f122c226939687c0b7b96 100644 --- a/core/fpdfdoc/cpdf_annotlist.cpp +++ b/core/fpdfdoc/cpdf_annotlist.cpp @@ -6,10 +6,12 @@ #include "core/fpdfdoc/cpdf_annotlist.h" +#include #include #include #include "core/fpdfapi/page/cpdf_page.h" +#include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_number.h" @@ -26,14 +28,15 @@ namespace { std::unique_ptr CreatePopupAnnot(CPDF_Annot* pAnnot, - CPDF_Document* pDocument) { + CPDF_Document* pDocument, + CPDF_Page* pPage) { CPDF_Dictionary* pParentDict = pAnnot->GetAnnotDict(); if (!pParentDict) return nullptr; // TODO(jaepark): We shouldn't strip BOM for some strings and not for others. // See pdfium:593. - CFX_WideString sContents = pParentDict->GetUnicodeTextFor("Contents"); + WideString sContents = pParentDict->GetUnicodeTextFor("Contents"); if (sContents.IsEmpty()) return nullptr; @@ -48,7 +51,20 @@ std::unique_ptr CreatePopupAnnot(CPDF_Annot* pAnnot, CFX_FloatRect rect = pParentDict->GetRectFor("Rect"); rect.Normalize(); CFX_FloatRect popupRect(0, 0, 200, 200); - popupRect.Translate(rect.left, rect.bottom - popupRect.Height()); + // Note that if the popup can set its own dimensions, then we will need to + // make sure that it isn't larger than the page size. + if (rect.left + popupRect.Width() > pPage->GetPageWidth() && + rect.bottom - popupRect.Height() < 0) { + // If the annotation is on the bottom-right corner of the page, then place + // the popup above and to the left of the annotation. + popupRect.Translate(rect.right - popupRect.Width(), rect.top); + } else { + // Place the popup below and to the right of the annotation without getting + // clipped by page edges. + popupRect.Translate( + std::min(rect.left, pPage->GetPageWidth() - popupRect.Width()), + std::max(rect.bottom - popupRect.Height(), 0.f)); + } pAnnotDict->SetRectFor("Rect", popupRect); pAnnotDict->SetNewFor("F", 0); @@ -59,10 +75,51 @@ std::unique_ptr CreatePopupAnnot(CPDF_Annot* pAnnot, return pPopupAnnot; } +void GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + if (!pAnnotDict || pAnnotDict->GetStringFor("Subtype") != "Widget") + return; + + CPDF_Object* pFieldTypeObj = FPDF_GetFieldAttr(pAnnotDict, "FT"); + if (!pFieldTypeObj) + return; + + ByteString field_type = pFieldTypeObj->GetString(); + if (field_type == "Tx") { + CPVT_GenerateAP::GenerateFormAP(CPVT_GenerateAP::kTextField, pDoc, + pAnnotDict); + return; + } + + CPDF_Object* pFieldFlagsObj = FPDF_GetFieldAttr(pAnnotDict, "Ff"); + uint32_t flags = pFieldFlagsObj ? pFieldFlagsObj->GetInteger() : 0; + if (field_type == "Ch") { + CPVT_GenerateAP::GenerateFormAP((flags & (1 << 17)) + ? CPVT_GenerateAP::kComboBox + : CPVT_GenerateAP::kListBox, + pDoc, pAnnotDict); + return; + } + + if (field_type != "Btn") + return; + if (flags & (1 << 16)) + return; + if (pAnnotDict->KeyExist("AS")) + return; + + CPDF_Dictionary* pParentDict = pAnnotDict->GetDictFor("Parent"); + if (!pParentDict || !pParentDict->KeyExist("AS")) + return; + + pAnnotDict->SetNewFor("AS", pParentDict->GetStringFor("AS"), + false); + return; +} + } // namespace CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) - : m_pDocument(pPage->m_pDocument) { + : m_pDocument(pPage->m_pDocument.Get()) { if (!pPage->m_pFormDict) return; @@ -70,14 +127,14 @@ CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) if (!pAnnots) return; - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + const CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm"); bool bRegenerateAP = pAcroForm && pAcroForm->GetBooleanFor("NeedAppearances"); for (size_t i = 0; i < pAnnots->GetCount(); ++i) { CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i)); if (!pDict) continue; - const CFX_ByteString subtype = pDict->GetStringFor("Subtype"); + const ByteString subtype = pDict->GetStringFor("Subtype"); if (subtype == "Popup") { // Skip creating Popup annotations in the PDF document since PDFium // provides its own Popup annotations. @@ -86,15 +143,15 @@ CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) pAnnots->ConvertToIndirectObjectAt(i, m_pDocument); m_AnnotList.push_back(pdfium::MakeUnique(pDict, m_pDocument)); if (bRegenerateAP && subtype == "Widget" && - CPDF_InterForm::IsUpdateAPEnabled()) { - FPDF_GenerateAP(m_pDocument, pDict); + CPDF_InterForm::IsUpdateAPEnabled() && !pDict->GetDictFor("AP")) { + GenerateAP(m_pDocument, pDict); } } size_t nAnnotListSize = m_AnnotList.size(); for (size_t i = 0; i < nAnnotListSize; ++i) { std::unique_ptr pPopupAnnot( - CreatePopupAnnot(m_AnnotList[i].get(), m_pDocument)); + CreatePopupAnnot(m_AnnotList[i].get(), m_pDocument, pPage)); if (pPopupAnnot) m_AnnotList.push_back(std::move(pPopupAnnot)); } @@ -126,26 +183,25 @@ void CPDF_AnnotList::DisplayPass(CPDF_Page* pPage, continue; if (pOptions) { - CFX_RetainPtr pOCContext = pOptions->m_pOCContext; CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); - if (pOCContext && pAnnotDict && - !pOCContext->CheckOCGVisible(pAnnotDict->GetDictFor("OC"))) { + if (pOptions->GetOCContext() && pAnnotDict && + !pOptions->GetOCContext()->CheckOCGVisible( + pAnnotDict->GetDictFor("OC"))) { continue; } } - CFX_FloatRect annot_rect_f = pAnnot->GetRect(); + CFX_Matrix matrix = *pMatrix; if (clip_rect) { - matrix.TransformRect(annot_rect_f); - - FX_RECT annot_rect = annot_rect_f.GetOuterRect(); + FX_RECT annot_rect = + matrix.TransformRect(pAnnot->GetRect()).GetOuterRect(); annot_rect.Intersect(*clip_rect); if (annot_rect.IsEmpty()) continue; } if (pContext) { pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal); - } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix, + } else if (!pAnnot->DrawAppearance(pPage, pDevice, matrix, CPDF_Annot::Normal, pOptions)) { pAnnot->DrawBorder(pDevice, &matrix, pOptions); } diff --git a/core/fpdfdoc/cpdf_apsettings.cpp b/core/fpdfdoc/cpdf_apsettings.cpp index 9fc9c1aa06670f395e8795c763f08b0bcebc23dc..076cdd9b9ea810da52563c5661aa5d54bf405de7 100644 --- a/core/fpdfdoc/cpdf_apsettings.cpp +++ b/core/fpdfdoc/cpdf_apsettings.cpp @@ -10,11 +10,15 @@ #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fxge/cfx_color.h" CPDF_ApSettings::CPDF_ApSettings(CPDF_Dictionary* pDict) : m_pDict(pDict) {} -bool CPDF_ApSettings::HasMKEntry(const CFX_ByteString& csEntry) const { +CPDF_ApSettings::CPDF_ApSettings(const CPDF_ApSettings& that) = default; + +CPDF_ApSettings::~CPDF_ApSettings() {} + +bool CPDF_ApSettings::HasMKEntry(const ByteString& csEntry) const { return m_pDict && m_pDict->KeyExist(csEntry); } @@ -23,8 +27,8 @@ int CPDF_ApSettings::GetRotation() const { } FX_ARGB CPDF_ApSettings::GetColor(int& iColorType, - const CFX_ByteString& csEntry) const { - iColorType = COLORTYPE_TRANSPARENT; + const ByteString& csEntry) const { + iColorType = CFX_Color::kTransparent; if (!m_pDict) return 0; @@ -35,34 +39,33 @@ FX_ARGB CPDF_ApSettings::GetColor(int& iColorType, FX_ARGB color = 0; size_t dwCount = pEntry->GetCount(); if (dwCount == 1) { - iColorType = COLORTYPE_GRAY; - FX_FLOAT g = pEntry->GetNumberAt(0) * 255; + iColorType = CFX_Color::kGray; + float g = pEntry->GetNumberAt(0) * 255; return ArgbEncode(255, (int)g, (int)g, (int)g); } if (dwCount == 3) { - iColorType = COLORTYPE_RGB; - FX_FLOAT r = pEntry->GetNumberAt(0) * 255; - FX_FLOAT g = pEntry->GetNumberAt(1) * 255; - FX_FLOAT b = pEntry->GetNumberAt(2) * 255; + iColorType = CFX_Color::kRGB; + float r = pEntry->GetNumberAt(0) * 255; + float g = pEntry->GetNumberAt(1) * 255; + float b = pEntry->GetNumberAt(2) * 255; return ArgbEncode(255, (int)r, (int)g, (int)b); } if (dwCount == 4) { - iColorType = COLORTYPE_CMYK; - FX_FLOAT c = pEntry->GetNumberAt(0); - FX_FLOAT m = pEntry->GetNumberAt(1); - FX_FLOAT y = pEntry->GetNumberAt(2); - FX_FLOAT k = pEntry->GetNumberAt(3); - FX_FLOAT r = 1.0f - std::min(1.0f, c + k); - FX_FLOAT g = 1.0f - std::min(1.0f, m + k); - FX_FLOAT b = 1.0f - std::min(1.0f, y + k); + iColorType = CFX_Color::kCMYK; + float c = pEntry->GetNumberAt(0); + float m = pEntry->GetNumberAt(1); + float y = pEntry->GetNumberAt(2); + float k = pEntry->GetNumberAt(3); + float r = 1.0f - std::min(1.0f, c + k); + float g = 1.0f - std::min(1.0f, m + k); + float b = 1.0f - std::min(1.0f, y + k); return ArgbEncode(255, (int)(r * 255), (int)(g * 255), (int)(b * 255)); } return color; } -FX_FLOAT CPDF_ApSettings::GetOriginalColor( - int index, - const CFX_ByteString& csEntry) const { +float CPDF_ApSettings::GetOriginalColor(int index, + const ByteString& csEntry) const { if (!m_pDict) return 0; @@ -71,9 +74,9 @@ FX_FLOAT CPDF_ApSettings::GetOriginalColor( } void CPDF_ApSettings::GetOriginalColor(int& iColorType, - FX_FLOAT fc[4], - const CFX_ByteString& csEntry) const { - iColorType = COLORTYPE_TRANSPARENT; + float fc[4], + const ByteString& csEntry) const { + iColorType = CFX_Color::kTransparent; for (int i = 0; i < 4; i++) fc[i] = 0; @@ -86,15 +89,15 @@ void CPDF_ApSettings::GetOriginalColor(int& iColorType, size_t dwCount = pEntry->GetCount(); if (dwCount == 1) { - iColorType = COLORTYPE_GRAY; + iColorType = CFX_Color::kGray; fc[0] = pEntry->GetNumberAt(0); } else if (dwCount == 3) { - iColorType = COLORTYPE_RGB; + iColorType = CFX_Color::kRGB; fc[0] = pEntry->GetNumberAt(0); fc[1] = pEntry->GetNumberAt(1); fc[2] = pEntry->GetNumberAt(2); } else if (dwCount == 4) { - iColorType = COLORTYPE_CMYK; + iColorType = CFX_Color::kCMYK; fc[0] = pEntry->GetNumberAt(0); fc[1] = pEntry->GetNumberAt(1); fc[2] = pEntry->GetNumberAt(2); @@ -102,12 +105,11 @@ void CPDF_ApSettings::GetOriginalColor(int& iColorType, } } -CFX_WideString CPDF_ApSettings::GetCaption( - const CFX_ByteString& csEntry) const { - return m_pDict ? m_pDict->GetUnicodeTextFor(csEntry) : CFX_WideString(); +WideString CPDF_ApSettings::GetCaption(const ByteString& csEntry) const { + return m_pDict ? m_pDict->GetUnicodeTextFor(csEntry) : WideString(); } -CPDF_Stream* CPDF_ApSettings::GetIcon(const CFX_ByteString& csEntry) const { +CPDF_Stream* CPDF_ApSettings::GetIcon(const ByteString& csEntry) const { return m_pDict ? m_pDict->GetStreamFor(csEntry) : nullptr; } diff --git a/core/fpdfdoc/cpdf_apsettings.h b/core/fpdfdoc/cpdf_apsettings.h index ffddffdbe061c47cd0a5c726892f1506c96356b1..a807c2b5813e66b2fd397fc68bb1b3baaad0a82f 100644 --- a/core/fpdfdoc/cpdf_apsettings.h +++ b/core/fpdfdoc/cpdf_apsettings.h @@ -10,6 +10,7 @@ #include "core/fpdfdoc/cpdf_iconfit.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" class CPDF_Dictionary; @@ -19,19 +20,21 @@ class CPDF_Stream; class CPDF_ApSettings { public: explicit CPDF_ApSettings(CPDF_Dictionary* pDict); + CPDF_ApSettings(const CPDF_ApSettings& that); + ~CPDF_ApSettings(); - bool HasMKEntry(const CFX_ByteString& csEntry) const; + bool HasMKEntry(const ByteString& csEntry) const; int GetRotation() const; FX_ARGB GetBorderColor(int& iColorType) const { return GetColor(iColorType, "BC"); } - FX_FLOAT GetOriginalBorderColor(int index) const { + float GetOriginalBorderColor(int index) const { return GetOriginalColor(index, "BC"); } - void GetOriginalBorderColor(int& iColorType, FX_FLOAT fc[4]) const { + void GetOriginalBorderColor(int& iColorType, float fc[4]) const { GetOriginalColor(iColorType, fc, "BC"); } @@ -39,36 +42,34 @@ class CPDF_ApSettings { return GetColor(iColorType, "BG"); } - FX_FLOAT GetOriginalBackgroundColor(int index) const { + float GetOriginalBackgroundColor(int index) const { return GetOriginalColor(index, "BG"); } - void GetOriginalBackgroundColor(int& iColorType, FX_FLOAT fc[4]) const { + void GetOriginalBackgroundColor(int& iColorType, float fc[4]) const { GetOriginalColor(iColorType, fc, "BG"); } - CFX_WideString GetNormalCaption() const { return GetCaption("CA"); } - CFX_WideString GetRolloverCaption() const { return GetCaption("RC"); } - CFX_WideString GetDownCaption() const { return GetCaption("AC"); } + WideString GetNormalCaption() const { return GetCaption("CA"); } + WideString GetRolloverCaption() const { return GetCaption("RC"); } + WideString GetDownCaption() const { return GetCaption("AC"); } CPDF_Stream* GetNormalIcon() const { return GetIcon("I"); } CPDF_Stream* GetRolloverIcon() const { return GetIcon("RI"); } CPDF_Stream* GetDownIcon() const { return GetIcon("IX"); } CPDF_IconFit GetIconFit() const; int GetTextPosition() const; - private: - friend class CPDF_FormControl; - - FX_ARGB GetColor(int& iColorType, const CFX_ByteString& csEntry) const; - FX_FLOAT GetOriginalColor(int index, const CFX_ByteString& csEntry) const; + FX_ARGB GetColor(int& iColorType, const ByteString& csEntry) const; + float GetOriginalColor(int index, const ByteString& csEntry) const; void GetOriginalColor(int& iColorType, - FX_FLOAT fc[4], - const CFX_ByteString& csEntry) const; + float fc[4], + const ByteString& csEntry) const; - CFX_WideString GetCaption(const CFX_ByteString& csEntry) const; - CPDF_Stream* GetIcon(const CFX_ByteString& csEntry) const; + WideString GetCaption(const ByteString& csEntry) const; + CPDF_Stream* GetIcon(const ByteString& csEntry) const; - CPDF_Dictionary* const m_pDict; + private: + UnownedPtr const m_pDict; }; #endif // CORE_FPDFDOC_CPDF_APSETTINGS_H_ diff --git a/core/fpdfdoc/cpdf_bookmark.cpp b/core/fpdfdoc/cpdf_bookmark.cpp index c2c37057170daf1226b9fda3ccb45a1ecec780c4..cc7e127d23753bdb8652144a69bcf755a63ec971 100644 --- a/core/fpdfdoc/cpdf_bookmark.cpp +++ b/core/fpdfdoc/cpdf_bookmark.cpp @@ -7,12 +7,21 @@ #include "core/fpdfdoc/cpdf_bookmark.h" #include +#include #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfdoc/cpdf_nametree.h" #include "core/fxge/fx_dib.h" +CPDF_Bookmark::CPDF_Bookmark() {} + +CPDF_Bookmark::CPDF_Bookmark(const CPDF_Bookmark& that) = default; + +CPDF_Bookmark::CPDF_Bookmark(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + +CPDF_Bookmark::~CPDF_Bookmark() {} + uint32_t CPDF_Bookmark::GetColorRef() const { if (!m_pDict) return FXSYS_RGB(0, 0, 0); @@ -31,25 +40,25 @@ uint32_t CPDF_Bookmark::GetFontStyle() const { return m_pDict ? m_pDict->GetIntegerFor("F") : 0; } -CFX_WideString CPDF_Bookmark::GetTitle() const { +WideString CPDF_Bookmark::GetTitle() const { if (!m_pDict) - return CFX_WideString(); + return WideString(); CPDF_String* pString = ToString(m_pDict->GetDirectObjectFor("Title")); if (!pString) - return CFX_WideString(); + return WideString(); - CFX_WideString title = pString->GetUnicodeText(); + WideString title = pString->GetUnicodeText(); int len = title.GetLength(); if (!len) - return CFX_WideString(); + return WideString(); - std::unique_ptr buf(new FX_WCHAR[len]); + std::vector buf(len); for (int i = 0; i < len; i++) { - FX_WCHAR w = title[i]; + wchar_t w = title[i]; buf[i] = w > 0x20 ? w : 0x20; } - return CFX_WideString(buf.get(), len); + return WideString(buf.data(), len); } CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument) const { @@ -61,7 +70,8 @@ CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument) const { return CPDF_Dest(); if (pDest->IsString() || pDest->IsName()) { CPDF_NameTree name_tree(pDocument, "Dests"); - return CPDF_Dest(name_tree.LookupNamedDest(pDocument, pDest->GetString())); + return CPDF_Dest( + name_tree.LookupNamedDest(pDocument, pDest->GetUnicodeText())); } if (CPDF_Array* pArray = pDest->AsArray()) return CPDF_Dest(pArray); @@ -69,5 +79,5 @@ CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument) const { } CPDF_Action CPDF_Bookmark::GetAction() const { - return m_pDict ? CPDF_Action(m_pDict->GetDictFor("A")) : CPDF_Action(); + return CPDF_Action(m_pDict ? m_pDict->GetDictFor("A") : nullptr); } diff --git a/core/fpdfdoc/cpdf_bookmark.h b/core/fpdfdoc/cpdf_bookmark.h index 30a8a512cce31449defb04cc8b1425bb585a34e2..60c86dd7b09dbe9da3392d5f2844b05fd0cb988b 100644 --- a/core/fpdfdoc/cpdf_bookmark.h +++ b/core/fpdfdoc/cpdf_bookmark.h @@ -10,24 +10,27 @@ #include "core/fpdfdoc/cpdf_action.h" #include "core/fpdfdoc/cpdf_dest.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; class CPDF_Document; class CPDF_Bookmark { public: - CPDF_Bookmark() : m_pDict(nullptr) {} - explicit CPDF_Bookmark(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + CPDF_Bookmark(); + CPDF_Bookmark(const CPDF_Bookmark& that); + explicit CPDF_Bookmark(CPDF_Dictionary* pDict); + ~CPDF_Bookmark(); - CPDF_Dictionary* GetDict() const { return m_pDict; } + CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } uint32_t GetColorRef() const; uint32_t GetFontStyle() const; - CFX_WideString GetTitle() const; + WideString GetTitle() const; CPDF_Dest GetDest(CPDF_Document* pDocument) const; CPDF_Action GetAction() const; private: - CPDF_Dictionary* m_pDict; + UnownedPtr m_pDict; }; #endif // CORE_FPDFDOC_CPDF_BOOKMARK_H_ diff --git a/core/fpdfdoc/cpdf_bookmarktree.cpp b/core/fpdfdoc/cpdf_bookmarktree.cpp index 2a4314547ce58ed8804c9568657cad0e93af6e55..33c9f3d15b680fbb86205fc89216476d26bcee25 100644 --- a/core/fpdfdoc/cpdf_bookmarktree.cpp +++ b/core/fpdfdoc/cpdf_bookmarktree.cpp @@ -8,13 +8,17 @@ #include "core/fpdfapi/parser/cpdf_document.h" +CPDF_BookmarkTree::CPDF_BookmarkTree(CPDF_Document* pDoc) : m_pDocument(pDoc) {} + +CPDF_BookmarkTree::~CPDF_BookmarkTree() {} + CPDF_Bookmark CPDF_BookmarkTree::GetFirstChild( const CPDF_Bookmark& parent) const { CPDF_Dictionary* pParentDict = parent.GetDict(); if (pParentDict) return CPDF_Bookmark(pParentDict->GetDictFor("First")); - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + const CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); if (!pRoot) return CPDF_Bookmark(); diff --git a/core/fpdfdoc/cpdf_bookmarktree.h b/core/fpdfdoc/cpdf_bookmarktree.h index 7207357b1e599a76baa53bdb73835acf386d3124..3729dfc737f99185b8f631549b5ddf3dd9325543 100644 --- a/core/fpdfdoc/cpdf_bookmarktree.h +++ b/core/fpdfdoc/cpdf_bookmarktree.h @@ -8,19 +8,21 @@ #define CORE_FPDFDOC_CPDF_BOOKMARKTREE_H_ #include "core/fpdfdoc/cpdf_bookmark.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_BookmarkTree { public: - explicit CPDF_BookmarkTree(CPDF_Document* pDoc) : m_pDocument(pDoc) {} + explicit CPDF_BookmarkTree(CPDF_Document* pDoc); + ~CPDF_BookmarkTree(); CPDF_Bookmark GetFirstChild(const CPDF_Bookmark& parent) const; CPDF_Bookmark GetNextSibling(const CPDF_Bookmark& bookmark) const; - CPDF_Document* GetDocument() const { return m_pDocument; } + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } private: - CPDF_Document* const m_pDocument; + UnownedPtr const m_pDocument; }; #endif // CORE_FPDFDOC_CPDF_BOOKMARKTREE_H_ diff --git a/core/fpdfdoc/cpdf_defaultappearance.cpp b/core/fpdfdoc/cpdf_defaultappearance.cpp index 19767650f3a83dc76acbcbb9ba90335e8d397f0a..02d6eea41f6fd090b1d13ea8390917b09687432d 100644 --- a/core/fpdfdoc/cpdf_defaultappearance.cpp +++ b/core/fpdfdoc/cpdf_defaultappearance.cpp @@ -10,22 +10,22 @@ #include "core/fpdfapi/parser/cpdf_simple_parser.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fxge/cfx_color.h" bool CPDF_DefaultAppearance::HasFont() { if (m_csDA.IsEmpty()) return false; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); return syntax.FindTagParamFromStart("Tf", 2); } -CFX_ByteString CPDF_DefaultAppearance::GetFontString() { - CFX_ByteString csFont; +ByteString CPDF_DefaultAppearance::GetFontString() { + ByteString csFont; if (m_csDA.IsEmpty()) return csFont; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart("Tf", 2)) { csFont += syntax.GetWord(); csFont += " "; @@ -36,27 +36,26 @@ CFX_ByteString CPDF_DefaultAppearance::GetFontString() { return csFont; } -void CPDF_DefaultAppearance::GetFont(CFX_ByteString& csFontNameTag, - FX_FLOAT& fFontSize) { - csFontNameTag = ""; - fFontSize = 0; +ByteString CPDF_DefaultAppearance::GetFont(float* fFontSize) { + *fFontSize = 0.0f; if (m_csDA.IsEmpty()) - return; + return ByteString(); - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + ByteString csFontNameTag; + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart("Tf", 2)) { - csFontNameTag = CFX_ByteString(syntax.GetWord()); + csFontNameTag = ByteString(syntax.GetWord()); csFontNameTag.Delete(0, 1); - fFontSize = FX_atof(syntax.GetWord()); + *fFontSize = FX_atof(syntax.GetWord()); } - csFontNameTag = PDF_NameDecode(csFontNameTag); + return PDF_NameDecode(csFontNameTag); } bool CPDF_DefaultAppearance::HasColor(PaintOperation nOperation) { if (m_csDA.IsEmpty()) return false; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "G" : "g"), 1)) { return true; @@ -69,13 +68,12 @@ bool CPDF_DefaultAppearance::HasColor(PaintOperation nOperation) { (nOperation == PaintOperation::STROKE ? "K" : "k"), 4); } -CFX_ByteString CPDF_DefaultAppearance::GetColorString( - PaintOperation nOperation) { - CFX_ByteString csColor; +ByteString CPDF_DefaultAppearance::GetColorString(PaintOperation nOperation) { + ByteString csColor; if (m_csDA.IsEmpty()) return csColor; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "G" : "g"), 1)) { csColor += syntax.GetWord(); @@ -110,25 +108,25 @@ CFX_ByteString CPDF_DefaultAppearance::GetColorString( } void CPDF_DefaultAppearance::GetColor(int& iColorType, - FX_FLOAT fc[4], + float fc[4], PaintOperation nOperation) { - iColorType = COLORTYPE_TRANSPARENT; + iColorType = CFX_Color::kTransparent; for (int c = 0; c < 4; c++) fc[c] = 0; if (m_csDA.IsEmpty()) return; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "G" : "g"), 1)) { - iColorType = COLORTYPE_GRAY; + iColorType = CFX_Color::kGray; fc[0] = FX_atof(syntax.GetWord()); return; } if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "RG" : "rg"), 3)) { - iColorType = COLORTYPE_RGB; + iColorType = CFX_Color::kRGB; fc[0] = FX_atof(syntax.GetWord()); fc[1] = FX_atof(syntax.GetWord()); fc[2] = FX_atof(syntax.GetWord()); @@ -136,7 +134,7 @@ void CPDF_DefaultAppearance::GetColor(int& iColorType, } if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "K" : "k"), 4)) { - iColorType = COLORTYPE_CMYK; + iColorType = CFX_Color::kCMYK; fc[0] = FX_atof(syntax.GetWord()); fc[1] = FX_atof(syntax.GetWord()); fc[2] = FX_atof(syntax.GetWord()); @@ -148,37 +146,37 @@ void CPDF_DefaultAppearance::GetColor(FX_ARGB& color, int& iColorType, PaintOperation nOperation) { color = 0; - iColorType = COLORTYPE_TRANSPARENT; + iColorType = CFX_Color::kTransparent; if (m_csDA.IsEmpty()) return; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "G" : "g"), 1)) { - iColorType = COLORTYPE_GRAY; - FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f; + iColorType = CFX_Color::kGray; + float g = FX_atof(syntax.GetWord()) * 255 + 0.5f; color = ArgbEncode(255, (int)g, (int)g, (int)g); return; } if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "RG" : "rg"), 3)) { - iColorType = COLORTYPE_RGB; - FX_FLOAT r = FX_atof(syntax.GetWord()) * 255 + 0.5f; - FX_FLOAT g = FX_atof(syntax.GetWord()) * 255 + 0.5f; - FX_FLOAT b = FX_atof(syntax.GetWord()) * 255 + 0.5f; + iColorType = CFX_Color::kRGB; + float r = FX_atof(syntax.GetWord()) * 255 + 0.5f; + float g = FX_atof(syntax.GetWord()) * 255 + 0.5f; + float b = FX_atof(syntax.GetWord()) * 255 + 0.5f; color = ArgbEncode(255, (int)r, (int)g, (int)b); return; } if (syntax.FindTagParamFromStart( (nOperation == PaintOperation::STROKE ? "K" : "k"), 4)) { - iColorType = COLORTYPE_CMYK; - FX_FLOAT c = FX_atof(syntax.GetWord()); - FX_FLOAT m = FX_atof(syntax.GetWord()); - FX_FLOAT y = FX_atof(syntax.GetWord()); - FX_FLOAT k = FX_atof(syntax.GetWord()); - FX_FLOAT r = 1.0f - std::min(1.0f, c + k); - FX_FLOAT g = 1.0f - std::min(1.0f, m + k); - FX_FLOAT b = 1.0f - std::min(1.0f, y + k); + iColorType = CFX_Color::kCMYK; + float c = FX_atof(syntax.GetWord()); + float m = FX_atof(syntax.GetWord()); + float y = FX_atof(syntax.GetWord()); + float k = FX_atof(syntax.GetWord()); + float r = 1.0f - std::min(1.0f, c + k); + float g = 1.0f - std::min(1.0f, m + k); + float b = 1.0f - std::min(1.0f, y + k); color = ArgbEncode(255, (int)(r * 255 + 0.5f), (int)(g * 255 + 0.5f), (int)(b * 255 + 0.5f)); } @@ -188,16 +186,16 @@ bool CPDF_DefaultAppearance::HasTextMatrix() { if (m_csDA.IsEmpty()) return false; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); return syntax.FindTagParamFromStart("Tm", 6); } -CFX_ByteString CPDF_DefaultAppearance::GetTextMatrixString() { - CFX_ByteString csTM; +ByteString CPDF_DefaultAppearance::GetTextMatrixString() { + ByteString csTM; if (m_csDA.IsEmpty()) return csTM; - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (syntax.FindTagParamFromStart("Tm", 6)) { for (int i = 0; i < 6; i++) { csTM += syntax.GetWord(); @@ -212,11 +210,11 @@ CFX_Matrix CPDF_DefaultAppearance::GetTextMatrix() { if (m_csDA.IsEmpty()) return CFX_Matrix(); - CPDF_SimpleParser syntax(m_csDA.AsStringC()); + CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (!syntax.FindTagParamFromStart("Tm", 6)) return CFX_Matrix(); - FX_FLOAT f[6]; + float f[6]; for (int i = 0; i < 6; i++) f[i] = FX_atof(syntax.GetWord()); return CFX_Matrix(f); diff --git a/core/fpdfdoc/cpdf_defaultappearance.h b/core/fpdfdoc/cpdf_defaultappearance.h index 4fd32ebd0c76ab162478ec1277a0e5120b41a55a..33d4bfdd9d70c0027573a59b6e701a00e976268b 100644 --- a/core/fpdfdoc/cpdf_defaultappearance.h +++ b/core/fpdfdoc/cpdf_defaultappearance.h @@ -19,34 +19,33 @@ enum class PaintOperation { STROKE, FILL }; class CPDF_DefaultAppearance { public: CPDF_DefaultAppearance() {} - explicit CPDF_DefaultAppearance(const CFX_ByteString& csDA) : m_csDA(csDA) {} + explicit CPDF_DefaultAppearance(const ByteString& csDA) : m_csDA(csDA) {} CPDF_DefaultAppearance(const CPDF_DefaultAppearance& cDA) { m_csDA = cDA.GetStr(); } - CFX_ByteString GetStr() const { return m_csDA; } + ByteString GetStr() const { return m_csDA; } bool HasFont(); - CFX_ByteString GetFontString(); - void GetFont(CFX_ByteString& csFontNameTag, FX_FLOAT& fFontSize); + ByteString GetFontString(); + ByteString GetFont(float* fFontSize); bool HasColor(PaintOperation nOperation = PaintOperation::FILL); - CFX_ByteString GetColorString( - PaintOperation nOperation = PaintOperation::FILL); + ByteString GetColorString(PaintOperation nOperation = PaintOperation::FILL); void GetColor(int& iColorType, - FX_FLOAT fc[4], + float fc[4], PaintOperation nOperation = PaintOperation::FILL); void GetColor(FX_ARGB& color, int& iColorType, PaintOperation nOperation = PaintOperation::FILL); bool HasTextMatrix(); - CFX_ByteString GetTextMatrixString(); + ByteString GetTextMatrixString(); CFX_Matrix GetTextMatrix(); private: - CFX_ByteString m_csDA; + ByteString m_csDA; }; #endif // CORE_FPDFDOC_CPDF_DEFAULTAPPEARANCE_H_ diff --git a/core/fpdfdoc/cpdf_dest.cpp b/core/fpdfdoc/cpdf_dest.cpp index 51e2d0b53427974a5a70613135064a8c551eb72a..0098f73f663b50e71d0073225dc31c71a0d5f682 100644 --- a/core/fpdfdoc/cpdf_dest.cpp +++ b/core/fpdfdoc/cpdf_dest.cpp @@ -6,6 +6,8 @@ #include "core/fpdfdoc/cpdf_dest.h" +#include + #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" @@ -13,13 +15,31 @@ namespace { -const FX_CHAR* const g_sZoomModes[] = {"XYZ", "Fit", "FitH", "FitV", "FitR", - "FitB", "FitBH", "FitBV", nullptr}; +// These arrays are indexed by the PDFDEST_VIEW_* constants. + +// Last element is a sentinel. +const char* const g_sZoomModes[] = {"Unknown", "XYZ", "Fit", "FitH", + "FitV", "FitR", "FitB", "FitBH", + "FitBV", nullptr}; + +const uint8_t g_sZoomModeMaxParamCount[] = {0, 3, 0, 1, 1, 4, 0, 1, 1, 0}; + +static_assert(FX_ArraySize(g_sZoomModes) == + FX_ArraySize(g_sZoomModeMaxParamCount), + "Zoom mode count Mismatch"); } // namespace -int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc) { - CPDF_Array* pArray = ToArray(m_pObj); +CPDF_Dest::CPDF_Dest() {} + +CPDF_Dest::CPDF_Dest(const CPDF_Dest& pObj) = default; + +CPDF_Dest::CPDF_Dest(CPDF_Object* pObj) : m_pObj(pObj) {} + +CPDF_Dest::~CPDF_Dest() {} + +int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc) const { + CPDF_Array* pArray = ToArray(m_pObj.Get()); if (!pArray) return 0; @@ -33,8 +53,8 @@ int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc) { return pDoc->GetPageIndex(pPage->GetObjNum()); } -uint32_t CPDF_Dest::GetPageObjNum() { - CPDF_Array* pArray = ToArray(m_pObj); +uint32_t CPDF_Dest::GetPageObjNum() const { + CPDF_Array* pArray = ToArray(m_pObj.Get()); if (!pArray) return 0; @@ -48,8 +68,8 @@ uint32_t CPDF_Dest::GetPageObjNum() { return 0; } -int CPDF_Dest::GetZoomMode() { - CPDF_Array* pArray = ToArray(m_pObj); +int CPDF_Dest::GetZoomMode() const { + CPDF_Array* pArray = ToArray(m_pObj.Get()); if (!pArray) return 0; @@ -57,10 +77,10 @@ int CPDF_Dest::GetZoomMode() { if (!pObj) return 0; - CFX_ByteString mode = pObj->GetString(); - for (int i = 0; g_sZoomModes[i]; ++i) { + ByteString mode = pObj->GetString(); + for (int i = 1; g_sZoomModes[i]; ++i) { if (mode == g_sZoomModes[i]) - return i + 1; + return i; } return 0; @@ -76,7 +96,7 @@ bool CPDF_Dest::GetXYZ(bool* pHasX, *pHasY = false; *pHasZoom = false; - CPDF_Array* pArray = ToArray(m_pObj); + CPDF_Array* pArray = ToArray(m_pObj.Get()); if (!pArray) return false; @@ -113,11 +133,21 @@ bool CPDF_Dest::GetXYZ(bool* pHasX, return true; } -FX_FLOAT CPDF_Dest::GetParam(int index) { - CPDF_Array* pArray = ToArray(m_pObj); +unsigned long CPDF_Dest::GetNumParams() const { + CPDF_Array* pArray = ToArray(m_pObj.Get()); + if (!pArray || pArray->GetCount() < 2) + return 0; + + unsigned long maxParamsForFitType = g_sZoomModeMaxParamCount[GetZoomMode()]; + unsigned long numParamsInArray = pArray->GetCount() - 2; + return std::min(maxParamsForFitType, numParamsInArray); +} + +float CPDF_Dest::GetParam(int index) const { + CPDF_Array* pArray = ToArray(m_pObj.Get()); return pArray ? pArray->GetNumberAt(2 + index) : 0; } -CFX_ByteString CPDF_Dest::GetRemoteName() { - return m_pObj ? m_pObj->GetString() : CFX_ByteString(); +ByteString CPDF_Dest::GetRemoteName() const { + return m_pObj ? m_pObj->GetString() : ByteString(); } diff --git a/core/fpdfdoc/cpdf_dest.h b/core/fpdfdoc/cpdf_dest.h index 527d1dcf8b1f6eed0caeef07918cc7fdfbfb99fc..584669a82da435332da25e4d93587b758aac9a95 100644 --- a/core/fpdfdoc/cpdf_dest.h +++ b/core/fpdfdoc/cpdf_dest.h @@ -9,21 +9,28 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_Object; class CPDF_Dest { public: - CPDF_Dest() : m_pObj(nullptr) {} - explicit CPDF_Dest(CPDF_Object* pObj) : m_pObj(pObj) {} + CPDF_Dest(); + CPDF_Dest(const CPDF_Dest& that); + explicit CPDF_Dest(CPDF_Object* pObj); + ~CPDF_Dest(); - CPDF_Object* GetObject() const { return m_pObj; } - CFX_ByteString GetRemoteName(); - int GetPageIndex(CPDF_Document* pDoc); - uint32_t GetPageObjNum(); - int GetZoomMode(); - FX_FLOAT GetParam(int index); + CPDF_Object* GetObject() const { return m_pObj.Get(); } + ByteString GetRemoteName() const; + int GetPageIndex(CPDF_Document* pDoc) const; + uint32_t GetPageObjNum() const; + + // Returns the zoom mode, as one of the PDFDEST_VIEW_* values in fpdf_doc.h. + int GetZoomMode() const; + + unsigned long GetNumParams() const; + float GetParam(int index) const; bool GetXYZ(bool* pHasX, bool* pHasY, @@ -33,7 +40,7 @@ class CPDF_Dest { float* pZoom) const; private: - CPDF_Object* m_pObj; + UnownedPtr m_pObj; }; #endif // CORE_FPDFDOC_CPDF_DEST_H_ diff --git a/core/fpdfdoc/cpdf_dest_unittest.cpp b/core/fpdfdoc/cpdf_dest_unittest.cpp index 7c35371085c364bd39fdb75d6a5a685a24665888..2b3c86a882809da28151e0fba098e11ac37e3e31 100644 --- a/core/fpdfdoc/cpdf_dest_unittest.cpp +++ b/core/fpdfdoc/cpdf_dest_unittest.cpp @@ -19,43 +19,48 @@ TEST(cpdf_dest, GetXYZ) { float y; float zoom; - auto dest = pdfium::MakeUnique(); - EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); - + // |array| must outlive |dest|. auto array = pdfium::MakeUnique(); array->AddNew(0); // Page Index. array->AddNew("XYZ"); array->AddNew(4); // X - - // Not enough entries. - dest = pdfium::MakeUnique(array.get()); - EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); - + { + auto dest = pdfium::MakeUnique(); + EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); + } + { + // Not enough entries. + auto dest = pdfium::MakeUnique(array.get()); + EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); + } array->AddNew(5); // Y array->AddNew(6); // Zoom. - - dest = pdfium::MakeUnique(array.get()); - EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); - EXPECT_TRUE(hasX); - EXPECT_TRUE(hasY); - EXPECT_TRUE(hasZoom); - EXPECT_EQ(4, x); - EXPECT_EQ(5, y); - EXPECT_EQ(6, zoom); - + { + auto dest = pdfium::MakeUnique(array.get()); + EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); + EXPECT_TRUE(hasX); + EXPECT_TRUE(hasY); + EXPECT_TRUE(hasZoom); + EXPECT_EQ(4, x); + EXPECT_EQ(5, y); + EXPECT_EQ(6, zoom); + } // Set zoom to 0. array->SetNewAt(4, 0); - dest = pdfium::MakeUnique(array.get()); - EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); - EXPECT_FALSE(hasZoom); - + { + auto dest = pdfium::MakeUnique(array.get()); + EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); + EXPECT_FALSE(hasZoom); + } // Set values to null. array->SetNewAt(2); array->SetNewAt(3); array->SetNewAt(4); - dest = pdfium::MakeUnique(array.get()); - EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); - EXPECT_FALSE(hasX); - EXPECT_FALSE(hasY); - EXPECT_FALSE(hasZoom); + { + auto dest = pdfium::MakeUnique(array.get()); + EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); + EXPECT_FALSE(hasX); + EXPECT_FALSE(hasY); + EXPECT_FALSE(hasZoom); + } } diff --git a/core/fpdfdoc/cpdf_docjsactions.cpp b/core/fpdfdoc/cpdf_docjsactions.cpp index a7fcdfd07107dc1618a572dbd7aea425548fc028..91db2b0484745a525a4b2fc21c9e2f30e2391bf0 100644 --- a/core/fpdfdoc/cpdf_docjsactions.cpp +++ b/core/fpdfdoc/cpdf_docjsactions.cpp @@ -10,31 +10,29 @@ CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc) : m_pDocument(pDoc) {} +CPDF_DocJSActions::~CPDF_DocJSActions() {} + int CPDF_DocJSActions::CountJSActions() const { ASSERT(m_pDocument); - CPDF_NameTree name_tree(m_pDocument, "JavaScript"); + CPDF_NameTree name_tree(m_pDocument.Get(), "JavaScript"); return name_tree.GetCount(); } -CPDF_Action CPDF_DocJSActions::GetJSAction(int index, - CFX_ByteString& csName) const { +CPDF_Action CPDF_DocJSActions::GetJSActionAndName(int index, + WideString* csName) const { ASSERT(m_pDocument); - CPDF_NameTree name_tree(m_pDocument, "JavaScript"); - CPDF_Object* pAction = name_tree.LookupValue(index, csName); - return ToDictionary(pAction) ? CPDF_Action(pAction->GetDict()) - : CPDF_Action(); + CPDF_NameTree name_tree(m_pDocument.Get(), "JavaScript"); + return CPDF_Action(ToDictionary(name_tree.LookupValueAndName(index, csName))); } -CPDF_Action CPDF_DocJSActions::GetJSAction(const CFX_ByteString& csName) const { +CPDF_Action CPDF_DocJSActions::GetJSAction(const WideString& csName) const { ASSERT(m_pDocument); - CPDF_NameTree name_tree(m_pDocument, "JavaScript"); - CPDF_Object* pAction = name_tree.LookupValue(csName); - return ToDictionary(pAction) ? CPDF_Action(pAction->GetDict()) - : CPDF_Action(); + CPDF_NameTree name_tree(m_pDocument.Get(), "JavaScript"); + return CPDF_Action(ToDictionary(name_tree.LookupValue(csName))); } -int CPDF_DocJSActions::FindJSAction(const CFX_ByteString& csName) const { +int CPDF_DocJSActions::FindJSAction(const WideString& csName) const { ASSERT(m_pDocument); - CPDF_NameTree name_tree(m_pDocument, "JavaScript"); + CPDF_NameTree name_tree(m_pDocument.Get(), "JavaScript"); return name_tree.GetIndex(csName); } diff --git a/core/fpdfdoc/cpdf_docjsactions.h b/core/fpdfdoc/cpdf_docjsactions.h index 8a8d03d3649b736ea58fb9f3a810202562701b2b..39aafb8d501b6c42d6212a75bc50553efd72bbf1 100644 --- a/core/fpdfdoc/cpdf_docjsactions.h +++ b/core/fpdfdoc/cpdf_docjsactions.h @@ -9,21 +9,23 @@ #include "core/fpdfdoc/cpdf_action.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_DocJSActions { public: explicit CPDF_DocJSActions(CPDF_Document* pDoc); + ~CPDF_DocJSActions(); int CountJSActions() const; - CPDF_Action GetJSAction(int index, CFX_ByteString& csName) const; - CPDF_Action GetJSAction(const CFX_ByteString& csName) const; - int FindJSAction(const CFX_ByteString& csName) const; - CPDF_Document* GetDocument() const { return m_pDocument; } + CPDF_Action GetJSActionAndName(int index, WideString* csName) const; + CPDF_Action GetJSAction(const WideString& csName) const; + int FindJSAction(const WideString& csName) const; + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } private: - CPDF_Document* const m_pDocument; + UnownedPtr const m_pDocument; }; #endif // CORE_FPDFDOC_CPDF_DOCJSACTIONS_H_ diff --git a/core/fpdfdoc/cpdf_filespec.cpp b/core/fpdfdoc/cpdf_filespec.cpp index ce6f9a247e982a200c6016ec747014c40b261304..2f999bcf4e1a3cace67849f426f49de56608afb6 100644 --- a/core/fpdfdoc/cpdf_filespec.cpp +++ b/core/fpdfdoc/cpdf_filespec.cpp @@ -6,25 +6,28 @@ #include "core/fpdfdoc/cpdf_filespec.h" +#include + #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_object.h" +#include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcrt/fx_system.h" namespace { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -CFX_WideString ChangeSlashToPlatform(const FX_WCHAR* str) { - CFX_WideString result; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \ + _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +WideString ChangeSlashToPlatform(const wchar_t* str) { + WideString result; while (*str) { if (*str == '/') { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - result += ':'; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + result += L':'; #else - result += '\\'; + result += L'\\'; #endif } else { result += *str; @@ -34,11 +37,11 @@ CFX_WideString ChangeSlashToPlatform(const FX_WCHAR* str) { return result; } -CFX_WideString ChangeSlashToPDF(const FX_WCHAR* str) { - CFX_WideString result; +WideString ChangeSlashToPDF(const wchar_t* str) { + WideString result; while (*str) { if (*str == '\\' || *str == ':') - result += '/'; + result += L'/'; else result += *str; @@ -46,125 +49,145 @@ CFX_WideString ChangeSlashToPDF(const FX_WCHAR* str) { } return result; } -#endif // _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_APPLE_ || _FX_PLATFORM_WINDOWS_ } // namespace -CFX_WideString CPDF_FileSpec::DecodeFileName(const CFX_WideStringC& filepath) { +CPDF_FileSpec::CPDF_FileSpec(CPDF_Object* pObj) : m_pObj(pObj) { + ASSERT(m_pObj); +} + +CPDF_FileSpec::~CPDF_FileSpec() {} + +WideString CPDF_FileSpec::DecodeFileName(const WideString& filepath) { if (filepath.GetLength() <= 1) - return CFX_WideString(); + return WideString(); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (filepath.Left(sizeof("/Mac") - 1) == CFX_WideStringC(L"/Mac")) +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + if (filepath.Left(sizeof("/Mac") - 1) == WideStringView(L"/Mac")) return ChangeSlashToPlatform(filepath.c_str() + 1); return ChangeSlashToPlatform(filepath.c_str()); -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ - if (filepath.GetAt(0) != '/') + if (filepath[0] != L'/') return ChangeSlashToPlatform(filepath.c_str()); - if (filepath.GetAt(1) == '/') + if (filepath[1] == L'/') return ChangeSlashToPlatform(filepath.c_str() + 1); - if (filepath.GetAt(2) == '/') { - CFX_WideString result; - result += filepath.GetAt(1); - result += ':'; + if (filepath[2] == L'/') { + WideString result; + result += filepath[1]; + result += L':'; result += ChangeSlashToPlatform(filepath.c_str() + 2); return result; } - CFX_WideString result; - result += '\\'; + WideString result; + result += L'\\'; result += ChangeSlashToPlatform(filepath.c_str()); return result; #else - return CFX_WideString(filepath); + return WideString(filepath); #endif } -bool CPDF_FileSpec::GetFileName(CFX_WideString* csFileName) const { +WideString CPDF_FileSpec::GetFileName() const { + WideString csFileName; if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) { - *csFileName = pDict->GetUnicodeTextFor("UF"); - if (csFileName->IsEmpty()) { - *csFileName = - CFX_WideString::FromLocal(pDict->GetStringFor("F").AsStringC()); + csFileName = pDict->GetUnicodeTextFor("UF"); + if (csFileName.IsEmpty()) { + csFileName = + WideString::FromLocal(pDict->GetStringFor("F").AsStringView()); } if (pDict->GetStringFor("FS") == "URL") - return true; - if (csFileName->IsEmpty()) { - if (pDict->KeyExist("DOS")) { - *csFileName = - CFX_WideString::FromLocal(pDict->GetStringFor("DOS").AsStringC()); - } else if (pDict->KeyExist("Mac")) { - *csFileName = - CFX_WideString::FromLocal(pDict->GetStringFor("Mac").AsStringC()); - } else if (pDict->KeyExist("Unix")) { - *csFileName = - CFX_WideString::FromLocal(pDict->GetStringFor("Unix").AsStringC()); - } else { - return false; + return csFileName; + + if (csFileName.IsEmpty()) { + constexpr const char* keys[] = {"DOS", "Mac", "Unix"}; + for (const auto* key : keys) { + if (pDict->KeyExist(key)) { + csFileName = + WideString::FromLocal(pDict->GetStringFor(key).AsStringView()); + break; + } } } } else if (m_pObj->IsString()) { - *csFileName = CFX_WideString::FromLocal(m_pObj->GetString().AsStringC()); - } else { - return false; + csFileName = WideString::FromLocal(m_pObj->GetString().AsStringView()); } - *csFileName = DecodeFileName(csFileName->AsStringC()); - return true; + return DecodeFileName(csFileName); } -CPDF_FileSpec::CPDF_FileSpec(const CFX_WeakPtr& pPool) { - m_pObj = new CPDF_Dictionary(pPool); - m_pObj->AsDictionary()->SetNewFor("Type", "Filespec"); +CPDF_Stream* CPDF_FileSpec::GetFileStream() const { + CPDF_Dictionary* pDict = m_pObj->AsDictionary(); + if (!pDict) + return nullptr; + + // Get the embedded files dictionary. + CPDF_Dictionary* pFiles = pDict->GetDictFor("EF"); + if (!pFiles) + return nullptr; + + // Get the file stream of the highest precedence with its file specification + // string available. Follows the same precedence order as GetFileName(). + constexpr const char* keys[] = {"UF", "F", "DOS", "Mac", "Unix"}; + size_t end = pDict->GetStringFor("FS") == "URL" ? 2 : FX_ArraySize(keys); + for (size_t i = 0; i < end; ++i) { + const ByteString& key = keys[i]; + if (!pDict->GetUnicodeTextFor(key).IsEmpty()) { + CPDF_Stream* pStream = pFiles->GetStreamFor(key); + if (pStream) + return pStream; + } + } + return nullptr; } -CFX_WideString CPDF_FileSpec::EncodeFileName(const CFX_WideStringC& filepath) { +CPDF_Dictionary* CPDF_FileSpec::GetParamsDict() const { + CPDF_Stream* pStream = GetFileStream(); + if (!pStream) + return nullptr; + + CPDF_Dictionary* pDict = pStream->GetDict(); + if (!pDict) + return nullptr; + + return pDict->GetDictFor("Params"); +} + +WideString CPDF_FileSpec::EncodeFileName(const WideString& filepath) { if (filepath.GetLength() <= 1) - return CFX_WideString(); + return WideString(); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - if (filepath.GetAt(1) == ':') { - CFX_WideString result; - result = '/'; - result += filepath.GetAt(0); - if (filepath.GetAt(2) != '\\') - result += '/'; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + if (filepath[1] == L':') { + WideString result(L'/'); + result += filepath[0]; + if (filepath[2] != L'\\') + result += L'/'; result += ChangeSlashToPDF(filepath.c_str() + 2); return result; } - if (filepath.GetAt(0) == '\\' && filepath.GetAt(1) == '\\') + if (filepath[0] == L'\\' && filepath[1] == L'\\') return ChangeSlashToPDF(filepath.c_str() + 1); - if (filepath.GetAt(0) == '\\') { - CFX_WideString result; - result = '/'; - result += ChangeSlashToPDF(filepath.c_str()); - return result; - } + if (filepath[0] == L'\\') + return L'/' + ChangeSlashToPDF(filepath.c_str()); return ChangeSlashToPDF(filepath.c_str()); -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (filepath.Left(sizeof("Mac") - 1) == L"Mac") { - CFX_WideString result; - result = '/'; - result += ChangeSlashToPDF(filepath.c_str()); - return result; - } +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + if (filepath.Left(sizeof("Mac") - 1) == L"Mac") + return L'/' + ChangeSlashToPDF(filepath.c_str()); return ChangeSlashToPDF(filepath.c_str()); #else - return CFX_WideString(filepath); + return WideString(filepath); #endif } -void CPDF_FileSpec::SetFileName(const CFX_WideStringC& wsFileName) { - if (!m_pObj) - return; - - CFX_WideString wsStr = EncodeFileName(wsFileName); +void CPDF_FileSpec::SetFileName(const WideString& wsFileName) { + WideString wsStr = EncodeFileName(wsFileName); if (m_pObj->IsString()) { - m_pObj->SetString(CFX_ByteString::FromUnicode(wsStr)); + m_pObj->SetString(ByteString::FromUnicode(wsStr)); } else if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) { - pDict->SetNewFor("F", CFX_ByteString::FromUnicode(wsStr), - false); + pDict->SetNewFor("F", ByteString::FromUnicode(wsStr), false); pDict->SetNewFor("UF", PDF_EncodeText(wsStr), false); } } diff --git a/core/fpdfdoc/cpdf_filespec.h b/core/fpdfdoc/cpdf_filespec.h index 6266c37a478cc70d985dce0b19c8ab7e5efeb9eb..deeccb961931d96e3f174a4d75555e537badfe69 100644 --- a/core/fpdfdoc/cpdf_filespec.h +++ b/core/fpdfdoc/cpdf_filespec.h @@ -7,31 +7,36 @@ #ifndef CORE_FPDFDOC_CPDF_FILESPEC_H_ #define CORE_FPDFDOC_CPDF_FILESPEC_H_ -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_weak_ptr.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxcrt/weak_ptr.h" +class CPDF_Dictionary; class CPDF_Object; +class CPDF_Stream; class CPDF_FileSpec { public: - explicit CPDF_FileSpec(const CFX_WeakPtr& pPool); - explicit CPDF_FileSpec(CPDF_Object* pObj) : m_pObj(pObj) {} + explicit CPDF_FileSpec(CPDF_Object* pObj); + ~CPDF_FileSpec(); // Convert a platform dependent file name into pdf format. - static CFX_WideString EncodeFileName(const CFX_WideStringC& filepath); + static WideString EncodeFileName(const WideString& filepath); // Convert a pdf file name into platform dependent format. - static CFX_WideString DecodeFileName(const CFX_WideStringC& filepath); + static WideString DecodeFileName(const WideString& filepath); - CPDF_Object* GetObj() const { return m_pObj; } - bool GetFileName(CFX_WideString* wsFileName) const; + CPDF_Object* GetObj() const { return m_pObj.Get(); } + WideString GetFileName() const; + CPDF_Stream* GetFileStream() const; + CPDF_Dictionary* GetParamsDict() const; // Set this file spec to refer to a file name (not a url). - void SetFileName(const CFX_WideStringC& wsFileName); + void SetFileName(const WideString& wsFileName); private: - CPDF_Object* m_pObj; + UnownedPtr const m_pObj; }; #endif // CORE_FPDFDOC_CPDF_FILESPEC_H_ diff --git a/core/fpdfdoc/cpdf_filespec_unittest.cpp b/core/fpdfdoc/cpdf_filespec_unittest.cpp index d164165f00da932242b4d0111cff2ecac28b3df7..73fc8a4ae8a3ccd37cefde3a778f511c5b665774 100644 --- a/core/fpdfdoc/cpdf_filespec_unittest.cpp +++ b/core/fpdfdoc/cpdf_filespec_unittest.cpp @@ -3,22 +3,26 @@ // found in the LICENSE file. #include +#include #include #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfdoc/cpdf_filespec.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" +#include "third_party/base/ptr_util.h" TEST(cpdf_filespec, EncodeDecodeFileName) { - std::vector test_data = { + static const std::vector test_data = { // Empty src string. {L"", L""}, // only file name. {L"test.pdf", L"test.pdf"}, -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ // With drive identifier. {L"r:\\pdfdocs\\spec.pdf", L"/r/pdfdocs/spec.pdf"}, // Relative path. @@ -29,7 +33,7 @@ TEST(cpdf_filespec, EncodeDecodeFileName) { {L"\\\\pdfdocs\\spec.pdf", L"/pdfdocs/spec.pdf"}, // Network resource name. It is not supported yet. // {L"pclib/eng:\\pdfdocs\\spec.pdf", L"/pclib/eng/pdfdocs/spec.pdf"}, -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ // Absolute path with colon separator. {L"Mac HD:PDFDocs:spec.pdf", L"/Mac HD/PDFDocs/spec.pdf"}, // Relative path with colon separator. @@ -44,22 +48,22 @@ TEST(cpdf_filespec, EncodeDecodeFileName) { #endif }; for (const auto& data : test_data) { - CFX_WideString encoded_str = CPDF_FileSpec::EncodeFileName(data.input); - EXPECT_TRUE(encoded_str == data.expected); + EXPECT_STREQ(data.expected, + CPDF_FileSpec::EncodeFileName(data.input).c_str()); // DecodeFileName is the reverse procedure of EncodeFileName. - CFX_WideString decoded_str = CPDF_FileSpec::DecodeFileName(data.expected); - EXPECT_TRUE(decoded_str == data.input); + EXPECT_STREQ(data.input, + CPDF_FileSpec::DecodeFileName(data.expected).c_str()); } } TEST(cpdf_filespec, GetFileName) { { // String object. - pdfium::NullTermWstrFuncTestData test_data = { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + static const pdfium::NullTermWstrFuncTestData test_data = { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ L"/C/docs/test.pdf", L"C:\\docs\\test.pdf" -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ L"/Mac HD/docs/test.pdf", L"Mac HD:docs:test.pdf" #else @@ -67,23 +71,20 @@ TEST(cpdf_filespec, GetFileName) { L"/docs/test.pdf" #endif }; - std::unique_ptr str_obj( - new CPDF_String(nullptr, test_data.input)); + auto str_obj = pdfium::MakeUnique(nullptr, test_data.input); CPDF_FileSpec file_spec(str_obj.get()); - CFX_WideString file_name; - EXPECT_TRUE(file_spec.GetFileName(&file_name)); - EXPECT_TRUE(file_name == test_data.expected); + EXPECT_STREQ(test_data.expected, file_spec.GetFileName().c_str()); } { // Dictionary object. - pdfium::NullTermWstrFuncTestData test_data[5] = { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + static const pdfium::NullTermWstrFuncTestData test_data[] = { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ {L"/C/docs/test.pdf", L"C:\\docs\\test.pdf"}, {L"/D/docs/test.pdf", L"D:\\docs\\test.pdf"}, {L"/E/docs/test.pdf", L"E:\\docs\\test.pdf"}, {L"/F/docs/test.pdf", L"F:\\docs\\test.pdf"}, {L"/G/docs/test.pdf", L"G:\\docs\\test.pdf"}, -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ {L"/Mac HD/docs1/test.pdf", L"Mac HD:docs1:test.pdf"}, {L"/Mac HD/docs2/test.pdf", L"Mac HD:docs2:test.pdf"}, {L"/Mac HD/docs3/test.pdf", L"Mac HD:docs3:test.pdf"}, @@ -98,37 +99,36 @@ TEST(cpdf_filespec, GetFileName) { #endif }; // Keyword fields in reverse order of precedence to retrieve the file name. - const char* const keywords[5] = {"Unix", "Mac", "DOS", "F", "UF"}; - std::unique_ptr dict_obj(new CPDF_Dictionary()); + const char* const keywords[] = {"Unix", "Mac", "DOS", "F", "UF"}; + static_assert(FX_ArraySize(test_data) == FX_ArraySize(keywords), + "size mismatch"); + auto dict_obj = pdfium::MakeUnique(); CPDF_FileSpec file_spec(dict_obj.get()); - CFX_WideString file_name; - for (int i = 0; i < 5; ++i) { + EXPECT_TRUE(file_spec.GetFileName().IsEmpty()); + for (size_t i = 0; i < FX_ArraySize(keywords); ++i) { dict_obj->SetNewFor(keywords[i], test_data[i].input); - EXPECT_TRUE(file_spec.GetFileName(&file_name)); - EXPECT_TRUE(file_name == test_data[i].expected); + EXPECT_STREQ(test_data[i].expected, file_spec.GetFileName().c_str()); } // With all the former fields and 'FS' field suggests 'URL' type. dict_obj->SetNewFor("FS", "URL", false); - EXPECT_TRUE(file_spec.GetFileName(&file_name)); // Url string is not decoded. - EXPECT_TRUE(file_name == test_data[4].input); + EXPECT_STREQ(test_data[4].input, file_spec.GetFileName().c_str()); } { // Invalid object. - std::unique_ptr name_obj(new CPDF_Name(nullptr, "test.pdf")); + auto name_obj = pdfium::MakeUnique(nullptr, "test.pdf"); CPDF_FileSpec file_spec(name_obj.get()); - CFX_WideString file_name; - EXPECT_FALSE(file_spec.GetFileName(&file_name)); + EXPECT_TRUE(file_spec.GetFileName().IsEmpty()); } } TEST(cpdf_filespec, SetFileName) { - pdfium::NullTermWstrFuncTestData test_data = { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + static const pdfium::NullTermWstrFuncTestData test_data = { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ L"C:\\docs\\test.pdf", L"/C/docs/test.pdf" -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ L"Mac HD:docs:test.pdf", L"/Mac HD/docs/test.pdf" #else @@ -137,27 +137,117 @@ TEST(cpdf_filespec, SetFileName) { #endif }; // String object. - std::unique_ptr str_obj(new CPDF_String(nullptr, L"babababa")); + auto str_obj = pdfium::MakeUnique(nullptr, L"babababa"); CPDF_FileSpec file_spec1(str_obj.get()); file_spec1.SetFileName(test_data.input); // Check internal object value. - CFX_ByteString str = CFX_ByteString::FromUnicode(test_data.expected); - EXPECT_TRUE(str == str_obj->GetString()); + EXPECT_STREQ(test_data.expected, str_obj->GetUnicodeText().c_str()); // Check we can get the file name back. - CFX_WideString file_name; - EXPECT_TRUE(file_spec1.GetFileName(&file_name)); - EXPECT_TRUE(file_name == test_data.input); + EXPECT_STREQ(test_data.input, file_spec1.GetFileName().c_str()); // Dictionary object. - std::unique_ptr dict_obj(new CPDF_Dictionary()); + auto dict_obj = pdfium::MakeUnique(); CPDF_FileSpec file_spec2(dict_obj.get()); file_spec2.SetFileName(test_data.input); // Check internal object value. - file_name = dict_obj->GetUnicodeTextFor("F"); - EXPECT_TRUE(file_name == test_data.expected); - file_name = dict_obj->GetUnicodeTextFor("UF"); - EXPECT_TRUE(file_name == test_data.expected); + EXPECT_STREQ(test_data.expected, dict_obj->GetUnicodeTextFor("F").c_str()); + EXPECT_STREQ(test_data.expected, dict_obj->GetUnicodeTextFor("UF").c_str()); // Check we can get the file name back. - EXPECT_TRUE(file_spec2.GetFileName(&file_name)); - EXPECT_TRUE(file_name == test_data.input); + EXPECT_STREQ(test_data.input, file_spec2.GetFileName().c_str()); +} + +TEST(cpdf_filespec, GetFileStream) { + { + // Invalid object. + auto name_obj = pdfium::MakeUnique(nullptr, "test.pdf"); + CPDF_FileSpec file_spec(name_obj.get()); + EXPECT_FALSE(file_spec.GetFileStream()); + } + { + // Dictionary object missing its embedded files dictionary. + auto dict_obj = pdfium::MakeUnique(); + CPDF_FileSpec file_spec(dict_obj.get()); + EXPECT_FALSE(file_spec.GetFileStream()); + } + { + // Dictionary object with an empty embedded files dictionary. + auto dict_obj = pdfium::MakeUnique(); + dict_obj->SetNewFor("EF"); + CPDF_FileSpec file_spec(dict_obj.get()); + EXPECT_FALSE(file_spec.GetFileStream()); + } + { + // Dictionary object with a non-empty embedded files dictionary. + auto dict_obj = pdfium::MakeUnique(); + dict_obj->SetNewFor("EF"); + CPDF_FileSpec file_spec(dict_obj.get()); + + const wchar_t file_name[] = L"test.pdf"; + const char* const keys[] = {"Unix", "Mac", "DOS", "F", "UF"}; + const char* const streams[] = {"test1", "test2", "test3", "test4", "test5"}; + static_assert(FX_ArraySize(keys) == FX_ArraySize(streams), "size mismatch"); + CPDF_Dictionary* file_dict = + file_spec.GetObj()->AsDictionary()->GetDictFor("EF"); + + // Keys in reverse order of precedence to retrieve the file content stream. + for (size_t i = 0; i < FX_ArraySize(keys); ++i) { + // Set the file name. + dict_obj->SetNewFor(keys[i], file_name); + + // Set the file stream. + auto pDict = pdfium::MakeUnique(); + size_t buf_len = strlen(streams[i]) + 1; + std::unique_ptr buf(FX_Alloc(uint8_t, buf_len)); + memcpy(buf.get(), streams[i], buf_len); + file_dict->SetNewFor(keys[i], std::move(buf), buf_len, + std::move(pDict)); + + // Check that the file content stream is as expected. + EXPECT_STREQ( + streams[i], + file_spec.GetFileStream()->GetUnicodeText().UTF8Encode().c_str()); + + if (i == 2) { + dict_obj->SetNewFor("FS", "URL", false); + EXPECT_FALSE(file_spec.GetFileStream()); + } + } + } +} + +TEST(cpdf_filespec, GetParamsDict) { + { + // Invalid object. + auto name_obj = pdfium::MakeUnique(nullptr, "test.pdf"); + CPDF_FileSpec file_spec(name_obj.get()); + EXPECT_FALSE(file_spec.GetParamsDict()); + } + { + // Dictionary object. + auto dict_obj = pdfium::MakeUnique(); + dict_obj->SetNewFor("EF"); + dict_obj->SetNewFor("UF", L"test.pdf"); + CPDF_FileSpec file_spec(dict_obj.get()); + EXPECT_FALSE(file_spec.GetParamsDict()); + + // Add a file stream to the embedded files dictionary. + CPDF_Dictionary* file_dict = + file_spec.GetObj()->AsDictionary()->GetDictFor("EF"); + auto pDict = pdfium::MakeUnique(); + std::unique_ptr buf(FX_Alloc(uint8_t, 6)); + memcpy(buf.get(), "hello", 6); + file_dict->SetNewFor("UF", std::move(buf), 6, + std::move(pDict)); + + // Add a params dictionary to the file stream. + CPDF_Stream* stream = file_dict->GetStreamFor("UF"); + CPDF_Dictionary* stream_dict = stream->GetDict(); + stream_dict->SetNewFor("Params"); + EXPECT_TRUE(file_spec.GetParamsDict()); + + // Add a parameter to the params dictionary. + CPDF_Dictionary* params_dict = stream_dict->GetDictFor("Params"); + params_dict->SetNewFor("Size", 6); + EXPECT_EQ(6, file_spec.GetParamsDict()->GetIntegerFor("Size")); + } } diff --git a/core/fpdfdoc/cpdf_formcontrol.cpp b/core/fpdfdoc/cpdf_formcontrol.cpp index 54edb4910c0553d3b356b3238ba990e57b133df1..384c35ea12fc1a60fa494b8b09277e70eb494303 100644 --- a/core/fpdfdoc/cpdf_formcontrol.cpp +++ b/core/fpdfdoc/cpdf_formcontrol.cpp @@ -20,7 +20,7 @@ namespace { -const FX_CHAR* const g_sHighlightingMode[] = { +const char* const g_sHighlightingMode[] = { // Must match order of HighlightingMode enum. "N", "I", "O", "P", "T"}; @@ -30,12 +30,14 @@ CPDF_FormControl::CPDF_FormControl(CPDF_FormField* pField, CPDF_Dictionary* pWidgetDict) : m_pField(pField), m_pWidgetDict(pWidgetDict), - m_pForm(m_pField->m_pForm) {} + m_pForm(m_pField->GetForm()) {} -CFX_ByteString CPDF_FormControl::GetOnStateName() const { +CPDF_FormControl::~CPDF_FormControl() {} + +ByteString CPDF_FormControl::GetOnStateName() const { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CFX_ByteString csOn; + ByteString csOn; CPDF_Dictionary* pAP = m_pWidgetDict->GetDictFor("AP"); if (!pAP) return csOn; @@ -48,19 +50,19 @@ CFX_ByteString CPDF_FormControl::GetOnStateName() const { if (it.first != "Off") return it.first; } - return CFX_ByteString(); + return ByteString(); } -void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn) { +void CPDF_FormControl::SetOnStateName(const ByteString& csOn) { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CFX_ByteString csValue = csOn; + ByteString csValue = csOn; if (csValue.IsEmpty()) csValue = "Yes"; else if (csValue == "Off") csValue = "Yes"; - CFX_ByteString csAS = m_pWidgetDict->GetStringFor("AS", "Off"); + ByteString csAS = m_pWidgetDict->GetStringFor("AS", "Off"); if (csAS != "Off") m_pWidgetDict->SetNewFor("AS", csValue); @@ -80,7 +82,7 @@ void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn) { auto subdict_it = pSubDict->begin(); while (subdict_it != pSubDict->end()) { - const CFX_ByteString& csKey2 = subdict_it->first; + const ByteString& csKey2 = subdict_it->first; CPDF_Object* pObj2 = subdict_it->second.get(); ++subdict_it; if (!pObj2) @@ -93,30 +95,28 @@ void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn) { } } -CFX_ByteString CPDF_FormControl::GetCheckedAPState() { +ByteString CPDF_FormControl::GetCheckedAPState() { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CFX_ByteString csOn = GetOnStateName(); + ByteString csOn = GetOnStateName(); if (GetType() == CPDF_FormField::RadioButton || GetType() == CPDF_FormField::CheckBox) { - if (ToArray(FPDF_GetFieldAttr(m_pField->m_pDict, "Opt"))) { - int iIndex = m_pField->GetControlIndex(this); - csOn.Format("%d", iIndex); - } + if (ToArray(FPDF_GetFieldAttr(m_pField->GetDict(), "Opt"))) + csOn = ByteString::Format("%d", m_pField->GetControlIndex(this)); } if (csOn.IsEmpty()) csOn = "Yes"; return csOn; } -CFX_WideString CPDF_FormControl::GetExportValue() const { +WideString CPDF_FormControl::GetExportValue() const { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CFX_ByteString csOn = GetOnStateName(); + ByteString csOn = GetOnStateName(); if (GetType() == CPDF_FormField::RadioButton || GetType() == CPDF_FormField::CheckBox) { if (CPDF_Array* pArray = - ToArray(FPDF_GetFieldAttr(m_pField->m_pDict, "Opt"))) { + ToArray(FPDF_GetFieldAttr(m_pField->GetDict(), "Opt"))) { int iIndex = m_pField->GetControlIndex(this); csOn = pArray->GetStringAt(iIndex); } @@ -129,29 +129,29 @@ CFX_WideString CPDF_FormControl::GetExportValue() const { bool CPDF_FormControl::IsChecked() const { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CFX_ByteString csOn = GetOnStateName(); - CFX_ByteString csAS = m_pWidgetDict->GetStringFor("AS"); + ByteString csOn = GetOnStateName(); + ByteString csAS = m_pWidgetDict->GetStringFor("AS"); return csAS == csOn; } bool CPDF_FormControl::IsDefaultChecked() const { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CPDF_Object* pDV = FPDF_GetFieldAttr(m_pField->m_pDict, "DV"); + CPDF_Object* pDV = FPDF_GetFieldAttr(m_pField->GetDict(), "DV"); if (!pDV) return false; - CFX_ByteString csDV = pDV->GetString(); - CFX_ByteString csOn = GetOnStateName(); + ByteString csDV = pDV->GetString(); + ByteString csOn = GetOnStateName(); return (csDV == csOn); } void CPDF_FormControl::CheckControl(bool bChecked) { ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton); - CFX_ByteString csOn = GetOnStateName(); - CFX_ByteString csOldAS = m_pWidgetDict->GetStringFor("AS", "Off"); - CFX_ByteString csAS = "Off"; + ByteString csOn = GetOnStateName(); + ByteString csOldAS = m_pWidgetDict->GetStringFor("AS", "Off"); + ByteString csAS = "Off"; if (bChecked) csAS = csOn; if (csOldAS == csAS) @@ -167,20 +167,20 @@ void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, if (m_pWidgetDict->GetIntegerFor("F") & ANNOTFLAG_HIDDEN) return; - CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode); + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict.Get(), mode); if (!pStream) return; - CFX_FloatRect form_bbox = pStream->GetDict()->GetRectFor("BBox"); CFX_Matrix form_matrix = pStream->GetDict()->GetMatrixFor("Matrix"); - form_matrix.TransformRect(form_bbox); + CFX_FloatRect form_bbox = + form_matrix.TransformRect(pStream->GetDict()->GetRectFor("BBox")); CFX_FloatRect arect = m_pWidgetDict->GetRectFor("Rect"); CFX_Matrix matrix; matrix.MatchRect(arect, form_bbox); matrix.Concat(*pMatrix); - CPDF_Form form(m_pField->m_pForm->m_pDocument, - m_pField->m_pForm->m_pFormDict->GetDictFor("DR"), pStream); - form.ParseContent(nullptr, nullptr, nullptr); + CPDF_Form form(m_pField->GetForm()->GetDocument(), + m_pField->GetForm()->GetFormDict()->GetDictFor("DR"), pStream); + form.ParseContent(); CPDF_RenderContext context(pPage); context.AppendLayer(&form, &matrix); context.Render(pDevice, pOptions, nullptr); @@ -190,7 +190,7 @@ CPDF_FormControl::HighlightingMode CPDF_FormControl::GetHighlightingMode() { if (!m_pWidgetDict) return Invert; - CFX_ByteString csH = m_pWidgetDict->GetStringFor("H", "I"); + ByteString csH = m_pWidgetDict->GetStringFor("H", "I"); for (size_t i = 0; i < FX_ArraySize(g_sHighlightingMode); ++i) { if (csH == g_sHighlightingMode[i]) return static_cast(i); @@ -203,7 +203,7 @@ CPDF_ApSettings CPDF_FormControl::GetMK() const { : nullptr); } -bool CPDF_FormControl::HasMKEntry(const CFX_ByteString& csEntry) const { +bool CPDF_FormControl::HasMKEntry(const ByteString& csEntry) const { return GetMK().HasMKEntry(csEntry); } @@ -211,27 +211,25 @@ int CPDF_FormControl::GetRotation() { return GetMK().GetRotation(); } -FX_ARGB CPDF_FormControl::GetColor(int& iColorType, - const CFX_ByteString& csEntry) { +FX_ARGB CPDF_FormControl::GetColor(int& iColorType, const ByteString& csEntry) { return GetMK().GetColor(iColorType, csEntry); } -FX_FLOAT CPDF_FormControl::GetOriginalColor(int index, - const CFX_ByteString& csEntry) { +float CPDF_FormControl::GetOriginalColor(int index, const ByteString& csEntry) { return GetMK().GetOriginalColor(index, csEntry); } void CPDF_FormControl::GetOriginalColor(int& iColorType, - FX_FLOAT fc[4], - const CFX_ByteString& csEntry) { + float fc[4], + const ByteString& csEntry) { GetMK().GetOriginalColor(iColorType, fc, csEntry); } -CFX_WideString CPDF_FormControl::GetCaption(const CFX_ByteString& csEntry) { +WideString CPDF_FormControl::GetCaption(const ByteString& csEntry) { return GetMK().GetCaption(csEntry); } -CPDF_Stream* CPDF_FormControl::GetIcon(const CFX_ByteString& csEntry) { +CPDF_Stream* CPDF_FormControl::GetIcon(const ByteString& csEntry) { return GetMK().GetIcon(csEntry); } @@ -245,21 +243,18 @@ int CPDF_FormControl::GetTextPosition() { CPDF_Action CPDF_FormControl::GetAction() { if (!m_pWidgetDict) - return CPDF_Action(); + return CPDF_Action(nullptr); if (m_pWidgetDict->KeyExist("A")) return CPDF_Action(m_pWidgetDict->GetDictFor("A")); - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "A"); - if (!pObj) - return CPDF_Action(); - - return CPDF_Action(pObj->GetDict()); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->GetDict(), "A"); + return CPDF_Action(pObj ? pObj->GetDict() : nullptr); } CPDF_AAction CPDF_FormControl::GetAdditionalAction() { if (!m_pWidgetDict) - return CPDF_AAction(); + return CPDF_AAction(nullptr); if (m_pWidgetDict->KeyExist("AA")) return CPDF_AAction(m_pWidgetDict->GetDictFor("AA")); @@ -273,33 +268,33 @@ CPDF_DefaultAppearance CPDF_FormControl::GetDefaultAppearance() { if (m_pWidgetDict->KeyExist("DA")) return CPDF_DefaultAppearance(m_pWidgetDict->GetStringFor("DA")); - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "DA"); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->GetDict(), "DA"); if (pObj) return CPDF_DefaultAppearance(pObj->GetString()); - return m_pField->m_pForm->GetDefaultAppearance(); + return m_pField->GetForm()->GetDefaultAppearance(); } CPDF_Font* CPDF_FormControl::GetDefaultControlFont() { + float fFontSize; CPDF_DefaultAppearance cDA = GetDefaultAppearance(); - CFX_ByteString csFontNameTag; - FX_FLOAT fFontSize; - cDA.GetFont(csFontNameTag, fFontSize); + ByteString csFontNameTag = cDA.GetFont(&fFontSize); if (csFontNameTag.IsEmpty()) return nullptr; - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pWidgetDict, "DR"); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pWidgetDict.Get(), "DR"); if (CPDF_Dictionary* pDict = ToDictionary(pObj)) { CPDF_Dictionary* pFonts = pDict->GetDictFor("Font"); if (pFonts) { CPDF_Dictionary* pElement = pFonts->GetDictFor(csFontNameTag); if (pElement) { - CPDF_Font* pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement); + CPDF_Font* pFont = + m_pField->GetForm()->GetDocument()->LoadFont(pElement); if (pFont) return pFont; } } } - if (CPDF_Font* pFormFont = m_pField->m_pForm->GetFormFont(csFontNameTag)) + if (CPDF_Font* pFormFont = m_pField->GetForm()->GetFormFont(csFontNameTag)) return pFormFont; CPDF_Dictionary* pPageDict = m_pWidgetDict->GetDictFor("P"); @@ -309,7 +304,8 @@ CPDF_Font* CPDF_FormControl::GetDefaultControlFont() { if (pFonts) { CPDF_Dictionary* pElement = pFonts->GetDictFor(csFontNameTag); if (pElement) { - CPDF_Font* pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement); + CPDF_Font* pFont = + m_pField->GetForm()->GetDocument()->LoadFont(pElement); if (pFont) return pFont; } @@ -324,8 +320,8 @@ int CPDF_FormControl::GetControlAlignment() { if (m_pWidgetDict->KeyExist("Q")) return m_pWidgetDict->GetIntegerFor("Q", 0); - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "Q"); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->GetDict(), "Q"); if (pObj) return pObj->GetInteger(); - return m_pField->m_pForm->GetFormAlignment(); + return m_pField->GetForm()->GetFormAlignment(); } diff --git a/core/fpdfdoc/cpdf_formcontrol.h b/core/fpdfdoc/cpdf_formcontrol.h index c0dad39098520f612670142616bc980d93db9216..6485af0b441c09d08fcace3c7989c05f014cc5e7 100644 --- a/core/fpdfdoc/cpdf_formcontrol.h +++ b/core/fpdfdoc/cpdf_formcontrol.h @@ -28,11 +28,6 @@ #define TEXTPOS_LEFT 5 #define TEXTPOS_OVERLAID 6 -#define COLORTYPE_TRANSPARENT 0 -#define COLORTYPE_GRAY 1 -#define COLORTYPE_RGB 2 -#define COLORTYPE_CMYK 3 - class CFX_RenderDevice; class CPDF_Dictionary; class CPDF_Font; @@ -47,11 +42,12 @@ class CPDF_FormControl { enum HighlightingMode { None = 0, Invert, Outline, Push, Toggle }; CPDF_FormControl(CPDF_FormField* pField, CPDF_Dictionary* pWidgetDict); + ~CPDF_FormControl(); CPDF_FormField::Type GetType() const { return m_pField->GetType(); } - CPDF_InterForm* GetInterForm() const { return m_pForm; } + const CPDF_InterForm* GetInterForm() const { return m_pForm.Get(); } CPDF_FormField* GetField() const { return m_pField; } - CPDF_Dictionary* GetWidget() const { return m_pWidgetDict; } + CPDF_Dictionary* GetWidget() const { return m_pWidgetDict.Get(); } CFX_FloatRect GetRect() const { return m_pWidgetDict->GetRectFor("Rect"); } void DrawControl(CFX_RenderDevice* pDevice, @@ -60,23 +56,23 @@ class CPDF_FormControl { CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions = nullptr); - CFX_ByteString GetCheckedAPState(); - CFX_WideString GetExportValue() const; + ByteString GetCheckedAPState(); + WideString GetExportValue() const; bool IsChecked() const; bool IsDefaultChecked() const; HighlightingMode GetHighlightingMode(); - bool HasMKEntry(const CFX_ByteString& csEntry) const; + bool HasMKEntry(const ByteString& csEntry) const; int GetRotation(); FX_ARGB GetBorderColor(int& iColorType) { return GetColor(iColorType, "BC"); } - FX_FLOAT GetOriginalBorderColor(int index) { + float GetOriginalBorderColor(int index) { return GetOriginalColor(index, "BC"); } - void GetOriginalBorderColor(int& iColorType, FX_FLOAT fc[4]) { + void GetOriginalBorderColor(int& iColorType, float fc[4]) { GetOriginalColor(iColorType, fc, "BC"); } @@ -84,17 +80,17 @@ class CPDF_FormControl { return GetColor(iColorType, "BG"); } - FX_FLOAT GetOriginalBackgroundColor(int index) { + float GetOriginalBackgroundColor(int index) { return GetOriginalColor(index, "BG"); } - void GetOriginalBackgroundColor(int& iColorType, FX_FLOAT fc[4]) { + void GetOriginalBackgroundColor(int& iColorType, float fc[4]) { GetOriginalColor(iColorType, fc, "BG"); } - CFX_WideString GetNormalCaption() { return GetCaption("CA"); } - CFX_WideString GetRolloverCaption() { return GetCaption("RC"); } - CFX_WideString GetDownCaption() { return GetCaption("AC"); } + WideString GetNormalCaption() { return GetCaption("CA"); } + WideString GetRolloverCaption() { return GetCaption("RC"); } + WideString GetDownCaption() { return GetCaption("AC"); } CPDF_Stream* GetNormalIcon() { return GetIcon("I"); } CPDF_Stream* GetRolloverIcon() { return GetIcon("RI"); } @@ -109,26 +105,24 @@ class CPDF_FormControl { CPDF_Font* GetDefaultControlFont(); int GetControlAlignment(); - private: - friend class CPDF_InterForm; - friend class CPDF_FormField; - - CFX_ByteString GetOnStateName() const; - void SetOnStateName(const CFX_ByteString& csOn); + ByteString GetOnStateName() const; void CheckControl(bool bChecked); - FX_ARGB GetColor(int& iColorType, const CFX_ByteString& csEntry); - FX_FLOAT GetOriginalColor(int index, const CFX_ByteString& csEntry); + + private: + void SetOnStateName(const ByteString& csOn); + FX_ARGB GetColor(int& iColorType, const ByteString& csEntry); + float GetOriginalColor(int index, const ByteString& csEntry); void GetOriginalColor(int& iColorType, - FX_FLOAT fc[4], - const CFX_ByteString& csEntry); + float fc[4], + const ByteString& csEntry); - CFX_WideString GetCaption(const CFX_ByteString& csEntry); - CPDF_Stream* GetIcon(const CFX_ByteString& csEntry); + WideString GetCaption(const ByteString& csEntry); + CPDF_Stream* GetIcon(const ByteString& csEntry); CPDF_ApSettings GetMK() const; CPDF_FormField* const m_pField; - CPDF_Dictionary* const m_pWidgetDict; - CPDF_InterForm* const m_pForm; + UnownedPtr const m_pWidgetDict; + UnownedPtr const m_pForm; }; #endif // CORE_FPDFDOC_CPDF_FORMCONTROL_H_ diff --git a/core/fpdfdoc/cpdf_formfield.cpp b/core/fpdfdoc/cpdf_formfield.cpp index b4aa90e2bebc2b99909f0b19769fc9811ecea1b7..df593697236eb0d8b9c739e4a6da2df98fd9b878 100644 --- a/core/fpdfdoc/cpdf_formfield.cpp +++ b/core/fpdfdoc/cpdf_formfield.cpp @@ -25,8 +25,6 @@ namespace { -const int kMaxRecursion = 32; - const int kFormListMultiSelect = 0x100; const int kFormComboEdit = 0x100; @@ -47,12 +45,19 @@ bool IsUnison(CPDF_FormField* pField) { } // namespace -CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict, - const FX_CHAR* name, +Optional IntToFormFieldType(int value) { + if (value >= static_cast(FormFieldType::kUnknown) && + value < static_cast(kFormFieldTypeCount)) { + return {static_cast(value)}; + } + return {}; +} + +CPDF_Object* FPDF_GetFieldAttr(const CPDF_Dictionary* pFieldDict, + const char* name, int nLevel) { - if (nLevel > kMaxRecursion) - return nullptr; - if (!pFieldDict) + static constexpr int kGetFieldMaxRecursion = 32; + if (!pFieldDict || nLevel > kGetFieldMaxRecursion) return nullptr; CPDF_Object* pAttr = pFieldDict->GetDirectObjectFor(name); @@ -60,18 +65,16 @@ CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict, return pAttr; CPDF_Dictionary* pParent = pFieldDict->GetDictFor("Parent"); - if (!pParent) - return nullptr; - return FPDF_GetFieldAttr(pParent, name, nLevel + 1); + return pParent ? FPDF_GetFieldAttr(pParent, name, nLevel + 1) : nullptr; } -CFX_WideString FPDF_GetFullName(CPDF_Dictionary* pFieldDict) { - CFX_WideString full_name; +WideString FPDF_GetFullName(CPDF_Dictionary* pFieldDict) { + WideString full_name; std::set visited; CPDF_Dictionary* pLevel = pFieldDict; while (pLevel) { visited.insert(pLevel); - CFX_WideString short_name = pLevel->GetUnicodeTextFor("T"); + WideString short_name = pLevel->GetUnicodeTextFor("T"); if (!short_name.IsEmpty()) { if (full_name.IsEmpty()) full_name = short_name; @@ -97,12 +100,10 @@ CPDF_FormField::CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict) CPDF_FormField::~CPDF_FormField() {} void CPDF_FormField::SyncFieldFlags() { - CFX_ByteString type_name = FPDF_GetFieldAttr(m_pDict, "FT") - ? FPDF_GetFieldAttr(m_pDict, "FT")->GetString() - : CFX_ByteString(); - uint32_t flags = FPDF_GetFieldAttr(m_pDict, "Ff") - ? FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger() - : 0; + CPDF_Object* ft_attr = FPDF_GetFieldAttr(m_pDict.Get(), "FT"); + ByteString type_name = ft_attr ? ft_attr->GetString() : ByteString(); + CPDF_Object* ff_attr = FPDF_GetFieldAttr(m_pDict.Get(), "Ff"); + uint32_t flags = ff_attr ? ff_attr->GetInteger() : 0; m_Flags = 0; if (flags & FORMFLAG_READONLY) m_Flags |= FORMFLAG_READONLY; @@ -156,8 +157,8 @@ void CPDF_FormField::SyncFieldFlags() { } } -CFX_WideString CPDF_FormField::GetFullName() const { - return FPDF_GetFullName(m_pDict); +WideString CPDF_FormField::GetFullName() const { + return FPDF_GetFullName(m_pDict.Get()); } bool CPDF_FormField::ResetField(bool bNotify) { @@ -176,13 +177,13 @@ bool CPDF_FormField::ResetField(bool bNotify) { CheckControl(i, GetControl(i)->IsDefaultChecked(), false); } } - if (bNotify && m_pForm->m_pFormNotify) - m_pForm->m_pFormNotify->AfterCheckedStatusChange(this); + if (bNotify && m_pForm->GetFormNotify()) + m_pForm->GetFormNotify()->AfterCheckedStatusChange(this); break; } case CPDF_FormField::ComboBox: case CPDF_FormField::ListBox: { - CFX_WideString csValue; + WideString csValue; ClearSelection(); int iIndex = GetDefaultSelectedItem(); if (iIndex >= 0) @@ -200,17 +201,17 @@ bool CPDF_FormField::ResetField(bool bNotify) { case CPDF_FormField::RichText: case CPDF_FormField::File: default: { - CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict, "DV"); - CFX_WideString csDValue; + CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict.Get(), "DV"); + WideString csDValue; if (pDV) csDValue = pDV->GetUnicodeText(); - CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V"); - CFX_WideString csValue; + CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict.Get(), "V"); + WideString csValue; if (pV) csValue = pV->GetUnicodeText(); - CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict, "RV"); + CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict.Get(), "RV"); if (!pRV && (csDValue == csValue)) return false; @@ -245,74 +246,73 @@ int CPDF_FormField::GetControlIndex(const CPDF_FormControl* pControl) const { return it != m_ControlList.end() ? it - m_ControlList.begin() : -1; } -int CPDF_FormField::GetFieldType() const { +FormFieldType CPDF_FormField::GetFieldType() const { switch (m_Type) { case PushButton: - return FIELDTYPE_PUSHBUTTON; + return FormFieldType::kPushButton; case CheckBox: - return FIELDTYPE_CHECKBOX; + return FormFieldType::kCheckBox; case RadioButton: - return FIELDTYPE_RADIOBUTTON; + return FormFieldType::kRadioButton; case ComboBox: - return FIELDTYPE_COMBOBOX; + return FormFieldType::kComboBox; case ListBox: - return FIELDTYPE_LISTBOX; + return FormFieldType::kListBox; case Text: case RichText: case File: - return FIELDTYPE_TEXTFIELD; + return FormFieldType::kTextField; case Sign: - return FIELDTYPE_SIGNATURE; + return FormFieldType::kSignature; default: - break; + return FormFieldType::kUnknown; } - return FIELDTYPE_UNKNOWN; } CPDF_AAction CPDF_FormField::GetAdditionalAction() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "AA"); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "AA"); return CPDF_AAction(pObj ? pObj->GetDict() : nullptr); } -CFX_WideString CPDF_FormField::GetAlternateName() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TU"); +WideString CPDF_FormField::GetAlternateName() const { + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "TU"); return pObj ? pObj->GetUnicodeText() : L""; } -CFX_WideString CPDF_FormField::GetMappingName() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TM"); +WideString CPDF_FormField::GetMappingName() const { + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "TM"); return pObj ? pObj->GetUnicodeText() : L""; } uint32_t CPDF_FormField::GetFieldFlags() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "Ff"); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "Ff"); return pObj ? pObj->GetInteger() : 0; } -CFX_ByteString CPDF_FormField::GetDefaultStyle() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DS"); +ByteString CPDF_FormField::GetDefaultStyle() const { + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "DS"); return pObj ? pObj->GetString() : ""; } -CFX_WideString CPDF_FormField::GetRichTextString() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "RV"); +WideString CPDF_FormField::GetRichTextString() const { + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "RV"); return pObj ? pObj->GetUnicodeText() : L""; } -CFX_WideString CPDF_FormField::GetValue(bool bDefault) const { +WideString CPDF_FormField::GetValue(bool bDefault) const { if (GetType() == CheckBox || GetType() == RadioButton) return GetCheckValue(bDefault); - CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, bDefault ? "DV" : "V"); + CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict.Get(), bDefault ? "DV" : "V"); if (!pValue) { if (!bDefault) { if (m_Type == RichText) - pValue = FPDF_GetFieldAttr(m_pDict, "V"); + pValue = FPDF_GetFieldAttr(m_pDict.Get(), "V"); if (!pValue && m_Type != Text) - pValue = FPDF_GetFieldAttr(m_pDict, "DV"); + pValue = FPDF_GetFieldAttr(m_pDict.Get(), "DV"); } if (!pValue) - return CFX_WideString(); + return WideString(); } switch (pValue->GetType()) { @@ -327,18 +327,18 @@ CFX_WideString CPDF_FormField::GetValue(bool bDefault) const { default: break; } - return CFX_WideString(); + return WideString(); } -CFX_WideString CPDF_FormField::GetValue() const { +WideString CPDF_FormField::GetValue() const { return GetValue(false); } -CFX_WideString CPDF_FormField::GetDefaultValue() const { +WideString CPDF_FormField::GetDefaultValue() const { return GetValue(true); } -bool CPDF_FormField::SetValue(const CFX_WideString& value, +bool CPDF_FormField::SetValue(const WideString& value, bool bDefault, bool bNotify) { switch (m_Type) { @@ -351,14 +351,14 @@ bool CPDF_FormField::SetValue(const CFX_WideString& value, case RichText: case Text: case ComboBox: { - CFX_WideString csValue = value; + WideString csValue = value; if (bNotify && !NotifyBeforeValueChange(csValue)) return false; - CFX_ByteString key(bDefault ? "DV" : "V"); + ByteString key(bDefault ? "DV" : "V"); int iIndex = FindOptionValue(csValue); if (iIndex < 0) { - CFX_ByteString bsEncodeText = PDF_EncodeText(csValue); + ByteString bsEncodeText = PDF_EncodeText(csValue); m_pDict->SetNewFor(key, bsEncodeText, false); if (m_Type == RichText && !bDefault) m_pDict->SetNewFor("RV", bsEncodeText, false); @@ -399,18 +399,18 @@ bool CPDF_FormField::SetValue(const CFX_WideString& value, return true; } -bool CPDF_FormField::SetValue(const CFX_WideString& value, bool bNotify) { +bool CPDF_FormField::SetValue(const WideString& value, bool bNotify) { return SetValue(value, false, bNotify); } int CPDF_FormField::GetMaxLen() const { - if (CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen")) + if (CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "MaxLen")) return pObj->GetInteger(); - for (const auto& pControl : m_ControlList) { + for (auto& pControl : m_ControlList) { if (!pControl) continue; - CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict; + CPDF_Dictionary* pWidgetDict = pControl->GetWidget(); if (pWidgetDict->KeyExist("MaxLen")) return pWidgetDict->GetIntegerFor("MaxLen"); } @@ -418,9 +418,9 @@ int CPDF_FormField::GetMaxLen() const { } int CPDF_FormField::CountSelectedItems() const { - CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); + CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict.Get(), "V"); if (!pValue) { - pValue = FPDF_GetFieldAttr(m_pDict, "I"); + pValue = FPDF_GetFieldAttr(m_pDict.Get(), "I"); if (!pValue) return 0; } @@ -433,16 +433,16 @@ int CPDF_FormField::CountSelectedItems() const { } int CPDF_FormField::GetSelectedIndex(int index) const { - CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); + CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict.Get(), "V"); if (!pValue) { - pValue = FPDF_GetFieldAttr(m_pDict, "I"); + pValue = FPDF_GetFieldAttr(m_pDict.Get(), "I"); if (!pValue) return -1; } if (pValue->IsNumber()) return pValue->GetInteger(); - CFX_WideString sel_value; + WideString sel_value; if (pValue->IsString()) { if (index != 0) return -1; @@ -453,12 +453,11 @@ int CPDF_FormField::GetSelectedIndex(int index) const { return -1; CPDF_Object* elementValue = pArray->GetDirectObjectAt(index); - sel_value = - elementValue ? elementValue->GetUnicodeText() : CFX_WideString(); + sel_value = elementValue ? elementValue->GetUnicodeText() : WideString(); } if (index < CountSelectedOptions()) { int iOptIndex = GetSelectedOptionIndex(index); - CFX_WideString csOpt = GetOptionValue(iOptIndex); + WideString csOpt = GetOptionValue(iOptIndex); if (csOpt == sel_value) return iOptIndex; } @@ -470,8 +469,8 @@ int CPDF_FormField::GetSelectedIndex(int index) const { } bool CPDF_FormField::ClearSelection(bool bNotify) { - if (bNotify && m_pForm->m_pFormNotify) { - CFX_WideString csValue; + if (bNotify && m_pForm->GetFormNotify()) { + WideString csValue; int iIndex = GetSelectedIndex(0); if (iIndex >= 0) csValue = GetOptionLabel(iIndex); @@ -493,10 +492,10 @@ bool CPDF_FormField::IsItemSelected(int index) const { if (IsOptionSelected(index)) return true; - CFX_WideString opt_value = GetOptionValue(index); - CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); + WideString opt_value = GetOptionValue(index); + CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict.Get(), "V"); if (!pValue) { - pValue = FPDF_GetFieldAttr(m_pDict, "I"); + pValue = FPDF_GetFieldAttr(m_pDict.Get(), "I"); if (!pValue) return false; } @@ -534,7 +533,7 @@ bool CPDF_FormField::SetItemSelection(int index, bool bSelected, bool bNotify) { if (index < 0 || index >= CountOptions()) return false; - CFX_WideString opt_value = GetOptionValue(index); + WideString opt_value = GetOptionValue(index); if (bNotify && !NotifyListOrComboBoxBeforeChange(opt_value)) return false; @@ -558,7 +557,7 @@ bool CPDF_FormField::SetItemSelection(int index, bool bSelected, bool bNotify) { pI->AddNew(index); } } else { - CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); + CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict.Get(), "V"); if (pValue) { if (GetType() == ListBox) { SelectOption(index, false); @@ -566,7 +565,7 @@ bool CPDF_FormField::SetItemSelection(int index, bool bSelected, bool bNotify) { if (pValue->GetUnicodeText() == opt_value) m_pDict->RemoveFor("V"); } else if (pValue->IsArray()) { - std::unique_ptr pArray(new CPDF_Array); + auto pArray = pdfium::MakeUnique(); for (int i = 0; i < CountOptions(); i++) { if (i != index && IsItemSelected(i)) { opt_value = GetOptionValue(i); @@ -597,10 +596,10 @@ bool CPDF_FormField::IsItemDefaultSelected(int index) const { int CPDF_FormField::GetDefaultSelectedItem() const { ASSERT(GetType() == ComboBox || GetType() == ListBox); - CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV"); + CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict.Get(), "DV"); if (!pValue) return -1; - CFX_WideString csDV = pValue->GetUnicodeText(); + WideString csDV = pValue->GetUnicodeText(); if (csDV.IsEmpty()) return -1; for (int i = 0; i < CountOptions(); i++) { @@ -611,34 +610,34 @@ int CPDF_FormField::GetDefaultSelectedItem() const { } int CPDF_FormField::CountOptions() const { - CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt")); + CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict.Get(), "Opt")); return pArray ? pArray->GetCount() : 0; } -CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index) const { - CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt")); +WideString CPDF_FormField::GetOptionText(int index, int sub_index) const { + CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict.Get(), "Opt")); if (!pArray) - return CFX_WideString(); + return WideString(); CPDF_Object* pOption = pArray->GetDirectObjectAt(index); if (!pOption) - return CFX_WideString(); + return WideString(); if (CPDF_Array* pOptionArray = pOption->AsArray()) pOption = pOptionArray->GetDirectObjectAt(sub_index); CPDF_String* pString = ToString(pOption); - return pString ? pString->GetUnicodeText() : CFX_WideString(); + return pString ? pString->GetUnicodeText() : WideString(); } -CFX_WideString CPDF_FormField::GetOptionLabel(int index) const { +WideString CPDF_FormField::GetOptionLabel(int index) const { return GetOptionText(index, 1); } -CFX_WideString CPDF_FormField::GetOptionValue(int index) const { +WideString CPDF_FormField::GetOptionValue(int index) const { return GetOptionText(index, 0); } -int CPDF_FormField::FindOption(CFX_WideString csOptLabel) const { +int CPDF_FormField::FindOption(WideString csOptLabel) const { for (int i = 0; i < CountOptions(); i++) { if (GetOptionValue(i) == csOptLabel) return i; @@ -646,7 +645,7 @@ int CPDF_FormField::FindOption(CFX_WideString csOptLabel) const { return -1; } -int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue) const { +int CPDF_FormField::FindOptionValue(const WideString& csOptValue) const { for (int i = 0; i < CountOptions(); i++) { if (GetOptionValue(i) == csOptValue) return i; @@ -655,7 +654,7 @@ int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue) const { } #ifdef PDF_ENABLE_XFA -int CPDF_FormField::InsertOption(CFX_WideString csOptLabel, +int CPDF_FormField::InsertOption(WideString csOptLabel, int index, bool bNotify) { if (csOptLabel.IsEmpty()) @@ -664,9 +663,8 @@ int CPDF_FormField::InsertOption(CFX_WideString csOptLabel, if (bNotify && !NotifyListOrComboBoxBeforeChange(csOptLabel)) return -1; - CFX_ByteString csStr = - PDF_EncodeText(csOptLabel.c_str(), csOptLabel.GetLength()); - CPDF_Array* pOpt = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt")); + ByteString csStr = PDF_EncodeText(csOptLabel); + CPDF_Array* pOpt = ToArray(FPDF_GetFieldAttr(m_pDict.Get(), "Opt")); if (!pOpt) pOpt = m_pDict->SetNewFor("Opt"); @@ -684,8 +682,8 @@ int CPDF_FormField::InsertOption(CFX_WideString csOptLabel, } bool CPDF_FormField::ClearOptions(bool bNotify) { - if (bNotify && m_pForm->m_pFormNotify) { - CFX_WideString csValue; + if (bNotify && m_pForm->GetFormNotify()) { + WideString csValue; int iIndex = GetSelectedIndex(0); if (iIndex >= 0) csValue = GetOptionLabel(iIndex); @@ -716,14 +714,14 @@ bool CPDF_FormField::CheckControl(int iControlIndex, if (!bChecked && pControl->IsChecked() == bChecked) return false; - CFX_WideString csWExport = pControl->GetExportValue(); - CFX_ByteString csBExport = PDF_EncodeText(csWExport); + WideString csWExport = pControl->GetExportValue(); + ByteString csBExport = PDF_EncodeText(csWExport); int iCount = CountControls(); bool bUnison = IsUnison(this); for (int i = 0; i < iCount; i++) { CPDF_FormControl* pCtrl = GetControl(i); if (bUnison) { - CFX_WideString csEValue = pCtrl->GetExportValue(); + WideString csEValue = pCtrl->GetExportValue(); if (csEValue == csWExport) { if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) pCtrl->CheckControl(bChecked); @@ -740,31 +738,29 @@ bool CPDF_FormField::CheckControl(int iControlIndex, } } - CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt"); + CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict.Get(), "Opt"); if (!ToArray(pOpt)) { if (bChecked) { m_pDict->SetNewFor("V", csBExport); } else { - CFX_ByteString csV; - CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V"); + ByteString csV; + CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict.Get(), "V"); if (pV) csV = pV->GetString(); if (csV == csBExport) m_pDict->SetNewFor("V", "Off"); } } else if (bChecked) { - CFX_ByteString csIndex; - csIndex.Format("%d", iControlIndex); - m_pDict->SetNewFor("V", csIndex); + m_pDict->SetNewFor("V", ByteString::Format("%d", iControlIndex)); } - if (bNotify && m_pForm->m_pFormNotify) - m_pForm->m_pFormNotify->AfterCheckedStatusChange(this); + if (bNotify && m_pForm->GetFormNotify()) + m_pForm->GetFormNotify()->AfterCheckedStatusChange(this); return true; } -CFX_WideString CPDF_FormField::GetCheckValue(bool bDefault) const { +WideString CPDF_FormField::GetCheckValue(bool bDefault) const { ASSERT(GetType() == CheckBox || GetType() == RadioButton); - CFX_WideString csExport = L"Off"; + WideString csExport = L"Off"; int iCount = CountControls(); for (int i = 0; i < iCount; i++) { CPDF_FormControl* pControl = GetControl(i); @@ -778,37 +774,37 @@ CFX_WideString CPDF_FormField::GetCheckValue(bool bDefault) const { return csExport; } -bool CPDF_FormField::SetCheckValue(const CFX_WideString& value, +bool CPDF_FormField::SetCheckValue(const WideString& value, bool bDefault, bool bNotify) { ASSERT(GetType() == CheckBox || GetType() == RadioButton); int iCount = CountControls(); for (int i = 0; i < iCount; i++) { CPDF_FormControl* pControl = GetControl(i); - CFX_WideString csExport = pControl->GetExportValue(); + WideString csExport = pControl->GetExportValue(); bool val = csExport == value; if (!bDefault) CheckControl(GetControlIndex(pControl), val); if (val) break; } - if (bNotify && m_pForm->m_pFormNotify) - m_pForm->m_pFormNotify->AfterCheckedStatusChange(this); + if (bNotify && m_pForm->GetFormNotify()) + m_pForm->GetFormNotify()->AfterCheckedStatusChange(this); return true; } int CPDF_FormField::GetTopVisibleIndex() const { - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI"); + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "TI"); return pObj ? pObj->GetInteger() : 0; } int CPDF_FormField::CountSelectedOptions() const { - CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "I")); + CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict.Get(), "I")); return pArray ? pArray->GetCount() : 0; } int CPDF_FormField::GetSelectedOptionIndex(int index) const { - CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "I")); + CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict.Get(), "I")); if (!pArray) return -1; @@ -819,7 +815,7 @@ int CPDF_FormField::GetSelectedOptionIndex(int index) const { } bool CPDF_FormField::IsOptionSelected(int iOptIndex) const { - CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "I")); + CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict.Get(), "I")); if (!pArray) return false; @@ -846,8 +842,8 @@ bool CPDF_FormField::SelectOption(int iOptIndex, bool bSelected, bool bNotify) { if (bSelected) return true; - if (bNotify && m_pForm->m_pFormNotify) { - CFX_WideString csValue = GetOptionLabel(iOptIndex); + if (bNotify && m_pForm->GetFormNotify()) { + WideString csValue = GetOptionLabel(iOptIndex); if (!NotifyListOrComboBoxBeforeChange(csValue)) return false; } @@ -860,8 +856,8 @@ bool CPDF_FormField::SelectOption(int iOptIndex, bool bSelected, bool bNotify) { if (!bSelected) continue; - if (bNotify && m_pForm->m_pFormNotify) { - CFX_WideString csValue = GetOptionLabel(iOptIndex); + if (bNotify && m_pForm->GetFormNotify()) { + WideString csValue = GetOptionLabel(iOptIndex); if (!NotifyListOrComboBoxBeforeChange(csValue)) return false; } @@ -884,8 +880,8 @@ bool CPDF_FormField::SelectOption(int iOptIndex, bool bSelected, bool bNotify) { } bool CPDF_FormField::ClearSelectedOptions(bool bNotify) { - if (bNotify && m_pForm->m_pFormNotify) { - CFX_WideString csValue; + if (bNotify && m_pForm->GetFormNotify()) { + WideString csValue; int iIndex = GetSelectedIndex(0); if (iIndex >= 0) csValue = GetOptionLabel(iIndex); @@ -901,12 +897,12 @@ bool CPDF_FormField::ClearSelectedOptions(bool bNotify) { } void CPDF_FormField::LoadDA() { - CPDF_Dictionary* pFormDict = m_pForm->m_pFormDict; + CPDF_Dictionary* pFormDict = m_pForm->GetFormDict(); if (!pFormDict) return; - CFX_ByteString DA; - if (CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DA")) + ByteString DA; + if (CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict.Get(), "DA")) DA = pObj->GetString(); if (DA.IsEmpty()) @@ -923,43 +919,42 @@ void CPDF_FormField::LoadDA() { if (!pFont) return; - CPDF_SimpleParser syntax(DA.AsStringC()); + CPDF_SimpleParser syntax(DA.AsStringView()); syntax.FindTagParamFromStart("Tf", 2); - CFX_ByteString font_name(syntax.GetWord()); + ByteString font_name(syntax.GetWord()); CPDF_Dictionary* pFontDict = pFont->GetDictFor(font_name); if (!pFontDict) return; - m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict); + m_pFont = m_pForm->GetDocument()->LoadFont(pFontDict); m_FontSize = FX_atof(syntax.GetWord()); } -bool CPDF_FormField::NotifyBeforeSelectionChange(const CFX_WideString& value) { - if (!m_pForm->m_pFormNotify) +bool CPDF_FormField::NotifyBeforeSelectionChange(const WideString& value) { + if (!m_pForm->GetFormNotify()) return true; - return m_pForm->m_pFormNotify->BeforeSelectionChange(this, value) >= 0; + return m_pForm->GetFormNotify()->BeforeSelectionChange(this, value) >= 0; } void CPDF_FormField::NotifyAfterSelectionChange() { - if (!m_pForm->m_pFormNotify) + if (!m_pForm->GetFormNotify()) return; - m_pForm->m_pFormNotify->AfterSelectionChange(this); + m_pForm->GetFormNotify()->AfterSelectionChange(this); } -bool CPDF_FormField::NotifyBeforeValueChange(const CFX_WideString& value) { - if (!m_pForm->m_pFormNotify) +bool CPDF_FormField::NotifyBeforeValueChange(const WideString& value) { + if (!m_pForm->GetFormNotify()) return true; - return m_pForm->m_pFormNotify->BeforeValueChange(this, value) >= 0; + return m_pForm->GetFormNotify()->BeforeValueChange(this, value) >= 0; } void CPDF_FormField::NotifyAfterValueChange() { - if (!m_pForm->m_pFormNotify) + if (!m_pForm->GetFormNotify()) return; - m_pForm->m_pFormNotify->AfterValueChange(this); + m_pForm->GetFormNotify()->AfterValueChange(this); } -bool CPDF_FormField::NotifyListOrComboBoxBeforeChange( - const CFX_WideString& value) { +bool CPDF_FormField::NotifyListOrComboBoxBeforeChange(const WideString& value) { switch (GetType()) { case ListBox: return NotifyBeforeSelectionChange(value); diff --git a/core/fpdfdoc/cpdf_formfield.h b/core/fpdfdoc/cpdf_formfield.h index 42608b1122d7f8bf4f628c238da6b8de98f0e6fc..4f25465b43be9f273bb798bc743b2e6d37ade5f2 100644 --- a/core/fpdfdoc/cpdf_formfield.h +++ b/core/fpdfdoc/cpdf_formfield.h @@ -7,23 +7,67 @@ #ifndef CORE_FPDFDOC_CPDF_FORMFIELD_H_ #define CORE_FPDFDOC_CPDF_FORMFIELD_H_ +#include +#include #include #include "core/fpdfdoc/cpdf_aaction.h" #include "core/fpdfdoc/cpdf_formfield.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #include "third_party/base/stl_util.h" -#define FIELDTYPE_UNKNOWN 0 -#define FIELDTYPE_PUSHBUTTON 1 -#define FIELDTYPE_CHECKBOX 2 -#define FIELDTYPE_RADIOBUTTON 3 -#define FIELDTYPE_COMBOBOX 4 -#define FIELDTYPE_LISTBOX 5 -#define FIELDTYPE_TEXTFIELD 6 -#define FIELDTYPE_SIGNATURE 7 +enum class FormFieldType : uint8_t { + kUnknown = 0, + kPushButton = 1, + kCheckBox = 2, + kRadioButton = 3, + kComboBox = 4, + kListBox = 5, + kTextField = 6, + kSignature = 7, +#ifdef PDF_ENABLE_XFA + kXFA = 8, // Generic XFA field, should use value below if possible. + kXFA_CheckBox = 9, + kXFA_ComboBox = 10, + kXFA_ImageField = 11, + kXFA_ListBox = 12, + kXFA_PushButton = 13, + kXFA_Signature = 14, + kXFA_TextField = 15 +#endif // PDF_ENABLE_XFA +}; + +Optional IntToFormFieldType(int value); + +// If values are added to FormFieldType, these will need to be updated. +#ifdef PDF_ENABLE_XFA +constexpr size_t kFormFieldTypeCount = 16; +#else +constexpr size_t kFormFieldTypeCount = 8; +#endif // PDF_ENABLE_XFA + +constexpr FormFieldType kFormFieldTypes[kFormFieldTypeCount] = { + FormFieldType::kUnknown, + FormFieldType::kPushButton, + FormFieldType::kCheckBox, + FormFieldType::kRadioButton, + FormFieldType::kComboBox, + FormFieldType::kListBox, + FormFieldType::kTextField, + FormFieldType::kSignature, +#ifdef PDF_ENABLE_XFA + FormFieldType::kXFA, + FormFieldType::kXFA_CheckBox, + FormFieldType::kXFA_ComboBox, + FormFieldType::kXFA_ImageField, + FormFieldType::kXFA_ListBox, + FormFieldType::kXFA_PushButton, + FormFieldType::kXFA_Signature, + FormFieldType::kXFA_TextField +#endif // PDF_ENABLE_XFA +}; #define FORMFLAG_READONLY 0x01 #define FORMFLAG_REQUIRED 0x02 @@ -35,10 +79,10 @@ class CPDF_FormControl; class CPDF_InterForm; class CPDF_String; -CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict, - const FX_CHAR* name, +CPDF_Object* FPDF_GetFieldAttr(const CPDF_Dictionary* pFieldDict, + const char* name, int nLevel = 0); -CFX_WideString FPDF_GetFullName(CPDF_Dictionary* pFieldDict); +WideString FPDF_GetFullName(CPDF_Dictionary* pFieldDict); class CPDF_FormField { public: @@ -55,12 +99,15 @@ class CPDF_FormField { Sign }; - CFX_WideString GetFullName() const; + CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict); + ~CPDF_FormField(); + + WideString GetFullName() const; Type GetType() const { return m_Type; } uint32_t GetFlags() const { return m_Flags; } - CPDF_Dictionary* GetFieldDict() const { return m_pDict; } + CPDF_Dictionary* GetFieldDict() const { return m_pDict.Get(); } void SetFieldDict(CPDF_Dictionary* pDict) { m_pDict = pDict; } bool ResetField(bool bNotify = false); @@ -69,22 +116,24 @@ class CPDF_FormField { return pdfium::CollectionSize(m_ControlList); } - CPDF_FormControl* GetControl(int index) const { return m_ControlList[index]; } + CPDF_FormControl* GetControl(int index) const { + return m_ControlList[index].Get(); + } int GetControlIndex(const CPDF_FormControl* pControl) const; - int GetFieldType() const; + FormFieldType GetFieldType() const; CPDF_AAction GetAdditionalAction() const; - CFX_WideString GetAlternateName() const; - CFX_WideString GetMappingName() const; + WideString GetAlternateName() const; + WideString GetMappingName() const; uint32_t GetFieldFlags() const; - CFX_ByteString GetDefaultStyle() const; - CFX_WideString GetRichTextString() const; + ByteString GetDefaultStyle() const; + WideString GetRichTextString() const; - CFX_WideString GetValue() const; - CFX_WideString GetDefaultValue() const; - bool SetValue(const CFX_WideString& value, bool bNotify = false); + WideString GetValue() const; + WideString GetDefaultValue() const; + bool SetValue(const WideString& value, bool bNotify = false); int GetMaxLen() const; int CountSelectedItems() const; @@ -99,11 +148,11 @@ class CPDF_FormField { int GetDefaultSelectedItem() const; int CountOptions() const; - CFX_WideString GetOptionLabel(int index) const; - CFX_WideString GetOptionValue(int index) const; + WideString GetOptionLabel(int index) const; + WideString GetOptionValue(int index) const; - int FindOption(CFX_WideString csOptLabel) const; - int FindOptionValue(const CFX_WideString& csOptValue) const; + int FindOption(WideString csOptLabel) const; + int FindOptionValue(const WideString& csOptValue) const; bool CheckControl(int iControlIndex, bool bChecked, bool bNotify = false); @@ -120,48 +169,53 @@ class CPDF_FormField { #ifdef PDF_ENABLE_XFA bool ClearOptions(bool bNotify = false); - int InsertOption(CFX_WideString csOptLabel, - int index = -1, - bool bNotify = false); + int InsertOption(WideString csOptLabel, int index = -1, bool bNotify = false); #endif // PDF_ENABLE_XFA - FX_FLOAT GetFontSize() const { return m_FontSize; } - CPDF_Font* GetFont() const { return m_pFont; } + float GetFontSize() const { return m_FontSize; } + CPDF_Font* GetFont() const { return m_pFont.Get(); } - private: - friend class CPDF_InterForm; - friend class CPDF_FormControl; + const CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } + const CPDF_InterForm* GetForm() const { return m_pForm.Get(); } - CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict); - ~CPDF_FormField(); + WideString GetCheckValue(bool bDefault) const; - CFX_WideString GetValue(bool bDefault) const; - bool SetValue(const CFX_WideString& value, bool bDefault, bool bNotify); + void AddFormControl(CPDF_FormControl* pFormControl) { + m_ControlList.emplace_back(pFormControl); + } + + void SetOpt(std::unique_ptr pOpt) { + m_pDict->SetFor("Opt", std::move(pOpt)); + } + + private: + WideString GetValue(bool bDefault) const; + bool SetValue(const WideString& value, bool bDefault, bool bNotify); void SyncFieldFlags(); int FindListSel(CPDF_String* str); - CFX_WideString GetOptionText(int index, int sub_index) const; + WideString GetOptionText(int index, int sub_index) const; void LoadDA(); - CFX_WideString GetCheckValue(bool bDefault) const; - bool SetCheckValue(const CFX_WideString& value, bool bDefault, bool bNotify); + bool SetCheckValue(const WideString& value, bool bDefault, bool bNotify); - bool NotifyBeforeSelectionChange(const CFX_WideString& value); + bool NotifyBeforeSelectionChange(const WideString& value); void NotifyAfterSelectionChange(); - bool NotifyBeforeValueChange(const CFX_WideString& value); + bool NotifyBeforeValueChange(const WideString& value); void NotifyAfterValueChange(); - bool NotifyListOrComboBoxBeforeChange(const CFX_WideString& value); + bool NotifyListOrComboBoxBeforeChange(const WideString& value); void NotifyListOrComboBoxAfterChange(); CPDF_FormField::Type m_Type; uint32_t m_Flags; - CPDF_InterForm* const m_pForm; - CPDF_Dictionary* m_pDict; - std::vector m_ControlList; // Owned by InterForm parent. - FX_FLOAT m_FontSize; - CPDF_Font* m_pFont; + UnownedPtr const m_pForm; + UnownedPtr m_pDict; + // Owned by InterForm parent. + std::vector> m_ControlList; + float m_FontSize; + UnownedPtr m_pFont; }; #endif // CORE_FPDFDOC_CPDF_FORMFIELD_H_ diff --git a/core/fpdfdoc/cpdf_formfield_unittest.cpp b/core/fpdfdoc/cpdf_formfield_unittest.cpp index 4aeda84c880ab8305c621fbd1a725cc607f17015..af5d15dab32447d43ba80b0c42623ab5e7a789dd 100644 --- a/core/fpdfdoc/cpdf_formfield_unittest.cpp +++ b/core/fpdfdoc/cpdf_formfield_unittest.cpp @@ -10,7 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" TEST(cpdf_formfield, FPDF_GetFullName) { - CFX_WideString name = FPDF_GetFullName(nullptr); + WideString name = FPDF_GetFullName(nullptr); EXPECT_TRUE(name.IsEmpty()); CPDF_IndirectObjectHolder obj_holder; diff --git a/core/fpdfdoc/cpdf_iconfit.cpp b/core/fpdfdoc/cpdf_iconfit.cpp index aedb7859129054db3814d213c4fa575f4294be28..20ed963e922cdfcf68862660b1402e5a042b2c26 100644 --- a/core/fpdfdoc/cpdf_iconfit.cpp +++ b/core/fpdfdoc/cpdf_iconfit.cpp @@ -10,11 +10,17 @@ #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fxcrt/fx_string.h" +CPDF_IconFit::CPDF_IconFit(const CPDF_Dictionary* pDict) : m_pDict(pDict) {} + +CPDF_IconFit::CPDF_IconFit(const CPDF_IconFit& that) = default; + +CPDF_IconFit::~CPDF_IconFit() {} + CPDF_IconFit::ScaleMethod CPDF_IconFit::GetScaleMethod() { if (!m_pDict) return Always; - CFX_ByteString csSW = m_pDict->GetStringFor("SW", "A"); + ByteString csSW = m_pDict->GetStringFor("SW", "A"); if (csSW == "B") return Bigger; if (csSW == "S") @@ -28,7 +34,7 @@ bool CPDF_IconFit::IsProportionalScale() { return m_pDict ? m_pDict->GetStringFor("S", "P") != "A" : true; } -void CPDF_IconFit::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom) { +void CPDF_IconFit::GetIconPosition(float& fLeft, float& fBottom) { fLeft = fBottom = 0.5; if (!m_pDict) return; diff --git a/core/fpdfdoc/cpdf_iconfit.h b/core/fpdfdoc/cpdf_iconfit.h index 37df48d43e51d78a9ef5031ed19a4840ef17fae5..e6aafb62e1c10dbf9da1dff00010a4e8f3226e4f 100644 --- a/core/fpdfdoc/cpdf_iconfit.h +++ b/core/fpdfdoc/cpdf_iconfit.h @@ -8,6 +8,7 @@ #define CORE_FPDFDOC_CPDF_ICONFIT_H_ #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; @@ -15,16 +16,18 @@ class CPDF_IconFit { public: enum ScaleMethod { Always = 0, Bigger, Smaller, Never }; - explicit CPDF_IconFit(const CPDF_Dictionary* pDict) : m_pDict(pDict) {} + explicit CPDF_IconFit(const CPDF_Dictionary* pDict); + CPDF_IconFit(const CPDF_IconFit& that); + ~CPDF_IconFit(); ScaleMethod GetScaleMethod(); bool IsProportionalScale(); - void GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom); + void GetIconPosition(float& fLeft, float& fBottom); bool GetFittingBounds(); - const CPDF_Dictionary* GetDict() const { return m_pDict; } + const CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } private: - const CPDF_Dictionary* const m_pDict; + UnownedPtr const m_pDict; }; #endif // CORE_FPDFDOC_CPDF_ICONFIT_H_ diff --git a/core/fpdfdoc/cpdf_interform.cpp b/core/fpdfdoc/cpdf_interform.cpp index d9f0db97479c55a3cbb9db8d7f819ac17e514907..1596b17d82141948bcd8125914c51e64a85cd5f6 100644 --- a/core/fpdfdoc/cpdf_interform.cpp +++ b/core/fpdfdoc/cpdf_interform.cpp @@ -20,8 +20,10 @@ #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfdoc/cpdf_filespec.h" #include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fxcrt/fx_codepage.h" #include "core/fxge/cfx_substfont.h" #include "core/fxge/fx_font.h" +#include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" namespace { @@ -29,7 +31,7 @@ namespace { const int nMaxRecursion = 32; const struct SupportFieldEncoding { - const FX_CHAR* m_name; + const char* m_name; uint16_t m_codePage; } g_fieldEncoding[] = { {"BigFive", 950}, @@ -38,24 +40,24 @@ const struct SupportFieldEncoding { {"UHC", 949}, }; -CFX_WideString GetFieldValue(const CPDF_Dictionary& pFieldDict, - const CFX_ByteString& bsEncoding) { - const CFX_ByteString csBValue = pFieldDict.GetStringFor("V"); +WideString GetFieldValue(const CPDF_Dictionary& pFieldDict, + const ByteString& bsEncoding) { + const ByteString csBValue = pFieldDict.GetStringFor("V"); for (const auto& encoding : g_fieldEncoding) { if (bsEncoding == encoding.m_name) - return CFX_WideString::FromCodePage(csBValue.AsStringC(), - encoding.m_codePage); + return WideString::FromCodePage(csBValue.AsStringView(), + encoding.m_codePage); } - CFX_ByteString csTemp = csBValue.Left(2); + ByteString csTemp = csBValue.Left(2); if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") return PDF_DecodeText(csBValue); - return CFX_WideString::FromLocal(csBValue.AsStringC()); + return WideString::FromLocal(csBValue.AsStringView()); } void AddFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, - CFX_ByteString& csNameTag); + ByteString* csNameTag); void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { if (!pDocument) @@ -67,30 +69,26 @@ void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { pFormDict->GetObjNum()); } - CFX_ByteString csDA; + ByteString csDA; if (!pFormDict->KeyExist("DR")) { - CFX_ByteString csBaseName; - CFX_ByteString csDefault; + ByteString csBaseName; uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); CPDF_Font* pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica"); - if (pFont) { - AddFont(pFormDict, pDocument, pFont, csBaseName); - csDefault = csBaseName; - } - if (charSet != FXFONT_ANSI_CHARSET) { - CFX_ByteString csFontName = - CPDF_InterForm::GetNativeFont(charSet, nullptr); + if (pFont) + AddFont(pFormDict, pDocument, pFont, &csBaseName); + + if (charSet != FX_CHARSET_ANSI) { + ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr); if (!pFont || csFontName != "Helvetica") { pFont = CPDF_InterForm::AddNativeFont(pDocument); if (pFont) { - csBaseName = ""; - AddFont(pFormDict, pDocument, pFont, csBaseName); - csDefault = csBaseName; + csBaseName.clear(); + AddFont(pFormDict, pDocument, pFont, &csBaseName); } } } if (pFont) - csDA = "/" + PDF_NameEncode(csDefault) + " 0 Tf"; + csDA = "/" + PDF_NameEncode(csBaseName) + " 0 Tf"; } if (!csDA.IsEmpty()) csDA += " "; @@ -102,8 +100,8 @@ void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { CPDF_Font* GetFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, - CFX_ByteString csNameTag) { - CFX_ByteString csAlias = PDF_NameDecode(csNameTag); + const ByteString& csNameTag) { + ByteString csAlias = PDF_NameDecode(csNameTag); if (!pFormDict || csAlias.IsEmpty()) return nullptr; @@ -127,7 +125,7 @@ CPDF_Font* GetFont(CPDF_Dictionary* pFormDict, CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, uint8_t charSet, - CFX_ByteString& csNameTag) { + ByteString* csNameTag) { if (!pFormDict) return nullptr; @@ -140,7 +138,7 @@ CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict, return nullptr; for (const auto& it : *pFonts) { - const CFX_ByteString& csKey = it.first; + const ByteString& csKey = it.first; if (!it.second) continue; @@ -157,8 +155,8 @@ CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict, if (!pSubst) continue; - if (pSubst->m_Charset == (int)charSet) { - csNameTag = csKey; + if (pSubst->m_Charset == static_cast(charSet)) { + *csNameTag = csKey; return pFind; } } @@ -167,7 +165,7 @@ CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict, bool FindFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, - CFX_ByteString& csNameTag) { + ByteString* csNameTag) { if (!pFormDict || !pFont) return false; @@ -180,7 +178,7 @@ bool FindFont(CPDF_Dictionary* pFormDict, return false; for (const auto& it : *pFonts) { - const CFX_ByteString& csKey = it.first; + const ByteString& csKey = it.first; if (!it.second) continue; CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); @@ -189,7 +187,7 @@ bool FindFont(CPDF_Dictionary* pFormDict, if (pElement->GetStringFor("Type") != "Font") continue; if (pFont->GetFontDict() == pElement) { - csNameTag = csKey; + *csNameTag = csKey; return true; } } @@ -198,9 +196,9 @@ bool FindFont(CPDF_Dictionary* pFormDict, bool FindFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, - CFX_ByteString csFontName, + ByteString csFontName, CPDF_Font*& pFont, - CFX_ByteString& csNameTag) { + ByteString* csNameTag) { if (!pFormDict) return false; @@ -211,11 +209,12 @@ bool FindFont(CPDF_Dictionary* pFormDict, CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); if (!pFonts) return false; + if (csFontName.GetLength() > 0) csFontName.Remove(' '); for (const auto& it : *pFonts) { - const CFX_ByteString& csKey = it.first; + const ByteString& csKey = it.first; if (!it.second) continue; @@ -228,11 +227,11 @@ bool FindFont(CPDF_Dictionary* pFormDict, if (!pFont) continue; - CFX_ByteString csBaseFont; + ByteString csBaseFont; csBaseFont = pFont->GetBaseFont(); csBaseFont.Remove(' '); if (csBaseFont == csFontName) { - csNameTag = csKey; + *csNameTag = csKey; return true; } } @@ -242,15 +241,15 @@ bool FindFont(CPDF_Dictionary* pFormDict, void AddFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, - CFX_ByteString& csNameTag) { + ByteString* csNameTag) { if (!pFont) return; if (!pFormDict) InitDict(pFormDict, pDocument); - CFX_ByteString csTag; - if (FindFont(pFormDict, pFont, csTag)) { - csNameTag = csTag; + ByteString csTag; + if (FindFont(pFormDict, pFont, &csTag)) { + *csNameTag = csTag; return; } if (!pFormDict) @@ -264,30 +263,30 @@ void AddFont(CPDF_Dictionary*& pFormDict, if (!pFonts) pFonts = pDR->SetNewFor("Font"); - if (csNameTag.IsEmpty()) - csNameTag = pFont->GetBaseFont(); + if (csNameTag->IsEmpty()) + *csNameTag = pFont->GetBaseFont(); - csNameTag.Remove(' '); - csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, - csNameTag.c_str()); - pFonts->SetNewFor(csNameTag, pDocument, + csNameTag->Remove(' '); + *csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, + csNameTag->c_str()); + pFonts->SetNewFor(*csNameTag, pDocument, pFont->GetFontDict()->GetObjNum()); } CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, uint8_t charSet, - CFX_ByteString& csNameTag) { + ByteString* csNameTag) { if (!pFormDict) InitDict(pFormDict, pDocument); - CFX_ByteString csTemp; - CPDF_Font* pFont = GetNativeFont(pFormDict, pDocument, charSet, csTemp); + ByteString csTemp; + CPDF_Font* pFont = GetNativeFont(pFormDict, pDocument, charSet, &csTemp); if (pFont) { - csNameTag = csTemp; + *csNameTag = csTemp; return pFont; } - CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr); + ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr); if (!csFontName.IsEmpty() && FindFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) { return pFont; @@ -301,29 +300,29 @@ CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict, class CFieldNameExtractor { public: - explicit CFieldNameExtractor(const CFX_WideString& full_name) + explicit CFieldNameExtractor(const WideString& full_name) : m_FullName(full_name) { m_pCur = m_FullName.c_str(); m_pEnd = m_pCur + m_FullName.GetLength(); } - void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) { + void GetNext(const wchar_t*& pSubName, size_t& size) { pSubName = m_pCur; while (m_pCur < m_pEnd && m_pCur[0] != L'.') m_pCur++; - size = (FX_STRSIZE)(m_pCur - pSubName); + size = static_cast(m_pCur - pSubName); if (m_pCur < m_pEnd && m_pCur[0] == L'.') m_pCur++; } protected: - CFX_WideString m_FullName; - const FX_WCHAR* m_pCur; - const FX_WCHAR* m_pEnd; + WideString m_FullName; + const wchar_t* m_pCur; + const wchar_t* m_pEnd; }; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ typedef struct { bool bFind; LOGFONTA lf; @@ -369,23 +368,7 @@ bool RetrieveSpecificFont(uint8_t charSet, } return RetrieveSpecificFont(lf); } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - -int CompareFieldName(const CFX_WideString& name1, const CFX_WideString& name2) { - const FX_WCHAR* ptr1 = name1.c_str(); - const FX_WCHAR* ptr2 = name2.c_str(); - if (name1.GetLength() == name2.GetLength()) - return name1 == name2 ? 1 : 0; - - int i = 0; - while (ptr1[i] == ptr2[i]) - i++; - if (i == name1.GetLength()) - return 2; - if (i == name2.GetLength()) - return 3; - return 0; -} +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ } // namespace @@ -393,37 +376,42 @@ class CFieldTree { public: class Node { public: - Node() : m_pField(nullptr) {} - Node(const CFX_WideString& short_name, CPDF_FormField* pField) - : m_ShortName(short_name), m_pField(pField) {} + Node() : m_pField(nullptr), m_level(0) {} + Node(const WideString& short_name, int level) + : m_ShortName(short_name), m_level(level) {} ~Node() {} - void AddChildNode(Node* pNode) { m_Children.push_back(pNode); } + void AddChildNode(std::unique_ptr pNode) { + m_Children.push_back(std::move(pNode)); + } size_t GetChildrenCount() const { return m_Children.size(); } - Node* GetChildAt(size_t i) { return m_Children[i]; } - const Node* GetChildAt(size_t i) const { return m_Children[i]; } + Node* GetChildAt(size_t i) { return m_Children[i].get(); } + const Node* GetChildAt(size_t i) const { return m_Children[i].get(); } CPDF_FormField* GetFieldAtIndex(size_t index) { size_t nFieldsToGo = index; return GetFieldInternal(&nFieldsToGo); } - size_t CountFields() const { return CountFieldsInternal(0); } + size_t CountFields() const { return CountFieldsInternal(); } - void SetField(CPDF_FormField* pField) { m_pField = pField; } + void SetField(std::unique_ptr pField) { + m_pField = std::move(pField); + } + + CPDF_FormField* GetField() const { return m_pField.get(); } - CPDF_FormField* GetField() { return m_pField; } - const CPDF_FormField* GetField() const { return m_pField; } + const WideString& GetShortName() const { return m_ShortName; } - const CFX_WideString& GetShortName() const { return m_ShortName; } + int GetLevel() const { return m_level; } private: CPDF_FormField* GetFieldInternal(size_t* pFieldsToGo) { if (m_pField) { if (*pFieldsToGo == 0) - return m_pField; + return m_pField.get(); --*pFieldsToGo; } @@ -435,72 +423,58 @@ class CFieldTree { return nullptr; } - size_t CountFieldsInternal(int nLevel) const { - if (nLevel > nMaxRecursion) - return 0; - + size_t CountFieldsInternal() const { size_t count = 0; if (m_pField) ++count; for (size_t i = 0; i < GetChildrenCount(); ++i) - count += GetChildAt(i)->CountFieldsInternal(nLevel + 1); + count += GetChildAt(i)->CountFieldsInternal(); return count; } - std::vector m_Children; - CFX_WideString m_ShortName; - CPDF_FormField* m_pField; + std::vector> m_Children; + WideString m_ShortName; + std::unique_ptr m_pField; + const int m_level; }; CFieldTree(); ~CFieldTree(); - void SetField(const CFX_WideString& full_name, CPDF_FormField* pField); - CPDF_FormField* GetField(const CFX_WideString& full_name); - void RemoveAll(); + bool SetField(const WideString& full_name, + std::unique_ptr pField); + CPDF_FormField* GetField(const WideString& full_name); - Node* FindNode(const CFX_WideString& full_name); - Node* AddChild(Node* pParent, - const CFX_WideString& short_name, - CPDF_FormField* pField); - void RemoveNode(Node* pNode, int nLevel = 0); + Node* FindNode(const WideString& full_name); + Node* AddChild(Node* pParent, const WideString& short_name); - Node* Lookup(Node* pParent, const CFX_WideString& short_name); + Node* Lookup(Node* pParent, const WideString& short_name); Node m_Root; }; CFieldTree::CFieldTree() {} -CFieldTree::~CFieldTree() { - RemoveAll(); -} +CFieldTree::~CFieldTree() {} CFieldTree::Node* CFieldTree::AddChild(Node* pParent, - const CFX_WideString& short_name, - CPDF_FormField* pField) { + const WideString& short_name) { if (!pParent) return nullptr; - Node* pNode = new Node(short_name, pField); - pParent->AddChildNode(pNode); - return pNode; -} - -void CFieldTree::RemoveNode(Node* pNode, int nLevel) { - if (!pNode) - return; + int level = pParent->GetLevel() + 1; + if (level > nMaxRecursion) + return nullptr; - if (nLevel <= nMaxRecursion) { - for (size_t i = 0; i < pNode->GetChildrenCount(); ++i) - RemoveNode(pNode->GetChildAt(i), nLevel + 1); - } - delete pNode; + auto pNew = pdfium::MakeUnique(short_name, pParent->GetLevel() + 1); + Node* pChild = pNew.get(); + pParent->AddChildNode(std::move(pNew)); + return pChild; } CFieldTree::Node* CFieldTree::Lookup(Node* pParent, - const CFX_WideString& short_name) { + const WideString& short_name) { if (!pParent) return nullptr; @@ -512,67 +486,67 @@ CFieldTree::Node* CFieldTree::Lookup(Node* pParent, return nullptr; } -void CFieldTree::RemoveAll() { - for (size_t i = 0; i < m_Root.GetChildrenCount(); ++i) - RemoveNode(m_Root.GetChildAt(i)); -} - -void CFieldTree::SetField(const CFX_WideString& full_name, - CPDF_FormField* pField) { +bool CFieldTree::SetField(const WideString& full_name, + std::unique_ptr pField) { if (full_name.IsEmpty()) - return; + return false; CFieldNameExtractor name_extractor(full_name); - const FX_WCHAR* pName; - FX_STRSIZE nLength; + const wchar_t* pName; + size_t nLength; name_extractor.GetNext(pName, nLength); Node* pNode = &m_Root; Node* pLast = nullptr; while (nLength > 0) { pLast = pNode; - CFX_WideString name = CFX_WideString(pName, nLength); + WideString name = WideString(pName, nLength); pNode = Lookup(pLast, name); if (!pNode) - pNode = AddChild(pLast, name, nullptr); + pNode = AddChild(pLast, name); + if (!pNode) + return false; name_extractor.GetNext(pName, nLength); } - if (pNode != &m_Root) - pNode->SetField(pField); + if (pNode == &m_Root) + return false; + + pNode->SetField(std::move(pField)); + return true; } -CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) { +CPDF_FormField* CFieldTree::GetField(const WideString& full_name) { if (full_name.IsEmpty()) return nullptr; CFieldNameExtractor name_extractor(full_name); - const FX_WCHAR* pName; - FX_STRSIZE nLength; + const wchar_t* pName; + size_t nLength; name_extractor.GetNext(pName, nLength); Node* pNode = &m_Root; Node* pLast = nullptr; while (nLength > 0 && pNode) { pLast = pNode; - CFX_WideString name = CFX_WideString(pName, nLength); + WideString name = WideString(pName, nLength); pNode = Lookup(pLast, name); name_extractor.GetNext(pName, nLength); } return pNode ? pNode->GetField() : nullptr; } -CFieldTree::Node* CFieldTree::FindNode(const CFX_WideString& full_name) { +CFieldTree::Node* CFieldTree::FindNode(const WideString& full_name) { if (full_name.IsEmpty()) return nullptr; CFieldNameExtractor name_extractor(full_name); - const FX_WCHAR* pName; - FX_STRSIZE nLength; + const wchar_t* pName; + size_t nLength; name_extractor.GetNext(pName, nLength); Node* pNode = &m_Root; Node* pLast = nullptr; while (nLength > 0 && pNode) { pLast = pNode; - CFX_WideString name = CFX_WideString(pName, nLength); + WideString name = WideString(pName, nLength); pNode = Lookup(pLast, name); name_extractor.GetNext(pName, nLength); } @@ -581,64 +555,64 @@ CFieldTree::Node* CFieldTree::FindNode(const CFX_WideString& full_name) { CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, - CFX_ByteString& csNameTag) { + ByteString* csNameTag) { uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); return AddNativeFont(pFormDict, pDocument, charSet, csNameTag); } // static uint8_t CPDF_InterForm::GetNativeCharSet() { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - uint8_t charSet = FXFONT_ANSI_CHARSET; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + uint8_t charSet = FX_CHARSET_ANSI; UINT iCodePage = ::GetACP(); switch (iCodePage) { - case 932: - charSet = FXFONT_SHIFTJIS_CHARSET; + case FX_CODEPAGE_ShiftJIS: + charSet = FX_CHARSET_ShiftJIS; break; - case 936: - charSet = FXFONT_GB2312_CHARSET; + case FX_CODEPAGE_ChineseSimplified: + charSet = FX_CHARSET_ChineseSimplified; break; - case 950: - charSet = FXFONT_CHINESEBIG5_CHARSET; + case FX_CODEPAGE_ChineseTraditional: + charSet = FX_CHARSET_ChineseTraditional; break; - case 1252: - charSet = FXFONT_ANSI_CHARSET; + case FX_CODEPAGE_MSWin_WesternEuropean: + charSet = FX_CHARSET_ANSI; break; - case 874: - charSet = FXFONT_THAI_CHARSET; + case FX_CODEPAGE_MSDOS_Thai: + charSet = FX_CHARSET_Thai; break; - case 949: - charSet = FXFONT_HANGUL_CHARSET; + case FX_CODEPAGE_Hangul: + charSet = FX_CHARSET_Hangul; break; - case 1200: - charSet = FXFONT_ANSI_CHARSET; + case FX_CODEPAGE_UTF16LE: + charSet = FX_CHARSET_ANSI; break; - case 1250: - charSet = FXFONT_EASTEUROPE_CHARSET; + case FX_CODEPAGE_MSWin_EasternEuropean: + charSet = FX_CHARSET_MSWin_EasternEuropean; break; - case 1251: - charSet = FXFONT_RUSSIAN_CHARSET; + case FX_CODEPAGE_MSWin_Cyrillic: + charSet = FX_CHARSET_MSWin_Cyrillic; break; - case 1253: - charSet = FXFONT_GREEK_CHARSET; + case FX_CODEPAGE_MSWin_Greek: + charSet = FX_CHARSET_MSWin_Greek; break; - case 1254: - charSet = FXFONT_TURKISH_CHARSET; + case FX_CODEPAGE_MSWin_Turkish: + charSet = FX_CHARSET_MSWin_Turkish; break; - case 1255: - charSet = FXFONT_HEBREW_CHARSET; + case FX_CODEPAGE_MSWin_Hebrew: + charSet = FX_CHARSET_MSWin_Hebrew; break; - case 1256: - charSet = FXFONT_ARABIC_CHARSET; + case FX_CODEPAGE_MSWin_Arabic: + charSet = FX_CHARSET_MSWin_Arabic; break; - case 1257: - charSet = FXFONT_BALTIC_CHARSET; + case FX_CODEPAGE_MSWin_Baltic: + charSet = FX_CHARSET_MSWin_Baltic; break; - case 1258: - charSet = FXFONT_VIETNAMESE_CHARSET; + case FX_CODEPAGE_MSWin_Vietnamese: + charSet = FX_CHARSET_MSWin_Vietnamese; break; - case 1361: - charSet = FXFONT_JOHAB_CHARSET; + case FX_CODEPAGE_Johab: + charSet = FX_CHARSET_Johab; break; } return charSet; @@ -650,7 +624,7 @@ uint8_t CPDF_InterForm::GetNativeCharSet() { CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument) : m_pDocument(pDocument), m_pFormDict(nullptr), - m_pFieldTree(new CFieldTree), + m_pFieldTree(pdfium::MakeUnique()), m_pFormNotify(nullptr) { CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); if (!pRoot) @@ -668,12 +642,7 @@ CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument) LoadField(pFields->GetDictAt(i), 0); } -CPDF_InterForm::~CPDF_InterForm() { - m_ControlMap.clear(); - size_t nCount = m_pFieldTree->m_Root.CountFields(); - for (size_t i = 0; i < nCount; ++i) - delete m_pFieldTree->m_Root.GetFieldAtIndex(i); -} +CPDF_InterForm::~CPDF_InterForm() {} bool CPDF_InterForm::s_bUpdateAP = true; @@ -685,13 +654,13 @@ void CPDF_InterForm::SetUpdateAP(bool bUpdateAP) { s_bUpdateAP = bUpdateAP; } -CFX_ByteString CPDF_InterForm::GenerateNewResourceName( +ByteString CPDF_InterForm::GenerateNewResourceName( const CPDF_Dictionary* pResDict, - const FX_CHAR* csType, + const char* csType, int iMinLen, - const FX_CHAR* csPrefix) { - CFX_ByteString csStr = csPrefix; - CFX_ByteString csBType = csType; + const char* csPrefix) { + ByteString csStr = csPrefix; + ByteString csBType = csType; if (csStr.IsEmpty()) { if (csBType == "ExtGState") csStr = "GS"; @@ -702,11 +671,11 @@ CFX_ByteString CPDF_InterForm::GenerateNewResourceName( else csStr = "Res"; } - CFX_ByteString csTmp = csStr; + ByteString csTmp = csStr; int iCount = csStr.GetLength(); int m = 0; if (iMinLen > 0) { - csTmp = ""; + csTmp.clear(); while (m < iMinLen && m < iCount) csTmp += csStr[m++]; while (m < iMinLen) { @@ -724,15 +693,15 @@ CFX_ByteString CPDF_InterForm::GenerateNewResourceName( return csTmp; int num = 0; - CFX_ByteString bsNum; + ByteString bsNum; while (true) { - CFX_ByteString csKey = csTmp + bsNum; + ByteString csKey = csTmp + bsNum; if (!pDict->KeyExist(csKey)) return csKey; if (m < iCount) csTmp += csStr[m++]; else - bsNum.Format("%d", num++); + bsNum = ByteString::Format("%d", num++); m++; } @@ -740,7 +709,7 @@ CFX_ByteString CPDF_InterForm::GenerateNewResourceName( } CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument, - CFX_ByteString csFontName) { + ByteString csFontName) { if (!pDocument || csFontName.IsEmpty()) return nullptr; @@ -751,22 +720,22 @@ CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument, return pDocument->AddStandardFont(csFontName.c_str(), &encoding); } -CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) { - CFX_ByteString csFontName; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) { + ByteString csFontName; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ LOGFONTA lf = {}; - if (charSet == FXFONT_ANSI_CHARSET) { + if (charSet == FX_CHARSET_ANSI) { csFontName = "Helvetica"; return csFontName; } bool bRet = false; - if (charSet == FXFONT_SHIFTJIS_CHARSET) { + if (charSet == FX_CHARSET_ShiftJIS) { bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MS Mincho", lf); - } else if (charSet == FXFONT_GB2312_CHARSET) { + } else if (charSet == FX_CHARSET_ChineseSimplified) { bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", lf); - } else if (charSet == FXFONT_CHINESEBIG5_CHARSET) { + } else if (charSet == FX_CHARSET_ChineseTraditional) { bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", lf); } @@ -798,9 +767,9 @@ CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, if (!pDocument) return nullptr; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ LOGFONTA lf; - CFX_ByteString csFontName = GetNativeFont(charSet, &lf); + ByteString csFontName = GetNativeFont(charSet, &lf); if (!csFontName.IsEmpty()) { if (csFontName == "Helvetica") return AddStandardFont(pDocument, csFontName); @@ -814,65 +783,7 @@ CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) { return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr; } -bool CPDF_InterForm::ValidateFieldName( - CFX_WideString& csNewFieldName, - int iType, - const CPDF_FormField* pExcludedField, - const CPDF_FormControl* pExcludedControl) const { - if (csNewFieldName.IsEmpty()) - return false; - - int iPos = 0; - int iLength = csNewFieldName.GetLength(); - CFX_WideString csSub; - while (true) { - while (iPos < iLength && - (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) { - iPos++; - } - if (iPos < iLength && !csSub.IsEmpty()) - csSub += L'.'; - while (iPos < iLength && csNewFieldName[iPos] != L'.') - csSub += csNewFieldName[iPos++]; - for (int i = csSub.GetLength() - 1; i > -1; i--) { - if (csSub[i] != L' ' && csSub[i] != L'.') - break; - - csSub.SetAt(i, L'\0'); - } - size_t dwCount = m_pFieldTree->m_Root.CountFields(); - for (size_t m = 0; m < dwCount; ++m) { - CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(m); - if (!pField) - continue; - if (pField == pExcludedField) { - if (!pExcludedControl || pField->CountControls() < 2) - continue; - } - CFX_WideString csFullName = pField->GetFullName(); - int iRet = CompareFieldName(csSub, csFullName); - if (iRet == 1) { - if (pField->GetFieldType() != iType) - return false; - } else if (iRet == 2 && csSub == csNewFieldName) { - if (csFullName[iPos] == L'.') - return false; - } else if (iRet == 3 && csSub == csNewFieldName) { - if (csNewFieldName[csFullName.GetLength()] == L'.') - return false; - } - } - if (iPos >= iLength) - break; - } - if (csSub.IsEmpty()) - return false; - - csNewFieldName = csSub; - return true; -} - -size_t CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) const { +size_t CPDF_InterForm::CountFields(const WideString& csFieldName) const { if (csFieldName.IsEmpty()) return m_pFieldTree->m_Root.CountFields(); @@ -880,9 +791,8 @@ size_t CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) const { return pNode ? pNode->CountFields() : 0; } -CPDF_FormField* CPDF_InterForm::GetField( - uint32_t index, - const CFX_WideString& csFieldName) const { +CPDF_FormField* CPDF_InterForm::GetField(uint32_t index, + const WideString& csFieldName) const { if (csFieldName.IsEmpty()) return m_pFieldTree->m_Root.GetFieldAtIndex(index); @@ -895,7 +805,7 @@ CPDF_FormField* CPDF_InterForm::GetFieldByDict( if (!pFieldDict) return nullptr; - CFX_WideString csWName = FPDF_GetFullName(pFieldDict); + WideString csWName = FPDF_GetFullName(pFieldDict); return m_pFieldTree->GetField(csWName); } @@ -968,14 +878,14 @@ int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) { for (size_t i = 0; i < pArray->GetCount(); i++) { CPDF_Object* pElement = pArray->GetDirectObjectAt(i); - if (pElement == pField->m_pDict) + if (pElement == pField->GetDict()) return i; } return -1; } -CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) { - return GetFont(m_pFormDict, m_pDocument, csNameTag); +CPDF_Font* CPDF_InterForm::GetFormFont(ByteString csNameTag) const { + return GetFont(m_pFormDict.Get(), m_pDocument.Get(), csNameTag); } CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() const { @@ -1060,7 +970,7 @@ bool CPDF_InterForm::HasXFAForm() const { } void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) { - CPDF_Dictionary* pPageDict = pPage->m_pFormDict; + CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get(); if (!pPageDict) return; @@ -1075,18 +985,18 @@ void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) { } } -CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { +void CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { if (!pFieldDict->KeyExist("FT")) { // Key "FT" is required for terminal fields, it is also inheritable. CPDF_Dictionary* pParentDict = pFieldDict->GetDictFor("Parent"); if (!pParentDict || !pParentDict->KeyExist("FT")) - return nullptr; + return; } CPDF_Dictionary* pDict = pFieldDict; - CFX_WideString csWName = FPDF_GetFullName(pFieldDict); + WideString csWName = FPDF_GetFullName(pFieldDict); if (csWName.IsEmpty()) - return nullptr; + return; CPDF_FormField* pField = nullptr; pField = m_pFieldTree->GetField(csWName); @@ -1113,7 +1023,8 @@ CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { } } - pField = new CPDF_FormField(this, pParent); + auto newField = pdfium::MakeUnique(this, pParent); + pField = newField.get(); CPDF_Object* pTObj = pDict->GetObjectFor("T"); if (ToReference(pTObj)) { std::unique_ptr pClone = pTObj->CloneDirectObject(); @@ -1122,7 +1033,8 @@ CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { else pDict->SetNewFor("T", ""); } - m_pFieldTree->SetField(csWName, pField); + if (!m_pFieldTree->SetField(csWName, std::move(newField))) + return; } CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); @@ -1140,7 +1052,6 @@ CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { if (pFieldDict->GetStringFor("Subtype") == "Widget") AddControl(pField, pFieldDict); } - return pField; } CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField, @@ -1152,7 +1063,7 @@ CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField, auto pNew = pdfium::MakeUnique(pField, pWidgetDict); CPDF_FormControl* pControl = pNew.get(); m_ControlMap[pWidgetDict] = std::move(pNew); - pField->m_ControlList.push_back(pControl); + pField->AddFormControl(pControl); return pControl; } @@ -1179,7 +1090,7 @@ bool CPDF_InterForm::CheckRequiredFields( if (fields) bFind = pdfium::ContainsValue(*fields, pField); if (bIncludeOrExclude == bFind) { - CPDF_Dictionary* pFieldDict = pField->m_pDict; + const CPDF_Dictionary* pFieldDict = pField->GetDict(); if ((dwFlags & FORMFLAG_REQUIRED) != 0 && pFieldDict->GetStringFor("V").IsEmpty()) { return false; @@ -1190,7 +1101,7 @@ bool CPDF_InterForm::CheckRequiredFields( } std::unique_ptr CPDF_InterForm::ExportToFDF( - const CFX_WideStringC& pdf_path, + const WideString& pdf_path, bool bSimpleFileSpec) const { std::vector fields; size_t nCount = m_pFieldTree->m_Root.CountFields(); @@ -1200,7 +1111,7 @@ std::unique_ptr CPDF_InterForm::ExportToFDF( } std::unique_ptr CPDF_InterForm::ExportToFDF( - const CFX_WideStringC& pdf_path, + const WideString& pdf_path, const std::vector& fields, bool bIncludeOrExclude, bool bSimpleFileSpec) const { @@ -1211,15 +1122,18 @@ std::unique_ptr CPDF_InterForm::ExportToFDF( CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictFor("FDF"); if (!pdf_path.IsEmpty()) { if (bSimpleFileSpec) { - CFX_WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path); + WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path); pMainDict->SetNewFor( - "F", CFX_ByteString::FromUnicode(wsFilePath), false); + "F", ByteString::FromUnicode(wsFilePath), false); pMainDict->SetNewFor("UF", PDF_EncodeText(wsFilePath), false); } else { - CPDF_FileSpec filespec(pDoc->GetByteStringPool()); + auto pNewDict = + pdfium::MakeUnique(pDoc->GetByteStringPool()); + pNewDict->SetNewFor("Type", "Filespec"); + CPDF_FileSpec filespec(pNewDict.get()); filespec.SetFileName(pdf_path); - pMainDict->SetFor("F", pdfium::WrapUnique(filespec.GetObj())); + pMainDict->SetFor("F", std::move(pNewDict)); } } @@ -1235,24 +1149,26 @@ std::unique_ptr CPDF_InterForm::ExportToFDF( continue; if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) { - if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetStringFor("V").IsEmpty()) + if ((dwFlags & 0x02) != 0 && + pField->GetDict()->GetStringFor("V").IsEmpty()) { continue; + } - CFX_WideString fullname = FPDF_GetFullName(pField->GetFieldDict()); + WideString fullname = FPDF_GetFullName(pField->GetFieldDict()); auto pFieldDict = pdfium::MakeUnique(pDoc->GetByteStringPool()); pFieldDict->SetNewFor("T", fullname); if (pField->GetType() == CPDF_FormField::CheckBox || pField->GetType() == CPDF_FormField::RadioButton) { - CFX_WideString csExport = pField->GetCheckValue(false); - CFX_ByteString csBExport = PDF_EncodeText(csExport); - CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt"); + WideString csExport = pField->GetCheckValue(false); + ByteString csBExport = PDF_EncodeText(csExport); + CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->GetDict(), "Opt"); if (pOpt) pFieldDict->SetNewFor("V", csBExport, false); else pFieldDict->SetNewFor("V", csBExport); } else { - CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V"); + CPDF_Object* pV = FPDF_GetFieldAttr(pField->GetDict(), "V"); if (pV) pFieldDict->SetFor("V", pV->CloneDirectObject()); } @@ -1263,10 +1179,10 @@ std::unique_ptr CPDF_InterForm::ExportToFDF( } void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, - const CFX_WideString& parent_name, + const WideString& parent_name, bool bNotify, int nLevel) { - CFX_WideString name; + WideString name; if (!parent_name.IsEmpty()) name = parent_name + L"."; @@ -1289,13 +1205,14 @@ void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, if (!pField) return; - CFX_WideString csWValue = GetFieldValue(*pFieldDict, m_bsEncoding); - int iType = pField->GetFieldType(); + WideString csWValue = GetFieldValue(*pFieldDict, m_bsEncoding); + FormFieldType fieldType = pField->GetFieldType(); if (bNotify && m_pFormNotify) { - if (iType == FIELDTYPE_LISTBOX) { + if (fieldType == FormFieldType::kListBox) { if (m_pFormNotify->BeforeSelectionChange(pField, csWValue) < 0) return; - } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) { + } else if (fieldType == FormFieldType::kComboBox || + fieldType == FormFieldType::kTextField) { if (m_pFormNotify->BeforeValueChange(pField, csWValue) < 0) return; } @@ -1304,17 +1221,19 @@ void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, CPDF_FormField::Type eType = pField->GetType(); if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && pFieldDict->KeyExist("Opt")) { - pField->m_pDict->SetFor( - "Opt", pFieldDict->GetDirectObjectFor("Opt")->CloneDirectObject()); + pField->SetOpt(pFieldDict->GetDirectObjectFor("Opt")->CloneDirectObject()); } if (bNotify && m_pFormNotify) { - if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) + if (fieldType == FormFieldType::kCheckBox || + fieldType == FormFieldType::kRadioButton) { m_pFormNotify->AfterCheckedStatusChange(pField); - else if (iType == FIELDTYPE_LISTBOX) + } else if (fieldType == FormFieldType::kListBox) { m_pFormNotify->AfterSelectionChange(pField); - else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) + } else if (fieldType == FormFieldType::kComboBox || + fieldType == FormFieldType::kTextField) { m_pFormNotify->AfterValueChange(pField); + } } } diff --git a/core/fpdfdoc/cpdf_interform.h b/core/fpdfdoc/cpdf_interform.h index cbaaa7bc2de7b8c18197fdcc7acfe60a47a41c56..e2673840c7ee664afad8bfdf7cf3a3eef9ec89ef 100644 --- a/core/fpdfdoc/cpdf_interform.h +++ b/core/fpdfdoc/cpdf_interform.h @@ -15,6 +15,7 @@ #include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CFieldTree; class CFDF_Document; @@ -29,7 +30,7 @@ class IPDF_FormNotify; CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, - CFX_ByteString& csNameTag); + ByteString* csNameTag); class CPDF_InterForm { public: @@ -38,20 +39,19 @@ class CPDF_InterForm { static void SetUpdateAP(bool bUpdateAP); static bool IsUpdateAPEnabled(); - static CFX_ByteString GenerateNewResourceName(const CPDF_Dictionary* pResDict, - const FX_CHAR* csType, - int iMinLen, - const FX_CHAR* csPrefix); + static ByteString GenerateNewResourceName(const CPDF_Dictionary* pResDict, + const char* csType, + int iMinLen, + const char* csPrefix); static CPDF_Font* AddStandardFont(CPDF_Document* pDocument, - CFX_ByteString csFontName); - static CFX_ByteString GetNativeFont(uint8_t iCharSet, void* pLogFont); + ByteString csFontName); + static ByteString GetNativeFont(uint8_t iCharSet, void* pLogFont); static uint8_t GetNativeCharSet(); static CPDF_Font* AddNativeFont(uint8_t iCharSet, CPDF_Document* pDocument); static CPDF_Font* AddNativeFont(CPDF_Document* pDocument); - size_t CountFields(const CFX_WideString& csFieldName) const; - CPDF_FormField* GetField(uint32_t index, - const CFX_WideString& csFieldName) const; + size_t CountFields(const WideString& csFieldName) const; + CPDF_FormField* GetField(uint32_t index, const WideString& csFieldName) const; CPDF_FormField* GetFieldByDict(CPDF_Dictionary* pFieldDict) const; CPDF_FormControl* GetControlAtPoint(CPDF_Page* pPage, @@ -64,18 +64,18 @@ class CPDF_InterForm { CPDF_FormField* GetFieldInCalculationOrder(int index); int FindFieldInCalculationOrder(const CPDF_FormField* pField); - CPDF_Font* GetFormFont(CFX_ByteString csNameTag); + CPDF_Font* GetFormFont(ByteString csNameTag) const; CPDF_DefaultAppearance GetDefaultAppearance() const; int GetFormAlignment() const; bool CheckRequiredFields(const std::vector* fields, bool bIncludeOrExclude) const; - std::unique_ptr ExportToFDF(const CFX_WideStringC& pdf_path, + std::unique_ptr ExportToFDF(const WideString& pdf_path, bool bSimpleFileSpec) const; std::unique_ptr ExportToFDF( - const CFX_WideStringC& pdf_path, + const WideString& pdf_path, const std::vector& fields, bool bIncludeOrExclude, bool bSimpleFileSpec) const; @@ -89,32 +89,29 @@ class CPDF_InterForm { bool HasXFAForm() const; void FixPageFields(const CPDF_Page* pPage); - private: - friend class CPDF_FormControl; - friend class CPDF_FormField; + IPDF_FormNotify* GetFormNotify() const { return m_pFormNotify.Get(); } + CPDF_Document* GetDocument() const { return m_pDocument.Get(); } + CPDF_Dictionary* GetFormDict() const { return m_pFormDict.Get(); } + private: void LoadField(CPDF_Dictionary* pFieldDict, int nLevel); - CPDF_FormField* AddTerminalField(CPDF_Dictionary* pFieldDict); + void AddTerminalField(CPDF_Dictionary* pFieldDict); CPDF_FormControl* AddControl(CPDF_FormField* pField, CPDF_Dictionary* pWidgetDict); void FDF_ImportField(CPDF_Dictionary* pField, - const CFX_WideString& parent_name, + const WideString& parent_name, bool bNotify = false, int nLevel = 0); - bool ValidateFieldName(CFX_WideString& csNewFieldName, - int iType, - const CPDF_FormField* pExcludedField, - const CPDF_FormControl* pExcludedControl) const; static bool s_bUpdateAP; - CPDF_Document* const m_pDocument; - CPDF_Dictionary* m_pFormDict; + UnownedPtr const m_pDocument; + UnownedPtr m_pFormDict; std::map> m_ControlMap; std::unique_ptr m_pFieldTree; - CFX_ByteString m_bsEncoding; - IPDF_FormNotify* m_pFormNotify; + ByteString m_bsEncoding; + UnownedPtr m_pFormNotify; }; #endif // CORE_FPDFDOC_CPDF_INTERFORM_H_ diff --git a/core/fpdfdoc/cpdf_link.cpp b/core/fpdfdoc/cpdf_link.cpp index 20ec486df28a9b05d28ea3afa3e499c195afbab3..f7aec4087e8d30fb6975cb906ce5bde9a925fa4b 100644 --- a/core/fpdfdoc/cpdf_link.cpp +++ b/core/fpdfdoc/cpdf_link.cpp @@ -9,6 +9,14 @@ #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfdoc/cpdf_nametree.h" +CPDF_Link::CPDF_Link() {} + +CPDF_Link::CPDF_Link(CPDF_Dictionary* pDict) : m_pDict(pDict) {} + +CPDF_Link::CPDF_Link(const CPDF_Link& that) = default; + +CPDF_Link::~CPDF_Link() {} + CFX_FloatRect CPDF_Link::GetRect() { return m_pDict->GetRectFor("Rect"); } @@ -20,7 +28,7 @@ CPDF_Dest CPDF_Link::GetDest(CPDF_Document* pDoc) { if (pDest->IsString() || pDest->IsName()) { CPDF_NameTree name_tree(pDoc, "Dests"); - return CPDF_Dest(name_tree.LookupNamedDest(pDoc, pDest->GetString())); + return CPDF_Dest(name_tree.LookupNamedDest(pDoc, pDest->GetUnicodeText())); } if (CPDF_Array* pArray = pDest->AsArray()) return CPDF_Dest(pArray); diff --git a/core/fpdfdoc/cpdf_link.h b/core/fpdfdoc/cpdf_link.h index 162630d6ac2f182e8bf9ea3d77ab699b8eb7a066..18200cc63744a7c718631e5d05c0d1a4df990cff 100644 --- a/core/fpdfdoc/cpdf_link.h +++ b/core/fpdfdoc/cpdf_link.h @@ -10,22 +10,24 @@ #include "core/fpdfdoc/cpdf_action.h" #include "core/fpdfdoc/cpdf_dest.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Dictionary; class CPDF_Link { public: - CPDF_Link() : m_pDict(nullptr) {} - explicit CPDF_Link(CPDF_Dictionary* pDict) : m_pDict(pDict) {} - - CPDF_Dictionary* GetDict() const { return m_pDict; } + CPDF_Link(); + explicit CPDF_Link(CPDF_Dictionary* pDict); + CPDF_Link(const CPDF_Link& that); + ~CPDF_Link(); + CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } CFX_FloatRect GetRect(); CPDF_Dest GetDest(CPDF_Document* pDoc); CPDF_Action GetAction(); private: - CPDF_Dictionary* m_pDict; + UnownedPtr m_pDict; }; #endif // CORE_FPDFDOC_CPDF_LINK_H_ diff --git a/core/fpdfdoc/cpdf_metadata.cpp b/core/fpdfdoc/cpdf_metadata.cpp index 5e3acbe3a230929c5414a6f7984876a06e5bb517..efe3c29dbf6ae998f98ea9ed26b1c9fa0765933d 100644 --- a/core/fpdfdoc/cpdf_metadata.cpp +++ b/core/fpdfdoc/cpdf_metadata.cpp @@ -9,10 +9,10 @@ #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcrt/fx_xml.h" +#include "core/fxcrt/xml/cxml_element.h" -CPDF_Metadata::CPDF_Metadata(CPDF_Document* pDoc) { - CPDF_Dictionary* pRoot = pDoc->GetRoot(); +CPDF_Metadata::CPDF_Metadata(const CPDF_Document* pDoc) { + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); if (!pRoot) return; @@ -20,9 +20,9 @@ CPDF_Metadata::CPDF_Metadata(CPDF_Document* pDoc) { if (!pStream) return; - CPDF_StreamAcc acc; - acc.LoadAllData(pStream, false); - m_pXmlElement = CXML_Element::Parse(acc.GetData(), acc.GetSize()); + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllDataFiltered(); + m_pXmlElement = CXML_Element::Parse(pAcc->GetData(), pAcc->GetSize()); } CPDF_Metadata::~CPDF_Metadata() {} diff --git a/core/fpdfdoc/cpdf_metadata.h b/core/fpdfdoc/cpdf_metadata.h index dd68dda713c7da83ccf611a6aa4e4e2b84bb7f47..fa958153fcfa1a18c4136b70804e4775e2b0c721 100644 --- a/core/fpdfdoc/cpdf_metadata.h +++ b/core/fpdfdoc/cpdf_metadata.h @@ -14,7 +14,7 @@ class CXML_Element; class CPDF_Metadata { public: - explicit CPDF_Metadata(CPDF_Document* pDoc); + explicit CPDF_Metadata(const CPDF_Document* pDoc); ~CPDF_Metadata(); const CXML_Element* GetRoot() const; diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp index b8d1eb0ab14ac47cb63ca546cd83fc676b562da9..3c5b08db21427ab376930df62b62714814eeaf77 100644 --- a/core/fpdfdoc/cpdf_nametree.cpp +++ b/core/fpdfdoc/cpdf_nametree.cpp @@ -6,58 +6,207 @@ #include "core/fpdfdoc/cpdf_nametree.h" +#include +#include + #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" namespace { -const int nMaxRecursion = 32; +constexpr int kNameTreeMaxRecursion = 32; + +std::pair GetNodeLimitsMaybeSwap(CPDF_Array* pLimits) { + ASSERT(pLimits); + WideString csLeft = pLimits->GetUnicodeTextAt(0); + WideString csRight = pLimits->GetUnicodeTextAt(1); + // If the lower limit is greater than the upper limit, swap them. + if (csLeft.Compare(csRight) > 0) { + pLimits->SetNewAt(0, csRight); + pLimits->SetNewAt(1, csLeft); + csLeft = pLimits->GetUnicodeTextAt(0); + csRight = pLimits->GetUnicodeTextAt(1); + } + return {csLeft, csRight}; +} + +// Get the limit arrays that leaf array |pFind| is under in the tree with root +// |pNode|. |pLimits| will hold all the limit arrays from the leaf up to before +// the root. Return true if successful. +bool GetNodeAncestorsLimits(const CPDF_Dictionary* pNode, + const CPDF_Array* pFind, + int nLevel, + std::vector* pLimits) { + if (nLevel > kNameTreeMaxRecursion) + return false; + + if (pNode->GetArrayFor("Names") == pFind) { + pLimits->push_back(pNode->GetArrayFor("Limits")); + return true; + } + + CPDF_Array* pKids = pNode->GetArrayFor("Kids"); + if (!pKids) + return false; + + for (size_t i = 0; i < pKids->GetCount(); ++i) { + CPDF_Dictionary* pKid = pKids->GetDictAt(i); + if (!pKid) + continue; + + if (GetNodeAncestorsLimits(pKid, pFind, nLevel + 1, pLimits)) { + pLimits->push_back(pNode->GetArrayFor("Limits")); + return true; + } + } + return false; +} + +// Upon the deletion of |csName| from leaf array |pFind|, update the ancestors +// of |pFind|. Specifically, the limits of |pFind|'s ancestors will be updated +// if needed, and any ancestors that are now empty will be removed. +bool UpdateNodesAndLimitsUponDeletion(CPDF_Dictionary* pNode, + const CPDF_Array* pFind, + const WideString& csName, + int nLevel) { + if (nLevel > kNameTreeMaxRecursion) + return false; + + CPDF_Array* pLimits = pNode->GetArrayFor("Limits"); + WideString csLeft; + WideString csRight; + if (pLimits) + std::tie(csLeft, csRight) = GetNodeLimitsMaybeSwap(pLimits); + + CPDF_Array* pNames = pNode->GetArrayFor("Names"); + if (pNames) { + if (pNames != pFind) + return false; + if (pNames->IsEmpty() || !pLimits) + return true; + if (csLeft != csName && csRight != csName) + return true; + + // Since |csName| defines |pNode|'s limits, we need to loop through the + // names to find the new lower and upper limits. + WideString csNewLeft = csRight; + WideString csNewRight = csLeft; + for (size_t i = 0; i < pNames->GetCount() / 2; ++i) { + WideString wsName = pNames->GetUnicodeTextAt(i * 2); + if (wsName.Compare(csNewLeft) < 0) + csNewLeft = wsName; + if (wsName.Compare(csNewRight) > 0) + csNewRight = wsName; + } + pLimits->SetNewAt(0, csNewLeft); + pLimits->SetNewAt(1, csNewRight); + return true; + } + + CPDF_Array* pKids = pNode->GetArrayFor("Kids"); + if (!pKids) + return false; + + // Loop through the kids to find the leaf array |pFind|. + for (size_t i = 0; i < pKids->GetCount(); ++i) { + CPDF_Dictionary* pKid = pKids->GetDictAt(i); + if (!pKid) + continue; + if (!UpdateNodesAndLimitsUponDeletion(pKid, pFind, csName, nLevel + 1)) + continue; + + // Remove this child node if it's empty. + if ((pKid->KeyExist("Names") && pKid->GetArrayFor("Names")->IsEmpty()) || + (pKid->KeyExist("Kids") && pKid->GetArrayFor("Kids")->IsEmpty())) { + pKids->RemoveAt(i); + } + if (pKids->IsEmpty() || !pLimits) + return true; + if (csLeft != csName && csRight != csName) + return true; + + // Since |csName| defines |pNode|'s limits, we need to loop through the + // kids to find the new lower and upper limits. + WideString csNewLeft = csRight; + WideString csNewRight = csLeft; + for (size_t j = 0; j < pKids->GetCount(); ++j) { + CPDF_Array* pKidLimits = pKids->GetDictAt(j)->GetArrayFor("Limits"); + ASSERT(pKidLimits); + if (pKidLimits->GetUnicodeTextAt(0).Compare(csNewLeft) < 0) + csNewLeft = pKidLimits->GetUnicodeTextAt(0); + if (pKidLimits->GetUnicodeTextAt(1).Compare(csNewRight) > 0) + csNewRight = pKidLimits->GetUnicodeTextAt(1); + } + pLimits->SetNewAt(0, csNewLeft); + pLimits->SetNewAt(1, csNewRight); + return true; + } + return false; +} -CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, - const CFX_ByteString& csName, - size_t& nIndex, - CPDF_Array** ppFind, - int nLevel = 0) { - if (nLevel > nMaxRecursion) +// Search for |csName| in the tree with root |pNode|. If successful, return the +// value that |csName| points to; |nIndex| will be the index of |csName|, +// |ppFind| will be the leaf array that |csName| is found in, and |pFindIndex| +// will be the index of |csName| in |ppFind|. If |csName| is not found, |ppFind| +// will be the leaf array that |csName| should be added to, and |pFindIndex| +// will be the index that it should be added at. +CPDF_Object* SearchNameNodeByName(const CPDF_Dictionary* pNode, + const WideString& csName, + int nLevel, + size_t* nIndex, + CPDF_Array** ppFind, + int* pFindIndex) { + if (nLevel > kNameTreeMaxRecursion) return nullptr; CPDF_Array* pLimits = pNode->GetArrayFor("Limits"); + CPDF_Array* pNames = pNode->GetArrayFor("Names"); if (pLimits) { - CFX_ByteString csLeft = pLimits->GetStringAt(0); - CFX_ByteString csRight = pLimits->GetStringAt(1); - if (csLeft.Compare(csRight.AsStringC()) > 0) { - CFX_ByteString csTmp = csRight; - csRight = csLeft; - csLeft = csTmp; - } - if (csName.Compare(csLeft.AsStringC()) < 0 || - csName.Compare(csRight.AsStringC()) > 0) { + WideString csLeft; + WideString csRight; + std::tie(csLeft, csRight) = GetNodeLimitsMaybeSwap(pLimits); + // Skip this node if the name to look for is smaller than its lower limit. + if (csName.Compare(csLeft) < 0) + return nullptr; + + // Skip this node if the name to look for is greater than its higher limit, + // and the node itself is a leaf node. + if (csName.Compare(csRight) > 0 && pNames) { + if (ppFind) + *ppFind = pNames; + if (pFindIndex) + *pFindIndex = pNames->GetCount() / 2 - 1; + return nullptr; } } - CPDF_Array* pNames = pNode->GetArrayFor("Names"); + // If the node is a leaf node, look for the name in its names array. if (pNames) { size_t dwCount = pNames->GetCount() / 2; for (size_t i = 0; i < dwCount; i++) { - CFX_ByteString csValue = pNames->GetStringAt(i * 2); - int32_t iCompare = csValue.Compare(csName.AsStringC()); - if (iCompare <= 0) { - if (ppFind) - *ppFind = pNames; - if (iCompare < 0) - continue; - } else { + WideString csValue = pNames->GetUnicodeTextAt(i * 2); + int32_t iCompare = csValue.Compare(csName); + if (iCompare > 0) break; - } - nIndex += i; + if (ppFind) + *ppFind = pNames; + if (pFindIndex) + *pFindIndex = i; + if (iCompare < 0) + continue; + + *nIndex += i; return pNames->GetDirectObjectAt(i * 2 + 1); } - nIndex += dwCount; + *nIndex += dwCount; return nullptr; } + // Search through the node's children. CPDF_Array* pKids = pNode->GetArrayFor("Kids"); if (!pKids) return nullptr; @@ -67,52 +216,63 @@ CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, if (!pKid) continue; - CPDF_Object* pFound = - SearchNameNode(pKid, csName, nIndex, ppFind, nLevel + 1); + CPDF_Object* pFound = SearchNameNodeByName(pKid, csName, nLevel + 1, nIndex, + ppFind, pFindIndex); if (pFound) return pFound; } return nullptr; } -CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, - size_t nIndex, - size_t& nCurIndex, - CFX_ByteString& csName, - CPDF_Array** ppFind, - int nLevel = 0) { - if (nLevel > nMaxRecursion) +// Get the key-value pair at |nIndex| in the tree with root |pNode|. If +// successful, return the value object; |csName| will be the key, |ppFind| +// will be the leaf array that this pair is in, and |pFindIndex| will be the +// index of the pair in |pFind|. +CPDF_Object* SearchNameNodeByIndex(const CPDF_Dictionary* pNode, + size_t nIndex, + int nLevel, + size_t* nCurIndex, + WideString* csName, + CPDF_Array** ppFind, + int* pFindIndex) { + if (nLevel > kNameTreeMaxRecursion) return nullptr; CPDF_Array* pNames = pNode->GetArrayFor("Names"); if (pNames) { size_t nCount = pNames->GetCount() / 2; - if (nIndex >= nCurIndex + nCount) { - nCurIndex += nCount; + if (nIndex >= *nCurIndex + nCount) { + *nCurIndex += nCount; return nullptr; } if (ppFind) *ppFind = pNames; - csName = pNames->GetStringAt((nIndex - nCurIndex) * 2); - return pNames->GetDirectObjectAt((nIndex - nCurIndex) * 2 + 1); + if (pFindIndex) + *pFindIndex = nIndex - *nCurIndex; + + *csName = pNames->GetUnicodeTextAt((nIndex - *nCurIndex) * 2); + return pNames->GetDirectObjectAt((nIndex - *nCurIndex) * 2 + 1); } + CPDF_Array* pKids = pNode->GetArrayFor("Kids"); if (!pKids) return nullptr; + for (size_t i = 0; i < pKids->GetCount(); i++) { CPDF_Dictionary* pKid = pKids->GetDictAt(i); if (!pKid) continue; - CPDF_Object* pFound = - SearchNameNode(pKid, nIndex, nCurIndex, csName, ppFind, nLevel + 1); + CPDF_Object* pFound = SearchNameNodeByIndex( + pKid, nIndex, nLevel + 1, nCurIndex, csName, ppFind, pFindIndex); if (pFound) return pFound; } return nullptr; } -size_t CountNames(CPDF_Dictionary* pNode, int nLevel = 0) { - if (nLevel > nMaxRecursion) +// Get the total number of key-value pairs in the tree with root |pNode|. +size_t CountNamesInternal(CPDF_Dictionary* pNode, int nLevel) { + if (nLevel > kNameTreeMaxRecursion) return 0; CPDF_Array* pNames = pNode->GetArrayFor("Names"); @@ -129,17 +289,19 @@ size_t CountNames(CPDF_Dictionary* pNode, int nLevel = 0) { if (!pKid) continue; - nCount += CountNames(pKid, nLevel + 1); + nCount += CountNamesInternal(pKid, nLevel + 1); } return nCount; } } // namespace -CPDF_NameTree::CPDF_NameTree(CPDF_Document* pDoc, - const CFX_ByteString& category) +CPDF_NameTree::CPDF_NameTree(CPDF_Dictionary* pRoot) : m_pRoot(pRoot) {} + +CPDF_NameTree::CPDF_NameTree(const CPDF_Document* pDoc, + const ByteString& category) : m_pRoot(nullptr) { - CPDF_Dictionary* pRoot = pDoc->GetRoot(); + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); if (!pRoot) return; @@ -150,43 +312,125 @@ CPDF_NameTree::CPDF_NameTree(CPDF_Document* pDoc, m_pRoot = pNames->GetDictFor(category); } +CPDF_NameTree::~CPDF_NameTree() {} + size_t CPDF_NameTree::GetCount() const { - return m_pRoot ? ::CountNames(m_pRoot) : 0; + return m_pRoot ? CountNamesInternal(m_pRoot.Get(), 0) : 0; } -int CPDF_NameTree::GetIndex(const CFX_ByteString& csName) const { +int CPDF_NameTree::GetIndex(const WideString& csName) const { if (!m_pRoot) return -1; size_t nIndex = 0; - if (!SearchNameNode(m_pRoot, csName, nIndex, nullptr)) + if (!SearchNameNodeByName(m_pRoot.Get(), csName, 0, &nIndex, nullptr, + nullptr)) { return -1; + } return nIndex; } -CPDF_Object* CPDF_NameTree::LookupValue(int nIndex, - CFX_ByteString& csName) const { +bool CPDF_NameTree::AddValueAndName(std::unique_ptr pObj, + const WideString& name) { + if (!m_pRoot) + return false; + + size_t nIndex = 0; + CPDF_Array* pFind = nullptr; + int nFindIndex = -1; + // Fail if the tree already contains this name or if the tree is too deep. + if (SearchNameNodeByName(m_pRoot.Get(), name, 0, &nIndex, &pFind, + &nFindIndex)) { + return false; + } + + // If the returned |pFind| is a nullptr, then |name| is smaller than all + // existing entries in the tree, and we did not find a leaf array to place + // |name| into. We instead will find the leftmost leaf array in which to place + // |name| and |pObj|. + if (!pFind) { + size_t nCurIndex = 0; + WideString csName; + SearchNameNodeByIndex(m_pRoot.Get(), 0, 0, &nCurIndex, &csName, &pFind, + nullptr); + } + ASSERT(pFind); + + // Insert the name and the object into the leaf array found. Note that the + // insertion position is right after the key-value pair returned by |index|. + size_t nNameIndex = (nFindIndex + 1) * 2; + size_t nValueIndex = nNameIndex + 1; + pFind->InsertNewAt(nNameIndex, name); + pFind->InsertAt(nValueIndex, std::move(pObj)); + + // Expand the limits that the newly added name is under, if the name falls + // outside of the limits of its leaf array or any arrays above it. + std::vector pLimits; + GetNodeAncestorsLimits(m_pRoot.Get(), pFind, 0, &pLimits); + for (auto* pLimit : pLimits) { + if (!pLimit) + continue; + + if (name.Compare(pLimit->GetUnicodeTextAt(0)) < 0) + pLimit->SetNewAt(0, name); + + if (name.Compare(pLimit->GetUnicodeTextAt(1)) > 0) + pLimit->SetNewAt(1, name); + } + return true; +} + +bool CPDF_NameTree::DeleteValueAndName(int nIndex) { + if (!m_pRoot) + return false; + + size_t nCurIndex = 0; + WideString csName; + CPDF_Array* pFind = nullptr; + int nFindIndex = -1; + // Fail if the tree does not contain |nIndex|. + if (!SearchNameNodeByIndex(m_pRoot.Get(), nIndex, 0, &nCurIndex, &csName, + &pFind, &nFindIndex)) { + return false; + } + + // Remove the name and the object from the leaf array |pFind|. + pFind->RemoveAt(nFindIndex * 2); + pFind->RemoveAt(nFindIndex * 2); + + // Delete empty nodes and update the limits of |pFind|'s ancestors as needed. + UpdateNodesAndLimitsUponDeletion(m_pRoot.Get(), pFind, csName, 0); + return true; +} + +CPDF_Object* CPDF_NameTree::LookupValueAndName(int nIndex, + WideString* csName) const { + csName->clear(); if (!m_pRoot) return nullptr; + size_t nCurIndex = 0; - return SearchNameNode(m_pRoot, nIndex, nCurIndex, csName, nullptr); + return SearchNameNodeByIndex(m_pRoot.Get(), nIndex, 0, &nCurIndex, csName, + nullptr, nullptr); } -CPDF_Object* CPDF_NameTree::LookupValue(const CFX_ByteString& csName) const { +CPDF_Object* CPDF_NameTree::LookupValue(const WideString& csName) const { if (!m_pRoot) return nullptr; + size_t nIndex = 0; - return SearchNameNode(m_pRoot, csName, nIndex, nullptr); + return SearchNameNodeByName(m_pRoot.Get(), csName, 0, &nIndex, nullptr, + nullptr); } CPDF_Array* CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc, - const CFX_ByteString& sName) { + const WideString& sName) { CPDF_Object* pValue = LookupValue(sName); if (!pValue) { CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDictFor("Dests"); if (!pDests) return nullptr; - pValue = pDests->GetDirectObjectFor(sName); + pValue = pDests->GetDirectObjectFor(PDF_EncodeText(sName)); } if (!pValue) return nullptr; diff --git a/core/fpdfdoc/cpdf_nametree.h b/core/fpdfdoc/cpdf_nametree.h index d6763ad98722499248bf6764ac21e203f6e48788..72d0d669e96b5b434064e0e820c7508e4212be42 100644 --- a/core/fpdfdoc/cpdf_nametree.h +++ b/core/fpdfdoc/cpdf_nametree.h @@ -7,7 +7,10 @@ #ifndef CORE_FPDFDOC_CPDF_NAMETREE_H_ #define CORE_FPDFDOC_CPDF_NAMETREE_H_ +#include + #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Array; class CPDF_Dictionary; @@ -16,19 +19,24 @@ class CPDF_Object; class CPDF_NameTree { public: - explicit CPDF_NameTree(CPDF_Dictionary* pRoot) : m_pRoot(pRoot) {} - CPDF_NameTree(CPDF_Document* pDoc, const CFX_ByteString& category); + explicit CPDF_NameTree(CPDF_Dictionary* pRoot); + CPDF_NameTree(const CPDF_Document* pDoc, const ByteString& category); + ~CPDF_NameTree(); + + bool AddValueAndName(std::unique_ptr pObj, + const WideString& name); + bool DeleteValueAndName(int nIndex); - CPDF_Object* LookupValue(int nIndex, CFX_ByteString& csName) const; - CPDF_Object* LookupValue(const CFX_ByteString& csName) const; - CPDF_Array* LookupNamedDest(CPDF_Document* pDoc, const CFX_ByteString& sName); + CPDF_Object* LookupValueAndName(int nIndex, WideString* csName) const; + CPDF_Object* LookupValue(const WideString& csName) const; + CPDF_Array* LookupNamedDest(CPDF_Document* pDoc, const WideString& sName); - int GetIndex(const CFX_ByteString& csName) const; + int GetIndex(const WideString& csName) const; size_t GetCount() const; - CPDF_Dictionary* GetRoot() const { return m_pRoot; } + CPDF_Dictionary* GetRoot() const { return m_pRoot.Get(); } private: - CPDF_Dictionary* m_pRoot; + UnownedPtr m_pRoot; }; #endif // CORE_FPDFDOC_CPDF_NAMETREE_H_ diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38c3140b9068eb47d73c3e2f1e6619ba655f758a --- /dev/null +++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp @@ -0,0 +1,297 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfdoc/cpdf_nametree.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +void AddNameKeyValue(CPDF_Array* pNames, const char* key, const int value) { + pNames->AddNew(key, false); + pNames->AddNew(value); +} + +void CheckNameKeyValue(CPDF_Array* pNames, + const int index, + const char* key, + const int value) { + EXPECT_STREQ(key, pNames->GetStringAt(index * 2).c_str()); + EXPECT_EQ(value, pNames->GetIntegerAt(index * 2 + 1)); +} + +void AddLimitsArray(CPDF_Dictionary* pNode, + const char* least, + const char* greatest) { + CPDF_Array* pLimits = pNode->SetNewFor("Limits"); + pLimits->AddNew(least, false); + pLimits->AddNew(greatest, false); +} + +void CheckLimitsArray(CPDF_Dictionary* pNode, + const char* least, + const char* greatest) { + CPDF_Array* pLimits = pNode->GetArrayFor("Limits"); + ASSERT_TRUE(pLimits); + EXPECT_STREQ(least, pLimits->GetStringAt(0).c_str()); + EXPECT_STREQ(greatest, pLimits->GetStringAt(1).c_str()); +} + +void FillNameTreeDict(CPDF_Dictionary* pRootDict) { + CPDF_Array* pKids = pRootDict->SetNewFor("Kids"); + CPDF_Dictionary* pKid1 = pKids->AddNew(); + + // Make the lower and upper limit out of order on purpose. + AddLimitsArray(pKid1, "9.txt", "1.txt"); + pKids = pKid1->SetNewFor("Kids"); + CPDF_Dictionary* pKid2 = pKids->AddNew(); + CPDF_Dictionary* pKid3 = pKids->AddNew(); + + AddLimitsArray(pKid2, "1.txt", "5.txt"); + pKids = pKid2->SetNewFor("Kids"); + CPDF_Dictionary* pKid4 = pKids->AddNew(); + CPDF_Dictionary* pKid5 = pKids->AddNew(); + + AddLimitsArray(pKid3, "9.txt", "9.txt"); + CPDF_Array* pNames = pKid3->SetNewFor("Names"); + AddNameKeyValue(pNames, "9.txt", 999); + + // Make the lower and upper limit out of order on purpose. + AddLimitsArray(pKid4, "2.txt", "1.txt"); + pNames = pKid4->SetNewFor("Names"); + AddNameKeyValue(pNames, "1.txt", 111); + AddNameKeyValue(pNames, "2.txt", 222); + + AddLimitsArray(pKid5, "3.txt", "5.txt"); + pNames = pKid5->SetNewFor("Names"); + AddNameKeyValue(pNames, "3.txt", 333); + AddNameKeyValue(pNames, "5.txt", 555); +} + +} // namespace + +TEST(cpdf_nametree, GetUnicodeNameWithBOM) { + // Set up the root dictionary with a Names array. + auto pRootDict = pdfium::MakeUnique(); + CPDF_Array* pNames = pRootDict->SetNewFor("Names"); + + // Add the key "1" (with BOM) and value 100 into the array. + std::ostringstream buf; + constexpr char kData[] = "\xFE\xFF\x00\x31"; + for (size_t i = 0; i < sizeof(kData); ++i) + buf.put(kData[i]); + pNames->AddNew(ByteString(buf), true); + pNames->AddNew(100); + + // Check that the key is as expected. + CPDF_NameTree nameTree(pRootDict.get()); + WideString storedName; + nameTree.LookupValueAndName(0, &storedName); + EXPECT_STREQ(L"1", storedName.c_str()); + + // Check that the correct value object can be obtained by looking up "1". + WideString matchName = L"1"; + CPDF_Object* pObj = nameTree.LookupValue(matchName); + ASSERT_TRUE(pObj->IsNumber()); + EXPECT_EQ(100, pObj->AsNumber()->GetInteger()); +} + +TEST(cpdf_nametree, AddIntoNames) { + // Set up a name tree with a single Names array. + auto pRootDict = pdfium::MakeUnique(); + CPDF_Array* pNames = pRootDict->SetNewFor("Names"); + AddNameKeyValue(pNames, "2.txt", 222); + AddNameKeyValue(pNames, "7.txt", 777); + + CPDF_NameTree nameTree(pRootDict.get()); + pNames = nameTree.GetRoot()->GetArrayFor("Names"); + + // Insert a name that already exists in the names array. + EXPECT_FALSE( + nameTree.AddValueAndName(pdfium::MakeUnique(111), L"2.txt")); + + // Insert in the beginning of the names array. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(111), L"1.txt")); + + // Insert in the middle of the names array. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(555), L"5.txt")); + + // Insert at the end of the names array. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(999), L"9.txt")); + + // Check that the names array has the expected key-value pairs. + CheckNameKeyValue(pNames, 0, "1.txt", 111); + CheckNameKeyValue(pNames, 1, "2.txt", 222); + CheckNameKeyValue(pNames, 2, "5.txt", 555); + CheckNameKeyValue(pNames, 3, "7.txt", 777); + CheckNameKeyValue(pNames, 4, "9.txt", 999); +} + +TEST(cpdf_nametree, AddIntoKids) { + // Set up a name tree with five nodes of three levels. + auto pRootDict = pdfium::MakeUnique(); + FillNameTreeDict(pRootDict.get()); + CPDF_NameTree nameTree(pRootDict.get()); + + // Check that adding an existing name would fail. + EXPECT_FALSE( + nameTree.AddValueAndName(pdfium::MakeUnique(444), L"9.txt")); + + // Add a name within the limits of a leaf node. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(444), L"4.txt")); + ASSERT_TRUE(nameTree.LookupValue(L"4.txt")); + EXPECT_EQ(444, nameTree.LookupValue(L"4.txt")->GetInteger()); + + // Add a name that requires changing the limits of two bottom levels. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(666), L"6.txt")); + ASSERT_TRUE(nameTree.LookupValue(L"6.txt")); + EXPECT_EQ(666, nameTree.LookupValue(L"6.txt")->GetInteger()); + + // Add a name that requires changing the limits of two top levels. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(99), L"99.txt")); + ASSERT_TRUE(nameTree.LookupValue(L"99.txt")); + EXPECT_EQ(99, nameTree.LookupValue(L"99.txt")->GetInteger()); + + // Add a name that requires changing the lower limit of all levels. + EXPECT_TRUE( + nameTree.AddValueAndName(pdfium::MakeUnique(-5), L"0.txt")); + ASSERT_TRUE(nameTree.LookupValue(L"0.txt")); + EXPECT_EQ(-5, nameTree.LookupValue(L"0.txt")->GetInteger()); + + // Check that the node on the first level has the expected limits. + CPDF_Dictionary* pKid1 = + nameTree.GetRoot()->GetArrayFor("Kids")->GetDictAt(0); + ASSERT_TRUE(pKid1); + CheckLimitsArray(pKid1, "0.txt", "99.txt"); + + // Check that the nodes on the second level has the expected limits and names. + CPDF_Dictionary* pKid2 = pKid1->GetArrayFor("Kids")->GetDictAt(0); + ASSERT_TRUE(pKid2); + CheckLimitsArray(pKid2, "0.txt", "6.txt"); + + CPDF_Dictionary* pKid3 = pKid1->GetArrayFor("Kids")->GetDictAt(1); + ASSERT_TRUE(pKid3); + CheckLimitsArray(pKid3, "9.txt", "99.txt"); + CPDF_Array* pNames = pKid3->GetArrayFor("Names"); + ASSERT_TRUE(pNames); + CheckNameKeyValue(pNames, 0, "9.txt", 999); + CheckNameKeyValue(pNames, 1, "99.txt", 99); + + // Check that the nodes on the third level has the expected limits and names. + CPDF_Dictionary* pKid4 = pKid2->GetArrayFor("Kids")->GetDictAt(0); + ASSERT_TRUE(pKid4); + CheckLimitsArray(pKid4, "0.txt", "2.txt"); + pNames = pKid4->GetArrayFor("Names"); + ASSERT_TRUE(pNames); + CheckNameKeyValue(pNames, 0, "0.txt", -5); + CheckNameKeyValue(pNames, 1, "1.txt", 111); + CheckNameKeyValue(pNames, 2, "2.txt", 222); + + CPDF_Dictionary* pKid5 = pKid2->GetArrayFor("Kids")->GetDictAt(1); + ASSERT_TRUE(pKid5); + CheckLimitsArray(pKid5, "3.txt", "6.txt"); + pNames = pKid5->GetArrayFor("Names"); + ASSERT_TRUE(pNames); + CheckNameKeyValue(pNames, 0, "3.txt", 333); + CheckNameKeyValue(pNames, 1, "4.txt", 444); + CheckNameKeyValue(pNames, 2, "5.txt", 555); + CheckNameKeyValue(pNames, 3, "6.txt", 666); +} + +TEST(cpdf_nametree, DeleteFromKids) { + // Set up a name tree with five nodes of three levels. + auto pRootDict = pdfium::MakeUnique(); + FillNameTreeDict(pRootDict.get()); + CPDF_NameTree nameTree(pRootDict.get()); + + // Retrieve the kid dictionaries. + CPDF_Dictionary* pKid1 = + nameTree.GetRoot()->GetArrayFor("Kids")->GetDictAt(0); + ASSERT_TRUE(pKid1); + CPDF_Dictionary* pKid2 = pKid1->GetArrayFor("Kids")->GetDictAt(0); + ASSERT_TRUE(pKid2); + CPDF_Dictionary* pKid3 = pKid1->GetArrayFor("Kids")->GetDictAt(1); + ASSERT_TRUE(pKid3); + CPDF_Dictionary* pKid4 = pKid2->GetArrayFor("Kids")->GetDictAt(0); + ASSERT_TRUE(pKid4); + CPDF_Dictionary* pKid5 = pKid2->GetArrayFor("Kids")->GetDictAt(1); + ASSERT_TRUE(pKid5); + + // Check that deleting an out-of-bound index would fail. + EXPECT_FALSE(nameTree.DeleteValueAndName(5)); + + // Delete the name "9.txt", and check that its node gets deleted and its + // parent node's limits get updated. + WideString csName; + ASSERT_TRUE(nameTree.LookupValue(L"9.txt")); + EXPECT_EQ(999, nameTree.LookupValue(L"9.txt")->GetInteger()); + EXPECT_TRUE(nameTree.LookupValueAndName(4, &csName)); + EXPECT_STREQ(L"9.txt", csName.c_str()); + EXPECT_EQ(2u, pKid1->GetArrayFor("Kids")->GetCount()); + EXPECT_TRUE(nameTree.DeleteValueAndName(4)); + EXPECT_EQ(1u, pKid1->GetArrayFor("Kids")->GetCount()); + CheckLimitsArray(pKid1, "1.txt", "5.txt"); + + // Delete the name "2.txt", and check that its node does not get deleted, its + // node's limits get updated, and no other limits get updated. + ASSERT_TRUE(nameTree.LookupValue(L"2.txt")); + EXPECT_EQ(222, nameTree.LookupValue(L"2.txt")->GetInteger()); + EXPECT_TRUE(nameTree.LookupValueAndName(1, &csName)); + EXPECT_STREQ(L"2.txt", csName.c_str()); + EXPECT_EQ(4u, pKid4->GetArrayFor("Names")->GetCount()); + EXPECT_TRUE(nameTree.DeleteValueAndName(1)); + EXPECT_EQ(2u, pKid4->GetArrayFor("Names")->GetCount()); + CheckLimitsArray(pKid4, "1.txt", "1.txt"); + CheckLimitsArray(pKid2, "1.txt", "5.txt"); + CheckLimitsArray(pKid1, "1.txt", "5.txt"); + + // Delete the name "1.txt", and check that its node gets deleted, and its + // parent's and gradparent's limits get updated. + ASSERT_TRUE(nameTree.LookupValue(L"1.txt")); + EXPECT_EQ(111, nameTree.LookupValue(L"1.txt")->GetInteger()); + EXPECT_TRUE(nameTree.LookupValueAndName(0, &csName)); + EXPECT_STREQ(L"1.txt", csName.c_str()); + EXPECT_EQ(2u, pKid2->GetArrayFor("Kids")->GetCount()); + EXPECT_TRUE(nameTree.DeleteValueAndName(0)); + EXPECT_EQ(1u, pKid2->GetArrayFor("Kids")->GetCount()); + CheckLimitsArray(pKid2, "3.txt", "5.txt"); + CheckLimitsArray(pKid1, "3.txt", "5.txt"); + + // Delete the name "3.txt", and check that its node does not get deleted, and + // its node's, its parent's, and its grandparent's limits get updated. + ASSERT_TRUE(nameTree.LookupValue(L"3.txt")); + EXPECT_EQ(333, nameTree.LookupValue(L"3.txt")->GetInteger()); + EXPECT_TRUE(nameTree.LookupValueAndName(0, &csName)); + EXPECT_STREQ(L"3.txt", csName.c_str()); + EXPECT_EQ(4u, pKid5->GetArrayFor("Names")->GetCount()); + EXPECT_TRUE(nameTree.DeleteValueAndName(0)); + EXPECT_EQ(2u, pKid5->GetArrayFor("Names")->GetCount()); + CheckLimitsArray(pKid5, "5.txt", "5.txt"); + CheckLimitsArray(pKid2, "5.txt", "5.txt"); + CheckLimitsArray(pKid1, "5.txt", "5.txt"); + + // Delete the name "5.txt", and check that all nodes in the tree get deleted + // since they are now all empty. + ASSERT_TRUE(nameTree.LookupValue(L"5.txt")); + EXPECT_EQ(555, nameTree.LookupValue(L"5.txt")->GetInteger()); + EXPECT_TRUE(nameTree.LookupValueAndName(0, &csName)); + EXPECT_STREQ(L"5.txt", csName.c_str()); + EXPECT_EQ(1u, nameTree.GetRoot()->GetArrayFor("Kids")->GetCount()); + EXPECT_TRUE(nameTree.DeleteValueAndName(0)); + EXPECT_EQ(0u, nameTree.GetRoot()->GetArrayFor("Kids")->GetCount()); + + // Check that the tree is now empty. + EXPECT_EQ(0u, nameTree.GetCount()); + EXPECT_FALSE(nameTree.LookupValueAndName(0, &csName)); + EXPECT_FALSE(nameTree.DeleteValueAndName(0)); +} diff --git a/core/fpdfdoc/cpdf_numbertree.cpp b/core/fpdfdoc/cpdf_numbertree.cpp index 5f2bc06666e20772688db4c764acf7fb9a4eaca4..952fb4ef1d44ebac8a73c3b07f053a8681a39700 100644 --- a/core/fpdfdoc/cpdf_numbertree.cpp +++ b/core/fpdfdoc/cpdf_numbertree.cpp @@ -47,6 +47,10 @@ CPDF_Object* SearchNumberNode(const CPDF_Dictionary* pNode, int num) { } // namespace +CPDF_NumberTree::CPDF_NumberTree(CPDF_Dictionary* pRoot) : m_pRoot(pRoot) {} + +CPDF_NumberTree::~CPDF_NumberTree() {} + CPDF_Object* CPDF_NumberTree::LookupValue(int num) const { - return SearchNumberNode(m_pRoot, num); + return SearchNumberNode(m_pRoot.Get(), num); } diff --git a/core/fpdfdoc/cpdf_numbertree.h b/core/fpdfdoc/cpdf_numbertree.h index bfe44fddb9a58af2d0149d7aba91ddd5e20616ad..47c40b93d312471b0c5f26c983a86e5467bac2c2 100644 --- a/core/fpdfdoc/cpdf_numbertree.h +++ b/core/fpdfdoc/cpdf_numbertree.h @@ -7,17 +7,20 @@ #ifndef CORE_FPDFDOC_CPDF_NUMBERTREE_H_ #define CORE_FPDFDOC_CPDF_NUMBERTREE_H_ +#include "core/fxcrt/unowned_ptr.h" + class CPDF_Dictionary; class CPDF_Object; class CPDF_NumberTree { public: - explicit CPDF_NumberTree(CPDF_Dictionary* pRoot) : m_pRoot(pRoot) {} + explicit CPDF_NumberTree(CPDF_Dictionary* pRoot); + ~CPDF_NumberTree(); CPDF_Object* LookupValue(int num) const; protected: - CPDF_Dictionary* const m_pRoot; + UnownedPtr const m_pRoot; }; #endif // CORE_FPDFDOC_CPDF_NUMBERTREE_H_ diff --git a/core/fpdfdoc/cpdf_occontext.cpp b/core/fpdfdoc/cpdf_occontext.cpp index c4272f4897c93459cd2be8c3e3e2df65ddcec82e..e59690996c992c8c18a2cdfed8b6084dd71b5393 100644 --- a/core/fpdfdoc/cpdf_occontext.cpp +++ b/core/fpdfdoc/cpdf_occontext.cpp @@ -24,13 +24,13 @@ int32_t FindGroup(const CPDF_Array* pArray, const CPDF_Dictionary* pGroupDict) { } bool HasIntent(const CPDF_Dictionary* pDict, - const CFX_ByteStringC& csElement, - const CFX_ByteStringC& csDef) { + const ByteStringView& csElement, + const ByteStringView& csDef) { CPDF_Object* pIntent = pDict->GetDirectObjectFor("Intent"); if (!pIntent) return csElement == csDef; - CFX_ByteString bsIntent; + ByteString bsIntent; if (CPDF_Array* pArray = pIntent->AsArray()) { for (size_t i = 0; i < pArray->GetCount(); i++) { bsIntent = pArray->GetStringAt(i); @@ -70,8 +70,8 @@ CPDF_Dictionary* GetConfig(CPDF_Document* pDoc, return pConfig; } -CFX_ByteString GetUsageTypeString(CPDF_OCContext::UsageType eType) { - CFX_ByteString csState; +ByteString GetUsageTypeString(CPDF_OCContext::UsageType eType) { + ByteString csState; switch (eType) { case CPDF_OCContext::Design: csState = "Design"; @@ -99,9 +99,9 @@ CPDF_OCContext::CPDF_OCContext(CPDF_Document* pDoc, UsageType eUsageType) CPDF_OCContext::~CPDF_OCContext() {} bool CPDF_OCContext::LoadOCGStateFromConfig( - const CFX_ByteString& csConfig, + const ByteString& csConfig, const CPDF_Dictionary* pOCGDict) const { - CPDF_Dictionary* pConfig = GetConfig(m_pDocument, pOCGDict); + CPDF_Dictionary* pConfig = GetConfig(m_pDocument.Get(), pOCGDict); if (!pConfig) return true; @@ -120,7 +120,7 @@ bool CPDF_OCContext::LoadOCGStateFromConfig( if (!pArray) return bState; - CFX_ByteString csFind = csConfig + "State"; + ByteString csFind = csConfig + "State"; for (size_t i = 0; i < pArray->GetCount(); i++) { CPDF_Dictionary* pUsage = pArray->GetDictAt(i); if (!pUsage) @@ -149,12 +149,12 @@ bool CPDF_OCContext::LoadOCGState(const CPDF_Dictionary* pOCGDict) const { if (!HasIntent(pOCGDict, "View", "View")) return true; - CFX_ByteString csState = GetUsageTypeString(m_eUsageType); + ByteString csState = GetUsageTypeString(m_eUsageType); CPDF_Dictionary* pUsage = pOCGDict->GetDictFor("Usage"); if (pUsage) { CPDF_Dictionary* pState = pUsage->GetDictFor(csState); if (pState) { - CFX_ByteString csFind = csState + "State"; + ByteString csFind = csState + "State"; if (pState->KeyExist(csFind)) return pState->GetStringFor(csFind) != "OFF"; } @@ -181,7 +181,7 @@ bool CPDF_OCContext::GetOCGVisible(const CPDF_Dictionary* pOCGDict) { } bool CPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj) { - for (int i = 0; i < pObj->m_ContentMark.CountItems(); i++) { + for (size_t i = 0; i < pObj->m_ContentMark.CountItems(); ++i) { const CPDF_ContentMarkItem& item = pObj->m_ContentMark.GetItem(i); if (item.GetName() == "OC" && item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict && @@ -196,7 +196,7 @@ bool CPDF_OCContext::GetOCGVE(CPDF_Array* pExpression, int nLevel) { if (nLevel > 32 || !pExpression) return false; - CFX_ByteString csOperator = pExpression->GetStringAt(0); + ByteString csOperator = pExpression->GetStringAt(0); if (csOperator == "Not") { CPDF_Object* pOCGObj = pExpression->GetDirectObjectAt(1); if (!pOCGObj) @@ -241,7 +241,7 @@ bool CPDF_OCContext::LoadOCMDState(const CPDF_Dictionary* pOCMDDict) { if (pVE) return GetOCGVE(pVE, 0); - CFX_ByteString csP = pOCMDDict->GetStringFor("P", "AnyOn"); + ByteString csP = pOCMDDict->GetStringFor("P", "AnyOn"); CPDF_Object* pOCGObj = pOCMDDict->GetDirectObjectFor("OCGs"); if (!pOCGObj) return true; @@ -254,25 +254,32 @@ bool CPDF_OCContext::LoadOCMDState(const CPDF_Dictionary* pOCMDDict) { return true; bool bState = (csP == "AllOn" || csP == "AllOff"); + // At least one entry of OCGs needs to be a valid dictionary for it to be + // considered present. See "OCGs" in table 4.49 in the PDF 1.7 spec. + bool bValidEntrySeen = false; for (size_t i = 0; i < pArray->GetCount(); i++) { bool bItem = true; CPDF_Dictionary* pItemDict = pArray->GetDictAt(i); - if (pItemDict) - bItem = GetOCGVisible(pItemDict); + if (!pItemDict) + continue; + + bValidEntrySeen = true; + bItem = GetOCGVisible(pItemDict); if ((csP == "AnyOn" && bItem) || (csP == "AnyOff" && !bItem)) return true; if ((csP == "AllOn" && !bItem) || (csP == "AllOff" && bItem)) return false; } - return bState; + + return !bValidEntrySeen || bState; } bool CPDF_OCContext::CheckOCGVisible(const CPDF_Dictionary* pOCGDict) { if (!pOCGDict) return true; - CFX_ByteString csType = pOCGDict->GetStringFor("Type", "OCG"); + ByteString csType = pOCGDict->GetStringFor("Type", "OCG"); if (csType == "OCG") return GetOCGVisible(pOCGDict); return LoadOCMDState(pOCGDict); diff --git a/core/fpdfdoc/cpdf_occontext.h b/core/fpdfdoc/cpdf_occontext.h index ecdcfae31b663a8a3b96162d9b653ba60c2eb3f1..07b41cc552d68235c999f0038025b59facb00a13 100644 --- a/core/fpdfdoc/cpdf_occontext.h +++ b/core/fpdfdoc/cpdf_occontext.h @@ -7,20 +7,20 @@ #ifndef CORE_FPDFDOC_CPDF_OCCONTEXT_H_ #define CORE_FPDFDOC_CPDF_OCCONTEXT_H_ -#include +#include -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" class CPDF_Array; class CPDF_Dictionary; class CPDF_Document; class CPDF_PageObject; -class CPDF_OCContext : public CFX_Retainable { +class CPDF_OCContext : public Retainable { public: template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); + friend RetainPtr pdfium::MakeRetain(Args&&... args); enum UsageType { View = 0, Design, Print, Export }; @@ -31,16 +31,16 @@ class CPDF_OCContext : public CFX_Retainable { CPDF_OCContext(CPDF_Document* pDoc, UsageType eUsageType); ~CPDF_OCContext() override; - bool LoadOCGStateFromConfig(const CFX_ByteString& csConfig, + bool LoadOCGStateFromConfig(const ByteString& csConfig, const CPDF_Dictionary* pOCGDict) const; bool LoadOCGState(const CPDF_Dictionary* pOCGDict) const; bool GetOCGVisible(const CPDF_Dictionary* pOCGDict); bool GetOCGVE(CPDF_Array* pExpression, int nLevel); bool LoadOCMDState(const CPDF_Dictionary* pOCMDDict); - CPDF_Document* const m_pDocument; + UnownedPtr const m_pDocument; const UsageType m_eUsageType; - std::unordered_map m_OCGStates; + std::map m_OCGStates; }; #endif // CORE_FPDFDOC_CPDF_OCCONTEXT_H_ diff --git a/core/fpdfdoc/cpdf_pagelabel.cpp b/core/fpdfdoc/cpdf_pagelabel.cpp index 2a79d77ca7e38091b766e2f7122c44db526da16f..f06e4018bb2a81af746ab716296b1f64d5c6187e 100644 --- a/core/fpdfdoc/cpdf_pagelabel.cpp +++ b/core/fpdfdoc/cpdf_pagelabel.cpp @@ -13,16 +13,15 @@ namespace { -CFX_WideString MakeRoman(int num) { +WideString MakeRoman(int num) { const int kArabic[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; - const CFX_WideString kRoman[] = {L"m", L"cm", L"d", L"cd", L"c", - L"xc", L"l", L"xl", L"x", L"ix", - L"v", L"iv", L"i"}; + const WideString kRoman[] = {L"m", L"cm", L"d", L"cd", L"c", L"xc", L"l", + L"xl", L"x", L"ix", L"v", L"iv", L"i"}; const int kMaxNum = 1000000; num %= kMaxNum; int i = 0; - CFX_WideString wsRomanNumber; + WideString wsRomanNumber; while (num > 0) { while (num >= kArabic[i]) { num = num - kArabic[i]; @@ -33,41 +32,43 @@ CFX_WideString MakeRoman(int num) { return wsRomanNumber; } -CFX_WideString MakeLetters(int num) { +WideString MakeLetters(int num) { if (num == 0) - return CFX_WideString(); + return WideString(); - CFX_WideString wsLetters; + WideString wsLetters; const int nMaxCount = 1000; const int nLetterCount = 26; --num; int count = num / nLetterCount + 1; count %= nMaxCount; - FX_WCHAR ch = L'a' + num % nLetterCount; + wchar_t ch = L'a' + num % nLetterCount; for (int i = 0; i < count; i++) wsLetters += ch; return wsLetters; } -CFX_WideString GetLabelNumPortion(int num, const CFX_ByteString& bsStyle) { - CFX_WideString wsNumPortion; +WideString GetLabelNumPortion(int num, const ByteString& bsStyle) { if (bsStyle.IsEmpty()) - return wsNumPortion; - if (bsStyle == "D") { - wsNumPortion.Format(L"%d", num); - } else if (bsStyle == "R") { - wsNumPortion = MakeRoman(num); + return L""; + if (bsStyle == "D") + return WideString::Format(L"%d", num); + if (bsStyle == "R") { + WideString wsNumPortion = MakeRoman(num); wsNumPortion.MakeUpper(); - } else if (bsStyle == "r") { - wsNumPortion = MakeRoman(num); - } else if (bsStyle == "A") { - wsNumPortion = MakeLetters(num); + return wsNumPortion; + } + if (bsStyle == "r") + return MakeRoman(num); + if (bsStyle == "A") { + WideString wsNumPortion = MakeLetters(num); wsNumPortion.MakeUpper(); - } else if (bsStyle == "a") { - wsNumPortion = MakeLetters(num); + return wsNumPortion; } - return wsNumPortion; + if (bsStyle == "a") + return MakeLetters(num); + return L""; } } // namespace @@ -75,20 +76,22 @@ CFX_WideString GetLabelNumPortion(int num, const CFX_ByteString& bsStyle) { CPDF_PageLabel::CPDF_PageLabel(CPDF_Document* pDocument) : m_pDocument(pDocument) {} -bool CPDF_PageLabel::GetLabel(int nPage, CFX_WideString* wsLabel) const { +CPDF_PageLabel::~CPDF_PageLabel() {} + +Optional CPDF_PageLabel::GetLabel(int nPage) const { if (!m_pDocument) - return false; + return {}; if (nPage < 0 || nPage >= m_pDocument->GetPageCount()) - return false; + return {}; - CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot(); + const CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot(); if (!pPDFRoot) - return false; + return {}; CPDF_Dictionary* pLabels = pPDFRoot->GetDictFor("PageLabels"); if (!pLabels) - return false; + return {}; CPDF_NumberTree numberTree(pLabels); CPDF_Object* pValue = nullptr; @@ -100,45 +103,47 @@ bool CPDF_PageLabel::GetLabel(int nPage, CFX_WideString* wsLabel) const { n--; } + WideString label; if (pValue) { pValue = pValue->GetDirect(); if (CPDF_Dictionary* pLabel = pValue->AsDictionary()) { if (pLabel->KeyExist("P")) - *wsLabel += pLabel->GetUnicodeTextFor("P"); + label += pLabel->GetUnicodeTextFor("P"); - CFX_ByteString bsNumberingStyle = pLabel->GetStringFor("S", ""); + ByteString bsNumberingStyle = pLabel->GetStringFor("S", ""); int nLabelNum = nPage - n + pLabel->GetIntegerFor("St", 1); - CFX_WideString wsNumPortion = - GetLabelNumPortion(nLabelNum, bsNumberingStyle); - *wsLabel += wsNumPortion; - return true; + WideString wsNumPortion = GetLabelNumPortion(nLabelNum, bsNumberingStyle); + label += wsNumPortion; + return {label}; } } - wsLabel->Format(L"%d", nPage + 1); - return true; + label = WideString::Format(L"%d", nPage + 1); + return {label}; } -int32_t CPDF_PageLabel::GetPageByLabel(const CFX_ByteStringC& bsLabel) const { +int32_t CPDF_PageLabel::GetPageByLabel(const ByteStringView& bsLabel) const { if (!m_pDocument) return -1; - CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot(); + const CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot(); if (!pPDFRoot) return -1; int nPages = m_pDocument->GetPageCount(); for (int i = 0; i < nPages; i++) { - CFX_WideString str; - if (!GetLabel(i, &str)) + Optional str = GetLabel(i); + if (!str.has_value()) continue; - if (PDF_EncodeText(str).Compare(bsLabel)) + if (PDF_EncodeText(str.value()).Compare(bsLabel)) return i; } - int nPage = FXSYS_atoi(CFX_ByteString(bsLabel).c_str()); // NUL terminate. + int nPage = FXSYS_atoi(ByteString(bsLabel).c_str()); // NUL terminate. return nPage > 0 && nPage <= nPages ? nPage : -1; } -int32_t CPDF_PageLabel::GetPageByLabel(const CFX_WideStringC& wsLabel) const { - return GetPageByLabel(PDF_EncodeText(wsLabel.c_str()).AsStringC()); +int32_t CPDF_PageLabel::GetPageByLabel(const WideStringView& wsLabel) const { + // TODO(tsepez): check usage of c_str() below. + return GetPageByLabel( + PDF_EncodeText(wsLabel.unterminated_c_str()).AsStringView()); } diff --git a/core/fpdfdoc/cpdf_pagelabel.h b/core/fpdfdoc/cpdf_pagelabel.h index 0f91f614d98f1f76b9896117487be07a91383514..4570e97b7a091c5078ebb88eee0df3720740b849 100644 --- a/core/fpdfdoc/cpdf_pagelabel.h +++ b/core/fpdfdoc/cpdf_pagelabel.h @@ -8,19 +8,21 @@ #define CORE_FPDFDOC_CPDF_PAGELABEL_H_ #include "core/fxcrt/fx_string.h" +#include "third_party/base/optional.h" class CPDF_Document; class CPDF_PageLabel { public: explicit CPDF_PageLabel(CPDF_Document* pDocument); + ~CPDF_PageLabel(); - bool GetLabel(int nPage, CFX_WideString* wsLabel) const; - int32_t GetPageByLabel(const CFX_ByteStringC& bsLabel) const; - int32_t GetPageByLabel(const CFX_WideStringC& wsLabel) const; + Optional GetLabel(int nPage) const; + int32_t GetPageByLabel(const ByteStringView& bsLabel) const; + int32_t GetPageByLabel(const WideStringView& wsLabel) const; private: - CPDF_Document* const m_pDocument; + UnownedPtr const m_pDocument; }; #endif // CORE_FPDFDOC_CPDF_PAGELABEL_H_ diff --git a/core/fpdfdoc/cpdf_structelement.cpp b/core/fpdfdoc/cpdf_structelement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13985b8fed42cb3518f9a21394808d5d16475d31 --- /dev/null +++ b/core/fpdfdoc/cpdf_structelement.cpp @@ -0,0 +1,136 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfdoc/cpdf_structelement.h" + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_object.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfdoc/cpdf_structtree.h" + +CPDF_StructKid::CPDF_StructKid() + : m_Type(Invalid), + m_pDict(nullptr), + m_PageObjNum(0), + m_RefObjNum(0), + m_ContentId(0) {} + +CPDF_StructKid::CPDF_StructKid(const CPDF_StructKid& that) = default; + +CPDF_StructKid::~CPDF_StructKid() = default; + +CPDF_StructElement::CPDF_StructElement(CPDF_StructTree* pTree, + CPDF_StructElement* pParent, + CPDF_Dictionary* pDict) + : m_pTree(pTree), + m_pParent(pParent), + m_pDict(pDict), + m_Type(pDict->GetStringFor("S")), + m_Title(pDict->GetStringFor("T")) { + if (pTree->GetRoleMap()) { + ByteString mapped = pTree->GetRoleMap()->GetStringFor(m_Type); + if (!mapped.IsEmpty()) + m_Type = mapped; + } + LoadKids(pDict); +} + +CPDF_StructElement::~CPDF_StructElement() = default; + +size_t CPDF_StructElement::CountKids() const { + return m_Kids.size(); +} + +CPDF_StructElement* CPDF_StructElement::GetKidIfElement(size_t index) const { + return m_Kids[index].m_Type == CPDF_StructKid::Element + ? m_Kids[index].m_pElement.Get() + : nullptr; +} + +void CPDF_StructElement::LoadKids(CPDF_Dictionary* pDict) { + CPDF_Object* pObj = pDict->GetObjectFor("Pg"); + uint32_t PageObjNum = 0; + if (CPDF_Reference* pRef = ToReference(pObj)) + PageObjNum = pRef->GetRefObjNum(); + + CPDF_Object* pKids = pDict->GetDirectObjectFor("K"); + if (!pKids) + return; + + m_Kids.clear(); + if (CPDF_Array* pArray = pKids->AsArray()) { + m_Kids.resize(pArray->GetCount()); + for (uint32_t i = 0; i < pArray->GetCount(); i++) { + CPDF_Object* pKid = pArray->GetDirectObjectAt(i); + LoadKid(PageObjNum, pKid, &m_Kids[i]); + } + return; + } + + m_Kids.resize(1); + LoadKid(PageObjNum, pKids, &m_Kids[0]); +} + +void CPDF_StructElement::LoadKid(uint32_t PageObjNum, + CPDF_Object* pKidObj, + CPDF_StructKid* pKid) { + pKid->m_Type = CPDF_StructKid::Invalid; + if (!pKidObj) + return; + + if (pKidObj->IsNumber()) { + if (m_pTree->GetPage() && m_pTree->GetPage()->GetObjNum() != PageObjNum) + return; + + pKid->m_Type = CPDF_StructKid::PageContent; + pKid->m_ContentId = pKidObj->GetInteger(); + pKid->m_PageObjNum = PageObjNum; + return; + } + + CPDF_Dictionary* pKidDict = pKidObj->AsDictionary(); + if (!pKidDict) + return; + if (CPDF_Reference* pRef = ToReference(pKidDict->GetObjectFor("Pg"))) + PageObjNum = pRef->GetRefObjNum(); + + ByteString type = pKidDict->GetStringFor("Type"); + if ((type == "MCR" || type == "OBJR") && m_pTree->GetPage() && + m_pTree->GetPage()->GetObjNum() != PageObjNum) { + return; + } + + if (type == "MCR") { + pKid->m_Type = CPDF_StructKid::StreamContent; + CPDF_Reference* pRef = ToReference(pKidDict->GetObjectFor("Stm")); + pKid->m_RefObjNum = pRef ? pRef->GetRefObjNum() : 0; + pKid->m_PageObjNum = PageObjNum; + pKid->m_ContentId = pKidDict->GetIntegerFor("MCID"); + return; + } + + if (type == "OBJR") { + pKid->m_Type = CPDF_StructKid::Object; + CPDF_Reference* pObj = ToReference(pKidDict->GetObjectFor("Obj")); + pKid->m_RefObjNum = pObj ? pObj->GetRefObjNum() : 0; + pKid->m_PageObjNum = PageObjNum; + return; + } + + pKid->m_Type = CPDF_StructKid::Element; + pKid->m_pDict = pKidDict; + if (m_pTree->GetPage()) { + pKid->m_pElement = nullptr; + return; + } + + pKid->m_pElement = + pdfium::MakeRetain(m_pTree.Get(), this, pKidDict); +} diff --git a/core/fpdfdoc/cpdf_structelement.h b/core/fpdfdoc/cpdf_structelement.h new file mode 100644 index 0000000000000000000000000000000000000000..51ee93bd548a0b7f661ff260e08e34223d51139e --- /dev/null +++ b/core/fpdfdoc/cpdf_structelement.h @@ -0,0 +1,67 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFDOC_CPDF_STRUCTELEMENT_H_ +#define CORE_FPDFDOC_CPDF_STRUCTELEMENT_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/fx_dib.h" + +class CPDF_Dictionary; +class CPDF_Object; +class CPDF_StructElement; +class CPDF_StructTree; + +class CPDF_StructKid { + public: + CPDF_StructKid(); + CPDF_StructKid(const CPDF_StructKid& that); + ~CPDF_StructKid(); + + enum { Invalid, Element, PageContent, StreamContent, Object } m_Type; + + RetainPtr m_pElement; // For Element. + UnownedPtr m_pDict; // For Element. + uint32_t m_PageObjNum; // For PageContent, StreamContent, Object. + uint32_t m_RefObjNum; // For StreamContent, Object. + uint32_t m_ContentId; // For PageContent, StreamContent. +}; + +class CPDF_StructElement : public Retainable { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + const ByteString& GetType() const { return m_Type; } + const ByteString& GetTitle() const { return m_Title; } + CPDF_Dictionary* GetDict() const { return m_pDict.Get(); } + + size_t CountKids() const; + CPDF_StructElement* GetKidIfElement(size_t index) const; + std::vector* GetKids() { return &m_Kids; } + + private: + CPDF_StructElement(CPDF_StructTree* pTree, + CPDF_StructElement* pParent, + CPDF_Dictionary* pDict); + ~CPDF_StructElement() override; + + void LoadKids(CPDF_Dictionary* pDict); + void LoadKid(uint32_t PageObjNum, CPDF_Object* pObj, CPDF_StructKid* pKid); + + UnownedPtr const m_pTree; + UnownedPtr const m_pParent; + UnownedPtr const m_pDict; + ByteString m_Type; + ByteString m_Title; + std::vector m_Kids; +}; + +#endif // CORE_FPDFDOC_CPDF_STRUCTELEMENT_H_ diff --git a/core/fpdfdoc/cpdf_structtree.cpp b/core/fpdfdoc/cpdf_structtree.cpp new file mode 100644 index 0000000000000000000000000000000000000000..97db691425a60e09680fa0860fd45fa1e7ac77f4 --- /dev/null +++ b/core/fpdfdoc/cpdf_structtree.cpp @@ -0,0 +1,145 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fpdfdoc/cpdf_structtree.h" + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfdoc/cpdf_numbertree.h" +#include "core/fpdfdoc/cpdf_structelement.h" + +namespace { + +bool IsTagged(const CPDF_Document* pDoc) { + const CPDF_Dictionary* pCatalog = pDoc->GetRoot(); + const CPDF_Dictionary* pMarkInfo = pCatalog->GetDictFor("MarkInfo"); + return pMarkInfo && pMarkInfo->GetIntegerFor("Marked"); +} + +} // namespace + +// static +std::unique_ptr CPDF_StructTree::LoadPage( + const CPDF_Document* pDoc, + const CPDF_Dictionary* pPageDict) { + if (!IsTagged(pDoc)) + return nullptr; + + auto pTree = pdfium::MakeUnique(pDoc); + pTree->LoadPageTree(pPageDict); + return pTree; +} + +CPDF_StructTree::CPDF_StructTree(const CPDF_Document* pDoc) + : m_pTreeRoot(pDoc->GetRoot()->GetDictFor("StructTreeRoot")), + m_pRoleMap(m_pTreeRoot ? m_pTreeRoot->GetDictFor("RoleMap") : nullptr), + m_pPage(nullptr) {} + +CPDF_StructTree::~CPDF_StructTree() {} + +void CPDF_StructTree::LoadPageTree(const CPDF_Dictionary* pPageDict) { + m_pPage = pPageDict; + if (!m_pTreeRoot) + return; + + CPDF_Object* pKids = m_pTreeRoot->GetDirectObjectFor("K"); + if (!pKids) + return; + + uint32_t dwKids = 0; + if (pKids->IsDictionary()) + dwKids = 1; + else if (CPDF_Array* pArray = pKids->AsArray()) + dwKids = pArray->GetCount(); + else + return; + + m_Kids.clear(); + m_Kids.resize(dwKids); + CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDictFor("ParentTree"); + if (!pParentTree) + return; + + CPDF_NumberTree parent_tree(pParentTree); + int parents_id = pPageDict->GetIntegerFor("StructParents", -1); + if (parents_id < 0) + return; + + CPDF_Array* pParentArray = ToArray(parent_tree.LookupValue(parents_id)); + if (!pParentArray) + return; + + std::map> element_map; + for (size_t i = 0; i < pParentArray->GetCount(); i++) { + if (CPDF_Dictionary* pParent = pParentArray->GetDictAt(i)) + AddPageNode(pParent, &element_map, 0); + } +} + +RetainPtr CPDF_StructTree::AddPageNode( + CPDF_Dictionary* pDict, + std::map>* map, + int nLevel) { + static constexpr int kStructTreeMaxRecursion = 32; + if (nLevel > kStructTreeMaxRecursion) + return nullptr; + + auto it = map->find(pDict); + if (it != map->end()) + return it->second; + + auto pElement = pdfium::MakeRetain(this, nullptr, pDict); + (*map)[pDict] = pElement; + CPDF_Dictionary* pParent = pDict->GetDictFor("P"); + if (!pParent || pParent->GetStringFor("Type") == "StructTreeRoot") { + if (!AddTopLevelNode(pDict, pElement)) + map->erase(pDict); + return pElement; + } + + RetainPtr pParentElement = + AddPageNode(pParent, map, nLevel + 1); + bool bSave = false; + for (CPDF_StructKid& kid : *pParentElement->GetKids()) { + if (kid.m_Type == CPDF_StructKid::Element && kid.m_pDict == pDict) { + kid.m_pElement = pElement; + bSave = true; + } + } + if (!bSave) + map->erase(pDict); + return pElement; +} + +bool CPDF_StructTree::AddTopLevelNode( + CPDF_Dictionary* pDict, + const RetainPtr& pElement) { + CPDF_Object* pObj = m_pTreeRoot->GetDirectObjectFor("K"); + if (!pObj) + return false; + + if (pObj->IsDictionary()) { + if (pObj->GetObjNum() != pDict->GetObjNum()) + return false; + m_Kids[0] = pElement; + } + + CPDF_Array* pTopKids = pObj->AsArray(); + if (!pTopKids) + return true; + + bool bSave = false; + for (size_t i = 0; i < pTopKids->GetCount(); i++) { + CPDF_Reference* pKidRef = ToReference(pTopKids->GetObjectAt(i)); + if (pKidRef && pKidRef->GetRefObjNum() == pDict->GetObjNum()) { + m_Kids[i] = pElement; + bSave = true; + } + } + return bSave; +} diff --git a/core/fpdfdoc/cpdf_structtree.h b/core/fpdfdoc/cpdf_structtree.h new file mode 100644 index 0000000000000000000000000000000000000000..99342fb6decd1249b56ae73beab8612e0590ebf8 --- /dev/null +++ b/core/fpdfdoc/cpdf_structtree.h @@ -0,0 +1,51 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFDOC_CPDF_STRUCTTREE_H_ +#define CORE_FPDFDOC_CPDF_STRUCTTREE_H_ + +#include +#include +#include + +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPDF_Dictionary; +class CPDF_Document; +class CPDF_StructElement; + +class CPDF_StructTree { + public: + static std::unique_ptr LoadPage( + const CPDF_Document* pDoc, + const CPDF_Dictionary* pPageDict); + + explicit CPDF_StructTree(const CPDF_Document* pDoc); + ~CPDF_StructTree(); + + size_t CountTopElements() const { return m_Kids.size(); } + CPDF_StructElement* GetTopElement(size_t i) const { return m_Kids[i].Get(); } + const CPDF_Dictionary* GetRoleMap() const { return m_pRoleMap.Get(); } + const CPDF_Dictionary* GetPage() const { return m_pPage.Get(); } + const CPDF_Dictionary* GetTreeRoot() const { return m_pTreeRoot.Get(); } + + private: + void LoadPageTree(const CPDF_Dictionary* pPageDict); + RetainPtr AddPageNode( + CPDF_Dictionary* pElement, + std::map>* map, + int nLevel); + bool AddTopLevelNode(CPDF_Dictionary* pDict, + const RetainPtr& pElement); + + UnownedPtr const m_pTreeRoot; + UnownedPtr const m_pRoleMap; + UnownedPtr m_pPage; + std::vector> m_Kids; +}; + +#endif // CORE_FPDFDOC_CPDF_STRUCTTREE_H_ diff --git a/core/fpdfdoc/cpdf_variabletext.cpp b/core/fpdfdoc/cpdf_variabletext.cpp index 94b3425a097aba5e239ff3de7ec8b824edcd1d29..74ea239cc6d3ecb8d8583321a00bf6b7cda94a69 100644 --- a/core/fpdfdoc/cpdf_variabletext.cpp +++ b/core/fpdfdoc/cpdf_variabletext.cpp @@ -7,15 +7,17 @@ #include "core/fpdfdoc/cpdf_variabletext.h" #include +#include #include "core/fpdfapi/font/cpdf_font.h" #include "core/fpdfdoc/cline.h" -#include "core/fpdfdoc/cpvt_section.h" #include "core/fpdfdoc/cpvt_word.h" #include "core/fpdfdoc/cpvt_wordinfo.h" #include "core/fpdfdoc/csection.h" #include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/fx_codepage.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" namespace { @@ -112,51 +114,18 @@ bool CPDF_VariableText::Iterator::PrevWord() { } bool CPDF_VariableText::Iterator::NextLine() { - if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) { - m_CurPos = - CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1); - return true; - } - if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) { - m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1); - return true; - } - } - return false; -} - -bool CPDF_VariableText::Iterator::PrevLine() { - if (m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - if (m_CurPos.nLineIndex > 0) { - m_CurPos = - CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1); - return true; - } - if (m_CurPos.nSecIndex > 0) { - if (CSection* pLastSection = - m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) { - m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, - pLastSection->m_LineArray.GetSize() - 1, -1); - return true; - } - } - } - return false; -} + if (!pdfium::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex)) + return false; -bool CPDF_VariableText::Iterator::NextSection() { - if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) { - m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1); + CSection* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get(); + if (m_CurPos.nLineIndex < + pdfium::CollectionSize(pSection->m_LineArray) - 1) { + m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1); return true; } - return false; -} - -bool CPDF_VariableText::Iterator::PrevSection() { - ASSERT(m_pVT); - if (m_CurPos.nSecIndex > 0) { - m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1); + if (m_CurPos.nSecIndex < + pdfium::CollectionSize(m_pVT->m_SectionArray) - 1) { + m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1); return true; } return false; @@ -164,82 +133,48 @@ bool CPDF_VariableText::Iterator::PrevSection() { bool CPDF_VariableText::Iterator::GetWord(CPVT_Word& word) const { word.WordPlace = m_CurPos; - if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - if (pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) { - if (CPVT_WordInfo* pWord = - pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) { - word.Word = pWord->Word; - word.nCharset = pWord->nCharset; - word.fWidth = m_pVT->GetWordWidth(*pWord); - word.ptWord = m_pVT->InToOut( - CFX_PointF(pWord->fWordX + pSection->m_SecInfo.rcSection.left, - pWord->fWordY + pSection->m_SecInfo.rcSection.top)); - word.fAscent = m_pVT->GetWordAscent(*pWord); - word.fDescent = m_pVT->GetWordDescent(*pWord); - if (pWord->pWordProps) - word.WordProps = *pWord->pWordProps; - - word.nFontIndex = m_pVT->GetWordFontIndex(*pWord); - word.fFontSize = m_pVT->GetWordFontSize(*pWord); - return true; - } - } - } - return false; -} + if (!pdfium::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex)) + return false; -bool CPDF_VariableText::Iterator::SetWord(const CPVT_Word& word) { - if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - if (CPVT_WordInfo* pWord = - pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) { - if (pWord->pWordProps) - *pWord->pWordProps = word.WordProps; - return true; - } + CSection* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_LineArray, m_CurPos.nLineIndex) || + !pdfium::IndexInBounds(pSection->m_WordArray, m_CurPos.nWordIndex)) { + return false; } - return false; + + CPVT_WordInfo* pWord = pSection->m_WordArray[m_CurPos.nWordIndex].get(); + word.Word = pWord->Word; + word.nCharset = pWord->nCharset; + word.fWidth = m_pVT->GetWordWidth(*pWord); + word.ptWord = + m_pVT->InToOut(CFX_PointF(pWord->fWordX + pSection->m_Rect.left, + pWord->fWordY + pSection->m_Rect.top)); + word.fAscent = m_pVT->GetWordAscent(*pWord); + word.fDescent = m_pVT->GetWordDescent(*pWord); + word.nFontIndex = m_pVT->GetWordFontIndex(*pWord); + word.fFontSize = m_pVT->GetWordFontSize(); + return true; } bool CPDF_VariableText::Iterator::GetLine(CPVT_Line& line) const { ASSERT(m_pVT); line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1); - if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - if (CLine* pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) { - line.ptLine = m_pVT->InToOut(CFX_PointF( - pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left, - pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top)); - line.fLineWidth = pLine->m_LineInfo.fLineWidth; - line.fLineAscent = pLine->m_LineInfo.fLineAscent; - line.fLineDescent = pLine->m_LineInfo.fLineDescent; - line.lineEnd = pLine->GetEndWordPlace(); - return true; - } - } - return false; -} + if (!pdfium::IndexInBounds(m_pVT->m_SectionArray, m_CurPos.nSecIndex)) + return false; -bool CPDF_VariableText::Iterator::GetSection(CPVT_Section& section) const { - section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1); - if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection); - if (pSection->m_SecInfo.pSecProps) - section.SecProps = *pSection->m_SecInfo.pSecProps; - if (pSection->m_SecInfo.pWordProps) - section.WordProps = *pSection->m_SecInfo.pWordProps; - return true; - } - return false; -} + CSection* pSection = m_pVT->m_SectionArray[m_CurPos.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_LineArray, m_CurPos.nLineIndex)) + return false; -bool CPDF_VariableText::Iterator::SetSection(const CPVT_Section& section) { - if (CSection* pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) { - if (pSection->m_SecInfo.pSecProps) - *pSection->m_SecInfo.pSecProps = section.SecProps; - if (pSection->m_SecInfo.pWordProps) - *pSection->m_SecInfo.pWordProps = section.WordProps; - return true; - } - return false; + CLine* pLine = pSection->m_LineArray[m_CurPos.nLineIndex].get(); + line.ptLine = m_pVT->InToOut( + CFX_PointF(pLine->m_LineInfo.fLineX + pSection->m_Rect.left, + pLine->m_LineInfo.fLineY + pSection->m_Rect.top)); + line.fLineWidth = pLine->m_LineInfo.fLineWidth; + line.fLineAscent = pLine->m_LineInfo.fLineAscent; + line.fLineDescent = pLine->m_LineInfo.fLineDescent; + line.lineEnd = pLine->GetEndWordPlace(); + return true; } CPDF_VariableText::CPDF_VariableText() @@ -254,44 +189,37 @@ CPDF_VariableText::CPDF_VariableText() m_nHorzScale(100), m_wSubWord(0), m_fFontSize(0.0f), - m_bInitial(false), + m_bInitialized(false), m_pVTProvider(nullptr) {} -CPDF_VariableText::~CPDF_VariableText() { - ResetAll(); -} +CPDF_VariableText::~CPDF_VariableText() {} void CPDF_VariableText::Initialize() { - if (!m_bInitial) { - CPVT_SectionInfo secinfo; - CPVT_WordPlace place; - place.nSecIndex = 0; - AddSection(place, secinfo); - CPVT_LineInfo lineinfo; - lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize()); - lineinfo.fLineDescent = - GetFontDescent(GetDefaultFontIndex(), GetFontSize()); - AddLine(place, lineinfo); - if (CSection* pSection = m_SectionArray.GetAt(0)) - pSection->ResetLinePlace(); + if (m_bInitialized) + return; - m_bInitial = true; - } -} + CPVT_WordPlace place; + place.nSecIndex = 0; + AddSection(place); + + CPVT_LineInfo lineinfo; + lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize()); + lineinfo.fLineDescent = GetFontDescent(GetDefaultFontIndex(), GetFontSize()); + AddLine(place, lineinfo); -void CPDF_VariableText::ResetAll() { - m_bInitial = false; - ResetSectionArray(); + if (!m_SectionArray.empty()) + m_SectionArray.front()->ResetLinePlace(); + + m_bInitialized = true; } CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace& place, uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps) { - int32_t nTotlaWords = GetTotalWords(); - if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) + int32_t charset) { + int32_t nTotalWords = GetTotalWords(); + if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar) return place; - if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) + if (m_nCharArray > 0 && nTotalWords >= m_nCharArray) return place; CPVT_WordPlace newplace = place; @@ -299,85 +227,45 @@ CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace& place, int32_t nFontIndex = GetSubWord() > 0 ? GetDefaultFontIndex() : GetWordFontIndex(word, charset, GetDefaultFontIndex()); - return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, nullptr)); + return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex)); } -CPVT_WordPlace CPDF_VariableText::InsertSection( - const CPVT_WordPlace& place, - const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps) { - int32_t nTotlaWords = GetTotalWords(); - if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) +CPVT_WordPlace CPDF_VariableText::InsertSection(const CPVT_WordPlace& place) { + int32_t nTotalWords = GetTotalWords(); + if (m_nLimitChar > 0 && nTotalWords >= m_nLimitChar) return place; - if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) + if (m_nCharArray > 0 && nTotalWords >= m_nCharArray) return place; if (!m_bMultiLine) return place; CPVT_WordPlace wordplace = place; UpdateWordPlace(wordplace); - CPVT_WordPlace newplace = place; - if (CSection* pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) { - CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1); - CPVT_SectionInfo secinfo; - AddSection(NewPlace, secinfo); - newplace = NewPlace; - if (CSection* pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) { - for (int32_t w = wordplace.nWordIndex + 1, - sz = pSection->m_WordArray.GetSize(); - w < sz; w++) { - if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(w)) { - NewPlace.nWordIndex++; - pNewSection->AddWord(NewPlace, *pWord); - } - } - } - ClearSectionRightWords(wordplace); - } - return newplace; -} - -CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace& place, - const FX_WCHAR* text) { - CFX_WideString swText = text; - CPVT_WordPlace wp = place; - for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) { - CPVT_WordPlace oldwp = wp; - uint16_t word = swText.GetAt(i); - switch (word) { - case 0x0D: - if (m_bMultiLine) { - if (swText.GetAt(i + 1) == 0x0A) - i += 1; - - wp = InsertSection(wp, nullptr, nullptr); - } - break; - case 0x0A: - if (m_bMultiLine) { - if (swText.GetAt(i + 1) == 0x0D) - i += 1; + if (!pdfium::IndexInBounds(m_SectionArray, wordplace.nSecIndex)) + return place; - wp = InsertSection(wp, nullptr, nullptr); - } - break; - case 0x09: - word = 0x20; - default: - wp = InsertWord(wp, word, FXFONT_DEFAULT_CHARSET, nullptr); - break; + CSection* pSection = m_SectionArray[wordplace.nSecIndex].get(); + CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1); + AddSection(NewPlace); + CPVT_WordPlace result = NewPlace; + if (pdfium::IndexInBounds(m_SectionArray, NewPlace.nSecIndex)) { + CSection* pNewSection = m_SectionArray[NewPlace.nSecIndex].get(); + for (int32_t w = wordplace.nWordIndex + 1; + w < pdfium::CollectionSize(pSection->m_WordArray); ++w) { + NewPlace.nWordIndex++; + pNewSection->AddWord(NewPlace, *pSection->m_WordArray[w]); } - if (wp == oldwp) - break; } - return wp; + ClearSectionRightWords(wordplace); + return result; } CPVT_WordPlace CPDF_VariableText::DeleteWords( const CPVT_WordRange& PlaceRange) { - bool bLastSecPos = false; - if (CSection* pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) - bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace()); + bool bLastSecPos = + pdfium::IndexInBounds(m_SectionArray, PlaceRange.EndPos.nSecIndex) && + PlaceRange.EndPos == + m_SectionArray[PlaceRange.EndPos.nSecIndex]->GetEndWordPlace(); ClearWords(PlaceRange); if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) { @@ -396,12 +284,11 @@ CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace& place) { return ClearLeftWord(AdjustLineHeader(place, true)); } -void CPDF_VariableText::SetText(const CFX_WideString& swText) { +void CPDF_VariableText::SetText(const WideString& swText) { DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace())); CPVT_WordPlace wp(0, 0, -1); - CPVT_SectionInfo secinfo; - if (CSection* pSection = m_SectionArray.GetAt(0)) - pSection->m_SecInfo = secinfo; + if (!m_SectionArray.empty()) + m_SectionArray.front()->m_Rect = CPVT_FloatRect(); int32_t nCharCount = 0; for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) { @@ -410,34 +297,28 @@ void CPDF_VariableText::SetText(const CFX_WideString& swText) { if (m_nCharArray > 0 && nCharCount >= m_nCharArray) break; - uint16_t word = swText.GetAt(i); + uint16_t word = swText[i]; switch (word) { case 0x0D: if (m_bMultiLine) { - if (swText.GetAt(i + 1) == 0x0A) - i += 1; - - wp.nSecIndex++; - wp.nLineIndex = 0; - wp.nWordIndex = -1; - AddSection(wp, secinfo); + if (i + 1 < sz && swText[i + 1] == 0x0A) + i++; + wp.AdvanceSection(); + AddSection(wp); } break; case 0x0A: if (m_bMultiLine) { - if (swText.GetAt(i + 1) == 0x0D) - i += 1; - - wp.nSecIndex++; - wp.nLineIndex = 0; - wp.nWordIndex = -1; - AddSection(wp, secinfo); + if (i + 1 < sz && swText[i + 1] == 0x0D) + i++; + wp.AdvanceSection(); + AddSection(wp); } break; case 0x09: word = 0x20; default: - wp = InsertWord(wp, word, FXFONT_DEFAULT_CHARSET, nullptr); + wp = InsertWord(wp, word, FX_CHARSET_Default); break; } nCharCount++; @@ -447,12 +328,12 @@ void CPDF_VariableText::SetText(const CFX_WideString& swText) { void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace& place) const { if (place.nSecIndex < 0) place = GetBeginWordPlace(); - if (place.nSecIndex >= m_SectionArray.GetSize()) + if (place.nSecIndex >= pdfium::CollectionSize(m_SectionArray)) place = GetEndWordPlace(); place = AdjustLineHeader(place, true); - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) - pSection->UpdateWordPlace(place); + if (pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + m_SectionArray[place.nSecIndex]->UpdateWordPlace(place); } int32_t CPDF_VariableText::WordPlaceToWordIndex( @@ -462,89 +343,86 @@ int32_t CPDF_VariableText::WordPlaceToWordIndex( int32_t nIndex = 0; int32_t i = 0; int32_t sz = 0; - for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex; - i++) { - if (CSection* pSection = m_SectionArray.GetAt(i)) { - nIndex += pSection->m_WordArray.GetSize(); - if (i != m_SectionArray.GetSize() - 1) - nIndex += kReturnLength; - } - } - if (i >= 0 && i < m_SectionArray.GetSize()) + for (i = 0, sz = pdfium::CollectionSize(m_SectionArray); + i < sz && i < newplace.nSecIndex; i++) { + CSection* pSection = m_SectionArray[i].get(); + nIndex += pdfium::CollectionSize(pSection->m_WordArray); + if (i != sz - 1) + nIndex += kReturnLength; + } + if (pdfium::IndexInBounds(m_SectionArray, i)) nIndex += newplace.nWordIndex + kReturnLength; return nIndex; } CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(int32_t index) const { CPVT_WordPlace place = GetBeginWordPlace(); - int32_t nOldIndex = 0, nIndex = 0; - bool bFind = false; - for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) { - if (CSection* pSection = m_SectionArray.GetAt(i)) { - nIndex += pSection->m_WordArray.GetSize(); - if (nIndex == index) { - place = pSection->GetEndWordPlace(); - bFind = true; - break; - } else if (nIndex > index) { - place.nSecIndex = i; - place.nWordIndex = index - nOldIndex - 1; - pSection->UpdateWordPlace(place); - bFind = true; - break; - } - if (i != m_SectionArray.GetSize() - 1) - nIndex += kReturnLength; - nOldIndex = nIndex; + int32_t nOldIndex = 0; + int32_t nIndex = 0; + bool bFound = false; + for (int32_t i = 0, sz = pdfium::CollectionSize(m_SectionArray); + i < sz; i++) { + CSection* pSection = m_SectionArray[i].get(); + nIndex += pdfium::CollectionSize(pSection->m_WordArray); + if (nIndex == index) { + place = pSection->GetEndWordPlace(); + bFound = true; + break; } + if (nIndex > index) { + place.nSecIndex = i; + place.nWordIndex = index - nOldIndex - 1; + pSection->UpdateWordPlace(place); + bFound = true; + break; + } + if (i != sz - 1) + nIndex += kReturnLength; + nOldIndex = nIndex; } - if (!bFind) + if (!bFound) place = GetEndWordPlace(); return place; } CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const { - return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace(); + return m_bInitialized ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace(); } CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const { - if (CSection* pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) - return pSection->GetEndWordPlace(); - return CPVT_WordPlace(); + if (m_SectionArray.empty()) + return CPVT_WordPlace(); + return m_SectionArray.back()->GetEndWordPlace(); } CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace( const CPVT_WordPlace& place) const { if (place.nSecIndex < 0) return GetBeginWordPlace(); - if (place.nSecIndex >= m_SectionArray.GetSize()) + if (place.nSecIndex >= pdfium::CollectionSize(m_SectionArray)) return GetEndWordPlace(); - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) { - if (CSection* pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) - return pPrevSection->GetEndWordPlace(); - return GetBeginWordPlace(); - } + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (place > pSection->GetBeginWordPlace()) return pSection->GetPrevWordPlace(place); - } - return place; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex - 1)) + return GetBeginWordPlace(); + return m_SectionArray[place.nSecIndex - 1]->GetEndWordPlace(); } CPVT_WordPlace CPDF_VariableText::GetNextWordPlace( const CPVT_WordPlace& place) const { if (place.nSecIndex < 0) return GetBeginWordPlace(); - if (place.nSecIndex >= m_SectionArray.GetSize()) + if (place.nSecIndex >= pdfium::CollectionSize(m_SectionArray)) return GetEndWordPlace(); - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) { - if (CSection* pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) - return pNextSection->GetBeginWordPlace(); - return GetEndWordPlace(); - } + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (place < pSection->GetEndWordPlace()) return pSection->GetNextWordPlace(place); - } - return place; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex + 1)) + return GetEndWordPlace(); + return m_SectionArray[place.nSecIndex + 1]->GetBeginWordPlace(); } CPVT_WordPlace CPDF_VariableText::SearchWordPlace( @@ -552,36 +430,32 @@ CPVT_WordPlace CPDF_VariableText::SearchWordPlace( CFX_PointF pt = OutToIn(point); CPVT_WordPlace place = GetBeginWordPlace(); int32_t nLeft = 0; - int32_t nRight = m_SectionArray.GetSize() - 1; - int32_t nMid = m_SectionArray.GetSize() / 2; + int32_t nRight = pdfium::CollectionSize(m_SectionArray) - 1; + int32_t nMid = pdfium::CollectionSize(m_SectionArray) / 2; bool bUp = true; bool bDown = true; while (nLeft <= nRight) { - if (CSection* pSection = m_SectionArray.GetAt(nMid)) { - if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) { - bUp = false; - } - if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) { - bDown = false; - } - if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) { - nRight = nMid - 1; - nMid = (nLeft + nRight) / 2; - continue; - } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) { - nLeft = nMid + 1; - nMid = (nLeft + nRight) / 2; - continue; - } else { - place = pSection->SearchWordPlace( - CFX_PointF(pt.x - pSection->m_SecInfo.rcSection.left, - pt.y - pSection->m_SecInfo.rcSection.top)); - place.nSecIndex = nMid; - return place; - } - } else { + if (!pdfium::IndexInBounds(m_SectionArray, nMid)) break; + CSection* pSection = m_SectionArray[nMid].get(); + if (IsFloatBigger(pt.y, pSection->m_Rect.top)) + bUp = false; + if (IsFloatBigger(pSection->m_Rect.bottom, pt.y)) + bDown = false; + if (IsFloatSmaller(pt.y, pSection->m_Rect.top)) { + nRight = nMid - 1; + nMid = (nLeft + nRight) / 2; + continue; } + if (IsFloatBigger(pt.y, pSection->m_Rect.bottom)) { + nLeft = nMid + 1; + nMid = (nLeft + nRight) / 2; + continue; + } + place = pSection->SearchWordPlace( + CFX_PointF(pt.x - pSection->m_Rect.left, pt.y - pSection->m_Rect.top)); + place.nSecIndex = nMid; + return place; } if (bUp) place = GetBeginWordPlace(); @@ -593,19 +467,22 @@ CPVT_WordPlace CPDF_VariableText::SearchWordPlace( CPVT_WordPlace CPDF_VariableText::GetUpWordPlace( const CPVT_WordPlace& place, const CFX_PointF& point) const { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - CPVT_WordPlace temp = place; - CFX_PointF pt = OutToIn(point); - if (temp.nLineIndex-- > 0) { - return pSection->SearchWordPlace( - pt.x - pSection->m_SecInfo.rcSection.left, temp); - } - if (temp.nSecIndex-- > 0) { - if (CSection* pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) { - temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1; - return pLastSection->SearchWordPlace( - pt.x - pLastSection->m_SecInfo.rcSection.left, temp); - } + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return place; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + CPVT_WordPlace temp = place; + CFX_PointF pt = OutToIn(point); + if (temp.nLineIndex-- > 0) { + return pSection->SearchWordPlace(pt.x - pSection->m_Rect.left, temp); + } + if (temp.nSecIndex-- > 0) { + if (pdfium::IndexInBounds(m_SectionArray, temp.nSecIndex)) { + CSection* pLastSection = m_SectionArray[temp.nSecIndex].get(); + temp.nLineIndex = + pdfium::CollectionSize(pLastSection->m_LineArray) - 1; + return pLastSection->SearchWordPlace(pt.x - pLastSection->m_Rect.left, + temp); } } return place; @@ -614,22 +491,22 @@ CPVT_WordPlace CPDF_VariableText::GetUpWordPlace( CPVT_WordPlace CPDF_VariableText::GetDownWordPlace( const CPVT_WordPlace& place, const CFX_PointF& point) const { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - CPVT_WordPlace temp = place; - CFX_PointF pt = OutToIn(point); - if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) { - return pSection->SearchWordPlace( - pt.x - pSection->m_SecInfo.rcSection.left, temp); - } - if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) { - if (CSection* pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) { - temp.nLineIndex = 0; - return pNextSection->SearchWordPlace( - pt.x - pSection->m_SecInfo.rcSection.left, temp); - } - } + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return place; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + CPVT_WordPlace temp = place; + CFX_PointF pt = OutToIn(point); + if (temp.nLineIndex++ < + pdfium::CollectionSize(pSection->m_LineArray) - 1) { + return pSection->SearchWordPlace(pt.x - pSection->m_Rect.left, temp); } - return place; + temp.AdvanceSection(); + if (!pdfium::IndexInBounds(m_SectionArray, temp.nSecIndex)) + return place; + + return m_SectionArray[temp.nSecIndex]->SearchWordPlace( + pt.x - pSection->m_Rect.left, temp); } CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace( @@ -639,11 +516,14 @@ CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace( CPVT_WordPlace CPDF_VariableText::GetLineEndPlace( const CPVT_WordPlace& place) const { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (CLine* pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) - return pLine->GetEndWordPlace(); - } - return place; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return place; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_LineArray, place.nLineIndex)) + return place; + + return pSection->m_LineArray[place.nLineIndex]->GetEndWordPlace(); } CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace( @@ -653,108 +533,93 @@ CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace( CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace( const CPVT_WordPlace& place) const { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) - return pSection->GetEndWordPlace(); - return place; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return place; + + return m_SectionArray[place.nSecIndex]->GetEndWordPlace(); } int32_t CPDF_VariableText::GetTotalWords() const { int32_t nTotal = 0; - for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) { - if (CSection* pSection = m_SectionArray.GetAt(i)) - nTotal += (pSection->m_WordArray.GetSize() + kReturnLength); + for (const auto& pSection : m_SectionArray) { + nTotal += + pdfium::CollectionSize(pSection->m_WordArray) + kReturnLength; } - return nTotal - kReturnLength; } -void CPDF_VariableText::ResetSectionArray() { - for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) - delete m_SectionArray.GetAt(s); - - m_SectionArray.RemoveAll(); -} - -CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace& place, - const CPVT_SectionInfo& secinfo) { +CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace& place) { if (IsValid() && !m_bMultiLine) return place; - int32_t nSecIndex = - std::max(std::min(place.nSecIndex, m_SectionArray.GetSize()), 0); - CSection* pSection = new CSection(this); - pSection->m_SecInfo = secinfo; - pSection->SecPlace.nSecIndex = nSecIndex; - if (nSecIndex == m_SectionArray.GetSize()) - m_SectionArray.Add(pSection); - else - m_SectionArray.InsertAt(nSecIndex, pSection); + int32_t nSecIndex = pdfium::clamp( + place.nSecIndex, 0, pdfium::CollectionSize(m_SectionArray)); + auto pSection = pdfium::MakeUnique(this); + pSection->m_Rect = CPVT_FloatRect(); + pSection->SecPlace.nSecIndex = nSecIndex; + m_SectionArray.insert(m_SectionArray.begin() + nSecIndex, + std::move(pSection)); return place; } CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace& place, const CPVT_LineInfo& lineinfo) { - if (m_SectionArray.IsEmpty()) + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) return place; - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) - return pSection->AddLine(lineinfo); - return place; + + return m_SectionArray[place.nSecIndex]->AddLine(lineinfo); } CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace& place, const CPVT_WordInfo& wordinfo) { - if (m_SectionArray.GetSize() <= 0) { + if (m_SectionArray.empty()) return place; - } + CPVT_WordPlace newplace = place; newplace.nSecIndex = - std::max(std::min(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0); - if (CSection* pSection = m_SectionArray.GetAt(newplace.nSecIndex)) - return pSection->AddWord(newplace, wordinfo); - return place; + pdfium::clamp(newplace.nSecIndex, 0, + pdfium::CollectionSize(m_SectionArray) - 1); + return m_SectionArray[newplace.nSecIndex]->AddWord(newplace, wordinfo); } bool CPDF_VariableText::GetWordInfo(const CPVT_WordPlace& place, CPVT_WordInfo& wordinfo) { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) { - wordinfo = *pWord; - return true; - } - } - return false; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return false; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_WordArray, place.nWordIndex)) + return false; + + wordinfo = *pSection->m_WordArray[place.nWordIndex]; + return true; } bool CPDF_VariableText::SetWordInfo(const CPVT_WordPlace& place, const CPVT_WordInfo& wordinfo) { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (CPVT_WordInfo* pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) { - *pWord = wordinfo; - return true; - } - } - return false; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return false; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_WordArray, place.nWordIndex)) + return false; + + *pSection->m_WordArray[place.nWordIndex] = wordinfo; + return true; } bool CPDF_VariableText::GetLineInfo(const CPVT_WordPlace& place, CPVT_LineInfo& lineinfo) { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (CLine* pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) { - lineinfo = pLine->m_LineInfo; - return true; - } - } - return false; -} + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return false; -bool CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace& place, - CPVT_SectionInfo& secinfo) { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - secinfo = pSection->m_SecInfo; - return true; - } - return false; + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_LineArray, place.nLineIndex)) + return false; + + lineinfo = pSection->m_LineArray[place.nLineIndex]->m_LineInfo; + return true; } void CPDF_VariableText::SetPlateRect(const CFX_FloatRect& rect) { @@ -773,7 +638,7 @@ const CFX_FloatRect& CPDF_VariableText::GetPlateRect() const { return m_rcPlate; } -FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo& WordInfo) { +float CPDF_VariableText::GetWordFontSize() { return GetFontSize(); } @@ -781,90 +646,83 @@ int32_t CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo& WordInfo) { return WordInfo.nFontIndex; } -FX_FLOAT CPDF_VariableText::GetWordWidth(int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord, - FX_FLOAT fCharSpace, - int32_t nHorzScale, - FX_FLOAT fFontSize, - FX_FLOAT fWordTail) { +float CPDF_VariableText::GetWordWidth(int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord, + float fCharSpace, + int32_t nHorzScale, + float fFontSize, + float fWordTail) { return (GetCharWidth(nFontIndex, Word, SubWord) * fFontSize * kFontScale + fCharSpace) * nHorzScale * kScalePercent + fWordTail; } -FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo& WordInfo) { +float CPDF_VariableText::GetWordWidth(const CPVT_WordInfo& WordInfo) { return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), - GetCharSpace(WordInfo), GetHorzScale(WordInfo), - GetWordFontSize(WordInfo), WordInfo.fWordTail); + GetCharSpace(), GetHorzScale(), GetWordFontSize(), + WordInfo.fWordTail); } -FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo& SecInfo) { +float CPDF_VariableText::GetLineAscent() { return GetFontAscent(GetDefaultFontIndex(), GetFontSize()); } -FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo& SecInfo) { +float CPDF_VariableText::GetLineDescent() { return GetFontDescent(GetDefaultFontIndex(), GetFontSize()); } -FX_FLOAT CPDF_VariableText::GetFontAscent(int32_t nFontIndex, - FX_FLOAT fFontSize) { - return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * kFontScale; +float CPDF_VariableText::GetFontAscent(int32_t nFontIndex, float fFontSize) { + return (float)GetTypeAscent(nFontIndex) * fFontSize * kFontScale; } -FX_FLOAT CPDF_VariableText::GetFontDescent(int32_t nFontIndex, - FX_FLOAT fFontSize) { - return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * kFontScale; +float CPDF_VariableText::GetFontDescent(int32_t nFontIndex, float fFontSize) { + return (float)GetTypeDescent(nFontIndex) * fFontSize * kFontScale; } -FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo, - FX_FLOAT fFontSize) { +float CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo, + float fFontSize) { return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize); } -FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo, - FX_FLOAT fFontSize) { +float CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo, + float fFontSize) { return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize); } -FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo) { - return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo)); +float CPDF_VariableText::GetWordAscent(const CPVT_WordInfo& WordInfo) { + return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize()); } -FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo) { - return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo)); +float CPDF_VariableText::GetWordDescent(const CPVT_WordInfo& WordInfo) { + return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize()); } -FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo& SecInfo) { +float CPDF_VariableText::GetLineLeading() { return m_fLineLeading; } -FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo& SecInfo) { +float CPDF_VariableText::GetLineIndent() { return 0.0f; } -int32_t CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo) { +int32_t CPDF_VariableText::GetAlignment() { return m_nAlignment; } -FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo& WordInfo) { - return m_fCharSpace; -} - -int32_t CPDF_VariableText::GetHorzScale(const CPVT_WordInfo& WordInfo) { - return m_nHorzScale; -} - void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace& place) { CPVT_WordPlace wordplace = AdjustLineHeader(place, true); - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - for (int32_t w = pSection->m_WordArray.GetSize() - 1; - w > wordplace.nWordIndex; w--) { - delete pSection->m_WordArray.GetAt(w); - pSection->m_WordArray.RemoveAt(w); - } - } + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + if (!pdfium::IndexInBounds(pSection->m_WordArray, wordplace.nWordIndex + 1)) + return; + + pSection->m_WordArray.erase( + pSection->m_WordArray.begin() + wordplace.nWordIndex + 1, + pSection->m_WordArray.end()); } CPVT_WordPlace CPDF_VariableText::AdjustLineHeader(const CPVT_WordPlace& place, @@ -875,16 +733,17 @@ CPVT_WordPlace CPDF_VariableText::AdjustLineHeader(const CPVT_WordPlace& place, } bool CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace& place) { - if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) + if (place.nSecIndex == 0 && m_SectionArray.size() == 1) return false; - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - if (pSection->m_WordArray.GetSize() == 0) { - delete pSection; - m_SectionArray.RemoveAt(place.nSecIndex); - return true; - } - } - return false; + + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return false; + + if (!m_SectionArray[place.nSecIndex]->m_WordArray.empty()) + return false; + + m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex); + return true; } void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange& PlaceRange) { @@ -898,19 +757,18 @@ void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange& PlaceRange) { void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace& place) { CPVT_WordPlace oldplace = AdjustLineHeader(place, true); - if (CSection* pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) { - if (CSection* pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) { - for (int32_t w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; - w++) { - if (CPVT_WordInfo* pWord = pNextSection->m_WordArray.GetAt(w)) { - oldplace.nWordIndex++; - pSection->AddWord(oldplace, *pWord); - } - } + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex + 1)) + return; + + CSection* pNextSection = m_SectionArray[place.nSecIndex + 1].get(); + if (pdfium::IndexInBounds(m_SectionArray, oldplace.nSecIndex)) { + CSection* pSection = m_SectionArray[oldplace.nSecIndex].get(); + for (auto& pWord : pNextSection->m_WordArray) { + oldplace.nWordIndex++; + pSection->AddWord(oldplace, *pWord); } - delete pNextSection; - m_SectionArray.RemoveAt(place.nSecIndex + 1); } + m_SectionArray.erase(m_SectionArray.begin() + place.nSecIndex + 1); } void CPDF_VariableText::ClearWords(const CPVT_WordRange& PlaceRange) { @@ -919,40 +777,44 @@ void CPDF_VariableText::ClearWords(const CPVT_WordRange& PlaceRange) { NewRange.EndPos = AdjustLineHeader(PlaceRange.EndPos, true); for (int32_t s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) { - if (CSection* pSection = m_SectionArray.GetAt(s)) - pSection->ClearWords(NewRange); + if (pdfium::IndexInBounds(m_SectionArray, s)) + m_SectionArray[s]->ClearWords(NewRange); } } CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace& place) { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - CPVT_WordPlace leftplace = GetPrevWordPlace(place); - if (leftplace != place) { - if (leftplace.nSecIndex != place.nSecIndex) { - if (pSection->m_WordArray.GetSize() == 0) - ClearEmptySection(place); - else - LinkLatterSection(leftplace); - } else { - pSection->ClearWord(place); - } - } - return leftplace; + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return place; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + CPVT_WordPlace leftplace = GetPrevWordPlace(place); + if (leftplace == place) + return place; + + if (leftplace.nSecIndex != place.nSecIndex) { + if (pSection->m_WordArray.empty()) + ClearEmptySection(place); + else + LinkLatterSection(leftplace); + } else { + pSection->ClearWord(place); } - return place; + return leftplace; } CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace& place) { - if (CSection* pSection = m_SectionArray.GetAt(place.nSecIndex)) { - CPVT_WordPlace rightplace = - AdjustLineHeader(GetNextWordPlace(place), false); - if (rightplace != place) { - if (rightplace.nSecIndex != place.nSecIndex) - LinkLatterSection(place); - else - pSection->ClearWord(rightplace); - } - } + if (!pdfium::IndexInBounds(m_SectionArray, place.nSecIndex)) + return place; + + CSection* pSection = m_SectionArray[place.nSecIndex].get(); + CPVT_WordPlace rightplace = AdjustLineHeader(GetNextWordPlace(place), false); + if (rightplace == place) + return place; + + if (rightplace.nSecIndex != place.nSecIndex) + LinkLatterSection(place); + else + pSection->ClearWord(rightplace); return place; } @@ -979,7 +841,7 @@ CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange& PlaceRange) { return rcRet; } -FX_FLOAT CPDF_VariableText::GetAutoFontSize() { +float CPDF_VariableText::GetAutoFontSize() { int32_t nTotal = sizeof(gFontSizeSteps) / sizeof(uint8_t); if (IsMultiLine()) nTotal /= 4; @@ -992,30 +854,24 @@ FX_FLOAT CPDF_VariableText::GetAutoFontSize() { int32_t nRight = nTotal - 1; int32_t nMid = nTotal / 2; while (nLeft <= nRight) { - if (IsBigger(gFontSizeSteps[nMid])) { + if (IsBigger(gFontSizeSteps[nMid])) nRight = nMid - 1; - nMid = (nLeft + nRight) / 2; - continue; - } else { + else nLeft = nMid + 1; - nMid = (nLeft + nRight) / 2; - continue; - } + nMid = (nLeft + nRight) / 2; } - return (FX_FLOAT)gFontSizeSteps[nMid]; + return (float)gFontSizeSteps[nMid]; } -bool CPDF_VariableText::IsBigger(FX_FLOAT fFontSize) const { +bool CPDF_VariableText::IsBigger(float fFontSize) const { CFX_SizeF szTotal; - for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) { - if (CSection* pSection = m_SectionArray.GetAt(s)) { - CFX_SizeF size = pSection->GetSectionSize(fFontSize); - szTotal.width = std::max(size.width, szTotal.width); - szTotal.height += size.height; - if (IsFloatBigger(szTotal.width, GetPlateWidth()) || - IsFloatBigger(szTotal.height, GetPlateHeight())) { - return true; - } + for (const auto& pSection : m_SectionArray) { + CFX_SizeF size = pSection->GetSectionSize(fFontSize); + szTotal.width = std::max(size.width, szTotal.width); + szTotal.height += size.height; + if (IsFloatBigger(szTotal.width, GetPlateWidth()) || + IsFloatBigger(szTotal.height, GetPlateHeight())) { + return true; } } return false; @@ -1024,40 +880,39 @@ bool CPDF_VariableText::IsBigger(FX_FLOAT fFontSize) const { CPVT_FloatRect CPDF_VariableText::RearrangeSections( const CPVT_WordRange& PlaceRange) { CPVT_WordPlace place; - FX_FLOAT fPosY = 0; - FX_FLOAT fOldHeight; + float fPosY = 0; + float fOldHeight; int32_t nSSecIndex = PlaceRange.BeginPos.nSecIndex; int32_t nESecIndex = PlaceRange.EndPos.nSecIndex; CPVT_FloatRect rcRet; - for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) { + for (int32_t s = 0, sz = pdfium::CollectionSize(m_SectionArray); + s < sz; s++) { place.nSecIndex = s; - if (CSection* pSection = m_SectionArray.GetAt(s)) { - pSection->SecPlace = place; - CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection; - if (s >= nSSecIndex) { - if (s <= nESecIndex) { - rcSec = pSection->Rearrange(); - rcSec.top += fPosY; - rcSec.bottom += fPosY; - } else { - fOldHeight = pSection->m_SecInfo.rcSection.bottom - - pSection->m_SecInfo.rcSection.top; - rcSec.top = fPosY; - rcSec.bottom = fPosY + fOldHeight; - } - pSection->m_SecInfo.rcSection = rcSec; - pSection->ResetLinePlace(); - } - if (s == 0) { - rcRet = rcSec; + CSection* pSection = m_SectionArray[s].get(); + pSection->SecPlace = place; + CPVT_FloatRect rcSec = pSection->m_Rect; + if (s >= nSSecIndex) { + if (s <= nESecIndex) { + rcSec = pSection->Rearrange(); + rcSec.top += fPosY; + rcSec.bottom += fPosY; } else { - rcRet.left = std::min(rcSec.left, rcRet.left); - rcRet.top = std::min(rcSec.top, rcRet.top); - rcRet.right = std::max(rcSec.right, rcRet.right); - rcRet.bottom = std::max(rcSec.bottom, rcRet.bottom); + fOldHeight = pSection->m_Rect.bottom - pSection->m_Rect.top; + rcSec.top = fPosY; + rcSec.bottom = fPosY + fOldHeight; } - fPosY += rcSec.Height(); + pSection->m_Rect = rcSec; + pSection->ResetLinePlace(); } + if (s == 0) { + rcRet = rcSec; + } else { + rcRet.left = std::min(rcSec.left, rcRet.left); + rcRet.top = std::min(rcSec.top, rcRet.top); + rcRet.right = std::max(rcSec.right, rcRet.right); + rcRet.bottom = std::max(rcSec.bottom, rcRet.bottom); + } + fPosY += rcSec.Height(); } return rcRet; } @@ -1105,10 +960,6 @@ void CPDF_VariableText::SetProvider(CPDF_VariableText::Provider* pProvider) { m_pVTProvider = pProvider; } -CFX_SizeF CPDF_VariableText::GetPlateSize() const { - return CFX_SizeF(GetPlateWidth(), GetPlateHeight()); -} - CFX_PointF CPDF_VariableText::GetBTPoint() const { return CFX_PointF(m_rcPlate.left, m_rcPlate.top); } diff --git a/core/fpdfdoc/cpdf_variabletext.h b/core/fpdfdoc/cpdf_variabletext.h index 8e7c0c964a682601fdd9b6c551b95a60a67d7d2f..a939dcb0e16129b69affdb91d6a38729381b89c8 100644 --- a/core/fpdfdoc/cpdf_variabletext.h +++ b/core/fpdfdoc/cpdf_variabletext.h @@ -8,8 +8,8 @@ #define CORE_FPDFDOC_CPDF_VARIABLETEXT_H_ #include +#include -#include "core/fpdfdoc/cpvt_arraytemplate.h" #include "core/fpdfdoc/cpvt_floatrect.h" #include "core/fpdfdoc/cpvt_line.h" #include "core/fpdfdoc/cpvt_lineinfo.h" @@ -18,23 +18,16 @@ #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_font.h" class CPVT_Word; class CSection; class IPVT_FontMap; -struct CPVT_SecProps; -struct CPVT_Section; -struct CPVT_SectionInfo; - struct CPVT_WordInfo; -struct CPVT_WordProps; #define VARIABLETEXT_HALF 0.5f class CPDF_VariableText { public: - enum class ScriptType { Normal, Super, Sub }; class Iterator { public: @@ -44,21 +37,15 @@ class CPDF_VariableText { bool NextWord(); bool PrevWord(); bool NextLine(); - bool PrevLine(); - bool NextSection(); - bool PrevSection(); - bool SetWord(const CPVT_Word& word); bool GetWord(CPVT_Word& word) const; bool GetLine(CPVT_Line& line) const; - bool GetSection(CPVT_Section& section) const; - bool SetSection(const CPVT_Section& section); void SetAt(int32_t nWordIndex); void SetAt(const CPVT_WordPlace& place); - const CPVT_WordPlace& GetAt() const { return m_CurPos; } + const CPVT_WordPlace& GetWordPlace() const { return m_CurPos; } private: CPVT_WordPlace m_CurPos; - CPDF_VariableText* const m_pVT; + UnownedPtr const m_pVT; }; class Provider { @@ -93,41 +80,38 @@ class CPDF_VariableText { void SetAlignment(int32_t nFormat) { m_nAlignment = nFormat; } void SetPasswordChar(uint16_t wSubWord) { m_wSubWord = wSubWord; } void SetLimitChar(int32_t nLimitChar) { m_nLimitChar = nLimitChar; } - void SetCharSpace(FX_FLOAT fCharSpace) { m_fCharSpace = fCharSpace; } + void SetCharSpace(float fCharSpace) { m_fCharSpace = fCharSpace; } void SetMultiLine(bool bMultiLine) { m_bMultiLine = bMultiLine; } void SetAutoReturn(bool bAuto) { m_bLimitWidth = bAuto; } - void SetFontSize(FX_FLOAT fFontSize) { m_fFontSize = fFontSize; } + void SetFontSize(float fFontSize) { m_fFontSize = fFontSize; } void SetCharArray(int32_t nCharArray) { m_nCharArray = nCharArray; } void SetAutoFontSize(bool bAuto) { m_bAutoFontSize = bAuto; } void Initialize(); - bool IsValid() const { return m_bInitial; } + bool IsValid() const { return m_bInitialized; } void RearrangeAll(); void RearrangePart(const CPVT_WordRange& PlaceRange); - void ResetAll(); - void SetText(const CFX_WideString& text); + void SetText(const WideString& text); CPVT_WordPlace InsertWord(const CPVT_WordPlace& place, uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps); - CPVT_WordPlace InsertSection(const CPVT_WordPlace& place, - const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps); - CPVT_WordPlace InsertText(const CPVT_WordPlace& place, const FX_WCHAR* text); + int32_t charset); + CPVT_WordPlace InsertSection(const CPVT_WordPlace& place); CPVT_WordPlace DeleteWords(const CPVT_WordRange& PlaceRange); CPVT_WordPlace DeleteWord(const CPVT_WordPlace& place); CPVT_WordPlace BackSpaceWord(const CPVT_WordPlace& place); int32_t GetTotalWords() const; - FX_FLOAT GetFontSize() const { return m_fFontSize; } + float GetFontSize() const { return m_fFontSize; } int32_t GetAlignment() const { return m_nAlignment; } uint16_t GetPasswordChar() const { return GetSubWord(); } int32_t GetCharArray() const { return m_nCharArray; } int32_t GetLimitChar() const { return m_nLimitChar; } bool IsMultiLine() const { return m_bMultiLine; } int32_t GetHorzScale() const { return m_nHorzScale; } - FX_FLOAT GetCharSpace() const { return m_fCharSpace; } + float GetCharSpace() const { return m_fCharSpace; } + bool IsAutoReturn() const { return m_bLimitWidth; } + CPVT_WordPlace GetBeginWordPlace() const; CPVT_WordPlace GetEndWordPlace() const; CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace& place) const; @@ -149,9 +133,8 @@ class CPDF_VariableText { uint16_t GetSubWord() const { return m_wSubWord; } - FX_FLOAT GetPlateWidth() const { return m_rcPlate.right - m_rcPlate.left; } - FX_FLOAT GetPlateHeight() const { return m_rcPlate.top - m_rcPlate.bottom; } - CFX_SizeF GetPlateSize() const; + float GetPlateWidth() const { return m_rcPlate.right - m_rcPlate.left; } + float GetPlateHeight() const { return m_rcPlate.top - m_rcPlate.bottom; } CFX_PointF GetBTPoint() const; CFX_PointF GetETPoint() const; @@ -160,19 +143,35 @@ class CPDF_VariableText { CFX_FloatRect InToOut(const CPVT_FloatRect& rect) const; CPVT_FloatRect OutToIn(const CFX_FloatRect& rect) const; - private: - friend class CTypeset; - friend class CSection; + float GetFontAscent(int32_t nFontIndex, float fFontSize); + float GetFontDescent(int32_t nFontIndex, float fFontSize); + int32_t GetDefaultFontIndex(); + float GetLineLeading(); + int32_t GetAlignment(); + float GetWordWidth(const CPVT_WordInfo& WordInfo); + float GetWordWidth(int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord, + float fCharSpace, + int32_t nHorzScale, + float fFontSize, + float fWordTail); + float GetWordAscent(const CPVT_WordInfo& WordInfo); + float GetWordDescent(const CPVT_WordInfo& WordInfo); + float GetWordAscent(const CPVT_WordInfo& WordInfo, float fFontSize); + float GetWordDescent(const CPVT_WordInfo& WordInfo, float fFontSize); + float GetLineAscent(); + float GetLineDescent(); + float GetLineIndent(); + private: int32_t GetCharWidth(int32_t nFontIndex, uint16_t Word, uint16_t SubWord); int32_t GetTypeAscent(int32_t nFontIndex); int32_t GetTypeDescent(int32_t nFontIndex); int32_t GetWordFontIndex(uint16_t word, int32_t charset, int32_t nFontIndex); - int32_t GetDefaultFontIndex(); bool IsLatinWord(uint16_t word); - CPVT_WordPlace AddSection(const CPVT_WordPlace& place, - const CPVT_SectionInfo& secinfo); + CPVT_WordPlace AddSection(const CPVT_WordPlace& place); CPVT_WordPlace AddLine(const CPVT_WordPlace& place, const CPVT_LineInfo& lineinfo); CPVT_WordPlace AddWord(const CPVT_WordPlace& place, @@ -180,30 +179,8 @@ class CPDF_VariableText { bool GetWordInfo(const CPVT_WordPlace& place, CPVT_WordInfo& wordinfo); bool SetWordInfo(const CPVT_WordPlace& place, const CPVT_WordInfo& wordinfo); bool GetLineInfo(const CPVT_WordPlace& place, CPVT_LineInfo& lineinfo); - bool GetSectionInfo(const CPVT_WordPlace& place, CPVT_SectionInfo& secinfo); - FX_FLOAT GetWordFontSize(const CPVT_WordInfo& WordInfo); - FX_FLOAT GetWordWidth(int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord, - FX_FLOAT fCharSpace, - int32_t nHorzScale, - FX_FLOAT fFontSize, - FX_FLOAT fWordTail); - FX_FLOAT GetWordWidth(const CPVT_WordInfo& WordInfo); - FX_FLOAT GetWordAscent(const CPVT_WordInfo& WordInfo, FX_FLOAT fFontSize); - FX_FLOAT GetWordDescent(const CPVT_WordInfo& WordInfo, FX_FLOAT fFontSize); - FX_FLOAT GetWordAscent(const CPVT_WordInfo& WordInfo); - FX_FLOAT GetWordDescent(const CPVT_WordInfo& WordInfo); - FX_FLOAT GetLineAscent(const CPVT_SectionInfo& SecInfo); - FX_FLOAT GetLineDescent(const CPVT_SectionInfo& SecInfo); - FX_FLOAT GetFontAscent(int32_t nFontIndex, FX_FLOAT fFontSize); - FX_FLOAT GetFontDescent(int32_t nFontIndex, FX_FLOAT fFontSize); + float GetWordFontSize(); int32_t GetWordFontIndex(const CPVT_WordInfo& WordInfo); - FX_FLOAT GetCharSpace(const CPVT_WordInfo& WordInfo); - int32_t GetHorzScale(const CPVT_WordInfo& WordInfo); - FX_FLOAT GetLineLeading(const CPVT_SectionInfo& SecInfo); - FX_FLOAT GetLineIndent(const CPVT_SectionInfo& SecInfo); - int32_t GetAlignment(const CPVT_SectionInfo& SecInfo); void ClearSectionRightWords(const CPVT_WordPlace& place); @@ -215,25 +192,23 @@ class CPDF_VariableText { CPVT_WordPlace ClearRightWord(const CPVT_WordPlace& place); CPVT_FloatRect Rearrange(const CPVT_WordRange& PlaceRange); - FX_FLOAT GetAutoFontSize(); - bool IsBigger(FX_FLOAT fFontSize) const; + float GetAutoFontSize(); + bool IsBigger(float fFontSize) const; CPVT_FloatRect RearrangeSections(const CPVT_WordRange& PlaceRange); - void ResetSectionArray(); - - CPVT_ArrayTemplate m_SectionArray; + std::vector> m_SectionArray; int32_t m_nLimitChar; int32_t m_nCharArray; bool m_bMultiLine; bool m_bLimitWidth; bool m_bAutoFontSize; int32_t m_nAlignment; - FX_FLOAT m_fLineLeading; - FX_FLOAT m_fCharSpace; + float m_fLineLeading; + float m_fCharSpace; int32_t m_nHorzScale; uint16_t m_wSubWord; - FX_FLOAT m_fFontSize; - bool m_bInitial; + float m_fFontSize; + bool m_bInitialized; CPDF_VariableText::Provider* m_pVTProvider; std::unique_ptr m_pVTIterator; CFX_FloatRect m_rcPlate; diff --git a/core/fpdfdoc/cpdf_viewerpreferences.cpp b/core/fpdfdoc/cpdf_viewerpreferences.cpp index f1fc4b0347d3da0d069a0d2de8451b793bf9aca9..e7fb1416a8b9cb80fb5fbe8d5551a8157aa18a41 100644 --- a/core/fpdfdoc/cpdf_viewerpreferences.cpp +++ b/core/fpdfdoc/cpdf_viewerpreferences.cpp @@ -34,13 +34,13 @@ CPDF_Array* CPDF_ViewerPreferences::PrintPageRange() const { return pDict ? pDict->GetArrayFor("PrintPageRange") : nullptr; } -CFX_ByteString CPDF_ViewerPreferences::Duplex() const { +ByteString CPDF_ViewerPreferences::Duplex() const { CPDF_Dictionary* pDict = GetViewerPreferences(); - return pDict ? pDict->GetStringFor("Duplex") : CFX_ByteString("None"); + return pDict ? pDict->GetStringFor("Duplex") : ByteString("None"); } -bool CPDF_ViewerPreferences::GenericName(const CFX_ByteString& bsKey, - CFX_ByteString* bsVal) const { +bool CPDF_ViewerPreferences::GenericName(const ByteString& bsKey, + ByteString* bsVal) const { ASSERT(bsVal); CPDF_Dictionary* pDict = GetViewerPreferences(); if (!pDict) @@ -55,6 +55,6 @@ bool CPDF_ViewerPreferences::GenericName(const CFX_ByteString& bsKey, } CPDF_Dictionary* CPDF_ViewerPreferences::GetViewerPreferences() const { - CPDF_Dictionary* pDict = m_pDoc->GetRoot(); + const CPDF_Dictionary* pDict = m_pDoc->GetRoot(); return pDict ? pDict->GetDictFor("ViewerPreferences") : nullptr; } diff --git a/core/fpdfdoc/cpdf_viewerpreferences.h b/core/fpdfdoc/cpdf_viewerpreferences.h index c7e9112380d6b685fc6a454ac0d31ed6bcb0b893..a1884748e42e51e056c6a4e5a391688adcd25bfe 100644 --- a/core/fpdfdoc/cpdf_viewerpreferences.h +++ b/core/fpdfdoc/cpdf_viewerpreferences.h @@ -9,6 +9,7 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Array; class CPDF_Dictionary; @@ -23,17 +24,17 @@ class CPDF_ViewerPreferences { bool PrintScaling() const; int32_t NumCopies() const; CPDF_Array* PrintPageRange() const; - CFX_ByteString Duplex() const; + ByteString Duplex() const; // Gets the entry for |bsKey|. If the entry exists and it is of type name, // then this method writes the value into |bsVal| and returns true. Otherwise // returns false and |bsVal| is untouched. |bsVal| must not be NULL. - bool GenericName(const CFX_ByteString& bsKey, CFX_ByteString* bsVal) const; + bool GenericName(const ByteString& bsKey, ByteString* bsVal) const; private: CPDF_Dictionary* GetViewerPreferences() const; - CPDF_Document* const m_pDoc; + UnownedPtr const m_pDoc; }; #endif // CORE_FPDFDOC_CPDF_VIEWERPREFERENCES_H_ diff --git a/core/fpdfdoc/cpvt_arraytemplate.h b/core/fpdfdoc/cpvt_arraytemplate.h deleted file mode 100644 index 5274bd9ba44f3d4e1f5843b456e2c782eb554680..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_arraytemplate.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_ARRAYTEMPLATE_H_ -#define CORE_FPDFDOC_CPVT_ARRAYTEMPLATE_H_ - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_system.h" - -template -class CPVT_ArrayTemplate : public CFX_ArrayTemplate { - public: - bool IsEmpty() { return CFX_ArrayTemplate::GetSize() <= 0; } - - TYPE GetAt(int nIndex) const { - if (nIndex >= 0 && nIndex < CFX_ArrayTemplate::GetSize()) - return CFX_ArrayTemplate::GetAt(nIndex); - return nullptr; - } - - void RemoveAt(int nIndex) { - if (nIndex >= 0 && nIndex < CFX_ArrayTemplate::GetSize()) - CFX_ArrayTemplate::RemoveAt(nIndex); - } -}; - -#endif // CORE_FPDFDOC_CPVT_ARRAYTEMPLATE_H_ diff --git a/core/fpdfdoc/cpvt_color.cpp b/core/fpdfdoc/cpvt_color.cpp deleted file mode 100644 index e0e6a26db7ab4ad1d18bf82f100b93a6ce344f71..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_color.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 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 "core/fpdfdoc/cpvt_color.h" - -#include "core/fpdfapi/parser/cpdf_simple_parser.h" - -// Static. -CPVT_Color CPVT_Color::ParseColor(const CFX_ByteString& str) { - CPDF_SimpleParser syntax(str.AsStringC()); - if (syntax.FindTagParamFromStart("g", 1)) - return CPVT_Color(CPVT_Color::kGray, FX_atof(syntax.GetWord())); - - if (syntax.FindTagParamFromStart("rg", 3)) { - FX_FLOAT f1 = FX_atof(syntax.GetWord()); - FX_FLOAT f2 = FX_atof(syntax.GetWord()); - FX_FLOAT f3 = FX_atof(syntax.GetWord()); - return CPVT_Color(CPVT_Color::kRGB, f1, f2, f3); - } - if (syntax.FindTagParamFromStart("k", 4)) { - FX_FLOAT f1 = FX_atof(syntax.GetWord()); - FX_FLOAT f2 = FX_atof(syntax.GetWord()); - FX_FLOAT f3 = FX_atof(syntax.GetWord()); - FX_FLOAT f4 = FX_atof(syntax.GetWord()); - return CPVT_Color(CPVT_Color::kCMYK, f1, f2, f3, f4); - } - return CPVT_Color(CPVT_Color::kTransparent); -} - -// Static. -CPVT_Color CPVT_Color::ParseColor(const CPDF_Array& array) { - CPVT_Color rt; - switch (array.GetCount()) { - case 1: - rt = CPVT_Color(CPVT_Color::kGray, array.GetFloatAt(0)); - break; - case 3: - rt = CPVT_Color(CPVT_Color::kRGB, array.GetFloatAt(0), - array.GetFloatAt(1), array.GetFloatAt(2)); - break; - case 4: - rt = CPVT_Color(CPVT_Color::kCMYK, array.GetFloatAt(0), - array.GetFloatAt(1), array.GetFloatAt(2), - array.GetFloatAt(3)); - break; - } - return rt; -} diff --git a/core/fpdfdoc/cpvt_color.h b/core/fpdfdoc/cpvt_color.h deleted file mode 100644 index 4d4942dbf989ec3508429a4097f7242b393caf24..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_color.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_COLOR_H_ -#define CORE_FPDFDOC_CPVT_COLOR_H_ - -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" - -struct CPVT_Color { - enum Type { kTransparent = 0, kGray, kRGB, kCMYK }; - - CPVT_Color(Type type = kTransparent, - FX_FLOAT color1 = 0.0f, - FX_FLOAT color2 = 0.0f, - FX_FLOAT color3 = 0.0f, - FX_FLOAT color4 = 0.0f) - : nColorType(type), - fColor1(color1), - fColor2(color2), - fColor3(color3), - fColor4(color4) {} - - Type nColorType; - FX_FLOAT fColor1; - FX_FLOAT fColor2; - FX_FLOAT fColor3; - FX_FLOAT fColor4; - - static CPVT_Color ParseColor(const CFX_ByteString& str); - static CPVT_Color ParseColor(const CPDF_Array& array); -}; - -#endif // CORE_FPDFDOC_CPVT_COLOR_H_ diff --git a/core/fpdfdoc/cpvt_dash.h b/core/fpdfdoc/cpvt_dash.h deleted file mode 100644 index f80d104c96e7cf0f7e5b4c211f84ba3be535aa2e..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_dash.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_DASH_H_ -#define CORE_FPDFDOC_CPVT_DASH_H_ - -#include - -struct CPVT_Dash { - CPVT_Dash(int32_t dash, int32_t gap, int32_t phase) - : nDash(dash), nGap(gap), nPhase(phase) {} - - int32_t nDash; - int32_t nGap; - int32_t nPhase; -}; - -#endif // CORE_FPDFDOC_CPVT_DASH_H_ diff --git a/core/fpdfdoc/cpvt_floatrect.h b/core/fpdfdoc/cpvt_floatrect.h index 6fc4b8ebce5625ffcf5a42f189783b50bbc47d39..c5eb2202bb70af13a4990a5e83ef697d61455e75 100644 --- a/core/fpdfdoc/cpvt_floatrect.h +++ b/core/fpdfdoc/cpvt_floatrect.h @@ -13,10 +13,10 @@ class CPVT_FloatRect : public CFX_FloatRect { public: CPVT_FloatRect() { left = top = right = bottom = 0.0f; } - CPVT_FloatRect(FX_FLOAT other_left, - FX_FLOAT other_top, - FX_FLOAT other_right, - FX_FLOAT other_bottom) { + CPVT_FloatRect(float other_left, + float other_top, + float other_right, + float other_bottom) { left = other_left; top = other_top; right = other_right; @@ -30,9 +30,7 @@ class CPVT_FloatRect : public CFX_FloatRect { bottom = rect.bottom; } - void Default() { left = top = right = bottom = 0.0f; } - - FX_FLOAT Height() const { + float Height() const { if (top > bottom) return top - bottom; return bottom - top; diff --git a/core/fpdfdoc/cpvt_fontmap.cpp b/core/fpdfdoc/cpvt_fontmap.cpp index 283f60011b2d7bd30dbe14e726ce0d79816c1e5b..aaf8661f1efb97a6c3f9957a3fa86cc25f39a903 100644 --- a/core/fpdfdoc/cpvt_fontmap.cpp +++ b/core/fpdfdoc/cpvt_fontmap.cpp @@ -11,84 +11,82 @@ #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfdoc/cpdf_interform.h" +#include "core/fxcrt/fx_codepage.h" +#include "third_party/base/logging.h" CPVT_FontMap::CPVT_FontMap(CPDF_Document* pDoc, CPDF_Dictionary* pResDict, CPDF_Font* pDefFont, - const CFX_ByteString& sDefFontAlias) + const ByteString& sDefFontAlias) : m_pDocument(pDoc), m_pResDict(pResDict), m_pDefFont(pDefFont), - m_sDefFontAlias(sDefFontAlias), - m_pSysFont(nullptr), - m_sSysFontAlias() {} + m_sDefFontAlias(sDefFontAlias) {} CPVT_FontMap::~CPVT_FontMap() {} -void CPVT_FontMap::GetAnnotSysPDFFont(CPDF_Document* pDoc, - const CPDF_Dictionary* pResDict, - CPDF_Font*& pSysFont, - CFX_ByteString& sSysFontAlias) { +CPDF_Font* CPVT_FontMap::GetAnnotSysPDFFont(CPDF_Document* pDoc, + const CPDF_Dictionary* pResDict, + ByteString* sSysFontAlias) { if (!pDoc || !pResDict) - return; + return nullptr; - CFX_ByteString sFontAlias; CPDF_Dictionary* pFormDict = pDoc->GetRoot()->GetDictFor("AcroForm"); CPDF_Font* pPDFFont = AddNativeInterFormFont(pFormDict, pDoc, sSysFontAlias); if (!pPDFFont) - return; + return nullptr; CPDF_Dictionary* pFontList = pResDict->GetDictFor("Font"); - if (pFontList && !pFontList->KeyExist(sSysFontAlias)) { - pFontList->SetNewFor(sSysFontAlias, pDoc, + if (pFontList && !pFontList->KeyExist(*sSysFontAlias)) { + pFontList->SetNewFor(*sSysFontAlias, pDoc, pPDFFont->GetFontDict()->GetObjNum()); } - pSysFont = pPDFFont; + return pPDFFont; } CPDF_Font* CPVT_FontMap::GetPDFFont(int32_t nFontIndex) { switch (nFontIndex) { case 0: - return m_pDefFont; + return m_pDefFont.Get(); case 1: if (!m_pSysFont) { - GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, - m_sSysFontAlias); + m_pSysFont = GetAnnotSysPDFFont(m_pDocument.Get(), m_pResDict.Get(), + &m_sSysFontAlias); } - return m_pSysFont; + return m_pSysFont.Get(); default: return nullptr; } } -CFX_ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) { +ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) { switch (nFontIndex) { case 0: return m_sDefFontAlias; case 1: if (!m_pSysFont) { - GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, - m_sSysFontAlias); + m_pSysFont = GetAnnotSysPDFFont(m_pDocument.Get(), m_pResDict.Get(), + &m_sSysFontAlias); } return m_sSysFontAlias; default: - return ""; + return ByteString(); } } int32_t CPVT_FontMap::GetWordFontIndex(uint16_t word, int32_t charset, int32_t nFontIndex) { - ASSERT(false); + NOTREACHED(); return 0; } int32_t CPVT_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) { - ASSERT(false); + NOTREACHED(); return 0; } int32_t CPVT_FontMap::CharSetFromUnicode(uint16_t word, int32_t nOldCharset) { - ASSERT(false); - return FXFONT_ANSI_CHARSET; + NOTREACHED(); + return FX_CHARSET_ANSI; } diff --git a/core/fpdfdoc/cpvt_fontmap.h b/core/fpdfdoc/cpvt_fontmap.h index 98e390f40975f117cded55248f45ef2657de1c98..a0b94cf25acf357984bbd8e1427a14754fb99508 100644 --- a/core/fpdfdoc/cpvt_fontmap.h +++ b/core/fpdfdoc/cpvt_fontmap.h @@ -11,6 +11,7 @@ #include "core/fpdfdoc/ipvt_fontmap.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Document; class CPDF_Dictionary; @@ -21,30 +22,29 @@ class CPVT_FontMap : public IPVT_FontMap { CPVT_FontMap(CPDF_Document* pDoc, CPDF_Dictionary* pResDict, CPDF_Font* pDefFont, - const CFX_ByteString& sDefFontAlias); + const ByteString& sDefFontAlias); ~CPVT_FontMap() override; // IPVT_FontMap: CPDF_Font* GetPDFFont(int32_t nFontIndex) override; - CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override; + ByteString GetPDFFontAlias(int32_t nFontIndex) override; int32_t GetWordFontIndex(uint16_t word, int32_t charset, int32_t nFontIndex) override; int32_t CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) override; int32_t CharSetFromUnicode(uint16_t word, int32_t nOldCharset) override; - static void GetAnnotSysPDFFont(CPDF_Document* pDoc, - const CPDF_Dictionary* pResDict, - CPDF_Font*& pSysFont, - CFX_ByteString& sSysFontAlias); + static CPDF_Font* GetAnnotSysPDFFont(CPDF_Document* pDoc, + const CPDF_Dictionary* pResDict, + ByteString* sSysFontAlias); private: - CPDF_Document* const m_pDocument; - const CPDF_Dictionary* const m_pResDict; - CPDF_Font* const m_pDefFont; - const CFX_ByteString m_sDefFontAlias; - CPDF_Font* m_pSysFont; - CFX_ByteString m_sSysFontAlias; + UnownedPtr const m_pDocument; + UnownedPtr const m_pResDict; + UnownedPtr const m_pDefFont; + UnownedPtr m_pSysFont; + const ByteString m_sDefFontAlias; + ByteString m_sSysFontAlias; }; #endif // CORE_FPDFDOC_CPVT_FONTMAP_H_ diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp index 15515151bc1ceef1bd600ed7fcd2b31e649ef376..1b94f7eca44a7a42053c5822d75153e4cf1bfaad 100644 --- a/core/fpdfdoc/cpvt_generateap.cpp +++ b/core/fpdfdoc/cpvt_generateap.cpp @@ -8,9 +8,11 @@ #include #include +#include #include #include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_boolean.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" @@ -23,451 +25,295 @@ #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfdoc/cpdf_annot.h" #include "core/fpdfdoc/cpdf_formfield.h" -#include "core/fpdfdoc/cpvt_color.h" #include "core/fpdfdoc/cpvt_fontmap.h" #include "core/fpdfdoc/cpvt_word.h" #include "third_party/base/ptr_util.h" +struct CPVT_Dash { + CPVT_Dash(int32_t dash, int32_t gap, int32_t phase) + : nDash(dash), nGap(gap), nPhase(phase) {} + + int32_t nDash; + int32_t nGap; + int32_t nPhase; +}; + namespace { -bool GenerateWidgetAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict, - const int32_t& nWidgetType) { - CPDF_Dictionary* pFormDict = nullptr; - if (CPDF_Dictionary* pRootDict = pDoc->GetRoot()) - pFormDict = pRootDict->GetDictFor("AcroForm"); - if (!pFormDict) - return false; +ByteString GetPDFWordString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord) { + if (SubWord > 0) + return ByteString::Format("%c", SubWord); - CFX_ByteString DA; - if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) - DA = pDAObj->GetString(); - if (DA.IsEmpty()) - DA = pFormDict->GetStringFor("DA"); - if (DA.IsEmpty()) - return false; + if (!pFontMap) + return ""; - CPDF_SimpleParser syntax(DA.AsStringC()); - syntax.FindTagParamFromStart("Tf", 2); - CFX_ByteString sFontName(syntax.GetWord()); - sFontName = PDF_NameDecode(sFontName); - if (sFontName.IsEmpty()) - return false; + CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex); + if (!pPDFFont) + return ""; - FX_FLOAT fFontSize = FX_atof(syntax.GetWord()); - CPVT_Color crText = CPVT_Color::ParseColor(DA); - CPDF_Dictionary* pDRDict = pFormDict->GetDictFor("DR"); - if (!pDRDict) - return false; + if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 || + pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) { + return ByteString::Format("%c", Word); + } - CPDF_Dictionary* pDRFontDict = pDRDict->GetDictFor("Font"); - if (!pDRFontDict) - return false; + ByteString sWord; + uint32_t dwCharCode = pPDFFont->CharCodeFromUnicode(Word); + if (dwCharCode != CPDF_Font::kInvalidCharCode) + pPDFFont->AppendChar(&sWord, dwCharCode); + return sWord; +} - CPDF_Dictionary* pFontDict = pDRFontDict->GetDictFor(sFontName.Mid(1)); - if (!pFontDict) { - pFontDict = pDoc->NewIndirect(); - pFontDict->SetNewFor("Type", "Font"); - pFontDict->SetNewFor("Subtype", "Type1"); - pFontDict->SetNewFor("BaseFont", "Helvetica"); - pFontDict->SetNewFor("Encoding", "WinAnsiEncoding"); - pDRFontDict->SetNewFor(sFontName.Mid(1), pDoc, - pFontDict->GetObjNum()); +ByteString GetWordRenderString(const ByteString& strWords) { + if (strWords.GetLength() > 0) + return PDF_EncodeString(strWords, false) + " Tj\n"; + return ""; +} + +ByteString GetFontSetString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + float fFontSize) { + std::ostringstream sRet; + if (pFontMap) { + ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); + if (sFontAlias.GetLength() > 0 && fFontSize > 0) + sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; } - CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict); - if (!pDefFont) - return false; + return ByteString(sRet); +} - CFX_FloatRect rcAnnot = pAnnotDict->GetRectFor("Rect"); - int32_t nRotate = 0; - if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictFor("MK")) - nRotate = pMKDict->GetIntegerFor("R"); +ByteString GenerateEditAP(IPVT_FontMap* pFontMap, + CPDF_VariableText::Iterator* pIterator, + const CFX_PointF& ptOffset, + bool bContinuous, + uint16_t SubWord) { + std::ostringstream sEditStream; + std::ostringstream sLineStream; + std::ostringstream sWords; + CFX_PointF ptOld; + CFX_PointF ptNew; + int32_t nCurFontIndex = -1; + CPVT_WordPlace oldplace; - CFX_FloatRect rcBBox; - CFX_Matrix matrix; - switch (nRotate % 360) { - case 0: - rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, - rcAnnot.top - rcAnnot.bottom); + pIterator->SetAt(0); + while (pIterator->NextWord()) { + CPVT_WordPlace place = pIterator->GetWordPlace(); + if (bContinuous) { + if (place.LineCmp(oldplace) != 0) { + if (sWords.tellp() > 0) { + sLineStream << GetWordRenderString(ByteString(sWords)); + sEditStream << sLineStream.str(); + sLineStream.str(""); + sWords.str(""); + } + CPVT_Word word; + if (pIterator->GetWord(word)) { + ptNew = CFX_PointF(word.ptWord.x + ptOffset.x, + word.ptWord.y + ptOffset.y); + } else { + CPVT_Line line; + pIterator->GetLine(line); + ptNew = CFX_PointF(line.ptLine.x + ptOffset.x, + line.ptLine.y + ptOffset.y); + } + if (ptNew != ptOld) { + sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y + << " Td\n"; + ptOld = ptNew; + } + } + CPVT_Word word; + if (pIterator->GetWord(word)) { + if (word.nFontIndex != nCurFontIndex) { + if (sWords.tellp() > 0) { + sLineStream << GetWordRenderString(ByteString(sWords)); + sWords.str(""); + } + sLineStream << GetFontSetString(pFontMap, word.nFontIndex, + word.fFontSize); + nCurFontIndex = word.nFontIndex; + } + sWords << GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord); + } + oldplace = place; + } else { + CPVT_Word word; + if (pIterator->GetWord(word)) { + ptNew = + CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y); + if (ptNew != ptOld) { + sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y + << " Td\n"; + ptOld = ptNew; + } + if (word.nFontIndex != nCurFontIndex) { + sEditStream << GetFontSetString(pFontMap, word.nFontIndex, + word.fFontSize); + nCurFontIndex = word.nFontIndex; + } + sEditStream << GetWordRenderString( + GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord)); + } + } + } + if (sWords.tellp() > 0) { + sLineStream << GetWordRenderString(ByteString(sWords)); + sEditStream << sLineStream.str(); + sWords.str(""); + } + return ByteString(sEditStream); +} + +ByteString GenerateColorAP(const CFX_Color& color, PaintOperation nOperation) { + std::ostringstream sColorStream; + switch (color.nColorType) { + case CFX_Color::kRGB: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " + << (nOperation == PaintOperation::STROKE ? "RG" : "rg") + << "\n"; break; - case 90: - matrix = CFX_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0); - rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, - rcAnnot.right - rcAnnot.left); + case CFX_Color::kGray: + sColorStream << color.fColor1 << " " + << (nOperation == PaintOperation::STROKE ? "G" : "g") + << "\n"; break; - case 180: - matrix = CFX_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, - rcAnnot.top - rcAnnot.bottom); - rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, - rcAnnot.top - rcAnnot.bottom); + case CFX_Color::kCMYK: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " << color.fColor4 << " " + << (nOperation == PaintOperation::STROKE ? "K" : "k") + << "\n"; break; - case 270: - matrix = CFX_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom); - rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, - rcAnnot.right - rcAnnot.left); + case CFX_Color::kTransparent: break; } + return ByteString(sColorStream); +} - BorderStyle nBorderStyle = BorderStyle::SOLID; - FX_FLOAT fBorderWidth = 1; - CPVT_Dash dsBorder(3, 0, 0); - CPVT_Color crLeftTop, crRightBottom; - if (CPDF_Dictionary* pBSDict = pAnnotDict->GetDictFor("BS")) { - if (pBSDict->KeyExist("W")) - fBorderWidth = pBSDict->GetNumberFor("W"); - - if (CPDF_Array* pArray = pBSDict->GetArrayFor("D")) { - dsBorder = CPVT_Dash(pArray->GetIntegerAt(0), pArray->GetIntegerAt(1), - pArray->GetIntegerAt(2)); - } - switch (pBSDict->GetStringFor("S").GetAt(0)) { - case 'S': - nBorderStyle = BorderStyle::SOLID; - break; - case 'D': - nBorderStyle = BorderStyle::DASH; +ByteString GenerateBorderAP(const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + const CPVT_Dash& dash) { + std::ostringstream sAppStream; + ByteString sColor; + float fLeft = rect.left; + float fRight = rect.right; + float fTop = rect.top; + float fBottom = rect.bottom; + if (fWidth > 0.0f) { + float fHalfWidth = fWidth / 2.0f; + switch (nStyle) { + default: + case BorderStyle::SOLID: + sColor = GenerateColorAP(color, PaintOperation::FILL); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " + << fTop - fBottom << " re\n"; + sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " + << fRight - fLeft - fWidth * 2 << " " + << fTop - fBottom - fWidth * 2 << " re\n"; + sAppStream << "f*\n"; + } break; - case 'B': - nBorderStyle = BorderStyle::BEVELED; - fBorderWidth *= 2; - crLeftTop = CPVT_Color(CPVT_Color::kGray, 1); - crRightBottom = CPVT_Color(CPVT_Color::kGray, 0.5); + case BorderStyle::DASH: + sColor = GenerateColorAP(color, PaintOperation::STROKE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fWidth << " w" + << " [" << dash.nDash << " " << dash.nGap << "] " + << dash.nPhase << " d\n"; + sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 + << " m\n"; + sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 + << " l\n"; + sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 + << " l\n"; + sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 + << " l\n"; + sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 + << " l S\n"; + } break; - case 'I': - nBorderStyle = BorderStyle::INSET; - fBorderWidth *= 2; - crLeftTop = CPVT_Color(CPVT_Color::kGray, 0.5); - crRightBottom = CPVT_Color(CPVT_Color::kGray, 0.75); + case BorderStyle::BEVELED: + case BorderStyle::INSET: + sColor = GenerateColorAP(crLeftTop, PaintOperation::FILL); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth + << " m\n"; + sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth + << " l\n"; + sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth + << " l\n"; + sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " l\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " l\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " l f\n"; + } + sColor = GenerateColorAP(crRightBottom, PaintOperation::FILL); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth + << " m\n"; + sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth + << " l\n"; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth + << " l\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " l\n"; + sAppStream << fRight - fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " l\n"; + sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " l f\n"; + } + sColor = GenerateColorAP(color, PaintOperation::FILL); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " + << fTop - fBottom << " re\n"; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " + << fRight - fLeft - fHalfWidth * 2 << " " + << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; + } break; - case 'U': - nBorderStyle = BorderStyle::UNDERLINE; + case BorderStyle::UNDERLINE: + sColor = GenerateColorAP(color, PaintOperation::STROKE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fWidth << " w\n"; + sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; + sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; + } break; } } - CPVT_Color crBorder, crBG; - if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictFor("MK")) { - if (CPDF_Array* pArray = pMKDict->GetArrayFor("BC")) - crBorder = CPVT_Color::ParseColor(*pArray); - if (CPDF_Array* pArray = pMKDict->GetArrayFor("BG")) - crBG = CPVT_Color::ParseColor(*pArray); - } - CFX_ByteTextBuf sAppStream; - CFX_ByteString sBG = - CPVT_GenerateAP::GenerateColorAP(crBG, PaintOperation::FILL); - if (sBG.GetLength() > 0) { - sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" - << "Q\n"; + return ByteString(sAppStream); +} + +ByteString GetColorStringWithDefault(CPDF_Array* pColor, + const CFX_Color& crDefaultColor, + PaintOperation nOperation) { + if (pColor) { + CFX_Color color = CFX_Color::ParseColor(*pColor); + return GenerateColorAP(color, nOperation); } - CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP( - rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - if (sBorderStream.GetLength() > 0) - sAppStream << "q\n" << sBorderStream << "Q\n"; - CFX_FloatRect rcBody = - CFX_FloatRect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth, - rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth); - rcBody.Normalize(); + return GenerateColorAP(crDefaultColor, nOperation); +} - CPDF_Dictionary* pAPDict = pAnnotDict->GetDictFor("AP"); - if (!pAPDict) - pAPDict = pAnnotDict->SetNewFor("AP"); - - CPDF_Stream* pNormalStream = pAPDict->GetStreamFor("N"); - if (!pNormalStream) { - pNormalStream = pDoc->NewIndirect(); - pAPDict->SetNewFor("N", pDoc, pNormalStream->GetObjNum()); - } - CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); - if (pStreamDict) { - pStreamDict->SetMatrixFor("Matrix", matrix); - pStreamDict->SetRectFor("BBox", rcBBox); - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); - if (pStreamResList) { - CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictFor("Font"); - if (!pStreamResFontList) - pStreamResFontList = pStreamResList->SetNewFor("Font"); - if (!pStreamResFontList->KeyExist(sFontName)) { - pStreamResFontList->SetNewFor(sFontName, pDoc, - pFontDict->GetObjNum()); - } - } else { - pStreamDict->SetFor("Resources", pFormDict->GetDictFor("DR")->Clone()); - pStreamResList = pStreamDict->GetDictFor("Resources"); - } - } - switch (nWidgetType) { - case 0: { - CFX_WideString swValue = - FPDF_GetFieldAttr(pAnnotDict, "V") - ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() - : CFX_WideString(); - int32_t nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q") - ? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() - : 0; - uint32_t dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff") - ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() - : 0; - uint32_t dwMaxLen = - FPDF_GetFieldAttr(pAnnotDict, "MaxLen") - ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() - : 0; - CPVT_FontMap map( - pDoc, pStreamDict ? pStreamDict->GetDictFor("Resources") : nullptr, - pDefFont, sFontName.Right(sFontName.GetLength() - 1)); - CPDF_VariableText::Provider prd(&map); - CPDF_VariableText vt; - vt.SetProvider(&prd); - vt.SetPlateRect(rcBody); - vt.SetAlignment(nAlign); - if (IsFloatZero(fFontSize)) - vt.SetAutoFontSize(true); - else - vt.SetFontSize(fFontSize); - - bool bMultiLine = (dwFlags >> 12) & 1; - if (bMultiLine) { - vt.SetMultiLine(true); - vt.SetAutoReturn(true); - } - uint16_t subWord = 0; - if ((dwFlags >> 13) & 1) { - subWord = '*'; - vt.SetPasswordChar(subWord); - } - bool bCharArray = (dwFlags >> 24) & 1; - if (bCharArray) - vt.SetCharArray(dwMaxLen); - else - vt.SetLimitChar(dwMaxLen); - - vt.Initialize(); - vt.SetText(swValue); - vt.RearrangeAll(); - CFX_FloatRect rcContent = vt.GetContentRect(); - CFX_PointF ptOffset; - if (!bMultiLine) { - ptOffset = - CFX_PointF(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f); - } - CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP( - &map, vt.GetIterator(), ptOffset, !bCharArray, subWord); - if (sBody.GetLength() > 0) { - sAppStream << "/Tx BMC\n" - << "q\n"; - if (rcContent.Width() > rcBody.Width() || - rcContent.Height() > rcBody.Height()) { - sAppStream << rcBody.left << " " << rcBody.bottom << " " - << rcBody.Width() << " " << rcBody.Height() - << " re\nW\nn\n"; - } - sAppStream << "BT\n" - << CPVT_GenerateAP::GenerateColorAP(crText, - PaintOperation::FILL) - << sBody << "ET\n" - << "Q\nEMC\n"; - } - } break; - case 1: { - CFX_WideString swValue = - FPDF_GetFieldAttr(pAnnotDict, "V") - ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() - : CFX_WideString(); - CPVT_FontMap map( - pDoc, pStreamDict ? pStreamDict->GetDictFor("Resources") : nullptr, - pDefFont, sFontName.Right(sFontName.GetLength() - 1)); - CPDF_VariableText::Provider prd(&map); - CPDF_VariableText vt; - vt.SetProvider(&prd); - CFX_FloatRect rcButton = rcBody; - rcButton.left = rcButton.right - 13; - rcButton.Normalize(); - CFX_FloatRect rcEdit = rcBody; - rcEdit.right = rcButton.left; - rcEdit.Normalize(); - vt.SetPlateRect(rcEdit); - if (IsFloatZero(fFontSize)) - vt.SetAutoFontSize(true); - else - vt.SetFontSize(fFontSize); - - vt.Initialize(); - vt.SetText(swValue); - vt.RearrangeAll(); - CFX_FloatRect rcContent = vt.GetContentRect(); - CFX_PointF ptOffset = - CFX_PointF(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f); - CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP( - &map, vt.GetIterator(), ptOffset, true, 0); - if (sEdit.GetLength() > 0) { - sAppStream << "/Tx BMC\n" - << "q\n"; - sAppStream << rcEdit.left << " " << rcEdit.bottom << " " - << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n"; - sAppStream << "BT\n" - << CPVT_GenerateAP::GenerateColorAP(crText, - PaintOperation::FILL) - << sEdit << "ET\n" - << "Q\nEMC\n"; - } - CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 220.0f / 255.0f, 220.0f / 255.0f, - 220.0f / 255.0f), - PaintOperation::FILL); - if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) { - sAppStream << "q\n" << sButton; - sAppStream << rcButton.left << " " << rcButton.bottom << " " - << rcButton.Width() << " " << rcButton.Height() << " re f\n"; - sAppStream << "Q\n"; - CFX_ByteString sButtonBorder = CPVT_GenerateAP::GenerateBorderAP( - rcButton, 2, CPVT_Color(CPVT_Color::kGray, 0), - CPVT_Color(CPVT_Color::kGray, 1), - CPVT_Color(CPVT_Color::kGray, 0.5), BorderStyle::BEVELED, - CPVT_Dash(3, 0, 0)); - if (sButtonBorder.GetLength() > 0) - sAppStream << "q\n" << sButtonBorder << "Q\n"; - - CFX_PointF ptCenter = CFX_PointF((rcButton.left + rcButton.right) / 2, - (rcButton.top + rcButton.bottom) / 2); - if (IsFloatBigger(rcButton.Width(), 6) && - IsFloatBigger(rcButton.Height(), 6)) { - sAppStream << "q\n" - << " 0 g\n"; - sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; - sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; - sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; - sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; - sAppStream << sButton << "Q\n"; - } - } - } break; - case 2: { - CPVT_FontMap map( - pDoc, pStreamDict ? pStreamDict->GetDictFor("Resources") : nullptr, - pDefFont, sFontName.Right(sFontName.GetLength() - 1)); - CPDF_VariableText::Provider prd(&map); - CPDF_Array* pOpts = ToArray(FPDF_GetFieldAttr(pAnnotDict, "Opt")); - CPDF_Array* pSels = ToArray(FPDF_GetFieldAttr(pAnnotDict, "I")); - CPDF_Object* pTi = FPDF_GetFieldAttr(pAnnotDict, "TI"); - int32_t nTop = pTi ? pTi->GetInteger() : 0; - CFX_ByteTextBuf sBody; - if (pOpts) { - FX_FLOAT fy = rcBody.top; - for (size_t i = nTop, sz = pOpts->GetCount(); i < sz; i++) { - if (IsFloatSmaller(fy, rcBody.bottom)) - break; - - if (CPDF_Object* pOpt = pOpts->GetDirectObjectAt(i)) { - CFX_WideString swItem; - if (pOpt->IsString()) - swItem = pOpt->GetUnicodeText(); - else if (CPDF_Array* pArray = pOpt->AsArray()) - swItem = pArray->GetDirectObjectAt(1)->GetUnicodeText(); - - bool bSelected = false; - if (pSels) { - for (size_t s = 0, ssz = pSels->GetCount(); s < ssz; s++) { - int value = pSels->GetIntegerAt(s); - if (value >= 0 && i == static_cast(value)) { - bSelected = true; - break; - } - } - } - CPDF_VariableText vt; - vt.SetProvider(&prd); - vt.SetPlateRect( - CFX_FloatRect(rcBody.left, 0.0f, rcBody.right, 0.0f)); - vt.SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); - - vt.Initialize(); - vt.SetText(swItem); - vt.RearrangeAll(); - FX_FLOAT fItemHeight = vt.GetContentRect().Height(); - if (bSelected) { - CFX_FloatRect rcItem = CFX_FloatRect( - rcBody.left, fy - fItemHeight, rcBody.right, fy); - sBody << "q\n" - << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 0, 51.0f / 255.0f, - 113.0f / 255.0f), - PaintOperation::FILL) - << rcItem.left << " " << rcItem.bottom << " " - << rcItem.Width() << " " << rcItem.Height() << " re f\n" - << "Q\n"; - sBody << "BT\n" - << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kGray, 1), - PaintOperation::FILL) - << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), - CFX_PointF(0.0f, fy), - true, 0) - << "ET\n"; - } else { - sBody << "BT\n" - << CPVT_GenerateAP::GenerateColorAP(crText, - PaintOperation::FILL) - << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), - CFX_PointF(0.0f, fy), - true, 0) - << "ET\n"; - } - fy -= fItemHeight; - } - } - } - if (sBody.GetSize() > 0) { - sAppStream << "/Tx BMC\nq\n" - << rcBody.left << " " << rcBody.bottom << " " - << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n" - << sBody.AsStringC() << "Q\nEMC\n"; - } - } break; - } - if (pNormalStream) { - pNormalStream->SetData(sAppStream.GetBuffer(), sAppStream.GetSize()); - pStreamDict = pNormalStream->GetDict(); - if (pStreamDict) { - pStreamDict->SetMatrixFor("Matrix", matrix); - pStreamDict->SetRectFor("BBox", rcBBox); - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); - if (pStreamResList) { - CPDF_Dictionary* pStreamResFontList = - pStreamResList->GetDictFor("Font"); - if (!pStreamResFontList) { - pStreamResFontList = - pStreamResList->SetNewFor("Font"); - } - if (!pStreamResFontList->KeyExist(sFontName)) { - pStreamResFontList->SetNewFor(sFontName, pDoc, - pFontDict->GetObjNum()); - } - } else { - pStreamDict->SetFor("Resources", pFormDict->GetDictFor("DR")->Clone()); - pStreamResList = pStreamDict->GetDictFor("Resources"); - } - } - } - return true; -} - -CFX_ByteString GetColorStringWithDefault(CPDF_Array* pColor, - const CPVT_Color& crDefaultColor, - PaintOperation nOperation) { - if (pColor) { - CPVT_Color color = CPVT_Color::ParseColor(*pColor); - return CPVT_GenerateAP::GenerateColorAP(color, nOperation); - } - - return CPVT_GenerateAP::GenerateColorAP(crDefaultColor, nOperation); -} - -FX_FLOAT GetBorderWidth(const CPDF_Dictionary& pAnnotDict) { - if (CPDF_Dictionary* pBorderStyleDict = pAnnotDict.GetDictFor("BS")) { - if (pBorderStyleDict->KeyExist("W")) - return pBorderStyleDict->GetNumberFor("W"); - } +float GetBorderWidth(const CPDF_Dictionary& pAnnotDict) { + if (CPDF_Dictionary* pBorderStyleDict = pAnnotDict.GetDictFor("BS")) { + if (pBorderStyleDict->KeyExist("W")) + return pBorderStyleDict->GetNumberFor("W"); + } if (CPDF_Array* pBorderArray = pAnnotDict.GetArrayFor("Border")) { if (pBorderArray->GetCount() > 2) @@ -491,28 +337,28 @@ CPDF_Array* GetDashArray(const CPDF_Dictionary& pAnnotDict) { return nullptr; } -CFX_ByteString GetDashPatternString(const CPDF_Dictionary& pAnnotDict) { +ByteString GetDashPatternString(const CPDF_Dictionary& pAnnotDict) { CPDF_Array* pDashArray = GetDashArray(pAnnotDict); if (!pDashArray || pDashArray->IsEmpty()) - return CFX_ByteString(); + return ByteString(); // Support maximum of ten elements in the dash array. size_t pDashArrayCount = std::min(pDashArray->GetCount(), 10); - CFX_ByteTextBuf sDashStream; + std::ostringstream sDashStream; sDashStream << "["; for (size_t i = 0; i < pDashArrayCount; ++i) sDashStream << pDashArray->GetNumberAt(i) << " "; sDashStream << "] 0 d\n"; - return sDashStream.MakeString(); + return ByteString(sDashStream); } -CFX_ByteString GetPopupContentsString(CPDF_Document* pDoc, - const CPDF_Dictionary& pAnnotDict, - CPDF_Font* pDefFont, - const CFX_ByteString& sFontName) { - CFX_WideString swValue(pAnnotDict.GetUnicodeTextFor("T")); +ByteString GetPopupContentsString(CPDF_Document* pDoc, + const CPDF_Dictionary& pAnnotDict, + CPDF_Font* pDefFont, + const ByteString& sFontName) { + WideString swValue(pAnnotDict.GetUnicodeTextFor("T")); swValue += L'\n'; swValue += pAnnotDict.GetUnicodeTextFor("Contents"); CPVT_FontMap map(pDoc, nullptr, pDefFont, sFontName); @@ -529,45 +375,24 @@ CFX_ByteString GetPopupContentsString(CPDF_Document* pDoc, vt.SetText(swValue); vt.RearrangeAll(); CFX_PointF ptOffset(3.0f, -3.0f); - CFX_ByteString sContent = CPVT_GenerateAP::GenerateEditAP( - &map, vt.GetIterator(), ptOffset, false, 0); + ByteString sContent = + GenerateEditAP(&map, vt.GetIterator(), ptOffset, false, 0); if (sContent.IsEmpty()) - return CFX_ByteString(); + return ByteString(); - CFX_ByteTextBuf sAppStream; + std::ostringstream sAppStream; sAppStream << "BT\n" - << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), PaintOperation::FILL) + << GenerateColorAP(CFX_Color(CFX_Color::kRGB, 0, 0, 0), + PaintOperation::FILL) << sContent << "ET\n" << "Q\n"; - return sAppStream.MakeString(); -} - -std::unique_ptr GenerateExtGStateDict( - const CPDF_Dictionary& pAnnotDict, - const CFX_ByteString& sExtGSDictName, - const CFX_ByteString& sBlendMode) { - auto pGSDict = - pdfium::MakeUnique(pAnnotDict.GetByteStringPool()); - pGSDict->SetNewFor("Type", "ExtGState", false); - - FX_FLOAT fOpacity = - pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberFor("CA") : 1; - pGSDict->SetNewFor("CA", fOpacity); - pGSDict->SetNewFor("ca", fOpacity); - pGSDict->SetNewFor("AIS", false); - pGSDict->SetNewFor("BM", sBlendMode, false); - - auto pExtGStateDict = - pdfium::MakeUnique(pAnnotDict.GetByteStringPool()); - pExtGStateDict->SetFor(sExtGSDictName, std::move(pGSDict)); - return pExtGStateDict; + return ByteString(sAppStream); } std::unique_ptr GenerateResourceFontDict( CPDF_Document* pDoc, - const CFX_ByteString& sFontDictName) { + const ByteString& sFontDictName) { CPDF_Dictionary* pFontDict = pDoc->NewIndirect(); pFontDict->SetNewFor("Type", "Font"); pFontDict->SetNewFor("Subtype", "Type1"); @@ -581,60 +406,24 @@ std::unique_ptr GenerateResourceFontDict( return pResourceFontDict; } -std::unique_ptr GenerateResourceDict( - CPDF_Document* pDoc, - std::unique_ptr pExtGStateDict, - std::unique_ptr pResourceFontDict) { - auto pResourceDict = - pdfium::MakeUnique(pDoc->GetByteStringPool()); - if (pExtGStateDict) - pResourceDict->SetFor("ExtGState", std::move(pExtGStateDict)); - if (pResourceFontDict) - pResourceDict->SetFor("Font", std::move(pResourceFontDict)); - return pResourceDict; -} - -void GenerateAndSetAPDict(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict, - const CFX_ByteTextBuf& sAppStream, - std::unique_ptr pResourceDict, - bool bIsTextMarkupAnnotation) { - CPDF_Stream* pNormalStream = pDoc->NewIndirect(); - pNormalStream->SetData(sAppStream.GetBuffer(), sAppStream.GetSize()); - - CPDF_Dictionary* pAPDict = pAnnotDict->SetNewFor("AP"); - pAPDict->SetNewFor("N", pDoc, pNormalStream->GetObjNum()); - - CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); - pStreamDict->SetNewFor("FormType", 1); - pStreamDict->SetNewFor("Subtype", "Form", false); - pStreamDict->SetMatrixFor("Matrix", CFX_Matrix()); - - CFX_FloatRect rect = bIsTextMarkupAnnotation - ? CPDF_Annot::RectFromQuadPoints(pAnnotDict) - : pAnnotDict->GetRectFor("Rect"); - pStreamDict->SetRectFor("BBox", rect); - pStreamDict->SetFor("Resources", std::move(pResourceDict)); -} - -CFX_ByteString GetPaintOperatorString(bool bIsStrokeRect, bool bIsFillRect) { +ByteString GetPaintOperatorString(bool bIsStrokeRect, bool bIsFillRect) { if (bIsStrokeRect) return bIsFillRect ? "b" : "s"; return bIsFillRect ? "f" : "n"; } -CFX_ByteString GenerateTextSymbolAP(const CFX_FloatRect& rect) { - CFX_ByteTextBuf sAppStream; - sAppStream << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), PaintOperation::FILL); - sAppStream << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); +ByteString GenerateTextSymbolAP(const CFX_FloatRect& rect) { + std::ostringstream sAppStream; + sAppStream << GenerateColorAP(CFX_Color(CFX_Color::kRGB, 1, 1, 0), + PaintOperation::FILL); + sAppStream << GenerateColorAP(CFX_Color(CFX_Color::kRGB, 0, 0, 0), + PaintOperation::STROKE); - const FX_FLOAT fBorderWidth = 1; + const float fBorderWidth = 1; sAppStream << fBorderWidth << " w\n"; - const FX_FLOAT fHalfWidth = fBorderWidth / 2; - const FX_FLOAT fTipDelta = 4; + const float fHalfWidth = fBorderWidth / 2; + const float fTipDelta = 4; CFX_FloatRect outerRect1 = rect; outerRect1.Deflate(fHalfWidth, fHalfWidth); @@ -644,7 +433,7 @@ CFX_ByteString GenerateTextSymbolAP(const CFX_FloatRect& rect) { outerRect2.left += fTipDelta; outerRect2.right = outerRect2.left + fTipDelta; outerRect2.top = outerRect2.bottom - fTipDelta; - FX_FLOAT outerRect2Middle = (outerRect2.left + outerRect2.right) / 2; + float outerRect2Middle = (outerRect2.left + outerRect2.right) / 2; // Draw outer boxes. sAppStream << outerRect1.left << " " << outerRect1.bottom << " m\n" @@ -658,8 +447,8 @@ CFX_ByteString GenerateTextSymbolAP(const CFX_FloatRect& rect) { // Draw inner lines. CFX_FloatRect lineRect = outerRect1; - const FX_FLOAT fXDelta = 2; - const FX_FLOAT fYDelta = (lineRect.top - lineRect.bottom) / 4; + const float fXDelta = 2; + const float fYDelta = (lineRect.top - lineRect.bottom) / 4; lineRect.left += fXDelta; lineRect.right -= fXDelta; @@ -670,81 +459,83 @@ CFX_ByteString GenerateTextSymbolAP(const CFX_FloatRect& rect) { } sAppStream << "B*\n"; - return sAppStream.MakeString(); + return ByteString(sAppStream); } -} // namespace - -bool FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { - if (!pAnnotDict || pAnnotDict->GetStringFor("Subtype") != "Widget") - return false; +std::unique_ptr GenerateExtGStateDict( + const CPDF_Dictionary& pAnnotDict, + const ByteString& sExtGSDictName, + const ByteString& sBlendMode) { + auto pGSDict = + pdfium::MakeUnique(pAnnotDict.GetByteStringPool()); + pGSDict->SetNewFor("Type", "ExtGState", false); - CPDF_Object* pFieldTypeObj = FPDF_GetFieldAttr(pAnnotDict, "FT"); - if (!pFieldTypeObj) - return false; + float fOpacity = + pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberFor("CA") : 1; + pGSDict->SetNewFor("CA", fOpacity); + pGSDict->SetNewFor("ca", fOpacity); + pGSDict->SetNewFor("AIS", false); + pGSDict->SetNewFor("BM", sBlendMode, false); - CFX_ByteString field_type = pFieldTypeObj->GetString(); - if (field_type == "Tx") - return CPVT_GenerateAP::GenerateTextFieldAP(pDoc, pAnnotDict); + auto pExtGStateDict = + pdfium::MakeUnique(pAnnotDict.GetByteStringPool()); + pExtGStateDict->SetFor(sExtGSDictName, std::move(pGSDict)); + return pExtGStateDict; +} - CPDF_Object* pFieldFlagsObj = FPDF_GetFieldAttr(pAnnotDict, "Ff"); - uint32_t flags = pFieldFlagsObj ? pFieldFlagsObj->GetInteger() : 0; - if (field_type == "Ch") { - return (flags & (1 << 17)) - ? CPVT_GenerateAP::GenerateComboBoxAP(pDoc, pAnnotDict) - : CPVT_GenerateAP::GenerateListBoxAP(pDoc, pAnnotDict); - } +std::unique_ptr GenerateResourceDict( + CPDF_Document* pDoc, + std::unique_ptr pExtGStateDict, + std::unique_ptr pResourceFontDict) { + auto pResourceDict = + pdfium::MakeUnique(pDoc->GetByteStringPool()); + if (pExtGStateDict) + pResourceDict->SetFor("ExtGState", std::move(pExtGStateDict)); + if (pResourceFontDict) + pResourceDict->SetFor("Font", std::move(pResourceFontDict)); + return pResourceDict; +} - if (field_type == "Btn") { - if (!(flags & (1 << 16))) { - if (!pAnnotDict->KeyExist("AS")) { - if (CPDF_Dictionary* pParentDict = pAnnotDict->GetDictFor("Parent")) { - if (pParentDict->KeyExist("AS")) { - pAnnotDict->SetNewFor( - "AS", pParentDict->GetStringFor("AS"), false); - } - } - } - } - } +void GenerateAndSetAPDict(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict, + std::ostringstream* psAppStream, + std::unique_ptr pResourceDict, + bool bIsTextMarkupAnnotation) { + CPDF_Stream* pNormalStream = pDoc->NewIndirect(); + pNormalStream->SetData(psAppStream); - return false; -} + CPDF_Dictionary* pAPDict = pAnnotDict->GetDictFor("AP"); + if (!pAPDict) + pAPDict = pAnnotDict->SetNewFor("AP"); -// Static. -bool CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - return GenerateWidgetAP(pDoc, pAnnotDict, 1); -} + pAPDict->SetNewFor("N", pDoc, pNormalStream->GetObjNum()); -// Static. -bool CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - return GenerateWidgetAP(pDoc, pAnnotDict, 2); -} + CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); + pStreamDict->SetNewFor("FormType", 1); + pStreamDict->SetNewFor("Subtype", "Form", false); + pStreamDict->SetMatrixFor("Matrix", CFX_Matrix()); -// Static. -bool CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - return GenerateWidgetAP(pDoc, pAnnotDict, 0); + CFX_FloatRect rect = bIsTextMarkupAnnotation + ? CPDF_Annot::RectFromQuadPoints(pAnnotDict) + : pAnnotDict->GetRectFor("Rect"); + pStreamDict->SetRectFor("BBox", rect); + pStreamDict->SetFor("Resources", std::move(pResourceDict)); } -bool CPVT_GenerateAP::GenerateCircleAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateCircleAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; CPDF_Array* pInteriorColor = pAnnotDict->GetArrayFor("IC"); - sAppStream << GetColorStringWithDefault(pInteriorColor, - CPVT_Color(CPVT_Color::kTransparent), - PaintOperation::FILL); + sAppStream << GetColorStringWithDefault( + pInteriorColor, CFX_Color(CFX_Color::kTransparent), PaintOperation::FILL); sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); - FX_FLOAT fBorderWidth = GetBorderWidth(*pAnnotDict); + float fBorderWidth = GetBorderWidth(*pAnnotDict); bool bIsStrokeRect = fBorderWidth > 0; if (bIsStrokeRect) { @@ -762,15 +553,15 @@ bool CPVT_GenerateAP::GenerateCircleAP(CPDF_Document* pDoc, rect.Deflate(fBorderWidth / 2, fBorderWidth / 2); } - const FX_FLOAT fMiddleX = (rect.left + rect.right) / 2; - const FX_FLOAT fMiddleY = (rect.top + rect.bottom) / 2; + const float fMiddleX = (rect.left + rect.right) / 2; + const float fMiddleY = (rect.top + rect.bottom) / 2; // |fL| is precalculated approximate value of 4 * tan((3.14 / 2) / 4) / 3, // where |fL| * radius is a good approximation of control points for // arc with 90 degrees. - const FX_FLOAT fL = 0.5523f; - const FX_FLOAT fDeltaX = fL * rect.Width() / 2.0; - const FX_FLOAT fDeltaY = fL * rect.Height() / 2.0; + const float fL = 0.5523f; + const float fDeltaX = fL * rect.Width() / 2.0; + const float fDeltaY = fL * rect.Height() / 2.0; // Starting point sAppStream << fMiddleX << " " << rect.top << " m\n"; @@ -798,19 +589,18 @@ bool CPVT_GenerateAP::GenerateCircleAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), false /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateHighlightAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateHighlightAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), + CFX_Color(CFX_Color::kRGB, 1, 1, 0), PaintOperation::FILL); CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict); @@ -825,15 +615,14 @@ bool CPVT_GenerateAP::GenerateHighlightAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), true /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateInkAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - FX_FLOAT fBorderWidth = GetBorderWidth(*pAnnotDict); +bool GenerateInkAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + float fBorderWidth = GetBorderWidth(*pAnnotDict); bool bIsStroke = fBorderWidth > 0; if (!bIsStroke) @@ -843,12 +632,12 @@ bool CPVT_GenerateAP::GenerateInkAP(CPDF_Document* pDoc, if (!pInkList || pInkList->IsEmpty()) return false; - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); sAppStream << fBorderWidth << " w "; @@ -880,19 +669,18 @@ bool CPVT_GenerateAP::GenerateInkAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), false /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateTextAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateTextAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; CFX_FloatRect rect = pAnnotDict->GetRectFor("Rect"); - const FX_FLOAT fNoteLength = 20; + const float fNoteLength = 20; CFX_FloatRect noteRect(rect.left, rect.bottom, rect.left + fNoteLength, rect.bottom + fNoteLength); pAnnotDict->SetRectFor("Rect", noteRect); @@ -903,25 +691,24 @@ bool CPVT_GenerateAP::GenerateTextAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), false /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateUnderlineAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict); rect.Normalize(); - FX_FLOAT fLineWidth = 1.0; + float fLineWidth = 1.0; sAppStream << fLineWidth << " w " << rect.left << " " << rect.bottom + fLineWidth << " m " << rect.right << " " << rect.bottom + fLineWidth << " l S\n"; @@ -930,23 +717,22 @@ bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), true /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GeneratePopupAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GeneratePopupAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs\n"; - sAppStream << GenerateColorAP(CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), + sAppStream << GenerateColorAP(CFX_Color(CFX_Color::kRGB, 1, 1, 0), PaintOperation::FILL); - sAppStream << GenerateColorAP(CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + sAppStream << GenerateColorAP(CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); - const FX_FLOAT fBorderWidth = 1; + const float fBorderWidth = 1; sAppStream << fBorderWidth << " w\n"; CFX_FloatRect rect = pAnnotDict->GetRectFor("Rect"); @@ -956,7 +742,7 @@ bool CPVT_GenerateAP::GeneratePopupAP(CPDF_Document* pDoc, sAppStream << rect.left << " " << rect.bottom << " " << rect.Width() << " " << rect.Height() << " re b\n"; - CFX_ByteString sFontName = "FONT"; + ByteString sFontName = "FONT"; auto pResourceFontDict = GenerateResourceFontDict(pDoc, sFontName); CPDF_Font* pDefFont = pDoc->LoadFont(pResourceFontDict.get()); if (!pDefFont) @@ -968,27 +754,25 @@ bool CPVT_GenerateAP::GeneratePopupAP(CPDF_Document* pDoc, std::move(pExtGStateDict)); sAppStream << GetPopupContentsString(pDoc, *pAnnotDict, pDefFont, sFontName); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), false /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateSquareAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateSquareAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; CPDF_Array* pInteriorColor = pAnnotDict->GetArrayFor("IC"); - sAppStream << GetColorStringWithDefault(pInteriorColor, - CPVT_Color(CPVT_Color::kTransparent), - PaintOperation::FILL); + sAppStream << GetColorStringWithDefault( + pInteriorColor, CFX_Color(CFX_Color::kTransparent), PaintOperation::FILL); sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); - FX_FLOAT fBorderWidth = GetBorderWidth(*pAnnotDict); + float fBorderWidth = GetBorderWidth(*pAnnotDict); bool bIsStrokeRect = fBorderWidth > 0; if (bIsStrokeRect) { @@ -1016,34 +800,33 @@ bool CPVT_GenerateAP::GenerateSquareAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), false /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateSquigglyAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict); rect.Normalize(); - FX_FLOAT fLineWidth = 1.0; + float fLineWidth = 1.0; sAppStream << fLineWidth << " w "; - const FX_FLOAT fDelta = 2.0; - const FX_FLOAT fTop = rect.bottom + fDelta; - const FX_FLOAT fBottom = rect.bottom; + const float fDelta = 2.0; + const float fTop = rect.bottom + fDelta; + const float fBottom = rect.bottom; sAppStream << rect.left << " " << fTop << " m "; - FX_FLOAT fX = rect.left + fDelta; + float fX = rect.left + fDelta; bool isUpwards = false; while (fX < rect.right) { @@ -1053,7 +836,7 @@ bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, isUpwards = !isUpwards; } - FX_FLOAT fRemainder = rect.right - (fX - fDelta); + float fRemainder = rect.right - (fX - fDelta); if (isUpwards) sAppStream << rect.right << " " << fBottom + fRemainder << " l "; else @@ -1065,26 +848,25 @@ bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), true /*IsTextMarkupAnnotation*/); return true; } -bool CPVT_GenerateAP::GenerateStrikeOutAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sExtGSDictName = "GS"; +bool GenerateStrikeOutAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + std::ostringstream sAppStream; + ByteString sExtGSDictName = "GS"; sAppStream << "/" << sExtGSDictName << " gs "; sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayFor("C"), - CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + CFX_Color(CFX_Color::kRGB, 0, 0, 0), PaintOperation::STROKE); CFX_FloatRect rect = CPDF_Annot::RectFromQuadPoints(pAnnotDict); rect.Normalize(); - FX_FLOAT fLineWidth = 1.0; - FX_FLOAT fY = (rect.top + rect.bottom) / 2; + float fLineWidth = 1.0; + float fY = (rect.top + rect.bottom) / 2; sAppStream << fLineWidth << " w " << rect.left << " " << fY << " m " << rect.right << " " << fY << " l S\n"; @@ -1092,275 +874,477 @@ bool CPVT_GenerateAP::GenerateStrikeOutAP(CPDF_Document* pDoc, GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); auto pResourceDict = GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); - GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, std::move(pResourceDict), + GenerateAndSetAPDict(pDoc, pAnnotDict, &sAppStream, std::move(pResourceDict), true /*IsTextMarkupAnnotation*/); return true; } -// Static. -CFX_ByteString CPVT_GenerateAP::GenerateEditAP( - IPVT_FontMap* pFontMap, - CPDF_VariableText::Iterator* pIterator, - const CFX_PointF& ptOffset, - bool bContinuous, - uint16_t SubWord) { - CFX_ByteTextBuf sEditStream; - CFX_ByteTextBuf sLineStream; - CFX_ByteTextBuf sWords; - CFX_PointF ptOld; - CFX_PointF ptNew; - int32_t nCurFontIndex = -1; - CPVT_WordPlace oldplace; +} // namespace - pIterator->SetAt(0); - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - if (bContinuous) { - if (place.LineCmp(oldplace) != 0) { - if (sWords.GetSize() > 0) { - sLineStream << GetWordRenderString(sWords.MakeString()); - sEditStream << sLineStream; - sLineStream.Clear(); - sWords.Clear(); - } - CPVT_Word word; - if (pIterator->GetWord(word)) { - ptNew = CFX_PointF(word.ptWord.x + ptOffset.x, - word.ptWord.y + ptOffset.y); - } else { - CPVT_Line line; - pIterator->GetLine(line); - ptNew = CFX_PointF(line.ptLine.x + ptOffset.x, - line.ptLine.y + ptOffset.y); - } - if (ptNew != ptOld) { - sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y - << " Td\n"; - ptOld = ptNew; - } - } - CPVT_Word word; - if (pIterator->GetWord(word)) { - if (word.nFontIndex != nCurFontIndex) { - if (sWords.GetSize() > 0) { - sLineStream << GetWordRenderString(sWords.MakeString()); - sWords.Clear(); - } - sLineStream << GetFontSetString(pFontMap, word.nFontIndex, - word.fFontSize); - nCurFontIndex = word.nFontIndex; - } - sWords << GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord); - } - oldplace = place; - } else { - CPVT_Word word; - if (pIterator->GetWord(word)) { - ptNew = - CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y); - if (ptNew != ptOld) { - sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y - << " Td\n"; - ptOld = ptNew; - } - if (word.nFontIndex != nCurFontIndex) { - sEditStream << GetFontSetString(pFontMap, word.nFontIndex, - word.fFontSize); - nCurFontIndex = word.nFontIndex; - } - sEditStream << GetWordRenderString( - GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord)); +// static +void CPVT_GenerateAP::GenerateFormAP(Type type, + CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + const CPDF_Dictionary* pRootDict = pDoc->GetRoot(); + if (!pRootDict) + return; + + const CPDF_Dictionary* pFormDict = pRootDict->GetDictFor("AcroForm"); + if (!pFormDict) + return; + + ByteString DA; + if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) + DA = pDAObj->GetString(); + if (DA.IsEmpty()) + DA = pFormDict->GetStringFor("DA"); + if (DA.IsEmpty()) + return; + + CPDF_SimpleParser syntax(DA.AsStringView()); + syntax.FindTagParamFromStart("Tf", 2); + ByteString sFontName(syntax.GetWord()); + sFontName = PDF_NameDecode(sFontName); + if (sFontName.IsEmpty()) + return; + + float fFontSize = FX_atof(syntax.GetWord()); + CFX_Color crText = CFX_Color::ParseColor(DA); + CPDF_Dictionary* pDRDict = pFormDict->GetDictFor("DR"); + if (!pDRDict) + return; + + CPDF_Dictionary* pDRFontDict = pDRDict->GetDictFor("Font"); + if (!pDRFontDict) + return; + + CPDF_Dictionary* pFontDict = + pDRFontDict->GetDictFor(sFontName.Right(sFontName.GetLength() - 1)); + if (!pFontDict) { + pFontDict = pDoc->NewIndirect(); + pFontDict->SetNewFor("Type", "Font"); + pFontDict->SetNewFor("Subtype", "Type1"); + pFontDict->SetNewFor("BaseFont", "Helvetica"); + pFontDict->SetNewFor("Encoding", "WinAnsiEncoding"); + pDRFontDict->SetNewFor( + sFontName.Right(sFontName.GetLength() - 1), pDoc, + pFontDict->GetObjNum()); + } + CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict); + if (!pDefFont) + return; + + CFX_FloatRect rcAnnot = pAnnotDict->GetRectFor("Rect"); + int32_t nRotate = 0; + if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictFor("MK")) + nRotate = pMKDict->GetIntegerFor("R"); + + CFX_FloatRect rcBBox; + CFX_Matrix matrix; + switch (nRotate % 360) { + case 0: + rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, + rcAnnot.top - rcAnnot.bottom); + break; + case 90: + matrix = CFX_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0); + rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, + rcAnnot.right - rcAnnot.left); + break; + case 180: + matrix = CFX_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, + rcAnnot.top - rcAnnot.bottom); + rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, + rcAnnot.top - rcAnnot.bottom); + break; + case 270: + matrix = CFX_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom); + rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, + rcAnnot.right - rcAnnot.left); + break; + } + + BorderStyle nBorderStyle = BorderStyle::SOLID; + float fBorderWidth = 1; + CPVT_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + if (CPDF_Dictionary* pBSDict = pAnnotDict->GetDictFor("BS")) { + if (pBSDict->KeyExist("W")) + fBorderWidth = pBSDict->GetNumberFor("W"); + + if (CPDF_Array* pArray = pBSDict->GetArrayFor("D")) { + dsBorder = CPVT_Dash(pArray->GetIntegerAt(0), pArray->GetIntegerAt(1), + pArray->GetIntegerAt(2)); + } + if (pBSDict->GetStringFor("S").GetLength()) { + switch (pBSDict->GetStringFor("S")[0]) { + case 'S': + nBorderStyle = BorderStyle::SOLID; + break; + case 'D': + nBorderStyle = BorderStyle::DASH; + break; + case 'B': + nBorderStyle = BorderStyle::BEVELED; + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 1); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.5); + break; + case 'I': + nBorderStyle = BorderStyle::INSET; + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 0.5); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.75); + break; + case 'U': + nBorderStyle = BorderStyle::UNDERLINE; + break; } } } - if (sWords.GetSize() > 0) { - sLineStream << GetWordRenderString(sWords.MakeString()); - sEditStream << sLineStream; - sWords.Clear(); + CFX_Color crBorder; + CFX_Color crBG; + if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictFor("MK")) { + if (CPDF_Array* pArray = pMKDict->GetArrayFor("BC")) + crBorder = CFX_Color::ParseColor(*pArray); + if (CPDF_Array* pArray = pMKDict->GetArrayFor("BG")) + crBG = CFX_Color::ParseColor(*pArray); } - return sEditStream.MakeString(); -} + std::ostringstream sAppStream; + ByteString sBG = GenerateColorAP(crBG, PaintOperation::FILL); + if (sBG.GetLength() > 0) { + sAppStream << "q\n" + << sBG << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" + << "Q\n"; + } + ByteString sBorderStream = + GenerateBorderAP(rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom, + nBorderStyle, dsBorder); + if (sBorderStream.GetLength() > 0) + sAppStream << "q\n" << sBorderStream << "Q\n"; -// Static. -CFX_ByteString CPVT_GenerateAP::GenerateBorderAP( - const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPVT_Color& color, - const CPVT_Color& crLeftTop, - const CPVT_Color& crRightBottom, - BorderStyle nStyle, - const CPVT_Dash& dash) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sColor; - FX_FLOAT fLeft = rect.left; - FX_FLOAT fRight = rect.right; - FX_FLOAT fTop = rect.top; - FX_FLOAT fBottom = rect.bottom; - if (fWidth > 0.0f) { - FX_FLOAT fHalfWidth = fWidth / 2.0f; - switch (nStyle) { - default: - case BorderStyle::SOLID: - sColor = GenerateColorAP(color, PaintOperation::FILL); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " - << fTop - fBottom << " re\n"; - sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " - << fRight - fLeft - fWidth * 2 << " " - << fTop - fBottom - fWidth * 2 << " re\n"; - sAppStream << "f*\n"; - } - break; - case BorderStyle::DASH: - sColor = GenerateColorAP(color, PaintOperation::STROKE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fWidth << " w" - << " [" << dash.nDash << " " << dash.nGap << "] " - << dash.nPhase << " d\n"; - sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 - << " m\n"; - sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 - << " l\n"; - sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 - << " l\n"; - sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 - << " l\n"; - sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 - << " l S\n"; - } - break; - case BorderStyle::BEVELED: - case BorderStyle::INSET: - sColor = GenerateColorAP(crLeftTop, PaintOperation::FILL); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth - << " m\n"; - sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth - << " l\n"; - sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth - << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l f\n"; - } - sColor = GenerateColorAP(crRightBottom, PaintOperation::FILL); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth - << " m\n"; - sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth - << " l\n"; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l f\n"; - } - sColor = GenerateColorAP(color, PaintOperation::FILL); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " - << fTop - fBottom << " re\n"; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " - << fRight - fLeft - fHalfWidth * 2 << " " - << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; - } - break; - case BorderStyle::UNDERLINE: - sColor = GenerateColorAP(color, PaintOperation::STROKE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fWidth << " w\n"; - sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; - sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; - } - break; + CFX_FloatRect rcBody = + CFX_FloatRect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth, + rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth); + rcBody.Normalize(); + + CPDF_Dictionary* pAPDict = pAnnotDict->GetDictFor("AP"); + if (!pAPDict) + pAPDict = pAnnotDict->SetNewFor("AP"); + + CPDF_Stream* pNormalStream = pAPDict->GetStreamFor("N"); + if (!pNormalStream) { + pNormalStream = pDoc->NewIndirect(); + pAPDict->SetNewFor("N", pDoc, pNormalStream->GetObjNum()); + } + CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); + if (pStreamDict) { + pStreamDict->SetMatrixFor("Matrix", matrix); + pStreamDict->SetRectFor("BBox", rcBBox); + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); + if (pStreamResList) { + CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictFor("Font"); + if (!pStreamResFontList) + pStreamResFontList = pStreamResList->SetNewFor("Font"); + if (!pStreamResFontList->KeyExist(sFontName)) { + pStreamResFontList->SetNewFor(sFontName, pDoc, + pFontDict->GetObjNum()); + } + } else { + pStreamDict->SetFor("Resources", pFormDict->GetDictFor("DR")->Clone()); + pStreamResList = pStreamDict->GetDictFor("Resources"); } } - return sAppStream.MakeString(); -} + switch (type) { + case CPVT_GenerateAP::kTextField: { + WideString swValue = + FPDF_GetFieldAttr(pAnnotDict, "V") + ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() + : WideString(); + int32_t nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q") + ? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() + : 0; + uint32_t dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff") + ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() + : 0; + uint32_t dwMaxLen = + FPDF_GetFieldAttr(pAnnotDict, "MaxLen") + ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() + : 0; + CPVT_FontMap map( + pDoc, pStreamDict ? pStreamDict->GetDictFor("Resources") : nullptr, + pDefFont, sFontName.Right(sFontName.GetLength() - 1)); + CPDF_VariableText::Provider prd(&map); + CPDF_VariableText vt; + vt.SetProvider(&prd); + vt.SetPlateRect(rcBody); + vt.SetAlignment(nAlign); + if (IsFloatZero(fFontSize)) + vt.SetAutoFontSize(true); + else + vt.SetFontSize(fFontSize); -// Static. -CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color& color, - PaintOperation nOperation) { - CFX_ByteTextBuf sColorStream; - switch (color.nColorType) { - case CPVT_Color::kRGB: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " - << (nOperation == PaintOperation::STROKE ? "RG" : "rg") - << "\n"; - break; - case CPVT_Color::kGray: - sColorStream << color.fColor1 << " " - << (nOperation == PaintOperation::STROKE ? "G" : "g") - << "\n"; - break; - case CPVT_Color::kCMYK: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " << color.fColor4 << " " - << (nOperation == PaintOperation::STROKE ? "K" : "k") - << "\n"; + bool bMultiLine = (dwFlags >> 12) & 1; + if (bMultiLine) { + vt.SetMultiLine(true); + vt.SetAutoReturn(true); + } + uint16_t subWord = 0; + if ((dwFlags >> 13) & 1) { + subWord = '*'; + vt.SetPasswordChar(subWord); + } + bool bCharArray = (dwFlags >> 24) & 1; + if (bCharArray) + vt.SetCharArray(dwMaxLen); + else + vt.SetLimitChar(dwMaxLen); + + vt.Initialize(); + vt.SetText(swValue); + vt.RearrangeAll(); + CFX_FloatRect rcContent = vt.GetContentRect(); + CFX_PointF ptOffset; + if (!bMultiLine) { + ptOffset = + CFX_PointF(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f); + } + ByteString sBody = GenerateEditAP(&map, vt.GetIterator(), ptOffset, + !bCharArray, subWord); + if (sBody.GetLength() > 0) { + sAppStream << "/Tx BMC\n" + << "q\n"; + if (rcContent.Width() > rcBody.Width() || + rcContent.Height() > rcBody.Height()) { + sAppStream << rcBody.left << " " << rcBody.bottom << " " + << rcBody.Width() << " " << rcBody.Height() + << " re\nW\nn\n"; + } + sAppStream << "BT\n" + << GenerateColorAP(crText, PaintOperation::FILL) << sBody + << "ET\n" + << "Q\nEMC\n"; + } break; - case CPVT_Color::kTransparent: + } + case CPVT_GenerateAP::kComboBox: { + WideString swValue = + FPDF_GetFieldAttr(pAnnotDict, "V") + ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() + : WideString(); + CPVT_FontMap map( + pDoc, pStreamDict ? pStreamDict->GetDictFor("Resources") : nullptr, + pDefFont, sFontName.Right(sFontName.GetLength() - 1)); + CPDF_VariableText::Provider prd(&map); + CPDF_VariableText vt; + vt.SetProvider(&prd); + CFX_FloatRect rcButton = rcBody; + rcButton.left = rcButton.right - 13; + rcButton.Normalize(); + CFX_FloatRect rcEdit = rcBody; + rcEdit.right = rcButton.left; + rcEdit.Normalize(); + vt.SetPlateRect(rcEdit); + if (IsFloatZero(fFontSize)) + vt.SetAutoFontSize(true); + else + vt.SetFontSize(fFontSize); + + vt.Initialize(); + vt.SetText(swValue); + vt.RearrangeAll(); + CFX_FloatRect rcContent = vt.GetContentRect(); + CFX_PointF ptOffset = + CFX_PointF(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f); + ByteString sEdit = + GenerateEditAP(&map, vt.GetIterator(), ptOffset, true, 0); + if (sEdit.GetLength() > 0) { + sAppStream << "/Tx BMC\n" + << "q\n"; + sAppStream << rcEdit.left << " " << rcEdit.bottom << " " + << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n"; + sAppStream << "BT\n" + << GenerateColorAP(crText, PaintOperation::FILL) << sEdit + << "ET\n" + << "Q\nEMC\n"; + } + ByteString sButton = + GenerateColorAP(CFX_Color(CFX_Color::kRGB, 220.0f / 255.0f, + 220.0f / 255.0f, 220.0f / 255.0f), + PaintOperation::FILL); + if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) { + sAppStream << "q\n" << sButton; + sAppStream << rcButton.left << " " << rcButton.bottom << " " + << rcButton.Width() << " " << rcButton.Height() << " re f\n"; + sAppStream << "Q\n"; + ByteString sButtonBorder = GenerateBorderAP( + rcButton, 2, CFX_Color(CFX_Color::kGray, 0), + CFX_Color(CFX_Color::kGray, 1), CFX_Color(CFX_Color::kGray, 0.5), + BorderStyle::BEVELED, CPVT_Dash(3, 0, 0)); + if (sButtonBorder.GetLength() > 0) + sAppStream << "q\n" << sButtonBorder << "Q\n"; + + CFX_PointF ptCenter = CFX_PointF((rcButton.left + rcButton.right) / 2, + (rcButton.top + rcButton.bottom) / 2); + if (IsFloatBigger(rcButton.Width(), 6) && + IsFloatBigger(rcButton.Height(), 6)) { + sAppStream << "q\n" + << " 0 g\n"; + sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; + sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; + sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; + sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; + sAppStream << sButton << "Q\n"; + } + } break; - } - return sColorStream.MakeString(); -} + } + case CPVT_GenerateAP::kListBox: { + CPVT_FontMap map( + pDoc, pStreamDict ? pStreamDict->GetDictFor("Resources") : nullptr, + pDefFont, sFontName.Right(sFontName.GetLength() - 1)); + CPDF_VariableText::Provider prd(&map); + CPDF_Array* pOpts = ToArray(FPDF_GetFieldAttr(pAnnotDict, "Opt")); + CPDF_Array* pSels = ToArray(FPDF_GetFieldAttr(pAnnotDict, "I")); + CPDF_Object* pTi = FPDF_GetFieldAttr(pAnnotDict, "TI"); + int32_t nTop = pTi ? pTi->GetInteger() : 0; + std::ostringstream sBody; + if (pOpts) { + float fy = rcBody.top; + for (size_t i = nTop, sz = pOpts->GetCount(); i < sz; i++) { + if (IsFloatSmaller(fy, rcBody.bottom)) + break; -// Static. -CFX_ByteString CPVT_GenerateAP::GetPDFWordString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord) { - CFX_ByteString sWord; - if (SubWord > 0) { - sWord.Format("%c", SubWord); - return sWord; - } + if (CPDF_Object* pOpt = pOpts->GetDirectObjectAt(i)) { + WideString swItem; + if (pOpt->IsString()) + swItem = pOpt->GetUnicodeText(); + else if (CPDF_Array* pArray = pOpt->AsArray()) + swItem = pArray->GetDirectObjectAt(1)->GetUnicodeText(); - if (!pFontMap) - return sWord; + bool bSelected = false; + if (pSels) { + for (size_t s = 0, ssz = pSels->GetCount(); s < ssz; s++) { + int value = pSels->GetIntegerAt(s); + if (value >= 0 && i == static_cast(value)) { + bSelected = true; + break; + } + } + } + CPDF_VariableText vt; + vt.SetProvider(&prd); + vt.SetPlateRect( + CFX_FloatRect(rcBody.left, 0.0f, rcBody.right, 0.0f)); + vt.SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); - if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) { - if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 || - pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) { - sWord.Format("%c", Word); - } else { - uint32_t dwCharCode = pPDFFont->CharCodeFromUnicode(Word); - if (dwCharCode != CPDF_Font::kInvalidCharCode) - pPDFFont->AppendChar(sWord, dwCharCode); + vt.Initialize(); + vt.SetText(swItem); + vt.RearrangeAll(); + float fItemHeight = vt.GetContentRect().Height(); + if (bSelected) { + CFX_FloatRect rcItem = CFX_FloatRect( + rcBody.left, fy - fItemHeight, rcBody.right, fy); + sBody << "q\n" + << GenerateColorAP( + CFX_Color(CFX_Color::kRGB, 0, 51.0f / 255.0f, + 113.0f / 255.0f), + PaintOperation::FILL) + << rcItem.left << " " << rcItem.bottom << " " + << rcItem.Width() << " " << rcItem.Height() << " re f\n" + << "Q\n"; + sBody << "BT\n" + << GenerateColorAP(CFX_Color(CFX_Color::kGray, 1), + PaintOperation::FILL) + << GenerateEditAP(&map, vt.GetIterator(), + CFX_PointF(0.0f, fy), true, 0) + << "ET\n"; + } else { + sBody << "BT\n" + << GenerateColorAP(crText, PaintOperation::FILL) + << GenerateEditAP(&map, vt.GetIterator(), + CFX_PointF(0.0f, fy), true, 0) + << "ET\n"; + } + fy -= fItemHeight; + } + } + } + if (sBody.tellp() > 0) { + sAppStream << "/Tx BMC\nq\n" + << rcBody.left << " " << rcBody.bottom << " " + << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n" + << sBody.str() << "Q\nEMC\n"; + } + break; } } - return sWord; + + if (pNormalStream) { + pNormalStream->SetDataAndRemoveFilter(&sAppStream); + pStreamDict = pNormalStream->GetDict(); + if (pStreamDict) { + pStreamDict->SetMatrixFor("Matrix", matrix); + pStreamDict->SetRectFor("BBox", rcBBox); + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); + if (pStreamResList) { + CPDF_Dictionary* pStreamResFontList = + pStreamResList->GetDictFor("Font"); + if (!pStreamResFontList) { + pStreamResFontList = + pStreamResList->SetNewFor("Font"); + } + if (!pStreamResFontList->KeyExist(sFontName)) { + pStreamResFontList->SetNewFor(sFontName, pDoc, + pFontDict->GetObjNum()); + } + } else { + pStreamDict->SetFor("Resources", pFormDict->GetDictFor("DR")->Clone()); + pStreamResList = pStreamDict->GetDictFor("Resources"); + } + } + } + return; } -// Static. -CFX_ByteString CPVT_GenerateAP::GetWordRenderString( - const CFX_ByteString& strWords) { - if (strWords.GetLength() > 0) - return PDF_EncodeString(strWords) + " Tj\n"; - return ""; +// static +void CPVT_GenerateAP::GenerateEmptyAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + auto pExtGStateDict = GenerateExtGStateDict(*pAnnotDict, "GS", "Normal"); + auto pResourceDict = + GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr); + + std::ostringstream sStream; + GenerateAndSetAPDict(pDoc, pAnnotDict, &sStream, std::move(pResourceDict), + false); } -// Static. -CFX_ByteString CPVT_GenerateAP::GetFontSetString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - FX_FLOAT fFontSize) { - CFX_ByteTextBuf sRet; - if (pFontMap) { - CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); - if (sFontAlias.GetLength() > 0 && fFontSize > 0) - sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; +// static +bool CPVT_GenerateAP::GenerateAnnotAP(CPDF_Annot::Subtype subtype, + CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + switch (subtype) { + case CPDF_Annot::Subtype::CIRCLE: + return GenerateCircleAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::HIGHLIGHT: + return GenerateHighlightAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::INK: + return GenerateInkAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::POPUP: + return GeneratePopupAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::SQUARE: + return GenerateSquareAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::SQUIGGLY: + return GenerateSquigglyAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::STRIKEOUT: + return GenerateStrikeOutAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::TEXT: + return GenerateTextAP(pDoc, pAnnotDict); + case CPDF_Annot::Subtype::UNDERLINE: + return GenerateUnderlineAP(pDoc, pAnnotDict); + default: + return false; } - return sRet.MakeString(); } diff --git a/core/fpdfdoc/cpvt_generateap.h b/core/fpdfdoc/cpvt_generateap.h index 62a84531eeec19daba223fbfbe8cb105bebadd73..6f569935757baf127f0d1f8aeca8d03195aa763d 100644 --- a/core/fpdfdoc/cpvt_generateap.h +++ b/core/fpdfdoc/cpvt_generateap.h @@ -7,68 +7,31 @@ #ifndef CORE_FPDFDOC_CPVT_GENERATEAP_H_ #define CORE_FPDFDOC_CPVT_GENERATEAP_H_ +#include + #include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fpdfdoc/cpdf_variabletext.h" -#include "core/fpdfdoc/cpvt_color.h" -#include "core/fpdfdoc/cpvt_dash.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxge/cfx_color.h" class CPDF_Dictionary; class CPDF_Document; -class IPVT_FontMap; - -struct CPVT_WordRange; - -bool FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); +struct CPVT_Dash; class CPVT_GenerateAP { public: - static bool GenerateCircleAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateComboBoxAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateHighlightAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateInkAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); - static bool GenerateListBoxAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GeneratePopupAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); - static bool GenerateSquareAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateSquigglyAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateStrikeOutAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateTextAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); - static bool GenerateTextFieldAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static bool GenerateUnderlineAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict); - static CFX_ByteString GenerateEditAP(IPVT_FontMap* pFontMap, - CPDF_VariableText::Iterator* pIterator, - const CFX_PointF& ptOffset, - bool bContinuous, - uint16_t SubWord); - static CFX_ByteString GenerateBorderAP(const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPVT_Color& color, - const CPVT_Color& crLeftTop, - const CPVT_Color& crRightBottom, - BorderStyle nStyle, - const CPVT_Dash& dash); - static CFX_ByteString GenerateColorAP(const CPVT_Color& color, - PaintOperation nOperation); + enum Type { kTextField, kComboBox, kListBox }; + + static void GenerateFormAP(Type type, + CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict); + static void GenerateEmptyAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); - static CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord); - static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords); - static CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - FX_FLOAT fFontSize); + static bool GenerateAnnotAP(CPDF_Annot::Subtype subtype, + CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict); }; #endif // CORE_FPDFDOC_CPVT_GENERATEAP_H_ diff --git a/core/fpdfdoc/cpvt_line.h b/core/fpdfdoc/cpvt_line.h index 47c3e84d6acae29f714a78aa6ecea74fa2ef03b7..087034d3d5f26b57f9381ee9d74dd719e0d12be1 100644 --- a/core/fpdfdoc/cpvt_line.h +++ b/core/fpdfdoc/cpvt_line.h @@ -18,9 +18,9 @@ class CPVT_Line { CPVT_WordPlace lineplace; CPVT_WordPlace lineEnd; CFX_PointF ptLine; - FX_FLOAT fLineWidth; - FX_FLOAT fLineAscent; - FX_FLOAT fLineDescent; + float fLineWidth; + float fLineAscent; + float fLineDescent; }; inline CPVT_Line::CPVT_Line() diff --git a/core/fpdfdoc/cpvt_lineinfo.h b/core/fpdfdoc/cpvt_lineinfo.h index 8fb10de2507d9586496beed0cac6401b5c37f28f..96a32343807877554db0790fd3c3f62632c04875 100644 --- a/core/fpdfdoc/cpvt_lineinfo.h +++ b/core/fpdfdoc/cpvt_lineinfo.h @@ -16,11 +16,11 @@ class CPVT_LineInfo { int32_t nTotalWord; int32_t nBeginWordIndex; int32_t nEndWordIndex; - FX_FLOAT fLineX; - FX_FLOAT fLineY; - FX_FLOAT fLineWidth; - FX_FLOAT fLineAscent; - FX_FLOAT fLineDescent; + float fLineX; + float fLineY; + float fLineWidth; + float fLineAscent; + float fLineDescent; }; inline CPVT_LineInfo::CPVT_LineInfo() diff --git a/core/fpdfdoc/cpvt_secprops.h b/core/fpdfdoc/cpvt_secprops.h deleted file mode 100644 index d1c4b589f11a8674990b0451e44ebbd9280a12a0..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_secprops.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_SECPROPS_H_ -#define CORE_FPDFDOC_CPVT_SECPROPS_H_ - -#include "core/fxcrt/fx_system.h" - -struct CPVT_SecProps { - CPVT_SecProps() : fLineLeading(0.0f), fLineIndent(0.0f), nAlignment(0) {} - - CPVT_SecProps(FX_FLOAT lineLeading, FX_FLOAT lineIndent, int32_t alignment) - : fLineLeading(lineLeading), - fLineIndent(lineIndent), - nAlignment(alignment) {} - - CPVT_SecProps(const CPVT_SecProps& other) - : fLineLeading(other.fLineLeading), - fLineIndent(other.fLineIndent), - nAlignment(other.nAlignment) {} - - FX_FLOAT fLineLeading; - FX_FLOAT fLineIndent; - int32_t nAlignment; -}; - -#endif // CORE_FPDFDOC_CPVT_SECPROPS_H_ diff --git a/core/fpdfdoc/cpvt_section.h b/core/fpdfdoc/cpvt_section.h deleted file mode 100644 index 42b16fd31061e088ba91fe88d7ef0691313ef8ae..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_section.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_SECTION_H_ -#define CORE_FPDFDOC_CPVT_SECTION_H_ - -#include "core/fpdfdoc/cpvt_secprops.h" -#include "core/fpdfdoc/cpvt_wordplace.h" -#include "core/fpdfdoc/cpvt_wordprops.h" -#include "core/fxcrt/fx_coordinates.h" - -struct CPVT_Section { - CPVT_WordPlace secplace; - CFX_FloatRect rcSection; - CPVT_SecProps SecProps; - CPVT_WordProps WordProps; -}; - -#endif // CORE_FPDFDOC_CPVT_SECTION_H_ diff --git a/core/fpdfdoc/cpvt_sectioninfo.cpp b/core/fpdfdoc/cpvt_sectioninfo.cpp deleted file mode 100644 index ec0262c1a02292eb4df4d037dee907323c8bac33..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_sectioninfo.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 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 "core/fpdfdoc/cpvt_sectioninfo.h" -#include "third_party/base/ptr_util.h" - -CPVT_SectionInfo::CPVT_SectionInfo() : rcSection(), nTotalLine(0) {} - -CPVT_SectionInfo::~CPVT_SectionInfo() {} - -CPVT_SectionInfo::CPVT_SectionInfo(const CPVT_SectionInfo& other) { - operator=(other); -} - -void CPVT_SectionInfo::operator=(const CPVT_SectionInfo& other) { - if (this == &other) - return; - - rcSection = other.rcSection; - nTotalLine = other.nTotalLine; - if (other.pSecProps) - pSecProps = pdfium::MakeUnique(*other.pSecProps); - else - pSecProps.reset(); - - if (other.pWordProps) - pWordProps = pdfium::MakeUnique(*other.pWordProps); - else - pWordProps.reset(); -} diff --git a/core/fpdfdoc/cpvt_sectioninfo.h b/core/fpdfdoc/cpvt_sectioninfo.h deleted file mode 100644 index 6422efe86859e1a454408cb09792736b3a87f52f..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_sectioninfo.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_SECTIONINFO_H_ -#define CORE_FPDFDOC_CPVT_SECTIONINFO_H_ - -#include - -#include "core/fpdfdoc/cpvt_floatrect.h" -#include "core/fpdfdoc/cpvt_secprops.h" -#include "core/fpdfdoc/cpvt_wordprops.h" - -struct CPVT_SectionInfo { - CPVT_SectionInfo(); - CPVT_SectionInfo(const CPVT_SectionInfo& other); - ~CPVT_SectionInfo(); - - void operator=(const CPVT_SectionInfo& other); - - CPVT_FloatRect rcSection; - int32_t nTotalLine; - std::unique_ptr pSecProps; - std::unique_ptr pWordProps; -}; - -#endif // CORE_FPDFDOC_CPVT_SECTIONINFO_H_ diff --git a/core/fpdfdoc/cpvt_word.h b/core/fpdfdoc/cpvt_word.h index 540f0416ad5264d088f430d527dd4da2ea660f76..ad0ba744cc1559977709b48fc981d820b3510127 100644 --- a/core/fpdfdoc/cpvt_word.h +++ b/core/fpdfdoc/cpvt_word.h @@ -8,7 +8,6 @@ #define CORE_FPDFDOC_CPVT_WORD_H_ #include "core/fpdfdoc/cpvt_wordplace.h" -#include "core/fpdfdoc/cpvt_wordprops.h" #include "core/fxcrt/fx_system.h" class CPVT_Word { @@ -19,12 +18,11 @@ class CPVT_Word { int32_t nCharset; CPVT_WordPlace WordPlace; CFX_PointF ptWord; - FX_FLOAT fAscent; - FX_FLOAT fDescent; - FX_FLOAT fWidth; + float fAscent; + float fDescent; + float fWidth; int32_t nFontIndex; - FX_FLOAT fFontSize; - CPVT_WordProps WordProps; + float fFontSize; }; inline CPVT_Word::CPVT_Word() diff --git a/core/fpdfdoc/cpvt_wordinfo.cpp b/core/fpdfdoc/cpvt_wordinfo.cpp index f1ea11915c4a1122e236ea32c728ae297af051f6..24ad4b89659e4d979058fca3a931e4c7853b6005 100644 --- a/core/fpdfdoc/cpvt_wordinfo.cpp +++ b/core/fpdfdoc/cpvt_wordinfo.cpp @@ -5,20 +5,18 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fpdfdoc/cpvt_wordinfo.h" +#include "core/fxcrt/fx_codepage.h" #include "third_party/base/ptr_util.h" CPVT_WordInfo::CPVT_WordInfo() : Word(0), - nCharset(FXFONT_ANSI_CHARSET), + nCharset(FX_CHARSET_ANSI), fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f), nFontIndex(-1) {} -CPVT_WordInfo::CPVT_WordInfo(uint16_t word, - int32_t charset, - int32_t fontIndex, - CPVT_WordProps* pProps) +CPVT_WordInfo::CPVT_WordInfo(uint16_t word, int32_t charset, int32_t fontIndex) : Word(word), nCharset(charset), fWordX(0.0f), @@ -28,7 +26,7 @@ CPVT_WordInfo::CPVT_WordInfo(uint16_t word, CPVT_WordInfo::CPVT_WordInfo(const CPVT_WordInfo& word) : Word(0), - nCharset(FXFONT_ANSI_CHARSET), + nCharset(FX_CHARSET_ANSI), fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f), @@ -48,8 +46,4 @@ void CPVT_WordInfo::operator=(const CPVT_WordInfo& word) { fWordX = word.fWordX; fWordY = word.fWordY; fWordTail = word.fWordTail; - if (word.pWordProps) - pWordProps = pdfium::MakeUnique(*word.pWordProps); - else - pWordProps.reset(); } diff --git a/core/fpdfdoc/cpvt_wordinfo.h b/core/fpdfdoc/cpvt_wordinfo.h index 861534b0a52bcda5ea67500123e9263cdb8615bb..9b2ec8a1e5fe76093614f3f79d5db5aadc832d0c 100644 --- a/core/fpdfdoc/cpvt_wordinfo.h +++ b/core/fpdfdoc/cpvt_wordinfo.h @@ -9,15 +9,11 @@ #include -#include "core/fpdfdoc/cpvt_wordprops.h" #include "core/fxcrt/fx_system.h" struct CPVT_WordInfo { CPVT_WordInfo(); - CPVT_WordInfo(uint16_t word, - int32_t charset, - int32_t fontIndex, - CPVT_WordProps* pProps); + CPVT_WordInfo(uint16_t word, int32_t charset, int32_t fontIndex); CPVT_WordInfo(const CPVT_WordInfo& word); ~CPVT_WordInfo(); @@ -25,11 +21,10 @@ struct CPVT_WordInfo { uint16_t Word; int32_t nCharset; - FX_FLOAT fWordX; - FX_FLOAT fWordY; - FX_FLOAT fWordTail; + float fWordX; + float fWordY; + float fWordTail; int32_t nFontIndex; - std::unique_ptr pWordProps; }; #endif // CORE_FPDFDOC_CPVT_WORDINFO_H_ diff --git a/core/fpdfdoc/cpvt_wordplace.h b/core/fpdfdoc/cpvt_wordplace.h index f4a6b087b924e88a2c0a86b1668d5fd833b08881..c0a1a9cd5c393b6b21595ba37565897bc172938f 100644 --- a/core/fpdfdoc/cpvt_wordplace.h +++ b/core/fpdfdoc/cpvt_wordplace.h @@ -14,55 +14,55 @@ struct CPVT_WordPlace { CPVT_WordPlace(int32_t other_nSecIndex, int32_t other_nLineIndex, - int32_t other_nWordIndex) { - nSecIndex = other_nSecIndex; - nLineIndex = other_nLineIndex; - nWordIndex = other_nWordIndex; + int32_t other_nWordIndex) + : nSecIndex(other_nSecIndex), + nLineIndex(other_nLineIndex), + nWordIndex(other_nWordIndex) {} + + void Reset() { + nSecIndex = -1; + nLineIndex = -1; + nWordIndex = -1; } - void Default() { nSecIndex = nLineIndex = nWordIndex = -1; } + void AdvanceSection() { + nSecIndex++; + nLineIndex = 0; + nWordIndex = -1; + } - bool operator==(const CPVT_WordPlace& wp) const { + inline bool operator==(const CPVT_WordPlace& wp) const { return wp.nSecIndex == nSecIndex && wp.nLineIndex == nLineIndex && wp.nWordIndex == nWordIndex; } - - bool operator!=(const CPVT_WordPlace& wp) const { return !(*this == wp); } - - inline int32_t WordCmp(const CPVT_WordPlace& wp) const { - if (nSecIndex > wp.nSecIndex) - return 1; - if (nSecIndex < wp.nSecIndex) - return -1; - if (nLineIndex > wp.nLineIndex) - return 1; - if (nLineIndex < wp.nLineIndex) - return -1; - if (nWordIndex > wp.nWordIndex) - return 1; - if (nWordIndex < wp.nWordIndex) - return -1; - return 0; + inline bool operator!=(const CPVT_WordPlace& wp) const { + return !(*this == wp); } - - inline int32_t LineCmp(const CPVT_WordPlace& wp) const { - if (nSecIndex > wp.nSecIndex) - return 1; - if (nSecIndex < wp.nSecIndex) - return -1; - if (nLineIndex > wp.nLineIndex) - return 1; - if (nLineIndex < wp.nLineIndex) - return -1; - return 0; + inline bool operator<(const CPVT_WordPlace& wp) const { + if (nSecIndex != wp.nSecIndex) + return nSecIndex < wp.nSecIndex; + if (nLineIndex != wp.nLineIndex) + return nLineIndex < wp.nLineIndex; + return nWordIndex < wp.nWordIndex; + } + inline bool operator>(const CPVT_WordPlace& wp) const { + if (nSecIndex != wp.nSecIndex) + return nSecIndex > wp.nSecIndex; + if (nLineIndex != wp.nLineIndex) + return nLineIndex > wp.nLineIndex; + return nWordIndex > wp.nWordIndex; + } + inline bool operator<=(const CPVT_WordPlace& wp) const { + return *this < wp || *this == wp; + } + inline bool operator>=(const CPVT_WordPlace& wp) const { + return *this > wp || *this == wp; } - inline int32_t SecCmp(const CPVT_WordPlace& wp) const { - if (nSecIndex > wp.nSecIndex) - return 1; - if (nSecIndex < wp.nSecIndex) - return -1; - return 0; + inline int32_t LineCmp(const CPVT_WordPlace& wp) const { + if (nSecIndex != wp.nSecIndex) + return nSecIndex - wp.nSecIndex; + return nLineIndex - wp.nLineIndex; } int32_t nSecIndex; diff --git a/core/fpdfdoc/cpvt_wordprops.h b/core/fpdfdoc/cpvt_wordprops.h deleted file mode 100644 index 2b7084116ae416eb4dac0e30ab4b07b62b690a37..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/cpvt_wordprops.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 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 CORE_FPDFDOC_CPVT_WORDPROPS_H_ -#define CORE_FPDFDOC_CPVT_WORDPROPS_H_ - -#include "core/fpdfdoc/cpdf_variabletext.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" - -struct CPVT_WordProps { - CPVT_WordProps() - : nFontIndex(-1), - fFontSize(0.0f), - dwWordColor(0), - nScriptType(CPDF_VariableText::ScriptType::Normal), - nWordStyle(0), - fCharSpace(0.0f), - nHorzScale(0) {} - - CPVT_WordProps(int32_t fontIndex, - FX_FLOAT fontSize, - FX_COLORREF wordColor = 0, - CPDF_VariableText::ScriptType scriptType = - CPDF_VariableText::ScriptType::Normal, - int32_t wordStyle = 0, - FX_FLOAT charSpace = 0, - int32_t horzScale = 100) - : nFontIndex(fontIndex), - fFontSize(fontSize), - dwWordColor(wordColor), - nScriptType(scriptType), - nWordStyle(wordStyle), - fCharSpace(charSpace), - nHorzScale(horzScale) {} - - CPVT_WordProps(const CPVT_WordProps& other) - : nFontIndex(other.nFontIndex), - fFontSize(other.fFontSize), - dwWordColor(other.dwWordColor), - nScriptType(other.nScriptType), - nWordStyle(other.nWordStyle), - fCharSpace(other.fCharSpace), - nHorzScale(other.nHorzScale) {} - - int32_t nFontIndex; - FX_FLOAT fFontSize; - FX_COLORREF dwWordColor; - CPDF_VariableText::ScriptType nScriptType; - int32_t nWordStyle; - FX_FLOAT fCharSpace; - int32_t nHorzScale; -}; - -#endif // CORE_FPDFDOC_CPVT_WORDPROPS_H_ diff --git a/core/fpdfdoc/cpvt_wordrange.h b/core/fpdfdoc/cpvt_wordrange.h index b291e50e53b0f04d65b635f43acac3ce071cb0e5..638f6c17c0fa6dcbf31707079fbe85202f7f0b8c 100644 --- a/core/fpdfdoc/cpvt_wordrange.h +++ b/core/fpdfdoc/cpvt_wordrange.h @@ -7,49 +7,62 @@ #ifndef CORE_FPDFDOC_CPVT_WORDRANGE_H_ #define CORE_FPDFDOC_CPVT_WORDRANGE_H_ +#include +#include + #include "core/fpdfdoc/cpvt_wordplace.h" #include "core/fxcrt/fx_system.h" struct CPVT_WordRange { CPVT_WordRange() {} - CPVT_WordRange(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) { - Set(begin, end); + CPVT_WordRange(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) + : BeginPos(begin), EndPos(end) { + Normalize(); } - void Default() { - BeginPos.Default(); - EndPos.Default(); + void Reset() { + BeginPos.Reset(); + EndPos.Reset(); } void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) { BeginPos = begin; EndPos = end; - SwapWordPlace(); + Normalize(); } void SetBeginPos(const CPVT_WordPlace& begin) { BeginPos = begin; - SwapWordPlace(); + Normalize(); } void SetEndPos(const CPVT_WordPlace& end) { EndPos = end; - SwapWordPlace(); + Normalize(); } - bool IsExist() const { return BeginPos != EndPos; } + CPVT_WordRange Intersect(const CPVT_WordRange& that) const { + if (that.EndPos < BeginPos || that.BeginPos > EndPos || + EndPos < that.BeginPos || BeginPos > that.EndPos) { + return CPVT_WordRange(); + } - bool operator!=(const CPVT_WordRange& wr) const { - return wr.BeginPos != BeginPos || wr.EndPos != EndPos; + return CPVT_WordRange(std::max(BeginPos, that.BeginPos), + std::min(EndPos, that.EndPos)); } - void SwapWordPlace() { - if (BeginPos.WordCmp(EndPos) > 0) { - CPVT_WordPlace place = EndPos; - EndPos = BeginPos; - BeginPos = place; - } + inline bool IsEmpty() const { return BeginPos == EndPos; } + inline bool operator==(const CPVT_WordRange& wr) const { + return wr.BeginPos == BeginPos && wr.EndPos == EndPos; + } + inline bool operator!=(const CPVT_WordRange& wr) const { + return !(*this == wr); + } + + void Normalize() { + if (BeginPos > EndPos) + std::swap(BeginPos, EndPos); } CPVT_WordPlace BeginPos; diff --git a/core/fpdfdoc/csection.cpp b/core/fpdfdoc/csection.cpp index 490ef1b23061955583afa79996af2031a6688ce1..45cbf6bdfc9895b674aba085d606015efe159ef2 100644 --- a/core/fpdfdoc/csection.cpp +++ b/core/fpdfdoc/csection.cpp @@ -9,139 +9,116 @@ #include #include "core/fpdfdoc/cline.h" +#include "core/fpdfdoc/cpdf_variabletext.h" #include "core/fpdfdoc/cpvt_wordinfo.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {} -CSection::~CSection() { - ResetAll(); -} +CSection::~CSection() {} void CSection::ResetAll() { - ResetWordArray(); - ResetLineArray(); -} - -void CSection::ResetLineArray() { - m_LineArray.RemoveAll(); -} - -void CSection::ResetWordArray() { - for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) { - delete m_WordArray.GetAt(i); - } - m_WordArray.RemoveAll(); + m_WordArray.clear(); + m_LineArray.clear(); } void CSection::ResetLinePlace() { - for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) { - if (CLine* pLine = m_LineArray.GetAt(i)) { - pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1); - } + int32_t i = 0; + for (auto& pLine : m_LineArray) { + pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1); + ++i; } } CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place, const CPVT_WordInfo& wordinfo) { - CPVT_WordInfo* pWord = new CPVT_WordInfo(wordinfo); - int32_t nWordIndex = - std::max(std::min(place.nWordIndex, m_WordArray.GetSize()), 0); - if (nWordIndex == m_WordArray.GetSize()) { - m_WordArray.Add(pWord); - } else { - m_WordArray.InsertAt(nWordIndex, pWord); - } + int32_t nWordIndex = pdfium::clamp( + place.nWordIndex, 0, pdfium::CollectionSize(m_WordArray)); + m_WordArray.insert(m_WordArray.begin() + nWordIndex, + pdfium::MakeUnique(wordinfo)); return place; } CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) { - return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1); + m_LineArray.push_back(pdfium::MakeUnique(lineinfo)); + return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.size() - 1, -1); } CPVT_FloatRect CSection::Rearrange() { - if (m_pVT->m_nCharArray > 0) { + if (m_pVT->GetCharArray() > 0) return CTypeset(this).CharArray(); - } return CTypeset(this).Typeset(); } -CFX_SizeF CSection::GetSectionSize(FX_FLOAT fFontSize) { +CFX_SizeF CSection::GetSectionSize(float fFontSize) { return CTypeset(this).GetEditSize(fFontSize); } CPVT_WordPlace CSection::GetBeginWordPlace() const { - if (CLine* pLine = m_LineArray.GetAt(0)) { - return pLine->GetBeginWordPlace(); - } - return SecPlace; + if (m_LineArray.empty()) + return SecPlace; + return m_LineArray.front()->GetBeginWordPlace(); } CPVT_WordPlace CSection::GetEndWordPlace() const { - if (CLine* pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) { - return pLine->GetEndWordPlace(); - } - return SecPlace; + if (m_LineArray.empty()) + return SecPlace; + return m_LineArray.back()->GetEndWordPlace(); } CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const { - if (place.nLineIndex < 0) { + if (place.nLineIndex < 0) return GetBeginWordPlace(); - } - if (place.nLineIndex >= m_LineArray.GetSize()) { + + if (place.nLineIndex >= pdfium::CollectionSize(m_LineArray)) return GetEndWordPlace(); - } - if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) { - if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) { - return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1); - } - if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { - if (CLine* pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) { - return pPrevLine->GetEndWordPlace(); - } - } else { - return pLine->GetPrevWordPlace(place); - } - } - return place; + + CLine* pLine = m_LineArray[place.nLineIndex].get(); + if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) + return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1); + + if (place.nWordIndex >= pLine->m_LineInfo.nBeginWordIndex) + return pLine->GetPrevWordPlace(place); + + if (!pdfium::IndexInBounds(m_LineArray, place.nLineIndex - 1)) + return place; + + return m_LineArray[place.nLineIndex - 1]->GetEndWordPlace(); } CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const { - if (place.nLineIndex < 0) { + if (place.nLineIndex < 0) return GetBeginWordPlace(); - } - if (place.nLineIndex >= m_LineArray.GetSize()) { + + if (place.nLineIndex >= pdfium::CollectionSize(m_LineArray)) return GetEndWordPlace(); - } - if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) { - if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) { - if (CLine* pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) { - return pNextLine->GetBeginWordPlace(); - } - } else { - return pLine->GetNextWordPlace(place); - } - } - return place; + + CLine* pLine = m_LineArray[place.nLineIndex].get(); + if (place.nWordIndex < pLine->m_LineInfo.nEndWordIndex) + return pLine->GetNextWordPlace(place); + + if (!pdfium::IndexInBounds(m_LineArray, place.nLineIndex + 1)) + return place; + + return m_LineArray[place.nLineIndex + 1]->GetBeginWordPlace(); } void CSection::UpdateWordPlace(CPVT_WordPlace& place) const { int32_t nLeft = 0; - int32_t nRight = m_LineArray.GetSize() - 1; + int32_t nRight = pdfium::CollectionSize(m_LineArray) - 1; int32_t nMid = (nLeft + nRight) / 2; while (nLeft <= nRight) { - if (CLine* pLine = m_LineArray.GetAt(nMid)) { - if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { - nRight = nMid - 1; - nMid = (nLeft + nRight) / 2; - } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) { - nLeft = nMid + 1; - nMid = (nLeft + nRight) / 2; - } else { - place.nLineIndex = nMid; - return; - } + CLine* pLine = m_LineArray[nMid].get(); + if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { + nRight = nMid - 1; + nMid = (nLeft + nRight) / 2; + } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) { + nLeft = nMid + 1; + nMid = (nLeft + nRight) / 2; } else { - break; + place.nLineIndex = nMid; + return; } } } @@ -152,61 +129,55 @@ CPVT_WordPlace CSection::SearchWordPlace(const CFX_PointF& point) const { bool bUp = true; bool bDown = true; int32_t nLeft = 0; - int32_t nRight = m_LineArray.GetSize() - 1; - int32_t nMid = m_LineArray.GetSize() / 2; - FX_FLOAT fTop = 0; - FX_FLOAT fBottom = 0; + int32_t nRight = pdfium::CollectionSize(m_LineArray) - 1; + int32_t nMid = pdfium::CollectionSize(m_LineArray) / 2; while (nLeft <= nRight) { - if (CLine* pLine = m_LineArray.GetAt(nMid)) { - fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - - m_pVT->GetLineLeading(m_SecInfo); - fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent; - if (IsFloatBigger(point.y, fTop)) { - bUp = false; - } - if (IsFloatSmaller(point.y, fBottom)) { - bDown = false; - } - if (IsFloatSmaller(point.y, fTop)) { - nRight = nMid - 1; - nMid = (nLeft + nRight) / 2; - continue; - } else if (IsFloatBigger(point.y, fBottom)) { - nLeft = nMid + 1; - nMid = (nLeft + nRight) / 2; - continue; - } else { - place = SearchWordPlace( - point.x, - CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), - pLine->GetEndWordPlace())); - place.nLineIndex = nMid; - return place; - } + CLine* pLine = m_LineArray[nMid].get(); + float fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - + m_pVT->GetLineLeading(); + float fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent; + if (IsFloatBigger(point.y, fTop)) + bUp = false; + if (IsFloatSmaller(point.y, fBottom)) + bDown = false; + if (IsFloatSmaller(point.y, fTop)) { + nRight = nMid - 1; + nMid = (nLeft + nRight) / 2; + continue; + } + if (IsFloatBigger(point.y, fBottom)) { + nLeft = nMid + 1; + nMid = (nLeft + nRight) / 2; + continue; } + place = SearchWordPlace( + point.x, + CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), + pLine->GetEndWordPlace())); + place.nLineIndex = nMid; + return place; } - if (bUp) { + if (bUp) place = GetBeginWordPlace(); - } - if (bDown) { + if (bDown) place = GetEndWordPlace(); - } return place; } CPVT_WordPlace CSection::SearchWordPlace( - FX_FLOAT fx, + float fx, const CPVT_WordPlace& lineplace) const { - if (CLine* pLine = m_LineArray.GetAt(lineplace.nLineIndex)) { - return SearchWordPlace( - fx - m_SecInfo.rcSection.left, - CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), - pLine->GetEndWordPlace())); - } - return GetBeginWordPlace(); + if (!pdfium::IndexInBounds(m_LineArray, lineplace.nLineIndex)) + return GetBeginWordPlace(); + + CLine* pLine = m_LineArray[lineplace.nLineIndex].get(); + return SearchWordPlace( + fx - m_Rect.left, + CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), + pLine->GetEndWordPlace())); } -CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, +CPVT_WordPlace CSection::SearchWordPlace(float fx, const CPVT_WordRange& range) const { CPVT_WordPlace wordplace = range.BeginPos; wordplace.nWordIndex = -1; @@ -217,75 +188,71 @@ CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, int32_t nRight = range.EndPos.nWordIndex + 1; int32_t nMid = (nLeft + nRight) / 2; while (nLeft < nRight) { - if (nMid == nLeft) { + if (nMid == nLeft) break; - } if (nMid == nRight) { nMid--; break; } - if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) { - if (fx > - pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { - nLeft = nMid; - nMid = (nLeft + nRight) / 2; - continue; - } else { - nRight = nMid; - nMid = (nLeft + nRight) / 2; - continue; - } - } else { + if (!pdfium::IndexInBounds(m_WordArray, nMid)) break; + CPVT_WordInfo* pWord = m_WordArray[nMid].get(); + if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { + nLeft = nMid; + nMid = (nLeft + nRight) / 2; + continue; } + nRight = nMid; + nMid = (nLeft + nRight) / 2; } - if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) { - if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { + if (pdfium::IndexInBounds(m_WordArray, nMid)) { + CPVT_WordInfo* pWord = m_WordArray[nMid].get(); + if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) wordplace.nWordIndex = nMid; - } } return wordplace; } void CSection::ClearLeftWords(int32_t nWordIndex) { for (int32_t i = nWordIndex; i >= 0; i--) { - delete m_WordArray.GetAt(i); - m_WordArray.RemoveAt(i); + if (pdfium::IndexInBounds(m_WordArray, i)) + m_WordArray.erase(m_WordArray.begin() + i); } } void CSection::ClearRightWords(int32_t nWordIndex) { - for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) { - delete m_WordArray.GetAt(i); - m_WordArray.RemoveAt(i); + int32_t sz = pdfium::CollectionSize(m_WordArray); + for (int32_t i = sz - 1; i > nWordIndex; i--) { + if (pdfium::IndexInBounds(m_WordArray, i)) + m_WordArray.erase(m_WordArray.begin() + i); } } void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) { for (int32_t i = nEndIndex; i > nBeginIndex; i--) { - delete m_WordArray.GetAt(i); - m_WordArray.RemoveAt(i); + if (pdfium::IndexInBounds(m_WordArray, i)) + m_WordArray.erase(m_WordArray.begin() + i); } } void CSection::ClearWords(const CPVT_WordRange& PlaceRange) { CPVT_WordPlace SecBeginPos = GetBeginWordPlace(); CPVT_WordPlace SecEndPos = GetEndWordPlace(); - if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) { - if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) { + if (PlaceRange.BeginPos >= SecBeginPos) { + if (PlaceRange.EndPos <= SecEndPos) { ClearMidWords(PlaceRange.BeginPos.nWordIndex, PlaceRange.EndPos.nWordIndex); } else { ClearRightWords(PlaceRange.BeginPos.nWordIndex); } - } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) { + } else if (PlaceRange.EndPos <= SecEndPos) { ClearLeftWords(PlaceRange.EndPos.nWordIndex); } else { - ResetWordArray(); + m_WordArray.clear(); } } void CSection::ClearWord(const CPVT_WordPlace& place) { - delete m_WordArray.GetAt(place.nWordIndex); - m_WordArray.RemoveAt(place.nWordIndex); + if (pdfium::IndexInBounds(m_WordArray, place.nWordIndex)) + m_WordArray.erase(m_WordArray.begin() + place.nWordIndex); } diff --git a/core/fpdfdoc/csection.h b/core/fpdfdoc/csection.h index a2ac43b102dcd2b3422f5ec6024f4d4da7aae883..a8ade8624ff1a72e9a12e42df2b9ea5f95eb32e7 100644 --- a/core/fpdfdoc/csection.h +++ b/core/fpdfdoc/csection.h @@ -7,8 +7,12 @@ #ifndef CORE_FPDFDOC_CSECTION_H_ #define CORE_FPDFDOC_CSECTION_H_ -#include "core/fpdfdoc/clines.h" -#include "core/fpdfdoc/cpvt_sectioninfo.h" +#include +#include + +#include "core/fpdfdoc/cline.h" +#include "core/fpdfdoc/cpvt_wordinfo.h" +#include "core/fpdfdoc/cpvt_wordrange.h" #include "core/fpdfdoc/ctypeset.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" @@ -24,8 +28,6 @@ class CSection final { ~CSection(); void ResetAll(); - void ResetLineArray(); - void ResetWordArray(); void ResetLinePlace(); CPVT_WordPlace AddWord(const CPVT_WordPlace& place, const CPVT_WordInfo& wordinfo); @@ -33,22 +35,21 @@ class CSection final { void ClearWords(const CPVT_WordRange& PlaceRange); void ClearWord(const CPVT_WordPlace& place); CPVT_FloatRect Rearrange(); - CFX_SizeF GetSectionSize(FX_FLOAT fFontSize); + CFX_SizeF GetSectionSize(float fFontSize); CPVT_WordPlace GetBeginWordPlace() const; CPVT_WordPlace GetEndWordPlace() const; CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace& place) const; CPVT_WordPlace GetNextWordPlace(const CPVT_WordPlace& place) const; void UpdateWordPlace(CPVT_WordPlace& place) const; CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const; - CPVT_WordPlace SearchWordPlace(FX_FLOAT fx, + CPVT_WordPlace SearchWordPlace(float fx, const CPVT_WordPlace& lineplace) const; - CPVT_WordPlace SearchWordPlace(FX_FLOAT fx, - const CPVT_WordRange& range) const; + CPVT_WordPlace SearchWordPlace(float fx, const CPVT_WordRange& range) const; CPVT_WordPlace SecPlace; - CPVT_SectionInfo m_SecInfo; - CLines m_LineArray; - CPVT_ArrayTemplate m_WordArray; + CPVT_FloatRect m_Rect; + std::vector> m_LineArray; + std::vector> m_WordArray; private: friend class CTypeset; @@ -57,7 +58,7 @@ class CSection final { void ClearRightWords(int32_t nWordIndex); void ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex); - CPDF_VariableText* const m_pVT; + UnownedPtr const m_pVT; }; #endif // CORE_FPDFDOC_CSECTION_H_ diff --git a/core/fpdfdoc/ctypeset.cpp b/core/fpdfdoc/ctypeset.cpp index 452143e68255ddfc682c050f4b49013d5006c58e..290b95e9b4d8c15ee6bda41074f17d9d837a8a70 100644 --- a/core/fpdfdoc/ctypeset.cpp +++ b/core/fpdfdoc/ctypeset.cpp @@ -9,8 +9,10 @@ #include #include "core/fpdfdoc/cline.h" +#include "core/fpdfdoc/cpdf_variabletext.h" #include "core/fpdfdoc/cpvt_wordinfo.h" #include "core/fpdfdoc/csection.h" +#include "third_party/base/stl_util.h" namespace { @@ -179,83 +181,86 @@ CTypeset::CTypeset(CSection* pSection) CTypeset::~CTypeset() {} CPVT_FloatRect CTypeset::CharArray() { - ASSERT(m_pSection); - FX_FLOAT fLineAscent = + m_rcRet = CPVT_FloatRect(0, 0, 0, 0); + if (m_pSection->m_LineArray.empty()) + return m_rcRet; + + float fNodeWidth = m_pVT->GetPlateWidth() / + (m_pVT->GetCharArray() <= 0 ? 1 : m_pVT->GetCharArray()); + float fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize()); - FX_FLOAT fLineDescent = + float fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize()); - m_rcRet.Default(); - FX_FLOAT x = 0.0f, y = 0.0f; - FX_FLOAT fNextWidth; + float x = 0.0f; + float y = m_pVT->GetLineLeading() + fLineAscent; int32_t nStart = 0; - FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() / - (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray); - if (CLine* pLine = m_pSection->m_LineArray.GetAt(0)) { - x = 0.0f; - y += m_pVT->GetLineLeading(m_pSection->m_SecInfo); - y += fLineAscent; - nStart = 0; - switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) { - case 0: - pLine->m_LineInfo.fLineX = fNodeWidth * VARIABLETEXT_HALF; - break; - case 1: - nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2; - pLine->m_LineInfo.fLineX = - fNodeWidth * nStart - fNodeWidth * VARIABLETEXT_HALF; - break; - case 2: - nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize(); - pLine->m_LineInfo.fLineX = - fNodeWidth * nStart - fNodeWidth * VARIABLETEXT_HALF; - break; + CLine* pLine = m_pSection->m_LineArray.front().get(); + switch (m_pVT->GetAlignment()) { + case 0: + pLine->m_LineInfo.fLineX = fNodeWidth * VARIABLETEXT_HALF; + break; + case 1: + nStart = (m_pVT->GetCharArray() - + pdfium::CollectionSize(m_pSection->m_WordArray)) / + 2; + pLine->m_LineInfo.fLineX = + fNodeWidth * nStart - fNodeWidth * VARIABLETEXT_HALF; + break; + case 2: + nStart = m_pVT->GetCharArray() - + pdfium::CollectionSize(m_pSection->m_WordArray); + pLine->m_LineInfo.fLineX = + fNodeWidth * nStart - fNodeWidth * VARIABLETEXT_HALF; + break; + } + for (int32_t w = 0, + sz = pdfium::CollectionSize(m_pSection->m_WordArray); + w < sz; w++) { + if (w >= m_pVT->GetCharArray()) + break; + + float fNextWidth = 0; + if (pdfium::IndexInBounds(m_pSection->m_WordArray, w + 1)) { + CPVT_WordInfo* pNextWord = m_pSection->m_WordArray[w + 1].get(); + pNextWord->fWordTail = 0; + fNextWidth = m_pVT->GetWordWidth(*pNextWord); } - for (int32_t w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) { - if (w >= m_pVT->m_nCharArray) { - break; - } - fNextWidth = 0; - if (CPVT_WordInfo* pNextWord = m_pSection->m_WordArray.GetAt(w + 1)) { - pNextWord->fWordTail = 0; - fNextWidth = m_pVT->GetWordWidth(*pNextWord); - } - if (CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(w)) { - pWord->fWordTail = 0; - FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord); - FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord); - FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord); - x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - - fWordWidth * VARIABLETEXT_HALF); - pWord->fWordX = x; - pWord->fWordY = y; - if (w == 0) { - pLine->m_LineInfo.fLineX = x; - } - if (w != m_pSection->m_WordArray.GetSize() - 1) { - pWord->fWordTail = - (fNodeWidth - (fWordWidth + fNextWidth) * VARIABLETEXT_HALF > 0 - ? fNodeWidth - (fWordWidth + fNextWidth) * VARIABLETEXT_HALF - : 0); - } else { - pWord->fWordTail = 0; - } - x += fWordWidth; - fLineAscent = std::max(fLineAscent, fWordAscent); - fLineDescent = std::min(fLineDescent, fWordDescent); - } + CPVT_WordInfo* pWord = m_pSection->m_WordArray[w].get(); + pWord->fWordTail = 0; + float fWordWidth = m_pVT->GetWordWidth(*pWord); + float fWordAscent = m_pVT->GetWordAscent(*pWord); + float fWordDescent = m_pVT->GetWordDescent(*pWord); + x = (float)(fNodeWidth * (w + nStart + 0.5) - + fWordWidth * VARIABLETEXT_HALF); + pWord->fWordX = x; + pWord->fWordY = y; + if (w == 0) { + pLine->m_LineInfo.fLineX = x; + } + if (w != pdfium::CollectionSize(m_pSection->m_WordArray) - 1) { + pWord->fWordTail = + (fNodeWidth - (fWordWidth + fNextWidth) * VARIABLETEXT_HALF > 0 + ? fNodeWidth - (fWordWidth + fNextWidth) * VARIABLETEXT_HALF + : 0); + } else { + pWord->fWordTail = 0; } - pLine->m_LineInfo.nBeginWordIndex = 0; - pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1; - pLine->m_LineInfo.fLineY = y; - pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX; - pLine->m_LineInfo.fLineAscent = fLineAscent; - pLine->m_LineInfo.fLineDescent = fLineDescent; - y -= fLineDescent; + x += fWordWidth; + fLineAscent = std::max(fLineAscent, fWordAscent); + fLineDescent = std::min(fLineDescent, fWordDescent); } - return m_rcRet = CPVT_FloatRect(0, 0, x, y); + pLine->m_LineInfo.nBeginWordIndex = 0; + pLine->m_LineInfo.nEndWordIndex = + pdfium::CollectionSize(m_pSection->m_WordArray) - 1; + pLine->m_LineInfo.fLineY = y; + pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX; + pLine->m_LineInfo.fLineAscent = fLineAscent; + pLine->m_LineInfo.fLineDescent = fLineDescent; + m_rcRet = CPVT_FloatRect(0, 0, x, y - fLineDescent); + return m_rcRet; } -CFX_SizeF CTypeset::GetEditSize(FX_FLOAT fFontSize) { +CFX_SizeF CTypeset::GetEditSize(float fFontSize) { ASSERT(m_pSection); ASSERT(m_pVT); SplitLines(false, fFontSize); @@ -264,40 +269,39 @@ CFX_SizeF CTypeset::GetEditSize(FX_FLOAT fFontSize) { CPVT_FloatRect CTypeset::Typeset() { ASSERT(m_pVT); - m_pSection->m_LineArray.Empty(); + m_pSection->m_LineArray.clear(); SplitLines(true, 0.0f); - m_pSection->m_LineArray.Clear(); OutputLines(); return m_rcRet; } -void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { +void CTypeset::SplitLines(bool bTypeset, float fFontSize) { ASSERT(m_pVT); ASSERT(m_pSection); int32_t nLineHead = 0; int32_t nLineTail = 0; - FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f; - FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f; - FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f; - FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f; + float fMaxX = 0.0f, fMaxY = 0.0f; + float fLineWidth = 0.0f, fBackupLineWidth = 0.0f; + float fLineAscent = 0.0f, fBackupLineAscent = 0.0f; + float fLineDescent = 0.0f, fBackupLineDescent = 0.0f; int32_t nWordStartPos = 0; bool bFullWord = false; int32_t nLineFullWordIndex = 0; int32_t nCharIndex = 0; CPVT_LineInfo line; - FX_FLOAT fWordWidth = 0; - FX_FLOAT fTypesetWidth = std::max( - m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo), - 0.0f); - int32_t nTotalWords = m_pSection->m_WordArray.GetSize(); + float fWordWidth = 0; + float fTypesetWidth = + std::max(m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(), 0.0f); + int32_t nTotalWords = + pdfium::CollectionSize(m_pSection->m_WordArray); bool bOpened = false; if (nTotalWords > 0) { int32_t i = 0; while (i < nTotalWords) { - CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(i); + CPVT_WordInfo* pWord = m_pSection->m_WordArray[i].get(); CPVT_WordInfo* pOldWord = pWord; if (i > 0) { - pOldWord = m_pSection->m_WordArray.GetAt(i - 1); + pOldWord = m_pSection->m_WordArray[i - 1].get(); } if (pWord) { if (bTypeset) { @@ -310,8 +314,8 @@ void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { fLineDescent = std::min(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize)); fWordWidth = m_pVT->GetWordWidth( - pWord->nFontIndex, pWord->Word, m_pVT->m_wSubWord, - m_pVT->m_fCharSpace, m_pVT->m_nHorzScale, fFontSize, + pWord->nFontIndex, pWord->Word, m_pVT->GetSubWord(), + m_pVT->GetCharSpace(), m_pVT->GetHorzScale(), fFontSize, pWord->fWordTail); } if (!bOpened) { @@ -340,7 +344,7 @@ void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { } nCharIndex++; } - if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 && + if (m_pVT->IsAutoReturn() && fTypesetWidth > 0 && fLineWidth + fWordWidth > fTypesetWidth) { if (nLineFullWordIndex > 0) { i = nWordStartPos; @@ -362,7 +366,7 @@ void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { line.fLineDescent = fLineDescent; m_pSection->AddLine(line); } - fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo)); + fMaxY += (fLineAscent + m_pVT->GetLineLeading()); fMaxY -= fLineDescent; fMaxX = std::max(fLineWidth, fMaxX); nLineHead = i; @@ -388,14 +392,14 @@ void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { line.fLineDescent = fLineDescent; m_pSection->AddLine(line); } - fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo)); + fMaxY += (fLineAscent + m_pVT->GetLineLeading()); fMaxY -= fLineDescent; fMaxX = std::max(fLineWidth, fMaxX); } } else { if (bTypeset) { - fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo); - fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo); + fLineAscent = m_pVT->GetLineAscent(); + fLineDescent = m_pVT->GetLineDescent(); } else { fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize); @@ -411,8 +415,7 @@ void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { line.fLineDescent = fLineDescent; m_pSection->AddLine(line); } - fMaxY += m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent - - fLineDescent; + fMaxY += m_pVT->GetLineLeading() + fLineAscent - fLineDescent; } m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY); } @@ -420,11 +423,11 @@ void CTypeset::SplitLines(bool bTypeset, FX_FLOAT fFontSize) { void CTypeset::OutputLines() { ASSERT(m_pVT); ASSERT(m_pSection); - FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f; - FX_FLOAT fPosX = 0.0f, fPosY = 0.0f; - FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo); - FX_FLOAT fTypesetWidth = std::max(m_pVT->GetPlateWidth() - fLineIndent, 0.0f); - switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) { + float fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f; + float fPosX = 0.0f, fPosY = 0.0f; + float fLineIndent = m_pVT->GetLineIndent(); + float fTypesetWidth = std::max(m_pVT->GetPlateWidth() - fLineIndent, 0.0f); + switch (m_pVT->GetAlignment()) { default: case 0: fMinX = 0.0f; @@ -439,54 +442,40 @@ void CTypeset::OutputLines() { fMaxX = fMinX + m_rcRet.Width(); fMinY = 0.0f; fMaxY = m_rcRet.Height(); - int32_t nTotalLines = m_pSection->m_LineArray.GetSize(); + int32_t nTotalLines = + pdfium::CollectionSize(m_pSection->m_LineArray); if (nTotalLines > 0) { - m_pSection->m_SecInfo.nTotalLine = nTotalLines; for (int32_t l = 0; l < nTotalLines; l++) { - if (CLine* pLine = m_pSection->m_LineArray.GetAt(l)) { - switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) { - default: - case 0: - fPosX = 0; - break; - case 1: - fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * - VARIABLETEXT_HALF; - break; - case 2: - fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth; - break; - } - fPosX += fLineIndent; - fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo); - fPosY += pLine->m_LineInfo.fLineAscent; - pLine->m_LineInfo.fLineX = fPosX - fMinX; - pLine->m_LineInfo.fLineY = fPosY - fMinY; - for (int32_t w = pLine->m_LineInfo.nBeginWordIndex; - w <= pLine->m_LineInfo.nEndWordIndex; w++) { - if (CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(w)) { - pWord->fWordX = fPosX - fMinX; - if (pWord->pWordProps) { - switch (pWord->pWordProps->nScriptType) { - default: - case CPDF_VariableText::ScriptType::Normal: - pWord->fWordY = fPosY - fMinY; - break; - case CPDF_VariableText::ScriptType::Super: - pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY; - break; - case CPDF_VariableText::ScriptType::Sub: - pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY; - break; - } - } else { - pWord->fWordY = fPosY - fMinY; - } - fPosX += m_pVT->GetWordWidth(*pWord); - } + CLine* pLine = m_pSection->m_LineArray[l].get(); + switch (m_pVT->GetAlignment()) { + default: + case 0: + fPosX = 0; + break; + case 1: + fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * + VARIABLETEXT_HALF; + break; + case 2: + fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth; + break; + } + fPosX += fLineIndent; + fPosY += m_pVT->GetLineLeading(); + fPosY += pLine->m_LineInfo.fLineAscent; + pLine->m_LineInfo.fLineX = fPosX - fMinX; + pLine->m_LineInfo.fLineY = fPosY - fMinY; + for (int32_t w = pLine->m_LineInfo.nBeginWordIndex; + w <= pLine->m_LineInfo.nEndWordIndex; w++) { + if (pdfium::IndexInBounds(m_pSection->m_WordArray, w)) { + CPVT_WordInfo* pWord = m_pSection->m_WordArray[w].get(); + pWord->fWordX = fPosX - fMinX; + pWord->fWordY = fPosY - fMinY; + + fPosX += m_pVT->GetWordWidth(*pWord); } - fPosY -= pLine->m_LineInfo.fLineDescent; } + fPosY -= pLine->m_LineInfo.fLineDescent; } } m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY); diff --git a/core/fpdfdoc/ctypeset.h b/core/fpdfdoc/ctypeset.h index 4161c03b426001a25805c0e1b4482676e9bf65dc..3d56a3b0926c6be0de9fde3f1ac5b61e8f2cbfe2 100644 --- a/core/fpdfdoc/ctypeset.h +++ b/core/fpdfdoc/ctypeset.h @@ -9,6 +9,7 @@ #include "core/fpdfdoc/cpvt_floatrect.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_VariableText; class CSection; @@ -18,16 +19,16 @@ class CTypeset final { explicit CTypeset(CSection* pSection); ~CTypeset(); - CFX_SizeF GetEditSize(FX_FLOAT fFontSize); + CFX_SizeF GetEditSize(float fFontSize); CPVT_FloatRect Typeset(); CPVT_FloatRect CharArray(); private: - void SplitLines(bool bTypeset, FX_FLOAT fFontSize); + void SplitLines(bool bTypeset, float fFontSize); void OutputLines(); CPVT_FloatRect m_rcRet; - CPDF_VariableText* const m_pVT; + UnownedPtr const m_pVT; CSection* const m_pSection; }; diff --git a/core/fpdfdoc/doc_tagged.cpp b/core/fpdfdoc/doc_tagged.cpp deleted file mode 100644 index af5cf8593823557e53ecde0423271456d5c8b651..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/doc_tagged.cpp +++ /dev/null @@ -1,418 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include -#include - -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_name.h" -#include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_reference.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfdoc/cpdf_numbertree.h" -#include "core/fpdfdoc/fpdf_tagged.h" -#include "core/fpdfdoc/tagged_int.h" -#include "third_party/base/ptr_util.h" - -namespace { - -const int nMaxRecursion = 32; - -bool IsTagged(const CPDF_Document* pDoc) { - CPDF_Dictionary* pCatalog = pDoc->GetRoot(); - CPDF_Dictionary* pMarkInfo = pCatalog->GetDictFor("MarkInfo"); - return pMarkInfo && pMarkInfo->GetIntegerFor("Marked"); -} - -} // namespace - -CPDF_StructKid::CPDF_StructKid() - : m_Type(Invalid), - m_pDict(nullptr), - m_PageObjNum(0), - m_RefObjNum(0), - m_ContentId(0) {} - -CPDF_StructKid::CPDF_StructKid(const CPDF_StructKid& that) = default; - -CPDF_StructKid::~CPDF_StructKid() {} - -// static -std::unique_ptr IPDF_StructTree::LoadPage( - const CPDF_Document* pDoc, - const CPDF_Dictionary* pPageDict) { - if (!IsTagged(pDoc)) - return nullptr; - - auto pTree = pdfium::MakeUnique(pDoc); - pTree->LoadPageTree(pPageDict); - return std::move(pTree); -} - -CPDF_StructTree::CPDF_StructTree(const CPDF_Document* pDoc) - : m_pTreeRoot(pDoc->GetRoot()->GetDictFor("StructTreeRoot")), - m_pRoleMap(m_pTreeRoot ? m_pTreeRoot->GetDictFor("RoleMap") : nullptr), - m_pPage(nullptr) {} - -CPDF_StructTree::~CPDF_StructTree() {} - -int CPDF_StructTree::CountTopElements() const { - return pdfium::CollectionSize(m_Kids); -} - -IPDF_StructElement* CPDF_StructTree::GetTopElement(int i) const { - return m_Kids[i].Get(); -} - -void CPDF_StructTree::LoadPageTree(const CPDF_Dictionary* pPageDict) { - m_pPage = pPageDict; - if (!m_pTreeRoot) - return; - - CPDF_Object* pKids = m_pTreeRoot->GetDirectObjectFor("K"); - if (!pKids) - return; - - uint32_t dwKids = 0; - if (pKids->IsDictionary()) - dwKids = 1; - else if (CPDF_Array* pArray = pKids->AsArray()) - dwKids = pArray->GetCount(); - else - return; - - m_Kids.clear(); - m_Kids.resize(dwKids); - CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDictFor("ParentTree"); - if (!pParentTree) - return; - - CPDF_NumberTree parent_tree(pParentTree); - int parents_id = pPageDict->GetIntegerFor("StructParents", -1); - if (parents_id < 0) - return; - - CPDF_Array* pParentArray = ToArray(parent_tree.LookupValue(parents_id)); - if (!pParentArray) - return; - - std::map> element_map; - for (size_t i = 0; i < pParentArray->GetCount(); i++) { - if (CPDF_Dictionary* pParent = pParentArray->GetDictAt(i)) - AddPageNode(pParent, &element_map); - } -} - -CFX_RetainPtr CPDF_StructTree::AddPageNode( - CPDF_Dictionary* pDict, - std::map>* map, - int nLevel) { - if (nLevel > nMaxRecursion) - return nullptr; - - auto it = map->find(pDict); - if (it != map->end()) - return it->second; - - auto pElement = pdfium::MakeRetain(this, nullptr, pDict); - (*map)[pDict] = pElement; - CPDF_Dictionary* pParent = pDict->GetDictFor("P"); - if (!pParent || pParent->GetStringFor("Type") == "StructTreeRoot") { - if (!AddTopLevelNode(pDict, pElement)) - map->erase(pDict); - return pElement; - } - - CFX_RetainPtr pParentElement = - AddPageNode(pParent, map, nLevel + 1); - bool bSave = false; - for (CPDF_StructKid& kid : *pParentElement->GetKids()) { - if (kid.m_Type == CPDF_StructKid::Element && kid.m_pDict == pDict) { - kid.m_pElement = pElement; - bSave = true; - } - } - if (!bSave) - map->erase(pDict); - return pElement; -} - -bool CPDF_StructTree::AddTopLevelNode( - CPDF_Dictionary* pDict, - const CFX_RetainPtr& pElement) { - CPDF_Object* pObj = m_pTreeRoot->GetDirectObjectFor("K"); - if (!pObj) - return false; - - if (pObj->IsDictionary()) { - if (pObj->GetObjNum() != pDict->GetObjNum()) - return false; - m_Kids[0] = pElement; - } - if (CPDF_Array* pTopKids = pObj->AsArray()) { - bool bSave = false; - for (size_t i = 0; i < pTopKids->GetCount(); i++) { - CPDF_Reference* pKidRef = ToReference(pTopKids->GetObjectAt(i)); - if (pKidRef && pKidRef->GetRefObjNum() == pDict->GetObjNum()) { - m_Kids[i] = pElement; - bSave = true; - } - } - if (!bSave) - return false; - } - return true; -} - -CPDF_StructElement::CPDF_StructElement(CPDF_StructTree* pTree, - CPDF_StructElement* pParent, - CPDF_Dictionary* pDict) - : m_pTree(pTree), - m_pParent(pParent), - m_pDict(pDict), - m_Type(pDict->GetStringFor("S")) { - if (pTree->m_pRoleMap) { - CFX_ByteString mapped = pTree->m_pRoleMap->GetStringFor(m_Type); - if (!mapped.IsEmpty()) - m_Type = mapped; - } - LoadKids(pDict); -} - -IPDF_StructTree* CPDF_StructElement::GetTree() const { - return m_pTree; -} - -const CFX_ByteString& CPDF_StructElement::GetType() const { - return m_Type; -} - -IPDF_StructElement* CPDF_StructElement::GetParent() const { - return m_pParent; -} - -CPDF_Dictionary* CPDF_StructElement::GetDict() const { - return m_pDict; -} - -int CPDF_StructElement::CountKids() const { - return pdfium::CollectionSize(m_Kids); -} - -IPDF_StructElement* CPDF_StructElement::GetKidIfElement(int index) const { - if (m_Kids[index].m_Type != CPDF_StructKid::Element) - return nullptr; - - return m_Kids[index].m_pElement.Get(); -} - -CPDF_StructElement::~CPDF_StructElement() {} - -void CPDF_StructElement::LoadKids(CPDF_Dictionary* pDict) { - CPDF_Object* pObj = pDict->GetObjectFor("Pg"); - uint32_t PageObjNum = 0; - if (CPDF_Reference* pRef = ToReference(pObj)) - PageObjNum = pRef->GetRefObjNum(); - - CPDF_Object* pKids = pDict->GetDirectObjectFor("K"); - if (!pKids) - return; - - m_Kids.clear(); - if (CPDF_Array* pArray = pKids->AsArray()) { - m_Kids.resize(pArray->GetCount()); - for (uint32_t i = 0; i < pArray->GetCount(); i++) { - CPDF_Object* pKid = pArray->GetDirectObjectAt(i); - LoadKid(PageObjNum, pKid, &m_Kids[i]); - } - } else { - m_Kids.resize(1); - LoadKid(PageObjNum, pKids, &m_Kids[0]); - } -} -void CPDF_StructElement::LoadKid(uint32_t PageObjNum, - CPDF_Object* pKidObj, - CPDF_StructKid* pKid) { - pKid->m_Type = CPDF_StructKid::Invalid; - if (!pKidObj) - return; - - if (pKidObj->IsNumber()) { - if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) { - return; - } - pKid->m_Type = CPDF_StructKid::PageContent; - pKid->m_ContentId = pKidObj->GetInteger(); - pKid->m_PageObjNum = PageObjNum; - return; - } - - CPDF_Dictionary* pKidDict = pKidObj->AsDictionary(); - if (!pKidDict) - return; - - if (CPDF_Reference* pRef = ToReference(pKidDict->GetObjectFor("Pg"))) - PageObjNum = pRef->GetRefObjNum(); - - CFX_ByteString type = pKidDict->GetStringFor("Type"); - if (type == "MCR") { - if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) { - return; - } - pKid->m_Type = CPDF_StructKid::StreamContent; - CPDF_Reference* pRef = ToReference(pKidDict->GetObjectFor("Stm")); - pKid->m_RefObjNum = pRef ? pRef->GetRefObjNum() : 0; - pKid->m_PageObjNum = PageObjNum; - pKid->m_ContentId = pKidDict->GetIntegerFor("MCID"); - } else if (type == "OBJR") { - if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) { - return; - } - pKid->m_Type = CPDF_StructKid::Object; - CPDF_Reference* pObj = ToReference(pKidDict->GetObjectFor("Obj")); - pKid->m_RefObjNum = pObj ? pObj->GetRefObjNum() : 0; - pKid->m_PageObjNum = PageObjNum; - } else { - pKid->m_Type = CPDF_StructKid::Element; - pKid->m_pDict = pKidDict; - if (!m_pTree->m_pPage) { - pKid->m_pElement = - pdfium::MakeRetain(m_pTree, this, pKidDict); - } else { - pKid->m_pElement = nullptr; - } - } -} -static CPDF_Dictionary* FindAttrDict(CPDF_Object* pAttrs, - const CFX_ByteStringC& owner, - FX_FLOAT nLevel = 0.0F) { - if (nLevel > nMaxRecursion) - return nullptr; - if (!pAttrs) - return nullptr; - - CPDF_Dictionary* pDict = nullptr; - if (pAttrs->IsDictionary()) { - pDict = pAttrs->AsDictionary(); - } else if (CPDF_Stream* pStream = pAttrs->AsStream()) { - pDict = pStream->GetDict(); - } else if (CPDF_Array* pArray = pAttrs->AsArray()) { - for (uint32_t i = 0; i < pArray->GetCount(); i++) { - CPDF_Object* pElement = pArray->GetDirectObjectAt(i); - pDict = FindAttrDict(pElement, owner, nLevel + 1); - if (pDict) - return pDict; - } - } - if (pDict && pDict->GetStringFor("O") == owner) - return pDict; - return nullptr; -} -CPDF_Object* CPDF_StructElement::GetAttr(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - bool bInheritable, - FX_FLOAT fLevel) { - if (fLevel > nMaxRecursion) { - return nullptr; - } - if (bInheritable) { - CPDF_Object* pAttr = GetAttr(owner, name, false); - if (pAttr) { - return pAttr; - } - if (!m_pParent) { - return nullptr; - } - return m_pParent->GetAttr(owner, name, true, fLevel + 1); - } - CPDF_Object* pA = m_pDict->GetDirectObjectFor("A"); - if (pA) { - CPDF_Dictionary* pAttrDict = FindAttrDict(pA, owner); - if (pAttrDict) { - CPDF_Object* pAttr = pAttrDict->GetDirectObjectFor(CFX_ByteString(name)); - if (pAttr) { - return pAttr; - } - } - } - CPDF_Object* pC = m_pDict->GetDirectObjectFor("C"); - if (!pC) - return nullptr; - - CPDF_Dictionary* pClassMap = m_pTree->m_pTreeRoot->GetDictFor("ClassMap"); - if (!pClassMap) - return nullptr; - - if (CPDF_Array* pArray = pC->AsArray()) { - for (uint32_t i = 0; i < pArray->GetCount(); i++) { - CFX_ByteString class_name = pArray->GetStringAt(i); - CPDF_Dictionary* pClassDict = pClassMap->GetDictFor(class_name); - if (pClassDict && pClassDict->GetStringFor("O") == owner) - return pClassDict->GetDirectObjectFor(CFX_ByteString(name)); - } - return nullptr; - } - CFX_ByteString class_name = pC->GetString(); - CPDF_Dictionary* pClassDict = pClassMap->GetDictFor(class_name); - if (pClassDict && pClassDict->GetStringFor("O") == owner) - return pClassDict->GetDirectObjectFor(CFX_ByteString(name)); - return nullptr; -} -CPDF_Object* CPDF_StructElement::GetAttr(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - bool bInheritable, - int subindex) { - CPDF_Object* pAttr = GetAttr(owner, name, bInheritable); - CPDF_Array* pArray = ToArray(pAttr); - if (!pArray || subindex == -1) - return pAttr; - - if (subindex >= static_cast(pArray->GetCount())) - return pAttr; - return pArray->GetDirectObjectAt(subindex); -} -CFX_ByteString CPDF_StructElement::GetName(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - const CFX_ByteStringC& default_value, - bool bInheritable, - int subindex) { - CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex); - if (ToName(pAttr)) - return pAttr->GetString(); - return CFX_ByteString(default_value); -} - -FX_ARGB CPDF_StructElement::GetColor(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - FX_ARGB default_value, - bool bInheritable, - int subindex) { - CPDF_Array* pArray = ToArray(GetAttr(owner, name, bInheritable, subindex)); - if (!pArray) - return default_value; - return 0xff000000 | ((int)(pArray->GetNumberAt(0) * 255) << 16) | - ((int)(pArray->GetNumberAt(1) * 255) << 8) | - (int)(pArray->GetNumberAt(2) * 255); -} -FX_FLOAT CPDF_StructElement::GetNumber(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - FX_FLOAT default_value, - bool bInheritable, - int subindex) { - CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex); - return ToNumber(pAttr) ? pAttr->GetNumber() : default_value; -} -int CPDF_StructElement::GetInteger(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - int default_value, - bool bInheritable, - int subindex) { - CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex); - return ToNumber(pAttr) ? pAttr->GetInteger() : default_value; -} diff --git a/core/fpdfdoc/fpdf_tagged.h b/core/fpdfdoc/fpdf_tagged.h deleted file mode 100644 index fbbb49f85680f849c6e7ce17570f542c0bf907d5..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/fpdf_tagged.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FPDFDOC_FPDF_TAGGED_H_ -#define CORE_FPDFDOC_FPDF_TAGGED_H_ - -#include - -#include "core/fxge/fx_dib.h" - -class CPDF_Dictionary; -class CPDF_Document; -class IPDF_StructElement; - -class IPDF_StructTree { - public: - static std::unique_ptr LoadPage( - const CPDF_Document* pDoc, - const CPDF_Dictionary* pPageDict); - - - virtual int CountTopElements() const = 0; - virtual IPDF_StructElement* GetTopElement(int i) const = 0; - - protected: - friend std::default_delete; - virtual ~IPDF_StructTree() {} -}; - -class IPDF_StructElement { - public: - virtual IPDF_StructTree* GetTree() const = 0; - virtual const CFX_ByteString& GetType() const = 0; - virtual IPDF_StructElement* GetParent() const = 0; - virtual CPDF_Dictionary* GetDict() const = 0; - virtual int CountKids() const = 0; - virtual IPDF_StructElement* GetKidIfElement(int index) const = 0; - - virtual CPDF_Object* GetAttr(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - bool bInheritable = false, - FX_FLOAT fLevel = 0.0F) = 0; - - virtual CFX_ByteString GetName(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - const CFX_ByteStringC& default_value, - bool bInheritable = false, - int subindex = -1) = 0; - - virtual FX_ARGB GetColor(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - FX_ARGB default_value, - bool bInheritable = false, - int subindex = -1) = 0; - - virtual FX_FLOAT GetNumber(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - FX_FLOAT default_value, - bool bInheritable = false, - int subindex = -1) = 0; - - virtual int GetInteger(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - int default_value, - bool bInheritable = false, - int subindex = -1) = 0; - - protected: - virtual ~IPDF_StructElement() {} -}; - -#endif // CORE_FPDFDOC_FPDF_TAGGED_H_ diff --git a/core/fpdfdoc/ipdf_formnotify.h b/core/fpdfdoc/ipdf_formnotify.h index bf6127dce29ab5ef5e52f9979f37600b8ce3ea08..52e5cc96aa81562a47e2ae36a467cb3b0eec2604 100644 --- a/core/fpdfdoc/ipdf_formnotify.h +++ b/core/fpdfdoc/ipdf_formnotify.h @@ -17,10 +17,10 @@ class IPDF_FormNotify { virtual ~IPDF_FormNotify() {} virtual int BeforeValueChange(CPDF_FormField* pField, - const CFX_WideString& csValue) = 0; + const WideString& csValue) = 0; virtual void AfterValueChange(CPDF_FormField* pField) = 0; virtual int BeforeSelectionChange(CPDF_FormField* pField, - const CFX_WideString& csValue) = 0; + const WideString& csValue) = 0; virtual void AfterSelectionChange(CPDF_FormField* pField) = 0; virtual void AfterCheckedStatusChange(CPDF_FormField* pField) = 0; virtual int BeforeFormReset(CPDF_InterForm* pForm) = 0; diff --git a/core/fpdfdoc/ipvt_fontmap.h b/core/fpdfdoc/ipvt_fontmap.h index 740cb19eb8c9326217dc5d02d2cadda369116930..31aa73b8a14464e436a94268cd695b7636457b72 100644 --- a/core/fpdfdoc/ipvt_fontmap.h +++ b/core/fpdfdoc/ipvt_fontmap.h @@ -18,7 +18,7 @@ class IPVT_FontMap { virtual ~IPVT_FontMap() {} virtual CPDF_Font* GetPDFFont(int32_t nFontIndex) = 0; - virtual CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) = 0; + virtual ByteString GetPDFFontAlias(int32_t nFontIndex) = 0; virtual int32_t GetWordFontIndex(uint16_t word, int32_t charset, int32_t nFontIndex) = 0; diff --git a/core/fpdfdoc/tagged_int.h b/core/fpdfdoc/tagged_int.h deleted file mode 100644 index ce246023dfc72fc9bcb08119d2d201117ba50f1e..0000000000000000000000000000000000000000 --- a/core/fpdfdoc/tagged_int.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FPDFDOC_TAGGED_INT_H_ -#define CORE_FPDFDOC_TAGGED_INT_H_ - -#include -#include -#include - -#include "core/fpdfdoc/fpdf_tagged.h" -#include "core/fxcrt/cfx_retain_ptr.h" -#include "third_party/base/stl_util.h" - -class CPDF_StructElement; - -struct CPDF_StructKid { - CPDF_StructKid(); - CPDF_StructKid(const CPDF_StructKid& that); - ~CPDF_StructKid(); - - enum { Invalid, Element, PageContent, StreamContent, Object } m_Type; - - CFX_RetainPtr m_pElement; // For Element. - CPDF_Dictionary* m_pDict; // For Element. - uint32_t m_PageObjNum; // For PageContent, StreamContent, Object. - uint32_t m_RefObjNum; // For StreamContent, Object. - uint32_t m_ContentId; // For PageContent, StreamContent. -}; - -class CPDF_StructTree final : public IPDF_StructTree { - public: - explicit CPDF_StructTree(const CPDF_Document* pDoc); - ~CPDF_StructTree() override; - - // IPDF_StructTree: - int CountTopElements() const override; - IPDF_StructElement* GetTopElement(int i) const override; - - void LoadPageTree(const CPDF_Dictionary* pPageDict); - CFX_RetainPtr AddPageNode( - CPDF_Dictionary* pElement, - std::map>* map, - int nLevel = 0); - bool AddTopLevelNode(CPDF_Dictionary* pDict, - const CFX_RetainPtr& pElement); - - protected: - const CPDF_Dictionary* const m_pTreeRoot; - const CPDF_Dictionary* const m_pRoleMap; - const CPDF_Dictionary* m_pPage; - std::vector> m_Kids; - - friend class CPDF_StructElement; -}; - -class CPDF_StructElement final : public CFX_Retainable, - public IPDF_StructElement { - public: - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - // IPDF_StructElement - IPDF_StructTree* GetTree() const override; - const CFX_ByteString& GetType() const override; - IPDF_StructElement* GetParent() const override; - CPDF_Dictionary* GetDict() const override; - int CountKids() const override; - IPDF_StructElement* GetKidIfElement(int index) const override; - CPDF_Object* GetAttr(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - bool bInheritable = false, - FX_FLOAT fLevel = 0.0F) override; - CFX_ByteString GetName(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - const CFX_ByteStringC& default_value, - bool bInheritable = false, - int subindex = -1) override; - FX_ARGB GetColor(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - FX_ARGB default_value, - bool bInheritable = false, - int subindex = -1) override; - FX_FLOAT GetNumber(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - FX_FLOAT default_value, - bool bInheritable = false, - int subindex = -1) override; - int GetInteger(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - int default_value, - bool bInheritable = false, - int subindex = -1) override; - - std::vector* GetKids() { return &m_Kids; } - void LoadKids(CPDF_Dictionary* pDict); - void LoadKid(uint32_t PageObjNum, CPDF_Object* pObj, CPDF_StructKid* pKid); - CPDF_Object* GetAttr(const CFX_ByteStringC& owner, - const CFX_ByteStringC& name, - bool bInheritable, - int subindex); - - private: - CPDF_StructElement(CPDF_StructTree* pTree, - CPDF_StructElement* pParent, - CPDF_Dictionary* pDict); - ~CPDF_StructElement() override; - - CPDF_StructTree* const m_pTree; - CPDF_StructElement* const m_pParent; - CPDF_Dictionary* const m_pDict; - CFX_ByteString m_Type; - std::vector m_Kids; -}; - -#endif // CORE_FPDFDOC_TAGGED_INT_H_ diff --git a/core/fpdftext/cpdf_linkextract.cpp b/core/fpdftext/cpdf_linkextract.cpp index a1fc93e158cba8b0e6d234fceaa1951ddc94336c..05cbdfb3a7f15067668f7214461558c58d94995b 100644 --- a/core/fpdftext/cpdf_linkextract.cpp +++ b/core/fpdftext/cpdf_linkextract.cpp @@ -9,10 +9,101 @@ #include #include "core/fpdftext/cpdf_textpage.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +namespace { + +// Find the end of a web link starting from offset |start| and ending at offset +// |end|. The purpose of this function is to separate url from the surrounding +// context characters, we do not intend to fully validate the url. |str| +// contains lower case characters only. +size_t FindWebLinkEnding(const WideString& str, size_t start, size_t end) { + if (str.Contains(L'/', start)) { + // When there is a path and query after '/', most ASCII chars are allowed. + // We don't sanitize in this case. + return end; + } + + // When there is no path, it only has IP address or host name. + // Port is optional at the end. + if (str[start] == L'[') { + // IPv6 reference. + // Find the end of the reference. + auto result = str.Find(L']', start + 1); + if (result.has_value()) { + end = result.value(); + if (end > start + 1) { // Has content inside brackets. + size_t len = str.GetLength(); + size_t off = end + 1; + if (off < len && str[off] == L':') { + off++; + while (off < len && str[off] >= L'0' && str[off] <= L'9') + off++; + if (off > end + 2 && + off <= len) // At least one digit in port number. + end = off - 1; // |off| is offset of the first invalid char. + } + } + } + return end; + } + + // According to RFC1123, host name only has alphanumeric chars, hyphens, + // and periods. Hyphen should not at the end though. + // Non-ASCII chars are ignored during checking. + while (end > start && str[end] < 0x80) { + if ((str[end] >= L'0' && str[end] <= L'9') || + (str[end] >= L'a' && str[end] <= L'z') || str[end] == L'.') + break; + end--; + } + return end; +} + +// Remove characters from the end of |str|, delimited by |start| and |end|, up +// to and including |charToFind|. No-op if |charToFind| is not present. Updates +// |end| if characters were removed. +void TrimBackwardsToChar(const WideString& str, + wchar_t charToFind, + size_t start, + size_t* end) { + for (size_t pos = *end; pos >= start; pos--) { + if (str[pos] == charToFind) { + *end = pos - 1; + break; + } + } +} + +// Finds opening brackets ()[]{}<> and quotes "' before the URL delimited by +// |start| and |end| in |str|. Matches a closing bracket or quote for each +// opening character and, if present, removes everything afterwards. Returns the +// new end position for the string. +size_t TrimExternalBracketsFromWebLink(const WideString& str, + size_t start, + size_t end) { + for (size_t pos = 0; pos < start; pos++) { + if (str[pos] == '(') { + TrimBackwardsToChar(str, ')', start, &end); + } else if (str[pos] == '[') { + TrimBackwardsToChar(str, ']', start, &end); + } else if (str[pos] == '{') { + TrimBackwardsToChar(str, '}', start, &end); + } else if (str[pos] == '<') { + TrimBackwardsToChar(str, '>', start, &end); + } else if (str[pos] == '"') { + TrimBackwardsToChar(str, '"', start, &end); + } else if (str[pos] == '\'') { + TrimBackwardsToChar(str, '\'', start, &end); + } + } + return end; +} + +} // namespace + CPDF_LinkExtract::CPDF_LinkExtract(const CPDF_TextPage* pTextPage) : m_pTextPage(pTextPage) {} @@ -23,7 +114,7 @@ void CPDF_LinkExtract::ExtractLinks() { if (!m_pTextPage->IsParsed()) return; - m_strPageText = m_pTextPage->GetPageText(0, -1); + m_strPageText = m_pTextPage->GetAllPageText(); if (m_strPageText.IsEmpty()) return; @@ -31,122 +122,174 @@ void CPDF_LinkExtract::ExtractLinks() { } void CPDF_LinkExtract::ParseLink() { - int start = 0, pos = 0; - int TotalChar = m_pTextPage->CountChars(); - while (pos < TotalChar) { + int start = 0; + int pos = 0; + int nTotalChar = m_pTextPage->CountChars(); + bool bAfterHyphen = false; + bool bLineBreak = false; + while (pos < nTotalChar) { FPDF_CHAR_INFO pageChar; m_pTextPage->GetCharInfo(pos, &pageChar); if (pageChar.m_Flag == FPDFTEXT_CHAR_GENERATED || - pageChar.m_Unicode == 0x20 || pos == TotalChar - 1) { + pageChar.m_Unicode == TEXT_SPACE_CHAR || pos == nTotalChar - 1) { int nCount = pos - start; - if (pos == TotalChar - 1) + if (pos == nTotalChar - 1) { nCount++; - CFX_WideString strBeCheck; + } else if (bAfterHyphen && (pageChar.m_Unicode == TEXT_LINEFEED_CHAR || + pageChar.m_Unicode == TEXT_RETURN_CHAR)) { + // Handle text breaks with a hyphen to the next line. + bLineBreak = true; + pos++; + continue; + } + WideString strBeCheck; strBeCheck = m_pTextPage->GetPageText(start, nCount); + if (bLineBreak) { + strBeCheck.Remove(TEXT_LINEFEED_CHAR); + strBeCheck.Remove(TEXT_RETURN_CHAR); + bLineBreak = false; + } + // Replace the generated code with the hyphen char. + strBeCheck.Replace(L"\xfffe", TEXT_HYPHEN); + if (strBeCheck.GetLength() > 5) { while (strBeCheck.GetLength() > 0) { - FX_WCHAR ch = strBeCheck.GetAt(strBeCheck.GetLength() - 1); + wchar_t ch = strBeCheck[strBeCheck.GetLength() - 1]; if (ch == L')' || ch == L',' || ch == L'>' || ch == L'.') { - strBeCheck = strBeCheck.Mid(0, strBeCheck.GetLength() - 1); + strBeCheck = strBeCheck.Left(strBeCheck.GetLength() - 1); nCount--; } else { break; } } - if (nCount > 5 && - (CheckWebLink(strBeCheck) || CheckMailLink(strBeCheck))) { - m_LinkArray.push_back({start, nCount, strBeCheck}); + // Check for potential web URLs and email addresses. + // Ftp address, file system links, data, blob etc. are not checked. + if (nCount > 5) { + int32_t nStartOffset; + int32_t nCountOverload; + if (CheckWebLink(&strBeCheck, &nStartOffset, &nCountOverload)) { + m_LinkArray.push_back( + {start + nStartOffset, nCountOverload, strBeCheck}); + } else if (CheckMailLink(&strBeCheck)) { + m_LinkArray.push_back({start, nCount, strBeCheck}); + } } } start = ++pos; } else { + bAfterHyphen = (pageChar.m_Flag == FPDFTEXT_CHAR_HYPHEN || + (pageChar.m_Flag == FPDFTEXT_CHAR_NORMAL && + pageChar.m_Unicode == TEXT_HYPHEN_CHAR)); pos++; } } } -bool CPDF_LinkExtract::CheckWebLink(CFX_WideString& strBeCheck) { - CFX_WideString str = strBeCheck; +bool CPDF_LinkExtract::CheckWebLink(WideString* strBeCheck, + int32_t* nStart, + int32_t* nCount) { + static const wchar_t kHttpScheme[] = L"http"; + static const size_t kHttpSchemeLen = FXSYS_len(kHttpScheme); + static const wchar_t kWWWAddrStart[] = L"www."; + static const size_t kWWWAddrStartLen = FXSYS_len(kWWWAddrStart); + + WideString str = *strBeCheck; str.MakeLower(); - if (str.Find(L"http://www.") != -1) { - strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"http://www.")); - return true; - } - if (str.Find(L"http://") != -1) { - strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"http://")); - return true; - } - if (str.Find(L"https://www.") != -1) { - strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"https://www.")); - return true; - } - if (str.Find(L"https://") != -1) { - strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"https://")); - return true; + + size_t len = str.GetLength(); + // First, try to find the scheme. + auto start = str.Find(kHttpScheme); + if (start.has_value()) { + size_t off = start.value() + kHttpSchemeLen; // move after "http". + if (len > off + 4) { // At least "://" follows. + if (str[off] == L's') // "https" scheme is accepted. + off++; + if (str[off] == L':' && str[off + 1] == L'/' && str[off + 2] == L'/') { + off += 3; + size_t end = TrimExternalBracketsFromWebLink(str, start.value(), + str.GetLength() - 1); + end = FindWebLinkEnding(str, off, end); + if (end > off) { // Non-empty host name. + *nStart = start.value(); + *nCount = end - start.value() + 1; + *strBeCheck = strBeCheck->Mid(*nStart, *nCount); + return true; + } + } + } } - if (str.Find(L"www.") != -1) { - strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"www.")); - strBeCheck = L"http://" + strBeCheck; - return true; + + // When there is no scheme, try to find url starting with "www.". + start = str.Find(kWWWAddrStart); + if (start.has_value() && len > start.value() + kWWWAddrStartLen) { + size_t end = TrimExternalBracketsFromWebLink(str, start.value(), + str.GetLength() - 1); + end = FindWebLinkEnding(str, start.value(), end); + if (end > start.value() + kWWWAddrStartLen) { + *nStart = start.value(); + *nCount = end - start.value() + 1; + *strBeCheck = L"http://" + strBeCheck->Mid(*nStart, *nCount); + return true; + } } return false; } -bool CPDF_LinkExtract::CheckMailLink(CFX_WideString& str) { - int aPos = str.Find(L'@'); - // Invalid when no '@'. - if (aPos < 1) +bool CPDF_LinkExtract::CheckMailLink(WideString* str) { + auto aPos = str->Find(L'@'); + // Invalid when no '@' or when starts/ends with '@'. + if (!aPos.has_value() || aPos.value() == 0 || aPos == str->GetLength() - 1) return false; // Check the local part. - int pPos = aPos; // Used to track the position of '@' or '.'. - for (int i = aPos - 1; i >= 0; i--) { - FX_WCHAR ch = str.GetAt(i); + size_t pPos = aPos.value(); // Used to track the position of '@' or '.'. + for (size_t i = aPos.value(); i > 0; i--) { + wchar_t ch = (*str)[i - 1]; if (ch == L'_' || ch == L'-' || FXSYS_iswalnum(ch)) continue; - if (ch != L'.' || i == pPos - 1 || i == 0) { - if (i == aPos - 1) { + if (ch != L'.' || i == pPos || i == 1) { + if (i == aPos.value()) { // There is '.' or invalid char before '@'. return false; } // End extracting for other invalid chars, '.' at the beginning, or // consecutive '.'. - int removed_len = i == pPos - 1 ? i + 2 : i + 1; - str = str.Right(str.GetLength() - removed_len); + size_t removed_len = i == pPos ? i + 1 : i; + *str = str->Right(str->GetLength() - removed_len); break; } // Found a valid '.'. - pPos = i; + pPos = i - 1; } // Check the domain name part. - aPos = str.Find(L'@'); - if (aPos < 1) + aPos = str->Find(L'@'); + if (!aPos.has_value() || aPos.value() == 0) return false; - str.TrimRight(L'.'); + str->TrimRight(L'.'); // At least one '.' in domain name, but not at the beginning. // TODO(weili): RFC5322 allows domain names to be a local name without '.'. // Check whether we should remove this check. - int ePos = str.Find(L'.', aPos + 1); - if (ePos == -1 || ePos == aPos + 1) + auto ePos = str->Find(L'.', aPos.value() + 1); + if (!ePos.has_value() || ePos.value() == aPos.value() + 1) return false; // Validate all other chars in domain name. - int nLen = str.GetLength(); + size_t nLen = str->GetLength(); pPos = 0; // Used to track the position of '.'. - for (int i = aPos + 1; i < nLen; i++) { - FX_WCHAR wch = str.GetAt(i); + for (size_t i = aPos.value() + 1; i < nLen; i++) { + wchar_t wch = (*str)[i]; if (wch == L'-' || FXSYS_iswalnum(wch)) continue; if (wch != L'.' || i == pPos + 1) { // Domain name should end before invalid char. - int host_end = i == pPos + 1 ? i - 2 : i - 1; - if (pPos > 0 && host_end - aPos >= 3) { + size_t host_end = i == pPos + 1 ? i - 2 : i - 1; + if (pPos > 0 && host_end - aPos.value() >= 3) { // Trim the ending invalid chars if there is at least one '.' and name. - str = str.Left(host_end + 1); + *str = str->Left(host_end + 1); break; } return false; @@ -154,13 +297,13 @@ bool CPDF_LinkExtract::CheckMailLink(CFX_WideString& str) { pPos = i; } - if (str.Find(L"mailto:") == -1) - str = L"mailto:" + str; + if (!str->Contains(L"mailto:")) + *str = L"mailto:" + *str; return true; } -CFX_WideString CPDF_LinkExtract::GetURL(size_t index) const { +WideString CPDF_LinkExtract::GetURL(size_t index) const { return index < m_LinkArray.size() ? m_LinkArray[index].m_strUrl : L""; } diff --git a/core/fpdftext/cpdf_linkextract.h b/core/fpdftext/cpdf_linkextract.h index 43306cf87ad8af485d74efc5fb5bc7f8acca2a30..713f6581693123498ff42d3370c207f90d4dc239 100644 --- a/core/fpdftext/cpdf_linkextract.h +++ b/core/fpdftext/cpdf_linkextract.h @@ -9,7 +9,6 @@ #include -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" @@ -23,23 +22,23 @@ class CPDF_LinkExtract { void ExtractLinks(); size_t CountLinks() const { return m_LinkArray.size(); } - CFX_WideString GetURL(size_t index) const; + WideString GetURL(size_t index) const; std::vector GetRects(size_t index) const; protected: void ParseLink(); - bool CheckWebLink(CFX_WideString& str); - bool CheckMailLink(CFX_WideString& str); + bool CheckWebLink(WideString* str, int32_t* nStart, int32_t* nCount); + bool CheckMailLink(WideString* str); private: struct Link { int m_Start; int m_Count; - CFX_WideString m_strUrl; + WideString m_strUrl; }; - const CPDF_TextPage* const m_pTextPage; - CFX_WideString m_strPageText; + UnownedPtr const m_pTextPage; + WideString m_strPageText; std::vector m_LinkArray; }; diff --git a/core/fpdftext/cpdf_linkextract_unittest.cpp b/core/fpdftext/cpdf_linkextract_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30438e6c1048066202db5711db310f691efea8cd --- /dev/null +++ b/core/fpdftext/cpdf_linkextract_unittest.cpp @@ -0,0 +1,187 @@ +// Copyright 2015 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. + +#include "core/fpdftext/cpdf_linkextract.h" + +#include "testing/gtest/include/gtest/gtest.h" + +// Class to help test functions in CPDF_LinkExtract class. +class CPDF_TestLinkExtract : public CPDF_LinkExtract { + public: + CPDF_TestLinkExtract() : CPDF_LinkExtract(nullptr) {} + + private: + // Add test cases as friends to access protected member functions. + // Access CheckMailLink and CheckWebLink. + FRIEND_TEST(CPDF_LinkExtractTest, CheckMailLink); + FRIEND_TEST(CPDF_LinkExtractTest, CheckWebLink); +}; + +TEST(CPDF_LinkExtractTest, CheckMailLink) { + CPDF_TestLinkExtract extractor; + // Check cases that fail to extract valid mail link. + const wchar_t* const invalid_strs[] = { + L"", + L"peter.pan", // '@' is required. + L"abc@server", // Domain name needs at least one '.'. + L"abc.@gmail.com", // '.' can not immediately precede '@'. + L"abc@xyz&q.org", // Domain name should not contain '&'. + L"abc@.xyz.org", // Domain name should not start with '.'. + L"fan@g..com" // Domain name should not have consecutive '.' + }; + for (size_t i = 0; i < FX_ArraySize(invalid_strs); ++i) { + const wchar_t* const input = invalid_strs[i]; + WideString text_str(input); + EXPECT_FALSE(extractor.CheckMailLink(&text_str)) << input; + } + + // Check cases that can extract valid mail link. + // An array of {input_string, expected_extracted_email_address}. + const wchar_t* const valid_strs[][2] = { + {L"peter@abc.d", L"peter@abc.d"}, + {L"red.teddy.b@abc.com", L"red.teddy.b@abc.com"}, + {L"abc_@gmail.com", L"abc_@gmail.com"}, // '_' is ok before '@'. + {L"dummy-hi@gmail.com", + L"dummy-hi@gmail.com"}, // '-' is ok in user name. + {L"a..df@gmail.com", L"df@gmail.com"}, // Stop at consecutive '.'. + {L".john@yahoo.com", L"john@yahoo.com"}, // Remove heading '.'. + {L"abc@xyz.org?/", L"abc@xyz.org"}, // Trim ending invalid chars. + {L"fan{abc@xyz.org", L"abc@xyz.org"}, // Trim beginning invalid chars. + {L"fan@g.com..", L"fan@g.com"}, // Trim the ending periods. + {L"CAP.cap@Gmail.Com", L"CAP.cap@Gmail.Com"}, // Keep the original case. + }; + for (size_t i = 0; i < FX_ArraySize(valid_strs); ++i) { + const wchar_t* const input = valid_strs[i][0]; + WideString text_str(input); + WideString expected_str(L"mailto:"); + expected_str += valid_strs[i][1]; + EXPECT_TRUE(extractor.CheckMailLink(&text_str)) << input; + EXPECT_STREQ(expected_str.c_str(), text_str.c_str()); + } +} + +TEST(CPDF_LinkExtractTest, CheckWebLink) { + CPDF_TestLinkExtract extractor; + // Check cases that fail to extract valid web link. + // The last few are legit web addresses that we don't handle now. + const wchar_t* const invalid_cases[] = { + L"", L"http", L"www.", L"https-and-www", + L"http:/abc.com", // Missing slash. + L"http://((()),", // Only invalid chars in host name. + L"ftp://example.com", // Ftp scheme is not supported. + L"http:example.com", // Missing slashes. + L"http//[example.com", // Invalid IPv6 address. + L"http//[00:00:00:00:00:00", // Invalid IPv6 address. + L"http//[]", // Empty IPv6 address. + // Web addresses that in correct format that we don't handle. + L"abc.example.com", // URL without scheme. + }; + const int32_t DEFAULT_VALUE = -42; + for (size_t i = 0; i < FX_ArraySize(invalid_cases); ++i) { + const wchar_t* const input = invalid_cases[i]; + WideString text_str(input); + int32_t start_offset = DEFAULT_VALUE; + int32_t count = DEFAULT_VALUE; + EXPECT_FALSE(extractor.CheckWebLink(&text_str, &start_offset, &count)) + << input; + EXPECT_EQ(DEFAULT_VALUE, start_offset) << input; + EXPECT_EQ(DEFAULT_VALUE, count) << input; + } + + // Check cases that can extract valid web link. + // An array of {input_string, expected_extracted_web_link}. + struct ValidCase { + const wchar_t* const input_string; + const wchar_t* const url_extracted; + const int32_t start_offset; + const int32_t count; + }; + const ValidCase valid_cases[] = { + {L"http://www.example.com", L"http://www.example.com", 0, + 22}, // standard URL. + {L"http://www.example.com:88", L"http://www.example.com:88", 0, + 25}, // URL with port number. + {L"http://test@www.example.com", L"http://test@www.example.com", 0, + 27}, // URL with username. + {L"http://test:test@example.com", L"http://test:test@example.com", 0, + 28}, // URL with username and password. + {L"http://example", L"http://example", 0, + 14}, // URL with short domain name. + {L"http////www.server", L"http://www.server", 8, + 10}, // URL starts with "www.". + {L"http:/www.abc.com", L"http://www.abc.com", 6, + 11}, // URL starts with "www.". + {L"www.a.b.c", L"http://www.a.b.c", 0, 9}, // URL starts with "www.". + {L"https://a.us", L"https://a.us", 0, 12}, // Secure http URL. + {L"https://www.t.us", L"https://www.t.us", 0, 16}, // Secure http URL. + {L"www.example-test.com", L"http://www.example-test.com", 0, + 20}, // '-' in host is ok. + {L"www.example.com,", L"http://www.example.com", 0, + 15}, // Trim ending invalid chars. + {L"www.example.com;(", L"http://www.example.com", 0, + 15}, // Trim ending invalid chars. + {L"test:www.abc.com", L"http://www.abc.com", 5, + 11}, // Trim chars before URL. + {L"(http://www.abc.com)", L"http://www.abc.com", 1, + 18}, // Trim external brackets. + {L"0(http://www.abc.com)0", L"http://www.abc.com", 2, + 18}, // Trim chars outside brackets as well. + {L"0(www.abc.com)0", L"http://www.abc.com", 2, + 11}, // Links without http should also have brackets trimmed. + {L"http://www.abc.com)0", L"http://www.abc.com)0", 0, + 20}, // Do not trim brackets that were not opened. + {L"{()}", L"http://www.abc.com", 3, + 18}, // Trim chars with multiple levels of brackets. + {L"[http://www.abc.com/z(1)]", L"http://www.abc.com/z(1)", 1, + 23}, // Brackets opened inside the URL should not be trimmed. + {L"(http://www.abc.com/z(1))", L"http://www.abc.com/z(1)", 1, + 23}, // Brackets opened inside the URL should not be trimmed. + {L"\"http://www.abc.com\"", L"http://www.abc.com", 1, + 18}, // External quotes can also be escaped + {L"www.g.com..", L"http://www.g.com..", 0, 11}, // Leave ending periods. + + // Web links can contain IP addresses too. + {L"http://192.168.0.1", L"http://192.168.0.1", 0, 18}, // IPv4 address. + {L"http://192.168.0.1:80", L"http://192.168.0.1:80", 0, + 21}, // IPv4 address with port. + {L"http://[aa::00:bb::00:cc:00]", L"http://[aa::00:bb::00:cc:00]", 0, + 28}, // IPv6 reference. + {L"http://[aa::00:bb::00:cc:00]:12", L"http://[aa::00:bb::00:cc:00]:12", + 0, 31}, // IPv6 reference with port. + {L"http://[aa]:12", L"http://[aa]:12", 0, + 14}, // Not validate IP address. + {L"http://[aa]:12abc", L"http://[aa]:12", 0, + 14}, // Trim for IPv6 address. + {L"http://[aa]:", L"http://[aa]", 0, 11}, // Trim for IPv6 address. + + // Path and query parts can be anything. + {L"www.abc.com/#%%^&&*(", L"http://www.abc.com/#%%^&&*(", 0, 20}, + {L"www.a.com/#a=@?q=rr&r=y", L"http://www.a.com/#a=@?q=rr&r=y", 0, 23}, + {L"http://a.com/1/2/3/4\5\6", L"http://a.com/1/2/3/4\5\6", 0, 22}, + {L"http://www.example.com/foo;bar", L"http://www.example.com/foo;bar", 0, + 30}, + + // Invalid chars inside host name are ok as we don't validate them. + {L"http://ex[am]ple", L"http://ex[am]ple", 0, 16}, + {L"http://:example.com", L"http://:example.com", 0, 19}, + {L"http://((())/path?", L"http://((())/path?", 0, 18}, + {L"http:////abc.server", L"http:////abc.server", 0, 19}, + + // Non-ASCII chars are not validated either. + {L"www.测试.net", L"http://www.测试.net", 0, 10}, + {L"www.测试。net。", L"http://www.测试。net。", 0, 11}, + {L"www.测试.net;", L"http://www.测试.net;", 0, 11}, + }; + for (size_t i = 0; i < FX_ArraySize(valid_cases); ++i) { + const wchar_t* const input = valid_cases[i].input_string; + WideString text_str(input); + int32_t start_offset = DEFAULT_VALUE; + int32_t count = DEFAULT_VALUE; + EXPECT_TRUE(extractor.CheckWebLink(&text_str, &start_offset, &count)) + << input; + EXPECT_STREQ(valid_cases[i].url_extracted, text_str.c_str()); + EXPECT_EQ(valid_cases[i].start_offset, start_offset) << input; + EXPECT_EQ(valid_cases[i].count, count) << input; + } +} diff --git a/core/fpdftext/cpdf_textpage.cpp b/core/fpdftext/cpdf_textpage.cpp index 73a1a7e88e40f9a61d458e597722d6e5d1e8882e..b448a59b33913c06353f91dc177020fd1e9355d0 100644 --- a/core/fpdftext/cpdf_textpage.cpp +++ b/core/fpdftext/cpdf_textpage.cpp @@ -20,18 +20,18 @@ #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdftext/unicodenormalizationdata.h" #include "core/fxcrt/fx_bidi.h" -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_ucd.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_unicode.h" #include "third_party/base/stl_util.h" namespace { -const FX_FLOAT kDefaultFontSize = 1.0f; +const float kDefaultFontSize = 1.0f; const uint16_t* const g_UnicodeData_Normalization_Maps[5] = { nullptr, g_UnicodeData_Normalization_Map1, g_UnicodeData_Normalization_Map2, g_UnicodeData_Normalization_Map3, g_UnicodeData_Normalization_Map4}; -FX_FLOAT NormalizeThreshold(FX_FLOAT threshold) { +float NormalizeThreshold(float threshold) { if (threshold < 300) return threshold / 2.0f; if (threshold < 500) @@ -41,21 +41,21 @@ FX_FLOAT NormalizeThreshold(FX_FLOAT threshold) { return threshold / 6.0f; } -FX_FLOAT CalculateBaseSpace(const CPDF_TextObject* pTextObj, - const CFX_Matrix& matrix) { - FX_FLOAT baseSpace = 0.0; - const int nItems = pTextObj->CountItems(); +float CalculateBaseSpace(const CPDF_TextObject* pTextObj, + const CFX_Matrix& matrix) { + float baseSpace = 0.0; + const size_t nItems = pTextObj->CountItems(); if (pTextObj->m_TextState.GetCharSpace() && nItems >= 3) { bool bAllChar = true; - FX_FLOAT spacing = + float spacing = matrix.TransformDistance(pTextObj->m_TextState.GetCharSpace()); baseSpace = spacing; - for (int i = 0; i < nItems; i++) { + for (size_t i = 0; i < nItems; ++i) { CPDF_TextObjectItem item; pTextObj->GetItemInfo(i, &item); if (item.m_CharCode == static_cast(-1)) { - FX_FLOAT fontsize_h = pTextObj->m_TextState.GetFontSizeH(); - FX_FLOAT kerning = -fontsize_h * item.m_Origin.x / 1000; + float fontsize_h = pTextObj->m_TextState.GetFontSizeH(); + float kerning = -fontsize_h * item.m_Origin.x / 1000; baseSpace = std::min(baseSpace, kerning + spacing); bAllChar = false; } @@ -66,9 +66,9 @@ FX_FLOAT CalculateBaseSpace(const CPDF_TextObject* pTextObj, return baseSpace; } -FX_STRSIZE Unicode_GetNormalization(FX_WCHAR wch, FX_WCHAR* pDst) { +size_t Unicode_GetNormalization(wchar_t wch, wchar_t* pDst) { wch = wch & 0xFFFF; - FX_WCHAR wFind = g_UnicodeData_Normalization[wch]; + wchar_t wFind = g_UnicodeData_Normalization[wch]; if (!wFind) { if (pDst) *pDst = wch; @@ -84,16 +84,16 @@ FX_STRSIZE Unicode_GetNormalization(FX_WCHAR wch, FX_WCHAR* pDst) { const uint16_t* pMap = g_UnicodeData_Normalization_Maps[wFind]; if (pMap == g_UnicodeData_Normalization_Map4) { pMap = g_UnicodeData_Normalization_Map4 + wch; - wFind = (FX_WCHAR)(*pMap++); + wFind = (wchar_t)(*pMap++); } else { pMap += wch; } if (pDst) { - FX_WCHAR n = wFind; + wchar_t n = wFind; while (n--) *pDst++ = *pMap++; } - return (FX_STRSIZE)wFind; + return static_cast(wFind); } float MaskPercentFilled(const std::vector& mask, @@ -106,8 +106,18 @@ float MaskPercentFilled(const std::vector& mask, return count / (end - start); } +bool IsHyphenCode(wchar_t c) { + return c == 0x2D || c == 0xAD; +} + } // namespace +PDFTEXT_Obj::PDFTEXT_Obj() {} + +PDFTEXT_Obj::PDFTEXT_Obj(const PDFTEXT_Obj& that) = default; + +PDFTEXT_Obj::~PDFTEXT_Obj() {} + FPDF_CHAR_INFO::FPDF_CHAR_INFO() : m_Unicode(0), m_Charcode(0), @@ -248,20 +258,17 @@ std::vector CPDF_TextPage::GetRectArray(int start, continue; } if (!pCurObj) - pCurObj = info_curchar.m_pTextObj; + pCurObj = info_curchar.m_pTextObj.Get(); if (pCurObj != info_curchar.m_pTextObj) { rectArray.push_back(rect); - pCurObj = info_curchar.m_pTextObj; + pCurObj = info_curchar.m_pTextObj.Get(); bFlagNewRect = true; } if (bFlagNewRect) { CFX_Matrix matrix = info_curchar.m_pTextObj->GetTextMatrix(); matrix.Concat(info_curchar.m_Matrix); - CFX_Matrix matrix_reverse; - matrix_reverse.SetReverse(matrix); - - CFX_PointF origin = matrix_reverse.Transform(info_curchar.m_Origin); + CFX_PointF origin = matrix.GetInverse().Transform(info_curchar.m_Origin); rect.left = info_curchar.m_CharBox.left; rect.right = info_curchar.m_CharBox.right; if (pCurObj->GetFont()->GetTypeDescent()) { @@ -277,7 +284,7 @@ std::vector CPDF_TextPage::GetRectArray(int start, rect.top = origin.y + pCurObj->GetFont()->GetTypeAscent() * pCurObj->GetFontSize() / 1000; - FX_FLOAT xPosTemp = + float xPosTemp = origin.x + GetCharWidth(info_curchar.m_CharCode, pCurObj->GetFont()) * pCurObj->GetFontSize() / 1000; @@ -323,14 +330,12 @@ int CPDF_TextPage::GetIndexAtPos(const CFX_PointF& point, charRectExt.bottom = charrect.bottom - tolerance.height / 2; if (charRectExt.Contains(point)) { double curXdif, curYdif; - curXdif = FXSYS_fabs(point.x - charrect.left) < - FXSYS_fabs(point.x - charrect.right) - ? FXSYS_fabs(point.x - charrect.left) - : FXSYS_fabs(point.x - charrect.right); - curYdif = FXSYS_fabs(point.y - charrect.bottom) < - FXSYS_fabs(point.y - charrect.top) - ? FXSYS_fabs(point.y - charrect.bottom) - : FXSYS_fabs(point.y - charrect.top); + curXdif = fabs(point.x - charrect.left) < fabs(point.x - charrect.right) + ? fabs(point.x - charrect.left) + : fabs(point.x - charrect.right); + curYdif = fabs(point.y - charrect.bottom) < fabs(point.y - charrect.top) + ? fabs(point.y - charrect.bottom) + : fabs(point.y - charrect.top); if (curYdif + curXdif < xdif + ydif) { ydif = curYdif; xdif = curXdif; @@ -343,17 +348,17 @@ int CPDF_TextPage::GetIndexAtPos(const CFX_PointF& point, return pos < pdfium::CollectionSize(m_CharList) ? pos : NearPos; } -CFX_WideString CPDF_TextPage::GetTextByRect(const CFX_FloatRect& rect) const { +WideString CPDF_TextPage::GetTextByRect(const CFX_FloatRect& rect) const { if (!m_bIsParsed) - return CFX_WideString(); + return WideString(); - FX_FLOAT posy = 0; + float posy = 0; bool IsContainPreChar = false; bool IsAddLineFeed = false; - CFX_WideString strText; + WideString strText; for (const auto& charinfo : m_CharList) { if (IsRectIntersect(rect, charinfo.m_CharBox)) { - if (FXSYS_fabs(posy - charinfo.m_Origin.y) > 0 && !IsContainPreChar && + if (fabs(posy - charinfo.m_Origin.y) > 0 && !IsContainPreChar && IsAddLineFeed) { posy = charinfo.m_Origin.y; if (!strText.IsEmpty()) @@ -378,10 +383,7 @@ CFX_WideString CPDF_TextPage::GetTextByRect(const CFX_FloatRect& rect) const { } void CPDF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO* info) const { - if (!m_bIsParsed) - return; - - if (index < 0 || index >= pdfium::CollectionSize(m_CharList)) + if (!m_bIsParsed || !pdfium::IndexInBounds(m_CharList, index)) return; const PAGECHAR_INFO& charinfo = m_CharList[index]; @@ -434,49 +436,27 @@ void CPDF_TextPage::CheckMarkedContentObject(int32_t& start, } } -CFX_WideString CPDF_TextPage::GetPageText(int start, int nCount) const { - if (!m_bIsParsed || nCount == 0) +WideString CPDF_TextPage::GetPageText(int start, int count) const { + if (start < 0 || start >= CountChars() || count <= 0 || !m_bIsParsed || + m_CharList.empty() || m_TextBuf.GetLength() == 0) { return L""; - - if (start < 0) - start = 0; - - if (nCount == -1) { - nCount = pdfium::CollectionSize(m_CharList) - start; - return CFX_WideString( - m_TextBuf.AsStringC().Mid(start, m_TextBuf.AsStringC().GetLength())); } - if (nCount <= 0 || m_CharList.empty()) - return L""; - if (nCount + start > pdfium::CollectionSize(m_CharList) - 1) - nCount = pdfium::CollectionSize(m_CharList) - start; - if (nCount <= 0) + + int text_start = TextIndexFromCharIndex(start); + if (text_start < 0) return L""; - CheckMarkedContentObject(start, nCount); - int startindex = 0; - PAGECHAR_INFO charinfo = m_CharList[start]; - int startOffset = 0; - while (charinfo.m_Index == -1) { - startOffset++; - if (startOffset > nCount || - start + startOffset >= pdfium::CollectionSize(m_CharList)) { - return L""; - } - charinfo = m_CharList[start + startOffset]; - } - startindex = charinfo.m_Index; - charinfo = m_CharList[start + nCount - 1]; - int nCountOffset = 0; - while (charinfo.m_Index == -1) { - nCountOffset++; - if (nCountOffset >= nCount) - return L""; - charinfo = m_CharList[start + nCount - nCountOffset - 1]; - } - nCount = start + nCount - nCountOffset - startindex; - if (nCount <= 0) + + count = std::min(count, CountChars() - start); + + int last = start + count - 1; + int text_last = TextIndexFromCharIndex(last); + if (text_last < 0 || text_last < text_start) return L""; - return CFX_WideString(m_TextBuf.AsStringC().Mid(startindex, nCount)); + + int text_count = text_last - text_start + 1; + + return WideString(m_TextBuf.AsStringView().Mid( + static_cast(text_start), static_cast(text_count))); } int CPDF_TextPage::CountRects(int start, int nCount) { @@ -491,21 +471,12 @@ int CPDF_TextPage::CountRects(int start, int nCount) { return pdfium::CollectionSize(m_SelRects); } -void CPDF_TextPage::GetRect(int rectIndex, - FX_FLOAT& left, - FX_FLOAT& top, - FX_FLOAT& right, - FX_FLOAT& bottom) const { - if (!m_bIsParsed) - return; - - if (rectIndex < 0 || rectIndex >= pdfium::CollectionSize(m_SelRects)) - return; +bool CPDF_TextPage::GetRect(int rectIndex, CFX_FloatRect* pRect) const { + if (!m_bIsParsed || !pdfium::IndexInBounds(m_SelRects, rectIndex)) + return false; - left = m_SelRects[rectIndex].left; - top = m_SelRects[rectIndex].top; - right = m_SelRects[rectIndex].right; - bottom = m_SelRects[rectIndex].bottom; + *pRect = m_SelRects[rectIndex]; + return true; } CPDF_TextPage::TextOrientation CPDF_TextPage::FindTextlineFlowOrientation() @@ -520,7 +491,7 @@ CPDF_TextPage::TextOrientation CPDF_TextPage::FindTextlineFlowOrientation() std::vector nHorizontalMask(nPageWidth); std::vector nVerticalMask(nPageHeight); - FX_FLOAT fLineHeight = 0.0f; + float fLineHeight = 0.0f; int32_t nStartH = nPageWidth; int32_t nEndH = 0; int32_t nStartV = nPageHeight; @@ -556,11 +527,11 @@ CPDF_TextPage::TextOrientation CPDF_TextPage::FindTextlineFlowOrientation() if ((nEndH - nStartH) < nDoubleLineHeight) return TextOrientation::Vertical; - const FX_FLOAT nSumH = MaskPercentFilled(nHorizontalMask, nStartH, nEndH); + const float nSumH = MaskPercentFilled(nHorizontalMask, nStartH, nEndH); if (nSumH > 0.8f) return TextOrientation::Horizontal; - const FX_FLOAT nSumV = MaskPercentFilled(nVerticalMask, nStartV, nEndV); + const float nSumV = MaskPercentFilled(nVerticalMask, nStartV, nEndV); if (nSumH > nSumV) return TextOrientation::Horizontal; if (nSumH < nSumV) @@ -568,7 +539,7 @@ CPDF_TextPage::TextOrientation CPDF_TextPage::FindTextlineFlowOrientation() return TextOrientation::Unknown; } -void CPDF_TextPage::AppendGeneratedCharacter(FX_WCHAR unicode, +void CPDF_TextPage::AppendGeneratedCharacter(wchar_t unicode, const CFX_Matrix& formMatrix) { PAGECHAR_INFO generateChar; if (!GenerateCharInfo(unicode, generateChar)) @@ -592,7 +563,7 @@ void CPDF_TextPage::ProcessObject() { CFX_Matrix matrix; ProcessTextObject(pObj->AsText(), matrix, pObjList, it); } else if (pObj->IsForm()) { - CFX_Matrix formMatrix(1, 0, 0, 1, 0, 0); + CFX_Matrix formMatrix; ProcessFormObject(pObj->AsForm(), formMatrix); } } @@ -606,12 +577,12 @@ void CPDF_TextPage::ProcessObject() { void CPDF_TextPage::ProcessFormObject(CPDF_FormObject* pFormObj, const CFX_Matrix& formMatrix) { - CPDF_PageObjectList* pObjectList = pFormObj->m_pForm->GetPageObjectList(); + const CPDF_PageObjectList* pObjectList = + pFormObj->form()->GetPageObjectList(); if (pObjectList->empty()) return; - CFX_Matrix curFormMatrix; - curFormMatrix = pFormObj->m_FormMatrix; + CFX_Matrix curFormMatrix = pFormObj->form_matrix(); curFormMatrix.Concat(formMatrix); for (auto it = pObjectList->begin(); it != pObjectList->end(); ++it) { @@ -631,15 +602,15 @@ int CPDF_TextPage::GetCharWidth(uint32_t charCode, CPDF_Font* pFont) const { if (int w = pFont->GetCharWidthF(charCode)) return w; - CFX_ByteString str; - pFont->AppendChar(str, charCode); + ByteString str; + pFont->AppendChar(&str, charCode); if (int w = pFont->GetStringWidth(str.c_str(), 1)) return w; return pFont->GetCharBBox(charCode).Width(); } -void CPDF_TextPage::AddCharInfoByLRDirection(FX_WCHAR wChar, +void CPDF_TextPage::AddCharInfoByLRDirection(wchar_t wChar, PAGECHAR_INFO info) { if (IsControlChar(info)) { info.m_Index = -1; @@ -649,12 +620,12 @@ void CPDF_TextPage::AddCharInfoByLRDirection(FX_WCHAR wChar, info.m_Index = m_TextBuf.GetLength(); if (wChar >= 0xFB00 && wChar <= 0xFB06) { - FX_WCHAR* pDst = nullptr; - FX_STRSIZE nCount = Unicode_GetNormalization(wChar, pDst); + wchar_t* pDst = nullptr; + size_t nCount = Unicode_GetNormalization(wChar, pDst); if (nCount >= 1) { - pDst = FX_Alloc(FX_WCHAR, nCount); + pDst = FX_Alloc(wchar_t, nCount); Unicode_GetNormalization(wChar, pDst); - for (int nIndex = 0; nIndex < nCount; nIndex++) { + for (size_t nIndex = 0; nIndex < nCount; nIndex++) { PAGECHAR_INFO info2 = info; info2.m_Unicode = pDst[nIndex]; info2.m_Flag = FPDFTEXT_CHAR_PIECE; @@ -669,7 +640,7 @@ void CPDF_TextPage::AddCharInfoByLRDirection(FX_WCHAR wChar, m_CharList.push_back(info); } -void CPDF_TextPage::AddCharInfoByRLDirection(FX_WCHAR wChar, +void CPDF_TextPage::AddCharInfoByRLDirection(wchar_t wChar, PAGECHAR_INFO info) { if (IsControlChar(info)) { info.m_Index = -1; @@ -678,13 +649,13 @@ void CPDF_TextPage::AddCharInfoByRLDirection(FX_WCHAR wChar, } info.m_Index = m_TextBuf.GetLength(); - wChar = FX_GetMirrorChar(wChar, true, false); - FX_WCHAR* pDst = nullptr; - FX_STRSIZE nCount = Unicode_GetNormalization(wChar, pDst); + wChar = FX_GetMirrorChar(wChar); + wchar_t* pDst = nullptr; + size_t nCount = Unicode_GetNormalization(wChar, pDst); if (nCount >= 1) { - pDst = FX_Alloc(FX_WCHAR, nCount); + pDst = FX_Alloc(wchar_t, nCount); Unicode_GetNormalization(wChar, pDst); - for (int nIndex = 0; nIndex < nCount; nIndex++) { + for (size_t nIndex = 0; nIndex < nCount; nIndex++) { PAGECHAR_INFO info2 = info; info2.m_Unicode = pDst[nIndex]; info2.m_Flag = FPDFTEXT_CHAR_PIECE; @@ -703,10 +674,10 @@ void CPDF_TextPage::CloseTempLine() { if (m_TempCharList.empty()) return; - CFX_WideString str = m_TempTextBuf.MakeString(); + WideString str = m_TempTextBuf.MakeString(); bool bPrevSpace = false; - for (int i = 0; i < str.GetLength(); i++) { - if (str.GetAt(i) != ' ') { + for (size_t i = 0; i < str.GetLength(); i++) { + if (str[i] != ' ') { bPrevSpace = false; continue; } @@ -744,7 +715,7 @@ void CPDF_TextPage::ProcessTextObject( const CFX_Matrix& formMatrix, const CPDF_PageObjectList* pObjList, CPDF_PageObjectList::const_iterator ObjPos) { - if (FXSYS_fabs(pTextObj->m_Right - pTextObj->m_Left) < 0.01f) + if (fabs(pTextObj->m_Right - pTextObj->m_Left) < 0.01f) return; size_t count = m_LineObj.size(); @@ -759,34 +730,36 @@ void CPDF_TextPage::ProcessTextObject( return; PDFTEXT_Obj prev_Obj = m_LineObj[count - 1]; + size_t nItem = prev_Obj.m_pTextObj->CountItems(); + if (nItem == 0) + return; + CPDF_TextObjectItem item; - int nItem = prev_Obj.m_pTextObj->CountItems(); prev_Obj.m_pTextObj->GetItemInfo(nItem - 1, &item); - FX_FLOAT prev_width = + float prev_width = GetCharWidth(item.m_CharCode, prev_Obj.m_pTextObj->GetFont()) * prev_Obj.m_pTextObj->GetFontSize() / 1000; CFX_Matrix prev_matrix = prev_Obj.m_pTextObj->GetTextMatrix(); - prev_width = FXSYS_fabs(prev_width); + prev_width = fabs(prev_width); prev_matrix.Concat(prev_Obj.m_formMatrix); prev_width = prev_matrix.TransformDistance(prev_width); pTextObj->GetItemInfo(0, &item); - FX_FLOAT this_width = GetCharWidth(item.m_CharCode, pTextObj->GetFont()) * - pTextObj->GetFontSize() / 1000; - this_width = FXSYS_fabs(this_width); + float this_width = GetCharWidth(item.m_CharCode, pTextObj->GetFont()) * + pTextObj->GetFontSize() / 1000; + this_width = fabs(this_width); CFX_Matrix this_matrix = pTextObj->GetTextMatrix(); - this_width = FXSYS_fabs(this_width); + this_width = fabs(this_width); this_matrix.Concat(formMatrix); this_width = this_matrix.TransformDistance(this_width); - FX_FLOAT threshold = - prev_width > this_width ? prev_width / 4 : this_width / 4; + float threshold = prev_width > this_width ? prev_width / 4 : this_width / 4; CFX_PointF prev_pos = m_DisplayMatrix.Transform( prev_Obj.m_formMatrix.Transform(prev_Obj.m_pTextObj->GetPos())); CFX_PointF this_pos = m_DisplayMatrix.Transform(formMatrix.Transform(pTextObj->GetPos())); - if (FXSYS_fabs(this_pos.y - prev_pos.y) > threshold * 2) { + if (fabs(this_pos.y - prev_pos.y) > threshold * 2) { for (size_t i = 0; i < count; i++) ProcessTextObject(m_LineObj[i]); m_LineObj.clear(); @@ -808,20 +781,19 @@ void CPDF_TextPage::ProcessTextObject( } FPDFText_MarkedContent CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj) { - CPDF_TextObject* pTextObj = Obj.m_pTextObj; - if (!pTextObj->m_ContentMark) + CPDF_TextObject* pTextObj = Obj.m_pTextObj.Get(); + if (!pTextObj->m_ContentMark.HasRef()) return FPDFText_MarkedContent::Pass; - int nContentMark = pTextObj->m_ContentMark.CountItems(); - if (nContentMark < 1) + size_t nContentMark = pTextObj->m_ContentMark.CountItems(); + if (nContentMark == 0) return FPDFText_MarkedContent::Pass; - CFX_WideString actText; + WideString actText; bool bExist = false; CPDF_Dictionary* pDict = nullptr; - int n = 0; - for (n = 0; n < nContentMark; n++) { - const CPDF_ContentMarkItem& item = pTextObj->m_ContentMark.GetItem(n); + for (size_t i = 0; i < nContentMark; ++i) { + const CPDF_ContentMarkItem& item = pTextObj->m_ContentMark.GetItem(i); pDict = item.GetParam(); if (!pDict) continue; @@ -834,21 +806,21 @@ FPDFText_MarkedContent CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj) { if (!bExist) return FPDFText_MarkedContent::Pass; - if (m_pPreTextObj && m_pPreTextObj->m_ContentMark && - m_pPreTextObj->m_ContentMark.CountItems() == n && - pDict == m_pPreTextObj->m_ContentMark.GetItem(n - 1).GetParam()) { - return FPDFText_MarkedContent::Done; + if (m_pPreTextObj) { + const CPDF_ContentMark& mark = m_pPreTextObj->m_ContentMark; + if (mark.HasRef() && mark.CountItems() == nContentMark && + mark.GetItem(nContentMark - 1).GetParam() == pDict) { + return FPDFText_MarkedContent::Done; + } } - FX_STRSIZE nItems = actText.GetLength(); - if (nItems < 1) + if (actText.IsEmpty()) return FPDFText_MarkedContent::Pass; CPDF_Font* pFont = pTextObj->GetFont(); bExist = false; - for (FX_STRSIZE i = 0; i < nItems; i++) { - if (pFont->CharCodeFromUnicode(actText.GetAt(i)) != - CPDF_Font::kInvalidCharCode) { + for (size_t i = 0; i < actText.GetLength(); i++) { + if (pFont->CharCodeFromUnicode(actText[i]) != CPDF_Font::kInvalidCharCode) { bExist = true; break; } @@ -857,8 +829,8 @@ FPDFText_MarkedContent CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj) { return FPDFText_MarkedContent::Pass; bExist = false; - for (FX_STRSIZE i = 0; i < nItems; i++) { - FX_WCHAR wChar = actText.GetAt(i); + for (size_t i = 0; i < actText.GetLength(); i++) { + wchar_t wChar = actText[i]; if ((wChar > 0x80 && wChar < 0xFFFD) || (wChar <= 0x80 && isprint(wChar))) { bExist = true; break; @@ -871,31 +843,30 @@ FPDFText_MarkedContent CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj) { } void CPDF_TextPage::ProcessMarkedContent(PDFTEXT_Obj Obj) { - CPDF_TextObject* pTextObj = Obj.m_pTextObj; - if (!pTextObj->m_ContentMark) + CPDF_TextObject* pTextObj = Obj.m_pTextObj.Get(); + if (!pTextObj->m_ContentMark.HasRef()) return; int nContentMark = pTextObj->m_ContentMark.CountItems(); if (nContentMark < 1) return; - CFX_WideString actText; + WideString actText; for (int n = 0; n < nContentMark; n++) { const CPDF_ContentMarkItem& item = pTextObj->m_ContentMark.GetItem(n); CPDF_Dictionary* pDict = item.GetParam(); if (pDict) actText = pDict->GetUnicodeTextFor("ActualText"); } - FX_STRSIZE nItems = actText.GetLength(); - if (nItems < 1) + if (actText.IsEmpty()) return; CPDF_Font* pFont = pTextObj->GetFont(); CFX_Matrix matrix = pTextObj->GetTextMatrix(); matrix.Concat(Obj.m_formMatrix); - for (FX_STRSIZE k = 0; k < nItems; k++) { - FX_WCHAR wChar = actText.GetAt(k); + for (size_t k = 0; k < actText.GetLength(); k++) { + wchar_t wChar = actText[k]; if (wChar <= 0x80 && !isprint(wChar)) wChar = 0x20; if (wChar >= 0xFFFD) @@ -934,7 +905,7 @@ void CPDF_TextPage::SwapTempTextBuf(int32_t iCharListStartAppend, std::swap(m_TempCharList[i], m_TempCharList[j]); std::swap(m_TempCharList[i].m_Index, m_TempCharList[j].m_Index); } - FX_WCHAR* pTempBuffer = m_TempTextBuf.GetBuffer(); + wchar_t* pTempBuffer = m_TempTextBuf.GetBuffer(); i = iBufStartAppend; j = m_TempTextBuf.GetLength() - 1; for (; i < j; i++, j--) @@ -943,17 +914,17 @@ void CPDF_TextPage::SwapTempTextBuf(int32_t iCharListStartAppend, bool CPDF_TextPage::IsRightToLeft(const CPDF_TextObject* pTextObj, const CPDF_Font* pFont, - int nItems) const { - CFX_WideString str; - for (int32_t i = 0; i < nItems; i++) { + size_t nItems) const { + WideString str; + for (size_t i = 0; i < nItems; ++i) { CPDF_TextObjectItem item; pTextObj->GetItemInfo(i, &item); if (item.m_CharCode == static_cast(-1)) continue; - CFX_WideString wstrItem = pFont->UnicodeFromCharCode(item.m_CharCode); - FX_WCHAR wChar = wstrItem.GetAt(0); - if ((wstrItem.IsEmpty() || wChar == 0) && item.m_CharCode) - wChar = (FX_WCHAR)item.m_CharCode; + WideString wstrItem = pFont->UnicodeFromCharCode(item.m_CharCode); + wchar_t wChar = !wstrItem.IsEmpty() ? wstrItem[0] : 0; + if (wChar == 0) + wChar = item.m_CharCode; if (wChar) str += wChar; } @@ -961,8 +932,8 @@ bool CPDF_TextPage::IsRightToLeft(const CPDF_TextObject* pTextObj, } void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { - CPDF_TextObject* pTextObj = Obj.m_pTextObj; - if (FXSYS_fabs(pTextObj->m_Right - pTextObj->m_Left) < 0.01f) + CPDF_TextObject* pTextObj = Obj.m_pTextObj.Get(); + if (fabs(pTextObj->m_Right - pTextObj->m_Left) < 0.01f) return; CFX_Matrix formMatrix = Obj.m_formMatrix; CPDF_Font* pFont = pTextObj->GetFont(); @@ -1007,16 +978,16 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { if (pTextObj->CountChars() == 1) { CPDF_TextObjectItem item; pTextObj->GetCharInfo(0, &item); - CFX_WideString wstrItem = + WideString wstrItem = pTextObj->GetFont()->UnicodeFromCharCode(item.m_CharCode); if (wstrItem.IsEmpty()) - wstrItem += (FX_WCHAR)item.m_CharCode; - FX_WCHAR curChar = wstrItem.GetAt(0); + wstrItem += (wchar_t)item.m_CharCode; + wchar_t curChar = wstrItem[0]; if (curChar == 0x2D || curChar == 0xAD) return; } while (m_TempTextBuf.GetSize() > 0 && - m_TempTextBuf.AsStringC().GetAt(m_TempTextBuf.GetLength() - 1) == + m_TempTextBuf.AsStringView()[m_TempTextBuf.GetLength() - 1] == 0x20) { m_TempTextBuf.Delete(m_TempTextBuf.GetLength() - 1, 1); m_TempCharList.pop_back(); @@ -1040,8 +1011,8 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { } m_pPreTextObj = pTextObj; m_perMatrix = formMatrix; - int nItems = pTextObj->CountItems(); - FX_FLOAT baseSpace = CalculateBaseSpace(pTextObj, matrix); + size_t nItems = pTextObj->CountItems(); + float baseSpace = CalculateBaseSpace(pTextObj, matrix); const bool bR2L = IsRightToLeft(pTextObj, pFont, nItems); const bool bIsBidiAndMirrorInverse = @@ -1050,33 +1021,33 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { int32_t iCharListStartAppend = pdfium::CollectionSize(m_TempCharList); - FX_FLOAT spacing = 0; - for (int i = 0; i < nItems; i++) { + float spacing = 0; + for (size_t i = 0; i < nItems; ++i) { CPDF_TextObjectItem item; PAGECHAR_INFO charinfo; pTextObj->GetItemInfo(i, &item); if (item.m_CharCode == static_cast(-1)) { - CFX_WideString str = m_TempTextBuf.MakeString(); + WideString str = m_TempTextBuf.MakeString(); if (str.IsEmpty()) - str = m_TextBuf.AsStringC(); - if (str.IsEmpty() || str.GetAt(str.GetLength() - 1) == TEXT_SPACE_CHAR) + str = m_TextBuf.AsStringView(); + if (str.IsEmpty() || str[str.GetLength() - 1] == TEXT_SPACE_CHAR) continue; - FX_FLOAT fontsize_h = pTextObj->m_TextState.GetFontSizeH(); + float fontsize_h = pTextObj->m_TextState.GetFontSizeH(); spacing = -fontsize_h * item.m_Origin.x / 1000; continue; } - FX_FLOAT charSpace = pTextObj->m_TextState.GetCharSpace(); + float charSpace = pTextObj->m_TextState.GetCharSpace(); if (charSpace > 0.001) spacing += matrix.TransformDistance(charSpace); else if (charSpace < -0.001) - spacing -= matrix.TransformDistance(FXSYS_fabs(charSpace)); + spacing -= matrix.TransformDistance(fabs(charSpace)); spacing -= baseSpace; if (spacing && i > 0) { int last_width = 0; - FX_FLOAT fontsize_h = pTextObj->m_TextState.GetFontSizeH(); + float fontsize_h = pTextObj->m_TextState.GetFontSizeH(); uint32_t space_charcode = pFont->CharCodeFromUnicode(' '); - FX_FLOAT threshold = 0; + float threshold = 0; if (space_charcode != CPDF_Font::kInvalidCharCode) threshold = fontsize_h * pFont->GetCharWidthF(space_charcode) / 1000; if (threshold > fontsize_h / 3) @@ -1085,9 +1056,9 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { threshold /= 2; if (threshold == 0) { threshold = fontsize_h; - int this_width = FXSYS_abs(GetCharWidth(item.m_CharCode, pFont)); - threshold = this_width > last_width ? (FX_FLOAT)this_width - : (FX_FLOAT)last_width; + int this_width = abs(GetCharWidth(item.m_CharCode, pFont)); + threshold = + this_width > last_width ? (float)this_width : (float)last_width; threshold = NormalizeThreshold(threshold); threshold = fontsize_h * threshold / 1000; } @@ -1109,10 +1080,10 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { continue; } spacing = 0; - CFX_WideString wstrItem = pFont->UnicodeFromCharCode(item.m_CharCode); + WideString wstrItem = pFont->UnicodeFromCharCode(item.m_CharCode); bool bNoUnicode = false; if (wstrItem.IsEmpty() && item.m_CharCode) { - wstrItem += static_cast(item.m_CharCode); + wstrItem += static_cast(item.m_CharCode); bNoUnicode = true; } charinfo.m_Index = -1; @@ -1143,49 +1114,46 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { charinfo.m_CharBox.right = charinfo.m_CharBox.left + pTextObj->GetCharWidth(charinfo.m_CharCode); } - matrix.TransformRect(charinfo.m_CharBox); + charinfo.m_CharBox = matrix.TransformRect(charinfo.m_CharBox); charinfo.m_Matrix = matrix; if (wstrItem.IsEmpty()) { charinfo.m_Unicode = 0; m_TempCharList.push_back(charinfo); m_TempTextBuf.AppendChar(0xfffe); continue; - } else { - int nTotal = wstrItem.GetLength(); - bool bDel = false; - const int count = - std::min(pdfium::CollectionSize(m_TempCharList), 7); - FX_FLOAT threshold = charinfo.m_Matrix.TransformXDistance( - (FX_FLOAT)TEXT_CHARRATIO_GAPDELTA * pTextObj->GetFontSize()); - for (int n = pdfium::CollectionSize(m_TempCharList); - n > pdfium::CollectionSize(m_TempCharList) - count; n--) { - const PAGECHAR_INFO& charinfo1 = m_TempCharList[n - 1]; - CFX_PointF diff = charinfo1.m_Origin - charinfo.m_Origin; - if (charinfo1.m_CharCode == charinfo.m_CharCode && - charinfo1.m_pTextObj->GetFont() == charinfo.m_pTextObj->GetFont() && - FXSYS_fabs(diff.x) < threshold && FXSYS_fabs(diff.y) < threshold) { - bDel = true; - break; - } + } + int nTotal = wstrItem.GetLength(); + bool bDel = false; + const int count = std::min(pdfium::CollectionSize(m_TempCharList), 7); + float threshold = charinfo.m_Matrix.TransformXDistance( + (float)TEXT_CHARRATIO_GAPDELTA * pTextObj->GetFontSize()); + for (int n = pdfium::CollectionSize(m_TempCharList); + n > pdfium::CollectionSize(m_TempCharList) - count; n--) { + const PAGECHAR_INFO& charinfo1 = m_TempCharList[n - 1]; + CFX_PointF diff = charinfo1.m_Origin - charinfo.m_Origin; + if (charinfo1.m_CharCode == charinfo.m_CharCode && + charinfo1.m_pTextObj->GetFont() == charinfo.m_pTextObj->GetFont() && + fabs(diff.x) < threshold && fabs(diff.y) < threshold) { + bDel = true; + break; } - if (!bDel) { - for (int nIndex = 0; nIndex < nTotal; nIndex++) { - charinfo.m_Unicode = wstrItem.GetAt(nIndex); - if (charinfo.m_Unicode) { - charinfo.m_Index = m_TextBuf.GetLength(); - m_TempTextBuf.AppendChar(charinfo.m_Unicode); - } else { - m_TempTextBuf.AppendChar(0xfffe); - } - m_TempCharList.push_back(charinfo); - } - } else if (i == 0) { - CFX_WideString str = m_TempTextBuf.MakeString(); - if (!str.IsEmpty() && - str.GetAt(str.GetLength() - 1) == TEXT_SPACE_CHAR) { - m_TempTextBuf.Delete(m_TempTextBuf.GetLength() - 1, 1); - m_TempCharList.pop_back(); + } + if (!bDel) { + for (int nIndex = 0; nIndex < nTotal; nIndex++) { + charinfo.m_Unicode = wstrItem[nIndex]; + if (charinfo.m_Unicode) { + charinfo.m_Index = m_TextBuf.GetLength(); + m_TempTextBuf.AppendChar(charinfo.m_Unicode); + } else { + m_TempTextBuf.AppendChar(0xfffe); } + m_TempCharList.push_back(charinfo); + } + } else if (i == 0) { + WideString str = m_TempTextBuf.MakeString(); + if (!str.IsEmpty() && str[str.GetLength() - 1] == TEXT_SPACE_CHAR) { + m_TempTextBuf.Delete(m_TempTextBuf.GetLength() - 1, 1); + m_TempCharList.pop_back(); } } } @@ -1195,8 +1163,8 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj) { CPDF_TextPage::TextOrientation CPDF_TextPage::GetTextObjectWritingMode( const CPDF_TextObject* pTextObj) const { - int32_t nChars = pTextObj->CountChars(); - if (nChars == 1) + size_t nChars = pTextObj->CountChars(); + if (nChars <= 1) return m_TextlineDir; CPDF_TextObjectItem first, last; @@ -1207,8 +1175,8 @@ CPDF_TextPage::TextOrientation CPDF_TextPage::GetTextObjectWritingMode( first.m_Origin = textMatrix.Transform(first.m_Origin); last.m_Origin = textMatrix.Transform(last.m_Origin); - FX_FLOAT dX = FXSYS_fabs(last.m_Origin.x - first.m_Origin.x); - FX_FLOAT dY = FXSYS_fabs(last.m_Origin.y - first.m_Origin.y); + float dX = fabs(last.m_Origin.x - first.m_Origin.x); + float dY = fabs(last.m_Origin.y - first.m_Origin.y); if (dX <= 0.0001f && dY <= 0.0001f) return TextOrientation::Unknown; @@ -1223,38 +1191,38 @@ CPDF_TextPage::TextOrientation CPDF_TextPage::GetTextObjectWritingMode( return m_TextlineDir; } -bool CPDF_TextPage::IsHyphen(FX_WCHAR curChar) { - CFX_WideString strCurText = m_TempTextBuf.MakeString(); - if (strCurText.IsEmpty()) - strCurText = m_TextBuf.AsStringC(); - FX_STRSIZE nCount = strCurText.GetLength(); - int nIndex = nCount - 1; - FX_WCHAR wcTmp = strCurText.GetAt(nIndex); - while (wcTmp == 0x20 && nIndex <= nCount - 1 && nIndex >= 0) - wcTmp = strCurText.GetAt(--nIndex); - if (0x2D == wcTmp || 0xAD == wcTmp) { - if (--nIndex > 0) { - FX_WCHAR preChar = strCurText.GetAt((nIndex)); - if (((preChar >= L'A' && preChar <= L'Z') || - (preChar >= L'a' && preChar <= L'z')) && - ((curChar >= L'A' && curChar <= L'Z') || - (curChar >= L'a' && curChar <= L'z'))) { - return true; - } - } - const PAGECHAR_INFO* preInfo; - if (!m_TempCharList.empty()) - preInfo = &m_TempCharList.back(); - else if (!m_CharList.empty()) - preInfo = &m_CharList.back(); - else - return false; - if (FPDFTEXT_CHAR_PIECE == preInfo->m_Flag && - (0xAD == preInfo->m_Unicode || 0x2D == preInfo->m_Unicode)) { +bool CPDF_TextPage::IsHyphen(wchar_t curChar) const { + WideStringView curText = m_TempTextBuf.AsStringView(); + if (curText.IsEmpty()) + curText = m_TextBuf.AsStringView(); + + if (curText.IsEmpty()) + return false; + + auto iter = curText.rbegin(); + for (; (iter + 1) != curText.rend() && *iter == 0x20; iter++) { + // Do nothing + } + + if (!IsHyphenCode(*iter)) + return false; + + if ((iter + 1) != curText.rend()) { + iter++; + if (FXSYS_iswalpha(*iter) && FXSYS_iswalpha(*iter)) return true; - } } - return false; + + const PAGECHAR_INFO* preInfo; + if (!m_TempCharList.empty()) + preInfo = &m_TempCharList.back(); + else if (!m_CharList.empty()) + preInfo = &m_CharList.back(); + else + return false; + + return FPDFTEXT_CHAR_PIECE == preInfo->m_Flag && + IsHyphenCode(preInfo->m_Unicode); } CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( @@ -1263,26 +1231,30 @@ CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( FindPreviousTextObject(); TextOrientation WritingMode = GetTextObjectWritingMode(pObj); if (WritingMode == TextOrientation::Unknown) - WritingMode = GetTextObjectWritingMode(m_pPreTextObj); + WritingMode = GetTextObjectWritingMode(m_pPreTextObj.Get()); + + size_t nItem = m_pPreTextObj->CountItems(); + if (nItem == 0) + return GenerateCharacter::None; - CFX_FloatRect this_rect = pObj->GetRect(); - CFX_FloatRect prev_rect = m_pPreTextObj->GetRect(); CPDF_TextObjectItem PrevItem; - CPDF_TextObjectItem item; - int nItem = m_pPreTextObj->CountItems(); m_pPreTextObj->GetItemInfo(nItem - 1, &PrevItem); + + CPDF_TextObjectItem item; pObj->GetItemInfo(0, &item); - CFX_WideString wstrItem = - pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode); + + CFX_FloatRect this_rect = pObj->GetRect(); + CFX_FloatRect prev_rect = m_pPreTextObj->GetRect(); + + WideString wstrItem = pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode); if (wstrItem.IsEmpty()) - wstrItem += static_cast(item.m_CharCode); - FX_WCHAR curChar = wstrItem.GetAt(0); + wstrItem += static_cast(item.m_CharCode); + wchar_t curChar = wstrItem[0]; if (WritingMode == TextOrientation::Horizontal) { if (this_rect.Height() > 4.5 && prev_rect.Height() > 4.5) { - FX_FLOAT top = - this_rect.top < prev_rect.top ? this_rect.top : prev_rect.top; - FX_FLOAT bottom = this_rect.bottom > prev_rect.bottom ? this_rect.bottom - : prev_rect.bottom; + float top = this_rect.top < prev_rect.top ? this_rect.top : prev_rect.top; + float bottom = this_rect.bottom > prev_rect.bottom ? this_rect.bottom + : prev_rect.bottom; if (bottom >= top) { return IsHyphen(curChar) ? GenerateCharacter::Hyphen : GenerateCharacter::LineBreak; @@ -1291,11 +1263,10 @@ CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( } else if (WritingMode == TextOrientation::Vertical) { if (this_rect.Width() > pObj->GetFontSize() * 0.1f && prev_rect.Width() > m_pPreTextObj->GetFontSize() * 0.1f) { - FX_FLOAT left = this_rect.left > m_CurlineRect.left ? this_rect.left - : m_CurlineRect.left; - FX_FLOAT right = this_rect.right < m_CurlineRect.right - ? this_rect.right - : m_CurlineRect.right; + float left = this_rect.left > m_CurlineRect.left ? this_rect.left + : m_CurlineRect.left; + float right = this_rect.right < m_CurlineRect.right ? this_rect.right + : m_CurlineRect.right; if (right <= left) { return IsHyphen(curChar) ? GenerateCharacter::Hyphen : GenerateCharacter::LineBreak; @@ -1303,21 +1274,19 @@ CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( } } - FX_FLOAT last_pos = PrevItem.m_Origin.x; + float last_pos = PrevItem.m_Origin.x; int nLastWidth = GetCharWidth(PrevItem.m_CharCode, m_pPreTextObj->GetFont()); - FX_FLOAT last_width = nLastWidth * m_pPreTextObj->GetFontSize() / 1000; - last_width = FXSYS_fabs(last_width); + float last_width = nLastWidth * m_pPreTextObj->GetFontSize() / 1000; + last_width = fabs(last_width); int nThisWidth = GetCharWidth(item.m_CharCode, pObj->GetFont()); - FX_FLOAT this_width = nThisWidth * pObj->GetFontSize() / 1000; - this_width = FXSYS_fabs(this_width); - FX_FLOAT threshold = - last_width > this_width ? last_width / 4 : this_width / 4; + float this_width = nThisWidth * pObj->GetFontSize() / 1000; + this_width = fabs(this_width); + float threshold = last_width > this_width ? last_width / 4 : this_width / 4; CFX_Matrix prev_matrix = m_pPreTextObj->GetTextMatrix(); prev_matrix.Concat(m_perMatrix); - CFX_Matrix prev_reverse; - prev_reverse.SetReverse(prev_matrix); + CFX_Matrix prev_reverse = prev_matrix.GetInverse(); CFX_PointF pos = prev_reverse.Transform(formMatrix.Transform(pObj->GetPos())); if (last_width < this_width) @@ -1332,8 +1301,7 @@ CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( rect1.Intersect(rect2); if ((rect1.IsEmpty() && rect2.Height() > 5 && rect3.Height() > 5) || ((pos.y > threshold * 2 || pos.y < threshold * -3) && - (FXSYS_fabs(pos.y) < 1 ? FXSYS_fabs(pos.x) < FXSYS_fabs(pos.y) - : true))) { + (fabs(pos.y) < 1 ? fabs(pos.x) < fabs(pos.y) : true))) { bNewline = true; if (nItem > 1) { CPDF_TextObjectItem tempItem; @@ -1361,27 +1329,26 @@ CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( : GenerateCharacter::LineBreak; } - int32_t nChars = pObj->CountChars(); - if (nChars == 1 && (0x2D == curChar || 0xAD == curChar) && + if (pObj->CountChars() == 1 && (0x2D == curChar || 0xAD == curChar) && IsHyphen(curChar)) { return GenerateCharacter::Hyphen; } - CFX_WideString PrevStr = + WideString PrevStr = m_pPreTextObj->GetFont()->UnicodeFromCharCode(PrevItem.m_CharCode); - FX_WCHAR preChar = PrevStr.GetAt(PrevStr.GetLength() - 1); + wchar_t preChar = PrevStr.Last(); CFX_Matrix matrix = pObj->GetTextMatrix(); matrix.Concat(formMatrix); - threshold = (FX_FLOAT)(nLastWidth > nThisWidth ? nLastWidth : nThisWidth); + threshold = (float)(nLastWidth > nThisWidth ? nLastWidth : nThisWidth); threshold = threshold > 400 ? (threshold < 700 ? threshold / 4 : (threshold > 800 ? threshold / 6 : threshold / 5)) : (threshold / 2); if (nLastWidth >= nThisWidth) { - threshold *= FXSYS_fabs(m_pPreTextObj->GetFontSize()); + threshold *= fabs(m_pPreTextObj->GetFontSize()); } else { - threshold *= FXSYS_fabs(pObj->GetFontSize()); + threshold *= fabs(pObj->GetFontSize()); threshold = matrix.TransformDistance(threshold); threshold = prev_reverse.TransformDistance(threshold); } @@ -1390,8 +1357,8 @@ CPDF_TextPage::GenerateCharacter CPDF_TextPage::ProcessInsertObject( (threshold < 1.39001 && threshold > 1.38999)) { threshold *= 1.5; } - if (FXSYS_fabs(last_pos + last_width - pos.x) > threshold && - curChar != L' ' && preChar != L' ') { + if (fabs(last_pos + last_width - pos.x) > threshold && curChar != L' ' && + preChar != L' ') { if (curChar != L' ' && preChar != L' ') { if ((pos.x - last_pos - last_width) > threshold || (last_pos - pos.x - last_width) > threshold) { @@ -1416,11 +1383,11 @@ bool CPDF_TextPage::IsSameTextObject(CPDF_TextObject* pTextObj1, CFX_FloatRect rcPreObj = pTextObj2->GetRect(); CFX_FloatRect rcCurObj = pTextObj1->GetRect(); if (rcPreObj.IsEmpty() && rcCurObj.IsEmpty()) { - FX_FLOAT dbXdif = FXSYS_fabs(rcPreObj.left - rcCurObj.left); + float dbXdif = fabs(rcPreObj.left - rcCurObj.left); size_t nCount = m_CharList.size(); if (nCount >= 2) { PAGECHAR_INFO perCharTemp = m_CharList[nCount - 2]; - FX_FLOAT dbSpace = perCharTemp.m_CharBox.Width(); + float dbSpace = perCharTemp.m_CharBox.Width(); if (dbXdif > dbSpace) return false; } @@ -1429,24 +1396,24 @@ bool CPDF_TextPage::IsSameTextObject(CPDF_TextObject* pTextObj1, rcPreObj.Intersect(rcCurObj); if (rcPreObj.IsEmpty()) return false; - if (FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) > - rcCurObj.Width() / 2) { + if (fabs(rcPreObj.Width() - rcCurObj.Width()) > rcCurObj.Width() / 2) { return false; } if (pTextObj2->GetFontSize() != pTextObj1->GetFontSize()) return false; } - int nPreCount = pTextObj2->CountItems(); - int nCurCount = pTextObj1->CountItems(); - if (nPreCount != nCurCount) + + size_t nPreCount = pTextObj2->CountItems(); + if (nPreCount != pTextObj1->CountItems()) return false; + // If both objects have no items, consider them same. - if (!nPreCount) + if (nPreCount == 0) return true; CPDF_TextObjectItem itemPer; CPDF_TextObjectItem itemCur; - for (int i = 0; i < nPreCount; i++) { + for (size_t i = 0; i < nPreCount; ++i) { pTextObj2->GetItemInfo(i, &itemPer); pTextObj1->GetItemInfo(i, &itemCur); if (itemCur.m_CharCode != itemPer.m_CharCode) @@ -1454,12 +1421,12 @@ bool CPDF_TextPage::IsSameTextObject(CPDF_TextObject* pTextObj1, } CFX_PointF diff = pTextObj1->GetPos() - pTextObj2->GetPos(); - FX_FLOAT font_size = pTextObj2->GetFontSize(); - FX_FLOAT char_size = GetCharWidth(itemPer.m_CharCode, pTextObj2->GetFont()); - FX_FLOAT max_pre_size = + float font_size = pTextObj2->GetFontSize(); + float char_size = GetCharWidth(itemPer.m_CharCode, pTextObj2->GetFont()); + float max_pre_size = std::max(std::max(rcPreObj.Height(), rcPreObj.Width()), font_size); - if (FXSYS_fabs(diff.x) > char_size * font_size / 1000 * 0.9 || - FXSYS_fabs(diff.y) > max_pre_size / 8) { + if (fabs(diff.x) > char_size * font_size / 1000 * 0.9 || + fabs(diff.y) > max_pre_size / 8) { return false; } return true; @@ -1482,7 +1449,7 @@ bool CPDF_TextPage::IsSameAsPreTextObject( return false; } -bool CPDF_TextPage::GenerateCharInfo(FX_WCHAR unicode, PAGECHAR_INFO& info) { +bool CPDF_TextPage::GenerateCharInfo(wchar_t unicode, PAGECHAR_INFO& info) { const PAGECHAR_INFO* preChar; if (!m_TempCharList.empty()) preChar = &m_TempCharList.back(); @@ -1503,8 +1470,8 @@ bool CPDF_TextPage::GenerateCharInfo(FX_WCHAR unicode, PAGECHAR_INFO& info) { GetCharWidth(preChar->m_CharCode, preChar->m_pTextObj->GetFont()); } - FX_FLOAT fFontSize = preChar->m_pTextObj ? preChar->m_pTextObj->GetFontSize() - : preChar->m_CharBox.Height(); + float fFontSize = preChar->m_pTextObj ? preChar->m_pTextObj->GetFontSize() + : preChar->m_CharBox.Height(); if (!fFontSize) fFontSize = kDefaultFontSize; diff --git a/core/fpdftext/cpdf_textpage.h b/core/fpdftext/cpdf_textpage.h index 91942d1bec06bf6bad5c0e24dd4e468265218c76..51d066071e40fdc57023bd761142e16dd3898cca 100644 --- a/core/fpdftext/cpdf_textpage.h +++ b/core/fpdftext/cpdf_textpage.h @@ -11,9 +11,10 @@ #include #include "core/fpdfapi/page/cpdf_pageobjectlist.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/cfx_widetextbuf.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDF_Font; class CPDF_FormObject; @@ -24,7 +25,6 @@ class CPDF_TextObject; #define FPDFTEXT_MATCHWHOLEWORD 0x00000002 #define FPDFTEXT_CONSECUTIVE 0x00000004 -#define FPDFTEXT_CHAR_ERROR -1 #define FPDFTEXT_CHAR_NORMAL 0 #define FPDFTEXT_CHAR_GENERATED 1 #define FPDFTEXT_CHAR_UNUNICODE 2 @@ -34,10 +34,9 @@ class CPDF_TextObject; #define TEXT_SPACE_CHAR L' ' #define TEXT_LINEFEED_CHAR L'\n' #define TEXT_RETURN_CHAR L'\r' +#define TEXT_HYPHEN_CHAR L'-' #define TEXT_EMPTY L"" -#define TEXT_SPACE L" " -#define TEXT_RETURN_LINEFEED L"\r\n" -#define TEXT_LINEFEED L"\n" +#define TEXT_HYPHEN L"-" #define TEXT_CHARRATIO_GAPDELTA 0.070 enum class FPDFText_MarkedContent { Pass = 0, Done, Delay }; @@ -49,13 +48,13 @@ class FPDF_CHAR_INFO { FPDF_CHAR_INFO(); ~FPDF_CHAR_INFO(); - FX_WCHAR m_Unicode; - FX_WCHAR m_Charcode; + wchar_t m_Unicode; + wchar_t m_Charcode; int32_t m_Flag; - FX_FLOAT m_FontSize; + float m_FontSize; CFX_PointF m_Origin; CFX_FloatRect m_CharBox; - CPDF_TextObject* m_pTextObj; + UnownedPtr m_pTextObj; CFX_Matrix m_Matrix; }; @@ -72,16 +71,20 @@ class PAGECHAR_INFO { int m_Index; int m_CharCode; - FX_WCHAR m_Unicode; + wchar_t m_Unicode; int32_t m_Flag; CFX_PointF m_Origin; CFX_FloatRect m_CharBox; - CPDF_TextObject* m_pTextObj; + UnownedPtr m_pTextObj; CFX_Matrix m_Matrix; }; struct PDFTEXT_Obj { - CPDF_TextObject* m_pTextObj; + PDFTEXT_Obj(); + PDFTEXT_Obj(const PDFTEXT_Obj& that); + ~PDFTEXT_Obj(); + + UnownedPtr m_pTextObj; CFX_Matrix m_formMatrix; }; @@ -99,14 +102,16 @@ class CPDF_TextPage { void GetCharInfo(int index, FPDF_CHAR_INFO* info) const; std::vector GetRectArray(int start, int nCount) const; int GetIndexAtPos(const CFX_PointF& point, const CFX_SizeF& tolerance) const; - CFX_WideString GetTextByRect(const CFX_FloatRect& rect) const; - CFX_WideString GetPageText(int start = 0, int nCount = -1) const; + WideString GetTextByRect(const CFX_FloatRect& rect) const; + + // Returns string with the text from |m_TextBuf| that are covered by the input + // range. |start| and |count| are in terms of the m_CharIndex, so the range + // will be converted into appropriate indices. + WideString GetPageText(int start, int count) const; + WideString GetAllPageText() const { return GetPageText(0, CountChars()); } + int CountRects(int start, int nCount); - void GetRect(int rectIndex, - FX_FLOAT& left, - FX_FLOAT& top, - FX_FLOAT& right, - FX_FLOAT& bottom) const; + bool GetRect(int rectIndex, CFX_FloatRect* pRect) const; static bool IsRectIntersect(const CFX_FloatRect& rect1, const CFX_FloatRect& rect2); @@ -125,7 +130,7 @@ class CPDF_TextPage { Hyphen, }; - bool IsHyphen(FX_WCHAR curChar); + bool IsHyphen(wchar_t curChar) const; bool IsControlChar(const PAGECHAR_INFO& charInfo); void ProcessObject(); void ProcessFormObject(CPDF_FormObject* pFormObj, @@ -137,7 +142,7 @@ class CPDF_TextPage { CPDF_PageObjectList::const_iterator ObjPos); GenerateCharacter ProcessInsertObject(const CPDF_TextObject* pObj, const CFX_Matrix& formMatrix); - bool GenerateCharInfo(FX_WCHAR unicode, PAGECHAR_INFO& info); + bool GenerateCharInfo(wchar_t unicode, PAGECHAR_INFO& info); bool IsSameAsPreTextObject(CPDF_TextObject* pTextObj, const CPDF_PageObjectList* pObjList, CPDF_PageObjectList::const_iterator ObjPos); @@ -148,26 +153,26 @@ class CPDF_TextPage { void ProcessMarkedContent(PDFTEXT_Obj pObj); void CheckMarkedContentObject(int32_t& start, int32_t& nCount) const; void FindPreviousTextObject(); - void AddCharInfoByLRDirection(FX_WCHAR wChar, PAGECHAR_INFO info); - void AddCharInfoByRLDirection(FX_WCHAR wChar, PAGECHAR_INFO info); + void AddCharInfoByLRDirection(wchar_t wChar, PAGECHAR_INFO info); + void AddCharInfoByRLDirection(wchar_t wChar, PAGECHAR_INFO info); TextOrientation GetTextObjectWritingMode( const CPDF_TextObject* pTextObj) const; TextOrientation FindTextlineFlowOrientation() const; - void AppendGeneratedCharacter(FX_WCHAR unicode, const CFX_Matrix& formMatrix); + void AppendGeneratedCharacter(wchar_t unicode, const CFX_Matrix& formMatrix); void SwapTempTextBuf(int32_t iCharListStartAppend, int32_t iBufStartAppend); bool IsRightToLeft(const CPDF_TextObject* pTextObj, const CPDF_Font* pFont, - int nItems) const; + size_t nItems) const; - const CPDF_Page* const m_pPage; + UnownedPtr const m_pPage; std::vector m_CharIndex; std::deque m_CharList; std::deque m_TempCharList; CFX_WideTextBuf m_TextBuf; CFX_WideTextBuf m_TempTextBuf; const FPDFText_Direction m_parserflag; - CPDF_TextObject* m_pPreTextObj; + UnownedPtr m_pPreTextObj; CFX_Matrix m_perMatrix; bool m_bIsParsed; CFX_Matrix m_DisplayMatrix; diff --git a/core/fpdftext/cpdf_textpagefind.cpp b/core/fpdftext/cpdf_textpagefind.cpp index a79b5e7e8a1ca017bf5aa998fd53851221ea3cd5..52fdb4aa382858e32a06423d3578dafd8d89b268 100644 --- a/core/fpdftext/cpdf_textpagefind.cpp +++ b/core/fpdftext/cpdf_textpagefind.cpp @@ -17,7 +17,7 @@ namespace { -bool IsIgnoreSpaceCharacter(FX_WCHAR curChar) { +bool IsIgnoreSpaceCharacter(wchar_t curChar) { if (curChar < 255 || (curChar >= 0x0600 && curChar <= 0x06FF) || (curChar >= 0xFE70 && curChar <= 0xFEFF) || (curChar >= 0xFB50 && curChar <= 0xFDFF) || @@ -36,14 +36,12 @@ bool IsIgnoreSpaceCharacter(FX_WCHAR curChar) { CPDF_TextPageFind::CPDF_TextPageFind(const CPDF_TextPage* pTextPage) : m_pTextPage(pTextPage), m_flags(0), - m_findNextStart(-1), - m_findPreStart(-1), m_bMatchCase(false), m_bMatchWholeWord(false), m_resStart(0), m_resEnd(-1), m_IsFind(false) { - m_strText = m_pTextPage->GetPageText(); + m_strText = m_pTextPage->GetAllPageText(); int nCount = pTextPage->CountChars(); if (nCount) m_CharIndex.push_back(0); @@ -81,14 +79,14 @@ int CPDF_TextPageFind::GetCharIndex(int index) const { return m_pTextPage->CharIndexFromTextIndex(index); } -bool CPDF_TextPageFind::FindFirst(const CFX_WideString& findwhat, +bool CPDF_TextPageFind::FindFirst(const WideString& findwhat, int flags, - int startPos) { + Optional startPos) { if (!m_pTextPage) return false; if (m_strText.IsEmpty() || m_bMatchCase != (flags & FPDFTEXT_MATCHCASE)) - m_strText = m_pTextPage->GetPageText(); - CFX_WideString findwhatStr = findwhat; + m_strText = m_pTextPage->GetAllPageText(); + WideString findwhatStr = findwhat; m_findWhat = findwhatStr; m_flags = flags; m_bMatchCase = flags & FPDFTEXT_MATCHCASE; @@ -96,30 +94,32 @@ bool CPDF_TextPageFind::FindFirst(const CFX_WideString& findwhat, m_IsFind = false; return true; } - FX_STRSIZE len = findwhatStr.GetLength(); + size_t len = findwhatStr.GetLength(); if (!m_bMatchCase) { findwhatStr.MakeLower(); m_strText.MakeLower(); } m_bMatchWholeWord = !!(flags & FPDFTEXT_MATCHWHOLEWORD); m_findNextStart = startPos; - if (startPos == -1) - m_findPreStart = m_strText.GetLength() - 1; - else + if (!startPos.has_value()) { + if (!m_strText.IsEmpty()) + m_findPreStart = m_strText.GetLength() - 1; + } else { m_findPreStart = startPos; + } + m_csFindWhatArray.clear(); - int i = 0; - while (i < len) { - if (findwhatStr.GetAt(i) != ' ') + size_t i = 0; + for (i = 0; i < len; ++i) + if (findwhatStr[i] != ' ') break; - i++; - } if (i < len) ExtractFindWhat(findwhatStr); else m_csFindWhatArray.push_back(findwhatStr); if (m_csFindWhatArray.empty()) return false; + m_IsFind = true; m_resStart = 0; m_resEnd = -1; @@ -130,27 +130,26 @@ bool CPDF_TextPageFind::FindNext() { if (!m_pTextPage) return false; m_resArray.clear(); - if (m_findNextStart == -1) + if (!m_findNextStart.has_value()) return false; if (m_strText.IsEmpty()) { m_IsFind = false; return m_IsFind; } - int strLen = m_strText.GetLength(); - if (m_findNextStart > strLen - 1) { + size_t strLen = m_strText.GetLength(); + if (m_findNextStart.value() > strLen - 1) { m_IsFind = false; return m_IsFind; } int nCount = pdfium::CollectionSize(m_csFindWhatArray); - int nResultPos = 0; - int nStartPos = 0; - nStartPos = m_findNextStart; + Optional nResultPos = 0; + size_t nStartPos = m_findNextStart.value(); bool bSpaceStart = false; for (int iWord = 0; iWord < nCount; iWord++) { - CFX_WideString csWord = m_csFindWhatArray[iWord]; + WideString csWord = m_csFindWhatArray[iWord]; if (csWord.IsEmpty()) { if (iWord == nCount - 1) { - FX_WCHAR strInsert = m_strText.GetAt(nStartPos); + wchar_t strInsert = m_strText[nStartPos]; if (strInsert == TEXT_LINEFEED_CHAR || strInsert == TEXT_SPACE_CHAR || strInsert == TEXT_RETURN_CHAR || strInsert == 160) { nResultPos = nStartPos + 1; @@ -162,28 +161,27 @@ bool CPDF_TextPageFind::FindNext() { } continue; } - int endIndex; nResultPos = m_strText.Find(csWord.c_str(), nStartPos); - if (nResultPos == -1) { + if (!nResultPos.has_value()) { m_IsFind = false; return m_IsFind; } - endIndex = nResultPos + csWord.GetLength() - 1; + size_t endIndex = nResultPos.value() + csWord.GetLength() - 1; if (iWord == 0) - m_resStart = nResultPos; + m_resStart = nResultPos.value(); bool bMatch = true; if (iWord != 0 && !bSpaceStart) { - int PreResEndPos = nStartPos; - int curChar = csWord.GetAt(0); - CFX_WideString lastWord = m_csFindWhatArray[iWord - 1]; - int lastChar = lastWord.GetAt(lastWord.GetLength() - 1); - if (nStartPos == nResultPos && + size_t PreResEndPos = nStartPos; + int curChar = csWord[0]; + WideString lastWord = m_csFindWhatArray[iWord - 1]; + int lastChar = lastWord[lastWord.GetLength() - 1]; + if (nStartPos == nResultPos.value() && !(IsIgnoreSpaceCharacter(lastChar) || IsIgnoreSpaceCharacter(curChar))) { bMatch = false; } - for (int d = PreResEndPos; d < nResultPos; d++) { - FX_WCHAR strInsert = m_strText.GetAt(d); + for (size_t d = PreResEndPos; d < nResultPos.value(); d++) { + wchar_t strInsert = m_strText[d]; if (strInsert != TEXT_LINEFEED_CHAR && strInsert != TEXT_SPACE_CHAR && strInsert != TEXT_RETURN_CHAR && strInsert != 160) { bMatch = false; @@ -191,19 +189,19 @@ bool CPDF_TextPageFind::FindNext() { } } } else if (bSpaceStart) { - if (nResultPos > 0) { - FX_WCHAR strInsert = m_strText.GetAt(nResultPos - 1); + if (nResultPos.value() > 0) { + wchar_t strInsert = m_strText[nResultPos.value() - 1]; if (strInsert != TEXT_LINEFEED_CHAR && strInsert != TEXT_SPACE_CHAR && strInsert != TEXT_RETURN_CHAR && strInsert != 160) { bMatch = false; - m_resStart = nResultPos; + m_resStart = nResultPos.value(); } else { - m_resStart = nResultPos - 1; + m_resStart = nResultPos.value() - 1; } } } if (m_bMatchWholeWord && bMatch) { - bMatch = IsMatchWholeWord(m_strText, nResultPos, endIndex); + bMatch = IsMatchWholeWord(m_strText, nResultPos.value(), endIndex); } nStartPos = endIndex + 1; if (!bMatch) { @@ -214,7 +212,7 @@ bool CPDF_TextPageFind::FindNext() { nStartPos = m_resStart + m_csFindWhatArray[0].GetLength(); } } - m_resEnd = nResultPos + m_csFindWhatArray.back().GetLength() - 1; + m_resEnd = nResultPos.value() + m_csFindWhatArray.back().GetLength() - 1; m_IsFind = true; int resStart = GetCharIndex(m_resStart); int resEnd = GetCharIndex(m_resEnd); @@ -233,23 +231,25 @@ bool CPDF_TextPageFind::FindPrev() { if (!m_pTextPage) return false; m_resArray.clear(); - if (m_strText.IsEmpty() || m_findPreStart < 0) { + if (m_strText.IsEmpty() || !m_findPreStart.has_value()) { m_IsFind = false; return m_IsFind; } - CPDF_TextPageFind findEngine(m_pTextPage); - bool ret = findEngine.FindFirst(m_findWhat, m_flags); + CPDF_TextPageFind findEngine(m_pTextPage.Get()); + bool ret = findEngine.FindFirst(m_findWhat, m_flags, Optional(0)); if (!ret) { m_IsFind = false; return m_IsFind; } - int order = -1, MatchedCount = 0; + int order = -1; + int MatchedCount = 0; while (ret) { ret = findEngine.FindNext(); if (ret) { int order1 = findEngine.GetCurOrder(); int MatchedCount1 = findEngine.GetMatchedCount(); - if (((order1 + MatchedCount1) - 1) > m_findPreStart) + int temp = order1 + MatchedCount1; + if (temp < 0 || static_cast(temp) > m_findPreStart.value() + 1) break; order = order1; MatchedCount = MatchedCount1; @@ -273,65 +273,67 @@ bool CPDF_TextPageFind::FindPrev() { return m_IsFind; } -void CPDF_TextPageFind::ExtractFindWhat(const CFX_WideString& findwhat) { +void CPDF_TextPageFind::ExtractFindWhat(const WideString& findwhat) { if (findwhat.IsEmpty()) return; int index = 0; while (1) { - CFX_WideString csWord = TEXT_EMPTY; - int ret = - ExtractSubString(csWord, findwhat.c_str(), index, TEXT_SPACE_CHAR); - if (csWord.IsEmpty()) { - if (ret) { - m_csFindWhatArray.push_back(L""); - index++; - continue; - } else { - break; - } + Optional word = + ExtractSubString(findwhat.c_str(), index, TEXT_SPACE_CHAR); + if (!word) + break; + + if (word->IsEmpty()) { + m_csFindWhatArray.push_back(L""); + index++; + continue; } - int pos = 0; - while (pos < csWord.GetLength()) { - CFX_WideString curStr = csWord.Mid(pos, 1); - FX_WCHAR curChar = csWord.GetAt(pos); + + size_t pos = 0; + while (pos < word->GetLength()) { + WideString curStr = word->Mid(pos, 1); + wchar_t curChar = word->operator[](pos); if (IsIgnoreSpaceCharacter(curChar)) { if (pos > 0 && curChar == 0x2019) { pos++; continue; } if (pos > 0) - m_csFindWhatArray.push_back(csWord.Mid(0, pos)); + m_csFindWhatArray.push_back(word->Left(pos)); m_csFindWhatArray.push_back(curStr); - if (pos == csWord.GetLength() - 1) { - csWord.clear(); + if (pos == word->GetLength() - 1) { + word->clear(); break; } - csWord = csWord.Right(csWord.GetLength() - pos - 1); + word.emplace(word->Right(word->GetLength() - pos - 1)); pos = 0; continue; } pos++; } - if (!csWord.IsEmpty()) - m_csFindWhatArray.push_back(csWord); + + if (!word->IsEmpty()) + m_csFindWhatArray.push_back(word.value()); index++; } } -bool CPDF_TextPageFind::IsMatchWholeWord(const CFX_WideString& csPageText, - int startPos, - int endPos) { - FX_WCHAR char_left = 0; - FX_WCHAR char_right = 0; - int char_count = endPos - startPos + 1; - if (char_count < 1) +bool CPDF_TextPageFind::IsMatchWholeWord(const WideString& csPageText, + size_t startPos, + size_t endPos) { + if (startPos > endPos) return false; - if (char_count == 1 && csPageText.GetAt(startPos) > 255) + wchar_t char_left = 0; + wchar_t char_right = 0; + size_t char_count = endPos - startPos + 1; + if (char_count == 0) + return false; + if (char_count == 1 && csPageText[startPos] > 255) return true; - if (startPos - 1 >= 0) - char_left = csPageText.GetAt(startPos - 1); + if (startPos >= 1) + char_left = csPageText[startPos - 1]; if (startPos + char_count < csPageText.GetLength()) - char_right = csPageText.GetAt(startPos + char_count); + char_right = csPageText[startPos + char_count]; if ((char_left > 'A' && char_left < 'a') || (char_left > 'a' && char_left < 'z') || (char_left > 0xfb00 && char_left < 0xfb06) || std::iswdigit(char_left) || @@ -348,52 +350,38 @@ bool CPDF_TextPageFind::IsMatchWholeWord(const CFX_WideString& csPageText, return false; } if (char_count > 0) { - if (csPageText.GetAt(startPos) >= L'0' && - csPageText.GetAt(startPos) <= L'9' && char_left >= L'0' && - char_left <= L'9') { + if (std::iswdigit(char_left) && std::iswdigit(csPageText[startPos])) return false; - } - if (csPageText.GetAt(endPos) >= L'0' && csPageText.GetAt(endPos) <= L'9' && - char_right >= L'0' && char_right <= L'9') { + if (std::iswdigit(char_right) && std::iswdigit(csPageText[endPos])) return false; - } } return true; } -bool CPDF_TextPageFind::ExtractSubString(CFX_WideString& rString, - const FX_WCHAR* lpszFullString, - int iSubString, - FX_WCHAR chSep) { +Optional CPDF_TextPageFind::ExtractSubString( + const wchar_t* lpszFullString, + int iSubString, + wchar_t chSep) { if (!lpszFullString) - return false; + return {}; + while (iSubString--) { lpszFullString = std::wcschr(lpszFullString, chSep); - if (!lpszFullString) { - rString.clear(); - return false; - } + if (!lpszFullString) + return {}; + lpszFullString++; while (*lpszFullString == chSep) lpszFullString++; } - const FX_WCHAR* lpchEnd = std::wcschr(lpszFullString, chSep); - int nLen = lpchEnd ? (int)(lpchEnd - lpszFullString) - : (int)FXSYS_wcslen(lpszFullString); - ASSERT(nLen >= 0); - FXSYS_memcpy(rString.GetBuffer(nLen), lpszFullString, - nLen * sizeof(FX_WCHAR)); - rString.ReleaseBuffer(); - return true; -} -CFX_WideString CPDF_TextPageFind::MakeReverse(const CFX_WideString& str) { - CFX_WideString str2; - str2.clear(); - int nlen = str.GetLength(); - for (int i = nlen - 1; i >= 0; i--) - str2 += str.GetAt(i); - return str2; + const wchar_t* lpchEnd = std::wcschr(lpszFullString, chSep); + int nLen = lpchEnd ? static_cast(lpchEnd - lpszFullString) + : static_cast(wcslen(lpszFullString)); + if (nLen < 0) + return {}; + + return {WideString(lpszFullString, static_cast(nLen))}; } int CPDF_TextPageFind::GetCurOrder() const { diff --git a/core/fpdftext/cpdf_textpagefind.h b/core/fpdftext/cpdf_textpagefind.h index c60cb576a775eb71a7cf5eefe4d5510d11a3fd9e..f7419cf14f71c88c88500554a44e3f748a4f86c4 100644 --- a/core/fpdftext/cpdf_textpagefind.h +++ b/core/fpdftext/cpdf_textpagefind.h @@ -12,6 +12,8 @@ #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" +#include "third_party/base/optional.h" class CPDF_TextPage; @@ -20,33 +22,33 @@ class CPDF_TextPageFind { explicit CPDF_TextPageFind(const CPDF_TextPage* pTextPage); ~CPDF_TextPageFind(); - bool FindFirst(const CFX_WideString& findwhat, int flags, int startPos = 0); + bool FindFirst(const WideString& findwhat, + int flags, + Optional startPos); bool FindNext(); bool FindPrev(); int GetCurOrder() const; int GetMatchedCount() const; protected: - void ExtractFindWhat(const CFX_WideString& findwhat); - bool IsMatchWholeWord(const CFX_WideString& csPageText, - int startPos, - int endPos); - bool ExtractSubString(CFX_WideString& rString, - const FX_WCHAR* lpszFullString, - int iSubString, - FX_WCHAR chSep); - CFX_WideString MakeReverse(const CFX_WideString& str); + void ExtractFindWhat(const WideString& findwhat); + bool IsMatchWholeWord(const WideString& csPageText, + size_t startPos, + size_t endPos); + Optional ExtractSubString(const wchar_t* lpszFullString, + int iSubString, + wchar_t chSep); int GetCharIndex(int index) const; private: std::vector m_CharIndex; - const CPDF_TextPage* m_pTextPage; - CFX_WideString m_strText; - CFX_WideString m_findWhat; + UnownedPtr m_pTextPage; + WideString m_strText; + WideString m_findWhat; int m_flags; - std::vector m_csFindWhatArray; - int m_findNextStart; - int m_findPreStart; + std::vector m_csFindWhatArray; + Optional m_findNextStart; + Optional m_findPreStart; bool m_bMatchCase; bool m_bMatchWholeWord; int m_resStart; diff --git a/core/fpdftext/fpdf_text_int_unittest.cpp b/core/fpdftext/fpdf_text_int_unittest.cpp deleted file mode 100644 index d7e48768bc866848bdd40c7384f343d0106c5e00..0000000000000000000000000000000000000000 --- a/core/fpdftext/fpdf_text_int_unittest.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2015 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. - -#include "core/fpdftext/cpdf_linkextract.h" - -#include "testing/gtest/include/gtest/gtest.h" - -// Class to help test functions in CPDF_LinkExtract class. -class CPDF_TestLinkExtract : public CPDF_LinkExtract { - public: - CPDF_TestLinkExtract() : CPDF_LinkExtract(nullptr) {} - - private: - // Add test cases as friends to access protected member functions. - // Access CheckMailLink. - FRIEND_TEST(fpdf_text_int, CheckMailLink); -}; - -TEST(fpdf_text_int, CheckMailLink) { - CPDF_TestLinkExtract extractor; - // Check cases that fail to extract valid mail link. - const wchar_t* invalid_strs[] = { - L"", - L"peter.pan", // '@' is required. - L"abc@server", // Domain name needs at least one '.'. - L"abc.@gmail.com", // '.' can not immediately precede '@'. - L"abc@xyz&q.org", // Domain name should not contain '&'. - L"abc@.xyz.org", // Domain name should not start with '.'. - L"fan@g..com" // Domain name should not have consecutive '.' - }; - for (size_t i = 0; i < FX_ArraySize(invalid_strs); ++i) { - CFX_WideString text_str(invalid_strs[i]); - EXPECT_FALSE(extractor.CheckMailLink(text_str)); - } - - // Check cases that can extract valid mail link. - // An array of {input_string, expected_extracted_email_address}. - const wchar_t* valid_strs[][2] = { - {L"peter@abc.d", L"peter@abc.d"}, - {L"red.teddy.b@abc.com", L"red.teddy.b@abc.com"}, - {L"abc_@gmail.com", L"abc_@gmail.com"}, // '_' is ok before '@'. - {L"dummy-hi@gmail.com", - L"dummy-hi@gmail.com"}, // '-' is ok in user name. - {L"a..df@gmail.com", L"df@gmail.com"}, // Stop at consecutive '.'. - {L".john@yahoo.com", L"john@yahoo.com"}, // Remove heading '.'. - {L"abc@xyz.org?/", L"abc@xyz.org"}, // Trim ending invalid chars. - {L"fan{abc@xyz.org", L"abc@xyz.org"}, // Trim beginning invalid chars. - {L"fan@g.com..", L"fan@g.com"}, // Trim the ending periods. - {L"CAP.cap@Gmail.Com", L"CAP.cap@Gmail.Com"}, // Keep the original case. - }; - for (size_t i = 0; i < FX_ArraySize(valid_strs); ++i) { - CFX_WideString text_str(valid_strs[i][0]); - CFX_WideString expected_str(L"mailto:"); - expected_str += valid_strs[i][1]; - EXPECT_TRUE(extractor.CheckMailLink(text_str)); - EXPECT_STREQ(text_str.c_str(), expected_str.c_str()); - } -} diff --git a/core/fxcodec/DEPS b/core/fxcodec/DEPS index a88b3294a9df1669e986af51dd74664d9faf62e1..9919478889c57e5f02e510f393d808a53e1750de 100644 --- a/core/fxcodec/DEPS +++ b/core/fxcodec/DEPS @@ -1,8 +1,8 @@ include_rules = [ - '+third_party/lcms2-2.6', + '+third_party/lcms', '+third_party/libjpeg/jpeglib.h', # For non-standalone builds that may use libjpeg_turbo. '+third_party/libjpeg_turbo/jpeglib.h', '+third_party/libopenjpeg20', - '+third_party/zlib_v128', + '+third_party/zlib', ] diff --git a/core/fxcodec/codec/ccodec_bmpmodule.cpp b/core/fxcodec/codec/ccodec_bmpmodule.cpp index 9d64199501aea70d1e509632d7a45fd06784e43f..b2fcca869b6037d184635a1981841de5b5b422fe 100644 --- a/core/fxcodec/codec/ccodec_bmpmodule.cpp +++ b/core/fxcodec/codec/ccodec_bmpmodule.cpp @@ -9,123 +9,76 @@ #include "core/fxcodec/codec/codec_int.h" #include "core/fxcodec/fx_codec.h" #include "core/fxcodec/lbmp/fx_bmp.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/ptr_util.h" -struct FXBMP_Context { - bmp_decompress_struct_p bmp_ptr; - void* parent_ptr; - - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; -extern "C" { -static void* bmp_alloc_func(unsigned int size) { - return FX_Alloc(char, size); -} -static void bmp_free_func(void* p) { - FX_Free(p); -} -}; -static void bmp_error_data(bmp_decompress_struct_p bmp_ptr, - const FX_CHAR* err_msg) { - FXSYS_strncpy((char*)bmp_ptr->err_ptr, err_msg, BMP_MAX_ERROR_SIZE - 1); - longjmp(bmp_ptr->jmpbuf, 1); -} -static void bmp_read_scanline(bmp_decompress_struct_p bmp_ptr, - int32_t row_num, - uint8_t* row_buf) { - FXBMP_Context* p = (FXBMP_Context*)bmp_ptr->context_ptr; - CCodec_BmpModule* pModule = (CCodec_BmpModule*)p->parent_ptr; - pModule->GetDelegate()->BmpReadScanline(row_num, row_buf); -} -static bool bmp_get_data_position(bmp_decompress_struct_p bmp_ptr, - uint32_t rcd_pos) { - FXBMP_Context* p = (FXBMP_Context*)bmp_ptr->context_ptr; - CCodec_BmpModule* pModule = (CCodec_BmpModule*)p->parent_ptr; - return pModule->GetDelegate()->BmpInputImagePositionBuf(rcd_pos); +CBmpContext::CBmpContext(CCodec_BmpModule* pModule, + CCodec_BmpModule::Delegate* pDelegate) + : m_pModule(pModule), m_pDelegate(pDelegate) { } -CCodec_BmpModule::CCodec_BmpModule() { - memset(m_szLastError, 0, sizeof(m_szLastError)); -} - -CCodec_BmpModule::~CCodec_BmpModule() {} +CBmpContext::~CBmpContext() {} -FXBMP_Context* CCodec_BmpModule::Start() { - FXBMP_Context* p = FX_Alloc(FXBMP_Context, 1); - if (!p) - return nullptr; +CCodec_BmpModule::CCodec_BmpModule() {} - FXSYS_memset(p, 0, sizeof(FXBMP_Context)); - if (!p) - return nullptr; +CCodec_BmpModule::~CCodec_BmpModule() {} - p->m_AllocFunc = bmp_alloc_func; - p->m_FreeFunc = bmp_free_func; - p->bmp_ptr = nullptr; - p->parent_ptr = (void*)this; - p->bmp_ptr = bmp_create_decompress(); - if (!p->bmp_ptr) { - FX_Free(p); - return nullptr; - } - p->bmp_ptr->context_ptr = (void*)p; - p->bmp_ptr->err_ptr = m_szLastError; - p->bmp_ptr->bmp_error_fn = bmp_error_data; - p->bmp_ptr->bmp_get_row_fn = bmp_read_scanline; - p->bmp_ptr->bmp_get_data_position_fn = bmp_get_data_position; +std::unique_ptr CCodec_BmpModule::Start( + Delegate* pDelegate) { + auto p = pdfium::MakeUnique(this, pDelegate); + p->m_Bmp.context_ptr = p.get(); return p; } -void CCodec_BmpModule::Finish(FXBMP_Context* ctx) { - if (ctx) { - bmp_destroy_decompress(&ctx->bmp_ptr); - ctx->m_FreeFunc(ctx); - } -} -int32_t CCodec_BmpModule::ReadHeader(FXBMP_Context* ctx, +int32_t CCodec_BmpModule::ReadHeader(Context* pContext, int32_t* width, int32_t* height, bool* tb_flag, int32_t* components, int32_t* pal_num, - uint32_t** pal_pp, + std::vector* palette, CFX_DIBAttribute* pAttribute) { - if (setjmp(ctx->bmp_ptr->jmpbuf)) { + auto* ctx = static_cast(pContext); + if (setjmp(ctx->m_Bmp.jmpbuf)) return 0; - } - int32_t ret = bmp_read_header(ctx->bmp_ptr); - if (ret != 1) { + + int32_t ret = ctx->m_Bmp.ReadHeader(); + if (ret != 1) return ret; - } - *width = ctx->bmp_ptr->width; - *height = ctx->bmp_ptr->height; - *tb_flag = ctx->bmp_ptr->imgTB_flag; - *components = ctx->bmp_ptr->components; - *pal_num = ctx->bmp_ptr->pal_num; - *pal_pp = ctx->bmp_ptr->pal_ptr; + + *width = ctx->m_Bmp.width; + *height = ctx->m_Bmp.height; + *tb_flag = ctx->m_Bmp.imgTB_flag; + *components = ctx->m_Bmp.components; + *pal_num = ctx->m_Bmp.pal_num; + *palette = ctx->m_Bmp.palette; if (pAttribute) { pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER; - pAttribute->m_nXDPI = ctx->bmp_ptr->dpi_x; - pAttribute->m_nYDPI = ctx->bmp_ptr->dpi_y; - pAttribute->m_nBmpCompressType = ctx->bmp_ptr->compress_flag; + pAttribute->m_nXDPI = ctx->m_Bmp.dpi_x; + pAttribute->m_nYDPI = ctx->m_Bmp.dpi_y; + pAttribute->m_nBmpCompressType = ctx->m_Bmp.compress_flag; } return 1; } -int32_t CCodec_BmpModule::LoadImage(FXBMP_Context* ctx) { - if (setjmp(ctx->bmp_ptr->jmpbuf)) +int32_t CCodec_BmpModule::LoadImage(Context* pContext) { + auto* ctx = static_cast(pContext); + if (setjmp(ctx->m_Bmp.jmpbuf)) return 0; - return bmp_decode_image(ctx->bmp_ptr); + + return ctx->m_Bmp.DecodeImage(); } -uint32_t CCodec_BmpModule::GetAvailInput(FXBMP_Context* ctx, +uint32_t CCodec_BmpModule::GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr) { - return bmp_get_avail_input(ctx->bmp_ptr, avail_buf_ptr); + auto* ctx = static_cast(pContext); + return ctx->m_Bmp.GetAvailInput(avail_buf_ptr); } -void CCodec_BmpModule::Input(FXBMP_Context* ctx, +void CCodec_BmpModule::Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size) { - bmp_input_buffer(ctx->bmp_ptr, (uint8_t*)src_buf, src_size); + auto* ctx = static_cast(pContext); + ctx->m_Bmp.SetInputBuffer(const_cast(src_buf), src_size); } diff --git a/core/fxcodec/codec/ccodec_bmpmodule.h b/core/fxcodec/codec/ccodec_bmpmodule.h index 11d5931cac3bec6ba37848be437ab2ef16554a8e..8a33f66eac7ce1801b65eed7bada512378e70321 100644 --- a/core/fxcodec/codec/ccodec_bmpmodule.h +++ b/core/fxcodec/codec/ccodec_bmpmodule.h @@ -7,33 +7,43 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_BMPMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_BMPMODULE_H_ -#include "core/fxcodec/codec/icodec_bmpmodule.h" +#include +#include + #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" + +class CFX_DIBAttribute; -class CCodec_BmpModule : public ICodec_BmpModule { +class CCodec_BmpModule { public: + class Context { + public: + virtual ~Context() {} + }; + + class Delegate { + public: + virtual bool BmpInputImagePositionBuf(uint32_t rcd_pos) = 0; + virtual void BmpReadScanline(uint32_t row_num, + const std::vector& row_buf) = 0; + }; + CCodec_BmpModule(); - ~CCodec_BmpModule() override; - - FXBMP_Context* Start() override; - void Finish(FXBMP_Context* pContext) override; - uint32_t GetAvailInput(FXBMP_Context* pContext, - uint8_t** avail_buf_ptr) override; - void Input(FXBMP_Context* pContext, - const uint8_t* src_buf, - uint32_t src_size) override; - int32_t ReadHeader(FXBMP_Context* pContext, + ~CCodec_BmpModule(); + + std::unique_ptr Start(Delegate* pDelegate); + uint32_t GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr); + void Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size); + int32_t ReadHeader(Context* pContext, int32_t* width, int32_t* height, bool* tb_flag, int32_t* components, int32_t* pal_num, - uint32_t** pal_pp, - CFX_DIBAttribute* pAttribute) override; - int32_t LoadImage(FXBMP_Context* pContext) override; - - protected: - FX_CHAR m_szLastError[256]; + std::vector* palette, + CFX_DIBAttribute* pAttribute); + int32_t LoadImage(Context* pContext); }; #endif // CORE_FXCODEC_CODEC_CCODEC_BMPMODULE_H_ diff --git a/core/fxcodec/codec/ccodec_faxmodule.h b/core/fxcodec/codec/ccodec_faxmodule.h index 92e45e6719a41f6a5c8de8b4b86b43a304775da3..4f8ab78ac40a409e88464e8859aa08a85f5849cb 100644 --- a/core/fxcodec/codec/ccodec_faxmodule.h +++ b/core/fxcodec/codec/ccodec_faxmodule.h @@ -26,14 +26,14 @@ class CCodec_FaxModule { bool BlackIs1, int Columns, int Rows); -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ static void FaxEncode(const uint8_t* src_buf, int width, int height, int pitch, std::unique_ptr* dest_buf, uint32_t* dest_size); -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ }; #endif // CORE_FXCODEC_CODEC_CCODEC_FAXMODULE_H_ diff --git a/core/fxcodec/codec/ccodec_flatemodule.h b/core/fxcodec/codec/ccodec_flatemodule.h index 5178943ca0cf3d129da6d06e37a94474cd340689..ae34103f3bde2a33533de96aca4befa1645412a2 100644 --- a/core/fxcodec/codec/ccodec_flatemodule.h +++ b/core/fxcodec/codec/ccodec_flatemodule.h @@ -34,12 +34,14 @@ class CCodec_FlateModule { int BitsPerComponent, int Columns, uint32_t estimated_size, - uint8_t*& dest_buf, - uint32_t& dest_size); + uint8_t** dest_buf, + uint32_t* dest_size); + bool Encode(const uint8_t* src_buf, uint32_t src_size, uint8_t** dest_buf, uint32_t* dest_size); + bool PngEncode(const uint8_t* src_buf, uint32_t src_size, uint8_t** dest_buf, diff --git a/core/fxcodec/codec/ccodec_gifmodule.cpp b/core/fxcodec/codec/ccodec_gifmodule.cpp index a85bc5eddc31ebf5fb1213866b26b461c43400fd..d6ab10d9c9038edb957814f5becd10407a97f4a1 100644 --- a/core/fxcodec/codec/ccodec_gifmodule.cpp +++ b/core/fxcodec/codec/ccodec_gifmodule.cpp @@ -8,191 +8,83 @@ #include "core/fxcodec/codec/codec_int.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcodec/lgif/fx_gif.h" +#include "core/fxcodec/gif/cfx_gif.h" +#include "core/fxcodec/gif/cfx_gifcontext.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/ptr_util.h" -struct FXGIF_Context { - gif_decompress_struct_p gif_ptr; - void* parent_ptr; - - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; - -extern "C" { -static void* gif_alloc_func(unsigned int size) { - return FX_Alloc(char, size); -} -static void gif_free_func(void* p) { - FX_Free(p); -} -}; - -static void gif_error_data(gif_decompress_struct_p gif_ptr, - const FX_CHAR* err_msg) { - FXSYS_strncpy((char*)gif_ptr->err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1); - longjmp(gif_ptr->jmpbuf, 1); -} - -static uint8_t* gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr, - int32_t pal_size) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - return pModule->GetDelegate()->GifAskLocalPaletteBuf( - gif_get_frame_num(gif_ptr), pal_size); -} - -static void gif_record_current_position(gif_decompress_struct_p gif_ptr, - uint32_t* cur_pos_ptr) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - pModule->GetDelegate()->GifRecordCurrentPosition(*cur_pos_ptr); -} - -static void gif_read_scanline(gif_decompress_struct_p gif_ptr, - int32_t row_num, - uint8_t* row_buf) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - pModule->GetDelegate()->GifReadScanline(row_num, row_buf); -} - -static bool gif_get_record_position(gif_decompress_struct_p gif_ptr, - uint32_t cur_pos, - int32_t left, - int32_t top, - int32_t width, - int32_t height, - int32_t pal_num, - void* pal_ptr, - int32_t delay_time, - bool user_input, - int32_t trans_index, - int32_t disposal_method, - bool interlace) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - return pModule->GetDelegate()->GifInputRecordPositionBuf( - cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal_ptr, - delay_time, user_input, trans_index, disposal_method, interlace); -} - -CCodec_GifModule::CCodec_GifModule() { - memset(m_szLastError, 0, sizeof(m_szLastError)); -} +CCodec_GifModule::CCodec_GifModule() {} CCodec_GifModule::~CCodec_GifModule() {} -FXGIF_Context* CCodec_GifModule::Start() { - FXGIF_Context* p = FX_Alloc(FXGIF_Context, 1); - if (!p) - return nullptr; - - FXSYS_memset(p, 0, sizeof(FXGIF_Context)); - p->m_AllocFunc = gif_alloc_func; - p->m_FreeFunc = gif_free_func; - p->gif_ptr = nullptr; - p->parent_ptr = (void*)this; - p->gif_ptr = gif_create_decompress(); - if (!p->gif_ptr) { - FX_Free(p); - return nullptr; - } - p->gif_ptr->context_ptr = (void*)p; - p->gif_ptr->err_ptr = m_szLastError; - p->gif_ptr->gif_error_fn = gif_error_data; - p->gif_ptr->gif_ask_buf_for_pal_fn = gif_ask_buf_for_pal; - p->gif_ptr->gif_record_current_position_fn = gif_record_current_position; - p->gif_ptr->gif_get_row_fn = gif_read_scanline; - p->gif_ptr->gif_get_record_position_fn = gif_get_record_position; - return p; +std::unique_ptr CCodec_GifModule::Start( + Delegate* pDelegate) { + return pdfium::MakeUnique(this, pDelegate); } -void CCodec_GifModule::Finish(FXGIF_Context* ctx) { - if (ctx) { - gif_destroy_decompress(&ctx->gif_ptr); - ctx->m_FreeFunc(ctx); - } -} - -int32_t CCodec_GifModule::ReadHeader(FXGIF_Context* ctx, - int* width, - int* height, - int* pal_num, - void** pal_pp, - int* bg_index, - CFX_DIBAttribute* pAttribute) { - if (setjmp(ctx->gif_ptr->jmpbuf)) - return 0; - - int32_t ret = gif_read_header(ctx->gif_ptr); - if (ret != 1) +CFX_GifDecodeStatus CCodec_GifModule::ReadHeader(Context* pContext, + int* width, + int* height, + int* pal_num, + void** pal_pp, + int* bg_index, + CFX_DIBAttribute* pAttribute) { + auto* context = static_cast(pContext); + CFX_GifDecodeStatus ret = context->ReadHeader(); + if (ret != CFX_GifDecodeStatus::Success) return ret; - *width = ctx->gif_ptr->width; - *height = ctx->gif_ptr->height; - *pal_num = ctx->gif_ptr->global_pal_num; - *pal_pp = ctx->gif_ptr->global_pal_ptr; - *bg_index = ctx->gif_ptr->bc_index; - return 1; + *width = context->width_; + *height = context->height_; + *pal_num = (2 << context->global_pal_exp_); + *pal_pp = context->global_palette_.empty() ? nullptr + : context->global_palette_.data(); + *bg_index = context->bc_index_; + return CFX_GifDecodeStatus::Success; } -int32_t CCodec_GifModule::LoadFrameInfo(FXGIF_Context* ctx, int* frame_num) { - if (setjmp(ctx->gif_ptr->jmpbuf)) - return 0; - - int32_t ret = gif_get_frame(ctx->gif_ptr); - if (ret != 1) - return ret; - - *frame_num = gif_get_frame_num(ctx->gif_ptr); - return 1; +std::pair CCodec_GifModule::LoadFrameInfo( + Context* pContext) { + auto* context = static_cast(pContext); + CFX_GifDecodeStatus ret = context->GetFrame(); + if (ret != CFX_GifDecodeStatus::Success) + return {ret, 0}; + return {CFX_GifDecodeStatus::Success, context->GetFrameNum()}; } -int32_t CCodec_GifModule::LoadFrame(FXGIF_Context* ctx, - int frame_num, - CFX_DIBAttribute* pAttribute) { - if (setjmp(ctx->gif_ptr->jmpbuf)) - return 0; +CFX_GifDecodeStatus CCodec_GifModule::LoadFrame(Context* pContext, + size_t frame_num, + CFX_DIBAttribute* pAttribute) { + auto* context = static_cast(pContext); + CFX_GifDecodeStatus ret = context->LoadFrame(frame_num); + if (ret != CFX_GifDecodeStatus::Success || !pAttribute) + return ret; - int32_t ret = gif_load_frame(ctx->gif_ptr, frame_num); - if (ret == 1) { - if (pAttribute) { - pAttribute->m_nGifLeft = - (*ctx->gif_ptr->img_ptr_arr_ptr)[frame_num]->image_info_ptr->left; - pAttribute->m_nGifTop = - (*ctx->gif_ptr->img_ptr_arr_ptr)[frame_num]->image_info_ptr->top; - pAttribute->m_fAspectRatio = ctx->gif_ptr->pixel_aspect; - if (ctx->gif_ptr->cmt_data_ptr) { - const uint8_t* buf = - (const uint8_t*)ctx->gif_ptr->cmt_data_ptr->GetBuffer(0); - uint32_t len = ctx->gif_ptr->cmt_data_ptr->GetLength(); - if (len > 21) { - uint8_t size = *buf++; - if (size) { - pAttribute->m_strAuthor = CFX_ByteString(buf, size); - } else { - pAttribute->m_strAuthor.clear(); - } - buf += size; - size = *buf++; - if (size == 20) { - FXSYS_memcpy(pAttribute->m_strTime, buf, size); - } - } - } - } + pAttribute->m_nGifLeft = context->images_[frame_num]->image_info.left; + pAttribute->m_nGifTop = context->images_[frame_num]->image_info.top; + pAttribute->m_fAspectRatio = context->pixel_aspect_; + const uint8_t* buf = + reinterpret_cast(context->cmt_data_.GetBuffer(0)); + uint32_t len = context->cmt_data_.GetLength(); + if (len > 21) { + uint8_t size = *buf++; + if (size != 0) + pAttribute->m_strAuthor = ByteString(buf, size); + else + pAttribute->m_strAuthor.clear(); } - return ret; + return CFX_GifDecodeStatus::Success; } -uint32_t CCodec_GifModule::GetAvailInput(FXGIF_Context* ctx, +uint32_t CCodec_GifModule::GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr) { - return gif_get_avail_input(ctx->gif_ptr, avail_buf_ptr); + auto* context = static_cast(pContext); + return context->GetAvailInput(avail_buf_ptr); } -void CCodec_GifModule::Input(FXGIF_Context* ctx, +void CCodec_GifModule::Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size) { - gif_input_buffer(ctx->gif_ptr, (uint8_t*)src_buf, src_size); + auto* context = static_cast(pContext); + context->SetInputBuffer((uint8_t*)src_buf, src_size); } diff --git a/core/fxcodec/codec/ccodec_gifmodule.h b/core/fxcodec/codec/ccodec_gifmodule.h index 7721d7a767a463361b77a758f3c0e87e1fd4a6a5..5ceff7bc4e13ac68f7149ac67a0a35799094bebe 100644 --- a/core/fxcodec/codec/ccodec_gifmodule.h +++ b/core/fxcodec/codec/ccodec_gifmodule.h @@ -7,39 +7,54 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_GIFMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_GIFMODULE_H_ -#include "core/fxcodec/codec/icodec_gifmodule.h" +#include +#include + +#include "core/fxcodec/gif/cfx_gif.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" -class CCodec_GifModule : public ICodec_GifModule { +class CFX_DIBAttribute; + +class CCodec_GifModule { public: + class Context { + public: + virtual ~Context() {} + }; + + class Delegate { + public: + virtual void GifRecordCurrentPosition(uint32_t& cur_pos) = 0; + virtual bool GifInputRecordPositionBuf(uint32_t rcd_pos, + const FX_RECT& img_rc, + int32_t pal_num, + void* pal_ptr, + int32_t delay_time, + bool user_input, + int32_t trans_index, + int32_t disposal_method, + bool interlace) = 0; + virtual void GifReadScanline(int32_t row_num, uint8_t* row_buf) = 0; + }; + CCodec_GifModule(); - ~CCodec_GifModule() override; - - FXGIF_Context* Start() override; - void Finish(FXGIF_Context* pContext) override; - uint32_t GetAvailInput(FXGIF_Context* pContext, - uint8_t** avail_buf_ptr = nullptr) override; - - void Input(FXGIF_Context* pContext, - const uint8_t* src_buf, - uint32_t src_size) override; - - int32_t ReadHeader(FXGIF_Context* pContext, - int* width, - int* height, - int* pal_num, - void** pal_pp, - int* bg_index, - CFX_DIBAttribute* pAttribute) override; - - int32_t LoadFrameInfo(FXGIF_Context* pContext, int* frame_num) override; - int32_t LoadFrame(FXGIF_Context* pContext, - int frame_num, - CFX_DIBAttribute* pAttribute) override; - - protected: - FX_CHAR m_szLastError[256]; + ~CCodec_GifModule(); + + std::unique_ptr Start(Delegate* pDelegate); + uint32_t GetAvailInput(Context* context, uint8_t** avail_buf_ptr = nullptr); + void Input(Context* context, const uint8_t* src_buf, uint32_t src_size); + CFX_GifDecodeStatus ReadHeader(Context* context, + int* width, + int* height, + int* pal_num, + void** pal_pp, + int* bg_index, + CFX_DIBAttribute* pAttribute); + std::pair LoadFrameInfo(Context* context); + CFX_GifDecodeStatus LoadFrame(Context* context, + size_t frame_num, + CFX_DIBAttribute* pAttribute); }; #endif // CORE_FXCODEC_CODEC_CCODEC_GIFMODULE_H_ diff --git a/core/fxcodec/codec/ccodec_iccmodule.h b/core/fxcodec/codec/ccodec_iccmodule.h index 1f856faa041a2d816d766b463356e38211cdb0e3..c304b4bb8e018b1055f80a665085dcfe81599320 100644 --- a/core/fxcodec/codec/ccodec_iccmodule.h +++ b/core/fxcodec/codec/ccodec_iccmodule.h @@ -7,23 +7,41 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_ICCMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_ICCMODULE_H_ +#include + #include "core/fxcodec/fx_codec_def.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "third_party/base/ptr_util.h" + +#if defined(USE_SYSTEM_LCMS2) +#include +#else +#include "third_party/lcms/include/lcms2.h" +#endif + +class CLcmsCmm { + public: + CLcmsCmm(int srcComponents, cmsHTRANSFORM transform, bool isLab); + ~CLcmsCmm(); + + cmsHTRANSFORM m_hTransform; + int m_nSrcComponents; + bool m_bLab; +}; class CCodec_IccModule { public: CCodec_IccModule(); ~CCodec_IccModule(); - void* CreateTransform_sRGB(const uint8_t* pProfileData, - uint32_t dwProfileSize, - uint32_t& nComponents, - int32_t intent = 0, - uint32_t dwSrcFormat = Icc_FORMAT_DEFAULT); - void DestroyTransform(void* pTransform); - void Translate(void* pTransform, FX_FLOAT* pSrcValues, FX_FLOAT* pDestValues); - void TranslateScanline(void* pTransform, + std::unique_ptr CreateTransform_sRGB(const uint8_t* pProfileData, + uint32_t dwProfileSize, + uint32_t* nComponents); + void Translate(CLcmsCmm* pTransform, + const float* pSrcValues, + float* pDestValues); + void TranslateScanline(CLcmsCmm* pTransform, uint8_t* pDest, const uint8_t* pSrc, int pixels); diff --git a/core/fxcodec/codec/ccodec_jbig2module.h b/core/fxcodec/codec/ccodec_jbig2module.h index c74ed5fb0266a1c326d63437f5c0390d45f61044..4fa4a817765d5b83ef5090eb47feb65f923c68da 100644 --- a/core/fxcodec/codec/ccodec_jbig2module.h +++ b/core/fxcodec/codec/ccodec_jbig2module.h @@ -10,12 +10,12 @@ #include #include "core/fxcodec/fx_codec_def.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/retain_ptr.h" class CJBig2_Context; class CJBig2_Image; class CPDF_StreamAcc; -class IFX_Pause; +class IFX_PauseIndicator; class JBig2_DocumentContext; class CCodec_Jbig2Context { @@ -25,11 +25,10 @@ class CCodec_Jbig2Context { uint32_t m_width; uint32_t m_height; - CPDF_StreamAcc* m_pGlobalStream; - CPDF_StreamAcc* m_pSrcStream; + RetainPtr m_pGlobalStream; + RetainPtr m_pSrcStream; uint8_t* m_dest_buf; uint32_t m_dest_pitch; - IFX_Pause* m_pPause; std::unique_ptr m_pContext; }; @@ -43,13 +42,16 @@ class CCodec_Jbig2Module { std::unique_ptr* pContextHolder, uint32_t width, uint32_t height, - CPDF_StreamAcc* src_stream, - CPDF_StreamAcc* global_stream, + const RetainPtr& src_stream, + const RetainPtr& global_stream, uint8_t* dest_buf, uint32_t dest_pitch, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS ContinueDecode(CCodec_Jbig2Context* pJbig2Context, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); + + private: + FXCODEC_STATUS Decode(CCodec_Jbig2Context* pJbig2Context, int result); }; #endif // CORE_FXCODEC_CODEC_CCODEC_JBIG2MODULE_H_ diff --git a/core/fxcodec/codec/ccodec_jpegmodule.h b/core/fxcodec/codec/ccodec_jpegmodule.h index bad6fa6a9439665961459034180d9fef7dc8ba3a..aed01bda9bfe8211c7a3c17c6d26b274f0ecf562 100644 --- a/core/fxcodec/codec/ccodec_jpegmodule.h +++ b/core/fxcodec/codec/ccodec_jpegmodule.h @@ -7,13 +7,14 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_JPEGMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_JPEGMODULE_H_ +#include #include #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" class CCodec_ScanlineDecoder; class CFX_DIBSource; -struct FXJPEG_Context; #ifdef PDF_ENABLE_XFA class CFX_DIBAttribute; @@ -21,7 +22,11 @@ class CFX_DIBAttribute; class CCodec_JpegModule { public: - CCodec_JpegModule() {} + class Context { + public: + virtual ~Context() {} + virtual jmp_buf* GetJumpMark() = 0; + }; std::unique_ptr CreateDecoder(const uint8_t* src_buf, uint32_t src_size, @@ -36,34 +41,29 @@ class CCodec_JpegModule { int* num_components, int* bits_per_components, bool* color_transform); - FXJPEG_Context* Start(); - void Finish(FXJPEG_Context* pContext); - void Input(FXJPEG_Context* pContext, - const uint8_t* src_buf, - uint32_t src_size); + + std::unique_ptr Start(); + void Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size); #ifndef PDF_ENABLE_XFA - int ReadHeader(FXJPEG_Context* pContext, - int* width, - int* height, - int* nComps); + int ReadHeader(Context* pContext, int* width, int* height, int* nComps); #else // PDF_ENABLE_XFA - int ReadHeader(FXJPEG_Context* pContext, + int ReadHeader(Context* pContext, int* width, int* height, int* nComps, CFX_DIBAttribute* pAttribute); #endif // PDF_ENABLE_XFA - bool StartScanline(FXJPEG_Context* pContext, int down_scale); - bool ReadScanline(FXJPEG_Context* pContext, uint8_t* dest_buf); - uint32_t GetAvailInput(FXJPEG_Context* pContext, uint8_t** avail_buf_ptr); + bool StartScanline(Context* pContext, int down_scale); + bool ReadScanline(Context* pContext, uint8_t* dest_buf); + uint32_t GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr); -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ - static bool JpegEncode(const CFX_DIBSource* pSource, +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + static bool JpegEncode(const RetainPtr& pSource, uint8_t** dest_buf, - FX_STRSIZE* dest_size); -#endif + size_t* dest_size); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ }; #endif // CORE_FXCODEC_CODEC_CCODEC_JPEGMODULE_H_ diff --git a/core/fxcodec/codec/ccodec_jpxmodule.h b/core/fxcodec/codec/ccodec_jpxmodule.h index fd919d91b08532f4c36c6755a030b4b6c33de5ff..c57002722eefa8174f2d4dcc77e69e8bd41e0b11 100644 --- a/core/fxcodec/codec/ccodec_jpxmodule.h +++ b/core/fxcodec/codec/ccodec_jpxmodule.h @@ -7,6 +7,7 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_JPXMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_JPXMODULE_H_ +#include #include #include "core/fxcrt/fx_system.h" @@ -19,9 +20,9 @@ class CCodec_JpxModule { CCodec_JpxModule(); ~CCodec_JpxModule(); - CJPX_Decoder* CreateDecoder(const uint8_t* src_buf, - uint32_t src_size, - CPDF_ColorSpace* cs); + std::unique_ptr CreateDecoder(const uint8_t* src_buf, + uint32_t src_size, + CPDF_ColorSpace* cs); void GetImageInfo(CJPX_Decoder* pDecoder, uint32_t* width, uint32_t* height, @@ -30,7 +31,6 @@ class CCodec_JpxModule { uint8_t* dest_data, int pitch, const std::vector& offsets); - void DestroyDecoder(CJPX_Decoder* pDecoder); }; #endif // CORE_FXCODEC_CODEC_CCODEC_JPXMODULE_H_ diff --git a/core/fxcodec/codec/ccodec_pngmodule.cpp b/core/fxcodec/codec/ccodec_pngmodule.cpp index 028513b729417d7be4ea88891fc6feb2de7aec96..37e83f7248edd39d715d963ced4e730bf87cec81 100644 --- a/core/fxcodec/codec/ccodec_pngmodule.cpp +++ b/core/fxcodec/codec/ccodec_pngmodule.cpp @@ -10,21 +10,43 @@ #include "core/fxcodec/codec/codec_int.h" #include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/ptr_util.h" -extern "C" { -#undef FAR +#ifdef USE_SYSTEM_LIBPNG +#include +#else #include "third_party/libpng16/png.h" -} +#endif + +#define PNG_ERROR_SIZE 256 + +class CPngContext : public CCodec_PngModule::Context { + public: + CPngContext(CCodec_PngModule* pModule, CCodec_PngModule::Delegate* pDelegate); + ~CPngContext() override; + + png_structp m_pPng; + png_infop m_pInfo; + UnownedPtr m_pModule; + UnownedPtr m_pDelegate; + void* (*m_AllocFunc)(unsigned int); + void (*m_FreeFunc)(void*); + char m_szLastError[PNG_ERROR_SIZE]; +}; + +extern "C" { static void _png_error_data(png_structp png_ptr, png_const_charp error_msg) { - if (png_get_error_ptr(png_ptr)) { - FXSYS_strncpy((char*)png_get_error_ptr(png_ptr), error_msg, - PNG_ERROR_SIZE - 1); - } + if (png_get_error_ptr(png_ptr)) + strncpy((char*)png_get_error_ptr(png_ptr), error_msg, PNG_ERROR_SIZE - 1); + longjmp(png_jmpbuf(png_ptr), 1); } + static void _png_warning_data(png_structp png_ptr, png_const_charp error_msg) {} + static void _png_load_bmp_attribute(png_structp png_ptr, png_infop info_ptr, CFX_DIBAttribute* pAttribute) { @@ -50,104 +72,77 @@ static void _png_load_bmp_attribute(png_structp png_ptr, int compress_type; png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile, &icc_proflen); -#endif - int bTime = 0; -#if defined(PNG_tIME_SUPPORTED) - png_timep t = nullptr; - png_get_tIME(png_ptr, info_ptr, &t); - if (t) { - FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); - FXSYS_snprintf((FX_CHAR*)pAttribute->m_strTime, - sizeof(pAttribute->m_strTime), "%4u:%2u:%2u %2u:%2u:%2u", - t->year, t->month, t->day, t->hour, t->minute, t->second); - pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0; - bTime = 1; - } #endif #if defined(PNG_TEXT_SUPPORTED) int i; - FX_STRSIZE len; - const FX_CHAR* buf; + size_t len; + const char* buf; int num_text; png_textp text = nullptr; png_get_text(png_ptr, info_ptr, &text, &num_text); for (i = 0; i < num_text; i++) { - len = FXSYS_strlen(text[i].key); + len = strlen(text[i].key); buf = "Time"; - if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { - if (!bTime) { - FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); - FXSYS_memcpy( - pAttribute->m_strTime, text[i].text, - std::min(sizeof(pAttribute->m_strTime) - 1, text[i].text_length)); - } - } else { + if (memcmp(buf, text[i].key, std::min(len, strlen(buf)))) { buf = "Author"; - if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { + if (!memcmp(buf, text[i].key, std::min(len, strlen(buf)))) { pAttribute->m_strAuthor = - CFX_ByteString(reinterpret_cast(text[i].text), - static_cast(text[i].text_length)); + text[i].text_length > 0 + ? ByteString(reinterpret_cast(text[i].text), + static_cast(text[i].text_length)) + : ByteString(); } } } #endif } } -struct FXPNG_Context { - png_structp png_ptr; - png_infop info_ptr; - void* parent_ptr; - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; -extern "C" { static void* _png_alloc_func(unsigned int size) { return FX_Alloc(char, size); } + static void _png_free_func(void* p) { FX_Free(p); } -}; -static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { - FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); - if (!p) - return; - CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; - if (!pModule) +static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { + auto* pContext = + reinterpret_cast(png_get_progressive_ptr(png_ptr)); + if (!pContext) return; - png_uint_32 width = 0, height = 0; - int bpc = 0, color_type = 0, color_type1 = 0, pass = 0; - double gamma = 1.0; + png_uint_32 width = 0; + png_uint_32 height = 0; + int bpc = 0; + int color_type = 0; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bpc, &color_type, nullptr, nullptr, nullptr); - color_type1 = color_type; - if (bpc > 8) { + int color_type1 = color_type; + if (bpc > 8) png_set_strip_16(png_ptr); - } else if (bpc < 8) { + else if (bpc < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - } + bpc = 8; - if (color_type == PNG_COLOR_TYPE_PALETTE) { + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - } - pass = png_set_interlace_handling(png_ptr); - if (!pModule->GetDelegate()->PngReadHeader(width, height, bpc, pass, - &color_type, &gamma)) { - png_error(p->png_ptr, "Read Header Callback Error"); + + int pass = png_set_interlace_handling(png_ptr); + double gamma = 1.0; + if (!pContext->m_pDelegate->PngReadHeader(width, height, bpc, pass, + &color_type, &gamma)) { + png_error(pContext->m_pPng, "Read Header Callback Error"); } int intent; if (png_get_sRGB(png_ptr, info_ptr, &intent)) { png_set_gamma(png_ptr, gamma, 0.45455); } else { double image_gamma; - if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) { + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) png_set_gamma(png_ptr, gamma, image_gamma); - } else { + else png_set_gamma(png_ptr, gamma, 0.45455); - } } switch (color_type) { case PNG_COLOR_TYPE_GRAY: @@ -158,7 +153,7 @@ static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { } break; case PNG_COLOR_TYPE_PALETTE: if (color_type1 != PNG_COLOR_TYPE_PALETTE) { - png_error(p->png_ptr, "Not Support Output Palette Now"); + png_error(pContext->m_pPng, "Not Support Output Palette Now"); } case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: @@ -168,95 +163,89 @@ static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { png_set_bgr(png_ptr); break; } - if (!(color_type & PNG_COLOR_MASK_ALPHA)) { + if (!(color_type & PNG_COLOR_MASK_ALPHA)) png_set_strip_alpha(png_ptr); - } + if (color_type & PNG_COLOR_MASK_ALPHA && !(color_type1 & PNG_COLOR_MASK_ALPHA)) { png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } png_read_update_info(png_ptr, info_ptr); } + static void _png_get_end_func(png_structp png_ptr, png_infop info_ptr) {} + static void _png_get_row_func(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass) { - FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); - if (!p) + auto* pContext = + reinterpret_cast(png_get_progressive_ptr(png_ptr)); + if (!pContext) return; - CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; - uint8_t* src_buf = nullptr; - if (!pModule->GetDelegate()->PngAskScanlineBuf(row_num, src_buf)) { + uint8_t* src_buf; + if (!pContext->m_pDelegate->PngAskScanlineBuf(row_num, &src_buf)) png_error(png_ptr, "Ask Scanline buffer Callback Error"); - } - if (src_buf) { + + if (src_buf) png_progressive_combine_row(png_ptr, src_buf, new_row); - } - pModule->GetDelegate()->PngFillScanlineBufCompleted(pass, row_num); + + pContext->m_pDelegate->PngFillScanlineBufCompleted(pass, row_num); } -CCodec_PngModule::CCodec_PngModule() { +} // extern "C" + +CPngContext::CPngContext(CCodec_PngModule* pModule, + CCodec_PngModule::Delegate* pDelegate) + : m_pPng(nullptr), + m_pInfo(nullptr), + m_pModule(pModule), + m_pDelegate(pDelegate), + m_AllocFunc(_png_alloc_func), + m_FreeFunc(_png_free_func) { memset(m_szLastError, 0, sizeof(m_szLastError)); } -CCodec_PngModule::~CCodec_PngModule() {} - -FXPNG_Context* CCodec_PngModule::Start() { - FXPNG_Context* p = FX_Alloc(FXPNG_Context, 1); - if (!p) - return nullptr; +CPngContext::~CPngContext() { + png_destroy_read_struct(m_pPng ? &m_pPng : nullptr, + m_pInfo ? &m_pInfo : nullptr, nullptr); +} - p->m_AllocFunc = _png_alloc_func; - p->m_FreeFunc = _png_free_func; - p->png_ptr = nullptr; - p->info_ptr = nullptr; - p->parent_ptr = (void*)this; - p->png_ptr = +std::unique_ptr CCodec_PngModule::Start( + Delegate* pDelegate) { + auto p = pdfium::MakeUnique(this, pDelegate); + p->m_pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!p->png_ptr) { - FX_Free(p); + if (!p->m_pPng) return nullptr; - } - p->info_ptr = png_create_info_struct(p->png_ptr); - if (!p->info_ptr) { - png_destroy_read_struct(&(p->png_ptr), nullptr, nullptr); - FX_Free(p); + + p->m_pInfo = png_create_info_struct(p->m_pPng); + if (!p->m_pInfo) return nullptr; - } - if (setjmp(png_jmpbuf(p->png_ptr))) { - if (p) { - png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), nullptr); - FX_Free(p); - } + + if (setjmp(png_jmpbuf(p->m_pPng))) return nullptr; - } - png_set_progressive_read_fn(p->png_ptr, p, _png_get_header_func, + + png_set_progressive_read_fn(p->m_pPng, p.get(), _png_get_header_func, _png_get_row_func, _png_get_end_func); - png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data, - (png_error_ptr)_png_warning_data); + png_set_error_fn(p->m_pPng, p->m_szLastError, _png_error_data, + _png_warning_data); return p; } -void CCodec_PngModule::Finish(FXPNG_Context* ctx) { - if (ctx) { - png_destroy_read_struct(&(ctx->png_ptr), &(ctx->info_ptr), nullptr); - ctx->m_FreeFunc(ctx); - } -} - -bool CCodec_PngModule::Input(FXPNG_Context* ctx, +bool CCodec_PngModule::Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size, CFX_DIBAttribute* pAttribute) { - if (setjmp(png_jmpbuf(ctx->png_ptr))) { + auto* ctx = static_cast(pContext); + if (setjmp(png_jmpbuf(ctx->m_pPng))) { if (pAttribute && - 0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) { - _png_load_bmp_attribute(ctx->png_ptr, ctx->info_ptr, pAttribute); + strcmp(ctx->m_szLastError, "Read Header Callback Error") == 0) { + _png_load_bmp_attribute(ctx->m_pPng, ctx->m_pInfo, pAttribute); } return false; } - png_process_data(ctx->png_ptr, ctx->info_ptr, (uint8_t*)src_buf, src_size); + png_process_data(ctx->m_pPng, ctx->m_pInfo, (uint8_t*)src_buf, src_size); return true; } diff --git a/core/fxcodec/codec/ccodec_pngmodule.h b/core/fxcodec/codec/ccodec_pngmodule.h index 1f3a3d96cc99ac36890ae68a23368f2c04aef32f..847f67e8ebbf75ce34ec34f62f329bc72c2bb903 100644 --- a/core/fxcodec/codec/ccodec_pngmodule.h +++ b/core/fxcodec/codec/ccodec_pngmodule.h @@ -7,25 +7,40 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_PNGMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_PNGMODULE_H_ -#include "core/fxcodec/codec/icodec_pngmodule.h" +#include + #include "core/fxcrt/fx_system.h" -#define PNG_ERROR_SIZE 256 +class CFX_DIBAttribute; -class CCodec_PngModule : public ICodec_PngModule { +class CCodec_PngModule { public: - CCodec_PngModule(); - ~CCodec_PngModule() override; - - FXPNG_Context* Start() override; - void Finish(FXPNG_Context* pContext) override; - bool Input(FXPNG_Context* pContext, + class Context { + public: + virtual ~Context() {} + }; + + class Delegate { + public: + virtual bool PngReadHeader(int width, + int height, + int bpc, + int pass, + int* color_type, + double* gamma) = 0; + + // Returns true on success. |pSrcBuf| will be set if this succeeds. + // |pSrcBuf| does not take ownership of the buffer. + virtual bool PngAskScanlineBuf(int line, uint8_t** pSrcBuf) = 0; + + virtual void PngFillScanlineBufCompleted(int pass, int line) = 0; + }; + + std::unique_ptr Start(Delegate* pDelegate); + bool Input(Context* pContext, const uint8_t* src_buf, uint32_t src_size, - CFX_DIBAttribute* pAttribute) override; - - protected: - FX_CHAR m_szLastError[PNG_ERROR_SIZE]; + CFX_DIBAttribute* pAttribute); }; #endif // CORE_FXCODEC_CODEC_CCODEC_PNGMODULE_H_ diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h index 61703dde29f199861e59544904b1aa287262e76e..41e10e6dcf6f2b460abd0b16ef6af8293009cd68 100644 --- a/core/fxcodec/codec/ccodec_progressivedecoder.h +++ b/core/fxcodec/codec/ccodec_progressivedecoder.h @@ -7,27 +7,28 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_PROGRESSIVEDECODER_H_ #define CORE_FXCODEC_CODEC_CCODEC_PROGRESSIVEDECODER_H_ +#include +#include #include -#include "core/fxcodec/codec/icodec_bmpmodule.h" -#include "core/fxcodec/codec/icodec_gifmodule.h" -#include "core/fxcodec/codec/icodec_pngmodule.h" -#include "core/fxcodec/codec/icodec_tiffmodule.h" +#include "core/fxcodec/codec/ccodec_bmpmodule.h" +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" +#include "core/fxcodec/codec/ccodec_pngmodule.h" +#include "core/fxcodec/codec/ccodec_tiffmodule.h" #include "core/fxcodec/fx_codec_def.h" -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" -class CCodec_JpegModule; class CCodec_ModuleMgr; class CFX_DIBAttribute; class IFX_SeekableReadStream; -class IFX_Pause; -struct FXJPEG_Context; -class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, - public ICodec_GifModule::Delegate, - public ICodec_PngModule::Delegate { +class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, + public CCodec_GifModule::Delegate, + public CCodec_PngModule::Delegate { public: enum FXCodec_Format { FXCodec_Invalid = 0, @@ -44,11 +45,10 @@ class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, explicit CCodec_ProgressiveDecoder(CCodec_ModuleMgr* pCodecMgr); virtual ~CCodec_ProgressiveDecoder(); - FXCODEC_STATUS LoadImageInfo( - const CFX_RetainPtr& pFile, - FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute, - bool bSkipImageTypeCheck); + FXCODEC_STATUS LoadImageInfo(const RetainPtr& pFile, + FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute, + bool bSkipImageTypeCheck); FXCODEC_IMAGE_TYPE GetType() const { return m_imagType; } int32_t GetWidth() const { return m_SrcWidth; } @@ -57,16 +57,14 @@ class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, int32_t GetBPC() const { return m_SrcBPC; } void SetClipBox(FX_RECT* clip); - FXCODEC_STATUS GetFrames(int32_t& frames, IFX_Pause* pPause = nullptr); - FXCODEC_STATUS StartDecode(CFX_DIBitmap* pDIBitmap, + std::pair GetFrames(); + FXCODEC_STATUS StartDecode(const RetainPtr& pDIBitmap, int start_x, int start_y, int size_x, - int size_y, - int32_t frames = 0, - bool bInterpol = true); + int size_y); - FXCODEC_STATUS ContinueDecode(IFX_Pause* pPause = nullptr); + FXCODEC_STATUS ContinueDecode(); struct PixelWeight { int m_SrcStart; @@ -84,8 +82,7 @@ class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, int dest_max, int src_len, int src_min, - int src_max, - bool bInterpol); + int src_max); PixelWeight* GetPixelWeight(int pixel) { return reinterpret_cast(m_pWeightTables.data() + (pixel - m_DestMin) * m_ItemSize); @@ -101,7 +98,7 @@ class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, CFXCODEC_HorzTable(); ~CFXCODEC_HorzTable(); - void Calc(int dest_len, int src_len, bool bInterpol); + void Calc(int dest_len, int src_len); PixelWeight* GetPixelWeight(int pixel) { return reinterpret_cast(m_pWeightTables.data() + pixel * m_ItemSize); @@ -125,62 +122,18 @@ class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, std::vector m_pWeightTables; }; - CFX_RetainPtr m_pFile; - CCodec_ModuleMgr* m_pCodecMgr; - FXJPEG_Context* m_pJpegContext; - FXPNG_Context* m_pPngContext; - FXGIF_Context* m_pGifContext; - FXBMP_Context* m_pBmpContext; - CCodec_TiffContext* m_pTiffContext; - FXCODEC_IMAGE_TYPE m_imagType; - uint32_t m_offSet; - uint8_t* m_pSrcBuf; - uint32_t m_SrcSize; - uint8_t* m_pDecodeBuf; - int m_ScanlineSize; - CFX_DIBitmap* m_pDeviceBitmap; - bool m_bInterpol; - CFXCODEC_WeightTable m_WeightHorz; - CFXCODEC_VertTable m_WeightVert; - CFXCODEC_HorzTable m_WeightHorzOO; - int m_SrcWidth; - int m_SrcHeight; - int m_SrcComponents; - int m_SrcBPC; - FX_RECT m_clipBox; - int m_startX; - int m_startY; - int m_sizeX; - int m_sizeY; - int m_TransMethod; - FX_ARGB* m_pSrcPalette; - int m_SrcPaletteNumber; - int m_SrcRow; - FXCodec_Format m_SrcFormat; - int m_SrcPassNumber; - int m_FrameNumber; - int m_FrameCur; - int m_GifBgIndex; - uint8_t* m_pGifPalette; - int32_t m_GifPltNumber; - int m_GifTransIndex; - FX_RECT m_GifFrameRect; - bool m_BmpIsTopBottom; - FXCODEC_STATUS m_status; - - // ICodec_PngModule::Delegate + // CCodec_PngModule::Delegate bool PngReadHeader(int width, int height, int bpc, int pass, int* color_type, double* gamma) override; - bool PngAskScanlineBuf(int line, uint8_t*& src_buf) override; + bool PngAskScanlineBuf(int line, uint8_t** pSrcBuf) override; void PngFillScanlineBufCompleted(int pass, int line) override; - // ICodec_GifModule::Delegate + // CCodec_GifModule::Delegate void GifRecordCurrentPosition(uint32_t& cur_pos) override; - uint8_t* GifAskLocalPaletteBuf(int32_t frame_num, int32_t pal_size) override; bool GifInputRecordPositionBuf(uint32_t rcd_pos, const FX_RECT& img_rc, int32_t pal_num, @@ -192,38 +145,103 @@ class CCodec_ProgressiveDecoder : public ICodec_BmpModule::Delegate, bool interlace) override; void GifReadScanline(int32_t row_num, uint8_t* row_buf) override; - // ICodec_BmpModule::Delegate + // CCodec_BmpModule::Delegate bool BmpInputImagePositionBuf(uint32_t rcd_pos) override; - void BmpReadScanline(int32_t row_num, uint8_t* row_buf) override; + void BmpReadScanline(uint32_t row_num, + const std::vector& row_buf) override; - protected: - bool BmpReadMoreData(ICodec_BmpModule* pBmpModule, + private: + bool BmpReadMoreData(CCodec_BmpModule* pBmpModule, FXCODEC_STATUS& err_status); - bool GifReadMoreData(ICodec_GifModule* pGifModule, + bool GifReadMoreData(CCodec_GifModule* pGifModule, FXCODEC_STATUS& err_status); - void GifDoubleLineResampleVert(CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row); - void PngOneOneMapResampleHorz(CFX_DIBitmap* pDeviceBitmap, + bool JpegReadMoreData(CCodec_JpegModule* pJpegModule, + FXCODEC_STATUS& err_status); + void PngOneOneMapResampleHorz(const RetainPtr& pDeviceBitmap, int32_t des_line, uint8_t* src_scan, FXCodec_Format src_format); bool DetectImageType(FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute* pAttribute); + bool BmpDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + bool JpegDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + bool PngDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + bool GifDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + bool TifDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + void GetDownScale(int& down_scale); void GetTransMethod(FXDIB_Format des_format, FXCodec_Format src_format); - void ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, + + void ReSampleScanline(const RetainPtr& pDeviceBitmap, int32_t des_line, uint8_t* src_scan, FXCodec_Format src_format); - void Resample(CFX_DIBitmap* pDeviceBitmap, + void Resample(const RetainPtr& pDeviceBitmap, int32_t src_line, uint8_t* src_scan, FXCodec_Format src_format); - void ResampleVert(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row); - bool JpegReadMoreData(CCodec_JpegModule* pJpegModule, - FXCODEC_STATUS& err_status); - void ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row); + void ResampleVert(const RetainPtr& pDeviceBitmap, + double scale_y, + int des_row); + void ResampleVertBT(const RetainPtr& pDeviceBitmap, + double scale_y, + int des_row); + void GifDoubleLineResampleVert(const RetainPtr& pDeviceBitmap, + double scale_y, + int des_row); + + FXCODEC_STATUS JpegStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS PngStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS GifStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS BmpStartDecode(const RetainPtr& pDIBitmap); + + FXCODEC_STATUS JpegContinueDecode(); + FXCODEC_STATUS PngContinueDecode(); + FXCODEC_STATUS GifContinueDecode(); + FXCODEC_STATUS BmpContinueDecode(); + FXCODEC_STATUS TifContinueDecode(); + + RetainPtr m_pFile; + RetainPtr m_pDeviceBitmap; + UnownedPtr m_pCodecMgr; + std::unique_ptr m_pJpegContext; + std::unique_ptr m_pPngContext; + std::unique_ptr m_pGifContext; + std::unique_ptr m_pBmpContext; + std::unique_ptr m_pTiffContext; + FXCODEC_IMAGE_TYPE m_imagType; + uint32_t m_offSet; + uint8_t* m_pSrcBuf; + uint32_t m_SrcSize; + uint8_t* m_pDecodeBuf; + int m_ScanlineSize; + CFXCODEC_WeightTable m_WeightHorz; + CFXCODEC_VertTable m_WeightVert; + CFXCODEC_HorzTable m_WeightHorzOO; + int m_SrcWidth; + int m_SrcHeight; + int m_SrcComponents; + int m_SrcBPC; + FX_RECT m_clipBox; + int m_startX; + int m_startY; + int m_sizeX; + int m_sizeY; + int m_TransMethod; + FX_ARGB* m_pSrcPalette; + int m_SrcPaletteNumber; + int m_SrcRow; + FXCodec_Format m_SrcFormat; + int m_SrcPassNumber; + size_t m_FrameNumber; + size_t m_FrameCur; + int m_GifBgIndex; + uint8_t* m_pGifPalette; + int32_t m_GifPltNumber; + int m_GifTransIndex; + FX_RECT m_GifFrameRect; + bool m_BmpIsTopBottom; + FXCODEC_STATUS m_status; }; #endif // CORE_FXCODEC_CODEC_CCODEC_PROGRESSIVEDECODER_H_ diff --git a/core/fxcodec/codec/ccodec_scanlinedecoder.cpp b/core/fxcodec/codec/ccodec_scanlinedecoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55b9a2a87da5411740c2918a258da0595c63806a --- /dev/null +++ b/core/fxcodec/codec/ccodec_scanlinedecoder.cpp @@ -0,0 +1,73 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" + +#include "core/fxcrt/ifx_pauseindicator.h" + +CCodec_ScanlineDecoder::CCodec_ScanlineDecoder() + : CCodec_ScanlineDecoder(0, 0, 0, 0, 0, 0, 0) {} + +CCodec_ScanlineDecoder::CCodec_ScanlineDecoder(int nOrigWidth, + int nOrigHeight, + int nOutputWidth, + int nOutputHeight, + int nComps, + int nBpc, + uint32_t nPitch) + : m_OrigWidth(nOrigWidth), + m_OrigHeight(nOrigHeight), + m_OutputWidth(nOutputWidth), + m_OutputHeight(nOutputHeight), + m_nComps(nComps), + m_bpc(nBpc), + m_Pitch(nPitch), + m_NextLine(-1), + m_pLastScanline(nullptr) {} + +CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder() {} + +const uint8_t* CCodec_ScanlineDecoder::GetScanline(int line) { + if (m_NextLine == line + 1) + return m_pLastScanline; + + if (m_NextLine < 0 || m_NextLine > line) { + if (!v_Rewind()) + return nullptr; + m_NextLine = 0; + } + while (m_NextLine < line) { + ReadNextLine(); + m_NextLine++; + } + m_pLastScanline = ReadNextLine(); + m_NextLine++; + return m_pLastScanline; +} + +bool CCodec_ScanlineDecoder::SkipToScanline(int line, + IFX_PauseIndicator* pPause) { + if (m_NextLine == line || m_NextLine == line + 1) + return false; + + if (m_NextLine < 0 || m_NextLine > line) { + v_Rewind(); + m_NextLine = 0; + } + m_pLastScanline = nullptr; + while (m_NextLine < line) { + m_pLastScanline = ReadNextLine(); + m_NextLine++; + if (pPause && pPause->NeedToPauseNow()) { + return true; + } + } + return false; +} + +uint8_t* CCodec_ScanlineDecoder::ReadNextLine() { + return v_GetNextLine(); +} diff --git a/core/fxcodec/codec/ccodec_scanlinedecoder.h b/core/fxcodec/codec/ccodec_scanlinedecoder.h index 06bb6d5abe7e42d9b56f4b7998b403c6e7b0210d..05d5eab92b7cf7b02bca6b42b64a11cfc7dfcf95 100644 --- a/core/fxcodec/codec/ccodec_scanlinedecoder.h +++ b/core/fxcodec/codec/ccodec_scanlinedecoder.h @@ -9,7 +9,7 @@ #include "core/fxcrt/fx_system.h" -class IFX_Pause; +class IFX_PauseIndicator; class CCodec_ScanlineDecoder { public: @@ -24,7 +24,7 @@ class CCodec_ScanlineDecoder { virtual ~CCodec_ScanlineDecoder(); const uint8_t* GetScanline(int line); - bool SkipToScanline(int line, IFX_Pause* pPause); + bool SkipToScanline(int line, IFX_PauseIndicator* pPause); int GetWidth() { return m_OutputWidth; } int GetHeight() { return m_OutputHeight; } diff --git a/core/fxcodec/codec/ccodec_tiffmodule.cpp b/core/fxcodec/codec/ccodec_tiffmodule.cpp index 736772892addd0e39540ee3361d9ef1570f81b47..0bf0045261fc6f93ce09560a08c089fb89590623 100644 --- a/core/fxcodec/codec/ccodec_tiffmodule.cpp +++ b/core/fxcodec/codec/ccodec_tiffmodule.cpp @@ -10,79 +10,87 @@ #include "core/fxcodec/codec/codec_int.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" extern "C" { #include "third_party/libtiff/tiffiop.h" } -class CCodec_TiffContext { +class CTiffContext : public CCodec_TiffModule::Context { public: - CCodec_TiffContext(); - ~CCodec_TiffContext(); + CTiffContext(); + ~CTiffContext() override; - bool InitDecoder(const CFX_RetainPtr& file_ptr); + bool InitDecoder(const RetainPtr& file_ptr); bool LoadFrameInfo(int32_t frame, int32_t* width, int32_t* height, int32_t* comps, int32_t* bpc, CFX_DIBAttribute* pAttribute); - bool Decode(CFX_DIBitmap* pDIBitmap); + bool Decode(const RetainPtr& pDIBitmap); - CFX_RetainPtr io_in() const { return m_io_in; } + RetainPtr io_in() const { return m_io_in; } uint32_t offset() const { return m_offset; } void set_offset(uint32_t offset) { m_offset = offset; } private: - bool IsSupport(const CFX_DIBitmap* pDIBitmap) const; - void SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps); - bool Decode1bppRGB(CFX_DIBitmap* pDIBitmap, + bool IsSupport(const RetainPtr& pDIBitmap) const; + void SetPalette(const RetainPtr& pDIBitmap, uint16_t bps); + bool Decode1bppRGB(const RetainPtr& pDIBitmap, int32_t height, int32_t width, uint16_t bps, uint16_t spp); - bool Decode8bppRGB(CFX_DIBitmap* pDIBitmap, + bool Decode8bppRGB(const RetainPtr& pDIBitmap, int32_t height, int32_t width, uint16_t bps, uint16_t spp); - bool Decode24bppRGB(CFX_DIBitmap* pDIBitmap, + bool Decode24bppRGB(const RetainPtr& pDIBitmap, int32_t height, int32_t width, uint16_t bps, uint16_t spp); - CFX_RetainPtr m_io_in; + RetainPtr m_io_in; uint32_t m_offset; TIFF* m_tif_ctx; }; +void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz) { + return FXMEM_DefaultCalloc(nmemb, siz); +} + void* _TIFFmalloc(tmsize_t size) { - return FXMEM_DefaultAlloc(size, 0); + return FXMEM_DefaultAlloc(size); } void _TIFFfree(void* ptr) { - FXMEM_DefaultFree(ptr, 0); + if (ptr) + FXMEM_DefaultFree(ptr); } void* _TIFFrealloc(void* ptr, tmsize_t size) { - return FXMEM_DefaultRealloc(ptr, size, 0); + return FXMEM_DefaultRealloc(ptr, size); } void _TIFFmemset(void* ptr, int val, tmsize_t size) { - FXSYS_memset(ptr, val, (size_t)size); + memset(ptr, val, static_cast(size)); } void _TIFFmemcpy(void* des, const void* src, tmsize_t size) { - FXSYS_memcpy(des, src, (size_t)size); + memcpy(des, src, static_cast(size)); } int _TIFFmemcmp(const void* ptr1, const void* ptr2, tmsize_t size) { - return FXSYS_memcmp(ptr1, ptr2, (size_t)size); + return memcmp(ptr1, ptr2, static_cast(size)); } int _TIFFIfMultiplicationOverflow(tmsize_t op1, tmsize_t op2) { @@ -95,8 +103,7 @@ TIFFErrorHandler _TIFFerrorHandler = nullptr; namespace { tsize_t tiff_read(thandle_t context, tdata_t buf, tsize_t length) { - CCodec_TiffContext* pTiffContext = - reinterpret_cast(context); + CTiffContext* pTiffContext = reinterpret_cast(context); FX_SAFE_UINT32 increment = pTiffContext->offset(); increment += length; if (!increment.IsValid()) @@ -114,13 +121,12 @@ tsize_t tiff_read(thandle_t context, tdata_t buf, tsize_t length) { } tsize_t tiff_write(thandle_t context, tdata_t buf, tsize_t length) { - ASSERT(false); + NOTREACHED(); return 0; } toff_t tiff_seek(thandle_t context, toff_t offset, int whence) { - CCodec_TiffContext* pTiffContext = - reinterpret_cast(context); + CTiffContext* pTiffContext = reinterpret_cast(context); FX_SAFE_FILESIZE safe_offset = offset; if (!safe_offset.IsValid()) return static_cast(-1); @@ -157,8 +163,7 @@ int tiff_close(thandle_t context) { } toff_t tiff_get_size(thandle_t context) { - CCodec_TiffContext* pTiffContext = - reinterpret_cast(context); + CTiffContext* pTiffContext = reinterpret_cast(context); return static_cast(pTiffContext->io_in()->GetSize()); } @@ -186,20 +191,20 @@ bool Tiff_Exif_GetInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttribute* pAttr) { return false; T* ptr = FX_Alloc(T, 1); *ptr = val; - pAttr->m_Exif[tag] = (void*)ptr; + pAttr->m_Exif[tag] = ptr; return true; } void Tiff_Exif_GetStringInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttribute* pAttr) { - FX_CHAR* buf = nullptr; + char* buf = nullptr; TIFFGetField(tif_ctx, tag, &buf); if (!buf) return; - FX_STRSIZE size = FXSYS_strlen(buf); + size_t size = strlen(buf); uint8_t* ptr = FX_Alloc(uint8_t, size + 1); - FXSYS_memcpy(ptr, buf, size); + memcpy(ptr, buf, size); ptr[size] = 0; pAttr->m_Exif[tag] = ptr; } @@ -215,27 +220,27 @@ void TiffBGRA2RGBA(uint8_t* pBuf, int32_t pixel, int32_t spp) { } // namespace -CCodec_TiffContext::CCodec_TiffContext() +CTiffContext::CTiffContext() : m_io_in(nullptr), m_offset(0), m_tif_ctx(nullptr) {} -CCodec_TiffContext::~CCodec_TiffContext() { +CTiffContext::~CTiffContext() { if (m_tif_ctx) TIFFClose(m_tif_ctx); } -bool CCodec_TiffContext::InitDecoder( - const CFX_RetainPtr& file_ptr) { +bool CTiffContext::InitDecoder( + const RetainPtr& file_ptr) { m_io_in = file_ptr; m_tif_ctx = tiff_open(this, "r"); return !!m_tif_ctx; } -bool CCodec_TiffContext::LoadFrameInfo(int32_t frame, - int32_t* width, - int32_t* height, - int32_t* comps, - int32_t* bpc, - CFX_DIBAttribute* pAttribute) { +bool CTiffContext::LoadFrameInfo(int32_t frame, + int32_t* width, + int32_t* height, + int32_t* comps, + int32_t* bpc, + CFX_DIBAttribute* pAttribute) { if (!TIFFSetDirectory(m_tif_ctx, (uint16)frame)) return false; @@ -257,16 +262,14 @@ bool CCodec_TiffContext::LoadFrameInfo(int32_t frame, pAttribute->m_wDPIUnit--; } Tiff_Exif_GetInfo(m_tif_ctx, TIFFTAG_ORIENTATION, pAttribute); - if (Tiff_Exif_GetInfo(m_tif_ctx, TIFFTAG_XRESOLUTION, - pAttribute)) { + if (Tiff_Exif_GetInfo(m_tif_ctx, TIFFTAG_XRESOLUTION, pAttribute)) { void* val = pAttribute->m_Exif[TIFFTAG_XRESOLUTION]; - FX_FLOAT fDpi = val ? *reinterpret_cast(val) : 0; + float fDpi = val ? *reinterpret_cast(val) : 0; pAttribute->m_nXDPI = (int32_t)(fDpi + 0.5f); } - if (Tiff_Exif_GetInfo(m_tif_ctx, TIFFTAG_YRESOLUTION, - pAttribute)) { + if (Tiff_Exif_GetInfo(m_tif_ctx, TIFFTAG_YRESOLUTION, pAttribute)) { void* val = pAttribute->m_Exif[TIFFTAG_YRESOLUTION]; - FX_FLOAT fDpi = val ? *reinterpret_cast(val) : 0; + float fDpi = val ? *reinterpret_cast(val) : 0; pAttribute->m_nYDPI = (int32_t)(fDpi + 0.5f); } Tiff_Exif_GetStringInfo(m_tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pAttribute); @@ -289,7 +292,7 @@ bool CCodec_TiffContext::LoadFrameInfo(int32_t frame, return true; } -bool CCodec_TiffContext::IsSupport(const CFX_DIBitmap* pDIBitmap) const { +bool CTiffContext::IsSupport(const RetainPtr& pDIBitmap) const { if (TIFFIsTiled(m_tif_ctx)) return false; @@ -319,7 +322,8 @@ bool CCodec_TiffContext::IsSupport(const CFX_DIBitmap* pDIBitmap) const { return planarconfig != PLANARCONFIG_SEPARATE; } -void CCodec_TiffContext::SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps) { +void CTiffContext::SetPalette(const RetainPtr& pDIBitmap, + uint16_t bps) { uint16_t* red_orig = nullptr; uint16_t* green_orig = nullptr; uint16_t* blue_orig = nullptr; @@ -338,15 +342,15 @@ void CCodec_TiffContext::SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps) { uint32_t b = blue_orig[index] & 0xFF; uint32_t color = (uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16) | (((uint32)0xffL) << 24); - pDIBitmap->SetPaletteEntry(index, color); + pDIBitmap->SetPaletteArgb(index, color); } } -bool CCodec_TiffContext::Decode1bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp) { +bool CTiffContext::Decode1bppRGB(const RetainPtr& pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp) { if (pDIBitmap->GetBPP() != 1 || spp != 1 || bps != 1 || !IsSupport(pDIBitmap)) { return false; @@ -370,11 +374,11 @@ bool CCodec_TiffContext::Decode1bppRGB(CFX_DIBitmap* pDIBitmap, return true; } -bool CCodec_TiffContext::Decode8bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp) { +bool CTiffContext::Decode8bppRGB(const RetainPtr& pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp) { if (pDIBitmap->GetBPP() != 8 || spp != 1 || (bps != 4 && bps != 8) || !IsSupport(pDIBitmap)) { return false; @@ -406,11 +410,11 @@ bool CCodec_TiffContext::Decode8bppRGB(CFX_DIBitmap* pDIBitmap, return true; } -bool CCodec_TiffContext::Decode24bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp) { +bool CTiffContext::Decode24bppRGB(const RetainPtr& pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp) { if (pDIBitmap->GetBPP() != 24 || !IsSupport(pDIBitmap)) return false; @@ -434,7 +438,7 @@ bool CCodec_TiffContext::Decode24bppRGB(CFX_DIBitmap* pDIBitmap, return true; } -bool CCodec_TiffContext::Decode(CFX_DIBitmap* pDIBitmap) { +bool CTiffContext::Decode(const RetainPtr& pDIBitmap) { uint32_t img_wid = pDIBitmap->GetWidth(); uint32_t img_hei = pDIBitmap->GetHeight(); uint32_t width = 0; @@ -475,30 +479,28 @@ bool CCodec_TiffContext::Decode(CFX_DIBitmap* pDIBitmap) { return false; } -CCodec_TiffContext* CCodec_TiffModule::CreateDecoder( - const CFX_RetainPtr& file_ptr) { - auto pDecoder = pdfium::MakeUnique(); +std::unique_ptr CCodec_TiffModule::CreateDecoder( + const RetainPtr& file_ptr) { + auto pDecoder = pdfium::MakeUnique(); if (!pDecoder->InitDecoder(file_ptr)) return nullptr; - return pDecoder.release(); + return pDecoder; } -bool CCodec_TiffModule::LoadFrameInfo(CCodec_TiffContext* ctx, +bool CCodec_TiffModule::LoadFrameInfo(Context* pContext, int32_t frame, int32_t* width, int32_t* height, int32_t* comps, int32_t* bpc, CFX_DIBAttribute* pAttribute) { + auto* ctx = static_cast(pContext); return ctx->LoadFrameInfo(frame, width, height, comps, bpc, pAttribute); } -bool CCodec_TiffModule::Decode(CCodec_TiffContext* ctx, - class CFX_DIBitmap* pDIBitmap) { +bool CCodec_TiffModule::Decode(Context* pContext, + const RetainPtr& pDIBitmap) { + auto* ctx = static_cast(pContext); return ctx->Decode(pDIBitmap); } - -void CCodec_TiffModule::DestroyDecoder(CCodec_TiffContext* ctx) { - delete ctx; -} diff --git a/core/fxcodec/codec/ccodec_tiffmodule.h b/core/fxcodec/codec/ccodec_tiffmodule.h index a8820f4aacc7362218ce417592aa6b1887408f77..8d3bed7df289b5492512584a351dc5b1feec50c1 100644 --- a/core/fxcodec/codec/ccodec_tiffmodule.h +++ b/core/fxcodec/codec/ccodec_tiffmodule.h @@ -7,25 +7,32 @@ #ifndef CORE_FXCODEC_CODEC_CCODEC_TIFFMODULE_H_ #define CORE_FXCODEC_CODEC_CCODEC_TIFFMODULE_H_ -#include "core/fxcodec/codec/icodec_tiffmodule.h" -#include "core/fxcrt/cfx_retain_ptr.h" +#include + #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibitmap.h" + +class CFX_DIBAttribute; +class IFX_SeekableReadStream; -class CCodec_TiffModule : public ICodec_TiffModule { +class CCodec_TiffModule { public: - ~CCodec_TiffModule() override {} + class Context { + public: + virtual ~Context() {} + }; - CCodec_TiffContext* CreateDecoder( - const CFX_RetainPtr& file_ptr) override; - bool LoadFrameInfo(CCodec_TiffContext* ctx, + std::unique_ptr CreateDecoder( + const RetainPtr& file_ptr); + bool LoadFrameInfo(Context* ctx, int32_t frame, int32_t* width, int32_t* height, int32_t* comps, int32_t* bpc, - CFX_DIBAttribute* pAttribute) override; - bool Decode(CCodec_TiffContext* ctx, class CFX_DIBitmap* pDIBitmap) override; - void DestroyDecoder(CCodec_TiffContext* ctx) override; + CFX_DIBAttribute* pAttribute); + bool Decode(Context* ctx, const RetainPtr& pDIBitmap); }; #endif // CORE_FXCODEC_CODEC_CCODEC_TIFFMODULE_H_ diff --git a/core/fxcodec/codec/cjpx_decoder.h b/core/fxcodec/codec/cjpx_decoder.h new file mode 100644 index 0000000000000000000000000000000000000000..c68969301cbb106595af57f306fc330d86551dc8 --- /dev/null +++ b/core/fxcodec/codec/cjpx_decoder.h @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCODEC_CODEC_CJPX_DECODER_H_ +#define CORE_FXCODEC_CODEC_CJPX_DECODER_H_ + +#include +#include + +#include "core/fxcodec/codec/codec_int.h" +#include "core/fxcrt/unowned_ptr.h" +#include "third_party/libopenjpeg20/openjpeg.h" + +class CPDF_ColorSpace; + +class CJPX_Decoder { + public: + explicit CJPX_Decoder(CPDF_ColorSpace* cs); + ~CJPX_Decoder(); + + bool Init(const unsigned char* src_data, uint32_t src_size); + void GetInfo(uint32_t* width, uint32_t* height, uint32_t* components); + bool Decode(uint8_t* dest_buf, + int pitch, + const std::vector& offsets); + + private: + const uint8_t* m_SrcData; + uint32_t m_SrcSize; + // TODO(rharrison): Convert these to unowned ptrs, if possible. + opj_image_t* m_Image; + opj_codec_t* m_Codec; + std::unique_ptr m_DecodeData; + opj_stream_t* m_Stream; + opj_dparameters_t m_Parameters; + UnownedPtr const m_ColorSpace; +}; + +#endif // CORE_FXCODEC_CODEC_CJPX_DECODER_H_ diff --git a/core/fxcodec/codec/codec_int.h b/core/fxcodec/codec/codec_int.h index edd5a67a25f43a6c0ef16c75a27c7e38d3d01dee..df2e758efe46f24c3ef14a9332cd27b6713fc4c9 100644 --- a/core/fxcodec/codec/codec_int.h +++ b/core/fxcodec/codec/codec_int.h @@ -14,17 +14,16 @@ #include #include -#include "core/fxcodec/fx_codec.h" #include "core/fxcodec/jbig2/JBig2_Context.h" #include "third_party/libopenjpeg20/openjpeg.h" class CPDF_ColorSpace; struct DecodeData { - public: - DecodeData(uint8_t* data, OPJ_SIZE_T size) + DecodeData(const uint8_t* data, OPJ_SIZE_T size) : src_data(data), src_size(size), offset(0) {} - uint8_t* src_data; + + const uint8_t* src_data; OPJ_SIZE_T src_size; OPJ_SIZE_T offset; }; @@ -35,9 +34,6 @@ void sycc420_to_rgb(opj_image_t* img); OPJ_SIZE_T opj_read_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_user_data); -OPJ_SIZE_T opj_write_from_memory(void* p_buffer, - OPJ_SIZE_T nb_bytes, - void* p_user_data); OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data); OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data); diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp index 0d886b43cb1161876d3e13b0f4012f6f1aada31d..4d094e54fbf257471e204f10ab67c9712445ee50 100644 --- a/core/fxcodec/codec/fx_codec.cpp +++ b/core/fxcodec/codec/fx_codec.cpp @@ -9,88 +9,1379 @@ #include #include #include +#include #include +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcodec/codec/ccodec_faxmodule.h" +#include "core/fxcodec/codec/ccodec_flatemodule.h" +#include "core/fxcodec/codec/ccodec_iccmodule.h" +#include "core/fxcodec/codec/ccodec_jbig2module.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" +#include "core/fxcodec/codec/ccodec_jpxmodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" #include "core/fxcodec/codec/codec_int.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_safe_types.h" #include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" +#ifdef PDF_ENABLE_XFA +#include "core/fxcodec/codec/ccodec_bmpmodule.h" +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#include "core/fxcodec/codec/ccodec_pngmodule.h" +#include "core/fxcodec/codec/ccodec_tiffmodule.h" +#endif // PDF_ENABLE_XFA + +namespace { + +const uint8_t g_CMYK[81 * 81 * 3] = { + 255, 255, 255, 225, 226, 228, 199, 200, 202, 173, 174, 178, 147, 149, 152, + 123, 125, 128, 99, 99, 102, 69, 70, 71, 34, 30, 31, 255, 253, 229, + 226, 224, 203, 200, 199, 182, 173, 173, 158, 149, 148, 135, 125, 124, 113, + 99, 99, 90, 70, 69, 63, 33, 29, 24, 255, 251, 204, 228, 223, 182, + 201, 198, 163, 174, 172, 142, 150, 147, 122, 125, 123, 101, 99, 98, 80, + 70, 68, 54, 32, 28, 16, 255, 249, 179, 230, 222, 160, 203, 197, 144, + 174, 170, 124, 150, 145, 105, 125, 122, 88, 99, 97, 69, 70, 68, 46, + 31, 28, 6, 255, 247, 154, 229, 220, 138, 203, 195, 122, 176, 169, 107, + 150, 145, 91, 125, 121, 74, 100, 96, 57, 70, 67, 35, 29, 26, 0, + 255, 246, 128, 231, 217, 114, 205, 194, 101, 176, 167, 88, 150, 144, 75, + 125, 120, 60, 100, 96, 44, 70, 66, 24, 28, 26, 0, 255, 244, 96, + 231, 217, 87, 203, 192, 78, 175, 167, 66, 150, 143, 56, 125, 119, 43, + 100, 95, 29, 69, 66, 7, 26, 26, 0, 255, 243, 51, 232, 215, 51, + 204, 191, 43, 176, 165, 38, 150, 142, 28, 125, 118, 17, 99, 94, 0, + 68, 65, 0, 24, 25, 0, 255, 241, 0, 231, 215, 0, 203, 190, 0, + 176, 164, 0, 150, 141, 0, 126, 117, 0, 99, 93, 0, 68, 65, 0, + 24, 25, 0, 252, 228, 238, 222, 201, 211, 197, 180, 190, 171, 156, 166, + 147, 133, 143, 123, 111, 119, 99, 88, 94, 71, 61, 66, 34, 22, 26, + 254, 226, 213, 224, 201, 191, 199, 179, 171, 172, 155, 148, 147, 133, 128, + 123, 110, 106, 98, 87, 83, 70, 59, 57, 33, 21, 18, 254, 224, 191, + 224, 199, 172, 200, 177, 153, 173, 154, 133, 147, 132, 115, 123, 109, 94, + 98, 86, 74, 70, 59, 49, 32, 21, 9, 255, 222, 168, 227, 198, 150, + 200, 175, 135, 173, 153, 118, 148, 130, 99, 123, 109, 82, 98, 86, 64, + 69, 58, 40, 31, 19, 0, 255, 221, 145, 227, 196, 129, 201, 174, 115, + 173, 151, 99, 148, 129, 85, 124, 108, 69, 98, 85, 52, 69, 58, 30, + 30, 19, 0, 255, 219, 121, 227, 195, 109, 201, 174, 97, 174, 150, 83, + 148, 129, 70, 124, 107, 55, 98, 84, 40, 69, 58, 19, 28, 18, 0, + 255, 218, 92, 229, 194, 82, 202, 173, 75, 174, 150, 63, 149, 128, 51, + 124, 106, 39, 98, 84, 24, 68, 57, 3, 26, 18, 0, 255, 217, 54, + 228, 193, 52, 201, 172, 46, 174, 148, 36, 148, 127, 27, 123, 105, 14, + 98, 83, 0, 68, 56, 0, 25, 18, 0, 255, 216, 0, 229, 192, 2, + 202, 171, 4, 173, 148, 0, 148, 126, 0, 124, 105, 0, 98, 83, 0, + 68, 56, 0, 24, 17, 0, 249, 204, 223, 219, 181, 199, 195, 160, 178, + 170, 140, 156, 146, 119, 134, 123, 99, 112, 98, 77, 88, 70, 52, 61, + 34, 11, 20, 250, 201, 200, 221, 180, 178, 197, 159, 161, 171, 139, 139, + 147, 119, 120, 123, 98, 99, 98, 77, 78, 69, 51, 52, 34, 11, 10, + 252, 201, 180, 223, 179, 162, 197, 159, 144, 170, 138, 125, 146, 117, 107, + 122, 97, 89, 98, 76, 69, 69, 50, 44, 32, 11, 2, 252, 199, 158, + 222, 177, 143, 199, 158, 127, 171, 137, 110, 147, 117, 93, 122, 96, 76, + 97, 75, 58, 69, 50, 36, 32, 10, 0, 253, 198, 137, 223, 177, 123, + 198, 156, 110, 171, 136, 95, 146, 116, 80, 122, 96, 65, 97, 75, 47, + 69, 50, 25, 30, 10, 0, 254, 197, 115, 225, 175, 104, 198, 156, 92, + 172, 135, 79, 147, 115, 66, 123, 95, 52, 98, 74, 37, 69, 49, 15, + 29, 10, 0, 254, 196, 89, 224, 175, 80, 199, 154, 70, 172, 134, 59, + 146, 114, 48, 122, 95, 36, 97, 74, 21, 68, 49, 0, 27, 9, 0, + 255, 195, 57, 225, 173, 52, 198, 154, 44, 172, 133, 36, 147, 113, 26, + 123, 94, 14, 98, 74, 0, 68, 49, 0, 26, 10, 0, 254, 194, 15, + 225, 172, 12, 198, 153, 7, 172, 132, 3, 146, 113, 0, 123, 93, 0, + 98, 73, 0, 68, 49, 0, 26, 9, 0, 246, 178, 209, 218, 159, 186, + 194, 140, 166, 168, 122, 145, 144, 104, 125, 121, 85, 103, 97, 65, 81, + 69, 41, 55, 34, 0, 12, 248, 176, 186, 219, 157, 166, 195, 139, 149, + 168, 121, 130, 144, 103, 111, 121, 85, 91, 97, 65, 71, 69, 41, 46, + 34, 0, 4, 249, 175, 168, 220, 156, 150, 196, 139, 135, 169, 121, 116, + 144, 103, 100, 122, 84, 83, 98, 65, 63, 70, 41, 39, 33, 0, 0, + 249, 175, 148, 220, 155, 133, 196, 138, 119, 169, 120, 103, 145, 101, 87, + 121, 83, 71, 97, 65, 54, 69, 41, 31, 32, 0, 0, 249, 173, 128, + 222, 154, 115, 195, 137, 102, 170, 119, 88, 145, 101, 74, 122, 83, 59, + 97, 64, 43, 68, 40, 20, 30, 0, 0, 250, 172, 108, 221, 154, 98, + 195, 136, 86, 170, 118, 73, 145, 100, 61, 122, 82, 48, 97, 63, 32, + 69, 40, 11, 28, 0, 0, 250, 171, 85, 221, 153, 76, 196, 136, 67, + 170, 117, 56, 145, 99, 44, 121, 82, 33, 97, 63, 17, 68, 40, 0, + 28, 0, 0, 251, 171, 58, 222, 152, 50, 197, 135, 43, 169, 117, 34, + 146, 99, 25, 121, 81, 10, 96, 63, 0, 68, 40, 0, 27, 0, 0, + 250, 170, 26, 222, 151, 19, 196, 134, 13, 169, 116, 4, 145, 99, 0, + 122, 81, 0, 97, 63, 0, 67, 40, 0, 26, 0, 0, 244, 153, 194, + 215, 136, 173, 192, 121, 155, 167, 104, 135, 143, 89, 115, 121, 72, 96, + 97, 54, 75, 70, 31, 49, 34, 0, 6, 245, 153, 173, 216, 136, 155, + 192, 120, 138, 167, 104, 121, 144, 88, 103, 121, 71, 85, 97, 54, 66, + 69, 31, 42, 34, 0, 0, 246, 152, 157, 217, 135, 140, 193, 120, 126, + 167, 103, 109, 143, 88, 92, 121, 72, 76, 97, 54, 58, 69, 31, 35, + 33, 0, 0, 245, 150, 139, 218, 134, 125, 193, 119, 111, 167, 103, 96, + 144, 87, 80, 121, 71, 66, 96, 53, 49, 68, 31, 26, 32, 0, 0, + 246, 151, 122, 218, 133, 108, 194, 118, 96, 168, 102, 81, 144, 86, 69, + 120, 71, 55, 95, 53, 39, 68, 30, 17, 31, 0, 0, 248, 150, 103, + 218, 133, 91, 193, 118, 81, 168, 102, 69, 143, 86, 56, 120, 70, 43, + 96, 53, 28, 68, 31, 6, 29, 0, 0, 247, 149, 81, 218, 132, 72, + 194, 117, 62, 168, 101, 52, 144, 86, 42, 121, 70, 29, 96, 52, 13, + 68, 30, 0, 28, 0, 0, 247, 148, 55, 219, 131, 50, 194, 117, 43, + 167, 101, 32, 144, 85, 22, 120, 69, 8, 96, 52, 0, 67, 30, 0, + 27, 0, 0, 247, 147, 29, 218, 131, 24, 194, 116, 20, 168, 100, 11, + 144, 85, 0, 120, 69, 0, 96, 52, 0, 67, 30, 0, 26, 0, 0, + 242, 130, 179, 214, 114, 160, 190, 101, 143, 166, 87, 125, 143, 72, 107, + 120, 58, 88, 96, 42, 68, 69, 17, 44, 35, 0, 0, 243, 129, 161, + 215, 114, 143, 191, 101, 128, 166, 87, 113, 143, 73, 96, 120, 58, 79, + 96, 41, 60, 69, 18, 37, 33, 0, 0, 243, 129, 146, 216, 114, 130, + 192, 101, 117, 166, 87, 101, 143, 72, 86, 121, 58, 69, 96, 42, 52, + 69, 18, 29, 31, 0, 0, 243, 128, 130, 216, 114, 115, 191, 101, 102, + 165, 86, 88, 142, 72, 75, 120, 58, 60, 95, 42, 43, 68, 19, 21, + 30, 0, 0, 244, 127, 112, 217, 113, 101, 192, 99, 89, 166, 85, 75, + 142, 72, 63, 119, 57, 50, 96, 41, 35, 68, 19, 13, 30, 0, 0, + 244, 127, 96, 216, 112, 86, 191, 99, 75, 166, 86, 64, 143, 72, 52, + 120, 57, 40, 95, 41, 24, 67, 20, 1, 29, 0, 0, 245, 126, 77, + 216, 113, 68, 191, 100, 59, 166, 85, 49, 142, 71, 38, 119, 57, 26, + 95, 41, 10, 67, 20, 0, 28, 0, 0, 244, 126, 55, 216, 112, 48, + 191, 99, 40, 166, 85, 31, 143, 71, 20, 119, 57, 6, 95, 42, 0, + 67, 20, 0, 28, 0, 0, 245, 126, 33, 217, 112, 26, 192, 99, 22, + 166, 84, 11, 142, 70, 0, 119, 57, 0, 95, 41, 0, 66, 20, 0, + 27, 0, 0, 241, 102, 167, 213, 90, 149, 189, 79, 133, 165, 66, 115, + 141, 54, 98, 119, 41, 81, 96, 25, 63, 69, 0, 38, 30, 0, 0, + 241, 102, 149, 213, 90, 133, 189, 79, 119, 165, 66, 103, 142, 55, 88, + 119, 41, 71, 96, 25, 53, 69, 0, 31, 28, 0, 0, 241, 102, 135, + 214, 90, 121, 190, 79, 108, 165, 66, 92, 141, 55, 78, 119, 42, 63, + 96, 26, 46, 69, 0, 24, 28, 0, 0, 241, 101, 120, 214, 90, 107, + 189, 79, 95, 165, 67, 83, 141, 54, 68, 118, 41, 54, 95, 27, 39, + 68, 0, 16, 27, 0, 0, 241, 102, 106, 213, 90, 93, 189, 78, 82, + 164, 67, 70, 141, 55, 58, 118, 42, 45, 94, 27, 29, 67, 2, 6, + 27, 0, 0, 242, 101, 90, 214, 89, 79, 190, 79, 69, 166, 67, 59, + 141, 55, 47, 118, 41, 35, 95, 27, 19, 67, 3, 0, 26, 0, 0, + 242, 102, 72, 213, 89, 63, 191, 79, 56, 164, 67, 45, 141, 55, 34, + 118, 42, 22, 94, 28, 6, 67, 3, 0, 26, 0, 0, 242, 100, 51, + 214, 89, 45, 190, 78, 38, 164, 67, 30, 141, 55, 18, 118, 42, 3, + 95, 28, 0, 66, 4, 0, 26, 0, 0, 243, 100, 33, 214, 90, 27, + 190, 78, 22, 165, 67, 13, 141, 55, 0, 118, 43, 0, 94, 29, 0, + 66, 5, 0, 26, 0, 0, 237, 69, 153, 211, 58, 135, 187, 51, 121, + 163, 41, 105, 141, 28, 90, 118, 15, 73, 96, 0, 56, 68, 0, 33, + 25, 0, 0, 239, 67, 137, 212, 60, 123, 189, 50, 110, 163, 41, 94, + 141, 29, 79, 118, 17, 65, 95, 0, 48, 69, 0, 26, 25, 0, 0, + 240, 69, 124, 211, 60, 111, 188, 50, 98, 163, 42, 85, 141, 31, 72, + 118, 18, 57, 94, 0, 41, 68, 0, 19, 25, 0, 0, 240, 70, 112, + 212, 61, 99, 188, 52, 87, 163, 41, 74, 140, 31, 62, 118, 20, 48, + 94, 2, 32, 68, 0, 11, 24, 0, 0, 239, 70, 98, 212, 62, 86, + 188, 53, 77, 164, 42, 64, 140, 32, 52, 118, 20, 40, 94, 3, 24, + 67, 0, 3, 23, 0, 0, 239, 71, 85, 212, 61, 74, 187, 53, 65, + 163, 44, 54, 140, 34, 43, 118, 22, 30, 95, 3, 14, 67, 0, 0, + 23, 0, 0, 239, 70, 67, 212, 62, 59, 188, 53, 51, 163, 45, 42, + 141, 34, 31, 117, 22, 17, 94, 5, 2, 66, 0, 0, 23, 0, 0, + 239, 71, 50, 213, 62, 43, 188, 54, 37, 164, 45, 28, 139, 34, 16, + 117, 22, 2, 94, 7, 0, 65, 0, 0, 23, 0, 0, 240, 71, 34, + 212, 63, 29, 189, 54, 24, 163, 46, 15, 139, 36, 2, 117, 25, 0, + 94, 8, 0, 66, 0, 0, 23, 0, 0, 237, 0, 140, 209, 0, 124, + 186, 0, 112, 162, 0, 97, 141, 0, 82, 118, 0, 67, 95, 0, 49, + 68, 0, 27, 20, 0, 0, 237, 0, 126, 210, 0, 113, 187, 0, 99, + 163, 0, 86, 139, 0, 72, 118, 0, 58, 95, 0, 42, 67, 0, 20, + 20, 0, 0, 237, 1, 114, 209, 1, 102, 187, 0, 90, 163, 0, 78, + 139, 0, 64, 118, 0, 50, 95, 0, 35, 67, 0, 13, 20, 0, 0, + 236, 16, 102, 209, 7, 91, 186, 0, 80, 162, 0, 68, 139, 0, 56, + 117, 0, 43, 94, 0, 27, 67, 0, 6, 20, 0, 0, 238, 15, 89, + 209, 13, 79, 186, 6, 69, 162, 0, 58, 139, 0, 47, 117, 0, 34, + 93, 0, 20, 66, 0, 2, 20, 0, 0, 237, 20, 78, 210, 12, 68, + 187, 4, 59, 163, 0, 49, 139, 0, 38, 116, 0, 26, 94, 0, 11, + 66, 0, 0, 20, 0, 0, 237, 25, 64, 210, 18, 56, 186, 11, 48, + 162, 4, 39, 138, 0, 27, 117, 0, 14, 93, 0, 0, 66, 0, 0, + 20, 0, 0, 238, 25, 48, 210, 22, 43, 186, 15, 35, 162, 8, 26, + 140, 0, 14, 117, 0, 0, 93, 0, 0, 65, 0, 0, 20, 0, 0, + 238, 28, 35, 210, 21, 30, 187, 15, 24, 162, 8, 16, 139, 1, 2, + 117, 0, 0, 93, 0, 0, 65, 0, 0, 22, 0, 0, 219, 242, 252, + 195, 214, 225, 172, 191, 201, 148, 165, 175, 127, 142, 150, 106, 119, 126, + 84, 95, 101, 58, 66, 72, 24, 27, 32, 222, 239, 226, 196, 213, 202, + 173, 189, 180, 150, 165, 158, 129, 141, 135, 107, 118, 113, 85, 94, 90, + 58, 66, 63, 21, 26, 24, 223, 237, 203, 198, 211, 182, 175, 188, 163, + 152, 164, 141, 129, 140, 121, 107, 117, 101, 85, 93, 80, 58, 64, 54, + 21, 26, 18, 226, 236, 179, 201, 210, 160, 177, 187, 143, 153, 162, 125, + 130, 139, 106, 108, 116, 89, 85, 92, 69, 58, 64, 45, 20, 25, 8, + 227, 234, 153, 201, 208, 139, 178, 185, 124, 154, 161, 107, 131, 138, 91, + 108, 115, 75, 85, 91, 58, 58, 63, 35, 17, 25, 0, 229, 233, 130, + 203, 207, 116, 178, 184, 104, 154, 160, 90, 131, 137, 76, 109, 114, 62, + 85, 90, 46, 58, 63, 25, 16, 24, 0, 230, 231, 100, 202, 205, 90, + 179, 183, 80, 154, 159, 69, 131, 136, 57, 109, 113, 46, 86, 90, 32, + 58, 63, 10, 14, 24, 0, 230, 230, 65, 204, 204, 58, 180, 182, 52, + 155, 157, 44, 132, 135, 35, 110, 113, 24, 86, 89, 9, 57, 62, 0, + 11, 24, 0, 232, 230, 19, 204, 204, 19, 180, 181, 17, 155, 157, 10, + 131, 134, 2, 109, 112, 0, 85, 89, 0, 57, 62, 0, 10, 23, 0, + 218, 216, 236, 194, 192, 211, 172, 171, 188, 149, 149, 164, 128, 127, 141, + 106, 106, 119, 84, 84, 94, 59, 57, 66, 25, 18, 26, 221, 214, 211, + 196, 191, 190, 174, 170, 170, 150, 148, 148, 128, 126, 127, 107, 105, 106, + 85, 83, 84, 59, 56, 58, 23, 17, 18, 222, 213, 190, 197, 189, 170, + 175, 169, 153, 151, 147, 133, 129, 126, 113, 108, 105, 94, 85, 82, 74, + 59, 56, 49, 22, 17, 11, 224, 211, 168, 199, 188, 151, 175, 168, 135, + 152, 146, 117, 129, 124, 99, 107, 103, 82, 84, 82, 64, 59, 55, 41, + 21, 17, 1, 224, 210, 145, 199, 187, 130, 176, 166, 117, 152, 145, 101, + 129, 123, 86, 107, 103, 70, 85, 81, 53, 58, 55, 31, 19, 17, 0, + 227, 208, 123, 200, 186, 110, 177, 165, 98, 153, 143, 84, 130, 122, 70, + 108, 102, 57, 85, 80, 41, 58, 54, 20, 18, 16, 0, 227, 208, 97, + 202, 185, 86, 177, 164, 77, 153, 142, 65, 130, 122, 54, 108, 101, 42, + 85, 80, 27, 58, 54, 7, 16, 16, 0, 228, 206, 66, 202, 184, 58, + 178, 163, 50, 154, 141, 42, 131, 121, 33, 109, 101, 21, 86, 79, 5, + 58, 54, 0, 13, 16, 0, 228, 206, 29, 202, 183, 25, 178, 163, 20, + 154, 141, 15, 131, 121, 5, 108, 100, 0, 85, 79, 0, 58, 53, 0, + 13, 16, 0, 217, 193, 221, 193, 172, 198, 172, 153, 178, 149, 133, 154, + 128, 114, 132, 107, 94, 111, 85, 74, 89, 59, 49, 61, 25, 8, 22, + 219, 191, 198, 195, 171, 178, 173, 153, 159, 149, 132, 139, 128, 113, 119, + 107, 94, 100, 85, 73, 79, 59, 48, 52, 25, 7, 14, 221, 191, 180, + 196, 170, 160, 174, 152, 144, 150, 132, 125, 129, 113, 107, 107, 93, 89, + 85, 73, 69, 59, 48, 45, 23, 7, 4, 222, 189, 159, 197, 169, 142, + 174, 151, 127, 151, 131, 110, 129, 112, 94, 108, 93, 78, 85, 72, 60, + 58, 47, 37, 22, 7, 0, 223, 188, 138, 197, 168, 123, 175, 150, 109, + 151, 130, 95, 130, 111, 81, 108, 92, 65, 85, 72, 49, 59, 47, 27, + 21, 7, 0, 224, 187, 118, 198, 167, 105, 176, 149, 93, 152, 129, 79, + 130, 110, 68, 108, 91, 54, 85, 71, 38, 59, 47, 17, 18, 7, 0, + 224, 187, 93, 199, 166, 83, 176, 148, 73, 152, 128, 62, 129, 109, 51, + 108, 90, 39, 85, 71, 25, 58, 46, 3, 16, 8, 0, 226, 186, 64, + 200, 165, 57, 177, 147, 50, 153, 127, 40, 130, 108, 31, 108, 90, 19, + 85, 70, 3, 58, 46, 0, 16, 8, 0, 227, 185, 35, 200, 165, 30, + 176, 146, 25, 152, 127, 18, 130, 108, 7, 108, 89, 0, 85, 70, 0, + 57, 46, 0, 14, 8, 0, 216, 169, 205, 192, 150, 184, 171, 134, 164, + 149, 116, 144, 128, 99, 124, 107, 81, 103, 85, 63, 81, 60, 39, 55, + 26, 0, 15, 217, 168, 186, 193, 150, 165, 172, 134, 149, 150, 116, 130, + 128, 99, 111, 107, 81, 92, 85, 62, 72, 59, 39, 47, 25, 0, 6, + 219, 168, 168, 194, 149, 150, 173, 133, 135, 150, 116, 117, 128, 98, 99, + 107, 80, 82, 86, 62, 63, 59, 38, 39, 24, 0, 0, 219, 166, 148, + 195, 149, 133, 173, 133, 119, 150, 115, 103, 128, 98, 88, 107, 80, 72, + 85, 61, 54, 59, 38, 32, 23, 0, 0, 220, 166, 129, 196, 148, 116, + 174, 132, 103, 151, 114, 89, 129, 97, 75, 107, 79, 60, 85, 61, 44, + 59, 38, 22, 21, 0, 0, 222, 164, 110, 197, 147, 99, 175, 131, 87, + 151, 113, 75, 129, 96, 63, 107, 79, 49, 85, 61, 33, 58, 38, 12, + 19, 0, 0, 222, 164, 88, 197, 146, 79, 174, 130, 69, 151, 113, 58, + 129, 95, 47, 107, 78, 35, 85, 60, 20, 58, 38, 0, 18, 0, 0, + 223, 164, 63, 198, 145, 55, 175, 129, 48, 151, 112, 39, 129, 95, 29, + 107, 78, 16, 85, 60, 1, 58, 38, 0, 17, 0, 0, 223, 163, 36, + 198, 145, 32, 174, 129, 26, 151, 111, 17, 129, 95, 7, 107, 78, 0, + 84, 60, 0, 57, 37, 0, 15, 0, 0, 215, 147, 192, 191, 130, 172, + 170, 116, 153, 148, 100, 133, 127, 85, 115, 107, 69, 96, 85, 51, 75, + 60, 28, 50, 25, 0, 8, 217, 146, 173, 192, 130, 154, 171, 115, 138, + 149, 100, 121, 128, 84, 103, 107, 68, 85, 85, 51, 66, 60, 28, 42, + 25, 0, 0, 217, 145, 157, 193, 129, 140, 173, 115, 125, 149, 100, 109, + 128, 84, 92, 107, 68, 76, 85, 51, 58, 59, 28, 35, 23, 0, 0, + 218, 145, 140, 193, 129, 125, 172, 114, 110, 149, 99, 96, 128, 83, 81, + 107, 67, 65, 84, 51, 49, 59, 29, 27, 22, 0, 0, 219, 144, 121, + 194, 128, 108, 172, 113, 96, 149, 98, 83, 128, 83, 69, 107, 68, 55, + 85, 50, 40, 59, 28, 18, 20, 0, 0, 220, 143, 104, 195, 128, 93, + 173, 114, 82, 150, 98, 69, 127, 82, 58, 107, 67, 45, 85, 50, 30, + 59, 28, 7, 19, 0, 0, 220, 143, 84, 195, 127, 74, 173, 113, 65, + 149, 97, 55, 128, 82, 44, 106, 67, 32, 84, 50, 16, 58, 28, 0, + 18, 0, 0, 221, 142, 62, 196, 126, 53, 173, 112, 46, 150, 97, 37, + 128, 82, 26, 107, 66, 14, 84, 50, 0, 58, 28, 0, 16, 0, 0, + 222, 142, 38, 196, 126, 34, 174, 112, 27, 150, 96, 17, 128, 82, 6, + 106, 66, 0, 84, 50, 0, 57, 29, 0, 16, 0, 0, 214, 123, 179, + 191, 110, 159, 169, 98, 143, 147, 84, 124, 126, 70, 106, 107, 55, 88, + 85, 39, 69, 60, 15, 45, 23, 0, 2, 216, 123, 161, 192, 110, 144, + 170, 98, 129, 148, 84, 112, 127, 70, 95, 107, 55, 79, 85, 39, 61, + 60, 15, 37, 20, 0, 0, 217, 122, 145, 192, 110, 130, 170, 97, 116, + 149, 84, 101, 127, 70, 85, 106, 55, 70, 85, 39, 53, 59, 16, 30, + 19, 0, 0, 217, 123, 131, 192, 109, 116, 171, 96, 103, 149, 83, 89, + 127, 70, 75, 106, 55, 60, 85, 40, 45, 59, 16, 23, 17, 0, 0, + 217, 122, 114, 193, 109, 101, 172, 96, 91, 149, 82, 77, 128, 69, 64, + 106, 55, 50, 84, 39, 35, 59, 17, 14, 17, 0, 0, 218, 122, 98, + 194, 108, 87, 171, 96, 77, 149, 82, 65, 127, 69, 52, 106, 55, 40, + 84, 40, 25, 59, 18, 3, 15, 0, 0, 219, 122, 80, 193, 108, 70, + 172, 95, 61, 149, 82, 51, 127, 69, 40, 106, 55, 28, 84, 39, 12, + 58, 17, 0, 13, 0, 0, 219, 121, 59, 194, 108, 52, 172, 96, 44, + 149, 82, 35, 127, 68, 24, 106, 55, 11, 84, 40, 0, 57, 18, 0, + 13, 0, 0, 219, 121, 40, 193, 108, 33, 172, 95, 26, 149, 81, 19, + 128, 68, 6, 106, 54, 0, 84, 39, 0, 57, 18, 0, 13, 0, 0, + 213, 99, 165, 189, 87, 148, 169, 76, 132, 147, 64, 115, 126, 52, 98, + 106, 39, 81, 85, 23, 63, 60, 0, 39, 16, 0, 0, 214, 98, 149, + 191, 87, 133, 170, 76, 119, 148, 65, 103, 127, 53, 88, 106, 39, 72, + 85, 24, 55, 60, 0, 32, 15, 0, 0, 215, 99, 136, 191, 87, 121, + 170, 77, 108, 148, 65, 93, 126, 53, 79, 106, 40, 64, 85, 24, 47, + 59, 0, 25, 14, 0, 0, 215, 99, 121, 192, 87, 108, 170, 77, 96, + 148, 65, 82, 126, 53, 69, 106, 40, 55, 85, 25, 39, 59, 0, 18, + 13, 0, 0, 216, 99, 106, 191, 87, 95, 170, 76, 83, 148, 65, 71, + 126, 53, 58, 106, 41, 45, 85, 26, 30, 59, 0, 8, 11, 0, 0, + 216, 98, 91, 192, 88, 82, 170, 77, 71, 148, 65, 60, 127, 53, 48, + 105, 41, 36, 83, 26, 21, 58, 1, 2, 11, 0, 0, 217, 99, 75, + 192, 87, 66, 170, 76, 57, 148, 65, 47, 126, 53, 36, 105, 41, 24, + 83, 26, 8, 57, 2, 0, 9, 0, 0, 217, 98, 57, 192, 87, 49, + 171, 77, 41, 147, 65, 32, 126, 53, 21, 105, 41, 8, 84, 27, 0, + 57, 3, 0, 9, 0, 0, 217, 98, 40, 193, 87, 34, 171, 76, 27, + 148, 65, 19, 126, 53, 6, 105, 41, 0, 83, 27, 0, 57, 4, 0, + 9, 0, 0, 211, 67, 152, 189, 58, 136, 168, 50, 122, 147, 39, 105, + 127, 28, 89, 106, 14, 74, 85, 0, 56, 59, 0, 33, 9, 0, 0, + 213, 68, 138, 190, 59, 123, 169, 51, 109, 148, 40, 95, 126, 30, 80, + 106, 16, 65, 85, 0, 48, 59, 0, 27, 9, 0, 0, 214, 69, 125, + 190, 59, 111, 168, 51, 99, 148, 41, 86, 126, 31, 72, 106, 18, 58, + 85, 0, 41, 59, 0, 20, 7, 0, 0, 215, 70, 112, 190, 61, 100, + 169, 52, 88, 147, 42, 76, 126, 32, 63, 106, 19, 49, 84, 1, 34, + 58, 0, 13, 7, 0, 0, 214, 70, 99, 190, 62, 88, 169, 53, 77, + 147, 43, 65, 125, 32, 53, 106, 20, 40, 84, 3, 26, 58, 0, 4, + 7, 0, 0, 214, 71, 86, 190, 61, 75, 169, 53, 65, 146, 43, 54, + 126, 33, 44, 105, 21, 31, 83, 4, 17, 57, 0, 0, 7, 0, 0, + 215, 71, 71, 191, 62, 62, 169, 53, 53, 147, 44, 44, 126, 34, 33, + 105, 22, 20, 83, 5, 4, 57, 0, 0, 7, 0, 0, 215, 71, 54, + 191, 62, 47, 169, 54, 39, 147, 44, 30, 126, 35, 20, 105, 23, 6, + 83, 6, 0, 56, 0, 0, 5, 0, 0, 215, 71, 41, 191, 63, 34, + 170, 54, 27, 147, 45, 17, 126, 35, 6, 105, 23, 0, 83, 8, 0, + 56, 0, 0, 5, 0, 0, 210, 13, 140, 189, 1, 125, 167, 0, 110, + 146, 0, 96, 126, 0, 81, 106, 0, 67, 85, 0, 51, 59, 0, 28, + 4, 0, 0, 212, 18, 126, 190, 7, 113, 168, 0, 100, 146, 0, 86, + 126, 0, 73, 106, 0, 59, 84, 0, 43, 59, 0, 22, 4, 0, 0, + 212, 21, 115, 190, 13, 103, 168, 3, 91, 146, 0, 78, 125, 0, 65, + 105, 0, 52, 84, 0, 36, 58, 0, 16, 4, 0, 0, 213, 24, 103, + 189, 19, 91, 168, 9, 82, 146, 0, 69, 125, 0, 57, 105, 0, 44, + 84, 0, 29, 58, 0, 7, 4, 0, 0, 213, 27, 92, 188, 21, 81, + 168, 14, 71, 146, 1, 59, 125, 0, 48, 105, 0, 36, 84, 0, 21, + 58, 0, 4, 4, 0, 0, 213, 30, 80, 189, 22, 69, 168, 17, 61, + 146, 5, 50, 125, 0, 39, 104, 0, 27, 83, 0, 12, 57, 0, 0, + 4, 0, 0, 214, 30, 67, 189, 25, 57, 168, 20, 50, 146, 9, 40, + 125, 0, 29, 104, 0, 17, 83, 0, 2, 56, 0, 0, 4, 0, 0, + 214, 32, 53, 189, 27, 44, 169, 20, 38, 146, 13, 28, 124, 2, 17, + 104, 0, 4, 83, 0, 0, 56, 0, 0, 4, 0, 0, 214, 33, 41, + 190, 27, 33, 168, 23, 27, 146, 13, 18, 125, 3, 5, 105, 0, 0, + 83, 0, 0, 56, 0, 0, 4, 0, 0, 185, 229, 250, 164, 204, 223, + 146, 182, 199, 127, 158, 174, 108, 136, 149, 89, 113, 125, 70, 90, 100, + 46, 62, 71, 10, 25, 33, 189, 227, 225, 168, 202, 201, 148, 181, 179, + 129, 157, 156, 109, 135, 134, 90, 113, 113, 70, 89, 90, 46, 62, 62, + 8, 24, 25, 192, 226, 202, 170, 202, 182, 151, 179, 162, 130, 156, 141, + 110, 133, 121, 91, 112, 101, 71, 89, 80, 46, 61, 54, 7, 24, 19, + 194, 224, 179, 173, 200, 160, 153, 178, 144, 132, 155, 125, 112, 133, 107, + 92, 111, 89, 71, 88, 69, 46, 61, 45, 6, 23, 10, 196, 223, 155, + 174, 198, 139, 154, 176, 124, 132, 153, 107, 113, 131, 91, 92, 110, 75, + 72, 87, 58, 47, 60, 37, 4, 23, 0, 198, 221, 131, 175, 197, 117, + 155, 175, 105, 133, 152, 91, 113, 130, 76, 92, 109, 63, 72, 86, 47, + 46, 60, 26, 3, 23, 0, 200, 220, 104, 176, 196, 94, 156, 175, 84, + 134, 151, 72, 113, 129, 59, 93, 108, 47, 72, 85, 33, 46, 59, 13, + 0, 23, 0, 201, 219, 73, 179, 195, 65, 157, 173, 57, 135, 150, 48, + 114, 129, 39, 94, 108, 28, 72, 85, 15, 47, 59, 0, 0, 22, 0, + 203, 219, 42, 178, 195, 37, 157, 173, 32, 135, 150, 26, 114, 128, 16, + 94, 107, 6, 73, 85, 0, 46, 58, 0, 0, 22, 0, 186, 205, 233, + 165, 183, 209, 148, 163, 187, 128, 142, 163, 109, 121, 140, 91, 101, 118, + 71, 80, 94, 48, 54, 66, 12, 15, 27, 189, 204, 211, 169, 182, 189, + 151, 163, 169, 131, 141, 147, 111, 121, 126, 92, 101, 105, 72, 79, 84, + 48, 54, 58, 11, 15, 19, 192, 202, 190, 171, 181, 170, 152, 161, 152, + 131, 141, 133, 112, 120, 113, 93, 100, 94, 72, 79, 74, 48, 53, 50, + 10, 15, 11, 195, 201, 169, 172, 179, 151, 153, 160, 135, 132, 139, 117, + 113, 119, 100, 93, 99, 82, 72, 78, 64, 48, 53, 41, 9, 14, 3, + 195, 200, 146, 174, 179, 131, 154, 159, 117, 133, 138, 101, 113, 118, 86, + 93, 98, 70, 73, 77, 53, 48, 52, 32, 8, 15, 0, 198, 199, 125, + 175, 177, 111, 155, 158, 100, 133, 137, 85, 113, 117, 71, 93, 97, 57, + 72, 77, 42, 47, 52, 22, 5, 14, 0, 199, 198, 101, 176, 177, 89, + 155, 157, 79, 134, 136, 68, 113, 116, 56, 94, 97, 44, 73, 76, 30, + 47, 52, 10, 2, 15, 0, 200, 197, 72, 178, 176, 63, 157, 156, 56, + 135, 136, 46, 114, 116, 37, 94, 96, 26, 73, 76, 11, 47, 51, 0, + 0, 14, 0, 201, 197, 45, 177, 175, 38, 156, 155, 31, 135, 135, 25, + 114, 115, 17, 94, 96, 5, 73, 75, 0, 46, 51, 0, 0, 14, 0, + 187, 183, 218, 167, 165, 197, 149, 147, 176, 129, 127, 153, 111, 109, 132, + 92, 90, 111, 73, 70, 89, 49, 46, 62, 15, 4, 22, 190, 183, 197, + 170, 164, 177, 151, 146, 159, 130, 127, 139, 112, 109, 119, 93, 90, 99, + 72, 70, 78, 49, 45, 53, 14, 4, 15, 192, 182, 179, 171, 163, 161, + 153, 145, 144, 132, 126, 125, 113, 108, 107, 93, 89, 88, 73, 70, 69, + 49, 45, 45, 13, 5, 6, 195, 181, 159, 172, 162, 142, 152, 145, 127, + 132, 125, 111, 113, 107, 94, 93, 88, 77, 73, 69, 59, 48, 45, 37, + 11, 5, 0, 195, 180, 139, 173, 161, 124, 153, 143, 110, 133, 125, 96, + 113, 106, 81, 94, 88, 66, 73, 68, 49, 49, 44, 28, 9, 6, 0, + 196, 179, 118, 174, 160, 106, 154, 142, 94, 133, 124, 81, 113, 105, 68, + 94, 87, 54, 73, 68, 39, 48, 44, 18, 5, 5, 0, 197, 178, 96, + 176, 159, 86, 155, 141, 75, 134, 123, 64, 114, 105, 53, 94, 87, 40, + 73, 68, 26, 48, 44, 5, 2, 6, 0, 199, 178, 70, 176, 158, 62, + 156, 141, 54, 134, 122, 44, 114, 104, 35, 94, 86, 23, 73, 67, 8, + 47, 44, 0, 2, 6, 0, 199, 177, 45, 178, 158, 40, 156, 140, 32, + 135, 122, 26, 114, 104, 16, 94, 86, 4, 73, 67, 0, 47, 44, 0, + 0, 7, 0, 188, 161, 204, 168, 144, 183, 149, 129, 164, 130, 112, 144, + 112, 95, 123, 93, 78, 103, 74, 60, 81, 50, 36, 56, 16, 0, 16, + 190, 160, 185, 170, 144, 165, 151, 128, 148, 132, 111, 130, 112, 95, 110, + 93, 78, 92, 74, 59, 72, 50, 36, 48, 16, 0, 8, 192, 160, 167, + 171, 143, 150, 153, 128, 134, 132, 111, 117, 112, 94, 100, 94, 77, 82, + 74, 59, 63, 50, 36, 40, 14, 0, 0, 193, 159, 149, 172, 143, 134, + 153, 127, 119, 133, 110, 103, 113, 94, 87, 93, 77, 72, 73, 59, 54, + 50, 36, 32, 12, 0, 0, 195, 159, 131, 173, 142, 117, 153, 127, 104, + 132, 110, 90, 113, 93, 76, 93, 76, 61, 74, 59, 45, 49, 36, 23, + 9, 0, 0, 196, 158, 113, 174, 141, 101, 155, 126, 89, 133, 109, 76, + 113, 93, 64, 94, 76, 51, 74, 58, 35, 49, 36, 14, 6, 0, 0, + 197, 157, 92, 174, 141, 80, 154, 125, 71, 134, 108, 60, 114, 92, 50, + 94, 75, 37, 73, 58, 22, 48, 36, 1, 5, 0, 0, 197, 157, 68, + 175, 140, 59, 155, 124, 51, 134, 108, 41, 113, 91, 32, 94, 75, 21, + 73, 57, 5, 48, 35, 0, 5, 0, 0, 198, 156, 46, 176, 140, 40, + 155, 124, 32, 134, 107, 24, 114, 91, 14, 94, 75, 2, 73, 57, 0, + 48, 36, 0, 3, 0, 0, 189, 140, 191, 168, 126, 172, 150, 112, 154, + 131, 97, 134, 112, 82, 115, 94, 66, 96, 74, 49, 75, 51, 25, 50, + 12, 0, 10, 191, 139, 173, 170, 125, 154, 152, 111, 138, 132, 96, 121, + 113, 81, 103, 94, 66, 85, 74, 48, 66, 50, 26, 42, 12, 0, 1, + 192, 139, 157, 171, 125, 140, 152, 111, 125, 132, 96, 109, 113, 81, 92, + 94, 65, 76, 74, 48, 58, 50, 26, 35, 9, 0, 0, 193, 139, 140, + 172, 124, 125, 153, 110, 112, 133, 95, 96, 113, 80, 82, 94, 65, 66, + 74, 49, 50, 50, 26, 28, 7, 0, 0, 194, 138, 123, 172, 123, 109, + 153, 110, 97, 133, 95, 84, 113, 80, 70, 94, 65, 56, 74, 48, 40, + 50, 26, 20, 6, 0, 0, 194, 138, 105, 173, 123, 94, 153, 109, 83, + 133, 94, 70, 112, 79, 59, 94, 64, 46, 74, 48, 31, 50, 26, 9, + 4, 0, 0, 196, 138, 87, 174, 122, 77, 153, 109, 67, 133, 93, 56, + 113, 79, 46, 94, 64, 34, 73, 48, 18, 49, 27, 0, 4, 0, 0, + 196, 137, 65, 174, 122, 57, 154, 108, 49, 133, 93, 39, 113, 79, 29, + 94, 64, 18, 74, 48, 3, 49, 27, 0, 2, 0, 0, 197, 137, 47, + 175, 122, 40, 155, 108, 32, 133, 93, 23, 114, 79, 14, 94, 64, 1, + 73, 48, 0, 48, 27, 0, 2, 0, 0, 189, 119, 177, 168, 106, 159, + 150, 94, 142, 131, 81, 124, 113, 67, 107, 94, 53, 89, 74, 37, 69, + 51, 11, 45, 6, 0, 3, 191, 119, 161, 170, 106, 144, 152, 94, 129, + 132, 81, 112, 113, 67, 96, 94, 53, 79, 74, 37, 61, 51, 13, 38, + 6, 0, 0, 192, 119, 146, 170, 106, 131, 152, 94, 117, 132, 80, 101, + 112, 67, 85, 94, 53, 70, 74, 37, 53, 50, 14, 31, 4, 0, 0, + 192, 119, 131, 171, 106, 117, 153, 94, 105, 132, 80, 89, 113, 67, 75, + 94, 54, 61, 74, 38, 45, 51, 14, 23, 3, 0, 0, 193, 118, 114, + 171, 106, 102, 153, 93, 90, 132, 80, 78, 113, 67, 65, 94, 53, 52, + 74, 37, 36, 50, 15, 16, 1, 0, 0, 194, 118, 99, 172, 105, 89, + 153, 93, 78, 132, 80, 66, 113, 67, 54, 94, 53, 42, 74, 38, 27, + 50, 16, 5, 1, 0, 0, 194, 118, 82, 173, 105, 72, 153, 93, 63, + 132, 79, 53, 113, 67, 42, 94, 53, 30, 74, 38, 15, 49, 16, 0, + 0, 0, 0, 195, 117, 63, 173, 105, 55, 154, 93, 47, 133, 79, 37, + 113, 66, 27, 94, 53, 15, 73, 38, 0, 48, 16, 0, 0, 0, 0, + 195, 117, 46, 173, 104, 39, 154, 92, 32, 133, 79, 22, 113, 66, 13, + 94, 53, 0, 73, 38, 0, 48, 17, 0, 0, 0, 0, 189, 96, 166, + 168, 85, 147, 150, 74, 132, 131, 62, 115, 113, 51, 99, 94, 38, 82, + 74, 21, 63, 51, 0, 40, 1, 0, 0, 190, 96, 150, 170, 85, 133, + 152, 75, 119, 132, 63, 104, 113, 51, 88, 94, 38, 72, 75, 22, 55, + 51, 0, 33, 1, 0, 0, 192, 96, 137, 170, 85, 121, 152, 74, 108, + 132, 64, 94, 113, 52, 79, 94, 39, 64, 74, 23, 48, 50, 0, 26, + 0, 0, 0, 192, 96, 122, 171, 86, 109, 152, 75, 96, 132, 63, 83, + 113, 52, 69, 94, 39, 56, 74, 24, 41, 50, 0, 19, 0, 0, 0, + 193, 96, 107, 171, 85, 96, 152, 75, 84, 132, 64, 72, 113, 52, 60, + 94, 39, 47, 74, 24, 32, 50, 1, 10, 0, 0, 0, 193, 96, 93, + 172, 85, 82, 152, 75, 72, 133, 63, 61, 113, 51, 49, 94, 39, 37, + 73, 25, 23, 49, 2, 2, 0, 0, 0, 194, 96, 78, 172, 85, 68, + 152, 75, 59, 132, 63, 49, 113, 52, 39, 94, 40, 26, 73, 25, 11, + 48, 3, 0, 0, 0, 0, 194, 96, 60, 173, 85, 52, 153, 75, 44, + 132, 64, 35, 112, 52, 25, 94, 40, 12, 73, 26, 0, 48, 4, 0, + 0, 0, 0, 195, 96, 46, 173, 85, 38, 154, 74, 31, 133, 63, 22, + 113, 52, 11, 93, 40, 0, 73, 26, 0, 47, 5, 0, 0, 0, 0, + 188, 67, 153, 168, 58, 137, 151, 49, 122, 131, 39, 106, 113, 28, 90, + 94, 13, 75, 75, 0, 57, 51, 0, 35, 0, 0, 0, 190, 68, 138, + 170, 59, 123, 152, 50, 110, 132, 41, 96, 113, 29, 80, 94, 16, 66, + 75, 0, 49, 50, 0, 27, 0, 0, 0, 191, 69, 126, 170, 59, 112, + 151, 52, 100, 132, 42, 86, 113, 30, 73, 95, 17, 58, 75, 0, 42, + 50, 0, 21, 0, 0, 0, 192, 70, 113, 170, 61, 100, 151, 52, 89, + 132, 42, 77, 113, 31, 64, 94, 19, 50, 74, 1, 35, 50, 0, 14, + 0, 0, 0, 192, 70, 100, 170, 62, 89, 151, 53, 77, 131, 43, 66, + 112, 32, 54, 94, 20, 42, 74, 2, 27, 49, 0, 5, 0, 0, 0, + 192, 71, 87, 171, 61, 77, 152, 53, 67, 131, 44, 57, 112, 33, 45, + 94, 21, 33, 74, 4, 19, 49, 0, 1, 0, 0, 0, 193, 71, 74, + 171, 62, 64, 152, 53, 55, 132, 44, 45, 113, 34, 34, 94, 22, 23, + 73, 5, 7, 48, 0, 0, 0, 0, 0, 193, 70, 58, 172, 62, 50, + 152, 54, 42, 132, 44, 32, 112, 35, 22, 93, 23, 10, 73, 6, 0, + 47, 0, 0, 0, 0, 0, 193, 70, 45, 172, 62, 38, 153, 54, 31, + 132, 44, 21, 112, 35, 9, 94, 23, 0, 73, 7, 0, 47, 0, 0, + 0, 0, 0, 189, 26, 141, 169, 15, 126, 150, 2, 112, 131, 0, 97, + 113, 0, 82, 94, 0, 67, 75, 0, 51, 50, 0, 29, 0, 0, 0, + 190, 28, 128, 170, 18, 114, 151, 8, 101, 132, 0, 88, 113, 0, 74, + 94, 0, 60, 75, 0, 44, 50, 0, 23, 0, 0, 0, 191, 30, 117, + 170, 23, 104, 152, 11, 92, 132, 1, 79, 113, 0, 67, 95, 0, 53, + 75, 0, 37, 50, 0, 17, 0, 0, 0, 191, 33, 105, 170, 26, 93, + 151, 18, 83, 132, 6, 70, 112, 0, 58, 94, 0, 45, 75, 0, 30, + 49, 0, 8, 0, 0, 0, 191, 34, 93, 170, 27, 82, 151, 20, 72, + 131, 8, 61, 112, 0, 49, 94, 0, 38, 74, 0, 23, 49, 0, 4, + 0, 0, 0, 191, 36, 82, 170, 29, 71, 151, 22, 63, 131, 11, 52, + 112, 0, 41, 93, 0, 29, 74, 0, 14, 48, 0, 1, 0, 0, 0, + 191, 38, 69, 170, 31, 60, 151, 24, 51, 131, 14, 41, 112, 1, 31, + 93, 0, 19, 73, 0, 3, 48, 0, 0, 0, 0, 0, 192, 37, 56, + 171, 31, 47, 152, 25, 40, 131, 17, 30, 112, 4, 19, 93, 0, 7, + 73, 0, 0, 47, 0, 0, 0, 0, 0, 192, 38, 45, 171, 33, 36, + 152, 26, 30, 131, 18, 21, 111, 7, 9, 93, 0, 0, 73, 0, 0, + 47, 0, 0, 0, 0, 0, 149, 218, 248, 133, 194, 222, 119, 173, 198, + 102, 151, 173, 86, 130, 148, 70, 108, 125, 53, 85, 100, 32, 59, 71, + 0, 22, 33, 154, 216, 223, 137, 193, 200, 122, 172, 178, 106, 150, 156, + 89, 128, 133, 73, 107, 112, 54, 85, 89, 31, 59, 63, 0, 22, 26, + 159, 215, 202, 141, 192, 181, 126, 171, 161, 108, 149, 141, 90, 128, 121, + 74, 107, 100, 55, 85, 80, 32, 58, 55, 0, 22, 19, 161, 213, 179, + 144, 190, 160, 126, 170, 143, 109, 148, 125, 92, 127, 107, 74, 106, 89, + 56, 84, 69, 32, 58, 46, 0, 21, 11, 163, 211, 156, 144, 189, 139, + 129, 168, 125, 110, 147, 108, 93, 126, 92, 75, 105, 76, 57, 83, 58, + 33, 58, 37, 0, 21, 1, 167, 211, 133, 147, 188, 120, 130, 167, 105, + 110, 145, 92, 93, 125, 78, 76, 104, 64, 58, 83, 48, 33, 57, 27, + 0, 21, 0, 169, 210, 108, 149, 187, 96, 131, 166, 86, 112, 144, 74, + 94, 124, 62, 77, 103, 49, 58, 82, 35, 33, 57, 15, 0, 21, 0, + 170, 209, 80, 151, 186, 71, 133, 165, 62, 114, 143, 52, 95, 123, 42, + 77, 103, 32, 58, 81, 18, 33, 56, 0, 0, 21, 0, 173, 208, 55, + 152, 186, 49, 134, 165, 41, 114, 143, 34, 95, 122, 25, 77, 102, 14, + 58, 81, 0, 33, 56, 0, 0, 21, 0, 154, 195, 232, 137, 174, 207, + 122, 156, 185, 105, 136, 163, 89, 116, 140, 73, 97, 117, 56, 76, 94, + 35, 51, 66, 0, 13, 28, 158, 194, 209, 141, 174, 187, 125, 155, 167, + 109, 135, 146, 91, 116, 125, 75, 96, 105, 57, 75, 83, 35, 50, 57, + 0, 12, 21, 161, 193, 189, 144, 173, 169, 128, 154, 151, 110, 134, 132, + 93, 115, 113, 77, 95, 94, 58, 75, 74, 35, 50, 50, 0, 12, 13, + 164, 192, 168, 145, 171, 151, 129, 153, 134, 111, 133, 117, 94, 114, 100, + 76, 95, 82, 58, 75, 64, 36, 50, 42, 0, 12, 5, 165, 191, 147, + 147, 170, 131, 130, 152, 117, 113, 132, 102, 95, 113, 86, 77, 94, 71, + 58, 74, 54, 35, 50, 33, 0, 13, 0, 167, 189, 126, 148, 169, 113, + 132, 151, 100, 113, 131, 86, 96, 112, 73, 77, 93, 59, 59, 73, 43, + 35, 49, 23, 0, 12, 0, 170, 189, 104, 150, 168, 91, 133, 150, 81, + 114, 130, 69, 96, 111, 57, 78, 92, 46, 59, 73, 31, 35, 49, 11, + 0, 13, 0, 171, 188, 78, 152, 168, 68, 134, 149, 60, 115, 130, 50, + 96, 111, 41, 78, 92, 29, 60, 73, 15, 35, 49, 0, 0, 12, 0, + 173, 187, 55, 153, 167, 47, 134, 149, 39, 115, 129, 33, 97, 110, 24, + 79, 92, 13, 60, 72, 0, 35, 48, 0, 0, 12, 0, 157, 175, 217, + 139, 157, 196, 125, 141, 175, 109, 122, 153, 92, 104, 132, 76, 86, 110, + 59, 67, 88, 37, 43, 61, 1, 1, 23, 161, 174, 196, 144, 156, 176, + 127, 140, 158, 110, 121, 137, 94, 104, 118, 77, 85, 98, 59, 67, 78, + 37, 43, 53, 0, 2, 16, 163, 174, 178, 146, 156, 160, 130, 139, 143, + 112, 121, 124, 95, 103, 106, 78, 85, 88, 60, 66, 69, 37, 42, 46, + 0, 2, 7, 166, 173, 159, 147, 154, 142, 130, 138, 127, 113, 120, 111, + 96, 103, 95, 78, 84, 77, 60, 66, 59, 37, 43, 37, 0, 2, 0, + 166, 172, 139, 148, 154, 125, 131, 137, 112, 113, 120, 96, 96, 102, 81, + 78, 84, 66, 60, 65, 50, 37, 42, 29, 0, 3, 0, 167, 171, 120, + 149, 153, 107, 133, 137, 95, 114, 118, 81, 97, 101, 69, 79, 84, 56, + 60, 65, 40, 37, 42, 19, 0, 3, 0, 170, 170, 99, 151, 152, 87, + 134, 136, 77, 115, 118, 66, 97, 101, 55, 79, 83, 42, 61, 65, 28, + 37, 42, 7, 0, 3, 0, 172, 170, 75, 152, 151, 65, 134, 135, 57, + 115, 117, 48, 97, 100, 38, 79, 83, 27, 61, 64, 12, 36, 42, 0, + 0, 3, 0, 172, 169, 55, 154, 151, 46, 135, 134, 40, 116, 116, 32, + 97, 99, 21, 80, 82, 10, 61, 64, 0, 36, 41, 0, 0, 3, 0, + 160, 154, 203, 143, 139, 182, 127, 124, 164, 111, 107, 143, 95, 91, 122, + 78, 75, 103, 60, 57, 81, 39, 33, 56, 1, 0, 18, 163, 154, 184, + 146, 138, 165, 130, 123, 148, 113, 107, 129, 96, 90, 110, 79, 74, 92, + 61, 56, 72, 39, 34, 48, 2, 0, 9, 165, 154, 167, 147, 137, 149, + 131, 122, 134, 114, 106, 117, 96, 90, 100, 79, 74, 82, 61, 56, 64, + 39, 33, 40, 2, 0, 1, 166, 153, 150, 149, 137, 133, 132, 122, 119, + 114, 106, 104, 97, 90, 88, 79, 74, 72, 61, 56, 55, 39, 34, 33, + 0, 0, 0, 168, 152, 132, 149, 136, 117, 132, 121, 104, 114, 105, 90, + 97, 89, 76, 79, 73, 62, 61, 56, 46, 38, 34, 25, 0, 0, 0, + 169, 151, 114, 150, 135, 101, 133, 121, 90, 114, 104, 77, 97, 89, 65, + 80, 73, 51, 61, 56, 36, 38, 34, 16, 0, 0, 0, 170, 150, 94, + 151, 135, 83, 134, 120, 73, 115, 104, 62, 98, 88, 51, 80, 72, 39, + 61, 56, 24, 38, 34, 3, 0, 0, 0, 172, 150, 72, 153, 134, 63, + 135, 119, 55, 115, 103, 45, 98, 88, 36, 80, 72, 24, 61, 55, 9, + 38, 34, 0, 0, 0, 0, 172, 150, 54, 153, 134, 47, 135, 119, 38, + 116, 103, 30, 98, 87, 21, 80, 72, 8, 62, 55, 0, 37, 34, 0, + 0, 0, 0, 162, 134, 190, 145, 120, 171, 129, 108, 153, 113, 93, 134, + 97, 78, 115, 80, 63, 96, 62, 46, 75, 41, 23, 51, 0, 0, 11, + 165, 134, 173, 147, 120, 154, 131, 107, 138, 114, 92, 120, 97, 78, 103, + 80, 63, 85, 62, 46, 66, 40, 23, 43, 0, 0, 2, 166, 134, 157, + 148, 120, 140, 132, 106, 125, 114, 92, 109, 97, 77, 93, 81, 63, 77, + 62, 46, 58, 40, 24, 36, 0, 0, 0, 168, 133, 140, 149, 119, 125, + 132, 106, 112, 115, 92, 97, 98, 77, 82, 81, 62, 67, 62, 46, 50, + 40, 24, 29, 0, 0, 0, 168, 133, 123, 150, 119, 110, 133, 106, 97, + 115, 91, 84, 98, 77, 70, 81, 62, 57, 62, 46, 41, 40, 24, 20, + 0, 0, 0, 169, 132, 107, 150, 118, 94, 133, 105, 84, 115, 91, 72, + 98, 76, 60, 80, 62, 47, 62, 46, 32, 39, 25, 11, 0, 0, 0, + 171, 132, 89, 152, 118, 79, 135, 105, 69, 115, 90, 58, 98, 76, 47, + 80, 62, 36, 62, 46, 21, 39, 25, 0, 0, 0, 0, 171, 132, 69, + 153, 117, 60, 135, 104, 52, 116, 90, 42, 98, 76, 33, 81, 61, 21, + 62, 46, 6, 38, 25, 0, 0, 0, 0, 172, 132, 54, 153, 118, 45, + 135, 104, 38, 116, 90, 28, 98, 76, 18, 81, 61, 6, 62, 46, 0, + 38, 25, 0, 0, 0, 0, 164, 115, 177, 146, 103, 159, 130, 91, 143, + 114, 78, 125, 97, 65, 107, 81, 51, 89, 63, 34, 69, 41, 9, 46, + 0, 0, 4, 166, 115, 161, 148, 103, 144, 132, 91, 129, 115, 78, 112, + 98, 65, 96, 81, 51, 79, 63, 35, 61, 41, 11, 38, 0, 0, 0, + 167, 115, 146, 150, 102, 131, 132, 91, 117, 115, 78, 101, 98, 65, 86, + 81, 51, 71, 63, 35, 54, 41, 12, 32, 0, 0, 0, 168, 114, 132, + 150, 103, 118, 133, 91, 105, 116, 78, 91, 98, 64, 76, 82, 51, 61, + 63, 36, 46, 41, 13, 24, 0, 0, 0, 169, 114, 116, 150, 102, 103, + 134, 90, 91, 116, 78, 79, 98, 65, 66, 81, 51, 53, 63, 36, 37, + 40, 14, 17, 0, 0, 0, 169, 114, 101, 151, 101, 89, 134, 90, 79, + 116, 77, 67, 98, 64, 56, 81, 51, 44, 63, 36, 29, 40, 15, 7, + 0, 0, 0, 170, 114, 85, 152, 101, 75, 135, 90, 65, 116, 77, 54, + 98, 64, 44, 81, 51, 32, 63, 36, 17, 39, 15, 0, 0, 0, 0, + 172, 113, 66, 152, 101, 58, 135, 89, 49, 116, 77, 40, 99, 64, 30, + 81, 51, 18, 62, 36, 3, 38, 16, 0, 0, 0, 0, 171, 113, 51, + 153, 101, 44, 136, 89, 36, 116, 77, 28, 99, 64, 18, 81, 51, 5, + 62, 36, 0, 38, 16, 0, 0, 0, 0, 165, 94, 166, 147, 82, 147, + 132, 72, 132, 115, 61, 115, 98, 49, 99, 82, 36, 82, 64, 19, 64, + 42, 0, 41, 0, 0, 0, 167, 93, 150, 150, 83, 134, 133, 73, 120, + 116, 62, 104, 99, 49, 88, 82, 36, 72, 64, 20, 55, 41, 0, 33, + 0, 0, 0, 169, 93, 137, 150, 83, 122, 134, 73, 109, 116, 61, 94, + 99, 50, 80, 82, 37, 65, 64, 21, 49, 41, 0, 27, 0, 0, 0, + 169, 94, 123, 150, 83, 110, 133, 73, 97, 116, 61, 83, 99, 50, 70, + 82, 38, 57, 63, 23, 42, 41, 0, 20, 0, 0, 0, 169, 94, 109, + 150, 84, 97, 134, 73, 85, 116, 62, 73, 99, 51, 61, 81, 38, 48, + 63, 23, 33, 41, 1, 11, 0, 0, 0, 170, 94, 96, 150, 83, 84, + 134, 73, 74, 116, 61, 62, 99, 50, 51, 82, 38, 39, 64, 23, 24, + 40, 3, 4, 0, 0, 0, 171, 93, 79, 152, 82, 70, 135, 73, 61, + 116, 62, 51, 98, 51, 40, 81, 38, 28, 63, 24, 14, 39, 4, 0, + 0, 0, 0, 171, 94, 64, 152, 83, 55, 135, 73, 47, 116, 62, 37, + 98, 50, 27, 81, 38, 15, 63, 24, 1, 39, 4, 0, 0, 0, 0, + 172, 93, 51, 153, 82, 42, 135, 73, 35, 117, 62, 26, 99, 51, 16, + 81, 39, 3, 63, 25, 0, 38, 5, 0, 0, 0, 0, 166, 68, 153, + 148, 59, 137, 133, 49, 121, 115, 39, 106, 99, 28, 91, 82, 13, 75, + 65, 0, 58, 42, 0, 36, 0, 0, 0, 168, 68, 139, 150, 59, 124, + 134, 50, 110, 116, 40, 96, 99, 30, 81, 82, 16, 66, 64, 0, 50, + 41, 0, 29, 0, 0, 0, 169, 69, 126, 150, 59, 113, 134, 51, 101, + 117, 42, 87, 100, 30, 73, 82, 17, 59, 65, 0, 43, 41, 0, 23, + 0, 0, 0, 169, 70, 115, 150, 61, 102, 134, 52, 89, 116, 42, 77, + 99, 32, 65, 82, 19, 52, 64, 0, 36, 41, 0, 15, 0, 0, 0, + 169, 70, 101, 150, 61, 90, 134, 52, 79, 116, 43, 68, 99, 32, 55, + 82, 21, 43, 64, 2, 28, 41, 0, 6, 0, 0, 0, 170, 70, 89, + 151, 62, 79, 134, 53, 69, 116, 44, 58, 99, 33, 46, 81, 21, 34, + 64, 3, 20, 41, 0, 2, 0, 0, 0, 170, 71, 76, 152, 62, 66, + 134, 53, 57, 116, 43, 46, 99, 33, 36, 82, 22, 24, 64, 5, 10, + 40, 0, 0, 0, 0, 0, 171, 70, 61, 152, 62, 52, 135, 53, 44, + 116, 44, 35, 99, 34, 24, 82, 22, 12, 63, 6, 0, 39, 0, 0, + 0, 0, 0, 171, 71, 49, 153, 62, 41, 135, 54, 33, 117, 45, 25, + 98, 34, 13, 81, 23, 0, 63, 7, 0, 39, 0, 0, 0, 0, 0, + 167, 33, 142, 149, 24, 127, 134, 10, 113, 116, 0, 97, 100, 0, 83, + 83, 0, 68, 65, 0, 52, 40, 0, 30, 0, 0, 0, 169, 33, 129, + 150, 26, 115, 134, 17, 102, 116, 3, 89, 100, 0, 75, 83, 0, 60, + 65, 0, 45, 40, 0, 24, 0, 0, 0, 169, 36, 118, 151, 27, 104, + 134, 19, 93, 116, 7, 80, 100, 0, 67, 83, 0, 54, 65, 0, 38, + 41, 0, 17, 0, 0, 0, 169, 39, 107, 150, 30, 94, 134, 22, 84, + 116, 11, 71, 99, 0, 59, 83, 0, 46, 64, 0, 31, 40, 0, 9, + 0, 0, 0, 169, 39, 95, 151, 31, 83, 134, 24, 73, 116, 15, 62, + 100, 1, 51, 83, 0, 38, 64, 0, 24, 40, 0, 5, 0, 0, 0, + 169, 41, 83, 151, 33, 73, 134, 26, 64, 117, 17, 54, 99, 4, 42, + 82, 0, 30, 64, 0, 16, 40, 0, 1, 0, 0, 0, 170, 42, 71, + 152, 34, 62, 134, 28, 53, 117, 19, 44, 99, 6, 33, 82, 0, 21, + 63, 0, 4, 39, 0, 0, 0, 0, 0, 171, 42, 59, 152, 35, 50, + 134, 29, 42, 117, 21, 32, 99, 9, 22, 82, 0, 9, 63, 0, 0, + 38, 0, 0, 0, 0, 0, 172, 42, 48, 152, 36, 40, 135, 29, 32, + 117, 21, 23, 99, 10, 12, 82, 0, 0, 63, 0, 0, 38, 0, 0, + 0, 0, 0, 107, 207, 246, 96, 185, 220, 86, 165, 196, 73, 144, 171, + 60, 123, 147, 46, 103, 125, 32, 82, 100, 9, 56, 71, 0, 20, 33, + 115, 206, 221, 104, 184, 198, 92, 164, 178, 78, 143, 154, 64, 123, 133, + 51, 102, 111, 34, 81, 89, 10, 56, 63, 0, 20, 27, 122, 204, 200, + 108, 183, 180, 95, 163, 161, 82, 142, 140, 68, 122, 120, 54, 102, 101, + 36, 81, 79, 11, 56, 55, 0, 20, 20, 125, 203, 179, 111, 181, 160, + 97, 162, 143, 85, 141, 124, 70, 121, 107, 55, 101, 89, 38, 80, 69, + 14, 55, 46, 0, 19, 10, 128, 202, 156, 113, 180, 140, 102, 161, 125, + 87, 140, 108, 71, 120, 92, 56, 100, 76, 39, 79, 59, 14, 55, 38, + 0, 20, 3, 132, 200, 135, 117, 179, 121, 103, 159, 106, 88, 139, 93, + 73, 119, 79, 57, 100, 65, 41, 79, 49, 15, 54, 28, 0, 19, 0, + 134, 200, 111, 119, 178, 98, 105, 158, 87, 89, 138, 76, 74, 118, 64, + 58, 99, 51, 41, 78, 37, 16, 54, 17, 0, 19, 0, 137, 199, 85, + 122, 177, 75, 108, 158, 66, 91, 137, 56, 75, 118, 46, 59, 98, 35, + 42, 78, 22, 16, 54, 3, 0, 19, 0, 140, 198, 62, 125, 177, 55, + 109, 158, 47, 92, 137, 40, 76, 117, 32, 59, 98, 21, 42, 78, 6, + 16, 54, 0, 0, 18, 0, 118, 186, 231, 106, 167, 206, 93, 149, 184, + 81, 130, 161, 67, 111, 139, 54, 92, 117, 39, 72, 93, 17, 48, 66, + 0, 10, 29, 123, 185, 207, 110, 166, 186, 98, 148, 167, 85, 129, 145, + 71, 111, 125, 56, 92, 104, 40, 72, 83, 18, 48, 57, 0, 10, 22, + 128, 184, 188, 113, 165, 168, 102, 147, 151, 88, 128, 131, 73, 110, 113, + 58, 91, 94, 42, 71, 74, 19, 48, 50, 0, 9, 15, 131, 183, 168, + 116, 164, 151, 104, 146, 134, 89, 127, 117, 73, 109, 100, 58, 90, 83, + 42, 71, 65, 20, 48, 42, 0, 9, 5, 134, 182, 148, 120, 163, 131, + 105, 145, 118, 90, 126, 102, 75, 108, 86, 59, 90, 72, 43, 71, 55, + 19, 47, 34, 0, 9, 0, 136, 181, 128, 122, 162, 115, 107, 144, 102, + 92, 125, 87, 76, 107, 74, 61, 89, 60, 44, 70, 45, 20, 47, 24, + 0, 8, 0, 139, 180, 106, 124, 161, 95, 109, 144, 83, 93, 124, 71, + 77, 107, 60, 61, 89, 47, 44, 70, 33, 20, 47, 13, 0, 8, 0, + 142, 179, 82, 125, 160, 72, 111, 143, 63, 94, 124, 54, 77, 106, 44, + 61, 88, 32, 44, 69, 18, 20, 46, 0, 0, 8, 0, 143, 179, 62, + 127, 160, 54, 111, 142, 47, 94, 124, 39, 78, 106, 29, 62, 88, 18, + 45, 69, 3, 20, 46, 0, 0, 8, 0, 124, 167, 216, 112, 150, 194, + 99, 134, 174, 87, 117, 153, 73, 100, 131, 58, 82, 110, 43, 64, 88, + 23, 40, 61, 0, 0, 24, 129, 166, 195, 116, 150, 175, 103, 134, 158, + 89, 116, 137, 75, 99, 118, 60, 82, 98, 44, 63, 78, 23, 40, 53, + 0, 0, 17, 132, 166, 177, 119, 149, 160, 106, 133, 143, 90, 115, 124, + 76, 99, 107, 61, 81, 88, 45, 63, 69, 24, 40, 46, 0, 0, 9, + 136, 166, 159, 121, 148, 143, 107, 132, 126, 92, 115, 111, 77, 98, 94, + 62, 81, 78, 46, 63, 60, 23, 40, 38, 0, 0, 0, 138, 164, 140, + 122, 147, 125, 108, 131, 111, 93, 114, 97, 79, 98, 82, 63, 80, 67, + 46, 62, 50, 24, 40, 29, 0, 0, 0, 139, 163, 122, 124, 146, 109, + 110, 131, 96, 94, 114, 83, 79, 97, 70, 63, 81, 57, 46, 62, 41, + 24, 40, 21, 0, 0, 0, 141, 163, 101, 126, 145, 90, 111, 130, 79, + 95, 113, 68, 79, 96, 56, 63, 80, 44, 47, 62, 30, 23, 40, 10, + 0, 0, 0, 144, 162, 79, 127, 145, 70, 112, 129, 60, 95, 112, 51, + 79, 96, 41, 64, 79, 30, 47, 61, 15, 23, 40, 0, 0, 0, 0, + 145, 162, 60, 129, 145, 52, 113, 129, 46, 96, 112, 37, 79, 95, 27, + 64, 79, 16, 47, 61, 1, 23, 39, 0, 0, 0, 0, 131, 147, 202, + 117, 133, 181, 105, 119, 162, 91, 103, 142, 77, 87, 122, 62, 71, 102, + 47, 54, 81, 26, 31, 56, 0, 0, 18, 135, 147, 183, 120, 132, 164, + 107, 118, 147, 93, 102, 128, 78, 87, 110, 63, 71, 92, 47, 54, 72, + 26, 31, 48, 0, 0, 10, 138, 147, 166, 123, 131, 149, 108, 118, 133, + 94, 102, 116, 79, 86, 100, 64, 71, 82, 48, 54, 64, 27, 31, 41, + 0, 0, 2, 139, 146, 149, 124, 131, 134, 111, 117, 119, 94, 101, 103, + 79, 86, 88, 64, 70, 72, 48, 53, 55, 27, 31, 33, 0, 0, 0, + 141, 146, 132, 125, 131, 117, 111, 117, 104, 95, 101, 91, 80, 86, 77, + 65, 70, 62, 48, 53, 46, 26, 31, 25, 0, 0, 0, 143, 145, 115, + 126, 130, 101, 112, 116, 90, 96, 100, 78, 80, 85, 65, 65, 70, 52, + 49, 53, 37, 27, 32, 17, 0, 0, 0, 144, 144, 96, 128, 129, 85, + 112, 115, 75, 97, 100, 64, 81, 85, 52, 65, 69, 40, 49, 53, 26, + 26, 31, 5, 0, 0, 0, 146, 144, 76, 129, 129, 67, 114, 115, 58, + 97, 99, 48, 82, 84, 38, 66, 69, 27, 49, 53, 12, 26, 32, 0, + 0, 0, 0, 146, 144, 59, 130, 128, 51, 114, 114, 43, 98, 99, 35, + 82, 84, 25, 66, 69, 13, 49, 53, 0, 26, 32, 0, 0, 0, 0, + 135, 129, 189, 122, 115, 170, 107, 103, 152, 94, 89, 133, 79, 74, 114, + 64, 60, 95, 49, 43, 75, 29, 20, 51, 0, 0, 12, 138, 129, 171, + 124, 115, 153, 110, 103, 138, 95, 89, 120, 81, 74, 103, 66, 60, 86, + 50, 44, 67, 28, 21, 43, 0, 0, 3, 140, 129, 156, 125, 115, 140, + 111, 103, 125, 96, 89, 109, 81, 74, 93, 67, 60, 76, 50, 44, 59, + 29, 22, 36, 0, 0, 0, 142, 128, 140, 127, 115, 125, 112, 102, 112, + 97, 88, 97, 82, 74, 83, 67, 60, 67, 50, 44, 51, 29, 22, 29, + 0, 0, 0, 142, 128, 124, 127, 114, 111, 113, 102, 98, 98, 88, 85, + 82, 74, 71, 66, 60, 58, 50, 44, 42, 29, 22, 21, 0, 0, 0, + 144, 127, 108, 128, 114, 96, 113, 101, 85, 98, 87, 73, 82, 74, 61, + 67, 60, 48, 50, 44, 33, 28, 23, 12, 0, 0, 0, 145, 127, 91, + 129, 114, 81, 115, 101, 71, 98, 87, 60, 82, 73, 48, 67, 59, 37, + 50, 44, 22, 29, 23, 1, 0, 0, 0, 147, 127, 73, 130, 113, 63, + 115, 101, 55, 98, 87, 45, 83, 73, 35, 67, 59, 24, 50, 44, 10, + 28, 24, 0, 0, 0, 0, 147, 127, 58, 131, 113, 49, 115, 100, 42, + 99, 86, 33, 83, 73, 23, 67, 59, 10, 50, 44, 0, 27, 24, 0, + 0, 0, 0, 138, 110, 177, 124, 99, 159, 110, 88, 142, 96, 75, 125, + 82, 62, 107, 66, 48, 89, 51, 33, 70, 30, 8, 46, 0, 0, 5, + 142, 111, 160, 127, 99, 144, 113, 88, 130, 98, 75, 112, 82, 62, 96, + 68, 49, 80, 51, 33, 61, 30, 10, 39, 0, 0, 0, 143, 111, 146, + 128, 99, 131, 114, 88, 118, 98, 75, 101, 83, 62, 86, 68, 49, 71, + 52, 33, 54, 30, 11, 32, 0, 0, 0, 144, 111, 132, 128, 99, 118, + 113, 88, 106, 99, 75, 91, 83, 62, 77, 68, 49, 62, 52, 34, 46, + 30, 12, 25, 0, 0, 0, 144, 111, 117, 129, 98, 104, 114, 87, 92, + 99, 75, 80, 83, 62, 67, 68, 49, 53, 51, 34, 38, 30, 13, 18, + 0, 0, 0, 145, 111, 103, 130, 98, 91, 114, 87, 80, 99, 75, 68, + 83, 63, 57, 68, 50, 45, 51, 34, 30, 30, 14, 8, 0, 0, 0, + 146, 110, 87, 131, 98, 76, 115, 87, 67, 99, 75, 56, 83, 62, 45, + 68, 49, 33, 52, 35, 19, 30, 15, 2, 0, 0, 0, 148, 110, 70, + 131, 98, 60, 116, 86, 52, 99, 74, 43, 84, 62, 33, 69, 49, 21, + 52, 35, 6, 29, 15, 0, 0, 0, 0, 148, 110, 56, 132, 97, 48, + 117, 87, 40, 100, 75, 31, 84, 62, 22, 68, 49, 9, 51, 35, 0, + 28, 15, 0, 0, 0, 0, 142, 91, 166, 126, 80, 148, 113, 71, 132, + 98, 59, 115, 83, 47, 99, 69, 34, 82, 53, 17, 64, 32, 0, 41, + 0, 0, 0, 143, 91, 150, 128, 81, 135, 114, 71, 120, 99, 60, 104, + 85, 48, 89, 69, 35, 73, 53, 19, 56, 32, 0, 34, 0, 0, 0, + 145, 91, 137, 129, 81, 122, 115, 71, 109, 100, 60, 94, 85, 48, 81, + 69, 35, 65, 53, 19, 49, 32, 0, 28, 0, 0, 0, 146, 92, 124, + 130, 81, 110, 115, 71, 98, 100, 60, 84, 85, 49, 71, 69, 36, 57, + 53, 21, 42, 32, 0, 21, 0, 0, 0, 147, 91, 110, 130, 81, 97, + 115, 71, 86, 100, 60, 74, 84, 49, 62, 69, 36, 48, 53, 22, 34, + 32, 0, 13, 0, 0, 0, 147, 92, 97, 130, 81, 85, 116, 72, 76, + 100, 60, 63, 85, 49, 52, 69, 37, 40, 53, 22, 26, 31, 1, 5, + 0, 0, 0, 148, 92, 82, 131, 81, 71, 116, 71, 62, 100, 60, 53, + 84, 49, 42, 69, 37, 30, 52, 23, 16, 31, 2, 0, 0, 0, 0, + 148, 91, 67, 132, 81, 57, 117, 71, 49, 100, 60, 39, 84, 49, 30, + 69, 37, 18, 52, 23, 2, 30, 2, 0, 0, 0, 0, 149, 91, 54, + 132, 81, 46, 118, 71, 39, 101, 60, 29, 85, 49, 19, 69, 37, 6, + 52, 23, 0, 29, 3, 0, 0, 0, 0, 143, 68, 153, 128, 59, 137, + 115, 49, 122, 99, 39, 107, 85, 28, 91, 70, 13, 75, 54, 0, 58, + 32, 0, 36, 0, 0, 0, 146, 68, 140, 131, 59, 125, 116, 51, 111, + 100, 40, 97, 85, 29, 82, 70, 15, 67, 54, 0, 50, 32, 0, 29, + 0, 0, 0, 147, 68, 127, 131, 59, 114, 117, 51, 102, 101, 41, 88, + 86, 30, 74, 70, 17, 60, 54, 0, 44, 32, 0, 23, 0, 0, 0, + 147, 70, 115, 131, 60, 103, 116, 52, 91, 100, 42, 78, 85, 32, 65, + 70, 19, 53, 54, 1, 38, 32, 0, 17, 0, 0, 0, 147, 70, 103, + 131, 61, 91, 117, 53, 81, 101, 43, 69, 86, 32, 57, 70, 20, 44, + 54, 2, 30, 32, 0, 7, 0, 0, 0, 148, 70, 91, 132, 61, 80, + 117, 52, 70, 101, 43, 59, 85, 33, 48, 70, 21, 36, 53, 4, 22, + 32, 0, 3, 0, 0, 0, 148, 70, 78, 132, 62, 68, 117, 53, 58, + 101, 43, 48, 85, 34, 38, 70, 22, 26, 53, 6, 12, 31, 0, 0, + 0, 0, 0, 149, 71, 64, 132, 62, 54, 118, 54, 46, 101, 44, 37, + 85, 34, 27, 69, 23, 15, 53, 7, 1, 30, 0, 0, 0, 0, 0, + 150, 70, 53, 134, 61, 44, 118, 54, 36, 101, 44, 28, 85, 35, 17, + 69, 23, 4, 52, 8, 0, 30, 0, 0, 0, 0, 0, 145, 38, 143, + 130, 29, 128, 117, 18, 114, 101, 3, 98, 87, 0, 84, 72, 0, 69, + 54, 0, 53, 30, 0, 31, 0, 0, 0, 147, 38, 130, 132, 30, 116, + 117, 22, 103, 101, 8, 89, 87, 0, 76, 72, 0, 62, 54, 0, 46, + 30, 0, 24, 0, 0, 0, 148, 40, 119, 132, 31, 105, 117, 23, 94, + 101, 13, 81, 87, 0, 68, 71, 0, 55, 54, 0, 39, 30, 0, 18, + 0, 0, 0, 148, 42, 108, 132, 34, 96, 117, 25, 85, 102, 15, 73, + 86, 2, 60, 71, 0, 47, 54, 0, 33, 30, 0, 11, 0, 0, 0, + 148, 43, 96, 133, 35, 85, 117, 28, 75, 102, 18, 64, 87, 5, 52, + 71, 0, 40, 54, 0, 25, 30, 0, 5, 0, 0, 0, 149, 44, 85, + 132, 36, 75, 118, 29, 66, 101, 20, 55, 86, 8, 44, 70, 0, 32, + 53, 0, 18, 29, 0, 2, 0, 0, 0, 149, 45, 74, 133, 37, 64, + 118, 31, 55, 102, 21, 45, 85, 10, 34, 70, 0, 22, 53, 0, 6, + 28, 0, 0, 0, 0, 0, 150, 46, 61, 133, 39, 52, 118, 31, 44, + 102, 23, 34, 85, 12, 24, 70, 0, 12, 52, 0, 0, 28, 0, 0, + 0, 0, 0, 150, 46, 51, 133, 40, 42, 119, 32, 35, 102, 24, 25, + 85, 13, 14, 70, 0, 1, 52, 0, 0, 27, 0, 0, 0, 0, 0, + 53, 198, 244, 49, 177, 218, 41, 158, 195, 32, 138, 171, 22, 118, 147, + 11, 98, 124, 0, 78, 100, 0, 54, 71, 0, 18, 34, 69, 196, 220, + 64, 175, 196, 54, 157, 176, 45, 137, 154, 32, 117, 133, 19, 98, 111, + 0, 78, 89, 0, 53, 63, 0, 17, 27, 80, 195, 198, 69, 175, 179, + 60, 156, 159, 50, 136, 139, 38, 116, 120, 25, 98, 101, 4, 77, 80, + 0, 53, 55, 0, 17, 21, 84, 193, 177, 75, 173, 159, 64, 155, 142, + 55, 135, 124, 41, 116, 107, 27, 97, 89, 9, 76, 70, 0, 53, 47, + 0, 17, 11, 89, 193, 157, 79, 172, 140, 70, 154, 125, 57, 134, 109, + 44, 115, 92, 32, 96, 76, 13, 76, 59, 0, 52, 39, 0, 16, 4, + 94, 191, 135, 85, 171, 121, 72, 152, 108, 60, 133, 94, 47, 114, 80, + 32, 95, 65, 15, 76, 49, 0, 52, 29, 0, 16, 0, 98, 190, 113, + 87, 170, 100, 76, 152, 89, 62, 132, 77, 49, 113, 65, 35, 95, 52, + 18, 75, 37, 0, 52, 18, 0, 15, 0, 103, 190, 89, 90, 169, 80, + 78, 151, 70, 64, 132, 60, 51, 113, 49, 37, 94, 38, 20, 75, 25, + 0, 52, 5, 0, 15, 0, 106, 189, 69, 93, 169, 61, 80, 151, 53, + 66, 131, 45, 52, 113, 36, 37, 94, 25, 19, 74, 11, 0, 51, 0, + 0, 15, 0, 76, 178, 229, 68, 159, 205, 61, 142, 183, 50, 124, 160, + 40, 106, 138, 28, 88, 116, 12, 69, 93, 0, 45, 66, 0, 5, 29, + 86, 177, 207, 78, 158, 184, 67, 142, 166, 56, 123, 145, 45, 106, 125, + 31, 88, 105, 16, 69, 83, 0, 45, 58, 0, 6, 22, 93, 176, 187, + 81, 158, 168, 71, 141, 150, 61, 123, 131, 47, 105, 113, 35, 87, 94, + 20, 68, 74, 0, 45, 51, 0, 5, 16, 98, 175, 168, 84, 157, 150, + 75, 140, 134, 63, 122, 117, 50, 104, 100, 37, 87, 83, 21, 68, 65, + 0, 45, 42, 0, 4, 7, 100, 174, 149, 89, 155, 132, 76, 139, 117, + 65, 121, 102, 53, 104, 87, 39, 86, 72, 23, 67, 55, 0, 45, 34, + 0, 3, 0, 103, 173, 130, 92, 155, 115, 80, 138, 102, 68, 120, 88, + 53, 103, 75, 40, 86, 61, 24, 67, 45, 0, 45, 25, 0, 3, 0, + 107, 172, 108, 95, 154, 96, 82, 137, 85, 70, 119, 73, 55, 102, 61, + 42, 85, 49, 25, 67, 34, 0, 45, 14, 0, 3, 0, 110, 172, 86, + 97, 153, 76, 85, 137, 67, 70, 119, 57, 56, 102, 46, 42, 84, 35, + 26, 66, 21, 0, 44, 1, 0, 3, 0, 112, 171, 67, 98, 153, 59, + 86, 137, 52, 71, 119, 44, 58, 102, 34, 44, 85, 22, 27, 66, 7, + 0, 44, 0, 0, 3, 0, 90, 160, 215, 81, 144, 193, 70, 129, 173, + 61, 112, 151, 49, 95, 131, 37, 79, 109, 22, 61, 87, 0, 38, 61, + 0, 0, 25, 96, 160, 194, 86, 143, 174, 75, 128, 157, 65, 112, 137, + 53, 95, 117, 40, 78, 98, 25, 60, 78, 0, 38, 53, 0, 0, 17, + 100, 159, 177, 89, 143, 159, 79, 128, 143, 67, 111, 124, 55, 95, 107, + 42, 78, 89, 27, 60, 70, 2, 38, 46, 0, 0, 9, 104, 158, 159, + 92, 142, 143, 81, 127, 127, 69, 110, 110, 56, 94, 94, 43, 78, 78, + 28, 60, 60, 2, 38, 38, 0, 0, 1, 107, 157, 140, 94, 141, 125, + 82, 126, 112, 71, 110, 97, 59, 94, 82, 45, 77, 67, 29, 59, 51, + 4, 37, 30, 0, 0, 0, 110, 156, 122, 97, 140, 109, 85, 125, 97, + 72, 109, 83, 58, 93, 71, 45, 77, 57, 29, 60, 42, 5, 38, 22, + 0, 0, 0, 111, 156, 103, 99, 139, 91, 87, 125, 81, 73, 108, 69, + 60, 92, 58, 46, 77, 45, 30, 59, 31, 5, 38, 12, 0, 0, 0, + 115, 156, 82, 101, 140, 73, 88, 124, 63, 74, 108, 53, 60, 92, 44, + 46, 76, 32, 31, 59, 18, 6, 37, 0, 0, 0, 0, 116, 155, 65, + 102, 139, 58, 89, 124, 49, 75, 108, 41, 61, 92, 32, 48, 76, 21, + 31, 59, 6, 5, 37, 0, 0, 0, 0, 100, 141, 201, 88, 127, 181, + 79, 114, 162, 69, 99, 142, 57, 83, 122, 44, 68, 102, 30, 51, 81, + 7, 28, 56, 0, 0, 19, 105, 141, 182, 94, 127, 163, 83, 114, 146, + 71, 98, 128, 59, 83, 110, 46, 68, 91, 31, 51, 72, 10, 28, 48, + 0, 0, 11, 108, 141, 166, 96, 127, 149, 85, 113, 133, 73, 98, 116, + 60, 83, 99, 46, 68, 82, 32, 51, 64, 11, 29, 41, 0, 0, 2, + 111, 141, 149, 98, 126, 134, 88, 112, 119, 74, 97, 103, 61, 83, 88, + 48, 67, 72, 33, 51, 56, 11, 29, 34, 0, 0, 0, 112, 140, 132, + 100, 125, 118, 89, 112, 105, 75, 97, 91, 62, 82, 77, 49, 68, 62, + 33, 51, 47, 12, 29, 26, 0, 0, 0, 115, 140, 116, 102, 125, 103, + 90, 111, 91, 76, 96, 78, 62, 82, 65, 49, 67, 52, 34, 51, 38, + 13, 29, 18, 0, 0, 0, 117, 139, 97, 103, 124, 87, 91, 111, 77, + 78, 96, 65, 63, 81, 54, 49, 67, 41, 34, 51, 27, 12, 29, 7, + 0, 0, 0, 119, 138, 78, 105, 124, 69, 92, 110, 60, 78, 95, 50, + 65, 81, 40, 50, 67, 29, 34, 51, 15, 13, 30, 0, 0, 0, 0, + 120, 138, 64, 106, 124, 54, 93, 110, 47, 78, 95, 38, 65, 81, 29, + 50, 66, 17, 34, 50, 2, 13, 29, 0, 0, 0, 0, 107, 124, 189, + 96, 111, 169, 85, 99, 152, 73, 85, 132, 61, 71, 114, 48, 57, 95, + 34, 41, 75, 14, 18, 51, 0, 0, 13, 111, 124, 171, 100, 111, 153, + 88, 99, 137, 75, 85, 120, 63, 72, 103, 50, 58, 85, 36, 41, 66, + 15, 19, 43, 0, 0, 4, 113, 124, 156, 101, 111, 139, 90, 99, 125, + 77, 85, 109, 64, 71, 93, 51, 57, 77, 36, 42, 59, 17, 20, 37, + 0, 0, 0, 115, 124, 140, 103, 111, 125, 90, 99, 112, 78, 85, 97, + 64, 71, 82, 52, 57, 67, 36, 42, 50, 16, 20, 30, 0, 0, 0, + 117, 123, 125, 104, 110, 111, 92, 98, 99, 79, 85, 86, 65, 71, 72, + 51, 58, 59, 37, 42, 43, 17, 21, 22, 0, 0, 0, 118, 123, 110, + 105, 110, 97, 93, 98, 86, 78, 84, 74, 66, 71, 62, 52, 57, 49, + 37, 42, 34, 17, 22, 14, 0, 0, 0, 120, 123, 93, 106, 109, 82, + 94, 97, 72, 80, 84, 61, 66, 71, 50, 52, 57, 38, 37, 42, 24, + 17, 22, 2, 0, 0, 0, 121, 122, 75, 108, 109, 66, 95, 97, 58, + 80, 84, 48, 66, 71, 37, 52, 57, 26, 37, 42, 12, 16, 22, 0, + 0, 0, 0, 122, 123, 62, 108, 109, 52, 95, 97, 45, 81, 84, 36, + 67, 70, 26, 52, 57, 14, 37, 42, 0, 15, 22, 0, 0, 0, 0, + 113, 107, 177, 102, 96, 159, 89, 85, 141, 78, 72, 124, 65, 60, 107, + 52, 46, 89, 37, 30, 70, 18, 5, 46, 0, 0, 6, 116, 107, 160, + 104, 96, 144, 92, 85, 129, 80, 72, 112, 67, 60, 96, 53, 47, 80, + 38, 31, 62, 19, 7, 39, 0, 0, 0, 118, 107, 147, 105, 96, 131, + 93, 85, 118, 80, 72, 101, 67, 60, 87, 54, 47, 71, 39, 31, 54, + 19, 8, 32, 0, 0, 0, 119, 107, 132, 106, 96, 118, 94, 85, 106, + 81, 73, 91, 67, 60, 77, 54, 47, 63, 39, 32, 47, 20, 9, 25, + 0, 0, 0, 119, 107, 118, 106, 95, 105, 94, 85, 93, 81, 72, 80, + 68, 60, 68, 54, 47, 54, 39, 32, 39, 20, 11, 18, 0, 0, 0, + 121, 107, 104, 107, 96, 92, 95, 84, 80, 81, 72, 69, 68, 61, 58, + 54, 48, 46, 39, 33, 31, 20, 12, 9, 0, 0, 0, 123, 107, 88, + 108, 95, 77, 96, 84, 68, 82, 72, 57, 68, 60, 46, 54, 47, 35, + 39, 33, 20, 19, 13, 2, 0, 0, 0, 123, 106, 72, 110, 95, 63, + 96, 84, 54, 82, 72, 45, 69, 60, 35, 55, 48, 23, 39, 33, 9, + 18, 14, 0, 0, 0, 0, 125, 106, 60, 110, 94, 50, 98, 84, 42, + 83, 72, 34, 69, 60, 25, 55, 48, 12, 39, 33, 0, 17, 13, 0, + 0, 0, 0, 118, 89, 165, 105, 79, 148, 93, 69, 132, 81, 57, 115, + 68, 45, 99, 55, 32, 82, 41, 15, 64, 21, 0, 41, 0, 0, 0, + 120, 89, 150, 107, 79, 135, 96, 69, 121, 82, 58, 105, 70, 46, 89, + 56, 34, 73, 41, 17, 56, 21, 0, 34, 0, 0, 0, 121, 89, 137, + 108, 79, 123, 96, 69, 109, 82, 58, 95, 70, 47, 81, 56, 34, 66, + 41, 18, 49, 21, 0, 28, 0, 0, 0, 122, 90, 124, 109, 79, 110, + 96, 69, 99, 83, 58, 85, 70, 47, 72, 56, 35, 58, 41, 19, 42, + 21, 0, 22, 0, 0, 0, 123, 90, 111, 110, 79, 98, 97, 69, 87, + 83, 59, 75, 70, 47, 63, 56, 35, 50, 41, 20, 35, 21, 0, 14, + 0, 0, 0, 123, 90, 98, 110, 79, 87, 97, 70, 76, 84, 58, 64, + 70, 48, 53, 56, 36, 41, 40, 21, 26, 21, 0, 5, 0, 0, 0, + 125, 89, 84, 111, 79, 73, 97, 69, 64, 84, 59, 54, 70, 48, 43, + 56, 36, 31, 40, 22, 17, 20, 1, 1, 0, 0, 0, 125, 89, 69, + 112, 79, 60, 98, 70, 51, 84, 59, 42, 70, 48, 32, 56, 36, 20, + 41, 22, 5, 19, 2, 0, 0, 0, 0, 126, 89, 57, 112, 79, 49, + 99, 70, 41, 84, 59, 32, 70, 48, 22, 56, 36, 10, 40, 22, 0, + 18, 2, 0, 0, 0, 0, 121, 67, 154, 108, 58, 138, 97, 50, 124, + 84, 39, 107, 71, 28, 92, 58, 12, 76, 43, 0, 59, 20, 0, 37, + 0, 0, 0, 124, 68, 140, 111, 59, 126, 98, 50, 112, 84, 40, 98, + 71, 29, 83, 58, 15, 67, 42, 0, 51, 20, 0, 30, 0, 0, 0, + 124, 68, 129, 111, 59, 114, 99, 51, 102, 86, 41, 88, 71, 30, 75, + 58, 17, 60, 42, 0, 45, 20, 0, 24, 0, 0, 0, 125, 70, 116, + 111, 60, 103, 99, 51, 92, 85, 41, 79, 71, 31, 66, 58, 19, 53, + 42, 3, 38, 20, 0, 17, 0, 0, 0, 125, 70, 104, 111, 61, 93, + 99, 52, 81, 85, 43, 69, 72, 32, 58, 58, 20, 45, 42, 4, 31, + 20, 0, 8, 0, 0, 0, 126, 70, 92, 111, 61, 81, 99, 52, 71, + 85, 42, 60, 71, 33, 49, 57, 21, 37, 42, 6, 23, 20, 0, 3, + 0, 0, 0, 126, 70, 79, 112, 61, 70, 99, 53, 60, 85, 43, 50, + 71, 33, 39, 57, 22, 28, 41, 7, 13, 19, 0, 0, 0, 0, 0, + 127, 71, 66, 113, 62, 56, 100, 53, 48, 86, 44, 39, 71, 34, 29, + 57, 23, 18, 41, 8, 2, 18, 0, 0, 0, 0, 0, 128, 70, 55, + 114, 62, 46, 100, 54, 39, 86, 44, 30, 71, 34, 20, 57, 23, 7, + 41, 9, 0, 18, 0, 0, 0, 0, 0, 124, 41, 145, 111, 32, 128, + 99, 23, 114, 86, 10, 100, 73, 0, 85, 60, 0, 71, 43, 0, 54, + 17, 0, 32, 0, 0, 0, 126, 42, 131, 113, 33, 117, 100, 25, 104, + 86, 14, 90, 73, 0, 77, 60, 0, 63, 44, 0, 47, 18, 0, 25, + 0, 0, 0, 127, 43, 120, 113, 34, 106, 101, 26, 95, 86, 17, 82, + 73, 2, 69, 59, 0, 56, 43, 0, 41, 18, 0, 19, 0, 0, 0, + 127, 45, 109, 113, 37, 97, 101, 28, 85, 86, 19, 74, 73, 5, 61, + 59, 0, 48, 43, 0, 34, 19, 0, 11, 0, 0, 0, 127, 46, 98, + 114, 38, 86, 100, 30, 76, 87, 21, 65, 73, 9, 54, 59, 0, 41, + 43, 0, 26, 18, 0, 5, 0, 0, 0, 127, 47, 87, 113, 39, 76, + 101, 31, 67, 86, 22, 56, 72, 11, 45, 59, 0, 33, 43, 0, 19, + 18, 0, 2, 0, 0, 0, 128, 48, 75, 114, 39, 65, 101, 33, 56, + 86, 23, 46, 72, 12, 36, 58, 0, 24, 42, 0, 9, 17, 0, 0, + 0, 0, 0, 129, 48, 63, 114, 41, 54, 102, 33, 46, 87, 24, 36, + 72, 14, 26, 58, 1, 14, 42, 0, 2, 16, 0, 0, 0, 0, 0, + 128, 48, 53, 114, 41, 44, 102, 34, 37, 87, 25, 27, 72, 15, 17, + 58, 1, 3, 41, 0, 0, 15, 0, 0, 0, 0, 0, 0, 189, 242, + 0, 169, 217, 0, 151, 194, 0, 132, 170, 0, 113, 147, 0, 94, 123, + 0, 74, 99, 0, 51, 71, 0, 15, 34, 1, 187, 219, 1, 167, 195, + 0, 150, 175, 0, 131, 153, 0, 113, 132, 0, 94, 111, 0, 74, 89, + 0, 50, 63, 0, 13, 28, 1, 186, 198, 1, 167, 178, 0, 149, 158, + 0, 130, 139, 0, 111, 119, 0, 93, 100, 0, 74, 80, 0, 50, 55, + 0, 13, 22, 1, 185, 176, 1, 165, 159, 1, 148, 142, 0, 129, 123, + 0, 111, 106, 0, 93, 89, 0, 73, 70, 0, 50, 47, 0, 13, 13, + 1, 184, 157, 1, 164, 141, 1, 147, 125, 0, 128, 110, 0, 110, 93, + 0, 92, 77, 0, 73, 60, 0, 50, 39, 0, 12, 5, 25, 182, 137, + 25, 163, 122, 17, 146, 109, 0, 128, 96, 0, 110, 81, 0, 92, 66, + 0, 73, 51, 0, 50, 30, 0, 10, 0, 42, 181, 114, 35, 163, 102, + 30, 145, 91, 14, 127, 80, 0, 109, 67, 0, 91, 53, 0, 72, 39, + 0, 50, 19, 0, 10, 0, 52, 181, 92, 43, 162, 83, 32, 145, 73, + 19, 126, 63, 0, 108, 52, 0, 90, 40, 0, 72, 27, 0, 50, 7, + 0, 10, 0, 57, 181, 74, 48, 162, 66, 37, 144, 57, 24, 126, 49, + 7, 108, 40, 0, 90, 29, 0, 72, 15, 0, 49, 0, 0, 10, 0, + 1, 170, 227, 1, 152, 203, 0, 136, 182, 0, 119, 159, 0, 101, 137, + 0, 84, 115, 0, 65, 92, 0, 43, 66, 0, 1, 29, 1, 169, 206, + 1, 151, 184, 1, 136, 165, 0, 118, 144, 0, 102, 125, 0, 84, 105, + 0, 65, 83, 0, 43, 58, 0, 0, 22, 29, 168, 186, 21, 151, 167, + 14, 135, 150, 4, 118, 131, 0, 101, 112, 0, 83, 94, 0, 65, 75, + 0, 43, 51, 0, 0, 16, 41, 167, 167, 33, 150, 150, 31, 134, 134, + 19, 117, 117, 4, 100, 100, 0, 83, 83, 0, 65, 65, 0, 42, 43, + 0, 0, 8, 48, 167, 149, 41, 149, 133, 33, 133, 118, 25, 116, 103, + 13, 99, 88, 0, 83, 73, 0, 65, 56, 0, 42, 35, 0, 0, 0, + 58, 165, 130, 49, 148, 115, 42, 132, 103, 31, 115, 89, 18, 99, 75, + 0, 82, 61, 0, 64, 46, 0, 42, 26, 0, 0, 0, 62, 164, 110, + 55, 147, 97, 45, 132, 87, 35, 115, 75, 22, 98, 63, 5, 82, 50, + 0, 64, 36, 0, 42, 16, 0, 0, 0, 69, 164, 89, 60, 147, 78, + 50, 131, 70, 37, 114, 59, 26, 98, 49, 10, 81, 37, 0, 64, 24, + 0, 42, 4, 0, 0, 0, 71, 164, 71, 63, 147, 63, 53, 131, 55, + 40, 114, 47, 28, 98, 38, 13, 81, 26, 0, 64, 12, 0, 42, 0, + 0, 0, 0, 28, 153, 214, 24, 138, 193, 23, 123, 171, 16, 107, 150, + 0, 91, 130, 0, 75, 109, 0, 58, 87, 0, 35, 61, 0, 0, 25, + 48, 153, 194, 41, 138, 174, 34, 123, 156, 27, 107, 136, 16, 91, 117, + 1, 75, 98, 0, 57, 78, 0, 35, 53, 0, 0, 17, 55, 153, 177, + 47, 137, 158, 42, 122, 142, 33, 107, 124, 22, 91, 106, 6, 75, 88, + 0, 57, 70, 0, 35, 46, 0, 0, 9, 61, 152, 158, 53, 136, 143, + 45, 122, 127, 36, 106, 111, 24, 90, 94, 10, 74, 78, 0, 57, 61, + 0, 35, 39, 0, 0, 2, 67, 151, 141, 59, 135, 126, 49, 121, 112, + 39, 105, 98, 29, 90, 83, 14, 74, 68, 0, 57, 52, 0, 35, 31, + 0, 0, 0, 71, 150, 123, 62, 135, 110, 54, 120, 98, 42, 105, 84, + 31, 89, 71, 16, 74, 58, 0, 57, 43, 0, 35, 22, 0, 0, 0, + 74, 150, 105, 64, 134, 92, 55, 120, 83, 45, 104, 71, 34, 89, 59, + 20, 73, 47, 0, 57, 32, 0, 35, 13, 0, 0, 0, 78, 149, 84, + 69, 134, 75, 59, 120, 66, 47, 103, 56, 34, 88, 46, 22, 73, 34, + 1, 57, 20, 0, 35, 1, 0, 0, 0, 80, 149, 69, 70, 133, 61, + 60, 119, 53, 49, 103, 44, 36, 88, 35, 23, 73, 24, 2, 56, 10, + 0, 35, 0, 0, 0, 0, 58, 136, 200, 50, 122, 180, 45, 109, 162, + 38, 94, 141, 27, 80, 121, 15, 65, 102, 0, 48, 81, 0, 26, 56, + 0, 0, 19, 66, 136, 182, 59, 122, 163, 52, 109, 146, 42, 94, 128, + 32, 80, 109, 20, 65, 91, 2, 48, 72, 0, 26, 49, 0, 0, 11, + 70, 136, 165, 62, 122, 149, 55, 108, 133, 46, 94, 116, 35, 80, 99, + 21, 65, 82, 4, 49, 64, 0, 26, 41, 0, 0, 3, 76, 135, 149, + 66, 121, 133, 58, 108, 119, 48, 94, 103, 36, 79, 88, 23, 65, 73, + 7, 49, 56, 0, 27, 34, 0, 0, 0, 78, 135, 133, 69, 120, 118, + 60, 107, 106, 50, 93, 92, 39, 79, 77, 26, 65, 63, 8, 49, 47, + 0, 27, 26, 0, 0, 0, 82, 134, 117, 71, 120, 104, 62, 107, 92, + 51, 93, 79, 39, 78, 66, 27, 64, 53, 10, 48, 39, 0, 27, 18, + 0, 0, 0, 84, 134, 99, 73, 119, 87, 64, 106, 77, 53, 92, 66, + 42, 78, 55, 28, 64, 42, 11, 48, 29, 0, 28, 9, 0, 0, 0, + 87, 133, 81, 76, 119, 72, 66, 106, 62, 55, 92, 52, 43, 78, 42, + 29, 64, 31, 12, 48, 17, 0, 28, 0, 0, 0, 0, 88, 134, 67, + 77, 119, 58, 68, 106, 51, 56, 92, 42, 44, 78, 32, 30, 64, 20, + 12, 48, 6, 0, 28, 0, 0, 0, 0, 73, 120, 189, 64, 107, 168, + 57, 96, 151, 47, 82, 133, 38, 69, 114, 26, 55, 95, 11, 39, 75, + 0, 16, 51, 0, 0, 14, 78, 120, 171, 69, 107, 153, 62, 95, 137, + 51, 82, 119, 40, 69, 102, 29, 55, 85, 15, 39, 66, 0, 17, 44, + 0, 0, 4, 81, 120, 156, 71, 107, 140, 64, 95, 125, 53, 82, 109, + 42, 69, 93, 31, 55, 77, 16, 39, 59, 0, 18, 37, 0, 0, 0, + 85, 120, 141, 74, 107, 126, 65, 95, 112, 54, 82, 97, 43, 69, 82, + 32, 55, 67, 17, 39, 51, 0, 19, 30, 0, 0, 0, 86, 119, 126, + 76, 106, 112, 66, 95, 100, 56, 81, 85, 45, 69, 72, 33, 55, 59, + 18, 40, 43, 0, 19, 22, 0, 0, 0, 89, 119, 110, 78, 106, 98, + 69, 94, 87, 56, 81, 75, 46, 68, 62, 33, 55, 49, 18, 40, 35, + 0, 20, 15, 0, 0, 0, 89, 119, 95, 80, 106, 83, 70, 94, 73, + 58, 81, 63, 46, 68, 51, 34, 55, 39, 19, 40, 25, 0, 20, 4, + 0, 0, 0, 92, 118, 78, 82, 106, 68, 70, 93, 59, 59, 81, 49, + 47, 68, 39, 34, 55, 28, 19, 40, 14, 0, 20, 0, 0, 0, 0, + 93, 118, 65, 82, 105, 55, 72, 93, 48, 60, 81, 39, 47, 68, 29, + 34, 55, 18, 20, 40, 2, 0, 20, 0, 0, 0, 0, 83, 104, 177, + 74, 93, 159, 65, 82, 142, 56, 70, 124, 45, 57, 106, 33, 44, 89, + 20, 28, 70, 1, 4, 46, 0, 0, 8, 86, 104, 161, 78, 93, 145, + 68, 82, 128, 58, 70, 112, 48, 58, 96, 35, 45, 80, 21, 29, 62, + 1, 6, 40, 0, 0, 0, 89, 104, 147, 79, 93, 131, 69, 82, 118, + 59, 70, 102, 47, 58, 87, 36, 45, 72, 23, 29, 55, 3, 7, 33, + 0, 0, 0, 90, 104, 132, 80, 93, 119, 71, 82, 106, 60, 70, 91, + 48, 58, 77, 37, 45, 62, 23, 30, 47, 4, 7, 26, 0, 0, 0, + 92, 104, 118, 82, 93, 105, 72, 82, 93, 61, 69, 80, 50, 58, 68, + 37, 45, 55, 23, 30, 39, 4, 8, 18, 0, 0, 0, 94, 104, 105, + 82, 92, 93, 72, 82, 82, 61, 70, 70, 50, 58, 58, 38, 46, 46, + 23, 31, 31, 6, 10, 11, 0, 0, 0, 95, 104, 90, 84, 92, 79, + 74, 82, 70, 62, 70, 58, 50, 58, 48, 37, 46, 36, 23, 31, 22, + 4, 11, 3, 0, 0, 0, 96, 103, 74, 85, 92, 65, 75, 81, 56, + 63, 70, 47, 50, 58, 37, 38, 46, 25, 24, 31, 11, 3, 11, 0, + 0, 0, 0, 97, 103, 62, 86, 92, 53, 76, 81, 45, 63, 69, 36, + 51, 58, 27, 38, 46, 15, 23, 31, 0, 3, 11, 0, 0, 0, 0, + 90, 87, 165, 81, 77, 148, 72, 67, 132, 62, 55, 116, 50, 44, 99, + 39, 31, 82, 25, 14, 64, 1, 0, 42, 0, 0, 1, 93, 87, 150, + 83, 77, 135, 74, 67, 121, 63, 56, 105, 52, 45, 90, 40, 32, 74, + 25, 16, 57, 3, 0, 35, 0, 0, 0, 95, 87, 138, 85, 77, 123, + 75, 67, 109, 63, 57, 95, 53, 45, 81, 41, 33, 66, 26, 17, 50, + 4, 0, 28, 0, 0, 0, 95, 88, 124, 85, 77, 111, 75, 67, 99, + 63, 57, 86, 53, 45, 72, 41, 33, 58, 26, 18, 43, 5, 1, 22, + 0, 0, 0, 97, 88, 112, 87, 77, 100, 76, 68, 88, 64, 57, 76, + 53, 46, 63, 41, 34, 50, 26, 19, 35, 5, 2, 14, 0, 0, 0, + 99, 87, 99, 87, 78, 88, 76, 68, 77, 65, 57, 65, 53, 46, 54, + 41, 35, 42, 27, 20, 27, 6, 2, 5, 0, 0, 0, 100, 87, 85, + 88, 77, 75, 77, 68, 65, 65, 57, 54, 53, 46, 44, 41, 35, 32, + 27, 21, 19, 5, 3, 2, 0, 0, 0, 100, 88, 71, 89, 77, 61, + 78, 68, 53, 66, 57, 44, 53, 47, 33, 41, 35, 22, 27, 21, 7, + 5, 3, 0, 0, 0, 0, 101, 87, 60, 90, 77, 52, 79, 68, 44, + 66, 58, 34, 53, 47, 25, 41, 35, 13, 26, 22, 0, 5, 3, 0, + 0, 0, 0, 97, 67, 155, 86, 58, 138, 77, 50, 125, 66, 39, 108, + 55, 28, 92, 43, 12, 76, 29, 0, 59, 2, 0, 37, 0, 0, 0, + 99, 67, 141, 88, 59, 127, 78, 50, 113, 68, 40, 98, 56, 29, 83, + 44, 15, 68, 29, 0, 52, 3, 0, 30, 0, 0, 0, 100, 68, 129, + 89, 59, 115, 80, 51, 103, 68, 41, 89, 56, 30, 75, 44, 16, 61, + 30, 0, 45, 4, 0, 24, 0, 0, 0, 100, 69, 118, 90, 60, 104, + 80, 51, 92, 67, 41, 79, 56, 31, 66, 44, 18, 53, 29, 2, 38, + 4, 0, 18, 0, 0, 0, 101, 69, 104, 90, 61, 93, 79, 51, 82, + 67, 42, 70, 56, 32, 59, 44, 20, 46, 29, 4, 31, 6, 0, 9, + 0, 0, 0, 102, 69, 93, 90, 61, 83, 80, 52, 72, 68, 42, 61, + 56, 33, 50, 43, 20, 38, 29, 5, 23, 7, 0, 4, 0, 0, 0, + 102, 70, 80, 91, 61, 71, 80, 52, 61, 68, 43, 51, 56, 32, 40, + 44, 21, 29, 30, 6, 14, 7, 0, 0, 0, 0, 0, 103, 70, 68, + 92, 61, 58, 81, 53, 50, 69, 43, 41, 56, 34, 31, 43, 22, 19, + 29, 7, 3, 7, 0, 0, 0, 0, 0, 104, 70, 57, 92, 61, 48, + 82, 53, 40, 69, 43, 32, 56, 34, 22, 43, 23, 10, 29, 8, 0, + 6, 0, 0, 0, 0, 0, 101, 45, 145, 91, 35, 129, 80, 26, 116, + 69, 15, 101, 59, 0, 86, 46, 0, 71, 31, 0, 55, 0, 0, 33, + 0, 0, 0, 104, 44, 132, 92, 36, 118, 82, 28, 105, 71, 17, 91, + 58, 3, 77, 46, 0, 63, 31, 0, 48, 2, 0, 26, 0, 0, 0, + 104, 46, 121, 93, 37, 107, 82, 30, 96, 70, 20, 83, 58, 6, 70, + 46, 0, 57, 32, 0, 41, 4, 0, 20, 0, 0, 0, 104, 48, 110, + 93, 40, 98, 82, 31, 87, 70, 22, 74, 59, 9, 62, 45, 0, 49, + 31, 0, 35, 6, 0, 13, 0, 0, 0, 104, 48, 99, 92, 41, 88, + 82, 32, 77, 70, 23, 65, 58, 11, 54, 46, 0, 42, 32, 0, 27, + 7, 0, 5, 0, 0, 0, 105, 50, 88, 93, 41, 77, 82, 34, 68, + 71, 24, 57, 58, 13, 46, 45, 1, 35, 31, 0, 21, 7, 0, 2, + 0, 0, 0, 105, 50, 76, 94, 41, 66, 83, 34, 57, 71, 25, 47, + 58, 15, 37, 45, 2, 25, 32, 0, 11, 7, 0, 0, 0, 0, 0, + 106, 50, 64, 94, 42, 55, 83, 35, 47, 71, 26, 38, 58, 16, 27, + 45, 4, 17, 31, 0, 4, 7, 0, 0, 0, 0, 0, 106, 51, 54, + 95, 42, 45, 83, 35, 38, 71, 27, 30, 58, 16, 19, 45, 5, 7, + 30, 0, 0, 6, 0, 0, 0, 0, 0, 0, 181, 240, 0, 162, 216, + 0, 144, 193, 0, 126, 168, 0, 109, 146, 0, 91, 123, 0, 71, 98, + 0, 48, 71, 0, 9, 34, 0, 179, 218, 0, 161, 195, 0, 144, 174, + 0, 126, 153, 0, 108, 132, 0, 90, 110, 0, 71, 88, 0, 48, 63, + 0, 8, 29, 0, 178, 197, 0, 159, 177, 0, 143, 159, 0, 125, 139, + 0, 107, 119, 0, 90, 99, 0, 71, 79, 0, 48, 55, 0, 8, 22, + 0, 177, 177, 0, 158, 158, 0, 142, 141, 0, 124, 123, 0, 107, 106, + 0, 89, 88, 0, 71, 70, 0, 48, 47, 0, 8, 14, 0, 176, 157, + 0, 158, 141, 0, 141, 126, 0, 123, 109, 0, 106, 93, 0, 89, 78, + 0, 70, 60, 0, 47, 39, 0, 7, 5, 0, 175, 138, 0, 157, 123, + 0, 141, 110, 0, 123, 96, 0, 105, 81, 0, 88, 67, 0, 70, 51, + 0, 48, 30, 0, 6, 0, 0, 173, 115, 0, 155, 104, 0, 140, 92, + 0, 122, 80, 0, 105, 67, 0, 88, 55, 0, 69, 40, 0, 47, 20, + 0, 6, 0, 0, 173, 94, 0, 155, 85, 0, 139, 75, 0, 121, 64, + 0, 104, 53, 0, 88, 42, 0, 70, 28, 0, 47, 9, 0, 6, 0, + 0, 173, 76, 0, 155, 70, 0, 138, 61, 0, 122, 53, 0, 104, 44, + 0, 87, 32, 0, 69, 18, 0, 47, 0, 0, 6, 0, 0, 164, 226, + 0, 147, 203, 0, 131, 181, 0, 114, 158, 0, 97, 136, 0, 80, 115, + 0, 63, 92, 0, 40, 65, 0, 0, 30, 0, 162, 205, 0, 145, 184, + 0, 130, 164, 0, 114, 143, 0, 97, 124, 0, 81, 104, 0, 63, 83, + 0, 40, 58, 0, 0, 23, 0, 162, 187, 0, 145, 167, 0, 130, 150, + 0, 113, 131, 0, 96, 112, 0, 80, 93, 0, 62, 74, 0, 40, 50, + 0, 0, 16, 0, 160, 167, 0, 144, 150, 0, 129, 134, 0, 112, 116, + 0, 96, 100, 0, 80, 82, 0, 62, 65, 0, 40, 43, 0, 0, 7, + 0, 160, 148, 0, 143, 133, 0, 128, 118, 0, 111, 103, 0, 96, 88, + 0, 80, 73, 0, 62, 56, 0, 40, 35, 0, 0, 0, 0, 158, 130, + 0, 142, 117, 0, 127, 104, 0, 111, 89, 0, 95, 76, 0, 79, 62, + 0, 62, 46, 0, 40, 26, 0, 0, 0, 0, 158, 111, 0, 141, 99, + 0, 127, 88, 0, 111, 76, 0, 95, 63, 0, 79, 51, 0, 62, 37, + 0, 40, 18, 0, 0, 0, 0, 158, 91, 0, 141, 81, 0, 126, 72, + 0, 110, 62, 0, 94, 50, 0, 79, 39, 0, 62, 25, 0, 40, 5, + 0, 0, 0, 0, 157, 74, 0, 141, 66, 0, 126, 59, 0, 110, 49, + 0, 94, 40, 0, 78, 29, 0, 61, 15, 0, 40, 0, 0, 0, 0, + 0, 148, 214, 0, 133, 192, 0, 119, 171, 0, 103, 150, 0, 87, 129, + 0, 72, 108, 0, 55, 86, 0, 32, 61, 0, 0, 25, 0, 147, 193, + 0, 132, 173, 0, 118, 155, 0, 103, 136, 0, 87, 116, 0, 72, 98, + 0, 55, 78, 0, 32, 53, 0, 0, 17, 0, 147, 176, 0, 132, 158, + 0, 118, 142, 0, 102, 124, 0, 87, 106, 0, 72, 88, 0, 55, 69, + 0, 33, 46, 0, 0, 9, 0, 146, 159, 0, 131, 142, 0, 117, 127, + 0, 102, 111, 0, 87, 95, 0, 71, 79, 0, 55, 61, 0, 33, 39, + 0, 0, 2, 0, 145, 140, 0, 130, 126, 0, 117, 112, 0, 101, 98, + 0, 86, 83, 0, 71, 68, 0, 55, 52, 0, 33, 31, 0, 0, 0, + 0, 144, 124, 0, 130, 111, 0, 116, 99, 0, 101, 84, 0, 86, 72, + 0, 71, 59, 0, 55, 43, 0, 33, 23, 0, 0, 0, 0, 144, 106, + 0, 129, 94, 0, 115, 83, 0, 101, 72, 0, 85, 60, 0, 71, 48, + 0, 55, 34, 0, 33, 14, 0, 0, 0, 3, 143, 86, 0, 129, 77, + 0, 115, 68, 0, 100, 58, 0, 85, 48, 0, 70, 36, 0, 54, 22, + 0, 33, 3, 0, 0, 0, 18, 143, 72, 13, 128, 63, 0, 115, 57, + 0, 100, 47, 0, 85, 37, 0, 70, 26, 0, 54, 13, 0, 33, 0, + 0, 0, 0, 0, 132, 200, 0, 118, 179, 0, 105, 161, 0, 91, 140, + 0, 76, 121, 0, 62, 101, 0, 46, 81, 0, 24, 56, 0, 0, 19, + 0, 131, 182, 0, 118, 163, 0, 105, 146, 0, 91, 128, 0, 77, 110, + 0, 62, 91, 0, 46, 72, 0, 25, 48, 0, 0, 11, 0, 131, 165, + 0, 117, 149, 0, 104, 133, 0, 91, 116, 0, 77, 99, 0, 62, 82, + 0, 46, 64, 0, 25, 41, 0, 0, 4, 0, 131, 149, 0, 116, 134, + 0, 104, 119, 0, 91, 104, 0, 77, 89, 0, 62, 73, 0, 46, 56, + 0, 25, 34, 0, 0, 0, 10, 130, 133, 2, 116, 119, 0, 104, 106, + 0, 90, 91, 0, 76, 78, 0, 62, 64, 0, 46, 48, 0, 26, 27, + 0, 0, 0, 23, 130, 118, 20, 116, 104, 13, 103, 93, 3, 89, 79, + 0, 76, 67, 0, 62, 54, 0, 46, 39, 0, 26, 19, 0, 0, 0, + 33, 129, 101, 27, 115, 89, 19, 103, 79, 9, 89, 67, 0, 75, 56, + 0, 61, 43, 0, 46, 29, 0, 26, 10, 0, 0, 0, 41, 128, 83, + 35, 115, 73, 27, 102, 64, 15, 89, 55, 0, 76, 45, 0, 62, 33, + 0, 46, 18, 0, 26, 0, 0, 0, 0, 43, 129, 69, 38, 115, 61, + 30, 102, 54, 17, 89, 45, 2, 75, 34, 0, 61, 23, 0, 46, 9, + 0, 26, 0, 0, 0, 0, 1, 116, 188, 1, 104, 168, 0, 92, 151, + 0, 79, 132, 0, 66, 113, 0, 52, 94, 0, 36, 75, 0, 14, 52, + 0, 0, 14, 17, 116, 171, 16, 104, 153, 14, 92, 137, 8, 79, 119, + 0, 67, 102, 0, 53, 85, 0, 37, 67, 0, 16, 44, 0, 0, 4, + 31, 116, 155, 27, 104, 140, 21, 92, 125, 13, 79, 109, 3, 66, 93, + 0, 53, 77, 0, 37, 59, 0, 16, 38, 0, 0, 0, 37, 115, 141, + 30, 103, 126, 26, 92, 112, 16, 79, 98, 5, 66, 83, 0, 53, 67, + 0, 38, 51, 0, 17, 31, 0, 0, 0, 41, 115, 126, 37, 103, 112, + 31, 92, 100, 22, 79, 86, 10, 66, 72, 0, 53, 59, 0, 38, 44, + 0, 17, 23, 0, 0, 0, 48, 115, 111, 41, 102, 99, 34, 91, 88, + 24, 78, 76, 14, 66, 63, 0, 53, 50, 0, 38, 36, 0, 18, 15, + 0, 0, 0, 51, 115, 95, 46, 102, 85, 37, 91, 74, 26, 78, 63, + 16, 66, 52, 0, 53, 40, 0, 38, 26, 0, 18, 5, 0, 0, 0, + 55, 114, 80, 47, 102, 69, 40, 90, 60, 30, 78, 51, 19, 66, 41, + 3, 53, 29, 0, 38, 15, 0, 17, 0, 0, 0, 0, 56, 114, 66, + 50, 102, 58, 40, 91, 50, 32, 78, 41, 18, 66, 32, 4, 53, 21, + 0, 38, 5, 0, 17, 0, 0, 0, 0, 39, 102, 178, 37, 90, 159, + 30, 79, 142, 21, 68, 124, 14, 55, 106, 0, 42, 89, 0, 26, 70, + 0, 4, 46, 0, 0, 8, 48, 102, 161, 42, 90, 145, 35, 79, 128, + 26, 68, 112, 19, 55, 96, 3, 43, 79, 0, 27, 62, 0, 6, 40, + 0, 0, 0, 50, 102, 147, 44, 90, 132, 37, 79, 118, 30, 68, 102, + 20, 56, 87, 7, 43, 72, 0, 28, 55, 0, 6, 34, 0, 0, 0, + 53, 101, 133, 47, 90, 118, 41, 79, 106, 32, 68, 91, 21, 56, 78, + 9, 43, 63, 0, 28, 47, 0, 6, 26, 0, 0, 0, 57, 101, 119, + 50, 89, 106, 42, 79, 94, 34, 67, 81, 24, 56, 68, 9, 44, 55, + 0, 29, 40, 0, 6, 19, 0, 0, 0, 60, 100, 105, 50, 90, 94, + 45, 80, 83, 36, 68, 71, 24, 56, 59, 11, 44, 46, 0, 29, 32, + 0, 7, 12, 0, 0, 0, 63, 101, 91, 55, 90, 80, 46, 79, 70, + 37, 68, 59, 26, 56, 49, 12, 44, 37, 1, 29, 23, 0, 7, 3, + 0, 0, 0, 64, 101, 75, 56, 89, 67, 48, 79, 57, 37, 68, 48, + 27, 56, 37, 15, 44, 26, 0, 29, 12, 0, 7, 0, 0, 0, 0, + 66, 101, 64, 58, 89, 55, 49, 79, 47, 39, 68, 38, 27, 56, 29, + 14, 44, 18, 1, 30, 2, 0, 7, 0, 0, 0, 0, 57, 86, 165, + 51, 75, 148, 45, 65, 133, 38, 54, 116, 28, 43, 100, 16, 29, 83, + 0, 13, 64, 0, 0, 42, 0, 0, 3, 60, 86, 151, 55, 75, 135, + 47, 66, 121, 39, 55, 105, 30, 44, 90, 18, 31, 74, 3, 16, 57, + 0, 1, 35, 0, 0, 0, 62, 86, 139, 56, 75, 123, 49, 66, 110, + 40, 55, 95, 30, 44, 81, 19, 31, 66, 4, 17, 51, 0, 1, 29, + 0, 0, 0, 65, 86, 125, 56, 76, 112, 49, 66, 99, 39, 55, 86, + 31, 44, 72, 19, 32, 59, 5, 18, 44, 0, 1, 23, 0, 0, 0, + 67, 86, 113, 58, 75, 100, 51, 66, 88, 41, 56, 77, 31, 45, 64, + 20, 32, 51, 6, 18, 35, 0, 1, 14, 0, 0, 0, 69, 86, 99, + 61, 76, 88, 52, 66, 78, 43, 56, 66, 32, 45, 55, 20, 33, 42, + 7, 19, 27, 0, 1, 6, 0, 0, 0, 69, 86, 86, 61, 76, 75, + 53, 67, 66, 43, 56, 55, 33, 45, 45, 21, 34, 34, 8, 20, 20, + 0, 2, 2, 0, 0, 0, 71, 86, 72, 63, 75, 62, 54, 66, 55, + 45, 56, 45, 33, 45, 35, 22, 34, 23, 7, 20, 8, 0, 2, 0, + 0, 0, 0, 71, 86, 62, 64, 75, 53, 55, 66, 46, 45, 56, 36, + 33, 46, 27, 22, 34, 15, 8, 20, 0, 0, 2, 0, 0, 0, 0, + 69, 67, 156, 61, 58, 140, 53, 50, 125, 45, 39, 108, 35, 28, 93, + 25, 12, 77, 12, 0, 59, 0, 0, 37, 0, 0, 0, 71, 68, 142, + 63, 59, 126, 56, 50, 114, 47, 40, 98, 37, 28, 84, 26, 15, 68, + 12, 0, 53, 0, 0, 30, 0, 0, 0, 72, 68, 130, 63, 59, 116, + 56, 50, 104, 47, 40, 90, 38, 30, 75, 27, 16, 61, 13, 0, 46, + 0, 0, 24, 0, 0, 0, 73, 69, 118, 65, 59, 105, 57, 51, 92, + 47, 41, 80, 37, 30, 67, 26, 18, 53, 14, 1, 39, 0, 0, 18, + 0, 0, 0, 74, 69, 106, 65, 60, 93, 57, 51, 82, 48, 41, 70, + 38, 31, 59, 26, 19, 46, 13, 2, 32, 0, 0, 10, 0, 0, 0, + 76, 69, 95, 66, 61, 84, 58, 52, 73, 48, 42, 61, 37, 32, 50, + 26, 20, 38, 14, 4, 24, 0, 0, 4, 0, 0, 0, 76, 69, 81, + 68, 60, 72, 58, 52, 62, 48, 42, 51, 38, 32, 41, 27, 21, 30, + 14, 4, 16, 0, 0, 1, 0, 0, 0, 76, 69, 68, 68, 61, 60, + 60, 52, 51, 49, 43, 41, 38, 33, 32, 27, 21, 20, 14, 5, 5, + 0, 0, 0, 0, 0, 0, 78, 70, 59, 69, 61, 50, 60, 52, 42, + 49, 43, 34, 39, 33, 24, 27, 22, 13, 14, 7, 1, 0, 0, 0, + 0, 0, 0, 75, 46, 146, 68, 38, 131, 60, 30, 117, 50, 19, 102, + 41, 4, 87, 29, 0, 72, 13, 0, 55, 0, 0, 33, 0, 0, 0, + 78, 47, 132, 70, 39, 119, 61, 30, 105, 53, 20, 92, 42, 5, 78, + 30, 0, 64, 13, 0, 49, 0, 0, 27, 0, 0, 0, 79, 48, 122, + 70, 40, 108, 62, 32, 96, 52, 22, 84, 42, 9, 71, 30, 0, 58, + 14, 0, 42, 0, 0, 20, 0, 0, 0, 79, 50, 111, 70, 42, 99, + 62, 33, 88, 52, 23, 74, 41, 11, 63, 29, 0, 50, 14, 0, 36, + 0, 0, 14, 0, 0, 0, 80, 50, 99, 70, 42, 89, 61, 34, 78, + 52, 25, 67, 41, 14, 55, 30, 0, 42, 15, 0, 28, 0, 0, 6, + 0, 0, 0, 81, 51, 89, 71, 43, 78, 62, 35, 69, 52, 25, 58, + 42, 15, 47, 30, 3, 36, 15, 0, 22, 0, 0, 3, 0, 0, 0, + 81, 51, 77, 71, 44, 68, 63, 36, 59, 53, 26, 49, 41, 16, 38, + 31, 4, 27, 16, 0, 12, 0, 0, 0, 0, 0, 0, 81, 52, 65, + 72, 43, 56, 63, 36, 48, 53, 27, 39, 41, 17, 29, 30, 4, 18, + 14, 0, 3, 0, 0, 0, 0, 0, 0, 81, 52, 55, 73, 44, 47, + 64, 36, 39, 53, 28, 32, 42, 18, 21, 31, 6, 9, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 174, 239, 0, 156, 214, 0, 139, 192, + 0, 121, 168, 0, 105, 145, 0, 87, 123, 0, 68, 98, 0, 46, 70, + 0, 3, 35, 0, 172, 217, 0, 155, 194, 0, 139, 173, 0, 121, 152, + 0, 104, 130, 0, 87, 110, 0, 69, 88, 0, 46, 63, 0, 4, 28, + 0, 171, 197, 0, 153, 175, 0, 138, 158, 0, 121, 139, 0, 103, 118, + 0, 86, 100, 0, 68, 79, 0, 46, 55, 0, 4, 22, 0, 170, 177, + 0, 152, 158, 0, 136, 141, 0, 119, 124, 0, 103, 106, 0, 86, 88, + 0, 68, 70, 0, 45, 47, 0, 3, 14, 0, 169, 157, 0, 152, 141, + 0, 136, 126, 0, 119, 109, 0, 102, 94, 0, 86, 78, 0, 68, 60, + 0, 46, 39, 0, 3, 5, 0, 167, 138, 0, 150, 124, 0, 135, 111, + 0, 118, 97, 0, 102, 82, 0, 85, 68, 0, 68, 52, 0, 46, 31, + 0, 3, 0, 0, 167, 118, 0, 150, 104, 0, 135, 94, 0, 118, 81, + 0, 101, 69, 0, 84, 56, 0, 67, 41, 0, 45, 21, 0, 3, 0, + 0, 166, 97, 0, 149, 87, 0, 134, 77, 0, 117, 67, 0, 101, 56, + 0, 85, 44, 0, 67, 30, 0, 45, 10, 0, 3, 0, 0, 165, 79, + 0, 149, 73, 0, 133, 64, 0, 117, 56, 0, 101, 46, 0, 85, 34, + 0, 68, 21, 0, 46, 1, 0, 3, 0, 0, 158, 225, 0, 141, 201, + 0, 126, 180, 0, 109, 158, 0, 94, 136, 0, 78, 114, 0, 60, 91, + 0, 38, 66, 0, 0, 30, 0, 156, 203, 0, 140, 183, 0, 125, 164, + 0, 109, 143, 0, 94, 124, 0, 78, 104, 0, 61, 83, 0, 38, 57, + 0, 0, 23, 0, 156, 186, 0, 140, 166, 0, 125, 150, 0, 109, 130, + 0, 93, 111, 0, 77, 93, 0, 60, 74, 0, 38, 50, 0, 0, 17, + 0, 155, 167, 0, 138, 149, 0, 124, 134, 0, 109, 117, 0, 93, 100, + 0, 76, 83, 0, 60, 65, 0, 38, 43, 0, 0, 9, 0, 153, 147, + 0, 138, 134, 0, 124, 120, 0, 107, 103, 0, 92, 88, 0, 77, 73, + 0, 60, 56, 0, 38, 35, 0, 0, 0, 0, 153, 131, 0, 137, 118, + 0, 122, 105, 0, 107, 90, 0, 91, 76, 0, 76, 63, 0, 60, 47, + 0, 39, 28, 0, 0, 0, 0, 153, 111, 0, 136, 100, 0, 123, 90, + 0, 107, 77, 0, 92, 65, 0, 76, 52, 0, 60, 37, 0, 38, 18, + 0, 0, 0, 0, 152, 93, 0, 136, 82, 0, 122, 74, 0, 106, 63, + 0, 91, 52, 0, 76, 40, 0, 59, 26, 0, 38, 6, 0, 0, 0, + 0, 151, 78, 0, 136, 69, 0, 121, 61, 0, 106, 52, 0, 91, 43, + 0, 76, 32, 0, 59, 17, 0, 38, 0, 0, 0, 0, 0, 143, 213, + 0, 128, 191, 0, 115, 171, 0, 100, 149, 0, 84, 128, 0, 69, 108, + 0, 52, 86, 0, 30, 61, 0, 0, 25, 0, 142, 193, 0, 127, 173, + 0, 114, 154, 0, 99, 134, 0, 84, 116, 0, 69, 98, 0, 52, 77, + 0, 31, 53, 0, 0, 18, 0, 141, 176, 0, 127, 158, 0, 114, 141, + 0, 98, 122, 0, 84, 105, 0, 69, 88, 0, 53, 69, 0, 31, 46, + 0, 0, 9, 0, 141, 159, 0, 126, 142, 0, 113, 127, 0, 98, 110, + 0, 83, 95, 0, 69, 78, 0, 53, 60, 0, 32, 39, 0, 0, 2, + 0, 140, 140, 0, 126, 126, 0, 112, 112, 0, 98, 98, 0, 83, 83, + 0, 68, 69, 0, 52, 52, 0, 31, 31, 0, 0, 0, 0, 140, 124, + 0, 125, 112, 0, 112, 100, 0, 97, 86, 0, 83, 72, 0, 68, 59, + 0, 52, 44, 0, 31, 23, 0, 0, 0, 0, 139, 106, 0, 125, 96, + 0, 111, 85, 0, 97, 72, 0, 83, 62, 0, 68, 49, 0, 52, 35, + 0, 31, 15, 0, 0, 0, 0, 138, 88, 0, 124, 79, 0, 111, 70, + 0, 96, 59, 0, 82, 48, 0, 68, 38, 0, 52, 24, 0, 31, 4, + 0, 0, 0, 0, 139, 76, 0, 124, 66, 0, 111, 58, 0, 96, 50, + 0, 82, 40, 0, 68, 29, 0, 52, 15, 0, 31, 0, 0, 0, 0, + 0, 129, 200, 0, 114, 179, 0, 102, 160, 0, 87, 139, 0, 74, 120, + 0, 60, 101, 0, 44, 81, 0, 22, 56, 0, 0, 19, 0, 127, 181, + 0, 114, 163, 0, 102, 146, 0, 88, 127, 0, 74, 109, 0, 60, 91, + 0, 44, 72, 0, 23, 48, 0, 0, 11, 0, 127, 166, 0, 113, 148, + 0, 101, 133, 0, 87, 115, 0, 74, 99, 0, 60, 82, 0, 44, 64, + 0, 23, 42, 0, 0, 4, 0, 127, 150, 0, 113, 134, 0, 101, 119, + 0, 87, 104, 0, 74, 89, 0, 60, 73, 0, 44, 56, 0, 23, 35, + 0, 0, 0, 0, 125, 134, 0, 112, 118, 0, 100, 106, 0, 87, 92, + 0, 73, 78, 0, 60, 64, 0, 44, 48, 0, 23, 27, 0, 0, 0, + 0, 125, 118, 0, 112, 105, 0, 100, 94, 0, 86, 80, 0, 73, 68, + 0, 60, 54, 0, 44, 39, 0, 23, 20, 0, 0, 0, 0, 125, 101, + 0, 111, 90, 0, 99, 80, 0, 86, 69, 0, 73, 58, 0, 59, 45, + 0, 44, 30, 0, 23, 11, 0, 0, 0, 0, 124, 85, 0, 111, 75, + 0, 99, 66, 0, 86, 56, 0, 73, 45, 0, 59, 34, 0, 44, 20, + 0, 23, 1, 0, 0, 0, 0, 125, 72, 0, 111, 62, 0, 99, 56, + 0, 86, 46, 0, 73, 36, 0, 60, 26, 0, 44, 12, 0, 23, 0, + 0, 0, 0, 0, 114, 188, 0, 101, 167, 0, 89, 150, 0, 77, 131, + 0, 64, 113, 0, 50, 95, 0, 34, 75, 0, 12, 52, 0, 0, 14, + 0, 113, 170, 0, 101, 153, 0, 89, 137, 0, 77, 120, 0, 64, 102, + 0, 50, 85, 0, 35, 67, 0, 12, 44, 0, 0, 4, 0, 113, 156, + 0, 100, 139, 0, 89, 125, 0, 77, 109, 0, 64, 92, 0, 51, 77, + 0, 35, 60, 0, 12, 38, 0, 0, 0, 0, 112, 141, 0, 100, 126, + 0, 89, 113, 0, 77, 98, 0, 64, 83, 0, 51, 68, 0, 35, 51, + 0, 12, 30, 0, 0, 0, 0, 112, 127, 0, 100, 112, 0, 89, 100, + 0, 76, 87, 0, 64, 74, 0, 51, 59, 0, 35, 44, 0, 13, 24, + 0, 0, 0, 0, 112, 111, 0, 100, 100, 0, 88, 88, 0, 76, 76, + 0, 64, 64, 0, 51, 52, 0, 36, 37, 0, 13, 17, 0, 0, 0, + 0, 111, 96, 0, 99, 85, 0, 88, 76, 0, 76, 64, 0, 64, 53, + 0, 51, 41, 0, 36, 27, 0, 13, 6, 0, 0, 0, 0, 111, 81, + 0, 99, 71, 0, 88, 62, 0, 76, 52, 0, 64, 43, 0, 51, 31, + 0, 36, 17, 0, 13, 0, 0, 0, 0, 0, 111, 69, 0, 99, 60, + 0, 88, 52, 0, 75, 43, 0, 63, 34, 0, 51, 21, 0, 36, 7, + 0, 13, 0, 0, 0, 0, 0, 99, 177, 0, 88, 158, 0, 77, 141, + 0, 66, 123, 0, 53, 106, 0, 40, 89, 0, 25, 71, 0, 5, 47, + 0, 0, 8, 0, 99, 160, 0, 88, 144, 0, 77, 129, 0, 66, 112, + 0, 54, 97, 0, 41, 80, 0, 26, 62, 0, 5, 40, 0, 0, 0, + 0, 99, 147, 0, 87, 132, 0, 78, 117, 0, 66, 102, 0, 54, 87, + 0, 42, 72, 0, 26, 55, 0, 5, 34, 0, 0, 0, 0, 99, 134, + 0, 88, 119, 0, 77, 107, 0, 66, 92, 0, 54, 78, 0, 42, 64, + 0, 27, 48, 0, 5, 27, 0, 0, 0, 0, 99, 120, 0, 87, 107, + 0, 78, 94, 0, 66, 81, 0, 54, 68, 0, 42, 55, 0, 27, 40, + 0, 6, 20, 0, 0, 0, 0, 98, 105, 0, 87, 94, 0, 77, 84, + 0, 65, 71, 0, 55, 59, 0, 42, 47, 0, 28, 33, 0, 6, 12, + 0, 0, 0, 0, 98, 93, 0, 87, 81, 0, 77, 72, 0, 66, 61, + 0, 54, 49, 0, 42, 37, 0, 28, 24, 0, 6, 4, 0, 0, 0, + 0, 98, 77, 0, 87, 68, 0, 77, 59, 0, 65, 49, 0, 54, 39, + 0, 42, 27, 0, 29, 14, 0, 6, 0, 0, 0, 0, 1, 98, 65, + 7, 87, 56, 0, 77, 49, 0, 66, 41, 0, 54, 30, 0, 42, 19, + 0, 29, 3, 0, 6, 0, 0, 0, 0, 0, 84, 166, 0, 74, 149, + 0, 64, 134, 0, 53, 117, 0, 41, 100, 0, 28, 83, 0, 11, 64, + 0, 0, 42, 0, 0, 3, 0, 84, 151, 0, 74, 135, 0, 64, 121, + 0, 53, 105, 0, 42, 90, 0, 30, 75, 0, 14, 58, 0, 0, 36, + 0, 0, 0, 0, 84, 138, 0, 74, 124, 1, 64, 110, 0, 54, 95, + 0, 43, 81, 0, 30, 67, 0, 15, 51, 0, 1, 29, 0, 0, 0, + 14, 84, 126, 12, 74, 112, 2, 65, 99, 0, 54, 85, 0, 44, 73, + 0, 31, 59, 0, 16, 44, 0, 1, 23, 0, 0, 0, 16, 84, 113, + 13, 74, 100, 6, 65, 89, 0, 54, 77, 0, 44, 65, 0, 31, 51, + 0, 17, 36, 0, 1, 16, 0, 0, 0, 24, 84, 100, 18, 74, 88, + 13, 65, 78, 2, 55, 68, 0, 44, 55, 0, 32, 43, 0, 18, 28, + 0, 1, 6, 0, 0, 0, 26, 84, 87, 24, 74, 76, 17, 65, 67, + 7, 54, 57, 0, 44, 46, 0, 32, 35, 0, 19, 21, 0, 2, 3, + 0, 0, 0, 30, 84, 74, 28, 74, 64, 20, 65, 55, 12, 55, 46, + 0, 44, 35, 0, 32, 24, 0, 18, 9, 0, 1, 0, 0, 0, 0, + 32, 84, 63, 28, 74, 54, 21, 65, 47, 13, 54, 38, 0, 44, 28, + 0, 32, 16, 0, 18, 1, 0, 1, 0, 0, 0, 0, 30, 67, 155, + 20, 58, 139, 20, 49, 126, 12, 39, 110, 0, 27, 94, 0, 13, 77, + 0, 0, 60, 0, 0, 37, 0, 0, 0, 35, 67, 142, 30, 58, 126, + 23, 50, 114, 16, 40, 99, 7, 29, 85, 0, 15, 69, 0, 0, 52, + 0, 0, 30, 0, 0, 0, 35, 68, 131, 30, 59, 116, 27, 50, 104, + 18, 40, 90, 9, 29, 76, 0, 17, 62, 0, 2, 46, 0, 0, 24, + 0, 0, 0, 37, 69, 119, 33, 59, 106, 27, 51, 94, 21, 41, 80, + 9, 30, 67, 0, 18, 54, 0, 3, 39, 0, 0, 18, 0, 0, 0, + 40, 69, 107, 36, 59, 94, 28, 51, 84, 18, 41, 72, 10, 31, 60, + 0, 19, 47, 0, 4, 32, 0, 0, 10, 0, 0, 0, 42, 69, 95, + 36, 59, 84, 29, 51, 74, 19, 41, 63, 10, 31, 52, 0, 20, 39, + 0, 4, 25, 0, 0, 4, 0, 0, 0, 43, 69, 83, 38, 60, 73, + 32, 51, 62, 23, 42, 53, 11, 31, 42, 0, 20, 31, 0, 5, 17, + 0, 0, 1, 0, 0, 0, 45, 69, 70, 39, 60, 60, 33, 51, 52, + 24, 42, 43, 13, 32, 33, 0, 21, 21, 0, 5, 6, 0, 0, 0, + 0, 0, 0, 47, 69, 59, 41, 60, 51, 34, 51, 43, 24, 42, 35, + 12, 33, 26, 1, 22, 14, 0, 5, 1, 0, 0, 0, 0, 0, 0, + 46, 48, 146, 42, 40, 131, 36, 32, 118, 27, 22, 103, 17, 6, 88, + 5, 0, 73, 0, 0, 55, 0, 0, 33, 0, 0, 0, 48, 48, 133, + 44, 40, 119, 37, 32, 107, 28, 22, 93, 20, 8, 79, 7, 0, 65, + 0, 0, 49, 0, 0, 27, 0, 0, 0, 48, 50, 123, 44, 41, 109, + 37, 33, 97, 30, 23, 83, 21, 11, 71, 8, 0, 58, 0, 0, 42, + 0, 0, 21, 0, 0, 0, 49, 51, 111, 45, 42, 99, 38, 34, 87, + 29, 25, 75, 20, 13, 63, 8, 0, 51, 0, 0, 36, 0, 0, 14, + 0, 0, 0, 52, 52, 100, 44, 43, 89, 38, 35, 79, 29, 26, 68, + 19, 15, 56, 10, 1, 43, 0, 0, 28, 0, 0, 6, 0, 0, 0, + 52, 52, 90, 47, 44, 79, 39, 36, 70, 30, 27, 59, 20, 16, 47, + 9, 2, 36, 0, 0, 22, 0, 0, 2, 0, 0, 0, 52, 53, 78, + 46, 44, 68, 39, 37, 60, 32, 27, 49, 22, 17, 39, 10, 3, 28, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 53, 53, 66, 47, 44, 57, + 40, 36, 48, 32, 27, 39, 22, 18, 30, 9, 4, 18, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 54, 53, 57, 48, 45, 49, 41, 37, 41, + 33, 28, 32, 22, 19, 23, 11, 6, 10, 1, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +} // namespace + CCodec_ModuleMgr::CCodec_ModuleMgr() - : m_pBasicModule(new CCodec_BasicModule), - m_pFaxModule(new CCodec_FaxModule), - m_pJpegModule(new CCodec_JpegModule), - m_pJpxModule(new CCodec_JpxModule), - m_pJbig2Module(new CCodec_Jbig2Module), - m_pIccModule(new CCodec_IccModule), - m_pFlateModule(new CCodec_FlateModule) { -} + : m_pBasicModule(pdfium::MakeUnique()), + m_pFaxModule(pdfium::MakeUnique()), + m_pJpegModule(pdfium::MakeUnique()), + m_pJpxModule(pdfium::MakeUnique()), + m_pJbig2Module(pdfium::MakeUnique()), + m_pIccModule(pdfium::MakeUnique()), + m_pFlateModule(pdfium::MakeUnique()) {} CCodec_ModuleMgr::~CCodec_ModuleMgr() {} -CCodec_ScanlineDecoder::CCodec_ScanlineDecoder() - : CCodec_ScanlineDecoder(0, 0, 0, 0, 0, 0, 0) {} - -CCodec_ScanlineDecoder::CCodec_ScanlineDecoder(int nOrigWidth, - int nOrigHeight, - int nOutputWidth, - int nOutputHeight, - int nComps, - int nBpc, - uint32_t nPitch) - : m_OrigWidth(nOrigWidth), - m_OrigHeight(nOrigHeight), - m_OutputWidth(nOutputWidth), - m_OutputHeight(nOutputHeight), - m_nComps(nComps), - m_bpc(nBpc), - m_Pitch(nPitch), - m_NextLine(-1), - m_pLastScanline(nullptr) {} - -CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder() {} - -const uint8_t* CCodec_ScanlineDecoder::GetScanline(int line) { - if (m_NextLine == line + 1) - return m_pLastScanline; - - if (m_NextLine < 0 || m_NextLine > line) { - if (!v_Rewind()) - return nullptr; - m_NextLine = 0; - } - while (m_NextLine < line) { - ReadNextLine(); - m_NextLine++; - } - m_pLastScanline = ReadNextLine(); - m_NextLine++; - return m_pLastScanline; +#ifdef PDF_ENABLE_XFA +void CCodec_ModuleMgr::SetBmpModule(std::unique_ptr module) { + m_pBmpModule = std::move(module); } -bool CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause) { - if (m_NextLine == line || m_NextLine == line + 1) - return false; +void CCodec_ModuleMgr::SetGifModule(std::unique_ptr module) { + m_pGifModule = std::move(module); +} - if (m_NextLine < 0 || m_NextLine > line) { - v_Rewind(); - m_NextLine = 0; - } - m_pLastScanline = nullptr; - while (m_NextLine < line) { - m_pLastScanline = ReadNextLine(); - m_NextLine++; - if (pPause && pPause->NeedToPauseNow()) { - return true; - } - } - return false; +void CCodec_ModuleMgr::SetPngModule(std::unique_ptr module) { + m_pPngModule = std::move(module); } -uint8_t* CCodec_ScanlineDecoder::ReadNextLine() { - return v_GetNextLine(); +void CCodec_ModuleMgr::SetTiffModule( + std::unique_ptr module) { + m_pTiffModule = std::move(module); } +#endif // PDF_ENABLE_XFA bool CCodec_BasicModule::RunLengthEncode(const uint8_t* src_buf, uint32_t src_size, @@ -253,9 +1544,8 @@ CFX_DIBAttribute::CFX_DIBAttribute() m_nGifTop(0), m_pGifLocalPalette(nullptr), m_nGifLocalPalNum(0), - m_nBmpCompressType(0) { - FXSYS_memset(m_strTime, 0, sizeof(m_strTime)); -} + m_nBmpCompressType(0) {} + CFX_DIBAttribute::~CFX_DIBAttribute() { for (const auto& pair : m_Exif) FX_Free(pair.second); @@ -361,7 +1651,7 @@ bool CCodec_RLScanlineDecoder::Create(const uint8_t* src_buf, return CheckDestSize(); } bool CCodec_RLScanlineDecoder::v_Rewind() { - FXSYS_memset(m_pScanline, 0, m_Pitch); + memset(m_pScanline, 0, m_Pitch); m_SrcOffset = 0; m_bEOD = false; m_Operator = 0; @@ -375,7 +1665,7 @@ uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() { return nullptr; } } - FXSYS_memset(m_pScanline, 0, m_Pitch); + memset(m_pScanline, 0, m_Pitch); uint32_t col_pos = 0; bool eol = false; while (m_SrcOffset < m_SrcSize && !eol) { @@ -389,7 +1679,7 @@ uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() { copy_len = m_SrcSize - m_SrcOffset; m_bEOD = true; } - FXSYS_memcpy(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len); + memcpy(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len); col_pos += copy_len; UpdateOperator((uint8_t)copy_len); } else if (m_Operator > 128) { @@ -402,7 +1692,7 @@ uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() { duplicate_len = m_dwLineBytes - col_pos; eol = true; } - FXSYS_memset(m_pScanline + col_pos, fill, duplicate_len); + memset(m_pScanline + col_pos, fill, duplicate_len); col_pos += duplicate_len; UpdateOperator((uint8_t)duplicate_len); } else { @@ -462,3 +1752,90 @@ CCodec_BasicModule::CreateRunLengthDecoder(const uint8_t* src_buf, return std::move(pDecoder); } + +std::tuple AdobeCMYK_to_sRGB1(uint8_t c, + uint8_t m, + uint8_t y, + uint8_t k) { + int fix_c = c << 8; + int fix_m = m << 8; + int fix_y = y << 8; + int fix_k = k << 8; + int c_index = (fix_c + 4096) >> 13; + int m_index = (fix_m + 4096) >> 13; + int y_index = (fix_y + 4096) >> 13; + int k_index = (fix_k + 4096) >> 13; + int pos = (c_index * 9 * 9 * 9 + m_index * 9 * 9 + y_index * 9 + k_index) * 3; + int fix_r = g_CMYK[pos] << 8; + int fix_g = g_CMYK[pos + 1] << 8; + int fix_b = g_CMYK[pos + 2] << 8; + int c1_index = fix_c >> 13; + if (c1_index == c_index) + c1_index = c1_index == 8 ? c1_index - 1 : c1_index + 1; + int m1_index = fix_m >> 13; + if (m1_index == m_index) + m1_index = m1_index == 8 ? m1_index - 1 : m1_index + 1; + int y1_index = fix_y >> 13; + if (y1_index == y_index) + y1_index = y1_index == 8 ? y1_index - 1 : y1_index + 1; + int k1_index = fix_k >> 13; + if (k1_index == k_index) + k1_index = k1_index == 8 ? k1_index - 1 : k1_index + 1; + int c1_pos = pos + (c1_index - c_index) * 9 * 9 * 9 * 3; + int m1_pos = pos + (m1_index - m_index) * 9 * 9 * 3; + int y1_pos = pos + (y1_index - y_index) * 9 * 3; + int k1_pos = pos + (k1_index - k_index) * 3; + int c_rate = (fix_c - (c_index << 13)) * (c_index - c1_index); + fix_r += (g_CMYK[pos] - g_CMYK[c1_pos]) * c_rate / 32; + fix_g += (g_CMYK[pos + 1] - g_CMYK[c1_pos + 1]) * c_rate / 32; + fix_b += (g_CMYK[pos + 2] - g_CMYK[c1_pos + 2]) * c_rate / 32; + int m_rate = (fix_m - (m_index << 13)) * (m_index - m1_index); + fix_r += (g_CMYK[pos] - g_CMYK[m1_pos]) * m_rate / 32; + fix_g += (g_CMYK[pos + 1] - g_CMYK[m1_pos + 1]) * m_rate / 32; + fix_b += (g_CMYK[pos + 2] - g_CMYK[m1_pos + 2]) * m_rate / 32; + int y_rate = (fix_y - (y_index << 13)) * (y_index - y1_index); + fix_r += (g_CMYK[pos] - g_CMYK[y1_pos]) * y_rate / 32; + fix_g += (g_CMYK[pos + 1] - g_CMYK[y1_pos + 1]) * y_rate / 32; + fix_b += (g_CMYK[pos + 2] - g_CMYK[y1_pos + 2]) * y_rate / 32; + int k_rate = (fix_k - (k_index << 13)) * (k_index - k1_index); + fix_r += (g_CMYK[pos] - g_CMYK[k1_pos]) * k_rate / 32; + fix_g += (g_CMYK[pos + 1] - g_CMYK[k1_pos + 1]) * k_rate / 32; + fix_b += (g_CMYK[pos + 2] - g_CMYK[k1_pos + 2]) * k_rate / 32; + fix_r = std::max(fix_r, 0); + fix_g = std::max(fix_g, 0); + fix_b = std::max(fix_b, 0); + return std::make_tuple(fix_r >> 8, fix_g >> 8, fix_b >> 8); +} + +std::tuple AdobeCMYK_to_sRGB(float c, + float m, + float y, + float k) { + // Convert to uint8_t with round-to-nearest. Avoid using FXSYS_round because + // it is incredibly expensive with VC++ (tested on VC++ 2015) because round() + // is very expensive. + // The 'magic' value of 0.49999997f, the float that precedes 0.5f, was chosen + // because it gives identical results to FXSYS_round(). Using the constant + // 0.5f gives different results (1 instead of 0) for one value, 0.0019607842. + // That value is close to the cusp but zero is the correct answer, and + // getting the same answer as before is desirable. + // All floats from 0.0 to 1.0 were tested and now give the same results. + const float rounding_offset = 0.49999997f; + uint8_t c1 = int(c * 255.f + rounding_offset); + uint8_t m1 = int(m * 255.f + rounding_offset); + uint8_t y1 = int(y * 255.f + rounding_offset); + uint8_t k1 = int(k * 255.f + rounding_offset); + + ASSERT(c1 == FXSYS_round(c * 255)); + ASSERT(m1 == FXSYS_round(m * 255)); + ASSERT(y1 == FXSYS_round(y * 255)); + ASSERT(k1 == FXSYS_round(k * 255)); + + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = AdobeCMYK_to_sRGB1(c1, m1, y1, k1); + // Multiply by a constant rather than dividing because division is much + // more expensive. + return std::make_tuple(r * (1.0f / 255), g * (1.0f / 255), b * (1.0f / 255)); +} diff --git a/core/fxcodec/codec/fx_codec_a85_unittest.cpp b/core/fxcodec/codec/fx_codec_a85_unittest.cpp index 78f9bd8fcca5bf3fdd9d1794fe4e62bb57f9aa3b..5e40548bf22f83b7fa64d844bc8bea9f5eb3be08 100644 --- a/core/fxcodec/codec/fx_codec_a85_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_a85_unittest.cpp @@ -8,7 +8,6 @@ #include "core/fxcodec/codec/ccodec_basicmodule.h" #include "core/fxcodec/fx_codec.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" TEST(fxcodec, A85TestBadInputs) { diff --git a/core/fxcodec/codec/fx_codec_fax.cpp b/core/fxcodec/codec/fx_codec_fax.cpp index 8a9c3efbc768d02f2aae8e17869c60a97af0e9d9..c800fda28367f8c562238246c3b1c8d7657c9f28 100644 --- a/core/fxcodec/codec/fx_codec_fax.cpp +++ b/core/fxcodec/codec/fx_codec_fax.cpp @@ -8,10 +8,13 @@ #include #include +#include "core/fxcodec/codec/ccodec_faxmodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" #include "core/fxcodec/codec/codec_int.h" -#include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/cfx_binarybuf.h" #include "core/fxcrt/fx_memory.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" namespace { @@ -104,7 +107,7 @@ void FaxG4FindB1B2(const std::vector& ref_buf, void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) { startpos = std::max(startpos, 0); - endpos = std::min(std::max(endpos, 0), columns); + endpos = pdfium::clamp(endpos, 0, columns); if (startpos >= endpos) return; @@ -122,7 +125,7 @@ void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) { dest_buf[last_byte] -= 1 << (7 - i); if (last_byte > first_byte + 1) - FXSYS_memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1); + memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1); } inline bool NextBit(const uint8_t* src_buf, int* bitpos) { @@ -266,14 +269,13 @@ int FaxGetRun(const uint8_t* ins_array, ++(*bitpos); int next_off = ins_off + ins * 3; for (; ins_off < next_off; ins_off += 3) { - if (ins_array[ins_off] == code) { + if (ins_array[ins_off] == code) return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256; - } } } } -bool FaxG4GetRow(const uint8_t* src_buf, +void FaxG4GetRow(const uint8_t* src_buf, int bitsize, int* bitpos, uint8_t* dest_buf, @@ -283,7 +285,7 @@ bool FaxG4GetRow(const uint8_t* src_buf, bool a0color = true; while (1) { if (*bitpos >= bitsize) - return false; + return; int a1; int a2; @@ -294,11 +296,11 @@ bool FaxG4GetRow(const uint8_t* src_buf, int v_delta = 0; if (!NextBit(src_buf, bitpos)) { if (*bitpos >= bitsize) - return false; + return; bool bit1 = NextBit(src_buf, bitpos); if (*bitpos >= bitsize) - return false; + return; bool bit2 = NextBit(src_buf, bitpos); if (bit1) { @@ -309,12 +311,13 @@ bool FaxG4GetRow(const uint8_t* src_buf, int run = FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize); run_len1 += run; - if (run < 64) { + if (run < 64) break; - } } if (a0 < 0) ++run_len1; + if (run_len1 < 0) + return; a1 = a0 + run_len1; if (!a0color) @@ -325,10 +328,11 @@ bool FaxG4GetRow(const uint8_t* src_buf, int run = FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns, src_buf, bitpos, bitsize); run_len2 += run; - if (run < 64) { + if (run < 64) break; - } } + if (run_len2 < 0) + return; a2 = a1 + run_len2; if (a0color) FaxFillBits(dest_buf, columns, a1, a2); @@ -337,47 +341,47 @@ bool FaxG4GetRow(const uint8_t* src_buf, if (a0 < columns) continue; - return true; + return; } else { if (*bitpos >= bitsize) - return false; + return; if (NextBit(src_buf, bitpos)) { if (!a0color) FaxFillBits(dest_buf, columns, a0, b2); if (b2 >= columns) - return true; + return; a0 = b2; continue; } if (*bitpos >= bitsize) - return false; + return; bool next_bit1 = NextBit(src_buf, bitpos); if (*bitpos >= bitsize) - return false; + return; bool next_bit2 = NextBit(src_buf, bitpos); if (next_bit1) { v_delta = next_bit2 ? 2 : -2; } else if (next_bit2) { if (*bitpos >= bitsize) - return false; + return; v_delta = NextBit(src_buf, bitpos) ? 3 : -3; } else { if (*bitpos >= bitsize) - return false; + return; if (NextBit(src_buf, bitpos)) { *bitpos += 3; continue; } *bitpos += 5; - return true; + return; } } } @@ -386,30 +390,29 @@ bool FaxG4GetRow(const uint8_t* src_buf, FaxFillBits(dest_buf, columns, a0, a1); if (a1 >= columns) - return true; + return; // The position of picture element must be monotonic increasing. if (a0 >= a1) - return false; + return; a0 = a1; a0color = !a0color; } } -bool FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) { +void FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) { int startbit = *bitpos; while (*bitpos < bitsize) { if (!NextBit(src_buf, bitpos)) continue; if (*bitpos - startbit <= 11) *bitpos = startbit; - return true; + return; } - return false; } -bool FaxGet1DLine(const uint8_t* src_buf, +void FaxGet1DLine(const uint8_t* src_buf, int bitsize, int* bitpos, std::vector* dest_buf, @@ -418,7 +421,7 @@ bool FaxGet1DLine(const uint8_t* src_buf, int startpos = 0; while (1) { if (*bitpos >= bitsize) - return false; + return; int run_len = 0; while (1) { @@ -427,14 +430,13 @@ bool FaxGet1DLine(const uint8_t* src_buf, if (run < 0) { while (*bitpos < bitsize) { if (NextBit(src_buf, bitpos)) - return true; + return; } - return false; + return; } run_len += run; - if (run < 64) { + if (run < 64) break; - } } if (!color) FaxFillBits(dest_buf->data(), columns, startpos, startpos + run_len); @@ -445,7 +447,6 @@ bool FaxGet1DLine(const uint8_t* src_buf, color = !color; } - return true; } } // namespace @@ -503,7 +504,7 @@ CCodec_FaxDecoder::CCodec_FaxDecoder(const uint8_t* src_buf, CCodec_FaxDecoder::~CCodec_FaxDecoder() {} bool CCodec_FaxDecoder::v_Rewind() { - FXSYS_memset(m_RefBuf.data(), 0xff, m_RefBuf.size()); + memset(m_RefBuf.data(), 0xff, m_RefBuf.size()); m_bitpos = 0; return true; } @@ -514,7 +515,7 @@ uint8_t* CCodec_FaxDecoder::v_GetNextLine() { if (m_bitpos >= bitsize) return nullptr; - FXSYS_memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size()); + memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size()); if (m_Encoding < 0) { FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf, m_OrigWidth); @@ -538,19 +539,17 @@ uint8_t* CCodec_FaxDecoder::v_GetNextLine() { int bitpos1 = (m_bitpos + 7) / 8 * 8; while (m_bByteAlign && bitpos0 < bitpos1) { int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8)); - if (bit != 0) { + if (bit != 0) m_bByteAlign = false; - } else { + else ++bitpos0; - } } if (m_bByteAlign) m_bitpos = bitpos1; } if (m_bBlack) { - for (uint32_t i = 0; i < m_Pitch; ++i) { + for (uint32_t i = 0; i < m_Pitch; ++i) m_ScanlineBuf[i] = ~m_ScanlineBuf[i]; - } } return m_ScanlineBuf.data(); } @@ -573,9 +572,9 @@ void FaxG4Decode(const uint8_t* src_buf, int bitpos = *pbitpos; for (int iRow = 0; iRow < height; iRow++) { uint8_t* line_buf = dest_buf + iRow * pitch; - FXSYS_memset(line_buf, 0xff, pitch); + memset(line_buf, 0xff, pitch); FaxG4GetRow(src_buf, src_size << 3, &bitpos, line_buf, ref_buf, width); - FXSYS_memcpy(ref_buf.data(), line_buf, pitch); + memcpy(ref_buf.data(), line_buf, pitch); } *pbitpos = bitpos; } @@ -608,7 +607,7 @@ std::unique_ptr CCodec_FaxModule::CreateDecoder( EncodedByteAlign, BlackIs1); } -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ namespace { const uint8_t BlackRunTerminator[128] = { 0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4, @@ -654,9 +653,8 @@ const uint8_t WhiteRunMarkup[80] = { void AddBitStream(uint8_t* dest_buf, int* dest_bitpos, int data, int bitlen) { for (int i = bitlen - 1; i >= 0; i--) { - if (data & (1 << i)) { + if (data & (1 << i)) dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8); - } (*dest_bitpos)++; } } @@ -726,16 +724,14 @@ void FaxEncode2DLine(uint8_t* dest_buf, (*dest_bitpos)++; dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8); (*dest_bitpos)++; - if (a0 < 0) { + if (a0 < 0) a0 = 0; - } FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color); FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, !a0color); a0 = a2; } - if (a0 >= cols) { + if (a0 >= cols) return; - } } } @@ -762,7 +758,7 @@ CCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf, int pitch) : m_Cols(width), m_Rows(height), m_Pitch(pitch), m_pSrcBuf(src_buf) { m_RefLine.resize(m_Pitch); - FXSYS_memset(m_RefLine.data(), 0xff, m_Pitch); + memset(m_RefLine.data(), 0xff, m_Pitch); m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8); m_DestBuf.EstimateSize(0, 10240); } @@ -778,17 +774,16 @@ void CCodec_FaxEncoder::Encode( uint8_t last_byte = 0; for (int i = 0; i < m_Rows; i++) { const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch; - FXSYS_memset(m_pLineBuf, 0, m_Pitch * 8); + memset(m_pLineBuf, 0, m_Pitch * 8); m_pLineBuf[0] = last_byte; FaxEncode2DLine(m_pLineBuf, &dest_bitpos, scan_line, m_RefLine, m_Cols); m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8); last_byte = m_pLineBuf[dest_bitpos / 8]; dest_bitpos %= 8; - FXSYS_memcpy(m_RefLine.data(), scan_line, m_Pitch); + memcpy(m_RefLine.data(), scan_line, m_Pitch); } - if (dest_bitpos) { + if (dest_bitpos) m_DestBuf.AppendByte(last_byte); - } *dest_size = m_DestBuf.GetSize(); *dest_buf = m_DestBuf.DetachBuffer(); } @@ -806,4 +801,4 @@ void CCodec_FaxModule::FaxEncode( encoder.Encode(dest_buf, dest_size); } -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ diff --git a/core/fxcodec/codec/fx_codec_flate.cpp b/core/fxcodec/codec/fx_codec_flate.cpp index 3cffc0b7cf3023b9af3f1f589db6cfc443c166ba..95902bb699225d3f4b01b29c6bf4b2d4334e02f2 100644 --- a/core/fxcodec/codec/fx_codec_flate.cpp +++ b/core/fxcodec/codec/fx_codec_flate.cpp @@ -11,85 +11,94 @@ #include #include -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcodec/codec/ccodec_flatemodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/numerics/safe_conversions.h" #include "third_party/base/ptr_util.h" -#include "third_party/zlib_v128/zlib.h" + +#if defined(USE_SYSTEM_ZLIB) +#include +#else +#include "third_party/zlib/zlib.h" +#endif extern "C" { + static void* my_alloc_func(void* opaque, unsigned int items, unsigned int size) { return FX_Alloc2D(uint8_t, items, size); } + static void my_free_func(void* opaque, void* address) { FX_Free(address); } -static int FPDFAPI_FlateGetTotalOut(void* context) { - return ((z_stream*)context)->total_out; + +} // extern "C" + +namespace { + +uint32_t FlateGetPossiblyTruncatedTotalOut(void* context) { + return pdfium::base::saturated_cast( + static_cast(context)->total_out); } -static int FPDFAPI_FlateGetTotalIn(void* context) { - return ((z_stream*)context)->total_in; + +uint32_t FlateGetPossiblyTruncatedTotalIn(void* context) { + return pdfium::base::saturated_cast( + static_cast(context)->total_in); } -static bool FPDFAPI_FlateCompress(unsigned char* dest_buf, - unsigned long* dest_size, - const unsigned char* src_buf, - unsigned long src_size) { +bool FlateCompress(unsigned char* dest_buf, + unsigned long* dest_size, + const unsigned char* src_buf, + uint32_t src_size) { return compress(dest_buf, dest_size, src_buf, src_size) == Z_OK; } -void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int), - void (*free_func)(void*, void*)) { - z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream)); - if (!p) - return nullptr; - - FXSYS_memset(p, 0, sizeof(z_stream)); - p->zalloc = alloc_func; - p->zfree = free_func; +void* FlateInit() { + z_stream* p = FX_Alloc(z_stream, 1); + memset(p, 0, sizeof(z_stream)); + p->zalloc = my_alloc_func; + p->zfree = my_free_func; inflateInit(p); return p; } -void FPDFAPI_FlateInput(void* context, - const unsigned char* src_buf, - unsigned int src_size) { - ((z_stream*)context)->next_in = (unsigned char*)src_buf; - ((z_stream*)context)->avail_in = src_size; +void FlateInput(void* context, + const unsigned char* src_buf, + uint32_t src_size) { + static_cast(context)->next_in = + const_cast(src_buf); + static_cast(context)->avail_in = src_size; } -int FPDFAPI_FlateOutput(void* context, - unsigned char* dest_buf, - unsigned int dest_size) { - ((z_stream*)context)->next_out = dest_buf; - ((z_stream*)context)->avail_out = dest_size; - unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); - int ret = inflate((z_stream*)context, Z_SYNC_FLUSH); - unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); - unsigned int written = post_pos - pre_pos; - if (written < dest_size) { - FXSYS_memset(dest_buf + written, '\0', dest_size - written); - } - return ret; -} +uint32_t FlateOutput(void* context, + unsigned char* dest_buf, + uint32_t dest_size) { + static_cast(context)->next_out = dest_buf; + static_cast(context)->avail_out = dest_size; + uint32_t pre_pos = FlateGetPossiblyTruncatedTotalOut(context); + int ret = inflate(static_cast(context), Z_SYNC_FLUSH); -int FPDFAPI_FlateGetAvailIn(void* context) { - return ((z_stream*)context)->avail_in; -} + uint32_t post_pos = FlateGetPossiblyTruncatedTotalOut(context); + ASSERT(post_pos >= pre_pos); -int FPDFAPI_FlateGetAvailOut(void* context) { - return ((z_stream*)context)->avail_out; -} + uint32_t written = post_pos - pre_pos; + if (written < dest_size) + memset(dest_buf + written, '\0', dest_size - written); -void FPDFAPI_FlateEnd(void* context) { - inflateEnd((z_stream*)context); - ((z_stream*)context)->zfree(0, context); + return ret; } -} // extern "C" +uint32_t FlateGetAvailOut(void* context) { + return static_cast(context)->avail_out; +} -namespace { +void FlateEnd(void* context) { + inflateEnd(static_cast(context)); + static_cast(context)->zfree(0, context); +} class CLZWDecoder { public: @@ -158,7 +167,7 @@ int CLZWDecoder::Decode(uint8_t* dest_buf, m_pOutput = dest_buf; m_Early = bEarlyChange ? 1 : 0; m_nCodes = 0; - uint32_t old_code = (uint32_t)-1; + uint32_t old_code = 0xFFFFFFFF; uint8_t last_char = 0; while (1) { if (m_InPos + m_CodeLen > src_size * 8) { @@ -181,6 +190,8 @@ int CLZWDecoder::Decode(uint8_t* dest_buf, } } m_InPos += m_CodeLen; + if (code == 257) + break; if (code < 256) { if (m_OutPos == dest_size) { return -5; @@ -190,20 +201,18 @@ int CLZWDecoder::Decode(uint8_t* dest_buf, } m_OutPos++; last_char = (uint8_t)code; - if (old_code != (uint32_t)-1) { + if (old_code != 0xFFFFFFFF) AddCode(old_code, last_char); - } old_code = code; } else if (code == 256) { m_CodeLen = 9; m_nCodes = 0; - old_code = (uint32_t)-1; - } else if (code == 257) { - break; + old_code = 0xFFFFFFFF; } else { - if (old_code == (uint32_t)-1) { + // Else 257 or greater. + if (old_code == 0xFFFFFFFF) return 2; - } + m_StackLen = 0; if (code >= m_nCodes + 258) { if (m_StackLen < sizeof(m_DecodeStack)) { @@ -242,9 +251,9 @@ int CLZWDecoder::Decode(uint8_t* dest_buf, uint8_t PathPredictor(int a, int b, int c) { int p = a + b - c; - int pa = FXSYS_abs(p - a); - int pb = FXSYS_abs(p - b); - int pc = FXSYS_abs(p - c); + int pa = abs(p - a); + int pb = abs(p - b); + int pc = abs(p - c); if (pa <= pb && pa <= pc) return (uint8_t)a; if (pb <= pc) @@ -288,7 +297,7 @@ void PNG_PredictLine(uint8_t* pDestData, int BytesPerPixel = (bpc * nColors + 7) / 8; uint8_t tag = pSrcData[0]; if (tag == 0) { - FXSYS_memmove(pDestData, pSrcData + 1, row_size); + memmove(pDestData, pSrcData + 1, row_size); return; } for (int byte = 0; byte < row_size; byte++) { @@ -370,7 +379,7 @@ bool PNG_Predictor(uint8_t*& data_buf, if ((row + 1) * (move_size + 1) > (int)data_size) { move_size = last_row_size - 1; } - FXSYS_memmove(pDestData, pSrcData + 1, move_size); + memmove(pDestData, pSrcData + 1, move_size); pSrcData += move_size + 1; pDestData += move_size; byte_cnt += move_size; @@ -465,7 +474,7 @@ void TIFF_PredictLine(uint8_t* dest_buf, } int BytesPerPixel = BitsPerComponent * Colors / 8; if (BitsPerComponent == 16) { - for (uint32_t i = BytesPerPixel; i < row_size; i += 2) { + for (uint32_t i = BytesPerPixel; i + 1 < row_size; i += 2) { uint16_t pixel = (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1]; pixel += (dest_buf[i] << 8) | dest_buf[i + 1]; @@ -505,109 +514,66 @@ void FlateUncompress(const uint8_t* src_buf, uint8_t*& dest_buf, uint32_t& dest_size, uint32_t& offset) { - uint32_t guess_size = orig_size ? orig_size : src_size * 2; - const uint32_t kStepSize = 10240; - uint32_t alloc_step = orig_size ? kStepSize : std::min(src_size, kStepSize); - static const uint32_t kMaxInitialAllocSize = 10000000; - if (guess_size > kMaxInitialAllocSize) { - guess_size = kMaxInitialAllocSize; - alloc_step = kMaxInitialAllocSize; - } - uint32_t buf_size = guess_size; - uint32_t last_buf_size = buf_size; - dest_buf = nullptr; dest_size = 0; - void* context = FPDFAPI_FlateInit(my_alloc_func, my_free_func); + void* context = FlateInit(); if (!context) return; + FlateInput(context, src_buf, src_size); + + const uint32_t kMaxInitialAllocSize = 10000000; + uint32_t guess_size = orig_size ? orig_size : src_size * 2; + guess_size = std::min(guess_size, kMaxInitialAllocSize); + + uint32_t buf_size = guess_size; + uint32_t last_buf_size = buf_size; std::unique_ptr guess_buf( FX_Alloc(uint8_t, guess_size + 1)); guess_buf.get()[guess_size] = '\0'; - FPDFAPI_FlateInput(context, src_buf, src_size); - - if (src_size < kStepSize) { - // This is the old implementation. - uint8_t* cur_buf = guess_buf.get(); - while (1) { - int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); - if (ret != Z_OK) - break; - int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); - if (avail_buf_size != 0) - break; - - uint32_t old_size = guess_size; - guess_size += alloc_step; - if (guess_size < old_size || guess_size + 1 < guess_size) { - FPDFAPI_FlateEnd(context); - return; - } - - { - uint8_t* new_buf = - FX_Realloc(uint8_t, guess_buf.release(), guess_size + 1); - guess_buf.reset(new_buf); - } - guess_buf.get()[guess_size] = '\0'; - cur_buf = guess_buf.get() + old_size; - buf_size = guess_size - old_size; - } - dest_size = FPDFAPI_FlateGetTotalOut(context); - offset = FPDFAPI_FlateGetTotalIn(context); - if (guess_size / 2 > dest_size) { - { - uint8_t* new_buf = - FX_Realloc(uint8_t, guess_buf.release(), dest_size + 1); - guess_buf.reset(new_buf); - } - guess_size = dest_size; - guess_buf.get()[guess_size] = '\0'; - } - dest_buf = guess_buf.release(); - } else { - std::vector result_tmp_bufs; - uint8_t* cur_buf = guess_buf.release(); - while (1) { - int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); - int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); - if (ret != Z_OK) { - last_buf_size = buf_size - avail_buf_size; - result_tmp_bufs.push_back(cur_buf); - break; - } - if (avail_buf_size != 0) { - last_buf_size = buf_size - avail_buf_size; - result_tmp_bufs.push_back(cur_buf); - break; - } + std::vector result_tmp_bufs; + uint8_t* cur_buf = guess_buf.release(); + while (1) { + uint32_t ret = FlateOutput(context, cur_buf, buf_size); + uint32_t avail_buf_size = FlateGetAvailOut(context); + if (ret != Z_OK || avail_buf_size != 0) { + last_buf_size = buf_size - avail_buf_size; result_tmp_bufs.push_back(cur_buf); - cur_buf = FX_Alloc(uint8_t, buf_size + 1); - cur_buf[buf_size] = '\0'; + break; } - dest_size = FPDFAPI_FlateGetTotalOut(context); - offset = FPDFAPI_FlateGetTotalIn(context); - if (result_tmp_bufs.size() == 1) { - dest_buf = result_tmp_bufs[0]; - } else { - uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); - uint32_t result_pos = 0; - for (size_t i = 0; i < result_tmp_bufs.size(); i++) { - uint8_t* tmp_buf = result_tmp_bufs[i]; - uint32_t tmp_buf_size = buf_size; - if (i == result_tmp_bufs.size() - 1) { - tmp_buf_size = last_buf_size; - } - FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size); - result_pos += tmp_buf_size; - FX_Free(result_tmp_bufs[i]); - } - dest_buf = result_buf; + result_tmp_bufs.push_back(cur_buf); + cur_buf = FX_Alloc(uint8_t, buf_size + 1); + cur_buf[buf_size] = '\0'; + } + + // The TotalOut size returned from the library may not be big enough to + // handle the content the library returns. We can only handle items + // up to 4GB in size. + dest_size = FlateGetPossiblyTruncatedTotalOut(context); + offset = FlateGetPossiblyTruncatedTotalIn(context); + if (result_tmp_bufs.size() == 1) { + dest_buf = result_tmp_bufs[0]; + } else { + uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); + uint32_t result_pos = 0; + uint32_t remaining = dest_size; + for (size_t i = 0; i < result_tmp_bufs.size(); i++) { + uint8_t* tmp_buf = result_tmp_bufs[i]; + uint32_t tmp_buf_size = buf_size; + if (i == result_tmp_bufs.size() - 1) + tmp_buf_size = last_buf_size; + + uint32_t cp_size = std::min(tmp_buf_size, remaining); + memcpy(result_buf + result_pos, tmp_buf, cp_size); + result_pos += cp_size; + remaining -= cp_size; + + FX_Free(result_tmp_bufs[i]); } + dest_buf = result_buf; } - FPDFAPI_FlateEnd(context); + FlateEnd(context); } } // namespace @@ -656,15 +622,16 @@ CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() { m_pPredictRaw = nullptr; m_LeftOver = 0; } + CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() { FX_Free(m_pScanline); FX_Free(m_pLastLine); FX_Free(m_pPredictBuffer); FX_Free(m_pPredictRaw); - if (m_pFlate) { - FPDFAPI_FlateEnd(m_pFlate); - } + if (m_pFlate) + FlateEnd(m_pFlate); } + void CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf, uint32_t src_size, int width, @@ -709,28 +676,30 @@ void CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf, } } } + bool CCodec_FlateScanlineDecoder::v_Rewind() { - if (m_pFlate) { - FPDFAPI_FlateEnd(m_pFlate); - } - m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func); - if (!m_pFlate) { + if (m_pFlate) + FlateEnd(m_pFlate); + + m_pFlate = FlateInit(); + if (!m_pFlate) return false; - } - FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize); + + FlateInput(m_pFlate, m_SrcBuf, m_SrcSize); m_LeftOver = 0; return true; } + uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() { if (m_Predictor) { if (m_Pitch == m_PredictPitch) { if (m_Predictor == 2) { - FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); + FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns); - FXSYS_memcpy(m_pLastLine, m_pScanline, m_PredictPitch); + memcpy(m_pLastLine, m_pScanline, m_PredictPitch); } else { - FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); + FlateOutput(m_pFlate, m_pScanline, m_Pitch); TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, m_OutputWidth); } @@ -739,38 +708,38 @@ uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() { size_t read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver; if (read_leftover) { - FXSYS_memcpy(m_pScanline, - m_pPredictBuffer + m_PredictPitch - m_LeftOver, - read_leftover); + memcpy(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_LeftOver, + read_leftover); m_LeftOver -= read_leftover; bytes_to_go -= read_leftover; } while (bytes_to_go) { if (m_Predictor == 2) { - FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); + FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns); - FXSYS_memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch); + memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch); } else { - FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch); + FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch); TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent, m_Colors, m_Columns); } size_t read_bytes = m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch; - FXSYS_memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, - read_bytes); + memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, + read_bytes); m_LeftOver += m_PredictPitch - read_bytes; bytes_to_go -= read_bytes; } } } else { - FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); + FlateOutput(m_pFlate, m_pScanline, m_Pitch); } return m_pScanline; } + uint32_t CCodec_FlateScanlineDecoder::GetSrcOffset() { - return FPDFAPI_FlateGetTotalIn(m_pFlate); + return FlateGetPossiblyTruncatedTotalIn(m_pFlate); } std::unique_ptr CCodec_FlateModule::CreateDecoder( @@ -799,48 +768,44 @@ uint32_t CCodec_FlateModule::FlateOrLZWDecode(bool bLZW, int BitsPerComponent, int Columns, uint32_t estimated_size, - uint8_t*& dest_buf, - uint32_t& dest_size) { - dest_buf = nullptr; + uint8_t** dest_buf, + uint32_t* dest_size) { + *dest_buf = nullptr; uint32_t offset = 0; int predictor_type = 0; if (predictor) { - if (predictor >= 10) { + if (predictor >= 10) predictor_type = 2; - } else if (predictor == 2) { + else if (predictor == 2) predictor_type = 1; - } } if (bLZW) { - { - std::unique_ptr decoder(new CLZWDecoder); - dest_size = (uint32_t)-1; - offset = src_size; - int err = - decoder->Decode(nullptr, dest_size, src_buf, offset, bEarlyChange); - if (err || dest_size == 0 || dest_size + 1 < dest_size) { - return FX_INVALID_OFFSET; - } - } - { - std::unique_ptr decoder(new CLZWDecoder); - dest_buf = FX_Alloc(uint8_t, dest_size + 1); - dest_buf[dest_size] = '\0'; - decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange); - } + auto decoder = pdfium::MakeUnique(); + *dest_size = 0xFFFFFFFF; + offset = src_size; + int err = + decoder->Decode(nullptr, *dest_size, src_buf, offset, bEarlyChange); + if (err || *dest_size == 0 || *dest_size + 1 < *dest_size) + return FX_INVALID_OFFSET; + + decoder = pdfium::MakeUnique(); + *dest_buf = FX_Alloc(uint8_t, *dest_size + 1); + (*dest_buf)[*dest_size] = '\0'; + decoder->Decode(*dest_buf, *dest_size, src_buf, offset, bEarlyChange); } else { - FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size, + FlateUncompress(src_buf, src_size, estimated_size, *dest_buf, *dest_size, offset); } - if (predictor_type == 0) { + if (predictor_type == 0) return offset; - } + bool ret = true; if (predictor_type == 2) { - ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns); - } else if (predictor_type == 1) { ret = - TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns); + PNG_Predictor(*dest_buf, *dest_size, Colors, BitsPerComponent, Columns); + } else if (predictor_type == 1) { + ret = TIFF_Predictor(*dest_buf, *dest_size, Colors, BitsPerComponent, + Columns); } return ret ? offset : FX_INVALID_OFFSET; } @@ -852,7 +817,7 @@ bool CCodec_FlateModule::Encode(const uint8_t* src_buf, *dest_size = src_size + src_size / 1000 + 12; *dest_buf = FX_Alloc(uint8_t, *dest_size); unsigned long temp_size = *dest_size; - if (!FPDFAPI_FlateCompress(*dest_buf, &temp_size, src_buf, src_size)) + if (!FlateCompress(*dest_buf, &temp_size, src_buf, src_size)) return false; *dest_size = (uint32_t)temp_size; @@ -864,7 +829,7 @@ bool CCodec_FlateModule::PngEncode(const uint8_t* src_buf, uint8_t** dest_buf, uint32_t* dest_size) { uint8_t* pSrcBuf = FX_Alloc(uint8_t, src_size); - FXSYS_memcpy(pSrcBuf, src_buf, src_size); + memcpy(pSrcBuf, src_buf, src_size); PNG_PredictorEncode(&pSrcBuf, &src_size); bool ret = Encode(pSrcBuf, src_size, dest_buf, dest_size); FX_Free(pSrcBuf); diff --git a/core/fxcodec/codec/fx_codec_icc.cpp b/core/fxcodec/codec/fx_codec_icc.cpp index f77c8507bfb623e0ba418c9a02f6d5b6bd245efc..29b37d19acd94918345959019359e33aedbd2df1 100644 --- a/core/fxcodec/codec/fx_codec_icc.cpp +++ b/core/fxcodec/codec/fx_codec_icc.cpp @@ -4,75 +4,57 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +#include + +#include "core/fxcodec/codec/ccodec_iccmodule.h" #include "core/fxcodec/codec/codec_int.h" -#include "core/fxcodec/fx_codec.h" -#include "third_party/lcms2-2.6/include/lcms2.h" +#include "core/fxcrt/cfx_fixedbufgrow.h" -struct CLcmsCmm { - cmsHTRANSFORM m_hTransform; - int m_nSrcComponents; - int m_nDstComponents; - bool m_bLab; -}; -bool CheckComponents(cmsColorSpaceSignature cs, int nComponents, bool bDst) { - if (nComponents <= 0 || nComponents > 15) { - return false; - } +namespace { + +bool Check3Components(cmsColorSpaceSignature cs, bool bDst) { switch (cs) { - case cmsSigLabData: - if (nComponents < 3) { - return false; - } - break; case cmsSigGrayData: - if (bDst && nComponents != 1) { - return false; - } - if (!bDst && nComponents > 2) { - return false; - } - break; - case cmsSigRgbData: - if (bDst && nComponents != 3) { - return false; - } - break; + return false; case cmsSigCmykData: - if (bDst && nComponents != 4) { + if (bDst) return false; - } break; + case cmsSigLabData: + case cmsSigRgbData: default: - if (nComponents != 3) { - return false; - } break; } return true; } -void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, - uint32_t dwSrcProfileSize, - uint32_t& nSrcComponents, - const unsigned char* pDstProfileData, - uint32_t dwDstProfileSize, - int32_t nDstComponents, - int intent, - uint32_t dwSrcFormat = Icc_FORMAT_DEFAULT, - uint32_t dwDstFormat = Icc_FORMAT_DEFAULT) { - nSrcComponents = 0; +} // namespace + +CLcmsCmm::CLcmsCmm(int srcComponents, cmsHTRANSFORM hTransform, bool isLab) + : m_hTransform(hTransform), + m_nSrcComponents(srcComponents), + m_bLab(isLab) {} + +CLcmsCmm::~CLcmsCmm() { + cmsDeleteTransform(m_hTransform); +} + +CCodec_IccModule::CCodec_IccModule() : m_nComponents(0) {} + +CCodec_IccModule::~CCodec_IccModule() {} + +std::unique_ptr CCodec_IccModule::CreateTransform_sRGB( + const unsigned char* pSrcProfileData, + uint32_t dwSrcProfileSize, + uint32_t* nSrcComponents) { + *nSrcComponents = 0; cmsHPROFILE srcProfile = - cmsOpenProfileFromMem((void*)pSrcProfileData, dwSrcProfileSize); + cmsOpenProfileFromMem(pSrcProfileData, dwSrcProfileSize); if (!srcProfile) return nullptr; cmsHPROFILE dstProfile; - if (!pDstProfileData && dwDstProfileSize == 0 && nDstComponents == 3) { - dstProfile = cmsCreate_sRGBProfile(); - } else { - dstProfile = - cmsOpenProfileFromMem((void*)pDstProfileData, dwDstProfileSize); - } + dstProfile = cmsCreate_sRGBProfile(); if (!dstProfile) { cmsCloseProfile(srcProfile); return nullptr; @@ -81,9 +63,9 @@ void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, bool bLab = false; cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile); - nSrcComponents = cmsChannelsOf(srcCS); + *nSrcComponents = cmsChannelsOf(srcCS); // According to PDF spec, number of components must be 1, 3, or 4. - if (nSrcComponents != 1 && nSrcComponents != 3 && nSrcComponents != 4) { + if (*nSrcComponents != 1 && *nSrcComponents != 3 && *nSrcComponents != 4) { cmsCloseProfile(srcProfile); cmsCloseProfile(dstProfile); return nullptr; @@ -91,23 +73,21 @@ void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, if (srcCS == cmsSigLabData) { srcFormat = - COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0); + COLORSPACE_SH(PT_Lab) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(0); bLab = true; } else { srcFormat = - COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1); - if (srcCS == cmsSigRgbData && T_DOSWAP(dwSrcFormat)) { - srcFormat |= DOSWAP_SH(1); - } + COLORSPACE_SH(PT_ANY) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(1); } cmsColorSpaceSignature dstCS = cmsGetColorSpace(dstProfile); - if (!CheckComponents(dstCS, nDstComponents, true)) { + if (!Check3Components(dstCS, true)) { cmsCloseProfile(srcProfile); cmsCloseProfile(dstProfile); return nullptr; } cmsHTRANSFORM hTransform = nullptr; + int intent = 0; switch (dstCS) { case cmsSigGrayData: hTransform = cmsCreateTransform(srcProfile, srcFormat, dstProfile, @@ -118,9 +98,8 @@ void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, TYPE_BGR_8, intent, 0); break; case cmsSigCmykData: - hTransform = cmsCreateTransform( - srcProfile, srcFormat, dstProfile, - T_DOSWAP(dwDstFormat) ? TYPE_KYMC_8 : TYPE_CMYK_8, intent, 0); + hTransform = cmsCreateTransform(srcProfile, srcFormat, dstProfile, + TYPE_CMYK_8, intent, 0); break; default: break; @@ -130,1539 +109,44 @@ void* IccLib_CreateTransform(const unsigned char* pSrcProfileData, cmsCloseProfile(dstProfile); return nullptr; } - CLcmsCmm* pCmm = new CLcmsCmm; - pCmm->m_nSrcComponents = nSrcComponents; - pCmm->m_nDstComponents = nDstComponents; - pCmm->m_hTransform = hTransform; - pCmm->m_bLab = bLab; + auto pCmm = pdfium::MakeUnique(*nSrcComponents, hTransform, bLab); cmsCloseProfile(srcProfile); cmsCloseProfile(dstProfile); return pCmm; } -void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, - uint32_t dwProfileSize, - uint32_t& nComponents, - int32_t intent, - uint32_t dwSrcFormat) { - return IccLib_CreateTransform(pProfileData, dwProfileSize, nComponents, - nullptr, 0, 3, intent, dwSrcFormat); -} -void IccLib_DestroyTransform(void* pTransform) { - if (!pTransform) { - return; - } - cmsDeleteTransform(((CLcmsCmm*)pTransform)->m_hTransform); - delete (CLcmsCmm*)pTransform; -} -void IccLib_Translate(void* pTransform, - uint32_t nSrcComponents, - FX_FLOAT* pSrcValues, - FX_FLOAT* pDestValues) { - if (!pTransform) { + +void CCodec_IccModule::Translate(CLcmsCmm* pTransform, + const float* pSrcValues, + float* pDestValues) { + if (!pTransform) return; - } - CLcmsCmm* p = (CLcmsCmm*)pTransform; + + uint32_t nSrcComponents = m_nComponents; uint8_t output[4]; - if (p->m_bLab) { + if (pTransform->m_bLab) { CFX_FixedBufGrow inputs(nSrcComponents); double* input = inputs; - for (uint32_t i = 0; i < nSrcComponents; i++) { + for (uint32_t i = 0; i < nSrcComponents; ++i) input[i] = pSrcValues[i]; - } - cmsDoTransform(p->m_hTransform, input, output, 1); + cmsDoTransform(pTransform->m_hTransform, input, output, 1); } else { CFX_FixedBufGrow inputs(nSrcComponents); uint8_t* input = inputs; - for (uint32_t i = 0; i < nSrcComponents; i++) { - if (pSrcValues[i] > 1.0f) { - input[i] = 255; - } else if (pSrcValues[i] < 0) { - input[i] = 0; - } else { - input[i] = (int)(pSrcValues[i] * 255.0f); - } + for (uint32_t i = 0; i < nSrcComponents; ++i) { + input[i] = + pdfium::clamp(static_cast(pSrcValues[i] * 255.0f), 0, 255); } - cmsDoTransform(p->m_hTransform, input, output, 1); - } - switch (p->m_nDstComponents) { - case 1: - pDestValues[0] = output[0] / 255.0f; - break; - case 3: - pDestValues[0] = output[2] / 255.0f; - pDestValues[1] = output[1] / 255.0f; - pDestValues[2] = output[0] / 255.0f; - break; - case 4: - pDestValues[0] = output[0] / 255.0f; - pDestValues[1] = output[1] / 255.0f; - pDestValues[2] = output[2] / 255.0f; - pDestValues[3] = output[3] / 255.0f; - break; + cmsDoTransform(pTransform->m_hTransform, input, output, 1); } -} -void IccLib_TranslateImage(void* pTransform, - unsigned char* pDest, - const unsigned char* pSrc, - int32_t pixels) { - cmsDoTransform(((CLcmsCmm*)pTransform)->m_hTransform, (void*)pSrc, pDest, - pixels); -} - -CCodec_IccModule::CCodec_IccModule() : m_nComponents(0) {} - -CCodec_IccModule::~CCodec_IccModule() { -} -void* CCodec_IccModule::CreateTransform_sRGB(const uint8_t* pProfileData, - uint32_t dwProfileSize, - uint32_t& nComponents, - int32_t intent, - uint32_t dwSrcFormat) { - return IccLib_CreateTransform_sRGB(pProfileData, dwProfileSize, nComponents, - intent, dwSrcFormat); + pDestValues[0] = output[2] / 255.0f; + pDestValues[1] = output[1] / 255.0f; + pDestValues[2] = output[0] / 255.0f; } -void CCodec_IccModule::DestroyTransform(void* pTransform) { - IccLib_DestroyTransform(pTransform); -} -void CCodec_IccModule::Translate(void* pTransform, - FX_FLOAT* pSrcValues, - FX_FLOAT* pDestValues) { - IccLib_Translate(pTransform, m_nComponents, pSrcValues, pDestValues); -} -void CCodec_IccModule::TranslateScanline(void* pTransform, - uint8_t* pDest, - const uint8_t* pSrc, +void CCodec_IccModule::TranslateScanline(CLcmsCmm* pTransform, + unsigned char* pDest, + const unsigned char* pSrc, int32_t pixels) { - IccLib_TranslateImage(pTransform, pDest, pSrc, pixels); -} -const uint8_t g_CMYKSamples[81 * 81 * 3] = { - 255, 255, 255, 225, 226, 228, 199, 200, 202, 173, 174, 178, 147, 149, 152, - 123, 125, 128, 99, 99, 102, 69, 70, 71, 34, 30, 31, 255, 253, 229, - 226, 224, 203, 200, 199, 182, 173, 173, 158, 149, 148, 135, 125, 124, 113, - 99, 99, 90, 70, 69, 63, 33, 29, 24, 255, 251, 204, 228, 223, 182, - 201, 198, 163, 174, 172, 142, 150, 147, 122, 125, 123, 101, 99, 98, 80, - 70, 68, 54, 32, 28, 16, 255, 249, 179, 230, 222, 160, 203, 197, 144, - 174, 170, 124, 150, 145, 105, 125, 122, 88, 99, 97, 69, 70, 68, 46, - 31, 28, 6, 255, 247, 154, 229, 220, 138, 203, 195, 122, 176, 169, 107, - 150, 145, 91, 125, 121, 74, 100, 96, 57, 70, 67, 35, 29, 26, 0, - 255, 246, 128, 231, 217, 114, 205, 194, 101, 176, 167, 88, 150, 144, 75, - 125, 120, 60, 100, 96, 44, 70, 66, 24, 28, 26, 0, 255, 244, 96, - 231, 217, 87, 203, 192, 78, 175, 167, 66, 150, 143, 56, 125, 119, 43, - 100, 95, 29, 69, 66, 7, 26, 26, 0, 255, 243, 51, 232, 215, 51, - 204, 191, 43, 176, 165, 38, 150, 142, 28, 125, 118, 17, 99, 94, 0, - 68, 65, 0, 24, 25, 0, 255, 241, 0, 231, 215, 0, 203, 190, 0, - 176, 164, 0, 150, 141, 0, 126, 117, 0, 99, 93, 0, 68, 65, 0, - 24, 25, 0, 252, 228, 238, 222, 201, 211, 197, 180, 190, 171, 156, 166, - 147, 133, 143, 123, 111, 119, 99, 88, 94, 71, 61, 66, 34, 22, 26, - 254, 226, 213, 224, 201, 191, 199, 179, 171, 172, 155, 148, 147, 133, 128, - 123, 110, 106, 98, 87, 83, 70, 59, 57, 33, 21, 18, 254, 224, 191, - 224, 199, 172, 200, 177, 153, 173, 154, 133, 147, 132, 115, 123, 109, 94, - 98, 86, 74, 70, 59, 49, 32, 21, 9, 255, 222, 168, 227, 198, 150, - 200, 175, 135, 173, 153, 118, 148, 130, 99, 123, 109, 82, 98, 86, 64, - 69, 58, 40, 31, 19, 0, 255, 221, 145, 227, 196, 129, 201, 174, 115, - 173, 151, 99, 148, 129, 85, 124, 108, 69, 98, 85, 52, 69, 58, 30, - 30, 19, 0, 255, 219, 121, 227, 195, 109, 201, 174, 97, 174, 150, 83, - 148, 129, 70, 124, 107, 55, 98, 84, 40, 69, 58, 19, 28, 18, 0, - 255, 218, 92, 229, 194, 82, 202, 173, 75, 174, 150, 63, 149, 128, 51, - 124, 106, 39, 98, 84, 24, 68, 57, 3, 26, 18, 0, 255, 217, 54, - 228, 193, 52, 201, 172, 46, 174, 148, 36, 148, 127, 27, 123, 105, 14, - 98, 83, 0, 68, 56, 0, 25, 18, 0, 255, 216, 0, 229, 192, 2, - 202, 171, 4, 173, 148, 0, 148, 126, 0, 124, 105, 0, 98, 83, 0, - 68, 56, 0, 24, 17, 0, 249, 204, 223, 219, 181, 199, 195, 160, 178, - 170, 140, 156, 146, 119, 134, 123, 99, 112, 98, 77, 88, 70, 52, 61, - 34, 11, 20, 250, 201, 200, 221, 180, 178, 197, 159, 161, 171, 139, 139, - 147, 119, 120, 123, 98, 99, 98, 77, 78, 69, 51, 52, 34, 11, 10, - 252, 201, 180, 223, 179, 162, 197, 159, 144, 170, 138, 125, 146, 117, 107, - 122, 97, 89, 98, 76, 69, 69, 50, 44, 32, 11, 2, 252, 199, 158, - 222, 177, 143, 199, 158, 127, 171, 137, 110, 147, 117, 93, 122, 96, 76, - 97, 75, 58, 69, 50, 36, 32, 10, 0, 253, 198, 137, 223, 177, 123, - 198, 156, 110, 171, 136, 95, 146, 116, 80, 122, 96, 65, 97, 75, 47, - 69, 50, 25, 30, 10, 0, 254, 197, 115, 225, 175, 104, 198, 156, 92, - 172, 135, 79, 147, 115, 66, 123, 95, 52, 98, 74, 37, 69, 49, 15, - 29, 10, 0, 254, 196, 89, 224, 175, 80, 199, 154, 70, 172, 134, 59, - 146, 114, 48, 122, 95, 36, 97, 74, 21, 68, 49, 0, 27, 9, 0, - 255, 195, 57, 225, 173, 52, 198, 154, 44, 172, 133, 36, 147, 113, 26, - 123, 94, 14, 98, 74, 0, 68, 49, 0, 26, 10, 0, 254, 194, 15, - 225, 172, 12, 198, 153, 7, 172, 132, 3, 146, 113, 0, 123, 93, 0, - 98, 73, 0, 68, 49, 0, 26, 9, 0, 246, 178, 209, 218, 159, 186, - 194, 140, 166, 168, 122, 145, 144, 104, 125, 121, 85, 103, 97, 65, 81, - 69, 41, 55, 34, 0, 12, 248, 176, 186, 219, 157, 166, 195, 139, 149, - 168, 121, 130, 144, 103, 111, 121, 85, 91, 97, 65, 71, 69, 41, 46, - 34, 0, 4, 249, 175, 168, 220, 156, 150, 196, 139, 135, 169, 121, 116, - 144, 103, 100, 122, 84, 83, 98, 65, 63, 70, 41, 39, 33, 0, 0, - 249, 175, 148, 220, 155, 133, 196, 138, 119, 169, 120, 103, 145, 101, 87, - 121, 83, 71, 97, 65, 54, 69, 41, 31, 32, 0, 0, 249, 173, 128, - 222, 154, 115, 195, 137, 102, 170, 119, 88, 145, 101, 74, 122, 83, 59, - 97, 64, 43, 68, 40, 20, 30, 0, 0, 250, 172, 108, 221, 154, 98, - 195, 136, 86, 170, 118, 73, 145, 100, 61, 122, 82, 48, 97, 63, 32, - 69, 40, 11, 28, 0, 0, 250, 171, 85, 221, 153, 76, 196, 136, 67, - 170, 117, 56, 145, 99, 44, 121, 82, 33, 97, 63, 17, 68, 40, 0, - 28, 0, 0, 251, 171, 58, 222, 152, 50, 197, 135, 43, 169, 117, 34, - 146, 99, 25, 121, 81, 10, 96, 63, 0, 68, 40, 0, 27, 0, 0, - 250, 170, 26, 222, 151, 19, 196, 134, 13, 169, 116, 4, 145, 99, 0, - 122, 81, 0, 97, 63, 0, 67, 40, 0, 26, 0, 0, 244, 153, 194, - 215, 136, 173, 192, 121, 155, 167, 104, 135, 143, 89, 115, 121, 72, 96, - 97, 54, 75, 70, 31, 49, 34, 0, 6, 245, 153, 173, 216, 136, 155, - 192, 120, 138, 167, 104, 121, 144, 88, 103, 121, 71, 85, 97, 54, 66, - 69, 31, 42, 34, 0, 0, 246, 152, 157, 217, 135, 140, 193, 120, 126, - 167, 103, 109, 143, 88, 92, 121, 72, 76, 97, 54, 58, 69, 31, 35, - 33, 0, 0, 245, 150, 139, 218, 134, 125, 193, 119, 111, 167, 103, 96, - 144, 87, 80, 121, 71, 66, 96, 53, 49, 68, 31, 26, 32, 0, 0, - 246, 151, 122, 218, 133, 108, 194, 118, 96, 168, 102, 81, 144, 86, 69, - 120, 71, 55, 95, 53, 39, 68, 30, 17, 31, 0, 0, 248, 150, 103, - 218, 133, 91, 193, 118, 81, 168, 102, 69, 143, 86, 56, 120, 70, 43, - 96, 53, 28, 68, 31, 6, 29, 0, 0, 247, 149, 81, 218, 132, 72, - 194, 117, 62, 168, 101, 52, 144, 86, 42, 121, 70, 29, 96, 52, 13, - 68, 30, 0, 28, 0, 0, 247, 148, 55, 219, 131, 50, 194, 117, 43, - 167, 101, 32, 144, 85, 22, 120, 69, 8, 96, 52, 0, 67, 30, 0, - 27, 0, 0, 247, 147, 29, 218, 131, 24, 194, 116, 20, 168, 100, 11, - 144, 85, 0, 120, 69, 0, 96, 52, 0, 67, 30, 0, 26, 0, 0, - 242, 130, 179, 214, 114, 160, 190, 101, 143, 166, 87, 125, 143, 72, 107, - 120, 58, 88, 96, 42, 68, 69, 17, 44, 35, 0, 0, 243, 129, 161, - 215, 114, 143, 191, 101, 128, 166, 87, 113, 143, 73, 96, 120, 58, 79, - 96, 41, 60, 69, 18, 37, 33, 0, 0, 243, 129, 146, 216, 114, 130, - 192, 101, 117, 166, 87, 101, 143, 72, 86, 121, 58, 69, 96, 42, 52, - 69, 18, 29, 31, 0, 0, 243, 128, 130, 216, 114, 115, 191, 101, 102, - 165, 86, 88, 142, 72, 75, 120, 58, 60, 95, 42, 43, 68, 19, 21, - 30, 0, 0, 244, 127, 112, 217, 113, 101, 192, 99, 89, 166, 85, 75, - 142, 72, 63, 119, 57, 50, 96, 41, 35, 68, 19, 13, 30, 0, 0, - 244, 127, 96, 216, 112, 86, 191, 99, 75, 166, 86, 64, 143, 72, 52, - 120, 57, 40, 95, 41, 24, 67, 20, 1, 29, 0, 0, 245, 126, 77, - 216, 113, 68, 191, 100, 59, 166, 85, 49, 142, 71, 38, 119, 57, 26, - 95, 41, 10, 67, 20, 0, 28, 0, 0, 244, 126, 55, 216, 112, 48, - 191, 99, 40, 166, 85, 31, 143, 71, 20, 119, 57, 6, 95, 42, 0, - 67, 20, 0, 28, 0, 0, 245, 126, 33, 217, 112, 26, 192, 99, 22, - 166, 84, 11, 142, 70, 0, 119, 57, 0, 95, 41, 0, 66, 20, 0, - 27, 0, 0, 241, 102, 167, 213, 90, 149, 189, 79, 133, 165, 66, 115, - 141, 54, 98, 119, 41, 81, 96, 25, 63, 69, 0, 38, 30, 0, 0, - 241, 102, 149, 213, 90, 133, 189, 79, 119, 165, 66, 103, 142, 55, 88, - 119, 41, 71, 96, 25, 53, 69, 0, 31, 28, 0, 0, 241, 102, 135, - 214, 90, 121, 190, 79, 108, 165, 66, 92, 141, 55, 78, 119, 42, 63, - 96, 26, 46, 69, 0, 24, 28, 0, 0, 241, 101, 120, 214, 90, 107, - 189, 79, 95, 165, 67, 83, 141, 54, 68, 118, 41, 54, 95, 27, 39, - 68, 0, 16, 27, 0, 0, 241, 102, 106, 213, 90, 93, 189, 78, 82, - 164, 67, 70, 141, 55, 58, 118, 42, 45, 94, 27, 29, 67, 2, 6, - 27, 0, 0, 242, 101, 90, 214, 89, 79, 190, 79, 69, 166, 67, 59, - 141, 55, 47, 118, 41, 35, 95, 27, 19, 67, 3, 0, 26, 0, 0, - 242, 102, 72, 213, 89, 63, 191, 79, 56, 164, 67, 45, 141, 55, 34, - 118, 42, 22, 94, 28, 6, 67, 3, 0, 26, 0, 0, 242, 100, 51, - 214, 89, 45, 190, 78, 38, 164, 67, 30, 141, 55, 18, 118, 42, 3, - 95, 28, 0, 66, 4, 0, 26, 0, 0, 243, 100, 33, 214, 90, 27, - 190, 78, 22, 165, 67, 13, 141, 55, 0, 118, 43, 0, 94, 29, 0, - 66, 5, 0, 26, 0, 0, 237, 69, 153, 211, 58, 135, 187, 51, 121, - 163, 41, 105, 141, 28, 90, 118, 15, 73, 96, 0, 56, 68, 0, 33, - 25, 0, 0, 239, 67, 137, 212, 60, 123, 189, 50, 110, 163, 41, 94, - 141, 29, 79, 118, 17, 65, 95, 0, 48, 69, 0, 26, 25, 0, 0, - 240, 69, 124, 211, 60, 111, 188, 50, 98, 163, 42, 85, 141, 31, 72, - 118, 18, 57, 94, 0, 41, 68, 0, 19, 25, 0, 0, 240, 70, 112, - 212, 61, 99, 188, 52, 87, 163, 41, 74, 140, 31, 62, 118, 20, 48, - 94, 2, 32, 68, 0, 11, 24, 0, 0, 239, 70, 98, 212, 62, 86, - 188, 53, 77, 164, 42, 64, 140, 32, 52, 118, 20, 40, 94, 3, 24, - 67, 0, 3, 23, 0, 0, 239, 71, 85, 212, 61, 74, 187, 53, 65, - 163, 44, 54, 140, 34, 43, 118, 22, 30, 95, 3, 14, 67, 0, 0, - 23, 0, 0, 239, 70, 67, 212, 62, 59, 188, 53, 51, 163, 45, 42, - 141, 34, 31, 117, 22, 17, 94, 5, 2, 66, 0, 0, 23, 0, 0, - 239, 71, 50, 213, 62, 43, 188, 54, 37, 164, 45, 28, 139, 34, 16, - 117, 22, 2, 94, 7, 0, 65, 0, 0, 23, 0, 0, 240, 71, 34, - 212, 63, 29, 189, 54, 24, 163, 46, 15, 139, 36, 2, 117, 25, 0, - 94, 8, 0, 66, 0, 0, 23, 0, 0, 237, 0, 140, 209, 0, 124, - 186, 0, 112, 162, 0, 97, 141, 0, 82, 118, 0, 67, 95, 0, 49, - 68, 0, 27, 20, 0, 0, 237, 0, 126, 210, 0, 113, 187, 0, 99, - 163, 0, 86, 139, 0, 72, 118, 0, 58, 95, 0, 42, 67, 0, 20, - 20, 0, 0, 237, 1, 114, 209, 1, 102, 187, 0, 90, 163, 0, 78, - 139, 0, 64, 118, 0, 50, 95, 0, 35, 67, 0, 13, 20, 0, 0, - 236, 16, 102, 209, 7, 91, 186, 0, 80, 162, 0, 68, 139, 0, 56, - 117, 0, 43, 94, 0, 27, 67, 0, 6, 20, 0, 0, 238, 15, 89, - 209, 13, 79, 186, 6, 69, 162, 0, 58, 139, 0, 47, 117, 0, 34, - 93, 0, 20, 66, 0, 2, 20, 0, 0, 237, 20, 78, 210, 12, 68, - 187, 4, 59, 163, 0, 49, 139, 0, 38, 116, 0, 26, 94, 0, 11, - 66, 0, 0, 20, 0, 0, 237, 25, 64, 210, 18, 56, 186, 11, 48, - 162, 4, 39, 138, 0, 27, 117, 0, 14, 93, 0, 0, 66, 0, 0, - 20, 0, 0, 238, 25, 48, 210, 22, 43, 186, 15, 35, 162, 8, 26, - 140, 0, 14, 117, 0, 0, 93, 0, 0, 65, 0, 0, 20, 0, 0, - 238, 28, 35, 210, 21, 30, 187, 15, 24, 162, 8, 16, 139, 1, 2, - 117, 0, 0, 93, 0, 0, 65, 0, 0, 22, 0, 0, 219, 242, 252, - 195, 214, 225, 172, 191, 201, 148, 165, 175, 127, 142, 150, 106, 119, 126, - 84, 95, 101, 58, 66, 72, 24, 27, 32, 222, 239, 226, 196, 213, 202, - 173, 189, 180, 150, 165, 158, 129, 141, 135, 107, 118, 113, 85, 94, 90, - 58, 66, 63, 21, 26, 24, 223, 237, 203, 198, 211, 182, 175, 188, 163, - 152, 164, 141, 129, 140, 121, 107, 117, 101, 85, 93, 80, 58, 64, 54, - 21, 26, 18, 226, 236, 179, 201, 210, 160, 177, 187, 143, 153, 162, 125, - 130, 139, 106, 108, 116, 89, 85, 92, 69, 58, 64, 45, 20, 25, 8, - 227, 234, 153, 201, 208, 139, 178, 185, 124, 154, 161, 107, 131, 138, 91, - 108, 115, 75, 85, 91, 58, 58, 63, 35, 17, 25, 0, 229, 233, 130, - 203, 207, 116, 178, 184, 104, 154, 160, 90, 131, 137, 76, 109, 114, 62, - 85, 90, 46, 58, 63, 25, 16, 24, 0, 230, 231, 100, 202, 205, 90, - 179, 183, 80, 154, 159, 69, 131, 136, 57, 109, 113, 46, 86, 90, 32, - 58, 63, 10, 14, 24, 0, 230, 230, 65, 204, 204, 58, 180, 182, 52, - 155, 157, 44, 132, 135, 35, 110, 113, 24, 86, 89, 9, 57, 62, 0, - 11, 24, 0, 232, 230, 19, 204, 204, 19, 180, 181, 17, 155, 157, 10, - 131, 134, 2, 109, 112, 0, 85, 89, 0, 57, 62, 0, 10, 23, 0, - 218, 216, 236, 194, 192, 211, 172, 171, 188, 149, 149, 164, 128, 127, 141, - 106, 106, 119, 84, 84, 94, 59, 57, 66, 25, 18, 26, 221, 214, 211, - 196, 191, 190, 174, 170, 170, 150, 148, 148, 128, 126, 127, 107, 105, 106, - 85, 83, 84, 59, 56, 58, 23, 17, 18, 222, 213, 190, 197, 189, 170, - 175, 169, 153, 151, 147, 133, 129, 126, 113, 108, 105, 94, 85, 82, 74, - 59, 56, 49, 22, 17, 11, 224, 211, 168, 199, 188, 151, 175, 168, 135, - 152, 146, 117, 129, 124, 99, 107, 103, 82, 84, 82, 64, 59, 55, 41, - 21, 17, 1, 224, 210, 145, 199, 187, 130, 176, 166, 117, 152, 145, 101, - 129, 123, 86, 107, 103, 70, 85, 81, 53, 58, 55, 31, 19, 17, 0, - 227, 208, 123, 200, 186, 110, 177, 165, 98, 153, 143, 84, 130, 122, 70, - 108, 102, 57, 85, 80, 41, 58, 54, 20, 18, 16, 0, 227, 208, 97, - 202, 185, 86, 177, 164, 77, 153, 142, 65, 130, 122, 54, 108, 101, 42, - 85, 80, 27, 58, 54, 7, 16, 16, 0, 228, 206, 66, 202, 184, 58, - 178, 163, 50, 154, 141, 42, 131, 121, 33, 109, 101, 21, 86, 79, 5, - 58, 54, 0, 13, 16, 0, 228, 206, 29, 202, 183, 25, 178, 163, 20, - 154, 141, 15, 131, 121, 5, 108, 100, 0, 85, 79, 0, 58, 53, 0, - 13, 16, 0, 217, 193, 221, 193, 172, 198, 172, 153, 178, 149, 133, 154, - 128, 114, 132, 107, 94, 111, 85, 74, 89, 59, 49, 61, 25, 8, 22, - 219, 191, 198, 195, 171, 178, 173, 153, 159, 149, 132, 139, 128, 113, 119, - 107, 94, 100, 85, 73, 79, 59, 48, 52, 25, 7, 14, 221, 191, 180, - 196, 170, 160, 174, 152, 144, 150, 132, 125, 129, 113, 107, 107, 93, 89, - 85, 73, 69, 59, 48, 45, 23, 7, 4, 222, 189, 159, 197, 169, 142, - 174, 151, 127, 151, 131, 110, 129, 112, 94, 108, 93, 78, 85, 72, 60, - 58, 47, 37, 22, 7, 0, 223, 188, 138, 197, 168, 123, 175, 150, 109, - 151, 130, 95, 130, 111, 81, 108, 92, 65, 85, 72, 49, 59, 47, 27, - 21, 7, 0, 224, 187, 118, 198, 167, 105, 176, 149, 93, 152, 129, 79, - 130, 110, 68, 108, 91, 54, 85, 71, 38, 59, 47, 17, 18, 7, 0, - 224, 187, 93, 199, 166, 83, 176, 148, 73, 152, 128, 62, 129, 109, 51, - 108, 90, 39, 85, 71, 25, 58, 46, 3, 16, 8, 0, 226, 186, 64, - 200, 165, 57, 177, 147, 50, 153, 127, 40, 130, 108, 31, 108, 90, 19, - 85, 70, 3, 58, 46, 0, 16, 8, 0, 227, 185, 35, 200, 165, 30, - 176, 146, 25, 152, 127, 18, 130, 108, 7, 108, 89, 0, 85, 70, 0, - 57, 46, 0, 14, 8, 0, 216, 169, 205, 192, 150, 184, 171, 134, 164, - 149, 116, 144, 128, 99, 124, 107, 81, 103, 85, 63, 81, 60, 39, 55, - 26, 0, 15, 217, 168, 186, 193, 150, 165, 172, 134, 149, 150, 116, 130, - 128, 99, 111, 107, 81, 92, 85, 62, 72, 59, 39, 47, 25, 0, 6, - 219, 168, 168, 194, 149, 150, 173, 133, 135, 150, 116, 117, 128, 98, 99, - 107, 80, 82, 86, 62, 63, 59, 38, 39, 24, 0, 0, 219, 166, 148, - 195, 149, 133, 173, 133, 119, 150, 115, 103, 128, 98, 88, 107, 80, 72, - 85, 61, 54, 59, 38, 32, 23, 0, 0, 220, 166, 129, 196, 148, 116, - 174, 132, 103, 151, 114, 89, 129, 97, 75, 107, 79, 60, 85, 61, 44, - 59, 38, 22, 21, 0, 0, 222, 164, 110, 197, 147, 99, 175, 131, 87, - 151, 113, 75, 129, 96, 63, 107, 79, 49, 85, 61, 33, 58, 38, 12, - 19, 0, 0, 222, 164, 88, 197, 146, 79, 174, 130, 69, 151, 113, 58, - 129, 95, 47, 107, 78, 35, 85, 60, 20, 58, 38, 0, 18, 0, 0, - 223, 164, 63, 198, 145, 55, 175, 129, 48, 151, 112, 39, 129, 95, 29, - 107, 78, 16, 85, 60, 1, 58, 38, 0, 17, 0, 0, 223, 163, 36, - 198, 145, 32, 174, 129, 26, 151, 111, 17, 129, 95, 7, 107, 78, 0, - 84, 60, 0, 57, 37, 0, 15, 0, 0, 215, 147, 192, 191, 130, 172, - 170, 116, 153, 148, 100, 133, 127, 85, 115, 107, 69, 96, 85, 51, 75, - 60, 28, 50, 25, 0, 8, 217, 146, 173, 192, 130, 154, 171, 115, 138, - 149, 100, 121, 128, 84, 103, 107, 68, 85, 85, 51, 66, 60, 28, 42, - 25, 0, 0, 217, 145, 157, 193, 129, 140, 173, 115, 125, 149, 100, 109, - 128, 84, 92, 107, 68, 76, 85, 51, 58, 59, 28, 35, 23, 0, 0, - 218, 145, 140, 193, 129, 125, 172, 114, 110, 149, 99, 96, 128, 83, 81, - 107, 67, 65, 84, 51, 49, 59, 29, 27, 22, 0, 0, 219, 144, 121, - 194, 128, 108, 172, 113, 96, 149, 98, 83, 128, 83, 69, 107, 68, 55, - 85, 50, 40, 59, 28, 18, 20, 0, 0, 220, 143, 104, 195, 128, 93, - 173, 114, 82, 150, 98, 69, 127, 82, 58, 107, 67, 45, 85, 50, 30, - 59, 28, 7, 19, 0, 0, 220, 143, 84, 195, 127, 74, 173, 113, 65, - 149, 97, 55, 128, 82, 44, 106, 67, 32, 84, 50, 16, 58, 28, 0, - 18, 0, 0, 221, 142, 62, 196, 126, 53, 173, 112, 46, 150, 97, 37, - 128, 82, 26, 107, 66, 14, 84, 50, 0, 58, 28, 0, 16, 0, 0, - 222, 142, 38, 196, 126, 34, 174, 112, 27, 150, 96, 17, 128, 82, 6, - 106, 66, 0, 84, 50, 0, 57, 29, 0, 16, 0, 0, 214, 123, 179, - 191, 110, 159, 169, 98, 143, 147, 84, 124, 126, 70, 106, 107, 55, 88, - 85, 39, 69, 60, 15, 45, 23, 0, 2, 216, 123, 161, 192, 110, 144, - 170, 98, 129, 148, 84, 112, 127, 70, 95, 107, 55, 79, 85, 39, 61, - 60, 15, 37, 20, 0, 0, 217, 122, 145, 192, 110, 130, 170, 97, 116, - 149, 84, 101, 127, 70, 85, 106, 55, 70, 85, 39, 53, 59, 16, 30, - 19, 0, 0, 217, 123, 131, 192, 109, 116, 171, 96, 103, 149, 83, 89, - 127, 70, 75, 106, 55, 60, 85, 40, 45, 59, 16, 23, 17, 0, 0, - 217, 122, 114, 193, 109, 101, 172, 96, 91, 149, 82, 77, 128, 69, 64, - 106, 55, 50, 84, 39, 35, 59, 17, 14, 17, 0, 0, 218, 122, 98, - 194, 108, 87, 171, 96, 77, 149, 82, 65, 127, 69, 52, 106, 55, 40, - 84, 40, 25, 59, 18, 3, 15, 0, 0, 219, 122, 80, 193, 108, 70, - 172, 95, 61, 149, 82, 51, 127, 69, 40, 106, 55, 28, 84, 39, 12, - 58, 17, 0, 13, 0, 0, 219, 121, 59, 194, 108, 52, 172, 96, 44, - 149, 82, 35, 127, 68, 24, 106, 55, 11, 84, 40, 0, 57, 18, 0, - 13, 0, 0, 219, 121, 40, 193, 108, 33, 172, 95, 26, 149, 81, 19, - 128, 68, 6, 106, 54, 0, 84, 39, 0, 57, 18, 0, 13, 0, 0, - 213, 99, 165, 189, 87, 148, 169, 76, 132, 147, 64, 115, 126, 52, 98, - 106, 39, 81, 85, 23, 63, 60, 0, 39, 16, 0, 0, 214, 98, 149, - 191, 87, 133, 170, 76, 119, 148, 65, 103, 127, 53, 88, 106, 39, 72, - 85, 24, 55, 60, 0, 32, 15, 0, 0, 215, 99, 136, 191, 87, 121, - 170, 77, 108, 148, 65, 93, 126, 53, 79, 106, 40, 64, 85, 24, 47, - 59, 0, 25, 14, 0, 0, 215, 99, 121, 192, 87, 108, 170, 77, 96, - 148, 65, 82, 126, 53, 69, 106, 40, 55, 85, 25, 39, 59, 0, 18, - 13, 0, 0, 216, 99, 106, 191, 87, 95, 170, 76, 83, 148, 65, 71, - 126, 53, 58, 106, 41, 45, 85, 26, 30, 59, 0, 8, 11, 0, 0, - 216, 98, 91, 192, 88, 82, 170, 77, 71, 148, 65, 60, 127, 53, 48, - 105, 41, 36, 83, 26, 21, 58, 1, 2, 11, 0, 0, 217, 99, 75, - 192, 87, 66, 170, 76, 57, 148, 65, 47, 126, 53, 36, 105, 41, 24, - 83, 26, 8, 57, 2, 0, 9, 0, 0, 217, 98, 57, 192, 87, 49, - 171, 77, 41, 147, 65, 32, 126, 53, 21, 105, 41, 8, 84, 27, 0, - 57, 3, 0, 9, 0, 0, 217, 98, 40, 193, 87, 34, 171, 76, 27, - 148, 65, 19, 126, 53, 6, 105, 41, 0, 83, 27, 0, 57, 4, 0, - 9, 0, 0, 211, 67, 152, 189, 58, 136, 168, 50, 122, 147, 39, 105, - 127, 28, 89, 106, 14, 74, 85, 0, 56, 59, 0, 33, 9, 0, 0, - 213, 68, 138, 190, 59, 123, 169, 51, 109, 148, 40, 95, 126, 30, 80, - 106, 16, 65, 85, 0, 48, 59, 0, 27, 9, 0, 0, 214, 69, 125, - 190, 59, 111, 168, 51, 99, 148, 41, 86, 126, 31, 72, 106, 18, 58, - 85, 0, 41, 59, 0, 20, 7, 0, 0, 215, 70, 112, 190, 61, 100, - 169, 52, 88, 147, 42, 76, 126, 32, 63, 106, 19, 49, 84, 1, 34, - 58, 0, 13, 7, 0, 0, 214, 70, 99, 190, 62, 88, 169, 53, 77, - 147, 43, 65, 125, 32, 53, 106, 20, 40, 84, 3, 26, 58, 0, 4, - 7, 0, 0, 214, 71, 86, 190, 61, 75, 169, 53, 65, 146, 43, 54, - 126, 33, 44, 105, 21, 31, 83, 4, 17, 57, 0, 0, 7, 0, 0, - 215, 71, 71, 191, 62, 62, 169, 53, 53, 147, 44, 44, 126, 34, 33, - 105, 22, 20, 83, 5, 4, 57, 0, 0, 7, 0, 0, 215, 71, 54, - 191, 62, 47, 169, 54, 39, 147, 44, 30, 126, 35, 20, 105, 23, 6, - 83, 6, 0, 56, 0, 0, 5, 0, 0, 215, 71, 41, 191, 63, 34, - 170, 54, 27, 147, 45, 17, 126, 35, 6, 105, 23, 0, 83, 8, 0, - 56, 0, 0, 5, 0, 0, 210, 13, 140, 189, 1, 125, 167, 0, 110, - 146, 0, 96, 126, 0, 81, 106, 0, 67, 85, 0, 51, 59, 0, 28, - 4, 0, 0, 212, 18, 126, 190, 7, 113, 168, 0, 100, 146, 0, 86, - 126, 0, 73, 106, 0, 59, 84, 0, 43, 59, 0, 22, 4, 0, 0, - 212, 21, 115, 190, 13, 103, 168, 3, 91, 146, 0, 78, 125, 0, 65, - 105, 0, 52, 84, 0, 36, 58, 0, 16, 4, 0, 0, 213, 24, 103, - 189, 19, 91, 168, 9, 82, 146, 0, 69, 125, 0, 57, 105, 0, 44, - 84, 0, 29, 58, 0, 7, 4, 0, 0, 213, 27, 92, 188, 21, 81, - 168, 14, 71, 146, 1, 59, 125, 0, 48, 105, 0, 36, 84, 0, 21, - 58, 0, 4, 4, 0, 0, 213, 30, 80, 189, 22, 69, 168, 17, 61, - 146, 5, 50, 125, 0, 39, 104, 0, 27, 83, 0, 12, 57, 0, 0, - 4, 0, 0, 214, 30, 67, 189, 25, 57, 168, 20, 50, 146, 9, 40, - 125, 0, 29, 104, 0, 17, 83, 0, 2, 56, 0, 0, 4, 0, 0, - 214, 32, 53, 189, 27, 44, 169, 20, 38, 146, 13, 28, 124, 2, 17, - 104, 0, 4, 83, 0, 0, 56, 0, 0, 4, 0, 0, 214, 33, 41, - 190, 27, 33, 168, 23, 27, 146, 13, 18, 125, 3, 5, 105, 0, 0, - 83, 0, 0, 56, 0, 0, 4, 0, 0, 185, 229, 250, 164, 204, 223, - 146, 182, 199, 127, 158, 174, 108, 136, 149, 89, 113, 125, 70, 90, 100, - 46, 62, 71, 10, 25, 33, 189, 227, 225, 168, 202, 201, 148, 181, 179, - 129, 157, 156, 109, 135, 134, 90, 113, 113, 70, 89, 90, 46, 62, 62, - 8, 24, 25, 192, 226, 202, 170, 202, 182, 151, 179, 162, 130, 156, 141, - 110, 133, 121, 91, 112, 101, 71, 89, 80, 46, 61, 54, 7, 24, 19, - 194, 224, 179, 173, 200, 160, 153, 178, 144, 132, 155, 125, 112, 133, 107, - 92, 111, 89, 71, 88, 69, 46, 61, 45, 6, 23, 10, 196, 223, 155, - 174, 198, 139, 154, 176, 124, 132, 153, 107, 113, 131, 91, 92, 110, 75, - 72, 87, 58, 47, 60, 37, 4, 23, 0, 198, 221, 131, 175, 197, 117, - 155, 175, 105, 133, 152, 91, 113, 130, 76, 92, 109, 63, 72, 86, 47, - 46, 60, 26, 3, 23, 0, 200, 220, 104, 176, 196, 94, 156, 175, 84, - 134, 151, 72, 113, 129, 59, 93, 108, 47, 72, 85, 33, 46, 59, 13, - 0, 23, 0, 201, 219, 73, 179, 195, 65, 157, 173, 57, 135, 150, 48, - 114, 129, 39, 94, 108, 28, 72, 85, 15, 47, 59, 0, 0, 22, 0, - 203, 219, 42, 178, 195, 37, 157, 173, 32, 135, 150, 26, 114, 128, 16, - 94, 107, 6, 73, 85, 0, 46, 58, 0, 0, 22, 0, 186, 205, 233, - 165, 183, 209, 148, 163, 187, 128, 142, 163, 109, 121, 140, 91, 101, 118, - 71, 80, 94, 48, 54, 66, 12, 15, 27, 189, 204, 211, 169, 182, 189, - 151, 163, 169, 131, 141, 147, 111, 121, 126, 92, 101, 105, 72, 79, 84, - 48, 54, 58, 11, 15, 19, 192, 202, 190, 171, 181, 170, 152, 161, 152, - 131, 141, 133, 112, 120, 113, 93, 100, 94, 72, 79, 74, 48, 53, 50, - 10, 15, 11, 195, 201, 169, 172, 179, 151, 153, 160, 135, 132, 139, 117, - 113, 119, 100, 93, 99, 82, 72, 78, 64, 48, 53, 41, 9, 14, 3, - 195, 200, 146, 174, 179, 131, 154, 159, 117, 133, 138, 101, 113, 118, 86, - 93, 98, 70, 73, 77, 53, 48, 52, 32, 8, 15, 0, 198, 199, 125, - 175, 177, 111, 155, 158, 100, 133, 137, 85, 113, 117, 71, 93, 97, 57, - 72, 77, 42, 47, 52, 22, 5, 14, 0, 199, 198, 101, 176, 177, 89, - 155, 157, 79, 134, 136, 68, 113, 116, 56, 94, 97, 44, 73, 76, 30, - 47, 52, 10, 2, 15, 0, 200, 197, 72, 178, 176, 63, 157, 156, 56, - 135, 136, 46, 114, 116, 37, 94, 96, 26, 73, 76, 11, 47, 51, 0, - 0, 14, 0, 201, 197, 45, 177, 175, 38, 156, 155, 31, 135, 135, 25, - 114, 115, 17, 94, 96, 5, 73, 75, 0, 46, 51, 0, 0, 14, 0, - 187, 183, 218, 167, 165, 197, 149, 147, 176, 129, 127, 153, 111, 109, 132, - 92, 90, 111, 73, 70, 89, 49, 46, 62, 15, 4, 22, 190, 183, 197, - 170, 164, 177, 151, 146, 159, 130, 127, 139, 112, 109, 119, 93, 90, 99, - 72, 70, 78, 49, 45, 53, 14, 4, 15, 192, 182, 179, 171, 163, 161, - 153, 145, 144, 132, 126, 125, 113, 108, 107, 93, 89, 88, 73, 70, 69, - 49, 45, 45, 13, 5, 6, 195, 181, 159, 172, 162, 142, 152, 145, 127, - 132, 125, 111, 113, 107, 94, 93, 88, 77, 73, 69, 59, 48, 45, 37, - 11, 5, 0, 195, 180, 139, 173, 161, 124, 153, 143, 110, 133, 125, 96, - 113, 106, 81, 94, 88, 66, 73, 68, 49, 49, 44, 28, 9, 6, 0, - 196, 179, 118, 174, 160, 106, 154, 142, 94, 133, 124, 81, 113, 105, 68, - 94, 87, 54, 73, 68, 39, 48, 44, 18, 5, 5, 0, 197, 178, 96, - 176, 159, 86, 155, 141, 75, 134, 123, 64, 114, 105, 53, 94, 87, 40, - 73, 68, 26, 48, 44, 5, 2, 6, 0, 199, 178, 70, 176, 158, 62, - 156, 141, 54, 134, 122, 44, 114, 104, 35, 94, 86, 23, 73, 67, 8, - 47, 44, 0, 2, 6, 0, 199, 177, 45, 178, 158, 40, 156, 140, 32, - 135, 122, 26, 114, 104, 16, 94, 86, 4, 73, 67, 0, 47, 44, 0, - 0, 7, 0, 188, 161, 204, 168, 144, 183, 149, 129, 164, 130, 112, 144, - 112, 95, 123, 93, 78, 103, 74, 60, 81, 50, 36, 56, 16, 0, 16, - 190, 160, 185, 170, 144, 165, 151, 128, 148, 132, 111, 130, 112, 95, 110, - 93, 78, 92, 74, 59, 72, 50, 36, 48, 16, 0, 8, 192, 160, 167, - 171, 143, 150, 153, 128, 134, 132, 111, 117, 112, 94, 100, 94, 77, 82, - 74, 59, 63, 50, 36, 40, 14, 0, 0, 193, 159, 149, 172, 143, 134, - 153, 127, 119, 133, 110, 103, 113, 94, 87, 93, 77, 72, 73, 59, 54, - 50, 36, 32, 12, 0, 0, 195, 159, 131, 173, 142, 117, 153, 127, 104, - 132, 110, 90, 113, 93, 76, 93, 76, 61, 74, 59, 45, 49, 36, 23, - 9, 0, 0, 196, 158, 113, 174, 141, 101, 155, 126, 89, 133, 109, 76, - 113, 93, 64, 94, 76, 51, 74, 58, 35, 49, 36, 14, 6, 0, 0, - 197, 157, 92, 174, 141, 80, 154, 125, 71, 134, 108, 60, 114, 92, 50, - 94, 75, 37, 73, 58, 22, 48, 36, 1, 5, 0, 0, 197, 157, 68, - 175, 140, 59, 155, 124, 51, 134, 108, 41, 113, 91, 32, 94, 75, 21, - 73, 57, 5, 48, 35, 0, 5, 0, 0, 198, 156, 46, 176, 140, 40, - 155, 124, 32, 134, 107, 24, 114, 91, 14, 94, 75, 2, 73, 57, 0, - 48, 36, 0, 3, 0, 0, 189, 140, 191, 168, 126, 172, 150, 112, 154, - 131, 97, 134, 112, 82, 115, 94, 66, 96, 74, 49, 75, 51, 25, 50, - 12, 0, 10, 191, 139, 173, 170, 125, 154, 152, 111, 138, 132, 96, 121, - 113, 81, 103, 94, 66, 85, 74, 48, 66, 50, 26, 42, 12, 0, 1, - 192, 139, 157, 171, 125, 140, 152, 111, 125, 132, 96, 109, 113, 81, 92, - 94, 65, 76, 74, 48, 58, 50, 26, 35, 9, 0, 0, 193, 139, 140, - 172, 124, 125, 153, 110, 112, 133, 95, 96, 113, 80, 82, 94, 65, 66, - 74, 49, 50, 50, 26, 28, 7, 0, 0, 194, 138, 123, 172, 123, 109, - 153, 110, 97, 133, 95, 84, 113, 80, 70, 94, 65, 56, 74, 48, 40, - 50, 26, 20, 6, 0, 0, 194, 138, 105, 173, 123, 94, 153, 109, 83, - 133, 94, 70, 112, 79, 59, 94, 64, 46, 74, 48, 31, 50, 26, 9, - 4, 0, 0, 196, 138, 87, 174, 122, 77, 153, 109, 67, 133, 93, 56, - 113, 79, 46, 94, 64, 34, 73, 48, 18, 49, 27, 0, 4, 0, 0, - 196, 137, 65, 174, 122, 57, 154, 108, 49, 133, 93, 39, 113, 79, 29, - 94, 64, 18, 74, 48, 3, 49, 27, 0, 2, 0, 0, 197, 137, 47, - 175, 122, 40, 155, 108, 32, 133, 93, 23, 114, 79, 14, 94, 64, 1, - 73, 48, 0, 48, 27, 0, 2, 0, 0, 189, 119, 177, 168, 106, 159, - 150, 94, 142, 131, 81, 124, 113, 67, 107, 94, 53, 89, 74, 37, 69, - 51, 11, 45, 6, 0, 3, 191, 119, 161, 170, 106, 144, 152, 94, 129, - 132, 81, 112, 113, 67, 96, 94, 53, 79, 74, 37, 61, 51, 13, 38, - 6, 0, 0, 192, 119, 146, 170, 106, 131, 152, 94, 117, 132, 80, 101, - 112, 67, 85, 94, 53, 70, 74, 37, 53, 50, 14, 31, 4, 0, 0, - 192, 119, 131, 171, 106, 117, 153, 94, 105, 132, 80, 89, 113, 67, 75, - 94, 54, 61, 74, 38, 45, 51, 14, 23, 3, 0, 0, 193, 118, 114, - 171, 106, 102, 153, 93, 90, 132, 80, 78, 113, 67, 65, 94, 53, 52, - 74, 37, 36, 50, 15, 16, 1, 0, 0, 194, 118, 99, 172, 105, 89, - 153, 93, 78, 132, 80, 66, 113, 67, 54, 94, 53, 42, 74, 38, 27, - 50, 16, 5, 1, 0, 0, 194, 118, 82, 173, 105, 72, 153, 93, 63, - 132, 79, 53, 113, 67, 42, 94, 53, 30, 74, 38, 15, 49, 16, 0, - 0, 0, 0, 195, 117, 63, 173, 105, 55, 154, 93, 47, 133, 79, 37, - 113, 66, 27, 94, 53, 15, 73, 38, 0, 48, 16, 0, 0, 0, 0, - 195, 117, 46, 173, 104, 39, 154, 92, 32, 133, 79, 22, 113, 66, 13, - 94, 53, 0, 73, 38, 0, 48, 17, 0, 0, 0, 0, 189, 96, 166, - 168, 85, 147, 150, 74, 132, 131, 62, 115, 113, 51, 99, 94, 38, 82, - 74, 21, 63, 51, 0, 40, 1, 0, 0, 190, 96, 150, 170, 85, 133, - 152, 75, 119, 132, 63, 104, 113, 51, 88, 94, 38, 72, 75, 22, 55, - 51, 0, 33, 1, 0, 0, 192, 96, 137, 170, 85, 121, 152, 74, 108, - 132, 64, 94, 113, 52, 79, 94, 39, 64, 74, 23, 48, 50, 0, 26, - 0, 0, 0, 192, 96, 122, 171, 86, 109, 152, 75, 96, 132, 63, 83, - 113, 52, 69, 94, 39, 56, 74, 24, 41, 50, 0, 19, 0, 0, 0, - 193, 96, 107, 171, 85, 96, 152, 75, 84, 132, 64, 72, 113, 52, 60, - 94, 39, 47, 74, 24, 32, 50, 1, 10, 0, 0, 0, 193, 96, 93, - 172, 85, 82, 152, 75, 72, 133, 63, 61, 113, 51, 49, 94, 39, 37, - 73, 25, 23, 49, 2, 2, 0, 0, 0, 194, 96, 78, 172, 85, 68, - 152, 75, 59, 132, 63, 49, 113, 52, 39, 94, 40, 26, 73, 25, 11, - 48, 3, 0, 0, 0, 0, 194, 96, 60, 173, 85, 52, 153, 75, 44, - 132, 64, 35, 112, 52, 25, 94, 40, 12, 73, 26, 0, 48, 4, 0, - 0, 0, 0, 195, 96, 46, 173, 85, 38, 154, 74, 31, 133, 63, 22, - 113, 52, 11, 93, 40, 0, 73, 26, 0, 47, 5, 0, 0, 0, 0, - 188, 67, 153, 168, 58, 137, 151, 49, 122, 131, 39, 106, 113, 28, 90, - 94, 13, 75, 75, 0, 57, 51, 0, 35, 0, 0, 0, 190, 68, 138, - 170, 59, 123, 152, 50, 110, 132, 41, 96, 113, 29, 80, 94, 16, 66, - 75, 0, 49, 50, 0, 27, 0, 0, 0, 191, 69, 126, 170, 59, 112, - 151, 52, 100, 132, 42, 86, 113, 30, 73, 95, 17, 58, 75, 0, 42, - 50, 0, 21, 0, 0, 0, 192, 70, 113, 170, 61, 100, 151, 52, 89, - 132, 42, 77, 113, 31, 64, 94, 19, 50, 74, 1, 35, 50, 0, 14, - 0, 0, 0, 192, 70, 100, 170, 62, 89, 151, 53, 77, 131, 43, 66, - 112, 32, 54, 94, 20, 42, 74, 2, 27, 49, 0, 5, 0, 0, 0, - 192, 71, 87, 171, 61, 77, 152, 53, 67, 131, 44, 57, 112, 33, 45, - 94, 21, 33, 74, 4, 19, 49, 0, 1, 0, 0, 0, 193, 71, 74, - 171, 62, 64, 152, 53, 55, 132, 44, 45, 113, 34, 34, 94, 22, 23, - 73, 5, 7, 48, 0, 0, 0, 0, 0, 193, 70, 58, 172, 62, 50, - 152, 54, 42, 132, 44, 32, 112, 35, 22, 93, 23, 10, 73, 6, 0, - 47, 0, 0, 0, 0, 0, 193, 70, 45, 172, 62, 38, 153, 54, 31, - 132, 44, 21, 112, 35, 9, 94, 23, 0, 73, 7, 0, 47, 0, 0, - 0, 0, 0, 189, 26, 141, 169, 15, 126, 150, 2, 112, 131, 0, 97, - 113, 0, 82, 94, 0, 67, 75, 0, 51, 50, 0, 29, 0, 0, 0, - 190, 28, 128, 170, 18, 114, 151, 8, 101, 132, 0, 88, 113, 0, 74, - 94, 0, 60, 75, 0, 44, 50, 0, 23, 0, 0, 0, 191, 30, 117, - 170, 23, 104, 152, 11, 92, 132, 1, 79, 113, 0, 67, 95, 0, 53, - 75, 0, 37, 50, 0, 17, 0, 0, 0, 191, 33, 105, 170, 26, 93, - 151, 18, 83, 132, 6, 70, 112, 0, 58, 94, 0, 45, 75, 0, 30, - 49, 0, 8, 0, 0, 0, 191, 34, 93, 170, 27, 82, 151, 20, 72, - 131, 8, 61, 112, 0, 49, 94, 0, 38, 74, 0, 23, 49, 0, 4, - 0, 0, 0, 191, 36, 82, 170, 29, 71, 151, 22, 63, 131, 11, 52, - 112, 0, 41, 93, 0, 29, 74, 0, 14, 48, 0, 1, 0, 0, 0, - 191, 38, 69, 170, 31, 60, 151, 24, 51, 131, 14, 41, 112, 1, 31, - 93, 0, 19, 73, 0, 3, 48, 0, 0, 0, 0, 0, 192, 37, 56, - 171, 31, 47, 152, 25, 40, 131, 17, 30, 112, 4, 19, 93, 0, 7, - 73, 0, 0, 47, 0, 0, 0, 0, 0, 192, 38, 45, 171, 33, 36, - 152, 26, 30, 131, 18, 21, 111, 7, 9, 93, 0, 0, 73, 0, 0, - 47, 0, 0, 0, 0, 0, 149, 218, 248, 133, 194, 222, 119, 173, 198, - 102, 151, 173, 86, 130, 148, 70, 108, 125, 53, 85, 100, 32, 59, 71, - 0, 22, 33, 154, 216, 223, 137, 193, 200, 122, 172, 178, 106, 150, 156, - 89, 128, 133, 73, 107, 112, 54, 85, 89, 31, 59, 63, 0, 22, 26, - 159, 215, 202, 141, 192, 181, 126, 171, 161, 108, 149, 141, 90, 128, 121, - 74, 107, 100, 55, 85, 80, 32, 58, 55, 0, 22, 19, 161, 213, 179, - 144, 190, 160, 126, 170, 143, 109, 148, 125, 92, 127, 107, 74, 106, 89, - 56, 84, 69, 32, 58, 46, 0, 21, 11, 163, 211, 156, 144, 189, 139, - 129, 168, 125, 110, 147, 108, 93, 126, 92, 75, 105, 76, 57, 83, 58, - 33, 58, 37, 0, 21, 1, 167, 211, 133, 147, 188, 120, 130, 167, 105, - 110, 145, 92, 93, 125, 78, 76, 104, 64, 58, 83, 48, 33, 57, 27, - 0, 21, 0, 169, 210, 108, 149, 187, 96, 131, 166, 86, 112, 144, 74, - 94, 124, 62, 77, 103, 49, 58, 82, 35, 33, 57, 15, 0, 21, 0, - 170, 209, 80, 151, 186, 71, 133, 165, 62, 114, 143, 52, 95, 123, 42, - 77, 103, 32, 58, 81, 18, 33, 56, 0, 0, 21, 0, 173, 208, 55, - 152, 186, 49, 134, 165, 41, 114, 143, 34, 95, 122, 25, 77, 102, 14, - 58, 81, 0, 33, 56, 0, 0, 21, 0, 154, 195, 232, 137, 174, 207, - 122, 156, 185, 105, 136, 163, 89, 116, 140, 73, 97, 117, 56, 76, 94, - 35, 51, 66, 0, 13, 28, 158, 194, 209, 141, 174, 187, 125, 155, 167, - 109, 135, 146, 91, 116, 125, 75, 96, 105, 57, 75, 83, 35, 50, 57, - 0, 12, 21, 161, 193, 189, 144, 173, 169, 128, 154, 151, 110, 134, 132, - 93, 115, 113, 77, 95, 94, 58, 75, 74, 35, 50, 50, 0, 12, 13, - 164, 192, 168, 145, 171, 151, 129, 153, 134, 111, 133, 117, 94, 114, 100, - 76, 95, 82, 58, 75, 64, 36, 50, 42, 0, 12, 5, 165, 191, 147, - 147, 170, 131, 130, 152, 117, 113, 132, 102, 95, 113, 86, 77, 94, 71, - 58, 74, 54, 35, 50, 33, 0, 13, 0, 167, 189, 126, 148, 169, 113, - 132, 151, 100, 113, 131, 86, 96, 112, 73, 77, 93, 59, 59, 73, 43, - 35, 49, 23, 0, 12, 0, 170, 189, 104, 150, 168, 91, 133, 150, 81, - 114, 130, 69, 96, 111, 57, 78, 92, 46, 59, 73, 31, 35, 49, 11, - 0, 13, 0, 171, 188, 78, 152, 168, 68, 134, 149, 60, 115, 130, 50, - 96, 111, 41, 78, 92, 29, 60, 73, 15, 35, 49, 0, 0, 12, 0, - 173, 187, 55, 153, 167, 47, 134, 149, 39, 115, 129, 33, 97, 110, 24, - 79, 92, 13, 60, 72, 0, 35, 48, 0, 0, 12, 0, 157, 175, 217, - 139, 157, 196, 125, 141, 175, 109, 122, 153, 92, 104, 132, 76, 86, 110, - 59, 67, 88, 37, 43, 61, 1, 1, 23, 161, 174, 196, 144, 156, 176, - 127, 140, 158, 110, 121, 137, 94, 104, 118, 77, 85, 98, 59, 67, 78, - 37, 43, 53, 0, 2, 16, 163, 174, 178, 146, 156, 160, 130, 139, 143, - 112, 121, 124, 95, 103, 106, 78, 85, 88, 60, 66, 69, 37, 42, 46, - 0, 2, 7, 166, 173, 159, 147, 154, 142, 130, 138, 127, 113, 120, 111, - 96, 103, 95, 78, 84, 77, 60, 66, 59, 37, 43, 37, 0, 2, 0, - 166, 172, 139, 148, 154, 125, 131, 137, 112, 113, 120, 96, 96, 102, 81, - 78, 84, 66, 60, 65, 50, 37, 42, 29, 0, 3, 0, 167, 171, 120, - 149, 153, 107, 133, 137, 95, 114, 118, 81, 97, 101, 69, 79, 84, 56, - 60, 65, 40, 37, 42, 19, 0, 3, 0, 170, 170, 99, 151, 152, 87, - 134, 136, 77, 115, 118, 66, 97, 101, 55, 79, 83, 42, 61, 65, 28, - 37, 42, 7, 0, 3, 0, 172, 170, 75, 152, 151, 65, 134, 135, 57, - 115, 117, 48, 97, 100, 38, 79, 83, 27, 61, 64, 12, 36, 42, 0, - 0, 3, 0, 172, 169, 55, 154, 151, 46, 135, 134, 40, 116, 116, 32, - 97, 99, 21, 80, 82, 10, 61, 64, 0, 36, 41, 0, 0, 3, 0, - 160, 154, 203, 143, 139, 182, 127, 124, 164, 111, 107, 143, 95, 91, 122, - 78, 75, 103, 60, 57, 81, 39, 33, 56, 1, 0, 18, 163, 154, 184, - 146, 138, 165, 130, 123, 148, 113, 107, 129, 96, 90, 110, 79, 74, 92, - 61, 56, 72, 39, 34, 48, 2, 0, 9, 165, 154, 167, 147, 137, 149, - 131, 122, 134, 114, 106, 117, 96, 90, 100, 79, 74, 82, 61, 56, 64, - 39, 33, 40, 2, 0, 1, 166, 153, 150, 149, 137, 133, 132, 122, 119, - 114, 106, 104, 97, 90, 88, 79, 74, 72, 61, 56, 55, 39, 34, 33, - 0, 0, 0, 168, 152, 132, 149, 136, 117, 132, 121, 104, 114, 105, 90, - 97, 89, 76, 79, 73, 62, 61, 56, 46, 38, 34, 25, 0, 0, 0, - 169, 151, 114, 150, 135, 101, 133, 121, 90, 114, 104, 77, 97, 89, 65, - 80, 73, 51, 61, 56, 36, 38, 34, 16, 0, 0, 0, 170, 150, 94, - 151, 135, 83, 134, 120, 73, 115, 104, 62, 98, 88, 51, 80, 72, 39, - 61, 56, 24, 38, 34, 3, 0, 0, 0, 172, 150, 72, 153, 134, 63, - 135, 119, 55, 115, 103, 45, 98, 88, 36, 80, 72, 24, 61, 55, 9, - 38, 34, 0, 0, 0, 0, 172, 150, 54, 153, 134, 47, 135, 119, 38, - 116, 103, 30, 98, 87, 21, 80, 72, 8, 62, 55, 0, 37, 34, 0, - 0, 0, 0, 162, 134, 190, 145, 120, 171, 129, 108, 153, 113, 93, 134, - 97, 78, 115, 80, 63, 96, 62, 46, 75, 41, 23, 51, 0, 0, 11, - 165, 134, 173, 147, 120, 154, 131, 107, 138, 114, 92, 120, 97, 78, 103, - 80, 63, 85, 62, 46, 66, 40, 23, 43, 0, 0, 2, 166, 134, 157, - 148, 120, 140, 132, 106, 125, 114, 92, 109, 97, 77, 93, 81, 63, 77, - 62, 46, 58, 40, 24, 36, 0, 0, 0, 168, 133, 140, 149, 119, 125, - 132, 106, 112, 115, 92, 97, 98, 77, 82, 81, 62, 67, 62, 46, 50, - 40, 24, 29, 0, 0, 0, 168, 133, 123, 150, 119, 110, 133, 106, 97, - 115, 91, 84, 98, 77, 70, 81, 62, 57, 62, 46, 41, 40, 24, 20, - 0, 0, 0, 169, 132, 107, 150, 118, 94, 133, 105, 84, 115, 91, 72, - 98, 76, 60, 80, 62, 47, 62, 46, 32, 39, 25, 11, 0, 0, 0, - 171, 132, 89, 152, 118, 79, 135, 105, 69, 115, 90, 58, 98, 76, 47, - 80, 62, 36, 62, 46, 21, 39, 25, 0, 0, 0, 0, 171, 132, 69, - 153, 117, 60, 135, 104, 52, 116, 90, 42, 98, 76, 33, 81, 61, 21, - 62, 46, 6, 38, 25, 0, 0, 0, 0, 172, 132, 54, 153, 118, 45, - 135, 104, 38, 116, 90, 28, 98, 76, 18, 81, 61, 6, 62, 46, 0, - 38, 25, 0, 0, 0, 0, 164, 115, 177, 146, 103, 159, 130, 91, 143, - 114, 78, 125, 97, 65, 107, 81, 51, 89, 63, 34, 69, 41, 9, 46, - 0, 0, 4, 166, 115, 161, 148, 103, 144, 132, 91, 129, 115, 78, 112, - 98, 65, 96, 81, 51, 79, 63, 35, 61, 41, 11, 38, 0, 0, 0, - 167, 115, 146, 150, 102, 131, 132, 91, 117, 115, 78, 101, 98, 65, 86, - 81, 51, 71, 63, 35, 54, 41, 12, 32, 0, 0, 0, 168, 114, 132, - 150, 103, 118, 133, 91, 105, 116, 78, 91, 98, 64, 76, 82, 51, 61, - 63, 36, 46, 41, 13, 24, 0, 0, 0, 169, 114, 116, 150, 102, 103, - 134, 90, 91, 116, 78, 79, 98, 65, 66, 81, 51, 53, 63, 36, 37, - 40, 14, 17, 0, 0, 0, 169, 114, 101, 151, 101, 89, 134, 90, 79, - 116, 77, 67, 98, 64, 56, 81, 51, 44, 63, 36, 29, 40, 15, 7, - 0, 0, 0, 170, 114, 85, 152, 101, 75, 135, 90, 65, 116, 77, 54, - 98, 64, 44, 81, 51, 32, 63, 36, 17, 39, 15, 0, 0, 0, 0, - 172, 113, 66, 152, 101, 58, 135, 89, 49, 116, 77, 40, 99, 64, 30, - 81, 51, 18, 62, 36, 3, 38, 16, 0, 0, 0, 0, 171, 113, 51, - 153, 101, 44, 136, 89, 36, 116, 77, 28, 99, 64, 18, 81, 51, 5, - 62, 36, 0, 38, 16, 0, 0, 0, 0, 165, 94, 166, 147, 82, 147, - 132, 72, 132, 115, 61, 115, 98, 49, 99, 82, 36, 82, 64, 19, 64, - 42, 0, 41, 0, 0, 0, 167, 93, 150, 150, 83, 134, 133, 73, 120, - 116, 62, 104, 99, 49, 88, 82, 36, 72, 64, 20, 55, 41, 0, 33, - 0, 0, 0, 169, 93, 137, 150, 83, 122, 134, 73, 109, 116, 61, 94, - 99, 50, 80, 82, 37, 65, 64, 21, 49, 41, 0, 27, 0, 0, 0, - 169, 94, 123, 150, 83, 110, 133, 73, 97, 116, 61, 83, 99, 50, 70, - 82, 38, 57, 63, 23, 42, 41, 0, 20, 0, 0, 0, 169, 94, 109, - 150, 84, 97, 134, 73, 85, 116, 62, 73, 99, 51, 61, 81, 38, 48, - 63, 23, 33, 41, 1, 11, 0, 0, 0, 170, 94, 96, 150, 83, 84, - 134, 73, 74, 116, 61, 62, 99, 50, 51, 82, 38, 39, 64, 23, 24, - 40, 3, 4, 0, 0, 0, 171, 93, 79, 152, 82, 70, 135, 73, 61, - 116, 62, 51, 98, 51, 40, 81, 38, 28, 63, 24, 14, 39, 4, 0, - 0, 0, 0, 171, 94, 64, 152, 83, 55, 135, 73, 47, 116, 62, 37, - 98, 50, 27, 81, 38, 15, 63, 24, 1, 39, 4, 0, 0, 0, 0, - 172, 93, 51, 153, 82, 42, 135, 73, 35, 117, 62, 26, 99, 51, 16, - 81, 39, 3, 63, 25, 0, 38, 5, 0, 0, 0, 0, 166, 68, 153, - 148, 59, 137, 133, 49, 121, 115, 39, 106, 99, 28, 91, 82, 13, 75, - 65, 0, 58, 42, 0, 36, 0, 0, 0, 168, 68, 139, 150, 59, 124, - 134, 50, 110, 116, 40, 96, 99, 30, 81, 82, 16, 66, 64, 0, 50, - 41, 0, 29, 0, 0, 0, 169, 69, 126, 150, 59, 113, 134, 51, 101, - 117, 42, 87, 100, 30, 73, 82, 17, 59, 65, 0, 43, 41, 0, 23, - 0, 0, 0, 169, 70, 115, 150, 61, 102, 134, 52, 89, 116, 42, 77, - 99, 32, 65, 82, 19, 52, 64, 0, 36, 41, 0, 15, 0, 0, 0, - 169, 70, 101, 150, 61, 90, 134, 52, 79, 116, 43, 68, 99, 32, 55, - 82, 21, 43, 64, 2, 28, 41, 0, 6, 0, 0, 0, 170, 70, 89, - 151, 62, 79, 134, 53, 69, 116, 44, 58, 99, 33, 46, 81, 21, 34, - 64, 3, 20, 41, 0, 2, 0, 0, 0, 170, 71, 76, 152, 62, 66, - 134, 53, 57, 116, 43, 46, 99, 33, 36, 82, 22, 24, 64, 5, 10, - 40, 0, 0, 0, 0, 0, 171, 70, 61, 152, 62, 52, 135, 53, 44, - 116, 44, 35, 99, 34, 24, 82, 22, 12, 63, 6, 0, 39, 0, 0, - 0, 0, 0, 171, 71, 49, 153, 62, 41, 135, 54, 33, 117, 45, 25, - 98, 34, 13, 81, 23, 0, 63, 7, 0, 39, 0, 0, 0, 0, 0, - 167, 33, 142, 149, 24, 127, 134, 10, 113, 116, 0, 97, 100, 0, 83, - 83, 0, 68, 65, 0, 52, 40, 0, 30, 0, 0, 0, 169, 33, 129, - 150, 26, 115, 134, 17, 102, 116, 3, 89, 100, 0, 75, 83, 0, 60, - 65, 0, 45, 40, 0, 24, 0, 0, 0, 169, 36, 118, 151, 27, 104, - 134, 19, 93, 116, 7, 80, 100, 0, 67, 83, 0, 54, 65, 0, 38, - 41, 0, 17, 0, 0, 0, 169, 39, 107, 150, 30, 94, 134, 22, 84, - 116, 11, 71, 99, 0, 59, 83, 0, 46, 64, 0, 31, 40, 0, 9, - 0, 0, 0, 169, 39, 95, 151, 31, 83, 134, 24, 73, 116, 15, 62, - 100, 1, 51, 83, 0, 38, 64, 0, 24, 40, 0, 5, 0, 0, 0, - 169, 41, 83, 151, 33, 73, 134, 26, 64, 117, 17, 54, 99, 4, 42, - 82, 0, 30, 64, 0, 16, 40, 0, 1, 0, 0, 0, 170, 42, 71, - 152, 34, 62, 134, 28, 53, 117, 19, 44, 99, 6, 33, 82, 0, 21, - 63, 0, 4, 39, 0, 0, 0, 0, 0, 171, 42, 59, 152, 35, 50, - 134, 29, 42, 117, 21, 32, 99, 9, 22, 82, 0, 9, 63, 0, 0, - 38, 0, 0, 0, 0, 0, 172, 42, 48, 152, 36, 40, 135, 29, 32, - 117, 21, 23, 99, 10, 12, 82, 0, 0, 63, 0, 0, 38, 0, 0, - 0, 0, 0, 107, 207, 246, 96, 185, 220, 86, 165, 196, 73, 144, 171, - 60, 123, 147, 46, 103, 125, 32, 82, 100, 9, 56, 71, 0, 20, 33, - 115, 206, 221, 104, 184, 198, 92, 164, 178, 78, 143, 154, 64, 123, 133, - 51, 102, 111, 34, 81, 89, 10, 56, 63, 0, 20, 27, 122, 204, 200, - 108, 183, 180, 95, 163, 161, 82, 142, 140, 68, 122, 120, 54, 102, 101, - 36, 81, 79, 11, 56, 55, 0, 20, 20, 125, 203, 179, 111, 181, 160, - 97, 162, 143, 85, 141, 124, 70, 121, 107, 55, 101, 89, 38, 80, 69, - 14, 55, 46, 0, 19, 10, 128, 202, 156, 113, 180, 140, 102, 161, 125, - 87, 140, 108, 71, 120, 92, 56, 100, 76, 39, 79, 59, 14, 55, 38, - 0, 20, 3, 132, 200, 135, 117, 179, 121, 103, 159, 106, 88, 139, 93, - 73, 119, 79, 57, 100, 65, 41, 79, 49, 15, 54, 28, 0, 19, 0, - 134, 200, 111, 119, 178, 98, 105, 158, 87, 89, 138, 76, 74, 118, 64, - 58, 99, 51, 41, 78, 37, 16, 54, 17, 0, 19, 0, 137, 199, 85, - 122, 177, 75, 108, 158, 66, 91, 137, 56, 75, 118, 46, 59, 98, 35, - 42, 78, 22, 16, 54, 3, 0, 19, 0, 140, 198, 62, 125, 177, 55, - 109, 158, 47, 92, 137, 40, 76, 117, 32, 59, 98, 21, 42, 78, 6, - 16, 54, 0, 0, 18, 0, 118, 186, 231, 106, 167, 206, 93, 149, 184, - 81, 130, 161, 67, 111, 139, 54, 92, 117, 39, 72, 93, 17, 48, 66, - 0, 10, 29, 123, 185, 207, 110, 166, 186, 98, 148, 167, 85, 129, 145, - 71, 111, 125, 56, 92, 104, 40, 72, 83, 18, 48, 57, 0, 10, 22, - 128, 184, 188, 113, 165, 168, 102, 147, 151, 88, 128, 131, 73, 110, 113, - 58, 91, 94, 42, 71, 74, 19, 48, 50, 0, 9, 15, 131, 183, 168, - 116, 164, 151, 104, 146, 134, 89, 127, 117, 73, 109, 100, 58, 90, 83, - 42, 71, 65, 20, 48, 42, 0, 9, 5, 134, 182, 148, 120, 163, 131, - 105, 145, 118, 90, 126, 102, 75, 108, 86, 59, 90, 72, 43, 71, 55, - 19, 47, 34, 0, 9, 0, 136, 181, 128, 122, 162, 115, 107, 144, 102, - 92, 125, 87, 76, 107, 74, 61, 89, 60, 44, 70, 45, 20, 47, 24, - 0, 8, 0, 139, 180, 106, 124, 161, 95, 109, 144, 83, 93, 124, 71, - 77, 107, 60, 61, 89, 47, 44, 70, 33, 20, 47, 13, 0, 8, 0, - 142, 179, 82, 125, 160, 72, 111, 143, 63, 94, 124, 54, 77, 106, 44, - 61, 88, 32, 44, 69, 18, 20, 46, 0, 0, 8, 0, 143, 179, 62, - 127, 160, 54, 111, 142, 47, 94, 124, 39, 78, 106, 29, 62, 88, 18, - 45, 69, 3, 20, 46, 0, 0, 8, 0, 124, 167, 216, 112, 150, 194, - 99, 134, 174, 87, 117, 153, 73, 100, 131, 58, 82, 110, 43, 64, 88, - 23, 40, 61, 0, 0, 24, 129, 166, 195, 116, 150, 175, 103, 134, 158, - 89, 116, 137, 75, 99, 118, 60, 82, 98, 44, 63, 78, 23, 40, 53, - 0, 0, 17, 132, 166, 177, 119, 149, 160, 106, 133, 143, 90, 115, 124, - 76, 99, 107, 61, 81, 88, 45, 63, 69, 24, 40, 46, 0, 0, 9, - 136, 166, 159, 121, 148, 143, 107, 132, 126, 92, 115, 111, 77, 98, 94, - 62, 81, 78, 46, 63, 60, 23, 40, 38, 0, 0, 0, 138, 164, 140, - 122, 147, 125, 108, 131, 111, 93, 114, 97, 79, 98, 82, 63, 80, 67, - 46, 62, 50, 24, 40, 29, 0, 0, 0, 139, 163, 122, 124, 146, 109, - 110, 131, 96, 94, 114, 83, 79, 97, 70, 63, 81, 57, 46, 62, 41, - 24, 40, 21, 0, 0, 0, 141, 163, 101, 126, 145, 90, 111, 130, 79, - 95, 113, 68, 79, 96, 56, 63, 80, 44, 47, 62, 30, 23, 40, 10, - 0, 0, 0, 144, 162, 79, 127, 145, 70, 112, 129, 60, 95, 112, 51, - 79, 96, 41, 64, 79, 30, 47, 61, 15, 23, 40, 0, 0, 0, 0, - 145, 162, 60, 129, 145, 52, 113, 129, 46, 96, 112, 37, 79, 95, 27, - 64, 79, 16, 47, 61, 1, 23, 39, 0, 0, 0, 0, 131, 147, 202, - 117, 133, 181, 105, 119, 162, 91, 103, 142, 77, 87, 122, 62, 71, 102, - 47, 54, 81, 26, 31, 56, 0, 0, 18, 135, 147, 183, 120, 132, 164, - 107, 118, 147, 93, 102, 128, 78, 87, 110, 63, 71, 92, 47, 54, 72, - 26, 31, 48, 0, 0, 10, 138, 147, 166, 123, 131, 149, 108, 118, 133, - 94, 102, 116, 79, 86, 100, 64, 71, 82, 48, 54, 64, 27, 31, 41, - 0, 0, 2, 139, 146, 149, 124, 131, 134, 111, 117, 119, 94, 101, 103, - 79, 86, 88, 64, 70, 72, 48, 53, 55, 27, 31, 33, 0, 0, 0, - 141, 146, 132, 125, 131, 117, 111, 117, 104, 95, 101, 91, 80, 86, 77, - 65, 70, 62, 48, 53, 46, 26, 31, 25, 0, 0, 0, 143, 145, 115, - 126, 130, 101, 112, 116, 90, 96, 100, 78, 80, 85, 65, 65, 70, 52, - 49, 53, 37, 27, 32, 17, 0, 0, 0, 144, 144, 96, 128, 129, 85, - 112, 115, 75, 97, 100, 64, 81, 85, 52, 65, 69, 40, 49, 53, 26, - 26, 31, 5, 0, 0, 0, 146, 144, 76, 129, 129, 67, 114, 115, 58, - 97, 99, 48, 82, 84, 38, 66, 69, 27, 49, 53, 12, 26, 32, 0, - 0, 0, 0, 146, 144, 59, 130, 128, 51, 114, 114, 43, 98, 99, 35, - 82, 84, 25, 66, 69, 13, 49, 53, 0, 26, 32, 0, 0, 0, 0, - 135, 129, 189, 122, 115, 170, 107, 103, 152, 94, 89, 133, 79, 74, 114, - 64, 60, 95, 49, 43, 75, 29, 20, 51, 0, 0, 12, 138, 129, 171, - 124, 115, 153, 110, 103, 138, 95, 89, 120, 81, 74, 103, 66, 60, 86, - 50, 44, 67, 28, 21, 43, 0, 0, 3, 140, 129, 156, 125, 115, 140, - 111, 103, 125, 96, 89, 109, 81, 74, 93, 67, 60, 76, 50, 44, 59, - 29, 22, 36, 0, 0, 0, 142, 128, 140, 127, 115, 125, 112, 102, 112, - 97, 88, 97, 82, 74, 83, 67, 60, 67, 50, 44, 51, 29, 22, 29, - 0, 0, 0, 142, 128, 124, 127, 114, 111, 113, 102, 98, 98, 88, 85, - 82, 74, 71, 66, 60, 58, 50, 44, 42, 29, 22, 21, 0, 0, 0, - 144, 127, 108, 128, 114, 96, 113, 101, 85, 98, 87, 73, 82, 74, 61, - 67, 60, 48, 50, 44, 33, 28, 23, 12, 0, 0, 0, 145, 127, 91, - 129, 114, 81, 115, 101, 71, 98, 87, 60, 82, 73, 48, 67, 59, 37, - 50, 44, 22, 29, 23, 1, 0, 0, 0, 147, 127, 73, 130, 113, 63, - 115, 101, 55, 98, 87, 45, 83, 73, 35, 67, 59, 24, 50, 44, 10, - 28, 24, 0, 0, 0, 0, 147, 127, 58, 131, 113, 49, 115, 100, 42, - 99, 86, 33, 83, 73, 23, 67, 59, 10, 50, 44, 0, 27, 24, 0, - 0, 0, 0, 138, 110, 177, 124, 99, 159, 110, 88, 142, 96, 75, 125, - 82, 62, 107, 66, 48, 89, 51, 33, 70, 30, 8, 46, 0, 0, 5, - 142, 111, 160, 127, 99, 144, 113, 88, 130, 98, 75, 112, 82, 62, 96, - 68, 49, 80, 51, 33, 61, 30, 10, 39, 0, 0, 0, 143, 111, 146, - 128, 99, 131, 114, 88, 118, 98, 75, 101, 83, 62, 86, 68, 49, 71, - 52, 33, 54, 30, 11, 32, 0, 0, 0, 144, 111, 132, 128, 99, 118, - 113, 88, 106, 99, 75, 91, 83, 62, 77, 68, 49, 62, 52, 34, 46, - 30, 12, 25, 0, 0, 0, 144, 111, 117, 129, 98, 104, 114, 87, 92, - 99, 75, 80, 83, 62, 67, 68, 49, 53, 51, 34, 38, 30, 13, 18, - 0, 0, 0, 145, 111, 103, 130, 98, 91, 114, 87, 80, 99, 75, 68, - 83, 63, 57, 68, 50, 45, 51, 34, 30, 30, 14, 8, 0, 0, 0, - 146, 110, 87, 131, 98, 76, 115, 87, 67, 99, 75, 56, 83, 62, 45, - 68, 49, 33, 52, 35, 19, 30, 15, 2, 0, 0, 0, 148, 110, 70, - 131, 98, 60, 116, 86, 52, 99, 74, 43, 84, 62, 33, 69, 49, 21, - 52, 35, 6, 29, 15, 0, 0, 0, 0, 148, 110, 56, 132, 97, 48, - 117, 87, 40, 100, 75, 31, 84, 62, 22, 68, 49, 9, 51, 35, 0, - 28, 15, 0, 0, 0, 0, 142, 91, 166, 126, 80, 148, 113, 71, 132, - 98, 59, 115, 83, 47, 99, 69, 34, 82, 53, 17, 64, 32, 0, 41, - 0, 0, 0, 143, 91, 150, 128, 81, 135, 114, 71, 120, 99, 60, 104, - 85, 48, 89, 69, 35, 73, 53, 19, 56, 32, 0, 34, 0, 0, 0, - 145, 91, 137, 129, 81, 122, 115, 71, 109, 100, 60, 94, 85, 48, 81, - 69, 35, 65, 53, 19, 49, 32, 0, 28, 0, 0, 0, 146, 92, 124, - 130, 81, 110, 115, 71, 98, 100, 60, 84, 85, 49, 71, 69, 36, 57, - 53, 21, 42, 32, 0, 21, 0, 0, 0, 147, 91, 110, 130, 81, 97, - 115, 71, 86, 100, 60, 74, 84, 49, 62, 69, 36, 48, 53, 22, 34, - 32, 0, 13, 0, 0, 0, 147, 92, 97, 130, 81, 85, 116, 72, 76, - 100, 60, 63, 85, 49, 52, 69, 37, 40, 53, 22, 26, 31, 1, 5, - 0, 0, 0, 148, 92, 82, 131, 81, 71, 116, 71, 62, 100, 60, 53, - 84, 49, 42, 69, 37, 30, 52, 23, 16, 31, 2, 0, 0, 0, 0, - 148, 91, 67, 132, 81, 57, 117, 71, 49, 100, 60, 39, 84, 49, 30, - 69, 37, 18, 52, 23, 2, 30, 2, 0, 0, 0, 0, 149, 91, 54, - 132, 81, 46, 118, 71, 39, 101, 60, 29, 85, 49, 19, 69, 37, 6, - 52, 23, 0, 29, 3, 0, 0, 0, 0, 143, 68, 153, 128, 59, 137, - 115, 49, 122, 99, 39, 107, 85, 28, 91, 70, 13, 75, 54, 0, 58, - 32, 0, 36, 0, 0, 0, 146, 68, 140, 131, 59, 125, 116, 51, 111, - 100, 40, 97, 85, 29, 82, 70, 15, 67, 54, 0, 50, 32, 0, 29, - 0, 0, 0, 147, 68, 127, 131, 59, 114, 117, 51, 102, 101, 41, 88, - 86, 30, 74, 70, 17, 60, 54, 0, 44, 32, 0, 23, 0, 0, 0, - 147, 70, 115, 131, 60, 103, 116, 52, 91, 100, 42, 78, 85, 32, 65, - 70, 19, 53, 54, 1, 38, 32, 0, 17, 0, 0, 0, 147, 70, 103, - 131, 61, 91, 117, 53, 81, 101, 43, 69, 86, 32, 57, 70, 20, 44, - 54, 2, 30, 32, 0, 7, 0, 0, 0, 148, 70, 91, 132, 61, 80, - 117, 52, 70, 101, 43, 59, 85, 33, 48, 70, 21, 36, 53, 4, 22, - 32, 0, 3, 0, 0, 0, 148, 70, 78, 132, 62, 68, 117, 53, 58, - 101, 43, 48, 85, 34, 38, 70, 22, 26, 53, 6, 12, 31, 0, 0, - 0, 0, 0, 149, 71, 64, 132, 62, 54, 118, 54, 46, 101, 44, 37, - 85, 34, 27, 69, 23, 15, 53, 7, 1, 30, 0, 0, 0, 0, 0, - 150, 70, 53, 134, 61, 44, 118, 54, 36, 101, 44, 28, 85, 35, 17, - 69, 23, 4, 52, 8, 0, 30, 0, 0, 0, 0, 0, 145, 38, 143, - 130, 29, 128, 117, 18, 114, 101, 3, 98, 87, 0, 84, 72, 0, 69, - 54, 0, 53, 30, 0, 31, 0, 0, 0, 147, 38, 130, 132, 30, 116, - 117, 22, 103, 101, 8, 89, 87, 0, 76, 72, 0, 62, 54, 0, 46, - 30, 0, 24, 0, 0, 0, 148, 40, 119, 132, 31, 105, 117, 23, 94, - 101, 13, 81, 87, 0, 68, 71, 0, 55, 54, 0, 39, 30, 0, 18, - 0, 0, 0, 148, 42, 108, 132, 34, 96, 117, 25, 85, 102, 15, 73, - 86, 2, 60, 71, 0, 47, 54, 0, 33, 30, 0, 11, 0, 0, 0, - 148, 43, 96, 133, 35, 85, 117, 28, 75, 102, 18, 64, 87, 5, 52, - 71, 0, 40, 54, 0, 25, 30, 0, 5, 0, 0, 0, 149, 44, 85, - 132, 36, 75, 118, 29, 66, 101, 20, 55, 86, 8, 44, 70, 0, 32, - 53, 0, 18, 29, 0, 2, 0, 0, 0, 149, 45, 74, 133, 37, 64, - 118, 31, 55, 102, 21, 45, 85, 10, 34, 70, 0, 22, 53, 0, 6, - 28, 0, 0, 0, 0, 0, 150, 46, 61, 133, 39, 52, 118, 31, 44, - 102, 23, 34, 85, 12, 24, 70, 0, 12, 52, 0, 0, 28, 0, 0, - 0, 0, 0, 150, 46, 51, 133, 40, 42, 119, 32, 35, 102, 24, 25, - 85, 13, 14, 70, 0, 1, 52, 0, 0, 27, 0, 0, 0, 0, 0, - 53, 198, 244, 49, 177, 218, 41, 158, 195, 32, 138, 171, 22, 118, 147, - 11, 98, 124, 0, 78, 100, 0, 54, 71, 0, 18, 34, 69, 196, 220, - 64, 175, 196, 54, 157, 176, 45, 137, 154, 32, 117, 133, 19, 98, 111, - 0, 78, 89, 0, 53, 63, 0, 17, 27, 80, 195, 198, 69, 175, 179, - 60, 156, 159, 50, 136, 139, 38, 116, 120, 25, 98, 101, 4, 77, 80, - 0, 53, 55, 0, 17, 21, 84, 193, 177, 75, 173, 159, 64, 155, 142, - 55, 135, 124, 41, 116, 107, 27, 97, 89, 9, 76, 70, 0, 53, 47, - 0, 17, 11, 89, 193, 157, 79, 172, 140, 70, 154, 125, 57, 134, 109, - 44, 115, 92, 32, 96, 76, 13, 76, 59, 0, 52, 39, 0, 16, 4, - 94, 191, 135, 85, 171, 121, 72, 152, 108, 60, 133, 94, 47, 114, 80, - 32, 95, 65, 15, 76, 49, 0, 52, 29, 0, 16, 0, 98, 190, 113, - 87, 170, 100, 76, 152, 89, 62, 132, 77, 49, 113, 65, 35, 95, 52, - 18, 75, 37, 0, 52, 18, 0, 15, 0, 103, 190, 89, 90, 169, 80, - 78, 151, 70, 64, 132, 60, 51, 113, 49, 37, 94, 38, 20, 75, 25, - 0, 52, 5, 0, 15, 0, 106, 189, 69, 93, 169, 61, 80, 151, 53, - 66, 131, 45, 52, 113, 36, 37, 94, 25, 19, 74, 11, 0, 51, 0, - 0, 15, 0, 76, 178, 229, 68, 159, 205, 61, 142, 183, 50, 124, 160, - 40, 106, 138, 28, 88, 116, 12, 69, 93, 0, 45, 66, 0, 5, 29, - 86, 177, 207, 78, 158, 184, 67, 142, 166, 56, 123, 145, 45, 106, 125, - 31, 88, 105, 16, 69, 83, 0, 45, 58, 0, 6, 22, 93, 176, 187, - 81, 158, 168, 71, 141, 150, 61, 123, 131, 47, 105, 113, 35, 87, 94, - 20, 68, 74, 0, 45, 51, 0, 5, 16, 98, 175, 168, 84, 157, 150, - 75, 140, 134, 63, 122, 117, 50, 104, 100, 37, 87, 83, 21, 68, 65, - 0, 45, 42, 0, 4, 7, 100, 174, 149, 89, 155, 132, 76, 139, 117, - 65, 121, 102, 53, 104, 87, 39, 86, 72, 23, 67, 55, 0, 45, 34, - 0, 3, 0, 103, 173, 130, 92, 155, 115, 80, 138, 102, 68, 120, 88, - 53, 103, 75, 40, 86, 61, 24, 67, 45, 0, 45, 25, 0, 3, 0, - 107, 172, 108, 95, 154, 96, 82, 137, 85, 70, 119, 73, 55, 102, 61, - 42, 85, 49, 25, 67, 34, 0, 45, 14, 0, 3, 0, 110, 172, 86, - 97, 153, 76, 85, 137, 67, 70, 119, 57, 56, 102, 46, 42, 84, 35, - 26, 66, 21, 0, 44, 1, 0, 3, 0, 112, 171, 67, 98, 153, 59, - 86, 137, 52, 71, 119, 44, 58, 102, 34, 44, 85, 22, 27, 66, 7, - 0, 44, 0, 0, 3, 0, 90, 160, 215, 81, 144, 193, 70, 129, 173, - 61, 112, 151, 49, 95, 131, 37, 79, 109, 22, 61, 87, 0, 38, 61, - 0, 0, 25, 96, 160, 194, 86, 143, 174, 75, 128, 157, 65, 112, 137, - 53, 95, 117, 40, 78, 98, 25, 60, 78, 0, 38, 53, 0, 0, 17, - 100, 159, 177, 89, 143, 159, 79, 128, 143, 67, 111, 124, 55, 95, 107, - 42, 78, 89, 27, 60, 70, 2, 38, 46, 0, 0, 9, 104, 158, 159, - 92, 142, 143, 81, 127, 127, 69, 110, 110, 56, 94, 94, 43, 78, 78, - 28, 60, 60, 2, 38, 38, 0, 0, 1, 107, 157, 140, 94, 141, 125, - 82, 126, 112, 71, 110, 97, 59, 94, 82, 45, 77, 67, 29, 59, 51, - 4, 37, 30, 0, 0, 0, 110, 156, 122, 97, 140, 109, 85, 125, 97, - 72, 109, 83, 58, 93, 71, 45, 77, 57, 29, 60, 42, 5, 38, 22, - 0, 0, 0, 111, 156, 103, 99, 139, 91, 87, 125, 81, 73, 108, 69, - 60, 92, 58, 46, 77, 45, 30, 59, 31, 5, 38, 12, 0, 0, 0, - 115, 156, 82, 101, 140, 73, 88, 124, 63, 74, 108, 53, 60, 92, 44, - 46, 76, 32, 31, 59, 18, 6, 37, 0, 0, 0, 0, 116, 155, 65, - 102, 139, 58, 89, 124, 49, 75, 108, 41, 61, 92, 32, 48, 76, 21, - 31, 59, 6, 5, 37, 0, 0, 0, 0, 100, 141, 201, 88, 127, 181, - 79, 114, 162, 69, 99, 142, 57, 83, 122, 44, 68, 102, 30, 51, 81, - 7, 28, 56, 0, 0, 19, 105, 141, 182, 94, 127, 163, 83, 114, 146, - 71, 98, 128, 59, 83, 110, 46, 68, 91, 31, 51, 72, 10, 28, 48, - 0, 0, 11, 108, 141, 166, 96, 127, 149, 85, 113, 133, 73, 98, 116, - 60, 83, 99, 46, 68, 82, 32, 51, 64, 11, 29, 41, 0, 0, 2, - 111, 141, 149, 98, 126, 134, 88, 112, 119, 74, 97, 103, 61, 83, 88, - 48, 67, 72, 33, 51, 56, 11, 29, 34, 0, 0, 0, 112, 140, 132, - 100, 125, 118, 89, 112, 105, 75, 97, 91, 62, 82, 77, 49, 68, 62, - 33, 51, 47, 12, 29, 26, 0, 0, 0, 115, 140, 116, 102, 125, 103, - 90, 111, 91, 76, 96, 78, 62, 82, 65, 49, 67, 52, 34, 51, 38, - 13, 29, 18, 0, 0, 0, 117, 139, 97, 103, 124, 87, 91, 111, 77, - 78, 96, 65, 63, 81, 54, 49, 67, 41, 34, 51, 27, 12, 29, 7, - 0, 0, 0, 119, 138, 78, 105, 124, 69, 92, 110, 60, 78, 95, 50, - 65, 81, 40, 50, 67, 29, 34, 51, 15, 13, 30, 0, 0, 0, 0, - 120, 138, 64, 106, 124, 54, 93, 110, 47, 78, 95, 38, 65, 81, 29, - 50, 66, 17, 34, 50, 2, 13, 29, 0, 0, 0, 0, 107, 124, 189, - 96, 111, 169, 85, 99, 152, 73, 85, 132, 61, 71, 114, 48, 57, 95, - 34, 41, 75, 14, 18, 51, 0, 0, 13, 111, 124, 171, 100, 111, 153, - 88, 99, 137, 75, 85, 120, 63, 72, 103, 50, 58, 85, 36, 41, 66, - 15, 19, 43, 0, 0, 4, 113, 124, 156, 101, 111, 139, 90, 99, 125, - 77, 85, 109, 64, 71, 93, 51, 57, 77, 36, 42, 59, 17, 20, 37, - 0, 0, 0, 115, 124, 140, 103, 111, 125, 90, 99, 112, 78, 85, 97, - 64, 71, 82, 52, 57, 67, 36, 42, 50, 16, 20, 30, 0, 0, 0, - 117, 123, 125, 104, 110, 111, 92, 98, 99, 79, 85, 86, 65, 71, 72, - 51, 58, 59, 37, 42, 43, 17, 21, 22, 0, 0, 0, 118, 123, 110, - 105, 110, 97, 93, 98, 86, 78, 84, 74, 66, 71, 62, 52, 57, 49, - 37, 42, 34, 17, 22, 14, 0, 0, 0, 120, 123, 93, 106, 109, 82, - 94, 97, 72, 80, 84, 61, 66, 71, 50, 52, 57, 38, 37, 42, 24, - 17, 22, 2, 0, 0, 0, 121, 122, 75, 108, 109, 66, 95, 97, 58, - 80, 84, 48, 66, 71, 37, 52, 57, 26, 37, 42, 12, 16, 22, 0, - 0, 0, 0, 122, 123, 62, 108, 109, 52, 95, 97, 45, 81, 84, 36, - 67, 70, 26, 52, 57, 14, 37, 42, 0, 15, 22, 0, 0, 0, 0, - 113, 107, 177, 102, 96, 159, 89, 85, 141, 78, 72, 124, 65, 60, 107, - 52, 46, 89, 37, 30, 70, 18, 5, 46, 0, 0, 6, 116, 107, 160, - 104, 96, 144, 92, 85, 129, 80, 72, 112, 67, 60, 96, 53, 47, 80, - 38, 31, 62, 19, 7, 39, 0, 0, 0, 118, 107, 147, 105, 96, 131, - 93, 85, 118, 80, 72, 101, 67, 60, 87, 54, 47, 71, 39, 31, 54, - 19, 8, 32, 0, 0, 0, 119, 107, 132, 106, 96, 118, 94, 85, 106, - 81, 73, 91, 67, 60, 77, 54, 47, 63, 39, 32, 47, 20, 9, 25, - 0, 0, 0, 119, 107, 118, 106, 95, 105, 94, 85, 93, 81, 72, 80, - 68, 60, 68, 54, 47, 54, 39, 32, 39, 20, 11, 18, 0, 0, 0, - 121, 107, 104, 107, 96, 92, 95, 84, 80, 81, 72, 69, 68, 61, 58, - 54, 48, 46, 39, 33, 31, 20, 12, 9, 0, 0, 0, 123, 107, 88, - 108, 95, 77, 96, 84, 68, 82, 72, 57, 68, 60, 46, 54, 47, 35, - 39, 33, 20, 19, 13, 2, 0, 0, 0, 123, 106, 72, 110, 95, 63, - 96, 84, 54, 82, 72, 45, 69, 60, 35, 55, 48, 23, 39, 33, 9, - 18, 14, 0, 0, 0, 0, 125, 106, 60, 110, 94, 50, 98, 84, 42, - 83, 72, 34, 69, 60, 25, 55, 48, 12, 39, 33, 0, 17, 13, 0, - 0, 0, 0, 118, 89, 165, 105, 79, 148, 93, 69, 132, 81, 57, 115, - 68, 45, 99, 55, 32, 82, 41, 15, 64, 21, 0, 41, 0, 0, 0, - 120, 89, 150, 107, 79, 135, 96, 69, 121, 82, 58, 105, 70, 46, 89, - 56, 34, 73, 41, 17, 56, 21, 0, 34, 0, 0, 0, 121, 89, 137, - 108, 79, 123, 96, 69, 109, 82, 58, 95, 70, 47, 81, 56, 34, 66, - 41, 18, 49, 21, 0, 28, 0, 0, 0, 122, 90, 124, 109, 79, 110, - 96, 69, 99, 83, 58, 85, 70, 47, 72, 56, 35, 58, 41, 19, 42, - 21, 0, 22, 0, 0, 0, 123, 90, 111, 110, 79, 98, 97, 69, 87, - 83, 59, 75, 70, 47, 63, 56, 35, 50, 41, 20, 35, 21, 0, 14, - 0, 0, 0, 123, 90, 98, 110, 79, 87, 97, 70, 76, 84, 58, 64, - 70, 48, 53, 56, 36, 41, 40, 21, 26, 21, 0, 5, 0, 0, 0, - 125, 89, 84, 111, 79, 73, 97, 69, 64, 84, 59, 54, 70, 48, 43, - 56, 36, 31, 40, 22, 17, 20, 1, 1, 0, 0, 0, 125, 89, 69, - 112, 79, 60, 98, 70, 51, 84, 59, 42, 70, 48, 32, 56, 36, 20, - 41, 22, 5, 19, 2, 0, 0, 0, 0, 126, 89, 57, 112, 79, 49, - 99, 70, 41, 84, 59, 32, 70, 48, 22, 56, 36, 10, 40, 22, 0, - 18, 2, 0, 0, 0, 0, 121, 67, 154, 108, 58, 138, 97, 50, 124, - 84, 39, 107, 71, 28, 92, 58, 12, 76, 43, 0, 59, 20, 0, 37, - 0, 0, 0, 124, 68, 140, 111, 59, 126, 98, 50, 112, 84, 40, 98, - 71, 29, 83, 58, 15, 67, 42, 0, 51, 20, 0, 30, 0, 0, 0, - 124, 68, 129, 111, 59, 114, 99, 51, 102, 86, 41, 88, 71, 30, 75, - 58, 17, 60, 42, 0, 45, 20, 0, 24, 0, 0, 0, 125, 70, 116, - 111, 60, 103, 99, 51, 92, 85, 41, 79, 71, 31, 66, 58, 19, 53, - 42, 3, 38, 20, 0, 17, 0, 0, 0, 125, 70, 104, 111, 61, 93, - 99, 52, 81, 85, 43, 69, 72, 32, 58, 58, 20, 45, 42, 4, 31, - 20, 0, 8, 0, 0, 0, 126, 70, 92, 111, 61, 81, 99, 52, 71, - 85, 42, 60, 71, 33, 49, 57, 21, 37, 42, 6, 23, 20, 0, 3, - 0, 0, 0, 126, 70, 79, 112, 61, 70, 99, 53, 60, 85, 43, 50, - 71, 33, 39, 57, 22, 28, 41, 7, 13, 19, 0, 0, 0, 0, 0, - 127, 71, 66, 113, 62, 56, 100, 53, 48, 86, 44, 39, 71, 34, 29, - 57, 23, 18, 41, 8, 2, 18, 0, 0, 0, 0, 0, 128, 70, 55, - 114, 62, 46, 100, 54, 39, 86, 44, 30, 71, 34, 20, 57, 23, 7, - 41, 9, 0, 18, 0, 0, 0, 0, 0, 124, 41, 145, 111, 32, 128, - 99, 23, 114, 86, 10, 100, 73, 0, 85, 60, 0, 71, 43, 0, 54, - 17, 0, 32, 0, 0, 0, 126, 42, 131, 113, 33, 117, 100, 25, 104, - 86, 14, 90, 73, 0, 77, 60, 0, 63, 44, 0, 47, 18, 0, 25, - 0, 0, 0, 127, 43, 120, 113, 34, 106, 101, 26, 95, 86, 17, 82, - 73, 2, 69, 59, 0, 56, 43, 0, 41, 18, 0, 19, 0, 0, 0, - 127, 45, 109, 113, 37, 97, 101, 28, 85, 86, 19, 74, 73, 5, 61, - 59, 0, 48, 43, 0, 34, 19, 0, 11, 0, 0, 0, 127, 46, 98, - 114, 38, 86, 100, 30, 76, 87, 21, 65, 73, 9, 54, 59, 0, 41, - 43, 0, 26, 18, 0, 5, 0, 0, 0, 127, 47, 87, 113, 39, 76, - 101, 31, 67, 86, 22, 56, 72, 11, 45, 59, 0, 33, 43, 0, 19, - 18, 0, 2, 0, 0, 0, 128, 48, 75, 114, 39, 65, 101, 33, 56, - 86, 23, 46, 72, 12, 36, 58, 0, 24, 42, 0, 9, 17, 0, 0, - 0, 0, 0, 129, 48, 63, 114, 41, 54, 102, 33, 46, 87, 24, 36, - 72, 14, 26, 58, 1, 14, 42, 0, 2, 16, 0, 0, 0, 0, 0, - 128, 48, 53, 114, 41, 44, 102, 34, 37, 87, 25, 27, 72, 15, 17, - 58, 1, 3, 41, 0, 0, 15, 0, 0, 0, 0, 0, 0, 189, 242, - 0, 169, 217, 0, 151, 194, 0, 132, 170, 0, 113, 147, 0, 94, 123, - 0, 74, 99, 0, 51, 71, 0, 15, 34, 1, 187, 219, 1, 167, 195, - 0, 150, 175, 0, 131, 153, 0, 113, 132, 0, 94, 111, 0, 74, 89, - 0, 50, 63, 0, 13, 28, 1, 186, 198, 1, 167, 178, 0, 149, 158, - 0, 130, 139, 0, 111, 119, 0, 93, 100, 0, 74, 80, 0, 50, 55, - 0, 13, 22, 1, 185, 176, 1, 165, 159, 1, 148, 142, 0, 129, 123, - 0, 111, 106, 0, 93, 89, 0, 73, 70, 0, 50, 47, 0, 13, 13, - 1, 184, 157, 1, 164, 141, 1, 147, 125, 0, 128, 110, 0, 110, 93, - 0, 92, 77, 0, 73, 60, 0, 50, 39, 0, 12, 5, 25, 182, 137, - 25, 163, 122, 17, 146, 109, 0, 128, 96, 0, 110, 81, 0, 92, 66, - 0, 73, 51, 0, 50, 30, 0, 10, 0, 42, 181, 114, 35, 163, 102, - 30, 145, 91, 14, 127, 80, 0, 109, 67, 0, 91, 53, 0, 72, 39, - 0, 50, 19, 0, 10, 0, 52, 181, 92, 43, 162, 83, 32, 145, 73, - 19, 126, 63, 0, 108, 52, 0, 90, 40, 0, 72, 27, 0, 50, 7, - 0, 10, 0, 57, 181, 74, 48, 162, 66, 37, 144, 57, 24, 126, 49, - 7, 108, 40, 0, 90, 29, 0, 72, 15, 0, 49, 0, 0, 10, 0, - 1, 170, 227, 1, 152, 203, 0, 136, 182, 0, 119, 159, 0, 101, 137, - 0, 84, 115, 0, 65, 92, 0, 43, 66, 0, 1, 29, 1, 169, 206, - 1, 151, 184, 1, 136, 165, 0, 118, 144, 0, 102, 125, 0, 84, 105, - 0, 65, 83, 0, 43, 58, 0, 0, 22, 29, 168, 186, 21, 151, 167, - 14, 135, 150, 4, 118, 131, 0, 101, 112, 0, 83, 94, 0, 65, 75, - 0, 43, 51, 0, 0, 16, 41, 167, 167, 33, 150, 150, 31, 134, 134, - 19, 117, 117, 4, 100, 100, 0, 83, 83, 0, 65, 65, 0, 42, 43, - 0, 0, 8, 48, 167, 149, 41, 149, 133, 33, 133, 118, 25, 116, 103, - 13, 99, 88, 0, 83, 73, 0, 65, 56, 0, 42, 35, 0, 0, 0, - 58, 165, 130, 49, 148, 115, 42, 132, 103, 31, 115, 89, 18, 99, 75, - 0, 82, 61, 0, 64, 46, 0, 42, 26, 0, 0, 0, 62, 164, 110, - 55, 147, 97, 45, 132, 87, 35, 115, 75, 22, 98, 63, 5, 82, 50, - 0, 64, 36, 0, 42, 16, 0, 0, 0, 69, 164, 89, 60, 147, 78, - 50, 131, 70, 37, 114, 59, 26, 98, 49, 10, 81, 37, 0, 64, 24, - 0, 42, 4, 0, 0, 0, 71, 164, 71, 63, 147, 63, 53, 131, 55, - 40, 114, 47, 28, 98, 38, 13, 81, 26, 0, 64, 12, 0, 42, 0, - 0, 0, 0, 28, 153, 214, 24, 138, 193, 23, 123, 171, 16, 107, 150, - 0, 91, 130, 0, 75, 109, 0, 58, 87, 0, 35, 61, 0, 0, 25, - 48, 153, 194, 41, 138, 174, 34, 123, 156, 27, 107, 136, 16, 91, 117, - 1, 75, 98, 0, 57, 78, 0, 35, 53, 0, 0, 17, 55, 153, 177, - 47, 137, 158, 42, 122, 142, 33, 107, 124, 22, 91, 106, 6, 75, 88, - 0, 57, 70, 0, 35, 46, 0, 0, 9, 61, 152, 158, 53, 136, 143, - 45, 122, 127, 36, 106, 111, 24, 90, 94, 10, 74, 78, 0, 57, 61, - 0, 35, 39, 0, 0, 2, 67, 151, 141, 59, 135, 126, 49, 121, 112, - 39, 105, 98, 29, 90, 83, 14, 74, 68, 0, 57, 52, 0, 35, 31, - 0, 0, 0, 71, 150, 123, 62, 135, 110, 54, 120, 98, 42, 105, 84, - 31, 89, 71, 16, 74, 58, 0, 57, 43, 0, 35, 22, 0, 0, 0, - 74, 150, 105, 64, 134, 92, 55, 120, 83, 45, 104, 71, 34, 89, 59, - 20, 73, 47, 0, 57, 32, 0, 35, 13, 0, 0, 0, 78, 149, 84, - 69, 134, 75, 59, 120, 66, 47, 103, 56, 34, 88, 46, 22, 73, 34, - 1, 57, 20, 0, 35, 1, 0, 0, 0, 80, 149, 69, 70, 133, 61, - 60, 119, 53, 49, 103, 44, 36, 88, 35, 23, 73, 24, 2, 56, 10, - 0, 35, 0, 0, 0, 0, 58, 136, 200, 50, 122, 180, 45, 109, 162, - 38, 94, 141, 27, 80, 121, 15, 65, 102, 0, 48, 81, 0, 26, 56, - 0, 0, 19, 66, 136, 182, 59, 122, 163, 52, 109, 146, 42, 94, 128, - 32, 80, 109, 20, 65, 91, 2, 48, 72, 0, 26, 49, 0, 0, 11, - 70, 136, 165, 62, 122, 149, 55, 108, 133, 46, 94, 116, 35, 80, 99, - 21, 65, 82, 4, 49, 64, 0, 26, 41, 0, 0, 3, 76, 135, 149, - 66, 121, 133, 58, 108, 119, 48, 94, 103, 36, 79, 88, 23, 65, 73, - 7, 49, 56, 0, 27, 34, 0, 0, 0, 78, 135, 133, 69, 120, 118, - 60, 107, 106, 50, 93, 92, 39, 79, 77, 26, 65, 63, 8, 49, 47, - 0, 27, 26, 0, 0, 0, 82, 134, 117, 71, 120, 104, 62, 107, 92, - 51, 93, 79, 39, 78, 66, 27, 64, 53, 10, 48, 39, 0, 27, 18, - 0, 0, 0, 84, 134, 99, 73, 119, 87, 64, 106, 77, 53, 92, 66, - 42, 78, 55, 28, 64, 42, 11, 48, 29, 0, 28, 9, 0, 0, 0, - 87, 133, 81, 76, 119, 72, 66, 106, 62, 55, 92, 52, 43, 78, 42, - 29, 64, 31, 12, 48, 17, 0, 28, 0, 0, 0, 0, 88, 134, 67, - 77, 119, 58, 68, 106, 51, 56, 92, 42, 44, 78, 32, 30, 64, 20, - 12, 48, 6, 0, 28, 0, 0, 0, 0, 73, 120, 189, 64, 107, 168, - 57, 96, 151, 47, 82, 133, 38, 69, 114, 26, 55, 95, 11, 39, 75, - 0, 16, 51, 0, 0, 14, 78, 120, 171, 69, 107, 153, 62, 95, 137, - 51, 82, 119, 40, 69, 102, 29, 55, 85, 15, 39, 66, 0, 17, 44, - 0, 0, 4, 81, 120, 156, 71, 107, 140, 64, 95, 125, 53, 82, 109, - 42, 69, 93, 31, 55, 77, 16, 39, 59, 0, 18, 37, 0, 0, 0, - 85, 120, 141, 74, 107, 126, 65, 95, 112, 54, 82, 97, 43, 69, 82, - 32, 55, 67, 17, 39, 51, 0, 19, 30, 0, 0, 0, 86, 119, 126, - 76, 106, 112, 66, 95, 100, 56, 81, 85, 45, 69, 72, 33, 55, 59, - 18, 40, 43, 0, 19, 22, 0, 0, 0, 89, 119, 110, 78, 106, 98, - 69, 94, 87, 56, 81, 75, 46, 68, 62, 33, 55, 49, 18, 40, 35, - 0, 20, 15, 0, 0, 0, 89, 119, 95, 80, 106, 83, 70, 94, 73, - 58, 81, 63, 46, 68, 51, 34, 55, 39, 19, 40, 25, 0, 20, 4, - 0, 0, 0, 92, 118, 78, 82, 106, 68, 70, 93, 59, 59, 81, 49, - 47, 68, 39, 34, 55, 28, 19, 40, 14, 0, 20, 0, 0, 0, 0, - 93, 118, 65, 82, 105, 55, 72, 93, 48, 60, 81, 39, 47, 68, 29, - 34, 55, 18, 20, 40, 2, 0, 20, 0, 0, 0, 0, 83, 104, 177, - 74, 93, 159, 65, 82, 142, 56, 70, 124, 45, 57, 106, 33, 44, 89, - 20, 28, 70, 1, 4, 46, 0, 0, 8, 86, 104, 161, 78, 93, 145, - 68, 82, 128, 58, 70, 112, 48, 58, 96, 35, 45, 80, 21, 29, 62, - 1, 6, 40, 0, 0, 0, 89, 104, 147, 79, 93, 131, 69, 82, 118, - 59, 70, 102, 47, 58, 87, 36, 45, 72, 23, 29, 55, 3, 7, 33, - 0, 0, 0, 90, 104, 132, 80, 93, 119, 71, 82, 106, 60, 70, 91, - 48, 58, 77, 37, 45, 62, 23, 30, 47, 4, 7, 26, 0, 0, 0, - 92, 104, 118, 82, 93, 105, 72, 82, 93, 61, 69, 80, 50, 58, 68, - 37, 45, 55, 23, 30, 39, 4, 8, 18, 0, 0, 0, 94, 104, 105, - 82, 92, 93, 72, 82, 82, 61, 70, 70, 50, 58, 58, 38, 46, 46, - 23, 31, 31, 6, 10, 11, 0, 0, 0, 95, 104, 90, 84, 92, 79, - 74, 82, 70, 62, 70, 58, 50, 58, 48, 37, 46, 36, 23, 31, 22, - 4, 11, 3, 0, 0, 0, 96, 103, 74, 85, 92, 65, 75, 81, 56, - 63, 70, 47, 50, 58, 37, 38, 46, 25, 24, 31, 11, 3, 11, 0, - 0, 0, 0, 97, 103, 62, 86, 92, 53, 76, 81, 45, 63, 69, 36, - 51, 58, 27, 38, 46, 15, 23, 31, 0, 3, 11, 0, 0, 0, 0, - 90, 87, 165, 81, 77, 148, 72, 67, 132, 62, 55, 116, 50, 44, 99, - 39, 31, 82, 25, 14, 64, 1, 0, 42, 0, 0, 1, 93, 87, 150, - 83, 77, 135, 74, 67, 121, 63, 56, 105, 52, 45, 90, 40, 32, 74, - 25, 16, 57, 3, 0, 35, 0, 0, 0, 95, 87, 138, 85, 77, 123, - 75, 67, 109, 63, 57, 95, 53, 45, 81, 41, 33, 66, 26, 17, 50, - 4, 0, 28, 0, 0, 0, 95, 88, 124, 85, 77, 111, 75, 67, 99, - 63, 57, 86, 53, 45, 72, 41, 33, 58, 26, 18, 43, 5, 1, 22, - 0, 0, 0, 97, 88, 112, 87, 77, 100, 76, 68, 88, 64, 57, 76, - 53, 46, 63, 41, 34, 50, 26, 19, 35, 5, 2, 14, 0, 0, 0, - 99, 87, 99, 87, 78, 88, 76, 68, 77, 65, 57, 65, 53, 46, 54, - 41, 35, 42, 27, 20, 27, 6, 2, 5, 0, 0, 0, 100, 87, 85, - 88, 77, 75, 77, 68, 65, 65, 57, 54, 53, 46, 44, 41, 35, 32, - 27, 21, 19, 5, 3, 2, 0, 0, 0, 100, 88, 71, 89, 77, 61, - 78, 68, 53, 66, 57, 44, 53, 47, 33, 41, 35, 22, 27, 21, 7, - 5, 3, 0, 0, 0, 0, 101, 87, 60, 90, 77, 52, 79, 68, 44, - 66, 58, 34, 53, 47, 25, 41, 35, 13, 26, 22, 0, 5, 3, 0, - 0, 0, 0, 97, 67, 155, 86, 58, 138, 77, 50, 125, 66, 39, 108, - 55, 28, 92, 43, 12, 76, 29, 0, 59, 2, 0, 37, 0, 0, 0, - 99, 67, 141, 88, 59, 127, 78, 50, 113, 68, 40, 98, 56, 29, 83, - 44, 15, 68, 29, 0, 52, 3, 0, 30, 0, 0, 0, 100, 68, 129, - 89, 59, 115, 80, 51, 103, 68, 41, 89, 56, 30, 75, 44, 16, 61, - 30, 0, 45, 4, 0, 24, 0, 0, 0, 100, 69, 118, 90, 60, 104, - 80, 51, 92, 67, 41, 79, 56, 31, 66, 44, 18, 53, 29, 2, 38, - 4, 0, 18, 0, 0, 0, 101, 69, 104, 90, 61, 93, 79, 51, 82, - 67, 42, 70, 56, 32, 59, 44, 20, 46, 29, 4, 31, 6, 0, 9, - 0, 0, 0, 102, 69, 93, 90, 61, 83, 80, 52, 72, 68, 42, 61, - 56, 33, 50, 43, 20, 38, 29, 5, 23, 7, 0, 4, 0, 0, 0, - 102, 70, 80, 91, 61, 71, 80, 52, 61, 68, 43, 51, 56, 32, 40, - 44, 21, 29, 30, 6, 14, 7, 0, 0, 0, 0, 0, 103, 70, 68, - 92, 61, 58, 81, 53, 50, 69, 43, 41, 56, 34, 31, 43, 22, 19, - 29, 7, 3, 7, 0, 0, 0, 0, 0, 104, 70, 57, 92, 61, 48, - 82, 53, 40, 69, 43, 32, 56, 34, 22, 43, 23, 10, 29, 8, 0, - 6, 0, 0, 0, 0, 0, 101, 45, 145, 91, 35, 129, 80, 26, 116, - 69, 15, 101, 59, 0, 86, 46, 0, 71, 31, 0, 55, 0, 0, 33, - 0, 0, 0, 104, 44, 132, 92, 36, 118, 82, 28, 105, 71, 17, 91, - 58, 3, 77, 46, 0, 63, 31, 0, 48, 2, 0, 26, 0, 0, 0, - 104, 46, 121, 93, 37, 107, 82, 30, 96, 70, 20, 83, 58, 6, 70, - 46, 0, 57, 32, 0, 41, 4, 0, 20, 0, 0, 0, 104, 48, 110, - 93, 40, 98, 82, 31, 87, 70, 22, 74, 59, 9, 62, 45, 0, 49, - 31, 0, 35, 6, 0, 13, 0, 0, 0, 104, 48, 99, 92, 41, 88, - 82, 32, 77, 70, 23, 65, 58, 11, 54, 46, 0, 42, 32, 0, 27, - 7, 0, 5, 0, 0, 0, 105, 50, 88, 93, 41, 77, 82, 34, 68, - 71, 24, 57, 58, 13, 46, 45, 1, 35, 31, 0, 21, 7, 0, 2, - 0, 0, 0, 105, 50, 76, 94, 41, 66, 83, 34, 57, 71, 25, 47, - 58, 15, 37, 45, 2, 25, 32, 0, 11, 7, 0, 0, 0, 0, 0, - 106, 50, 64, 94, 42, 55, 83, 35, 47, 71, 26, 38, 58, 16, 27, - 45, 4, 17, 31, 0, 4, 7, 0, 0, 0, 0, 0, 106, 51, 54, - 95, 42, 45, 83, 35, 38, 71, 27, 30, 58, 16, 19, 45, 5, 7, - 30, 0, 0, 6, 0, 0, 0, 0, 0, 0, 181, 240, 0, 162, 216, - 0, 144, 193, 0, 126, 168, 0, 109, 146, 0, 91, 123, 0, 71, 98, - 0, 48, 71, 0, 9, 34, 0, 179, 218, 0, 161, 195, 0, 144, 174, - 0, 126, 153, 0, 108, 132, 0, 90, 110, 0, 71, 88, 0, 48, 63, - 0, 8, 29, 0, 178, 197, 0, 159, 177, 0, 143, 159, 0, 125, 139, - 0, 107, 119, 0, 90, 99, 0, 71, 79, 0, 48, 55, 0, 8, 22, - 0, 177, 177, 0, 158, 158, 0, 142, 141, 0, 124, 123, 0, 107, 106, - 0, 89, 88, 0, 71, 70, 0, 48, 47, 0, 8, 14, 0, 176, 157, - 0, 158, 141, 0, 141, 126, 0, 123, 109, 0, 106, 93, 0, 89, 78, - 0, 70, 60, 0, 47, 39, 0, 7, 5, 0, 175, 138, 0, 157, 123, - 0, 141, 110, 0, 123, 96, 0, 105, 81, 0, 88, 67, 0, 70, 51, - 0, 48, 30, 0, 6, 0, 0, 173, 115, 0, 155, 104, 0, 140, 92, - 0, 122, 80, 0, 105, 67, 0, 88, 55, 0, 69, 40, 0, 47, 20, - 0, 6, 0, 0, 173, 94, 0, 155, 85, 0, 139, 75, 0, 121, 64, - 0, 104, 53, 0, 88, 42, 0, 70, 28, 0, 47, 9, 0, 6, 0, - 0, 173, 76, 0, 155, 70, 0, 138, 61, 0, 122, 53, 0, 104, 44, - 0, 87, 32, 0, 69, 18, 0, 47, 0, 0, 6, 0, 0, 164, 226, - 0, 147, 203, 0, 131, 181, 0, 114, 158, 0, 97, 136, 0, 80, 115, - 0, 63, 92, 0, 40, 65, 0, 0, 30, 0, 162, 205, 0, 145, 184, - 0, 130, 164, 0, 114, 143, 0, 97, 124, 0, 81, 104, 0, 63, 83, - 0, 40, 58, 0, 0, 23, 0, 162, 187, 0, 145, 167, 0, 130, 150, - 0, 113, 131, 0, 96, 112, 0, 80, 93, 0, 62, 74, 0, 40, 50, - 0, 0, 16, 0, 160, 167, 0, 144, 150, 0, 129, 134, 0, 112, 116, - 0, 96, 100, 0, 80, 82, 0, 62, 65, 0, 40, 43, 0, 0, 7, - 0, 160, 148, 0, 143, 133, 0, 128, 118, 0, 111, 103, 0, 96, 88, - 0, 80, 73, 0, 62, 56, 0, 40, 35, 0, 0, 0, 0, 158, 130, - 0, 142, 117, 0, 127, 104, 0, 111, 89, 0, 95, 76, 0, 79, 62, - 0, 62, 46, 0, 40, 26, 0, 0, 0, 0, 158, 111, 0, 141, 99, - 0, 127, 88, 0, 111, 76, 0, 95, 63, 0, 79, 51, 0, 62, 37, - 0, 40, 18, 0, 0, 0, 0, 158, 91, 0, 141, 81, 0, 126, 72, - 0, 110, 62, 0, 94, 50, 0, 79, 39, 0, 62, 25, 0, 40, 5, - 0, 0, 0, 0, 157, 74, 0, 141, 66, 0, 126, 59, 0, 110, 49, - 0, 94, 40, 0, 78, 29, 0, 61, 15, 0, 40, 0, 0, 0, 0, - 0, 148, 214, 0, 133, 192, 0, 119, 171, 0, 103, 150, 0, 87, 129, - 0, 72, 108, 0, 55, 86, 0, 32, 61, 0, 0, 25, 0, 147, 193, - 0, 132, 173, 0, 118, 155, 0, 103, 136, 0, 87, 116, 0, 72, 98, - 0, 55, 78, 0, 32, 53, 0, 0, 17, 0, 147, 176, 0, 132, 158, - 0, 118, 142, 0, 102, 124, 0, 87, 106, 0, 72, 88, 0, 55, 69, - 0, 33, 46, 0, 0, 9, 0, 146, 159, 0, 131, 142, 0, 117, 127, - 0, 102, 111, 0, 87, 95, 0, 71, 79, 0, 55, 61, 0, 33, 39, - 0, 0, 2, 0, 145, 140, 0, 130, 126, 0, 117, 112, 0, 101, 98, - 0, 86, 83, 0, 71, 68, 0, 55, 52, 0, 33, 31, 0, 0, 0, - 0, 144, 124, 0, 130, 111, 0, 116, 99, 0, 101, 84, 0, 86, 72, - 0, 71, 59, 0, 55, 43, 0, 33, 23, 0, 0, 0, 0, 144, 106, - 0, 129, 94, 0, 115, 83, 0, 101, 72, 0, 85, 60, 0, 71, 48, - 0, 55, 34, 0, 33, 14, 0, 0, 0, 3, 143, 86, 0, 129, 77, - 0, 115, 68, 0, 100, 58, 0, 85, 48, 0, 70, 36, 0, 54, 22, - 0, 33, 3, 0, 0, 0, 18, 143, 72, 13, 128, 63, 0, 115, 57, - 0, 100, 47, 0, 85, 37, 0, 70, 26, 0, 54, 13, 0, 33, 0, - 0, 0, 0, 0, 132, 200, 0, 118, 179, 0, 105, 161, 0, 91, 140, - 0, 76, 121, 0, 62, 101, 0, 46, 81, 0, 24, 56, 0, 0, 19, - 0, 131, 182, 0, 118, 163, 0, 105, 146, 0, 91, 128, 0, 77, 110, - 0, 62, 91, 0, 46, 72, 0, 25, 48, 0, 0, 11, 0, 131, 165, - 0, 117, 149, 0, 104, 133, 0, 91, 116, 0, 77, 99, 0, 62, 82, - 0, 46, 64, 0, 25, 41, 0, 0, 4, 0, 131, 149, 0, 116, 134, - 0, 104, 119, 0, 91, 104, 0, 77, 89, 0, 62, 73, 0, 46, 56, - 0, 25, 34, 0, 0, 0, 10, 130, 133, 2, 116, 119, 0, 104, 106, - 0, 90, 91, 0, 76, 78, 0, 62, 64, 0, 46, 48, 0, 26, 27, - 0, 0, 0, 23, 130, 118, 20, 116, 104, 13, 103, 93, 3, 89, 79, - 0, 76, 67, 0, 62, 54, 0, 46, 39, 0, 26, 19, 0, 0, 0, - 33, 129, 101, 27, 115, 89, 19, 103, 79, 9, 89, 67, 0, 75, 56, - 0, 61, 43, 0, 46, 29, 0, 26, 10, 0, 0, 0, 41, 128, 83, - 35, 115, 73, 27, 102, 64, 15, 89, 55, 0, 76, 45, 0, 62, 33, - 0, 46, 18, 0, 26, 0, 0, 0, 0, 43, 129, 69, 38, 115, 61, - 30, 102, 54, 17, 89, 45, 2, 75, 34, 0, 61, 23, 0, 46, 9, - 0, 26, 0, 0, 0, 0, 1, 116, 188, 1, 104, 168, 0, 92, 151, - 0, 79, 132, 0, 66, 113, 0, 52, 94, 0, 36, 75, 0, 14, 52, - 0, 0, 14, 17, 116, 171, 16, 104, 153, 14, 92, 137, 8, 79, 119, - 0, 67, 102, 0, 53, 85, 0, 37, 67, 0, 16, 44, 0, 0, 4, - 31, 116, 155, 27, 104, 140, 21, 92, 125, 13, 79, 109, 3, 66, 93, - 0, 53, 77, 0, 37, 59, 0, 16, 38, 0, 0, 0, 37, 115, 141, - 30, 103, 126, 26, 92, 112, 16, 79, 98, 5, 66, 83, 0, 53, 67, - 0, 38, 51, 0, 17, 31, 0, 0, 0, 41, 115, 126, 37, 103, 112, - 31, 92, 100, 22, 79, 86, 10, 66, 72, 0, 53, 59, 0, 38, 44, - 0, 17, 23, 0, 0, 0, 48, 115, 111, 41, 102, 99, 34, 91, 88, - 24, 78, 76, 14, 66, 63, 0, 53, 50, 0, 38, 36, 0, 18, 15, - 0, 0, 0, 51, 115, 95, 46, 102, 85, 37, 91, 74, 26, 78, 63, - 16, 66, 52, 0, 53, 40, 0, 38, 26, 0, 18, 5, 0, 0, 0, - 55, 114, 80, 47, 102, 69, 40, 90, 60, 30, 78, 51, 19, 66, 41, - 3, 53, 29, 0, 38, 15, 0, 17, 0, 0, 0, 0, 56, 114, 66, - 50, 102, 58, 40, 91, 50, 32, 78, 41, 18, 66, 32, 4, 53, 21, - 0, 38, 5, 0, 17, 0, 0, 0, 0, 39, 102, 178, 37, 90, 159, - 30, 79, 142, 21, 68, 124, 14, 55, 106, 0, 42, 89, 0, 26, 70, - 0, 4, 46, 0, 0, 8, 48, 102, 161, 42, 90, 145, 35, 79, 128, - 26, 68, 112, 19, 55, 96, 3, 43, 79, 0, 27, 62, 0, 6, 40, - 0, 0, 0, 50, 102, 147, 44, 90, 132, 37, 79, 118, 30, 68, 102, - 20, 56, 87, 7, 43, 72, 0, 28, 55, 0, 6, 34, 0, 0, 0, - 53, 101, 133, 47, 90, 118, 41, 79, 106, 32, 68, 91, 21, 56, 78, - 9, 43, 63, 0, 28, 47, 0, 6, 26, 0, 0, 0, 57, 101, 119, - 50, 89, 106, 42, 79, 94, 34, 67, 81, 24, 56, 68, 9, 44, 55, - 0, 29, 40, 0, 6, 19, 0, 0, 0, 60, 100, 105, 50, 90, 94, - 45, 80, 83, 36, 68, 71, 24, 56, 59, 11, 44, 46, 0, 29, 32, - 0, 7, 12, 0, 0, 0, 63, 101, 91, 55, 90, 80, 46, 79, 70, - 37, 68, 59, 26, 56, 49, 12, 44, 37, 1, 29, 23, 0, 7, 3, - 0, 0, 0, 64, 101, 75, 56, 89, 67, 48, 79, 57, 37, 68, 48, - 27, 56, 37, 15, 44, 26, 0, 29, 12, 0, 7, 0, 0, 0, 0, - 66, 101, 64, 58, 89, 55, 49, 79, 47, 39, 68, 38, 27, 56, 29, - 14, 44, 18, 1, 30, 2, 0, 7, 0, 0, 0, 0, 57, 86, 165, - 51, 75, 148, 45, 65, 133, 38, 54, 116, 28, 43, 100, 16, 29, 83, - 0, 13, 64, 0, 0, 42, 0, 0, 3, 60, 86, 151, 55, 75, 135, - 47, 66, 121, 39, 55, 105, 30, 44, 90, 18, 31, 74, 3, 16, 57, - 0, 1, 35, 0, 0, 0, 62, 86, 139, 56, 75, 123, 49, 66, 110, - 40, 55, 95, 30, 44, 81, 19, 31, 66, 4, 17, 51, 0, 1, 29, - 0, 0, 0, 65, 86, 125, 56, 76, 112, 49, 66, 99, 39, 55, 86, - 31, 44, 72, 19, 32, 59, 5, 18, 44, 0, 1, 23, 0, 0, 0, - 67, 86, 113, 58, 75, 100, 51, 66, 88, 41, 56, 77, 31, 45, 64, - 20, 32, 51, 6, 18, 35, 0, 1, 14, 0, 0, 0, 69, 86, 99, - 61, 76, 88, 52, 66, 78, 43, 56, 66, 32, 45, 55, 20, 33, 42, - 7, 19, 27, 0, 1, 6, 0, 0, 0, 69, 86, 86, 61, 76, 75, - 53, 67, 66, 43, 56, 55, 33, 45, 45, 21, 34, 34, 8, 20, 20, - 0, 2, 2, 0, 0, 0, 71, 86, 72, 63, 75, 62, 54, 66, 55, - 45, 56, 45, 33, 45, 35, 22, 34, 23, 7, 20, 8, 0, 2, 0, - 0, 0, 0, 71, 86, 62, 64, 75, 53, 55, 66, 46, 45, 56, 36, - 33, 46, 27, 22, 34, 15, 8, 20, 0, 0, 2, 0, 0, 0, 0, - 69, 67, 156, 61, 58, 140, 53, 50, 125, 45, 39, 108, 35, 28, 93, - 25, 12, 77, 12, 0, 59, 0, 0, 37, 0, 0, 0, 71, 68, 142, - 63, 59, 126, 56, 50, 114, 47, 40, 98, 37, 28, 84, 26, 15, 68, - 12, 0, 53, 0, 0, 30, 0, 0, 0, 72, 68, 130, 63, 59, 116, - 56, 50, 104, 47, 40, 90, 38, 30, 75, 27, 16, 61, 13, 0, 46, - 0, 0, 24, 0, 0, 0, 73, 69, 118, 65, 59, 105, 57, 51, 92, - 47, 41, 80, 37, 30, 67, 26, 18, 53, 14, 1, 39, 0, 0, 18, - 0, 0, 0, 74, 69, 106, 65, 60, 93, 57, 51, 82, 48, 41, 70, - 38, 31, 59, 26, 19, 46, 13, 2, 32, 0, 0, 10, 0, 0, 0, - 76, 69, 95, 66, 61, 84, 58, 52, 73, 48, 42, 61, 37, 32, 50, - 26, 20, 38, 14, 4, 24, 0, 0, 4, 0, 0, 0, 76, 69, 81, - 68, 60, 72, 58, 52, 62, 48, 42, 51, 38, 32, 41, 27, 21, 30, - 14, 4, 16, 0, 0, 1, 0, 0, 0, 76, 69, 68, 68, 61, 60, - 60, 52, 51, 49, 43, 41, 38, 33, 32, 27, 21, 20, 14, 5, 5, - 0, 0, 0, 0, 0, 0, 78, 70, 59, 69, 61, 50, 60, 52, 42, - 49, 43, 34, 39, 33, 24, 27, 22, 13, 14, 7, 1, 0, 0, 0, - 0, 0, 0, 75, 46, 146, 68, 38, 131, 60, 30, 117, 50, 19, 102, - 41, 4, 87, 29, 0, 72, 13, 0, 55, 0, 0, 33, 0, 0, 0, - 78, 47, 132, 70, 39, 119, 61, 30, 105, 53, 20, 92, 42, 5, 78, - 30, 0, 64, 13, 0, 49, 0, 0, 27, 0, 0, 0, 79, 48, 122, - 70, 40, 108, 62, 32, 96, 52, 22, 84, 42, 9, 71, 30, 0, 58, - 14, 0, 42, 0, 0, 20, 0, 0, 0, 79, 50, 111, 70, 42, 99, - 62, 33, 88, 52, 23, 74, 41, 11, 63, 29, 0, 50, 14, 0, 36, - 0, 0, 14, 0, 0, 0, 80, 50, 99, 70, 42, 89, 61, 34, 78, - 52, 25, 67, 41, 14, 55, 30, 0, 42, 15, 0, 28, 0, 0, 6, - 0, 0, 0, 81, 51, 89, 71, 43, 78, 62, 35, 69, 52, 25, 58, - 42, 15, 47, 30, 3, 36, 15, 0, 22, 0, 0, 3, 0, 0, 0, - 81, 51, 77, 71, 44, 68, 63, 36, 59, 53, 26, 49, 41, 16, 38, - 31, 4, 27, 16, 0, 12, 0, 0, 0, 0, 0, 0, 81, 52, 65, - 72, 43, 56, 63, 36, 48, 53, 27, 39, 41, 17, 29, 30, 4, 18, - 14, 0, 3, 0, 0, 0, 0, 0, 0, 81, 52, 55, 73, 44, 47, - 64, 36, 39, 53, 28, 32, 42, 18, 21, 31, 6, 9, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 174, 239, 0, 156, 214, 0, 139, 192, - 0, 121, 168, 0, 105, 145, 0, 87, 123, 0, 68, 98, 0, 46, 70, - 0, 3, 35, 0, 172, 217, 0, 155, 194, 0, 139, 173, 0, 121, 152, - 0, 104, 130, 0, 87, 110, 0, 69, 88, 0, 46, 63, 0, 4, 28, - 0, 171, 197, 0, 153, 175, 0, 138, 158, 0, 121, 139, 0, 103, 118, - 0, 86, 100, 0, 68, 79, 0, 46, 55, 0, 4, 22, 0, 170, 177, - 0, 152, 158, 0, 136, 141, 0, 119, 124, 0, 103, 106, 0, 86, 88, - 0, 68, 70, 0, 45, 47, 0, 3, 14, 0, 169, 157, 0, 152, 141, - 0, 136, 126, 0, 119, 109, 0, 102, 94, 0, 86, 78, 0, 68, 60, - 0, 46, 39, 0, 3, 5, 0, 167, 138, 0, 150, 124, 0, 135, 111, - 0, 118, 97, 0, 102, 82, 0, 85, 68, 0, 68, 52, 0, 46, 31, - 0, 3, 0, 0, 167, 118, 0, 150, 104, 0, 135, 94, 0, 118, 81, - 0, 101, 69, 0, 84, 56, 0, 67, 41, 0, 45, 21, 0, 3, 0, - 0, 166, 97, 0, 149, 87, 0, 134, 77, 0, 117, 67, 0, 101, 56, - 0, 85, 44, 0, 67, 30, 0, 45, 10, 0, 3, 0, 0, 165, 79, - 0, 149, 73, 0, 133, 64, 0, 117, 56, 0, 101, 46, 0, 85, 34, - 0, 68, 21, 0, 46, 1, 0, 3, 0, 0, 158, 225, 0, 141, 201, - 0, 126, 180, 0, 109, 158, 0, 94, 136, 0, 78, 114, 0, 60, 91, - 0, 38, 66, 0, 0, 30, 0, 156, 203, 0, 140, 183, 0, 125, 164, - 0, 109, 143, 0, 94, 124, 0, 78, 104, 0, 61, 83, 0, 38, 57, - 0, 0, 23, 0, 156, 186, 0, 140, 166, 0, 125, 150, 0, 109, 130, - 0, 93, 111, 0, 77, 93, 0, 60, 74, 0, 38, 50, 0, 0, 17, - 0, 155, 167, 0, 138, 149, 0, 124, 134, 0, 109, 117, 0, 93, 100, - 0, 76, 83, 0, 60, 65, 0, 38, 43, 0, 0, 9, 0, 153, 147, - 0, 138, 134, 0, 124, 120, 0, 107, 103, 0, 92, 88, 0, 77, 73, - 0, 60, 56, 0, 38, 35, 0, 0, 0, 0, 153, 131, 0, 137, 118, - 0, 122, 105, 0, 107, 90, 0, 91, 76, 0, 76, 63, 0, 60, 47, - 0, 39, 28, 0, 0, 0, 0, 153, 111, 0, 136, 100, 0, 123, 90, - 0, 107, 77, 0, 92, 65, 0, 76, 52, 0, 60, 37, 0, 38, 18, - 0, 0, 0, 0, 152, 93, 0, 136, 82, 0, 122, 74, 0, 106, 63, - 0, 91, 52, 0, 76, 40, 0, 59, 26, 0, 38, 6, 0, 0, 0, - 0, 151, 78, 0, 136, 69, 0, 121, 61, 0, 106, 52, 0, 91, 43, - 0, 76, 32, 0, 59, 17, 0, 38, 0, 0, 0, 0, 0, 143, 213, - 0, 128, 191, 0, 115, 171, 0, 100, 149, 0, 84, 128, 0, 69, 108, - 0, 52, 86, 0, 30, 61, 0, 0, 25, 0, 142, 193, 0, 127, 173, - 0, 114, 154, 0, 99, 134, 0, 84, 116, 0, 69, 98, 0, 52, 77, - 0, 31, 53, 0, 0, 18, 0, 141, 176, 0, 127, 158, 0, 114, 141, - 0, 98, 122, 0, 84, 105, 0, 69, 88, 0, 53, 69, 0, 31, 46, - 0, 0, 9, 0, 141, 159, 0, 126, 142, 0, 113, 127, 0, 98, 110, - 0, 83, 95, 0, 69, 78, 0, 53, 60, 0, 32, 39, 0, 0, 2, - 0, 140, 140, 0, 126, 126, 0, 112, 112, 0, 98, 98, 0, 83, 83, - 0, 68, 69, 0, 52, 52, 0, 31, 31, 0, 0, 0, 0, 140, 124, - 0, 125, 112, 0, 112, 100, 0, 97, 86, 0, 83, 72, 0, 68, 59, - 0, 52, 44, 0, 31, 23, 0, 0, 0, 0, 139, 106, 0, 125, 96, - 0, 111, 85, 0, 97, 72, 0, 83, 62, 0, 68, 49, 0, 52, 35, - 0, 31, 15, 0, 0, 0, 0, 138, 88, 0, 124, 79, 0, 111, 70, - 0, 96, 59, 0, 82, 48, 0, 68, 38, 0, 52, 24, 0, 31, 4, - 0, 0, 0, 0, 139, 76, 0, 124, 66, 0, 111, 58, 0, 96, 50, - 0, 82, 40, 0, 68, 29, 0, 52, 15, 0, 31, 0, 0, 0, 0, - 0, 129, 200, 0, 114, 179, 0, 102, 160, 0, 87, 139, 0, 74, 120, - 0, 60, 101, 0, 44, 81, 0, 22, 56, 0, 0, 19, 0, 127, 181, - 0, 114, 163, 0, 102, 146, 0, 88, 127, 0, 74, 109, 0, 60, 91, - 0, 44, 72, 0, 23, 48, 0, 0, 11, 0, 127, 166, 0, 113, 148, - 0, 101, 133, 0, 87, 115, 0, 74, 99, 0, 60, 82, 0, 44, 64, - 0, 23, 42, 0, 0, 4, 0, 127, 150, 0, 113, 134, 0, 101, 119, - 0, 87, 104, 0, 74, 89, 0, 60, 73, 0, 44, 56, 0, 23, 35, - 0, 0, 0, 0, 125, 134, 0, 112, 118, 0, 100, 106, 0, 87, 92, - 0, 73, 78, 0, 60, 64, 0, 44, 48, 0, 23, 27, 0, 0, 0, - 0, 125, 118, 0, 112, 105, 0, 100, 94, 0, 86, 80, 0, 73, 68, - 0, 60, 54, 0, 44, 39, 0, 23, 20, 0, 0, 0, 0, 125, 101, - 0, 111, 90, 0, 99, 80, 0, 86, 69, 0, 73, 58, 0, 59, 45, - 0, 44, 30, 0, 23, 11, 0, 0, 0, 0, 124, 85, 0, 111, 75, - 0, 99, 66, 0, 86, 56, 0, 73, 45, 0, 59, 34, 0, 44, 20, - 0, 23, 1, 0, 0, 0, 0, 125, 72, 0, 111, 62, 0, 99, 56, - 0, 86, 46, 0, 73, 36, 0, 60, 26, 0, 44, 12, 0, 23, 0, - 0, 0, 0, 0, 114, 188, 0, 101, 167, 0, 89, 150, 0, 77, 131, - 0, 64, 113, 0, 50, 95, 0, 34, 75, 0, 12, 52, 0, 0, 14, - 0, 113, 170, 0, 101, 153, 0, 89, 137, 0, 77, 120, 0, 64, 102, - 0, 50, 85, 0, 35, 67, 0, 12, 44, 0, 0, 4, 0, 113, 156, - 0, 100, 139, 0, 89, 125, 0, 77, 109, 0, 64, 92, 0, 51, 77, - 0, 35, 60, 0, 12, 38, 0, 0, 0, 0, 112, 141, 0, 100, 126, - 0, 89, 113, 0, 77, 98, 0, 64, 83, 0, 51, 68, 0, 35, 51, - 0, 12, 30, 0, 0, 0, 0, 112, 127, 0, 100, 112, 0, 89, 100, - 0, 76, 87, 0, 64, 74, 0, 51, 59, 0, 35, 44, 0, 13, 24, - 0, 0, 0, 0, 112, 111, 0, 100, 100, 0, 88, 88, 0, 76, 76, - 0, 64, 64, 0, 51, 52, 0, 36, 37, 0, 13, 17, 0, 0, 0, - 0, 111, 96, 0, 99, 85, 0, 88, 76, 0, 76, 64, 0, 64, 53, - 0, 51, 41, 0, 36, 27, 0, 13, 6, 0, 0, 0, 0, 111, 81, - 0, 99, 71, 0, 88, 62, 0, 76, 52, 0, 64, 43, 0, 51, 31, - 0, 36, 17, 0, 13, 0, 0, 0, 0, 0, 111, 69, 0, 99, 60, - 0, 88, 52, 0, 75, 43, 0, 63, 34, 0, 51, 21, 0, 36, 7, - 0, 13, 0, 0, 0, 0, 0, 99, 177, 0, 88, 158, 0, 77, 141, - 0, 66, 123, 0, 53, 106, 0, 40, 89, 0, 25, 71, 0, 5, 47, - 0, 0, 8, 0, 99, 160, 0, 88, 144, 0, 77, 129, 0, 66, 112, - 0, 54, 97, 0, 41, 80, 0, 26, 62, 0, 5, 40, 0, 0, 0, - 0, 99, 147, 0, 87, 132, 0, 78, 117, 0, 66, 102, 0, 54, 87, - 0, 42, 72, 0, 26, 55, 0, 5, 34, 0, 0, 0, 0, 99, 134, - 0, 88, 119, 0, 77, 107, 0, 66, 92, 0, 54, 78, 0, 42, 64, - 0, 27, 48, 0, 5, 27, 0, 0, 0, 0, 99, 120, 0, 87, 107, - 0, 78, 94, 0, 66, 81, 0, 54, 68, 0, 42, 55, 0, 27, 40, - 0, 6, 20, 0, 0, 0, 0, 98, 105, 0, 87, 94, 0, 77, 84, - 0, 65, 71, 0, 55, 59, 0, 42, 47, 0, 28, 33, 0, 6, 12, - 0, 0, 0, 0, 98, 93, 0, 87, 81, 0, 77, 72, 0, 66, 61, - 0, 54, 49, 0, 42, 37, 0, 28, 24, 0, 6, 4, 0, 0, 0, - 0, 98, 77, 0, 87, 68, 0, 77, 59, 0, 65, 49, 0, 54, 39, - 0, 42, 27, 0, 29, 14, 0, 6, 0, 0, 0, 0, 1, 98, 65, - 7, 87, 56, 0, 77, 49, 0, 66, 41, 0, 54, 30, 0, 42, 19, - 0, 29, 3, 0, 6, 0, 0, 0, 0, 0, 84, 166, 0, 74, 149, - 0, 64, 134, 0, 53, 117, 0, 41, 100, 0, 28, 83, 0, 11, 64, - 0, 0, 42, 0, 0, 3, 0, 84, 151, 0, 74, 135, 0, 64, 121, - 0, 53, 105, 0, 42, 90, 0, 30, 75, 0, 14, 58, 0, 0, 36, - 0, 0, 0, 0, 84, 138, 0, 74, 124, 1, 64, 110, 0, 54, 95, - 0, 43, 81, 0, 30, 67, 0, 15, 51, 0, 1, 29, 0, 0, 0, - 14, 84, 126, 12, 74, 112, 2, 65, 99, 0, 54, 85, 0, 44, 73, - 0, 31, 59, 0, 16, 44, 0, 1, 23, 0, 0, 0, 16, 84, 113, - 13, 74, 100, 6, 65, 89, 0, 54, 77, 0, 44, 65, 0, 31, 51, - 0, 17, 36, 0, 1, 16, 0, 0, 0, 24, 84, 100, 18, 74, 88, - 13, 65, 78, 2, 55, 68, 0, 44, 55, 0, 32, 43, 0, 18, 28, - 0, 1, 6, 0, 0, 0, 26, 84, 87, 24, 74, 76, 17, 65, 67, - 7, 54, 57, 0, 44, 46, 0, 32, 35, 0, 19, 21, 0, 2, 3, - 0, 0, 0, 30, 84, 74, 28, 74, 64, 20, 65, 55, 12, 55, 46, - 0, 44, 35, 0, 32, 24, 0, 18, 9, 0, 1, 0, 0, 0, 0, - 32, 84, 63, 28, 74, 54, 21, 65, 47, 13, 54, 38, 0, 44, 28, - 0, 32, 16, 0, 18, 1, 0, 1, 0, 0, 0, 0, 30, 67, 155, - 20, 58, 139, 20, 49, 126, 12, 39, 110, 0, 27, 94, 0, 13, 77, - 0, 0, 60, 0, 0, 37, 0, 0, 0, 35, 67, 142, 30, 58, 126, - 23, 50, 114, 16, 40, 99, 7, 29, 85, 0, 15, 69, 0, 0, 52, - 0, 0, 30, 0, 0, 0, 35, 68, 131, 30, 59, 116, 27, 50, 104, - 18, 40, 90, 9, 29, 76, 0, 17, 62, 0, 2, 46, 0, 0, 24, - 0, 0, 0, 37, 69, 119, 33, 59, 106, 27, 51, 94, 21, 41, 80, - 9, 30, 67, 0, 18, 54, 0, 3, 39, 0, 0, 18, 0, 0, 0, - 40, 69, 107, 36, 59, 94, 28, 51, 84, 18, 41, 72, 10, 31, 60, - 0, 19, 47, 0, 4, 32, 0, 0, 10, 0, 0, 0, 42, 69, 95, - 36, 59, 84, 29, 51, 74, 19, 41, 63, 10, 31, 52, 0, 20, 39, - 0, 4, 25, 0, 0, 4, 0, 0, 0, 43, 69, 83, 38, 60, 73, - 32, 51, 62, 23, 42, 53, 11, 31, 42, 0, 20, 31, 0, 5, 17, - 0, 0, 1, 0, 0, 0, 45, 69, 70, 39, 60, 60, 33, 51, 52, - 24, 42, 43, 13, 32, 33, 0, 21, 21, 0, 5, 6, 0, 0, 0, - 0, 0, 0, 47, 69, 59, 41, 60, 51, 34, 51, 43, 24, 42, 35, - 12, 33, 26, 1, 22, 14, 0, 5, 1, 0, 0, 0, 0, 0, 0, - 46, 48, 146, 42, 40, 131, 36, 32, 118, 27, 22, 103, 17, 6, 88, - 5, 0, 73, 0, 0, 55, 0, 0, 33, 0, 0, 0, 48, 48, 133, - 44, 40, 119, 37, 32, 107, 28, 22, 93, 20, 8, 79, 7, 0, 65, - 0, 0, 49, 0, 0, 27, 0, 0, 0, 48, 50, 123, 44, 41, 109, - 37, 33, 97, 30, 23, 83, 21, 11, 71, 8, 0, 58, 0, 0, 42, - 0, 0, 21, 0, 0, 0, 49, 51, 111, 45, 42, 99, 38, 34, 87, - 29, 25, 75, 20, 13, 63, 8, 0, 51, 0, 0, 36, 0, 0, 14, - 0, 0, 0, 52, 52, 100, 44, 43, 89, 38, 35, 79, 29, 26, 68, - 19, 15, 56, 10, 1, 43, 0, 0, 28, 0, 0, 6, 0, 0, 0, - 52, 52, 90, 47, 44, 79, 39, 36, 70, 30, 27, 59, 20, 16, 47, - 9, 2, 36, 0, 0, 22, 0, 0, 2, 0, 0, 0, 52, 53, 78, - 46, 44, 68, 39, 37, 60, 32, 27, 49, 22, 17, 39, 10, 3, 28, - 0, 0, 12, 0, 0, 0, 0, 0, 0, 53, 53, 66, 47, 44, 57, - 40, 36, 48, 32, 27, 39, 22, 18, 30, 9, 4, 18, 0, 0, 3, - 0, 0, 0, 0, 0, 0, 54, 53, 57, 48, 45, 49, 41, 37, 41, - 33, 28, 32, 22, 19, 23, 11, 6, 10, 1, 0, 0, 0, 0, 0, - 0, 0, 0, -}; -void AdobeCMYK_to_sRGB1(uint8_t c, - uint8_t m, - uint8_t y, - uint8_t k, - uint8_t& R, - uint8_t& G, - uint8_t& B) { - int fix_c = c << 8; - int fix_m = m << 8; - int fix_y = y << 8; - int fix_k = k << 8; - int c_index = (fix_c + 4096) >> 13; - int m_index = (fix_m + 4096) >> 13; - int y_index = (fix_y + 4096) >> 13; - int k_index = (fix_k + 4096) >> 13; - int pos = (c_index * 9 * 9 * 9 + m_index * 9 * 9 + y_index * 9 + k_index) * 3; - int fix_r = g_CMYKSamples[pos] << 8; - int fix_g = g_CMYKSamples[pos + 1] << 8; - int fix_b = g_CMYKSamples[pos + 2] << 8; - int c1_index = fix_c >> 13; - if (c1_index == c_index) { - c1_index = c1_index == 8 ? c1_index - 1 : c1_index + 1; - } - int m1_index = fix_m >> 13; - if (m1_index == m_index) { - m1_index = m1_index == 8 ? m1_index - 1 : m1_index + 1; - } - int y1_index = fix_y >> 13; - if (y1_index == y_index) { - y1_index = y1_index == 8 ? y1_index - 1 : y1_index + 1; - } - int k1_index = fix_k >> 13; - if (k1_index == k_index) { - k1_index = k1_index == 8 ? k1_index - 1 : k1_index + 1; - } - int c1_pos = pos + (c1_index - c_index) * 9 * 9 * 9 * 3; - int m1_pos = pos + (m1_index - m_index) * 9 * 9 * 3; - int y1_pos = pos + (y1_index - y_index) * 9 * 3; - int k1_pos = pos + (k1_index - k_index) * 3; - int c_r_delta = g_CMYKSamples[pos] - g_CMYKSamples[c1_pos]; - int c_g_delta = g_CMYKSamples[pos + 1] - g_CMYKSamples[c1_pos + 1]; - int c_b_delta = g_CMYKSamples[pos + 2] - g_CMYKSamples[c1_pos + 2]; - int m_r_delta = g_CMYKSamples[pos] - g_CMYKSamples[m1_pos]; - int m_g_delta = g_CMYKSamples[pos + 1] - g_CMYKSamples[m1_pos + 1]; - int m_b_delta = g_CMYKSamples[pos + 2] - g_CMYKSamples[m1_pos + 2]; - int y_r_delta = g_CMYKSamples[pos] - g_CMYKSamples[y1_pos]; - int y_g_delta = g_CMYKSamples[pos + 1] - g_CMYKSamples[y1_pos + 1]; - int y_b_delta = g_CMYKSamples[pos + 2] - g_CMYKSamples[y1_pos + 2]; - int k_r_delta = g_CMYKSamples[pos] - g_CMYKSamples[k1_pos]; - int k_g_delta = g_CMYKSamples[pos + 1] - g_CMYKSamples[k1_pos + 1]; - int k_b_delta = g_CMYKSamples[pos + 2] - g_CMYKSamples[k1_pos + 2]; - int c_rate = (fix_c - (c_index << 13)) * (c_index - c1_index); - fix_r += c_r_delta * c_rate / 32; - fix_g += c_g_delta * c_rate / 32; - fix_b += c_b_delta * c_rate / 32; - int m_rate = (fix_m - (m_index << 13)) * (m_index - m1_index); - fix_r += m_r_delta * m_rate / 32; - fix_g += m_g_delta * m_rate / 32; - fix_b += m_b_delta * m_rate / 32; - int y_rate = (fix_y - (y_index << 13)) * (y_index - y1_index); - fix_r += y_r_delta * y_rate / 32; - fix_g += y_g_delta * y_rate / 32; - fix_b += y_b_delta * y_rate / 32; - int k_rate = (fix_k - (k_index << 13)) * (k_index - k1_index); - fix_r += k_r_delta * k_rate / 32; - fix_g += k_g_delta * k_rate / 32; - fix_b += k_b_delta * k_rate / 32; - if (fix_r < 0) { - fix_r = 0; - } - if (fix_g < 0) { - fix_g = 0; - } - if (fix_b < 0) { - fix_b = 0; - } - R = fix_r >> 8; - G = fix_g >> 8; - B = fix_b >> 8; -} -void AdobeCMYK_to_sRGB(FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B) { - // Convert to uint8_t with round-to-nearest. Avoid using FXSYS_round because - // it is incredibly expensive with VC++ (tested on VC++ 2015) because round() - // is very expensive. - // The 'magic' value of 0.49999997f, the float that precedes 0.5f, was chosen - // because it gives identical results to FXSYS_round(). Using the constant - // 0.5f gives different results (1 instead of 0) for one value, 0.0019607842. - // That value is close to the cusp but zero is the correct answer, and - // getting the same answer as before is desirable. - // All floats from 0.0 to 1.0 were tested and now give the same results. - const float rounding_offset = 0.49999997f; - uint8_t c1 = int(c * 255.f + rounding_offset); - uint8_t m1 = int(m * 255.f + rounding_offset); - uint8_t y1 = int(y * 255.f + rounding_offset); - uint8_t k1 = int(k * 255.f + rounding_offset); - - ASSERT(c1 == FXSYS_round(c * 255)); - ASSERT(m1 == FXSYS_round(m * 255)); - ASSERT(y1 == FXSYS_round(y * 255)); - ASSERT(k1 == FXSYS_round(k * 255)); - - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(c1, m1, y1, k1, r, g, b); - // Multiply by a constant rather than dividing because division is much - // more expensive. - R = r * (1.0f / 255); - G = g * (1.0f / 255); - B = b * (1.0f / 255); + if (pTransform) + cmsDoTransform(pTransform->m_hTransform, pSrc, pDest, pixels); } diff --git a/core/fxcodec/codec/fx_codec_jbig.cpp b/core/fxcodec/codec/fx_codec_jbig.cpp index 926541f07dce19289f5b0f6895de880e13d2c56c..543aeebc8787a739902666da2bc69c433acc1d2f 100644 --- a/core/fxcodec/codec/fx_codec_jbig.cpp +++ b/core/fxcodec/codec/fx_codec_jbig.cpp @@ -33,8 +33,7 @@ CCodec_Jbig2Context::CCodec_Jbig2Context() m_pGlobalStream(nullptr), m_pSrcStream(nullptr), m_dest_buf(0), - m_dest_pitch(0), - m_pPause(nullptr) {} + m_dest_pitch(0) {} CCodec_Jbig2Context::~CCodec_Jbig2Context() {} @@ -45,11 +44,11 @@ FXCODEC_STATUS CCodec_Jbig2Module::StartDecode( std::unique_ptr* pContextHolder, uint32_t width, uint32_t height, - CPDF_StreamAcc* src_stream, - CPDF_StreamAcc* global_stream, + const RetainPtr& src_stream, + const RetainPtr& global_stream, uint8_t* dest_buf, uint32_t dest_pitch, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { if (!pJbig2Context) return FXCODEC_STATUS_ERR_PARAMS; @@ -61,45 +60,34 @@ FXCODEC_STATUS CCodec_Jbig2Module::StartDecode( pJbig2Context->m_pGlobalStream = global_stream; pJbig2Context->m_dest_buf = dest_buf; pJbig2Context->m_dest_pitch = dest_pitch; - pJbig2Context->m_pPause = pPause; - FXSYS_memset(dest_buf, 0, height * dest_pitch); + memset(dest_buf, 0, height * dest_pitch); pJbig2Context->m_pContext = pdfium::MakeUnique( global_stream, src_stream, pJBig2DocumentContext->GetSymbolDictCache(), - pPause, false); - if (!pJbig2Context->m_pContext) - return FXCODEC_STATUS_ERROR; - + false); int ret = pJbig2Context->m_pContext->getFirstPage(dest_buf, width, height, dest_pitch, pPause); - if (pJbig2Context->m_pContext->GetProcessingStatus() == - FXCODEC_STATUS_DECODE_FINISH) { - pJbig2Context->m_pContext.reset(); - if (ret != JBIG2_SUCCESS) - return FXCODEC_STATUS_ERROR; - - int dword_size = height * dest_pitch / 4; - uint32_t* dword_buf = (uint32_t*)dest_buf; - for (int i = 0; i < dword_size; i++) - dword_buf[i] = ~dword_buf[i]; - return FXCODEC_STATUS_DECODE_FINISH; - } - return pJbig2Context->m_pContext->GetProcessingStatus(); + return Decode(pJbig2Context, ret); } FXCODEC_STATUS CCodec_Jbig2Module::ContinueDecode( CCodec_Jbig2Context* pJbig2Context, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { int ret = pJbig2Context->m_pContext->Continue(pPause); - if (pJbig2Context->m_pContext->GetProcessingStatus() != - FXCODEC_STATUS_DECODE_FINISH) { - return pJbig2Context->m_pContext->GetProcessingStatus(); - } + return Decode(pJbig2Context, ret); +} + +FXCODEC_STATUS CCodec_Jbig2Module::Decode(CCodec_Jbig2Context* pJbig2Context, + int result) { + FXCODEC_STATUS status = pJbig2Context->m_pContext->GetProcessingStatus(); + if (status != FXCODEC_STATUS_DECODE_FINISH) + return status; + pJbig2Context->m_pContext.reset(); - if (ret != JBIG2_SUCCESS) + if (result != JBIG2_SUCCESS) return FXCODEC_STATUS_ERROR; int dword_size = pJbig2Context->m_height * pJbig2Context->m_dest_pitch / 4; - uint32_t* dword_buf = (uint32_t*)pJbig2Context->m_dest_buf; + uint32_t* dword_buf = reinterpret_cast(pJbig2Context->m_dest_buf); for (int i = 0; i < dword_size; i++) dword_buf[i] = ~dword_buf[i]; return FXCODEC_STATUS_DECODE_FINISH; diff --git a/core/fxcodec/codec/fx_codec_jpeg.cpp b/core/fxcodec/codec/fx_codec_jpeg.cpp index c79760557536aa64f3d9cff8831d9d9d0dc8dd4f..6e227ca20eba076c2c8dbeaae083f6c6f5337cde 100644 --- a/core/fxcodec/codec/fx_codec_jpeg.cpp +++ b/core/fxcodec/codec/fx_codec_jpeg.cpp @@ -9,10 +9,13 @@ #include #include -#include "core/fxcodec/codec/codec_int.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" #include "core/fxcodec/fx_codec.h" #include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/dib/cfx_dibsource.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" extern "C" { @@ -24,7 +27,23 @@ extern "C" { #else #include "third_party/libjpeg/jpeglib.h" #endif -} +} // extern "C" + +class CJpegContext : public CCodec_JpegModule::Context { + public: + CJpegContext(); + ~CJpegContext() override; + + jmp_buf* GetJumpMark() override { return &m_JumpMark; } + + jmp_buf m_JumpMark; + jpeg_decompress_struct m_Info; + jpeg_error_mgr m_ErrMgr; + jpeg_source_mgr m_SrcMgr; + unsigned int m_SkipSize; + void* (*m_AllocFunc)(unsigned int); + void (*m_FreeFunc)(void*); +}; extern "C" { @@ -71,14 +90,14 @@ static void _error_do_nothing1(j_common_ptr cinfo, int) {} static void _error_do_nothing2(j_common_ptr cinfo, char*) {} -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ static void _dest_do_nothing(j_compress_ptr cinfo) {} static boolean _dest_empty(j_compress_ptr cinfo) { return false; } -#endif -}; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +} // extern "C" #define JPEG_MARKER_ICC (JPEG_APP0 + 2) #define JPEG_MARKER_MAXSIZE 0xFFFF @@ -185,9 +204,9 @@ CCodec_JpegDecoder::CCodec_JpegDecoder() { m_pScanlineBuf = nullptr; m_bStarted = false; m_bInited = false; - FXSYS_memset(&cinfo, 0, sizeof(cinfo)); - FXSYS_memset(&jerr, 0, sizeof(jerr)); - FXSYS_memset(&src, 0, sizeof(src)); + memset(&cinfo, 0, sizeof(cinfo)); + memset(&jerr, 0, sizeof(jerr)); + memset(&src, 0, sizeof(src)); m_nDefaultScaleDenom = 1; } @@ -253,8 +272,7 @@ bool CCodec_JpegDecoder::Create(const uint8_t* src_buf, src.fill_input_buffer = _src_fill_buffer; src.resync_to_restart = _src_resync; m_bJpegTransform = ColorTransform; - if (src_size > 1 && - FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { + if (src_size > 1 && memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { ((uint8_t*)src_buf)[src_size - 2] = 0xFF; ((uint8_t*)src_buf)[src_size - 1] = 0xD9; } @@ -297,7 +315,7 @@ bool CCodec_JpegDecoder::v_Rewind() { return false; } if ((int)cinfo.output_width > m_OrigWidth) { - ASSERT(false); + NOTREACHED(); return false; } m_bStarted = true; @@ -345,71 +363,75 @@ bool CCodec_JpegModule::LoadInfo(const uint8_t* src_buf, bits_per_components, color_transform); } -struct FXJPEG_Context { - jmp_buf m_JumpMark; - jpeg_decompress_struct m_Info; - jpeg_error_mgr m_ErrMgr; - jpeg_source_mgr m_SrcMgr; - unsigned int m_SkipSize; - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; extern "C" { + static void _error_fatal1(j_common_ptr cinfo) { - longjmp(((FXJPEG_Context*)cinfo->client_data)->m_JumpMark, -1); + auto* pContext = reinterpret_cast(cinfo->client_data); + longjmp(pContext->m_JumpMark, -1); } -}; -extern "C" { + static void _src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) { - if (cinfo->src->bytes_in_buffer < (size_t)num) { - ((FXJPEG_Context*)cinfo->client_data)->m_SkipSize = - (unsigned int)(num - cinfo->src->bytes_in_buffer); + if (cinfo->src->bytes_in_buffer < static_cast(num)) { + auto* pContext = reinterpret_cast(cinfo->client_data); + pContext->m_SkipSize = (unsigned int)(num - cinfo->src->bytes_in_buffer); cinfo->src->bytes_in_buffer = 0; } else { cinfo->src->next_input_byte += num; cinfo->src->bytes_in_buffer -= num; } } -}; + static void* jpeg_alloc_func(unsigned int size) { return FX_Alloc(char, size); } + static void jpeg_free_func(void* p) { FX_Free(p); } -FXJPEG_Context* CCodec_JpegModule::Start() { - FXJPEG_Context* p = FX_Alloc(FXJPEG_Context, 1); - p->m_AllocFunc = jpeg_alloc_func; - p->m_FreeFunc = jpeg_free_func; - p->m_ErrMgr.error_exit = _error_fatal1; - p->m_ErrMgr.emit_message = _error_do_nothing1; - p->m_ErrMgr.output_message = _error_do_nothing; - p->m_ErrMgr.format_message = _error_do_nothing2; - p->m_ErrMgr.reset_error_mgr = _error_do_nothing; - p->m_SrcMgr.init_source = _src_do_nothing; - p->m_SrcMgr.term_source = _src_do_nothing; - p->m_SrcMgr.skip_input_data = _src_skip_data1; - p->m_SrcMgr.fill_input_buffer = _src_fill_buffer; - p->m_SrcMgr.resync_to_restart = _src_resync; - p->m_Info.client_data = p; - p->m_Info.err = &p->m_ErrMgr; - if (setjmp(p->m_JumpMark) == -1) { - return 0; - } - jpeg_create_decompress(&p->m_Info); - p->m_Info.src = &p->m_SrcMgr; - p->m_SkipSize = 0; - return p; + +} // extern "C" + +CJpegContext::CJpegContext() + : m_SkipSize(0), m_AllocFunc(jpeg_alloc_func), m_FreeFunc(jpeg_free_func) { + memset(&m_Info, 0, sizeof(m_Info)); + m_Info.client_data = this; + m_Info.err = &m_ErrMgr; + + memset(&m_ErrMgr, 0, sizeof(m_ErrMgr)); + m_ErrMgr.error_exit = _error_fatal1; + m_ErrMgr.emit_message = _error_do_nothing1; + m_ErrMgr.output_message = _error_do_nothing; + m_ErrMgr.format_message = _error_do_nothing2; + m_ErrMgr.reset_error_mgr = _error_do_nothing; + + memset(&m_SrcMgr, 0, sizeof(m_SrcMgr)); + m_SrcMgr.init_source = _src_do_nothing; + m_SrcMgr.term_source = _src_do_nothing; + m_SrcMgr.skip_input_data = _src_skip_data1; + m_SrcMgr.fill_input_buffer = _src_fill_buffer; + m_SrcMgr.resync_to_restart = _src_resync; } -void CCodec_JpegModule::Finish(FXJPEG_Context* ctx) { - jpeg_destroy_decompress(&ctx->m_Info); - ctx->m_FreeFunc(ctx); +CJpegContext::~CJpegContext() { + jpeg_destroy_decompress(&m_Info); } -void CCodec_JpegModule::Input(FXJPEG_Context* ctx, +std::unique_ptr CCodec_JpegModule::Start() { + // Use ordinary pointer until past the possibility of a longjump. + auto* pContext = new CJpegContext(); + if (setjmp(pContext->m_JumpMark) == -1) + return nullptr; + + jpeg_create_decompress(&pContext->m_Info); + pContext->m_Info.src = &pContext->m_SrcMgr; + pContext->m_SkipSize = 0; + return pdfium::WrapUnique(pContext); +} + +void CCodec_JpegModule::Input(Context* pContext, const unsigned char* src_buf, uint32_t src_size) { + auto* ctx = static_cast(pContext); if (ctx->m_SkipSize) { if (ctx->m_SkipSize > src_size) { ctx->m_SrcMgr.bytes_in_buffer = 0; @@ -425,20 +447,18 @@ void CCodec_JpegModule::Input(FXJPEG_Context* ctx, } #ifdef PDF_ENABLE_XFA -int CCodec_JpegModule::ReadHeader(FXJPEG_Context* ctx, +int CCodec_JpegModule::ReadHeader(Context* pContext, int* width, int* height, int* nComps, CFX_DIBAttribute* pAttribute) { #else // PDF_ENABLE_XFA -int CCodec_JpegModule::ReadHeader(FXJPEG_Context* ctx, +int CCodec_JpegModule::ReadHeader(Context* pContext, int* width, int* height, int* nComps) { #endif // PDF_ENABLE_XFA - if (setjmp(ctx->m_JumpMark) == -1) - return 1; - + auto* ctx = static_cast(pContext); int ret = jpeg_read_header(&ctx->m_Info, true); if (ret == JPEG_SUSPENDED) return 2; @@ -454,25 +474,22 @@ int CCodec_JpegModule::ReadHeader(FXJPEG_Context* ctx, return 0; } -bool CCodec_JpegModule::StartScanline(FXJPEG_Context* ctx, int down_scale) { - if (setjmp(ctx->m_JumpMark) == -1) - return false; - - ctx->m_Info.scale_denom = down_scale; +bool CCodec_JpegModule::StartScanline(Context* pContext, int down_scale) { + auto* ctx = static_cast(pContext); + ctx->m_Info.scale_denom = static_cast(down_scale); return !!jpeg_start_decompress(&ctx->m_Info); } -bool CCodec_JpegModule::ReadScanline(FXJPEG_Context* ctx, +bool CCodec_JpegModule::ReadScanline(Context* pContext, unsigned char* dest_buf) { - if (setjmp(ctx->m_JumpMark) == -1) - return false; - - int nlines = jpeg_read_scanlines(&ctx->m_Info, &dest_buf, 1); + auto* ctx = static_cast(pContext); + unsigned int nlines = jpeg_read_scanlines(&ctx->m_Info, &dest_buf, 1); return nlines == 1; } -uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, +uint32_t CCodec_JpegModule::GetAvailInput(Context* pContext, uint8_t** avail_buf_ptr) { + auto* ctx = static_cast(pContext); if (avail_buf_ptr) { *avail_buf_ptr = nullptr; if (ctx->m_SrcMgr.bytes_in_buffer > 0) { @@ -482,11 +499,11 @@ uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; } -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #define JPEG_BLOCK_SIZE 1048576 -bool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource, +bool CCodec_JpegModule::JpegEncode(const RetainPtr& pSource, uint8_t** dest_buf, - FX_STRSIZE* dest_size) { + size_t* dest_size) { struct jpeg_error_mgr jerr; jerr.error_exit = _error_do_nothing; jerr.emit_message = _error_do_nothing1; @@ -579,8 +596,8 @@ bool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource, jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); FX_Free(line_buf); - *dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer; + *dest_size = dest_buf_length - static_cast(dest.free_in_buffer); return true; } -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ diff --git a/core/fxcodec/codec/fx_codec_jpx_opj.cpp b/core/fxcodec/codec/fx_codec_jpx_opj.cpp index fa163567f4235eefa0ef9fe71cb863d4c2a838f1..89c512390d81543ddc8646ba9fc3a8a72db27cc8 100644 --- a/core/fxcodec/codec/fx_codec_jpx_opj.cpp +++ b/core/fxcodec/codec/fx_codec_jpx_opj.cpp @@ -7,172 +7,60 @@ #include #include #include +#include #include #include "core/fpdfapi/page/cpdf_colorspace.h" -#include "core/fxcodec/codec/codec_int.h" -#include "core/fxcodec/fx_codec.h" +#include "core/fxcodec/codec/ccodec_jpxmodule.h" +#include "core/fxcodec/codec/cjpx_decoder.h" +#include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_safe_types.h" -#include "third_party/lcms2-2.6/include/lcms2.h" +#include "third_party/base/ptr_util.h" #include "third_party/libopenjpeg20/openjpeg.h" +#include "third_party/libopenjpeg20/opj_malloc.h" -static void fx_error_callback(const char* msg, void* client_data) { - (void)client_data; -} -static void fx_warning_callback(const char* msg, void* client_data) { - (void)client_data; -} -static void fx_info_callback(const char* msg, void* client_data) { - (void)client_data; -} +namespace { -OPJ_SIZE_T opj_read_from_memory(void* p_buffer, - OPJ_SIZE_T nb_bytes, - void* p_user_data) { - DecodeData* srcData = static_cast(p_user_data); - if (!srcData || !srcData->src_data || srcData->src_size == 0) { - return static_cast(-1); - } - // Reads at EOF return an error code. - if (srcData->offset >= srcData->src_size) { - return static_cast(-1); - } - OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; - OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength; - memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength); - srcData->offset += readlength; - return readlength; -} +void fx_ignore_callback(const char* msg, void* client_data) {} -OPJ_SIZE_T opj_write_from_memory(void* p_buffer, - OPJ_SIZE_T nb_bytes, - void* p_user_data) { - DecodeData* srcData = static_cast(p_user_data); - if (!srcData || !srcData->src_data || srcData->src_size == 0) { - return static_cast(-1); - } - // Writes at EOF return an error code. - if (srcData->offset >= srcData->src_size) { - return static_cast(-1); - } - OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; - OPJ_SIZE_T writeLength = nb_bytes < bufferLength ? nb_bytes : bufferLength; - memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength); - srcData->offset += writeLength; - return writeLength; -} - -OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) { - DecodeData* srcData = static_cast(p_user_data); - if (!srcData || !srcData->src_data || srcData->src_size == 0) { - return static_cast(-1); - } - // Offsets are signed and may indicate a negative skip. Do not support this - // because of the strange return convention where either bytes skipped or - // -1 is returned. Following that convention, a successful relative seek of - // -1 bytes would be required to to give the same result as the error case. - if (nb_bytes < 0) { - return static_cast(-1); - } - // FIXME: use std::make_unsigned::type once c++11 lib is OK'd. - uint64_t unsignedNbBytes = static_cast(nb_bytes); - // Additionally, the offset may take us beyond the range of a size_t (e.g. - // 32-bit platforms). If so, just clamp at EOF. - if (unsignedNbBytes > - std::numeric_limits::max() - srcData->offset) { - srcData->offset = srcData->src_size; - } else { - OPJ_SIZE_T checkedNbBytes = static_cast(unsignedNbBytes); - // Otherwise, mimic fseek() semantics to always succeed, even past EOF, - // clamping at EOF. We can get away with this since we don't actually - // provide negative relative skips from beyond EOF back to inside the - // data, which would be the only reason to need to know exactly how far - // beyond EOF we are. - srcData->offset = - std::min(srcData->offset + checkedNbBytes, srcData->src_size); - } - return nb_bytes; -} - -OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) { - DecodeData* srcData = static_cast(p_user_data); - if (!srcData || !srcData->src_data || srcData->src_size == 0) { - return OPJ_FALSE; - } - // Offsets are signed and may indicate a negative position, which would - // be before the start of the file. Do not support this. - if (nb_bytes < 0) { - return OPJ_FALSE; - } - // FIXME: use std::make_unsigned::type once c++11 lib is OK'd. - uint64_t unsignedNbBytes = static_cast(nb_bytes); - // Additionally, the offset may take us beyond the range of a size_t (e.g. - // 32-bit platforms). If so, just clamp at EOF. - if (unsignedNbBytes > std::numeric_limits::max()) { - srcData->offset = srcData->src_size; - } else { - OPJ_SIZE_T checkedNbBytes = static_cast(nb_bytes); - // Otherwise, mimic fseek() semantics to always succeed, even past EOF, - // again clamping at EOF. - srcData->offset = std::min(checkedNbBytes, srcData->src_size); - } - return OPJ_TRUE; -} opj_stream_t* fx_opj_stream_create_memory_stream(DecodeData* data, OPJ_SIZE_T p_size, OPJ_BOOL p_is_read_stream) { - opj_stream_t* l_stream = 00; - if (!data || !data->src_data || data->src_size <= 0) { + if (!data || !data->src_data || data->src_size <= 0) return nullptr; - } - l_stream = opj_stream_create(p_size, p_is_read_stream); - if (!l_stream) { + + opj_stream_t* stream = opj_stream_create(p_size, p_is_read_stream); + if (!stream) return nullptr; - } - opj_stream_set_user_data(l_stream, data, nullptr); - opj_stream_set_user_data_length(l_stream, data->src_size); - opj_stream_set_read_function(l_stream, opj_read_from_memory); - opj_stream_set_write_function(l_stream, opj_write_from_memory); - opj_stream_set_skip_function(l_stream, opj_skip_from_memory); - opj_stream_set_seek_function(l_stream, opj_seek_from_memory); - return l_stream; + + opj_stream_set_user_data(stream, data, nullptr); + opj_stream_set_user_data_length(stream, data->src_size); + opj_stream_set_read_function(stream, opj_read_from_memory); + opj_stream_set_skip_function(stream, opj_skip_from_memory); + opj_stream_set_seek_function(stream, opj_seek_from_memory); + return stream; } -static void sycc_to_rgb(int offset, - int upb, - int y, - int cb, - int cr, - int* out_r, - int* out_g, - int* out_b) { - int r, g, b; + +void sycc_to_rgb(int offset, + int upb, + int y, + int cb, + int cr, + int* out_r, + int* out_g, + int* out_b) { cb -= offset; cr -= offset; - r = y + (int)(1.402 * (float)cr); - if (r < 0) { - r = 0; - } else if (r > upb) { - r = upb; - } - *out_r = r; - g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr); - if (g < 0) { - g = 0; - } else if (g > upb) { - g = upb; - } - *out_g = g; - b = y + (int)(1.772 * (float)cb); - if (b < 0) { - b = 0; - } else if (b > upb) { - b = upb; - } - *out_b = b; + *out_r = pdfium::clamp(y + static_cast(1.402 * cr), 0, upb); + *out_g = pdfium::clamp(y - static_cast(0.344 * cb + 0.714 * cr), 0, upb); + *out_b = pdfium::clamp(y + static_cast(1.772 * cb), 0, upb); } -static void sycc444_to_rgb(opj_image_t* img) { +void sycc444_to_rgb(opj_image_t* img) { int prec = img->comps[0].prec; + // If we shift 31 we're going to go negative, then things go bad. + if (prec > 30) + return; int offset = 1 << (prec - 1); int upb = (1 << prec) - 1; OPJ_UINT32 maxw = @@ -181,6 +69,7 @@ static void sycc444_to_rgb(opj_image_t* img) { std::min({img->comps[0].h, img->comps[1].h, img->comps[2].h}); FX_SAFE_SIZE_T max_size = maxw; max_size *= maxh; + max_size *= sizeof(int); if (!max_size.IsValid()) return; @@ -190,44 +79,42 @@ static void sycc444_to_rgb(opj_image_t* img) { if (!y || !cb || !cr) return; - int* r = FX_Alloc(int, max_size.ValueOrDie()); - int* g = FX_Alloc(int, max_size.ValueOrDie()); - int* b = FX_Alloc(int, max_size.ValueOrDie()); + int* r = static_cast(opj_image_data_alloc(max_size.ValueOrDie())); + int* g = static_cast(opj_image_data_alloc(max_size.ValueOrDie())); + int* b = static_cast(opj_image_data_alloc(max_size.ValueOrDie())); int* d0 = r; int* d1 = g; int* d2 = b; + max_size /= sizeof(int); for (size_t i = 0; i < max_size.ValueOrDie(); ++i) { - sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); - ++y; - ++cb; - ++cr; - ++r; - ++g; - ++b; + sycc_to_rgb(offset, upb, *y++, *cb++, *cr++, r++, g++, b++); } - FX_Free(img->comps[0].data); - FX_Free(img->comps[1].data); - FX_Free(img->comps[2].data); + opj_image_data_free(img->comps[0].data); + opj_image_data_free(img->comps[1].data); + opj_image_data_free(img->comps[2].data); img->comps[0].data = d0; img->comps[1].data = d1; img->comps[2].data = d2; } -static bool sycc420_422_size_is_valid(opj_image_t* img) { - return (img && img->comps[0].w != std::numeric_limits::max() && - (img->comps[0].w + 1) / 2 == img->comps[1].w && - img->comps[1].w == img->comps[2].w && - img->comps[1].h == img->comps[2].h); +bool sycc420_422_size_is_valid(opj_image_t* img) { + return img && img->comps[0].w != std::numeric_limits::max() && + (img->comps[0].w + 1) / 2 == img->comps[1].w && + img->comps[1].w == img->comps[2].w && + img->comps[1].h == img->comps[2].h; } -static bool sycc420_size_is_valid(opj_image_t* img) { - return (sycc420_422_size_is_valid(img) && - img->comps[0].h != std::numeric_limits::max() && - (img->comps[0].h + 1) / 2 == img->comps[1].h); + +bool sycc420_size_is_valid(opj_image_t* img) { + return sycc420_422_size_is_valid(img) && + img->comps[0].h != std::numeric_limits::max() && + (img->comps[0].h + 1) / 2 == img->comps[1].h; } -static bool sycc422_size_is_valid(opj_image_t* img) { - return (sycc420_422_size_is_valid(img) && img->comps[0].h == img->comps[1].h); + +bool sycc422_size_is_valid(opj_image_t* img) { + return sycc420_422_size_is_valid(img) && img->comps[0].h == img->comps[1].h; } -static void sycc422_to_rgb(opj_image_t* img) { + +void sycc422_to_rgb(opj_image_t* img) { if (!sycc422_size_is_valid(img)) return; @@ -237,11 +124,11 @@ static void sycc422_to_rgb(opj_image_t* img) { int offset = 1 << (prec - 1); int upb = (1 << prec) - 1; - OPJ_UINT32 maxw = img->comps[0].w; OPJ_UINT32 maxh = img->comps[0].h; FX_SAFE_SIZE_T max_size = maxw; max_size *= maxh; + max_size *= sizeof(int); if (!max_size.IsValid()) return; @@ -251,41 +138,27 @@ static void sycc422_to_rgb(opj_image_t* img) { if (!y || !cb || !cr) return; - int *d0, *d1, *d2, *r, *g, *b; - d0 = r = FX_Alloc(int, max_size.ValueOrDie()); - d1 = g = FX_Alloc(int, max_size.ValueOrDie()); - d2 = b = FX_Alloc(int, max_size.ValueOrDie()); + int* r = static_cast(opj_image_data_alloc(max_size.ValueOrDie())); + int* g = static_cast(opj_image_data_alloc(max_size.ValueOrDie())); + int* b = static_cast(opj_image_data_alloc(max_size.ValueOrDie())); + int* d0 = r; + int* d1 = g; + int* d2 = b; for (uint32_t i = 0; i < maxh; ++i) { OPJ_UINT32 j; for (j = 0; j < (maxw & ~static_cast(1)); j += 2) { - sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); - ++y; - ++r; - ++g; - ++b; - sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); - ++y; - ++r; - ++g; - ++b; - ++cb; - ++cr; + sycc_to_rgb(offset, upb, *y++, *cb, *cr, r++, g++, b++); + sycc_to_rgb(offset, upb, *y++, *cb++, *cr++, r++, g++, b++); } if (j < maxw) { - sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); - ++y; - ++r; - ++g; - ++b; - ++cb; - ++cr; + sycc_to_rgb(offset, upb, *y++, *cb++, *cr++, r++, g++, b++); } } - FX_Free(img->comps[0].data); + opj_image_data_free(img->comps[0].data); + opj_image_data_free(img->comps[1].data); + opj_image_data_free(img->comps[2].data); img->comps[0].data = d0; - FX_Free(img->comps[1].data); img->comps[1].data = d1; - FX_Free(img->comps[2].data); img->comps[2].data = d2; img->comps[1].w = maxw; img->comps[1].h = maxh; @@ -296,9 +169,123 @@ static void sycc422_to_rgb(opj_image_t* img) { img->comps[1].dy = img->comps[0].dy; img->comps[2].dy = img->comps[0].dy; } -static bool sycc420_must_extend_cbcr(OPJ_UINT32 y, OPJ_UINT32 cbcr) { + +bool sycc420_must_extend_cbcr(OPJ_UINT32 y, OPJ_UINT32 cbcr) { return (y & 1) && (cbcr == y / 2); } + +bool is_sycc420(const opj_image_t* img) { + return img->comps[0].dx == 1 && img->comps[0].dy == 1 && + img->comps[1].dx == 2 && img->comps[1].dy == 2 && + img->comps[2].dx == 2 && img->comps[2].dy == 2; +} + +bool is_sycc422(const opj_image_t* img) { + return img->comps[0].dx == 1 && img->comps[0].dy == 1 && + img->comps[1].dx == 2 && img->comps[1].dy == 1 && + img->comps[2].dx == 2 && img->comps[2].dy == 1; +} + +bool is_sycc444(const opj_image_t* img) { + return img->comps[0].dx == 1 && img->comps[0].dy == 1 && + img->comps[1].dx == 1 && img->comps[1].dy == 1 && + img->comps[2].dx == 1 && img->comps[2].dy == 1; +} + +void color_sycc_to_rgb(opj_image_t* img) { + if (img->numcomps < 3) { + img->color_space = OPJ_CLRSPC_GRAY; + return; + } + if (is_sycc420(img)) + sycc420_to_rgb(img); + else if (is_sycc422(img)) + sycc422_to_rgb(img); + else if (is_sycc444(img)) + sycc444_to_rgb(img); + else + return; + + img->color_space = OPJ_CLRSPC_SRGB; +} + +} // namespace + +OPJ_SIZE_T opj_read_from_memory(void* p_buffer, + OPJ_SIZE_T nb_bytes, + void* p_user_data) { + DecodeData* srcData = static_cast(p_user_data); + if (!srcData || !srcData->src_data || srcData->src_size == 0) + return static_cast(-1); + + // Reads at EOF return an error code. + if (srcData->offset >= srcData->src_size) + return static_cast(-1); + + OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; + OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength; + memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength); + srcData->offset += readlength; + return readlength; +} + +OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) { + DecodeData* srcData = static_cast(p_user_data); + if (!srcData || !srcData->src_data || srcData->src_size == 0) + return static_cast(-1); + + // Offsets are signed and may indicate a negative skip. Do not support this + // because of the strange return convention where either bytes skipped or + // -1 is returned. Following that convention, a successful relative seek of + // -1 bytes would be required to to give the same result as the error case. + if (nb_bytes < 0) + return static_cast(-1); + + // FIXME: use std::make_unsigned::type once c++11 lib is OK'd. + uint64_t unsignedNbBytes = static_cast(nb_bytes); + // Additionally, the offset may take us beyond the range of a size_t (e.g. + // 32-bit platforms). If so, just clamp at EOF. + if (unsignedNbBytes > + std::numeric_limits::max() - srcData->offset) { + srcData->offset = srcData->src_size; + } else { + OPJ_SIZE_T checkedNbBytes = static_cast(unsignedNbBytes); + // Otherwise, mimic fseek() semantics to always succeed, even past EOF, + // clamping at EOF. We can get away with this since we don't actually + // provide negative relative skips from beyond EOF back to inside the + // data, which would be the only reason to need to know exactly how far + // beyond EOF we are. + srcData->offset = + std::min(srcData->offset + checkedNbBytes, srcData->src_size); + } + return nb_bytes; +} + +OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) { + DecodeData* srcData = static_cast(p_user_data); + if (!srcData || !srcData->src_data || srcData->src_size == 0) + return OPJ_FALSE; + + // Offsets are signed and may indicate a negative position, which would + // be before the start of the file. Do not support this. + if (nb_bytes < 0) + return OPJ_FALSE; + + // FIXME: use std::make_unsigned::type once c++11 lib is OK'd. + uint64_t unsignedNbBytes = static_cast(nb_bytes); + // Additionally, the offset may take us beyond the range of a size_t (e.g. + // 32-bit platforms). If so, just clamp at EOF. + if (unsignedNbBytes > std::numeric_limits::max()) { + srcData->offset = srcData->src_size; + } else { + OPJ_SIZE_T checkedNbBytes = static_cast(nb_bytes); + // Otherwise, mimic fseek() semantics to always succeed, even past EOF, + // again clamping at EOF. + srcData->offset = std::min(checkedNbBytes, srcData->src_size); + } + return OPJ_TRUE; +} + void sycc420_to_rgb(opj_image_t* img) { if (!sycc420_size_is_valid(img)) return; @@ -306,6 +293,7 @@ void sycc420_to_rgb(opj_image_t* img) { OPJ_UINT32 prec = img->comps[0].prec; if (!prec) return; + OPJ_UINT32 offset = 1 << (prec - 1); OPJ_UINT32 upb = (1 << prec) - 1; OPJ_UINT32 yw = img->comps[0].w; @@ -317,11 +305,13 @@ void sycc420_to_rgb(opj_image_t* img) { bool exth = sycc420_must_extend_cbcr(yh, cbh); FX_SAFE_UINT32 safeSize = yw; safeSize *= yh; + safeSize *= sizeof(int); if (!safeSize.IsValid()) return; - int* r = FX_Alloc(int, safeSize.ValueOrDie()); - int* g = FX_Alloc(int, safeSize.ValueOrDie()); - int* b = FX_Alloc(int, safeSize.ValueOrDie()); + + int* r = static_cast(opj_image_data_alloc(safeSize.ValueOrDie())); + int* g = static_cast(opj_image_data_alloc(safeSize.ValueOrDie())); + int* b = static_cast(opj_image_data_alloc(safeSize.ValueOrDie())); int* d0 = r; int* d1 = g; int* d2 = b; @@ -417,11 +407,11 @@ void sycc420_to_rgb(opj_image_t* img) { } } - FX_Free(img->comps[0].data); + opj_image_data_free(img->comps[0].data); + opj_image_data_free(img->comps[1].data); + opj_image_data_free(img->comps[2].data); img->comps[0].data = d0; - FX_Free(img->comps[1].data); img->comps[1].data = d1; - FX_Free(img->comps[2].data); img->comps[2].data = d2; img->comps[1].w = yw; img->comps[1].h = yh; @@ -436,290 +426,21 @@ void sycc420_to_rgb(opj_image_t* img) { img->comps[1].dy = img->comps[0].dy; img->comps[2].dy = img->comps[0].dy; } -void color_sycc_to_rgb(opj_image_t* img) { - if (img->numcomps < 3) { - img->color_space = OPJ_CLRSPC_GRAY; - return; - } - if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && - (img->comps[2].dx == 2) && (img->comps[0].dy == 1) && - (img->comps[1].dy == 2) && (img->comps[2].dy == 2)) { - sycc420_to_rgb(img); - } else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && - (img->comps[2].dx == 2) && (img->comps[0].dy == 1) && - (img->comps[1].dy == 1) && (img->comps[2].dy == 1)) { - sycc422_to_rgb(img); - } else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 1) && - (img->comps[2].dx == 1) && (img->comps[0].dy == 1) && - (img->comps[1].dy == 1) && (img->comps[2].dy == 1)) { - sycc444_to_rgb(img); - } else { - return; - } - img->color_space = OPJ_CLRSPC_SRGB; -} -void color_apply_icc_profile(opj_image_t* image) { - cmsHPROFILE out_prof; - cmsUInt32Number in_type; - cmsUInt32Number out_type; - int* r; - int* g; - int* b; - int max; - cmsHPROFILE in_prof = - cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len); - if (!in_prof) { - return; - } - cmsColorSpaceSignature out_space = cmsGetColorSpace(in_prof); - cmsUInt32Number intent = cmsGetHeaderRenderingIntent(in_prof); - int max_w = (int)image->comps[0].w; - int max_h = (int)image->comps[0].h; - int prec = (int)image->comps[0].prec; - OPJ_COLOR_SPACE oldspace = image->color_space; - if (out_space == cmsSigRgbData) { - if (prec <= 8) { - in_type = TYPE_RGB_8; - out_type = TYPE_RGB_8; - } else { - in_type = TYPE_RGB_16; - out_type = TYPE_RGB_16; - } - out_prof = cmsCreate_sRGBProfile(); - image->color_space = OPJ_CLRSPC_SRGB; - } else if (out_space == cmsSigGrayData) { - if (prec <= 8) { - in_type = TYPE_GRAY_8; - out_type = TYPE_RGB_8; - } else { - in_type = TYPE_GRAY_16; - out_type = TYPE_RGB_16; - } - out_prof = cmsCreate_sRGBProfile(); - image->color_space = OPJ_CLRSPC_SRGB; - } else if (out_space == cmsSigYCbCrData) { - in_type = TYPE_YCbCr_16; - out_type = TYPE_RGB_16; - out_prof = cmsCreate_sRGBProfile(); - image->color_space = OPJ_CLRSPC_SRGB; - } else { - return; - } - cmsHTRANSFORM transform = - cmsCreateTransform(in_prof, in_type, out_prof, out_type, intent, 0); - cmsCloseProfile(in_prof); - cmsCloseProfile(out_prof); - if (!transform) { - image->color_space = oldspace; - return; - } - if (image->numcomps > 2) { - if (prec <= 8) { - unsigned char *inbuf, *outbuf, *in, *out; - max = max_w * max_h; - cmsUInt32Number nr_samples = max * 3 * sizeof(unsigned char); - in = inbuf = FX_Alloc(unsigned char, nr_samples); - out = outbuf = FX_Alloc(unsigned char, nr_samples); - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - for (int i = 0; i < max; ++i) { - *in++ = (unsigned char)*r++; - *in++ = (unsigned char)*g++; - *in++ = (unsigned char)*b++; - } - cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - for (int i = 0; i < max; ++i) { - *r++ = (int)*out++; - *g++ = (int)*out++; - *b++ = (int)*out++; - } - FX_Free(inbuf); - FX_Free(outbuf); - } else { - unsigned short *inbuf, *outbuf, *in, *out; - max = max_w * max_h; - cmsUInt32Number nr_samples = max * 3 * sizeof(unsigned short); - in = inbuf = FX_Alloc(unsigned short, nr_samples); - out = outbuf = FX_Alloc(unsigned short, nr_samples); - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - for (int i = 0; i < max; ++i) { - *in++ = (unsigned short)*r++; - *in++ = (unsigned short)*g++; - *in++ = (unsigned short)*b++; - } - cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - for (int i = 0; i < max; ++i) { - *r++ = (int)*out++; - *g++ = (int)*out++; - *b++ = (int)*out++; - } - FX_Free(inbuf); - FX_Free(outbuf); - } - } else { - unsigned char *in, *inbuf, *out, *outbuf; - max = max_w * max_h; - cmsUInt32Number nr_samples = - (cmsUInt32Number)max * 3 * sizeof(unsigned char); - in = inbuf = FX_Alloc(unsigned char, nr_samples); - out = outbuf = FX_Alloc(unsigned char, nr_samples); - image->comps = (opj_image_comp_t*)realloc( - image->comps, (image->numcomps + 2) * sizeof(opj_image_comp_t)); - if (image->numcomps == 2) { - image->comps[3] = image->comps[1]; - } - image->comps[1] = image->comps[0]; - image->comps[2] = image->comps[0]; - image->comps[1].data = FX_Alloc(int, (size_t)max); - FXSYS_memset(image->comps[1].data, 0, sizeof(int) * (size_t)max); - image->comps[2].data = FX_Alloc(int, (size_t)max); - FXSYS_memset(image->comps[2].data, 0, sizeof(int) * (size_t)max); - image->numcomps += 2; - r = image->comps[0].data; - for (int i = 0; i < max; ++i) { - *in++ = (unsigned char)*r++; - } - cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); - r = image->comps[0].data; - g = image->comps[1].data; - b = image->comps[2].data; - for (int i = 0; i < max; ++i) { - *r++ = (int)*out++; - *g++ = (int)*out++; - *b++ = (int)*out++; - } - FX_Free(inbuf); - FX_Free(outbuf); - } - cmsDeleteTransform(transform); -} -void color_apply_conversion(opj_image_t* image) { - int* row; - int enumcs, numcomps; - numcomps = image->numcomps; - if (numcomps < 3) { - return; - } - row = (int*)image->icc_profile_buf; - enumcs = row[0]; - if (enumcs == 14) { - int *L, *a, *b, *red, *green, *blue, *src0, *src1, *src2; - double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2; - double minL, maxL, mina, maxa, minb, maxb; - unsigned int default_type; - unsigned int i, max; - cmsHPROFILE in, out; - cmsHTRANSFORM transform; - cmsUInt16Number RGB[3]; - cmsCIELab Lab; - in = cmsCreateLab4Profile(nullptr); - out = cmsCreate_sRGBProfile(); - transform = cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16, - INTENT_PERCEPTUAL, 0); - cmsCloseProfile(in); - cmsCloseProfile(out); - if (!transform) { - return; - } - prec0 = (double)image->comps[0].prec; - prec1 = (double)image->comps[1].prec; - prec2 = (double)image->comps[2].prec; - default_type = row[1]; - if (default_type == 0x44454600) { - rl = 100; - ra = 170; - rb = 200; - ol = 0; - oa = pow(2, prec1 - 1); - ob = pow(2, prec2 - 2) + pow(2, prec2 - 3); - } else { - rl = row[2]; - ra = row[4]; - rb = row[6]; - ol = row[3]; - oa = row[5]; - ob = row[7]; - } - L = src0 = image->comps[0].data; - a = src1 = image->comps[1].data; - b = src2 = image->comps[2].data; - max = image->comps[0].w * image->comps[0].h; - red = FX_Alloc(int, max); - image->comps[0].data = red; - green = FX_Alloc(int, max); - image->comps[1].data = green; - blue = FX_Alloc(int, max); - image->comps[2].data = blue; - minL = -(rl * ol) / (pow(2, prec0) - 1); - maxL = minL + rl; - mina = -(ra * oa) / (pow(2, prec1) - 1); - maxa = mina + ra; - minb = -(rb * ob) / (pow(2, prec2) - 1); - maxb = minb + rb; - for (i = 0; i < max; ++i) { - Lab.L = minL + (double)(*L) * (maxL - minL) / (pow(2, prec0) - 1); - ++L; - Lab.a = mina + (double)(*a) * (maxa - mina) / (pow(2, prec1) - 1); - ++a; - Lab.b = minb + (double)(*b) * (maxb - minb) / (pow(2, prec2) - 1); - ++b; - cmsDoTransform(transform, &Lab, RGB, 1); - *red++ = RGB[0]; - *green++ = RGB[1]; - *blue++ = RGB[2]; - } - cmsDeleteTransform(transform); - FX_Free(src0); - FX_Free(src1); - FX_Free(src2); - image->color_space = OPJ_CLRSPC_SRGB; - image->comps[0].prec = 16; - image->comps[1].prec = 16; - image->comps[2].prec = 16; - return; - } -} -class CJPX_Decoder { - public: - explicit CJPX_Decoder(CPDF_ColorSpace* cs); - ~CJPX_Decoder(); - bool Init(const unsigned char* src_data, uint32_t src_size); - void GetInfo(uint32_t* width, uint32_t* height, uint32_t* components); - bool Decode(uint8_t* dest_buf, - int pitch, - const std::vector& offsets); - - private: - const uint8_t* m_SrcData; - uint32_t m_SrcSize; - opj_image_t* image; - opj_codec_t* l_codec; - opj_stream_t* l_stream; - const CPDF_ColorSpace* const m_ColorSpace; -}; CJPX_Decoder::CJPX_Decoder(CPDF_ColorSpace* cs) - : image(nullptr), l_codec(nullptr), l_stream(nullptr), m_ColorSpace(cs) {} + : m_Image(nullptr), + m_Codec(nullptr), + m_DecodeData(nullptr), + m_Stream(nullptr), + m_ColorSpace(cs) {} CJPX_Decoder::~CJPX_Decoder() { - if (l_codec) { - opj_destroy_codec(l_codec); - } - if (l_stream) { - opj_stream_destroy(l_stream); - } - if (image) { - opj_image_destroy(image); - } + if (m_Codec) + opj_destroy_codec(m_Codec); + if (m_Stream) + opj_stream_destroy(m_Stream); + if (m_Image) + opj_image_destroy(m_Image); } bool CJPX_Decoder::Init(const unsigned char* src_data, uint32_t src_size) { @@ -728,134 +449,139 @@ bool CJPX_Decoder::Init(const unsigned char* src_data, uint32_t src_size) { if (!src_data || src_size < sizeof(szJP2Header)) return false; - image = nullptr; + m_Image = nullptr; m_SrcData = src_data; m_SrcSize = src_size; - DecodeData srcData(const_cast(src_data), src_size); - l_stream = fx_opj_stream_create_memory_stream(&srcData, - OPJ_J2K_STREAM_CHUNK_SIZE, 1); - if (!l_stream) { + m_DecodeData = pdfium::MakeUnique( + const_cast(src_data), src_size); + m_Stream = fx_opj_stream_create_memory_stream( + m_DecodeData.get(), static_cast(OPJ_J2K_STREAM_CHUNK_SIZE), + 1); + if (!m_Stream) return false; - } - opj_dparameters_t parameters; - opj_set_default_decoder_parameters(¶meters); - parameters.decod_format = 0; - parameters.cod_format = 3; - if (FXSYS_memcmp(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) { - l_codec = opj_create_decompress(OPJ_CODEC_JP2); - parameters.decod_format = 1; + + opj_set_default_decoder_parameters(&m_Parameters); + m_Parameters.decod_format = 0; + m_Parameters.cod_format = 3; + if (memcmp(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) { + m_Codec = opj_create_decompress(OPJ_CODEC_JP2); + m_Parameters.decod_format = 1; } else { - l_codec = opj_create_decompress(OPJ_CODEC_J2K); + m_Codec = opj_create_decompress(OPJ_CODEC_J2K); } - if (!l_codec) { + if (!m_Codec) return false; - } + if (m_ColorSpace && m_ColorSpace->GetFamily() == PDFCS_INDEXED) - parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; - opj_set_info_handler(l_codec, fx_info_callback, 00); - opj_set_warning_handler(l_codec, fx_warning_callback, 00); - opj_set_error_handler(l_codec, fx_error_callback, 00); - if (!opj_setup_decoder(l_codec, ¶meters)) { + m_Parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; + opj_set_info_handler(m_Codec, fx_ignore_callback, nullptr); + opj_set_warning_handler(m_Codec, fx_ignore_callback, nullptr); + opj_set_error_handler(m_Codec, fx_ignore_callback, nullptr); + if (!opj_setup_decoder(m_Codec, &m_Parameters)) return false; - } - if (!opj_read_header(l_stream, l_codec, &image)) { - image = nullptr; + + if (!opj_read_header(m_Stream, m_Codec, &m_Image)) { + m_Image = nullptr; return false; } - image->pdfium_use_colorspace = !!m_ColorSpace; + m_Image->pdfium_use_colorspace = !!m_ColorSpace; - if (!parameters.nb_tile_to_decode) { - if (!opj_set_decode_area(l_codec, image, parameters.DA_x0, parameters.DA_y0, - parameters.DA_x1, parameters.DA_y1)) { - opj_image_destroy(image); - image = nullptr; + if (!m_Parameters.nb_tile_to_decode) { + if (!opj_set_decode_area(m_Codec, m_Image, m_Parameters.DA_x0, + m_Parameters.DA_y0, m_Parameters.DA_x1, + m_Parameters.DA_y1)) { + opj_image_destroy(m_Image); + m_Image = nullptr; return false; } - if (!(opj_decode(l_codec, l_stream, image) && - opj_end_decompress(l_codec, l_stream))) { - opj_image_destroy(image); - image = nullptr; + if (!(opj_decode(m_Codec, m_Stream, m_Image) && + opj_end_decompress(m_Codec, m_Stream))) { + opj_image_destroy(m_Image); + m_Image = nullptr; return false; } - } else { - if (!opj_get_decoded_tile(l_codec, l_stream, image, - parameters.tile_index)) { - return false; - } - } - opj_stream_destroy(l_stream); - l_stream = nullptr; - if (image->color_space != OPJ_CLRSPC_SYCC && image->numcomps == 3 && - image->comps[0].dx == image->comps[0].dy && image->comps[1].dx != 1) { - image->color_space = OPJ_CLRSPC_SYCC; - } else if (image->numcomps <= 2) { - image->color_space = OPJ_CLRSPC_GRAY; - } - if (image->color_space == OPJ_CLRSPC_SYCC) { - color_sycc_to_rgb(image); + } else if (!opj_get_decoded_tile(m_Codec, m_Stream, m_Image, + m_Parameters.tile_index)) { + return false; } - if (image->icc_profile_buf) { - FX_Free(image->icc_profile_buf); - image->icc_profile_buf = nullptr; - image->icc_profile_len = 0; + + opj_stream_destroy(m_Stream); + m_Stream = nullptr; + if (m_Image->color_space != OPJ_CLRSPC_SYCC && m_Image->numcomps == 3 && + m_Image->comps[0].dx == m_Image->comps[0].dy && + m_Image->comps[1].dx != 1) { + m_Image->color_space = OPJ_CLRSPC_SYCC; + } else if (m_Image->numcomps <= 2) { + m_Image->color_space = OPJ_CLRSPC_GRAY; } - if (!image) { - return false; + if (m_Image->color_space == OPJ_CLRSPC_SYCC) + color_sycc_to_rgb(m_Image); + + if (m_Image->icc_profile_buf) { + // TODO(palmer): Using |opj_free| here resolves the crash described in + // https://crbug.com/737033, but ultimately we need to harmonize the + // memory allocation strategy across OpenJPEG and its PDFium callers. + opj_free(m_Image->icc_profile_buf); + m_Image->icc_profile_buf = nullptr; + m_Image->icc_profile_len = 0; } + return true; } void CJPX_Decoder::GetInfo(uint32_t* width, uint32_t* height, uint32_t* components) { - *width = (uint32_t)image->x1; - *height = (uint32_t)image->y1; - *components = (uint32_t)image->numcomps; + *width = m_Image->x1; + *height = m_Image->y1; + *components = m_Image->numcomps; } bool CJPX_Decoder::Decode(uint8_t* dest_buf, int pitch, const std::vector& offsets) { - if (image->comps[0].w != image->x1 || image->comps[0].h != image->y1) + if (m_Image->comps[0].w != m_Image->x1 || m_Image->comps[0].h != m_Image->y1) return false; - if (pitch<(int)(image->comps[0].w * 8 * image->numcomps + 31)>> 5 << 2) + if (pitch(m_Image->comps[0].w * 8 * m_Image->numcomps + 31)>> + 5 << 2) { return false; + } - FXSYS_memset(dest_buf, 0xff, image->y1 * pitch); - std::vector channel_bufs(image->numcomps); - std::vector adjust_comps(image->numcomps); - for (uint32_t i = 0; i < image->numcomps; i++) { + memset(dest_buf, 0xff, m_Image->y1 * pitch); + std::vector channel_bufs(m_Image->numcomps); + std::vector adjust_comps(m_Image->numcomps); + for (uint32_t i = 0; i < m_Image->numcomps; i++) { channel_bufs[i] = dest_buf + offsets[i]; - adjust_comps[i] = image->comps[i].prec - 8; + adjust_comps[i] = m_Image->comps[i].prec - 8; if (i > 0) { - if (image->comps[i].dx != image->comps[i - 1].dx || - image->comps[i].dy != image->comps[i - 1].dy || - image->comps[i].prec != image->comps[i - 1].prec) { + if (m_Image->comps[i].dx != m_Image->comps[i - 1].dx || + m_Image->comps[i].dy != m_Image->comps[i - 1].dy || + m_Image->comps[i].prec != m_Image->comps[i - 1].prec) { return false; } } } - int width = image->comps[0].w; - int height = image->comps[0].h; - for (uint32_t channel = 0; channel < image->numcomps; ++channel) { + int width = m_Image->comps[0].w; + int height = m_Image->comps[0].h; + for (uint32_t channel = 0; channel < m_Image->numcomps; ++channel) { uint8_t* pChannel = channel_bufs[channel]; if (adjust_comps[channel] < 0) { for (int row = 0; row < height; ++row) { uint8_t* pScanline = pChannel + row * pitch; for (int col = 0; col < width; ++col) { - uint8_t* pPixel = pScanline + col * image->numcomps; - if (!image->comps[channel].data) + uint8_t* pPixel = pScanline + col * m_Image->numcomps; + if (!m_Image->comps[channel].data) continue; - int src = image->comps[channel].data[row * width + col]; - src += image->comps[channel].sgnd - ? 1 << (image->comps[channel].prec - 1) + int src = m_Image->comps[channel].data[row * width + col]; + src += m_Image->comps[channel].sgnd + ? 1 << (m_Image->comps[channel].prec - 1) : 0; if (adjust_comps[channel] > 0) { *pPixel = 0; } else { - *pPixel = (uint8_t)(src << -adjust_comps[channel]); + *pPixel = static_cast(src << -adjust_comps[channel]); } } } @@ -863,25 +589,21 @@ bool CJPX_Decoder::Decode(uint8_t* dest_buf, for (int row = 0; row < height; ++row) { uint8_t* pScanline = pChannel + row * pitch; for (int col = 0; col < width; ++col) { - uint8_t* pPixel = pScanline + col * image->numcomps; - if (!image->comps[channel].data) + uint8_t* pPixel = pScanline + col * m_Image->numcomps; + if (!m_Image->comps[channel].data) continue; - int src = image->comps[channel].data[row * width + col]; - src += image->comps[channel].sgnd - ? 1 << (image->comps[channel].prec - 1) + int src = m_Image->comps[channel].data[row * width + col]; + src += m_Image->comps[channel].sgnd + ? 1 << (m_Image->comps[channel].prec - 1) : 0; if (adjust_comps[channel] - 1 < 0) { - *pPixel = (uint8_t)((src >> adjust_comps[channel])); + *pPixel = static_cast((src >> adjust_comps[channel])); } else { int tmpPixel = (src >> adjust_comps[channel]) + ((src >> (adjust_comps[channel] - 1)) % 2); - if (tmpPixel > 255) { - tmpPixel = 255; - } else if (tmpPixel < 0) { - tmpPixel = 0; - } - *pPixel = (uint8_t)tmpPixel; + tmpPixel = pdfium::clamp(tmpPixel, 0, 255); + *pPixel = static_cast(tmpPixel); } } } @@ -891,13 +613,15 @@ bool CJPX_Decoder::Decode(uint8_t* dest_buf, } CCodec_JpxModule::CCodec_JpxModule() {} + CCodec_JpxModule::~CCodec_JpxModule() {} -CJPX_Decoder* CCodec_JpxModule::CreateDecoder(const uint8_t* src_buf, - uint32_t src_size, - CPDF_ColorSpace* cs) { - std::unique_ptr decoder(new CJPX_Decoder(cs)); - return decoder->Init(src_buf, src_size) ? decoder.release() : nullptr; +std::unique_ptr CCodec_JpxModule::CreateDecoder( + const uint8_t* src_buf, + uint32_t src_size, + CPDF_ColorSpace* cs) { + auto decoder = pdfium::MakeUnique(cs); + return decoder->Init(src_buf, src_size) ? std::move(decoder) : nullptr; } void CCodec_JpxModule::GetImageInfo(CJPX_Decoder* pDecoder, @@ -913,7 +637,3 @@ bool CCodec_JpxModule::Decode(CJPX_Decoder* pDecoder, const std::vector& offsets) { return pDecoder->Decode(dest_data, pitch, offsets); } - -void CCodec_JpxModule::DestroyDecoder(CJPX_Decoder* pDecoder) { - delete pDecoder; -} diff --git a/core/fxcodec/codec/fx_codec_jpx_unittest.cpp b/core/fxcodec/codec/fx_codec_jpx_unittest.cpp index 3ef14e62c357db97687d9974ea14f1bf4fb90915..1bd368e56236d564bf9e5b8a60c54a03b57758f4 100644 --- a/core/fxcodec/codec/fx_codec_jpx_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_jpx_unittest.cpp @@ -7,14 +7,14 @@ #include #include "core/fxcodec/codec/codec_int.h" -#include "testing/fx_string_testhelpers.h" +#include "core/fxcodec/fx_codec.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libopenjpeg20/opj_malloc.h" static const OPJ_OFF_T kSkipError = static_cast(-1); static const OPJ_SIZE_T kReadError = static_cast(-1); -static const OPJ_SIZE_T kWriteError = static_cast(-1); -static unsigned char stream_data[] = { +static const uint8_t stream_data[] = { 0x00, 0x01, 0x02, 0x03, 0x84, 0x85, 0x86, 0x87, // Include some hi-bytes, too. }; @@ -23,39 +23,38 @@ union Float_t { Float_t(float num = 0.0f) : f(num) {} int32_t i; - FX_FLOAT f; + float f; }; TEST(fxcodec, CMYK_Rounding) { // Testing all floats from 0.0 to 1.0 takes about 35 seconds in release // builds and much longer in debug builds, so just test the known-dangerous // range. - const FX_FLOAT startValue = 0.001f; - const FX_FLOAT endValue = 0.003f; - FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; + const float startValue = 0.001f; + const float endValue = 0.003f; + float R = 0.0f, G = 0.0f, B = 0.0f; // Iterate through floats by incrementing the representation, as discussed in // https://randomascii.wordpress.com/2012/01/23/stupid-float-tricks-2/ for (Float_t f = startValue; f.f < endValue; f.i++) { - AdobeCMYK_to_sRGB(f.f, f.f, f.f, f.f, R, G, B); + std::tie(R, G, B) = AdobeCMYK_to_sRGB(f.f, f.f, f.f, f.f); } // Check various other 'special' numbers. - AdobeCMYK_to_sRGB(0.0f, 0.25f, 0.5f, 1.0f, R, G, B); + std::tie(R, G, B) = AdobeCMYK_to_sRGB(0.0f, 0.25f, 0.5f, 1.0f); } TEST(fxcodec, DecodeDataNullDecodeData) { - unsigned char buffer[16]; + uint8_t buffer[16]; DecodeData* ptr = nullptr; // Error codes, not segvs, should callers pass us a nullptr pointer. EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), ptr)); - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, sizeof(buffer), ptr)); EXPECT_EQ(kSkipError, opj_skip_from_memory(1, ptr)); EXPECT_FALSE(opj_seek_from_memory(1, ptr)); } TEST(fxcodec, DecodeDataNullStream) { DecodeData dd(nullptr, 0); - unsigned char buffer[16]; + uint8_t buffer[16]; // Reads of size 0 do nothing but return an error code. memset(buffer, 0xbd, sizeof(buffer)); @@ -67,12 +66,6 @@ TEST(fxcodec, DecodeDataNullStream) { EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd)); EXPECT_EQ(0xbd, buffer[0]); - // writes of size 0 do nothing but return an error code. - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, 0, &dd)); - - // writes of nonzero size do nothing but return an error code. - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, sizeof(buffer), &dd)); - // Skips of size 0 always return an error code. EXPECT_EQ(kSkipError, opj_skip_from_memory(0, &dd)); @@ -88,7 +81,7 @@ TEST(fxcodec, DecodeDataNullStream) { TEST(fxcodec, DecodeDataZeroSize) { DecodeData dd(stream_data, 0); - unsigned char buffer[16]; + uint8_t buffer[16]; // Reads of size 0 do nothing but return an error code. memset(buffer, 0xbd, sizeof(buffer)); @@ -100,12 +93,6 @@ TEST(fxcodec, DecodeDataZeroSize) { EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd)); EXPECT_EQ(0xbd, buffer[0]); - // writes of size 0 do nothing but return an error code. - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, 0, &dd)); - - // writes of nonzero size do nothing but return an error code. - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, sizeof(buffer), &dd)); - // Skips of size 0 always return an error code. EXPECT_EQ(kSkipError, opj_skip_from_memory(0, &dd)); @@ -120,7 +107,7 @@ TEST(fxcodec, DecodeDataZeroSize) { } TEST(fxcodec, DecodeDataReadInBounds) { - unsigned char buffer[16]; + uint8_t buffer[16]; { DecodeData dd(stream_data, sizeof(stream_data)); @@ -171,7 +158,7 @@ TEST(fxcodec, DecodeDataReadInBounds) { } TEST(fxcodec, DecodeDataReadBeyondBounds) { - unsigned char buffer[16]; + uint8_t buffer[16]; { DecodeData dd(stream_data, sizeof(stream_data)); @@ -234,86 +221,10 @@ TEST(fxcodec, DecodeDataReadBeyondBounds) { } } -TEST(fxcodec, DecodeDataWriteInBounds) { - unsigned char stream[16]; - static unsigned char buffer_data[] = { - 0x00, 0x01, 0x02, 0x03, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, - }; - { - // Pretend the stream can only hold 4 bytes. - DecodeData dd(stream, 4); - - memset(stream, 0xbd, sizeof(stream)); - EXPECT_EQ(4u, opj_write_from_memory(buffer_data, 4, &dd)); - EXPECT_EQ(0x00, stream[0]); - EXPECT_EQ(0x01, stream[1]); - EXPECT_EQ(0x02, stream[2]); - EXPECT_EQ(0x03, stream[3]); - EXPECT_EQ(0xbd, stream[4]); - } - { - // Pretend the stream can only hold 4 bytes. - DecodeData dd(stream, 4); - - memset(stream, 0xbd, sizeof(stream)); - EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 2, &dd)); - EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 2, &dd)); - EXPECT_EQ(0x00, stream[0]); - EXPECT_EQ(0x01, stream[1]); - EXPECT_EQ(0x00, stream[2]); - EXPECT_EQ(0x01, stream[3]); - EXPECT_EQ(0xbd, stream[4]); - } -} - -TEST(fxcodec, DecodeDataWriteBeyondBounds) { - unsigned char stream[16]; - static unsigned char buffer_data[] = { - 0x10, 0x11, 0x12, 0x13, 0x94, 0x95, 0x96, 0x97, - }; - { - // Pretend the stream can only hold 4 bytes. - DecodeData dd(stream, 4); - - // Write ending past EOF transfers up til EOF. - memset(stream, 0xbd, sizeof(stream)); - EXPECT_EQ(4u, opj_write_from_memory(buffer_data, 5, &dd)); - EXPECT_EQ(0x10, stream[0]); - EXPECT_EQ(0x11, stream[1]); - EXPECT_EQ(0x12, stream[2]); - EXPECT_EQ(0x13, stream[3]); - EXPECT_EQ(0xbd, stream[4]); - - // Subsequent writes fail. - memset(stream, 0xbd, sizeof(stream)); - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer_data, 5, &dd)); - EXPECT_EQ(0xbd, stream[0]); - } - { - // Pretend the stream can only hold 4 bytes. - DecodeData dd(stream, 4); - - // Write ending past EOF (two steps) transfers up til EOF. - memset(stream, 0xbd, sizeof(stream)); - EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 2, &dd)); - EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 4, &dd)); - EXPECT_EQ(0x10, stream[0]); - EXPECT_EQ(0x11, stream[1]); - EXPECT_EQ(0x10, stream[2]); - EXPECT_EQ(0x11, stream[3]); - EXPECT_EQ(0xbd, stream[4]); - - // Subsequent writes fail. - memset(stream, 0xbd, sizeof(stream)); - EXPECT_EQ(kWriteError, opj_write_from_memory(buffer_data, 5, &dd)); - EXPECT_EQ(0xbd, stream[0]); - } -} - // Note: Some care needs to be taken here because the skip/seek functions // take OPJ_OFF_T's as arguments, which are typically a signed type. TEST(fxcodec, DecodeDataSkip) { - unsigned char buffer[16]; + uint8_t buffer[16]; { DecodeData dd(stream_data, sizeof(stream_data)); @@ -430,7 +341,7 @@ TEST(fxcodec, DecodeDataSkip) { } TEST(fxcodec, DecodeDataSeek) { - unsigned char buffer[16]; + uint8_t buffer[16]; DecodeData dd(stream_data, sizeof(stream_data)); // Seeking within buffer is allowed and read succeeds @@ -526,11 +437,14 @@ TEST(fxcodec, YUV420ToRGB) { y.h = y.w; img.x1 = y.w; img.y1 = y.h; - y.data = FX_Alloc(OPJ_INT32, y.w * y.h); + y.data = static_cast( + opj_image_data_alloc(y.w * y.h * sizeof(OPJ_INT32))); + v.data = static_cast( + opj_image_data_alloc(v.w * v.h * sizeof(OPJ_INT32))); + u.data = static_cast( + opj_image_data_alloc(u.w * u.h * sizeof(OPJ_INT32))); memset(y.data, 1, y.w * y.h * sizeof(OPJ_INT32)); - u.data = FX_Alloc(OPJ_INT32, u.w * u.h); memset(u.data, 0, u.w * u.h * sizeof(OPJ_INT32)); - v.data = FX_Alloc(OPJ_INT32, v.w * v.h); memset(v.data, 0, v.w * v.h * sizeof(OPJ_INT32)); img.comps[0] = y; img.comps[1] = u; @@ -547,9 +461,9 @@ TEST(fxcodec, YUV420ToRGB) { EXPECT_NE(img.comps[0].w, img.comps[2].w); EXPECT_NE(img.comps[0].h, img.comps[2].h); } - FX_Free(img.comps[0].data); - FX_Free(img.comps[1].data); - FX_Free(img.comps[2].data); + opj_image_data_free(img.comps[0].data); + opj_image_data_free(img.comps[1].data); + opj_image_data_free(img.comps[2].data); } FX_Free(img.comps); } diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp index 1f2f50c29e129ae987564842c175eb4e5c6f4286..eb0ecc9d87ebb8d56839933c795247e4b227d3fb 100644 --- a/core/fxcodec/codec/fx_codec_progress.cpp +++ b/core/fxcodec/codec/fx_codec_progress.cpp @@ -8,9 +8,14 @@ #include #include +#include +#include #include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/logging.h" #include "third_party/base/numerics/safe_math.h" #include "third_party/base/ptr_util.h" @@ -18,11 +23,11 @@ namespace { -#if _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ +#if _FX_OS_ == _FX_OS_MACOSX_ const double kPngGamma = 1.7; -#else // _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ +#else // _FX_OS_ == _FX_OS_MACOSX_ const double kPngGamma = 2.2; -#endif // _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ +#endif // _FX_OS_ == _FX_OS_MACOSX_ void RGB2BGR(uint8_t* buffer, int width = 1) { if (buffer && width > 0) { @@ -48,46 +53,36 @@ void CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, int dest_max, int src_len, int src_min, - int src_max, - bool bInterpol) { + int src_max) { double scale, base; - scale = (FX_FLOAT)src_len / (FX_FLOAT)dest_len; + scale = (float)src_len / (float)dest_len; if (dest_len < 0) { - base = (FX_FLOAT)(src_len); + base = (float)(src_len); } else { base = 0.0f; } m_ItemSize = - (int)(sizeof(int) * 2 + - sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + 1)); + (int)(sizeof(int) * 2 + sizeof(int) * (ceil(fabs((float)scale)) + 1)); m_DestMin = dest_min; m_pWeightTables.resize((dest_max - dest_min) * m_ItemSize + 4); - if (FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { + if (fabs((float)scale) < 1.0f) { for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); double src_pos = dest_pixel * scale + scale / 2 + base; - if (bInterpol) { - pixel_weights.m_SrcStart = - (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); - pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); - if (pixel_weights.m_SrcStart < src_min) { - pixel_weights.m_SrcStart = src_min; - } - if (pixel_weights.m_SrcEnd >= src_max) { - pixel_weights.m_SrcEnd = src_max - 1; - } - if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { - pixel_weights.m_Weights[0] = 65536; - } else { - pixel_weights.m_Weights[1] = FXSYS_round( - (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * - 65536); - pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; - } - } else { - pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = - (int)FXSYS_floor((FX_FLOAT)src_pos); + pixel_weights.m_SrcStart = (int)floor((float)src_pos - 1.0f / 2); + pixel_weights.m_SrcEnd = (int)floor((float)src_pos + 1.0f / 2); + if (pixel_weights.m_SrcStart < src_min) { + pixel_weights.m_SrcStart = src_min; + } + if (pixel_weights.m_SrcEnd >= src_max) { + pixel_weights.m_SrcEnd = src_max - 1; + } + if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_Weights[0] = 65536; + } else { + pixel_weights.m_Weights[1] = FXSYS_round( + (float)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536); + pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; } } return; @@ -98,11 +93,11 @@ void CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, double src_end = src_start + scale; int start_i, end_i; if (src_start < src_end) { - start_i = (int)FXSYS_floor((FX_FLOAT)src_start); - end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); + start_i = (int)floor((float)src_start); + end_i = (int)ceil((float)src_end); } else { - start_i = (int)FXSYS_floor((FX_FLOAT)src_end); - end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); + start_i = (int)floor((float)src_end); + end_i = (int)ceil((float)src_start); } if (start_i < src_min) { start_i = src_min; @@ -118,18 +113,17 @@ void CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, pixel_weights.m_SrcStart = start_i; pixel_weights.m_SrcEnd = end_i; for (int j = start_i; j <= end_i; j++) { - double dest_start = ((FX_FLOAT)j - base) / scale; - double dest_end = ((FX_FLOAT)(j + 1) - base) / scale; + double dest_start = ((float)j - base) / scale; + double dest_end = ((float)(j + 1) - base) / scale; if (dest_start > dest_end) { double temp = dest_start; dest_start = dest_end; dest_end = temp; } - double area_start = dest_start > (FX_FLOAT)(dest_pixel) - ? dest_start - : (FX_FLOAT)(dest_pixel); - double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) - ? (FX_FLOAT)(dest_pixel + 1) + double area_start = + dest_start > (float)(dest_pixel) ? dest_start : (float)(dest_pixel); + double area_end = dest_end > (float)(dest_pixel + 1) + ? (float)(dest_pixel + 1) : dest_end; double weight = area_start >= area_end ? 0.0f : area_end - area_start; if (weight == 0 && j == end_i) { @@ -137,7 +131,7 @@ void CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, break; } pixel_weights.m_Weights[j - start_i] = - FXSYS_round((FX_FLOAT)(weight * 65536)); + FXSYS_round((float)(weight * 65536)); } } } @@ -147,8 +141,7 @@ CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::CFXCODEC_HorzTable() {} CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::~CFXCODEC_HorzTable() {} void CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, - int src_len, - bool bInterpol) { + int src_len) { double scale = (double)dest_len / (double)src_len; m_ItemSize = sizeof(int) * 4; int size = dest_len * m_ItemSize + 4; @@ -157,7 +150,7 @@ void CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, int pre_des_col = 0; for (int src_col = 0; src_col < src_len; src_col++) { double des_col_f = src_col * scale; - int des_col = FXSYS_round((FX_FLOAT)des_col_f); + int des_col = FXSYS_round((float)des_col_f); PixelWeight* pWeight = GetPixelWeight(des_col); pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; pWeight->m_Weights[0] = 65536; @@ -179,10 +172,8 @@ void CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, pWeight->m_SrcStart = src_col - 1; pWeight->m_SrcEnd = src_col; pWeight->m_Weights[0] = - bInterpol ? FXSYS_round((FX_FLOAT)( - ((FX_FLOAT)des_col - (FX_FLOAT)des_col_index) / - (FX_FLOAT)des_col_len * 65536)) - : 65536; + FXSYS_round((float)(((float)des_col - (float)des_col_index) / + (float)des_col_len * 65536)); pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; } pre_des_col = des_col; @@ -191,7 +182,7 @@ void CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, } for (int des_col = 0; des_col < dest_len; des_col++) { double src_col_f = des_col / scale; - int src_col = FXSYS_round((FX_FLOAT)src_col_f); + int src_col = FXSYS_round((float)src_col_f); PixelWeight* pWeight = GetPixelWeight(des_col); pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; pWeight->m_Weights[0] = 65536; @@ -249,8 +240,8 @@ void CCodec_ProgressiveDecoder::CFXCODEC_VertTable::Calc(int dest_len, PixelWeight* pWeight = GetPixelWeight(des_row); pWeight->m_SrcStart = start_step; pWeight->m_SrcEnd = end_step; - pWeight->m_Weights[0] = FXSYS_round((FX_FLOAT)(end_step - des_row) / - (FX_FLOAT)length * 65536); + pWeight->m_Weights[0] = + FXSYS_round((float)(end_step - des_row) / (float)length * 65536); pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; } } @@ -261,7 +252,6 @@ CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder( m_pFile = nullptr; m_pJpegContext = nullptr; m_pPngContext = nullptr; - m_pGifContext = nullptr; m_pBmpContext = nullptr; m_pTiffContext = nullptr; m_pCodecMgr = nullptr; @@ -284,7 +274,6 @@ CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder( m_TransMethod = -1; m_SrcRow = 0; m_SrcFormat = FXCodec_Invalid; - m_bInterpol = true; m_FrameNumber = 0; m_FrameCur = 0; m_SrcPaletteNumber = 0; @@ -297,17 +286,6 @@ CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder( } CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() { - m_pFile = nullptr; - if (m_pJpegContext) - m_pCodecMgr->GetJpegModule()->Finish(m_pJpegContext); - if (m_pBmpContext) - m_pCodecMgr->GetBmpModule()->Finish(m_pBmpContext); - if (m_pGifContext) - m_pCodecMgr->GetGifModule()->Finish(m_pGifContext); - if (m_pPngContext) - m_pCodecMgr->GetPngModule()->Finish(m_pPngContext); - if (m_pTiffContext) - m_pCodecMgr->GetTiffModule()->DestroyDecoder(m_pTiffContext); FX_Free(m_pSrcBuf); FX_Free(m_pDecodeBuf); FX_Free(m_pSrcPalette); @@ -320,7 +298,7 @@ bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, return false; } dwSize = dwSize - m_offSet; - uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext, nullptr); + uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr); if (dwAvail == m_SrcSize) { if (dwSize > FXCODEC_BLOCK_SIZE) { dwSize = FXCODEC_BLOCK_SIZE; @@ -335,7 +313,7 @@ bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, } else { uint32_t dwConsume = m_SrcSize - dwAvail; if (dwAvail) { - FXSYS_memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); } if (dwSize > dwConsume) { dwSize = dwConsume; @@ -346,7 +324,7 @@ bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, return false; } m_offSet += dwSize; - pJpegModule->Input(m_pJpegContext, m_pSrcBuf, dwSize + dwAvail); + pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail); return true; } @@ -386,7 +364,7 @@ bool CCodec_ProgressiveDecoder::PngReadHeader(int width, switch (format) { case FXDIB_1bppMask: case FXDIB_1bppRgb: - ASSERT(false); + NOTREACHED(); return false; case FXDIB_8bppMask: case FXDIB_8bppRgb: @@ -400,17 +378,17 @@ bool CCodec_ProgressiveDecoder::PngReadHeader(int width, *color_type = 6; break; default: - ASSERT(false); + NOTREACHED(); return false; } *gamma = kPngGamma; return true; } -bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t*& src_buf) { - CFX_DIBitmap* pDIBitmap = m_pDeviceBitmap; +bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t** pSrcBuf) { + RetainPtr pDIBitmap = m_pDeviceBitmap; if (!pDIBitmap) { - ASSERT(false); + NOTREACHED(); return false; } if (line >= m_clipBox.top && line < m_clipBox.bottom) { @@ -418,7 +396,7 @@ bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t*& src_buf) { int32_t row = (int32_t)((line - m_clipBox.top) * scale_y) + m_startY; uint8_t* src_scan = (uint8_t*)pDIBitmap->GetScanline(row); uint8_t* des_scan = m_pDecodeBuf; - src_buf = m_pDecodeBuf; + *pSrcBuf = m_pDecodeBuf; int32_t src_Bpp = pDIBitmap->GetBPP() >> 3; int32_t des_Bpp = (m_SrcFormat & 0xff) >> 3; int32_t src_left = m_startX; @@ -433,7 +411,7 @@ bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t*& src_buf) { switch (pDIBitmap->GetFormat()) { case FXDIB_1bppMask: case FXDIB_1bppRgb: - ASSERT(false); + NOTREACHED(); return false; case FXDIB_8bppMask: case FXDIB_8bppRgb: { @@ -477,7 +455,7 @@ bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t*& src_buf) { } void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( - CFX_DIBitmap* pDeviceBitmap, + const RetainPtr& pDeviceBitmap, int32_t des_line, uint8_t* src_scan, FXCodec_Format src_format) { @@ -493,7 +471,7 @@ void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( switch (pDeviceBitmap->GetFormat()) { case FXDIB_1bppMask: case FXDIB_1bppRgb: - ASSERT(false); + NOTREACHED(); return; case FXDIB_8bppMask: case FXDIB_8bppRgb: { @@ -550,7 +528,7 @@ void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, int line) { - CFX_DIBitmap* pDIBitmap = m_pDeviceBitmap; + RetainPtr pDIBitmap = m_pDeviceBitmap; ASSERT(pDIBitmap); int src_top = m_clipBox.top; int src_bottom = m_clipBox.bottom; @@ -575,14 +553,14 @@ void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, } } -bool CCodec_ProgressiveDecoder::GifReadMoreData(ICodec_GifModule* pGifModule, +bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule, FXCODEC_STATUS& err_status) { uint32_t dwSize = (uint32_t)m_pFile->GetSize(); if (dwSize <= m_offSet) { return false; } dwSize = dwSize - m_offSet; - uint32_t dwAvail = pGifModule->GetAvailInput(m_pGifContext, nullptr); + uint32_t dwAvail = pGifModule->GetAvailInput(m_pGifContext.get(), nullptr); if (dwAvail == m_SrcSize) { if (dwSize > FXCODEC_BLOCK_SIZE) { dwSize = FXCODEC_BLOCK_SIZE; @@ -597,7 +575,7 @@ bool CCodec_ProgressiveDecoder::GifReadMoreData(ICodec_GifModule* pGifModule, } else { uint32_t dwConsume = m_SrcSize - dwAvail; if (dwAvail) { - FXSYS_memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); } if (dwSize > dwConsume) { dwSize = dwConsume; @@ -608,21 +586,16 @@ bool CCodec_ProgressiveDecoder::GifReadMoreData(ICodec_GifModule* pGifModule, return false; } m_offSet += dwSize; - pGifModule->Input(m_pGifContext, m_pSrcBuf, dwSize + dwAvail); + pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, dwSize + dwAvail); return true; } void CCodec_ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) { uint32_t remain_size = - m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext); + m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext.get()); cur_pos = m_offSet - remain_size; } -uint8_t* CCodec_ProgressiveDecoder::GifAskLocalPaletteBuf(int32_t frame_num, - int32_t pal_size) { - return FX_Alloc(uint8_t, pal_size); -} - bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf( uint32_t rcd_pos, const FX_RECT& img_rc, @@ -642,6 +615,8 @@ bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf( if (pal_num != 0 && pal_ptr) { pPalette = (uint8_t*)pal_ptr; } else { + if (!m_pGifPalette) + return false; pal_num = m_GifPltNumber; pPalette = m_pGifPalette; } @@ -662,7 +637,7 @@ bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf( m_GifFrameRect = img_rc; m_SrcPassNumber = interlace ? 4 : 1; int32_t pal_index = m_GifBgIndex; - CFX_DIBitmap* pDevice = m_pDeviceBitmap; + RetainPtr pDevice = m_pDeviceBitmap; if (trans_index >= pal_num) trans_index = -1; if (trans_index != -1) { @@ -686,7 +661,7 @@ bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf( case 3: { uint8_t gray = FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); - FXSYS_memset(pScanline, gray, sizeX); + memset(pScanline, gray, sizeX); break; } case 8: { @@ -712,7 +687,7 @@ bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf( void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, uint8_t* row_buf) { - CFX_DIBitmap* pDIBitmap = m_pDeviceBitmap; + RetainPtr pDIBitmap = m_pDeviceBitmap; ASSERT(pDIBitmap); int32_t img_width = m_GifFrameRect.Width(); if (!pDIBitmap->HasAlpha()) { @@ -728,11 +703,11 @@ void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, if (m_GifTransIndex != -1 && m_pDeviceBitmap->HasAlpha()) { pal_index = m_GifTransIndex; } - FXSYS_memset(m_pDecodeBuf, pal_index, m_SrcWidth); + memset(m_pDecodeBuf, pal_index, m_SrcWidth); bool bLastPass = (row_num % 2) == 1; int32_t line = row_num + m_GifFrameRect.top; int32_t left = m_GifFrameRect.left; - FXSYS_memcpy(m_pDecodeBuf + left, row_buf, img_width); + memcpy(m_pDecodeBuf + left, row_buf, img_width); int src_top = m_clipBox.top; int src_bottom = m_clipBox.bottom; int des_top = m_startY; @@ -748,7 +723,7 @@ void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, return; ReSampleScanline(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat); - if (scale_y > 1.0 && (!m_bInterpol || m_SrcPassNumber == 1)) { + if (scale_y > 1.0 && m_SrcPassNumber == 1) { ResampleVert(pDIBitmap, scale_y, des_row); return; } @@ -766,7 +741,7 @@ void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, uint8_t* scan_des = (uint8_t*)pDIBitmap->GetScanline(cur_row) + des_ScanOffet; uint32_t size = m_sizeX * des_Bpp; - FXSYS_memmove(scan_des, scan_src, size); + memmove(scan_des, scan_src, size); } } if (bLastPass) @@ -774,7 +749,7 @@ void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, } void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( - CFX_DIBitmap* pDeviceBitmap, + const RetainPtr& pDeviceBitmap, double scale_y, int des_row) { int des_Bpp = pDeviceBitmap->GetBPP() >> 3; @@ -854,14 +829,14 @@ void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( } } -bool CCodec_ProgressiveDecoder::BmpReadMoreData(ICodec_BmpModule* pBmpModule, +bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule, FXCODEC_STATUS& err_status) { uint32_t dwSize = (uint32_t)m_pFile->GetSize(); if (dwSize <= m_offSet) return false; dwSize = dwSize - m_offSet; - uint32_t dwAvail = pBmpModule->GetAvailInput(m_pBmpContext, nullptr); + uint32_t dwAvail = pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr); if (dwAvail == m_SrcSize) { if (dwSize > FXCODEC_BLOCK_SIZE) { dwSize = FXCODEC_BLOCK_SIZE; @@ -876,7 +851,7 @@ bool CCodec_ProgressiveDecoder::BmpReadMoreData(ICodec_BmpModule* pBmpModule, } else { uint32_t dwConsume = m_SrcSize - dwAvail; if (dwAvail) { - FXSYS_memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); } if (dwSize > dwConsume) { dwSize = dwConsume; @@ -887,7 +862,7 @@ bool CCodec_ProgressiveDecoder::BmpReadMoreData(ICodec_BmpModule* pBmpModule, return false; } m_offSet += dwSize; - pBmpModule->Input(m_pBmpContext, m_pSrcBuf, dwSize + dwAvail); + pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail); return true; } @@ -897,18 +872,21 @@ bool CCodec_ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) { return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), error_status); } -void CCodec_ProgressiveDecoder::BmpReadScanline(int32_t row_num, - uint8_t* row_buf) { - CFX_DIBitmap* pDIBitmap = m_pDeviceBitmap; +void CCodec_ProgressiveDecoder::BmpReadScanline( + uint32_t row_num, + const std::vector& row_buf) { + RetainPtr pDIBitmap = m_pDeviceBitmap; ASSERT(pDIBitmap); - FXSYS_memcpy(m_pDecodeBuf, row_buf, m_ScanlineSize); + std::copy(row_buf.begin(), row_buf.begin() + m_ScanlineSize, m_pDecodeBuf); int src_top = m_clipBox.top; int src_bottom = m_clipBox.bottom; int des_top = m_startY; int src_hei = m_clipBox.Height(); int des_hei = m_sizeY; - if (row_num < src_top || row_num >= src_bottom) + if ((src_top >= 0 && row_num < static_cast(src_top)) || + src_bottom < 0 || row_num >= static_cast(src_bottom)) { return; + } double scale_y = (double)des_hei / (double)src_hei; int src_row = row_num - src_top; @@ -920,16 +898,17 @@ void CCodec_ProgressiveDecoder::BmpReadScanline(int32_t row_num, if (scale_y <= 1.0) return; - if (m_BmpIsTopBottom || !m_bInterpol) { + if (m_BmpIsTopBottom) { ResampleVert(pDIBitmap, scale_y, des_row); return; } ResampleVertBT(pDIBitmap, scale_y, des_row); } -void CCodec_ProgressiveDecoder::ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row) { +void CCodec_ProgressiveDecoder::ResampleVertBT( + const RetainPtr& pDeviceBitmap, + double scale_y, + int des_row) { int des_Bpp = pDeviceBitmap->GetBPP() >> 3; uint32_t des_ScanOffet = m_startX * des_Bpp; int des_top = m_startY; @@ -944,7 +923,7 @@ void CCodec_ProgressiveDecoder::ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, uint8_t* scan_des = (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; uint32_t size = m_sizeX * des_Bpp; - FXSYS_memmove(scan_des, scan_src, size); + memmove(scan_des, scan_src, size); } return; } @@ -1020,240 +999,288 @@ bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, } FX_Free(m_pSrcBuf); m_pSrcBuf = FX_Alloc(uint8_t, size); - FXSYS_memset(m_pSrcBuf, 0, size); + memset(m_pSrcBuf, 0, size); m_SrcSize = size; switch (imageType) { - case FXCODEC_IMAGE_BMP: { - ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - pBmpModule->SetDelegate(this); - m_pBmpContext = pBmpModule->Start(); - if (!m_pBmpContext) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += size; - pBmpModule->Input(m_pBmpContext, m_pSrcBuf, size); - uint32_t* pPalette = nullptr; - int32_t readResult = pBmpModule->ReadHeader( - m_pBmpContext, &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, - &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!BmpReadMoreData(pBmpModule, error_status)) { - m_status = error_status; - return false; - } - readResult = pBmpModule->ReadHeader( - m_pBmpContext, &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, - &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute); - } - if (readResult == 1) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - FX_Free(m_pSrcPalette); - if (m_SrcPaletteNumber) { - m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber); - FXSYS_memcpy(m_pSrcPalette, pPalette, - m_SrcPaletteNumber * sizeof(uint32_t)); - } else { - m_pSrcPalette = nullptr; - } - return true; - } - if (m_pBmpContext) { - pBmpModule->Finish(m_pBmpContext); - m_pBmpContext = nullptr; - } + case FXCODEC_IMAGE_BMP: + return BmpDetectImageType(pAttribute, size); + case FXCODEC_IMAGE_JPG: + return JpegDetectImageType(pAttribute, size); + case FXCODEC_IMAGE_PNG: + return PngDetectImageType(pAttribute, size); + case FXCODEC_IMAGE_GIF: + return GifDetectImageType(pAttribute, size); + case FXCODEC_IMAGE_TIF: + return TifDetectImageType(pAttribute, size); + default: m_status = FXCODEC_STATUS_ERR_FORMAT; return false; + } +} + +bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + + m_pBmpContext = pBmpModule->Start(this); + if (!m_pBmpContext) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + + if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + + m_offSet += size; + pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, size); + std::vector palette; + int32_t readResult = pBmpModule->ReadHeader( + m_pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, + &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!BmpReadMoreData(pBmpModule, error_status)) { + m_status = error_status; + return false; } - case FXCODEC_IMAGE_JPG: { - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - if (!pJpegModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - m_pJpegContext = pJpegModule->Start(); - if (!m_pJpegContext) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += size; - pJpegModule->Input(m_pJpegContext, m_pSrcBuf, size); - int32_t readResult = - pJpegModule->ReadHeader(m_pJpegContext, &m_SrcWidth, &m_SrcHeight, - &m_SrcComponents, pAttribute); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_status = error_status; - return false; - } - readResult = - pJpegModule->ReadHeader(m_pJpegContext, &m_SrcWidth, &m_SrcHeight, - &m_SrcComponents, pAttribute); - } - if (!readResult) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - return true; - } - if (m_pJpegContext) { - pJpegModule->Finish(m_pJpegContext); - m_pJpegContext = nullptr; - } + readResult = pBmpModule->ReadHeader( + m_pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, + &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute); + } + + if (readResult != 1) { + m_pBmpContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + + FXDIB_Format format = FXDIB_Invalid; + switch (m_SrcComponents) { + case 1: + m_SrcFormat = FXCodec_8bppRgb; + format = FXDIB_8bppRgb; + break; + case 3: + m_SrcFormat = FXCodec_Rgb; + format = FXDIB_Rgb; + break; + case 4: + m_SrcFormat = FXCodec_Rgb32; + format = FXDIB_Rgb32; + break; + default: + m_pBmpContext.reset(); m_status = FXCODEC_STATUS_ERR_FORMAT; return false; + } + + uint32_t pitch = 0; + uint32_t neededData = 0; + if (!CFX_DIBitmap::CalculatePitchAndSize(m_SrcWidth, m_SrcHeight, format, + &pitch, &neededData)) { + m_pBmpContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + + uint32_t availableData = m_SrcSize > m_offSet ? m_SrcSize - m_offSet : 0; + if (neededData > availableData) { + m_pBmpContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + FX_Free(m_pSrcPalette); + if (m_SrcPaletteNumber) { + m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber); + memcpy(m_pSrcPalette, palette.data(), m_SrcPaletteNumber * sizeof(FX_ARGB)); + } else { + m_pSrcPalette = nullptr; + } + return true; +} + +bool CCodec_ProgressiveDecoder::JpegDetectImageType( + CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + // Setting jump marker before calling Start or ReadHeader, since a longjmp + // to the marker indicates a fatal error in these functions. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_status = FXCODEC_STATUS_ERROR; + return false; + } + + m_pJpegContext = pJpegModule->Start(); + if (!m_pJpegContext) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += size; + pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, size); + // Setting jump marker before calling ReadHeader, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + + int32_t readResult = + pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, + &m_SrcComponents, pAttribute); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_status = error_status; + return false; } - case FXCODEC_IMAGE_PNG: { - ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - pPngModule->SetDelegate(this); - m_pPngContext = pPngModule->Start(); - if (!m_pPngContext) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += size; - bResult = pPngModule->Input(m_pPngContext, m_pSrcBuf, size, pAttribute); - while (bResult) { - uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; - uint32_t input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - if (m_pPngContext) { - pPngModule->Finish(m_pPngContext); - } - m_pPngContext = nullptr; - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - if (m_pSrcBuf && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - FXSYS_memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; - } - bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += input_size; - bResult = - pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, pAttribute); - } - ASSERT(!bResult); - if (m_pPngContext) { - pPngModule->Finish(m_pPngContext); - m_pPngContext = nullptr; - } - if (m_SrcPassNumber == 0) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - return true; - } - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - pGifModule->SetDelegate(this); - m_pGifContext = pGifModule->Start(); - if (!m_pGifContext) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += size; - pGifModule->Input(m_pGifContext, m_pSrcBuf, size); - m_SrcComponents = 1; - int32_t readResult = pGifModule->ReadHeader( - m_pGifContext, &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, - (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!GifReadMoreData(pGifModule, error_status)) { - m_status = error_status; - return false; - } - readResult = pGifModule->ReadHeader( - m_pGifContext, &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, - (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); - } - if (readResult == 1) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - return true; - } - if (m_pGifContext) { - pGifModule->Finish(m_pGifContext); - m_pGifContext = nullptr; - } + readResult = + pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, + &m_SrcComponents, pAttribute); + } + if (!readResult) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + return true; + } + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; +} + +bool CCodec_ProgressiveDecoder::PngDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + m_pPngContext = pPngModule->Start(this); + if (!m_pPngContext) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += size; + bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, size, pAttribute); + while (bResult) { + uint32_t remain_size = static_cast(m_pFile->GetSize()) - m_offSet; + uint32_t input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + m_pPngContext.reset(); m_status = FXCODEC_STATUS_ERR_FORMAT; return false; } - case FXCODEC_IMAGE_TIF: { - ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - if (!pTiffModule) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); - if (!m_pTiffContext) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - int32_t dummy_bpc; - bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext, 0, &m_SrcWidth, - &m_SrcHeight, &m_SrcComponents, - &dummy_bpc, pAttribute); - m_SrcComponents = 4; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - if (!ret) { - pTiffModule->DestroyDecoder(m_pTiffContext); - m_pTiffContext = nullptr; - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - return true; + if (m_pSrcBuf && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; } - default: - m_status = FXCODEC_STATUS_ERR_FORMAT; + bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += input_size; + bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, + pAttribute); + } + ASSERT(!bResult); + m_pPngContext.reset(); + if (m_SrcPassNumber == 0) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + return true; +} + +bool CCodec_ProgressiveDecoder::GifDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + m_pGifContext = pGifModule->Start(this); + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += size; + pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, size); + m_SrcComponents = 1; + CFX_GifDecodeStatus readResult = pGifModule->ReadHeader( + m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, + (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); + while (readResult == CFX_GifDecodeStatus::Unfinished) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!GifReadMoreData(pGifModule, error_status)) { + m_pGifContext = nullptr; + m_status = error_status; return false; + } + readResult = pGifModule->ReadHeader( + m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, + (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); + } + if (readResult == CFX_GifDecodeStatus::Success) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + return true; + } + m_pGifContext = nullptr; + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; +} + +bool CCodec_ProgressiveDecoder::TifDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + if (!pTiffModule) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; } + m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); + if (!m_pTiffContext) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + int32_t dummy_bpc; + bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth, + &m_SrcHeight, &m_SrcComponents, + &dummy_bpc, pAttribute); + m_SrcComponents = 4; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + if (!ret) { + m_pTiffContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + return true; } FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( - const CFX_RetainPtr& pFile, + const RetainPtr& pFile, FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute* pAttribute, bool bSkipImageTypeCheck) { @@ -1444,10 +1471,11 @@ void CCodec_ProgressiveDecoder::GetTransMethod(FXDIB_Format des_format, } } -void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, - int des_line, - uint8_t* src_scan, - FXCodec_Format src_format) { +void CCodec_ProgressiveDecoder::ReSampleScanline( + const RetainPtr& pDeviceBitmap, + int des_line, + uint8_t* src_scan, + FXCodec_Format src_format) { int src_left = m_clipBox.left; int des_left = m_startX; uint8_t* des_scan = @@ -1512,10 +1540,12 @@ void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, int pixel_weight = pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; const uint8_t* src_pixel = src_scan + j * src_Bpp; - uint8_t src_b = 0, src_g = 0, src_r = 0; - AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], - 255 - src_pixel[2], 255 - src_pixel[3], src_r, - src_g, src_b); + uint8_t src_b = 0; + uint8_t src_g = 0; + uint8_t src_r = 0; + std::tie(src_r, src_g, src_b) = + AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], + 255 - src_pixel[2], 255 - src_pixel[3]); des_b += pixel_weight * src_b; des_g += pixel_weight * src_g; des_r += pixel_weight * src_r; @@ -1533,7 +1563,7 @@ void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; des_g += pixel_weight * src_scan[j]; } - FXSYS_memset(des_scan, (uint8_t)(des_g >> 16), 3); + memset(des_scan, (uint8_t)(des_g >> 16), 3); des_scan += des_Bpp; } break; case 8: { @@ -1609,10 +1639,12 @@ void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, int pixel_weight = pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; const uint8_t* src_pixel = src_scan + j * src_Bpp; - uint8_t src_b = 0, src_g = 0, src_r = 0; - AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], - 255 - src_pixel[2], 255 - src_pixel[3], src_r, - src_g, src_b); + uint8_t src_b = 0; + uint8_t src_g = 0; + uint8_t src_r = 0; + std::tie(src_r, src_g, src_b) = + AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], + 255 - src_pixel[2], 255 - src_pixel[3]); des_b += pixel_weight * src_b; des_g += pixel_weight * src_g; des_r += pixel_weight * src_r; @@ -1646,92 +1678,17 @@ void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, } } -void CCodec_ProgressiveDecoder::ResampleVert(CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row) { +void CCodec_ProgressiveDecoder::ResampleVert( + const RetainPtr& pDeviceBitmap, + double scale_y, + int des_row) { int des_Bpp = pDeviceBitmap->GetBPP() >> 3; uint32_t des_ScanOffet = m_startX * des_Bpp; - if (m_bInterpol) { - int des_top = m_startY; - pdfium::base::CheckedNumeric check_des_row_1 = des_row; - check_des_row_1 -= pdfium::base::checked_cast(scale_y); - int des_row_1 = check_des_row_1.ValueOrDie(); - if (des_row_1 < des_top) { - int des_bottom = des_top + m_sizeY; - if (des_row + (int)scale_y >= des_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - while (++des_row < des_bottom) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - uint32_t size = m_sizeX * des_Bpp; - FXSYS_memmove(scan_des, scan_src, size); - } - } - return; - } - for (; des_row_1 < des_row; des_row_1++) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; - PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); - const uint8_t* scan_src1 = - pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + - des_ScanOffet; - const uint8_t* scan_src2 = - pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + - des_ScanOffet; - for (int des_col = 0; des_col < m_sizeX; des_col++) { - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_Invalid: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette()) { - return; - } - int des_g = 0; - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)(des_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - uint32_t des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - scan_src1 += des_Bpp - 3; - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - scan_src2 += des_Bpp - 3; - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - scan_des += des_Bpp - 3; - } break; - case FXDIB_Argb: { - uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - des_a += pWeight->m_Weights[0] * (*scan_src1++); - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - des_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - *scan_des++ = (uint8_t)((des_a) >> 16); - } break; - default: - return; - } - } - } + int des_top = m_startY; + pdfium::base::CheckedNumeric check_des_row_1 = des_row; + check_des_row_1 -= pdfium::base::checked_cast(scale_y); + int des_row_1 = check_des_row_1.ValueOrDie(); + if (des_row_1 < des_top) { int des_bottom = des_top + m_sizeY; if (des_row + (int)scale_y >= des_bottom - 1) { uint8_t* scan_src = @@ -1740,31 +1697,90 @@ void CCodec_ProgressiveDecoder::ResampleVert(CFX_DIBitmap* pDeviceBitmap, uint8_t* scan_des = (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; uint32_t size = m_sizeX * des_Bpp; - FXSYS_memmove(scan_des, scan_src, size); + memmove(scan_des, scan_src, size); } } return; } - int multiple = (int)FXSYS_ceil((FX_FLOAT)scale_y - 1); - if (multiple > 0) { + for (; des_row_1 < des_row; des_row_1++) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; + PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); + const uint8_t* scan_src1 = + pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + + des_ScanOffet; + const uint8_t* scan_src2 = + pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet; + for (int des_col = 0; des_col < m_sizeX; des_col++) { + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_Invalid: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette()) { + return; + } + int des_g = 0; + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)(des_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + uint32_t des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + scan_src1 += des_Bpp - 3; + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + scan_src2 += des_Bpp - 3; + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + scan_des += des_Bpp - 3; + } break; + case FXDIB_Argb: { + uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + des_a += pWeight->m_Weights[0] * (*scan_src1++); + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + des_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + *scan_des++ = (uint8_t)((des_a) >> 16); + } break; + default: + return; + } + } + } + int des_bottom = des_top + m_sizeY; + if (des_row + (int)scale_y >= des_bottom - 1) { uint8_t* scan_src = (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - for (int i = 1; i <= multiple; i++) { - if (des_row + i >= m_startY + m_sizeY) { - return; - } + while (++des_row < des_bottom) { uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row + i) + des_ScanOffet; + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; uint32_t size = m_sizeX * des_Bpp; - FXSYS_memmove(scan_des, scan_src, size); + memmove(scan_des, scan_src, size); } } } -void CCodec_ProgressiveDecoder::Resample(CFX_DIBitmap* pDeviceBitmap, - int32_t src_line, - uint8_t* src_scan, - FXCodec_Format src_format) { +void CCodec_ProgressiveDecoder::Resample( + const RetainPtr& pDeviceBitmap, + int32_t src_line, + uint8_t* src_scan, + FXCodec_Format src_format) { int src_top = m_clipBox.top; int des_top = m_startY; int src_hei = m_clipBox.Height(); @@ -1783,72 +1799,64 @@ void CCodec_ProgressiveDecoder::Resample(CFX_DIBitmap* pDeviceBitmap, } } -FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t& frames, - IFX_Pause* pPause) { +std::pair CCodec_ProgressiveDecoder::GetFrames() { if (!(m_status == FXCODEC_STATUS_FRAME_READY || m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) { - return FXCODEC_STATUS_ERROR; + return {FXCODEC_STATUS_ERROR, 0}; } + switch (m_imagType) { case FXCODEC_IMAGE_JPG: case FXCODEC_IMAGE_BMP: case FXCODEC_IMAGE_PNG: case FXCODEC_IMAGE_TIF: - frames = m_FrameNumber = 1; + m_FrameNumber = 1; m_status = FXCODEC_STATUS_DECODE_READY; - return m_status; + return {m_status, 1}; case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); if (!pGifModule) { m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; + return {m_status, 0}; } while (true) { - int32_t readResult = - pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber); - while (readResult == 2) { + CFX_GifDecodeStatus readResult; + std::tie(readResult, m_FrameNumber) = + pGifModule->LoadFrameInfo(m_pGifContext.get()); + while (readResult == CFX_GifDecodeStatus::Unfinished) { FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; - if (!GifReadMoreData(pGifModule, error_status)) { - return error_status; - } - if (pPause && pPause->NeedToPauseNow()) { - m_status = FXCODEC_STATUS_FRAME_TOBECONTINUE; - return m_status; - } - readResult = pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber); + if (!GifReadMoreData(pGifModule, error_status)) + return {error_status, 0}; + + std::tie(readResult, m_FrameNumber) = + pGifModule->LoadFrameInfo(m_pGifContext.get()); } - if (readResult == 1) { - frames = m_FrameNumber; + if (readResult == CFX_GifDecodeStatus::Success) { m_status = FXCODEC_STATUS_DECODE_READY; - return m_status; - } - if (m_pGifContext) { - pGifModule->Finish(m_pGifContext); - m_pGifContext = nullptr; + return {m_status, m_FrameNumber}; } + m_pGifContext = nullptr; m_status = FXCODEC_STATUS_ERROR; - return m_status; + return {m_status, 0}; } } default: - return FXCODEC_STATUS_ERROR; + return {FXCODEC_STATUS_ERROR, 0}; } } -FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode(CFX_DIBitmap* pDIBitmap, - int start_x, - int start_y, - int size_x, - int size_y, - int32_t frames, - bool bInterpol) { +FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode( + const RetainPtr& pDIBitmap, + int start_x, + int start_y, + int size_x, + int size_y) { if (m_status != FXCODEC_STATUS_DECODE_READY) return FXCODEC_STATUS_ERROR; - if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || frames < 0 || - frames >= m_FrameNumber) { + if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0) return FXCODEC_STATUS_ERR_PARAMS; - } + m_pDeviceBitmap = pDIBitmap; if (m_clipBox.IsEmpty()) return FXCODEC_STATUS_ERR_PARAMS; @@ -1868,483 +1876,492 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode(CFX_DIBitmap* pDIBitmap, m_startY = device_rc.top; m_sizeX = device_rc.Width(); m_sizeY = device_rc.Height(); - m_bInterpol = bInterpol; m_FrameCur = 0; if (start_x < 0 || out_range_x > 0) { - FX_FLOAT scaleX = (FX_FLOAT)m_clipBox.Width() / (FX_FLOAT)size_x; + float scaleX = (float)m_clipBox.Width() / (float)size_x; if (start_x < 0) { - m_clipBox.left -= (int32_t)FXSYS_ceil((FX_FLOAT)start_x * scaleX); + m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX); } if (out_range_x > 0) { - m_clipBox.right -= (int32_t)FXSYS_floor((FX_FLOAT)out_range_x * scaleX); + m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX); } } if (start_y < 0 || out_range_y > 0) { - FX_FLOAT scaleY = (FX_FLOAT)m_clipBox.Height() / (FX_FLOAT)size_y; + float scaleY = (float)m_clipBox.Height() / (float)size_y; if (start_y < 0) { - m_clipBox.top -= (int32_t)FXSYS_ceil((FX_FLOAT)start_y * scaleY); + m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY); } if (out_range_y > 0) { - m_clipBox.bottom -= (int32_t)FXSYS_floor((FX_FLOAT)out_range_y * scaleY); + m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY); } } if (m_clipBox.IsEmpty()) { return FXCODEC_STATUS_ERR_PARAMS; } switch (m_imagType) { - case FXCODEC_IMAGE_JPG: { - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - int down_scale = 1; - GetDownScale(down_scale); - bool bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); - while (!bStart) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); - } - int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; - scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - FXSYS_memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - switch (m_SrcComponents) { - case 1: - m_SrcFormat = FXCodec_8bppGray; - break; - case 3: - m_SrcFormat = FXCodec_Rgb; - break; - case 4: - m_SrcFormat = FXCodec_Cmyk; - break; - } - GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; - } - case FXCODEC_IMAGE_PNG: { - ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - if (m_pPngContext) { - pPngModule->Finish(m_pPngContext); - m_pPngContext = nullptr; - } - m_pPngContext = pPngModule->Start(); - if (!m_pPngContext) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_offSet = 0; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppMask: - case FXDIB_8bppRgb: - m_SrcComponents = 1; - m_SrcFormat = FXCodec_8bppGray; - break; - case FXDIB_Rgb: - m_SrcComponents = 3; - m_SrcFormat = FXCodec_Rgb; - break; - case FXDIB_Rgb32: - case FXDIB_Argb: - m_SrcComponents = 4; - m_SrcFormat = FXCodec_Argb; - break; - default: { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_PARAMS; - return m_status; - } - } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - FXSYS_memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + case FXCODEC_IMAGE_JPG: + return JpegStartDecode(pDIBitmap); + case FXCODEC_IMAGE_PNG: + return PngStartDecode(pDIBitmap); + case FXCODEC_IMAGE_GIF: + return GifStartDecode(pDIBitmap); + case FXCODEC_IMAGE_BMP: + return BmpStartDecode(pDIBitmap); + case FXCODEC_IMAGE_TIF: m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; return m_status; - } - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_SrcFormat = FXCodec_8bppRgb; - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - FXSYS_memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_FrameCur = frames; - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + default: + return FXCODEC_STATUS_ERROR; + } +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode( + const RetainPtr& pDIBitmap) { + int down_scale = 1; + GetDownScale(down_scale); + // Setting jump marker before calling StartScanLine, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERROR; + return FXCODEC_STATUS_ERROR; + } + + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + bool startStatus = + pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); + while (!startStatus) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; return m_status; } - case FXCODEC_IMAGE_BMP: { - ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - switch (m_SrcComponents) { - case 1: - m_SrcFormat = FXCodec_8bppRgb; - break; - case 3: - m_SrcFormat = FXCodec_Rgb; - break; - case 4: - m_SrcFormat = FXCodec_Rgb32; - break; - } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); - FXSYS_memset(m_pDecodeBuf, 0, m_ScanlineSize); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + + startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); + } + int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; + scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + switch (m_SrcComponents) { + case 1: + m_SrcFormat = FXCodec_8bppGray; + break; + case 3: + m_SrcFormat = FXCodec_Rgb; + break; + case 4: + m_SrcFormat = FXCodec_Cmyk; + break; + } + GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode( + const RetainPtr& pDIBitmap) { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_pPngContext = pPngModule->Start(this); + if (!m_pPngContext) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_offSet = 0; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppMask: + case FXDIB_8bppRgb: + m_SrcComponents = 1; + m_SrcFormat = FXCodec_8bppGray; + break; + case FXDIB_Rgb: + m_SrcComponents = 3; + m_SrcFormat = FXCodec_Rgb; + break; + case FXDIB_Rgb32: + case FXDIB_Argb: + m_SrcComponents = 4; + m_SrcFormat = FXCodec_Argb; + break; + default: { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_PARAMS; return m_status; } + } + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode( + const RetainPtr& pDIBitmap) { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_SrcFormat = FXCodec_8bppRgb; + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_FrameCur = 0; + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode( + const RetainPtr& pDIBitmap) { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); + memset(m_pDecodeBuf, 0, m_ScanlineSize); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { + if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) + return FXCODEC_STATUS_ERROR; + + switch (m_imagType) { + case FXCODEC_IMAGE_JPG: + return JpegContinueDecode(); + case FXCODEC_IMAGE_PNG: + return PngContinueDecode(); + case FXCODEC_IMAGE_GIF: + return GifContinueDecode(); + case FXCODEC_IMAGE_BMP: + return BmpContinueDecode(); case FXCODEC_IMAGE_TIF: - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; + return TifContinueDecode(); default: return FXCODEC_STATUS_ERROR; } } -FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode(IFX_Pause* pPause) { - if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) +FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegContinueDecode() { + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + // Setting jump marker before calling ReadScanLine, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERROR; return FXCODEC_STATUS_ERROR; + } - switch (m_imagType) { - case FXCODEC_IMAGE_JPG: { - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - while (true) { - bool readRes = pJpegModule->ReadScanline(m_pJpegContext, m_pDecodeBuf); - while (!readRes) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - readRes = pJpegModule->ReadScanline(m_pJpegContext, m_pDecodeBuf); - } - if (m_SrcFormat == FXCodec_Rgb) { - int src_Bpp = (m_SrcFormat & 0xff) >> 3; - RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); - } - if (m_SrcRow >= m_clipBox.bottom) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); - m_SrcRow++; - if (pPause && pPause->NeedToPauseNow()) { - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; - } - } - } - case FXCODEC_IMAGE_PNG: { - ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; - uint32_t input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - if (m_pPngContext) { - pPngModule->Finish(m_pPngContext); - } - m_pPngContext = nullptr; - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - if (m_pSrcBuf && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - FXSYS_memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_READ; - return m_status; - } - m_offSet += input_size; - bResult = - pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, nullptr); - if (!bResult) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - if (pPause && pPause->NeedToPauseNow()) { - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; - } - } - } - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - int32_t readRes = - pGifModule->LoadFrame(m_pGifContext, m_FrameCur, nullptr); - while (readRes == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!GifReadMoreData(pGifModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - if (pPause && pPause->NeedToPauseNow()) { - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; - } - readRes = pGifModule->LoadFrame(m_pGifContext, m_FrameCur, nullptr); - } - if (readRes == 1) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } + while (true) { + bool readRes = + pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); + while (!readRes) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!JpegReadMoreData(pJpegModule, error_status)) { m_pDeviceBitmap = nullptr; m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; + m_status = error_status; return m_status; } + readRes = pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); } - case FXCODEC_IMAGE_BMP: { - ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - int32_t readRes = pBmpModule->LoadImage(m_pBmpContext); - while (readRes == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!BmpReadMoreData(pBmpModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - if (pPause && pPause->NeedToPauseNow()) { - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; - } - readRes = pBmpModule->LoadImage(m_pBmpContext); - } - if (readRes == 1) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } + if (m_SrcFormat == FXCodec_Rgb) { + int src_Bpp = (m_SrcFormat & 0xff) >> 3; + RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); } - case FXCODEC_IMAGE_TIF: { - ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - if (!pTiffModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - bool ret = false; - if (m_pDeviceBitmap->GetBPP() == 32 && - m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && - m_pDeviceBitmap->GetHeight() == m_SrcHeight && - m_SrcHeight == m_sizeY && m_startX == 0 && m_startY == 0 && - m_clipBox.left == 0 && m_clipBox.top == 0 && - m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) { - ret = pTiffModule->Decode(m_pTiffContext, m_pDeviceBitmap); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - if (!ret) { - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } + if (m_SrcRow >= m_clipBox.bottom) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); + m_SrcRow++; + } +} - CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; - pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); - if (!pDIBitmap->GetBuffer()) { - delete pDIBitmap; - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - ret = pTiffModule->Decode(m_pTiffContext, pDIBitmap); - if (!ret) { - delete pDIBitmap; - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - CFX_DIBitmap* pClipBitmap = - (m_clipBox.left == 0 && m_clipBox.top == 0 && - m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) - ? pDIBitmap - : pDIBitmap->Clone(&m_clipBox).release(); - if (pDIBitmap != pClipBitmap) { - delete pDIBitmap; - } - if (!pClipBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - CFX_DIBitmap* pFormatBitmap = nullptr; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_8bppRgb); - break; - case FXDIB_8bppMask: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_8bppMask); - break; - case FXDIB_Rgb: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_Rgb); - break; - case FXDIB_Rgb32: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_Rgb32); - break; - case FXDIB_Argb: - pFormatBitmap = pClipBitmap; - break; - default: - break; - } - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - case FXDIB_8bppMask: { - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *des_line++ = FXRGB2GRAY(r, g, b); - src_line += 4; - } - } - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *des_line++ = b; - *des_line++ = g; - *des_line++ = r; - des_line += desBpp - 3; - src_line += 4; - } - } - } break; - default: - break; - } - if (pClipBitmap != pFormatBitmap) { - delete pClipBitmap; - } - if (!pFormatBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - std::unique_ptr pStrechBitmap = pFormatBitmap->StretchTo( - m_sizeX, m_sizeY, m_bInterpol ? FXDIB_INTERPOL : FXDIB_DOWNSAMPLE); - delete pFormatBitmap; - pFormatBitmap = nullptr; - if (!pStrechBitmap) { +FXCODEC_STATUS CCodec_ProgressiveDecoder::PngContinueDecode() { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + while (true) { + uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; + uint32_t input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + m_pPngContext.reset(); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + if (m_pSrcBuf && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; + } + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_READ; + return m_status; + } + m_offSet += input_size; + bResult = + pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, nullptr); + if (!bResult) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + } +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::GifContinueDecode() { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + + CFX_GifDecodeStatus readRes = + pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); + while (readRes == CFX_GifDecodeStatus::Unfinished) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!GifReadMoreData(pGifModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); + } + + if (readRes == CFX_GifDecodeStatus::Success) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpContinueDecode() { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + while (true) { + int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get()); + while (readRes == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!BmpReadMoreData(pBmpModule, error_status)) { m_pDeviceBitmap = nullptr; m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; + m_status = error_status; return m_status; } - m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, - pStrechBitmap.get(), 0, 0); + readRes = pBmpModule->LoadImage(m_pBmpContext.get()); + } + if (readRes == 1) { m_pDeviceBitmap = nullptr; m_pFile = nullptr; m_status = FXCODEC_STATUS_DECODE_FINISH; return m_status; } + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::TifContinueDecode() { + CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + if (!pTiffModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + bool ret = false; + if (m_pDeviceBitmap->GetBPP() == 32 && + m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && + m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY && + m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 && + m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth && + m_clipBox.bottom == m_SrcHeight) { + ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + if (!ret) { + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + + auto pDIBitmap = pdfium::MakeRetain(); + pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); + if (!pDIBitmap->GetBuffer()) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap); + if (!ret) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + RetainPtr pClipBitmap = + (m_clipBox.left == 0 && m_clipBox.top == 0 && + m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) + ? pDIBitmap + : pDIBitmap->Clone(&m_clipBox); + if (!pClipBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + RetainPtr pFormatBitmap; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_8bppRgb); + break; + case FXDIB_8bppMask: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_8bppMask); + break; + case FXDIB_Rgb: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_Rgb); + break; + case FXDIB_Rgb32: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_Rgb32); + break; + case FXDIB_Argb: + pFormatBitmap = pClipBitmap; + break; default: - return FXCODEC_STATUS_ERROR; + break; } + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + case FXDIB_8bppMask: { + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *des_line++ = FXRGB2GRAY(r, g, b); + src_line += 4; + } + } + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *des_line++ = b; + *des_line++ = g; + *des_line++ = r; + des_line += desBpp - 3; + src_line += 4; + } + } + } break; + default: + break; + } + if (!pFormatBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + RetainPtr pStrechBitmap = + pFormatBitmap->StretchTo(m_sizeX, m_sizeY, FXDIB_INTERPOL, nullptr); + pFormatBitmap = nullptr; + if (!pStrechBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, + pStrechBitmap, 0, 0); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; } std::unique_ptr diff --git a/core/fxcodec/codec/fx_codec_rle_unittest.cpp b/core/fxcodec/codec/fx_codec_rle_unittest.cpp index d90a515d450bd409ecdb10e3df493c9bf7b63fa7..7b0af908195efe0f685059e0ab72e026c2325f4e 100644 --- a/core/fxcodec/codec/fx_codec_rle_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_rle_unittest.cpp @@ -9,7 +9,6 @@ #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcodec/codec/ccodec_basicmodule.h" #include "core/fxcodec/fx_codec.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" TEST(fxcodec, RLETestBadInputs) { @@ -75,7 +74,7 @@ TEST(fxcodec, RLETestNormalInputs) { pEncoders->RunLengthEncode(src_buf_1, src_size, &dest_buf, &dest_size)); uint8_t* decoded_buf = nullptr; uint32_t decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_1[i], decoded_buf[i]) << " at " << i; @@ -89,7 +88,7 @@ TEST(fxcodec, RLETestNormalInputs) { pEncoders->RunLengthEncode(src_buf_2, src_size, &dest_buf, &dest_size)); decoded_buf = nullptr; decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_2[i], decoded_buf[i]) << " at " << i; @@ -103,7 +102,7 @@ TEST(fxcodec, RLETestNormalInputs) { pEncoders->RunLengthEncode(src_buf_3, src_size, &dest_buf, &dest_size)); decoded_buf = nullptr; decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_3[i], decoded_buf[i]) << " at " << i; @@ -144,7 +143,7 @@ TEST(fxcodec, RLETestFullLengthInputs) { pEncoders->RunLengthEncode(src_buf_1, src_size, &dest_buf, &dest_size)); uint8_t* decoded_buf = nullptr; uint32_t decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_1[i], decoded_buf[i]) << " at " << i; @@ -158,7 +157,7 @@ TEST(fxcodec, RLETestFullLengthInputs) { pEncoders->RunLengthEncode(src_buf_2, src_size, &dest_buf, &dest_size)); decoded_buf = nullptr; decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_2[i], decoded_buf[i]) << " at " << i; @@ -172,7 +171,7 @@ TEST(fxcodec, RLETestFullLengthInputs) { pEncoders->RunLengthEncode(src_buf_3, src_size, &dest_buf, &dest_size)); decoded_buf = nullptr; decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_3[i], decoded_buf[i]) << " at " << i; @@ -186,7 +185,7 @@ TEST(fxcodec, RLETestFullLengthInputs) { pEncoders->RunLengthEncode(src_buf_4, src_size, &dest_buf, &dest_size)); decoded_buf = nullptr; decoded_size = 0; - RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + RunLengthDecode(dest_buf, dest_size, &decoded_buf, &decoded_size); ASSERT_EQ(src_size, decoded_size); for (uint32_t i = 0; i < src_size; i++) EXPECT_EQ(src_buf_4[i], decoded_buf[i]) << " at " << i; diff --git a/core/fxcodec/codec/icodec_bmpmodule.h b/core/fxcodec/codec/icodec_bmpmodule.h deleted file mode 100644 index a67e20cf0211d85a176f430e6b18ac4d2c965170..0000000000000000000000000000000000000000 --- a/core/fxcodec/codec/icodec_bmpmodule.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCODEC_CODEC_ICODEC_BMPMODULE_H_ -#define CORE_FXCODEC_CODEC_ICODEC_BMPMODULE_H_ - -#include "core/fxcrt/fx_system.h" - -struct FXBMP_Context; -class CFX_DIBAttribute; - -// Virtual interface to avoid linking in a concrete implementation -// if we do not enable this codec. -class ICodec_BmpModule { - public: - class Delegate { - public: - virtual bool BmpInputImagePositionBuf(uint32_t rcd_pos) = 0; - virtual void BmpReadScanline(int32_t row_num, uint8_t* row_buf) = 0; - }; - - virtual ~ICodec_BmpModule() {} - - virtual FXBMP_Context* Start() = 0; - virtual void Finish(FXBMP_Context* pContext) = 0; - virtual uint32_t GetAvailInput(FXBMP_Context* pContext, - uint8_t** avail_buf_ptr) = 0; - virtual void Input(FXBMP_Context* pContext, - const uint8_t* src_buf, - uint32_t src_size) = 0; - virtual int32_t ReadHeader(FXBMP_Context* pContext, - int32_t* width, - int32_t* height, - bool* tb_flag, - int32_t* components, - int32_t* pal_num, - uint32_t** pal_pp, - CFX_DIBAttribute* pAttribute) = 0; - virtual int32_t LoadImage(FXBMP_Context* pContext) = 0; - - Delegate* GetDelegate() const { return m_pDelegate; } - void SetDelegate(Delegate* pDelegate) { m_pDelegate = pDelegate; } - - protected: - Delegate* m_pDelegate; -}; - -#endif // CORE_FXCODEC_CODEC_ICODEC_BMPMODULE_H_ diff --git a/core/fxcodec/codec/icodec_gifmodule.h b/core/fxcodec/codec/icodec_gifmodule.h deleted file mode 100644 index 9dc0708ebe23037f984d5c0dd2cd2a35c579e83e..0000000000000000000000000000000000000000 --- a/core/fxcodec/codec/icodec_gifmodule.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCODEC_CODEC_ICODEC_GIFMODULE_H_ -#define CORE_FXCODEC_CODEC_ICODEC_GIFMODULE_H_ - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" - -class CFX_DIBAttribute; -struct FXGIF_Context; - -// Virtual interface to avoid linking in a concrete implementation -// if we do not enable this codec. -class ICodec_GifModule { - public: - class Delegate { - public: - virtual void GifRecordCurrentPosition(uint32_t& cur_pos) = 0; - virtual uint8_t* GifAskLocalPaletteBuf(int32_t frame_num, - int32_t pal_size) = 0; - virtual bool GifInputRecordPositionBuf(uint32_t rcd_pos, - const FX_RECT& img_rc, - int32_t pal_num, - void* pal_ptr, - int32_t delay_time, - bool user_input, - int32_t trans_index, - int32_t disposal_method, - bool interlace) = 0; - virtual void GifReadScanline(int32_t row_num, uint8_t* row_buf) = 0; - }; - - virtual ~ICodec_GifModule() {} - - virtual FXGIF_Context* Start() = 0; - virtual void Finish(FXGIF_Context* pContext) = 0; - virtual uint32_t GetAvailInput(FXGIF_Context* pContext, - uint8_t** avail_buf_ptr = nullptr) = 0; - - virtual void Input(FXGIF_Context* pContext, - const uint8_t* src_buf, - uint32_t src_size) = 0; - - virtual int32_t ReadHeader(FXGIF_Context* pContext, - int* width, - int* height, - int* pal_num, - void** pal_pp, - int* bg_index, - CFX_DIBAttribute* pAttribute) = 0; - - virtual int32_t LoadFrameInfo(FXGIF_Context* pContext, int* frame_num) = 0; - virtual int32_t LoadFrame(FXGIF_Context* pContext, - int frame_num, - CFX_DIBAttribute* pAttribute) = 0; - - Delegate* GetDelegate() const { return m_pDelegate; } - void SetDelegate(Delegate* pDelegate) { m_pDelegate = pDelegate; } - - protected: - Delegate* m_pDelegate; -}; - -#endif // CORE_FXCODEC_CODEC_ICODEC_GIFMODULE_H_ diff --git a/core/fxcodec/codec/icodec_pngmodule.h b/core/fxcodec/codec/icodec_pngmodule.h deleted file mode 100644 index 63e61fe5b5d3108955f92150364219a3b7ca2b1f..0000000000000000000000000000000000000000 --- a/core/fxcodec/codec/icodec_pngmodule.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCODEC_CODEC_ICODEC_PNGMODULE_H_ -#define CORE_FXCODEC_CODEC_ICODEC_PNGMODULE_H_ - -#include "core/fxcrt/fx_system.h" - -class CFX_DIBAttribute; -struct FXPNG_Context; - -// Virtual interface to avoid linking in a concrete implementation -// if we do not enable this codec. -class ICodec_PngModule { - public: - class Delegate { - public: - virtual bool PngReadHeader(int width, - int height, - int bpc, - int pass, - int* color_type, - double* gamma) = 0; - virtual bool PngAskScanlineBuf(int line, uint8_t*& src_buf) = 0; - virtual void PngFillScanlineBufCompleted(int pass, int line) = 0; - }; - - virtual ~ICodec_PngModule() {} - - virtual FXPNG_Context* Start() = 0; - virtual void Finish(FXPNG_Context* pContext) = 0; - virtual bool Input(FXPNG_Context* pContext, - const uint8_t* src_buf, - uint32_t src_size, - CFX_DIBAttribute* pAttribute) = 0; - - Delegate* GetDelegate() const { return m_pDelegate; } - void SetDelegate(Delegate* delegate) { m_pDelegate = delegate; } - - protected: - Delegate* m_pDelegate; -}; - -#endif // CORE_FXCODEC_CODEC_ICODEC_PNGMODULE_H_ diff --git a/core/fxcodec/codec/icodec_tiffmodule.h b/core/fxcodec/codec/icodec_tiffmodule.h deleted file mode 100644 index 540d82ff639c611790568e8093f7ebf7ee605697..0000000000000000000000000000000000000000 --- a/core/fxcodec/codec/icodec_tiffmodule.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCODEC_CODEC_ICODEC_TIFFMODULE_H_ -#define CORE_FXCODEC_CODEC_ICODEC_TIFFMODULE_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_system.h" - -class CCodec_TiffContext; -class CFX_DIBAttribute; -class CFX_DIBitmap; -class IFX_SeekableReadStream; - -class ICodec_TiffModule { - public: - virtual ~ICodec_TiffModule() {} - - virtual CCodec_TiffContext* CreateDecoder( - const CFX_RetainPtr& file_ptr) = 0; - virtual bool LoadFrameInfo(CCodec_TiffContext* ctx, - int32_t frame, - int32_t* width, - int32_t* height, - int32_t* comps, - int32_t* bpc, - CFX_DIBAttribute* pAttribute) = 0; - virtual bool Decode(CCodec_TiffContext* ctx, - class CFX_DIBitmap* pDIBitmap) = 0; - virtual void DestroyDecoder(CCodec_TiffContext* ctx) = 0; -}; - -#endif // CORE_FXCODEC_CODEC_ICODEC_TIFFMODULE_H_ diff --git a/core/fxcodec/fx_codec.h b/core/fxcodec/fx_codec.h index b0b9fa1821e355a8916590f4d4a32bedd4a702a6..923eb7cb71cada4bded18129610727665ff36f16 100644 --- a/core/fxcodec/fx_codec.h +++ b/core/fxcodec/fx_codec.h @@ -9,35 +9,32 @@ #include #include +#include #include #include -#include "core/fxcodec/codec/ccodec_basicmodule.h" -#include "core/fxcodec/codec/ccodec_faxmodule.h" -#include "core/fxcodec/codec/ccodec_flatemodule.h" -#include "core/fxcodec/codec/ccodec_iccmodule.h" -#include "core/fxcodec/codec/ccodec_jbig2module.h" -#include "core/fxcodec/codec/ccodec_jpegmodule.h" -#include "core/fxcodec/codec/ccodec_jpxmodule.h" -#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" #include "core/fxcodec/fx_codec_def.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" - -#ifdef PDF_ENABLE_XFA -#include "core/fxcodec/codec/icodec_bmpmodule.h" -#include "core/fxcodec/codec/icodec_gifmodule.h" -#include "core/fxcodec/codec/icodec_pngmodule.h" -#include "core/fxcodec/codec/icodec_tiffmodule.h" -#endif // PDF_ENABLE_XFA - +#include "core/fxcrt/fx_string.h" + +class CCodec_BasicModule; +class CCodec_FaxModule; +class CCodec_FlateModule; +class CCodec_IccModule; +class CCodec_Jbig2Module; +class CCodec_JpegModule; +class CCodec_JpxModule; class CFX_DIBSource; class CJPX_Decoder; class CPDF_ColorSpace; class CPDF_StreamAcc; #ifdef PDF_ENABLE_XFA +class CCodec_BmpModule; +class CCodec_GifModule; +class CCodec_PngModule; class CCodec_ProgressiveDecoder; +class CCodec_TiffModule; class CFX_DIBAttribute { public: @@ -46,10 +43,9 @@ class CFX_DIBAttribute { int32_t m_nXDPI; int32_t m_nYDPI; - FX_FLOAT m_fAspectRatio; + float m_fAspectRatio; uint16_t m_wDPIUnit; - CFX_ByteString m_strAuthor; - uint8_t m_strTime[20]; + ByteString m_strAuthor; int32_t m_nGifLeft; int32_t m_nGifTop; uint32_t* m_pGifLocalPalette; @@ -74,22 +70,14 @@ class CCodec_ModuleMgr { #ifdef PDF_ENABLE_XFA std::unique_ptr CreateProgressiveDecoder(); - void SetBmpModule(std::unique_ptr module) { - m_pBmpModule = std::move(module); - } - void SetGifModule(std::unique_ptr module) { - m_pGifModule = std::move(module); - } - void SetPngModule(std::unique_ptr module) { - m_pPngModule = std::move(module); - } - void SetTiffModule(std::unique_ptr module) { - m_pTiffModule = std::move(module); - } - ICodec_BmpModule* GetBmpModule() const { return m_pBmpModule.get(); } - ICodec_GifModule* GetGifModule() const { return m_pGifModule.get(); } - ICodec_PngModule* GetPngModule() const { return m_pPngModule.get(); } - ICodec_TiffModule* GetTiffModule() const { return m_pTiffModule.get(); } + void SetBmpModule(std::unique_ptr module); + void SetGifModule(std::unique_ptr module); + void SetPngModule(std::unique_ptr module); + void SetTiffModule(std::unique_ptr module); + CCodec_BmpModule* GetBmpModule() const { return m_pBmpModule.get(); } + CCodec_GifModule* GetGifModule() const { return m_pGifModule.get(); } + CCodec_PngModule* GetPngModule() const { return m_pPngModule.get(); } + CCodec_TiffModule* GetTiffModule() const { return m_pTiffModule.get(); } #endif // PDF_ENABLE_XFA protected: @@ -101,10 +89,10 @@ class CCodec_ModuleMgr { std::unique_ptr m_pIccModule; #ifdef PDF_ENABLE_XFA - std::unique_ptr m_pBmpModule; - std::unique_ptr m_pGifModule; - std::unique_ptr m_pPngModule; - std::unique_ptr m_pTiffModule; + std::unique_ptr m_pBmpModule; + std::unique_ptr m_pGifModule; + std::unique_ptr m_pPngModule; + std::unique_ptr m_pTiffModule; #endif // PDF_ENABLE_XFA std::unique_ptr m_pFlateModule; @@ -112,28 +100,14 @@ class CCodec_ModuleMgr { void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels); uint32_t ComponentsForFamily(int family); -void sRGB_to_AdobeCMYK(FX_FLOAT R, - FX_FLOAT G, - FX_FLOAT B, - FX_FLOAT& c, - FX_FLOAT& m, - FX_FLOAT& y, - FX_FLOAT& k); -void AdobeCMYK_to_sRGB(FX_FLOAT c, - FX_FLOAT m, - FX_FLOAT y, - FX_FLOAT k, - FX_FLOAT& R, - FX_FLOAT& G, - FX_FLOAT& B); -void AdobeCMYK_to_sRGB1(uint8_t c, - uint8_t m, - uint8_t y, - uint8_t k, - uint8_t& R, - uint8_t& G, - uint8_t& B); -bool MD5ComputeID(const void* buf, uint32_t dwSize, uint8_t ID[16]); +std::tuple AdobeCMYK_to_sRGB(float c, + float m, + float y, + float k); +std::tuple AdobeCMYK_to_sRGB1(uint8_t c, + uint8_t m, + uint8_t y, + uint8_t k); void FaxG4Decode(const uint8_t* src_buf, uint32_t src_size, int* pbitpos, diff --git a/core/fxcodec/fx_codec_def.h b/core/fxcodec/fx_codec_def.h index fd23d78fa5933fd351446b68b795d0c0d8b6969e..3983285d6d341280d40c657d0d414233ade467cd 100644 --- a/core/fxcodec/fx_codec_def.h +++ b/core/fxcodec/fx_codec_def.h @@ -22,45 +22,7 @@ enum FXCODEC_STATUS { FXCODEC_STATUS_ERR_FORMAT, FXCODEC_STATUS_ERR_PARAMS }; -#define JP2_SPACE_INVALID -1 -#define JPX_SPACE_INVALID -1 -#define JP2_SPACE_bilevel1 0 -#define JP2_SPACE_YCbCr1 1 -#define JP2_SPACE_YCbCr2 3 -#define JP2_SPACE_YCbCr3 4 -#define JP2_SPACE_PhotoYCC 9 -#define JP2_SPACE_CMY 11 -#define JP2_SPACE_CMYK 12 -#define JP2_SPACE_YCCK 13 -#define JP2_SPACE_CIELab 14 -#define JP2_SPACE_bilevel2 15 -#define JP2_SPACE_sRGB 16 -#define JP2_SPACE_sLUM 17 -#define JP2_SPACE_sYCC 18 -#define JP2_SPACE_CIEJab 19 -#define JP2_SPACE_esRGB 20 -#define JP2_SPACE_ROMMRGB 21 -#define JP2_SPACE_YPbPr60 22 -#define JP2_SPACE_YPbPr50 23 -#define JP2_SPACE_esYCC 24 -#define JP2_SPACE_iccLUM 100 -#define JP2_SPACE_iccRGB 101 -#define Icc_INTENT_PERCEPTUAL 0 -#define Icc_INTENT_RELATIVE_COLORIMETRIC 1 -#define Icc_INTENT_SATURATION 2 -#define Icc_INTENT_ABSOLUTE_COLORIMETRIC 3 -#define Icc_FORMAT_DEFAULT 0 -#define Icc_FORMAT_SWAP (1 << 10) -#define Icc_FLAGS_DEFAULT 0x0000 -#define Icc_FLAGS_BLACKPOINTCOMPENSATION 0x2000 -#define Icc_FLAGS_NOWHITEONWHITEFIXUP 0x0004 -#define Icc_FLAGS_HIGHRESPRECALC 0x0400 -#define Icc_FLAGS_LOWRESPRECALC 0x0800 -#define Icc_FLAGS_GAMUTCHECK 0x1000 -#define Icc_FLAGS_SOFTPROOFING 0x4000 -#define Icc_PARAMTYPE_NONE 0 -#define Icc_PARAMTYPE_BUFFER 1 -#define Icc_PARAMTYPE_PARAM 2 + #ifdef PDF_ENABLE_XFA enum FXCODEC_IMAGE_TYPE { FXCODEC_IMAGE_UNKNOWN = 0, @@ -78,15 +40,5 @@ enum FXCODEC_RESUNIT { FXCODEC_RESUNIT_METER }; #endif // PDF_ENABLE_XFA -#define EXIFTAG_USHORT_RESUNIT 296 -#define EXIFTAG_FLOAT_DPIX 282 -#define EXIFTAG_FLOAT_DPIY 283 -#define EXIFTAG_USHORT_ORIENTATION 274 -#define EXIFTAG_STRING_MANUFACTURER 271 -#define EXIFTAG_STRING_MODULE 272 -#define EXIFTAG_STRING_SOFTWARE 305 -#define EXIFTAG_STRING_IAMGEDESCRIPTION 270 -#define EXIFTAG_STRING_DATETIME 306 -#define EXIFTAG_STRING_COPYRIGHT 33432 #endif // CORE_FXCODEC_FX_CODEC_DEF_H_ diff --git a/core/fxcodec/gif/cfx_gif.cpp b/core/fxcodec/gif/cfx_gif.cpp new file mode 100644 index 0000000000000000000000000000000000000000..985a687906c19d093f82488953d4ad0a7c73a79b --- /dev/null +++ b/core/fxcodec/gif/cfx_gif.cpp @@ -0,0 +1,23 @@ +// 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 "core/fxcodec/gif/cfx_gif.h" + +const char* kGifSignature87 = "GIF87a"; +const char* kGifSignature89 = "GIF89a"; + +static_assert(sizeof(CFX_CFX_GifImageInfo) == 9, + "CFX_CFX_GifImageInfo should have a size of 9"); +static_assert(sizeof(CFX_GifPalette) == 3, + "CFX_GifPalette should have a size of 3"); +static_assert(sizeof(CFX_GifPlainTextExtension) == 13, + "CFX_GifPlainTextExtension should have a size of 13"); +static_assert(sizeof(CFX_GifGraphicControlExtension) == 5, + "CFX_GifGraphicControlExtension should have a size of 5"); +static_assert(sizeof(CFX_GifHeader) == 6, + "CFX_GifHeader should have a size of 6"); +static_assert(sizeof(CFX_GifLocalScreenDescriptor) == 7, + "CFX_GifLocalScreenDescriptor should have a size of 7"); diff --git a/core/fxcodec/gif/cfx_gif.h b/core/fxcodec/gif/cfx_gif.h new file mode 100644 index 0000000000000000000000000000000000000000..ab8278ecd2f250936ba17e4ea40039a7a991f9fb --- /dev/null +++ b/core/fxcodec/gif/cfx_gif.h @@ -0,0 +1,127 @@ +// 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 CORE_FXCODEC_GIF_CFX_GIF_H_ +#define CORE_FXCODEC_GIF_CFX_GIF_H_ + +#include +#include + +class CFX_GifContext; + +extern const char* kGifSignature87; +extern const char* kGifSignature89; + +#define GIF_SIG_EXTENSION 0x21 +#define GIF_SIG_IMAGE 0x2C +#define GIF_SIG_TRAILER 0x3B +#define GIF_BLOCK_GCE 0xF9 +#define GIF_BLOCK_PTE 0x01 +#define GIF_BLOCK_CE 0xFE +#define GIF_BLOCK_TERMINAL 0x00 +#define GIF_MAX_LZW_EXP 12 +#define GIF_MAX_LZW_CODE 4096 +#define GIF_DATA_BLOCK 255 +#define GIF_D_STATUS_SIG 0x01 +#define GIF_D_STATUS_TAIL 0x02 +#define GIF_D_STATUS_EXT 0x03 +#define GIF_D_STATUS_EXT_CE 0x05 +#define GIF_D_STATUS_EXT_GCE 0x06 +#define GIF_D_STATUS_EXT_PTE 0x07 +#define GIF_D_STATUS_EXT_UNE 0x08 +#define GIF_D_STATUS_IMG_INFO 0x09 +#define GIF_D_STATUS_IMG_DATA 0x0A + +#pragma pack(1) +typedef struct { + uint8_t pal_bits : 3; + uint8_t sort_flag : 1; + uint8_t color_resolution : 3; + uint8_t global_pal : 1; +} CFX_GifGlobalFlags; + +typedef struct { + uint8_t pal_bits : 3; + uint8_t reserved : 2; + uint8_t sort_flag : 1; + uint8_t interlace : 1; + uint8_t local_pal : 1; +} CFX_GifLocalFlags; + +typedef struct { char signature[6]; } CFX_GifHeader; + +typedef struct { + uint16_t width; + uint16_t height; + CFX_GifGlobalFlags global_flags; + uint8_t bc_index; + uint8_t pixel_aspect; +} CFX_GifLocalScreenDescriptor; + +typedef struct { + uint16_t left; + uint16_t top; + uint16_t width; + uint16_t height; + CFX_GifLocalFlags local_flags; +} CFX_CFX_GifImageInfo; + +typedef struct { + uint8_t transparency : 1; + uint8_t user_input : 1; + uint8_t disposal_method : 3; + uint8_t reserved : 3; +} CFX_GifControlExtensionFlags; + +typedef struct { + uint8_t block_size; + CFX_GifControlExtensionFlags gce_flags; + uint16_t delay_time; + uint8_t trans_index; +} CFX_GifGraphicControlExtension; + +typedef struct { + uint8_t block_size; + uint16_t grid_left; + uint16_t grid_top; + uint16_t grid_width; + uint16_t grid_height; + + uint8_t char_width; + uint8_t char_height; + + uint8_t fc_index; + uint8_t bc_index; +} CFX_GifPlainTextExtension; + +typedef struct { + uint8_t block_size; + uint8_t app_identify[8]; + uint8_t app_authentication[3]; +} GifApplicationExtension; + +typedef struct { uint8_t r, g, b; } CFX_GifPalette; +#pragma pack() + +enum class CFX_GifDecodeStatus { + Error, + Success, + Unfinished, + InsufficientDestSize, // Only used internally by CGifLZWDecoder::Decode() +}; + +typedef struct { + std::unique_ptr image_GCE; + std::vector local_palettes; + std::vector row_buffer; + CFX_CFX_GifImageInfo image_info; + uint8_t local_pallette_exp; + uint8_t code_exp; + uint32_t data_pos; + int32_t row_num; +} CFX_GifImage; + +#endif // CORE_FXCODEC_GIF_CFX_GIF_H_ diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6159e56c13d2e88b642b80bc815ed98c776b3f31 --- /dev/null +++ b/core/fxcodec/gif/cfx_gifcontext.cpp @@ -0,0 +1,572 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcodec/gif/cfx_gifcontext.h" + +#include +#include + +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#include "core/fxcodec/gif/cfx_gif.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; + +} // namespace + +CFX_GifContext::CFX_GifContext(CCodec_GifModule* gif_module, + CCodec_GifModule::Delegate* delegate) + : gif_module_(gif_module), + delegate_(delegate), + global_pal_exp_(0), + img_row_offset_(0), + img_row_avail_size_(0), + avail_in_(0), + decode_status_(GIF_D_STATUS_SIG), + skip_size_(0), + next_in_(nullptr), + width_(0), + height_(0), + bc_index_(0), + pixel_aspect_(0), + global_sort_flag_(0), + global_color_resolution_(0), + img_pass_num_(0) {} + +CFX_GifContext::~CFX_GifContext() {} + +void CFX_GifContext::RecordCurrentPosition(uint32_t* cur_pos) { + delegate_->GifRecordCurrentPosition(*cur_pos); +} + +void CFX_GifContext::ReadScanline(int32_t row_num, uint8_t* row_buf) { + delegate_->GifReadScanline(row_num, row_buf); +} + +bool CFX_GifContext::GetRecordPosition(uint32_t cur_pos, + int32_t left, + int32_t top, + int32_t width, + int32_t height, + int32_t pal_num, + CFX_GifPalette* pal, + int32_t delay_time, + bool user_input, + int32_t trans_index, + int32_t disposal_method, + bool interlace) { + return delegate_->GifInputRecordPositionBuf( + cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal, + delay_time, user_input, trans_index, disposal_method, interlace); +} + +CFX_GifDecodeStatus CFX_GifContext::ReadHeader() { + CFX_GifDecodeStatus status = ReadGifSignature(); + if (status != CFX_GifDecodeStatus::Success) + return status; + return ReadLogicalScreenDescriptor(); +} + +CFX_GifDecodeStatus CFX_GifContext::GetFrame() { + CFX_GifDecodeStatus ret = CFX_GifDecodeStatus::Success; + while (true) { + switch (decode_status_) { + case GIF_D_STATUS_TAIL: + return CFX_GifDecodeStatus::Success; + case GIF_D_STATUS_SIG: { + uint8_t* signature = nullptr; + if (!ReadData(&signature, 1)) + return CFX_GifDecodeStatus::Unfinished; + + switch (*signature) { + case GIF_SIG_EXTENSION: + SaveDecodingStatus(GIF_D_STATUS_EXT); + continue; + case GIF_SIG_IMAGE: + SaveDecodingStatus(GIF_D_STATUS_IMG_INFO); + continue; + case GIF_SIG_TRAILER: + SaveDecodingStatus(GIF_D_STATUS_TAIL); + return CFX_GifDecodeStatus::Success; + default: + if (avail_in_) { + // The Gif File has non_standard Tag! + SaveDecodingStatus(GIF_D_STATUS_SIG); + continue; + } + // The Gif File Doesn't have Trailer Tag! + return CFX_GifDecodeStatus::Success; + } + } + case GIF_D_STATUS_EXT: { + uint8_t* extension = nullptr; + if (!ReadData(&extension, 1)) + return CFX_GifDecodeStatus::Unfinished; + + switch (*extension) { + case GIF_BLOCK_CE: + SaveDecodingStatus(GIF_D_STATUS_EXT_CE); + continue; + case GIF_BLOCK_GCE: + SaveDecodingStatus(GIF_D_STATUS_EXT_GCE); + continue; + case GIF_BLOCK_PTE: + SaveDecodingStatus(GIF_D_STATUS_EXT_PTE); + continue; + default: { + int32_t status = GIF_D_STATUS_EXT_UNE; + if (*extension == GIF_BLOCK_PTE) { + status = GIF_D_STATUS_EXT_PTE; + } + SaveDecodingStatus(status); + continue; + } + } + } + case GIF_D_STATUS_IMG_INFO: { + ret = DecodeImageInfo(); + if (ret != CFX_GifDecodeStatus::Success) + return ret; + + continue; + } + case GIF_D_STATUS_IMG_DATA: { + uint8_t* img_data_size = nullptr; + uint8_t* img_data = nullptr; + uint32_t skip_size_org = skip_size_; + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + while (*img_data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&img_data, *img_data_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + skip_size_org = skip_size_; + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + } + SaveDecodingStatus(GIF_D_STATUS_SIG); + continue; + } + default: { + ret = DecodeExtension(); + if (ret != CFX_GifDecodeStatus::Success) + return ret; + break; + } + } + } + return CFX_GifDecodeStatus::Success; +} + +CFX_GifDecodeStatus CFX_GifContext::LoadFrame(int32_t frame_num) { + if (!pdfium::IndexInBounds(images_, frame_num)) + return CFX_GifDecodeStatus::Error; + + uint8_t* img_data_size = nullptr; + uint8_t* img_data = nullptr; + uint32_t skip_size_org = skip_size_; + CFX_GifImage* gif_image = images_[static_cast(frame_num)].get(); + if (gif_image->image_info.height == 0) + return CFX_GifDecodeStatus::Error; + + uint32_t gif_img_row_bytes = gif_image->image_info.width; + if (gif_img_row_bytes == 0) + return CFX_GifDecodeStatus::Error; + + if (decode_status_ == GIF_D_STATUS_TAIL) { + gif_image->row_buffer.resize(gif_img_row_bytes); + CFX_GifGraphicControlExtension* gif_img_gce = gif_image->image_GCE.get(); + int32_t loc_pal_num = + gif_image->image_info.local_flags.local_pal + ? (2 << gif_image->image_info.local_flags.pal_bits) + : 0; + avail_in_ = 0; + CFX_GifPalette* pLocalPalette = gif_image->local_palettes.empty() + ? nullptr + : gif_image->local_palettes.data(); + if (!gif_img_gce) { + bool bRes = GetRecordPosition( + gif_image->data_pos, gif_image->image_info.left, + gif_image->image_info.top, gif_image->image_info.width, + gif_image->image_info.height, loc_pal_num, pLocalPalette, 0, 0, -1, 0, + gif_image->image_info.local_flags.interlace); + if (!bRes) { + gif_image->row_buffer.clear(); + return CFX_GifDecodeStatus::Error; + } + } else { + bool bRes = GetRecordPosition( + gif_image->data_pos, gif_image->image_info.left, + gif_image->image_info.top, gif_image->image_info.width, + gif_image->image_info.height, loc_pal_num, pLocalPalette, + static_cast(gif_image->image_GCE->delay_time), + gif_image->image_GCE->gce_flags.user_input, + gif_image->image_GCE->gce_flags.transparency + ? static_cast(gif_image->image_GCE->trans_index) + : -1, + static_cast(gif_image->image_GCE->gce_flags.disposal_method), + gif_image->image_info.local_flags.interlace); + if (!bRes) { + gif_image->row_buffer.clear(); + return CFX_GifDecodeStatus::Error; + } + } + + if (gif_image->code_exp > GIF_MAX_LZW_EXP) { + gif_image->row_buffer.clear(); + return CFX_GifDecodeStatus::Error; + } + + img_row_offset_ = 0; + img_row_avail_size_ = 0; + img_pass_num_ = 0; + gif_image->row_num = 0; + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + } + + if (decode_status_ == GIF_D_STATUS_IMG_DATA) { + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + if (*img_data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&img_data, *img_data_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + if (!lzw_decompressor_.get()) + lzw_decompressor_ = CFX_LZWDecompressor::Create( + !gif_image->local_palettes.empty() ? gif_image->local_pallette_exp + : global_pal_exp_, + gif_image->code_exp); + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + img_row_offset_ += img_row_avail_size_; + img_row_avail_size_ = gif_img_row_bytes - img_row_offset_; + CFX_GifDecodeStatus ret = + lzw_decompressor_.get() + ? lzw_decompressor_->Decode( + img_data, *img_data_size, + gif_image->row_buffer.data() + img_row_offset_, + &img_row_avail_size_) + : CFX_GifDecodeStatus::Error; + if (ret == CFX_GifDecodeStatus::Error) { + DecodingFailureAtTailCleanup(gif_image); + return CFX_GifDecodeStatus::Error; + } + while (ret != CFX_GifDecodeStatus::Error) { + if (ret == CFX_GifDecodeStatus::Success) { + ReadScanline(gif_image->row_num, gif_image->row_buffer.data()); + gif_image->row_buffer.clear(); + SaveDecodingStatus(GIF_D_STATUS_TAIL); + return CFX_GifDecodeStatus::Success; + } + if (ret == CFX_GifDecodeStatus::Unfinished) { + skip_size_org = skip_size_; + if (!ReadData(&img_data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + if (*img_data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&img_data, *img_data_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + if (!lzw_decompressor_.get()) + lzw_decompressor_ = CFX_LZWDecompressor::Create( + !gif_image->local_palettes.empty() + ? gif_image->local_pallette_exp + : global_pal_exp_, + gif_image->code_exp); + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + img_row_offset_ += img_row_avail_size_; + img_row_avail_size_ = gif_img_row_bytes - img_row_offset_; + ret = lzw_decompressor_.get() + ? lzw_decompressor_->Decode( + img_data, *img_data_size, + gif_image->row_buffer.data() + img_row_offset_, + &img_row_avail_size_) + : CFX_GifDecodeStatus::Error; + } + } + if (ret == CFX_GifDecodeStatus::InsufficientDestSize) { + if (gif_image->image_info.local_flags.interlace) { + ReadScanline(gif_image->row_num, gif_image->row_buffer.data()); + gif_image->row_num += s_gif_interlace_step[img_pass_num_]; + if (gif_image->row_num >= + static_cast(gif_image->image_info.height)) { + img_pass_num_++; + if (img_pass_num_ == FX_ArraySize(s_gif_interlace_step)) { + DecodingFailureAtTailCleanup(gif_image); + return CFX_GifDecodeStatus::Error; + } + gif_image->row_num = s_gif_interlace_step[img_pass_num_] / 2; + } + } else { + ReadScanline(gif_image->row_num++, gif_image->row_buffer.data()); + } + img_row_offset_ = 0; + img_row_avail_size_ = gif_img_row_bytes; + ret = lzw_decompressor_.get() + ? lzw_decompressor_->Decode( + img_data, *img_data_size, + gif_image->row_buffer.data() + img_row_offset_, + &img_row_avail_size_) + : CFX_GifDecodeStatus::Error; + } + if (ret == CFX_GifDecodeStatus::Error) { + DecodingFailureAtTailCleanup(gif_image); + return CFX_GifDecodeStatus::Error; + } + } + } + SaveDecodingStatus(GIF_D_STATUS_TAIL); + } + return CFX_GifDecodeStatus::Error; +} + +void CFX_GifContext::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) { + next_in_ = src_buf; + avail_in_ = src_size; + skip_size_ = 0; +} + +uint32_t CFX_GifContext::GetAvailInput(uint8_t** avail_buf) const { + if (avail_buf) { + *avail_buf = nullptr; + if (avail_in_ > 0) + *avail_buf = next_in_; + } + return avail_in_; +} + +uint8_t* CFX_GifContext::ReadData(uint8_t** des_buf_pp, uint32_t data_size) { + if (!next_in_) + return nullptr; + if (avail_in_ <= skip_size_) + return nullptr; + if (!des_buf_pp) + return nullptr; + if (data_size == 0) + return nullptr; + if (avail_in_ - skip_size_ < data_size) + return nullptr; + + *des_buf_pp = next_in_ + skip_size_; + skip_size_ += data_size; + return *des_buf_pp; +} + +CFX_GifDecodeStatus CFX_GifContext::ReadGifSignature() { + CFX_GifHeader* header = nullptr; + uint32_t skip_size_org = skip_size_; + if (!ReadData(reinterpret_cast(&header), 6)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + if (strncmp(header->signature, kGifSignature87, 6) != 0 && + strncmp(header->signature, kGifSignature89, 6) != 0) + return CFX_GifDecodeStatus::Error; + + return CFX_GifDecodeStatus::Success; +} + +CFX_GifDecodeStatus CFX_GifContext::ReadLogicalScreenDescriptor() { + CFX_GifLocalScreenDescriptor* lsd = nullptr; + uint32_t skip_size_org = skip_size_; + if (!ReadData(reinterpret_cast(&lsd), 7)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + if (lsd->global_flags.global_pal) { + uint32_t palette_count = unsigned(2 << lsd->global_flags.pal_bits); + if (lsd->bc_index >= palette_count) + return CFX_GifDecodeStatus::Error; + bc_index_ = lsd->bc_index; + + uint32_t palette_size = palette_count * 3u; + uint8_t* palette = nullptr; + if (!ReadData(&palette, palette_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + global_pal_exp_ = lsd->global_flags.pal_bits; + global_sort_flag_ = lsd->global_flags.sort_flag; + global_color_resolution_ = lsd->global_flags.color_resolution; + global_palette_.resize(palette_count); + memcpy(global_palette_.data(), palette, palette_size); + } + + width_ = static_cast( + FXWORD_GET_LSBFIRST(reinterpret_cast(&lsd->width))); + height_ = static_cast( + FXWORD_GET_LSBFIRST(reinterpret_cast(&lsd->height))); + + pixel_aspect_ = lsd->pixel_aspect; + return CFX_GifDecodeStatus::Success; +} + +void CFX_GifContext::SaveDecodingStatus(int32_t status) { + decode_status_ = status; + next_in_ += skip_size_; + avail_in_ -= skip_size_; + skip_size_ = 0; +} + +CFX_GifDecodeStatus CFX_GifContext::DecodeExtension() { + uint8_t* data_size = nullptr; + uint8_t* data_buf = nullptr; + uint32_t skip_size_org = skip_size_; + switch (decode_status_) { + case GIF_D_STATUS_EXT_CE: { + if (!ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + cmt_data_.clear(); + while (*data_size != GIF_BLOCK_TERMINAL) { + uint8_t block_size = *data_size; + if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + cmt_data_ += ByteString(data_buf, block_size); + } + break; + } + case GIF_D_STATUS_EXT_PTE: { + CFX_GifPlainTextExtension* gif_pte = nullptr; + if (!ReadData(reinterpret_cast(&gif_pte), 13)) + return CFX_GifDecodeStatus::Unfinished; + + graphic_control_extension_ = nullptr; + if (!ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + while (*data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + } + break; + } + case GIF_D_STATUS_EXT_GCE: { + CFX_GifGraphicControlExtension* gif_gce = nullptr; + if (!ReadData(reinterpret_cast(&gif_gce), 6)) + return CFX_GifDecodeStatus::Unfinished; + + if (!graphic_control_extension_.get()) + graphic_control_extension_ = + pdfium::MakeUnique(); + graphic_control_extension_->block_size = gif_gce->block_size; + graphic_control_extension_->gce_flags = gif_gce->gce_flags; + graphic_control_extension_->delay_time = + FXWORD_GET_LSBFIRST(reinterpret_cast(&gif_gce->delay_time)); + graphic_control_extension_->trans_index = gif_gce->trans_index; + break; + } + default: { + if (decode_status_ == GIF_D_STATUS_EXT_PTE) + graphic_control_extension_ = nullptr; + if (!ReadData(&data_size, 1)) + return CFX_GifDecodeStatus::Unfinished; + + while (*data_size != GIF_BLOCK_TERMINAL) { + if (!ReadData(&data_buf, *data_size) || !ReadData(&data_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + } + } + } + SaveDecodingStatus(GIF_D_STATUS_SIG); + return CFX_GifDecodeStatus::Success; +} + +CFX_GifDecodeStatus CFX_GifContext::DecodeImageInfo() { + if (width_ <= 0 || height_ <= 0) + return CFX_GifDecodeStatus::Error; + + uint32_t skip_size_org = skip_size_; + CFX_CFX_GifImageInfo* img_info = nullptr; + if (!ReadData(reinterpret_cast(&img_info), 9)) + return CFX_GifDecodeStatus::Unfinished; + + auto gif_image = pdfium::MakeUnique(); + gif_image->image_info.left = + FXWORD_GET_LSBFIRST(reinterpret_cast(&img_info->left)); + gif_image->image_info.top = + FXWORD_GET_LSBFIRST(reinterpret_cast(&img_info->top)); + gif_image->image_info.width = + FXWORD_GET_LSBFIRST(reinterpret_cast(&img_info->width)); + gif_image->image_info.height = + FXWORD_GET_LSBFIRST(reinterpret_cast(&img_info->height)); + gif_image->image_info.local_flags = img_info->local_flags; + if (gif_image->image_info.left + gif_image->image_info.width > width_ || + gif_image->image_info.top + gif_image->image_info.height > height_) + return CFX_GifDecodeStatus::Error; + + CFX_GifLocalFlags* gif_img_info_lf = &img_info->local_flags; + if (gif_img_info_lf->local_pal) { + gif_image->local_pallette_exp = gif_img_info_lf->pal_bits; + uint32_t loc_pal_size = unsigned(2 << gif_img_info_lf->pal_bits) * 3u; + uint8_t* loc_pal = nullptr; + if (!ReadData(&loc_pal, loc_pal_size)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + gif_image->local_palettes = std::vector(loc_pal_size / 3); + std::copy(loc_pal, loc_pal + loc_pal_size, + reinterpret_cast(gif_image->local_palettes.data())); + } + + uint8_t* code_size = nullptr; + if (!ReadData(&code_size, 1)) { + skip_size_ = skip_size_org; + return CFX_GifDecodeStatus::Unfinished; + } + + gif_image->code_exp = *code_size; + RecordCurrentPosition(&gif_image->data_pos); + gif_image->data_pos += skip_size_; + gif_image->image_GCE = nullptr; + if (graphic_control_extension_.get()) { + if (graphic_control_extension_->gce_flags.transparency) { + // Need to test that the color that is going to be transparent is actually + // in the palette being used. + if (graphic_control_extension_->trans_index >= + 2 << (gif_image->local_palettes.empty() + ? global_pal_exp_ + : gif_image->local_pallette_exp)) + return CFX_GifDecodeStatus::Error; + } + gif_image->image_GCE = std::move(graphic_control_extension_); + graphic_control_extension_ = nullptr; + } + + images_.push_back(std::move(gif_image)); + SaveDecodingStatus(GIF_D_STATUS_IMG_DATA); + return CFX_GifDecodeStatus::Success; +} + +void CFX_GifContext::DecodingFailureAtTailCleanup(CFX_GifImage* gif_image) { + gif_image->row_buffer.clear(); + SaveDecodingStatus(GIF_D_STATUS_TAIL); +} diff --git a/core/fxcodec/gif/cfx_gifcontext.h b/core/fxcodec/gif/cfx_gifcontext.h new file mode 100644 index 0000000000000000000000000000000000000000..3a367bd3618aba27ebd1afc7c8dec51e0c36c0be --- /dev/null +++ b/core/fxcodec/gif/cfx_gifcontext.h @@ -0,0 +1,80 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCODEC_GIF_CFX_GIFCONTEXT_H_ +#define CORE_FXCODEC_GIF_CFX_GIFCONTEXT_H_ + +#include +#include + +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#include "core/fxcodec/gif/cfx_gif.h" +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" + +class CFX_GifContext : public CCodec_GifModule::Context { + public: + CFX_GifContext(CCodec_GifModule* gif_module, + CCodec_GifModule::Delegate* delegate); + ~CFX_GifContext() override; + + void RecordCurrentPosition(uint32_t* cur_pos); + void ReadScanline(int32_t row_num, uint8_t* row_buf); + bool GetRecordPosition(uint32_t cur_pos, + int32_t left, + int32_t top, + int32_t width, + int32_t height, + int32_t pal_num, + CFX_GifPalette* pal, + int32_t delay_time, + bool user_input, + int32_t trans_index, + int32_t disposal_method, + bool interlace); + CFX_GifDecodeStatus ReadHeader(); + CFX_GifDecodeStatus GetFrame(); + CFX_GifDecodeStatus LoadFrame(int32_t frame_num); + void SetInputBuffer(uint8_t* src_buf, uint32_t src_size); + uint32_t GetAvailInput(uint8_t** avail_buf) const; + size_t GetFrameNum() const { return images_.size(); } + + UnownedPtr gif_module_; + UnownedPtr delegate_; + std::vector global_palette_; + uint8_t global_pal_exp_; + uint32_t img_row_offset_; + uint32_t img_row_avail_size_; + uint32_t avail_in_; + int32_t decode_status_; + uint32_t skip_size_; + ByteString cmt_data_; + std::unique_ptr graphic_control_extension_; + uint8_t* next_in_; + std::vector> images_; + std::unique_ptr lzw_decompressor_; + int width_; + int height_; + uint8_t bc_index_; + uint8_t pixel_aspect_; + uint8_t global_sort_flag_; + uint8_t global_color_resolution_; + uint8_t img_pass_num_; + + protected: + uint8_t* ReadData(uint8_t** des_buf_pp, uint32_t data_size); + CFX_GifDecodeStatus ReadGifSignature(); + CFX_GifDecodeStatus ReadLogicalScreenDescriptor(); + + private: + void SaveDecodingStatus(int32_t status); + CFX_GifDecodeStatus DecodeExtension(); + CFX_GifDecodeStatus DecodeImageInfo(); + void DecodingFailureAtTailCleanup(CFX_GifImage* gif_image); +}; + +#endif // CORE_FXCODEC_GIF_CFX_GIFCONTEXT_H_ diff --git a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5d3ac90c7a62ea9b70a502a548eec18c51fa309 --- /dev/null +++ b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp @@ -0,0 +1,315 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcodec/gif/cfx_gifcontext.h" + +#include "core/fxcrt/unowned_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CFX_GifContextForTest : public CFX_GifContext { + public: + CFX_GifContextForTest(CCodec_GifModule* gif_module, + CCodec_GifModule::Delegate* delegate) + : CFX_GifContext(gif_module, delegate) {} + ~CFX_GifContextForTest() override {} + + using CFX_GifContext::ReadData; + using CFX_GifContext::ReadGifSignature; + using CFX_GifContext::ReadLogicalScreenDescriptor; +}; + +TEST(CFX_GifContext, SetInputBuffer) { + CFX_GifContextForTest context(nullptr, nullptr); + + context.SetInputBuffer(nullptr, 0); + EXPECT_EQ(nullptr, context.next_in_); + EXPECT_EQ(0u, context.avail_in_); + EXPECT_EQ(0u, context.skip_size_); + + context.SetInputBuffer(nullptr, 100); + EXPECT_EQ(nullptr, context.next_in_); + EXPECT_EQ(100u, context.avail_in_); + EXPECT_EQ(0u, context.skip_size_); + + uint8_t buffer[] = {0x00, 0x01, 0x02}; + context.SetInputBuffer(buffer, 0); + EXPECT_EQ(buffer, context.next_in_); + EXPECT_EQ(0u, context.avail_in_); + EXPECT_EQ(0u, context.skip_size_); + + context.SetInputBuffer(buffer, 3); + EXPECT_EQ(buffer, context.next_in_); + EXPECT_EQ(3u, context.avail_in_); + EXPECT_EQ(0u, context.skip_size_); + + context.SetInputBuffer(buffer, 100); + EXPECT_EQ(buffer, context.next_in_); + EXPECT_EQ(100u, context.avail_in_); + EXPECT_EQ(0u, context.skip_size_); +} + +TEST(CFX_GifContext, ReadData) { + CFX_GifContextForTest context(nullptr, nullptr); + + context.SetInputBuffer(nullptr, 0); + EXPECT_EQ(nullptr, context.ReadData(nullptr, 0)); + EXPECT_EQ(nullptr, context.ReadData(nullptr, 10)); + + uint8_t* dest_buffer = nullptr; + EXPECT_EQ(nullptr, + context.ReadData(reinterpret_cast(&dest_buffer), 0)); + EXPECT_EQ(nullptr, + context.ReadData(reinterpret_cast(&dest_buffer), 10)); + + uint8_t src_buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09}; + context.SetInputBuffer(src_buffer, 0); + EXPECT_EQ(nullptr, + context.ReadData(reinterpret_cast(&dest_buffer), 10)); + EXPECT_EQ(reinterpret_cast(src_buffer), context.next_in_); + EXPECT_EQ(0u, context.avail_in_); + EXPECT_EQ(0u, context.skip_size_); + + dest_buffer = nullptr; + context.SetInputBuffer(src_buffer, 10); + EXPECT_EQ(src_buffer, + context.ReadData(reinterpret_cast(&dest_buffer), 10)); + EXPECT_EQ(reinterpret_cast(src_buffer), dest_buffer); + EXPECT_EQ(src_buffer, context.next_in_); + EXPECT_EQ(10u, context.avail_in_); + EXPECT_EQ(10u, context.skip_size_); + + dest_buffer = nullptr; + context.SetInputBuffer(src_buffer, 10); + EXPECT_EQ(src_buffer, + context.ReadData(reinterpret_cast(&dest_buffer), 5)); + EXPECT_EQ(reinterpret_cast(src_buffer), dest_buffer); + EXPECT_EQ(src_buffer, context.next_in_); + EXPECT_EQ(10u, context.avail_in_); + EXPECT_EQ(5u, context.skip_size_); + + dest_buffer = nullptr; + EXPECT_EQ(src_buffer + 5, + context.ReadData(reinterpret_cast(&dest_buffer), 5)); + EXPECT_EQ(reinterpret_cast(src_buffer + 5), dest_buffer); + EXPECT_EQ(src_buffer, context.next_in_); + EXPECT_EQ(10u, context.avail_in_); + EXPECT_EQ(10u, context.skip_size_); + + dest_buffer = nullptr; + EXPECT_EQ(nullptr, + context.ReadData(reinterpret_cast(&dest_buffer), 5)); + EXPECT_EQ(nullptr, dest_buffer); + EXPECT_EQ(src_buffer, context.next_in_); + EXPECT_EQ(10u, context.avail_in_); + EXPECT_EQ(10u, context.skip_size_); +} + +TEST(CFX_GifContext, ReadGifSignature) { + CFX_GifContextForTest context(nullptr, nullptr); + + { + uint8_t data[1]; + context.SetInputBuffer(data, 0); + EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature()); + EXPECT_EQ(0u, context.skip_size_); + } + // Make sure testing the entire signature + { + uint8_t data[] = {'G', 'I', 'F'}; + context.SetInputBuffer(data, sizeof(data)); + EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature()); + EXPECT_EQ(0u, context.skip_size_); + } + { + uint8_t data[] = {'N', 'O', 'T', 'G', 'I', 'F'}; + context.SetInputBuffer(data, sizeof(data)); + EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature()); + EXPECT_EQ(6u, context.skip_size_); + } + // Make sure not matching GIF8*a + { + uint8_t data[] = {'G', 'I', 'F', '8', '0', 'a'}; + context.SetInputBuffer(data, sizeof(data)); + EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature()); + EXPECT_EQ(6u, context.skip_size_); + } + // Make sure not matching GIF**a + { + uint8_t data[] = {'G', 'I', 'F', '9', '2', 'a'}; + context.SetInputBuffer(data, sizeof(data)); + EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature()); + EXPECT_EQ(6u, context.skip_size_); + } + // One valid signature + { + uint8_t data[] = {'G', 'I', 'F', '8', '7', 'a'}; + context.SetInputBuffer(data, sizeof(data)); + EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature()); + EXPECT_EQ(6u, context.skip_size_); + } + // The other valid signature + { + uint8_t data[] = {'G', 'I', 'F', '8', '9', 'a'}; + context.SetInputBuffer(data, sizeof(data)); + EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature()); + EXPECT_EQ(6u, context.skip_size_); + } +} + +TEST(CFX_GifContext, ReadLocalScreenDescriptor) { + CFX_GifContextForTest context(nullptr, nullptr); + { + uint8_t data[1]; + context.SetInputBuffer(data, 0); + EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, + context.ReadLogicalScreenDescriptor()); + } + // LSD with all the values zero'd + { + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)]; + memset(&lsd, 0, sizeof(CFX_GifLocalScreenDescriptor)); + context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor)); + + EXPECT_EQ(CFX_GifDecodeStatus::Success, + context.ReadLogicalScreenDescriptor()); + + EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_); + EXPECT_EQ(0, context.width_); + EXPECT_EQ(0, context.height_); + EXPECT_EQ(0u, context.bc_index_); + EXPECT_EQ(0u, context.pixel_aspect_); + } + // LSD with no global palette + { + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)] = {0x0A, 0x00, 0x00, 0x0F, + 0x00, 0x01, 0x02}; + context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor)); + + EXPECT_EQ(CFX_GifDecodeStatus::Success, + context.ReadLogicalScreenDescriptor()); + + EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_); + EXPECT_EQ(0x000A, context.width_); + EXPECT_EQ(0x0F00, context.height_); + EXPECT_EQ(0u, context.bc_index_); // bc_index_ is 0 if no global palette + EXPECT_EQ(2u, context.pixel_aspect_); + } + // LSD with global palette bit set, but no global palette + { + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)] = {0x0A, 0x00, 0x00, 0x0F, + 0x80, 0x01, 0x02}; + context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor)); + + EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, + context.ReadLogicalScreenDescriptor()); + + EXPECT_EQ(0u, context.skip_size_); + } + // LSD with global palette + { + struct { + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)]; + uint8_t palette[4 * sizeof(CFX_GifPalette)]; + } data = {{0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02}, + {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}}; + context.SetInputBuffer(reinterpret_cast(&data), sizeof(data)); + + EXPECT_EQ(CFX_GifDecodeStatus::Success, + context.ReadLogicalScreenDescriptor()); + + EXPECT_EQ(sizeof(data), context.skip_size_); + EXPECT_EQ(0x000A, context.width_); + EXPECT_EQ(0x0F00, context.height_); + EXPECT_EQ(1u, context.bc_index_); + EXPECT_EQ(2u, context.pixel_aspect_); + + EXPECT_EQ(1u, context.global_pal_exp_); + EXPECT_EQ(1, context.global_sort_flag_); + EXPECT_EQ(2, context.global_color_resolution_); + EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(), + sizeof(data.palette))); + } +} + +TEST(CFX_GifContext, ReadHeader) { + CFX_GifContextForTest context(nullptr, nullptr); + // Bad signature + { + struct { + uint8_t signature[6]; + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)]; + } data = {{'N', 'O', 'T', 'G', 'I', 'F'}, + {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}}; + context.SetInputBuffer(reinterpret_cast(&data), sizeof(data)); + + EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadHeader()); + + EXPECT_EQ(sizeof(data.signature), context.skip_size_); + } + // Short after signature + { + uint8_t signature[] = {'G', 'I', 'F', '8', '7', 'a'}; + context.SetInputBuffer(reinterpret_cast(&signature), + sizeof(signature)); + + EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader()); + + EXPECT_EQ(sizeof(signature), context.skip_size_); + } + // Success without global palette + { + struct { + uint8_t signature[6]; + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)]; + } data = {{'G', 'I', 'F', '8', '7', 'a'}, + {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}}; + context.SetInputBuffer(reinterpret_cast(&data), sizeof(data)); + + EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader()); + + EXPECT_EQ(sizeof(data), context.skip_size_); + EXPECT_EQ(0x000A, context.width_); + EXPECT_EQ(0x0F00, context.height_); + EXPECT_EQ(0u, context.bc_index_); // bc_index_ is 0 if no global palette + EXPECT_EQ(2u, context.pixel_aspect_); + } + // Missing Global Palette + { + struct { + uint8_t signature[6]; + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)]; + } data = {{'G', 'I', 'F', '8', '7', 'a'}, + {0x0A, 0x00, 0x00, 0x0F, 0x80, 0x01, 0x02}}; + context.SetInputBuffer(reinterpret_cast(&data), sizeof(data)); + + EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader()); + + EXPECT_EQ(sizeof(data.signature), context.skip_size_); + } + // Success with global palette + { + struct { + uint8_t signature[6]; + uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)]; + uint8_t palette[4 * sizeof(CFX_GifPalette)]; + } data = {{'G', 'I', 'F', '8', '7', 'a'}, + {0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02}, + {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}}; + context.SetInputBuffer(reinterpret_cast(&data), sizeof(data)); + + EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader()); + + EXPECT_EQ(sizeof(data), context.skip_size_); + EXPECT_EQ(0x000A, context.width_); + EXPECT_EQ(0x0F00, context.height_); + EXPECT_EQ(1u, context.bc_index_); + EXPECT_EQ(2u, context.pixel_aspect_); + EXPECT_EQ(1u, context.global_pal_exp_); + EXPECT_EQ(1, context.global_sort_flag_); + EXPECT_EQ(2, context.global_color_resolution_); + EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(), + sizeof(data.palette))); + } +} diff --git a/core/fxcodec/gif/cfx_lzwdecompressor.cpp b/core/fxcodec/gif/cfx_lzwdecompressor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ee7b5a2174a4cdd8b9c2cff1785ee65d76d5f5c --- /dev/null +++ b/core/fxcodec/gif/cfx_lzwdecompressor.cpp @@ -0,0 +1,196 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" + +#include +#include +#include + +#include "core/fxcodec/lbmp/fx_bmp.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +std::unique_ptr CFX_LZWDecompressor::Create( + uint8_t color_exp, + uint8_t code_exp) { + // color_exp generates 2^(n + 1) codes, where as the code_exp reserves 2^n. + // This is a quirk of the GIF spec. + if (code_exp > GIF_MAX_LZW_EXP || code_exp < color_exp + 1) + return nullptr; + return std::unique_ptr( + new CFX_LZWDecompressor(color_exp, code_exp)); +} + +CFX_LZWDecompressor::CFX_LZWDecompressor(uint8_t color_exp, uint8_t code_exp) + : code_size_(code_exp), + code_size_cur_(0), + code_color_end_(static_cast(1 << (color_exp + 1))), + code_clear_(static_cast(1 << code_exp)), + code_end_(static_cast((1 << code_exp) + 1)), + code_next_(0), + code_first_(0), + code_old_(0), + next_in_(nullptr), + avail_in_(0), + bits_left_(0), + code_store_(0) {} + +CFX_LZWDecompressor::~CFX_LZWDecompressor() {} + +CFX_GifDecodeStatus CFX_LZWDecompressor::Decode(uint8_t* src_buf, + uint32_t src_size, + uint8_t* des_buf, + uint32_t* des_size) { + if (!src_buf || src_size == 0 || !des_buf || !des_size) + return CFX_GifDecodeStatus::Error; + + if (*des_size == 0) + return CFX_GifDecodeStatus::InsufficientDestSize; + + next_in_ = src_buf; + avail_in_ = src_size; + + ClearTable(); + + uint32_t i = 0; + if (decompressed_next_ != 0) { + uint32_t extracted_size = ExtractData(des_buf, *des_size); + if (decompressed_next_ != 0) + return CFX_GifDecodeStatus::InsufficientDestSize; + + des_buf += extracted_size; + i += extracted_size; + } + + while (i <= *des_size && (avail_in_ > 0 || bits_left_ >= code_size_cur_)) { + if (code_size_cur_ > GIF_MAX_LZW_EXP) + return CFX_GifDecodeStatus::Error; + + if (avail_in_ > 0) { + if (bits_left_ > 31) + return CFX_GifDecodeStatus::Error; + + pdfium::base::CheckedNumeric safe_code = *next_in_++; + safe_code <<= bits_left_; + safe_code |= code_store_; + if (!safe_code.IsValid()) + return CFX_GifDecodeStatus::Error; + + code_store_ = safe_code.ValueOrDie(); + --avail_in_; + bits_left_ += 8; + } + + while (bits_left_ >= code_size_cur_) { + uint16_t code = + static_cast(code_store_) & ((1 << code_size_cur_) - 1); + code_store_ >>= code_size_cur_; + bits_left_ -= code_size_cur_; + if (code == code_clear_) { + ClearTable(); + continue; + } + if (code == code_end_) { + *des_size = i; + return CFX_GifDecodeStatus::Success; + } + + if (code_old_ != static_cast(-1)) { + if (code_next_ < GIF_MAX_LZW_CODE) { + if (code == code_next_) { + AddCode(code_old_, code_first_); + if (!DecodeString(code)) + return CFX_GifDecodeStatus::Error; + } else if (code > code_next_) { + return CFX_GifDecodeStatus::Error; + } else { + if (!DecodeString(code)) + return CFX_GifDecodeStatus::Error; + + uint8_t append_char = decompressed_[decompressed_next_ - 1]; + AddCode(code_old_, append_char); + } + } + } else { + if (!DecodeString(code)) + return CFX_GifDecodeStatus::Error; + } + + code_old_ = code; + uint32_t extracted_size = ExtractData(des_buf, *des_size - i); + if (decompressed_next_ != 0) + return CFX_GifDecodeStatus::InsufficientDestSize; + + des_buf += extracted_size; + i += extracted_size; + } + } + + if (avail_in_ != 0) + return CFX_GifDecodeStatus::Error; + + *des_size = i; + return CFX_GifDecodeStatus::Unfinished; +} + +void CFX_LZWDecompressor::ClearTable() { + code_size_cur_ = code_size_ + 1; + code_next_ = code_end_ + 1; + code_old_ = static_cast(-1); + memset(code_table_, 0, sizeof(code_table_)); + for (uint16_t i = 0; i < code_clear_; i++) + code_table_[i].suffix = static_cast(i); + decompressed_.resize(code_next_ - code_clear_ + 1); + decompressed_next_ = 0; +} + +void CFX_LZWDecompressor::AddCode(uint16_t prefix_code, uint8_t append_char) { + if (code_next_ == GIF_MAX_LZW_CODE) + return; + + code_table_[code_next_].prefix = prefix_code; + code_table_[code_next_].suffix = append_char; + if (++code_next_ < GIF_MAX_LZW_CODE) { + if (code_next_ >> code_size_cur_) + code_size_cur_++; + } +} + +bool CFX_LZWDecompressor::DecodeString(uint16_t code) { + decompressed_.resize(code_next_ - code_clear_ + 1); + decompressed_next_ = 0; + + while (code >= code_clear_ && code <= code_next_) { + if (code == code_table_[code].prefix || + decompressed_next_ >= decompressed_.size()) + return false; + + decompressed_[decompressed_next_++] = code_table_[code].suffix; + code = code_table_[code].prefix; + } + + if (code >= code_color_end_) + return false; + + decompressed_[decompressed_next_++] = static_cast(code); + code_first_ = static_cast(code); + return true; +} + +uint32_t CFX_LZWDecompressor::ExtractData(uint8_t* des_buf, uint32_t des_size) { + if (des_size == 0) + return 0; + + uint32_t copy_size = des_size <= decompressed_next_ + ? des_size + : static_cast(decompressed_next_); + std::reverse_copy(decompressed_.data() + decompressed_next_ - copy_size, + decompressed_.data() + decompressed_next_, des_buf); + decompressed_next_ -= copy_size; + return copy_size; +} diff --git a/core/fxcodec/gif/cfx_lzwdecompressor.h b/core/fxcodec/gif/cfx_lzwdecompressor.h new file mode 100644 index 0000000000000000000000000000000000000000..717c055973657f40aa5350dc65d5b637eb472c7d --- /dev/null +++ b/core/fxcodec/gif/cfx_lzwdecompressor.h @@ -0,0 +1,65 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCODEC_GIF_CFX_LZWDECOMPRESSOR_H_ +#define CORE_FXCODEC_GIF_CFX_LZWDECOMPRESSOR_H_ + +#include +#include + +#include "core/fxcodec/gif/cfx_gif.h" + +class CFX_LZWDecompressor { + public: + typedef struct { + uint16_t prefix; + uint8_t suffix; + } CodeEntry; + + // Returns nullptr on error + static std::unique_ptr Create(uint8_t color_exp, + uint8_t code_exp); + ~CFX_LZWDecompressor(); + + CFX_GifDecodeStatus Decode(uint8_t* src_buf, + uint32_t src_size, + uint8_t* des_buf, + uint32_t* des_size); + + // Used by unittests, should not be called in production code. + uint32_t ExtractDataForTest(uint8_t* des_buf, uint32_t des_size) { + return ExtractData(des_buf, des_size); + } + + std::vector* DecompressedForTest() { return &decompressed_; } + + size_t* DecompressedNextForTest() { return &decompressed_next_; } + + private: + CFX_LZWDecompressor(uint8_t color_exp, uint8_t code_exp); + void ClearTable(); + void AddCode(uint16_t prefix_code, uint8_t append_char); + bool DecodeString(uint16_t code); + uint32_t ExtractData(uint8_t* des_buf, uint32_t des_size); + + uint8_t code_size_; + uint8_t code_size_cur_; + uint16_t code_color_end_; + uint16_t code_clear_; + uint16_t code_end_; + uint16_t code_next_; + uint8_t code_first_; + std::vector decompressed_; + size_t decompressed_next_; + CodeEntry code_table_[GIF_MAX_LZW_CODE]; + uint16_t code_old_; + uint8_t* next_in_; + uint32_t avail_in_; + uint8_t bits_left_; + uint32_t code_store_; +}; + +#endif // CORE_FXCODEC_GIF_CFX_LZWDECOMPRESSOR_H_ diff --git a/core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp b/core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d0906eb102da250af8077d63eeee52559f6d171 --- /dev/null +++ b/core/fxcodec/gif/cfx_lzwdecompressor_unittest.cpp @@ -0,0 +1,217 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" + +#include "core/fxcrt/fx_memory.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(CFX_LZWDecompressor, CreateBadParams) { + EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x10, 0x02)); + EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x04, 0x0F)); + EXPECT_EQ(nullptr, CFX_LZWDecompressor::Create(0x02, 0x02)); +} + +TEST(CFX_LZWDecompressor, ExtractData) { + uint8_t palette_exp = 0x1; + uint8_t code_exp = 0x2; + auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp); + ASSERT_NE(nullptr, decompressor); + + // Check that 0 length extract does nothing + { + std::vector* decompressed = decompressor->DecompressedForTest(); + *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + *(decompressor->DecompressedNextForTest()) = decompressed->size(); + uint8_t des_buf[20]; + memset(des_buf, static_cast(-1), sizeof(des_buf)); + + EXPECT_EQ(0u, decompressor->ExtractDataForTest(des_buf, 0)); + for (size_t i = 0; i < FX_ArraySize(des_buf); ++i) + EXPECT_EQ(static_cast(-1), des_buf[i]); + + EXPECT_EQ(10u, *(decompressor->DecompressedNextForTest())); + for (size_t i = 0; i < *(decompressor->DecompressedNextForTest()); ++i) + EXPECT_EQ(i, decompressed->operator[](i)); + } + + // Check that less than decompressed size only gets the expected number + { + std::vector* decompressed = decompressor->DecompressedForTest(); + *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + *(decompressor->DecompressedNextForTest()) = decompressed->size(); + uint8_t des_buf[20]; + memset(des_buf, static_cast(-1), sizeof(des_buf)); + + EXPECT_EQ(5u, decompressor->ExtractDataForTest(des_buf, 5)); + size_t i = 0; + for (; i < 5; ++i) + EXPECT_EQ(9 - i, des_buf[i]); + for (; i < FX_ArraySize(des_buf); ++i) + EXPECT_EQ(static_cast(-1), des_buf[i]); + + EXPECT_EQ(5u, *(decompressor->DecompressedNextForTest())); + for (i = 0; i < *(decompressor->DecompressedNextForTest()); ++i) + EXPECT_EQ(i, decompressed->operator[](i)); + } + + // Check that greater than decompressed size depletes the decompressor + { + std::vector* decompressed = decompressor->DecompressedForTest(); + *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + *(decompressor->DecompressedNextForTest()) = decompressed->size(); + uint8_t des_buf[20]; + memset(des_buf, static_cast(-1), sizeof(des_buf)); + + EXPECT_EQ(10u, + decompressor->ExtractDataForTest(des_buf, FX_ArraySize(des_buf))); + size_t i = 0; + for (; i < 10; ++i) + EXPECT_EQ(9 - i, des_buf[i]); + for (; i < FX_ArraySize(des_buf); ++i) + EXPECT_EQ(static_cast(-1), des_buf[i]); + + EXPECT_EQ(0u, *(decompressor->DecompressedNextForTest())); + } +} + +TEST(CFX_LZWDecompressor, DecodeBadParams) { + uint8_t palette_exp = 0x0; + uint8_t code_exp = 0x2; + auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp); + ASSERT_NE(nullptr, decompressor); + + uint8_t image_data[10]; + uint32_t image_size = FX_ArraySize(image_data); + + uint8_t output_data[10]; + uint32_t output_size = FX_ArraySize(output_data); + + EXPECT_EQ( + CFX_GifDecodeStatus::Error, + decompressor->Decode(nullptr, image_size, output_data, &output_size)); + EXPECT_EQ(CFX_GifDecodeStatus::Error, + decompressor->Decode(image_data, 0, output_data, &output_size)); + EXPECT_EQ( + CFX_GifDecodeStatus::Error, + decompressor->Decode(image_data, image_size, nullptr, &output_size)); + EXPECT_EQ(CFX_GifDecodeStatus::Error, + decompressor->Decode(image_data, image_size, output_data, nullptr)); + + output_size = 0; + EXPECT_EQ( + CFX_GifDecodeStatus::InsufficientDestSize, + decompressor->Decode(image_data, image_size, output_data, &output_size)); +} + +TEST(CFX_LZWDecompressor, Decode1x1SingleColour) { + uint8_t palette_exp = 0x0; + uint8_t code_exp = 0x2; + auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp); + ASSERT_NE(nullptr, decompressor); + + uint8_t image_data[] = {0x44, 0x01}; + uint32_t image_size = FX_ArraySize(image_data); + + uint8_t expected_data[] = {0x00}; + uint8_t output_data[FX_ArraySize(expected_data)]; + memset(output_data, 0, sizeof(output_data)); + uint32_t output_size = FX_ArraySize(output_data); + + EXPECT_EQ( + CFX_GifDecodeStatus::Success, + decompressor->Decode(image_data, image_size, output_data, &output_size)); + + EXPECT_EQ(FX_ArraySize(output_data), output_size); + EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data))); +} + +TEST(CFX_LZWDecompressor, Decode10x10SingleColour) { + uint8_t palette_exp = 0x0; + uint8_t code_exp = 0x2; + auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp); + ASSERT_NE(nullptr, decompressor); + + uint8_t image_data[] = {0x84, 0x8F, 0xA9, 0xCB, 0xED, 0x0F, 0x63, 0x2B}; + uint32_t image_size = FX_ArraySize(image_data); + + uint8_t expected_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t output_data[FX_ArraySize(expected_data)]; + memset(output_data, 0, sizeof(output_data)); + uint32_t output_size = FX_ArraySize(output_data); + + EXPECT_EQ( + CFX_GifDecodeStatus::Success, + decompressor->Decode(image_data, image_size, output_data, &output_size)); + + EXPECT_EQ(FX_ArraySize(output_data), output_size); + EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data))); +} + +TEST(CFX_LZWDecompressor, Decode10x10MultipleColour) { + uint8_t palette_exp = 0x1; + uint8_t code_exp = 0x2; + auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp); + ASSERT_NE(nullptr, decompressor); + + uint8_t image_data[] = {0x8C, 0x2D, 0x99, 0x87, 0x2A, 0x1C, 0xDC, 0x33, + 0xA0, 0x02, 0x75, 0xEC, 0x95, 0xFA, 0xA8, 0xDE, + 0x60, 0x8C, 0x04, 0x91, 0x4C, 0x01}; + uint32_t image_size = FX_ArraySize(image_data); + + uint8_t expected_data[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01}; + + uint8_t output_data[FX_ArraySize(expected_data)]; + memset(output_data, 0, sizeof(output_data)); + uint32_t output_size = FX_ArraySize(output_data); + + EXPECT_EQ( + CFX_GifDecodeStatus::Success, + decompressor->Decode(image_data, image_size, output_data, &output_size)); + + EXPECT_EQ(FX_ArraySize(output_data), output_size); + EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data))); +} + +TEST(CFX_LZWDecompressor, HandleColourCodeOutOfPalette) { + uint8_t palette_exp = 0x2; // Image uses 10 colours, so the palette exp + // should be 3, 2^(3+1) = 16 colours. + uint8_t code_exp = 0x4; + auto decompressor = CFX_LZWDecompressor::Create(palette_exp, code_exp); + ASSERT_NE(nullptr, decompressor); + + uint8_t image_data[] = {0x30, 0xC9, 0x49, 0x81, 0xBD, 0x78, 0xE8, 0xCD, + 0x89, 0xFF, 0x60, 0x20, 0x8E, 0xE4, 0x61, 0x9E, + 0xA8, 0xA1, 0xAE, 0x2C, 0xE2, 0xBE, 0xB0, 0x20, + 0xCF, 0x74, 0x61, 0xDF, 0x78, 0x04}; + uint32_t image_size = FX_ArraySize(image_data); + + uint8_t output_data[100]; // The uncompressed data is for a 10x10 image + memset(output_data, 0, sizeof(output_data)); + uint32_t output_size = FX_ArraySize(output_data); + + EXPECT_EQ( + CFX_GifDecodeStatus::Error, + decompressor->Decode(image_data, image_size, output_data, &output_size)); +} diff --git a/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp b/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp index 0d45f57bdfb6536f38be857da0fa3503046d778e..deba72bfc53a7f64170539ff3ab304fde62463f9 100644 --- a/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp +++ b/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp @@ -7,7 +7,7 @@ #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h" #include "core/fxcodec/jbig2/JBig2_BitStream.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_memory.h" namespace { @@ -56,7 +56,7 @@ int DecodeNLPS(JBig2ArithCtx* pCX, const JBig2ArithQe& qe) { } // namespace CJBig2_ArithDecoder::CJBig2_ArithDecoder(CJBig2_BitStream* pStream) - : m_pStream(pStream) { + : m_Complete(false), m_FinishedStream(false), m_pStream(pStream) { m_B = m_pStream->getCurByte_arith(); m_C = (m_B ^ 0xff) << 16; BYTEIN(); @@ -95,6 +95,12 @@ void CJBig2_ArithDecoder::BYTEIN() { B1 = m_pStream->getNextByte_arith(); if (B1 > 0x8f) { m_CT = 8; + // If we are here, it means that we have finished decoding data (see JBIG2 + // spec, Section E.3.4). If we arrive here a second time, we're looping, + // so complete decoding. + if (m_FinishedStream) + m_Complete = true; + m_FinishedStream = true; } else { m_pStream->incByteIdx(); m_B = B1; @@ -107,6 +113,9 @@ void CJBig2_ArithDecoder::BYTEIN() { m_C = m_C + 0xff00 - (m_B << 8); m_CT = 8; } + + if (!m_pStream->IsInBounds()) + m_Complete = true; } void CJBig2_ArithDecoder::ReadValueA() { diff --git a/core/fxcodec/jbig2/JBig2_ArithDecoder.h b/core/fxcodec/jbig2/JBig2_ArithDecoder.h index a8ab5dd7309a770c74dec6aa87cab9a808695d04..c9e29a5937e34d43926d873f8abc025b452064e3 100644 --- a/core/fxcodec/jbig2/JBig2_ArithDecoder.h +++ b/core/fxcodec/jbig2/JBig2_ArithDecoder.h @@ -7,6 +7,10 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_ARITHDECODER_H_ #define CORE_FXCODEC_JBIG2_JBIG2_ARITHDECODER_H_ +#include + +#include "core/fxcrt/unowned_ptr.h" + class CJBig2_BitStream; struct JBig2ArithCtx { @@ -24,15 +28,19 @@ class CJBig2_ArithDecoder { int DECODE(JBig2ArithCtx* pCX); + bool IsComplete() const { return m_Complete; } + private: void BYTEIN(); void ReadValueA(); - unsigned char m_B; + bool m_Complete; + bool m_FinishedStream; + uint8_t m_B; unsigned int m_C; unsigned int m_A; unsigned int m_CT; - CJBig2_BitStream* const m_pStream; + UnownedPtr const m_pStream; }; #endif // CORE_FXCODEC_JBIG2_JBIG2_ARITHDECODER_H_ diff --git a/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp b/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp index 228e16ec09a13361424275ef5b11858848ddae6c..7ed7702964f9876d39c5e52c584be88173c17019 100644 --- a/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp +++ b/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp @@ -8,7 +8,7 @@ #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_memory.h" namespace { @@ -49,6 +49,9 @@ CJBig2_ArithIntDecoder::~CJBig2_ArithIntDecoder() {} bool CJBig2_ArithIntDecoder::decode(CJBig2_ArithDecoder* pArithDecoder, int* nResult) { + // This decoding algorithm is explained in "Annex A - Arithmetic Integer + // Decoding Procedure" on page 113 of the JBIG2 specification (ISO/IEC FCD + // 14492). int PREV = 1; const int S = pArithDecoder->DECODE(&m_IAx[PREV]); PREV = ShiftOr(PREV, S); @@ -64,8 +67,17 @@ bool CJBig2_ArithIntDecoder::decode(CJBig2_ArithDecoder* pArithDecoder, PREV = (PREV & 511) | 256; nTemp = ShiftOr(nTemp, D); } - int nValue = g_ArithIntDecodeData[nDecodeDataIndex].nValue; - nValue += nTemp; + pdfium::base::CheckedNumeric safeValue = + g_ArithIntDecodeData[nDecodeDataIndex].nValue; + safeValue += nTemp; + + // Value does not fit in int. + if (!safeValue.IsValid()) { + *nResult = 0; + return false; + } + + int nValue = safeValue.ValueOrDie(); if (S == 1 && nValue > 0) nValue = -nValue; diff --git a/core/fxcodec/jbig2/JBig2_BitStream.cpp b/core/fxcodec/jbig2/JBig2_BitStream.cpp index dc4beabc4b8045c1f4f9a5861fdae0b89c5b309c..a72099d4ffe9d17018a5ddc14fddcab7d68c28f6 100644 --- a/core/fxcodec/jbig2/JBig2_BitStream.cpp +++ b/core/fxcodec/jbig2/JBig2_BitStream.cpp @@ -11,7 +11,7 @@ #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" -CJBig2_BitStream::CJBig2_BitStream(CPDF_StreamAcc* pSrcStream) +CJBig2_BitStream::CJBig2_BitStream(const RetainPtr& pSrcStream) : m_pBuf(pSrcStream->GetData()), m_dwLength(pSrcStream->GetSize()), m_dwByteIdx(0), @@ -27,6 +27,9 @@ CJBig2_BitStream::CJBig2_BitStream(CPDF_StreamAcc* pSrcStream) CJBig2_BitStream::~CJBig2_BitStream() {} int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, uint32_t* dwResult) { + if (!IsInBounds()) + return -1; + uint32_t dwBitPos = getBitPos(); if (dwBitPos > LengthInBits()) return -1; @@ -46,6 +49,9 @@ int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, uint32_t* dwResult) { } int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, int32_t* nResult) { + if (!IsInBounds()) + return -1; + uint32_t dwBitPos = getBitPos(); if (dwBitPos > LengthInBits()) return -1; @@ -65,7 +71,7 @@ int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, int32_t* nResult) { } int32_t CJBig2_BitStream::read1Bit(uint32_t* dwResult) { - if (!IsInBound()) + if (!IsInBounds()) return -1; *dwResult = (m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01; @@ -74,7 +80,7 @@ int32_t CJBig2_BitStream::read1Bit(uint32_t* dwResult) { } int32_t CJBig2_BitStream::read1Bit(bool* bResult) { - if (!IsInBound()) + if (!IsInBounds()) return -1; *bResult = (m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01; @@ -83,7 +89,7 @@ int32_t CJBig2_BitStream::read1Bit(bool* bResult) { } int32_t CJBig2_BitStream::read1Byte(uint8_t* cResult) { - if (!IsInBound()) + if (!IsInBounds()) return -1; *cResult = m_pBuf[m_dwByteIdx]; @@ -118,16 +124,16 @@ void CJBig2_BitStream::alignByte() { } uint8_t CJBig2_BitStream::getCurByte() const { - return IsInBound() ? m_pBuf[m_dwByteIdx] : 0; + return IsInBounds() ? m_pBuf[m_dwByteIdx] : 0; } void CJBig2_BitStream::incByteIdx() { - if (IsInBound()) + if (IsInBounds()) ++m_dwByteIdx; } uint8_t CJBig2_BitStream::getCurByte_arith() const { - return IsInBound() ? m_pBuf[m_dwByteIdx] : 0xFF; + return IsInBounds() ? m_pBuf[m_dwByteIdx] : 0xFF; } uint8_t CJBig2_BitStream::getNextByte_arith() const { @@ -176,7 +182,7 @@ void CJBig2_BitStream::AdvanceBit() { } } -bool CJBig2_BitStream::IsInBound() const { +bool CJBig2_BitStream::IsInBounds() const { return m_dwByteIdx < m_dwLength; } diff --git a/core/fxcodec/jbig2/JBig2_BitStream.h b/core/fxcodec/jbig2/JBig2_BitStream.h index aeb2eba693c4d5a8a6d6b8a7ad1b656b2c991147..0edb432ddeb0f6eea02382c506818ee3ef5fe550 100644 --- a/core/fxcodec/jbig2/JBig2_BitStream.h +++ b/core/fxcodec/jbig2/JBig2_BitStream.h @@ -7,13 +7,13 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_BITSTREAM_H_ #define CORE_FXCODEC_JBIG2_JBIG2_BITSTREAM_H_ -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/retain_ptr.h" class CPDF_StreamAcc; class CJBig2_BitStream { public: - explicit CJBig2_BitStream(CPDF_StreamAcc* pSrcStream); + explicit CJBig2_BitStream(const RetainPtr& pSrcStream); ~CJBig2_BitStream(); // TODO(thestig): readFoo() should return bool. @@ -40,9 +40,10 @@ class CJBig2_BitStream { uint32_t getByteLeft() const; uint32_t getObjNum() const; + bool IsInBounds() const; + private: void AdvanceBit(); - bool IsInBound() const; uint32_t LengthInBits() const; const uint8_t* m_pBuf; diff --git a/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp b/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b66d8b065155c8fe0688706d2917e5205b919f0e --- /dev/null +++ b/core/fxcodec/jbig2/JBig2_BitStream_unittest.cpp @@ -0,0 +1,119 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcodec/jbig2/JBig2_BitStream.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +TEST(JBig2_BitStream, ReadNBits) { + std::unique_ptr data(FX_Alloc(uint8_t, 1)); + data.get()[0] = 0xb1; // 10110001 + + auto in_stream = pdfium::MakeUnique(std::move(data), 1, nullptr); + auto acc = pdfium::MakeRetain(in_stream.get()); + acc->LoadAllDataFiltered(); + + CJBig2_BitStream stream(acc); + + uint32_t val1; + EXPECT_EQ(0, stream.readNBits(1, &val1)); + EXPECT_EQ(1U, val1); + + int32_t val2; + EXPECT_EQ(0, stream.readNBits(1, &val2)); + EXPECT_EQ(0, val2); + + EXPECT_EQ(0, stream.readNBits(2, &val2)); + EXPECT_EQ(3, val2); + + EXPECT_EQ(0, stream.readNBits(4, &val2)); + EXPECT_EQ(1, val2); +} + +TEST(JBig2_BitStream, ReadNBitsLargerThenData) { + std::unique_ptr data(FX_Alloc(uint8_t, 1)); + data.get()[0] = 0xb1; + + auto in_stream = pdfium::MakeUnique(std::move(data), 1, nullptr); + auto acc = pdfium::MakeRetain(in_stream.get()); + acc->LoadAllDataFiltered(); + + CJBig2_BitStream stream(acc); + + uint32_t val1; + EXPECT_EQ(0, stream.readNBits(10, &val1)); + EXPECT_EQ(0xb1U, val1); +} + +TEST(JBig2_BitStream, ReadNBitsNullStream) { + auto in_stream = pdfium::MakeUnique(nullptr, 0, nullptr); + auto acc = pdfium::MakeRetain(in_stream.get()); + acc->LoadAllDataFiltered(); + + CJBig2_BitStream stream(acc); + + uint32_t val1; + EXPECT_EQ(-1, stream.readNBits(1, &val1)); + + int32_t val2; + EXPECT_EQ(-1, stream.readNBits(2, &val2)); +} + +TEST(JBig2_BitStream, ReadNBitsEmptyStream) { + std::unique_ptr data(FX_Alloc(uint8_t, 1)); + + auto in_stream = pdfium::MakeUnique(std::move(data), 0, nullptr); + auto acc = pdfium::MakeRetain(in_stream.get()); + acc->LoadAllDataFiltered(); + + CJBig2_BitStream stream(acc); + + uint32_t val1; + EXPECT_EQ(-1, stream.readNBits(1, &val1)); + + int32_t val2; + EXPECT_EQ(-1, stream.readNBits(2, &val2)); +} + +TEST(JBig2_BitStream, ReadNBitsOutOfBounds) { + std::unique_ptr data(FX_Alloc(uint8_t, 1)); + data.get()[0] = 0xb1; // 10110001 + + auto in_stream = pdfium::MakeUnique(std::move(data), 1, nullptr); + auto acc = pdfium::MakeRetain(in_stream.get()); + acc->LoadAllDataFiltered(); + + CJBig2_BitStream stream(acc); + + uint32_t val1; + EXPECT_EQ(0, stream.readNBits(8, &val1)); + + int32_t val2; + EXPECT_EQ(-1, stream.readNBits(2, &val2)); +} + +TEST(JBig2_BitStream, ReadNBitsWhereNIs36) { + std::unique_ptr data(FX_Alloc(uint8_t, 5)); + data.get()[0] = 0xb0; + data.get()[1] = 0x01; + data.get()[2] = 0x00; + data.get()[3] = 0x00; + data.get()[4] = 0x40; + + auto in_stream = pdfium::MakeUnique(std::move(data), 5, nullptr); + auto acc = pdfium::MakeRetain(in_stream.get()); + acc->LoadAllDataFiltered(); + + CJBig2_BitStream stream(acc); + + // This will shift off the top two bits and they end up lost. + uint32_t val1; + EXPECT_EQ(0, stream.readNBits(34, &val1)); + EXPECT_EQ(0xc0040001U, val1); +} diff --git a/core/fxcodec/jbig2/JBig2_Context.cpp b/core/fxcodec/jbig2/JBig2_Context.cpp index 109013204e153e92c6344e9bb6c897085fae5238..30e4aab78c14333c78909c27f23cf36a641864b4 100644 --- a/core/fxcodec/jbig2/JBig2_Context.cpp +++ b/core/fxcodec/jbig2/JBig2_Context.cpp @@ -7,6 +7,7 @@ #include "core/fxcodec/jbig2/JBig2_Context.h" #include +#include #include #include #include @@ -22,8 +23,8 @@ #include "core/fxcodec/jbig2/JBig2_PddProc.h" #include "core/fxcodec/jbig2/JBig2_SddProc.h" #include "core/fxcodec/jbig2/JBig2_TrdProc.h" +#include "core/fxcrt/ifx_pauseindicator.h" #include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" namespace { @@ -44,32 +45,32 @@ size_t GetRefAggContextSize(bool val) { // list keeps track of the freshness of entries, with freshest ones // at the front. Even a tiny cache size like 2 makes a dramatic // difference for typical JBIG2 documents. -static const int kSymbolDictCacheMaxSize = 2; +static const size_t kSymbolDictCacheMaxSize = 2; +static_assert(kSymbolDictCacheMaxSize > 0, + "Symbol Dictionary Cache must have non-zero size"); -CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream, - CPDF_StreamAcc* pSrcStream, +CJBig2_Context::CJBig2_Context(const RetainPtr& pGlobalStream, + const RetainPtr& pSrcStream, std::list* pSymbolDictCache, - IFX_Pause* pPause, bool bIsGlobal) : m_nSegmentDecoded(0), m_bInPage(false), m_bBufSpecified(false), m_PauseStep(10), - m_pPause(pPause), m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY), m_dwOffset(0), m_pSymbolDictCache(pSymbolDictCache), m_bIsGlobal(bIsGlobal) { - if (pGlobalStream && (pGlobalStream->GetSize() > 0)) { + if (pGlobalStream && pGlobalStream->GetSize() > 0) { m_pGlobalContext = pdfium::MakeUnique( - nullptr, pGlobalStream, pSymbolDictCache, pPause, true); + nullptr, pGlobalStream, pSymbolDictCache, true); } m_pStream = pdfium::MakeUnique(pSrcStream); } CJBig2_Context::~CJBig2_Context() {} -int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) { +int32_t CJBig2_Context::decodeSequential(IFX_PauseIndicator* pPause) { int32_t nRet; if (m_pStream->getByteLeft() <= 0) return JBIG2_END_OF_FILE; @@ -100,7 +101,10 @@ int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) { } if (m_pSegment->m_dwData_length != 0xffffffff) { m_dwOffset += m_pSegment->m_dwData_length; - m_pStream->setOffset(m_dwOffset); + if (!m_dwOffset.IsValid()) + return JBIG2_ERROR_FATAL; + + m_pStream->setOffset(m_dwOffset.ValueOrDie()); } else { m_pStream->offset(4); } @@ -115,32 +119,29 @@ int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) { return JBIG2_SUCCESS; } -int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) { - return decode_SquentialOrgnazation(pPause); -} - -int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) { +int32_t CJBig2_Context::decodeRandomFirstPage(IFX_PauseIndicator* pPause) { int32_t nRet; while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) { - std::unique_ptr pSegment(new CJBig2_Segment); + auto pSegment = pdfium::MakeUnique(); nRet = parseSegmentHeader(pSegment.get()); - if (nRet != JBIG2_SUCCESS) { + if (nRet != JBIG2_SUCCESS) return nRet; - } else if (pSegment->m_cFlags.s.type == 51) { + + if (pSegment->m_cFlags.s.type == 51) break; - } + m_SegmentList.push_back(std::move(pSegment)); - if (pPause && m_pPause && pPause->NeedToPauseNow()) { + if (pPause && pPause->NeedToPauseNow()) { m_PauseStep = 3; m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE; return JBIG2_SUCCESS; } } m_nSegmentDecoded = 0; - return decode_RandomOrgnazation(pPause); + return decodeRandom(pPause); } -int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) { +int32_t CJBig2_Context::decodeRandom(IFX_PauseIndicator* pPause) { for (; m_nSegmentDecoded < m_SegmentList.size(); ++m_nSegmentDecoded) { int32_t nRet = parseSegmentData(m_SegmentList[m_nSegmentDecoded].get(), pPause); @@ -163,10 +164,10 @@ int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf, int32_t width, int32_t height, int32_t stride, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { int32_t nRet = 0; if (m_pGlobalContext) { - nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause); + nRet = m_pGlobalContext->decodeSequential(pPause); if (nRet != JBIG2_SUCCESS) { m_ProcessingStatus = FXCODEC_STATUS_ERROR; return nRet; @@ -183,43 +184,37 @@ int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf, return Continue(pPause); } -int32_t CJBig2_Context::Continue(IFX_Pause* pPause) { +int32_t CJBig2_Context::Continue(IFX_PauseIndicator* pPause) { m_ProcessingStatus = FXCODEC_STATUS_DECODE_READY; int32_t nRet = 0; - if (m_PauseStep <= 1) { - nRet = decode_EmbedOrgnazation(pPause); - } else if (m_PauseStep == 2) { - nRet = decode_SquentialOrgnazation(pPause); + if (m_PauseStep <= 2) { + nRet = decodeSequential(pPause); } else if (m_PauseStep == 3) { - nRet = decode_RandomOrgnazation_FirstPage(pPause); + nRet = decodeRandomFirstPage(pPause); } else if (m_PauseStep == 4) { - nRet = decode_RandomOrgnazation(pPause); + nRet = decodeRandom(pPause); } else if (m_PauseStep == 5) { m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH; return JBIG2_SUCCESS; } - if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) { + if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) return nRet; - } + m_PauseStep = 5; if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) { m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH; return JBIG2_SUCCESS; } - if (nRet == JBIG2_SUCCESS) { - m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH; - } else { - m_ProcessingStatus = FXCODEC_STATUS_ERROR; - } + m_ProcessingStatus = nRet == JBIG2_SUCCESS ? FXCODEC_STATUS_DECODE_FINISH + : FXCODEC_STATUS_ERROR; return nRet; } CJBig2_Segment* CJBig2_Context::findSegmentByNumber(uint32_t dwNumber) { if (m_pGlobalContext) { CJBig2_Segment* pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber); - if (pSeg) { + if (pSeg) return pSeg; - } } for (const auto& pSeg : m_SegmentList) { if (pSeg->m_dwNumber == dwNumber) @@ -235,7 +230,7 @@ CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex( int32_t count = 0; for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { CJBig2_Segment* pSeg = - findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]); + findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); if (pSeg && pSeg->m_cFlags.s.type == cType) { if (count == nIndex) return pSeg; @@ -275,31 +270,31 @@ int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) { pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1; uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1; if (pSegment->m_nReferred_to_segment_count) { - pSegment->m_pReferred_to_segment_numbers = - FX_Alloc(uint32_t, pSegment->m_nReferred_to_segment_count); + pSegment->m_Referred_to_segment_numbers.resize( + pSegment->m_nReferred_to_segment_count); for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { switch (cSSize) { case 1: if (m_pStream->read1Byte(&cTemp) != 0) return JBIG2_ERROR_TOO_SHORT; - pSegment->m_pReferred_to_segment_numbers[i] = cTemp; + pSegment->m_Referred_to_segment_numbers[i] = cTemp; break; case 2: uint16_t wTemp; if (m_pStream->readShortInteger(&wTemp) != 0) return JBIG2_ERROR_TOO_SHORT; - pSegment->m_pReferred_to_segment_numbers[i] = wTemp; + pSegment->m_Referred_to_segment_numbers[i] = wTemp; break; case 4: if (m_pStream->readInteger(&dwTemp) != 0) return JBIG2_ERROR_TOO_SHORT; - pSegment->m_pReferred_to_segment_numbers[i] = dwTemp; + pSegment->m_Referred_to_segment_numbers[i] = dwTemp; break; } - if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber) + if (pSegment->m_Referred_to_segment_numbers[i] >= pSegment->m_dwNumber) return JBIG2_ERROR_TOO_SHORT; } } @@ -322,7 +317,7 @@ int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) { } int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { int32_t ret = ProcessingParseSegmentData(pSegment, pPause); while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE && m_pStream->getByteLeft() > 0) { @@ -332,10 +327,10 @@ int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment, } int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { switch (pSegment->m_cFlags.s.type) { case 0: - return parseSymbolDict(pSegment, pPause); + return parseSymbolDict(pSegment); case 4: case 6: case 7: @@ -364,7 +359,7 @@ int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment, return parseGenericRefinementRegion(pSegment); case 48: { uint16_t wTemp; - std::unique_ptr pPageInfo(new JBig2PageInfo); + auto pPageInfo = pdfium::MakeUnique(); if (m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0 || m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0 || m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0 || @@ -386,7 +381,7 @@ int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment, pdfium::MakeUnique(pPageInfo->m_dwWidth, height); } - if (!m_pPage->m_pData) { + if (!m_pPage->data()) { m_ProcessingStatus = FXCODEC_STATUS_ERROR; return JBIG2_ERROR_TOO_SHORT; } @@ -418,13 +413,12 @@ int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment, return JBIG2_SUCCESS; } -int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, - IFX_Pause* pPause) { +int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment) { uint16_t wFlags; if (m_pStream->readShortInteger(&wFlags) != 0) return JBIG2_ERROR_TOO_SHORT; - std::unique_ptr pSymbolDictDecoder(new CJBig2_SDDProc); + auto pSymbolDictDecoder = pdfium::MakeUnique(); pSymbolDictDecoder->SDHUFF = wFlags & 0x0001; pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001; pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003; @@ -455,16 +449,16 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, return JBIG2_ERROR_LIMIT; } for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { - if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) + if (!findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i])) return JBIG2_ERROR_FATAL; } CJBig2_Segment* pLRSeg = nullptr; pSymbolDictDecoder->SDNUMINSYMS = 0; for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { CJBig2_Segment* pSeg = - findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]); + findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); if (pSeg->m_cFlags.s.type == 0) { - pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->NumImages(); + pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_SymbolDict->NumImages(); pLRSeg = pSeg; } } @@ -475,9 +469,9 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, uint32_t dwTemp = 0; for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { CJBig2_Segment* pSeg = - findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]); + findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); if (pSeg->m_cFlags.s.type == 0) { - const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd; + const CJBig2_SymbolDict& dict = *pSeg->m_SymbolDict.get(); for (size_t j = 0; j < dict.NumImages(); ++j) SDINSYMS.get()[dwTemp + j] = dict.GetImage(j); dwTemp += dict.NumImages(); @@ -509,7 +503,7 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht; + pSymbolDictDecoder->SDHUFFDH = pSeg->m_HuffmanTable.get(); } if (cSDHUFFDW == 0) { Table_B2 = pdfium::MakeUnique( @@ -524,7 +518,7 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht; + pSymbolDictDecoder->SDHUFFDW = pSeg->m_HuffmanTable.get(); } if (cSDHUFFBMSIZE == 0) { Table_B1 = pdfium::MakeUnique( @@ -535,7 +529,7 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht; + pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_HuffmanTable.get(); } if (pSymbolDictDecoder->SDREFAGG == 1) { if (cSDHUFFAGGINST == 0) { @@ -549,7 +543,7 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht; + pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_HuffmanTable.get(); } } } @@ -564,12 +558,12 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, std::vector grContext; if ((wFlags & 0x0100) && pLRSeg) { if (bUseGbContext) { - gbContext = pLRSeg->m_Result.sd->GbContext(); + gbContext = pLRSeg->m_SymbolDict->GbContext(); if (gbContext.size() != gbContextSize) return JBIG2_ERROR_FATAL; } if (bUseGrContext) { - grContext = pLRSeg->m_Result.sd->GrContext(); + grContext = pLRSeg->m_SymbolDict->GrContext(); if (grContext.size() != grContextSize) return JBIG2_ERROR_FATAL; } @@ -588,8 +582,7 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end(); ++it) { if (it->first == key) { - std::unique_ptr copy(it->second->DeepCopy()); - pSegment->m_Result.sd = copy.release(); + pSegment->m_SymbolDict = it->second->DeepCopy(); m_pSymbolDictCache->push_front( CJBig2_CachePair(key, std::move(it->second))); m_pSymbolDictCache->erase(it); @@ -600,26 +593,26 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, } if (!cache_hit) { if (bUseGbContext) { - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(m_pStream.get())); - pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith( + auto pArithDecoder = + pdfium::MakeUnique(m_pStream.get()); + pSegment->m_SymbolDict = pSymbolDictDecoder->decode_Arith( pArithDecoder.get(), &gbContext, &grContext); - if (!pSegment->m_Result.sd) + if (!pSegment->m_SymbolDict) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); m_pStream->offset(2); } else { - pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman( - m_pStream.get(), &gbContext, &grContext, pPause); - if (!pSegment->m_Result.sd) + pSegment->m_SymbolDict = pSymbolDictDecoder->decode_Huffman( + m_pStream.get(), &gbContext, &grContext); + if (!pSegment->m_SymbolDict) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); } if (m_bIsGlobal) { std::unique_ptr value = - pSegment->m_Result.sd->DeepCopy(); - int size = pdfium::CollectionSize(*m_pSymbolDictCache); + pSegment->m_SymbolDict->DeepCopy(); + size_t size = m_pSymbolDictCache->size(); while (size >= kSymbolDictCacheMaxSize) { m_pSymbolDictCache->pop_back(); --size; @@ -629,9 +622,9 @@ int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment, } if (wFlags & 0x0200) { if (bUseGbContext) - pSegment->m_Result.sd->SetGbContext(gbContext); + pSegment->m_SymbolDict->SetGbContext(gbContext); if (bUseGrContext) - pSegment->m_Result.sd->SetGrContext(grContext); + pSegment->m_SymbolDict->SetGrContext(grContext); } return JBIG2_SUCCESS; } @@ -644,7 +637,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { return JBIG2_ERROR_TOO_SHORT; } - std::unique_ptr pTRD(new CJBig2_TRDProc); + auto pTRD = pdfium::MakeUnique(); pTRD->SBW = ri.width; pTRD->SBH = ri.height; pTRD->SBHUFF = wFlags & 0x0001; @@ -692,16 +685,16 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { return JBIG2_ERROR_TOO_SHORT; for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { - if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i])) + if (!findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i])) return JBIG2_ERROR_FATAL; } pTRD->SBNUMSYMS = 0; for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { CJBig2_Segment* pSeg = - findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]); + findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); if (pSeg->m_cFlags.s.type == 0) { - pTRD->SBNUMSYMS += pSeg->m_Result.sd->NumImages(); + pTRD->SBNUMSYMS += pSeg->m_SymbolDict->NumImages(); } } @@ -711,9 +704,9 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { dwTemp = 0; for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { CJBig2_Segment* pSeg = - findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]); + findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); if (pSeg->m_cFlags.s.type == 0) { - const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd; + const CJBig2_SymbolDict& dict = *pSeg->m_SymbolDict.get(); for (size_t j = 0; j < dict.NumImages(); ++j) SBSYMS.get()[dwTemp + j] = dict.GetImage(j); dwTemp += dict.NumImages(); @@ -724,15 +717,14 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { pTRD->SBSYMS = nullptr; } - std::unique_ptr SBSYMCODES; if (pTRD->SBHUFF == 1) { - SBSYMCODES.reset( - decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS)); - if (!SBSYMCODES) + std::vector SBSYMCODES = + decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS); + if (SBSYMCODES.empty()) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); - pTRD->SBSYMCODES = SBSYMCODES.get(); + pTRD->SBSYMCODES = std::move(SBSYMCODES); } else { dwTemp = 0; while ((uint32_t)(1 << dwTemp) < pTRD->SBNUMSYMS) { @@ -771,7 +763,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFFS = pSeg->m_Result.ht; + pTRD->SBHUFFFS = pSeg->m_HuffmanTable.get(); } if (cSBHUFFDS == 0) { Table_B8 = pdfium::MakeUnique( @@ -790,7 +782,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFDS = pSeg->m_Result.ht; + pTRD->SBHUFFDS = pSeg->m_HuffmanTable.get(); } if (cSBHUFFDT == 0) { Table_B11 = pdfium::MakeUnique( @@ -809,7 +801,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFDT = pSeg->m_Result.ht; + pTRD->SBHUFFDT = pSeg->m_HuffmanTable.get(); } if (cSBHUFFRDW == 0) { Table_B14 = pdfium::MakeUnique( @@ -824,7 +816,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFRDW = pSeg->m_Result.ht; + pTRD->SBHUFFRDW = pSeg->m_HuffmanTable.get(); } if (cSBHUFFRDH == 0) { if (!Table_B14) { @@ -843,7 +835,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFRDH = pSeg->m_Result.ht; + pTRD->SBHUFFRDH = pSeg->m_HuffmanTable.get(); } if (cSBHUFFRDX == 0) { if (!Table_B14) { @@ -862,7 +854,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFRDX = pSeg->m_Result.ht; + pTRD->SBHUFFRDX = pSeg->m_HuffmanTable.get(); } if (cSBHUFFRDY == 0) { if (!Table_B14) { @@ -881,7 +873,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFRDY = pSeg->m_Result.ht; + pTRD->SBHUFFRDY = pSeg->m_HuffmanTable.get(); } if (cSBHUFFRSIZE == 0) { Table_B1 = pdfium::MakeUnique( @@ -892,7 +884,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); if (!pSeg) return JBIG2_ERROR_FATAL; - pTRD->SBHUFFRSIZE = pSeg->m_Result.ht; + pTRD->SBHUFFRSIZE = pSeg->m_HuffmanTable.get(); } } std::unique_ptr grContext; @@ -902,20 +894,19 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); } if (pTRD->SBHUFF == 0) { - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(m_pStream.get())); + auto pArithDecoder = + pdfium::MakeUnique(m_pStream.get()); pSegment->m_nResultType = JBIG2_IMAGE_POINTER; - pSegment->m_Result.im = + pSegment->m_Image = pTRD->decode_Arith(pArithDecoder.get(), grContext.get(), nullptr); - if (!pSegment->m_Result.im) + if (!pSegment->m_Image) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); m_pStream->offset(2); } else { pSegment->m_nResultType = JBIG2_IMAGE_POINTER; - pSegment->m_Result.im = - pTRD->decode_Huffman(m_pStream.get(), grContext.get()); - if (!pSegment->m_Result.im) + pSegment->m_Image = pTRD->decode_Huffman(m_pStream.get(), grContext.get()); + if (!pSegment->m_Image) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); } @@ -927,18 +918,17 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } } - m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im, + m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Image.get(), (JBig2ComposeOp)(ri.flags & 0x03)); - delete pSegment->m_Result.im; - pSegment->m_Result.im = nullptr; + pSegment->m_Image.reset(); } return JBIG2_SUCCESS; } int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { uint8_t cFlags; - std::unique_ptr pPDD(new CJBig2_PDDProc); + auto pPDD = pdfium::MakeUnique(); if (m_pStream->read1Byte(&cFlags) != 0 || m_pStream->read1Byte(&pPDD->HDPW) != 0 || m_pStream->read1Byte(&pPDD->HDPH) != 0 || @@ -956,18 +946,18 @@ int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment, std::unique_ptr gbContext( FX_Alloc(JBig2ArithCtx, size)); JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size); - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(m_pStream.get())); - pSegment->m_Result.pd = + auto pArithDecoder = + pdfium::MakeUnique(m_pStream.get()); + pSegment->m_PatternDict = pPDD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause); - if (!pSegment->m_Result.pd) + if (!pSegment->m_PatternDict) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); m_pStream->offset(2); } else { - pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream.get(), pPause); - if (!pSegment->m_Result.pd) + pSegment->m_PatternDict = pPDD->decode_MMR(m_pStream.get()); + if (!pSegment->m_PatternDict) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); } @@ -975,10 +965,10 @@ int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment, } int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { uint8_t cFlags; JBig2RegionInfo ri; - std::unique_ptr pHRD(new CJBig2_HTRDProc); + auto pHRD = pdfium::MakeUnique(); if (parseRegionInfo(&ri) != JBIG2_SUCCESS || m_pStream->read1Byte(&cFlags) != 0 || m_pStream->readInteger(&pHRD->HGW) != 0 || @@ -1004,16 +994,16 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, return JBIG2_ERROR_FATAL; CJBig2_Segment* pSeg = - findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]); + findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]); if (!pSeg || (pSeg->m_cFlags.s.type != 16)) return JBIG2_ERROR_FATAL; - CJBig2_PatternDict* pPatternDict = pSeg->m_Result.pd; + const CJBig2_PatternDict* pPatternDict = pSeg->m_PatternDict.get(); if (!pPatternDict || (pPatternDict->NUMPATS == 0)) return JBIG2_ERROR_FATAL; pHRD->HNUMPATS = pPatternDict->NUMPATS; - pHRD->HPATS = pPatternDict->HDPATS; + pHRD->HPATS = &pPatternDict->HDPATS; pHRD->HPW = pPatternDict->HDPATS[0]->width(); pHRD->HPH = pPatternDict->HDPATS[0]->height(); pSegment->m_nResultType = JBIG2_IMAGE_POINTER; @@ -1022,18 +1012,18 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, std::unique_ptr gbContext( FX_Alloc(JBig2ArithCtx, size)); JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size); - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(m_pStream.get())); - pSegment->m_Result.im = + auto pArithDecoder = + pdfium::MakeUnique(m_pStream.get()); + pSegment->m_Image = pHRD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause); - if (!pSegment->m_Result.im) + if (!pSegment->m_Image) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); m_pStream->offset(2); } else { - pSegment->m_Result.im = pHRD->decode_MMR(m_pStream.get(), pPause); - if (!pSegment->m_Result.im) + pSegment->m_Image = pHRD->decode_MMR(m_pStream.get()); + if (!pSegment->m_Image) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); } @@ -1045,18 +1035,17 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } } - m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im, + m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Image.get(), (JBig2ComposeOp)(ri.flags & 0x03)); - delete pSegment->m_Result.im; - pSegment->m_Result.im = nullptr; + pSegment->m_Image.reset(); } return JBIG2_SUCCESS; } int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { if (!m_pGRD) { - std::unique_ptr pGRD(new CJBig2_GRDProc); + auto pGRD = pdfium::MakeUnique(); uint8_t cFlags; if (parseRegionInfo(&m_ri) != JBIG2_SUCCESS || m_pStream->read1Byte(&cFlags) != 0) { @@ -1064,7 +1053,6 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, } if (m_ri.height < 0 || m_ri.width < 0) return JBIG2_FAILED; - pGRD->GBW = m_ri.width; pGRD->GBH = m_ri.height; pGRD->MMR = cFlags & 0x01; @@ -1073,15 +1061,13 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, if (pGRD->MMR == 0) { if (pGRD->GBTEMPLATE == 0) { for (int32_t i = 0; i < 8; ++i) { - if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) { + if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) return JBIG2_ERROR_TOO_SHORT; - } } } else { for (int32_t i = 0; i < 2; ++i) { - if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) { + if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) return JBIG2_ERROR_TOO_SHORT; - } } } } @@ -1090,18 +1076,16 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, } pSegment->m_nResultType = JBIG2_IMAGE_POINTER; if (m_pGRD->MMR == 0) { - if (m_gbContext.empty()) { - const size_t size = GetHuffContextSize(m_pGRD->GBTEMPLATE); - m_gbContext.resize(size); - } + if (m_gbContext.empty()) + m_gbContext.resize(GetHuffContextSize(m_pGRD->GBTEMPLATE)); if (!m_pArithDecoder) { m_pArithDecoder = pdfium::MakeUnique(m_pStream.get()); - m_ProcessingStatus = m_pGRD->Start_decode_Arith(&pSegment->m_Result.im, - m_pArithDecoder.get(), - &m_gbContext[0], pPause); + m_ProcessingStatus = m_pGRD->Start_decode_Arith( + &pSegment->m_Image, m_pArithDecoder.get(), &m_gbContext[0], pPause); } else { - m_ProcessingStatus = m_pGRD->Continue_decode(pPause); + m_ProcessingStatus = + m_pGRD->Continue_decode(pPause, m_pArithDecoder.get()); } if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) { if (pSegment->m_cFlags.s.type != 36) { @@ -1115,24 +1099,23 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, } FX_RECT Rect = m_pGRD->GetReplaceRect(); m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top, - pSegment->m_Result.im, + pSegment->m_Image.get(), (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect); } return JBIG2_SUCCESS; - } else { - m_pArithDecoder.reset(); - m_gbContext.clear(); - if (!pSegment->m_Result.im) { - m_ProcessingStatus = FXCODEC_STATUS_ERROR; - m_pGRD.reset(); - return JBIG2_ERROR_FATAL; - } - m_pStream->alignByte(); - m_pStream->offset(2); } + m_pArithDecoder.reset(); + m_gbContext.clear(); + if (!pSegment->m_Image) { + m_ProcessingStatus = FXCODEC_STATUS_ERROR; + m_pGRD.reset(); + return JBIG2_ERROR_FATAL; + } + m_pStream->alignByte(); + m_pStream->offset(2); } else { - m_pGRD->Start_decode_MMR(&pSegment->m_Result.im, m_pStream.get(), pPause); - if (!pSegment->m_Result.im) { + m_pGRD->Start_decode_MMR(&pSegment->m_Image, m_pStream.get()); + if (!pSegment->m_Image) { m_pGRD.reset(); return JBIG2_ERROR_FATAL; } @@ -1149,10 +1132,9 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, } FX_RECT Rect = m_pGRD->GetReplaceRect(); m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top, - pSegment->m_Result.im, + pSegment->m_Image.get(), (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect); - delete pSegment->m_Result.im; - pSegment->m_Result.im = nullptr; + pSegment->m_Image.reset(); } m_pGRD.reset(); return JBIG2_SUCCESS; @@ -1165,7 +1147,7 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { m_pStream->read1Byte(&cFlags) != 0) { return JBIG2_ERROR_TOO_SHORT; } - std::unique_ptr pGRRD(new CJBig2_GRRDProc); + auto pGRRD = pdfium::MakeUnique(); pGRRD->GRW = ri.width; pGRRD->GRH = ri.height; pGRRD->GRTEMPLATE = !!(cFlags & 0x01); @@ -1180,7 +1162,7 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { if (pSegment->m_nReferred_to_segment_count > 0) { int32_t i; for (i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { - pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]); + pSeg = findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]); if (!pSeg) return JBIG2_ERROR_FATAL; @@ -1192,7 +1174,7 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { if (i >= pSegment->m_nReferred_to_segment_count) return JBIG2_ERROR_FATAL; - pGRRD->GRREFERENCE = pSeg->m_Result.im; + pGRRD->GRREFERENCE = pSeg->m_Image.get(); } else { pGRRD->GRREFERENCE = m_pPage.get(); } @@ -1202,11 +1184,10 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { std::unique_ptr grContext( FX_Alloc(JBig2ArithCtx, size)); JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(m_pStream.get())); + auto pArithDecoder = pdfium::MakeUnique(m_pStream.get()); pSegment->m_nResultType = JBIG2_IMAGE_POINTER; - pSegment->m_Result.im = pGRRD->decode(pArithDecoder.get(), grContext.get()); - if (!pSegment->m_Result.im) + pSegment->m_Image = pGRRD->decode(pArithDecoder.get(), grContext.get()); + if (!pSegment->m_Image) return JBIG2_ERROR_FATAL; m_pStream->alignByte(); @@ -1219,23 +1200,21 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } } - m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im, + m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Image.get(), (JBig2ComposeOp)(ri.flags & 0x03)); - delete pSegment->m_Result.im; - pSegment->m_Result.im = nullptr; + pSegment->m_Image.reset(); } return JBIG2_SUCCESS; } int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) { pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER; - pSegment->m_Result.ht = nullptr; - std::unique_ptr pHuff( - new CJBig2_HuffmanTable(m_pStream.get())); + pSegment->m_HuffmanTable.reset(); + auto pHuff = pdfium::MakeUnique(m_pStream.get()); if (!pHuff->IsOK()) return JBIG2_ERROR_FATAL; - pSegment->m_Result.ht = pHuff.release(); + pSegment->m_HuffmanTable = std::move(pHuff); m_pStream->alignByte(); return JBIG2_SUCCESS; } @@ -1251,35 +1230,35 @@ int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) { return JBIG2_SUCCESS; } -JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable( +std::vector CJBig2_Context::decodeSymbolIDHuffmanTable( CJBig2_BitStream* pStream, uint32_t SBNUMSYMS) { const size_t kRunCodesSize = 35; - int32_t runcodes[kRunCodesSize]; - int32_t runcodes_len[kRunCodesSize]; + JBig2HuffmanCode huffman_codes[kRunCodesSize]; for (size_t i = 0; i < kRunCodesSize; ++i) { - if (pStream->readNBits(4, &runcodes_len[i]) != 0) - return nullptr; + if (pStream->readNBits(4, &huffman_codes[i].codelen) != 0) + return std::vector(); } - huffman_assign_code(runcodes, runcodes_len, kRunCodesSize); + huffman_assign_code(huffman_codes, kRunCodesSize); - std::unique_ptr SBSYMCODES( - FX_Alloc(JBig2HuffmanCode, SBNUMSYMS)); + std::vector SBSYMCODES(SBNUMSYMS); int32_t run = 0; int32_t i = 0; - while (i < (int)SBNUMSYMS) { + while (i < static_cast(SBNUMSYMS)) { size_t j; int32_t nVal = 0; int32_t nBits = 0; uint32_t nTemp; while (true) { - if (pStream->read1Bit(&nTemp) != 0) - return nullptr; + if (nVal > std::numeric_limits::max() / 2 || + pStream->read1Bit(&nTemp) != 0) { + return std::vector(); + } nVal = (nVal << 1) | nTemp; ++nBits; for (j = 0; j < kRunCodesSize; ++j) { - if (nBits == runcodes_len[j] && nVal == runcodes[j]) + if (nBits == huffman_codes[j].codelen && nVal == huffman_codes[j].code) break; } if (j < kRunCodesSize) @@ -1287,110 +1266,58 @@ JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable( } int32_t runcode = static_cast(j); if (runcode < 32) { - SBSYMCODES.get()[i].codelen = runcode; + SBSYMCODES[i].codelen = runcode; run = 0; } else if (runcode == 32) { if (pStream->readNBits(2, &nTemp) != 0) - return nullptr; + return std::vector(); run = nTemp + 3; } else if (runcode == 33) { if (pStream->readNBits(3, &nTemp) != 0) - return nullptr; + return std::vector(); run = nTemp + 3; } else if (runcode == 34) { if (pStream->readNBits(7, &nTemp) != 0) - return nullptr; + return std::vector(); run = nTemp + 11; } if (run > 0) { if (i + run > (int)SBNUMSYMS) - return nullptr; + return std::vector(); for (int32_t k = 0; k < run; ++k) { - if (runcode == 32 && i > 0) { - SBSYMCODES.get()[i + k].codelen = SBSYMCODES.get()[i - 1].codelen; - } else { - SBSYMCODES.get()[i + k].codelen = 0; - } + if (runcode == 32 && i > 0) + SBSYMCODES[i + k].codelen = SBSYMCODES[i - 1].codelen; + else + SBSYMCODES[i + k].codelen = 0; } i += run; } else { ++i; } } - huffman_assign_code(SBSYMCODES.get(), SBNUMSYMS); - return SBSYMCODES.release(); -} - -void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) { - // TODO(thestig) CJBig2_HuffmanTable::parseFromCodedBuffer() has similar code. - int CURLEN, LENMAX, CURCODE, CURTEMP, i; - int* LENCOUNT; - int* FIRSTCODE; - LENMAX = 0; - for (i = 0; i < NTEMP; ++i) { - if (PREFLEN[i] > LENMAX) { - LENMAX = PREFLEN[i]; - } - } - LENCOUNT = FX_Alloc(int, LENMAX + 1); - JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1)); - FIRSTCODE = FX_Alloc(int, LENMAX + 1); - for (i = 0; i < NTEMP; ++i) { - ++LENCOUNT[PREFLEN[i]]; - } - CURLEN = 1; - FIRSTCODE[0] = 0; - LENCOUNT[0] = 0; - while (CURLEN <= LENMAX) { - FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1; - CURCODE = FIRSTCODE[CURLEN]; - CURTEMP = 0; - while (CURTEMP < NTEMP) { - if (PREFLEN[CURTEMP] == CURLEN) { - CODES[CURTEMP] = CURCODE; - CURCODE = CURCODE + 1; - } - CURTEMP = CURTEMP + 1; - } - CURLEN = CURLEN + 1; - } - FX_Free(LENCOUNT); - FX_Free(FIRSTCODE); + huffman_assign_code(SBSYMCODES.data(), SBNUMSYMS); + return SBSYMCODES; } void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES, int NTEMP) { - int CURLEN, LENMAX, CURCODE, CURTEMP, i; - int* LENCOUNT; - int* FIRSTCODE; - LENMAX = 0; - for (i = 0; i < NTEMP; ++i) { - if (SBSYMCODES[i].codelen > LENMAX) { - LENMAX = SBSYMCODES[i].codelen; - } - } - LENCOUNT = FX_Alloc(int, (LENMAX + 1)); - JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1)); - FIRSTCODE = FX_Alloc(int, (LENMAX + 1)); - for (i = 0; i < NTEMP; ++i) { + // TODO(thestig) CJBig2_HuffmanTable::parseFromCodedBuffer() has similar code. + int LENMAX = 0; + for (int i = 0; i < NTEMP; ++i) + LENMAX = std::max(LENMAX, SBSYMCODES[i].codelen); + std::vector LENCOUNT(LENMAX + 1); + std::vector FIRSTCODE(LENMAX + 1); + for (int i = 0; i < NTEMP; ++i) ++LENCOUNT[SBSYMCODES[i].codelen]; - } - CURLEN = 1; - FIRSTCODE[0] = 0; LENCOUNT[0] = 0; - while (CURLEN <= LENMAX) { + for (int CURLEN = 1; CURLEN <= LENMAX; ++CURLEN) { FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1; - CURCODE = FIRSTCODE[CURLEN]; - CURTEMP = 0; - while (CURTEMP < NTEMP) { + int CURCODE = FIRSTCODE[CURLEN]; + for (int CURTEMP = 0; CURTEMP < NTEMP; ++CURTEMP) { if (SBSYMCODES[CURTEMP].codelen == CURLEN) { SBSYMCODES[CURTEMP].code = CURCODE; CURCODE = CURCODE + 1; } - CURTEMP = CURTEMP + 1; } - CURLEN = CURLEN + 1; } - FX_Free(LENCOUNT); - FX_Free(FIRSTCODE); } diff --git a/core/fxcodec/jbig2/JBig2_Context.h b/core/fxcodec/jbig2/JBig2_Context.h index cd44a82c61d6d71b9ffe52ccfde26d3a0babd3ed..f86aa2ea1d52fd89af2a12a002e1c255aed861f5 100644 --- a/core/fxcodec/jbig2/JBig2_Context.h +++ b/core/fxcodec/jbig2/JBig2_Context.h @@ -16,11 +16,12 @@ #include "core/fxcodec/fx_codec_def.h" #include "core/fxcodec/jbig2/JBig2_Page.h" #include "core/fxcodec/jbig2/JBig2_Segment.h" +#include "core/fxcrt/fx_safe_types.h" class CJBig2_ArithDecoder; class CJBig2_GRDProc; class CPDF_StreamAcc; -class IFX_Pause; +class IFX_PauseIndicator; // Cache is keyed by the ObjNum of a stream and an index within the stream. using CJBig2_CacheKey = std::pair; @@ -33,17 +34,14 @@ using CJBig2_CachePair = #define JBIG2_ERROR_FATAL -3 #define JBIG2_END_OF_PAGE 2 #define JBIG2_END_OF_FILE 3 -#define JBIG2_ERROR_FILE_FORMAT -4 -#define JBIG2_ERROR_STREAM_TYPE -5 #define JBIG2_ERROR_LIMIT -6 #define JBIG2_MIN_SEGMENT_SIZE 11 class CJBig2_Context { public: - CJBig2_Context(CPDF_StreamAcc* pGlobalStream, - CPDF_StreamAcc* pSrcStream, + CJBig2_Context(const RetainPtr& pGlobalStream, + const RetainPtr& pSrcStream, std::list* pSymbolDictCache, - IFX_Pause* pPause, bool bIsGlobal); ~CJBig2_Context(); @@ -51,16 +49,15 @@ class CJBig2_Context { int32_t width, int32_t height, int32_t stride, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); - int32_t Continue(IFX_Pause* pPause); - FXCODEC_STATUS GetProcessingStatus() { return m_ProcessingStatus; } + int32_t Continue(IFX_PauseIndicator* pPause); + FXCODEC_STATUS GetProcessingStatus() const { return m_ProcessingStatus; } private: - int32_t decode_SquentialOrgnazation(IFX_Pause* pPause); - int32_t decode_EmbedOrgnazation(IFX_Pause* pPause); - int32_t decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause); - int32_t decode_RandomOrgnazation(IFX_Pause* pPause); + int32_t decodeSequential(IFX_PauseIndicator* pPause); + int32_t decodeRandomFirstPage(IFX_PauseIndicator* pPause); + int32_t decodeRandom(IFX_PauseIndicator* pPause); CJBig2_Segment* findSegmentByNumber(uint32_t dwNumber); CJBig2_Segment* findReferredSegmentByTypeAndIndex(CJBig2_Segment* pSegment, @@ -68,22 +65,26 @@ class CJBig2_Context { int32_t nIndex); int32_t parseSegmentHeader(CJBig2_Segment* pSegment); - int32_t parseSegmentData(CJBig2_Segment* pSegment, IFX_Pause* pPause); + int32_t parseSegmentData(CJBig2_Segment* pSegment, + IFX_PauseIndicator* pPause); int32_t ProcessingParseSegmentData(CJBig2_Segment* pSegment, - IFX_Pause* pPause); - int32_t parseSymbolDict(CJBig2_Segment* pSegment, IFX_Pause* pPause); + IFX_PauseIndicator* pPause); + int32_t parseSymbolDict(CJBig2_Segment* pSegment); int32_t parseTextRegion(CJBig2_Segment* pSegment); - int32_t parsePatternDict(CJBig2_Segment* pSegment, IFX_Pause* pPause); - int32_t parseHalftoneRegion(CJBig2_Segment* pSegment, IFX_Pause* pPause); - int32_t parseGenericRegion(CJBig2_Segment* pSegment, IFX_Pause* pPause); + int32_t parsePatternDict(CJBig2_Segment* pSegment, + IFX_PauseIndicator* pPause); + int32_t parseHalftoneRegion(CJBig2_Segment* pSegment, + IFX_PauseIndicator* pPause); + int32_t parseGenericRegion(CJBig2_Segment* pSegment, + IFX_PauseIndicator* pPause); int32_t parseGenericRefinementRegion(CJBig2_Segment* pSegment); int32_t parseTable(CJBig2_Segment* pSegment); int32_t parseRegionInfo(JBig2RegionInfo* pRI); - JBig2HuffmanCode* decodeSymbolIDHuffmanTable(CJBig2_BitStream* pStream, - uint32_t SBNUMSYMS); + std::vector decodeSymbolIDHuffmanTable( + CJBig2_BitStream* pStream, + uint32_t SBNUMSYMS); - void huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP); void huffman_assign_code(JBig2HuffmanCode* SBSYMCODES, int NTEMP); std::unique_ptr m_pGlobalContext; @@ -95,13 +96,12 @@ class CJBig2_Context { bool m_bInPage; bool m_bBufSpecified; int32_t m_PauseStep; - IFX_Pause* const m_pPause; FXCODEC_STATUS m_ProcessingStatus; std::vector m_gbContext; std::unique_ptr m_pArithDecoder; std::unique_ptr m_pGRD; std::unique_ptr m_pSegment; - uint32_t m_dwOffset; + FX_SAFE_UINT32 m_dwOffset; JBig2RegionInfo m_ri; std::list* const m_pSymbolDictCache; bool m_bIsGlobal; diff --git a/core/fxcodec/jbig2/JBig2_Define.h b/core/fxcodec/jbig2/JBig2_Define.h index 86df248786b7aa197db8b908e76e225ea4696121..6fc3434ac74d28a19ab3d648a775400e2c413397 100644 --- a/core/fxcodec/jbig2/JBig2_Define.h +++ b/core/fxcodec/jbig2/JBig2_Define.h @@ -9,9 +9,8 @@ #include "core/fxcrt/fx_system.h" -#define JBIG2_memset FXSYS_memset -#define JBIG2_memcmp FXSYS_memcmp -#define JBIG2_memcpy FXSYS_memcpy +#define JBIG2_memset memset +#define JBIG2_memcpy memcpy #define JBIG2_OOB 1 struct JBig2RegionInfo { diff --git a/core/fxcodec/jbig2/JBig2_GrdProc.cpp b/core/fxcodec/jbig2/JBig2_GrdProc.cpp index 8c6d58e5119e29ea8fe4b5cd5f91280d9299beb1..e308ae35ee44d03bfb361383fbc519aa49facec0 100644 --- a/core/fxcodec/jbig2/JBig2_GrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_GrdProc.cpp @@ -7,16 +7,18 @@ #include "core/fxcodec/jbig2/JBig2_GrdProc.h" #include +#include #include "core/fxcodec/fx_codec.h" #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h" #include "core/fxcodec/jbig2/JBig2_BitStream.h" #include "core/fxcodec/jbig2/JBig2_Image.h" +#include "core/fxcrt/ifx_pauseindicator.h" +#include "third_party/base/ptr_util.h" CJBig2_GRDProc::CJBig2_GRDProc() : m_loopIndex(0), m_pLine(nullptr), - m_pPause(nullptr), m_DecodeType(0), m_LTP(0) { m_ReplaceRect.left = 0; @@ -25,6 +27,8 @@ CJBig2_GRDProc::CJBig2_GRDProc() m_ReplaceRect.right = 0; } +CJBig2_GRDProc::~CJBig2_GRDProc() {} + bool CJBig2_GRDProc::UseTemplate0Opt3() const { return (GBAT[0] == 3) && (GBAT[1] == -1) && (GBAT[2] == -3) && (GBAT[3] == -1) && (GBAT[4] == 2) && (GBAT[5] == -2) && @@ -39,10 +43,13 @@ bool CJBig2_GRDProc::UseTemplate23Opt3() const { return (GBAT[0] == 2) && (GBAT[1] == -1); } -CJBig2_Image* CJBig2_GRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext) { - if (GBW == 0 || GBH == 0) - return new CJBig2_Image(GBW, GBH); +std::unique_ptr CJBig2_GRDProc::decode_Arith( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext) { + if (GBW == 0 || GBW > JBIG2_MAX_IMAGE_SIZE || GBH == 0 || + GBH > JBIG2_MAX_IMAGE_SIZE) { + return pdfium::MakeUnique(GBW, GBH); + } if (GBTEMPLATE == 0) { if (UseTemplate0Opt3()) @@ -62,23 +69,28 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, return decode_Arith_Template3_unopt(pArithDecoder, gbContext); } } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( + +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template0_opt3( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); - if (!GBREG->m_pData) + auto GBREG = pdfium::MakeUnique(GBW, GBH); + if (!GBREG->data()) return nullptr; int LTP = 0; - uint8_t* pLine = GBREG->m_pData; + uint8_t* pLine = GBREG->data(); int32_t nStride = GBREG->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); uint32_t height = GBH & 0x7fffffff; for (uint32_t h = 0; h < height; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]); + } if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -93,6 +105,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( line2 = (line2 << 8) | (*pLine2++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal | @@ -104,6 +119,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = @@ -121,6 +139,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( } uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = @@ -131,6 +152,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal | @@ -141,18 +165,22 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( } pLine += nStride; } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_unopt( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template0_unopt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { int LTP = 0; - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); + auto GBREG = pdfium::MakeUnique(GBW, GBH); GBREG->fill(0); for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]); + } if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -174,6 +202,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_unopt( CONTEXT |= GBREG->getPixel(w + GBAT[4], h + GBAT[5]) << 11; CONTEXT |= line1 << 12; CONTEXT |= GBREG->getPixel(w + GBAT[6], h + GBAT[7]) << 15; + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -185,25 +216,29 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_unopt( } } } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template1_opt3( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); - if (!GBREG->m_pData) + auto GBREG = pdfium::MakeUnique(GBW, GBH); + if (!GBREG->data()) return nullptr; int LTP = 0; - uint8_t* pLine = GBREG->m_pData; + uint8_t* pLine = GBREG->data(); int32_t nStride = GBREG->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]); + } if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -218,6 +253,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( line2 = (line2 << 8) | (*pLine2++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal | @@ -229,6 +267,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal | @@ -246,6 +287,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( } uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal | @@ -256,6 +300,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = @@ -266,18 +313,22 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( } pLine += nStride; } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_unopt( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template1_unopt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { int LTP = 0; - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); + auto GBREG = pdfium::MakeUnique(GBW, GBH); GBREG->fill(0); for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]); + } if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -297,6 +348,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_unopt( CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 3; CONTEXT |= line2 << 4; CONTEXT |= line1 << 9; + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -308,25 +362,29 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_unopt( } } } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template2_opt3( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); - if (!GBREG->m_pData) + auto GBREG = pdfium::MakeUnique(GBW, GBH); + if (!GBREG->data()) return nullptr; int LTP = 0; - uint8_t* pLine = GBREG->m_pData; + uint8_t* pLine = GBREG->data(); int32_t nStride = GBREG->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]); + } if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -341,6 +399,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( line2 = (line2 << 8) | (*pLine2++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -352,6 +413,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -369,6 +433,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( } uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -379,6 +446,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -389,18 +459,22 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( } pLine += nStride; } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_unopt( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template2_unopt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { int LTP = 0; - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); + auto GBREG = pdfium::MakeUnique(GBW, GBH); GBREG->fill(0); for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]); + } if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -418,6 +492,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_unopt( CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 2; CONTEXT |= line2 << 3; CONTEXT |= line1 << 7; + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -429,24 +506,30 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_unopt( } } } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template3_opt3( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); - if (!GBREG->m_pData) + auto GBREG = pdfium::MakeUnique(GBW, GBH); + if (!GBREG->data()) return nullptr; int LTP = 0; - uint8_t* pLine = GBREG->m_pData; + uint8_t* pLine = GBREG->data(); int32_t nStride = GBREG->stride(); int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); + for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]); + } + if (LTP) { GBREG->copyLine(h, h - 1); } else { @@ -458,6 +541,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( line1 = (line1 << 8) | (*pLine1++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal | @@ -468,6 +554,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( line1 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = @@ -479,6 +568,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( for (int32_t cc = 0; cc < nLineBytes; cc++) { uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal; @@ -487,6 +579,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( } uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal; @@ -496,18 +591,22 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( } pLine += nStride; } - return GBREG.release(); + return GBREG; } -CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_unopt( +std::unique_ptr CJBig2_GRDProc::decode_Arith_Template3_unopt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext) { int LTP = 0; - std::unique_ptr GBREG(new CJBig2_Image(GBW, GBH)); + auto GBREG = pdfium::MakeUnique(GBW, GBH); GBREG->fill(0); for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]); + } if (LTP == 1) { GBREG->copyLine(h, h - 1); } else { @@ -522,6 +621,9 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_unopt( uint32_t CONTEXT = line2; CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4; CONTEXT |= line1 << 5; + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -532,108 +634,108 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_unopt( } } } - return GBREG.release(); + return GBREG; } FXCODEC_STATUS CJBig2_GRDProc::Start_decode_Arith( - CJBig2_Image** pImage, + std::unique_ptr* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { - if (GBW == 0 || GBH == 0) { + IFX_PauseIndicator* pPause) { + if (GBW == 0 || GBW > JBIG2_MAX_IMAGE_SIZE || GBH == 0 || + GBH > JBIG2_MAX_IMAGE_SIZE) { m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH; return FXCODEC_STATUS_DECODE_FINISH; } m_ProssiveStatus = FXCODEC_STATUS_DECODE_READY; - m_pPause = pPause; if (!*pImage) - *pImage = new CJBig2_Image(GBW, GBH); - if (!(*pImage)->m_pData) { - delete *pImage; + *pImage = pdfium::MakeUnique(GBW, GBH); + if (!(*pImage)->data()) { *pImage = nullptr; m_ProssiveStatus = FXCODEC_STATUS_ERROR; return FXCODEC_STATUS_ERROR; } m_DecodeType = 1; - m_pImage = pImage; - (*m_pImage)->fill(0); - m_pArithDecoder = pArithDecoder; + m_pImage = pImage->get(); + m_pImage->fill(0); m_gbContext = gbContext; m_LTP = 0; m_pLine = nullptr; m_loopIndex = 0; - return decode_Arith(pPause); + return decode_Arith(pPause, pArithDecoder); } -FXCODEC_STATUS CJBig2_GRDProc::decode_Arith(IFX_Pause* pPause) { +FXCODEC_STATUS CJBig2_GRDProc::decode_Arith( + IFX_PauseIndicator* pPause, + CJBig2_ArithDecoder* pArithDecoder) { int iline = m_loopIndex; - CJBig2_Image* pImage = *m_pImage; if (GBTEMPLATE == 0) { if (UseTemplate0Opt3()) { - m_ProssiveStatus = decode_Arith_Template0_opt3(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template0_opt3(m_pImage, pArithDecoder, m_gbContext, pPause); } else { - m_ProssiveStatus = decode_Arith_Template0_unopt(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template0_unopt(m_pImage, pArithDecoder, m_gbContext, pPause); } } else if (GBTEMPLATE == 1) { if (UseTemplate1Opt3()) { - m_ProssiveStatus = decode_Arith_Template1_opt3(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template1_opt3(m_pImage, pArithDecoder, m_gbContext, pPause); } else { - m_ProssiveStatus = decode_Arith_Template1_unopt(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template1_unopt(m_pImage, pArithDecoder, m_gbContext, pPause); } } else if (GBTEMPLATE == 2) { if (UseTemplate23Opt3()) { - m_ProssiveStatus = decode_Arith_Template2_opt3(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template2_opt3(m_pImage, pArithDecoder, m_gbContext, pPause); } else { - m_ProssiveStatus = decode_Arith_Template2_unopt(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template2_unopt(m_pImage, pArithDecoder, m_gbContext, pPause); } } else { if (UseTemplate23Opt3()) { - m_ProssiveStatus = decode_Arith_Template3_opt3(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template3_opt3(m_pImage, pArithDecoder, m_gbContext, pPause); } else { - m_ProssiveStatus = decode_Arith_Template3_unopt(pImage, m_pArithDecoder, + m_ProssiveStatus = decode_Arith_Template3_unopt(m_pImage, pArithDecoder, m_gbContext, pPause); } } m_ReplaceRect.left = 0; - m_ReplaceRect.right = pImage->width(); + m_ReplaceRect.right = m_pImage->width(); m_ReplaceRect.top = iline; m_ReplaceRect.bottom = m_loopIndex; - if (m_ProssiveStatus == FXCODEC_STATUS_DECODE_FINISH) { + if (m_ProssiveStatus == FXCODEC_STATUS_DECODE_FINISH) m_loopIndex = 0; - } + return m_ProssiveStatus; } -FXCODEC_STATUS CJBig2_GRDProc::Start_decode_MMR(CJBig2_Image** pImage, - CJBig2_BitStream* pStream, - IFX_Pause* pPause) { +FXCODEC_STATUS CJBig2_GRDProc::Start_decode_MMR( + std::unique_ptr* pImage, + CJBig2_BitStream* pStream) { int bitpos, i; - *pImage = new CJBig2_Image(GBW, GBH); - if (!(*pImage)->m_pData) { - delete (*pImage); - (*pImage) = nullptr; + auto image = pdfium::MakeUnique(GBW, GBH); + if (!image->data()) { + *pImage = nullptr; m_ProssiveStatus = FXCODEC_STATUS_ERROR; return m_ProssiveStatus; } - bitpos = (int)pStream->getBitPos(); - FaxG4Decode(pStream->getBuf(), pStream->getLength(), &bitpos, - (*pImage)->m_pData, GBW, GBH, (*pImage)->stride()); + bitpos = static_cast(pStream->getBitPos()); + FaxG4Decode(pStream->getBuf(), pStream->getLength(), &bitpos, image->data(), + GBW, GBH, image->stride()); pStream->setBitPos(bitpos); - for (i = 0; (uint32_t)i < (*pImage)->stride() * GBH; i++) { - (*pImage)->m_pData[i] = ~(*pImage)->m_pData[i]; - } + for (i = 0; (uint32_t)i < image->stride() * GBH; ++i) + image->data()[i] = ~image->data()[i]; m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH; + *pImage = std::move(image); return m_ProssiveStatus; } -FXCODEC_STATUS CJBig2_GRDProc::Continue_decode(IFX_Pause* pPause) { +FXCODEC_STATUS CJBig2_GRDProc::Continue_decode( + IFX_PauseIndicator* pPause, + CJBig2_ArithDecoder* pArithDecoder) { if (m_ProssiveStatus != FXCODEC_STATUS_DECODE_TOBECONTINUE) return m_ProssiveStatus; @@ -641,26 +743,29 @@ FXCODEC_STATUS CJBig2_GRDProc::Continue_decode(IFX_Pause* pPause) { m_ProssiveStatus = FXCODEC_STATUS_ERROR; return m_ProssiveStatus; } - - return decode_Arith(pPause); + return decode_Arith(pPause, pArithDecoder); } FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { - if (!m_pLine) { - m_pLine = pImage->m_pData; - } + IFX_PauseIndicator* pPause) { + if (!m_pLine) + m_pLine = pImage->data(); int32_t nStride = pImage->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); uint32_t height = GBH & 0x7fffffff; + for (; m_loopIndex < height; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -675,6 +780,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3( line2 = (line2 << 8) | (*pLine2++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal | @@ -686,6 +794,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = @@ -703,6 +814,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3( } uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = @@ -713,6 +827,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal | @@ -736,10 +853,14 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { for (; m_loopIndex < GBH; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x9b25]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -761,6 +882,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_unopt( CONTEXT |= pImage->getPixel(w + GBAT[4], m_loopIndex + GBAT[5]) << 11; CONTEXT |= line1 << 12; CONTEXT |= pImage->getPixel(w + GBAT[6], m_loopIndex + GBAT[7]) << 15; + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -787,17 +911,20 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { - if (!m_pLine) { - m_pLine = pImage->m_pData; - } + IFX_PauseIndicator* pPause) { + if (!m_pLine) + m_pLine = pImage->data(); int32_t nStride = pImage->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (; m_loopIndex < GBH; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -812,6 +939,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3( line2 = (line2 << 8) | (*pLine2++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal | @@ -823,6 +953,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal | @@ -840,6 +973,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3( } uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal | @@ -850,6 +986,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = @@ -873,10 +1012,14 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { for (uint32_t h = 0; h < GBH; h++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0795]); + } if (m_LTP) { pImage->copyLine(h, h - 1); } else { @@ -896,6 +1039,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_unopt( CONTEXT |= pImage->getPixel(w + GBAT[0], h + GBAT[1]) << 3; CONTEXT |= line2 << 4; CONTEXT |= line1 << 9; + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -920,17 +1066,20 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { - if (!m_pLine) { - m_pLine = pImage->m_pData; - } + IFX_PauseIndicator* pPause) { + if (!m_pLine) + m_pLine = pImage->data(); int32_t nStride = pImage->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (; m_loopIndex < GBH; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -945,6 +1094,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3( line2 = (line2 << 8) | (*pLine2++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -956,6 +1108,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -973,6 +1128,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3( } uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -983,6 +1141,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3( line2 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal | @@ -1006,10 +1167,14 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { for (; m_loopIndex < GBH; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x00e5]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -1027,6 +1192,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_unopt( CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 2; CONTEXT |= line2 << 3; CONTEXT |= line1 << 7; + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { @@ -1053,16 +1221,19 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { if (!m_pLine) - m_pLine = pImage->m_pData; - + m_pLine = pImage->data(); int32_t nStride = pImage->stride(); int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (; m_loopIndex < GBH; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -1074,6 +1245,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3( line1 = (line1 << 8) | (*pLine1++); uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal | @@ -1084,6 +1258,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3( line1 <<= 8; uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = @@ -1095,6 +1272,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3( for (int32_t cc = 0; cc < nLineBytes; cc++) { uint8_t cVal = 0; for (int32_t k = 7; k >= 0; k--) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal |= bVal << k; CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal; @@ -1103,6 +1283,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3( } uint8_t cVal1 = 0; for (int32_t k = 0; k < nBitsLeft; k++) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + int bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); cVal1 |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal; @@ -1125,10 +1308,14 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { for (; m_loopIndex < GBH; m_loopIndex++) { - if (TPGDON) + if (TPGDON) { + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + m_LTP = m_LTP ^ pArithDecoder->DECODE(&gbContext[0x0195]); + } if (m_LTP) { pImage->copyLine(m_loopIndex, m_loopIndex - 1); } else { @@ -1143,6 +1330,9 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_unopt( uint32_t CONTEXT = line2; CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4; CONTEXT |= line1 << 5; + if (pArithDecoder->IsComplete()) + return FXCODEC_STATUS_ERROR; + bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]); } if (bVal) { diff --git a/core/fxcodec/jbig2/JBig2_GrdProc.h b/core/fxcodec/jbig2/JBig2_GrdProc.h index a82aecbf12011e59953cb5d83be48049889bc8e9..79992adcba44211b88e589e87b6c3925e466f5e1 100644 --- a/core/fxcodec/jbig2/JBig2_GrdProc.h +++ b/core/fxcodec/jbig2/JBig2_GrdProc.h @@ -7,31 +7,35 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_GRDPROC_H_ #define CORE_FXCODEC_JBIG2_JBIG2_GRDPROC_H_ +#include + #include "core/fxcodec/fx_codec_def.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CJBig2_ArithDecoder; class CJBig2_BitStream; class CJBig2_Image; -class IFX_Pause; +class IFX_PauseIndicator; struct JBig2ArithCtx; class CJBig2_GRDProc { public: CJBig2_GRDProc(); + ~CJBig2_GRDProc(); - CJBig2_Image* decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith(CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - FXCODEC_STATUS Start_decode_Arith(CJBig2_Image** pImage, + FXCODEC_STATUS Start_decode_Arith(std::unique_ptr* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); - FXCODEC_STATUS Start_decode_MMR(CJBig2_Image** pImage, - CJBig2_BitStream* pStream, - IFX_Pause* pPause); - FXCODEC_STATUS Continue_decode(IFX_Pause* pPause); + IFX_PauseIndicator* pPause); + FXCODEC_STATUS Start_decode_MMR(std::unique_ptr* pImage, + CJBig2_BitStream* pStream); + FXCODEC_STATUS Continue_decode(IFX_PauseIndicator* pPause, + CJBig2_ArithDecoder* pArithDecoder); FX_RECT GetReplaceRect() const { return m_ReplaceRect; } bool MMR; @@ -48,73 +52,80 @@ class CJBig2_GRDProc { bool UseTemplate1Opt3() const; bool UseTemplate23Opt3() const; - FXCODEC_STATUS decode_Arith(IFX_Pause* pPause); + FXCODEC_STATUS decode_Arith(IFX_PauseIndicator* pPause, + CJBig2_ArithDecoder* pArithDecoder); FXCODEC_STATUS decode_Arith_Template0_opt3(CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template0_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template1_opt3(CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template1_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template2_opt3(CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template2_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template3_opt3(CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + IFX_PauseIndicator* pPause); FXCODEC_STATUS decode_Arith_Template3_unopt( CJBig2_Image* pImage, CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause); - CJBig2_Image* decode_Arith_Template0_opt3(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + IFX_PauseIndicator* pPause); + std::unique_ptr decode_Arith_Template0_opt3( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template0_unopt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template0_unopt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template1_opt3(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template1_opt3( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template1_unopt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template1_unopt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template2_opt3(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template2_opt3( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template2_unopt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template2_unopt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template3_opt3(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template3_opt3( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); - CJBig2_Image* decode_Arith_Template3_unopt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext); + std::unique_ptr decode_Arith_Template3_unopt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext); uint32_t m_loopIndex; uint8_t* m_pLine; - IFX_Pause* m_pPause; FXCODEC_STATUS m_ProssiveStatus; - CJBig2_Image** m_pImage; - CJBig2_ArithDecoder* m_pArithDecoder; + CJBig2_Image* m_pImage; JBig2ArithCtx* m_gbContext; uint16_t m_DecodeType; int m_LTP; diff --git a/core/fxcodec/jbig2/JBig2_GrrdProc.cpp b/core/fxcodec/jbig2/JBig2_GrrdProc.cpp index 669fed68e9c14be18efb43c298df89cde52bb2a9..f5f569c04a4a16f85f6d1a8c4c9ae58f7e066a95 100644 --- a/core/fxcodec/jbig2/JBig2_GrrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_GrrdProc.cpp @@ -11,11 +11,15 @@ #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h" #include "core/fxcodec/jbig2/JBig2_BitStream.h" #include "core/fxcodec/jbig2/JBig2_Image.h" +#include "third_party/base/ptr_util.h" -CJBig2_Image* CJBig2_GRRDProc::decode(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext) { - if (GRW == 0 || GRH == 0) - return new CJBig2_Image(GRW, GRH); +std::unique_ptr CJBig2_GRRDProc::decode( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext) { + if (GRW == 0 || GRW > JBIG2_MAX_IMAGE_SIZE || GRH == 0 || + GRH > JBIG2_MAX_IMAGE_SIZE) { + return pdfium::MakeUnique(GRW, GRH); + } if (!GRTEMPLATE) { if ((GRAT[0] == -1) && (GRAT[1] == -1) && (GRAT[2] == -1) && @@ -28,83 +32,50 @@ CJBig2_Image* CJBig2_GRRDProc::decode(CJBig2_ArithDecoder* pArithDecoder, if ((GRREFERENCEDX == 0) && (GRW == (uint32_t)GRREFERENCE->width())) return decode_Template1_opt(pArithDecoder, grContext); + return decode_Template1_unopt(pArithDecoder, grContext); } -CJBig2_Image* CJBig2_GRRDProc::decode_Template0_unopt( +std::unique_ptr CJBig2_GRRDProc::decode_Template0_unopt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* grContext) { int LTP = 0; - std::unique_ptr GRREG(new CJBig2_Image(GRW, GRH)); + auto GRREG = pdfium::MakeUnique(GRW, GRH); GRREG->fill(0); for (uint32_t h = 0; h < GRH; h++) { - if (TPGRON) + if (TPGRON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0010]); + } + uint32_t lines[5]; + lines[0] = GRREG->getPixel(1, h - 1); + lines[0] |= GRREG->getPixel(0, h - 1) << 1; + lines[1] = 0; + lines[2] = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY - 1); + lines[2] |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1) + << 1; + lines[3] = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY); + lines[3] |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1; + lines[3] |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY) + << 2; + lines[4] = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1); + lines[4] |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1) + << 1; + lines[4] |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY + 1) + << 2; if (!LTP) { - uint32_t line1 = GRREG->getPixel(1, h - 1); - line1 |= GRREG->getPixel(0, h - 1) << 1; - uint32_t line2 = 0; - uint32_t line3 = - GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY - 1); - line3 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1) - << 1; - uint32_t line4 = - GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY); - line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1; - line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY) - << 2; - uint32_t line5 = - GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1); - line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1) - << 1; - line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY + 1) - << 2; for (uint32_t w = 0; w < GRW; w++) { - uint32_t CONTEXT = line5; - CONTEXT |= line4 << 3; - CONTEXT |= line3 << 6; - CONTEXT |= GRREFERENCE->getPixel(w - GRREFERENCEDX + GRAT[2], - h - GRREFERENCEDY + GRAT[3]) - << 8; - CONTEXT |= line2 << 9; - CONTEXT |= line1 << 10; - CONTEXT |= GRREG->getPixel(w + GRAT[0], h + GRAT[1]) << 12; + uint32_t CONTEXT = + decode_Template0_unopt_CalculateContext(*GRREG, lines, w, h); + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); - GRREG->setPixel(w, h, bVal); - line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x03; - line2 = ((line2 << 1) | bVal) & 0x01; - line3 = ((line3 << 1) | - GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, - h - GRREFERENCEDY - 1)) & - 0x03; - line4 = - ((line4 << 1) | - GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) & - 0x07; - line5 = ((line5 << 1) | - GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, - h - GRREFERENCEDY + 1)) & - 0x07; + decode_Template0_unopt_SetPixel(GRREG.get(), lines, w, h, bVal); } } else { - uint32_t line1 = GRREG->getPixel(1, h - 1); - line1 |= GRREG->getPixel(0, h - 1) << 1; - uint32_t line2 = 0; - uint32_t line3 = - GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY - 1); - line3 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1) - << 1; - uint32_t line4 = - GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY); - line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1; - line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY) - << 2; - uint32_t line5 = - GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1); - line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1) - << 1; - line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY + 1) - << 2; for (uint32_t w = 0; w < GRW; w++) { int bVal = GRREFERENCE->getPixel(w, h); if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w - 1, h - 1)) && @@ -115,53 +86,71 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template0_unopt( (bVal == GRREFERENCE->getPixel(w - 1, h + 1)) && (bVal == GRREFERENCE->getPixel(w, h + 1)) && (bVal == GRREFERENCE->getPixel(w + 1, h + 1)))) { - uint32_t CONTEXT = line5; - CONTEXT |= line4 << 3; - CONTEXT |= line3 << 6; - CONTEXT |= GRREFERENCE->getPixel(w - GRREFERENCEDX + GRAT[2], - h - GRREFERENCEDY + GRAT[3]) - << 8; - CONTEXT |= line2 << 9; - CONTEXT |= line1 << 10; - CONTEXT |= GRREG->getPixel(w + GRAT[0], h + GRAT[1]) << 12; + uint32_t CONTEXT = + decode_Template0_unopt_CalculateContext(*GRREG, lines, w, h); + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); } - GRREG->setPixel(w, h, bVal); - line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x03; - line2 = ((line2 << 1) | bVal) & 0x01; - line3 = ((line3 << 1) | - GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, - h - GRREFERENCEDY - 1)) & - 0x03; - line4 = - ((line4 << 1) | - GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) & - 0x07; - line5 = ((line5 << 1) | - GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, - h - GRREFERENCEDY + 1)) & - 0x07; + decode_Template0_unopt_SetPixel(GRREG.get(), lines, w, h, bVal); } } } - return GRREG.release(); + return GRREG; +} + +uint32_t CJBig2_GRRDProc::decode_Template0_unopt_CalculateContext( + const CJBig2_Image& GRREG, + const uint32_t* lines, + uint32_t w, + uint32_t h) const { + uint32_t CONTEXT = lines[4]; + CONTEXT |= lines[3] << 3; + CONTEXT |= lines[2] << 6; + CONTEXT |= GRREFERENCE->getPixel(w - GRREFERENCEDX + GRAT[2], + h - GRREFERENCEDY + GRAT[3]) + << 8; + CONTEXT |= lines[1] << 9; + CONTEXT |= lines[0] << 10; + CONTEXT |= GRREG.getPixel(w + GRAT[0], h + GRAT[1]) << 12; + return CONTEXT; } -CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt( +void CJBig2_GRRDProc::decode_Template0_unopt_SetPixel(CJBig2_Image* GRREG, + uint32_t* lines, + uint32_t w, + uint32_t h, + int bVal) { + GRREG->setPixel(w, h, bVal); + lines[0] = ((lines[0] << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x03; + lines[1] = ((lines[1] << 1) | bVal) & 0x01; + lines[2] = ((lines[2] << 1) | GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, + h - GRREFERENCEDY - 1)) & + 0x03; + lines[3] = ((lines[3] << 1) | + GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) & + 0x07; + lines[4] = ((lines[4] << 1) | GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, + h - GRREFERENCEDY + 1)) & + 0x07; +} + +std::unique_ptr CJBig2_GRRDProc::decode_Template0_opt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* grContext) { - if (!GRREFERENCE->m_pData) + if (!GRREFERENCE->data()) return nullptr; int32_t iGRW = static_cast(GRW); int32_t iGRH = static_cast(GRH); - std::unique_ptr GRREG(new CJBig2_Image(iGRW, iGRH)); - if (!GRREG->m_pData) + auto GRREG = pdfium::MakeUnique(iGRW, iGRH); + if (!GRREG->data()) return nullptr; int LTP = 0; - uint8_t* pLine = GRREG->m_pData; - uint8_t* pLineR = GRREFERENCE->m_pData; + uint8_t* pLine = GRREG->data(); + uint8_t* pLineR = GRREFERENCE->data(); intptr_t nStride = GRREG->stride(); intptr_t nStrideR = GRREFERENCE->stride(); int32_t GRWR = GRREFERENCE->width(); @@ -170,8 +159,12 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt( GRREFERENCEDY = 0; intptr_t nOffset = -GRREFERENCEDY * nStrideR; for (int32_t h = 0; h < iGRH; h++) { - if (TPGRON) + if (TPGRON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0010]); + } uint32_t line1 = (h > 0) ? pLine[-nStride] << 4 : 0; int32_t reference_h = h - GRREFERENCEDY; bool line1_r_ok = (reference_h > 0 && reference_h < GRHR + 1); @@ -213,6 +206,9 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt( } uint8_t cVal = 0; for (int32_t k = 0; k < nBits; k++) { + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); cVal |= bVal << (7 - k); CONTEXT = ((CONTEXT & 0x0cdb) << 1) | (bVal << 9) | @@ -259,6 +255,9 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt( (bVal == GRREFERENCE->getPixel(w + k - 1, h + 1)) && (bVal == GRREFERENCE->getPixel(w + k, h + 1)) && (bVal == GRREFERENCE->getPixel(w + k + 1, h + 1)))) { + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); } cVal |= bVal << (7 - k); @@ -272,22 +271,25 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt( } } pLine += nStride; - if (h < GRHR + GRREFERENCEDY) { + if (h < GRHR + GRREFERENCEDY) pLineR += nStrideR; - } } - return GRREG.release(); + return GRREG; } -CJBig2_Image* CJBig2_GRRDProc::decode_Template1_unopt( +std::unique_ptr CJBig2_GRRDProc::decode_Template1_unopt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* grContext) { int LTP = 0; - std::unique_ptr GRREG(new CJBig2_Image(GRW, GRH)); + auto GRREG = pdfium::MakeUnique(GRW, GRH); GRREG->fill(0); for (uint32_t h = 0; h < GRH; h++) { - if (TPGRON) + if (TPGRON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0008]); + } if (!LTP) { uint32_t line1 = GRREG->getPixel(1, h - 1); line1 |= GRREG->getPixel(0, h - 1) << 1; @@ -310,6 +312,9 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_unopt( CONTEXT |= line3 << 5; CONTEXT |= line2 << 6; CONTEXT |= line1 << 7; + if (pArithDecoder->IsComplete()) + return nullptr; + int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); GRREG->setPixel(w, h, bVal); line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x07; @@ -358,6 +363,9 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_unopt( CONTEXT |= line3 << 5; CONTEXT |= line2 << 6; CONTEXT |= line1 << 7; + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); } GRREG->setPixel(w, h, bVal); @@ -378,24 +386,24 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_unopt( } } } - return GRREG.release(); + return GRREG; } -CJBig2_Image* CJBig2_GRRDProc::decode_Template1_opt( +std::unique_ptr CJBig2_GRRDProc::decode_Template1_opt( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* grContext) { - if (!GRREFERENCE->m_pData) + if (!GRREFERENCE->data()) return nullptr; int32_t iGRW = static_cast(GRW); int32_t iGRH = static_cast(GRH); - std::unique_ptr GRREG(new CJBig2_Image(iGRW, iGRH)); - if (!GRREG->m_pData) + auto GRREG = pdfium::MakeUnique(iGRW, iGRH); + if (!GRREG->data()) return nullptr; int LTP = 0; - uint8_t* pLine = GRREG->m_pData; - uint8_t* pLineR = GRREFERENCE->m_pData; + uint8_t* pLine = GRREG->data(); + uint8_t* pLineR = GRREFERENCE->data(); intptr_t nStride = GRREG->stride(); intptr_t nStrideR = GRREFERENCE->stride(); int32_t GRWR = GRREFERENCE->width(); @@ -405,8 +413,12 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_opt( } intptr_t nOffset = -GRREFERENCEDY * nStrideR; for (int32_t h = 0; h < iGRH; h++) { - if (TPGRON) + if (TPGRON) { + if (pArithDecoder->IsComplete()) + return nullptr; + LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0008]); + } uint32_t line1 = (h > 0) ? pLine[-nStride] << 1 : 0; int32_t reference_h = h - GRREFERENCEDY; bool line1_r_ok = (reference_h > 0 && reference_h < GRHR + 1); @@ -482,6 +494,9 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_opt( (bVal == GRREFERENCE->getPixel(w + k - 1, h + 1)) && (bVal == GRREFERENCE->getPixel(w + k, h + 1)) && (bVal == GRREFERENCE->getPixel(w + k + 1, h + 1)))) { + if (pArithDecoder->IsComplete()) + return nullptr; + bVal = pArithDecoder->DECODE(&grContext[CONTEXT]); } cVal |= bVal << (7 - k); @@ -495,9 +510,8 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_opt( } } pLine += nStride; - if (h < GRHR + GRREFERENCEDY) { + if (h < GRHR + GRREFERENCEDY) pLineR += nStrideR; - } } - return GRREG.release(); + return GRREG; } diff --git a/core/fxcodec/jbig2/JBig2_GrrdProc.h b/core/fxcodec/jbig2/JBig2_GrrdProc.h index bdb49d7e9177c139d41b8d416e5a1313be4f3247..a9a14398fe05159470837a9e03ed92eb3eb1ff5a 100644 --- a/core/fxcodec/jbig2/JBig2_GrrdProc.h +++ b/core/fxcodec/jbig2/JBig2_GrrdProc.h @@ -7,6 +7,8 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_GRRDPROC_H_ #define CORE_FXCODEC_JBIG2_JBIG2_GRRDPROC_H_ +#include + #include "core/fxcrt/fx_system.h" class CJBig2_ArithDecoder; @@ -15,21 +17,9 @@ struct JBig2ArithCtx; class CJBig2_GRRDProc { public: - CJBig2_Image* decode(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext); - - CJBig2_Image* decode_Template0_unopt(CJBig2_ArithDecoder* pArithDecoder, + std::unique_ptr decode(CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* grContext); - CJBig2_Image* decode_Template0_opt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext); - - CJBig2_Image* decode_Template1_unopt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext); - - CJBig2_Image* decode_Template1_opt(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext); - uint32_t GRW; uint32_t GRH; bool GRTEMPLATE; @@ -38,6 +28,32 @@ class CJBig2_GRRDProc { int32_t GRREFERENCEDY; bool TPGRON; int8_t GRAT[4]; + + private: + std::unique_ptr decode_Template0_unopt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext); + uint32_t decode_Template0_unopt_CalculateContext(const CJBig2_Image& GRREG, + const uint32_t* lines, + uint32_t w, + uint32_t h) const; + void decode_Template0_unopt_SetPixel(CJBig2_Image* GRREG, + uint32_t* lines, + uint32_t w, + uint32_t h, + int bVal); + + std::unique_ptr decode_Template0_opt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext); + + std::unique_ptr decode_Template1_unopt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext); + + std::unique_ptr decode_Template1_opt( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext); }; #endif // CORE_FXCODEC_JBIG2_JBIG2_GRRDPROC_H_ diff --git a/core/fxcodec/jbig2/JBig2_GsidProc.cpp b/core/fxcodec/jbig2/JBig2_GsidProc.cpp deleted file mode 100644 index 387f8ee51151d7d3177502f2682262f95cdb9ba3..0000000000000000000000000000000000000000 --- a/core/fxcodec/jbig2/JBig2_GsidProc.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2015 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 "core/fxcodec/jbig2/JBig2_GsidProc.h" - -#include -#include - -#include "core/fxcodec/jbig2/JBig2_BitStream.h" -#include "core/fxcodec/jbig2/JBig2_GrdProc.h" -#include "core/fxcodec/jbig2/JBig2_Image.h" -#include "core/fxcrt/fx_basic.h" - -uint32_t* CJBig2_GSIDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { - std::unique_ptr pGRD(new CJBig2_GRDProc()); - pGRD->MMR = GSMMR; - pGRD->GBW = GSW; - pGRD->GBH = GSH; - pGRD->GBTEMPLATE = GSTEMPLATE; - pGRD->TPGDON = 0; - pGRD->USESKIP = GSUSESKIP; - pGRD->SKIP = GSKIP; - if (GSTEMPLATE <= 1) { - pGRD->GBAT[0] = 3; - } else { - pGRD->GBAT[0] = 2; - } - pGRD->GBAT[1] = -1; - if (pGRD->GBTEMPLATE == 0) { - pGRD->GBAT[2] = -3; - pGRD->GBAT[3] = -1; - pGRD->GBAT[4] = 2; - pGRD->GBAT[5] = -2; - pGRD->GBAT[6] = -2; - pGRD->GBAT[7] = -2; - } - - std::vector> GSPLANES(GSBPP); - for (int32_t i = GSBPP - 1; i >= 0; --i) { - CJBig2_Image* pImage = nullptr; - FXCODEC_STATUS status = - pGRD->Start_decode_Arith(&pImage, pArithDecoder, gbContext, nullptr); - while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) - status = pGRD->Continue_decode(pPause); - - if (!pImage) - return nullptr; - - GSPLANES[i].reset(pImage); - if (i < GSBPP - 1) - pImage->composeFrom(0, 0, GSPLANES[i + 1].get(), JBIG2_COMPOSE_XOR); - } - std::unique_ptr GSVALS( - FX_Alloc2D(uint32_t, GSW, GSH)); - JBIG2_memset(GSVALS.get(), 0, sizeof(uint32_t) * GSW * GSH); - for (uint32_t y = 0; y < GSH; ++y) { - for (uint32_t x = 0; x < GSW; ++x) { - for (int32_t i = 0; i < GSBPP; ++i) - GSVALS.get()[y * GSW + x] |= GSPLANES[i]->getPixel(x, y) << i; - } - } - return GSVALS.release(); -} - -uint32_t* CJBig2_GSIDProc::decode_MMR(CJBig2_BitStream* pStream, - IFX_Pause* pPause) { - std::unique_ptr pGRD(new CJBig2_GRDProc()); - pGRD->MMR = GSMMR; - pGRD->GBW = GSW; - pGRD->GBH = GSH; - - std::unique_ptr GSPLANES(FX_Alloc(CJBig2_Image*, GSBPP)); - JBIG2_memset(GSPLANES.get(), 0, sizeof(CJBig2_Image*) * GSBPP); - pGRD->Start_decode_MMR(&GSPLANES.get()[GSBPP - 1], pStream, nullptr); - if (!GSPLANES.get()[GSBPP - 1]) - return nullptr; - - pStream->alignByte(); - pStream->offset(3); - int32_t J = GSBPP - 2; - while (J >= 0) { - pGRD->Start_decode_MMR(&GSPLANES.get()[J], pStream, nullptr); - if (!GSPLANES.get()[J]) { - for (int32_t K = GSBPP - 1; K > J; --K) - delete GSPLANES.get()[K]; - return nullptr; - } - pStream->alignByte(); - pStream->offset(3); - GSPLANES.get()[J]->composeFrom(0, 0, GSPLANES.get()[J + 1], - JBIG2_COMPOSE_XOR); - J = J - 1; - } - std::unique_ptr GSVALS(FX_Alloc2D(uint32_t, GSW, GSH)); - JBIG2_memset(GSVALS.get(), 0, sizeof(uint32_t) * GSW * GSH); - for (uint32_t y = 0; y < GSH; ++y) { - for (uint32_t x = 0; x < GSW; ++x) { - for (J = 0; J < GSBPP; ++J) { - GSVALS.get()[y * GSW + x] |= GSPLANES.get()[J]->getPixel(x, y) << J; - } - } - } - for (J = 0; J < GSBPP; ++J) { - delete GSPLANES.get()[J]; - } - return GSVALS.release(); -} diff --git a/core/fxcodec/jbig2/JBig2_GsidProc.h b/core/fxcodec/jbig2/JBig2_GsidProc.h deleted file mode 100644 index 3d5dc2dd4a5ef52a23ed1f5fbd1e6167deb372f7..0000000000000000000000000000000000000000 --- a/core/fxcodec/jbig2/JBig2_GsidProc.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015 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 CORE_FXCODEC_JBIG2_JBIG2_GSIDPROC_H_ -#define CORE_FXCODEC_JBIG2_JBIG2_GSIDPROC_H_ - -#include "core/fxcrt/fx_system.h" - -class CJBig2_ArithDecoder; -class CJBig2_BitStream; -class CJBig2_Image; -class IFX_Pause; -struct JBig2ArithCtx; - -class CJBig2_GSIDProc { - public: - uint32_t* decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext, - IFX_Pause* pPause); - - uint32_t* decode_MMR(CJBig2_BitStream* pStream, IFX_Pause* pPause); - - public: - bool GSMMR; - bool GSUSESKIP; - uint8_t GSBPP; - uint32_t GSW; - uint32_t GSH; - uint8_t GSTEMPLATE; - CJBig2_Image* GSKIP; -}; - -#endif // CORE_FXCODEC_JBIG2_JBIG2_GSIDPROC_H_ diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp index 121bf1d6dfa803e35fc1a46363af0b8c17d11e98..bd1d92f2bef3cfa00abd716ac34b554d3287036c 100644 --- a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp @@ -6,30 +6,27 @@ #include "core/fxcodec/jbig2/JBig2_HtrdProc.h" -#include +#include +#include -#include "core/fxcodec/jbig2/JBig2_GsidProc.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcodec/jbig2/JBig2_BitStream.h" +#include "core/fxcodec/jbig2/JBig2_GrdProc.h" +#include "core/fxcodec/jbig2/JBig2_Image.h" #include "third_party/base/ptr_util.h" -CJBig2_Image* CJBig2_HTRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { - uint32_t ng, mg; - int32_t x, y; - uint32_t HBPP; - uint32_t* GI; +std::unique_ptr CJBig2_HTRDProc::decode_Arith( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext, + IFX_PauseIndicator* pPause) { std::unique_ptr HSKIP; - std::unique_ptr HTREG(new CJBig2_Image(HBW, HBH)); - HTREG->fill(HDEFPIXEL); if (HENABLESKIP == 1) { HSKIP = pdfium::MakeUnique(HGW, HGH); - for (mg = 0; mg < HGH; mg++) { - for (ng = 0; ng < HGW; ng++) { - x = (HGX + mg * HRY + ng * HRX) >> 8; - y = (HGY + mg * HRX - ng * HRY) >> 8; - if ((x + HPW <= 0) | (x >= (int32_t)HBW) | (y + HPH <= 0) | - (y >= (int32_t)HPH)) { + for (uint32_t mg = 0; mg < HGH; ++mg) { + for (uint32_t ng = 0; ng < HGW; ++ng) { + int32_t x = (HGX + mg * HRY + ng * HRX) >> 8; + int32_t y = (HGY + mg * HRX - ng * HRY) >> 8; + if ((x + HPW <= 0) | (x >= static_cast(HBW)) | (y + HPH <= 0) | + (y >= static_cast(HPH))) { HSKIP->setPixel(ng, mg, 1); } else { HSKIP->setPixel(ng, mg, 0); @@ -37,69 +34,100 @@ CJBig2_Image* CJBig2_HTRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, } } } - HBPP = 1; - while ((uint32_t)(1 << HBPP) < HNUMPATS) { - HBPP++; + uint32_t HBPP = 1; + while (static_cast(1 << HBPP) < HNUMPATS) + ++HBPP; + + CJBig2_GRDProc GRD; + GRD.MMR = HMMR; + GRD.GBW = HGW; + GRD.GBH = HGH; + GRD.GBTEMPLATE = HTEMPLATE; + GRD.TPGDON = 0; + GRD.USESKIP = HENABLESKIP; + GRD.SKIP = HSKIP.get(); + if (HTEMPLATE <= 1) + GRD.GBAT[0] = 3; + else + GRD.GBAT[0] = 2; + GRD.GBAT[1] = -1; + if (GRD.GBTEMPLATE == 0) { + GRD.GBAT[2] = -3; + GRD.GBAT[3] = -1; + GRD.GBAT[4] = 2; + GRD.GBAT[5] = -2; + GRD.GBAT[6] = -2; + GRD.GBAT[7] = -2; } - std::unique_ptr pGID(new CJBig2_GSIDProc()); - pGID->GSMMR = HMMR; - pGID->GSW = HGW; - pGID->GSH = HGH; - pGID->GSBPP = (uint8_t)HBPP; - pGID->GSUSESKIP = HENABLESKIP; - pGID->GSKIP = HSKIP.get(); - pGID->GSTEMPLATE = HTEMPLATE; - GI = pGID->decode_Arith(pArithDecoder, gbContext, pPause); - if (!GI) - return nullptr; - for (mg = 0; mg < HGH; mg++) { - for (ng = 0; ng < HGW; ng++) { - x = (HGX + mg * HRY + ng * HRX) >> 8; - y = (HGY + mg * HRX - ng * HRY) >> 8; - uint32_t pat_index = GI[mg * HGW + ng]; - if (pat_index >= HNUMPATS) { - pat_index = HNUMPATS - 1; - } - HTREG->composeFrom(x, y, HPATS[pat_index], HCOMBOP); - } + uint8_t GSBPP = static_cast(HBPP); + std::vector> GSPLANES(GSBPP); + for (int32_t i = GSBPP - 1; i >= 0; --i) { + std::unique_ptr pImage; + FXCODEC_STATUS status = + GRD.Start_decode_Arith(&pImage, pArithDecoder, gbContext, nullptr); + while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) + status = GRD.Continue_decode(pPause, pArithDecoder); + + if (!pImage) + return nullptr; + + GSPLANES[i] = std::move(pImage); + if (i < GSBPP - 1) + GSPLANES[i]->composeFrom(0, 0, GSPLANES[i + 1].get(), JBIG2_COMPOSE_XOR); } - FX_Free(GI); - return HTREG.release(); + return decode_image(GSPLANES); } -CJBig2_Image* CJBig2_HTRDProc::decode_MMR(CJBig2_BitStream* pStream, - IFX_Pause* pPause) { - uint32_t ng, mg; - int32_t x, y; - uint32_t* GI; - std::unique_ptr HTREG(new CJBig2_Image(HBW, HBH)); - HTREG->fill(HDEFPIXEL); +std::unique_ptr CJBig2_HTRDProc::decode_MMR( + CJBig2_BitStream* pStream) { uint32_t HBPP = 1; - while ((uint32_t)(1 << HBPP) < HNUMPATS) { - HBPP++; - } - std::unique_ptr pGID(new CJBig2_GSIDProc()); - pGID->GSMMR = HMMR; - pGID->GSW = HGW; - pGID->GSH = HGH; - pGID->GSBPP = (uint8_t)HBPP; - pGID->GSUSESKIP = 0; - GI = pGID->decode_MMR(pStream, pPause); - if (!GI) + while (static_cast(1 << HBPP) < HNUMPATS) + ++HBPP; + + CJBig2_GRDProc GRD; + GRD.MMR = HMMR; + GRD.GBW = HGW; + GRD.GBH = HGH; + + uint8_t GSBPP = static_cast(HBPP); + std::vector> GSPLANES(GSBPP); + GRD.Start_decode_MMR(&GSPLANES[GSBPP - 1], pStream); + if (!GSPLANES[GSBPP - 1]) return nullptr; - for (mg = 0; mg < HGH; mg++) { - for (ng = 0; ng < HGW; ng++) { - x = (HGX + mg * HRY + ng * HRX) >> 8; - y = (HGY + mg * HRX - ng * HRY) >> 8; - uint32_t pat_index = GI[mg * HGW + ng]; - if (pat_index >= HNUMPATS) { - pat_index = HNUMPATS - 1; - } - HTREG->composeFrom(x, y, HPATS[pat_index], HCOMBOP); + pStream->alignByte(); + pStream->offset(3); + for (int32_t J = GSBPP - 2; J >= 0; --J) { + GRD.Start_decode_MMR(&GSPLANES[J], pStream); + if (!GSPLANES[J]) + return nullptr; + + pStream->alignByte(); + pStream->offset(3); + GSPLANES[J]->composeFrom(0, 0, GSPLANES[J + 1].get(), JBIG2_COMPOSE_XOR); + } + return decode_image(GSPLANES); +} + +std::unique_ptr CJBig2_HTRDProc::decode_image( + const std::vector>& GSPLANES) { + auto HTREG = pdfium::MakeUnique(HBW, HBH); + HTREG->fill(HDEFPIXEL); + std::vector GSVALS(HGW * HGH); + for (uint32_t y = 0; y < HGH; ++y) { + for (uint32_t x = 0; x < HGW; ++x) { + for (uint8_t J = 0; J < GSPLANES.size(); ++J) + GSVALS[y * HGW + x] |= GSPLANES[J]->getPixel(x, y) << J; + } + } + for (uint32_t mg = 0; mg < HGH; ++mg) { + for (uint32_t ng = 0; ng < HGW; ++ng) { + int32_t x = (HGX + mg * HRY + ng * HRX) >> 8; + int32_t y = (HGY + mg * HRX - ng * HRY) >> 8; + uint32_t pat_index = std::min(GSVALS[mg * HGW + ng], HNUMPATS - 1); + HTREG->composeFrom(x, y, (*HPATS)[pat_index].get(), HCOMBOP); } } - FX_Free(GI); - return HTREG.release(); + return HTREG; } diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.h b/core/fxcodec/jbig2/JBig2_HtrdProc.h index 9a9a5c59c4bc96b270d54c994634301bdbb957cf..ed7cdbf2b5bfc41dc8a76b45817b14ea22714189 100644 --- a/core/fxcodec/jbig2/JBig2_HtrdProc.h +++ b/core/fxcodec/jbig2/JBig2_HtrdProc.h @@ -7,21 +7,24 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_HTRDPROC_H_ #define CORE_FXCODEC_JBIG2_JBIG2_HTRDPROC_H_ +#include +#include + #include "core/fxcodec/jbig2/JBig2_Image.h" #include "core/fxcrt/fx_system.h" class CJBig2_ArithDecoder; class CJBig2_BitStream; -class IFX_Pause; +class IFX_PauseIndicator; struct JBig2ArithCtx; class CJBig2_HTRDProc { public: - CJBig2_Image* decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + std::unique_ptr decode_Arith(CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext, + IFX_PauseIndicator* pPause); - CJBig2_Image* decode_MMR(CJBig2_BitStream* pStream, IFX_Pause* pPause); + std::unique_ptr decode_MMR(CJBig2_BitStream* pStream); public: uint32_t HBW; @@ -29,7 +32,7 @@ class CJBig2_HTRDProc { bool HMMR; uint8_t HTEMPLATE; uint32_t HNUMPATS; - CJBig2_Image** HPATS; + const std::vector>* HPATS; bool HDEFPIXEL; JBig2ComposeOp HCOMBOP; bool HENABLESKIP; @@ -41,6 +44,10 @@ class CJBig2_HTRDProc { uint16_t HRY; uint8_t HPW; uint8_t HPH; + + private: + std::unique_ptr decode_image( + const std::vector>& GSPLANES); }; #endif // CORE_FXCODEC_JBIG2_JBIG2_HTRDPROC_H_ diff --git a/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h b/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h index c72346ac1829d8b2f90395a0918c1a36cc262a8b..ac53b4d9c012e00fae31d82fbd442a5ac5f3c221 100644 --- a/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h +++ b/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h @@ -9,6 +9,8 @@ #include "core/fxcodec/jbig2/JBig2_BitStream.h" #include "core/fxcodec/jbig2/JBig2_HuffmanTable.h" +#include "core/fxcrt/unowned_ptr.h" + class CJBig2_HuffmanDecoder { public: explicit CJBig2_HuffmanDecoder(CJBig2_BitStream* pStream); @@ -18,7 +20,7 @@ class CJBig2_HuffmanDecoder { int decodeAValue(CJBig2_HuffmanTable* pTable, int* nResult); private: - CJBig2_BitStream* const m_pStream; + UnownedPtr const m_pStream; }; #endif // CORE_FXCODEC_JBIG2_JBIG2_HUFFMANDECODER_H_ diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp b/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp index baf97567fb79ecb7708ef64349968cbbf959321c..1127f52a52c7f4be72a1830f4f0456ffa0d72949 100644 --- a/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp +++ b/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp @@ -7,6 +7,7 @@ #include "core/fxcodec/jbig2/JBig2_HuffmanTable.h" #include +#include #include #include "core/fxcodec/jbig2/JBig2_BitStream.h" @@ -52,7 +53,9 @@ bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) { uint32_t HTLOW; uint32_t HTHIGH; if (pStream->readInteger(&HTLOW) == -1 || - pStream->readInteger(&HTHIGH) == -1) { + pStream->readInteger(&HTHIGH) == -1 || + HTLOW > static_cast(std::numeric_limits::max()) || + HTHIGH > static_cast(std::numeric_limits::max())) { return false; } @@ -70,6 +73,10 @@ bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) { return false; } RANGELOW[NTEMP] = cur_low.ValueOrDie(); + + if (RANGELEN[NTEMP] >= 32) + return false; + cur_low += (1 << RANGELEN[NTEMP]); if (!cur_low.IsValid()) return false; @@ -97,11 +104,10 @@ bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) { ++NTEMP; } - InitCodes(); - return true; + return InitCodes(); } -void CJBig2_HuffmanTable::InitCodes() { +bool CJBig2_HuffmanTable::InitCodes() { int lenmax = 0; for (uint32_t i = 0; i < NTEMP; ++i) lenmax = std::max(PREFLEN[i], lenmax); @@ -115,13 +121,21 @@ void CJBig2_HuffmanTable::InitCodes() { FIRSTCODE[0] = 0; LENCOUNT[0] = 0; for (int i = 1; i <= lenmax; ++i) { - FIRSTCODE[i] = (FIRSTCODE[i - 1] + LENCOUNT[i - 1]) << 1; + pdfium::base::CheckedNumeric shifted; + shifted = FIRSTCODE[i - 1] + LENCOUNT[i - 1]; + shifted <<= 1; + if (!shifted.IsValid()) + return false; + + FIRSTCODE[i] = shifted.ValueOrDie(); int CURCODE = FIRSTCODE[i]; for (uint32_t j = 0; j < NTEMP; ++j) { if (PREFLEN[j] == i) CODES[j] = CURCODE++; } } + + return true; } void CJBig2_HuffmanTable::ExtendBuffers(bool increment) { diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable.h b/core/fxcodec/jbig2/JBig2_HuffmanTable.h index 58a31248813346f52674c0346b5e55293ef32cdb..b49fcebc9c50ff36363e0962c896261259899888 100644 --- a/core/fxcodec/jbig2/JBig2_HuffmanTable.h +++ b/core/fxcodec/jbig2/JBig2_HuffmanTable.h @@ -35,7 +35,7 @@ class CJBig2_HuffmanTable { private: void ParseFromStandardTable(const JBig2TableLine* pTable); bool ParseFromCodedBuffer(CJBig2_BitStream* pStream); - void InitCodes(); + bool InitCodes(); void ExtendBuffers(bool increment); bool m_bOK; diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.cpp b/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.cpp index 4c2ba997d5570b85ae972acce3996e0cea02417d..abff7868e81a601810e5c74afb020e02809d30d8 100644 --- a/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.cpp +++ b/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.cpp @@ -5,7 +5,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h" -#include "core/fxcrt/fx_basic.h" + +#include "core/fxcrt/fx_memory.h" const bool HuffmanTable_HTOOB_B1 = false; const JBig2TableLine HuffmanTable_B1[] = {{1, 4, 0}, diff --git a/core/fxcodec/jbig2/JBig2_Image.cpp b/core/fxcodec/jbig2/JBig2_Image.cpp index 8f935ceb1f948ea8e812de7c6b0cd008220e4947..b0d75d4d96ec21c8ed8dd977f41f639ed2d3082b 100644 --- a/core/fxcodec/jbig2/JBig2_Image.cpp +++ b/core/fxcodec/jbig2/JBig2_Image.cpp @@ -4,11 +4,17 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +#include "core/fxcodec/jbig2/JBig2_Image.h" + #include -#include "core/fxcodec/jbig2/JBig2_Image.h" +#include +#include + #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_safe_types.h" +#include "third_party/base/ptr_util.h" namespace { @@ -18,11 +24,7 @@ const int kMaxImageBytes = kMaxImagePixels / 8; } // namespace CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) - : m_pData(nullptr), - m_nWidth(0), - m_nHeight(0), - m_nStride(0), - m_bOwnsBuffer(true) { + : m_pData(nullptr), m_nWidth(0), m_nHeight(0), m_nStride(0) { if (w <= 0 || h <= 0 || w > kMaxImagePixels) return; @@ -33,15 +35,12 @@ CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) m_nWidth = w; m_nHeight = h; m_nStride = stride_pixels / 8; - m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); + m_pData.Reset(std::unique_ptr( + FX_Alloc2D(uint8_t, m_nStride, m_nHeight))); } CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf) - : m_pData(nullptr), - m_nWidth(0), - m_nHeight(0), - m_nStride(0), - m_bOwnsBuffer(false) { + : m_pData(nullptr), m_nWidth(0), m_nHeight(0), m_nStride(0) { if (w < 0 || h < 0 || stride < 0 || stride > kMaxImageBytes) return; @@ -52,28 +51,24 @@ CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf) m_nWidth = w; m_nHeight = h; m_nStride = stride; - m_pData = pBuf; + m_pData.Reset(pBuf); } CJBig2_Image::CJBig2_Image(const CJBig2_Image& other) : m_pData(nullptr), m_nWidth(other.m_nWidth), m_nHeight(other.m_nHeight), - m_nStride(other.m_nStride), - m_bOwnsBuffer(true) { + m_nStride(other.m_nStride) { if (other.m_pData) { - m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); - JBIG2_memcpy(m_pData, other.m_pData, m_nStride * m_nHeight); + m_pData.Reset(std::unique_ptr( + FX_Alloc2D(uint8_t, m_nStride, m_nHeight))); + JBIG2_memcpy(data(), other.data(), m_nStride * m_nHeight); } } -CJBig2_Image::~CJBig2_Image() { - if (m_bOwnsBuffer) { - FX_Free(m_pData); - } -} +CJBig2_Image::~CJBig2_Image() {} -int CJBig2_Image::getPixel(int32_t x, int32_t y) { +int CJBig2_Image::getPixel(int32_t x, int32_t y) const { if (!m_pData) return 0; @@ -85,7 +80,7 @@ int CJBig2_Image::getPixel(int32_t x, int32_t y) { int32_t m = y * m_nStride + (x >> 3); int32_t n = x & 7; - return ((m_pData[m] >> (7 - n)) & 1); + return ((data()[m] >> (7 - n)) & 1); } int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, int v) { @@ -101,37 +96,37 @@ int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, int v) { int32_t m = y * m_nStride + (x >> 3); int32_t n = x & 7; if (v) - m_pData[m] |= 1 << (7 - n); + data()[m] |= 1 << (7 - n); else - m_pData[m] &= ~(1 << (7 - n)); + data()[m] &= ~(1 << (7 - n)); return 1; } void CJBig2_Image::copyLine(int32_t hTo, int32_t hFrom) { - if (!m_pData) { + if (!m_pData) return; - } + if (hFrom < 0 || hFrom >= m_nHeight) { - JBIG2_memset(m_pData + hTo * m_nStride, 0, m_nStride); + JBIG2_memset(data() + hTo * m_nStride, 0, m_nStride); } else { - JBIG2_memcpy(m_pData + hTo * m_nStride, m_pData + hFrom * m_nStride, + JBIG2_memcpy(data() + hTo * m_nStride, data() + hFrom * m_nStride, m_nStride); } } void CJBig2_Image::fill(bool v) { - if (!m_pData) { + if (!m_pData) return; - } - JBIG2_memset(m_pData, v ? 0xff : 0, m_nStride * m_nHeight); + + JBIG2_memset(data(), v ? 0xff : 0, m_nStride * m_nHeight); } bool CJBig2_Image::composeTo(CJBig2_Image* pDst, int32_t x, int32_t y, JBig2ComposeOp op) { - if (!m_pData) { + if (!m_pData) return false; - } + return composeTo_opt2(pDst, x, y, op); } bool CJBig2_Image::composeTo(CJBig2_Image* pDst, @@ -152,9 +147,9 @@ bool CJBig2_Image::composeFrom(int32_t x, int32_t y, CJBig2_Image* pSrc, JBig2ComposeOp op) { - if (!m_pData) { + if (!m_pData) return false; - } + return pSrc->composeTo(this, x, y, op); } bool CJBig2_Image::composeFrom(int32_t x, @@ -162,34 +157,39 @@ bool CJBig2_Image::composeFrom(int32_t x, CJBig2_Image* pSrc, JBig2ComposeOp op, const FX_RECT* pSrcRect) { - if (!m_pData) { - return false; - } - return pSrc->composeTo(this, x, y, op, pSrcRect); + return m_pData ? pSrc->composeTo(this, x, y, op, pSrcRect) : false; } + #define JBIG2_GETDWORD(buf) \ ((uint32_t)(((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3])) -CJBig2_Image* CJBig2_Image::subImage(int32_t x, - int32_t y, - int32_t w, - int32_t h) { - int32_t m, n, j; - uint8_t *pLineSrc, *pLineDst; + +std::unique_ptr CJBig2_Image::subImage(int32_t x, + int32_t y, + int32_t w, + int32_t h) { + int32_t m; + int32_t n; + int32_t j; + uint8_t* pLineSrc; + uint8_t* pLineDst; uint32_t wTmp; - uint8_t *pSrc, *pSrcEnd, *pDst, *pDstEnd; - if (w == 0 || h == 0) { + uint8_t* pSrc; + uint8_t* pSrcEnd; + uint8_t* pDst; + uint8_t* pDstEnd; + if (w == 0 || h == 0) return nullptr; - } - CJBig2_Image* pImage = new CJBig2_Image(w, h); + + auto pImage = pdfium::MakeUnique(w, h); if (!m_pData) { pImage->fill(0); return pImage; } - if (!pImage->m_pData) { + if (!pImage->m_pData) return pImage; - } - pLineSrc = m_pData + m_nStride * y; - pLineDst = pImage->m_pData; + + pLineSrc = data() + m_nStride * y; + pLineDst = pImage->data(); m = (x >> 5) << 2; n = x & 31; if (n == 0) { @@ -233,15 +233,16 @@ void CJBig2_Image::expand(int32_t h, bool v) { if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride) return; - if (m_bOwnsBuffer) { - m_pData = FX_Realloc(uint8_t, m_pData, h * m_nStride); + if (m_pData.IsOwned()) { + m_pData.Reset(std::unique_ptr( + FX_Realloc(uint8_t, m_pData.Release().release(), h * m_nStride))); } else { - uint8_t* pExternalBuffer = m_pData; - m_pData = FX_Alloc(uint8_t, h * m_nStride); - JBIG2_memcpy(m_pData, pExternalBuffer, m_nHeight * m_nStride); - m_bOwnsBuffer = true; + uint8_t* pExternalBuffer = data(); + m_pData.Reset(std::unique_ptr( + FX_Alloc(uint8_t, h * m_nStride))); + JBIG2_memcpy(data(), pExternalBuffer, m_nHeight * m_nStride); } - JBIG2_memset(m_pData + m_nHeight * m_nStride, v ? 0xff : 0, + JBIG2_memset(data() + m_nHeight * m_nStride, v ? 0xff : 0, (h - m_nHeight) * m_nStride); m_nHeight = h; } @@ -250,63 +251,56 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, int32_t x, int32_t y, JBig2ComposeOp op) { - int32_t xs0 = 0, ys0 = 0, xs1 = 0, ys1 = 0, xd0 = 0, yd0 = 0, xd1 = 0, - yd1 = 0, xx = 0, yy = 0, w = 0, h = 0, middleDwords = 0, lineLeft = 0; - - uint32_t s1 = 0, d1 = 0, d2 = 0, shift = 0, shift1 = 0, shift2 = 0, tmp = 0, - tmp1 = 0, tmp2 = 0, maskL = 0, maskR = 0, maskM = 0; - if (!m_pData) return false; if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) return false; - if (y < 0) { - ys0 = -y; - } - if (y + m_nHeight > pDst->m_nHeight) { + int32_t xs0 = x < 0 ? -x : 0; + int32_t xs1; + FX_SAFE_INT32 iChecked = pDst->m_nWidth; + iChecked -= x; + if (iChecked.IsValid() && m_nWidth > iChecked.ValueOrDie()) + xs1 = iChecked.ValueOrDie(); + else + xs1 = m_nWidth; + + int32_t ys0 = y < 0 ? -y : 0; + int32_t ys1; + iChecked = pDst->m_nHeight; + iChecked -= y; + if (iChecked.IsValid() && m_nHeight > iChecked.ValueOrDie()) ys1 = pDst->m_nHeight - y; - } else { + else ys1 = m_nHeight; - } - if (x < 0) { - xs0 = -x; - } - if (x + m_nWidth > pDst->m_nWidth) { - xs1 = pDst->m_nWidth - x; - } else { - xs1 = m_nWidth; - } - if ((ys0 >= ys1) || (xs0 >= xs1)) { - return 0; - } - w = xs1 - xs0; - h = ys1 - ys0; - if (y >= 0) { - yd0 = y; - } - if (x >= 0) { - xd0 = x; - } - xd1 = xd0 + w; - yd1 = yd0 + h; - d1 = xd0 & 31; - d2 = xd1 & 31; - s1 = xs0 & 31; - maskL = 0xffffffff >> d1; - maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32); - maskM = maskL & maskR; - uint8_t* lineSrc = m_pData + ys0 * m_nStride + ((xs0 >> 5) << 2); - lineLeft = m_nStride - ((xs0 >> 5) << 2); - uint8_t* lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2); + + if (ys0 >= ys1 || xs0 >= xs1) + return false; + + int32_t xd0 = std::max(x, 0); + int32_t yd0 = std::max(y, 0); + int32_t w = xs1 - xs0; + int32_t h = ys1 - ys0; + int32_t xd1 = xd0 + w; + int32_t yd1 = yd0 + h; + uint32_t d1 = xd0 & 31; + uint32_t d2 = xd1 & 31; + uint32_t s1 = xs0 & 31; + uint32_t maskL = 0xffffffff >> d1; + uint32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32); + uint32_t maskM = maskL & maskR; + uint8_t* lineSrc = data() + ys0 * m_nStride + ((xs0 >> 5) << 2); + int32_t lineLeft = m_nStride - ((xs0 >> 5) << 2); + uint8_t* lineDst = pDst->data() + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2); if ((xd0 & ~31) == ((xd1 - 1) & ~31)) { if ((xs0 & ~31) == ((xs1 - 1) & ~31)) { if (s1 > d1) { - shift = s1 - d1; - for (yy = yd0; yy < yd1; yy++) { - tmp1 = JBIG2_GETDWORD(lineSrc) << shift; - tmp2 = JBIG2_GETDWORD(lineDst); + uint32_t shift = s1 - d1; + for (int32_t yy = yd0; yy < yd1; yy++) { + uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) << shift; + uint32_t tmp2 = JBIG2_GETDWORD(lineDst); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); @@ -332,10 +326,11 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, lineDst += pDst->m_nStride; } } else { - shift = d1 - s1; - for (yy = yd0; yy < yd1; yy++) { - tmp1 = JBIG2_GETDWORD(lineSrc) >> shift; - tmp2 = JBIG2_GETDWORD(lineDst); + uint32_t shift = d1 - s1; + for (int32_t yy = yd0; yy < yd1; yy++) { + uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) >> shift; + uint32_t tmp2 = JBIG2_GETDWORD(lineDst); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); @@ -362,12 +357,13 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, } } } else { - shift1 = s1 - d1; - shift2 = 32 - shift1; - for (yy = yd0; yy < yd1; yy++) { - tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | - (JBIG2_GETDWORD(lineSrc + 4) >> shift2); - tmp2 = JBIG2_GETDWORD(lineDst); + uint32_t shift1 = s1 - d1; + uint32_t shift2 = 32 - shift1; + for (int32_t yy = yd0; yy < yd1; yy++) { + uint32_t tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | + (JBIG2_GETDWORD(lineSrc + 4) >> shift2); + uint32_t tmp2 = JBIG2_GETDWORD(lineDst); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); @@ -398,16 +394,17 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, uint8_t* dp = nullptr; if (s1 > d1) { - shift1 = s1 - d1; - shift2 = 32 - shift1; - middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); - for (yy = yd0; yy < yd1; yy++) { + uint32_t shift1 = s1 - d1; + uint32_t shift2 = 32 - shift1; + int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); + for (int32_t yy = yd0; yy < yd1; yy++) { sp = lineSrc; dp = lineDst; if (d1 != 0) { - tmp1 = (JBIG2_GETDWORD(sp) << shift1) | - (JBIG2_GETDWORD(sp + 4) >> shift2); - tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | + (JBIG2_GETDWORD(sp + 4) >> shift2); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); @@ -432,10 +429,11 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, sp += 4; dp += 4; } - for (xx = 0; xx < middleDwords; xx++) { - tmp1 = (JBIG2_GETDWORD(sp) << shift1) | - (JBIG2_GETDWORD(sp + 4) >> shift2); - tmp2 = JBIG2_GETDWORD(dp); + for (int32_t xx = 0; xx < middleDwords; xx++) { + uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | + (JBIG2_GETDWORD(sp + 4) >> shift2); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = tmp1 | tmp2; @@ -461,11 +459,12 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, dp += 4; } if (d2 != 0) { - tmp1 = + uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift2); - tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); @@ -492,13 +491,14 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, lineDst += pDst->m_nStride; } } else if (s1 == d1) { - middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); - for (yy = yd0; yy < yd1; yy++) { + int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); + for (int32_t yy = yd0; yy < yd1; yy++) { sp = lineSrc; dp = lineDst; if (d1 != 0) { - tmp1 = JBIG2_GETDWORD(sp); - tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp1 = JBIG2_GETDWORD(sp); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); @@ -523,9 +523,10 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, sp += 4; dp += 4; } - for (xx = 0; xx < middleDwords; xx++) { - tmp1 = JBIG2_GETDWORD(sp); - tmp2 = JBIG2_GETDWORD(dp); + for (int32_t xx = 0; xx < middleDwords; xx++) { + uint32_t tmp1 = JBIG2_GETDWORD(sp); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = tmp1 | tmp2; @@ -551,8 +552,9 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, dp += 4; } if (d2 != 0) { - tmp1 = JBIG2_GETDWORD(sp); - tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp1 = JBIG2_GETDWORD(sp); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); @@ -579,15 +581,16 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, lineDst += pDst->m_nStride; } } else { - shift1 = d1 - s1; - shift2 = 32 - shift1; - middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); - for (yy = yd0; yy < yd1; yy++) { + uint32_t shift1 = d1 - s1; + uint32_t shift2 = 32 - shift1; + int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); + for (int32_t yy = yd0; yy < yd1; yy++) { sp = lineSrc; dp = lineDst; if (d1 != 0) { - tmp1 = JBIG2_GETDWORD(sp) >> shift1; - tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp1 = JBIG2_GETDWORD(sp) >> shift1; + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); @@ -611,10 +614,11 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, dp[3] = (uint8_t)tmp; dp += 4; } - for (xx = 0; xx < middleDwords; xx++) { - tmp1 = (JBIG2_GETDWORD(sp) << shift2) | - ((JBIG2_GETDWORD(sp + 4)) >> shift1); - tmp2 = JBIG2_GETDWORD(dp); + for (int32_t xx = 0; xx < middleDwords; xx++) { + uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift2) | + ((JBIG2_GETDWORD(sp + 4)) >> shift1); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = tmp1 | tmp2; @@ -640,11 +644,12 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, dp += 4; } if (d2 != 0) { - tmp1 = + uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift2) | (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift1); - tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp2 = JBIG2_GETDWORD(dp); + uint32_t tmp = 0; switch (op) { case JBIG2_COMPOSE_OR: tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); @@ -672,16 +677,17 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, } } } - return 1; + return true; } + bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, int32_t x, int32_t y, JBig2ComposeOp op, const FX_RECT* pSrcRect) { - if (!m_pData) { + if (!m_pData) return false; - } + // TODO(weili): Check whether the range check is correct. Should x>=1048576? if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) { return false; @@ -707,10 +713,10 @@ bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, int32_t maskL = 0xffffffff >> d1; int32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32); int32_t maskM = maskL & maskR; - uint8_t* lineSrc = m_pData + (pSrcRect->top + ys0) * m_nStride + + uint8_t* lineSrc = data() + (pSrcRect->top + ys0) * m_nStride + (((xs0 + pSrcRect->left) >> 5) << 2); int32_t lineLeft = m_nStride - ((xs0 >> 5) << 2); - uint8_t* lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2); + uint8_t* lineDst = pDst->data() + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2); if ((xd0 & ~31) == ((xd1 - 1) & ~31)) { if ((xs0 & ~31) == ((xs1 - 1) & ~31)) { if (s1 > d1) { diff --git a/core/fxcodec/jbig2/JBig2_Image.h b/core/fxcodec/jbig2/JBig2_Image.h index 54529ef868d3a75a387cf10c085f4466d5066f74..c0980407db4e600c3a070cf270a5b7b14fff6b4c 100644 --- a/core/fxcodec/jbig2/JBig2_Image.h +++ b/core/fxcodec/jbig2/JBig2_Image.h @@ -7,7 +7,10 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_ #define CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_ +#include + #include "core/fxcodec/jbig2/JBig2_Define.h" +#include "core/fxcrt/maybe_owned.h" struct FX_RECT; @@ -29,8 +32,9 @@ class CJBig2_Image { int32_t width() const { return m_nWidth; } int32_t height() const { return m_nHeight; } int32_t stride() const { return m_nStride; } + uint8_t* data() const { return m_pData.Get(); } - int getPixel(int32_t x, int32_t y); + int getPixel(int32_t x, int32_t y) const; int32_t setPixel(int32_t x, int32_t y, int bVal); void copyLine(int32_t hTo, int32_t hFrom); @@ -60,16 +64,18 @@ class CJBig2_Image { JBig2ComposeOp op, const FX_RECT* pSrcRect); - CJBig2_Image* subImage(int32_t x, int32_t y, int32_t w, int32_t h); + std::unique_ptr subImage(int32_t x, + int32_t y, + int32_t w, + int32_t h); void expand(int32_t h, bool v); - uint8_t* m_pData; private: + MaybeOwned m_pData; int32_t m_nWidth; // 1-bit pixels int32_t m_nHeight; // lines int32_t m_nStride; // bytes - bool m_bOwnsBuffer; }; #endif // CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_ diff --git a/core/fxcodec/jbig2/JBig2_Image_unittest.cpp b/core/fxcodec/jbig2/JBig2_Image_unittest.cpp index 788f922a02e97280cd0669e482544b139241c67a..2e53e7b3372ed54fce8be74224c0a93cf57a81a9 100644 --- a/core/fxcodec/jbig2/JBig2_Image_unittest.cpp +++ b/core/fxcodec/jbig2/JBig2_Image_unittest.cpp @@ -34,7 +34,7 @@ TEST(fxcodec, JBig2ImageCreateTooBig) { CJBig2_Image img(kWidthPixels, kTooLargeHeightLines); EXPECT_EQ(0, img.width()); EXPECT_EQ(0, img.height()); - EXPECT_EQ(nullptr, img.m_pData); + EXPECT_EQ(nullptr, img.data()); } TEST(fxcodec, JBig2ImageCreateExternal) { @@ -53,7 +53,7 @@ TEST(fxcodec, JBig2ImageCreateExternalTooBig) { CJBig2_Image img(kWidthPixels, kTooLargeHeightLines, kStrideBytes, buf); EXPECT_EQ(0, img.width()); EXPECT_EQ(0, img.height()); - EXPECT_EQ(nullptr, img.m_pData); + EXPECT_EQ(nullptr, img.data()); } TEST(fxcodec, JBig2ImageExpand) { diff --git a/core/fxcodec/jbig2/JBig2_PatternDict.cpp b/core/fxcodec/jbig2/JBig2_PatternDict.cpp index cd6a2ad3c2cc025e7606965d1c7eb938a5c72911..450e78a8fa434e287b9c437506fd8a9034875dcb 100644 --- a/core/fxcodec/jbig2/JBig2_PatternDict.cpp +++ b/core/fxcodec/jbig2/JBig2_PatternDict.cpp @@ -8,16 +8,7 @@ #include "core/fxcrt/fx_memory.h" -CJBig2_PatternDict::CJBig2_PatternDict() { - NUMPATS = 0; - HDPATS = nullptr; -} +CJBig2_PatternDict::CJBig2_PatternDict(uint32_t dict_size) + : NUMPATS(dict_size), HDPATS(dict_size) {} -CJBig2_PatternDict::~CJBig2_PatternDict() { - if (HDPATS) { - for (uint32_t i = 0; i < NUMPATS; i++) { - delete HDPATS[i]; - } - FX_Free(HDPATS); - } -} +CJBig2_PatternDict::~CJBig2_PatternDict() {} diff --git a/core/fxcodec/jbig2/JBig2_PatternDict.h b/core/fxcodec/jbig2/JBig2_PatternDict.h index dddd4747f0b1802c42816e6a3f6f0a47d4a5999e..ad55917d6b54e8fcfdfd509e42fb9aabec11a2da 100644 --- a/core/fxcodec/jbig2/JBig2_PatternDict.h +++ b/core/fxcodec/jbig2/JBig2_PatternDict.h @@ -7,17 +7,20 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_PATTERNDICT_H_ #define CORE_FXCODEC_JBIG2_JBIG2_PATTERNDICT_H_ +#include +#include + #include "core/fxcodec/jbig2/JBig2_Define.h" #include "core/fxcodec/jbig2/JBig2_Image.h" class CJBig2_PatternDict { public: - CJBig2_PatternDict(); + explicit CJBig2_PatternDict(uint32_t dict_size); ~CJBig2_PatternDict(); uint32_t NUMPATS; - CJBig2_Image** HDPATS; + std::vector> HDPATS; }; #endif // CORE_FXCODEC_JBIG2_JBIG2_PATTERNDICT_H_ diff --git a/core/fxcodec/jbig2/JBig2_PddProc.cpp b/core/fxcodec/jbig2/JBig2_PddProc.cpp index 679a87a03695881518c8bd49c80d93bfa3fd7c3e..ee891cc0025f3d96796c60178fd0b73e0db12fc2 100644 --- a/core/fxcodec/jbig2/JBig2_PddProc.cpp +++ b/core/fxcodec/jbig2/JBig2_PddProc.cpp @@ -11,19 +11,17 @@ #include "core/fxcodec/jbig2/JBig2_GrdProc.h" #include "core/fxcodec/jbig2/JBig2_Image.h" #include "core/fxcodec/jbig2/JBig2_PatternDict.h" +#include "third_party/base/ptr_util.h" -CJBig2_PatternDict* CJBig2_PDDProc::decode_Arith( +std::unique_ptr CJBig2_PDDProc::decode_Arith( CJBig2_ArithDecoder* pArithDecoder, JBig2ArithCtx* gbContext, - IFX_Pause* pPause) { + IFX_PauseIndicator* pPause) { uint32_t GRAY; - CJBig2_Image* BHDC = nullptr; - std::unique_ptr pDict(new CJBig2_PatternDict()); - pDict->NUMPATS = GRAYMAX + 1; - pDict->HDPATS = FX_Alloc(CJBig2_Image*, pDict->NUMPATS); - JBIG2_memset(pDict->HDPATS, 0, sizeof(CJBig2_Image*) * pDict->NUMPATS); + std::unique_ptr BHDC; + auto pDict = pdfium::MakeUnique(GRAYMAX + 1); - std::unique_ptr pGRD(new CJBig2_GRDProc()); + auto pGRD = pdfium::MakeUnique(); pGRD->MMR = HDMMR; pGRD->GBW = (GRAYMAX + 1) * HDPW; pGRD->GBH = HDPH; @@ -43,7 +41,7 @@ CJBig2_PatternDict* CJBig2_PDDProc::decode_Arith( FXCODEC_STATUS status = pGRD->Start_decode_Arith(&BHDC, pArithDecoder, gbContext, nullptr); while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) - status = pGRD->Continue_decode(pPause); + status = pGRD->Continue_decode(pPause, pArithDecoder); if (!BHDC) return nullptr; @@ -52,24 +50,20 @@ CJBig2_PatternDict* CJBig2_PDDProc::decode_Arith( pDict->HDPATS[GRAY] = BHDC->subImage(HDPW * GRAY, 0, HDPW, HDPH); GRAY = GRAY + 1; } - delete BHDC; - return pDict.release(); + return pDict; } -CJBig2_PatternDict* CJBig2_PDDProc::decode_MMR(CJBig2_BitStream* pStream, - IFX_Pause* pPause) { +std::unique_ptr CJBig2_PDDProc::decode_MMR( + CJBig2_BitStream* pStream) { uint32_t GRAY; - CJBig2_Image* BHDC = nullptr; - std::unique_ptr pDict(new CJBig2_PatternDict()); - pDict->NUMPATS = GRAYMAX + 1; - pDict->HDPATS = FX_Alloc(CJBig2_Image*, pDict->NUMPATS); - JBIG2_memset(pDict->HDPATS, 0, sizeof(CJBig2_Image*) * pDict->NUMPATS); + std::unique_ptr BHDC; + auto pDict = pdfium::MakeUnique(GRAYMAX + 1); - std::unique_ptr pGRD(new CJBig2_GRDProc()); + auto pGRD = pdfium::MakeUnique(); pGRD->MMR = HDMMR; pGRD->GBW = (GRAYMAX + 1) * HDPW; pGRD->GBH = HDPH; - pGRD->Start_decode_MMR(&BHDC, pStream, nullptr); + pGRD->Start_decode_MMR(&BHDC, pStream); if (!BHDC) return nullptr; @@ -78,6 +72,5 @@ CJBig2_PatternDict* CJBig2_PDDProc::decode_MMR(CJBig2_BitStream* pStream, pDict->HDPATS[GRAY] = BHDC->subImage(HDPW * GRAY, 0, HDPW, HDPH); GRAY = GRAY + 1; } - delete BHDC; - return pDict.release(); + return pDict; } diff --git a/core/fxcodec/jbig2/JBig2_PddProc.h b/core/fxcodec/jbig2/JBig2_PddProc.h index 578f6031227ee89caeab4e0c0fdf940441376a7d..938da1b209a82bdef0c96b3a40fcb56f6f4b8536 100644 --- a/core/fxcodec/jbig2/JBig2_PddProc.h +++ b/core/fxcodec/jbig2/JBig2_PddProc.h @@ -7,21 +7,24 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_PDDPROC_H_ #define CORE_FXCODEC_JBIG2_JBIG2_PDDPROC_H_ +#include + #include "core/fxcrt/fx_system.h" class CJBig2_ArithDecoder; class CJBig2_BitStream; class CJBig2_PatternDict; -class IFX_Pause; +class IFX_PauseIndicator; struct JBig2ArithCtx; class CJBig2_PDDProc { public: - CJBig2_PatternDict* decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* gbContext, - IFX_Pause* pPause); + std::unique_ptr decode_Arith( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* gbContext, + IFX_PauseIndicator* pPause); - CJBig2_PatternDict* decode_MMR(CJBig2_BitStream* pStream, IFX_Pause* pPause); + std::unique_ptr decode_MMR(CJBig2_BitStream* pStream); public: bool HDMMR; diff --git a/core/fxcodec/jbig2/JBig2_SddProc.cpp b/core/fxcodec/jbig2/JBig2_SddProc.cpp index 5f23fcf4e1dbb33ca309ae65ac856632e44d26c1..a446dbc6c0ac2b2b9c94a3a2bff03098f9aae8db 100644 --- a/core/fxcodec/jbig2/JBig2_SddProc.cpp +++ b/core/fxcodec/jbig2/JBig2_SddProc.cpp @@ -6,7 +6,9 @@ #include "core/fxcodec/jbig2/JBig2_SddProc.h" +#include #include +#include #include #include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h" @@ -17,21 +19,19 @@ #include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h" #include "core/fxcodec/jbig2/JBig2_SymbolDict.h" #include "core/fxcodec/jbig2/JBig2_TrdProc.h" -#include "core/fxcrt/fx_basic.h" #include "third_party/base/ptr_util.h" -CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( +std::unique_ptr CJBig2_SDDProc::decode_Arith( CJBig2_ArithDecoder* pArithDecoder, std::vector* gbContext, std::vector* grContext) { - CJBig2_Image** SDNEWSYMS; + std::vector> SDNEWSYMS; uint32_t HCHEIGHT, NSYMSDECODED; int32_t HCDH; uint32_t SYMWIDTH, TOTWIDTH; int32_t DW; - CJBig2_Image* BS; uint32_t I, J, REFAGGNINST; - bool* EXFLAGS; + std::vector EXFLAGS; uint32_t EXINDEX; bool CUREXFLAG; uint32_t EXRUNLENGTH; @@ -40,39 +40,39 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( uint8_t SBSYMCODELEN; int32_t RDXI, RDYI; uint32_t num_ex_syms; - CJBig2_Image** SBSYMS; + // Pointers are not owned + std::vector SBSYMS; std::unique_ptr IAID; std::unique_ptr pDict; - std::unique_ptr IADH(new CJBig2_ArithIntDecoder); - std::unique_ptr IADW(new CJBig2_ArithIntDecoder); - std::unique_ptr IAAI(new CJBig2_ArithIntDecoder); - std::unique_ptr IARDX(new CJBig2_ArithIntDecoder); - std::unique_ptr IARDY(new CJBig2_ArithIntDecoder); - std::unique_ptr IAEX(new CJBig2_ArithIntDecoder); - std::unique_ptr IADT(new CJBig2_ArithIntDecoder); - std::unique_ptr IAFS(new CJBig2_ArithIntDecoder); - std::unique_ptr IADS(new CJBig2_ArithIntDecoder); - std::unique_ptr IAIT(new CJBig2_ArithIntDecoder); - std::unique_ptr IARI(new CJBig2_ArithIntDecoder); - std::unique_ptr IARDW(new CJBig2_ArithIntDecoder); - std::unique_ptr IARDH(new CJBig2_ArithIntDecoder); + auto IADH = pdfium::MakeUnique(); + auto IADW = pdfium::MakeUnique(); + auto IAAI = pdfium::MakeUnique(); + auto IARDX = pdfium::MakeUnique(); + auto IARDY = pdfium::MakeUnique(); + auto IAEX = pdfium::MakeUnique(); + auto IADT = pdfium::MakeUnique(); + auto IAFS = pdfium::MakeUnique(); + auto IADS = pdfium::MakeUnique(); + auto IAIT = pdfium::MakeUnique(); + auto IARI = pdfium::MakeUnique(); + auto IARDW = pdfium::MakeUnique(); + auto IARDH = pdfium::MakeUnique(); nTmp = 0; while ((uint32_t)(1 << nTmp) < (SDNUMINSYMS + SDNUMNEWSYMS)) { nTmp++; } IAID = pdfium::MakeUnique((uint8_t)nTmp); - SDNEWSYMS = FX_Alloc(CJBig2_Image*, SDNUMNEWSYMS); - FXSYS_memset(SDNEWSYMS, 0, SDNUMNEWSYMS * sizeof(CJBig2_Image*)); + SDNEWSYMS.resize(SDNUMNEWSYMS); HCHEIGHT = 0; NSYMSDECODED = 0; while (NSYMSDECODED < SDNUMNEWSYMS) { - BS = nullptr; + std::unique_ptr BS; IADH->decode(pArithDecoder, &HCDH); HCHEIGHT = HCHEIGHT + HCDH; - if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) { - goto failed; - } + if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) + return nullptr; + SYMWIDTH = 0; TOTWIDTH = 0; for (;;) { @@ -80,11 +80,11 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( break; if (NSYMSDECODED >= SDNUMNEWSYMS) - goto failed; + return nullptr; SYMWIDTH = SYMWIDTH + DW; if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE) - goto failed; + return nullptr; if (HCHEIGHT == 0 || SYMWIDTH == 0) { TOTWIDTH = TOTWIDTH + SYMWIDTH; @@ -94,7 +94,7 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( } TOTWIDTH = TOTWIDTH + SYMWIDTH; if (SDREFAGG == 0) { - std::unique_ptr pGRD(new CJBig2_GRDProc()); + auto pGRD = pdfium::MakeUnique(); pGRD->MMR = 0; pGRD->GBW = SYMWIDTH; pGRD->GBH = HCHEIGHT; @@ -110,13 +110,12 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( pGRD->GBAT[6] = SDAT[6]; pGRD->GBAT[7] = SDAT[7]; BS = pGRD->decode_Arith(pArithDecoder, gbContext->data()); - if (!BS) { - goto failed; - } + if (!BS) + return nullptr; } else { IAAI->decode(pArithDecoder, (int*)&REFAGGNINST); if (REFAGGNINST > 1) { - std::unique_ptr pDecoder(new CJBig2_TRDProc()); + auto pDecoder = pdfium::MakeUnique(); pDecoder->SBHUFF = SDHUFF; pDecoder->SBREFINE = 1; pDecoder->SBW = SYMWIDTH; @@ -131,37 +130,32 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( } SBSYMCODELEN = (uint8_t)nTmp; pDecoder->SBSYMCODELEN = SBSYMCODELEN; - SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS); - JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*)); - JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS, - NSYMSDECODED * sizeof(CJBig2_Image*)); - pDecoder->SBSYMS = SBSYMS; + SBSYMS.resize(SBNUMSYMS); + std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin()); + for (size_t i = 0; i < NSYMSDECODED; ++i) + SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get(); + pDecoder->SBSYMS = SBSYMS.data(); pDecoder->SBDEFPIXEL = 0; pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR; pDecoder->TRANSPOSED = 0; pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT; pDecoder->SBDSOFFSET = 0; - std::unique_ptr SBHUFFFS(new CJBig2_HuffmanTable( - HuffmanTable_B6, HuffmanTable_B6_Size, HuffmanTable_HTOOB_B6)); - std::unique_ptr SBHUFFDS(new CJBig2_HuffmanTable( - HuffmanTable_B8, HuffmanTable_B8_Size, HuffmanTable_HTOOB_B8)); - std::unique_ptr SBHUFFDT(new CJBig2_HuffmanTable( - HuffmanTable_B11, HuffmanTable_B11_Size, HuffmanTable_HTOOB_B11)); - std::unique_ptr SBHUFFRDW( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRDH( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRDX( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRDY( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRSIZE( - new CJBig2_HuffmanTable(HuffmanTable_B1, HuffmanTable_B1_Size, - HuffmanTable_HTOOB_B1)); + auto SBHUFFFS = pdfium::MakeUnique( + HuffmanTable_B6, HuffmanTable_B6_Size, HuffmanTable_HTOOB_B6); + auto SBHUFFDS = pdfium::MakeUnique( + HuffmanTable_B8, HuffmanTable_B8_Size, HuffmanTable_HTOOB_B8); + auto SBHUFFDT = pdfium::MakeUnique( + HuffmanTable_B11, HuffmanTable_B11_Size, HuffmanTable_HTOOB_B11); + auto SBHUFFRDW = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRDH = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRDX = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRDY = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRSIZE = pdfium::MakeUnique( + HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); pDecoder->SBHUFFFS = SBHUFFFS.get(); pDecoder->SBHUFFDS = SBHUFFDS.get(); pDecoder->SBHUFFDT = SBHUFFDT.get(); @@ -187,29 +181,25 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( ids.IARDY = IARDY.get(); ids.IAID = IAID.get(); BS = pDecoder->decode_Arith(pArithDecoder, grContext->data(), &ids); - if (!BS) { - FX_Free(SBSYMS); - goto failed; - } - FX_Free(SBSYMS); + if (!BS) + return nullptr; } else if (REFAGGNINST == 1) { SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED; uint32_t IDI; IAID->decode(pArithDecoder, &IDI); IARDX->decode(pArithDecoder, &RDXI); IARDY->decode(pArithDecoder, &RDYI); - if (IDI >= SBNUMSYMS) { - goto failed; - } - SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS); - JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*)); - JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS, - NSYMSDECODED * sizeof(CJBig2_Image*)); - if (!SBSYMS[IDI]) { - FX_Free(SBSYMS); - goto failed; - } - std::unique_ptr pGRRD(new CJBig2_GRRDProc()); + if (IDI >= SBNUMSYMS) + return nullptr; + + SBSYMS.resize(SBNUMSYMS); + std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin()); + for (size_t i = 0; i < NSYMSDECODED; ++i) + SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get(); + if (!SBSYMS[IDI]) + return nullptr; + + auto pGRRD = pdfium::MakeUnique(); pGRRD->GRW = SYMWIDTH; pGRRD->GRH = HCHEIGHT; pGRRD->GRTEMPLATE = SDRTEMPLATE; @@ -222,28 +212,23 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( pGRRD->GRAT[2] = SDRAT[2]; pGRRD->GRAT[3] = SDRAT[3]; BS = pGRRD->decode(pArithDecoder, grContext->data()); - if (!BS) { - FX_Free(SBSYMS); - goto failed; - } - FX_Free(SBSYMS); + if (!BS) + return nullptr; } } - SDNEWSYMS[NSYMSDECODED] = BS; - BS = nullptr; + SDNEWSYMS[NSYMSDECODED] = std::move(BS); NSYMSDECODED = NSYMSDECODED + 1; } } EXINDEX = 0; CUREXFLAG = 0; - EXFLAGS = FX_Alloc(bool, SDNUMINSYMS + SDNUMNEWSYMS); + EXFLAGS.resize(SDNUMINSYMS + SDNUMNEWSYMS); num_ex_syms = 0; while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) { IAEX->decode(pArithDecoder, (int*)&EXRUNLENGTH); - if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) { - FX_Free(EXFLAGS); - goto failed; - } + if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) + return nullptr; + if (EXRUNLENGTH != 0) { for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) { if (CUREXFLAG) @@ -254,125 +239,100 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith( EXINDEX = EXINDEX + EXRUNLENGTH; CUREXFLAG = !CUREXFLAG; } - if (num_ex_syms > SDNUMEXSYMS) { - FX_Free(EXFLAGS); - goto failed; - } + if (num_ex_syms > SDNUMEXSYMS) + return nullptr; pDict = pdfium::MakeUnique(); I = J = 0; for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) { - if (EXFLAGS[I] && J < SDNUMEXSYMS) { - if (I < SDNUMINSYMS) { - pDict->AddImage(SDINSYMS[I] - ? pdfium::MakeUnique(*SDINSYMS[I]) - : nullptr); - } else { - pDict->AddImage(pdfium::WrapUnique(SDNEWSYMS[I - SDNUMINSYMS])); - } - ++J; - } else if (!EXFLAGS[I] && I >= SDNUMINSYMS) { - delete SDNEWSYMS[I - SDNUMINSYMS]; - } - } - FX_Free(EXFLAGS); - FX_Free(SDNEWSYMS); - return pDict.release(); -failed: - for (I = 0; I < NSYMSDECODED; I++) { - if (SDNEWSYMS[I]) { - delete SDNEWSYMS[I]; - SDNEWSYMS[I] = nullptr; + if (!EXFLAGS[I] || J >= SDNUMEXSYMS) + continue; + if (I < SDNUMINSYMS) { + pDict->AddImage(SDINSYMS[I] + ? pdfium::MakeUnique(*SDINSYMS[I]) + : nullptr); + } else { + pDict->AddImage(std::move(SDNEWSYMS[I - SDNUMINSYMS])); } + ++J; } - FX_Free(SDNEWSYMS); - return nullptr; + return pDict; } -CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( +std::unique_ptr CJBig2_SDDProc::decode_Huffman( CJBig2_BitStream* pStream, std::vector* gbContext, - std::vector* grContext, - IFX_Pause* pPause) { - CJBig2_Image** SDNEWSYMS; - uint32_t* SDNEWSYMWIDTHS; + std::vector* grContext) { + std::vector> SDNEWSYMS; + std::vector SDNEWSYMWIDTHS; uint32_t HCHEIGHT, NSYMSDECODED; int32_t HCDH; uint32_t SYMWIDTH, TOTWIDTH, HCFIRSTSYM; int32_t DW; - CJBig2_Image *BS, *BHC; uint32_t I, J, REFAGGNINST; - bool* EXFLAGS; + std::vector EXFLAGS; uint32_t EXINDEX; bool CUREXFLAG; uint32_t EXRUNLENGTH; - int32_t nVal, nBits; + int32_t nVal; uint32_t nTmp; uint32_t SBNUMSYMS; uint8_t SBSYMCODELEN; - JBig2HuffmanCode* SBSYMCODES; uint32_t IDI; int32_t RDXI, RDYI; uint32_t BMSIZE; uint32_t stride; uint32_t num_ex_syms; - CJBig2_Image** SBSYMS; - std::unique_ptr pHuffmanDecoder( - new CJBig2_HuffmanDecoder(pStream)); - SDNEWSYMS = FX_Alloc(CJBig2_Image*, SDNUMNEWSYMS); - FXSYS_memset(SDNEWSYMS, 0, SDNUMNEWSYMS * sizeof(CJBig2_Image*)); - SDNEWSYMWIDTHS = nullptr; - BHC = nullptr; - if (SDREFAGG == 0) { - SDNEWSYMWIDTHS = FX_Alloc(uint32_t, SDNUMNEWSYMS); - FXSYS_memset(SDNEWSYMWIDTHS, 0, SDNUMNEWSYMS * sizeof(uint32_t)); - } - std::unique_ptr pDict(new CJBig2_SymbolDict()); + // Pointers are not owned + std::vector SBSYMS; + auto pHuffmanDecoder = pdfium::MakeUnique(pStream); + SDNEWSYMS.resize(SDNUMNEWSYMS); + if (SDREFAGG == 0) + SDNEWSYMWIDTHS.resize(SDNUMNEWSYMS); + auto pDict = pdfium::MakeUnique(); std::unique_ptr pTable; HCHEIGHT = 0; NSYMSDECODED = 0; - BS = nullptr; + std::unique_ptr BS; while (NSYMSDECODED < SDNUMNEWSYMS) { - if (pHuffmanDecoder->decodeAValue(SDHUFFDH, &HCDH) != 0) { - goto failed; - } + if (pHuffmanDecoder->decodeAValue(SDHUFFDH, &HCDH) != 0) + return nullptr; + HCHEIGHT = HCHEIGHT + HCDH; - if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) { - goto failed; - } + if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) + return nullptr; + SYMWIDTH = 0; TOTWIDTH = 0; HCFIRSTSYM = NSYMSDECODED; for (;;) { nVal = pHuffmanDecoder->decodeAValue(SDHUFFDW, &DW); - if (nVal == JBIG2_OOB) { + if (nVal == JBIG2_OOB) break; - } else if (nVal != 0) { - goto failed; - } else { - if (NSYMSDECODED >= SDNUMNEWSYMS) { - goto failed; - } - SYMWIDTH = SYMWIDTH + DW; - if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE) { - goto failed; - } else if (HCHEIGHT == 0 || SYMWIDTH == 0) { - TOTWIDTH = TOTWIDTH + SYMWIDTH; - SDNEWSYMS[NSYMSDECODED] = nullptr; - NSYMSDECODED = NSYMSDECODED + 1; - continue; - } + if (nVal != 0) + return nullptr; + if (NSYMSDECODED >= SDNUMNEWSYMS) + return nullptr; + + SYMWIDTH = SYMWIDTH + DW; + if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE) + return nullptr; + if (HCHEIGHT == 0 || SYMWIDTH == 0) { TOTWIDTH = TOTWIDTH + SYMWIDTH; + SDNEWSYMS[NSYMSDECODED] = nullptr; + NSYMSDECODED = NSYMSDECODED + 1; + continue; } + TOTWIDTH = TOTWIDTH + SYMWIDTH; if (SDREFAGG == 1) { if (pHuffmanDecoder->decodeAValue(SDHUFFAGGINST, (int*)&REFAGGNINST) != 0) { - goto failed; + return nullptr; } BS = nullptr; if (REFAGGNINST > 1) { - std::unique_ptr pDecoder(new CJBig2_TRDProc()); + auto pDecoder = pdfium::MakeUnique(); pDecoder->SBHUFF = SDHUFF; pDecoder->SBREFINE = 1; pDecoder->SBW = SYMWIDTH; @@ -381,47 +341,41 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( pDecoder->SBSTRIPS = 1; pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED; SBNUMSYMS = pDecoder->SBNUMSYMS; - SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS); + std::vector SBSYMCODES(SBNUMSYMS); nTmp = 1; - while ((uint32_t)(1 << nTmp) < SBNUMSYMS) { - nTmp++; - } - for (I = 0; I < SBNUMSYMS; I++) { + while (static_cast(1 << nTmp) < SBNUMSYMS) + ++nTmp; + for (I = 0; I < SBNUMSYMS; ++I) { SBSYMCODES[I].codelen = nTmp; SBSYMCODES[I].code = I; } - pDecoder->SBSYMCODES = SBSYMCODES; - SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS); - JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*)); - JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS, - NSYMSDECODED * sizeof(CJBig2_Image*)); - pDecoder->SBSYMS = SBSYMS; + pDecoder->SBSYMCODES = std::move(SBSYMCODES); + SBSYMS.resize(SBNUMSYMS); + std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin()); + for (size_t i = 0; i < NSYMSDECODED; ++i) + SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get(); + pDecoder->SBSYMS = SBSYMS.data(); pDecoder->SBDEFPIXEL = 0; pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR; pDecoder->TRANSPOSED = 0; pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT; pDecoder->SBDSOFFSET = 0; - std::unique_ptr SBHUFFFS(new CJBig2_HuffmanTable( - HuffmanTable_B6, HuffmanTable_B6_Size, HuffmanTable_HTOOB_B6)); - std::unique_ptr SBHUFFDS(new CJBig2_HuffmanTable( - HuffmanTable_B8, HuffmanTable_B8_Size, HuffmanTable_HTOOB_B8)); - std::unique_ptr SBHUFFDT(new CJBig2_HuffmanTable( - HuffmanTable_B11, HuffmanTable_B11_Size, HuffmanTable_HTOOB_B11)); - std::unique_ptr SBHUFFRDW( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRDH( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRDX( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRDY( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRSIZE( - new CJBig2_HuffmanTable(HuffmanTable_B1, HuffmanTable_B1_Size, - HuffmanTable_HTOOB_B1)); + auto SBHUFFFS = pdfium::MakeUnique( + HuffmanTable_B6, HuffmanTable_B6_Size, HuffmanTable_HTOOB_B6); + auto SBHUFFDS = pdfium::MakeUnique( + HuffmanTable_B8, HuffmanTable_B8_Size, HuffmanTable_HTOOB_B8); + auto SBHUFFDT = pdfium::MakeUnique( + HuffmanTable_B11, HuffmanTable_B11_Size, HuffmanTable_HTOOB_B11); + auto SBHUFFRDW = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRDH = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRDX = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRDY = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRSIZE = pdfium::MakeUnique( + HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); pDecoder->SBHUFFFS = SBHUFFFS.get(); pDecoder->SBHUFFDS = SBHUFFDS.get(); pDecoder->SBHUFFDT = SBHUFFDT.get(); @@ -436,13 +390,9 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( pDecoder->SBRAT[2] = SDRAT[2]; pDecoder->SBRAT[3] = SDRAT[3]; BS = pDecoder->decode_Huffman(pStream, grContext->data()); - if (!BS) { - FX_Free(SBSYMCODES); - FX_Free(SBSYMS); - goto failed; - } - FX_Free(SBSYMCODES); - FX_Free(SBSYMS); + if (!BS) + return nullptr; + } else if (REFAGGNINST == 1) { SBNUMSYMS = SDNUMINSYMS + SDNUMNEWSYMS; nTmp = 1; @@ -450,48 +400,35 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( nTmp++; } SBSYMCODELEN = (uint8_t)nTmp; - SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS); - for (I = 0; I < SBNUMSYMS; I++) { - SBSYMCODES[I].codelen = SBSYMCODELEN; - SBSYMCODES[I].code = I; - } - nVal = 0; - nBits = 0; + uint32_t uVal = 0; for (;;) { - if (pStream->read1Bit(&nTmp) != 0) { - FX_Free(SBSYMCODES); - goto failed; - } - nVal = (nVal << 1) | nTmp; - for (IDI = 0; IDI < SBNUMSYMS; IDI++) { - if ((nVal == SBSYMCODES[IDI].code) && - (nBits == SBSYMCODES[IDI].codelen)) { - break; - } - } - if (IDI < SBNUMSYMS) { + if (pStream->read1Bit(&nTmp) != 0) + return nullptr; + + uVal = (uVal << 1) | nTmp; + if (uVal >= SBNUMSYMS) + return nullptr; + + IDI = SBSYMCODELEN == 0 ? uVal : SBNUMSYMS; + if (IDI < SBNUMSYMS) break; - } } - FX_Free(SBSYMCODES); - std::unique_ptr SBHUFFRDX( - new CJBig2_HuffmanTable(HuffmanTable_B15, HuffmanTable_B15_Size, - HuffmanTable_HTOOB_B15)); - std::unique_ptr SBHUFFRSIZE( - new CJBig2_HuffmanTable(HuffmanTable_B1, HuffmanTable_B1_Size, - HuffmanTable_HTOOB_B1)); + auto SBHUFFRDX = pdfium::MakeUnique( + HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); + auto SBHUFFRSIZE = pdfium::MakeUnique( + HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); if ((pHuffmanDecoder->decodeAValue(SBHUFFRDX.get(), &RDXI) != 0) || (pHuffmanDecoder->decodeAValue(SBHUFFRDX.get(), &RDYI) != 0) || (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE.get(), &nVal) != 0)) { - goto failed; + return nullptr; } pStream->alignByte(); nTmp = pStream->getOffset(); - SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS); - JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*)); - JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS, - NSYMSDECODED * sizeof(CJBig2_Image*)); - std::unique_ptr pGRRD(new CJBig2_GRRDProc()); + SBSYMS.resize(SBNUMSYMS); + std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin()); + for (size_t i = 0; i < NSYMSDECODED; ++i) + SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get(); + auto pGRRD = pdfium::MakeUnique(); pGRRD->GRW = SYMWIDTH; pGRRD->GRH = HCHEIGHT; pGRRD->GRTEMPLATE = SDRTEMPLATE; @@ -503,83 +440,73 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( pGRRD->GRAT[1] = SDRAT[1]; pGRRD->GRAT[2] = SDRAT[2]; pGRRD->GRAT[3] = SDRAT[3]; - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(pStream)); + auto pArithDecoder = pdfium::MakeUnique(pStream); BS = pGRRD->decode(pArithDecoder.get(), grContext->data()); - if (!BS) { - FX_Free(SBSYMS); - goto failed; - } + if (!BS) + return nullptr; + pStream->alignByte(); pStream->offset(2); - if ((uint32_t)nVal != (pStream->getOffset() - nTmp)) { - delete BS; - FX_Free(SBSYMS); - goto failed; - } - FX_Free(SBSYMS); + if ((uint32_t)nVal != (pStream->getOffset() - nTmp)) + return nullptr; } - SDNEWSYMS[NSYMSDECODED] = BS; + SDNEWSYMS[NSYMSDECODED] = std::move(BS); } - if (SDREFAGG == 0) { + if (SDREFAGG == 0) SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH; - } NSYMSDECODED = NSYMSDECODED + 1; } if (SDREFAGG == 0) { - if (pHuffmanDecoder->decodeAValue(SDHUFFBMSIZE, (int32_t*)&BMSIZE) != 0) { - goto failed; - } + if (pHuffmanDecoder->decodeAValue(SDHUFFBMSIZE, (int32_t*)&BMSIZE) != 0) + return nullptr; + pStream->alignByte(); + std::unique_ptr BHC; if (BMSIZE == 0) { stride = (TOTWIDTH + 7) >> 3; if (pStream->getByteLeft() >= stride * HCHEIGHT) { - BHC = new CJBig2_Image(TOTWIDTH, HCHEIGHT); + BHC = pdfium::MakeUnique(TOTWIDTH, HCHEIGHT); for (I = 0; I < HCHEIGHT; I++) { - JBIG2_memcpy(BHC->m_pData + I * BHC->stride(), - pStream->getPointer(), stride); + JBIG2_memcpy(BHC->data() + I * BHC->stride(), pStream->getPointer(), + stride); pStream->offset(stride); } } else { - goto failed; + return nullptr; } } else { - std::unique_ptr pGRD(new CJBig2_GRDProc()); + auto pGRD = pdfium::MakeUnique(); pGRD->MMR = 1; pGRD->GBW = TOTWIDTH; pGRD->GBH = HCHEIGHT; - pGRD->Start_decode_MMR(&BHC, pStream, nullptr); + pGRD->Start_decode_MMR(&BHC, pStream); pStream->alignByte(); } nTmp = 0; - if (!BHC) { + if (!BHC) continue; - } - for (I = HCFIRSTSYM; I < NSYMSDECODED; I++) { + + for (I = HCFIRSTSYM; I < NSYMSDECODED; ++I) { SDNEWSYMS[I] = BHC->subImage(nTmp, 0, SDNEWSYMWIDTHS[I], HCHEIGHT); nTmp += SDNEWSYMWIDTHS[I]; } - delete BHC; - BHC = nullptr; } } EXINDEX = 0; CUREXFLAG = 0; pTable = pdfium::MakeUnique( HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); - EXFLAGS = FX_Alloc(bool, SDNUMINSYMS + SDNUMNEWSYMS); + EXFLAGS.resize(SDNUMINSYMS + SDNUMNEWSYMS); num_ex_syms = 0; while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) { - if (pHuffmanDecoder->decodeAValue(pTable.get(), (int*)&EXRUNLENGTH) != 0) { - FX_Free(EXFLAGS); - goto failed; - } - if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) { - FX_Free(EXFLAGS); - goto failed; - } + if (pHuffmanDecoder->decodeAValue(pTable.get(), (int*)&EXRUNLENGTH) != 0) + return nullptr; + + if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) + return nullptr; + if (EXRUNLENGTH != 0) { - for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) { + for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; ++I) { if (CUREXFLAG) num_ex_syms++; @@ -589,39 +516,21 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( EXINDEX = EXINDEX + EXRUNLENGTH; CUREXFLAG = !CUREXFLAG; } - if (num_ex_syms > SDNUMEXSYMS) { - FX_Free(EXFLAGS); - goto failed; - } + if (num_ex_syms > SDNUMEXSYMS) + return nullptr; I = J = 0; - for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) { - if (EXFLAGS[I] && J < SDNUMEXSYMS) { - if (I < SDNUMINSYMS) { - pDict->AddImage(SDINSYMS[I] - ? pdfium::MakeUnique(*SDINSYMS[I]) - : nullptr); - } else { - pDict->AddImage(pdfium::WrapUnique(SDNEWSYMS[I - SDNUMINSYMS])); - } - ++J; - } else if (!EXFLAGS[I] && I >= SDNUMINSYMS) { - delete SDNEWSYMS[I - SDNUMINSYMS]; + for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; ++I) { + if (!EXFLAGS[I] || J >= SDNUMEXSYMS) + continue; + if (I < SDNUMINSYMS) { + pDict->AddImage(SDINSYMS[I] + ? pdfium::MakeUnique(*SDINSYMS[I]) + : nullptr); + } else { + pDict->AddImage(std::move(SDNEWSYMS[I - SDNUMINSYMS])); } + ++J; } - FX_Free(EXFLAGS); - FX_Free(SDNEWSYMS); - if (SDREFAGG == 0) { - FX_Free(SDNEWSYMWIDTHS); - } - return pDict.release(); -failed: - for (I = 0; I < NSYMSDECODED; I++) { - delete SDNEWSYMS[I]; - } - FX_Free(SDNEWSYMS); - if (SDREFAGG == 0) { - FX_Free(SDNEWSYMWIDTHS); - } - return nullptr; + return pDict; } diff --git a/core/fxcodec/jbig2/JBig2_SddProc.h b/core/fxcodec/jbig2/JBig2_SddProc.h index 4df0cb4146018c4c5cfd008ed9071b57938958fe..80b988ef98af41dc5560dae27b13837bac7651cb 100644 --- a/core/fxcodec/jbig2/JBig2_SddProc.h +++ b/core/fxcodec/jbig2/JBig2_SddProc.h @@ -7,6 +7,7 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_SDDPROC_H_ #define CORE_FXCODEC_JBIG2_JBIG2_SDDPROC_H_ +#include #include #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h" @@ -16,20 +17,19 @@ class CJBig2_BitStream; class CJBig2_HuffmanTable; class CJBig2_Image; class CJBig2_SymbolDict; -class IFX_Pause; class CJBig2_SDDProc { public: - CJBig2_SymbolDict* decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - std::vector* gbContext, - std::vector* grContext); + std::unique_ptr decode_Arith( + CJBig2_ArithDecoder* pArithDecoder, + std::vector* gbContext, + std::vector* grContext); - CJBig2_SymbolDict* decode_Huffman(CJBig2_BitStream* pStream, - std::vector* gbContext, - std::vector* grContext, - IFX_Pause* pPause); + std::unique_ptr decode_Huffman( + CJBig2_BitStream* pStream, + std::vector* gbContext, + std::vector* grContext); - public: bool SDHUFF; bool SDREFAGG; uint32_t SDNUMINSYMS; diff --git a/core/fxcodec/jbig2/JBig2_Segment.cpp b/core/fxcodec/jbig2/JBig2_Segment.cpp index 610246b6e2ce6840a363eda05b0f2e8aef380bc9..58be8103d705c3db3bfcdc4a7094dd61423fd6cf 100644 --- a/core/fxcodec/jbig2/JBig2_Segment.cpp +++ b/core/fxcodec/jbig2/JBig2_Segment.cpp @@ -8,37 +8,17 @@ #include "core/fxcrt/fx_memory.h" -CJBig2_Segment::CJBig2_Segment() { - m_dwNumber = 0; +CJBig2_Segment::CJBig2_Segment() + : m_dwNumber(0), + m_nReferred_to_segment_count(0), + m_dwPage_association(0), + m_dwData_length(0), + m_dwHeader_Length(0), + m_dwObjNum(0), + m_dwDataOffset(0), + m_State(JBIG2_SEGMENT_HEADER_UNPARSED), + m_nResultType(JBIG2_VOID_POINTER) { m_cFlags.c = 0; - m_nReferred_to_segment_count = 0; - m_pReferred_to_segment_numbers = nullptr; - m_dwPage_association = 0; - m_dwData_length = 0; - m_dwHeader_Length = 0; - m_dwObjNum = 0; - m_dwDataOffset = 0; - m_State = JBIG2_SEGMENT_HEADER_UNPARSED; - m_nResultType = JBIG2_VOID_POINTER; - m_Result.vd = nullptr; } -CJBig2_Segment::~CJBig2_Segment() { - FX_Free(m_pReferred_to_segment_numbers); - switch (m_nResultType) { - case JBIG2_IMAGE_POINTER: - delete m_Result.im; - break; - case JBIG2_SYMBOL_DICT_POINTER: - delete m_Result.sd; - break; - case JBIG2_PATTERN_DICT_POINTER: - delete m_Result.pd; - break; - case JBIG2_HUFFMAN_TABLE_POINTER: - delete m_Result.ht; - break; - default: - FX_Free(m_Result.vd); - } -} +CJBig2_Segment::~CJBig2_Segment() {} diff --git a/core/fxcodec/jbig2/JBig2_Segment.h b/core/fxcodec/jbig2/JBig2_Segment.h index d89d6526992876a0f9089f693d612958b6b08a7a..914115b52209ddabf74e58b0f1c76329499085ec 100644 --- a/core/fxcodec/jbig2/JBig2_Segment.h +++ b/core/fxcodec/jbig2/JBig2_Segment.h @@ -7,14 +7,14 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_SEGMENT_H_ #define CORE_FXCODEC_JBIG2_JBIG2_SEGMENT_H_ +#include +#include + #include "core/fxcodec/jbig2/JBig2_Define.h" #include "core/fxcodec/jbig2/JBig2_HuffmanTable.h" #include "core/fxcodec/jbig2/JBig2_PatternDict.h" #include "core/fxcodec/jbig2/JBig2_SymbolDict.h" -#define JBIG2_GET_INT32(buf) \ - (((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3]) -#define JBIG2_GET_INT16(buf) (((buf)[0] << 8) | (buf)[1]) typedef enum { JBIG2_SEGMENT_HEADER_UNPARSED, JBIG2_SEGMENT_DATA_UNPARSED, @@ -45,7 +45,7 @@ class CJBig2_Segment { uint8_t c; } m_cFlags; int32_t m_nReferred_to_segment_count; - uint32_t* m_pReferred_to_segment_numbers; + std::vector m_Referred_to_segment_numbers; uint32_t m_dwPage_association; uint32_t m_dwData_length; @@ -54,13 +54,10 @@ class CJBig2_Segment { uint32_t m_dwDataOffset; JBig2_SegmentState m_State; JBig2_ResultType m_nResultType; - union { - CJBig2_SymbolDict* sd; - CJBig2_PatternDict* pd; - CJBig2_Image* im; - CJBig2_HuffmanTable* ht; - void* vd; - } m_Result; + std::unique_ptr m_SymbolDict; + std::unique_ptr m_PatternDict; + std::unique_ptr m_Image; + std::unique_ptr m_HuffmanTable; }; #endif // CORE_FXCODEC_JBIG2_JBIG2_SEGMENT_H_ diff --git a/core/fxcodec/jbig2/JBig2_SymbolDict.h b/core/fxcodec/jbig2/JBig2_SymbolDict.h index d6b897ce706672df241acd25af358a86bd956aa5..49289fb650bcf79eb575fe3022f18719fe4aca31 100644 --- a/core/fxcodec/jbig2/JBig2_SymbolDict.h +++ b/core/fxcodec/jbig2/JBig2_SymbolDict.h @@ -12,7 +12,6 @@ #include #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h" -#include "core/fxcrt/fx_basic.h" class CJBig2_Image; diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.cpp b/core/fxcodec/jbig2/JBig2_TrdProc.cpp index 84042dbd8ce17a29814e8ea9f4b19b3e761e9619..332e5868ac3045f6f1726b7e3391144bb6ff512b 100644 --- a/core/fxcodec/jbig2/JBig2_TrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_TrdProc.cpp @@ -12,65 +12,76 @@ #include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h" #include "core/fxcodec/jbig2/JBig2_GrrdProc.h" #include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h" +#include "core/fxcrt/maybe_owned.h" #include "third_party/base/ptr_util.h" -CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, - JBig2ArithCtx* grContext) { - std::unique_ptr pHuffmanDecoder( - new CJBig2_HuffmanDecoder(pStream)); - std::unique_ptr SBREG(new CJBig2_Image(SBW, SBH)); +CJBig2_TRDProc::CJBig2_TRDProc() {} + +CJBig2_TRDProc::~CJBig2_TRDProc() {} + +std::unique_ptr CJBig2_TRDProc::decode_Huffman( + CJBig2_BitStream* pStream, + JBig2ArithCtx* grContext) { + auto pHuffmanDecoder = pdfium::MakeUnique(pStream); + auto SBREG = pdfium::MakeUnique(SBW, SBH); SBREG->fill(SBDEFPIXEL); - int32_t STRIPT; - if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &STRIPT) != 0) + int32_t INITIAL_STRIPT; + if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &INITIAL_STRIPT) != 0) return nullptr; + FX_SAFE_INT32 STRIPT = INITIAL_STRIPT; STRIPT *= SBSTRIPS; STRIPT = -STRIPT; - int32_t FIRSTS = 0; + FX_SAFE_INT32 FIRSTS = 0; uint32_t NINSTANCES = 0; while (NINSTANCES < SBNUMINSTANCES) { - int32_t DT; - if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &DT) != 0) + int32_t INITIAL_DT; + if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &INITIAL_DT) != 0) return nullptr; + FX_SAFE_INT32 DT = INITIAL_DT; DT *= SBSTRIPS; - STRIPT = STRIPT + DT; + STRIPT += DT; bool bFirst = true; - int32_t CURS = 0; + FX_SAFE_INT32 CURS = 0; for (;;) { if (bFirst) { int32_t DFS; if (pHuffmanDecoder->decodeAValue(SBHUFFFS, &DFS) != 0) return nullptr; - FIRSTS = FIRSTS + DFS; + FIRSTS += DFS; CURS = FIRSTS; bFirst = false; } else { int32_t IDS; int32_t nVal = pHuffmanDecoder->decodeAValue(SBHUFFDS, &IDS); - if (nVal == JBIG2_OOB) { + if (nVal == JBIG2_OOB) break; - } else if (nVal != 0) { + + if (nVal != 0) return nullptr; - } else { - CURS = CURS + IDS + SBDSOFFSET; - } + + CURS += IDS; + CURS += SBDSOFFSET; } uint8_t CURT = 0; if (SBSTRIPS != 1) { uint32_t nTmp = 1; - while ((uint32_t)(1 << nTmp) < SBSTRIPS) { - nTmp++; - } + while (static_cast(1 << nTmp) < SBSTRIPS) + ++nTmp; int32_t nVal; if (pStream->readNBits(nTmp, &nVal) != 0) return nullptr; CURT = nVal; } - int32_t TI = STRIPT + CURT; - int32_t nVal = 0; + FX_SAFE_INT32 SAFE_TI = STRIPT + CURT; + if (!SAFE_TI.IsValid()) + return nullptr; + + int32_t TI = SAFE_TI.ValueOrDie(); + pdfium::base::CheckedNumeric nVal = 0; int32_t nBits = 0; uint32_t IDI; for (;;) { @@ -78,23 +89,26 @@ CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, if (pStream->read1Bit(&nTmp) != 0) return nullptr; - nVal = (nVal << 1) | nTmp; - nBits++; - for (IDI = 0; IDI < SBNUMSYMS; IDI++) { + nVal <<= 1; + if (!nVal.IsValid()) + return nullptr; + + nVal |= nTmp; + ++nBits; + for (IDI = 0; IDI < SBNUMSYMS; ++IDI) { if ((nBits == SBSYMCODES[IDI].codelen) && - (nVal == SBSYMCODES[IDI].code)) { + (nVal.ValueOrDie() == SBSYMCODES[IDI].code)) { break; } } - if (IDI < SBNUMSYMS) { + if (IDI < SBNUMSYMS) break; - } } bool RI = 0; - if (SBREFINE != 0 && pStream->read1Bit(&RI) != 0) { + if (SBREFINE != 0 && pStream->read1Bit(&RI) != 0) return nullptr; - } - CJBig2_Image* IBI = nullptr; + + MaybeOwned IBI; if (RI == 0) { IBI = SBSYMS[IDI]; } else { @@ -102,11 +116,12 @@ CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, int32_t RDHI; int32_t RDXI; int32_t RDYI; + int32_t HUFFRSIZE; if ((pHuffmanDecoder->decodeAValue(SBHUFFRDW, &RDWI) != 0) || (pHuffmanDecoder->decodeAValue(SBHUFFRDH, &RDHI) != 0) || (pHuffmanDecoder->decodeAValue(SBHUFFRDX, &RDXI) != 0) || (pHuffmanDecoder->decodeAValue(SBHUFFRDY, &RDYI) != 0) || - (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE, &nVal) != 0)) { + (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE, &HUFFRSIZE) != 0)) { return nullptr; } pStream->alignByte(); @@ -117,10 +132,12 @@ CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, uint32_t WOI = IBOI->width(); uint32_t HOI = IBOI->height(); - if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0) + if (static_cast(WOI + RDWI) < 0 || + static_cast(HOI + RDHI) < 0) { return nullptr; + } - std::unique_ptr pGRRD(new CJBig2_GRRDProc()); + auto pGRRD = pdfium::MakeUnique(); pGRRD->GRW = WOI + RDWI; pGRRD->GRH = HOI + RDHI; pGRRD->GRTEMPLATE = SBRTEMPLATE; @@ -133,104 +150,90 @@ CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, pGRRD->GRAT[2] = SBRAT[2]; pGRRD->GRAT[3] = SBRAT[3]; - { - std::unique_ptr pArithDecoder( - new CJBig2_ArithDecoder(pStream)); - IBI = pGRRD->decode(pArithDecoder.get(), grContext); - if (!IBI) - return nullptr; - } + auto pArithDecoder = pdfium::MakeUnique(pStream); + IBI = pGRRD->decode(pArithDecoder.get(), grContext); + if (!IBI) + return nullptr; pStream->alignByte(); pStream->offset(2); - if ((uint32_t)nVal != (pStream->getOffset() - nTmp)) { - delete IBI; + if (static_cast(HUFFRSIZE) != (pStream->getOffset() - nTmp)) return nullptr; - } } - if (!IBI) { + if (!IBI) continue; - } + uint32_t WI = IBI->width(); uint32_t HI = IBI->height(); if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) || (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) { - CURS = CURS + WI - 1; + CURS += WI - 1; } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) || (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) { - CURS = CURS + HI - 1; + CURS += HI - 1; } - int32_t SI = CURS; + if (!CURS.IsValid()) + return nullptr; + + int32_t SI = CURS.ValueOrDie(); if (TRANSPOSED == 0) { switch (REFCORNER) { case JBIG2_CORNER_TOPLEFT: - SBREG->composeFrom(SI, TI, IBI, SBCOMBOP); + SBREG->composeFrom(SI, TI, IBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_TOPRIGHT: - SBREG->composeFrom(SI - WI + 1, TI, IBI, SBCOMBOP); + SBREG->composeFrom(SI - WI + 1, TI, IBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMLEFT: - SBREG->composeFrom(SI, TI - HI + 1, IBI, SBCOMBOP); + SBREG->composeFrom(SI, TI - HI + 1, IBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMRIGHT: - SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI, SBCOMBOP); + SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI.Get(), SBCOMBOP); break; } } else { switch (REFCORNER) { case JBIG2_CORNER_TOPLEFT: - SBREG->composeFrom(TI, SI, IBI, SBCOMBOP); + SBREG->composeFrom(TI, SI, IBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_TOPRIGHT: - SBREG->composeFrom(TI - WI + 1, SI, IBI, SBCOMBOP); + SBREG->composeFrom(TI - WI + 1, SI, IBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMLEFT: - SBREG->composeFrom(TI, SI - HI + 1, IBI, SBCOMBOP); + SBREG->composeFrom(TI, SI - HI + 1, IBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMRIGHT: - SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI, SBCOMBOP); + SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI.Get(), SBCOMBOP); break; } } - if (RI != 0) { - delete IBI; - } if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) || (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) { - CURS = CURS + WI - 1; + CURS += WI - 1; } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) || (REFCORNER == JBIG2_CORNER_TOPRIGHT))) { - CURS = CURS + HI - 1; + CURS += HI - 1; } NINSTANCES = NINSTANCES + 1; } } - return SBREG.release(); + return SBREG; } -CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext, - JBig2IntDecoderState* pIDS) { - std::unique_ptr IADT; - std::unique_ptr IAFS; - std::unique_ptr IADS; - std::unique_ptr IAIT; - std::unique_ptr IARI; - std::unique_ptr IARDW; - std::unique_ptr IARDH; - std::unique_ptr IARDX; - std::unique_ptr IARDY; - std::unique_ptr IAID; - CJBig2_ArithIntDecoder* pIADT; - CJBig2_ArithIntDecoder* pIAFS; - CJBig2_ArithIntDecoder* pIADS; - CJBig2_ArithIntDecoder* pIAIT; - CJBig2_ArithIntDecoder* pIARI; - CJBig2_ArithIntDecoder* pIARDW; - CJBig2_ArithIntDecoder* pIARDH; - CJBig2_ArithIntDecoder* pIARDX; - CJBig2_ArithIntDecoder* pIARDY; - CJBig2_ArithIaidDecoder* pIAID; +std::unique_ptr CJBig2_TRDProc::decode_Arith( + CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext, + JBig2IntDecoderState* pIDS) { + MaybeOwned pIADT; + MaybeOwned pIAFS; + MaybeOwned pIADS; + MaybeOwned pIAIT; + MaybeOwned pIARI; + MaybeOwned pIARDW; + MaybeOwned pIARDH; + MaybeOwned pIARDX; + MaybeOwned pIARDY; + MaybeOwned pIAID; if (pIDS) { pIADT = pIDS->IADT; pIAFS = pIDS->IAFS; @@ -243,41 +246,35 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, pIARDY = pIDS->IARDY; pIAID = pIDS->IAID; } else { - IADT = pdfium::MakeUnique(); - IAFS = pdfium::MakeUnique(); - IADS = pdfium::MakeUnique(); - IAIT = pdfium::MakeUnique(); - IARI = pdfium::MakeUnique(); - IARDW = pdfium::MakeUnique(); - IARDH = pdfium::MakeUnique(); - IARDX = pdfium::MakeUnique(); - IARDY = pdfium::MakeUnique(); - IAID = pdfium::MakeUnique(SBSYMCODELEN); - pIADT = IADT.get(); - pIAFS = IAFS.get(); - pIADS = IADS.get(); - pIAIT = IAIT.get(); - pIARI = IARI.get(); - pIARDW = IARDW.get(); - pIARDH = IARDH.get(); - pIARDX = IARDX.get(); - pIARDY = IARDY.get(); - pIAID = IAID.get(); + pIADT = pdfium::MakeUnique(); + pIAFS = pdfium::MakeUnique(); + pIADS = pdfium::MakeUnique(); + pIAIT = pdfium::MakeUnique(); + pIARI = pdfium::MakeUnique(); + pIARDW = pdfium::MakeUnique(); + pIARDH = pdfium::MakeUnique(); + pIARDX = pdfium::MakeUnique(); + pIARDY = pdfium::MakeUnique(); + pIAID = pdfium::MakeUnique(SBSYMCODELEN); } - std::unique_ptr SBREG(new CJBig2_Image(SBW, SBH)); + auto SBREG = pdfium::MakeUnique(SBW, SBH); SBREG->fill(SBDEFPIXEL); - int32_t STRIPT; - if (!pIADT->decode(pArithDecoder, &STRIPT)) + int32_t INITIAL_STRIPT; + if (!pIADT->decode(pArithDecoder, &INITIAL_STRIPT)) return nullptr; + + FX_SAFE_INT32 STRIPT = INITIAL_STRIPT; STRIPT *= SBSTRIPS; STRIPT = -STRIPT; - int32_t FIRSTS = 0; + FX_SAFE_INT32 FIRSTS = 0; uint32_t NINSTANCES = 0; while (NINSTANCES < SBNUMINSTANCES) { - int32_t CURS = 0; - int32_t DT; - if (!pIADT->decode(pArithDecoder, &DT)) + FX_SAFE_INT32 CURS = 0; + int32_t INITIAL_DT; + if (!pIADT->decode(pArithDecoder, &INITIAL_DT)) return nullptr; + + FX_SAFE_INT32 DT = INITIAL_DT; DT *= SBSTRIPS; STRIPT += DT; bool bFirst = true; @@ -292,16 +289,22 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, int32_t IDS; if (!pIADS->decode(pArithDecoder, &IDS)) break; - CURS += IDS + SBDSOFFSET; + + CURS += IDS; + CURS += SBDSOFFSET; } - if (NINSTANCES >= SBNUMINSTANCES) { + if (NINSTANCES >= SBNUMINSTANCES) break; - } + int CURT = 0; if (SBSTRIPS != 1) pIAIT->decode(pArithDecoder, &CURT); - int32_t TI = STRIPT + CURT; + FX_SAFE_INT32 SAFE_TI = STRIPT + CURT; + if (!SAFE_TI.IsValid()) + return nullptr; + + int32_t TI = SAFE_TI.ValueOrDie(); uint32_t IDI; pIAID->decode(pArithDecoder, &IDI); if (IDI >= SBNUMSYMS) @@ -313,8 +316,7 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, else pIARI->decode(pArithDecoder, &RI); - std::unique_ptr IBI; - CJBig2_Image* pIBI; + MaybeOwned pIBI; if (RI == 0) { pIBI = SBSYMS[IDI]; } else { @@ -332,10 +334,12 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, uint32_t WOI = IBOI->width(); uint32_t HOI = IBOI->height(); - if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0) + if (static_cast(WOI + RDWI) < 0 || + static_cast(HOI + RDHI) < 0) { return nullptr; + } - std::unique_ptr pGRRD(new CJBig2_GRRDProc()); + auto pGRRD = pdfium::MakeUnique(); pGRRD->GRW = WOI + RDWI; pGRRD->GRH = HOI + RDHI; pGRRD->GRTEMPLATE = SBRTEMPLATE; @@ -347,8 +351,7 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, pGRRD->GRAT[1] = SBRAT[1]; pGRRD->GRAT[2] = SBRAT[2]; pGRRD->GRAT[3] = SBRAT[3]; - IBI.reset(pGRRD->decode(pArithDecoder, grContext)); - pIBI = IBI.get(); + pIBI = pGRRD->decode(pArithDecoder, grContext); } if (!pIBI) return nullptr; @@ -362,35 +365,38 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) { CURS += HI - 1; } - int32_t SI = CURS; + if (!CURS.IsValid()) + return nullptr; + + int32_t SI = CURS.ValueOrDie(); if (TRANSPOSED == 0) { switch (REFCORNER) { case JBIG2_CORNER_TOPLEFT: - SBREG->composeFrom(SI, TI, pIBI, SBCOMBOP); + SBREG->composeFrom(SI, TI, pIBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_TOPRIGHT: - SBREG->composeFrom(SI - WI + 1, TI, pIBI, SBCOMBOP); + SBREG->composeFrom(SI - WI + 1, TI, pIBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMLEFT: - SBREG->composeFrom(SI, TI - HI + 1, pIBI, SBCOMBOP); + SBREG->composeFrom(SI, TI - HI + 1, pIBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMRIGHT: - SBREG->composeFrom(SI - WI + 1, TI - HI + 1, pIBI, SBCOMBOP); + SBREG->composeFrom(SI - WI + 1, TI - HI + 1, pIBI.Get(), SBCOMBOP); break; } } else { switch (REFCORNER) { case JBIG2_CORNER_TOPLEFT: - SBREG->composeFrom(TI, SI, pIBI, SBCOMBOP); + SBREG->composeFrom(TI, SI, pIBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_TOPRIGHT: - SBREG->composeFrom(TI - WI + 1, SI, pIBI, SBCOMBOP); + SBREG->composeFrom(TI - WI + 1, SI, pIBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMLEFT: - SBREG->composeFrom(TI, SI - HI + 1, pIBI, SBCOMBOP); + SBREG->composeFrom(TI, SI - HI + 1, pIBI.Get(), SBCOMBOP); break; case JBIG2_CORNER_BOTTOMRIGHT: - SBREG->composeFrom(TI - WI + 1, SI - HI + 1, pIBI, SBCOMBOP); + SBREG->composeFrom(TI - WI + 1, SI - HI + 1, pIBI.Get(), SBCOMBOP); break; } } @@ -404,5 +410,5 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, ++NINSTANCES; } } - return SBREG.release(); + return SBREG; } diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.h b/core/fxcodec/jbig2/JBig2_TrdProc.h index be50ec152f42f44faaf70757ceeea5de84d79487..a66415b0bd13358b80bfc8d99f89c90413bb589b 100644 --- a/core/fxcodec/jbig2/JBig2_TrdProc.h +++ b/core/fxcodec/jbig2/JBig2_TrdProc.h @@ -7,6 +7,9 @@ #ifndef CORE_FXCODEC_JBIG2_JBIG2_TRDPROC_H_ #define CORE_FXCODEC_JBIG2_JBIG2_TRDPROC_H_ +#include +#include + #include "core/fxcodec/jbig2/JBig2_Image.h" #include "core/fxcrt/fx_system.h" @@ -40,12 +43,15 @@ enum JBig2Corner { class CJBig2_TRDProc { public: - CJBig2_Image* decode_Huffman(CJBig2_BitStream* pStream, - JBig2ArithCtx* grContext); + CJBig2_TRDProc(); + ~CJBig2_TRDProc(); + + std::unique_ptr decode_Huffman(CJBig2_BitStream* pStream, + JBig2ArithCtx* grContext); - CJBig2_Image* decode_Arith(CJBig2_ArithDecoder* pArithDecoder, - JBig2ArithCtx* grContext, - JBig2IntDecoderState* pIDS); + std::unique_ptr decode_Arith(CJBig2_ArithDecoder* pArithDecoder, + JBig2ArithCtx* grContext, + JBig2IntDecoderState* pIDS); bool SBHUFF; bool SBREFINE; @@ -55,7 +61,7 @@ class CJBig2_TRDProc { uint32_t SBSTRIPS; uint32_t SBNUMSYMS; - JBig2HuffmanCode* SBSYMCODES; + std::vector SBSYMCODES; uint8_t SBSYMCODELEN; CJBig2_Image** SBSYMS; diff --git a/core/fxcodec/lbmp/fx_bmp.cpp b/core/fxcodec/lbmp/fx_bmp.cpp index 2b072a4a0c061038f9c6585e4ddaa6186ea3faa6..73be66e2568520f4377b24c5a24c3caf4fec3ff2 100644 --- a/core/fxcodec/lbmp/fx_bmp.cpp +++ b/core/fxcodec/lbmp/fx_bmp.cpp @@ -7,337 +7,357 @@ #include "core/fxcodec/lbmp/fx_bmp.h" #include +#include + +#include "core/fxcrt/fx_system.h" +#include "third_party/base/logging.h" +#include "third_party/base/ptr_util.h" + +static_assert(sizeof(BmpFileHeader) == 14, + "BmpFileHeader should have a size of 14"); namespace { const size_t kBmpCoreHeaderSize = 12; const size_t kBmpInfoHeaderSize = 40; -// TODO(thestig): Replace with FXDWORD_GET_LSBFIRST? -uint32_t GetDWord_LSBFirst(uint8_t* p) { - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +uint8_t HalfRoundUp(uint8_t value) { + uint16_t value16 = value; + return static_cast((value16 + 1) / 2); } -void SetDWord_LSBFirst(uint8_t* p, uint32_t v) { - p[0] = (uint8_t)v; - p[1] = (uint8_t)(v >> 8); - p[2] = (uint8_t)(v >> 16); - p[3] = (uint8_t)(v >> 24); -} } // namespace -uint16_t GetWord_LSBFirst(uint8_t* p) { - return p[0] | (p[1] << 8); -} -void SetWord_LSBFirst(uint8_t* p, uint16_t v) { - p[0] = (uint8_t)v; - p[1] = (uint8_t)(v >> 8); -} -void bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg) { - if (bmp_ptr && bmp_ptr->bmp_error_fn) { - bmp_ptr->bmp_error_fn(bmp_ptr, err_msg); - } +BMPDecompressor::BMPDecompressor() + : context_ptr(nullptr), + next_in(nullptr), + header_offset(0), + width(0), + height(0), + compress_flag(0), + components(0), + src_row_bytes(0), + out_row_bytes(0), + bitCounts(0), + color_used(0), + imgTB_flag(false), + pal_num(0), + pal_type(0), + data_size(0), + img_data_offset(0), + img_ifh_size(0), + row_num(0), + col_num(0), + dpi_x(0), + dpi_y(0), + mask_red(0), + mask_green(0), + mask_blue(0), + avail_in(0), + skip_size(0), + decode_status(BMP_D_STATUS_HEADER) {} + +BMPDecompressor::~BMPDecompressor() {} + +void BMPDecompressor::Error() { + longjmp(jmpbuf, 1); } -bmp_decompress_struct_p bmp_create_decompress() { - bmp_decompress_struct_p bmp_ptr = FX_Alloc(bmp_decompress_struct, 1); - FXSYS_memset(bmp_ptr, 0, sizeof(bmp_decompress_struct)); - bmp_ptr->decode_status = BMP_D_STATUS_HEADER; - bmp_ptr->bmp_header_ptr = FX_Alloc(BmpFileHeader, 1); - return bmp_ptr; + +void BMPDecompressor::ReadScanline(uint32_t row_num, + const std::vector& row_buf) { + auto* p = reinterpret_cast(context_ptr); + p->m_pDelegate->BmpReadScanline(row_num, row_buf); } -void bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr) { - if (!bmp_ptr_ptr || !*bmp_ptr_ptr) - return; - bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr; - *bmp_ptr_ptr = nullptr; - if (bmp_ptr->out_row_buffer) { - FX_Free(bmp_ptr->out_row_buffer); - } - FX_Free(bmp_ptr->pal_ptr); - FX_Free(bmp_ptr->bmp_header_ptr); - FX_Free(bmp_ptr); +bool BMPDecompressor::GetDataPosition(uint32_t rcd_pos) { + auto* p = reinterpret_cast(context_ptr); + return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos); } -int32_t bmp_read_header(bmp_decompress_struct_p bmp_ptr) { - if (!bmp_ptr) - return 0; - - uint32_t skip_size_org = bmp_ptr->skip_size; - if (bmp_ptr->decode_status == BMP_D_STATUS_HEADER) { - ASSERT(sizeof(BmpFileHeader) == 14); - BmpFileHeader* bmp_header_ptr = nullptr; - if (!bmp_read_data(bmp_ptr, (uint8_t**)&bmp_header_ptr, 14)) + +int32_t BMPDecompressor::ReadHeader() { + uint32_t skip_size_org = skip_size; + if (decode_status == BMP_D_STATUS_HEADER) { + BmpFileHeader* pBmp_header = nullptr; + if (!ReadData(reinterpret_cast(&pBmp_header), + sizeof(BmpFileHeader))) { return 2; + } - bmp_ptr->bmp_header_ptr->bfType = - GetWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfType); - bmp_ptr->bmp_header_ptr->bfOffBits = - GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfOffBits); - bmp_ptr->data_size = GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfSize); - if (bmp_ptr->bmp_header_ptr->bfType != BMP_SIGNATURE) { - bmp_error(bmp_ptr, "Not A Bmp Image"); - return 0; + pBmp_header->bfType = + FXWORD_GET_LSBFIRST(reinterpret_cast(&pBmp_header->bfType)); + pBmp_header->bfOffBits = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_header->bfOffBits)); + data_size = + FXDWORD_GET_LSBFIRST(reinterpret_cast(&pBmp_header->bfSize)); + if (pBmp_header->bfType != BMP_SIGNATURE) { + Error(); + NOTREACHED(); } - if (bmp_ptr->avail_in < sizeof(uint32_t)) { - bmp_ptr->skip_size = skip_size_org; + if (avail_in < sizeof(uint32_t)) { + skip_size = skip_size_org; return 2; } - bmp_ptr->img_ifh_size = - GetDWord_LSBFirst(bmp_ptr->next_in + bmp_ptr->skip_size); - bmp_ptr->pal_type = 0; + img_ifh_size = + FXDWORD_GET_LSBFIRST(static_cast(next_in + skip_size)); + pal_type = 0; static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize, "BmpCoreHeader has wrong size"); static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize, "BmpInfoHeader has wrong size"); - switch (bmp_ptr->img_ifh_size) { + switch (img_ifh_size) { case kBmpCoreHeaderSize: { - bmp_ptr->pal_type = 1; - BmpCoreHeaderPtr bmp_core_header_ptr = nullptr; - if (!bmp_read_data(bmp_ptr, (uint8_t**)&bmp_core_header_ptr, - bmp_ptr->img_ifh_size)) { - bmp_ptr->skip_size = skip_size_org; + pal_type = 1; + BmpCoreHeader* pBmp_core_header = nullptr; + if (!ReadData(reinterpret_cast(&pBmp_core_header), + img_ifh_size)) { + skip_size = skip_size_org; return 2; } - bmp_ptr->width = - GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcWidth); - bmp_ptr->height = - GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcHeight); - bmp_ptr->bitCounts = - GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcBitCount); - bmp_ptr->compress_flag = BMP_RGB; - bmp_ptr->imgTB_flag = false; + width = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_core_header->bcWidth)); + height = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_core_header->bcHeight)); + bitCounts = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_core_header->bcBitCount)); + compress_flag = BMP_RGB; + imgTB_flag = false; } break; case kBmpInfoHeaderSize: { - BmpInfoHeaderPtr bmp_info_header_ptr = nullptr; - if (!bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, - bmp_ptr->img_ifh_size)) { - bmp_ptr->skip_size = skip_size_org; + BmpInfoHeader* pBmp_info_header = nullptr; + if (!ReadData(reinterpret_cast(&pBmp_info_header), + img_ifh_size)) { + skip_size = skip_size_org; return 2; } - bmp_ptr->width = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth); - bmp_ptr->height = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight); - bmp_ptr->bitCounts = - GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount); - bmp_ptr->compress_flag = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression); - bmp_ptr->color_used = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed); - bmp_ptr->dpi_x = (int32_t)GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter); - bmp_ptr->dpi_y = (int32_t)GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter); - if (bmp_ptr->height < 0) { - bmp_ptr->height = -bmp_ptr->height; - bmp_ptr->imgTB_flag = true; - } + width = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biWidth)); + int32_t signed_height = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biHeight)); + bitCounts = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biBitCount)); + compress_flag = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biCompression)); + color_used = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biClrUsed)); + dpi_x = static_cast(FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biXPelsPerMeter))); + dpi_y = static_cast(FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biYPelsPerMeter))); + SetHeight(signed_height); } break; default: { - if (bmp_ptr->img_ifh_size > + if (img_ifh_size > std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) { - BmpInfoHeaderPtr bmp_info_header_ptr = nullptr; - if (!bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, - bmp_ptr->img_ifh_size)) { - bmp_ptr->skip_size = skip_size_org; + BmpInfoHeader* pBmp_info_header = nullptr; + if (!ReadData(reinterpret_cast(&pBmp_info_header), + img_ifh_size)) { + skip_size = skip_size_org; return 2; } uint16_t biPlanes; - bmp_ptr->width = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth); - bmp_ptr->height = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight); - bmp_ptr->bitCounts = - GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount); - bmp_ptr->compress_flag = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression); - bmp_ptr->color_used = - GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed); - biPlanes = GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biPlanes); - bmp_ptr->dpi_x = GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter); - bmp_ptr->dpi_y = GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter); - if (bmp_ptr->height < 0) { - bmp_ptr->height = -bmp_ptr->height; - bmp_ptr->imgTB_flag = true; - } - if (bmp_ptr->compress_flag == BMP_RGB && biPlanes == 1 && - bmp_ptr->color_used == 0) { + width = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biWidth)); + int32_t signed_height = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biHeight)); + bitCounts = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biBitCount)); + compress_flag = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biCompression)); + color_used = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biClrUsed)); + biPlanes = FXWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biPlanes)); + dpi_x = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biXPelsPerMeter)); + dpi_y = FXDWORD_GET_LSBFIRST( + reinterpret_cast(&pBmp_info_header->biYPelsPerMeter)); + SetHeight(signed_height); + if (compress_flag == BMP_RGB && biPlanes == 1 && color_used == 0) break; - } } - bmp_error(bmp_ptr, "Unsupported Bmp File"); - return 0; + Error(); + NOTREACHED(); } } - if (bmp_ptr->width <= 0 || bmp_ptr->compress_flag > BMP_BITFIELDS) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (width > BMP_MAX_WIDTH || compress_flag > BMP_BITFIELDS) { + Error(); + NOTREACHED(); } - switch (bmp_ptr->bitCounts) { + switch (bitCounts) { case 1: case 4: case 8: case 16: case 24: { - if (bmp_ptr->color_used > ((uint32_t)1) << bmp_ptr->bitCounts) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (color_used > 1U << bitCounts) { + Error(); + NOTREACHED(); } } case 32: break; default: - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + Error(); + NOTREACHED(); } - bmp_ptr->src_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, bmp_ptr->bitCounts); - switch (bmp_ptr->bitCounts) { + src_row_bytes = BMP_WIDTHBYTES(width, bitCounts); + switch (bitCounts) { case 1: case 4: case 8: - bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 8); - bmp_ptr->components = 1; + out_row_bytes = BMP_WIDTHBYTES(width, 8); + components = 1; break; case 16: case 24: - bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 24); - bmp_ptr->components = 3; + out_row_bytes = BMP_WIDTHBYTES(width, 24); + components = 3; break; case 32: - bmp_ptr->out_row_bytes = bmp_ptr->src_row_bytes; - bmp_ptr->components = 4; + out_row_bytes = src_row_bytes; + components = 4; break; } - FX_Free(bmp_ptr->out_row_buffer); + out_row_buffer.clear(); - if (bmp_ptr->out_row_bytes <= 0) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (out_row_bytes <= 0) { + Error(); + NOTREACHED(); } - bmp_ptr->out_row_buffer = FX_Alloc(uint8_t, bmp_ptr->out_row_bytes); - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_PAL); + out_row_buffer.resize(out_row_bytes); + SaveDecodingStatus(BMP_D_STATUS_PAL); } - if (bmp_ptr->decode_status == BMP_D_STATUS_PAL) { - skip_size_org = bmp_ptr->skip_size; - if (bmp_ptr->compress_flag == BMP_BITFIELDS) { - if (bmp_ptr->bitCounts != 16 && bmp_ptr->bitCounts != 32) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (decode_status == BMP_D_STATUS_PAL) { + skip_size_org = skip_size; + if (compress_flag == BMP_BITFIELDS) { + if (bitCounts != 16 && bitCounts != 32) { + Error(); + NOTREACHED(); } uint32_t* mask; - if (bmp_read_data(bmp_ptr, (uint8_t**)&mask, 3 * sizeof(uint32_t)) == + if (ReadData(reinterpret_cast(&mask), 3 * sizeof(uint32_t)) == nullptr) { - bmp_ptr->skip_size = skip_size_org; + skip_size = skip_size_org; return 2; } - bmp_ptr->mask_red = GetDWord_LSBFirst((uint8_t*)&mask[0]); - bmp_ptr->mask_green = GetDWord_LSBFirst((uint8_t*)&mask[1]); - bmp_ptr->mask_blue = GetDWord_LSBFirst((uint8_t*)&mask[2]); - if (bmp_ptr->mask_red & bmp_ptr->mask_green || - bmp_ptr->mask_red & bmp_ptr->mask_blue || - bmp_ptr->mask_green & bmp_ptr->mask_blue) { - bmp_error(bmp_ptr, "The Bitfield Bmp File Is Corrupt"); - return 0; - } - if (bmp_ptr->bmp_header_ptr->bfOffBits < 26 + bmp_ptr->img_ifh_size) { - bmp_ptr->bmp_header_ptr->bfOffBits = 26 + bmp_ptr->img_ifh_size; + mask_red = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[0])); + mask_green = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[1])); + mask_blue = FXDWORD_GET_LSBFIRST(reinterpret_cast(&mask[2])); + if (mask_red & mask_green || mask_red & mask_blue || + mask_green & mask_blue) { + Error(); + NOTREACHED(); } - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE); + header_offset = std::max(header_offset, 26 + img_ifh_size); + SaveDecodingStatus(BMP_D_STATUS_DATA_PRE); return 1; - } else if (bmp_ptr->bitCounts == 16) { - bmp_ptr->mask_red = 0x7C00; - bmp_ptr->mask_green = 0x03E0; - bmp_ptr->mask_blue = 0x001F; + } else if (bitCounts == 16) { + mask_red = 0x7C00; + mask_green = 0x03E0; + mask_blue = 0x001F; } - bmp_ptr->pal_num = 0; - if (bmp_ptr->bitCounts < 16) { - bmp_ptr->pal_num = 1 << bmp_ptr->bitCounts; - if (bmp_ptr->color_used != 0) { - bmp_ptr->pal_num = bmp_ptr->color_used; - } + pal_num = 0; + if (bitCounts < 16) { + pal_num = 1 << bitCounts; + if (color_used != 0) + pal_num = color_used; uint8_t* src_pal_ptr = nullptr; - uint32_t src_pal_size = bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4); - if (bmp_read_data(bmp_ptr, (uint8_t**)&src_pal_ptr, src_pal_size) == - nullptr) { - bmp_ptr->skip_size = skip_size_org; + uint32_t src_pal_size = pal_num * (pal_type ? 3 : 4); + if (ReadData(&src_pal_ptr, src_pal_size) == nullptr) { + skip_size = skip_size_org; return 2; } - FX_Free(bmp_ptr->pal_ptr); - bmp_ptr->pal_ptr = FX_Alloc(uint32_t, bmp_ptr->pal_num); + palette.resize(pal_num); int32_t src_pal_index = 0; - if (bmp_ptr->pal_type == BMP_PAL_OLD) { - while (src_pal_index < bmp_ptr->pal_num) { - bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE( + if (pal_type == BMP_PAL_OLD) { + while (src_pal_index < pal_num) { + palette[src_pal_index++] = BMP_PAL_ENCODE( 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]); src_pal_ptr += 3; } } else { - while (src_pal_index < bmp_ptr->pal_num) { - bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE( + while (src_pal_index < pal_num) { + palette[src_pal_index++] = BMP_PAL_ENCODE( src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]); src_pal_ptr += 4; } } } - if (bmp_ptr->bmp_header_ptr->bfOffBits < - 14 + bmp_ptr->img_ifh_size + - bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4)) { - bmp_ptr->bmp_header_ptr->bfOffBits = - 14 + bmp_ptr->img_ifh_size + - bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4); - } - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE); + header_offset = std::max(header_offset, + 14 + img_ifh_size + pal_num * (pal_type ? 3 : 4)); + SaveDecodingStatus(BMP_D_STATUS_DATA_PRE); } return 1; } -int32_t bmp_decode_image(bmp_decompress_struct_p bmp_ptr) { - if (bmp_ptr->decode_status == BMP_D_STATUS_DATA_PRE) { - bmp_ptr->avail_in = 0; - if (!bmp_ptr->bmp_get_data_position_fn( - bmp_ptr, bmp_ptr->bmp_header_ptr->bfOffBits)) { - bmp_ptr->decode_status = BMP_D_STATUS_TAIL; - bmp_error(bmp_ptr, "The Bmp File Is Corrupt, Unexpected Stream Offset"); - return 0; - } - bmp_ptr->row_num = 0; - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + +bool BMPDecompressor::ValidateFlag() const { + switch (compress_flag) { + case BMP_RGB: + case BMP_BITFIELDS: + case BMP_RLE8: + case BMP_RLE4: + return true; + default: + return false; } - if (bmp_ptr->decode_status == BMP_D_STATUS_DATA) { - switch (bmp_ptr->compress_flag) { - case BMP_RGB: - case BMP_BITFIELDS: - return bmp_decode_rgb(bmp_ptr); - case BMP_RLE8: - return bmp_decode_rle8(bmp_ptr); - case BMP_RLE4: - return bmp_decode_rle4(bmp_ptr); +} + +int32_t BMPDecompressor::DecodeImage() { + if (decode_status == BMP_D_STATUS_DATA_PRE) { + avail_in = 0; + if (!GetDataPosition(header_offset)) { + decode_status = BMP_D_STATUS_TAIL; + Error(); + NOTREACHED(); } + row_num = 0; + SaveDecodingStatus(BMP_D_STATUS_DATA); + } + if (decode_status != BMP_D_STATUS_DATA || !ValidateFlag()) { + Error(); + NOTREACHED(); + } + switch (compress_flag) { + case BMP_RGB: + case BMP_BITFIELDS: + return DecodeRGB(); + case BMP_RLE8: + return DecodeRLE8(); + case BMP_RLE4: + return DecodeRLE4(); + default: + return 0; + } +} + +bool BMPDecompressor::ValidateColorIndex(uint8_t val) { + if (val >= pal_num) { + Error(); + NOTREACHED(); } - bmp_error(bmp_ptr, "Any Uncontrol Error"); - return 0; + return true; } -int32_t bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) { - uint8_t* row_buf = bmp_ptr->out_row_buffer; + +int32_t BMPDecompressor::DecodeRGB() { uint8_t* des_buf = nullptr; - while (bmp_ptr->row_num < bmp_ptr->height) { - if (!bmp_read_data(bmp_ptr, &des_buf, bmp_ptr->src_row_bytes)) + while (row_num < height) { + size_t idx = 0; + if (!ReadData(&des_buf, src_row_bytes)) return 2; - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); - switch (bmp_ptr->bitCounts) { + SaveDecodingStatus(BMP_D_STATUS_DATA); + switch (bitCounts) { case 1: { - for (int32_t col = 0; col < bmp_ptr->width; col++) { - *row_buf++ = des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00; - } + for (uint32_t col = 0; col < width; ++col) + out_row_buffer[idx++] = + des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00; } break; case 4: { - for (int32_t col = 0; col < bmp_ptr->width; col++) { - *row_buf++ = (col & 0x01) ? (des_buf[col >> 1] & 0x0F) - : ((des_buf[col >> 1] & 0xF0) >> 4); + for (uint32_t col = 0; col < width; ++col) { + out_row_buffer[idx++] = (col & 0x01) + ? (des_buf[col >> 1] & 0x0F) + : ((des_buf[col >> 1] & 0xF0) >> 4); } } break; case 16: { @@ -346,15 +366,12 @@ int32_t bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) { uint8_t green_bits = 0; uint8_t red_bits = 0; for (int32_t i = 0; i < 16; i++) { - if ((bmp_ptr->mask_blue >> i) & 0x01) { + if ((mask_blue >> i) & 0x01) blue_bits++; - } - if ((bmp_ptr->mask_green >> i) & 0x01) { + if ((mask_green >> i) & 0x01) green_bits++; - } - if ((bmp_ptr->mask_red >> i) & 0x01) { + if ((mask_red >> i) & 0x01) red_bits++; - } } green_bits += blue_bits; red_bits += green_bits; @@ -363,577 +380,292 @@ int32_t bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) { blue_bits = 8 - blue_bits; green_bits -= 8; red_bits -= 8; - for (int32_t col = 0; col < bmp_ptr->width; col++) { - *buf = GetWord_LSBFirst((uint8_t*)buf); - *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_blue) << blue_bits); - *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_green) >> green_bits); - *row_buf++ = (uint8_t)((*buf++ & bmp_ptr->mask_red) >> red_bits); + for (uint32_t col = 0; col < width; ++col) { + *buf = FXWORD_GET_LSBFIRST(reinterpret_cast(buf)); + out_row_buffer[idx++] = + static_cast((*buf & mask_blue) << blue_bits); + out_row_buffer[idx++] = + static_cast((*buf & mask_green) >> green_bits); + out_row_buffer[idx++] = + static_cast((*buf++ & mask_red) >> red_bits); } } break; case 8: case 24: case 32: - FXSYS_memcpy(bmp_ptr->out_row_buffer, des_buf, bmp_ptr->src_row_bytes); + std::copy(des_buf, des_buf + src_row_bytes, out_row_buffer.begin()); + idx += src_row_bytes; break; } - row_buf = bmp_ptr->out_row_buffer; - bmp_ptr->bmp_get_row_fn(bmp_ptr, - bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); + for (uint8_t byte : out_row_buffer) { + if (!ValidateColorIndex(byte)) + return 0; + } + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); } - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + SaveDecodingStatus(BMP_D_STATUS_TAIL); return 1; } -int32_t bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) { + +int32_t BMPDecompressor::DecodeRLE8() { uint8_t* first_byte_ptr = nullptr; uint8_t* second_byte_ptr = nullptr; - bmp_ptr->col_num = 0; + col_num = 0; while (true) { - uint32_t skip_size_org = bmp_ptr->skip_size; - if (!bmp_read_data(bmp_ptr, &first_byte_ptr, 1)) + uint32_t skip_size_org = skip_size; + if (!ReadData(&first_byte_ptr, 1)) return 2; switch (*first_byte_ptr) { case RLE_MARKER: { - if (!bmp_read_data(bmp_ptr, &first_byte_ptr, 1)) { - bmp_ptr->skip_size = skip_size_org; + if (!ReadData(&first_byte_ptr, 1)) { + skip_size = skip_size_org; return 2; } switch (*first_byte_ptr) { case RLE_EOL: { - if (bmp_ptr->row_num >= bmp_ptr->height) { - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (row_num >= height) { + SaveDecodingStatus(BMP_D_STATUS_TAIL); + Error(); + NOTREACHED(); } - bmp_ptr->bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - bmp_ptr->col_num = 0; - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); + col_num = 0; + std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0); + SaveDecodingStatus(BMP_D_STATUS_DATA); continue; } case RLE_EOI: { - if (bmp_ptr->row_num < bmp_ptr->height) { - bmp_ptr->bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); + if (row_num < height) { + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); } - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + SaveDecodingStatus(BMP_D_STATUS_TAIL); return 1; } case RLE_DELTA: { uint8_t* delta_ptr; - if (!bmp_read_data(bmp_ptr, &delta_ptr, 2)) { - bmp_ptr->skip_size = skip_size_org; + if (!ReadData(&delta_ptr, 2)) { + skip_size = skip_size_org; return 2; } - bmp_ptr->col_num += (int32_t)delta_ptr[0]; - int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1]; - if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes || - bmp_row_num_next >= bmp_ptr->height) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported"); - return 0; + col_num += delta_ptr[0]; + size_t bmp_row_num_next = row_num + delta_ptr[1]; + if (col_num >= out_row_bytes || bmp_row_num_next >= height) { + Error(); + NOTREACHED(); } - while (bmp_ptr->row_num < bmp_row_num_next) { - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_ptr->bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); + while (row_num < bmp_row_num_next) { + std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0); + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); } } break; default: { - if ((int32_t)(*first_byte_ptr) > - bmp_ptr->src_row_bytes - bmp_ptr->col_num) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + int32_t avail_size = out_row_bytes - col_num; + if (!avail_size || + static_cast(*first_byte_ptr) > avail_size) { + Error(); + NOTREACHED(); } - if (!bmp_read_data(bmp_ptr, &second_byte_ptr, - *first_byte_ptr & 1 ? *first_byte_ptr + 1 - : *first_byte_ptr)) { - bmp_ptr->skip_size = skip_size_org; + if (!ReadData(&second_byte_ptr, *first_byte_ptr & 1 + ? *first_byte_ptr + 1 + : *first_byte_ptr)) { + skip_size = skip_size_org; return 2; } - FXSYS_memcpy(bmp_ptr->out_row_buffer + bmp_ptr->col_num, - second_byte_ptr, *first_byte_ptr); - bmp_ptr->col_num += (int32_t)(*first_byte_ptr); + std::copy(second_byte_ptr, second_byte_ptr + *first_byte_ptr, + out_row_buffer.begin() + col_num); + for (size_t i = col_num; i < col_num + *first_byte_ptr; ++i) { + if (!ValidateColorIndex(out_row_buffer[i])) + return 0; + } + col_num += *first_byte_ptr; } } } break; default: { - if (!bmp_read_data(bmp_ptr, &second_byte_ptr, 1)) { - bmp_ptr->skip_size = skip_size_org; + int32_t avail_size = out_row_bytes - col_num; + if (!avail_size || static_cast(*first_byte_ptr) > avail_size) { + Error(); + NOTREACHED(); + } + if (!ReadData(&second_byte_ptr, 1)) { + skip_size = skip_size_org; return 2; } - if ((int32_t)(*first_byte_ptr) > - bmp_ptr->src_row_bytes - bmp_ptr->col_num) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + std::fill(out_row_buffer.begin() + col_num, + out_row_buffer.begin() + col_num + *first_byte_ptr, + *second_byte_ptr); + if (!ValidateColorIndex(out_row_buffer[col_num])) return 0; - } - FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num, - *second_byte_ptr, *first_byte_ptr); - bmp_ptr->col_num += (int32_t)(*first_byte_ptr); + col_num += *first_byte_ptr; } } } - bmp_error(bmp_ptr, "Any Uncontrol Error"); - return 0; + Error(); + NOTREACHED(); } -int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) { + +int32_t BMPDecompressor::DecodeRLE4() { uint8_t* first_byte_ptr = nullptr; uint8_t* second_byte_ptr = nullptr; - bmp_ptr->col_num = 0; + col_num = 0; while (true) { - uint32_t skip_size_org = bmp_ptr->skip_size; - if (!bmp_read_data(bmp_ptr, &first_byte_ptr, 1)) + uint32_t skip_size_org = skip_size; + if (!ReadData(&first_byte_ptr, 1)) return 2; switch (*first_byte_ptr) { case RLE_MARKER: { - if (!bmp_read_data(bmp_ptr, &first_byte_ptr, 1)) { - bmp_ptr->skip_size = skip_size_org; + if (!ReadData(&first_byte_ptr, 1)) { + skip_size = skip_size_org; return 2; } switch (*first_byte_ptr) { case RLE_EOL: { - if (bmp_ptr->row_num >= bmp_ptr->height) { - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (row_num >= height) { + SaveDecodingStatus(BMP_D_STATUS_TAIL); + Error(); + NOTREACHED(); } - bmp_ptr->bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - bmp_ptr->col_num = 0; - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); + col_num = 0; + std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0); + SaveDecodingStatus(BMP_D_STATUS_DATA); continue; } case RLE_EOI: { - if (bmp_ptr->row_num < bmp_ptr->height) { - bmp_ptr->bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); + if (row_num < height) { + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); } - bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + SaveDecodingStatus(BMP_D_STATUS_TAIL); return 1; } case RLE_DELTA: { uint8_t* delta_ptr; - if (!bmp_read_data(bmp_ptr, &delta_ptr, 2)) { - bmp_ptr->skip_size = skip_size_org; + if (!ReadData(&delta_ptr, 2)) { + skip_size = skip_size_org; return 2; } - bmp_ptr->col_num += (int32_t)delta_ptr[0]; - int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1]; - if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes || - bmp_row_num_next >= bmp_ptr->height) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported"); - return 0; + col_num += delta_ptr[0]; + size_t bmp_row_num_next = row_num + delta_ptr[1]; + if (col_num >= out_row_bytes || bmp_row_num_next >= height) { + Error(); + NOTREACHED(); } - while (bmp_ptr->row_num < bmp_row_num_next) { - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_ptr->bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); + while (row_num < bmp_row_num_next) { + std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0); + ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++), + out_row_buffer); } } break; default: { - uint8_t size = (uint8_t)(((uint16_t)(*first_byte_ptr) + 1) >> 1); - if ((int32_t)*first_byte_ptr >= - bmp_ptr->out_row_bytes - bmp_ptr->col_num) { - if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + int32_t avail_size = out_row_bytes - col_num; + if (!avail_size) { + Error(); + NOTREACHED(); + } + uint8_t size = HalfRoundUp(*first_byte_ptr); + if (static_cast(*first_byte_ptr) > avail_size) { + if (size + (col_num >> 1) > src_row_bytes) { + Error(); + NOTREACHED(); } - *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1; + *first_byte_ptr = avail_size - 1; } - if (!bmp_read_data(bmp_ptr, &second_byte_ptr, - size & 1 ? size + 1 : size)) { - bmp_ptr->skip_size = skip_size_org; + if (!ReadData(&second_byte_ptr, size & 1 ? size + 1 : size)) { + skip_size = skip_size_org; return 2; } for (uint8_t i = 0; i < *first_byte_ptr; i++) { - if (i & 0x01) { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - (*second_byte_ptr++ & 0x0F); - } else { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - ((*second_byte_ptr & 0xF0) >> 4); - } + uint8_t color = (i & 0x01) ? (*second_byte_ptr++ & 0x0F) + : (*second_byte_ptr & 0xF0) >> 4; + if (!ValidateColorIndex(color)) + return 0; + + out_row_buffer[col_num++] = color; } } } } break; default: { - if (!bmp_read_data(bmp_ptr, &second_byte_ptr, 1)) { - bmp_ptr->skip_size = skip_size_org; - return 2; + int32_t avail_size = out_row_bytes - col_num; + if (!avail_size) { + Error(); + NOTREACHED(); } - if ((int32_t)*first_byte_ptr > - bmp_ptr->out_row_bytes - bmp_ptr->col_num) { - uint8_t size = (uint8_t)(((uint16_t)(*first_byte_ptr) + 1) >> 1); - if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) { - bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; + if (static_cast(*first_byte_ptr) > avail_size) { + uint8_t size = HalfRoundUp(*first_byte_ptr); + if (size + (col_num >> 1) > src_row_bytes) { + Error(); + NOTREACHED(); } - *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1; + *first_byte_ptr = avail_size - 1; + } + if (!ReadData(&second_byte_ptr, 1)) { + skip_size = skip_size_org; + return 2; } for (uint8_t i = 0; i < *first_byte_ptr; i++) { - if (i & 0x01) { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - (*second_byte_ptr & 0x0F); - } else { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - ((*second_byte_ptr & 0xF0) >> 4); - } + uint8_t second_byte = *second_byte_ptr; + second_byte = + i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4; + if (!ValidateColorIndex(second_byte)) + return 0; + out_row_buffer[col_num++] = second_byte; } } } } - bmp_error(bmp_ptr, "Any Uncontrol Error"); - return 0; + Error(); + NOTREACHED(); } -uint8_t* bmp_read_data(bmp_decompress_struct_p bmp_ptr, - uint8_t** des_buf_pp, - uint32_t data_size) { - if (!bmp_ptr || bmp_ptr->avail_in < bmp_ptr->skip_size + data_size) + +uint8_t* BMPDecompressor::ReadData(uint8_t** des_buf, uint32_t data_size) { + if (avail_in < skip_size + data_size) return nullptr; - *des_buf_pp = bmp_ptr->next_in + bmp_ptr->skip_size; - bmp_ptr->skip_size += data_size; - return *des_buf_pp; -} -void bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, int32_t status) { - bmp_ptr->decode_status = status; - bmp_ptr->next_in += bmp_ptr->skip_size; - bmp_ptr->avail_in -= bmp_ptr->skip_size; - bmp_ptr->skip_size = 0; -} -void bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, - uint8_t* src_buf, - uint32_t src_size) { - bmp_ptr->next_in = src_buf; - bmp_ptr->avail_in = src_size; - bmp_ptr->skip_size = 0; -} -uint32_t bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, - uint8_t** avail_buf_ptr) { - if (avail_buf_ptr) { - *avail_buf_ptr = nullptr; - if (bmp_ptr->avail_in > 0) { - *avail_buf_ptr = bmp_ptr->next_in; - } - } - return bmp_ptr->avail_in; -} -bmp_compress_struct_p bmp_create_compress() { - bmp_compress_struct_p bmp_ptr; - bmp_ptr = FX_Alloc(bmp_compress_struct, 1); - if (bmp_ptr) { - FXSYS_memset(bmp_ptr, 0, sizeof(bmp_compress_struct)); - } - return bmp_ptr; -} -void bmp_destroy_compress(bmp_compress_struct_p bmp_ptr) { - if (bmp_ptr) { - if (bmp_ptr->src_free && bmp_ptr->src_buf) { - FX_Free(bmp_ptr->src_buf); - } - FX_Free(bmp_ptr); - } + *des_buf = next_in + skip_size; + skip_size += data_size; + return *des_buf; } -static void WriteFileHeader(BmpFileHeaderPtr head_ptr, uint8_t* dst_buf) { - uint32_t offset; - offset = 0; - SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfType); - offset += 2; - SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfSize); - offset += 4; - SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved1); - offset += 2; - SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved2); - offset += 2; - SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfOffBits); - offset += 4; + +void BMPDecompressor::SaveDecodingStatus(int32_t status) { + decode_status = status; + next_in += skip_size; + avail_in -= skip_size; + skip_size = 0; } -static void WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr, uint8_t* dst_buf) { - uint32_t offset; - offset = sizeof(BmpFileHeader); - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSize); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biWidth); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biHeight); - offset += 4; - SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biPlanes); - offset += 2; - SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biBitCount); - offset += 2; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biCompression); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSizeImage); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biXPelsPerMeter); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biYPelsPerMeter); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrUsed); - offset += 4; - SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrImportant); - offset += 4; + +void BMPDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) { + next_in = src_buf; + avail_in = src_size; + skip_size = 0; } -static void bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - uint32_t& dst_size) { - if (bmp_ptr->info_header.biBitCount != 16 && - bmp_ptr->info_header.biBitCount != 32) { - return; - } - uint32_t size, dst_pos, i; - size = bmp_ptr->src_pitch * bmp_ptr->src_row * - bmp_ptr->info_header.biBitCount / 16; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - FXSYS_memset(&dst_buf[dst_pos], 0, size); - uint32_t mask_red; - uint32_t mask_green; - uint32_t mask_blue; - mask_red = 0x7C00; - mask_green = 0x03E0; - mask_blue = 0x001F; - if (bmp_ptr->info_header.biCompression == BMP_BITFIELDS) { - if (bmp_ptr->bit_type == BMP_BIT_565) { - mask_red = 0xF800; - mask_green = 0x07E0; - mask_blue = 0x001F; - } - if (bmp_ptr->info_header.biBitCount == 32) { - mask_red = 0xFF0000; - mask_green = 0x00FF00; - mask_blue = 0x0000FF; - } - SetDWord_LSBFirst(&dst_buf[dst_pos], mask_red); - dst_pos += 4; - SetDWord_LSBFirst(&dst_buf[dst_pos], mask_green); - dst_pos += 4; - SetDWord_LSBFirst(&dst_buf[dst_pos], mask_blue); - dst_pos += 4; - bmp_ptr->file_header.bfOffBits = dst_pos; - } - uint8_t blue_bits = 0; - uint8_t green_bits = 0; - uint8_t red_bits = 0; - for (i = 0; i < bmp_ptr->info_header.biBitCount; i++) { - if ((mask_blue >> i) & 0x01) { - blue_bits++; - } - if ((mask_green >> i) & 0x01) { - green_bits++; - } - if ((mask_red >> i) & 0x01) { - red_bits++; - } - } - green_bits += blue_bits; - red_bits += green_bits; - blue_bits = 8 - blue_bits; - green_bits -= 8; - red_bits -= 8; - i = 0; - for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--, i = 0) { - while (i < bmp_ptr->src_width * bmp_ptr->src_bpp / 8) { - uint8_t b = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; - uint8_t g = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; - uint8_t r = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; - if (bmp_ptr->src_bpp == 32) { - i++; - } - uint32_t pix_val = 0; - pix_val |= (b >> blue_bits) & mask_blue; - pix_val |= (g << green_bits) & mask_green; - pix_val |= (r << red_bits) & mask_red; - if (bmp_ptr->info_header.biBitCount == 16) { - SetWord_LSBFirst(&dst_buf[dst_pos], pix_val); - dst_pos += 2; - } else { - SetDWord_LSBFirst(&dst_buf[dst_pos], pix_val); - dst_pos += 4; - } - } + +uint32_t BMPDecompressor::GetAvailInput(uint8_t** avail_buf) { + if (avail_buf) { + *avail_buf = nullptr; + if (avail_in > 0) + *avail_buf = next_in; } - dst_size = dst_pos; + return avail_in; } -static void bmp_encode_rgb(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - uint32_t& dst_size) { - if (bmp_ptr->info_header.biBitCount == 16) { - bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size); +void BMPDecompressor::SetHeight(int32_t signed_height) { + if (signed_height >= 0) { + height = signed_height; return; } - uint32_t size, dst_pos; - uint32_t dst_pitch = - (bmp_ptr->src_width * bmp_ptr->info_header.biBitCount + 31) / 32 * 4; - size = dst_pitch * bmp_ptr->src_row; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - FXSYS_memset(&dst_buf[dst_pos], 0, size); - for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--) { - FXSYS_memcpy(&dst_buf[dst_pos], - &bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch], - bmp_ptr->src_pitch); - dst_pos += dst_pitch; - } - dst_size = dst_pos; -} -static uint8_t bmp_rle8_search(const uint8_t* buf, int32_t len) { - uint8_t num; - num = 1; - while (num < len) { - if (buf[num - 1] != buf[num] || num == 0xFF) { - break; - } - num++; - } - return num; -} -static void bmp_encode_rle8(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - uint32_t& dst_size) { - uint32_t size, dst_pos, index; - uint8_t rle[2] = {0}; - size = bmp_ptr->src_pitch * bmp_ptr->src_row * 2; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - FXSYS_memset(&dst_buf[dst_pos], 0, size); - for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;) { - index = row_num * bmp_ptr->src_pitch; - rle[0] = bmp_rle8_search(&bmp_ptr->src_buf[index + i], size - index - i); - rle[1] = bmp_ptr->src_buf[index + i]; - if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) { - rle[0] = uint8_t(bmp_ptr->src_pitch - i); - if (rle[0]) { - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOL; - i = 0; - row_num--; - } else { - i += rle[0]; - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } + if (signed_height == std::numeric_limits::min()) { + Error(); + NOTREACHED(); } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOI; - dst_size = dst_pos; -} -static uint8_t bmp_rle4_search(const uint8_t* buf, int32_t len) { - uint8_t num; - num = 2; - while (num < len) { - if (buf[num - 2] != buf[num] || num == 0xFF) { - break; - } - num++; - } - return num; -} -static void bmp_encode_rle4(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - uint32_t& dst_size) { - uint32_t size, dst_pos, index; - uint8_t rle[2] = {0}; - size = bmp_ptr->src_pitch * bmp_ptr->src_row; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - FXSYS_memset(&dst_buf[dst_pos], 0, size); - for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1; - rle[1] = 0) { - index = row_num * bmp_ptr->src_pitch; - rle[0] = bmp_rle4_search(&bmp_ptr->src_buf[index + i], size - index - i); - rle[1] |= (bmp_ptr->src_buf[index + i] & 0x0f) << 4; - rle[1] |= bmp_ptr->src_buf[index + i + 1] & 0x0f; - if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) { - rle[0] = uint8_t(bmp_ptr->src_pitch - i); - if (rle[0]) { - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOL; - i = 0; - row_num--; - } else { - i += rle[0]; - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOI; - dst_size = dst_pos; -} -bool bmp_encode_image(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - uint32_t& dst_size) { - uint32_t head_size = sizeof(BmpFileHeader) + sizeof(BmpInfoHeader); - uint32_t pal_size = sizeof(uint32_t) * bmp_ptr->pal_num; - if (bmp_ptr->info_header.biClrUsed > 0 && - bmp_ptr->info_header.biClrUsed < bmp_ptr->pal_num) { - pal_size = sizeof(uint32_t) * bmp_ptr->info_header.biClrUsed; - } - dst_size = head_size + sizeof(uint32_t) * bmp_ptr->pal_num; - dst_buf = FX_TryAlloc(uint8_t, dst_size); - if (!dst_buf) - return false; - - FXSYS_memset(dst_buf, 0, dst_size); - bmp_ptr->file_header.bfOffBits = head_size; - if (bmp_ptr->pal_ptr && pal_size) { - FXSYS_memcpy(&dst_buf[head_size], bmp_ptr->pal_ptr, pal_size); - bmp_ptr->file_header.bfOffBits += pal_size; - } - WriteInfoHeader(&bmp_ptr->info_header, dst_buf); - switch (bmp_ptr->info_header.biCompression) { - case BMP_RGB: - bmp_encode_rgb(bmp_ptr, dst_buf, dst_size); - break; - case BMP_BITFIELDS: - bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size); - break; - case BMP_RLE8: - bmp_encode_rle8(bmp_ptr, dst_buf, dst_size); - break; - case BMP_RLE4: - bmp_encode_rle4(bmp_ptr, dst_buf, dst_size); - break; - default: - break; - } - bmp_ptr->file_header.bfSize = dst_size; - WriteFileHeader(&bmp_ptr->file_header, dst_buf); - return true; + height = -signed_height; + imgTB_flag = true; } diff --git a/core/fxcodec/lbmp/fx_bmp.h b/core/fxcodec/lbmp/fx_bmp.h index 27a0f19970de859ff9508a851579db9ea68fb212..9dfa849939c11fd64b636236ad8947b65723f09f 100644 --- a/core/fxcodec/lbmp/fx_bmp.h +++ b/core/fxcodec/lbmp/fx_bmp.h @@ -9,7 +9,10 @@ #include -#include "core/fxcrt/fx_basic.h" +#include +#include + +#include "core/fxcodec/codec/ccodec_bmpmodule.h" #define BMP_WIDTHBYTES(width, bitCount) ((width * bitCount) + 31) / 32 * 4 #define BMP_PAL_ENCODE(a, r, g, b) \ @@ -20,7 +23,6 @@ #define BMP_D_STATUS_DATA 0x04 #define BMP_D_STATUS_TAIL 0x00 #define BMP_SIGNATURE 0x4D42 -#define BMP_PAL_NEW 0 #define BMP_PAL_OLD 1 #define RLE_MARKER 0 #define RLE_EOL 0 @@ -30,9 +32,8 @@ #define BMP_RLE8 1L #define BMP_RLE4 2L #define BMP_BITFIELDS 3L -#define BMP_BIT_555 0 -#define BMP_BIT_565 1 -#define BMP_MAX_ERROR_SIZE 256 +// Limit width to (MAXINT32 - 31) / 32 +#define BMP_MAX_WIDTH 67108863 #pragma pack(1) typedef struct tagBmpFileHeader { uint16_t bfType; @@ -40,14 +41,14 @@ typedef struct tagBmpFileHeader { uint16_t bfReserved1; uint16_t bfReserved2; uint32_t bfOffBits; -} BmpFileHeader, *BmpFileHeaderPtr; +} BmpFileHeader; typedef struct tagBmpCoreHeader { uint32_t bcSize; uint16_t bcWidth; uint16_t bcHeight; uint16_t bcPlanes; uint16_t bcBitCount; -} BmpCoreHeader, *BmpCoreHeaderPtr; +} BmpCoreHeader; typedef struct tagBmpInfoHeader { uint32_t biSize; int32_t biWidth; @@ -60,96 +61,76 @@ typedef struct tagBmpInfoHeader { int32_t biYPelsPerMeter; uint32_t biClrUsed; uint32_t biClrImportant; -} BmpInfoHeader, *BmpInfoHeaderPtr; +} BmpInfoHeader; #pragma pack() -typedef struct tag_bmp_decompress_struct bmp_decompress_struct; -typedef bmp_decompress_struct* bmp_decompress_struct_p; -typedef bmp_decompress_struct_p* bmp_decompress_struct_pp; -struct tag_bmp_decompress_struct { +class BMPDecompressor { + public: + BMPDecompressor(); + ~BMPDecompressor(); + + void Error(); + int32_t DecodeImage(); + int32_t ReadHeader(); + void SetInputBuffer(uint8_t* src_buf, uint32_t src_size); + uint32_t GetAvailInput(uint8_t** avail_buf); + jmp_buf jmpbuf; - FX_CHAR* err_ptr; - void (*bmp_error_fn)(bmp_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); void* context_ptr; - BmpFileHeaderPtr bmp_header_ptr; - BmpInfoHeaderPtr bmp_infoheader_ptr; - int32_t width; - int32_t height; + std::vector out_row_buffer; + std::vector palette; + uint8_t* next_in; + + uint32_t header_offset; + uint32_t width; + uint32_t height; uint32_t compress_flag; int32_t components; - int32_t src_row_bytes; - int32_t out_row_bytes; - uint8_t* out_row_buffer; + size_t src_row_bytes; + size_t out_row_bytes; uint16_t bitCounts; uint32_t color_used; bool imgTB_flag; int32_t pal_num; int32_t pal_type; - uint32_t* pal_ptr; uint32_t data_size; uint32_t img_data_offset; uint32_t img_ifh_size; - int32_t row_num; - int32_t col_num; + size_t row_num; + size_t col_num; int32_t dpi_x; int32_t dpi_y; uint32_t mask_red; uint32_t mask_green; uint32_t mask_blue; - bool (*bmp_get_data_position_fn)(bmp_decompress_struct_p bmp_ptr, - uint32_t cur_pos); - void (*bmp_get_row_fn)(bmp_decompress_struct_p bmp_ptr, - int32_t row_num, - uint8_t* row_buf); - uint8_t* next_in; uint32_t avail_in; uint32_t skip_size; int32_t decode_status; -}; -void bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg); -bmp_decompress_struct_p bmp_create_decompress(); -void bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr); -int32_t bmp_read_header(bmp_decompress_struct_p bmp_ptr); -int32_t bmp_decode_image(bmp_decompress_struct_p bmp_ptr); -int32_t bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr); -int32_t bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr); -int32_t bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr); -uint8_t* bmp_read_data(bmp_decompress_struct_p bmp_ptr, - uint8_t** des_buf_pp, - uint32_t data_size); -void bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, int32_t status); -void bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, - uint8_t* src_buf, - uint32_t src_size); -uint32_t bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, - uint8_t** avail_buf_ptr); -typedef struct tag_bmp_compress_struct bmp_compress_struct; -typedef bmp_compress_struct* bmp_compress_struct_p; -typedef bmp_compress_struct_p* bmp_compress_struct_pp; -struct tag_bmp_compress_struct { - BmpFileHeader file_header; - BmpInfoHeader info_header; - uint8_t* src_buf; - uint32_t src_pitch; - uint32_t src_row; - uint8_t src_bpp; - uint32_t src_width; - bool src_free; - uint32_t* pal_ptr; - uint16_t pal_num; - uint8_t bit_type; + + private: + bool GetDataPosition(uint32_t cur_pos); + void ReadScanline(uint32_t row_num, const std::vector& row_buf); + int32_t DecodeRGB(); + int32_t DecodeRLE8(); + int32_t DecodeRLE4(); + uint8_t* ReadData(uint8_t** des_buf, uint32_t data_size); + void SaveDecodingStatus(int32_t status); + bool ValidateColorIndex(uint8_t val); + bool ValidateFlag() const; + void SetHeight(int32_t signed_height); }; -bmp_compress_struct_p bmp_create_compress(); -void bmp_destroy_compress(bmp_compress_struct_p bmp_ptr); -bool bmp_encode_image(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - uint32_t& dst_size); +class CBmpContext : public CCodec_BmpModule::Context { + public: + CBmpContext(CCodec_BmpModule* pModule, CCodec_BmpModule::Delegate* pDelegate); + ~CBmpContext() override; -uint16_t GetWord_LSBFirst(uint8_t* p); -void SetWord_LSBFirst(uint8_t* p, uint16_t v); + BMPDecompressor m_Bmp; + UnownedPtr const m_pModule; + UnownedPtr const m_pDelegate; +}; #endif // CORE_FXCODEC_LBMP_FX_BMP_H_ diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp deleted file mode 100644 index d62dacb36c28972ed326e4843bde3e2818fa5b7a..0000000000000000000000000000000000000000 --- a/core/fxcodec/lgif/fx_gif.cpp +++ /dev/null @@ -1,1262 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcodec/lgif/fx_gif.h" - -#include "core/fxcodec/lbmp/fx_bmp.h" -#include "third_party/base/stl_util.h" - -void CGifLZWDecoder::Input(uint8_t* src_buf, uint32_t src_size) { - next_in = src_buf; - avail_in = src_size; -} - -uint32_t CGifLZWDecoder::GetAvailInput() { - return avail_in; -} - -CGifLZWDecoder::CGifLZWDecoder(FX_CHAR* error_ptr) - : code_size(0), - code_size_cur(0), - code_clear(0), - code_end(0), - code_next(0), - code_first(0), - stack_size(0), - code_old(0), - next_in(nullptr), - avail_in(0), - bits_left(0), - code_store(0), - err_msg_ptr(error_ptr) {} - -CGifLZWDecoder::~CGifLZWDecoder() {} - -void CGifLZWDecoder::InitTable(uint8_t code_len) { - code_size = code_len; - ASSERT(code_size < 32); - code_clear = 1 << code_size; - code_end = code_clear + 1; - bits_left = 0; - code_store = 0; - next_in = nullptr; - avail_in = 0; - stack_size = 0; - code_first = 0; - ClearTable(); -} -void CGifLZWDecoder::ClearTable() { - code_size_cur = code_size + 1; - code_next = code_end + 1; - code_old = (uint16_t)-1; - FXSYS_memset(code_table, 0, sizeof(tag_Table) * GIF_MAX_LZW_CODE); - FXSYS_memset(stack, 0, GIF_MAX_LZW_CODE); - for (uint16_t i = 0; i < code_clear; i++) { - code_table[i].suffix = (uint8_t)i; - } -} -void CGifLZWDecoder::DecodeString(uint16_t code) { - stack_size = 0; - while (true) { - ASSERT(code <= code_next); - if (code < code_clear || code > code_next) { - break; - } - stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix; - code = code_table[code].prefix; - } - stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = (uint8_t)code; - code_first = (uint8_t)code; -} -void CGifLZWDecoder::AddCode(uint16_t prefix_code, uint8_t append_char) { - if (code_next == GIF_MAX_LZW_CODE) { - return; - } - code_table[code_next].prefix = prefix_code; - code_table[code_next].suffix = append_char; - if (++code_next < GIF_MAX_LZW_CODE) { - if (code_next >> code_size_cur) { - code_size_cur++; - } - } -} -int32_t CGifLZWDecoder::Decode(uint8_t* des_buf, uint32_t& des_size) { - if (des_size == 0) { - return 3; - } - uint32_t i = 0; - if (stack_size != 0) { - if (des_size < stack_size) { - FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size); - stack_size -= (uint16_t)des_size; - return 3; - } - FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size); - des_buf += stack_size; - i += stack_size; - stack_size = 0; - } - uint16_t code = 0; - while (i <= des_size && (avail_in > 0 || bits_left >= code_size_cur)) { - if (code_size_cur > 12) { - if (err_msg_ptr) { - FXSYS_strncpy(err_msg_ptr, "Code Length Out Of Range", - GIF_MAX_ERROR_SIZE - 1); - } - return 0; - } - if (avail_in > 0) { - if (bits_left > 31) { - if (err_msg_ptr) - FXSYS_strncpy(err_msg_ptr, "Decode Error", GIF_MAX_ERROR_SIZE - 1); - return 0; - } - pdfium::base::CheckedNumeric safe_code = *next_in++; - safe_code <<= bits_left; - safe_code |= code_store; - if (!safe_code.IsValid()) { - if (err_msg_ptr) { - FXSYS_strncpy(err_msg_ptr, "Code Store Out Of Range", - GIF_MAX_ERROR_SIZE - 1); - } - return 0; - } - code_store = safe_code.ValueOrDie(); - avail_in--; - bits_left += 8; - } - while (bits_left >= code_size_cur) { - code = (uint16_t)code_store & ((1 << code_size_cur) - 1); - code_store >>= code_size_cur; - bits_left -= code_size_cur; - if (code == code_clear) { - ClearTable(); - continue; - } else if (code >= code_end) { - des_size = i; - return 1; - } else { - if (code_old != (uint16_t)-1) { - if (code_next < GIF_MAX_LZW_CODE) { - if (code == code_next) { - AddCode(code_old, code_first); - DecodeString(code); - } else if (code > code_next) { - if (err_msg_ptr) { - FXSYS_strncpy(err_msg_ptr, "Decode Error, Out Of Range", - GIF_MAX_ERROR_SIZE - 1); - } - return 0; - } else { - DecodeString(code); - uint8_t append_char = stack[GIF_MAX_LZW_CODE - stack_size]; - AddCode(code_old, append_char); - } - } - } else { - DecodeString(code); - } - code_old = code; - if (i + stack_size > des_size) { - FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], - des_size - i); - stack_size -= (uint16_t)(des_size - i); - return 3; - } - FXSYS_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], - stack_size); - des_buf += stack_size; - i += stack_size; - stack_size = 0; - } - } - } - if (avail_in == 0) { - des_size = i; - return 2; - } - return 0; -} -static bool gif_grow_buf(uint8_t*& dst_buf, uint32_t& dst_len, uint32_t size) { - if (dst_len < size) { - uint32_t len_org = dst_len; - while (dst_buf && dst_len < size) { - dst_len <<= 1; - // TODO(thestig): Probably should be a try-realloc here. - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len); - } - if (!dst_buf) { - dst_len = size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len); - } - FXSYS_memset(dst_buf + len_org, 0, dst_len - len_org); - return !!dst_buf; - } - return true; -} -static inline void gif_cut_index(uint8_t& val, - uint32_t index, - uint8_t index_bit, - uint8_t index_bit_use, - uint8_t bit_use) { - uint32_t cut = ((1 << (index_bit - index_bit_use)) - 1) << index_bit_use; - val |= ((index & cut) >> index_bit_use) << bit_use; -} -static inline uint8_t gif_cut_buf(const uint8_t* buf, - uint32_t& offset, - uint8_t bit_cut, - uint8_t& bit_offset, - uint32_t& bit_num) { - if (bit_cut != 8) { - uint16_t index = 0; - index |= ((1 << bit_cut) - 1) << (7 - bit_offset); - uint8_t ret = ((index & buf[offset]) >> (7 - bit_offset)); - bit_offset += bit_cut; - if (bit_offset >= 8) { - if (bit_offset > 8) { - ret |= ((index & (buf[offset + 1] << 8)) >> 8); - } - bit_offset -= 8; - offset++; - } - bit_num += bit_cut; - return ret; - } - bit_num += bit_cut; - return buf[offset++]; -} -CGifLZWEncoder::CGifLZWEncoder() { - FXSYS_memset(this, 0, sizeof(CGifLZWEncoder)); -} -CGifLZWEncoder::~CGifLZWEncoder() {} -void CGifLZWEncoder::ClearTable() { - index_bit_cur = code_size + 1; - index_num = code_end + 1; - table_cur = code_end + 1; - for (uint16_t i = 0; i < GIF_MAX_LZW_CODE; i++) { - code_table[i].prefix = 0; - code_table[i].suffix = 0; - } -} -void CGifLZWEncoder::Start(uint8_t code_len, - const uint8_t* src_buf, - uint8_t*& dst_buf, - uint32_t& offset) { - code_size = code_len + 1; - ASSERT(code_size < 32); - src_bit_cut = code_size; - if (code_len == 0) { - src_bit_cut = 1; - code_size = 2; - } - code_clear = 1 << code_size; - code_end = code_clear + 1; - dst_buf[offset++] = code_size; - bit_offset = 0; - ClearTable(); - src_offset = 0; - src_bit_offset = 0; - src_bit_num = 0; - code_table[index_num].prefix = gif_cut_buf(src_buf, src_offset, src_bit_cut, - src_bit_offset, src_bit_num); - code_table[index_num].suffix = gif_cut_buf(src_buf, src_offset, src_bit_cut, - src_bit_offset, src_bit_num); -} -void CGifLZWEncoder::WriteBlock(uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& offset) { - if (!gif_grow_buf(dst_buf, dst_len, offset + GIF_DATA_BLOCK + 1)) { - longjmp(jmp, 1); - } - dst_buf[offset++] = index_buf_len; - FXSYS_memcpy(&dst_buf[offset], index_buf, index_buf_len); - offset += index_buf_len; - FXSYS_memset(index_buf, 0, GIF_DATA_BLOCK); - index_buf_len = 0; -} -void CGifLZWEncoder::EncodeString(uint32_t index, - uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& offset) { - uint8_t index_bit_use; - index_bit_use = 0; - if (index_buf_len == GIF_DATA_BLOCK) { - WriteBlock(dst_buf, dst_len, offset); - } - gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, - bit_offset); - if (index_bit_cur <= (8 - bit_offset)) { - bit_offset += index_bit_cur; - } else if (index_bit_cur <= (16 - bit_offset)) { - index_bit_use += (8 - bit_offset); - bit_offset = 0; - index_buf_len++; - if (index_buf_len == GIF_DATA_BLOCK) { - WriteBlock(dst_buf, dst_len, offset); - } - gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, - bit_offset); - bit_offset = index_bit_cur - index_bit_use; - } else { - index_bit_use += (8 - bit_offset); - bit_offset = 0; - index_buf_len++; - if (index_buf_len == GIF_DATA_BLOCK) { - WriteBlock(dst_buf, dst_len, offset); - } - gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, - bit_offset); - index_bit_use += 8; - bit_offset = 0; - index_buf_len++; - if (index_buf_len == GIF_DATA_BLOCK) { - WriteBlock(dst_buf, dst_len, offset); - } - gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, - bit_offset); - bit_offset = index_bit_cur - index_bit_use; - } - if (bit_offset == 8) { - bit_offset = 0; - index_buf_len++; - if (index_buf_len == GIF_DATA_BLOCK) { - WriteBlock(dst_buf, dst_len, offset); - } - } - if (index == code_end) { - index_buf_len++; - WriteBlock(dst_buf, dst_len, offset); - } - if (index_num++ >> index_bit_cur) { - index_bit_cur++; - } -} -bool CGifLZWEncoder::Encode(const uint8_t* src_buf, - uint32_t src_len, - uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& offset) { - uint8_t suffix; - if (setjmp(jmp)) { - return false; - } - while (src_bit_num < src_len) { - if (!LookUpInTable(src_buf, src_offset, src_bit_offset)) { - EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset); - if (index_num == GIF_MAX_LZW_CODE) { - suffix = code_table[index_num - 1].suffix; - EncodeString(code_clear, dst_buf, dst_len, offset); - ClearTable(); - code_table[index_num].prefix = suffix; - code_table[index_num].suffix = gif_cut_buf( - src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num); - } else { - code_table[index_num].prefix = code_table[index_num - 1].suffix; - code_table[index_num].suffix = gif_cut_buf( - src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num); - } - } - } - src_offset = 0; - src_bit_offset = 0; - src_bit_num = 0; - return true; -} -bool CGifLZWEncoder::LookUpInTable(const uint8_t* buf, - uint32_t& offset, - uint8_t& out_bit_offset) { - for (uint16_t i = table_cur; i < index_num; i++) { - if (code_table[i].prefix == code_table[index_num].prefix && - code_table[i].suffix == code_table[index_num].suffix) { - code_table[index_num].prefix = i; - code_table[index_num].suffix = - gif_cut_buf(buf, offset, src_bit_cut, out_bit_offset, src_bit_num); - table_cur = i; - return true; - } - } - table_cur = code_end + 1; - return false; -} -void CGifLZWEncoder::Finish(uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& offset) { - EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset); - EncodeString(code_end, dst_buf, dst_len, offset); - bit_offset = 0; - ClearTable(); -} -gif_decompress_struct_p gif_create_decompress() { - gif_decompress_struct_p gif_ptr = FX_Alloc(gif_decompress_struct, 1); - FXSYS_memset(gif_ptr, 0, sizeof(gif_decompress_struct)); - gif_ptr->decode_status = GIF_D_STATUS_SIG; - gif_ptr->img_ptr_arr_ptr = new std::vector; - gif_ptr->cmt_data_ptr = new CFX_ByteString; - gif_ptr->pt_ptr_arr_ptr = new std::vector; - return gif_ptr; -} -void gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr) { - if (!gif_ptr_ptr || !*gif_ptr_ptr) - return; - - gif_decompress_struct_p gif_ptr = *gif_ptr_ptr; - *gif_ptr_ptr = nullptr; - FX_Free(gif_ptr->global_pal_ptr); - delete gif_ptr->img_decoder_ptr; - if (gif_ptr->img_ptr_arr_ptr) { - size_t size_img_arr = gif_ptr->img_ptr_arr_ptr->size(); - for (size_t i = 0; i < size_img_arr; i++) { - GifImage* p = (*gif_ptr->img_ptr_arr_ptr)[i]; - FX_Free(p->image_info_ptr); - FX_Free(p->image_gce_ptr); - FX_Free(p->image_row_buf); - if (p->local_pal_ptr && p->local_pal_ptr != gif_ptr->global_pal_ptr) { - FX_Free(p->local_pal_ptr); - } - FX_Free(p); - } - gif_ptr->img_ptr_arr_ptr->clear(); - delete gif_ptr->img_ptr_arr_ptr; - } - delete gif_ptr->cmt_data_ptr; - FX_Free(gif_ptr->gce_ptr); - if (gif_ptr->pt_ptr_arr_ptr) { - size_t size_pt_arr = gif_ptr->pt_ptr_arr_ptr->size(); - for (size_t i = 0; i < size_pt_arr; i++) { - GifPlainText* p = (*gif_ptr->pt_ptr_arr_ptr)[i]; - FX_Free(p->gce_ptr); - FX_Free(p->pte_ptr); - delete p->string_ptr; - FX_Free(p); - } - gif_ptr->pt_ptr_arr_ptr->clear(); - delete gif_ptr->pt_ptr_arr_ptr; - } - FX_Free(gif_ptr); -} -gif_compress_struct_p gif_create_compress() { - gif_compress_struct_p gif_ptr = FX_Alloc(gif_compress_struct, 1); - FXSYS_memset(gif_ptr, 0, sizeof(gif_compress_struct)); - gif_ptr->img_encoder_ptr = new CGifLZWEncoder; - gif_ptr->header_ptr = FX_Alloc(GifHeader, 1); - if (!gif_ptr->header_ptr) { - delete (gif_ptr->img_encoder_ptr); - FX_Free(gif_ptr); - return nullptr; - } - FXSYS_memcpy(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3); - FXSYS_memcpy(gif_ptr->header_ptr->version, "89a", 3); - gif_ptr->lsd_ptr = FX_Alloc(GifLSD, 1); - if (!gif_ptr->lsd_ptr) { - FX_Free(gif_ptr->header_ptr); - delete (gif_ptr->img_encoder_ptr); - FX_Free(gif_ptr); - return nullptr; - } - FXSYS_memset(gif_ptr->lsd_ptr, 0, sizeof(GifLSD)); - gif_ptr->image_info_ptr = FX_Alloc(GifImageInfo, 1); - if (!gif_ptr->image_info_ptr) { - FX_Free(gif_ptr->lsd_ptr); - FX_Free(gif_ptr->header_ptr); - delete (gif_ptr->img_encoder_ptr); - FX_Free(gif_ptr); - return nullptr; - } - FXSYS_memset(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo)); - gif_ptr->gce_ptr = FX_Alloc(GifGCE, 1); - if (!gif_ptr->gce_ptr) { - FX_Free(gif_ptr->image_info_ptr); - FX_Free(gif_ptr->lsd_ptr); - FX_Free(gif_ptr->header_ptr); - delete (gif_ptr->img_encoder_ptr); - FX_Free(gif_ptr); - return nullptr; - } - gif_ptr->pte_ptr = FX_Alloc(GifPTE, 1); - if (!gif_ptr->pte_ptr) { - FX_Free(gif_ptr->gce_ptr); - FX_Free(gif_ptr->image_info_ptr); - FX_Free(gif_ptr->lsd_ptr); - FX_Free(gif_ptr->header_ptr); - delete (gif_ptr->img_encoder_ptr); - FX_Free(gif_ptr); - return nullptr; - } - FXSYS_memset(gif_ptr->pte_ptr, 0, sizeof(GifPTE)); - gif_ptr->pte_ptr->block_size = 12; - return gif_ptr; -} -void gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr) { - if (!gif_ptr_ptr || !*gif_ptr_ptr) - return; - - gif_compress_struct_p gif_ptr = *gif_ptr_ptr; - *gif_ptr_ptr = nullptr; - FX_Free(gif_ptr->header_ptr); - FX_Free(gif_ptr->lsd_ptr); - FX_Free(gif_ptr->global_pal); - FX_Free(gif_ptr->image_info_ptr); - FX_Free(gif_ptr->local_pal); - delete gif_ptr->img_encoder_ptr; - FX_Free(gif_ptr->gce_ptr); - FX_Free(gif_ptr->cmt_data_ptr); - FX_Free(gif_ptr->pte_ptr); - FX_Free(gif_ptr); -} -void gif_error(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg) { - if (gif_ptr && gif_ptr->gif_error_fn) { - gif_ptr->gif_error_fn(gif_ptr, err_msg); - } -} -void gif_warn(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg) {} -int32_t gif_read_header(gif_decompress_struct_p gif_ptr) { - if (!gif_ptr) - return 0; - - uint32_t skip_size_org = gif_ptr->skip_size; - ASSERT(sizeof(GifHeader) == 6); - GifHeader* gif_header_ptr = nullptr; - if (!gif_read_data(gif_ptr, (uint8_t**)&gif_header_ptr, 6)) - return 2; - - if (FXSYS_strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 || - gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') { - gif_error(gif_ptr, "Not A Gif Image"); - return 0; - } - ASSERT(sizeof(GifLSD) == 7); - GifLSD* gif_lsd_ptr = nullptr; - if (!gif_read_data(gif_ptr, (uint8_t**)&gif_lsd_ptr, 7)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - if (((GifGF*)&gif_lsd_ptr->global_flag)->global_pal) { - gif_ptr->global_pal_num = 2 - << ((GifGF*)&gif_lsd_ptr->global_flag)->pal_bits; - ASSERT(sizeof(GifPalette) == 3); - int32_t global_pal_size = gif_ptr->global_pal_num * 3; - uint8_t* global_pal_ptr = nullptr; - if (!gif_read_data(gif_ptr, &global_pal_ptr, global_pal_size)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - gif_ptr->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag; - gif_ptr->global_color_resolution = - ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution; - FX_Free(gif_ptr->global_pal_ptr); - gif_ptr->global_pal_ptr = (GifPalette*)FX_Alloc(uint8_t, global_pal_size); - FXSYS_memcpy(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size); - } - gif_ptr->width = (int)GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->width); - gif_ptr->height = (int)GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->height); - gif_ptr->bc_index = gif_lsd_ptr->bc_index; - gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect; - return 1; -} -int32_t gif_get_frame(gif_decompress_struct_p gif_ptr) { - if (!gif_ptr) - return 0; - - int32_t ret = 1; - while (true) { - switch (gif_ptr->decode_status) { - case GIF_D_STATUS_TAIL: - return 1; - case GIF_D_STATUS_SIG: { - uint8_t* sig_ptr = nullptr; - if (!gif_read_data(gif_ptr, &sig_ptr, 1)) - return 2; - - switch (*sig_ptr) { - case GIF_SIG_EXTENSION: - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT); - continue; - case GIF_SIG_IMAGE: - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_INFO); - continue; - case GIF_SIG_TRAILER: - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); - return 1; - default: - if (gif_ptr->avail_in) { - gif_warn(gif_ptr, "The Gif File has non_standard Tag!"); - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG); - continue; - } - gif_warn(gif_ptr, "The Gif File Doesn't have Trailer Tag!"); - return 1; - } - } - case GIF_D_STATUS_EXT: { - uint8_t* ext_ptr = nullptr; - if (!gif_read_data(gif_ptr, &ext_ptr, 1)) - return 2; - - switch (*ext_ptr) { - case GIF_BLOCK_CE: - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_CE); - continue; - case GIF_BLOCK_GCE: - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_GCE); - continue; - case GIF_BLOCK_PTE: - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_PTE); - continue; - default: { - int32_t status = GIF_D_STATUS_EXT_UNE; - if (*ext_ptr == GIF_BLOCK_PTE) { - status = GIF_D_STATUS_EXT_PTE; - } - gif_save_decoding_status(gif_ptr, status); - continue; - } - } - } - case GIF_D_STATUS_IMG_INFO: { - ret = gif_decode_image_info(gif_ptr); - if (ret != 1) { - return ret; - } - continue; - } - case GIF_D_STATUS_IMG_DATA: { - uint8_t* data_size_ptr = nullptr; - uint8_t* data_ptr = nullptr; - uint32_t skip_size_org = gif_ptr->skip_size; - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) - return 2; - - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); - skip_size_org = gif_ptr->skip_size; - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) - return 2; - } - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG); - continue; - } - default: { - ret = gif_decode_extension(gif_ptr); - if (ret != 1) { - return ret; - } - continue; - } - } - } - return 1; -} -void gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, - GifGCE** gce_ptr_ptr) { - *gce_ptr_ptr = nullptr; - if (gif_ptr->gce_ptr && gce_ptr_ptr) { - *gce_ptr_ptr = gif_ptr->gce_ptr; - gif_ptr->gce_ptr = nullptr; - } -} -int32_t gif_decode_extension(gif_decompress_struct_p gif_ptr) { - uint8_t* data_size_ptr = nullptr; - uint8_t* data_ptr = nullptr; - uint32_t skip_size_org = gif_ptr->skip_size; - switch (gif_ptr->decode_status) { - case GIF_D_STATUS_EXT_CE: { - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - gif_ptr->cmt_data_ptr->clear(); - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - uint8_t data_size = *data_size_ptr; - if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) || - !gif_read_data(gif_ptr, &data_size_ptr, 1)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - *(gif_ptr->cmt_data_ptr) += - CFX_ByteString((const FX_CHAR*)data_ptr, data_size); - } - } break; - case GIF_D_STATUS_EXT_PTE: { - ASSERT(sizeof(GifPTE) == 13); - GifPTE* gif_pte_ptr = nullptr; - if (!gif_read_data(gif_ptr, (uint8_t**)&gif_pte_ptr, 13)) { - return 2; - } - GifPlainText* gif_pt_ptr = FX_Alloc(GifPlainText, 1); - FXSYS_memset(gif_pt_ptr, 0, sizeof(GifPlainText)); - gif_takeover_gce_ptr(gif_ptr, &gif_pt_ptr->gce_ptr); - gif_pt_ptr->pte_ptr = FX_Alloc(GifPTE, 1); - gif_pt_ptr->string_ptr = new CFX_ByteString; - gif_pt_ptr->pte_ptr->block_size = gif_pte_ptr->block_size; - gif_pt_ptr->pte_ptr->grid_left = - GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_left); - gif_pt_ptr->pte_ptr->grid_top = - GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_top); - gif_pt_ptr->pte_ptr->grid_width = - GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_width); - gif_pt_ptr->pte_ptr->grid_height = - GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_height); - gif_pt_ptr->pte_ptr->char_width = gif_pte_ptr->char_width; - gif_pt_ptr->pte_ptr->char_height = gif_pte_ptr->char_height; - gif_pt_ptr->pte_ptr->fc_index = gif_pte_ptr->fc_index; - gif_pt_ptr->pte_ptr->bc_index = gif_pte_ptr->bc_index; - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) { - gif_ptr->skip_size = skip_size_org; - if (gif_pt_ptr) { - FX_Free(gif_pt_ptr->gce_ptr); - FX_Free(gif_pt_ptr->pte_ptr); - delete gif_pt_ptr->string_ptr; - FX_Free(gif_pt_ptr); - } - return 2; - } - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - uint8_t data_size = *data_size_ptr; - if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) || - !gif_read_data(gif_ptr, &data_size_ptr, 1)) { - gif_ptr->skip_size = skip_size_org; - if (gif_pt_ptr) { - FX_Free(gif_pt_ptr->gce_ptr); - FX_Free(gif_pt_ptr->pte_ptr); - delete gif_pt_ptr->string_ptr; - FX_Free(gif_pt_ptr); - } - return 2; - } - *(gif_pt_ptr->string_ptr) += - CFX_ByteString((const FX_CHAR*)data_ptr, data_size); - } - gif_ptr->pt_ptr_arr_ptr->push_back(gif_pt_ptr); - } break; - case GIF_D_STATUS_EXT_GCE: { - ASSERT(sizeof(GifGCE) == 5); - GifGCE* gif_gce_ptr = nullptr; - if (!gif_read_data(gif_ptr, (uint8_t**)&gif_gce_ptr, 6)) - return 2; - - if (!gif_ptr->gce_ptr) - gif_ptr->gce_ptr = FX_Alloc(GifGCE, 1); - gif_ptr->gce_ptr->block_size = gif_gce_ptr->block_size; - gif_ptr->gce_ptr->gce_flag = gif_gce_ptr->gce_flag; - gif_ptr->gce_ptr->delay_time = - GetWord_LSBFirst((uint8_t*)&gif_gce_ptr->delay_time); - gif_ptr->gce_ptr->trans_index = gif_gce_ptr->trans_index; - } break; - default: { - if (gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE) { - FX_Free(gif_ptr->gce_ptr); - gif_ptr->gce_ptr = nullptr; - } - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) - return 2; - - while (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) || - !gif_read_data(gif_ptr, &data_size_ptr, 1)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - } - } - } - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG); - return 1; -} -int32_t gif_decode_image_info(gif_decompress_struct_p gif_ptr) { - if (gif_ptr->width == 0 || gif_ptr->height == 0) { - gif_error(gif_ptr, "No Image Header Info"); - return 0; - } - uint32_t skip_size_org = gif_ptr->skip_size; - ASSERT(sizeof(GifImageInfo) == 9); - GifImageInfo* gif_img_info_ptr = nullptr; - if (!gif_read_data(gif_ptr, (uint8_t**)&gif_img_info_ptr, 9)) - return 2; - - GifImage* gif_image_ptr = FX_Alloc(GifImage, 1); - FXSYS_memset(gif_image_ptr, 0, sizeof(GifImage)); - gif_image_ptr->image_info_ptr = FX_Alloc(GifImageInfo, 1); - gif_image_ptr->image_info_ptr->left = - GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->left); - gif_image_ptr->image_info_ptr->top = - GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->top); - gif_image_ptr->image_info_ptr->width = - GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->width); - gif_image_ptr->image_info_ptr->height = - GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->height); - gif_image_ptr->image_info_ptr->local_flag = gif_img_info_ptr->local_flag; - if (gif_image_ptr->image_info_ptr->left + - gif_image_ptr->image_info_ptr->width > - gif_ptr->width || - gif_image_ptr->image_info_ptr->top + - gif_image_ptr->image_info_ptr->height > - gif_ptr->height) { - FX_Free(gif_image_ptr->image_info_ptr); - FX_Free(gif_image_ptr->image_row_buf); - FX_Free(gif_image_ptr); - gif_error(gif_ptr, "Image Data Out Of LSD, The File May Be Corrupt"); - return 0; - } - GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag; - if (gif_img_info_lf_ptr->local_pal) { - ASSERT(sizeof(GifPalette) == 3); - int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3; - uint8_t* loc_pal_ptr = nullptr; - if (!gif_read_data(gif_ptr, &loc_pal_ptr, loc_pal_size)) { - gif_ptr->skip_size = skip_size_org; - FX_Free(gif_image_ptr->image_info_ptr); - FX_Free(gif_image_ptr->image_row_buf); - FX_Free(gif_image_ptr); - return 2; - } - gif_image_ptr->local_pal_ptr = - (GifPalette*)gif_ptr->gif_ask_buf_for_pal_fn(gif_ptr, loc_pal_size); - if (gif_image_ptr->local_pal_ptr) { - FXSYS_memcpy((uint8_t*)gif_image_ptr->local_pal_ptr, loc_pal_ptr, - loc_pal_size); - } - } - uint8_t* code_size_ptr = nullptr; - if (!gif_read_data(gif_ptr, &code_size_ptr, 1)) { - gif_ptr->skip_size = skip_size_org; - FX_Free(gif_image_ptr->image_info_ptr); - FX_Free(gif_image_ptr->local_pal_ptr); - FX_Free(gif_image_ptr->image_row_buf); - FX_Free(gif_image_ptr); - return 2; - } - gif_image_ptr->image_code_size = *code_size_ptr; - gif_ptr->gif_record_current_position_fn(gif_ptr, - &gif_image_ptr->image_data_pos); - gif_image_ptr->image_data_pos += gif_ptr->skip_size; - gif_takeover_gce_ptr(gif_ptr, &gif_image_ptr->image_gce_ptr); - gif_ptr->img_ptr_arr_ptr->push_back(gif_image_ptr); - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); - return 1; -} -int32_t gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num) { - if (!gif_ptr || frame_num < 0 || - frame_num >= pdfium::CollectionSize(*gif_ptr->img_ptr_arr_ptr)) { - return 0; - } - uint8_t* data_size_ptr = nullptr; - uint8_t* data_ptr = nullptr; - uint32_t skip_size_org = gif_ptr->skip_size; - GifImage* gif_image_ptr = (*gif_ptr->img_ptr_arr_ptr)[frame_num]; - uint32_t gif_img_row_bytes = gif_image_ptr->image_info_ptr->width; - if (gif_img_row_bytes == 0) { - gif_error(gif_ptr, "Error Invalid Number of Row Bytes"); - return 0; - } - if (gif_ptr->decode_status == GIF_D_STATUS_TAIL) { - if (gif_image_ptr->image_row_buf) { - FX_Free(gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_buf = nullptr; - } - gif_image_ptr->image_row_buf = FX_Alloc(uint8_t, gif_img_row_bytes); - GifGCE* gif_img_gce_ptr = gif_image_ptr->image_gce_ptr; - int32_t loc_pal_num = - ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->local_pal - ? (2 << ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag) - ->pal_bits) - : 0; - gif_ptr->avail_in = 0; - if (!gif_img_gce_ptr) { - bool bRes = gif_ptr->gif_get_record_position_fn( - gif_ptr, gif_image_ptr->image_data_pos, - gif_image_ptr->image_info_ptr->left, - gif_image_ptr->image_info_ptr->top, - gif_image_ptr->image_info_ptr->width, - gif_image_ptr->image_info_ptr->height, loc_pal_num, - gif_image_ptr->local_pal_ptr, 0, 0, -1, 0, - (bool)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag) - ->interlace); - if (!bRes) { - FX_Free(gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_buf = nullptr; - gif_error(gif_ptr, "Error Read Record Position Data"); - return 0; - } - } else { - bool bRes = gif_ptr->gif_get_record_position_fn( - gif_ptr, gif_image_ptr->image_data_pos, - gif_image_ptr->image_info_ptr->left, - gif_image_ptr->image_info_ptr->top, - gif_image_ptr->image_info_ptr->width, - gif_image_ptr->image_info_ptr->height, loc_pal_num, - gif_image_ptr->local_pal_ptr, - (int32_t)gif_image_ptr->image_gce_ptr->delay_time, - (bool)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->user_input, - ((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->transparency - ? (int32_t)gif_image_ptr->image_gce_ptr->trans_index - : -1, - (int32_t)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag) - ->disposal_method, - (bool)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag) - ->interlace); - if (!bRes) { - FX_Free(gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_buf = nullptr; - gif_error(gif_ptr, "Error Read Record Position Data"); - return 0; - } - } - if (gif_image_ptr->image_code_size >= 32) { - FX_Free(gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_buf = nullptr; - gif_error(gif_ptr, "Error Invalid Code Size"); - return 0; - } - if (!gif_ptr->img_decoder_ptr) - gif_ptr->img_decoder_ptr = new CGifLZWDecoder(gif_ptr->err_ptr); - gif_ptr->img_decoder_ptr->InitTable(gif_image_ptr->image_code_size); - gif_ptr->img_row_offset = 0; - gif_ptr->img_row_avail_size = 0; - gif_ptr->img_pass_num = 0; - gif_image_ptr->image_row_num = 0; - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); - } - CGifLZWDecoder* img_decoder_ptr = gif_ptr->img_decoder_ptr; - if (gif_ptr->decode_status == GIF_D_STATUS_IMG_DATA) { - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) - return 2; - - if (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - img_decoder_ptr->Input(data_ptr, *data_size_ptr); - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); - gif_ptr->img_row_offset += gif_ptr->img_row_avail_size; - gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset; - int32_t ret = img_decoder_ptr->Decode( - gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, - gif_ptr->img_row_avail_size); - if (ret == 0) { - gif_decoding_failure_at_tail_cleanup(gif_ptr, gif_image_ptr); - return 0; - } - while (ret != 0) { - if (ret == 1) { - gif_ptr->gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, - gif_image_ptr->image_row_buf); - FX_Free(gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_buf = nullptr; - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); - return 1; - } - if (ret == 2) { - ASSERT(img_decoder_ptr->GetAvailInput() == 0); - skip_size_org = gif_ptr->skip_size; - if (!gif_read_data(gif_ptr, &data_size_ptr, 1)) - return 2; - - if (*data_size_ptr != GIF_BLOCK_TERMINAL) { - if (!gif_read_data(gif_ptr, &data_ptr, *data_size_ptr)) { - gif_ptr->skip_size = skip_size_org; - return 2; - } - img_decoder_ptr->Input(data_ptr, *data_size_ptr); - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); - gif_ptr->img_row_offset += gif_ptr->img_row_avail_size; - gif_ptr->img_row_avail_size = - gif_img_row_bytes - gif_ptr->img_row_offset; - ret = img_decoder_ptr->Decode( - gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, - gif_ptr->img_row_avail_size); - } - } - if (ret == 3) { - if (((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) { - gif_ptr->gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, - gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_num += - s_gif_interlace_step[gif_ptr->img_pass_num]; - if (gif_image_ptr->image_row_num >= - (int32_t)gif_image_ptr->image_info_ptr->height) { - gif_ptr->img_pass_num++; - if (gif_ptr->img_pass_num == FX_ArraySize(s_gif_interlace_step)) { - gif_decoding_failure_at_tail_cleanup(gif_ptr, gif_image_ptr); - return 0; - } - gif_image_ptr->image_row_num = - s_gif_interlace_step[gif_ptr->img_pass_num] / 2; - } - } else { - gif_ptr->gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num++, - gif_image_ptr->image_row_buf); - } - gif_ptr->img_row_offset = 0; - gif_ptr->img_row_avail_size = gif_img_row_bytes; - ret = img_decoder_ptr->Decode( - gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, - gif_ptr->img_row_avail_size); - } - if (ret == 0) { - gif_decoding_failure_at_tail_cleanup(gif_ptr, gif_image_ptr); - return 0; - } - } - } - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); - } - gif_error(gif_ptr, "Decode Image Data Error"); - return 0; -} -void gif_decoding_failure_at_tail_cleanup(gif_decompress_struct_p gif_ptr, - GifImage* gif_image_ptr) { - FX_Free(gif_image_ptr->image_row_buf); - gif_image_ptr->image_row_buf = nullptr; - gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); - gif_error(gif_ptr, "Decode Image Data Error"); -} -void gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status) { - gif_ptr->decode_status = status; - gif_ptr->next_in += gif_ptr->skip_size; - gif_ptr->avail_in -= gif_ptr->skip_size; - gif_ptr->skip_size = 0; -} -uint8_t* gif_read_data(gif_decompress_struct_p gif_ptr, - uint8_t** des_buf_pp, - uint32_t data_size) { - if (!gif_ptr || gif_ptr->avail_in < gif_ptr->skip_size + data_size) - return nullptr; - - *des_buf_pp = gif_ptr->next_in + gif_ptr->skip_size; - gif_ptr->skip_size += data_size; - return *des_buf_pp; -} -void gif_input_buffer(gif_decompress_struct_p gif_ptr, - uint8_t* src_buf, - uint32_t src_size) { - gif_ptr->next_in = src_buf; - gif_ptr->avail_in = src_size; - gif_ptr->skip_size = 0; -} -uint32_t gif_get_avail_input(gif_decompress_struct_p gif_ptr, - uint8_t** avail_buf_ptr) { - if (avail_buf_ptr) { - *avail_buf_ptr = nullptr; - if (gif_ptr->avail_in > 0) { - *avail_buf_ptr = gif_ptr->next_in; - } - } - return gif_ptr->avail_in; -} -int32_t gif_get_frame_num(gif_decompress_struct_p gif_ptr) { - return pdfium::CollectionSize(*gif_ptr->img_ptr_arr_ptr); -} -static bool gif_write_header(gif_compress_struct_p gif_ptr, - uint8_t*& dst_buf, - uint32_t& dst_len) { - if (gif_ptr->cur_offset) { - return true; - } - dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF); - dst_buf = FX_TryAlloc(uint8_t, dst_len); - if (!dst_buf) - return false; - - FXSYS_memset(dst_buf, 0, dst_len); - FXSYS_memcpy(dst_buf, gif_ptr->header_ptr, sizeof(GifHeader)); - gif_ptr->cur_offset += sizeof(GifHeader); - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->width); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->height); - gif_ptr->cur_offset += 2; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->global_flag; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->bc_index; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->pixel_aspect; - if (gif_ptr->global_pal) { - uint16_t size = sizeof(GifPalette) * gif_ptr->gpal_num; - if (!gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + size)) { - return false; - } - FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size); - gif_ptr->cur_offset += size; - } - return true; -} -void interlace_buf(const uint8_t* buf, uint32_t pitch, uint32_t height) { - std::vector pass[4]; - uint32_t row = 0; - uint8_t* temp; - while (row < height) { - size_t j; - if (row % 8 == 0) { - j = 0; - } else if (row % 4 == 0) { - j = 1; - } else if (row % 2 == 0) { - j = 2; - } else { - j = 3; - } - temp = FX_Alloc(uint8_t, pitch); - FXSYS_memcpy(temp, &buf[pitch * row], pitch); - pass[j].push_back(temp); - row++; - } - for (size_t i = 0, row = 0; i < 4; i++) { - for (size_t j = 0; j < pass[i].size(); j++, row++) { - FXSYS_memcpy((uint8_t*)&buf[pitch * row], pass[i][j], pitch); - FX_Free(pass[i][j]); - } - } -} -static void gif_write_block_data(const uint8_t* src_buf, - uint32_t src_len, - uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& dst_offset) { - uint32_t src_offset = 0; - while (src_len > GIF_DATA_BLOCK) { - dst_buf[dst_offset++] = GIF_DATA_BLOCK; - FXSYS_memcpy(&dst_buf[dst_offset], &src_buf[src_offset], GIF_DATA_BLOCK); - dst_offset += GIF_DATA_BLOCK; - src_offset += GIF_DATA_BLOCK; - src_len -= GIF_DATA_BLOCK; - } - dst_buf[dst_offset++] = (uint8_t)src_len; - FXSYS_memcpy(&dst_buf[dst_offset], &src_buf[src_offset], src_len); - dst_offset += src_len; -} -static bool gif_write_data(gif_compress_struct_p gif_ptr, - uint8_t*& dst_buf, - uint32_t& dst_len) { - if (!gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + GIF_DATA_BLOCK)) { - return false; - } - if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0) { - dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; - dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_GCE; - gif_ptr->gce_ptr->block_size = 4; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->block_size; - gif_ptr->gce_ptr->gce_flag = 0; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->gce_flag; - gif_ptr->gce_ptr->delay_time = 10; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->gce_ptr->delay_time); - gif_ptr->cur_offset += 2; - gif_ptr->gce_ptr->trans_index = 0; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->trans_index; - dst_buf[gif_ptr->cur_offset++] = 0; - } - dst_buf[gif_ptr->cur_offset++] = GIF_SIG_IMAGE; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->image_info_ptr->left); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->top); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->image_info_ptr->width); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->image_info_ptr->height); - gif_ptr->cur_offset += 2; - GifLF& lf = (GifLF&)gif_ptr->image_info_ptr->local_flag; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->image_info_ptr->local_flag; - if (gif_ptr->local_pal) { - uint32_t pal_size = sizeof(GifPalette) * gif_ptr->lpal_num; - if (!gif_grow_buf(dst_buf, dst_len, pal_size + gif_ptr->cur_offset)) { - return false; - } - FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->local_pal, pal_size); - gif_ptr->cur_offset += pal_size; - } - if (lf.interlace) { - interlace_buf(gif_ptr->src_buf, gif_ptr->src_pitch, - gif_ptr->image_info_ptr->height); - } - uint8_t code_bit = lf.pal_bits; - if (lf.local_pal == 0) { - GifGF& gf = (GifGF&)gif_ptr->lsd_ptr->global_flag; - code_bit = gf.pal_bits; - } - if (code_bit >= 31) - return false; - gif_ptr->img_encoder_ptr->Start(code_bit, gif_ptr->src_buf, dst_buf, - gif_ptr->cur_offset); - uint32_t i; - for (i = 0; i < gif_ptr->src_row; i++) { - if (!gif_ptr->img_encoder_ptr->Encode( - &gif_ptr->src_buf[i * gif_ptr->src_pitch], - gif_ptr->src_width * (code_bit + 1), dst_buf, dst_len, - gif_ptr->cur_offset)) { - return false; - } - } - gif_ptr->img_encoder_ptr->Finish(dst_buf, dst_len, gif_ptr->cur_offset); - dst_buf[gif_ptr->cur_offset++] = 0; - if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0 && - gif_ptr->cmt_data_ptr) { - dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; - dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_CE; - gif_write_block_data(gif_ptr->cmt_data_ptr, gif_ptr->cmt_data_len, dst_buf, - dst_len, gif_ptr->cur_offset); - dst_buf[gif_ptr->cur_offset++] = 0; - } - if (FXSYS_memcmp(gif_ptr->header_ptr->version, "89a", 3) == 0 && - gif_ptr->pte_data_ptr) { - dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; - dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_PTE; - dst_buf[gif_ptr->cur_offset++] = gif_ptr->pte_ptr->block_size; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->pte_ptr->grid_left); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_top); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->pte_ptr->grid_width); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->pte_ptr->grid_height); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->pte_ptr->char_width); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, - gif_ptr->pte_ptr->char_height); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->fc_index); - gif_ptr->cur_offset += 2; - SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->bc_index); - gif_ptr->cur_offset += 2; - gif_write_block_data(gif_ptr->pte_data_ptr, gif_ptr->pte_data_len, dst_buf, - dst_len, gif_ptr->cur_offset); - gif_ptr->cur_offset += gif_ptr->pte_data_len; - dst_buf[gif_ptr->cur_offset++] = 0; - } - dst_buf[gif_ptr->cur_offset++] = GIF_SIG_TRAILER; - return true; -} -bool gif_encode(gif_compress_struct_p gif_ptr, - uint8_t*& dst_buf, - uint32_t& dst_len) { - if (!gif_write_header(gif_ptr, dst_buf, dst_len)) { - return false; - } - uint32_t cur_offset = gif_ptr->cur_offset; - bool res = true; - if (gif_ptr->frames) { - gif_ptr->cur_offset--; - } - if (!gif_write_data(gif_ptr, dst_buf, dst_len)) { - gif_ptr->cur_offset = cur_offset; - res = false; - } - dst_len = gif_ptr->cur_offset; - dst_buf[dst_len - 1] = GIF_SIG_TRAILER; - if (res) { - gif_ptr->frames++; - } - return res; -} diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h deleted file mode 100644 index a8b780b099958636f75fa927a51737a99854e3c9..0000000000000000000000000000000000000000 --- a/core/fxcodec/lgif/fx_gif.h +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCODEC_LGIF_FX_GIF_H_ -#define CORE_FXCODEC_LGIF_FX_GIF_H_ - -#include -#include - -#include "core/fxcrt/fx_basic.h" - -#define GIF_SIGNATURE "GIF" -#define GIF_SIG_EXTENSION 0x21 -#define GIF_SIG_IMAGE 0x2C -#define GIF_SIG_TRAILER 0x3B -#define GIF_BLOCK_GCE 0xF9 -#define GIF_BLOCK_PTE 0x01 -#define GIF_BLOCK_CE 0xFE -#define GIF_BLOCK_AE 0xFF -#define GIF_BLOCK_TERMINAL 0x00 -#define GIF_MAX_LZW_CODE 4096 -#define GIF_DATA_BLOCK 255 -#define GIF_MAX_ERROR_SIZE 256 -#define GIF_D_STATUS_SIG 0x01 -#define GIF_D_STATUS_TAIL 0x02 -#define GIF_D_STATUS_EXT 0x03 -#define GIF_D_STATUS_EXT_AE 0x04 -#define GIF_D_STATUS_EXT_CE 0x05 -#define GIF_D_STATUS_EXT_GCE 0x06 -#define GIF_D_STATUS_EXT_PTE 0x07 -#define GIF_D_STATUS_EXT_UNE 0x08 -#define GIF_D_STATUS_IMG_INFO 0x09 -#define GIF_D_STATUS_IMG_DATA 0x0A -#pragma pack(1) -typedef struct tagGifGF { - uint8_t pal_bits : 3; - uint8_t sort_flag : 1; - uint8_t color_resolution : 3; - uint8_t global_pal : 1; -} GifGF; -typedef struct tagGifLF { - uint8_t pal_bits : 3; - uint8_t reserved : 2; - uint8_t sort_flag : 1; - uint8_t interlace : 1; - uint8_t local_pal : 1; -} GifLF; -typedef struct tagGifHeader { - char signature[3]; - char version[3]; -} GifHeader; -typedef struct tagGifLSD { - uint16_t width; - uint16_t height; - uint8_t global_flag; - uint8_t bc_index; - uint8_t pixel_aspect; -} GifLSD; -typedef struct tagGifImageInfo { - uint16_t left; - uint16_t top; - uint16_t width; - uint16_t height; - - uint8_t local_flag; -} GifImageInfo; -typedef struct tagGifCEF { - uint8_t transparency : 1; - uint8_t user_input : 1; - uint8_t disposal_method : 3; - uint8_t reserved : 3; -} GifCEF; -typedef struct tagGifGCE { - uint8_t block_size; - uint8_t gce_flag; - uint16_t delay_time; - uint8_t trans_index; -} GifGCE; -typedef struct tagGifPTE { - uint8_t block_size; - uint16_t grid_left; - uint16_t grid_top; - uint16_t grid_width; - uint16_t grid_height; - - uint8_t char_width; - uint8_t char_height; - - uint8_t fc_index; - uint8_t bc_index; -} GifPTE; -typedef struct tagGifAE { - uint8_t block_size; - uint8_t app_identify[8]; - uint8_t app_authentication[3]; -} GifAE; -typedef struct tagGifPalette { uint8_t r, g, b; } GifPalette; -#pragma pack() -typedef struct tagGifImage { - GifGCE* image_gce_ptr; - GifPalette* local_pal_ptr; - GifImageInfo* image_info_ptr; - uint8_t image_code_size; - uint32_t image_data_pos; - uint8_t* image_row_buf; - int32_t image_row_num; -} GifImage; - -typedef struct tagGifPlainText { - GifGCE* gce_ptr; - GifPTE* pte_ptr; - CFX_ByteString* string_ptr; -} GifPlainText; - -class CGifLZWDecoder { - public: - struct tag_Table { - uint16_t prefix; - uint8_t suffix; - }; - - explicit CGifLZWDecoder(FX_CHAR* error_ptr); - ~CGifLZWDecoder(); - - void InitTable(uint8_t code_len); - int32_t Decode(uint8_t* des_buf, uint32_t& des_size); - void Input(uint8_t* src_buf, uint32_t src_size); - uint32_t GetAvailInput(); - - private: - void ClearTable(); - void AddCode(uint16_t prefix_code, uint8_t append_char); - void DecodeString(uint16_t code); - - uint8_t code_size; - uint8_t code_size_cur; - uint16_t code_clear; - uint16_t code_end; - uint16_t code_next; - uint8_t code_first; - uint8_t stack[GIF_MAX_LZW_CODE]; - uint16_t stack_size; - tag_Table code_table[GIF_MAX_LZW_CODE]; - uint16_t code_old; - - uint8_t* next_in; - uint32_t avail_in; - - uint8_t bits_left; - uint32_t code_store; - - FX_CHAR* err_msg_ptr; -}; - -class CGifLZWEncoder { - public: - struct tag_Table { - uint16_t prefix; - uint8_t suffix; - }; - - CGifLZWEncoder(); - ~CGifLZWEncoder(); - - void Start(uint8_t code_len, - const uint8_t* src_buf, - uint8_t*& dst_buf, - uint32_t& offset); - bool Encode(const uint8_t* src_buf, - uint32_t src_len, - uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& offset); - void Finish(uint8_t*& dst_buf, uint32_t& dst_len, uint32_t& offset); - - private: - void ClearTable(); - bool LookUpInTable(const uint8_t* buf, uint32_t& offset, uint8_t& bit_offset); - void EncodeString(uint32_t index, - uint8_t*& dst_buf, - uint32_t& dst_len, - uint32_t& offset); - void WriteBlock(uint8_t*& dst_buf, uint32_t& dst_len, uint32_t& offset); - - jmp_buf jmp; - uint32_t src_offset; - uint8_t src_bit_offset; - uint8_t src_bit_cut; - uint32_t src_bit_num; - uint8_t code_size; - uint16_t code_clear; - uint16_t code_end; - uint16_t index_num; - uint8_t bit_offset; - uint8_t index_bit_cur; - uint8_t index_buf[GIF_DATA_BLOCK]; - uint8_t index_buf_len; - tag_Table code_table[GIF_MAX_LZW_CODE]; - uint16_t table_cur; -}; - -typedef struct tag_gif_decompress_struct gif_decompress_struct; -typedef gif_decompress_struct* gif_decompress_struct_p; -typedef gif_decompress_struct_p* gif_decompress_struct_pp; -static const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; -struct tag_gif_decompress_struct { - jmp_buf jmpbuf; - FX_CHAR* err_ptr; - void (*gif_error_fn)(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); - void* context_ptr; - int width; - int height; - GifPalette* global_pal_ptr; - int32_t global_pal_num; - uint8_t global_sort_flag; - uint8_t global_color_resolution; - - uint8_t bc_index; - uint8_t pixel_aspect; - CGifLZWDecoder* img_decoder_ptr; - uint32_t img_row_offset; - uint32_t img_row_avail_size; - uint8_t img_pass_num; - std::vector* img_ptr_arr_ptr; - uint8_t* (*gif_ask_buf_for_pal_fn)(gif_decompress_struct_p gif_ptr, - int32_t pal_size); - uint8_t* next_in; - uint32_t avail_in; - int32_t decode_status; - uint32_t skip_size; - void (*gif_record_current_position_fn)(gif_decompress_struct_p gif_ptr, - uint32_t* cur_pos_ptr); - void (*gif_get_row_fn)(gif_decompress_struct_p gif_ptr, - int32_t row_num, - uint8_t* row_buf); - bool (*gif_get_record_position_fn)(gif_decompress_struct_p gif_ptr, - uint32_t cur_pos, - int32_t left, - int32_t top, - int32_t width, - int32_t height, - int32_t pal_num, - void* pal_ptr, - int32_t delay_time, - bool user_input, - int32_t trans_index, - int32_t disposal_method, - bool interlace); - CFX_ByteString* cmt_data_ptr; - GifGCE* gce_ptr; - std::vector* pt_ptr_arr_ptr; -}; -typedef struct tag_gif_compress_struct gif_compress_struct; -typedef gif_compress_struct* gif_compress_struct_p; -typedef gif_compress_struct_p* gif_compress_struct_pp; -struct tag_gif_compress_struct { - const uint8_t* src_buf; - uint32_t src_pitch; - uint32_t src_width; - uint32_t src_row; - uint32_t cur_offset; - uint32_t frames; - GifHeader* header_ptr; - GifLSD* lsd_ptr; - GifPalette* global_pal; - uint16_t gpal_num; - GifPalette* local_pal; - uint16_t lpal_num; - GifImageInfo* image_info_ptr; - CGifLZWEncoder* img_encoder_ptr; - - uint8_t* cmt_data_ptr; - uint32_t cmt_data_len; - GifGCE* gce_ptr; - GifPTE* pte_ptr; - const uint8_t* pte_data_ptr; - uint32_t pte_data_len; -}; - -void gif_error(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); -void gif_warn(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); -gif_decompress_struct_p gif_create_decompress(); -void gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr); -gif_compress_struct_p gif_create_compress(); -void gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr); -int32_t gif_read_header(gif_decompress_struct_p gif_ptr); -int32_t gif_get_frame(gif_decompress_struct_p gif_ptr); -int32_t gif_get_frame_num(gif_decompress_struct_p gif_ptr); -int32_t gif_decode_extension(gif_decompress_struct_p gif_ptr); -int32_t gif_decode_image_info(gif_decompress_struct_p gif_ptr); -void gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, - GifGCE** gce_ptr_ptr); -int32_t gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num); -uint8_t* gif_read_data(gif_decompress_struct_p gif_ptr, - uint8_t** des_buf_pp, - uint32_t data_size); -void gif_decoding_failure_at_tail_cleanup(gif_decompress_struct_p gif_ptr, - GifImage* gif_image_ptr); -void gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status); -void gif_input_buffer(gif_decompress_struct_p gif_ptr, - uint8_t* src_buf, - uint32_t src_size); -uint32_t gif_get_avail_input(gif_decompress_struct_p gif_ptr, - uint8_t** avail_buf_ptr); -void interlace_buf(const uint8_t* buf, uint32_t width, uint32_t height); -bool gif_encode(gif_compress_struct_p gif_ptr, - uint8_t*& dst_buf, - uint32_t& dst_len); - -#endif // CORE_FXCODEC_LGIF_FX_GIF_H_ diff --git a/core/fxcrt/autorestorer.h b/core/fxcrt/autorestorer.h new file mode 100644 index 0000000000000000000000000000000000000000..745a56fff2de44c7f60a010b5c12dbd1c7e31b57 --- /dev/null +++ b/core/fxcrt/autorestorer.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FXCRT_AUTORESTORER_H_ +#define CORE_FXCRT_AUTORESTORER_H_ + +namespace fxcrt { + +template +class AutoRestorer { + public: + explicit AutoRestorer(T* location) + : m_Location(location), m_OldValue(*location) {} + ~AutoRestorer() { *m_Location = m_OldValue; } + + private: + T* const m_Location; + const T m_OldValue; +}; + +} // namespace fxcrt + +using fxcrt::AutoRestorer; + +#endif // CORE_FXCRT_AUTORESTORER_H_ diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ab1379974e0bb59178df0f5977b069c25754c7e --- /dev/null +++ b/core/fxcrt/bytestring.cpp @@ -0,0 +1,808 @@ +// 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 "core/fxcrt/bytestring.h" + +#include + +#include +#include +#include + +#include "core/fxcrt/cfx_utf8decoder.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/string_pool_template.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/stl_util.h" + +template class fxcrt::StringDataTemplate; +template class fxcrt::StringViewTemplate; +template class fxcrt::StringPoolTemplate; +template struct std::hash; + +namespace { + +constexpr char kTrimChars[] = "\x09\x0a\x0b\x0c\x0d\x20"; + +const char* FX_strstr(const char* haystack, + int haystack_len, + const char* needle, + int needle_len) { + if (needle_len > haystack_len || needle_len == 0) { + return nullptr; + } + const char* end_ptr = haystack + haystack_len - needle_len; + while (haystack <= end_ptr) { + int i = 0; + while (1) { + if (haystack[i] != needle[i]) { + break; + } + i++; + if (i == needle_len) { + return haystack; + } + } + haystack++; + } + return nullptr; +} + +#ifndef NDEBUG +bool IsValidCodePage(uint16_t codepage) { + switch (codepage) { + case FX_CODEPAGE_DefANSI: + case FX_CODEPAGE_ShiftJIS: + case FX_CODEPAGE_ChineseSimplified: + case FX_CODEPAGE_Hangul: + case FX_CODEPAGE_ChineseTraditional: + return true; + default: + return false; + } +} +#endif + +ByteString GetByteString(uint16_t codepage, const WideStringView& wstr) { +#ifndef NDEBUG + ASSERT(IsValidCodePage(codepage)); +#endif + + int src_len = wstr.GetLength(); + int dest_len = + FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len, + nullptr, 0, nullptr, nullptr); + if (!dest_len) + return ByteString(); + + ByteString bstr; + char* dest_buf = bstr.GetBuffer(dest_len); + FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len, + dest_buf, dest_len, nullptr, nullptr); + bstr.ReleaseBuffer(dest_len); + return bstr; +} + +} // namespace + +namespace fxcrt { + +static_assert(sizeof(ByteString) <= sizeof(char*), + "Strings must not require more space than pointers"); + +#define FORCE_ANSI 0x10000 +#define FORCE_UNICODE 0x20000 +#define FORCE_INT64 0x40000 + +// static +ByteString ByteString::FormatInteger(int i) { + char buf[32]; + FXSYS_snprintf(buf, sizeof(buf), "%d", i); + return ByteString(buf); +} + +// static +ByteString ByteString::FormatFloat(float d) { + char buf[32]; + return ByteString(buf, FX_ftoa(d, buf)); +} + +// static +ByteString ByteString::FormatV(const char* pFormat, va_list argList) { + va_list argListCopy; + va_copy(argListCopy, argList); + int nMaxLen = vsnprintf(nullptr, 0, pFormat, argListCopy); + va_end(argListCopy); + + if (nMaxLen <= 0) + return ""; + + ByteString ret; + char* buf = ret.GetBuffer(nMaxLen); + if (buf) { + // In the following two calls, there's always space in the buffer for + // a terminating NUL that's not included in nMaxLen. + memset(buf, 0, nMaxLen + 1); + va_copy(argListCopy, argList); + vsnprintf(buf, nMaxLen + 1, pFormat, argListCopy); + va_end(argListCopy); + ret.ReleaseBuffer(ret.GetStringLength()); + } + return ret; +} + +// static +ByteString ByteString::Format(const char* pFormat, ...) { + va_list argList; + va_start(argList, pFormat); + ByteString ret = FormatV(pFormat, argList); + va_end(argList); + + return ret; +} + +ByteString::ByteString(const char* pStr, size_t nLen) { + if (nLen) + m_pData.Reset(StringData::Create(pStr, nLen)); +} + +ByteString::ByteString(const uint8_t* pStr, size_t nLen) { + if (nLen) + m_pData.Reset( + StringData::Create(reinterpret_cast(pStr), nLen)); +} + +ByteString::ByteString() {} + +ByteString::ByteString(const ByteString& other) : m_pData(other.m_pData) {} + +ByteString::ByteString(ByteString&& other) noexcept { + m_pData.Swap(other.m_pData); +} + +ByteString::ByteString(char ch) { + m_pData.Reset(StringData::Create(1)); + m_pData->m_String[0] = ch; +} + +ByteString::ByteString(const char* ptr) + : ByteString(ptr, ptr ? strlen(ptr) : 0) {} + +ByteString::ByteString(const ByteStringView& stringSrc) { + if (!stringSrc.IsEmpty()) + m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), + stringSrc.GetLength())); +} + +ByteString::ByteString(const ByteStringView& str1, const ByteStringView& str2) { + FX_SAFE_SIZE_T nSafeLen = str1.GetLength(); + nSafeLen += str2.GetLength(); + + size_t nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); + m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), + str2.GetLength()); +} + +ByteString::ByteString(const std::initializer_list& list) { + FX_SAFE_SIZE_T nSafeLen = 0; + for (const auto& item : list) + nSafeLen += item.GetLength(); + + size_t nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + + size_t nOffset = 0; + for (const auto& item : list) { + m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), + item.GetLength()); + nOffset += item.GetLength(); + } +} + +ByteString::ByteString(const std::ostringstream& outStream) { + std::string str = outStream.str(); + if (str.length() > 0) + m_pData.Reset(StringData::Create(str.c_str(), str.length())); +} + +ByteString::~ByteString() {} + +const ByteString& ByteString::operator=(const char* pStr) { + if (!pStr || !pStr[0]) + clear(); + else + AssignCopy(pStr, strlen(pStr)); + + return *this; +} + +const ByteString& ByteString::operator=(const ByteStringView& stringSrc) { + if (stringSrc.IsEmpty()) + clear(); + else + AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength()); + + return *this; +} + +const ByteString& ByteString::operator=(const ByteString& stringSrc) { + if (m_pData != stringSrc.m_pData) + m_pData = stringSrc.m_pData; + + return *this; +} + +const ByteString& ByteString::operator+=(const char* pStr) { + if (pStr) + Concat(pStr, strlen(pStr)); + + return *this; +} + +const ByteString& ByteString::operator+=(char ch) { + Concat(&ch, 1); + return *this; +} + +const ByteString& ByteString::operator+=(const ByteString& str) { + if (str.m_pData) + Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); + + return *this; +} + +const ByteString& ByteString::operator+=(const ByteStringView& str) { + if (!str.IsEmpty()) + Concat(str.unterminated_c_str(), str.GetLength()); + + return *this; +} + +bool ByteString::operator==(const char* ptr) const { + if (!m_pData) + return !ptr || !ptr[0]; + + if (!ptr) + return m_pData->m_nDataLength == 0; + + return strlen(ptr) == m_pData->m_nDataLength && + memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; +} + +bool ByteString::operator==(const ByteStringView& str) const { + if (!m_pData) + return str.IsEmpty(); + + return m_pData->m_nDataLength == str.GetLength() && + memcmp(m_pData->m_String, str.unterminated_c_str(), str.GetLength()) == + 0; +} + +bool ByteString::operator==(const ByteString& other) const { + if (m_pData == other.m_pData) + return true; + + if (IsEmpty()) + return other.IsEmpty(); + + if (other.IsEmpty()) + return false; + + return other.m_pData->m_nDataLength == m_pData->m_nDataLength && + memcmp(other.m_pData->m_String, m_pData->m_String, + m_pData->m_nDataLength) == 0; +} + +bool ByteString::operator<(const char* ptr) const { + if (!m_pData && !ptr) + return false; + if (c_str() == ptr) + return false; + + size_t len = GetLength(); + size_t other_len = ptr ? strlen(ptr) : 0; + int result = memcmp(c_str(), ptr, std::min(len, other_len)); + return result < 0 || (result == 0 && len < other_len); +} + +bool ByteString::operator<(const ByteStringView& str) const { + return Compare(str) < 0; +} + +bool ByteString::operator<(const ByteString& other) const { + if (m_pData == other.m_pData) + return false; + + size_t len = GetLength(); + size_t other_len = other.GetLength(); + int result = memcmp(c_str(), other.c_str(), std::min(len, other_len)); + return result < 0 || (result == 0 && len < other_len); +} + +bool ByteString::EqualNoCase(const ByteStringView& str) const { + if (!m_pData) + return str.IsEmpty(); + + size_t len = str.GetLength(); + if (m_pData->m_nDataLength != len) + return false; + + const uint8_t* pThis = (const uint8_t*)m_pData->m_String; + const uint8_t* pThat = str.raw_str(); + for (size_t i = 0; i < len; i++) { + if ((*pThis) != (*pThat)) { + uint8_t bThis = FXSYS_tolower(*pThis); + uint8_t bThat = FXSYS_tolower(*pThat); + if (bThis != bThat) + return false; + } + pThis++; + pThat++; + } + return true; +} + +void ByteString::AssignCopy(const char* pSrcData, size_t nSrcLen) { + AllocBeforeWrite(nSrcLen); + m_pData->CopyContents(pSrcData, nSrcLen); + m_pData->m_nDataLength = nSrcLen; +} + +void ByteString::ReallocBeforeWrite(size_t nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + RetainPtr pNewData(StringData::Create(nNewLength)); + if (m_pData) { + size_t nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); + pNewData->CopyContents(m_pData->m_String, nCopyLength); + pNewData->m_nDataLength = nCopyLength; + } else { + pNewData->m_nDataLength = 0; + } + pNewData->m_String[pNewData->m_nDataLength] = 0; + m_pData.Swap(pNewData); +} + +void ByteString::AllocBeforeWrite(size_t nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + m_pData.Reset(StringData::Create(nNewLength)); +} + +void ByteString::ReleaseBuffer(size_t nNewLength) { + if (!m_pData) + return; + + nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); + if (nNewLength == 0) { + clear(); + return; + } + + ASSERT(m_pData->m_nRefs == 1); + m_pData->m_nDataLength = nNewLength; + m_pData->m_String[nNewLength] = 0; + if (m_pData->m_nAllocLength - nNewLength >= 32) { + // Over arbitrary threshold, so pay the price to relocate. Force copy to + // always occur by holding a second reference to the string. + ByteString preserve(*this); + ReallocBeforeWrite(nNewLength); + } +} + +void ByteString::Reserve(size_t len) { + GetBuffer(len); +} + +char* ByteString::GetBuffer(size_t nMinBufLength) { + if (!m_pData) { + if (nMinBufLength == 0) + return nullptr; + + m_pData.Reset(StringData::Create(nMinBufLength)); + m_pData->m_nDataLength = 0; + m_pData->m_String[0] = 0; + return m_pData->m_String; + } + + if (m_pData->CanOperateInPlace(nMinBufLength)) + return m_pData->m_String; + + nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); + if (nMinBufLength == 0) + return nullptr; + + RetainPtr pNewData(StringData::Create(nMinBufLength)); + pNewData->CopyContents(*m_pData); + pNewData->m_nDataLength = m_pData->m_nDataLength; + m_pData.Swap(pNewData); + return m_pData->m_String; +} + +size_t ByteString::Delete(size_t index, size_t count) { + if (!m_pData) + return 0; + + size_t old_length = m_pData->m_nDataLength; + if (count == 0 || + index != pdfium::clamp(index, static_cast(0), old_length)) + return old_length; + + size_t removal_length = index + count; + if (removal_length > old_length) + return old_length; + + ReallocBeforeWrite(old_length); + size_t chars_to_copy = old_length - removal_length + 1; + memmove(m_pData->m_String + index, m_pData->m_String + removal_length, + chars_to_copy); + m_pData->m_nDataLength = old_length - count; + return m_pData->m_nDataLength; +} + +void ByteString::Concat(const char* pSrcData, size_t nSrcLen) { + if (!pSrcData || nSrcLen == 0) + return; + + if (!m_pData) { + m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); + return; + } + + if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { + m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData->m_nDataLength += nSrcLen; + return; + } + + RetainPtr pNewData( + StringData::Create(m_pData->m_nDataLength + nSrcLen)); + pNewData->CopyContents(*m_pData); + pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData.Swap(pNewData); +} + +ByteString ByteString::Mid(size_t first, size_t count) const { + if (!m_pData) + return ByteString(); + + if (!IsValidIndex(first)) + return ByteString(); + + if (count == 0 || !IsValidLength(count)) + return ByteString(); + + if (!IsValidIndex(first + count - 1)) + return ByteString(); + + if (first == 0 && count == m_pData->m_nDataLength) + return *this; + + ByteString dest; + AllocCopy(dest, count, first); + return dest; +} + +ByteString ByteString::Left(size_t count) const { + if (count == 0 || !IsValidLength(count)) + return ByteString(); + return Mid(0, count); +} + +ByteString ByteString::Right(size_t count) const { + if (count == 0 || !IsValidLength(count)) + return ByteString(); + return Mid(GetLength() - count, count); +} + +void ByteString::AllocCopy(ByteString& dest, + size_t nCopyLen, + size_t nCopyIndex) const { + if (nCopyLen == 0) + return; + + RetainPtr pNewData( + StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); + dest.m_pData.Swap(pNewData); +} + +void ByteString::SetAt(size_t index, char c) { + ASSERT(IsValidIndex(index)); + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[index] = c; +} + +size_t ByteString::Insert(size_t location, char ch) { + const size_t cur_length = m_pData ? m_pData->m_nDataLength : 0; + if (!IsValidLength(location)) + return cur_length; + + const size_t new_length = cur_length + 1; + ReallocBeforeWrite(new_length); + memmove(m_pData->m_String + location + 1, m_pData->m_String + location, + new_length - location); + m_pData->m_String[location] = ch; + m_pData->m_nDataLength = new_length; + return new_length; +} + +Optional ByteString::Find(char ch, size_t start) const { + if (!m_pData) + return Optional(); + + if (!IsValidIndex(start)) + return Optional(); + + const char* pStr = static_cast( + memchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start)); + return pStr ? Optional(static_cast(pStr - m_pData->m_String)) + : Optional(); +} + +Optional ByteString::Find(const ByteStringView& subStr, + size_t start) const { + if (!m_pData) + return Optional(); + + if (!IsValidIndex(start)) + return Optional(); + + const char* pStr = + FX_strstr(m_pData->m_String + start, m_pData->m_nDataLength - start, + subStr.unterminated_c_str(), subStr.GetLength()); + return pStr ? Optional(static_cast(pStr - m_pData->m_String)) + : Optional(); +} + +Optional ByteString::ReverseFind(char ch) const { + if (!m_pData) + return Optional(); + + size_t nLength = m_pData->m_nDataLength; + while (nLength--) { + if (m_pData->m_String[nLength] == ch) + return Optional(nLength); + } + return Optional(); +} + +void ByteString::MakeLower() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_strlwr(m_pData->m_String); +} + +void ByteString::MakeUpper() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_strupr(m_pData->m_String); +} + +size_t ByteString::Remove(char chRemove) { + if (!m_pData || m_pData->m_nDataLength < 1) + return 0; + + char* pstrSource = m_pData->m_String; + char* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + while (pstrSource < pstrEnd) { + if (*pstrSource == chRemove) + break; + pstrSource++; + } + if (pstrSource == pstrEnd) + return 0; + + ptrdiff_t copied = pstrSource - m_pData->m_String; + ReallocBeforeWrite(m_pData->m_nDataLength); + pstrSource = m_pData->m_String + copied; + pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + + char* pstrDest = pstrSource; + while (pstrSource < pstrEnd) { + if (*pstrSource != chRemove) { + *pstrDest = *pstrSource; + pstrDest++; + } + pstrSource++; + } + + *pstrDest = 0; + size_t nCount = static_cast(pstrSource - pstrDest); + m_pData->m_nDataLength -= nCount; + return nCount; +} + +size_t ByteString::Replace(const ByteStringView& pOld, + const ByteStringView& pNew) { + if (!m_pData || pOld.IsEmpty()) + return 0; + + size_t nSourceLen = pOld.GetLength(); + size_t nReplacementLen = pNew.GetLength(); + size_t nCount = 0; + const char* pStart = m_pData->m_String; + char* pEnd = m_pData->m_String + m_pData->m_nDataLength; + while (1) { + const char* pTarget = FX_strstr(pStart, static_cast(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + if (!pTarget) + break; + + nCount++; + pStart = pTarget + nSourceLen; + } + if (nCount == 0) + return 0; + + size_t nNewLength = + m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; + + if (nNewLength == 0) { + clear(); + return nCount; + } + + RetainPtr pNewData(StringData::Create(nNewLength)); + pStart = m_pData->m_String; + char* pDest = pNewData->m_String; + for (size_t i = 0; i < nCount; i++) { + const char* pTarget = FX_strstr(pStart, static_cast(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + memcpy(pDest, pStart, pTarget - pStart); + pDest += pTarget - pStart; + memcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); + pDest += pNew.GetLength(); + pStart = pTarget + nSourceLen; + } + memcpy(pDest, pStart, pEnd - pStart); + m_pData.Swap(pNewData); + return nCount; +} + +WideString ByteString::UTF8Decode() const { + CFX_UTF8Decoder decoder; + for (size_t i = 0; i < GetLength(); i++) { + decoder.Input(static_cast(m_pData->m_String[i])); + } + return WideString(decoder.GetResult()); +} + +// static +ByteString ByteString::FromUnicode(const WideString& str) { + return GetByteString(0, str.AsStringView()); +} + +int ByteString::Compare(const ByteStringView& str) const { + if (!m_pData) + return str.IsEmpty() ? 0 : -1; + + size_t this_len = m_pData->m_nDataLength; + size_t that_len = str.GetLength(); + size_t min_len = std::min(this_len, that_len); + int result = memcmp(m_pData->m_String, str.unterminated_c_str(), min_len); + if (result != 0) + return result; + if (this_len == that_len) + return 0; + return this_len < that_len ? -1 : 1; +} + +void ByteString::Trim() { + TrimRight(kTrimChars); + TrimLeft(kTrimChars); +} + +void ByteString::Trim(char target) { + ByteStringView targets(target); + TrimRight(targets); + TrimLeft(targets); +} + +void ByteString::Trim(const ByteStringView& targets) { + TrimRight(targets); + TrimLeft(targets); +} + +void ByteString::TrimLeft() { + TrimLeft(kTrimChars); +} + +void ByteString::TrimLeft(char target) { + TrimLeft(ByteStringView(target)); +} + +void ByteString::TrimLeft(const ByteStringView& targets) { + if (!m_pData || targets.IsEmpty()) + return; + + size_t len = GetLength(); + if (len == 0) + return; + + size_t pos = 0; + while (pos < len) { + size_t i = 0; + while (i < targets.GetLength() && targets[i] != m_pData->m_String[pos]) + i++; + if (i == targets.GetLength()) + break; + pos++; + } + if (pos) { + ReallocBeforeWrite(len); + size_t nDataLength = len - pos; + memmove(m_pData->m_String, m_pData->m_String + pos, + (nDataLength + 1) * sizeof(char)); + m_pData->m_nDataLength = nDataLength; + } +} + +void ByteString::TrimRight() { + TrimRight(kTrimChars); +} + +void ByteString::TrimRight(char target) { + TrimRight(ByteStringView(target)); +} + +void ByteString::TrimRight(const ByteStringView& targets) { + if (!m_pData || targets.IsEmpty()) + return; + + size_t pos = GetLength(); + if (pos == 0) + return; + + while (pos) { + size_t i = 0; + while (i < targets.GetLength() && targets[i] != m_pData->m_String[pos - 1]) + i++; + if (i == targets.GetLength()) + break; + pos--; + } + if (pos < m_pData->m_nDataLength) { + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[pos] = 0; + m_pData->m_nDataLength = pos; + } +} + +std::ostream& operator<<(std::ostream& os, const ByteString& str) { + return os.write(str.c_str(), str.GetLength()); +} + +std::ostream& operator<<(std::ostream& os, const ByteStringView& str) { + return os.write(str.unterminated_c_str(), str.GetLength()); +} + +} // namespace fxcrt diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h new file mode 100644 index 0000000000000000000000000000000000000000..70f10dcaba4883b300e04d0e00a1dd3b5e53e7b3 --- /dev/null +++ b/core/fxcrt/bytestring.h @@ -0,0 +1,283 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_BYTESTRING_H_ +#define CORE_FXCRT_BYTESTRING_H_ + +#include +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/string_data_template.h" +#include "core/fxcrt/string_view_template.h" +#include "third_party/base/optional.h" + +namespace fxcrt { + +class ByteString_Concat_Test; +class StringPool_ByteString_Test; +class WideString; + +// A mutable string with shared buffers using copy-on-write semantics that +// avoids the cost of std::string's iterator stability guarantees. +class ByteString { + public: + using CharType = char; + using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator; + + static ByteString FormatInteger(int i) WARN_UNUSED_RESULT; + static ByteString FormatFloat(float f) WARN_UNUSED_RESULT; + static ByteString Format(const char* lpszFormat, ...) WARN_UNUSED_RESULT; + static ByteString FormatV(const char* lpszFormat, + va_list argList) WARN_UNUSED_RESULT; + + ByteString(); + ByteString(const ByteString& other); + ByteString(ByteString&& other) noexcept; + + // Deliberately implicit to avoid calling on every string literal. + // NOLINTNEXTLINE(runtime/explicit) + ByteString(char ch); + // NOLINTNEXTLINE(runtime/explicit) + ByteString(const char* ptr); + + // No implicit conversions from wide strings. + // NOLINTNEXTLINE(runtime/explicit) + ByteString(wchar_t) = delete; + + ByteString(const char* ptr, size_t len); + ByteString(const uint8_t* ptr, size_t len); + + explicit ByteString(const ByteStringView& bstrc); + ByteString(const ByteStringView& bstrc1, const ByteStringView& bstrc2); + ByteString(const std::initializer_list& list); + explicit ByteString(const std::ostringstream& outStream); + + ~ByteString(); + + void clear() { m_pData.Reset(); } + + static ByteString FromUnicode(const WideString& str) WARN_UNUSED_RESULT; + + // Explicit conversion to C-style string. + // Note: Any subsequent modification of |this| will invalidate the result. + const char* c_str() const { return m_pData ? m_pData->m_String : ""; } + + // Explicit conversion to uint8_t*. + // Note: Any subsequent modification of |this| will invalidate the result. + const uint8_t* raw_str() const { + return m_pData ? reinterpret_cast(m_pData->m_String) + : nullptr; + } + + // Explicit conversion to ByteStringView. + // Note: Any subsequent modification of |this| will invalidate the result. + ByteStringView AsStringView() const { + return ByteStringView(raw_str(), GetLength()); + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } + const_iterator end() const { + return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } + size_t GetStringLength() const { + return m_pData ? strlen(m_pData->m_String) : 0; + } + bool IsEmpty() const { return !GetLength(); } + bool IsValidIndex(size_t index) const { return index < GetLength(); } + bool IsValidLength(size_t length) const { return length <= GetLength(); } + + int Compare(const ByteStringView& str) const; + bool EqualNoCase(const ByteStringView& str) const; + + bool operator==(const char* ptr) const; + bool operator==(const ByteStringView& str) const; + bool operator==(const ByteString& other) const; + + bool operator!=(const char* ptr) const { return !(*this == ptr); } + bool operator!=(const ByteStringView& str) const { return !(*this == str); } + bool operator!=(const ByteString& other) const { return !(*this == other); } + + bool operator<(const char* ptr) const; + bool operator<(const ByteStringView& str) const; + bool operator<(const ByteString& other) const; + + const ByteString& operator=(const char* str); + const ByteString& operator=(const ByteStringView& bstrc); + const ByteString& operator=(const ByteString& stringSrc); + + const ByteString& operator+=(char ch); + const ByteString& operator+=(const char* str); + const ByteString& operator+=(const ByteString& str); + const ByteString& operator+=(const ByteStringView& bstrc); + + CharType operator[](const size_t index) const { + ASSERT(IsValidIndex(index)); + return m_pData ? m_pData->m_String[index] : 0; + } + + CharType First() const { return GetLength() ? (*this)[0] : 0; } + CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } + + void SetAt(size_t index, char c); + + size_t Insert(size_t index, char ch); + size_t InsertAtFront(char ch) { return Insert(0, ch); } + size_t InsertAtBack(char ch) { return Insert(GetLength(), ch); } + size_t Delete(size_t index, size_t count = 1); + + void Reserve(size_t len); + char* GetBuffer(size_t len); + void ReleaseBuffer(size_t len); + + ByteString Mid(size_t first, size_t count) const; + ByteString Left(size_t count) const; + ByteString Right(size_t count) const; + + Optional Find(const ByteStringView& lpszSub, size_t start = 0) const; + Optional Find(char ch, size_t start = 0) const; + Optional ReverseFind(char ch) const; + + bool Contains(const ByteStringView& lpszSub, size_t start = 0) const { + return Find(lpszSub, start).has_value(); + } + + bool Contains(char ch, size_t start = 0) const { + return Find(ch, start).has_value(); + } + + void MakeLower(); + void MakeUpper(); + + void Trim(); + void Trim(char target); + void Trim(const ByteStringView& targets); + + void TrimLeft(); + void TrimLeft(char target); + void TrimLeft(const ByteStringView& targets); + + void TrimRight(); + void TrimRight(char target); + void TrimRight(const ByteStringView& targets); + + size_t Replace(const ByteStringView& lpszOld, const ByteStringView& lpszNew); + + size_t Remove(char ch); + + WideString UTF8Decode() const; + + uint32_t GetID() const { return AsStringView().GetID(); } + + protected: + using StringData = StringDataTemplate; + + void ReallocBeforeWrite(size_t nNewLen); + void AllocBeforeWrite(size_t nNewLen); + void AllocCopy(ByteString& dest, size_t nCopyLen, size_t nCopyIndex) const; + void AssignCopy(const char* pSrcData, size_t nSrcLen); + void Concat(const char* lpszSrcData, size_t nSrcLen); + + RetainPtr m_pData; + + friend ByteString_Concat_Test; + friend class StringPool_ByteString_Test; +}; + +inline bool operator==(const char* lhs, const ByteString& rhs) { + return rhs == lhs; +} +inline bool operator==(const ByteStringView& lhs, const ByteString& rhs) { + return rhs == lhs; +} +inline bool operator!=(const char* lhs, const ByteString& rhs) { + return rhs != lhs; +} +inline bool operator!=(const ByteStringView& lhs, const ByteString& rhs) { + return rhs != lhs; +} +inline bool operator<(const char* lhs, const ByteString& rhs) { + return rhs.Compare(lhs) > 0; +} + +inline ByteString operator+(const ByteStringView& str1, + const ByteStringView& str2) { + return ByteString(str1, str2); +} +inline ByteString operator+(const ByteStringView& str1, const char* str2) { + return ByteString(str1, str2); +} +inline ByteString operator+(const char* str1, const ByteStringView& str2) { + return ByteString(str1, str2); +} +inline ByteString operator+(const ByteStringView& str1, char ch) { + return ByteString(str1, ByteStringView(ch)); +} +inline ByteString operator+(char ch, const ByteStringView& str2) { + return ByteString(ch, str2); +} +inline ByteString operator+(const ByteString& str1, const ByteString& str2) { + return ByteString(str1.AsStringView(), str2.AsStringView()); +} +inline ByteString operator+(const ByteString& str1, char ch) { + return ByteString(str1.AsStringView(), ByteStringView(ch)); +} +inline ByteString operator+(char ch, const ByteString& str2) { + return ByteString(ch, str2.AsStringView()); +} +inline ByteString operator+(const ByteString& str1, const char* str2) { + return ByteString(str1.AsStringView(), str2); +} +inline ByteString operator+(const char* str1, const ByteString& str2) { + return ByteString(str1, str2.AsStringView()); +} +inline ByteString operator+(const ByteString& str1, + const ByteStringView& str2) { + return ByteString(str1.AsStringView(), str2); +} +inline ByteString operator+(const ByteStringView& str1, + const ByteString& str2) { + return ByteString(str1, str2.AsStringView()); +} + +std::ostream& operator<<(std::ostream& os, const ByteString& str); +std::ostream& operator<<(std::ostream& os, const ByteStringView& str); + +} // namespace fxcrt + +using ByteString = fxcrt::ByteString; + +uint32_t FX_HashCode_GetA(const ByteStringView& str, bool bIgnoreCase); + +namespace std { + +template <> +struct hash { + std::size_t operator()(const ByteString& str) const { + return FX_HashCode_GetA(str.AsStringView(), false); + } +}; + +} // namespace std + +extern template struct std::hash; + +#endif // CORE_FXCRT_BYTESTRING_H_ diff --git a/core/fxcrt/bytestring_unittest.cpp b/core/fxcrt/bytestring_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce1512b4cfc91dc856f38d0f385972541706c3e0 --- /dev/null +++ b/core/fxcrt/bytestring_unittest.cpp @@ -0,0 +1,1727 @@ +// 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. + +#include "core/fxcrt/bytestring.h" + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/stl_util.h" + +namespace fxcrt { + +TEST(ByteString, ElementAccess) { + const ByteString abc("abc"); + EXPECT_EQ('a', abc[0]); + EXPECT_EQ('b', abc[1]); + EXPECT_EQ('c', abc[2]); +#ifndef NDEBUG + EXPECT_DEATH({ abc[3]; }, ".*"); +#endif + + ByteString mutable_abc = abc; + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ('a', mutable_abc[0]); + EXPECT_EQ('b', mutable_abc[1]); + EXPECT_EQ('c', mutable_abc[2]); + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ("abc", abc); + + const char* c_str = abc.c_str(); + mutable_abc.SetAt(0, 'd'); + EXPECT_EQ(c_str, abc.c_str()); + EXPECT_NE(c_str, mutable_abc.c_str()); + EXPECT_EQ("abc", abc); + EXPECT_EQ("dbc", mutable_abc); + + mutable_abc.SetAt(1, 'e'); + EXPECT_EQ("abc", abc); + EXPECT_EQ("dec", mutable_abc); + + mutable_abc.SetAt(2, 'f'); + EXPECT_EQ("abc", abc); + EXPECT_EQ("def", mutable_abc); +#ifndef NDEBUG + EXPECT_DEATH({ mutable_abc.SetAt(3, 'g'); }, ".*"); + EXPECT_EQ("abc", abc); +#endif +} + +TEST(ByteString, OperatorLT) { + ByteString empty; + ByteString a("a"); + ByteString abc("abc"); + ByteString def("def"); + ByteStringView v_empty; + ByteStringView v_a("a"); + ByteStringView v_abc("abc"); + ByteStringView v_def("def"); + const char* const c_null = nullptr; + const char* const c_empty = ""; + const char* const c_a = "a"; + const char* const c_abc = "abc"; + const char* const c_def = "def"; + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + EXPECT_FALSE(c_null < empty); + EXPECT_FALSE(c_empty < empty); + EXPECT_FALSE(c_a < a); + EXPECT_FALSE(c_abc < abc); + EXPECT_FALSE(c_def < def); + EXPECT_FALSE(empty < c_null); + EXPECT_FALSE(empty < c_empty); + EXPECT_FALSE(a < c_a); + EXPECT_FALSE(abc < c_abc); + EXPECT_FALSE(def < c_def); + EXPECT_FALSE(empty < v_empty); + EXPECT_FALSE(a < v_a); + EXPECT_FALSE(abc < v_abc); + EXPECT_FALSE(def < v_def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + EXPECT_TRUE(c_null < a); + EXPECT_TRUE(c_empty < a); + EXPECT_FALSE(c_a < empty); + EXPECT_TRUE(empty < c_a); + EXPECT_FALSE(a < c_null); + EXPECT_FALSE(a < c_empty); + EXPECT_TRUE(empty < v_a); + EXPECT_FALSE(a < v_empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + EXPECT_TRUE(c_null < abc); + EXPECT_TRUE(c_empty < abc); + EXPECT_FALSE(c_abc < empty); + EXPECT_TRUE(empty < c_abc); + EXPECT_FALSE(abc < c_null); + EXPECT_FALSE(abc < c_empty); + EXPECT_TRUE(empty < v_abc); + EXPECT_FALSE(abc < v_empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + EXPECT_TRUE(c_null < def); + EXPECT_TRUE(c_empty < def); + EXPECT_FALSE(c_def < empty); + EXPECT_TRUE(empty < c_def); + EXPECT_FALSE(def < c_null); + EXPECT_FALSE(def < c_empty); + EXPECT_TRUE(empty < v_def); + EXPECT_FALSE(def < v_empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + EXPECT_TRUE(c_a < abc); + EXPECT_FALSE(c_abc < a); + EXPECT_TRUE(a < c_abc); + EXPECT_FALSE(abc < c_a); + EXPECT_TRUE(a < v_abc); + EXPECT_FALSE(abc < v_a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + EXPECT_TRUE(c_a < def); + EXPECT_FALSE(c_def < a); + EXPECT_TRUE(a < c_def); + EXPECT_FALSE(def < c_a); + EXPECT_TRUE(a < v_def); + EXPECT_FALSE(def < v_a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); + EXPECT_TRUE(c_abc < def); + EXPECT_FALSE(c_def < abc); + EXPECT_TRUE(abc < c_def); + EXPECT_FALSE(def < c_abc); + EXPECT_TRUE(abc < v_def); + EXPECT_FALSE(def < v_abc); +} + +TEST(ByteString, OperatorEQ) { + ByteString null_string; + EXPECT_TRUE(null_string == null_string); + + ByteString empty_string(""); + EXPECT_TRUE(empty_string == empty_string); + EXPECT_TRUE(empty_string == null_string); + EXPECT_TRUE(null_string == empty_string); + + ByteString deleted_string("hello"); + deleted_string.Delete(0, 5); + EXPECT_TRUE(deleted_string == deleted_string); + EXPECT_TRUE(deleted_string == null_string); + EXPECT_TRUE(deleted_string == empty_string); + EXPECT_TRUE(null_string == deleted_string); + EXPECT_TRUE(empty_string == deleted_string); + + ByteString byte_string("hello"); + EXPECT_TRUE(byte_string == byte_string); + EXPECT_FALSE(byte_string == null_string); + EXPECT_FALSE(byte_string == empty_string); + EXPECT_FALSE(byte_string == deleted_string); + EXPECT_FALSE(null_string == byte_string); + EXPECT_FALSE(empty_string == byte_string); + EXPECT_FALSE(deleted_string == byte_string); + + ByteString byte_string_same1("hello"); + EXPECT_TRUE(byte_string == byte_string_same1); + EXPECT_TRUE(byte_string_same1 == byte_string); + + ByteString byte_string_same2(byte_string); + EXPECT_TRUE(byte_string == byte_string_same2); + EXPECT_TRUE(byte_string_same2 == byte_string); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_FALSE(byte_string == byte_string1); + EXPECT_FALSE(byte_string == byte_string2); + EXPECT_FALSE(byte_string == byte_string3); + EXPECT_FALSE(byte_string1 == byte_string); + EXPECT_FALSE(byte_string2 == byte_string); + EXPECT_FALSE(byte_string3 == byte_string); + + ByteStringView null_string_c; + ByteStringView empty_string_c(""); + EXPECT_TRUE(null_string == null_string_c); + EXPECT_TRUE(null_string == empty_string_c); + EXPECT_TRUE(empty_string == null_string_c); + EXPECT_TRUE(empty_string == empty_string_c); + EXPECT_TRUE(deleted_string == null_string_c); + EXPECT_TRUE(deleted_string == empty_string_c); + EXPECT_TRUE(null_string_c == null_string); + EXPECT_TRUE(empty_string_c == null_string); + EXPECT_TRUE(null_string_c == empty_string); + EXPECT_TRUE(empty_string_c == empty_string); + EXPECT_TRUE(null_string_c == deleted_string); + EXPECT_TRUE(empty_string_c == deleted_string); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_TRUE(byte_string == byte_string_c_same1); + EXPECT_TRUE(byte_string_c_same1 == byte_string); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_FALSE(byte_string == byte_string_c1); + EXPECT_FALSE(byte_string == byte_string_c2); + EXPECT_FALSE(byte_string == byte_string_c3); + EXPECT_FALSE(byte_string_c1 == byte_string); + EXPECT_FALSE(byte_string_c2 == byte_string); + EXPECT_FALSE(byte_string_c3 == byte_string); + + const char* const c_null_string = nullptr; + const char* const c_empty_string = ""; + EXPECT_TRUE(null_string == c_null_string); + EXPECT_TRUE(null_string == c_empty_string); + EXPECT_TRUE(empty_string == c_null_string); + EXPECT_TRUE(empty_string == c_empty_string); + EXPECT_TRUE(deleted_string == c_null_string); + EXPECT_TRUE(deleted_string == c_empty_string); + EXPECT_TRUE(c_null_string == null_string); + EXPECT_TRUE(c_empty_string == null_string); + EXPECT_TRUE(c_null_string == empty_string); + EXPECT_TRUE(c_empty_string == empty_string); + EXPECT_TRUE(c_null_string == deleted_string); + EXPECT_TRUE(c_empty_string == deleted_string); + + const char* const c_string_same1 = "hello"; + EXPECT_TRUE(byte_string == c_string_same1); + EXPECT_TRUE(c_string_same1 == byte_string); + + const char* const c_string1 = "he"; + const char* const c_string2 = "hellp"; + const char* const c_string3 = "hellod"; + EXPECT_FALSE(byte_string == c_string1); + EXPECT_FALSE(byte_string == c_string2); + EXPECT_FALSE(byte_string == c_string3); + EXPECT_FALSE(c_string1 == byte_string); + EXPECT_FALSE(c_string2 == byte_string); + EXPECT_FALSE(c_string3 == byte_string); +} + +TEST(ByteString, OperatorNE) { + ByteString null_string; + EXPECT_FALSE(null_string != null_string); + + ByteString empty_string(""); + EXPECT_FALSE(empty_string != empty_string); + EXPECT_FALSE(empty_string != null_string); + EXPECT_FALSE(null_string != empty_string); + + ByteString deleted_string("hello"); + deleted_string.Delete(0, 5); + EXPECT_FALSE(deleted_string != deleted_string); + EXPECT_FALSE(deleted_string != null_string); + EXPECT_FALSE(deleted_string != empty_string); + EXPECT_FALSE(deleted_string != deleted_string); + EXPECT_FALSE(null_string != deleted_string); + EXPECT_FALSE(empty_string != deleted_string); + EXPECT_FALSE(deleted_string != deleted_string); + + ByteString byte_string("hello"); + EXPECT_FALSE(byte_string != byte_string); + EXPECT_TRUE(byte_string != null_string); + EXPECT_TRUE(byte_string != empty_string); + EXPECT_TRUE(byte_string != deleted_string); + EXPECT_TRUE(null_string != byte_string); + EXPECT_TRUE(empty_string != byte_string); + EXPECT_TRUE(deleted_string != byte_string); + + ByteString byte_string_same1("hello"); + EXPECT_FALSE(byte_string != byte_string_same1); + EXPECT_FALSE(byte_string_same1 != byte_string); + + ByteString byte_string_same2(byte_string); + EXPECT_FALSE(byte_string != byte_string_same2); + EXPECT_FALSE(byte_string_same2 != byte_string); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_TRUE(byte_string != byte_string1); + EXPECT_TRUE(byte_string != byte_string2); + EXPECT_TRUE(byte_string != byte_string3); + EXPECT_TRUE(byte_string1 != byte_string); + EXPECT_TRUE(byte_string2 != byte_string); + EXPECT_TRUE(byte_string3 != byte_string); + + ByteStringView null_string_c; + ByteStringView empty_string_c(""); + EXPECT_FALSE(null_string != null_string_c); + EXPECT_FALSE(null_string != empty_string_c); + EXPECT_FALSE(empty_string != null_string_c); + EXPECT_FALSE(empty_string != empty_string_c); + EXPECT_FALSE(null_string_c != null_string); + EXPECT_FALSE(empty_string_c != null_string); + EXPECT_FALSE(null_string_c != empty_string); + EXPECT_FALSE(empty_string_c != empty_string); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_FALSE(byte_string != byte_string_c_same1); + EXPECT_FALSE(byte_string_c_same1 != byte_string); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_TRUE(byte_string != byte_string_c1); + EXPECT_TRUE(byte_string != byte_string_c2); + EXPECT_TRUE(byte_string != byte_string_c3); + EXPECT_TRUE(byte_string_c1 != byte_string); + EXPECT_TRUE(byte_string_c2 != byte_string); + EXPECT_TRUE(byte_string_c3 != byte_string); + + const char* const c_null_string = nullptr; + const char* const c_empty_string = ""; + EXPECT_FALSE(null_string != c_null_string); + EXPECT_FALSE(null_string != c_empty_string); + EXPECT_FALSE(empty_string != c_null_string); + EXPECT_FALSE(empty_string != c_empty_string); + EXPECT_FALSE(deleted_string != c_null_string); + EXPECT_FALSE(deleted_string != c_empty_string); + EXPECT_FALSE(c_null_string != null_string); + EXPECT_FALSE(c_empty_string != null_string); + EXPECT_FALSE(c_null_string != empty_string); + EXPECT_FALSE(c_empty_string != empty_string); + EXPECT_FALSE(c_null_string != deleted_string); + EXPECT_FALSE(c_empty_string != deleted_string); + + const char* const c_string_same1 = "hello"; + EXPECT_FALSE(byte_string != c_string_same1); + EXPECT_FALSE(c_string_same1 != byte_string); + + const char* const c_string1 = "he"; + const char* const c_string2 = "hellp"; + const char* const c_string3 = "hellod"; + EXPECT_TRUE(byte_string != c_string1); + EXPECT_TRUE(byte_string != c_string2); + EXPECT_TRUE(byte_string != c_string3); + EXPECT_TRUE(c_string1 != byte_string); + EXPECT_TRUE(c_string2 != byte_string); + EXPECT_TRUE(c_string3 != byte_string); +} + +TEST(ByteStringView, Null) { + ByteStringView null_string; + EXPECT_FALSE(null_string.raw_str()); + EXPECT_EQ(0u, null_string.GetLength()); + EXPECT_TRUE(null_string.IsEmpty()); + + ByteStringView another_null_string; + EXPECT_EQ(null_string, another_null_string); + + ByteStringView copied_null_string(null_string); + EXPECT_FALSE(copied_null_string.raw_str()); + EXPECT_EQ(0u, copied_null_string.GetLength()); + EXPECT_TRUE(copied_null_string.IsEmpty()); + EXPECT_EQ(null_string, copied_null_string); + + ByteStringView empty_string(""); // Pointer to NUL, not NULL pointer. + EXPECT_TRUE(empty_string.raw_str()); + EXPECT_EQ(0u, empty_string.GetLength()); + EXPECT_TRUE(empty_string.IsEmpty()); + EXPECT_EQ(null_string, empty_string); + + ByteStringView assigned_null_string("initially not nullptr"); + assigned_null_string = null_string; + EXPECT_FALSE(assigned_null_string.raw_str()); + EXPECT_EQ(0u, assigned_null_string.GetLength()); + EXPECT_TRUE(assigned_null_string.IsEmpty()); + EXPECT_EQ(null_string, assigned_null_string); + + ByteStringView assigned_nullptr_string("initially not nullptr"); + assigned_nullptr_string = nullptr; + EXPECT_FALSE(assigned_nullptr_string.raw_str()); + EXPECT_EQ(0u, assigned_nullptr_string.GetLength()); + EXPECT_TRUE(assigned_nullptr_string.IsEmpty()); + EXPECT_EQ(null_string, assigned_nullptr_string); + + ByteStringView non_null_string("a"); + EXPECT_NE(null_string, non_null_string); +} + +TEST(ByteString, Concat) { + ByteString fred; + fred.Concat("FRED", 4); + EXPECT_EQ("FRED", fred); + + fred.Concat("DY", 2); + EXPECT_EQ("FREDDY", fred); + + fred.Delete(3, 3); + EXPECT_EQ("FRE", fred); + + fred.Concat("D", 1); + EXPECT_EQ("FRED", fred); + + ByteString copy = fred; + fred.Concat("DY", 2); + EXPECT_EQ("FREDDY", fred); + EXPECT_EQ("FRED", copy); +} + +TEST(ByteString, Remove) { + ByteString freed("FREED"); + freed.Remove('E'); + EXPECT_EQ("FRD", freed); + freed.Remove('F'); + EXPECT_EQ("RD", freed); + freed.Remove('D'); + EXPECT_EQ("R", freed); + freed.Remove('X'); + EXPECT_EQ("R", freed); + freed.Remove('R'); + EXPECT_EQ("", freed); + + ByteString empty; + empty.Remove('X'); + EXPECT_EQ("", empty); +} + +TEST(ByteString, RemoveCopies) { + ByteString freed("FREED"); + const char* old_buffer = freed.c_str(); + + // No change with single reference - no copy. + freed.Remove('Q'); + EXPECT_EQ("FREED", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // Change with single reference - no copy. + freed.Remove('E'); + EXPECT_EQ("FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // No change with multiple references - no copy. + ByteString shared(freed); + freed.Remove('Q'); + EXPECT_EQ("FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + EXPECT_EQ(old_buffer, shared.c_str()); + + // Change with multiple references -- must copy. + freed.Remove('D'); + EXPECT_EQ("FR", freed); + EXPECT_NE(old_buffer, freed.c_str()); + EXPECT_EQ("FRD", shared); + EXPECT_EQ(old_buffer, shared.c_str()); +} + +TEST(ByteString, Replace) { + ByteString fred("FRED"); + fred.Replace("FR", "BL"); + EXPECT_EQ("BLED", fred); + fred.Replace("D", "DDY"); + EXPECT_EQ("BLEDDY", fred); + fred.Replace("LEDD", ""); + EXPECT_EQ("BY", fred); + fred.Replace("X", "CLAMS"); + EXPECT_EQ("BY", fred); + fred.Replace("BY", "HI"); + EXPECT_EQ("HI", fred); + fred.Replace("", "CLAMS"); + EXPECT_EQ("HI", fred); + fred.Replace("HI", ""); + EXPECT_EQ("", fred); +} + +TEST(ByteString, Insert) { + ByteString fred("FRED"); + EXPECT_EQ(5u, fred.Insert(0, 'S')); + EXPECT_EQ("SFRED", fred); + EXPECT_EQ(6u, fred.Insert(1, 'T')); + EXPECT_EQ("STFRED", fred); + EXPECT_EQ(7u, fred.Insert(4, 'U')); + EXPECT_EQ("STFRUED", fred); + EXPECT_EQ(8u, fred.Insert(7, 'V')); + EXPECT_EQ("STFRUEDV", fred); + EXPECT_EQ(8u, fred.Insert(12, 'P')); + EXPECT_EQ("STFRUEDV", fred); + { + ByteString empty; + EXPECT_EQ(1u, empty.Insert(0, 'X')); + EXPECT_EQ("X", empty); + } + { + ByteString empty; + EXPECT_EQ(0u, empty.Insert(5, 'X')); + EXPECT_NE("X", empty); + } +} + +TEST(ByteString, InsertAtFrontAndInsertAtBack) { + { + ByteString empty; + EXPECT_EQ(1u, empty.InsertAtFront('D')); + EXPECT_EQ("D", empty); + EXPECT_EQ(2u, empty.InsertAtFront('E')); + EXPECT_EQ("ED", empty); + EXPECT_EQ(3u, empty.InsertAtFront('R')); + EXPECT_EQ("RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ("FRED", empty); + } + { + ByteString empty; + EXPECT_EQ(1u, empty.InsertAtBack('F')); + EXPECT_EQ("F", empty); + EXPECT_EQ(2u, empty.InsertAtBack('R')); + EXPECT_EQ("FR", empty); + EXPECT_EQ(3u, empty.InsertAtBack('E')); + EXPECT_EQ("FRE", empty); + EXPECT_EQ(4u, empty.InsertAtBack('D')); + EXPECT_EQ("FRED", empty); + } + { + ByteString empty; + EXPECT_EQ(1u, empty.InsertAtBack('E')); + EXPECT_EQ("E", empty); + EXPECT_EQ(2u, empty.InsertAtFront('R')); + EXPECT_EQ("RE", empty); + EXPECT_EQ(3u, empty.InsertAtBack('D')); + EXPECT_EQ("RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ("FRED", empty); + } +} + +TEST(ByteString, Delete) { + ByteString fred("FRED"); + EXPECT_EQ(4u, fred.Delete(0, 0)); + EXPECT_EQ("FRED", fred); + EXPECT_EQ(2u, fred.Delete(0, 2)); + EXPECT_EQ("ED", fred); + EXPECT_EQ(1u, fred.Delete(1)); + EXPECT_EQ("E", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ("", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ("", fred); + + ByteString empty; + EXPECT_EQ(0u, empty.Delete(0)); + EXPECT_EQ("", empty); + EXPECT_EQ(0u, empty.Delete(1)); + EXPECT_EQ("", empty); +} + +TEST(ByteString, Mid) { + ByteString fred("FRED"); + EXPECT_EQ("", fred.Mid(0, 0)); + EXPECT_EQ("", fred.Mid(3, 0)); + EXPECT_EQ("FRED", fred.Mid(0, 4)); + EXPECT_EQ("RED", fred.Mid(1, 3)); + EXPECT_EQ("ED", fred.Mid(2, 2)); + EXPECT_EQ("D", fred.Mid(3, 1)); + EXPECT_EQ("F", fred.Mid(0, 1)); + EXPECT_EQ("R", fred.Mid(1, 1)); + EXPECT_EQ("E", fred.Mid(2, 1)); + EXPECT_EQ("D", fred.Mid(3, 1)); + EXPECT_EQ("FR", fred.Mid(0, 2)); + EXPECT_EQ("FRED", fred.Mid(0, 4)); + EXPECT_EQ("", fred.Mid(0, 10)); + + EXPECT_EQ("RED", fred.Mid(1, 3)); + EXPECT_EQ("", fred.Mid(4, 1)); + + ByteString empty; + EXPECT_EQ("", empty.Mid(0, 0)); +} + +TEST(ByteString, Left) { + ByteString fred("FRED"); + EXPECT_EQ("", fred.Left(0)); + EXPECT_EQ("F", fred.Left(1)); + EXPECT_EQ("FR", fred.Left(2)); + EXPECT_EQ("FRE", fred.Left(3)); + EXPECT_EQ("FRED", fred.Left(4)); + + EXPECT_EQ("", fred.Left(5)); + + ByteString empty; + EXPECT_EQ("", empty.Left(0)); + EXPECT_EQ("", empty.Left(1)); +} + +TEST(ByteString, Right) { + ByteString fred("FRED"); + EXPECT_EQ("", fred.Right(0)); + EXPECT_EQ("D", fred.Right(1)); + EXPECT_EQ("ED", fred.Right(2)); + EXPECT_EQ("RED", fred.Right(3)); + EXPECT_EQ("FRED", fred.Right(4)); + + EXPECT_EQ("", fred.Right(5)); + + ByteString empty; + EXPECT_EQ("", empty.Right(0)); + EXPECT_EQ("", empty.Right(1)); +} + +TEST(ByteString, Find) { + ByteString null_string; + EXPECT_FALSE(null_string.Find('a').has_value()); + EXPECT_FALSE(null_string.Find('\0').has_value()); + + ByteString empty_string(""); + EXPECT_FALSE(empty_string.Find('a').has_value()); + EXPECT_FALSE(empty_string.Find('\0').has_value()); + + Optional result; + ByteString single_string("a"); + result = single_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find('b').has_value()); + EXPECT_FALSE(single_string.Find('\0').has_value()); + + ByteString longer_string("abccc"); + result = longer_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find('c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find('c', 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find('d').has_value()); + EXPECT_FALSE(longer_string.Find('\0').has_value()); + + result = longer_string.Find("ab"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find("ccc"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find("cc", 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find("d").has_value()); + + ByteString hibyte_string( + "ab\x8c" + "def"); + result = hibyte_string.Find('\x8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(ByteString, ReverseFind) { + ByteString null_string; + EXPECT_FALSE(null_string.ReverseFind('a').has_value()); + EXPECT_FALSE(null_string.ReverseFind('\0').has_value()); + + ByteString empty_string(""); + EXPECT_FALSE(empty_string.ReverseFind('a').has_value()); + EXPECT_FALSE(empty_string.ReverseFind('\0').has_value()); + + Optional result; + ByteString single_string("a"); + result = single_string.ReverseFind('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.ReverseFind('b').has_value()); + EXPECT_FALSE(single_string.ReverseFind('\0').has_value()); + + ByteString longer_string("abccc"); + result = longer_string.ReverseFind('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.ReverseFind('c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(4u, result.value()); + EXPECT_FALSE(longer_string.ReverseFind('\0').has_value()); + + ByteString hibyte_string( + "ab\x8c" + "def"); + result = hibyte_string.ReverseFind('\x8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(ByteString, UpperLower) { + ByteString fred("F-Re.42D"); + fred.MakeLower(); + EXPECT_EQ("f-re.42d", fred); + fred.MakeUpper(); + EXPECT_EQ("F-RE.42D", fred); + + ByteString empty; + empty.MakeLower(); + EXPECT_EQ("", empty); + empty.MakeUpper(); + EXPECT_EQ("", empty); +} + +TEST(ByteString, Trim) { + ByteString fred(" FRED "); + fred.Trim(); + EXPECT_EQ("FRED", fred); + fred.Trim('E'); + EXPECT_EQ("FRED", fred); + fred.Trim('F'); + EXPECT_EQ("RED", fred); + fred.Trim("ERP"); + EXPECT_EQ("D", fred); + + ByteString blank(" "); + blank.Trim("ERP"); + EXPECT_EQ(" ", blank); + blank.Trim('E'); + EXPECT_EQ(" ", blank); + blank.Trim(); + EXPECT_EQ("", blank); + + ByteString empty; + empty.Trim("ERP"); + EXPECT_EQ("", empty); + empty.Trim('E'); + EXPECT_EQ("", empty); + empty.Trim(); + EXPECT_EQ("", empty); + + ByteString abc(" ABCCBA "); + abc.Trim("A"); + EXPECT_EQ(" ABCCBA ", abc); + abc.Trim(" A"); + EXPECT_EQ("BCCB", abc); +} + +TEST(ByteString, TrimLeft) { + ByteString fred(" FRED "); + fred.TrimLeft(); + EXPECT_EQ("FRED ", fred); + fred.TrimLeft('E'); + EXPECT_EQ("FRED ", fred); + fred.TrimLeft('F'); + EXPECT_EQ("RED ", fred); + fred.TrimLeft("ERP"); + EXPECT_EQ("D ", fred); + + ByteString blank(" "); + blank.TrimLeft("ERP"); + EXPECT_EQ(" ", blank); + blank.TrimLeft('E'); + EXPECT_EQ(" ", blank); + blank.TrimLeft(); + EXPECT_EQ("", blank); + + ByteString empty; + empty.TrimLeft("ERP"); + EXPECT_EQ("", empty); + empty.TrimLeft('E'); + EXPECT_EQ("", empty); + empty.TrimLeft(); + EXPECT_EQ("", empty); +} + +TEST(ByteString, TrimLeftCopies) { + { + // With a single reference, no copy takes place. + ByteString fred(" FRED "); + const char* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ("FRED ", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + ByteString fred(" FRED "); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ("FRED ", fred); + EXPECT_EQ(" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + ByteString fred("FRED"); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ("FRED", fred); + EXPECT_EQ("FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(ByteString, TrimRight) { + ByteString fred(" FRED "); + fred.TrimRight(); + EXPECT_EQ(" FRED", fred); + fred.TrimRight('E'); + EXPECT_EQ(" FRED", fred); + fred.TrimRight('D'); + EXPECT_EQ(" FRE", fred); + fred.TrimRight("ERP"); + EXPECT_EQ(" F", fred); + + ByteString blank(" "); + blank.TrimRight("ERP"); + EXPECT_EQ(" ", blank); + blank.TrimRight('E'); + EXPECT_EQ(" ", blank); + blank.TrimRight(); + EXPECT_EQ("", blank); + + ByteString empty; + empty.TrimRight("ERP"); + EXPECT_EQ("", empty); + empty.TrimRight('E'); + EXPECT_EQ("", empty); + empty.TrimRight(); + EXPECT_EQ("", empty); +} + +TEST(ByteString, TrimRightCopies) { + { + // With a single reference, no copy takes place. + ByteString fred(" FRED "); + const char* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(" FRED", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + ByteString fred(" FRED "); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(" FRED", fred); + EXPECT_EQ(" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + ByteString fred("FRED"); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ("FRED", fred); + EXPECT_EQ("FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(ByteString, Reserve) { + { + ByteString str; + str.Reserve(6); + const char* old_buffer = str.c_str(); + str += "ABCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += "Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } + { + ByteString str("A"); + str.Reserve(6); + const char* old_buffer = str.c_str(); + str += "BCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += "Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } +} + +TEST(ByteString, GetBuffer) { + { + ByteString str; + char* buffer = str.GetBuffer(12); + // NOLINTNEXTLINE(runtime/printf) + strcpy(buffer, "clams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ("clams", str); + } + { + ByteString str("cl"); + char* buffer = str.GetBuffer(12); + // NOLINTNEXTLINE(runtime/printf) + strcpy(buffer + 2, "ams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ("clams", str); + } +} + +TEST(ByteString, ReleaseBuffer) { + { + ByteString str; + str.Reserve(12); + str += "clams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + ByteString str("c"); + str.Reserve(12); + str += "lams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + ByteString str; + str.Reserve(200); + str += "clams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + ByteString str("c"); + str.Reserve(200); + str += "lams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } +} + +TEST(ByteString, EmptyReverseIterator) { + ByteString empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(ByteString, OneCharReverseIterator) { + ByteString one_str("a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(ByteString, MultiCharReverseIterator) { + ByteString multi_str("abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(ByteStringView, NotNull) { + ByteStringView string3("abc"); + ByteStringView string6("abcdef"); + ByteStringView alternate_string3("abcdef", 3); + ByteStringView embedded_nul_string7("abc\0def", 7); + ByteStringView illegal_string7("abcdef", 7); + + EXPECT_EQ(3u, string3.GetLength()); + EXPECT_EQ(6u, string6.GetLength()); + EXPECT_EQ(3u, alternate_string3.GetLength()); + EXPECT_EQ(7u, embedded_nul_string7.GetLength()); + EXPECT_EQ(7u, illegal_string7.GetLength()); + + EXPECT_NE(string3, string6); + EXPECT_EQ(string3, alternate_string3); + EXPECT_NE(string3, embedded_nul_string7); + EXPECT_NE(string3, illegal_string7); + EXPECT_NE(string6, alternate_string3); + EXPECT_NE(string6, embedded_nul_string7); + EXPECT_NE(string6, illegal_string7); + EXPECT_NE(alternate_string3, embedded_nul_string7); + EXPECT_NE(alternate_string3, illegal_string7); + EXPECT_NE(embedded_nul_string7, illegal_string7); + + ByteStringView copied_string3(string3); + ByteStringView copied_alternate_string3(alternate_string3); + ByteStringView copied_embedded_nul_string7(embedded_nul_string7); + + EXPECT_EQ(string3, copied_string3); + EXPECT_EQ(alternate_string3, copied_alternate_string3); + EXPECT_EQ(embedded_nul_string7, copied_embedded_nul_string7); + + ByteStringView assigned_string3("intially something else"); + ByteStringView assigned_alternate_string3("initally something else"); + ByteStringView assigned_ptr_string3("initially something else"); + ByteStringView assigned_embedded_nul_string7("initially something else"); + + assigned_string3 = string3; + assigned_alternate_string3 = alternate_string3; + assigned_ptr_string3 = "abc"; + assigned_embedded_nul_string7 = embedded_nul_string7; + EXPECT_EQ(string3, assigned_string3); + EXPECT_EQ(alternate_string3, assigned_alternate_string3); + EXPECT_EQ(alternate_string3, assigned_ptr_string3); + EXPECT_EQ(embedded_nul_string7, assigned_embedded_nul_string7); +} + +TEST(ByteStringView, FromChar) { + ByteStringView null_string; + ByteStringView lower_a_string("a"); + + // Must have lvalues that outlive the corresponding ByteStringC. + char nul = '\0'; + char lower_a = 'a'; + ByteStringView nul_string_from_char(nul); + ByteStringView lower_a_string_from_char(lower_a); + + // Pointer to nul, not nullptr ptr, hence length 1 ... + EXPECT_EQ(1u, nul_string_from_char.GetLength()); + EXPECT_NE(null_string, nul_string_from_char); + + EXPECT_EQ(1u, lower_a_string_from_char.GetLength()); + EXPECT_EQ(lower_a_string, lower_a_string_from_char); + EXPECT_NE(nul_string_from_char, lower_a_string_from_char); + + ByteStringView longer_string("ab"); + EXPECT_NE(longer_string, lower_a_string_from_char); +} + +TEST(ByteStringView, FromVector) { + std::vector null_vec; + ByteStringView null_string(null_vec); + EXPECT_EQ(0u, null_string.GetLength()); + + std::vector lower_a_vec(10, static_cast('a')); + ByteStringView lower_a_string(lower_a_vec); + EXPECT_EQ(static_cast(10), lower_a_string.GetLength()); + EXPECT_EQ("aaaaaaaaaa", lower_a_string); + + std::vector cleared_vec; + cleared_vec.push_back(42); + cleared_vec.pop_back(); + ByteStringView cleared_string(cleared_vec); + EXPECT_EQ(0u, cleared_string.GetLength()); + EXPECT_EQ(nullptr, cleared_string.raw_str()); +} + +TEST(ByteStringView, GetID) { + ByteStringView null_string; + EXPECT_EQ(0u, null_string.GetID()); + + ByteStringView empty_string(""); + EXPECT_EQ(0u, empty_string.GetID()); + + ByteStringView short_string("ab"); + EXPECT_EQ(FXBSTR_ID('a', 'b', 0, 0), short_string.GetID()); + + ByteStringView longer_string("abcdef"); + EXPECT_EQ(FXBSTR_ID('a', 'b', 'c', 'd'), longer_string.GetID()); +} + +TEST(ByteStringView, Find) { + ByteStringView null_string; + EXPECT_FALSE(null_string.Find('a').has_value()); + EXPECT_FALSE(null_string.Find('\0').has_value()); + + ByteStringView empty_string(""); + EXPECT_FALSE(empty_string.Find('a').has_value()); + EXPECT_FALSE(empty_string.Find('\0').has_value()); + + Optional result; + ByteStringView single_string("a"); + result = single_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find('b').has_value()); + EXPECT_FALSE(single_string.Find('\0').has_value()); + + ByteStringView longer_string("abccc"); + result = longer_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find('c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + EXPECT_FALSE(longer_string.Find('d').has_value()); + EXPECT_FALSE(longer_string.Find('\0').has_value()); + + ByteStringView hibyte_string( + "ab\x8c" + "def"); + result = hibyte_string.Find('\x8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(ByteStringView, Mid) { + ByteStringView null_string; + EXPECT_EQ(null_string, null_string.Mid(0, 1)); + EXPECT_EQ(null_string, null_string.Mid(1, 1)); + + ByteStringView empty_string(""); + EXPECT_EQ("", empty_string.Mid(0, 1)); + EXPECT_EQ("", empty_string.Mid(1, 1)); + + ByteStringView single_character("a"); + EXPECT_EQ("", single_character.Mid(0, 0)); + EXPECT_EQ(single_character, single_character.Mid(0, 1)); + EXPECT_EQ("", single_character.Mid(1, 0)); + EXPECT_EQ("", single_character.Mid(1, 1)); + + ByteStringView longer_string("abcdef"); + EXPECT_EQ(longer_string, longer_string.Mid(0, 6)); + EXPECT_EQ("", longer_string.Mid(0, 187)); + + ByteStringView leading_substring("ab"); + EXPECT_EQ(leading_substring, longer_string.Mid(0, 2)); + + ByteStringView middle_substring("bcde"); + EXPECT_EQ(middle_substring, longer_string.Mid(1, 4)); + + ByteStringView trailing_substring("ef"); + EXPECT_EQ(trailing_substring, longer_string.Mid(4, 2)); + EXPECT_EQ("", longer_string.Mid(4, 3)); +} + +TEST(ByteStringView, TrimmedRight) { + ByteStringView fred("FRED"); + EXPECT_EQ("FRED", fred.TrimmedRight('E')); + EXPECT_EQ("FRE", fred.TrimmedRight('D')); + ByteStringView fredd("FREDD"); + EXPECT_EQ("FRE", fred.TrimmedRight('D')); +} + +TEST(ByteStringView, ElementAccess) { + // ByteStringView includes the NUL terminator for non-empty strings. + ByteStringView abc("abc"); + EXPECT_EQ('a', static_cast(abc[0])); + EXPECT_EQ('b', static_cast(abc[1])); + EXPECT_EQ('c', static_cast(abc[2])); +#ifndef NDEBUG + EXPECT_DEATH({ abc[3]; }, ".*"); +#endif +} + +TEST(ByteStringView, OperatorLT) { + ByteStringView empty; + ByteStringView a("a"); + ByteStringView abc("abc"); + ByteStringView def("def"); + const char* const c_null = nullptr; + const char* const c_empty = ""; + const char* const c_a = "a"; + const char* const c_abc = "abc"; + const char* const c_def = "def"; + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + EXPECT_FALSE(c_null < empty); + EXPECT_FALSE(c_empty < empty); + EXPECT_FALSE(c_a < a); + EXPECT_FALSE(c_abc < abc); + EXPECT_FALSE(c_def < def); + EXPECT_FALSE(empty < c_null); + EXPECT_FALSE(empty < c_empty); + EXPECT_FALSE(a < c_a); + EXPECT_FALSE(abc < c_abc); + EXPECT_FALSE(def < c_def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + EXPECT_TRUE(empty < c_a); + EXPECT_FALSE(a < c_null); + EXPECT_FALSE(a < c_empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + EXPECT_TRUE(empty < c_abc); + EXPECT_FALSE(abc < c_null); + EXPECT_FALSE(abc < c_empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + EXPECT_TRUE(empty < c_def); + EXPECT_FALSE(def < c_null); + EXPECT_FALSE(def < c_empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + EXPECT_TRUE(a < c_abc); + EXPECT_FALSE(abc < c_a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + EXPECT_TRUE(a < c_def); + EXPECT_FALSE(def < c_a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); + EXPECT_TRUE(abc < c_def); + EXPECT_FALSE(def < c_abc); +} + +TEST(ByteStringView, OperatorEQ) { + ByteStringView byte_string_c("hello"); + EXPECT_TRUE(byte_string_c == byte_string_c); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_TRUE(byte_string_c == byte_string_c_same1); + EXPECT_TRUE(byte_string_c_same1 == byte_string_c); + + ByteStringView byte_string_c_same2(byte_string_c); + EXPECT_TRUE(byte_string_c == byte_string_c_same2); + EXPECT_TRUE(byte_string_c_same2 == byte_string_c); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_FALSE(byte_string_c == byte_string_c1); + EXPECT_FALSE(byte_string_c == byte_string_c2); + EXPECT_FALSE(byte_string_c == byte_string_c3); + EXPECT_FALSE(byte_string_c1 == byte_string_c); + EXPECT_FALSE(byte_string_c2 == byte_string_c); + EXPECT_FALSE(byte_string_c3 == byte_string_c); + + ByteString byte_string_same1("hello"); + EXPECT_TRUE(byte_string_c == byte_string_same1); + EXPECT_TRUE(byte_string_same1 == byte_string_c); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_FALSE(byte_string_c == byte_string1); + EXPECT_FALSE(byte_string_c == byte_string2); + EXPECT_FALSE(byte_string_c == byte_string3); + EXPECT_FALSE(byte_string1 == byte_string_c); + EXPECT_FALSE(byte_string2 == byte_string_c); + EXPECT_FALSE(byte_string3 == byte_string_c); + + const char* const c_string_same1 = "hello"; + EXPECT_TRUE(byte_string_c == c_string_same1); + EXPECT_TRUE(c_string_same1 == byte_string_c); + + const char* const c_string1 = "he"; + const char* const c_string2 = "hellp"; + const char* const c_string3 = "hellod"; + EXPECT_FALSE(byte_string_c == c_string1); + EXPECT_FALSE(byte_string_c == c_string2); + EXPECT_FALSE(byte_string_c == c_string3); + + EXPECT_FALSE(c_string1 == byte_string_c); + EXPECT_FALSE(c_string2 == byte_string_c); + EXPECT_FALSE(c_string3 == byte_string_c); +} + +TEST(ByteStringView, OperatorNE) { + ByteStringView byte_string_c("hello"); + EXPECT_FALSE(byte_string_c != byte_string_c); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_FALSE(byte_string_c != byte_string_c_same1); + EXPECT_FALSE(byte_string_c_same1 != byte_string_c); + + ByteStringView byte_string_c_same2(byte_string_c); + EXPECT_FALSE(byte_string_c != byte_string_c_same2); + EXPECT_FALSE(byte_string_c_same2 != byte_string_c); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_TRUE(byte_string_c != byte_string_c1); + EXPECT_TRUE(byte_string_c != byte_string_c2); + EXPECT_TRUE(byte_string_c != byte_string_c3); + EXPECT_TRUE(byte_string_c1 != byte_string_c); + EXPECT_TRUE(byte_string_c2 != byte_string_c); + EXPECT_TRUE(byte_string_c3 != byte_string_c); + + ByteString byte_string_same1("hello"); + EXPECT_FALSE(byte_string_c != byte_string_same1); + EXPECT_FALSE(byte_string_same1 != byte_string_c); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_TRUE(byte_string_c != byte_string1); + EXPECT_TRUE(byte_string_c != byte_string2); + EXPECT_TRUE(byte_string_c != byte_string3); + EXPECT_TRUE(byte_string1 != byte_string_c); + EXPECT_TRUE(byte_string2 != byte_string_c); + EXPECT_TRUE(byte_string3 != byte_string_c); + + const char* const c_string_same1 = "hello"; + EXPECT_FALSE(byte_string_c != c_string_same1); + EXPECT_FALSE(c_string_same1 != byte_string_c); + + const char* const c_string1 = "he"; + const char* const c_string2 = "hellp"; + const char* const c_string3 = "hellod"; + EXPECT_TRUE(byte_string_c != c_string1); + EXPECT_TRUE(byte_string_c != c_string2); + EXPECT_TRUE(byte_string_c != c_string3); + + EXPECT_TRUE(c_string1 != byte_string_c); + EXPECT_TRUE(c_string2 != byte_string_c); + EXPECT_TRUE(c_string3 != byte_string_c); +} + +TEST(ByteStringView, NullIterator) { + ByteStringView null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteStringView, EmptyIterator) { + ByteStringView empty_str(""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteStringView, OneCharIterator) { + ByteStringView one_str("a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a', sum); +} + +TEST(ByteStringView, MultiCharIterator) { + ByteStringView one_str("abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a' + 'b' + 'c', sum); +} + +TEST(ByteStringView, EmptyReverseIterator) { + ByteStringView empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(ByteStringView, OneCharReverseIterator) { + ByteStringView one_str("a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(ByteStringView, MultiCharReverseIterator) { + ByteStringView multi_str("abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(ByteStringView, AnyAllNoneOf) { + ByteStringView str("aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); +} + +TEST(ByteString, FormatWidth) { + EXPECT_EQ(" 1", ByteString::Format("%5d", 1)); + EXPECT_EQ("1", ByteString::Format("%d", 1)); + EXPECT_EQ(" 1", ByteString::Format("%*d", 5, 1)); + EXPECT_EQ("1", ByteString::Format("%-1d", 1)); + EXPECT_EQ("1", ByteString::Format("%0d", 1)); +} + +TEST(ByteString, FormatPrecision) { + EXPECT_EQ("1.12", ByteString::Format("%.2f", 1.12345)); + EXPECT_EQ("1.123", ByteString::Format("%.*f", 3, 1.12345)); + EXPECT_EQ("1.123450", ByteString::Format("%f", 1.12345)); + EXPECT_EQ("1.123450", ByteString::Format("%-1f", 1.12345)); + EXPECT_EQ("1.123450", ByteString::Format("%0f", 1.12345)); +} + +TEST(ByteString, Empty) { + ByteString empty_str; + EXPECT_TRUE(empty_str.IsEmpty()); + EXPECT_EQ(0u, empty_str.GetLength()); + const char* cstr = empty_str.c_str(); + EXPECT_EQ(0u, strlen(cstr)); +} + +TEST(ByteString, InitializerList) { + ByteString many_str({"clams", " and ", "oysters"}); + EXPECT_EQ("clams and oysters", many_str); + many_str = {"fish", " and ", "chips", " and ", "soda"}; + EXPECT_EQ("fish and chips and soda", many_str); +} + +TEST(ByteString, NullIterator) { + ByteString null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteString, EmptyIterator) { + ByteString empty_str(""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteString, OneCharIterator) { + ByteString one_str("a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a', sum); +} + +TEST(ByteString, MultiCharIterator) { + ByteString one_str("abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a' + 'b' + 'c', sum); +} + +TEST(ByteString, AnyAllNoneOf) { + ByteString str("aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); +} + +TEST(CFX_BytrString, EqualNoCase) { + ByteString str("aaa"); + EXPECT_TRUE(str.EqualNoCase("aaa")); + EXPECT_TRUE(str.EqualNoCase("AAA")); + EXPECT_TRUE(str.EqualNoCase("aaA")); + EXPECT_TRUE(str.EqualNoCase("Aaa")); + EXPECT_FALSE(str.EqualNoCase("aab")); + EXPECT_FALSE(str.EqualNoCase("aaaa")); + EXPECT_FALSE(str.EqualNoCase("BBBB")); + EXPECT_FALSE(str.EqualNoCase("a")); + EXPECT_FALSE(str.EqualNoCase("")); +} + +TEST(ByteString, OStreamOverload) { + std::ostringstream stream; + + // Basic case, empty string + ByteString str; + stream << str; + EXPECT_EQ("", stream.str()); + + // Basic case, non-empty string + str = "def"; + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Changing the ByteString does not change the stream it was written to. + str = "123"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Writing it again to the stream will use the latest value. + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abc123ghi", stream.str()); + + char stringWithNulls[]{'x', 'y', '\0', 'z'}; + + // Writing a ByteString with nulls and no specified length treats it as + // a C-style null-terminated string. + str = ByteString(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + + // Writing a ByteString with nulls but specifying its length treats it as + // a C++-style string. + str = ByteString(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + + // << operators can be chained. + ByteString str1("abc"); + ByteString str2("def"); + stream.str(""); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); +} + +TEST(ByteStringView, OStreamOverload) { + // Basic case, empty string + { + std::ostringstream stream; + ByteStringView str; + stream << str; + EXPECT_EQ("", stream.str()); + } + + // Basic case, non-empty string + { + std::ostringstream stream; + ByteStringView str("def"); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + } + + // Changing the ByteStringView does not change the stream it was written to. + { + std::ostringstream stream; + ByteStringView str("abc"); + stream << str; + str = "123"; + EXPECT_EQ("abc", stream.str()); + } + + // Writing it again to the stream will use the latest value. + { + std::ostringstream stream; + ByteStringView str("abc"); + stream << str; + stream.str(""); + str = "123"; + stream << str; + EXPECT_EQ("123", stream.str()); + } + + // Writing a ByteStringView with nulls and no specified length treats it as + // a C-style null-terminated string. + { + std::ostringstream stream; + char stringWithNulls[]{'x', 'y', '\0', 'z'}; + ByteStringView str(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + str = ""; + } + + // Writing a ByteStringView with nulls but specifying its length treats it as + // a C++-style string. + { + std::ostringstream stream; + char stringWithNulls[]{'x', 'y', '\0', 'z'}; + ByteStringView str(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + str = ""; + } + + // << operators can be chained. + { + std::ostringstream stream; + ByteStringView str1("abc"); + ByteStringView str2("def"); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); + } +} + +TEST(ByteString, FormatInteger) { + // Base case of 0. + EXPECT_EQ("0", ByteString::FormatInteger(0)); + + // Positive ordinary number. + EXPECT_EQ("123456", ByteString::FormatInteger(123456)); + + // Negative ordinary number. + EXPECT_EQ("-123456", ByteString::FormatInteger(-123456)); + + // int limits. + EXPECT_EQ("2147483647", ByteString::FormatInteger(INT_MAX)); + EXPECT_EQ("-2147483648", ByteString::FormatInteger(INT_MIN)); +} + +} // namespace fxcrt diff --git a/core/fxcrt/cfx_binarybuf.cpp b/core/fxcrt/cfx_binarybuf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1243593a77284aa27e511a070b5a181df15a109e --- /dev/null +++ b/core/fxcrt/cfx_binarybuf.cpp @@ -0,0 +1,74 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_binarybuf.h" + +#include +#include + +CFX_BinaryBuf::CFX_BinaryBuf() + : m_AllocStep(0), m_AllocSize(0), m_DataSize(0) {} + +CFX_BinaryBuf::~CFX_BinaryBuf() {} + +void CFX_BinaryBuf::Delete(size_t start_index, size_t count) { + if (!m_pBuffer || count > m_DataSize || start_index > m_DataSize - count) + return; + + memmove(m_pBuffer.get() + start_index, m_pBuffer.get() + start_index + count, + m_DataSize - start_index - count); + m_DataSize -= count; +} + +size_t CFX_BinaryBuf::GetLength() const { + return m_DataSize; +} + +void CFX_BinaryBuf::Clear() { + m_DataSize = 0; +} + +std::unique_ptr CFX_BinaryBuf::DetachBuffer() { + m_DataSize = 0; + m_AllocSize = 0; + return std::move(m_pBuffer); +} + +void CFX_BinaryBuf::EstimateSize(size_t size, size_t step) { + m_AllocStep = step; + if (m_AllocSize < size) + ExpandBuf(size - m_DataSize); +} + +void CFX_BinaryBuf::ExpandBuf(size_t add_size) { + FX_SAFE_SIZE_T new_size = m_DataSize; + new_size += add_size; + if (m_AllocSize >= new_size.ValueOrDie()) + return; + + size_t alloc_step = std::max(static_cast(128), + m_AllocStep ? m_AllocStep : m_AllocSize / 4); + new_size += alloc_step - 1; // Quantize, don't combine these lines. + new_size /= alloc_step; + new_size *= alloc_step; + m_AllocSize = new_size.ValueOrDie(); + m_pBuffer.reset(m_pBuffer + ? FX_Realloc(uint8_t, m_pBuffer.release(), m_AllocSize) + : FX_Alloc(uint8_t, m_AllocSize)); +} + +void CFX_BinaryBuf::AppendBlock(const void* pBuf, size_t size) { + if (size == 0) + return; + + ExpandBuf(size); + if (pBuf) { + memcpy(m_pBuffer.get() + m_DataSize, pBuf, size); + } else { + memset(m_pBuffer.get() + m_DataSize, 0, size); + } + m_DataSize += size; +} diff --git a/core/fxcrt/cfx_binarybuf.h b/core/fxcrt/cfx_binarybuf.h new file mode 100644 index 0000000000000000000000000000000000000000..2d4f0195601d0e26c5eadc71616e220acffde7a1 --- /dev/null +++ b/core/fxcrt/cfx_binarybuf.h @@ -0,0 +1,52 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_BINARYBUF_H_ +#define CORE_FXCRT_CFX_BINARYBUF_H_ + +#include + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" + +class CFX_BinaryBuf { + public: + CFX_BinaryBuf(); + virtual ~CFX_BinaryBuf(); + + uint8_t* GetBuffer() const { return m_pBuffer.get(); } + size_t GetSize() const { return m_DataSize; } + virtual size_t GetLength() const; + bool IsEmpty() const { return GetLength() == 0; } + + void Clear(); + void EstimateSize(size_t size, size_t alloc_step = 0); + void AppendBlock(const void* pBuf, size_t size); + void AppendString(const ByteString& str) { + AppendBlock(str.c_str(), str.GetLength()); + } + + void AppendByte(uint8_t byte) { + ExpandBuf(1); + m_pBuffer.get()[m_DataSize++] = byte; + } + + void Delete(size_t start_index, size_t count); + + // Releases ownership of |m_pBuffer| and returns it. + std::unique_ptr DetachBuffer(); + + protected: + void ExpandBuf(size_t size); + + size_t m_AllocStep; + size_t m_AllocSize; + size_t m_DataSize; + std::unique_ptr m_pBuffer; +}; + +#endif // CORE_FXCRT_CFX_BINARYBUF_H_ diff --git a/core/fxcrt/cfx_bitstream.cpp b/core/fxcrt/cfx_bitstream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cf6d36adf6058682e294694825c372fd1e476da --- /dev/null +++ b/core/fxcrt/cfx_bitstream.cpp @@ -0,0 +1,57 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_bitstream.h" + +#include + +#include "core/fxcrt/fx_system.h" + +CFX_BitStream::CFX_BitStream(const uint8_t* pData, uint32_t dwSize) + : m_BitPos(0), m_BitSize(dwSize * 8), m_pData(pData) { + ASSERT(dwSize <= std::numeric_limits::max() / 8); +} + +CFX_BitStream::~CFX_BitStream() {} + +void CFX_BitStream::ByteAlign() { + m_BitPos = (m_BitPos + 7) & ~7; +} + +uint32_t CFX_BitStream::GetBits(uint32_t nBits) { + if (nBits > m_BitSize || m_BitPos + nBits > m_BitSize) + return 0; + + const uint8_t* data = m_pData.Get(); + + if (nBits == 1) { + int bit = (data[m_BitPos / 8] & (1 << (7 - m_BitPos % 8))) ? 1 : 0; + m_BitPos++; + return bit; + } + + uint32_t byte_pos = m_BitPos / 8; + uint32_t bit_pos = m_BitPos % 8; + uint32_t bit_left = nBits; + uint32_t result = 0; + if (bit_pos) { + if (8 - bit_pos >= bit_left) { + result = (data[byte_pos] & (0xff >> bit_pos)) >> (8 - bit_pos - bit_left); + m_BitPos += bit_left; + return result; + } + bit_left -= 8 - bit_pos; + result = (data[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left; + } + while (bit_left >= 8) { + bit_left -= 8; + result |= data[byte_pos++] << bit_left; + } + if (bit_left) + result |= data[byte_pos] >> (8 - bit_left); + m_BitPos += nBits; + return result; +} diff --git a/core/fxcrt/cfx_bitstream.h b/core/fxcrt/cfx_bitstream.h new file mode 100644 index 0000000000000000000000000000000000000000..168760ddd83ad843276ec49e7e1c099ea5a3af22 --- /dev/null +++ b/core/fxcrt/cfx_bitstream.h @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_BITSTREAM_H_ +#define CORE_FXCRT_CFX_BITSTREAM_H_ + +#include + +#include "core/fxcrt/unowned_ptr.h" + +class CFX_BitStream { + public: + CFX_BitStream(const uint8_t* pData, uint32_t dwSize); + ~CFX_BitStream(); + + void ByteAlign(); + + bool IsEOF() const { return m_BitPos >= m_BitSize; } + uint32_t GetPos() const { return m_BitPos; } + uint32_t GetBits(uint32_t nBits); + + void SkipBits(uint32_t nBits) { m_BitPos += nBits; } + void Rewind() { m_BitPos = 0; } + + uint32_t BitsRemaining() const { + return m_BitSize >= m_BitPos ? m_BitSize - m_BitPos : 0; + } + + private: + uint32_t m_BitPos; + uint32_t m_BitSize; + UnownedPtr m_pData; +}; + +#endif // CORE_FXCRT_CFX_BITSTREAM_H_ diff --git a/core/fxcrt/cfx_blockbuffer.cpp b/core/fxcrt/cfx_blockbuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13134f0e7b19f7e132fa82c633f0b4ecc977f187 --- /dev/null +++ b/core/fxcrt/cfx_blockbuffer.cpp @@ -0,0 +1,121 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_blockbuffer.h" + +#include +#include + +namespace { + +const size_t kAllocStep = 1024 * 1024; + +} // namespace + +CFX_BlockBuffer::CFX_BlockBuffer() + : m_DataLength(0), m_BufferSize(0), m_StartPosition(0) {} + +CFX_BlockBuffer::~CFX_BlockBuffer() {} + +size_t CFX_BlockBuffer::GetAllocStep() const { + return kAllocStep; +} + +std::pair CFX_BlockBuffer::GetAvailableBlock() { + if (m_BlockArray.empty()) + return {nullptr, 0}; + + size_t realIndex = m_StartPosition + m_DataLength; + if (realIndex == m_BufferSize) { + m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep)); + m_BufferSize += kAllocStep; + return {m_BlockArray.back().get(), 0}; + } + return {m_BlockArray[realIndex / kAllocStep].get(), realIndex % kAllocStep}; +} + +bool CFX_BlockBuffer::InitBuffer() { + m_BlockArray.clear(); + m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep)); + m_BufferSize = kAllocStep; + return true; +} + +void CFX_BlockBuffer::SetTextChar(size_t index, wchar_t ch) { + size_t realIndex = m_StartPosition + index; + size_t blockIndex = realIndex / kAllocStep; + if (blockIndex >= m_BlockArray.size()) { + size_t newBlocks = blockIndex - m_BlockArray.size() + 1; + do { + m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep)); + m_BufferSize += kAllocStep; + } while (--newBlocks); + } + wchar_t* pTextData = m_BlockArray[blockIndex].get(); + pTextData[realIndex % kAllocStep] = ch; + m_DataLength = std::max(m_DataLength, index + 1); +} + +void CFX_BlockBuffer::DeleteTextChars(size_t count) { + if (count == 0) + return; + + if (count >= m_DataLength) { + Reset(false); + return; + } + m_DataLength -= count; +} + +WideString CFX_BlockBuffer::GetTextData(size_t start, size_t length) const { + if (m_BufferSize <= m_StartPosition + 1 || length == 0) + return WideString(); + + size_t maybeDataLength = m_BufferSize - 1 - m_StartPosition; + if (start > maybeDataLength) + return WideString(); + length = std::min(length, maybeDataLength); + + WideString wsTextData; + wchar_t* pBuf = wsTextData.GetBuffer(length); + if (!pBuf) + return WideString(); + + size_t startBlock = 0; + size_t startInner = 0; + std::tie(startBlock, startInner) = TextDataIndex2BufIndex(start); + + size_t endBlock = 0; + size_t endInner = 0; + std::tie(endBlock, endInner) = TextDataIndex2BufIndex(start + length); + + size_t pointer = 0; + for (size_t i = startBlock; i <= endBlock; ++i) { + size_t bufferPointer = 0; + size_t copyLength = kAllocStep; + if (i == startBlock) { + copyLength -= startInner; + bufferPointer = startInner; + } + if (i == endBlock) + copyLength -= ((kAllocStep - 1) - endInner); + + wchar_t* pBlockBuf = m_BlockArray[i].get(); + memcpy(pBuf + pointer, pBlockBuf + bufferPointer, + copyLength * sizeof(wchar_t)); + pointer += copyLength; + } + wsTextData.ReleaseBuffer(length); + return wsTextData; +} + +std::pair CFX_BlockBuffer::TextDataIndex2BufIndex( + const size_t iIndex) const { + ASSERT(iIndex >= 0); + + size_t realIndex = m_StartPosition + iIndex; + return {realIndex / kAllocStep, realIndex % kAllocStep}; +} diff --git a/core/fxcrt/cfx_blockbuffer.h b/core/fxcrt/cfx_blockbuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..423aa6820b7bf99f42d46c15a074fef7a2db6a0c --- /dev/null +++ b/core/fxcrt/cfx_blockbuffer.h @@ -0,0 +1,51 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_BLOCKBUFFER_H_ +#define CORE_FXCRT_CFX_BLOCKBUFFER_H_ + +#include + +#include +#include +#include + +#include "core/fxcrt/fx_string.h" + +class CFX_BlockBuffer { + public: + CFX_BlockBuffer(); + ~CFX_BlockBuffer(); + + bool InitBuffer(); + bool IsInitialized() { return m_BufferSize / GetAllocStep() >= 1; } + + std::pair GetAvailableBlock(); + size_t GetAllocStep() const; + size_t GetDataLength() const { return m_DataLength; } + void IncrementDataLength() { m_DataLength++; } + bool IsEmpty() const { return m_DataLength == 0; } + + void Reset(bool bReserveData) { + if (!bReserveData) + m_StartPosition = 0; + m_DataLength = 0; + } + + void SetTextChar(size_t iIndex, wchar_t ch); + void DeleteTextChars(size_t iCount); + WideString GetTextData(size_t iStart, size_t iLength) const; + + private: + std::pair TextDataIndex2BufIndex(const size_t iIndex) const; + + std::vector> m_BlockArray; + size_t m_DataLength; + size_t m_BufferSize; + size_t m_StartPosition; +}; + +#endif // CORE_FXCRT_CFX_BLOCKBUFFER_H_ diff --git a/core/fxcrt/cfx_char.cpp b/core/fxcrt/cfx_char.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc04b0fd723b8b7a56c8523a1eb356e371916b7f --- /dev/null +++ b/core/fxcrt/cfx_char.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_char.h" + +CFX_Char::CFX_Char(uint16_t wCharCode, uint32_t dwCharProps) + : CFX_Char(wCharCode, dwCharProps, 100, 100) {} + +CFX_Char::CFX_Char(uint16_t wCharCode, + uint32_t dwCharProps, + int32_t iHorizontalScale, + int32_t iVerticalScale) + : m_dwStatus(CFX_BreakType::None), + m_nBreakType(0), + m_dwCharStyles(0), + m_iCharWidth(0), + m_iBidiClass(0), + m_iBidiLevel(0), + m_iBidiPos(0), + m_iBidiOrder(0), + m_iFontSize(0), + m_dwIdentity(0), + m_wCharCode(wCharCode), + m_dwCharProps(dwCharProps), + m_iHorizontalScale(iHorizontalScale), + m_iVerticalScale(iVerticalScale) {} + +CFX_Char::CFX_Char(const CFX_Char& other) = default; + +CFX_Char::~CFX_Char() = default; + +FX_CHARTYPE CFX_Char::GetCharType() const { + return GetCharTypeFromProp(m_dwCharProps); +} diff --git a/core/fxcrt/cfx_char.h b/core/fxcrt/cfx_char.h new file mode 100644 index 0000000000000000000000000000000000000000..fb625ee038f9c141d278c5db86eee506ffd6e6be --- /dev/null +++ b/core/fxcrt/cfx_char.h @@ -0,0 +1,52 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_CHAR_H_ +#define CORE_FXCRT_CFX_CHAR_H_ + +#include + +#include "core/fxcrt/fx_unicode.h" + +enum class CFX_BreakType { None = 0, Piece, Line, Paragraph, Page }; + +class CFX_Char { + public: + CFX_Char(uint16_t wCharCode, uint32_t dwCharProps); + CFX_Char(uint16_t wCharCode, + uint32_t dwCharProps, + int32_t iHorizontalScale, + int32_t iVerticalScale); + CFX_Char(const CFX_Char& other); + ~CFX_Char(); + + FX_CHARTYPE GetCharType() const; + + uint16_t char_code() const { return m_wCharCode; } + uint32_t char_props() const { return m_dwCharProps; } + int16_t horizonal_scale() const { return m_iHorizontalScale; } + int16_t vertical_scale() const { return m_iVerticalScale; } + + CFX_BreakType m_dwStatus; + uint8_t m_nBreakType; + uint32_t m_dwCharStyles; + int32_t m_iCharWidth; + int16_t m_iBidiClass; + int16_t m_iBidiLevel; + int16_t m_iBidiPos; + int16_t m_iBidiOrder; + int32_t m_iFontSize; + uint32_t m_dwIdentity; + RetainPtr m_pUserData; + + private: + uint16_t m_wCharCode; + uint32_t m_dwCharProps; + int32_t m_iHorizontalScale; + int32_t m_iVerticalScale; +}; + +#endif // CORE_FXCRT_CFX_CHAR_H_ diff --git a/core/fxcrt/cfx_checksumcontext.cpp b/core/fxcrt/cfx_checksumcontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d3409dceb2ec21bae88e1d3ca3c06251f468e93 --- /dev/null +++ b/core/fxcrt/cfx_checksumcontext.cpp @@ -0,0 +1,152 @@ +// 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 "core/fxcrt/cfx_checksumcontext.h" + +#include "core/fdrm/crypto/fx_crypt.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/xml/cfx_saxreaderhandler.h" +#include "third_party/base/ptr_util.h" + +namespace { + +struct FX_BASE64DATA { + uint32_t data1 : 2; + uint32_t data2 : 6; + uint32_t data3 : 4; + uint32_t data4 : 4; + uint32_t data5 : 6; + uint32_t data6 : 2; + uint32_t data7 : 8; +}; + +const 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', '+', '/', +}; + +void Base64EncodePiece(const FX_BASE64DATA& src, int32_t iBytes, char dst[4]) { + dst[0] = g_FXBase64EncoderMap[src.data2]; + uint32_t 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] = '='; + } +} + +int32_t Base64EncodeA(const uint8_t* pSrc, int32_t iSrcLen, char* pDst) { + ASSERT(pSrc); + if (iSrcLen < 1) { + return 0; + } + if (!pDst) { + int32_t iDstLen = iSrcLen / 3 * 4; + if ((iSrcLen % 3) != 0) { + iDstLen += 4; + } + return iDstLen; + } + FX_BASE64DATA srcData; + int32_t iBytes = 3; + char* pDstEnd = pDst; + while (iSrcLen > 0) { + if (iSrcLen > 2) { + ((uint8_t*)&srcData)[0] = *pSrc++; + ((uint8_t*)&srcData)[1] = *pSrc++; + ((uint8_t*)&srcData)[2] = *pSrc++; + iSrcLen -= 3; + } else { + *((uint32_t*)&srcData) = 0; + ((uint8_t*)&srcData)[0] = *pSrc++; + if (iSrcLen > 1) { + ((uint8_t*)&srcData)[1] = *pSrc++; + } + iBytes = iSrcLen; + iSrcLen = 0; + } + Base64EncodePiece(srcData, iBytes, pDstEnd); + pDstEnd += 4; + } + return pDstEnd - pDst; +} + +} // namespace + +CFX_ChecksumContext::CFX_ChecksumContext() {} + +CFX_ChecksumContext::~CFX_ChecksumContext() {} + +void CFX_ChecksumContext::StartChecksum() { + FinishChecksum(); + m_pByteContext = pdfium::MakeUnique(); + CRYPT_SHA1Start(m_pByteContext.get()); + m_bsChecksum.clear(); + m_pSAXReader = pdfium::MakeUnique(); +} + +bool CFX_ChecksumContext::UpdateChecksum( + const RetainPtr& pSrcFile, + FX_FILESIZE offset, + size_t size) { + if (!m_pSAXReader || !pSrcFile) + return false; + + if (size < 1) + size = pSrcFile->GetSize(); + + CFX_SAXReaderHandler handler(this); + m_pSAXReader->SetHandler(&handler); + if (m_pSAXReader->StartParse( + pSrcFile, (uint32_t)offset, (uint32_t)size, + CFX_SaxParseMode_NotSkipSpace | CFX_SaxParseMode_NotConvert_amp | + CFX_SaxParseMode_NotConvert_lt | CFX_SaxParseMode_NotConvert_gt | + CFX_SaxParseMode_NotConvert_sharp) < 0) { + return false; + } + return m_pSAXReader->ContinueParse() > 99; +} + +void CFX_ChecksumContext::FinishChecksum() { + m_pSAXReader.reset(); + if (m_pByteContext) { + uint8_t digest[20]; + memset(digest, 0, 20); + CRYPT_SHA1Finish(m_pByteContext.get(), digest); + int32_t nLen = Base64EncodeA(digest, 20, nullptr); + char* pBuffer = m_bsChecksum.GetBuffer(nLen); + Base64EncodeA(digest, 20, pBuffer); + m_bsChecksum.ReleaseBuffer(nLen); + m_pByteContext.reset(); + } +} + +ByteString CFX_ChecksumContext::GetChecksum() const { + return m_bsChecksum; +} + +void CFX_ChecksumContext::Update(const ByteStringView& bsText) { + if (!m_pByteContext) + return; + + CRYPT_SHA1Update(m_pByteContext.get(), bsText.raw_str(), bsText.GetLength()); +} diff --git a/core/fxcrt/cfx_checksumcontext.h b/core/fxcrt/cfx_checksumcontext.h new file mode 100644 index 0000000000000000000000000000000000000000..6d7963ad935e95158237de3c241ed0721fe053fc --- /dev/null +++ b/core/fxcrt/cfx_checksumcontext.h @@ -0,0 +1,34 @@ +// 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 CORE_FXCRT_CFX_CHECKSUMCONTEXT_H_ +#define CORE_FXCRT_CFX_CHECKSUMCONTEXT_H_ + +#include + +#include "core/fdrm/crypto/fx_crypt.h" +#include "core/fxcrt/xml/cfx_saxreader.h" + +class CFX_ChecksumContext { + public: + CFX_ChecksumContext(); + ~CFX_ChecksumContext(); + + void StartChecksum(); + void Update(const ByteStringView& bsText); + bool UpdateChecksum(const RetainPtr& pSrcFile, + FX_FILESIZE offset = 0, + size_t size = 0); + void FinishChecksum(); + ByteString GetChecksum() const; + + private: + std::unique_ptr m_pSAXReader; + std::unique_ptr m_pByteContext; + ByteString m_bsChecksum; +}; + +#endif // CORE_FXCRT_CFX_CHECKSUMCONTEXT_H_ diff --git a/core/fxcrt/cfx_datetime.cpp b/core/fxcrt/cfx_datetime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04fa8a57ba579906870e497aee191f759474e12b --- /dev/null +++ b/core/fxcrt/cfx_datetime.cpp @@ -0,0 +1,133 @@ +// 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 "core/fxcrt/cfx_datetime.h" +#include "core/fxcrt/fx_system.h" + +#if _FX_OS_ == _FX_OS_LINUX_ || _FX_OS_ == _FX_OS_ANDROID_ || \ + _FX_OS_ == _FX_OS_MACOSX_ +#include +#include +#endif + +namespace { + +const uint8_t g_FXDaysPerMonth[12] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; +const uint8_t g_FXDaysPerLeapMonth[12] = {31, 29, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; +const int32_t g_FXDaysBeforeMonth[12] = {0, 31, 59, 90, 120, 151, + 181, 212, 243, 273, 304, 334}; +const int32_t g_FXDaysBeforeLeapMonth[12] = {0, 31, 60, 91, 121, 152, + 182, 213, 244, 274, 305, 335}; +const int32_t g_FXDaysPerYear = 365; +const int32_t g_FXDaysPerLeapYear = 366; + +int32_t DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) { + ASSERT(iYear != 0); + ASSERT(iMonth >= 1 && iMonth <= 12); + + const int32_t* p = + FX_IsLeapYear(iYear) ? g_FXDaysBeforeLeapMonth : g_FXDaysBeforeMonth; + return p[iMonth - 1]; +} + +int32_t DaysInYear(int32_t iYear) { + ASSERT(iYear != 0); + return FX_IsLeapYear(iYear) ? g_FXDaysPerLeapYear : g_FXDaysPerYear; +} + +int64_t DateToDays(int32_t iYear, + uint8_t iMonth, + uint8_t iDay, + bool bIncludeThisDay) { + ASSERT(iYear != 0); + ASSERT(iMonth >= 1 && iMonth <= 12); + ASSERT(iDay >= 1 && iDay <= FX_DaysInMonth(iYear, iMonth)); + + int64_t iDays = DaysBeforeMonthInYear(iYear, iMonth); + iDays += iDay; + if (!bIncludeThisDay) + iDays--; + + if (iYear > 0) { + iYear--; + } else { + iDays -= DaysInYear(iYear); + iYear++; + } + return iDays + static_cast(iYear) * 365 + iYear / 4 - iYear / 100 + + iYear / 400; +} + +struct FXUT_SYSTEMTIME { + uint16_t wYear; + uint16_t wMonth; + uint16_t wDayOfWeek; + uint16_t wDay; + uint16_t wHour; + uint16_t wMinute; + uint16_t wSecond; + uint16_t wMillisecond; +}; + +} // namespace + +uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth) { + ASSERT(iYear != 0); + ASSERT(iMonth >= 1 && iMonth <= 12); + + const uint8_t* p = + FX_IsLeapYear(iYear) ? g_FXDaysPerLeapMonth : g_FXDaysPerMonth; + return p[iMonth - 1]; +} + +bool FX_IsLeapYear(int32_t iYear) { + ASSERT(iYear != 0); + return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0; +} + +// static +CFX_DateTime CFX_DateTime::Now() { + FXUT_SYSTEMTIME utLocal; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + ::GetLocalTime((LPSYSTEMTIME)&utLocal); +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + timeval curTime; + gettimeofday(&curTime, nullptr); + + 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.wMillisecond = curTime.tv_usec / 1000; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + + return CFX_DateTime(utLocal.wYear, static_cast(utLocal.wMonth), + static_cast(utLocal.wDay), + static_cast(utLocal.wHour), + static_cast(utLocal.wMinute), + static_cast(utLocal.wSecond), + static_cast(utLocal.wMillisecond)); +} + +int32_t CFX_DateTime::GetDayOfWeek() const { + int32_t v = static_cast(DateToDays(year_, month_, day_, true) % 7); + if (v < 0) + v += 7; + return v; +} + +bool CFX_DateTime::operator==(const CFX_DateTime& other) const { + return year_ == other.year_ && month_ == other.month_ && day_ == other.day_ && + hour_ == other.hour_ && minute_ == other.minute_ && + second_ == other.second_ && millisecond_ == other.millisecond_; +} diff --git a/core/fxcrt/cfx_datetime.h b/core/fxcrt/cfx_datetime.h new file mode 100644 index 0000000000000000000000000000000000000000..910a84750632d00d3cc62412ccba35c5ce144ccc --- /dev/null +++ b/core/fxcrt/cfx_datetime.h @@ -0,0 +1,105 @@ +// 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 CORE_FXCRT_CFX_DATETIME_H_ +#define CORE_FXCRT_CFX_DATETIME_H_ + +#include "core/fxcrt/fx_system.h" + +bool FX_IsLeapYear(int32_t iYear); +uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth); + +class CFX_DateTime { + public: + static CFX_DateTime Now(); + + CFX_DateTime() + : year_(0), + month_(0), + day_(0), + hour_(0), + minute_(0), + second_(0), + millisecond_(0) {} + CFX_DateTime(int32_t year, + uint8_t month, + uint8_t day, + uint8_t hour, + uint8_t minute, + uint8_t second, + uint16_t millisecond) + : year_(year), + month_(month), + day_(day), + hour_(hour), + minute_(minute), + second_(second), + millisecond_(millisecond) {} + + void Reset() { + year_ = 0; + month_ = 0; + day_ = 0; + hour_ = 0; + minute_ = 0; + second_ = 0; + millisecond_ = 0; + } + + bool IsSet() const { + return year_ != 0 || month_ != 0 || day_ != 0 || hour_ != 0 || + minute_ != 0 || second_ != 0 || millisecond_ != 0; + } + + void SetDate(int32_t year, uint8_t month, uint8_t day) { + year_ = year; + month_ = month; + day_ = day; + } + + void SetTime(uint8_t hour, + uint8_t minute, + uint8_t second, + uint16_t millisecond) { + hour_ = hour; + minute_ = minute; + second_ = second; + millisecond_ = millisecond; + } + + int32_t GetYear() const { return year_; } + uint8_t GetMonth() const { return month_; } + uint8_t GetDay() const { return day_; } + uint8_t GetHour() const { return hour_; } + uint8_t GetMinute() const { return minute_; } + uint8_t GetSecond() const { return second_; } + uint16_t GetMillisecond() const { return millisecond_; } + int32_t GetDayOfWeek() const; + + bool operator==(const CFX_DateTime& other) const; + + private: + int32_t year_; + uint8_t month_; + uint8_t day_; + uint8_t hour_; + uint8_t minute_; + uint8_t second_; + uint16_t millisecond_; +}; + +#if _FX_OS_ != _FX_OS_ANDROID_ +#pragma pack(push, 1) +#endif +struct FX_TIMEZONE { + int8_t tzHour; + uint8_t tzMinute; +}; +#if _FX_OS_ != _FX_OS_ANDROID_ +#pragma pack(pop) +#endif + +#endif // CORE_FXCRT_CFX_DATETIME_H_ diff --git a/core/fxcrt/cfx_decimal.cpp b/core/fxcrt/cfx_decimal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45980db6ee95709916b34dbf1acca286cbac8d03 --- /dev/null +++ b/core/fxcrt/cfx_decimal.cpp @@ -0,0 +1,473 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_decimal.h" + +#include +#include + +#include "core/fxcrt/fx_extension.h" + +#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) \ + ((uint8_t)(((FLAGS) & ~FXMATH_DECIMAL_NEGMASK) >> 0x10)) +#define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x) >> 0x10 >> 0x10) +#define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x) << 0x10 << 0x10) + +namespace { + +inline uint8_t decimal_helper_div10(uint64_t& phi, + uint64_t& pmid, + uint64_t& plo) { + uint8_t retVal; + pmid += FXMATH_DECIMAL_LSHIFT32BIT(phi % 0xA); + phi /= 0xA; + plo += FXMATH_DECIMAL_LSHIFT32BIT(pmid % 0xA); + pmid /= 0xA; + retVal = plo % 0xA; + plo /= 0xA; + return retVal; +} + +inline uint8_t decimal_helper_div10_any(uint64_t nums[], uint8_t numcount) { + uint8_t 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; +} + +inline void decimal_helper_mul10(uint64_t& phi, uint64_t& pmid, uint64_t& plo) { + plo *= 0xA; + pmid = pmid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(plo); + plo = (uint32_t)plo; + phi = phi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(pmid); + pmid = (uint32_t)pmid; +} + +inline void decimal_helper_mul10_any(uint64_t nums[], uint8_t 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] = (uint32_t)nums[i - 1]; + } +} + +inline void decimal_helper_normalize(uint64_t& phi, + uint64_t& pmid, + uint64_t& plo) { + phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid); + pmid = (uint32_t)pmid; + pmid += FXMATH_DECIMAL_RSHIFT32BIT(plo); + plo = (uint32_t)plo; + phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid); + pmid = (uint32_t)pmid; +} + +inline void decimal_helper_normalize_any(uint64_t nums[], uint8_t len) { + for (int i = len - 2; i > 0; i--) { + nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]); + nums[i] = (uint32_t)nums[i]; + } + for (int i = 0; i < len - 1; i++) { + nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]); + nums[i] = (uint32_t)nums[i]; + } +} + +inline int8_t decimal_helper_raw_compare_any(uint64_t a[], + uint8_t al, + uint64_t b[], + uint8_t bl) { + int8_t retVal = 0; + for (int i = std::max(al - 1, bl - 1); i >= 0; i--) { + uint64_t 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; +} + +inline void decimal_helper_dec_any(uint64_t a[], uint8_t al) { + for (int i = 0; i < al; i++) { + if (a[i]--) + return; + } +} + +inline void decimal_helper_inc_any(uint64_t a[], uint8_t al) { + for (int i = 0; i < al; i++) { + a[i]++; + if ((uint32_t)a[i] == a[i]) + return; + a[i] = 0; + } +} + +inline void decimal_helper_raw_mul(uint64_t a[], + uint8_t al, + uint64_t b[], + uint8_t bl, + uint64_t c[], + uint8_t 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++) { + uint64_t m = (uint64_t)a[i] * b[j]; + c[i + j] += (uint32_t)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] = (uint32_t)c[i]; + } + for (int i = 0; i < cl; i++) + c[i] = (uint32_t)c[i]; +} + +inline void decimal_helper_raw_div(uint64_t a[], + uint8_t al, + uint64_t b[], + uint8_t bl, + uint64_t c[], + uint8_t cl) { + for (int i = 0; i < cl; i++) + c[i] = 0; + + uint64_t left[16] = {0}; + uint64_t right[16] = {0}; + left[0] = 0; + for (int i = 0; i < al; i++) + right[i] = a[i]; + + uint64_t tmp[16]; + while (decimal_helper_raw_compare_any(left, al, right, al) <= 0) { + uint64_t cur[16]; + for (int i = 0; i < al; i++) + cur[i] = left[i] + right[i]; + + for (int i = al - 1; i >= 0; i--) { + if (i) + cur[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(cur[i] % 2); + cur[i] /= 2; + } + + decimal_helper_raw_mul(cur, al, b, bl, tmp, 16); + switch (decimal_helper_raw_compare_any(tmp, 16, a, al)) { + case -1: + for (int i = 0; i < 16; i++) + left[i] = cur[i]; + + left[0]++; + decimal_helper_normalize_any(left, al); + break; + case 1: + for (int i = 0; i < 16; i++) + right[i] = cur[i]; + decimal_helper_dec_any(right, al); + break; + case 0: + for (int i = 0; i < std::min(al, cl); i++) + c[i] = cur[i]; + return; + } + } + for (int i = 0; i < std::min(al, cl); i++) + c[i] = left[i]; +} + +inline bool decimal_helper_outofrange(uint64_t a[], uint8_t al, uint8_t goal) { + for (int i = goal; i < al; i++) { + if (a[i]) + return true; + } + return false; +} + +inline void decimal_helper_shrinkintorange(uint64_t a[], + uint8_t al, + uint8_t goal, + uint8_t& scale) { + bool bRoundUp = false; + while (scale != 0 && (scale > FXMATH_DECIMAL_SCALELIMIT || + decimal_helper_outofrange(a, al, goal))) { + bRoundUp = decimal_helper_div10_any(a, al) >= 5; + scale--; + } + if (bRoundUp) { + decimal_helper_normalize_any(a, goal); + decimal_helper_inc_any(a, goal); + } +} + +inline void decimal_helper_truncate(uint64_t& phi, + uint64_t& pmid, + uint64_t& plo, + uint8_t& scale, + uint8_t minscale = 0) { + while (scale > minscale) { + uint64_t thi = phi, tmid = pmid, tlo = plo; + if (decimal_helper_div10(thi, tmid, tlo) != 0) + break; + + phi = thi; + pmid = tmid; + plo = tlo; + scale--; + } +} + +} // namespace + +CFX_Decimal::CFX_Decimal() : m_uHi(0), m_uLo(0), m_uMid(0), m_uFlags(0) {} + +CFX_Decimal::CFX_Decimal(uint64_t val) + : m_uHi(0), + m_uLo(static_cast(val)), + m_uMid(static_cast(FXMATH_DECIMAL_RSHIFT32BIT(val))), + m_uFlags(0) {} + +CFX_Decimal::CFX_Decimal(uint32_t val) + : m_uHi(0), m_uLo(static_cast(val)), m_uMid(0), m_uFlags(0) {} + +CFX_Decimal::CFX_Decimal(uint32_t lo, + uint32_t mid, + uint32_t hi, + bool neg, + uint8_t scale) + : m_uHi(hi), + m_uLo(lo), + m_uMid(mid), + m_uFlags(FXMATH_DECIMAL_MAKEFLAGS( + neg && IsNotZero(), + (scale > FXMATH_DECIMAL_SCALELIMIT ? 0 : scale))) {} + +CFX_Decimal::CFX_Decimal(int32_t val) { + if (val >= 0) { + *this = CFX_Decimal(static_cast(val)); + } else { + *this = CFX_Decimal(static_cast(-val)); + SetNegate(); + } +} + +CFX_Decimal::CFX_Decimal(float val, uint8_t scale) { + float newval = fabs(val); + uint64_t phi; + uint64_t pmid; + uint64_t plo; + plo = static_cast(newval); + pmid = static_cast(newval / 1e32); + phi = static_cast(newval / 1e64); + newval = fmod(newval, 1.0f); + for (uint8_t iter = 0; iter < scale; iter++) { + decimal_helper_mul10(phi, pmid, plo); + newval *= 10; + plo += static_cast(newval); + newval = fmod(newval, 1.0f); + } + + plo += FXSYS_round(newval); + decimal_helper_normalize(phi, pmid, plo); + m_uHi = static_cast(phi); + m_uMid = static_cast(pmid); + m_uLo = static_cast(plo); + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale); +} + +CFX_Decimal::CFX_Decimal(const WideStringView& strObj) { + const wchar_t* str = strObj.unterminated_c_str(); + const wchar_t* strBound = str + strObj.GetLength(); + bool pointmet = false; + bool negmet = false; + uint8_t scale = 0; + m_uHi = 0; + m_uMid = 0; + m_uLo = 0; + while (str != strBound && *str == ' ') + str++; + if (str != strBound && *str == '-') { + negmet = 1; + str++; + } else if (str != strBound && *str == '+') { + str++; + } + + while (str != strBound && (std::iswdigit(*str) || *str == '.') && + scale < FXMATH_DECIMAL_SCALELIMIT) { + if (*str == '.') { + if (!pointmet) + pointmet = 1; + } else { + m_uHi = m_uHi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uMid * 0xA); + m_uMid = m_uMid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uLo * 0xA); + m_uLo = m_uLo * 0xA + (*str - '0'); + if (pointmet) + scale++; + } + str++; + } + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale); +} + +CFX_Decimal::operator WideString() const { + WideString retString; + WideString tmpbuf; + uint64_t phi = m_uHi; + uint64_t pmid = m_uMid; + uint64_t plo = m_uLo; + while (phi || pmid || plo) + tmpbuf += decimal_helper_div10(phi, pmid, plo) + '0'; + + uint8_t outputlen = (uint8_t)tmpbuf.GetLength(); + uint8_t scale = (uint8_t)FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); + while (scale >= outputlen) { + tmpbuf += '0'; + outputlen++; + } + if (FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero()) + retString += '-'; + + for (uint8_t 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 = static_cast(m_uHi) * pow * pow + + static_cast(m_uMid) * pow + static_cast(m_uLo); + int8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); + bool bNeg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags); + return (bNeg ? -1 : 1) * base * ::pow(10.0, -scale); +} + +void CFX_Decimal::SetScale(uint8_t newscale) { + uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); + if (newscale > oldscale) { + uint64_t phi = m_uHi; + uint64_t pmid = m_uMid; + uint64_t plo = m_uLo; + for (uint8_t iter = 0; iter < newscale - oldscale; iter++) + decimal_helper_mul10(phi, pmid, plo); + + m_uHi = static_cast(phi); + m_uMid = static_cast(pmid); + m_uLo = static_cast(plo); + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( + FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); + } else if (newscale < oldscale) { + uint64_t phi; + uint64_t pmid; + uint64_t plo; + phi = 0; + pmid = 0; + plo = 5; + for (uint8_t iter = 0; iter < oldscale - newscale - 1; iter++) + decimal_helper_mul10(phi, pmid, plo); + + phi += m_uHi; + pmid += m_uMid; + plo += m_uLo; + decimal_helper_normalize(phi, pmid, plo); + for (uint8_t iter = 0; iter < oldscale - newscale; iter++) + decimal_helper_div10(phi, pmid, plo); + + m_uHi = static_cast(phi); + m_uMid = static_cast(pmid); + m_uLo = static_cast(plo); + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( + FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); + } +} + +uint8_t CFX_Decimal::GetScale() { + return FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); +} + +void CFX_Decimal::SetNegate() { + if (IsNotZero()) + m_uFlags ^= FXMATH_DECIMAL_NEGMASK; +} + +void CFX_Decimal::Swap(CFX_Decimal& val) { + std::swap(m_uHi, val.m_uHi); + std::swap(m_uMid, val.m_uMid); + std::swap(m_uLo, val.m_uLo); + std::swap(m_uFlags, val.m_uFlags); +} + +CFX_Decimal CFX_Decimal::operator*(const CFX_Decimal& val) const { + uint64_t a[3] = {m_uLo, m_uMid, m_uHi}, + b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}; + uint64_t c[6]; + decimal_helper_raw_mul(a, 3, b, 3, c, 6); + bool neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ + FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags); + uint8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) + + FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags); + decimal_helper_shrinkintorange(c, 6, 3, scale); + return CFX_Decimal(static_cast(c[0]), static_cast(c[1]), + static_cast(c[2]), neg, scale); +} + +CFX_Decimal CFX_Decimal::operator/(const CFX_Decimal& val) const { + if (!val.IsNotZero()) + return CFX_Decimal(); + + bool neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ + FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags); + uint64_t a[7] = {m_uLo, m_uMid, m_uHi}, + b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0}; + uint8_t 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--) { + decimal_helper_mul10_any(a, 7); + } + } else { + scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) - + FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags); + } + + uint8_t minscale = scale; + if (!IsNotZero()) + return CFX_Decimal(0, 0, 0, 0, minscale); + + while (!a[6]) { + decimal_helper_mul10_any(a, 7); + scale++; + } + + decimal_helper_div10_any(a, 7); + scale--; + decimal_helper_raw_div(a, 6, b, 3, c, 7); + decimal_helper_shrinkintorange(c, 6, 3, scale); + decimal_helper_truncate(c[2], c[1], c[0], scale, minscale); + return CFX_Decimal(static_cast(c[0]), static_cast(c[1]), + static_cast(c[2]), neg, scale); +} diff --git a/core/fxcrt/cfx_decimal.h b/core/fxcrt/cfx_decimal.h new file mode 100644 index 0000000000000000000000000000000000000000..de6e3de5e5d4441b5c841fe3dd565431b7e4d370 --- /dev/null +++ b/core/fxcrt/cfx_decimal.h @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_DECIMAL_H_ +#define CORE_FXCRT_CFX_DECIMAL_H_ + +#include "core/fxcrt/fx_string.h" + +class CFX_Decimal { + public: + CFX_Decimal(); + explicit CFX_Decimal(uint32_t val); + explicit CFX_Decimal(uint64_t val); + explicit CFX_Decimal(int32_t val); + CFX_Decimal(float val, uint8_t scale); + explicit CFX_Decimal(const WideStringView& str); + + operator WideString() const; + operator double() const; + + CFX_Decimal operator*(const CFX_Decimal& val) const; + CFX_Decimal operator/(const CFX_Decimal& val) const; + + void SetScale(uint8_t newScale); + uint8_t GetScale(); + void SetNegate(); + + private: + CFX_Decimal(uint32_t hi, uint32_t mid, uint32_t lo, bool neg, uint8_t scale); + bool IsNotZero() const { return m_uHi || m_uMid || m_uLo; } + void Swap(CFX_Decimal& val); + + uint32_t m_uHi; + uint32_t m_uLo; + uint32_t m_uMid; + uint32_t m_uFlags; +}; + +#endif // CORE_FXCRT_CFX_DECIMAL_H_ diff --git a/core/fxcrt/cfx_fileaccess_posix.cpp b/core/fxcrt/cfx_fileaccess_posix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f85670c5933150e8fe6d9b370000b2d0d84c8ea --- /dev/null +++ b/core/fxcrt/cfx_fileaccess_posix.cpp @@ -0,0 +1,153 @@ +// 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 "core/fxcrt/cfx_fileaccess_posix.h" + +#include + +#include "third_party/base/ptr_util.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif // O_BINARY + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif // O_LARGEFILE + +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ || \ + _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \ + _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ + +namespace { + +void GetFileMode(uint32_t dwModes, int32_t& nFlags, int32_t& nMasks) { + nFlags = O_BINARY | O_LARGEFILE; + if (dwModes & FX_FILEMODE_ReadOnly) { + nFlags |= O_RDONLY; + nMasks = 0; + } else { + nFlags |= O_RDWR | O_CREAT; + if (dwModes & FX_FILEMODE_Truncate) { + nFlags |= O_TRUNC; + } + nMasks = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + } +} + +} // namespace + +// static +std::unique_ptr IFX_FileAccess::Create() { + return pdfium::MakeUnique(); +} + +CFX_FileAccess_Posix::CFX_FileAccess_Posix() : m_nFD(-1) {} + +CFX_FileAccess_Posix::~CFX_FileAccess_Posix() { + Close(); +} + +bool CFX_FileAccess_Posix::Open(const ByteStringView& fileName, + uint32_t dwMode) { + if (m_nFD > -1) + return false; + + int32_t nFlags; + int32_t nMasks; + GetFileMode(dwMode, nFlags, nMasks); + + // TODO(tsepez): check usage of c_str() below. + m_nFD = open(fileName.unterminated_c_str(), nFlags, nMasks); + return m_nFD > -1; +} + +bool CFX_FileAccess_Posix::Open(const WideStringView& fileName, + uint32_t dwMode) { + return Open(FX_UTF8Encode(fileName).AsStringView(), dwMode); +} + +void CFX_FileAccess_Posix::Close() { + if (m_nFD < 0) { + return; + } + close(m_nFD); + m_nFD = -1; +} +FX_FILESIZE CFX_FileAccess_Posix::GetSize() const { + if (m_nFD < 0) { + return 0; + } + struct stat s; + memset(&s, 0, sizeof(s)); + fstat(m_nFD, &s); + return s.st_size; +} +FX_FILESIZE CFX_FileAccess_Posix::GetPosition() const { + if (m_nFD < 0) { + return (FX_FILESIZE)-1; + } + return lseek(m_nFD, 0, SEEK_CUR); +} +FX_FILESIZE CFX_FileAccess_Posix::SetPosition(FX_FILESIZE pos) { + if (m_nFD < 0) { + return (FX_FILESIZE)-1; + } + return lseek(m_nFD, pos, SEEK_SET); +} +size_t CFX_FileAccess_Posix::Read(void* pBuffer, size_t szBuffer) { + if (m_nFD < 0) { + return 0; + } + return read(m_nFD, pBuffer, szBuffer); +} +size_t CFX_FileAccess_Posix::Write(const void* pBuffer, size_t szBuffer) { + if (m_nFD < 0) { + return 0; + } + return write(m_nFD, pBuffer, szBuffer); +} +size_t CFX_FileAccess_Posix::ReadPos(void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) { + if (m_nFD < 0) { + return 0; + } + if (pos >= GetSize()) { + return 0; + } + if (SetPosition(pos) == (FX_FILESIZE)-1) { + return 0; + } + return Read(pBuffer, szBuffer); +} +size_t CFX_FileAccess_Posix::WritePos(const void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) { + if (m_nFD < 0) { + return 0; + } + if (SetPosition(pos) == (FX_FILESIZE)-1) { + return 0; + } + return Write(pBuffer, szBuffer); +} + +bool CFX_FileAccess_Posix::Flush() { + if (m_nFD < 0) + return false; + + return fsync(m_nFD) > -1; +} + +bool CFX_FileAccess_Posix::Truncate(FX_FILESIZE szFile) { + if (m_nFD < 0) + return false; + + return !ftruncate(m_nFD, szFile); +} + +#endif diff --git a/core/fxcrt/cfx_fileaccess_posix.h b/core/fxcrt/cfx_fileaccess_posix.h new file mode 100644 index 0000000000000000000000000000000000000000..efa25ebb4cc071be39fc8217d4704152c4af3c61 --- /dev/null +++ b/core/fxcrt/cfx_fileaccess_posix.h @@ -0,0 +1,41 @@ +// 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 CORE_FXCRT_CFX_FILEACCESS_POSIX_H_ +#define CORE_FXCRT_CFX_FILEACCESS_POSIX_H_ + +#include "core/fxcrt/ifx_fileaccess.h" + +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ || \ + _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \ + _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ +class CFX_FileAccess_Posix : public IFX_FileAccess { + public: + CFX_FileAccess_Posix(); + ~CFX_FileAccess_Posix() override; + + // IFX_FileAccess: + bool Open(const ByteStringView& fileName, uint32_t dwMode) override; + bool Open(const WideStringView& fileName, uint32_t dwMode) override; + void Close() override; + FX_FILESIZE GetSize() const override; + FX_FILESIZE GetPosition() const override; + FX_FILESIZE SetPosition(FX_FILESIZE pos) override; + size_t Read(void* pBuffer, size_t szBuffer) override; + size_t Write(const void* pBuffer, size_t szBuffer) override; + size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) override; + size_t WritePos(const void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) override; + bool Flush() override; + bool Truncate(FX_FILESIZE szFile) override; + + protected: + int32_t m_nFD; +}; +#endif + +#endif // CORE_FXCRT_CFX_FILEACCESS_POSIX_H_ diff --git a/core/fxcrt/cfx_fileaccess_windows.cpp b/core/fxcrt/cfx_fileaccess_windows.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ac4496edb657362cc961f2a9b645ea48282ea85 --- /dev/null +++ b/core/fxcrt/cfx_fileaccess_windows.cpp @@ -0,0 +1,196 @@ +// 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 "core/fxcrt/cfx_fileaccess_windows.h" + +#include + +#include "core/fxcrt/fx_string.h" +#include "third_party/base/ptr_util.h" + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + +namespace { + +void GetFileMode(uint32_t dwMode, + uint32_t& dwAccess, + uint32_t& dwShare, + uint32_t& dwCreation) { + dwAccess = GENERIC_READ; + dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE; + if (!(dwMode & FX_FILEMODE_ReadOnly)) { + dwAccess |= GENERIC_WRITE; + dwCreation = (dwMode & FX_FILEMODE_Truncate) ? CREATE_ALWAYS : OPEN_ALWAYS; + } else { + dwCreation = OPEN_EXISTING; + } +} + +} // namespace + +// static +std::unique_ptr IFX_FileAccess::Create() { + return pdfium::MakeUnique(); +} + +#ifdef __cplusplus +extern "C" { +#endif +WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize); +WINBASEAPI BOOL WINAPI SetFilePointerEx(HANDLE hFile, + LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, + DWORD dwMoveMethod); +#ifdef __cplusplus +} +#endif + +CFX_FileAccess_Windows::CFX_FileAccess_Windows() : m_hFile(nullptr) {} + +CFX_FileAccess_Windows::~CFX_FileAccess_Windows() { + Close(); +} + +bool CFX_FileAccess_Windows::Open(const ByteStringView& fileName, + uint32_t dwMode) { + if (m_hFile) + return false; + + uint32_t dwAccess, dwShare, dwCreation; + GetFileMode(dwMode, dwAccess, dwShare, dwCreation); + m_hFile = ::CreateFileA(fileName.unterminated_c_str(), dwAccess, dwShare, + nullptr, dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr); + if (m_hFile == INVALID_HANDLE_VALUE) + m_hFile = nullptr; + + return !!m_hFile; +} + +bool CFX_FileAccess_Windows::Open(const WideStringView& fileName, + uint32_t dwMode) { + if (m_hFile) + return false; + + uint32_t dwAccess, dwShare, dwCreation; + GetFileMode(dwMode, dwAccess, dwShare, dwCreation); + m_hFile = + ::CreateFileW((LPCWSTR)fileName.unterminated_c_str(), dwAccess, dwShare, + nullptr, dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr); + if (m_hFile == INVALID_HANDLE_VALUE) + m_hFile = nullptr; + + return !!m_hFile; +} + +void CFX_FileAccess_Windows::Close() { + if (!m_hFile) + return; + + ::CloseHandle(m_hFile); + m_hFile = nullptr; +} + +FX_FILESIZE CFX_FileAccess_Windows::GetSize() const { + if (!m_hFile) + return 0; + + LARGE_INTEGER size = {}; + if (!::GetFileSizeEx(m_hFile, &size)) + return 0; + + return (FX_FILESIZE)size.QuadPart; +} + +FX_FILESIZE CFX_FileAccess_Windows::GetPosition() const { + if (!m_hFile) + return (FX_FILESIZE)-1; + + LARGE_INTEGER dist = {}; + LARGE_INTEGER newPos = {}; + if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_CURRENT)) + return (FX_FILESIZE)-1; + + return (FX_FILESIZE)newPos.QuadPart; +} + +FX_FILESIZE CFX_FileAccess_Windows::SetPosition(FX_FILESIZE pos) { + if (!m_hFile) + return (FX_FILESIZE)-1; + + LARGE_INTEGER dist; + dist.QuadPart = pos; + LARGE_INTEGER newPos = {}; + if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_BEGIN)) + return (FX_FILESIZE)-1; + + return (FX_FILESIZE)newPos.QuadPart; +} + +size_t CFX_FileAccess_Windows::Read(void* pBuffer, size_t szBuffer) { + if (!m_hFile) + return 0; + + size_t szRead = 0; + if (!::ReadFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szRead, + nullptr)) { + return 0; + } + return szRead; +} + +size_t CFX_FileAccess_Windows::Write(const void* pBuffer, size_t szBuffer) { + if (!m_hFile) + return 0; + + size_t szWrite = 0; + if (!::WriteFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szWrite, + nullptr)) { + return 0; + } + return szWrite; +} + +size_t CFX_FileAccess_Windows::ReadPos(void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) { + if (!m_hFile) + return 0; + + if (pos >= GetSize()) + return 0; + + if (SetPosition(pos) == (FX_FILESIZE)-1) + return 0; + + return Read(pBuffer, szBuffer); +} + +size_t CFX_FileAccess_Windows::WritePos(const void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) { + if (!m_hFile) { + return 0; + } + if (SetPosition(pos) == (FX_FILESIZE)-1) { + return 0; + } + return Write(pBuffer, szBuffer); +} + +bool CFX_FileAccess_Windows::Flush() { + if (!m_hFile) + return false; + + return !!::FlushFileBuffers(m_hFile); +} + +bool CFX_FileAccess_Windows::Truncate(FX_FILESIZE szFile) { + if (SetPosition(szFile) == (FX_FILESIZE)-1) + return false; + + return !!::SetEndOfFile(m_hFile); +} +#endif diff --git a/core/fxcrt/cfx_fileaccess_windows.h b/core/fxcrt/cfx_fileaccess_windows.h new file mode 100644 index 0000000000000000000000000000000000000000..6fd07d553c57283ea556110590595993fa00aaf4 --- /dev/null +++ b/core/fxcrt/cfx_fileaccess_windows.h @@ -0,0 +1,39 @@ +// 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 CORE_FXCRT_CFX_FILEACCESS_WINDOWS_H_ +#define CORE_FXCRT_CFX_FILEACCESS_WINDOWS_H_ + +#include "core/fxcrt/ifx_fileaccess.h" + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +class CFX_FileAccess_Windows : public IFX_FileAccess { + public: + CFX_FileAccess_Windows(); + ~CFX_FileAccess_Windows() override; + + // IFX_FileAccess + bool Open(const ByteStringView& fileName, uint32_t dwMode) override; + bool Open(const WideStringView& fileName, uint32_t dwMode) override; + void Close() override; + FX_FILESIZE GetSize() const override; + FX_FILESIZE GetPosition() const override; + FX_FILESIZE SetPosition(FX_FILESIZE pos) override; + size_t Read(void* pBuffer, size_t szBuffer) override; + size_t Write(const void* pBuffer, size_t szBuffer) override; + size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) override; + size_t WritePos(const void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) override; + bool Flush() override; + bool Truncate(FX_FILESIZE szFile) override; + + protected: + void* m_hFile; +}; +#endif + +#endif // CORE_FXCRT_CFX_FILEACCESS_WINDOWS_H_ diff --git a/core/fxcrt/cfx_fixedbufgrow.h b/core/fxcrt/cfx_fixedbufgrow.h new file mode 100644 index 0000000000000000000000000000000000000000..b12b710473698d488d0aaccc8d06f9fe096a4634 --- /dev/null +++ b/core/fxcrt/cfx_fixedbufgrow.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_FIXEDBUFGROW_H_ +#define CORE_FXCRT_CFX_FIXEDBUFGROW_H_ + +#include + +#include "core/fxcrt/fx_memory.h" + +template +class CFX_FixedBufGrow { + public: + explicit CFX_FixedBufGrow(int data_size) { + if (data_size > FixedSize) { + m_pGrowData.reset(FX_Alloc(DataType, data_size)); + return; + } + memset(m_FixedData, 0, sizeof(DataType) * FixedSize); + } + operator DataType*() { return m_pGrowData ? m_pGrowData.get() : m_FixedData; } + + private: + DataType m_FixedData[FixedSize]; + std::unique_ptr m_pGrowData; +}; + +#endif // CORE_FXCRT_CFX_FIXEDBUFGROW_H_ diff --git a/core/fxcrt/cfx_maybe_owned.h b/core/fxcrt/cfx_maybe_owned.h deleted file mode 100644 index 92b1c1c24254bbf7f110cea83e4ec6145f94337c..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_maybe_owned.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2016 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. - -#ifndef CORE_FXCRT_CFX_MAYBE_OWNED_H_ -#define CORE_FXCRT_CFX_MAYBE_OWNED_H_ - -#include -#include -#include - -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" - -// A template that can hold either owned or unowned references, and cleans up -// appropriately. Possibly the most pernicious anti-pattern imaginable, but -// it crops up throughout the codebase due to a desire to avoid copying-in -// objects or data. -template > -class CFX_MaybeOwned { - public: - CFX_MaybeOwned() : m_pObj(nullptr) {} - explicit CFX_MaybeOwned(T* ptr) : m_pObj(ptr) {} - explicit CFX_MaybeOwned(std::unique_ptr ptr) - : m_pOwnedObj(std::move(ptr)), m_pObj(m_pOwnedObj.get()) {} - - CFX_MaybeOwned(const CFX_MaybeOwned& that) = delete; - CFX_MaybeOwned(CFX_MaybeOwned&& that) - : m_pOwnedObj(that.m_pOwnedObj.release()), m_pObj(that.m_pObj) { - that.m_pObj = nullptr; - } - - void Reset(std::unique_ptr ptr) { - m_pOwnedObj = std::move(ptr); - m_pObj = m_pOwnedObj.get(); - } - void Reset(T* ptr = nullptr) { - m_pOwnedObj.reset(); - m_pObj = ptr; - } - - bool IsOwned() const { return !!m_pOwnedObj; } - T* Get() const { return m_pObj; } - std::unique_ptr Release() { - ASSERT(IsOwned()); - return std::move(m_pOwnedObj); - } - - CFX_MaybeOwned& operator=(const CFX_MaybeOwned& that) = delete; - CFX_MaybeOwned& operator=(CFX_MaybeOwned&& that) { - m_pOwnedObj = std::move(that.m_pOwnedObj); - m_pObj = that.m_pObj; - that.m_pObj = nullptr; - return *this; - } - CFX_MaybeOwned& operator=(T* ptr) { - Reset(ptr); - return *this; - } - CFX_MaybeOwned& operator=(std::unique_ptr ptr) { - Reset(std::move(ptr)); - return *this; - } - - bool operator==(const CFX_MaybeOwned& that) const { - return Get() == that.Get(); - } - bool operator==(const std::unique_ptr& ptr) const { - return Get() == ptr.get(); - } - bool operator==(T* ptr) const { return Get() == ptr; } - - bool operator!=(const CFX_MaybeOwned& that) const { return !(*this == that); } - bool operator!=(const std::unique_ptr ptr) const { - return !(*this == ptr); - } - bool operator!=(T* ptr) const { return !(*this == ptr); } - - explicit operator bool() const { return !!m_pObj; } - T& operator*() const { return *m_pObj; } - T* operator->() const { return m_pObj; } - - private: - std::unique_ptr m_pOwnedObj; - T* m_pObj; -}; - -#endif // CORE_FXCRT_CFX_MAYBE_OWNED_H_ diff --git a/core/fxcrt/cfx_maybe_owned_unittest.cpp b/core/fxcrt/cfx_maybe_owned_unittest.cpp deleted file mode 100644 index 8f513a358d4b750f2f0078a5e3bbc26563281553..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_maybe_owned_unittest.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/cfx_maybe_owned.h" - -#include -#include - -#include "core/fxcrt/fx_memory.h" -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/ptr_util.h" - -namespace { - -class PseudoDeletable { - public: - explicit PseudoDeletable(int id, int* count_location) - : id_(id), count_location_(count_location) {} - ~PseudoDeletable() { ++(*count_location_); } - int GetID() const { return id_; } - - private: - int id_; - int* count_location_; -}; - -} // namespace - -TEST(fxcrt, MaybeOwnedNull) { - CFX_MaybeOwned ptr1; - EXPECT_FALSE(ptr1.IsOwned()); - EXPECT_FALSE(ptr1); - EXPECT_EQ(nullptr, ptr1.Get()); - - CFX_MaybeOwned ptr2; - EXPECT_TRUE(ptr1 == ptr2); - EXPECT_FALSE(ptr1 != ptr2); -} - -TEST(fxcrt, MaybeOwnedNotOwned) { - int delete_count = 0; - PseudoDeletable thing1(100, &delete_count); - { - CFX_MaybeOwned ptr(&thing1); - EXPECT_FALSE(ptr.IsOwned()); - EXPECT_EQ(ptr.Get(), &thing1); - EXPECT_EQ(100, ptr->GetID()); - EXPECT_TRUE(ptr == &thing1); - EXPECT_FALSE(ptr != &thing1); - - CFX_MaybeOwned empty; - EXPECT_FALSE(ptr == empty); - EXPECT_TRUE(ptr != empty); - } - EXPECT_EQ(0, delete_count); - - delete_count = 0; - PseudoDeletable thing2(200, &delete_count); - { - CFX_MaybeOwned ptr(&thing1); - ptr = &thing2; - EXPECT_FALSE(ptr.IsOwned()); - EXPECT_EQ(ptr.Get(), &thing2); - EXPECT_EQ(200, ptr->GetID()); - } - EXPECT_EQ(0, delete_count); - - delete_count = 0; - int owned_delete_count = 0; - { - CFX_MaybeOwned ptr(&thing1); - EXPECT_EQ(100, ptr->GetID()); - ptr = pdfium::MakeUnique(300, &owned_delete_count); - EXPECT_TRUE(ptr.IsOwned()); - EXPECT_EQ(300, ptr->GetID()); - } - EXPECT_EQ(0, delete_count); - EXPECT_EQ(1, owned_delete_count); -} - -TEST(fxcrt, MaybeOwnedOwned) { - int delete_count = 0; - { - CFX_MaybeOwned ptr( - pdfium::MakeUnique(100, &delete_count)); - EXPECT_TRUE(ptr.IsOwned()); - EXPECT_EQ(100, ptr->GetID()); - - CFX_MaybeOwned empty; - EXPECT_FALSE(ptr == empty); - EXPECT_TRUE(ptr != empty); - } - EXPECT_EQ(1, delete_count); - - delete_count = 0; - { - CFX_MaybeOwned ptr( - pdfium::MakeUnique(200, &delete_count)); - ptr = pdfium::MakeUnique(300, &delete_count); - EXPECT_TRUE(ptr.IsOwned()); - EXPECT_EQ(300, ptr->GetID()); - EXPECT_EQ(1, delete_count); - } - EXPECT_EQ(2, delete_count); - - delete_count = 0; - int unowned_delete_count = 0; - PseudoDeletable thing2(400, &unowned_delete_count); - { - CFX_MaybeOwned ptr( - pdfium::MakeUnique(500, &delete_count)); - ptr = &thing2; - EXPECT_FALSE(ptr.IsOwned()); - EXPECT_EQ(400, ptr->GetID()); - EXPECT_EQ(1, delete_count); - EXPECT_EQ(0, unowned_delete_count); - } - EXPECT_EQ(1, delete_count); - EXPECT_EQ(0, unowned_delete_count); -} - -TEST(fxcrt, MaybeOwnedRelease) { - int delete_count = 0; - { - std::unique_ptr stolen; - { - CFX_MaybeOwned ptr( - pdfium::MakeUnique(100, &delete_count)); - EXPECT_TRUE(ptr.IsOwned()); - stolen = ptr.Release(); - EXPECT_FALSE(ptr.IsOwned()); - EXPECT_EQ(ptr, stolen); - EXPECT_EQ(0, delete_count); - } - EXPECT_EQ(0, delete_count); - } - EXPECT_EQ(1, delete_count); -} - -TEST(fxcrt, MaybeOwnedMove) { - int delete_count = 0; - PseudoDeletable thing1(100, &delete_count); - { - CFX_MaybeOwned ptr1(&thing1); - CFX_MaybeOwned ptr2( - pdfium::MakeUnique(200, &delete_count)); - EXPECT_FALSE(ptr1.IsOwned()); - EXPECT_TRUE(ptr2.IsOwned()); - - CFX_MaybeOwned ptr3(std::move(ptr1)); - CFX_MaybeOwned ptr4(std::move(ptr2)); - EXPECT_FALSE(ptr1.IsOwned()); - EXPECT_FALSE(ptr2.IsOwned()); - EXPECT_FALSE(ptr3.IsOwned()); - EXPECT_TRUE(ptr4.IsOwned()); - EXPECT_EQ(0, delete_count); - EXPECT_EQ(nullptr, ptr1.Get()); - EXPECT_EQ(nullptr, ptr2.Get()); - EXPECT_EQ(100, ptr3->GetID()); - EXPECT_EQ(200, ptr4->GetID()); - - CFX_MaybeOwned ptr5; - CFX_MaybeOwned ptr6; - ptr5 = std::move(ptr3); - ptr6 = std::move(ptr4); - EXPECT_FALSE(ptr3.IsOwned()); - EXPECT_FALSE(ptr4.IsOwned()); - EXPECT_FALSE(ptr5.IsOwned()); - EXPECT_TRUE(ptr6.IsOwned()); - EXPECT_EQ(0, delete_count); - EXPECT_EQ(nullptr, ptr3.Get()); - EXPECT_EQ(nullptr, ptr4.Get()); - EXPECT_EQ(100, ptr5->GetID()); - EXPECT_EQ(200, ptr6->GetID()); - } - EXPECT_EQ(1, delete_count); -} diff --git a/core/fxcrt/cfx_memorystream.cpp b/core/fxcrt/cfx_memorystream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..345b381226ad231c5934e8bf8a38741f902f4d43 --- /dev/null +++ b/core/fxcrt/cfx_memorystream.cpp @@ -0,0 +1,199 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_memorystream.h" + +#include + +#include "core/fxcrt/fx_safe_types.h" + +namespace { + +const int32_t kBlockSize = 64 * 1024; + +} // namespace + +CFX_MemoryStream::CFX_MemoryStream(bool bConsecutive) + : m_nTotalSize(0), + m_nCurSize(0), + m_nCurPos(0), + m_nGrowSize(kBlockSize), + m_dwFlags(Type::kTakeOver | (bConsecutive ? Type::kConsecutive : 0)) {} + +CFX_MemoryStream::CFX_MemoryStream(uint8_t* pBuffer, + size_t nSize, + bool bTakeOver) + : m_nTotalSize(nSize), + m_nCurSize(nSize), + m_nCurPos(0), + m_nGrowSize(kBlockSize), + m_dwFlags(Type::kConsecutive | (bTakeOver ? Type::kTakeOver : 0)) { + m_Blocks.push_back(pBuffer); +} + +CFX_MemoryStream::~CFX_MemoryStream() { + if (m_dwFlags & Type::kTakeOver) { + for (uint8_t* pBlock : m_Blocks) + FX_Free(pBlock); + } +} + +FX_FILESIZE CFX_MemoryStream::GetSize() { + return static_cast(m_nCurSize); +} + +bool CFX_MemoryStream::IsEOF() { + return m_nCurPos >= static_cast(GetSize()); +} + +FX_FILESIZE CFX_MemoryStream::GetPosition() { + return static_cast(m_nCurPos); +} + +bool CFX_MemoryStream::Flush() { + return true; +} + +bool CFX_MemoryStream::ReadBlock(void* buffer, + FX_FILESIZE offset, + size_t size) { + if (!buffer || !size || offset < 0) + return false; + + FX_SAFE_SIZE_T newPos = size; + newPos += offset; + if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 || + newPos.ValueOrDie() > m_nCurSize) { + return false; + } + + m_nCurPos = newPos.ValueOrDie(); + if (m_dwFlags & Type::kConsecutive) { + memcpy(buffer, m_Blocks[0] + static_cast(offset), size); + return true; + } + + size_t nStartBlock = static_cast(offset) / m_nGrowSize; + offset -= static_cast(nStartBlock * m_nGrowSize); + while (size) { + size_t nRead = std::min(size, m_nGrowSize - static_cast(offset)); + memcpy(buffer, m_Blocks[nStartBlock] + offset, nRead); + buffer = static_cast(buffer) + nRead; + size -= nRead; + ++nStartBlock; + offset = 0; + } + return true; +} + +size_t CFX_MemoryStream::ReadBlock(void* buffer, size_t size) { + if (m_nCurPos >= m_nCurSize) + return 0; + + size_t nRead = std::min(size, m_nCurSize - m_nCurPos); + if (!ReadBlock(buffer, static_cast(m_nCurPos), nRead)) + return 0; + + return nRead; +} + +bool CFX_MemoryStream::WriteBlock(const void* buffer, + FX_FILESIZE offset, + size_t size) { + if (!buffer || !size) + return false; + + if (m_dwFlags & Type::kConsecutive) { + FX_SAFE_SIZE_T newPos = size; + newPos += offset; + if (!newPos.IsValid()) + return false; + + m_nCurPos = newPos.ValueOrDie(); + if (m_nCurPos > m_nTotalSize) { + m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize; + if (m_Blocks.empty()) + m_Blocks.push_back(FX_Alloc(uint8_t, m_nTotalSize)); + else + m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize); + } + + memcpy(m_Blocks[0] + offset, buffer, size); + m_nCurSize = std::max(m_nCurSize, m_nCurPos); + + return true; + } + + FX_SAFE_SIZE_T newPos = size; + newPos += offset; + if (!newPos.IsValid()) + return false; + if (!ExpandBlocks(newPos.ValueOrDie())) + return false; + + m_nCurPos = newPos.ValueOrDie(); + size_t nStartBlock = static_cast(offset) / m_nGrowSize; + offset -= static_cast(nStartBlock * m_nGrowSize); + while (size) { + size_t nWrite = std::min(size, m_nGrowSize - static_cast(offset)); + memcpy(m_Blocks[nStartBlock] + offset, buffer, nWrite); + buffer = static_cast(buffer) + nWrite; + size -= nWrite; + ++nStartBlock; + offset = 0; + } + return true; +} + +void CFX_MemoryStream::EstimateSize(size_t nInitSize, size_t nGrowSize) { + if (m_dwFlags & Type::kConsecutive) { + if (m_Blocks.empty()) { + m_Blocks.push_back( + FX_Alloc(uint8_t, std::max(nInitSize, static_cast(4096)))); + } + m_nGrowSize = std::max(nGrowSize, static_cast(4096)); + } else if (m_Blocks.empty()) { + m_nGrowSize = std::max(nGrowSize, static_cast(4096)); + } +} + +void CFX_MemoryStream::AttachBuffer(uint8_t* pBuffer, size_t nSize) { + if (!(m_dwFlags & Type::kConsecutive)) + return; + + m_Blocks.clear(); + m_Blocks.push_back(pBuffer); + m_nTotalSize = nSize; + m_nCurSize = nSize; + m_nCurPos = 0; + m_dwFlags = Type::kConsecutive; +} + +void CFX_MemoryStream::DetachBuffer() { + if (!(m_dwFlags & Type::kConsecutive)) + return; + + m_Blocks.clear(); + m_nTotalSize = 0; + m_nCurSize = 0; + m_nCurPos = 0; + m_dwFlags = Type::kTakeOver; +} + +bool CFX_MemoryStream::ExpandBlocks(size_t size) { + m_nCurSize = std::max(m_nCurSize, size); + if (size <= m_nTotalSize) + return true; + + size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize; + size_t iCount = m_Blocks.size(); + m_Blocks.resize(iCount + size); + while (size--) { + m_Blocks[iCount++] = FX_Alloc(uint8_t, m_nGrowSize); + m_nTotalSize += m_nGrowSize; + } + return true; +} diff --git a/core/fxcrt/cfx_memorystream.h b/core/fxcrt/cfx_memorystream.h new file mode 100644 index 0000000000000000000000000000000000000000..ef66080420a681d50cf71c71f67805587ac0a4ca --- /dev/null +++ b/core/fxcrt/cfx_memorystream.h @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_MEMORYSTREAM_H_ +#define CORE_FXCRT_CFX_MEMORYSTREAM_H_ + +#include + +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/retain_ptr.h" + +class CFX_MemoryStream : public IFX_SeekableStream { + public: + enum Type { kConsecutive = 1 << 0, kTakeOver = 1 << 1 }; + + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + // IFX_SeekableStream + FX_FILESIZE GetSize() override; + FX_FILESIZE GetPosition() override; + bool IsEOF() override; + bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; + size_t ReadBlock(void* buffer, size_t size) override; + bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override; + bool Flush() override; + + bool IsConsecutive() const { return !!(m_dwFlags & Type::kConsecutive); } + + uint8_t* GetBuffer() const { + return !m_Blocks.empty() ? m_Blocks.front() : nullptr; + } + + void EstimateSize(size_t nInitSize, size_t nGrowSize); + void AttachBuffer(uint8_t* pBuffer, size_t nSize); + void DetachBuffer(); + + private: + explicit CFX_MemoryStream(bool bConsecutive); + CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, bool bTakeOver); + ~CFX_MemoryStream() override; + + bool ExpandBlocks(size_t size); + + std::vector m_Blocks; + size_t m_nTotalSize; + size_t m_nCurSize; + size_t m_nCurPos; + size_t m_nGrowSize; + uint32_t m_dwFlags; +}; + +#endif // CORE_FXCRT_CFX_MEMORYSTREAM_H_ diff --git a/core/fxcrt/cfx_observable.h b/core/fxcrt/cfx_observable.h deleted file mode 100644 index 8dc0907cae6f0323cb0cfe84f245f1f60e3e5630..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_observable.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2016 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. - -#ifndef CORE_FXCRT_CFX_OBSERVABLE_H_ -#define CORE_FXCRT_CFX_OBSERVABLE_H_ - -#include - -#include "core/fxcrt/fx_system.h" -#include "third_party/base/stl_util.h" - -template -class CFX_Observable { - public: - class ObservedPtr { - public: - ObservedPtr() : m_pObservable(nullptr) {} - explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) { - if (m_pObservable) - m_pObservable->AddObservedPtr(this); - } - ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {} - ~ObservedPtr() { - if (m_pObservable) - m_pObservable->RemoveObservedPtr(this); - } - void Reset(T* pObservable = nullptr) { - if (m_pObservable) - m_pObservable->RemoveObservedPtr(this); - m_pObservable = pObservable; - if (m_pObservable) - m_pObservable->AddObservedPtr(this); - } - void OnDestroy() { - ASSERT(m_pObservable); - m_pObservable = nullptr; - } - ObservedPtr& operator=(const ObservedPtr& that) { - Reset(that.Get()); - return *this; - } - bool operator==(const ObservedPtr& that) const { - return m_pObservable == that.m_pObservable; - } - bool operator!=(const ObservedPtr& that) const { return !(*this == that); } - explicit operator bool() const { return !!m_pObservable; } - T* Get() const { return m_pObservable; } - T& operator*() const { return *m_pObservable; } - T* operator->() const { return m_pObservable; } - - private: - T* m_pObservable; - }; - - CFX_Observable() {} - CFX_Observable(const CFX_Observable& that) = delete; - ~CFX_Observable() { NotifyObservedPtrs(); } - void AddObservedPtr(ObservedPtr* pObservedPtr) { - ASSERT(!pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr)); - m_ObservedPtrs.insert(pObservedPtr); - } - void RemoveObservedPtr(ObservedPtr* pObservedPtr) { - ASSERT(pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr)); - m_ObservedPtrs.erase(pObservedPtr); - } - void NotifyObservedPtrs() { - for (auto* pObservedPtr : m_ObservedPtrs) - pObservedPtr->OnDestroy(); - m_ObservedPtrs.clear(); - } - CFX_Observable& operator=(const CFX_Observable& that) = delete; - - protected: - size_t ActiveObservedPtrsForTesting() const { return m_ObservedPtrs.size(); } - - private: - std::set m_ObservedPtrs; -}; - -#endif // CORE_FXCRT_CFX_OBSERVABLE_H_ diff --git a/core/fxcrt/cfx_observable_unittest.cpp b/core/fxcrt/cfx_observable_unittest.cpp deleted file mode 100644 index 3c0fabb13e92489261d8d844a5e4dca3135d0cf0..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_observable_unittest.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/cfx_observable.h" - -#include -#include - -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class PseudoObservable : public CFX_Observable { - public: - PseudoObservable() {} - int SomeMethod() { return 42; } - size_t ActiveObservedPtrs() const { return ActiveObservedPtrsForTesting(); } -}; - -} // namespace - -TEST(fxcrt, ObservePtrNull) { - PseudoObservable::ObservedPtr ptr; - EXPECT_EQ(nullptr, ptr.Get()); -} - -TEST(fxcrt, ObservePtrLivesLonger) { - PseudoObservable* pObs = new PseudoObservable; - PseudoObservable::ObservedPtr ptr(pObs); - EXPECT_NE(nullptr, ptr.Get()); - EXPECT_EQ(1u, pObs->ActiveObservedPtrs()); - delete pObs; - EXPECT_EQ(nullptr, ptr.Get()); -} - -TEST(fxcrt, ObservePtrLivesShorter) { - PseudoObservable obs; - { - PseudoObservable::ObservedPtr ptr(&obs); - EXPECT_NE(nullptr, ptr.Get()); - EXPECT_EQ(1u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(0u, obs.ActiveObservedPtrs()); -} - -TEST(fxcrt, ObserveCopyConstruct) { - PseudoObservable obs; - { - PseudoObservable::ObservedPtr ptr(&obs); - EXPECT_NE(nullptr, ptr.Get()); - EXPECT_EQ(1u, obs.ActiveObservedPtrs()); - { - PseudoObservable::ObservedPtr ptr2(ptr); - EXPECT_NE(nullptr, ptr2.Get()); - EXPECT_EQ(2u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(1u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(0u, obs.ActiveObservedPtrs()); -} - -TEST(fxcrt, ObserveCopyAssign) { - PseudoObservable obs; - { - PseudoObservable::ObservedPtr ptr(&obs); - EXPECT_NE(nullptr, ptr.Get()); - EXPECT_EQ(1u, obs.ActiveObservedPtrs()); - { - PseudoObservable::ObservedPtr ptr2; - ptr2 = ptr; - EXPECT_NE(nullptr, ptr2.Get()); - EXPECT_EQ(2u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(1u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(0u, obs.ActiveObservedPtrs()); -} - -TEST(fxcrt, ObserveVector) { - PseudoObservable obs; - { - std::vector vec1; - std::vector vec2; - vec1.emplace_back(&obs); - vec1.emplace_back(&obs); - EXPECT_NE(nullptr, vec1[0].Get()); - EXPECT_NE(nullptr, vec1[1].Get()); - EXPECT_EQ(2u, obs.ActiveObservedPtrs()); - vec2 = vec1; - EXPECT_NE(nullptr, vec2[0].Get()); - EXPECT_NE(nullptr, vec2[1].Get()); - EXPECT_EQ(4u, obs.ActiveObservedPtrs()); - vec1.clear(); - EXPECT_EQ(2u, obs.ActiveObservedPtrs()); - vec2.resize(10000); - EXPECT_EQ(2u, obs.ActiveObservedPtrs()); - vec2.resize(0); - EXPECT_EQ(0u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(0u, obs.ActiveObservedPtrs()); -} - -TEST(fxcrt, ObserveVectorAutoClear) { - std::vector vec1; - { - PseudoObservable obs; - vec1.emplace_back(&obs); - vec1.emplace_back(&obs); - EXPECT_NE(nullptr, vec1[0].Get()); - EXPECT_NE(nullptr, vec1[1].Get()); - EXPECT_EQ(2u, obs.ActiveObservedPtrs()); - } - EXPECT_EQ(nullptr, vec1[0].Get()); - EXPECT_EQ(nullptr, vec1[1].Get()); -} - -TEST(fxcrt, ObservePtrResetNull) { - PseudoObservable obs; - PseudoObservable::ObservedPtr ptr(&obs); - EXPECT_EQ(1u, obs.ActiveObservedPtrs()); - ptr.Reset(); - EXPECT_EQ(0u, obs.ActiveObservedPtrs()); -} - -TEST(fxcrt, ObservePtrReset) { - PseudoObservable obs1; - PseudoObservable obs2; - PseudoObservable::ObservedPtr ptr(&obs1); - EXPECT_EQ(1u, obs1.ActiveObservedPtrs()); - EXPECT_EQ(0u, obs2.ActiveObservedPtrs()); - ptr.Reset(&obs2); - EXPECT_EQ(0u, obs1.ActiveObservedPtrs()); - EXPECT_EQ(1u, obs2.ActiveObservedPtrs()); -} - -TEST(fxcrt, ObservePtrEquals) { - PseudoObservable obj1; - PseudoObservable obj2; - PseudoObservable::ObservedPtr null_ptr1; - PseudoObservable::ObservedPtr obj1_ptr1(&obj1); - PseudoObservable::ObservedPtr obj2_ptr1(&obj2); - { - PseudoObservable::ObservedPtr null_ptr2; - EXPECT_TRUE(null_ptr1 == null_ptr2); - - PseudoObservable::ObservedPtr obj1_ptr2(&obj1); - EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); - - PseudoObservable::ObservedPtr obj2_ptr2(&obj2); - EXPECT_TRUE(obj2_ptr1 == obj2_ptr2); - } - EXPECT_FALSE(null_ptr1 == obj1_ptr1); - EXPECT_FALSE(null_ptr1 == obj2_ptr1); - EXPECT_FALSE(obj1_ptr1 == obj2_ptr1); -} - -TEST(fxcrt, ObservePtrNotEquals) { - PseudoObservable obj1; - PseudoObservable obj2; - PseudoObservable::ObservedPtr null_ptr1; - PseudoObservable::ObservedPtr obj1_ptr1(&obj1); - PseudoObservable::ObservedPtr obj2_ptr1(&obj2); - { - PseudoObservable::ObservedPtr null_ptr2; - PseudoObservable::ObservedPtr obj1_ptr2(&obj1); - PseudoObservable::ObservedPtr obj2_ptr2(&obj2); - EXPECT_FALSE(null_ptr1 != null_ptr2); - EXPECT_FALSE(obj1_ptr1 != obj1_ptr2); - EXPECT_FALSE(obj2_ptr1 != obj2_ptr2); - } - EXPECT_TRUE(null_ptr1 != obj1_ptr1); - EXPECT_TRUE(null_ptr1 != obj2_ptr1); - EXPECT_TRUE(obj1_ptr1 != obj2_ptr1); -} - -TEST(fxcrt, ObservePtrBool) { - PseudoObservable obj1; - PseudoObservable::ObservedPtr null_ptr; - PseudoObservable::ObservedPtr obj1_ptr(&obj1); - bool null_bool = !!null_ptr; - bool obj1_bool = !!obj1_ptr; - EXPECT_FALSE(null_bool); - EXPECT_TRUE(obj1_bool); -} diff --git a/core/fxcrt/cfx_retain_ptr.h b/core/fxcrt/cfx_retain_ptr.h deleted file mode 100644 index 0267ae04cd8f332b71b2d7ae9a6becfc47edac34..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_retain_ptr.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2016 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. - -#ifndef CORE_FXCRT_CFX_RETAIN_PTR_H_ -#define CORE_FXCRT_CFX_RETAIN_PTR_H_ - -#include -#include -#include - -#include "core/fxcrt/fx_memory.h" - -// Analogous to base's scoped_refptr. -template -class CFX_RetainPtr { - public: - explicit CFX_RetainPtr(T* pObj) : m_pObj(pObj) { - if (m_pObj) - m_pObj->Retain(); - } - - CFX_RetainPtr() {} - CFX_RetainPtr(const CFX_RetainPtr& that) : CFX_RetainPtr(that.Get()) {} - CFX_RetainPtr(CFX_RetainPtr&& that) { Swap(that); } - - // Deliberately implicit to allow returning nullptrs. - CFX_RetainPtr(std::nullptr_t ptr) {} - - template - CFX_RetainPtr(const CFX_RetainPtr& that) : CFX_RetainPtr(that.Get()) {} - - template - CFX_RetainPtr As() const { - return CFX_RetainPtr(static_cast(Get())); - } - - void Reset(T* obj = nullptr) { - if (obj) - obj->Retain(); - m_pObj.reset(obj); - } - - T* Get() const { return m_pObj.get(); } - void Swap(CFX_RetainPtr& that) { m_pObj.swap(that.m_pObj); } - - // TODO(tsepez): temporary scaffolding, to be removed. - T* Leak() { return m_pObj.release(); } - void Unleak(T* ptr) { m_pObj.reset(ptr); } - - CFX_RetainPtr& operator=(const CFX_RetainPtr& that) { - if (*this != that) - Reset(that.Get()); - return *this; - } - - bool operator==(const CFX_RetainPtr& that) const { - return Get() == that.Get(); - } - bool operator!=(const CFX_RetainPtr& that) const { return !(*this == that); } - - bool operator<(const CFX_RetainPtr& that) const { - return std::less()(Get(), that.Get()); - } - - explicit operator bool() const { return !!m_pObj; } - T& operator*() const { return *m_pObj.get(); } - T* operator->() const { return m_pObj.get(); } - - private: - std::unique_ptr> m_pObj; -}; - -// Trivial implementation - internal ref count with virtual destructor. -class CFX_Retainable { - public: - bool HasOneRef() const { return m_nRefCount == 1; } - - protected: - virtual ~CFX_Retainable() {} - - private: - template - friend struct ReleaseDeleter; - - template - friend class CFX_RetainPtr; - - void Retain() { ++m_nRefCount; } - void Release() { - ASSERT(m_nRefCount > 0); - if (--m_nRefCount == 0) - delete this; - } - - intptr_t m_nRefCount = 0; -}; - -namespace pdfium { - -// Helper to make a CFX_RetainPtr along the lines of std::make_unique<>(), -// or pdfium::MakeUnique<>(). Arguments are forwarded to T's constructor. -// Classes managed by CFX_RetainPtr should have protected (or private) -// constructors, and should friend this function. -template -CFX_RetainPtr MakeRetain(Args&&... args) { - return CFX_RetainPtr(new T(std::forward(args)...)); -} - -} // namespace pdfium - -#endif // CORE_FXCRT_CFX_RETAIN_PTR_H_ diff --git a/core/fxcrt/cfx_retain_ptr_unittest.cpp b/core/fxcrt/cfx_retain_ptr_unittest.cpp deleted file mode 100644 index 3168b5a4c7bfeb28d55a185e36da69cfc3a3afcf..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_retain_ptr_unittest.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/cfx_retain_ptr.h" - -#include - -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class PseudoRetainable { - public: - PseudoRetainable() : retain_count_(0), release_count_(0) {} - void Retain() { ++retain_count_; } - void Release() { ++release_count_; } - int retain_count() const { return retain_count_; } - int release_count() const { return release_count_; } - - private: - int retain_count_; - int release_count_; -}; - -} // namespace - -TEST(fxcrt, RetainPtrNull) { - CFX_RetainPtr ptr; - EXPECT_EQ(nullptr, ptr.Get()); -} - -TEST(fxcrt, RetainPtrNormal) { - PseudoRetainable obj; - { - CFX_RetainPtr ptr(&obj); - EXPECT_EQ(&obj, ptr.Get()); - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); -} - -TEST(fxcrt, RetainPtrCopyCtor) { - PseudoRetainable obj; - { - CFX_RetainPtr ptr1(&obj); - { - CFX_RetainPtr ptr2(ptr1); - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); - } - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(2, obj.release_count()); -} - -TEST(fxcrt, RetainPtrMoveCtor) { - PseudoRetainable obj; - { - CFX_RetainPtr ptr1(&obj); - { - CFX_RetainPtr ptr2(std::move(ptr1)); - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); -} - -TEST(fxcrt, RetainPtrResetNull) { - PseudoRetainable obj; - { - CFX_RetainPtr ptr(&obj); - ptr.Reset(); - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); -} - -TEST(fxcrt, RetainPtrReset) { - PseudoRetainable obj1; - PseudoRetainable obj2; - { - CFX_RetainPtr ptr(&obj1); - ptr.Reset(&obj2); - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(1, obj1.release_count()); - EXPECT_EQ(1, obj2.retain_count()); - EXPECT_EQ(0, obj2.release_count()); - } - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(1, obj1.release_count()); - EXPECT_EQ(1, obj2.retain_count()); - EXPECT_EQ(1, obj2.release_count()); -} - -TEST(fxcrt, RetainPtrSwap) { - PseudoRetainable obj1; - PseudoRetainable obj2; - { - CFX_RetainPtr ptr1(&obj1); - { - CFX_RetainPtr ptr2(&obj2); - ptr1.Swap(ptr2); - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(0, obj1.release_count()); - EXPECT_EQ(1, obj2.retain_count()); - EXPECT_EQ(0, obj2.release_count()); - } - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(1, obj1.release_count()); - EXPECT_EQ(1, obj2.retain_count()); - EXPECT_EQ(0, obj2.release_count()); - } - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(1, obj1.release_count()); - EXPECT_EQ(1, obj2.retain_count()); - EXPECT_EQ(1, obj2.release_count()); -} - -TEST(fxcrt, RetainPtrLeak) { - PseudoRetainable obj; - PseudoRetainable* leak; - { - CFX_RetainPtr ptr(&obj); - leak = ptr.Leak(); - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - { - CFX_RetainPtr ptr; - ptr.Unleak(leak); - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(1, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); -} - -TEST(fxcrt, RetainPtrSwapNull) { - PseudoRetainable obj1; - { - CFX_RetainPtr ptr1(&obj1); - { - CFX_RetainPtr ptr2; - ptr1.Swap(ptr2); - EXPECT_FALSE(ptr1); - EXPECT_TRUE(ptr2); - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(0, obj1.release_count()); - } - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(1, obj1.release_count()); - } - EXPECT_EQ(1, obj1.retain_count()); - EXPECT_EQ(1, obj1.release_count()); -} - -TEST(fxcrt, RetainPtrAssign) { - PseudoRetainable obj; - { - CFX_RetainPtr ptr(&obj); - { - CFX_RetainPtr ptr2; - ptr2 = ptr; - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(0, obj.release_count()); - } - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(1, obj.release_count()); - } - EXPECT_EQ(2, obj.retain_count()); - EXPECT_EQ(2, obj.release_count()); -} - -TEST(fxcrt, RetainPtrEquals) { - PseudoRetainable obj1; - PseudoRetainable obj2; - CFX_RetainPtr null_ptr1; - CFX_RetainPtr obj1_ptr1(&obj1); - CFX_RetainPtr obj2_ptr1(&obj2); - { - CFX_RetainPtr null_ptr2; - EXPECT_TRUE(null_ptr1 == null_ptr2); - - CFX_RetainPtr obj1_ptr2(&obj1); - EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); - - CFX_RetainPtr obj2_ptr2(&obj2); - EXPECT_TRUE(obj2_ptr1 == obj2_ptr2); - } - EXPECT_FALSE(null_ptr1 == obj1_ptr1); - EXPECT_FALSE(null_ptr1 == obj2_ptr1); - EXPECT_FALSE(obj1_ptr1 == obj2_ptr1); -} - -TEST(fxcrt, RetainPtrNotEquals) { - PseudoRetainable obj1; - PseudoRetainable obj2; - CFX_RetainPtr null_ptr1; - CFX_RetainPtr obj1_ptr1(&obj1); - CFX_RetainPtr obj2_ptr1(&obj2); - { - CFX_RetainPtr null_ptr2; - CFX_RetainPtr obj1_ptr2(&obj1); - CFX_RetainPtr obj2_ptr2(&obj2); - EXPECT_FALSE(null_ptr1 != null_ptr2); - EXPECT_FALSE(obj1_ptr1 != obj1_ptr2); - EXPECT_FALSE(obj2_ptr1 != obj2_ptr2); - } - EXPECT_TRUE(null_ptr1 != obj1_ptr1); - EXPECT_TRUE(null_ptr1 != obj2_ptr1); - EXPECT_TRUE(obj1_ptr1 != obj2_ptr1); -} - -TEST(fxcrt, RetainPtrLessThan) { - PseudoRetainable objs[2]; - CFX_RetainPtr obj1_ptr(&objs[0]); - CFX_RetainPtr obj2_ptr(&objs[1]); - EXPECT_TRUE(obj1_ptr < obj2_ptr); - EXPECT_FALSE(obj2_ptr < obj1_ptr); -} - -TEST(fxcrt, RetainPtrBool) { - PseudoRetainable obj1; - CFX_RetainPtr null_ptr; - CFX_RetainPtr obj1_ptr(&obj1); - bool null_bool = !!null_ptr; - bool obj1_bool = !!obj1_ptr; - EXPECT_FALSE(null_bool); - EXPECT_TRUE(obj1_bool); -} - -TEST(fxcrt, RetainPtrMakeRetained) { - auto ptr = pdfium::MakeRetain(); - EXPECT_TRUE(ptr->HasOneRef()); - { - CFX_RetainPtr other = ptr; - EXPECT_FALSE(ptr->HasOneRef()); - } - EXPECT_TRUE(ptr->HasOneRef()); -} diff --git a/core/fxcrt/cfx_seekablemultistream.cpp b/core/fxcrt/cfx_seekablemultistream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92286b1939d97908469f12ae05dc7ea23127837f --- /dev/null +++ b/core/fxcrt/cfx_seekablemultistream.cpp @@ -0,0 +1,85 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_seekablemultistream.h" + +#include + +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "third_party/base/logging.h" +#include "third_party/base/stl_util.h" + +CFX_SeekableMultiStream::CFX_SeekableMultiStream( + const std::vector& streams) { + for (CPDF_Stream* pStream : streams) { + m_Data.push_back(pdfium::MakeRetain(pStream)); + m_Data.back()->LoadAllDataFiltered(); + } +} + +CFX_SeekableMultiStream::~CFX_SeekableMultiStream() {} + +FX_FILESIZE CFX_SeekableMultiStream::GetSize() { + uint32_t dwSize = 0; + for (const auto& acc : m_Data) + dwSize += acc->GetSize(); + return dwSize; +} + +bool CFX_SeekableMultiStream::ReadBlock(void* buffer, + FX_FILESIZE offset, + size_t size) { + int32_t iCount = pdfium::CollectionSize(m_Data); + int32_t index = 0; + while (index < iCount) { + const auto& acc = m_Data[index]; + FX_FILESIZE dwSize = acc->GetSize(); + if (offset < dwSize) + break; + + offset -= dwSize; + index++; + } + while (index < iCount) { + const auto& acc = m_Data[index]; + uint32_t dwSize = acc->GetSize(); + size_t dwRead = std::min(size, static_cast(dwSize - offset)); + memcpy(buffer, acc->GetData() + offset, dwRead); + size -= dwRead; + if (size == 0) + return true; + + buffer = static_cast(buffer) + dwRead; + offset = 0; + index++; + } + return false; +} + +size_t CFX_SeekableMultiStream::ReadBlock(void* buffer, size_t size) { + NOTREACHED(); + return 0; +} + +FX_FILESIZE CFX_SeekableMultiStream::GetPosition() { + return 0; +} + +bool CFX_SeekableMultiStream::IsEOF() { + return false; +} + +bool CFX_SeekableMultiStream::Flush() { + NOTREACHED(); + return false; +} + +bool CFX_SeekableMultiStream::WriteBlock(const void* pData, + FX_FILESIZE offset, + size_t size) { + NOTREACHED(); + return false; +} diff --git a/core/fxcrt/cfx_seekablemultistream.h b/core/fxcrt/cfx_seekablemultistream.h new file mode 100644 index 0000000000000000000000000000000000000000..9138d7c321527f1f9bf8c6a8ebdb5a6bf410403f --- /dev/null +++ b/core/fxcrt/cfx_seekablemultistream.h @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_SEEKABLEMULTISTREAM_H_ +#define CORE_FXCRT_CFX_SEEKABLEMULTISTREAM_H_ + +#include + +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/retain_ptr.h" + +class CPDF_Stream; +class CPDF_StreamAcc; + +class CFX_SeekableMultiStream : public IFX_SeekableStream { + public: + explicit CFX_SeekableMultiStream(const std::vector& streams); + ~CFX_SeekableMultiStream() override; + + // IFX_SeekableReadStream + FX_FILESIZE GetPosition() override; + FX_FILESIZE GetSize() override; + bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; + size_t ReadBlock(void* buffer, size_t size) override; + bool IsEOF() override; + bool Flush() override; + bool WriteBlock(const void* pData, FX_FILESIZE offset, size_t size) override; + + private: + std::vector> m_Data; +}; + +#endif // CORE_FXCRT_CFX_SEEKABLEMULTISTREAM_H_ diff --git a/core/fxcrt/cfx_seekablemultistream_unittest.cpp b/core/fxcrt/cfx_seekablemultistream_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89213b13af02ed7a7ca74ec1086fb5ddc2a5ff86 --- /dev/null +++ b/core/fxcrt/cfx_seekablemultistream_unittest.cpp @@ -0,0 +1,85 @@ +// Copyright 2016 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. + +#include "core/fxcrt/cfx_seekablemultistream.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fxcrt/fx_memory.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" + +TEST(CFX_SeekableMultiStreamTest, NoStreams) { + std::vector streams; + auto fileread = pdfium::MakeRetain(streams); + + uint8_t output_buffer[16]; + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_FALSE(fileread->ReadBlock(output_buffer, 0, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); +} + +TEST(CXFAFileReadTest, EmptyStreams) { + std::vector streams; + auto stream1 = pdfium::MakeUnique(); + streams.push_back(stream1.get()); + auto fileread = pdfium::MakeRetain(streams); + + uint8_t output_buffer[16]; + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_FALSE(fileread->ReadBlock(output_buffer, 0, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); +} + +TEST(CXFAFileReadTest, NormalStreams) { + std::vector streams; + auto stream1 = pdfium::MakeUnique(); + auto stream2 = pdfium::MakeUnique(); + auto stream3 = pdfium::MakeUnique(); + + // 16 chars total. + stream1->InitStream(reinterpret_cast("one t"), 5, + pdfium::MakeUnique()); + stream2->InitStream(reinterpret_cast("wo "), 3, + pdfium::MakeUnique()); + stream3->InitStream(reinterpret_cast("three!!!"), 8, + pdfium::MakeUnique()); + + streams.push_back(stream1.get()); + streams.push_back(stream2.get()); + streams.push_back(stream3.get()); + auto fileread = pdfium::MakeRetain(streams); + + uint8_t output_buffer[16]; + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 1, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, 1)); + EXPECT_EQ(0, memcmp(output_buffer, "o", 1)); + EXPECT_EQ(0xbd, output_buffer[1]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, sizeof(output_buffer))); + EXPECT_EQ(0, memcmp(output_buffer, "one two three!!!", 16)); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 2, 10)); + EXPECT_EQ(0, memcmp(output_buffer, "e two thre", 10)); + EXPECT_EQ(0xbd, output_buffer[11]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_FALSE(fileread->ReadBlock(output_buffer, 1, sizeof(output_buffer))); + EXPECT_EQ(0, memcmp(output_buffer, "ne two three!!!", 15)); + EXPECT_EQ(0xbd, output_buffer[15]); +} diff --git a/core/fxcrt/cfx_seekablestreamproxy.cpp b/core/fxcrt/cfx_seekablestreamproxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..989c440db166e2981730d0289b8867f104d4807e --- /dev/null +++ b/core/fxcrt/cfx_seekablestreamproxy.cpp @@ -0,0 +1,286 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_seekablestreamproxy.h" + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#include +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + +#include +#include +#include +#include +#include + +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +// Returns {src bytes consumed, dst bytes produced}. +std::pair UTF8Decode(const char* pSrc, + size_t srcLen, + wchar_t* pDst, + size_t dstLen) { + ASSERT(pDst && dstLen > 0); + + if (srcLen < 1) + return {0, 0}; + + uint32_t dwCode = 0; + int32_t iPending = 0; + size_t iSrcNum = 0; + size_t iDstNum = 0; + size_t iIndex = 0; + int32_t k = 1; + while (iIndex < srcLen) { + uint8_t byte = static_cast(*(pSrc + iIndex)); + if (byte < 0x80) { + iPending = 0; + k = 1; + iDstNum++; + iSrcNum += k; + *pDst++ = byte; + if (iDstNum >= dstLen) + break; + } else if (byte < 0xc0) { + if (iPending < 1) + break; + + iPending--; + dwCode |= (byte & 0x3f) << (iPending * 6); + if (iPending == 0) { + iDstNum++; + iSrcNum += k; + *pDst++ = dwCode; + if (iDstNum >= dstLen) + 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++; + } + return {iSrcNum, iDstNum}; +} + +void UTF16ToWChar(void* pBuffer, size_t iLength) { + ASSERT(pBuffer); + ASSERT(iLength > 0); + ASSERT(sizeof(wchar_t) > 2); + + uint16_t* pSrc = static_cast(pBuffer); + wchar_t* pDst = static_cast(pBuffer); + for (size_t i = 0; i < iLength; i++) + pDst[i] = static_cast(pSrc[i]); +} + +void SwapByteOrder(wchar_t* pStr, size_t iLength) { + ASSERT(pStr); + + uint16_t wch; + if (sizeof(wchar_t) > 2) { + while (iLength-- > 0) { + wch = static_cast(*pStr); + wch = (wch >> 8) | (wch << 8); + wch &= 0x00FF; + *pStr = wch; + ++pStr; + } + return; + } + + while (iLength-- > 0) { + wch = static_cast(*pStr); + wch = (wch >> 8) | (wch << 8); + *pStr = wch; + ++pStr; + } +} + +} // namespace + +#define BOM_MASK 0x00FFFFFF +#define BOM_UTF8 0x00BFBBEF +#define BOM_UTF16_MASK 0x0000FFFF +#define BOM_UTF16_BE 0x0000FFFE +#define BOM_UTF16_LE 0x0000FEFF + +CFX_SeekableStreamProxy::CFX_SeekableStreamProxy( + const RetainPtr& stream, + bool isWriteStream) + : m_IsWriteStream(isWriteStream), + m_wCodePage(FX_CODEPAGE_DefANSI), + m_wBOMLength(0), + m_iPosition(0), + m_pStream(stream) { + ASSERT(m_pStream); + + if (isWriteStream) { + m_iPosition = m_pStream->GetSize(); + return; + } + + Seek(From::Begin, 0); + + uint32_t bom = 0; + ReadData(reinterpret_cast(&bom), 3); + + bom &= BOM_MASK; + if (bom == BOM_UTF8) { + m_wBOMLength = 3; + m_wCodePage = FX_CODEPAGE_UTF8; + } else { + bom &= BOM_UTF16_MASK; + if (bom == BOM_UTF16_BE) { + m_wBOMLength = 2; + m_wCodePage = FX_CODEPAGE_UTF16BE; + } else if (bom == BOM_UTF16_LE) { + m_wBOMLength = 2; + m_wCodePage = FX_CODEPAGE_UTF16LE; + } else { + m_wBOMLength = 0; + m_wCodePage = FXSYS_GetACP(); + } + } + + Seek(From::Begin, static_cast(m_wBOMLength)); +} + +CFX_SeekableStreamProxy::CFX_SeekableStreamProxy(uint8_t* data, size_t size) + : CFX_SeekableStreamProxy( + pdfium::MakeRetain(data, size, false), + false) {} + +CFX_SeekableStreamProxy::~CFX_SeekableStreamProxy() {} + +void CFX_SeekableStreamProxy::Seek(From eSeek, FX_FILESIZE iOffset) { + switch (eSeek) { + case From::Begin: + m_iPosition = iOffset; + break; + case From::Current: { + pdfium::base::CheckedNumeric new_pos = m_iPosition; + new_pos += iOffset; + m_iPosition = + new_pos.ValueOrDefault(std::numeric_limits::max()); + } break; + } + m_iPosition = + pdfium::clamp(m_iPosition, static_cast(0), GetLength()); +} + +void CFX_SeekableStreamProxy::SetCodePage(uint16_t wCodePage) { + if (m_wBOMLength > 0) + return; + m_wCodePage = wCodePage; +} + +size_t CFX_SeekableStreamProxy::ReadData(uint8_t* pBuffer, size_t iBufferSize) { + ASSERT(pBuffer && iBufferSize > 0); + + if (m_IsWriteStream) + return 0; + + iBufferSize = + std::min(iBufferSize, static_cast(GetLength() - m_iPosition)); + if (iBufferSize <= 0) + return 0; + + if (!m_pStream->ReadBlock(pBuffer, m_iPosition, iBufferSize)) + return 0; + + pdfium::base::CheckedNumeric new_pos = m_iPosition; + new_pos += iBufferSize; + m_iPosition = new_pos.ValueOrDefault(m_iPosition); + return new_pos.IsValid() ? iBufferSize : 0; +} + +size_t CFX_SeekableStreamProxy::ReadString(wchar_t* pStr, + size_t iMaxLength, + bool* bEOS) { + if (!pStr || iMaxLength == 0) + return 0; + + if (m_IsWriteStream) + return 0; + + if (m_wCodePage == FX_CODEPAGE_UTF16LE || + m_wCodePage == FX_CODEPAGE_UTF16BE) { + size_t iBytes = iMaxLength * 2; + size_t iLen = ReadData(reinterpret_cast(pStr), iBytes); + iMaxLength = iLen / 2; + if (sizeof(wchar_t) > 2 && iMaxLength > 0) + UTF16ToWChar(pStr, iMaxLength); + + if (m_wCodePage == FX_CODEPAGE_UTF16BE) + SwapByteOrder(pStr, iMaxLength); + + } else { + FX_FILESIZE pos = GetPosition(); + size_t iBytes = + std::min(iMaxLength, static_cast(GetLength() - pos)); + + if (iBytes > 0) { + std::vector buf(iBytes); + + size_t iLen = ReadData(buf.data(), iBytes); + if (m_wCodePage != FX_CODEPAGE_UTF8) + return 0; + + size_t iSrc = 0; + std::tie(iSrc, iMaxLength) = UTF8Decode( + reinterpret_cast(buf.data()), iLen, pStr, iMaxLength); + Seek(From::Current, iSrc - iLen); + } else { + iMaxLength = 0; + } + } + + *bEOS = IsEOF(); + return iMaxLength; +} + +void CFX_SeekableStreamProxy::WriteString(const WideStringView& str) { + if (!m_IsWriteStream || str.GetLength() == 0 || + m_wCodePage != FX_CODEPAGE_UTF8) { + return; + } + if (!m_pStream->WriteBlock(str.unterminated_c_str(), m_iPosition, + str.GetLength() * sizeof(wchar_t))) { + return; + } + + pdfium::base::CheckedNumeric new_pos = m_iPosition; + new_pos += str.GetLength() * sizeof(wchar_t); + m_iPosition = new_pos.ValueOrDefault(std::numeric_limits::max()); + m_iPosition = + pdfium::clamp(m_iPosition, static_cast(0), GetLength()); +} diff --git a/core/fxcrt/cfx_seekablestreamproxy.h b/core/fxcrt/cfx_seekablestreamproxy.h new file mode 100644 index 0000000000000000000000000000000000000000..c25ab3c9b67cf3d2240628eae9cb8afa9a54a34c --- /dev/null +++ b/core/fxcrt/cfx_seekablestreamproxy.h @@ -0,0 +1,54 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_SEEKABLESTREAMPROXY_H_ +#define CORE_FXCRT_CFX_SEEKABLESTREAMPROXY_H_ + +#include + +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" + +class CFX_SeekableStreamProxy : public Retainable { + public: + enum class From { + Begin = 0, + Current, + }; + + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + FX_FILESIZE GetLength() const { return m_pStream->GetSize(); } + FX_FILESIZE GetPosition() { return m_iPosition; } + size_t GetBOMLength() const { return m_wBOMLength; } + bool IsEOF() const { return m_iPosition >= GetLength(); } + + void Seek(From eSeek, FX_FILESIZE iOffset); + size_t ReadString(wchar_t* pStr, size_t iMaxLength, bool* bEOS); + + void WriteString(const WideStringView& str); + + uint16_t GetCodePage() const { return m_wCodePage; } + void SetCodePage(uint16_t wCodePage); + + private: + CFX_SeekableStreamProxy(const RetainPtr& stream, + bool isWriteSteam); + CFX_SeekableStreamProxy(uint8_t* data, size_t size); + ~CFX_SeekableStreamProxy() override; + + size_t ReadData(uint8_t* pBuffer, size_t iBufferSize); + + bool m_IsWriteStream; + uint16_t m_wCodePage; + size_t m_wBOMLength; + FX_FILESIZE m_iPosition; + RetainPtr m_pStream; +}; + +#endif // CORE_FXCRT_CFX_SEEKABLESTREAMPROXY_H_ diff --git a/core/fxcrt/cfx_shared_copy_on_write.h b/core/fxcrt/cfx_shared_copy_on_write.h deleted file mode 100644 index c87d96509df97e551fedc73e6dabb26f01a850f3..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_shared_copy_on_write.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2016 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 CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_ -#define CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_system.h" - -// A shared object with Copy on Write semantics that makes it appear as -// if each one were independent. -template -class CFX_SharedCopyOnWrite { - public: - CFX_SharedCopyOnWrite() {} - CFX_SharedCopyOnWrite(const CFX_SharedCopyOnWrite& other) - : m_pObject(other.m_pObject) {} - ~CFX_SharedCopyOnWrite() {} - - template - ObjClass* Emplace(Args... params) { - m_pObject.Reset(new CountedObj(params...)); - return m_pObject.Get(); - } - - CFX_SharedCopyOnWrite& operator=(const CFX_SharedCopyOnWrite& that) { - if (*this != that) - m_pObject = that.m_pObject; - return *this; - } - - void SetNull() { m_pObject.Reset(); } - const ObjClass* GetObject() const { return m_pObject.Get(); } - - template - ObjClass* GetPrivateCopy(Args... params) { - if (!m_pObject) - return Emplace(params...); - if (!m_pObject->HasOneRef()) - m_pObject.Reset(new CountedObj(*m_pObject)); - return m_pObject.Get(); - } - - bool operator==(const CFX_SharedCopyOnWrite& that) const { - return m_pObject == that.m_pObject; - } - bool operator!=(const CFX_SharedCopyOnWrite& that) const { - return !(*this == that); - } - explicit operator bool() const { return !!m_pObject; } - - private: - class CountedObj : public ObjClass { - public: - template - // NOLINTNEXTLINE(runtime/explicit) - CountedObj(Args... params) : ObjClass(params...), m_RefCount(0) {} - - CountedObj(const CountedObj& src) : ObjClass(src), m_RefCount(0) {} - ~CountedObj() { m_RefCount = 0; } - - bool HasOneRef() const { return m_RefCount == 1; } - void Retain() { m_RefCount++; } - void Release() { - ASSERT(m_RefCount); - if (--m_RefCount == 0) - delete this; - } - - private: - // To ensure ref counts do not overflow, consider the worst possible case: - // the entire address space contains nothing but pointers to this object. - // Since the count increments with each new pointer, the largest value is - // the number of pointers that can fit into the address space. The size of - // the address space itself is a good upper bound on it. - intptr_t m_RefCount; - }; - - CFX_RetainPtr m_pObject; -}; - -#endif // CORE_FXCRT_CFX_SHARED_COPY_ON_WRITE_H_ diff --git a/core/fxcrt/cfx_shared_copy_on_write_unittest.cpp b/core/fxcrt/cfx_shared_copy_on_write_unittest.cpp deleted file mode 100644 index b0205d899bcd698ac4d50391349d7b4d025f4a23..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_shared_copy_on_write_unittest.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/cfx_shared_copy_on_write.h" - -#include -#include - -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class Observer { - public: - void OnConstruct(const std::string& name) { construction_counts_[name]++; } - void OnDestruct(const std::string& name) { destruction_counts_[name]++; } - int GetConstructionCount(const std::string& name) { - return construction_counts_[name]; - } - int GetDestructionCount(const std::string& name) { - return destruction_counts_[name]; - } - - private: - std::map construction_counts_; - std::map destruction_counts_; -}; - -class Object { - public: - Object(Observer* observer, const std::string& name) - : name_(name), observer_(observer) { - observer->OnConstruct(name_); - } - Object(const Object& that) : name_(that.name_), observer_(that.observer_) { - observer_->OnConstruct(name_); - } - ~Object() { observer_->OnDestruct(name_); } - - private: - std::string name_; - Observer* observer_; -}; - -} // namespace - -TEST(fxcrt, SharedCopyOnWriteNull) { - Observer observer; - { - CFX_SharedCopyOnWrite ptr; - EXPECT_EQ(nullptr, ptr.GetObject()); - } -} - -TEST(fxcrt, SharedCopyOnWriteCopy) { - Observer observer; - { - CFX_SharedCopyOnWrite ptr1; - ptr1.Emplace(&observer, std::string("one")); - { - CFX_SharedCopyOnWrite ptr2 = ptr1; - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - } - { - CFX_SharedCopyOnWrite ptr3(ptr1); - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - } - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - } - EXPECT_EQ(1, observer.GetDestructionCount("one")); -} - -TEST(fxcrt, SharedCopyOnWriteAssignOverOld) { - Observer observer; - { - CFX_SharedCopyOnWrite ptr1; - ptr1.Emplace(&observer, std::string("one")); - ptr1.Emplace(&observer, std::string("two")); - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(1, observer.GetConstructionCount("two")); - EXPECT_EQ(1, observer.GetDestructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("two")); - } - EXPECT_EQ(1, observer.GetDestructionCount("two")); -} - -TEST(fxcrt, SharedCopyOnWriteAssignOverRetained) { - Observer observer; - { - CFX_SharedCopyOnWrite ptr1; - ptr1.Emplace(&observer, std::string("one")); - CFX_SharedCopyOnWrite ptr2(ptr1); - ptr1.Emplace(&observer, std::string("two")); - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(1, observer.GetConstructionCount("two")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("two")); - } - EXPECT_EQ(1, observer.GetDestructionCount("one")); - EXPECT_EQ(1, observer.GetDestructionCount("two")); -} - -TEST(fxcrt, SharedCopyOnWriteGetModify) { - Observer observer; - { - CFX_SharedCopyOnWrite ptr; - EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one"))); - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - - EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one"))); - EXPECT_EQ(1, observer.GetConstructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - { - CFX_SharedCopyOnWrite other(ptr); - EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one"))); - EXPECT_EQ(2, observer.GetConstructionCount("one")); - EXPECT_EQ(0, observer.GetDestructionCount("one")); - } - EXPECT_EQ(2, observer.GetConstructionCount("one")); - EXPECT_EQ(1, observer.GetDestructionCount("one")); - } - EXPECT_EQ(2, observer.GetDestructionCount("one")); -} diff --git a/core/fxcrt/cfx_string_c_template.h b/core/fxcrt/cfx_string_c_template.h deleted file mode 100644 index 3bfcc915fb36b6d2f63e3e6c246f015bee94b1c7..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_string_c_template.h +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2016 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 CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ -#define CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ - -#include -#include - -#include "core/fxcrt/fx_system.h" - -// An immutable string with caller-provided storage which must outlive the -// string itself. These are not necessarily nul-terminated, so that substring -// extraction (via the Mid(), Left(), and Right() methods) is copy-free. -template -class CFX_StringCTemplate { - public: - using CharType = T; - using UnsignedType = typename std::make_unsigned::type; - - CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {} - - // Deliberately implicit to avoid calling on every string literal. - // NOLINTNEXTLINE(runtime/explicit) - CFX_StringCTemplate(const CharType* ptr) - : m_Ptr(reinterpret_cast(ptr)), - m_Length(ptr ? FXSYS_len(ptr) : 0) {} - - CFX_StringCTemplate(const CharType* ptr, FX_STRSIZE len) - : m_Ptr(reinterpret_cast(ptr)), - m_Length(len == -1 ? FXSYS_len(ptr) : len) {} - - template - CFX_StringCTemplate( - const UnsignedType* ptr, - FX_STRSIZE size, - typename std::enable_if::value>::type* = 0) - : m_Ptr(ptr), m_Length(size) {} - - // Deliberately implicit to avoid calling on every string literal. - // |ch| must be an lvalue that outlives the the CFX_StringCTemplate. - // NOLINTNEXTLINE(runtime/explicit) - CFX_StringCTemplate(CharType& ch) { - m_Ptr = reinterpret_cast(&ch); - m_Length = 1; - } - - CFX_StringCTemplate(const CFX_StringCTemplate& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - } - - CFX_StringCTemplate& operator=(const CharType* src) { - m_Ptr = reinterpret_cast(src); - m_Length = src ? FXSYS_len(src) : 0; - return *this; - } - - CFX_StringCTemplate& operator=(const CFX_StringCTemplate& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - return *this; - } - - bool operator==(const CharType* ptr) const { - return FXSYS_len(ptr) == m_Length && - FXSYS_cmp(ptr, reinterpret_cast(m_Ptr), m_Length) == - 0; - } - bool operator==(const CFX_StringCTemplate& other) const { - return other.m_Length == m_Length && - FXSYS_cmp(reinterpret_cast(other.m_Ptr), - reinterpret_cast(m_Ptr), m_Length) == 0; - } - bool operator!=(const CharType* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_StringCTemplate& other) const { - return !(*this == other); - } - - uint32_t GetID(FX_STRSIZE start_pos = 0) const { - if (m_Length == 0 || start_pos < 0 || start_pos >= m_Length) - return 0; - - uint32_t strid = 0; - FX_STRSIZE size = std::min(4, m_Length - start_pos); - for (FX_STRSIZE i = 0; i < size; i++) - strid = strid * 256 + m_Ptr[start_pos + i]; - - return strid << ((4 - size) * 8); - } - - const UnsignedType* raw_str() const { return m_Ptr; } - const CharType* c_str() const { - return reinterpret_cast(m_Ptr); - } - - FX_STRSIZE GetLength() const { return m_Length; } - bool IsEmpty() const { return m_Length == 0; } - - UnsignedType GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } - CharType CharAt(FX_STRSIZE index) const { - return static_cast(m_Ptr[index]); - } - - FX_STRSIZE Find(CharType ch) const { - const UnsignedType* found = reinterpret_cast( - FXSYS_chr(reinterpret_cast(m_Ptr), ch, m_Length)); - return found ? found - m_Ptr : -1; - } - - CFX_StringCTemplate Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { - index = std::max(0, index); - if (index > m_Length) - return CFX_StringCTemplate(); - - if (count < 0 || count > m_Length - index) - count = m_Length - index; - - return CFX_StringCTemplate(m_Ptr + index, count); - } - - CFX_StringCTemplate Left(FX_STRSIZE count) const { - if (count <= 0) - return CFX_StringCTemplate(); - - return CFX_StringCTemplate(m_Ptr, std::min(count, m_Length)); - } - - CFX_StringCTemplate Right(FX_STRSIZE count) const { - if (count <= 0) - return CFX_StringCTemplate(); - - count = std::min(count, m_Length); - return CFX_StringCTemplate(m_Ptr + m_Length - count, count); - } - - const UnsignedType& operator[](size_t index) const { return m_Ptr[index]; } - - bool operator<(const CFX_StringCTemplate& that) const { - int result = FXSYS_cmp(reinterpret_cast(m_Ptr), - reinterpret_cast(that.m_Ptr), - std::min(m_Length, that.m_Length)); - return result < 0 || (result == 0 && m_Length < that.m_Length); - } - - protected: - const UnsignedType* m_Ptr; - FX_STRSIZE m_Length; - - private: - void* operator new(size_t) throw() { return nullptr; } -}; - -template -inline bool operator==(const T* lhs, const CFX_StringCTemplate& rhs) { - return rhs == lhs; -} - -template -inline bool operator!=(const T* lhs, const CFX_StringCTemplate& rhs) { - return rhs != lhs; -} - -extern template class CFX_StringCTemplate; -extern template class CFX_StringCTemplate; - -#endif // CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ diff --git a/core/fxcrt/cfx_string_data_template.h b/core/fxcrt/cfx_string_data_template.h deleted file mode 100644 index c3e090fef0c8431aa54467c77ae1bc996521db9a..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_string_data_template.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2016 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 CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_ -#define CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_ - -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" -#include "third_party/base/numerics/safe_math.h" - -template -class CFX_StringDataTemplate { - public: - static CFX_StringDataTemplate* Create(FX_STRSIZE nLen) { - ASSERT(nLen > 0); - - // Calculate space needed for the fixed portion of the struct plus the - // NUL char that is not included in |m_nAllocLength|. - int overhead = - offsetof(CFX_StringDataTemplate, m_String) + sizeof(CharType); - pdfium::base::CheckedNumeric nSize = nLen; - nSize *= sizeof(CharType); - nSize += overhead; - - // Now round to an 8-byte boundary. We'd expect that this is the minimum - // granularity of any of the underlying allocators, so there may be cases - // where we can save a re-alloc when adding a few characters to a string - // by using this otherwise wasted space. - nSize += 7; - nSize &= ~7; - int totalSize = nSize.ValueOrDie(); - int usableLen = (totalSize - overhead) / sizeof(CharType); - ASSERT(usableLen >= nLen); - - void* pData = FX_Alloc(uint8_t, totalSize); - return new (pData) CFX_StringDataTemplate(nLen, usableLen); - } - - static CFX_StringDataTemplate* Create(const CFX_StringDataTemplate& other) { - CFX_StringDataTemplate* result = Create(other.m_nDataLength); - result->CopyContents(other); - return result; - } - - static CFX_StringDataTemplate* Create(const CharType* pStr, FX_STRSIZE nLen) { - CFX_StringDataTemplate* result = Create(nLen); - result->CopyContents(pStr, nLen); - return result; - } - - void Retain() { ++m_nRefs; } - void Release() { - if (--m_nRefs <= 0) - FX_Free(this); - } - - bool CanOperateInPlace(FX_STRSIZE nTotalLen) const { - return m_nRefs <= 1 && nTotalLen <= m_nAllocLength; - } - - void CopyContents(const CFX_StringDataTemplate& other) { - ASSERT(other.m_nDataLength <= m_nAllocLength); - FXSYS_memcpy(m_String, other.m_String, - (other.m_nDataLength + 1) * sizeof(CharType)); - } - - void CopyContents(const CharType* pStr, FX_STRSIZE nLen) { - ASSERT(nLen >= 0 && nLen <= m_nAllocLength); - FXSYS_memcpy(m_String, pStr, nLen * sizeof(CharType)); - m_String[nLen] = 0; - } - - void CopyContentsAt(FX_STRSIZE offset, - const CharType* pStr, - FX_STRSIZE nLen) { - ASSERT(offset >= 0 && nLen >= 0 && offset + nLen <= m_nAllocLength); - FXSYS_memcpy(m_String + offset, pStr, nLen * sizeof(CharType)); - m_String[offset + nLen] = 0; - } - - // To ensure ref counts do not overflow, consider the worst possible case: - // the entire address space contains nothing but pointers to this object. - // Since the count increments with each new pointer, the largest value is - // the number of pointers that can fit into the address space. The size of - // the address space itself is a good upper bound on it. - intptr_t m_nRefs; - - // |FX_STRSIZE| is currently typedef'd as |int|. - // TODO(palmer): It should be a |size_t|, or at least unsigned. - // These lengths are in terms of number of characters, not bytes, and do not - // include the terminating NUL character, but the underlying buffer is sized - // to be capable of holding it. - FX_STRSIZE m_nDataLength; - FX_STRSIZE m_nAllocLength; - - // Not really 1, variable size. - CharType m_String[1]; - - private: - CFX_StringDataTemplate(FX_STRSIZE dataLen, FX_STRSIZE allocLen) - : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) { - ASSERT(dataLen >= 0); - ASSERT(dataLen <= allocLen); - m_String[dataLen] = 0; - } - - ~CFX_StringDataTemplate() = delete; -}; - -extern template class CFX_StringDataTemplate; -extern template class CFX_StringDataTemplate; - -#endif // CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_ diff --git a/core/fxcrt/cfx_string_pool_template.h b/core/fxcrt/cfx_string_pool_template.h deleted file mode 100644 index bfc1ce4bfb64a84fd46b3e14bc48a2315c6fb4c4..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_string_pool_template.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 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 CORE_FXCRT_CFX_STRING_POOL_TEMPLATE_H_ -#define CORE_FXCRT_CFX_STRING_POOL_TEMPLATE_H_ - -#include - -#include "core/fxcrt/fx_string.h" - -template -class CFX_StringPoolTemplate { - public: - StringType Intern(const StringType& str) { return *m_Pool.insert(str).first; } - void Clear() { m_Pool.clear(); } - - private: - std::unordered_set m_Pool; -}; - -using CFX_ByteStringPool = CFX_StringPoolTemplate; -using CFX_WideStringPool = CFX_StringPoolTemplate; - -extern template class CFX_StringPoolTemplate; -extern template class CFX_StringPoolTemplate; - -#endif // CORE_FXCRT_CFX_STRING_POOL_TEMPLATE_H_ diff --git a/core/fxcrt/cfx_string_pool_template_unittest.cpp b/core/fxcrt/cfx_string_pool_template_unittest.cpp deleted file mode 100644 index d0f5fbe96d1e5c85bb6244f60e10d67aaa0a9af6..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_string_pool_template_unittest.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/fx_string.h" -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fxcrt, ByteStringPool) { - CFX_ByteStringPool pool; - - CFX_ByteString null1; - CFX_ByteString null2; - CFX_ByteString goats1("goats"); - CFX_ByteString goats2("goats"); - - // Underlying storage, if non-null, is not shared. - EXPECT_EQ(nullptr, null1.m_pData.Get()); - EXPECT_EQ(nullptr, null2.m_pData.Get()); - EXPECT_NE(goats1.m_pData, goats2.m_pData); - - CFX_ByteString interned_null1 = pool.Intern(null1); - CFX_ByteString interned_null2 = pool.Intern(null2); - CFX_ByteString interned_goats1 = pool.Intern(goats1); - CFX_ByteString interned_goats2 = pool.Intern(goats2); - - // Strings are logically equal after being interned. - EXPECT_EQ(null1, interned_null1); - EXPECT_EQ(null2, interned_null2); - EXPECT_EQ(goats1, interned_goats1); - EXPECT_EQ(goats2, interned_goats2); - - // Interned underlying storage, if non-null, belongs to first seen. - EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); - EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); - EXPECT_EQ(goats1.m_pData, interned_goats1.m_pData); - EXPECT_EQ(goats1.m_pData, interned_goats2.m_pData); - - pool.Clear(); - CFX_ByteString reinterned_null2 = pool.Intern(null2); - CFX_ByteString reinterned_null1 = pool.Intern(null2); - CFX_ByteString reinterned_goats2 = pool.Intern(goats2); - CFX_ByteString reinterned_goats1 = pool.Intern(goats2); - - // After clearing pool, storage was re-interned using second strings. - EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); - EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); - EXPECT_EQ(goats2.m_pData, reinterned_goats1.m_pData); - EXPECT_EQ(goats2.m_pData, reinterned_goats2.m_pData); -} - -TEST(fxcrt, WideStringPool) { - CFX_WideStringPool pool; - - CFX_WideString null1; - CFX_WideString null2; - CFX_WideString goats1(L"goats"); - CFX_WideString goats2(L"goats"); - - // Underlying storage, if non-null, is not shared. - EXPECT_EQ(nullptr, null1.m_pData.Get()); - EXPECT_EQ(nullptr, null2.m_pData.Get()); - EXPECT_NE(goats1.m_pData, goats2.m_pData); - - CFX_WideString interned_null1 = pool.Intern(null1); - CFX_WideString interned_null2 = pool.Intern(null2); - CFX_WideString interned_goats1 = pool.Intern(goats1); - CFX_WideString interned_goats2 = pool.Intern(goats2); - - // Strings are logically equal after being interned. - EXPECT_EQ(null1, interned_null1); - EXPECT_EQ(null2, interned_null2); - EXPECT_EQ(goats1, interned_goats1); - EXPECT_EQ(goats2, interned_goats2); - - // Interned underlying storage, if non-null, belongs to first seen. - EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); - EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); - EXPECT_EQ(goats1.m_pData, interned_goats1.m_pData); - EXPECT_EQ(goats1.m_pData, interned_goats2.m_pData); - - pool.Clear(); - CFX_WideString reinterned_null2 = pool.Intern(null2); - CFX_WideString reinterned_null1 = pool.Intern(null2); - CFX_WideString reinterned_goats2 = pool.Intern(goats2); - CFX_WideString reinterned_goats1 = pool.Intern(goats2); - - // After clearing pool, storage was re-interned using second strings. - EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); - EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); - EXPECT_EQ(goats2.m_pData, reinterned_goats1.m_pData); - EXPECT_EQ(goats2.m_pData, reinterned_goats2.m_pData); -} diff --git a/core/fxcrt/cfx_utf8decoder.cpp b/core/fxcrt/cfx_utf8decoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bee5e16da4a2ecc5a7e3ebeda7e0314456b56587 --- /dev/null +++ b/core/fxcrt/cfx_utf8decoder.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_utf8decoder.h" + +void CFX_UTF8Decoder::Clear() { + m_Buffer.Clear(); + m_PendingBytes = 0; +} + +void CFX_UTF8Decoder::AppendCodePoint(uint32_t ch) { + m_Buffer.AppendChar(static_cast(ch)); +} + +void CFX_UTF8Decoder::Input(uint8_t byte) { + if (byte < 0x80) { + m_PendingBytes = 0; + m_Buffer.AppendChar(byte); + } else if (byte < 0xc0) { + if (m_PendingBytes == 0) { + return; + } + m_PendingBytes--; + m_PendingChar |= (byte & 0x3f) << (m_PendingBytes * 6); + if (m_PendingBytes == 0) { + AppendCodePoint(m_PendingChar); + } + } else if (byte < 0xe0) { + m_PendingBytes = 1; + m_PendingChar = (byte & 0x1f) << 6; + } else if (byte < 0xf0) { + m_PendingBytes = 2; + m_PendingChar = (byte & 0x0f) << 12; + } else if (byte < 0xf8) { + m_PendingBytes = 3; + m_PendingChar = (byte & 0x07) << 18; + } else if (byte < 0xfc) { + m_PendingBytes = 4; + m_PendingChar = (byte & 0x03) << 24; + } else if (byte < 0xfe) { + m_PendingBytes = 5; + m_PendingChar = (byte & 0x01) << 30; + } +} diff --git a/core/fxcrt/cfx_utf8decoder.h b/core/fxcrt/cfx_utf8decoder.h new file mode 100644 index 0000000000000000000000000000000000000000..1cafbe4472b1183f9356f8c39e1df280fcc59468 --- /dev/null +++ b/core/fxcrt/cfx_utf8decoder.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_UTF8DECODER_H_ +#define CORE_FXCRT_CFX_UTF8DECODER_H_ + +#include "core/fxcrt/cfx_widetextbuf.h" + +class CFX_UTF8Decoder { + public: + CFX_UTF8Decoder() { m_PendingBytes = 0; } + + void Clear(); + void Input(uint8_t byte); + void AppendCodePoint(uint32_t ch); + void ClearStatus() { m_PendingBytes = 0; } + WideStringView GetResult() const { return m_Buffer.AsStringView(); } + + private: + int m_PendingBytes; + uint32_t m_PendingChar; + CFX_WideTextBuf m_Buffer; +}; + +#endif // CORE_FXCRT_CFX_UTF8DECODER_H_ diff --git a/core/fxcrt/cfx_weak_ptr.h b/core/fxcrt/cfx_weak_ptr.h deleted file mode 100644 index 43ae5b881d47dc54ecdd737895b26102bf8cb93d..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_weak_ptr.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2016 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 CORE_FXCRT_CFX_WEAK_PTR_H_ -#define CORE_FXCRT_CFX_WEAK_PTR_H_ - -#include -#include -#include - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_system.h" - -template > -class CFX_WeakPtr { - public: - CFX_WeakPtr() {} - CFX_WeakPtr(const CFX_WeakPtr& that) : m_pHandle(that.m_pHandle) {} - CFX_WeakPtr(CFX_WeakPtr&& that) { Swap(that); } - explicit CFX_WeakPtr(std::unique_ptr pObj) - : m_pHandle(new Handle(std::move(pObj))) {} - - // Deliberately implicit to allow passing nullptr. - // NOLINTNEXTLINE(runtime/explicit) - CFX_WeakPtr(std::nullptr_t arg) {} - - explicit operator bool() const { return m_pHandle && !!m_pHandle->Get(); } - bool HasOneRef() const { return m_pHandle && m_pHandle->HasOneRef(); } - T* operator->() { return m_pHandle->Get(); } - const T* operator->() const { return m_pHandle->Get(); } - CFX_WeakPtr& operator=(const CFX_WeakPtr& that) { - m_pHandle = that.m_pHandle; - return *this; - } - bool operator==(const CFX_WeakPtr& that) const { - return m_pHandle == that.m_pHandle; - } - bool operator!=(const CFX_WeakPtr& that) const { return !(*this == that); } - - T* Get() const { return m_pHandle ? m_pHandle->Get() : nullptr; } - void DeleteObject() { - if (m_pHandle) { - m_pHandle->Clear(); - m_pHandle.Reset(); - } - } - void Reset() { m_pHandle.Reset(); } - void Reset(std::unique_ptr pObj) { - m_pHandle.Reset(new Handle(std::move(pObj))); - } - void Swap(CFX_WeakPtr& that) { m_pHandle.Swap(that.m_pHandle); } - - private: - class Handle { - public: - explicit Handle(std::unique_ptr ptr) - : m_nCount(0), m_pObj(std::move(ptr)) {} - void Reset(std::unique_ptr ptr) { m_pObj = std::move(ptr); } - void Clear() { // Now you're all weak ptrs ... - m_pObj.reset(); // unique_ptr nulls first before invoking delete. - } - T* Get() const { return m_pObj.get(); } - T* Retain() { - ++m_nCount; - return m_pObj.get(); - } - void Release() { - if (--m_nCount == 0) - delete this; - } - bool HasOneRef() const { return m_nCount == 1; } - - private: - ~Handle() {} - - intptr_t m_nCount; - std::unique_ptr m_pObj; - }; - - CFX_RetainPtr m_pHandle; -}; - -#endif // CORE_FXCRT_CFX_WEAK_PTR_H_ diff --git a/core/fxcrt/cfx_weak_ptr_unittest.cpp b/core/fxcrt/cfx_weak_ptr_unittest.cpp deleted file mode 100644 index 47f63c35b240e6d24ea3c2615bfedb3b795e299b..0000000000000000000000000000000000000000 --- a/core/fxcrt/cfx_weak_ptr_unittest.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/cfx_weak_ptr.h" - -#include -#include - -#include "core/fxcrt/fx_memory.h" -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class PseudoDeletable; -using WeakPtr = CFX_WeakPtr>; -using UniquePtr = - std::unique_ptr>; - -class PseudoDeletable { - public: - PseudoDeletable() : delete_count_(0) {} - void Release() { - ++delete_count_; - next_.Reset(); - } - void SetNext(const WeakPtr& next) { next_ = next; } - int delete_count() const { return delete_count_; } - - private: - int delete_count_; - WeakPtr next_; -}; - -} // namespace - -TEST(fxcrt, WeakPtrNull) { - WeakPtr ptr1; - EXPECT_FALSE(ptr1); - - WeakPtr ptr2; - EXPECT_TRUE(ptr1 == ptr2); - EXPECT_FALSE(ptr1 != ptr2); - - WeakPtr ptr3(ptr1); - EXPECT_TRUE(ptr1 == ptr3); - EXPECT_FALSE(ptr1 != ptr3); - - WeakPtr ptr4 = ptr1; - EXPECT_TRUE(ptr1 == ptr4); - EXPECT_FALSE(ptr1 != ptr4); -} - -TEST(fxcrt, WeakPtrNonNull) { - PseudoDeletable thing; - EXPECT_EQ(0, thing.delete_count()); - { - UniquePtr unique(&thing); - WeakPtr ptr1(std::move(unique)); - EXPECT_TRUE(ptr1); - EXPECT_EQ(&thing, ptr1.Get()); - - WeakPtr ptr2; - EXPECT_FALSE(ptr1 == ptr2); - EXPECT_TRUE(ptr1 != ptr2); - { - WeakPtr ptr3(ptr1); - EXPECT_TRUE(ptr1 == ptr3); - EXPECT_FALSE(ptr1 != ptr3); - EXPECT_EQ(&thing, ptr3.Get()); - { - WeakPtr ptr4 = ptr1; - EXPECT_TRUE(ptr1 == ptr4); - EXPECT_FALSE(ptr1 != ptr4); - EXPECT_EQ(&thing, ptr4.Get()); - } - } - EXPECT_EQ(0, thing.delete_count()); - } - EXPECT_EQ(1, thing.delete_count()); -} - -TEST(fxcrt, WeakPtrResetNull) { - PseudoDeletable thing; - { - UniquePtr unique(&thing); - WeakPtr ptr1(std::move(unique)); - WeakPtr ptr2 = ptr1; - ptr1.Reset(); - EXPECT_FALSE(ptr1); - EXPECT_EQ(nullptr, ptr1.Get()); - EXPECT_TRUE(ptr2); - EXPECT_EQ(&thing, ptr2.Get()); - EXPECT_FALSE(ptr1 == ptr2); - EXPECT_TRUE(ptr1 != ptr2); - EXPECT_EQ(0, thing.delete_count()); - } - EXPECT_EQ(1, thing.delete_count()); -} - -TEST(fxcrt, WeakPtrResetNonNull) { - PseudoDeletable thing1; - PseudoDeletable thing2; - { - UniquePtr unique1(&thing1); - WeakPtr ptr1(std::move(unique1)); - WeakPtr ptr2 = ptr1; - UniquePtr unique2(&thing2); - ptr2.Reset(std::move(unique2)); - EXPECT_TRUE(ptr1); - EXPECT_EQ(&thing1, ptr1.Get()); - EXPECT_TRUE(ptr2); - EXPECT_EQ(&thing2, ptr2.Get()); - EXPECT_FALSE(ptr1 == ptr2); - EXPECT_TRUE(ptr1 != ptr2); - EXPECT_EQ(0, thing1.delete_count()); - EXPECT_EQ(0, thing2.delete_count()); - } - EXPECT_EQ(1, thing1.delete_count()); - EXPECT_EQ(1, thing2.delete_count()); -} - -TEST(fxcrt, WeakPtrDeleteObject) { - PseudoDeletable thing; - { - UniquePtr unique(&thing); - WeakPtr ptr1(std::move(unique)); - WeakPtr ptr2 = ptr1; - ptr1.DeleteObject(); - EXPECT_FALSE(ptr1); - EXPECT_EQ(nullptr, ptr1.Get()); - EXPECT_FALSE(ptr2); - EXPECT_EQ(nullptr, ptr2.Get()); - EXPECT_FALSE(ptr1 == ptr2); - EXPECT_TRUE(ptr1 != ptr2); - EXPECT_EQ(1, thing.delete_count()); - } - EXPECT_EQ(1, thing.delete_count()); -} - -TEST(fxcrt, WeakPtrCyclic) { - PseudoDeletable thing1; - PseudoDeletable thing2; - { - UniquePtr unique1(&thing1); - UniquePtr unique2(&thing2); - WeakPtr ptr1(std::move(unique1)); - WeakPtr ptr2(std::move(unique2)); - ptr1->SetNext(ptr2); - ptr2->SetNext(ptr1); - } - // Leaks without explicit clear. - EXPECT_EQ(0, thing1.delete_count()); - EXPECT_EQ(0, thing2.delete_count()); -} - -TEST(fxcrt, WeakPtrCyclicDeleteObject) { - PseudoDeletable thing1; - PseudoDeletable thing2; - { - UniquePtr unique1(&thing1); - UniquePtr unique2(&thing2); - WeakPtr ptr1(std::move(unique1)); - WeakPtr ptr2(std::move(unique2)); - ptr1->SetNext(ptr2); - ptr2->SetNext(ptr1); - ptr1.DeleteObject(); - EXPECT_EQ(1, thing1.delete_count()); - EXPECT_EQ(0, thing2.delete_count()); - } - EXPECT_EQ(1, thing1.delete_count()); - EXPECT_EQ(1, thing2.delete_count()); -} diff --git a/core/fxcrt/cfx_widetextbuf.cpp b/core/fxcrt/cfx_widetextbuf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9b59b5ff8dd9487a85c58c15c4ec8f1df11a363 --- /dev/null +++ b/core/fxcrt/cfx_widetextbuf.cpp @@ -0,0 +1,62 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/cfx_widetextbuf.h" + +size_t CFX_WideTextBuf::GetLength() const { + return m_DataSize / sizeof(wchar_t); +} + +void CFX_WideTextBuf::AppendChar(wchar_t ch) { + ExpandBuf(sizeof(wchar_t)); + *(wchar_t*)(m_pBuffer.get() + m_DataSize) = ch; + m_DataSize += sizeof(wchar_t); +} + +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const WideStringView& str) { + AppendBlock(str.unterminated_c_str(), str.GetLength() * sizeof(wchar_t)); + return *this; +} + +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const WideString& str) { + AppendBlock(str.c_str(), str.GetLength() * sizeof(wchar_t)); + return *this; +} + +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(int i) { + char buf[32]; + FXSYS_itoa(i, buf, 10); + size_t len = strlen(buf); + ExpandBuf(len * sizeof(wchar_t)); + wchar_t* str = (wchar_t*)(m_pBuffer.get() + m_DataSize); + for (size_t j = 0; j < len; j++) { + *str++ = buf[j]; + } + m_DataSize += len * sizeof(wchar_t); + return *this; +} + +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(double f) { + char buf[32]; + size_t len = FX_ftoa((float)f, buf); + ExpandBuf(len * sizeof(wchar_t)); + wchar_t* str = (wchar_t*)(m_pBuffer.get() + m_DataSize); + for (size_t i = 0; i < len; i++) { + *str++ = buf[i]; + } + m_DataSize += len * sizeof(wchar_t); + return *this; +} + +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const wchar_t* lpsz) { + AppendBlock(lpsz, wcslen(lpsz) * sizeof(wchar_t)); + return *this; +} + +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const CFX_WideTextBuf& buf) { + AppendBlock(buf.m_pBuffer.get(), buf.m_DataSize); + return *this; +} diff --git a/core/fxcrt/cfx_widetextbuf.h b/core/fxcrt/cfx_widetextbuf.h new file mode 100644 index 0000000000000000000000000000000000000000..84553a3e59a06521a88c1e060afadabb6af71216 --- /dev/null +++ b/core/fxcrt/cfx_widetextbuf.h @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CFX_WIDETEXTBUF_H_ +#define CORE_FXCRT_CFX_WIDETEXTBUF_H_ + +#include "core/fxcrt/cfx_binarybuf.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" + +class CFX_WideTextBuf : public CFX_BinaryBuf { + public: + void AppendChar(wchar_t wch); + size_t GetLength() const override; + wchar_t* GetBuffer() const { + return reinterpret_cast(m_pBuffer.get()); + } + + WideStringView AsStringView() const { + return WideStringView(reinterpret_cast(m_pBuffer.get()), + m_DataSize / sizeof(wchar_t)); + } + WideString MakeString() const { + return WideString(reinterpret_cast(m_pBuffer.get()), + m_DataSize / sizeof(wchar_t)); + } + + void Delete(int start_index, int count) { + CFX_BinaryBuf::Delete(start_index * sizeof(wchar_t), + count * sizeof(wchar_t)); + } + + CFX_WideTextBuf& operator<<(int i); + CFX_WideTextBuf& operator<<(double f); + CFX_WideTextBuf& operator<<(const wchar_t* lpsz); + CFX_WideTextBuf& operator<<(const WideStringView& str); + CFX_WideTextBuf& operator<<(const WideString& str); + CFX_WideTextBuf& operator<<(const CFX_WideTextBuf& buf); +}; + +#endif // CORE_FXCRT_CFX_WIDETEXTBUF_H_ diff --git a/core/fxcrt/css/cfx_css.h b/core/fxcrt/css/cfx_css.h new file mode 100644 index 0000000000000000000000000000000000000000..7b1d7d3f995a37e9d426ba48ee4ec8ad818a5feb --- /dev/null +++ b/core/fxcrt/css/cfx_css.h @@ -0,0 +1,242 @@ +// 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 CORE_FXCRT_CSS_CFX_CSS_H_ +#define CORE_FXCRT_CSS_CFX_CSS_H_ + +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxge/fx_dib.h" + +enum CFX_CSSVALUETYPE { + CFX_CSSVALUETYPE_Primitive = 1 << 0, + CFX_CSSVALUETYPE_List = 1 << 1, + CFX_CSSVALUETYPE_Shorthand = 1 << 2, + // Note the values below this comment must be > 0x0F so we can mask the above. + CFX_CSSVALUETYPE_MaybeNumber = 1 << 4, + CFX_CSSVALUETYPE_MaybeEnum = 1 << 5, + CFX_CSSVALUETYPE_MaybeString = 1 << 7, + CFX_CSSVALUETYPE_MaybeColor = 1 << 8 +}; + +enum class CFX_CSSPrimitiveType : uint8_t { + Unknown = 0, + Number, + String, + RGB, + Enum, + Function, + List, +}; + +enum class CFX_CSSPropertyValue : uint8_t { + Bolder = 0, + None, + Dot, + Sub, + Top, + Right, + Normal, + Auto, + Text, + XSmall, + Thin, + Small, + Bottom, + Underline, + Double, + Lighter, + Oblique, + Super, + Center, + XxLarge, + Smaller, + Baseline, + Thick, + Justify, + Middle, + Medium, + ListItem, + XxSmall, + Bold, + SmallCaps, + Inline, + Overline, + TextBottom, + Larger, + InlineTable, + InlineBlock, + Blink, + Block, + Italic, + LineThrough, + XLarge, + Large, + Left, + TextTop, + LAST_MARKER +}; + +enum class CFX_CSSProperty : uint8_t { + BorderLeft = 0, + Top, + Margin, + TextIndent, + Right, + PaddingLeft, + MarginLeft, + Border, + BorderTop, + Bottom, + PaddingRight, + BorderBottom, + FontFamily, + FontWeight, + Color, + LetterSpacing, + TextAlign, + BorderRightWidth, + VerticalAlign, + PaddingTop, + FontVariant, + BorderWidth, + BorderBottomWidth, + BorderRight, + FontSize, + BorderSpacing, + FontStyle, + Font, + LineHeight, + MarginRight, + BorderLeftWidth, + Display, + PaddingBottom, + BorderTopWidth, + WordSpacing, + Left, + TextDecoration, + Padding, + MarginBottom, + MarginTop, + LAST_MARKER +}; + +enum class CFX_CSSSelectorType : uint8_t { Element = 0, Descendant }; + +enum class CFX_CSSLengthUnit : uint8_t { + Auto, + None, + Normal, + Point, + Percent, +}; + +enum class CFX_CSSDisplay : uint8_t { + None, + ListItem, + Block, + Inline, + InlineBlock, + InlineTable, +}; + +enum class CFX_CSSFontStyle : uint8_t { + Normal, + Italic, +}; + +enum class CFX_CSSTextAlign : uint8_t { + Left, + Right, + Center, + Justify, + JustifyAll, +}; + +enum class CFX_CSSVerticalAlign : uint8_t { + Baseline, + Sub, + Super, + Top, + TextTop, + Middle, + Bottom, + TextBottom, + Number, +}; + +enum class CFX_CSSFontVariant : uint8_t { + Normal, + SmallCaps, +}; + +enum CFX_CSSTEXTDECORATION { + CFX_CSSTEXTDECORATION_None = 0, + CFX_CSSTEXTDECORATION_Underline = 1 << 0, + CFX_CSSTEXTDECORATION_Overline = 1 << 1, + CFX_CSSTEXTDECORATION_LineThrough = 1 << 2, + CFX_CSSTEXTDECORATION_Blink = 1 << 3, + CFX_CSSTEXTDECORATION_Double = 1 << 4, +}; + +class CFX_CSSLength { + public: + CFX_CSSLength() {} + + explicit CFX_CSSLength(CFX_CSSLengthUnit eUnit) : m_unit(eUnit) {} + + CFX_CSSLength(CFX_CSSLengthUnit eUnit, float fValue) + : m_unit(eUnit), m_fValue(fValue) {} + + CFX_CSSLength& Set(CFX_CSSLengthUnit eUnit) { + m_unit = eUnit; + return *this; + } + + CFX_CSSLength& Set(CFX_CSSLengthUnit eUnit, float fValue) { + m_unit = eUnit; + m_fValue = fValue; + return *this; + } + + CFX_CSSLengthUnit GetUnit() const { return m_unit; } + + float GetValue() const { return m_fValue; } + bool NonZero() const { return static_cast(m_fValue) != 0; } + + private: + CFX_CSSLengthUnit m_unit; + float m_fValue; +}; + +class CFX_CSSRect { + public: + CFX_CSSRect() {} + + CFX_CSSRect(CFX_CSSLengthUnit eUnit, float val) + : left(eUnit, val), + top(eUnit, val), + right(eUnit, val), + bottom(eUnit, val) {} + + CFX_CSSRect& Set(CFX_CSSLengthUnit eUnit) { + left.Set(eUnit); + top.Set(eUnit); + right.Set(eUnit); + bottom.Set(eUnit); + return *this; + } + CFX_CSSRect& Set(CFX_CSSLengthUnit eUnit, float fValue) { + left.Set(eUnit, fValue); + top.Set(eUnit, fValue); + right.Set(eUnit, fValue); + bottom.Set(eUnit, fValue); + return *this; + } + + CFX_CSSLength left, top, right, bottom; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSS_H_ diff --git a/core/fxcrt/css/cfx_csscolorvalue.cpp b/core/fxcrt/css/cfx_csscolorvalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c5473b3297f4a53fd1633bf4cefdc4b256a3d43 --- /dev/null +++ b/core/fxcrt/css/cfx_csscolorvalue.cpp @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_csscolorvalue.h" + +CFX_CSSColorValue::CFX_CSSColorValue(FX_ARGB value) + : CFX_CSSValue(CFX_CSSPrimitiveType::RGB), value_(value) {} + +CFX_CSSColorValue::~CFX_CSSColorValue() {} diff --git a/core/fxcrt/css/cfx_csscolorvalue.h b/core/fxcrt/css/cfx_csscolorvalue.h new file mode 100644 index 0000000000000000000000000000000000000000..f59c0c5d3d83c3f5ec11a8cbd0510bc486cfa01e --- /dev/null +++ b/core/fxcrt/css/cfx_csscolorvalue.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSCOLORVALUE_H_ +#define CORE_FXCRT_CSS_CFX_CSSCOLORVALUE_H_ + +#include "core/fxcrt/css/cfx_cssvalue.h" + +class CFX_CSSColorValue : public CFX_CSSValue { + public: + explicit CFX_CSSColorValue(FX_ARGB color); + ~CFX_CSSColorValue() override; + + FX_ARGB Value() const { return value_; } + + private: + FX_ARGB value_; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSCOLORVALUE_H_ diff --git a/core/fxcrt/css/cfx_csscomputedstyle.cpp b/core/fxcrt/css/cfx_csscomputedstyle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aae88a364a42fcd376f138e83c0d427a2fb6cbca --- /dev/null +++ b/core/fxcrt/css/cfx_csscomputedstyle.cpp @@ -0,0 +1,195 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_csscomputedstyle.h" + +#include "core/fxcrt/css/cfx_cssstringvalue.h" +#include "core/fxcrt/css/cfx_cssvaluelist.h" +#include "third_party/base/stl_util.h" + +CFX_CSSComputedStyle::CFX_CSSComputedStyle() {} + +CFX_CSSComputedStyle::~CFX_CSSComputedStyle() {} + +bool CFX_CSSComputedStyle::GetCustomStyle(const WideString& wsName, + WideString& wsValue) const { + for (auto iter = m_CustomProperties.rbegin(); + iter != m_CustomProperties.rend(); iter++) { + if (wsName == iter->name()) { + wsValue = iter->value(); + return true; + } + } + return false; +} + +int32_t CFX_CSSComputedStyle::CountFontFamilies() const { + return m_InheritedData.m_pFontFamily + ? m_InheritedData.m_pFontFamily->CountValues() + : 0; +} + +const WideString CFX_CSSComputedStyle::GetFontFamily(int32_t index) const { + return m_InheritedData.m_pFontFamily->GetValue(index) + .As() + ->Value(); +} + +uint16_t CFX_CSSComputedStyle::GetFontWeight() const { + return m_InheritedData.m_wFontWeight; +} + +CFX_CSSFontVariant CFX_CSSComputedStyle::GetFontVariant() const { + return m_InheritedData.m_eFontVariant; +} + +CFX_CSSFontStyle CFX_CSSComputedStyle::GetFontStyle() const { + return m_InheritedData.m_eFontStyle; +} + +float CFX_CSSComputedStyle::GetFontSize() const { + return m_InheritedData.m_fFontSize; +} + +FX_ARGB CFX_CSSComputedStyle::GetColor() const { + return m_InheritedData.m_dwFontColor; +} + +void CFX_CSSComputedStyle::SetFontWeight(uint16_t wFontWeight) { + m_InheritedData.m_wFontWeight = wFontWeight; +} + +void CFX_CSSComputedStyle::SetFontVariant(CFX_CSSFontVariant eFontVariant) { + m_InheritedData.m_eFontVariant = eFontVariant; +} + +void CFX_CSSComputedStyle::SetFontStyle(CFX_CSSFontStyle eFontStyle) { + m_InheritedData.m_eFontStyle = eFontStyle; +} + +void CFX_CSSComputedStyle::SetFontSize(float fFontSize) { + m_InheritedData.m_fFontSize = fFontSize; +} + +void CFX_CSSComputedStyle::SetColor(FX_ARGB dwFontColor) { + m_InheritedData.m_dwFontColor = dwFontColor; +} + +const CFX_CSSRect* CFX_CSSComputedStyle::GetBorderWidth() const { + return m_NonInheritedData.m_bHasBorder ? &(m_NonInheritedData.m_BorderWidth) + : nullptr; +} + +const CFX_CSSRect* CFX_CSSComputedStyle::GetMarginWidth() const { + return m_NonInheritedData.m_bHasMargin ? &(m_NonInheritedData.m_MarginWidth) + : nullptr; +} + +const CFX_CSSRect* CFX_CSSComputedStyle::GetPaddingWidth() const { + return m_NonInheritedData.m_bHasPadding ? &(m_NonInheritedData.m_PaddingWidth) + : nullptr; +} + +void CFX_CSSComputedStyle::SetMarginWidth(const CFX_CSSRect& rect) { + m_NonInheritedData.m_MarginWidth = rect; + m_NonInheritedData.m_bHasMargin = true; +} + +void CFX_CSSComputedStyle::SetPaddingWidth(const CFX_CSSRect& rect) { + m_NonInheritedData.m_PaddingWidth = rect; + m_NonInheritedData.m_bHasPadding = true; +} + +CFX_CSSDisplay CFX_CSSComputedStyle::GetDisplay() const { + return m_NonInheritedData.m_eDisplay; +} + +float CFX_CSSComputedStyle::GetLineHeight() const { + return m_InheritedData.m_fLineHeight; +} + +const CFX_CSSLength& CFX_CSSComputedStyle::GetTextIndent() const { + return m_InheritedData.m_TextIndent; +} + +CFX_CSSTextAlign CFX_CSSComputedStyle::GetTextAlign() const { + return m_InheritedData.m_eTextAlign; +} + +CFX_CSSVerticalAlign CFX_CSSComputedStyle::GetVerticalAlign() const { + return m_NonInheritedData.m_eVerticalAlign; +} + +float CFX_CSSComputedStyle::GetNumberVerticalAlign() const { + return m_NonInheritedData.m_fVerticalAlign; +} + +uint32_t CFX_CSSComputedStyle::GetTextDecoration() const { + return m_NonInheritedData.m_dwTextDecoration; +} + +const CFX_CSSLength& CFX_CSSComputedStyle::GetLetterSpacing() const { + return m_InheritedData.m_LetterSpacing; +} + +void CFX_CSSComputedStyle::SetLineHeight(float fLineHeight) { + m_InheritedData.m_fLineHeight = fLineHeight; +} + +void CFX_CSSComputedStyle::SetTextIndent(const CFX_CSSLength& textIndent) { + m_InheritedData.m_TextIndent = textIndent; +} + +void CFX_CSSComputedStyle::SetTextAlign(CFX_CSSTextAlign eTextAlign) { + m_InheritedData.m_eTextAlign = eTextAlign; +} + +void CFX_CSSComputedStyle::SetNumberVerticalAlign(float fAlign) { + m_NonInheritedData.m_eVerticalAlign = CFX_CSSVerticalAlign::Number, + m_NonInheritedData.m_fVerticalAlign = fAlign; +} + +void CFX_CSSComputedStyle::SetTextDecoration(uint32_t dwTextDecoration) { + m_NonInheritedData.m_dwTextDecoration = dwTextDecoration; +} + +void CFX_CSSComputedStyle::SetLetterSpacing( + const CFX_CSSLength& letterSpacing) { + m_InheritedData.m_LetterSpacing = letterSpacing; +} + +void CFX_CSSComputedStyle::AddCustomStyle(const CFX_CSSCustomProperty& prop) { + // Force the property to be copied so we aren't dependent on the lifetime + // of whatever currently owns it. + m_CustomProperties.push_back(prop); +} + +CFX_CSSComputedStyle::InheritedData::InheritedData() + : m_LetterSpacing(CFX_CSSLengthUnit::Normal), + m_WordSpacing(CFX_CSSLengthUnit::Normal), + m_TextIndent(CFX_CSSLengthUnit::Point, 0), + m_pFontFamily(nullptr), + m_fFontSize(12.0f), + m_fLineHeight(14.0f), + m_dwFontColor(0xFF000000), + m_wFontWeight(400), + m_eFontVariant(CFX_CSSFontVariant::Normal), + m_eFontStyle(CFX_CSSFontStyle::Normal), + m_eTextAlign(CFX_CSSTextAlign::Left) {} + +CFX_CSSComputedStyle::InheritedData::~InheritedData() {} + +CFX_CSSComputedStyle::NonInheritedData::NonInheritedData() + : m_MarginWidth(CFX_CSSLengthUnit::Point, 0), + m_BorderWidth(CFX_CSSLengthUnit::Point, 0), + m_PaddingWidth(CFX_CSSLengthUnit::Point, 0), + m_fVerticalAlign(0.0f), + m_eDisplay(CFX_CSSDisplay::Inline), + m_eVerticalAlign(CFX_CSSVerticalAlign::Baseline), + m_dwTextDecoration(0), + m_bHasMargin(false), + m_bHasBorder(false), + m_bHasPadding(false) {} diff --git a/core/fxcrt/css/cfx_csscomputedstyle.h b/core/fxcrt/css/cfx_csscomputedstyle.h new file mode 100644 index 0000000000000000000000000000000000000000..4b44a6d87c0b3a15df016064af3959958f2d360e --- /dev/null +++ b/core/fxcrt/css/cfx_csscomputedstyle.h @@ -0,0 +1,109 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSCOMPUTEDSTYLE_H_ +#define CORE_FXCRT_CSS_CFX_CSSCOMPUTEDSTYLE_H_ + +#include + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_csscustomproperty.h" +#include "core/fxcrt/fx_string.h" + +class CFX_CSSValueList; + +class CFX_CSSComputedStyle : public Retainable { + public: + class InheritedData { + public: + InheritedData(); + ~InheritedData(); + + CFX_CSSLength m_LetterSpacing; + CFX_CSSLength m_WordSpacing; + CFX_CSSLength m_TextIndent; + RetainPtr m_pFontFamily; + float m_fFontSize; + float m_fLineHeight; + FX_ARGB m_dwFontColor; + uint16_t m_wFontWeight; + CFX_CSSFontVariant m_eFontVariant; + CFX_CSSFontStyle m_eFontStyle; + CFX_CSSTextAlign m_eTextAlign; + }; + + class NonInheritedData { + public: + NonInheritedData(); + + CFX_CSSRect m_MarginWidth; + CFX_CSSRect m_BorderWidth; + CFX_CSSRect m_PaddingWidth; + CFX_CSSLength m_Top; + CFX_CSSLength m_Bottom; + CFX_CSSLength m_Left; + CFX_CSSLength m_Right; + float m_fVerticalAlign; + CFX_CSSDisplay m_eDisplay; + CFX_CSSVerticalAlign m_eVerticalAlign; + uint8_t m_dwTextDecoration; + bool m_bHasMargin; + bool m_bHasBorder; + bool m_bHasPadding; + }; + + int32_t CountFontFamilies() const; + const WideString GetFontFamily(int32_t index) const; + uint16_t GetFontWeight() const; + CFX_CSSFontVariant GetFontVariant() const; + CFX_CSSFontStyle GetFontStyle() const; + float GetFontSize() const; + FX_ARGB GetColor() const; + void SetFontWeight(uint16_t wFontWeight); + void SetFontVariant(CFX_CSSFontVariant eFontVariant); + void SetFontStyle(CFX_CSSFontStyle eFontStyle); + void SetFontSize(float fFontSize); + void SetColor(FX_ARGB dwFontColor); + + const CFX_CSSRect* GetBorderWidth() const; + const CFX_CSSRect* GetMarginWidth() const; + const CFX_CSSRect* GetPaddingWidth() const; + void SetMarginWidth(const CFX_CSSRect& rect); + void SetPaddingWidth(const CFX_CSSRect& rect); + + CFX_CSSDisplay GetDisplay() const; + + float GetLineHeight() const; + const CFX_CSSLength& GetTextIndent() const; + CFX_CSSTextAlign GetTextAlign() const; + CFX_CSSVerticalAlign GetVerticalAlign() const; + float GetNumberVerticalAlign() const; + uint32_t GetTextDecoration() const; + const CFX_CSSLength& GetLetterSpacing() const; + void SetLineHeight(float fLineHeight); + void SetTextIndent(const CFX_CSSLength& textIndent); + void SetTextAlign(CFX_CSSTextAlign eTextAlign); + void SetNumberVerticalAlign(float fAlign); + void SetTextDecoration(uint32_t dwTextDecoration); + void SetLetterSpacing(const CFX_CSSLength& letterSpacing); + void AddCustomStyle(const CFX_CSSCustomProperty& prop); + + bool GetCustomStyle(const WideString& wsName, WideString& wsValue) const; + + InheritedData m_InheritedData; + NonInheritedData m_NonInheritedData; + + private: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + CFX_CSSComputedStyle(); + ~CFX_CSSComputedStyle() override; + + std::vector m_CustomProperties; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSCOMPUTEDSTYLE_H_ diff --git a/core/fxcrt/css/cfx_csscustomproperty.cpp b/core/fxcrt/css/cfx_csscustomproperty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..353facd5f0a3c30255ac937373533ff63acf5901 --- /dev/null +++ b/core/fxcrt/css/cfx_csscustomproperty.cpp @@ -0,0 +1,14 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/css/cfx_csscustomproperty.h" + +CFX_CSSCustomProperty::CFX_CSSCustomProperty(const WideString& name, + const WideString& value) + : name_(name), value_(value) {} + +CFX_CSSCustomProperty::CFX_CSSCustomProperty(const CFX_CSSCustomProperty& prop) + : name_(prop.name_), value_(prop.value_) {} + +CFX_CSSCustomProperty::~CFX_CSSCustomProperty() {} diff --git a/core/fxcrt/css/cfx_csscustomproperty.h b/core/fxcrt/css/cfx_csscustomproperty.h new file mode 100644 index 0000000000000000000000000000000000000000..15c3eca1241851fc2569604651a8d28053004062 --- /dev/null +++ b/core/fxcrt/css/cfx_csscustomproperty.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_ +#define CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_ + +#include "core/fxcrt/fx_string.h" + +class CFX_CSSCustomProperty { + public: + CFX_CSSCustomProperty(const WideString& name, const WideString& value); + CFX_CSSCustomProperty(const CFX_CSSCustomProperty& prop); + ~CFX_CSSCustomProperty(); + + WideString name() const { return name_; } + WideString value() const { return value_; } + + private: + WideString name_; + WideString value_; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_ diff --git a/core/fxcrt/css/cfx_cssdatatable.cpp b/core/fxcrt/css/cfx_cssdatatable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53617b6a480cb8448add1f515eb373c0f0fc62db --- /dev/null +++ b/core/fxcrt/css/cfx_cssdatatable.cpp @@ -0,0 +1,147 @@ +// 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 "core/fxcrt/css/cfx_cssdatatable.h" + +#include + +#include "core/fxcrt/css/cfx_cssstyleselector.h" +#include "core/fxcrt/css/cfx_cssvaluelistparser.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" + +static const CFX_CSSPropertyTable g_CFX_CSSProperties[] = { + {CFX_CSSProperty::BorderLeft, L"border-left", 0x04080036, + CFX_CSSVALUETYPE_Shorthand}, + {CFX_CSSProperty::Top, L"top", 0x0BEDAF33, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::Margin, L"margin", 0x0CB016BE, + CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::TextIndent, L"text-indent", 0x169ADB74, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::Right, L"right", 0x193ADE3E, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::PaddingLeft, L"padding-left", 0x228CF02F, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::MarginLeft, L"margin-left", 0x297C5656, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber | + CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::Border, L"border", 0x2A23349E, + CFX_CSSVALUETYPE_Shorthand}, + {CFX_CSSProperty::BorderTop, L"border-top", 0x2B866ADE, + CFX_CSSVALUETYPE_Shorthand}, + {CFX_CSSProperty::Bottom, L"bottom", 0x399F02B5, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::PaddingRight, L"padding-right", 0x3F616AC2, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::BorderBottom, L"border-bottom", 0x452CE780, + CFX_CSSVALUETYPE_Shorthand}, + {CFX_CSSProperty::FontFamily, L"font-family", 0x574686E6, + CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeString}, + {CFX_CSSProperty::FontWeight, L"font-weight", 0x6692F60C, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::Color, L"color", 0x6E67921F, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeColor}, + {CFX_CSSProperty::LetterSpacing, L"letter-spacing", 0x70536102, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::TextAlign, L"text-align", 0x7553F1BD, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::BorderRightWidth, L"border-right-width", 0x8F5A6036, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::VerticalAlign, L"vertical-align", 0x934A87D2, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::PaddingTop, L"padding-top", 0x959D22B7, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::FontVariant, L"font-variant", 0x9C785779, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::BorderWidth, L"border-width", 0xA8DE4FEB, + CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::BorderBottomWidth, L"border-bottom-width", 0xAE41204D, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::BorderRight, L"border-right", 0xB78E9EA9, + CFX_CSSVALUETYPE_Shorthand}, + {CFX_CSSProperty::FontSize, L"font-size", 0xB93956DF, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::BorderSpacing, L"border-spacing", 0xC72030F0, + CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::FontStyle, L"font-style", 0xCB1950F5, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::Font, L"font", 0xCD308B77, CFX_CSSVALUETYPE_Shorthand}, + {CFX_CSSProperty::LineHeight, L"line-height", 0xCFCACE2E, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::MarginRight, L"margin-right", 0xD13C58C9, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber | + CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::BorderLeftWidth, L"border-left-width", 0xD1E93D83, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::Display, L"display", 0xD4224C36, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::PaddingBottom, L"padding-bottom", 0xE555B3B9, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::BorderTopWidth, L"border-top-width", 0xED2CB62B, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::WordSpacing, L"word-spacing", 0xEDA63BAE, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::Left, L"left", 0xF5AD782B, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum | + CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::TextDecoration, L"text-decoration", 0xF7C634BA, + CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::Padding, L"padding", 0xF8C373F7, + CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeNumber}, + {CFX_CSSProperty::MarginBottom, L"margin-bottom", 0xF93485A0, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber | + CFX_CSSVALUETYPE_MaybeEnum}, + {CFX_CSSProperty::MarginTop, L"margin-top", 0xFE51DCFE, + CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber | + CFX_CSSVALUETYPE_MaybeEnum}, +}; +const int32_t g_iCSSPropertyCount = + sizeof(g_CFX_CSSProperties) / sizeof(CFX_CSSPropertyTable); +static_assert(g_iCSSPropertyCount == + static_cast(CFX_CSSProperty::LAST_MARKER), + "Property table differs in size from property enum"); + +const CFX_CSSPropertyTable* CFX_GetCSSPropertyByName( + const WideStringView& wsName) { + ASSERT(!wsName.IsEmpty()); + uint32_t dwHash = FX_HashCode_GetW(wsName, true); + int32_t iEnd = g_iCSSPropertyCount; + int32_t iMid, iStart = 0; + uint32_t dwMid; + do { + iMid = (iStart + iEnd) / 2; + dwMid = g_CFX_CSSProperties[iMid].dwHash; + if (dwHash == dwMid) { + return g_CFX_CSSProperties + iMid; + } else if (dwHash > dwMid) { + iStart = iMid + 1; + } else { + iEnd = iMid - 1; + } + } while (iStart <= iEnd); + return nullptr; +} + +const CFX_CSSPropertyTable* CFX_GetCSSPropertyByEnum(CFX_CSSProperty eName) { + return g_CFX_CSSProperties + static_cast(eName); +} diff --git a/core/fxcrt/css/cfx_cssdatatable.h b/core/fxcrt/css/cfx_cssdatatable.h new file mode 100644 index 0000000000000000000000000000000000000000..63c303488e6f8f37c31c4cdb8aef5ba607a11be4 --- /dev/null +++ b/core/fxcrt/css/cfx_cssdatatable.h @@ -0,0 +1,29 @@ +// 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 CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_ +#define CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_ + +#include +#include + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_cssnumbervalue.h" +#include "core/fxcrt/css/cfx_cssvalue.h" +#include "core/fxcrt/fx_system.h" + +struct CFX_CSSPropertyTable { + CFX_CSSProperty eName; + const wchar_t* pszName; + uint32_t dwHash; + uint32_t dwType; +}; + +const CFX_CSSPropertyTable* CFX_GetCSSPropertyByName( + const WideStringView& wsName); +const CFX_CSSPropertyTable* CFX_GetCSSPropertyByEnum(CFX_CSSProperty eName); + +#endif // CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_ diff --git a/core/fxcrt/css/cfx_cssdeclaration.cpp b/core/fxcrt/css/cfx_cssdeclaration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90bdf4e0ea46686286d90fe0513ebfb474dcdacd --- /dev/null +++ b/core/fxcrt/css/cfx_cssdeclaration.cpp @@ -0,0 +1,781 @@ +// 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 "core/fxcrt/css/cfx_cssdeclaration.h" + +#include "core/fxcrt/css/cfx_csscolorvalue.h" +#include "core/fxcrt/css/cfx_csscustomproperty.h" +#include "core/fxcrt/css/cfx_cssenumvalue.h" +#include "core/fxcrt/css/cfx_cssnumbervalue.h" +#include "core/fxcrt/css/cfx_csspropertyholder.h" +#include "core/fxcrt/css/cfx_cssstringvalue.h" +#include "core/fxcrt/css/cfx_cssvaluelist.h" +#include "core/fxcrt/css/cfx_cssvaluelistparser.h" +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/logging.h" +#include "third_party/base/ptr_util.h" + +namespace { + +uint8_t Hex2Dec(uint8_t hexHigh, uint8_t hexLow) { + return (FXSYS_HexCharToInt(hexHigh) << 4) + FXSYS_HexCharToInt(hexLow); +} + +struct CFX_CSSPropertyValueTable { + CFX_CSSPropertyValue eName; + const wchar_t* pszName; + uint32_t dwHash; +}; +const CFX_CSSPropertyValueTable g_CFX_CSSPropertyValues[] = { + {CFX_CSSPropertyValue::Bolder, L"bolder", 0x009F1058}, + {CFX_CSSPropertyValue::None, L"none", 0x048B6670}, + {CFX_CSSPropertyValue::Dot, L"dot", 0x0A48CB27}, + {CFX_CSSPropertyValue::Sub, L"sub", 0x0BD37FAA}, + {CFX_CSSPropertyValue::Top, L"top", 0x0BEDAF33}, + {CFX_CSSPropertyValue::Right, L"right", 0x193ADE3E}, + {CFX_CSSPropertyValue::Normal, L"normal", 0x247CF3E9}, + {CFX_CSSPropertyValue::Auto, L"auto", 0x2B35B6D9}, + {CFX_CSSPropertyValue::Text, L"text", 0x2D08AF85}, + {CFX_CSSPropertyValue::XSmall, L"x-small", 0x2D2FCAFE}, + {CFX_CSSPropertyValue::Thin, L"thin", 0x2D574D53}, + {CFX_CSSPropertyValue::Small, L"small", 0x316A3739}, + {CFX_CSSPropertyValue::Bottom, L"bottom", 0x399F02B5}, + {CFX_CSSPropertyValue::Underline, L"underline", 0x3A0273A6}, + {CFX_CSSPropertyValue::Double, L"double", 0x3D98515B}, + {CFX_CSSPropertyValue::Lighter, L"lighter", 0x45BEB7AF}, + {CFX_CSSPropertyValue::Oblique, L"oblique", 0x53EBDDB1}, + {CFX_CSSPropertyValue::Super, L"super", 0x6A4F842F}, + {CFX_CSSPropertyValue::Center, L"center", 0x6C51AFC1}, + {CFX_CSSPropertyValue::XxLarge, L"xx-large", 0x70BB1508}, + {CFX_CSSPropertyValue::Smaller, L"smaller", 0x849769F0}, + {CFX_CSSPropertyValue::Baseline, L"baseline", 0x87436BA3}, + {CFX_CSSPropertyValue::Thick, L"thick", 0x8CC35EB3}, + {CFX_CSSPropertyValue::Justify, L"justify", 0x8D269CAE}, + {CFX_CSSPropertyValue::Middle, L"middle", 0x947FA00F}, + {CFX_CSSPropertyValue::Medium, L"medium", 0xA084A381}, + {CFX_CSSPropertyValue::ListItem, L"list-item", 0xA32382B8}, + {CFX_CSSPropertyValue::XxSmall, L"xx-small", 0xADE1FC76}, + {CFX_CSSPropertyValue::Bold, L"bold", 0xB18313A1}, + {CFX_CSSPropertyValue::SmallCaps, L"small-caps", 0xB299428D}, + {CFX_CSSPropertyValue::Inline, L"inline", 0xC02D649F}, + {CFX_CSSPropertyValue::Overline, L"overline", 0xC0EC9FA4}, + {CFX_CSSPropertyValue::TextBottom, L"text-bottom", 0xC7D08D87}, + {CFX_CSSPropertyValue::Larger, L"larger", 0xCD3C409D}, + {CFX_CSSPropertyValue::InlineTable, L"inline-table", 0xD131F494}, + {CFX_CSSPropertyValue::InlineBlock, L"inline-block", 0xD26A8BD7}, + {CFX_CSSPropertyValue::Blink, L"blink", 0xDC36E390}, + {CFX_CSSPropertyValue::Block, L"block", 0xDCD480AB}, + {CFX_CSSPropertyValue::Italic, L"italic", 0xE31D5396}, + {CFX_CSSPropertyValue::LineThrough, L"line-through", 0xE4C5A276}, + {CFX_CSSPropertyValue::XLarge, L"x-large", 0xF008E390}, + {CFX_CSSPropertyValue::Large, L"large", 0xF4434FCB}, + {CFX_CSSPropertyValue::Left, L"left", 0xF5AD782B}, + {CFX_CSSPropertyValue::TextTop, L"text-top", 0xFCB58D45}, +}; +const int32_t g_iCSSPropertyValueCount = + sizeof(g_CFX_CSSPropertyValues) / sizeof(CFX_CSSPropertyValueTable); +static_assert(g_iCSSPropertyValueCount == + static_cast(CFX_CSSPropertyValue::LAST_MARKER), + "Property value table differs in size from property value enum"); + +struct CFX_CSSLengthUnitTable { + uint16_t wHash; + CFX_CSSNumberType wValue; +}; +const CFX_CSSLengthUnitTable g_CFX_CSSLengthUnits[] = { + {0x0672, CFX_CSSNumberType::EMS}, + {0x067D, CFX_CSSNumberType::EXS}, + {0x1AF7, CFX_CSSNumberType::Inches}, + {0x2F7A, CFX_CSSNumberType::MilliMeters}, + {0x3ED3, CFX_CSSNumberType::Picas}, + {0x3EE4, CFX_CSSNumberType::Points}, + {0x3EE8, CFX_CSSNumberType::Pixels}, + {0xFC30, CFX_CSSNumberType::CentiMeters}, +}; + +struct CFX_CSSColorTable { + uint32_t dwHash; + FX_ARGB dwValue; +}; +const CFX_CSSColorTable g_CFX_CSSColors[] = { + {0x031B47FE, 0xff000080}, {0x0BB8DF5B, 0xffff0000}, + {0x0D82A78C, 0xff800000}, {0x2ACC82E8, 0xff00ffff}, + {0x2D083986, 0xff008080}, {0x4A6A6195, 0xffc0c0c0}, + {0x546A8EF3, 0xff808080}, {0x65C9169C, 0xffffa500}, + {0x8422BB61, 0xffffffff}, {0x9271A558, 0xff800080}, + {0xA65A3EE3, 0xffff00ff}, {0xB1345708, 0xff0000ff}, + {0xB6D2CF1F, 0xff808000}, {0xD19B5E1C, 0xffffff00}, + {0xDB64391D, 0xff000000}, {0xF616D507, 0xff00ff00}, + {0xF6EFFF31, 0xff008000}, +}; + +const CFX_CSSPropertyValueTable* GetCSSPropertyValueByName( + const WideStringView& wsName) { + ASSERT(!wsName.IsEmpty()); + uint32_t dwHash = FX_HashCode_GetW(wsName, true); + int32_t iEnd = g_iCSSPropertyValueCount; + int32_t iMid, iStart = 0; + uint32_t dwMid; + do { + iMid = (iStart + iEnd) / 2; + dwMid = g_CFX_CSSPropertyValues[iMid].dwHash; + if (dwHash == dwMid) { + return g_CFX_CSSPropertyValues + iMid; + } else if (dwHash > dwMid) { + iStart = iMid + 1; + } else { + iEnd = iMid - 1; + } + } while (iStart <= iEnd); + return nullptr; +} + +const CFX_CSSLengthUnitTable* GetCSSLengthUnitByName( + const WideStringView& wsName) { + ASSERT(!wsName.IsEmpty()); + uint16_t wHash = FX_HashCode_GetW(wsName, true); + int32_t iEnd = + sizeof(g_CFX_CSSLengthUnits) / sizeof(CFX_CSSLengthUnitTable) - 1; + int32_t iMid, iStart = 0; + uint16_t wMid; + do { + iMid = (iStart + iEnd) / 2; + wMid = g_CFX_CSSLengthUnits[iMid].wHash; + if (wHash == wMid) { + return g_CFX_CSSLengthUnits + iMid; + } else if (wHash > wMid) { + iStart = iMid + 1; + } else { + iEnd = iMid - 1; + } + } while (iStart <= iEnd); + return nullptr; +} + +const CFX_CSSColorTable* GetCSSColorByName(const WideStringView& wsName) { + ASSERT(!wsName.IsEmpty()); + uint32_t dwHash = FX_HashCode_GetW(wsName, true); + int32_t iEnd = sizeof(g_CFX_CSSColors) / sizeof(CFX_CSSColorTable) - 1; + int32_t iMid, iStart = 0; + uint32_t dwMid; + do { + iMid = (iStart + iEnd) / 2; + dwMid = g_CFX_CSSColors[iMid].dwHash; + if (dwHash == dwMid) { + return g_CFX_CSSColors + iMid; + } else if (dwHash > dwMid) { + iStart = iMid + 1; + } else { + iEnd = iMid - 1; + } + } while (iStart <= iEnd); + return nullptr; +} + +bool ParseCSSNumber(const wchar_t* pszValue, + int32_t iValueLen, + float& fValue, + CFX_CSSNumberType& eUnit) { + ASSERT(pszValue && iValueLen > 0); + int32_t iUsedLen = 0; + fValue = FXSYS_wcstof(pszValue, iValueLen, &iUsedLen); + if (iUsedLen <= 0) + return false; + + iValueLen -= iUsedLen; + pszValue += iUsedLen; + eUnit = CFX_CSSNumberType::Number; + if (iValueLen >= 1 && *pszValue == '%') { + eUnit = CFX_CSSNumberType::Percent; + } else if (iValueLen == 2) { + const CFX_CSSLengthUnitTable* pUnit = + GetCSSLengthUnitByName(WideStringView(pszValue, 2)); + if (pUnit) + eUnit = pUnit->wValue; + } + return true; +} + +} // namespace + +// static +bool CFX_CSSDeclaration::ParseCSSString(const wchar_t* pszValue, + int32_t iValueLen, + int32_t* iOffset, + int32_t* iLength) { + ASSERT(pszValue && iValueLen > 0); + *iOffset = 0; + *iLength = iValueLen; + if (iValueLen >= 2) { + wchar_t first = pszValue[0], last = pszValue[iValueLen - 1]; + if ((first == '\"' && last == '\"') || (first == '\'' && last == '\'')) { + *iOffset = 1; + *iLength -= 2; + } + } + return iValueLen > 0; +} + +// static. +bool CFX_CSSDeclaration::ParseCSSColor(const wchar_t* pszValue, + int32_t iValueLen, + FX_ARGB* dwColor) { + ASSERT(pszValue && iValueLen > 0); + ASSERT(dwColor); + + if (*pszValue == '#') { + switch (iValueLen) { + case 4: { + uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[1]); + uint8_t green = Hex2Dec((uint8_t)pszValue[2], (uint8_t)pszValue[2]); + uint8_t blue = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[3]); + *dwColor = ArgbEncode(255, red, green, blue); + return true; + } + case 7: { + uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[2]); + uint8_t green = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[4]); + uint8_t blue = Hex2Dec((uint8_t)pszValue[5], (uint8_t)pszValue[6]); + *dwColor = ArgbEncode(255, red, green, blue); + return true; + } + default: + return false; + } + } + + if (iValueLen >= 10) { + if (pszValue[iValueLen - 1] != ')' || FXSYS_wcsnicmp(L"rgb(", pszValue, 4)) + return false; + + uint8_t rgb[3] = {0}; + float fValue; + CFX_CSSPrimitiveType eType; + CFX_CSSValueListParser list(pszValue + 4, iValueLen - 5, ','); + for (int32_t i = 0; i < 3; ++i) { + if (!list.NextValue(&eType, &pszValue, &iValueLen)) + return false; + if (eType != CFX_CSSPrimitiveType::Number) + return false; + CFX_CSSNumberType eNumType; + if (!ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) + return false; + + rgb[i] = eNumType == CFX_CSSNumberType::Percent + ? FXSYS_round(fValue * 2.55f) + : FXSYS_round(fValue); + } + *dwColor = ArgbEncode(255, rgb[0], rgb[1], rgb[2]); + return true; + } + + const CFX_CSSColorTable* pColor = + GetCSSColorByName(WideStringView(pszValue, iValueLen)); + if (!pColor) + return false; + + *dwColor = pColor->dwValue; + return true; +} + +CFX_CSSDeclaration::CFX_CSSDeclaration() {} + +CFX_CSSDeclaration::~CFX_CSSDeclaration() {} + +RetainPtr CFX_CSSDeclaration::GetProperty( + CFX_CSSProperty eProperty, + bool* bImportant) const { + for (const auto& p : properties_) { + if (p->eProperty == eProperty) { + *bImportant = p->bImportant; + return p->pValue; + } + } + return nullptr; +} + +void CFX_CSSDeclaration::AddPropertyHolder(CFX_CSSProperty eProperty, + RetainPtr pValue, + bool bImportant) { + auto pHolder = pdfium::MakeUnique(); + pHolder->bImportant = bImportant; + pHolder->eProperty = eProperty; + pHolder->pValue = pValue; + properties_.push_back(std::move(pHolder)); +} + +void CFX_CSSDeclaration::AddProperty(const CFX_CSSPropertyTable* pTable, + const WideStringView& value) { + ASSERT(!value.IsEmpty()); + + const wchar_t* pszValue = value.unterminated_c_str(); + int32_t iValueLen = value.GetLength(); + bool bImportant = false; + if (iValueLen >= 10 && pszValue[iValueLen - 10] == '!' && + FXSYS_wcsnicmp(L"important", pszValue + iValueLen - 9, 9) == 0) { + if ((iValueLen -= 10) == 0) + return; + + bImportant = true; + } + const uint32_t dwType = pTable->dwType; + switch (dwType & 0x0F) { + case CFX_CSSVALUETYPE_Primitive: { + static const uint32_t g_ValueGuessOrder[] = { + CFX_CSSVALUETYPE_MaybeNumber, CFX_CSSVALUETYPE_MaybeEnum, + CFX_CSSVALUETYPE_MaybeColor, CFX_CSSVALUETYPE_MaybeString, + }; + static const int32_t g_ValueGuessCount = + sizeof(g_ValueGuessOrder) / sizeof(uint32_t); + for (int32_t i = 0; i < g_ValueGuessCount; ++i) { + const uint32_t dwMatch = dwType & g_ValueGuessOrder[i]; + if (dwMatch == 0) { + continue; + } + RetainPtr pCSSValue; + switch (dwMatch) { + case CFX_CSSVALUETYPE_MaybeNumber: + pCSSValue = ParseNumber(pszValue, iValueLen); + break; + case CFX_CSSVALUETYPE_MaybeEnum: + pCSSValue = ParseEnum(pszValue, iValueLen); + break; + case CFX_CSSVALUETYPE_MaybeColor: + pCSSValue = ParseColor(pszValue, iValueLen); + break; + case CFX_CSSVALUETYPE_MaybeString: + pCSSValue = ParseString(pszValue, iValueLen); + break; + default: + break; + } + if (pCSSValue) { + AddPropertyHolder(pTable->eName, pCSSValue, bImportant); + return; + } + + if ((dwType & ~(g_ValueGuessOrder[i])) == CFX_CSSVALUETYPE_Primitive) + return; + } + break; + } + case CFX_CSSVALUETYPE_Shorthand: { + RetainPtr pWidth; + switch (pTable->eName) { + case CFX_CSSProperty::Font: + ParseFontProperty(pszValue, iValueLen, bImportant); + return; + case CFX_CSSProperty::Border: + if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { + AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth, + bImportant); + AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth, + bImportant); + AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth, + bImportant); + AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth, + bImportant); + return; + } + break; + case CFX_CSSProperty::BorderLeft: + if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { + AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth, + bImportant); + return; + } + break; + case CFX_CSSProperty::BorderTop: + if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { + AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth, + bImportant); + return; + } + break; + case CFX_CSSProperty::BorderRight: + if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { + AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth, + bImportant); + return; + } + break; + case CFX_CSSProperty::BorderBottom: + if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { + AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth, + bImportant); + return; + } + break; + default: + break; + } + } break; + case CFX_CSSVALUETYPE_List: + ParseValueListProperty(pTable, pszValue, iValueLen, bImportant); + return; + default: + NOTREACHED(); + break; + } +} + +void CFX_CSSDeclaration::AddProperty(const WideString& prop, + const WideString& value) { + custom_properties_.push_back( + pdfium::MakeUnique(prop, value)); +} + +RetainPtr CFX_CSSDeclaration::ParseNumber(const wchar_t* pszValue, + int32_t iValueLen) { + float fValue; + CFX_CSSNumberType eUnit; + if (!ParseCSSNumber(pszValue, iValueLen, fValue, eUnit)) + return nullptr; + return pdfium::MakeRetain(eUnit, fValue); +} + +RetainPtr CFX_CSSDeclaration::ParseEnum(const wchar_t* pszValue, + int32_t iValueLen) { + const CFX_CSSPropertyValueTable* pValue = + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); + return pValue ? pdfium::MakeRetain(pValue->eName) : nullptr; +} + +RetainPtr CFX_CSSDeclaration::ParseColor(const wchar_t* pszValue, + int32_t iValueLen) { + FX_ARGB dwColor; + if (!ParseCSSColor(pszValue, iValueLen, &dwColor)) + return nullptr; + return pdfium::MakeRetain(dwColor); +} + +RetainPtr CFX_CSSDeclaration::ParseString(const wchar_t* pszValue, + int32_t iValueLen) { + int32_t iOffset; + if (!ParseCSSString(pszValue, iValueLen, &iOffset, &iValueLen)) + return nullptr; + + if (iValueLen <= 0) + return nullptr; + + return pdfium::MakeRetain( + WideString(pszValue + iOffset, iValueLen)); +} + +void CFX_CSSDeclaration::ParseValueListProperty( + const CFX_CSSPropertyTable* pTable, + const wchar_t* pszValue, + int32_t iValueLen, + bool bImportant) { + wchar_t separator = + (pTable->eName == CFX_CSSProperty::FontFamily) ? ',' : ' '; + CFX_CSSValueListParser parser(pszValue, iValueLen, separator); + + const uint32_t dwType = pTable->dwType; + CFX_CSSPrimitiveType eType; + std::vector> list; + while (parser.NextValue(&eType, &pszValue, &iValueLen)) { + switch (eType) { + case CFX_CSSPrimitiveType::Number: + if (dwType & CFX_CSSVALUETYPE_MaybeNumber) { + float fValue; + CFX_CSSNumberType eNumType; + if (ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) + list.push_back( + pdfium::MakeRetain(eNumType, fValue)); + } + break; + case CFX_CSSPrimitiveType::String: + if (dwType & CFX_CSSVALUETYPE_MaybeColor) { + FX_ARGB dwColor; + if (ParseCSSColor(pszValue, iValueLen, &dwColor)) { + list.push_back(pdfium::MakeRetain(dwColor)); + continue; + } + } + if (dwType & CFX_CSSVALUETYPE_MaybeEnum) { + const CFX_CSSPropertyValueTable* pValue = + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); + if (pValue) { + list.push_back(pdfium::MakeRetain(pValue->eName)); + continue; + } + } + if (dwType & CFX_CSSVALUETYPE_MaybeString) { + list.push_back(pdfium::MakeRetain( + WideString(pszValue, iValueLen))); + } + break; + case CFX_CSSPrimitiveType::RGB: + if (dwType & CFX_CSSVALUETYPE_MaybeColor) { + FX_ARGB dwColor; + if (ParseCSSColor(pszValue, iValueLen, &dwColor)) { + list.push_back(pdfium::MakeRetain(dwColor)); + } + } + break; + default: + break; + } + } + if (list.empty()) + return; + + switch (pTable->eName) { + case CFX_CSSProperty::BorderWidth: + Add4ValuesProperty(list, bImportant, CFX_CSSProperty::BorderLeftWidth, + CFX_CSSProperty::BorderTopWidth, + CFX_CSSProperty::BorderRightWidth, + CFX_CSSProperty::BorderBottomWidth); + return; + case CFX_CSSProperty::Margin: + Add4ValuesProperty(list, bImportant, CFX_CSSProperty::MarginLeft, + CFX_CSSProperty::MarginTop, + CFX_CSSProperty::MarginRight, + CFX_CSSProperty::MarginBottom); + return; + case CFX_CSSProperty::Padding: + Add4ValuesProperty(list, bImportant, CFX_CSSProperty::PaddingLeft, + CFX_CSSProperty::PaddingTop, + CFX_CSSProperty::PaddingRight, + CFX_CSSProperty::PaddingBottom); + return; + default: { + auto pList = pdfium::MakeRetain(list); + AddPropertyHolder(pTable->eName, pList, bImportant); + return; + } + } +} + +void CFX_CSSDeclaration::Add4ValuesProperty( + const std::vector>& list, + bool bImportant, + CFX_CSSProperty eLeft, + CFX_CSSProperty eTop, + CFX_CSSProperty eRight, + CFX_CSSProperty eBottom) { + switch (list.size()) { + case 1: + AddPropertyHolder(eLeft, list[0], bImportant); + AddPropertyHolder(eTop, list[0], bImportant); + AddPropertyHolder(eRight, list[0], bImportant); + AddPropertyHolder(eBottom, list[0], bImportant); + return; + case 2: + AddPropertyHolder(eLeft, list[1], bImportant); + AddPropertyHolder(eTop, list[0], bImportant); + AddPropertyHolder(eRight, list[1], bImportant); + AddPropertyHolder(eBottom, list[0], bImportant); + return; + case 3: + AddPropertyHolder(eLeft, list[1], bImportant); + AddPropertyHolder(eTop, list[0], bImportant); + AddPropertyHolder(eRight, list[1], bImportant); + AddPropertyHolder(eBottom, list[2], bImportant); + return; + case 4: + AddPropertyHolder(eLeft, list[3], bImportant); + AddPropertyHolder(eTop, list[0], bImportant); + AddPropertyHolder(eRight, list[1], bImportant); + AddPropertyHolder(eBottom, list[2], bImportant); + return; + default: + break; + } +} + +bool CFX_CSSDeclaration::ParseBorderProperty( + const wchar_t* pszValue, + int32_t iValueLen, + RetainPtr& pWidth) const { + pWidth.Reset(nullptr); + + CFX_CSSValueListParser parser(pszValue, iValueLen, ' '); + CFX_CSSPrimitiveType eType; + while (parser.NextValue(&eType, &pszValue, &iValueLen)) { + switch (eType) { + case CFX_CSSPrimitiveType::Number: { + if (pWidth) + continue; + + float fValue; + CFX_CSSNumberType eNumType; + if (ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) + pWidth = pdfium::MakeRetain(eNumType, fValue); + break; + } + case CFX_CSSPrimitiveType::String: { + const CFX_CSSColorTable* pColorItem = + GetCSSColorByName(WideStringView(pszValue, iValueLen)); + if (pColorItem) + continue; + + const CFX_CSSPropertyValueTable* pValue = + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); + if (!pValue) + continue; + + switch (pValue->eName) { + case CFX_CSSPropertyValue::Thin: + case CFX_CSSPropertyValue::Thick: + case CFX_CSSPropertyValue::Medium: + if (!pWidth) + pWidth = pdfium::MakeRetain(pValue->eName); + break; + default: + break; + } + break; + } + default: + break; + } + } + if (!pWidth) + pWidth = + pdfium::MakeRetain(CFX_CSSNumberType::Number, 0.0f); + + return true; +} + +void CFX_CSSDeclaration::ParseFontProperty(const wchar_t* pszValue, + int32_t iValueLen, + bool bImportant) { + CFX_CSSValueListParser parser(pszValue, iValueLen, '/'); + RetainPtr pStyle; + RetainPtr pVariant; + RetainPtr pWeight; + RetainPtr pFontSize; + RetainPtr pLineHeight; + std::vector> familyList; + CFX_CSSPrimitiveType eType; + while (parser.NextValue(&eType, &pszValue, &iValueLen)) { + switch (eType) { + case CFX_CSSPrimitiveType::String: { + const CFX_CSSPropertyValueTable* pValue = + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); + if (pValue) { + switch (pValue->eName) { + case CFX_CSSPropertyValue::XxSmall: + case CFX_CSSPropertyValue::XSmall: + case CFX_CSSPropertyValue::Small: + case CFX_CSSPropertyValue::Medium: + case CFX_CSSPropertyValue::Large: + case CFX_CSSPropertyValue::XLarge: + case CFX_CSSPropertyValue::XxLarge: + case CFX_CSSPropertyValue::Smaller: + case CFX_CSSPropertyValue::Larger: + if (!pFontSize) + pFontSize = pdfium::MakeRetain(pValue->eName); + continue; + case CFX_CSSPropertyValue::Bold: + case CFX_CSSPropertyValue::Bolder: + case CFX_CSSPropertyValue::Lighter: + if (!pWeight) + pWeight = pdfium::MakeRetain(pValue->eName); + continue; + case CFX_CSSPropertyValue::Italic: + case CFX_CSSPropertyValue::Oblique: + if (!pStyle) + pStyle = pdfium::MakeRetain(pValue->eName); + continue; + case CFX_CSSPropertyValue::SmallCaps: + if (!pVariant) + pVariant = pdfium::MakeRetain(pValue->eName); + continue; + case CFX_CSSPropertyValue::Normal: + if (!pStyle) + pStyle = pdfium::MakeRetain(pValue->eName); + else if (!pVariant) + pVariant = pdfium::MakeRetain(pValue->eName); + else if (!pWeight) + pWeight = pdfium::MakeRetain(pValue->eName); + else if (!pFontSize) + pFontSize = pdfium::MakeRetain(pValue->eName); + else if (!pLineHeight) + pLineHeight = + pdfium::MakeRetain(pValue->eName); + continue; + default: + break; + } + } + if (pFontSize) { + familyList.push_back(pdfium::MakeRetain( + WideString(pszValue, iValueLen))); + } + parser.UseCommaSeparator(); + break; + } + case CFX_CSSPrimitiveType::Number: { + float fValue; + CFX_CSSNumberType eNumType; + if (!ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) + break; + if (eType == CFX_CSSPrimitiveType::Number) { + switch ((int32_t)fValue) { + case 100: + case 200: + case 300: + case 400: + case 500: + case 600: + case 700: + case 800: + case 900: + if (!pWeight) + pWeight = pdfium::MakeRetain( + CFX_CSSNumberType::Number, fValue); + continue; + } + } + if (!pFontSize) + pFontSize = pdfium::MakeRetain(eNumType, fValue); + else if (!pLineHeight) + pLineHeight = + pdfium::MakeRetain(eNumType, fValue); + break; + } + default: + break; + } + } + + if (!pStyle) { + pStyle = pdfium::MakeRetain(CFX_CSSPropertyValue::Normal); + } + if (!pVariant) { + pVariant = + pdfium::MakeRetain(CFX_CSSPropertyValue::Normal); + } + if (!pWeight) { + pWeight = + pdfium::MakeRetain(CFX_CSSPropertyValue::Normal); + } + if (!pFontSize) { + pFontSize = + pdfium::MakeRetain(CFX_CSSPropertyValue::Medium); + } + if (!pLineHeight) { + pLineHeight = + pdfium::MakeRetain(CFX_CSSPropertyValue::Normal); + } + + AddPropertyHolder(CFX_CSSProperty::FontStyle, pStyle, bImportant); + AddPropertyHolder(CFX_CSSProperty::FontVariant, pVariant, bImportant); + AddPropertyHolder(CFX_CSSProperty::FontWeight, pWeight, bImportant); + AddPropertyHolder(CFX_CSSProperty::FontSize, pFontSize, bImportant); + AddPropertyHolder(CFX_CSSProperty::LineHeight, pLineHeight, bImportant); + if (!familyList.empty()) { + auto pList = pdfium::MakeRetain(familyList); + AddPropertyHolder(CFX_CSSProperty::FontFamily, pList, bImportant); + } +} + +size_t CFX_CSSDeclaration::PropertyCountForTesting() const { + return properties_.size(); +} diff --git a/core/fxcrt/css/cfx_cssdeclaration.h b/core/fxcrt/css/cfx_cssdeclaration.h new file mode 100644 index 0000000000000000000000000000000000000000..7dd0bba90e797dcb345ba558b1cb88407fbb248d --- /dev/null +++ b/core/fxcrt/css/cfx_cssdeclaration.h @@ -0,0 +1,92 @@ +// 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 CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_ +#define CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_ + +#include +#include +#include + +#include "core/fxcrt/css/cfx_cssdatatable.h" + +class CFX_CSSPropertyHolder; +class CFX_CSSCustomProperty; + +class CFX_CSSDeclaration { + public: + using const_prop_iterator = + std::vector>::const_iterator; + using const_custom_iterator = + std::vector>::const_iterator; + + static bool ParseCSSString(const wchar_t* pszValue, + int32_t iValueLen, + int32_t* iOffset, + int32_t* iLength); + static bool ParseCSSColor(const wchar_t* pszValue, + int32_t iValueLen, + FX_ARGB* dwColor); + + CFX_CSSDeclaration(); + ~CFX_CSSDeclaration(); + + RetainPtr GetProperty(CFX_CSSProperty eProperty, + bool* bImportant) const; + + const_prop_iterator begin() const { return properties_.begin(); } + const_prop_iterator end() const { return properties_.end(); } + + const_custom_iterator custom_begin() const { + return custom_properties_.begin(); + } + const_custom_iterator custom_end() const { return custom_properties_.end(); } + + bool empty() const { return properties_.empty(); } + + void AddProperty(const CFX_CSSPropertyTable* pTable, + const WideStringView& value); + void AddProperty(const WideString& prop, const WideString& value); + + size_t PropertyCountForTesting() const; + + FX_ARGB ParseColorForTest(const wchar_t* pszValue, + int32_t iValueLen, + FX_ARGB* dwColor) const; + + private: + void ParseFontProperty(const wchar_t* pszValue, + int32_t iValueLen, + bool bImportant); + bool ParseBorderProperty(const wchar_t* pszValue, + int32_t iValueLen, + RetainPtr& pWidth) const; + void ParseValueListProperty(const CFX_CSSPropertyTable* pTable, + const wchar_t* pszValue, + int32_t iValueLen, + bool bImportant); + void Add4ValuesProperty(const std::vector>& list, + bool bImportant, + CFX_CSSProperty eLeft, + CFX_CSSProperty eTop, + CFX_CSSProperty eRight, + CFX_CSSProperty eBottom); + RetainPtr ParseNumber(const wchar_t* pszValue, + int32_t iValueLen); + RetainPtr ParseEnum(const wchar_t* pszValue, int32_t iValueLen); + RetainPtr ParseColor(const wchar_t* pszValue, + int32_t iValueLen); + RetainPtr ParseString(const wchar_t* pszValue, + int32_t iValueLen); + void AddPropertyHolder(CFX_CSSProperty eProperty, + RetainPtr pValue, + bool bImportant); + + std::vector> properties_; + std::vector> custom_properties_; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_ diff --git a/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp b/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..535e67da97627c1acef3f1491389fbd85bd0a2b8 --- /dev/null +++ b/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp @@ -0,0 +1,62 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/css/cfx_cssdeclaration.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CFX_CSSDeclarationTest, HexEncodingParsing) { + FX_ARGB color; + + // Length value invalid. + EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000", 3, &color)); + EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000000", 5, &color)); + EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000000", 8, &color)); + + // Invalid characters + EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#zxytlm", 7, &color)); + EXPECT_EQ(0, FXARGB_R(color)); + EXPECT_EQ(0, FXARGB_G(color)); + EXPECT_EQ(0, FXARGB_B(color)); + + EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#000", 4, &color)); + EXPECT_EQ(0, FXARGB_R(color)); + EXPECT_EQ(0, FXARGB_G(color)); + EXPECT_EQ(0, FXARGB_B(color)); + + EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#FFF", 4, &color)); + EXPECT_EQ(255, FXARGB_R(color)); + EXPECT_EQ(255, FXARGB_G(color)); + EXPECT_EQ(255, FXARGB_B(color)); + + EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#F0F0F0", 7, &color)); + EXPECT_EQ(240, FXARGB_R(color)); + EXPECT_EQ(240, FXARGB_G(color)); + EXPECT_EQ(240, FXARGB_B(color)); + + // Upper and lower case characters. + EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#1b2F3c", 7, &color)); + EXPECT_EQ(27, FXARGB_R(color)); + EXPECT_EQ(47, FXARGB_G(color)); + EXPECT_EQ(60, FXARGB_B(color)); +} + +TEST(CFX_CSSDeclarationTest, RGBEncodingParsing) { + FX_ARGB color; + + // Invalid input for rgb() syntax. + EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"blahblahblah", 11, &color)); + + EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"rgb(0, 0, 0)", 12, &color)); + EXPECT_EQ(0, FXARGB_R(color)); + EXPECT_EQ(0, FXARGB_G(color)); + EXPECT_EQ(0, FXARGB_B(color)); + + EXPECT_TRUE( + CFX_CSSDeclaration::ParseCSSColor(L"rgb(128,255,48)", 15, &color)); + EXPECT_EQ(128, FXARGB_R(color)); + EXPECT_EQ(255, FXARGB_G(color)); + EXPECT_EQ(48, FXARGB_B(color)); +} diff --git a/core/fxcrt/css/cfx_cssenumvalue.cpp b/core/fxcrt/css/cfx_cssenumvalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9b39beb34d74f1564d8e8b930434fcaf7528d14 --- /dev/null +++ b/core/fxcrt/css/cfx_cssenumvalue.cpp @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssenumvalue.h" + +CFX_CSSEnumValue::CFX_CSSEnumValue(CFX_CSSPropertyValue value) + : CFX_CSSValue(CFX_CSSPrimitiveType::Enum), value_(value) {} + +CFX_CSSEnumValue::~CFX_CSSEnumValue() {} diff --git a/core/fxcrt/css/cfx_cssenumvalue.h b/core/fxcrt/css/cfx_cssenumvalue.h new file mode 100644 index 0000000000000000000000000000000000000000..0d6b87e85da843642aa452e9d09868276d210d64 --- /dev/null +++ b/core/fxcrt/css/cfx_cssenumvalue.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSENUMVALUE_H_ +#define CORE_FXCRT_CSS_CFX_CSSENUMVALUE_H_ + +#include "core/fxcrt/css/cfx_cssvalue.h" + +class CFX_CSSEnumValue : public CFX_CSSValue { + public: + explicit CFX_CSSEnumValue(CFX_CSSPropertyValue value); + ~CFX_CSSEnumValue() override; + + CFX_CSSPropertyValue Value() const { return value_; } + + private: + CFX_CSSPropertyValue value_; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSENUMVALUE_H_ diff --git a/core/fxcrt/css/cfx_cssexttextbuf.cpp b/core/fxcrt/css/cfx_cssexttextbuf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..287dc2e954df7c3d7e636ccde8bf46ca8cc21137 --- /dev/null +++ b/core/fxcrt/css/cfx_cssexttextbuf.cpp @@ -0,0 +1,17 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssexttextbuf.h" + +CFX_CSSExtTextBuf::CFX_CSSExtTextBuf() + : m_pExtBuffer(nullptr), m_iDatLen(0), m_iDatPos(0) {} + +CFX_CSSExtTextBuf::~CFX_CSSExtTextBuf() {} + +void CFX_CSSExtTextBuf::AttachBuffer(const wchar_t* pBuffer, int32_t iBufLen) { + m_pExtBuffer = pBuffer; + m_iDatLen = iBufLen; +} diff --git a/core/fxcrt/css/cfx_cssexttextbuf.h b/core/fxcrt/css/cfx_cssexttextbuf.h new file mode 100644 index 0000000000000000000000000000000000000000..342b91e8aa7226b641d4728bf2fb7748a5885dfa --- /dev/null +++ b/core/fxcrt/css/cfx_cssexttextbuf.h @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSEXTTEXTBUF_H_ +#define CORE_FXCRT_CSS_CFX_CSSEXTTEXTBUF_H_ + +#include "core/fxcrt/fx_system.h" + +class CFX_CSSExtTextBuf { + public: + CFX_CSSExtTextBuf(); + ~CFX_CSSExtTextBuf(); + + void AttachBuffer(const wchar_t* pBuffer, int32_t iBufLen); + + bool IsEOF() const { return m_iDatPos >= m_iDatLen; } + + wchar_t GetChar() const { return m_pExtBuffer[m_iDatPos]; } + wchar_t GetNextChar() const { + return (m_iDatPos + 1 >= m_iDatLen) ? 0 : m_pExtBuffer[m_iDatPos + 1]; + } + + void MoveNext() { m_iDatPos++; } + + protected: + const wchar_t* m_pExtBuffer; + int32_t m_iDatLen; + int32_t m_iDatPos; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSEXTTEXTBUF_H_ diff --git a/core/fxcrt/css/cfx_cssnumbervalue.cpp b/core/fxcrt/css/cfx_cssnumbervalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8f72479d43c5e0fcdf8a01b215808469bf761a3 --- /dev/null +++ b/core/fxcrt/css/cfx_cssnumbervalue.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssnumbervalue.h" + +CFX_CSSNumberValue::CFX_CSSNumberValue(CFX_CSSNumberType type, float value) + : CFX_CSSValue(CFX_CSSPrimitiveType::Number), type_(type), value_(value) { + if (type_ == CFX_CSSNumberType::Number && fabs(value_) < 0.001f) + value_ = 0.0f; +} + +CFX_CSSNumberValue::~CFX_CSSNumberValue() {} + +float CFX_CSSNumberValue::Apply(float percentBase) const { + switch (type_) { + case CFX_CSSNumberType::Pixels: + case CFX_CSSNumberType::Number: + return value_ * 72 / 96; + case CFX_CSSNumberType::EMS: + case CFX_CSSNumberType::EXS: + return value_ * percentBase; + case CFX_CSSNumberType::Percent: + return value_ * percentBase / 100.0f; + case CFX_CSSNumberType::CentiMeters: + return value_ * 28.3464f; + case CFX_CSSNumberType::MilliMeters: + return value_ * 2.8346f; + case CFX_CSSNumberType::Inches: + return value_ * 72.0f; + case CFX_CSSNumberType::Picas: + return value_ / 12.0f; + case CFX_CSSNumberType::Points: + return value_; + } + return value_; +} diff --git a/core/fxcrt/css/cfx_cssnumbervalue.h b/core/fxcrt/css/cfx_cssnumbervalue.h new file mode 100644 index 0000000000000000000000000000000000000000..a49328d663db43ed79c093419ea4ee486e4fab5c --- /dev/null +++ b/core/fxcrt/css/cfx_cssnumbervalue.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_ +#define CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_ + +#include "core/fxcrt/css/cfx_cssvalue.h" +#include "core/fxcrt/fx_system.h" + +enum class CFX_CSSNumberType { + Number, + Percent, + EMS, + EXS, + Pixels, + CentiMeters, + MilliMeters, + Inches, + Points, + Picas, +}; + +class CFX_CSSNumberValue : public CFX_CSSValue { + public: + CFX_CSSNumberValue(CFX_CSSNumberType type, float value); + ~CFX_CSSNumberValue() override; + + float Value() const { return value_; } + CFX_CSSNumberType Kind() const { return type_; } + + float Apply(float percentBase) const; + + private: + CFX_CSSNumberType type_; + float value_; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_ diff --git a/core/fxcrt/css/cfx_csspropertyholder.cpp b/core/fxcrt/css/cfx_csspropertyholder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11e0d4b75295f296819e148ef423ee5e6687e67b --- /dev/null +++ b/core/fxcrt/css/cfx_csspropertyholder.cpp @@ -0,0 +1,11 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_csspropertyholder.h" + +CFX_CSSPropertyHolder::CFX_CSSPropertyHolder() {} + +CFX_CSSPropertyHolder::~CFX_CSSPropertyHolder() {} diff --git a/core/fxcrt/css/cfx_csspropertyholder.h b/core/fxcrt/css/cfx_csspropertyholder.h new file mode 100644 index 0000000000000000000000000000000000000000..a271bdafc72a506c0cc57c9f032998637eb2d40b --- /dev/null +++ b/core/fxcrt/css/cfx_csspropertyholder.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSPROPERTYHOLDER_H_ +#define CORE_FXCRT_CSS_CFX_CSSPROPERTYHOLDER_H_ + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_cssvalue.h" +#include "core/fxcrt/retain_ptr.h" + +class CFX_CSSPropertyHolder { + public: + CFX_CSSPropertyHolder(); + ~CFX_CSSPropertyHolder(); + + CFX_CSSProperty eProperty; + bool bImportant; + RetainPtr pValue; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSPROPERTYHOLDER_H_ diff --git a/core/fxcrt/css/cfx_cssrulecollection.cpp b/core/fxcrt/css/cfx_cssrulecollection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2030518b69a5bc7df343057c1a70f65d48e78c5d --- /dev/null +++ b/core/fxcrt/css/cfx_cssrulecollection.cpp @@ -0,0 +1,56 @@ +// Copyright 2016 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 "core/fxcrt/css/cfx_cssrulecollection.h" + +#include +#include + +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/css/cfx_cssselector.h" +#include "core/fxcrt/css/cfx_cssstylerule.h" +#include "core/fxcrt/css/cfx_cssstylesheet.h" +#include "core/fxcrt/css/cfx_csssyntaxparser.h" +#include "third_party/base/ptr_util.h" + +CFX_CSSRuleCollection::CFX_CSSRuleCollection() : m_iSelectors(0) {} + +CFX_CSSRuleCollection::~CFX_CSSRuleCollection() { + Clear(); +} + +void CFX_CSSRuleCollection::Clear() { + m_TagRules.clear(); + m_iSelectors = 0; +} + +const std::vector>* +CFX_CSSRuleCollection::GetTagRuleData(const WideString& tagname) const { + auto it = m_TagRules.find(FX_HashCode_GetW(tagname.c_str(), true)); + return it != m_TagRules.end() ? &it->second : nullptr; +} + +void CFX_CSSRuleCollection::AddRulesFrom(const CFX_CSSStyleSheet* sheet) { + int32_t iRules = sheet->CountRules(); + for (int32_t j = 0; j < iRules; j++) + AddRulesFrom(sheet, sheet->GetRule(j)); +} + +void CFX_CSSRuleCollection::AddRulesFrom(const CFX_CSSStyleSheet* pStyleSheet, + CFX_CSSStyleRule* pStyleRule) { + CFX_CSSDeclaration* pDeclaration = pStyleRule->GetDeclaration(); + int32_t iSelectors = pStyleRule->CountSelectorLists(); + for (int32_t i = 0; i < iSelectors; ++i) { + CFX_CSSSelector* pSelector = pStyleRule->GetSelectorList(i); + m_TagRules[pSelector->GetNameHash()].push_back( + pdfium::MakeUnique(pSelector, pDeclaration)); + m_iSelectors++; + } +} + +CFX_CSSRuleCollection::Data::Data(CFX_CSSSelector* pSel, + CFX_CSSDeclaration* pDecl) + : pSelector(pSel), pDeclaration(pDecl) {} diff --git a/core/fxcrt/css/cfx_cssrulecollection.h b/core/fxcrt/css/cfx_cssrulecollection.h new file mode 100644 index 0000000000000000000000000000000000000000..72ae58c55f1a289f97fbcd940865a86e66f914cd --- /dev/null +++ b/core/fxcrt/css/cfx_cssrulecollection.h @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSRULECOLLECTION_H_ +#define CORE_FXCRT_CSS_CFX_CSSRULECOLLECTION_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_string.h" + +class CFX_CSSDeclaration; +class CFX_CSSSelector; +class CFX_CSSStyleRule; +class CFX_CSSStyleSheet; + +class CFX_CSSRuleCollection { + public: + class Data { + public: + Data(CFX_CSSSelector* pSel, CFX_CSSDeclaration* pDecl); + + CFX_CSSSelector* const pSelector; + CFX_CSSDeclaration* const pDeclaration; + }; + + CFX_CSSRuleCollection(); + ~CFX_CSSRuleCollection(); + + void AddRulesFrom(const CFX_CSSStyleSheet* sheet); + void Clear(); + int32_t CountSelectors() const { return m_iSelectors; } + + const std::vector>* GetTagRuleData( + const WideString& tagname) const; + + private: + void AddRulesFrom(const CFX_CSSStyleSheet* pStyleSheet, + CFX_CSSStyleRule* pRule); + + std::map>> m_TagRules; + int32_t m_iSelectors; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSRULECOLLECTION_H_ diff --git a/core/fxcrt/css/cfx_cssselector.cpp b/core/fxcrt/css/cfx_cssselector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3993dcae5c8eb44ab9c102ceff3e0f39ac17cf8b --- /dev/null +++ b/core/fxcrt/css/cfx_cssselector.cpp @@ -0,0 +1,87 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssselector.h" + +#include + +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/ptr_util.h" + +namespace { + +int32_t GetCSSNameLen(const wchar_t* psz, const wchar_t* pEnd) { + const wchar_t* pStart = psz; + while (psz < pEnd) { + wchar_t wch = *psz; + if (!FXSYS_iswalnum(wch) && wch != '_' && wch != '-') + break; + ++psz; + } + return psz - pStart; +} + +} // namespace + +CFX_CSSSelector::CFX_CSSSelector(CFX_CSSSelectorType eType, + const wchar_t* psz, + int32_t iLen, + bool bIgnoreCase) + : m_eType(eType), + m_dwHash(FX_HashCode_GetW(WideStringView(psz, iLen), bIgnoreCase)) {} + +CFX_CSSSelector::~CFX_CSSSelector() {} + +CFX_CSSSelectorType CFX_CSSSelector::GetType() const { + return m_eType; +} + +uint32_t CFX_CSSSelector::GetNameHash() const { + return m_dwHash; +} + +CFX_CSSSelector* CFX_CSSSelector::GetNextSelector() const { + return m_pNext.get(); +} + +// static. +std::unique_ptr CFX_CSSSelector::FromString( + const WideStringView& str) { + ASSERT(!str.IsEmpty()); + + const wchar_t* psz = str.unterminated_c_str(); + const wchar_t* pStart = psz; + const wchar_t* pEnd = psz + str.GetLength(); + for (; psz < pEnd; ++psz) { + switch (*psz) { + case '>': + case '[': + case '+': + return nullptr; + } + } + + std::unique_ptr pFirst = nullptr; + for (psz = pStart; psz < pEnd;) { + wchar_t wch = *psz; + if (FXSYS_iswalpha(wch) || wch == '*') { + int32_t iNameLen = wch == '*' ? 1 : GetCSSNameLen(psz, pEnd); + auto p = pdfium::MakeUnique(CFX_CSSSelectorType::Element, + psz, iNameLen, true); + if (pFirst) { + pFirst->SetType(CFX_CSSSelectorType::Descendant); + p->SetNext(std::move(pFirst)); + } + pFirst = std::move(p); + psz += iNameLen; + } else if (wch == ' ') { + psz++; + } else { + return nullptr; + } + } + return pFirst; +} diff --git a/core/fxcrt/css/cfx_cssselector.h b/core/fxcrt/css/cfx_cssselector.h new file mode 100644 index 0000000000000000000000000000000000000000..62f8b166cceb7b27180eba9f0efe616a6e0b0bc1 --- /dev/null +++ b/core/fxcrt/css/cfx_cssselector.h @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSSELECTOR_H_ +#define CORE_FXCRT_CSS_CFX_CSSSELECTOR_H_ + +#include +#include + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/fx_string.h" + +class CFX_CSSSelector { + public: + static std::unique_ptr FromString(const WideStringView& str); + + CFX_CSSSelector(CFX_CSSSelectorType eType, + const wchar_t* psz, + int32_t iLen, + bool bIgnoreCase); + ~CFX_CSSSelector(); + + CFX_CSSSelectorType GetType() const; + uint32_t GetNameHash() const; + CFX_CSSSelector* GetNextSelector() const; + + void SetNext(std::unique_ptr pNext) { + m_pNext = std::move(pNext); + } + + private: + void SetType(CFX_CSSSelectorType eType) { m_eType = eType; } + + CFX_CSSSelectorType m_eType; + uint32_t m_dwHash; + std::unique_ptr m_pNext; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSSELECTOR_H_ diff --git a/core/fxcrt/css/cfx_cssstringvalue.cpp b/core/fxcrt/css/cfx_cssstringvalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ff2a33c9b43a783e624bc035ab0b17afa88e0e3 --- /dev/null +++ b/core/fxcrt/css/cfx_cssstringvalue.cpp @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssstringvalue.h" + +CFX_CSSStringValue::CFX_CSSStringValue(const WideString& value) + : CFX_CSSValue(CFX_CSSPrimitiveType::String), value_(value) {} + +CFX_CSSStringValue::~CFX_CSSStringValue() {} diff --git a/core/fxcrt/css/cfx_cssstringvalue.h b/core/fxcrt/css/cfx_cssstringvalue.h new file mode 100644 index 0000000000000000000000000000000000000000..d72078a6302a147356f900adddb105f524518c1e --- /dev/null +++ b/core/fxcrt/css/cfx_cssstringvalue.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_ +#define CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_ + +#include "core/fxcrt/css/cfx_cssvalue.h" + +class CFX_CSSStringValue : public CFX_CSSValue { + public: + explicit CFX_CSSStringValue(const WideString& value); + ~CFX_CSSStringValue() override; + + const WideString Value() const { return value_; } + + private: + const WideString value_; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_ diff --git a/core/fxcrt/css/cfx_cssstylerule.cpp b/core/fxcrt/css/cfx_cssstylerule.cpp new file mode 100644 index 0000000000000000000000000000000000000000..504771ed46dd4c66d25e488f3aa1c19e5c6d0c00 --- /dev/null +++ b/core/fxcrt/css/cfx_cssstylerule.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssstylerule.h" + +CFX_CSSStyleRule::CFX_CSSStyleRule() {} + +CFX_CSSStyleRule::~CFX_CSSStyleRule() {} + +size_t CFX_CSSStyleRule::CountSelectorLists() const { + return m_ppSelector.size(); +} + +CFX_CSSSelector* CFX_CSSStyleRule::GetSelectorList(int32_t index) const { + return m_ppSelector[index].get(); +} + +CFX_CSSDeclaration* CFX_CSSStyleRule::GetDeclaration() { + return &m_Declaration; +} + +void CFX_CSSStyleRule::SetSelector( + std::vector>* list) { + ASSERT(m_ppSelector.empty()); + + m_ppSelector.swap(*list); +} diff --git a/core/fxcrt/css/cfx_cssstylerule.h b/core/fxcrt/css/cfx_cssstylerule.h new file mode 100644 index 0000000000000000000000000000000000000000..bba1fc53c8ab8de6600c187ce388b636e85e3b2a --- /dev/null +++ b/core/fxcrt/css/cfx_cssstylerule.h @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSSTYLERULE_H_ +#define CORE_FXCRT_CSS_CFX_CSSSTYLERULE_H_ + +#include +#include + +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/css/cfx_cssselector.h" + +class CFX_CSSStyleRule { + public: + CFX_CSSStyleRule(); + ~CFX_CSSStyleRule(); + + size_t CountSelectorLists() const; + CFX_CSSSelector* GetSelectorList(int32_t index) const; + CFX_CSSDeclaration* GetDeclaration(); + + void SetSelector(std::vector>* list); + + private: + CFX_CSSDeclaration m_Declaration; + std::vector> m_ppSelector; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSSTYLERULE_H_ diff --git a/core/fxcrt/css/cfx_cssstyleselector.cpp b/core/fxcrt/css/cfx_cssstyleselector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb9ab2f499d138244398959e4da9fdda8d67ca7b --- /dev/null +++ b/core/fxcrt/css/cfx_cssstyleselector.cpp @@ -0,0 +1,597 @@ +// 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 "core/fxcrt/css/cfx_cssstyleselector.h" + +#include +#include + +#include "core/fxcrt/css/cfx_csscolorvalue.h" +#include "core/fxcrt/css/cfx_csscomputedstyle.h" +#include "core/fxcrt/css/cfx_csscustomproperty.h" +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/css/cfx_cssenumvalue.h" +#include "core/fxcrt/css/cfx_csspropertyholder.h" +#include "core/fxcrt/css/cfx_cssselector.h" +#include "core/fxcrt/css/cfx_cssstylesheet.h" +#include "core/fxcrt/css/cfx_csssyntaxparser.h" +#include "core/fxcrt/css/cfx_cssvaluelist.h" +#include "third_party/base/logging.h" +#include "third_party/base/ptr_util.h" + +CFX_CSSStyleSelector::CFX_CSSStyleSelector() : m_fDefFontSize(12.0f) {} + +CFX_CSSStyleSelector::~CFX_CSSStyleSelector() {} + +void CFX_CSSStyleSelector::SetDefFontSize(float fFontSize) { + ASSERT(fFontSize > 0); + m_fDefFontSize = fFontSize; +} + +RetainPtr CFX_CSSStyleSelector::CreateComputedStyle( + CFX_CSSComputedStyle* pParentStyle) { + auto pStyle = pdfium::MakeRetain(); + if (pParentStyle) + pStyle->m_InheritedData = pParentStyle->m_InheritedData; + return pStyle; +} + +void CFX_CSSStyleSelector::SetUAStyleSheet( + std::unique_ptr pSheet) { + m_UAStyles = std::move(pSheet); +} + +void CFX_CSSStyleSelector::UpdateStyleIndex() { + m_UARules.Clear(); + m_UARules.AddRulesFrom(m_UAStyles.get()); +} + +std::vector CFX_CSSStyleSelector::MatchDeclarations( + const WideString& tagname) { + std::vector matchedDecls; + if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty()) + return matchedDecls; + + auto* rules = m_UARules.GetTagRuleData(tagname); + if (!rules) + return matchedDecls; + + for (const auto& d : *rules) { + if (MatchSelector(tagname, d->pSelector)) + matchedDecls.push_back(d->pDeclaration); + } + return matchedDecls; +} + +bool CFX_CSSStyleSelector::MatchSelector(const WideString& tagname, + CFX_CSSSelector* pSel) { + // TODO(dsinclair): The code only supports a single level of selector at this + // point. None of the code using selectors required the complexity so lets + // just say we don't support them to simplify the code for now. + if (!pSel || pSel->GetNextSelector() || + pSel->GetType() == CFX_CSSSelectorType::Descendant) { + return false; + } + return pSel->GetNameHash() == FX_HashCode_GetW(tagname.c_str(), true); +} + +void CFX_CSSStyleSelector::ComputeStyle( + const std::vector& declArray, + const WideString& styleString, + const WideString& alignString, + CFX_CSSComputedStyle* pDest) { + std::unique_ptr pDecl; + if (!styleString.IsEmpty() || !alignString.IsEmpty()) { + pDecl = pdfium::MakeUnique(); + + if (!styleString.IsEmpty()) + AppendInlineStyle(pDecl.get(), styleString); + if (!alignString.IsEmpty()) { + pDecl->AddProperty(CFX_GetCSSPropertyByEnum(CFX_CSSProperty::TextAlign), + alignString.AsStringView()); + } + } + ApplyDeclarations(declArray, pDecl.get(), pDest); +} + +void CFX_CSSStyleSelector::ApplyDeclarations( + const std::vector& declArray, + const CFX_CSSDeclaration* extraDecl, + CFX_CSSComputedStyle* pComputedStyle) { + std::vector importants; + std::vector normals; + std::vector customs; + + for (auto* decl : declArray) + ExtractValues(decl, &importants, &normals, &customs); + + if (extraDecl) + ExtractValues(extraDecl, &importants, &normals, &customs); + + for (auto* prop : normals) + ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle); + + for (auto* prop : customs) + pComputedStyle->AddCustomStyle(*prop); + + for (auto* prop : importants) + ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle); +} + +void CFX_CSSStyleSelector::ExtractValues( + const CFX_CSSDeclaration* decl, + std::vector* importants, + std::vector* normals, + std::vector* custom) { + for (const auto& holder : *decl) { + if (holder->bImportant) + importants->push_back(holder.get()); + else + normals->push_back(holder.get()); + } + for (auto it = decl->custom_begin(); it != decl->custom_end(); it++) + custom->push_back(it->get()); +} + +void CFX_CSSStyleSelector::AppendInlineStyle(CFX_CSSDeclaration* pDecl, + const WideString& style) { + ASSERT(pDecl && !style.IsEmpty()); + + auto pSyntax = pdfium::MakeUnique( + style.c_str(), style.GetLength(), 32, true); + int32_t iLen2 = 0; + const CFX_CSSPropertyTable* table = nullptr; + WideString wsName; + while (1) { + CFX_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse(); + if (eStatus == CFX_CSSSyntaxStatus::PropertyName) { + WideStringView strValue = pSyntax->GetCurrentString(); + table = CFX_GetCSSPropertyByName(strValue); + if (!table) + wsName = WideString(strValue); + } else if (eStatus == CFX_CSSSyntaxStatus::PropertyValue) { + if (table || iLen2 > 0) { + WideStringView strValue = pSyntax->GetCurrentString(); + if (!strValue.IsEmpty()) { + if (table) + pDecl->AddProperty(table, strValue); + else if (iLen2 > 0) + pDecl->AddProperty(wsName, WideString(strValue)); + } + } + } else { + break; + } + } +} + +void CFX_CSSStyleSelector::ApplyProperty(CFX_CSSProperty eProperty, + const RetainPtr& pValue, + CFX_CSSComputedStyle* pComputedStyle) { + if (pValue->GetType() != CFX_CSSPrimitiveType::List) { + CFX_CSSPrimitiveType eType = pValue->GetType(); + switch (eProperty) { + case CFX_CSSProperty::Display: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_NonInheritedData.m_eDisplay = + ToDisplay(pValue.As()->Value()); + } + break; + case CFX_CSSProperty::FontSize: { + float& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize; + if (eType == CFX_CSSPrimitiveType::Number) { + fFontSize = pValue.As()->Apply(fFontSize); + } else if (eType == CFX_CSSPrimitiveType::Enum) { + fFontSize = + ToFontSize(pValue.As()->Value(), fFontSize); + } + } break; + case CFX_CSSProperty::LineHeight: + if (eType == CFX_CSSPrimitiveType::Number) { + RetainPtr v = pValue.As(); + if (v->Kind() == CFX_CSSNumberType::Number) { + pComputedStyle->m_InheritedData.m_fLineHeight = + v->Value() * pComputedStyle->m_InheritedData.m_fFontSize; + } else { + pComputedStyle->m_InheritedData.m_fLineHeight = + v->Apply(pComputedStyle->m_InheritedData.m_fFontSize); + } + } + break; + case CFX_CSSProperty::TextAlign: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_InheritedData.m_eTextAlign = + ToTextAlign(pValue.As()->Value()); + } + break; + case CFX_CSSProperty::TextIndent: + SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent, + eType, pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + break; + case CFX_CSSProperty::FontWeight: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_InheritedData.m_wFontWeight = + ToFontWeight(pValue.As()->Value()); + } else if (eType == CFX_CSSPrimitiveType::Number) { + int32_t iValue = + (int32_t)pValue.As()->Value() / 100; + if (iValue >= 1 && iValue <= 9) { + pComputedStyle->m_InheritedData.m_wFontWeight = iValue * 100; + } + } + break; + case CFX_CSSProperty::FontStyle: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_InheritedData.m_eFontStyle = + ToFontStyle(pValue.As()->Value()); + } + break; + case CFX_CSSProperty::Color: + if (eType == CFX_CSSPrimitiveType::RGB) { + pComputedStyle->m_InheritedData.m_dwFontColor = + pValue.As()->Value(); + } + break; + case CFX_CSSProperty::MarginLeft: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_MarginWidth.left, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasMargin = true; + } + break; + case CFX_CSSProperty::MarginTop: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_MarginWidth.top, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasMargin = true; + } + break; + case CFX_CSSProperty::MarginRight: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_MarginWidth.right, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasMargin = true; + } + break; + case CFX_CSSProperty::MarginBottom: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_MarginWidth.bottom, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasMargin = true; + } + break; + case CFX_CSSProperty::PaddingLeft: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_PaddingWidth.left, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasPadding = true; + } + break; + case CFX_CSSProperty::PaddingTop: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_PaddingWidth.top, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasPadding = true; + } + break; + case CFX_CSSProperty::PaddingRight: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_PaddingWidth.right, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasPadding = true; + } + break; + case CFX_CSSProperty::PaddingBottom: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_PaddingWidth.bottom, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasPadding = true; + } + break; + case CFX_CSSProperty::BorderLeftWidth: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_BorderWidth.left, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasBorder = true; + } + break; + case CFX_CSSProperty::BorderTopWidth: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_BorderWidth.top, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasBorder = true; + } + break; + case CFX_CSSProperty::BorderRightWidth: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_BorderWidth.right, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasBorder = true; + } + break; + case CFX_CSSProperty::BorderBottomWidth: + if (SetLengthWithPercent( + pComputedStyle->m_NonInheritedData.m_BorderWidth.bottom, eType, + pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { + pComputedStyle->m_NonInheritedData.m_bHasBorder = true; + } + break; + case CFX_CSSProperty::VerticalAlign: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_NonInheritedData.m_eVerticalAlign = + ToVerticalAlign(pValue.As()->Value()); + } else if (eType == CFX_CSSPrimitiveType::Number) { + pComputedStyle->m_NonInheritedData.m_eVerticalAlign = + CFX_CSSVerticalAlign::Number; + pComputedStyle->m_NonInheritedData.m_fVerticalAlign = + pValue.As()->Apply( + pComputedStyle->m_InheritedData.m_fFontSize); + } + break; + case CFX_CSSProperty::FontVariant: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_InheritedData.m_eFontVariant = + ToFontVariant(pValue.As()->Value()); + } + break; + case CFX_CSSProperty::LetterSpacing: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_InheritedData.m_LetterSpacing.Set( + CFX_CSSLengthUnit::Normal); + } else if (eType == CFX_CSSPrimitiveType::Number) { + if (pValue.As()->Kind() == + CFX_CSSNumberType::Percent) { + break; + } + + SetLengthWithPercent(pComputedStyle->m_InheritedData.m_LetterSpacing, + eType, pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + } + break; + case CFX_CSSProperty::WordSpacing: + if (eType == CFX_CSSPrimitiveType::Enum) { + pComputedStyle->m_InheritedData.m_WordSpacing.Set( + CFX_CSSLengthUnit::Normal); + } else if (eType == CFX_CSSPrimitiveType::Number) { + if (pValue.As()->Kind() == + CFX_CSSNumberType::Percent) { + break; + } + SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing, + eType, pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + } + break; + case CFX_CSSProperty::Top: + SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Top, eType, + pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + break; + case CFX_CSSProperty::Bottom: + SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Bottom, eType, + pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + break; + case CFX_CSSProperty::Left: + SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Left, eType, + pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + break; + case CFX_CSSProperty::Right: + SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Right, eType, + pValue, + pComputedStyle->m_InheritedData.m_fFontSize); + break; + default: + break; + } + } else if (pValue->GetType() == CFX_CSSPrimitiveType::List) { + RetainPtr pList = pValue.As(); + int32_t iCount = pList->CountValues(); + if (iCount > 0) { + switch (eProperty) { + case CFX_CSSProperty::FontFamily: + pComputedStyle->m_InheritedData.m_pFontFamily = pList; + break; + case CFX_CSSProperty::TextDecoration: + pComputedStyle->m_NonInheritedData.m_dwTextDecoration = + ToTextDecoration(pList); + break; + default: + break; + } + } + } else { + NOTREACHED(); + } +} + +CFX_CSSDisplay CFX_CSSStyleSelector::ToDisplay(CFX_CSSPropertyValue eValue) { + switch (eValue) { + case CFX_CSSPropertyValue::Block: + return CFX_CSSDisplay::Block; + case CFX_CSSPropertyValue::None: + return CFX_CSSDisplay::None; + case CFX_CSSPropertyValue::ListItem: + return CFX_CSSDisplay::ListItem; + case CFX_CSSPropertyValue::InlineTable: + return CFX_CSSDisplay::InlineTable; + case CFX_CSSPropertyValue::InlineBlock: + return CFX_CSSDisplay::InlineBlock; + case CFX_CSSPropertyValue::Inline: + default: + return CFX_CSSDisplay::Inline; + } +} + +CFX_CSSTextAlign CFX_CSSStyleSelector::ToTextAlign( + CFX_CSSPropertyValue eValue) { + switch (eValue) { + case CFX_CSSPropertyValue::Center: + return CFX_CSSTextAlign::Center; + case CFX_CSSPropertyValue::Right: + return CFX_CSSTextAlign::Right; + case CFX_CSSPropertyValue::Justify: + return CFX_CSSTextAlign::Justify; + case CFX_CSSPropertyValue::Left: + default: + return CFX_CSSTextAlign::Left; + } +} + +uint16_t CFX_CSSStyleSelector::ToFontWeight(CFX_CSSPropertyValue eValue) { + switch (eValue) { + case CFX_CSSPropertyValue::Bold: + return 700; + case CFX_CSSPropertyValue::Bolder: + return 900; + case CFX_CSSPropertyValue::Lighter: + return 200; + case CFX_CSSPropertyValue::Normal: + default: + return 400; + } +} + +CFX_CSSFontStyle CFX_CSSStyleSelector::ToFontStyle( + CFX_CSSPropertyValue eValue) { + switch (eValue) { + case CFX_CSSPropertyValue::Italic: + case CFX_CSSPropertyValue::Oblique: + return CFX_CSSFontStyle::Italic; + default: + return CFX_CSSFontStyle::Normal; + } +} + +bool CFX_CSSStyleSelector::SetLengthWithPercent( + CFX_CSSLength& width, + CFX_CSSPrimitiveType eType, + const RetainPtr& pValue, + float fFontSize) { + if (eType == CFX_CSSPrimitiveType::Number) { + RetainPtr v = pValue.As(); + if (v->Kind() == CFX_CSSNumberType::Percent) { + width.Set(CFX_CSSLengthUnit::Percent, + pValue.As()->Value() / 100.0f); + return width.NonZero(); + } + + float fValue = v->Apply(fFontSize); + width.Set(CFX_CSSLengthUnit::Point, fValue); + return width.NonZero(); + } else if (eType == CFX_CSSPrimitiveType::Enum) { + switch (pValue.As()->Value()) { + case CFX_CSSPropertyValue::Auto: + width.Set(CFX_CSSLengthUnit::Auto); + return true; + case CFX_CSSPropertyValue::None: + width.Set(CFX_CSSLengthUnit::None); + return true; + case CFX_CSSPropertyValue::Thin: + width.Set(CFX_CSSLengthUnit::Point, 2); + return true; + case CFX_CSSPropertyValue::Medium: + width.Set(CFX_CSSLengthUnit::Point, 3); + return true; + case CFX_CSSPropertyValue::Thick: + width.Set(CFX_CSSLengthUnit::Point, 4); + return true; + default: + return false; + } + } + return false; +} + +float CFX_CSSStyleSelector::ToFontSize(CFX_CSSPropertyValue eValue, + float fCurFontSize) { + switch (eValue) { + case CFX_CSSPropertyValue::XxSmall: + return m_fDefFontSize / 1.2f / 1.2f / 1.2f; + case CFX_CSSPropertyValue::XSmall: + return m_fDefFontSize / 1.2f / 1.2f; + case CFX_CSSPropertyValue::Small: + return m_fDefFontSize / 1.2f; + case CFX_CSSPropertyValue::Medium: + return m_fDefFontSize; + case CFX_CSSPropertyValue::Large: + return m_fDefFontSize * 1.2f; + case CFX_CSSPropertyValue::XLarge: + return m_fDefFontSize * 1.2f * 1.2f; + case CFX_CSSPropertyValue::XxLarge: + return m_fDefFontSize * 1.2f * 1.2f * 1.2f; + case CFX_CSSPropertyValue::Larger: + return fCurFontSize * 1.2f; + case CFX_CSSPropertyValue::Smaller: + return fCurFontSize / 1.2f; + default: + return fCurFontSize; + } +} + +CFX_CSSVerticalAlign CFX_CSSStyleSelector::ToVerticalAlign( + CFX_CSSPropertyValue eValue) { + switch (eValue) { + case CFX_CSSPropertyValue::Middle: + return CFX_CSSVerticalAlign::Middle; + case CFX_CSSPropertyValue::Bottom: + return CFX_CSSVerticalAlign::Bottom; + case CFX_CSSPropertyValue::Super: + return CFX_CSSVerticalAlign::Super; + case CFX_CSSPropertyValue::Sub: + return CFX_CSSVerticalAlign::Sub; + case CFX_CSSPropertyValue::Top: + return CFX_CSSVerticalAlign::Top; + case CFX_CSSPropertyValue::TextTop: + return CFX_CSSVerticalAlign::TextTop; + case CFX_CSSPropertyValue::TextBottom: + return CFX_CSSVerticalAlign::TextBottom; + case CFX_CSSPropertyValue::Baseline: + default: + return CFX_CSSVerticalAlign::Baseline; + } +} + +uint32_t CFX_CSSStyleSelector::ToTextDecoration( + const RetainPtr& pValue) { + uint32_t dwDecoration = 0; + for (int32_t i = pValue->CountValues() - 1; i >= 0; --i) { + const RetainPtr pVal = pValue->GetValue(i); + if (pVal->GetType() != CFX_CSSPrimitiveType::Enum) + continue; + + switch (pVal.As()->Value()) { + case CFX_CSSPropertyValue::Underline: + dwDecoration |= CFX_CSSTEXTDECORATION_Underline; + break; + case CFX_CSSPropertyValue::LineThrough: + dwDecoration |= CFX_CSSTEXTDECORATION_LineThrough; + break; + case CFX_CSSPropertyValue::Overline: + dwDecoration |= CFX_CSSTEXTDECORATION_Overline; + break; + case CFX_CSSPropertyValue::Blink: + dwDecoration |= CFX_CSSTEXTDECORATION_Blink; + break; + case CFX_CSSPropertyValue::Double: + dwDecoration |= CFX_CSSTEXTDECORATION_Double; + break; + default: + break; + } + } + return dwDecoration; +} + +CFX_CSSFontVariant CFX_CSSStyleSelector::ToFontVariant( + CFX_CSSPropertyValue eValue) { + return eValue == CFX_CSSPropertyValue::SmallCaps + ? CFX_CSSFontVariant::SmallCaps + : CFX_CSSFontVariant::Normal; +} diff --git a/core/fxcrt/css/cfx_cssstyleselector.h b/core/fxcrt/css/cfx_cssstyleselector.h new file mode 100644 index 0000000000000000000000000000000000000000..13a0f74427fff2cb82a9c4a703885f19b60e54f5 --- /dev/null +++ b/core/fxcrt/css/cfx_cssstyleselector.h @@ -0,0 +1,83 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSSTYLESELECTOR_H_ +#define CORE_FXCRT_CSS_CFX_CSSSTYLESELECTOR_H_ + +#include +#include + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_cssrulecollection.h" +#include "core/fxcrt/fx_system.h" + +class CFX_CSSComputedStyle; +class CFX_CSSCustomProperty; +class CFX_CSSDeclaration; +class CFX_CSSPropertyHolder; +class CFX_CSSSelector; +class CFX_CSSStyleSheet; +class CFX_CSSValue; +class CFX_CSSValueList; + +class CFX_CSSStyleSelector { + public: + CFX_CSSStyleSelector(); + ~CFX_CSSStyleSelector(); + + void SetDefFontSize(float fFontSize); + void SetUAStyleSheet(std::unique_ptr pSheet); + void UpdateStyleIndex(); + + RetainPtr CreateComputedStyle( + CFX_CSSComputedStyle* pParentStyle); + + // Note, the dest style has to be an out param because the CXFA_TextParser + // adds non-inherited data from the parent style. Attempting to copy + // internally will fail as you'll lose the non-inherited data. + void ComputeStyle(const std::vector& declArray, + const WideString& styleString, + const WideString& alignString, + CFX_CSSComputedStyle* pDestStyle); + + std::vector MatchDeclarations( + const WideString& tagname); + + private: + bool MatchSelector(const WideString& tagname, CFX_CSSSelector* pSel); + + void AppendInlineStyle(CFX_CSSDeclaration* pDecl, const WideString& style); + void ApplyDeclarations( + const std::vector& declArray, + const CFX_CSSDeclaration* extraDecl, + CFX_CSSComputedStyle* pDestStyle); + void ApplyProperty(CFX_CSSProperty eProperty, + const RetainPtr& pValue, + CFX_CSSComputedStyle* pComputedStyle); + void ExtractValues(const CFX_CSSDeclaration* decl, + std::vector* importants, + std::vector* normals, + std::vector* custom); + + bool SetLengthWithPercent(CFX_CSSLength& width, + CFX_CSSPrimitiveType eType, + const RetainPtr& pValue, + float fFontSize); + float ToFontSize(CFX_CSSPropertyValue eValue, float fCurFontSize); + CFX_CSSDisplay ToDisplay(CFX_CSSPropertyValue eValue); + CFX_CSSTextAlign ToTextAlign(CFX_CSSPropertyValue eValue); + uint16_t ToFontWeight(CFX_CSSPropertyValue eValue); + CFX_CSSFontStyle ToFontStyle(CFX_CSSPropertyValue eValue); + CFX_CSSVerticalAlign ToVerticalAlign(CFX_CSSPropertyValue eValue); + uint32_t ToTextDecoration(const RetainPtr& pList); + CFX_CSSFontVariant ToFontVariant(CFX_CSSPropertyValue eValue); + + float m_fDefFontSize; + std::unique_ptr m_UAStyles; + CFX_CSSRuleCollection m_UARules; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSSTYLESELECTOR_H_ diff --git a/core/fxcrt/css/cfx_cssstylesheet.cpp b/core/fxcrt/css/cfx_cssstylesheet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..183765f3b0b83001ef015c2602f072692296dfe0 --- /dev/null +++ b/core/fxcrt/css/cfx_cssstylesheet.cpp @@ -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 + +#include "core/fxcrt/css/cfx_cssstylesheet.h" + +#include + +#include "core/fxcrt/css/cfx_cssdatatable.h" +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/css/cfx_cssstylerule.h" +#include "core/fxcrt/fx_codepage.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CFX_CSSStyleSheet::CFX_CSSStyleSheet() {} + +CFX_CSSStyleSheet::~CFX_CSSStyleSheet() { + Reset(); +} + +void CFX_CSSStyleSheet::Reset() { + m_RuleArray.clear(); + m_StringCache.clear(); +} + +int32_t CFX_CSSStyleSheet::CountRules() const { + return pdfium::CollectionSize(m_RuleArray); +} + +CFX_CSSStyleRule* CFX_CSSStyleSheet::GetRule(int32_t index) const { + return m_RuleArray[index].get(); +} + +bool CFX_CSSStyleSheet::LoadBuffer(const wchar_t* pBuffer, int32_t iBufSize) { + ASSERT(pBuffer); + ASSERT(iBufSize > 0); + + auto pSyntax = pdfium::MakeUnique(pBuffer, iBufSize); + Reset(); + CFX_CSSSyntaxStatus eStatus; + do { + switch (eStatus = pSyntax->DoSyntaxParse()) { + case CFX_CSSSyntaxStatus::StyleRule: + eStatus = LoadStyleRule(pSyntax.get(), &m_RuleArray); + break; + default: + break; + } + } while (eStatus >= CFX_CSSSyntaxStatus::None); + + m_StringCache.clear(); + return eStatus != CFX_CSSSyntaxStatus::Error; +} + +CFX_CSSSyntaxStatus CFX_CSSStyleSheet::LoadStyleRule( + CFX_CSSSyntaxParser* pSyntax, + std::vector>* ruleArray) { + std::vector> selectors; + + CFX_CSSStyleRule* pStyleRule = nullptr; + int32_t iValueLen = 0; + const CFX_CSSPropertyTable* propertyTable = nullptr; + WideString wsName; + while (1) { + switch (pSyntax->DoSyntaxParse()) { + case CFX_CSSSyntaxStatus::Selector: { + WideStringView strValue = pSyntax->GetCurrentString(); + auto pSelector = CFX_CSSSelector::FromString(strValue); + if (pSelector) + selectors.push_back(std::move(pSelector)); + break; + } + case CFX_CSSSyntaxStatus::PropertyName: { + WideStringView strValue = pSyntax->GetCurrentString(); + propertyTable = CFX_GetCSSPropertyByName(strValue); + if (!propertyTable) + wsName = WideString(strValue); + break; + } + case CFX_CSSSyntaxStatus::PropertyValue: { + if (propertyTable || iValueLen > 0) { + WideStringView strValue = pSyntax->GetCurrentString(); + auto* decl = pStyleRule->GetDeclaration(); + if (!strValue.IsEmpty()) { + if (propertyTable) { + decl->AddProperty(propertyTable, strValue); + } else { + decl->AddProperty(wsName, WideString(strValue)); + } + } + } + break; + } + case CFX_CSSSyntaxStatus::DeclOpen: { + if (!pStyleRule && !selectors.empty()) { + auto rule = pdfium::MakeUnique(); + pStyleRule = rule.get(); + pStyleRule->SetSelector(&selectors); + ruleArray->push_back(std::move(rule)); + } else { + SkipRuleSet(pSyntax); + return CFX_CSSSyntaxStatus::None; + } + break; + } + case CFX_CSSSyntaxStatus::DeclClose: { + if (pStyleRule && pStyleRule->GetDeclaration()->empty()) { + ruleArray->pop_back(); + pStyleRule = nullptr; + } + return CFX_CSSSyntaxStatus::None; + } + case CFX_CSSSyntaxStatus::EOS: + return CFX_CSSSyntaxStatus::EOS; + case CFX_CSSSyntaxStatus::Error: + default: + return CFX_CSSSyntaxStatus::Error; + } + } +} + +void CFX_CSSStyleSheet::SkipRuleSet(CFX_CSSSyntaxParser* pSyntax) { + while (1) { + switch (pSyntax->DoSyntaxParse()) { + case CFX_CSSSyntaxStatus::Selector: + case CFX_CSSSyntaxStatus::DeclOpen: + case CFX_CSSSyntaxStatus::PropertyName: + case CFX_CSSSyntaxStatus::PropertyValue: + break; + case CFX_CSSSyntaxStatus::DeclClose: + case CFX_CSSSyntaxStatus::EOS: + case CFX_CSSSyntaxStatus::Error: + default: + return; + } + } +} diff --git a/core/fxcrt/css/cfx_cssstylesheet.h b/core/fxcrt/css/cfx_cssstylesheet.h new file mode 100644 index 0000000000000000000000000000000000000000..3f3a94a84b6d6b9c9953c11597a7d61ab07de0e7 --- /dev/null +++ b/core/fxcrt/css/cfx_cssstylesheet.h @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSSTYLESHEET_H_ +#define CORE_FXCRT_CSS_CFX_CSSSTYLESHEET_H_ + +#include +#include +#include + +#include "core/fxcrt/css/cfx_csssyntaxparser.h" +#include "core/fxcrt/fx_string.h" + +class CFX_CSSStyleRule; + +class CFX_CSSStyleSheet { + public: + CFX_CSSStyleSheet(); + ~CFX_CSSStyleSheet(); + + bool LoadBuffer(const wchar_t* pBuffer, int32_t iBufSize); + + int32_t CountRules() const; + CFX_CSSStyleRule* GetRule(int32_t index) const; + + private: + void Reset(); + CFX_CSSSyntaxStatus LoadStyleRule( + CFX_CSSSyntaxParser* pSyntax, + std::vector>* ruleArray); + void SkipRuleSet(CFX_CSSSyntaxParser* pSyntax); + + std::vector> m_RuleArray; + std::map m_StringCache; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSSTYLESHEET_H_ diff --git a/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..baa002b05c63369b9cb771c96a8adffedbef0baa --- /dev/null +++ b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp @@ -0,0 +1,239 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssstylesheet.h" + +#include +#include + +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/css/cfx_cssenumvalue.h" +#include "core/fxcrt/css/cfx_cssnumbervalue.h" +#include "core/fxcrt/css/cfx_cssstylerule.h" +#include "core/fxcrt/css/cfx_cssvaluelist.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +class CFX_CSSStyleSheetTest : public testing::Test { + public: + void SetUp() override { + sheet_ = pdfium::MakeUnique(); + decl_ = nullptr; + } + + void TearDown() override { decl_ = nullptr; } + + void LoadAndVerifyDecl(const wchar_t* buf, + const std::vector& selectors, + size_t decl_count) { + ASSERT(sheet_); + + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(sheet_->CountRules(), 1); + + CFX_CSSStyleRule* style = sheet_->GetRule(0); + EXPECT_EQ(selectors.size(), style->CountSelectorLists()); + + for (size_t i = 0; i < selectors.size(); i++) { + uint32_t hash = FX_HashCode_GetW(selectors[i].AsStringView(), true); + EXPECT_EQ(hash, style->GetSelectorList(i)->GetNameHash()); + } + + decl_ = style->GetDeclaration(); + EXPECT_EQ(decl_->PropertyCountForTesting(), decl_count); + } + + void VerifyFloat(CFX_CSSProperty prop, float val, CFX_CSSNumberType type) { + ASSERT(decl_); + + bool important; + RetainPtr v = decl_->GetProperty(prop, &important); + EXPECT_EQ(v->GetType(), CFX_CSSPrimitiveType::Number); + EXPECT_EQ(v.As()->Kind(), type); + EXPECT_EQ(v.As()->Value(), val); + } + + void VerifyEnum(CFX_CSSProperty prop, CFX_CSSPropertyValue val) { + ASSERT(decl_); + + bool important; + RetainPtr v = decl_->GetProperty(prop, &important); + EXPECT_EQ(v->GetType(), CFX_CSSPrimitiveType::Enum); + EXPECT_EQ(v.As()->Value(), val); + } + + void VerifyList(CFX_CSSProperty prop, + std::vector values) { + ASSERT(decl_); + + bool important; + RetainPtr list = + decl_->GetProperty(prop, &important).As(); + EXPECT_EQ(list->CountValues(), pdfium::CollectionSize(values)); + + for (size_t i = 0; i < values.size(); i++) { + RetainPtr val = list->GetValue(i); + EXPECT_EQ(val->GetType(), CFX_CSSPrimitiveType::Enum); + EXPECT_EQ(val.As()->Value(), values[i]); + } + } + + std::unique_ptr sheet_; + CFX_CSSDeclaration* decl_; +}; + +TEST_F(CFX_CSSStyleSheetTest, ParseMultipleSelectors) { + const wchar_t* buf = + L"a { border: 10px; }\nb { text-decoration: underline; }"; + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(2, sheet_->CountRules()); + + CFX_CSSStyleRule* style = sheet_->GetRule(0); + EXPECT_EQ(1UL, style->CountSelectorLists()); + + bool found_selector = false; + uint32_t hash = FX_HashCode_GetW(L"a", true); + for (size_t i = 0; i < style->CountSelectorLists(); i++) { + if (style->GetSelectorList(i)->GetNameHash() == hash) { + found_selector = true; + break; + } + } + EXPECT_TRUE(found_selector); + + decl_ = style->GetDeclaration(); + EXPECT_EQ(4UL, decl_->PropertyCountForTesting()); + + VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 10.0, + CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderRightWidth, 10.0, + CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderTopWidth, 10.0, CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 10.0, + CFX_CSSNumberType::Pixels); + + style = sheet_->GetRule(1); + EXPECT_EQ(1UL, style->CountSelectorLists()); + + found_selector = false; + hash = FX_HashCode_GetW(L"b", true); + for (size_t i = 0; i < style->CountSelectorLists(); i++) { + if (style->GetSelectorList(i)->GetNameHash() == hash) { + found_selector = true; + break; + } + } + EXPECT_TRUE(found_selector); + + decl_ = style->GetDeclaration(); + EXPECT_EQ(1UL, decl_->PropertyCountForTesting()); + VerifyList(CFX_CSSProperty::TextDecoration, + {CFX_CSSPropertyValue::Underline}); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseChildSelectors) { + const wchar_t* buf = L"a b c { border: 10px; }"; + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(1, sheet_->CountRules()); + + CFX_CSSStyleRule* style = sheet_->GetRule(0); + EXPECT_EQ(1UL, style->CountSelectorLists()); + + auto* sel = style->GetSelectorList(0); + EXPECT_TRUE(sel != nullptr); + EXPECT_EQ(FX_HashCode_GetW(L"c", true), sel->GetNameHash()); + + sel = sel->GetNextSelector(); + EXPECT_TRUE(sel != nullptr); + EXPECT_EQ(FX_HashCode_GetW(L"b", true), sel->GetNameHash()); + + sel = sel->GetNextSelector(); + EXPECT_TRUE(sel != nullptr); + EXPECT_EQ(FX_HashCode_GetW(L"a", true), sel->GetNameHash()); + + sel = sel->GetNextSelector(); + EXPECT_TRUE(sel == nullptr); + + decl_ = style->GetDeclaration(); + EXPECT_EQ(4UL, decl_->PropertyCountForTesting()); + + VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 10.0, + CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderRightWidth, 10.0, + CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderTopWidth, 10.0, CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 10.0, + CFX_CSSNumberType::Pixels); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseUnhandledSelectors) { + const wchar_t* buf = L"a > b { padding: 0; }"; + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(0, sheet_->CountRules()); + + buf = L"a[first] { padding: 0; }"; + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(0, sheet_->CountRules()); + + buf = L"a+b { padding: 0; }"; + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(0, sheet_->CountRules()); + + buf = L"a ^ b { padding: 0; }"; + EXPECT_TRUE(sheet_->LoadBuffer(buf, wcslen(buf))); + EXPECT_EQ(0, sheet_->CountRules()); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseMultipleSelectorsCombined) { + LoadAndVerifyDecl(L"a, b, c { border: 5px; }", {L"a", L"b", L"c"}, 4); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorder) { + LoadAndVerifyDecl(L"a { border: 5px; }", {L"a"}, 4); + VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 5.0, CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderRightWidth, 5.0, + CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderTopWidth, 5.0, CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 5.0, + CFX_CSSNumberType::Pixels); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorderFull) { + LoadAndVerifyDecl(L"a { border: 5px solid red; }", {L"a"}, 4); + VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 5.0, CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderRightWidth, 5.0, + CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderTopWidth, 5.0, CFX_CSSNumberType::Pixels); + VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 5.0, + CFX_CSSNumberType::Pixels); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorderLeft) { + LoadAndVerifyDecl(L"a { border-left: 2.5pc; }", {L"a"}, 1); + VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 2.5, CFX_CSSNumberType::Picas); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorderLeftThick) { + LoadAndVerifyDecl(L"a { border-left: thick; }", {L"a"}, 1); + VerifyEnum(CFX_CSSProperty::BorderLeftWidth, CFX_CSSPropertyValue::Thick); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorderRight) { + LoadAndVerifyDecl(L"a { border-right: 2.5pc; }", {L"a"}, 1); + VerifyFloat(CFX_CSSProperty::BorderRightWidth, 2.5, CFX_CSSNumberType::Picas); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorderTop) { + LoadAndVerifyDecl(L"a { border-top: 2.5pc; }", {L"a"}, 1); + VerifyFloat(CFX_CSSProperty::BorderTopWidth, 2.5, CFX_CSSNumberType::Picas); +} + +TEST_F(CFX_CSSStyleSheetTest, ParseBorderBottom) { + LoadAndVerifyDecl(L"a { border-bottom: 2.5pc; }", {L"a"}, 1); + VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 2.5, + CFX_CSSNumberType::Picas); +} diff --git a/core/fxcrt/css/cfx_csssyntaxparser.cpp b/core/fxcrt/css/cfx_csssyntaxparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..066b82b5d67538f927beafe782a4071bfcd12e08 --- /dev/null +++ b/core/fxcrt/css/cfx_csssyntaxparser.cpp @@ -0,0 +1,228 @@ +// 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 "core/fxcrt/css/cfx_csssyntaxparser.h" + +#include + +#include "core/fxcrt/css/cfx_cssdatatable.h" +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/logging.h" + +namespace { + +bool IsSelectorStart(wchar_t wch) { + return wch == '.' || wch == '#' || wch == '*' || FXSYS_iswalpha(wch); +} + +} // namespace + +CFX_CSSSyntaxParser::CFX_CSSSyntaxParser(const wchar_t* pBuffer, + int32_t iBufferSize) + : CFX_CSSSyntaxParser(pBuffer, iBufferSize, 32, false) {} + +CFX_CSSSyntaxParser::CFX_CSSSyntaxParser(const wchar_t* pBuffer, + int32_t iBufferSize, + int32_t iTextDatSize, + bool bOnlyDeclaration) + : m_iTextDataLen(0), + m_dwCheck(0xFFFFFFFF), + m_eStatus(CFX_CSSSyntaxStatus::None) { + ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0); + m_eMode = bOnlyDeclaration ? CFX_CSSSyntaxMode::PropertyName + : CFX_CSSSyntaxMode::RuleSet; + m_TextData.InitWithSize(iTextDatSize); + m_TextPlane.AttachBuffer(pBuffer, iBufferSize); +} + +CFX_CSSSyntaxParser::~CFX_CSSSyntaxParser() {} + +CFX_CSSSyntaxStatus CFX_CSSSyntaxParser::DoSyntaxParse() { + while (m_eStatus >= CFX_CSSSyntaxStatus::None) { + if (m_TextPlane.IsEOF()) { + if (m_eMode == CFX_CSSSyntaxMode::PropertyValue && + m_TextData.GetLength() > 0) { + SaveTextData(); + m_eStatus = CFX_CSSSyntaxStatus::PropertyValue; + return m_eStatus; + } + m_eStatus = CFX_CSSSyntaxStatus::EOS; + return m_eStatus; + } + wchar_t wch; + while (!m_TextPlane.IsEOF()) { + wch = m_TextPlane.GetChar(); + switch (m_eMode) { + case CFX_CSSSyntaxMode::RuleSet: + switch (wch) { + case '}': + m_TextPlane.MoveNext(); + if (RestoreMode()) + return CFX_CSSSyntaxStatus::DeclClose; + + m_eStatus = CFX_CSSSyntaxStatus::Error; + return m_eStatus; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + m_ModeStack.push(m_eMode); + SwitchMode(CFX_CSSSyntaxMode::Comment); + break; + } + default: + if (wch <= ' ') { + m_TextPlane.MoveNext(); + } else if (IsSelectorStart(wch)) { + SwitchMode(CFX_CSSSyntaxMode::Selector); + return CFX_CSSSyntaxStatus::StyleRule; + } else { + m_eStatus = CFX_CSSSyntaxStatus::Error; + return m_eStatus; + } + break; + } + break; + case CFX_CSSSyntaxMode::Selector: + switch (wch) { + case ',': + m_TextPlane.MoveNext(); + SwitchMode(CFX_CSSSyntaxMode::Selector); + if (m_iTextDataLen > 0) + return CFX_CSSSyntaxStatus::Selector; + break; + case '{': + if (m_TextData.GetLength() > 0) { + SaveTextData(); + return CFX_CSSSyntaxStatus::Selector; + } + m_TextPlane.MoveNext(); + m_ModeStack.push(CFX_CSSSyntaxMode::RuleSet); + SwitchMode(CFX_CSSSyntaxMode::PropertyName); + return CFX_CSSSyntaxStatus::DeclOpen; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return CFX_CSSSyntaxStatus::Selector; + break; + } + default: + AppendChar(wch); + break; + } + break; + case CFX_CSSSyntaxMode::PropertyName: + switch (wch) { + case ':': + m_TextPlane.MoveNext(); + SwitchMode(CFX_CSSSyntaxMode::PropertyValue); + return CFX_CSSSyntaxStatus::PropertyName; + case '}': + m_TextPlane.MoveNext(); + if (RestoreMode()) + return CFX_CSSSyntaxStatus::DeclClose; + + m_eStatus = CFX_CSSSyntaxStatus::Error; + return m_eStatus; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return CFX_CSSSyntaxStatus::PropertyName; + break; + } + default: + AppendChar(wch); + break; + } + break; + case CFX_CSSSyntaxMode::PropertyValue: + switch (wch) { + case ';': + m_TextPlane.MoveNext(); + case '}': + SwitchMode(CFX_CSSSyntaxMode::PropertyName); + return CFX_CSSSyntaxStatus::PropertyValue; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return CFX_CSSSyntaxStatus::PropertyValue; + break; + } + default: + AppendChar(wch); + break; + } + break; + case CFX_CSSSyntaxMode::Comment: + if (wch == '/' && m_TextData.GetLength() > 0 && + m_TextData.GetBuffer()[m_TextData.GetLength() - 1] == '*') { + RestoreMode(); + } else { + m_TextData.AppendChar(wch); + } + m_TextPlane.MoveNext(); + break; + case CFX_CSSSyntaxMode::UnknownRule: + if (wch == ';') + SwitchMode(CFX_CSSSyntaxMode::RuleSet); + m_TextPlane.MoveNext(); + break; + default: + NOTREACHED(); + break; + } + } + } + return m_eStatus; +} + +bool CFX_CSSSyntaxParser::IsImportEnabled() const { + if ((m_dwCheck & CFX_CSSSYNTAXCHECK_AllowImport) == 0) + return false; + if (m_ModeStack.size() > 1) + return false; + return true; +} + +bool CFX_CSSSyntaxParser::AppendChar(wchar_t wch) { + m_TextPlane.MoveNext(); + if (m_TextData.GetLength() > 0 || wch > ' ') { + m_TextData.AppendChar(wch); + return true; + } + return false; +} + +int32_t CFX_CSSSyntaxParser::SaveTextData() { + m_iTextDataLen = m_TextData.TrimEnd(); + m_TextData.Clear(); + return m_iTextDataLen; +} + +void CFX_CSSSyntaxParser::SwitchMode(CFX_CSSSyntaxMode eMode) { + m_eMode = eMode; + SaveTextData(); +} + +int32_t CFX_CSSSyntaxParser::SwitchToComment() { + int32_t iLength = m_TextData.GetLength(); + m_ModeStack.push(m_eMode); + SwitchMode(CFX_CSSSyntaxMode::Comment); + return iLength; +} + +bool CFX_CSSSyntaxParser::RestoreMode() { + if (m_ModeStack.empty()) + return false; + + SwitchMode(m_ModeStack.top()); + m_ModeStack.pop(); + return true; +} + +WideStringView CFX_CSSSyntaxParser::GetCurrentString() const { + return WideStringView(m_TextData.GetBuffer(), m_iTextDataLen); +} diff --git a/core/fxcrt/css/cfx_csssyntaxparser.h b/core/fxcrt/css/cfx_csssyntaxparser.h new file mode 100644 index 0000000000000000000000000000000000000000..778f9a327274c789d715452288ce621fce1117a4 --- /dev/null +++ b/core/fxcrt/css/cfx_csssyntaxparser.h @@ -0,0 +1,75 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSSYNTAXPARSER_H_ +#define CORE_FXCRT_CSS_CFX_CSSSYNTAXPARSER_H_ + +#include + +#include "core/fxcrt/css/cfx_cssexttextbuf.h" +#include "core/fxcrt/css/cfx_csstextbuf.h" +#include "core/fxcrt/fx_string.h" + +#define CFX_CSSSYNTAXCHECK_AllowCharset 1 +#define CFX_CSSSYNTAXCHECK_AllowImport 2 + +enum class CFX_CSSSyntaxMode { + RuleSet, + Comment, + UnknownRule, + Selector, + PropertyName, + PropertyValue, +}; + +enum class CFX_CSSSyntaxStatus : uint8_t { + Error, + EOS, + None, + StyleRule, + Selector, + DeclOpen, + DeclClose, + PropertyName, + PropertyValue, +}; + +class CFX_CSSSyntaxParser { + public: + CFX_CSSSyntaxParser(const wchar_t* pBuffer, int32_t iBufferSize); + CFX_CSSSyntaxParser(const wchar_t* pBuffer, + int32_t iBufferSize, + int32_t iTextDatSize, + bool bOnlyDeclaration); + ~CFX_CSSSyntaxParser(); + + CFX_CSSSyntaxStatus DoSyntaxParse(); + WideStringView GetCurrentString() const; + + protected: + void SwitchMode(CFX_CSSSyntaxMode eMode); + int32_t SwitchToComment(); + + bool RestoreMode(); + bool AppendChar(wchar_t wch); + int32_t SaveTextData(); + bool IsCharsetEnabled() const { + return (m_dwCheck & CFX_CSSSYNTAXCHECK_AllowCharset) != 0; + } + void DisableCharset() { m_dwCheck = CFX_CSSSYNTAXCHECK_AllowImport; } + bool IsImportEnabled() const; + void DisableImport() { m_dwCheck = 0; } + + CFX_CSSTextBuf m_TextData; + CFX_CSSExtTextBuf m_TextPlane; + int32_t m_iTextDataLen; + uint32_t m_dwCheck; + CFX_CSSSyntaxMode m_eMode; + CFX_CSSSyntaxStatus m_eStatus; + std::stack m_ModeStack; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSSYNTAXPARSER_H_ diff --git a/core/fxcrt/css/cfx_csstextbuf.cpp b/core/fxcrt/css/cfx_csstextbuf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2f3b944196f2519f31e7bacdbdb18021feee8b1 --- /dev/null +++ b/core/fxcrt/css/cfx_csstextbuf.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_csstextbuf.h" + +#include "core/fxcrt/fx_memory.h" + +CFX_CSSTextBuf::CFX_CSSTextBuf() + : m_pBuffer(nullptr), m_iBufLen(0), m_iDatLen(0) {} + +CFX_CSSTextBuf::~CFX_CSSTextBuf() { + FX_Free(m_pBuffer); + m_pBuffer = nullptr; + m_iDatLen = m_iBufLen; +} + +void CFX_CSSTextBuf::InitWithSize(int32_t iAllocSize) { + ExpandBuf(iAllocSize); +} + +void CFX_CSSTextBuf::AppendChar(wchar_t wch) { + if (m_iDatLen >= m_iBufLen) + ExpandBuf(m_iBufLen * 2); + + m_pBuffer[m_iDatLen++] = wch; +} + +int32_t CFX_CSSTextBuf::TrimEnd() { + while (m_iDatLen > 0 && m_pBuffer[m_iDatLen - 1] <= ' ') + --m_iDatLen; + AppendChar(0); + return --m_iDatLen; +} + +void CFX_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) { + ASSERT(iDesiredSize > 0); + if (m_pBuffer && m_iBufLen == iDesiredSize) + return; + + if (m_pBuffer) + m_pBuffer = FX_Realloc(wchar_t, m_pBuffer, iDesiredSize); + else + m_pBuffer = FX_Alloc(wchar_t, iDesiredSize); + + m_iBufLen = iDesiredSize; +} diff --git a/core/fxcrt/css/cfx_csstextbuf.h b/core/fxcrt/css/cfx_csstextbuf.h new file mode 100644 index 0000000000000000000000000000000000000000..e1b9c64e1443060335e520206003bd3b5af87c83 --- /dev/null +++ b/core/fxcrt/css/cfx_csstextbuf.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSTEXTBUF_H_ +#define CORE_FXCRT_CSS_CFX_CSSTEXTBUF_H_ + +#include "core/fxcrt/fx_system.h" + +class CFX_CSSTextBuf { + public: + CFX_CSSTextBuf(); + ~CFX_CSSTextBuf(); + + void InitWithSize(int32_t iAllocSize); + void AppendChar(wchar_t wch); + + void Clear() { m_iDatLen = 0; } + + int32_t TrimEnd(); + + int32_t GetLength() const { return m_iDatLen; } + const wchar_t* GetBuffer() const { return m_pBuffer; } + + protected: + void ExpandBuf(int32_t iDesiredSize); + + wchar_t* m_pBuffer; + int32_t m_iBufLen; + int32_t m_iDatLen; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSTEXTBUF_H_ diff --git a/core/fxcrt/css/cfx_cssvalue.cpp b/core/fxcrt/css/cfx_cssvalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a55fc742b0276bac471aeb66be6fe3309ab5406a --- /dev/null +++ b/core/fxcrt/css/cfx_cssvalue.cpp @@ -0,0 +1,9 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssvalue.h" + +CFX_CSSValue::CFX_CSSValue(CFX_CSSPrimitiveType type) : m_value(type) {} diff --git a/core/fxcrt/css/cfx_cssvalue.h b/core/fxcrt/css/cfx_cssvalue.h new file mode 100644 index 0000000000000000000000000000000000000000..f143e96036ce27d5c33944cbaa6e93735bbd770b --- /dev/null +++ b/core/fxcrt/css/cfx_cssvalue.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSVALUE_H_ +#define CORE_FXCRT_CSS_CFX_CSSVALUE_H_ + +#include "core/fxcrt/css/cfx_css.h" + +class CFX_CSSValue : public Retainable { + public: + CFX_CSSPrimitiveType GetType() const { return m_value; } + + protected: + explicit CFX_CSSValue(CFX_CSSPrimitiveType type); + + private: + CFX_CSSPrimitiveType m_value; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSVALUE_H_ diff --git a/core/fxcrt/css/cfx_cssvaluelist.cpp b/core/fxcrt/css/cfx_cssvaluelist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b96f1658afdeed0381515205dd132d008b120772 --- /dev/null +++ b/core/fxcrt/css/cfx_cssvaluelist.cpp @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssvaluelist.h" + +#include + +#include "core/fxcrt/css/cfx_css.h" + +CFX_CSSValueList::CFX_CSSValueList(std::vector>& list) + : CFX_CSSValue(CFX_CSSPrimitiveType::List), m_ppList(std::move(list)) {} + +CFX_CSSValueList::~CFX_CSSValueList() {} + +int32_t CFX_CSSValueList::CountValues() const { + return m_ppList.size(); +} + +RetainPtr CFX_CSSValueList::GetValue(int32_t index) const { + return m_ppList[index]; +} diff --git a/core/fxcrt/css/cfx_cssvaluelist.h b/core/fxcrt/css/cfx_cssvaluelist.h new file mode 100644 index 0000000000000000000000000000000000000000..d2b0c6e7d15bcdbc3b3b715641b6749b2b171901 --- /dev/null +++ b/core/fxcrt/css/cfx_cssvaluelist.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSVALUELIST_H_ +#define CORE_FXCRT_CSS_CFX_CSSVALUELIST_H_ + +#include + +#include "core/fxcrt/css/cfx_cssvalue.h" + +class CFX_CSSValueList : public CFX_CSSValue { + public: + explicit CFX_CSSValueList(std::vector>& list); + ~CFX_CSSValueList() override; + + int32_t CountValues() const; + RetainPtr GetValue(int32_t index) const; + + protected: + std::vector> m_ppList; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSVALUELIST_H_ diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.cpp b/core/fxcrt/css/cfx_cssvaluelistparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2339dec386a72b12c065f5789f1147f2f35f577a --- /dev/null +++ b/core/fxcrt/css/cfx_cssvaluelistparser.cpp @@ -0,0 +1,87 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssvaluelistparser.h" + +#include "core/fxcrt/fx_extension.h" + +CFX_CSSValueListParser::CFX_CSSValueListParser(const wchar_t* psz, + int32_t iLen, + wchar_t separator) + : m_Separator(separator), m_pCur(psz), m_pEnd(psz + iLen) { + ASSERT(psz && iLen > 0); +} + +bool CFX_CSSValueListParser::NextValue(CFX_CSSPrimitiveType* eType, + const wchar_t** pStart, + int32_t* iLength) { + while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator)) + ++m_pCur; + + if (m_pCur >= m_pEnd) + return false; + + *eType = CFX_CSSPrimitiveType::Unknown; + *pStart = m_pCur; + *iLength = 0; + wchar_t wch = *m_pCur; + if (wch == '#') { + *iLength = SkipTo(' ', false, false); + if (*iLength == 4 || *iLength == 7) + *eType = CFX_CSSPrimitiveType::RGB; + } else if (std::iswdigit(wch) || wch == '.' || wch == '-' || wch == '+') { + while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator)) + ++m_pCur; + + *iLength = m_pCur - *pStart; + *eType = CFX_CSSPrimitiveType::Number; + } else if (wch == '\"' || wch == '\'') { + ++(*pStart); + m_pCur++; + *iLength = SkipTo(wch, false, false); + m_pCur++; + *eType = CFX_CSSPrimitiveType::String; + } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') { + if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) { + *iLength = SkipTo(')', false, false) + 1; + m_pCur++; + *eType = CFX_CSSPrimitiveType::RGB; + } + } else { + *iLength = SkipTo(m_Separator, true, true); + *eType = CFX_CSSPrimitiveType::String; + } + return m_pCur <= m_pEnd && *iLength > 0; +} + +int32_t CFX_CSSValueListParser::SkipTo(wchar_t wch, + bool breakOnSpace, + bool matchBrackets) { + const wchar_t* pStart = m_pCur; + int32_t bracketCount = 0; + while (m_pCur < m_pEnd && *m_pCur != wch) { + if (breakOnSpace && *m_pCur <= ' ') + break; + if (!matchBrackets) { + m_pCur++; + continue; + } + + if (*m_pCur == '(') + bracketCount++; + else if (*m_pCur == ')') + bracketCount--; + + m_pCur++; + } + + while (bracketCount > 0 && m_pCur < m_pEnd) { + if (*m_pCur == ')') + bracketCount--; + m_pCur++; + } + return m_pCur - pStart; +} diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.h b/core/fxcrt/css/cfx_cssvaluelistparser.h new file mode 100644 index 0000000000000000000000000000000000000000..6872ee278c82c9076f7e70cc97da0373f6ecb02a --- /dev/null +++ b/core/fxcrt/css/cfx_cssvaluelistparser.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_ +#define CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_ + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/fx_system.h" + +class CFX_CSSValueListParser { + public: + CFX_CSSValueListParser(const wchar_t* psz, int32_t iLen, wchar_t separator); + + bool NextValue(CFX_CSSPrimitiveType* eType, + const wchar_t** pStart, + int32_t* iLength); + void UseCommaSeparator() { m_Separator = ','; } + + private: + int32_t SkipTo(wchar_t wch, bool breakOnSpace, bool matchBrackets); + + wchar_t m_Separator; + const wchar_t* m_pCur; + const wchar_t* m_pEnd; +}; + +#endif // CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_ diff --git a/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e232a2dc65caec45766ce5ff514a02f1e6ace7c8 --- /dev/null +++ b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp @@ -0,0 +1,141 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/css/cfx_cssvaluelistparser.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" + +TEST(CFX_CSSValueListParserTest, rgb_short) { + CFX_CSSPrimitiveType type; + const wchar_t* start; + int32_t len; + + auto parser = pdfium::MakeUnique(L"#abc", 4, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); + EXPECT_EQ(L"#abc", WideString(start, len)); + EXPECT_FALSE(parser->NextValue(&type, &start, &len)); + + parser = pdfium::MakeUnique(L"#abcdef", 7, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); + EXPECT_EQ(L"#abcdef", WideString(start, len)); + EXPECT_FALSE(parser->NextValue(&type, &start, &len)); + + parser = + pdfium::MakeUnique(L"rgb(1, 255, 4)", 14, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); + EXPECT_EQ(L"rgb(1, 255, 4)", WideString(start, len)); + + parser = pdfium::MakeUnique(L"#abcdefghij", 11, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Unknown, type); + EXPECT_EQ(L"#abcdefghij", WideString(start, len)); + EXPECT_FALSE(parser->NextValue(&type, &start, &len)); +} + +TEST(CFX_CSSValueListParserTest, number_parsing) { + CFX_CSSPrimitiveType type; + const wchar_t* start; + int32_t len; + + auto parser = pdfium::MakeUnique(L"1234", 4, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"1234", WideString(start, len)); + + parser = pdfium::MakeUnique(L"-1234", 5, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"-1234", WideString(start, len)); + + parser = pdfium::MakeUnique(L"+1234", 5, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"+1234", WideString(start, len)); + + parser = pdfium::MakeUnique(L".1234", 5, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L".1234", WideString(start, len)); + + parser = pdfium::MakeUnique(L"4321.1234", 9, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"4321.1234", WideString(start, len)); + + // TODO(dsinclair): These should probably fail but currently don't. + parser = pdfium::MakeUnique(L"4321.12.34", 10, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"4321.12.34", WideString(start, len)); + + parser = pdfium::MakeUnique(L"43a1.12.34", 10, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"43a1.12.34", WideString(start, len)); +} + +TEST(CFX_CSSValueListParserTest, string_parsing) { + CFX_CSSPrimitiveType type; + const wchar_t* start; + int32_t len; + + auto parser = + pdfium::MakeUnique(L"'string'", 8, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::String, type); + EXPECT_EQ(L"string", WideString(start, len)); + + parser = pdfium::MakeUnique(L"\"another string\"", 16, + L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::String, type); + EXPECT_EQ(L"another string", WideString(start, len)); + + parser = pdfium::MakeUnique(L"standalone", 10, L' '); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::String, type); + EXPECT_EQ(L"standalone", WideString(start, len)); +} + +TEST(CFX_CSSValueListParserTest, multiparsing) { + CFX_CSSPrimitiveType type; + const wchar_t* start; + int32_t len; + + auto parser = pdfium::MakeUnique(L"1, 2, 3", 7, L','); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"1", WideString(start, len)); + + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"2", WideString(start, len)); + + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"3", WideString(start, len)); + + EXPECT_FALSE(parser->NextValue(&type, &start, &len)); + + parser = pdfium::MakeUnique(L"'str', rgb(1, 2, 3), 4", + 22, L','); + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::String, type); + EXPECT_EQ(L"str", WideString(start, len)); + + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); + EXPECT_EQ(L"rgb(1, 2, 3)", WideString(start, len)); + + EXPECT_TRUE(parser->NextValue(&type, &start, &len)); + EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); + EXPECT_EQ(L"4", WideString(start, len)); +} diff --git a/core/fxcrt/extension.h b/core/fxcrt/extension.h deleted file mode 100644 index b62f67772b3d454029bd12f38f8a07df957b804a..0000000000000000000000000000000000000000 --- a/core/fxcrt/extension.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_EXTENSION_H_ -#define CORE_FXCRT_EXTENSION_H_ - -#include -#include - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_safe_types.h" - -class IFXCRT_FileAccess { - public: - static IFXCRT_FileAccess* Create(); - virtual ~IFXCRT_FileAccess() {} - - virtual bool Open(const CFX_ByteStringC& fileName, uint32_t dwMode) = 0; - virtual bool Open(const CFX_WideStringC& fileName, uint32_t dwMode) = 0; - virtual void Close() = 0; - virtual FX_FILESIZE GetSize() const = 0; - virtual FX_FILESIZE GetPosition() const = 0; - virtual FX_FILESIZE SetPosition(FX_FILESIZE pos) = 0; - virtual size_t Read(void* pBuffer, size_t szBuffer) = 0; - virtual size_t Write(const void* pBuffer, size_t szBuffer) = 0; - virtual size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0; - virtual size_t WritePos(const void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) = 0; - virtual bool Flush() = 0; - virtual bool Truncate(FX_FILESIZE szFile) = 0; -}; - -#ifdef __cplusplus -extern "C" { -#endif -#define MT_N 848 -#define MT_M 456 -#define MT_Matrix_A 0x9908b0df -#define MT_Upper_Mask 0x80000000 -#define MT_Lower_Mask 0x7fffffff -struct FX_MTRANDOMCONTEXT { - FX_MTRANDOMCONTEXT() { - mti = MT_N + 1; - bHaveSeed = false; - } - uint32_t mti; - bool bHaveSeed; - uint32_t mt[MT_N]; -}; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -bool FX_GenerateCryptoRandom(uint32_t* pBuffer, int32_t iCount); -#endif -#ifdef __cplusplus -} -#endif - -#endif // CORE_FXCRT_EXTENSION_H_ diff --git a/core/fxcrt/fx_arabic.cpp b/core/fxcrt/fx_arabic.cpp index 108c6c19ac470d890cdd2b876637d0fee7926e51..0d6f0395a6d53c0e3dd43c1501db14211fbf2ec5 100644 --- a/core/fxcrt/fx_arabic.cpp +++ b/core/fxcrt/fx_arabic.cpp @@ -9,11 +9,29 @@ #include #include -#include "core/fxcrt/fx_ucd.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_unicode.h" #include "third_party/base/stl_util.h" namespace { +struct FX_ARBFORMTABLE { + uint16_t wIsolated; + uint16_t wFinal; + uint16_t wInitial; + uint16_t wMedial; +}; + +struct FX_ARAALEF { + uint16_t wAlef; + uint16_t wIsolated; +}; + +struct FX_ARASHADDA { + uint16_t wShadda; + uint16_t wIsolated; +}; + const FX_ARBFORMTABLE g_FX_ArabicFormTables[] = { {0xFE81, 0xFE82, 0xFE81, 0xFE82}, {0xFE83, 0xFE84, 0xFE83, 0xFE84}, {0xFE85, 0xFE86, 0xFE85, 0xFE86}, {0xFE87, 0xFE88, 0xFE87, 0xFE88}, @@ -119,615 +137,96 @@ const FX_ARASHADDA gs_FX_ShaddaTable[] = { {0x064F, 0xFC61}, {0x0650, 0xFC62}, }; -const int32_t gc_FX_BidiNTypes[] = { - FX_BIDICLASS_N, FX_BIDICLASS_L, FX_BIDICLASS_R, FX_BIDICLASS_AN, - FX_BIDICLASS_EN, FX_BIDICLASS_AL, FX_BIDICLASS_NSM, FX_BIDICLASS_CS, - FX_BIDICLASS_ES, FX_BIDICLASS_ET, FX_BIDICLASS_BN, FX_BIDICLASS_BN, - FX_BIDICLASS_N, FX_BIDICLASS_B, FX_BIDICLASS_RLO, FX_BIDICLASS_RLE, - FX_BIDICLASS_LRO, FX_BIDICLASS_LRE, FX_BIDICLASS_PDF, FX_BIDICLASS_ON, -}; - -const int32_t gc_FX_BidiWeakStates[][10] = { - {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa, - FX_BWSao, FX_BWSao, FX_BWSao}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr, - FX_BWSro, FX_BWSro, FX_BWSrt}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl, - FX_BWSlo, FX_BWSlo, FX_BWSlt}, - {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao, - FX_BWSao, FX_BWSao, FX_BWSao}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro, - FX_BWSro, FX_BWSro, FX_BWSrt}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo, - FX_BWSlo, FX_BWSlo, FX_BWSlt}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt, - FX_BWSro, FX_BWSro, FX_BWSrt}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt, - FX_BWSlo, FX_BWSlo, FX_BWSlt}, - {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn, - FX_BWSac, FX_BWSao, FX_BWSao}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra, - FX_BWSrc, FX_BWSro, FX_BWSrt}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre, - FX_BWSrs, FX_BWSrs, FX_BWSret}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla, - FX_BWSlc, FX_BWSlo, FX_BWSlt}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle, - FX_BWSls, FX_BWSls, FX_BWSlet}, - {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao, - FX_BWSao, FX_BWSao, FX_BWSao}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro, - FX_BWSro, FX_BWSro, FX_BWSrt}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro, - FX_BWSro, FX_BWSro, FX_BWSrt}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo, - FX_BWSlo, FX_BWSlo, FX_BWSlt}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo, - FX_BWSlo, FX_BWSlo, FX_BWSlt}, - {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret, - FX_BWSro, FX_BWSro, FX_BWSret}, - {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet, - FX_BWSlo, FX_BWSlo, FX_BWSlet}, -}; - -const int32_t gc_FX_BidiWeakActions[][10] = { - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR, - FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, - FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, - FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR, - FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, - FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, - FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR, - FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR, - FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR, - FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, - FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, - FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, - FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, - FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR, - FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR, - FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR, - FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR, - FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, - {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR, - FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, - FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE}, - {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, - FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL}, -}; - -const int32_t gc_FX_BidiNeutralStates[][5] = { - {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr}, - {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, - {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr}, - {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, - {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, - {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, -}; -const int32_t gc_FX_BidiNeutralActions[][5] = { - {FX_BNAIn, 0, 0, 0, 0}, - {FX_BNAIn, 0, 0, 0, FX_BIDICLASS_L}, - {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn}, - {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL}, - {FX_BNAIn, 0, 0, 0, FX_BIDICLASS_L}, - {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn}, -}; - -const int32_t gc_FX_BidiAddLevel[][4] = { - {0, 1, 2, 2}, - {1, 0, 1, 1}, -}; +const FX_ARBFORMTABLE* GetArabicFormTable(wchar_t unicode) { + if (unicode < 0x622 || unicode > 0x6d5) + return nullptr; + return g_FX_ArabicFormTables + unicode - 0x622; +} const FX_ARBFORMTABLE* ParseChar(const CFX_Char* pTC, - FX_WCHAR& wChar, - FX_CHARTYPE& eType) { + wchar_t* wChar, + FX_CHARTYPE* eType) { if (!pTC) { - eType = FX_CHARTYPE_Unknown; - wChar = 0xFEFF; + *eType = FX_CHARTYPE_Unknown; + *wChar = 0xFEFF; return nullptr; } - eType = pTC->GetCharType(); - wChar = (FX_WCHAR)pTC->m_wCharCode; - const FX_ARBFORMTABLE* pFT = FX_GetArabicFormTable(wChar); - if (!pFT || eType >= FX_CHARTYPE_ArabicNormal) - eType = FX_CHARTYPE_Unknown; + + *eType = pTC->GetCharType(); + *wChar = static_cast(pTC->char_code()); + const FX_ARBFORMTABLE* pFT = GetArabicFormTable(*wChar); + if (!pFT || *eType >= FX_CHARTYPE_ArabicNormal) + *eType = FX_CHARTYPE_Unknown; return pFT; } -} // namespace - -const FX_ARBFORMTABLE* FX_GetArabicFormTable(FX_WCHAR unicode) { - if (unicode < 0x622 || unicode > 0x6d5) { - return nullptr; - } - return g_FX_ArabicFormTables + unicode - 0x622; -} -FX_WCHAR FX_GetArabicFromAlefTable(FX_WCHAR alef) { - static const int32_t s_iAlefCount = - sizeof(gs_FX_AlefTable) / sizeof(FX_ARAALEF); - for (int32_t iStart = 0; iStart < s_iAlefCount; iStart++) { +wchar_t GetArabicFromAlefTable(wchar_t alef) { + static const size_t s_iAlefCount = FX_ArraySize(gs_FX_AlefTable); + for (size_t iStart = 0; iStart < s_iAlefCount; iStart++) { const FX_ARAALEF& v = gs_FX_AlefTable[iStart]; - if (v.wAlef == alef) { + if (v.wAlef == alef) return v.wIsolated; - } } return alef; } -FX_WCHAR FX_GetArabicFromShaddaTable(FX_WCHAR shadda) { - static const int32_t s_iShaddaCount = - sizeof(gs_FX_ShaddaTable) / sizeof(FX_ARASHADDA); - for (int32_t iStart = 0; iStart < s_iShaddaCount; iStart++) { - const FX_ARASHADDA& v = gs_FX_ShaddaTable[iStart]; - if (v.wShadda == shadda) { - return v.wIsolated; - } - } - return shadda; -} + +} // namespace namespace pdfium { namespace arabic { -bool IsArabicChar(FX_WCHAR wch) { - uint32_t dwRet = - kTextLayoutCodeProperties[(uint16_t)wch] & FX_CHARTYPEBITSMASK; - return dwRet >= FX_CHARTYPE_ArabicAlef; -} - -bool IsArabicFormChar(FX_WCHAR wch) { - return (kTextLayoutCodeProperties[(uint16_t)wch] & FX_CHARTYPEBITSMASK) == - FX_CHARTYPE_ArabicForm; -} - -FX_WCHAR GetFormChar(FX_WCHAR wch, FX_WCHAR prev, FX_WCHAR next) { - CFX_Char c(wch, kTextLayoutCodeProperties[(uint16_t)wch]); - CFX_Char p(prev, kTextLayoutCodeProperties[(uint16_t)prev]); - CFX_Char n(next, kTextLayoutCodeProperties[(uint16_t)next]); +wchar_t GetFormChar(wchar_t wch, wchar_t prev, wchar_t next) { + CFX_Char c(wch, FX_GetUnicodeProperties(wch)); + CFX_Char p(prev, FX_GetUnicodeProperties(prev)); + CFX_Char n(next, FX_GetUnicodeProperties(next)); return GetFormChar(&c, &p, &n); } -FX_WCHAR GetFormChar(const CFX_Char* cur, - const CFX_Char* prev, - const CFX_Char* next) { +wchar_t GetFormChar(const CFX_Char* cur, + const CFX_Char* prev, + const CFX_Char* next) { FX_CHARTYPE eCur; - FX_WCHAR wCur; - const FX_ARBFORMTABLE* ft = ParseChar(cur, wCur, eCur); - if (eCur < FX_CHARTYPE_ArabicAlef || eCur >= FX_CHARTYPE_ArabicNormal) { + wchar_t wCur; + const FX_ARBFORMTABLE* ft = ParseChar(cur, &wCur, &eCur); + if (eCur < FX_CHARTYPE_ArabicAlef || eCur >= FX_CHARTYPE_ArabicNormal) return wCur; - } + FX_CHARTYPE ePrev; - FX_WCHAR wPrev; - ParseChar(prev, wPrev, ePrev); - if (wPrev == 0x0644 && eCur == FX_CHARTYPE_ArabicAlef) { + wchar_t wPrev; + ParseChar(prev, &wPrev, &ePrev); + if (wPrev == 0x0644 && eCur == FX_CHARTYPE_ArabicAlef) return 0xFEFF; - } + FX_CHARTYPE eNext; - FX_WCHAR wNext; - ParseChar(next, wNext, eNext); + wchar_t wNext; + ParseChar(next, &wNext, &eNext); bool bAlef = (eNext == FX_CHARTYPE_ArabicAlef && wCur == 0x644); if (ePrev < FX_CHARTYPE_ArabicAlef) { - if (bAlef) { - return FX_GetArabicFromAlefTable(wNext); - } + if (bAlef) + return GetArabicFromAlefTable(wNext); return (eNext < FX_CHARTYPE_ArabicAlef) ? ft->wIsolated : ft->wInitial; } + if (bAlef) { - wCur = FX_GetArabicFromAlefTable(wNext); + wCur = GetArabicFromAlefTable(wNext); return (ePrev != FX_CHARTYPE_ArabicDistortion) ? wCur : ++wCur; } - if (ePrev == FX_CHARTYPE_ArabicAlef || ePrev == FX_CHARTYPE_ArabicSpecial) { + + if (ePrev == FX_CHARTYPE_ArabicAlef || ePrev == FX_CHARTYPE_ArabicSpecial) return (eNext < FX_CHARTYPE_ArabicAlef) ? ft->wIsolated : ft->wInitial; - } return (eNext < FX_CHARTYPE_ArabicAlef) ? ft->wFinal : ft->wMedial; } } // namespace arabic } // namespace pdfium -void FX_BidiReverseString(CFX_WideString& wsText, - int32_t iStart, - int32_t iCount) { - ASSERT(iStart > -1 && iStart < wsText.GetLength()); - ASSERT(iCount >= 0 && iStart + iCount <= wsText.GetLength()); - FX_WCHAR wch; - FX_WCHAR* pStart = const_cast(wsText.c_str()); - pStart += iStart; - FX_WCHAR* pEnd = pStart + iCount - 1; - while (pStart < pEnd) { - wch = *pStart; - *pStart++ = *pEnd; - *pEnd-- = wch; - } -} - - -int32_t FX_BidiGetDeferredNeutrals(int32_t iAction, int32_t iLevel) { - iAction = (iAction >> 4) & 0xF; - if (iAction == (FX_BIDINEUTRALACTION_En >> 4)) { - return FX_BidiDirection(iLevel); - } else { - return iAction; - } -} - -int32_t FX_BidiGetResolvedNeutrals(int32_t iAction) { - iAction = (iAction & 0xF); - if (iAction == FX_BIDINEUTRALACTION_In) { - return 0; - } else { - return iAction; - } -} - -int32_t FX_BidiReorderLevel(int32_t iBaseLevel, - CFX_WideString& wsText, - const CFX_ArrayTemplate& levels, - int32_t iStart, - bool bReverse) { - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - ASSERT(wsText.GetLength() == levels.GetSize()); - ASSERT(iStart >= 0 && iStart < wsText.GetLength()); - int32_t iSize = wsText.GetLength(); - if (iSize < 1) { - return 0; - } - bReverse = bReverse || FX_IsOdd(iBaseLevel); - int32_t i = iStart, iLevel; - for (; i < iSize; i++) { - if ((iLevel = levels.GetAt(i)) == iBaseLevel) { - continue; - } - if (iLevel < iBaseLevel) { - break; - } - i += FX_BidiReorderLevel(iBaseLevel + 1, wsText, levels, i, bReverse) - 1; - } - int32_t iCount = i - iStart; - if (bReverse && iCount > 1) { - FX_BidiReverseString(wsText, iStart, iCount); - } - return iCount; -} -void FX_BidiReorder(int32_t iBaseLevel, - CFX_WideString& wsText, - const CFX_ArrayTemplate& levels) { - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - ASSERT(wsText.GetLength() == levels.GetSize()); - int32_t iSize = wsText.GetLength(); - if (iSize < 1) { - return; - } - int32_t i = 0; - while (i < iSize) { - i += FX_BidiReorderLevel(iBaseLevel, wsText, levels, i, false); - } -} - -template -class CFX_BidiLineTemplate { - public: - void FX_BidiReverseString(std::vector& chars, - int32_t iStart, - int32_t iCount) { - ASSERT(iStart >= 0 && iStart < pdfium::CollectionSize(chars)); - ASSERT(iCount >= 0 && - iStart + iCount <= pdfium::CollectionSize(chars)); - std::reverse(chars.begin() + iStart, chars.begin() + iStart + iCount); - } - - void FX_BidiSetDeferredRun(std::vector& chars, - bool bClass, - int32_t iStart, - int32_t iCount, - int32_t iValue) { - ASSERT(iStart >= 0 && iStart <= pdfium::CollectionSize(chars)); - ASSERT(iStart - iCount > -1); - int32_t iLast = iStart - iCount; - if (bClass) { - for (int32_t i = iStart - 1; i >= iLast; i--) - chars[i].m_iBidiClass = (int16_t)iValue; - } else { - for (int32_t i = iStart - 1; i >= iLast; i--) - chars[i].m_iBidiLevel = (int16_t)iValue; - } - } - - void FX_BidiClassify(std::vector& chars, int32_t iCount, bool bWS) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - if (bWS) { - for (int32_t i = 0; i < iCount; i++) { - chars[i].m_iBidiClass = - (int16_t)(chars[i].m_dwCharProps & FX_BIDICLASSBITSMASK) >> - FX_BIDICLASSBITS; - } - } else { - for (int32_t i = 0; i < iCount; i++) { - chars[i].m_iBidiClass = (int16_t) - gc_FX_BidiNTypes[(chars[i].m_dwCharProps & FX_BIDICLASSBITSMASK) >> - FX_BIDICLASSBITS]; - } - } - } - - void FX_BidiResolveExplicit(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - for (int32_t i = 0; i < iCount; i++) - chars[i].m_iBidiLevel = static_cast(iBaseLevel); - } - - void FX_BidiResolveWeak(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - iCount--; - if (iCount < 1) { - return; - } - baseType *pTC, *pTCNext; - int32_t iLevelCur = iBaseLevel; - int32_t iState = FX_IsOdd(iBaseLevel) ? FX_BWSxr : FX_BWSxl; - int32_t i = 0, iNum = 0, iClsCur, iClsRun, iClsNew, iAction; - for (; i <= iCount; i++) { - pTC = &chars[i]; - iClsCur = pTC->m_iBidiClass; - if (iClsCur == FX_BIDICLASS_BN) { - pTC->m_iBidiLevel = (int16_t)iLevelCur; - if (i == iCount && iLevelCur != iBaseLevel) { - iClsCur = FX_BidiDirection(iLevelCur); - pTC->m_iBidiClass = (int16_t)iClsCur; - } else if (i < iCount) { - pTCNext = &chars[i + 1]; - int32_t iLevelNext, iLevelNew; - iClsNew = pTCNext->m_iBidiClass; - iLevelNext = pTCNext->m_iBidiLevel; - if (iClsNew != FX_BIDICLASS_BN && iLevelCur != iLevelNext) { - iLevelNew = iLevelNext; - if (iLevelCur > iLevelNew) { - iLevelNew = iLevelCur; - } - pTC->m_iBidiLevel = (int16_t)iLevelNew; - iClsCur = FX_BidiDirection(iLevelNew); - pTC->m_iBidiClass = (int16_t)iClsCur; - iLevelCur = iLevelNext; - } else { - if (iNum > 0) { - iNum++; - } - continue; - } - } else { - if (iNum > 0) { - iNum++; - } - continue; - } - } - ASSERT(iClsCur <= FX_BIDICLASS_BN); - iAction = gc_FX_BidiWeakActions[iState][iClsCur]; - iClsRun = FX_BidiGetDeferredType(iAction); - if (iClsRun != FX_BIDIWEAKACTION_XX && iNum > 0) { - FX_BidiSetDeferredRun(chars, true, i, iNum, iClsRun); - iNum = 0; - } - iClsNew = FX_BidiGetResolvedType(iAction); - if (iClsNew != FX_BIDIWEAKACTION_XX) { - pTC->m_iBidiClass = (int16_t)iClsNew; - } - if (FX_BIDIWEAKACTION_IX & iAction) { - iNum++; - } - iState = gc_FX_BidiWeakStates[iState][iClsCur]; - } - if (iNum > 0) { - iClsCur = FX_BidiDirection(iBaseLevel); - iClsRun = FX_BidiGetDeferredType(gc_FX_BidiWeakActions[iState][iClsCur]); - if (iClsRun != FX_BIDIWEAKACTION_XX) { - FX_BidiSetDeferredRun(chars, true, i, iNum, iClsRun); - } - } - } - - void FX_BidiResolveNeutrals(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - iCount--; - if (iCount < 1) { - return; - } - baseType* pTC; - int32_t iLevel = iBaseLevel; - int32_t iState = FX_IsOdd(iBaseLevel) ? FX_BNSr : FX_BNSl; - int32_t i = 0, iNum = 0, iClsCur, iClsRun, iClsNew, iAction; - for (; i <= iCount; i++) { - pTC = &chars[i]; - iClsCur = pTC->m_iBidiClass; - if (iClsCur == FX_BIDICLASS_BN) { - if (iNum) { - iNum++; - } - continue; - } - ASSERT(iClsCur < FX_BIDICLASS_AL); - iAction = gc_FX_BidiNeutralActions[iState][iClsCur]; - iClsRun = FX_BidiGetDeferredNeutrals(iAction, iLevel); - if (iClsRun != FX_BIDICLASS_N && iNum > 0) { - FX_BidiSetDeferredRun(chars, true, i, iNum, iClsRun); - iNum = 0; - } - iClsNew = FX_BidiGetResolvedNeutrals(iAction); - if (iClsNew != FX_BIDICLASS_N) { - pTC->m_iBidiClass = (int16_t)iClsNew; - } - if (FX_BIDINEUTRALACTION_In & iAction) { - iNum++; - } - iState = gc_FX_BidiNeutralStates[iState][iClsCur]; - iLevel = pTC->m_iBidiLevel; - } - if (iNum > 0) { - iClsCur = FX_BidiDirection(iLevel); - iClsRun = FX_BidiGetDeferredNeutrals( - gc_FX_BidiNeutralActions[iState][iClsCur], iLevel); - if (iClsRun != FX_BIDICLASS_N) { - FX_BidiSetDeferredRun(chars, true, i, iNum, iClsRun); - } - } - } - - void FX_BidiResolveImplicit(std::vector& chars, int32_t iCount) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - for (int32_t i = 0; i < iCount; i++) { - int32_t iCls = chars[i].m_iBidiClass; - if (iCls == FX_BIDICLASS_BN) { - continue; - } - ASSERT(iCls > FX_BIDICLASS_ON && iCls < FX_BIDICLASS_AL); - int32_t iLevel = chars[i].m_iBidiLevel; - iLevel += gc_FX_BidiAddLevel[FX_IsOdd(iLevel)][iCls - 1]; - chars[i].m_iBidiLevel = (int16_t)iLevel; - } - } - - void FX_BidiResolveWhitespace(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - if (iCount < 1) { - return; - } - iCount--; - int32_t iLevel = iBaseLevel; - int32_t i = 0, iNum = 0; - for (; i <= iCount; i++) { - switch (chars[i].m_iBidiClass) { - case FX_BIDICLASS_WS: - iNum++; - break; - case FX_BIDICLASS_RLE: - case FX_BIDICLASS_LRE: - case FX_BIDICLASS_LRO: - case FX_BIDICLASS_RLO: - case FX_BIDICLASS_PDF: - case FX_BIDICLASS_BN: - chars[i].m_iBidiLevel = (int16_t)iLevel; - iNum++; - break; - case FX_BIDICLASS_S: - case FX_BIDICLASS_B: - if (iNum > 0) { - FX_BidiSetDeferredRun(chars, false, i, iNum, iBaseLevel); - } - chars[i].m_iBidiLevel = (int16_t)iBaseLevel; - iNum = 0; - break; - default: - iNum = 0; - break; - } - iLevel = chars[i].m_iBidiLevel; - } - if (iNum > 0) { - FX_BidiSetDeferredRun(chars, false, i, iNum, iBaseLevel); - } - } - - int32_t FX_BidiReorderLevel(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel, - int32_t iStart, - bool bReverse) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - ASSERT(iStart >= 0 && iStart < iCount); - if (iCount < 1) { - return 0; - } - bReverse = bReverse || FX_IsOdd(iBaseLevel); - int32_t i = iStart; - for (; i < iCount; i++) { - int32_t iLevel = chars[i].m_iBidiLevel; - if (iLevel == iBaseLevel) - continue; - if (iLevel < iBaseLevel) - break; - i += FX_BidiReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1; - } - int32_t iNum = i - iStart; - if (bReverse && iNum > 1) { - FX_BidiReverseString(chars, iStart, iNum); - } - return iNum; - } - - void FX_BidiReorder(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - ASSERT(iBaseLevel >= 0 && iBaseLevel <= FX_BIDIMAXLEVEL); - int32_t i = 0; - while (i < iCount) { - i += FX_BidiReorderLevel(chars, iCount, iBaseLevel, i, false); - } - } - - void FX_BidiPosition(std::vector& chars, int32_t iCount) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - for (int32_t i = 0; i < iCount; ++i) - chars[chars[i].m_iBidiPos].m_iBidiOrder = i; - } - - void FX_BidiLine(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - ASSERT(iCount >= 0 && iCount <= pdfium::CollectionSize(chars)); - if (iCount < 2) { - return; - } - FX_BidiClassify(chars, iCount, false); - FX_BidiResolveExplicit(chars, iCount, iBaseLevel); - FX_BidiResolveWeak(chars, iCount, iBaseLevel); - FX_BidiResolveNeutrals(chars, iCount, iBaseLevel); - FX_BidiResolveImplicit(chars, iCount); - FX_BidiClassify(chars, iCount, true); - FX_BidiResolveWhitespace(chars, iCount, iBaseLevel); - FX_BidiReorder(chars, iCount, iBaseLevel); - FX_BidiPosition(chars, iCount); +wchar_t FX_GetArabicFromShaddaTable(wchar_t shadda) { + static const size_t s_iShaddaCount = FX_ArraySize(gs_FX_ShaddaTable); + for (size_t iStart = 0; iStart < s_iShaddaCount; iStart++) { + const FX_ARASHADDA& v = gs_FX_ShaddaTable[iStart]; + if (v.wShadda == shadda) + return v.wIsolated; } -}; - -void FX_BidiLine(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - CFX_BidiLineTemplate blt; - blt.FX_BidiLine(chars, iCount, iBaseLevel); -} -void FX_BidiLine(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel) { - CFX_BidiLineTemplate blt; - blt.FX_BidiLine(chars, iCount, iBaseLevel); + return shadda; } diff --git a/core/fxcrt/fx_arabic.h b/core/fxcrt/fx_arabic.h index e7ba079f4379de5ebbdc4597b20945f8dfff26f2..9d23b1557dfc04295103c2eb51bbc9a08444c78c 100644 --- a/core/fxcrt/fx_arabic.h +++ b/core/fxcrt/fx_arabic.h @@ -7,182 +7,22 @@ #ifndef CORE_FXCRT_FX_ARABIC_H_ #define CORE_FXCRT_FX_ARABIC_H_ -#include "core/fxcrt/fx_arb.h" +#include -#define FX_BIDIMAXLEVEL 61 -#define FX_BidiDirection(a) (FX_IsOdd(a) ? FX_BIDICLASS_R : FX_BIDICLASS_L) -#define FX_BidiGetDeferredType(a) (((a) >> 4) & 0x0F) -#define FX_BidiGetResolvedType(a) ((a)&0x0F) +#include "core/fxcrt/cfx_char.h" +#include "core/fxcrt/fx_system.h" namespace pdfium { namespace arabic { -bool IsArabicChar(FX_WCHAR wch); -bool IsArabicFormChar(FX_WCHAR wch); -FX_WCHAR GetFormChar(FX_WCHAR wch, FX_WCHAR prev = 0, FX_WCHAR next = 0); -FX_WCHAR GetFormChar(const CFX_Char* cur, - const CFX_Char* prev, - const CFX_Char* next); +wchar_t GetFormChar(wchar_t wch, wchar_t prev, wchar_t next); +wchar_t GetFormChar(const CFX_Char* cur, + const CFX_Char* prev, + const CFX_Char* next); } // namespace arabic } // namespace pdfium -void FX_BidiReverseString(CFX_WideString& wsText, - int32_t iStart, - int32_t iCount); -void FX_BidiSetDeferredRun(CFX_ArrayTemplate& values, - int32_t iStart, - int32_t iCount, - int32_t iValue); -void FX_BidiClassify(const CFX_WideString& wsText, - CFX_ArrayTemplate& classes, - bool bWS = false); -int32_t FX_BidiResolveExplicit(int32_t iBaseLevel, - int32_t iDirection, - CFX_ArrayTemplate& classes, - CFX_ArrayTemplate& levels, - int32_t iStart, - int32_t iCount, - int32_t iNest = 0); - -enum FX_BIDIWEAKSTATE { - FX_BIDIWEAKSTATE_xa = 0, - FX_BIDIWEAKSTATE_xr, - FX_BIDIWEAKSTATE_xl, - FX_BIDIWEAKSTATE_ao, - FX_BIDIWEAKSTATE_ro, - FX_BIDIWEAKSTATE_lo, - FX_BIDIWEAKSTATE_rt, - FX_BIDIWEAKSTATE_lt, - FX_BIDIWEAKSTATE_cn, - FX_BIDIWEAKSTATE_ra, - FX_BIDIWEAKSTATE_re, - FX_BIDIWEAKSTATE_la, - FX_BIDIWEAKSTATE_le, - FX_BIDIWEAKSTATE_ac, - FX_BIDIWEAKSTATE_rc, - FX_BIDIWEAKSTATE_rs, - FX_BIDIWEAKSTATE_lc, - FX_BIDIWEAKSTATE_ls, - FX_BIDIWEAKSTATE_ret, - FX_BIDIWEAKSTATE_let, -}; -#define FX_BWSxa FX_BIDIWEAKSTATE_xa -#define FX_BWSxr FX_BIDIWEAKSTATE_xr -#define FX_BWSxl FX_BIDIWEAKSTATE_xl -#define FX_BWSao FX_BIDIWEAKSTATE_ao -#define FX_BWSro FX_BIDIWEAKSTATE_ro -#define FX_BWSlo FX_BIDIWEAKSTATE_lo -#define FX_BWSrt FX_BIDIWEAKSTATE_rt -#define FX_BWSlt FX_BIDIWEAKSTATE_lt -#define FX_BWScn FX_BIDIWEAKSTATE_cn -#define FX_BWSra FX_BIDIWEAKSTATE_ra -#define FX_BWSre FX_BIDIWEAKSTATE_re -#define FX_BWSla FX_BIDIWEAKSTATE_la -#define FX_BWSle FX_BIDIWEAKSTATE_le -#define FX_BWSac FX_BIDIWEAKSTATE_ac -#define FX_BWSrc FX_BIDIWEAKSTATE_rc -#define FX_BWSrs FX_BIDIWEAKSTATE_rs -#define FX_BWSlc FX_BIDIWEAKSTATE_lc -#define FX_BWSls FX_BIDIWEAKSTATE_ls -#define FX_BWSret FX_BIDIWEAKSTATE_ret -#define FX_BWSlet FX_BIDIWEAKSTATE_let - -enum FX_BIDIWEAKACTION { - FX_BIDIWEAKACTION_IX = 0x100, - FX_BIDIWEAKACTION_XX = 0x0F, - FX_BIDIWEAKACTION_xxx = (0x0F << 4) + 0x0F, - FX_BIDIWEAKACTION_xIx = 0x100 + FX_BIDIWEAKACTION_xxx, - FX_BIDIWEAKACTION_xxN = (0x0F << 4) + FX_BIDICLASS_ON, - FX_BIDIWEAKACTION_xxE = (0x0F << 4) + FX_BIDICLASS_EN, - FX_BIDIWEAKACTION_xxA = (0x0F << 4) + FX_BIDICLASS_AN, - FX_BIDIWEAKACTION_xxR = (0x0F << 4) + FX_BIDICLASS_R, - FX_BIDIWEAKACTION_xxL = (0x0F << 4) + FX_BIDICLASS_L, - FX_BIDIWEAKACTION_Nxx = (FX_BIDICLASS_ON << 4) + 0x0F, - FX_BIDIWEAKACTION_Axx = (FX_BIDICLASS_AN << 4) + 0x0F, - FX_BIDIWEAKACTION_ExE = (FX_BIDICLASS_EN << 4) + FX_BIDICLASS_EN, - FX_BIDIWEAKACTION_NIx = (FX_BIDICLASS_ON << 4) + 0x0F + 0x100, - FX_BIDIWEAKACTION_NxN = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_ON, - FX_BIDIWEAKACTION_NxR = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_R, - FX_BIDIWEAKACTION_NxE = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_EN, - FX_BIDIWEAKACTION_AxA = (FX_BIDICLASS_AN << 4) + FX_BIDICLASS_AN, - FX_BIDIWEAKACTION_NxL = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_L, - FX_BIDIWEAKACTION_LxL = (FX_BIDICLASS_L << 4) + FX_BIDICLASS_L, - FX_BIDIWEAKACTION_xIL = (0x0F << 4) + FX_BIDICLASS_L + 0x100, - FX_BIDIWEAKACTION_AxR = (FX_BIDICLASS_AN << 4) + FX_BIDICLASS_R, - FX_BIDIWEAKACTION_Lxx = (FX_BIDICLASS_L << 4) + 0x0F, -}; -#define FX_BWAIX FX_BIDIWEAKACTION_IX -#define FX_BWAXX FX_BIDIWEAKACTION_XX -#define FX_BWAxxx FX_BIDIWEAKACTION_xxx -#define FX_BWAxIx FX_BIDIWEAKACTION_xIx -#define FX_BWAxxN FX_BIDIWEAKACTION_xxN -#define FX_BWAxxE FX_BIDIWEAKACTION_xxE -#define FX_BWAxxA FX_BIDIWEAKACTION_xxA -#define FX_BWAxxR FX_BIDIWEAKACTION_xxR -#define FX_BWAxxL FX_BIDIWEAKACTION_xxL -#define FX_BWANxx FX_BIDIWEAKACTION_Nxx -#define FX_BWAAxx FX_BIDIWEAKACTION_Axx -#define FX_BWAExE FX_BIDIWEAKACTION_ExE -#define FX_BWANIx FX_BIDIWEAKACTION_NIx -#define FX_BWANxN FX_BIDIWEAKACTION_NxN -#define FX_BWANxR FX_BIDIWEAKACTION_NxR -#define FX_BWANxE FX_BIDIWEAKACTION_NxE -#define FX_BWAAxA FX_BIDIWEAKACTION_AxA -#define FX_BWANxL FX_BIDIWEAKACTION_NxL -#define FX_BWALxL FX_BIDIWEAKACTION_LxL -#define FX_BWAxIL FX_BIDIWEAKACTION_xIL -#define FX_BWAAxR FX_BIDIWEAKACTION_AxR -#define FX_BWALxx FX_BIDIWEAKACTION_Lxx - -void FX_BidiResolveWeak(int32_t iBaseLevel, - CFX_ArrayTemplate& classes, - CFX_ArrayTemplate& levels); -enum FX_BIDINEUTRALSTATE { - FX_BIDINEUTRALSTATE_r = 0, - FX_BIDINEUTRALSTATE_l, - FX_BIDINEUTRALSTATE_rn, - FX_BIDINEUTRALSTATE_ln, - FX_BIDINEUTRALSTATE_a, - FX_BIDINEUTRALSTATE_na, -}; -#define FX_BNSr FX_BIDINEUTRALSTATE_r -#define FX_BNSl FX_BIDINEUTRALSTATE_l -#define FX_BNSrn FX_BIDINEUTRALSTATE_rn -#define FX_BNSln FX_BIDINEUTRALSTATE_ln -#define FX_BNSa FX_BIDINEUTRALSTATE_a -#define FX_BNSna FX_BIDINEUTRALSTATE_na -enum FX_BIDINEUTRALACTION { - FX_BIDINEUTRALACTION_nL = FX_BIDICLASS_L, - FX_BIDINEUTRALACTION_En = (FX_BIDICLASS_AN << 4), - FX_BIDINEUTRALACTION_Rn = (FX_BIDICLASS_R << 4), - FX_BIDINEUTRALACTION_Ln = (FX_BIDICLASS_L << 4), - FX_BIDINEUTRALACTION_In = FX_BIDIWEAKACTION_IX, - FX_BIDINEUTRALACTION_LnL = (FX_BIDICLASS_L << 4) + FX_BIDICLASS_L, -}; -#define FX_BNAnL FX_BIDINEUTRALACTION_nL -#define FX_BNAEn FX_BIDINEUTRALACTION_En -#define FX_BNARn FX_BIDINEUTRALACTION_Rn -#define FX_BNALn FX_BIDINEUTRALACTION_Ln -#define FX_BNAIn FX_BIDINEUTRALACTION_In -#define FX_BNALnL FX_BIDINEUTRALACTION_LnL -int32_t FX_BidiGetDeferredNeutrals(int32_t iAction, int32_t iLevel); -int32_t FX_BidiGetResolvedNeutrals(int32_t iAction); -void FX_BidiResolveNeutrals(int32_t iBaseLevel, - CFX_ArrayTemplate& classes, - const CFX_ArrayTemplate& levels); -void FX_BidiResolveImplicit(const CFX_ArrayTemplate& classes, - CFX_ArrayTemplate& levels); -void FX_BidiResolveWhitespace(int32_t iBaseLevel, - const CFX_ArrayTemplate& classes, - CFX_ArrayTemplate& levels); -int32_t FX_BidiReorderLevel(int32_t iBaseLevel, - CFX_WideString& wsText, - const CFX_ArrayTemplate& levels, - int32_t iStart, - bool bReverse = false); -void FX_BidiReorder(int32_t iBaseLevel, - CFX_WideString& wsText, - const CFX_ArrayTemplate& levels); +wchar_t FX_GetArabicFromShaddaTable(wchar_t shadda); #endif // CORE_FXCRT_FX_ARABIC_H_ diff --git a/core/fxcrt/fx_arb.h b/core/fxcrt/fx_arb.h deleted file mode 100644 index d24197c7e5c7edd63ea20cc638f311caa4fc0e11..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_arb.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FX_ARB_H_ -#define CORE_FXCRT_FX_ARB_H_ - -#include - -#include "core/fxcrt/fx_system.h" -#include "core/fxcrt/fx_ucd.h" - -struct FX_ARBFORMTABLE { - uint16_t wIsolated; - uint16_t wFinal; - uint16_t wInitial; - uint16_t wMedial; -}; - -struct FX_ARAALEF { - uint16_t wAlef; - uint16_t wIsolated; -}; - -struct FX_ARASHADDA { - uint16_t wShadda; - uint16_t wIsolated; -}; - -const FX_ARBFORMTABLE* FX_GetArabicFormTable(FX_WCHAR unicode); -FX_WCHAR FX_GetArabicFromAlefTable(FX_WCHAR alef); -FX_WCHAR FX_GetArabicFromShaddaTable(FX_WCHAR shadda); - -enum FX_ARBPOSITION { - FX_ARBPOSITION_Isolated = 0, - FX_ARBPOSITION_Final, - FX_ARBPOSITION_Initial, - FX_ARBPOSITION_Medial, -}; - -void FX_BidiLine(CFX_WideString& wsText, int32_t iBaseLevel = 0); -void FX_BidiLine(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel = 0); -void FX_BidiLine(std::vector& chars, - int32_t iCount, - int32_t iBaseLevel = 0); - -#endif // CORE_FXCRT_FX_ARB_H_ diff --git a/core/fxcrt/fx_basic.h b/core/fxcrt/fx_basic.h deleted file mode 100644 index 18413b2e70669e70a626702b66e57af03a961e2d..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic.h +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FX_BASIC_H_ -#define CORE_FXCRT_FX_BASIC_H_ - -#include -#include - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_stream.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" - -#ifdef PDF_ENABLE_XFA -#define FX_IsOdd(a) ((a)&1) -#endif // PDF_ENABLE_XFA - -class CFX_BinaryBuf { - public: - CFX_BinaryBuf(); - explicit CFX_BinaryBuf(FX_STRSIZE size); - ~CFX_BinaryBuf(); - - uint8_t* GetBuffer() const { return m_pBuffer.get(); } - FX_STRSIZE GetSize() const { return m_DataSize; } - - void Clear(); - void EstimateSize(FX_STRSIZE size, FX_STRSIZE alloc_step = 0); - void AppendBlock(const void* pBuf, FX_STRSIZE size); - void AppendString(const CFX_ByteString& str) { - AppendBlock(str.c_str(), str.GetLength()); - } - - void AppendByte(uint8_t byte) { - ExpandBuf(1); - m_pBuffer.get()[m_DataSize++] = byte; - } - - void InsertBlock(FX_STRSIZE pos, const void* pBuf, FX_STRSIZE size); - void Delete(int start_index, int count); - - // Releases ownership of |m_pBuffer| and returns it. - std::unique_ptr DetachBuffer(); - - protected: - void ExpandBuf(FX_STRSIZE size); - - FX_STRSIZE m_AllocStep; - FX_STRSIZE m_AllocSize; - FX_STRSIZE m_DataSize; - std::unique_ptr m_pBuffer; -}; - -class CFX_ByteTextBuf : public CFX_BinaryBuf { - public: - FX_STRSIZE GetLength() const { return m_DataSize; } - CFX_ByteString MakeString() const { - return CFX_ByteString(m_pBuffer.get(), m_DataSize); - } - CFX_ByteStringC AsStringC() const { - return CFX_ByteStringC(m_pBuffer.get(), m_DataSize); - } - - void AppendChar(int ch) { AppendByte(static_cast(ch)); } - CFX_ByteTextBuf& operator<<(int i); - CFX_ByteTextBuf& operator<<(uint32_t i); - CFX_ByteTextBuf& operator<<(double f); - CFX_ByteTextBuf& operator<<(const FX_CHAR* pStr) { - return *this << CFX_ByteStringC(pStr); - } - CFX_ByteTextBuf& operator<<(const CFX_ByteString& str) { - return *this << str.AsStringC(); - } - CFX_ByteTextBuf& operator<<(const CFX_ByteStringC& lpsz); - CFX_ByteTextBuf& operator<<(const CFX_ByteTextBuf& buf); -}; - -class CFX_WideTextBuf : public CFX_BinaryBuf { - public: - void AppendChar(FX_WCHAR wch); - FX_STRSIZE GetLength() const { return m_DataSize / sizeof(FX_WCHAR); } - FX_WCHAR* GetBuffer() const { - return reinterpret_cast(m_pBuffer.get()); - } - - CFX_WideStringC AsStringC() const { - return CFX_WideStringC(reinterpret_cast(m_pBuffer.get()), - m_DataSize / sizeof(FX_WCHAR)); - } - CFX_WideString MakeString() const { - return CFX_WideString(reinterpret_cast(m_pBuffer.get()), - m_DataSize / sizeof(FX_WCHAR)); - } - - void Delete(int start_index, int count) { - CFX_BinaryBuf::Delete(start_index * sizeof(FX_WCHAR), - count * sizeof(FX_WCHAR)); - } - - CFX_WideTextBuf& operator<<(int i); - CFX_WideTextBuf& operator<<(double f); - CFX_WideTextBuf& operator<<(const FX_WCHAR* lpsz); - CFX_WideTextBuf& operator<<(const CFX_WideStringC& str); - CFX_WideTextBuf& operator<<(const CFX_WideString& str); - CFX_WideTextBuf& operator<<(const CFX_WideTextBuf& buf); -}; - -class CFX_FileBufferArchive { - public: - CFX_FileBufferArchive(); - ~CFX_FileBufferArchive(); - - void Clear(); - bool Flush(); - int32_t AppendBlock(const void* pBuf, size_t size); - int32_t AppendByte(uint8_t byte); - int32_t AppendDWord(uint32_t i); - int32_t AppendString(const CFX_ByteStringC& lpsz); - void AttachFile(const CFX_RetainPtr& pFile); - - private: - static const size_t kBufSize = 32768; - - size_t m_Length; - std::unique_ptr m_pBuffer; - CFX_RetainPtr m_pFile; -}; - -class CFX_CharMap { - public: - static CFX_ByteString GetByteString(uint16_t codepage, - const CFX_WideStringC& wstr); - - static CFX_WideString GetWideString(uint16_t codepage, - const CFX_ByteStringC& bstr); - - CFX_CharMap() = delete; -}; - -class CFX_UTF8Decoder { - public: - CFX_UTF8Decoder() { m_PendingBytes = 0; } - - void Clear(); - - void Input(uint8_t byte); - - void AppendChar(uint32_t ch); - - void ClearStatus() { m_PendingBytes = 0; } - - CFX_WideStringC GetResult() const { return m_Buffer.AsStringC(); } - - protected: - int m_PendingBytes; - - uint32_t m_PendingChar; - - CFX_WideTextBuf m_Buffer; -}; - -class CFX_UTF8Encoder { - public: - CFX_UTF8Encoder() {} - - void Input(FX_WCHAR unicode); - void AppendStr(const CFX_ByteStringC& str) { m_Buffer << str; } - CFX_ByteStringC GetResult() const { return m_Buffer.AsStringC(); } - - protected: - CFX_ByteTextBuf m_Buffer; -}; - -class CFX_BasicArray { - protected: - explicit CFX_BasicArray(int unit_size); - CFX_BasicArray(const CFX_BasicArray&) = delete; - ~CFX_BasicArray(); - - bool SetSize(int nNewSize); - bool Append(const CFX_BasicArray& src); - bool Copy(const CFX_BasicArray& src); - uint8_t* InsertSpaceAt(int nIndex, int nCount); - bool RemoveAt(int nIndex, int nCount); - bool InsertAt(int nStartIndex, const CFX_BasicArray* pNewArray); - const void* GetDataPtr(int index) const; - - protected: - uint8_t* m_pData; - int m_nSize; - int m_nMaxSize; - int m_nUnitSize; -}; - -template -class CFX_ArrayTemplate : public CFX_BasicArray { - public: - CFX_ArrayTemplate() : CFX_BasicArray(sizeof(TYPE)) {} - - int GetSize() const { return m_nSize; } - - int GetUpperBound() const { return m_nSize - 1; } - - bool SetSize(int nNewSize) { return CFX_BasicArray::SetSize(nNewSize); } - - void RemoveAll() { SetSize(0); } - - const TYPE GetAt(int nIndex) const { - if (nIndex < 0 || nIndex >= m_nSize) { - PDFIUM_IMMEDIATE_CRASH(); - } - return ((const TYPE*)m_pData)[nIndex]; - } - - bool SetAt(int nIndex, TYPE newElement) { - if (nIndex < 0 || nIndex >= m_nSize) { - return false; - } - ((TYPE*)m_pData)[nIndex] = newElement; - return true; - } - - TYPE& ElementAt(int nIndex) { - if (nIndex < 0 || nIndex >= m_nSize) { - PDFIUM_IMMEDIATE_CRASH(); - } - return ((TYPE*)m_pData)[nIndex]; - } - - const TYPE* GetData() const { return (const TYPE*)m_pData; } - - TYPE* GetData() { return (TYPE*)m_pData; } - - bool SetAtGrow(int nIndex, TYPE newElement) { - if (nIndex < 0) - return false; - - if (nIndex >= m_nSize && !SetSize(nIndex + 1)) - return false; - - ((TYPE*)m_pData)[nIndex] = newElement; - return true; - } - - bool Add(TYPE newElement) { - if (m_nSize < m_nMaxSize) { - m_nSize++; - } else if (!SetSize(m_nSize + 1)) { - return false; - } - ((TYPE*)m_pData)[m_nSize - 1] = newElement; - return true; - } - - bool Append(const CFX_ArrayTemplate& src) { - return CFX_BasicArray::Append(src); - } - - bool Copy(const CFX_ArrayTemplate& src) { return CFX_BasicArray::Copy(src); } - - TYPE* GetDataPtr(int index) { - return (TYPE*)CFX_BasicArray::GetDataPtr(index); - } - - TYPE* AddSpace() { return (TYPE*)CFX_BasicArray::InsertSpaceAt(m_nSize, 1); } - - TYPE* InsertSpaceAt(int nIndex, int nCount) { - return (TYPE*)CFX_BasicArray::InsertSpaceAt(nIndex, nCount); - } - - const TYPE operator[](int nIndex) const { - if (nIndex < 0 || nIndex >= m_nSize) { - *(volatile char*)0 = '\0'; - } - return ((const TYPE*)m_pData)[nIndex]; - } - - TYPE& operator[](int nIndex) { - if (nIndex < 0 || nIndex >= m_nSize) { - *(volatile char*)0 = '\0'; - } - return ((TYPE*)m_pData)[nIndex]; - } - - bool InsertAt(int nIndex, TYPE newElement, int nCount = 1) { - if (!InsertSpaceAt(nIndex, nCount)) { - return false; - } - while (nCount--) { - ((TYPE*)m_pData)[nIndex++] = newElement; - } - return true; - } - - bool RemoveAt(int nIndex, int nCount = 1) { - return CFX_BasicArray::RemoveAt(nIndex, nCount); - } - - bool InsertAt(int nStartIndex, const CFX_BasicArray* pNewArray) { - return CFX_BasicArray::InsertAt(nStartIndex, pNewArray); - } - - int Find(TYPE data, int iStart = 0) const { - if (iStart < 0) { - return -1; - } - for (; iStart < (int)m_nSize; iStart++) - if (((TYPE*)m_pData)[iStart] == data) { - return iStart; - } - return -1; - } -}; - -template -class CFX_FixedBufGrow { - public: - explicit CFX_FixedBufGrow(int data_size) { - if (data_size > FixedSize) { - m_pGrowData.reset(FX_Alloc(DataType, data_size)); - return; - } - FXSYS_memset(m_FixedData, 0, sizeof(DataType) * FixedSize); - } - operator DataType*() { return m_pGrowData ? m_pGrowData.get() : m_FixedData; } - - private: - DataType m_FixedData[FixedSize]; - std::unique_ptr m_pGrowData; -}; - -class CFX_BitStream { - public: - void Init(const uint8_t* pData, uint32_t dwSize); - - uint32_t GetBits(uint32_t nBits); - - void ByteAlign(); - - bool IsEOF() { return m_BitPos >= m_BitSize; } - - void SkipBits(uint32_t nBits) { m_BitPos += nBits; } - - void Rewind() { m_BitPos = 0; } - - uint32_t GetPos() const { return m_BitPos; } - - uint32_t BitsRemaining() const { - return m_BitSize >= m_BitPos ? m_BitSize - m_BitPos : 0; - } - - protected: - uint32_t m_BitPos; - uint32_t m_BitSize; - const uint8_t* m_pData; -}; - -class IFX_Pause { - public: - virtual ~IFX_Pause() {} - virtual bool NeedToPauseNow() = 0; -}; - -template -class CFX_AutoRestorer { - public: - explicit CFX_AutoRestorer(T* location) - : m_Location(location), m_OldValue(*location) {} - ~CFX_AutoRestorer() { *m_Location = m_OldValue; } - - private: - T* const m_Location; - const T m_OldValue; -}; - -#define FX_DATALIST_LENGTH 1024 -template -class CFX_SortListArray { - protected: - struct DataList { - int32_t start; - - int32_t count; - uint8_t* data; - }; - - public: - CFX_SortListArray() : m_CurList(0) {} - - ~CFX_SortListArray() { Clear(); } - - void Clear() { - for (int32_t i = m_DataLists.GetUpperBound(); i >= 0; i--) { - DataList list = m_DataLists.ElementAt(i); - FX_Free(list.data); - } - m_DataLists.RemoveAll(); - m_CurList = 0; - } - - void Append(int32_t nStart, int32_t nCount) { - if (nStart < 0) { - return; - } - while (nCount > 0) { - int32_t temp_count = std::min(nCount, FX_DATALIST_LENGTH); - DataList list; - list.data = FX_Alloc2D(uint8_t, temp_count, unit); - list.start = nStart; - list.count = temp_count; - Append(list); - nCount -= temp_count; - nStart += temp_count; - } - } - - uint8_t* GetAt(int32_t nIndex) { - if (nIndex < 0) { - return nullptr; - } - if (m_CurList < 0 || m_CurList >= m_DataLists.GetSize()) { - return nullptr; - } - DataList* pCurList = m_DataLists.GetDataPtr(m_CurList); - if (!pCurList || nIndex < pCurList->start || - nIndex >= pCurList->start + pCurList->count) { - pCurList = nullptr; - int32_t iStart = 0; - int32_t iEnd = m_DataLists.GetUpperBound(); - int32_t iMid = 0; - while (iStart <= iEnd) { - iMid = (iStart + iEnd) / 2; - DataList* list = m_DataLists.GetDataPtr(iMid); - if (nIndex < list->start) { - iEnd = iMid - 1; - } else if (nIndex >= list->start + list->count) { - iStart = iMid + 1; - } else { - pCurList = list; - m_CurList = iMid; - break; - } - } - } - return pCurList ? pCurList->data + (nIndex - pCurList->start) * unit - : nullptr; - } - - protected: - void Append(const DataList& list) { - int32_t iStart = 0; - int32_t iEnd = m_DataLists.GetUpperBound(); - int32_t iFind = 0; - while (iStart <= iEnd) { - int32_t iMid = (iStart + iEnd) / 2; - DataList* cur_list = m_DataLists.GetDataPtr(iMid); - if (list.start < cur_list->start + cur_list->count) { - iEnd = iMid - 1; - } else { - if (iMid == iEnd) { - iFind = iMid + 1; - break; - } - DataList* next_list = m_DataLists.GetDataPtr(iMid + 1); - if (list.start < next_list->start) { - iFind = iMid + 1; - break; - } else { - iStart = iMid + 1; - } - } - } - m_DataLists.InsertAt(iFind, list); - } - int32_t m_CurList; - CFX_ArrayTemplate m_DataLists; -}; -template -class CFX_ListArrayTemplate { - public: - void Clear() { m_Data.Clear(); } - - void Add(int32_t nStart, int32_t nCount) { m_Data.Append(nStart, nCount); } - - T2& operator[](int32_t nIndex) { - uint8_t* data = m_Data.GetAt(nIndex); - ASSERT(data); - return (T2&)(*(volatile T2*)data); - } - - T2* GetPtrAt(int32_t nIndex) { return (T2*)m_Data.GetAt(nIndex); } - - protected: - T1 m_Data; -}; -typedef CFX_ListArrayTemplate, - FX_FILESIZE> - CFX_FileSizeListArray; - -class CFX_Vector_3by1 { - public: - CFX_Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {} - - CFX_Vector_3by1(FX_FLOAT a1, FX_FLOAT b1, FX_FLOAT c1) - : a(a1), b(b1), c(c1) {} - - FX_FLOAT a; - FX_FLOAT b; - FX_FLOAT c; -}; -class CFX_Matrix_3by3 { - public: - CFX_Matrix_3by3() - : a(0.0f), - b(0.0f), - c(0.0f), - d(0.0f), - e(0.0f), - f(0.0f), - g(0.0f), - h(0.0f), - i(0.0f) {} - - CFX_Matrix_3by3(FX_FLOAT a1, - FX_FLOAT b1, - FX_FLOAT c1, - FX_FLOAT d1, - FX_FLOAT e1, - FX_FLOAT f1, - FX_FLOAT g1, - FX_FLOAT h1, - FX_FLOAT i1) - : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1) {} - - CFX_Matrix_3by3 Inverse(); - - CFX_Matrix_3by3 Multiply(const CFX_Matrix_3by3& m); - - CFX_Vector_3by1 TransformVector(const CFX_Vector_3by1& v); - - FX_FLOAT a; - FX_FLOAT b; - FX_FLOAT c; - FX_FLOAT d; - FX_FLOAT e; - FX_FLOAT f; - FX_FLOAT g; - FX_FLOAT h; - FX_FLOAT i; -}; - -uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits); - -#endif // CORE_FXCRT_FX_BASIC_H_ diff --git a/core/fxcrt/fx_basic_array.cpp b/core/fxcrt/fx_basic_array.cpp deleted file mode 100644 index 83c981e9e7643e67f77d06e3afdef08920a05540..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_array.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fx_basic.h" -#include "third_party/base/numerics/safe_math.h" - -CFX_BasicArray::CFX_BasicArray(int unit_size) - : m_pData(nullptr), m_nSize(0), m_nMaxSize(0) { - if (unit_size < 0 || unit_size > (1 << 28)) { - m_nUnitSize = 4; - } else { - m_nUnitSize = unit_size; - } -} -CFX_BasicArray::~CFX_BasicArray() { - FX_Free(m_pData); -} -bool CFX_BasicArray::SetSize(int nNewSize) { - if (nNewSize <= 0) { - FX_Free(m_pData); - m_pData = nullptr; - m_nSize = m_nMaxSize = 0; - return 0 == nNewSize; - } - - if (!m_pData) { - pdfium::base::CheckedNumeric totalSize = nNewSize; - totalSize *= m_nUnitSize; - if (!totalSize.IsValid()) { - m_nSize = m_nMaxSize = 0; - return false; - } - m_pData = - FX_Alloc(uint8_t, pdfium::base::ValueOrDieForType(totalSize)); - m_nSize = m_nMaxSize = nNewSize; - } else if (nNewSize <= m_nMaxSize) { - if (nNewSize > m_nSize) { - FXSYS_memset(m_pData + m_nSize * m_nUnitSize, 0, - (nNewSize - m_nSize) * m_nUnitSize); - } - m_nSize = nNewSize; - } else { - int nNewMax = nNewSize < m_nMaxSize ? m_nMaxSize : nNewSize; - pdfium::base::CheckedNumeric totalSize = nNewMax; - totalSize *= m_nUnitSize; - if (!totalSize.IsValid() || nNewMax < m_nSize) { - return false; - } - uint8_t* pNewData = FX_Realloc( - uint8_t, m_pData, pdfium::base::ValueOrDieForType(totalSize)); - if (!pNewData) { - return false; - } - FXSYS_memset(pNewData + m_nSize * m_nUnitSize, 0, - (nNewMax - m_nSize) * m_nUnitSize); - m_pData = pNewData; - m_nSize = nNewSize; - m_nMaxSize = nNewMax; - } - return true; -} -bool CFX_BasicArray::Append(const CFX_BasicArray& src) { - int nOldSize = m_nSize; - pdfium::base::CheckedNumeric newSize = m_nSize; - newSize += src.m_nSize; - if (m_nUnitSize != src.m_nUnitSize || !newSize.IsValid() || - !SetSize(newSize.ValueOrDie())) { - return false; - } - - FXSYS_memcpy(m_pData + nOldSize * m_nUnitSize, src.m_pData, - src.m_nSize * m_nUnitSize); - return true; -} -bool CFX_BasicArray::Copy(const CFX_BasicArray& src) { - if (!SetSize(src.m_nSize)) { - return false; - } - FXSYS_memcpy(m_pData, src.m_pData, src.m_nSize * m_nUnitSize); - return true; -} -uint8_t* CFX_BasicArray::InsertSpaceAt(int nIndex, int nCount) { - if (nIndex < 0 || nCount <= 0) { - return nullptr; - } - if (nIndex >= m_nSize) { - if (!SetSize(nIndex + nCount)) { - return nullptr; - } - } else { - int nOldSize = m_nSize; - if (!SetSize(m_nSize + nCount)) { - return nullptr; - } - FXSYS_memmove(m_pData + (nIndex + nCount) * m_nUnitSize, - m_pData + nIndex * m_nUnitSize, - (nOldSize - nIndex) * m_nUnitSize); - FXSYS_memset(m_pData + nIndex * m_nUnitSize, 0, nCount * m_nUnitSize); - } - return m_pData + nIndex * m_nUnitSize; -} -bool CFX_BasicArray::RemoveAt(int nIndex, int nCount) { - if (nIndex < 0 || nCount <= 0 || m_nSize < nIndex + nCount) { - return false; - } - int nMoveCount = m_nSize - (nIndex + nCount); - if (nMoveCount) { - FXSYS_memmove(m_pData + nIndex * m_nUnitSize, - m_pData + (nIndex + nCount) * m_nUnitSize, - nMoveCount * m_nUnitSize); - } - m_nSize -= nCount; - return true; -} -bool CFX_BasicArray::InsertAt(int nStartIndex, - const CFX_BasicArray* pNewArray) { - if (!pNewArray) { - return false; - } - if (pNewArray->m_nSize == 0) { - return true; - } - if (!InsertSpaceAt(nStartIndex, pNewArray->m_nSize)) { - return false; - } - FXSYS_memcpy(m_pData + nStartIndex * m_nUnitSize, pNewArray->m_pData, - pNewArray->m_nSize * m_nUnitSize); - return true; -} -const void* CFX_BasicArray::GetDataPtr(int index) const { - if (index < 0 || index >= m_nSize || !m_pData) { - return nullptr; - } - return m_pData + index * m_nUnitSize; -} diff --git a/core/fxcrt/fx_basic_bstring.cpp b/core/fxcrt/fx_basic_bstring.cpp deleted file mode 100644 index 2669474f009336848f66dcc1aa4b461d0a0410b6..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_bstring.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include -#include - -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/fx_basic.h" -#include "third_party/base/numerics/safe_math.h" - -template class CFX_StringDataTemplate; -template class CFX_StringCTemplate; -template class CFX_StringPoolTemplate; -template struct std::hash; - -namespace { - -int Buffer_itoa(char* buf, int i, uint32_t flags) { - if (i == 0) { - buf[0] = '0'; - return 1; - } - char buf1[32]; - int buf_pos = 31; - uint32_t u = i; - if ((flags & FXFORMAT_SIGNED) && i < 0) { - u = -i; - } - int base = 10; - const FX_CHAR* str = "0123456789abcdef"; - if (flags & FXFORMAT_HEX) { - base = 16; - if (flags & FXFORMAT_CAPITAL) { - str = "0123456789ABCDEF"; - } - } - while (u != 0) { - buf1[buf_pos--] = str[u % base]; - u = u / base; - } - if ((flags & FXFORMAT_SIGNED) && i < 0) { - buf1[buf_pos--] = '-'; - } - int len = 31 - buf_pos; - for (int ii = 0; ii < len; ii++) { - buf[ii] = buf1[ii + buf_pos + 1]; - } - return len; -} - -const FX_CHAR* FX_strstr(const FX_CHAR* haystack, - int haystack_len, - const FX_CHAR* needle, - int needle_len) { - if (needle_len > haystack_len || needle_len == 0) { - return nullptr; - } - const FX_CHAR* end_ptr = haystack + haystack_len - needle_len; - while (haystack <= end_ptr) { - int i = 0; - while (1) { - if (haystack[i] != needle[i]) { - break; - } - i++; - if (i == needle_len) { - return haystack; - } - } - haystack++; - } - return nullptr; -} - -} // namespace - -static_assert(sizeof(CFX_ByteString) <= sizeof(FX_CHAR*), - "Strings must not require more space than pointers"); - -CFX_ByteString::CFX_ByteString(const FX_CHAR* pStr, FX_STRSIZE nLen) { - if (nLen < 0) - nLen = pStr ? FXSYS_strlen(pStr) : 0; - - if (nLen) - m_pData.Reset(StringData::Create(pStr, nLen)); -} - -CFX_ByteString::CFX_ByteString(const uint8_t* pStr, FX_STRSIZE nLen) { - if (nLen > 0) { - m_pData.Reset( - StringData::Create(reinterpret_cast(pStr), nLen)); - } -} - -CFX_ByteString::CFX_ByteString() {} - -CFX_ByteString::CFX_ByteString(const CFX_ByteString& other) - : m_pData(other.m_pData) {} - -CFX_ByteString::CFX_ByteString(CFX_ByteString&& other) { - m_pData.Swap(other.m_pData); -} - -CFX_ByteString::CFX_ByteString(char ch) { - m_pData.Reset(StringData::Create(1)); - m_pData->m_String[0] = ch; -} - -CFX_ByteString::CFX_ByteString(const FX_CHAR* ptr) - : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) {} - -CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& stringSrc) { - if (!stringSrc.IsEmpty()) - m_pData.Reset(StringData::Create(stringSrc.c_str(), stringSrc.GetLength())); -} - -CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& str1, - const CFX_ByteStringC& str2) { - int nNewLen = str1.GetLength() + str2.GetLength(); - if (nNewLen == 0) - return; - - m_pData.Reset(StringData::Create(nNewLen)); - m_pData->CopyContents(str1.c_str(), str1.GetLength()); - m_pData->CopyContentsAt(str1.GetLength(), str2.c_str(), str2.GetLength()); -} - -CFX_ByteString::~CFX_ByteString() {} - -const CFX_ByteString& CFX_ByteString::operator=(const FX_CHAR* pStr) { - if (!pStr || !pStr[0]) - clear(); - else - AssignCopy(pStr, FXSYS_strlen(pStr)); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator=( - const CFX_ByteStringC& stringSrc) { - if (stringSrc.IsEmpty()) - clear(); - else - AssignCopy(stringSrc.c_str(), stringSrc.GetLength()); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator=( - const CFX_ByteString& stringSrc) { - if (m_pData != stringSrc.m_pData) - m_pData = stringSrc.m_pData; - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(const FX_CHAR* pStr) { - if (pStr) - Concat(pStr, FXSYS_strlen(pStr)); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(char ch) { - Concat(&ch, 1); - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteString& str) { - if (str.m_pData) - Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteStringC& str) { - if (!str.IsEmpty()) - Concat(str.c_str(), str.GetLength()); - - return *this; -} - -bool CFX_ByteString::operator==(const char* ptr) const { - if (!m_pData) - return !ptr || !ptr[0]; - - if (!ptr) - return m_pData->m_nDataLength == 0; - - return FXSYS_strlen(ptr) == m_pData->m_nDataLength && - FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; -} - -bool CFX_ByteString::operator==(const CFX_ByteStringC& str) const { - if (!m_pData) - return str.IsEmpty(); - - return m_pData->m_nDataLength == str.GetLength() && - FXSYS_memcmp(m_pData->m_String, str.c_str(), str.GetLength()) == 0; -} - -bool CFX_ByteString::operator==(const CFX_ByteString& other) const { - if (m_pData == other.m_pData) - return true; - - if (IsEmpty()) - return other.IsEmpty(); - - if (other.IsEmpty()) - return false; - - return other.m_pData->m_nDataLength == m_pData->m_nDataLength && - FXSYS_memcmp(other.m_pData->m_String, m_pData->m_String, - m_pData->m_nDataLength) == 0; -} - -bool CFX_ByteString::operator<(const CFX_ByteString& str) const { - if (m_pData == str.m_pData) - return false; - - int result = FXSYS_memcmp(c_str(), str.c_str(), - std::min(GetLength(), str.GetLength())); - return result < 0 || (result == 0 && GetLength() < str.GetLength()); -} - -bool CFX_ByteString::EqualNoCase(const CFX_ByteStringC& str) const { - if (!m_pData) - return str.IsEmpty(); - - FX_STRSIZE len = str.GetLength(); - if (m_pData->m_nDataLength != len) - return false; - - const uint8_t* pThis = (const uint8_t*)m_pData->m_String; - const uint8_t* pThat = str.raw_str(); - for (FX_STRSIZE i = 0; i < len; i++) { - if ((*pThis) != (*pThat)) { - uint8_t bThis = *pThis; - if (bThis >= 'A' && bThis <= 'Z') - bThis += 'a' - 'A'; - - uint8_t bThat = *pThat; - if (bThat >= 'A' && bThat <= 'Z') - bThat += 'a' - 'A'; - - if (bThis != bThat) - return false; - } - pThis++; - pThat++; - } - return true; -} - -void CFX_ByteString::AssignCopy(const FX_CHAR* pSrcData, FX_STRSIZE nSrcLen) { - AllocBeforeWrite(nSrcLen); - m_pData->CopyContents(pSrcData, nSrcLen); - m_pData->m_nDataLength = nSrcLen; -} - -void CFX_ByteString::ReallocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength <= 0) { - clear(); - return; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - if (m_pData) { - FX_STRSIZE nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); - pNewData->CopyContents(m_pData->m_String, nCopyLength); - pNewData->m_nDataLength = nCopyLength; - } else { - pNewData->m_nDataLength = 0; - } - pNewData->m_String[pNewData->m_nDataLength] = 0; - m_pData.Swap(pNewData); -} - -void CFX_ByteString::AllocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength <= 0) { - clear(); - return; - } - - m_pData.Reset(StringData::Create(nNewLength)); -} - -void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) { - if (!m_pData) - return; - - if (nNewLength == -1) - nNewLength = FXSYS_strlen(m_pData->m_String); - - nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); - if (nNewLength == 0) { - clear(); - return; - } - - ASSERT(m_pData->m_nRefs == 1); - m_pData->m_nDataLength = nNewLength; - m_pData->m_String[nNewLength] = 0; - if (m_pData->m_nAllocLength - nNewLength >= 32) { - // Over arbitrary threshold, so pay the price to relocate. Force copy to - // always occur by holding a second reference to the string. - CFX_ByteString preserve(*this); - ReallocBeforeWrite(nNewLength); - } -} - -void CFX_ByteString::Reserve(FX_STRSIZE len) { - GetBuffer(len); -} - -FX_CHAR* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) { - if (!m_pData) { - if (nMinBufLength == 0) - return nullptr; - - m_pData.Reset(StringData::Create(nMinBufLength)); - m_pData->m_nDataLength = 0; - m_pData->m_String[0] = 0; - return m_pData->m_String; - } - - if (m_pData->CanOperateInPlace(nMinBufLength)) - return m_pData->m_String; - - nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); - if (nMinBufLength == 0) - return nullptr; - - CFX_RetainPtr pNewData(StringData::Create(nMinBufLength)); - pNewData->CopyContents(*m_pData); - pNewData->m_nDataLength = m_pData->m_nDataLength; - m_pData.Swap(pNewData); - return m_pData->m_String; -} - -FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) { - if (!m_pData) - return 0; - - if (nIndex < 0) - nIndex = 0; - - FX_STRSIZE nOldLength = m_pData->m_nDataLength; - if (nCount > 0 && nIndex < nOldLength) { - FX_STRSIZE mLength = nIndex + nCount; - if (mLength >= nOldLength) { - m_pData->m_nDataLength = nIndex; - return m_pData->m_nDataLength; - } - ReallocBeforeWrite(nOldLength); - int nCharsToCopy = nOldLength - mLength + 1; - FXSYS_memmove(m_pData->m_String + nIndex, m_pData->m_String + mLength, - nCharsToCopy); - m_pData->m_nDataLength = nOldLength - nCount; - } - return m_pData->m_nDataLength; -} - -void CFX_ByteString::Concat(const FX_CHAR* pSrcData, FX_STRSIZE nSrcLen) { - if (!pSrcData || nSrcLen <= 0) - return; - - if (!m_pData) { - m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); - return; - } - - if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { - m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData->m_nDataLength += nSrcLen; - return; - } - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_nDataLength + nSrcLen)); - pNewData->CopyContents(*m_pData); - pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData.Swap(pNewData); -} - -CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst) const { - if (!m_pData) - return CFX_ByteString(); - - return Mid(nFirst, m_pData->m_nDataLength - nFirst); -} - -CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const { - if (!m_pData) - return CFX_ByteString(); - - nFirst = std::min(std::max(nFirst, 0), m_pData->m_nDataLength); - nCount = std::min(std::max(nCount, 0), m_pData->m_nDataLength - nFirst); - if (nCount == 0) - return CFX_ByteString(); - - if (nFirst == 0 && nCount == m_pData->m_nDataLength) - return *this; - - CFX_ByteString dest; - AllocCopy(dest, nCount, nFirst); - return dest; -} - -void CFX_ByteString::AllocCopy(CFX_ByteString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const { - if (nCopyLen <= 0) - return; - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); - dest.m_pData.Swap(pNewData); -} - -#define FORCE_ANSI 0x10000 -#define FORCE_UNICODE 0x20000 -#define FORCE_INT64 0x40000 - -CFX_ByteString CFX_ByteString::FormatInteger(int i, uint32_t flags) { - char buf[32]; - return CFX_ByteString(buf, Buffer_itoa(buf, i, flags)); -} - -void CFX_ByteString::FormatV(const FX_CHAR* pFormat, va_list argList) { - va_list argListSave; -#if defined(__ARMCC_VERSION) || \ - (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || \ - _FX_CPU_ == _FX_ARM64_)) || \ - defined(__native_client__) - va_copy(argListSave, argList); -#else - argListSave = argList; -#endif - int nMaxLen = 0; - for (const FX_CHAR* pStr = pFormat; *pStr != 0; pStr++) { - if (*pStr != '%' || *(pStr = pStr + 1) == '%') { - nMaxLen += FXSYS_strlen(pStr); - continue; - } - int nItemLen = 0; - int nWidth = 0; - for (; *pStr != 0; pStr++) { - if (*pStr == '#') { - nMaxLen += 2; - } else if (*pStr == '*') { - nWidth = va_arg(argList, int); - } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') { - break; - } - } - if (nWidth == 0) { - nWidth = FXSYS_atoi(pStr); - while (std::isdigit(*pStr)) - pStr++; - } - if (nWidth < 0 || nWidth > 128 * 1024) { - pFormat = "Bad width"; - nMaxLen = 10; - break; - } - int nPrecision = 0; - if (*pStr == '.') { - pStr++; - if (*pStr == '*') { - nPrecision = va_arg(argList, int); - pStr++; - } else { - nPrecision = FXSYS_atoi(pStr); - while (std::isdigit(*pStr)) - pStr++; - } - } - if (nPrecision < 0 || nPrecision > 128 * 1024) { - pFormat = "Bad precision"; - nMaxLen = 14; - break; - } - int nModifier = 0; - if (FXSYS_strncmp(pStr, "I64", 3) == 0) { - pStr += 3; - nModifier = FORCE_INT64; - } else { - switch (*pStr) { - case 'h': - nModifier = FORCE_ANSI; - pStr++; - break; - case 'l': - nModifier = FORCE_UNICODE; - pStr++; - break; - case 'F': - case 'N': - case 'L': - pStr++; - break; - } - } - switch (*pStr | nModifier) { - case 'c': - case 'C': - nItemLen = 2; - va_arg(argList, int); - break; - case 'c' | FORCE_ANSI: - case 'C' | FORCE_ANSI: - nItemLen = 2; - va_arg(argList, int); - break; - case 'c' | FORCE_UNICODE: - case 'C' | FORCE_UNICODE: - nItemLen = 2; - va_arg(argList, int); - break; - case 's': { - const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_strlen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 'S': { - FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_wcslen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 's' | FORCE_ANSI: - case 'S' | FORCE_ANSI: { - const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_strlen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 's' | FORCE_UNICODE: - case 'S' | FORCE_UNICODE: { - FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_wcslen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - } - if (nItemLen != 0) { - if (nPrecision != 0 && nItemLen > nPrecision) { - nItemLen = nPrecision; - } - if (nItemLen < nWidth) { - nItemLen = nWidth; - } - } else { - switch (*pStr) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - if (nModifier & FORCE_INT64) { - va_arg(argList, int64_t); - } else { - va_arg(argList, int); - } - nItemLen = 32; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'a': - case 'A': - case 'e': - case 'E': - case 'g': - case 'G': - va_arg(argList, double); - nItemLen = 128; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'f': - if (nWidth + nPrecision > 100) { - nItemLen = nPrecision + nWidth + 128; - } else { - char pszTemp[256]; - double f = va_arg(argList, double); - memset(pszTemp, 0, sizeof(pszTemp)); - FXSYS_snprintf(pszTemp, sizeof(pszTemp) - 1, "%*.*f", nWidth, - nPrecision + 6, f); - nItemLen = FXSYS_strlen(pszTemp); - } - break; - case 'p': - va_arg(argList, void*); - nItemLen = 32; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'n': - va_arg(argList, int*); - break; - } - } - nMaxLen += nItemLen; - } - nMaxLen += 32; // Fudge factor. - GetBuffer(nMaxLen); - if (m_pData) { - memset(m_pData->m_String, 0, nMaxLen); - FXSYS_vsnprintf(m_pData->m_String, nMaxLen - 1, pFormat, argListSave); - ReleaseBuffer(); - } - va_end(argListSave); -} - -void CFX_ByteString::Format(const FX_CHAR* pFormat, ...) { - va_list argList; - va_start(argList, pFormat); - FormatV(pFormat, argList); - va_end(argList); -} - -FX_STRSIZE CFX_ByteString::Insert(FX_STRSIZE nIndex, FX_CHAR ch) { - FX_STRSIZE nNewLength = m_pData ? m_pData->m_nDataLength : 0; - nIndex = std::max(nIndex, 0); - nIndex = std::min(nIndex, nNewLength); - nNewLength++; - - ReallocBeforeWrite(nNewLength); - FXSYS_memmove(m_pData->m_String + nIndex + 1, m_pData->m_String + nIndex, - nNewLength - nIndex); - m_pData->m_String[nIndex] = ch; - m_pData->m_nDataLength = nNewLength; - return nNewLength; -} - -CFX_ByteString CFX_ByteString::Right(FX_STRSIZE nCount) const { - if (!m_pData) - return CFX_ByteString(); - - nCount = std::max(nCount, 0); - if (nCount >= m_pData->m_nDataLength) - return *this; - - CFX_ByteString dest; - AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount); - return dest; -} - -CFX_ByteString CFX_ByteString::Left(FX_STRSIZE nCount) const { - if (!m_pData) - return CFX_ByteString(); - - nCount = std::max(nCount, 0); - if (nCount >= m_pData->m_nDataLength) - return *this; - - CFX_ByteString dest; - AllocCopy(dest, nCount, 0); - return dest; -} - -FX_STRSIZE CFX_ByteString::Find(FX_CHAR ch, FX_STRSIZE nStart) const { - if (!m_pData) - return -1; - - if (nStart < 0 || nStart >= m_pData->m_nDataLength) - return -1; - - const FX_CHAR* pStr = static_cast( - memchr(m_pData->m_String + nStart, ch, m_pData->m_nDataLength - nStart)); - return pStr ? pStr - m_pData->m_String : -1; -} - -FX_STRSIZE CFX_ByteString::ReverseFind(FX_CHAR ch) const { - if (!m_pData) - return -1; - - FX_STRSIZE nLength = m_pData->m_nDataLength; - while (nLength--) { - if (m_pData->m_String[nLength] == ch) - return nLength; - } - return -1; -} - -FX_STRSIZE CFX_ByteString::Find(const CFX_ByteStringC& pSub, - FX_STRSIZE nStart) const { - if (!m_pData) - return -1; - - FX_STRSIZE nLength = m_pData->m_nDataLength; - if (nStart > nLength) - return -1; - - const FX_CHAR* pStr = - FX_strstr(m_pData->m_String + nStart, m_pData->m_nDataLength - nStart, - pSub.c_str(), pSub.GetLength()); - return pStr ? (int)(pStr - m_pData->m_String) : -1; -} - -void CFX_ByteString::MakeLower() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_strlwr(m_pData->m_String); -} - -void CFX_ByteString::MakeUpper() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_strupr(m_pData->m_String); -} - -FX_STRSIZE CFX_ByteString::Remove(FX_CHAR chRemove) { - if (!m_pData || m_pData->m_nDataLength < 1) - return 0; - - FX_CHAR* pstrSource = m_pData->m_String; - FX_CHAR* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - while (pstrSource < pstrEnd) { - if (*pstrSource == chRemove) - break; - pstrSource++; - } - if (pstrSource == pstrEnd) - return 0; - - ptrdiff_t copied = pstrSource - m_pData->m_String; - ReallocBeforeWrite(m_pData->m_nDataLength); - pstrSource = m_pData->m_String + copied; - pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - - FX_CHAR* pstrDest = pstrSource; - while (pstrSource < pstrEnd) { - if (*pstrSource != chRemove) { - *pstrDest = *pstrSource; - pstrDest++; - } - pstrSource++; - } - - *pstrDest = 0; - FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest); - m_pData->m_nDataLength -= nCount; - return nCount; -} - -FX_STRSIZE CFX_ByteString::Replace(const CFX_ByteStringC& pOld, - const CFX_ByteStringC& pNew) { - if (!m_pData || pOld.IsEmpty()) - return 0; - - FX_STRSIZE nSourceLen = pOld.GetLength(); - FX_STRSIZE nReplacementLen = pNew.GetLength(); - FX_STRSIZE nCount = 0; - const FX_CHAR* pStart = m_pData->m_String; - FX_CHAR* pEnd = m_pData->m_String + m_pData->m_nDataLength; - while (1) { - const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart), - pOld.c_str(), nSourceLen); - if (!pTarget) - break; - - nCount++; - pStart = pTarget + nSourceLen; - } - if (nCount == 0) - return 0; - - FX_STRSIZE nNewLength = - m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; - - if (nNewLength == 0) { - clear(); - return nCount; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - pStart = m_pData->m_String; - FX_CHAR* pDest = pNewData->m_String; - for (FX_STRSIZE i = 0; i < nCount; i++) { - const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart), - pOld.c_str(), nSourceLen); - FXSYS_memcpy(pDest, pStart, pTarget - pStart); - pDest += pTarget - pStart; - FXSYS_memcpy(pDest, pNew.c_str(), pNew.GetLength()); - pDest += pNew.GetLength(); - pStart = pTarget + nSourceLen; - } - FXSYS_memcpy(pDest, pStart, pEnd - pStart); - m_pData.Swap(pNewData); - return nCount; -} - -void CFX_ByteString::SetAt(FX_STRSIZE nIndex, FX_CHAR ch) { - if (!m_pData) { - return; - } - ASSERT(nIndex >= 0); - ASSERT(nIndex < m_pData->m_nDataLength); - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[nIndex] = ch; -} - -CFX_WideString CFX_ByteString::UTF8Decode() const { - CFX_UTF8Decoder decoder; - for (FX_STRSIZE i = 0; i < GetLength(); i++) { - decoder.Input((uint8_t)m_pData->m_String[i]); - } - return CFX_WideString(decoder.GetResult()); -} - -// static -CFX_ByteString CFX_ByteString::FromUnicode(const FX_WCHAR* str, - FX_STRSIZE len) { - FX_STRSIZE str_len = len >= 0 ? len : FXSYS_wcslen(str); - return FromUnicode(CFX_WideString(str, str_len)); -} - -// static -CFX_ByteString CFX_ByteString::FromUnicode(const CFX_WideString& str) { - return CFX_CharMap::GetByteString(0, str.AsStringC()); -} - -int CFX_ByteString::Compare(const CFX_ByteStringC& str) const { - if (!m_pData) { - return str.IsEmpty() ? 0 : -1; - } - int this_len = m_pData->m_nDataLength; - int that_len = str.GetLength(); - int min_len = this_len < that_len ? this_len : that_len; - for (int i = 0; i < min_len; i++) { - if ((uint8_t)m_pData->m_String[i] < str.GetAt(i)) { - return -1; - } - if ((uint8_t)m_pData->m_String[i] > str.GetAt(i)) { - return 1; - } - } - if (this_len < that_len) { - return -1; - } - if (this_len > that_len) { - return 1; - } - return 0; -} - -void CFX_ByteString::TrimRight(const CFX_ByteStringC& pTargets) { - if (!m_pData || pTargets.IsEmpty()) { - return; - } - FX_STRSIZE pos = GetLength(); - if (pos < 1) { - return; - } - while (pos) { - FX_STRSIZE i = 0; - while (i < pTargets.GetLength() && - pTargets[i] != m_pData->m_String[pos - 1]) { - i++; - } - if (i == pTargets.GetLength()) { - break; - } - pos--; - } - if (pos < m_pData->m_nDataLength) { - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[pos] = 0; - m_pData->m_nDataLength = pos; - } -} - -void CFX_ByteString::TrimRight(FX_CHAR chTarget) { - TrimRight(CFX_ByteStringC(chTarget)); -} - -void CFX_ByteString::TrimRight() { - TrimRight("\x09\x0a\x0b\x0c\x0d\x20"); -} - -void CFX_ByteString::TrimLeft(const CFX_ByteStringC& pTargets) { - if (!m_pData || pTargets.IsEmpty()) - return; - - FX_STRSIZE len = GetLength(); - if (len < 1) - return; - - FX_STRSIZE pos = 0; - while (pos < len) { - FX_STRSIZE i = 0; - while (i < pTargets.GetLength() && pTargets[i] != m_pData->m_String[pos]) { - i++; - } - if (i == pTargets.GetLength()) { - break; - } - pos++; - } - if (pos) { - ReallocBeforeWrite(len); - FX_STRSIZE nDataLength = len - pos; - FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos, - (nDataLength + 1) * sizeof(FX_CHAR)); - m_pData->m_nDataLength = nDataLength; - } -} - -void CFX_ByteString::TrimLeft(FX_CHAR chTarget) { - TrimLeft(CFX_ByteStringC(chTarget)); -} - -void CFX_ByteString::TrimLeft() { - TrimLeft("\x09\x0a\x0b\x0c\x0d\x20"); -} - -uint32_t CFX_ByteString::GetID(FX_STRSIZE start_pos) const { - return AsStringC().GetID(start_pos); -} -FX_STRSIZE FX_ftoa(FX_FLOAT d, FX_CHAR* buf) { - buf[0] = '0'; - buf[1] = '\0'; - if (d == 0.0f) { - return 1; - } - bool bNegative = false; - if (d < 0) { - bNegative = true; - d = -d; - } - int scale = 1; - int scaled = FXSYS_round(d); - while (scaled < 100000) { - if (scale == 1000000) { - break; - } - scale *= 10; - scaled = FXSYS_round(d * scale); - } - if (scaled == 0) { - return 1; - } - char buf2[32]; - int buf_size = 0; - if (bNegative) { - buf[buf_size++] = '-'; - } - int i = scaled / scale; - FXSYS_itoa(i, buf2, 10); - FX_STRSIZE len = FXSYS_strlen(buf2); - FXSYS_memcpy(buf + buf_size, buf2, len); - buf_size += len; - int fraction = scaled % scale; - if (fraction == 0) { - return buf_size; - } - buf[buf_size++] = '.'; - scale /= 10; - while (fraction) { - buf[buf_size++] = '0' + fraction / scale; - fraction %= scale; - scale /= 10; - } - return buf_size; -} -CFX_ByteString CFX_ByteString::FormatFloat(FX_FLOAT d, int precision) { - FX_CHAR buf[32]; - FX_STRSIZE len = FX_ftoa(d, buf); - return CFX_ByteString(buf, len); -} diff --git a/core/fxcrt/fx_basic_bstring_unittest.cpp b/core/fxcrt/fx_basic_bstring_unittest.cpp deleted file mode 100644 index 503e68458ab8a1404ef3939fe9fd616b78c48b05..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_bstring_unittest.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/fxcrt/fx_string.h" -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fxcrt, ByteStringOperatorSubscript) { - // CFX_ByteString includes the NUL terminator for non-empty strings. - CFX_ByteString abc("abc"); - EXPECT_EQ('a', abc[0]); - EXPECT_EQ('b', abc[1]); - EXPECT_EQ('c', abc[2]); - EXPECT_EQ(0, abc[3]); -} - -TEST(fxcrt, ByteStringOperatorLT) { - CFX_ByteString empty; - CFX_ByteString a("a"); - CFX_ByteString abc("abc"); - CFX_ByteString def("def"); - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, ByteStringOperatorEQ) { - CFX_ByteString null_string; - EXPECT_TRUE(null_string == null_string); - - CFX_ByteString empty_string(""); - EXPECT_TRUE(empty_string == empty_string); - EXPECT_TRUE(empty_string == null_string); - EXPECT_TRUE(null_string == empty_string); - - CFX_ByteString deleted_string("hello"); - deleted_string.Delete(0, 5); - EXPECT_TRUE(deleted_string == deleted_string); - EXPECT_TRUE(deleted_string == null_string); - EXPECT_TRUE(deleted_string == empty_string); - EXPECT_TRUE(null_string == deleted_string); - EXPECT_TRUE(empty_string == deleted_string); - - CFX_ByteString byte_string("hello"); - EXPECT_TRUE(byte_string == byte_string); - EXPECT_FALSE(byte_string == null_string); - EXPECT_FALSE(byte_string == empty_string); - EXPECT_FALSE(byte_string == deleted_string); - EXPECT_FALSE(null_string == byte_string); - EXPECT_FALSE(empty_string == byte_string); - EXPECT_FALSE(deleted_string == byte_string); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_TRUE(byte_string == byte_string_same1); - EXPECT_TRUE(byte_string_same1 == byte_string); - - CFX_ByteString byte_string_same2(byte_string); - EXPECT_TRUE(byte_string == byte_string_same2); - EXPECT_TRUE(byte_string_same2 == byte_string); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_FALSE(byte_string == byte_string1); - EXPECT_FALSE(byte_string == byte_string2); - EXPECT_FALSE(byte_string == byte_string3); - EXPECT_FALSE(byte_string1 == byte_string); - EXPECT_FALSE(byte_string2 == byte_string); - EXPECT_FALSE(byte_string3 == byte_string); - - CFX_ByteStringC null_string_c; - CFX_ByteStringC empty_string_c(""); - EXPECT_TRUE(null_string == null_string_c); - EXPECT_TRUE(null_string == empty_string_c); - EXPECT_TRUE(empty_string == null_string_c); - EXPECT_TRUE(empty_string == empty_string_c); - EXPECT_TRUE(deleted_string == null_string_c); - EXPECT_TRUE(deleted_string == empty_string_c); - EXPECT_TRUE(null_string_c == null_string); - EXPECT_TRUE(empty_string_c == null_string); - EXPECT_TRUE(null_string_c == empty_string); - EXPECT_TRUE(empty_string_c == empty_string); - EXPECT_TRUE(null_string_c == deleted_string); - EXPECT_TRUE(empty_string_c == deleted_string); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_TRUE(byte_string == byte_string_c_same1); - EXPECT_TRUE(byte_string_c_same1 == byte_string); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_FALSE(byte_string == byte_string_c1); - EXPECT_FALSE(byte_string == byte_string_c2); - EXPECT_FALSE(byte_string == byte_string_c3); - EXPECT_FALSE(byte_string_c1 == byte_string); - EXPECT_FALSE(byte_string_c2 == byte_string); - EXPECT_FALSE(byte_string_c3 == byte_string); - - const char* c_null_string = nullptr; - const char* c_empty_string = ""; - EXPECT_TRUE(null_string == c_null_string); - EXPECT_TRUE(null_string == c_empty_string); - EXPECT_TRUE(empty_string == c_null_string); - EXPECT_TRUE(empty_string == c_empty_string); - EXPECT_TRUE(deleted_string == c_null_string); - EXPECT_TRUE(deleted_string == c_empty_string); - EXPECT_TRUE(c_null_string == null_string); - EXPECT_TRUE(c_empty_string == null_string); - EXPECT_TRUE(c_null_string == empty_string); - EXPECT_TRUE(c_empty_string == empty_string); - EXPECT_TRUE(c_null_string == deleted_string); - EXPECT_TRUE(c_empty_string == deleted_string); - - const char* c_string_same1 = "hello"; - EXPECT_TRUE(byte_string == c_string_same1); - EXPECT_TRUE(c_string_same1 == byte_string); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_FALSE(byte_string == c_string1); - EXPECT_FALSE(byte_string == c_string2); - EXPECT_FALSE(byte_string == c_string3); - EXPECT_FALSE(c_string1 == byte_string); - EXPECT_FALSE(c_string2 == byte_string); - EXPECT_FALSE(c_string3 == byte_string); -} - -TEST(fxcrt, ByteStringOperatorNE) { - CFX_ByteString null_string; - EXPECT_FALSE(null_string != null_string); - - CFX_ByteString empty_string(""); - EXPECT_FALSE(empty_string != empty_string); - EXPECT_FALSE(empty_string != null_string); - EXPECT_FALSE(null_string != empty_string); - - CFX_ByteString deleted_string("hello"); - deleted_string.Delete(0, 5); - EXPECT_FALSE(deleted_string != deleted_string); - EXPECT_FALSE(deleted_string != null_string); - EXPECT_FALSE(deleted_string != empty_string); - EXPECT_FALSE(deleted_string != deleted_string); - EXPECT_FALSE(null_string != deleted_string); - EXPECT_FALSE(empty_string != deleted_string); - EXPECT_FALSE(deleted_string != deleted_string); - - CFX_ByteString byte_string("hello"); - EXPECT_FALSE(byte_string != byte_string); - EXPECT_TRUE(byte_string != null_string); - EXPECT_TRUE(byte_string != empty_string); - EXPECT_TRUE(byte_string != deleted_string); - EXPECT_TRUE(null_string != byte_string); - EXPECT_TRUE(empty_string != byte_string); - EXPECT_TRUE(deleted_string != byte_string); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_FALSE(byte_string != byte_string_same1); - EXPECT_FALSE(byte_string_same1 != byte_string); - - CFX_ByteString byte_string_same2(byte_string); - EXPECT_FALSE(byte_string != byte_string_same2); - EXPECT_FALSE(byte_string_same2 != byte_string); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_TRUE(byte_string != byte_string1); - EXPECT_TRUE(byte_string != byte_string2); - EXPECT_TRUE(byte_string != byte_string3); - EXPECT_TRUE(byte_string1 != byte_string); - EXPECT_TRUE(byte_string2 != byte_string); - EXPECT_TRUE(byte_string3 != byte_string); - - CFX_ByteStringC null_string_c; - CFX_ByteStringC empty_string_c(""); - EXPECT_FALSE(null_string != null_string_c); - EXPECT_FALSE(null_string != empty_string_c); - EXPECT_FALSE(empty_string != null_string_c); - EXPECT_FALSE(empty_string != empty_string_c); - EXPECT_FALSE(null_string_c != null_string); - EXPECT_FALSE(empty_string_c != null_string); - EXPECT_FALSE(null_string_c != empty_string); - EXPECT_FALSE(empty_string_c != empty_string); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_FALSE(byte_string != byte_string_c_same1); - EXPECT_FALSE(byte_string_c_same1 != byte_string); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_TRUE(byte_string != byte_string_c1); - EXPECT_TRUE(byte_string != byte_string_c2); - EXPECT_TRUE(byte_string != byte_string_c3); - EXPECT_TRUE(byte_string_c1 != byte_string); - EXPECT_TRUE(byte_string_c2 != byte_string); - EXPECT_TRUE(byte_string_c3 != byte_string); - - const char* c_null_string = nullptr; - const char* c_empty_string = ""; - EXPECT_FALSE(null_string != c_null_string); - EXPECT_FALSE(null_string != c_empty_string); - EXPECT_FALSE(empty_string != c_null_string); - EXPECT_FALSE(empty_string != c_empty_string); - EXPECT_FALSE(deleted_string != c_null_string); - EXPECT_FALSE(deleted_string != c_empty_string); - EXPECT_FALSE(c_null_string != null_string); - EXPECT_FALSE(c_empty_string != null_string); - EXPECT_FALSE(c_null_string != empty_string); - EXPECT_FALSE(c_empty_string != empty_string); - EXPECT_FALSE(c_null_string != deleted_string); - EXPECT_FALSE(c_empty_string != deleted_string); - - const char* c_string_same1 = "hello"; - EXPECT_FALSE(byte_string != c_string_same1); - EXPECT_FALSE(c_string_same1 != byte_string); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_TRUE(byte_string != c_string1); - EXPECT_TRUE(byte_string != c_string2); - EXPECT_TRUE(byte_string != c_string3); - EXPECT_TRUE(c_string1 != byte_string); - EXPECT_TRUE(c_string2 != byte_string); - EXPECT_TRUE(c_string3 != byte_string); -} - -TEST(fxcrt, ByteStringCNull) { - CFX_ByteStringC null_string; - EXPECT_FALSE(null_string.raw_str()); - EXPECT_EQ(null_string.GetLength(), 0); - EXPECT_TRUE(null_string.IsEmpty()); - - CFX_ByteStringC another_null_string; - EXPECT_EQ(null_string, another_null_string); - - CFX_ByteStringC copied_null_string(null_string); - EXPECT_FALSE(copied_null_string.raw_str()); - EXPECT_EQ(copied_null_string.GetLength(), 0); - EXPECT_TRUE(copied_null_string.IsEmpty()); - EXPECT_EQ(null_string, copied_null_string); - - CFX_ByteStringC empty_string(""); // Pointer to NUL, not NULL pointer. - EXPECT_TRUE(empty_string.raw_str()); - EXPECT_EQ(empty_string.GetLength(), 0); - EXPECT_TRUE(empty_string.IsEmpty()); - EXPECT_EQ(null_string, empty_string); - - CFX_ByteStringC assigned_null_string("initially not nullptr"); - assigned_null_string = null_string; - EXPECT_FALSE(assigned_null_string.raw_str()); - EXPECT_EQ(assigned_null_string.GetLength(), 0); - EXPECT_TRUE(assigned_null_string.IsEmpty()); - EXPECT_EQ(null_string, assigned_null_string); - - CFX_ByteStringC assigned_nullptr_string("initially not nullptr"); - assigned_nullptr_string = (const FX_CHAR*)nullptr; - EXPECT_FALSE(assigned_nullptr_string.raw_str()); - EXPECT_EQ(assigned_nullptr_string.GetLength(), 0); - EXPECT_TRUE(assigned_nullptr_string.IsEmpty()); - EXPECT_EQ(null_string, assigned_nullptr_string); - - CFX_ByteStringC non_null_string("a"); - EXPECT_NE(null_string, non_null_string); -} - -TEST(fxcrt, ByteStringConcat) { - CFX_ByteString fred; - fred.Concat("FRED", 4); - EXPECT_EQ("FRED", fred); - - fred.Concat("DY", 2); - EXPECT_EQ("FREDDY", fred); - - fred.Delete(3, 3); - EXPECT_EQ("FRE", fred); - - fred.Concat("D", 1); - EXPECT_EQ("FRED", fred); - - CFX_ByteString copy = fred; - fred.Concat("DY", 2); - EXPECT_EQ("FREDDY", fred); - EXPECT_EQ("FRED", copy); - - // Test invalid arguments. - copy = fred; - fred.Concat("freddy", -6); - CFX_ByteString not_aliased("xxxxxx"); - EXPECT_EQ("FREDDY", fred); - EXPECT_EQ("xxxxxx", not_aliased); -} - -TEST(fxcrt, ByteStringRemove) { - CFX_ByteString freed("FREED"); - freed.Remove('E'); - EXPECT_EQ("FRD", freed); - freed.Remove('F'); - EXPECT_EQ("RD", freed); - freed.Remove('D'); - EXPECT_EQ("R", freed); - freed.Remove('X'); - EXPECT_EQ("R", freed); - freed.Remove('R'); - EXPECT_EQ("", freed); - - CFX_ByteString empty; - empty.Remove('X'); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringRemoveCopies) { - CFX_ByteString freed("FREED"); - const FX_CHAR* old_buffer = freed.c_str(); - - // No change with single reference - no copy. - freed.Remove('Q'); - EXPECT_EQ("FREED", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // Change with single reference - no copy. - freed.Remove('E'); - EXPECT_EQ("FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // No change with multiple references - no copy. - CFX_ByteString shared(freed); - freed.Remove('Q'); - EXPECT_EQ("FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - EXPECT_EQ(old_buffer, shared.c_str()); - - // Change with multiple references -- must copy. - freed.Remove('D'); - EXPECT_EQ("FR", freed); - EXPECT_NE(old_buffer, freed.c_str()); - EXPECT_EQ("FRD", shared); - EXPECT_EQ(old_buffer, shared.c_str()); -} - -TEST(fxcrt, ByteStringReplace) { - CFX_ByteString fred("FRED"); - fred.Replace("FR", "BL"); - EXPECT_EQ("BLED", fred); - fred.Replace("D", "DDY"); - EXPECT_EQ("BLEDDY", fred); - fred.Replace("LEDD", ""); - EXPECT_EQ("BY", fred); - fred.Replace("X", "CLAMS"); - EXPECT_EQ("BY", fred); - fred.Replace("BY", "HI"); - EXPECT_EQ("HI", fred); - fred.Replace("", "CLAMS"); - EXPECT_EQ("HI", fred); - fred.Replace("HI", ""); - EXPECT_EQ("", fred); -} - -TEST(fxcrt, ByteStringInsert) { - CFX_ByteString fred("FRED"); - fred.Insert(-1, 'X'); - EXPECT_EQ("XFRED", fred); - fred.Insert(0, 'S'); - EXPECT_EQ("SXFRED", fred); - fred.Insert(2, 'T'); - EXPECT_EQ("SXTFRED", fred); - fred.Insert(5, 'U'); - EXPECT_EQ("SXTFRUED", fred); - fred.Insert(8, 'V'); - EXPECT_EQ("SXTFRUEDV", fred); - fred.Insert(12, 'P'); - EXPECT_EQ("SXTFRUEDVP", fred); - { - CFX_ByteString empty; - empty.Insert(-1, 'X'); - EXPECT_EQ("X", empty); - } - { - CFX_ByteString empty; - empty.Insert(0, 'X'); - EXPECT_EQ("X", empty); - } - { - CFX_ByteString empty; - empty.Insert(5, 'X'); - EXPECT_EQ("X", empty); - } -} - -TEST(fxcrt, ByteStringDelete) { - CFX_ByteString fred("FRED"); - fred.Delete(0, 2); - EXPECT_EQ("ED", fred); - fred.Delete(1); - EXPECT_EQ("E", fred); - fred.Delete(-1); - EXPECT_EQ("", fred); - fred.Delete(1); - EXPECT_EQ("", fred); - - CFX_ByteString empty; - empty.Delete(0); - EXPECT_EQ("", empty); - empty.Delete(-1); - EXPECT_EQ("", empty); - empty.Delete(1); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringMid) { - CFX_ByteString fred("FRED"); - EXPECT_EQ("", fred.Mid(0, 0)); - EXPECT_EQ("", fred.Mid(3, 0)); - EXPECT_EQ("FRED", fred.Mid(0)); - EXPECT_EQ("RED", fred.Mid(1)); - EXPECT_EQ("ED", fred.Mid(2)); - EXPECT_EQ("D", fred.Mid(3)); - EXPECT_EQ("F", fred.Mid(0, 1)); - EXPECT_EQ("R", fred.Mid(1, 1)); - EXPECT_EQ("E", fred.Mid(2, 1)); - EXPECT_EQ("D", fred.Mid(3, 1)); - EXPECT_EQ("FR", fred.Mid(0, 2)); - EXPECT_EQ("FRED", fred.Mid(0, 4)); - EXPECT_EQ("FRED", fred.Mid(0, 10)); - - EXPECT_EQ("FR", fred.Mid(-1, 2)); - EXPECT_EQ("RED", fred.Mid(1, 4)); - EXPECT_EQ("", fred.Mid(4, 1)); - - CFX_ByteString empty; - EXPECT_EQ("", empty.Mid(0, 0)); - EXPECT_EQ("", empty.Mid(0)); - EXPECT_EQ("", empty.Mid(1)); - EXPECT_EQ("", empty.Mid(-1)); -} - -TEST(fxcrt, ByteStringLeft) { - CFX_ByteString fred("FRED"); - EXPECT_EQ("", fred.Left(0)); - EXPECT_EQ("F", fred.Left(1)); - EXPECT_EQ("FR", fred.Left(2)); - EXPECT_EQ("FRE", fred.Left(3)); - EXPECT_EQ("FRED", fred.Left(4)); - - EXPECT_EQ("FRED", fred.Left(5)); - EXPECT_EQ("", fred.Left(-1)); - - CFX_ByteString empty; - EXPECT_EQ("", empty.Left(0)); - EXPECT_EQ("", empty.Left(1)); - EXPECT_EQ("", empty.Left(-1)); -} - -TEST(fxcrt, ByteStringRight) { - CFX_ByteString fred("FRED"); - EXPECT_EQ("", fred.Right(0)); - EXPECT_EQ("D", fred.Right(1)); - EXPECT_EQ("ED", fred.Right(2)); - EXPECT_EQ("RED", fred.Right(3)); - EXPECT_EQ("FRED", fred.Right(4)); - - EXPECT_EQ("FRED", fred.Right(5)); - EXPECT_EQ("", fred.Right(-1)); - - CFX_ByteString empty; - EXPECT_EQ("", empty.Right(0)); - EXPECT_EQ("", empty.Right(1)); - EXPECT_EQ("", empty.Right(-1)); -} - -TEST(fxcrt, ByteStringUpperLower) { - CFX_ByteString fred("F-Re.42D"); - fred.MakeLower(); - EXPECT_EQ("f-re.42d", fred); - fred.MakeUpper(); - EXPECT_EQ("F-RE.42D", fred); - - CFX_ByteString empty; - empty.MakeLower(); - EXPECT_EQ("", empty); - empty.MakeUpper(); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringTrimRight) { - CFX_ByteString fred(" FRED "); - fred.TrimRight(); - EXPECT_EQ(" FRED", fred); - fred.TrimRight('E'); - EXPECT_EQ(" FRED", fred); - fred.TrimRight('D'); - EXPECT_EQ(" FRE", fred); - fred.TrimRight("ERP"); - EXPECT_EQ(" F", fred); - - CFX_ByteString blank(" "); - blank.TrimRight("ERP"); - EXPECT_EQ(" ", blank); - blank.TrimRight('E'); - EXPECT_EQ(" ", blank); - blank.TrimRight(); - EXPECT_EQ("", blank); - - CFX_ByteString empty; - empty.TrimRight("ERP"); - EXPECT_EQ("", empty); - empty.TrimRight('E'); - EXPECT_EQ("", empty); - empty.TrimRight(); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringTrimRightCopies) { - { - // With a single reference, no copy takes place. - CFX_ByteString fred(" FRED "); - const FX_CHAR* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(" FRED", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_ByteString fred(" FRED "); - CFX_ByteString other_fred = fred; - const FX_CHAR* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(" FRED", fred); - EXPECT_EQ(" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_ByteString fred("FRED"); - CFX_ByteString other_fred = fred; - const FX_CHAR* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ("FRED", fred); - EXPECT_EQ("FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, ByteStringTrimLeft) { - CFX_ByteString fred(" FRED "); - fred.TrimLeft(); - EXPECT_EQ("FRED ", fred); - fred.TrimLeft('E'); - EXPECT_EQ("FRED ", fred); - fred.TrimLeft('F'); - EXPECT_EQ("RED ", fred); - fred.TrimLeft("ERP"); - EXPECT_EQ("D ", fred); - - CFX_ByteString blank(" "); - blank.TrimLeft("ERP"); - EXPECT_EQ(" ", blank); - blank.TrimLeft('E'); - EXPECT_EQ(" ", blank); - blank.TrimLeft(); - EXPECT_EQ("", blank); - - CFX_ByteString empty; - empty.TrimLeft("ERP"); - EXPECT_EQ("", empty); - empty.TrimLeft('E'); - EXPECT_EQ("", empty); - empty.TrimLeft(); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringTrimLeftCopies) { - { - // With a single reference, no copy takes place. - CFX_ByteString fred(" FRED "); - const FX_CHAR* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ("FRED ", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_ByteString fred(" FRED "); - CFX_ByteString other_fred = fred; - const FX_CHAR* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ("FRED ", fred); - EXPECT_EQ(" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_ByteString fred("FRED"); - CFX_ByteString other_fred = fred; - const FX_CHAR* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ("FRED", fred); - EXPECT_EQ("FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, ByteStringReserve) { - { - CFX_ByteString str; - str.Reserve(6); - const FX_CHAR* old_buffer = str.c_str(); - str += "ABCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += "Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } - { - CFX_ByteString str("A"); - str.Reserve(6); - const FX_CHAR* old_buffer = str.c_str(); - str += "BCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += "Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } -} - -TEST(fxcrt, ByteStringGetBuffer) { - { - CFX_ByteString str; - FX_CHAR* buffer = str.GetBuffer(12); - // NOLINTNEXTLINE(runtime/printf) - strcpy(buffer, "clams"); - str.ReleaseBuffer(); - EXPECT_EQ("clams", str); - } - { - CFX_ByteString str("cl"); - FX_CHAR* buffer = str.GetBuffer(12); - // NOLINTNEXTLINE(runtime/printf) - strcpy(buffer + 2, "ams"); - str.ReleaseBuffer(); - EXPECT_EQ("clams", str); - } -} - -TEST(fxcrt, ByteStringReleaseBuffer) { - { - CFX_ByteString str; - str.Reserve(12); - str += "clams"; - const FX_CHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } - { - CFX_ByteString str("c"); - str.Reserve(12); - str += "lams"; - const FX_CHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } - { - CFX_ByteString str; - str.Reserve(200); - str += "clams"; - const FX_CHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } - { - CFX_ByteString str("c"); - str.Reserve(200); - str += "lams"; - const FX_CHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } -} - -TEST(fxcrt, ByteStringCNotNull) { - CFX_ByteStringC string3("abc"); - CFX_ByteStringC string6("abcdef"); - CFX_ByteStringC alternate_string3("abcdef", 3); - CFX_ByteStringC embedded_nul_string7("abc\0def", 7); - CFX_ByteStringC illegal_string7("abcdef", 7); - - EXPECT_EQ(3, string3.GetLength()); - EXPECT_EQ(6, string6.GetLength()); - EXPECT_EQ(3, alternate_string3.GetLength()); - EXPECT_EQ(7, embedded_nul_string7.GetLength()); - EXPECT_EQ(7, illegal_string7.GetLength()); - - EXPECT_NE(string3, string6); - EXPECT_EQ(string3, alternate_string3); - EXPECT_NE(string3, embedded_nul_string7); - EXPECT_NE(string3, illegal_string7); - EXPECT_NE(string6, alternate_string3); - EXPECT_NE(string6, embedded_nul_string7); - EXPECT_NE(string6, illegal_string7); - EXPECT_NE(alternate_string3, embedded_nul_string7); - EXPECT_NE(alternate_string3, illegal_string7); - EXPECT_NE(embedded_nul_string7, illegal_string7); - - CFX_ByteStringC copied_string3(string3); - CFX_ByteStringC copied_alternate_string3(alternate_string3); - CFX_ByteStringC copied_embedded_nul_string7(embedded_nul_string7); - - EXPECT_EQ(string3, copied_string3); - EXPECT_EQ(alternate_string3, copied_alternate_string3); - EXPECT_EQ(embedded_nul_string7, copied_embedded_nul_string7); - - CFX_ByteStringC assigned_string3("intially something else"); - CFX_ByteStringC assigned_alternate_string3("initally something else"); - CFX_ByteStringC assigned_ptr_string3("initially something else"); - CFX_ByteStringC assigned_embedded_nul_string7("initially something else"); - - assigned_string3 = string3; - assigned_alternate_string3 = alternate_string3; - assigned_ptr_string3 = "abc"; - assigned_embedded_nul_string7 = embedded_nul_string7; - EXPECT_EQ(string3, assigned_string3); - EXPECT_EQ(alternate_string3, assigned_alternate_string3); - EXPECT_EQ(alternate_string3, assigned_ptr_string3); - EXPECT_EQ(embedded_nul_string7, assigned_embedded_nul_string7); -} - -TEST(fxcrt, ByteStringCFromChar) { - CFX_ByteStringC null_string; - CFX_ByteStringC lower_a_string("a"); - - // Must have lvalues that outlive the corresponding ByteStringC. - char nul = '\0'; - char lower_a = 'a'; - CFX_ByteStringC nul_string_from_char(nul); - CFX_ByteStringC lower_a_string_from_char(lower_a); - - // Pointer to nul, not nullptr ptr, hence length 1 ... - EXPECT_EQ(1, nul_string_from_char.GetLength()); - EXPECT_NE(null_string, nul_string_from_char); - - EXPECT_EQ(1, lower_a_string_from_char.GetLength()); - EXPECT_EQ(lower_a_string, lower_a_string_from_char); - EXPECT_NE(nul_string_from_char, lower_a_string_from_char); - - CFX_ByteStringC longer_string("ab"); - EXPECT_NE(longer_string, lower_a_string_from_char); -} - -TEST(fxcrt, ByteStringCGetID) { - CFX_ByteStringC null_string; - EXPECT_EQ(0u, null_string.GetID()); - EXPECT_EQ(0u, null_string.GetID(1)); - EXPECT_EQ(0u, null_string.GetID(-1)); - EXPECT_EQ(0u, null_string.GetID(-1000000)); - - CFX_ByteStringC empty_string(""); - EXPECT_EQ(0u, empty_string.GetID()); - EXPECT_EQ(0u, empty_string.GetID(1)); - EXPECT_EQ(0u, empty_string.GetID(-1)); - EXPECT_EQ(0u, empty_string.GetID(-1000000)); - - CFX_ByteStringC short_string("ab"); - EXPECT_EQ(FXBSTR_ID('a', 'b', 0, 0), short_string.GetID()); - EXPECT_EQ(FXBSTR_ID('b', 0, 0, 0), short_string.GetID(1)); - EXPECT_EQ(0u, short_string.GetID(2)); - EXPECT_EQ(0u, short_string.GetID(-1)); - EXPECT_EQ(0u, short_string.GetID(-1000000)); - - CFX_ByteStringC longer_string("abcdef"); - EXPECT_EQ(FXBSTR_ID('a', 'b', 'c', 'd'), longer_string.GetID()); - EXPECT_EQ(FXBSTR_ID('b', 'c', 'd', 'e'), longer_string.GetID(1)); - EXPECT_EQ(FXBSTR_ID('c', 'd', 'e', 'f'), longer_string.GetID(2)); - EXPECT_EQ(FXBSTR_ID('d', 'e', 'f', 0), longer_string.GetID(3)); - EXPECT_EQ(FXBSTR_ID('e', 'f', 0, 0), longer_string.GetID(4)); - EXPECT_EQ(FXBSTR_ID('f', 0, 0, 0), longer_string.GetID(5)); - EXPECT_EQ(0u, longer_string.GetID(6)); - EXPECT_EQ(0u, longer_string.GetID(-1)); - EXPECT_EQ(0u, longer_string.GetID(-1000000)); -} - -TEST(fxcrt, ByteStringCFind) { - CFX_ByteStringC null_string; - EXPECT_EQ(-1, null_string.Find('a')); - EXPECT_EQ(-1, null_string.Find(0)); - - CFX_ByteStringC empty_string(""); - EXPECT_EQ(-1, empty_string.Find('a')); - EXPECT_EQ(-1, empty_string.Find(0)); - - CFX_ByteStringC single_string("a"); - EXPECT_EQ(0, single_string.Find('a')); - EXPECT_EQ(-1, single_string.Find('b')); - EXPECT_EQ(-1, single_string.Find(0)); - - CFX_ByteStringC longer_string("abccc"); - EXPECT_EQ(0, longer_string.Find('a')); - EXPECT_EQ(2, longer_string.Find('c')); - EXPECT_EQ(-1, longer_string.Find(0)); - - CFX_ByteStringC hibyte_string( - "ab\x8c" - "def"); - EXPECT_EQ(2, hibyte_string.Find('\x8c')); -} - -TEST(fxcrt, ByteStringCMid) { - CFX_ByteStringC null_string; - EXPECT_EQ(null_string, null_string.Mid(0, 1)); - EXPECT_EQ(null_string, null_string.Mid(1, 1)); - - CFX_ByteStringC empty_string(""); - EXPECT_EQ(empty_string, empty_string.Mid(0, 1)); - EXPECT_EQ(empty_string, empty_string.Mid(1, 1)); - - CFX_ByteStringC single_character("a"); - EXPECT_EQ(empty_string, single_character.Mid(0, 0)); - EXPECT_EQ(single_character, single_character.Mid(0, 1)); - EXPECT_EQ(empty_string, single_character.Mid(1, 0)); - EXPECT_EQ(empty_string, single_character.Mid(1, 1)); - - CFX_ByteStringC longer_string("abcdef"); - EXPECT_EQ(longer_string, longer_string.Mid(0, 6)); - EXPECT_EQ(longer_string, longer_string.Mid(0, 187)); - EXPECT_EQ(longer_string, longer_string.Mid(-42, 6)); - EXPECT_EQ(longer_string, longer_string.Mid(-42, 187)); - - CFX_ByteStringC leading_substring("ab"); - EXPECT_EQ(leading_substring, longer_string.Mid(0, 2)); - EXPECT_EQ(leading_substring, longer_string.Mid(-1, 2)); - - CFX_ByteStringC middle_substring("bcde"); - EXPECT_EQ(middle_substring, longer_string.Mid(1, 4)); - - CFX_ByteStringC trailing_substring("ef"); - EXPECT_EQ(trailing_substring, longer_string.Mid(4, 2)); - EXPECT_EQ(trailing_substring, longer_string.Mid(4, 3)); -} - -TEST(fxcrt, ByteStringCGetAt) { - CFX_ByteString short_string("a"); - CFX_ByteString longer_string("abc"); - CFX_ByteString embedded_nul_string("ab\0c", 4); - - EXPECT_EQ('a', short_string.GetAt(0)); - EXPECT_EQ('c', longer_string.GetAt(2)); - EXPECT_EQ('b', embedded_nul_string.GetAt(1)); - EXPECT_EQ('\0', embedded_nul_string.GetAt(2)); - EXPECT_EQ('c', embedded_nul_string.GetAt(3)); -} - -TEST(fxcrt, ByteStringCOperatorSubscript) { - // CFX_ByteStringC includes the NUL terminator for non-empty strings. - CFX_ByteStringC abc("abc"); - EXPECT_EQ('a', abc[0]); - EXPECT_EQ('b', abc[1]); - EXPECT_EQ('c', abc[2]); - EXPECT_EQ(0, abc[3]); -} - -TEST(fxcrt, ByteStringCOperatorLT) { - CFX_ByteStringC empty; - CFX_ByteStringC a("a"); - CFX_ByteStringC abc("abc"); - CFX_ByteStringC def("def"); - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, ByteStringCOperatorEQ) { - CFX_ByteStringC byte_string_c("hello"); - EXPECT_TRUE(byte_string_c == byte_string_c); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_TRUE(byte_string_c == byte_string_c_same1); - EXPECT_TRUE(byte_string_c_same1 == byte_string_c); - - CFX_ByteStringC byte_string_c_same2(byte_string_c); - EXPECT_TRUE(byte_string_c == byte_string_c_same2); - EXPECT_TRUE(byte_string_c_same2 == byte_string_c); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_FALSE(byte_string_c == byte_string_c1); - EXPECT_FALSE(byte_string_c == byte_string_c2); - EXPECT_FALSE(byte_string_c == byte_string_c3); - EXPECT_FALSE(byte_string_c1 == byte_string_c); - EXPECT_FALSE(byte_string_c2 == byte_string_c); - EXPECT_FALSE(byte_string_c3 == byte_string_c); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_TRUE(byte_string_c == byte_string_same1); - EXPECT_TRUE(byte_string_same1 == byte_string_c); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_FALSE(byte_string_c == byte_string1); - EXPECT_FALSE(byte_string_c == byte_string2); - EXPECT_FALSE(byte_string_c == byte_string3); - EXPECT_FALSE(byte_string1 == byte_string_c); - EXPECT_FALSE(byte_string2 == byte_string_c); - EXPECT_FALSE(byte_string3 == byte_string_c); - - const char* c_string_same1 = "hello"; - EXPECT_TRUE(byte_string_c == c_string_same1); - EXPECT_TRUE(c_string_same1 == byte_string_c); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_FALSE(byte_string_c == c_string1); - EXPECT_FALSE(byte_string_c == c_string2); - EXPECT_FALSE(byte_string_c == c_string3); - - EXPECT_FALSE(c_string1 == byte_string_c); - EXPECT_FALSE(c_string2 == byte_string_c); - EXPECT_FALSE(c_string3 == byte_string_c); -} - -TEST(fxcrt, ByteStringCOperatorNE) { - CFX_ByteStringC byte_string_c("hello"); - EXPECT_FALSE(byte_string_c != byte_string_c); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_FALSE(byte_string_c != byte_string_c_same1); - EXPECT_FALSE(byte_string_c_same1 != byte_string_c); - - CFX_ByteStringC byte_string_c_same2(byte_string_c); - EXPECT_FALSE(byte_string_c != byte_string_c_same2); - EXPECT_FALSE(byte_string_c_same2 != byte_string_c); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_TRUE(byte_string_c != byte_string_c1); - EXPECT_TRUE(byte_string_c != byte_string_c2); - EXPECT_TRUE(byte_string_c != byte_string_c3); - EXPECT_TRUE(byte_string_c1 != byte_string_c); - EXPECT_TRUE(byte_string_c2 != byte_string_c); - EXPECT_TRUE(byte_string_c3 != byte_string_c); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_FALSE(byte_string_c != byte_string_same1); - EXPECT_FALSE(byte_string_same1 != byte_string_c); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_TRUE(byte_string_c != byte_string1); - EXPECT_TRUE(byte_string_c != byte_string2); - EXPECT_TRUE(byte_string_c != byte_string3); - EXPECT_TRUE(byte_string1 != byte_string_c); - EXPECT_TRUE(byte_string2 != byte_string_c); - EXPECT_TRUE(byte_string3 != byte_string_c); - - const char* c_string_same1 = "hello"; - EXPECT_FALSE(byte_string_c != c_string_same1); - EXPECT_FALSE(c_string_same1 != byte_string_c); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_TRUE(byte_string_c != c_string1); - EXPECT_TRUE(byte_string_c != c_string2); - EXPECT_TRUE(byte_string_c != c_string3); - - EXPECT_TRUE(c_string1 != byte_string_c); - EXPECT_TRUE(c_string2 != byte_string_c); - EXPECT_TRUE(c_string3 != byte_string_c); -} - -TEST(fxcrt, ByteStringFormatWidth) { - { - CFX_ByteString str; - str.Format("%5d", 1); - EXPECT_EQ(" 1", str); - } - - { - CFX_ByteString str; - str.Format("%d", 1); - EXPECT_EQ("1", str); - } - - { - CFX_ByteString str; - str.Format("%*d", 5, 1); - EXPECT_EQ(" 1", str); - } - - { - CFX_ByteString str; - str.Format("%-1d", 1); - EXPECT_EQ("1", str); - } - - { - CFX_ByteString str; - str.Format("%0d", 1); - EXPECT_EQ("1", str); - } - - { - CFX_ByteString str; - str.Format("%1048576d", 1); - EXPECT_EQ("Bad width", str); - } -} - -TEST(fxcrt, ByteStringFormatPrecision) { - { - CFX_ByteString str; - str.Format("%.2f", 1.12345); - EXPECT_EQ("1.12", str); - } - - { - CFX_ByteString str; - str.Format("%.*f", 3, 1.12345); - EXPECT_EQ("1.123", str); - } - - { - CFX_ByteString str; - str.Format("%f", 1.12345); - EXPECT_EQ("1.123450", str); - } - - { - CFX_ByteString str; - str.Format("%-1f", 1.12345); - EXPECT_EQ("1.123450", str); - } - - { - CFX_ByteString str; - str.Format("%0f", 1.12345); - EXPECT_EQ("1.123450", str); - } - - { - CFX_ByteString str; - str.Format("%.1048576f", 1.2); - EXPECT_EQ("Bad precision", str); - } -} - -TEST(fxcrt, EmptyByteString) { - CFX_ByteString empty_str; - EXPECT_TRUE(empty_str.IsEmpty()); - EXPECT_EQ(0, empty_str.GetLength()); - const FX_CHAR* cstr = empty_str.c_str(); - EXPECT_EQ(0, FXSYS_strlen(cstr)); -} diff --git a/core/fxcrt/fx_basic_buffer.cpp b/core/fxcrt/fx_basic_buffer.cpp deleted file mode 100644 index 14a85c2ee5ed487e0afe7d584fce8c067ac54fb4..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_buffer.cpp +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include -#include -#include - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_safe_types.h" -#include "third_party/base/numerics/safe_conversions.h" - -CFX_BinaryBuf::CFX_BinaryBuf() - : m_AllocStep(0), m_AllocSize(0), m_DataSize(0) {} - -CFX_BinaryBuf::CFX_BinaryBuf(FX_STRSIZE size) - : m_AllocStep(0), m_AllocSize(size), m_DataSize(size) { - m_pBuffer.reset(FX_Alloc(uint8_t, size)); -} - -CFX_BinaryBuf::~CFX_BinaryBuf() {} - -void CFX_BinaryBuf::Delete(int start_index, int count) { - if (!m_pBuffer || start_index < 0 || count < 0 || count > m_DataSize || - start_index > m_DataSize - count) { - return; - } - FXSYS_memmove(m_pBuffer.get() + start_index, - m_pBuffer.get() + start_index + count, - m_DataSize - start_index - count); - m_DataSize -= count; -} - -void CFX_BinaryBuf::Clear() { - m_DataSize = 0; -} - -std::unique_ptr CFX_BinaryBuf::DetachBuffer() { - m_DataSize = 0; - m_AllocSize = 0; - return std::move(m_pBuffer); -} - -void CFX_BinaryBuf::EstimateSize(FX_STRSIZE size, FX_STRSIZE step) { - m_AllocStep = step; - if (m_AllocSize < size) - ExpandBuf(size - m_DataSize); -} - -void CFX_BinaryBuf::ExpandBuf(FX_STRSIZE add_size) { - FX_SAFE_STRSIZE new_size = m_DataSize; - new_size += add_size; - if (m_AllocSize >= new_size.ValueOrDie()) - return; - - int alloc_step = std::max(128, m_AllocStep ? m_AllocStep : m_AllocSize / 4); - new_size += alloc_step - 1; // Quantize, don't combine these lines. - new_size /= alloc_step; - new_size *= alloc_step; - m_AllocSize = new_size.ValueOrDie(); - m_pBuffer.reset(m_pBuffer - ? FX_Realloc(uint8_t, m_pBuffer.release(), m_AllocSize) - : FX_Alloc(uint8_t, m_AllocSize)); -} - -void CFX_BinaryBuf::AppendBlock(const void* pBuf, FX_STRSIZE size) { - if (size <= 0) - return; - - ExpandBuf(size); - if (pBuf) { - FXSYS_memcpy(m_pBuffer.get() + m_DataSize, pBuf, size); - } else { - FXSYS_memset(m_pBuffer.get() + m_DataSize, 0, size); - } - m_DataSize += size; -} - -void CFX_BinaryBuf::InsertBlock(FX_STRSIZE pos, - const void* pBuf, - FX_STRSIZE size) { - if (size <= 0) - return; - - ExpandBuf(size); - FXSYS_memmove(m_pBuffer.get() + pos + size, m_pBuffer.get() + pos, - m_DataSize - pos); - if (pBuf) { - FXSYS_memcpy(m_pBuffer.get() + pos, pBuf, size); - } else { - FXSYS_memset(m_pBuffer.get() + pos, 0, size); - } - m_DataSize += size; -} - -CFX_ByteTextBuf& CFX_ByteTextBuf::operator<<(const CFX_ByteStringC& lpsz) { - AppendBlock(lpsz.raw_str(), lpsz.GetLength()); - return *this; -} - -CFX_ByteTextBuf& CFX_ByteTextBuf::operator<<(int i) { - char buf[32]; - FXSYS_itoa(i, buf, 10); - AppendBlock(buf, FXSYS_strlen(buf)); - return *this; -} - -CFX_ByteTextBuf& CFX_ByteTextBuf::operator<<(uint32_t i) { - char buf[32]; - FXSYS_itoa(i, buf, 10); - AppendBlock(buf, FXSYS_strlen(buf)); - return *this; -} - -CFX_ByteTextBuf& CFX_ByteTextBuf::operator<<(double f) { - char buf[32]; - FX_STRSIZE len = FX_ftoa((FX_FLOAT)f, buf); - AppendBlock(buf, len); - return *this; -} - -CFX_ByteTextBuf& CFX_ByteTextBuf::operator<<(const CFX_ByteTextBuf& buf) { - AppendBlock(buf.m_pBuffer.get(), buf.m_DataSize); - return *this; -} - -void CFX_WideTextBuf::AppendChar(FX_WCHAR ch) { - ExpandBuf(sizeof(FX_WCHAR)); - *(FX_WCHAR*)(m_pBuffer.get() + m_DataSize) = ch; - m_DataSize += sizeof(FX_WCHAR); -} - -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const CFX_WideStringC& str) { - AppendBlock(str.c_str(), str.GetLength() * sizeof(FX_WCHAR)); - return *this; -} - -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const CFX_WideString& str) { - AppendBlock(str.c_str(), str.GetLength() * sizeof(FX_WCHAR)); - return *this; -} - -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(int i) { - char buf[32]; - FXSYS_itoa(i, buf, 10); - FX_STRSIZE len = FXSYS_strlen(buf); - ExpandBuf(len * sizeof(FX_WCHAR)); - FX_WCHAR* str = (FX_WCHAR*)(m_pBuffer.get() + m_DataSize); - for (FX_STRSIZE j = 0; j < len; j++) { - *str++ = buf[j]; - } - m_DataSize += len * sizeof(FX_WCHAR); - return *this; -} - -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(double f) { - char buf[32]; - FX_STRSIZE len = FX_ftoa((FX_FLOAT)f, buf); - ExpandBuf(len * sizeof(FX_WCHAR)); - FX_WCHAR* str = (FX_WCHAR*)(m_pBuffer.get() + m_DataSize); - for (FX_STRSIZE i = 0; i < len; i++) { - *str++ = buf[i]; - } - m_DataSize += len * sizeof(FX_WCHAR); - return *this; -} - -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const FX_WCHAR* lpsz) { - AppendBlock(lpsz, FXSYS_wcslen(lpsz) * sizeof(FX_WCHAR)); - return *this; -} - -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const CFX_WideTextBuf& buf) { - AppendBlock(buf.m_pBuffer.get(), buf.m_DataSize); - return *this; -} - -void CFX_BitStream::Init(const uint8_t* pData, uint32_t dwSize) { - m_pData = pData; - m_BitSize = dwSize * 8; - m_BitPos = 0; -} - -void CFX_BitStream::ByteAlign() { - m_BitPos = (m_BitPos + 7) & ~7; -} - -uint32_t CFX_BitStream::GetBits(uint32_t nBits) { - if (nBits > m_BitSize || m_BitPos + nBits > m_BitSize) - return 0; - - if (nBits == 1) { - int bit = (m_pData[m_BitPos / 8] & (1 << (7 - m_BitPos % 8))) ? 1 : 0; - m_BitPos++; - return bit; - } - - uint32_t byte_pos = m_BitPos / 8; - uint32_t bit_pos = m_BitPos % 8; - uint32_t bit_left = nBits; - uint32_t result = 0; - if (bit_pos) { - if (8 - bit_pos >= bit_left) { - result = - (m_pData[byte_pos] & (0xff >> bit_pos)) >> (8 - bit_pos - bit_left); - m_BitPos += bit_left; - return result; - } - bit_left -= 8 - bit_pos; - result = (m_pData[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left; - } - while (bit_left >= 8) { - bit_left -= 8; - result |= m_pData[byte_pos++] << bit_left; - } - if (bit_left) - result |= m_pData[byte_pos] >> (8 - bit_left); - m_BitPos += nBits; - return result; -} - -CFX_FileBufferArchive::CFX_FileBufferArchive() - : m_Length(0), m_pFile(nullptr) {} - -CFX_FileBufferArchive::~CFX_FileBufferArchive() {} - -void CFX_FileBufferArchive::Clear() { - m_Length = 0; - m_pBuffer.reset(); - m_pFile.Reset(); -} - -bool CFX_FileBufferArchive::Flush() { - size_t nRemaining = m_Length; - m_Length = 0; - if (!m_pFile) - return false; - if (!m_pBuffer || !nRemaining) - return true; - return m_pFile->WriteBlock(m_pBuffer.get(), nRemaining); -} - -int32_t CFX_FileBufferArchive::AppendBlock(const void* pBuf, size_t size) { - if (!pBuf || size < 1) - return 0; - - if (!m_pBuffer) - m_pBuffer.reset(FX_Alloc(uint8_t, kBufSize)); - - const uint8_t* buffer = reinterpret_cast(pBuf); - size_t temp_size = size; - while (temp_size) { - size_t buf_size = std::min(kBufSize - m_Length, temp_size); - FXSYS_memcpy(m_pBuffer.get() + m_Length, buffer, buf_size); - m_Length += buf_size; - if (m_Length == kBufSize) { - if (!Flush()) { - return -1; - } - } - temp_size -= buf_size; - buffer += buf_size; - } - return pdfium::base::checked_cast(size); -} - -int32_t CFX_FileBufferArchive::AppendByte(uint8_t byte) { - return AppendBlock(&byte, 1); -} - -int32_t CFX_FileBufferArchive::AppendDWord(uint32_t i) { - char buf[32]; - FXSYS_itoa(i, buf, 10); - return AppendBlock(buf, (size_t)FXSYS_strlen(buf)); -} - -int32_t CFX_FileBufferArchive::AppendString(const CFX_ByteStringC& lpsz) { - return AppendBlock(lpsz.raw_str(), lpsz.GetLength()); -} - -void CFX_FileBufferArchive::AttachFile( - const CFX_RetainPtr& pFile) { - ASSERT(pFile); - m_pFile = pFile; -} diff --git a/core/fxcrt/fx_basic_coords.cpp b/core/fxcrt/fx_basic_coords.cpp deleted file mode 100644 index cb5a010427131e72884684bfc4ac70f3763a9184..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_coords.cpp +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_ext.h" - -namespace { - -void MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int* i1, int* i2) { - int length = static_cast(FXSYS_ceil(f2 - f1)); - int i1_1 = static_cast(FXSYS_floor(f1)); - int i1_2 = static_cast(FXSYS_ceil(f1)); - FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length); - FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length); - - *i1 = (error1 > error2) ? i1_2 : i1_1; - *i2 = *i1 + length; -} - -} // namespace - -void FX_RECT::Normalize() { - if (left > right) { - int temp = left; - left = right; - right = temp; - } - if (top > bottom) { - int temp = top; - top = bottom; - bottom = temp; - } -} -void FX_RECT::Intersect(const FX_RECT& src) { - FX_RECT src_n = src; - src_n.Normalize(); - Normalize(); - left = left > src_n.left ? left : src_n.left; - top = top > src_n.top ? top : src_n.top; - right = right < src_n.right ? right : src_n.right; - bottom = bottom < src_n.bottom ? bottom : src_n.bottom; - if (left > right || top > bottom) { - left = top = right = bottom = 0; - } -} - -bool GetIntersection(FX_FLOAT low1, - FX_FLOAT high1, - FX_FLOAT low2, - FX_FLOAT high2, - FX_FLOAT& interlow, - FX_FLOAT& interhigh) { - if (low1 >= high2 || low2 >= high1) { - return false; - } - interlow = low1 > low2 ? low1 : low2; - interhigh = high1 > high2 ? high2 : high1; - return true; -} -extern "C" int FXSYS_round(FX_FLOAT d) { - if (d < (FX_FLOAT)INT_MIN) { - return INT_MIN; - } - if (d > (FX_FLOAT)INT_MAX) { - return INT_MAX; - } - - return (int)round(d); -} -CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect) { - left = (FX_FLOAT)(rect.left); - right = (FX_FLOAT)(rect.right); - bottom = (FX_FLOAT)(rect.top); - top = (FX_FLOAT)(rect.bottom); -} -void CFX_FloatRect::Normalize() { - FX_FLOAT temp; - if (left > right) { - temp = left; - left = right; - right = temp; - } - if (bottom > top) { - temp = top; - top = bottom; - bottom = temp; - } -} -void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect) { - Normalize(); - CFX_FloatRect other = other_rect; - other.Normalize(); - left = left > other.left ? left : other.left; - right = right < other.right ? right : other.right; - bottom = bottom > other.bottom ? bottom : other.bottom; - top = top < other.top ? top : other.top; - if (left > right || bottom > top) { - left = right = bottom = top = 0; - } -} -void CFX_FloatRect::Union(const CFX_FloatRect& other_rect) { - Normalize(); - CFX_FloatRect other = other_rect; - other.Normalize(); - left = left < other.left ? left : other.left; - right = right > other.right ? right : other.right; - bottom = bottom < other.bottom ? bottom : other.bottom; - top = top > other.top ? top : other.top; -} - -int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects) { - Normalize(); - s.Normalize(); - int nRects = 0; - CFX_FloatRect rects[4]; - if (left < s.left) { - rects[nRects].left = left; - rects[nRects].right = s.left; - rects[nRects].bottom = bottom; - rects[nRects].top = top; - nRects++; - } - if (s.left < right && s.top < top) { - rects[nRects].left = s.left; - rects[nRects].right = right; - rects[nRects].bottom = s.top; - rects[nRects].top = top; - nRects++; - } - if (s.top > bottom && s.right < right) { - rects[nRects].left = s.right; - rects[nRects].right = right; - rects[nRects].bottom = bottom; - rects[nRects].top = s.top; - nRects++; - } - if (s.bottom > bottom) { - rects[nRects].left = s.left; - rects[nRects].right = s.right; - rects[nRects].bottom = bottom; - rects[nRects].top = s.bottom; - nRects++; - } - if (nRects == 0) { - return 0; - } - for (int i = 0; i < nRects; i++) { - pRects[i] = rects[i]; - pRects[i].Intersect(*this); - } - return nRects; -} - -FX_RECT CFX_FloatRect::GetOuterRect() const { - CFX_FloatRect rect1 = *this; - FX_RECT rect; - rect.left = (int)FXSYS_floor(rect1.left); - rect.right = (int)FXSYS_ceil(rect1.right); - rect.top = (int)FXSYS_floor(rect1.bottom); - rect.bottom = (int)FXSYS_ceil(rect1.top); - rect.Normalize(); - return rect; -} - -FX_RECT CFX_FloatRect::GetInnerRect() const { - CFX_FloatRect rect1 = *this; - FX_RECT rect; - rect.left = (int)FXSYS_ceil(rect1.left); - rect.right = (int)FXSYS_floor(rect1.right); - rect.top = (int)FXSYS_ceil(rect1.bottom); - rect.bottom = (int)FXSYS_floor(rect1.top); - rect.Normalize(); - return rect; -} - -FX_RECT CFX_FloatRect::GetClosestRect() const { - CFX_FloatRect rect1 = *this; - FX_RECT rect; - MatchFloatRange(rect1.left, rect1.right, &rect.left, &rect.right); - MatchFloatRange(rect1.bottom, rect1.top, &rect.top, &rect.bottom); - rect.Normalize(); - return rect; -} - -bool CFX_FloatRect::Contains(const CFX_PointF& point) const { - CFX_FloatRect n1(*this); - n1.Normalize(); - return point.x <= n1.right && point.x >= n1.left && point.y <= n1.top && - point.y >= n1.bottom; -} - -bool CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const { - CFX_FloatRect n1(*this); - CFX_FloatRect n2(other_rect); - n1.Normalize(); - n2.Normalize(); - return n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && - n2.top <= n1.top; -} - -void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y) { - left = std::min(left, x); - right = std::max(right, x); - bottom = std::min(bottom, y); - top = std::max(top, y); -} - -CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_PointF* pPoints, int nPoints) { - if (nPoints == 0) - return CFX_FloatRect(); - - FX_FLOAT min_x = pPoints->x; - FX_FLOAT max_x = pPoints->x; - FX_FLOAT min_y = pPoints->y; - FX_FLOAT max_y = pPoints->y; - for (int i = 1; i < nPoints; i++) { - min_x = std::min(min_x, pPoints[i].x); - max_x = std::max(max_x, pPoints[i].x); - min_y = std::min(min_y, pPoints[i].y); - max_y = std::max(max_y, pPoints[i].y); - } - return CFX_FloatRect(min_x, min_y, max_x, max_y); -} - -void CFX_Matrix::SetReverse(const CFX_Matrix& m) { - FX_FLOAT i = m.a * m.d - m.b * m.c; - if (FXSYS_fabs(i) == 0) - return; - - FX_FLOAT j = -i; - a = m.d / i; - b = m.b / j; - c = m.c / j; - d = m.a / i; - e = (m.c * m.f - m.d * m.e) / i; - f = (m.a * m.f - m.b * m.e) / j; -} - -void CFX_Matrix::Concat(const CFX_Matrix& m, bool bPrepended) { - ConcatInternal(m, bPrepended); -} - -void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, bool bPrepended) { - CFX_Matrix m; - m.SetReverse(src); - Concat(m, bPrepended); -} - -bool CFX_Matrix::Is90Rotated() const { - return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) && - FXSYS_fabs(d * 1000) < FXSYS_fabs(c); -} - -bool CFX_Matrix::IsScaled() const { - return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) && - FXSYS_fabs(c * 1000) < FXSYS_fabs(d); -} - -void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, bool bPrepended) { - if (bPrepended) { - e += x * a + y * c; - f += y * d + x * b; - return; - } - e += x; - f += y; -} - -void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, bool bPrepended) { - a *= sx; - d *= sy; - if (bPrepended) { - b *= sx; - c *= sy; - return; - } - - b *= sy; - c *= sx; - e *= sx; - f *= sy; -} - -void CFX_Matrix::Rotate(FX_FLOAT fRadian, bool bPrepended) { - FX_FLOAT cosValue = FXSYS_cos(fRadian); - FX_FLOAT sinValue = FXSYS_sin(fRadian); - ConcatInternal(CFX_Matrix(cosValue, sinValue, -sinValue, cosValue, 0, 0), - bPrepended); -} - -void CFX_Matrix::RotateAt(FX_FLOAT fRadian, - FX_FLOAT dx, - FX_FLOAT dy, - bool bPrepended) { - Translate(dx, dy, bPrepended); - Rotate(fRadian, bPrepended); - Translate(-dx, -dy, bPrepended); -} - -void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian, - FX_FLOAT fBetaRadian, - bool bPrepended) { - ConcatInternal( - CFX_Matrix(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0), - bPrepended); -} - -void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, - const CFX_FloatRect& src) { - FX_FLOAT fDiff = src.left - src.right; - a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff; - - fDiff = src.bottom - src.top; - d = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff; - e = dest.left - src.left * a; - f = dest.bottom - src.bottom * d; - b = 0; - c = 0; -} - -FX_FLOAT CFX_Matrix::GetXUnit() const { - if (b == 0) - return (a > 0 ? a : -a); - if (a == 0) - return (b > 0 ? b : -b); - return FXSYS_sqrt(a * a + b * b); -} - -FX_FLOAT CFX_Matrix::GetYUnit() const { - if (c == 0) - return (d > 0 ? d : -d); - if (d == 0) - return (c > 0 ? c : -c); - return FXSYS_sqrt(c * c + d * d); -} - -CFX_FloatRect CFX_Matrix::GetUnitRect() const { - CFX_FloatRect rect(0, 0, 1, 1); - TransformRect(rect); - return rect; -} - -FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const { - FX_FLOAT fx = a * dx; - FX_FLOAT fy = b * dx; - return FXSYS_sqrt(fx * fx + fy * fy); -} - -FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const { - FX_FLOAT fx = a * dx + c * dy; - FX_FLOAT fy = b * dx + d * dy; - return FXSYS_sqrt(fx * fx + fy * fy); -} - -FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const { - return distance * (GetXUnit() + GetYUnit()) / 2; -} - -CFX_PointF CFX_Matrix::Transform(const CFX_PointF& point) const { - return CFX_PointF(a * point.x + c * point.y + e, - b * point.x + d * point.y + f); -} - -void CFX_Matrix::TransformRect(CFX_RectF& rect) const { - FX_FLOAT right = rect.right(), bottom = rect.bottom(); - TransformRect(rect.left, right, bottom, rect.top); - rect.width = right - rect.left; - rect.height = bottom - rect.top; -} - -void CFX_Matrix::TransformRect(FX_FLOAT& left, - FX_FLOAT& right, - FX_FLOAT& top, - FX_FLOAT& bottom) const { - CFX_PointF points[] = { - {left, top}, {left, bottom}, {right, top}, {right, bottom}}; - for (int i = 0; i < 4; i++) - points[i] = Transform(points[i]); - - right = points[0].x; - left = points[0].x; - top = points[0].y; - bottom = points[0].y; - for (int i = 1; i < 4; i++) { - right = std::max(right, points[i].x); - left = std::min(left, points[i].x); - top = std::max(top, points[i].y); - bottom = std::min(bottom, points[i].y); - } -} - -void CFX_Matrix::ConcatInternal(const CFX_Matrix& other, bool prepend) { - CFX_Matrix left; - CFX_Matrix right; - if (prepend) { - left = other; - right = *this; - } else { - left = *this; - right = other; - } - - a = left.a * right.a + left.b * right.c; - b = left.a * right.b + left.b * right.d; - c = left.c * right.a + left.d * right.c; - d = left.c * right.b + left.d * right.d; - e = left.e * right.a + left.f * right.c + right.e; - f = left.e * right.b + left.f * right.d + right.f; -} diff --git a/core/fxcrt/fx_basic_gcc.cpp b/core/fxcrt/fx_basic_gcc.cpp deleted file mode 100644 index 42fb2a17f7a7426c83c4551b8f4424e44bbae819..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_gcc.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include -#include - -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_string.h" - -template -IntType FXSYS_StrToInt(const CharType* str) { - if (!str) - return 0; - - // Process the sign. - bool neg = *str == '-'; - if (neg || *str == '+') - str++; - - IntType num = 0; - while (*str && FXSYS_isDecimalDigit(*str)) { - IntType val = FXSYS_toDecimalDigit(*str); - if (num > (std::numeric_limits::max() - val) / 10) { - if (neg && std::numeric_limits::is_signed) { - // Return MIN when the represented number is signed type and is smaller - // than the min value. - return std::numeric_limits::min(); - } else { - // Return MAX when the represented number is signed type and is larger - // than the max value, or the number is unsigned type and out of range. - return std::numeric_limits::max(); - } - } - - num = num * 10 + val; - str++; - } - // When it is a negative value, -num should be returned. Since num may be of - // unsigned type, use ~num + 1 to avoid the warning of applying unary minus - // operator to unsigned type. - return neg ? ~num + 1 : num; -} - -template -STR_T FXSYS_IntToStr(T value, STR_T str, int radix) { - if (radix < 2 || radix > 16) { - str[0] = 0; - return str; - } - if (value == 0) { - str[0] = '0'; - str[1] = 0; - return str; - } - int i = 0; - UT uvalue; - if (value < 0) { - str[i++] = '-'; - // Standard trick to avoid undefined behaviour when negating INT_MIN. - uvalue = static_cast(-(value + 1)) + 1; - } else { - uvalue = value; - } - int digits = 1; - T order = uvalue / radix; - while (order > 0) { - digits++; - order = order / radix; - } - for (int d = digits - 1; d > -1; d--) { - str[d + i] = "0123456789abcdef"[uvalue % radix]; - uvalue /= radix; - } - str[digits + i] = 0; - return str; -} - -#ifdef __cplusplus -extern "C" { -#endif -int32_t FXSYS_atoi(const FX_CHAR* str) { - return FXSYS_StrToInt(str); -} -uint32_t FXSYS_atoui(const FX_CHAR* str) { - return FXSYS_StrToInt(str); -} -int32_t FXSYS_wtoi(const FX_WCHAR* str) { - return FXSYS_StrToInt(str); -} -int64_t FXSYS_atoi64(const FX_CHAR* str) { - return FXSYS_StrToInt(str); -} -int64_t FXSYS_wtoi64(const FX_WCHAR* str) { - return FXSYS_StrToInt(str); -} -const FX_CHAR* FXSYS_i64toa(int64_t value, FX_CHAR* str, int radix) { - return FXSYS_IntToStr(value, str, radix); -} -#ifdef __cplusplus -} -#endif -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ -#ifdef __cplusplus -extern "C" { -#endif -int FXSYS_GetACP() { - return 0; -} -uint32_t FXSYS_GetFullPathName(const FX_CHAR* filename, - uint32_t buflen, - FX_CHAR* buf, - FX_CHAR** filepart) { - int srclen = FXSYS_strlen(filename); - if (!buf || (int)buflen < srclen + 1) { - return srclen + 1; - } - FXSYS_strcpy(buf, filename); - return srclen; -} -uint32_t FXSYS_GetModuleFileName(void* hModule, char* buf, uint32_t bufsize) { - return (uint32_t)-1; -} -#ifdef __cplusplus -} -#endif -#endif -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ -#ifdef __cplusplus -extern "C" { -#endif -FXSYS_FILE* FXSYS_wfopen(const FX_WCHAR* filename, const FX_WCHAR* mode) { - return FXSYS_fopen(CFX_ByteString::FromUnicode(filename).c_str(), - CFX_ByteString::FromUnicode(mode).c_str()); -} -char* FXSYS_strlwr(char* str) { - if (!str) { - return nullptr; - } - char* s = str; - while (*str) { - *str = FXSYS_tolower(*str); - str++; - } - return s; -} -char* FXSYS_strupr(char* str) { - if (!str) { - return nullptr; - } - char* s = str; - while (*str) { - *str = FXSYS_toupper(*str); - str++; - } - return s; -} -FX_WCHAR* FXSYS_wcslwr(FX_WCHAR* str) { - if (!str) { - return nullptr; - } - FX_WCHAR* s = str; - while (*str) { - *str = FXSYS_tolower(*str); - str++; - } - return s; -} -FX_WCHAR* FXSYS_wcsupr(FX_WCHAR* str) { - if (!str) { - return nullptr; - } - FX_WCHAR* s = str; - while (*str) { - *str = FXSYS_toupper(*str); - str++; - } - return s; -} -int FXSYS_stricmp(const char* dst, const char* src) { - int f, l; - do { - if (((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z')) { - f -= ('A' - 'a'); - } - if (((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z')) { - l -= ('A' - 'a'); - } - } while (f && (f == l)); - return (f - l); -} -int FXSYS_wcsicmp(const FX_WCHAR* dst, const FX_WCHAR* src) { - FX_WCHAR f, l; - do { - if (((f = (FX_WCHAR)(*(dst++))) >= 'A') && (f <= 'Z')) { - f -= ('A' - 'a'); - } - if (((l = (FX_WCHAR)(*(src++))) >= 'A') && (l <= 'Z')) { - l -= ('A' - 'a'); - } - } while (f && (f == l)); - return (f - l); -} -char* FXSYS_itoa(int value, char* str, int radix) { - return FXSYS_IntToStr(value, str, radix); -} -#ifdef __cplusplus -} -#endif -#endif -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ -#ifdef __cplusplus -extern "C" { -#endif -int FXSYS_WideCharToMultiByte(uint32_t codepage, - uint32_t dwFlags, - const FX_WCHAR* wstr, - int wlen, - FX_CHAR* buf, - int buflen, - const FX_CHAR* default_str, - int* pUseDefault) { - int len = 0; - for (int i = 0; i < wlen; i++) { - if (wstr[i] < 0x100) { - if (buf && len < buflen) - buf[len] = static_cast(wstr[i]); - len++; - } - } - return len; -} -int FXSYS_MultiByteToWideChar(uint32_t codepage, - uint32_t dwFlags, - const FX_CHAR* bstr, - int blen, - FX_WCHAR* buf, - int buflen) { - int wlen = 0; - for (int i = 0; i < blen; i++) { - if (buf && wlen < buflen) { - buf[wlen] = bstr[i]; - } - wlen++; - } - return wlen; -} -#ifdef __cplusplus -} -#endif -#endif diff --git a/core/fxcrt/fx_basic_gcc_unittest.cpp b/core/fxcrt/fx_basic_gcc_unittest.cpp deleted file mode 100644 index 665eede9ffe3205d7a3c641a7fae087ed05bac89..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_gcc_unittest.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2016 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. - -#include "core/fxcrt/fx_system.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fxcrt, FXSYS_atoi) { - EXPECT_EQ(0, FXSYS_atoi("")); - EXPECT_EQ(0, FXSYS_atoi("0")); - EXPECT_EQ(-1, FXSYS_atoi("-1")); - EXPECT_EQ(2345, FXSYS_atoi("2345")); - EXPECT_EQ(-2147483647, FXSYS_atoi("-2147483647")); - // Handle the sign. - EXPECT_EQ(-2345, FXSYS_atoi("-2345")); - EXPECT_EQ(2345, FXSYS_atoi("+2345")); - // The max value. - EXPECT_EQ(2147483647, FXSYS_atoi("2147483647")); - // The min value. Written in -1 format to avoid "unary minus operator applied - // to unsigned type" warning. - EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483648")); - // With invalid char. - EXPECT_EQ(9, FXSYS_atoi("9x9")); - - // Out of range values. - EXPECT_EQ(2147483647, FXSYS_atoi("2147483623423412348")); - EXPECT_EQ(2147483647, FXSYS_atoi("2147483648")); - EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483650")); -} - -TEST(fxcrt, FXSYS_atoi64) { - EXPECT_EQ(0, FXSYS_atoi64("")); - EXPECT_EQ(0, FXSYS_atoi64("0")); - EXPECT_EQ(-1, FXSYS_atoi64("-1")); - EXPECT_EQ(2345, FXSYS_atoi64("2345")); - EXPECT_EQ(-9223372036854775807LL, FXSYS_atoi64("-9223372036854775807")); - // Handle the sign. - EXPECT_EQ(-2345, FXSYS_atoi64("-2345")); - EXPECT_EQ(2345, FXSYS_atoi64("+2345")); - // The max value. - EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775807")); - // The min value. Written in -1 format to avoid implicit unsigned warning. - EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775808")); - // With invalid char. - EXPECT_EQ(9, FXSYS_atoi64("9x9")); - - // Out of range values. - EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("922337203685471234123475807")); - EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775808")); - EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775810")); -} - -TEST(fxcrt, FXSYS_wtoi) { - EXPECT_EQ(0, FXSYS_wtoi(L"")); - EXPECT_EQ(0, FXSYS_wtoi(L"0")); - EXPECT_EQ(-1, FXSYS_wtoi(L"-1")); - EXPECT_EQ(2345, FXSYS_wtoi(L"2345")); - EXPECT_EQ(-2147483647, FXSYS_wtoi(L"-2147483647")); - // The max value. - EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483647")); - // The min value. - EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483648")); - EXPECT_EQ(9, FXSYS_wtoi64(L"9x9")); - - // Out of range values. - EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483623423412348")); - EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483648")); - EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483652")); -} - -TEST(fxcrt, FXSYS_wtoi64) { - EXPECT_EQ(0, FXSYS_wtoi64(L"")); - EXPECT_EQ(0, FXSYS_wtoi64(L"0")); - EXPECT_EQ(-1, FXSYS_wtoi64(L"-1")); - EXPECT_EQ(2345, FXSYS_wtoi64(L"2345")); - EXPECT_EQ(-9223372036854775807LL, FXSYS_wtoi64(L"-9223372036854775807")); - // Handle the sign. - EXPECT_EQ(-2345, FXSYS_wtoi64(L"-2345")); - EXPECT_EQ(2345, FXSYS_wtoi64(L"+2345")); - // The max value. - EXPECT_EQ(9223372036854775807LL, FXSYS_wtoi64(L"9223372036854775807")); - // The min value. - EXPECT_EQ(-9223372036854775807LL - 1LL, - FXSYS_wtoi64(L"-9223372036854775808")); - // With invalid char. - EXPECT_EQ(9, FXSYS_wtoi64(L"9x9")); - - // Out of range values. - EXPECT_EQ(9223372036854775807LL, - FXSYS_wtoi64(L"922337203685471234123475807")); - EXPECT_EQ(9223372036854775807LL, FXSYS_wtoi64(L"9223372036854775808")); - EXPECT_EQ(-9223372036854775807LL - 1LL, - FXSYS_wtoi64(L"-9223372036854775810")); -} - -TEST(fxcrt, FXSYS_atoui) { - EXPECT_EQ(0u, FXSYS_atoui("")); - EXPECT_EQ(0u, FXSYS_atoui("0")); - EXPECT_EQ(4294967295, FXSYS_atoui("-1")); - EXPECT_EQ(2345u, FXSYS_atoui("2345")); - // Handle the sign. - EXPECT_EQ(4294964951, FXSYS_atoui("-2345")); - EXPECT_EQ(2345u, FXSYS_atoui("+2345")); - // The max value. - EXPECT_EQ(4294967295, FXSYS_atoui("4294967295")); - EXPECT_EQ(9u, FXSYS_atoui("9x9")); - - // Out of range values. - EXPECT_EQ(4294967295, FXSYS_atoui("2147483623423412348")); - EXPECT_EQ(4294967295, FXSYS_atoui("4294967296")); - EXPECT_EQ(4294967295, FXSYS_atoui("-4294967345")); -} diff --git a/core/fxcrt/fx_basic_memmgr.cpp b/core/fxcrt/fx_basic_memmgr.cpp deleted file mode 100644 index 927b994b5ff62da16523fce2472aad672b3ecbe3..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_memmgr.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include // For abort(). - -#include "core/fxcrt/fx_memory.h" - -void* FXMEM_DefaultAlloc(size_t byte_size, int flags) { - return (void*)malloc(byte_size); -} -void* FXMEM_DefaultRealloc(void* pointer, size_t new_size, int flags) { - return realloc(pointer, new_size); -} -void FXMEM_DefaultFree(void* pointer, int flags) { - free(pointer); -} - -NEVER_INLINE void FX_OutOfMemoryTerminate() { - // Termimate cleanly if we can, else crash at a specific address (0xbd). - abort(); -#ifndef _WIN32 - reinterpret_cast(0xbd)(); -#endif -} diff --git a/core/fxcrt/fx_basic_memmgr_unittest.cpp b/core/fxcrt/fx_basic_memmgr_unittest.cpp deleted file mode 100644 index fdffd98f1978fbf1ca13097213315b22a1a639b6..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_memmgr_unittest.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2015 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. - -#include - -#include "core/fxcrt/fx_memory.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const size_t kMaxByteAlloc = std::numeric_limits::max(); -const size_t kMaxIntAlloc = kMaxByteAlloc / sizeof(int); -const size_t kOverflowIntAlloc = kMaxIntAlloc + 100; -const size_t kWidth = 640; -const size_t kOverflowIntAlloc2D = kMaxIntAlloc / kWidth + 10; - -} // namespace - -// TODO(tsepez): re-enable OOM tests if we can find a way to -// prevent it from hosing the bots. -TEST(fxcrt, DISABLED_FX_AllocOOM) { - EXPECT_DEATH_IF_SUPPORTED((void)FX_Alloc(int, kMaxIntAlloc), ""); - - int* ptr = FX_Alloc(int, 1); - EXPECT_TRUE(ptr); - EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kMaxIntAlloc), ""); - FX_Free(ptr); -} - -TEST(fxcrt, FX_AllocOverflow) { - // |ptr| needs to be defined and used to avoid Clang optimizes away the - // FX_Alloc() statement overzealously for optimized builds. - int* ptr = nullptr; - EXPECT_DEATH_IF_SUPPORTED(ptr = FX_Alloc(int, kOverflowIntAlloc), "") << ptr; - - ptr = FX_Alloc(int, 1); - EXPECT_TRUE(ptr); - EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kOverflowIntAlloc), ""); - FX_Free(ptr); -} - -TEST(fxcrt, FX_AllocOverflow2D) { - // |ptr| needs to be defined and used to avoid Clang optimizes away the - // FX_Alloc() statement overzealously for optimized builds. - int* ptr = nullptr; - EXPECT_DEATH_IF_SUPPORTED(ptr = FX_Alloc2D(int, kWidth, kOverflowIntAlloc2D), - "") - << ptr; -} - -TEST(fxcrt, DISABLED_FX_TryAllocOOM) { - EXPECT_FALSE(FX_TryAlloc(int, kMaxIntAlloc)); - - int* ptr = FX_Alloc(int, 1); - EXPECT_TRUE(ptr); - EXPECT_FALSE(FX_TryRealloc(int, ptr, kMaxIntAlloc)); - FX_Free(ptr); -} - -TEST(fxcrt, FX_TryAllocOverflow) { - // |ptr| needs to be defined and used to avoid Clang optimizes away the - // calloc() statement overzealously for optimized builds. - int* ptr = (int*)calloc(sizeof(int), kOverflowIntAlloc); - EXPECT_FALSE(ptr) << ptr; - - ptr = FX_Alloc(int, 1); - EXPECT_TRUE(ptr); - EXPECT_FALSE(FX_TryRealloc(int, ptr, kOverflowIntAlloc)); - FX_Free(ptr); -} - -TEST(fxcrt, DISABLED_FXMEM_DefaultOOM) { - EXPECT_FALSE(FXMEM_DefaultAlloc(kMaxByteAlloc, 0)); - - void* ptr = FXMEM_DefaultAlloc(1, 0); - EXPECT_TRUE(ptr); - EXPECT_FALSE(FXMEM_DefaultRealloc(ptr, kMaxByteAlloc, 0)); - FXMEM_DefaultFree(ptr, 0); -} diff --git a/core/fxcrt/fx_basic_utf.cpp b/core/fxcrt/fx_basic_utf.cpp deleted file mode 100644 index c0f14c81787cba7ace9f3e71a1c69b8fa5065e6d..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_utf.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fx_basic.h" - -void CFX_UTF8Decoder::Clear() { - m_Buffer.Clear(); - m_PendingBytes = 0; -} -void CFX_UTF8Decoder::AppendChar(uint32_t ch) { - m_Buffer.AppendChar((FX_WCHAR)ch); -} -void CFX_UTF8Decoder::Input(uint8_t byte) { - if (byte < 0x80) { - m_PendingBytes = 0; - m_Buffer.AppendChar(byte); - } else if (byte < 0xc0) { - if (m_PendingBytes == 0) { - return; - } - m_PendingBytes--; - m_PendingChar |= (byte & 0x3f) << (m_PendingBytes * 6); - if (m_PendingBytes == 0) { - AppendChar(m_PendingChar); - } - } else if (byte < 0xe0) { - m_PendingBytes = 1; - m_PendingChar = (byte & 0x1f) << 6; - } else if (byte < 0xf0) { - m_PendingBytes = 2; - m_PendingChar = (byte & 0x0f) << 12; - } else if (byte < 0xf8) { - m_PendingBytes = 3; - m_PendingChar = (byte & 0x07) << 18; - } else if (byte < 0xfc) { - m_PendingBytes = 4; - m_PendingChar = (byte & 0x03) << 24; - } else if (byte < 0xfe) { - m_PendingBytes = 5; - m_PendingChar = (byte & 0x01) << 30; - } -} -void CFX_UTF8Encoder::Input(FX_WCHAR unicode) { - if ((uint32_t)unicode < 0x80) { - m_Buffer.AppendChar(unicode); - } else { - if ((uint32_t)unicode >= 0x80000000) { - return; - } - int nbytes = 0; - if ((uint32_t)unicode < 0x800) { - nbytes = 2; - } else if ((uint32_t)unicode < 0x10000) { - nbytes = 3; - } else if ((uint32_t)unicode < 0x200000) { - nbytes = 4; - } else if ((uint32_t)unicode < 0x4000000) { - nbytes = 5; - } else { - nbytes = 6; - } - static uint8_t prefix[] = {0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; - int order = 1 << ((nbytes - 1) * 6); - int code = unicode; - m_Buffer.AppendChar(prefix[nbytes - 2] | (code / order)); - for (int i = 0; i < nbytes - 1; i++) { - code = code % order; - order >>= 6; - m_Buffer.AppendChar(0x80 | (code / order)); - } - } -} - -CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr) { - FX_STRSIZE len = wsStr.GetLength(); - const FX_WCHAR* pStr = wsStr.c_str(); - CFX_UTF8Encoder encoder; - while (len-- > 0) - encoder.Input(*pStr++); - - return CFX_ByteString(encoder.GetResult()); -} diff --git a/core/fxcrt/fx_basic_util.cpp b/core/fxcrt/fx_basic_util.cpp deleted file mode 100644 index f608e290a2a9236c93fa4cdd6a2da6206364bc44..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_util.cpp +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_ext.h" - -#include -#include -#include -#include - -bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { - if (strc.Find('.') != -1) { - FX_FLOAT* pFloat = static_cast(pData); - *pFloat = FX_atof(strc); - return false; - } - - // Note, numbers in PDF are typically of the form 123, -123, etc. But, - // for things like the Permissions on the encryption hash the number is - // actually an unsigned value. We use a uint32_t so we can deal with the - // unsigned and then check for overflow if the user actually signed the value. - // The Permissions flag is listed in Table 3.20 PDF 1.7 spec. - pdfium::base::CheckedNumeric integer = 0; - bool bNegative = false; - bool bSigned = false; - int cc = 0; - if (strc[0] == '+') { - cc++; - bSigned = true; - } else if (strc[0] == '-') { - bNegative = true; - bSigned = true; - cc++; - } - - while (cc < strc.GetLength() && std::isdigit(strc[cc])) { - integer = integer * 10 + FXSYS_toDecimalDigit(strc.CharAt(cc)); - if (!integer.IsValid()) - break; - cc++; - } - - // We have a sign, and the value was greater then a regular integer - // we've overflowed, reset to the default value. - if (bSigned) { - if (bNegative) { - if (integer.ValueOrDefault(0) > - static_cast(std::numeric_limits::max()) + 1) { - integer = 0; - } - } else if (integer.ValueOrDefault(0) > - static_cast(std::numeric_limits::max())) { - integer = 0; - } - } - - // Switch back to the int space so we can flip to a negative if we need. - uint32_t uValue = integer.ValueOrDefault(0); - int32_t value = static_cast(uValue); - if (bNegative) - value = -value; - - int* pInt = static_cast(pData); - *pInt = value; - return true; -} - -static const FX_FLOAT fraction_scales[] = { - 0.1f, 0.01f, 0.001f, 0.0001f, - 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, - 0.000000001f, 0.0000000001f, 0.00000000001f}; - -int FXSYS_FractionalScaleCount() { - return FX_ArraySize(fraction_scales); -} - -FX_FLOAT FXSYS_FractionalScale(size_t scale_factor, int value) { - return fraction_scales[scale_factor] * value; -} - -FX_FLOAT FX_atof(const CFX_ByteStringC& strc) { - if (strc.IsEmpty()) - return 0.0; - - int cc = 0; - bool bNegative = false; - int len = strc.GetLength(); - if (strc[0] == '+') { - cc++; - } else if (strc[0] == '-') { - bNegative = true; - cc++; - } - while (cc < len) { - if (strc[cc] != '+' && strc[cc] != '-') - break; - cc++; - } - FX_FLOAT value = 0; - while (cc < len) { - if (strc[cc] == '.') - break; - value = value * 10 + FXSYS_toDecimalDigit(strc.CharAt(cc)); - cc++; - } - int scale = 0; - if (cc < len && strc[cc] == '.') { - cc++; - while (cc < len) { - value += - FXSYS_FractionalScale(scale, FXSYS_toDecimalDigit(strc.CharAt(cc))); - scale++; - if (scale == FXSYS_FractionalScaleCount()) - break; - cc++; - } - } - return bNegative ? -value : value; -} - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 -void FXSYS_snprintf(char* str, - size_t size, - _Printf_format_string_ const char* fmt, - ...) { - va_list ap; - va_start(ap, fmt); - FXSYS_vsnprintf(str, size, fmt, ap); - va_end(ap); -} - -void FXSYS_vsnprintf(char* str, size_t size, const char* fmt, va_list ap) { - (void)_vsnprintf(str, size, fmt, ap); - if (size) - str[size - 1] = 0; -} -#endif // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 - -FX_FileHandle* FX_OpenFolder(const FX_CHAR* path) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - std::unique_ptr pData(new CFindFileDataA); - pData->m_Handle = FindFirstFileExA((CFX_ByteString(path) + "/*.*").c_str(), - FindExInfoStandard, &pData->m_FindData, - FindExSearchNameMatch, nullptr, 0); - if (pData->m_Handle == INVALID_HANDLE_VALUE) - return nullptr; - - pData->m_bEnd = false; - return pData.release(); -#else - return opendir(path); -#endif -} - -bool FX_GetNextFile(FX_FileHandle* handle, - CFX_ByteString* filename, - bool* bFolder) { - if (!handle) - return false; - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - if (handle->m_bEnd) - return false; - - *filename = handle->m_FindData.cFileName; - *bFolder = - (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - if (!FindNextFileA(handle->m_Handle, &handle->m_FindData)) - handle->m_bEnd = true; - return true; -#elif defined(__native_client__) - abort(); - return false; -#else - struct dirent* de = readdir(handle); - if (!de) - return false; - *filename = de->d_name; - *bFolder = de->d_type == DT_DIR; - return true; -#endif -} - -void FX_CloseFolder(FX_FileHandle* handle) { - if (!handle) - return; - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - FindClose(handle->m_Handle); - delete handle; -#else - closedir(handle); -#endif -} - -FX_WCHAR FX_GetFolderSeparator() { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - return '\\'; -#else - return '/'; -#endif -} - -CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() { - FX_FLOAT det = - a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g); - if (FXSYS_fabs(det) < 0.0000001) - return CFX_Matrix_3by3(); - - return CFX_Matrix_3by3( - (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det, - -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det, - (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det); -} - -CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3& m) { - return CFX_Matrix_3by3( - a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h, - a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g, - d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i, - g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h, - g * m.c + h * m.f + i * m.i); -} - -CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1& v) { - return CFX_Vector_3by1(a * v.a + b * v.b + c * v.c, - d * v.a + e * v.b + f * v.c, - g * v.a + h * v.b + i * v.c); -} - -uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits) { - ASSERT(0 < nbits && nbits <= 32); - const uint8_t* dataPtr = &pData[bitpos / 8]; - int bitShift; - int bitMask; - int dstShift; - int bitCount = bitpos & 0x07; - if (nbits < 8 && nbits + bitCount <= 8) { - bitShift = 8 - nbits - bitCount; - bitMask = (1 << nbits) - 1; - dstShift = 0; - } else { - bitShift = 0; - int bitOffset = 8 - bitCount; - bitMask = (1 << std::min(bitOffset, nbits)) - 1; - dstShift = nbits - bitOffset; - } - uint32_t result = - static_cast((*dataPtr++ >> bitShift & bitMask) << dstShift); - while (dstShift >= 8) { - dstShift -= 8; - result |= *dataPtr++ << dstShift; - } - if (dstShift > 0) { - bitShift = 8 - dstShift; - bitMask = (1 << dstShift) - 1; - result |= *dataPtr++ >> bitShift & bitMask; - } - return result; -} diff --git a/core/fxcrt/fx_basic_util_unittest.cpp b/core/fxcrt/fx_basic_util_unittest.cpp deleted file mode 100644 index 471c6deeb3f4853eba1f8e9678cf575edcfcb283..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_util_unittest.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2016 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. - -#include - -#include "core/fxcrt/fx_basic.h" -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -uint32_t ReferenceGetBits32(const uint8_t* pData, int bitpos, int nbits) { - int result = 0; - for (int i = 0; i < nbits; i++) { - if (pData[(bitpos + i) / 8] & (1 << (7 - (bitpos + i) % 8))) - result |= 1 << (nbits - i - 1); - } - return result; -} - -} // namespace - -TEST(fxge, GetBits32) { - unsigned char data[] = {0xDE, 0x3F, 0xB1, 0x7C, 0x12, 0x9A, 0x04, 0x56}; - for (int nbits = 1; nbits <= 32; ++nbits) { - for (int bitpos = 0; bitpos < (int)sizeof(data) * 8 - nbits; ++bitpos) { - EXPECT_EQ(ReferenceGetBits32(data, bitpos, nbits), - GetBits32(data, bitpos, nbits)); - } - } -} - -TEST(fxcrt, FX_atonum) { - int i; - EXPECT_TRUE(FX_atonum("10", &i)); - EXPECT_EQ(10, i); - - EXPECT_TRUE(FX_atonum("-10", &i)); - EXPECT_EQ(-10, i); - - EXPECT_TRUE(FX_atonum("+10", &i)); - EXPECT_EQ(10, i); - - EXPECT_TRUE(FX_atonum("-2147483648", &i)); - EXPECT_EQ(std::numeric_limits::min(), i); - - EXPECT_TRUE(FX_atonum("2147483647", &i)); - EXPECT_EQ(2147483647, i); - - // Value overflows. - EXPECT_TRUE(FX_atonum("-2147483649", &i)); - EXPECT_EQ(0, i); - - // Value overflows. - EXPECT_TRUE(FX_atonum("+2147483648", &i)); - EXPECT_EQ(0, i); - - // Value overflows. - EXPECT_TRUE(FX_atonum("4223423494965252", &i)); - EXPECT_EQ(0, i); - - // No explicit sign will allow the number to go negative. This is for things - // like the encryption Permissions flag (Table 3.20 PDF 1.7 spec) - EXPECT_TRUE(FX_atonum("4294965252", &i)); - EXPECT_EQ(-2044, i); - - EXPECT_TRUE(FX_atonum("-4294965252", &i)); - EXPECT_EQ(0, i); - - EXPECT_TRUE(FX_atonum("+4294965252", &i)); - EXPECT_EQ(0, i); - - float f; - EXPECT_FALSE(FX_atonum("3.24", &f)); - EXPECT_FLOAT_EQ(3.24f, f); -} diff --git a/core/fxcrt/fx_basic_wstring.cpp b/core/fxcrt/fx_basic_wstring.cpp deleted file mode 100644 index 93b9ba7c25a1b9a03bf0921b6a0fa1da31f0c045..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_wstring.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include -#include - -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/numerics/safe_math.h" - -template class CFX_StringDataTemplate; -template class CFX_StringCTemplate; -template class CFX_StringPoolTemplate; -template struct std::hash; - -namespace { - -#ifndef NDEBUG -bool IsValidCodePage(uint16_t codepage) { - switch (codepage) { - case 0: - case 932: - case 936: - case 949: - case 950: - return true; - - default: - return false; - } -} -#endif - -const FX_WCHAR* FX_wcsstr(const FX_WCHAR* haystack, - int haystack_len, - const FX_WCHAR* needle, - int needle_len) { - if (needle_len > haystack_len || needle_len == 0) { - return nullptr; - } - const FX_WCHAR* end_ptr = haystack + haystack_len - needle_len; - while (haystack <= end_ptr) { - int i = 0; - while (1) { - if (haystack[i] != needle[i]) { - break; - } - i++; - if (i == needle_len) { - return haystack; - } - } - haystack++; - } - return nullptr; -} - -} // namespace - -static_assert(sizeof(CFX_WideString) <= sizeof(FX_WCHAR*), - "Strings must not require more space than pointers"); - -CFX_WideString::CFX_WideString() {} - -CFX_WideString::CFX_WideString(const CFX_WideString& other) - : m_pData(other.m_pData) {} - -CFX_WideString::CFX_WideString(CFX_WideString&& other) { - m_pData.Swap(other.m_pData); -} - -CFX_WideString::CFX_WideString(const FX_WCHAR* pStr, FX_STRSIZE nLen) { - if (nLen < 0) - nLen = pStr ? FXSYS_wcslen(pStr) : 0; - - if (nLen) - m_pData.Reset(StringData::Create(pStr, nLen)); -} - -CFX_WideString::CFX_WideString(FX_WCHAR ch) { - m_pData.Reset(StringData::Create(1)); - m_pData->m_String[0] = ch; -} - -CFX_WideString::CFX_WideString(const FX_WCHAR* ptr) - : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) {} - -CFX_WideString::CFX_WideString(const CFX_WideStringC& stringSrc) { - if (!stringSrc.IsEmpty()) { - m_pData.Reset(StringData::Create(stringSrc.c_str(), stringSrc.GetLength())); - } -} - -CFX_WideString::CFX_WideString(const CFX_WideStringC& str1, - const CFX_WideStringC& str2) { - int nNewLen = str1.GetLength() + str2.GetLength(); - if (nNewLen == 0) - return; - - m_pData.Reset(StringData::Create(nNewLen)); - m_pData->CopyContents(str1.c_str(), str1.GetLength()); - m_pData->CopyContentsAt(str1.GetLength(), str2.c_str(), str2.GetLength()); -} - -CFX_WideString::~CFX_WideString() {} - -const CFX_WideString& CFX_WideString::operator=(const FX_WCHAR* pStr) { - if (!pStr || !pStr[0]) - clear(); - else - AssignCopy(pStr, FXSYS_wcslen(pStr)); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator=( - const CFX_WideStringC& stringSrc) { - if (stringSrc.IsEmpty()) - clear(); - else - AssignCopy(stringSrc.c_str(), stringSrc.GetLength()); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator=( - const CFX_WideString& stringSrc) { - if (m_pData != stringSrc.m_pData) - m_pData = stringSrc.m_pData; - - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(const FX_WCHAR* pStr) { - if (pStr) - Concat(pStr, FXSYS_wcslen(pStr)); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(FX_WCHAR ch) { - Concat(&ch, 1); - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(const CFX_WideString& str) { - if (str.m_pData) - Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(const CFX_WideStringC& str) { - if (!str.IsEmpty()) - Concat(str.c_str(), str.GetLength()); - - return *this; -} - -bool CFX_WideString::operator==(const wchar_t* ptr) const { - if (!m_pData) - return !ptr || !ptr[0]; - - if (!ptr) - return m_pData->m_nDataLength == 0; - - return wcslen(ptr) == static_cast(m_pData->m_nDataLength) && - wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; -} - -bool CFX_WideString::operator==(const CFX_WideStringC& str) const { - if (!m_pData) - return str.IsEmpty(); - - return m_pData->m_nDataLength == str.GetLength() && - wmemcmp(m_pData->m_String, str.c_str(), str.GetLength()) == 0; -} - -bool CFX_WideString::operator==(const CFX_WideString& other) const { - if (m_pData == other.m_pData) - return true; - - if (IsEmpty()) - return other.IsEmpty(); - - if (other.IsEmpty()) - return false; - - return other.m_pData->m_nDataLength == m_pData->m_nDataLength && - wmemcmp(other.m_pData->m_String, m_pData->m_String, - m_pData->m_nDataLength) == 0; -} - -bool CFX_WideString::operator<(const CFX_WideString& str) const { - if (m_pData == str.m_pData) - return false; - - int result = - wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); - return result < 0 || (result == 0 && GetLength() < str.GetLength()); -} - -void CFX_WideString::AssignCopy(const FX_WCHAR* pSrcData, FX_STRSIZE nSrcLen) { - AllocBeforeWrite(nSrcLen); - m_pData->CopyContents(pSrcData, nSrcLen); - m_pData->m_nDataLength = nSrcLen; -} - -void CFX_WideString::ReallocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength <= 0) { - clear(); - return; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - if (m_pData) { - FX_STRSIZE nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); - pNewData->CopyContents(m_pData->m_String, nCopyLength); - pNewData->m_nDataLength = nCopyLength; - } else { - pNewData->m_nDataLength = 0; - } - pNewData->m_String[pNewData->m_nDataLength] = 0; - m_pData.Swap(pNewData); -} - -void CFX_WideString::AllocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength <= 0) { - clear(); - return; - } - - m_pData.Reset(StringData::Create(nNewLength)); -} - -void CFX_WideString::ReleaseBuffer(FX_STRSIZE nNewLength) { - if (!m_pData) - return; - - if (nNewLength == -1) - nNewLength = FXSYS_wcslen(m_pData->m_String); - - nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); - if (nNewLength == 0) { - clear(); - return; - } - - ASSERT(m_pData->m_nRefs == 1); - m_pData->m_nDataLength = nNewLength; - m_pData->m_String[nNewLength] = 0; - if (m_pData->m_nAllocLength - nNewLength >= 32) { - // Over arbitrary threshold, so pay the price to relocate. Force copy to - // always occur by holding a second reference to the string. - CFX_WideString preserve(*this); - ReallocBeforeWrite(nNewLength); - } -} - -void CFX_WideString::Reserve(FX_STRSIZE len) { - GetBuffer(len); -} - -FX_WCHAR* CFX_WideString::GetBuffer(FX_STRSIZE nMinBufLength) { - if (!m_pData) { - if (nMinBufLength == 0) - return nullptr; - - m_pData.Reset(StringData::Create(nMinBufLength)); - m_pData->m_nDataLength = 0; - m_pData->m_String[0] = 0; - return m_pData->m_String; - } - - if (m_pData->CanOperateInPlace(nMinBufLength)) - return m_pData->m_String; - - nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); - if (nMinBufLength == 0) - return nullptr; - - CFX_RetainPtr pNewData(StringData::Create(nMinBufLength)); - pNewData->CopyContents(*m_pData); - pNewData->m_nDataLength = m_pData->m_nDataLength; - m_pData.Swap(pNewData); - return m_pData->m_String; -} - -FX_STRSIZE CFX_WideString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) { - if (!m_pData) - return 0; - - if (nIndex < 0) - nIndex = 0; - - FX_STRSIZE nOldLength = m_pData->m_nDataLength; - if (nCount > 0 && nIndex < nOldLength) { - FX_STRSIZE mLength = nIndex + nCount; - if (mLength >= nOldLength) { - m_pData->m_nDataLength = nIndex; - return m_pData->m_nDataLength; - } - ReallocBeforeWrite(nOldLength); - int nCharsToCopy = nOldLength - mLength + 1; - wmemmove(m_pData->m_String + nIndex, m_pData->m_String + mLength, - nCharsToCopy); - m_pData->m_nDataLength = nOldLength - nCount; - } - return m_pData->m_nDataLength; -} - -void CFX_WideString::Concat(const FX_WCHAR* pSrcData, FX_STRSIZE nSrcLen) { - if (!pSrcData || nSrcLen <= 0) - return; - - if (!m_pData) { - m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); - return; - } - - if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { - m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData->m_nDataLength += nSrcLen; - return; - } - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_nDataLength + nSrcLen)); - pNewData->CopyContents(*m_pData); - pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData.Swap(pNewData); -} - -CFX_ByteString CFX_WideString::UTF8Encode() const { - return FX_UTF8Encode(AsStringC()); -} - -CFX_ByteString CFX_WideString::UTF16LE_Encode() const { - if (!m_pData) { - return CFX_ByteString("\0\0", 2); - } - int len = m_pData->m_nDataLength; - CFX_ByteString result; - FX_CHAR* buffer = result.GetBuffer(len * 2 + 2); - for (int i = 0; i < len; i++) { - buffer[i * 2] = m_pData->m_String[i] & 0xff; - buffer[i * 2 + 1] = m_pData->m_String[i] >> 8; - } - buffer[len * 2] = 0; - buffer[len * 2 + 1] = 0; - result.ReleaseBuffer(len * 2 + 2); - return result; -} - -CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst) const { - if (!m_pData) - return CFX_WideString(); - - return Mid(nFirst, m_pData->m_nDataLength - nFirst); -} - -CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const { - if (!m_pData) - return CFX_WideString(); - - nFirst = std::min(std::max(nFirst, 0), m_pData->m_nDataLength); - nCount = std::min(std::max(nCount, 0), m_pData->m_nDataLength - nFirst); - if (nCount == 0) - return CFX_WideString(); - - if (nFirst == 0 && nCount == m_pData->m_nDataLength) - return *this; - - CFX_WideString dest; - AllocCopy(dest, nCount, nFirst); - return dest; -} - -void CFX_WideString::AllocCopy(CFX_WideString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const { - if (nCopyLen <= 0) - return; - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); - dest.m_pData.Swap(pNewData); -} - -#define FORCE_ANSI 0x10000 -#define FORCE_UNICODE 0x20000 -#define FORCE_INT64 0x40000 - -void CFX_WideString::FormatV(const FX_WCHAR* pFormat, va_list argList) { - va_list argListSave; -#if defined(__ARMCC_VERSION) || \ - (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || \ - _FX_CPU_ == _FX_ARM64_)) || \ - defined(__native_client__) - va_copy(argListSave, argList); -#else - argListSave = argList; -#endif - int nMaxLen = 0; - for (const FX_WCHAR* pStr = pFormat; *pStr != 0; pStr++) { - if (*pStr != '%' || *(pStr = pStr + 1) == '%') { - nMaxLen += FXSYS_wcslen(pStr); - continue; - } - int nItemLen = 0; - int nWidth = 0; - for (; *pStr != 0; pStr++) { - if (*pStr == '#') { - nMaxLen += 2; - } else if (*pStr == '*') { - nWidth = va_arg(argList, int); - } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') { - break; - } - } - if (nWidth == 0) { - nWidth = FXSYS_wtoi(pStr); - while (std::iswdigit(*pStr)) - ++pStr; - } - if (nWidth < 0 || nWidth > 128 * 1024) { - pFormat = L"Bad width"; - nMaxLen = 10; - break; - } - int nPrecision = 0; - if (*pStr == '.') { - pStr++; - if (*pStr == '*') { - nPrecision = va_arg(argList, int); - pStr++; - } else { - nPrecision = FXSYS_wtoi(pStr); - while (std::iswdigit(*pStr)) - ++pStr; - } - } - if (nPrecision < 0 || nPrecision > 128 * 1024) { - pFormat = L"Bad precision"; - nMaxLen = 14; - break; - } - int nModifier = 0; - if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') { - pStr += 3; - nModifier = FORCE_INT64; - } else { - switch (*pStr) { - case 'h': - nModifier = FORCE_ANSI; - pStr++; - break; - case 'l': - nModifier = FORCE_UNICODE; - pStr++; - break; - case 'F': - case 'N': - case 'L': - pStr++; - break; - } - } - switch (*pStr | nModifier) { - case 'c': - case 'C': - nItemLen = 2; - va_arg(argList, int); - break; - case 'c' | FORCE_ANSI: - case 'C' | FORCE_ANSI: - nItemLen = 2; - va_arg(argList, int); - break; - case 'c' | FORCE_UNICODE: - case 'C' | FORCE_UNICODE: - nItemLen = 2; - va_arg(argList, int); - break; - case 's': { - const FX_WCHAR* pstrNextArg = va_arg(argList, const FX_WCHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_wcslen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 'S': { - const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_strlen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 's' | FORCE_ANSI: - case 'S' | FORCE_ANSI: { - const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_strlen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 's' | FORCE_UNICODE: - case 'S' | FORCE_UNICODE: { - const FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); - if (pstrNextArg) { - nItemLen = FXSYS_wcslen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - } - if (nItemLen != 0) { - if (nPrecision != 0 && nItemLen > nPrecision) { - nItemLen = nPrecision; - } - if (nItemLen < nWidth) { - nItemLen = nWidth; - } - } else { - switch (*pStr) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - if (nModifier & FORCE_INT64) { - va_arg(argList, int64_t); - } else { - va_arg(argList, int); - } - nItemLen = 32; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'a': - case 'A': - case 'e': - case 'E': - case 'g': - case 'G': - va_arg(argList, double); - nItemLen = 128; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'f': - if (nWidth + nPrecision > 100) { - nItemLen = nPrecision + nWidth + 128; - } else { - double f; - char pszTemp[256]; - f = va_arg(argList, double); - FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, - nPrecision + 6, f); - nItemLen = FXSYS_strlen(pszTemp); - } - break; - case 'p': - va_arg(argList, void*); - nItemLen = 32; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'n': - va_arg(argList, int*); - break; - } - } - nMaxLen += nItemLen; - } - GetBuffer(nMaxLen); - if (m_pData) { - FXSYS_vswprintf((wchar_t*)m_pData->m_String, nMaxLen + 1, - (const wchar_t*)pFormat, argListSave); - ReleaseBuffer(); - } - va_end(argListSave); -} - -void CFX_WideString::Format(const FX_WCHAR* pFormat, ...) { - va_list argList; - va_start(argList, pFormat); - FormatV(pFormat, argList); - va_end(argList); -} - -FX_STRSIZE CFX_WideString::Insert(FX_STRSIZE nIndex, FX_WCHAR ch) { - FX_STRSIZE nNewLength = m_pData ? m_pData->m_nDataLength : 0; - nIndex = std::max(nIndex, 0); - nIndex = std::min(nIndex, nNewLength); - nNewLength++; - - ReallocBeforeWrite(nNewLength); - wmemmove(m_pData->m_String + nIndex + 1, m_pData->m_String + nIndex, - nNewLength - nIndex); - m_pData->m_String[nIndex] = ch; - m_pData->m_nDataLength = nNewLength; - return nNewLength; -} - -CFX_WideString CFX_WideString::Right(FX_STRSIZE nCount) const { - if (!m_pData) - return CFX_WideString(); - - nCount = std::max(nCount, 0); - if (nCount >= m_pData->m_nDataLength) - return *this; - - CFX_WideString dest; - AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount); - return dest; -} - -CFX_WideString CFX_WideString::Left(FX_STRSIZE nCount) const { - if (!m_pData) - return CFX_WideString(); - - nCount = std::max(nCount, 0); - if (nCount >= m_pData->m_nDataLength) - return *this; - - CFX_WideString dest; - AllocCopy(dest, nCount, 0); - return dest; -} - -FX_STRSIZE CFX_WideString::Find(FX_WCHAR ch, FX_STRSIZE nStart) const { - if (!m_pData) - return -1; - - if (nStart < 0 || nStart >= m_pData->m_nDataLength) - return -1; - - const FX_WCHAR* pStr = - wmemchr(m_pData->m_String + nStart, ch, m_pData->m_nDataLength - nStart); - return pStr ? pStr - m_pData->m_String : -1; -} - -FX_STRSIZE CFX_WideString::Find(const CFX_WideStringC& pSub, - FX_STRSIZE nStart) const { - if (!m_pData) - return -1; - - FX_STRSIZE nLength = m_pData->m_nDataLength; - if (nStart > nLength) - return -1; - - const FX_WCHAR* pStr = - FX_wcsstr(m_pData->m_String + nStart, m_pData->m_nDataLength - nStart, - pSub.c_str(), pSub.GetLength()); - return pStr ? (int)(pStr - m_pData->m_String) : -1; -} - -void CFX_WideString::MakeLower() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_wcslwr(m_pData->m_String); -} - -void CFX_WideString::MakeUpper() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_wcsupr(m_pData->m_String); -} - -FX_STRSIZE CFX_WideString::Remove(FX_WCHAR chRemove) { - if (!m_pData || m_pData->m_nDataLength < 1) - return 0; - - FX_WCHAR* pstrSource = m_pData->m_String; - FX_WCHAR* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - while (pstrSource < pstrEnd) { - if (*pstrSource == chRemove) - break; - pstrSource++; - } - if (pstrSource == pstrEnd) - return 0; - - ptrdiff_t copied = pstrSource - m_pData->m_String; - ReallocBeforeWrite(m_pData->m_nDataLength); - pstrSource = m_pData->m_String + copied; - pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - - FX_WCHAR* pstrDest = pstrSource; - while (pstrSource < pstrEnd) { - if (*pstrSource != chRemove) { - *pstrDest = *pstrSource; - pstrDest++; - } - pstrSource++; - } - - *pstrDest = 0; - FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest); - m_pData->m_nDataLength -= nCount; - return nCount; -} - -FX_STRSIZE CFX_WideString::Replace(const CFX_WideStringC& pOld, - const CFX_WideStringC& pNew) { - if (!m_pData || pOld.IsEmpty()) - return 0; - - FX_STRSIZE nSourceLen = pOld.GetLength(); - FX_STRSIZE nReplacementLen = pNew.GetLength(); - FX_STRSIZE nCount = 0; - const FX_WCHAR* pStart = m_pData->m_String; - FX_WCHAR* pEnd = m_pData->m_String + m_pData->m_nDataLength; - while (1) { - const FX_WCHAR* pTarget = FX_wcsstr(pStart, (FX_STRSIZE)(pEnd - pStart), - pOld.c_str(), nSourceLen); - if (!pTarget) - break; - - nCount++; - pStart = pTarget + nSourceLen; - } - if (nCount == 0) - return 0; - - FX_STRSIZE nNewLength = - m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; - - if (nNewLength == 0) { - clear(); - return nCount; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - pStart = m_pData->m_String; - FX_WCHAR* pDest = pNewData->m_String; - for (FX_STRSIZE i = 0; i < nCount; i++) { - const FX_WCHAR* pTarget = FX_wcsstr(pStart, (FX_STRSIZE)(pEnd - pStart), - pOld.c_str(), nSourceLen); - wmemcpy(pDest, pStart, pTarget - pStart); - pDest += pTarget - pStart; - wmemcpy(pDest, pNew.c_str(), pNew.GetLength()); - pDest += pNew.GetLength(); - pStart = pTarget + nSourceLen; - } - wmemcpy(pDest, pStart, pEnd - pStart); - m_pData.Swap(pNewData); - return nCount; -} - -void CFX_WideString::SetAt(FX_STRSIZE nIndex, FX_WCHAR ch) { - if (!m_pData) { - return; - } - ASSERT(nIndex >= 0); - ASSERT(nIndex < m_pData->m_nDataLength); - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[nIndex] = ch; -} - -// static -CFX_WideString CFX_WideString::FromLocal(const CFX_ByteStringC& str) { - return FromCodePage(str, 0); -} - -// static -CFX_WideString CFX_WideString::FromCodePage(const CFX_ByteStringC& str, - uint16_t codepage) { - return CFX_CharMap::GetWideString(codepage, str); -} - -// static -CFX_WideString CFX_WideString::FromUTF8(const CFX_ByteStringC& str) { - if (str.IsEmpty()) - return CFX_WideString(); - - CFX_UTF8Decoder decoder; - for (FX_STRSIZE i = 0; i < str.GetLength(); i++) - decoder.Input(str[i]); - - return CFX_WideString(decoder.GetResult()); -} - -// static -CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, - FX_STRSIZE wlen) { - if (!wstr || 0 == wlen) { - return CFX_WideString(); - } - - CFX_WideString result; - FX_WCHAR* buf = result.GetBuffer(wlen); - for (int i = 0; i < wlen; i++) { - buf[i] = wstr[i]; - } - result.ReleaseBuffer(wlen); - return result; -} - -int CFX_WideString::Compare(const FX_WCHAR* lpsz) const { - if (m_pData) - return FXSYS_wcscmp(m_pData->m_String, lpsz); - return (!lpsz || lpsz[0] == 0) ? 0 : -1; -} - -int CFX_WideString::Compare(const CFX_WideString& str) const { - if (!m_pData) { - if (!str.m_pData) { - return 0; - } - return -1; - } - if (!str.m_pData) { - return 1; - } - int this_len = m_pData->m_nDataLength; - int that_len = str.m_pData->m_nDataLength; - int min_len = this_len < that_len ? this_len : that_len; - for (int i = 0; i < min_len; i++) { - if (m_pData->m_String[i] < str.m_pData->m_String[i]) { - return -1; - } - if (m_pData->m_String[i] > str.m_pData->m_String[i]) { - return 1; - } - } - if (this_len < that_len) { - return -1; - } - if (this_len > that_len) { - return 1; - } - return 0; -} - -int CFX_WideString::CompareNoCase(const FX_WCHAR* lpsz) const { - if (!m_pData) { - return (!lpsz || lpsz[0] == 0) ? 0 : -1; - } - return FXSYS_wcsicmp(m_pData->m_String, lpsz); -} - -FX_STRSIZE CFX_WideString::WStringLength(const unsigned short* str) { - FX_STRSIZE len = 0; - if (str) - while (str[len]) - len++; - return len; -} - -void CFX_WideString::TrimRight(const CFX_WideStringC& pTargets) { - if (IsEmpty() || pTargets.IsEmpty()) - return; - - FX_STRSIZE pos = GetLength(); - while (pos && pTargets.Find(m_pData->m_String[pos - 1]) != -1) - pos--; - - if (pos < m_pData->m_nDataLength) { - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[pos] = 0; - m_pData->m_nDataLength = pos; - } -} - -void CFX_WideString::TrimRight(FX_WCHAR chTarget) { - FX_WCHAR str[2] = {chTarget, 0}; - TrimRight(str); -} - -void CFX_WideString::TrimRight() { - TrimRight(L"\x09\x0a\x0b\x0c\x0d\x20"); -} - -void CFX_WideString::TrimLeft(const CFX_WideStringC& pTargets) { - if (!m_pData || pTargets.IsEmpty()) - return; - - FX_STRSIZE len = GetLength(); - if (len < 1) - return; - - FX_STRSIZE pos = 0; - while (pos < len) { - FX_STRSIZE i = 0; - while (i < pTargets.GetLength() && - pTargets.CharAt(i) != m_pData->m_String[pos]) { - i++; - } - if (i == pTargets.GetLength()) { - break; - } - pos++; - } - if (pos) { - ReallocBeforeWrite(len); - FX_STRSIZE nDataLength = len - pos; - FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos, - (nDataLength + 1) * sizeof(FX_WCHAR)); - m_pData->m_nDataLength = nDataLength; - } -} - -void CFX_WideString::TrimLeft(FX_WCHAR chTarget) { - FX_WCHAR str[2] = {chTarget, 0}; - TrimLeft(str); -} - -void CFX_WideString::TrimLeft() { - TrimLeft(L"\x09\x0a\x0b\x0c\x0d\x20"); -} -FX_FLOAT FX_wtof(const FX_WCHAR* str, int len) { - if (len == 0) { - return 0.0; - } - int cc = 0; - bool bNegative = false; - if (str[0] == '+') { - cc++; - } else if (str[0] == '-') { - bNegative = true; - cc++; - } - int integer = 0; - while (cc < len) { - if (str[cc] == '.') { - break; - } - integer = integer * 10 + FXSYS_toDecimalDigit(str[cc]); - cc++; - } - FX_FLOAT fraction = 0; - if (str[cc] == '.') { - cc++; - FX_FLOAT scale = 0.1f; - while (cc < len) { - fraction += scale * FXSYS_toDecimalDigit(str[cc]); - scale *= 0.1f; - cc++; - } - } - fraction += (FX_FLOAT)integer; - return bNegative ? -fraction : fraction; -} - -int CFX_WideString::GetInteger() const { - return m_pData ? FXSYS_wtoi(m_pData->m_String) : 0; -} - -FX_FLOAT CFX_WideString::GetFloat() const { - return m_pData ? FX_wtof(m_pData->m_String, m_pData->m_nDataLength) : 0.0f; -} - -// static -CFX_ByteString CFX_CharMap::GetByteString(uint16_t codepage, - const CFX_WideStringC& wstr) { - ASSERT(IsValidCodePage(codepage)); - int src_len = wstr.GetLength(); - int dest_len = FXSYS_WideCharToMultiByte(codepage, 0, wstr.c_str(), src_len, - nullptr, 0, nullptr, nullptr); - CFX_ByteString bstr; - if (dest_len) { - FX_CHAR* dest_buf = bstr.GetBuffer(dest_len); - FXSYS_WideCharToMultiByte(codepage, 0, wstr.c_str(), src_len, dest_buf, - dest_len, nullptr, nullptr); - bstr.ReleaseBuffer(dest_len); - } - return bstr; -} - -// static -CFX_WideString CFX_CharMap::GetWideString(uint16_t codepage, - const CFX_ByteStringC& bstr) { - ASSERT(IsValidCodePage(codepage)); - int src_len = bstr.GetLength(); - int dest_len = - FXSYS_MultiByteToWideChar(codepage, 0, bstr.c_str(), src_len, nullptr, 0); - CFX_WideString wstr; - if (dest_len) { - FX_WCHAR* dest_buf = wstr.GetBuffer(dest_len); - FXSYS_MultiByteToWideChar(codepage, 0, bstr.c_str(), src_len, dest_buf, - dest_len); - wstr.ReleaseBuffer(dest_len); - } - return wstr; -} diff --git a/core/fxcrt/fx_basic_wstring_unittest.cpp b/core/fxcrt/fx_basic_wstring_unittest.cpp deleted file mode 100644 index 07b5aaf13c19bdf65d3451133194d09c87480cb9..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_basic_wstring_unittest.cpp +++ /dev/null @@ -1,941 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/fxcrt/fx_basic.h" -#include "testing/fx_string_testhelpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fxcrt, WideStringOperatorSubscript) { - // CFX_WideString includes the NUL terminator for non-empty strings. - CFX_WideString abc(L"abc"); - EXPECT_EQ(L'a', abc[0]); - EXPECT_EQ(L'b', abc[1]); - EXPECT_EQ(L'c', abc[2]); - EXPECT_EQ(L'\0', abc[3]); -} - -TEST(fxcrt, WideStringOperatorLT) { - CFX_WideString empty; - CFX_WideString a(L"a"); - CFX_WideString abc(L"\x0110qq"); // Comes before despite endianness. - CFX_WideString def(L"\x1001qq"); // Comes after despite endianness. - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, WideStringOperatorEQ) { - CFX_WideString null_string; - EXPECT_TRUE(null_string == null_string); - - CFX_WideString empty_string(L""); - EXPECT_TRUE(empty_string == empty_string); - EXPECT_TRUE(empty_string == null_string); - EXPECT_TRUE(null_string == empty_string); - - CFX_WideString deleted_string(L"hello"); - deleted_string.Delete(0, 5); - EXPECT_TRUE(deleted_string == deleted_string); - EXPECT_TRUE(deleted_string == null_string); - EXPECT_TRUE(deleted_string == empty_string); - EXPECT_TRUE(null_string == deleted_string); - EXPECT_TRUE(null_string == empty_string); - - CFX_WideString wide_string(L"hello"); - EXPECT_TRUE(wide_string == wide_string); - EXPECT_FALSE(wide_string == null_string); - EXPECT_FALSE(wide_string == empty_string); - EXPECT_FALSE(wide_string == deleted_string); - EXPECT_FALSE(null_string == wide_string); - EXPECT_FALSE(empty_string == wide_string); - EXPECT_FALSE(deleted_string == wide_string); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_TRUE(wide_string == wide_string_same1); - EXPECT_TRUE(wide_string_same1 == wide_string); - - CFX_WideString wide_string_same2(wide_string); - EXPECT_TRUE(wide_string == wide_string_same2); - EXPECT_TRUE(wide_string_same2 == wide_string); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_FALSE(wide_string == wide_string1); - EXPECT_FALSE(wide_string == wide_string2); - EXPECT_FALSE(wide_string == wide_string3); - EXPECT_FALSE(wide_string1 == wide_string); - EXPECT_FALSE(wide_string2 == wide_string); - EXPECT_FALSE(wide_string3 == wide_string); - - CFX_WideStringC null_string_c; - CFX_WideStringC empty_string_c(L""); - EXPECT_TRUE(null_string == null_string_c); - EXPECT_TRUE(null_string == empty_string_c); - EXPECT_TRUE(empty_string == null_string_c); - EXPECT_TRUE(empty_string == empty_string_c); - EXPECT_TRUE(deleted_string == null_string_c); - EXPECT_TRUE(deleted_string == empty_string_c); - EXPECT_TRUE(null_string_c == null_string); - EXPECT_TRUE(empty_string_c == null_string); - EXPECT_TRUE(null_string_c == empty_string); - EXPECT_TRUE(empty_string_c == empty_string); - EXPECT_TRUE(null_string_c == deleted_string); - EXPECT_TRUE(empty_string_c == deleted_string); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_TRUE(wide_string == wide_string_c_same1); - EXPECT_TRUE(wide_string_c_same1 == wide_string); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_FALSE(wide_string == wide_string_c1); - EXPECT_FALSE(wide_string == wide_string_c2); - EXPECT_FALSE(wide_string == wide_string_c3); - EXPECT_FALSE(wide_string_c1 == wide_string); - EXPECT_FALSE(wide_string_c2 == wide_string); - EXPECT_FALSE(wide_string_c3 == wide_string); - - const wchar_t* c_null_string = nullptr; - const wchar_t* c_empty_string = L""; - EXPECT_TRUE(null_string == c_null_string); - EXPECT_TRUE(null_string == c_empty_string); - EXPECT_TRUE(empty_string == c_null_string); - EXPECT_TRUE(empty_string == c_empty_string); - EXPECT_TRUE(deleted_string == c_null_string); - EXPECT_TRUE(deleted_string == c_empty_string); - EXPECT_TRUE(c_null_string == null_string); - EXPECT_TRUE(c_empty_string == null_string); - EXPECT_TRUE(c_null_string == empty_string); - EXPECT_TRUE(c_empty_string == empty_string); - EXPECT_TRUE(c_null_string == deleted_string); - EXPECT_TRUE(c_empty_string == deleted_string); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_TRUE(wide_string == c_string_same1); - EXPECT_TRUE(c_string_same1 == wide_string); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_FALSE(wide_string == c_string1); - EXPECT_FALSE(wide_string == c_string2); - EXPECT_FALSE(wide_string == c_string3); - EXPECT_FALSE(c_string1 == wide_string); - EXPECT_FALSE(c_string2 == wide_string); - EXPECT_FALSE(c_string3 == wide_string); -} - -TEST(fxcrt, WideStringOperatorNE) { - CFX_WideString null_string; - EXPECT_FALSE(null_string != null_string); - - CFX_WideString empty_string(L""); - EXPECT_FALSE(empty_string != empty_string); - EXPECT_FALSE(empty_string != null_string); - EXPECT_FALSE(null_string != empty_string); - - CFX_WideString deleted_string(L"hello"); - deleted_string.Delete(0, 5); - EXPECT_FALSE(deleted_string != deleted_string); - EXPECT_FALSE(deleted_string != null_string); - EXPECT_FALSE(deleted_string != empty_string); - EXPECT_FALSE(null_string != deleted_string); - EXPECT_FALSE(null_string != empty_string); - - CFX_WideString wide_string(L"hello"); - EXPECT_FALSE(wide_string != wide_string); - EXPECT_TRUE(wide_string != null_string); - EXPECT_TRUE(wide_string != empty_string); - EXPECT_TRUE(wide_string != deleted_string); - EXPECT_TRUE(null_string != wide_string); - EXPECT_TRUE(empty_string != wide_string); - EXPECT_TRUE(deleted_string != wide_string); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_FALSE(wide_string != wide_string_same1); - EXPECT_FALSE(wide_string_same1 != wide_string); - - CFX_WideString wide_string_same2(wide_string); - EXPECT_FALSE(wide_string != wide_string_same2); - EXPECT_FALSE(wide_string_same2 != wide_string); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_TRUE(wide_string != wide_string1); - EXPECT_TRUE(wide_string != wide_string2); - EXPECT_TRUE(wide_string != wide_string3); - EXPECT_TRUE(wide_string1 != wide_string); - EXPECT_TRUE(wide_string2 != wide_string); - EXPECT_TRUE(wide_string3 != wide_string); - - CFX_WideStringC null_string_c; - CFX_WideStringC empty_string_c(L""); - EXPECT_FALSE(null_string != null_string_c); - EXPECT_FALSE(null_string != empty_string_c); - EXPECT_FALSE(empty_string != null_string_c); - EXPECT_FALSE(empty_string != empty_string_c); - EXPECT_FALSE(deleted_string != null_string_c); - EXPECT_FALSE(deleted_string != empty_string_c); - EXPECT_FALSE(null_string_c != null_string); - EXPECT_FALSE(empty_string_c != null_string); - EXPECT_FALSE(null_string_c != empty_string); - EXPECT_FALSE(empty_string_c != empty_string); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_FALSE(wide_string != wide_string_c_same1); - EXPECT_FALSE(wide_string_c_same1 != wide_string); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_TRUE(wide_string != wide_string_c1); - EXPECT_TRUE(wide_string != wide_string_c2); - EXPECT_TRUE(wide_string != wide_string_c3); - EXPECT_TRUE(wide_string_c1 != wide_string); - EXPECT_TRUE(wide_string_c2 != wide_string); - EXPECT_TRUE(wide_string_c3 != wide_string); - - const wchar_t* c_null_string = nullptr; - const wchar_t* c_empty_string = L""; - EXPECT_FALSE(null_string != c_null_string); - EXPECT_FALSE(null_string != c_empty_string); - EXPECT_FALSE(empty_string != c_null_string); - EXPECT_FALSE(empty_string != c_empty_string); - EXPECT_FALSE(deleted_string != c_null_string); - EXPECT_FALSE(deleted_string != c_empty_string); - EXPECT_FALSE(c_null_string != null_string); - EXPECT_FALSE(c_empty_string != null_string); - EXPECT_FALSE(c_null_string != empty_string); - EXPECT_FALSE(c_empty_string != empty_string); - EXPECT_FALSE(c_null_string != deleted_string); - EXPECT_FALSE(c_empty_string != deleted_string); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_FALSE(wide_string != c_string_same1); - EXPECT_FALSE(c_string_same1 != wide_string); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_TRUE(wide_string != c_string1); - EXPECT_TRUE(wide_string != c_string2); - EXPECT_TRUE(wide_string != c_string3); - EXPECT_TRUE(c_string1 != wide_string); - EXPECT_TRUE(c_string2 != wide_string); - EXPECT_TRUE(c_string3 != wide_string); -} - -TEST(fxcrt, WideStringConcatInPlace) { - CFX_WideString fred; - fred.Concat(L"FRED", 4); - EXPECT_EQ(L"FRED", fred); - - fred.Concat(L"DY", 2); - EXPECT_EQ(L"FREDDY", fred); - - fred.Delete(3, 3); - EXPECT_EQ(L"FRE", fred); - - fred.Concat(L"D", 1); - EXPECT_EQ(L"FRED", fred); - - CFX_WideString copy = fred; - fred.Concat(L"DY", 2); - EXPECT_EQ(L"FREDDY", fred); - EXPECT_EQ(L"FRED", copy); - - // Test invalid arguments. - copy = fred; - fred.Concat(L"freddy", -6); - CFX_WideString not_aliased(L"xxxxxx"); - EXPECT_EQ(L"FREDDY", fred); - EXPECT_EQ(L"xxxxxx", not_aliased); -} - -TEST(fxcrt, WideStringRemove) { - CFX_WideString freed(L"FREED"); - freed.Remove(L'E'); - EXPECT_EQ(L"FRD", freed); - freed.Remove(L'F'); - EXPECT_EQ(L"RD", freed); - freed.Remove(L'D'); - EXPECT_EQ(L"R", freed); - freed.Remove(L'X'); - EXPECT_EQ(L"R", freed); - freed.Remove(L'R'); - EXPECT_EQ(L"", freed); - - CFX_WideString empty; - empty.Remove(L'X'); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringRemoveCopies) { - CFX_WideString freed(L"FREED"); - const FX_WCHAR* old_buffer = freed.c_str(); - - // No change with single reference - no copy. - freed.Remove(L'Q'); - EXPECT_EQ(L"FREED", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // Change with single reference - no copy. - freed.Remove(L'E'); - EXPECT_EQ(L"FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // No change with multiple references - no copy. - CFX_WideString shared(freed); - freed.Remove(L'Q'); - EXPECT_EQ(L"FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - EXPECT_EQ(old_buffer, shared.c_str()); - - // Change with multiple references -- must copy. - freed.Remove(L'D'); - EXPECT_EQ(L"FR", freed); - EXPECT_NE(old_buffer, freed.c_str()); - EXPECT_EQ(L"FRD", shared); - EXPECT_EQ(old_buffer, shared.c_str()); -} - -TEST(fxcrt, WideStringReplace) { - CFX_WideString fred(L"FRED"); - fred.Replace(L"FR", L"BL"); - EXPECT_EQ(L"BLED", fred); - fred.Replace(L"D", L"DDY"); - EXPECT_EQ(L"BLEDDY", fred); - fred.Replace(L"LEDD", L""); - EXPECT_EQ(L"BY", fred); - fred.Replace(L"X", L"CLAMS"); - EXPECT_EQ(L"BY", fred); - fred.Replace(L"BY", L"HI"); - EXPECT_EQ(L"HI", fred); - fred.Replace(L"", L"CLAMS"); - EXPECT_EQ(L"HI", fred); - fred.Replace(L"HI", L""); - EXPECT_EQ(L"", fred); -} - -TEST(fxcrt, WideStringInsert) { - CFX_WideString fred(L"FRED"); - fred.Insert(-1, 'X'); - EXPECT_EQ(L"XFRED", fred); - - fred.Insert(0, 'S'); - EXPECT_EQ(L"SXFRED", fred); - - fred.Insert(2, 'T'); - EXPECT_EQ(L"SXTFRED", fred); - - fred.Insert(5, 'U'); - EXPECT_EQ(L"SXTFRUED", fred); - - fred.Insert(8, 'V'); - EXPECT_EQ(L"SXTFRUEDV", fred); - - fred.Insert(12, 'P'); - EXPECT_EQ(L"SXTFRUEDVP", fred); - - { - CFX_WideString empty; - empty.Insert(-1, 'X'); - EXPECT_EQ(L"X", empty); - } - { - CFX_WideString empty; - empty.Insert(0, 'X'); - EXPECT_EQ(L"X", empty); - } - { - CFX_WideString empty; - empty.Insert(5, 'X'); - EXPECT_EQ(L"X", empty); - } -} - -TEST(fxcrt, WideStringDelete) { - CFX_WideString fred(L"FRED"); - fred.Delete(0, 2); - EXPECT_EQ(L"ED", fred); - fred.Delete(1); - EXPECT_EQ(L"E", fred); - fred.Delete(-1); - EXPECT_EQ(L"", fred); - fred.Delete(1); - EXPECT_EQ(L"", fred); - - CFX_WideString empty; - empty.Delete(0); - EXPECT_EQ(L"", empty); - empty.Delete(-1); - EXPECT_EQ(L"", empty); - empty.Delete(1); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringMid) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(L"", fred.Mid(0, 0)); - EXPECT_EQ(L"", fred.Mid(3, 0)); - EXPECT_EQ(L"FRED", fred.Mid(0)); - EXPECT_EQ(L"RED", fred.Mid(1)); - EXPECT_EQ(L"ED", fred.Mid(2)); - EXPECT_EQ(L"D", fred.Mid(3)); - EXPECT_EQ(L"F", fred.Mid(0, 1)); - EXPECT_EQ(L"R", fred.Mid(1, 1)); - EXPECT_EQ(L"E", fred.Mid(2, 1)); - EXPECT_EQ(L"D", fred.Mid(3, 1)); - EXPECT_EQ(L"FR", fred.Mid(0, 2)); - EXPECT_EQ(L"FRED", fred.Mid(0, 4)); - EXPECT_EQ(L"FRED", fred.Mid(0, 10)); - - EXPECT_EQ(L"FR", fred.Mid(-1, 2)); - EXPECT_EQ(L"RED", fred.Mid(1, 4)); - EXPECT_EQ(L"", fred.Mid(4, 1)); - - CFX_WideString empty; - EXPECT_EQ(L"", empty.Mid(0, 0)); - EXPECT_EQ(L"", empty.Mid(0)); - EXPECT_EQ(L"", empty.Mid(1)); - EXPECT_EQ(L"", empty.Mid(-1)); -} - -TEST(fxcrt, WideStringLeft) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(L"", fred.Left(0)); - EXPECT_EQ(L"F", fred.Left(1)); - EXPECT_EQ(L"FR", fred.Left(2)); - EXPECT_EQ(L"FRE", fred.Left(3)); - EXPECT_EQ(L"FRED", fred.Left(4)); - - EXPECT_EQ(L"FRED", fred.Left(5)); - EXPECT_EQ(L"", fred.Left(-1)); - - CFX_WideString empty; - EXPECT_EQ(L"", empty.Left(0)); - EXPECT_EQ(L"", empty.Left(1)); - EXPECT_EQ(L"", empty.Left(-1)); -} - -TEST(fxcrt, WideStringRight) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(L"", fred.Right(0)); - EXPECT_EQ(L"D", fred.Right(1)); - EXPECT_EQ(L"ED", fred.Right(2)); - EXPECT_EQ(L"RED", fred.Right(3)); - EXPECT_EQ(L"FRED", fred.Right(4)); - - EXPECT_EQ(L"FRED", fred.Right(5)); - EXPECT_EQ(L"", fred.Right(-1)); - - CFX_WideString empty; - EXPECT_EQ(L"", empty.Right(0)); - EXPECT_EQ(L"", empty.Right(1)); - EXPECT_EQ(L"", empty.Right(-1)); -} - -TEST(fxcrt, WideStringUpperLower) { - CFX_WideString fred(L"F-Re.42D"); - fred.MakeLower(); - EXPECT_EQ(L"f-re.42d", fred); - fred.MakeUpper(); - EXPECT_EQ(L"F-RE.42D", fred); - - CFX_WideString empty; - empty.MakeLower(); - EXPECT_EQ(L"", empty); - empty.MakeUpper(); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringTrimRight) { - CFX_WideString fred(L" FRED "); - fred.TrimRight(); - EXPECT_EQ(L" FRED", fred); - fred.TrimRight(L'E'); - EXPECT_EQ(L" FRED", fred); - fred.TrimRight(L'D'); - EXPECT_EQ(L" FRE", fred); - fred.TrimRight(L"ERP"); - EXPECT_EQ(L" F", fred); - - CFX_WideString blank(L" "); - blank.TrimRight(L"ERP"); - EXPECT_EQ(L" ", blank); - blank.TrimRight(L'E'); - EXPECT_EQ(L" ", blank); - blank.TrimRight(); - EXPECT_EQ(L"", blank); - - CFX_WideString empty; - empty.TrimRight(L"ERP"); - EXPECT_EQ(L"", empty); - empty.TrimRight(L'E'); - EXPECT_EQ(L"", empty); - empty.TrimRight(); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringTrimRightCopies) { - { - // With a single reference, no copy takes place. - CFX_WideString fred(L" FRED "); - const FX_WCHAR* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(L" FRED", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_WideString fred(L" FRED "); - CFX_WideString other_fred = fred; - const FX_WCHAR* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(L" FRED", fred); - EXPECT_EQ(L" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_WideString fred(L"FRED"); - CFX_WideString other_fred = fred; - const FX_WCHAR* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(L"FRED", fred); - EXPECT_EQ(L"FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, WideStringTrimLeft) { - CFX_WideString fred(L" FRED "); - fred.TrimLeft(); - EXPECT_EQ(L"FRED ", fred); - fred.TrimLeft(L'E'); - EXPECT_EQ(L"FRED ", fred); - fred.TrimLeft(L'F'); - EXPECT_EQ(L"RED ", fred); - fred.TrimLeft(L"ERP"); - EXPECT_EQ(L"D ", fred); - - CFX_WideString blank(L" "); - blank.TrimLeft(L"ERP"); - EXPECT_EQ(L" ", blank); - blank.TrimLeft(L'E'); - EXPECT_EQ(L" ", blank); - blank.TrimLeft(); - EXPECT_EQ(L"", blank); - - CFX_WideString empty; - empty.TrimLeft(L"ERP"); - EXPECT_EQ(L"", empty); - empty.TrimLeft(L'E'); - EXPECT_EQ(L"", empty); - empty.TrimLeft(); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringTrimLeftCopies) { - { - // With a single reference, no copy takes place. - CFX_WideString fred(L" FRED "); - const FX_WCHAR* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ(L"FRED ", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_WideString fred(L" FRED "); - CFX_WideString other_fred = fred; - const FX_WCHAR* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ(L"FRED ", fred); - EXPECT_EQ(L" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_WideString fred(L"FRED"); - CFX_WideString other_fred = fred; - const FX_WCHAR* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ(L"FRED", fred); - EXPECT_EQ(L"FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, WideStringReserve) { - { - CFX_WideString str; - str.Reserve(6); - const FX_WCHAR* old_buffer = str.c_str(); - str += L"ABCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += L"Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } - { - CFX_WideString str(L"A"); - str.Reserve(6); - const FX_WCHAR* old_buffer = str.c_str(); - str += L"BCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += L"Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } -} - -TEST(fxcrt, WideStringGetBuffer) { - { - CFX_WideString str; - FX_WCHAR* buffer = str.GetBuffer(12); - wcscpy(buffer, L"clams"); - str.ReleaseBuffer(); - EXPECT_EQ(L"clams", str); - } - { - CFX_WideString str(L"cl"); - FX_WCHAR* buffer = str.GetBuffer(12); - wcscpy(buffer + 2, L"ams"); - str.ReleaseBuffer(); - EXPECT_EQ(L"clams", str); - } -} - -TEST(fxcrt, WideStringReleaseBuffer) { - { - CFX_WideString str; - str.Reserve(12); - str += L"clams"; - const FX_WCHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } - { - CFX_WideString str(L"c"); - str.Reserve(12); - str += L"lams"; - const FX_WCHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } - { - CFX_WideString str; - str.Reserve(200); - str += L"clams"; - const FX_WCHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } - { - CFX_WideString str(L"c"); - str.Reserve(200); - str += L"lams"; - const FX_WCHAR* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } -} - -TEST(fxcrt, WideStringUTF16LE_Encode) { - struct UTF16LEEncodeCase { - CFX_WideString ws; - CFX_ByteString bs; - } utf16le_encode_cases[] = { - {L"", CFX_ByteString("\0\0", 2)}, - {L"abc", CFX_ByteString("a\0b\0c\0\0\0", 8)}, - {L"abcdef", CFX_ByteString("a\0b\0c\0d\0e\0f\0\0\0", 14)}, - {L"abc\0def", CFX_ByteString("a\0b\0c\0\0\0", 8)}, - {L"\xaabb\xccdd", CFX_ByteString("\xbb\xaa\xdd\xcc\0\0", 6)}, - {L"\x3132\x6162", CFX_ByteString("\x32\x31\x62\x61\0\0", 6)}, - }; - - for (size_t i = 0; i < FX_ArraySize(utf16le_encode_cases); ++i) { - EXPECT_EQ(utf16le_encode_cases[i].bs, - utf16le_encode_cases[i].ws.UTF16LE_Encode()) - << " for case number " << i; - } -} - -TEST(fxcrt, WideStringCOperatorSubscript) { - // CFX_WideStringC includes the NUL terminator for non-empty strings. - CFX_WideStringC abc(L"abc"); - EXPECT_EQ(L'a', abc.CharAt(0)); - EXPECT_EQ(L'b', abc.CharAt(1)); - EXPECT_EQ(L'c', abc.CharAt(2)); - EXPECT_EQ(L'\0', abc.CharAt(3)); -} - -TEST(fxcrt, WideStringCOperatorLT) { - CFX_WideStringC empty; - CFX_WideStringC a(L"a"); - CFX_WideStringC abc(L"\x0110qq"); // Comes before despite endianness. - CFX_WideStringC def(L"\x1001qq"); // Comes after despite endianness. - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, WideStringCOperatorEQ) { - CFX_WideStringC wide_string_c(L"hello"); - EXPECT_TRUE(wide_string_c == wide_string_c); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_TRUE(wide_string_c == wide_string_c_same1); - EXPECT_TRUE(wide_string_c_same1 == wide_string_c); - - CFX_WideStringC wide_string_c_same2(wide_string_c); - EXPECT_TRUE(wide_string_c == wide_string_c_same2); - EXPECT_TRUE(wide_string_c_same2 == wide_string_c); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_FALSE(wide_string_c == wide_string_c1); - EXPECT_FALSE(wide_string_c == wide_string_c2); - EXPECT_FALSE(wide_string_c == wide_string_c3); - EXPECT_FALSE(wide_string_c1 == wide_string_c); - EXPECT_FALSE(wide_string_c2 == wide_string_c); - EXPECT_FALSE(wide_string_c3 == wide_string_c); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_TRUE(wide_string_c == wide_string_same1); - EXPECT_TRUE(wide_string_same1 == wide_string_c); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_FALSE(wide_string_c == wide_string1); - EXPECT_FALSE(wide_string_c == wide_string2); - EXPECT_FALSE(wide_string_c == wide_string3); - EXPECT_FALSE(wide_string1 == wide_string_c); - EXPECT_FALSE(wide_string2 == wide_string_c); - EXPECT_FALSE(wide_string3 == wide_string_c); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_TRUE(wide_string_c == c_string_same1); - EXPECT_TRUE(c_string_same1 == wide_string_c); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_FALSE(wide_string_c == c_string1); - EXPECT_FALSE(wide_string_c == c_string2); - EXPECT_FALSE(wide_string_c == c_string3); - - EXPECT_FALSE(c_string1 == wide_string_c); - EXPECT_FALSE(c_string2 == wide_string_c); - EXPECT_FALSE(c_string3 == wide_string_c); -} - -TEST(fxcrt, WideStringCOperatorNE) { - CFX_WideStringC wide_string_c(L"hello"); - EXPECT_FALSE(wide_string_c != wide_string_c); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_FALSE(wide_string_c != wide_string_c_same1); - EXPECT_FALSE(wide_string_c_same1 != wide_string_c); - - CFX_WideStringC wide_string_c_same2(wide_string_c); - EXPECT_FALSE(wide_string_c != wide_string_c_same2); - EXPECT_FALSE(wide_string_c_same2 != wide_string_c); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_TRUE(wide_string_c != wide_string_c1); - EXPECT_TRUE(wide_string_c != wide_string_c2); - EXPECT_TRUE(wide_string_c != wide_string_c3); - EXPECT_TRUE(wide_string_c1 != wide_string_c); - EXPECT_TRUE(wide_string_c2 != wide_string_c); - EXPECT_TRUE(wide_string_c3 != wide_string_c); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_FALSE(wide_string_c != wide_string_same1); - EXPECT_FALSE(wide_string_same1 != wide_string_c); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_TRUE(wide_string_c != wide_string1); - EXPECT_TRUE(wide_string_c != wide_string2); - EXPECT_TRUE(wide_string_c != wide_string3); - EXPECT_TRUE(wide_string1 != wide_string_c); - EXPECT_TRUE(wide_string2 != wide_string_c); - EXPECT_TRUE(wide_string3 != wide_string_c); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_FALSE(wide_string_c != c_string_same1); - EXPECT_FALSE(c_string_same1 != wide_string_c); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_TRUE(wide_string_c != c_string1); - EXPECT_TRUE(wide_string_c != c_string2); - EXPECT_TRUE(wide_string_c != c_string3); - - EXPECT_TRUE(c_string1 != wide_string_c); - EXPECT_TRUE(c_string2 != wide_string_c); - EXPECT_TRUE(c_string3 != wide_string_c); -} - -TEST(fxcrt, WideStringCFind) { - CFX_WideStringC null_string; - EXPECT_EQ(-1, null_string.Find(L'a')); - EXPECT_EQ(-1, null_string.Find(0)); - - CFX_WideStringC empty_string(L""); - EXPECT_EQ(-1, empty_string.Find(L'a')); - EXPECT_EQ(-1, empty_string.Find(0)); - - CFX_WideStringC single_string(L"a"); - EXPECT_EQ(0, single_string.Find(L'a')); - EXPECT_EQ(-1, single_string.Find(L'b')); - EXPECT_EQ(-1, single_string.Find(0)); - - CFX_WideStringC longer_string(L"abccc"); - EXPECT_EQ(0, longer_string.Find(L'a')); - EXPECT_EQ(2, longer_string.Find(L'c')); - EXPECT_EQ(-1, longer_string.Find(0)); - - CFX_WideStringC hibyte_string( - L"ab\xff08" - L"def"); - EXPECT_EQ(2, hibyte_string.Find(L'\xff08')); -} - -TEST(fxcrt, WideStringFormatWidth) { - { - CFX_WideString str; - str.Format(L"%5d", 1); - EXPECT_EQ(L" 1", str); - } - - { - CFX_WideString str; - str.Format(L"%d", 1); - EXPECT_EQ(L"1", str); - } - - { - CFX_WideString str; - str.Format(L"%*d", 5, 1); - EXPECT_EQ(L" 1", str); - } - - { - CFX_WideString str; - str.Format(L"%-1d", 1); - EXPECT_EQ(L"1", str); - } - - { - CFX_WideString str; - str.Format(L"%0d", 1); - EXPECT_EQ(L"1", str); - } - - { - CFX_WideString str; - str.Format(L"%1048576d", 1); - EXPECT_EQ(L"Bad width", str); - } -} - -TEST(fxcrt, WideStringFormatPrecision) { - { - CFX_WideString str; - str.Format(L"%.2f", 1.12345); - EXPECT_EQ(L"1.12", str); - } - - { - CFX_WideString str; - str.Format(L"%.*f", 3, 1.12345); - EXPECT_EQ(L"1.123", str); - } - - { - CFX_WideString str; - str.Format(L"%f", 1.12345); - EXPECT_EQ(L"1.123450", str); - } - - { - CFX_WideString str; - str.Format(L"%-1f", 1.12345); - EXPECT_EQ(L"1.123450", str); - } - - { - CFX_WideString str; - str.Format(L"%0f", 1.12345); - EXPECT_EQ(L"1.123450", str); - } - - { - CFX_WideString str; - str.Format(L"%.1048576f", 1.2); - EXPECT_EQ(L"Bad precision", str); - } -} - -TEST(fxcrt, EmptyWideString) { - CFX_WideString empty_str; - EXPECT_TRUE(empty_str.IsEmpty()); - EXPECT_EQ(0, empty_str.GetLength()); - const FX_WCHAR* cstr = empty_str.c_str(); - EXPECT_EQ(0, FXSYS_wcslen(cstr)); -} diff --git a/core/fxcrt/fx_bidi.cpp b/core/fxcrt/fx_bidi.cpp index e82b3e72847c6876ebd4429bad0ae70c503ba6b0..db46d994c9a4923f4eab46dd6e0a755f745b1616 100644 --- a/core/fxcrt/fx_bidi.cpp +++ b/core/fxcrt/fx_bidi.cpp @@ -5,14 +5,543 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fxcrt/fx_bidi.h" -#include "core/fxcrt/fx_ucd.h" #include +#include "core/fxcrt/fx_unicode.h" +#include "third_party/base/ptr_util.h" + +#ifdef PDF_ENABLE_XFA +#include "core/fxcrt/fx_extension.h" +#endif // PDF_ENABLE_XFA + +namespace { + +enum FX_BIDICLASS { + FX_BIDICLASS_ON = 0, // Other Neutral + FX_BIDICLASS_L = 1, // Left Letter + FX_BIDICLASS_R = 2, // Right Letter + FX_BIDICLASS_AN = 3, // Arabic Number + FX_BIDICLASS_EN = 4, // European Number + FX_BIDICLASS_AL = 5, // Arabic Letter + FX_BIDICLASS_NSM = 6, // Non-spacing Mark + FX_BIDICLASS_CS = 7, // Common Number Separator + FX_BIDICLASS_ES = 8, // European Separator + FX_BIDICLASS_ET = 9, // European Number Terminator + FX_BIDICLASS_BN = 10, // Boundary Neutral + FX_BIDICLASS_S = 11, // Segment Separator + FX_BIDICLASS_WS = 12, // Whitespace + FX_BIDICLASS_B = 13, // Paragraph Separator + FX_BIDICLASS_RLO = 14, // Right-to-Left Override + FX_BIDICLASS_RLE = 15, // Right-to-Left Embedding + FX_BIDICLASS_LRO = 16, // Left-to-Right Override + FX_BIDICLASS_LRE = 17, // Left-to-Right Embedding + FX_BIDICLASS_PDF = 18, // Pop Directional Format + FX_BIDICLASS_N = FX_BIDICLASS_ON, +}; +constexpr uint32_t FX_BIDICLASSBITS = 6; +constexpr uint32_t FX_BIDICLASSBITSMASK = 0x1F << FX_BIDICLASSBITS; + +#ifdef PDF_ENABLE_XFA + +#ifndef NDEBUG +constexpr int32_t kBidiMaxLevel = 61; +#endif // NDEBUG + +enum FX_BIDIWEAKSTATE { + FX_BWSxa = 0, + FX_BWSxr, + FX_BWSxl, + FX_BWSao, + FX_BWSro, + FX_BWSlo, + FX_BWSrt, + FX_BWSlt, + FX_BWScn, + FX_BWSra, + FX_BWSre, + FX_BWSla, + FX_BWSle, + FX_BWSac, + FX_BWSrc, + FX_BWSrs, + FX_BWSlc, + FX_BWSls, + FX_BWSret, + FX_BWSlet +}; + +enum FX_BIDIWEAKACTION { + FX_BWAIX = 0x100, + FX_BWAXX = 0x0F, + FX_BWAxxx = (0x0F << 4) + 0x0F, + FX_BWAxIx = 0x100 + FX_BWAxxx, + FX_BWAxxN = (0x0F << 4) + FX_BIDICLASS_ON, + FX_BWAxxE = (0x0F << 4) + FX_BIDICLASS_EN, + FX_BWAxxA = (0x0F << 4) + FX_BIDICLASS_AN, + FX_BWAxxR = (0x0F << 4) + FX_BIDICLASS_R, + FX_BWAxxL = (0x0F << 4) + FX_BIDICLASS_L, + FX_BWANxx = (FX_BIDICLASS_ON << 4) + 0x0F, + FX_BWAAxx = (FX_BIDICLASS_AN << 4) + 0x0F, + FX_BWAExE = (FX_BIDICLASS_EN << 4) + FX_BIDICLASS_EN, + FX_BWANIx = (FX_BIDICLASS_ON << 4) + 0x0F + 0x100, + FX_BWANxN = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_ON, + FX_BWANxR = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_R, + FX_BWANxE = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_EN, + FX_BWAAxA = (FX_BIDICLASS_AN << 4) + FX_BIDICLASS_AN, + FX_BWANxL = (FX_BIDICLASS_ON << 4) + FX_BIDICLASS_L, + FX_BWALxL = (FX_BIDICLASS_L << 4) + FX_BIDICLASS_L, + FX_BWAxIL = (0x0F << 4) + FX_BIDICLASS_L + 0x100, + FX_BWAAxR = (FX_BIDICLASS_AN << 4) + FX_BIDICLASS_R, + FX_BWALxx = (FX_BIDICLASS_L << 4) + 0x0F, +}; + +enum FX_BIDINEUTRALSTATE { + FX_BNSr = 0, + FX_BNSl, + FX_BNSrn, + FX_BNSln, + FX_BNSa, + FX_BNSna +}; + +enum FX_BIDINEUTRALACTION { + FX_BNAnL = FX_BIDICLASS_L, + FX_BNAEn = (FX_BIDICLASS_AN << 4), + FX_BNARn = (FX_BIDICLASS_R << 4), + FX_BNALn = (FX_BIDICLASS_L << 4), + FX_BNAIn = FX_BWAIX, + FX_BNALnL = (FX_BIDICLASS_L << 4) + FX_BIDICLASS_L, +}; + +const int32_t gc_FX_BidiNTypes[] = { + FX_BIDICLASS_N, FX_BIDICLASS_L, FX_BIDICLASS_R, FX_BIDICLASS_AN, + FX_BIDICLASS_EN, FX_BIDICLASS_AL, FX_BIDICLASS_NSM, FX_BIDICLASS_CS, + FX_BIDICLASS_ES, FX_BIDICLASS_ET, FX_BIDICLASS_BN, FX_BIDICLASS_BN, + FX_BIDICLASS_N, FX_BIDICLASS_B, FX_BIDICLASS_RLO, FX_BIDICLASS_RLE, + FX_BIDICLASS_LRO, FX_BIDICLASS_LRE, FX_BIDICLASS_PDF, FX_BIDICLASS_ON, +}; + +const int32_t gc_FX_BidiWeakStates[][10] = { + {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSxa, + FX_BWSao, FX_BWSao, FX_BWSao}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSxr, + FX_BWSro, FX_BWSro, FX_BWSrt}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSxl, + FX_BWSlo, FX_BWSlo, FX_BWSlt}, + {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao, + FX_BWSao, FX_BWSao, FX_BWSao}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro, + FX_BWSro, FX_BWSro, FX_BWSrt}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo, + FX_BWSlo, FX_BWSlo, FX_BWSlt}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSrt, + FX_BWSro, FX_BWSro, FX_BWSrt}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlt, + FX_BWSlo, FX_BWSlo, FX_BWSlt}, + {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWScn, + FX_BWSac, FX_BWSao, FX_BWSao}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSra, + FX_BWSrc, FX_BWSro, FX_BWSrt}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSre, + FX_BWSrs, FX_BWSrs, FX_BWSret}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSla, + FX_BWSlc, FX_BWSlo, FX_BWSlt}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSle, + FX_BWSls, FX_BWSls, FX_BWSlet}, + {FX_BWSao, FX_BWSxl, FX_BWSxr, FX_BWScn, FX_BWScn, FX_BWSxa, FX_BWSao, + FX_BWSao, FX_BWSao, FX_BWSao}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro, + FX_BWSro, FX_BWSro, FX_BWSrt}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSro, + FX_BWSro, FX_BWSro, FX_BWSrt}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo, + FX_BWSlo, FX_BWSlo, FX_BWSlt}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlo, + FX_BWSlo, FX_BWSlo, FX_BWSlt}, + {FX_BWSro, FX_BWSxl, FX_BWSxr, FX_BWSra, FX_BWSre, FX_BWSxa, FX_BWSret, + FX_BWSro, FX_BWSro, FX_BWSret}, + {FX_BWSlo, FX_BWSxl, FX_BWSxr, FX_BWSla, FX_BWSle, FX_BWSxa, FX_BWSlet, + FX_BWSlo, FX_BWSlo, FX_BWSlet}, +}; + +const int32_t gc_FX_BidiWeakActions[][10] = { + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR, + FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, + FX_BWAxxR, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, + FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR, + FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxxN}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, + FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, + FX_BWAxxN, FX_BWAxxN, FX_BWAxxN, FX_BWAxIx}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR, + FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR, + FX_BWAxIx, FX_BWANxN, FX_BWANxN, FX_BWAxIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxA, FX_BWAxxR, + FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxxN}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, + FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, + FX_BWAxxE, FX_BWAxIx, FX_BWAxIx, FX_BWAxxE}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, + FX_BWAxxA, FX_BWAxIx, FX_BWAxxN, FX_BWAxIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, + FX_BWAxxL, FX_BWAxIx, FX_BWAxIx, FX_BWAxxL}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWAAxA, FX_BWANxR, + FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANxN}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxE, FX_BWANxR, + FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAExE, FX_BWANxR, + FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWAAxx, FX_BWANxL, FX_BWANxR, + FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, + {FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWANxx, FX_BWALxL, FX_BWANxR, + FX_BWANxN, FX_BWANxN, FX_BWANxN, FX_BWANIx}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxE, FX_BWAxxR, + FX_BWAxxE, FX_BWAxxN, FX_BWAxxN, FX_BWAxxE}, + {FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxx, FX_BWAxxL, FX_BWAxxR, + FX_BWAxxL, FX_BWAxxN, FX_BWAxxN, FX_BWAxxL}, +}; + +const int32_t gc_FX_BidiNeutralStates[][5] = { + {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr}, + {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, + {FX_BNSrn, FX_BNSl, FX_BNSr, FX_BNSr, FX_BNSr}, + {FX_BNSln, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, + {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, + {FX_BNSna, FX_BNSl, FX_BNSr, FX_BNSa, FX_BNSl}, +}; +const int32_t gc_FX_BidiNeutralActions[][5] = { + {FX_BNAIn, 0, 0, 0, 0}, + {FX_BNAIn, 0, 0, 0, FX_BIDICLASS_L}, + {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNARn}, + {FX_BNAIn, FX_BNALn, FX_BNAEn, FX_BNAEn, FX_BNALnL}, + {FX_BNAIn, 0, 0, 0, FX_BIDICLASS_L}, + {FX_BNAIn, FX_BNAEn, FX_BNARn, FX_BNARn, FX_BNAEn}, +}; + +const int32_t gc_FX_BidiAddLevel[][4] = { + {0, 1, 2, 2}, + {1, 0, 1, 1}, +}; + +class CFX_BidiLine { + public: + void BidiLine(std::vector* chars, size_t iCount) { + ASSERT(iCount <= chars->size()); + if (iCount < 2) + return; + + Classify(chars, iCount, false); + ResolveExplicit(chars, iCount); + ResolveWeak(chars, iCount); + ResolveNeutrals(chars, iCount); + ResolveImplicit(chars, iCount); + Classify(chars, iCount, true); + ResolveWhitespace(chars, iCount); + Reorder(chars, iCount); + Position(chars, iCount); + } + + private: + int32_t Direction(int32_t val) { + return FX_IsOdd(val) ? FX_BIDICLASS_R : FX_BIDICLASS_L; + } + + int32_t GetDeferredType(int32_t val) { return (val >> 4) & 0x0F; } + + int32_t GetResolvedType(int32_t val) { return val & 0x0F; } + + int32_t GetDeferredNeutrals(int32_t iAction, int32_t iLevel) { + iAction = (iAction >> 4) & 0xF; + if (iAction == (FX_BNAEn >> 4)) + return Direction(iLevel); + return iAction; + } + + int32_t GetResolvedNeutrals(int32_t iAction) { + iAction &= 0xF; + return iAction == FX_BNAIn ? 0 : iAction; + } + + void ReverseString(std::vector* chars, + size_t iStart, + size_t iCount) { + ASSERT(pdfium::IndexInBounds(*chars, iStart)); + ASSERT(iStart + iCount <= chars->size()); + + std::reverse(chars->begin() + iStart, chars->begin() + iStart + iCount); + } + + void SetDeferredRun(std::vector* chars, + bool bClass, + size_t iStart, + size_t iCount, + int32_t iValue) { + ASSERT(iStart <= chars->size()); + ASSERT(iStart >= iCount); + + size_t iLast = iStart - iCount; + for (size_t i = iStart - 1; i >= iLast; --i) { + if (bClass) + (*chars)[i].m_iBidiClass = static_cast(iValue); + else + (*chars)[i].m_iBidiLevel = static_cast(iValue); + + if (i == 0) + break; + } + } + + void Classify(std::vector* chars, size_t iCount, bool bWS) { + if (bWS) { + for (size_t i = 0; i < iCount; ++i) { + CFX_Char& cur = (*chars)[i]; + cur.m_iBidiClass = + static_cast(cur.char_props() & FX_BIDICLASSBITSMASK) >> + FX_BIDICLASSBITS; + } + return; + } + + for (size_t i = 0; i < iCount; ++i) { + CFX_Char& cur = (*chars)[i]; + cur.m_iBidiClass = static_cast( + gc_FX_BidiNTypes[(cur.char_props() & FX_BIDICLASSBITSMASK) >> + FX_BIDICLASSBITS]); + } + } + + void ResolveExplicit(std::vector* chars, size_t iCount) { + for (size_t i = 0; i < iCount; ++i) + (*chars)[i].m_iBidiLevel = 0; + } + + void ResolveWeak(std::vector* chars, size_t iCount) { + if (iCount <= 1) + return; + --iCount; + + int32_t iLevelCur = 0; + int32_t iState = FX_BWSxl; + size_t i = 0; + size_t iNum = 0; + int32_t iClsCur; + int32_t iClsRun; + int32_t iClsNew; + int32_t iAction; + for (; i <= iCount; ++i) { + CFX_Char* pTC = &(*chars)[i]; + iClsCur = pTC->m_iBidiClass; + if (iClsCur == FX_BIDICLASS_BN) { + pTC->m_iBidiLevel = (int16_t)iLevelCur; + if (i == iCount && iLevelCur != 0) { + iClsCur = Direction(iLevelCur); + pTC->m_iBidiClass = (int16_t)iClsCur; + } else if (i < iCount) { + CFX_Char* pTCNext = &(*chars)[i + 1]; + int32_t iLevelNext, iLevelNew; + iClsNew = pTCNext->m_iBidiClass; + iLevelNext = pTCNext->m_iBidiLevel; + if (iClsNew != FX_BIDICLASS_BN && iLevelCur != iLevelNext) { + iLevelNew = std::max(iLevelNext, iLevelCur); + pTC->m_iBidiLevel = static_cast(iLevelNew); + iClsCur = Direction(iLevelNew); + pTC->m_iBidiClass = static_cast(iClsCur); + iLevelCur = iLevelNext; + } else { + if (iNum > 0) + ++iNum; + continue; + } + } else { + if (iNum > 0) + ++iNum; + continue; + } + } + + ASSERT(iClsCur <= FX_BIDICLASS_BN); + iAction = gc_FX_BidiWeakActions[iState][iClsCur]; + iClsRun = GetDeferredType(iAction); + if (iClsRun != FX_BWAXX && iNum > 0) { + SetDeferredRun(chars, true, i, iNum, iClsRun); + iNum = 0; + } + iClsNew = GetResolvedType(iAction); + if (iClsNew != FX_BWAXX) + pTC->m_iBidiClass = static_cast(iClsNew); + if (FX_BWAIX & iAction) + ++iNum; + + iState = gc_FX_BidiWeakStates[iState][iClsCur]; + } + if (iNum == 0) + return; + + iClsCur = Direction(0); + iClsRun = GetDeferredType(gc_FX_BidiWeakActions[iState][iClsCur]); + if (iClsRun != FX_BWAXX) + SetDeferredRun(chars, true, i, iNum, iClsRun); + } + + void ResolveNeutrals(std::vector* chars, size_t iCount) { + if (iCount <= 1) + return; + --iCount; + + CFX_Char* pTC; + int32_t iLevel = 0; + int32_t iState = FX_BNSl; + size_t i = 0; + size_t iNum = 0; + int32_t iClsCur; + int32_t iClsRun; + int32_t iClsNew; + int32_t iAction; + for (; i <= iCount; ++i) { + pTC = &(*chars)[i]; + iClsCur = pTC->m_iBidiClass; + if (iClsCur == FX_BIDICLASS_BN) { + if (iNum) + ++iNum; + continue; + } + + ASSERT(iClsCur < FX_BIDICLASS_AL); + iAction = gc_FX_BidiNeutralActions[iState][iClsCur]; + iClsRun = GetDeferredNeutrals(iAction, iLevel); + if (iClsRun != FX_BIDICLASS_N && iNum > 0) { + SetDeferredRun(chars, true, i, iNum, iClsRun); + iNum = 0; + } + + iClsNew = GetResolvedNeutrals(iAction); + if (iClsNew != FX_BIDICLASS_N) + pTC->m_iBidiClass = (int16_t)iClsNew; + if (FX_BNAIn & iAction) + ++iNum; + + iState = gc_FX_BidiNeutralStates[iState][iClsCur]; + iLevel = pTC->m_iBidiLevel; + } + if (iNum == 0) + return; + + iClsCur = Direction(iLevel); + iClsRun = + GetDeferredNeutrals(gc_FX_BidiNeutralActions[iState][iClsCur], iLevel); + if (iClsRun != FX_BIDICLASS_N) + SetDeferredRun(chars, true, i, iNum, iClsRun); + } + + void ResolveImplicit(std::vector* chars, size_t iCount) { + for (size_t i = 0; i < iCount; ++i) { + int32_t iCls = (*chars)[i].m_iBidiClass; + if (iCls == FX_BIDICLASS_BN) + continue; + + ASSERT(iCls > FX_BIDICLASS_ON && iCls < FX_BIDICLASS_AL); + int32_t iLevel = (*chars)[i].m_iBidiLevel; + iLevel += gc_FX_BidiAddLevel[FX_IsOdd(iLevel)][iCls - 1]; + (*chars)[i].m_iBidiLevel = (int16_t)iLevel; + } + } + + void ResolveWhitespace(std::vector* chars, size_t iCount) { + if (iCount <= 1) + return; + iCount--; + + int32_t iLevel = 0; + size_t i = 0; + size_t iNum = 0; + for (; i <= iCount; ++i) { + switch ((*chars)[i].m_iBidiClass) { + case FX_BIDICLASS_WS: + ++iNum; + break; + case FX_BIDICLASS_RLE: + case FX_BIDICLASS_LRE: + case FX_BIDICLASS_LRO: + case FX_BIDICLASS_RLO: + case FX_BIDICLASS_PDF: + case FX_BIDICLASS_BN: + (*chars)[i].m_iBidiLevel = static_cast(iLevel); + ++iNum; + break; + case FX_BIDICLASS_S: + case FX_BIDICLASS_B: + if (iNum > 0) + SetDeferredRun(chars, false, i, iNum, 0); + + (*chars)[i].m_iBidiLevel = 0; + iNum = 0; + break; + default: + iNum = 0; + break; + } + iLevel = (*chars)[i].m_iBidiLevel; + } + if (iNum > 0) + SetDeferredRun(chars, false, i, iNum, 0); + } + + size_t ReorderLevel(std::vector* chars, + size_t iCount, + int32_t iBaseLevel, + size_t iStart, + bool bReverse) { + ASSERT(iBaseLevel >= 0 && iBaseLevel <= kBidiMaxLevel); + ASSERT(iStart < iCount); + + if (iCount < 1) + return 0; + + bReverse = bReverse || FX_IsOdd(iBaseLevel); + size_t i = iStart; + for (; i < iCount; ++i) { + int32_t iLevel = (*chars)[i].m_iBidiLevel; + if (iLevel == iBaseLevel) + continue; + if (iLevel < iBaseLevel) + break; + + i += ReorderLevel(chars, iCount, iBaseLevel + 1, i, bReverse) - 1; + } + + size_t iNum = i - iStart; + if (bReverse && iNum > 1) + ReverseString(chars, iStart, iNum); + + return iNum; + } + + void Reorder(std::vector* chars, size_t iCount) { + for (size_t i = 0; i < iCount;) + i += ReorderLevel(chars, iCount, 0, i, false); + } + + void Position(std::vector* chars, size_t iCount) { + for (size_t i = 0; i < iCount; ++i) + (*chars)[(*chars)[i].m_iBidiPos].m_iBidiOrder = i; + } +}; + +#endif // PDF_ENABLE_XFA + +} // namespace + CFX_BidiChar::CFX_BidiChar() : m_CurrentSegment({0, 0, NEUTRAL}), m_LastSegment({0, 0, NEUTRAL}) {} -bool CFX_BidiChar::AppendChar(FX_WCHAR wch) { +bool CFX_BidiChar::AppendChar(wchar_t wch) { uint32_t dwProps = FX_GetUnicodeProperties(wch); int32_t iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS; Direction direction = NEUTRAL; @@ -48,12 +577,12 @@ void CFX_BidiChar::StartNewSegment(CFX_BidiChar::Direction direction) { m_CurrentSegment.direction = direction; } -CFX_BidiString::CFX_BidiString(const CFX_WideString& str) +CFX_BidiString::CFX_BidiString(const WideString& str) : m_Str(str), - m_pBidiChar(new CFX_BidiChar), + m_pBidiChar(pdfium::MakeUnique()), m_eOverallDirection(CFX_BidiChar::LEFT) { - for (int i = 0; i < m_Str.GetLength(); ++i) { - if (m_pBidiChar->AppendChar(m_Str.GetAt(i))) + for (const auto& c : m_Str) { + if (m_pBidiChar->AppendChar(c)) m_Order.push_back(m_pBidiChar->GetSegmentInfo()); } if (m_pBidiChar->EndChar()) @@ -81,3 +610,10 @@ void CFX_BidiString::SetOverallDirectionRight() { m_eOverallDirection = CFX_BidiChar::RIGHT; } } + +#ifdef PDF_ENABLE_XFA +void FX_BidiLine(std::vector* chars, size_t iCount) { + CFX_BidiLine blt; + blt.BidiLine(chars, iCount); +} +#endif // PDF_ENABLE_XFA diff --git a/core/fxcrt/fx_bidi.h b/core/fxcrt/fx_bidi.h index 8d12cc899784159c4e3a96b4e5562d91cc526991..a9b52cf6fbd585d513948e54e139d840282135d0 100644 --- a/core/fxcrt/fx_bidi.h +++ b/core/fxcrt/fx_bidi.h @@ -13,6 +13,10 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#ifdef PDF_ENABLE_XFA +#include "core/fxcrt/cfx_char.h" +#endif // PDF_ENABLE_XFA + // Processes characters and group them into segments based on text direction. class CFX_BidiChar { public: @@ -28,7 +32,7 @@ class CFX_BidiChar { // Append a character and classify it as left, right, or neutral. // Returns true if the character has a different direction than the // existing direction to indicate there is a segment to process. - bool AppendChar(FX_WCHAR wch); + bool AppendChar(wchar_t wch); // Call this after the last character has been appended. AppendChar() // must not be called after this. @@ -50,7 +54,7 @@ class CFX_BidiString { public: using const_iterator = std::vector::const_iterator; - explicit CFX_BidiString(const CFX_WideString& str); + explicit CFX_BidiString(const WideString& str); ~CFX_BidiString(); // Overall direction is always LEFT or RIGHT, never NEUTRAL. @@ -61,15 +65,19 @@ class CFX_BidiString { // Force the overall direction to be R2L regardless of what was detected. void SetOverallDirectionRight(); - FX_WCHAR CharAt(size_t x) const { return m_Str[x]; } + wchar_t CharAt(size_t x) const { return m_Str[x]; } const_iterator begin() const { return m_Order.begin(); } const_iterator end() const { return m_Order.end(); } private: - const CFX_WideString m_Str; + const WideString m_Str; std::unique_ptr m_pBidiChar; std::vector m_Order; CFX_BidiChar::Direction m_eOverallDirection; }; +#if PDF_ENABLE_XFA +void FX_BidiLine(std::vector* chars, size_t iCount); +#endif // PDF_ENABLE_XFA + #endif // CORE_FXCRT_FX_BIDI_H_ diff --git a/core/fxcrt/fx_bidi_unittest.cpp b/core/fxcrt/fx_bidi_unittest.cpp index 2c1996be4610c01471627dc6f943ca922cb71587..ad598a6741d83eb222d041d9e0eb511aa8519b23 100644 --- a/core/fxcrt/fx_bidi_unittest.cpp +++ b/core/fxcrt/fx_bidi_unittest.cpp @@ -7,9 +7,9 @@ namespace { -const FX_WCHAR kNeutralChar = 32; -const FX_WCHAR kLeftChar = 65; -const FX_WCHAR kRightChar = 1424; +const wchar_t kNeutralChar = 32; +const wchar_t kLeftChar = 65; +const wchar_t kRightChar = 1424; } // namespace @@ -126,7 +126,7 @@ TEST(fxcrt, BidiStringEmpty) { TEST(fxcrt, BidiStringAllNeutral) { { - const FX_WCHAR str[] = {kNeutralChar, 0}; + const wchar_t str[] = {kNeutralChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::LEFT, bidi.OverallDirection()); @@ -139,7 +139,7 @@ TEST(fxcrt, BidiStringAllNeutral) { EXPECT_TRUE(it == bidi.end()); } { - const FX_WCHAR str[] = {kNeutralChar, kNeutralChar, kNeutralChar, 0}; + const wchar_t str[] = {kNeutralChar, kNeutralChar, kNeutralChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::LEFT, bidi.OverallDirection()); @@ -155,7 +155,7 @@ TEST(fxcrt, BidiStringAllNeutral) { TEST(fxcrt, BidiStringAllLeft) { { - const FX_WCHAR str[] = {kLeftChar, 0}; + const wchar_t str[] = {kLeftChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::LEFT, bidi.OverallDirection()); @@ -176,7 +176,7 @@ TEST(fxcrt, BidiStringAllLeft) { EXPECT_TRUE(it == bidi.end()); } { - const FX_WCHAR str[] = {kLeftChar, kLeftChar, kLeftChar, 0}; + const wchar_t str[] = {kLeftChar, kLeftChar, kLeftChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::LEFT, bidi.OverallDirection()); @@ -200,7 +200,7 @@ TEST(fxcrt, BidiStringAllLeft) { TEST(fxcrt, BidiStringAllRight) { { - const FX_WCHAR str[] = {kRightChar, 0}; + const wchar_t str[] = {kRightChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::RIGHT, bidi.OverallDirection()); @@ -221,7 +221,7 @@ TEST(fxcrt, BidiStringAllRight) { EXPECT_TRUE(it == bidi.end()); } { - const FX_WCHAR str[] = {kRightChar, kRightChar, kRightChar, 0}; + const wchar_t str[] = {kRightChar, kRightChar, kRightChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::RIGHT, bidi.OverallDirection()); @@ -244,7 +244,7 @@ TEST(fxcrt, BidiStringAllRight) { } TEST(fxcrt, BidiStringLeftNeutralLeftRight) { - const FX_WCHAR str[] = {kLeftChar, kNeutralChar, kLeftChar, kRightChar, 0}; + const wchar_t str[] = {kLeftChar, kNeutralChar, kLeftChar, kRightChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::LEFT, bidi.OverallDirection()); @@ -284,7 +284,7 @@ TEST(fxcrt, BidiStringLeftNeutralLeftRight) { } TEST(fxcrt, BidiStringRightNeutralLeftRight) { - const FX_WCHAR str[] = {kRightChar, kNeutralChar, kLeftChar, kRightChar, 0}; + const wchar_t str[] = {kRightChar, kNeutralChar, kLeftChar, kRightChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::RIGHT, bidi.OverallDirection()); @@ -324,7 +324,7 @@ TEST(fxcrt, BidiStringRightNeutralLeftRight) { } TEST(fxcrt, BidiStringReverse) { - const FX_WCHAR str[] = {kLeftChar, kNeutralChar, kRightChar, kLeftChar, 0}; + const wchar_t str[] = {kLeftChar, kNeutralChar, kRightChar, kLeftChar, 0}; CFX_BidiString bidi(str); EXPECT_EQ(CFX_BidiChar::LEFT, bidi.OverallDirection()); bidi.SetOverallDirectionRight(); diff --git a/core/fxcrt/fx_codepage.h b/core/fxcrt/fx_codepage.h new file mode 100644 index 0000000000000000000000000000000000000000..874f96db7f7c69a2a3aac289543c0308300f64ec --- /dev/null +++ b/core/fxcrt/fx_codepage.h @@ -0,0 +1,91 @@ +// 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 CORE_FXCRT_FX_CODEPAGE_H_ +#define CORE_FXCRT_FX_CODEPAGE_H_ + +#define FX_CODEPAGE_DefANSI 0 +#define FX_CODEPAGE_Symbol 42 +#define FX_CODEPAGE_MSDOS_US 437 +#define FX_CODEPAGE_Arabic_ASMO708 708 +#define FX_CODEPAGE_MSDOS_Greek1 737 +#define FX_CODEPAGE_MSDOS_Baltic 775 +#define FX_CODEPAGE_MSDOS_WesternEuropean 850 +#define FX_CODEPAGE_MSDOS_EasternEuropean 852 +#define FX_CODEPAGE_MSDOS_Cyrillic 855 +#define FX_CODEPAGE_MSDOS_Turkish 857 +#define FX_CODEPAGE_MSDOS_Portuguese 860 +#define FX_CODEPAGE_MSDOS_Icelandic 861 +#define FX_CODEPAGE_MSDOS_Hebrew 862 +#define FX_CODEPAGE_MSDOS_FrenchCanadian 863 +#define FX_CODEPAGE_MSDOS_Arabic 864 +#define FX_CODEPAGE_MSDOS_Norwegian 865 +#define FX_CODEPAGE_MSDOS_Russian 866 +#define FX_CODEPAGE_MSDOS_Greek2 869 +#define FX_CODEPAGE_MSDOS_Thai 874 +#define FX_CODEPAGE_ShiftJIS 932 +#define FX_CODEPAGE_ChineseSimplified 936 +#define FX_CODEPAGE_Hangul 949 +#define FX_CODEPAGE_ChineseTraditional 950 +#define FX_CODEPAGE_UTF16LE 1200 +#define FX_CODEPAGE_UTF16BE 1201 +#define FX_CODEPAGE_MSWin_EasternEuropean 1250 +#define FX_CODEPAGE_MSWin_Cyrillic 1251 +#define FX_CODEPAGE_MSWin_WesternEuropean 1252 +#define FX_CODEPAGE_MSWin_Greek 1253 +#define FX_CODEPAGE_MSWin_Turkish 1254 +#define FX_CODEPAGE_MSWin_Hebrew 1255 +#define FX_CODEPAGE_MSWin_Arabic 1256 +#define FX_CODEPAGE_MSWin_Baltic 1257 +#define FX_CODEPAGE_MSWin_Vietnamese 1258 +#define FX_CODEPAGE_Johab 1361 +#define FX_CODEPAGE_MAC_Roman 10000 +#define FX_CODEPAGE_MAC_ShiftJIS 10001 +#define FX_CODEPAGE_MAC_ChineseTraditional 10002 +#define FX_CODEPAGE_MAC_Korean 10003 +#define FX_CODEPAGE_MAC_Arabic 10004 +#define FX_CODEPAGE_MAC_Hebrew 10005 +#define FX_CODEPAGE_MAC_Greek 10006 +#define FX_CODEPAGE_MAC_Cyrillic 10007 +#define FX_CODEPAGE_MAC_ChineseSimplified 10008 +#define FX_CODEPAGE_MAC_Thai 10021 +#define FX_CODEPAGE_MAC_EasternEuropean 10029 +#define FX_CODEPAGE_MAC_Turkish 10081 +#define FX_CODEPAGE_UTF8 65001 + +#define FX_CHARSET_ANSI 0 +#define FX_CHARSET_Default 1 +#define FX_CHARSET_Symbol 2 +#define FX_CHARSET_MAC_Roman 77 +#define FX_CHARSET_MAC_ShiftJIS 78 +#define FX_CHARSET_MAC_Korean 79 +#define FX_CHARSET_MAC_ChineseSimplified 80 +#define FX_CHARSET_MAC_ChineseTraditional 81 +#define FX_CHARSET_MAC_Hebrew 83 +#define FX_CHARSET_MAC_Arabic 84 +#define FX_CHARSET_MAC_Greek 85 +#define FX_CHARSET_MAC_Turkish 86 +#define FX_CHARSET_MAC_Thai 87 +#define FX_CHARSET_MAC_EasternEuropean 88 +#define FX_CHARSET_MAC_Cyrillic 89 +#define FX_CHARSET_ShiftJIS 128 +#define FX_CHARSET_Hangul 129 +#define FX_CHARSET_Johab 130 +#define FX_CHARSET_ChineseSimplified 134 +#define FX_CHARSET_ChineseTraditional 136 +#define FX_CHARSET_MSWin_Greek 161 +#define FX_CHARSET_MSWin_Turkish 162 +#define FX_CHARSET_MSWin_Vietnamese 163 +#define FX_CHARSET_MSWin_Hebrew 177 +#define FX_CHARSET_MSWin_Arabic 178 +#define FX_CHARSET_MSWin_Baltic 186 +#define FX_CHARSET_MSWin_Cyrillic 204 +#define FX_CHARSET_Thai 222 +#define FX_CHARSET_MSWin_EasternEuropean 238 +#define FX_CHARSET_US 254 +#define FX_CHARSET_OEM 255 + +#endif // CORE_FXCRT_FX_CODEPAGE_H_ diff --git a/core/fxcrt/fx_coordinates.cpp b/core/fxcrt/fx_coordinates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac13a323291ed44bbf5653b52f2b0c31ed1f6e57 --- /dev/null +++ b/core/fxcrt/fx_coordinates.cpp @@ -0,0 +1,392 @@ +// 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 "core/fxcrt/fx_coordinates.h" + +#include +#include + +#include "core/fxcrt/fx_extension.h" + +namespace { + +void MatchFloatRange(float f1, float f2, int* i1, int* i2) { + int length = static_cast(ceil(f2 - f1)); + int i1_1 = static_cast(floor(f1)); + int i1_2 = static_cast(ceil(f1)); + float error1 = f1 - i1_1 + fabsf(f2 - i1_1 - length); + float error2 = i1_2 - f1 + fabsf(f2 - i1_2 - length); + + *i1 = error1 > error2 ? i1_2 : i1_1; + *i2 = *i1 + length; +} + +} // namespace + +void FX_RECT::Normalize() { + if (left > right) + std::swap(left, right); + if (top > bottom) + std::swap(top, bottom); +} + +void FX_RECT::Intersect(const FX_RECT& src) { + FX_RECT src_n = src; + src_n.Normalize(); + Normalize(); + left = std::max(left, src_n.left); + top = std::max(top, src_n.top); + right = std::min(right, src_n.right); + bottom = std::min(bottom, src_n.bottom); + if (left > right || top > bottom) { + left = top = right = bottom = 0; + } +} + +CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect) { + left = rect.left; + top = rect.bottom; + right = rect.right; + bottom = rect.top; +} + +// static +CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_PointF* pPoints, int nPoints) { + if (nPoints == 0) + return CFX_FloatRect(); + + float min_x = pPoints->x; + float max_x = pPoints->x; + float min_y = pPoints->y; + float max_y = pPoints->y; + for (int i = 1; i < nPoints; i++) { + min_x = std::min(min_x, pPoints[i].x); + max_x = std::max(max_x, pPoints[i].x); + min_y = std::min(min_y, pPoints[i].y); + max_y = std::max(max_y, pPoints[i].y); + } + return CFX_FloatRect(min_x, min_y, max_x, max_y); +} + +void CFX_FloatRect::Normalize() { + if (left > right) + std::swap(left, right); + if (bottom > top) + std::swap(top, bottom); +} + +void CFX_FloatRect::Reset() { + left = 0.0f; + right = 0.0f; + bottom = 0.0f; + top = 0.0f; +} + +void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect) { + Normalize(); + CFX_FloatRect other = other_rect; + other.Normalize(); + left = std::max(left, other.left); + bottom = std::max(bottom, other.bottom); + right = std::min(right, other.right); + top = std::min(top, other.top); + if (left > right || bottom > top) + Reset(); +} + +void CFX_FloatRect::Union(const CFX_FloatRect& other_rect) { + Normalize(); + CFX_FloatRect other = other_rect; + other.Normalize(); + left = std::min(left, other.left); + bottom = std::min(bottom, other.bottom); + right = std::max(right, other.right); + top = std::max(top, other.top); +} + +FX_RECT CFX_FloatRect::GetOuterRect() const { + FX_RECT rect; + rect.left = static_cast(floor(left)); + rect.bottom = static_cast(ceil(top)); + rect.right = static_cast(ceil(right)); + rect.top = static_cast(floor(bottom)); + rect.Normalize(); + return rect; +} + +FX_RECT CFX_FloatRect::GetInnerRect() const { + FX_RECT rect; + rect.left = static_cast(ceil(left)); + rect.bottom = static_cast(floor(top)); + rect.right = static_cast(floor(right)); + rect.top = static_cast(ceil(bottom)); + rect.Normalize(); + return rect; +} + +FX_RECT CFX_FloatRect::GetClosestRect() const { + FX_RECT rect; + MatchFloatRange(left, right, &rect.left, &rect.right); + MatchFloatRange(bottom, top, &rect.top, &rect.bottom); + rect.Normalize(); + return rect; +} + +CFX_FloatRect CFX_FloatRect::GetCenterSquare() const { + float fWidth = right - left; + float fHeight = top - bottom; + float fHalfWidth = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2; + + float fCenterX = (left + right) / 2.0f; + float fCenterY = (top + bottom) / 2.0f; + return CFX_FloatRect(fCenterX - fHalfWidth, fCenterY - fHalfWidth, + fCenterX + fHalfWidth, fCenterY + fHalfWidth); +} + +bool CFX_FloatRect::Contains(const CFX_PointF& point) const { + CFX_FloatRect n1(*this); + n1.Normalize(); + return point.x <= n1.right && point.x >= n1.left && point.y <= n1.top && + point.y >= n1.bottom; +} + +bool CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const { + CFX_FloatRect n1(*this); + CFX_FloatRect n2(other_rect); + n1.Normalize(); + n2.Normalize(); + return n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom && + n2.top <= n1.top; +} + +void CFX_FloatRect::UpdateRect(const CFX_PointF& point) { + left = std::min(left, point.x); + bottom = std::min(bottom, point.y); + right = std::max(right, point.x); + top = std::max(top, point.y); +} + +void CFX_FloatRect::Scale(float fScale) { + left *= fScale; + bottom *= fScale; + right *= fScale; + top *= fScale; +} + +void CFX_FloatRect::ScaleFromCenterPoint(float fScale) { + float fHalfWidth = (right - left) / 2.0f; + float fHalfHeight = (top - bottom) / 2.0f; + + float center_x = (left + right) / 2; + float center_y = (top + bottom) / 2; + + left = center_x - fHalfWidth * fScale; + bottom = center_y - fHalfHeight * fScale; + right = center_x + fHalfWidth * fScale; + top = center_y + fHalfHeight * fScale; +} + +FX_RECT CFX_FloatRect::ToFxRect() const { + return FX_RECT(static_cast(left), static_cast(top), + static_cast(right), static_cast(bottom)); +} + +FX_RECT CFX_FloatRect::ToRoundedFxRect() const { + return FX_RECT(FXSYS_round(left), FXSYS_round(top), FXSYS_round(right), + FXSYS_round(bottom)); +} + +#ifndef NDEBUG +std::ostream& operator<<(std::ostream& os, const CFX_FloatRect& rect) { + os << "rect[" << rect.Width() << "x" << rect.Height() << " (" << rect.left + << ", " << rect.bottom << ")]"; + return os; +} +#endif + +CFX_Matrix CFX_Matrix::GetInverse() const { + CFX_Matrix inverse; + float i = a * d - b * c; + if (fabs(i) == 0) + return inverse; + + float j = -i; + inverse.a = d / i; + inverse.b = b / j; + inverse.c = c / j; + inverse.d = a / i; + inverse.e = (c * f - d * e) / i; + inverse.f = (a * f - b * e) / j; + return inverse; +} + +void CFX_Matrix::Concat(const CFX_Matrix& m, bool bPrepended) { + ConcatInternal(m, bPrepended); +} + +void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, bool bPrepended) { + Concat(src.GetInverse(), bPrepended); +} + +bool CFX_Matrix::Is90Rotated() const { + return fabs(a * 1000) < fabs(b) && fabs(d * 1000) < fabs(c); +} + +bool CFX_Matrix::IsScaled() const { + return fabs(b * 1000) < fabs(a) && fabs(c * 1000) < fabs(d); +} + +void CFX_Matrix::Translate(float x, float y, bool bPrepended) { + if (bPrepended) { + e += x * a + y * c; + f += y * d + x * b; + return; + } + e += x; + f += y; +} + +void CFX_Matrix::Scale(float sx, float sy, bool bPrepended) { + a *= sx; + d *= sy; + if (bPrepended) { + b *= sx; + c *= sy; + return; + } + + b *= sy; + c *= sx; + e *= sx; + f *= sy; +} + +void CFX_Matrix::Rotate(float fRadian, bool bPrepended) { + float cosValue = cos(fRadian); + float sinValue = sin(fRadian); + ConcatInternal(CFX_Matrix(cosValue, sinValue, -sinValue, cosValue, 0, 0), + bPrepended); +} + +void CFX_Matrix::RotateAt(float fRadian, float dx, float dy, bool bPrepended) { + Translate(dx, dy, bPrepended); + Rotate(fRadian, bPrepended); + Translate(-dx, -dy, bPrepended); +} + +void CFX_Matrix::Shear(float fAlphaRadian, float fBetaRadian, bool bPrepended) { + ConcatInternal(CFX_Matrix(1, tan(fAlphaRadian), tan(fBetaRadian), 1, 0, 0), + bPrepended); +} + +void CFX_Matrix::MatchRect(const CFX_FloatRect& dest, + const CFX_FloatRect& src) { + float fDiff = src.left - src.right; + a = fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff; + + fDiff = src.bottom - src.top; + d = fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff; + e = dest.left - src.left * a; + f = dest.bottom - src.bottom * d; + b = 0; + c = 0; +} + +float CFX_Matrix::GetXUnit() const { + if (b == 0) + return (a > 0 ? a : -a); + if (a == 0) + return (b > 0 ? b : -b); + return sqrt(a * a + b * b); +} + +float CFX_Matrix::GetYUnit() const { + if (c == 0) + return (d > 0 ? d : -d); + if (d == 0) + return (c > 0 ? c : -c); + return sqrt(c * c + d * d); +} + +CFX_FloatRect CFX_Matrix::GetUnitRect() const { + return TransformRect(CFX_FloatRect(0.f, 0.f, 1.f, 1.f)); +} + +float CFX_Matrix::TransformXDistance(float dx) const { + float fx = a * dx; + float fy = b * dx; + return sqrt(fx * fx + fy * fy); +} + +float CFX_Matrix::TransformDistance(float distance) const { + return distance * (GetXUnit() + GetYUnit()) / 2; +} + +CFX_PointF CFX_Matrix::Transform(const CFX_PointF& point) const { + return CFX_PointF(a * point.x + c * point.y + e, + b * point.x + d * point.y + f); +} +std::tuple CFX_Matrix::TransformRect( + const float& left, + const float& right, + const float& top, + const float& bottom) const { + CFX_PointF points[] = { + {left, top}, {left, bottom}, {right, top}, {right, bottom}}; + for (int i = 0; i < 4; i++) + points[i] = Transform(points[i]); + + float new_right = points[0].x; + float new_left = points[0].x; + float new_top = points[0].y; + float new_bottom = points[0].y; + for (int i = 1; i < 4; i++) { + new_right = std::max(new_right, points[i].x); + new_left = std::min(new_left, points[i].x); + new_top = std::max(new_top, points[i].y); + new_bottom = std::min(new_bottom, points[i].y); + } + return std::make_tuple(new_left, new_right, new_top, new_bottom); +} + +CFX_RectF CFX_Matrix::TransformRect(const CFX_RectF& rect) const { + float left; + float right; + float bottom; + float top; + std::tie(left, right, bottom, top) = + TransformRect(rect.left, rect.right(), rect.bottom(), rect.top); + return CFX_RectF(left, top, right - left, bottom - top); +} + +CFX_FloatRect CFX_Matrix::TransformRect(const CFX_FloatRect& rect) const { + float left; + float right; + float top; + float bottom; + std::tie(left, right, top, bottom) = + TransformRect(rect.left, rect.right, rect.top, rect.bottom); + return CFX_FloatRect(left, bottom, right, top); +} + +void CFX_Matrix::ConcatInternal(const CFX_Matrix& other, bool prepend) { + CFX_Matrix left; + CFX_Matrix right; + if (prepend) { + left = other; + right = *this; + } else { + left = *this; + right = other; + } + + a = left.a * right.a + left.b * right.c; + b = left.a * right.b + left.b * right.d; + c = left.c * right.a + left.d * right.c; + d = left.c * right.b + left.d * right.d; + e = left.e * right.a + left.f * right.c + right.e; + f = left.e * right.b + left.f * right.d + right.f; +} diff --git a/core/fxcrt/fx_coordinates.h b/core/fxcrt/fx_coordinates.h index 2c84d0776ced42101c8c4eb47c13a742ebdcac21..69d16d1c550ded5a3923606eb1b3baa77a46fc7d 100644 --- a/core/fxcrt/fx_coordinates.h +++ b/core/fxcrt/fx_coordinates.h @@ -7,7 +7,11 @@ #ifndef CORE_FXCRT_FX_COORDINATES_H_ #define CORE_FXCRT_FX_COORDINATES_H_ -#include "core/fxcrt/fx_basic.h" +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "third_party/base/numerics/safe_math.h" class CFX_Matrix; @@ -17,10 +21,7 @@ class CFX_PTemplate { CFX_PTemplate() : x(0), y(0) {} CFX_PTemplate(BaseType new_x, BaseType new_y) : x(new_x), y(new_y) {} CFX_PTemplate(const CFX_PTemplate& other) : x(other.x), y(other.y) {} - void clear() { - x = 0; - y = 0; - } + CFX_PTemplate operator=(const CFX_PTemplate& other) { if (this != &other) { x = other.x; @@ -44,34 +45,18 @@ class CFX_PTemplate { y -= obj.y; return *this; } - CFX_PTemplate& operator*=(BaseType factor) { - x *= factor; - y *= factor; - return *this; - } - CFX_PTemplate& operator/=(BaseType divisor) { - x /= divisor; - y /= divisor; - return *this; - } CFX_PTemplate operator+(const CFX_PTemplate& other) const { return CFX_PTemplate(x + other.x, y + other.y); } CFX_PTemplate operator-(const CFX_PTemplate& other) const { return CFX_PTemplate(x - other.x, y - other.y); } - CFX_PTemplate operator*(BaseType factor) const { - return CFX_PTemplate(x * factor, y * factor); - } - CFX_PTemplate operator/(BaseType divisor) const { - return CFX_PTemplate(x / divisor, y / divisor); - } BaseType x; BaseType y; }; using CFX_Point = CFX_PTemplate; -using CFX_PointF = CFX_PTemplate; +using CFX_PointF = CFX_PTemplate; template class CFX_STemplate { @@ -144,7 +129,7 @@ class CFX_STemplate { BaseType height; }; using CFX_Size = CFX_STemplate; -using CFX_SizeF = CFX_STemplate; +using CFX_SizeF = CFX_STemplate; template class CFX_VTemplate : public CFX_PTemplate { @@ -162,9 +147,9 @@ class CFX_VTemplate : public CFX_PTemplate { const CFX_PTemplate& point2) : CFX_PTemplate(point2.x - point1.x, point2.y - point1.y) {} - FX_FLOAT Length() const { return FXSYS_sqrt(x * x + y * y); } + float Length() const { return sqrt(x * x + y * y); } void Normalize() { - FX_FLOAT fLen = Length(); + float fLen = Length(); if (fLen < 0.0001f) return; @@ -179,19 +164,203 @@ class CFX_VTemplate : public CFX_PTemplate { x *= sx; y *= sy; } - void Rotate(FX_FLOAT fRadian) { - FX_FLOAT cosValue = FXSYS_cos(fRadian); - FX_FLOAT sinValue = FXSYS_sin(fRadian); + void Rotate(float fRadian) { + float cosValue = cos(fRadian); + float sinValue = sin(fRadian); x = x * cosValue - y * sinValue; y = x * sinValue + y * cosValue; } }; using CFX_Vector = CFX_VTemplate; -using CFX_VectorF = CFX_VTemplate; +using CFX_VectorF = CFX_VTemplate; // Rectangles. // TODO(tsepez): Consolidate all these different rectangle classes. +// LTRB rectangles (y-axis runs downwards). +struct FX_RECT { + FX_RECT() : left(0), top(0), right(0), bottom(0) {} + FX_RECT(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} + + int Width() const { return right - left; } + int Height() const { return bottom - top; } + bool IsEmpty() const { return right <= left || bottom <= top; } + + bool Valid() const { + pdfium::base::CheckedNumeric w = right; + pdfium::base::CheckedNumeric h = bottom; + w -= left; + h -= top; + return w.IsValid() && h.IsValid(); + } + + void Normalize(); + + void Intersect(const FX_RECT& src); + void Intersect(int l, int t, int r, int b) { Intersect(FX_RECT(l, t, r, b)); } + + void Offset(int dx, int dy) { + left += dx; + right += dx; + top += dy; + bottom += dy; + } + + bool operator==(const FX_RECT& src) const { + return left == src.left && right == src.right && top == src.top && + bottom == src.bottom; + } + + bool Contains(int x, int y) const { + return x >= left && x < right && y >= top && y < bottom; + } + + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +}; + +// LTRB rectangles (y-axis runs upwards). +class CFX_FloatRect { + public: + CFX_FloatRect() : CFX_FloatRect(0.0f, 0.0f, 0.0f, 0.0f) {} + CFX_FloatRect(float l, float b, float r, float t) + : left(l), bottom(b), right(r), top(t) {} + + explicit CFX_FloatRect(const float* pArray) + : CFX_FloatRect(pArray[0], pArray[1], pArray[2], pArray[3]) {} + + explicit CFX_FloatRect(const FX_RECT& rect); + + static CFX_FloatRect GetBBox(const CFX_PointF* pPoints, int nPoints); + + void Normalize(); + + void Reset(); + + bool IsEmpty() const { return left >= right || bottom >= top; } + + bool Contains(const CFX_PointF& point) const; + bool Contains(const CFX_FloatRect& other_rect) const; + + void Intersect(const CFX_FloatRect& other_rect); + void Union(const CFX_FloatRect& other_rect); + + // These may be better at rounding than ToFxRect() and friends. + // + // Returned rect has bounds rounded up/down such that it is contained in the + // original. + FX_RECT GetInnerRect() const; + + // Returned rect has bounds rounded up/down such that the original is + // contained in it. + FX_RECT GetOuterRect() const; + + // Returned rect has bounds rounded up/down such that the dimensions are + // rounded up and the sum of the error in the bounds is minimized. + FX_RECT GetClosestRect() const; + + CFX_FloatRect GetCenterSquare() const; + + void InitRect(const CFX_PointF& point) { + left = point.x; + right = point.x; + bottom = point.y; + top = point.y; + } + void UpdateRect(const CFX_PointF& point); + + float Width() const { return right - left; } + float Height() const { return top - bottom; } + + void Inflate(float x, float y) { + Normalize(); + left -= x; + right += x; + bottom -= y; + top += y; + } + + void Inflate(float other_left, + float other_bottom, + float other_right, + float other_top) { + Normalize(); + left -= other_left; + bottom -= other_bottom; + right += other_right; + top += other_top; + } + + void Inflate(const CFX_FloatRect& rt) { + Inflate(rt.left, rt.bottom, rt.right, rt.top); + } + + void Deflate(float x, float y) { + Normalize(); + left += x; + right -= x; + bottom += y; + top -= y; + } + + void Deflate(float other_left, + float other_bottom, + float other_right, + float other_top) { + Normalize(); + left += other_left; + bottom += other_bottom; + right -= other_right; + top -= other_top; + } + + void Deflate(const CFX_FloatRect& rt) { + Deflate(rt.left, rt.bottom, rt.right, rt.top); + } + + CFX_FloatRect GetDeflated(float x, float y) const { + if (IsEmpty()) + return CFX_FloatRect(); + + CFX_FloatRect that = *this; + that.Deflate(x, y); + that.Normalize(); + return that; + } + + void Translate(float e, float f) { + left += e; + right += e; + top += f; + bottom += f; + } + + void Scale(float fScale); + void ScaleFromCenterPoint(float fScale); + + // GetInnerRect() and friends may be better at rounding than these methods. + // Unlike the methods above, these two blindly floor / round the LBRT values. + // Doing so may introduce rounding errors that are visible to users as + // off-by-one pixels/lines. + // + // Floors LBRT values. + FX_RECT ToFxRect() const; + + // Rounds LBRT values. + FX_RECT ToRoundedFxRect() const; + + float left; + float bottom; + float right; + float top; +}; + +#ifndef NDEBUG +std::ostream& operator<<(std::ostream& os, const CFX_FloatRect& rect); +#endif + // LTWH rectangles (y-axis runs downwards). template class CFX_RTemplate { @@ -228,6 +397,12 @@ class CFX_RTemplate { Normalize(); } + explicit CFX_RTemplate(const CFX_FloatRect& r) + : left(static_cast(r.left)), + top(static_cast(r.top)), + width(static_cast(r.Width())), + height(static_cast(r.Height())) {} + // NOLINTNEXTLINE(runtime/explicit) CFX_RTemplate(const RectType& other) : left(other.left), @@ -313,7 +488,7 @@ class CFX_RTemplate { Deflate(rt.left, rt.top, rt.top + rt.width, rt.top + rt.height); } bool IsEmpty() const { return width <= 0 || height <= 0; } - bool IsEmpty(FX_FLOAT fEpsilon) const { + bool IsEmpty(float fEpsilon) const { return width <= fEpsilon || height <= fEpsilon; } void Empty() { width = height = 0; } @@ -340,14 +515,12 @@ class CFX_RTemplate { void Union(BaseType x, BaseType y) { BaseType r = right(); BaseType b = bottom(); - if (left > x) - left = x; - if (r < x) - r = x; - if (top > y) - top = y; - if (b < y) - b = y; + + left = std::min(left, x); + top = std::min(top, y); + r = std::max(r, x); + b = std::max(b, y); + width = r - left; height = b - top; } @@ -355,28 +528,24 @@ class CFX_RTemplate { void Union(const RectType& rt) { BaseType r = right(); BaseType b = bottom(); - if (left > rt.left) - left = rt.left; - if (r < rt.right()) - r = rt.right(); - if (top > rt.top) - top = rt.top; - if (b < rt.bottom()) - b = rt.bottom(); + + left = std::min(left, rt.left); + top = std::min(top, rt.top); + r = std::max(r, rt.right()); + b = std::max(b, rt.bottom()); + width = r - left; height = b - top; } void Intersect(const RectType& rt) { BaseType r = right(); BaseType b = bottom(); - if (left < rt.left) - left = rt.left; - if (r > rt.right()) - r = rt.right(); - if (top < rt.top) - top = rt.top; - if (b > rt.bottom()) - b = rt.bottom(); + + left = std::max(left, rt.left); + top = std::max(top, rt.top); + r = std::min(r, rt.right()); + b = std::min(b, rt.bottom()); + width = r - left; height = b - top; } @@ -385,7 +554,7 @@ class CFX_RTemplate { rect.Intersect(*this); return !rect.IsEmpty(); } - bool IntersectWith(const RectType& rt, FX_FLOAT fEpsilon) const { + bool IntersectWith(const RectType& rt, float fEpsilon) const { RectType rect = rt; rect.Intersect(*this); return !rect.IsEmpty(fEpsilon); @@ -398,195 +567,36 @@ class CFX_RTemplate { return !(rc1 == rc2); } + CFX_FloatRect ToFloatRect() const { + // Note, we flip top/bottom here because the CFX_FloatRect has the + // y-axis running in the opposite direction. + return CFX_FloatRect(left, top, right(), bottom()); + } + BaseType left; BaseType top; BaseType width; BaseType height; }; using CFX_Rect = CFX_RTemplate; -using CFX_RectF = CFX_RTemplate; - -// LTRB rectangles (y-axis runs downwards). -struct FX_RECT { - FX_RECT() : left(0), top(0), right(0), bottom(0) {} - FX_RECT(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} - - int Width() const { return right - left; } - int Height() const { return bottom - top; } - bool IsEmpty() const { return right <= left || bottom <= top; } - - bool Valid() const { - pdfium::base::CheckedNumeric w = right; - pdfium::base::CheckedNumeric h = bottom; - w -= left; - h -= top; - return w.IsValid() && h.IsValid(); - } - - void Normalize(); - - void Intersect(const FX_RECT& src); - void Intersect(int l, int t, int r, int b) { Intersect(FX_RECT(l, t, r, b)); } - - void Offset(int dx, int dy) { - left += dx; - right += dx; - top += dy; - bottom += dy; - } - - bool operator==(const FX_RECT& src) const { - return left == src.left && right == src.right && top == src.top && - bottom == src.bottom; - } - - bool Contains(int x, int y) const { - return x >= left && x < right && y >= top && y < bottom; - } - - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; -}; - -// LTRB rectangles (y-axis runs upwards). -class CFX_FloatRect { - public: - CFX_FloatRect() : CFX_FloatRect(0.0f, 0.0f, 0.0f, 0.0f) {} - CFX_FloatRect(FX_FLOAT l, FX_FLOAT b, FX_FLOAT r, FX_FLOAT t) - : left(l), bottom(b), right(r), top(t) {} - - explicit CFX_FloatRect(const FX_FLOAT* pArray) - : CFX_FloatRect(pArray[0], pArray[1], pArray[2], pArray[3]) {} - - explicit CFX_FloatRect(const FX_RECT& rect); - - void Normalize(); - - void Reset() { - left = 0.0f; - right = 0.0f; - bottom = 0.0f; - top = 0.0f; - } - - bool IsEmpty() const { return left >= right || bottom >= top; } - - bool Contains(const CFX_PointF& point) const; - bool Contains(const CFX_FloatRect& other_rect) const; - - void Intersect(const CFX_FloatRect& other_rect); - void Union(const CFX_FloatRect& other_rect); - - FX_RECT GetInnerRect() const; - FX_RECT GetOuterRect() const; - FX_RECT GetClosestRect() const; - - int Substract4(CFX_FloatRect& substract_rect, CFX_FloatRect* pRects); - - void InitRect(FX_FLOAT x, FX_FLOAT y) { - left = x; - right = x; - bottom = y; - top = y; - } - void UpdateRect(FX_FLOAT x, FX_FLOAT y); - - FX_FLOAT Width() const { return right - left; } - FX_FLOAT Height() const { return top - bottom; } - - void Inflate(FX_FLOAT x, FX_FLOAT y) { - Normalize(); - left -= x; - right += x; - bottom -= y; - top += y; - } - - void Inflate(FX_FLOAT other_left, - FX_FLOAT other_bottom, - FX_FLOAT other_right, - FX_FLOAT other_top) { - Normalize(); - left -= other_left; - bottom -= other_bottom; - right += other_right; - top += other_top; - } - - void Inflate(const CFX_FloatRect& rt) { - Inflate(rt.left, rt.bottom, rt.right, rt.top); - } - - void Deflate(FX_FLOAT x, FX_FLOAT y) { - Normalize(); - left += x; - right -= x; - bottom += y; - top -= y; - } - - void Deflate(FX_FLOAT other_left, - FX_FLOAT other_bottom, - FX_FLOAT other_right, - FX_FLOAT other_top) { - Normalize(); - left += other_left; - bottom += other_bottom; - right -= other_right; - top -= other_top; - } - - void Deflate(const CFX_FloatRect& rt) { - Deflate(rt.left, rt.bottom, rt.right, rt.top); - } - - void Translate(FX_FLOAT e, FX_FLOAT f) { - left += e; - right += e; - top += f; - bottom += f; - } - - static CFX_FloatRect GetBBox(const CFX_PointF* pPoints, int nPoints); - - FX_RECT ToFxRect() const { - return FX_RECT(static_cast(left), static_cast(top), - static_cast(right), static_cast(bottom)); - } - - static CFX_FloatRect FromCFXRectF(const CFX_RectF& rect) { - return CFX_FloatRect(rect.left, rect.top, rect.right(), rect.bottom()); - } - - FX_FLOAT left; - FX_FLOAT bottom; - FX_FLOAT right; - FX_FLOAT top; -}; - +using CFX_RectF = CFX_RTemplate; + +// The matrix is of the form: +// | a b 0 | +// | c d 0 | +// | e f 1 | +// See PDF spec 1.7 Section 4.2.3. +// class CFX_Matrix { public: CFX_Matrix() { SetIdentity(); } - explicit CFX_Matrix(const FX_FLOAT n[6]) + explicit CFX_Matrix(const float n[6]) : a(n[0]), b(n[1]), c(n[2]), d(n[3]), e(n[4]), f(n[5]) {} - CFX_Matrix(const CFX_Matrix& other) - : a(other.a), - b(other.b), - c(other.c), - d(other.d), - e(other.e), - f(other.f) {} - - CFX_Matrix(FX_FLOAT a1, - FX_FLOAT b1, - FX_FLOAT c1, - FX_FLOAT d1, - FX_FLOAT e1, - FX_FLOAT f1) + CFX_Matrix(const CFX_Matrix& other) = default; + + CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1) : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1) {} void operator=(const CFX_Matrix& other) { @@ -607,7 +617,7 @@ class CFX_Matrix { f = 0; } - void SetReverse(const CFX_Matrix& m); + CFX_Matrix GetInverse() const; void Concat(const CFX_Matrix& m, bool bPrepended = false); void ConcatInverse(const CFX_Matrix& m, bool bPrepended = false); @@ -620,49 +630,42 @@ class CFX_Matrix { bool IsScaled() const; bool WillScale() const { return a != 1.0f || b != 0 || c != 0 || d != 1.0f; } - void Translate(FX_FLOAT x, FX_FLOAT y, bool bPrepended = false); + void Translate(float x, float y, bool bPrepended = false); void Translate(int32_t x, int32_t y, bool bPrepended = false) { - Translate(static_cast(x), static_cast(y), bPrepended); + Translate(static_cast(x), static_cast(y), bPrepended); } - void Scale(FX_FLOAT sx, FX_FLOAT sy, bool bPrepended = false); - void Rotate(FX_FLOAT fRadian, bool bPrepended = false); - void RotateAt(FX_FLOAT fRadian, - FX_FLOAT x, - FX_FLOAT y, - bool bPrepended = false); + void Scale(float sx, float sy, bool bPrepended = false); + void Rotate(float fRadian, bool bPrepended = false); + void RotateAt(float fRadian, float x, float y, bool bPrepended = false); - void Shear(FX_FLOAT fAlphaRadian, - FX_FLOAT fBetaRadian, - bool bPrepended = false); + void Shear(float fAlphaRadian, float fBetaRadian, bool bPrepended = false); void MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src); - FX_FLOAT GetXUnit() const; - FX_FLOAT GetYUnit() const; + float GetXUnit() const; + float GetYUnit() const; CFX_FloatRect GetUnitRect() const; - FX_FLOAT TransformXDistance(FX_FLOAT dx) const; - FX_FLOAT TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const; - FX_FLOAT TransformDistance(FX_FLOAT distance) const; + float TransformXDistance(float dx) const; + float TransformDistance(float distance) const; CFX_PointF Transform(const CFX_PointF& point) const; - void TransformRect(CFX_RectF& rect) const; - void TransformRect(FX_FLOAT& left, - FX_FLOAT& right, - FX_FLOAT& top, - FX_FLOAT& bottom) const; - void TransformRect(CFX_FloatRect& rect) const { - TransformRect(rect.left, rect.right, rect.top, rect.bottom); - } - - FX_FLOAT a; - FX_FLOAT b; - FX_FLOAT c; - FX_FLOAT d; - FX_FLOAT e; - FX_FLOAT f; + std::tuple TransformRect( + const float& left, + const float& right, + const float& top, + const float& bottom) const; + CFX_RectF TransformRect(const CFX_RectF& rect) const; + CFX_FloatRect TransformRect(const CFX_FloatRect& rect) const; + + float a; + float b; + float c; + float d; + float e; + float f; private: void ConcatInternal(const CFX_Matrix& other, bool prepend); diff --git a/core/fxcrt/fx_coordinates_unittest.cpp b/core/fxcrt/fx_coordinates_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3368a40e18d8e383a9ff38686e12f8b01017ba4c --- /dev/null +++ b/core/fxcrt/fx_coordinates_unittest.cpp @@ -0,0 +1,291 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/fx_coordinates.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" + +TEST(CFX_FloatRect, GetBBox) { + CFX_FloatRect rect = CFX_FloatRect::GetBBox(nullptr, 0); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + + std::vector data; + data.emplace_back(0.0f, 0.0f); + rect = CFX_FloatRect::GetBBox(data.data(), 0); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect = CFX_FloatRect::GetBBox(data.data(), data.size()); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + + data.emplace_back(2.5f, 6.2f); + data.emplace_back(1.5f, 6.2f); + rect = CFX_FloatRect::GetBBox(data.data(), 2); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(2.5f, rect.right); + EXPECT_FLOAT_EQ(6.2f, rect.top); + + rect = CFX_FloatRect::GetBBox(data.data(), data.size()); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(2.5f, rect.right); + EXPECT_FLOAT_EQ(6.2f, rect.top); + + data.emplace_back(2.5f, 6.3f); + rect = CFX_FloatRect::GetBBox(data.data(), data.size()); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(2.5f, rect.right); + EXPECT_FLOAT_EQ(6.3f, rect.top); + + data.emplace_back(-3.0f, 6.3f); + rect = CFX_FloatRect::GetBBox(data.data(), data.size()); + EXPECT_FLOAT_EQ(-3.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(2.5f, rect.right); + EXPECT_FLOAT_EQ(6.3f, rect.top); + + data.emplace_back(4.0f, -8.0f); + rect = CFX_FloatRect::GetBBox(data.data(), data.size()); + EXPECT_FLOAT_EQ(-3.0f, rect.left); + EXPECT_FLOAT_EQ(-8.0f, rect.bottom); + EXPECT_FLOAT_EQ(4.0f, rect.right); + EXPECT_FLOAT_EQ(6.3f, rect.top); +} + +TEST(CFX_FloatRect, Normalize) { + CFX_FloatRect rect; + rect.Normalize(); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + + rect = CFX_FloatRect(-1.0f, -3.0f, 4.5f, 3.2f); + rect.Normalize(); + EXPECT_FLOAT_EQ(-1.0f, rect.left); + EXPECT_FLOAT_EQ(-3.0f, rect.bottom); + EXPECT_FLOAT_EQ(4.5f, rect.right); + EXPECT_FLOAT_EQ(3.2f, rect.top); + rect.Scale(-1.0f); + rect.Normalize(); + EXPECT_FLOAT_EQ(-4.5f, rect.left); + EXPECT_FLOAT_EQ(-3.2f, rect.bottom); + EXPECT_FLOAT_EQ(1.0f, rect.right); + EXPECT_FLOAT_EQ(3.0f, rect.top); +} + +TEST(CFX_FloatRect, Scale) { + CFX_FloatRect rect(-1.0f, -3.0f, 4.5f, 3.2f); + rect.Scale(1.0f); + EXPECT_FLOAT_EQ(-1.0f, rect.left); + EXPECT_FLOAT_EQ(-3.0f, rect.bottom); + EXPECT_FLOAT_EQ(4.5f, rect.right); + EXPECT_FLOAT_EQ(3.2f, rect.top); + rect.Scale(0.5f); + EXPECT_FLOAT_EQ(-0.5, rect.left); + EXPECT_FLOAT_EQ(-1.5, rect.bottom); + EXPECT_FLOAT_EQ(2.25f, rect.right); + EXPECT_FLOAT_EQ(1.6f, rect.top); + rect.Scale(2.0f); + EXPECT_FLOAT_EQ(-1.0f, rect.left); + EXPECT_FLOAT_EQ(-3.0f, rect.bottom); + EXPECT_FLOAT_EQ(4.5f, rect.right); + EXPECT_FLOAT_EQ(3.2f, rect.top); + rect.Scale(-1.0f); + EXPECT_FLOAT_EQ(1.0f, rect.left); + EXPECT_FLOAT_EQ(3.0f, rect.bottom); + EXPECT_FLOAT_EQ(-4.5f, rect.right); + EXPECT_FLOAT_EQ(-3.2f, rect.top); + rect.Scale(0.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); +} + +TEST(CFX_FloatRect, ScaleEmpty) { + CFX_FloatRect rect; + rect.Scale(1.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect.Scale(0.5f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect.Scale(2.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect.Scale(0.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); +} + +TEST(CFX_FloatRect, ScaleFromCenterPoint) { + CFX_FloatRect rect(-1.0f, -3.0f, 4.5f, 3.2f); + rect.ScaleFromCenterPoint(1.0f); + EXPECT_FLOAT_EQ(-1.0f, rect.left); + EXPECT_FLOAT_EQ(-3.0f, rect.bottom); + EXPECT_FLOAT_EQ(4.5f, rect.right); + EXPECT_FLOAT_EQ(3.2f, rect.top); + rect.ScaleFromCenterPoint(0.5f); + EXPECT_FLOAT_EQ(0.375f, rect.left); + EXPECT_FLOAT_EQ(-1.45f, rect.bottom); + EXPECT_FLOAT_EQ(3.125f, rect.right); + EXPECT_FLOAT_EQ(1.65f, rect.top); + rect.ScaleFromCenterPoint(2.0f); + EXPECT_FLOAT_EQ(-1.0f, rect.left); + EXPECT_FLOAT_EQ(-3.0f, rect.bottom); + EXPECT_FLOAT_EQ(4.5f, rect.right); + EXPECT_FLOAT_EQ(3.2f, rect.top); + rect.ScaleFromCenterPoint(-1.0f); + EXPECT_FLOAT_EQ(4.5f, rect.left); + EXPECT_FLOAT_EQ(3.2f, rect.bottom); + EXPECT_FLOAT_EQ(-1.0f, rect.right); + EXPECT_FLOAT_EQ(-3.0f, rect.top); + rect.ScaleFromCenterPoint(0.0f); + EXPECT_FLOAT_EQ(1.75f, rect.left); + EXPECT_NEAR(0.1f, rect.bottom, 0.001f); + EXPECT_FLOAT_EQ(1.75f, rect.right); + EXPECT_NEAR(0.1f, rect.top, 0.001f); +} + +TEST(CFX_FloatRect, ScaleFromCenterPointEmpty) { + CFX_FloatRect rect; + rect.ScaleFromCenterPoint(1.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect.ScaleFromCenterPoint(0.5f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect.ScaleFromCenterPoint(2.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); + rect.ScaleFromCenterPoint(0.0f); + EXPECT_FLOAT_EQ(0.0f, rect.left); + EXPECT_FLOAT_EQ(0.0f, rect.bottom); + EXPECT_FLOAT_EQ(0.0f, rect.right); + EXPECT_FLOAT_EQ(0.0f, rect.top); +} + +#ifndef NDEBUG +TEST(CFX_FloatRect, Print) { + std::ostringstream os; + CFX_FloatRect rect; + os << rect; + EXPECT_STREQ("rect[0x0 (0, 0)]", os.str().c_str()); + + os.str(""); + rect = CFX_FloatRect(10, 20, 14, 23); + os << rect; + EXPECT_STREQ("rect[4x3 (10, 20)]", os.str().c_str()); + + os.str(""); + rect = CFX_FloatRect(10.5, 20.5, 14.75, 23.75); + os << rect; + EXPECT_STREQ("rect[4.25x3.25 (10.5, 20.5)]", os.str().c_str()); +} +#endif + +TEST(CFX_Matrix, ReverseIdentity) { + CFX_Matrix m; + m.SetIdentity(); + CFX_Matrix rev = m.GetInverse(); + + EXPECT_FLOAT_EQ(1.0, rev.a); + EXPECT_FLOAT_EQ(0.0, rev.b); + EXPECT_FLOAT_EQ(0.0, rev.c); + EXPECT_FLOAT_EQ(1.0, rev.d); + EXPECT_FLOAT_EQ(0.0, rev.e); + EXPECT_FLOAT_EQ(0.0, rev.f); + + CFX_PointF expected(2, 3); + CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); + EXPECT_FLOAT_EQ(expected.x, result.x); + EXPECT_FLOAT_EQ(expected.y, result.y); +} + +TEST(CFX_Matrix, Reverse) { + static constexpr float data[6] = {3, 0, 2, 3, 1, 4}; + CFX_Matrix m(data); + CFX_Matrix rev = m.GetInverse(); + + EXPECT_FLOAT_EQ(0.33333334f, rev.a); + EXPECT_FLOAT_EQ(0.0f, rev.b); + EXPECT_FLOAT_EQ(-0.22222222f, rev.c); + EXPECT_FLOAT_EQ(0.33333334f, rev.d); + EXPECT_FLOAT_EQ(0.55555556f, rev.e); + EXPECT_FLOAT_EQ(-1.3333334f, rev.f); + + CFX_PointF expected(2, 3); + CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); + EXPECT_FLOAT_EQ(expected.x, result.x); + EXPECT_FLOAT_EQ(expected.y, result.y); +} + +// Note, I think these are a bug and the matrix should be the identity. +TEST(CFX_Matrix, ReverseCR702041) { + // The determinate is < std::numeric_limits::epsilon() + static constexpr float data[6] = {0.947368443f, -0.108947366f, -0.923076928f, + 0.106153846f, 18.0f, 787.929993f}; + CFX_Matrix m(data); + CFX_Matrix rev = m.GetInverse(); + + EXPECT_FLOAT_EQ(14247728.0f, rev.a); + EXPECT_FLOAT_EQ(14622668.0f, rev.b); + EXPECT_FLOAT_EQ(1.2389329e+08f, rev.c); + EXPECT_FLOAT_EQ(1.2715364e+08f, rev.d); + EXPECT_FLOAT_EQ(-9.7875698e+10f, rev.e); + EXPECT_FLOAT_EQ(-1.0045138e+11f, rev.f); + + // Should be 2, 3 + CFX_PointF expected(0, 0); + CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); + EXPECT_FLOAT_EQ(expected.x, result.x); + EXPECT_FLOAT_EQ(expected.y, result.y); +} + +TEST(CFX_Matrix, ReverseCR714187) { + // The determinate is < std::numeric_limits::epsilon() + static constexpr float data[6] = {0.000037f, 0.0f, 0.0f, + -0.000037f, 182.413101f, 136.977646f}; + CFX_Matrix m(data); + CFX_Matrix rev = m.GetInverse(); + + EXPECT_FLOAT_EQ(27027.025f, rev.a); + EXPECT_FLOAT_EQ(0.0f, rev.b); + EXPECT_FLOAT_EQ(0.0f, rev.c); + EXPECT_FLOAT_EQ(-27027.025f, rev.d); + EXPECT_FLOAT_EQ(-4930083.5f, rev.e); + EXPECT_FLOAT_EQ(3702098.2f, rev.f); + + // Should be 3 .... + CFX_PointF expected(2, 2.75); + CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); + EXPECT_FLOAT_EQ(expected.x, result.x); + EXPECT_FLOAT_EQ(expected.y, result.y); +} diff --git a/core/fxcrt/fx_ext.h b/core/fxcrt/fx_ext.h deleted file mode 100644 index 9203938c2c7b38e04e1c838df8f49847b3e6204a..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_ext.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FX_EXT_H_ -#define CORE_FXCRT_FX_EXT_H_ - -#include -#include -#include - -#include "core/fxcrt/fx_basic.h" - -#define FX_INVALID_OFFSET static_cast(-1) - -FX_FLOAT FXSYS_tan(FX_FLOAT a); -FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x); -FX_FLOAT FXSYS_strtof(const FX_CHAR* pcsStr, - int32_t iLength = -1, - int32_t* pUsedLen = nullptr); -FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr, - int32_t iLength = -1, - int32_t* pUsedLen = nullptr); -FX_WCHAR* FXSYS_wcsncpy(FX_WCHAR* dstStr, const FX_WCHAR* srcStr, size_t count); -int32_t FXSYS_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count); -int32_t FXSYS_strnicmp(const FX_CHAR* s1, const FX_CHAR* s2, size_t count); - -inline bool FXSYS_islower(int32_t ch) { - return ch >= 'a' && ch <= 'z'; -} -inline bool FXSYS_isupper(int32_t ch) { - return ch >= 'A' && ch <= 'Z'; -} -inline int32_t FXSYS_tolower(int32_t ch) { - return ch < 'A' || ch > 'Z' ? ch : (ch + 0x20); -} -inline int32_t FXSYS_toupper(int32_t ch) { - return ch < 'a' || ch > 'z' ? ch : (ch - 0x20); -} -inline bool FXSYS_iswalpha(wchar_t wch) { - return (wch >= L'A' && wch <= L'Z') || (wch >= L'a' && wch <= L'z'); -} -inline bool FXSYS_iswdigit(wchar_t wch) { - return wch >= L'0' && wch <= L'9'; -} -inline bool FXSYS_iswalnum(wchar_t wch) { - return FXSYS_iswalpha(wch) || FXSYS_iswdigit(wch); -} -inline bool FXSYS_iswspace(FX_WCHAR c) { - return (c == 0x20) || (c == 0x0d) || (c == 0x0a) || (c == 0x09); -} - -inline int FXSYS_toHexDigit(const FX_CHAR c) { - if (!std::isxdigit(c)) - return 0; - char upchar = std::toupper(c); - return upchar > '9' ? upchar - 'A' + 10 : upchar - '0'; -} - -inline bool FXSYS_isDecimalDigit(const FX_CHAR c) { - return !!std::isdigit(c); -} - -inline bool FXSYS_isDecimalDigit(const FX_WCHAR c) { - return !!std::iswdigit(c); -} - -inline int FXSYS_toDecimalDigit(const FX_CHAR c) { - return std::isdigit(c) ? c - '0' : 0; -} - -inline int FXSYS_toDecimalDigit(const FX_WCHAR c) { - return std::iswdigit(c) ? c - L'0' : 0; -} - -FX_FLOAT FXSYS_FractionalScale(size_t scale_factor, int value); -int FXSYS_FractionalScaleCount(); - -void* FX_Random_MT_Start(uint32_t dwSeed); -void FX_Random_MT_Close(void* pContext); -uint32_t FX_Random_MT_Generate(void* pContext); -void FX_Random_GenerateBase(uint32_t* pBuffer, int32_t iCount); -void FX_Random_GenerateMT(uint32_t* pBuffer, int32_t iCount); -void FX_Random_GenerateCrypto(uint32_t* pBuffer, int32_t iCount); - -#ifdef PDF_ENABLE_XFA -struct FX_GUID { - uint32_t data1; - uint16_t data2; - uint16_t data3; - uint8_t data4[8]; -}; -void FX_GUID_CreateV4(FX_GUID* pGUID); -void FX_GUID_ToString(const FX_GUID* pGUID, - CFX_ByteString& bsStr, - bool bSeparator = true); -#endif // PDF_ENABLE_XFA - -#endif // CORE_FXCRT_FX_EXT_H_ diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp index 5b577f745cab4554fde38529c19985a3d7628fe6..62cf8a0e048eaefb0235f94aa9bc8fe81a0169e0 100644 --- a/core/fxcrt/fx_extension.cpp +++ b/core/fxcrt/fx_extension.cpp @@ -4,452 +4,18 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxcrt/extension.h" +#include "core/fxcrt/fx_extension.h" #include -#include -#include +#include -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_ext.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#include -#else -#include -#endif - -namespace { - -#ifdef PDF_ENABLE_XFA - -class CFX_CRTFileAccess : public IFX_FileAccess { - public: - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - // IFX_FileAccess - void GetPath(CFX_WideString& wsPath) override; - CFX_RetainPtr CreateFileStream(uint32_t dwModes) override; - - bool Init(const CFX_WideStringC& wsPath); - - private: - CFX_CRTFileAccess(); - ~CFX_CRTFileAccess() override; - - CFX_WideString m_path; -}; - -CFX_CRTFileAccess::CFX_CRTFileAccess() {} - -CFX_CRTFileAccess::~CFX_CRTFileAccess() {} - -void CFX_CRTFileAccess::GetPath(CFX_WideString& wsPath) { - wsPath = m_path; -} - -CFX_RetainPtr CFX_CRTFileAccess::CreateFileStream( - uint32_t dwModes) { - return IFX_SeekableStream::CreateFromFilename(m_path.c_str(), dwModes); -} - -bool CFX_CRTFileAccess::Init(const CFX_WideStringC& wsPath) { - m_path = wsPath; - return true; -} - -#endif // PDF_ENABLE_XFA - -class CFX_CRTFileStream final : public IFX_SeekableStream { - public: - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - // IFX_SeekableStream: - FX_FILESIZE GetSize() override; - bool IsEOF() override; - FX_FILESIZE GetPosition() override; - bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; - size_t ReadBlock(void* buffer, size_t size) override; - bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override; - bool Flush() override; - - private: - explicit CFX_CRTFileStream(std::unique_ptr pFA); - ~CFX_CRTFileStream() override; - - std::unique_ptr m_pFile; -}; - -CFX_CRTFileStream::CFX_CRTFileStream(std::unique_ptr pFA) - : m_pFile(std::move(pFA)) {} - -CFX_CRTFileStream::~CFX_CRTFileStream() {} - -FX_FILESIZE CFX_CRTFileStream::GetSize() { - return m_pFile->GetSize(); -} - -bool CFX_CRTFileStream::IsEOF() { - return GetPosition() >= GetSize(); -} - -FX_FILESIZE CFX_CRTFileStream::GetPosition() { - return m_pFile->GetPosition(); -} - -bool CFX_CRTFileStream::ReadBlock(void* buffer, - FX_FILESIZE offset, - size_t size) { - return m_pFile->ReadPos(buffer, size, offset) > 0; -} - -size_t CFX_CRTFileStream::ReadBlock(void* buffer, size_t size) { - return m_pFile->Read(buffer, size); -} - -bool CFX_CRTFileStream::WriteBlock(const void* buffer, - FX_FILESIZE offset, - size_t size) { - return !!m_pFile->WritePos(buffer, size, offset); -} - -bool CFX_CRTFileStream::Flush() { - return m_pFile->Flush(); -} - -#define FX_MEMSTREAM_BlockSize (64 * 1024) -#define FX_MEMSTREAM_Consecutive 0x01 -#define FX_MEMSTREAM_TakeOver 0x02 - -class CFX_MemoryStream final : public IFX_MemoryStream { - public: - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - // IFX_MemoryStream - FX_FILESIZE GetSize() override; - bool IsEOF() override; - FX_FILESIZE GetPosition() override; - bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; - size_t ReadBlock(void* buffer, size_t size) override; - bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override; - bool Flush() override; - bool IsConsecutive() const override; - void EstimateSize(size_t nInitSize, size_t nGrowSize) override; - uint8_t* GetBuffer() const override; - void AttachBuffer(uint8_t* pBuffer, - size_t nSize, - bool bTakeOver = false) override; - void DetachBuffer() override; - - private: - explicit CFX_MemoryStream(bool bConsecutive); - CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, bool bTakeOver); - ~CFX_MemoryStream() override; - - bool ExpandBlocks(size_t size); - - CFX_ArrayTemplate m_Blocks; - size_t m_nTotalSize; - size_t m_nCurSize; - size_t m_nCurPos; - size_t m_nGrowSize; - uint32_t m_dwFlags; -}; - -CFX_MemoryStream::CFX_MemoryStream(bool bConsecutive) - : m_nTotalSize(0), - m_nCurSize(0), - m_nCurPos(0), - m_nGrowSize(FX_MEMSTREAM_BlockSize) { - m_dwFlags = - FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0); -} - -CFX_MemoryStream::CFX_MemoryStream(uint8_t* pBuffer, - size_t nSize, - bool bTakeOver) - : m_nTotalSize(nSize), - m_nCurSize(nSize), - m_nCurPos(0), - m_nGrowSize(FX_MEMSTREAM_BlockSize) { - m_Blocks.Add(pBuffer); - m_dwFlags = - FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0); -} - -CFX_MemoryStream::~CFX_MemoryStream() { - if (m_dwFlags & FX_MEMSTREAM_TakeOver) { - for (int32_t i = 0; i < m_Blocks.GetSize(); i++) { - FX_Free(m_Blocks[i]); - } - } - m_Blocks.RemoveAll(); -} - -FX_FILESIZE CFX_MemoryStream::GetSize() { - return (FX_FILESIZE)m_nCurSize; -} - -bool CFX_MemoryStream::IsEOF() { - return m_nCurPos >= (size_t)GetSize(); -} - -FX_FILESIZE CFX_MemoryStream::GetPosition() { - return (FX_FILESIZE)m_nCurPos; -} - -bool CFX_MemoryStream::ReadBlock(void* buffer, - FX_FILESIZE offset, - size_t size) { - if (!buffer || !size || offset < 0) - return false; - - FX_SAFE_SIZE_T newPos = size; - newPos += offset; - if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 || - newPos.ValueOrDie() > m_nCurSize) { - return false; - } - - m_nCurPos = newPos.ValueOrDie(); - if (m_dwFlags & FX_MEMSTREAM_Consecutive) { - FXSYS_memcpy(buffer, m_Blocks[0] + (size_t)offset, size); - return true; - } - size_t nStartBlock = (size_t)offset / m_nGrowSize; - offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize); - while (size) { - size_t nRead = m_nGrowSize - (size_t)offset; - if (nRead > size) { - nRead = size; - } - FXSYS_memcpy(buffer, m_Blocks[(int)nStartBlock] + (size_t)offset, nRead); - buffer = ((uint8_t*)buffer) + nRead; - size -= nRead; - nStartBlock++; - offset = 0; - } - return true; -} - -size_t CFX_MemoryStream::ReadBlock(void* buffer, size_t size) { - if (m_nCurPos >= m_nCurSize) { - return 0; - } - size_t nRead = std::min(size, m_nCurSize - m_nCurPos); - if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) { - return 0; - } - return nRead; -} - -bool CFX_MemoryStream::WriteBlock(const void* buffer, - FX_FILESIZE offset, - size_t size) { - if (!buffer || !size) - return false; - - if (m_dwFlags & FX_MEMSTREAM_Consecutive) { - FX_SAFE_SIZE_T newPos = size; - newPos += offset; - if (!newPos.IsValid()) - return false; - - m_nCurPos = newPos.ValueOrDie(); - if (m_nCurPos > m_nTotalSize) { - m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize; - if (m_Blocks.GetSize() < 1) { - uint8_t* block = FX_Alloc(uint8_t, m_nTotalSize); - m_Blocks.Add(block); - } else { - m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize); - } - if (!m_Blocks[0]) { - m_Blocks.RemoveAll(); - return false; - } - } - FXSYS_memcpy(m_Blocks[0] + (size_t)offset, buffer, size); - if (m_nCurSize < m_nCurPos) { - m_nCurSize = m_nCurPos; - } - return true; - } - - FX_SAFE_SIZE_T newPos = size; - newPos += offset; - if (!newPos.IsValid()) { - return false; - } - - if (!ExpandBlocks(newPos.ValueOrDie())) { - return false; - } - m_nCurPos = newPos.ValueOrDie(); - size_t nStartBlock = (size_t)offset / m_nGrowSize; - offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize); - while (size) { - size_t nWrite = m_nGrowSize - (size_t)offset; - if (nWrite > size) { - nWrite = size; - } - FXSYS_memcpy(m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite); - buffer = ((uint8_t*)buffer) + nWrite; - size -= nWrite; - nStartBlock++; - offset = 0; - } - return true; -} - -bool CFX_MemoryStream::Flush() { - return true; -} - -bool CFX_MemoryStream::IsConsecutive() const { - return !!(m_dwFlags & FX_MEMSTREAM_Consecutive); -} - -void CFX_MemoryStream::EstimateSize(size_t nInitSize, size_t nGrowSize) { - if (m_dwFlags & FX_MEMSTREAM_Consecutive) { - if (m_Blocks.GetSize() < 1) { - uint8_t* pBlock = - FX_Alloc(uint8_t, std::max(nInitSize, static_cast(4096))); - m_Blocks.Add(pBlock); - } - m_nGrowSize = std::max(nGrowSize, static_cast(4096)); - } else if (m_Blocks.GetSize() < 1) { - m_nGrowSize = std::max(nGrowSize, static_cast(4096)); - } -} - -uint8_t* CFX_MemoryStream::GetBuffer() const { - return m_Blocks.GetSize() ? m_Blocks[0] : nullptr; -} - -void CFX_MemoryStream::AttachBuffer(uint8_t* pBuffer, - size_t nSize, - bool bTakeOver) { - if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) - return; - - m_Blocks.RemoveAll(); - m_Blocks.Add(pBuffer); - m_nTotalSize = m_nCurSize = nSize; - m_nCurPos = 0; - m_dwFlags = - FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0); -} - -void CFX_MemoryStream::DetachBuffer() { - if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) { - return; - } - m_Blocks.RemoveAll(); - m_nTotalSize = m_nCurSize = m_nCurPos = 0; - m_dwFlags = FX_MEMSTREAM_TakeOver; -} - -bool CFX_MemoryStream::ExpandBlocks(size_t size) { - if (m_nCurSize < size) { - m_nCurSize = size; - } - if (size <= m_nTotalSize) { - return true; - } - int32_t iCount = m_Blocks.GetSize(); - size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize; - m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size); - while (size--) { - uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize); - m_Blocks.SetAt(iCount++, pBlock); - m_nTotalSize += m_nGrowSize; - } - return true; -} - -} // namespace - -#ifdef PDF_ENABLE_XFA -CFX_RetainPtr IFX_FileAccess::CreateDefault( - const CFX_WideStringC& wsPath) { - if (wsPath.GetLength() == 0) - return nullptr; - - auto pFA = pdfium::MakeRetain(); - pFA->Init(wsPath); - return pFA; -} -#endif // PDF_ENABLE_XFA - -// static -CFX_RetainPtr IFX_SeekableStream::CreateFromFilename( - const FX_CHAR* filename, - uint32_t dwModes) { - std::unique_ptr pFA(IFXCRT_FileAccess::Create()); - if (!pFA->Open(filename, dwModes)) - return nullptr; - return pdfium::MakeRetain(std::move(pFA)); -} - -// static -CFX_RetainPtr IFX_SeekableStream::CreateFromFilename( - const FX_WCHAR* filename, - uint32_t dwModes) { - std::unique_ptr pFA(IFXCRT_FileAccess::Create()); - if (!pFA->Open(filename, dwModes)) - return nullptr; - return pdfium::MakeRetain(std::move(pFA)); -} - -// static -CFX_RetainPtr -IFX_SeekableReadStream::CreateFromFilename(const FX_CHAR* filename) { - return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly); -} - -// static -CFX_RetainPtr IFX_MemoryStream::Create(uint8_t* pBuffer, - size_t dwSize, - bool bTakeOver) { - return pdfium::MakeRetain(pBuffer, dwSize, bTakeOver); -} - -// static -CFX_RetainPtr IFX_MemoryStream::Create(bool bConsecutive) { - return pdfium::MakeRetain(bConsecutive); -} - -FX_FLOAT FXSYS_tan(FX_FLOAT a) { - return (FX_FLOAT)tan(a); -} -FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x) { - return FXSYS_log(x) / FXSYS_log(b); -} -FX_FLOAT FXSYS_strtof(const FX_CHAR* pcsStr, - int32_t iLength, - int32_t* pUsedLen) { - ASSERT(pcsStr); - if (iLength < 0) { - iLength = (int32_t)FXSYS_strlen(pcsStr); - } - CFX_WideString ws = - CFX_WideString::FromLocal(CFX_ByteStringC(pcsStr, iLength)); - return FXSYS_wcstof(ws.c_str(), iLength, pUsedLen); -} -FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr, - int32_t iLength, - int32_t* pUsedLen) { +float FXSYS_wcstof(const wchar_t* pwsStr, int32_t iLength, int32_t* pUsedLen) { ASSERT(pwsStr); - if (iLength < 0) { - iLength = (int32_t)FXSYS_wcslen(pwsStr); - } - if (iLength == 0) { + if (iLength < 0) + iLength = static_cast(wcslen(pwsStr)); + if (iLength == 0) return 0.0f; - } + int32_t iUsedLen = 0; bool bNegtive = false; switch (pwsStr[iUsedLen]) { @@ -459,218 +25,130 @@ FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr, iUsedLen++; break; } - FX_FLOAT fValue = 0.0f; + + 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 { + wchar_t wch = pwsStr[iUsedLen]; + if (!std::iswdigit(wch)) break; - } + + fValue = fValue * 10.0f + (wch - L'0'); iUsedLen++; } + if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') { - FX_FLOAT fPrecise = 0.1f; + 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 { + wchar_t wch = pwsStr[iUsedLen]; + if (!std::iswdigit(wch)) break; - } + + fValue += (wch - L'0') * fPrecise; + fPrecise *= 0.1f; } } - if (pUsedLen) { + if (pUsedLen) *pUsedLen = iUsedLen; - } + return bNegtive ? -fValue : fValue; } -FX_WCHAR* FXSYS_wcsncpy(FX_WCHAR* dstStr, - const FX_WCHAR* srcStr, - size_t count) { + +wchar_t* FXSYS_wcsncpy(wchar_t* dstStr, const wchar_t* srcStr, size_t count) { ASSERT(dstStr && srcStr && count > 0); for (size_t i = 0; i < count; ++i) - if ((dstStr[i] = srcStr[i]) == L'\0') { + if ((dstStr[i] = srcStr[i]) == L'\0') break; - } return dstStr; } -int32_t FXSYS_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count) { + +int32_t FXSYS_wcsnicmp(const wchar_t* s1, const wchar_t* s2, size_t count) { ASSERT(s1 && s2 && count > 0); - FX_WCHAR wch1 = 0, wch2 = 0; + wchar_t wch1 = 0, wch2 = 0; while (count-- > 0) { - wch1 = (FX_WCHAR)FXSYS_tolower(*s1++); - wch2 = (FX_WCHAR)FXSYS_tolower(*s2++); - if (wch1 != wch2) { + wch1 = static_cast(FXSYS_tolower(*s1++)); + wch2 = static_cast(FXSYS_tolower(*s2++)); + if (wch1 != wch2) break; - } } return wch1 - wch2; } -int32_t FXSYS_strnicmp(const FX_CHAR* s1, const FX_CHAR* s2, size_t count) { - ASSERT(s1 && s2 && count > 0); - FX_CHAR ch1 = 0, ch2 = 0; - while (count-- > 0) { - ch1 = (FX_CHAR)FXSYS_tolower(*s1++); - ch2 = (FX_CHAR)FXSYS_tolower(*s2++); - if (ch1 != ch2) { - break; - } - } - return ch1 - ch2; -} -uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase) { +uint32_t FX_HashCode_GetA(const ByteStringView& str, bool bIgnoreCase) { uint32_t dwHashCode = 0; if (bIgnoreCase) { - for (FX_STRSIZE i = 0; i < str.GetLength(); ++i) - dwHashCode = 31 * dwHashCode + FXSYS_tolower(str.CharAt(i)); + for (const auto& c : str) + dwHashCode = 31 * dwHashCode + FXSYS_tolower(c); } else { - for (FX_STRSIZE i = 0; i < str.GetLength(); ++i) - dwHashCode = 31 * dwHashCode + str.CharAt(i); + for (const auto& c : str) + dwHashCode = 31 * dwHashCode + c; } return dwHashCode; } -uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase) { +uint32_t FX_HashCode_GetW(const WideStringView& str, bool bIgnoreCase) { uint32_t dwHashCode = 0; if (bIgnoreCase) { - for (FX_STRSIZE i = 0; i < str.GetLength(); ++i) - dwHashCode = 1313 * dwHashCode + FXSYS_tolower(str.CharAt(i)); + for (const auto& c : str) + dwHashCode = 1313 * dwHashCode + FXSYS_tolower(c); } else { - for (FX_STRSIZE i = 0; i < str.GetLength(); ++i) - dwHashCode = 1313 * dwHashCode + str.CharAt(i); + for (const auto& c : str) + dwHashCode = 1313 * dwHashCode + c; } return dwHashCode; } -void* FX_Random_MT_Start(uint32_t dwSeed) { - FX_MTRANDOMCONTEXT* pContext = FX_Alloc(FX_MTRANDOMCONTEXT, 1); - pContext->mt[0] = dwSeed; - uint32_t& i = pContext->mti; - uint32_t* pBuf = pContext->mt; - for (i = 1; i < MT_N; i++) { - pBuf[i] = (1812433253UL * (pBuf[i - 1] ^ (pBuf[i - 1] >> 30)) + i); - } - pContext->bHaveSeed = true; - return pContext; -} -uint32_t FX_Random_MT_Generate(void* pContext) { - ASSERT(pContext); - FX_MTRANDOMCONTEXT* pMTC = static_cast(pContext); - uint32_t v; - static uint32_t mag[2] = {0, MT_Matrix_A}; - uint32_t& mti = pMTC->mti; - uint32_t* pBuf = pMTC->mt; - if ((int)mti < 0 || mti >= MT_N) { - if (mti > MT_N && !pMTC->bHaveSeed) { - return 0; - } - uint32_t kk; - for (kk = 0; kk < MT_N - MT_M; kk++) { - v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask); - pBuf[kk] = pBuf[kk + MT_M] ^ (v >> 1) ^ mag[v & 1]; - } - for (; kk < MT_N - 1; kk++) { - v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask); - pBuf[kk] = pBuf[kk + (MT_M - MT_N)] ^ (v >> 1) ^ mag[v & 1]; - } - v = (pBuf[MT_N - 1] & MT_Upper_Mask) | (pBuf[0] & MT_Lower_Mask); - pBuf[MT_N - 1] = pBuf[MT_M - 1] ^ (v >> 1) ^ mag[v & 1]; - mti = 0; - } - v = pBuf[mti++]; - v ^= (v >> 11); - v ^= (v << 7) & 0x9d2c5680UL; - v ^= (v << 15) & 0xefc60000UL; - v ^= (v >> 18); - return v; +void FXSYS_IntToTwoHexChars(uint8_t n, char* buf) { + static const char kHex[] = "0123456789ABCDEF"; + buf[0] = kHex[n / 16]; + buf[1] = kHex[n % 16]; } -void FX_Random_MT_Close(void* pContext) { - ASSERT(pContext); - FX_Free(pContext); + +void FXSYS_IntToFourHexChars(uint16_t n, char* buf) { + FXSYS_IntToTwoHexChars(n / 256, buf); + FXSYS_IntToTwoHexChars(n % 256, buf + 2); } -void FX_Random_GenerateMT(uint32_t* pBuffer, int32_t iCount) { - uint32_t dwSeed; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - if (!FX_GenerateCryptoRandom(&dwSeed, 1)) { - FX_Random_GenerateBase(&dwSeed, 1); - } -#else - FX_Random_GenerateBase(&dwSeed, 1); -#endif - void* pContext = FX_Random_MT_Start(dwSeed); - while (iCount-- > 0) { - *pBuffer++ = FX_Random_MT_Generate(pContext); + +size_t FXSYS_ToUTF16BE(uint32_t unicode, char* buf) { + ASSERT(unicode <= 0xD7FF || (unicode > 0xDFFF && unicode <= 0x10FFFF)); + if (unicode <= 0xFFFF) { + FXSYS_IntToFourHexChars(unicode, buf); + return 4; } - FX_Random_MT_Close(pContext); + unicode -= 0x010000; + // High ten bits plus 0xD800 + FXSYS_IntToFourHexChars(0xD800 + unicode / 0x400, buf); + // Low ten bits plus 0xDC00 + FXSYS_IntToFourHexChars(0xDC00 + unicode % 0x400, buf + 4); + return 8; } -void FX_Random_GenerateBase(uint32_t* pBuffer, int32_t iCount) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - SYSTEMTIME st1, st2; - ::GetSystemTime(&st1); - do { - ::GetSystemTime(&st2); - } while (FXSYS_memcmp(&st1, &st2, sizeof(SYSTEMTIME)) == 0); - uint32_t dwHash1 = - FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)&st1, sizeof(st1)), true); - uint32_t dwHash2 = - FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)&st2, sizeof(st2)), true); - ::srand((dwHash1 << 16) | (uint32_t)dwHash2); -#else - time_t tmLast = time(nullptr); - time_t tmCur; - while ((tmCur = time(nullptr)) == tmLast) { - continue; - } - ::srand((tmCur << 16) | (tmLast & 0xFFFF)); -#endif - while (iCount-- > 0) { - *pBuffer++ = (uint32_t)((::rand() << 16) | (::rand() & 0xFFFF)); +uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits) { + ASSERT(0 < nbits && nbits <= 32); + const uint8_t* dataPtr = &pData[bitpos / 8]; + int bitShift; + int bitMask; + int dstShift; + int bitCount = bitpos & 0x07; + if (nbits < 8 && nbits + bitCount <= 8) { + bitShift = 8 - nbits - bitCount; + bitMask = (1 << nbits) - 1; + dstShift = 0; + } else { + bitShift = 0; + int bitOffset = 8 - bitCount; + bitMask = (1 << std::min(bitOffset, nbits)) - 1; + dstShift = nbits - bitOffset; } -} -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -bool FX_GenerateCryptoRandom(uint32_t* pBuffer, int32_t iCount) { - HCRYPTPROV hCP = 0; - if (!::CryptAcquireContext(&hCP, nullptr, nullptr, PROV_RSA_FULL, 0) || - !hCP) { - return false; + uint32_t result = + static_cast((*dataPtr++ >> bitShift & bitMask) << dstShift); + while (dstShift >= 8) { + dstShift -= 8; + result |= *dataPtr++ << dstShift; } - ::CryptGenRandom(hCP, iCount * sizeof(uint32_t), (uint8_t*)pBuffer); - ::CryptReleaseContext(hCP, 0); - return true; -} -#endif -void FX_Random_GenerateCrypto(uint32_t* pBuffer, int32_t iCount) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - FX_GenerateCryptoRandom(pBuffer, iCount); -#else - FX_Random_GenerateBase(pBuffer, iCount); -#endif -} - -#ifdef PDF_ENABLE_XFA -static const FX_CHAR gs_FX_pHexChars[] = "0123456789ABCDEF"; -void FX_GUID_CreateV4(FX_GUID* pGUID) { - FX_Random_GenerateMT((uint32_t*)pGUID, 4); - uint8_t& b = ((uint8_t*)pGUID)[6]; - b = (b & 0x0F) | 0x40; -} -void FX_GUID_ToString(const FX_GUID* pGUID, - CFX_ByteString& bsStr, - bool bSeparator) { - FX_CHAR* pBuf = bsStr.GetBuffer(40); - uint8_t b; - for (int32_t i = 0; i < 16; i++) { - b = ((const uint8_t*)pGUID)[i]; - *pBuf++ = gs_FX_pHexChars[b >> 4]; - *pBuf++ = gs_FX_pHexChars[b & 0x0F]; - if (bSeparator && (i == 3 || i == 5 || i == 7 || i == 9)) { - *pBuf++ = L'-'; - } + if (dstShift > 0) { + bitShift = 8 - dstShift; + bitMask = (1 << dstShift) - 1; + result |= *dataPtr++ >> bitShift & bitMask; } - bsStr.ReleaseBuffer(bSeparator ? 36 : 32); + return result; } -#endif // PDF_ENABLE_XFA diff --git a/core/fxcrt/fx_extension.h b/core/fxcrt/fx_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..e02d58d0dffeaf7dee302ca54f3108e3f989473b --- /dev/null +++ b/core/fxcrt/fx_extension.h @@ -0,0 +1,91 @@ +// 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 CORE_FXCRT_FX_EXTENSION_H_ +#define CORE_FXCRT_FX_EXTENSION_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_string.h" + +#define FX_INVALID_OFFSET static_cast(-1) + +#ifdef PDF_ENABLE_XFA +#define FX_IsOdd(a) ((a)&1) +#endif // PDF_ENABLE_XFA + +float FXSYS_wcstof(const wchar_t* pwsStr, + int32_t iLength = -1, + int32_t* pUsedLen = nullptr); +wchar_t* FXSYS_wcsncpy(wchar_t* dstStr, const wchar_t* srcStr, size_t count); +int32_t FXSYS_wcsnicmp(const wchar_t* s1, const wchar_t* s2, size_t count); + +inline bool FXSYS_islower(int32_t ch) { + return ch >= 'a' && ch <= 'z'; +} + +inline bool FXSYS_isupper(int32_t ch) { + return ch >= 'A' && ch <= 'Z'; +} + +inline int32_t FXSYS_tolower(int32_t ch) { + return ch < 'A' || ch > 'Z' ? ch : (ch + 0x20); +} + +inline int32_t FXSYS_toupper(int32_t ch) { + return ch < 'a' || ch > 'z' ? ch : (ch - 0x20); +} + +inline bool FXSYS_iswalpha(wchar_t wch) { + return FXSYS_isupper(wch) || FXSYS_islower(wch); +} + +inline bool FXSYS_iswalnum(wchar_t wch) { + return FXSYS_iswalpha(wch) || std::iswdigit(wch); +} + +inline bool FXSYS_iswspace(wchar_t c) { + return (c == 0x20) || (c == 0x0d) || (c == 0x0a) || (c == 0x09); +} + +inline bool FXSYS_isHexDigit(const char c) { + return !((c & 0x80) || !std::isxdigit(c)); +} + +inline int FXSYS_HexCharToInt(const char c) { + if (!FXSYS_isHexDigit(c)) + return 0; + char upchar = std::toupper(c); + return upchar > '9' ? upchar - 'A' + 10 : upchar - '0'; +} + +inline bool FXSYS_isDecimalDigit(const char c) { + return !((c & 0x80) || !std::isdigit(c)); +} + +inline bool FXSYS_isDecimalDigit(const wchar_t c) { + return !!std::iswdigit(c); +} + +inline int FXSYS_DecimalCharToInt(const char c) { + return FXSYS_isDecimalDigit(c) ? c - '0' : 0; +} + +inline int FXSYS_DecimalCharToInt(const wchar_t c) { + return std::iswdigit(c) ? c - L'0' : 0; +} + +void FXSYS_IntToTwoHexChars(uint8_t c, char* buf); + +void FXSYS_IntToFourHexChars(uint16_t c, char* buf); + +size_t FXSYS_ToUTF16BE(uint32_t unicode, char* buf); + +uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits); + +#endif // CORE_FXCRT_FX_EXTENSION_H_ diff --git a/core/fxcrt/fx_extension_unittest.cpp b/core/fxcrt/fx_extension_unittest.cpp index 3739a3db8c65e37ccdb137065b372ec6f33cf9ae..0500a14b6fe94933e3182c2053e759316be6dbdf 100644 --- a/core/fxcrt/fx_extension_unittest.cpp +++ b/core/fxcrt/fx_extension_unittest.cpp @@ -2,22 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "core/fxcrt/fx_extension.h" #include "testing/gtest/include/gtest/gtest.h" -#include "core/fxcrt/fx_ext.h" +namespace { -TEST(fxcrt, FXSYS_toHexDigit) { - EXPECT_EQ(10, FXSYS_toHexDigit('a')); - EXPECT_EQ(10, FXSYS_toHexDigit('A')); - EXPECT_EQ(7, FXSYS_toHexDigit('7')); - EXPECT_EQ(0, FXSYS_toHexDigit('i')); +uint32_t ReferenceGetBits32(const uint8_t* pData, int bitpos, int nbits) { + int result = 0; + for (int i = 0; i < nbits; i++) { + if (pData[(bitpos + i) / 8] & (1 << (7 - (bitpos + i) % 8))) + result |= 1 << (nbits - i - 1); + } + return result; } -TEST(fxcrt, FXSYS_toDecimalDigit) { - EXPECT_EQ(7, FXSYS_toDecimalDigit('7')); - EXPECT_EQ(0, FXSYS_toDecimalDigit('a')); - EXPECT_EQ(7, FXSYS_toDecimalDigit(L'7')); - EXPECT_EQ(0, FXSYS_toDecimalDigit(L'a')); +} // namespace + +TEST(fxcrt, FXSYS_HexCharToInt) { + EXPECT_EQ(10, FXSYS_HexCharToInt('a')); + EXPECT_EQ(10, FXSYS_HexCharToInt('A')); + EXPECT_EQ(7, FXSYS_HexCharToInt('7')); + EXPECT_EQ(0, FXSYS_HexCharToInt('i')); +} + +TEST(fxcrt, FXSYS_DecimalCharToInt) { + EXPECT_EQ(7, FXSYS_DecimalCharToInt('7')); + EXPECT_EQ(0, FXSYS_DecimalCharToInt('a')); + EXPECT_EQ(7, FXSYS_DecimalCharToInt(L'7')); + EXPECT_EQ(0, FXSYS_DecimalCharToInt(L'a')); } TEST(fxcrt, FXSYS_isDecimalDigit) { @@ -40,3 +52,63 @@ TEST(fxcrt, FX_HashCode_Wide) { EXPECT_EQ(97u, FX_HashCode_GetW(L"A", true)); EXPECT_EQ(1313 * 65u + 66u, FX_HashCode_GetW(L"AB", false)); } + +TEST(fxcrt, FXSYS_IntToTwoHexChars) { + char buf[3] = {0}; + FXSYS_IntToTwoHexChars(0x0, buf); + EXPECT_STREQ("00", buf); + FXSYS_IntToTwoHexChars(0x9, buf); + EXPECT_STREQ("09", buf); + FXSYS_IntToTwoHexChars(0xA, buf); + EXPECT_STREQ("0A", buf); + FXSYS_IntToTwoHexChars(0x8C, buf); + EXPECT_STREQ("8C", buf); + FXSYS_IntToTwoHexChars(0xBE, buf); + EXPECT_STREQ("BE", buf); + FXSYS_IntToTwoHexChars(0xD0, buf); + EXPECT_STREQ("D0", buf); + FXSYS_IntToTwoHexChars(0xFF, buf); + EXPECT_STREQ("FF", buf); +} + +TEST(fxcrt, FXSYS_IntToFourHexChars) { + char buf[5] = {0}; + FXSYS_IntToFourHexChars(0x0, buf); + EXPECT_STREQ("0000", buf); + FXSYS_IntToFourHexChars(0xA23, buf); + EXPECT_STREQ("0A23", buf); + FXSYS_IntToFourHexChars(0xB701, buf); + EXPECT_STREQ("B701", buf); + FXSYS_IntToFourHexChars(0xFFFF, buf); + EXPECT_STREQ("FFFF", buf); +} + +TEST(fxcrt, FXSYS_ToUTF16BE) { + char buf[9] = {0}; + // Test U+0000 to U+D7FF and U+E000 to U+FFFF + EXPECT_EQ(4U, FXSYS_ToUTF16BE(0x0, buf)); + EXPECT_STREQ("0000", buf); + EXPECT_EQ(4U, FXSYS_ToUTF16BE(0xD7FF, buf)); + EXPECT_STREQ("D7FF", buf); + EXPECT_EQ(4U, FXSYS_ToUTF16BE(0xE000, buf)); + EXPECT_STREQ("E000", buf); + EXPECT_EQ(4U, FXSYS_ToUTF16BE(0xFFFF, buf)); + EXPECT_STREQ("FFFF", buf); + // Test U+10000 to U+10FFFF + EXPECT_EQ(8U, FXSYS_ToUTF16BE(0x10000, buf)); + EXPECT_STREQ("D800DC00", buf); + EXPECT_EQ(8U, FXSYS_ToUTF16BE(0x10FFFF, buf)); + EXPECT_STREQ("DBFFDFFF", buf); + EXPECT_EQ(8U, FXSYS_ToUTF16BE(0x2003E, buf)); + EXPECT_STREQ("D840DC3E", buf); +} + +TEST(fxcrt, GetBits32) { + unsigned char data[] = {0xDE, 0x3F, 0xB1, 0x7C, 0x12, 0x9A, 0x04, 0x56}; + for (int nbits = 1; nbits <= 32; ++nbits) { + for (int bitpos = 0; bitpos < (int)sizeof(data) * 8 - nbits; ++bitpos) { + EXPECT_EQ(ReferenceGetBits32(data, bitpos, nbits), + GetBits32(data, bitpos, nbits)); + } + } +} diff --git a/core/fxcrt/fx_memory.cpp b/core/fxcrt/fx_memory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a135ae0f87bdb7375627181d0578fe21b57c41b --- /dev/null +++ b/core/fxcrt/fx_memory.cpp @@ -0,0 +1,52 @@ +// 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 "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_safe_types.h" + +#include // For abort(). + +pdfium::base::PartitionAllocatorGeneric gArrayBufferPartitionAllocator; +pdfium::base::PartitionAllocatorGeneric gGeneralPartitionAllocator; +pdfium::base::PartitionAllocatorGeneric gStringPartitionAllocator; + +void FXMEM_InitializePartitionAlloc() { + static bool s_gPartitionAllocatorsInitialized = false; + if (!s_gPartitionAllocatorsInitialized) { + pdfium::base::PartitionAllocGlobalInit(FX_OutOfMemoryTerminate); + gArrayBufferPartitionAllocator.init(); + gGeneralPartitionAllocator.init(); + gStringPartitionAllocator.init(); + s_gPartitionAllocatorsInitialized = true; + } +} + +void* FXMEM_DefaultAlloc(size_t byte_size) { + return pdfium::base::PartitionAllocGenericFlags( + gGeneralPartitionAllocator.root(), pdfium::base::PartitionAllocReturnNull, + byte_size, "GeneralPartition"); +} + +void* FXMEM_DefaultCalloc(size_t num_elems, size_t byte_size) { + return FX_SafeAlloc(num_elems, byte_size); +} + +void* FXMEM_DefaultRealloc(void* pointer, size_t new_size) { + return pdfium::base::PartitionReallocGeneric( + gGeneralPartitionAllocator.root(), pointer, new_size, "GeneralPartition"); +} + +void FXMEM_DefaultFree(void* pointer) { + pdfium::base::PartitionFree(pointer); +} + +NEVER_INLINE void FX_OutOfMemoryTerminate() { + // Termimate cleanly if we can, else crash at a specific address (0xbd). + abort(); +#ifndef _WIN32 + reinterpret_cast(0xbd)(); +#endif +} diff --git a/core/fxcrt/fx_memory.h b/core/fxcrt/fx_memory.h index 0ad28ce896114da99d2ee850cae72e86ba341516..ecf3e426553cf451e1d945437a27d934c536e293 100644 --- a/core/fxcrt/fx_memory.h +++ b/core/fxcrt/fx_memory.h @@ -14,9 +14,10 @@ extern "C" { #endif // For external C libraries to malloc through PDFium. These may return nullptr. -void* FXMEM_DefaultAlloc(size_t byte_size, int flags); -void* FXMEM_DefaultRealloc(void* pointer, size_t new_size, int flags); -void FXMEM_DefaultFree(void* pointer, int flags); +void* FXMEM_DefaultAlloc(size_t byte_size); +void* FXMEM_DefaultCalloc(size_t num_elems, size_t byte_size); +void* FXMEM_DefaultRealloc(void* pointer, size_t new_size); +void FXMEM_DefaultFree(void* pointer); #ifdef __cplusplus } // extern "C" @@ -26,28 +27,54 @@ void FXMEM_DefaultFree(void* pointer, int flags); #include #include +#include "core/fxcrt/fx_safe_types.h" +#include "third_party/base/allocator/partition_allocator/partition_alloc.h" + +extern pdfium::base::PartitionAllocatorGeneric gArrayBufferPartitionAllocator; +extern pdfium::base::PartitionAllocatorGeneric gGeneralPartitionAllocator; +extern pdfium::base::PartitionAllocatorGeneric gStringPartitionAllocator; + +void FXMEM_InitializePartitionAlloc(); NEVER_INLINE void FX_OutOfMemoryTerminate(); +inline void* FX_SafeAlloc(size_t num_members, size_t member_size) { + FX_SAFE_SIZE_T total = member_size; + total *= num_members; + if (!total.IsValid()) + return nullptr; + + void* result = pdfium::base::PartitionAllocGenericFlags( + gGeneralPartitionAllocator.root(), pdfium::base::PartitionAllocReturnNull, + total.ValueOrDie(), "GeneralPartition"); + if (result) + memset(result, 0, total.ValueOrDie()); + return result; +} + inline void* FX_SafeRealloc(void* ptr, size_t num_members, size_t member_size) { - if (num_members < std::numeric_limits::max() / member_size) { - return realloc(ptr, num_members * member_size); - } - return nullptr; + FX_SAFE_SIZE_T size = num_members; + size *= member_size; + if (!size.IsValid()) + return nullptr; + + return pdfium::base::PartitionReallocGeneric( + gGeneralPartitionAllocator.root(), ptr, size.ValueOrDie(), + "GeneralPartition"); } inline void* FX_AllocOrDie(size_t num_members, size_t member_size) { // TODO(tsepez): See if we can avoid the implicit memset(0). - if (void* result = calloc(num_members, member_size)) { + if (void* result = FX_SafeAlloc(num_members, member_size)) return result; - } + FX_OutOfMemoryTerminate(); // Never returns. return nullptr; // Suppress compiler warning. } inline void* FX_AllocOrDie2D(size_t w, size_t h, size_t member_size) { - if (w < std::numeric_limits::max() / h) { + if (w < std::numeric_limits::max() / h) return FX_AllocOrDie(w * h, member_size); - } + FX_OutOfMemoryTerminate(); // Never returns. return nullptr; // Suppress compiler warning. } @@ -55,25 +82,39 @@ inline void* FX_AllocOrDie2D(size_t w, size_t h, size_t member_size) { inline void* FX_ReallocOrDie(void* ptr, size_t num_members, size_t member_size) { - if (void* result = FX_SafeRealloc(ptr, num_members, member_size)) { + if (void* result = FX_SafeRealloc(ptr, num_members, member_size)) return result; - } + FX_OutOfMemoryTerminate(); // Never returns. return nullptr; // Suppress compiler warning. } -// Never returns nullptr. -#define FX_Alloc(type, size) (type*)FX_AllocOrDie(size, sizeof(type)) -#define FX_Alloc2D(type, w, h) (type*)FX_AllocOrDie2D(w, h, sizeof(type)) +// These never return nullptr. +#define FX_Alloc(type, size) \ + static_cast(FX_AllocOrDie(size, sizeof(type))) +#define FX_Alloc2D(type, w, h) \ + static_cast(FX_AllocOrDie2D(w, h, sizeof(type))) #define FX_Realloc(type, ptr, size) \ - (type*)FX_ReallocOrDie(ptr, size, sizeof(type)) + static_cast(FX_ReallocOrDie(ptr, size, sizeof(type))) // May return nullptr. -#define FX_TryAlloc(type, size) (type*)calloc(size, sizeof(type)) +#define FX_TryAlloc(type, size) \ + static_cast(FX_SafeAlloc(size, sizeof(type))) #define FX_TryRealloc(type, ptr, size) \ - (type*)FX_SafeRealloc(ptr, size, sizeof(type)) - -#define FX_Free(ptr) free(ptr) + static_cast(FX_SafeRealloc(ptr, size, sizeof(type))) + +inline void FX_Free(void* ptr) { + // TODO(palmer): Removing this check exposes crashes when PDFium callers + // attempt to free |nullptr|. Although libc's |free| allows freeing |NULL|, no + // other Partition Alloc callers need this tolerant behavior. Additionally, + // checking for |nullptr| adds a branch to |PartitionFree|, and it's nice to + // not have to have that. + // + // So this check is hiding (what I consider to be) bugs, and we should try to + // fix them. https://bugs.chromium.org/p/pdfium/issues/detail?id=690 + if (ptr) + pdfium::base::PartitionFree(ptr); +} // The FX_ArraySize(arr) macro returns the # of elements in an array arr. // The expression is a compile-time constant, and therefore can be @@ -95,12 +136,6 @@ struct FxFreeDeleter { inline void operator()(void* ptr) const { FX_Free(ptr); } }; -// Used with std::unique_ptr to Release() objects that can't be deleted. -template -struct ReleaseDeleter { - inline void operator()(T* ptr) const { ptr->Release(); } -}; - #endif // __cplusplus #endif // CORE_FXCRT_FX_MEMORY_H_ diff --git a/core/fxcrt/fx_memory_unittest.cpp b/core/fxcrt/fx_memory_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2856bb95928f8861cb6a940ca4ebd3c12ac4035c --- /dev/null +++ b/core/fxcrt/fx_memory_unittest.cpp @@ -0,0 +1,81 @@ +// Copyright 2015 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. + +#include "core/fxcrt/fx_memory.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const size_t kMaxByteAlloc = std::numeric_limits::max(); +const size_t kMaxIntAlloc = kMaxByteAlloc / sizeof(int); +const size_t kOverflowIntAlloc = kMaxIntAlloc + 100; +const size_t kWidth = 640; +const size_t kOverflowIntAlloc2D = kMaxIntAlloc / kWidth + 10; + +} // namespace + +// TODO(tsepez): re-enable OOM tests if we can find a way to +// prevent it from hosing the bots. +TEST(fxcrt, DISABLED_FX_AllocOOM) { + EXPECT_DEATH_IF_SUPPORTED((void)FX_Alloc(int, kMaxIntAlloc), ""); + + int* ptr = FX_Alloc(int, 1); + EXPECT_TRUE(ptr); + EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kMaxIntAlloc), ""); + FX_Free(ptr); +} + +TEST(fxcrt, FX_AllocOverflow) { + // |ptr| needs to be defined and used to avoid Clang optimizes away the + // FX_Alloc() statement overzealously for optimized builds. + int* ptr = nullptr; + EXPECT_DEATH_IF_SUPPORTED(ptr = FX_Alloc(int, kOverflowIntAlloc), "") << ptr; + + ptr = FX_Alloc(int, 1); + EXPECT_TRUE(ptr); + EXPECT_DEATH_IF_SUPPORTED((void)FX_Realloc(int, ptr, kOverflowIntAlloc), ""); + FX_Free(ptr); +} + +TEST(fxcrt, FX_AllocOverflow2D) { + // |ptr| needs to be defined and used to avoid Clang optimizes away the + // FX_Alloc() statement overzealously for optimized builds. + int* ptr = nullptr; + EXPECT_DEATH_IF_SUPPORTED(ptr = FX_Alloc2D(int, kWidth, kOverflowIntAlloc2D), + "") + << ptr; +} + +TEST(fxcrt, DISABLED_FX_TryAllocOOM) { + EXPECT_FALSE(FX_TryAlloc(int, kMaxIntAlloc)); + + int* ptr = FX_Alloc(int, 1); + EXPECT_TRUE(ptr); + EXPECT_FALSE(FX_TryRealloc(int, ptr, kMaxIntAlloc)); + FX_Free(ptr); +} + +TEST(fxcrt, FX_TryAllocOverflow) { + // |ptr| needs to be defined and used to avoid Clang optimizes away the + // calloc() statement overzealously for optimized builds. + int* ptr = (int*)calloc(sizeof(int), kOverflowIntAlloc); + EXPECT_FALSE(ptr) << ptr; + + ptr = FX_Alloc(int, 1); + EXPECT_TRUE(ptr); + EXPECT_FALSE(FX_TryRealloc(int, ptr, kOverflowIntAlloc)); + FX_Free(ptr); +} + +TEST(fxcrt, DISABLED_FXMEM_DefaultOOM) { + EXPECT_FALSE(FXMEM_DefaultAlloc(kMaxByteAlloc)); + + void* ptr = FXMEM_DefaultAlloc(1); + EXPECT_TRUE(ptr); + EXPECT_FALSE(FXMEM_DefaultRealloc(ptr, kMaxByteAlloc)); + FXMEM_DefaultFree(ptr); +} diff --git a/core/fxcrt/fx_random.cpp b/core/fxcrt/fx_random.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56f84d59b342fcfe752f05695c3292f4537c94a7 --- /dev/null +++ b/core/fxcrt/fx_random.cpp @@ -0,0 +1,132 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/fx_random.h" + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" + +#define MT_N 848 +#define MT_M 456 +#define MT_Matrix_A 0x9908b0df +#define MT_Upper_Mask 0x80000000 +#define MT_Lower_Mask 0x7fffffff + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#include +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#include +#include +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + +namespace { + +struct MTContext { + uint32_t mti; + uint32_t mt[MT_N]; +}; + +bool g_bHaveGlobalSeed = false; +uint32_t g_nGlobalSeed = 0; + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +bool GenerateSeedFromCryptoRandom(uint32_t* pSeed) { + HCRYPTPROV hCP = 0; + if (!::CryptAcquireContext(&hCP, nullptr, nullptr, PROV_RSA_FULL, 0) || + !hCP) { + return false; + } + ::CryptGenRandom(hCP, sizeof(uint32_t), reinterpret_cast(pSeed)); + ::CryptReleaseContext(hCP, 0); + return true; +} +#endif + +uint32_t GenerateSeedFromEnvironment() { + char c; + uintptr_t p = reinterpret_cast(&c); + uint32_t seed = ~static_cast(p >> 3); +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + SYSTEMTIME st; + GetSystemTime(&st); + seed ^= static_cast(st.wSecond) * 1000000; + seed ^= static_cast(st.wMilliseconds) * 1000; + seed ^= GetCurrentProcessId(); +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + struct timeval tv; + gettimeofday(&tv, 0); + seed ^= static_cast(tv.tv_sec) * 1000000; + seed ^= static_cast(tv.tv_usec); + seed ^= static_cast(getpid()); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + return seed; +} + +void* ContextFromNextGlobalSeed() { + if (!g_bHaveGlobalSeed) { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + if (!GenerateSeedFromCryptoRandom(&g_nGlobalSeed)) + g_nGlobalSeed = GenerateSeedFromEnvironment(); +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + g_nGlobalSeed = GenerateSeedFromEnvironment(); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + g_bHaveGlobalSeed = true; + } + return FX_Random_MT_Start(++g_nGlobalSeed); +} + +} // namespace + +void* FX_Random_MT_Start(uint32_t dwSeed) { + MTContext* pContext = FX_Alloc(MTContext, 1); + uint32_t* pBuf = pContext->mt; + pBuf[0] = dwSeed; + for (uint32_t i = 1; i < MT_N; i++) + pBuf[i] = (1812433253UL * (pBuf[i - 1] ^ (pBuf[i - 1] >> 30)) + i); + + pContext->mti = MT_N; + return pContext; +} + +uint32_t FX_Random_MT_Generate(void* pContext) { + MTContext* pMTC = static_cast(pContext); + uint32_t* pBuf = pMTC->mt; + uint32_t v; + if (pMTC->mti >= MT_N) { + static const uint32_t mag[2] = {0, MT_Matrix_A}; + uint32_t kk; + for (kk = 0; kk < MT_N - MT_M; kk++) { + v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask); + pBuf[kk] = pBuf[kk + MT_M] ^ (v >> 1) ^ mag[v & 1]; + } + for (; kk < MT_N - 1; kk++) { + v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask); + pBuf[kk] = pBuf[kk + (MT_M - MT_N)] ^ (v >> 1) ^ mag[v & 1]; + } + v = (pBuf[MT_N - 1] & MT_Upper_Mask) | (pBuf[0] & MT_Lower_Mask); + pBuf[MT_N - 1] = pBuf[MT_M - 1] ^ (v >> 1) ^ mag[v & 1]; + pMTC->mti = 0; + } + v = pBuf[pMTC->mti++]; + v ^= (v >> 11); + v ^= (v << 7) & 0x9d2c5680UL; + v ^= (v << 15) & 0xefc60000UL; + v ^= (v >> 18); + return v; +} + +void FX_Random_MT_Close(void* pContext) { + FX_Free(pContext); +} + +void FX_Random_GenerateMT(uint32_t* pBuffer, int32_t iCount) { + void* pContext = ContextFromNextGlobalSeed(); + while (iCount-- > 0) + *pBuffer++ = FX_Random_MT_Generate(pContext); + + FX_Random_MT_Close(pContext); +} diff --git a/core/fxcrt/fx_random.h b/core/fxcrt/fx_random.h new file mode 100644 index 0000000000000000000000000000000000000000..52d514ba53e82e7b6fdc5e70efd0fbf8d0159bf7 --- /dev/null +++ b/core/fxcrt/fx_random.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_FX_RANDOM_H_ +#define CORE_FXCRT_FX_RANDOM_H_ + +#include + +void* FX_Random_MT_Start(uint32_t dwSeed); +void FX_Random_MT_Close(void* pContext); +uint32_t FX_Random_MT_Generate(void* pContext); + +void FX_Random_GenerateMT(uint32_t* pBuffer, int32_t iCount); + +#endif // CORE_FXCRT_FX_RANDOM_H_ diff --git a/core/fxcrt/fx_random_unittest.cpp b/core/fxcrt/fx_random_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..607f1409b7761cf8b087157dacf3548334b4b10b --- /dev/null +++ b/core/fxcrt/fx_random_unittest.cpp @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/fx_random.h" + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" + +TEST(FX_Random, GenerateMT3600times) { + // Prove this doesn't spin wait for a second each time. + // Since our global seeds are sequential, they wont't collide once + // seeded until 2^32 calls, and if the PNRG is any good, we won't + // get the same sequence from different seeds, esp. with this few + // iterations. + std::set> seen; + std::array current; + for (int i = 0; i < 3600; ++i) { + FX_Random_GenerateMT(current.data(), 16); + EXPECT_TRUE(seen.insert(current).second); + } +} diff --git a/core/fxcrt/fx_safe_types.h b/core/fxcrt/fx_safe_types.h index 66dbc576811a464818e5505aeb5b3385f72367e9..51eb89cf766306d1cf9e7832be777fbae229fcad 100644 --- a/core/fxcrt/fx_safe_types.h +++ b/core/fxcrt/fx_safe_types.h @@ -7,7 +7,6 @@ #include // For size_t. -#include "core/fxcrt/fx_stream.h" // for FX_FILESIZE. #include "core/fxcrt/fx_system.h" #include "third_party/base/numerics/safe_math.h" @@ -15,6 +14,5 @@ typedef pdfium::base::CheckedNumeric FX_SAFE_UINT32; typedef pdfium::base::CheckedNumeric FX_SAFE_INT32; typedef pdfium::base::CheckedNumeric FX_SAFE_SIZE_T; typedef pdfium::base::CheckedNumeric FX_SAFE_FILESIZE; -typedef pdfium::base::CheckedNumeric FX_SAFE_STRSIZE; #endif // CORE_FXCRT_FX_SAFE_TYPES_H_ diff --git a/core/fxcrt/fx_stream.cpp b/core/fxcrt/fx_stream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd75ad6ec736e8c32f56f0786a511f10ab86cb49 --- /dev/null +++ b/core/fxcrt/fx_stream.cpp @@ -0,0 +1,154 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/fx_stream.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/ifx_fileaccess.h" +#include "third_party/base/ptr_util.h" + +namespace { + +class CFX_CRTFileStream final : public IFX_SeekableStream { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + // IFX_SeekableStream: + FX_FILESIZE GetSize() override { return m_pFile->GetSize(); } + bool IsEOF() override { return GetPosition() >= GetSize(); } + FX_FILESIZE GetPosition() override { return m_pFile->GetPosition(); } + bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { + return m_pFile->ReadPos(buffer, size, offset) > 0; + } + size_t ReadBlock(void* buffer, size_t size) override { + return m_pFile->Read(buffer, size); + } + bool WriteBlock(const void* buffer, + FX_FILESIZE offset, + size_t size) override { + return !!m_pFile->WritePos(buffer, size, offset); + } + bool Flush() override { return m_pFile->Flush(); } + + private: + explicit CFX_CRTFileStream(std::unique_ptr pFA) + : m_pFile(std::move(pFA)) {} + ~CFX_CRTFileStream() override {} + + std::unique_ptr m_pFile; +}; + +} // namespace + +// static +RetainPtr IFX_SeekableStream::CreateFromFilename( + const char* filename, + uint32_t dwModes) { + std::unique_ptr pFA = IFX_FileAccess::Create(); + if (!pFA->Open(filename, dwModes)) + return nullptr; + return pdfium::MakeRetain(std::move(pFA)); +} + +// static +RetainPtr IFX_SeekableStream::CreateFromFilename( + const wchar_t* filename, + uint32_t dwModes) { + std::unique_ptr pFA = IFX_FileAccess::Create(); + if (!pFA->Open(filename, dwModes)) + return nullptr; + return pdfium::MakeRetain(std::move(pFA)); +} + +// static +RetainPtr IFX_SeekableReadStream::CreateFromFilename( + const char* filename) { + return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly); +} + +bool IFX_SeekableWriteStream::WriteBlock(const void* pData, size_t size) { + return WriteBlock(pData, GetSize(), size); +} + +bool IFX_SeekableReadStream::IsEOF() { + return false; +} + +FX_FILESIZE IFX_SeekableReadStream::GetPosition() { + return 0; +} + +size_t IFX_SeekableReadStream::ReadBlock(void* buffer, size_t size) { + return 0; +} + +bool IFX_SeekableStream::WriteBlock(const void* buffer, size_t size) { + return WriteBlock(buffer, GetSize(), size); +} + +bool IFX_SeekableStream::WriteString(const ByteStringView& str) { + return WriteBlock(str.unterminated_c_str(), str.GetLength()); +} + +FX_FileHandle* FX_OpenFolder(const char* path) { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + auto pData = pdfium::MakeUnique(); + pData->m_Handle = + FindFirstFileExA((ByteString(path) + "/*.*").c_str(), FindExInfoStandard, + &pData->m_FindData, FindExSearchNameMatch, nullptr, 0); + if (pData->m_Handle == INVALID_HANDLE_VALUE) + return nullptr; + + pData->m_bEnd = false; + return pData.release(); +#else + return opendir(path); +#endif +} + +bool FX_GetNextFile(FX_FileHandle* handle, + ByteString* filename, + bool* bFolder) { + if (!handle) + return false; + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + if (handle->m_bEnd) + return false; + + *filename = handle->m_FindData.cFileName; + *bFolder = + (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + if (!FindNextFileA(handle->m_Handle, &handle->m_FindData)) + handle->m_bEnd = true; + return true; +#else + struct dirent* de = readdir(handle); + if (!de) + return false; + *filename = de->d_name; + *bFolder = de->d_type == DT_DIR; + return true; +#endif +} + +void FX_CloseFolder(FX_FileHandle* handle) { + if (!handle) + return; + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + FindClose(handle->m_Handle); + delete handle; +#else + closedir(handle); +#endif +} diff --git a/core/fxcrt/fx_stream.h b/core/fxcrt/fx_stream.h index 2f4b5ad28055c5c5aa89ea94c7963f2c1f85e03c..8d0a596bd9da249ea73e06cdf0379d8106dd3940 100644 --- a/core/fxcrt/fx_stream.h +++ b/core/fxcrt/fx_stream.h @@ -7,18 +7,17 @@ #ifndef CORE_FXCRT_FX_STREAM_H_ #define CORE_FXCRT_FX_STREAM_H_ -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #include class CFindFileDataA; typedef CFindFileDataA FX_FileHandle; -#define FX_FILESIZE int32_t -#else +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #include #include @@ -26,35 +25,30 @@ typedef CFindFileDataA FX_FileHandle; #include #include -#ifndef O_BINARY -#define O_BINARY 0 -#endif // O_BINARY - -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif // O_LARGEFILE - typedef DIR FX_FileHandle; -#define FX_FILESIZE off_t -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ -FX_FileHandle* FX_OpenFolder(const FX_CHAR* path); -bool FX_GetNextFile(FX_FileHandle* handle, - CFX_ByteString* filename, - bool* bFolder); +FX_FileHandle* FX_OpenFolder(const char* path); +bool FX_GetNextFile(FX_FileHandle* handle, ByteString* filename, bool* bFolder); void FX_CloseFolder(FX_FileHandle* handle); -FX_WCHAR FX_GetFolderSeparator(); -#define FX_FILEMODE_Write 0 #define FX_FILEMODE_ReadOnly 1 #define FX_FILEMODE_Truncate 2 -class IFX_WriteStream : virtual public CFX_Retainable { +class IFX_WriteStream : virtual public Retainable { public: virtual bool WriteBlock(const void* pData, size_t size) = 0; + virtual bool WriteString(const ByteStringView& str) = 0; }; -class IFX_ReadStream : virtual public CFX_Retainable { +class IFX_ArchiveStream : public IFX_WriteStream { + public: + virtual bool WriteByte(uint8_t byte) = 0; + virtual bool WriteDWord(uint32_t i) = 0; + virtual FX_FILESIZE CurrentOffset() const = 0; +}; + +class IFX_ReadStream : virtual public Retainable { public: virtual bool IsEOF() = 0; virtual FX_FILESIZE GetPosition() = 0; @@ -75,8 +69,8 @@ class IFX_SeekableWriteStream : public IFX_WriteStream { class IFX_SeekableReadStream : public IFX_ReadStream { public: - static CFX_RetainPtr CreateFromFilename( - const FX_CHAR* filename); + static RetainPtr CreateFromFilename( + const char* filename); // IFX_ReadStream: bool IsEOF() override; @@ -90,12 +84,11 @@ class IFX_SeekableReadStream : public IFX_ReadStream { class IFX_SeekableStream : public IFX_SeekableReadStream, public IFX_SeekableWriteStream { public: - static CFX_RetainPtr CreateFromFilename( - const FX_CHAR* filename, - uint32_t dwModes); + static RetainPtr CreateFromFilename(const char* filename, + uint32_t dwModes); - static CFX_RetainPtr CreateFromFilename( - const FX_WCHAR* filename, + static RetainPtr CreateFromFilename( + const wchar_t* filename, uint32_t dwModes); // IFX_SeekableReadStream: @@ -110,51 +103,12 @@ class IFX_SeekableStream : public IFX_SeekableReadStream, FX_FILESIZE offset, size_t size) override = 0; bool WriteBlock(const void* buffer, size_t size) override; - bool Flush() override = 0; -}; - -class IFX_MemoryStream : public IFX_SeekableStream { - public: - static CFX_RetainPtr Create(uint8_t* pBuffer, - size_t nSize, - bool bTakeOver = false); - static CFX_RetainPtr Create(bool bConsecutive = false); - - virtual bool IsConsecutive() const = 0; - virtual void EstimateSize(size_t nInitSize, size_t nGrowSize) = 0; - virtual uint8_t* GetBuffer() const = 0; - virtual void AttachBuffer(uint8_t* pBuffer, - size_t nSize, - bool bTakeOver = false) = 0; - virtual void DetachBuffer() = 0; -}; + bool WriteString(const ByteStringView& str) override; -class IFX_BufferedReadStream : public IFX_ReadStream { - public: - // IFX_ReadStream: - bool IsEOF() override = 0; - FX_FILESIZE GetPosition() override = 0; - size_t ReadBlock(void* buffer, size_t size) override = 0; - - virtual bool ReadNextBlock(bool bRestart = false) = 0; - virtual const uint8_t* GetBlockBuffer() = 0; - virtual size_t GetBlockSize() = 0; - virtual FX_FILESIZE GetBlockOffset() = 0; -}; - -#ifdef PDF_ENABLE_XFA -class IFX_FileAccess : public CFX_Retainable { - public: - static CFX_RetainPtr CreateDefault( - const CFX_WideStringC& wsPath); - - virtual void GetPath(CFX_WideString& wsPath) = 0; - virtual CFX_RetainPtr CreateFileStream( - uint32_t dwModes) = 0; + bool Flush() override = 0; }; -#endif // PDF_ENABLE_XFA -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ class CFindFileData { public: virtual ~CFindFileData() {} @@ -167,12 +121,6 @@ class CFindFileDataA : public CFindFileData { ~CFindFileDataA() override {} WIN32_FIND_DATAA m_FindData; }; - -class CFindFileDataW : public CFindFileData { - public: - ~CFindFileDataW() override {} - WIN32_FIND_DATAW m_FindData; -}; #endif #endif // CORE_FXCRT_FX_STREAM_H_ diff --git a/core/fxcrt/fx_string.cpp b/core/fxcrt/fx_string.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13eb3a5bdd49d34f9e632ecbcaa2e1a1c14aa4ca --- /dev/null +++ b/core/fxcrt/fx_string.cpp @@ -0,0 +1,232 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_string.h" + +namespace { + +class CFX_UTF8Encoder { + public: + CFX_UTF8Encoder() {} + ~CFX_UTF8Encoder() {} + + void Input(wchar_t unicodeAsWchar) { + uint32_t unicode = static_cast(unicodeAsWchar); + if (unicode < 0x80) { + m_Buffer.push_back(unicode); + } else { + if (unicode >= 0x80000000) + return; + + int nbytes = 0; + if (unicode < 0x800) + nbytes = 2; + else if (unicode < 0x10000) + nbytes = 3; + else if (unicode < 0x200000) + nbytes = 4; + else if (unicode < 0x4000000) + nbytes = 5; + else + nbytes = 6; + + static uint8_t prefix[] = {0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; + int order = 1 << ((nbytes - 1) * 6); + int code = unicodeAsWchar; + m_Buffer.push_back(prefix[nbytes - 2] | (code / order)); + for (int i = 0; i < nbytes - 1; i++) { + code = code % order; + order >>= 6; + m_Buffer.push_back(0x80 | (code / order)); + } + } + } + + // The data returned by GetResult() is invalidated when this is modified by + // appending any data. + ByteStringView GetResult() const { + return ByteStringView(m_Buffer.data(), m_Buffer.size()); + } + + private: + std::vector m_Buffer; +}; + +} // namespace + +ByteString FX_UTF8Encode(const WideStringView& wsStr) { + size_t len = wsStr.GetLength(); + const wchar_t* pStr = wsStr.unterminated_c_str(); + CFX_UTF8Encoder encoder; + while (len-- > 0) + encoder.Input(*pStr++); + + return ByteString(encoder.GetResult()); +} + +namespace { + +const float fraction_scales[] = {0.1f, 0.01f, 0.001f, + 0.0001f, 0.00001f, 0.000001f, + 0.0000001f, 0.00000001f, 0.000000001f, + 0.0000000001f, 0.00000000001f}; + +float FractionalScale(size_t scale_factor, int value) { + return fraction_scales[scale_factor] * value; +} + +} // namespace + +bool FX_atonum(const ByteStringView& strc, void* pData) { + if (strc.Contains('.')) { + float* pFloat = static_cast(pData); + *pFloat = FX_atof(strc); + return false; + } + + // Note, numbers in PDF are typically of the form 123, -123, etc. But, + // for things like the Permissions on the encryption hash the number is + // actually an unsigned value. We use a uint32_t so we can deal with the + // unsigned and then check for overflow if the user actually signed the value. + // The Permissions flag is listed in Table 3.20 PDF 1.7 spec. + pdfium::base::CheckedNumeric integer = 0; + bool bNegative = false; + bool bSigned = false; + size_t cc = 0; + if (strc[0] == '+') { + cc++; + bSigned = true; + } else if (strc[0] == '-') { + bNegative = true; + bSigned = true; + cc++; + } + + while (cc < strc.GetLength() && std::isdigit(strc[cc])) { + integer = integer * 10 + FXSYS_DecimalCharToInt(strc.CharAt(cc)); + if (!integer.IsValid()) + break; + cc++; + } + + // We have a sign, and the value was greater then a regular integer + // we've overflowed, reset to the default value. + if (bSigned) { + if (bNegative) { + if (integer.ValueOrDefault(0) > + static_cast(std::numeric_limits::max()) + 1) { + integer = 0; + } + } else if (integer.ValueOrDefault(0) > + static_cast(std::numeric_limits::max())) { + integer = 0; + } + } + + // Switch back to the int space so we can flip to a negative if we need. + uint32_t uValue = integer.ValueOrDefault(0); + int32_t value = static_cast(uValue); + if (bNegative) + value = -value; + + int* pInt = static_cast(pData); + *pInt = value; + return true; +} + +float FX_atof(const ByteStringView& strc) { + if (strc.IsEmpty()) + return 0.0; + + int cc = 0; + bool bNegative = false; + int len = strc.GetLength(); + if (strc[0] == '+') { + cc++; + } else if (strc[0] == '-') { + bNegative = true; + cc++; + } + while (cc < len) { + if (strc[cc] != '+' && strc[cc] != '-') + break; + cc++; + } + float value = 0; + while (cc < len) { + if (strc[cc] == '.') + break; + value = value * 10 + FXSYS_DecimalCharToInt(strc.CharAt(cc)); + cc++; + } + int scale = 0; + if (cc < len && strc[cc] == '.') { + cc++; + while (cc < len) { + value += FractionalScale(scale, FXSYS_DecimalCharToInt(strc.CharAt(cc))); + scale++; + if (scale == FX_ArraySize(fraction_scales)) + break; + cc++; + } + } + return bNegative ? -value : value; +} + +float FX_atof(const WideStringView& wsStr) { + return FX_atof(FX_UTF8Encode(wsStr).c_str()); +} + +size_t FX_ftoa(float d, char* buf) { + buf[0] = '0'; + buf[1] = '\0'; + if (d == 0.0f) { + return 1; + } + bool bNegative = false; + if (d < 0) { + bNegative = true; + d = -d; + } + int scale = 1; + int scaled = FXSYS_round(d); + while (scaled < 100000) { + if (scale == 1000000) { + break; + } + scale *= 10; + scaled = FXSYS_round(d * scale); + } + if (scaled == 0) { + return 1; + } + char buf2[32]; + size_t buf_size = 0; + if (bNegative) { + buf[buf_size++] = '-'; + } + int i = scaled / scale; + FXSYS_itoa(i, buf2, 10); + size_t len = strlen(buf2); + memcpy(buf + buf_size, buf2, len); + buf_size += len; + int fraction = scaled % scale; + if (fraction == 0) { + return buf_size; + } + buf[buf_size++] = '.'; + scale /= 10; + while (fraction) { + buf[buf_size++] = '0' + fraction / scale; + fraction %= scale; + scale /= 10; + } + return buf_size; +} diff --git a/core/fxcrt/fx_string.h b/core/fxcrt/fx_string.h index cd93f272750d5755bd2ce54bc229bb4617ae21ce..4c24181e372a534abf2f0c5c8e9dc2a4745b6ee9 100644 --- a/core/fxcrt/fx_string.h +++ b/core/fxcrt/fx_string.h @@ -7,453 +7,17 @@ #ifndef CORE_FXCRT_FX_STRING_H_ #define CORE_FXCRT_FX_STRING_H_ -#include // For intptr_t. - -#include -#include - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/cfx_string_c_template.h" -#include "core/fxcrt/cfx_string_data_template.h" -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" - -class CFX_ByteString; -class CFX_WideString; - -using CFX_ByteStringC = CFX_StringCTemplate; -using CFX_WideStringC = CFX_StringCTemplate; +#include "core/fxcrt/bytestring.h" +#include "core/fxcrt/widestring.h" #define FXBSTR_ID(c1, c2, c3, c4) \ (((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) | ((uint32_t)c3 << 8) | \ ((uint32_t)c4)) -// A mutable string with shared buffers using copy-on-write semantics that -// avoids the cost of std::string's iterator stability guarantees. -class CFX_ByteString { - public: - using CharType = FX_CHAR; - - CFX_ByteString(); - CFX_ByteString(const CFX_ByteString& other); - CFX_ByteString(CFX_ByteString&& other); - - // Deliberately implicit to avoid calling on every string literal. - // NOLINTNEXTLINE(runtime/explicit) - CFX_ByteString(char ch); - // NOLINTNEXTLINE(runtime/explicit) - CFX_ByteString(const FX_CHAR* ptr); - - CFX_ByteString(const FX_CHAR* ptr, FX_STRSIZE len); - CFX_ByteString(const uint8_t* ptr, FX_STRSIZE len); - - explicit CFX_ByteString(const CFX_ByteStringC& bstrc); - CFX_ByteString(const CFX_ByteStringC& bstrc1, const CFX_ByteStringC& bstrc2); - - ~CFX_ByteString(); - - void clear() { m_pData.Reset(); } - - static CFX_ByteString FromUnicode(const FX_WCHAR* ptr, FX_STRSIZE len = -1); - static CFX_ByteString FromUnicode(const CFX_WideString& str); - - // Explicit conversion to C-style string. - // Note: Any subsequent modification of |this| will invalidate the result. - const FX_CHAR* c_str() const { return m_pData ? m_pData->m_String : ""; } - - // Explicit conversion to uint8_t*. - // Note: Any subsequent modification of |this| will invalidate the result. - const uint8_t* raw_str() const { - return m_pData ? reinterpret_cast(m_pData->m_String) - : nullptr; - } - - // Explicit conversion to CFX_ByteStringC. - // Note: Any subsequent modification of |this| will invalidate the result. - CFX_ByteStringC AsStringC() const { - return CFX_ByteStringC(raw_str(), GetLength()); - } - - FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } - bool IsEmpty() const { return !GetLength(); } - - int Compare(const CFX_ByteStringC& str) const; - bool EqualNoCase(const CFX_ByteStringC& str) const; - - bool operator==(const char* ptr) const; - bool operator==(const CFX_ByteStringC& str) const; - bool operator==(const CFX_ByteString& other) const; - - bool operator!=(const char* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_ByteStringC& str) const { return !(*this == str); } - bool operator!=(const CFX_ByteString& other) const { - return !(*this == other); - } - - bool operator<(const CFX_ByteString& str) const; - - const CFX_ByteString& operator=(const FX_CHAR* str); - const CFX_ByteString& operator=(const CFX_ByteStringC& bstrc); - const CFX_ByteString& operator=(const CFX_ByteString& stringSrc); - - const CFX_ByteString& operator+=(FX_CHAR ch); - const CFX_ByteString& operator+=(const FX_CHAR* str); - const CFX_ByteString& operator+=(const CFX_ByteString& str); - const CFX_ByteString& operator+=(const CFX_ByteStringC& bstrc); - - uint8_t GetAt(FX_STRSIZE nIndex) const { - return m_pData ? m_pData->m_String[nIndex] : 0; - } - - uint8_t operator[](FX_STRSIZE nIndex) const { - return m_pData ? m_pData->m_String[nIndex] : 0; - } - - void SetAt(FX_STRSIZE nIndex, FX_CHAR ch); - FX_STRSIZE Insert(FX_STRSIZE index, FX_CHAR ch); - FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); - - void Format(const FX_CHAR* lpszFormat, ...); - void FormatV(const FX_CHAR* lpszFormat, va_list argList); - - void Reserve(FX_STRSIZE len); - FX_CHAR* GetBuffer(FX_STRSIZE len); - void ReleaseBuffer(FX_STRSIZE len = -1); - - CFX_ByteString Mid(FX_STRSIZE first) const; - CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const; - CFX_ByteString Left(FX_STRSIZE count) const; - CFX_ByteString Right(FX_STRSIZE count) const; - - FX_STRSIZE Find(const CFX_ByteStringC& lpszSub, FX_STRSIZE start = 0) const; - FX_STRSIZE Find(FX_CHAR ch, FX_STRSIZE start = 0) const; - FX_STRSIZE ReverseFind(FX_CHAR ch) const; - - void MakeLower(); - void MakeUpper(); - - void TrimRight(); - void TrimRight(FX_CHAR chTarget); - void TrimRight(const CFX_ByteStringC& lpszTargets); - - void TrimLeft(); - void TrimLeft(FX_CHAR chTarget); - void TrimLeft(const CFX_ByteStringC& lpszTargets); - - FX_STRSIZE Replace(const CFX_ByteStringC& lpszOld, - const CFX_ByteStringC& lpszNew); - - FX_STRSIZE Remove(FX_CHAR ch); - - CFX_WideString UTF8Decode() const; - - uint32_t GetID(FX_STRSIZE start_pos = 0) const; - -#define FXFORMAT_SIGNED 1 -#define FXFORMAT_HEX 2 -#define FXFORMAT_CAPITAL 4 - - static CFX_ByteString FormatInteger(int i, uint32_t flags = 0); - static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0); - - protected: - using StringData = CFX_StringDataTemplate; - - void ReallocBeforeWrite(FX_STRSIZE nNewLen); - void AllocBeforeWrite(FX_STRSIZE nNewLen); - void AllocCopy(CFX_ByteString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const; - void AssignCopy(const FX_CHAR* pSrcData, FX_STRSIZE nSrcLen); - void Concat(const FX_CHAR* lpszSrcData, FX_STRSIZE nSrcLen); - - CFX_RetainPtr m_pData; - - friend class fxcrt_ByteStringConcat_Test; - friend class fxcrt_ByteStringPool_Test; -}; - -inline bool operator==(const char* lhs, const CFX_ByteString& rhs) { - return rhs == lhs; -} -inline bool operator==(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { - return rhs == lhs; -} -inline bool operator!=(const char* lhs, const CFX_ByteString& rhs) { - return rhs != lhs; -} -inline bool operator!=(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { - return rhs != lhs; -} - -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, - const CFX_ByteStringC& str2) { - return CFX_ByteString(str1, str2); -} -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, - const FX_CHAR* str2) { - return CFX_ByteString(str1, str2); -} -inline CFX_ByteString operator+(const FX_CHAR* str1, - const CFX_ByteStringC& str2) { - return CFX_ByteString(str1, str2); -} -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, FX_CHAR ch) { - return CFX_ByteString(str1, CFX_ByteStringC(ch)); -} -inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteStringC& str2) { - return CFX_ByteString(ch, str2); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, - const CFX_ByteString& str2) { - return CFX_ByteString(str1.AsStringC(), str2.AsStringC()); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, FX_CHAR ch) { - return CFX_ByteString(str1.AsStringC(), CFX_ByteStringC(ch)); -} -inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteString& str2) { - return CFX_ByteString(ch, str2.AsStringC()); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, - const FX_CHAR* str2) { - return CFX_ByteString(str1.AsStringC(), str2); -} -inline CFX_ByteString operator+(const FX_CHAR* str1, - const CFX_ByteString& str2) { - return CFX_ByteString(str1, str2.AsStringC()); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, - const CFX_ByteStringC& str2) { - return CFX_ByteString(str1.AsStringC(), str2); -} -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, - const CFX_ByteString& str2) { - return CFX_ByteString(str1, str2.AsStringC()); -} - -// A mutable string with shared buffers using copy-on-write semantics that -// avoids the cost of std::string's iterator stability guarantees. -class CFX_WideString { - public: - using CharType = FX_WCHAR; - - CFX_WideString(); - CFX_WideString(const CFX_WideString& other); - CFX_WideString(CFX_WideString&& other); - - // Deliberately implicit to avoid calling on every string literal. - // NOLINTNEXTLINE(runtime/explicit) - CFX_WideString(FX_WCHAR ch); - // NOLINTNEXTLINE(runtime/explicit) - CFX_WideString(const FX_WCHAR* ptr); - - CFX_WideString(const FX_WCHAR* ptr, FX_STRSIZE len); - - explicit CFX_WideString(const CFX_WideStringC& str); - CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2); - - ~CFX_WideString(); - - static CFX_WideString FromLocal(const CFX_ByteStringC& str); - static CFX_WideString FromCodePage(const CFX_ByteStringC& str, - uint16_t codepage); - - static CFX_WideString FromUTF8(const CFX_ByteStringC& str); - static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len); - - static FX_STRSIZE WStringLength(const unsigned short* str); - - // Explicit conversion to C-style wide string. - // Note: Any subsequent modification of |this| will invalidate the result. - const FX_WCHAR* c_str() const { return m_pData ? m_pData->m_String : L""; } - - // Explicit conversion to CFX_WideStringC. - // Note: Any subsequent modification of |this| will invalidate the result. - CFX_WideStringC AsStringC() const { - return CFX_WideStringC(c_str(), GetLength()); - } - - void clear() { m_pData.Reset(); } - - FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } - bool IsEmpty() const { return !GetLength(); } - - const CFX_WideString& operator=(const FX_WCHAR* str); - const CFX_WideString& operator=(const CFX_WideString& stringSrc); - const CFX_WideString& operator=(const CFX_WideStringC& stringSrc); - - const CFX_WideString& operator+=(const FX_WCHAR* str); - const CFX_WideString& operator+=(FX_WCHAR ch); - const CFX_WideString& operator+=(const CFX_WideString& str); - const CFX_WideString& operator+=(const CFX_WideStringC& str); - - bool operator==(const wchar_t* ptr) const; - bool operator==(const CFX_WideStringC& str) const; - bool operator==(const CFX_WideString& other) const; - - bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } - bool operator!=(const CFX_WideString& other) const { - return !(*this == other); - } - - bool operator<(const CFX_WideString& str) const; - - FX_WCHAR GetAt(FX_STRSIZE nIndex) const { - return m_pData ? m_pData->m_String[nIndex] : 0; - } - - FX_WCHAR operator[](FX_STRSIZE nIndex) const { - return m_pData ? m_pData->m_String[nIndex] : 0; - } - - void SetAt(FX_STRSIZE nIndex, FX_WCHAR ch); - - int Compare(const FX_WCHAR* str) const; - int Compare(const CFX_WideString& str) const; - int CompareNoCase(const FX_WCHAR* str) const; - - CFX_WideString Mid(FX_STRSIZE first) const; - CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const; - CFX_WideString Left(FX_STRSIZE count) const; - CFX_WideString Right(FX_STRSIZE count) const; - - FX_STRSIZE Insert(FX_STRSIZE index, FX_WCHAR ch); - FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); - - void Format(const FX_WCHAR* lpszFormat, ...); - void FormatV(const FX_WCHAR* lpszFormat, va_list argList); - - void MakeLower(); - void MakeUpper(); - - void TrimRight(); - void TrimRight(FX_WCHAR chTarget); - void TrimRight(const CFX_WideStringC& pTargets); - - void TrimLeft(); - void TrimLeft(FX_WCHAR chTarget); - void TrimLeft(const CFX_WideStringC& pTargets); - - void Reserve(FX_STRSIZE len); - FX_WCHAR* GetBuffer(FX_STRSIZE len); - void ReleaseBuffer(FX_STRSIZE len = -1); - - int GetInteger() const; - FX_FLOAT GetFloat() const; - - FX_STRSIZE Find(const CFX_WideStringC& pSub, FX_STRSIZE start = 0) const; - FX_STRSIZE Find(FX_WCHAR ch, FX_STRSIZE start = 0) const; - FX_STRSIZE Replace(const CFX_WideStringC& pOld, const CFX_WideStringC& pNew); - FX_STRSIZE Remove(FX_WCHAR ch); - - CFX_ByteString UTF8Encode() const; - CFX_ByteString UTF16LE_Encode() const; - - protected: - using StringData = CFX_StringDataTemplate; - - void ReallocBeforeWrite(FX_STRSIZE nLen); - void AllocBeforeWrite(FX_STRSIZE nLen); - void AllocCopy(CFX_WideString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const; - void AssignCopy(const FX_WCHAR* pSrcData, FX_STRSIZE nSrcLen); - void Concat(const FX_WCHAR* lpszSrcData, FX_STRSIZE nSrcLen); - - CFX_RetainPtr m_pData; - - friend class fxcrt_WideStringConcatInPlace_Test; - friend class fxcrt_WideStringPool_Test; -}; - -inline CFX_WideString operator+(const CFX_WideStringC& str1, - const CFX_WideStringC& str2) { - return CFX_WideString(str1, str2); -} -inline CFX_WideString operator+(const CFX_WideStringC& str1, - const FX_WCHAR* str2) { - return CFX_WideString(str1, str2); -} -inline CFX_WideString operator+(const FX_WCHAR* str1, - const CFX_WideStringC& str2) { - return CFX_WideString(str1, str2); -} -inline CFX_WideString operator+(const CFX_WideStringC& str1, FX_WCHAR ch) { - return CFX_WideString(str1, CFX_WideStringC(ch)); -} -inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideStringC& str2) { - return CFX_WideString(ch, str2); -} -inline CFX_WideString operator+(const CFX_WideString& str1, - const CFX_WideString& str2) { - return CFX_WideString(str1.AsStringC(), str2.AsStringC()); -} -inline CFX_WideString operator+(const CFX_WideString& str1, FX_WCHAR ch) { - return CFX_WideString(str1.AsStringC(), CFX_WideStringC(ch)); -} -inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideString& str2) { - return CFX_WideString(ch, str2.AsStringC()); -} -inline CFX_WideString operator+(const CFX_WideString& str1, - const FX_WCHAR* str2) { - return CFX_WideString(str1.AsStringC(), str2); -} -inline CFX_WideString operator+(const FX_WCHAR* str1, - const CFX_WideString& str2) { - return CFX_WideString(str1, str2.AsStringC()); -} -inline CFX_WideString operator+(const CFX_WideString& str1, - const CFX_WideStringC& str2) { - return CFX_WideString(str1.AsStringC(), str2); -} -inline CFX_WideString operator+(const CFX_WideStringC& str1, - const CFX_WideString& str2) { - return CFX_WideString(str1, str2.AsStringC()); -} -inline bool operator==(const wchar_t* lhs, const CFX_WideString& rhs) { - return rhs == lhs; -} -inline bool operator==(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { - return rhs == lhs; -} -inline bool operator!=(const wchar_t* lhs, const CFX_WideString& rhs) { - return rhs != lhs; -} -inline bool operator!=(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { - return rhs != lhs; -} - -CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr); -FX_FLOAT FX_atof(const CFX_ByteStringC& str); -inline FX_FLOAT FX_atof(const CFX_WideStringC& wsStr) { - return FX_atof(FX_UTF8Encode(wsStr).c_str()); -} -bool FX_atonum(const CFX_ByteStringC& str, void* pData); -FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_CHAR* buf); - -uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase); -uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase); - -namespace std { - -template <> -struct hash { - std::size_t operator()(const CFX_ByteString& str) const { - return FX_HashCode_GetA(str.AsStringC(), false); - } -}; - -template <> -struct hash { - std::size_t operator()(const CFX_WideString& str) const { - return FX_HashCode_GetW(str.AsStringC(), false); - } -}; - -} // namespace std - -extern template struct std::hash; -extern template struct std::hash; +ByteString FX_UTF8Encode(const WideStringView& wsStr); +float FX_atof(const ByteStringView& str); +float FX_atof(const WideStringView& wsStr); +bool FX_atonum(const ByteStringView& str, void* pData); +size_t FX_ftoa(float f, char* buf); #endif // CORE_FXCRT_FX_STRING_H_ diff --git a/core/fxcrt/fx_string_unittest.cpp b/core/fxcrt/fx_string_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b311165638f4c054b4531ab18e8327be6de6e57f --- /dev/null +++ b/core/fxcrt/fx_string_unittest.cpp @@ -0,0 +1,53 @@ +// Copyright 2016 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. + +#include + +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(fxstring, FX_atonum) { + int i; + EXPECT_TRUE(FX_atonum("10", &i)); + EXPECT_EQ(10, i); + + EXPECT_TRUE(FX_atonum("-10", &i)); + EXPECT_EQ(-10, i); + + EXPECT_TRUE(FX_atonum("+10", &i)); + EXPECT_EQ(10, i); + + EXPECT_TRUE(FX_atonum("-2147483648", &i)); + EXPECT_EQ(std::numeric_limits::min(), i); + + EXPECT_TRUE(FX_atonum("2147483647", &i)); + EXPECT_EQ(2147483647, i); + + // Value overflows. + EXPECT_TRUE(FX_atonum("-2147483649", &i)); + EXPECT_EQ(0, i); + + // Value overflows. + EXPECT_TRUE(FX_atonum("+2147483648", &i)); + EXPECT_EQ(0, i); + + // Value overflows. + EXPECT_TRUE(FX_atonum("4223423494965252", &i)); + EXPECT_EQ(0, i); + + // No explicit sign will allow the number to go negative. This is for things + // like the encryption Permissions flag (Table 3.20 PDF 1.7 spec) + EXPECT_TRUE(FX_atonum("4294965252", &i)); + EXPECT_EQ(-2044, i); + + EXPECT_TRUE(FX_atonum("-4294965252", &i)); + EXPECT_EQ(0, i); + + EXPECT_TRUE(FX_atonum("+4294965252", &i)); + EXPECT_EQ(0, i); + + float f; + EXPECT_FALSE(FX_atonum("3.24", &f)); + EXPECT_FLOAT_EQ(3.24f, f); +} diff --git a/core/fxcrt/fx_system.cpp b/core/fxcrt/fx_system.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5ceec5be162b8a8916aa5f19471ddf8e7980e29 --- /dev/null +++ b/core/fxcrt/fx_system.cpp @@ -0,0 +1,242 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/fx_system.h" + +#include + +#include "core/fxcrt/fx_extension.h" + +namespace { + +template +IntType FXSYS_StrToInt(const CharType* str) { + if (!str) + return 0; + + // Process the sign. + bool neg = *str == '-'; + if (neg || *str == '+') + str++; + + IntType num = 0; + while (*str && FXSYS_isDecimalDigit(*str)) { + IntType val = FXSYS_DecimalCharToInt(*str); + if (num > (std::numeric_limits::max() - val) / 10) { + if (neg && std::numeric_limits::is_signed) { + // Return MIN when the represented number is signed type and is smaller + // than the min value. + return std::numeric_limits::min(); + } else { + // Return MAX when the represented number is signed type and is larger + // than the max value, or the number is unsigned type and out of range. + return std::numeric_limits::max(); + } + } + + num = num * 10 + val; + str++; + } + // When it is a negative value, -num should be returned. Since num may be of + // unsigned type, use ~num + 1 to avoid the warning of applying unary minus + // operator to unsigned type. + return neg ? ~num + 1 : num; +} + +template +STR_T FXSYS_IntToStr(T value, STR_T str, int radix) { + if (radix < 2 || radix > 16) { + str[0] = 0; + return str; + } + if (value == 0) { + str[0] = '0'; + str[1] = 0; + return str; + } + int i = 0; + UT uvalue; + if (value < 0) { + str[i++] = '-'; + // Standard trick to avoid undefined behaviour when negating INT_MIN. + uvalue = static_cast(-(value + 1)) + 1; + } else { + uvalue = value; + } + int digits = 1; + T order = uvalue / radix; + while (order > 0) { + digits++; + order = order / radix; + } + for (int d = digits - 1; d > -1; d--) { + str[d + i] = "0123456789abcdef"[uvalue % radix]; + uvalue /= radix; + } + str[digits + i] = 0; + return str; +} + +} // namespace + +int FXSYS_round(float d) { + if (d < static_cast(std::numeric_limits::min())) + return std::numeric_limits::min(); + if (d > static_cast(std::numeric_limits::max())) + return std::numeric_limits::max(); + return static_cast(round(d)); +} + +int32_t FXSYS_atoi(const char* str) { + return FXSYS_StrToInt(str); +} +uint32_t FXSYS_atoui(const char* str) { + return FXSYS_StrToInt(str); +} +int32_t FXSYS_wtoi(const wchar_t* str) { + return FXSYS_StrToInt(str); +} +int64_t FXSYS_atoi64(const char* str) { + return FXSYS_StrToInt(str); +} +const char* FXSYS_i64toa(int64_t value, char* str, int radix) { + return FXSYS_IntToStr(value, str, radix); +} + +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + +int FXSYS_GetACP() { + return 0; +} + +char* FXSYS_strlwr(char* str) { + if (!str) { + return nullptr; + } + char* s = str; + while (*str) { + *str = FXSYS_tolower(*str); + str++; + } + return s; +} +char* FXSYS_strupr(char* str) { + if (!str) { + return nullptr; + } + char* s = str; + while (*str) { + *str = FXSYS_toupper(*str); + str++; + } + return s; +} +wchar_t* FXSYS_wcslwr(wchar_t* str) { + if (!str) { + return nullptr; + } + wchar_t* s = str; + while (*str) { + *str = FXSYS_tolower(*str); + str++; + } + return s; +} +wchar_t* FXSYS_wcsupr(wchar_t* str) { + if (!str) { + return nullptr; + } + wchar_t* s = str; + while (*str) { + *str = FXSYS_toupper(*str); + str++; + } + return s; +} + +int FXSYS_stricmp(const char* dst, const char* src) { + int f; + int l; + do { + f = FXSYS_toupper(*dst); + l = FXSYS_toupper(*src); + ++dst; + ++src; + } while (f && f == l); + return f - l; +} + +int FXSYS_wcsicmp(const wchar_t* dst, const wchar_t* src) { + wchar_t f; + wchar_t l; + do { + f = FXSYS_toupper(*dst); + l = FXSYS_toupper(*src); + ++dst; + ++src; + } while (f && f == l); + return f - l; +} + +char* FXSYS_itoa(int value, char* str, int radix) { + return FXSYS_IntToStr(value, str, radix); +} + +int FXSYS_WideCharToMultiByte(uint32_t codepage, + uint32_t dwFlags, + const wchar_t* wstr, + int wlen, + char* buf, + int buflen, + const char* default_str, + int* pUseDefault) { + int len = 0; + for (int i = 0; i < wlen; i++) { + if (wstr[i] < 0x100) { + if (buf && len < buflen) + buf[len] = static_cast(wstr[i]); + len++; + } + } + return len; +} +int FXSYS_MultiByteToWideChar(uint32_t codepage, + uint32_t dwFlags, + const char* bstr, + int blen, + wchar_t* buf, + int buflen) { + int wlen = 0; + for (int i = 0; i < blen; i++) { + if (buf && wlen < buflen) { + buf[wlen] = bstr[i]; + } + wlen++; + } + return wlen; +} + +#else // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + +size_t FXSYS_wcsftime(wchar_t* strDest, + size_t maxsize, + const wchar_t* format, + const struct tm* timeptr) { + // Avoid tripping an invalid parameter handler and crashing process. + // Note: leap seconds may cause tm_sec == 60. + if (timeptr->tm_year < -1900 || timeptr->tm_year > 8099 || + timeptr->tm_mon < 0 || timeptr->tm_mon > 11 || timeptr->tm_mday < 1 || + timeptr->tm_mday > 31 || timeptr->tm_hour < 0 || timeptr->tm_hour > 23 || + timeptr->tm_min < 0 || timeptr->tm_min > 59 || timeptr->tm_sec < 0 || + timeptr->tm_sec > 60 || timeptr->tm_wday < 0 || timeptr->tm_wday > 6 || + timeptr->tm_yday < 0 || timeptr->tm_yday > 365) { + strDest[0] = L'\0'; + return 0; + } + return wcsftime(strDest, maxsize, format, timeptr); +} + +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ diff --git a/core/fxcrt/fx_system.h b/core/fxcrt/fx_system.h index c31bef974fe06f42d63d66d2d5751596f6d62e32..8ad23a19c733607a40ab3a156a5a2e93a8553736 100644 --- a/core/fxcrt/fx_system.h +++ b/core/fxcrt/fx_system.h @@ -18,34 +18,38 @@ #include // _FX_OS_ values: -#define _FX_WIN32_DESKTOP_ 1 -#define _FX_WIN64_DESKTOP_ 2 -#define _FX_LINUX_DESKTOP_ 4 -#define _FX_MACOSX_ 7 -#define _FX_ANDROID_ 12 - -// _FXM_PLATFORM_ values; -#define _FXM_PLATFORM_WINDOWS_ 1 // _FX_WIN32_DESKTOP_ or _FX_WIN64_DESKTOP_. -#define _FXM_PLATFORM_LINUX_ 2 // _FX_LINUX_DESKTOP_ always. -#define _FXM_PLATFORM_APPLE_ 3 // _FX_MACOSX_ always. -#define _FXM_PLATFORM_ANDROID_ 4 // _FX_ANDROID_ always. +#define _FX_OS_WIN32_ 1 +#define _FX_OS_WIN64_ 2 +#define _FX_OS_LINUX_ 4 +#define _FX_OS_MACOSX_ 7 +#define _FX_OS_ANDROID_ 12 +#define _FX_OS_WASM_ 13 + +// _FX_PLATFORM_ values; +#define _FX_PLATFORM_WINDOWS_ 1 // _FX_OS_WIN32_ or _FX_OS_WIN64_. +#define _FX_PLATFORM_LINUX_ 2 // _FX_OS_LINUX_ or _FX_OS_WASM_. +#define _FX_PLATFORM_APPLE_ 3 // _FX_OS_MACOSX_ always. +#define _FX_PLATFORM_ANDROID_ 4 // _FX_OS_ANDROID_ always. #ifndef _FX_OS_ #if defined(__ANDROID__) -#define _FX_OS_ _FX_ANDROID_ -#define _FXM_PLATFORM_ _FXM_PLATFORM_ANDROID_ +#define _FX_OS_ _FX_OS_ANDROID_ +#define _FX_PLATFORM_ _FX_PLATFORM_ANDROID_ #elif defined(_WIN32) -#define _FX_OS_ _FX_WIN32_DESKTOP_ -#define _FXM_PLATFORM_ _FXM_PLATFORM_WINDOWS_ +#define _FX_OS_ _FX_OS_WIN32_ +#define _FX_PLATFORM_ _FX_PLATFORM_WINDOWS_ #elif defined(_WIN64) -#define _FX_OS_ _FX_WIN64_DESKTOP_ -#define _FXM_PLATFORM_ _FXM_PLATFORM_WINDOWS_ +#define _FX_OS_ _FX_OS_WIN64_ +#define _FX_PLATFORM_ _FX_PLATFORM_WINDOWS_ #elif defined(__linux__) -#define _FX_OS_ _FX_LINUX_DESKTOP_ -#define _FXM_PLATFORM_ _FXM_PLATFORM_LINUX_ +#define _FX_OS_ _FX_OS_LINUX_ +#define _FX_PLATFORM_ _FX_PLATFORM_LINUX_ #elif defined(__APPLE__) -#define _FX_OS_ _FX_MACOSX_ -#define _FXM_PLATFORM_ _FXM_PLATFORM_APPLE_ +#define _FX_OS_ _FX_OS_MACOSX_ +#define _FX_PLATFORM_ _FX_PLATFORM_APPLE_ +#elif defined(__asmjs__) || defined(__wasm__) +#define _FX_OS_ _FX_OS_WASM_ +#define _FX_PLATFORM_ _FX_PLATFORM_LINUX_ #endif #endif // _FX_OS_ @@ -53,155 +57,112 @@ #error Sorry, can not figure out target OS. Please specify _FX_OS_ macro. #endif -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#error Sorry, VC++ 2015 or later is required to compile PDFium. +#endif // defined(_MSC_VER) && _MSC_VER < 1900 + +#if _FX_OS_ == _FX_OS_WASM_ && defined(PDF_ENABLE_V8) +#error Cannot compile v8 with wasm. +#endif // PDF_ENABLE_V8 + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #include #include -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ #include #include -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ #ifdef __cplusplus extern "C" { #endif // __cplusplus -typedef void* FX_POSITION; // Keep until fxcrt containers gone -typedef float FX_FLOAT; // Keep, allow upgrade to doubles. -typedef double FX_DOUBLE; // Keep, allow downgrade to floats. -typedef char FX_CHAR; // Keep, questionable signedness. -typedef wchar_t FX_WCHAR; // Keep, maybe bad platform wchars. - #define IsFloatZero(f) ((f) < 0.0001 && (f) > -0.0001) #define IsFloatBigger(fa, fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb))) #define IsFloatSmaller(fa, fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb))) #define IsFloatEqual(fa, fb) IsFloatZero((fa) - (fb)) -// PDFium string sizes are limited to 2^31-1, and the value is signed to -// allow -1 as a placeholder for "unknown". -// TODO(palmer): it should be a |size_t|, or at least unsigned. -typedef int FX_STRSIZE; +// PDFium file sizes match the platform, but PDFium itself does not support +// files larger than 2GB even if the platform does. The value must be signed +// to support -1 error returns. +// TODO(tsepez): support larger files. +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#define FX_FILESIZE int32_t +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#define FX_FILESIZE off_t +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #ifndef ASSERT #ifndef NDEBUG #define ASSERT assert #else #define ASSERT(a) -#endif -#endif +#endif // NDEBUG +#endif // ASSERT #if defined(__clang__) || defined(__GNUC__) #define PDFIUM_IMMEDIATE_CRASH() __builtin_trap() #else #define PDFIUM_IMMEDIATE_CRASH() ((void)(*(volatile char*)0 = 0)) -#endif +#endif // defined(__clang__) || defined(__GNUC__) // M_PI not universally present on all platforms. #define FX_PI 3.1415926535897932384626433832795f #define FX_BEZIER 0.5522847498308f // NOTE: prevent use of the return value from snprintf() since some platforms -// have different return values (e.g. windows _vsnprintf()), and provide -// versions that always NUL-terminate. -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 -void FXSYS_snprintf(char* str, - size_t size, - _Printf_format_string_ const char* fmt, - ...); -void FXSYS_vsnprintf(char* str, size_t size, const char* fmt, va_list ap); -#else +// have different return values. #define FXSYS_snprintf (void)snprintf #define FXSYS_vsnprintf (void)vsnprintf -#endif - #define FXSYS_sprintf DO_NOT_USE_SPRINTF_DIE_DIE_DIE #define FXSYS_vsprintf DO_NOT_USE_VSPRINTF_DIE_DIE_DIE -#define FXSYS_strncmp strncmp -#define FXSYS_strcmp strcmp -#define FXSYS_strcpy strcpy -#define FXSYS_strncpy strncpy -#define FXSYS_strstr strstr -#define FXSYS_FILE FILE -#define FXSYS_fopen fopen -#define FXSYS_fclose fclose -#define FXSYS_SEEK_END SEEK_END -#define FXSYS_SEEK_SET SEEK_SET -#define FXSYS_fseek fseek -#define FXSYS_ftell ftell -#define FXSYS_fread fread -#define FXSYS_fwrite fwrite -#define FXSYS_fprintf fprintf -#define FXSYS_fflush fflush - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#ifdef _NATIVE_WCHAR_T_DEFINED -#define FXSYS_wfopen(f, m) _wfopen((const wchar_t*)(f), (const wchar_t*)(m)) -#else -#define FXSYS_wfopen _wfopen -#endif -#else -FXSYS_FILE* FXSYS_wfopen(const FX_WCHAR* filename, const FX_WCHAR* mode); -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ #ifdef __cplusplus } // extern "C" #include "third_party/base/numerics/safe_conversions.h" -#define FXSYS_strlen(ptr) pdfium::base::checked_cast(strlen(ptr)) -#define FXSYS_wcslen(ptr) pdfium::base::checked_cast(wcslen(ptr)) - // Overloaded functions for C++ templates -inline FX_STRSIZE FXSYS_len(const FX_CHAR* ptr) { - return FXSYS_strlen(ptr); +inline size_t FXSYS_len(const char* ptr) { + return strlen(ptr); } -inline FX_STRSIZE FXSYS_len(const FX_WCHAR* ptr) { - return FXSYS_wcslen(ptr); +inline size_t FXSYS_len(const wchar_t* ptr) { + return wcslen(ptr); } -inline int FXSYS_cmp(const FX_CHAR* ptr1, const FX_CHAR* ptr2, size_t len) { +inline int FXSYS_cmp(const char* ptr1, const char* ptr2, size_t len) { return memcmp(ptr1, ptr2, len); } -inline int FXSYS_cmp(const FX_WCHAR* ptr1, const FX_WCHAR* ptr2, size_t len) { +inline int FXSYS_cmp(const wchar_t* ptr1, const wchar_t* ptr2, size_t len) { return wmemcmp(ptr1, ptr2, len); } -inline const FX_CHAR* FXSYS_chr(const FX_CHAR* ptr, FX_CHAR ch, size_t len) { - return reinterpret_cast(memchr(ptr, ch, len)); +inline const char* FXSYS_chr(const char* ptr, char ch, size_t len) { + return reinterpret_cast(memchr(ptr, ch, len)); } -inline const FX_WCHAR* FXSYS_chr(const FX_WCHAR* ptr, FX_WCHAR ch, size_t len) { +inline const wchar_t* FXSYS_chr(const wchar_t* ptr, wchar_t ch, size_t len) { return wmemchr(ptr, ch, len); } extern "C" { -#else -#define FXSYS_strlen(ptr) ((FX_STRSIZE)strlen(ptr)) -#define FXSYS_wcslen(ptr) ((FX_STRSIZE)wcslen(ptr)) -#endif +#endif // __cplusplus -#define FXSYS_wcscmp wcscmp -#define FXSYS_wcsstr wcsstr -#define FXSYS_wcsncmp wcsncmp -#define FXSYS_vswprintf vswprintf -#define FXSYS_mbstowcs mbstowcs -#define FXSYS_wcstombs wcstombs -#define FXSYS_memcmp memcmp -#define FXSYS_memcpy memcpy -#define FXSYS_memmove memmove -#define FXSYS_memset memset -#define FXSYS_qsort qsort -#define FXSYS_bsearch bsearch - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #define FXSYS_GetACP GetACP #define FXSYS_itoa _itoa #define FXSYS_strlwr _strlwr #define FXSYS_strupr _strupr #define FXSYS_stricmp _stricmp +#define FXSYS_pow(a, b) (float)powf(a, b) +size_t FXSYS_wcsftime(wchar_t* strDest, + size_t maxsize, + const wchar_t* format, + const struct tm* timeptr); #ifdef _NATIVE_WCHAR_T_DEFINED #define FXSYS_wcsicmp(str1, str2) _wcsicmp((wchar_t*)(str1), (wchar_t*)(str2)) #define FXSYS_WideCharToMultiByte(p1, p2, p3, p4, p5, p6, p7, p8) \ @@ -210,16 +171,16 @@ extern "C" { MultiByteToWideChar(p1, p2, p3, p4, (wchar_t*)(p5), p6) #define FXSYS_wcslwr(str) _wcslwr((wchar_t*)(str)) #define FXSYS_wcsupr(str) _wcsupr((wchar_t*)(str)) -#else +#else // _NATIVE_WCHAR_T_DEFINED #define FXSYS_wcsicmp _wcsicmp #define FXSYS_WideCharToMultiByte WideCharToMultiByte #define FXSYS_MultiByteToWideChar MultiByteToWideChar #define FXSYS_wcslwr _wcslwr #define FXSYS_wcsupr _wcsupr -#endif -#define FXSYS_GetFullPathName GetFullPathName -#define FXSYS_GetModuleFileName GetModuleFileName -#else +#endif // _NATIVE_WCHAR_T_DEFINED + +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + int FXSYS_GetACP(); char* FXSYS_itoa(int value, char* str, int radix); int FXSYS_WideCharToMultiByte(uint32_t codepage, @@ -236,64 +197,44 @@ int FXSYS_MultiByteToWideChar(uint32_t codepage, int blen, wchar_t* buf, int buflen); -uint32_t FXSYS_GetFullPathName(const char* filename, - uint32_t buflen, - char* buf, - char** filepart); -uint32_t FXSYS_GetModuleFileName(void* hModule, char* buf, uint32_t bufsize); char* FXSYS_strlwr(char* str); char* FXSYS_strupr(char* str); int FXSYS_stricmp(const char*, const char*); int FXSYS_wcsicmp(const wchar_t* str1, const wchar_t* str2); wchar_t* FXSYS_wcslwr(wchar_t* str); wchar_t* FXSYS_wcsupr(wchar_t* str); -#endif // _FXM_PLATFORM == _FXM_PLATFORM_WINDOWS_ - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#define FXSYS_pow(a, b) (FX_FLOAT) powf(a, b) -#else -#define FXSYS_pow(a, b) (FX_FLOAT) pow(a, b) -#endif -#define FXSYS_sqrt(a) (FX_FLOAT) sqrt(a) -#define FXSYS_fabs(a) (FX_FLOAT) fabs(a) -#define FXSYS_atan2(a, b) (FX_FLOAT) atan2(a, b) -#define FXSYS_ceil(a) (FX_FLOAT) ceil(a) -#define FXSYS_floor(a) (FX_FLOAT) floor(a) -#define FXSYS_cos(a) (FX_FLOAT) cos(a) -#define FXSYS_acos(a) (FX_FLOAT) acos(a) -#define FXSYS_sin(a) (FX_FLOAT) sin(a) -#define FXSYS_log(a) (FX_FLOAT) log(a) -#define FXSYS_log10(a) (FX_FLOAT) log10(a) -#define FXSYS_fmod(a, b) (FX_FLOAT) fmod(a, b) -#define FXSYS_abs abs +#define FXSYS_pow(a, b) (float)pow(a, b) +#define FXSYS_wcsftime wcsftime +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + +#define FXWORD_GET_LSBFIRST(p) \ + (static_cast((static_cast(p[1]) << 8) | \ + (static_cast(p[0])))) +#define FXWORD_GET_MSBFIRST(p) \ + (static_cast((static_cast(p[0]) << 8) | \ + (static_cast(p[1])))) #define FXDWORD_GET_LSBFIRST(p) \ ((static_cast(p[3]) << 24) | (static_cast(p[2]) << 16) | \ (static_cast(p[1]) << 8) | (static_cast(p[0]))) #define FXDWORD_GET_MSBFIRST(p) \ ((static_cast(p[0]) << 24) | (static_cast(p[1]) << 16) | \ (static_cast(p[2]) << 8) | (static_cast(p[3]))) -#define FXSYS_HIBYTE(word) ((uint8_t)((word) >> 8)) -#define FXSYS_LOBYTE(word) ((uint8_t)(word)) -#define FXSYS_HIWORD(dword) ((uint16_t)((dword) >> 16)) -#define FXSYS_LOWORD(dword) ((uint16_t)(dword)) -int32_t FXSYS_atoi(const FX_CHAR* str); -uint32_t FXSYS_atoui(const FX_CHAR* str); -int32_t FXSYS_wtoi(const FX_WCHAR* str); -int64_t FXSYS_atoi64(const FX_CHAR* str); -int64_t FXSYS_wtoi64(const FX_WCHAR* str); -const FX_CHAR* FXSYS_i64toa(int64_t value, FX_CHAR* str, int radix); -int FXSYS_round(FX_FLOAT f); -#define FXSYS_sqrt2(a, b) (FX_FLOAT) FXSYS_sqrt((a) * (a) + (b) * (b)) +int32_t FXSYS_atoi(const char* str); +uint32_t FXSYS_atoui(const char* str); +int32_t FXSYS_wtoi(const wchar_t* str); +int64_t FXSYS_atoi64(const char* str); +const char* FXSYS_i64toa(int64_t value, char* str, int radix); +int FXSYS_round(float f); +#define FXSYS_sqrt2(a, b) (float)sqrt((a) * (a) + (b) * (b)) #ifdef __cplusplus -}; -#endif +} // extern C +#endif // __cplusplus // To print a size_t value in a portable way: // size_t size; // printf("xyz: %" PRIuS, size); // The "u" in the macro corresponds to %u, and S is for "size". - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ #if (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && !defined(PRId64) #error "inttypes.h has already been included before this header file, but " @@ -310,20 +251,20 @@ int FXSYS_round(FX_FLOAT f); #define PRIuS "zu" #endif -#else // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#else // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ #if !defined(PRIuS) #define PRIuS "Iu" #endif -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ // Prevent a function from ever being inlined, typically because we'd // like it to appear in stack traces. -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #define NEVER_INLINE __declspec(noinline) -#else // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #define NEVER_INLINE __attribute__((__noinline__)) -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ #endif // CORE_FXCRT_FX_SYSTEM_H_ diff --git a/core/fxcrt/fx_system_unittest.cpp b/core/fxcrt/fx_system_unittest.cpp index 4ab37c7bdb4155608169c4aefbc849c02059ee90..73f9c75c1e065740eb8928cc503d45dea756aba7 100644 --- a/core/fxcrt/fx_system_unittest.cpp +++ b/core/fxcrt/fx_system_unittest.cpp @@ -3,91 +3,90 @@ // found in the LICENSE file. #include -#include +#include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" // Unit test covering cases where PDFium replaces well-known library // functionality on any given platformn. -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ namespace { -const FX_CHAR kSentinel = 0x7f; +const char kSentinel = 0x7f; void Check32BitBase16Itoa(int32_t input, const char* expected_output) { const size_t kBufLen = 11; // "-" + 8 digits + NUL + sentinel. - FX_CHAR buf[kBufLen]; + char buf[kBufLen]; buf[kBufLen - 1] = kSentinel; FXSYS_itoa(input, buf, 16); - EXPECT_EQ(std::string(expected_output), buf); + EXPECT_STREQ(expected_output, buf); EXPECT_EQ(kSentinel, buf[kBufLen - 1]); } void Check32BitBase10Itoa(int32_t input, const char* expected_output) { const size_t kBufLen = 13; // "-" + 10 digits + NUL + sentinel. - FX_CHAR buf[kBufLen]; + char buf[kBufLen]; buf[kBufLen - 1] = kSentinel; FXSYS_itoa(input, buf, 10); - EXPECT_EQ(std::string(expected_output), buf); + EXPECT_STREQ(expected_output, buf); EXPECT_EQ(kSentinel, buf[kBufLen - 1]); } void Check32BitBase2Itoa(int32_t input, const char* expected_output) { const size_t kBufLen = 35; // "-" + 32 digits + NUL + sentinel. - FX_CHAR buf[kBufLen]; + char buf[kBufLen]; buf[kBufLen - 1] = kSentinel; FXSYS_itoa(input, buf, 2); - EXPECT_EQ(std::string(expected_output), buf); + EXPECT_STREQ(expected_output, buf); EXPECT_EQ(kSentinel, buf[kBufLen - 1]); } void Check64BitBase16Itoa(int64_t input, const char* expected_output) { const size_t kBufLen = 19; // "-" + 16 digits + NUL + sentinel. - FX_CHAR buf[kBufLen]; + char buf[kBufLen]; buf[kBufLen - 1] = kSentinel; FXSYS_i64toa(input, buf, 16); - EXPECT_EQ(std::string(expected_output), buf); + EXPECT_STREQ(expected_output, buf); EXPECT_EQ(kSentinel, buf[kBufLen - 1]); } void Check64BitBase10Itoa(int64_t input, const char* expected_output) { const size_t kBufLen = 22; // "-" + 19 digits + NUL + sentinel. - FX_CHAR buf[kBufLen]; + char buf[kBufLen]; buf[kBufLen - 1] = kSentinel; FXSYS_i64toa(input, buf, 10); - EXPECT_EQ(std::string(expected_output), buf); + EXPECT_STREQ(expected_output, buf); EXPECT_EQ(kSentinel, buf[kBufLen - 1]); } void Check64BitBase2Itoa(int64_t input, const char* expected_output) { const size_t kBufLen = 67; // "-" + 64 digits + NUL + sentinel. - FX_CHAR buf[kBufLen]; + char buf[kBufLen]; buf[kBufLen - 1] = kSentinel; FXSYS_i64toa(input, buf, 2); - EXPECT_EQ(std::string(expected_output), buf); + EXPECT_STREQ(expected_output, buf); EXPECT_EQ(kSentinel, buf[kBufLen - 1]); } } // namespace TEST(fxcrt, FXSYS_itoa_InvalidRadix) { - FX_CHAR buf[32]; + char buf[32]; FXSYS_itoa(42, buf, 17); // Ours stops at 16. - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); FXSYS_itoa(42, buf, 1); - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); FXSYS_itoa(42, buf, 0); - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); FXSYS_itoa(42, buf, -1); - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); } TEST(fxcrt, FXSYS_itoa) { @@ -115,19 +114,19 @@ TEST(fxcrt, FXSYS_itoa) { } TEST(fxcrt, FXSYS_i64toa_InvalidRadix) { - FX_CHAR buf[32]; + char buf[32]; FXSYS_i64toa(42, buf, 17); // Ours stops at 16. - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); FXSYS_i64toa(42, buf, 1); - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); FXSYS_i64toa(42, buf, 0); - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); FXSYS_i64toa(42, buf, -1); - EXPECT_EQ(std::string(""), buf); + EXPECT_STREQ("", buf); } TEST(fxcrt, FXSYS_i64toa) { @@ -159,4 +158,136 @@ TEST(fxcrt, FXSYS_i64toa) { "111111111111111111111111111111111111111111111111111111111111111"); } -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + +TEST(fxcrt, FXSYS_wcsftime) { + struct tm good_time = {}; + good_time.tm_year = 74; // 1900-based. + good_time.tm_mon = 7; // 0-based. + good_time.tm_mday = 9; // 1-based. + good_time.tm_hour = 11; + good_time.tm_min = 59; + good_time.tm_sec = 59; + + wchar_t buf[100] = {}; + EXPECT_EQ(19u, FXSYS_wcsftime(buf, FX_ArraySize(buf), L"%Y-%m-%dT%H:%M:%S", + &good_time)); + EXPECT_STREQ(L"1974-08-09T11:59:59", buf); + + // Ensure wcsftime handles a wide range of years without crashing. + struct tm year_time = {}; + year_time.tm_mon = 7; // 0-based. + year_time.tm_mday = 9; // 1-based. + year_time.tm_hour = 11; + year_time.tm_min = 59; + year_time.tm_sec = 59; + + for (int year = -2500; year <= 8500; ++year) { + year_time.tm_year = year; + wchar_t year_buf[100] = {}; + FXSYS_wcsftime(year_buf, FX_ArraySize(year_buf), L"%Y-%m-%dT%H:%M:%S", + &year_time); + } + + // Ensure wcsftime handles bad years, etc. without crashing. + struct tm bad_time = {}; + bad_time.tm_year = -1; + bad_time.tm_mon = -1; + bad_time.tm_mday = -1; + bad_time.tm_hour = -1; + bad_time.tm_min = -1; + bad_time.tm_sec = -1; + + FXSYS_wcsftime(buf, FX_ArraySize(buf), L"%y-%m-%dT%H:%M:%S", &bad_time); + + // Ensure wcsftime handles bad-ish day without crashing (Feb 30). + struct tm feb_time = {}; + feb_time.tm_year = 115; // 1900-based. + feb_time.tm_mon = 1; // 0-based. + feb_time.tm_mday = 30; // 1-based. + feb_time.tm_hour = 12; + feb_time.tm_min = 00; + feb_time.tm_sec = 00; + + FXSYS_wcsftime(buf, FX_ArraySize(buf), L"%y-%m-%dT%H:%M:%S", &feb_time); +} + +TEST(fxcrt, FXSYS_atoi) { + EXPECT_EQ(0, FXSYS_atoi("")); + EXPECT_EQ(0, FXSYS_atoi("0")); + EXPECT_EQ(-1, FXSYS_atoi("-1")); + EXPECT_EQ(2345, FXSYS_atoi("2345")); + EXPECT_EQ(-2147483647, FXSYS_atoi("-2147483647")); + // Handle the sign. + EXPECT_EQ(-2345, FXSYS_atoi("-2345")); + EXPECT_EQ(2345, FXSYS_atoi("+2345")); + // The max value. + EXPECT_EQ(2147483647, FXSYS_atoi("2147483647")); + // The min value. Written in -1 format to avoid "unary minus operator applied + // to unsigned type" warning. + EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483648")); + // With invalid char. + EXPECT_EQ(9, FXSYS_atoi("9x9")); + + // Out of range values. + EXPECT_EQ(2147483647, FXSYS_atoi("2147483623423412348")); + EXPECT_EQ(2147483647, FXSYS_atoi("2147483648")); + EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483650")); +} + +TEST(fxcrt, FXSYS_atoi64) { + EXPECT_EQ(0, FXSYS_atoi64("")); + EXPECT_EQ(0, FXSYS_atoi64("0")); + EXPECT_EQ(-1, FXSYS_atoi64("-1")); + EXPECT_EQ(2345, FXSYS_atoi64("2345")); + EXPECT_EQ(-9223372036854775807LL, FXSYS_atoi64("-9223372036854775807")); + // Handle the sign. + EXPECT_EQ(-2345, FXSYS_atoi64("-2345")); + EXPECT_EQ(2345, FXSYS_atoi64("+2345")); + // The max value. + EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775807")); + // The min value. Written in -1 format to avoid implicit unsigned warning. + EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775808")); + // With invalid char. + EXPECT_EQ(9, FXSYS_atoi64("9x9")); + + // Out of range values. + EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("922337203685471234123475807")); + EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775808")); + EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775810")); +} + +TEST(fxcrt, FXSYS_wtoi) { + EXPECT_EQ(0, FXSYS_wtoi(L"")); + EXPECT_EQ(0, FXSYS_wtoi(L"0")); + EXPECT_EQ(-1, FXSYS_wtoi(L"-1")); + EXPECT_EQ(2345, FXSYS_wtoi(L"2345")); + EXPECT_EQ(-2147483647, FXSYS_wtoi(L"-2147483647")); + // The max value. + EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483647")); + // The min value. + EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483648")); + + // Out of range values. + EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483623423412348")); + EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483648")); + EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483652")); +} + +TEST(fxcrt, FXSYS_atoui) { + EXPECT_EQ(0u, FXSYS_atoui("")); + EXPECT_EQ(0u, FXSYS_atoui("0")); + EXPECT_EQ(4294967295, FXSYS_atoui("-1")); + EXPECT_EQ(2345u, FXSYS_atoui("2345")); + // Handle the sign. + EXPECT_EQ(4294964951, FXSYS_atoui("-2345")); + EXPECT_EQ(2345u, FXSYS_atoui("+2345")); + // The max value. + EXPECT_EQ(4294967295, FXSYS_atoui("4294967295")); + EXPECT_EQ(9u, FXSYS_atoui("9x9")); + + // Out of range values. + EXPECT_EQ(4294967295, FXSYS_atoui("2147483623423412348")); + EXPECT_EQ(4294967295, FXSYS_atoui("4294967296")); + EXPECT_EQ(4294967295, FXSYS_atoui("-4294967345")); +} diff --git a/core/fxcrt/fx_ucd.h b/core/fxcrt/fx_ucd.h deleted file mode 100644 index eb4bad097e9da8ce69c117734a92305db48ec882..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_ucd.h +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FX_UCD_H_ -#define CORE_FXCRT_FX_UCD_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_basic.h" - -#define FX_BIDICLASSBITS 6 -#define FX_BIDICLASSBITSMASK (31 << FX_BIDICLASSBITS) - -enum FX_BIDICLASS { - FX_BIDICLASS_ON = 0, // Other Neutral - FX_BIDICLASS_L = 1, // Left Letter - FX_BIDICLASS_R = 2, // Right Letter - FX_BIDICLASS_AN = 3, // Arabic Number - FX_BIDICLASS_EN = 4, // European Number - FX_BIDICLASS_AL = 5, // Arabic Letter - FX_BIDICLASS_NSM = 6, // Non-spacing Mark - FX_BIDICLASS_CS = 7, // Common Number Separator - FX_BIDICLASS_ES = 8, // European Separator - FX_BIDICLASS_ET = 9, // European Number Terminator - FX_BIDICLASS_BN = 10, // Boundary Neutral - FX_BIDICLASS_S = 11, // Segment Separator - FX_BIDICLASS_WS = 12, // Whitespace - FX_BIDICLASS_B = 13, // Paragraph Separator - FX_BIDICLASS_RLO = 14, // Right-to-Left Override - FX_BIDICLASS_RLE = 15, // Right-to-Left Embedding - FX_BIDICLASS_LRO = 16, // Left-to-Right Override - FX_BIDICLASS_LRE = 17, // Left-to-Right Embedding - FX_BIDICLASS_PDF = 18, // Pop Directional Format - FX_BIDICLASS_N = FX_BIDICLASS_ON, -}; - -extern const uint32_t kTextLayoutCodeProperties[]; -extern const size_t kTextLayoutCodePropertiesSize; - -extern const uint16_t kFXTextLayoutVerticalMirror[]; -extern const size_t kFXTextLayoutVerticalMirrorSize; - -extern const uint16_t kFXTextLayoutBidiMirror[]; -extern const size_t kFXTextLayoutBidiMirrorSize; - -uint32_t FX_GetUnicodeProperties(FX_WCHAR wch); -FX_WCHAR FX_GetMirrorChar(FX_WCHAR wch, bool bRTL, bool bVertical); - -#ifdef PDF_ENABLE_XFA -enum FX_CHARBREAKPROP { - FX_CBP_OP = 0, - FX_CBP_CL = 1, - FX_CBP_QU = 2, - FX_CBP_GL = 3, - FX_CBP_NS = 4, - FX_CBP_EX = 5, - FX_CBP_SY = 6, - FX_CBP_IS = 7, - FX_CBP_PR = 8, - FX_CBP_PO = 9, - FX_CBP_NU = 10, - FX_CBP_AL = 11, - FX_CBP_ID = 12, - FX_CBP_IN = 13, - FX_CBP_HY = 14, - FX_CBP_BA = 15, - FX_CBP_BB = 16, - FX_CBP_B2 = 17, - FX_CBP_ZW = 18, - FX_CBP_CM = 19, - FX_CBP_WJ = 20, - FX_CBP_H2 = 21, - FX_CBP_H3 = 22, - FX_CBP_JL = 23, - FX_CBP_JV = 24, - FX_CBP_JT = 25, - - FX_CBP_BK = 26, - FX_CBP_CR = 27, - FX_CBP_LF = 28, - FX_CBP_NL = 29, - FX_CBP_SA = 30, - FX_CBP_SG = 31, - FX_CBP_CB = 32, - FX_CBP_XX = 33, - FX_CBP_AI = 34, - FX_CBP_SP = 35, - FX_CBP_TB = 37, - FX_CBP_NONE = 36, -}; - -#define FX_CHARTYPEBITS 11 -#define FX_CHARTYPEBITSMASK (15 << FX_CHARTYPEBITS) -enum FX_CHARTYPE { - FX_CHARTYPE_Unknown = 0, - FX_CHARTYPE_Tab = (1 << FX_CHARTYPEBITS), - FX_CHARTYPE_Space = (2 << FX_CHARTYPEBITS), - FX_CHARTYPE_Control = (3 << FX_CHARTYPEBITS), - FX_CHARTYPE_Combination = (4 << FX_CHARTYPEBITS), - FX_CHARTYPE_Numeric = (5 << FX_CHARTYPEBITS), - FX_CHARTYPE_Normal = (6 << FX_CHARTYPEBITS), - FX_CHARTYPE_ArabicAlef = (7 << FX_CHARTYPEBITS), - FX_CHARTYPE_ArabicSpecial = (8 << FX_CHARTYPEBITS), - FX_CHARTYPE_ArabicDistortion = (9 << FX_CHARTYPEBITS), - FX_CHARTYPE_ArabicNormal = (10 << FX_CHARTYPEBITS), - FX_CHARTYPE_ArabicForm = (11 << FX_CHARTYPEBITS), - FX_CHARTYPE_Arabic = (12 << FX_CHARTYPEBITS), -}; -inline FX_CHARTYPE GetCharTypeFromProp(uint32_t prop) { - return static_cast(prop & FX_CHARTYPEBITSMASK); -} - -bool FX_IsCtrlCode(FX_WCHAR ch); -FX_WCHAR FX_GetMirrorChar(FX_WCHAR wch, - uint32_t dwProps, - bool bRTL, - bool bVertical); -class CFX_Char { - public: - CFX_Char() - : m_wCharCode(0), - m_nBreakType(0), - m_dwCharProps(0), - m_iCharWidth(0), - m_iHorizontalScale(100), - m_iVerticalScale(100) {} - - CFX_Char(uint16_t wCharCode, uint32_t dwCharProps) - : m_wCharCode(wCharCode), - m_nBreakType(0), - m_dwCharProps(dwCharProps), - m_iCharWidth(0), - m_iHorizontalScale(100), - m_iVerticalScale(100) {} - - FX_CHARTYPE GetCharType() const { return GetCharTypeFromProp(m_dwCharProps); } - - uint16_t m_wCharCode; - uint8_t m_nBreakType; - uint32_t m_dwCharProps; - int32_t m_iCharWidth; - int32_t m_iHorizontalScale; - int32_t m_iVerticalScale; -}; - -class CFX_TxtChar : public CFX_Char { - public: - CFX_TxtChar() - : m_nRotation(0), - m_dwCharStyles(0), - m_dwStatus(0), - m_iBidiClass(0), - m_iBidiLevel(0), - m_iBidiPos(0), - m_iBidiOrder(0), - m_pUserData(nullptr) {} - - int8_t m_nRotation; - uint32_t m_dwCharStyles; - uint32_t m_dwStatus; - int16_t m_iBidiClass; - int16_t m_iBidiLevel; - int16_t m_iBidiPos; - int16_t m_iBidiOrder; - void* m_pUserData; -}; - -enum class CFX_RTFBreakType { None = 0, Piece, Line, Paragraph, Page }; - -class CFX_RTFChar : public CFX_Char { - public: - CFX_RTFChar(); - CFX_RTFChar(const CFX_RTFChar& other); - ~CFX_RTFChar(); - - CFX_RTFBreakType m_dwStatus; - int32_t m_iFontSize; - int32_t m_iFontHeight; - int16_t m_iBidiClass; - int16_t m_iBidiLevel; - int16_t m_iBidiPos; - int16_t m_iBidiOrder; - uint32_t m_dwIdentity; - CFX_RetainPtr m_pUserData; -}; - -inline CFX_RTFChar::CFX_RTFChar() - : m_dwStatus(CFX_RTFBreakType::None), - m_iFontSize(0), - m_iFontHeight(0), - m_iBidiClass(0), - m_iBidiLevel(0), - m_iBidiPos(0), - m_dwIdentity(0), - m_pUserData(nullptr) {} - -inline CFX_RTFChar::CFX_RTFChar(const CFX_RTFChar& other) = default; -inline CFX_RTFChar::~CFX_RTFChar() = default; - -#endif // PDF_ENABLE_XFA - -#endif // CORE_FXCRT_FX_UCD_H_ diff --git a/core/fxcrt/fx_ucddata.cpp b/core/fxcrt/fx_ucddata.cpp index b8661b87cb7d2f63f3a5822a3c54003c689354f8..527eacfdbd09fa1d5d592b66d9aac94b85213e50 100644 --- a/core/fxcrt/fx_ucddata.cpp +++ b/core/fxcrt/fx_ucddata.cpp @@ -4,8 +4,9 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_ucd.h" +#include "core/fxcrt/fx_ucddata.h" + +#include "core/fxcrt/fx_memory.h" const uint32_t kTextLayoutCodeProperties[] = { 0xfffe9a93, 0xfffe9a93, 0xfffe9a93, 0xfffe9a93, 0xfffe9a93, 0xfffe9a93, @@ -10936,19 +10937,6 @@ const uint32_t kTextLayoutCodeProperties[] = { const size_t kTextLayoutCodePropertiesSize = FX_ArraySize(kTextLayoutCodeProperties); -const uint16_t kFXTextLayoutVerticalMirror[] = { - 0xFE33, 0xFE32, 0xFE31, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE3F, - 0xFE40, 0xFE3D, 0xFE3E, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE3B, - 0xFE3C, 0xFE39, 0xFE3A, 0xFE34, 0xFE35, 0xFE36, 0xFE37, 0xFE38, - 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, - 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, - 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, - 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, - 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, 0xFEFF, -}; -const size_t kFXTextLayoutVerticalMirrorSize = - FX_ArraySize(kFXTextLayoutVerticalMirror); - const uint16_t kFXTextLayoutBidiMirror[] = { 0x0029, 0x0028, 0x003E, 0x003C, 0x005D, 0x005B, 0x007D, 0x007B, 0x00BB, 0x00AB, 0x0F3B, 0x0F3A, 0x0F3D, 0x0F3C, 0x169C, 0x169B, 0x2019, 0x2018, diff --git a/core/fxcrt/fx_ucddata.h b/core/fxcrt/fx_ucddata.h new file mode 100644 index 0000000000000000000000000000000000000000..78a6b970cc6a5bea3ac4189f16e7f218dd18147f --- /dev/null +++ b/core/fxcrt/fx_ucddata.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_FX_UCDDATA_H_ +#define CORE_FXCRT_FX_UCDDATA_H_ + +#include "core/fxcrt/fx_system.h" + +extern const uint32_t kTextLayoutCodeProperties[]; +extern const size_t kTextLayoutCodePropertiesSize; + +extern const uint16_t kFXTextLayoutBidiMirror[]; +extern const size_t kFXTextLayoutBidiMirrorSize; + +#endif // CORE_FXCRT_FX_UCDDATA_H_ diff --git a/core/fxcrt/fx_unicode.cpp b/core/fxcrt/fx_unicode.cpp index e6f423e2afa036dc155f2a3b0d72b0648c2e5faa..aafdba15eec4816acfa4709172bd9893f30522c4 100644 --- a/core/fxcrt/fx_unicode.cpp +++ b/core/fxcrt/fx_unicode.cpp @@ -4,64 +4,38 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxcrt/fx_ucd.h" +#include "core/fxcrt/fx_unicode.h" -uint32_t FX_GetUnicodeProperties(FX_WCHAR wch) { +#include "core/fxcrt/fx_ucddata.h" + +namespace { + +constexpr uint32_t kMirrorBits = 23; +constexpr uint32_t kMirrorMask = 0x1FFU << kMirrorBits; + +wchar_t GetMirrorChar(wchar_t wch, uint32_t dwProps) { + uint32_t dwTemp = (dwProps & kMirrorMask); + if (dwTemp == kMirrorMask) + return wch; + size_t idx = dwTemp >> kMirrorBits; + return idx < kFXTextLayoutBidiMirrorSize ? kFXTextLayoutBidiMirror[idx] : wch; +} + +} // namespace + +uint32_t FX_GetUnicodeProperties(wchar_t wch) { size_t idx = static_cast(wch); if (idx < kTextLayoutCodePropertiesSize) - return kTextLayoutCodeProperties[(uint16_t)wch]; + return kTextLayoutCodeProperties[idx]; return 0; } -#ifdef PDF_ENABLE_XFA -bool FX_IsCtrlCode(FX_WCHAR ch) { - uint32_t dwRet = (FX_GetUnicodeProperties(ch) & FX_CHARTYPEBITSMASK); - return dwRet == FX_CHARTYPE_Tab || dwRet == FX_CHARTYPE_Control; -} -#endif // PDF_ENABLE_XFA - -FX_WCHAR FX_GetMirrorChar(FX_WCHAR wch, bool bRTL, bool bVertical) { - uint32_t dwProps = FX_GetUnicodeProperties(wch); - uint32_t dwTemp = (dwProps & 0xFF800000); - if (bRTL && dwTemp < 0xFF800000) { - size_t idx = dwTemp >> 23; - if (idx < kFXTextLayoutBidiMirrorSize) { - wch = kFXTextLayoutBidiMirror[idx]; - dwProps = FX_GetUnicodeProperties(wch); - } - } - if (bVertical) { - dwTemp = (dwProps & 0x007E0000); - if (dwTemp < 0x007E0000) { - size_t idx = dwTemp >> 17; - if (idx < kFXTextLayoutVerticalMirrorSize) - wch = kFXTextLayoutVerticalMirror[idx]; - } - } - return wch; +wchar_t FX_GetMirrorChar(wchar_t wch) { + return GetMirrorChar(wch, FX_GetUnicodeProperties(wch)); } #ifdef PDF_ENABLE_XFA -FX_WCHAR FX_GetMirrorChar(FX_WCHAR wch, - uint32_t dwProps, - bool bRTL, - bool bVertical) { - uint32_t dwTemp = (dwProps & 0xFF800000); - if (bRTL && dwTemp < 0xFF800000) { - size_t idx = dwTemp >> 23; - if (idx < kFXTextLayoutBidiMirrorSize) { - wch = kFXTextLayoutBidiMirror[idx]; - dwProps = FX_GetUnicodeProperties(wch); - } - } - if (bVertical) { - dwTemp = (dwProps & 0x007E0000); - if (dwTemp < 0x007E0000) { - size_t idx = dwTemp >> 17; - if (idx < kFXTextLayoutVerticalMirrorSize) - wch = kFXTextLayoutVerticalMirror[idx]; - } - } - return wch; +wchar_t FX_GetMirrorChar(wchar_t wch, uint32_t dwProps) { + return GetMirrorChar(wch, dwProps); } #endif // PDF_ENABLE_XFA diff --git a/core/fxcrt/fx_unicode.h b/core/fxcrt/fx_unicode.h new file mode 100644 index 0000000000000000000000000000000000000000..18657bd0e1e0c2b01cadc7e7534c69b02889175c --- /dev/null +++ b/core/fxcrt/fx_unicode.h @@ -0,0 +1,48 @@ +// 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 CORE_FXCRT_FX_UNICODE_H_ +#define CORE_FXCRT_FX_UNICODE_H_ + +#include "core/fxcrt/retain_ptr.h" + +uint32_t FX_GetUnicodeProperties(wchar_t wch); +wchar_t FX_GetMirrorChar(wchar_t wch); + +#ifdef PDF_ENABLE_XFA + +// As defined in http://www.unicode.org/reports/tr14 +constexpr uint8_t kBreakPropertySpace = 35; +constexpr uint8_t kBreakPropertyTB = 37; // Don't know what this is ... + +constexpr uint32_t FX_CHARTYPEBITS = 11; +constexpr uint32_t FX_CHARTYPEBITSMASK = 0xF << FX_CHARTYPEBITS; + +enum FX_CHARTYPE { + FX_CHARTYPE_Unknown = 0, + FX_CHARTYPE_Tab = (1 << FX_CHARTYPEBITS), + FX_CHARTYPE_Space = (2 << FX_CHARTYPEBITS), + FX_CHARTYPE_Control = (3 << FX_CHARTYPEBITS), + FX_CHARTYPE_Combination = (4 << FX_CHARTYPEBITS), + FX_CHARTYPE_Numeric = (5 << FX_CHARTYPEBITS), + FX_CHARTYPE_Normal = (6 << FX_CHARTYPEBITS), + FX_CHARTYPE_ArabicAlef = (7 << FX_CHARTYPEBITS), + FX_CHARTYPE_ArabicSpecial = (8 << FX_CHARTYPEBITS), + FX_CHARTYPE_ArabicDistortion = (9 << FX_CHARTYPEBITS), + FX_CHARTYPE_ArabicNormal = (10 << FX_CHARTYPEBITS), + FX_CHARTYPE_ArabicForm = (11 << FX_CHARTYPEBITS), + FX_CHARTYPE_Arabic = (12 << FX_CHARTYPEBITS), +}; + +inline FX_CHARTYPE GetCharTypeFromProp(uint32_t prop) { + return static_cast(prop & FX_CHARTYPEBITSMASK); +} + +wchar_t FX_GetMirrorChar(wchar_t wch, uint32_t dwProps); + +#endif // PDF_ENABLE_XFA + +#endif // CORE_FXCRT_FX_UNICODE_H_ diff --git a/core/fxcrt/fx_xml.h b/core/fxcrt/fx_xml.h deleted file mode 100644 index 87f1915cb1a07dc3801c009996374f02a2daa5b1..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_xml.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FX_XML_H_ -#define CORE_FXCRT_FX_XML_H_ - -#include -#include - -#include "core/fxcrt/fx_basic.h" - -class CXML_AttrItem { - public: - bool Matches(const CFX_ByteString& space, const CFX_ByteString& name) const; - - CFX_ByteString m_QSpaceName; - CFX_ByteString m_AttrName; - CFX_WideString m_Value; -}; - -class CXML_AttrMap { - public: - CXML_AttrMap(); - ~CXML_AttrMap(); - - const CFX_WideString* Lookup(const CFX_ByteString& space, - const CFX_ByteString& name) const; - int GetSize() const; - CXML_AttrItem& GetAt(int index) const; - - void SetAt(const CFX_ByteString& space, - const CFX_ByteString& name, - const CFX_WideString& value); - - std::unique_ptr> m_pMap; -}; - -class CXML_Content { - public: - CXML_Content() : m_bCDATA(false), m_Content() {} - void Set(bool bCDATA, const CFX_WideStringC& content) { - m_bCDATA = bCDATA; - m_Content = content; - } - - bool m_bCDATA; - CFX_WideString m_Content; -}; - -class CXML_Element { - public: - enum ChildType { Invalid, Element, Content }; - - static std::unique_ptr Parse(const void* pBuffer, size_t size); - - CXML_Element(const CXML_Element* pParent, - const CFX_ByteStringC& qSpace, - const CFX_ByteStringC& tagname); - ~CXML_Element(); - - void Empty(); - CFX_ByteString GetTagName(bool bQualified = false) const; - CFX_ByteString GetNamespace(bool bQualified = false) const; - CFX_ByteString GetNamespaceURI(const CFX_ByteString& qName) const; - const CXML_Element* GetParent() const { return m_pParent; } - uint32_t CountAttrs() const { return m_AttrMap.GetSize(); } - void GetAttrByIndex(int index, - CFX_ByteString& space, - CFX_ByteString& name, - CFX_WideString& value) const; - bool HasAttr(const CFX_ByteStringC& qName) const; - bool GetAttrValue(const CFX_ByteStringC& name, - CFX_WideString& attribute) const; - CFX_WideString GetAttrValue(const CFX_ByteStringC& name) const { - CFX_WideString attr; - GetAttrValue(name, attr); - return attr; - } - - bool GetAttrValue(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - CFX_WideString& attribute) const; - CFX_WideString GetAttrValue(const CFX_ByteStringC& space, - const CFX_ByteStringC& name) const { - CFX_WideString attr; - GetAttrValue(space, name, attr); - return attr; - } - - bool GetAttrInteger(const CFX_ByteStringC& name, int& attribute) const; - int GetAttrInteger(const CFX_ByteStringC& name) const { - int attr = 0; - GetAttrInteger(name, attr); - return attr; - } - - bool GetAttrInteger(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - int& attribute) const; - int GetAttrInteger(const CFX_ByteStringC& space, - const CFX_ByteStringC& name) const { - int attr = 0; - GetAttrInteger(space, name, attr); - return attr; - } - - bool GetAttrFloat(const CFX_ByteStringC& name, FX_FLOAT& attribute) const; - FX_FLOAT GetAttrFloat(const CFX_ByteStringC& name) const { - FX_FLOAT attr = 0; - GetAttrFloat(name, attr); - return attr; - } - - bool GetAttrFloat(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - FX_FLOAT& attribute) const; - FX_FLOAT GetAttrFloat(const CFX_ByteStringC& space, - const CFX_ByteStringC& name) const { - FX_FLOAT attr = 0; - GetAttrFloat(space, name, attr); - return attr; - } - - uint32_t CountChildren() const { return m_Children.size(); } - ChildType GetChildType(uint32_t index) const; - CFX_WideString GetContent(uint32_t index) const; - CXML_Element* GetElement(uint32_t index) const; - CXML_Element* GetElement(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag) const { - return GetElement(space, tag, 0); - } - - uint32_t CountElements(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag) const; - CXML_Element* GetElement(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag, - int index) const; - - uint32_t FindElement(CXML_Element* pChild) const; - void SetTag(const CFX_ByteStringC& qTagName); - void RemoveChildren(); - void RemoveChild(uint32_t index); - - protected: - struct ChildRecord { - ChildType type; - void* child; // CXML_Element and CXML_Content lack a common ancestor. - }; - - const CXML_Element* const m_pParent; - CFX_ByteString m_QSpaceName; - CFX_ByteString m_TagName; - CXML_AttrMap m_AttrMap; - std::vector m_Children; - - friend class CXML_Parser; - friend class CXML_Composer; -}; - -#endif // CORE_FXCRT_FX_XML_H_ diff --git a/core/fxcrt/fx_xml_composer.cpp b/core/fxcrt/fx_xml_composer.cpp deleted file mode 100644 index 637d64cd82f6a2db76b690140ac113938f0acce2..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_xml_composer.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/xml_int.h" - -#include "core/fxcrt/fx_xml.h" - -void FX_XML_SplitQualifiedName(const CFX_ByteStringC& bsFullName, - CFX_ByteStringC& bsSpace, - CFX_ByteStringC& bsName) { - if (bsFullName.IsEmpty()) - return; - - FX_STRSIZE iStart = bsFullName.Find(':'); - if (iStart == -1) { - bsName = bsFullName; - } else { - bsSpace = bsFullName.Mid(0, iStart); - bsName = bsFullName.Mid(iStart + 1); - } -} - -void CXML_Element::SetTag(const CFX_ByteStringC& qTagName) { - ASSERT(!qTagName.IsEmpty()); - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; - FX_XML_SplitQualifiedName(qTagName, bsSpace, bsName); - m_QSpaceName = bsSpace; - m_TagName = bsName; -} diff --git a/core/fxcrt/fx_xml_parser.cpp b/core/fxcrt/fx_xml_parser.cpp deleted file mode 100644 index 761aae777584cbcd747e54643b6e1a4a28635bb2..0000000000000000000000000000000000000000 --- a/core/fxcrt/fx_xml_parser.cpp +++ /dev/null @@ -1,918 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include -#include - -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_xml.h" -#include "core/fxcrt/xml_int.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -#define FXCRTM_XML_CHARTYPE_Normal 0x00 -#define FXCRTM_XML_CHARTYPE_SpaceChar 0x01 -#define FXCRTM_XML_CHARTYPE_Letter 0x02 -#define FXCRTM_XML_CHARTYPE_Digital 0x04 -#define FXCRTM_XML_CHARTYPE_NameIntro 0x08 -#define FXCRTM_XML_CHARTYPE_NameChar 0x10 -#define FXCRTM_XML_CHARTYPE_HexDigital 0x20 -#define FXCRTM_XML_CHARTYPE_HexLowerLetter 0x40 -#define FXCRTM_XML_CHARTYPE_HexUpperLetter 0x60 -#define FXCRTM_XML_CHARTYPE_HexChar 0x60 - -const uint8_t g_FXCRT_XML_ByteTypes[256] = { - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x01, 0x01, -}; - -bool g_FXCRT_XML_IsWhiteSpace(uint8_t ch) { - return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_SpaceChar); -} - -bool g_FXCRT_XML_IsDigital(uint8_t ch) { - return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_Digital); -} - -bool g_FXCRT_XML_IsNameIntro(uint8_t ch) { - return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_NameIntro); -} - -bool g_FXCRT_XML_IsNameChar(uint8_t ch) { - return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_NameChar); -} - -class CXML_DataBufAcc : public IFX_BufferedReadStream { - public: - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - // IFX_BufferedReadStream - bool IsEOF() override; - FX_FILESIZE GetPosition() override; - size_t ReadBlock(void* buffer, size_t size) override; - bool ReadNextBlock(bool bRestart) override; - const uint8_t* GetBlockBuffer() override; - size_t GetBlockSize() override; - FX_FILESIZE GetBlockOffset() override; - - private: - CXML_DataBufAcc(const uint8_t* pBuffer, size_t size); - ~CXML_DataBufAcc() override; - - const uint8_t* m_pBuffer; - size_t m_dwSize; - size_t m_dwCurPos; -}; - -CXML_DataBufAcc::CXML_DataBufAcc(const uint8_t* pBuffer, size_t size) - : m_pBuffer(pBuffer), m_dwSize(size), m_dwCurPos(0) {} - -CXML_DataBufAcc::~CXML_DataBufAcc() {} - -bool CXML_DataBufAcc::IsEOF() { - return m_dwCurPos >= m_dwSize; -} - -FX_FILESIZE CXML_DataBufAcc::GetPosition() { - return static_cast(m_dwCurPos); -} - -size_t CXML_DataBufAcc::ReadBlock(void* buffer, size_t size) { - return 0; -} - -bool CXML_DataBufAcc::ReadNextBlock(bool bRestart) { - if (bRestart) - m_dwCurPos = 0; - - if (m_dwCurPos < m_dwSize) { - m_dwCurPos = m_dwSize; - return true; - } - return false; -} - -const uint8_t* CXML_DataBufAcc::GetBlockBuffer() { - return m_pBuffer; -} - -size_t CXML_DataBufAcc::GetBlockSize() { - return m_dwSize; -} - -FX_FILESIZE CXML_DataBufAcc::GetBlockOffset() { - return 0; -} - -class CXML_DataStmAcc : public IFX_BufferedReadStream { - public: - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - // IFX_BufferedReadStream - bool IsEOF() override; - FX_FILESIZE GetPosition() override; - size_t ReadBlock(void* buffer, size_t size) override; - bool ReadNextBlock(bool bRestart) override; - const uint8_t* GetBlockBuffer() override; - size_t GetBlockSize() override; - FX_FILESIZE GetBlockOffset() override; - - private: - explicit CXML_DataStmAcc( - const CFX_RetainPtr& pFileRead); - ~CXML_DataStmAcc() override; - - CFX_RetainPtr m_pFileRead; - uint8_t* m_pBuffer; - FX_FILESIZE m_nStart; - size_t m_dwSize; -}; - -CXML_DataStmAcc::CXML_DataStmAcc( - const CFX_RetainPtr& pFileRead) - : m_pFileRead(pFileRead), m_pBuffer(nullptr), m_nStart(0), m_dwSize(0) { - ASSERT(m_pFileRead); -} - -CXML_DataStmAcc::~CXML_DataStmAcc() { - FX_Free(m_pBuffer); -} - -bool CXML_DataStmAcc::IsEOF() { - return m_nStart + static_cast(m_dwSize) >= - m_pFileRead->GetSize(); -} - -FX_FILESIZE CXML_DataStmAcc::GetPosition() { - return m_nStart + static_cast(m_dwSize); -} - -size_t CXML_DataStmAcc::ReadBlock(void* buffer, size_t size) { - return 0; -} - -bool CXML_DataStmAcc::ReadNextBlock(bool bRestart) { - if (bRestart) - m_nStart = 0; - - FX_FILESIZE nLength = m_pFileRead->GetSize(); - m_nStart += static_cast(m_dwSize); - if (m_nStart >= nLength) - return false; - - static const FX_FILESIZE FX_XMLDATASTREAM_BufferSize = 32 * 1024; - m_dwSize = static_cast( - std::min(FX_XMLDATASTREAM_BufferSize, nLength - m_nStart)); - if (!m_pBuffer) - m_pBuffer = FX_Alloc(uint8_t, m_dwSize); - - return m_pFileRead->ReadBlock(m_pBuffer, m_nStart, m_dwSize); -} - -const uint8_t* CXML_DataStmAcc::GetBlockBuffer() { - return (const uint8_t*)m_pBuffer; -} - -size_t CXML_DataStmAcc::GetBlockSize() { - return m_dwSize; -} - -FX_FILESIZE CXML_DataStmAcc::GetBlockOffset() { - return m_nStart; -} - -} // namespace - -CXML_Parser::CXML_Parser() - : m_nOffset(0), - m_pBuffer(nullptr), - m_dwBufferSize(0), - m_nBufferOffset(0), - m_dwIndex(0) {} - -CXML_Parser::~CXML_Parser() {} - -bool CXML_Parser::Init(const uint8_t* pBuffer, size_t size) { - m_pDataAcc = pdfium::MakeRetain(pBuffer, size); - m_nOffset = 0; - return ReadNextBlock(); -} - -bool CXML_Parser::ReadNextBlock() { - if (!m_pDataAcc->ReadNextBlock()) - return false; - - m_pBuffer = m_pDataAcc->GetBlockBuffer(); - m_dwBufferSize = m_pDataAcc->GetBlockSize(); - m_nBufferOffset = m_pDataAcc->GetBlockOffset(); - m_dwIndex = 0; - return m_dwBufferSize > 0; -} - -bool CXML_Parser::IsEOF() { - return m_pDataAcc->IsEOF() && m_dwIndex >= m_dwBufferSize; -} - -void CXML_Parser::SkipWhiteSpaces() { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) - return; - - do { - while (m_dwIndex < m_dwBufferSize && - g_FXCRT_XML_IsWhiteSpace(m_pBuffer[m_dwIndex])) { - m_dwIndex++; - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); -} - -void CXML_Parser::GetName(CFX_ByteString* space, CFX_ByteString* name) { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) - return; - - CFX_ByteTextBuf buf; - uint8_t ch; - do { - while (m_dwIndex < m_dwBufferSize) { - ch = m_pBuffer[m_dwIndex]; - if (ch == ':') { - *space = buf.AsStringC(); - buf.Clear(); - } else if (g_FXCRT_XML_IsNameChar(ch)) { - buf.AppendChar(ch); - } else { - break; - } - m_dwIndex++; - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); - *name = buf.AsStringC(); -} - -void CXML_Parser::SkipLiterals(const CFX_ByteStringC& str) { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) { - return; - } - int32_t i = 0, iLen = str.GetLength(); - do { - while (m_dwIndex < m_dwBufferSize) { - if (str.GetAt(i) != m_pBuffer[m_dwIndex++]) { - i = 0; - continue; - } - i++; - if (i == iLen) - break; - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (i == iLen) - return; - - if (m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); - while (!m_pDataAcc->IsEOF()) { - ReadNextBlock(); - m_nOffset = m_nBufferOffset + static_cast(m_dwBufferSize); - } - m_dwIndex = m_dwBufferSize; -} - -uint32_t CXML_Parser::GetCharRef() { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) - return 0; - - uint8_t ch; - int32_t iState = 0; - CFX_ByteTextBuf buf; - uint32_t code = 0; - do { - while (m_dwIndex < m_dwBufferSize) { - ch = m_pBuffer[m_dwIndex]; - switch (iState) { - case 0: - if (ch == '#') { - m_dwIndex++; - iState = 2; - break; - } - iState = 1; - case 1: - m_dwIndex++; - if (ch == ';') { - CFX_ByteStringC ref = buf.AsStringC(); - if (ref == "gt") - code = '>'; - else if (ref == "lt") - code = '<'; - else if (ref == "amp") - code = '&'; - else if (ref == "apos") - code = '\''; - else if (ref == "quot") - code = '"'; - iState = 10; - break; - } - buf.AppendByte(ch); - break; - case 2: - if (ch == 'x') { - m_dwIndex++; - iState = 4; - break; - } - iState = 3; - case 3: - m_dwIndex++; - if (ch == ';') { - iState = 10; - break; - } - if (g_FXCRT_XML_IsDigital(ch)) - code = code * 10 + FXSYS_toDecimalDigit(static_cast(ch)); - break; - case 4: - m_dwIndex++; - if (ch == ';') { - iState = 10; - break; - } - uint8_t nHex = - g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_HexChar; - if (nHex) { - if (nHex == FXCRTM_XML_CHARTYPE_HexDigital) { - code = - (code << 4) + FXSYS_toDecimalDigit(static_cast(ch)); - } else if (nHex == FXCRTM_XML_CHARTYPE_HexLowerLetter) { - code = (code << 4) + ch - 87; - } else { - code = (code << 4) + ch - 55; - } - } - break; - } - if (iState == 10) - break; - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF()) { - break; - } - } while (ReadNextBlock()); - return code; -} - -void CXML_Parser::GetAttrValue(CFX_WideString& value) { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) - return; - - CFX_UTF8Decoder decoder; - uint8_t mark = 0, ch = 0; - do { - while (m_dwIndex < m_dwBufferSize) { - ch = m_pBuffer[m_dwIndex]; - if (mark == 0) { - if (ch != '\'' && ch != '"') - return; - - mark = ch; - m_dwIndex++; - ch = 0; - continue; - } - m_dwIndex++; - if (ch == mark) - break; - - if (ch == '&') { - decoder.AppendChar(GetCharRef()); - if (IsEOF()) { - value = decoder.GetResult(); - return; - } - } else { - decoder.Input(ch); - } - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (ch == mark || m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); - value = decoder.GetResult(); -} - -void CXML_Parser::GetTagName(bool bStartTag, - bool* bEndTag, - CFX_ByteString* space, - CFX_ByteString* name) { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) - return; - - *bEndTag = false; - uint8_t ch; - int32_t iState = bStartTag ? 1 : 0; - do { - while (m_dwIndex < m_dwBufferSize) { - ch = m_pBuffer[m_dwIndex]; - switch (iState) { - case 0: - m_dwIndex++; - if (ch != '<') - break; - - iState = 1; - break; - case 1: - if (ch == '?') { - m_dwIndex++; - SkipLiterals("?>"); - iState = 0; - break; - } - if (ch == '!') { - m_dwIndex++; - SkipLiterals("-->"); - iState = 0; - break; - } - if (ch == '/') { - m_dwIndex++; - GetName(space, name); - *bEndTag = true; - } else { - GetName(space, name); - *bEndTag = false; - } - return; - } - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); -} - -std::unique_ptr CXML_Parser::ParseElement(CXML_Element* pParent, - bool bStartTag) { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (IsEOF()) - return nullptr; - - CFX_ByteString tag_name; - CFX_ByteString tag_space; - bool bEndTag; - GetTagName(bStartTag, &bEndTag, &tag_space, &tag_name); - if (tag_name.IsEmpty() || bEndTag) - return nullptr; - - auto pElement = pdfium::MakeUnique( - pParent, tag_space.AsStringC(), tag_name.AsStringC()); - do { - CFX_ByteString attr_space; - CFX_ByteString attr_name; - while (m_dwIndex < m_dwBufferSize) { - SkipWhiteSpaces(); - if (IsEOF()) - break; - - if (!g_FXCRT_XML_IsNameIntro(m_pBuffer[m_dwIndex])) - break; - - GetName(&attr_space, &attr_name); - SkipWhiteSpaces(); - if (IsEOF()) - break; - - if (m_pBuffer[m_dwIndex] != '=') - break; - - m_dwIndex++; - SkipWhiteSpaces(); - if (IsEOF()) - break; - - CFX_WideString attr_value; - GetAttrValue(attr_value); - pElement->m_AttrMap.SetAt(attr_space, attr_name, attr_value); - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); - SkipWhiteSpaces(); - if (IsEOF()) - return pElement; - - uint8_t ch = m_pBuffer[m_dwIndex++]; - if (ch == '/') { - m_dwIndex++; - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - return pElement; - } - if (ch != '>') { - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - return nullptr; - } - SkipWhiteSpaces(); - if (IsEOF()) - return pElement; - - CFX_UTF8Decoder decoder; - CFX_WideTextBuf content; - bool bCDATA = false; - int32_t iState = 0; - do { - while (m_dwIndex < m_dwBufferSize) { - ch = m_pBuffer[m_dwIndex++]; - switch (iState) { - case 0: - if (ch == '<') { - iState = 1; - } else if (ch == '&') { - decoder.ClearStatus(); - decoder.AppendChar(GetCharRef()); - } else { - decoder.Input(ch); - } - break; - case 1: - if (ch == '!') { - iState = 2; - } else if (ch == '?') { - SkipLiterals("?>"); - SkipWhiteSpaces(); - iState = 0; - } else if (ch == '/') { - CFX_ByteString space; - CFX_ByteString name; - GetName(&space, &name); - SkipWhiteSpaces(); - m_dwIndex++; - iState = 10; - } else { - content << decoder.GetResult(); - CFX_WideString dataStr = content.MakeString(); - if (!bCDATA) - dataStr.TrimRight(L" \t\r\n"); - - InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement.get()); - content.Clear(); - decoder.Clear(); - bCDATA = false; - iState = 0; - m_dwIndex--; - std::unique_ptr pSubElement( - ParseElement(pElement.get(), true)); - if (!pSubElement) - break; - - pElement->m_Children.push_back( - {CXML_Element::Element, pSubElement.release()}); - SkipWhiteSpaces(); - } - break; - case 2: - if (ch == '[') { - SkipLiterals("]]>"); - } else if (ch == '-') { - m_dwIndex++; - SkipLiterals("-->"); - } else { - SkipLiterals(">"); - } - decoder.Clear(); - SkipWhiteSpaces(); - iState = 0; - break; - } - if (iState == 10) { - break; - } - } - m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); - if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF()) - break; - } while (ReadNextBlock()); - content << decoder.GetResult(); - CFX_WideString dataStr = content.MakeString(); - dataStr.TrimRight(L" \t\r\n"); - - InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement.get()); - content.Clear(); - decoder.Clear(); - bCDATA = false; - return pElement; -} - -void CXML_Parser::InsertContentSegment(bool bCDATA, - const CFX_WideStringC& content, - CXML_Element* pElement) { - if (content.IsEmpty()) - return; - - CXML_Content* pContent = new CXML_Content; - pContent->Set(bCDATA, content); - pElement->m_Children.push_back({CXML_Element::Content, pContent}); -} - -std::unique_ptr CXML_Element::Parse(const void* pBuffer, - size_t size) { - CXML_Parser parser; - if (!parser.Init(static_cast(pBuffer), size)) - return nullptr; - return parser.ParseElement(nullptr, false); -} - -CXML_Element::CXML_Element(const CXML_Element* pParent, - const CFX_ByteStringC& qSpace, - const CFX_ByteStringC& tagname) - : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {} - -CXML_Element::~CXML_Element() { - Empty(); -} - -void CXML_Element::Empty() { - RemoveChildren(); -} -void CXML_Element::RemoveChildren() { - for (const ChildRecord& record : m_Children) { - if (record.type == Content) { - delete static_cast(record.child); - } else if (record.type == Element) { - CXML_Element* child = static_cast(record.child); - child->RemoveChildren(); - delete child; - } - } - m_Children.clear(); -} -CFX_ByteString CXML_Element::GetTagName(bool bQualified) const { - if (!bQualified || m_QSpaceName.IsEmpty()) { - return m_TagName; - } - CFX_ByteString bsTag = m_QSpaceName; - bsTag += ":"; - bsTag += m_TagName; - return bsTag; -} - -CFX_ByteString CXML_Element::GetNamespace(bool bQualified) const { - return bQualified ? m_QSpaceName : GetNamespaceURI(m_QSpaceName); -} - -CFX_ByteString CXML_Element::GetNamespaceURI( - const CFX_ByteString& qName) const { - const CFX_WideString* pwsSpace; - const CXML_Element* pElement = this; - do { - if (qName.IsEmpty()) - pwsSpace = pElement->m_AttrMap.Lookup("", "xmlns"); - else - pwsSpace = pElement->m_AttrMap.Lookup("xmlns", qName); - if (pwsSpace) - break; - - pElement = pElement->GetParent(); - } while (pElement); - return pwsSpace ? pwsSpace->UTF8Encode() : CFX_ByteString(); -} - -void CXML_Element::GetAttrByIndex(int index, - CFX_ByteString& space, - CFX_ByteString& name, - CFX_WideString& value) const { - if (index < 0 || index >= m_AttrMap.GetSize()) - return; - - CXML_AttrItem& item = m_AttrMap.GetAt(index); - space = item.m_QSpaceName; - name = item.m_AttrName; - value = item.m_Value; -} - -bool CXML_Element::HasAttr(const CFX_ByteStringC& name) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; - FX_XML_SplitQualifiedName(name, bsSpace, bsName); - return !!m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName)); -} - -bool CXML_Element::GetAttrValue(const CFX_ByteStringC& name, - CFX_WideString& attribute) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; - FX_XML_SplitQualifiedName(name, bsSpace, bsName); - return GetAttrValue(bsSpace, bsName, attribute); -} - -bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - CFX_WideString& attribute) const { - const CFX_WideString* pValue = - m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name)); - if (!pValue) - return false; - - attribute = *pValue; - return true; -} - -bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name, - int& attribute) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; - FX_XML_SplitQualifiedName(name, bsSpace, bsName); - const CFX_WideString* pwsValue = - m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName)); - if (!pwsValue) - return false; - - attribute = pwsValue->GetInteger(); - return true; -} - -bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - int& attribute) const { - const CFX_WideString* pwsValue = - m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name)); - if (!pwsValue) - return false; - - attribute = pwsValue->GetInteger(); - return true; -} - -bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& name, - FX_FLOAT& attribute) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; - FX_XML_SplitQualifiedName(name, bsSpace, bsName); - return GetAttrFloat(bsSpace, bsName, attribute); -} - -bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - FX_FLOAT& attribute) const { - const CFX_WideString* pValue = - m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name)); - if (!pValue) - return false; - - attribute = pValue->GetFloat(); - return true; -} - -CXML_Element::ChildType CXML_Element::GetChildType(uint32_t index) const { - return index < m_Children.size() ? m_Children[index].type : Invalid; -} - -CFX_WideString CXML_Element::GetContent(uint32_t index) const { - if (index < m_Children.size() && m_Children[index].type == Content) { - CXML_Content* pContent = - static_cast(m_Children[index].child); - if (pContent) - return pContent->m_Content; - } - return CFX_WideString(); -} - -CXML_Element* CXML_Element::GetElement(uint32_t index) const { - if (index < m_Children.size() && m_Children[index].type == Element) - return static_cast(m_Children[index].child); - return nullptr; -} - -uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag) const { - int count = 0; - for (const ChildRecord& record : m_Children) { - if (record.type != Element) - continue; - - CXML_Element* pKid = static_cast(record.child); - if ((space.IsEmpty() || pKid->m_QSpaceName == space) && - pKid->m_TagName == tag) { - count++; - } - } - return count; -} - -CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag, - int index) const { - if (index < 0) - return nullptr; - - for (const ChildRecord& record : m_Children) { - if (record.type != Element) - continue; - - CXML_Element* pKid = static_cast(record.child); - if ((space.IsEmpty() || pKid->m_QSpaceName == space) && - pKid->m_TagName == tag) { - if (index-- == 0) - return pKid; - } - } - return nullptr; -} - -uint32_t CXML_Element::FindElement(CXML_Element* pChild) const { - int index = 0; - for (const ChildRecord& record : m_Children) { - if (record.type == Element && - static_cast(record.child) == pChild) { - return index; - } - ++index; - } - return (uint32_t)-1; -} - -bool CXML_AttrItem::Matches(const CFX_ByteString& space, - const CFX_ByteString& name) const { - return (space.IsEmpty() || m_QSpaceName == space) && m_AttrName == name; -} - -CXML_AttrMap::CXML_AttrMap() {} - -CXML_AttrMap::~CXML_AttrMap() {} - -const CFX_WideString* CXML_AttrMap::Lookup(const CFX_ByteString& space, - const CFX_ByteString& name) const { - if (!m_pMap) - return nullptr; - - for (const auto& item : *m_pMap) { - if (item.Matches(space, name)) - return &item.m_Value; - } - return nullptr; -} - -void CXML_AttrMap::SetAt(const CFX_ByteString& space, - const CFX_ByteString& name, - const CFX_WideString& value) { - if (!m_pMap) - m_pMap = pdfium::MakeUnique>(); - - for (CXML_AttrItem& item : *m_pMap) { - if (item.Matches(space, name)) { - item.m_Value = value; - return; - } - } - - m_pMap->push_back({space, name, CFX_WideString(value)}); -} - -int CXML_AttrMap::GetSize() const { - return m_pMap ? pdfium::CollectionSize(*m_pMap) : 0; -} - -CXML_AttrItem& CXML_AttrMap::GetAt(int index) const { - return (*m_pMap)[index]; -} diff --git a/core/fxcrt/fxcrt_posix.cpp b/core/fxcrt/fxcrt_posix.cpp deleted file mode 100644 index a96f164c7f16c1b188fa383b976814434970aed3..0000000000000000000000000000000000000000 --- a/core/fxcrt/fxcrt_posix.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fxcrt_posix.h" - -#include "core/fxcrt/fx_basic.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - -// static -IFXCRT_FileAccess* IFXCRT_FileAccess::Create() { - return new CFXCRT_FileAccess_Posix; -} - -void FXCRT_Posix_GetFileMode(uint32_t dwModes, - int32_t& nFlags, - int32_t& nMasks) { - nFlags = O_BINARY | O_LARGEFILE; - if (dwModes & FX_FILEMODE_ReadOnly) { - nFlags |= O_RDONLY; - nMasks = 0; - } else { - nFlags |= O_RDWR | O_CREAT; - if (dwModes & FX_FILEMODE_Truncate) { - nFlags |= O_TRUNC; - } - nMasks = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - } -} -CFXCRT_FileAccess_Posix::CFXCRT_FileAccess_Posix() : m_nFD(-1) {} -CFXCRT_FileAccess_Posix::~CFXCRT_FileAccess_Posix() { - Close(); -} - -bool CFXCRT_FileAccess_Posix::Open(const CFX_ByteStringC& fileName, - uint32_t dwMode) { - if (m_nFD > -1) - return false; - - int32_t nFlags; - int32_t nMasks; - FXCRT_Posix_GetFileMode(dwMode, nFlags, nMasks); - m_nFD = open(fileName.c_str(), nFlags, nMasks); - return m_nFD > -1; -} - -bool CFXCRT_FileAccess_Posix::Open(const CFX_WideStringC& fileName, - uint32_t dwMode) { - return Open(FX_UTF8Encode(fileName).AsStringC(), dwMode); -} - -void CFXCRT_FileAccess_Posix::Close() { - if (m_nFD < 0) { - return; - } - close(m_nFD); - m_nFD = -1; -} -FX_FILESIZE CFXCRT_FileAccess_Posix::GetSize() const { - if (m_nFD < 0) { - return 0; - } - struct stat s; - FXSYS_memset(&s, 0, sizeof(s)); - fstat(m_nFD, &s); - return s.st_size; -} -FX_FILESIZE CFXCRT_FileAccess_Posix::GetPosition() const { - if (m_nFD < 0) { - return (FX_FILESIZE)-1; - } - return lseek(m_nFD, 0, SEEK_CUR); -} -FX_FILESIZE CFXCRT_FileAccess_Posix::SetPosition(FX_FILESIZE pos) { - if (m_nFD < 0) { - return (FX_FILESIZE)-1; - } - return lseek(m_nFD, pos, SEEK_SET); -} -size_t CFXCRT_FileAccess_Posix::Read(void* pBuffer, size_t szBuffer) { - if (m_nFD < 0) { - return 0; - } - return read(m_nFD, pBuffer, szBuffer); -} -size_t CFXCRT_FileAccess_Posix::Write(const void* pBuffer, size_t szBuffer) { - if (m_nFD < 0) { - return 0; - } - return write(m_nFD, pBuffer, szBuffer); -} -size_t CFXCRT_FileAccess_Posix::ReadPos(void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) { - if (m_nFD < 0) { - return 0; - } - if (pos >= GetSize()) { - return 0; - } - if (SetPosition(pos) == (FX_FILESIZE)-1) { - return 0; - } - return Read(pBuffer, szBuffer); -} -size_t CFXCRT_FileAccess_Posix::WritePos(const void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) { - if (m_nFD < 0) { - return 0; - } - if (SetPosition(pos) == (FX_FILESIZE)-1) { - return 0; - } - return Write(pBuffer, szBuffer); -} - -bool CFXCRT_FileAccess_Posix::Flush() { - if (m_nFD < 0) - return false; - - return fsync(m_nFD) > -1; -} - -bool CFXCRT_FileAccess_Posix::Truncate(FX_FILESIZE szFile) { - if (m_nFD < 0) - return false; - - return !ftruncate(m_nFD, szFile); -} - -#endif diff --git a/core/fxcrt/fxcrt_posix.h b/core/fxcrt/fxcrt_posix.h deleted file mode 100644 index 20faa5c02f0ee54bbf049d9ccaf863dd044439d3..0000000000000000000000000000000000000000 --- a/core/fxcrt/fxcrt_posix.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FXCRT_POSIX_H_ -#define CORE_FXCRT_FXCRT_POSIX_H_ - -#include "core/fxcrt/extension.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ -class CFXCRT_FileAccess_Posix : public IFXCRT_FileAccess { - public: - CFXCRT_FileAccess_Posix(); - ~CFXCRT_FileAccess_Posix() override; - - // IFXCRT_FileAccess: - bool Open(const CFX_ByteStringC& fileName, uint32_t dwMode) override; - bool Open(const CFX_WideStringC& fileName, uint32_t dwMode) override; - void Close() override; - FX_FILESIZE GetSize() const override; - FX_FILESIZE GetPosition() const override; - FX_FILESIZE SetPosition(FX_FILESIZE pos) override; - size_t Read(void* pBuffer, size_t szBuffer) override; - size_t Write(const void* pBuffer, size_t szBuffer) override; - size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) override; - size_t WritePos(const void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) override; - bool Flush() override; - bool Truncate(FX_FILESIZE szFile) override; - - protected: - int32_t m_nFD; -}; -#endif - -#endif // CORE_FXCRT_FXCRT_POSIX_H_ diff --git a/core/fxcrt/fxcrt_stream.cpp b/core/fxcrt/fxcrt_stream.cpp deleted file mode 100644 index 3afe6323b282bf056f7bc9993045a80c86e7d90c..0000000000000000000000000000000000000000 --- a/core/fxcrt/fxcrt_stream.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2016 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 "core/fxcrt/fx_stream.h" - -bool IFX_SeekableWriteStream::WriteBlock(const void* pData, size_t size) { - return WriteBlock(pData, GetSize(), size); -} - -bool IFX_SeekableReadStream::IsEOF() { - return false; -} - -FX_FILESIZE IFX_SeekableReadStream::GetPosition() { - return 0; -} - -size_t IFX_SeekableReadStream::ReadBlock(void* buffer, size_t size) { - return 0; -} - -bool IFX_SeekableStream::WriteBlock(const void* buffer, size_t size) { - return WriteBlock(buffer, GetSize(), size); -} diff --git a/core/fxcrt/fxcrt_windows.cpp b/core/fxcrt/fxcrt_windows.cpp deleted file mode 100644 index 638338706e2cc884088dbde6c22842f1640df598..0000000000000000000000000000000000000000 --- a/core/fxcrt/fxcrt_windows.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fxcrt_windows.h" - -#include "core/fxcrt/fx_string.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - -// static -IFXCRT_FileAccess* IFXCRT_FileAccess::Create() { - return new CFXCRT_FileAccess_Win64; -} - -void FXCRT_Windows_GetFileMode(uint32_t dwMode, - uint32_t& dwAccess, - uint32_t& dwShare, - uint32_t& dwCreation) { - dwAccess = GENERIC_READ; - dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE; - if (!(dwMode & FX_FILEMODE_ReadOnly)) { - dwAccess |= GENERIC_WRITE; - dwCreation = (dwMode & FX_FILEMODE_Truncate) ? CREATE_ALWAYS : OPEN_ALWAYS; - } else { - dwCreation = OPEN_EXISTING; - } -} - -#ifdef __cplusplus -extern "C" { -#endif -WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize); -WINBASEAPI BOOL WINAPI SetFilePointerEx(HANDLE hFile, - LARGE_INTEGER liDistanceToMove, - PLARGE_INTEGER lpNewFilePointer, - DWORD dwMoveMethod); -#ifdef __cplusplus -} -#endif - -CFXCRT_FileAccess_Win64::CFXCRT_FileAccess_Win64() : m_hFile(nullptr) {} - -CFXCRT_FileAccess_Win64::~CFXCRT_FileAccess_Win64() { - Close(); -} - -bool CFXCRT_FileAccess_Win64::Open(const CFX_ByteStringC& fileName, - uint32_t dwMode) { - if (m_hFile) - return false; - - uint32_t dwAccess, dwShare, dwCreation; - FXCRT_Windows_GetFileMode(dwMode, dwAccess, dwShare, dwCreation); - m_hFile = ::CreateFileA(fileName.c_str(), dwAccess, dwShare, nullptr, - dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr); - if (m_hFile == INVALID_HANDLE_VALUE) - m_hFile = nullptr; - - return !!m_hFile; -} - -bool CFXCRT_FileAccess_Win64::Open(const CFX_WideStringC& fileName, - uint32_t dwMode) { - if (m_hFile) - return false; - - uint32_t dwAccess, dwShare, dwCreation; - FXCRT_Windows_GetFileMode(dwMode, dwAccess, dwShare, dwCreation); - m_hFile = ::CreateFileW((LPCWSTR)fileName.c_str(), dwAccess, dwShare, nullptr, - dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr); - if (m_hFile == INVALID_HANDLE_VALUE) - m_hFile = nullptr; - - return !!m_hFile; -} - -void CFXCRT_FileAccess_Win64::Close() { - if (!m_hFile) - return; - - ::CloseHandle(m_hFile); - m_hFile = nullptr; -} - -FX_FILESIZE CFXCRT_FileAccess_Win64::GetSize() const { - if (!m_hFile) - return 0; - - LARGE_INTEGER size = {}; - if (!::GetFileSizeEx(m_hFile, &size)) - return 0; - - return (FX_FILESIZE)size.QuadPart; -} - -FX_FILESIZE CFXCRT_FileAccess_Win64::GetPosition() const { - if (!m_hFile) - return (FX_FILESIZE)-1; - - LARGE_INTEGER dist = {}; - LARGE_INTEGER newPos = {}; - if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_CURRENT)) - return (FX_FILESIZE)-1; - - return (FX_FILESIZE)newPos.QuadPart; -} - -FX_FILESIZE CFXCRT_FileAccess_Win64::SetPosition(FX_FILESIZE pos) { - if (!m_hFile) - return (FX_FILESIZE)-1; - - LARGE_INTEGER dist; - dist.QuadPart = pos; - LARGE_INTEGER newPos = {}; - if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_BEGIN)) - return (FX_FILESIZE)-1; - - return (FX_FILESIZE)newPos.QuadPart; -} - -size_t CFXCRT_FileAccess_Win64::Read(void* pBuffer, size_t szBuffer) { - if (!m_hFile) - return 0; - - size_t szRead = 0; - if (!::ReadFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szRead, - nullptr)) { - return 0; - } - return szRead; -} - -size_t CFXCRT_FileAccess_Win64::Write(const void* pBuffer, size_t szBuffer) { - if (!m_hFile) - return 0; - - size_t szWrite = 0; - if (!::WriteFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szWrite, - nullptr)) { - return 0; - } - return szWrite; -} - -size_t CFXCRT_FileAccess_Win64::ReadPos(void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) { - if (!m_hFile) - return 0; - - if (pos >= GetSize()) - return 0; - - if (SetPosition(pos) == (FX_FILESIZE)-1) - return 0; - - return Read(pBuffer, szBuffer); -} - -size_t CFXCRT_FileAccess_Win64::WritePos(const void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) { - if (!m_hFile) { - return 0; - } - if (SetPosition(pos) == (FX_FILESIZE)-1) { - return 0; - } - return Write(pBuffer, szBuffer); -} - -bool CFXCRT_FileAccess_Win64::Flush() { - if (!m_hFile) - return false; - - return !!::FlushFileBuffers(m_hFile); -} - -bool CFXCRT_FileAccess_Win64::Truncate(FX_FILESIZE szFile) { - if (SetPosition(szFile) == (FX_FILESIZE)-1) - return false; - - return !!::SetEndOfFile(m_hFile); -} -#endif diff --git a/core/fxcrt/fxcrt_windows.h b/core/fxcrt/fxcrt_windows.h deleted file mode 100644 index f8f948360da4e21c2be8fd56971def3667e0b66e..0000000000000000000000000000000000000000 --- a/core/fxcrt/fxcrt_windows.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_FXCRT_WINDOWS_H_ -#define CORE_FXCRT_FXCRT_WINDOWS_H_ - -#include "core/fxcrt/extension.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -class CFXCRT_FileAccess_Win64 : public IFXCRT_FileAccess { - public: - CFXCRT_FileAccess_Win64(); - ~CFXCRT_FileAccess_Win64() override; - - // IFXCRT_FileAccess - bool Open(const CFX_ByteStringC& fileName, uint32_t dwMode) override; - bool Open(const CFX_WideStringC& fileName, uint32_t dwMode) override; - void Close() override; - FX_FILESIZE GetSize() const override; - FX_FILESIZE GetPosition() const override; - FX_FILESIZE SetPosition(FX_FILESIZE pos) override; - size_t Read(void* pBuffer, size_t szBuffer) override; - size_t Write(const void* pBuffer, size_t szBuffer) override; - size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) override; - size_t WritePos(const void* pBuffer, - size_t szBuffer, - FX_FILESIZE pos) override; - bool Flush() override; - bool Truncate(FX_FILESIZE szFile) override; - - protected: - void* m_hFile; -}; -#endif - -#endif // CORE_FXCRT_FXCRT_WINDOWS_H_ diff --git a/core/fxcrt/ifx_fileaccess.h b/core/fxcrt/ifx_fileaccess.h new file mode 100644 index 0000000000000000000000000000000000000000..9bfe2b4e63bede6b9db1068aa5864dfeeaecca21 --- /dev/null +++ b/core/fxcrt/ifx_fileaccess.h @@ -0,0 +1,38 @@ +// 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 CORE_FXCRT_IFX_FILEACCESS_H_ +#define CORE_FXCRT_IFX_FILEACCESS_H_ + +#include +#include + +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/fx_string.h" + +class IFX_FileAccess { + public: + static std::unique_ptr Create(); + virtual ~IFX_FileAccess() {} + + virtual bool Open(const ByteStringView& fileName, uint32_t dwMode) = 0; + virtual bool Open(const WideStringView& fileName, uint32_t dwMode) = 0; + virtual void Close() = 0; + virtual FX_FILESIZE GetSize() const = 0; + virtual FX_FILESIZE GetPosition() const = 0; + virtual FX_FILESIZE SetPosition(FX_FILESIZE pos) = 0; + virtual size_t Read(void* pBuffer, size_t szBuffer) = 0; + virtual size_t Write(const void* pBuffer, size_t szBuffer) = 0; + virtual size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0; + virtual size_t WritePos(const void* pBuffer, + size_t szBuffer, + FX_FILESIZE pos) = 0; + virtual bool Flush() = 0; + virtual bool Truncate(FX_FILESIZE szFile) = 0; +}; + +#endif // CORE_FXCRT_IFX_FILEACCESS_H_ diff --git a/core/fxcrt/ifx_locale.h b/core/fxcrt/ifx_locale.h new file mode 100644 index 0000000000000000000000000000000000000000..5918e7a183e6d5cc2c6253319980a3924a397ae1 --- /dev/null +++ b/core/fxcrt/ifx_locale.h @@ -0,0 +1,76 @@ +// 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 CORE_FXCRT_IFX_LOCALE_H_ +#define CORE_FXCRT_IFX_LOCALE_H_ + +#include "core/fxcrt/cfx_datetime.h" +#include "core/fxcrt/fx_string.h" + +enum FX_LOCALENUMSYMBOL { + FX_LOCALENUMSYMBOL_Decimal, + FX_LOCALENUMSYMBOL_Grouping, + FX_LOCALENUMSYMBOL_Percent, + FX_LOCALENUMSYMBOL_Minus, + FX_LOCALENUMSYMBOL_Zero, + FX_LOCALENUMSYMBOL_CurrencySymbol, + FX_LOCALENUMSYMBOL_CurrencyName, +}; + +enum FX_LOCALEDATETIMESUBCATEGORY { + FX_LOCALEDATETIMESUBCATEGORY_Default, + FX_LOCALEDATETIMESUBCATEGORY_Short, + FX_LOCALEDATETIMESUBCATEGORY_Medium, + FX_LOCALEDATETIMESUBCATEGORY_Full, + FX_LOCALEDATETIMESUBCATEGORY_Long, +}; + +enum FX_LOCALENUMSUBCATEGORY { + FX_LOCALENUMPATTERN_Percent, + FX_LOCALENUMPATTERN_Currency, + FX_LOCALENUMPATTERN_Decimal, + FX_LOCALENUMPATTERN_Integer, +}; + +enum FX_LOCALECATEGORY { + FX_LOCALECATEGORY_Unknown, + FX_LOCALECATEGORY_Date, + FX_LOCALECATEGORY_Time, + FX_LOCALECATEGORY_DateTime, + FX_LOCALECATEGORY_Num, + FX_LOCALECATEGORY_Text, + FX_LOCALECATEGORY_Zero, + FX_LOCALECATEGORY_Null, +}; + +enum FX_DATETIMETYPE { + FX_DATETIMETYPE_Unknown, + FX_DATETIMETYPE_Date, + FX_DATETIMETYPE_Time, + FX_DATETIMETYPE_DateTime, + FX_DATETIMETYPE_TimeDate, +}; + +class IFX_Locale { + public: + virtual ~IFX_Locale() {} + + virtual WideString GetName() const = 0; + virtual WideString GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const = 0; + virtual WideString GetDateTimeSymbols() const = 0; + virtual WideString GetMonthName(int32_t nMonth, bool bAbbr) const = 0; + virtual WideString GetDayName(int32_t nWeek, bool bAbbr) const = 0; + virtual WideString GetMeridiemName(bool bAM) const = 0; + virtual FX_TIMEZONE GetTimeZone() const = 0; + virtual WideString GetEraName(bool bAD) const = 0; + virtual WideString GetDatePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const = 0; + virtual WideString GetTimePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const = 0; + virtual WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const = 0; +}; + +#endif // CORE_FXCRT_IFX_LOCALE_H_ diff --git a/core/fxcrt/ifx_pauseindicator.h b/core/fxcrt/ifx_pauseindicator.h new file mode 100644 index 0000000000000000000000000000000000000000..79c6016706d61acb5cc280d5db7f7c3106f3f8ab --- /dev/null +++ b/core/fxcrt/ifx_pauseindicator.h @@ -0,0 +1,16 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_IFX_PAUSEINDICATOR_H_ +#define CORE_FXCRT_IFX_PAUSEINDICATOR_H_ + +class IFX_PauseIndicator { + public: + virtual ~IFX_PauseIndicator() {} + virtual bool NeedToPauseNow() = 0; +}; + +#endif // CORE_FXCRT_IFX_PAUSEINDICATOR_H_ diff --git a/core/fxcrt/maybe_owned.h b/core/fxcrt/maybe_owned.h new file mode 100644 index 0000000000000000000000000000000000000000..11dd68642d08d0ea4cca88ca8113525b15879f2d --- /dev/null +++ b/core/fxcrt/maybe_owned.h @@ -0,0 +1,92 @@ +// Copyright 2016 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. + +#ifndef CORE_FXCRT_MAYBE_OWNED_H_ +#define CORE_FXCRT_MAYBE_OWNED_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_system.h" + +namespace fxcrt { + +// A template that can hold either owned or unowned references, and cleans up +// appropriately. Possibly the most pernicious anti-pattern imaginable, but +// it crops up throughout the codebase due to a desire to avoid copying-in +// objects or data. +template > +class MaybeOwned { + public: + MaybeOwned() : m_pObj(nullptr) {} + explicit MaybeOwned(T* ptr) : m_pObj(ptr) {} + explicit MaybeOwned(std::unique_ptr ptr) + : m_pOwnedObj(std::move(ptr)), m_pObj(m_pOwnedObj.get()) {} + + MaybeOwned(const MaybeOwned& that) = delete; + MaybeOwned(MaybeOwned&& that) noexcept + : m_pOwnedObj(that.m_pOwnedObj.release()), m_pObj(that.m_pObj) { + that.m_pObj = nullptr; + } + + void Reset(std::unique_ptr ptr) { + m_pOwnedObj = std::move(ptr); + m_pObj = m_pOwnedObj.get(); + } + void Reset(T* ptr = nullptr) { + m_pOwnedObj.reset(); + m_pObj = ptr; + } + + bool IsOwned() const { return !!m_pOwnedObj; } + T* Get() const { return m_pObj; } + std::unique_ptr Release() { + ASSERT(IsOwned()); + return std::move(m_pOwnedObj); + } + + MaybeOwned& operator=(const MaybeOwned& that) = delete; + MaybeOwned& operator=(MaybeOwned&& that) { + m_pOwnedObj = std::move(that.m_pOwnedObj); + m_pObj = that.m_pObj; + that.m_pObj = nullptr; + return *this; + } + MaybeOwned& operator=(T* ptr) { + Reset(ptr); + return *this; + } + MaybeOwned& operator=(std::unique_ptr ptr) { + Reset(std::move(ptr)); + return *this; + } + + bool operator==(const MaybeOwned& that) const { return Get() == that.Get(); } + bool operator==(const std::unique_ptr& ptr) const { + return Get() == ptr.get(); + } + bool operator==(T* ptr) const { return Get() == ptr; } + + bool operator!=(const MaybeOwned& that) const { return !(*this == that); } + bool operator!=(const std::unique_ptr ptr) const { + return !(*this == ptr); + } + bool operator!=(T* ptr) const { return !(*this == ptr); } + + explicit operator bool() const { return !!m_pObj; } + T& operator*() const { return *m_pObj; } + T* operator->() const { return m_pObj; } + + private: + std::unique_ptr m_pOwnedObj; + T* m_pObj; +}; + +} // namespace fxcrt + +using fxcrt::MaybeOwned; + +#endif // CORE_FXCRT_MAYBE_OWNED_H_ diff --git a/core/fxcrt/maybe_owned_unittest.cpp b/core/fxcrt/maybe_owned_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..718264720749241aaa6f61409b3087e7fed24f49 --- /dev/null +++ b/core/fxcrt/maybe_owned_unittest.cpp @@ -0,0 +1,181 @@ +// Copyright 2016 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. + +#include "core/fxcrt/maybe_owned.h" + +#include +#include + +#include "core/fxcrt/fx_memory.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +namespace fxcrt { +namespace { + +class PseudoDeletable { + public: + explicit PseudoDeletable(int id, int* count_location) + : id_(id), count_location_(count_location) {} + ~PseudoDeletable() { ++(*count_location_); } + int GetID() const { return id_; } + + private: + int id_; + int* count_location_; +}; + +} // namespace + +TEST(MaybeOwned, Null) { + MaybeOwned ptr1; + EXPECT_FALSE(ptr1.IsOwned()); + EXPECT_FALSE(ptr1); + EXPECT_EQ(nullptr, ptr1.Get()); + + MaybeOwned ptr2; + EXPECT_TRUE(ptr1 == ptr2); + EXPECT_FALSE(ptr1 != ptr2); +} + +TEST(MaybeOwned, NotOwned) { + int delete_count = 0; + PseudoDeletable thing1(100, &delete_count); + { + MaybeOwned ptr(&thing1); + EXPECT_FALSE(ptr.IsOwned()); + EXPECT_EQ(ptr.Get(), &thing1); + EXPECT_EQ(100, ptr->GetID()); + EXPECT_TRUE(ptr == &thing1); + EXPECT_FALSE(ptr != &thing1); + + MaybeOwned empty; + EXPECT_FALSE(ptr == empty); + EXPECT_TRUE(ptr != empty); + } + EXPECT_EQ(0, delete_count); + + delete_count = 0; + PseudoDeletable thing2(200, &delete_count); + { + MaybeOwned ptr(&thing1); + ptr = &thing2; + EXPECT_FALSE(ptr.IsOwned()); + EXPECT_EQ(ptr.Get(), &thing2); + EXPECT_EQ(200, ptr->GetID()); + } + EXPECT_EQ(0, delete_count); + + delete_count = 0; + int owned_delete_count = 0; + { + MaybeOwned ptr(&thing1); + EXPECT_EQ(100, ptr->GetID()); + ptr = pdfium::MakeUnique(300, &owned_delete_count); + EXPECT_TRUE(ptr.IsOwned()); + EXPECT_EQ(300, ptr->GetID()); + } + EXPECT_EQ(0, delete_count); + EXPECT_EQ(1, owned_delete_count); +} + +TEST(MaybeOwned, Owned) { + int delete_count = 0; + { + MaybeOwned ptr( + pdfium::MakeUnique(100, &delete_count)); + EXPECT_TRUE(ptr.IsOwned()); + EXPECT_EQ(100, ptr->GetID()); + + MaybeOwned empty; + EXPECT_FALSE(ptr == empty); + EXPECT_TRUE(ptr != empty); + } + EXPECT_EQ(1, delete_count); + + delete_count = 0; + { + MaybeOwned ptr( + pdfium::MakeUnique(200, &delete_count)); + ptr = pdfium::MakeUnique(300, &delete_count); + EXPECT_TRUE(ptr.IsOwned()); + EXPECT_EQ(300, ptr->GetID()); + EXPECT_EQ(1, delete_count); + } + EXPECT_EQ(2, delete_count); + + delete_count = 0; + int unowned_delete_count = 0; + PseudoDeletable thing2(400, &unowned_delete_count); + { + MaybeOwned ptr( + pdfium::MakeUnique(500, &delete_count)); + ptr = &thing2; + EXPECT_FALSE(ptr.IsOwned()); + EXPECT_EQ(400, ptr->GetID()); + EXPECT_EQ(1, delete_count); + EXPECT_EQ(0, unowned_delete_count); + } + EXPECT_EQ(1, delete_count); + EXPECT_EQ(0, unowned_delete_count); +} + +TEST(MaybeOwned, Release) { + int delete_count = 0; + { + std::unique_ptr stolen; + { + MaybeOwned ptr( + pdfium::MakeUnique(100, &delete_count)); + EXPECT_TRUE(ptr.IsOwned()); + stolen = ptr.Release(); + EXPECT_FALSE(ptr.IsOwned()); + EXPECT_EQ(ptr, stolen); + EXPECT_EQ(0, delete_count); + } + EXPECT_EQ(0, delete_count); + } + EXPECT_EQ(1, delete_count); +} + +TEST(MaybeOwned, Move) { + int delete_count = 0; + PseudoDeletable thing1(100, &delete_count); + { + MaybeOwned ptr1(&thing1); + MaybeOwned ptr2( + pdfium::MakeUnique(200, &delete_count)); + EXPECT_FALSE(ptr1.IsOwned()); + EXPECT_TRUE(ptr2.IsOwned()); + + MaybeOwned ptr3(std::move(ptr1)); + MaybeOwned ptr4(std::move(ptr2)); + EXPECT_FALSE(ptr1.IsOwned()); + EXPECT_FALSE(ptr2.IsOwned()); + EXPECT_FALSE(ptr3.IsOwned()); + EXPECT_TRUE(ptr4.IsOwned()); + EXPECT_EQ(0, delete_count); + EXPECT_EQ(nullptr, ptr1.Get()); + EXPECT_EQ(nullptr, ptr2.Get()); + EXPECT_EQ(100, ptr3->GetID()); + EXPECT_EQ(200, ptr4->GetID()); + + MaybeOwned ptr5; + MaybeOwned ptr6; + ptr5 = std::move(ptr3); + ptr6 = std::move(ptr4); + EXPECT_FALSE(ptr3.IsOwned()); + EXPECT_FALSE(ptr4.IsOwned()); + EXPECT_FALSE(ptr5.IsOwned()); + EXPECT_TRUE(ptr6.IsOwned()); + EXPECT_EQ(0, delete_count); + EXPECT_EQ(nullptr, ptr3.Get()); + EXPECT_EQ(nullptr, ptr4.Get()); + EXPECT_EQ(100, ptr5->GetID()); + EXPECT_EQ(200, ptr6->GetID()); + } + EXPECT_EQ(1, delete_count); +} + +} // namespace fxcrt diff --git a/core/fxcrt/observable.h b/core/fxcrt/observable.h new file mode 100644 index 0000000000000000000000000000000000000000..2013b75be91cd26559e7b7a36f9f0dfce5c50f66 --- /dev/null +++ b/core/fxcrt/observable.h @@ -0,0 +1,87 @@ +// Copyright 2016 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. + +#ifndef CORE_FXCRT_OBSERVABLE_H_ +#define CORE_FXCRT_OBSERVABLE_H_ + +#include + +#include "core/fxcrt/fx_system.h" +#include "third_party/base/stl_util.h" + +namespace fxcrt { + +template +class Observable { + public: + class ObservedPtr { + public: + ObservedPtr() : m_pObservable(nullptr) {} + explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) { + if (m_pObservable) + m_pObservable->AddObservedPtr(this); + } + ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {} + ~ObservedPtr() { + if (m_pObservable) + m_pObservable->RemoveObservedPtr(this); + } + void Reset(T* pObservable = nullptr) { + if (m_pObservable) + m_pObservable->RemoveObservedPtr(this); + m_pObservable = pObservable; + if (m_pObservable) + m_pObservable->AddObservedPtr(this); + } + void OnDestroy() { + ASSERT(m_pObservable); + m_pObservable = nullptr; + } + ObservedPtr& operator=(const ObservedPtr& that) { + Reset(that.Get()); + return *this; + } + bool operator==(const ObservedPtr& that) const { + return m_pObservable == that.m_pObservable; + } + bool operator!=(const ObservedPtr& that) const { return !(*this == that); } + explicit operator bool() const { return !!m_pObservable; } + T* Get() const { return m_pObservable; } + T& operator*() const { return *m_pObservable; } + T* operator->() const { return m_pObservable; } + + private: + T* m_pObservable; + }; + + Observable() = default; + Observable(const Observable& that) = delete; + ~Observable() { NotifyObservedPtrs(); } + void AddObservedPtr(ObservedPtr* pObservedPtr) { + ASSERT(!pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr)); + m_ObservedPtrs.insert(pObservedPtr); + } + void RemoveObservedPtr(ObservedPtr* pObservedPtr) { + ASSERT(pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr)); + m_ObservedPtrs.erase(pObservedPtr); + } + void NotifyObservedPtrs() { + for (auto* pObservedPtr : m_ObservedPtrs) + pObservedPtr->OnDestroy(); + m_ObservedPtrs.clear(); + } + Observable& operator=(const Observable& that) = delete; + + protected: + size_t ActiveObservedPtrsForTesting() const { return m_ObservedPtrs.size(); } + + private: + std::set m_ObservedPtrs; +}; + +} // namespace fxcrt + +using fxcrt::Observable; + +#endif // CORE_FXCRT_OBSERVABLE_H_ diff --git a/core/fxcrt/observable_unittest.cpp b/core/fxcrt/observable_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e64743d86ff68fd769ff5659b78e99467dbc39f --- /dev/null +++ b/core/fxcrt/observable_unittest.cpp @@ -0,0 +1,188 @@ +// Copyright 2016 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. + +#include "core/fxcrt/observable.h" + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { +namespace { + +class PseudoObservable : public Observable { + public: + PseudoObservable() {} + int SomeMethod() { return 42; } + size_t ActiveObservedPtrs() const { return ActiveObservedPtrsForTesting(); } +}; + +} // namespace + +TEST(ObservePtr, Null) { + PseudoObservable::ObservedPtr ptr; + EXPECT_EQ(nullptr, ptr.Get()); +} + +TEST(ObservePtr, LivesLonger) { + PseudoObservable* pObs = new PseudoObservable; + PseudoObservable::ObservedPtr ptr(pObs); + EXPECT_NE(nullptr, ptr.Get()); + EXPECT_EQ(1u, pObs->ActiveObservedPtrs()); + delete pObs; + EXPECT_EQ(nullptr, ptr.Get()); +} + +TEST(ObservePtr, LivesShorter) { + PseudoObservable obs; + { + PseudoObservable::ObservedPtr ptr(&obs); + EXPECT_NE(nullptr, ptr.Get()); + EXPECT_EQ(1u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(0u, obs.ActiveObservedPtrs()); +} + +TEST(ObservePtr, CopyConstruct) { + PseudoObservable obs; + { + PseudoObservable::ObservedPtr ptr(&obs); + EXPECT_NE(nullptr, ptr.Get()); + EXPECT_EQ(1u, obs.ActiveObservedPtrs()); + { + PseudoObservable::ObservedPtr ptr2(ptr); + EXPECT_NE(nullptr, ptr2.Get()); + EXPECT_EQ(2u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(1u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(0u, obs.ActiveObservedPtrs()); +} + +TEST(ObservePtr, CopyAssign) { + PseudoObservable obs; + { + PseudoObservable::ObservedPtr ptr(&obs); + EXPECT_NE(nullptr, ptr.Get()); + EXPECT_EQ(1u, obs.ActiveObservedPtrs()); + { + PseudoObservable::ObservedPtr ptr2; + ptr2 = ptr; + EXPECT_NE(nullptr, ptr2.Get()); + EXPECT_EQ(2u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(1u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(0u, obs.ActiveObservedPtrs()); +} + +TEST(ObservePtr, Vector) { + PseudoObservable obs; + { + std::vector vec1; + std::vector vec2; + vec1.emplace_back(&obs); + vec1.emplace_back(&obs); + EXPECT_NE(nullptr, vec1[0].Get()); + EXPECT_NE(nullptr, vec1[1].Get()); + EXPECT_EQ(2u, obs.ActiveObservedPtrs()); + vec2 = vec1; + EXPECT_NE(nullptr, vec2[0].Get()); + EXPECT_NE(nullptr, vec2[1].Get()); + EXPECT_EQ(4u, obs.ActiveObservedPtrs()); + vec1.clear(); + EXPECT_EQ(2u, obs.ActiveObservedPtrs()); + vec2.resize(10000); + EXPECT_EQ(2u, obs.ActiveObservedPtrs()); + vec2.resize(0); + EXPECT_EQ(0u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(0u, obs.ActiveObservedPtrs()); +} + +TEST(ObservePtr, VectorAutoClear) { + std::vector vec1; + { + PseudoObservable obs; + vec1.emplace_back(&obs); + vec1.emplace_back(&obs); + EXPECT_NE(nullptr, vec1[0].Get()); + EXPECT_NE(nullptr, vec1[1].Get()); + EXPECT_EQ(2u, obs.ActiveObservedPtrs()); + } + EXPECT_EQ(nullptr, vec1[0].Get()); + EXPECT_EQ(nullptr, vec1[1].Get()); +} + +TEST(ObservePtr, ResetNull) { + PseudoObservable obs; + PseudoObservable::ObservedPtr ptr(&obs); + EXPECT_EQ(1u, obs.ActiveObservedPtrs()); + ptr.Reset(); + EXPECT_EQ(0u, obs.ActiveObservedPtrs()); +} + +TEST(ObservePtr, Reset) { + PseudoObservable obs1; + PseudoObservable obs2; + PseudoObservable::ObservedPtr ptr(&obs1); + EXPECT_EQ(1u, obs1.ActiveObservedPtrs()); + EXPECT_EQ(0u, obs2.ActiveObservedPtrs()); + ptr.Reset(&obs2); + EXPECT_EQ(0u, obs1.ActiveObservedPtrs()); + EXPECT_EQ(1u, obs2.ActiveObservedPtrs()); +} + +TEST(ObservePtr, Equals) { + PseudoObservable obj1; + PseudoObservable obj2; + PseudoObservable::ObservedPtr null_ptr1; + PseudoObservable::ObservedPtr obj1_ptr1(&obj1); + PseudoObservable::ObservedPtr obj2_ptr1(&obj2); + { + PseudoObservable::ObservedPtr null_ptr2; + EXPECT_TRUE(null_ptr1 == null_ptr2); + + PseudoObservable::ObservedPtr obj1_ptr2(&obj1); + EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); + + PseudoObservable::ObservedPtr obj2_ptr2(&obj2); + EXPECT_TRUE(obj2_ptr1 == obj2_ptr2); + } + EXPECT_FALSE(null_ptr1 == obj1_ptr1); + EXPECT_FALSE(null_ptr1 == obj2_ptr1); + EXPECT_FALSE(obj1_ptr1 == obj2_ptr1); +} + +TEST(ObservePtr, NotEquals) { + PseudoObservable obj1; + PseudoObservable obj2; + PseudoObservable::ObservedPtr null_ptr1; + PseudoObservable::ObservedPtr obj1_ptr1(&obj1); + PseudoObservable::ObservedPtr obj2_ptr1(&obj2); + { + PseudoObservable::ObservedPtr null_ptr2; + PseudoObservable::ObservedPtr obj1_ptr2(&obj1); + PseudoObservable::ObservedPtr obj2_ptr2(&obj2); + EXPECT_FALSE(null_ptr1 != null_ptr2); + EXPECT_FALSE(obj1_ptr1 != obj1_ptr2); + EXPECT_FALSE(obj2_ptr1 != obj2_ptr2); + } + EXPECT_TRUE(null_ptr1 != obj1_ptr1); + EXPECT_TRUE(null_ptr1 != obj2_ptr1); + EXPECT_TRUE(obj1_ptr1 != obj2_ptr1); +} + +TEST(ObservePtr, Bool) { + PseudoObservable obj1; + PseudoObservable::ObservedPtr null_ptr; + PseudoObservable::ObservedPtr obj1_ptr(&obj1); + bool null_bool = !!null_ptr; + bool obj1_bool = !!obj1_ptr; + EXPECT_FALSE(null_bool); + EXPECT_TRUE(obj1_bool); +} + +} // namespace fxcrt diff --git a/core/fxcrt/retain_ptr.h b/core/fxcrt/retain_ptr.h new file mode 100644 index 0000000000000000000000000000000000000000..e14b1ef5dc2f4dffca6aecac938e393074177b80 --- /dev/null +++ b/core/fxcrt/retain_ptr.h @@ -0,0 +1,130 @@ +// Copyright 2016 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. + +#ifndef CORE_FXCRT_RETAIN_PTR_H_ +#define CORE_FXCRT_RETAIN_PTR_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_system.h" + +namespace fxcrt { + +// Used with std::unique_ptr to Release() objects that can't be deleted. +template +struct ReleaseDeleter { + inline void operator()(T* ptr) const { ptr->Release(); } +}; + +// Analogous to base's scoped_refptr. +template +class RetainPtr { + public: + explicit RetainPtr(T* pObj) : m_pObj(pObj) { + if (m_pObj) + m_pObj->Retain(); + } + + RetainPtr() = default; + RetainPtr(const RetainPtr& that) : RetainPtr(that.Get()) {} + RetainPtr(RetainPtr&& that) noexcept { Swap(that); } + + // Deliberately implicit to allow returning nullptrs. + // NOLINTNEXTLINE(runtime/explicit) + RetainPtr(std::nullptr_t ptr) {} + + template + RetainPtr(const RetainPtr& that) : RetainPtr(that.Get()) {} + + template + RetainPtr As() const { + return RetainPtr(static_cast(Get())); + } + + void Reset(T* obj = nullptr) { + if (obj) + obj->Retain(); + m_pObj.reset(obj); + } + + T* Get() const { return m_pObj.get(); } + void Swap(RetainPtr& that) { m_pObj.swap(that.m_pObj); } + + // Useful for passing notion of object ownership across a C API. + T* Leak() { return m_pObj.release(); } + void Unleak(T* ptr) { m_pObj.reset(ptr); } + + RetainPtr& operator=(const RetainPtr& that) { + if (*this != that) + Reset(that.Get()); + return *this; + } + + RetainPtr& operator=(RetainPtr&& that) { + m_pObj.reset(that.Leak()); + return *this; + } + + bool operator==(const RetainPtr& that) const { return Get() == that.Get(); } + bool operator!=(const RetainPtr& that) const { return !(*this == that); } + + bool operator<(const RetainPtr& that) const { + return std::less()(Get(), that.Get()); + } + + explicit operator bool() const { return !!m_pObj; } + T& operator*() const { return *m_pObj.get(); } + T* operator->() const { return m_pObj.get(); } + + private: + std::unique_ptr> m_pObj; +}; + +// Trivial implementation - internal ref count with virtual destructor. +class Retainable { + public: + bool HasOneRef() const { return m_nRefCount == 1; } + + protected: + virtual ~Retainable() = default; + + private: + template + friend struct ReleaseDeleter; + + template + friend class RetainPtr; + + void Retain() { ++m_nRefCount; } + void Release() { + ASSERT(m_nRefCount > 0); + if (--m_nRefCount == 0) + delete this; + } + + intptr_t m_nRefCount = 0; +}; + +} // namespace fxcrt + +using fxcrt::ReleaseDeleter; +using fxcrt::RetainPtr; +using fxcrt::Retainable; + +namespace pdfium { + +// Helper to make a RetainPtr along the lines of std::make_unique<>(), +// or pdfium::MakeUnique<>(). Arguments are forwarded to T's constructor. +// Classes managed by RetainPtr should have protected (or private) +// constructors, and should friend this function. +template +RetainPtr MakeRetain(Args&&... args) { + return RetainPtr(new T(std::forward(args)...)); +} + +} // namespace pdfium + +#endif // CORE_FXCRT_RETAIN_PTR_H_ diff --git a/core/fxcrt/retain_ptr_unittest.cpp b/core/fxcrt/retain_ptr_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4b2994eaed7759d0502f40533c1cef6655053eb --- /dev/null +++ b/core/fxcrt/retain_ptr_unittest.cpp @@ -0,0 +1,303 @@ +// Copyright 2016 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. + +#include "core/fxcrt/retain_ptr.h" + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { +namespace { + +class PseudoRetainable { + public: + PseudoRetainable() : retain_count_(0), release_count_(0) {} + void Retain() { ++retain_count_; } + void Release() { ++release_count_; } + int retain_count() const { return retain_count_; } + int release_count() const { return release_count_; } + + private: + int retain_count_; + int release_count_; +}; + +} // namespace + +TEST(RetainPtr, Null) { + RetainPtr ptr; + EXPECT_EQ(nullptr, ptr.Get()); +} + +TEST(RetainPtr, Normal) { + PseudoRetainable obj; + { + RetainPtr ptr(&obj); + EXPECT_EQ(&obj, ptr.Get()); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, CopyCtor) { + PseudoRetainable obj; + { + RetainPtr ptr1(&obj); + { + RetainPtr ptr2(ptr1); + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(2, obj.release_count()); +} + +TEST(RetainPtr, MoveCtor) { + PseudoRetainable obj; + { + RetainPtr ptr1(&obj); + { + RetainPtr ptr2(std::move(ptr1)); + EXPECT_EQ(nullptr, ptr1.Get()); + EXPECT_EQ(&obj, ptr2.Get()); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, ResetNull) { + PseudoRetainable obj; + { + RetainPtr ptr(&obj); + ptr.Reset(); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, Reset) { + PseudoRetainable obj1; + PseudoRetainable obj2; + { + RetainPtr ptr(&obj1); + ptr.Reset(&obj2); + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(1, obj1.release_count()); + EXPECT_EQ(1, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + } + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(1, obj1.release_count()); + EXPECT_EQ(1, obj2.retain_count()); + EXPECT_EQ(1, obj2.release_count()); +} + +TEST(RetainPtr, Swap) { + PseudoRetainable obj1; + PseudoRetainable obj2; + { + RetainPtr ptr1(&obj1); + { + RetainPtr ptr2(&obj2); + ptr1.Swap(ptr2); + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(0, obj1.release_count()); + EXPECT_EQ(1, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + } + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(1, obj1.release_count()); + EXPECT_EQ(1, obj2.retain_count()); + EXPECT_EQ(0, obj2.release_count()); + } + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(1, obj1.release_count()); + EXPECT_EQ(1, obj2.retain_count()); + EXPECT_EQ(1, obj2.release_count()); +} + +TEST(RetainPtr, Leak) { + PseudoRetainable obj; + PseudoRetainable* leak; + { + RetainPtr ptr(&obj); + leak = ptr.Leak(); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + { + RetainPtr ptr; + ptr.Unleak(leak); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, SwapNull) { + PseudoRetainable obj1; + { + RetainPtr ptr1(&obj1); + { + RetainPtr ptr2; + ptr1.Swap(ptr2); + EXPECT_FALSE(ptr1); + EXPECT_TRUE(ptr2); + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(0, obj1.release_count()); + } + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(1, obj1.release_count()); + } + EXPECT_EQ(1, obj1.retain_count()); + EXPECT_EQ(1, obj1.release_count()); +} + +TEST(RetainPtr, Assign) { + PseudoRetainable obj; + { + RetainPtr ptr(&obj); + { + RetainPtr ptr2; + ptr2 = ptr; + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(2, obj.retain_count()); + EXPECT_EQ(2, obj.release_count()); +} + +TEST(RetainPtr, MoveAssign) { + PseudoRetainable obj; + { + RetainPtr ptr1(&obj); + { + RetainPtr ptr2; + EXPECT_EQ(&obj, ptr1.Get()); + EXPECT_EQ(nullptr, ptr2.Get()); + ptr2 = std::move(ptr1); + EXPECT_EQ(nullptr, ptr1.Get()); + EXPECT_EQ(&obj, ptr2.Get()); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +TEST(RetainPtr, Equals) { + PseudoRetainable obj1; + PseudoRetainable obj2; + RetainPtr null_ptr1; + RetainPtr obj1_ptr1(&obj1); + RetainPtr obj2_ptr1(&obj2); + { + RetainPtr null_ptr2; + EXPECT_TRUE(null_ptr1 == null_ptr2); + + RetainPtr obj1_ptr2(&obj1); + EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); + + RetainPtr obj2_ptr2(&obj2); + EXPECT_TRUE(obj2_ptr1 == obj2_ptr2); + } + EXPECT_FALSE(null_ptr1 == obj1_ptr1); + EXPECT_FALSE(null_ptr1 == obj2_ptr1); + EXPECT_FALSE(obj1_ptr1 == obj2_ptr1); +} + +TEST(RetainPtr, NotEquals) { + PseudoRetainable obj1; + PseudoRetainable obj2; + RetainPtr null_ptr1; + RetainPtr obj1_ptr1(&obj1); + RetainPtr obj2_ptr1(&obj2); + { + RetainPtr null_ptr2; + RetainPtr obj1_ptr2(&obj1); + RetainPtr obj2_ptr2(&obj2); + EXPECT_FALSE(null_ptr1 != null_ptr2); + EXPECT_FALSE(obj1_ptr1 != obj1_ptr2); + EXPECT_FALSE(obj2_ptr1 != obj2_ptr2); + } + EXPECT_TRUE(null_ptr1 != obj1_ptr1); + EXPECT_TRUE(null_ptr1 != obj2_ptr1); + EXPECT_TRUE(obj1_ptr1 != obj2_ptr1); +} + +TEST(RetainPtr, LessThan) { + PseudoRetainable objs[2]; + RetainPtr obj1_ptr(&objs[0]); + RetainPtr obj2_ptr(&objs[1]); + EXPECT_TRUE(obj1_ptr < obj2_ptr); + EXPECT_FALSE(obj2_ptr < obj1_ptr); +} + +TEST(RetainPtr, Bool) { + PseudoRetainable obj1; + RetainPtr null_ptr; + RetainPtr obj1_ptr(&obj1); + bool null_bool = !!null_ptr; + bool obj1_bool = !!obj1_ptr; + EXPECT_FALSE(null_bool); + EXPECT_TRUE(obj1_bool); +} + +TEST(RetainPtr, MakeRetained) { + auto ptr = pdfium::MakeRetain(); + EXPECT_TRUE(ptr->HasOneRef()); + { + RetainPtr other = ptr; + EXPECT_FALSE(ptr->HasOneRef()); + } + EXPECT_TRUE(ptr->HasOneRef()); +} + +TEST(RetainPtr, VectorMove) { + // Proves move ctor is selected by std::vector over copy/delete, this + // may require the ctor to be marked "noexcept". + PseudoRetainable obj; + { + RetainPtr ptr(&obj); + std::vector> vec1; + vec1.push_back(std::move(ptr)); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + + std::vector> vec2 = std::move(vec1); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + + vec2.resize(4096); + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(0, obj.release_count()); + } + EXPECT_EQ(1, obj.retain_count()); + EXPECT_EQ(1, obj.release_count()); +} + +} // namespace fxcrt diff --git a/core/fxcrt/shared_copy_on_write.h b/core/fxcrt/shared_copy_on_write.h new file mode 100644 index 0000000000000000000000000000000000000000..f7d7a2afdb88c112ea95fef7ffed15e0f2898327 --- /dev/null +++ b/core/fxcrt/shared_copy_on_write.h @@ -0,0 +1,65 @@ +// Copyright 2016 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 CORE_FXCRT_SHARED_COPY_ON_WRITE_H_ +#define CORE_FXCRT_SHARED_COPY_ON_WRITE_H_ + +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" + +namespace fxcrt { + +// A shared object with Copy on Write semantics that makes it appear as +// if each one were independent. +template +class SharedCopyOnWrite { + public: + SharedCopyOnWrite() {} + SharedCopyOnWrite(const SharedCopyOnWrite& other) + : m_pObject(other.m_pObject) {} + ~SharedCopyOnWrite() {} + + template + ObjClass* Emplace(Args... params) { + m_pObject.Reset(new ObjClass(params...)); + return m_pObject.Get(); + } + + SharedCopyOnWrite& operator=(const SharedCopyOnWrite& that) { + if (*this != that) + m_pObject = that.m_pObject; + return *this; + } + + void SetNull() { m_pObject.Reset(); } + const ObjClass* GetObject() const { return m_pObject.Get(); } + + template + ObjClass* GetPrivateCopy(Args... params) { + if (!m_pObject) + return Emplace(params...); + if (!m_pObject->HasOneRef()) + m_pObject.Reset(new ObjClass(*m_pObject)); + return m_pObject.Get(); + } + + bool operator==(const SharedCopyOnWrite& that) const { + return m_pObject == that.m_pObject; + } + bool operator!=(const SharedCopyOnWrite& that) const { + return !(*this == that); + } + explicit operator bool() const { return !!m_pObject; } + + private: + RetainPtr m_pObject; +}; + +} // namespace fxcrt + +using fxcrt::SharedCopyOnWrite; + +#endif // CORE_FXCRT_SHARED_COPY_ON_WRITE_H_ diff --git a/core/fxcrt/shared_copy_on_write_unittest.cpp b/core/fxcrt/shared_copy_on_write_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57e33d10194fc92db19ce0119afe3930838d1867 --- /dev/null +++ b/core/fxcrt/shared_copy_on_write_unittest.cpp @@ -0,0 +1,132 @@ +// Copyright 2016 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. + +#include "core/fxcrt/shared_copy_on_write.h" + +#include +#include + +#include "core/fxcrt/retain_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { +namespace { + +class Observer { + public: + void OnConstruct(const std::string& name) { construction_counts_[name]++; } + void OnDestruct(const std::string& name) { destruction_counts_[name]++; } + int GetConstructionCount(const std::string& name) { + return construction_counts_[name]; + } + int GetDestructionCount(const std::string& name) { + return destruction_counts_[name]; + } + + private: + std::map construction_counts_; + std::map destruction_counts_; +}; + +class Object : public Retainable { + public: + Object(Observer* observer, const std::string& name) + : name_(name), observer_(observer) { + observer->OnConstruct(name_); + } + Object(const Object& that) : name_(that.name_), observer_(that.observer_) { + observer_->OnConstruct(name_); + } + ~Object() override { observer_->OnDestruct(name_); } + + private: + std::string name_; + Observer* observer_; +}; + +} // namespace + +TEST(SharedCopyOnWrite, Null) { + Observer observer; + { + SharedCopyOnWrite ptr; + EXPECT_EQ(nullptr, ptr.GetObject()); + } +} + +TEST(SharedCopyOnWrite, Copy) { + Observer observer; + { + SharedCopyOnWrite ptr1; + ptr1.Emplace(&observer, std::string("one")); + { + SharedCopyOnWrite ptr2 = ptr1; + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + } + { + SharedCopyOnWrite ptr3(ptr1); + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + } + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + } + EXPECT_EQ(1, observer.GetDestructionCount("one")); +} + +TEST(SharedCopyOnWrite, AssignOverOld) { + Observer observer; + { + SharedCopyOnWrite ptr1; + ptr1.Emplace(&observer, std::string("one")); + ptr1.Emplace(&observer, std::string("two")); + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(1, observer.GetConstructionCount("two")); + EXPECT_EQ(1, observer.GetDestructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("two")); + } + EXPECT_EQ(1, observer.GetDestructionCount("two")); +} + +TEST(SharedCopyOnWrite, AssignOverRetained) { + Observer observer; + { + SharedCopyOnWrite ptr1; + ptr1.Emplace(&observer, std::string("one")); + SharedCopyOnWrite ptr2(ptr1); + ptr1.Emplace(&observer, std::string("two")); + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(1, observer.GetConstructionCount("two")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("two")); + } + EXPECT_EQ(1, observer.GetDestructionCount("one")); + EXPECT_EQ(1, observer.GetDestructionCount("two")); +} + +TEST(SharedCopyOnWrite, GetModify) { + Observer observer; + { + SharedCopyOnWrite ptr; + EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one"))); + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + + EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one"))); + EXPECT_EQ(1, observer.GetConstructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + { + SharedCopyOnWrite other(ptr); + EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one"))); + EXPECT_EQ(2, observer.GetConstructionCount("one")); + EXPECT_EQ(0, observer.GetDestructionCount("one")); + } + EXPECT_EQ(2, observer.GetConstructionCount("one")); + EXPECT_EQ(1, observer.GetDestructionCount("one")); + } + EXPECT_EQ(2, observer.GetDestructionCount("one")); +} + +} // namespace fxcrt diff --git a/core/fxcrt/string_data_template.h b/core/fxcrt/string_data_template.h new file mode 100644 index 0000000000000000000000000000000000000000..bc797c07e23a41d43a7b254f11037b12eec666ea --- /dev/null +++ b/core/fxcrt/string_data_template.h @@ -0,0 +1,119 @@ +// Copyright 2016 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 CORE_FXCRT_STRING_DATA_TEMPLATE_H_ +#define CORE_FXCRT_STRING_DATA_TEMPLATE_H_ + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_system.h" +#include "third_party/base/numerics/safe_math.h" + +namespace fxcrt { + +template +class StringDataTemplate { + public: + static StringDataTemplate* Create(size_t nLen) { + ASSERT(nLen > 0); + + // Calculate space needed for the fixed portion of the struct plus the + // NUL char that is not included in |m_nAllocLength|. + int overhead = offsetof(StringDataTemplate, m_String) + sizeof(CharType); + pdfium::base::CheckedNumeric nSize = nLen; + nSize *= sizeof(CharType); + nSize += overhead; + + // Now round to an 8-byte boundary. We'd expect that this is the minimum + // granularity of any of the underlying allocators, so there may be cases + // where we can save a re-alloc when adding a few characters to a string + // by using this otherwise wasted space. + nSize += 7; + nSize &= ~7; + size_t totalSize = nSize.ValueOrDie(); + size_t usableLen = (totalSize - overhead) / sizeof(CharType); + ASSERT(usableLen >= nLen); + + void* pData = pdfium::base::PartitionAllocGeneric( + gStringPartitionAllocator.root(), totalSize, "StringDataTemplate"); + return new (pData) StringDataTemplate(nLen, usableLen); + } + + static StringDataTemplate* Create(const StringDataTemplate& other) { + StringDataTemplate* result = Create(other.m_nDataLength); + result->CopyContents(other); + return result; + } + + static StringDataTemplate* Create(const CharType* pStr, size_t nLen) { + StringDataTemplate* result = Create(nLen); + result->CopyContents(pStr, nLen); + return result; + } + + void Retain() { ++m_nRefs; } + void Release() { + if (--m_nRefs <= 0) + pdfium::base::PartitionFreeGeneric(gStringPartitionAllocator.root(), + this); + } + + bool CanOperateInPlace(size_t nTotalLen) const { + return m_nRefs <= 1 && nTotalLen <= m_nAllocLength; + } + + void CopyContents(const StringDataTemplate& other) { + ASSERT(other.m_nDataLength <= m_nAllocLength); + memcpy(m_String, other.m_String, + (other.m_nDataLength + 1) * sizeof(CharType)); + } + + void CopyContents(const CharType* pStr, size_t nLen) { + ASSERT(nLen >= 0 && nLen <= m_nAllocLength); + memcpy(m_String, pStr, nLen * sizeof(CharType)); + m_String[nLen] = 0; + } + + void CopyContentsAt(size_t offset, const CharType* pStr, size_t nLen) { + ASSERT(offset >= 0 && nLen >= 0 && offset + nLen <= m_nAllocLength); + memcpy(m_String + offset, pStr, nLen * sizeof(CharType)); + m_String[offset + nLen] = 0; + } + + // To ensure ref counts do not overflow, consider the worst possible case: + // the entire address space contains nothing but pointers to this object. + // Since the count increments with each new pointer, the largest value is + // the number of pointers that can fit into the address space. The size of + // the address space itself is a good upper bound on it. + intptr_t m_nRefs; + + // These lengths are in terms of number of characters, not bytes, and do not + // include the terminating NUL character, but the underlying buffer is sized + // to be capable of holding it. + size_t m_nDataLength; + size_t m_nAllocLength; + + // Not really 1, variable size. + CharType m_String[1]; + + private: + StringDataTemplate(size_t dataLen, size_t allocLen) + : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) { + ASSERT(dataLen >= 0); + ASSERT(dataLen <= allocLen); + m_String[dataLen] = 0; + } + + ~StringDataTemplate() = delete; +}; + +extern template class StringDataTemplate; +extern template class StringDataTemplate; + +} // namespace fxcrt + +using fxcrt::StringDataTemplate; + +#endif // CORE_FXCRT_STRING_DATA_TEMPLATE_H_ diff --git a/core/fxcrt/string_pool_template.h b/core/fxcrt/string_pool_template.h new file mode 100644 index 0000000000000000000000000000000000000000..2f9fb09a9feecfd89134acda6a5e4b32a9545b81 --- /dev/null +++ b/core/fxcrt/string_pool_template.h @@ -0,0 +1,36 @@ +// Copyright 2016 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 CORE_FXCRT_STRING_POOL_TEMPLATE_H_ +#define CORE_FXCRT_STRING_POOL_TEMPLATE_H_ + +#include + +#include "core/fxcrt/fx_string.h" + +namespace fxcrt { + +template +class StringPoolTemplate { + public: + StringType Intern(const StringType& str) { return *m_Pool.insert(str).first; } + void Clear() { m_Pool.clear(); } + + private: + std::unordered_set m_Pool; +}; + +extern template class StringPoolTemplate; +extern template class StringPoolTemplate; + +} // namespace fxcrt + +using fxcrt::StringPoolTemplate; + +using ByteStringPool = StringPoolTemplate; +using WideStringPool = StringPoolTemplate; + +#endif // CORE_FXCRT_STRING_POOL_TEMPLATE_H_ diff --git a/core/fxcrt/string_pool_template_unittest.cpp b/core/fxcrt/string_pool_template_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..717e33d9193102819693da39000cfd23707e28c1 --- /dev/null +++ b/core/fxcrt/string_pool_template_unittest.cpp @@ -0,0 +1,97 @@ +// Copyright 2016 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. + +#include "core/fxcrt/string_pool_template.h" +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { + +TEST(StringPool, ByteString) { + ByteStringPool pool; + + ByteString null1; + ByteString null2; + ByteString goats1("goats"); + ByteString goats2("goats"); + + // Underlying storage, if non-null, is not shared. + EXPECT_EQ(nullptr, null1.m_pData.Get()); + EXPECT_EQ(nullptr, null2.m_pData.Get()); + EXPECT_NE(goats1.m_pData, goats2.m_pData); + + ByteString interned_null1 = pool.Intern(null1); + ByteString interned_null2 = pool.Intern(null2); + ByteString interned_goats1 = pool.Intern(goats1); + ByteString interned_goats2 = pool.Intern(goats2); + + // Strings are logically equal after being interned. + EXPECT_EQ(null1, interned_null1); + EXPECT_EQ(null2, interned_null2); + EXPECT_EQ(goats1, interned_goats1); + EXPECT_EQ(goats2, interned_goats2); + + // Interned underlying storage, if non-null, belongs to first seen. + EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); + EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); + EXPECT_EQ(goats1.m_pData, interned_goats1.m_pData); + EXPECT_EQ(goats1.m_pData, interned_goats2.m_pData); + + pool.Clear(); + ByteString reinterned_null2 = pool.Intern(null2); + ByteString reinterned_null1 = pool.Intern(null2); + ByteString reinterned_goats2 = pool.Intern(goats2); + ByteString reinterned_goats1 = pool.Intern(goats2); + + // After clearing pool, storage was re-interned using second strings. + EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); + EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); + EXPECT_EQ(goats2.m_pData, reinterned_goats1.m_pData); + EXPECT_EQ(goats2.m_pData, reinterned_goats2.m_pData); +} + +TEST(StringPool, WideString) { + WideStringPool pool; + + WideString null1; + WideString null2; + WideString goats1(L"goats"); + WideString goats2(L"goats"); + + // Underlying storage, if non-null, is not shared. + EXPECT_EQ(nullptr, null1.m_pData.Get()); + EXPECT_EQ(nullptr, null2.m_pData.Get()); + EXPECT_NE(goats1.m_pData, goats2.m_pData); + + WideString interned_null1 = pool.Intern(null1); + WideString interned_null2 = pool.Intern(null2); + WideString interned_goats1 = pool.Intern(goats1); + WideString interned_goats2 = pool.Intern(goats2); + + // Strings are logically equal after being interned. + EXPECT_EQ(null1, interned_null1); + EXPECT_EQ(null2, interned_null2); + EXPECT_EQ(goats1, interned_goats1); + EXPECT_EQ(goats2, interned_goats2); + + // Interned underlying storage, if non-null, belongs to first seen. + EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); + EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); + EXPECT_EQ(goats1.m_pData, interned_goats1.m_pData); + EXPECT_EQ(goats1.m_pData, interned_goats2.m_pData); + + pool.Clear(); + WideString reinterned_null2 = pool.Intern(null2); + WideString reinterned_null1 = pool.Intern(null2); + WideString reinterned_goats2 = pool.Intern(goats2); + WideString reinterned_goats1 = pool.Intern(goats2); + + // After clearing pool, storage was re-interned using second strings. + EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); + EXPECT_EQ(nullptr, interned_null2.m_pData.Get()); + EXPECT_EQ(goats2.m_pData, reinterned_goats1.m_pData); + EXPECT_EQ(goats2.m_pData, reinterned_goats2.m_pData); +} + +} // namespace fxcrt diff --git a/core/fxcrt/string_view_template.h b/core/fxcrt/string_view_template.h new file mode 100644 index 0000000000000000000000000000000000000000..1e436d397889c845977ad25e5fb5defaf4fd358f --- /dev/null +++ b/core/fxcrt/string_view_template.h @@ -0,0 +1,249 @@ +// Copyright 2016 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 CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ +#define CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ + +#include +#include +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" +#include "third_party/base/optional.h" +#include "third_party/base/stl_util.h" + +namespace fxcrt { + +// An immutable string with caller-provided storage which must outlive the +// string itself. These are not necessarily nul-terminated, so that substring +// extraction (via the Mid(), Left(), and Right() methods) is copy-free. +template +class StringViewTemplate { + public: + using CharType = T; + using UnsignedType = typename std::make_unsigned::type; + using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator; + + StringViewTemplate() : m_Ptr(nullptr), m_Length(0) {} + + // Deliberately implicit to avoid calling on every string literal. + // NOLINTNEXTLINE(runtime/explicit) + StringViewTemplate(const CharType* ptr) + : m_Ptr(reinterpret_cast(ptr)), + m_Length(ptr ? FXSYS_len(ptr) : 0) {} + + StringViewTemplate(const CharType* ptr, size_t len) + : m_Ptr(reinterpret_cast(ptr)), m_Length(len) {} + + template + StringViewTemplate( + const UnsignedType* ptr, + size_t size, + typename std::enable_if::value>::type* = 0) + : m_Ptr(ptr), m_Length(size) {} + + // Deliberately implicit to avoid calling on every string literal. + // |ch| must be an lvalue that outlives the StringViewTemplate. + // NOLINTNEXTLINE(runtime/explicit) + StringViewTemplate(CharType& ch) { + m_Ptr = reinterpret_cast(&ch); + m_Length = 1; + } + + StringViewTemplate(const StringViewTemplate& src) { + m_Ptr = src.m_Ptr; + m_Length = src.m_Length; + } + + // Any changes to |vec| invalidate the string. + explicit StringViewTemplate(const std::vector& vec) { + m_Length = vec.size(); + m_Ptr = m_Length ? vec.data() : nullptr; + } + + StringViewTemplate& operator=(const CharType* src) { + m_Ptr = reinterpret_cast(src); + m_Length = src ? FXSYS_len(src) : 0; + return *this; + } + + StringViewTemplate& operator=(const StringViewTemplate& src) { + m_Ptr = src.m_Ptr; + m_Length = src.m_Length; + return *this; + } + + const_iterator begin() const { + return reinterpret_cast(m_Ptr.Get()); + } + const_iterator end() const { + return m_Ptr ? reinterpret_cast(m_Ptr.Get()) + m_Length + : nullptr; + } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + bool operator==(const CharType* ptr) const { + return FXSYS_len(ptr) == m_Length && + FXSYS_cmp(ptr, reinterpret_cast(m_Ptr.Get()), + m_Length) == 0; + } + bool operator==(const StringViewTemplate& other) const { + return other.m_Length == m_Length && + FXSYS_cmp(reinterpret_cast(other.m_Ptr.Get()), + reinterpret_cast(m_Ptr.Get()), + m_Length) == 0; + } + bool operator!=(const CharType* ptr) const { return !(*this == ptr); } + bool operator!=(const StringViewTemplate& other) const { + return !(*this == other); + } + + uint32_t GetID() const { + if (m_Length == 0) + return 0; + + uint32_t strid = 0; + size_t size = std::min(static_cast(4), m_Length); + for (size_t i = 0; i < size; i++) + strid = strid * 256 + m_Ptr.Get()[i]; + + return strid << ((4 - size) * 8); + } + + const UnsignedType* raw_str() const { return m_Ptr.Get(); } + const CharType* unterminated_c_str() const { + return reinterpret_cast(m_Ptr.Get()); + } + + size_t GetLength() const { return m_Length; } + bool IsEmpty() const { return m_Length == 0; } + bool IsValidIndex(size_t index) const { return index < GetLength(); } + bool IsValidLength(size_t length) const { return length <= GetLength(); } + + const UnsignedType& operator[](const size_t index) const { + ASSERT(IsValidIndex(index)); + return m_Ptr.Get()[index]; + } + + UnsignedType First() const { return GetLength() ? (*this)[0] : 0; } + + UnsignedType Last() const { + return GetLength() ? (*this)[GetLength() - 1] : 0; + } + + const CharType CharAt(const size_t index) const { + ASSERT(IsValidIndex(index)); + return static_cast(m_Ptr.Get()[index]); + } + + Optional Find(CharType ch) const { + const auto* found = reinterpret_cast(FXSYS_chr( + reinterpret_cast(m_Ptr.Get()), ch, m_Length)); + + return found ? Optional(found - m_Ptr.Get()) : Optional(); + } + + bool Contains(CharType ch) const { return Find(ch).has_value(); } + + StringViewTemplate Mid(size_t first, size_t count) const { + if (!m_Ptr.Get()) + return StringViewTemplate(); + + if (!IsValidIndex(first)) + return StringViewTemplate(); + + if (count == 0 || !IsValidLength(count)) + return StringViewTemplate(); + + if (!IsValidIndex(first + count - 1)) + return StringViewTemplate(); + + return StringViewTemplate(m_Ptr.Get() + first, count); + } + + StringViewTemplate Left(size_t count) const { + if (count == 0 || !IsValidLength(count)) + return StringViewTemplate(); + return Mid(0, count); + } + + StringViewTemplate Right(size_t count) const { + if (count == 0 || !IsValidLength(count)) + return StringViewTemplate(); + return Mid(GetLength() - count, count); + } + + StringViewTemplate TrimmedRight(CharType ch) const { + if (IsEmpty()) + return StringViewTemplate(); + + size_t pos = GetLength(); + while (pos && CharAt(pos - 1) == ch) + pos--; + + if (pos == 0) + return StringViewTemplate(); + + return StringViewTemplate(m_Ptr.Get(), pos); + } + + bool operator<(const StringViewTemplate& that) const { + int result = FXSYS_cmp(reinterpret_cast(m_Ptr.Get()), + reinterpret_cast(that.m_Ptr.Get()), + std::min(m_Length, that.m_Length)); + return result < 0 || (result == 0 && m_Length < that.m_Length); + } + + bool operator>(const StringViewTemplate& that) const { + int result = FXSYS_cmp(reinterpret_cast(m_Ptr.Get()), + reinterpret_cast(that.m_Ptr.Get()), + std::min(m_Length, that.m_Length)); + return result > 0 || (result == 0 && m_Length > that.m_Length); + } + + protected: + UnownedPtr m_Ptr; + size_t m_Length; + + private: + void* operator new(size_t) throw() { return nullptr; } +}; + +template +inline bool operator==(const T* lhs, const StringViewTemplate& rhs) { + return rhs == lhs; +} +template +inline bool operator!=(const T* lhs, const StringViewTemplate& rhs) { + return rhs != lhs; +} +template +inline bool operator<(const T* lhs, const StringViewTemplate& rhs) { + return rhs > lhs; +} + +extern template class StringViewTemplate; +extern template class StringViewTemplate; + +using ByteStringView = StringViewTemplate; +using WideStringView = StringViewTemplate; + +} // namespace fxcrt + +using ByteStringView = fxcrt::ByteStringView; +using WideStringView = fxcrt::WideStringView; + +#endif // CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ diff --git a/core/fxcrt/unowned_ptr.h b/core/fxcrt/unowned_ptr.h new file mode 100644 index 0000000000000000000000000000000000000000..f9753cde3704d761008288c035fa762e55e0d871 --- /dev/null +++ b/core/fxcrt/unowned_ptr.h @@ -0,0 +1,121 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CORE_FXCRT_UNOWNED_PTR_H_ +#define CORE_FXCRT_UNOWNED_PTR_H_ + +#include +#include +#include +#include + +// UnownedPtr is a smart pointer class that behaves very much like a +// standard C-style pointer. The advantages of using it over raw +// pointers are: +// +// 1. It documents the nature of the pointer with no need to add a comment +// explaining that is it // Not owned. Additionally, an attempt to delete +// an unowned ptr will fail to compile rather than silently succeeding, +// since it is a class and not a raw pointer. +// +// 2. When built for a memory tool like ASAN, the class provides a destructor +// which checks that the object being pointed to is still alive. +// +// Hence, when using UnownedPtr, no dangling pointers are ever permitted, +// even if they are not de-referenced after becoming dangling. The style of +// programming required is that the lifetime an object containing an +// UnownedPtr must be strictly less than the object to which it points. +// +// The same checks are also performed at assignment time to prove that the +// old value was not a dangling pointer, either. +// +// The array indexing operation [] is not supported on an unowned ptr, +// because an unowned ptr expresses a one to one relationship with some +// other heap object. + +namespace fxcrt { + +template +class UnownedPtr { + public: + UnownedPtr() = default; + UnownedPtr(const UnownedPtr& that) : UnownedPtr(that.Get()) {} + + template + explicit UnownedPtr(U* pObj) : m_pObj(pObj) {} + + // Deliberately implicit to allow returning nullptrs. + // NOLINTNEXTLINE(runtime/explicit) + UnownedPtr(std::nullptr_t ptr) {} + + ~UnownedPtr() { ProbeForLowSeverityLifetimeIssue(); } + + UnownedPtr& operator=(T* that) { + ProbeForLowSeverityLifetimeIssue(); + m_pObj = that; + return *this; + } + + UnownedPtr& operator=(const UnownedPtr& that) { + ProbeForLowSeverityLifetimeIssue(); + if (*this != that) + m_pObj = that.Get(); + return *this; + } + + bool operator==(const UnownedPtr& that) const { return Get() == that.Get(); } + bool operator!=(const UnownedPtr& that) const { return !(*this == that); } + bool operator<(const UnownedPtr& that) const { + return std::less()(Get(), that.Get()); + } + + template + bool operator==(const U* that) const { + return Get() == that; + } + + template + bool operator!=(const U* that) const { + return !(*this == that); + } + + T* Get() const { return m_pObj; } + + T* Release() { + ProbeForLowSeverityLifetimeIssue(); + T* pTemp = nullptr; + std::swap(pTemp, m_pObj); + return pTemp; + } + + explicit operator bool() const { return !!m_pObj; } + T& operator*() const { return *m_pObj; } + T* operator->() const { return m_pObj; } + + private: + inline void ProbeForLowSeverityLifetimeIssue() { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + if (m_pObj) + reinterpret_cast(m_pObj)[0]; +#endif + } + + T* m_pObj = nullptr; +}; + +template +inline bool operator==(const U* lhs, const UnownedPtr& rhs) { + return rhs == lhs; +} + +template +inline bool operator!=(const U* lhs, const UnownedPtr& rhs) { + return rhs != lhs; +} + +} // namespace fxcrt + +using fxcrt::UnownedPtr; + +#endif // CORE_FXCRT_UNOWNED_PTR_H_ diff --git a/core/fxcrt/unowned_ptr_unittest.cpp b/core/fxcrt/unowned_ptr_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26dffd46ecea9d1a82da00f091c151dea8086c5a --- /dev/null +++ b/core/fxcrt/unowned_ptr_unittest.cpp @@ -0,0 +1,142 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/unowned_ptr.h" + +#include +#include + +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { +namespace { + +class Clink { + public: + UnownedPtr next_ = nullptr; +}; + +void DeleteDangling() { + Clink* ptr1 = new Clink(); + Clink* ptr2 = new Clink(); + ptr2->next_ = ptr1; + delete ptr1; + delete ptr2; +} + +void AssignDangling() { + Clink* ptr1 = new Clink(); + Clink* ptr2 = new Clink(); + ptr2->next_ = ptr1; + delete ptr1; + ptr2->next_ = nullptr; + delete ptr2; +} + +void ReleaseDangling() { + Clink* ptr1 = new Clink(); + Clink* ptr2 = new Clink(); + ptr2->next_ = ptr1; + delete ptr1; + ptr2->next_.Release(); + delete ptr2; +} + +} // namespace + +TEST(UnownedPtr, PtrOk) { + Clink* ptr1 = new Clink(); + Clink* ptr2 = new Clink(); + ptr2->next_ = ptr1; + delete ptr2; + delete ptr1; +} + +TEST(UnownedPtr, PtrNotOk) { +#if defined(ADDRESS_SANITIZER) + EXPECT_DEATH(DeleteDangling(), ""); +#else + DeleteDangling(); +#endif +} + +TEST(UnownedPtr, AssignOk) { + Clink* ptr1 = new Clink(); + Clink* ptr2 = new Clink(); + ptr2->next_ = ptr1; + ptr2->next_ = nullptr; + delete ptr2; + delete ptr1; +} + +TEST(UnownedPtr, AssignNotOk) { +#if defined(ADDRESS_SANITIZER) + EXPECT_DEATH(AssignDangling(), ""); +#else + AssignDangling(); +#endif +} + +TEST(UnownedPtr, ReleaseOk) { + Clink* ptr1 = new Clink(); + Clink* ptr2 = new Clink(); + ptr2->next_ = ptr1; + ptr2->next_.Release(); + delete ptr1; + delete ptr2; +} + +TEST(UnownedPtr, ReleaseNotOk) { +#if defined(ADDRESS_SANITIZER) + EXPECT_DEATH(ReleaseDangling(), ""); +#else + ReleaseDangling(); +#endif +} + +TEST(UnownedPtr, OperatorEQ) { + int foo; + UnownedPtr ptr1; + EXPECT_TRUE(ptr1 == ptr1); + + UnownedPtr ptr2; + EXPECT_TRUE(ptr1 == ptr2); + + UnownedPtr ptr3(&foo); + EXPECT_TRUE(&foo == ptr3); + EXPECT_TRUE(ptr3 == &foo); + EXPECT_FALSE(ptr1 == ptr3); + + ptr1 = &foo; + EXPECT_TRUE(ptr1 == ptr3); +} + +TEST(UnownedPtr, OperatorNE) { + int foo; + UnownedPtr ptr1; + EXPECT_FALSE(ptr1 != ptr1); + + UnownedPtr ptr2; + EXPECT_FALSE(ptr1 != ptr2); + + UnownedPtr ptr3(&foo); + EXPECT_FALSE(&foo != ptr3); + EXPECT_FALSE(ptr3 != &foo); + EXPECT_TRUE(ptr1 != ptr3); + + ptr1 = &foo; + EXPECT_FALSE(ptr1 != ptr3); +} + +TEST(UnownedPtr, OperatorLT) { + int foos[2]; + UnownedPtr ptr1(&foos[0]); + UnownedPtr ptr2(&foos[1]); + + EXPECT_FALSE(ptr1 < ptr1); + EXPECT_TRUE(ptr1 < ptr2); + EXPECT_FALSE(ptr2 < ptr1); +} + +} // namespace fxcrt diff --git a/core/fxcrt/weak_ptr.h b/core/fxcrt/weak_ptr.h new file mode 100644 index 0000000000000000000000000000000000000000..3ec3942c5f033969deb3bcef8825964d9955e720 --- /dev/null +++ b/core/fxcrt/weak_ptr.h @@ -0,0 +1,92 @@ +// Copyright 2016 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 CORE_FXCRT_WEAK_PTR_H_ +#define CORE_FXCRT_WEAK_PTR_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" + +namespace fxcrt { + +template > +class WeakPtr { + public: + WeakPtr() = default; + WeakPtr(const WeakPtr& that) : m_pHandle(that.m_pHandle) {} + WeakPtr(WeakPtr&& that) noexcept { Swap(that); } + explicit WeakPtr(std::unique_ptr pObj) + : m_pHandle(new Handle(std::move(pObj))) {} + + // Deliberately implicit to allow passing nullptr. + // NOLINTNEXTLINE(runtime/explicit) + WeakPtr(std::nullptr_t arg) {} + + explicit operator bool() const { return m_pHandle && !!m_pHandle->Get(); } + bool HasOneRef() const { return m_pHandle && m_pHandle->HasOneRef(); } + T* operator->() { return m_pHandle->Get(); } + const T* operator->() const { return m_pHandle->Get(); } + WeakPtr& operator=(const WeakPtr& that) { + m_pHandle = that.m_pHandle; + return *this; + } + bool operator==(const WeakPtr& that) const { + return m_pHandle == that.m_pHandle; + } + bool operator!=(const WeakPtr& that) const { return !(*this == that); } + + T* Get() const { return m_pHandle ? m_pHandle->Get() : nullptr; } + void DeleteObject() { + if (m_pHandle) { + m_pHandle->Clear(); + m_pHandle.Reset(); + } + } + void Reset() { m_pHandle.Reset(); } + void Reset(std::unique_ptr pObj) { + m_pHandle.Reset(new Handle(std::move(pObj))); + } + void Swap(WeakPtr& that) { m_pHandle.Swap(that.m_pHandle); } + + private: + class Handle { + public: + explicit Handle(std::unique_ptr ptr) + : m_nCount(0), m_pObj(std::move(ptr)) {} + void Reset(std::unique_ptr ptr) { m_pObj = std::move(ptr); } + void Clear() { // Now you're all weak ptrs ... + m_pObj.reset(); // unique_ptr nulls first before invoking delete. + } + T* Get() const { return m_pObj.get(); } + T* Retain() { + ++m_nCount; + return m_pObj.get(); + } + void Release() { + if (--m_nCount == 0) + delete this; + } + bool HasOneRef() const { return m_nCount == 1; } + + private: + ~Handle() = default; + + intptr_t m_nCount; + std::unique_ptr m_pObj; + }; + + RetainPtr m_pHandle; +}; + +} // namespace fxcrt + +using fxcrt::WeakPtr; + +#endif // CORE_FXCRT_WEAK_PTR_H_ diff --git a/core/fxcrt/weak_ptr_unittest.cpp b/core/fxcrt/weak_ptr_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22a723043b2d646a6081758372c35cc6b80c1fb1 --- /dev/null +++ b/core/fxcrt/weak_ptr_unittest.cpp @@ -0,0 +1,176 @@ +// Copyright 2016 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. + +#include "core/fxcrt/weak_ptr.h" + +#include +#include + +#include "core/fxcrt/fx_memory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { +namespace { + +class PseudoDeletable; +using WeakTestPtr = WeakPtr>; +using UniqueTestPtr = + std::unique_ptr>; + +class PseudoDeletable { + public: + PseudoDeletable() : delete_count_(0) {} + void Release() { + ++delete_count_; + next_.Reset(); + } + void SetNext(const WeakTestPtr& next) { next_ = next; } + int delete_count() const { return delete_count_; } + + private: + int delete_count_; + WeakTestPtr next_; +}; + +} // namespace + +TEST(WeakPtr, Null) { + WeakTestPtr ptr1; + EXPECT_FALSE(ptr1); + + WeakTestPtr ptr2; + EXPECT_TRUE(ptr1 == ptr2); + EXPECT_FALSE(ptr1 != ptr2); + + WeakTestPtr ptr3(ptr1); + EXPECT_TRUE(ptr1 == ptr3); + EXPECT_FALSE(ptr1 != ptr3); + + WeakTestPtr ptr4 = ptr1; + EXPECT_TRUE(ptr1 == ptr4); + EXPECT_FALSE(ptr1 != ptr4); +} + +TEST(WeakPtr, NonNull) { + PseudoDeletable thing; + EXPECT_EQ(0, thing.delete_count()); + { + UniqueTestPtr unique(&thing); + WeakTestPtr ptr1(std::move(unique)); + EXPECT_TRUE(ptr1); + EXPECT_EQ(&thing, ptr1.Get()); + + WeakTestPtr ptr2; + EXPECT_FALSE(ptr1 == ptr2); + EXPECT_TRUE(ptr1 != ptr2); + { + WeakTestPtr ptr3(ptr1); + EXPECT_TRUE(ptr1 == ptr3); + EXPECT_FALSE(ptr1 != ptr3); + EXPECT_EQ(&thing, ptr3.Get()); + { + WeakTestPtr ptr4 = ptr1; + EXPECT_TRUE(ptr1 == ptr4); + EXPECT_FALSE(ptr1 != ptr4); + EXPECT_EQ(&thing, ptr4.Get()); + } + } + EXPECT_EQ(0, thing.delete_count()); + } + EXPECT_EQ(1, thing.delete_count()); +} + +TEST(WeakPtr, ResetNull) { + PseudoDeletable thing; + { + UniqueTestPtr unique(&thing); + WeakTestPtr ptr1(std::move(unique)); + WeakTestPtr ptr2 = ptr1; + ptr1.Reset(); + EXPECT_FALSE(ptr1); + EXPECT_EQ(nullptr, ptr1.Get()); + EXPECT_TRUE(ptr2); + EXPECT_EQ(&thing, ptr2.Get()); + EXPECT_FALSE(ptr1 == ptr2); + EXPECT_TRUE(ptr1 != ptr2); + EXPECT_EQ(0, thing.delete_count()); + } + EXPECT_EQ(1, thing.delete_count()); +} + +TEST(WeakPtr, ResetNonNull) { + PseudoDeletable thing1; + PseudoDeletable thing2; + { + UniqueTestPtr unique1(&thing1); + WeakTestPtr ptr1(std::move(unique1)); + WeakTestPtr ptr2 = ptr1; + UniqueTestPtr unique2(&thing2); + ptr2.Reset(std::move(unique2)); + EXPECT_TRUE(ptr1); + EXPECT_EQ(&thing1, ptr1.Get()); + EXPECT_TRUE(ptr2); + EXPECT_EQ(&thing2, ptr2.Get()); + EXPECT_FALSE(ptr1 == ptr2); + EXPECT_TRUE(ptr1 != ptr2); + EXPECT_EQ(0, thing1.delete_count()); + EXPECT_EQ(0, thing2.delete_count()); + } + EXPECT_EQ(1, thing1.delete_count()); + EXPECT_EQ(1, thing2.delete_count()); +} + +TEST(WeakPtr, DeleteObject) { + PseudoDeletable thing; + { + UniqueTestPtr unique(&thing); + WeakTestPtr ptr1(std::move(unique)); + WeakTestPtr ptr2 = ptr1; + ptr1.DeleteObject(); + EXPECT_FALSE(ptr1); + EXPECT_EQ(nullptr, ptr1.Get()); + EXPECT_FALSE(ptr2); + EXPECT_EQ(nullptr, ptr2.Get()); + EXPECT_FALSE(ptr1 == ptr2); + EXPECT_TRUE(ptr1 != ptr2); + EXPECT_EQ(1, thing.delete_count()); + } + EXPECT_EQ(1, thing.delete_count()); +} + +TEST(WeakPtr, Cyclic) { + PseudoDeletable thing1; + PseudoDeletable thing2; + { + UniqueTestPtr unique1(&thing1); + UniqueTestPtr unique2(&thing2); + WeakTestPtr ptr1(std::move(unique1)); + WeakTestPtr ptr2(std::move(unique2)); + ptr1->SetNext(ptr2); + ptr2->SetNext(ptr1); + } + // Leaks without explicit clear. + EXPECT_EQ(0, thing1.delete_count()); + EXPECT_EQ(0, thing2.delete_count()); +} + +TEST(WeakPtr, CyclicDeleteObject) { + PseudoDeletable thing1; + PseudoDeletable thing2; + { + UniqueTestPtr unique1(&thing1); + UniqueTestPtr unique2(&thing2); + WeakTestPtr ptr1(std::move(unique1)); + WeakTestPtr ptr2(std::move(unique2)); + ptr1->SetNext(ptr2); + ptr2->SetNext(ptr1); + ptr1.DeleteObject(); + EXPECT_EQ(1, thing1.delete_count()); + EXPECT_EQ(0, thing2.delete_count()); + } + EXPECT_EQ(1, thing1.delete_count()); + EXPECT_EQ(1, thing2.delete_count()); +} + +} // namespace fxcrt diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d47564e13f0fe93b465a617f6a01052b595993f --- /dev/null +++ b/core/fxcrt/widestring.cpp @@ -0,0 +1,1082 @@ +// 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 "core/fxcrt/widestring.h" + +#include + +#include +#include +#include + +#include "core/fxcrt/cfx_utf8decoder.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/string_pool_template.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/stl_util.h" + +template class fxcrt::StringDataTemplate; +template class fxcrt::StringViewTemplate; +template class fxcrt::StringPoolTemplate; +template struct std::hash; + +#define FORCE_ANSI 0x10000 +#define FORCE_UNICODE 0x20000 +#define FORCE_INT64 0x40000 + +namespace { + +constexpr wchar_t kWideTrimChars[] = L"\x09\x0a\x0b\x0c\x0d\x20"; + +const wchar_t* FX_wcsstr(const wchar_t* haystack, + int haystack_len, + const wchar_t* needle, + int needle_len) { + if (needle_len > haystack_len || needle_len == 0) { + return nullptr; + } + const wchar_t* end_ptr = haystack + haystack_len - needle_len; + while (haystack <= end_ptr) { + int i = 0; + while (1) { + if (haystack[i] != needle[i]) { + break; + } + i++; + if (i == needle_len) { + return haystack; + } + } + haystack++; + } + return nullptr; +} + +Optional GuessSizeForVSWPrintf(const wchar_t* pFormat, + va_list argList) { + size_t nMaxLen = 0; + for (const wchar_t* pStr = pFormat; *pStr != 0; pStr++) { + if (*pStr != '%' || *(pStr = pStr + 1) == '%') { + ++nMaxLen; + continue; + } + int nItemLen = 0; + int nWidth = 0; + for (; *pStr != 0; pStr++) { + if (*pStr == '#') { + nMaxLen += 2; + } else if (*pStr == '*') { + nWidth = va_arg(argList, int); + } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') { + break; + } + } + if (nWidth == 0) { + nWidth = FXSYS_wtoi(pStr); + while (std::iswdigit(*pStr)) + ++pStr; + } + if (nWidth < 0 || nWidth > 128 * 1024) + return Optional(); + int nPrecision = 0; + if (*pStr == '.') { + pStr++; + if (*pStr == '*') { + nPrecision = va_arg(argList, int); + pStr++; + } else { + nPrecision = FXSYS_wtoi(pStr); + while (std::iswdigit(*pStr)) + ++pStr; + } + } + if (nPrecision < 0 || nPrecision > 128 * 1024) + return Optional(); + int nModifier = 0; + if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') { + pStr += 3; + nModifier = FORCE_INT64; + } else { + switch (*pStr) { + case 'h': + nModifier = FORCE_ANSI; + pStr++; + break; + case 'l': + nModifier = FORCE_UNICODE; + pStr++; + break; + case 'F': + case 'N': + case 'L': + pStr++; + break; + } + } + switch (*pStr | nModifier) { + case 'c': + case 'C': + nItemLen = 2; + va_arg(argList, int); + break; + case 'c' | FORCE_ANSI: + case 'C' | FORCE_ANSI: + nItemLen = 2; + va_arg(argList, int); + break; + case 'c' | FORCE_UNICODE: + case 'C' | FORCE_UNICODE: + nItemLen = 2; + va_arg(argList, int); + break; + case 's': { + const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*); + if (pstrNextArg) { + nItemLen = wcslen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + case 'S': { + const char* pstrNextArg = va_arg(argList, const char*); + if (pstrNextArg) { + nItemLen = strlen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + case 's' | FORCE_ANSI: + case 'S' | FORCE_ANSI: { + const char* pstrNextArg = va_arg(argList, const char*); + if (pstrNextArg) { + nItemLen = strlen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + case 's' | FORCE_UNICODE: + case 'S' | FORCE_UNICODE: { + const wchar_t* pstrNextArg = va_arg(argList, wchar_t*); + if (pstrNextArg) { + nItemLen = wcslen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + } + if (nItemLen != 0) { + if (nPrecision != 0 && nItemLen > nPrecision) { + nItemLen = nPrecision; + } + if (nItemLen < nWidth) { + nItemLen = nWidth; + } + } else { + switch (*pStr) { + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': + case 'o': + if (nModifier & FORCE_INT64) { + va_arg(argList, int64_t); + } else { + va_arg(argList, int); + } + nItemLen = 32; + if (nItemLen < nWidth + nPrecision) { + nItemLen = nWidth + nPrecision; + } + break; + case 'a': + case 'A': + case 'e': + case 'E': + case 'g': + case 'G': + va_arg(argList, double); + nItemLen = 128; + if (nItemLen < nWidth + nPrecision) { + nItemLen = nWidth + nPrecision; + } + break; + case 'f': + if (nWidth + nPrecision > 100) { + nItemLen = nPrecision + nWidth + 128; + } else { + double f; + char pszTemp[256]; + f = va_arg(argList, double); + FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, + nPrecision + 6, f); + nItemLen = strlen(pszTemp); + } + break; + case 'p': + va_arg(argList, void*); + nItemLen = 32; + if (nItemLen < nWidth + nPrecision) { + nItemLen = nWidth + nPrecision; + } + break; + case 'n': + va_arg(argList, int*); + break; + } + } + nMaxLen += nItemLen; + } + nMaxLen += 32; // Fudge factor. + return Optional(nMaxLen); +} + +// Returns string unless we ran out of space. +Optional TryVSWPrintf(size_t size, + const wchar_t* pFormat, + va_list argList) { + WideString str; + wchar_t* buffer = str.GetBuffer(size); + + // In the following two calls, there's always space in the buffer for + // a terminating NUL that's not included in nMaxLen. + // For vswprintf(), MSAN won't untaint the buffer on a truncated write's + // -1 return code even though the buffer is written. Probably just as well + // not to trust the vendor's implementation to write anything anyways. + // See https://crbug.com/705912. + memset(buffer, 0, (size + 1) * sizeof(wchar_t)); + int ret = vswprintf(buffer, size + 1, pFormat, argList); + + bool bSufficientBuffer = ret >= 0 || buffer[size - 1] == 0; + if (!bSufficientBuffer) + return {}; + + str.ReleaseBuffer(str.GetStringLength()); + return {str}; +} + +#ifndef NDEBUG +bool IsValidWideCodePage(uint16_t codepage) { + switch (codepage) { + case FX_CODEPAGE_DefANSI: + case FX_CODEPAGE_ShiftJIS: + case FX_CODEPAGE_ChineseSimplified: + case FX_CODEPAGE_Hangul: + case FX_CODEPAGE_ChineseTraditional: + return true; + default: + return false; + } +} +#endif + +WideString GetWideString(uint16_t codepage, const ByteStringView& bstr) { +#ifndef NDEBUG + ASSERT(IsValidWideCodePage(codepage)); +#endif + + int src_len = bstr.GetLength(); + int dest_len = FXSYS_MultiByteToWideChar( + codepage, 0, bstr.unterminated_c_str(), src_len, nullptr, 0); + if (!dest_len) + return WideString(); + + WideString wstr; + wchar_t* dest_buf = wstr.GetBuffer(dest_len); + FXSYS_MultiByteToWideChar(codepage, 0, bstr.unterminated_c_str(), src_len, + dest_buf, dest_len); + wstr.ReleaseBuffer(dest_len); + return wstr; +} + +} // namespace + +namespace fxcrt { + +static_assert(sizeof(WideString) <= sizeof(wchar_t*), + "Strings must not require more space than pointers"); + +// static +WideString WideString::FormatV(const wchar_t* format, va_list argList) { + va_list argListCopy; + va_copy(argListCopy, argList); + int maxLen = vswprintf(nullptr, 0, format, argListCopy); + va_end(argListCopy); + + if (maxLen <= 0) { + va_copy(argListCopy, argList); + auto guess = GuessSizeForVSWPrintf(format, argListCopy); + va_end(argListCopy); + + if (!guess.has_value()) + return L""; + maxLen = pdfium::base::checked_cast(guess.value()); + } + + while (maxLen < 32 * 1024) { + va_copy(argListCopy, argList); + Optional ret = + TryVSWPrintf(static_cast(maxLen), format, argListCopy); + va_end(argListCopy); + + if (ret) + return *ret; + maxLen *= 2; + } + return L""; +} + +// static +WideString WideString::Format(const wchar_t* pFormat, ...) { + va_list argList; + va_start(argList, pFormat); + WideString ret = FormatV(pFormat, argList); + va_end(argList); + return ret; +} + +WideString::WideString() {} + +WideString::WideString(const WideString& other) : m_pData(other.m_pData) {} + +WideString::WideString(WideString&& other) noexcept { + m_pData.Swap(other.m_pData); +} + +WideString::WideString(const wchar_t* pStr, size_t nLen) { + if (nLen) + m_pData.Reset(StringData::Create(pStr, nLen)); +} + +WideString::WideString(wchar_t ch) { + m_pData.Reset(StringData::Create(1)); + m_pData->m_String[0] = ch; +} + +WideString::WideString(const wchar_t* ptr) + : WideString(ptr, ptr ? wcslen(ptr) : 0) {} + +WideString::WideString(const WideStringView& stringSrc) { + if (!stringSrc.IsEmpty()) { + m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), + stringSrc.GetLength())); + } +} + +WideString::WideString(const WideStringView& str1, const WideStringView& str2) { + FX_SAFE_SIZE_T nSafeLen = str1.GetLength(); + nSafeLen += str2.GetLength(); + + size_t nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); + m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), + str2.GetLength()); +} + +WideString::WideString(const std::initializer_list& list) { + FX_SAFE_SIZE_T nSafeLen = 0; + for (const auto& item : list) + nSafeLen += item.GetLength(); + + size_t nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + + size_t nOffset = 0; + for (const auto& item : list) { + m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), + item.GetLength()); + nOffset += item.GetLength(); + } +} + +WideString::~WideString() {} + +const WideString& WideString::operator=(const wchar_t* pStr) { + if (!pStr || !pStr[0]) + clear(); + else + AssignCopy(pStr, wcslen(pStr)); + + return *this; +} + +const WideString& WideString::operator=(const WideStringView& stringSrc) { + if (stringSrc.IsEmpty()) + clear(); + else + AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength()); + + return *this; +} + +const WideString& WideString::operator=(const WideString& stringSrc) { + if (m_pData != stringSrc.m_pData) + m_pData = stringSrc.m_pData; + + return *this; +} + +const WideString& WideString::operator+=(const wchar_t* pStr) { + if (pStr) + Concat(pStr, wcslen(pStr)); + + return *this; +} + +const WideString& WideString::operator+=(wchar_t ch) { + Concat(&ch, 1); + return *this; +} + +const WideString& WideString::operator+=(const WideString& str) { + if (str.m_pData) + Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); + + return *this; +} + +const WideString& WideString::operator+=(const WideStringView& str) { + if (!str.IsEmpty()) + Concat(str.unterminated_c_str(), str.GetLength()); + + return *this; +} + +bool WideString::operator==(const wchar_t* ptr) const { + if (!m_pData) + return !ptr || !ptr[0]; + + if (!ptr) + return m_pData->m_nDataLength == 0; + + return wcslen(ptr) == m_pData->m_nDataLength && + wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; +} + +bool WideString::operator==(const WideStringView& str) const { + if (!m_pData) + return str.IsEmpty(); + + return m_pData->m_nDataLength == str.GetLength() && + wmemcmp(m_pData->m_String, str.unterminated_c_str(), + str.GetLength()) == 0; +} + +bool WideString::operator==(const WideString& other) const { + if (m_pData == other.m_pData) + return true; + + if (IsEmpty()) + return other.IsEmpty(); + + if (other.IsEmpty()) + return false; + + return other.m_pData->m_nDataLength == m_pData->m_nDataLength && + wmemcmp(other.m_pData->m_String, m_pData->m_String, + m_pData->m_nDataLength) == 0; +} + +bool WideString::operator<(const wchar_t* ptr) const { + return Compare(ptr) < 0; +} + +bool WideString::operator<(const WideStringView& str) const { + if (!m_pData && !str.unterminated_c_str()) + return false; + if (c_str() == str.unterminated_c_str()) + return false; + + size_t len = GetLength(); + size_t other_len = str.GetLength(); + int result = + wmemcmp(c_str(), str.unterminated_c_str(), std::min(len, other_len)); + return result < 0 || (result == 0 && len < other_len); +} + +bool WideString::operator<(const WideString& other) const { + return Compare(other) < 0; +} + +void WideString::AssignCopy(const wchar_t* pSrcData, size_t nSrcLen) { + AllocBeforeWrite(nSrcLen); + m_pData->CopyContents(pSrcData, nSrcLen); + m_pData->m_nDataLength = nSrcLen; +} + +void WideString::ReallocBeforeWrite(size_t nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + RetainPtr pNewData(StringData::Create(nNewLength)); + if (m_pData) { + size_t nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); + pNewData->CopyContents(m_pData->m_String, nCopyLength); + pNewData->m_nDataLength = nCopyLength; + } else { + pNewData->m_nDataLength = 0; + } + pNewData->m_String[pNewData->m_nDataLength] = 0; + m_pData.Swap(pNewData); +} + +void WideString::AllocBeforeWrite(size_t nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + m_pData.Reset(StringData::Create(nNewLength)); +} + +void WideString::ReleaseBuffer(size_t nNewLength) { + if (!m_pData) + return; + + nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); + if (nNewLength == 0) { + clear(); + return; + } + + ASSERT(m_pData->m_nRefs == 1); + m_pData->m_nDataLength = nNewLength; + m_pData->m_String[nNewLength] = 0; + if (m_pData->m_nAllocLength - nNewLength >= 32) { + // Over arbitrary threshold, so pay the price to relocate. Force copy to + // always occur by holding a second reference to the string. + WideString preserve(*this); + ReallocBeforeWrite(nNewLength); + } +} + +void WideString::Reserve(size_t len) { + GetBuffer(len); +} + +wchar_t* WideString::GetBuffer(size_t nMinBufLength) { + if (!m_pData) { + if (nMinBufLength == 0) + return nullptr; + + m_pData.Reset(StringData::Create(nMinBufLength)); + m_pData->m_nDataLength = 0; + m_pData->m_String[0] = 0; + return m_pData->m_String; + } + + if (m_pData->CanOperateInPlace(nMinBufLength)) + return m_pData->m_String; + + nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); + if (nMinBufLength == 0) + return nullptr; + + RetainPtr pNewData(StringData::Create(nMinBufLength)); + pNewData->CopyContents(*m_pData); + pNewData->m_nDataLength = m_pData->m_nDataLength; + m_pData.Swap(pNewData); + return m_pData->m_String; +} + +size_t WideString::Delete(size_t index, size_t count) { + if (!m_pData) + return 0; + + size_t old_length = m_pData->m_nDataLength; + if (count == 0 || + index != pdfium::clamp(index, static_cast(0), old_length)) + return old_length; + + size_t removal_length = index + count; + if (removal_length > old_length) + return old_length; + + ReallocBeforeWrite(old_length); + size_t chars_to_copy = old_length - removal_length + 1; + wmemmove(m_pData->m_String + index, m_pData->m_String + removal_length, + chars_to_copy); + m_pData->m_nDataLength = old_length - count; + return m_pData->m_nDataLength; +} + +void WideString::Concat(const wchar_t* pSrcData, size_t nSrcLen) { + if (!pSrcData || nSrcLen == 0) + return; + + if (!m_pData) { + m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); + return; + } + + if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { + m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData->m_nDataLength += nSrcLen; + return; + } + + RetainPtr pNewData( + StringData::Create(m_pData->m_nDataLength + nSrcLen)); + pNewData->CopyContents(*m_pData); + pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData.Swap(pNewData); +} + +ByteString WideString::UTF8Encode() const { + return FX_UTF8Encode(AsStringView()); +} + +ByteString WideString::UTF16LE_Encode() const { + if (!m_pData) { + return ByteString("\0\0", 2); + } + int len = m_pData->m_nDataLength; + ByteString result; + char* buffer = result.GetBuffer(len * 2 + 2); + for (int i = 0; i < len; i++) { + buffer[i * 2] = m_pData->m_String[i] & 0xff; + buffer[i * 2 + 1] = m_pData->m_String[i] >> 8; + } + buffer[len * 2] = 0; + buffer[len * 2 + 1] = 0; + result.ReleaseBuffer(len * 2 + 2); + return result; +} + +WideString WideString::Mid(size_t first, size_t count) const { + if (!m_pData) + return WideString(); + + if (!IsValidIndex(first)) + return WideString(); + + if (count == 0 || !IsValidLength(count)) + return WideString(); + + if (!IsValidIndex(first + count - 1)) + return WideString(); + + if (first == 0 && count == GetLength()) + return *this; + + WideString dest; + AllocCopy(dest, count, first); + return dest; +} + +WideString WideString::Left(size_t count) const { + if (count == 0 || !IsValidLength(count)) + return WideString(); + return Mid(0, count); +} + +WideString WideString::Right(size_t count) const { + if (count == 0 || !IsValidLength(count)) + return WideString(); + return Mid(GetLength() - count, count); +} + +void WideString::AllocCopy(WideString& dest, + size_t nCopyLen, + size_t nCopyIndex) const { + if (nCopyLen == 0) + return; + + RetainPtr pNewData( + StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); + dest.m_pData.Swap(pNewData); +} + +size_t WideString::Insert(size_t location, wchar_t ch) { + const size_t cur_length = m_pData ? m_pData->m_nDataLength : 0; + if (!IsValidLength(location)) + return cur_length; + + const size_t new_length = cur_length + 1; + ReallocBeforeWrite(new_length); + wmemmove(m_pData->m_String + location + 1, m_pData->m_String + location, + new_length - location); + m_pData->m_String[location] = ch; + m_pData->m_nDataLength = new_length; + return new_length; +} + +Optional WideString::Find(wchar_t ch, size_t start) const { + if (!m_pData) + return Optional(); + + if (!IsValidIndex(start)) + return Optional(); + + const wchar_t* pStr = + wmemchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start); + return pStr ? Optional(static_cast(pStr - m_pData->m_String)) + : Optional(); +} + +Optional WideString::Find(const WideStringView& subStr, + size_t start) const { + if (!m_pData) + return Optional(); + + if (!IsValidIndex(start)) + return Optional(); + + const wchar_t* pStr = + FX_wcsstr(m_pData->m_String + start, m_pData->m_nDataLength - start, + subStr.unterminated_c_str(), subStr.GetLength()); + return pStr ? Optional(static_cast(pStr - m_pData->m_String)) + : Optional(); +} + +void WideString::MakeLower() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_wcslwr(m_pData->m_String); +} + +void WideString::MakeUpper() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_wcsupr(m_pData->m_String); +} + +size_t WideString::Remove(wchar_t chRemove) { + if (!m_pData || m_pData->m_nDataLength < 1) + return 0; + + wchar_t* pstrSource = m_pData->m_String; + wchar_t* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + while (pstrSource < pstrEnd) { + if (*pstrSource == chRemove) + break; + pstrSource++; + } + if (pstrSource == pstrEnd) + return 0; + + ptrdiff_t copied = pstrSource - m_pData->m_String; + ReallocBeforeWrite(m_pData->m_nDataLength); + pstrSource = m_pData->m_String + copied; + pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + + wchar_t* pstrDest = pstrSource; + while (pstrSource < pstrEnd) { + if (*pstrSource != chRemove) { + *pstrDest = *pstrSource; + pstrDest++; + } + pstrSource++; + } + + *pstrDest = 0; + size_t count = static_cast(pstrSource - pstrDest); + m_pData->m_nDataLength -= count; + return count; +} + +size_t WideString::Replace(const WideStringView& pOld, + const WideStringView& pNew) { + if (!m_pData || pOld.IsEmpty()) + return 0; + + size_t nSourceLen = pOld.GetLength(); + size_t nReplacementLen = pNew.GetLength(); + size_t count = 0; + const wchar_t* pStart = m_pData->m_String; + wchar_t* pEnd = m_pData->m_String + m_pData->m_nDataLength; + while (1) { + const wchar_t* pTarget = + FX_wcsstr(pStart, static_cast(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + if (!pTarget) + break; + + count++; + pStart = pTarget + nSourceLen; + } + if (count == 0) + return 0; + + size_t nNewLength = + m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * count; + + if (nNewLength == 0) { + clear(); + return count; + } + + RetainPtr pNewData(StringData::Create(nNewLength)); + pStart = m_pData->m_String; + wchar_t* pDest = pNewData->m_String; + for (size_t i = 0; i < count; i++) { + const wchar_t* pTarget = + FX_wcsstr(pStart, static_cast(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + wmemcpy(pDest, pStart, pTarget - pStart); + pDest += pTarget - pStart; + wmemcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); + pDest += pNew.GetLength(); + pStart = pTarget + nSourceLen; + } + wmemcpy(pDest, pStart, pEnd - pStart); + m_pData.Swap(pNewData); + return count; +} + +// static +WideString WideString::FromLocal(const ByteStringView& str) { + return FromCodePage(str, 0); +} + +// static +WideString WideString::FromCodePage(const ByteStringView& str, + uint16_t codepage) { + return GetWideString(codepage, str); +} + +// static +WideString WideString::FromUTF8(const ByteStringView& str) { + if (str.IsEmpty()) + return WideString(); + + CFX_UTF8Decoder decoder; + for (size_t i = 0; i < str.GetLength(); i++) + decoder.Input(str[i]); + + return WideString(decoder.GetResult()); +} + +// static +WideString WideString::FromUTF16LE(const unsigned short* wstr, size_t wlen) { + if (!wstr || wlen == 0) { + return WideString(); + } + + WideString result; + wchar_t* buf = result.GetBuffer(wlen); + for (size_t i = 0; i < wlen; i++) { + buf[i] = wstr[i]; + } + result.ReleaseBuffer(wlen); + return result; +} + +void WideString::SetAt(size_t index, wchar_t c) { + ASSERT(IsValidIndex(index)); + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[index] = c; +} + +int WideString::Compare(const wchar_t* lpsz) const { + if (m_pData) + return lpsz ? wcscmp(m_pData->m_String, lpsz) : 1; + return (!lpsz || lpsz[0] == 0) ? 0 : -1; +} + +int WideString::Compare(const WideString& str) const { + if (!m_pData) + return str.m_pData ? -1 : 0; + if (!str.m_pData) + return 1; + + size_t this_len = m_pData->m_nDataLength; + size_t that_len = str.m_pData->m_nDataLength; + size_t min_len = std::min(this_len, that_len); + int result = wmemcmp(m_pData->m_String, str.m_pData->m_String, min_len); + if (result != 0) + return result; + if (this_len == that_len) + return 0; + return this_len < that_len; +} + +int WideString::CompareNoCase(const wchar_t* lpsz) const { + if (m_pData) + return lpsz ? FXSYS_wcsicmp(m_pData->m_String, lpsz) : 1; + return (!lpsz || lpsz[0] == 0) ? 0 : -1; +} + +size_t WideString::WStringLength(const unsigned short* str) { + size_t len = 0; + if (str) + while (str[len]) + len++; + return len; +} + +void WideString::Trim() { + TrimRight(kWideTrimChars); + TrimLeft(kWideTrimChars); +} + +void WideString::Trim(wchar_t target) { + wchar_t str[2] = {target, 0}; + TrimRight(str); + TrimLeft(str); +} + +void WideString::Trim(const WideStringView& targets) { + TrimRight(targets); + TrimLeft(targets); +} + +void WideString::TrimLeft() { + TrimLeft(kWideTrimChars); +} + +void WideString::TrimLeft(wchar_t target) { + wchar_t str[2] = {target, 0}; + TrimLeft(str); +} + +void WideString::TrimLeft(const WideStringView& targets) { + if (!m_pData || targets.IsEmpty()) + return; + + size_t len = GetLength(); + if (len == 0) + return; + + size_t pos = 0; + while (pos < len) { + size_t i = 0; + while (i < targets.GetLength() && + targets.CharAt(i) != m_pData->m_String[pos]) { + i++; + } + if (i == targets.GetLength()) + break; + pos++; + } + if (!pos) + return; + + ReallocBeforeWrite(len); + size_t nDataLength = len - pos; + memmove(m_pData->m_String, m_pData->m_String + pos, + (nDataLength + 1) * sizeof(wchar_t)); + m_pData->m_nDataLength = nDataLength; +} + +void WideString::TrimRight() { + TrimRight(kWideTrimChars); +} + +void WideString::TrimRight(wchar_t target) { + wchar_t str[2] = {target, 0}; + TrimRight(str); +} + +void WideString::TrimRight(const WideStringView& targets) { + if (IsEmpty() || targets.IsEmpty()) + return; + + size_t pos = GetLength(); + while (pos && targets.Contains(m_pData->m_String[pos - 1])) + pos--; + + if (pos < m_pData->m_nDataLength) { + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[pos] = 0; + m_pData->m_nDataLength = pos; + } +} + +float FX_wtof(const wchar_t* str, int len) { + if (len == 0) { + return 0.0; + } + int cc = 0; + bool bNegative = false; + if (str[0] == '+') { + cc++; + } else if (str[0] == '-') { + bNegative = true; + cc++; + } + int integer = 0; + while (cc < len) { + if (str[cc] == '.') { + break; + } + integer = integer * 10 + FXSYS_DecimalCharToInt(str[cc]); + cc++; + } + float fraction = 0; + if (str[cc] == '.') { + cc++; + float scale = 0.1f; + while (cc < len) { + fraction += scale * FXSYS_DecimalCharToInt(str[cc]); + scale *= 0.1f; + cc++; + } + } + fraction += static_cast(integer); + return bNegative ? -fraction : fraction; +} + +int WideString::GetInteger() const { + return m_pData ? FXSYS_wtoi(m_pData->m_String) : 0; +} + +float WideString::GetFloat() const { + return m_pData ? FX_wtof(m_pData->m_String, m_pData->m_nDataLength) : 0.0f; +} + +std::wostream& operator<<(std::wostream& os, const WideString& str) { + return os.write(str.c_str(), str.GetLength()); +} + +std::ostream& operator<<(std::ostream& os, const WideString& str) { + os << str.UTF8Encode(); + return os; +} + +std::wostream& operator<<(std::wostream& os, const WideStringView& str) { + return os.write(str.unterminated_c_str(), str.GetLength()); +} + +std::ostream& operator<<(std::ostream& os, const WideStringView& str) { + os << FX_UTF8Encode(str); + return os; +} + +} // namespace fxcrt diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h new file mode 100644 index 0000000000000000000000000000000000000000..30a423d9aa5e7704df146cc1c4bac9d268130790 --- /dev/null +++ b/core/fxcrt/widestring.h @@ -0,0 +1,287 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_WIDESTRING_H_ +#define CORE_FXCRT_WIDESTRING_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/string_data_template.h" +#include "core/fxcrt/string_view_template.h" +#include "third_party/base/optional.h" + + +namespace fxcrt { + +class ByteString; +class StringPool_WideString_Test; +class WideString_ConcatInPlace_Test; + +// A mutable string with shared buffers using copy-on-write semantics that +// avoids the cost of std::string's iterator stability guarantees. +class WideString { + public: + using CharType = wchar_t; + using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator; + + static WideString Format(const wchar_t* lpszFormat, ...) WARN_UNUSED_RESULT; + static WideString FormatV(const wchar_t* lpszFormat, + va_list argList) WARN_UNUSED_RESULT; + + WideString(); + WideString(const WideString& other); + WideString(WideString&& other) noexcept; + + // Deliberately implicit to avoid calling on every string literal. + // NOLINTNEXTLINE(runtime/explicit) + WideString(wchar_t ch); + // NOLINTNEXTLINE(runtime/explicit) + WideString(const wchar_t* ptr); + + // No implicit conversions from byte strings. + // NOLINTNEXTLINE(runtime/explicit) + WideString(char) = delete; + + WideString(const wchar_t* ptr, size_t len); + + explicit WideString(const WideStringView& str); + WideString(const WideStringView& str1, const WideStringView& str2); + WideString(const std::initializer_list& list); + + ~WideString(); + + static WideString FromLocal(const ByteStringView& str) WARN_UNUSED_RESULT; + static WideString FromCodePage(const ByteStringView& str, + uint16_t codepage) WARN_UNUSED_RESULT; + + static WideString FromUTF8(const ByteStringView& str) WARN_UNUSED_RESULT; + static WideString FromUTF16LE(const unsigned short* str, + size_t len) WARN_UNUSED_RESULT; + + static size_t WStringLength(const unsigned short* str) WARN_UNUSED_RESULT; + + // Explicit conversion to C-style wide string. + // Note: Any subsequent modification of |this| will invalidate the result. + const wchar_t* c_str() const { return m_pData ? m_pData->m_String : L""; } + + // Explicit conversion to WideStringView. + // Note: Any subsequent modification of |this| will invalidate the result. + WideStringView AsStringView() const { + return WideStringView(c_str(), GetLength()); + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } + const_iterator end() const { + return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + void clear() { m_pData.Reset(); } + + size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } + size_t GetStringLength() const { + return m_pData ? wcslen(m_pData->m_String) : 0; + } + bool IsEmpty() const { return !GetLength(); } + bool IsValidIndex(size_t index) const { return index < GetLength(); } + bool IsValidLength(size_t length) const { return length <= GetLength(); } + + const WideString& operator=(const wchar_t* str); + const WideString& operator=(const WideString& stringSrc); + const WideString& operator=(const WideStringView& stringSrc); + + const WideString& operator+=(const wchar_t* str); + const WideString& operator+=(wchar_t ch); + const WideString& operator+=(const WideString& str); + const WideString& operator+=(const WideStringView& str); + + bool operator==(const wchar_t* ptr) const; + bool operator==(const WideStringView& str) const; + bool operator==(const WideString& other) const; + + bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } + bool operator!=(const WideStringView& str) const { return !(*this == str); } + bool operator!=(const WideString& other) const { return !(*this == other); } + + bool operator<(const wchar_t* ptr) const; + bool operator<(const WideStringView& str) const; + bool operator<(const WideString& other) const; + + CharType operator[](const size_t index) const { + ASSERT(IsValidIndex(index)); + return m_pData ? m_pData->m_String[index] : 0; + } + + CharType First() const { return GetLength() ? (*this)[0] : 0; } + CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } + + void SetAt(size_t index, wchar_t c); + + int Compare(const wchar_t* str) const; + int Compare(const WideString& str) const; + int CompareNoCase(const wchar_t* str) const; + + WideString Mid(size_t first, size_t count) const; + WideString Left(size_t count) const; + WideString Right(size_t count) const; + + size_t Insert(size_t index, wchar_t ch); + size_t InsertAtFront(wchar_t ch) { return Insert(0, ch); } + size_t InsertAtBack(wchar_t ch) { return Insert(GetLength(), ch); } + size_t Delete(size_t index, size_t count = 1); + + void MakeLower(); + void MakeUpper(); + + void Trim(); + void Trim(wchar_t target); + void Trim(const WideStringView& targets); + + void TrimLeft(); + void TrimLeft(wchar_t target); + void TrimLeft(const WideStringView& targets); + + void TrimRight(); + void TrimRight(wchar_t target); + void TrimRight(const WideStringView& targets); + + void Reserve(size_t len); + wchar_t* GetBuffer(size_t len); + void ReleaseBuffer(size_t len); + + int GetInteger() const; + float GetFloat() const; + + Optional Find(const WideStringView& pSub, size_t start = 0) const; + Optional Find(wchar_t ch, size_t start = 0) const; + + bool Contains(const WideStringView& lpszSub, size_t start = 0) const { + return Find(lpszSub, start).has_value(); + } + + bool Contains(char ch, size_t start = 0) const { + return Find(ch, start).has_value(); + } + + size_t Replace(const WideStringView& pOld, const WideStringView& pNew); + size_t Remove(wchar_t ch); + + ByteString UTF8Encode() const; + + // This method will add \0\0 to the end of the string to represent the + // wide string terminator. These values are in the string, not just the data, + // so GetLength() will include them. + ByteString UTF16LE_Encode() const; + + protected: + using StringData = StringDataTemplate; + + void ReallocBeforeWrite(size_t nLen); + void AllocBeforeWrite(size_t nLen); + void AllocCopy(WideString& dest, size_t nCopyLen, size_t nCopyIndex) const; + void AssignCopy(const wchar_t* pSrcData, size_t nSrcLen); + void Concat(const wchar_t* lpszSrcData, size_t nSrcLen); + + RetainPtr m_pData; + + friend WideString_ConcatInPlace_Test; + friend StringPool_WideString_Test; +}; + +inline WideString operator+(const WideStringView& str1, + const WideStringView& str2) { + return WideString(str1, str2); +} +inline WideString operator+(const WideStringView& str1, const wchar_t* str2) { + return WideString(str1, str2); +} +inline WideString operator+(const wchar_t* str1, const WideStringView& str2) { + return WideString(str1, str2); +} +inline WideString operator+(const WideStringView& str1, wchar_t ch) { + return WideString(str1, WideStringView(ch)); +} +inline WideString operator+(wchar_t ch, const WideStringView& str2) { + return WideString(ch, str2); +} +inline WideString operator+(const WideString& str1, const WideString& str2) { + return WideString(str1.AsStringView(), str2.AsStringView()); +} +inline WideString operator+(const WideString& str1, wchar_t ch) { + return WideString(str1.AsStringView(), WideStringView(ch)); +} +inline WideString operator+(wchar_t ch, const WideString& str2) { + return WideString(ch, str2.AsStringView()); +} +inline WideString operator+(const WideString& str1, const wchar_t* str2) { + return WideString(str1.AsStringView(), str2); +} +inline WideString operator+(const wchar_t* str1, const WideString& str2) { + return WideString(str1, str2.AsStringView()); +} +inline WideString operator+(const WideString& str1, + const WideStringView& str2) { + return WideString(str1.AsStringView(), str2); +} +inline WideString operator+(const WideStringView& str1, + const WideString& str2) { + return WideString(str1, str2.AsStringView()); +} +inline bool operator==(const wchar_t* lhs, const WideString& rhs) { + return rhs == lhs; +} +inline bool operator==(const WideStringView& lhs, const WideString& rhs) { + return rhs == lhs; +} +inline bool operator!=(const wchar_t* lhs, const WideString& rhs) { + return rhs != lhs; +} +inline bool operator!=(const WideStringView& lhs, const WideString& rhs) { + return rhs != lhs; +} +inline bool operator<(const wchar_t* lhs, const WideString& rhs) { + return rhs.Compare(lhs) > 0; +} + +std::wostream& operator<<(std::wostream& os, const WideString& str); +std::ostream& operator<<(std::ostream& os, const WideString& str); +std::wostream& operator<<(std::wostream& os, const WideStringView& str); +std::ostream& operator<<(std::ostream& os, const WideStringView& str); + +} // namespace fxcrt + +using WideString = fxcrt::WideString; + +uint32_t FX_HashCode_GetW(const WideStringView& str, bool bIgnoreCase); + +namespace std { + +template <> +struct hash { + std::size_t operator()(const WideString& str) const { + return FX_HashCode_GetW(str.AsStringView(), false); + } +}; + +} // namespace std + +extern template struct std::hash; + +#endif // CORE_FXCRT_WIDESTRING_H_ diff --git a/core/fxcrt/widestring_unittest.cpp b/core/fxcrt/widestring_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fb9e8c8b41d2cb8bd636978eb3e6ebc1872ab34 --- /dev/null +++ b/core/fxcrt/widestring_unittest.cpp @@ -0,0 +1,1679 @@ +// 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. + +#include "core/fxcrt/widestring.h" + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace fxcrt { + +TEST(WideString, ElementAccess) { + const WideString abc(L"abc"); + EXPECT_EQ(L'a', abc[0]); + EXPECT_EQ(L'b', abc[1]); + EXPECT_EQ(L'c', abc[2]); +#ifndef NDEBUG + EXPECT_DEATH({ abc[4]; }, ".*"); +#endif + + WideString mutable_abc = abc; + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ(L'a', mutable_abc[0]); + EXPECT_EQ(L'b', mutable_abc[1]); + EXPECT_EQ(L'c', mutable_abc[2]); + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ(L"abc", abc); + + const wchar_t* c_str = abc.c_str(); + mutable_abc.SetAt(0, L'd'); + EXPECT_EQ(c_str, abc.c_str()); + EXPECT_NE(c_str, mutable_abc.c_str()); + EXPECT_EQ(L"abc", abc); + EXPECT_EQ(L"dbc", mutable_abc); + + mutable_abc.SetAt(1, L'e'); + EXPECT_EQ(L"abc", abc); + EXPECT_EQ(L"dec", mutable_abc); + + mutable_abc.SetAt(2, L'f'); + EXPECT_EQ(L"abc", abc); + EXPECT_EQ(L"def", mutable_abc); +#ifndef NDEBUG + EXPECT_DEATH({ mutable_abc.SetAt(3, L'g'); }, ".*"); + EXPECT_EQ(L"abc", abc); +#endif +} + +TEST(WideString, OperatorLT) { + WideString empty; + WideString a(L"a"); + WideString abc(L"\x0110qq"); // Comes before despite endianness. + WideString def(L"\x1001qq"); // Comes after despite endianness. + WideStringView v_empty; + WideStringView v_a(L"a"); + WideStringView v_abc(L"\x0110qq"); + WideStringView v_def(L"\x1001qq"); + const wchar_t* const c_null = nullptr; + const wchar_t* const c_empty = L""; + const wchar_t* const c_a = L"a"; + const wchar_t* const c_abc = L"\x0110qq"; + const wchar_t* const c_def = L"\x1001qq"; + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + EXPECT_FALSE(c_null < empty); + EXPECT_FALSE(c_empty < empty); + EXPECT_FALSE(c_a < a); + EXPECT_FALSE(c_abc < abc); + EXPECT_FALSE(c_def < def); + EXPECT_FALSE(empty < c_null); + EXPECT_FALSE(empty < c_empty); + EXPECT_FALSE(a < c_a); + EXPECT_FALSE(abc < c_abc); + EXPECT_FALSE(def < c_def); + EXPECT_FALSE(empty < v_empty); + EXPECT_FALSE(a < v_a); + EXPECT_FALSE(abc < v_abc); + EXPECT_FALSE(def < v_def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + EXPECT_TRUE(c_null < a); + EXPECT_TRUE(c_empty < a); + EXPECT_FALSE(c_a < empty); + EXPECT_TRUE(empty < c_a); + EXPECT_FALSE(a < c_null); + EXPECT_FALSE(a < c_empty); + EXPECT_TRUE(empty < v_a); + EXPECT_FALSE(a < v_empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + EXPECT_TRUE(c_null < abc); + EXPECT_TRUE(c_empty < abc); + EXPECT_FALSE(c_abc < empty); + EXPECT_TRUE(empty < c_abc); + EXPECT_FALSE(abc < c_null); + EXPECT_FALSE(abc < c_empty); + EXPECT_TRUE(empty < v_abc); + EXPECT_FALSE(abc < v_empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + EXPECT_TRUE(c_null < def); + EXPECT_TRUE(c_empty < def); + EXPECT_FALSE(c_def < empty); + EXPECT_TRUE(empty < c_def); + EXPECT_FALSE(def < c_null); + EXPECT_FALSE(def < c_empty); + EXPECT_TRUE(empty < v_def); + EXPECT_FALSE(def < v_empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + EXPECT_TRUE(c_a < abc); + EXPECT_FALSE(c_abc < a); + EXPECT_TRUE(a < c_abc); + EXPECT_FALSE(abc < c_a); + EXPECT_TRUE(a < v_abc); + EXPECT_FALSE(abc < v_a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + EXPECT_TRUE(c_a < def); + EXPECT_FALSE(c_def < a); + EXPECT_TRUE(a < c_def); + EXPECT_FALSE(def < c_a); + EXPECT_TRUE(a < v_def); + EXPECT_FALSE(def < v_a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); + EXPECT_TRUE(c_abc < def); + EXPECT_FALSE(c_def < abc); + EXPECT_TRUE(abc < c_def); + EXPECT_FALSE(def < c_abc); + EXPECT_TRUE(abc < v_def); + EXPECT_FALSE(def < v_abc); +} + +TEST(WideString, OperatorEQ) { + WideString null_string; + EXPECT_TRUE(null_string == null_string); + + WideString empty_string(L""); + EXPECT_TRUE(empty_string == empty_string); + EXPECT_TRUE(empty_string == null_string); + EXPECT_TRUE(null_string == empty_string); + + WideString deleted_string(L"hello"); + deleted_string.Delete(0, 5); + EXPECT_TRUE(deleted_string == deleted_string); + EXPECT_TRUE(deleted_string == null_string); + EXPECT_TRUE(deleted_string == empty_string); + EXPECT_TRUE(null_string == deleted_string); + EXPECT_TRUE(null_string == empty_string); + + WideString wide_string(L"hello"); + EXPECT_TRUE(wide_string == wide_string); + EXPECT_FALSE(wide_string == null_string); + EXPECT_FALSE(wide_string == empty_string); + EXPECT_FALSE(wide_string == deleted_string); + EXPECT_FALSE(null_string == wide_string); + EXPECT_FALSE(empty_string == wide_string); + EXPECT_FALSE(deleted_string == wide_string); + + WideString wide_string_same1(L"hello"); + EXPECT_TRUE(wide_string == wide_string_same1); + EXPECT_TRUE(wide_string_same1 == wide_string); + + WideString wide_string_same2(wide_string); + EXPECT_TRUE(wide_string == wide_string_same2); + EXPECT_TRUE(wide_string_same2 == wide_string); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_FALSE(wide_string == wide_string1); + EXPECT_FALSE(wide_string == wide_string2); + EXPECT_FALSE(wide_string == wide_string3); + EXPECT_FALSE(wide_string1 == wide_string); + EXPECT_FALSE(wide_string2 == wide_string); + EXPECT_FALSE(wide_string3 == wide_string); + + WideStringView null_string_c; + WideStringView empty_string_c(L""); + EXPECT_TRUE(null_string == null_string_c); + EXPECT_TRUE(null_string == empty_string_c); + EXPECT_TRUE(empty_string == null_string_c); + EXPECT_TRUE(empty_string == empty_string_c); + EXPECT_TRUE(deleted_string == null_string_c); + EXPECT_TRUE(deleted_string == empty_string_c); + EXPECT_TRUE(null_string_c == null_string); + EXPECT_TRUE(empty_string_c == null_string); + EXPECT_TRUE(null_string_c == empty_string); + EXPECT_TRUE(empty_string_c == empty_string); + EXPECT_TRUE(null_string_c == deleted_string); + EXPECT_TRUE(empty_string_c == deleted_string); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_TRUE(wide_string == wide_string_c_same1); + EXPECT_TRUE(wide_string_c_same1 == wide_string); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_FALSE(wide_string == wide_string_c1); + EXPECT_FALSE(wide_string == wide_string_c2); + EXPECT_FALSE(wide_string == wide_string_c3); + EXPECT_FALSE(wide_string_c1 == wide_string); + EXPECT_FALSE(wide_string_c2 == wide_string); + EXPECT_FALSE(wide_string_c3 == wide_string); + + const wchar_t* const c_null_string = nullptr; + const wchar_t* const c_empty_string = L""; + EXPECT_TRUE(null_string == c_null_string); + EXPECT_TRUE(null_string == c_empty_string); + EXPECT_TRUE(empty_string == c_null_string); + EXPECT_TRUE(empty_string == c_empty_string); + EXPECT_TRUE(deleted_string == c_null_string); + EXPECT_TRUE(deleted_string == c_empty_string); + EXPECT_TRUE(c_null_string == null_string); + EXPECT_TRUE(c_empty_string == null_string); + EXPECT_TRUE(c_null_string == empty_string); + EXPECT_TRUE(c_empty_string == empty_string); + EXPECT_TRUE(c_null_string == deleted_string); + EXPECT_TRUE(c_empty_string == deleted_string); + + const wchar_t* const c_string_same1 = L"hello"; + EXPECT_TRUE(wide_string == c_string_same1); + EXPECT_TRUE(c_string_same1 == wide_string); + + const wchar_t* const c_string1 = L"he"; + const wchar_t* const c_string2 = L"hellp"; + const wchar_t* const c_string3 = L"hellod"; + EXPECT_FALSE(wide_string == c_string1); + EXPECT_FALSE(wide_string == c_string2); + EXPECT_FALSE(wide_string == c_string3); + EXPECT_FALSE(c_string1 == wide_string); + EXPECT_FALSE(c_string2 == wide_string); + EXPECT_FALSE(c_string3 == wide_string); +} + +TEST(WideString, OperatorNE) { + WideString null_string; + EXPECT_FALSE(null_string != null_string); + + WideString empty_string(L""); + EXPECT_FALSE(empty_string != empty_string); + EXPECT_FALSE(empty_string != null_string); + EXPECT_FALSE(null_string != empty_string); + + WideString deleted_string(L"hello"); + deleted_string.Delete(0, 5); + EXPECT_FALSE(deleted_string != deleted_string); + EXPECT_FALSE(deleted_string != null_string); + EXPECT_FALSE(deleted_string != empty_string); + EXPECT_FALSE(null_string != deleted_string); + EXPECT_FALSE(null_string != empty_string); + + WideString wide_string(L"hello"); + EXPECT_FALSE(wide_string != wide_string); + EXPECT_TRUE(wide_string != null_string); + EXPECT_TRUE(wide_string != empty_string); + EXPECT_TRUE(wide_string != deleted_string); + EXPECT_TRUE(null_string != wide_string); + EXPECT_TRUE(empty_string != wide_string); + EXPECT_TRUE(deleted_string != wide_string); + + WideString wide_string_same1(L"hello"); + EXPECT_FALSE(wide_string != wide_string_same1); + EXPECT_FALSE(wide_string_same1 != wide_string); + + WideString wide_string_same2(wide_string); + EXPECT_FALSE(wide_string != wide_string_same2); + EXPECT_FALSE(wide_string_same2 != wide_string); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_TRUE(wide_string != wide_string1); + EXPECT_TRUE(wide_string != wide_string2); + EXPECT_TRUE(wide_string != wide_string3); + EXPECT_TRUE(wide_string1 != wide_string); + EXPECT_TRUE(wide_string2 != wide_string); + EXPECT_TRUE(wide_string3 != wide_string); + + WideStringView null_string_c; + WideStringView empty_string_c(L""); + EXPECT_FALSE(null_string != null_string_c); + EXPECT_FALSE(null_string != empty_string_c); + EXPECT_FALSE(empty_string != null_string_c); + EXPECT_FALSE(empty_string != empty_string_c); + EXPECT_FALSE(deleted_string != null_string_c); + EXPECT_FALSE(deleted_string != empty_string_c); + EXPECT_FALSE(null_string_c != null_string); + EXPECT_FALSE(empty_string_c != null_string); + EXPECT_FALSE(null_string_c != empty_string); + EXPECT_FALSE(empty_string_c != empty_string); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_FALSE(wide_string != wide_string_c_same1); + EXPECT_FALSE(wide_string_c_same1 != wide_string); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_TRUE(wide_string != wide_string_c1); + EXPECT_TRUE(wide_string != wide_string_c2); + EXPECT_TRUE(wide_string != wide_string_c3); + EXPECT_TRUE(wide_string_c1 != wide_string); + EXPECT_TRUE(wide_string_c2 != wide_string); + EXPECT_TRUE(wide_string_c3 != wide_string); + + const wchar_t* const c_null_string = nullptr; + const wchar_t* const c_empty_string = L""; + EXPECT_FALSE(null_string != c_null_string); + EXPECT_FALSE(null_string != c_empty_string); + EXPECT_FALSE(empty_string != c_null_string); + EXPECT_FALSE(empty_string != c_empty_string); + EXPECT_FALSE(deleted_string != c_null_string); + EXPECT_FALSE(deleted_string != c_empty_string); + EXPECT_FALSE(c_null_string != null_string); + EXPECT_FALSE(c_empty_string != null_string); + EXPECT_FALSE(c_null_string != empty_string); + EXPECT_FALSE(c_empty_string != empty_string); + EXPECT_FALSE(c_null_string != deleted_string); + EXPECT_FALSE(c_empty_string != deleted_string); + + const wchar_t* const c_string_same1 = L"hello"; + EXPECT_FALSE(wide_string != c_string_same1); + EXPECT_FALSE(c_string_same1 != wide_string); + + const wchar_t* const c_string1 = L"he"; + const wchar_t* const c_string2 = L"hellp"; + const wchar_t* const c_string3 = L"hellod"; + EXPECT_TRUE(wide_string != c_string1); + EXPECT_TRUE(wide_string != c_string2); + EXPECT_TRUE(wide_string != c_string3); + EXPECT_TRUE(c_string1 != wide_string); + EXPECT_TRUE(c_string2 != wide_string); + EXPECT_TRUE(c_string3 != wide_string); +} + +TEST(WideString, ConcatInPlace) { + WideString fred; + fred.Concat(L"FRED", 4); + EXPECT_EQ(L"FRED", fred); + + fred.Concat(L"DY", 2); + EXPECT_EQ(L"FREDDY", fred); + + fred.Delete(3, 3); + EXPECT_EQ(L"FRE", fred); + + fred.Concat(L"D", 1); + EXPECT_EQ(L"FRED", fred); + + WideString copy = fred; + fred.Concat(L"DY", 2); + EXPECT_EQ(L"FREDDY", fred); + EXPECT_EQ(L"FRED", copy); +} + +TEST(WideString, Remove) { + WideString freed(L"FREED"); + freed.Remove(L'E'); + EXPECT_EQ(L"FRD", freed); + freed.Remove(L'F'); + EXPECT_EQ(L"RD", freed); + freed.Remove(L'D'); + EXPECT_EQ(L"R", freed); + freed.Remove(L'X'); + EXPECT_EQ(L"R", freed); + freed.Remove(L'R'); + EXPECT_EQ(L"", freed); + + WideString empty; + empty.Remove(L'X'); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, RemoveCopies) { + WideString freed(L"FREED"); + const wchar_t* old_buffer = freed.c_str(); + + // No change with single reference - no copy. + freed.Remove(L'Q'); + EXPECT_EQ(L"FREED", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // Change with single reference - no copy. + freed.Remove(L'E'); + EXPECT_EQ(L"FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // No change with multiple references - no copy. + WideString shared(freed); + freed.Remove(L'Q'); + EXPECT_EQ(L"FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + EXPECT_EQ(old_buffer, shared.c_str()); + + // Change with multiple references -- must copy. + freed.Remove(L'D'); + EXPECT_EQ(L"FR", freed); + EXPECT_NE(old_buffer, freed.c_str()); + EXPECT_EQ(L"FRD", shared); + EXPECT_EQ(old_buffer, shared.c_str()); +} + +TEST(WideString, Replace) { + WideString fred(L"FRED"); + fred.Replace(L"FR", L"BL"); + EXPECT_EQ(L"BLED", fred); + fred.Replace(L"D", L"DDY"); + EXPECT_EQ(L"BLEDDY", fred); + fred.Replace(L"LEDD", L""); + EXPECT_EQ(L"BY", fred); + fred.Replace(L"X", L"CLAMS"); + EXPECT_EQ(L"BY", fred); + fred.Replace(L"BY", L"HI"); + EXPECT_EQ(L"HI", fred); + fred.Replace(L"", L"CLAMS"); + EXPECT_EQ(L"HI", fred); + fred.Replace(L"HI", L""); + EXPECT_EQ(L"", fred); +} + +TEST(WideString, Insert) { + WideString fred(L"FRED"); + EXPECT_EQ(5u, fred.Insert(0, 'S')); + EXPECT_EQ(L"SFRED", fred); + EXPECT_EQ(6u, fred.Insert(1, 'T')); + EXPECT_EQ(L"STFRED", fred); + EXPECT_EQ(7u, fred.Insert(4, 'U')); + EXPECT_EQ(L"STFRUED", fred); + EXPECT_EQ(8u, fred.Insert(7, 'V')); + EXPECT_EQ(L"STFRUEDV", fred); + EXPECT_EQ(8u, fred.Insert(12, 'P')); + EXPECT_EQ(L"STFRUEDV", fred); + { + WideString empty; + EXPECT_EQ(1u, empty.Insert(0, 'X')); + EXPECT_EQ(L"X", empty); + } + { + WideString empty; + EXPECT_EQ(0u, empty.Insert(5, 'X')); + EXPECT_NE(L"X", empty); + } +} + +TEST(WideString, InsertAtFrontAndInsertAtBack) { + { + WideString empty; + EXPECT_EQ(1u, empty.InsertAtFront('D')); + EXPECT_EQ(L"D", empty); + EXPECT_EQ(2u, empty.InsertAtFront('E')); + EXPECT_EQ(L"ED", empty); + EXPECT_EQ(3u, empty.InsertAtFront('R')); + EXPECT_EQ(L"RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ(L"FRED", empty); + } + { + WideString empty; + EXPECT_EQ(1u, empty.InsertAtBack('F')); + EXPECT_EQ(L"F", empty); + EXPECT_EQ(2u, empty.InsertAtBack('R')); + EXPECT_EQ(L"FR", empty); + EXPECT_EQ(3u, empty.InsertAtBack('E')); + EXPECT_EQ(L"FRE", empty); + EXPECT_EQ(4u, empty.InsertAtBack('D')); + EXPECT_EQ(L"FRED", empty); + } + { + WideString empty; + EXPECT_EQ(1u, empty.InsertAtBack('E')); + EXPECT_EQ(L"E", empty); + EXPECT_EQ(2u, empty.InsertAtFront('R')); + EXPECT_EQ(L"RE", empty); + EXPECT_EQ(3u, empty.InsertAtBack('D')); + EXPECT_EQ(L"RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ(L"FRED", empty); + } +} + +TEST(WideString, Delete) { + WideString fred(L"FRED"); + EXPECT_EQ(4u, fred.Delete(0, 0)); + EXPECT_EQ(L"FRED", fred); + EXPECT_EQ(2u, fred.Delete(0, 2)); + EXPECT_EQ(L"ED", fred); + EXPECT_EQ(1u, fred.Delete(1)); + EXPECT_EQ(L"E", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ(L"", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ(L"", fred); + + WideString empty; + EXPECT_EQ(0u, empty.Delete(0)); + EXPECT_EQ(L"", empty); + EXPECT_EQ(0u, empty.Delete(1)); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, Mid) { + WideString fred(L"FRED"); + EXPECT_EQ(L"", fred.Mid(0, 0)); + EXPECT_EQ(L"", fred.Mid(3, 0)); + EXPECT_EQ(L"FRED", fred.Mid(0, 4)); + EXPECT_EQ(L"RED", fred.Mid(1, 3)); + EXPECT_EQ(L"ED", fred.Mid(2, 2)); + EXPECT_EQ(L"D", fred.Mid(3, 1)); + EXPECT_EQ(L"F", fred.Mid(0, 1)); + EXPECT_EQ(L"R", fred.Mid(1, 1)); + EXPECT_EQ(L"E", fred.Mid(2, 1)); + EXPECT_EQ(L"D", fred.Mid(3, 1)); + EXPECT_EQ(L"FR", fred.Mid(0, 2)); + EXPECT_EQ(L"FRED", fred.Mid(0, 4)); + EXPECT_EQ(L"", fred.Mid(0, 10)); + + EXPECT_EQ(L"", fred.Mid(1, 4)); + EXPECT_EQ(L"", fred.Mid(4, 1)); + + WideString empty; + EXPECT_EQ(L"", empty.Mid(0, 0)); +} + +TEST(WideString, Left) { + WideString fred(L"FRED"); + EXPECT_EQ(L"", fred.Left(0)); + EXPECT_EQ(L"F", fred.Left(1)); + EXPECT_EQ(L"FR", fred.Left(2)); + EXPECT_EQ(L"FRE", fred.Left(3)); + EXPECT_EQ(L"FRED", fred.Left(4)); + + EXPECT_EQ(L"", fred.Left(5)); + + WideString empty; + EXPECT_EQ(L"", empty.Left(0)); + EXPECT_EQ(L"", empty.Left(1)); +} + +TEST(WideString, Right) { + WideString fred(L"FRED"); + EXPECT_EQ(L"", fred.Right(0)); + EXPECT_EQ(L"D", fred.Right(1)); + EXPECT_EQ(L"ED", fred.Right(2)); + EXPECT_EQ(L"RED", fred.Right(3)); + EXPECT_EQ(L"FRED", fred.Right(4)); + + EXPECT_EQ(L"", fred.Right(5)); + + WideString empty; + EXPECT_EQ(L"", empty.Right(0)); + EXPECT_EQ(L"", empty.Right(1)); +} + +TEST(WideString, Find) { + WideString null_string; + EXPECT_FALSE(null_string.Find(L'a').has_value()); + EXPECT_FALSE(null_string.Find(L'\0').has_value()); + + WideString empty_string(L""); + EXPECT_FALSE(empty_string.Find(L'a').has_value()); + EXPECT_FALSE(empty_string.Find(L'\0').has_value()); + + Optional result; + WideString single_string(L"a"); + result = single_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find(L'b').has_value()); + EXPECT_FALSE(single_string.Find(L'\0').has_value()); + + WideString longer_string(L"abccc"); + result = longer_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find(L'c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find(L'c', 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find(L'\0').has_value()); + + result = longer_string.Find(L"ab"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find(L"ccc"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find(L"cc", 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find(L"d").has_value()); + + WideString hibyte_string( + L"ab\xff8c" + L"def"); + result = hibyte_string.Find(L'\xff8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(WideString, UpperLower) { + WideString fred(L"F-Re.42D"); + fred.MakeLower(); + EXPECT_EQ(L"f-re.42d", fred); + fred.MakeUpper(); + EXPECT_EQ(L"F-RE.42D", fred); + + WideString empty; + empty.MakeLower(); + EXPECT_EQ(L"", empty); + empty.MakeUpper(); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, Trim) { + WideString fred(L" FRED "); + fred.Trim(); + EXPECT_EQ(L"FRED", fred); + fred.Trim(L'E'); + EXPECT_EQ(L"FRED", fred); + fred.Trim(L'F'); + EXPECT_EQ(L"RED", fred); + fred.Trim(L"ERP"); + EXPECT_EQ(L"D", fred); + + WideString blank(L" "); + blank.Trim(L"ERP"); + EXPECT_EQ(L" ", blank); + blank.Trim(L'E'); + EXPECT_EQ(L" ", blank); + blank.Trim(); + EXPECT_EQ(L"", blank); + + WideString empty; + empty.Trim(L"ERP"); + EXPECT_EQ(L"", empty); + empty.Trim(L'E'); + EXPECT_EQ(L"", empty); + empty.Trim(); + EXPECT_EQ(L"", empty); + + WideString abc(L" ABCCBA "); + abc.Trim(L"A"); + EXPECT_EQ(L" ABCCBA ", abc); + abc.Trim(L" A"); + EXPECT_EQ(L"BCCB", abc); +} + +TEST(WideString, TrimLeft) { + WideString fred(L" FRED "); + fred.TrimLeft(); + EXPECT_EQ(L"FRED ", fred); + fred.TrimLeft(L'E'); + EXPECT_EQ(L"FRED ", fred); + fred.TrimLeft(L'F'); + EXPECT_EQ(L"RED ", fred); + fred.TrimLeft(L"ERP"); + EXPECT_EQ(L"D ", fred); + + WideString blank(L" "); + blank.TrimLeft(L"ERP"); + EXPECT_EQ(L" ", blank); + blank.TrimLeft(L'E'); + EXPECT_EQ(L" ", blank); + blank.TrimLeft(); + EXPECT_EQ(L"", blank); + + WideString empty; + empty.TrimLeft(L"ERP"); + EXPECT_EQ(L"", empty); + empty.TrimLeft(L'E'); + EXPECT_EQ(L"", empty); + empty.TrimLeft(); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, TrimLeftCopies) { + { + // With a single reference, no copy takes place. + WideString fred(L" FRED "); + const wchar_t* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ(L"FRED ", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + WideString fred(L" FRED "); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ(L"FRED ", fred); + EXPECT_EQ(L" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + WideString fred(L"FRED"); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ(L"FRED", fred); + EXPECT_EQ(L"FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(WideString, TrimRight) { + WideString fred(L" FRED "); + fred.TrimRight(); + EXPECT_EQ(L" FRED", fred); + fred.TrimRight(L'E'); + EXPECT_EQ(L" FRED", fred); + fred.TrimRight(L'D'); + EXPECT_EQ(L" FRE", fred); + fred.TrimRight(L"ERP"); + EXPECT_EQ(L" F", fred); + + WideString blank(L" "); + blank.TrimRight(L"ERP"); + EXPECT_EQ(L" ", blank); + blank.TrimRight(L'E'); + EXPECT_EQ(L" ", blank); + blank.TrimRight(); + EXPECT_EQ(L"", blank); + + WideString empty; + empty.TrimRight(L"ERP"); + EXPECT_EQ(L"", empty); + empty.TrimRight(L'E'); + EXPECT_EQ(L"", empty); + empty.TrimRight(); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, TrimRightCopies) { + { + // With a single reference, no copy takes place. + WideString fred(L" FRED "); + const wchar_t* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(L" FRED", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + WideString fred(L" FRED "); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(L" FRED", fred); + EXPECT_EQ(L" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + WideString fred(L"FRED"); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(L"FRED", fred); + EXPECT_EQ(L"FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(WideString, Reserve) { + { + WideString str; + str.Reserve(6); + const wchar_t* old_buffer = str.c_str(); + str += L"ABCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += L"Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } + { + WideString str(L"A"); + str.Reserve(6); + const wchar_t* old_buffer = str.c_str(); + str += L"BCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += L"Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } +} + +TEST(WideString, GetBuffer) { + { + WideString str; + wchar_t* buffer = str.GetBuffer(12); + wcscpy(buffer, L"clams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ(L"clams", str); + } + { + WideString str(L"cl"); + wchar_t* buffer = str.GetBuffer(12); + wcscpy(buffer + 2, L"ams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ(L"clams", str); + } +} + +TEST(WideString, ReleaseBuffer) { + { + WideString str; + str.Reserve(12); + str += L"clams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + WideString str(L"c"); + str.Reserve(12); + str += L"lams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + WideString str; + str.Reserve(200); + str += L"clams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + WideString str(L"c"); + str.Reserve(200); + str += L"lams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } +} + +TEST(WideString, EmptyReverseIterator) { + WideString empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(WideString, OneCharReverseIterator) { + WideString one_str(L"a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(WideString, MultiCharReverseIterator) { + WideString multi_str(L"abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(WideString, UTF16LE_Encode) { + struct UTF16LEEncodeCase { + WideString ws; + ByteString bs; + } const utf16le_encode_cases[] = { + {L"", ByteString("\0\0", 2)}, + {L"abc", ByteString("a\0b\0c\0\0\0", 8)}, + {L"abcdef", ByteString("a\0b\0c\0d\0e\0f\0\0\0", 14)}, + {L"abc\0def", ByteString("a\0b\0c\0\0\0", 8)}, + {L"\xaabb\xccdd", ByteString("\xbb\xaa\xdd\xcc\0\0", 6)}, + {L"\x3132\x6162", ByteString("\x32\x31\x62\x61\0\0", 6)}, + }; + + for (size_t i = 0; i < FX_ArraySize(utf16le_encode_cases); ++i) { + EXPECT_EQ(utf16le_encode_cases[i].bs, + utf16le_encode_cases[i].ws.UTF16LE_Encode()) + << " for case number " << i; + } +} + +TEST(WideStringView, FromVector) { + std::vector null_vec; + WideStringView null_string(null_vec); + EXPECT_EQ(0u, null_string.GetLength()); + + std::vector lower_a_vec( + 10, static_cast(L'a')); + WideStringView lower_a_string(lower_a_vec); + EXPECT_EQ(10u, lower_a_string.GetLength()); + EXPECT_EQ(L"aaaaaaaaaa", lower_a_string); + + std::vector cleared_vec; + cleared_vec.push_back(42); + cleared_vec.pop_back(); + WideStringView cleared_string(cleared_vec); + EXPECT_EQ(0u, cleared_string.GetLength()); + EXPECT_EQ(nullptr, cleared_string.raw_str()); +} + +TEST(WideStringView, ElementAccess) { + WideStringView abc(L"abc"); + EXPECT_EQ(L'a', static_cast(abc[0])); + EXPECT_EQ(L'b', static_cast(abc[1])); + EXPECT_EQ(L'c', static_cast(abc[2])); +#ifndef NDEBUG + EXPECT_DEATH({ abc[4]; }, ".*"); +#endif +} + +TEST(WideStringView, OperatorLT) { + WideStringView empty; + WideStringView a(L"a"); + WideStringView abc(L"\x0110qq"); // Comes InsertAtFront despite endianness. + WideStringView def(L"\x1001qq"); // Comes InsertAtBack despite endianness. + const wchar_t* const c_null = nullptr; + const wchar_t* const c_empty = L""; + const wchar_t* const c_a = L"a"; + const wchar_t* const c_abc = L"\x0110qq"; + const wchar_t* const c_def = L"\x1001qq"; + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + EXPECT_FALSE(c_null < empty); + EXPECT_FALSE(c_empty < empty); + EXPECT_FALSE(c_a < a); + EXPECT_FALSE(c_abc < abc); + EXPECT_FALSE(c_def < def); + EXPECT_FALSE(empty < c_null); + EXPECT_FALSE(empty < c_empty); + EXPECT_FALSE(a < c_a); + EXPECT_FALSE(abc < c_abc); + EXPECT_FALSE(def < c_def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + EXPECT_TRUE(empty < c_a); + EXPECT_FALSE(a < c_null); + EXPECT_FALSE(a < c_empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + EXPECT_TRUE(empty < c_abc); + EXPECT_FALSE(abc < c_null); + EXPECT_FALSE(abc < c_empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + EXPECT_TRUE(empty < c_def); + EXPECT_FALSE(def < c_null); + EXPECT_FALSE(def < c_empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + EXPECT_TRUE(a < c_abc); + EXPECT_FALSE(abc < c_a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + EXPECT_TRUE(a < c_def); + EXPECT_FALSE(def < c_a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); + EXPECT_TRUE(abc < c_def); + EXPECT_FALSE(def < c_abc); +} + +TEST(WideStringView, OperatorEQ) { + WideStringView wide_string_c(L"hello"); + EXPECT_TRUE(wide_string_c == wide_string_c); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_TRUE(wide_string_c == wide_string_c_same1); + EXPECT_TRUE(wide_string_c_same1 == wide_string_c); + + WideStringView wide_string_c_same2(wide_string_c); + EXPECT_TRUE(wide_string_c == wide_string_c_same2); + EXPECT_TRUE(wide_string_c_same2 == wide_string_c); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_FALSE(wide_string_c == wide_string_c1); + EXPECT_FALSE(wide_string_c == wide_string_c2); + EXPECT_FALSE(wide_string_c == wide_string_c3); + EXPECT_FALSE(wide_string_c1 == wide_string_c); + EXPECT_FALSE(wide_string_c2 == wide_string_c); + EXPECT_FALSE(wide_string_c3 == wide_string_c); + + WideString wide_string_same1(L"hello"); + EXPECT_TRUE(wide_string_c == wide_string_same1); + EXPECT_TRUE(wide_string_same1 == wide_string_c); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_FALSE(wide_string_c == wide_string1); + EXPECT_FALSE(wide_string_c == wide_string2); + EXPECT_FALSE(wide_string_c == wide_string3); + EXPECT_FALSE(wide_string1 == wide_string_c); + EXPECT_FALSE(wide_string2 == wide_string_c); + EXPECT_FALSE(wide_string3 == wide_string_c); + + const wchar_t* const c_string_same1 = L"hello"; + EXPECT_TRUE(wide_string_c == c_string_same1); + EXPECT_TRUE(c_string_same1 == wide_string_c); + + const wchar_t* const c_string1 = L"he"; + const wchar_t* const c_string2 = L"hellp"; + const wchar_t* const c_string3 = L"hellod"; + EXPECT_FALSE(wide_string_c == c_string1); + EXPECT_FALSE(wide_string_c == c_string2); + EXPECT_FALSE(wide_string_c == c_string3); + + EXPECT_FALSE(c_string1 == wide_string_c); + EXPECT_FALSE(c_string2 == wide_string_c); + EXPECT_FALSE(c_string3 == wide_string_c); +} + +TEST(WideStringView, OperatorNE) { + WideStringView wide_string_c(L"hello"); + EXPECT_FALSE(wide_string_c != wide_string_c); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_FALSE(wide_string_c != wide_string_c_same1); + EXPECT_FALSE(wide_string_c_same1 != wide_string_c); + + WideStringView wide_string_c_same2(wide_string_c); + EXPECT_FALSE(wide_string_c != wide_string_c_same2); + EXPECT_FALSE(wide_string_c_same2 != wide_string_c); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_TRUE(wide_string_c != wide_string_c1); + EXPECT_TRUE(wide_string_c != wide_string_c2); + EXPECT_TRUE(wide_string_c != wide_string_c3); + EXPECT_TRUE(wide_string_c1 != wide_string_c); + EXPECT_TRUE(wide_string_c2 != wide_string_c); + EXPECT_TRUE(wide_string_c3 != wide_string_c); + + WideString wide_string_same1(L"hello"); + EXPECT_FALSE(wide_string_c != wide_string_same1); + EXPECT_FALSE(wide_string_same1 != wide_string_c); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_TRUE(wide_string_c != wide_string1); + EXPECT_TRUE(wide_string_c != wide_string2); + EXPECT_TRUE(wide_string_c != wide_string3); + EXPECT_TRUE(wide_string1 != wide_string_c); + EXPECT_TRUE(wide_string2 != wide_string_c); + EXPECT_TRUE(wide_string3 != wide_string_c); + + const wchar_t* const c_string_same1 = L"hello"; + EXPECT_FALSE(wide_string_c != c_string_same1); + EXPECT_FALSE(c_string_same1 != wide_string_c); + + const wchar_t* const c_string1 = L"he"; + const wchar_t* const c_string2 = L"hellp"; + const wchar_t* const c_string3 = L"hellod"; + EXPECT_TRUE(wide_string_c != c_string1); + EXPECT_TRUE(wide_string_c != c_string2); + EXPECT_TRUE(wide_string_c != c_string3); + + EXPECT_TRUE(c_string1 != wide_string_c); + EXPECT_TRUE(c_string2 != wide_string_c); + EXPECT_TRUE(c_string3 != wide_string_c); +} + +TEST(WideStringView, Find) { + WideStringView null_string; + EXPECT_FALSE(null_string.Find(L'a').has_value()); + EXPECT_FALSE(null_string.Find(L'\0').has_value()); + + WideStringView empty_string(L""); + EXPECT_FALSE(empty_string.Find(L'a').has_value()); + EXPECT_FALSE(empty_string.Find(L'\0').has_value()); + + Optional result; + WideStringView single_string(L"a"); + result = single_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find(L'b').has_value()); + EXPECT_FALSE(single_string.Find(L'\0').has_value()); + + WideStringView longer_string(L"abccc"); + result = longer_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find(L'c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + EXPECT_FALSE(longer_string.Find(L'd').has_value()); + EXPECT_FALSE(longer_string.Find(L'\0').has_value()); + + WideStringView hibyte_string( + L"ab\xFF8c" + L"def"); + result = hibyte_string.Find(L'\xFF8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(WideStringView, NullIterator) { + WideStringView null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideStringView, EmptyIterator) { + WideStringView empty_str(L""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideStringView, OneCharIterator) { + WideStringView one_str(L"a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a'), sum); +} + +TEST(WideStringView, MultiCharIterator) { + WideStringView one_str(L"abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a' + L'b' + L'c'), sum); +} + +TEST(WideStringView, EmptyReverseIterator) { + WideStringView empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(WideStringView, OneCharReverseIterator) { + WideStringView one_str(L"a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(WideStringView, MultiCharReverseIterator) { + WideStringView multi_str(L"abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(WideStringView, AnyAllNoneOf) { + WideStringView str(L"aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); +} + +TEST(WideStringView, TrimmedRight) { + WideStringView fred(L"FRED"); + EXPECT_EQ(L"FRED", fred.TrimmedRight(L'E')); + EXPECT_EQ(L"FRE", fred.TrimmedRight(L'D')); + WideStringView fredd(L"FREDD"); + EXPECT_EQ(L"FRE", fred.TrimmedRight(L'D')); +} + +TEST(WideString, FormatWidth) { + EXPECT_EQ(L" 1", WideString::Format(L"%5d", 1)); + EXPECT_EQ(L"1", WideString::Format(L"%d", 1)); + EXPECT_EQ(L" 1", WideString::Format(L"%*d", 5, 1)); + EXPECT_EQ(L"1", WideString::Format(L"%-1d", 1)); + EXPECT_EQ(L"1", WideString::Format(L"%0d", 1)); + EXPECT_EQ(L"", WideString::Format(L"%1048576d", 1)); +} + +TEST(WideString, FormatPrecision) { + EXPECT_EQ(L"1.12", WideString::Format(L"%.2f", 1.12345)); + EXPECT_EQ(L"1.123", WideString::Format(L"%.*f", 3, 1.12345)); + EXPECT_EQ(L"1.123450", WideString::Format(L"%f", 1.12345)); + EXPECT_EQ(L"1.123450", WideString::Format(L"%-1f", 1.12345)); + EXPECT_EQ(L"1.123450", WideString::Format(L"%0f", 1.12345)); + EXPECT_EQ(L"", WideString::Format(L"%.1048576f", 1.2)); +} + +TEST(WideString, FormatOutOfRangeChar) { + EXPECT_NE(L"", WideString::Format(L"unsupported char '%c'", 0x00FF00FF)); +} + +TEST(WideString, Empty) { + WideString empty_str; + EXPECT_TRUE(empty_str.IsEmpty()); + EXPECT_EQ(0u, empty_str.GetLength()); + const wchar_t* cstr = empty_str.c_str(); + EXPECT_EQ(0u, wcslen(cstr)); +} + +TEST(CFX_WidString, InitializerList) { + WideString many_str({L"clams", L" and ", L"oysters"}); + EXPECT_EQ(L"clams and oysters", many_str); + many_str = {L"fish", L" and ", L"chips", L" and ", L"soda"}; + EXPECT_EQ(L"fish and chips and soda", many_str); +} + +TEST(WideString, NullIterator) { + WideString null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideString, EmptyIterator) { + WideString empty_str(L""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideString, OneCharIterator) { + WideString one_str(L"a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a'), sum); +} + +TEST(WideString, MultiCharIterator) { + WideString one_str(L"abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a' + L'b' + L'c'), sum); +} + +TEST(WideString, AnyAllNoneOf) { + WideString str(L"aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); +} + +TEST(WideString, OStreamOverload) { + std::ostringstream stream; + + // Basic case, empty string + WideString str; + stream << str; + EXPECT_EQ("", stream.str()); + + // Basic case, wide character + str = L"\u20AC"; + stream << str; + EXPECT_EQ("\u20AC", stream.str()); + + // Basic case, non-empty string + str = L"def"; + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Changing the WideString does not change the stream it was written to. + str = L"123"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Writing it again to the stream will use the latest value. + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abc123ghi", stream.str()); + + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + + // Writing a WideString with nulls and no specified length treats it as + // a C-style null-terminated string. + str = WideString(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + + // Writing a WideString with nulls but specifying its length treats it as + // a C++-style string. + str = WideString(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + + // << operators can be chained. + WideString str1(L"abc"); + WideString str2(L"def"); + stream.str(""); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); +} + +TEST(WideString, WideOStreamOverload) { + std::wostringstream stream; + + // Basic case, empty string + WideString str; + stream << str; + EXPECT_EQ(L"", stream.str()); + + // Basic case, wide character + str = L"\u20AC"; + stream << str; + EXPECT_EQ(L"\u20AC", stream.str()); + + // Basic case, non-empty string + str = L"def"; + stream.str(L""); + stream << L"abc" << str << L"ghi"; + EXPECT_EQ(L"abcdefghi", stream.str()); + + // Changing the WideString does not change the stream it was written to. + str = L"123"; + EXPECT_EQ(L"abcdefghi", stream.str()); + + // Writing it again to the stream will use the latest value. + stream.str(L""); + stream << L"abc" << str << L"ghi"; + EXPECT_EQ(L"abc123ghi", stream.str()); + + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + + // Writing a WideString with nulls and no specified length treats it as + // a C-style null-terminated string. + str = WideString(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream.str(L""); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + + // Writing a WideString with nulls but specifying its length treats it as + // a C++-style string. + str = WideString(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream.str(L""); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + + // << operators can be chained. + WideString str1(L"abc"); + WideString str2(L"def"); + stream.str(L""); + stream << str1 << str2; + EXPECT_EQ(L"abcdef", stream.str()); +} + +TEST(WideStringView, OStreamOverload) { + // Basic case, empty string + { + std::ostringstream stream; + WideStringView str; + stream << str; + EXPECT_EQ("", stream.str()); + } + + // Basic case, non-empty string + { + std::ostringstream stream; + WideStringView str(L"def"); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + } + + // Basic case, wide character + { + std::ostringstream stream; + WideStringView str(L"\u20AC"); + stream << str; + EXPECT_EQ("\u20AC", stream.str()); + } + + // Changing the WideStringView does not change the stream it was written to. + { + std::ostringstream stream; + WideStringView str(L"abc"); + stream << str; + str = L"123"; + EXPECT_EQ("abc", stream.str()); + } + + // Writing it again to the stream will use the latest value. + { + std::ostringstream stream; + WideStringView str(L"abc"); + stream << str; + stream.str(""); + str = L"123"; + stream << str; + EXPECT_EQ("123", stream.str()); + } + + // Writing a WideStringView with nulls and no specified length treats it as + // a C-style null-terminated string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::ostringstream stream; + WideStringView str(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + str = L""; + } + + // Writing a WideStringView with nulls but specifying its length treats it as + // a C++-style string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::ostringstream stream; + WideStringView str(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + str = L""; + } + + // << operators can be chained. + { + std::ostringstream stream; + WideStringView str1(L"abc"); + WideStringView str2(L"def"); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); + } +} + +TEST(WideStringView, WideOStreamOverload) { + // Basic case, empty string + { + std::wostringstream stream; + WideStringView str; + stream << str; + EXPECT_EQ(L"", stream.str()); + } + + // Basic case, non-empty string + { + std::wostringstream stream; + WideStringView str(L"def"); + stream << "abc" << str << "ghi"; + EXPECT_EQ(L"abcdefghi", stream.str()); + } + + // Basic case, wide character + { + std::wostringstream stream; + WideStringView str(L"\u20AC"); + stream << str; + EXPECT_EQ(L"\u20AC", stream.str()); + } + + // Changing the WideStringView does not change the stream it was written to. + { + std::wostringstream stream; + WideStringView str(L"abc"); + stream << str; + str = L"123"; + EXPECT_EQ(L"abc", stream.str()); + } + + // Writing it again to the stream will use the latest value. + { + std::wostringstream stream; + WideStringView str(L"abc"); + stream << str; + stream.str(L""); + str = L"123"; + stream << str; + EXPECT_EQ(L"123", stream.str()); + } + + // Writing a WideStringView with nulls and no specified length treats it as + // a C-style null-terminated string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::wostringstream stream; + WideStringView str(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + } + + // Writing a WideStringView with nulls but specifying its length treats it as + // a C++-style string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::wostringstream stream; + WideStringView str(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + } + + // << operators can be chained. + { + std::wostringstream stream; + WideStringView str1(L"abc"); + WideStringView str2(L"def"); + stream << str1 << str2; + EXPECT_EQ(L"abcdef", stream.str()); + } +} + +} // namespace fxcrt diff --git a/core/fxcrt/xml/cfx_saxcontext.cpp b/core/fxcrt/xml/cfx_saxcontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e2f0c58c92dc0675f9b14524225c3cce4a2f71c --- /dev/null +++ b/core/fxcrt/xml/cfx_saxcontext.cpp @@ -0,0 +1,9 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/xml/cfx_saxcontext.h" + +CFX_SAXContext::CFX_SAXContext() : m_eNode(CFX_SAXItem::Type::Unknown) {} + +CFX_SAXContext::~CFX_SAXContext() {} diff --git a/core/fxcrt/xml/cfx_saxcontext.h b/core/fxcrt/xml/cfx_saxcontext.h new file mode 100644 index 0000000000000000000000000000000000000000..d4d74a385b50ba8779fe3497e7626fa0677c346e --- /dev/null +++ b/core/fxcrt/xml/cfx_saxcontext.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_SAXCONTEXT_H_ +#define CORE_FXCRT_XML_CFX_SAXCONTEXT_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_saxreader.h" + +class CFX_SAXContext { + public: + CFX_SAXContext(); + ~CFX_SAXContext(); + + std::ostringstream m_TextBuf; + ByteString m_bsTagName; + CFX_SAXItem::Type m_eNode; +}; + +#endif // CORE_FXCRT_XML_CFX_SAXCONTEXT_H_ diff --git a/core/fxcrt/xml/cfx_saxreader.cpp b/core/fxcrt/xml/cfx_saxreader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..762144f4bb276c43876b75081d3ceed38ad2c0e9 --- /dev/null +++ b/core/fxcrt/xml/cfx_saxreader.cpp @@ -0,0 +1,744 @@ +// 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 "core/fxcrt/xml/cfx_saxreader.h" + +#include +#include + +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/xml/cfx_saxreaderhandler.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +enum class CFX_SaxMode { + Text = 0, + NodeStart, + DeclOrComment, + DeclNode, + Comment, + CommentContent, + TagName, + TagAttributeName, + TagAttributeEqual, + TagAttributeValue, + TagMaybeClose, + TagClose, + TagEnd, + TargetData, +}; + +class CFX_SAXCommentContext { + public: + CFX_SAXCommentContext() : m_iHeaderCount(0), m_iTailCount(0) {} + int32_t m_iHeaderCount; + int32_t m_iTailCount; +}; + +namespace { + +const uint32_t kSaxFileBufSize = 32768; + +} // namespace + +CFX_SAXFile::CFX_SAXFile() + : m_dwStart(0), + m_dwEnd(0), + m_dwCur(0), + m_pBuf(nullptr), + m_dwBufSize(0), + m_dwBufIndex(0) {} + +CFX_SAXFile::~CFX_SAXFile() {} + +bool CFX_SAXFile::StartFile(const RetainPtr& pFile, + uint32_t dwStart, + uint32_t dwLen) { + ASSERT(!m_pFile && pFile); + uint32_t dwSize = pFile->GetSize(); + if (dwStart >= dwSize) + return false; + + if (dwLen == static_cast(-1) || dwStart + dwLen > dwSize) + dwLen = dwSize - dwStart; + + if (dwLen == 0) + return false; + + m_dwBufSize = std::min(dwLen, kSaxFileBufSize); + m_pBuf = FX_Alloc(uint8_t, m_dwBufSize); + 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; +} + +bool CFX_SAXFile::ReadNextBlock() { + ASSERT(m_pFile); + uint32_t dwSize = m_dwEnd - m_dwCur; + if (dwSize == 0) { + return false; + } + m_dwBufSize = std::min(dwSize, kSaxFileBufSize); + 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 = nullptr; + } + m_pFile = nullptr; +} + +CFX_SAXReader::CFX_SAXReader() + : m_File(), + m_pHandler(nullptr), + m_iState(-1), + m_dwItemID(0), + m_dwParseMode(0) { + m_Data.reserve(256); + m_Name.reserve(256); +} + +CFX_SAXReader::~CFX_SAXReader() { + Reset(); +} + +void CFX_SAXReader::Reset() { + m_File.Reset(); + m_iState = -1; + m_Stack = std::stack>(); + m_dwItemID = 0; + m_SkipStack = std::stack(); + m_SkipChar = 0; + m_pCommentContext.reset(); + ClearData(); + ClearName(); +} + +void CFX_SAXReader::Push() { + std::unique_ptr pNew = + pdfium::MakeUnique(++m_dwItemID); + if (!m_Stack.empty()) + pNew->m_bSkip = m_Stack.top()->m_bSkip; + m_Stack.push(std::move(pNew)); +} + +void CFX_SAXReader::Pop() { + if (!m_Stack.empty()) + m_Stack.pop(); +} + +CFX_SAXItem* CFX_SAXReader::GetCurrentItem() const { + return m_Stack.empty() ? nullptr : m_Stack.top().get(); +} + +void CFX_SAXReader::ClearData() { + m_Data.clear(); + m_iEntityStart = -1; +} + +void CFX_SAXReader::ClearName() { + m_Name.clear(); +} + +void CFX_SAXReader::AppendToData(uint8_t ch) { + m_Data.push_back(ch); +} + +void CFX_SAXReader::AppendToName(uint8_t ch) { + m_Name.push_back(ch); +} + +void CFX_SAXReader::BackUpAndReplaceDataAt(int32_t index, uint8_t ch) { + ASSERT(index > -1); + m_Data.erase(m_Data.begin() + index, m_Data.end()); + AppendToData(ch); +} + +int32_t CFX_SAXReader::CurrentDataIndex() const { + return pdfium::CollectionSize(m_Data) - 1; +} + +bool CFX_SAXReader::IsEntityStart(uint8_t ch) const { + return m_iEntityStart == -1 && ch == '&'; +} + +bool CFX_SAXReader::IsEntityEnd(uint8_t ch) const { + return m_iEntityStart != -1 && ch == ';'; +} + +bool CFX_SAXReader::SkipSpace(uint8_t ch) { + return (m_dwParseMode & CFX_SaxParseMode_NotSkipSpace) == 0 && ch < 0x21; +} + +int32_t CFX_SAXReader::StartParse( + const RetainPtr& pFile, + uint32_t dwStart, + uint32_t dwLen, + uint32_t dwParseMode) { + Reset(); + if (!m_File.StartFile(pFile, dwStart, dwLen)) + return -1; + + m_iState = 0; + m_eMode = CFX_SaxMode::Text; + m_ePrevMode = CFX_SaxMode::Text; + m_bCharData = false; + m_dwDataOffset = 0; + m_dwParseMode = dwParseMode; + m_Stack.push(pdfium::MakeUnique(++m_dwItemID)); + return 0; +} + +int32_t CFX_SAXReader::ContinueParse() { + if (m_iState < 0 || m_iState > 99) + return m_iState; + + while (m_File.m_dwCur < m_File.m_dwEnd) { + uint32_t& index = m_File.m_dwBufIndex; + uint32_t size = m_File.m_dwBufSize; + const uint8_t* pBuf = m_File.m_pBuf; + while (index < size) { + m_CurByte = pBuf[index]; + ParseInternal(); + 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; + } + return m_iState; +} + +void CFX_SAXReader::ParseInternal() { + switch (m_eMode) { + case CFX_SaxMode::Text: + ParseText(); + break; + case CFX_SaxMode::NodeStart: + ParseNodeStart(); + break; + case CFX_SaxMode::DeclOrComment: + ParseDeclOrComment(); + break; + case CFX_SaxMode::DeclNode: + ParseDeclNode(); + break; + case CFX_SaxMode::Comment: + ParseComment(); + break; + case CFX_SaxMode::CommentContent: + ParseCommentContent(); + break; + case CFX_SaxMode::TagName: + ParseTagName(); + break; + case CFX_SaxMode::TagAttributeName: + ParseTagAttributeName(); + break; + case CFX_SaxMode::TagAttributeEqual: + ParseTagAttributeEqual(); + break; + case CFX_SaxMode::TagAttributeValue: + ParseTagAttributeValue(); + break; + case CFX_SaxMode::TagMaybeClose: + ParseMaybeClose(); + break; + case CFX_SaxMode::TagClose: + ParseTagClose(); + break; + case CFX_SaxMode::TagEnd: + ParseTagEnd(); + break; + case CFX_SaxMode::TargetData: + ParseTargetData(); + break; + } +} + +void CFX_SAXReader::ParseChar(uint8_t ch) { + AppendToData(ch); + if (IsEntityStart(ch)) { + m_iEntityStart = CurrentDataIndex(); + return; + } + if (!IsEntityEnd(ch)) + return; + + // No matter what, we're no longer in an entity. + ASSERT(m_iEntityStart > -1); + int32_t iSaveStart = m_iEntityStart; + m_iEntityStart = -1; + + // NOTE: Relies on negative lengths being treated as empty strings. + ByteString csEntity(m_Data.data() + iSaveStart + 1, + CurrentDataIndex() - iSaveStart - 1); + int32_t iLen = csEntity.GetLength(); + if (iLen == 0) + return; + + if (csEntity[0] == '#') { + if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_sharp) == 0) { + ch = 0; + uint8_t w; + if (iLen > 1 && csEntity[1] == 'x') { + for (int32_t 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 (int32_t i = 1; i < iLen; i++) { + w = csEntity[i]; + if (w < '0' || w > '9') + break; + ch = ch * 10 + w - '0'; + } + } + if (ch != 0) + BackUpAndReplaceDataAt(iSaveStart, ch); + } + return; + } + if (csEntity == "amp") { + if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_amp) == 0) + BackUpAndReplaceDataAt(iSaveStart, '&'); + return; + } + if (csEntity == "lt") { + if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_lt) == 0) + BackUpAndReplaceDataAt(iSaveStart, '<'); + return; + } + if (csEntity == "gt") { + if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_gt) == 0) + BackUpAndReplaceDataAt(iSaveStart, '>'); + return; + } + if (csEntity == "apos") { + if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_apos) == 0) + BackUpAndReplaceDataAt(iSaveStart, '\''); + return; + } + if (csEntity == "quot") { + if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_quot) == 0) + BackUpAndReplaceDataAt(iSaveStart, '\"'); + return; + } +} + +void CFX_SAXReader::ParseText() { + if (m_CurByte == '<') { + if (!m_Data.empty()) { + NotifyData(); + ClearData(); + } + Push(); + m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex; + m_eMode = CFX_SaxMode::NodeStart; + return; + } + if (m_Data.empty() && SkipSpace(m_CurByte)) + return; + + ParseChar(m_CurByte); +} + +void CFX_SAXReader::ParseNodeStart() { + if (m_CurByte == '?') { + GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Instruction; + m_eMode = CFX_SaxMode::TagName; + return; + } + if (m_CurByte == '!') { + m_eMode = CFX_SaxMode::DeclOrComment; + return; + } + if (m_CurByte == '/') { + m_eMode = CFX_SaxMode::TagEnd; + return; + } + if (m_CurByte == '>') { + Pop(); + m_eMode = CFX_SaxMode::Text; + return; + } + if (m_CurByte > 0x20) { + m_dwDataOffset = m_File.m_dwBufIndex; + GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Tag; + m_eMode = CFX_SaxMode::TagName; + AppendToData(m_CurByte); + } +} + +void CFX_SAXReader::ParseDeclOrComment() { + if (m_CurByte == '-') { + m_eMode = CFX_SaxMode::Comment; + GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Comment; + if (!m_pCommentContext) + m_pCommentContext = pdfium::MakeUnique(); + m_pCommentContext->m_iHeaderCount = 1; + m_pCommentContext->m_iTailCount = 0; + return; + } + m_eMode = CFX_SaxMode::DeclNode; + m_dwDataOffset = m_File.m_dwBufIndex; + m_SkipChar = '>'; + m_SkipStack.push('>'); + SkipNode(); +} + +void CFX_SAXReader::ParseComment() { + m_pCommentContext->m_iHeaderCount = 2; + m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex; + m_eMode = CFX_SaxMode::CommentContent; +} + +void CFX_SAXReader::ParseCommentContent() { + if (m_CurByte == '-') { + m_pCommentContext->m_iTailCount++; + return; + } + if (m_CurByte == '>' && m_pCommentContext->m_iTailCount == 2) { + NotifyTargetData(); + ClearData(); + Pop(); + m_eMode = CFX_SaxMode::Text; + return; + } + while (m_pCommentContext->m_iTailCount > 0) { + AppendToData('-'); + m_pCommentContext->m_iTailCount--; + } + AppendToData(m_CurByte); +} + +void CFX_SAXReader::ParseDeclNode() { + SkipNode(); +} + +void CFX_SAXReader::ParseTagName() { + if (m_CurByte < 0x21 || m_CurByte == '/' || m_CurByte == '>' || + m_CurByte == '?') { + NotifyEnter(); + ClearData(); + if (m_CurByte < 0x21) { + ClearName(); + m_eMode = CFX_SaxMode::TagAttributeName; + } else if (m_CurByte == '/' || m_CurByte == '?') { + m_ePrevMode = m_eMode; + m_eMode = CFX_SaxMode::TagMaybeClose; + } else { + NotifyBreak(); + m_eMode = CFX_SaxMode::Text; + } + } else { + AppendToData(m_CurByte); + } +} + +void CFX_SAXReader::ParseTagAttributeName() { + if (m_CurByte < 0x21 || m_CurByte == '=') { + if (m_Name.empty() && m_CurByte < 0x21) + return; + + m_SkipChar = 0; + m_eMode = m_CurByte == '=' ? CFX_SaxMode::TagAttributeValue + : CFX_SaxMode::TagAttributeEqual; + ClearData(); + return; + } + if (m_CurByte == '/' || m_CurByte == '>' || m_CurByte == '?') { + if (m_CurByte == '/' || m_CurByte == '?') { + m_ePrevMode = m_eMode; + m_eMode = CFX_SaxMode::TagMaybeClose; + } else { + NotifyBreak(); + m_eMode = CFX_SaxMode::Text; + } + return; + } + if (m_Name.empty()) + m_dwDataOffset = m_File.m_dwBufIndex; + AppendToName(m_CurByte); +} + +void CFX_SAXReader::ParseTagAttributeEqual() { + if (m_CurByte == '=') { + m_SkipChar = 0; + m_eMode = CFX_SaxMode::TagAttributeValue; + return; + } + if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) { + AppendToName(0x20); + m_eMode = CFX_SaxMode::TargetData; + ParseTargetData(); + } +} + +void CFX_SAXReader::ParseTagAttributeValue() { + if (m_SkipChar) { + if (m_SkipChar == m_CurByte) { + NotifyAttribute(); + ClearData(); + ClearName(); + m_SkipChar = 0; + m_eMode = CFX_SaxMode::TagAttributeName; + return; + } + ParseChar(m_CurByte); + return; + } + if (m_CurByte < 0x21) { + return; + } + if (m_Data.empty()) { + if (m_CurByte == '\'' || m_CurByte == '\"') + m_SkipChar = m_CurByte; + } +} + +void CFX_SAXReader::ParseMaybeClose() { + if (m_CurByte == '>') { + if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) { + NotifyTargetData(); + ClearData(); + ClearName(); + } + ParseTagClose(); + m_eMode = CFX_SaxMode::Text; + } else if (m_ePrevMode == CFX_SaxMode::TagName) { + AppendToData('/'); + m_eMode = CFX_SaxMode::TagName; + m_ePrevMode = CFX_SaxMode::Text; + ParseTagName(); + } else if (m_ePrevMode == CFX_SaxMode::TagAttributeName) { + AppendToName('/'); + m_eMode = CFX_SaxMode::TagAttributeName; + m_ePrevMode = CFX_SaxMode::Text; + ParseTagAttributeName(); + } else if (m_ePrevMode == CFX_SaxMode::TargetData) { + AppendToName('?'); + m_eMode = CFX_SaxMode::TargetData; + m_ePrevMode = CFX_SaxMode::Text; + ParseTargetData(); + } +} +void CFX_SAXReader::ParseTagClose() { + m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex; + 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; + NotifyEnd(); + ClearData(); + Pop(); + m_eMode = CFX_SaxMode::Text; + } else { + ParseChar(m_CurByte); + } +} +void CFX_SAXReader::ParseTargetData() { + if (m_CurByte == '?') { + m_ePrevMode = m_eMode; + m_eMode = CFX_SaxMode::TagMaybeClose; + } else { + AppendToName(m_CurByte); + } +} +void CFX_SAXReader::SkipNode() { + if (m_SkipChar == '\'' || m_SkipChar == '\"') { + if (m_CurByte != m_SkipChar) + return; + + ASSERT(!m_SkipStack.empty()); + m_SkipStack.pop(); + m_SkipChar = !m_SkipStack.empty() ? m_SkipStack.top() : 0; + return; + } + switch (m_CurByte) { + case '<': + m_SkipChar = '>'; + m_SkipStack.push('>'); + break; + case '[': + m_SkipChar = ']'; + m_SkipStack.push(']'); + break; + case '(': + m_SkipChar = ')'; + m_SkipStack.push(')'); + break; + case '\'': + m_SkipChar = '\''; + m_SkipStack.push('\''); + break; + case '\"': + m_SkipChar = '\"'; + m_SkipStack.push('\"'); + break; + default: + if (m_CurByte == m_SkipChar) { + m_SkipStack.pop(); + m_SkipChar = !m_SkipStack.empty() ? m_SkipStack.top() : 0; + if (m_SkipStack.empty() && m_CurByte == '>') { + if (m_Data.size() >= 9 && memcmp(m_Data.data(), "[CDATA[", 7) == 0 && + memcmp(m_Data.data() + m_Data.size() - 2, "]]", 2) == 0) { + Pop(); + m_Data.erase(m_Data.begin(), m_Data.begin() + 7); + m_Data.erase(m_Data.end() - 2, m_Data.end()); + m_bCharData = true; + NotifyData(); + m_bCharData = false; + } else { + Pop(); + } + ClearData(); + m_eMode = CFX_SaxMode::Text; + } + } + break; + } + if (!m_SkipStack.empty()) + ParseChar(m_CurByte); +} + +void CFX_SAXReader::NotifyData() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Tag) + m_pHandler->OnTagData( + pItem->m_pNode, + m_bCharData ? CFX_SAXItem::Type::CharData : CFX_SAXItem::Type::Text, + ByteStringView(m_Data), m_File.m_dwCur + m_dwDataOffset); +} + +void CFX_SAXReader::NotifyEnter() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Tag || + pItem->m_eNode == CFX_SAXItem::Type::Instruction) { + pItem->m_pNode = m_pHandler->OnTagEnter(ByteStringView(m_Data), + pItem->m_eNode, m_dwNodePos); + } +} + +void CFX_SAXReader::NotifyAttribute() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Tag || + pItem->m_eNode == CFX_SAXItem::Type::Instruction) { + m_pHandler->OnTagAttribute(pItem->m_pNode, ByteStringView(m_Name), + ByteStringView(m_Data)); + } +} + +void CFX_SAXReader::NotifyBreak() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Tag) + m_pHandler->OnTagBreak(pItem->m_pNode); +} + +void CFX_SAXReader::NotifyClose() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Tag || + pItem->m_eNode == CFX_SAXItem::Type::Instruction) { + m_pHandler->OnTagClose(pItem->m_pNode, m_dwNodePos); + } +} + +void CFX_SAXReader::NotifyEnd() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Tag) + m_pHandler->OnTagEnd(pItem->m_pNode, ByteStringView(m_Data), m_dwNodePos); +} + +void CFX_SAXReader::NotifyTargetData() { + if (!m_pHandler) + return; + + CFX_SAXItem* pItem = GetCurrentItem(); + if (!pItem) + return; + + if (pItem->m_eNode == CFX_SAXItem::Type::Instruction) { + m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode, + ByteStringView(m_Name), m_dwNodePos); + } else if (pItem->m_eNode == CFX_SAXItem::Type::Comment) { + m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode, + ByteStringView(m_Data), m_dwNodePos); + } +} + +void CFX_SAXReader::SkipCurrentNode() { + CFX_SAXItem* pItem = GetCurrentItem(); + if (pItem) + pItem->m_bSkip = true; +} diff --git a/core/fxcrt/xml/cfx_saxreader.h b/core/fxcrt/xml/cfx_saxreader.h new file mode 100644 index 0000000000000000000000000000000000000000..9ff755d05323652d0957a7a339f57e1f787bb4b6 --- /dev/null +++ b/core/fxcrt/xml/cfx_saxreader.h @@ -0,0 +1,174 @@ +// 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 CORE_FXCRT_XML_CFX_SAXREADER_H_ +#define CORE_FXCRT_XML_CFX_SAXREADER_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" + +class CFX_SAXCommentContext; +class CFX_SAXContext; +class IFX_SeekableReadStream; +enum class CFX_SaxMode; + +class CFX_SAXItem { + public: + enum class Type { + Unknown = 0, + Instruction, + Declaration, + Comment, + Tag, + Text, + CharData, + }; + + explicit CFX_SAXItem(uint32_t id) + : m_pNode(nullptr), m_eNode(Type::Unknown), m_dwID(id), m_bSkip(false) {} + + CFX_SAXContext* m_pNode; + Type m_eNode; + const uint32_t m_dwID; + bool m_bSkip; +}; + +class CFX_SAXFile { + public: + CFX_SAXFile(); + ~CFX_SAXFile(); + + bool StartFile(const RetainPtr& pFile, + uint32_t dwStart, + uint32_t dwLen); + bool ReadNextBlock(); + void Reset(); + + RetainPtr m_pFile; + uint32_t m_dwStart; + uint32_t m_dwEnd; + uint32_t m_dwCur; + uint8_t* m_pBuf; + uint32_t m_dwBufSize; + uint32_t m_dwBufIndex; +}; + +enum CFX_SaxParseMode { + CFX_SaxParseMode_NotConvert_amp = 1 << 0, + CFX_SaxParseMode_NotConvert_lt = 1 << 1, + CFX_SaxParseMode_NotConvert_gt = 1 << 2, + CFX_SaxParseMode_NotConvert_apos = 1 << 3, + CFX_SaxParseMode_NotConvert_quot = 1 << 4, + CFX_SaxParseMode_NotConvert_sharp = 1 << 5, + CFX_SaxParseMode_NotSkipSpace = 1 << 6 +}; + +class CFX_SAXReader { + public: + class HandlerIface { + public: + virtual ~HandlerIface() {} + virtual CFX_SAXContext* OnTagEnter(const ByteStringView& bsTagName, + CFX_SAXItem::Type eType, + uint32_t dwStartPos) = 0; + virtual void OnTagAttribute(CFX_SAXContext* pTag, + const ByteStringView& bsAttri, + const ByteStringView& bsValue) = 0; + virtual void OnTagBreak(CFX_SAXContext* pTag) = 0; + virtual void OnTagData(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos) = 0; + virtual void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) = 0; + virtual void OnTagEnd(CFX_SAXContext* pTag, + const ByteStringView& bsTagName, + uint32_t dwEndPos) = 0; + virtual void OnTargetData(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos) = 0; + }; + + CFX_SAXReader(); + ~CFX_SAXReader(); + + int32_t StartParse(const RetainPtr& pFile, + uint32_t dwStart = 0, + uint32_t dwLen = -1, + uint32_t dwParseMode = 0); + int32_t ContinueParse(); + void SetHandler(HandlerIface* pHandler) { m_pHandler = pHandler; } + + private: + void ParseInternal(); + void SkipCurrentNode(); + void AppendData(uint8_t ch); + void AppendName(uint8_t 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(); + void Reset(); + void ClearData(); + void ClearName(); + void AppendToData(uint8_t ch); + void AppendToName(uint8_t ch); + void BackUpAndReplaceDataAt(int32_t index, uint8_t ch); + bool IsEntityStart(uint8_t ch) const; + bool IsEntityEnd(uint8_t ch) const; + int32_t CurrentDataIndex() const; + void Push(); + void Pop(); + CFX_SAXItem* GetCurrentItem() const; + bool SkipSpace(uint8_t ch); + void SkipNode(); + void NotifyData(); + void NotifyEnter(); + void NotifyAttribute(); + void NotifyBreak(); + void NotifyClose(); + void NotifyEnd(); + void NotifyTargetData(); + void ReallocDataBuffer(); + void ReallocNameBuffer(); + void ParseChar(uint8_t ch); + + CFX_SAXFile m_File; + HandlerIface* m_pHandler; + int32_t m_iState; + std::stack> m_Stack; + uint32_t m_dwItemID; + CFX_SaxMode m_eMode; + CFX_SaxMode m_ePrevMode; + bool m_bCharData; + uint8_t m_CurByte; + uint32_t m_dwDataOffset; + std::stack m_SkipStack; + uint8_t m_SkipChar; + uint32_t m_dwNodePos; + std::vector m_Data; + int32_t m_iEntityStart; // Index into m_Data. + std::vector m_Name; + uint32_t m_dwParseMode; + std::unique_ptr m_pCommentContext; +}; + +#endif // CORE_FXCRT_XML_CFX_SAXREADER_H_ diff --git a/core/fxcrt/xml/cfx_saxreader_unittest.cpp b/core/fxcrt/xml/cfx_saxreader_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13d06325a79928950595a5565797da311609e6be --- /dev/null +++ b/core/fxcrt/xml/cfx_saxreader_unittest.cpp @@ -0,0 +1,152 @@ +// Copyright 2017 The 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. + +#include "core/fxcrt/xml/cfx_saxreader.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +using testing::_; +using testing::Eq; +using testing::Return; + +namespace { + +class MockHandler : public CFX_SAXReader::HandlerIface { + public: + MOCK_METHOD3(OnTagEnter, + CFX_SAXContext*(const ByteStringView& bsTagName, + CFX_SAXItem::Type eType, + uint32_t dwStartPos)); + MOCK_METHOD3(OnTagAttribute, + void(CFX_SAXContext* pTag, + const ByteStringView& bsAttri, + const ByteStringView& bsValue)); + MOCK_METHOD1(OnTagBreak, void(CFX_SAXContext* pTag)); + MOCK_METHOD4(OnTagData, + void(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos)); + MOCK_METHOD2(OnTagClose, void(CFX_SAXContext* pTag, uint32_t dwEndPos)); + MOCK_METHOD3(OnTagEnd, + void(CFX_SAXContext* pTag, + const ByteStringView& bsTagName, + uint32_t dwEndPos)); + MOCK_METHOD4(OnTargetData, + void(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos)); +}; + +} // namespace + +class CFX_SAXReaderTest : public testing::Test { + public: + void SetHandler(CFX_SAXReader::HandlerIface* handler) { + reader_.SetHandler(handler); + } + + bool StartParse(char* str) { + return reader_.StartParse( + pdfium::MakeRetain( + reinterpret_cast(str), strlen(str), false), + 0, static_cast(-1), + CFX_SaxParseMode_NotSkipSpace) >= 0; + } + + int32_t ContinueParse() { + int32_t ret; + do { + ret = reader_.ContinueParse(); + } while (ret >= 0 && ret < 100); + return ret; + } + + private: + CFX_SAXReader reader_; +}; + +TEST_F(CFX_SAXReaderTest, Null) { + char data[] = ""; + ASSERT_FALSE(StartParse(data)); +} + +TEST_F(CFX_SAXReaderTest, SimpleText) { + MockHandler mock; + SetHandler(&mock); + + char data[] = "clams"; + ASSERT_TRUE(StartParse(data)); + EXPECT_EQ(100, ContinueParse()); +} + +TEST_F(CFX_SAXReaderTest, SimpleTag) { + MockHandler mock; + EXPECT_CALL(mock, OnTagEnter(Eq("clams"), _, _)); + EXPECT_CALL(mock, OnTagBreak(_)); + SetHandler(&mock); + + char data[] = ""; + ASSERT_TRUE(StartParse(data)); + EXPECT_EQ(100, ContinueParse()); +} + +TEST_F(CFX_SAXReaderTest, AttributeTag) { + MockHandler mock; + EXPECT_CALL(mock, OnTagEnter(Eq("clams"), _, _)); + EXPECT_CALL(mock, OnTagAttribute(_, Eq("size"), Eq("small"))); + EXPECT_CALL(mock, OnTagAttribute(_, Eq("color"), Eq("red"))); + EXPECT_CALL(mock, OnTagBreak(_)); + SetHandler(&mock); + + char data[] = ""; + ASSERT_TRUE(StartParse(data)); + EXPECT_EQ(100, ContinueParse()); +} + +TEST_F(CFX_SAXReaderTest, AttributeEntityTag) { + MockHandler mock; + EXPECT_CALL(mock, OnTagEnter(Eq("clams"), _, _)); + EXPECT_CALL(mock, OnTagAttribute(_, Eq("predicate"), Eq("1 < 2"))); + EXPECT_CALL(mock, OnTagBreak(_)); + SetHandler(&mock); + + char data[] = ""; + ASSERT_TRUE(StartParse(data)); + EXPECT_EQ(100, ContinueParse()); +} + +TEST_F(CFX_SAXReaderTest, TextWithinTag) { + MockHandler mock; + EXPECT_CALL(mock, OnTagEnter(Eq("b"), _, _)); + EXPECT_CALL(mock, OnTagBreak(_)); + EXPECT_CALL(mock, OnTagData(_, _, Eq("biff"), _)); + EXPECT_CALL(mock, OnTagEnd(_, Eq("b"), _)); + SetHandler(&mock); + + char data[] = "biff"; + ASSERT_TRUE(StartParse(data)); + EXPECT_EQ(100, ContinueParse()); +} + +TEST_F(CFX_SAXReaderTest, bug_711459) { + char data[] = + "&ax;"; + ASSERT_TRUE(StartParse(data)); + EXPECT_EQ(100, ContinueParse()); +} diff --git a/core/fxcrt/xml/cfx_saxreaderhandler.cpp b/core/fxcrt/xml/cfx_saxreaderhandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d255ce924da22bc6f08a3a03e90ecd093dafa9f9 --- /dev/null +++ b/core/fxcrt/xml/cfx_saxreaderhandler.cpp @@ -0,0 +1,128 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_saxreaderhandler.h" + +#include + +#include "core/fxcrt/cfx_checksumcontext.h" + +CFX_SAXReaderHandler::CFX_SAXReaderHandler(CFX_ChecksumContext* pContext) + : m_pContext(pContext) { + ASSERT(m_pContext); +} + +CFX_SAXReaderHandler::~CFX_SAXReaderHandler() {} + +CFX_SAXContext* CFX_SAXReaderHandler::OnTagEnter( + const ByteStringView& bsTagName, + CFX_SAXItem::Type eType, + uint32_t dwStartPos) { + UpdateChecksum(true); + if (eType != CFX_SAXItem::Type::Tag && + eType != CFX_SAXItem::Type::Instruction) { + return nullptr; + } + + m_SAXContext.m_eNode = eType; + m_SAXContext.m_TextBuf << "<"; + if (eType == CFX_SAXItem::Type::Instruction) + m_SAXContext.m_TextBuf << "?"; + + m_SAXContext.m_TextBuf << bsTagName; + m_SAXContext.m_bsTagName = bsTagName; + return &m_SAXContext; +} + +void CFX_SAXReaderHandler::OnTagAttribute(CFX_SAXContext* pTag, + const ByteStringView& bsAttri, + const ByteStringView& bsValue) { + if (!pTag) + return; + pTag->m_TextBuf << " " << bsAttri << "=\"" << bsValue << "\""; +} + +void CFX_SAXReaderHandler::OnTagBreak(CFX_SAXContext* pTag) { + if (!pTag) + return; + + pTag->m_TextBuf << ">"; + UpdateChecksum(false); +} + +void CFX_SAXReaderHandler::OnTagData(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos) { + if (!pTag) + return; + + if (eType == CFX_SAXItem::Type::CharData) + pTag->m_TextBuf << "m_TextBuf << bsData; + if (eType == CFX_SAXItem::Type::CharData) + pTag->m_TextBuf << "]]>"; +} + +void CFX_SAXReaderHandler::OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) { + if (!pTag) + return; + + if (pTag->m_eNode == CFX_SAXItem::Type::Instruction) + pTag->m_TextBuf << "?>"; + else if (pTag->m_eNode == CFX_SAXItem::Type::Tag) + pTag->m_TextBuf << ">m_bsTagName.AsStringView() << ">"; + + UpdateChecksum(false); +} + +void CFX_SAXReaderHandler::OnTagEnd(CFX_SAXContext* pTag, + const ByteStringView& bsTagName, + uint32_t dwEndPos) { + if (!pTag) + return; + + pTag->m_TextBuf << ""; + UpdateChecksum(false); +} + +void CFX_SAXReaderHandler::OnTargetData(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos) { + if (!pTag && eType != CFX_SAXItem::Type::Comment) + return; + + if (eType == CFX_SAXItem::Type::Comment) { + m_SAXContext.m_TextBuf << ""; + UpdateChecksum(false); + } else { + pTag->m_TextBuf << " " << bsData; + } +} + +void CFX_SAXReaderHandler::UpdateChecksum(bool bCheckSpace) { + int32_t iLength = m_SAXContext.m_TextBuf.tellp(); + if (iLength < 1) + return; + + std::string sBuffer = m_SAXContext.m_TextBuf.str(); + const uint8_t* pBuffer = reinterpret_cast(sBuffer.c_str()); + bool bUpdata = true; + if (bCheckSpace) { + bUpdata = false; + for (int32_t i = 0; i < iLength; i++) { + bUpdata = (pBuffer[i] > 0x20); + if (bUpdata) + break; + } + } + if (bUpdata) + m_pContext->Update(ByteStringView(pBuffer, iLength)); + + m_SAXContext.m_TextBuf.str(""); +} diff --git a/core/fxcrt/xml/cfx_saxreaderhandler.h b/core/fxcrt/xml/cfx_saxreaderhandler.h new file mode 100644 index 0000000000000000000000000000000000000000..263008f1ff7eaa6bbb4e14c38882991d91e6e680 --- /dev/null +++ b/core/fxcrt/xml/cfx_saxreaderhandler.h @@ -0,0 +1,48 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_SAXREADERHANDLER_H_ +#define CORE_FXCRT_XML_CFX_SAXREADERHANDLER_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_saxcontext.h" +#include "core/fxcrt/xml/cfx_saxreader.h" + +class CFX_ChecksumContext; + +class CFX_SAXReaderHandler : public CFX_SAXReader::HandlerIface { + public: + explicit CFX_SAXReaderHandler(CFX_ChecksumContext* pContext); + ~CFX_SAXReaderHandler() override; + + CFX_SAXContext* OnTagEnter(const ByteStringView& bsTagName, + CFX_SAXItem::Type eType, + uint32_t dwStartPos) override; + void OnTagAttribute(CFX_SAXContext* pTag, + const ByteStringView& bsAttri, + const ByteStringView& bsValue) override; + void OnTagBreak(CFX_SAXContext* pTag) override; + void OnTagData(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos) override; + void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) override; + void OnTagEnd(CFX_SAXContext* pTag, + const ByteStringView& bsTagName, + uint32_t dwEndPos) override; + void OnTargetData(CFX_SAXContext* pTag, + CFX_SAXItem::Type eType, + const ByteStringView& bsData, + uint32_t dwStartPos) override; + + private: + void UpdateChecksum(bool bCheckSpace); + + CFX_ChecksumContext* m_pContext; + CFX_SAXContext m_SAXContext; +}; + +#endif // CORE_FXCRT_XML_CFX_SAXREADERHANDLER_H_ diff --git a/core/fxcrt/xml/cfx_xmlattributenode.cpp b/core/fxcrt/xml/cfx_xmlattributenode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6104747793cec8a3aa45c4db23f3cd8086734541 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlattributenode.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmlattributenode.h" + +#include "core/fxcrt/fx_extension.h" + +CFX_XMLAttributeNode::CFX_XMLAttributeNode(const WideString& name) + : CFX_XMLNode(), name_(name) { + ASSERT(name_.GetLength() > 0); +} + +CFX_XMLAttributeNode::~CFX_XMLAttributeNode() {} + +bool CFX_XMLAttributeNode::HasAttribute(const WideString& name) const { + return attrs_.find(name) != attrs_.end(); +} + +WideString CFX_XMLAttributeNode::GetString(const WideString& name) const { + auto it = attrs_.find(name); + return it != attrs_.end() ? it->second : WideString(); +} + +void CFX_XMLAttributeNode::SetString(const WideString& name, + const WideString& value) { + attrs_[name] = value; +} + +void CFX_XMLAttributeNode::RemoveAttribute(const WideString& name) { + attrs_.erase(name); +} diff --git a/core/fxcrt/xml/cfx_xmlattributenode.h b/core/fxcrt/xml/cfx_xmlattributenode.h new file mode 100644 index 0000000000000000000000000000000000000000..1ac9b84db232300fe6e7ba5f99692c9eea32667f --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlattributenode.h @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLATTRIBUTENODE_H_ +#define CORE_FXCRT_XML_CFX_XMLATTRIBUTENODE_H_ + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" + +class CFX_XMLAttributeNode : public CFX_XMLNode { + public: + explicit CFX_XMLAttributeNode(const WideString& name); + ~CFX_XMLAttributeNode() override; + + // CFX_XMLNode + FX_XMLNODETYPE GetType() const override = 0; + std::unique_ptr Clone() override = 0; + + WideString GetName() const { return name_; } + const std::map& GetAttributes() const { + return attrs_; + } + void SetAttributes(const std::map& attrs) { + attrs_ = attrs; + } + bool HasAttribute(const WideString& name) const; + + void SetString(const WideString& name, const WideString& value); + WideString GetString(const WideString& name) const; + + void RemoveAttribute(const WideString& name); + + private: + WideString name_; + std::map attrs_; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLATTRIBUTENODE_H_ diff --git a/core/fxcrt/xml/cfx_xmlchardata.cpp b/core/fxcrt/xml/cfx_xmlchardata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..902d139c99155d3072fbb9dd92029a4d104316a9 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlchardata.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmlchardata.h" + +#include "third_party/base/ptr_util.h" + +CFX_XMLCharData::CFX_XMLCharData(const WideString& wsCData) + : CFX_XMLText(wsCData) {} + +CFX_XMLCharData::~CFX_XMLCharData() {} + +FX_XMLNODETYPE CFX_XMLCharData::GetType() const { + return FX_XMLNODE_CharData; +} + +std::unique_ptr CFX_XMLCharData::Clone() { + return pdfium::MakeUnique(GetText()); +} diff --git a/core/fxcrt/xml/cfx_xmlchardata.h b/core/fxcrt/xml/cfx_xmlchardata.h new file mode 100644 index 0000000000000000000000000000000000000000..9a4710fa51d073b9a5cd140b109353cda859c4e0 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlchardata.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLCHARDATA_H_ +#define CORE_FXCRT_XML_CFX_XMLCHARDATA_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_xmltext.h" + +class CFX_XMLCharData : public CFX_XMLText { + public: + explicit CFX_XMLCharData(const WideString& wsCData); + ~CFX_XMLCharData() override; + + FX_XMLNODETYPE GetType() const override; + std::unique_ptr Clone() override; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLCHARDATA_H_ diff --git a/core/fxcrt/xml/cfx_xmldoc.cpp b/core/fxcrt/xml/cfx_xmldoc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36c3606017b0610dde68a1d4ac78a3d62507d73f --- /dev/null +++ b/core/fxcrt/xml/cfx_xmldoc.cpp @@ -0,0 +1,160 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmldoc.h" + +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CFX_XMLDoc::CFX_XMLDoc() + : m_iStatus(0), m_pRoot(pdfium::MakeUnique()) { + m_pRoot->InsertChildNode(new CFX_XMLInstruction(L"xml")); +} + +CFX_XMLDoc::~CFX_XMLDoc() {} + +bool CFX_XMLDoc::LoadXML(std::unique_ptr pXMLParser) { + if (!pXMLParser) + return false; + + m_iStatus = 0; + m_pStream.Reset(); + m_pRoot->DeleteChildren(); + m_pXMLParser = std::move(pXMLParser); + return true; +} + +int32_t CFX_XMLDoc::DoLoad() { + if (m_iStatus < 100) + m_iStatus = m_pXMLParser->DoParser(); + + return m_iStatus; +} + +void CFX_XMLDoc::CloseXML() { + m_pXMLParser.reset(); +} + +void CFX_XMLDoc::SaveXMLNode( + const RetainPtr& pXMLStream, + CFX_XMLNode* pINode) { + CFX_XMLNode* pNode = (CFX_XMLNode*)pINode; + switch (pNode->GetType()) { + case FX_XMLNODE_Instruction: { + CFX_XMLInstruction* pInstruction = (CFX_XMLInstruction*)pNode; + if (pInstruction->GetName().CompareNoCase(L"xml") == 0) { + WideString ws = L"GetCodePage(); + if (wCodePage == FX_CODEPAGE_UTF16LE) { + ws += L"UTF-16"; + } else if (wCodePage == FX_CODEPAGE_UTF16BE) { + ws += L"UTF-16be"; + } else { + ws += L"UTF-8"; + } + ws += L"\"?>"; + pXMLStream->WriteString(ws.AsStringView()); + } else { + WideString ws = + WideString::Format(L"GetName().c_str()); + pXMLStream->WriteString(ws.AsStringView()); + + for (auto it : pInstruction->GetAttributes()) { + WideString wsValue = it.second; + wsValue.Replace(L"&", L"&"); + wsValue.Replace(L"<", L"<"); + wsValue.Replace(L">", L">"); + wsValue.Replace(L"\'", L"'"); + wsValue.Replace(L"\"", L"""); + + ws = L" "; + ws += it.first; + ws += L"=\""; + ws += wsValue; + ws += L"\""; + pXMLStream->WriteString(ws.AsStringView()); + } + + for (auto target : pInstruction->GetTargetData()) { + ws = L" \""; + ws += target; + ws += L"\""; + pXMLStream->WriteString(ws.AsStringView()); + } + ws = L"?>"; + pXMLStream->WriteString(ws.AsStringView()); + } + break; + } + case FX_XMLNODE_Element: { + WideString ws; + ws = L"<"; + ws += static_cast(pNode)->GetName(); + pXMLStream->WriteString(ws.AsStringView()); + + for (auto it : static_cast(pNode)->GetAttributes()) { + WideString wsValue = it.second; + wsValue.Replace(L"&", L"&"); + wsValue.Replace(L"<", L"<"); + wsValue.Replace(L">", L">"); + wsValue.Replace(L"\'", L"'"); + wsValue.Replace(L"\"", L"""); + + ws = L" "; + ws += it.first; + ws += L"=\""; + ws += wsValue; + ws += L"\""; + pXMLStream->WriteString(ws.AsStringView()); + } + if (pNode->m_pChild) { + ws = L"\n>"; + pXMLStream->WriteString(ws.AsStringView()); + CFX_XMLNode* pChild = pNode->m_pChild; + while (pChild) { + SaveXMLNode(pXMLStream, static_cast(pChild)); + pChild = pChild->m_pNext; + } + ws = L"(pNode)->GetName(); + ws += L"\n>"; + } else { + ws = L"\n/>"; + } + pXMLStream->WriteString(ws.AsStringView()); + break; + } + case FX_XMLNODE_Text: { + WideString ws = static_cast(pNode)->GetText(); + ws.Replace(L"&", L"&"); + ws.Replace(L"<", L"<"); + ws.Replace(L">", L">"); + ws.Replace(L"\'", L"'"); + ws.Replace(L"\"", L"""); + pXMLStream->WriteString(ws.AsStringView()); + break; + } + case FX_XMLNODE_CharData: { + WideString ws = L"(pNode)->GetText(); + ws += L"]]>"; + pXMLStream->WriteString(ws.AsStringView()); + break; + } + case FX_XMLNODE_Unknown: + default: + break; + } +} diff --git a/core/fxcrt/xml/cfx_xmldoc.h b/core/fxcrt/xml/cfx_xmldoc.h new file mode 100644 index 0000000000000000000000000000000000000000..28de7fdba19a397b873b84f958dee3faa3833ff5 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmldoc.h @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLDOC_H_ +#define CORE_FXCRT_XML_CFX_XMLDOC_H_ + +#include + +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmlparser.h" + +class CFX_XMLDoc { + public: + CFX_XMLDoc(); + ~CFX_XMLDoc(); + + bool LoadXML(std::unique_ptr pXMLParser); + int32_t DoLoad(); + void CloseXML(); + + CFX_XMLNode* GetRoot() const { return m_pRoot.get(); } + void SaveXMLNode(const RetainPtr& pXMLStream, + CFX_XMLNode* pNode); + + private: + int32_t m_iStatus; + std::unique_ptr m_pRoot; + std::unique_ptr m_pXMLParser; + RetainPtr m_pStream; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLDOC_H_ diff --git a/core/fxcrt/xml/cfx_xmlelement.cpp b/core/fxcrt/xml/cfx_xmlelement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1317e9a72b9b4a3c752df5c708147b5bc6163caf --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlelement.cpp @@ -0,0 +1,103 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmlelement.h" + +#include + +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CFX_XMLElement::CFX_XMLElement(const WideString& wsTag) + : CFX_XMLAttributeNode(wsTag) {} + +CFX_XMLElement::~CFX_XMLElement() {} + +FX_XMLNODETYPE CFX_XMLElement::GetType() const { + return FX_XMLNODE_Element; +} + +std::unique_ptr CFX_XMLElement::Clone() { + auto pClone = pdfium::MakeUnique(GetName()); + pClone->SetAttributes(GetAttributes()); + + WideString wsText; + CFX_XMLNode* pChild = m_pChild; + while (pChild) { + switch (pChild->GetType()) { + case FX_XMLNODE_Text: + wsText += static_cast(pChild)->GetText(); + break; + default: + break; + } + pChild = pChild->m_pNext; + } + pClone->SetTextData(wsText); + return std::move(pClone); +} + +WideString CFX_XMLElement::GetLocalTagName() const { + auto pos = GetName().Find(L':'); + return pos.has_value() + ? GetName().Right(GetName().GetLength() - pos.value() - 1) + : GetName(); +} + +WideString CFX_XMLElement::GetNamespacePrefix() const { + auto pos = GetName().Find(L':'); + return pos.has_value() ? GetName().Left(pos.value()) : WideString(); +} + +WideString CFX_XMLElement::GetNamespaceURI() const { + WideString wsAttri(L"xmlns"); + WideString wsPrefix = GetNamespacePrefix(); + if (wsPrefix.GetLength() > 0) { + wsAttri += L":"; + wsAttri += wsPrefix; + } + + auto* pNode = static_cast(this); + while (pNode) { + if (pNode->GetType() != FX_XMLNODE_Element) + break; + + auto* pElement = static_cast(pNode); + if (!pElement->HasAttribute(wsAttri)) { + pNode = pNode->GetNodeItem(CFX_XMLNode::Parent); + continue; + } + return pElement->GetString(wsAttri); + } + return WideString(); +} + +WideString CFX_XMLElement::GetTextData() const { + CFX_WideTextBuf buffer; + CFX_XMLNode* pChild = m_pChild; + while (pChild) { + switch (pChild->GetType()) { + case FX_XMLNODE_Text: + case FX_XMLNODE_CharData: + buffer << static_cast(pChild)->GetText(); + break; + default: + break; + } + pChild = pChild->m_pNext; + } + return buffer.MakeString(); +} + +void CFX_XMLElement::SetTextData(const WideString& wsText) { + if (wsText.GetLength() < 1) + return; + InsertChildNode(new CFX_XMLText(wsText)); +} diff --git a/core/fxcrt/xml/cfx_xmlelement.h b/core/fxcrt/xml/cfx_xmlelement.h new file mode 100644 index 0000000000000000000000000000000000000000..59e3af6a4472c81fabc8ff274bad118dda6342a9 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlelement.h @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLELEMENT_H_ +#define CORE_FXCRT_XML_CFX_XMLELEMENT_H_ + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_xmlattributenode.h" + +class CFX_XMLElement : public CFX_XMLAttributeNode { + public: + explicit CFX_XMLElement(const WideString& wsTag); + ~CFX_XMLElement() override; + + // CFX_XMLNode + FX_XMLNODETYPE GetType() const override; + std::unique_ptr Clone() override; + + WideString GetLocalTagName() const; + WideString GetNamespacePrefix() const; + WideString GetNamespaceURI() const; + + WideString GetTextData() const; + void SetTextData(const WideString& wsText); +}; + +#endif // CORE_FXCRT_XML_CFX_XMLELEMENT_H_ diff --git a/core/fxcrt/xml/cfx_xmlinstruction.cpp b/core/fxcrt/xml/cfx_xmlinstruction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75a4a2eec6ee415bb74d140824704775a69b9398 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlinstruction.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmlinstruction.h" + +#include + +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CFX_XMLInstruction::CFX_XMLInstruction(const WideString& wsTarget) + : CFX_XMLAttributeNode(wsTarget) {} + +CFX_XMLInstruction::~CFX_XMLInstruction() {} + +FX_XMLNODETYPE CFX_XMLInstruction::GetType() const { + return FX_XMLNODE_Instruction; +} + +std::unique_ptr CFX_XMLInstruction::Clone() { + auto pClone = pdfium::MakeUnique(GetName()); + pClone->SetAttributes(GetAttributes()); + pClone->m_TargetData = m_TargetData; + return std::move(pClone); +} + +void CFX_XMLInstruction::AppendData(const WideString& wsData) { + m_TargetData.push_back(wsData); +} + +void CFX_XMLInstruction::RemoveData(int32_t index) { + if (pdfium::IndexInBounds(m_TargetData, index)) + m_TargetData.erase(m_TargetData.begin() + index); +} diff --git a/core/fxcrt/xml/cfx_xmlinstruction.h b/core/fxcrt/xml/cfx_xmlinstruction.h new file mode 100644 index 0000000000000000000000000000000000000000..ff27dae3a42cab5c6faf5467b9064316ee939d3f --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlinstruction.h @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLINSTRUCTION_H_ +#define CORE_FXCRT_XML_CFX_XMLINSTRUCTION_H_ + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_xmlattributenode.h" + +class CFX_XMLInstruction : public CFX_XMLAttributeNode { + public: + explicit CFX_XMLInstruction(const WideString& wsTarget); + ~CFX_XMLInstruction() override; + + // CFX_XMLNode + FX_XMLNODETYPE GetType() const override; + std::unique_ptr Clone() override; + + const std::vector& GetTargetData() const { return m_TargetData; } + void AppendData(const WideString& wsData); + void RemoveData(int32_t index); + + private: + std::vector m_TargetData; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLINSTRUCTION_H_ diff --git a/core/fxcrt/xml/cfx_xmlnode.cpp b/core/fxcrt/xml/cfx_xmlnode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41889e2d1c74140e230cc4c3d6661855e7e60ad7 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlnode.cpp @@ -0,0 +1,439 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmlnode.h" + +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "third_party/base/stl_util.h" + +CFX_XMLNode::CFX_XMLNode() + : m_pParent(nullptr), + m_pChild(nullptr), + m_pPrior(nullptr), + m_pNext(nullptr) {} + +FX_XMLNODETYPE CFX_XMLNode::GetType() const { + return FX_XMLNODE_Unknown; +} + +CFX_XMLNode::~CFX_XMLNode() { + DeleteChildren(); +} + +void CFX_XMLNode::DeleteChildren() { + CFX_XMLNode* pChild = m_pChild; + while (pChild) { + CFX_XMLNode* pNext = pChild->m_pNext; + delete pChild; + pChild = pNext; + } + m_pChild = nullptr; +} + +int32_t CFX_XMLNode::CountChildNodes() const { + int32_t iCount = 0; + CFX_XMLNode* pChild = m_pChild; + while (pChild) { + iCount++; + pChild = pChild->m_pNext; + } + return iCount; +} + +CFX_XMLNode* CFX_XMLNode::GetChildNode(int32_t index) const { + CFX_XMLNode* pChild = m_pChild; + while (pChild) { + if (index == 0) { + return pChild; + } + index--; + pChild = pChild->m_pNext; + } + return nullptr; +} + +int32_t CFX_XMLNode::GetChildNodeIndex(CFX_XMLNode* pNode) const { + int32_t index = 0; + CFX_XMLNode* pChild = m_pChild; + while (pChild) { + if (pChild == pNode) { + return index; + } + index++; + pChild = pChild->m_pNext; + } + return -1; +} + +CFX_XMLNode* CFX_XMLNode::GetPath(const wchar_t* pPath, + int32_t iLength, + bool bQualifiedName) const { + ASSERT(pPath); + if (iLength < 0) { + iLength = wcslen(pPath); + } + if (iLength == 0) { + return nullptr; + } + WideString csPath; + const wchar_t* pStart = pPath; + const wchar_t* pEnd = pPath + iLength; + wchar_t ch; + while (pStart < pEnd) { + ch = *pStart++; + if (ch == L'/') + break; + csPath += ch; + } + iLength -= pStart - pPath; + CFX_XMLNode* pFind = nullptr; + if (csPath.GetLength() < 1) { + pFind = GetNodeItem(CFX_XMLNode::Root); + } else if (csPath.Compare(L"..") == 0) { + pFind = m_pParent; + } else if (csPath.Compare(L".") == 0) { + pFind = (CFX_XMLNode*)this; + } else { + WideString wsTag; + CFX_XMLNode* pNode = m_pChild; + while (pNode) { + if (pNode->GetType() == FX_XMLNODE_Element) { + if (bQualifiedName) + wsTag = static_cast(pNode)->GetName(); + else + wsTag = static_cast(pNode)->GetLocalTagName(); + + if (wsTag.Compare(csPath) == 0) { + if (iLength < 1) + pFind = pNode; + else + pFind = pNode->GetPath(pStart, iLength, bQualifiedName); + + if (pFind) + return pFind; + } + } + pNode = pNode->m_pNext; + } + } + if (!pFind || iLength < 1) + return pFind; + return pFind->GetPath(pStart, iLength, bQualifiedName); +} + +int32_t CFX_XMLNode::InsertChildNode(CFX_XMLNode* pNode, int32_t index) { + pNode->m_pParent = this; + if (!m_pChild) { + m_pChild = pNode; + pNode->m_pPrior = nullptr; + pNode->m_pNext = nullptr; + return 0; + } + if (index == 0) { + pNode->m_pNext = m_pChild; + pNode->m_pPrior = nullptr; + m_pChild->m_pPrior = pNode; + m_pChild = pNode; + return 0; + } + int32_t iCount = 0; + CFX_XMLNode* pFind = m_pChild; + while (++iCount != index && pFind->m_pNext) { + pFind = pFind->m_pNext; + } + pNode->m_pPrior = pFind; + pNode->m_pNext = pFind->m_pNext; + if (pFind->m_pNext) + pFind->m_pNext->m_pPrior = pNode; + pFind->m_pNext = pNode; + return iCount; +} + +void CFX_XMLNode::RemoveChildNode(CFX_XMLNode* pNode) { + ASSERT(m_pChild && pNode); + if (m_pChild == pNode) { + m_pChild = pNode->m_pNext; + } else { + pNode->m_pPrior->m_pNext = pNode->m_pNext; + } + if (pNode->m_pNext) + pNode->m_pNext->m_pPrior = pNode->m_pPrior; + pNode->m_pParent = nullptr; + pNode->m_pNext = nullptr; + pNode->m_pPrior = nullptr; +} + +CFX_XMLNode* CFX_XMLNode::GetNodeItem(CFX_XMLNode::NodeItem eItem) const { + switch (eItem) { + case CFX_XMLNode::Root: { + CFX_XMLNode* pParent = (CFX_XMLNode*)this; + while (pParent->m_pParent) { + pParent = pParent->m_pParent; + } + return pParent; + } + case CFX_XMLNode::Parent: + return m_pParent; + case CFX_XMLNode::FirstSibling: { + CFX_XMLNode* pItem = (CFX_XMLNode*)this; + while (pItem->m_pPrior) { + pItem = pItem->m_pPrior; + } + return pItem == (CFX_XMLNode*)this ? nullptr : pItem; + } + case CFX_XMLNode::PriorSibling: + return m_pPrior; + case CFX_XMLNode::NextSibling: + return m_pNext; + case CFX_XMLNode::LastSibling: { + CFX_XMLNode* pItem = (CFX_XMLNode*)this; + while (pItem->m_pNext) + pItem = pItem->m_pNext; + return pItem == (CFX_XMLNode*)this ? nullptr : pItem; + } + case CFX_XMLNode::FirstNeighbor: { + CFX_XMLNode* pParent = (CFX_XMLNode*)this; + while (pParent->m_pParent) + pParent = pParent->m_pParent; + return pParent == (CFX_XMLNode*)this ? nullptr : pParent; + } + case CFX_XMLNode::PriorNeighbor: { + if (!m_pPrior) + return m_pParent; + + CFX_XMLNode* pItem = m_pPrior; + while (pItem->m_pChild) { + pItem = pItem->m_pChild; + while (pItem->m_pNext) + pItem = pItem->m_pNext; + } + return pItem; + } + case CFX_XMLNode::NextNeighbor: { + if (m_pChild) + return m_pChild; + if (m_pNext) + return m_pNext; + CFX_XMLNode* pItem = m_pParent; + while (pItem) { + if (pItem->m_pNext) + return pItem->m_pNext; + pItem = pItem->m_pParent; + } + return nullptr; + } + case CFX_XMLNode::LastNeighbor: { + CFX_XMLNode* pItem = (CFX_XMLNode*)this; + while (pItem->m_pParent) { + pItem = pItem->m_pParent; + } + while (true) { + while (pItem->m_pNext) + pItem = pItem->m_pNext; + if (!pItem->m_pChild) + break; + pItem = pItem->m_pChild; + } + return pItem == (CFX_XMLNode*)this ? nullptr : pItem; + } + case CFX_XMLNode::FirstChild: + return m_pChild; + case CFX_XMLNode::LastChild: { + if (!m_pChild) + return nullptr; + + CFX_XMLNode* pChild = m_pChild; + while (pChild->m_pNext) + pChild = pChild->m_pNext; + return pChild; + } + default: + break; + } + return nullptr; +} + +int32_t CFX_XMLNode::GetNodeLevel() const { + int32_t iLevel = 0; + const CFX_XMLNode* pItem = m_pParent; + while (pItem) { + iLevel++; + pItem = pItem->m_pParent; + } + return iLevel; +} + +bool CFX_XMLNode::InsertNodeItem(CFX_XMLNode::NodeItem eItem, + CFX_XMLNode* pNode) { + switch (eItem) { + case CFX_XMLNode::NextSibling: { + pNode->m_pParent = m_pParent; + pNode->m_pNext = m_pNext; + pNode->m_pPrior = this; + if (m_pNext) { + m_pNext->m_pPrior = pNode; + } + m_pNext = pNode; + return true; + } + case CFX_XMLNode::PriorSibling: { + pNode->m_pParent = m_pParent; + pNode->m_pNext = this; + pNode->m_pPrior = m_pPrior; + if (m_pPrior) { + m_pPrior->m_pNext = pNode; + } else if (m_pParent) { + m_pParent->m_pChild = pNode; + } + m_pPrior = pNode; + return true; + } + default: + return false; + } +} + +CFX_XMLNode* CFX_XMLNode::RemoveNodeItem(CFX_XMLNode::NodeItem eItem) { + CFX_XMLNode* pNode = nullptr; + switch (eItem) { + case CFX_XMLNode::NextSibling: + if (m_pNext) { + pNode = m_pNext; + m_pNext = pNode->m_pNext; + if (m_pNext) { + m_pNext->m_pPrior = this; + } + pNode->m_pParent = nullptr; + pNode->m_pNext = nullptr; + pNode->m_pPrior = nullptr; + } + break; + default: + break; + } + return pNode; +} + +std::unique_ptr CFX_XMLNode::Clone() { + return nullptr; +} + +void CFX_XMLNode::SaveXMLNode( + const RetainPtr& pXMLStream) { + CFX_XMLNode* pNode = (CFX_XMLNode*)this; + switch (pNode->GetType()) { + case FX_XMLNODE_Instruction: { + WideString ws; + CFX_XMLInstruction* pInstruction = (CFX_XMLInstruction*)pNode; + if (pInstruction->GetName().CompareNoCase(L"xml") == 0) { + ws = L"GetCodePage(); + if (wCodePage == FX_CODEPAGE_UTF16LE) { + ws += L"UTF-16"; + } else if (wCodePage == FX_CODEPAGE_UTF16BE) { + ws += L"UTF-16be"; + } else { + ws += L"UTF-8"; + } + ws += L"\"?>"; + pXMLStream->WriteString(ws.AsStringView()); + } else { + ws = WideString::Format(L"GetName().c_str()); + pXMLStream->WriteString(ws.AsStringView()); + + for (auto it : pInstruction->GetAttributes()) { + WideString wsValue = it.second; + wsValue.Replace(L"&", L"&"); + wsValue.Replace(L"<", L"<"); + wsValue.Replace(L">", L">"); + wsValue.Replace(L"\'", L"'"); + wsValue.Replace(L"\"", L"""); + + ws = L" "; + ws += it.first; + ws += L"=\""; + ws += wsValue; + ws += L"\""; + pXMLStream->WriteString(ws.AsStringView()); + } + + for (auto target : pInstruction->GetTargetData()) { + ws = L" \""; + ws += target; + ws += L"\""; + pXMLStream->WriteString(ws.AsStringView()); + } + ws = L"?>"; + pXMLStream->WriteString(ws.AsStringView()); + } + break; + } + case FX_XMLNODE_Element: { + WideString ws; + ws = L"<"; + ws += static_cast(pNode)->GetName(); + pXMLStream->WriteString(ws.AsStringView()); + + for (auto it : static_cast(pNode)->GetAttributes()) { + WideString wsValue = it.second; + wsValue.Replace(L"&", L"&"); + wsValue.Replace(L"<", L"<"); + wsValue.Replace(L">", L">"); + wsValue.Replace(L"\'", L"'"); + wsValue.Replace(L"\"", L"""); + + ws = L" "; + ws += it.first; + ws += L"=\""; + ws += wsValue; + ws += L"\""; + pXMLStream->WriteString(ws.AsStringView()); + } + if (pNode->m_pChild) { + ws = L"\n>"; + pXMLStream->WriteString(ws.AsStringView()); + CFX_XMLNode* pChild = pNode->m_pChild; + while (pChild) { + pChild->SaveXMLNode(pXMLStream); + pChild = pChild->m_pNext; + } + ws = L"(pNode)->GetName(); + ws += L"\n>"; + } else { + ws = L"\n/>"; + } + pXMLStream->WriteString(ws.AsStringView()); + break; + } + case FX_XMLNODE_Text: { + WideString ws = static_cast(pNode)->GetText(); + ws.Replace(L"&", L"&"); + ws.Replace(L"<", L"<"); + ws.Replace(L">", L">"); + ws.Replace(L"\'", L"'"); + ws.Replace(L"\"", L"""); + pXMLStream->WriteString(ws.AsStringView()); + break; + } + case FX_XMLNODE_CharData: { + WideString ws = L"(pNode)->GetText(); + ws += L"]]>"; + pXMLStream->WriteString(ws.AsStringView()); + break; + } + case FX_XMLNODE_Unknown: + default: + break; + } +} diff --git a/core/fxcrt/xml/cfx_xmlnode.h b/core/fxcrt/xml/cfx_xmlnode.h new file mode 100644 index 0000000000000000000000000000000000000000..278b3bf15a7e35cf28a90648b31fa9ed28154f46 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlnode.h @@ -0,0 +1,75 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLNODE_H_ +#define CORE_FXCRT_XML_CFX_XMLNODE_H_ + +#include + +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/retain_ptr.h" + +enum FX_XMLNODETYPE { + FX_XMLNODE_Unknown = 0, + FX_XMLNODE_Instruction, + FX_XMLNODE_Element, + FX_XMLNODE_Text, + FX_XMLNODE_CharData, +}; + +struct FX_XMLNODE { + int32_t iNodeNum; + FX_XMLNODETYPE eNodeType; +}; + +class CFX_XMLNode { + public: + enum NodeItem { + Root = 0, + Parent, + FirstSibling, + PriorSibling, + NextSibling, + LastSibling, + FirstNeighbor, + PriorNeighbor, + NextNeighbor, + LastNeighbor, + FirstChild, + LastChild + }; + + CFX_XMLNode(); + virtual ~CFX_XMLNode(); + + virtual FX_XMLNODETYPE GetType() const; + virtual std::unique_ptr Clone(); + + int32_t CountChildNodes() const; + CFX_XMLNode* GetChildNode(int32_t index) const; + int32_t GetChildNodeIndex(CFX_XMLNode* pNode) const; + int32_t InsertChildNode(CFX_XMLNode* pNode, int32_t index = -1); + void RemoveChildNode(CFX_XMLNode* pNode); + void DeleteChildren(); + + CFX_XMLNode* GetPath(const wchar_t* pPath, + int32_t iLength = -1, + bool bQualifiedName = true) const; + + int32_t GetNodeLevel() const; + CFX_XMLNode* GetNodeItem(CFX_XMLNode::NodeItem eItem) const; + bool InsertNodeItem(CFX_XMLNode::NodeItem eItem, CFX_XMLNode* pNode); + CFX_XMLNode* RemoveNodeItem(CFX_XMLNode::NodeItem eItem); + + void SaveXMLNode(const RetainPtr& pXMLStream); + + CFX_XMLNode* m_pParent; + CFX_XMLNode* m_pChild; + CFX_XMLNode* m_pPrior; + CFX_XMLNode* m_pNext; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLNODE_H_ diff --git a/core/fxcrt/xml/cfx_xmlparser.cpp b/core/fxcrt/xml/cfx_xmlparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f08b06255a7666a02bce35d094e93e5fe141c19 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlparser.cpp @@ -0,0 +1,167 @@ +// Copyright 2016 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 "core/fxcrt/xml/cfx_xmlparser.h" + +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "third_party/base/ptr_util.h" + +CFX_XMLParser::CFX_XMLParser(CFX_XMLNode* pParent, + const RetainPtr& pStream) + : m_nElementStart(0), + m_dwCheckStatus(0), + m_dwCurrentCheckStatus(0), + m_pStream(pStream), + m_pParser(pdfium::MakeUnique(m_pStream)), + m_pParent(pParent), + m_pChild(nullptr), + m_syntaxParserResult(FX_XmlSyntaxResult::None) { + ASSERT(m_pParent && m_pStream); + m_NodeStack.push(m_pParent); +} + +CFX_XMLParser::~CFX_XMLParser() {} + +int32_t CFX_XMLParser::DoParser() { + if (m_syntaxParserResult == FX_XmlSyntaxResult::Error) + return -1; + if (m_syntaxParserResult == FX_XmlSyntaxResult::EndOfString) + return 100; + + int32_t iCount = 0; + while (true) { + m_syntaxParserResult = m_pParser->DoSyntaxParse(); + switch (m_syntaxParserResult) { + case FX_XmlSyntaxResult::InstructionOpen: + break; + case FX_XmlSyntaxResult::InstructionClose: + if (m_pChild) { + if (m_pChild->GetType() != FX_XMLNODE_Instruction) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + break; + } + } + m_pChild = m_pParent; + break; + case FX_XmlSyntaxResult::ElementOpen: + if (m_dwCheckStatus != 0x03 && m_NodeStack.size() == 2) + m_nElementStart = m_pParser->GetCurrentPos() - 1; + break; + case FX_XmlSyntaxResult::ElementBreak: + break; + case FX_XmlSyntaxResult::ElementClose: + if (m_pChild->GetType() != FX_XMLNODE_Element) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + break; + } + m_ws1 = m_pParser->GetTagName(); + m_ws2 = static_cast(m_pChild)->GetName(); + if (m_ws1.GetLength() > 0 && m_ws1 != m_ws2) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + break; + } + if (!m_NodeStack.empty()) + m_NodeStack.pop(); + if (m_NodeStack.empty()) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + break; + } + if (m_dwCurrentCheckStatus != 0 && m_NodeStack.size() == 2) { + m_nSize[m_dwCurrentCheckStatus - 1] = + m_pParser->GetCurrentBinaryPos() - + m_nStart[m_dwCurrentCheckStatus - 1]; + m_dwCurrentCheckStatus = 0; + } + m_pParent = m_NodeStack.top(); + m_pChild = m_pParent; + iCount++; + break; + case FX_XmlSyntaxResult::TargetName: + m_ws1 = m_pParser->GetTargetName(); + if (m_ws1 == L"originalXFAVersion" || m_ws1 == L"acrobat") { + m_pChild = new CFX_XMLInstruction(m_ws1); + m_pParent->InsertChildNode(m_pChild); + } else { + m_pChild = nullptr; + } + m_ws1.clear(); + break; + case FX_XmlSyntaxResult::TagName: + m_ws1 = m_pParser->GetTagName(); + m_pChild = new CFX_XMLElement(m_ws1); + m_pParent->InsertChildNode(m_pChild); + m_NodeStack.push(m_pChild); + m_pParent = m_pChild; + + if (m_dwCheckStatus != 0x03 && m_NodeStack.size() == 3) { + WideString wsTag = + static_cast(m_pChild)->GetLocalTagName(); + if (wsTag == L"template") { + m_dwCheckStatus |= 0x01; + m_dwCurrentCheckStatus = 0x01; + m_nStart[0] = m_pParser->GetCurrentBinaryPos() - + (m_pParser->GetCurrentPos() - m_nElementStart); + } else if (wsTag == L"datasets") { + m_dwCheckStatus |= 0x02; + m_dwCurrentCheckStatus = 0x02; + m_nStart[1] = m_pParser->GetCurrentBinaryPos() - + (m_pParser->GetCurrentPos() - m_nElementStart); + } + } + break; + case FX_XmlSyntaxResult::AttriName: + m_ws1 = m_pParser->GetAttributeName(); + break; + case FX_XmlSyntaxResult::AttriValue: + if (m_pChild) { + m_ws2 = m_pParser->GetAttributeName(); + if (m_pChild->GetType() == FX_XMLNODE_Element) + static_cast(m_pChild)->SetString(m_ws1, m_ws2); + } + m_ws1.clear(); + break; + case FX_XmlSyntaxResult::Text: + m_ws1 = m_pParser->GetTextData(); + m_pChild = new CFX_XMLText(m_ws1); + m_pParent->InsertChildNode(m_pChild); + m_pChild = m_pParent; + break; + case FX_XmlSyntaxResult::CData: + m_ws1 = m_pParser->GetTextData(); + m_pChild = new CFX_XMLCharData(m_ws1); + m_pParent->InsertChildNode(m_pChild); + m_pChild = m_pParent; + break; + case FX_XmlSyntaxResult::TargetData: + if (m_pChild) { + if (m_pChild->GetType() != FX_XMLNODE_Instruction) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + break; + } + auto* instruction = static_cast(m_pChild); + if (!m_ws1.IsEmpty()) + instruction->AppendData(m_ws1); + instruction->AppendData(m_pParser->GetTargetData()); + } + m_ws1.clear(); + break; + default: + break; + } + if (m_syntaxParserResult == FX_XmlSyntaxResult::Error || + m_syntaxParserResult == FX_XmlSyntaxResult::EndOfString) { + break; + } + } + return (m_syntaxParserResult == FX_XmlSyntaxResult::Error || + m_NodeStack.size() != 1) + ? -1 + : m_pParser->GetStatus(); +} diff --git a/core/fxcrt/xml/cfx_xmlparser.h b/core/fxcrt/xml/cfx_xmlparser.h new file mode 100644 index 0000000000000000000000000000000000000000..0038f6d9b20d25c0434ffe26d4dbae5b3b323745 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlparser.h @@ -0,0 +1,46 @@ +// Copyright 2016 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 CORE_FXCRT_XML_CFX_XMLPARSER_H_ +#define CORE_FXCRT_XML_CFX_XMLPARSER_H_ + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/xml/cfx_xmlsyntaxparser.h" + +class CFX_XMLElement; +class CFX_XMLNode; +class CFX_SeekableStreamProxy; + +class CFX_XMLParser { + public: + CFX_XMLParser(CFX_XMLNode* pParent, + const RetainPtr& pStream); + ~CFX_XMLParser(); + + int32_t DoParser(); + + FX_FILESIZE m_nStart[2]; + size_t m_nSize[2]; + FX_FILESIZE m_nElementStart; + uint16_t m_dwCheckStatus; + uint16_t m_dwCurrentCheckStatus; + + private: + RetainPtr m_pStream; + std::unique_ptr m_pParser; + CFX_XMLNode* m_pParent; + CFX_XMLNode* m_pChild; + std::stack m_NodeStack; + WideString m_ws1; + WideString m_ws2; + FX_XmlSyntaxResult m_syntaxParserResult; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLPARSER_H_ diff --git a/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp b/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0cc1a6ac9c71cbbb71e1838994d1fed2373002b --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp @@ -0,0 +1,694 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmlsyntaxparser.h" + +#include +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" + +namespace { + +const uint32_t kMaxCharRange = 0x10ffff; + +bool IsXMLWhiteSpace(wchar_t ch) { + return ch == L' ' || ch == 0x0A || ch == 0x0D || ch == 0x09; +} + +struct FX_XMLNAMECHAR { + uint16_t wStart; + uint16_t wEnd; + bool bStartChar; +}; + +const FX_XMLNAMECHAR g_XMLNameChars[] = { + {L'-', L'.', false}, {L'0', L'9', false}, {L':', L':', false}, + {L'A', L'Z', true}, {L'_', L'_', true}, {L'a', L'z', true}, + {0xB7, 0xB7, false}, {0xC0, 0xD6, true}, {0xD8, 0xF6, true}, + {0xF8, 0x02FF, true}, {0x0300, 0x036F, false}, {0x0370, 0x037D, true}, + {0x037F, 0x1FFF, true}, {0x200C, 0x200D, true}, {0x203F, 0x2040, false}, + {0x2070, 0x218F, true}, {0x2C00, 0x2FEF, true}, {0x3001, 0xD7FF, true}, + {0xF900, 0xFDCF, true}, {0xFDF0, 0xFFFD, true}, +}; + + +int32_t GetUTF8EncodeLength(const std::vector& src, + FX_FILESIZE iSrcLen) { + uint32_t unicode = 0; + int32_t iDstNum = 0; + const wchar_t* pSrc = src.data(); + while (iSrcLen-- > 0) { + unicode = *pSrc++; + int nbytes = 0; + if ((uint32_t)unicode < 0x80) { + nbytes = 1; + } else if ((uint32_t)unicode < 0x800) { + nbytes = 2; + } else if ((uint32_t)unicode < 0x10000) { + nbytes = 3; + } else if ((uint32_t)unicode < 0x200000) { + nbytes = 4; + } else if ((uint32_t)unicode < 0x4000000) { + nbytes = 5; + } else { + nbytes = 6; + } + iDstNum += nbytes; + } + return iDstNum; +} + +} // namespace + +// static +bool CFX_XMLSyntaxParser::IsXMLNameChar(wchar_t ch, bool bFirstChar) { + auto* it = std::lower_bound( + std::begin(g_XMLNameChars), std::end(g_XMLNameChars), ch, + [](const FX_XMLNAMECHAR& arg, wchar_t ch) { return arg.wEnd < ch; }); + return it != std::end(g_XMLNameChars) && ch >= it->wStart && + (!bFirstChar || it->bStartChar); +} + +CFX_XMLSyntaxParser::CFX_XMLSyntaxParser( + const RetainPtr& pStream) + : m_pStream(pStream), + m_iXMLPlaneSize(32 * 1024), + m_iCurrentPos(0), + m_iCurrentNodeNum(-1), + m_iLastNodeNum(-1), + m_iParsedBytes(0), + m_ParsedChars(0), + m_iBufferChars(0), + m_bEOS(false), + m_Start(0), + m_End(0), + m_iAllocStep(m_BlockBuffer.GetAllocStep()), + m_pCurrentBlock(nullptr), + m_iIndexInBlock(0), + m_iTextDataLength(0), + m_syntaxParserResult(FX_XmlSyntaxResult::None), + m_syntaxParserState(FDE_XmlSyntaxState::Text), + m_wQuotationMark(0), + m_iEntityStart(-1) { + ASSERT(pStream); + + m_CurNode.iNodeNum = -1; + m_CurNode.eNodeType = FX_XMLNODE_Unknown; + + m_iXMLPlaneSize = + std::min(m_iXMLPlaneSize, + pdfium::base::checked_cast(m_pStream->GetLength())); + m_iCurrentPos = m_pStream->GetBOMLength(); + + FX_SAFE_SIZE_T alloc_size_safe = m_iXMLPlaneSize; + alloc_size_safe += 1; // For NUL. + if (!alloc_size_safe.IsValid() || alloc_size_safe.ValueOrDie() <= 0) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return; + } + + m_Buffer.resize(pdfium::base::ValueOrDieForType(alloc_size_safe)); + + m_BlockBuffer.InitBuffer(); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); +} + +CFX_XMLSyntaxParser::~CFX_XMLSyntaxParser() {} + +FX_XmlSyntaxResult CFX_XMLSyntaxParser::DoSyntaxParse() { + if (m_syntaxParserResult == FX_XmlSyntaxResult::Error || + m_syntaxParserResult == FX_XmlSyntaxResult::EndOfString) { + return m_syntaxParserResult; + } + + FX_FILESIZE iStreamLength = m_pStream->GetLength(); + FX_FILESIZE iPos; + + FX_XmlSyntaxResult syntaxParserResult = FX_XmlSyntaxResult::None; + while (true) { + if (m_Start >= m_End) { + if (m_bEOS || m_iCurrentPos >= iStreamLength) { + m_syntaxParserResult = FX_XmlSyntaxResult::EndOfString; + return m_syntaxParserResult; + } + m_ParsedChars += m_End; + m_iParsedBytes = m_iCurrentPos; + if (m_pStream->GetPosition() != m_iCurrentPos) + m_pStream->Seek(CFX_SeekableStreamProxy::From::Begin, m_iCurrentPos); + + m_iBufferChars = + m_pStream->ReadString(m_Buffer.data(), m_iXMLPlaneSize, &m_bEOS); + iPos = m_pStream->GetPosition(); + if (m_iBufferChars < 1) { + m_iCurrentPos = iStreamLength; + m_syntaxParserResult = FX_XmlSyntaxResult::EndOfString; + return m_syntaxParserResult; + } + m_iCurrentPos = iPos; + m_Start = 0; + m_End = m_iBufferChars; + } + + while (m_Start < m_End) { + wchar_t ch = m_Buffer[m_Start]; + switch (m_syntaxParserState) { + case FDE_XmlSyntaxState::Text: + if (ch == L'<') { + if (!m_BlockBuffer.IsEmpty()) { + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_iEntityStart = -1; + syntaxParserResult = FX_XmlSyntaxResult::Text; + } else { + m_Start++; + m_syntaxParserState = FDE_XmlSyntaxState::Node; + } + } else { + ParseTextChar(ch); + } + break; + case FDE_XmlSyntaxState::Node: + if (ch == L'!') { + m_Start++; + m_syntaxParserState = FDE_XmlSyntaxState::SkipCommentOrDecl; + } else if (ch == L'/') { + m_Start++; + m_syntaxParserState = FDE_XmlSyntaxState::CloseElement; + } else if (ch == L'?') { + m_iLastNodeNum++; + m_iCurrentNodeNum = m_iLastNodeNum; + m_CurNode.iNodeNum = m_iLastNodeNum; + m_CurNode.eNodeType = FX_XMLNODE_Instruction; + m_XMLNodeStack.push(m_CurNode); + m_Start++; + m_syntaxParserState = FDE_XmlSyntaxState::Target; + syntaxParserResult = FX_XmlSyntaxResult::InstructionOpen; + } else { + m_iLastNodeNum++; + m_iCurrentNodeNum = m_iLastNodeNum; + m_CurNode.iNodeNum = m_iLastNodeNum; + m_CurNode.eNodeType = FX_XMLNODE_Element; + m_XMLNodeStack.push(m_CurNode); + m_syntaxParserState = FDE_XmlSyntaxState::Tag; + syntaxParserResult = FX_XmlSyntaxResult::ElementOpen; + } + break; + case FDE_XmlSyntaxState::Target: + case FDE_XmlSyntaxState::Tag: + if (!IsXMLNameChar(ch, m_BlockBuffer.IsEmpty())) { + if (m_BlockBuffer.IsEmpty()) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (m_syntaxParserState != FDE_XmlSyntaxState::Target) + syntaxParserResult = FX_XmlSyntaxResult::TagName; + else + syntaxParserResult = FX_XmlSyntaxResult::TargetName; + + m_syntaxParserState = FDE_XmlSyntaxState::AttriName; + } else { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) { + return FX_XmlSyntaxResult::Error; + } + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + m_Start++; + } + break; + case FDE_XmlSyntaxState::AttriName: + if (m_BlockBuffer.IsEmpty() && IsXMLWhiteSpace(ch)) { + m_Start++; + break; + } + if (!IsXMLNameChar(ch, m_BlockBuffer.IsEmpty())) { + if (m_BlockBuffer.IsEmpty()) { + if (m_CurNode.eNodeType == FX_XMLNODE_Element) { + if (ch == L'>' || ch == L'/') { + m_syntaxParserState = FDE_XmlSyntaxState::BreakElement; + break; + } + } else if (m_CurNode.eNodeType == FX_XMLNODE_Instruction) { + if (ch == L'?') { + m_syntaxParserState = FDE_XmlSyntaxState::CloseInstruction; + m_Start++; + } else { + m_syntaxParserState = FDE_XmlSyntaxState::TargetData; + } + break; + } + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } else { + if (m_CurNode.eNodeType == FX_XMLNODE_Instruction) { + if (ch != '=' && !IsXMLWhiteSpace(ch)) { + m_syntaxParserState = FDE_XmlSyntaxState::TargetData; + break; + } + } + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_syntaxParserState = FDE_XmlSyntaxState::AttriEqualSign; + syntaxParserResult = FX_XmlSyntaxResult::AttriName; + } + } else { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) { + return FX_XmlSyntaxResult::Error; + } + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + m_Start++; + } + break; + case FDE_XmlSyntaxState::AttriEqualSign: + if (IsXMLWhiteSpace(ch)) { + m_Start++; + break; + } + if (ch != L'=') { + if (m_CurNode.eNodeType == FX_XMLNODE_Instruction) { + m_syntaxParserState = FDE_XmlSyntaxState::TargetData; + break; + } + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } else { + m_syntaxParserState = FDE_XmlSyntaxState::AttriQuotation; + m_Start++; + } + break; + case FDE_XmlSyntaxState::AttriQuotation: + if (IsXMLWhiteSpace(ch)) { + m_Start++; + break; + } + if (ch != L'\"' && ch != L'\'') { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } else { + m_wQuotationMark = ch; + m_syntaxParserState = FDE_XmlSyntaxState::AttriValue; + m_Start++; + } + break; + case FDE_XmlSyntaxState::AttriValue: + if (ch == m_wQuotationMark) { + if (m_iEntityStart > -1) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_wQuotationMark = 0; + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_Start++; + m_syntaxParserState = FDE_XmlSyntaxState::AttriName; + syntaxParserResult = FX_XmlSyntaxResult::AttriValue; + } else { + ParseTextChar(ch); + } + break; + case FDE_XmlSyntaxState::CloseInstruction: + if (ch != L'>') { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) { + return FX_XmlSyntaxResult::Error; + } + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + m_syntaxParserState = FDE_XmlSyntaxState::TargetData; + } else if (!m_BlockBuffer.IsEmpty()) { + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + syntaxParserResult = FX_XmlSyntaxResult::TargetData; + } else { + m_Start++; + if (m_XMLNodeStack.empty()) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + m_XMLNodeStack.pop(); + if (!m_XMLNodeStack.empty()) { + m_CurNode = m_XMLNodeStack.top(); + } else { + m_CurNode.iNodeNum = -1; + m_CurNode.eNodeType = FX_XMLNODE_Unknown; + } + m_iCurrentNodeNum = m_CurNode.iNodeNum; + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_syntaxParserState = FDE_XmlSyntaxState::Text; + syntaxParserResult = FX_XmlSyntaxResult::InstructionClose; + } + break; + case FDE_XmlSyntaxState::BreakElement: + if (ch == L'>') { + m_syntaxParserState = FDE_XmlSyntaxState::Text; + syntaxParserResult = FX_XmlSyntaxResult::ElementBreak; + } else if (ch == L'/') { + m_syntaxParserState = FDE_XmlSyntaxState::CloseElement; + } else { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + m_Start++; + break; + case FDE_XmlSyntaxState::CloseElement: + if (!IsXMLNameChar(ch, m_BlockBuffer.IsEmpty())) { + if (ch == L'>') { + if (m_XMLNodeStack.empty()) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + m_XMLNodeStack.pop(); + if (!m_XMLNodeStack.empty()) { + m_CurNode = m_XMLNodeStack.top(); + } else { + m_CurNode.iNodeNum = -1; + m_CurNode.eNodeType = FX_XMLNODE_Unknown; + } + m_iCurrentNodeNum = m_CurNode.iNodeNum; + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_syntaxParserState = FDE_XmlSyntaxState::Text; + syntaxParserResult = FX_XmlSyntaxResult::ElementClose; + } else if (!IsXMLWhiteSpace(ch)) { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + } else { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) { + return FX_XmlSyntaxResult::Error; + } + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + } + m_Start++; + break; + case FDE_XmlSyntaxState::SkipCommentOrDecl: + if (FXSYS_wcsnicmp(m_Buffer.data() + m_Start, L"--", 2) == 0) { + m_Start += 2; + m_syntaxParserState = FDE_XmlSyntaxState::SkipComment; + } else if (FXSYS_wcsnicmp(m_Buffer.data() + m_Start, L"[CDATA[", 7) == + 0) { + m_Start += 7; + m_syntaxParserState = FDE_XmlSyntaxState::SkipCData; + } else { + m_syntaxParserState = FDE_XmlSyntaxState::SkipDeclNode; + m_SkipChar = L'>'; + m_SkipStack.push(L'>'); + } + break; + case FDE_XmlSyntaxState::SkipCData: { + if (FXSYS_wcsnicmp(m_Buffer.data() + m_Start, L"]]>", 3) == 0) { + m_Start += 3; + syntaxParserResult = FX_XmlSyntaxResult::CData; + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_syntaxParserState = FDE_XmlSyntaxState::Text; + } else { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) + return FX_XmlSyntaxResult::Error; + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + m_Start++; + } + break; + } + case FDE_XmlSyntaxState::SkipDeclNode: + if (m_SkipChar == L'\'' || m_SkipChar == L'\"') { + m_Start++; + if (ch != m_SkipChar) + break; + + m_SkipStack.pop(); + if (m_SkipStack.empty()) + m_syntaxParserState = FDE_XmlSyntaxState::Text; + else + m_SkipChar = m_SkipStack.top(); + } else { + switch (ch) { + case L'<': + m_SkipChar = L'>'; + m_SkipStack.push(L'>'); + break; + case L'[': + m_SkipChar = L']'; + m_SkipStack.push(L']'); + break; + case L'(': + m_SkipChar = L')'; + m_SkipStack.push(L')'); + break; + case L'\'': + m_SkipChar = L'\''; + m_SkipStack.push(L'\''); + break; + case L'\"': + m_SkipChar = L'\"'; + m_SkipStack.push(L'\"'); + break; + default: + if (ch == m_SkipChar) { + m_SkipStack.pop(); + if (m_SkipStack.empty()) { + if (m_BlockBuffer.GetDataLength() >= 9) + (void)m_BlockBuffer.GetTextData(0, 7); + + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_syntaxParserState = FDE_XmlSyntaxState::Text; + } else { + m_SkipChar = m_SkipStack.top(); + } + } + break; + } + if (!m_SkipStack.empty()) { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) { + return FX_XmlSyntaxResult::Error; + } + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + } + m_Start++; + } + break; + case FDE_XmlSyntaxState::SkipComment: + if (FXSYS_wcsnicmp(m_Buffer.data() + m_Start, L"-->", 3) == 0) { + m_Start += 2; + m_syntaxParserState = FDE_XmlSyntaxState::Text; + } + + m_Start++; + break; + case FDE_XmlSyntaxState::TargetData: + if (IsXMLWhiteSpace(ch)) { + if (m_BlockBuffer.IsEmpty()) { + m_Start++; + break; + } + if (m_wQuotationMark == 0) { + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_wQuotationMark = 0; + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_Start++; + syntaxParserResult = FX_XmlSyntaxResult::TargetData; + break; + } + } + if (ch == '?') { + m_syntaxParserState = FDE_XmlSyntaxState::CloseInstruction; + m_Start++; + } else if (ch == '\"') { + if (m_wQuotationMark == 0) { + m_wQuotationMark = ch; + m_Start++; + } else if (ch == m_wQuotationMark) { + m_iTextDataLength = m_BlockBuffer.GetDataLength(); + m_wQuotationMark = 0; + m_BlockBuffer.Reset(true); + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_Start++; + syntaxParserResult = FX_XmlSyntaxResult::TargetData; + } else { + m_syntaxParserResult = FX_XmlSyntaxResult::Error; + return m_syntaxParserResult; + } + } else { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) { + return FX_XmlSyntaxResult::Error; + } + } + m_pCurrentBlock[m_iIndexInBlock++] = ch; + m_BlockBuffer.IncrementDataLength(); + m_Start++; + } + break; + default: + break; + } + if (syntaxParserResult != FX_XmlSyntaxResult::None) + return syntaxParserResult; + } + } + return FX_XmlSyntaxResult::Text; +} + +int32_t CFX_XMLSyntaxParser::GetStatus() const { + if (!m_pStream) + return -1; + + int32_t iStreamLength = m_pStream->GetLength(); + if (iStreamLength < 1) + return 100; + + if (m_syntaxParserResult == FX_XmlSyntaxResult::Error) + return -1; + + if (m_syntaxParserResult == FX_XmlSyntaxResult::EndOfString) + return 100; + return m_iParsedBytes * 100 / iStreamLength; +} + +FX_FILESIZE CFX_XMLSyntaxParser::GetCurrentBinaryPos() const { + if (!m_pStream) + return 0; + + int32_t nDstLen = GetUTF8EncodeLength(m_Buffer, m_Start); + return m_iParsedBytes + nDstLen; +} + +void CFX_XMLSyntaxParser::ParseTextChar(wchar_t character) { + if (m_iIndexInBlock == m_iAllocStep) { + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + if (!m_pCurrentBlock) + return; + } + + m_pCurrentBlock[m_iIndexInBlock++] = character; + m_BlockBuffer.IncrementDataLength(); + if (m_iEntityStart > -1 && character == L';') { + WideString csEntity = m_BlockBuffer.GetTextData( + m_iEntityStart + 1, + m_BlockBuffer.GetDataLength() - 1 - m_iEntityStart - 1); + int32_t iLen = csEntity.GetLength(); + if (iLen > 0) { + if (csEntity[0] == L'#') { + uint32_t ch = 0; + wchar_t w; + if (iLen > 1 && csEntity[1] == L'x') { + for (int32_t i = 2; i < iLen; i++) { + w = csEntity[i]; + if (std::iswdigit(w)) + ch = (ch << 4) + w - L'0'; + else if (w >= L'A' && w <= L'F') + ch = (ch << 4) + w - 55; + else if (w >= L'a' && w <= L'f') + ch = (ch << 4) + w - 87; + else + break; + } + } else { + for (int32_t i = 1; i < iLen; i++) { + w = csEntity[i]; + if (!std::iswdigit(w)) + break; + ch = ch * 10 + w - L'0'; + } + } + if (ch > kMaxCharRange) + ch = ' '; + + character = static_cast(ch); + if (character != 0) { + m_BlockBuffer.SetTextChar(m_iEntityStart, character); + m_iEntityStart++; + } + } else { + if (csEntity.Compare(L"amp") == 0) { + m_BlockBuffer.SetTextChar(m_iEntityStart, L'&'); + m_iEntityStart++; + } else if (csEntity.Compare(L"lt") == 0) { + m_BlockBuffer.SetTextChar(m_iEntityStart, L'<'); + m_iEntityStart++; + } else if (csEntity.Compare(L"gt") == 0) { + m_BlockBuffer.SetTextChar(m_iEntityStart, L'>'); + m_iEntityStart++; + } else if (csEntity.Compare(L"apos") == 0) { + m_BlockBuffer.SetTextChar(m_iEntityStart, L'\''); + m_iEntityStart++; + } else if (csEntity.Compare(L"quot") == 0) { + m_BlockBuffer.SetTextChar(m_iEntityStart, L'\"'); + m_iEntityStart++; + } + } + } + if (m_iEntityStart >= 0 && + m_BlockBuffer.GetDataLength() > static_cast(m_iEntityStart)) { + m_BlockBuffer.DeleteTextChars(m_BlockBuffer.GetDataLength() - + m_iEntityStart); + } + std::tie(m_pCurrentBlock, m_iIndexInBlock) = + m_BlockBuffer.GetAvailableBlock(); + m_iEntityStart = -1; + } else if (m_iEntityStart < 0 && character == L'&') { + m_iEntityStart = m_BlockBuffer.GetDataLength() - 1; + } + m_Start++; +} diff --git a/core/fxcrt/xml/cfx_xmlsyntaxparser.h b/core/fxcrt/xml/cfx_xmlsyntaxparser.h new file mode 100644 index 0000000000000000000000000000000000000000..b93bbb680124f793cb2f7bfba622b3a79705cf10 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlsyntaxparser.h @@ -0,0 +1,130 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLSYNTAXPARSER_H_ +#define CORE_FXCRT_XML_CFX_XMLSYNTAXPARSER_H_ + +#include +#include + +#include "core/fxcrt/cfx_blockbuffer.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" + +enum class FX_XmlSyntaxResult { + None, + InstructionOpen, + InstructionClose, + ElementOpen, + ElementBreak, + ElementClose, + TargetName, + TagName, + AttriName, + AttriValue, + Text, + CData, + TargetData, + Error, + EndOfString +}; + +class CFX_XMLSyntaxParser { + public: + static bool IsXMLNameChar(wchar_t ch, bool bFirstChar); + + explicit CFX_XMLSyntaxParser( + const RetainPtr& pStream); + ~CFX_XMLSyntaxParser(); + + FX_XmlSyntaxResult DoSyntaxParse(); + + int32_t GetStatus() const; + FX_FILESIZE GetCurrentPos() const { return m_ParsedChars + m_Start; } + FX_FILESIZE GetCurrentBinaryPos() const; + int32_t GetCurrentNodeNumber() const { return m_iCurrentNodeNum; } + int32_t GetLastNodeNumber() const { return m_iLastNodeNum; } + + WideString GetTargetName() const { + return m_BlockBuffer.GetTextData(0, m_iTextDataLength); + } + + WideString GetTagName() const { + return m_BlockBuffer.GetTextData(0, m_iTextDataLength); + } + + WideString GetAttributeName() const { + return m_BlockBuffer.GetTextData(0, m_iTextDataLength); + } + + WideString GetAttributeValue() const { + return m_BlockBuffer.GetTextData(0, m_iTextDataLength); + } + + WideString GetTextData() const { + return m_BlockBuffer.GetTextData(0, m_iTextDataLength); + } + + WideString GetTargetData() const { + return m_BlockBuffer.GetTextData(0, m_iTextDataLength); + } + + protected: + enum class FDE_XmlSyntaxState { + Text, + Node, + Target, + Tag, + AttriName, + AttriEqualSign, + AttriQuotation, + AttriValue, + Entity, + EntityDecimal, + EntityHex, + CloseInstruction, + BreakElement, + CloseElement, + SkipDeclNode, + DeclCharData, + SkipComment, + SkipCommentOrDecl, + SkipCData, + TargetData + }; + + void ParseTextChar(wchar_t ch); + + RetainPtr m_pStream; + size_t m_iXMLPlaneSize; + FX_FILESIZE m_iCurrentPos; + int32_t m_iCurrentNodeNum; + int32_t m_iLastNodeNum; + int32_t m_iParsedBytes; + FX_FILESIZE m_ParsedChars; + std::vector m_Buffer; + size_t m_iBufferChars; + bool m_bEOS; + FX_FILESIZE m_Start; // Start position in m_Buffer + FX_FILESIZE m_End; // End position in m_Buffer + FX_XMLNODE m_CurNode; + std::stack m_XMLNodeStack; + CFX_BlockBuffer m_BlockBuffer; + int32_t m_iAllocStep; + wchar_t* m_pCurrentBlock; // Pointer into CFX_BlockBuffer + int32_t m_iIndexInBlock; + int32_t m_iTextDataLength; + FX_XmlSyntaxResult m_syntaxParserResult; + FDE_XmlSyntaxState m_syntaxParserState; + wchar_t m_wQuotationMark; + int32_t m_iEntityStart; + std::stack m_SkipStack; + wchar_t m_SkipChar; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLSYNTAXPARSER_H_ diff --git a/core/fxcrt/xml/cfx_xmlsyntaxparser_unittest.cpp b/core/fxcrt/xml/cfx_xmlsyntaxparser_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7f7c416b15f57aebc144f34cb6a3345a89f22b1 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmlsyntaxparser_unittest.cpp @@ -0,0 +1,542 @@ +// Copyright 2016 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. + +#include "core/fxcrt/xml/cfx_xmlsyntaxparser.h" + +#include + +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/fx_codepage.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CFX_XMLSyntaxParserTest, CData) { + const char* input = + ""; + + const wchar_t* cdata = + L"\n" + L" if (a[1] < 3)\n" + L" app.alert(\"Tclams\");\n" + L" "; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::CData, parser.DoSyntaxParse()); + ASSERT_EQ(cdata, parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, CDataWithInnerScript) { + const char* input = + "\n" + " ]]>\n" + ""; + + const wchar_t* cdata = + L"\n" + L" if (a[1] < 3)\n" + L" app.alert(\"Tclams\");\n" + L" \n" + L" "; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::CData, parser.DoSyntaxParse()); + ASSERT_EQ(cdata, parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, ArrowBangArrow) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, ArrowBangBracketArrow) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + // Parser walks to end of input. + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, IncompleteCData) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + // Parser walks to end of input. + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, UnClosedCData) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + // Parser walks to end of input. + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, EmptyCData) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::CData, parser.DoSyntaxParse()); + ASSERT_EQ(L"", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, Comment) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, IncorrectCommentStart) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, CommentEmpty) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, CommentThreeDash) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, CommentTwoDash) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"\n ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, Entities) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L"BTH\xab48", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, EntityOverflowHex) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L" ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, EntityOverflowDecimal) { + const char* input = + ""; + + RetainPtr stream = + pdfium::MakeRetain( + reinterpret_cast(const_cast(input)), strlen(input)); + stream->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLSyntaxParser parser(stream); + ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); + ASSERT_EQ(L"contentType", parser.GetAttributeName()); + ASSERT_EQ(FX_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); + ASSERT_EQ(L"application/x-javascript", parser.GetAttributeValue()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); + ASSERT_EQ(FX_XmlSyntaxResult::Text, parser.DoSyntaxParse()); + ASSERT_EQ(L" ", parser.GetTextData()); + + ASSERT_EQ(FX_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); + ASSERT_EQ(L"script", parser.GetTagName()); + + ASSERT_EQ(FX_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); +} + +TEST(CFX_XMLSyntaxParserTest, IsXMLNameChar) { + EXPECT_FALSE(CFX_XMLSyntaxParser::IsXMLNameChar(L'-', true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(L'-', false)); + + EXPECT_FALSE(CFX_XMLSyntaxParser::IsXMLNameChar(0x2069, true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(0x2070, true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(0x2073, true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(0x218F, true)); + EXPECT_FALSE(CFX_XMLSyntaxParser::IsXMLNameChar(0x2190, true)); + + EXPECT_FALSE(CFX_XMLSyntaxParser::IsXMLNameChar(0xFDEF, true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(0xFDF0, true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(0xFDF1, true)); + EXPECT_TRUE(CFX_XMLSyntaxParser::IsXMLNameChar(0xFFFD, true)); + EXPECT_FALSE(CFX_XMLSyntaxParser::IsXMLNameChar(0xFFFE, true)); +} diff --git a/core/fxcrt/xml/cfx_xmltext.cpp b/core/fxcrt/xml/cfx_xmltext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83ad0434bff11ac6d649e71722fd12d310cb8b35 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmltext.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cfx_xmltext.h" + +#include "third_party/base/ptr_util.h" + +CFX_XMLText::CFX_XMLText(const WideString& wsText) + : CFX_XMLNode(), m_wsText(wsText) {} + +CFX_XMLText::~CFX_XMLText() {} + +FX_XMLNODETYPE CFX_XMLText::GetType() const { + return FX_XMLNODE_Text; +} + +std::unique_ptr CFX_XMLText::Clone() { + return pdfium::MakeUnique(m_wsText); +} diff --git a/core/fxcrt/xml/cfx_xmltext.h b/core/fxcrt/xml/cfx_xmltext.h new file mode 100644 index 0000000000000000000000000000000000000000..e9f35855f5a6ba9ade9e5cd5c0fe3b08a8eb7a33 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmltext.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CFX_XMLTEXT_H_ +#define CORE_FXCRT_XML_CFX_XMLTEXT_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" + +class CFX_XMLText : public CFX_XMLNode { + public: + explicit CFX_XMLText(const WideString& wsText); + ~CFX_XMLText() override; + + // CFX_XMLNode + FX_XMLNODETYPE GetType() const override; + std::unique_ptr Clone() override; + + WideString GetText() const { return m_wsText; } + void SetText(const WideString& wsText) { m_wsText = wsText; } + + private: + WideString m_wsText; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLTEXT_H_ diff --git a/core/fxcrt/xml/cxml_attritem.cpp b/core/fxcrt/xml/cxml_attritem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbbf3f60416df921d91023410088bc39242ade70 --- /dev/null +++ b/core/fxcrt/xml/cxml_attritem.cpp @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cxml_attritem.h" + +bool CXML_AttrItem::Matches(const ByteString& space, + const ByteString& name) const { + return (space.IsEmpty() || m_QSpaceName == space) && m_AttrName == name; +} diff --git a/core/fxcrt/xml/cxml_attritem.h b/core/fxcrt/xml/cxml_attritem.h new file mode 100644 index 0000000000000000000000000000000000000000..84d82950f96c9331b9e6097c23dc3277afc0eca3 --- /dev/null +++ b/core/fxcrt/xml/cxml_attritem.h @@ -0,0 +1,21 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CXML_ATTRITEM_H_ +#define CORE_FXCRT_XML_CXML_ATTRITEM_H_ + +#include "core/fxcrt/fx_string.h" + +class CXML_AttrItem { + public: + bool Matches(const ByteString& space, const ByteString& name) const; + + ByteString m_QSpaceName; + ByteString m_AttrName; + WideString m_Value; +}; + +#endif // CORE_FXCRT_XML_CXML_ATTRITEM_H_ diff --git a/core/fxcrt/xml/cxml_content.cpp b/core/fxcrt/xml/cxml_content.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a23500942446d38f54cf59c40b58f869504102ed --- /dev/null +++ b/core/fxcrt/xml/cxml_content.cpp @@ -0,0 +1,20 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cxml_content.h" + +CXML_Content::CXML_Content(bool bCDATA, const WideStringView& content) + : m_bCDATA(bCDATA), m_Content(content) {} + +CXML_Content::~CXML_Content() {} + +CXML_Content* CXML_Content::AsContent() { + return this; +} + +const CXML_Content* CXML_Content::AsContent() const { + return this; +} diff --git a/core/fxcrt/xml/cxml_content.h b/core/fxcrt/xml/cxml_content.h new file mode 100644 index 0000000000000000000000000000000000000000..97c1abfe1c2204dca9316989ae57f4224fa2e0ae --- /dev/null +++ b/core/fxcrt/xml/cxml_content.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CXML_CONTENT_H_ +#define CORE_FXCRT_XML_CXML_CONTENT_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/xml/cxml_object.h" + +class CXML_Content : public CXML_Object { + public: + CXML_Content(bool bCDATA, const WideStringView& content); + ~CXML_Content() override; + + // CXML_Object: + CXML_Content* AsContent() override; + const CXML_Content* AsContent() const override; + + bool m_bCDATA; + WideString m_Content; +}; + +#endif // CORE_FXCRT_XML_CXML_CONTENT_H_ diff --git a/core/fxcrt/xml/cxml_databufacc.cpp b/core/fxcrt/xml/cxml_databufacc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3e2e1f3e0136bad69776c840d4f9518dfead2d9 --- /dev/null +++ b/core/fxcrt/xml/cxml_databufacc.cpp @@ -0,0 +1,20 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cxml_databufacc.h" + +CXML_DataBufAcc::CXML_DataBufAcc(const uint8_t* pBuffer, size_t size) + : m_pBuffer(pBuffer), m_dwSize(size), m_dwCurPos(0) {} + +CXML_DataBufAcc::~CXML_DataBufAcc() {} + +bool CXML_DataBufAcc::ReadNextBlock() { + if (m_dwCurPos >= m_dwSize) + return false; + + m_dwCurPos = m_dwSize; + return true; +} diff --git a/core/fxcrt/xml/cxml_databufacc.h b/core/fxcrt/xml/cxml_databufacc.h new file mode 100644 index 0000000000000000000000000000000000000000..4fb44b302c9c4c5ba9cb973e2a390352662e2ce0 --- /dev/null +++ b/core/fxcrt/xml/cxml_databufacc.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CXML_DATABUFACC_H_ +#define CORE_FXCRT_XML_CXML_DATABUFACC_H_ + +#include "core/fxcrt/fx_system.h" + +class CXML_DataBufAcc { + public: + CXML_DataBufAcc(const uint8_t* pBuffer, size_t size); + ~CXML_DataBufAcc(); + + bool IsEOF() const { return m_dwCurPos >= m_dwSize; } + FX_FILESIZE GetPosition() const { + return static_cast(m_dwCurPos); + } + bool ReadNextBlock(); + const uint8_t* GetBlockBuffer() const { return m_pBuffer; } + size_t GetBlockSize() const { return m_dwSize; } + + private: + const uint8_t* m_pBuffer; + size_t m_dwSize; + size_t m_dwCurPos; +}; + +#endif // CORE_FXCRT_XML_CXML_DATABUFACC_H_ diff --git a/core/fxcrt/xml/cxml_element.cpp b/core/fxcrt/xml/cxml_element.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d42e8eac3ae08ba5743713df10cf4820179893c --- /dev/null +++ b/core/fxcrt/xml/cxml_element.cpp @@ -0,0 +1,165 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cxml_element.h" + +#include "core/fxcrt/xml/cxml_content.h" +#include "core/fxcrt/xml/cxml_parser.h" + +namespace { + +void SplitQualifiedName(const ByteStringView& bsFullName, + ByteStringView* bsSpace, + ByteStringView* bsName) { + if (bsFullName.IsEmpty()) + return; + + auto iStart = bsFullName.Find(':'); + if (iStart.has_value()) { + *bsSpace = bsFullName.Left(iStart.value()); + *bsName = bsFullName.Right(bsFullName.GetLength() - (iStart.value() + 1)); + } else { + *bsName = bsFullName; + } +} + +} // namespace + +// static +std::unique_ptr CXML_Element::Parse(const void* pBuffer, + size_t size) { + CXML_Parser parser; + if (!parser.Init(static_cast(pBuffer), size)) + return nullptr; + return parser.ParseElement(nullptr, false); +} + +CXML_Element::CXML_Element(const CXML_Element* pParent, + const ByteStringView& qSpace, + const ByteStringView& tagname) + : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {} + +CXML_Element::~CXML_Element() {} + +CXML_Element* CXML_Element::AsElement() { + return this; +} + +const CXML_Element* CXML_Element::AsElement() const { + return this; +} + +ByteString CXML_Element::GetTagName() const { + return m_TagName; +} + +ByteString CXML_Element::GetNamespaceURI(const ByteString& qName) const { + const CXML_Element* pElement = this; + do { + const WideString* pwsSpace; + if (qName.IsEmpty()) + pwsSpace = pElement->Lookup("", "xmlns"); + else + pwsSpace = pElement->Lookup("xmlns", qName); + if (pwsSpace) + return pwsSpace->UTF8Encode(); + + pElement = pElement->GetParent(); + } while (pElement); + return ByteString(); +} + +void CXML_Element::GetAttrByIndex(size_t index, + ByteString* space, + ByteString* name, + WideString* value) const { + if (index >= m_AttrMap.size()) + return; + + const CXML_AttrItem& item = m_AttrMap[index]; + *space = item.m_QSpaceName; + *name = item.m_AttrName; + *value = item.m_Value; +} + +WideString CXML_Element::GetAttrValue(const ByteStringView& name) const { + ByteStringView bsSpace; + ByteStringView bsName; + SplitQualifiedName(name, &bsSpace, &bsName); + + WideString attr; + const WideString* pValue = Lookup(ByteString(bsSpace), ByteString(bsName)); + if (pValue) + attr = *pValue; + return attr; +} + +int CXML_Element::GetAttrInteger(const ByteStringView& name) const { + ByteStringView bsSpace; + ByteStringView bsName; + SplitQualifiedName(name, &bsSpace, &bsName); + + const WideString* pwsValue = Lookup(ByteString(bsSpace), ByteString(bsName)); + return pwsValue ? pwsValue->GetInteger() : 0; +} + +size_t CXML_Element::CountElements(const ByteStringView& space, + const ByteStringView& tag) const { + size_t count = 0; + for (const auto& pChild : m_Children) { + const CXML_Element* pKid = pChild->AsElement(); + if (MatchesElement(pKid, space, tag)) + count++; + } + return count; +} + +CXML_Object* CXML_Element::GetChild(size_t index) const { + return index < m_Children.size() ? m_Children[index].get() : nullptr; +} + +CXML_Element* CXML_Element::GetElement(const ByteStringView& space, + const ByteStringView& tag, + size_t nth) const { + for (const auto& pChild : m_Children) { + CXML_Element* pKid = pChild->AsElement(); + if (MatchesElement(pKid, space, tag)) { + if (nth == 0) + return pKid; + --nth; + } + } + return nullptr; +} + +void CXML_Element::SetAttribute(const ByteString& space, + const ByteString& name, + const WideString& value) { + for (CXML_AttrItem& item : m_AttrMap) { + if (item.Matches(space, name)) { + item.m_Value = value; + return; + } + } + m_AttrMap.push_back({space, name, WideString(value)}); +} + +// static +bool CXML_Element::MatchesElement(const CXML_Element* pKid, + const ByteStringView& space, + const ByteStringView& tag) { + return pKid && pKid->m_TagName == tag && + (space.IsEmpty() || pKid->m_QSpaceName == space); +} + +const WideString* CXML_Element::Lookup(const ByteString& space, + const ByteString& name) const { + for (const CXML_AttrItem& item : m_AttrMap) { + if (item.Matches(space, name)) + return &item.m_Value; + } + return nullptr; +} diff --git a/core/fxcrt/xml/cxml_element.h b/core/fxcrt/xml/cxml_element.h new file mode 100644 index 0000000000000000000000000000000000000000..d3049d77a4fdd8d2dd9c4868c81ce9cf4a1fab53 --- /dev/null +++ b/core/fxcrt/xml/cxml_element.h @@ -0,0 +1,73 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CXML_ELEMENT_H_ +#define CORE_FXCRT_XML_CXML_ELEMENT_H_ + +#include +#include +#include + +#include "core/fxcrt/xml/cxml_attritem.h" +#include "core/fxcrt/xml/cxml_object.h" + +class CXML_Element : public CXML_Object { + public: + static std::unique_ptr Parse(const void* pBuffer, size_t size); + + CXML_Element(const CXML_Element* pParent, + const ByteStringView& qSpace, + const ByteStringView& tagname); + ~CXML_Element() override; + + // CXML_Object: + CXML_Element* AsElement() override; + const CXML_Element* AsElement() const override; + + ByteString GetTagName() const; + ByteString GetNamespaceURI(const ByteString& qName) const; + const CXML_Element* GetParent() const { return m_pParent.Get(); } + size_t CountAttrs() const { return m_AttrMap.size(); } + void GetAttrByIndex(size_t index, + ByteString* space, + ByteString* name, + WideString* value) const; + WideString GetAttrValue(const ByteStringView& name) const; + + int GetAttrInteger(const ByteStringView& name) const; + + void AppendChild(std::unique_ptr child) { + m_Children.push_back(std::move(child)); + } + + size_t CountChildren() const { return m_Children.size(); } + size_t CountElements(const ByteStringView& space, + const ByteStringView& tag) const; + CXML_Object* GetChild(size_t index) const; + CXML_Element* GetElement(const ByteStringView& space, + const ByteStringView& tag, + size_t nth) const; + + void SetAttribute(const ByteString& space, + const ByteString& name, + const WideString& value); + + private: + static bool MatchesElement(const CXML_Element* pKid, + const ByteStringView& space, + const ByteStringView& tag); + + const WideString* Lookup(const ByteString& space, + const ByteString& name) const; + + UnownedPtr const m_pParent; + const ByteString m_QSpaceName; + const ByteString m_TagName; + std::vector m_AttrMap; + std::vector> m_Children; +}; + +#endif // CORE_FXCRT_XML_CXML_ELEMENT_H_ diff --git a/core/fxcrt/xml/cxml_object.cpp b/core/fxcrt/xml/cxml_object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..61e88cb407cce1fa43b546bed5c165f2b457d812 --- /dev/null +++ b/core/fxcrt/xml/cxml_object.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/xml/cxml_object.h" + +CXML_Object::~CXML_Object() {} + +CXML_Content* CXML_Object::AsContent() { + return nullptr; +} + +CXML_Element* CXML_Object::AsElement() { + return nullptr; +} + +const CXML_Content* CXML_Object::AsContent() const { + return nullptr; +} + +const CXML_Element* CXML_Object::AsElement() const { + return nullptr; +} diff --git a/core/fxcrt/xml/cxml_object.h b/core/fxcrt/xml/cxml_object.h new file mode 100644 index 0000000000000000000000000000000000000000..d00935993260b8e71b22e0e1775a11224975fc67 --- /dev/null +++ b/core/fxcrt/xml/cxml_object.h @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_XML_CXML_OBJECT_H_ +#define CORE_FXCRT_XML_CXML_OBJECT_H_ + +class CXML_Content; +class CXML_Element; + +class CXML_Object { + public: + virtual ~CXML_Object(); + + virtual CXML_Content* AsContent(); + virtual const CXML_Content* AsContent() const; + + virtual CXML_Element* AsElement(); + virtual const CXML_Element* AsElement() const; + + protected: + CXML_Object() {} +}; + +inline CXML_Content* ToContent(CXML_Object* pObj) { + return pObj ? pObj->AsContent() : nullptr; +} + +inline const CXML_Content* ToContent(const CXML_Object* pObj) { + return pObj ? pObj->AsContent() : nullptr; +} + +inline CXML_Element* ToElement(CXML_Object* pObj) { + return pObj ? pObj->AsElement() : nullptr; +} + +inline const CXML_Element* ToElement(const CXML_Object* pObj) { + return pObj ? pObj->AsElement() : nullptr; +} + +#endif // CORE_FXCRT_XML_CXML_OBJECT_H_ diff --git a/core/fxcrt/xml/cxml_parser.cpp b/core/fxcrt/xml/cxml_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae5fd6d0fc2e54881c26dac671411e2388d0762c --- /dev/null +++ b/core/fxcrt/xml/cxml_parser.cpp @@ -0,0 +1,528 @@ +// 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 +#include +#include +#include +#include +#include + +#include "core/fxcrt/cfx_utf8decoder.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cxml_content.h" +#include "core/fxcrt/xml/cxml_element.h" +#include "core/fxcrt/xml/cxml_parser.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +#define FXCRTM_XML_CHARTYPE_Normal 0x00 +#define FXCRTM_XML_CHARTYPE_SpaceChar 0x01 +#define FXCRTM_XML_CHARTYPE_Letter 0x02 +#define FXCRTM_XML_CHARTYPE_Digital 0x04 +#define FXCRTM_XML_CHARTYPE_NameIntro 0x08 +#define FXCRTM_XML_CHARTYPE_NameChar 0x10 +#define FXCRTM_XML_CHARTYPE_HexDigital 0x20 +#define FXCRTM_XML_CHARTYPE_HexLowerLetter 0x40 +#define FXCRTM_XML_CHARTYPE_HexUpperLetter 0x60 +#define FXCRTM_XML_CHARTYPE_HexChar 0x60 + +const uint8_t g_FXCRT_XML_ByteTypes[256] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1A, 0x1A, 0x01, 0x01, +}; + +constexpr int kMaxDepth = 1024; + +bool g_FXCRT_XML_IsWhiteSpace(uint8_t ch) { + return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_SpaceChar); +} + +bool g_FXCRT_XML_IsDigital(uint8_t ch) { + return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_Digital); +} + +bool g_FXCRT_XML_IsNameIntro(uint8_t ch) { + return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_NameIntro); +} + +bool g_FXCRT_XML_IsNameChar(uint8_t ch) { + return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_NameChar); +} + +} // namespace + +CXML_Parser::CXML_Parser() + : m_nOffset(0), + m_pBuffer(nullptr), + m_dwBufferSize(0), + m_nBufferOffset(0), + m_dwIndex(0) {} + +CXML_Parser::~CXML_Parser() {} + +bool CXML_Parser::Init(const uint8_t* pBuffer, size_t size) { + m_pDataAcc = pdfium::MakeUnique(pBuffer, size); + m_nOffset = 0; + return ReadNextBlock(); +} + +bool CXML_Parser::ReadNextBlock() { + if (!m_pDataAcc->ReadNextBlock()) + return false; + + m_pBuffer = m_pDataAcc->GetBlockBuffer(); + m_dwBufferSize = m_pDataAcc->GetBlockSize(); + m_nBufferOffset = 0; + m_dwIndex = 0; + return m_dwBufferSize > 0; +} + +bool CXML_Parser::IsEOF() { + return m_pDataAcc->IsEOF() && m_dwIndex >= m_dwBufferSize; +} + +void CXML_Parser::SkipWhiteSpaces() { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) + return; + + do { + while (m_dwIndex < m_dwBufferSize && + g_FXCRT_XML_IsWhiteSpace(m_pBuffer[m_dwIndex])) { + m_dwIndex++; + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); +} + +void CXML_Parser::GetName(ByteString* space, ByteString* name) { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) + return; + + std::ostringstream buf; + do { + while (m_dwIndex < m_dwBufferSize) { + uint8_t ch = m_pBuffer[m_dwIndex]; + if (ch == ':') { + *space = ByteString(buf); + buf.str(""); + } else if (g_FXCRT_XML_IsNameChar(ch)) { + buf << static_cast(ch); + } else { + break; + } + m_dwIndex++; + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); + *name = ByteString(buf); +} + +void CXML_Parser::SkipLiterals(const ByteStringView& str) { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) { + return; + } + int32_t i = 0, iLen = str.GetLength(); + do { + while (m_dwIndex < m_dwBufferSize) { + if (str[i] != m_pBuffer[m_dwIndex++]) { + i = 0; + continue; + } + i++; + if (i == iLen) + break; + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (i == iLen) + return; + + if (m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); + while (!m_pDataAcc->IsEOF()) { + ReadNextBlock(); + m_nOffset = m_nBufferOffset + static_cast(m_dwBufferSize); + } + m_dwIndex = m_dwBufferSize; +} + +uint32_t CXML_Parser::GetCharRef() { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) + return 0; + + uint8_t ch; + int32_t iState = 0; + std::ostringstream buf; + uint32_t code = 0; + do { + while (m_dwIndex < m_dwBufferSize) { + ch = m_pBuffer[m_dwIndex]; + switch (iState) { + case 0: + if (ch == '#') { + m_dwIndex++; + iState = 2; + break; + } + iState = 1; + case 1: + m_dwIndex++; + if (ch == ';') { + std::string ref = buf.str(); + if (ref == "gt") + code = '>'; + else if (ref == "lt") + code = '<'; + else if (ref == "amp") + code = '&'; + else if (ref == "apos") + code = '\''; + else if (ref == "quot") + code = '"'; + iState = 10; + break; + } + buf << static_cast(ch); + break; + case 2: + if (ch == 'x') { + m_dwIndex++; + iState = 4; + break; + } + iState = 3; + case 3: + m_dwIndex++; + if (ch == ';') { + iState = 10; + break; + } + if (g_FXCRT_XML_IsDigital(ch)) + code = code * 10 + FXSYS_DecimalCharToInt(static_cast(ch)); + break; + case 4: + m_dwIndex++; + if (ch == ';') { + iState = 10; + break; + } + uint8_t nHex = + g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_HexChar; + if (nHex) { + if (nHex == FXCRTM_XML_CHARTYPE_HexDigital) { + code = (code << 4) + + FXSYS_DecimalCharToInt(static_cast(ch)); + } else if (nHex == FXCRTM_XML_CHARTYPE_HexLowerLetter) { + code = (code << 4) + ch - 87; + } else { + code = (code << 4) + ch - 55; + } + } + break; + } + if (iState == 10) + break; + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF()) { + break; + } + } while (ReadNextBlock()); + return code; +} + +WideString CXML_Parser::GetAttrValue() { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) + return WideString(); + + CFX_UTF8Decoder decoder; + uint8_t mark = 0; + uint8_t ch = 0; + do { + while (m_dwIndex < m_dwBufferSize) { + ch = m_pBuffer[m_dwIndex]; + if (mark == 0) { + if (ch != '\'' && ch != '"') + return WideString(); + + mark = ch; + m_dwIndex++; + ch = 0; + continue; + } + m_dwIndex++; + if (ch == mark) + break; + + if (ch == '&') { + decoder.AppendCodePoint(GetCharRef()); + if (IsEOF()) + return WideString(decoder.GetResult()); + } else { + decoder.Input(ch); + } + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (ch == mark || m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); + return WideString(decoder.GetResult()); +} + +void CXML_Parser::GetTagName(bool bStartTag, + bool* bEndTag, + ByteString* space, + ByteString* name) { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) + return; + + *bEndTag = false; + uint8_t ch; + int32_t iState = bStartTag ? 1 : 0; + do { + while (m_dwIndex < m_dwBufferSize) { + ch = m_pBuffer[m_dwIndex]; + switch (iState) { + case 0: + m_dwIndex++; + if (ch != '<') + break; + + iState = 1; + break; + case 1: + if (ch == '?') { + m_dwIndex++; + SkipLiterals("?>"); + iState = 0; + break; + } + if (ch == '!') { + m_dwIndex++; + SkipLiterals("-->"); + iState = 0; + break; + } + if (ch == '/') { + m_dwIndex++; + GetName(space, name); + *bEndTag = true; + } else { + GetName(space, name); + *bEndTag = false; + } + return; + } + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); +} + +std::unique_ptr CXML_Parser::ParseElement(CXML_Element* pParent, + bool bStartTag) { + return ParseElementInternal(pParent, bStartTag, 0); +} + +std::unique_ptr CXML_Parser::ParseElementInternal( + CXML_Element* pParent, + bool bStartTag, + int nDepth) { + if (nDepth > kMaxDepth) + return nullptr; + + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (IsEOF()) + return nullptr; + + ByteString tag_name; + ByteString tag_space; + bool bEndTag; + GetTagName(bStartTag, &bEndTag, &tag_space, &tag_name); + if (tag_name.IsEmpty() || bEndTag) + return nullptr; + + auto pElement = pdfium::MakeUnique( + pParent, tag_space.AsStringView(), tag_name.AsStringView()); + do { + ByteString attr_space; + ByteString attr_name; + while (m_dwIndex < m_dwBufferSize) { + SkipWhiteSpaces(); + if (IsEOF()) + break; + + if (!g_FXCRT_XML_IsNameIntro(m_pBuffer[m_dwIndex])) + break; + + GetName(&attr_space, &attr_name); + SkipWhiteSpaces(); + if (IsEOF()) + break; + + if (m_pBuffer[m_dwIndex] != '=') + break; + + m_dwIndex++; + SkipWhiteSpaces(); + if (IsEOF()) + break; + + WideString attr_value = GetAttrValue(); + pElement->SetAttribute(attr_space, attr_name, attr_value); + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); + SkipWhiteSpaces(); + if (IsEOF()) + return pElement; + + uint8_t ch = m_pBuffer[m_dwIndex++]; + if (ch == '/') { + m_dwIndex++; + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + return pElement; + } + if (ch != '>') { + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + return nullptr; + } + SkipWhiteSpaces(); + if (IsEOF()) + return pElement; + + CFX_UTF8Decoder decoder; + CFX_WideTextBuf content; + bool bCDATA = false; + int32_t iState = 0; + do { + while (m_dwIndex < m_dwBufferSize) { + ch = m_pBuffer[m_dwIndex++]; + switch (iState) { + case 0: + if (ch == '<') { + iState = 1; + } else if (ch == '&') { + decoder.ClearStatus(); + decoder.AppendCodePoint(GetCharRef()); + } else { + decoder.Input(ch); + } + break; + case 1: + if (ch == '!') { + iState = 2; + } else if (ch == '?') { + SkipLiterals("?>"); + SkipWhiteSpaces(); + iState = 0; + } else if (ch == '/') { + ByteString space; + ByteString name; + GetName(&space, &name); + SkipWhiteSpaces(); + m_dwIndex++; + iState = 10; + } else { + content << decoder.GetResult(); + WideString dataStr = content.MakeString(); + if (!bCDATA) + dataStr.TrimRight(L" \t\r\n"); + + InsertContentSegment(bCDATA, dataStr.AsStringView(), + pElement.get()); + content.Clear(); + decoder.Clear(); + bCDATA = false; + iState = 0; + m_dwIndex--; + std::unique_ptr pSubElement = + ParseElementInternal(pElement.get(), true, nDepth + 1); + if (!pSubElement) + break; + + pElement->AppendChild(std::move(pSubElement)); + SkipWhiteSpaces(); + } + break; + case 2: + if (ch == '[') { + SkipLiterals("]]>"); + } else if (ch == '-') { + m_dwIndex++; + SkipLiterals("-->"); + } else { + SkipLiterals(">"); + } + decoder.Clear(); + SkipWhiteSpaces(); + iState = 0; + break; + } + if (iState == 10) { + break; + } + } + m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); + if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF()) + break; + } while (ReadNextBlock()); + content << decoder.GetResult(); + WideString dataStr = content.MakeString(); + dataStr.TrimRight(L" \t\r\n"); + + InsertContentSegment(bCDATA, dataStr.AsStringView(), pElement.get()); + content.Clear(); + decoder.Clear(); + bCDATA = false; + return pElement; +} + +void CXML_Parser::InsertContentSegment(bool bCDATA, + const WideStringView& content, + CXML_Element* pElement) { + if (content.IsEmpty()) + return; + + pElement->AppendChild(pdfium::MakeUnique(bCDATA, content)); +} diff --git a/core/fxcrt/xml/cxml_parser.h b/core/fxcrt/xml/cxml_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..a6f1303023c5136fb9382deb96263c989f8bc665 --- /dev/null +++ b/core/fxcrt/xml/cxml_parser.h @@ -0,0 +1,57 @@ +// 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 CORE_FXCRT_XML_CXML_PARSER_H_ +#define CORE_FXCRT_XML_CXML_PARSER_H_ + +#include +#include + +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/xml/cxml_databufacc.h" + +class CFX_UTF8Decoder; +class CXML_Element; + +class CXML_Parser { + public: + CXML_Parser(); + ~CXML_Parser(); + + bool Init(const uint8_t* pBuffer, size_t size); + bool ReadNextBlock(); + bool IsEOF(); + bool HaveAvailData(); + void SkipWhiteSpaces(); + void GetName(ByteString* space, ByteString* name); + WideString GetAttrValue(); + uint32_t GetCharRef(); + void GetTagName(bool bStartTag, + bool* bEndTag, + ByteString* space, + ByteString* name); + void SkipLiterals(const ByteStringView& str); + std::unique_ptr ParseElement(CXML_Element* pParent, + bool bStartTag); + void InsertContentSegment(bool bCDATA, + const WideStringView& content, + CXML_Element* pElement); + void InsertCDATASegment(CFX_UTF8Decoder& decoder, CXML_Element* pElement); + + private: + std::unique_ptr ParseElementInternal(CXML_Element* pParent, + bool bStartTag, + int nDepth); + + std::unique_ptr m_pDataAcc; + FX_FILESIZE m_nOffset; + const uint8_t* m_pBuffer; + size_t m_dwBufferSize; + FX_FILESIZE m_nBufferOffset; + size_t m_dwIndex; +}; + +#endif // CORE_FXCRT_XML_CXML_PARSER_H_ diff --git a/core/fxcrt/xml_int.h b/core/fxcrt/xml_int.h deleted file mode 100644 index 96a7da9c51dec8a458f30a5a82f40a96b603b00d..0000000000000000000000000000000000000000 --- a/core/fxcrt/xml_int.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_XML_INT_H_ -#define CORE_FXCRT_XML_INT_H_ - -#include -#include - -#include "core/fxcrt/fx_stream.h" - -class CFX_UTF8Decoder; -class CXML_Element; - -class CXML_Parser { - public: - CXML_Parser(); - ~CXML_Parser(); - - bool Init(const uint8_t* pBuffer, size_t size); - bool ReadNextBlock(); - bool IsEOF(); - bool HaveAvailData(); - void SkipWhiteSpaces(); - void GetName(CFX_ByteString* space, CFX_ByteString* name); - void GetAttrValue(CFX_WideString& value); - uint32_t GetCharRef(); - void GetTagName(bool bStartTag, - bool* bEndTag, - CFX_ByteString* space, - CFX_ByteString* name); - void SkipLiterals(const CFX_ByteStringC& str); - std::unique_ptr ParseElement(CXML_Element* pParent, - bool bStartTag); - void InsertContentSegment(bool bCDATA, - const CFX_WideStringC& content, - CXML_Element* pElement); - void InsertCDATASegment(CFX_UTF8Decoder& decoder, CXML_Element* pElement); - - CFX_RetainPtr m_pDataAcc; - FX_FILESIZE m_nOffset; - const uint8_t* m_pBuffer; - size_t m_dwBufferSize; - FX_FILESIZE m_nBufferOffset; - size_t m_dwIndex; -}; - -void FX_XML_SplitQualifiedName(const CFX_ByteStringC& bsFullName, - CFX_ByteStringC& bsSpace, - CFX_ByteStringC& bsName); - -#endif // CORE_FXCRT_XML_INT_H_ diff --git a/core/fxge/ge/DEPS b/core/fxge/DEPS similarity index 100% rename from core/fxge/ge/DEPS rename to core/fxge/DEPS diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp index 8c7277752eec68b5c7b6744759609cce71571756..b394facacec81d14d4b6eef6dc02dc8229d119cb 100644 --- a/core/fxge/agg/fx_agg_driver.cpp +++ b/core/fxge/agg/fx_agg_driver.cpp @@ -9,17 +9,12 @@ #include #include -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_memory.h" -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_cliprgn.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/dib/dib_int.h" -#include "core/fxge/ge/cfx_cliprgn.h" -#include "core/fxge/ge/fx_text_int.h" -#include "core/fxge/ifx_renderdevicedriver.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/dib/cfx_imagestretcher.h" #include "third_party/agg23/agg_conv_dash.h" #include "third_party/agg23/agg_conv_stroke.h" #include "third_party/agg23/agg_curves.h" @@ -29,19 +24,25 @@ #include "third_party/agg23/agg_renderer_scanline.h" #include "third_party/agg23/agg_scanline_u.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" namespace { +const float kMaxPos = 32000.0f; + CFX_PointF HardClip(const CFX_PointF& pos) { - return CFX_PointF(std::max(std::min(pos.x, 50000.0f), -50000.0f), - std::max(std::min(pos.y, 50000.0f), -50000.0f)); + return CFX_PointF(pdfium::clamp(pos.x, -kMaxPos, kMaxPos), + pdfium::clamp(pos.y, -kMaxPos, kMaxPos)); } -void RgbByteOrderSetPixel(CFX_DIBitmap* pBitmap, int x, int y, uint32_t argb) { +void RgbByteOrderSetPixel(const RetainPtr& pBitmap, + int x, + int y, + uint32_t argb) { if (x < 0 || x >= pBitmap->GetWidth() || y < 0 || y >= pBitmap->GetHeight()) return; - uint8_t* pos = (uint8_t*)pBitmap->GetBuffer() + y * pBitmap->GetPitch() + + uint8_t* pos = pBitmap->GetBuffer() + y * pBitmap->GetPitch() + x * pBitmap->GetBPP() / 8; if (pBitmap->GetFormat() == FXDIB_Argb) { FXARGB_SETRGBORDERDIB(pos, argb); @@ -54,7 +55,7 @@ void RgbByteOrderSetPixel(CFX_DIBitmap* pBitmap, int x, int y, uint32_t argb) { pos[2] = (FXARGB_B(argb) * alpha + pos[2] * (255 - alpha)) / 255; } -void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, +void RgbByteOrderCompositeRect(const RetainPtr& pBitmap, int left, int top, int width, @@ -71,7 +72,6 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, int src_g = FXARGB_G(argb); int src_b = FXARGB_B(argb); int Bpp = pBitmap->GetBPP() / 8; - bool bAlpha = pBitmap->HasAlpha(); int dib_argb = FXARGB_TOBGRORDERDIB(argb); uint8_t* pBuffer = pBitmap->GetBuffer(); if (src_alpha == 255) { @@ -79,7 +79,7 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, uint8_t* dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp; if (Bpp == 4) { - uint32_t* scan = (uint32_t*)dest_scan; + uint32_t* scan = reinterpret_cast(dest_scan); for (int col = 0; col < width; col++) *scan++ = dib_argb; } else { @@ -92,6 +92,7 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, } return; } + bool bAlpha = pBitmap->HasAlpha(); for (int row = rect.top; row < rect.bottom; row++) { uint8_t* dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp; if (bAlpha) { @@ -114,27 +115,27 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); dest_scan += 2; } - } else { - for (int col = 0; col < width; col++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); + continue; + } + for (int col = 0; col < width; col++) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); + dest_scan++; + if (Bpp == 4) dest_scan++; - if (Bpp == 4) - dest_scan++; - } } } } -void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, +void RgbByteOrderTransferBitmap(const RetainPtr& pBitmap, int dest_left, int dest_top, int width, int height, - const CFX_DIBSource* pSrcBitmap, + const RetainPtr& pSrcBitmap, int src_left, int src_top) { if (!pBitmap) @@ -155,7 +156,8 @@ void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, for (int row = 0; row < height; row++) { uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp; uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; + const_cast(pSrcBitmap->GetScanline(src_top + row)) + + src_left * Bpp; if (Bpp == 4) { for (int col = 0; col < width; col++) { FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0], @@ -163,13 +165,13 @@ void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, dest_scan += 4; src_scan += 4; } - } else { - for (int col = 0; col < width; col++) { - *dest_scan++ = src_scan[2]; - *dest_scan++ = src_scan[1]; - *dest_scan++ = src_scan[0]; - src_scan += 3; - } + continue; + } + for (int col = 0; col < width; col++) { + *dest_scan++ = src_scan[2]; + *dest_scan++ = src_scan[1]; + *dest_scan++ = src_scan[0]; + src_scan += 3; } } return; @@ -177,190 +179,76 @@ void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, uint8_t* dest_buf = buffer + dest_top * pitch + dest_left * Bpp; if (dest_format == FXDIB_Rgb) { - if (src_format == FXDIB_Rgb32) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * pitch; - uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4; - for (int col = 0; col < width; col++) { - *dest_scan++ = src_scan[2]; - *dest_scan++ = src_scan[1]; - *dest_scan++ = src_scan[0]; - src_scan += 4; - } + ASSERT(src_format == FXDIB_Rgb32); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = dest_buf + row * pitch; + uint8_t* src_scan = + const_cast(pSrcBitmap->GetScanline(src_top + row)) + + src_left * 4; + for (int col = 0; col < width; col++) { + *dest_scan++ = src_scan[2]; + *dest_scan++ = src_scan[1]; + *dest_scan++ = src_scan[0]; + src_scan += 4; } - } else { - ASSERT(false); } return; } - if (dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32) { - if (src_format == FXDIB_Rgb) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = (uint8_t*)(dest_buf + row * pitch); - uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3; - for (int col = 0; col < width; col++) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], - src_scan[2])); - dest_scan += 4; - src_scan += 3; - } - } - } else if (src_format == FXDIB_Rgb32) { - ASSERT(dest_format == FXDIB_Argb); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * pitch; - uint8_t* src_scan = - (uint8_t*)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4); - for (int col = 0; col < width; col++) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], - src_scan[2])); - src_scan += 4; - dest_scan += 4; - } + ASSERT(dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32); + if (src_format == FXDIB_Rgb) { + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = dest_buf + row * pitch; + uint8_t* src_scan = + const_cast(pSrcBitmap->GetScanline(src_top + row)) + + src_left * 3; + for (int col = 0; col < width; col++) { + FXARGB_SETDIB(dest_scan, + FXARGB_MAKE(0xff, src_scan[0], src_scan[1], src_scan[2])); + dest_scan += 4; + src_scan += 3; } } return; } - - ASSERT(false); -} - -FX_ARGB DefaultCMYK2ARGB(FX_CMYK cmyk, uint8_t alpha) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), - FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, g, b); - return ArgbEncode(alpha, r, g, b); + if (src_format != FXDIB_Rgb32) + return; + ASSERT(dest_format == FXDIB_Argb); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = dest_buf + row * pitch; + uint8_t* src_scan = + const_cast(pSrcBitmap->GetScanline(src_top + row)) + + src_left * 4; + for (int col = 0; col < width; col++) { + FXARGB_SETDIB(dest_scan, + FXARGB_MAKE(0xff, src_scan[0], src_scan[1], src_scan[2])); + src_scan += 4; + dest_scan += 4; + } + } } -bool DibSetPixel(CFX_DIBitmap* pDevice, +bool DibSetPixel(const RetainPtr& pDevice, int x, int y, - uint32_t color, - int alpha_flag, - void* pIccTransform) { - bool bObjCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); - int alpha = bObjCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); - if (pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - color = bObjCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&color, - (uint8_t*)&color, 1); - color = bObjCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - if (!pDevice->IsCmykImage()) { - color = (color & 0xffffff) | (alpha << 24); - } - } else { - if (pDevice->IsCmykImage()) { - if (!bObjCMYK) - return false; - } else { - if (bObjCMYK) - color = DefaultCMYK2ARGB(color, alpha); - } - } + uint32_t color) { + int alpha = FXARGB_A(color); + if (pDevice->IsCmykImage()) + return false; + pDevice->SetPixel(x, y, color); - if (pDevice->m_pAlphaMask) { + if (pDevice->m_pAlphaMask) pDevice->m_pAlphaMask->SetPixel(x, y, alpha << 24); - } return true; } -} // namespace - -void CAgg_PathData::BuildPath(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device) { - const std::vector& pPoints = pPathData->GetPoints(); - for (size_t i = 0; i < pPoints.size(); i++) { - CFX_PointF pos = pPoints[i].m_Point; - if (pObject2Device) - pos = pObject2Device->Transform(pos); - - pos = HardClip(pos); - FXPT_TYPE point_type = pPoints[i].m_Type; - if (point_type == FXPT_TYPE::MoveTo) { - m_PathData.move_to(pos.x, pos.y); - } else if (point_type == FXPT_TYPE::LineTo) { - if (pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) && - (i == pPoints.size() - 1 || - pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) && - pPoints[i].m_Point == pPoints[i - 1].m_Point) { - pos.x += 1; - } - m_PathData.line_to(pos.x, pos.y); - } else if (point_type == FXPT_TYPE::BezierTo) { - CFX_PointF pos0 = pPoints[i - 1].m_Point; - CFX_PointF pos2 = pPoints[i + 1].m_Point; - CFX_PointF pos3 = pPoints[i + 2].m_Point; - if (pObject2Device) { - pos0 = pObject2Device->Transform(pos0); - pos2 = pObject2Device->Transform(pos2); - pos3 = pObject2Device->Transform(pos3); - } - pos0 = HardClip(pos0); - pos2 = HardClip(pos2); - pos3 = HardClip(pos3); - agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x, - pos3.y); - i += 2; - m_PathData.add_path_curve(curve); - } - if (pPoints[i].m_CloseFigure) - m_PathData.end_poly(); - } -} - -namespace agg { - -template -class renderer_scanline_aa_offset { - public: - typedef BaseRenderer base_ren_type; - typedef typename base_ren_type::color_type color_type; - renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top) - : m_ren(&ren), m_left(left), m_top(top) {} - void color(const color_type& c) { m_color = c; } - const color_type& color() const { return m_color; } - void prepare(unsigned) {} - template - void render(const Scanline& sl) { - int y = sl.y(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - for (;;) { - int x = span->x; - if (span->len > 0) { - m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len, - m_color, span->covers); - } else { - m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1), - m_color, *(span->covers)); - } - if (--num_spans == 0) { - break; - } - ++span; - } - } - - private: - base_ren_type* m_ren; - color_type m_color; - unsigned m_left, m_top; -}; - -} // namespace agg - -static void RasterizeStroke(agg::rasterizer_scanline_aa& rasterizer, - agg::path_storage& path_data, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState, - FX_FLOAT scale = 1.0f, - bool bStrokeAdjust = false, - bool bTextMode = false) { +void RasterizeStroke(agg::rasterizer_scanline_aa* rasterizer, + agg::path_storage* path_data, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + float scale, + bool bStrokeAdjust, + bool bTextMode) { agg::line_cap_e cap; switch (pGraphState->m_LineCap) { case CFX_GraphStateData::LineCapRound: @@ -385,29 +273,24 @@ static void RasterizeStroke(agg::rasterizer_scanline_aa& rasterizer, join = agg::miter_join_revert; break; } - FX_FLOAT width = pGraphState->m_LineWidth * scale; - FX_FLOAT unit = 1.f; + float width = pGraphState->m_LineWidth * scale; + float unit = 1.0f; if (pObject2Device) { unit = 1.0f / ((pObject2Device->GetXUnit() + pObject2Device->GetYUnit()) / 2); } - if (width < unit) { - width = unit; - } + width = std::max(width, unit); if (pGraphState->m_DashArray) { typedef agg::conv_dash dash_converter; - dash_converter dash(path_data); + dash_converter dash(*path_data); for (int i = 0; i < (pGraphState->m_DashCount + 1) / 2; i++) { - FX_FLOAT on = pGraphState->m_DashArray[i * 2]; - if (on <= 0.000001f) { + float on = pGraphState->m_DashArray[i * 2]; + if (on <= 0.000001f) on = 1.0f / 10; - } - FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount - ? on - : pGraphState->m_DashArray[i * 2 + 1]; - if (off < 0) { - off = 0; - } + float off = i * 2 + 1 == pGraphState->m_DashCount + ? on + : pGraphState->m_DashArray[i * 2 + 1]; + off = std::max(off, 0.0f); dash.add_dash(on * scale, off * scale); } dash.dash_start(pGraphState->m_DashPhase * scale); @@ -417,325 +300,190 @@ static void RasterizeStroke(agg::rasterizer_scanline_aa& rasterizer, stroke.line_cap(cap); stroke.miter_limit(pGraphState->m_MiterLimit); stroke.width(width); - rasterizer.add_path_transformed(stroke, pObject2Device); - } else { - agg::conv_stroke stroke(path_data); - stroke.line_join(join); - stroke.line_cap(cap); - stroke.miter_limit(pGraphState->m_MiterLimit); - stroke.width(width); - rasterizer.add_path_transformed(stroke, pObject2Device); + rasterizer->add_path_transformed(stroke, pObject2Device); + return; } + agg::conv_stroke stroke(*path_data); + stroke.line_join(join); + stroke.line_cap(cap); + stroke.miter_limit(pGraphState->m_MiterLimit); + stroke.width(width); + rasterizer->add_path_transformed(stroke, pObject2Device); } -CFX_AggDeviceDriver::CFX_AggDeviceDriver(CFX_DIBitmap* pBitmap, - bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, - bool bGroupKnockout) - : m_pBitmap(pBitmap), -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_pPlatformGraphics(nullptr), -#endif - m_FillFlags(0), - m_bRgbByteOrder(bRgbByteOrder), - m_pOriDevice(pOriDevice), - m_bGroupKnockout(bGroupKnockout) { - InitPlatform(); -} +class CFX_Renderer { + public: + // Needed for agg caller + void prepare(unsigned) {} -CFX_AggDeviceDriver::~CFX_AggDeviceDriver() { - DestroyPlatform(); -} + void CompositeSpan(uint8_t* dest_scan, + uint8_t* ori_scan, + int Bpp, + bool bDestAlpha, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan); -uint8_t* CFX_AggDeviceDriver::GetBuffer() const { - return m_pBitmap->GetBuffer(); -} + void CompositeSpan1bpp(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ -void CFX_AggDeviceDriver::InitPlatform() {} + void CompositeSpanGray(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan); -void CFX_AggDeviceDriver::DestroyPlatform() {} + void CompositeSpanARGB(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan); -bool CFX_AggDeviceDriver::DrawDeviceText(int nChars, - const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, - const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, - uint32_t color) { - return false; -} -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ + void CompositeSpanRGB(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan); -int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const { - switch (caps_id) { - case FXDC_DEVICE_CLASS: - return FXDC_DISPLAY; - case FXDC_PIXEL_WIDTH: - return m_pBitmap->GetWidth(); - case FXDC_PIXEL_HEIGHT: - return m_pBitmap->GetHeight(); - case FXDC_BITS_PIXEL: - return m_pBitmap->GetBPP(); - case FXDC_HORZ_SIZE: - case FXDC_VERT_SIZE: - return 0; - case FXDC_RENDER_CAPS: { - int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | - FXRC_BLEND_MODE | FXRC_SOFT_CLIP; - if (m_pBitmap->HasAlpha()) { - flags |= FXRC_ALPHA_OUTPUT; - } else if (m_pBitmap->IsAlphaMask()) { - if (m_pBitmap->GetBPP() == 1) { - flags |= FXRC_BITMASK_OUTPUT; - } else { - flags |= FXRC_BYTEMASK_OUTPUT; - } - } - if (m_pBitmap->IsCmykImage()) { - flags |= FXRC_CMYK_OUTPUT; - } - return flags; - } - } - return 0; -} + void CompositeSpanCMYK(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan); -void CFX_AggDeviceDriver::SaveState() { - std::unique_ptr pClip; - if (m_pClipRgn) - pClip = pdfium::MakeUnique(*m_pClipRgn); - m_StateStack.push_back(std::move(pClip)); -} + bool Init(const RetainPtr& pDevice, + const RetainPtr& pOriDevice, + const CFX_ClipRgn* pClipRgn, + uint32_t color, + bool bFullCover, + bool bRgbByteOrder); -void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) { - m_pClipRgn.reset(); + template + void render(const Scanline& sl); - if (m_StateStack.empty()) - return; + private: + void (CFX_Renderer::*composite_span)(uint8_t*, + int, + int, + int, + uint8_t*, + int, + int, + uint8_t*, + uint8_t*); - if (bKeepSaved) { - if (m_StateStack.back()) - m_pClipRgn = pdfium::MakeUnique(*m_StateStack.back()); - } else { - m_pClipRgn = std::move(m_StateStack.back()); - m_StateStack.pop_back(); - } -} + void CompositeSpan1bppHelper(uint8_t* dest_scan, + int col_start, + int col_end, + const uint8_t* cover_scan, + const uint8_t* clip_scan, + int span_left); -void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) { - FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(), - rasterizer.max_x() + 1, rasterizer.max_y() + 1); - path_rect.Intersect(m_pClipRgn->GetBox()); - CFX_DIBitmapRef mask; - CFX_DIBitmap* pThisLayer = mask.Emplace(); - pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); - pThisLayer->Clear(0); - agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(), - pThisLayer->GetHeight(), - pThisLayer->GetPitch()); - agg::pixfmt_gray8 pixel_buf(raw_buf); - agg::renderer_base base_buf(pixel_buf); - agg::renderer_scanline_aa_offset > - final_render(base_buf, path_rect.left, path_rect.top); - final_render.color(agg::gray8(255)); - agg::scanline_u8 scanline; - agg::render_scanlines(rasterizer, scanline, final_render, - (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0); - m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask); -} + inline int GetSrcAlpha(const uint8_t* clip_scan, int col) const { + return clip_scan ? m_Alpha * clip_scan[col] / 255 : m_Alpha; + } -bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - int fill_mode) { - m_FillFlags = fill_mode; - if (!m_pClipRgn) { - m_pClipRgn = pdfium::MakeUnique( - GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); + inline int GetSourceAlpha(const uint8_t* cover_scan, + const uint8_t* clip_scan, + int col) const { + return clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255 + : m_Alpha * cover_scan[col] / 255; } - size_t size = pPathData->GetPoints().size(); - if (size == 5 || size == 4) { - CFX_FloatRect rectf; - if (pPathData->IsRect(pObject2Device, &rectf)) { - rectf.Intersect( - CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH), - (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - FX_RECT rect = rectf.GetOuterRect(); - m_pClipRgn->IntersectRect(rect); - return true; - } + + inline int GetColStart(int span_left, int clip_left) const { + return span_left < clip_left ? clip_left - span_left : 0; } - CAgg_PathData path_data; - path_data.BuildPath(pPathData, pObject2Device); - path_data.m_PathData.end_poly(); - agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - rasterizer.add_path(path_data.m_PathData); - rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING - ? agg::fill_non_zero - : agg::fill_even_odd); - SetClipMask(rasterizer); - return true; -} -bool CFX_AggDeviceDriver::SetClip_PathStroke( - const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState) { - if (!m_pClipRgn) { - m_pClipRgn = pdfium::MakeUnique( - GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); + inline int GetColEnd(int span_left, int span_len, int clip_right) const { + return span_left + span_len < clip_right ? span_len + : clip_right - span_left; } - CAgg_PathData path_data; - path_data.BuildPath(pPathData, nullptr); - agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - RasterizeStroke(rasterizer, path_data.m_PathData, pObject2Device, - pGraphState); - rasterizer.filling_rule(agg::fill_non_zero); - SetClipMask(rasterizer); - return true; -} -class CFX_Renderer { - private: - int m_Alpha, m_Red, m_Green, m_Blue, m_Gray; + int m_Alpha; + int m_Red; + int m_Green; + int m_Blue; + int m_Gray; uint32_t m_Color; bool m_bFullCover; bool m_bRgbByteOrder; - CFX_DIBitmap* m_pOriDevice; FX_RECT m_ClipBox; - const CFX_DIBitmap* m_pClipMask; - CFX_DIBitmap* m_pDevice; - const CFX_ClipRgn* m_pClipRgn; - void (CFX_Renderer::*composite_span)(uint8_t*, - int, - int, - int, - uint8_t*, - int, - int, - uint8_t*, - uint8_t*); - - public: - void prepare(unsigned) {} + RetainPtr m_pOriDevice; + RetainPtr m_pClipMask; + RetainPtr m_pDevice; + UnownedPtr m_pClipRgn; +}; - void CompositeSpan(uint8_t* dest_scan, - uint8_t* ori_scan, - int Bpp, - bool bDestAlpha, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan) { - ASSERT(!m_pDevice->IsCmykImage()); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - if (Bpp) { - dest_scan += col_start * Bpp; - ori_scan += col_start * Bpp; - } else { - dest_scan += col_start / 8; - ori_scan += col_start / 8; - } - if (m_bRgbByteOrder) { - if (Bpp == 4 && bDestAlpha) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - uint8_t dest_alpha = - ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); - dest_scan++; - ori_scan++; - } else { - int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); - int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); - ori_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += 2; - } - } - return; - } - if (Bpp == 3 || Bpp == 4) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); - ori_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += Bpp - 2; - } - } - return; - } +void CFX_Renderer::CompositeSpan(uint8_t* dest_scan, + uint8_t* ori_scan, + int Bpp, + bool bDestAlpha, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan) { + ASSERT(!m_pDevice->IsCmykImage()); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + if (Bpp) { + dest_scan += col_start * Bpp; + ori_scan += col_start * Bpp; + } else { + dest_scan += col_start / 8; + ori_scan += col_start / 8; + } + if (m_bRgbByteOrder) { if (Bpp == 4 && bDestAlpha) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - int src_alpha_covered = src_alpha * cover_scan[col] / 255; - if (src_alpha_covered == 0) { - dest_scan += 4; - continue; - } - if (cover_scan[col] == 255) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; + int src_alpha = GetSrcAlpha(clip_scan, col); + uint8_t dest_alpha = + ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (m_bFullCover) { + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); + dest_scan++; + ori_scan++; } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t cover = cover_scan[col]; - dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); + int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); + int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); + int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); + ori_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); dest_scan += 2; } } @@ -743,688 +491,788 @@ class CFX_Renderer { } if (Bpp == 3 || Bpp == 4) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - ori_scan += Bpp - 2; - continue; - } - int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); + int src_alpha = GetSrcAlpha(clip_scan, col); + int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); + int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); ori_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); dest_scan += Bpp - 2; - continue; } - return; } - if (Bpp == 1) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - if (m_bFullCover) { - *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); - } else { - int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); - dest_scan++; - } + return; + } + if (Bpp == 4 && bDestAlpha) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + int src_alpha_covered = src_alpha * cover_scan[col] / 255; + if (src_alpha_covered == 0) { + dest_scan += 4; + continue; } - } else { - int index = 0; - if (m_pDevice->GetPalette()) { - for (int i = 0; i < 2; i++) { - if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { - index = i; - } - } - } else { - index = ((uint8_t)m_Color == 0xff) ? 1 : 0; + if (cover_scan[col] == 255) { + dest_scan[3] = src_alpha_covered; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; } - uint8_t* dest_scan1 = dest_scan; - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (!index) { - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - } else { - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); - } - } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; + if (dest_scan[3] == 0) { + dest_scan[3] = src_alpha_covered; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; } + uint8_t cover = cover_scan[col]; + dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); + dest_scan += 2; } + return; } - - void CompositeSpan1bpp(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - ASSERT(!m_bRgbByteOrder); - ASSERT(!m_pDevice->IsCmykImage()); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start / 8; - int index = 0; - if (m_pDevice->GetPalette()) { - for (int i = 0; i < 2; i++) { - if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { - index = i; - } + if (Bpp == 3 || Bpp == 4) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + if (m_bFullCover) { + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); + dest_scan += Bpp - 2; + ori_scan += Bpp - 2; + continue; } - } else { - index = ((uint8_t)m_Color == 0xff) ? 1 : 0; + int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); + int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); + int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); + ori_scan += Bpp - 2; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); + dest_scan += Bpp - 2; + continue; } - uint8_t* dest_scan1 = dest_scan; + return; + } + if (Bpp == 1) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (!index) { - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - } else { - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); - } + int src_alpha = GetSrcAlpha(clip_scan, col); + if (m_bFullCover) { + *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); + continue; } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; + int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); + dest_scan++; } + return; } + CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan, + span_left); +} - void CompositeSpanGray(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - ASSERT(!m_bRgbByteOrder); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start; - if (dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan = m_Gray; - *dest_extra_alpha_scan = m_Alpha; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); - dest_scan++; - continue; - } - } - dest_extra_alpha_scan++; - dest_scan++; - } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; +void CFX_Renderer::CompositeSpan1bpp(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan) { + ASSERT(!m_bRgbByteOrder); + ASSERT(!m_pDevice->IsCmykImage()); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start / 8; + CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan, + span_left); +} + +void CFX_Renderer::CompositeSpanGray(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan) { + ASSERT(!m_bRgbByteOrder); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start; + if (dest_extra_alpha_scan) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *dest_scan = m_Gray; + *dest_extra_alpha_scan = m_Alpha; } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan = m_Gray; - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); - } + uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - + (*dest_extra_alpha_scan) * src_alpha / 255; + *dest_extra_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); + dest_scan++; + continue; } - dest_scan++; } + dest_extra_alpha_scan++; + dest_scan++; } + return; } - - void CompositeSpanARGB(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *(uint32_t*)dest_scan = m_Color; - } else { - uint8_t dest_alpha = - dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan += 2; - continue; - } - } - dest_scan += 4; - } - return; + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) + *dest_scan = m_Gray; + else + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); } + dest_scan++; + } +} + +void CFX_Renderer::CompositeSpanARGB(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan) { + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start * Bpp; + if (m_bRgbByteOrder) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); if (src_alpha) { if (src_alpha == 255) { - *(uint32_t*)dest_scan = m_Color; + *(reinterpret_cast(dest_scan)) = m_Color; } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } uint8_t dest_alpha = dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; dest_scan[3] = dest_alpha; int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); dest_scan += 2; continue; } } - dest_scan += Bpp; + dest_scan += 4; } + return; } - - void CompositeSpanRGB(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - if (Bpp == 4) { - *(uint32_t*)dest_scan = m_Color; - } else if (Bpp == 3) { - *dest_scan++ = m_Red; - *dest_scan++ = m_Green; - *dest_scan++ = m_Blue; - continue; - } - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan += Bpp - 2; - continue; - } + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast(dest_scan)) = m_Color; + } else { + if (dest_scan[3] == 0) { + dest_scan[3] = src_alpha; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; } - dest_scan += Bpp; + uint8_t dest_alpha = + dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan += 2; + continue; } - return; } - if (Bpp == 3 && dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan++ = (uint8_t)m_Blue; - *dest_scan++ = (uint8_t)m_Green; - *dest_scan++ = (uint8_t)m_Red; - *dest_extra_alpha_scan++ = (uint8_t)m_Alpha; - continue; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; + dest_scan += Bpp; + } +} + +void CFX_Renderer::CompositeSpanRGB(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan) { + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start * Bpp; + if (m_bRgbByteOrder) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + if (Bpp == 4) { + *(uint32_t*)dest_scan = m_Color; + } else if (Bpp == 3) { + *dest_scan++ = m_Red; + *dest_scan++ = m_Green; + *dest_scan++ = m_Blue; continue; } + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + dest_scan += Bpp - 2; + continue; } - dest_extra_alpha_scan++; - dest_scan += Bpp; } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } + dest_scan += Bpp; + } + return; + } + if (Bpp == 3 && dest_extra_alpha_scan) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *dest_scan++ = static_cast(m_Blue); + *dest_scan++ = static_cast(m_Green); + *dest_scan++ = static_cast(m_Red); + *dest_extra_alpha_scan++ = static_cast(m_Alpha); + continue; } - if (src_alpha) { - if (src_alpha == 255) { - if (Bpp == 4) { - *(uint32_t*)dest_scan = m_Color; - } else if (Bpp == 3) { - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan++ = m_Red; - continue; - } - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - continue; - } + uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - + (*dest_extra_alpha_scan) * src_alpha / 255; + *dest_extra_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan++; + continue; + } + dest_extra_alpha_scan++; + dest_scan += Bpp; + } + return; + } + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + if (Bpp == 4) { + *(uint32_t*)dest_scan = m_Color; + } else if (Bpp == 3) { + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan++ = m_Red; + continue; } - dest_scan += Bpp; + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + dest_scan += Bpp - 2; + continue; } } + dest_scan += Bpp; } +} - void CompositeSpanCMYK(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - ASSERT(!m_bRgbByteOrder); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * 4; - if (dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } +void CFX_Renderer::CompositeSpanCMYK(uint8_t* dest_scan, + int Bpp, + int span_left, + int span_len, + uint8_t* cover_scan, + int clip_left, + int clip_right, + uint8_t* clip_scan, + uint8_t* dest_extra_alpha_scan) { + ASSERT(!m_bRgbByteOrder); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start * 4; + if (dest_extra_alpha_scan) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast(dest_scan)) = m_Color; + *dest_extra_alpha_scan = static_cast(m_Alpha); } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *(FX_CMYK*)dest_scan = m_Color; - *dest_extra_alpha_scan = (uint8_t)m_Alpha; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); - dest_scan++; - continue; - } + uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - + (*dest_extra_alpha_scan) * src_alpha / 255; + *dest_extra_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); + dest_scan++; + continue; } - dest_extra_alpha_scan++; - dest_scan += 4; } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *(FX_CMYK*)dest_scan = m_Color; - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); - dest_scan++; - continue; - } - } - dest_scan += 4; + dest_extra_alpha_scan++; + dest_scan += 4; + } + return; + } + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast(dest_scan)) = m_Color; + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); + dest_scan++; + continue; } } + dest_scan += 4; + } +} + +bool CFX_Renderer::Init(const RetainPtr& pDevice, + const RetainPtr& pOriDevice, + const CFX_ClipRgn* pClipRgn, + uint32_t color, + bool bFullCover, + bool bRgbByteOrder) { + m_pDevice = pDevice; + m_pClipRgn = pClipRgn; + composite_span = nullptr; + m_bRgbByteOrder = bRgbByteOrder; + m_pOriDevice = pOriDevice; + if (m_pClipRgn) { + m_ClipBox = m_pClipRgn->GetBox(); + } else { + m_ClipBox.left = m_ClipBox.top = 0; + m_ClipBox.right = m_pDevice->GetWidth(); + m_ClipBox.bottom = m_pDevice->GetHeight(); + } + m_pClipMask = nullptr; + if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) + m_pClipMask = m_pClipRgn->GetMask(); + m_bFullCover = bFullCover; + bool bDeviceCMYK = pDevice->IsCmykImage(); + m_Alpha = FXARGB_A(color); + if (m_pDevice->GetBPP() == 8) { + ASSERT(!m_bRgbByteOrder); + composite_span = &CFX_Renderer::CompositeSpanGray; + if (m_pDevice->IsAlphaMask()) + m_Gray = 255; + else + m_Gray = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); + return true; + } + if (bDeviceCMYK) { + ASSERT(!m_bRgbByteOrder); + composite_span = &CFX_Renderer::CompositeSpanCMYK; + return false; + } + composite_span = (pDevice->GetFormat() == FXDIB_Argb) + ? &CFX_Renderer::CompositeSpanARGB + : &CFX_Renderer::CompositeSpanRGB; + if (m_bRgbByteOrder) + m_Color = FXARGB_TOBGRORDERDIB(color); + else + m_Color = FXARGB_TODIB(color); + std::tie(m_Alpha, m_Red, m_Green, m_Blue) = ArgbDecode(color); + if (m_pDevice->GetBPP() == 1) + composite_span = &CFX_Renderer::CompositeSpan1bpp; + return true; +} + +template +void CFX_Renderer::render(const Scanline& sl) { + if (!m_pOriDevice && !composite_span) + return; + + int y = sl.y(); + if (y < m_ClipBox.top || y >= m_ClipBox.bottom) + return; + + uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; + uint8_t* dest_scan_extra_alpha = nullptr; + RetainPtr pAlphaMask = m_pDevice->m_pAlphaMask; + if (pAlphaMask) { + dest_scan_extra_alpha = + pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; + } + uint8_t* ori_scan = nullptr; + if (m_pOriDevice) + ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; + int Bpp = m_pDevice->GetBPP() / 8; + bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + while (1) { + if (span->len <= 0) + break; + + int x = span->x; + uint8_t* dest_pos = nullptr; + uint8_t* dest_extra_alpha_pos = nullptr; + uint8_t* ori_pos = nullptr; + if (Bpp) { + ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; + dest_pos = dest_scan + x * Bpp; + dest_extra_alpha_pos = + dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; + } else { + dest_pos = dest_scan + x / 8; + ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; + } + uint8_t* clip_pos = nullptr; + if (m_pClipMask) { + clip_pos = m_pClipMask->GetBuffer() + + (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - + m_ClipBox.left; + } + if (ori_pos) { + CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, + span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); + } else { + (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, + m_ClipBox.left, m_ClipBox.right, clip_pos, + dest_extra_alpha_pos); + } + if (--num_spans == 0) + break; + + ++span; + } +} + +void CFX_Renderer::CompositeSpan1bppHelper(uint8_t* dest_scan, + int col_start, + int col_end, + const uint8_t* cover_scan, + const uint8_t* clip_scan, + int span_left) { + int index = 0; + if (m_pDevice->GetPalette()) { + for (int i = 0; i < 2; i++) { + if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) + index = i; + } + } else { + index = (static_cast(m_Color) == 0xff) ? 1 : 0; + } + uint8_t* dest_scan1 = dest_scan; + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (!index) + *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); + else + *dest_scan1 |= 1 << (7 - (col + span_left) % 8); + } + dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; } +} + +} // namespace +namespace agg { + +template +class renderer_scanline_aa_offset { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top) + : m_ren(&ren), m_left(left), m_top(top) {} + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + void prepare(unsigned) {} template void render(const Scanline& sl) { - if (!m_pOriDevice && !composite_span) { - return; - } int y = sl.y(); - if (y < m_ClipBox.top || y >= m_ClipBox.bottom) { - return; - } - uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; - uint8_t* dest_scan_extra_alpha = nullptr; - CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask; - if (pAlphaMask) { - dest_scan_extra_alpha = - pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; - } - uint8_t* ori_scan = nullptr; - if (m_pOriDevice) { - ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; - } - int Bpp = m_pDevice->GetBPP() / 8; - bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); while (1) { int x = span->x; - ASSERT(span->len > 0); - uint8_t* dest_pos = nullptr; - uint8_t* dest_extra_alpha_pos = nullptr; - uint8_t* ori_pos = nullptr; - if (Bpp) { - ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; - dest_pos = dest_scan + x * Bpp; - dest_extra_alpha_pos = - dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; - } else { - dest_pos = dest_scan + x / 8; - ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; - } - uint8_t* clip_pos = nullptr; - if (m_pClipMask) { - clip_pos = m_pClipMask->GetBuffer() + - (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - - m_ClipBox.left; - } - if (ori_pos) { - CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, - span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); + if (span->len > 0) { + m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len, + m_color, span->covers); } else { - (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, - m_ClipBox.left, m_ClipBox.right, clip_pos, - dest_extra_alpha_pos); + m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1), + m_color, *(span->covers)); } - if (--num_spans == 0) { + if (--num_spans == 0) break; - } + ++span; } } - bool Init(CFX_DIBitmap* pDevice, - CFX_DIBitmap* pOriDevice, - const CFX_ClipRgn* pClipRgn, - uint32_t color, - bool bFullCover, - bool bRgbByteOrder, - int alpha_flag = 0, - void* pIccTransform = nullptr) { - m_pDevice = pDevice; - m_pClipRgn = pClipRgn; - composite_span = nullptr; - m_bRgbByteOrder = bRgbByteOrder; - m_pOriDevice = pOriDevice; - if (m_pClipRgn) { - m_ClipBox = m_pClipRgn->GetBox(); - } else { - m_ClipBox.left = m_ClipBox.top = 0; - m_ClipBox.right = m_pDevice->GetWidth(); - m_ClipBox.bottom = m_pDevice->GetHeight(); - } - m_pClipMask = nullptr; - if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) { - m_pClipMask = m_pClipRgn->GetMask().GetObject(); - } - m_bFullCover = bFullCover; - bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); - bool bDeviceCMYK = pDevice->IsCmykImage(); - m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); - CCodec_IccModule* pIccModule = nullptr; - if (!CFX_GEModule::Get()->GetCodecModule() || - !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - pIccTransform = nullptr; - } else { - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - } - if (m_pDevice->GetBPP() == 8) { - ASSERT(!m_bRgbByteOrder); - composite_span = &CFX_Renderer::CompositeSpanGray; - if (m_pDevice->IsAlphaMask()) { - m_Gray = 255; - } else { - if (pIccTransform) { - uint8_t gray; - color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, &gray, - (const uint8_t*)&color, 1); - m_Gray = gray; - } else { - if (bObjectCMYK) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), - r, g, b); - m_Gray = FXRGB2GRAY(r, g, b); - } else { - m_Gray = - FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); - } - } + private: + base_ren_type* m_ren; + color_type m_color; + unsigned m_left, m_top; +}; + +} // namespace agg + +void CAgg_PathData::BuildPath(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device) { + const std::vector& pPoints = pPathData->GetPoints(); + for (size_t i = 0; i < pPoints.size(); i++) { + CFX_PointF pos = pPoints[i].m_Point; + if (pObject2Device) + pos = pObject2Device->Transform(pos); + + pos = HardClip(pos); + FXPT_TYPE point_type = pPoints[i].m_Type; + if (point_type == FXPT_TYPE::MoveTo) { + m_PathData.move_to(pos.x, pos.y); + } else if (point_type == FXPT_TYPE::LineTo) { + if (i > 0 && pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) && + (i == pPoints.size() - 1 || + pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) && + pPoints[i].m_Point == pPoints[i - 1].m_Point) { + pos.x += 1; } - return true; - } - if (bDeviceCMYK) { - ASSERT(!m_bRgbByteOrder); - composite_span = &CFX_Renderer::CompositeSpanCMYK; - if (bObjectCMYK) { - m_Color = FXCMYK_TODIB(color); - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&m_Color, 1); - } - } else { - if (!pIccTransform) { - return false; + m_PathData.line_to(pos.x, pos.y); + } else if (point_type == FXPT_TYPE::BezierTo) { + if (i > 0 && i + 2 < pPoints.size()) { + CFX_PointF pos0 = pPoints[i - 1].m_Point; + CFX_PointF pos2 = pPoints[i + 1].m_Point; + CFX_PointF pos3 = pPoints[i + 2].m_Point; + if (pObject2Device) { + pos0 = pObject2Device->Transform(pos0); + pos2 = pObject2Device->Transform(pos2); + pos3 = pObject2Device->Transform(pos3); } - color = FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&color, 1); + pos0 = HardClip(pos0); + pos2 = HardClip(pos2); + pos3 = HardClip(pos3); + agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x, + pos3.y); + i += 2; + m_PathData.add_path_curve(curve); } - m_Red = ((uint8_t*)&m_Color)[0]; - m_Green = ((uint8_t*)&m_Color)[1]; - m_Blue = ((uint8_t*)&m_Color)[2]; - m_Gray = ((uint8_t*)&m_Color)[3]; - } else { - composite_span = (pDevice->GetFormat() == FXDIB_Argb) - ? &CFX_Renderer::CompositeSpanARGB - : &CFX_Renderer::CompositeSpanRGB; - if (pIccTransform) { - color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&color, 1); - ((uint8_t*)&m_Color)[3] = m_Alpha; - m_Red = ((uint8_t*)&m_Color)[2]; - m_Green = ((uint8_t*)&m_Color)[1]; - m_Blue = ((uint8_t*)&m_Color)[0]; - if (m_bRgbByteOrder) { - m_Color = FXARGB_TODIB(m_Color); - m_Color = FXARGB_TOBGRORDERDIB(m_Color); - } - } else { - if (bObjectCMYK) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, - g, b); - m_Color = FXARGB_MAKE(m_Alpha, r, g, b); - if (m_bRgbByteOrder) { - m_Color = FXARGB_TOBGRORDERDIB(m_Color); - } else { - m_Color = FXARGB_TODIB(m_Color); - } - m_Red = r; - m_Green = g; - m_Blue = b; - } else { - if (m_bRgbByteOrder) { - m_Color = FXARGB_TOBGRORDERDIB(color); - } else { - m_Color = FXARGB_TODIB(color); - } - ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue); - } + } + if (pPoints[i].m_CloseFigure) + m_PathData.end_poly(); + } +} + +CFX_AggDeviceDriver::CFX_AggDeviceDriver( + const RetainPtr& pBitmap, + bool bRgbByteOrder, + const RetainPtr& pOriDevice, + bool bGroupKnockout) + : m_pBitmap(pBitmap), +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + m_pPlatformGraphics(nullptr), +#endif + m_FillFlags(0), + m_bRgbByteOrder(bRgbByteOrder), + m_pOriDevice(pOriDevice), + m_bGroupKnockout(bGroupKnockout) { + InitPlatform(); +} + +CFX_AggDeviceDriver::~CFX_AggDeviceDriver() { + DestroyPlatform(); +} + +uint8_t* CFX_AggDeviceDriver::GetBuffer() const { + return m_pBitmap->GetBuffer(); +} + +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ +void CFX_AggDeviceDriver::InitPlatform() {} + +void CFX_AggDeviceDriver::DestroyPlatform() {} + +bool CFX_AggDeviceDriver::DrawDeviceText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + const CFX_Matrix* pObject2Device, + float font_size, + uint32_t color) { + return false; +} +#endif // _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ + +int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const { + switch (caps_id) { + case FXDC_DEVICE_CLASS: + return FXDC_DISPLAY; + case FXDC_PIXEL_WIDTH: + return m_pBitmap->GetWidth(); + case FXDC_PIXEL_HEIGHT: + return m_pBitmap->GetHeight(); + case FXDC_BITS_PIXEL: + return m_pBitmap->GetBPP(); + case FXDC_HORZ_SIZE: + case FXDC_VERT_SIZE: + return 0; + case FXDC_RENDER_CAPS: { + int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | + FXRC_BLEND_MODE | FXRC_SOFT_CLIP; + if (m_pBitmap->HasAlpha()) { + flags |= FXRC_ALPHA_OUTPUT; + } else if (m_pBitmap->IsAlphaMask()) { + if (m_pBitmap->GetBPP() == 1) + flags |= FXRC_BITMASK_OUTPUT; + else + flags |= FXRC_BYTEMASK_OUTPUT; } + if (m_pBitmap->IsCmykImage()) + flags |= FXRC_CMYK_OUTPUT; + return flags; } - if (m_pDevice->GetBPP() == 1) { - composite_span = &CFX_Renderer::CompositeSpan1bpp; + default: + return 0; + } +} + +void CFX_AggDeviceDriver::SaveState() { + std::unique_ptr pClip; + if (m_pClipRgn) + pClip = pdfium::MakeUnique(*m_pClipRgn); + m_StateStack.push_back(std::move(pClip)); +} + +void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) { + m_pClipRgn.reset(); + + if (m_StateStack.empty()) + return; + + if (bKeepSaved) { + if (m_StateStack.back()) + m_pClipRgn = pdfium::MakeUnique(*m_StateStack.back()); + } else { + m_pClipRgn = std::move(m_StateStack.back()); + m_StateStack.pop_back(); + } +} + +void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) { + FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(), + rasterizer.max_x() + 1, rasterizer.max_y() + 1); + path_rect.Intersect(m_pClipRgn->GetBox()); + auto pThisLayer = pdfium::MakeRetain(); + pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); + pThisLayer->Clear(0); + agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(), + pThisLayer->GetHeight(), + pThisLayer->GetPitch()); + agg::pixfmt_gray8 pixel_buf(raw_buf); + agg::renderer_base base_buf(pixel_buf); + agg::renderer_scanline_aa_offset > + final_render(base_buf, path_rect.left, path_rect.top); + final_render.color(agg::gray8(255)); + agg::scanline_u8 scanline; + agg::render_scanlines(rasterizer, scanline, final_render, + (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0); + m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, pThisLayer); +} + +bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + int fill_mode) { + m_FillFlags = fill_mode; + if (!m_pClipRgn) { + m_pClipRgn = pdfium::MakeUnique( + GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); + } + size_t size = pPathData->GetPoints().size(); + if (size == 5 || size == 4) { + CFX_FloatRect rectf; + if (pPathData->IsRect(pObject2Device, &rectf)) { + rectf.Intersect(CFX_FloatRect( + 0, 0, static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT)))); + FX_RECT rect = rectf.GetOuterRect(); + m_pClipRgn->IntersectRect(rect); + return true; } - return true; } -}; + CAgg_PathData path_data; + path_data.BuildPath(pPathData, pObject2Device); + path_data.m_PathData.end_poly(); + agg::rasterizer_scanline_aa rasterizer; + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + rasterizer.add_path(path_data.m_PathData); + rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING + ? agg::fill_non_zero + : agg::fill_even_odd); + SetClipMask(rasterizer); + return true; +} + +bool CFX_AggDeviceDriver::SetClip_PathStroke( + const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState) { + if (!m_pClipRgn) { + m_pClipRgn = pdfium::MakeUnique( + GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); + } + CAgg_PathData path_data; + path_data.BuildPath(pPathData, nullptr); + agg::rasterizer_scanline_aa rasterizer; + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + RasterizeStroke(&rasterizer, &path_data.m_PathData, pObject2Device, + pGraphState, 1.0f, false, false); + rasterizer.filling_rule(agg::fill_non_zero); + SetClipMask(rasterizer); + return true; +} int CFX_AggDeviceDriver::GetDriverType() const { return 1; @@ -1434,13 +1282,11 @@ bool CFX_AggDeviceDriver::RenderRasterizer( agg::rasterizer_scanline_aa& rasterizer, uint32_t color, bool bFullCover, - bool bGroupKnockout, - int alpha_flag, - void* pIccTransform) { - CFX_DIBitmap* pt = bGroupKnockout ? m_pOriDevice : nullptr; + bool bGroupKnockout) { + RetainPtr pt = bGroupKnockout ? m_pOriDevice : nullptr; CFX_Renderer render; if (!render.Init(m_pBitmap, pt, m_pClipRgn.get(), color, bFullCover, - m_bRgbByteOrder, alpha_flag, pIccTransform)) { + m_bRgbByteOrder)) { return false; } agg::scanline_u8 scanline; @@ -1467,15 +1313,15 @@ bool CFX_AggDeviceDriver::DrawPath(const CFX_PathData* pPathData, CAgg_PathData path_data; path_data.BuildPath(pPathData, pObject2Device); agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); rasterizer.add_path(path_data.m_PathData); rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING ? agg::fill_non_zero : agg::fill_even_odd); if (!RenderRasterizer(rasterizer, fill_color, - !!(fill_mode & FXFILL_FULLCOVER), false, 0, - nullptr)) { + !!(fill_mode & FXFILL_FULLCOVER), false)) { return false; } } @@ -1487,40 +1333,37 @@ bool CFX_AggDeviceDriver::DrawPath(const CFX_PathData* pPathData, CAgg_PathData path_data; path_data.BuildPath(pPathData, pObject2Device); agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - RasterizeStroke(rasterizer, path_data.m_PathData, nullptr, pGraphState, 1, + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + RasterizeStroke(&rasterizer, &path_data.m_PathData, nullptr, pGraphState, 1, false, !!(fill_mode & FX_STROKE_TEXT_MODE)); return RenderRasterizer(rasterizer, stroke_color, - !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout, - 0, nullptr); + !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout); } CFX_Matrix matrix1; CFX_Matrix matrix2; if (pObject2Device) { - matrix1.a = - std::max(FXSYS_fabs(pObject2Device->a), FXSYS_fabs(pObject2Device->b)); + matrix1.a = std::max(fabs(pObject2Device->a), fabs(pObject2Device->b)); matrix1.d = matrix1.a; matrix2 = CFX_Matrix( pObject2Device->a / matrix1.a, pObject2Device->b / matrix1.a, pObject2Device->c / matrix1.d, pObject2Device->d / matrix1.d, 0, 0); - CFX_Matrix mtRervese; - mtRervese.SetReverse(matrix2); matrix1 = *pObject2Device; - matrix1.Concat(mtRervese); + matrix1.Concat(matrix2.GetInverse()); } CAgg_PathData path_data; path_data.BuildPath(pPathData, &matrix1); agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - RasterizeStroke(rasterizer, path_data.m_PathData, &matrix2, pGraphState, + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + RasterizeStroke(&rasterizer, &path_data.m_PathData, &matrix2, pGraphState, matrix1.a, false, !!(fill_mode & FX_STROKE_TEXT_MODE)); return RenderRasterizer(rasterizer, stroke_color, - !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout, 0, - nullptr); + !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout); } bool CFX_AggDeviceDriver::SetPixel(int x, int y, uint32_t color) { @@ -1529,7 +1372,7 @@ bool CFX_AggDeviceDriver::SetPixel(int x, int y, uint32_t color) { if (!m_pClipRgn) { if (!m_bRgbByteOrder) - return DibSetPixel(m_pBitmap, x, y, color, 0, nullptr); + return DibSetPixel(m_pBitmap, x, y, color); RgbByteOrderSetPixel(m_pBitmap, x, y, color); return true; } @@ -1538,21 +1381,21 @@ bool CFX_AggDeviceDriver::SetPixel(int x, int y, uint32_t color) { if (m_pClipRgn->GetType() == CFX_ClipRgn::RectI) { if (!m_bRgbByteOrder) - return DibSetPixel(m_pBitmap, x, y, color, 0, nullptr); + return DibSetPixel(m_pBitmap, x, y, color); RgbByteOrderSetPixel(m_pBitmap, x, y, color); return true; } if (m_pClipRgn->GetType() != CFX_ClipRgn::MaskF) return true; - const CFX_DIBitmap* pMask = m_pClipRgn->GetMask().GetObject(); - int new_alpha = FXARGB_A(color) * pMask->GetScanline(y)[x] / 255; + int new_alpha = + FXARGB_A(color) * m_pClipRgn->GetMask()->GetScanline(y)[x] / 255; color = (color & 0xffffff) | (new_alpha << 24); if (m_bRgbByteOrder) { RgbByteOrderSetPixel(m_pBitmap, x, y, color); return true; } - return DibSetPixel(m_pBitmap, x, y, color, 0, nullptr); + return DibSetPixel(m_pBitmap, x, y, color); } bool CFX_AggDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, @@ -1579,15 +1422,15 @@ bool CFX_AggDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, fill_color); } else { m_pBitmap->CompositeRect(draw_rect.left, draw_rect.top, draw_rect.Width(), - draw_rect.Height(), fill_color, 0, nullptr); + draw_rect.Height(), fill_color, 0); } return true; } - m_pBitmap->CompositeMask( - draw_rect.left, draw_rect.top, draw_rect.Width(), draw_rect.Height(), - m_pClipRgn->GetMask().GetObject(), fill_color, - draw_rect.left - clip_rect.left, draw_rect.top - clip_rect.top, - FXDIB_BLEND_NORMAL, nullptr, m_bRgbByteOrder, 0, nullptr); + m_pBitmap->CompositeMask(draw_rect.left, draw_rect.top, draw_rect.Width(), + draw_rect.Height(), m_pClipRgn->GetMask(), + fill_color, draw_rect.left - clip_rect.left, + draw_rect.top - clip_rect.top, FXDIB_BLEND_NORMAL, + nullptr, m_bRgbByteOrder, 0); return true; } @@ -1602,13 +1445,15 @@ bool CFX_AggDeviceDriver::GetClipBox(FX_RECT* pRect) { return true; } -bool CFX_AggDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { +bool CFX_AggDeviceDriver::GetDIBits(const RetainPtr& pBitmap, + int left, + int top) { if (!m_pBitmap || !m_pBitmap->GetBuffer()) return true; FX_RECT rect(left, top, left + pBitmap->GetWidth(), top + pBitmap->GetHeight()); - std::unique_ptr pBack; + RetainPtr pBack; if (m_pOriDevice) { pBack = m_pOriDevice->Clone(&rect); if (!pBack) @@ -1626,18 +1471,18 @@ bool CFX_AggDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { top = std::min(top, 0); if (m_bRgbByteOrder) { RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(), - pBack.get(), left, top); + pBack, left, top); return true; } - return pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack.get(), - left, top); + return pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack, left, + top); } -CFX_DIBitmap* CFX_AggDeviceDriver::GetBackDrop() { +RetainPtr CFX_AggDeviceDriver::GetBackDrop() { return m_pOriDevice; } -bool CFX_AggDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, +bool CFX_AggDeviceDriver::SetDIBits(const RetainPtr& pBitmap, uint32_t argb, const FX_RECT* pSrcRect, int left, @@ -1647,17 +1492,17 @@ bool CFX_AggDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, return true; if (pBitmap->IsAlphaMask()) { - return m_pBitmap->CompositeMask( - left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb, - pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(), - m_bRgbByteOrder, 0, nullptr); + return m_pBitmap->CompositeMask(left, top, pSrcRect->Width(), + pSrcRect->Height(), pBitmap, argb, + pSrcRect->left, pSrcRect->top, blend_type, + m_pClipRgn.get(), m_bRgbByteOrder, 0); } return m_pBitmap->CompositeBitmap( left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left, - pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr); + pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder); } -bool CFX_AggDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, +bool CFX_AggDeviceDriver::StretchDIBits(const RetainPtr& pSource, uint32_t argb, int dest_left, int dest_top, @@ -1681,7 +1526,7 @@ bool CFX_AggDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, dest_clip.Intersect(*pClipRect); CFX_BitmapComposer composer; composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false, - false, false, m_bRgbByteOrder, 0, nullptr, blend_type); + false, false, m_bRgbByteOrder, 0, blend_type); dest_clip.Offset(-dest_rect.left, -dest_rect.top); CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height, dest_clip, flags); @@ -1690,46 +1535,37 @@ bool CFX_AggDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, return true; } -bool CFX_AggDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, - int bitmap_alpha, - uint32_t argb, - const CFX_Matrix* pMatrix, - uint32_t render_flags, - void*& handle, - int blend_type) { +bool CFX_AggDeviceDriver::StartDIBits( + const RetainPtr& pSource, + int bitmap_alpha, + uint32_t argb, + const CFX_Matrix* pMatrix, + uint32_t render_flags, + std::unique_ptr* handle, + int blend_type) { if (!m_pBitmap->GetBuffer()) return true; - CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer; - pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, - pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr); - handle = pRenderer; + *handle = pdfium::MakeUnique( + m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, pMatrix, + render_flags, m_bRgbByteOrder); return true; } -bool CFX_AggDeviceDriver::ContinueDIBits(void* pHandle, IFX_Pause* pPause) { - if (!m_pBitmap->GetBuffer()) { - return true; - } - return ((CFX_ImageRenderer*)pHandle)->Continue(pPause); -} - -void CFX_AggDeviceDriver::CancelDIBits(void* pHandle) { - if (!m_pBitmap->GetBuffer()) { - return; - } - delete (CFX_ImageRenderer*)pHandle; +bool CFX_AggDeviceDriver::ContinueDIBits(CFX_ImageRenderer* pHandle, + IFX_PauseIndicator* pPause) { + return m_pBitmap->GetBuffer() ? pHandle->Continue(pPause) : true; } #ifndef _SKIA_SUPPORT_ -CFX_FxgeDevice::CFX_FxgeDevice() { - m_bOwnedBitmap = false; -} +CFX_DefaultRenderDevice::CFX_DefaultRenderDevice() {} + +CFX_DefaultRenderDevice::~CFX_DefaultRenderDevice() {} -bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, - bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, - bool bGroupKnockout) { +bool CFX_DefaultRenderDevice::Attach(const RetainPtr& pBitmap, + bool bRgbByteOrder, + const RetainPtr& pOriDevice, + bool bGroupKnockout) { if (!pBitmap) return false; @@ -1739,25 +1575,19 @@ bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, return true; } -bool CFX_FxgeDevice::Create(int width, - int height, - FXDIB_Format format, - CFX_DIBitmap* pOriDevice) { - m_bOwnedBitmap = true; - CFX_DIBitmap* pBitmap = new CFX_DIBitmap; - if (!pBitmap->Create(width, height, format)) { - delete pBitmap; +bool CFX_DefaultRenderDevice::Create( + int width, + int height, + FXDIB_Format format, + const RetainPtr& pOriDevice) { + auto pBitmap = pdfium::MakeRetain(); + if (!pBitmap->Create(width, height, format)) return false; - } + SetBitmap(pBitmap); SetDeviceDriver(pdfium::MakeUnique(pBitmap, false, pOriDevice, false)); return true; } -CFX_FxgeDevice::~CFX_FxgeDevice() { - if (m_bOwnedBitmap) { - delete GetBitmap(); - } -} #endif diff --git a/core/fxge/agg/fx_agg_driver.h b/core/fxge/agg/fx_agg_driver.h index 8da63394a4654ddadd744abbb03ca3e4cc8613e3..92500c3df6db28b6e223780cb470bb9d8eea4cc7 100644 --- a/core/fxge/agg/fx_agg_driver.h +++ b/core/fxge/agg/fx_agg_driver.h @@ -32,9 +32,9 @@ class CAgg_PathData { class CFX_AggDeviceDriver : public IFX_RenderDeviceDriver { public: - CFX_AggDeviceDriver(CFX_DIBitmap* pBitmap, + CFX_AggDeviceDriver(const RetainPtr& pBitmap, bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, + const RetainPtr& pOriDevice, bool bGroupKnockout); ~CFX_AggDeviceDriver() override; @@ -63,15 +63,17 @@ class CFX_AggDeviceDriver : public IFX_RenderDeviceDriver { uint32_t fill_color, int blend_type) override; bool GetClipBox(FX_RECT* pRect) override; - bool GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) override; - CFX_DIBitmap* GetBackDrop() override; - bool SetDIBits(const CFX_DIBSource* pBitmap, + bool GetDIBits(const RetainPtr& pBitmap, + int left, + int top) override; + RetainPtr GetBackDrop() override; + bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int left, int top, int blend_type) override; - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -80,44 +82,42 @@ class CFX_AggDeviceDriver : public IFX_RenderDeviceDriver { const FX_RECT* pClipRect, uint32_t flags, int blend_type) override; - bool StartDIBits(const CFX_DIBSource* pBitmap, + bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags, - void*& handle, + std::unique_ptr* handle, int blend_type) override; - bool ContinueDIBits(void* handle, IFX_Pause* pPause) override; - void CancelDIBits(void* handle) override; + bool ContinueDIBits(CFX_ImageRenderer* handle, + IFX_PauseIndicator* pPause) override; bool DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) override; int GetDriverType() const override; bool RenderRasterizer(agg::rasterizer_scanline_aa& rasterizer, uint32_t color, bool bFullCover, - bool bGroupKnockout, - int alpha_flag, - void* pIccTransform); + bool bGroupKnockout); void SetClipMask(agg::rasterizer_scanline_aa& rasterizer); virtual uint8_t* GetBuffer() const; private: - CFX_DIBitmap* m_pBitmap; + RetainPtr m_pBitmap; std::unique_ptr m_pClipRgn; std::vector> m_StateStack; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ void* m_pPlatformGraphics; #endif int m_FillFlags; bool m_bRgbByteOrder; - CFX_DIBitmap* m_pOriDevice; + RetainPtr m_pOriDevice; bool m_bGroupKnockout; }; diff --git a/core/fxge/android/cfpf_skiabufferfont.cpp b/core/fxge/android/cfpf_skiabufferfont.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fce483bdc9f84762d382807583292243105e91b --- /dev/null +++ b/core/fxge/android/cfpf_skiabufferfont.cpp @@ -0,0 +1,16 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/android/cfpf_skiabufferfont.h" + +CFPF_SkiaBufferFont::CFPF_SkiaBufferFont() + : m_pBuffer(nullptr), m_szBuffer(0) {} + +CFPF_SkiaBufferFont::~CFPF_SkiaBufferFont() = default; + +int32_t CFPF_SkiaBufferFont::GetType() const { + return FPF_SKIAFONTTYPE_Buffer; +} diff --git a/core/fxge/android/cfpf_skiabufferfont.h b/core/fxge/android/cfpf_skiabufferfont.h index 02fdadea1ed9b070d3dca17da225ad2fb9a3fbde..3a94a51b6a47ae7d93f9ae8e772acd08dfc5e0b0 100644 --- a/core/fxge/android/cfpf_skiabufferfont.h +++ b/core/fxge/android/cfpf_skiabufferfont.h @@ -13,10 +13,11 @@ class CFPF_SkiaBufferFont : public CFPF_SkiaFontDescriptor { public: - CFPF_SkiaBufferFont() : m_pBuffer(nullptr), m_szBuffer(0) {} + CFPF_SkiaBufferFont(); + ~CFPF_SkiaBufferFont() override; // CFPF_SkiaFontDescriptor - int32_t GetType() const override { return FPF_SKIAFONTTYPE_Buffer; } + int32_t GetType() const override; void* m_pBuffer; size_t m_szBuffer; diff --git a/core/fxge/android/cfpf_skiadevicemodule.cpp b/core/fxge/android/cfpf_skiadevicemodule.cpp index 7bdf64666f5d766a3119f4ad72484aa5ba1457b6..bb3f70afa16135dbf6d250a75d691613a7ae9e15 100644 --- a/core/fxge/android/cfpf_skiadevicemodule.cpp +++ b/core/fxge/android/cfpf_skiadevicemodule.cpp @@ -6,7 +6,10 @@ #include "core/fxge/android/cfpf_skiadevicemodule.h" +#include + #include "core/fxge/android/cfpf_skiafontmgr.h" +#include "third_party/base/ptr_util.h" namespace { @@ -20,9 +23,9 @@ CFPF_SkiaDeviceModule* CFPF_GetSkiaDeviceModule() { return gs_pPFModule; } -CFPF_SkiaDeviceModule::~CFPF_SkiaDeviceModule() { - delete m_pFontMgr; -} +CFPF_SkiaDeviceModule::CFPF_SkiaDeviceModule() {} + +CFPF_SkiaDeviceModule::~CFPF_SkiaDeviceModule() {} void CFPF_SkiaDeviceModule::Destroy() { delete gs_pPFModule; @@ -31,11 +34,10 @@ void CFPF_SkiaDeviceModule::Destroy() { CFPF_SkiaFontMgr* CFPF_SkiaDeviceModule::GetFontMgr() { if (!m_pFontMgr) { - m_pFontMgr = new CFPF_SkiaFontMgr; - if (!m_pFontMgr->InitFTLibrary()) { - delete m_pFontMgr; + auto pNewMgr = pdfium::MakeUnique(); + if (!pNewMgr->InitFTLibrary()) return nullptr; - } + m_pFontMgr = std::move(pNewMgr); } - return m_pFontMgr; + return m_pFontMgr.get(); } diff --git a/core/fxge/android/cfpf_skiadevicemodule.h b/core/fxge/android/cfpf_skiadevicemodule.h index 326182003922531556fda495dc7fd6b8577b5b0b..558b08413dad47642757a18e1bcdb9fecf952315 100644 --- a/core/fxge/android/cfpf_skiadevicemodule.h +++ b/core/fxge/android/cfpf_skiadevicemodule.h @@ -7,18 +7,20 @@ #ifndef CORE_FXGE_ANDROID_CFPF_SKIADEVICEMODULE_H_ #define CORE_FXGE_ANDROID_CFPF_SKIADEVICEMODULE_H_ +#include + class CFPF_SkiaFontMgr; class CFPF_SkiaDeviceModule { public: - CFPF_SkiaDeviceModule() : m_pFontMgr(nullptr) {} + CFPF_SkiaDeviceModule(); ~CFPF_SkiaDeviceModule(); void Destroy(); CFPF_SkiaFontMgr* GetFontMgr(); protected: - CFPF_SkiaFontMgr* m_pFontMgr; + std::unique_ptr m_pFontMgr; }; CFPF_SkiaDeviceModule* CFPF_GetSkiaDeviceModule(); diff --git a/core/fxge/android/cfpf_skiafilefont.cpp b/core/fxge/android/cfpf_skiafilefont.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cdf58a4ced4004b648907a1a656ffd0e28fda4f --- /dev/null +++ b/core/fxge/android/cfpf_skiafilefont.cpp @@ -0,0 +1,17 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/android/cfpf_skiafilefont.h" + +#include "core/fxcrt/fx_stream.h" + +CFPF_SkiaFileFont::CFPF_SkiaFileFont() = default; + +CFPF_SkiaFileFont::~CFPF_SkiaFileFont() = default; + +int32_t CFPF_SkiaFileFont::GetType() const { + return FPF_SKIAFONTTYPE_File; +} diff --git a/core/fxge/android/cfpf_skiafilefont.h b/core/fxge/android/cfpf_skiafilefont.h index 2c9fc90ad2d3f2aa975632b1d9022910dc631dbd..5e2ebbc5298715d6b83905bc24395311e747d0c7 100644 --- a/core/fxge/android/cfpf_skiafilefont.h +++ b/core/fxge/android/cfpf_skiafilefont.h @@ -7,7 +7,7 @@ #ifndef CORE_FXGE_ANDROID_CFPF_SKIAFILEFONT_H_ #define CORE_FXGE_ANDROID_CFPF_SKIAFILEFONT_H_ -#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/retain_ptr.h" #include "core/fxge/android/cfpf_skiafontdescriptor.h" class IFX_SeekableReadStream; @@ -16,12 +16,13 @@ class IFX_SeekableReadStream; class CFPF_SkiaFileFont : public CFPF_SkiaFontDescriptor { public: - CFPF_SkiaFileFont() {} + CFPF_SkiaFileFont(); + ~CFPF_SkiaFileFont() override; // CFPF_SkiaFontDescriptor - int32_t GetType() const override { return FPF_SKIAFONTTYPE_File; } + int32_t GetType() const override; - CFX_RetainPtr m_pFile; + RetainPtr m_pFile; }; #endif // CORE_FXGE_ANDROID_CFPF_SKIAFILEFONT_H_ diff --git a/core/fxge/android/cfpf_skiafont.cpp b/core/fxge/android/cfpf_skiafont.cpp index 5e11efae9dfeb953a3debbf3f50feba66a66cae4..1ca0f576be11ac0bb6fde0639177005dc3c8659c 100644 --- a/core/fxge/android/cfpf_skiafont.cpp +++ b/core/fxge/android/cfpf_skiafont.cpp @@ -41,19 +41,19 @@ CFPF_SkiaFont* CFPF_SkiaFont::Retain() { return this; } -CFX_ByteString CFPF_SkiaFont::GetFamilyName() { +ByteString CFPF_SkiaFont::GetFamilyName() { if (!m_Face) - return CFX_ByteString(); - return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face)); + return ByteString(); + return ByteString(FXFT_Get_Face_Family_Name(m_Face)); } -CFX_ByteString CFPF_SkiaFont::GetPsName() { +ByteString CFPF_SkiaFont::GetPsName() { if (!m_Face) - return CFX_ByteString(); + return ByteString(); return FXFT_Get_Postscript_Name(m_Face); } -int32_t CFPF_SkiaFont::GetGlyphIndex(FX_WCHAR wUnicode) { +int32_t CFPF_SkiaFont::GetGlyphIndex(wchar_t wUnicode) { if (!m_Face) return wUnicode; if (FXFT_Select_Charmap(m_Face, FXFT_ENCODING_UNICODE)) @@ -181,7 +181,7 @@ uint32_t CFPF_SkiaFont::GetFontData(uint32_t dwTable, bool CFPF_SkiaFont::InitFont(CFPF_SkiaFontMgr* pFontMgr, CFPF_SkiaFontDescriptor* pFontDes, - const CFX_ByteStringC& bsFamily, + const ByteStringView& bsFamily, uint32_t dwStyle, uint8_t uCharset) { if (!pFontMgr || !pFontDes) diff --git a/core/fxge/android/cfpf_skiafont.h b/core/fxge/android/cfpf_skiafont.h index b72c1111778ce91315c44b259460a0e17b57c475..1b2f6058386f21b12919d7a6b8548586e7f7fc16 100644 --- a/core/fxge/android/cfpf_skiafont.h +++ b/core/fxge/android/cfpf_skiafont.h @@ -8,6 +8,7 @@ #define CORE_FXGE_ANDROID_CFPF_SKIAFONT_H_ #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_font.h" class CFPF_SkiaFontDescriptor; @@ -21,11 +22,11 @@ class CFPF_SkiaFont { void Release(); CFPF_SkiaFont* Retain(); - CFX_ByteString GetFamilyName(); - CFX_ByteString GetPsName(); + ByteString GetFamilyName(); + ByteString GetPsName(); uint32_t GetFontStyle() const { return m_dwStyle; } uint8_t GetCharset() const { return m_uCharset; } - int32_t GetGlyphIndex(FX_WCHAR wUnicode); + int32_t GetGlyphIndex(wchar_t wUnicode); int32_t GetGlyphWidth(int32_t iGlyphIndex); int32_t GetAscent() const; int32_t GetDescent() const; @@ -37,13 +38,13 @@ class CFPF_SkiaFont { bool InitFont(CFPF_SkiaFontMgr* pFontMgr, CFPF_SkiaFontDescriptor* pFontDes, - const CFX_ByteStringC& bsFamily, + const ByteStringView& bsFamily, uint32_t dwStyle, uint8_t uCharset); private: - CFPF_SkiaFontMgr* m_pFontMgr; - CFPF_SkiaFontDescriptor* m_pFontDes; + UnownedPtr m_pFontMgr; + UnownedPtr m_pFontDes; FXFT_Face m_Face; uint32_t m_dwStyle; uint8_t m_uCharset; diff --git a/core/fxge/android/cfpf_skiafontdescriptor.cpp b/core/fxge/android/cfpf_skiafontdescriptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8dd4481a7dc726d3e725ecc5ebea3c3c0b3c81f5 --- /dev/null +++ b/core/fxge/android/cfpf_skiafontdescriptor.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/android/cfpf_skiafontdescriptor.h" + +#include "core/fxcrt/fx_memory.h" + +CFPF_SkiaFontDescriptor::CFPF_SkiaFontDescriptor() + : m_pFamily(nullptr), + m_dwStyle(0), + m_iFaceIndex(0), + m_dwCharsets(0), + m_iGlyphNum(0) {} + +CFPF_SkiaFontDescriptor::~CFPF_SkiaFontDescriptor() { + FX_Free(m_pFamily); +} + +int32_t CFPF_SkiaFontDescriptor::GetType() const { + return FPF_SKIAFONTTYPE_Unknown; +} + +void CFPF_SkiaFontDescriptor::SetFamily(const char* pFamily) { + FX_Free(m_pFamily); + int32_t iSize = strlen(pFamily); + m_pFamily = FX_Alloc(char, iSize + 1); + memcpy(m_pFamily, pFamily, iSize * sizeof(char)); + m_pFamily[iSize] = 0; +} diff --git a/core/fxge/android/cfpf_skiafontdescriptor.h b/core/fxge/android/cfpf_skiafontdescriptor.h index 57b85404ad6cc94bd9e739a65563cb1c2728b5ef..00a19ecc54d2a4675d1596ed63a523d455e85b0c 100644 --- a/core/fxge/android/cfpf_skiafontdescriptor.h +++ b/core/fxge/android/cfpf_skiafontdescriptor.h @@ -13,24 +13,14 @@ class CFPF_SkiaFontDescriptor { public: - CFPF_SkiaFontDescriptor() - : m_pFamily(nullptr), - m_dwStyle(0), - m_iFaceIndex(0), - m_dwCharsets(0), - m_iGlyphNum(0) {} - virtual ~CFPF_SkiaFontDescriptor() { FX_Free(m_pFamily); } - - virtual int32_t GetType() const { return FPF_SKIAFONTTYPE_Unknown; } - - void SetFamily(const FX_CHAR* pFamily) { - FX_Free(m_pFamily); - int32_t iSize = FXSYS_strlen(pFamily); - m_pFamily = FX_Alloc(FX_CHAR, iSize + 1); - FXSYS_memcpy(m_pFamily, pFamily, iSize * sizeof(FX_CHAR)); - m_pFamily[iSize] = 0; - } - FX_CHAR* m_pFamily; + CFPF_SkiaFontDescriptor(); + virtual ~CFPF_SkiaFontDescriptor(); + + virtual int32_t GetType() const; + + void SetFamily(const char* pFamily); + + char* m_pFamily; uint32_t m_dwStyle; int32_t m_iFaceIndex; uint32_t m_dwCharsets; diff --git a/core/fxge/android/cfpf_skiafontmgr.cpp b/core/fxge/android/cfpf_skiafontmgr.cpp index e3511be67a1e69740be7f809846ddb9d1f4d2b38..d8b751d9b20eab405d87e38d6bb902a9fa111855 100644 --- a/core/fxge/android/cfpf_skiafontmgr.cpp +++ b/core/fxge/android/cfpf_skiafontmgr.cpp @@ -13,7 +13,8 @@ #include -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_system.h" #include "core/fxge/android/cfpf_skiafont.h" @@ -36,7 +37,8 @@ static unsigned long FPF_SkiaStream_Read(FXFT_Stream stream, if (!pFileRead) return 0; - if (!pFileRead->ReadBlock(buffer, (FX_FILESIZE)offset, (size_t)count)) + if (!pFileRead->ReadBlock(buffer, (FX_FILESIZE)offset, + static_cast(count))) return 0; return count; @@ -87,12 +89,12 @@ uint32_t FPF_SkiaGetSubstFont(uint32_t dwHash, return 0; } -uint32_t FPF_GetHashCode_StringA(const FX_CHAR* pStr, int32_t iLength) { +uint32_t FPF_GetHashCode_StringA(const char* pStr, int32_t iLength) { if (!pStr) return 0; if (iLength < 0) - iLength = FXSYS_strlen(pStr); - const FX_CHAR* pStrEnd = pStr + iLength; + iLength = strlen(pStr); + const char* pStrEnd = pStr + iLength; uint32_t uHashCode = 0; while (pStr < pStrEnd) uHashCode = 31 * uHashCode + FXSYS_tolower(*pStr++); @@ -123,46 +125,46 @@ enum FPF_SKIACHARSET { uint32_t FPF_SkiaGetCharset(uint8_t uCharset) { switch (uCharset) { - case FXFONT_ANSI_CHARSET: + case FX_CHARSET_ANSI: return FPF_SKIACHARSET_Ansi; - case FXFONT_DEFAULT_CHARSET: + case FX_CHARSET_Default: return FPF_SKIACHARSET_Default; - case FXFONT_SYMBOL_CHARSET: + case FX_CHARSET_Symbol: return FPF_SKIACHARSET_Symbol; - case FXFONT_SHIFTJIS_CHARSET: + case FX_CHARSET_ShiftJIS: return FPF_SKIACHARSET_ShiftJIS; - case FXFONT_HANGUL_CHARSET: + case FX_CHARSET_Hangul: return FPF_SKIACHARSET_Korean; - case FXFONT_GB2312_CHARSET: + case FX_CHARSET_ChineseSimplified: return FPF_SKIACHARSET_GB2312; - case FXFONT_CHINESEBIG5_CHARSET: + case FX_CHARSET_ChineseTraditional: return FPF_SKIACHARSET_BIG5; - case FXFONT_GREEK_CHARSET: + case FX_CHARSET_MSWin_Greek: return FPF_SKIACHARSET_Greek; - case FXFONT_TURKISH_CHARSET: + case FX_CHARSET_MSWin_Turkish: return FPF_SKIACHARSET_Turkish; - case FXFONT_HEBREW_CHARSET: + case FX_CHARSET_MSWin_Hebrew: return FPF_SKIACHARSET_Hebrew; - case FXFONT_ARABIC_CHARSET: + case FX_CHARSET_MSWin_Arabic: return FPF_SKIACHARSET_Arabic; - case FXFONT_BALTIC_CHARSET: + case FX_CHARSET_MSWin_Baltic: return FPF_SKIACHARSET_Baltic; - case FXFONT_RUSSIAN_CHARSET: + case FX_CHARSET_MSWin_Cyrillic: return FPF_SKIACHARSET_Cyrillic; - case FXFONT_THAI_CHARSET: + case FX_CHARSET_Thai: return FPF_SKIACHARSET_Thai; - case FXFONT_EASTEUROPE_CHARSET: + case FX_CHARSET_MSWin_EasternEuropean: return FPF_SKIACHARSET_EeasternEuropean; } return FPF_SKIACHARSET_Default; } -uint32_t FPF_SKIANormalizeFontName(const CFX_ByteStringC& bsfamily) { +uint32_t FPF_SKIANormalizeFontName(const ByteStringView& bsfamily) { uint32_t dwHash = 0; int32_t iLength = bsfamily.GetLength(); - const FX_CHAR* pBuffer = bsfamily.c_str(); + const char* pBuffer = bsfamily.unterminated_c_str(); for (int32_t i = 0; i < iLength; i++) { - FX_CHAR ch = pBuffer[i]; + char ch = pBuffer[i]; if (ch == ' ' || ch == '-' || ch == ',') continue; dwHash = 31 * dwHash + FXSYS_tolower(ch); @@ -170,37 +172,36 @@ uint32_t FPF_SKIANormalizeFontName(const CFX_ByteStringC& bsfamily) { return dwHash; } -uint32_t FPF_SKIAGetFamilyHash(const CFX_ByteStringC& bsFamily, +uint32_t FPF_SKIAGetFamilyHash(const ByteStringView& bsFamily, uint32_t dwStyle, uint8_t uCharset) { - CFX_ByteString bsFont(bsFamily); - if (dwStyle & FXFONT_BOLD) + ByteString bsFont(bsFamily); + if (FontStyleIsBold(dwStyle)) bsFont += "Bold"; - if (dwStyle & FXFONT_ITALIC) + if (FontStyleIsItalic(dwStyle)) bsFont += "Italic"; - if (dwStyle & FXFONT_SERIF) + if (FontStyleIsSerif(dwStyle)) bsFont += "Serif"; bsFont += uCharset; return FPF_GetHashCode_StringA(bsFont.c_str(), bsFont.GetLength()); } bool FPF_SkiaIsCJK(uint8_t uCharset) { - return (uCharset == FXFONT_GB2312_CHARSET) || - (uCharset == FXFONT_CHINESEBIG5_CHARSET) || - (uCharset == FXFONT_HANGUL_CHARSET) || - (uCharset == FXFONT_SHIFTJIS_CHARSET); + return (uCharset == FX_CHARSET_ChineseSimplified) || + (uCharset == FX_CHARSET_ChineseTraditional) || + (uCharset == FX_CHARSET_Hangul) || (uCharset == FX_CHARSET_ShiftJIS); } -bool FPF_SkiaMaybeSymbol(const CFX_ByteStringC& bsFacename) { - CFX_ByteString bsName(bsFacename); +bool FPF_SkiaMaybeSymbol(const ByteStringView& bsFacename) { + ByteString bsName(bsFacename); bsName.MakeLower(); - return bsName.Find("symbol") > -1; + return bsName.Contains("symbol"); } -bool FPF_SkiaMaybeArabic(const CFX_ByteStringC& bsFacename) { - CFX_ByteString bsName(bsFacename); +bool FPF_SkiaMaybeArabic(const ByteStringView& bsFacename) { + ByteString bsName(bsFacename); bsName.MakeLower(); - return bsName.Find("arabic") > -1; + return bsName.Contains("arabic"); } const uint32_t g_FPFSkiaFontCharsets[] = { @@ -280,7 +281,7 @@ void CFPF_SkiaFontMgr::LoadSystemFonts() { m_bLoaded = true; } -CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const CFX_ByteStringC& bsFamilyname, +CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const ByteStringView& bsFamilyname, uint8_t uCharset, uint32_t dwStyle, uint32_t dwMatch) { @@ -295,11 +296,12 @@ CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const CFX_ByteStringC& bsFamilyname, uint32_t dwSubstSans = FPF_SkiaGetSubstFont(dwFaceName, g_SkiaSansFontMap, FX_ArraySize(g_SkiaSansFontMap)); bool bMaybeSymbol = FPF_SkiaMaybeSymbol(bsFamilyname); - if (uCharset != FXFONT_ARABIC_CHARSET && FPF_SkiaMaybeArabic(bsFamilyname)) { - uCharset = FXFONT_ARABIC_CHARSET; - } else if (uCharset == FXFONT_ANSI_CHARSET && + if (uCharset != FX_CHARSET_MSWin_Arabic && + FPF_SkiaMaybeArabic(bsFamilyname)) { + uCharset = FX_CHARSET_MSWin_Arabic; + } else if (uCharset == FX_CHARSET_ANSI && (dwMatch & FPF_MATCHFONT_REPLACEANSI)) { - uCharset = FXFONT_DEFAULT_CHARSET; + uCharset = FX_CHARSET_Default; } int32_t nExpectVal = FPF_SKIAMATCHWEIGHT_NAME1 + FPF_SKIAMATCHWEIGHT_1 * 3 + FPF_SKIAMATCHWEIGHT_2 * 2; @@ -315,23 +317,23 @@ CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const CFX_ByteStringC& bsFamilyname, if (dwFaceName == dwSysFontName) nFind += FPF_SKIAMATCHWEIGHT_NAME1; bool bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1); - if ((dwStyle & FXFONT_BOLD) == (pFontDes->m_dwStyle & FXFONT_BOLD)) + if (FontStyleIsBold(dwStyle) == FontStyleIsBold(pFontDes->m_dwStyle)) nFind += FPF_SKIAMATCHWEIGHT_1; - if ((dwStyle & FXFONT_ITALIC) == (pFontDes->m_dwStyle & FXFONT_ITALIC)) + if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(pFontDes->m_dwStyle)) nFind += FPF_SKIAMATCHWEIGHT_1; - if ((dwStyle & FXFONT_FIXED_PITCH) == - (pFontDes->m_dwStyle & FXFONT_FIXED_PITCH)) { + if (FontStyleIsFixedPitch(dwStyle) == + FontStyleIsFixedPitch(pFontDes->m_dwStyle)) { nFind += FPF_SKIAMATCHWEIGHT_2; } - if ((dwStyle & FXFONT_SERIF) == (pFontDes->m_dwStyle & FXFONT_SERIF)) + if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(pFontDes->m_dwStyle)) nFind += FPF_SKIAMATCHWEIGHT_1; - if ((dwStyle & FXFONT_SCRIPT) == (pFontDes->m_dwStyle & FXFONT_SCRIPT)) + if (FontStyleIsScript(dwStyle) == FontStyleIsScript(pFontDes->m_dwStyle)) nFind += FPF_SKIAMATCHWEIGHT_2; if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) { nFind += FPF_SKIAMATCHWEIGHT_NAME2; bMatchedName = true; } - if (uCharset == FXFONT_DEFAULT_CHARSET || bMaybeSymbol) { + if (uCharset == FX_CHARSET_Default || bMaybeSymbol) { if (nFind > nMax && bMatchedName) { nMax = nFind; pBestFontDes = *it; @@ -362,7 +364,7 @@ CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const CFX_ByteStringC& bsFamilyname, } FXFT_Face CFPF_SkiaFontMgr::GetFontFace( - const CFX_RetainPtr& pFileRead, + const RetainPtr& pFileRead, int32_t iFaceIndex) { if (!pFileRead) return nullptr; @@ -371,7 +373,7 @@ FXFT_Face CFPF_SkiaFontMgr::GetFontFace( if (iFaceIndex < 0) return nullptr; FXFT_StreamRec streamRec; - FXSYS_memset(&streamRec, 0, sizeof(FXFT_StreamRec)); + memset(&streamRec, 0, sizeof(FXFT_StreamRec)); streamRec.size = pFileRead->GetSize(); streamRec.descriptor.pointer = static_cast(pFileRead.Get()); streamRec.read = FPF_SkiaStream_Read; @@ -386,7 +388,7 @@ FXFT_Face CFPF_SkiaFontMgr::GetFontFace( return face; } -FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const CFX_ByteStringC& bsFile, +FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const ByteStringView& bsFile, int32_t iFaceIndex) { if (bsFile.IsEmpty()) return nullptr; @@ -394,7 +396,7 @@ FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const CFX_ByteStringC& bsFile, return nullptr; FXFT_Open_Args args; args.flags = FT_OPEN_PATHNAME; - args.pathname = const_cast(bsFile.c_str()); + args.pathname = const_cast(bsFile.unterminated_c_str()); FXFT_Face face; if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) return nullptr; @@ -420,23 +422,23 @@ FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const uint8_t* pBuffer, return face; } -void CFPF_SkiaFontMgr::ScanPath(const CFX_ByteString& path) { +void CFPF_SkiaFontMgr::ScanPath(const ByteString& path) { DIR* handle = FX_OpenFolder(path.c_str()); if (!handle) return; - CFX_ByteString filename; + ByteString filename; bool bFolder = false; while (FX_GetNextFile(handle, &filename, &bFolder)) { if (bFolder) { if (filename == "." || filename == "..") continue; } else { - CFX_ByteString ext = filename.Right(4); + ByteString ext = filename.Right(4); ext.MakeLower(); if (ext != ".ttf" && ext != ".ttc" && ext != ".otf") continue; } - CFX_ByteString fullpath(path); + ByteString fullpath(path); fullpath += "/"; fullpath += filename; if (bFolder) @@ -447,8 +449,8 @@ void CFPF_SkiaFontMgr::ScanPath(const CFX_ByteString& path) { FX_CloseFolder(handle); } -void CFPF_SkiaFontMgr::ScanFile(const CFX_ByteString& file) { - FXFT_Face face = GetFontFace(file.AsStringC()); +void CFPF_SkiaFontMgr::ScanFile(const ByteString& file) { + FXFT_Face face = GetFontFace(file.AsStringView()); if (!face) return; CFPF_SkiaPathFont* pFontDesc = new CFPF_SkiaPathFont; diff --git a/core/fxge/android/cfpf_skiafontmgr.h b/core/fxge/android/cfpf_skiafontmgr.h index 4d0ea0e0d2df4701096b067ea4d9768a21988398..11ad47a3603354361154db0d294178c9955c4588 100644 --- a/core/fxge/android/cfpf_skiafontmgr.h +++ b/core/fxge/android/cfpf_skiafontmgr.h @@ -25,22 +25,22 @@ class CFPF_SkiaFontMgr { ~CFPF_SkiaFontMgr(); void LoadSystemFonts(); - CFPF_SkiaFont* CreateFont(const CFX_ByteStringC& bsFamilyname, + CFPF_SkiaFont* CreateFont(const ByteStringView& bsFamilyname, uint8_t uCharset, uint32_t dwStyle, uint32_t dwMatch = 0); bool InitFTLibrary(); - FXFT_Face GetFontFace(const CFX_RetainPtr& pFileRead, + FXFT_Face GetFontFace(const RetainPtr& pFileRead, int32_t iFaceIndex = 0); - FXFT_Face GetFontFace(const CFX_ByteStringC& bsFile, int32_t iFaceIndex = 0); + FXFT_Face GetFontFace(const ByteStringView& bsFile, int32_t iFaceIndex = 0); FXFT_Face GetFontFace(const uint8_t* pBuffer, size_t szBuffer, int32_t iFaceIndex = 0); private: - void ScanPath(const CFX_ByteString& path); - void ScanFile(const CFX_ByteString& file); + void ScanPath(const ByteString& path); + void ScanFile(const ByteString& file); void ReportFace(FXFT_Face face, CFPF_SkiaFontDescriptor* pFontDesc); bool m_bLoaded; diff --git a/core/fxge/android/cfpf_skiapathfont.cpp b/core/fxge/android/cfpf_skiapathfont.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27f4fde9881083715f9ef6b0da8f7a43642202f0 --- /dev/null +++ b/core/fxge/android/cfpf_skiapathfont.cpp @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/android/cfpf_skiapathfont.h" + +#include "core/fxcrt/fx_memory.h" + +CFPF_SkiaPathFont::CFPF_SkiaPathFont() : m_pPath(nullptr) {} + +CFPF_SkiaPathFont::~CFPF_SkiaPathFont() { + FX_Free(m_pPath); +} + +int32_t CFPF_SkiaPathFont::GetType() const { + return FPF_SKIAFONTTYPE_Path; +} + +void CFPF_SkiaPathFont::SetPath(const char* pPath) { + FX_Free(m_pPath); + int32_t iSize = strlen(pPath); + m_pPath = FX_Alloc(char, iSize + 1); + memcpy(m_pPath, pPath, iSize * sizeof(char)); + m_pPath[iSize] = 0; +} diff --git a/core/fxge/android/cfpf_skiapathfont.h b/core/fxge/android/cfpf_skiapathfont.h index f1cff2574b7d22ab5df23c2dc0f0114127741191..6cba42acfff98d1761b3a24afb621efce51145ce 100644 --- a/core/fxge/android/cfpf_skiapathfont.h +++ b/core/fxge/android/cfpf_skiapathfont.h @@ -14,20 +14,15 @@ class CFPF_SkiaPathFont : public CFPF_SkiaFontDescriptor { public: - CFPF_SkiaPathFont() : m_pPath(nullptr) {} - ~CFPF_SkiaPathFont() override { FX_Free(m_pPath); } + CFPF_SkiaPathFont(); + ~CFPF_SkiaPathFont() override; // CFPF_SkiaFontDescriptor - int32_t GetType() const override { return FPF_SKIAFONTTYPE_Path; } - - void SetPath(const FX_CHAR* pPath) { - FX_Free(m_pPath); - int32_t iSize = FXSYS_strlen(pPath); - m_pPath = FX_Alloc(FX_CHAR, iSize + 1); - FXSYS_memcpy(m_pPath, pPath, iSize * sizeof(FX_CHAR)); - m_pPath[iSize] = 0; - } - FX_CHAR* m_pPath; + int32_t GetType() const override; + + void SetPath(const char* pPath); + + char* m_pPath; }; #endif // CORE_FXGE_ANDROID_CFPF_SKIAPATHFONT_H_ diff --git a/core/fxge/android/cfx_androidfontinfo.cpp b/core/fxge/android/cfx_androidfontinfo.cpp index 03a7ffbd9e42f1b118d5fbdda9cdd8a5aca52287..61d213edd619257012b7a44189b8d99ff83a350d 100644 --- a/core/fxge/android/cfx_androidfontinfo.cpp +++ b/core/fxge/android/cfx_androidfontinfo.cpp @@ -30,8 +30,7 @@ void* CFX_AndroidFontInfo::MapFont(int weight, bool bItalic, int charset, int pitch_family, - const FX_CHAR* face, - int& iExact) { + const char* face) { if (!m_pFontMgr) return nullptr; @@ -40,17 +39,17 @@ void* CFX_AndroidFontInfo::MapFont(int weight, dwStyle |= FXFONT_BOLD; if (bItalic) dwStyle |= FXFONT_ITALIC; - if (pitch_family & FXFONT_FF_FIXEDPITCH) + if (FontFamilyIsFixedPitch(pitch_family)) dwStyle |= FXFONT_FIXED_PITCH; - if (pitch_family & FXFONT_FF_SCRIPT) + if (FontFamilyIsScript(pitch_family)) dwStyle |= FXFONT_SCRIPT; - if (pitch_family & FXFONT_FF_ROMAN) + if (FontFamilyIsRoman(pitch_family)) dwStyle |= FXFONT_SERIF; return m_pFontMgr->CreateFont(face, charset, dwStyle, FPF_MATCHFONT_REPLACEANSI); } -void* CFX_AndroidFontInfo::GetFont(const FX_CHAR* face) { +void* CFX_AndroidFontInfo::GetFont(const char* face) { return nullptr; } @@ -63,19 +62,19 @@ uint32_t CFX_AndroidFontInfo::GetFontData(void* hFont, return static_cast(hFont)->GetFontData(table, buffer, size); } -bool CFX_AndroidFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { +bool CFX_AndroidFontInfo::GetFaceName(void* hFont, ByteString* name) { if (!hFont) return false; - name = static_cast(hFont)->GetFamilyName(); + *name = static_cast(hFont)->GetFamilyName(); return true; } -bool CFX_AndroidFontInfo::GetFontCharset(void* hFont, int& charset) { +bool CFX_AndroidFontInfo::GetFontCharset(void* hFont, int* charset) { if (!hFont) return false; - charset = static_cast(hFont)->GetCharset(); + *charset = static_cast(hFont)->GetCharset(); return false; } diff --git a/core/fxge/android/cfx_androidfontinfo.h b/core/fxge/android/cfx_androidfontinfo.h index 94e1db88ac034ab547acd9fdaf4ea7ff01305475..e49b1617dea46342ae7cd7b126ac78f792181e43 100644 --- a/core/fxge/android/cfx_androidfontinfo.h +++ b/core/fxge/android/cfx_androidfontinfo.h @@ -8,8 +8,8 @@ #define CORE_FXGE_ANDROID_CFX_ANDROIDFONTINFO_H_ #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/fx_font.h" #include "core/fxge/ifx_systemfontinfo.h" class CFPF_SkiaFontMgr; @@ -27,19 +27,18 @@ class CFX_AndroidFontInfo : public IFX_SystemFontInfo { bool bItalic, int charset, int pitch_family, - const FX_CHAR* face, - int& bExact) override; - void* GetFont(const FX_CHAR* face) override; + const char* face) override; + void* GetFont(const char* face) override; uint32_t GetFontData(void* hFont, uint32_t table, uint8_t* buffer, uint32_t size) override; - bool GetFaceName(void* hFont, CFX_ByteString& name) override; - bool GetFontCharset(void* hFont, int& charset) override; + bool GetFaceName(void* hFont, ByteString* name) override; + bool GetFontCharset(void* hFont, int* charset) override; void DeleteFont(void* hFont) override; protected: - CFPF_SkiaFontMgr* m_pFontMgr; + UnownedPtr m_pFontMgr; }; #endif // CORE_FXGE_ANDROID_CFX_ANDROIDFONTINFO_H_ diff --git a/core/fxge/android/fx_android_imp.cpp b/core/fxge/android/fx_android_imp.cpp index b8e7c5b2180944fa5658a6b646e97c8836318c8c..db2f3efbec4df39ca0ca33805d454652d77fa7f6 100644 --- a/core/fxge/android/fx_android_imp.cpp +++ b/core/fxge/android/fx_android_imp.cpp @@ -11,6 +11,8 @@ #include "core/fxge/android/cfpf_skiadevicemodule.h" #include "core/fxge/android/cfx_androidfontinfo.h" +#include "core/fxge/cfx_fontmgr.h" +#include "third_party/base/ptr_util.h" void CFX_GEModule::InitPlatform() { CFPF_SkiaDeviceModule* pDeviceModule = CFPF_GetSkiaDeviceModule(); @@ -19,7 +21,7 @@ void CFX_GEModule::InitPlatform() { CFPF_SkiaFontMgr* pFontMgr = pDeviceModule->GetFontMgr(); if (pFontMgr) { - std::unique_ptr pFontInfo(new CFX_AndroidFontInfo); + auto pFontInfo = pdfium::MakeUnique(); pFontInfo->Init(pFontMgr); m_pFontMgr->SetSystemFontInfo(std::move(pFontInfo)); } diff --git a/core/fxge/apple/apple_int.h b/core/fxge/apple/apple_int.h index fed6abcfb09d1dd1e7dd9a5b05fcfa2398e4a212..82415ec07f3ccbf9808a5b26ccccbf6099e31c1f 100644 --- a/core/fxge/apple/apple_int.h +++ b/core/fxge/apple/apple_int.h @@ -19,7 +19,7 @@ class CQuartz2D { public: - void* createGraphics(CFX_DIBitmap* bitmap); + void* createGraphics(const RetainPtr& bitmap); void destroyGraphics(void* graphics); void* CreateFont(const uint8_t* pFontData, uint32_t dwFontSize); @@ -27,7 +27,7 @@ class CQuartz2D { void setGraphicsTextMatrix(void* graphics, CFX_Matrix* matrix); bool drawGraphicsString(void* graphics, void* font, - FX_FLOAT fontSize, + float fontSize, uint16_t* glyphIndices, CGPoint* glyphPositions, int32_t chars, diff --git a/core/fxge/apple/fx_apple_platform.cpp b/core/fxge/apple/fx_apple_platform.cpp index f576eb0ba27290f4584053bdb523a0cd48fa1183..3c142c6984c6b0831664f811aadc2468b44d4324 100644 --- a/core/fxge/apple/fx_apple_platform.cpp +++ b/core/fxge/apple/fx_apple_platform.cpp @@ -4,6 +4,9 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +#include + +#include "core/fxcrt/cfx_fixedbufgrow.h" #include "core/fxcrt/fx_system.h" #ifndef _SKIA_SUPPORT_ @@ -11,13 +14,12 @@ #endif #include "core/fxge/apple/apple_int.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/cfx_facecache.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/dib/dib_int.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/cfx_cliprgn.h" -#include "core/fxge/ge/fx_text_int.h" #ifndef _SKIA_SUPPORT_ @@ -30,7 +32,7 @@ bool CGDrawGlyphRun(CGContextRef pContext, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t argb) { if (nChars == 0) return true; @@ -102,7 +104,7 @@ bool CFX_AggDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t argb) { if (!pFont) return false; @@ -129,7 +131,7 @@ bool CFX_AggDeviceDriver::DrawDeviceText(int nChars, rect_cg = CGRectMake(m_pClipRgn->GetBox().left, m_pClipRgn->GetBox().top, m_pClipRgn->GetBox().Width(), m_pClipRgn->GetBox().Height()); - const CFX_DIBitmap* pClipMask = m_pClipRgn->GetMask().GetObject(); + RetainPtr pClipMask = m_pClipRgn->GetMask(); if (pClipMask) { CGDataProviderRef pClipMaskDataProvider = CGDataProviderCreateWithData( nullptr, pClipMask->GetBuffer(), @@ -163,7 +165,7 @@ void CFX_FaceCache::InitPlatform() {} void CFX_FaceCache::DestroyPlatform() {} -CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext( +std::unique_ptr CFX_FaceCache::RenderGlyph_Nativetext( const CFX_Font* pFont, uint32_t glyph_index, const CFX_Matrix* pMatrix, diff --git a/core/fxge/apple/fx_mac_imp.cpp b/core/fxge/apple/fx_mac_imp.cpp index c05aea34f54b2c3cdb6d34b4d93822c081b6d92e..b212f1567ccfe732be710badfd60117babcd12ef 100644 --- a/core/fxge/apple/fx_mac_imp.cpp +++ b/core/fxge/apple/fx_mac_imp.cpp @@ -5,17 +5,21 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include +#include +#include "core/fxcrt/fx_codepage.h" #include "core/fxge/apple/apple_int.h" +#include "core/fxge/cfx_folderfontinfo.h" +#include "core/fxge/cfx_fontmgr.h" #include "core/fxge/cfx_gemodule.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" #include "core/fxge/ifx_systemfontinfo.h" +#include "third_party/base/ptr_util.h" namespace { const struct { - const FX_CHAR* m_pName; - const FX_CHAR* m_pSubstName; + const char* m_pName; + const char* m_pSubstName; } g_Base14Substs[] = { {"Courier", "Courier New"}, {"Courier-Bold", "Courier New Bold"}, @@ -41,33 +45,30 @@ class CFX_MacFontInfo : public CFX_FolderFontInfo { bool bItalic, int charset, int pitch_family, - const FX_CHAR* family, - int& iExact) override; + const char* family) override; }; const char JAPAN_GOTHIC[] = "Hiragino Kaku Gothic Pro W6"; const char JAPAN_MINCHO[] = "Hiragino Mincho Pro W6"; -void GetJapanesePreference(CFX_ByteString* face, int weight, int pitch_family) { - if (face->Find("Gothic") >= 0) { +void GetJapanesePreference(ByteString* face, int weight, int pitch_family) { + if (face->Contains("Gothic")) { *face = JAPAN_GOTHIC; return; } - *face = ((pitch_family & FXFONT_FF_ROMAN) || weight <= 400) ? JAPAN_MINCHO - : JAPAN_GOTHIC; + *face = (FontFamilyIsRoman(pitch_family) || weight <= 400) ? JAPAN_MINCHO + : JAPAN_GOTHIC; } void* CFX_MacFontInfo::MapFont(int weight, bool bItalic, int charset, int pitch_family, - const FX_CHAR* cstr_face, - int& iExact) { - CFX_ByteString face = cstr_face; - for (size_t i = 0; i < FX_ArraySize(g_Base14Substs); ++i) { - if (face == CFX_ByteStringC(g_Base14Substs[i].m_pName)) { - face = g_Base14Substs[i].m_pSubstName; - iExact = true; + const char* cstr_face) { + ByteString face = cstr_face; + for (const auto& sub : g_Base14Substs) { + if (face == ByteStringView(sub.m_pName)) { + face = sub.m_pSubstName; return GetFont(face.c_str()); } } @@ -79,53 +80,53 @@ void* CFX_MacFontInfo::MapFont(int weight, // Times New Roman. A more sophisticated approach would be to find all the // fonts in |m_FontList| with |face| in the name, and examine the fonts to // see which best matches the requested characteristics. - if (face.Find("Bold") == -1 && face.Find("Italic") == -1) { - CFX_ByteString new_face = face; + if (!face.Contains("Bold") && !face.Contains("Italic")) { + ByteString new_face = face; if (weight > 400) new_face += " Bold"; if (bItalic) new_face += " Italic"; auto it = m_FontList.find(new_face); if (it != m_FontList.end()) - return it->second; + return it->second.get(); } auto it = m_FontList.find(face); if (it != m_FontList.end()) - return it->second; + return it->second.get(); - if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) + if (charset == FX_CHARSET_ANSI && FontFamilyIsFixedPitch(pitch_family)) return GetFont("Courier New"); - if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_SYMBOL_CHARSET) + if (charset == FX_CHARSET_ANSI || charset == FX_CHARSET_Symbol) return nullptr; switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: + case FX_CHARSET_ShiftJIS: GetJapanesePreference(&face, weight, pitch_family); break; - case FXFONT_GB2312_CHARSET: + case FX_CHARSET_ChineseSimplified: face = "STSong"; break; - case FXFONT_HANGUL_CHARSET: + case FX_CHARSET_Hangul: face = "AppleMyungjo"; break; - case FXFONT_CHINESEBIG5_CHARSET: + case FX_CHARSET_ChineseTraditional: face = "LiSong Pro Light"; } it = m_FontList.find(face); - return it != m_FontList.end() ? it->second : nullptr; + return it != m_FontList.end() ? it->second.get() : nullptr; } } // namespace std::unique_ptr IFX_SystemFontInfo::CreateDefault( const char** pUnused) { - CFX_MacFontInfo* pInfo(new CFX_MacFontInfo); + auto pInfo = pdfium::MakeUnique(); pInfo->AddPath("~/Library/Fonts"); pInfo->AddPath("/Library/Fonts"); pInfo->AddPath("/System/Library/Fonts"); - return std::unique_ptr(pInfo); + return std::move(pInfo); } void CFX_GEModule::InitPlatform() { diff --git a/core/fxge/apple/fx_quartz_device.cpp b/core/fxge/apple/fx_quartz_device.cpp index 0cd5b6b93a073b6ff45b59388f58024e076de41d..709f201f8a2cc7482ed712df21c0d0690e50c704 100644 --- a/core/fxge/apple/fx_quartz_device.cpp +++ b/core/fxge/apple/fx_quartz_device.cpp @@ -4,20 +4,18 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" #if !defined _SKIA_SUPPORT_ && !defined _SKIA_SUPPORT_PATHS_ #include "core/fxge/agg/fx_agg_driver.h" #endif #include "core/fxcrt/fx_memory.h" -#include "core/fxge/cfx_gemodule.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/dib/dib_int.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" #include "third_party/base/ptr_util.h" #include "core/fxge/apple/apple_int.h" @@ -25,7 +23,7 @@ #error Expected CGFLOAT_IS_DOUBLE to be defined by CoreGraphics headers #endif -void* CQuartz2D::createGraphics(CFX_DIBitmap* pBitmap) { +void* CQuartz2D::createGraphics(const RetainPtr& pBitmap) { if (!pBitmap) return nullptr; CGBitmapInfo bmpInfo = kCGBitmapByteOrder32Little; @@ -52,7 +50,7 @@ void CQuartz2D::destroyGraphics(void* graphics) { void* CQuartz2D::CreateFont(const uint8_t* pFontData, uint32_t dwFontSize) { CGDataProviderRef pDataProvider = CGDataProviderCreateWithData( - nullptr, pFontData, (size_t)dwFontSize, nullptr); + nullptr, pFontData, static_cast(dwFontSize), nullptr); if (!pDataProvider) return nullptr; @@ -77,7 +75,7 @@ void CQuartz2D::setGraphicsTextMatrix(void* graphics, CFX_Matrix* matrix) { bool CQuartz2D::drawGraphicsString(void* graphics, void* font, - FX_FLOAT fontSize, + float fontSize, uint16_t* glyphIndices, CGPoint* glyphPositions, int32_t charsCount, @@ -95,8 +93,11 @@ bool CQuartz2D::drawGraphicsString(void* graphics, matrix->e, matrix->f)); CGContextSetTextMatrix(context, m); } - int32_t a, r, g, b; - ArgbDecode(argb, a, r, g, b); + int32_t a; + int32_t r; + int32_t g; + int32_t b; + std::tie(a, r, g, b) = ArgbDecode(argb); CGContextSetRGBFillColor(context, r / 255.f, g / 255.f, b / 255.f, a / 255.f); CGContextSaveGState(context); #if CGFLOAT_IS_DOUBLE diff --git a/core/fxge/cfx_cliprgn.cpp b/core/fxge/cfx_cliprgn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9569ee909c4ce1794dd3551ce5b6f9098b0f9bff --- /dev/null +++ b/core/fxge/cfx_cliprgn.cpp @@ -0,0 +1,106 @@ +// Copyright 2016 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 "core/fxge/cfx_cliprgn.h" + +#include + +#include "core/fxge/dib/cfx_dibitmap.h" +#include "third_party/base/logging.h" + +CFX_ClipRgn::CFX_ClipRgn(int width, int height) + : m_Type(RectI), m_Box(0, 0, width, height) {} + +CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) { + m_Type = src.m_Type; + m_Box = src.m_Box; + m_Mask = src.m_Mask; +} + +CFX_ClipRgn::~CFX_ClipRgn() {} + +void CFX_ClipRgn::Reset(const FX_RECT& rect) { + m_Type = RectI; + m_Box = rect; + m_Mask = nullptr; +} + +void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) { + if (m_Type == RectI) { + m_Box.Intersect(rect); + return; + } + if (m_Type == MaskF) { + IntersectMaskRect(rect, m_Box, m_Mask); + return; + } +} + +void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, + FX_RECT mask_rect, + const RetainPtr& pMask) { + m_Type = MaskF; + m_Box = rect; + m_Box.Intersect(mask_rect); + if (m_Box.IsEmpty()) { + m_Type = RectI; + return; + } + if (m_Box == mask_rect) { + m_Mask = pMask; + return; + } + RetainPtr pOldMask(pMask); + m_Mask = pdfium::MakeRetain(); + m_Mask->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); + for (int row = m_Box.top; row < m_Box.bottom; row++) { + uint8_t* dest_scan = + m_Mask->GetBuffer() + m_Mask->GetPitch() * (row - m_Box.top); + uint8_t* src_scan = + pOldMask->GetBuffer() + pOldMask->GetPitch() * (row - mask_rect.top); + for (int col = m_Box.left; col < m_Box.right; col++) + dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; + } +} + +void CFX_ClipRgn::IntersectMaskF(int left, + int top, + const RetainPtr& pMask) { + ASSERT(pMask->GetFormat() == FXDIB_8bppMask); + FX_RECT mask_box(left, top, left + pMask->GetWidth(), + top + pMask->GetHeight()); + if (m_Type == RectI) { + IntersectMaskRect(m_Box, mask_box, pMask); + return; + } + if (m_Type == MaskF) { + FX_RECT new_box = m_Box; + new_box.Intersect(mask_box); + if (new_box.IsEmpty()) { + m_Type = RectI; + m_Mask = nullptr; + m_Box = new_box; + return; + } + auto new_dib = pdfium::MakeRetain(); + new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); + for (int row = new_box.top; row < new_box.bottom; row++) { + uint8_t* old_scan = + m_Mask->GetBuffer() + (row - m_Box.top) * m_Mask->GetPitch(); + uint8_t* mask_scan = pMask->GetBuffer() + (row - top) * pMask->GetPitch(); + uint8_t* new_scan = + new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); + for (int col = new_box.left; col < new_box.right; col++) { + new_scan[col - new_box.left] = + old_scan[col - m_Box.left] * mask_scan[col - left] / 255; + } + } + m_Box = new_box; + m_Mask = std::move(new_dib); + return; + } + NOTREACHED(); +} diff --git a/core/fxge/cfx_cliprgn.h b/core/fxge/cfx_cliprgn.h new file mode 100644 index 0000000000000000000000000000000000000000..58ebb4de7303a316f3c4edcf5310e6bc4496c43b --- /dev/null +++ b/core/fxge/cfx_cliprgn.h @@ -0,0 +1,41 @@ +// Copyright 2016 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 CORE_FXGE_CFX_CLIPRGN_H_ +#define CORE_FXGE_CFX_CLIPRGN_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" + +class CFX_DIBitmap; + +class CFX_ClipRgn { + public: + enum ClipType { RectI, MaskF }; + + CFX_ClipRgn(int device_width, int device_height); + CFX_ClipRgn(const CFX_ClipRgn& src); + ~CFX_ClipRgn(); + + ClipType GetType() const { return m_Type; } + const FX_RECT& GetBox() const { return m_Box; } + RetainPtr GetMask() const { return m_Mask; } + + void Reset(const FX_RECT& rect); + void IntersectRect(const FX_RECT& rect); + void IntersectMaskF(int left, int top, const RetainPtr& Mask); + + private: + void IntersectMaskRect(FX_RECT rect, + FX_RECT mask_box, + const RetainPtr& Mask); + + ClipType m_Type; + FX_RECT m_Box; + RetainPtr m_Mask; +}; + +#endif // CORE_FXGE_CFX_CLIPRGN_H_ diff --git a/core/fxge/cfx_color.cpp b/core/fxge/cfx_color.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42ab39d6704ecec634b8da7021e4afacd897b150 --- /dev/null +++ b/core/fxge/cfx_color.cpp @@ -0,0 +1,220 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_color.h" + +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" + +namespace { + +bool InRange(float comp) { + return comp >= 0.0f && comp <= 1.0f; +} + +CFX_Color ConvertCMYK2GRAY(float dC, float dM, float dY, float dK) { + if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK)) + return CFX_Color(CFX_Color::kGray); + return CFX_Color( + CFX_Color::kGray, + 1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK)); +} + +CFX_Color ConvertGRAY2CMYK(float dGray) { + if (!InRange(dGray)) + return CFX_Color(CFX_Color::kCMYK); + return CFX_Color(CFX_Color::kCMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray); +} + +CFX_Color ConvertGRAY2RGB(float dGray) { + if (!InRange(dGray)) + return CFX_Color(CFX_Color::kRGB); + return CFX_Color(CFX_Color::kRGB, dGray, dGray, dGray); +} + +CFX_Color ConvertRGB2GRAY(float dR, float dG, float dB) { + if (!InRange(dR) || !InRange(dG) || !InRange(dB)) + return CFX_Color(CFX_Color::kGray); + return CFX_Color(CFX_Color::kGray, 0.3f * dR + 0.59f * dG + 0.11f * dB); +} + +CFX_Color ConvertCMYK2RGB(float dC, float dM, float dY, float dK) { + if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK)) + return CFX_Color(CFX_Color::kRGB); + return CFX_Color(CFX_Color::kRGB, 1.0f - std::min(1.0f, dC + dK), + 1.0f - std::min(1.0f, dM + dK), + 1.0f - std::min(1.0f, dY + dK)); +} + +CFX_Color ConvertRGB2CMYK(float dR, float dG, float dB) { + if (!InRange(dR) || !InRange(dG) || !InRange(dB)) + return CFX_Color(CFX_Color::kCMYK); + + float c = 1.0f - dR; + float m = 1.0f - dG; + float y = 1.0f - dB; + return CFX_Color(CFX_Color::kCMYK, c, m, y, std::min(c, std::min(m, y))); +} + +} // namespace + +// Static. +CFX_Color CFX_Color::ParseColor(const CPDF_Array& array) { + CFX_Color rt; + switch (array.GetCount()) { + case 1: + rt = CFX_Color(CFX_Color::kGray, array.GetFloatAt(0)); + break; + case 3: + rt = CFX_Color(CFX_Color::kRGB, array.GetFloatAt(0), array.GetFloatAt(1), + array.GetFloatAt(2)); + break; + case 4: + rt = CFX_Color(CFX_Color::kCMYK, array.GetFloatAt(0), array.GetFloatAt(1), + array.GetFloatAt(2), array.GetFloatAt(3)); + break; + } + return rt; +} + +// Static. +CFX_Color CFX_Color::ParseColor(const ByteString& str) { + CPDF_SimpleParser syntax(str.AsStringView()); + if (syntax.FindTagParamFromStart("g", 1)) + return CFX_Color(CFX_Color::kGray, FX_atof(syntax.GetWord())); + + if (syntax.FindTagParamFromStart("rg", 3)) { + float f1 = FX_atof(syntax.GetWord()); + float f2 = FX_atof(syntax.GetWord()); + float f3 = FX_atof(syntax.GetWord()); + return CFX_Color(CFX_Color::kRGB, f1, f2, f3); + } + if (syntax.FindTagParamFromStart("k", 4)) { + float f1 = FX_atof(syntax.GetWord()); + float f2 = FX_atof(syntax.GetWord()); + float f3 = FX_atof(syntax.GetWord()); + float f4 = FX_atof(syntax.GetWord()); + return CFX_Color(CFX_Color::kCMYK, f1, f2, f3, f4); + } + return CFX_Color(CFX_Color::kTransparent); +} + +CFX_Color CFX_Color::ConvertColorType(int32_t nConvertColorType) const { + if (nColorType == nConvertColorType) + return *this; + + CFX_Color ret; + switch (nColorType) { + case CFX_Color::kTransparent: + ret = *this; + ret.nColorType = CFX_Color::kTransparent; + break; + case CFX_Color::kGray: + switch (nConvertColorType) { + case CFX_Color::kRGB: + ret = ConvertGRAY2RGB(fColor1); + break; + case CFX_Color::kCMYK: + ret = ConvertGRAY2CMYK(fColor1); + break; + } + break; + case CFX_Color::kRGB: + switch (nConvertColorType) { + case CFX_Color::kGray: + ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3); + break; + case CFX_Color::kCMYK: + ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3); + break; + } + break; + case CFX_Color::kCMYK: + switch (nConvertColorType) { + case CFX_Color::kGray: + ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4); + break; + case CFX_Color::kRGB: + ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4); + break; + } + break; + } + return ret; +} + +FX_COLORREF CFX_Color::ToFXColor(int32_t nTransparency) const { + CFX_Color ret; + switch (nColorType) { + case CFX_Color::kTransparent: { + ret = CFX_Color(CFX_Color::kTransparent, 0, 0, 0, 0); + break; + } + case CFX_Color::kGray: { + ret = ConvertGRAY2RGB(fColor1); + ret.fColor4 = nTransparency; + break; + } + case CFX_Color::kRGB: { + ret = CFX_Color(CFX_Color::kRGB, fColor1, fColor2, fColor3); + ret.fColor4 = nTransparency; + break; + } + case CFX_Color::kCMYK: { + ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4); + ret.fColor4 = nTransparency; + break; + } + } + return ArgbEncode(ret.fColor4, static_cast(ret.fColor1 * 255), + static_cast(ret.fColor2 * 255), + static_cast(ret.fColor3 * 255)); +} + +CFX_Color CFX_Color::operator-(float fColorSub) const { + CFX_Color sRet(nColorType); + switch (nColorType) { + case CFX_Color::kTransparent: + sRet.nColorType = CFX_Color::kRGB; + sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f); + sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f); + sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f); + break; + case CFX_Color::kRGB: + case CFX_Color::kGray: + case CFX_Color::kCMYK: + sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f); + sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f); + sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f); + sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f); + break; + } + return sRet; +} + +CFX_Color CFX_Color::operator/(float fColorDivide) const { + CFX_Color sRet(nColorType); + switch (nColorType) { + case CFX_Color::kTransparent: + sRet.nColorType = CFX_Color::kRGB; + sRet.fColor1 = 1.0f / fColorDivide; + sRet.fColor2 = 1.0f / fColorDivide; + sRet.fColor3 = 1.0f / fColorDivide; + break; + case CFX_Color::kRGB: + case CFX_Color::kGray: + case CFX_Color::kCMYK: + sRet = *this; + sRet.fColor1 /= fColorDivide; + sRet.fColor2 /= fColorDivide; + sRet.fColor3 /= fColorDivide; + sRet.fColor4 /= fColorDivide; + break; + } + return sRet; +} diff --git a/core/fxge/cfx_color.h b/core/fxge/cfx_color.h new file mode 100644 index 0000000000000000000000000000000000000000..099e19b11e276d6426e2b84de2e4a48898a9fb10 --- /dev/null +++ b/core/fxge/cfx_color.h @@ -0,0 +1,64 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_CFX_COLOR_H_ +#define CORE_FXGE_CFX_COLOR_H_ + +#include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fxge/fx_dib.h" + +struct CFX_Color { + static CFX_Color ParseColor(const CPDF_Array& array); + static CFX_Color ParseColor(const ByteString& str); + + enum Type { kTransparent = 0, kGray, kRGB, kCMYK }; + + explicit CFX_Color(FX_COLORREF ref) + : CFX_Color(FXARGB_R(ref), FXARGB_G(ref), FXARGB_B(ref)) {} + + CFX_Color(int32_t type = CFX_Color::kTransparent, + float color1 = 0.0f, + float color2 = 0.0f, + float color3 = 0.0f, + float color4 = 0.0f) + : nColorType(type), + fColor1(color1), + fColor2(color2), + fColor3(color3), + fColor4(color4) {} + + CFX_Color(int32_t r, int32_t g, int32_t b) + : nColorType(CFX_Color::kRGB), + fColor1(r / 255.0f), + fColor2(g / 255.0f), + fColor3(b / 255.0f), + fColor4(0) {} + + CFX_Color(const CFX_Color&) = default; + + CFX_Color operator/(float fColorDivide) const; + CFX_Color operator-(float fColorSub) const; + + CFX_Color ConvertColorType(int32_t other_nColorType) const; + + FX_COLORREF ToFXColor(int32_t nTransparency) const; + + void Reset() { + nColorType = CFX_Color::kTransparent; + fColor1 = 0.0f; + fColor2 = 0.0f; + fColor3 = 0.0f; + fColor4 = 0.0f; + } + + int32_t nColorType; + float fColor1; + float fColor2; + float fColor3; + float fColor4; +}; + +#endif // CORE_FXGE_CFX_COLOR_H_ diff --git a/core/fxge/cfx_defaultrenderdevice.h b/core/fxge/cfx_defaultrenderdevice.h new file mode 100644 index 0000000000000000000000000000000000000000..59415df6414ec36bdd04e19a7914c764e4773896 --- /dev/null +++ b/core/fxge/cfx_defaultrenderdevice.h @@ -0,0 +1,43 @@ +// Copyright 2016 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 CORE_FXGE_CFX_DEFAULTRENDERDEVICE_H_ +#define CORE_FXGE_CFX_DEFAULTRENDERDEVICE_H_ + +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/fx_dib.h" + +class SkPictureRecorder; + +class CFX_DefaultRenderDevice : public CFX_RenderDevice { + public: + CFX_DefaultRenderDevice(); + ~CFX_DefaultRenderDevice() override; + + bool Attach(const RetainPtr& pBitmap, + bool bRgbByteOrder, + const RetainPtr& pOriDevice, + bool bGroupKnockout); + bool Create(int width, + int height, + FXDIB_Format format, + const RetainPtr& pOriDevice); + +#ifdef _SKIA_SUPPORT_ + bool AttachRecorder(SkPictureRecorder* recorder); + void Clear(uint32_t color); + SkPictureRecorder* CreateRecorder(int size_x, int size_y); + void DebugVerifyBitmapIsPreMultiplied() const override; + bool SetBitsWithMask(const RetainPtr& pBitmap, + const RetainPtr& pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) override; +#endif +}; + +#endif // CORE_FXGE_CFX_DEFAULTRENDERDEVICE_H_ diff --git a/core/fxge/cfx_facecache.cpp b/core/fxge/cfx_facecache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f373fff892c6e01c412dca2e207a2074c40dab2 --- /dev/null +++ b/core/fxge/cfx_facecache.cpp @@ -0,0 +1,362 @@ +// Copyright 2016 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 "core/fxge/cfx_facecache.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_font.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/fx_freetype.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/ptr_util.h" + +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ +#include "third_party/skia/include/core/SkStream.h" +#include "third_party/skia/include/core/SkTypeface.h" + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#include "third_party/skia/include/ports/SkFontMgr.h" +#include "third_party/skia/include/ports/SkFontMgr_empty.h" +#endif +#endif + +namespace { + +constexpr uint32_t kInvalidGlyphIndex = static_cast(-1); + +constexpr int kMaxGlyphDimension = 2048; + +struct UniqueKeyGen { + void Generate(int count, ...); + + char key_[128]; + int key_len_; +}; + +void UniqueKeyGen::Generate(int count, ...) { + va_list argList; + va_start(argList, count); + for (int i = 0; i < count; i++) { + int p = va_arg(argList, int); + reinterpret_cast(key_)[i] = p; + } + va_end(argList); + key_len_ = count * sizeof(uint32_t); +} + +} // namespace + +CFX_FaceCache::CFX_FaceCache(FXFT_Face face) + : m_Face(face) +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ + , + m_pTypeface(nullptr) +#endif +{ +} + +CFX_FaceCache::~CFX_FaceCache() {} + +std::unique_ptr CFX_FaceCache::RenderGlyph( + const CFX_Font* pFont, + uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias) { + if (!m_Face) + return nullptr; + + FXFT_Matrix ft_matrix; + ft_matrix.xx = (signed long)(pMatrix->a / 64 * 65536); + ft_matrix.xy = (signed long)(pMatrix->c / 64 * 65536); + ft_matrix.yx = (signed long)(pMatrix->b / 64 * 65536); + ft_matrix.yy = (signed long)(pMatrix->d / 64 * 65536); + bool bUseCJKSubFont = false; + const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); + if (pSubstFont) { + bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle; + int skew = 0; + if (bUseCJKSubFont) + skew = pSubstFont->m_bItalicCJK ? -15 : 0; + else + skew = pSubstFont->m_ItalicAngle; + if (skew) { + // |skew| is nonpositive so |-skew| is used as the index. We need to make + // sure |skew| != INT_MIN since -INT_MIN is undefined. + if (skew <= 0 && skew != std::numeric_limits::min() && + static_cast(-skew) < CFX_Font::kAngleSkewArraySize) { + skew = -CFX_Font::s_AngleSkew[-skew]; + } else { + skew = -58; + } + if (pFont->IsVertical()) + ft_matrix.yx += ft_matrix.yy * skew / 100; + else + ft_matrix.xy -= ft_matrix.xx * skew / 100; + } + if (pSubstFont->m_bFlagMM) { + pFont->AdjustMMParams(glyph_index, dest_width, + pFont->GetSubstFont()->m_Weight); + } + } + ScopedFontTransform scoped_transform(m_Face, &ft_matrix); + int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) + ? FXFT_LOAD_NO_BITMAP + : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); + int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + if (error) { + // if an error is returned, try to reload glyphs without hinting. + if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) + return nullptr; + + load_flags |= FT_LOAD_NO_HINTING; + error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + + if (error) + return nullptr; + } + int weight = 0; + if (bUseCJKSubFont) + weight = pSubstFont->m_WeightCJK; + else + weight = pSubstFont ? pSubstFont->m_Weight : 0; + if (pSubstFont && !pSubstFont->m_bFlagMM && weight > 400) { + uint32_t index = (weight - 400) / 10; + if (index >= CFX_Font::kWeightPowArraySize) + return nullptr; + pdfium::base::CheckedNumeric level = 0; + if (pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) + level = CFX_Font::s_WeightPow_SHIFTJIS[index] * 2; + else + level = CFX_Font::s_WeightPow_11[index]; + + level = level * + (abs(static_cast(ft_matrix.xx)) + + abs(static_cast(ft_matrix.xy))) / + 36655; + FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), + level.ValueOrDefault(0)); + } + FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(), + FT_LCD_FILTER_DEFAULT); + error = FXFT_Render_Glyph(m_Face, anti_alias); + if (error) + return nullptr; + int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); + int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); + if (bmwidth > kMaxGlyphDimension || bmheight > kMaxGlyphDimension) + return nullptr; + int dib_width = bmwidth; + auto pGlyphBitmap = pdfium::MakeUnique(); + pGlyphBitmap->m_pBitmap->Create( + dib_width, bmheight, + anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); + pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); + pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); + int dest_pitch = pGlyphBitmap->m_pBitmap->GetPitch(); + int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); + uint8_t* pDestBuf = pGlyphBitmap->m_pBitmap->GetBuffer(); + uint8_t* pSrcBuf = + (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); + if (anti_alias != FXFT_RENDER_MODE_MONO && + FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == + FXFT_PIXEL_MODE_MONO) { + int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; + for (int i = 0; i < bmheight; i++) { + for (int n = 0; n < bmwidth; n++) { + uint8_t data = + (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; + for (int b = 0; b < bytes; b++) + pDestBuf[i * dest_pitch + n * bytes + b] = data; + } + } + } else { + memset(pDestBuf, 0, dest_pitch * bmheight); + int rowbytes = std::min(abs(src_pitch), dest_pitch); + for (int row = 0; row < bmheight; row++) + memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, rowbytes); + } + return pGlyphBitmap; +} + +const CFX_PathData* CFX_FaceCache::LoadGlyphPath(const CFX_Font* pFont, + uint32_t glyph_index, + int dest_width) { + if (!m_Face || glyph_index == kInvalidGlyphIndex) + return nullptr; + + const auto* pSubstFont = pFont->GetSubstFont(); + int weight = pSubstFont ? pSubstFont->m_Weight : 0; + int angle = pSubstFont ? pSubstFont->m_ItalicAngle : 0; + bool vertical = pSubstFont ? pFont->IsVertical() : false; + const PathMapKey key = + std::make_tuple(glyph_index, dest_width, weight, angle, vertical); + auto it = m_PathMap.find(key); + if (it != m_PathMap.end()) + return it->second.get(); + + CFX_PathData* pGlyphPath = pFont->LoadGlyphPathImpl(glyph_index, dest_width); + m_PathMap[key] = std::unique_ptr(pGlyphPath); + return pGlyphPath; +} + +const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(const CFX_Font* pFont, + uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias, + int& text_flags) { + if (glyph_index == kInvalidGlyphIndex) + return nullptr; + + UniqueKeyGen keygen; + int nMatrixA = static_cast(pMatrix->a * 10000); + int nMatrixB = static_cast(pMatrix->b * 10000); + int nMatrixC = static_cast(pMatrix->c * 10000); + int nMatrixD = static_cast(pMatrix->d * 10000); +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ + if (pFont->GetSubstFont()) { + keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + } else { + keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias); + } +#else + if (text_flags & FXTEXT_NO_NATIVETEXT) { + if (pFont->GetSubstFont()) { + keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, + pFont->IsVertical()); + } else { + keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias); + } + } else { + if (pFont->GetSubstFont()) { + keygen.Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), + 3); + } else { + keygen.Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, 3); + } + } +#endif + ByteString FaceGlyphsKey(keygen.key_, keygen.key_len_); +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \ + defined _SKIA_SUPPORT_PATHS_ + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, + bFontStyle, dest_width, anti_alias); +#else + if (text_flags & FXTEXT_NO_NATIVETEXT) { + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, + bFontStyle, dest_width, anti_alias); + } + std::unique_ptr pGlyphBitmap; + auto it = m_SizeMap.find(FaceGlyphsKey); + if (it != m_SizeMap.end()) { + SizeGlyphCache* pSizeCache = &(it->second); + auto it2 = pSizeCache->find(glyph_index); + if (it2 != pSizeCache->end()) + return it2->second.get(); + + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap) { + CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); + (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap); + return pResult; + } + } else { + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap) { + CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); + + SizeGlyphCache cache; + cache[glyph_index] = std::move(pGlyphBitmap); + + m_SizeMap[FaceGlyphsKey] = std::move(cache); + return pResult; + } + } + if (pFont->GetSubstFont()) { + keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + } else { + keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias); + } + ByteString FaceGlyphsKey2(keygen.key_, keygen.key_len_); + text_flags |= FXTEXT_NO_NATIVETEXT; + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, + bFontStyle, dest_width, anti_alias); +#endif +} + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +CFX_TypeFace* CFX_FaceCache::GetDeviceCache(const CFX_Font* pFont) { + if (!m_pTypeface) { + m_pTypeface = SkTypeface::MakeFromStream( + new SkMemoryStream(pFont->GetFontData(), pFont->GetSize())); + } +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + if (!m_pTypeface) { + sk_sp customMgr(SkFontMgr_New_Custom_Empty()); + m_pTypeface = customMgr->makeFromStream(pdfium::MakeUnique( + pFont->GetFontData(), pFont->GetSize())); + } +#endif + return m_pTypeface.get(); +} +#endif + +#if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_ +void CFX_FaceCache::InitPlatform() {} +#endif + +CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap( + const CFX_Font* pFont, + const CFX_Matrix* pMatrix, + const ByteString& FaceGlyphsKey, + uint32_t glyph_index, + bool bFontStyle, + int dest_width, + int anti_alias) { + SizeGlyphCache* pSizeCache; + auto it = m_SizeMap.find(FaceGlyphsKey); + if (it == m_SizeMap.end()) { + m_SizeMap[FaceGlyphsKey] = SizeGlyphCache(); + pSizeCache = &(m_SizeMap[FaceGlyphsKey]); + } else { + pSizeCache = &(it->second); + } + + auto it2 = pSizeCache->find(glyph_index); + if (it2 != pSizeCache->end()) + return it2->second.get(); + + std::unique_ptr pGlyphBitmap = RenderGlyph( + pFont, glyph_index, bFontStyle, pMatrix, dest_width, anti_alias); + CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); + (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap); + return pResult; +} diff --git a/core/fxge/cfx_facecache.h b/core/fxge/cfx_facecache.h index 44ed0b287ac297dec03698de0f8c82ce7352c671..a39da88b01394cd331b3a6dd01b86eef702dd5df 100644 --- a/core/fxge/cfx_facecache.h +++ b/core/fxge/cfx_facecache.h @@ -9,10 +9,19 @@ #include #include +#include +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ +#include "third_party/skia/include/core/SkTypeface.h" +#endif + +class CFX_Font; +class CFX_PathData; + class CFX_FaceCache { public: explicit CFX_FaceCache(FXFT_Face face); @@ -33,20 +42,25 @@ class CFX_FaceCache { #endif private: - CFX_GlyphBitmap* RenderGlyph(const CFX_Font* pFont, - uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias); - CFX_GlyphBitmap* RenderGlyph_Nativetext(const CFX_Font* pFont, - uint32_t glyph_index, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias); + using SizeGlyphCache = std::map>; + // + using PathMapKey = std::tuple; + + std::unique_ptr RenderGlyph(const CFX_Font* pFont, + uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias); + std::unique_ptr RenderGlyph_Nativetext( + const CFX_Font* pFont, + uint32_t glyph_index, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias); CFX_GlyphBitmap* LookUpGlyphBitmap(const CFX_Font* pFont, const CFX_Matrix* pMatrix, - const CFX_ByteString& FaceGlyphsKey, + const ByteString& FaceGlyphsKey, uint32_t glyph_index, bool bFontStyle, int dest_width, @@ -55,10 +69,10 @@ class CFX_FaceCache { void DestroyPlatform(); FXFT_Face const m_Face; - std::map> m_SizeMap; - std::map> m_PathMap; + std::map m_SizeMap; + std::map> m_PathMap; #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ - CFX_TypeFace* m_pTypeface; + sk_sp m_pTypeface; #endif }; diff --git a/core/fxge/cfx_folderfontinfo.cpp b/core/fxge/cfx_folderfontinfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..532824d248f5e89ee91d7cb2b7ae51c70273fbd1 --- /dev/null +++ b/core/fxge/cfx_folderfontinfo.cpp @@ -0,0 +1,398 @@ +// Copyright 2016 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 "core/fxge/cfx_folderfontinfo.h" + +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/fx_font.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +#define CHARSET_FLAG_ANSI (1 << 0) +#define CHARSET_FLAG_SYMBOL (1 << 1) +#define CHARSET_FLAG_SHIFTJIS (1 << 2) +#define CHARSET_FLAG_BIG5 (1 << 3) +#define CHARSET_FLAG_GB (1 << 4) +#define CHARSET_FLAG_KOREAN (1 << 5) + +namespace { + +const struct { + const char* m_pName; + const char* m_pSubstName; +} Base14Substs[] = { + {"Courier", "Courier New"}, + {"Courier-Bold", "Courier New Bold"}, + {"Courier-BoldOblique", "Courier New Bold Italic"}, + {"Courier-Oblique", "Courier New Italic"}, + {"Helvetica", "Arial"}, + {"Helvetica-Bold", "Arial Bold"}, + {"Helvetica-BoldOblique", "Arial Bold Italic"}, + {"Helvetica-Oblique", "Arial Italic"}, + {"Times-Roman", "Times New Roman"}, + {"Times-Bold", "Times New Roman Bold"}, + {"Times-BoldItalic", "Times New Roman Bold Italic"}, + {"Times-Italic", "Times New Roman Italic"}, +}; + +ByteString FPDF_ReadStringFromFile(FILE* pFile, uint32_t size) { + ByteString buffer; + if (!fread(buffer.GetBuffer(size), size, 1, pFile)) + return ByteString(); + buffer.ReleaseBuffer(size); + return buffer; +} + +ByteString FPDF_LoadTableFromTT(FILE* pFile, + const uint8_t* pTables, + uint32_t nTables, + uint32_t tag, + uint32_t fileSize) { + for (uint32_t i = 0; i < nTables; i++) { + const uint8_t* p = pTables + i * 16; + if (GET_TT_LONG(p) == tag) { + uint32_t offset = GET_TT_LONG(p + 8); + uint32_t size = GET_TT_LONG(p + 12); + if (offset > std::numeric_limits::max() - size || + offset + size > fileSize || fseek(pFile, offset, SEEK_SET) < 0) { + return ByteString(); + } + return FPDF_ReadStringFromFile(pFile, size); + } + } + return ByteString(); +} + +uint32_t GetCharset(int charset) { + switch (charset) { + case FX_CHARSET_ShiftJIS: + return CHARSET_FLAG_SHIFTJIS; + case FX_CHARSET_ChineseSimplified: + return CHARSET_FLAG_GB; + case FX_CHARSET_ChineseTraditional: + return CHARSET_FLAG_BIG5; + case FX_CHARSET_Hangul: + return CHARSET_FLAG_KOREAN; + case FX_CHARSET_Symbol: + return CHARSET_FLAG_SYMBOL; + case FX_CHARSET_ANSI: + return CHARSET_FLAG_ANSI; + default: + break; + } + return 0; +} + +int32_t GetSimilarValue(int weight, + bool bItalic, + int pitch_family, + uint32_t style) { + int32_t iSimilarValue = 0; + if (FontStyleIsBold(style) == (weight > 400)) + iSimilarValue += 16; + if (FontStyleIsItalic(style) == bItalic) + iSimilarValue += 16; + if (FontStyleIsSerif(style) == FontFamilyIsRoman(pitch_family)) + iSimilarValue += 16; + if (FontStyleIsScript(style) == FontFamilyIsScript(pitch_family)) + iSimilarValue += 8; + if (FontStyleIsFixedPitch(style) == FontFamilyIsFixedPitch(pitch_family)) + iSimilarValue += 8; + return iSimilarValue; +} + +} // namespace + +CFX_FolderFontInfo::CFX_FolderFontInfo() {} + +CFX_FolderFontInfo::~CFX_FolderFontInfo() {} + +void CFX_FolderFontInfo::AddPath(const ByteString& path) { + m_PathList.push_back(path); +} + +bool CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { + m_pMapper = pMapper; + for (const auto& path : m_PathList) + ScanPath(path); + return true; +} + +void CFX_FolderFontInfo::ScanPath(const ByteString& path) { + FX_FileHandle* handle = FX_OpenFolder(path.c_str()); + if (!handle) + return; + + ByteString filename; + bool bFolder; + while (FX_GetNextFile(handle, &filename, &bFolder)) { + if (bFolder) { + if (filename == "." || filename == "..") + continue; + } else { + ByteString ext = filename.Right(4); + ext.MakeUpper(); + if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") + continue; + } + + ByteString fullpath = path; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + fullpath += "\\"; +#else + fullpath += "/"; +#endif + + fullpath += filename; + bFolder ? ScanPath(fullpath) : ScanFile(fullpath); + } + FX_CloseFolder(handle); +} + +void CFX_FolderFontInfo::ScanFile(const ByteString& path) { + FILE* pFile = fopen(path.c_str(), "rb"); + if (!pFile) + return; + + fseek(pFile, 0, SEEK_END); + + uint32_t filesize = ftell(pFile); + uint8_t buffer[16]; + fseek(pFile, 0, SEEK_SET); + + size_t readCnt = fread(buffer, 12, 1, pFile); + if (readCnt != 1) { + fclose(pFile); + return; + } + + if (GET_TT_LONG(buffer) == kTableTTCF) { + uint32_t nFaces = GET_TT_LONG(buffer + 8); + if (nFaces > std::numeric_limits::max() / 4) { + fclose(pFile); + return; + } + uint32_t face_bytes = nFaces * 4; + uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); + readCnt = fread(offsets, 1, face_bytes, pFile); + if (readCnt != face_bytes) { + FX_Free(offsets); + fclose(pFile); + return; + } + for (uint32_t i = 0; i < nFaces; i++) { + uint8_t* p = offsets + i * 4; + ReportFace(path, pFile, filesize, GET_TT_LONG(p)); + } + FX_Free(offsets); + } else { + ReportFace(path, pFile, filesize, 0); + } + fclose(pFile); +} + +void CFX_FolderFontInfo::ReportFace(const ByteString& path, + FILE* pFile, + uint32_t filesize, + uint32_t offset) { + char buffer[16]; + if (fseek(pFile, offset, SEEK_SET) < 0 || !fread(buffer, 12, 1, pFile)) + return; + + uint32_t nTables = GET_TT_SHORT(buffer + 4); + ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16); + if (tables.IsEmpty()) + return; + + ByteString names = FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, + 0x6e616d65, filesize); + if (names.IsEmpty()) + return; + + ByteString facename = GetNameFromTT(names.raw_str(), names.GetLength(), 1); + if (facename.IsEmpty()) + return; + + ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2); + if (style != "Regular") + facename += " " + style; + + if (pdfium::ContainsKey(m_FontList, facename)) + return; + + auto pInfo = pdfium::MakeUnique(path, facename, tables, offset, + filesize); + ByteString os2 = FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, + 0x4f532f32, filesize); + if (os2.GetLength() >= 86) { + const uint8_t* p = os2.raw_str() + 78; + uint32_t codepages = GET_TT_LONG(p); + if (codepages & (1 << 17)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ShiftJIS); + pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; + } + if (codepages & (1 << 18)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ChineseSimplified); + pInfo->m_Charsets |= CHARSET_FLAG_GB; + } + if (codepages & (1 << 20)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ChineseTraditional); + pInfo->m_Charsets |= CHARSET_FLAG_BIG5; + } + if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_Hangul); + pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; + } + if (codepages & (1 << 31)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_Symbol); + pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; + } + } + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ANSI); + pInfo->m_Charsets |= CHARSET_FLAG_ANSI; + pInfo->m_Styles = 0; + if (style.Contains("Bold")) + pInfo->m_Styles |= FXFONT_BOLD; + if (style.Contains("Italic") || style.Contains("Oblique")) + pInfo->m_Styles |= FXFONT_ITALIC; + if (facename.Contains("Serif")) + pInfo->m_Styles |= FXFONT_SERIF; + + m_FontList[facename] = std::move(pInfo); +} + +void* CFX_FolderFontInfo::GetSubstFont(const ByteString& face) { + for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs); + iBaseFont++) { + if (face == Base14Substs[iBaseFont].m_pName) + return GetFont(Base14Substs[iBaseFont].m_pSubstName); + } + return nullptr; +} + +void* CFX_FolderFontInfo::FindFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family, + bool bMatchName) { + FontFaceInfo* pFind = nullptr; + if (charset == FX_CHARSET_ANSI && FontFamilyIsFixedPitch(pitch_family)) + return GetFont("Courier New"); + + uint32_t charset_flag = GetCharset(charset); + int32_t iBestSimilar = 0; + for (const auto& it : m_FontList) { + const ByteString& bsName = it.first; + FontFaceInfo* pFont = it.second.get(); + if (!(pFont->m_Charsets & charset_flag) && charset != FX_CHARSET_Default) + continue; + + if (bMatchName && !bsName.Contains(family)) + continue; + + int32_t iSimilarValue = + GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles); + if (iSimilarValue > iBestSimilar) { + iBestSimilar = iSimilarValue; + pFind = pFont; + } + } + return pFind; +} + +void* CFX_FolderFontInfo::MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family) { + return nullptr; +} + +#ifdef PDF_ENABLE_XFA +void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, + int weight, + bool bItalic, + int pitch_family) { + return nullptr; +} +#endif // PDF_ENABLE_XFA + +void* CFX_FolderFontInfo::GetFont(const char* face) { + auto it = m_FontList.find(face); + return it != m_FontList.end() ? it->second.get() : nullptr; +} + +uint32_t CFX_FolderFontInfo::GetFontData(void* hFont, + uint32_t table, + uint8_t* buffer, + uint32_t size) { + if (!hFont) + return 0; + + const FontFaceInfo* pFont = static_cast(hFont); + uint32_t datasize = 0; + uint32_t offset = 0; + if (table == 0) { + datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; + } else if (table == kTableTTCF) { + datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; + } else { + uint32_t nTables = pFont->m_FontTables.GetLength() / 16; + for (uint32_t i = 0; i < nTables; i++) { + const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16; + if (GET_TT_LONG(p) == table) { + offset = GET_TT_LONG(p + 8); + datasize = GET_TT_LONG(p + 12); + } + } + } + + if (!datasize || size < datasize) + return datasize; + + FILE* pFile = fopen(pFont->m_FilePath.c_str(), "rb"); + if (!pFile) + return 0; + + if (fseek(pFile, offset, SEEK_SET) < 0 || + fread(buffer, datasize, 1, pFile) != 1) { + datasize = 0; + } + fclose(pFile); + return datasize; +} + +void CFX_FolderFontInfo::DeleteFont(void* hFont) {} + +bool CFX_FolderFontInfo::GetFaceName(void* hFont, ByteString* name) { + if (!hFont) + return false; + *name = static_cast(hFont)->m_FaceName; + return true; +} + +bool CFX_FolderFontInfo::GetFontCharset(void* hFont, int* charset) { + return false; +} + +CFX_FolderFontInfo::FontFaceInfo::FontFaceInfo(ByteString filePath, + ByteString faceName, + ByteString fontTables, + uint32_t fontOffset, + uint32_t fileSize) + : m_FilePath(filePath), + m_FaceName(faceName), + m_FontTables(fontTables), + m_FontOffset(fontOffset), + m_FileSize(fileSize), + m_Styles(0), + m_Charsets(0) {} diff --git a/core/fxge/cfx_folderfontinfo.h b/core/fxge/cfx_folderfontinfo.h new file mode 100644 index 0000000000000000000000000000000000000000..397b38606676100c8eee7bdea5067a1a350917de --- /dev/null +++ b/core/fxge/cfx_folderfontinfo.h @@ -0,0 +1,84 @@ +// Copyright 2016 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 CORE_FXGE_CFX_FOLDERFONTINFO_H_ +#define CORE_FXGE_CFX_FOLDERFONTINFO_H_ + +#include +#include +#include + +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/ifx_systemfontinfo.h" + +class CFX_FolderFontInfo : public IFX_SystemFontInfo { + public: + CFX_FolderFontInfo(); + ~CFX_FolderFontInfo() override; + + void AddPath(const ByteString& path); + + // IFX_SytemFontInfo: + bool EnumFontList(CFX_FontMapper* pMapper) override; + void* MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* face) override; +#ifdef PDF_ENABLE_XFA + void* MapFontByUnicode(uint32_t dwUnicode, + int weight, + bool bItalic, + int pitch_family) override; +#endif // PDF_ENABLE_XFA + void* GetFont(const char* face) override; + uint32_t GetFontData(void* hFont, + uint32_t table, + uint8_t* buffer, + uint32_t size) override; + void DeleteFont(void* hFont) override; + bool GetFaceName(void* hFont, ByteString* name) override; + bool GetFontCharset(void* hFont, int* charset) override; + + protected: + class FontFaceInfo { + public: + FontFaceInfo(ByteString filePath, + ByteString faceName, + ByteString fontTables, + uint32_t fontOffset, + uint32_t fileSize); + + const ByteString m_FilePath; + const ByteString m_FaceName; + const ByteString m_FontTables; + const uint32_t m_FontOffset; + const uint32_t m_FileSize; + uint32_t m_Styles; + uint32_t m_Charsets; + }; + + void ScanPath(const ByteString& path); + void ScanFile(const ByteString& path); + void ReportFace(const ByteString& path, + FILE* pFile, + uint32_t filesize, + uint32_t offset); + void* GetSubstFont(const ByteString& face); + void* FindFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family, + bool bMatchName); + + std::map> m_FontList; + std::vector m_PathList; + UnownedPtr m_pMapper; +}; + +#endif // CORE_FXGE_CFX_FOLDERFONTINFO_H_ diff --git a/core/fxge/ge/cfx_font.cpp b/core/fxge/cfx_font.cpp similarity index 77% rename from core/fxge/ge/cfx_font.cpp rename to core/fxge/cfx_font.cpp index 87157b010114b70c5e16a495074024bf6c070966..6d969a345c713e08a170dc54448cdf4f938ebf61 100644 --- a/core/fxge/ge/cfx_font.cpp +++ b/core/fxge/cfx_font.cpp @@ -4,7 +4,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxge/fx_font.h" +#include "core/fxge/cfx_font.h" #include #include @@ -13,6 +13,8 @@ #include #include "core/fpdfapi/font/cpdf_font.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_stream.h" #include "core/fxge/cfx_facecache.h" #include "core/fxge/cfx_fontcache.h" #include "core/fxge/cfx_fontmgr.h" @@ -20,19 +22,21 @@ #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_substfont.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" #include "third_party/base/ptr_util.h" #define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em) namespace { -typedef struct { +constexpr int kThousandthMinInt = std::numeric_limits::min() / 1000; +constexpr int kThousandthMaxInt = std::numeric_limits::max() / 1000; + +struct OUTLINE_PARAMS { CFX_PathData* m_pPath; int m_CurX; int m_CurY; - FX_FLOAT m_CoordUnit; -} OUTLINE_PARAMS; + float m_CoordUnit; +}; #ifdef PDF_ENABLE_XFA @@ -45,20 +49,14 @@ unsigned long FTStreamRead(FXFT_Stream stream, IFX_SeekableReadStream* pFile = static_cast(stream->descriptor.pointer); - if (!pFile) - return 0; - - if (!pFile->ReadBlock(buffer, offset, count)) - return 0; - - return count; + return pFile && pFile->ReadBlock(buffer, offset, count) ? count : 0; } void FTStreamClose(FXFT_Stream stream) {} bool LoadFileImp(FXFT_Library library, FXFT_Face* Face, - const CFX_RetainPtr& pFile, + const RetainPtr& pFile, int32_t faceIndex, std::unique_ptr* stream) { auto stream1 = pdfium::MakeUnique(); @@ -102,7 +100,7 @@ void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) { } int Outline_MoveTo(const FXFT_Vector* to, void* user) { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + OUTLINE_PARAMS* param = static_cast(user); Outline_CheckEmptyContour(param); @@ -117,7 +115,7 @@ int Outline_MoveTo(const FXFT_Vector* to, void* user) { } int Outline_LineTo(const FXFT_Vector* to, void* user) { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + OUTLINE_PARAMS* param = static_cast(user); param->m_pPath->AppendPoint( CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), @@ -131,7 +129,7 @@ int Outline_LineTo(const FXFT_Vector* to, void* user) { int Outline_ConicTo(const FXFT_Vector* control, const FXFT_Vector* to, void* user) { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + OUTLINE_PARAMS* param = static_cast(user); param->m_pPath->AppendPoint( CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / @@ -158,7 +156,7 @@ int Outline_CubicTo(const FXFT_Vector* control1, const FXFT_Vector* control2, const FXFT_Vector* to, void* user) { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + OUTLINE_PARAMS* param = static_cast(user); param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit, control1->y / param->m_CoordUnit), @@ -213,16 +211,12 @@ const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = { CFX_Font::CFX_Font() : -#ifdef PDF_ENABLE_XFA - m_bShallowCopy(false), - m_pOwnedStream(nullptr), -#endif // PDF_ENABLE_XFA m_Face(nullptr), m_FaceCache(nullptr), m_pFontData(nullptr), m_pGsubData(nullptr), m_dwSize(0), -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ m_pPlatformFont(nullptr), #endif m_bEmbedded(false), @@ -230,45 +224,17 @@ CFX_Font::CFX_Font() } #ifdef PDF_ENABLE_XFA -bool CFX_Font::LoadClone(const CFX_Font* pFont) { - if (!pFont) - return false; - - m_bShallowCopy = true; - if (pFont->m_pSubstFont) { - m_pSubstFont = pdfium::MakeUnique(); - m_pSubstFont->m_Charset = pFont->m_pSubstFont->m_Charset; - m_pSubstFont->m_SubstFlags = pFont->m_pSubstFont->m_SubstFlags; - m_pSubstFont->m_Weight = pFont->m_pSubstFont->m_Weight; - m_pSubstFont->m_Family = pFont->m_pSubstFont->m_Family; - m_pSubstFont->m_ItalicAngle = pFont->m_pSubstFont->m_ItalicAngle; - } - m_Face = pFont->m_Face; - m_bEmbedded = pFont->m_bEmbedded; - m_bVertical = pFont->m_bVertical; - m_dwSize = pFont->m_dwSize; - m_pFontData = pFont->m_pFontData; - m_pGsubData = pFont->m_pGsubData; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_pPlatformFont = pFont->m_pPlatformFont; -#endif - m_pOwnedStream = pFont->m_pOwnedStream; - m_FaceCache = pFont->GetFaceCache(); - return true; -} - void CFX_Font::SetFace(FXFT_Face face) { ClearFaceCache(); m_Face = face; } +void CFX_Font::SetSubstFont(std::unique_ptr subst) { + m_pSubstFont = std::move(subst); +} #endif // PDF_ENABLE_XFA CFX_Font::~CFX_Font() { -#ifdef PDF_ENABLE_XFA - if (m_bShallowCopy) - return; -#endif // PDF_ENABLE_XFA if (m_Face) { #ifndef PDF_ENABLE_XFA if (FXFT_Get_Face_External_Stream(m_Face)) { @@ -277,26 +243,21 @@ CFX_Font::~CFX_Font() { #endif // PDF_ENABLE_XFA DeleteFace(); } -#ifdef PDF_ENABLE_XFA - delete m_pOwnedStream; -#endif // PDF_ENABLE_XFA - FX_Free(m_pGsubData); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && !defined _SKIA_SUPPORT_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ ReleasePlatformResource(); #endif } void CFX_Font::DeleteFace() { ClearFaceCache(); - if (m_bEmbedded) { + if (m_bEmbedded) FXFT_Done_Face(m_Face); - } else { + else CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); - } m_Face = nullptr; } -void CFX_Font::LoadSubst(const CFX_ByteString& face_name, +void CFX_Font::LoadSubst(const ByteString& face_name, bool bTrueType, uint32_t flags, int weight, @@ -316,9 +277,8 @@ void CFX_Font::LoadSubst(const CFX_ByteString& face_name, } #ifdef PDF_ENABLE_XFA -bool CFX_Font::LoadFile(const CFX_RetainPtr& pFile, - int nFaceIndex, - int* pFaceCount) { +bool CFX_Font::LoadFile(const RetainPtr& pFile, + int nFaceIndex) { m_bEmbedded = false; CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); @@ -329,9 +289,7 @@ bool CFX_Font::LoadFile(const CFX_RetainPtr& pFile, if (!LoadFileImp(library, &m_Face, pFile, nFaceIndex, &stream)) return false; - if (pFaceCount) - *pFaceCount = (int)m_Face->num_faces; - m_pOwnedStream = stream.release(); + m_pOwnedStream = std::move(stream); FXFT_Set_Pixel_Sizes(m_Face, 0, 64); return true; } @@ -340,16 +298,19 @@ bool CFX_Font::LoadFile(const CFX_RetainPtr& pFile, int CFX_Font::GetGlyphWidth(uint32_t glyph_index) { if (!m_Face) return 0; - if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) + if (m_pSubstFont && m_pSubstFont->m_bFlagMM) AdjustMMParams(glyph_index, 0, 0); int err = FXFT_Load_Glyph( m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if (err) return 0; - int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Glyph_HoriAdvance(m_Face)); - return width; + + int horiAdvance = FXFT_Get_Glyph_HoriAdvance(m_Face); + if (horiAdvance < kThousandthMinInt || horiAdvance > kThousandthMaxInt) + return 0; + + return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), horiAdvance); } bool CFX_Font::LoadEmbedded(const uint8_t* data, uint32_t size) { @@ -363,23 +324,29 @@ bool CFX_Font::LoadEmbedded(const uint8_t* data, uint32_t size) { } bool CFX_Font::IsTTFont() const { - if (!m_Face) - return false; - return FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; + return m_Face && FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; } int CFX_Font::GetAscent() const { if (!m_Face) return 0; - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_Ascender(m_Face)); + + int ascender = FXFT_Get_Face_Ascender(m_Face); + if (ascender < kThousandthMinInt || ascender > kThousandthMaxInt) + return 0; + + return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), ascender); } int CFX_Font::GetDescent() const { if (!m_Face) return 0; - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_Descender(m_Face)); + + int descender = FXFT_Get_Face_Descender(m_Face); + if (descender < kThousandthMinInt || descender > kThousandthMaxInt) + return 0; + + return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), descender); } bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { @@ -390,18 +357,21 @@ bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72); if (error) return false; + error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if (error) return false; + FXFT_BBox cbox; FT_Glyph glyph; - error = FXFT_Get_Glyph(((FXFT_Face)m_Face)->glyph, &glyph); + error = FXFT_Get_Glyph(m_Face->glyph, &glyph); if (error) return false; + FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); - int pixel_size_x = ((FXFT_Face)m_Face)->size->metrics.x_ppem, - pixel_size_y = ((FXFT_Face)m_Face)->size->metrics.y_ppem; + int pixel_size_x = m_Face->size->metrics.x_ppem, + pixel_size_y = m_Face->size->metrics.y_ppem; if (pixel_size_x == 0 || pixel_size_y == 0) { bbox.left = cbox.xMin; bbox.right = cbox.xMax; @@ -413,10 +383,10 @@ bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { bbox.top = cbox.yMax * 1000 / pixel_size_y; bbox.bottom = cbox.yMin * 1000 / pixel_size_y; } - if (bbox.top > FXFT_Get_Face_Ascender(m_Face)) - bbox.top = FXFT_Get_Face_Ascender(m_Face); - if (bbox.bottom < FXFT_Get_Face_Descender(m_Face)) - bbox.bottom = FXFT_Get_Face_Descender(m_Face); + bbox.top = std::min(bbox.top, + static_cast(FXFT_Get_Face_Ascender(m_Face))); + bbox.bottom = std::max( + bbox.bottom, static_cast(FXFT_Get_Face_Descender(m_Face))); FT_Done_Glyph(glyph); return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0; } @@ -447,51 +417,47 @@ bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { bool CFX_Font::IsItalic() const { if (!m_Face) return false; - if (FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC) return true; - CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face)); + + ByteString str(FXFT_Get_Face_Style_Name(m_Face)); str.MakeLower(); - return str.Find("italic") != -1; + return str.Contains("italic"); } bool CFX_Font::IsBold() const { - if (!m_Face) - return false; - return FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; + return m_Face && FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; } bool CFX_Font::IsFixedWidth() const { - if (!m_Face) - return false; - return FXFT_Is_Face_fixedwidth(m_Face) != 0; + return m_Face && FXFT_Is_Face_fixedwidth(m_Face) != 0; } -CFX_ByteString CFX_Font::GetPsName() const { +ByteString CFX_Font::GetPsName() const { if (!m_Face) - return CFX_ByteString(); + return ByteString(); - CFX_ByteString psName = FXFT_Get_Postscript_Name(m_Face); + ByteString psName = FXFT_Get_Postscript_Name(m_Face); if (psName.IsEmpty()) psName = "Untitled"; return psName; } -CFX_ByteString CFX_Font::GetFamilyName() const { +ByteString CFX_Font::GetFamilyName() const { if (!m_Face && !m_pSubstFont) - return CFX_ByteString(); + return ByteString(); if (m_Face) - return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face)); + return ByteString(FXFT_Get_Face_Family_Name(m_Face)); + return m_pSubstFont->m_Family; } -CFX_ByteString CFX_Font::GetFaceName() const { +ByteString CFX_Font::GetFaceName() const { if (!m_Face && !m_pSubstFont) - return CFX_ByteString(); + return ByteString(); if (m_Face) { - CFX_ByteString facename; - CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face)); - facename = GetFamilyName(); + ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face)); + ByteString facename = GetFamilyName(); if (facename.IsEmpty()) facename = "Untitled"; if (!style.IsEmpty() && style != "Regular") @@ -504,6 +470,7 @@ CFX_ByteString CFX_Font::GetFaceName() const { bool CFX_Font::GetBBox(FX_RECT& bbox) { if (!m_Face) return false; + int em = FXFT_Get_Face_UnitsPerEM(m_Face); if (em == 0) { bbox.left = FXFT_Get_Face_xMin(m_Face); @@ -519,50 +486,18 @@ bool CFX_Font::GetBBox(FX_RECT& bbox) { return true; } -int CFX_Font::GetHeight() const { - if (!m_Face) - return 0; - - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_Height(m_Face)); -} - -int CFX_Font::GetMaxAdvanceWidth() const { - if (!m_Face) - return 0; - - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_MaxAdvanceWidth(m_Face)); -} - CFX_FaceCache* CFX_Font::GetFaceCache() const { - if (!m_FaceCache) { + if (!m_FaceCache) m_FaceCache = CFX_GEModule::Get()->GetFontCache()->GetCachedFace(this); - } - return m_FaceCache; + return m_FaceCache.Get(); } void CFX_Font::ClearFaceCache() { if (!m_FaceCache) return; - CFX_GEModule::Get()->GetFontCache()->ReleaseCachedFace(this); - m_FaceCache = nullptr; -} - -int CFX_Font::GetULPos() const { - if (!m_Face) - return 0; - - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_UnderLinePosition(m_Face)); -} -int CFX_Font::GetULthickness() const { - if (!m_Face) - return 0; - - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_UnderLineThickness(m_Face)); + m_FaceCache = nullptr; + CFX_GEModule::Get()->GetFontCache()->ReleaseCachedFace(this); } void CFX_Font::AdjustMMParams(int glyph_index, @@ -572,11 +507,13 @@ void CFX_Font::AdjustMMParams(int glyph_index, FXFT_Get_MM_Var(m_Face, &pMasters); if (!pMasters) return; + long coords[2]; if (weight == 0) coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; else coords[0] = weight; + if (dest_width == 0) { coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; } else { @@ -598,9 +535,8 @@ void CFX_Font::AdjustMMParams(int glyph_index, FXFT_Free(m_Face, pMasters); return; } - int param = min_param + - (max_param - min_param) * (dest_width - min_width) / - (max_width - min_width); + int param = min_param + (max_param - min_param) * (dest_width - min_width) / + (max_width - min_width); coords[1] = param; } FXFT_Free(m_Face, pMasters); @@ -629,9 +565,8 @@ CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index, else ft_matrix.xy -= ft_matrix.xx * skew / 100; } - if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { + if (m_pSubstFont->m_bFlagMM) AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); - } } ScopedFontTransform scoped_transform(m_Face, &ft_matrix); int load_flags = FXFT_LOAD_NO_BITMAP; @@ -639,12 +574,12 @@ CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index, load_flags |= FT_LOAD_NO_HINTING; if (FXFT_Load_Glyph(m_Face, glyph_index, load_flags)) return nullptr; - if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && + if (m_pSubstFont && !m_pSubstFont->m_bFlagMM && m_pSubstFont->m_Weight > 400) { uint32_t index = (m_pSubstFont->m_Weight - 400) / 10; index = std::min(index, static_cast(kWeightPowArraySize - 1)); int level = 0; - if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) + if (m_pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; else level = s_WeightPow[index] * 2; diff --git a/core/fxge/cfx_font.h b/core/fxge/cfx_font.h new file mode 100644 index 0000000000000000000000000000000000000000..c8c4cf7a5f1ce10965f0376fbe4662ae253ef374 --- /dev/null +++ b/core/fxge/cfx_font.h @@ -0,0 +1,124 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_CFX_FONT_H_ +#define CORE_FXGE_CFX_FONT_H_ + +#include +#include + +#include "core/fxcrt/bytestring.h" +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/fx_freetype.h" + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +#include "core/fxge/fx_font.h" +#endif + +class CFX_FaceCache; +class CFX_GlyphBitmap; +class CFX_PathData; +class CFX_SubstFont; +class IFX_SeekableReadStream; + +class CFX_Font { + public: + CFX_Font(); + ~CFX_Font(); + + void LoadSubst(const ByteString& face_name, + bool bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int CharsetCP, + bool bVertical); + + bool LoadEmbedded(const uint8_t* data, uint32_t size); + FXFT_Face GetFace() const { return m_Face; } + CFX_SubstFont* GetSubstFont() const { return m_pSubstFont.get(); } + +#ifdef PDF_ENABLE_XFA + bool LoadFile(const RetainPtr& pFile, int nFaceIndex); + + void SetFace(FXFT_Face face); + void SetSubstFont(std::unique_ptr subst); +#endif // PDF_ENABLE_XFA + + const CFX_GlyphBitmap* LoadGlyphBitmap(uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias, + int& text_flags) const; + const CFX_PathData* LoadGlyphPath(uint32_t glyph_index, int dest_width) const; + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ + CFX_TypeFace* GetDeviceCache() const; +#endif + + int GetGlyphWidth(uint32_t glyph_index); + int GetAscent() const; + int GetDescent() const; + bool GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox); + bool IsItalic() const; + bool IsBold() const; + bool IsFixedWidth() const; + bool IsVertical() const { return m_bVertical; } + ByteString GetPsName() const; + ByteString GetFamilyName() const; + ByteString GetFaceName() const; + bool IsTTFont() const; + bool GetBBox(FX_RECT& bbox); + bool IsEmbedded() const { return m_bEmbedded; } + uint8_t* GetSubData() const { return m_pGsubData.get(); } + void SetSubData(uint8_t* data) { m_pGsubData.reset(data); } +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + void* GetPlatformFont() const { return m_pPlatformFont; } + void SetPlatformFont(void* font) { m_pPlatformFont = font; } +#endif + uint8_t* GetFontData() const { return m_pFontData; } + uint32_t GetSize() const { return m_dwSize; } + void AdjustMMParams(int glyph_index, int width, int weight) const; + + CFX_PathData* LoadGlyphPathImpl(uint32_t glyph_index, int dest_width) const; + + static const size_t kAngleSkewArraySize = 30; + static const char s_AngleSkew[kAngleSkewArraySize]; + static const size_t kWeightPowArraySize = 100; + static const uint8_t s_WeightPow[kWeightPowArraySize]; + static const uint8_t s_WeightPow_11[kWeightPowArraySize]; + static const uint8_t s_WeightPow_SHIFTJIS[kWeightPowArraySize]; + +#ifdef PDF_ENABLE_XFA + protected: + std::unique_ptr m_pOwnedStream; +#endif // PDF_ENABLE_XFA + + private: + CFX_FaceCache* GetFaceCache() const; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + void ReleasePlatformResource(); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + void DeleteFace(); + void ClearFaceCache(); + + FXFT_Face m_Face; + mutable UnownedPtr m_FaceCache; + std::unique_ptr m_pSubstFont; + std::vector m_pFontDataAllocation; + uint8_t* m_pFontData; + std::unique_ptr m_pGsubData; + uint32_t m_dwSize; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + void* m_pPlatformFont; +#endif + bool m_bEmbedded; + bool m_bVertical; +}; + +#endif // CORE_FXGE_CFX_FONT_H_ diff --git a/core/fxge/ge/cfx_fontcache.cpp b/core/fxge/cfx_fontcache.cpp similarity index 85% rename from core/fxge/ge/cfx_fontcache.cpp rename to core/fxge/cfx_fontcache.cpp index 58cee06d42ccf7b09994954ae187662d42e28cfe..5ccac8cfbcd6545eda5c6104eb1211b9b9860c7e 100644 --- a/core/fxge/ge/cfx_fontcache.cpp +++ b/core/fxge/cfx_fontcache.cpp @@ -12,6 +12,7 @@ #include "core/fxge/cfx_facecache.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" +#include "third_party/base/ptr_util.h" CFX_FontCache::CountedFaceCache::CountedFaceCache() {} @@ -35,10 +36,12 @@ CFX_FaceCache* CFX_FontCache::GetCachedFace(const CFX_Font* pFont) { return counted_face_cache->m_Obj.get(); } - std::unique_ptr counted_face_cache(new CountedFaceCache); + auto counted_face_cache = pdfium::MakeUnique(); counted_face_cache->m_nCount = 2; - CFX_FaceCache* face_cache = new CFX_FaceCache(bExternal ? nullptr : face); - counted_face_cache->m_Obj.reset(face_cache); + auto new_cache = + pdfium::MakeUnique(bExternal ? nullptr : face); + CFX_FaceCache* face_cache = new_cache.get(); + counted_face_cache->m_Obj = std::move(new_cache); map[face] = std::move(counted_face_cache); return face_cache; } diff --git a/core/fxge/cfx_fontcache.h b/core/fxge/cfx_fontcache.h index 52ac3fa342bb604c30a58b7a25ae925e6b6d58c9..a14ed09a1ef8ef2d7151d508b8498d78d5f08ad8 100644 --- a/core/fxge/cfx_fontcache.h +++ b/core/fxge/cfx_fontcache.h @@ -11,6 +11,7 @@ #include #include "core/fxcrt/fx_system.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" diff --git a/core/fxge/cfx_fontmapper.cpp b/core/fxge/cfx_fontmapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dba8f68b1c5119ad2e36375e122957614d0a660 --- /dev/null +++ b/core/fxge/cfx_fontmapper.cpp @@ -0,0 +1,802 @@ +// Copyright 2016 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 "core/fxge/cfx_fontmapper.h" + +#include +#include +#include +#include +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/ifx_systemfontinfo.h" +#include "third_party/base/stl_util.h" + +namespace { + +const int kNumStandardFonts = 14; + +const char* const g_Base14FontNames[kNumStandardFonts] = { + "Courier", + "Courier-Bold", + "Courier-BoldOblique", + "Courier-Oblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-BoldOblique", + "Helvetica-Oblique", + "Times-Roman", + "Times-Bold", + "Times-BoldItalic", + "Times-Italic", + "Symbol", + "ZapfDingbats", +}; + +const struct AltFontName { + const char* m_pName; + int m_Index; +} g_AltFontNames[] = { + {"Arial", 4}, + {"Arial,Bold", 5}, + {"Arial,BoldItalic", 6}, + {"Arial,Italic", 7}, + {"Arial-Bold", 5}, + {"Arial-BoldItalic", 6}, + {"Arial-BoldItalicMT", 6}, + {"Arial-BoldMT", 5}, + {"Arial-Italic", 7}, + {"Arial-ItalicMT", 7}, + {"ArialBold", 5}, + {"ArialBoldItalic", 6}, + {"ArialItalic", 7}, + {"ArialMT", 4}, + {"ArialMT,Bold", 5}, + {"ArialMT,BoldItalic", 6}, + {"ArialMT,Italic", 7}, + {"ArialRoundedMTBold", 5}, + {"Courier", 0}, + {"Courier,Bold", 1}, + {"Courier,BoldItalic", 2}, + {"Courier,Italic", 3}, + {"Courier-Bold", 1}, + {"Courier-BoldOblique", 2}, + {"Courier-Oblique", 3}, + {"CourierBold", 1}, + {"CourierBoldItalic", 2}, + {"CourierItalic", 3}, + {"CourierNew", 0}, + {"CourierNew,Bold", 1}, + {"CourierNew,BoldItalic", 2}, + {"CourierNew,Italic", 3}, + {"CourierNew-Bold", 1}, + {"CourierNew-BoldItalic", 2}, + {"CourierNew-Italic", 3}, + {"CourierNewBold", 1}, + {"CourierNewBoldItalic", 2}, + {"CourierNewItalic", 3}, + {"CourierNewPS-BoldItalicMT", 2}, + {"CourierNewPS-BoldMT", 1}, + {"CourierNewPS-ItalicMT", 3}, + {"CourierNewPSMT", 0}, + {"CourierStd", 0}, + {"CourierStd-Bold", 1}, + {"CourierStd-BoldOblique", 2}, + {"CourierStd-Oblique", 3}, + {"Helvetica", 4}, + {"Helvetica,Bold", 5}, + {"Helvetica,BoldItalic", 6}, + {"Helvetica,Italic", 7}, + {"Helvetica-Bold", 5}, + {"Helvetica-BoldItalic", 6}, + {"Helvetica-BoldOblique", 6}, + {"Helvetica-Italic", 7}, + {"Helvetica-Oblique", 7}, + {"HelveticaBold", 5}, + {"HelveticaBoldItalic", 6}, + {"HelveticaItalic", 7}, + {"Symbol", 12}, + {"SymbolMT", 12}, + {"Times-Bold", 9}, + {"Times-BoldItalic", 10}, + {"Times-Italic", 11}, + {"Times-Roman", 8}, + {"TimesBold", 9}, + {"TimesBoldItalic", 10}, + {"TimesItalic", 11}, + {"TimesNewRoman", 8}, + {"TimesNewRoman,Bold", 9}, + {"TimesNewRoman,BoldItalic", 10}, + {"TimesNewRoman,Italic", 11}, + {"TimesNewRoman-Bold", 9}, + {"TimesNewRoman-BoldItalic", 10}, + {"TimesNewRoman-Italic", 11}, + {"TimesNewRomanBold", 9}, + {"TimesNewRomanBoldItalic", 10}, + {"TimesNewRomanItalic", 11}, + {"TimesNewRomanPS", 8}, + {"TimesNewRomanPS-Bold", 9}, + {"TimesNewRomanPS-BoldItalic", 10}, + {"TimesNewRomanPS-BoldItalicMT", 10}, + {"TimesNewRomanPS-BoldMT", 9}, + {"TimesNewRomanPS-Italic", 11}, + {"TimesNewRomanPS-ItalicMT", 11}, + {"TimesNewRomanPSMT", 8}, + {"TimesNewRomanPSMT,Bold", 9}, + {"TimesNewRomanPSMT,BoldItalic", 10}, + {"TimesNewRomanPSMT,Italic", 11}, + {"ZapfDingbats", 13}, +}; + +const struct AltFontFamily { + const char* m_pFontName; + const char* m_pFontFamily; +} g_AltFontFamilies[] = { + {"AGaramondPro", "Adobe Garamond Pro"}, + {"BankGothicBT-Medium", "BankGothic Md BT"}, + {"ForteMT", "Forte"}, +}; + +const struct CODEPAGE_MAP { + uint16_t codepage; + uint8_t charset; +} g_Codepage2CharsetTable[] = { + {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, + {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, + {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, + {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, + {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, + {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, + {10081, 86}, +}; + +ByteString TT_NormalizeName(const char* family) { + ByteString norm(family); + norm.Remove(' '); + norm.Remove('-'); + norm.Remove(','); + auto pos = norm.Find('+'); + if (pos.has_value() && pos.value() != 0) + norm = norm.Left(pos.value()); + norm.MakeLower(); + return norm; +} + +uint8_t GetCharsetFromCodePage(uint16_t codepage) { + const CODEPAGE_MAP* pEnd = + g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); + const CODEPAGE_MAP* pCharmap = + std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, + [](const CODEPAGE_MAP& charset, uint16_t page) { + return charset.codepage < page; + }); + if (pCharmap < pEnd && codepage == pCharmap->codepage) + return pCharmap->charset; + return FX_CHARSET_Default; +} + +void GetFontFamily(uint32_t nStyle, ByteString* fontName) { + if (fontName->Contains("Script")) { + if (FontStyleIsBold(nStyle)) + *fontName = "ScriptMTBold"; + else if (fontName->Contains("Palace")) + *fontName = "PalaceScriptMT"; + else if (fontName->Contains("French")) + *fontName = "FrenchScriptMT"; + else if (fontName->Contains("FreeStyle")) + *fontName = "FreeStyleScript"; + return; + } + for (const auto& alternate : g_AltFontFamilies) { + if (fontName->Contains(alternate.m_pFontName)) { + *fontName = alternate.m_pFontFamily; + return; + } + } +} + +ByteString ParseStyle(const char* pStyle, int iLen, int iIndex) { + std::ostringstream buf; + if (!iLen || iLen <= iIndex) + return ByteString(buf); + while (iIndex < iLen) { + if (pStyle[iIndex] == ',') + break; + buf << pStyle[iIndex]; + ++iIndex; + } + return ByteString(buf); +} + +const struct FX_FontStyle { + const char* name; + size_t len; + uint32_t style; +} g_FontStyles[] = { + {"Bold", 4, FXFONT_BOLD}, + {"Italic", 6, FXFONT_ITALIC}, + {"BoldItalic", 10, FXFONT_BOLD | FXFONT_ITALIC}, + {"Reg", 3, FXFONT_NORMAL}, + {"Regular", 7, FXFONT_NORMAL}, +}; + +// +std::tuple GetStyleType(const ByteString& bsStyle, + bool bReverse) { + if (bsStyle.IsEmpty()) + return std::make_tuple(false, FXFONT_NORMAL, 0); + + for (int i = FX_ArraySize(g_FontStyles) - 1; i >= 0; --i) { + const FX_FontStyle* pStyle = g_FontStyles + i; + if (!pStyle || pStyle->len > bsStyle.GetLength()) + continue; + + if (bReverse) { + if (bsStyle.Right(pStyle->len).Compare(pStyle->name) == 0) + return std::make_tuple(true, pStyle->style, pStyle->len); + } else { + if (bsStyle.Left(pStyle->len).Compare(pStyle->name) == 0) + return std::make_tuple(true, pStyle->style, pStyle->len); + } + } + return std::make_tuple(false, FXFONT_NORMAL, 0); +} + +bool CheckSupportThirdPartFont(const ByteString& name, int* PitchFamily) { + if (name != "MyriadPro") + return false; + *PitchFamily &= ~FXFONT_FF_ROMAN; + return true; +} + +void UpdatePitchFamily(uint32_t flags, int* PitchFamily) { + if (FontStyleIsSerif(flags)) + *PitchFamily |= FXFONT_FF_ROMAN; + if (FontStyleIsScript(flags)) + *PitchFamily |= FXFONT_FF_SCRIPT; + if (FontStyleIsFixedPitch(flags)) + *PitchFamily |= FXFONT_FF_FIXEDPITCH; +} + +} // namespace + +CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) + : m_bListLoaded(false), m_pFontMgr(mgr) { + m_MMFaces[0] = nullptr; + m_MMFaces[1] = nullptr; + memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); +} + +CFX_FontMapper::~CFX_FontMapper() { + for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { + if (m_FoxitFaces[i]) + FXFT_Done_Face(m_FoxitFaces[i]); + } + if (m_MMFaces[0]) + FXFT_Done_Face(m_MMFaces[0]); + if (m_MMFaces[1]) + FXFT_Done_Face(m_MMFaces[1]); +} + +void CFX_FontMapper::SetSystemFontInfo( + std::unique_ptr pFontInfo) { + if (!pFontInfo) + return; + + m_pFontInfo = std::move(pFontInfo); +} + +ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { + if (!m_pFontInfo) + return ByteString(); + + uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); + if (!size) + return ByteString(); + + std::vector buffer(size); + uint8_t* buffer_ptr = buffer.data(); + uint32_t bytes_read = + m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); + return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) + : ByteString(); +} + +void CFX_FontMapper::AddInstalledFont(const ByteString& name, int charset) { + if (!m_pFontInfo) + return; + + m_FaceArray.push_back({name, static_cast(charset)}); + if (name == m_LastFamily) + return; + + bool bLocalized = std::any_of(name.begin(), name.end(), [](const char& c) { + return static_cast(c) > 0x80; + }); + + if (bLocalized) { + void* hFont = m_pFontInfo->GetFont(name.c_str()); + if (!hFont) { + hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str()); + if (!hFont) + return; + } + + ByteString new_name = GetPSNameFromTT(hFont); + if (!new_name.IsEmpty()) + m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); + m_pFontInfo->DeleteFont(hFont); + } + m_InstalledTTFonts.push_back(name); + m_LastFamily = name; +} + +void CFX_FontMapper::LoadInstalledFonts() { + if (!m_pFontInfo || m_bListLoaded) + return; + + m_pFontInfo->EnumFontList(this); + m_bListLoaded = true; +} + +ByteString CFX_FontMapper::MatchInstalledFonts(const ByteString& norm_name) { + LoadInstalledFonts(); + int i; + for (i = pdfium::CollectionSize(m_InstalledTTFonts) - 1; i >= 0; i--) { + ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); + if (norm1 == norm_name) + return m_InstalledTTFonts[i]; + } + for (i = pdfium::CollectionSize(m_LocalizedTTFonts) - 1; i >= 0; i--) { + ByteString norm1 = TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str()); + if (norm1 == norm_name) + return m_LocalizedTTFonts[i].second; + } + return ByteString(); +} + +FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, + int iBaseFont, + int italic_angle, + int weight, + int pitch_family) { + if (iBaseFont < kNumStandardFonts) { + if (m_FoxitFaces[iBaseFont]) + return m_FoxitFaces[iBaseFont]; + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { + m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[iBaseFont]; + } + } + pSubstFont->m_bFlagMM = true; + pSubstFont->m_ItalicAngle = italic_angle; + if (weight) + pSubstFont->m_Weight = weight; + if (FontFamilyIsRoman(pitch_family)) { + pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; + pSubstFont->m_Family = "Chrome Serif"; + if (m_MMFaces[1]) + return m_MMFaces[1]; + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); + m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[1]; + } + pSubstFont->m_Family = "Chrome Sans"; + if (m_MMFaces[0]) + return m_MMFaces[0]; + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); + m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[0]; +} + +FXFT_Face CFX_FontMapper::FindSubstFont(const ByteString& name, + bool bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int WindowCP, + CFX_SubstFont* pSubstFont) { + if (weight == 0) + weight = FXFONT_FW_NORMAL; + + if (!(flags & FXFONT_USEEXTERNATTR)) { + weight = FXFONT_FW_NORMAL; + italic_angle = 0; + } + ByteString SubstName = name; + SubstName.Remove(' '); + if (bTrueType && name.GetLength() > 0 && name[0] == '@') + SubstName = name.Right(name.GetLength() - 1); + PDF_GetStandardFontName(&SubstName); + if (SubstName == "Symbol" && !bTrueType) { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_Charset = FX_CHARSET_Symbol; + return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0); + } + if (SubstName == "ZapfDingbats") { + pSubstFont->m_Family = "Chrome Dingbats"; + pSubstFont->m_Charset = FX_CHARSET_Symbol; + return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0); + } + int iBaseFont = 0; + ByteString family; + ByteString style; + bool bHasComma = false; + bool bHasHyphen = false; + auto pos = SubstName.Find(",", 0); + if (pos.has_value()) { + family = SubstName.Left(pos.value()); + PDF_GetStandardFontName(&family); + style = SubstName.Right(SubstName.GetLength() - (pos.value() + 1)); + bHasComma = true; + } else { + family = SubstName; + } + for (; iBaseFont < 12; iBaseFont++) { + if (family == ByteStringView(g_Base14FontNames[iBaseFont])) + break; + } + int PitchFamily = 0; + bool bItalic = false; + uint32_t nStyle = FXFONT_NORMAL; + bool bStyleAvail = false; + if (iBaseFont < 12) { + if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) + nStyle |= FXFONT_BOLD; + if ((iBaseFont % 4) / 2) + nStyle |= FXFONT_ITALIC; + if (iBaseFont < 4) + PitchFamily |= FXFONT_FF_FIXEDPITCH; + if (iBaseFont >= 8) + PitchFamily |= FXFONT_FF_ROMAN; + } else { + iBaseFont = kNumStandardFonts; + if (!bHasComma) { + pos = family.ReverseFind('-'); + if (pos.has_value()) { + style = family.Right(family.GetLength() - (pos.value() + 1)); + family = family.Left(pos.value()); + bHasHyphen = true; + } + } + if (!bHasHyphen) { + int nLen = family.GetLength(); + bool hasStyleType; + uint32_t styleType; + size_t len; + std::tie(hasStyleType, styleType, len) = GetStyleType(family, true); + if (hasStyleType) { + family = family.Left(nLen - len); + nStyle |= styleType; + } + } + UpdatePitchFamily(flags, &PitchFamily); + } + + int old_weight = weight; + if (FontStyleIsBold(nStyle)) + weight = FXFONT_FW_BOLD; + + if (!style.IsEmpty()) { + int nLen = style.GetLength(); + const char* pStyle = style.c_str(); + int i = 0; + bool bFirstItem = true; + ByteString buf; + while (i < nLen) { + buf = ParseStyle(pStyle, nLen, i); + + bool hasStyleType; + uint32_t styleType; + size_t len; + std::tie(hasStyleType, styleType, len) = GetStyleType(buf, false); + if ((i && !bStyleAvail) || (!i && !hasStyleType)) { + family = SubstName; + iBaseFont = kNumStandardFonts; + break; + } + if (hasStyleType) + bStyleAvail = true; + + if (FontStyleIsBold(styleType)) { + // If we're already bold, then we're double bold, use special weight. + if (FontStyleIsBold(nStyle)) { + weight = FXFONT_FW_BOLD_BOLD; + } else { + weight = FXFONT_FW_BOLD; + nStyle |= FXFONT_BOLD; + } + + bFirstItem = false; + } + if (FontStyleIsItalic(styleType) && FontStyleIsBold(styleType)) { + nStyle |= FXFONT_ITALIC; + } else if (FontStyleIsItalic(styleType)) { + if (bFirstItem) { + nStyle |= FXFONT_ITALIC; + } else { + family = SubstName; + iBaseFont = kNumStandardFonts; + } + break; + } + i += buf.GetLength() + 1; + } + } + if (FontStyleIsItalic(nStyle)) + bItalic = true; + + int Charset = FX_CHARSET_ANSI; + if (WindowCP) + Charset = GetCharsetFromCodePage(WindowCP); + else if (iBaseFont == kNumStandardFonts && FontStyleIsSymbolic(flags)) + Charset = FX_CHARSET_Symbol; + + bool bCJK = (Charset == FX_CHARSET_ShiftJIS || + Charset == FX_CHARSET_ChineseSimplified || + Charset == FX_CHARSET_Hangul || + Charset == FX_CHARSET_ChineseTraditional); + if (!m_pFontInfo) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + GetFontFamily(nStyle, &family); + ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); + if (match.IsEmpty() && family != SubstName && + (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) { + match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); + } + if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) { + if (!bCJK) { + if (!CheckSupportThirdPartFont(family, &PitchFamily)) { + bItalic = italic_angle != 0; + weight = old_weight; + } +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ + const char* narrow_family = "LiberationSansNarrow"; +#elif _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ + const char* narrow_family = "RobotoCondensed"; +#else + const char* narrow_family = "ArialNarrow"; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ + auto pos = SubstName.Find("Narrow"); + if (pos.has_value() && pos.value() != 0) + family = narrow_family; + pos = SubstName.Find("Condensed"); + if (pos.has_value() && pos.value() != 0) + family = narrow_family; + } else { + pSubstFont->m_bSubstCJK = true; + if (nStyle) + pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL; + if (FontStyleIsItalic(nStyle)) + pSubstFont->m_bItalicCJK = true; + } + } else { + italic_angle = 0; + } + + if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) { + if (!match.IsEmpty()) + family = match; + if (iBaseFont < kNumStandardFonts) { + if (nStyle && !(iBaseFont % 4)) { + if (FontStyleIsBold(nStyle) && FontStyleIsItalic(nStyle)) + iBaseFont += 2; + else if (FontStyleIsBold(nStyle)) + iBaseFont += 1; + else if (FontStyleIsItalic(nStyle)) + iBaseFont += 3; + } + family = g_Base14FontNames[iBaseFont]; + } + } else if (FontStyleIsItalic(flags)) { + bItalic = true; + } + void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, + family.c_str()); + if (!hFont) { +#ifdef PDF_ENABLE_XFA + if (flags & FXFONT_EXACTMATCH) + return nullptr; +#endif // PDF_ENABLE_XFA + if (bCJK) { + bItalic = italic_angle != 0; + weight = old_weight; + } + if (!match.IsEmpty()) { + hFont = m_pFontInfo->GetFont(match.c_str()); + if (!hFont) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + } else { + if (Charset == FX_CHARSET_Symbol) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \ + _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ + if (SubstName == "Symbol") { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_Charset = FX_CHARSET_Symbol; + return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight, + PitchFamily); + } +#endif + return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, + weight, italic_angle, 0, pSubstFont); + } + if (Charset == FX_CHARSET_ANSI) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + + auto it = + std::find_if(m_FaceArray.begin(), m_FaceArray.end(), + [Charset](const FaceData& face) { + return face.charset == static_cast(Charset); + }); + if (it == m_FaceArray.end()) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + hFont = m_pFontInfo->GetFont(it->name.c_str()); + } + } + if (!hFont) + return nullptr; + + m_pFontInfo->GetFaceName(hFont, &SubstName); + if (Charset == FX_CHARSET_Default) + m_pFontInfo->GetFontCharset(hFont, &Charset); + uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); + uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + FXFT_Face face = nullptr; + if (ttc_size) + face = GetCachedTTCFace(hFont, kTableTTCF, ttc_size, font_size); + else + face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); + if (!face) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + pSubstFont->m_Family = SubstName; + pSubstFont->m_Charset = Charset; + bool bNeedUpdateWeight = false; + if (FXFT_Is_Face_Bold(face)) + bNeedUpdateWeight = weight != FXFONT_FW_BOLD; + else + bNeedUpdateWeight = weight != FXFONT_FW_NORMAL; + if (bNeedUpdateWeight) + pSubstFont->m_Weight = weight; + if (bItalic && !FXFT_Is_Face_Italic(face)) { + if (italic_angle == 0) + italic_angle = -12; + else if (abs(italic_angle) < 5) + italic_angle = 0; + pSubstFont->m_ItalicAngle = italic_angle; + } + m_pFontInfo->DeleteFont(hFont); + return face; +} + +#ifdef PDF_ENABLE_XFA +FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, + uint32_t flags, + int weight, + int italic_angle) { + if (!m_pFontInfo) + return nullptr; + + bool bItalic = (flags & FXFONT_ITALIC) != 0; + int PitchFamily = 0; + UpdatePitchFamily(flags, &PitchFamily); + void* hFont = + m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); + if (!hFont) + return nullptr; + + uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); + uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + FXFT_Face face = nullptr; + if (ttc_size) { + face = GetCachedTTCFace(hFont, 0x74746366, ttc_size, font_size); + } else { + ByteString SubstName; + m_pFontInfo->GetFaceName(hFont, &SubstName); + face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); + } + m_pFontInfo->DeleteFont(hFont); + return face; +} +#endif // PDF_ENABLE_XFA + +int CFX_FontMapper::GetFaceSize() const { + return pdfium::CollectionSize(m_FaceArray); +} + +bool CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { + for (size_t i = 0; i < MM_FACE_COUNT; ++i) { + if (m_MMFaces[i] == face) + return true; + } + for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { + if (m_FoxitFaces[i] == face) + return true; + } + return false; +} + +FXFT_Face CFX_FontMapper::GetCachedTTCFace(void* hFont, + const uint32_t tableTTCF, + uint32_t ttc_size, + uint32_t font_size) { + uint8_t buffer[1024]; + m_pFontInfo->GetFontData(hFont, tableTTCF, buffer, FX_ArraySize(buffer)); + uint32_t* pBuffer = reinterpret_cast(buffer); + uint32_t checksum = 0; + for (int i = 0; i < 256; i++) + checksum += pBuffer[i]; + uint8_t* pFontData; + FXFT_Face face = m_pFontMgr->GetCachedTTCFace( + ttc_size, checksum, ttc_size - font_size, &pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, ttc_size); + m_pFontInfo->GetFontData(hFont, tableTTCF, pFontData, ttc_size); + face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, + ttc_size - font_size); + } + return face; +} + +FXFT_Face CFX_FontMapper::GetCachedFace(void* hFont, + ByteString SubstName, + int weight, + bool bItalic, + uint32_t font_size) { + uint8_t* pFontData; + FXFT_Face face = + m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, &pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, font_size); + m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); + face = + m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, + font_size, m_pFontInfo->GetFaceIndex(hFont)); + } + return face; +} + +int PDF_GetStandardFontName(ByteString* name) { + const auto* end = std::end(g_AltFontNames); + const auto* found = + std::lower_bound(std::begin(g_AltFontNames), end, name->c_str(), + [](const AltFontName& element, const char* name) { + return FXSYS_stricmp(element.m_pName, name) < 0; + }); + if (found == end || FXSYS_stricmp(found->m_pName, name->c_str())) + return -1; + + *name = g_Base14FontNames[found->m_Index]; + return found->m_Index; +} diff --git a/core/fxge/cfx_fontmapper.h b/core/fxge/cfx_fontmapper.h index 96630a77dfdb95db40f10fd00836b5cd88e3e7da..ed8ab614452e54673066ca42ae865fe121e1fffd 100644 --- a/core/fxge/cfx_fontmapper.h +++ b/core/fxge/cfx_fontmapper.h @@ -11,10 +11,11 @@ #include #include -#include "core/fxge/cfx_fontmgr.h" #include "core/fxge/fx_font.h" +class CFX_FontMgr; class CFX_SubstFont; +class IFX_SystemFontInfo; class CFX_FontMapper { public: @@ -23,10 +24,10 @@ class CFX_FontMapper { void SetSystemFontInfo(std::unique_ptr pFontInfo); IFX_SystemFontInfo* GetSystemFontInfo() { return m_pFontInfo.get(); } - void AddInstalledFont(const CFX_ByteString& name, int charset); + void AddInstalledFont(const ByteString& name, int charset); void LoadInstalledFonts(); - FXFT_Face FindSubstFont(const CFX_ByteString& face_name, + FXFT_Face FindSubstFont(const ByteString& face_name, bool bTrueType, uint32_t flags, int weight, @@ -41,19 +42,17 @@ class CFX_FontMapper { #endif // PDF_ENABLE_XFA bool IsBuiltinFace(const FXFT_Face face) const; int GetFaceSize() const; - CFX_ByteString GetFaceName(int index) const { - return m_FaceArray[index].name; - } + ByteString GetFaceName(int index) const { return m_FaceArray[index].name; } - std::vector m_InstalledTTFonts; - std::vector> m_LocalizedTTFonts; + std::vector m_InstalledTTFonts; + std::vector> m_LocalizedTTFonts; private: static const size_t MM_FACE_COUNT = 2; static const size_t FOXIT_FACE_COUNT = 14; - CFX_ByteString GetPSNameFromTT(void* hFont); - CFX_ByteString MatchInstalledFonts(const CFX_ByteString& norm_name); + ByteString GetPSNameFromTT(void* hFont); + ByteString MatchInstalledFonts(const ByteString& norm_name); FXFT_Face UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, @@ -64,23 +63,23 @@ class CFX_FontMapper { uint32_t ttc_size, uint32_t font_size); FXFT_Face GetCachedFace(void* hFont, - CFX_ByteString SubstName, + ByteString SubstName, int weight, bool bItalic, uint32_t font_size); struct FaceData { - CFX_ByteString name; + ByteString name; uint32_t charset; }; bool m_bListLoaded; FXFT_Face m_MMFaces[MM_FACE_COUNT]; - CFX_ByteString m_LastFamily; + ByteString m_LastFamily; std::vector m_FaceArray; std::unique_ptr m_pFontInfo; FXFT_Face m_FoxitFaces[FOXIT_FACE_COUNT]; - CFX_FontMgr* const m_pFontMgr; + UnownedPtr const m_pFontMgr; }; #endif // CORE_FXGE_CFX_FONTMAPPER_H_ diff --git a/core/fxge/cfx_fontmgr.cpp b/core/fxge/cfx_fontmgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2be93eab49e30f21fc3986aacfef6bb84e9f736 --- /dev/null +++ b/core/fxge/cfx_fontmgr.cpp @@ -0,0 +1,252 @@ +// Copyright 2016 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 "core/fxge/cfx_fontmgr.h" + +#include +#include + +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/cttfontdesc.h" +#include "core/fxge/fontdata/chromefontdata/chromefontdata.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/ifx_systemfontinfo.h" +#include "third_party/base/ptr_util.h" + +namespace { + +struct BuiltinFont { + const uint8_t* m_pFontData; + uint32_t m_dwSize; +}; + +const BuiltinFont g_FoxitFonts[14] = { + {g_FoxitFixedFontData, 17597}, + {g_FoxitFixedBoldFontData, 18055}, + {g_FoxitFixedBoldItalicFontData, 19151}, + {g_FoxitFixedItalicFontData, 18746}, + {g_FoxitSansFontData, 15025}, + {g_FoxitSansBoldFontData, 16344}, + {g_FoxitSansBoldItalicFontData, 16418}, + {g_FoxitSansItalicFontData, 16339}, + {g_FoxitSerifFontData, 19469}, + {g_FoxitSerifBoldFontData, 19395}, + {g_FoxitSerifBoldItalicFontData, 20733}, + {g_FoxitSerifItalicFontData, 21227}, + {g_FoxitSymbolFontData, 16729}, + {g_FoxitDingbatsFontData, 29513}, +}; + +const BuiltinFont g_MMFonts[2] = { + {g_FoxitSerifMMFontData, 113417}, + {g_FoxitSansMMFontData, 66919}, +}; + +ByteString KeyNameFromFace(const ByteString& face_name, + int weight, + bool bItalic) { + ByteString key(face_name); + key += ','; + key += ByteString::FormatInteger(weight); + key += bItalic ? 'I' : 'N'; + return key; +} + +ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { + return ByteString::Format("%d:%d", ttc_size, checksum); +} + +int GetTTCIndex(const uint8_t* pFontData, + uint32_t ttc_size, + uint32_t font_offset) { + const uint8_t* p = pFontData + 8; + uint32_t nfont = GET_TT_LONG(p); + uint32_t index; + for (index = 0; index < nfont; index++) { + p = pFontData + 12 + index * 4; + if (GET_TT_LONG(p) == font_offset) + break; + } + return index < nfont ? index : 0; +} + +} // namespace + +CFX_FontMgr::CFX_FontMgr() + : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { + m_pBuiltinMapper = pdfium::MakeUnique(this); +} + +CFX_FontMgr::~CFX_FontMgr() { + // |m_FaceMap| and |m_pBuiltinMapper| reference |m_FTLibrary|, so they must + // be destroyed first. + m_FaceMap.clear(); + m_pBuiltinMapper.reset(); + FXFT_Done_FreeType(m_FTLibrary); +} + +void CFX_FontMgr::InitFTLibrary() { + if (m_FTLibrary) + return; + + FXFT_Init_FreeType(&m_FTLibrary); + m_FTLibrarySupportsHinting = + SetLcdFilterMode() || FreeTypeVersionSupportsHinting(); +} + +void CFX_FontMgr::SetSystemFontInfo( + std::unique_ptr pFontInfo) { + m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); +} + +FXFT_Face CFX_FontMgr::FindSubstFont(const ByteString& face_name, + bool bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int CharsetCP, + CFX_SubstFont* pSubstFont) { + InitFTLibrary(); + return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, + italic_angle, CharsetCP, pSubstFont); +} + +FXFT_Face CFX_FontMgr::GetCachedFace(const ByteString& face_name, + int weight, + bool bItalic, + uint8_t** pFontData) { + auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); + if (it == m_FaceMap.end()) + return nullptr; + + CTTFontDesc* pFontDesc = it->second.get(); + *pFontData = pFontDesc->FontData(); + pFontDesc->AddRef(); + return pFontDesc->SingleFace(); +} + +FXFT_Face CFX_FontMgr::AddCachedFace(const ByteString& face_name, + int weight, + bool bItalic, + uint8_t* pData, + uint32_t size, + int face_index) { + InitFTLibrary(); + + FXFT_Face face = nullptr; + int ret = FXFT_New_Memory_Face(m_FTLibrary, pData, size, face_index, &face); + if (ret) + return nullptr; + + ret = FXFT_Set_Pixel_Sizes(face, 64, 64); + if (ret) + return nullptr; + + auto pFontDesc = pdfium::MakeUnique(pData, face); + CTTFontDesc* pResult = pFontDesc.get(); + m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = std::move(pFontDesc); + return pResult->SingleFace(); +} + +FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, + uint32_t checksum, + int font_offset, + uint8_t** pFontData) { + auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); + if (it == m_FaceMap.end()) + return nullptr; + + CTTFontDesc* pFontDesc = it->second.get(); + *pFontData = pFontDesc->FontData(); + int face_index = GetTTCIndex(pFontDesc->FontData(), ttc_size, font_offset); + if (!pFontDesc->TTCFace(face_index)) { + pFontDesc->SetTTCFace( + face_index, GetFixedFace(pFontDesc->FontData(), ttc_size, face_index)); + } + pFontDesc->AddRef(); + return pFontDesc->TTCFace(face_index); +} + +FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, + uint32_t checksum, + uint8_t* pData, + uint32_t size, + int font_offset) { + int face_index = GetTTCIndex(pData, ttc_size, font_offset); + FXFT_Face face = GetFixedFace(pData, ttc_size, face_index); + auto pFontDesc = pdfium::MakeUnique(pData, face_index, face); + m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = std::move(pFontDesc); + return face; +} + +FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, + uint32_t size, + int face_index) { + InitFTLibrary(); + FXFT_Face face = nullptr; + if (FXFT_New_Memory_Face(m_FTLibrary, pData, size, face_index, &face)) + return nullptr; + return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; +} + +FXFT_Face CFX_FontMgr::GetFileFace(const char* filename, int face_index) { + InitFTLibrary(); + FXFT_Face face = nullptr; + if (FXFT_New_Face(m_FTLibrary, filename, face_index, &face)) + return nullptr; + return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; +} + +void CFX_FontMgr::ReleaseFace(FXFT_Face face) { + if (!face) + return; + bool bNeedFaceDone = true; + for (auto it = m_FaceMap.begin(); it != m_FaceMap.end(); ++it) { + CTTFontDesc::ReleaseStatus nRet = it->second->ReleaseFace(face); + if (nRet == CTTFontDesc::kNotAppropriate) + continue; + bNeedFaceDone = false; + if (nRet == CTTFontDesc::kReleased) + m_FaceMap.erase(it); + break; + } + if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) + FXFT_Done_Face(face); +} + +bool CFX_FontMgr::GetBuiltinFont(size_t index, + const uint8_t** pFontData, + uint32_t* size) { + if (index < FX_ArraySize(g_FoxitFonts)) { + *pFontData = g_FoxitFonts[index].m_pFontData; + *size = g_FoxitFonts[index].m_dwSize; + return true; + } + size_t mm_index = index - FX_ArraySize(g_FoxitFonts); + if (mm_index < FX_ArraySize(g_MMFonts)) { + *pFontData = g_MMFonts[mm_index].m_pFontData; + *size = g_MMFonts[mm_index].m_dwSize; + return true; + } + return false; +} + +bool CFX_FontMgr::FreeTypeVersionSupportsHinting() const { + FT_Int major; + FT_Int minor; + FT_Int patch; + FXFT_Library_Version(m_FTLibrary, &major, &minor, &patch); + // Freetype versions >= 2.8.1 support hinting even if subpixel rendering is + // disabled. https://sourceforge.net/projects/freetype/files/freetype2/2.8.1/ + return major > 2 || (major == 2 && minor > 8) || + (major == 2 && minor == 8 && patch >= 1); +} + +bool CFX_FontMgr::SetLcdFilterMode() const { + return FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != + FT_Err_Unimplemented_Feature; +} diff --git a/core/fxge/cfx_fontmgr.h b/core/fxge/cfx_fontmgr.h index 432f34b38ca1cd6c959c72f7d7d960a6da1c14a7..e53a4ca324e1fa2404d1a99ed0b7dba751c13fd2 100644 --- a/core/fxge/cfx_fontmgr.h +++ b/core/fxge/cfx_fontmgr.h @@ -12,10 +12,10 @@ #include "core/fxge/fx_font.h" -class IFX_SystemFontInfo; class CFX_FontMapper; class CFX_SubstFont; class CTTFontDesc; +class IFX_SystemFontInfo; class CFX_FontMgr { public: @@ -24,11 +24,11 @@ class CFX_FontMgr { void InitFTLibrary(); - FXFT_Face GetCachedFace(const CFX_ByteString& face_name, + FXFT_Face GetCachedFace(const ByteString& face_name, int weight, bool bItalic, - uint8_t*& pFontData); - FXFT_Face AddCachedFace(const CFX_ByteString& face_name, + uint8_t** pFontData); + FXFT_Face AddCachedFace(const ByteString& face_name, int weight, bool bItalic, uint8_t* pData, @@ -37,17 +37,17 @@ class CFX_FontMgr { FXFT_Face GetCachedTTCFace(int ttc_size, uint32_t checksum, int font_offset, - uint8_t*& pFontData); + uint8_t** pFontData); FXFT_Face AddCachedTTCFace(int ttc_size, uint32_t checksum, uint8_t* pData, uint32_t size, int font_offset); - FXFT_Face GetFileFace(const FX_CHAR* filename, int face_index); + FXFT_Face GetFileFace(const char* filename, int face_index); FXFT_Face GetFixedFace(const uint8_t* pData, uint32_t size, int face_index); void ReleaseFace(FXFT_Face face); void SetSystemFontInfo(std::unique_ptr pFontInfo); - FXFT_Face FindSubstFont(const CFX_ByteString& face_name, + FXFT_Face FindSubstFont(const ByteString& face_name, bool bTrueType, uint32_t flags, int weight, @@ -60,8 +60,11 @@ class CFX_FontMgr { bool FTLibrarySupportsHinting() const { return m_FTLibrarySupportsHinting; } private: + bool FreeTypeVersionSupportsHinting() const; + bool SetLcdFilterMode() const; + std::unique_ptr m_pBuiltinMapper; - std::map m_FaceMap; + std::map> m_FaceMap; FXFT_Library m_FTLibrary; bool m_FTLibrarySupportsHinting; }; diff --git a/core/fxge/cfx_fxgedevice.h b/core/fxge/cfx_fxgedevice.h deleted file mode 100644 index 8358e436667a31d73c32c7cfcfc2c77818ff37a0..0000000000000000000000000000000000000000 --- a/core/fxge/cfx_fxgedevice.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 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 CORE_FXGE_CFX_FXGEDEVICE_H_ -#define CORE_FXGE_CFX_FXGEDEVICE_H_ - -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/fx_dib.h" - -class SkPictureRecorder; - -class CFX_FxgeDevice : public CFX_RenderDevice { - public: - CFX_FxgeDevice(); - ~CFX_FxgeDevice() override; - - bool Attach(CFX_DIBitmap* pBitmap, - bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, - bool bGroupKnockout); - bool Create(int width, - int height, - FXDIB_Format format, - CFX_DIBitmap* pOriDevice); - -#ifdef _SKIA_SUPPORT_ - bool AttachRecorder(SkPictureRecorder* recorder); - void Clear(uint32_t color); - SkPictureRecorder* CreateRecorder(int size_x, int size_y); - void DebugVerifyBitmapIsPreMultiplied() const override; - bool SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, - int left, - int top, - int bitmap_alpha, - int blend_type) override; -#endif - - private: - bool m_bOwnedBitmap; -}; - -#endif // CORE_FXGE_CFX_FXGEDEVICE_H_ diff --git a/core/fxge/cfx_gemodule.cpp b/core/fxge/cfx_gemodule.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbc66c3cac7bdb011bd46182d5f113d2ddbd423a --- /dev/null +++ b/core/fxge/cfx_gemodule.cpp @@ -0,0 +1,53 @@ +// Copyright 2016 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 "core/fxge/cfx_gemodule.h" + +#include "core/fxge/cfx_folderfontinfo.h" +#include "core/fxge/cfx_fontcache.h" +#include "core/fxge/cfx_fontmgr.h" +#include "third_party/base/ptr_util.h" + +namespace { + +CFX_GEModule* g_pGEModule = nullptr; + +} // namespace + +CFX_GEModule::CFX_GEModule() + : m_pFontMgr(pdfium::MakeUnique()), + m_pPlatformData(nullptr), + m_pUserFontPaths(nullptr) {} + +CFX_GEModule::~CFX_GEModule() { + DestroyPlatform(); +} + +// static +CFX_GEModule* CFX_GEModule::Get() { + if (!g_pGEModule) + g_pGEModule = new CFX_GEModule(); + return g_pGEModule; +} + +// static +void CFX_GEModule::Destroy() { + ASSERT(g_pGEModule); + delete g_pGEModule; + g_pGEModule = nullptr; +} + +void CFX_GEModule::Init(const char** userFontPaths) { + ASSERT(g_pGEModule); + m_pUserFontPaths = userFontPaths; + InitPlatform(); +} + +CFX_FontCache* CFX_GEModule::GetFontCache() { + if (!m_pFontCache) + m_pFontCache = pdfium::MakeUnique(); + return m_pFontCache.get(); +} diff --git a/core/fxge/cfx_gemodule.h b/core/fxge/cfx_gemodule.h index c5bd84100257c622fc941e24069772eeedbe0cdd..f48d0655612f332c967260bcea160ed263369c84 100644 --- a/core/fxge/cfx_gemodule.h +++ b/core/fxge/cfx_gemodule.h @@ -9,10 +9,6 @@ #include -#include "core/fxge/cfx_fontmgr.h" -#include "core/fxge/fx_font.h" - -class CCodec_ModuleMgr; class CFX_FontCache; class CFX_FontMgr; @@ -21,17 +17,12 @@ class CFX_GEModule { static CFX_GEModule* Get(); static void Destroy(); - void Init(const char** pUserFontPaths, CCodec_ModuleMgr* pCodecModule); + void Init(const char** pUserFontPaths); CFX_FontCache* GetFontCache(); CFX_FontMgr* GetFontMgr() { return m_pFontMgr.get(); } - void SetTextGamma(FX_FLOAT gammaValue); - const uint8_t* GetTextGammaTable() const; - CCodec_ModuleMgr* GetCodecModule() { return m_pCodecModule; } void* GetPlatformData() { return m_pPlatformData; } - FXFT_Library m_FTLibrary; - private: CFX_GEModule(); ~CFX_GEModule(); @@ -39,10 +30,8 @@ class CFX_GEModule { void InitPlatform(); void DestroyPlatform(); - uint8_t m_GammaValue[256]; - CFX_FontCache* m_pFontCache; + std::unique_ptr m_pFontCache; std::unique_ptr m_pFontMgr; - CCodec_ModuleMgr* m_pCodecModule; void* m_pPlatformData; const char** m_pUserFontPaths; }; diff --git a/core/fxge/cfx_graphstate.cpp b/core/fxge/cfx_graphstate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad6b5fc6c7c8fa037fd04c66f48dd69436b665a6 --- /dev/null +++ b/core/fxge/cfx_graphstate.cpp @@ -0,0 +1,61 @@ +// Copyright 2016 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 "core/fxge/cfx_graphstate.h" + +#include "core/fpdfapi/parser/cpdf_array.h" + +CFX_GraphState::CFX_GraphState() {} + +CFX_GraphState::CFX_GraphState(const CFX_GraphState& that) + : m_Ref(that.m_Ref) {} + +CFX_GraphState::~CFX_GraphState() {} + +void CFX_GraphState::Emplace() { + m_Ref.Emplace(); +} + +void CFX_GraphState::SetLineDash(CPDF_Array* pArray, float phase, float scale) { + CFX_GraphStateData* pData = m_Ref.GetPrivateCopy(); + pData->m_DashPhase = phase * scale; + pData->SetDashCount(static_cast(pArray->GetCount())); + for (size_t i = 0; i < pArray->GetCount(); i++) + pData->m_DashArray[i] = pArray->GetNumberAt(i) * scale; +} + +float CFX_GraphState::GetLineWidth() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineWidth : 1.f; +} + +void CFX_GraphState::SetLineWidth(float width) { + m_Ref.GetPrivateCopy()->m_LineWidth = width; +} + +CFX_GraphStateData::LineCap CFX_GraphState::GetLineCap() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineCap + : CFX_GraphStateData::LineCapButt; +} +void CFX_GraphState::SetLineCap(CFX_GraphStateData::LineCap cap) { + m_Ref.GetPrivateCopy()->m_LineCap = cap; +} + +CFX_GraphStateData::LineJoin CFX_GraphState::GetLineJoin() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineJoin + : CFX_GraphStateData::LineJoinMiter; +} + +void CFX_GraphState::SetLineJoin(CFX_GraphStateData::LineJoin join) { + m_Ref.GetPrivateCopy()->m_LineJoin = join; +} + +float CFX_GraphState::GetMiterLimit() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_MiterLimit : 10.f; +} + +void CFX_GraphState::SetMiterLimit(float limit) { + m_Ref.GetPrivateCopy()->m_MiterLimit = limit; +} diff --git a/core/fxge/cfx_graphstate.h b/core/fxge/cfx_graphstate.h index a838dfc17ca6a3acef038be558d915d20e439dd1..bf4fccd47d6226863fb0887afea7a44ff2c22160 100644 --- a/core/fxge/cfx_graphstate.h +++ b/core/fxge/cfx_graphstate.h @@ -7,7 +7,7 @@ #ifndef CORE_FXGE_CFX_GRAPHSTATE_H_ #define CORE_FXGE_CFX_GRAPHSTATE_H_ -#include "core/fxcrt/cfx_shared_copy_on_write.h" +#include "core/fxcrt/shared_copy_on_write.h" #include "core/fxge/cfx_graphstatedata.h" class CPDF_Array; @@ -20,10 +20,10 @@ class CFX_GraphState { void Emplace(); - void SetLineDash(CPDF_Array* pArray, FX_FLOAT phase, FX_FLOAT scale); + void SetLineDash(CPDF_Array* pArray, float phase, float scale); - FX_FLOAT GetLineWidth() const; - void SetLineWidth(FX_FLOAT width); + float GetLineWidth() const; + void SetLineWidth(float width); CFX_GraphStateData::LineCap GetLineCap() const; void SetLineCap(CFX_GraphStateData::LineCap cap); @@ -31,14 +31,14 @@ class CFX_GraphState { CFX_GraphStateData::LineJoin GetLineJoin() const; void SetLineJoin(CFX_GraphStateData::LineJoin join); - FX_FLOAT GetMiterLimit() const; - void SetMiterLimit(FX_FLOAT limit); + float GetMiterLimit() const; + void SetMiterLimit(float limit); // FIXME(tsepez): remove when all GraphStateData usage gone. const CFX_GraphStateData* GetObject() const { return m_Ref.GetObject(); } private: - CFX_SharedCopyOnWrite m_Ref; + SharedCopyOnWrite m_Ref; }; #endif // CORE_FXGE_CFX_GRAPHSTATE_H_ diff --git a/core/fxge/ge/cfx_graphstatedata.cpp b/core/fxge/cfx_graphstatedata.cpp similarity index 87% rename from core/fxge/ge/cfx_graphstatedata.cpp rename to core/fxge/cfx_graphstatedata.cpp index 03798a63200c59324f5aea2abbe35f0f56666310..82fede176a59442036ff686f1948b084be71551c 100644 --- a/core/fxge/ge/cfx_graphstatedata.cpp +++ b/core/fxge/cfx_graphstatedata.cpp @@ -33,8 +33,8 @@ void CFX_GraphStateData::Copy(const CFX_GraphStateData& src) { m_MiterLimit = src.m_MiterLimit; m_LineWidth = src.m_LineWidth; if (m_DashCount) { - m_DashArray = FX_Alloc(FX_FLOAT, m_DashCount); - FXSYS_memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(FX_FLOAT)); + m_DashArray = FX_Alloc(float, m_DashCount); + memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(float)); } } @@ -48,5 +48,5 @@ void CFX_GraphStateData::SetDashCount(int count) { m_DashCount = count; if (count == 0) return; - m_DashArray = FX_Alloc(FX_FLOAT, count); + m_DashArray = FX_Alloc(float, count); } diff --git a/core/fxge/cfx_graphstatedata.h b/core/fxge/cfx_graphstatedata.h index 03e4a8f51a9c5ea227c9f6bd568f1363f2fb13d8..1afff83c1c1bc69d4e9421fc9c0e7ae2946f1be3 100644 --- a/core/fxge/cfx_graphstatedata.h +++ b/core/fxge/cfx_graphstatedata.h @@ -8,22 +8,23 @@ #define CORE_FXGE_CFX_GRAPHSTATEDATA_H_ #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" -class CFX_GraphStateData { +class CFX_GraphStateData : public Retainable { public: enum LineCap { LineCapButt = 0, LineCapRound = 1, LineCapSquare = 2 }; CFX_GraphStateData(); CFX_GraphStateData(const CFX_GraphStateData& src); - ~CFX_GraphStateData(); + ~CFX_GraphStateData() override; void Copy(const CFX_GraphStateData& src); void SetDashCount(int count); LineCap m_LineCap; int m_DashCount; - FX_FLOAT* m_DashArray; - FX_FLOAT m_DashPhase; + float* m_DashArray; + float m_DashPhase; enum LineJoin { LineJoinMiter = 0, @@ -31,8 +32,8 @@ class CFX_GraphStateData { LineJoinBevel = 2, }; LineJoin m_LineJoin; - FX_FLOAT m_MiterLimit; - FX_FLOAT m_LineWidth; + float m_MiterLimit; + float m_LineWidth; }; #endif // CORE_FXGE_CFX_GRAPHSTATEDATA_H_ diff --git a/core/fxge/ge/cfx_pathdata.cpp b/core/fxge/cfx_pathdata.cpp similarity index 77% rename from core/fxge/ge/cfx_pathdata.cpp rename to core/fxge/cfx_pathdata.cpp index 9fa2cd2aacfb74e00cfd2d9a8cb216f2d9cc1acc..4ac5cf6a7a5a392798989a2c300e7e2e33b57d01 100644 --- a/core/fxge/ge/cfx_pathdata.cpp +++ b/core/fxge/cfx_pathdata.cpp @@ -14,70 +14,70 @@ namespace { void UpdateLineEndPoints(CFX_FloatRect* rect, const CFX_PointF& start_pos, const CFX_PointF& end_pos, - FX_FLOAT hw) { + float hw) { if (start_pos.x == end_pos.x) { if (start_pos.y == end_pos.y) { - rect->UpdateRect(end_pos.x + hw, end_pos.y + hw); - rect->UpdateRect(end_pos.x - hw, end_pos.y - hw); + rect->UpdateRect(end_pos + CFX_PointF(hw, hw)); + rect->UpdateRect(end_pos - CFX_PointF(hw, hw)); return; } - FX_FLOAT point_y; + float point_y; if (end_pos.y < start_pos.y) point_y = end_pos.y - hw; else point_y = end_pos.y + hw; - rect->UpdateRect(end_pos.x + hw, point_y); - rect->UpdateRect(end_pos.x - hw, point_y); + rect->UpdateRect(CFX_PointF(end_pos.x + hw, point_y)); + rect->UpdateRect(CFX_PointF(end_pos.x - hw, point_y)); return; } if (start_pos.y == end_pos.y) { - FX_FLOAT point_x; + float point_x; if (end_pos.x < start_pos.x) point_x = end_pos.x - hw; else point_x = end_pos.x + hw; - rect->UpdateRect(point_x, end_pos.y + hw); - rect->UpdateRect(point_x, end_pos.y - hw); + rect->UpdateRect(CFX_PointF(point_x, end_pos.y + hw)); + rect->UpdateRect(CFX_PointF(point_x, end_pos.y - hw)); return; } CFX_PointF diff = end_pos - start_pos; - FX_FLOAT ll = FXSYS_sqrt2(diff.x, diff.y); - FX_FLOAT mx = end_pos.x + hw * diff.x / ll; - FX_FLOAT my = end_pos.y + hw * diff.y / ll; - FX_FLOAT dx1 = hw * diff.y / ll; - FX_FLOAT dy1 = hw * diff.x / ll; - rect->UpdateRect(mx - dx1, my + dy1); - rect->UpdateRect(mx + dx1, my - dy1); + float ll = FXSYS_sqrt2(diff.x, diff.y); + float mx = end_pos.x + hw * diff.x / ll; + float my = end_pos.y + hw * diff.y / ll; + float dx1 = hw * diff.y / ll; + float dy1 = hw * diff.x / ll; + rect->UpdateRect(CFX_PointF(mx - dx1, my + dy1)); + rect->UpdateRect(CFX_PointF(mx + dx1, my - dy1)); } void UpdateLineJoinPoints(CFX_FloatRect* rect, const CFX_PointF& start_pos, const CFX_PointF& mid_pos, const CFX_PointF& end_pos, - FX_FLOAT half_width, - FX_FLOAT miter_limit) { - FX_FLOAT start_k = 0; - FX_FLOAT start_c = 0; - FX_FLOAT end_k = 0; - FX_FLOAT end_c = 0; - FX_FLOAT start_len = 0; - FX_FLOAT start_dc = 0; - FX_FLOAT end_len = 0; - FX_FLOAT end_dc = 0; - FX_FLOAT one_twentieth = 1.0f / 20; - - bool bStartVert = FXSYS_fabs(start_pos.x - mid_pos.x) < one_twentieth; - bool bEndVert = FXSYS_fabs(mid_pos.x - end_pos.x) < one_twentieth; + float half_width, + float miter_limit) { + float start_k = 0; + float start_c = 0; + float end_k = 0; + float end_c = 0; + float start_len = 0; + float start_dc = 0; + float end_len = 0; + float end_dc = 0; + float one_twentieth = 1.0f / 20; + + bool bStartVert = fabs(start_pos.x - mid_pos.x) < one_twentieth; + bool bEndVert = fabs(mid_pos.x - end_pos.x) < one_twentieth; if (bStartVert && bEndVert) { int start_dir = mid_pos.y > start_pos.y ? 1 : -1; - FX_FLOAT point_y = mid_pos.y + half_width * start_dir; - rect->UpdateRect(mid_pos.x + half_width, point_y); - rect->UpdateRect(mid_pos.x - half_width, point_y); + float point_y = mid_pos.y + half_width * start_dir; + rect->UpdateRect(CFX_PointF(mid_pos.x + half_width, point_y)); + rect->UpdateRect(CFX_PointF(mid_pos.x - half_width, point_y)); return; } @@ -86,16 +86,15 @@ void UpdateLineJoinPoints(CFX_FloatRect* rect, start_k = (mid_pos.y - start_pos.y) / (mid_pos.x - start_pos.x); start_c = mid_pos.y - (start_k * mid_pos.x); start_len = FXSYS_sqrt2(start_to_mid.x, start_to_mid.y); - start_dc = static_cast( - FXSYS_fabs(half_width * start_len / start_to_mid.x)); + start_dc = + static_cast(fabs(half_width * start_len / start_to_mid.x)); } if (!bEndVert) { CFX_PointF end_to_mid = end_pos - mid_pos; end_k = end_to_mid.y / end_to_mid.x; end_c = mid_pos.y - (end_k * mid_pos.x); end_len = FXSYS_sqrt2(end_to_mid.x, end_to_mid.y); - end_dc = - static_cast(FXSYS_fabs(half_width * end_len / end_to_mid.x)); + end_dc = static_cast(fabs(half_width * end_len / end_to_mid.x)); } if (bStartVert) { CFX_PointF outside(start_pos.x, 0); @@ -109,7 +108,7 @@ void UpdateLineJoinPoints(CFX_FloatRect* rect, else outside.y = (end_k * outside.x) + end_c - end_dc; - rect->UpdateRect(outside.x, outside.y); + rect->UpdateRect(outside); return; } @@ -125,11 +124,11 @@ void UpdateLineJoinPoints(CFX_FloatRect* rect, else outside.y = (start_k * outside.x) + start_c - start_dc; - rect->UpdateRect(outside.x, outside.y); + rect->UpdateRect(outside); return; } - if (FXSYS_fabs(start_k - end_k) < one_twentieth) { + if (fabs(start_k - end_k) < one_twentieth) { int start_dir = mid_pos.x > start_pos.x ? 1 : -1; int end_dir = end_pos.x > mid_pos.x ? 1 : -1; if (start_dir == end_dir) @@ -139,21 +138,21 @@ void UpdateLineJoinPoints(CFX_FloatRect* rect, return; } - FX_FLOAT start_outside_c = start_c; + float start_outside_c = start_c; if (end_pos.y < (start_k * end_pos.x) + start_c) start_outside_c += start_dc; else start_outside_c -= start_dc; - FX_FLOAT end_outside_c = end_c; + float end_outside_c = end_c; if (start_pos.y < (end_k * start_pos.x) + end_c) end_outside_c += end_dc; else end_outside_c -= end_dc; - FX_FLOAT join_x = (end_outside_c - start_outside_c) / (start_k - end_k); - FX_FLOAT join_y = start_k * join_x + start_outside_c; - rect->UpdateRect(join_x, join_y); + float join_x = (end_outside_c - start_outside_c) / (start_k - end_k); + float join_y = start_k * join_x + start_outside_c; + rect->UpdateRect(CFX_PointF(join_x, join_y)); } } // namespace @@ -203,20 +202,28 @@ void CFX_PathData::AppendPoint(const CFX_PointF& point, m_Points.push_back(FX_PATHPOINT(point, type, closeFigure)); } -void CFX_PathData::AppendRect(FX_FLOAT left, - FX_FLOAT bottom, - FX_FLOAT right, - FX_FLOAT top) { - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(left, bottom), FXPT_TYPE::MoveTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(left, top), FXPT_TYPE::LineTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(right, top), FXPT_TYPE::LineTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(right, bottom), FXPT_TYPE::LineTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(left, bottom), FXPT_TYPE::LineTo, true)); +void CFX_PathData::AppendLine(const CFX_PointF& pt1, const CFX_PointF& pt2) { + if (m_Points.empty() || fabs(m_Points.back().m_Point.x - pt1.x) > 0.001 || + fabs(m_Points.back().m_Point.y - pt1.y) > 0.001) { + AppendPoint(pt1, FXPT_TYPE::MoveTo, false); + } + AppendPoint(pt2, FXPT_TYPE::LineTo, false); +} + +void CFX_PathData::AppendRect(float left, + float bottom, + float right, + float top) { + CFX_PointF left_bottom(left, bottom); + CFX_PointF left_top(left, top); + CFX_PointF right_top(right, top); + CFX_PointF right_bottom(right, bottom); + + AppendLine(left_bottom, left_top); + AppendLine(left_top, right_top); + AppendLine(right_top, right_bottom); + AppendLine(right_bottom, left_bottom); + ClosePath(); } CFX_FloatRect CFX_PathData::GetBoundingBox() const { @@ -224,31 +231,33 @@ CFX_FloatRect CFX_PathData::GetBoundingBox() const { return CFX_FloatRect(); CFX_FloatRect rect; - rect.InitRect(m_Points[0].m_Point.x, m_Points[0].m_Point.y); + rect.InitRect(m_Points[0].m_Point); for (size_t i = 1; i < m_Points.size(); i++) - rect.UpdateRect(m_Points[i].m_Point.x, m_Points[i].m_Point.y); + rect.UpdateRect(m_Points[i].m_Point); return rect; } -CFX_FloatRect CFX_PathData::GetBoundingBox(FX_FLOAT line_width, - FX_FLOAT miter_limit) const { +CFX_FloatRect CFX_PathData::GetBoundingBox(float line_width, + float miter_limit) const { CFX_FloatRect rect(100000.0f, 100000.0f, -100000.0f, -100000.0f); size_t iPoint = 0; - FX_FLOAT half_width = line_width; + float half_width = line_width; int iStartPoint = 0; int iEndPoint = 0; int iMiddlePoint = 0; bool bJoin; while (iPoint < m_Points.size()) { if (m_Points[iPoint].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { + if (iPoint + 1 == m_Points.size()) + break; + iStartPoint = iPoint + 1; iEndPoint = iPoint; bJoin = false; } else { if (m_Points[iPoint].IsTypeAndOpen(FXPT_TYPE::BezierTo)) { - rect.UpdateRect(m_Points[iPoint].m_Point.x, m_Points[iPoint].m_Point.y); - rect.UpdateRect(m_Points[iPoint + 1].m_Point.x, - m_Points[iPoint + 1].m_Point.y); + rect.UpdateRect(m_Points[iPoint].m_Point); + rect.UpdateRect(m_Points[iPoint + 1].m_Point); iPoint += 2; } if (iPoint == m_Points.size() - 1 || @@ -344,14 +353,14 @@ bool CFX_PathData::GetZeroAreaPath(const CFX_Matrix* pMatrix, } } - int stratPoint = 0; + int startPoint = 0; int next = 0; for (size_t i = 0; i < m_Points.size(); i++) { FXPT_TYPE point_type = m_Points[i].m_Type; if (point_type == FXPT_TYPE::MoveTo) { - stratPoint = i; + startPoint = i; } else if (point_type == FXPT_TYPE::LineTo) { - next = (i + 1 - stratPoint) % (m_Points.size() - stratPoint) + stratPoint; + next = (i + 1 - startPoint) % (m_Points.size() - startPoint) + startPoint; if (m_Points[next].m_Type != FXPT_TYPE::BezierTo && m_Points[next].m_Type != FXPT_TYPE::MoveTo) { if ((m_Points[i - 1].m_Point.x == m_Points[i].m_Point.x && @@ -360,8 +369,8 @@ bool CFX_PathData::GetZeroAreaPath(const CFX_Matrix* pMatrix, (m_Points[i].m_Point.y - m_Points[next].m_Point.y) > 0)) { int pre = i; - if (FXSYS_fabs(m_Points[i].m_Point.y - m_Points[i - 1].m_Point.y) < - FXSYS_fabs(m_Points[i].m_Point.y - m_Points[next].m_Point.y)) { + if (fabs(m_Points[i].m_Point.y - m_Points[i - 1].m_Point.y) < + fabs(m_Points[i].m_Point.y - m_Points[next].m_Point.y)) { pre--; next--; } @@ -375,8 +384,8 @@ bool CFX_PathData::GetZeroAreaPath(const CFX_Matrix* pMatrix, (m_Points[i].m_Point.x - m_Points[next].m_Point.x) > 0)) { int pre = i; - if (FXSYS_fabs(m_Points[i].m_Point.x - m_Points[i - 1].m_Point.x) < - FXSYS_fabs(m_Points[i].m_Point.x - m_Points[next].m_Point.x)) { + if (fabs(m_Points[i].m_Point.x - m_Points[i - 1].m_Point.x) < + fabs(m_Points[i].m_Point.x - m_Points[next].m_Point.x)) { pre--; next--; } diff --git a/core/fxge/cfx_pathdata.h b/core/fxge/cfx_pathdata.h index b0e30e32ad7fb8ede81cf34d05ff95ea3dd8efce..d346ba066603c3ee7b138ce9a75d48c150c0ae0f 100644 --- a/core/fxge/cfx_pathdata.h +++ b/core/fxge/cfx_pathdata.h @@ -29,11 +29,11 @@ class FX_PATHPOINT { bool m_CloseFigure; }; -class CFX_PathData { +class CFX_PathData : public Retainable { public: CFX_PathData(); CFX_PathData(const CFX_PathData& src); - ~CFX_PathData(); + ~CFX_PathData() override; void Clear(); @@ -47,7 +47,7 @@ class CFX_PathData { std::vector& GetPoints() { return m_Points; } CFX_FloatRect GetBoundingBox() const; - CFX_FloatRect GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const; + CFX_FloatRect GetBoundingBox(float line_width, float miter_limit) const; void Transform(const CFX_Matrix* pMatrix); bool IsRect() const; @@ -59,7 +59,8 @@ class CFX_PathData { bool IsRect(const CFX_Matrix* pMatrix, CFX_FloatRect* rect) const; void Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix); - void AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top); + void AppendRect(float left, float bottom, float right, float top); + void AppendLine(const CFX_PointF& pt1, const CFX_PointF& pt2); void AppendPoint(const CFX_PointF& pos, FXPT_TYPE type, bool closeFigure); void ClosePath(); diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp new file mode 100644 index 0000000000000000000000000000000000000000..919a7a98a7cd2ebdc9e35ff51f155709d6bcd3e0 --- /dev/null +++ b/core/fxge/cfx_renderdevice.cpp @@ -0,0 +1,1364 @@ +// Copyright 2016 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 "core/fxge/cfx_renderdevice.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_facecache.h" +#include "core/fxge/cfx_font.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/ifx_renderdevicedriver.h" + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +#include "third_party/skia/include/core/SkTypes.h" +#endif + +namespace { + +void AdjustGlyphSpace(std::vector* pGlyphAndPos) { + ASSERT(pGlyphAndPos->size() > 1); + std::vector& glyphs = *pGlyphAndPos; + bool bVertical = glyphs.back().m_Origin.x == glyphs.front().m_Origin.x; + if (!bVertical && (glyphs.back().m_Origin.y != glyphs.front().m_Origin.y)) + return; + + for (size_t i = glyphs.size() - 1; i > 1; --i) { + FXTEXT_GLYPHPOS& next = glyphs[i]; + int next_origin = bVertical ? next.m_Origin.y : next.m_Origin.x; + float next_origin_f = bVertical ? next.m_fOrigin.y : next.m_fOrigin.x; + + FXTEXT_GLYPHPOS& current = glyphs[i - 1]; + int& current_origin = bVertical ? current.m_Origin.y : current.m_Origin.x; + float current_origin_f = + bVertical ? current.m_fOrigin.y : current.m_fOrigin.x; + + int space = next_origin - current_origin; + float space_f = next_origin_f - current_origin_f; + float error = fabs(space_f) - fabs(static_cast(space)); + if (error > 0.5f) + current_origin += space > 0 ? -1 : 1; + } +} + +const uint8_t g_TextGammaAdjust[256] = { + 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, + 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, + 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, + 255, +}; + +int TextGammaAdjust(int value) { + ASSERT(value >= 0); + ASSERT(value <= 255); + return g_TextGammaAdjust[value]; +} + +int CalcAlpha(int src, int alpha) { + return src * alpha / 255; +} + +void Merge(uint8_t src, int channel, int alpha, uint8_t* dest) { + *dest = FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(src, alpha)); +} + +void MergeGammaAdjust(uint8_t src, int channel, int alpha, uint8_t* dest) { + *dest = + FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(TextGammaAdjust(src), alpha)); +} + +void MergeGammaAdjustBgr(const uint8_t* src, + int r, + int g, + int b, + int a, + uint8_t* dest) { + MergeGammaAdjust(src[0], b, a, &dest[0]); + MergeGammaAdjust(src[1], g, a, &dest[1]); + MergeGammaAdjust(src[2], r, a, &dest[2]); +} + +void MergeGammaAdjustRgb(const uint8_t* src, + int r, + int g, + int b, + int a, + uint8_t* dest) { + MergeGammaAdjust(src[2], b, a, &dest[0]); + MergeGammaAdjust(src[1], g, a, &dest[1]); + MergeGammaAdjust(src[0], r, a, &dest[2]); +} + +int AverageRgb(const uint8_t* src) { + return (src[0] + src[1] + src[2]) / 3; +} + +uint8_t CalculateDestAlpha(uint8_t back_alpha, int src_alpha) { + return back_alpha + src_alpha - back_alpha * src_alpha / 255; +} + +void ApplyAlpha(uint8_t* dest, int b, int g, int r, int alpha) { + dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, alpha); + dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, alpha); + dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, alpha); +} + +void ApplyDestAlpha(uint8_t back_alpha, + int src_alpha, + int r, + int g, + int b, + uint8_t* dest) { + uint8_t dest_alpha = CalculateDestAlpha(back_alpha, src_alpha); + ApplyAlpha(dest, b, g, r, src_alpha * 255 / dest_alpha); + dest[3] = dest_alpha; +} + +void NormalizeArgb(int src_value, + int r, + int g, + int b, + int a, + uint8_t* dest, + int src_alpha) { + uint8_t back_alpha = dest[3]; + if (back_alpha == 0) + FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); + else if (src_alpha != 0) + ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); +} + +void NormalizeDest(bool has_alpha, + int src_value, + int r, + int g, + int b, + int a, + uint8_t* dest) { + if (has_alpha) { + NormalizeArgb(src_value, r, g, b, a, dest, + CalcAlpha(TextGammaAdjust(src_value), a)); + return; + } + int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); + if (src_alpha == 0) + return; + + ApplyAlpha(dest, b, g, r, src_alpha); +} + +void NormalizeSrc(bool has_alpha, + int src_value, + int r, + int g, + int b, + int a, + uint8_t* dest) { + if (!has_alpha) { + ApplyAlpha(dest, b, g, r, CalcAlpha(TextGammaAdjust(src_value), a)); + return; + } + int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); + if (src_alpha != 0) + NormalizeArgb(src_value, r, g, b, a, dest, src_alpha); +} + +void NextPixel(uint8_t** src_scan, uint8_t** dst_scan, int bpp) { + *src_scan += 3; + *dst_scan += bpp; +} + +void SetAlpha(bool has_alpha, uint8_t* alpha) { + if (has_alpha) + alpha[3] = 255; +} + +void DrawNormalTextHelper(const RetainPtr& bitmap, + const RetainPtr& pGlyph, + int nrows, + int left, + int top, + int start_col, + int end_col, + bool bNormal, + bool bBGRStripe, + int x_subpixel, + int a, + int r, + int g, + int b) { + const bool has_alpha = bitmap->GetFormat() == FXDIB_Argb; + uint8_t* src_buf = pGlyph->GetBuffer(); + int src_pitch = pGlyph->GetPitch(); + uint8_t* dest_buf = bitmap->GetBuffer(); + int dest_pitch = bitmap->GetPitch(); + const int Bpp = has_alpha ? 4 : bitmap->GetBPP() / 8; + for (int row = 0; row < nrows; ++row) { + int dest_row = row + top; + if (dest_row < 0 || dest_row >= bitmap->GetHeight()) + continue; + + uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; + uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; + if (bBGRStripe) { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; ++col) { + if (has_alpha) { + Merge(src_scan[2], r, a, &dest_scan[2]); + Merge(src_scan[1], g, a, &dest_scan[1]); + Merge(src_scan[0], b, a, &dest_scan[0]); + } else { + MergeGammaAdjustBgr(&src_scan[0], r, g, b, a, &dest_scan[0]); + } + SetAlpha(has_alpha, dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + } + continue; + } + if (x_subpixel == 1) { + MergeGammaAdjust(src_scan[1], r, a, &dest_scan[2]); + MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); + if (start_col > left) + MergeGammaAdjust(src_scan[-1], b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col - 1; ++col) { + MergeGammaAdjustBgr(&src_scan[-1], r, g, b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + } + continue; + } + MergeGammaAdjust(src_scan[0], r, a, &dest_scan[2]); + if (start_col > left) { + MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); + MergeGammaAdjust(src_scan[-2], b, a, &dest_scan[0]); + } + SetAlpha(has_alpha, dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col - 1; ++col) { + MergeGammaAdjustBgr(&src_scan[-2], r, g, b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + } + continue; + } + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; ++col) { + if (bNormal) { + int src_value = AverageRgb(&src_scan[0]); + NormalizeDest(has_alpha, src_value, r, g, b, a, dest_scan); + } else { + MergeGammaAdjustRgb(&src_scan[0], r, g, b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + } + continue; + } + if (x_subpixel == 1) { + if (bNormal) { + int src_value = start_col > left ? AverageRgb(&src_scan[-1]) + : (src_scan[0] + src_scan[1]) / 3; + NormalizeSrc(has_alpha, src_value, r, g, b, a, dest_scan); + } else { + if (start_col > left) + MergeGammaAdjust(src_scan[-1], r, a, &dest_scan[2]); + MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); + MergeGammaAdjust(src_scan[1], b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col; ++col) { + if (bNormal) { + int src_value = AverageRgb(&src_scan[-1]); + NormalizeDest(has_alpha, src_value, r, g, b, a, dest_scan); + } else { + MergeGammaAdjustRgb(&src_scan[-1], r, g, b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + } + continue; + } + if (bNormal) { + int src_value = + start_col > left ? AverageRgb(&src_scan[-2]) : src_scan[0] / 3; + NormalizeSrc(has_alpha, src_value, r, g, b, a, dest_scan); + } else { + if (start_col > left) { + MergeGammaAdjust(src_scan[-2], r, a, &dest_scan[2]); + MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); + } + MergeGammaAdjust(src_scan[0], b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col; ++col) { + if (bNormal) { + int src_value = AverageRgb(&src_scan[-2]); + NormalizeDest(has_alpha, src_value, r, g, b, a, dest_scan); + } else { + MergeGammaAdjustRgb(&src_scan[-2], r, g, b, a, &dest_scan[0]); + SetAlpha(has_alpha, dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + } + } +} + +bool ShouldDrawDeviceText(const CFX_Font* pFont, uint32_t text_flags) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + if (text_flags & FXFONT_CIDFONT) + return false; + + const ByteString bsPsName = pFont->GetPsName(); + if (bsPsName.Contains("+ZJHL")) + return false; + + if (bsPsName == "CNAAJI+cmex10") + return false; +#endif + return true; +} + +} // namespace + +FXTEXT_CHARPOS::FXTEXT_CHARPOS() + : m_Unicode(0), + m_GlyphIndex(0), + m_FontCharWidth(0), +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + m_ExtGID(0), +#endif + m_FallbackFontPosition(0), + m_bGlyphAdjust(false), + m_bFontStyle(false) { +} + +FXTEXT_CHARPOS::FXTEXT_CHARPOS(const FXTEXT_CHARPOS&) = default; + +FXTEXT_CHARPOS::~FXTEXT_CHARPOS(){}; + +CFX_RenderDevice::CFX_RenderDevice() + : m_pBitmap(nullptr), + m_Width(0), + m_Height(0), + m_bpp(0), + m_RenderCaps(0), + m_DeviceClass(0) {} + +CFX_RenderDevice::~CFX_RenderDevice() { + RestoreState(false); +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ + Flush(true); +#endif +} + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +void CFX_RenderDevice::Flush(bool release) { + if (release) + m_pDeviceDriver.reset(); + else + m_pDeviceDriver->Flush(); +} +#endif + +void CFX_RenderDevice::SetDeviceDriver( + std::unique_ptr pDriver) { + m_pDeviceDriver = std::move(pDriver); + InitDeviceInfo(); +} + +void CFX_RenderDevice::InitDeviceInfo() { + m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); + m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); + m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); + m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); + m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); + if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { + m_ClipBox.left = 0; + m_ClipBox.top = 0; + m_ClipBox.right = m_Width; + m_ClipBox.bottom = m_Height; + } +} + +void CFX_RenderDevice::SaveState() { + m_pDeviceDriver->SaveState(); +} + +void CFX_RenderDevice::RestoreState(bool bKeepSaved) { + if (m_pDeviceDriver) { + m_pDeviceDriver->RestoreState(bKeepSaved); + UpdateClipBox(); + } +} + +int CFX_RenderDevice::GetDeviceCaps(int caps_id) const { + return m_pDeviceDriver->GetDeviceCaps(caps_id); +} + +CFX_Matrix CFX_RenderDevice::GetCTM() const { + return m_pDeviceDriver->GetCTM(); +} + +RetainPtr CFX_RenderDevice::GetBitmap() const { + return m_pBitmap; +} + +void CFX_RenderDevice::SetBitmap(const RetainPtr& pBitmap) { + m_pBitmap = pBitmap; +} + +bool CFX_RenderDevice::CreateCompatibleBitmap( + const RetainPtr& pDIB, + int width, + int height) const { + if (m_RenderCaps & FXRC_CMYK_OUTPUT) { + return pDIB->Create( + width, height, + m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Cmyka : FXDIB_Cmyk); + } + if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) + return pDIB->Create(width, height, FXDIB_8bppMask); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_PATHS_ + return pDIB->Create( + width, height, + m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb32); +#else + return pDIB->Create( + width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); +#endif +} + +bool CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + int fill_mode) { + if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, + fill_mode)) { + return false; + } + UpdateClipBox(); + return true; +} + +bool CFX_RenderDevice::SetClip_PathStroke( + const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState) { + if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, + pGraphState)) { + return false; + } + UpdateClipBox(); + return true; +} + +bool CFX_RenderDevice::SetClip_Rect(const CFX_RectF& rtClip) { + return SetClip_Rect(FX_RECT(static_cast(floor(rtClip.left)), + static_cast(floor(rtClip.top)), + static_cast(ceil(rtClip.right())), + static_cast(ceil(rtClip.bottom())))); +} + +bool CFX_RenderDevice::SetClip_Rect(const FX_RECT& rect) { + CFX_PathData path; + path.AppendRect(rect.left, rect.bottom, rect.right, rect.top); + if (!SetClip_PathFill(&path, nullptr, FXFILL_WINDING)) + return false; + + UpdateClipBox(); + return true; +} + +void CFX_RenderDevice::UpdateClipBox() { + if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) + return; + m_ClipBox.left = 0; + m_ClipBox.top = 0; + m_ClipBox.right = m_Width; + m_ClipBox.bottom = m_Height; +} + +bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + uint32_t stroke_color, + int fill_mode, + int blend_type) { + uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0; + uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0; + const std::vector& pPoints = pPathData->GetPoints(); + if (stroke_alpha == 0 && pPoints.size() == 2) { + CFX_PointF pos1 = pPoints[0].m_Point; + CFX_PointF pos2 = pPoints[1].m_Point; + if (pObject2Device) { + pos1 = pObject2Device->Transform(pos1); + pos2 = pObject2Device->Transform(pos2); + } + DrawCosmeticLine(pos1, pos2, fill_color, fill_mode, blend_type); + return true; + } + + if ((pPoints.size() == 5 || pPoints.size() == 4) && stroke_alpha == 0) { + CFX_FloatRect rect_f; + if (!(fill_mode & FXFILL_RECT_AA) && + pPathData->IsRect(pObject2Device, &rect_f)) { + FX_RECT rect_i = rect_f.GetOuterRect(); + + // Depending on the top/bottom, left/right values of the rect it's + // possible to overflow the Width() and Height() calculations. Check that + // the rect will have valid dimension before continuing. + if (!rect_i.Valid()) + return false; + + int width = static_cast(ceil(rect_f.right - rect_f.left)); + if (width < 1) { + width = 1; + if (rect_i.left == rect_i.right) + ++rect_i.right; + } + int height = static_cast(ceil(rect_f.top - rect_f.bottom)); + if (height < 1) { + height = 1; + if (rect_i.bottom == rect_i.top) + ++rect_i.bottom; + } + if (rect_i.Width() >= width + 1) { + if (rect_f.left - static_cast(rect_i.left) > + static_cast(rect_i.right) - rect_f.right) { + ++rect_i.left; + } else { + --rect_i.right; + } + } + if (rect_i.Height() >= height + 1) { + if (rect_f.top - static_cast(rect_i.top) > + static_cast(rect_i.bottom) - rect_f.bottom) { + ++rect_i.top; + } else { + --rect_i.bottom; + } + } + if (FillRectWithBlend(&rect_i, fill_color, blend_type)) + return true; + } + } + if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && + !(fill_mode & FX_FILL_TEXT_MODE)) { + CFX_PathData newPath; + bool bThin = false; + bool setIdentity = false; + if (pPathData->GetZeroAreaPath(pObject2Device, + !!m_pDeviceDriver->GetDriverType(), &newPath, + &bThin, &setIdentity)) { + CFX_GraphStateData graphState; + graphState.m_LineWidth = 0.0f; + + uint32_t strokecolor = fill_color; + if (bThin) + strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); + + const CFX_Matrix* pMatrix = nullptr; + if (pObject2Device && !pObject2Device->IsIdentity() && !setIdentity) + pMatrix = pObject2Device; + + int smooth_path = FX_ZEROAREA_FILL; + if (fill_mode & FXFILL_NOPATHSMOOTH) + smooth_path |= FXFILL_NOPATHSMOOTH; + + m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, + smooth_path, blend_type); + } + } + if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && + (fill_mode & FX_FILL_STROKE)) { + if (m_RenderCaps & FXRC_FILLSTROKE_PATH) { + return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, + blend_type); + } + return DrawFillStrokePath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, blend_type); + } + return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, + blend_type); +} + +// This can be removed once PDFium entirely relies on Skia +bool CFX_RenderDevice::DrawFillStrokePath(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + uint32_t stroke_color, + int fill_mode, + int blend_type) { + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + CFX_FloatRect bbox; + if (pGraphState) { + bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, + pGraphState->m_MiterLimit); + } else { + bbox = pPathData->GetBoundingBox(); + } + if (pObject2Device) + bbox = pObject2Device->TransformRect(bbox); + + CFX_Matrix ctm = GetCTM(); + float fScaleX = fabs(ctm.a); + float fScaleY = fabs(ctm.d); + FX_RECT rect = bbox.GetOuterRect(); + auto bitmap = pdfium::MakeRetain(); + auto Backdrop = pdfium::MakeRetain(); + if (!CreateCompatibleBitmap(bitmap, FXSYS_round(rect.Width() * fScaleX), + FXSYS_round(rect.Height() * fScaleY))) { + return false; + } + if (bitmap->HasAlpha()) { + bitmap->Clear(0); + Backdrop->Copy(bitmap); + } else { + if (!m_pDeviceDriver->GetDIBits(bitmap, rect.left, rect.top)) + return false; + Backdrop->Copy(bitmap); + } + CFX_DefaultRenderDevice bitmap_device; + bitmap_device.Attach(bitmap, false, Backdrop, true); + + CFX_Matrix matrix; + if (pObject2Device) + matrix = *pObject2Device; + matrix.Translate(-rect.left, -rect.top); + matrix.Concat(CFX_Matrix(fScaleX, 0, 0, fScaleY, 0, 0)); + if (!bitmap_device.GetDeviceDriver()->DrawPath( + pPathData, &matrix, pGraphState, fill_color, stroke_color, fill_mode, + blend_type)) { + return false; + } +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ + bitmap_device.GetDeviceDriver()->Flush(); +#endif + FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), + FXSYS_round(rect.Height() * fScaleY)); + return m_pDeviceDriver->SetDIBits(bitmap, 0, &src_rect, rect.left, rect.top, + FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::FillRectWithBlend(const FX_RECT* pRect, + uint32_t fill_color, + int blend_type) { + if (m_pDeviceDriver->FillRectWithBlend(pRect, fill_color, blend_type)) + return true; + + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + + auto bitmap = pdfium::MakeRetain(); + if (!CreateCompatibleBitmap(bitmap, pRect->Width(), pRect->Height())) + return false; + + if (!m_pDeviceDriver->GetDIBits(bitmap, pRect->left, pRect->top)) + return false; + + if (!bitmap->CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, + 0)) { + return false; + } + FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); + m_pDeviceDriver->SetDIBits(bitmap, 0, &src_rect, pRect->left, pRect->top, + FXDIB_BLEND_NORMAL); + return true; +} + +bool CFX_RenderDevice::DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, + uint32_t color, + int fill_mode, + int blend_type) { + if ((color >= 0xff000000) && m_pDeviceDriver->DrawCosmeticLine( + ptMoveTo, ptLineTo, color, blend_type)) { + return true; + } + CFX_GraphStateData graph_state; + CFX_PathData path; + path.AppendPoint(ptMoveTo, FXPT_TYPE::MoveTo, false); + path.AppendPoint(ptLineTo, FXPT_TYPE::LineTo, false); + return m_pDeviceDriver->DrawPath(&path, nullptr, &graph_state, 0, color, + fill_mode, blend_type); +} + +bool CFX_RenderDevice::GetDIBits(const RetainPtr& pBitmap, + int left, + int top) { + return (m_RenderCaps & FXRC_GET_BITS) && + m_pDeviceDriver->GetDIBits(pBitmap, left, top); +} + +RetainPtr CFX_RenderDevice::GetBackDrop() { + return m_pDeviceDriver->GetBackDrop(); +} + +bool CFX_RenderDevice::SetDIBitsWithBlend( + const RetainPtr& pBitmap, + int left, + int top, + int blend_mode) { + ASSERT(!pBitmap->IsAlphaMask()); + CFX_Matrix ctm = GetCTM(); + float fScaleX = fabs(ctm.a); + float fScaleY = fabs(ctm.d); + FX_RECT dest_rect(left, top, + FXSYS_round(left + pBitmap->GetWidth() / fScaleX), + FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); + dest_rect.Intersect(m_ClipBox); + if (dest_rect.IsEmpty()) + return true; + + FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, + dest_rect.left - left + dest_rect.Width(), + dest_rect.top - top + dest_rect.Height()); + src_rect.left = FXSYS_round(src_rect.left * fScaleX); + src_rect.top = FXSYS_round(src_rect.top * fScaleY); + src_rect.right = FXSYS_round(src_rect.right * fScaleX); + src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); + if ((blend_mode == FXDIB_BLEND_NORMAL || (m_RenderCaps & FXRC_BLEND_MODE)) && + (!pBitmap->HasAlpha() || (m_RenderCaps & FXRC_ALPHA_IMAGE))) { + return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, + dest_rect.top, blend_mode); + } + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + + int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); + int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); + auto background = pdfium::MakeRetain(); + if (!background->Create( + bg_pixel_width, bg_pixel_height, + (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { + return false; + } + if (!m_pDeviceDriver->GetDIBits(background, dest_rect.left, dest_rect.top)) { + return false; + } + if (!background->CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, + pBitmap, src_rect.left, src_rect.top, + blend_mode, nullptr, false)) { + return false; + } + FX_RECT rect(0, 0, bg_pixel_width, bg_pixel_height); + return m_pDeviceDriver->SetDIBits(background, 0, &rect, dest_rect.left, + dest_rect.top, FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::StretchDIBitsWithFlagsAndBlend( + const RetainPtr& pBitmap, + int left, + int top, + int dest_width, + int dest_height, + uint32_t flags, + int blend_mode) { + FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); + FX_RECT clip_box = m_ClipBox; + clip_box.Intersect(dest_rect); + return clip_box.IsEmpty() || m_pDeviceDriver->StretchDIBits( + pBitmap, 0, left, top, dest_width, + dest_height, &clip_box, flags, blend_mode); +} + +bool CFX_RenderDevice::SetBitMask(const RetainPtr& pBitmap, + int left, + int top, + uint32_t argb) { + FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); + return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, + FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::StretchBitMask(const RetainPtr& pBitmap, + int left, + int top, + int dest_width, + int dest_height, + uint32_t color) { + return StretchBitMaskWithFlags(pBitmap, left, top, dest_width, dest_height, + color, 0); +} + +bool CFX_RenderDevice::StretchBitMaskWithFlags( + const RetainPtr& pBitmap, + int left, + int top, + int dest_width, + int dest_height, + uint32_t argb, + uint32_t flags) { + FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); + FX_RECT clip_box = m_ClipBox; + clip_box.Intersect(dest_rect); + return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, + dest_height, &clip_box, flags, + FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::StartDIBitsWithBlend( + const RetainPtr& pBitmap, + int bitmap_alpha, + uint32_t argb, + const CFX_Matrix* pMatrix, + uint32_t flags, + std::unique_ptr* handle, + int blend_mode) { + return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, + flags, handle, blend_mode); +} + +bool CFX_RenderDevice::ContinueDIBits(CFX_ImageRenderer* handle, + IFX_PauseIndicator* pPause) { + return m_pDeviceDriver->ContinueDIBits(handle, pPause); +} + +#ifdef _SKIA_SUPPORT_ +void CFX_RenderDevice::DebugVerifyBitmapIsPreMultiplied() const { + SkASSERT(0); +} + +bool CFX_RenderDevice::SetBitsWithMask(const RetainPtr& pBitmap, + const RetainPtr& pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { + return m_pDeviceDriver->SetBitsWithMask(pBitmap, pMask, left, top, + bitmap_alpha, blend_type); +} +#endif + +bool CFX_RenderDevice::DrawNormalText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + float font_size, + const CFX_Matrix* pText2Device, + uint32_t fill_color, + uint32_t text_flags) { + int nativetext_flags = text_flags; + if (m_DeviceClass != FXDC_DISPLAY) { + if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { + if (ShouldDrawDeviceText(pFont, text_flags) && + m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, + font_size, fill_color)) { + return true; + } + } + if (FXARGB_A(fill_color) < 255) + return false; + } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { + if (ShouldDrawDeviceText(pFont, text_flags) && + m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, + font_size, fill_color)) { + return true; + } + } + CFX_Matrix char2device; + CFX_Matrix text2Device; + if (pText2Device) { + char2device = *pText2Device; + text2Device = *pText2Device; + } + + char2device.Scale(font_size, -font_size); + if (fabs(char2device.a) + fabs(char2device.b) > 50 * 1.0f || + ((m_DeviceClass == FXDC_PRINTER) && + !(text_flags & FXTEXT_PRINTIMAGETEXT))) { + if (pFont->GetFace()) { + int nPathFlags = + (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; + return DrawTextPath(nChars, pCharPos, pFont, font_size, pText2Device, + nullptr, nullptr, fill_color, 0, nullptr, nPathFlags); + } + } + int anti_alias = FXFT_RENDER_MODE_MONO; + bool bNormal = false; + if ((text_flags & FXTEXT_NOSMOOTH) == 0) { + if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { + if (!CFX_GEModule::Get()->GetFontMgr()->FTLibrarySupportsHinting()) { + // Some Freetype implementations (like the one packaged with Fedora) do + // not support hinting due to patents 6219025, 6239783, 6307566, + // 6225973, 6243070, 6393145, 6421054, 6282327, and 6624828; the latest + // one expires 10/7/19. This makes LCD antialiasing very ugly, so we + // instead fall back on NORMAL antialiasing. + anti_alias = FXFT_RENDER_MODE_NORMAL; + } else if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { + anti_alias = FXFT_RENDER_MODE_LCD; + bNormal = true; + } else if (m_bpp < 16) { + anti_alias = FXFT_RENDER_MODE_NORMAL; + } else { + anti_alias = FXFT_RENDER_MODE_LCD; + + bool bClearType = false; + if (pFont->GetFace()) + bClearType = !!(text_flags & FXTEXT_CLEARTYPE); + bNormal = !bClearType; + } + } + } + std::vector glyphs(nChars); + CFX_Matrix matrixCTM = GetCTM(); + float scale_x = fabs(matrixCTM.a); + float scale_y = fabs(matrixCTM.d); + CFX_Matrix deviceCtm = char2device; + CFX_Matrix m(scale_x, 0, 0, scale_y, 0, 0); + deviceCtm.Concat(m); + text2Device.Concat(m); + + for (size_t i = 0; i < glyphs.size(); ++i) { + FXTEXT_GLYPHPOS& glyph = glyphs[i]; + const FXTEXT_CHARPOS& charpos = pCharPos[i]; + + glyph.m_fOrigin = text2Device.Transform(charpos.m_Origin); + if (anti_alias < FXFT_RENDER_MODE_LCD) + glyph.m_Origin.x = FXSYS_round(glyph.m_fOrigin.x); + else + glyph.m_Origin.x = static_cast(floor(glyph.m_fOrigin.x)); + glyph.m_Origin.y = FXSYS_round(glyph.m_fOrigin.y); + + if (charpos.m_bGlyphAdjust) { + CFX_Matrix new_matrix( + charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); + new_matrix.Concat(deviceCtm); + glyph.m_pGlyph = pFont->LoadGlyphBitmap( + charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, + charpos.m_FontCharWidth, anti_alias, nativetext_flags); + } else { + glyph.m_pGlyph = pFont->LoadGlyphBitmap( + charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, + charpos.m_FontCharWidth, anti_alias, nativetext_flags); + } + } + if (anti_alias < FXFT_RENDER_MODE_LCD && glyphs.size() > 1) + AdjustGlyphSpace(&glyphs); + + FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(glyphs, anti_alias, 1.0f, 1.0f); + if (scale_x > 1 && scale_y > 1) { + --bmp_rect1.left; + --bmp_rect1.top; + ++bmp_rect1.right; + ++bmp_rect1.bottom; + } + FX_RECT bmp_rect(FXSYS_round((float)(bmp_rect1.left) / scale_x), + FXSYS_round((float)(bmp_rect1.top) / scale_y), + FXSYS_round((float)bmp_rect1.right / scale_x), + FXSYS_round((float)bmp_rect1.bottom / scale_y)); + bmp_rect.Intersect(m_ClipBox); + if (bmp_rect.IsEmpty()) + return true; + + int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); + int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); + int pixel_left = FXSYS_round(bmp_rect.left * scale_x); + int pixel_top = FXSYS_round(bmp_rect.top * scale_y); + if (anti_alias == FXFT_RENDER_MODE_MONO) { + auto bitmap = pdfium::MakeRetain(); + if (!bitmap->Create(pixel_width, pixel_height, FXDIB_1bppMask)) + return false; + bitmap->Clear(0); + for (const FXTEXT_GLYPHPOS& glyph : glyphs) { + if (!glyph.m_pGlyph) + continue; + RetainPtr pGlyph = glyph.m_pGlyph->m_pBitmap; + bitmap->TransferBitmap( + glyph.m_Origin.x + glyph.m_pGlyph->m_Left - pixel_left, + glyph.m_Origin.y - glyph.m_pGlyph->m_Top - pixel_top, + pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); + } + return SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color); + } + auto bitmap = pdfium::MakeRetain(); + if (m_bpp == 8) { + if (!bitmap->Create(pixel_width, pixel_height, FXDIB_8bppMask)) + return false; + } else { + if (!CreateCompatibleBitmap(bitmap, pixel_width, pixel_height)) + return false; + } + if (!bitmap->HasAlpha() && !bitmap->IsAlphaMask()) { + bitmap->Clear(0xFFFFFFFF); + if (!GetDIBits(bitmap, bmp_rect.left, bmp_rect.top)) + return false; + } else { + bitmap->Clear(0); + if (bitmap->m_pAlphaMask) + bitmap->m_pAlphaMask->Clear(0); + } + int dest_width = pixel_width; + int a = 0; + int r = 0; + int g = 0; + int b = 0; + if (anti_alias == FXFT_RENDER_MODE_LCD) + std::tie(a, r, g, b) = ArgbDecode(fill_color); + + for (const FXTEXT_GLYPHPOS& glyph : glyphs) { + if (!glyph.m_pGlyph) + continue; + + pdfium::base::CheckedNumeric left = glyph.m_Origin.x; + left += glyph.m_pGlyph->m_Left; + left -= pixel_left; + if (!left.IsValid()) + return false; + + pdfium::base::CheckedNumeric top = glyph.m_Origin.y; + top -= glyph.m_pGlyph->m_Top; + top -= pixel_top; + if (!top.IsValid()) + return false; + + RetainPtr pGlyph = glyph.m_pGlyph->m_pBitmap; + int ncols = pGlyph->GetWidth(); + int nrows = pGlyph->GetHeight(); + if (anti_alias == FXFT_RENDER_MODE_NORMAL) { + if (!bitmap->CompositeMask(left.ValueOrDie(), top.ValueOrDie(), ncols, + nrows, pGlyph, fill_color, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, false, 0)) { + return false; + } + continue; + } + bool bBGRStripe = !!(text_flags & FXTEXT_BGR_STRIPE); + ncols /= 3; + int x_subpixel = static_cast(glyph.m_fOrigin.x * 3) % 3; + int start_col = + pdfium::base::ValueOrDieForType(pdfium::base::CheckMax(left, 0)); + pdfium::base::CheckedNumeric end_col_safe = left; + end_col_safe += ncols; + if (!end_col_safe.IsValid()) + return false; + + int end_col = + std::min(static_cast(end_col_safe.ValueOrDie()), dest_width); + if (start_col >= end_col) + continue; + + DrawNormalTextHelper(bitmap, pGlyph, nrows, left.ValueOrDie(), + top.ValueOrDie(), start_col, end_col, bNormal, + bBGRStripe, x_subpixel, a, r, g, b); + } + if (bitmap->IsAlphaMask()) + SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color); + else + SetDIBits(bitmap, bmp_rect.left, bmp_rect.top); + return true; +} + +bool CFX_RenderDevice::DrawTextPath(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + float font_size, + const CFX_Matrix* pText2User, + const CFX_Matrix* pUser2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + FX_ARGB stroke_color, + CFX_PathData* pClippingPath, + int nFlag) { + for (int iChar = 0; iChar < nChars; ++iChar) { + const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; + CFX_Matrix matrix; + if (charpos.m_bGlyphAdjust) { + matrix = CFX_Matrix(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], + 0, 0); + } + matrix.Concat(CFX_Matrix(font_size, 0, 0, font_size, charpos.m_Origin.x, + charpos.m_Origin.y)); + const CFX_PathData* pPath = + pFont->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth); + if (!pPath) + continue; + + matrix.Concat(*pText2User); + + CFX_PathData TransformedPath(*pPath); + TransformedPath.Transform(&matrix); + if (fill_color || stroke_color) { + int fill_mode = nFlag; + if (fill_color) + fill_mode |= FXFILL_WINDING; + fill_mode |= FX_FILL_TEXT_MODE; + if (!DrawPathWithBlend(&TransformedPath, pUser2Device, pGraphState, + fill_color, stroke_color, fill_mode, + FXDIB_BLEND_NORMAL)) { + return false; + } + } + if (pClippingPath) + pClippingPath->Append(&TransformedPath, pUser2Device); + } + return true; +} + +void CFX_RenderDevice::DrawFillRect(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + const FX_COLORREF& color) { + CFX_PathData path; + CFX_FloatRect rcTemp(rect); + path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top); + DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_WINDING); +} + +void CFX_RenderDevice::DrawFillArea(const CFX_Matrix* pUser2Device, + const CFX_PointF* pPts, + int32_t nCount, + const FX_COLORREF& color) { + CFX_PathData path; + path.AppendPoint(pPts[0], FXPT_TYPE::MoveTo, false); + for (int32_t i = 1; i < nCount; i++) + path.AppendPoint(pPts[i], FXPT_TYPE::LineTo, false); + + DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_ALTERNATE); +} + +void CFX_RenderDevice::DrawStrokeRect(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + const FX_COLORREF& color, + float fWidth) { + CFX_PathData path; + CFX_FloatRect rcTemp(rect); + path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top); + + CFX_GraphStateData gsd; + gsd.m_LineWidth = fWidth; + + DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE); +} + +void CFX_RenderDevice::DrawStrokeLine(const CFX_Matrix* pUser2Device, + const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, + const FX_COLORREF& color, + float fWidth) { + CFX_PathData path; + path.AppendPoint(ptMoveTo, FXPT_TYPE::MoveTo, false); + path.AppendPoint(ptLineTo, FXPT_TYPE::LineTo, false); + + CFX_GraphStateData gsd; + gsd.m_LineWidth = fWidth; + + DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE); +} + +void CFX_RenderDevice::DrawFillRect(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + const CFX_Color& color, + int32_t nTransparency) { + DrawFillRect(pUser2Device, rect, color.ToFXColor(nTransparency)); +} + +void CFX_RenderDevice::DrawShadow(const CFX_Matrix* pUser2Device, + bool bVertical, + bool bHorizontal, + CFX_FloatRect rect, + int32_t nTransparency, + int32_t nStartGray, + int32_t nEndGray) { + float fStepGray = 1.0f; + + if (bVertical) { + fStepGray = (nEndGray - nStartGray) / rect.Height(); + + for (float fy = rect.bottom + 0.5f; fy <= rect.top - 0.5f; fy += 1.0f) { + int32_t nGray = nStartGray + (int32_t)(fStepGray * (fy - rect.bottom)); + DrawStrokeLine(pUser2Device, CFX_PointF(rect.left, fy), + CFX_PointF(rect.right, fy), + ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f); + } + } + + if (bHorizontal) { + fStepGray = (nEndGray - nStartGray) / rect.Width(); + + for (float fx = rect.left + 0.5f; fx <= rect.right - 0.5f; fx += 1.0f) { + int32_t nGray = nStartGray + (int32_t)(fStepGray * (fx - rect.left)); + DrawStrokeLine(pUser2Device, CFX_PointF(fx, rect.bottom), + CFX_PointF(fx, rect.top), + ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f); + } + } +} + +void CFX_RenderDevice::DrawBorder(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + int32_t nTransparency) { + float fLeft = rect.left; + float fRight = rect.right; + float fTop = rect.top; + float fBottom = rect.bottom; + + if (fWidth > 0.0f) { + float fHalfWidth = fWidth / 2.0f; + + switch (nStyle) { + default: + case BorderStyle::SOLID: { + CFX_PathData path; + path.AppendRect(fLeft, fBottom, fRight, fTop); + path.AppendRect(fLeft + fWidth, fBottom + fWidth, fRight - fWidth, + fTop - fWidth); + DrawPath(&path, pUser2Device, nullptr, color.ToFXColor(nTransparency), + 0, FXFILL_ALTERNATE); + break; + } + case BorderStyle::DASH: { + CFX_PathData path; + path.AppendPoint( + CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f), + FXPT_TYPE::MoveTo, false); + path.AppendPoint( + CFX_PointF(fLeft + fWidth / 2.0f, fTop - fWidth / 2.0f), + FXPT_TYPE::LineTo, false); + path.AppendPoint( + CFX_PointF(fRight - fWidth / 2.0f, fTop - fWidth / 2.0f), + FXPT_TYPE::LineTo, false); + path.AppendPoint( + CFX_PointF(fRight - fWidth / 2.0f, fBottom + fWidth / 2.0f), + FXPT_TYPE::LineTo, false); + path.AppendPoint( + CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f), + FXPT_TYPE::LineTo, false); + + CFX_GraphStateData gsd; + gsd.SetDashCount(2); + gsd.m_DashArray[0] = 3.0f; + gsd.m_DashArray[1] = 3.0f; + gsd.m_DashPhase = 0; + + gsd.m_LineWidth = fWidth; + DrawPath(&path, pUser2Device, &gsd, 0, color.ToFXColor(nTransparency), + FXFILL_WINDING); + break; + } + case BorderStyle::BEVELED: + case BorderStyle::INSET: { + CFX_GraphStateData gsd; + gsd.m_LineWidth = fHalfWidth; + + CFX_PathData pathLT; + + pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), + FXPT_TYPE::MoveTo, false); + pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fTop - fHalfWidth), + FXPT_TYPE::LineTo, false); + pathLT.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), + FXPT_TYPE::LineTo, false); + pathLT.AppendPoint( + CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2), + FXPT_TYPE::LineTo, false); + pathLT.AppendPoint( + CFX_PointF(fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2), + FXPT_TYPE::LineTo, false); + pathLT.AppendPoint( + CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2), + FXPT_TYPE::LineTo, false); + pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), + FXPT_TYPE::LineTo, false); + + DrawPath(&pathLT, pUser2Device, &gsd, + crLeftTop.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE); + + CFX_PathData pathRB; + pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), + FXPT_TYPE::MoveTo, false); + pathRB.AppendPoint( + CFX_PointF(fRight - fHalfWidth, fBottom + fHalfWidth), + FXPT_TYPE::LineTo, false); + pathRB.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), + FXPT_TYPE::LineTo, false); + pathRB.AppendPoint( + CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2), + FXPT_TYPE::LineTo, false); + pathRB.AppendPoint( + CFX_PointF(fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2), + FXPT_TYPE::LineTo, false); + pathRB.AppendPoint( + CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2), + FXPT_TYPE::LineTo, false); + pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), + FXPT_TYPE::LineTo, false); + + DrawPath(&pathRB, pUser2Device, &gsd, + crRightBottom.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE); + + CFX_PathData path; + + path.AppendRect(fLeft, fBottom, fRight, fTop); + path.AppendRect(fLeft + fHalfWidth, fBottom + fHalfWidth, + fRight - fHalfWidth, fTop - fHalfWidth); + + DrawPath(&path, pUser2Device, &gsd, color.ToFXColor(nTransparency), 0, + FXFILL_ALTERNATE); + break; + } + case BorderStyle::UNDERLINE: { + CFX_PathData path; + path.AppendPoint(CFX_PointF(fLeft, fBottom + fWidth / 2), + FXPT_TYPE::MoveTo, false); + path.AppendPoint(CFX_PointF(fRight, fBottom + fWidth / 2), + FXPT_TYPE::LineTo, false); + + CFX_GraphStateData gsd; + gsd.m_LineWidth = fWidth; + + DrawPath(&path, pUser2Device, &gsd, 0, color.ToFXColor(nTransparency), + FXFILL_ALTERNATE); + break; + } + } + } +} + +CFX_RenderDevice::StateRestorer::StateRestorer(CFX_RenderDevice* pDevice) + : m_pDevice(pDevice) { + m_pDevice->SaveState(); +} + +CFX_RenderDevice::StateRestorer::~StateRestorer() { + m_pDevice->RestoreState(false); +} diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h index 2e9abf9963d53ba6636f60d68c94d093800129c8..d8cb9a69520289616eed70bab49cd5aa9dd4e1ff 100644 --- a/core/fxge/cfx_renderdevice.h +++ b/core/fxge/cfx_renderdevice.h @@ -9,12 +9,15 @@ #include -#include "core/fxge/cfx_gemodule.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_color.h" #include "core/fxge/fx_dib.h" -#include "core/fxge/fx_font.h" +class CFX_DIBitmap; class CFX_Font; class CFX_GraphStateData; +class CFX_ImageRenderer; +class IFX_PauseIndicator; class IFX_RenderDeviceDriver; #define FXDC_DEVICE_CLASS 1 @@ -29,7 +32,6 @@ class IFX_RenderDeviceDriver; #define FXRC_GET_BITS 0x01 #define FXRC_BIT_MASK 0x02 -#define FXRC_ALPHA_MASK 0x04 #define FXRC_ALPHA_PATH 0x10 #define FXRC_ALPHA_IMAGE 0x20 #define FXRC_ALPHA_OUTPUT 0x40 @@ -60,6 +62,8 @@ class IFX_RenderDeviceDriver; #define FXTEXT_PRINTIMAGETEXT 0x10 #define FXTEXT_NOSMOOTH 0x20 +class CFX_PathData; + enum class FXPT_TYPE : uint8_t { LineTo, BezierTo, MoveTo }; class FXTEXT_CHARPOS { @@ -68,11 +72,12 @@ class FXTEXT_CHARPOS { FXTEXT_CHARPOS(const FXTEXT_CHARPOS&); ~FXTEXT_CHARPOS(); - FX_FLOAT m_AdjustMatrix[4]; + float m_AdjustMatrix[4]; CFX_PointF m_Origin; + uint32_t m_Unicode; uint32_t m_GlyphIndex; int32_t m_FontCharWidth; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ uint32_t m_ExtGID; #endif int32_t m_FallbackFontPosition; @@ -82,6 +87,15 @@ class FXTEXT_CHARPOS { class CFX_RenderDevice { public: + class StateRestorer { + public: + explicit StateRestorer(CFX_RenderDevice* pDevice); + ~StateRestorer(); + + private: + UnownedPtr m_pDevice; + }; + CFX_RenderDevice(); virtual ~CFX_RenderDevice(); @@ -100,13 +114,16 @@ class CFX_RenderDevice { int GetRenderCaps() const { return m_RenderCaps; } int GetDeviceCaps(int id) const; CFX_Matrix GetCTM() const; - CFX_DIBitmap* GetBitmap() const { return m_pBitmap; } - void SetBitmap(CFX_DIBitmap* pBitmap) { m_pBitmap = pBitmap; } - bool CreateCompatibleBitmap(CFX_DIBitmap* pDIB, int width, int height) const; + RetainPtr GetBitmap() const; + void SetBitmap(const RetainPtr& pBitmap); + bool CreateCompatibleBitmap(const RetainPtr& pDIB, + int width, + int height) const; const FX_RECT& GetClipBox() const { return m_ClipBox; } bool SetClip_PathFill(const CFX_PathData* pPathData, const CFX_Matrix* pObject2Device, int fill_mode); + bool SetClip_Rect(const CFX_RectF& pRect); bool SetClip_Rect(const FX_RECT& pRect); bool SetClip_PathStroke(const CFX_PathData* pPathData, const CFX_Matrix* pObject2Device, @@ -127,29 +144,20 @@ class CFX_RenderDevice { uint32_t stroke_color, int fill_mode, int blend_type); - bool SetPixel(int x, int y, uint32_t color); bool FillRect(const FX_RECT* pRect, uint32_t color) { return FillRectWithBlend(pRect, color, FXDIB_BLEND_NORMAL); } - bool FillRectWithBlend(const FX_RECT* pRect, uint32_t color, int blend_type); - bool DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, - uint32_t color, - int fill_mode, - int blend_type); - bool GetDIBits(CFX_DIBitmap* pBitmap, int left, int top); - CFX_DIBitmap* GetBackDrop(); - bool SetDIBits(const CFX_DIBSource* pBitmap, int left, int top) { + RetainPtr GetBackDrop(); + bool GetDIBits(const RetainPtr& pBitmap, int left, int top); + bool SetDIBits(const RetainPtr& pBitmap, int left, int top) { return SetDIBitsWithBlend(pBitmap, left, top, FXDIB_BLEND_NORMAL); } - bool SetDIBitsWithBlend(const CFX_DIBSource* pBitmap, + bool SetDIBitsWithBlend(const RetainPtr& pBitmap, int left, int top, int blend_type); - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, int left, int top, int dest_width, @@ -157,60 +165,59 @@ class CFX_RenderDevice { return StretchDIBitsWithFlagsAndBlend(pBitmap, left, top, dest_width, dest_height, 0, FXDIB_BLEND_NORMAL); } - bool StretchDIBitsWithFlagsAndBlend(const CFX_DIBSource* pBitmap, + bool StretchDIBitsWithFlagsAndBlend(const RetainPtr& pBitmap, int left, int top, int dest_width, int dest_height, uint32_t flags, int blend_type); - bool SetBitMask(const CFX_DIBSource* pBitmap, + bool SetBitMask(const RetainPtr& pBitmap, int left, int top, uint32_t color); - bool StretchBitMask(const CFX_DIBSource* pBitmap, + bool StretchBitMask(const RetainPtr& pBitmap, int left, int top, int dest_width, int dest_height, uint32_t color); - bool StretchBitMaskWithFlags(const CFX_DIBSource* pBitmap, + bool StretchBitMaskWithFlags(const RetainPtr& pBitmap, int left, int top, int dest_width, int dest_height, uint32_t color, uint32_t flags); - bool StartDIBits(const CFX_DIBSource* pBitmap, + bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags, - void*& handle) { + std::unique_ptr* handle) { return StartDIBitsWithBlend(pBitmap, bitmap_alpha, color, pMatrix, flags, handle, FXDIB_BLEND_NORMAL); } - bool StartDIBitsWithBlend(const CFX_DIBSource* pBitmap, + bool StartDIBitsWithBlend(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags, - void*& handle, + std::unique_ptr* handle, int blend_type); - bool ContinueDIBits(void* handle, IFX_Pause* pPause); - void CancelDIBits(void* handle); + bool ContinueDIBits(CFX_ImageRenderer* handle, IFX_PauseIndicator* pPause); bool DrawNormalText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pText2Device, uint32_t fill_color, uint32_t text_flags); bool DrawTextPath(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, - FX_FLOAT font_size, + float font_size, const CFX_Matrix* pText2User, const CFX_Matrix* pUser2Device, const CFX_GraphStateData* pGraphState, @@ -219,17 +226,53 @@ class CFX_RenderDevice { CFX_PathData* pClippingPath, int nFlag); + void DrawFillRect(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + const CFX_Color& color, + int32_t nTransparency); + void DrawFillRect(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + const FX_COLORREF& color); + void DrawStrokeRect(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + const FX_COLORREF& color, + float fWidth); + void DrawStrokeLine(const CFX_Matrix* pUser2Device, + const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, + const FX_COLORREF& color, + float fWidth); + void DrawBorder(const CFX_Matrix* pUser2Device, + const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + int32_t nTransparency); + void DrawFillArea(const CFX_Matrix* pUser2Device, + const CFX_PointF* pPts, + int32_t nCount, + const FX_COLORREF& color); + void DrawShadow(const CFX_Matrix* pUser2Device, + bool bVertical, + bool bHorizontal, + CFX_FloatRect rect, + int32_t nTransparency, + int32_t nStartGray, + int32_t nEndGray); + #ifdef _SKIA_SUPPORT_ virtual void DebugVerifyBitmapIsPreMultiplied() const; - virtual bool SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, + virtual bool SetBitsWithMask(const RetainPtr& pBitmap, + const RetainPtr& pMask, int left, int top, int bitmap_alpha, int blend_type); #endif #if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - void Flush(); + void Flush(bool release); #endif private: @@ -242,8 +285,14 @@ class CFX_RenderDevice { uint32_t stroke_color, int fill_mode, int blend_type); + bool DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, + uint32_t color, + int fill_mode, + int blend_type); + bool FillRectWithBlend(const FX_RECT* pRect, uint32_t color, int blend_type); - CFX_DIBitmap* m_pBitmap; + RetainPtr m_pBitmap; int m_Width; int m_Height; int m_bpp; diff --git a/core/fxge/cfx_substfont.cpp b/core/fxge/cfx_substfont.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c5459ede6dcf0ab0543797caf4d99f98032c888 --- /dev/null +++ b/core/fxge/cfx_substfont.cpp @@ -0,0 +1,23 @@ +// Copyright 2016 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 "core/fxge/cfx_substfont.h" + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/fx_font.h" + +CFX_SubstFont::CFX_SubstFont() + : m_Charset(FX_CHARSET_ANSI), + m_Weight(0), + m_ItalicAngle(0), + m_WeightCJK(0), + m_bSubstCJK(false), + m_bItalicCJK(false), +#ifdef PDF_ENABLE_XFA + m_bFlagItalic(false), +#endif // PDF_ENABLE_XFA + m_bFlagMM(false) { +} diff --git a/core/fxge/cfx_substfont.h b/core/fxge/cfx_substfont.h index 01196d442ab48e2a27d0cde2e44c2d30e6b0558f..e6d93a80a47bce54c452fcd5546391ac42da71e6 100644 --- a/core/fxge/cfx_substfont.h +++ b/core/fxge/cfx_substfont.h @@ -9,21 +9,22 @@ #include "core/fxcrt/fx_string.h" -#define FXFONT_SUBST_MM 0x01 -#define FXFONT_SUBST_EXACT 0x40 - class CFX_SubstFont { public: CFX_SubstFont(); - CFX_ByteString m_Family; + ByteString m_Family; int m_Charset; - uint32_t m_SubstFlags; int m_Weight; int m_ItalicAngle; - bool m_bSubstCJK; int m_WeightCJK; + bool m_bSubstCJK; bool m_bItalicCJK; + +#ifdef PDF_ENABLE_XFA + bool m_bFlagItalic; +#endif // PDF_ENABLE_XFA + bool m_bFlagMM; }; #endif // CORE_FXGE_CFX_SUBSTFONT_H_ diff --git a/core/fxge/ge/cfx_unicodeencoding.cpp b/core/fxge/cfx_unicodeencoding.cpp similarity index 88% rename from core/fxge/ge/cfx_unicodeencoding.cpp rename to core/fxge/cfx_unicodeencoding.cpp index cba67ba35466e1bdf305df9e0bd1ba7cfffff0a0..446b62c43190bc47d1667ebdb102620fbb2292b1 100644 --- a/core/fxge/ge/cfx_unicodeencoding.cpp +++ b/core/fxge/cfx_unicodeencoding.cpp @@ -6,6 +6,8 @@ #include "core/fxge/cfx_unicodeencoding.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" @@ -22,7 +24,7 @@ uint32_t CFX_UnicodeEncoding::GlyphFromCharCode(uint32_t charcode) { return FXFT_Get_Char_Index(face, charcode); if (m_pFont->GetSubstFont() && - m_pFont->GetSubstFont()->m_Charset == FXFONT_SYMBOL_CHARSET) { + m_pFont->GetSubstFont()->m_Charset == FX_CHARSET_Symbol) { uint32_t index = 0; if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) index = FXFT_Get_Char_Index(face, charcode); diff --git a/core/fxge/cfx_unicodeencoding.h b/core/fxge/cfx_unicodeencoding.h index 7d020894c0778618a4f83c2ed3a9ae3661cc5bc4..f8bcff391fd48a21d27bddca66c0055348b96982 100644 --- a/core/fxge/cfx_unicodeencoding.h +++ b/core/fxge/cfx_unicodeencoding.h @@ -7,10 +7,7 @@ #ifndef CORE_FXGE_CFX_UNICODEENCODING_H_ #define CORE_FXGE_CFX_UNICODEENCODING_H_ -#include "core/fxge/fx_font.h" - -#define ENCODING_INTERNAL 0 -#define ENCODING_UNICODE 1 +#include #ifdef PDF_ENABLE_XFA #define FXFM_ENC_TAG(a, b, c, d) \ @@ -32,6 +29,8 @@ #define FXFM_ENCODING_APPLE_ROMAN FXFM_ENC_TAG('a', 'r', 'm', 'n') #endif // PDF_ENABLE_XFA +class CFX_Font; + class CFX_UnicodeEncoding { public: explicit CFX_UnicodeEncoding(CFX_Font* pFont); diff --git a/core/fxge/ge/cfx_unicodeencodingex.cpp b/core/fxge/cfx_unicodeencodingex.cpp similarity index 82% rename from core/fxge/ge/cfx_unicodeencodingex.cpp rename to core/fxge/cfx_unicodeencodingex.cpp index c7e3303f0269fc458211293bf88b19240e56bcdd..a8db745612ae381039de77a29cfca0cbdc924821 100644 --- a/core/fxge/ge/cfx_unicodeencodingex.cpp +++ b/core/fxge/cfx_unicodeencodingex.cpp @@ -6,9 +6,12 @@ #include "core/fxge/cfx_unicodeencodingex.h" +#include + #include "core/fpdfapi/font/cpdf_font.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" +#include "third_party/base/ptr_util.h" namespace { @@ -22,11 +25,12 @@ const uint32_t g_EncodingID[] = { FXFM_ENCODING_APPLE_ROMAN, }; -CFX_UnicodeEncodingEx* FXFM_CreateFontEncoding(CFX_Font* pFont, - uint32_t nEncodingID) { +std::unique_ptr FXFM_CreateFontEncoding( + CFX_Font* pFont, + uint32_t nEncodingID) { if (FXFT_Select_Charmap(pFont->GetFace(), nEncodingID)) return nullptr; - return new CFX_UnicodeEncodingEx(pFont, nEncodingID); + return pdfium::MakeUnique(pFont, nEncodingID); } } // namespace @@ -62,7 +66,7 @@ uint32_t CFX_UnicodeEncodingEx::GlyphFromCharCode(uint32_t charcode) { return 0; } -uint32_t CFX_UnicodeEncodingEx::CharCodeFromUnicode(FX_WCHAR Unicode) const { +uint32_t CFX_UnicodeEncodingEx::CharCodeFromUnicode(wchar_t Unicode) const { if (m_nEncodingID == FXFM_ENCODING_UNICODE || m_nEncodingID == FXFM_ENCODING_MS_SYMBOL) { return Unicode; @@ -80,17 +84,17 @@ uint32_t CFX_UnicodeEncodingEx::CharCodeFromUnicode(FX_WCHAR Unicode) const { return CPDF_Font::kInvalidCharCode; } -CFX_UnicodeEncodingEx* FX_CreateFontEncodingEx(CFX_Font* pFont, - uint32_t nEncodingID) { +std::unique_ptr FX_CreateFontEncodingEx( + CFX_Font* pFont, + uint32_t nEncodingID) { if (!pFont || !pFont->GetFace()) return nullptr; if (nEncodingID != FXFM_ENCODING_NONE) return FXFM_CreateFontEncoding(pFont, nEncodingID); - for (size_t i = 0; i < FX_ArraySize(g_EncodingID); ++i) { - CFX_UnicodeEncodingEx* pFontEncoding = - FXFM_CreateFontEncoding(pFont, g_EncodingID[i]); + for (uint32_t id : g_EncodingID) { + auto pFontEncoding = FXFM_CreateFontEncoding(pFont, id); if (pFontEncoding) return pFontEncoding; } diff --git a/core/fxge/cfx_unicodeencodingex.h b/core/fxge/cfx_unicodeencodingex.h index df2edbe1bf63c6529089f5a9c44d04ea99a76690..5632d9665d2ea72b2e9d55b7bea67ba01335ad51 100644 --- a/core/fxge/cfx_unicodeencodingex.h +++ b/core/fxge/cfx_unicodeencodingex.h @@ -14,7 +14,6 @@ #include "core/fxcrt/fx_system.h" #include "core/fxge/cfx_unicodeencoding.h" #include "core/fxge/fx_dib.h" -#include "core/fxge/fx_freetype.h" class CFX_UnicodeEncodingEx : public CFX_UnicodeEncoding { public: @@ -24,14 +23,14 @@ class CFX_UnicodeEncodingEx : public CFX_UnicodeEncoding { // CFX_UnicodeEncoding: uint32_t GlyphFromCharCode(uint32_t charcode) override; - uint32_t CharCodeFromUnicode(FX_WCHAR Unicode) const; + uint32_t CharCodeFromUnicode(wchar_t Unicode) const; private: uint32_t m_nEncodingID; }; -CFX_UnicodeEncodingEx* FX_CreateFontEncodingEx( +std::unique_ptr FX_CreateFontEncodingEx( CFX_Font* pFont, - uint32_t nEncodingID = FXFM_ENCODING_NONE); + uint32_t nEncodingID); #endif // CORE_FXGE_CFX_UNICODEENCODINGEX_H_ diff --git a/core/fxge/cfx_windowsdevice.h b/core/fxge/cfx_windowsdevice.h deleted file mode 100644 index 6240d842197c9f203d39021118054e1338606886..0000000000000000000000000000000000000000 --- a/core/fxge/cfx_windowsdevice.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 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 CORE_FXGE_CFX_WINDOWSDEVICE_H_ -#define CORE_FXGE_CFX_WINDOWSDEVICE_H_ - -#ifdef _WIN32 -#ifndef _WINDOWS_ -#include -#endif - -#include "core/fxge/cfx_renderdevice.h" - -class IFX_RenderDeviceDriver; - -#if defined(PDFIUM_PRINT_TEXT_WITH_GDI) -typedef void (*PDFiumEnsureTypefaceCharactersAccessible)(const LOGFONT* font, - const wchar_t* text, - size_t text_length); - -extern bool g_pdfium_print_text_with_gdi; -extern PDFiumEnsureTypefaceCharactersAccessible - g_pdfium_typeface_accessible_func; -#endif -extern int g_pdfium_print_postscript_level; - -class CFX_WindowsDevice : public CFX_RenderDevice { - public: - static IFX_RenderDeviceDriver* CreateDriver(HDC hDC); - - explicit CFX_WindowsDevice(HDC hDC); - ~CFX_WindowsDevice() override; - - HDC GetDC() const; -}; - -#endif // _WIN32 - -#endif // CORE_FXGE_CFX_WINDOWSDEVICE_H_ diff --git a/core/fxge/cfx_windowsrenderdevice.h b/core/fxge/cfx_windowsrenderdevice.h new file mode 100644 index 0000000000000000000000000000000000000000..f1e0cbdb7a303145a8fe2d240cb417c8504eb742 --- /dev/null +++ b/core/fxge/cfx_windowsrenderdevice.h @@ -0,0 +1,47 @@ +// Copyright 2016 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 CORE_FXGE_CFX_WINDOWSRENDERDEVICE_H_ +#define CORE_FXGE_CFX_WINDOWSRENDERDEVICE_H_ + +#ifdef _WIN32 +#ifndef _WINDOWS_ +#include +#endif + +#include "core/fxge/cfx_renderdevice.h" + +enum WindowsPrintMode { + kModeEmf = 0, + kModeTextOnly = 1, + kModePostScript2 = 2, + kModePostScript3 = 3, +}; + +class IFX_RenderDeviceDriver; + +#if defined(PDFIUM_PRINT_TEXT_WITH_GDI) +typedef void (*PDFiumEnsureTypefaceCharactersAccessible)(const LOGFONT* font, + const wchar_t* text, + size_t text_length); + +extern bool g_pdfium_print_text_with_gdi; +extern PDFiumEnsureTypefaceCharactersAccessible + g_pdfium_typeface_accessible_func; +#endif +extern int g_pdfium_print_mode; + +class CFX_WindowsRenderDevice : public CFX_RenderDevice { + public: + static IFX_RenderDeviceDriver* CreateDriver(HDC hDC); + + explicit CFX_WindowsRenderDevice(HDC hDC); + ~CFX_WindowsRenderDevice() override; +}; + +#endif // _WIN32 + +#endif // CORE_FXGE_CFX_WINDOWSRENDERDEVICE_H_ diff --git a/core/fxge/cttfontdesc.cpp b/core/fxge/cttfontdesc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdf24518b76e675375403520ee4630c2ae9a7794 --- /dev/null +++ b/core/fxge/cttfontdesc.cpp @@ -0,0 +1,68 @@ +// Copyright 2016 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 "core/fxge/cttfontdesc.h" + +#include "core/fxge/fx_freetype.h" +#include "third_party/base/stl_util.h" + +CTTFontDesc::CTTFontDesc(uint8_t* pData, FXFT_Face face) + : m_bIsTTC(false), m_SingleFace(face), m_pFontData(pData) {} + +CTTFontDesc::CTTFontDesc(uint8_t* pData, size_t index, FXFT_Face face) + : m_bIsTTC(true), m_pFontData(pData) { + for (size_t i = 0; i < FX_ArraySize(m_TTCFaces); i++) + m_TTCFaces[i] = nullptr; + SetTTCFace(index, face); +} + +CTTFontDesc::~CTTFontDesc() { + ASSERT(m_RefCount == 0); + if (m_bIsTTC) { + for (size_t i = 0; i < FX_ArraySize(m_TTCFaces); i++) { + if (m_TTCFaces[i]) + FXFT_Done_Face(m_TTCFaces[i]); + } + } else { + if (m_SingleFace) + FXFT_Done_Face(m_SingleFace); + } + FX_Free(m_pFontData); +} + +void CTTFontDesc::SetTTCFace(size_t index, FXFT_Face face) { + ASSERT(m_bIsTTC); + ASSERT(index < FX_ArraySize(m_TTCFaces)); + m_TTCFaces[index] = face; +} + +void CTTFontDesc::AddRef() { + ASSERT(m_RefCount > 0); + ++m_RefCount; +} + +CTTFontDesc::ReleaseStatus CTTFontDesc::ReleaseFace(FXFT_Face face) { + if (m_bIsTTC) { + if (!pdfium::ContainsValue(m_TTCFaces, face)) + return kNotAppropriate; + } else { + if (m_SingleFace != face) + return kNotAppropriate; + } + ASSERT(m_RefCount > 0); + return --m_RefCount == 0 ? kReleased : kNotReleased; +} + +FXFT_Face CTTFontDesc::SingleFace() const { + ASSERT(!m_bIsTTC); + return m_SingleFace; +} + +FXFT_Face CTTFontDesc::TTCFace(size_t index) const { + ASSERT(m_bIsTTC); + ASSERT(index < FX_ArraySize(m_TTCFaces)); + return m_TTCFaces[index]; +} diff --git a/core/fxge/cttfontdesc.h b/core/fxge/cttfontdesc.h new file mode 100644 index 0000000000000000000000000000000000000000..b48e78c6b6387db5d003f76734657e657080b721 --- /dev/null +++ b/core/fxge/cttfontdesc.h @@ -0,0 +1,52 @@ +// Copyright 2016 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 CORE_FXGE_CTTFONTDESC_H_ +#define CORE_FXGE_CTTFONTDESC_H_ + +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_font.h" + +class CTTFontDesc { + public: + enum ReleaseStatus { + kNotAppropriate, // ReleaseFace() not appropriate for given object. + kReleased, + kNotReleased // Object still alive. + }; + + // Single face ctor. + CTTFontDesc(uint8_t* pData, FXFT_Face face); + + // TTC face ctor. + CTTFontDesc(uint8_t* pData, size_t index, FXFT_Face face); + + ~CTTFontDesc(); + + void SetTTCFace(size_t index, FXFT_Face face); + + void AddRef(); + + // May not decrement refcount, depending on the value of |face|. + ReleaseStatus ReleaseFace(FXFT_Face face); + + uint8_t* FontData() const { return m_pFontData; } + + FXFT_Face SingleFace() const; + FXFT_Face TTCFace(size_t index) const; + + private: + const bool m_bIsTTC; + + union { + const FXFT_Face m_SingleFace; + FXFT_Face m_TTCFaces[16]; + }; + uint8_t* const m_pFontData; + int m_RefCount = 1; +}; + +#endif // CORE_FXGE_CTTFONTDESC_H_ diff --git a/core/fxge/dib/README.md b/core/fxge/dib/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a1e8f75ed7269737a76d31226a553bf739fb398d --- /dev/null +++ b/core/fxge/dib/README.md @@ -0,0 +1 @@ +DIB stands for Device-Independent Bitmap. diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3854949207bcccc109d3a2273b884e8c9974b08f --- /dev/null +++ b/core/fxge/dib/cfx_bitmapcomposer.cpp @@ -0,0 +1,201 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_bitmapcomposer.h" + +#include "core/fxge/cfx_cliprgn.h" +#include "core/fxge/dib/cfx_dibitmap.h" + +CFX_BitmapComposer::CFX_BitmapComposer() + : m_bRgbByteOrder(false), m_BlendType(FXDIB_BLEND_NORMAL) {} + +CFX_BitmapComposer::~CFX_BitmapComposer() {} + +void CFX_BitmapComposer::Compose(const RetainPtr& pDest, + const CFX_ClipRgn* pClipRgn, + int bitmap_alpha, + uint32_t mask_color, + const FX_RECT& dest_rect, + bool bVertical, + bool bFlipX, + bool bFlipY, + bool bRgbByteOrder, + int alpha_flag, + int blend_type) { + m_pBitmap = pDest; + m_pClipRgn = pClipRgn; + m_DestLeft = dest_rect.left; + m_DestTop = dest_rect.top; + m_DestWidth = dest_rect.Width(); + m_DestHeight = dest_rect.Height(); + m_BitmapAlpha = bitmap_alpha; + m_MaskColor = mask_color; + m_pClipMask = nullptr; + if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) + m_pClipMask = pClipRgn->GetMask(); + m_bVertical = bVertical; + m_bFlipX = bFlipX; + m_bFlipY = bFlipY; + m_AlphaFlag = alpha_flag; + m_bRgbByteOrder = bRgbByteOrder; + m_BlendType = blend_type; +} + +bool CFX_BitmapComposer::SetInfo(int width, + int height, + FXDIB_Format src_format, + uint32_t* pSrcPalette) { + m_SrcFormat = src_format; + if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, + m_MaskColor, FXDIB_BLEND_NORMAL, + m_pClipMask != nullptr || (m_BitmapAlpha < 255), + m_bRgbByteOrder, m_AlphaFlag)) { + return false; + } + if (m_bVertical) { + m_pScanlineV.resize(m_pBitmap->GetBPP() / 8 * width + 4); + m_pClipScanV.resize(m_pBitmap->GetHeight()); + if (m_pBitmap->m_pAlphaMask) + m_pScanlineAlphaV.resize(width + 4); + } + if (m_BitmapAlpha < 255) { + m_pAddClipScan.resize(m_bVertical ? m_pBitmap->GetHeight() + : m_pBitmap->GetWidth()); + } + return true; +} + +void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan, + const uint8_t* src_scan, + int dest_width, + const uint8_t* clip_scan, + const uint8_t* src_extra_alpha, + uint8_t* dst_extra_alpha) { + uint8_t* pAddClipScan = m_pAddClipScan.data(); + if (m_BitmapAlpha < 255) { + if (clip_scan) { + for (int i = 0; i < dest_width; ++i) + pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255; + } else { + memset(pAddClipScan, m_BitmapAlpha, dest_width); + } + clip_scan = pAddClipScan; + } + if (m_SrcFormat == FXDIB_8bppMask) { + m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, + clip_scan, dst_extra_alpha); + } else if ((m_SrcFormat & 0xff) == 8) { + m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, + clip_scan, src_extra_alpha, + dst_extra_alpha); + } else { + m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, + clip_scan, src_extra_alpha, + dst_extra_alpha); + } +} + +void CFX_BitmapComposer::ComposeScanline(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha) { + if (m_bVertical) { + ComposeScanlineV(line, scanline, scan_extra_alpha); + return; + } + const uint8_t* clip_scan = nullptr; + if (m_pClipMask) { + clip_scan = m_pClipMask->GetBuffer() + + (m_DestTop + line - m_pClipRgn->GetBox().top) * + m_pClipMask->GetPitch() + + (m_DestLeft - m_pClipRgn->GetBox().left); + } + uint8_t* dest_scan = + const_cast(m_pBitmap->GetScanline(line + m_DestTop)) + + m_DestLeft * m_pBitmap->GetBPP() / 8; + uint8_t* dest_alpha_scan = + m_pBitmap->m_pAlphaMask + ? const_cast( + m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop)) + + m_DestLeft + : nullptr; + DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, + dest_alpha_scan); +} + +void CFX_BitmapComposer::ComposeScanlineV(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha) { + int Bpp = m_pBitmap->GetBPP() / 8; + int dest_pitch = m_pBitmap->GetPitch(); + int dest_alpha_pitch = + m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0; + int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line); + uint8_t* dest_buf = + m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch; + uint8_t* dest_alpha_buf = m_pBitmap->m_pAlphaMask + ? m_pBitmap->m_pAlphaMask->GetBuffer() + + dest_x + m_DestTop * dest_alpha_pitch + : nullptr; + if (m_bFlipY) { + dest_buf += dest_pitch * (m_DestHeight - 1); + dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1); + } + int y_step = dest_pitch; + int y_alpha_step = dest_alpha_pitch; + if (m_bFlipY) { + y_step = -y_step; + y_alpha_step = -y_alpha_step; + } + uint8_t* src_scan = m_pScanlineV.data(); + uint8_t* dest_scan = dest_buf; + for (int i = 0; i < m_DestHeight; ++i) { + for (int j = 0; j < Bpp; ++j) + *src_scan++ = dest_scan[j]; + dest_scan += y_step; + } + uint8_t* src_alpha_scan = m_pScanlineAlphaV.data(); + uint8_t* dest_alpha_scan = dest_alpha_buf; + if (dest_alpha_scan) { + for (int i = 0; i < m_DestHeight; ++i) { + *src_alpha_scan++ = *dest_alpha_scan; + dest_alpha_scan += y_alpha_step; + } + } + uint8_t* clip_scan = nullptr; + if (m_pClipMask) { + clip_scan = m_pClipScanV.data(); + int clip_pitch = m_pClipMask->GetPitch(); + const uint8_t* src_clip = + m_pClipMask->GetBuffer() + + (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch + + (dest_x - m_pClipRgn->GetBox().left); + if (m_bFlipY) { + src_clip += clip_pitch * (m_DestHeight - 1); + clip_pitch = -clip_pitch; + } + for (int i = 0; i < m_DestHeight; ++i) { + clip_scan[i] = *src_clip; + src_clip += clip_pitch; + } + } + DoCompose(m_pScanlineV.data(), scanline, m_DestHeight, clip_scan, + scan_extra_alpha, m_pScanlineAlphaV.data()); + src_scan = m_pScanlineV.data(); + dest_scan = dest_buf; + for (int i = 0; i < m_DestHeight; ++i) { + for (int j = 0; j < Bpp; ++j) + dest_scan[j] = *src_scan++; + dest_scan += y_step; + } + src_alpha_scan = m_pScanlineAlphaV.data(); + dest_alpha_scan = dest_alpha_buf; + if (!dest_alpha_scan) + return; + for (int i = 0; i < m_DestHeight; ++i) { + *dest_alpha_scan = *src_alpha_scan++; + dest_alpha_scan += y_alpha_step; + } +} diff --git a/core/fxge/dib/cfx_bitmapcomposer.h b/core/fxge/dib/cfx_bitmapcomposer.h new file mode 100644 index 0000000000000000000000000000000000000000..98c1f778470d333cd1ef23825cc4a59b89d0bfcd --- /dev/null +++ b/core/fxge/dib/cfx_bitmapcomposer.h @@ -0,0 +1,82 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_BITMAPCOMPOSER_H_ +#define CORE_FXGE_DIB_CFX_BITMAPCOMPOSER_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/dib/cfx_scanlinecompositor.h" +#include "core/fxge/dib/ifx_scanlinecomposer.h" + +class CFX_ClipRgn; +class CFX_DIBitmap; + +class CFX_BitmapComposer : public IFX_ScanlineComposer { + public: + CFX_BitmapComposer(); + ~CFX_BitmapComposer() override; + + void Compose(const RetainPtr& pDest, + const CFX_ClipRgn* pClipRgn, + int bitmap_alpha, + uint32_t mask_color, + const FX_RECT& dest_rect, + bool bVertical, + bool bFlipX, + bool bFlipY, + bool bRgbByteOrder, + int alpha_flag, + int blend_type); + + // IFX_ScanlineComposer + bool SetInfo(int width, + int height, + FXDIB_Format src_format, + uint32_t* pSrcPalette) override; + + void ComposeScanline(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha) override; + + private: + void DoCompose(uint8_t* dest_scan, + const uint8_t* src_scan, + int dest_width, + const uint8_t* clip_scan, + const uint8_t* src_extra_alpha, + uint8_t* dst_extra_alpha); + void ComposeScanlineV(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha); + + RetainPtr m_pBitmap; + UnownedPtr m_pClipRgn; + FXDIB_Format m_SrcFormat; + int m_DestLeft; + int m_DestTop; + int m_DestWidth; + int m_DestHeight; + int m_BitmapAlpha; + uint32_t m_MaskColor; + RetainPtr m_pClipMask; + CFX_ScanlineCompositor m_Compositor; + bool m_bVertical; + bool m_bFlipX; + bool m_bFlipY; + int m_AlphaFlag; + bool m_bRgbByteOrder; + int m_BlendType; + std::vector m_pScanlineV; + std::vector m_pClipScanV; + std::vector m_pAddClipScan; + std::vector m_pScanlineAlphaV; +}; + +#endif // CORE_FXGE_DIB_CFX_BITMAPCOMPOSER_H_ diff --git a/core/fxge/dib/cfx_bitmapstorer.cpp b/core/fxge/dib/cfx_bitmapstorer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f649e0caea1e1565c03caff5c9f1338ed0d72b56 --- /dev/null +++ b/core/fxge/dib/cfx_bitmapstorer.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_bitmapstorer.h" + +#include + +#include "third_party/base/ptr_util.h" + +CFX_BitmapStorer::CFX_BitmapStorer() {} + +CFX_BitmapStorer::~CFX_BitmapStorer() {} + +RetainPtr CFX_BitmapStorer::Detach() { + return std::move(m_pBitmap); +} + +void CFX_BitmapStorer::Replace(RetainPtr&& pBitmap) { + m_pBitmap = std::move(pBitmap); +} + +void CFX_BitmapStorer::ComposeScanline(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha) { + uint8_t* dest_buf = const_cast(m_pBitmap->GetScanline(line)); + uint8_t* dest_alpha_buf = + m_pBitmap->m_pAlphaMask + ? const_cast(m_pBitmap->m_pAlphaMask->GetScanline(line)) + : nullptr; + if (dest_buf) + memcpy(dest_buf, scanline, m_pBitmap->GetPitch()); + + if (dest_alpha_buf) { + memcpy(dest_alpha_buf, scan_extra_alpha, + m_pBitmap->m_pAlphaMask->GetPitch()); + } +} + +bool CFX_BitmapStorer::SetInfo(int width, + int height, + FXDIB_Format src_format, + uint32_t* pSrcPalette) { + auto pBitmap = pdfium::MakeRetain(); + if (!pBitmap->Create(width, height, src_format)) + return false; + + if (pSrcPalette) + pBitmap->SetPalette(pSrcPalette); + + m_pBitmap = std::move(pBitmap); + return true; +} diff --git a/core/fxge/dib/cfx_bitmapstorer.h b/core/fxge/dib/cfx_bitmapstorer.h new file mode 100644 index 0000000000000000000000000000000000000000..3d3416daa14af4108030f707ef75cf472f5f1350 --- /dev/null +++ b/core/fxge/dib/cfx_bitmapstorer.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_BITMAPSTORER_H_ +#define CORE_FXGE_DIB_CFX_BITMAPSTORER_H_ + +#include +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/ifx_scanlinecomposer.h" +#include "third_party/base/stl_util.h" + +class CFX_BitmapStorer : public IFX_ScanlineComposer { + public: + CFX_BitmapStorer(); + ~CFX_BitmapStorer() override; + + // IFX_ScanlineComposer + void ComposeScanline(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha) override; + bool SetInfo(int width, + int height, + FXDIB_Format src_format, + uint32_t* pSrcPalette) override; + + RetainPtr GetBitmap() { return m_pBitmap; } + RetainPtr Detach(); + void Replace(RetainPtr&& pBitmap); + + private: + RetainPtr m_pBitmap; +}; + +#endif // CORE_FXGE_DIB_CFX_BITMAPSTORER_H_ diff --git a/core/fxge/dib/cfx_dibextractor.cpp b/core/fxge/dib/cfx_dibextractor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13ad461cb1af59e57bbad9d869a78e03908da946 --- /dev/null +++ b/core/fxge/dib/cfx_dibextractor.cpp @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_dibextractor.h" + +#include "core/fxge/dib/cfx_dibsource.h" + +CFX_DIBExtractor::CFX_DIBExtractor(const RetainPtr& pSrc) { + if (!pSrc->GetBuffer()) { + m_pBitmap = pSrc->Clone(nullptr); + return; + } + RetainPtr pOldSrc(pSrc); + m_pBitmap = pdfium::MakeRetain(); + if (!m_pBitmap->Create(pOldSrc->GetWidth(), pOldSrc->GetHeight(), + pOldSrc->GetFormat(), pOldSrc->GetBuffer())) { + m_pBitmap.Reset(); + return; + } + m_pBitmap->SetPalette(pOldSrc->GetPalette()); + m_pBitmap->SetAlphaMask(pOldSrc->m_pAlphaMask, nullptr); +} + +CFX_DIBExtractor::~CFX_DIBExtractor() {} diff --git a/core/fxge/dib/cfx_dibextractor.h b/core/fxge/dib/cfx_dibextractor.h new file mode 100644 index 0000000000000000000000000000000000000000..b6c27a7bd78a32ee055f28b19fe3e9214c919728 --- /dev/null +++ b/core/fxge/dib/cfx_dibextractor.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_DIBEXTRACTOR_H_ +#define CORE_FXGE_DIB_CFX_DIBEXTRACTOR_H_ + +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibitmap.h" + +class CFX_DIBSource; + +class CFX_DIBExtractor { + public: + explicit CFX_DIBExtractor(const RetainPtr& pSrc); + ~CFX_DIBExtractor(); + + RetainPtr GetBitmap() { return m_pBitmap; } + + private: + RetainPtr m_pBitmap; +}; + +#endif // CORE_FXGE_DIB_CFX_DIBEXTRACTOR_H_ diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..857ca9a3ceb3ef6468c7c79b35259c87bdde90ce --- /dev/null +++ b/core/fxge/dib/cfx_dibitmap.cpp @@ -0,0 +1,1240 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_dibitmap.h" + +#include +#include +#include + +#include "core/fxcodec/fx_codec.h" +#include "core/fxge/cfx_cliprgn.h" +#include "core/fxge/dib/cfx_scanlinecompositor.h" +#include "third_party/base/ptr_util.h" + +#define MAX_OOM_LIMIT 12000000 + +namespace { + +const int8_t g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3}; + +} // namespace + +CFX_DIBitmap::CFX_DIBitmap() { + m_pPalette = nullptr; +#ifdef _SKIA_SUPPORT_PATHS_ + m_nFormat = Format::kCleared; +#endif +} + +bool CFX_DIBitmap::Create(int width, + int height, + FXDIB_Format format, + uint8_t* pBuffer, + uint32_t pitch) { + m_pBuffer = nullptr; + m_bpp = static_cast(format); + m_AlphaFlag = static_cast(format >> 8); + m_Width = 0; + m_Height = 0; + m_Pitch = 0; + + uint32_t calculatedSize; + if (!CFX_DIBitmap::CalculatePitchAndSize(height, width, format, &pitch, + &calculatedSize)) + return false; + + if (pBuffer) { + m_pBuffer.Reset(pBuffer); + } else { + size_t bufferSize = calculatedSize + 4; + size_t oomlimit = MAX_OOM_LIMIT; + if (bufferSize >= oomlimit) { + m_pBuffer = std::unique_ptr( + FX_TryAlloc(uint8_t, bufferSize)); + if (!m_pBuffer) + return false; + } else { + m_pBuffer = std::unique_ptr( + FX_Alloc(uint8_t, bufferSize)); + } + } + m_Width = width; + m_Height = height; + m_Pitch = pitch; + if (!HasAlpha() || format == FXDIB_Argb) + return true; + + if (BuildAlphaMask()) + return true; + + if (pBuffer) + return true; + + m_pBuffer = nullptr; + m_Width = 0; + m_Height = 0; + m_Pitch = 0; + return false; +} + +bool CFX_DIBitmap::Copy(const RetainPtr& pSrc) { + if (m_pBuffer) + return false; + + if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat())) + return false; + + SetPalette(pSrc->GetPalette()); + SetAlphaMask(pSrc->m_pAlphaMask, nullptr); + for (int row = 0; row < pSrc->GetHeight(); row++) + memcpy(m_pBuffer.Get() + row * m_Pitch, pSrc->GetScanline(row), m_Pitch); + return true; +} + +CFX_DIBitmap::~CFX_DIBitmap() {} + +uint8_t* CFX_DIBitmap::GetBuffer() const { + return m_pBuffer.Get(); +} + +const uint8_t* CFX_DIBitmap::GetScanline(int line) const { + return m_pBuffer.Get() ? m_pBuffer.Get() + line * m_Pitch : nullptr; +} + +void CFX_DIBitmap::TakeOver(RetainPtr&& pSrcBitmap) { + m_pBuffer = std::move(pSrcBitmap->m_pBuffer); + m_pPalette = std::move(pSrcBitmap->m_pPalette); + m_pAlphaMask = pSrcBitmap->m_pAlphaMask; + pSrcBitmap->m_pBuffer = nullptr; + pSrcBitmap->m_pAlphaMask = nullptr; + m_bpp = pSrcBitmap->m_bpp; + m_AlphaFlag = pSrcBitmap->m_AlphaFlag; + m_Width = pSrcBitmap->m_Width; + m_Height = pSrcBitmap->m_Height; + m_Pitch = pSrcBitmap->m_Pitch; +} + +void CFX_DIBitmap::Clear(uint32_t color) { + if (!m_pBuffer) + return; + + uint8_t* pBuffer = m_pBuffer.Get(); + switch (GetFormat()) { + case FXDIB_1bppMask: + memset(pBuffer, (color & 0xff000000) ? 0xff : 0, m_Pitch * m_Height); + break; + case FXDIB_1bppRgb: { + int index = FindPalette(color); + memset(pBuffer, index ? 0xff : 0, m_Pitch * m_Height); + break; + } + case FXDIB_8bppMask: + memset(pBuffer, color >> 24, m_Pitch * m_Height); + break; + case FXDIB_8bppRgb: { + int index = FindPalette(color); + memset(pBuffer, index, m_Pitch * m_Height); + break; + } + case FXDIB_Rgb: + case FXDIB_Rgba: { + int a; + int r; + int g; + int b; + std::tie(a, r, g, b) = ArgbDecode(color); + if (r == g && g == b) { + memset(pBuffer, r, m_Pitch * m_Height); + } else { + int byte_pos = 0; + for (int col = 0; col < m_Width; col++) { + pBuffer[byte_pos++] = b; + pBuffer[byte_pos++] = g; + pBuffer[byte_pos++] = r; + } + for (int row = 1; row < m_Height; row++) { + memcpy(pBuffer + row * m_Pitch, pBuffer, m_Pitch); + } + } + break; + } + case FXDIB_Rgb32: + case FXDIB_Argb: { + color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); +#ifdef _SKIA_SUPPORT_ + if (FXDIB_Rgb32 == GetFormat() && !IsCmykImage()) + color |= 0xFF000000; +#endif + for (int i = 0; i < m_Width; i++) + reinterpret_cast(pBuffer)[i] = color; + for (int row = 1; row < m_Height; row++) + memcpy(pBuffer + row * m_Pitch, pBuffer, m_Pitch); + break; + } + default: + break; + } +} + +bool CFX_DIBitmap::TransferBitmap(int dest_left, + int dest_top, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + if (!m_pBuffer) + return false; + + GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), + pSrcBitmap->GetHeight(), src_left, src_top, nullptr); + if (width == 0 || height == 0) + return true; + + FXDIB_Format dest_format = GetFormat(); + FXDIB_Format src_format = pSrcBitmap->GetFormat(); + if (dest_format == src_format) { + if (GetBPP() == 1) { + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = m_pBuffer.Get() + (dest_top + row) * m_Pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); + for (int col = 0; col < width; col++) { + if (src_scan[(src_left + col) / 8] & + (1 << (7 - (src_left + col) % 8))) { + dest_scan[(dest_left + col) / 8] |= 1 + << (7 - (dest_left + col) % 8); + } else { + dest_scan[(dest_left + col) / 8] &= + ~(1 << (7 - (dest_left + col) % 8)); + } + } + } + } else { + int Bpp = GetBPP() / 8; + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = + m_pBuffer.Get() + (dest_top + row) * m_Pitch + dest_left * Bpp; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; + memcpy(dest_scan, src_scan, width * Bpp); + } + } + } else { + if (m_pPalette) + return false; + + if (m_bpp == 8) + dest_format = FXDIB_8bppMask; + + uint8_t* dest_buf = + m_pBuffer.Get() + dest_top * m_Pitch + dest_left * GetBPP() / 8; + std::unique_ptr d_plt; + if (!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height, + pSrcBitmap, src_left, src_top, &d_plt)) { + return false; + } + } + return true; +} + +bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, + const RetainPtr& pSrcBitmap, + FXDIB_Channel srcChannel) { + if (!m_pBuffer) + return false; + + RetainPtr pSrcClone = pSrcBitmap; + int srcOffset; + if (srcChannel == FXDIB_Alpha) { + if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask()) + return false; + + if (pSrcBitmap->GetBPP() == 1) { + pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask); + if (!pSrcClone) + return false; + } + srcOffset = pSrcBitmap->GetFormat() == FXDIB_Argb ? 3 : 0; + } else { + if (pSrcBitmap->IsAlphaMask()) + return false; + + if (pSrcBitmap->GetBPP() < 24) { + if (pSrcBitmap->IsCmykImage()) { + pSrcClone = pSrcBitmap->CloneConvert(static_cast( + (pSrcBitmap->GetFormat() & 0xff00) | 0x20)); + } else { + pSrcClone = pSrcBitmap->CloneConvert(static_cast( + (pSrcBitmap->GetFormat() & 0xff00) | 0x18)); + } + if (!pSrcClone) + return false; + } + srcOffset = g_ChannelOffset[srcChannel]; + } + int destOffset = 0; + if (destChannel == FXDIB_Alpha) { + if (IsAlphaMask()) { + if (!ConvertFormat(FXDIB_8bppMask)) + return false; + } else { + if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) + return false; + + if (GetFormat() == FXDIB_Argb) + destOffset = 3; + } + } else { + if (IsAlphaMask()) + return false; + + if (GetBPP() < 24) { + if (HasAlpha()) { + if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) + return false; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) { +#else + } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) { +#endif + return false; + } + } + destOffset = g_ChannelOffset[destChannel]; + } + if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) { + RetainPtr pAlphaMask = pSrcClone->m_pAlphaMask; + if (pSrcClone->GetWidth() != m_Width || + pSrcClone->GetHeight() != m_Height) { + if (pAlphaMask) { + pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height, 0, nullptr); + if (!pAlphaMask) + return false; + } + } + pSrcClone = std::move(pAlphaMask); + srcOffset = 0; + } else if (pSrcClone->GetWidth() != m_Width || + pSrcClone->GetHeight() != m_Height) { + RetainPtr pSrcMatched = + pSrcClone->StretchTo(m_Width, m_Height, 0, nullptr); + if (!pSrcMatched) + return false; + + pSrcClone = std::move(pSrcMatched); + } + RetainPtr pDst(this); + if (destChannel == FXDIB_Alpha && m_pAlphaMask) { + pDst = m_pAlphaMask; + destOffset = 0; + } + int srcBytes = pSrcClone->GetBPP() / 8; + int destBytes = pDst->GetBPP() / 8; + for (int row = 0; row < m_Height; row++) { + uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset; + const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset; + for (int col = 0; col < m_Width; col++) { + *dest_pos = *src_pos; + dest_pos += destBytes; + src_pos += srcBytes; + } + } + return true; +} + +bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value) { + if (!m_pBuffer) + return false; + + int destOffset; + if (destChannel == FXDIB_Alpha) { + if (IsAlphaMask()) { + if (!ConvertFormat(FXDIB_8bppMask)) { + return false; + } + destOffset = 0; + } else { + destOffset = 0; + if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) { + return false; + } + if (GetFormat() == FXDIB_Argb) { + destOffset = 3; + } + } + } else { + if (IsAlphaMask()) { + return false; + } + if (GetBPP() < 24) { + if (HasAlpha()) { + if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) { + return false; + } +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) { +#else + } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) { +#endif + return false; + } + } + destOffset = g_ChannelOffset[destChannel]; + } + int Bpp = GetBPP() / 8; + if (Bpp == 1) { + memset(m_pBuffer.Get(), value, m_Height * m_Pitch); + return true; + } + if (destChannel == FXDIB_Alpha && m_pAlphaMask) { + memset(m_pAlphaMask->GetBuffer(), value, + m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch()); + return true; + } + for (int row = 0; row < m_Height; row++) { + uint8_t* scan_line = m_pBuffer.Get() + row * m_Pitch + destOffset; + for (int col = 0; col < m_Width; col++) { + *scan_line = value; + scan_line += Bpp; + } + } + return true; +} + +bool CFX_DIBitmap::MultiplyAlpha(const RetainPtr& pSrcBitmap) { + if (!m_pBuffer) + return false; + + ASSERT(pSrcBitmap->IsAlphaMask()); + if (!pSrcBitmap->IsAlphaMask()) + return false; + + if (!IsAlphaMask() && !HasAlpha()) + return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha); + + RetainPtr pSrcClone = pSrcBitmap.As(); + if (pSrcBitmap->GetWidth() != m_Width || + pSrcBitmap->GetHeight() != m_Height) { + pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height, 0, nullptr); + if (!pSrcClone) + return false; + } + if (IsAlphaMask()) { + if (!ConvertFormat(FXDIB_8bppMask)) + return false; + + for (int row = 0; row < m_Height; row++) { + uint8_t* dest_scan = m_pBuffer.Get() + m_Pitch * row; + uint8_t* src_scan = pSrcClone->m_pBuffer.Get() + pSrcClone->m_Pitch * row; + if (pSrcClone->GetBPP() == 1) { + for (int col = 0; col < m_Width; col++) { + if (!((1 << (7 - col % 8)) & src_scan[col / 8])) + dest_scan[col] = 0; + } + } else { + for (int col = 0; col < m_Width; col++) { + *dest_scan = (*dest_scan) * src_scan[col] / 255; + dest_scan++; + } + } + } + } else { + if (GetFormat() == FXDIB_Argb) { + if (pSrcClone->GetBPP() == 1) + return false; + + for (int row = 0; row < m_Height; row++) { + uint8_t* dest_scan = m_pBuffer.Get() + m_Pitch * row + 3; + uint8_t* src_scan = + pSrcClone->m_pBuffer.Get() + pSrcClone->m_Pitch * row; + for (int col = 0; col < m_Width; col++) { + *dest_scan = (*dest_scan) * src_scan[col] / 255; + dest_scan += 4; + } + } + } else { + m_pAlphaMask->MultiplyAlpha(pSrcClone); + } + } + return true; +} + +bool CFX_DIBitmap::MultiplyAlpha(int alpha) { + if (!m_pBuffer) + return false; + + switch (GetFormat()) { + case FXDIB_1bppMask: + if (!ConvertFormat(FXDIB_8bppMask)) { + return false; + } + MultiplyAlpha(alpha); + break; + case FXDIB_8bppMask: { + for (int row = 0; row < m_Height; row++) { + uint8_t* scan_line = m_pBuffer.Get() + row * m_Pitch; + for (int col = 0; col < m_Width; col++) { + scan_line[col] = scan_line[col] * alpha / 255; + } + } + break; + } + case FXDIB_Argb: { + for (int row = 0; row < m_Height; row++) { + uint8_t* scan_line = m_pBuffer.Get() + row * m_Pitch + 3; + for (int col = 0; col < m_Width; col++) { + *scan_line = (*scan_line) * alpha / 255; + scan_line += 4; + } + } + break; + } + default: + if (HasAlpha()) { + m_pAlphaMask->MultiplyAlpha(alpha); + } else if (IsCmykImage()) { + if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) { + return false; + } + m_pAlphaMask->MultiplyAlpha(alpha); + } else { + if (!ConvertFormat(FXDIB_Argb)) { + return false; + } + MultiplyAlpha(alpha); + } + break; + } + return true; +} + +uint32_t CFX_DIBitmap::GetPixel(int x, int y) const { + if (!m_pBuffer) + return 0; + + uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8; + switch (GetFormat()) { + case FXDIB_1bppMask: { + if ((*pos) & (1 << (7 - x % 8))) { + return 0xff000000; + } + return 0; + } + case FXDIB_1bppRgb: { + if ((*pos) & (1 << (7 - x % 8))) { + return m_pPalette ? m_pPalette.get()[1] : 0xffffffff; + } + return m_pPalette ? m_pPalette.get()[0] : 0xff000000; + } + case FXDIB_8bppMask: + return (*pos) << 24; + case FXDIB_8bppRgb: + return m_pPalette ? m_pPalette.get()[*pos] + : (0xff000000 | ((*pos) * 0x10101)); + case FXDIB_Rgb: + case FXDIB_Rgba: + case FXDIB_Rgb32: + return FXARGB_GETDIB(pos) | 0xff000000; + case FXDIB_Argb: + return FXARGB_GETDIB(pos); + default: + break; + } + return 0; +} + +void CFX_DIBitmap::SetPixel(int x, int y, uint32_t color) { + if (!m_pBuffer) + return; + + if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) + return; + + uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8; + switch (GetFormat()) { + case FXDIB_1bppMask: + if (color >> 24) { + *pos |= 1 << (7 - x % 8); + } else { + *pos &= ~(1 << (7 - x % 8)); + } + break; + case FXDIB_1bppRgb: + if (m_pPalette) { + if (color == m_pPalette.get()[1]) { + *pos |= 1 << (7 - x % 8); + } else { + *pos &= ~(1 << (7 - x % 8)); + } + } else { + if (color == 0xffffffff) { + *pos |= 1 << (7 - x % 8); + } else { + *pos &= ~(1 << (7 - x % 8)); + } + } + break; + case FXDIB_8bppMask: + *pos = (uint8_t)(color >> 24); + break; + case FXDIB_8bppRgb: { + if (m_pPalette) { + for (int i = 0; i < 256; i++) { + if (m_pPalette.get()[i] == color) { + *pos = (uint8_t)i; + return; + } + } + *pos = 0; + } else { + *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); + } + break; + } + case FXDIB_Rgb: + case FXDIB_Rgb32: { + int alpha = FXARGB_A(color); + pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255; + pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255; + pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255; + break; + } + case FXDIB_Rgba: { + pos[0] = FXARGB_B(color); + pos[1] = FXARGB_G(color); + pos[2] = FXARGB_R(color); + break; + } + case FXDIB_Argb: + FXARGB_SETDIB(pos, color); + break; + default: + break; + } +} + +void CFX_DIBitmap::DownSampleScanline(int line, + uint8_t* dest_scan, + int dest_bpp, + int dest_width, + bool bFlipX, + int clip_left, + int clip_width) const { + if (!m_pBuffer) + return; + + int src_Bpp = m_bpp / 8; + uint8_t* scanline = m_pBuffer.Get() + line * m_Pitch; + if (src_Bpp == 0) { + for (int i = 0; i < clip_width; i++) { + uint32_t dest_x = clip_left + i; + uint32_t src_x = dest_x * m_Width / dest_width; + if (bFlipX) { + src_x = m_Width - src_x - 1; + } + src_x %= m_Width; + dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0; + } + } else if (src_Bpp == 1) { + for (int i = 0; i < clip_width; i++) { + uint32_t dest_x = clip_left + i; + uint32_t src_x = dest_x * m_Width / dest_width; + if (bFlipX) { + src_x = m_Width - src_x - 1; + } + src_x %= m_Width; + int dest_pos = i; + if (m_pPalette) { + if (!IsCmykImage()) { + dest_pos *= 3; + FX_ARGB argb = m_pPalette.get()[scanline[src_x]]; + dest_scan[dest_pos] = FXARGB_B(argb); + dest_scan[dest_pos + 1] = FXARGB_G(argb); + dest_scan[dest_pos + 2] = FXARGB_R(argb); + } else { + dest_pos *= 4; + FX_CMYK cmyk = m_pPalette.get()[scanline[src_x]]; + dest_scan[dest_pos] = FXSYS_GetCValue(cmyk); + dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk); + dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk); + dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk); + } + } else { + dest_scan[dest_pos] = scanline[src_x]; + } + } + } else { + for (int i = 0; i < clip_width; i++) { + uint32_t dest_x = clip_left + i; + uint32_t src_x = + bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp + : (dest_x * m_Width / dest_width) * src_Bpp; + src_x %= m_Width * src_Bpp; + int dest_pos = i * src_Bpp; + for (int b = 0; b < src_Bpp; b++) { + dest_scan[dest_pos + b] = scanline[src_x + b]; + } + } + } +} + +void CFX_DIBitmap::ConvertRGBColorScale(uint32_t forecolor, + uint32_t backcolor) { + int fr = FXSYS_GetRValue(forecolor); + int fg = FXSYS_GetGValue(forecolor); + int fb = FXSYS_GetBValue(forecolor); + int br = FXSYS_GetRValue(backcolor); + int bg = FXSYS_GetGValue(backcolor); + int bb = FXSYS_GetBValue(backcolor); + if (m_bpp <= 8) { + if (forecolor == 0 && backcolor == 0xffffff && !m_pPalette) + return; + if (!m_pPalette) + BuildPalette(); + int size = 1 << m_bpp; + for (int i = 0; i < size; ++i) { + int gray = FXRGB2GRAY(FXARGB_R(m_pPalette.get()[i]), + FXARGB_G(m_pPalette.get()[i]), + FXARGB_B(m_pPalette.get()[i])); + m_pPalette.get()[i] = + FXARGB_MAKE(0xff, br + (fr - br) * gray / 255, + bg + (fg - bg) * gray / 255, bb + (fb - bb) * gray / 255); + } + return; + } + if (forecolor == 0 && backcolor == 0xffffff) { + for (int row = 0; row < m_Height; ++row) { + uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; + int gap = m_bpp / 8 - 2; + for (int col = 0; col < m_Width; ++col) { + int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]); + *scanline++ = gray; + *scanline++ = gray; + *scanline = gray; + scanline += gap; + } + } + return; + } + for (int row = 0; row < m_Height; ++row) { + uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; + int gap = m_bpp / 8 - 2; + for (int col = 0; col < m_Width; ++col) { + int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]); + *scanline++ = bb + (fb - bb) * gray / 255; + *scanline++ = bg + (fg - bg) * gray / 255; + *scanline = br + (fr - br) * gray / 255; + scanline += gap; + } + } +} + +void CFX_DIBitmap::ConvertCMYKColorScale(uint32_t forecolor, + uint32_t backcolor) { + int fc = FXSYS_GetCValue(forecolor); + int fm = FXSYS_GetMValue(forecolor); + int fy = FXSYS_GetYValue(forecolor); + int fk = FXSYS_GetKValue(forecolor); + int bc = FXSYS_GetCValue(backcolor); + int bm = FXSYS_GetMValue(backcolor); + int by = FXSYS_GetYValue(backcolor); + int bk = FXSYS_GetKValue(backcolor); + if (m_bpp <= 8) { + if (forecolor == 0xff && backcolor == 0 && !m_pPalette) + return; + if (!m_pPalette) + BuildPalette(); + int size = 1 << m_bpp; + for (int i = 0; i < size; ++i) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette.get()[i]), + FXSYS_GetMValue(m_pPalette.get()[i]), + FXSYS_GetYValue(m_pPalette.get()[i]), + FXSYS_GetKValue(m_pPalette.get()[i])); + int gray = 255 - FXRGB2GRAY(r, g, b); + m_pPalette.get()[i] = + CmykEncode(bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255, + by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255); + } + return; + } + if (forecolor == 0xff && backcolor == 0x00) { + for (int row = 0; row < m_Height; ++row) { + uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; + for (int col = 0; col < m_Width; ++col) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = AdobeCMYK_to_sRGB1(scanline[0], scanline[1], + scanline[2], scanline[3]); + *scanline++ = 0; + *scanline++ = 0; + *scanline++ = 0; + *scanline++ = 255 - FXRGB2GRAY(r, g, b); + } + } + return; + } + for (int row = 0; row < m_Height; ++row) { + uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; + for (int col = 0; col < m_Width; ++col) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = AdobeCMYK_to_sRGB1(scanline[0], scanline[1], + scanline[2], scanline[3]); + int gray = 255 - FXRGB2GRAY(r, g, b); + *scanline++ = bc + (fc - bc) * gray / 255; + *scanline++ = bm + (fm - bm) * gray / 255; + *scanline++ = by + (fy - by) * gray / 255; + *scanline++ = bk + (fk - bk) * gray / 255; + } + } +} + +bool CFX_DIBitmap::ConvertColorScale(uint32_t forecolor, uint32_t backcolor) { + ASSERT(!IsAlphaMask()); + if (!m_pBuffer || IsAlphaMask()) + return false; + + if (IsCmykImage()) + ConvertCMYKColorScale(forecolor, backcolor); + else + ConvertRGBColorScale(forecolor, backcolor); + return true; +} + +bool CFX_DIBitmap::CalculatePitchAndSize(int height, + int width, + FXDIB_Format format, + uint32_t* pitch, + uint32_t* size) { + if (width <= 0 || height <= 0) + return false; + + if ((INT_MAX - 31) / width < (format & 0xFF)) + return false; + + if (!*pitch) + *pitch = static_cast((width * (format & 0xff) + 31) / 32 * 4); + + if ((1 << 30) / *pitch < static_cast(height)) + return false; + + *size = *pitch * static_cast(height); + return true; +} + +bool CFX_DIBitmap::CompositeBitmap(int dest_left, + int dest_top, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top, + int blend_type, + const CFX_ClipRgn* pClipRgn, + bool bRgbByteOrder) { + if (!m_pBuffer) + return false; + + ASSERT(!pSrcBitmap->IsAlphaMask()); + ASSERT(m_bpp >= 8); + if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) { + return false; + } + GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), + pSrcBitmap->GetHeight(), src_left, src_top, pClipRgn); + if (width == 0 || height == 0) { + return true; + } + RetainPtr pClipMask; + FX_RECT clip_box; + if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { + ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); + pClipMask = pClipRgn->GetMask(); + clip_box = pClipRgn->GetBox(); + } + CFX_ScanlineCompositor compositor; + if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, + pSrcBitmap->GetPalette(), 0, blend_type, + pClipMask != nullptr, bRgbByteOrder, 0)) { + return false; + } + int dest_Bpp = m_bpp / 8; + int src_Bpp = pSrcBitmap->GetBPP() / 8; + bool bRgb = src_Bpp > 1 && !pSrcBitmap->IsCmykImage(); + RetainPtr pSrcAlphaMask = pSrcBitmap->m_pAlphaMask; + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = + m_pBuffer.Get() + (dest_top + row) * m_Pitch + dest_left * dest_Bpp; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp; + const uint8_t* src_scan_extra_alpha = + pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left + : nullptr; + uint8_t* dst_scan_extra_alpha = + m_pAlphaMask + ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left + : nullptr; + const uint8_t* clip_scan = nullptr; + if (pClipMask) { + clip_scan = pClipMask->m_pBuffer.Get() + + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + + (dest_left - clip_box.left); + } + if (bRgb) { + compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, + src_scan_extra_alpha, + dst_scan_extra_alpha); + } else { + compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, + clip_scan, src_scan_extra_alpha, + dst_scan_extra_alpha); + } + } + return true; +} + +bool CFX_DIBitmap::CompositeMask(int dest_left, + int dest_top, + int width, + int height, + const RetainPtr& pMask, + uint32_t color, + int src_left, + int src_top, + int blend_type, + const CFX_ClipRgn* pClipRgn, + bool bRgbByteOrder, + int alpha_flag) { + if (!m_pBuffer) + return false; + + ASSERT(pMask->IsAlphaMask()); + ASSERT(m_bpp >= 8); + if (!pMask->IsAlphaMask() || m_bpp < 8) + return false; + + GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), + pMask->GetHeight(), src_left, src_top, pClipRgn); + if (width == 0 || height == 0) + return true; + + int src_alpha = + (uint8_t)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); + if (src_alpha == 0) + return true; + + RetainPtr pClipMask; + FX_RECT clip_box; + if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { + ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); + pClipMask = pClipRgn->GetMask(); + clip_box = pClipRgn->GetBox(); + } + int src_bpp = pMask->GetBPP(); + int Bpp = GetBPP() / 8; + CFX_ScanlineCompositor compositor; + if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, nullptr, color, + blend_type, pClipMask != nullptr, bRgbByteOrder, + alpha_flag)) { + return false; + } + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = + m_pBuffer.Get() + (dest_top + row) * m_Pitch + dest_left * Bpp; + const uint8_t* src_scan = pMask->GetScanline(src_top + row); + uint8_t* dst_scan_extra_alpha = + m_pAlphaMask + ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left + : nullptr; + const uint8_t* clip_scan = nullptr; + if (pClipMask) { + clip_scan = pClipMask->m_pBuffer.Get() + + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + + (dest_left - clip_box.left); + } + if (src_bpp == 1) { + compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, + clip_scan, dst_scan_extra_alpha); + } else { + compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, + clip_scan, dst_scan_extra_alpha); + } + } + return true; +} + +bool CFX_DIBitmap::CompositeRect(int left, + int top, + int width, + int height, + uint32_t color, + int alpha_flag) { + if (!m_pBuffer) + return false; + + int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); + if (src_alpha == 0) + return true; + + FX_RECT rect(left, top, left + width, top + height); + rect.Intersect(0, 0, m_Width, m_Height); + if (rect.IsEmpty()) + return true; + + width = rect.Width(); + uint32_t dst_color; + if (alpha_flag >> 8) + dst_color = FXCMYK_TODIB(color); + else + dst_color = FXARGB_TODIB(color); + uint8_t* color_p = (uint8_t*)&dst_color; + if (m_bpp == 8) { + uint8_t gray = 255; + if (!IsAlphaMask()) { + if (alpha_flag >> 8) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = + AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3]); + gray = FXRGB2GRAY(r, g, b); + } else { + gray = (uint8_t)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]); + } + if (IsCmykImage()) { + gray = ~gray; + } + } + for (int row = rect.top; row < rect.bottom; row++) { + uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left; + if (src_alpha == 255) { + memset(dest_scan, gray, width); + } else { + for (int col = 0; col < width; col++) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); + dest_scan++; + } + } + } + return true; + } + if (m_bpp == 1) { + ASSERT(!IsCmykImage() && static_cast(alpha_flag >> 8) == 0); + int left_shift = rect.left % 8; + int right_shift = rect.right % 8; + int new_width = rect.right / 8 - rect.left / 8; + int index = 0; + if (m_pPalette) { + for (int i = 0; i < 2; i++) { + if (m_pPalette.get()[i] == color) + index = i; + } + } else { + index = (static_cast(color) == 0xff) ? 1 : 0; + } + for (int row = rect.top; row < rect.bottom; row++) { + uint8_t* dest_scan_top = + const_cast(GetScanline(row)) + rect.left / 8; + uint8_t* dest_scan_top_r = + const_cast(GetScanline(row)) + rect.right / 8; + uint8_t left_flag = *dest_scan_top & (255 << (8 - left_shift)); + uint8_t right_flag = *dest_scan_top_r & (255 >> right_shift); + if (new_width) { + memset(dest_scan_top + 1, index ? 255 : 0, new_width - 1); + if (!index) { + *dest_scan_top &= left_flag; + *dest_scan_top_r &= right_flag; + } else { + *dest_scan_top |= ~left_flag; + *dest_scan_top_r |= ~right_flag; + } + } else { + if (!index) { + *dest_scan_top &= left_flag | right_flag; + } else { + *dest_scan_top |= ~(left_flag | right_flag); + } + } + } + return true; + } + ASSERT(m_bpp >= 24); + if (m_bpp < 24 || (!(alpha_flag >> 8) && IsCmykImage())) + return false; + if (alpha_flag >> 8 && !IsCmykImage()) { + std::tie(color_p[2], color_p[1], color_p[0]) = + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), + FXSYS_GetYValue(color), FXSYS_GetKValue(color)); + } + if (!IsCmykImage()) + color_p[3] = static_cast(src_alpha); + int Bpp = m_bpp / 8; + bool bAlpha = HasAlpha(); + bool bArgb = GetFormat() == FXDIB_Argb; + if (src_alpha == 255) { + for (int row = rect.top; row < rect.bottom; row++) { + uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left * Bpp; + uint8_t* dest_scan_alpha = + m_pAlphaMask ? (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left + : nullptr; + if (dest_scan_alpha) { + memset(dest_scan_alpha, 0xff, width); + } + if (Bpp == 4) { + uint32_t* scan = (uint32_t*)dest_scan; + for (int col = 0; col < width; col++) { + *scan++ = dst_color; + } + } else { + for (int col = 0; col < width; col++) { + *dest_scan++ = color_p[0]; + *dest_scan++ = color_p[1]; + *dest_scan++ = color_p[2]; + } + } + } + return true; + } + for (int row = rect.top; row < rect.bottom; row++) { + uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left * Bpp; + if (bAlpha) { + if (bArgb) { + for (int col = 0; col < width; col++) { + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], + color_p[1], color_p[0])); + dest_scan += 4; + continue; + } + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio); + dest_scan++; + *dest_scan++ = dest_alpha; + } + } else { + uint8_t* dest_scan_alpha = + (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left; + for (int col = 0; col < width; col++) { + uint8_t back_alpha = *dest_scan_alpha; + if (back_alpha == 0) { + *dest_scan_alpha++ = src_alpha; + memcpy(dest_scan, color_p, Bpp); + dest_scan += Bpp; + continue; + } + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_scan_alpha++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + for (int comps = 0; comps < Bpp; comps++) { + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio); + dest_scan++; + } + } + } + } else { + for (int col = 0; col < width; col++) { + for (int comps = 0; comps < Bpp; comps++) { + if (comps == 3) { + *dest_scan++ = 255; + continue; + } + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha); + dest_scan++; + } + } + } + } + return true; +} + +bool CFX_DIBitmap::ConvertFormat(FXDIB_Format dest_format) { + FXDIB_Format src_format = GetFormat(); + if (dest_format == src_format) + return true; + + if (dest_format == FXDIB_8bppMask && src_format == FXDIB_8bppRgb && + !m_pPalette) { + m_AlphaFlag = 1; + return true; + } + if (dest_format == FXDIB_Argb && src_format == FXDIB_Rgb32) { + m_AlphaFlag = 2; + for (int row = 0; row < m_Height; row++) { + uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch + 3; + for (int col = 0; col < m_Width; col++) { + *scanline = 0xff; + scanline += 4; + } + } + return true; + } + int dest_bpp = dest_format & 0xff; + int dest_pitch = (dest_bpp * m_Width + 31) / 32 * 4; + std::unique_ptr dest_buf( + FX_TryAlloc(uint8_t, dest_pitch * m_Height + 4)); + if (!dest_buf) + return false; + + RetainPtr pAlphaMask; + if (dest_format == FXDIB_Argb) { + memset(dest_buf.get(), 0xff, dest_pitch * m_Height + 4); + if (m_pAlphaMask) { + for (int row = 0; row < m_Height; row++) { + uint8_t* pDstScanline = dest_buf.get() + row * dest_pitch + 3; + const uint8_t* pSrcScanline = m_pAlphaMask->GetScanline(row); + for (int col = 0; col < m_Width; col++) { + *pDstScanline = *pSrcScanline++; + pDstScanline += 4; + } + } + } + } else if (dest_format & 0x0200) { + if (src_format == FXDIB_Argb) { + pAlphaMask = CloneAlphaMask(); + if (!pAlphaMask) + return false; + } else { + if (!m_pAlphaMask) { + if (!BuildAlphaMask()) + return false; + pAlphaMask = std::move(m_pAlphaMask); + } else { + pAlphaMask = m_pAlphaMask; + } + } + } + bool ret = false; + RetainPtr holder(this); + std::unique_ptr pal_8bpp; + ret = ConvertBuffer(dest_format, dest_buf.get(), dest_pitch, m_Width, + m_Height, holder, 0, 0, &pal_8bpp); + if (!ret) + return false; + + m_pAlphaMask = pAlphaMask; + m_pPalette = std::move(pal_8bpp); + m_pBuffer = std::move(dest_buf); + m_bpp = static_cast(dest_format); + m_AlphaFlag = static_cast(dest_format >> 8); + m_Pitch = dest_pitch; + return true; +} diff --git a/core/fxge/dib/cfx_dibitmap.h b/core/fxge/dib/cfx_dibitmap.h new file mode 100644 index 0000000000000000000000000000000000000000..7240829773965e62ae555035354c8b2c09d9e73d --- /dev/null +++ b/core/fxge/dib/cfx_dibitmap.h @@ -0,0 +1,129 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_DIBITMAP_H_ +#define CORE_FXGE_DIB_CFX_DIBITMAP_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibsource.h" +#include "third_party/base/stl_util.h" + +class CFX_DIBitmap : public CFX_DIBSource { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + ~CFX_DIBitmap() override; + + bool Create(int width, + int height, + FXDIB_Format format, + uint8_t* pBuffer = nullptr, + uint32_t pitch = 0); + + bool Copy(const RetainPtr& pSrc); + + // CFX_DIBSource + uint8_t* GetBuffer() const override; + const uint8_t* GetScanline(int line) const override; + void DownSampleScanline(int line, + uint8_t* dest_scan, + int dest_bpp, + int dest_width, + bool bFlipX, + int clip_left, + int clip_width) const override; + + void TakeOver(RetainPtr&& pSrcBitmap); + bool ConvertFormat(FXDIB_Format format); + void Clear(uint32_t color); + + uint32_t GetPixel(int x, int y) const; + void SetPixel(int x, int y, uint32_t color); + + bool LoadChannel(FXDIB_Channel destChannel, + const RetainPtr& pSrcBitmap, + FXDIB_Channel srcChannel); + bool LoadChannel(FXDIB_Channel destChannel, int value); + + bool MultiplyAlpha(int alpha); + bool MultiplyAlpha(const RetainPtr& pAlphaMask); + + bool TransferBitmap(int dest_left, + int dest_top, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top); + + bool CompositeBitmap(int dest_left, + int dest_top, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top, + int blend_type = FXDIB_BLEND_NORMAL, + const CFX_ClipRgn* pClipRgn = nullptr, + bool bRgbByteOrder = false); + + bool CompositeMask(int dest_left, + int dest_top, + int width, + int height, + const RetainPtr& pMask, + uint32_t color, + int src_left, + int src_top, + int blend_type = FXDIB_BLEND_NORMAL, + const CFX_ClipRgn* pClipRgn = nullptr, + bool bRgbByteOrder = false, + int alpha_flag = 0); + + bool CompositeRect(int dest_left, + int dest_top, + int width, + int height, + uint32_t color, + int alpha_flag); + + bool ConvertColorScale(uint32_t forecolor, uint32_t backcolor); + + static bool CalculatePitchAndSize(int height, + int width, + FXDIB_Format format, + uint32_t* pitch, + uint32_t* size); + +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ + void PreMultiply(); +#endif +#if defined _SKIA_SUPPORT_PATHS_ + void UnPreMultiply(); +#endif + + protected: + CFX_DIBitmap(); + CFX_DIBitmap(const CFX_DIBitmap& src); + +#if defined _SKIA_SUPPORT_PATHS_ + enum class Format { kCleared, kPreMultiplied, kUnPreMultiplied }; +#endif + + MaybeOwned m_pBuffer; +#if defined _SKIA_SUPPORT_PATHS_ + Format m_nFormat; +#endif + + private: + void ConvertRGBColorScale(uint32_t forecolor, uint32_t backcolor); + void ConvertCMYKColorScale(uint32_t forecolor, uint32_t backcolor); +}; + +#endif // CORE_FXGE_DIB_CFX_DIBITMAP_H_ diff --git a/core/fxge/dib/cfx_dibsource.cpp b/core/fxge/dib/cfx_dibsource.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eda6d9efda4128e4be1935a9cd022bb752c0c087 --- /dev/null +++ b/core/fxge/dib/cfx_dibsource.cpp @@ -0,0 +1,1229 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_dibsource.h" + +#include +#include +#include +#include + +#include "core/fxcodec/fx_codec.h" +#include "core/fxge/cfx_cliprgn.h" +#include "core/fxge/dib/cfx_bitmapstorer.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/cfx_imagestretcher.h" +#include "core/fxge/dib/cfx_imagetransformer.h" +#include "third_party/base/logging.h" +#include "third_party/base/ptr_util.h" + +namespace { + +class CFX_Palette { + public: + explicit CFX_Palette(const RetainPtr& pBitmap); + ~CFX_Palette(); + + const uint32_t* GetPalette() { return m_Palette.data(); } + const std::pair* GetLuts() const { return m_Luts.data(); } + int32_t GetLutCount() const { return m_lut; } + void SetAmountLut(int row, uint32_t value) { m_Luts[row].first = value; } + + private: + std::vector m_Palette; + // (Amount, Color) pairs + std::vector> m_Luts; + int m_lut; +}; + +void ColorDecode(uint32_t pal_v, uint8_t* r, uint8_t* g, uint8_t* b) { + *r = static_cast((pal_v & 0xf00) >> 4); + *g = static_cast(pal_v & 0x0f0); + *b = static_cast((pal_v & 0x00f) << 4); +} + +void Obtain_Pal(std::pair* luts, + uint32_t* dest_pal, + uint32_t lut) { + uint32_t lut_1 = lut - 1; + for (int row = 0; row < 256; ++row) { + int lut_offset = lut_1 - row; + if (lut_offset < 0) + lut_offset += 256; + uint32_t color = luts[lut_offset].second; + uint8_t r; + uint8_t g; + uint8_t b; + ColorDecode(color, &r, &g, &b); + dest_pal[row] = (static_cast(r) << 16) | + (static_cast(g) << 8) | b | 0xff000000; + luts[lut_offset].first = row; + } +} + +CFX_Palette::CFX_Palette(const RetainPtr& pBitmap) + : m_Palette(256), m_Luts(4096), m_lut(0) { + int bpp = pBitmap->GetBPP() / 8; + int width = pBitmap->GetWidth(); + int height = pBitmap->GetHeight(); + for (int row = 0; row < height; ++row) { + const uint8_t* scan_line = pBitmap->GetScanline(row); + for (int col = 0; col < width; ++col) { + const uint8_t* src_port = scan_line + col * bpp; + uint32_t b = src_port[0] & 0xf0; + uint32_t g = src_port[1] & 0xf0; + uint32_t r = src_port[2] & 0xf0; + uint32_t index = (r << 4) + g + (b >> 4); + ++m_Luts[index].first; + } + } + // Move non-zeros to the front and count them + for (int row = 0; row < 4096; ++row) { + if (m_Luts[row].first != 0) { + m_Luts[m_lut].first = m_Luts[row].first; + m_Luts[m_lut].second = row; + ++m_lut; + } + } + std::sort(m_Luts.begin(), m_Luts.begin() + m_lut, + [](const std::pair& arg1, + const std::pair& arg2) { + return arg1.first < arg2.first; + }); + Obtain_Pal(m_Luts.data(), m_Palette.data(), m_lut); +} + +CFX_Palette::~CFX_Palette() {} + +void ConvertBuffer_1bppMask2Gray(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + uint8_t set_gray, reset_gray; + set_gray = 0xff; + reset_gray = 0x00; + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + memset(dest_scan, reset_gray, width); + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); + for (int col = src_left; col < src_left + width; ++col) { + if (src_scan[col / 8] & (1 << (7 - col % 8))) + *dest_scan = set_gray; + ++dest_scan; + } + } +} + +void ConvertBuffer_8bppMask2Gray(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; + memcpy(dest_scan, src_scan, width); + } +} + +void ConvertBuffer_1bppPlt2Gray(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + uint32_t* src_plt = pSrcBitmap->GetPalette(); + uint8_t gray[2]; + uint8_t reset_r; + uint8_t reset_g; + uint8_t reset_b; + uint8_t set_r; + uint8_t set_g; + uint8_t set_b; + if (pSrcBitmap->IsCmykImage()) { + std::tie(reset_r, reset_g, reset_b) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]), + FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0])); + std::tie(set_r, set_g, set_b) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]), + FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1])); + } else { + reset_r = FXARGB_R(src_plt[0]); + reset_g = FXARGB_G(src_plt[0]); + reset_b = FXARGB_B(src_plt[0]); + set_r = FXARGB_R(src_plt[1]); + set_g = FXARGB_G(src_plt[1]); + set_b = FXARGB_B(src_plt[1]); + } + gray[0] = FXRGB2GRAY(reset_r, reset_g, reset_b); + gray[1] = FXRGB2GRAY(set_r, set_g, set_b); + + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + memset(dest_scan, gray[0], width); + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); + for (int col = src_left; col < src_left + width; ++col) { + if (src_scan[col / 8] & (1 << (7 - col % 8))) + *dest_scan = gray[1]; + ++dest_scan; + } + } +} + +void ConvertBuffer_8bppPlt2Gray(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + uint32_t* src_plt = pSrcBitmap->GetPalette(); + uint8_t gray[256]; + if (pSrcBitmap->IsCmykImage()) { + uint8_t r; + uint8_t g; + uint8_t b; + for (size_t i = 0; i < FX_ArraySize(gray); ++i) { + std::tie(r, g, b) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]), + FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i])); + gray[i] = FXRGB2GRAY(r, g, b); + } + } else { + for (size_t i = 0; i < FX_ArraySize(gray); ++i) { + gray[i] = FXRGB2GRAY(FXARGB_R(src_plt[i]), FXARGB_G(src_plt[i]), + FXARGB_B(src_plt[i])); + } + } + + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; + for (int col = 0; col < width; ++col) + *dest_scan++ = gray[*src_scan++]; + } +} + +void ConvertBuffer_RgbOrCmyk2Gray(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + int Bpp = pSrcBitmap->GetBPP() / 8; + if (pSrcBitmap->IsCmykImage()) { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * 4; + for (int col = 0; col < width; ++col) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(static_cast(src_scan[0])), + FXSYS_GetMValue(static_cast(src_scan[1])), + FXSYS_GetYValue(static_cast(src_scan[2])), + FXSYS_GetKValue(static_cast(src_scan[3]))); + *dest_scan++ = FXRGB2GRAY(r, g, b); + src_scan += 4; + } + } + } else { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; + for (int col = 0; col < width; ++col) { + *dest_scan++ = FXRGB2GRAY(src_scan[2], src_scan[1], src_scan[0]); + src_scan += Bpp; + } + } + } +} + +void ConvertBuffer_IndexCopy(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + if (pSrcBitmap->GetBPP() == 1) { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + // Set all destination pixels to be white initially. + memset(dest_scan, 255, width); + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); + for (int col = src_left; col < src_left + width; ++col) { + // If the source bit is set, then set the destination pixel to be black. + if (src_scan[col / 8] & (1 << (7 - col % 8))) + *dest_scan = 0; + + ++dest_scan; + } + } + } else { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left; + memcpy(dest_scan, src_scan, width); + } + } +} + +void ConvertBuffer_Plt2PltRgb8(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top, + uint32_t* dst_plt) { + ConvertBuffer_IndexCopy(dest_buf, dest_pitch, width, height, pSrcBitmap, + src_left, src_top); + uint32_t* src_plt = pSrcBitmap->GetPalette(); + int plt_size = pSrcBitmap->GetPaletteSize(); + if (pSrcBitmap->IsCmykImage()) { + for (int i = 0; i < plt_size; ++i) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]), + FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i])); + dst_plt[i] = FXARGB_MAKE(0xff, r, g, b); + } + } else { + memcpy(dst_plt, src_plt, plt_size * 4); + } +} + +void ConvertBuffer_Rgb2PltRgb8(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top, + uint32_t* dst_plt) { + int bpp = pSrcBitmap->GetBPP() / 8; + CFX_Palette palette(pSrcBitmap); + const std::pair* Luts = palette.GetLuts(); + int lut = palette.GetLutCount(); + const uint32_t* pal = palette.GetPalette(); + if (lut > 256) { + int err; + int min_err; + int lut_256 = lut - 256; + for (int row = 0; row < lut_256; ++row) { + min_err = 1000000; + uint8_t r; + uint8_t g; + uint8_t b; + ColorDecode(Luts[row].second, &r, &g, &b); + uint32_t clrindex = 0; + for (int col = 0; col < 256; ++col) { + uint32_t p_color = pal[col]; + int d_r = r - static_cast(p_color >> 16); + int d_g = g - static_cast(p_color >> 8); + int d_b = b - static_cast(p_color); + err = d_r * d_r + d_g * d_g + d_b * d_b; + if (err < min_err) { + min_err = err; + clrindex = col; + } + } + palette.SetAmountLut(row, clrindex); + } + } + int32_t lut_1 = lut - 1; + for (int row = 0; row < height; ++row) { + uint8_t* src_scan = + const_cast(pSrcBitmap->GetScanline(src_top + row)) + src_left; + uint8_t* dest_scan = dest_buf + row * dest_pitch; + for (int col = 0; col < width; ++col) { + uint8_t* src_port = src_scan + col * bpp; + int r = src_port[2] & 0xf0; + int g = src_port[1] & 0xf0; + int b = src_port[0] & 0xf0; + uint32_t clrindex = (r << 4) + g + (b >> 4); + for (int i = lut_1; i >= 0; --i) + if (clrindex == Luts[i].second) { + *(dest_scan + col) = static_cast(Luts[i].first); + break; + } + } + } + memcpy(dst_plt, pal, sizeof(uint32_t) * 256); +} + +void ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format, + uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + int comps = (dst_format & 0xff) / 8; + uint8_t set_gray, reset_gray; + set_gray = 0xff; + reset_gray = 0x00; + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); + for (int col = src_left; col < src_left + width; ++col) { + if (src_scan[col / 8] & (1 << (7 - col % 8))) { + dest_scan[0] = set_gray; + dest_scan[1] = set_gray; + dest_scan[2] = set_gray; + } else { + dest_scan[0] = reset_gray; + dest_scan[1] = reset_gray; + dest_scan[2] = reset_gray; + } + dest_scan += comps; + } + } +} + +void ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format, + uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + int comps = (dst_format & 0xff) / 8; + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; + uint8_t src_pixel; + for (int col = 0; col < width; ++col) { + src_pixel = *src_scan++; + *dest_scan++ = src_pixel; + *dest_scan++ = src_pixel; + *dest_scan = src_pixel; + dest_scan += comps - 2; + } + } +} + +void ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format, + uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + int comps = (dst_format & 0xff) / 8; + uint32_t* src_plt = pSrcBitmap->GetPalette(); + uint32_t plt[2]; + uint8_t* bgr_ptr = reinterpret_cast(plt); + if (pSrcBitmap->IsCmykImage()) { + plt[0] = FXCMYK_TODIB(src_plt[0]); + plt[1] = FXCMYK_TODIB(src_plt[1]); + } else { + bgr_ptr[0] = FXARGB_B(src_plt[0]); + bgr_ptr[1] = FXARGB_G(src_plt[0]); + bgr_ptr[2] = FXARGB_R(src_plt[0]); + bgr_ptr[3] = FXARGB_B(src_plt[1]); + bgr_ptr[4] = FXARGB_G(src_plt[1]); + bgr_ptr[5] = FXARGB_R(src_plt[1]); + } + + if (pSrcBitmap->IsCmykImage()) { + std::tie(bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]), + FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0])); + std::tie(bgr_ptr[5], bgr_ptr[4], bgr_ptr[3]) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]), + FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1])); + } + + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); + for (int col = src_left; col < src_left + width; ++col) { + if (src_scan[col / 8] & (1 << (7 - col % 8))) { + *dest_scan++ = bgr_ptr[3]; + *dest_scan++ = bgr_ptr[4]; + *dest_scan = bgr_ptr[5]; + } else { + *dest_scan++ = bgr_ptr[0]; + *dest_scan++ = bgr_ptr[1]; + *dest_scan = bgr_ptr[2]; + } + dest_scan += comps - 2; + } + } +} + +void ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format, + uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + int comps = (dst_format & 0xff) / 8; + uint32_t* src_plt = pSrcBitmap->GetPalette(); + uint32_t plt[256]; + uint8_t* bgr_ptr = reinterpret_cast(plt); + if (!pSrcBitmap->IsCmykImage()) { + for (int i = 0; i < 256; ++i) { + *bgr_ptr++ = FXARGB_B(src_plt[i]); + *bgr_ptr++ = FXARGB_G(src_plt[i]); + *bgr_ptr++ = FXARGB_R(src_plt[i]); + } + bgr_ptr = reinterpret_cast(plt); + } + + if (pSrcBitmap->IsCmykImage()) { + for (int i = 0; i < 256; ++i) { + std::tie(bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]) = AdobeCMYK_to_sRGB1( + FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]), + FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i])); + bgr_ptr += 3; + } + bgr_ptr = reinterpret_cast(plt); + } + + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; + for (int col = 0; col < width; ++col) { + uint8_t* src_pixel = bgr_ptr + 3 * (*src_scan++); + *dest_scan++ = *src_pixel++; + *dest_scan++ = *src_pixel++; + *dest_scan = *src_pixel++; + dest_scan += comps - 2; + } + } +} + +void ConvertBuffer_24bppRgb2Rgb24(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * 3; + memcpy(dest_scan, src_scan, width * 3); + } +} + +void ConvertBuffer_32bppRgb2Rgb24(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * 4; + for (int col = 0; col < width; ++col) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + ++src_scan; + } + } +} + +void ConvertBuffer_Rgb2Rgb32(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + int comps = pSrcBitmap->GetBPP() / 8; + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * comps; + for (int col = 0; col < width; ++col) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + ++dest_scan; + src_scan += comps - 3; + } + } +} + +void ConvertBuffer_32bppCmyk2Rgb32(uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top) { + for (int row = 0; row < height; ++row) { + uint8_t* dest_scan = dest_buf + row * dest_pitch; + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row) + src_left * 4; + for (int col = 0; col < width; ++col) { + std::tie(dest_scan[2], dest_scan[1], dest_scan[0]) = AdobeCMYK_to_sRGB1( + src_scan[0], src_scan[1], src_scan[2], src_scan[3]); + dest_scan += 4; + src_scan += 4; + } + } +} + +} // namespace + +CFX_DIBSource::CFX_DIBSource() + : m_Width(0), m_Height(0), m_bpp(0), m_AlphaFlag(0), m_Pitch(0) {} + +CFX_DIBSource::~CFX_DIBSource() {} + +uint8_t* CFX_DIBSource::GetBuffer() const { + return nullptr; +} + +bool CFX_DIBSource::SkipToScanline(int line, IFX_PauseIndicator* pPause) const { + return false; +} + +RetainPtr CFX_DIBSource::Clone(const FX_RECT* pClip) const { + FX_RECT rect(0, 0, m_Width, m_Height); + if (pClip) { + rect.Intersect(*pClip); + if (rect.IsEmpty()) + return nullptr; + } + auto pNewBitmap = pdfium::MakeRetain(); + if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat())) + return nullptr; + + pNewBitmap->SetPalette(m_pPalette.get()); + pNewBitmap->SetAlphaMask(m_pAlphaMask, pClip); + if (GetBPP() == 1 && rect.left % 8 != 0) { + int left_shift = rect.left % 32; + int right_shift = 32 - left_shift; + int dword_count = pNewBitmap->m_Pitch / 4; + for (int row = rect.top; row < rect.bottom; ++row) { + uint32_t* src_scan = (uint32_t*)GetScanline(row) + rect.left / 32; + uint32_t* dest_scan = (uint32_t*)pNewBitmap->GetScanline(row - rect.top); + for (int i = 0; i < dword_count; ++i) { + dest_scan[i] = + (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift); + } + } + } else { + int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8; + if (m_Pitch < static_cast(copy_len)) + copy_len = m_Pitch; + + for (int row = rect.top; row < rect.bottom; ++row) { + const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8; + uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top); + memcpy(dest_scan, src_scan, copy_len); + } + } + return pNewBitmap; +} + +void CFX_DIBSource::BuildPalette() { + if (m_pPalette) + return; + + if (GetBPP() == 1) { + m_pPalette.reset(FX_Alloc(uint32_t, 2)); + if (IsCmykImage()) { + m_pPalette.get()[0] = 0xff; + m_pPalette.get()[1] = 0; + } else { + m_pPalette.get()[0] = 0xff000000; + m_pPalette.get()[1] = 0xffffffff; + } + } else if (GetBPP() == 8) { + m_pPalette.reset(FX_Alloc(uint32_t, 256)); + if (IsCmykImage()) { + for (int i = 0; i < 256; ++i) + m_pPalette.get()[i] = 0xff - i; + } else { + for (int i = 0; i < 256; ++i) + m_pPalette.get()[i] = 0xff000000 | (i * 0x10101); + } + } +} + +bool CFX_DIBSource::BuildAlphaMask() { + if (m_pAlphaMask) + return true; + + m_pAlphaMask = pdfium::MakeRetain(); + if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) { + m_pAlphaMask = nullptr; + return false; + } + memset(m_pAlphaMask->GetBuffer(), 0xff, + m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch()); + return true; +} + +uint32_t CFX_DIBSource::GetPaletteArgb(int index) const { + ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask()); + if (m_pPalette) + return m_pPalette.get()[index]; + + if (IsCmykImage()) { + if (GetBPP() == 1) + return index ? 0 : 0xff; + + return 0xff - index; + } + if (GetBPP() == 1) + return index ? 0xffffffff : 0xff000000; + + return index * 0x10101 | 0xff000000; +} + +void CFX_DIBSource::SetPaletteArgb(int index, uint32_t color) { + ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask()); + if (!m_pPalette) { + BuildPalette(); + } + m_pPalette.get()[index] = color; +} + +int CFX_DIBSource::FindPalette(uint32_t color) const { + ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask()); + if (!m_pPalette) { + if (IsCmykImage()) { + if (GetBPP() == 1) + return (static_cast(color) == 0xff) ? 0 : 1; + + return 0xff - static_cast(color); + } + if (GetBPP() == 1) + return (static_cast(color) == 0xff) ? 1 : 0; + + return static_cast(color); + } + int palsize = (1 << GetBPP()); + for (int i = 0; i < palsize; ++i) { + if (m_pPalette.get()[i] == color) + return i; + } + return -1; +} + +void CFX_DIBSource::GetOverlapRect(int& dest_left, + int& dest_top, + int& width, + int& height, + int src_width, + int src_height, + int& src_left, + int& src_top, + const CFX_ClipRgn* pClipRgn) { + if (width == 0 || height == 0) + return; + + ASSERT(width > 0 && height > 0); + if (dest_left > m_Width || dest_top > m_Height) { + width = 0; + height = 0; + return; + } + int x_offset = dest_left - src_left; + int y_offset = dest_top - src_top; + FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height); + FX_RECT src_bound(0, 0, src_width, src_height); + src_rect.Intersect(src_bound); + FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset, + src_rect.right + x_offset, src_rect.bottom + y_offset); + FX_RECT dest_bound(0, 0, m_Width, m_Height); + dest_rect.Intersect(dest_bound); + if (pClipRgn) + dest_rect.Intersect(pClipRgn->GetBox()); + dest_left = dest_rect.left; + dest_top = dest_rect.top; + src_left = dest_left - x_offset; + src_top = dest_top - y_offset; + width = dest_rect.right - dest_rect.left; + height = dest_rect.bottom - dest_rect.top; +} + +void CFX_DIBSource::SetPalette(const uint32_t* pSrc) { + static const uint32_t kPaletteSize = 256; + if (!pSrc || GetBPP() > 8) { + m_pPalette.reset(); + return; + } + uint32_t pal_size = 1 << GetBPP(); + if (!m_pPalette) + m_pPalette.reset(FX_Alloc(uint32_t, pal_size)); + pal_size = std::min(pal_size, kPaletteSize); + memcpy(m_pPalette.get(), pSrc, pal_size * sizeof(uint32_t)); +} + +void CFX_DIBSource::GetPalette(uint32_t* pal, int alpha) const { + ASSERT(GetBPP() <= 8 && !IsCmykImage()); + if (GetBPP() == 1) { + pal[0] = ((m_pPalette ? m_pPalette.get()[0] : 0xff000000) & 0xffffff) | + (alpha << 24); + pal[1] = ((m_pPalette ? m_pPalette.get()[1] : 0xffffffff) & 0xffffff) | + (alpha << 24); + return; + } + if (m_pPalette) { + for (int i = 0; i < 256; ++i) + pal[i] = (m_pPalette.get()[i] & 0x00ffffff) | (alpha << 24); + } else { + for (int i = 0; i < 256; ++i) + pal[i] = (i * 0x10101) | (alpha << 24); + } +} + +RetainPtr CFX_DIBSource::CloneAlphaMask() const { + ASSERT(GetFormat() == FXDIB_Argb); + FX_RECT rect(0, 0, m_Width, m_Height); + auto pMask = pdfium::MakeRetain(); + if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask)) + return nullptr; + + for (int row = rect.top; row < rect.bottom; ++row) { + const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3; + uint8_t* dest_scan = + const_cast(pMask->GetScanline(row - rect.top)); + for (int col = rect.left; col < rect.right; ++col) { + *dest_scan++ = *src_scan; + src_scan += 4; + } + } + return pMask; +} + +bool CFX_DIBSource::SetAlphaMask(const RetainPtr& pAlphaMask, + const FX_RECT* pClip) { + if (!HasAlpha() || GetFormat() == FXDIB_Argb) + return false; + + if (!pAlphaMask) { + m_pAlphaMask->Clear(0xff000000); + return true; + } + FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height); + if (pClip) { + rect.Intersect(*pClip); + if (rect.IsEmpty() || rect.Width() != m_Width || + rect.Height() != m_Height) { + return false; + } + } else { + if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height) + return false; + } + for (int row = 0; row < m_Height; ++row) { + memcpy(const_cast(m_pAlphaMask->GetScanline(row)), + pAlphaMask->GetScanline(row + rect.top) + rect.left, + m_pAlphaMask->m_Pitch); + } + return true; +} + +RetainPtr CFX_DIBSource::FlipImage(bool bXFlip, + bool bYFlip) const { + auto pFlipped = pdfium::MakeRetain(); + if (!pFlipped->Create(m_Width, m_Height, GetFormat())) + return nullptr; + + pFlipped->SetPalette(m_pPalette.get()); + uint8_t* pDestBuffer = pFlipped->GetBuffer(); + int Bpp = m_bpp / 8; + for (int row = 0; row < m_Height; ++row) { + const uint8_t* src_scan = GetScanline(row); + uint8_t* dest_scan = + pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row); + if (!bXFlip) { + memcpy(dest_scan, src_scan, m_Pitch); + continue; + } + if (m_bpp == 1) { + memset(dest_scan, 0, m_Pitch); + for (int col = 0; col < m_Width; ++col) + if (src_scan[col / 8] & (1 << (7 - col % 8))) { + int dest_col = m_Width - col - 1; + dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8)); + } + } else { + dest_scan += (m_Width - 1) * Bpp; + if (Bpp == 1) { + for (int col = 0; col < m_Width; ++col) { + *dest_scan = *src_scan; + --dest_scan; + ++src_scan; + } + } else if (Bpp == 3) { + for (int col = 0; col < m_Width; ++col) { + dest_scan[0] = src_scan[0]; + dest_scan[1] = src_scan[1]; + dest_scan[2] = src_scan[2]; + dest_scan -= 3; + src_scan += 3; + } + } else { + ASSERT(Bpp == 4); + for (int col = 0; col < m_Width; ++col) { + *(uint32_t*)dest_scan = *(uint32_t*)src_scan; + dest_scan -= 4; + src_scan += 4; + } + } + } + } + if (m_pAlphaMask) { + pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer(); + uint32_t dest_pitch = pFlipped->m_pAlphaMask->GetPitch(); + for (int row = 0; row < m_Height; ++row) { + const uint8_t* src_scan = m_pAlphaMask->GetScanline(row); + uint8_t* dest_scan = + pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row); + if (!bXFlip) { + memcpy(dest_scan, src_scan, dest_pitch); + continue; + } + dest_scan += (m_Width - 1); + for (int col = 0; col < m_Width; ++col) { + *dest_scan = *src_scan; + --dest_scan; + ++src_scan; + } + } + } + return pFlipped; +} + +RetainPtr CFX_DIBSource::CloneConvert(FXDIB_Format dest_format) { + if (dest_format == GetFormat()) + return Clone(nullptr); + + auto pClone = pdfium::MakeRetain(); + if (!pClone->Create(m_Width, m_Height, dest_format)) + return nullptr; + + RetainPtr pSrcAlpha; + if (HasAlpha()) { + if (GetFormat() == FXDIB_Argb) + pSrcAlpha = CloneAlphaMask(); + else + pSrcAlpha = m_pAlphaMask; + + if (!pSrcAlpha) + return nullptr; + } + bool ret = true; + if (dest_format & 0x0200) { + if (dest_format == FXDIB_Argb) { + ret = pSrcAlpha ? pClone->LoadChannel(FXDIB_Alpha, pSrcAlpha, FXDIB_Alpha) + : pClone->LoadChannel(FXDIB_Alpha, 0xff); + } else { + ret = pClone->SetAlphaMask(pSrcAlpha, nullptr); + } + } + if (!ret) + return nullptr; + + RetainPtr holder(this); + std::unique_ptr pal_8bpp; + if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(), + m_Width, m_Height, holder, 0, 0, &pal_8bpp)) { + return nullptr; + } + if (pal_8bpp) + pClone->SetPalette(pal_8bpp.get()); + + return pClone; +} + +RetainPtr CFX_DIBSource::SwapXY(bool bXFlip, bool bYFlip) const { + FX_RECT dest_clip(0, 0, m_Height, m_Width); + if (dest_clip.IsEmpty()) + return nullptr; + + auto pTransBitmap = pdfium::MakeRetain(); + int result_height = dest_clip.Height(); + int result_width = dest_clip.Width(); + if (!pTransBitmap->Create(result_width, result_height, GetFormat())) + return nullptr; + + pTransBitmap->SetPalette(m_pPalette.get()); + int dest_pitch = pTransBitmap->GetPitch(); + uint8_t* dest_buf = pTransBitmap->GetBuffer(); + int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left; + int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right; + int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top; + int col_end = bYFlip ? m_Width - dest_clip.top : dest_clip.bottom; + if (GetBPP() == 1) { + memset(dest_buf, 0xff, dest_pitch * result_height); + for (int row = row_start; row < row_end; ++row) { + const uint8_t* src_scan = GetScanline(row); + int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) - + dest_clip.left; + uint8_t* dest_scan = dest_buf; + if (bYFlip) + dest_scan += (result_height - 1) * dest_pitch; + int dest_step = bYFlip ? -dest_pitch : dest_pitch; + for (int col = col_start; col < col_end; ++col) { + if (!(src_scan[col / 8] & (1 << (7 - col % 8)))) + dest_scan[dest_col / 8] &= ~(1 << (7 - dest_col % 8)); + dest_scan += dest_step; + } + } + } else { + int nBytes = GetBPP() / 8; + int dest_step = bYFlip ? -dest_pitch : dest_pitch; + if (nBytes == 3) + dest_step -= 2; + for (int row = row_start; row < row_end; ++row) { + int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) - + dest_clip.left; + uint8_t* dest_scan = dest_buf + dest_col * nBytes; + if (bYFlip) + dest_scan += (result_height - 1) * dest_pitch; + if (nBytes == 4) { + uint32_t* src_scan = (uint32_t*)GetScanline(row) + col_start; + for (int col = col_start; col < col_end; ++col) { + *(uint32_t*)dest_scan = *src_scan++; + dest_scan += dest_step; + } + } else { + const uint8_t* src_scan = GetScanline(row) + col_start * nBytes; + if (nBytes == 1) { + for (int col = col_start; col < col_end; ++col) { + *dest_scan = *src_scan++; + dest_scan += dest_step; + } + } else { + for (int col = col_start; col < col_end; ++col) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan = *src_scan++; + dest_scan += dest_step; + } + } + } + } + } + if (m_pAlphaMask) { + dest_pitch = pTransBitmap->m_pAlphaMask->GetPitch(); + dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer(); + int dest_step = bYFlip ? -dest_pitch : dest_pitch; + for (int row = row_start; row < row_end; ++row) { + int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) - + dest_clip.left; + uint8_t* dest_scan = dest_buf + dest_col; + if (bYFlip) + dest_scan += (result_height - 1) * dest_pitch; + const uint8_t* src_scan = m_pAlphaMask->GetScanline(row) + col_start; + for (int col = col_start; col < col_end; ++col) { + *dest_scan = *src_scan++; + dest_scan += dest_step; + } + } + } + return pTransBitmap; +} + +RetainPtr CFX_DIBSource::TransformTo( + const CFX_Matrix* pDestMatrix, + int* result_left, + int* result_top) { + RetainPtr holder(this); + CFX_ImageTransformer transformer(holder, pDestMatrix, 0, nullptr); + transformer.Continue(nullptr); + *result_left = transformer.result().left; + *result_top = transformer.result().top; + return transformer.DetachBitmap(); +} + +RetainPtr CFX_DIBSource::StretchTo(int dest_width, + int dest_height, + uint32_t flags, + const FX_RECT* pClip) { + RetainPtr holder(this); + FX_RECT clip_rect(0, 0, abs(dest_width), abs(dest_height)); + if (pClip) + clip_rect.Intersect(*pClip); + + if (clip_rect.IsEmpty()) + return nullptr; + + if (dest_width == m_Width && dest_height == m_Height) + return Clone(&clip_rect); + + CFX_BitmapStorer storer; + CFX_ImageStretcher stretcher(&storer, holder, dest_width, dest_height, + clip_rect, flags); + if (stretcher.Start()) + stretcher.Continue(nullptr); + + return storer.Detach(); +} + +// static +bool CFX_DIBSource::ConvertBuffer( + FXDIB_Format dest_format, + uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top, + std::unique_ptr* p_pal) { + FXDIB_Format src_format = pSrcBitmap->GetFormat(); + switch (dest_format) { + case FXDIB_Invalid: + case FXDIB_1bppCmyk: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + NOTREACHED(); + return false; + case FXDIB_8bppMask: { + if ((src_format & 0xff) == 1) { + if (pSrcBitmap->GetPalette()) { + ConvertBuffer_1bppPlt2Gray(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_1bppMask2Gray(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) == 8) { + if (pSrcBitmap->GetPalette()) { + ConvertBuffer_8bppPlt2Gray(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_8bppMask2Gray(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) >= 24) { + ConvertBuffer_RgbOrCmyk2Gray(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + return false; + } + case FXDIB_8bppRgb: + case FXDIB_8bppRgba: { + if ((src_format & 0xff) == 8 && !pSrcBitmap->GetPalette()) { + return ConvertBuffer(FXDIB_8bppMask, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top, p_pal); + } + p_pal->reset(FX_Alloc(uint32_t, 256)); + if (((src_format & 0xff) == 1 || (src_format & 0xff) == 8) && + pSrcBitmap->GetPalette()) { + ConvertBuffer_Plt2PltRgb8(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top, p_pal->get()); + return true; + } + if ((src_format & 0xff) >= 24) { + ConvertBuffer_Rgb2PltRgb8(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top, p_pal->get()); + return true; + } + return false; + } + case FXDIB_Rgb: + case FXDIB_Rgba: { + if ((src_format & 0xff) == 1) { + if (pSrcBitmap->GetPalette()) { + ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) == 8) { + if (pSrcBitmap->GetPalette()) { + ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) == 24) { + ConvertBuffer_24bppRgb2Rgb24(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) == 32) { + ConvertBuffer_32bppRgb2Rgb24(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + return false; + } + case FXDIB_Argb: + case FXDIB_Rgb32: { + if ((src_format & 0xff) == 1) { + if (pSrcBitmap->GetPalette()) { + ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) == 8) { + if (pSrcBitmap->GetPalette()) { + ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, width, + height, pSrcBitmap, src_left, src_top); + return true; + } + if ((src_format & 0xff) >= 24) { + if (src_format & 0x0400) { + ConvertBuffer_32bppCmyk2Rgb32(dest_buf, dest_pitch, width, height, + pSrcBitmap, src_left, src_top); + return true; + } + ConvertBuffer_Rgb2Rgb32(dest_buf, dest_pitch, width, height, pSrcBitmap, + src_left, src_top); + return true; + } + return false; + } + default: + return false; + } +} diff --git a/core/fxge/dib/cfx_dibsource.h b/core/fxge/dib/cfx_dibsource.h new file mode 100644 index 0000000000000000000000000000000000000000..02cae5d0f22de66140b07c86de9cd3c1ba82d3b2 --- /dev/null +++ b/core/fxge/dib/cfx_dibsource.h @@ -0,0 +1,136 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_DIBSOURCE_H_ +#define CORE_FXGE_DIB_CFX_DIBSOURCE_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/fx_dib.h" + +enum FXDIB_Channel { + FXDIB_Red = 1, + FXDIB_Green, + FXDIB_Blue, + FXDIB_Cyan, + FXDIB_Magenta, + FXDIB_Yellow, + FXDIB_Black, + FXDIB_Alpha +}; + +class CFX_ClipRgn; +class CFX_DIBitmap; +class IFX_PauseIndicator; + +class CFX_DIBSource : public Retainable { + public: + ~CFX_DIBSource() override; + + virtual uint8_t* GetBuffer() const; + virtual const uint8_t* GetScanline(int line) const = 0; + virtual bool SkipToScanline(int line, IFX_PauseIndicator* pPause) const; + virtual void DownSampleScanline(int line, + uint8_t* dest_scan, + int dest_bpp, + int dest_width, + bool bFlipX, + int clip_left, + int clip_width) const = 0; + + int GetWidth() const { return m_Width; } + int GetHeight() const { return m_Height; } + + FXDIB_Format GetFormat() const { + return static_cast(m_AlphaFlag * 0x100 + m_bpp); + } + uint32_t GetPitch() const { return m_Pitch; } + uint32_t* GetPalette() const { return m_pPalette.get(); } + int GetBPP() const { return m_bpp; } + + // TODO(thestig): Investigate this. Given the possible values of FXDIB_Format, + // it feels as though this should be implemented as !!(m_AlphaFlag & 1) and + // IsOpaqueImage() below should never be able to return true. + bool IsAlphaMask() const { return m_AlphaFlag == 1; } + bool HasAlpha() const { return !!(m_AlphaFlag & 2); } + bool IsOpaqueImage() const { return !(m_AlphaFlag & 3); } + bool IsCmykImage() const { return !!(m_AlphaFlag & 4); } + + int GetPaletteSize() const { + return IsAlphaMask() ? 0 : (m_bpp == 1 ? 2 : (m_bpp == 8 ? 256 : 0)); + } + + uint32_t GetPaletteArgb(int index) const; + void SetPaletteArgb(int index, uint32_t color); + + // Copies into internally-owned palette. + void SetPalette(const uint32_t* pSrcPal); + + RetainPtr Clone(const FX_RECT* pClip) const; + RetainPtr CloneConvert(FXDIB_Format format); + RetainPtr StretchTo(int dest_width, + int dest_height, + uint32_t flags, + const FX_RECT* pClip); + RetainPtr TransformTo(const CFX_Matrix* pMatrix, + int* left, + int* top); + RetainPtr SwapXY(bool bXFlip, bool bYFlip) const; + RetainPtr FlipImage(bool bXFlip, bool bYFlip) const; + + RetainPtr CloneAlphaMask() const; + + // Copies into internally-owned mask. + bool SetAlphaMask(const RetainPtr& pAlphaMask, + const FX_RECT* pClip); + + void GetOverlapRect(int& dest_left, + int& dest_top, + int& width, + int& height, + int src_width, + int src_height, + int& src_left, + int& src_top, + const CFX_ClipRgn* pClipRgn); + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ + void DebugVerifyBitmapIsPreMultiplied(void* buffer) const; +#endif + + RetainPtr m_pAlphaMask; + + protected: + CFX_DIBSource(); + + static bool ConvertBuffer(FXDIB_Format dest_format, + uint8_t* dest_buf, + int dest_pitch, + int width, + int height, + const RetainPtr& pSrcBitmap, + int src_left, + int src_top, + std::unique_ptr* pal); + + void BuildPalette(); + bool BuildAlphaMask(); + int FindPalette(uint32_t color) const; + void GetPalette(uint32_t* pal, int alpha) const; + + int m_Width; + int m_Height; + int m_bpp; + uint32_t m_AlphaFlag; + uint32_t m_Pitch; + // TODO(weili): Use std::vector for this. + std::unique_ptr m_pPalette; +}; + +#endif // CORE_FXGE_DIB_CFX_DIBSOURCE_H_ diff --git a/core/fxge/dib/cfx_filtereddib.cpp b/core/fxge/dib/cfx_filtereddib.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96fc8062a03dc4d8f75d984f24238b5df88cce89 --- /dev/null +++ b/core/fxge/dib/cfx_filtereddib.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_filtereddib.h" + +#include "core/fxge/fx_dib.h" + +CFX_FilteredDIB::CFX_FilteredDIB() {} + +CFX_FilteredDIB::~CFX_FilteredDIB() {} + +void CFX_FilteredDIB::LoadSrc(const RetainPtr& pSrc) { + m_pSrc = pSrc; + m_Width = pSrc->GetWidth(); + m_Height = pSrc->GetHeight(); + FXDIB_Format format = GetDestFormat(); + m_bpp = static_cast(format); + m_AlphaFlag = static_cast(format >> 8); + m_Pitch = (m_Width * (format & 0xff) + 31) / 32 * 4; + m_pPalette.reset(GetDestPalette()); + m_Scanline.resize(m_Pitch); +} + +const uint8_t* CFX_FilteredDIB::GetScanline(int line) const { + TranslateScanline(m_pSrc->GetScanline(line), &m_Scanline); + return m_Scanline.data(); +} + +void CFX_FilteredDIB::DownSampleScanline(int line, + uint8_t* dest_scan, + int dest_bpp, + int dest_width, + bool bFlipX, + int clip_left, + int clip_width) const { + m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX, + clip_left, clip_width); + TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp); +} diff --git a/core/fxge/dib/cfx_filtereddib.h b/core/fxge/dib/cfx_filtereddib.h new file mode 100644 index 0000000000000000000000000000000000000000..e998c7169aab6110fa1d24474f6a44ab0d0b75a6 --- /dev/null +++ b/core/fxge/dib/cfx_filtereddib.h @@ -0,0 +1,50 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_FILTEREDDIB_H_ +#define CORE_FXGE_DIB_CFX_FILTEREDDIB_H_ + +#include + +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibsource.h" + +class CFX_FilteredDIB : public CFX_DIBSource { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + ~CFX_FilteredDIB() override; + + virtual FXDIB_Format GetDestFormat() = 0; + virtual uint32_t* GetDestPalette() = 0; + virtual void TranslateScanline(const uint8_t* src_buf, + std::vector* dest_buf) const = 0; + virtual void TranslateDownSamples(uint8_t* dest_buf, + const uint8_t* src_buf, + int pixels, + int Bpp) const = 0; + + void LoadSrc(const RetainPtr& pSrc); + + protected: + CFX_FilteredDIB(); + + // CFX_DIBSource + const uint8_t* GetScanline(int line) const override; + void DownSampleScanline(int line, + uint8_t* dest_scan, + int dest_bpp, + int dest_width, + bool bFlipX, + int clip_left, + int clip_width) const override; + + RetainPtr m_pSrc; + mutable std::vector m_Scanline; +}; + +#endif // CORE_FXGE_DIB_CFX_FILTEREDDIB_H_ diff --git a/core/fxge/dib/cfx_imagerenderer.cpp b/core/fxge/dib/cfx_imagerenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..658d363c89d5cd3055e87ffa4222c4997b02507c --- /dev/null +++ b/core/fxge/dib/cfx_imagerenderer.cpp @@ -0,0 +1,124 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_imagerenderer.h" + +#include + +#include "core/fxge/cfx_cliprgn.h" +#include "core/fxge/dib/cfx_imagestretcher.h" +#include "core/fxge/dib/cfx_imagetransformer.h" +#include "third_party/base/ptr_util.h" + +CFX_ImageRenderer::CFX_ImageRenderer(const RetainPtr& pDevice, + const CFX_ClipRgn* pClipRgn, + const RetainPtr& pSource, + int bitmap_alpha, + uint32_t mask_color, + const CFX_Matrix* pMatrix, + uint32_t dib_flags, + bool bRgbByteOrder) + : m_pDevice(pDevice), + m_pClipRgn(pClipRgn), + m_Matrix(*pMatrix), + m_BitmapAlpha(bitmap_alpha), + m_BlendType(FXDIB_BLEND_NORMAL), + m_bRgbByteOrder(bRgbByteOrder), + m_MaskColor(mask_color), + m_Status(0), + m_AlphaFlag(0) { + FX_RECT image_rect = m_Matrix.GetUnitRect().GetOuterRect(); + m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(), + pDevice->GetHeight()); + m_ClipBox.Intersect(image_rect); + if (m_ClipBox.IsEmpty()) + return; + + if ((fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) || + (fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) { + if (fabs(m_Matrix.a) < fabs(m_Matrix.b) / 20 && + fabs(m_Matrix.d) < fabs(m_Matrix.c) / 20 && fabs(m_Matrix.a) < 0.5f && + fabs(m_Matrix.d) < 0.5f) { + int dest_width = image_rect.Width(); + int dest_height = image_rect.Height(); + FX_RECT bitmap_clip = m_ClipBox; + bitmap_clip.Offset(-image_rect.left, -image_rect.top); + bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height, + m_Matrix.c > 0, m_Matrix.b < 0); + m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, + true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder, + 0, m_BlendType); + m_Stretcher = pdfium::MakeUnique( + &m_Composer, pSource, dest_height, dest_width, bitmap_clip, + dib_flags); + if (m_Stretcher->Start()) + m_Status = 1; + return; + } + m_Status = 2; + m_pTransformer = pdfium::MakeUnique( + pSource, &m_Matrix, dib_flags, &m_ClipBox); + return; + } + + int dest_width = image_rect.Width(); + if (m_Matrix.a < 0) + dest_width = -dest_width; + + int dest_height = image_rect.Height(); + if (m_Matrix.d > 0) + dest_height = -dest_height; + + if (dest_width == 0 || dest_height == 0) + return; + + FX_RECT bitmap_clip = m_ClipBox; + bitmap_clip.Offset(-image_rect.left, -image_rect.top); + m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, + false, false, false, m_bRgbByteOrder, 0, m_BlendType); + m_Status = 1; + m_Stretcher = pdfium::MakeUnique( + &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags); + m_Stretcher->Start(); +} + +CFX_ImageRenderer::~CFX_ImageRenderer() {} + +bool CFX_ImageRenderer::Continue(IFX_PauseIndicator* pPause) { + if (m_Status == 1) + return m_Stretcher->Continue(pPause); + if (m_Status != 2) + return false; + if (m_pTransformer->Continue(pPause)) + return true; + + RetainPtr pBitmap = m_pTransformer->DetachBitmap(); + if (!pBitmap || !pBitmap->GetBuffer()) + return false; + + if (pBitmap->IsAlphaMask()) { + if (m_BitmapAlpha != 255) { + if (m_AlphaFlag >> 8) { + m_AlphaFlag = (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) | + ((m_AlphaFlag >> 8) << 8)); + } else { + m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha); + } + } + m_pDevice->CompositeMask( + m_pTransformer->result().left, m_pTransformer->result().top, + pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, m_MaskColor, 0, 0, + m_BlendType, m_pClipRgn.Get(), m_bRgbByteOrder, m_AlphaFlag); + } else { + if (m_BitmapAlpha != 255) + pBitmap->MultiplyAlpha(m_BitmapAlpha); + m_pDevice->CompositeBitmap( + m_pTransformer->result().left, m_pTransformer->result().top, + pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, 0, 0, m_BlendType, + m_pClipRgn.Get(), m_bRgbByteOrder); + } + return false; +} diff --git a/core/fxge/dib/cfx_imagerenderer.h b/core/fxge/dib/cfx_imagerenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..18a56e278293b6b202a8f33cc29747d7f517a629 --- /dev/null +++ b/core/fxge/dib/cfx_imagerenderer.h @@ -0,0 +1,54 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_IMAGERENDERER_H_ +#define CORE_FXGE_DIB_CFX_IMAGERENDERER_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/dib/cfx_bitmapcomposer.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/cfx_dibsource.h" +#include "core/fxge/fx_dib.h" +#include "third_party/base/stl_util.h" + +class CFX_ImageTransformer; +class CFX_ImageStretcher; + +class CFX_ImageRenderer { + public: + CFX_ImageRenderer(const RetainPtr& pDevice, + const CFX_ClipRgn* pClipRgn, + const RetainPtr& pSource, + int bitmap_alpha, + uint32_t mask_color, + const CFX_Matrix* pMatrix, + uint32_t dib_flags, + bool bRgbByteOrder); + ~CFX_ImageRenderer(); + + bool Continue(IFX_PauseIndicator* pPause); + + private: + const RetainPtr m_pDevice; + const UnownedPtr m_pClipRgn; + const CFX_Matrix m_Matrix; + const int m_BitmapAlpha; + const int m_BlendType; + const bool m_bRgbByteOrder; + uint32_t m_MaskColor; + std::unique_ptr m_pTransformer; + std::unique_ptr m_Stretcher; + CFX_BitmapComposer m_Composer; + int m_Status; + FX_RECT m_ClipBox; + int m_AlphaFlag; +}; + +#endif // CORE_FXGE_DIB_CFX_IMAGERENDERER_H_ diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03518c688e3a0c0d10c538d2cc18b4b552ee599a --- /dev/null +++ b/core/fxge/dib/cfx_imagestretcher.cpp @@ -0,0 +1,208 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_imagestretcher.h" + +#include +#include + +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/cfx_dibsource.h" +#include "core/fxge/dib/cstretchengine.h" +#include "core/fxge/fx_dib.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const int kMaxProgressiveStretchPixels = 1000000; + +bool SourceSizeWithinLimit(int width, int height) { + return !height || width < kMaxProgressiveStretchPixels / height; +} + +FXDIB_Format GetStretchedFormat(const CFX_DIBSource& src) { + FXDIB_Format format = src.GetFormat(); + if (format == FXDIB_1bppMask) + return FXDIB_8bppMask; + if (format == FXDIB_1bppRgb) + return FXDIB_8bppRgb; + if (format == FXDIB_8bppRgb && src.GetPalette()) + return FXDIB_Rgb; + return format; +} + +// Returns tuple c, m, y, k +std::tuple CmykDecode(const uint32_t cmyk) { + return std::make_tuple(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), + FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); +} + +} // namespace + +CFX_ImageStretcher::CFX_ImageStretcher(IFX_ScanlineComposer* pDest, + const RetainPtr& pSource, + int dest_width, + int dest_height, + const FX_RECT& bitmap_rect, + uint32_t flags) + : m_pDest(pDest), + m_pSource(pSource), + m_Flags(flags), + m_bFlipX(false), + m_bFlipY(false), + m_DestWidth(dest_width), + m_DestHeight(dest_height), + m_ClipRect(bitmap_rect), + m_DestFormat(GetStretchedFormat(*pSource)), + m_DestBPP(m_DestFormat & 0xff), + m_LineIndex(0) {} + +CFX_ImageStretcher::~CFX_ImageStretcher() {} + +bool CFX_ImageStretcher::Start() { + if (m_DestWidth == 0 || m_DestHeight == 0) + return false; + + if (m_pSource->GetFormat() == FXDIB_1bppRgb && m_pSource->GetPalette()) { + FX_ARGB pal[256]; + int a0; + int r0; + int g0; + int b0; + std::tie(a0, r0, g0, b0) = ArgbDecode(m_pSource->GetPaletteArgb(0)); + int a1; + int r1; + int g1; + int b1; + std::tie(a1, r1, g1, b1) = ArgbDecode(m_pSource->GetPaletteArgb(1)); + for (int i = 0; i < 256; ++i) { + int a = a0 + (a1 - a0) * i / 255; + int r = r0 + (r1 - r0) * i / 255; + int g = g0 + (g1 - g0) * i / 255; + int b = b0 + (b1 - b0) * i / 255; + pal[i] = ArgbEncode(a, r, g, b); + } + if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat, + pal)) { + return false; + } + } else if (m_pSource->GetFormat() == FXDIB_1bppCmyk && + m_pSource->GetPalette()) { + FX_CMYK pal[256]; + int c0; + int m0; + int y0; + int k0; + std::tie(c0, m0, y0, k0) = CmykDecode(m_pSource->GetPaletteArgb(0)); + int c1; + int m1; + int y1; + int k1; + std::tie(c1, m1, y1, k1) = CmykDecode(m_pSource->GetPaletteArgb(1)); + for (int i = 0; i < 256; ++i) { + int c = c0 + (c1 - c0) * i / 255; + int m = m0 + (m1 - m0) * i / 255; + int y = y0 + (y1 - y0) * i / 255; + int k = k0 + (k1 - k0) * i / 255; + pal[i] = CmykEncode(c, m, y, k); + } + if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat, + pal)) { + return false; + } + } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), + m_DestFormat, nullptr)) { + return false; + } + + if (m_Flags & FXDIB_DOWNSAMPLE) + return StartQuickStretch(); + + return StartStretch(); +} + +bool CFX_ImageStretcher::Continue(IFX_PauseIndicator* pPause) { + if (m_Flags & FXDIB_DOWNSAMPLE) + return ContinueQuickStretch(pPause); + return ContinueStretch(pPause); +} + +bool CFX_ImageStretcher::StartStretch() { + m_pStretchEngine = pdfium::MakeUnique( + m_pDest.Get(), m_DestFormat, m_DestWidth, m_DestHeight, m_ClipRect, + m_pSource, m_Flags); + m_pStretchEngine->StartStretchHorz(); + if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { + m_pStretchEngine->Continue(nullptr); + return false; + } + return true; +} + +bool CFX_ImageStretcher::ContinueStretch(IFX_PauseIndicator* pPause) { + return m_pStretchEngine && m_pStretchEngine->Continue(pPause); +} + +bool CFX_ImageStretcher::StartQuickStretch() { + if (m_DestWidth < 0) { + m_bFlipX = true; + m_DestWidth = -m_DestWidth; + } + if (m_DestHeight < 0) { + m_bFlipY = true; + m_DestHeight = -m_DestHeight; + } + uint32_t size = m_ClipRect.Width(); + if (size && m_DestBPP > static_cast(INT_MAX / size)) + return false; + + size *= m_DestBPP; + m_pScanline.reset(FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4)); + if (m_pSource->m_pAlphaMask) + m_pMaskScanline.reset(FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4)); + + if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { + ContinueQuickStretch(nullptr); + return false; + } + return true; +} + +bool CFX_ImageStretcher::ContinueQuickStretch(IFX_PauseIndicator* pPause) { + if (!m_pScanline) + return false; + + int result_width = m_ClipRect.Width(); + int result_height = m_ClipRect.Height(); + int src_height = m_pSource->GetHeight(); + for (; m_LineIndex < result_height; ++m_LineIndex) { + int dest_y; + int src_y; + if (m_bFlipY) { + dest_y = result_height - m_LineIndex - 1; + src_y = (m_DestHeight - (dest_y + m_ClipRect.top) - 1) * src_height / + m_DestHeight; + } else { + dest_y = m_LineIndex; + src_y = (dest_y + m_ClipRect.top) * src_height / m_DestHeight; + } + src_y = pdfium::clamp(src_y, 0, src_height - 1); + + if (m_pSource->SkipToScanline(src_y, pPause)) + return true; + + m_pSource->DownSampleScanline(src_y, m_pScanline.get(), m_DestBPP, + m_DestWidth, m_bFlipX, m_ClipRect.left, + result_width); + if (m_pMaskScanline) { + m_pSource->m_pAlphaMask->DownSampleScanline( + src_y, m_pMaskScanline.get(), 1, m_DestWidth, m_bFlipX, + m_ClipRect.left, result_width); + } + m_pDest->ComposeScanline(dest_y, m_pScanline.get(), m_pMaskScanline.get()); + } + return false; +} diff --git a/core/fxge/dib/cfx_imagestretcher.h b/core/fxge/dib/cfx_imagestretcher.h new file mode 100644 index 0000000000000000000000000000000000000000..2ecb2a0492fe2089de3699258bcf5f313a73bb5a --- /dev/null +++ b/core/fxge/dib/cfx_imagestretcher.h @@ -0,0 +1,59 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_IMAGESTRETCHER_H_ +#define CORE_FXGE_DIB_CFX_IMAGESTRETCHER_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/dib/ifx_scanlinecomposer.h" +#include "core/fxge/fx_dib.h" + +class CFX_DIBSource; +class IFX_PauseIndicator; + +class CFX_ImageStretcher { + public: + CFX_ImageStretcher(IFX_ScanlineComposer* pDest, + const RetainPtr& pSource, + int dest_width, + int dest_height, + const FX_RECT& bitmap_rect, + uint32_t flags); + ~CFX_ImageStretcher(); + + bool Start(); + bool Continue(IFX_PauseIndicator* pPause); + + RetainPtr source() { return m_pSource; } + + private: + bool StartQuickStretch(); + bool StartStretch(); + bool ContinueQuickStretch(IFX_PauseIndicator* pPause); + bool ContinueStretch(IFX_PauseIndicator* pPause); + + UnownedPtr const m_pDest; + RetainPtr m_pSource; + std::unique_ptr m_pStretchEngine; + std::unique_ptr m_pScanline; + std::unique_ptr m_pMaskScanline; + const uint32_t m_Flags; + bool m_bFlipX; + bool m_bFlipY; + int m_DestWidth; + int m_DestHeight; + FX_RECT m_ClipRect; + const FXDIB_Format m_DestFormat; + const int m_DestBPP; + int m_LineIndex; +}; + +#endif // CORE_FXGE_DIB_CFX_IMAGESTRETCHER_H_ diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e01127b00a4644db99e7fb00d02596e9a5744a7 --- /dev/null +++ b/core/fxge/dib/cfx_imagetransformer.cpp @@ -0,0 +1,557 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_imagetransformer.h" + +#include +#include +#include + +#include "core/fxge/dib/cfx_imagestretcher.h" +#include "core/fxge/fx_dib.h" +#include "third_party/base/numerics/safe_conversions.h" +#include "third_party/base/ptr_util.h" + +namespace { + +constexpr int kBase = 256; +constexpr float kFix16 = 0.05f; +constexpr uint8_t kOpaqueAlpha = 0xff; + +uint8_t bilinear_interpol(const uint8_t* buf, + int row_offset_l, + int row_offset_r, + int src_col_l, + int src_col_r, + int res_x, + int res_y, + int bpp, + int c_offset) { + int i_resx = 255 - res_x; + int col_bpp_l = src_col_l * bpp; + int col_bpp_r = src_col_r * bpp; + const uint8_t* buf_u = buf + row_offset_l + c_offset; + const uint8_t* buf_d = buf + row_offset_r + c_offset; + const uint8_t* src_pos0 = buf_u + col_bpp_l; + const uint8_t* src_pos1 = buf_u + col_bpp_r; + const uint8_t* src_pos2 = buf_d + col_bpp_l; + const uint8_t* src_pos3 = buf_d + col_bpp_r; + uint8_t r_pos_0 = (*src_pos0 * i_resx + *src_pos1 * res_x) >> 8; + uint8_t r_pos_1 = (*src_pos2 * i_resx + *src_pos3 * res_x) >> 8; + return (r_pos_0 * (255 - res_y) + r_pos_1 * res_y) >> 8; +} + +uint8_t bicubic_interpol(const uint8_t* buf, + uint32_t pitch, + const int pos_pixel[], + const int u_w[], + const int v_w[], + int res_x, + int res_y, + int bpp, + int c_offset) { + int s_result = 0; + for (int i = 0; i < 4; i++) { + int a_result = 0; + for (int j = 0; j < 4; j++) { + uint8_t val = + *(buf + pos_pixel[i + 4] * pitch + pos_pixel[j] * bpp + c_offset); + a_result += u_w[j] * val; + } + s_result += a_result * v_w[i]; + } + s_result >>= 16; + return static_cast(pdfium::clamp(s_result, 0, 255)); +} + +void bicubic_get_pos_weight(int pos_pixel[], + int u_w[], + int v_w[], + int src_col_l, + int src_row_l, + int res_x, + int res_y, + int stretch_width, + int stretch_height) { + pos_pixel[0] = src_col_l - 1; + pos_pixel[1] = src_col_l; + pos_pixel[2] = src_col_l + 1; + pos_pixel[3] = src_col_l + 2; + pos_pixel[4] = src_row_l - 1; + pos_pixel[5] = src_row_l; + pos_pixel[6] = src_row_l + 1; + pos_pixel[7] = src_row_l + 2; + for (int i = 0; i < 4; i++) { + pos_pixel[i] = pdfium::clamp(pos_pixel[i], 0, stretch_width - 1); + pos_pixel[i + 4] = pdfium::clamp(pos_pixel[i + 4], 0, stretch_height - 1); + } + u_w[0] = SDP_Table[256 + res_x]; + u_w[1] = SDP_Table[res_x]; + u_w[2] = SDP_Table[256 - res_x]; + u_w[3] = SDP_Table[512 - res_x]; + v_w[0] = SDP_Table[256 + res_y]; + v_w[1] = SDP_Table[res_y]; + v_w[2] = SDP_Table[256 - res_y]; + v_w[3] = SDP_Table[512 - res_y]; +} + +FXDIB_Format GetTransformedFormat(const RetainPtr& pDrc) { + if (pDrc->IsAlphaMask()) + return FXDIB_8bppMask; + + FXDIB_Format format = pDrc->GetFormat(); + if (format >= 1025) + return FXDIB_Cmyka; + if (format <= 32 || format == FXDIB_Argb) + return FXDIB_Argb; + return FXDIB_Rgba; +} + +bool NeedAlpha(bool bHasAlpha, FXDIB_Format format) { + return bHasAlpha || format == FXDIB_Cmyka; +} + +void WriteMonoResult(uint32_t r_bgra_cmyk, FXDIB_Format format, uint8_t* dest) { + if (format == FXDIB_Rgba) { + dest[0] = static_cast(r_bgra_cmyk >> 24); + dest[1] = static_cast(r_bgra_cmyk >> 16); + dest[2] = static_cast(r_bgra_cmyk >> 8); + } else { + *reinterpret_cast(dest) = r_bgra_cmyk; + } +} + +void WriteColorResult(std::function func, + bool bHasAlpha, + FXDIB_Format format, + uint8_t* dest) { + uint8_t blue_c = func(0); + uint8_t green_m = func(1); + uint8_t red_y = func(2); + uint8_t alpha_k = NeedAlpha(bHasAlpha, format) ? func(3) : kOpaqueAlpha; + + uint32_t* dest32 = reinterpret_cast(dest); + if (bHasAlpha) { + if (format == FXDIB_Argb) { + *dest32 = FXARGB_TODIB(FXARGB_MAKE(alpha_k, red_y, green_m, blue_c)); + } else if (format == FXDIB_Rgba) { + dest[0] = blue_c; + dest[1] = green_m; + dest[2] = red_y; + } else { + *dest32 = FXCMYK_TODIB(CmykEncode(blue_c, green_m, red_y, alpha_k)); + } + return; + } + + if (format == FXDIB_Cmyka) { + *dest32 = FXCMYK_TODIB(CmykEncode(blue_c, green_m, red_y, alpha_k)); + } else { + ASSERT(alpha_k == kOpaqueAlpha); + *dest32 = FXARGB_TODIB(FXARGB_MAKE(kOpaqueAlpha, red_y, green_m, blue_c)); + } +} + +class CPDF_FixedMatrix { + public: + explicit CPDF_FixedMatrix(const CFX_Matrix& src) + : a(FXSYS_round(src.a * kBase)), + b(FXSYS_round(src.b * kBase)), + c(FXSYS_round(src.c * kBase)), + d(FXSYS_round(src.d * kBase)), + e(FXSYS_round(src.e * kBase)), + f(FXSYS_round(src.f * kBase)) {} + + void Transform(int x, int y, int* x1, int* y1) const { + std::pair val = TransformInternal(x, y); + *x1 = pdfium::base::saturated_cast(val.first / kBase); + *y1 = pdfium::base::saturated_cast(val.second / kBase); + } + + protected: + std::pair TransformInternal(float x, float y) const { + return std::make_pair(a * x + c * y + e + kBase / 2, + b * x + d * y + f + kBase / 2); + } + + const int a; + const int b; + const int c; + const int d; + const int e; + const int f; +}; + +class CFX_BilinearMatrix : public CPDF_FixedMatrix { + public: + explicit CFX_BilinearMatrix(const CFX_Matrix& src) : CPDF_FixedMatrix(src) {} + + void Transform(int x, int y, int* x1, int* y1, int* res_x, int* res_y) const { + std::pair val = TransformInternal(x, y); + *x1 = pdfium::base::saturated_cast(val.first / kBase); + *y1 = pdfium::base::saturated_cast(val.second / kBase); + + *res_x = static_cast(fmodf(val.first, kBase)); + *res_y = static_cast(fmodf(val.second, kBase)); + if (*res_x < 0 && *res_x > -kBase) + *res_x = kBase + *res_x; + if (*res_y < 0 && *res_x > -kBase) + *res_y = kBase + *res_y; + } +}; + +} // namespace + +CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr& pSrc, + const CFX_Matrix* pMatrix, + int flags, + const FX_RECT* pClip) + : m_pSrc(pSrc), + m_pMatrix(pMatrix), + m_pClip(pClip), + m_Flags(flags), + m_Status(0) { + FX_RECT result_rect = m_pMatrix->GetUnitRect().GetClosestRect(); + FX_RECT result_clip = result_rect; + if (m_pClip) + result_clip.Intersect(*m_pClip); + + if (result_clip.IsEmpty()) + return; + + m_result = result_clip; + if (fabs(m_pMatrix->a) < fabs(m_pMatrix->b) / 20 && + fabs(m_pMatrix->d) < fabs(m_pMatrix->c) / 20 && + fabs(m_pMatrix->a) < 0.5f && fabs(m_pMatrix->d) < 0.5f) { + int dest_width = result_rect.Width(); + int dest_height = result_rect.Height(); + result_clip.Offset(-result_rect.left, -result_rect.top); + result_clip = FXDIB_SwapClipBox(result_clip, dest_width, dest_height, + m_pMatrix->c > 0, m_pMatrix->b < 0); + m_Stretcher = pdfium::MakeUnique( + &m_Storer, m_pSrc, dest_height, dest_width, result_clip, m_Flags); + m_Stretcher->Start(); + m_Status = 1; + return; + } + if (fabs(m_pMatrix->b) < kFix16 && fabs(m_pMatrix->c) < kFix16) { + int dest_width = static_cast(m_pMatrix->a > 0 ? ceil(m_pMatrix->a) + : floor(m_pMatrix->a)); + int dest_height = static_cast(m_pMatrix->d > 0 ? -ceil(m_pMatrix->d) + : -floor(m_pMatrix->d)); + result_clip.Offset(-result_rect.left, -result_rect.top); + m_Stretcher = pdfium::MakeUnique( + &m_Storer, m_pSrc, dest_width, dest_height, result_clip, m_Flags); + m_Stretcher->Start(); + m_Status = 2; + return; + } + int stretch_width = + static_cast(ceil(FXSYS_sqrt2(m_pMatrix->a, m_pMatrix->b))); + int stretch_height = + static_cast(ceil(FXSYS_sqrt2(m_pMatrix->c, m_pMatrix->d))); + CFX_Matrix stretch2dest(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, stretch_height); + stretch2dest.Concat( + CFX_Matrix(m_pMatrix->a / stretch_width, m_pMatrix->b / stretch_width, + m_pMatrix->c / stretch_height, m_pMatrix->d / stretch_height, + m_pMatrix->e, m_pMatrix->f)); + m_dest2stretch = stretch2dest.GetInverse(); + + m_StretchClip = + m_dest2stretch.TransformRect(CFX_FloatRect(result_clip)).GetOuterRect(); + m_StretchClip.Intersect(0, 0, stretch_width, stretch_height); + m_Stretcher = pdfium::MakeUnique( + &m_Storer, m_pSrc, stretch_width, stretch_height, m_StretchClip, m_Flags); + m_Stretcher->Start(); + m_Status = 3; +} + +CFX_ImageTransformer::~CFX_ImageTransformer() {} + +bool CFX_ImageTransformer::Continue(IFX_PauseIndicator* pPause) { + if (m_Status == 1) { + if (m_Stretcher->Continue(pPause)) + return true; + + if (m_Storer.GetBitmap()) { + m_Storer.Replace( + m_Storer.GetBitmap()->SwapXY(m_pMatrix->c > 0, m_pMatrix->b < 0)); + } + return false; + } + + if (m_Status == 2) + return m_Stretcher->Continue(pPause); + if (m_Status != 3) + return false; + if (m_Stretcher->Continue(pPause)) + return true; + + if (!m_Storer.GetBitmap()) + return false; + + auto pTransformed = pdfium::MakeRetain(); + FXDIB_Format format = GetTransformedFormat(m_Stretcher->source()); + if (!pTransformed->Create(m_result.Width(), m_result.Height(), format)) + return false; + + const auto& pSrcMask = m_Storer.GetBitmap()->m_pAlphaMask; + const uint8_t* pSrcMaskBuf = pSrcMask ? pSrcMask->GetBuffer() : nullptr; + + pTransformed->Clear(0); + auto& pDestMask = pTransformed->m_pAlphaMask; + if (pDestMask) + pDestMask->Clear(0); + + CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, m_result.left, + m_result.top); + result2stretch.Concat(m_dest2stretch); + result2stretch.Translate(-m_StretchClip.left, -m_StretchClip.top); + if (!pSrcMaskBuf && pDestMask) { + pDestMask->Clear(0xff000000); + } else if (pDestMask) { + CalcData cdata = { + pDestMask.Get(), result2stretch, pSrcMaskBuf, + m_Storer.GetBitmap()->m_pAlphaMask->GetPitch(), + }; + CalcMask(cdata); + } + + CalcData cdata = {pTransformed.Get(), result2stretch, + m_Storer.GetBitmap()->GetBuffer(), + m_Storer.GetBitmap()->GetPitch()}; + if (m_Storer.GetBitmap()->IsAlphaMask()) { + CalcAlpha(cdata); + } else { + int Bpp = m_Storer.GetBitmap()->GetBPP() / 8; + if (Bpp == 1) + CalcMono(cdata, format); + else + CalcColor(cdata, format, Bpp); + } + m_Storer.Replace(std::move(pTransformed)); + return false; +} + +RetainPtr CFX_ImageTransformer::DetachBitmap() { + return m_Storer.Detach(); +} + +void CFX_ImageTransformer::CalcMask(const CalcData& cdata) { + if (IsBilinear()) { + auto func = [&cdata](const BilinearData& data, uint8_t* dest) { + *dest = bilinear_interpol(cdata.buf, data.row_offset_l, data.row_offset_r, + data.src_col_l, data.src_col_r, data.res_x, + data.res_y, 1, 0); + }; + DoBilinearLoop(cdata, 1, func); + } else if (IsBiCubic()) { + auto func = [&cdata](const BicubicData& data, uint8_t* dest) { + *dest = bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, + data.v_w, data.res_x, data.res_y, 1, 0); + }; + DoBicubicLoop(cdata, 1, func); + } else { + auto func = [&cdata](const DownSampleData& data, uint8_t* dest) { + *dest = cdata.buf[data.src_row * cdata.pitch + data.src_col]; + }; + DoDownSampleLoop(cdata, 1, func); + } +} + +void CFX_ImageTransformer::CalcAlpha(const CalcData& cdata) { + if (IsBilinear()) { + auto func = [&cdata](const BilinearData& data, uint8_t* dest) { + *dest = bilinear_interpol(cdata.buf, data.row_offset_l, data.row_offset_r, + data.src_col_l, data.src_col_r, data.res_x, + data.res_y, 1, 0); + }; + DoBilinearLoop(cdata, 1, func); + } else if (IsBiCubic()) { + auto func = [&cdata](const BicubicData& data, uint8_t* dest) { + *dest = bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, + data.v_w, data.res_x, data.res_y, 1, 0); + }; + DoBicubicLoop(cdata, 1, func); + } else { + auto func = [&cdata](const DownSampleData& data, uint8_t* dest) { + const uint8_t* src_pixel = + cdata.buf + cdata.pitch * data.src_row + data.src_col; + *dest = *src_pixel; + }; + DoDownSampleLoop(cdata, 1, func); + } +} + +void CFX_ImageTransformer::CalcMono(const CalcData& cdata, + FXDIB_Format format) { + uint32_t argb[256]; + FX_ARGB* pPal = m_Storer.GetBitmap()->GetPalette(); + if (pPal) { + for (size_t i = 0; i < FX_ArraySize(argb); i++) + argb[i] = pPal[i]; + } else if (m_Storer.GetBitmap()->IsCmykImage()) { + for (size_t i = 0; i < FX_ArraySize(argb); i++) + argb[i] = 255 - i; + } else { + for (size_t i = 0; i < FX_ArraySize(argb); i++) + argb[i] = 0xff000000 | (i * 0x010101); + } + int destBpp = cdata.bitmap->GetBPP() / 8; + if (IsBilinear()) { + auto func = [&cdata, format, &argb](const BilinearData& data, + uint8_t* dest) { + uint8_t idx = bilinear_interpol( + cdata.buf, data.row_offset_l, data.row_offset_r, data.src_col_l, + data.src_col_r, data.res_x, data.res_y, 1, 0); + uint32_t r_bgra_cmyk = argb[idx]; + WriteMonoResult(r_bgra_cmyk, format, dest); + }; + DoBilinearLoop(cdata, destBpp, func); + } else if (IsBiCubic()) { + auto func = [&cdata, format, &argb](const BicubicData& data, + uint8_t* dest) { + uint32_t r_bgra_cmyk = argb[bicubic_interpol( + cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, data.v_w, + data.res_x, data.res_y, 1, 0)]; + WriteMonoResult(r_bgra_cmyk, format, dest); + }; + DoBicubicLoop(cdata, destBpp, func); + } else { + auto func = [&cdata, format, &argb](const DownSampleData& data, + uint8_t* dest) { + uint32_t r_bgra_cmyk = + argb[cdata.buf[data.src_row * cdata.pitch + data.src_col]]; + WriteMonoResult(r_bgra_cmyk, format, dest); + }; + DoDownSampleLoop(cdata, destBpp, func); + } +} + +void CFX_ImageTransformer::CalcColor(const CalcData& cdata, + FXDIB_Format format, + int Bpp) { + bool bHasAlpha = m_Storer.GetBitmap()->HasAlpha(); + int destBpp = cdata.bitmap->GetBPP() / 8; + if (IsBilinear()) { + auto func = [&cdata, format, Bpp, bHasAlpha](const BilinearData& data, + uint8_t* dest) { + auto bilinear_interpol_func = [&cdata, &data, Bpp](int offset) { + return bilinear_interpol( + cdata.buf, data.row_offset_l, data.row_offset_r, data.src_col_l, + data.src_col_r, data.res_x, data.res_y, Bpp, offset); + }; + WriteColorResult(bilinear_interpol_func, bHasAlpha, format, dest); + }; + DoBilinearLoop(cdata, destBpp, func); + } else if (IsBiCubic()) { + auto func = [&cdata, format, Bpp, bHasAlpha](const BicubicData& data, + uint8_t* dest) { + auto bicubic_interpol_func = [&cdata, &data, Bpp](int offset) { + return bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, + data.u_w, data.v_w, data.res_x, data.res_y, Bpp, + offset); + }; + WriteColorResult(bicubic_interpol_func, bHasAlpha, format, dest); + }; + DoBicubicLoop(cdata, destBpp, func); + } else { + auto func = [&cdata, format, bHasAlpha, Bpp](const DownSampleData& data, + uint8_t* dest) { + const uint8_t* src_pos = + cdata.buf + data.src_row * cdata.pitch + data.src_col * Bpp; + auto sample_func = [src_pos](int offset) { return src_pos[offset]; }; + WriteColorResult(sample_func, bHasAlpha, format, dest); + }; + DoDownSampleLoop(cdata, destBpp, func); + } +} + +void CFX_ImageTransformer::AdjustCoords(int* col, int* row) const { + int& src_col = *col; + int& src_row = *row; + if (src_col == stretch_width()) + src_col--; + if (src_row == stretch_height()) + src_row--; +} + +void CFX_ImageTransformer::DoBilinearLoop( + const CalcData& cdata, + int increment, + std::function func) { + CFX_BilinearMatrix matrix_fix(cdata.matrix); + for (int row = 0; row < m_result.Height(); row++) { + uint8_t* dest = const_cast(cdata.bitmap->GetScanline(row)); + for (int col = 0; col < m_result.Width(); col++) { + BilinearData d; + d.res_x = 0; + d.res_y = 0; + d.src_col_l = 0; + d.src_row_l = 0; + matrix_fix.Transform(col, row, &d.src_col_l, &d.src_row_l, &d.res_x, + &d.res_y); + if (InStretchBounds(d.src_col_l, d.src_row_l)) { + AdjustCoords(&d.src_col_l, &d.src_row_l); + d.src_col_r = d.src_col_l + 1; + d.src_row_r = d.src_row_l + 1; + AdjustCoords(&d.src_col_r, &d.src_row_r); + d.row_offset_l = d.src_row_l * cdata.pitch; + d.row_offset_r = d.src_row_r * cdata.pitch; + func(d, dest); + } + dest += increment; + } + } +} + +void CFX_ImageTransformer::DoBicubicLoop( + const CalcData& cdata, + int increment, + std::function func) { + CFX_BilinearMatrix matrix_fix(cdata.matrix); + for (int row = 0; row < m_result.Height(); row++) { + uint8_t* dest = const_cast(cdata.bitmap->GetScanline(row)); + for (int col = 0; col < m_result.Width(); col++) { + BicubicData d; + d.res_x = 0; + d.res_y = 0; + d.src_col_l = 0; + d.src_row_l = 0; + matrix_fix.Transform(col, row, &d.src_col_l, &d.src_row_l, &d.res_x, + &d.res_y); + if (InStretchBounds(d.src_col_l, d.src_row_l)) { + AdjustCoords(&d.src_col_l, &d.src_row_l); + bicubic_get_pos_weight(d.pos_pixel, d.u_w, d.v_w, d.src_col_l, + d.src_row_l, d.res_x, d.res_y, stretch_width(), + stretch_height()); + func(d, dest); + } + dest += increment; + } + } +} + +void CFX_ImageTransformer::DoDownSampleLoop( + const CalcData& cdata, + int increment, + std::function func) { + CPDF_FixedMatrix matrix_fix(cdata.matrix); + for (int row = 0; row < m_result.Height(); row++) { + uint8_t* dest = const_cast(cdata.bitmap->GetScanline(row)); + for (int col = 0; col < m_result.Width(); col++) { + DownSampleData d; + d.src_col = 0; + d.src_row = 0; + matrix_fix.Transform(col, row, &d.src_col, &d.src_row); + if (InStretchBounds(d.src_col, d.src_row)) { + AdjustCoords(&d.src_col, &d.src_row); + func(d, dest); + } + dest += increment; + } + } +} diff --git a/core/fxge/dib/cfx_imagetransformer.h b/core/fxge/dib/cfx_imagetransformer.h new file mode 100644 index 0000000000000000000000000000000000000000..d13ce3f130ed46e2e0d81eb6f213dbbd916eaa7c --- /dev/null +++ b/core/fxge/dib/cfx_imagetransformer.h @@ -0,0 +1,113 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_IMAGETRANSFORMER_H_ +#define CORE_FXGE_DIB_CFX_IMAGETRANSFORMER_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/dib/cfx_bitmapstorer.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/cfx_dibsource.h" + +class CFX_ImageStretcher; + +class CFX_ImageTransformer { + public: + CFX_ImageTransformer(const RetainPtr& pSrc, + const CFX_Matrix* pMatrix, + int flags, + const FX_RECT* pClip); + ~CFX_ImageTransformer(); + + bool Continue(IFX_PauseIndicator* pPause); + + const FX_RECT& result() const { return m_result; } + RetainPtr DetachBitmap(); + + private: + struct BilinearData { + int res_x; + int res_y; + int src_col_l; + int src_row_l; + int src_col_r; + int src_row_r; + int row_offset_l; + int row_offset_r; + }; + + struct BicubicData { + int res_x; + int res_y; + int src_col_l; + int src_row_l; + int src_col_r; + int src_row_r; + int pos_pixel[8]; + int u_w[4]; + int v_w[4]; + }; + + struct DownSampleData { + int src_col; + int src_row; + }; + + struct CalcData { + const CFX_DIBitmap* bitmap; + const CFX_Matrix& matrix; + const uint8_t* buf; + uint32_t pitch; + }; + + void CalcMask(const CalcData& cdata); + void CalcAlpha(const CalcData& cdata); + void CalcMono(const CalcData& cdata, FXDIB_Format format); + void CalcColor(const CalcData& cdata, FXDIB_Format format, int Bpp); + + bool IsBilinear() const { + return !(m_Flags & FXDIB_DOWNSAMPLE) && !IsBiCubic(); + } + bool IsBiCubic() const { return !!(m_Flags & FXDIB_BICUBIC_INTERPOL); } + + int stretch_width() const { return m_StretchClip.Width(); } + int stretch_height() const { return m_StretchClip.Height(); } + + bool InStretchBounds(int col, int row) const { + return col >= 0 && col <= stretch_width() && row >= 0 && + row <= stretch_height(); + } + + void AdjustCoords(int* col, int* row) const; + + void DoBilinearLoop(const CalcData& cdata, + int increment, + std::function func); + void DoBicubicLoop(const CalcData& cdata, + int increment, + std::function func); + void DoDownSampleLoop( + const CalcData& cdata, + int increment, + std::function func); + + const RetainPtr m_pSrc; + UnownedPtr const m_pMatrix; + const FX_RECT* const m_pClip; + FX_RECT m_StretchClip; + FX_RECT m_result; + CFX_Matrix m_dest2stretch; + std::unique_ptr m_Stretcher; + CFX_BitmapStorer m_Storer; + const uint32_t m_Flags; + int m_Status; +}; + +#endif // CORE_FXGE_DIB_CFX_IMAGETRANSFORMER_H_ diff --git a/core/fxge/dib/cfx_scanlinecompositor.cpp b/core/fxge/dib/cfx_scanlinecompositor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1254e2116ede92c46a7ffd92753d1fad411eb10 --- /dev/null +++ b/core/fxge/dib/cfx_scanlinecompositor.cpp @@ -0,0 +1,3336 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cfx_scanlinecompositor.h" + +#include + +#include "core/fxcodec/fx_codec.h" + +#define FX_CCOLOR(val) (255 - (val)) +#define FXDIB_ALPHA_UNION(dest, src) ((dest) + (src) - (dest) * (src) / 255) +#define FXARGB_COPY(dest, src) \ + *(dest) = *(src), *((dest) + 1) = *((src) + 1), \ + *((dest) + 2) = *((src) + 2), *((dest) + 3) = *((src) + 3) +#define FXARGB_RGBORDERCOPY(dest, src) \ + *((dest) + 3) = *((src) + 3), *(dest) = *((src) + 2), \ + *((dest) + 1) = *((src) + 1), *((dest) + 2) = *((src)) + +namespace { + +const uint8_t color_sqrt[256] = { + 0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26, + 0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46, + 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C, + 0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, + 0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, + 0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91, + 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, + 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, + 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, + 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, + 0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF, + 0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, + 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE, + 0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, + 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, + 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4, + 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, + 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1, + 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, + 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, + 0xFD, 0xFE, 0xFE, 0xFF}; + +int Blend(int blend_mode, int back_color, int src_color) { + switch (blend_mode) { + case FXDIB_BLEND_NORMAL: + return src_color; + case FXDIB_BLEND_MULTIPLY: + return src_color * back_color / 255; + case FXDIB_BLEND_SCREEN: + return src_color + back_color - src_color * back_color / 255; + case FXDIB_BLEND_OVERLAY: + return Blend(FXDIB_BLEND_HARDLIGHT, src_color, back_color); + case FXDIB_BLEND_DARKEN: + return src_color < back_color ? src_color : back_color; + case FXDIB_BLEND_LIGHTEN: + return src_color > back_color ? src_color : back_color; + case FXDIB_BLEND_COLORDODGE: { + if (src_color == 255) + return src_color; + + return std::min(back_color * 255 / (255 - src_color), 255); + } + case FXDIB_BLEND_COLORBURN: { + if (src_color == 0) + return src_color; + + return 255 - std::min((255 - back_color) * 255 / src_color, 255); + } + case FXDIB_BLEND_HARDLIGHT: + if (src_color < 128) + return (src_color * back_color * 2) / 255; + + return Blend(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255); + case FXDIB_BLEND_SOFTLIGHT: { + if (src_color < 128) { + return back_color - + (255 - 2 * src_color) * back_color * (255 - back_color) / 255 / + 255; + } + return back_color + + (2 * src_color - 255) * (color_sqrt[back_color] - back_color) / + 255; + } + case FXDIB_BLEND_DIFFERENCE: + return back_color < src_color ? src_color - back_color + : back_color - src_color; + case FXDIB_BLEND_EXCLUSION: + return back_color + src_color - 2 * back_color * src_color / 255; + } + return src_color; +} + +struct RGB { + int red; + int green; + int blue; +}; + +int Lum(RGB color) { + return (color.red * 30 + color.green * 59 + color.blue * 11) / 100; +} + +RGB ClipColor(RGB color) { + int l = Lum(color); + int n = std::min(color.red, std::min(color.green, color.blue)); + int x = std::max(color.red, std::max(color.green, color.blue)); + if (n < 0) { + color.red = l + ((color.red - l) * l / (l - n)); + color.green = l + ((color.green - l) * l / (l - n)); + color.blue = l + ((color.blue - l) * l / (l - n)); + } + if (x > 255) { + color.red = l + ((color.red - l) * (255 - l) / (x - l)); + color.green = l + ((color.green - l) * (255 - l) / (x - l)); + color.blue = l + ((color.blue - l) * (255 - l) / (x - l)); + } + return color; +} + +RGB SetLum(RGB color, int l) { + int d = l - Lum(color); + color.red += d; + color.green += d; + color.blue += d; + return ClipColor(color); +} + +int Sat(RGB color) { + return std::max(color.red, std::max(color.green, color.blue)) - + std::min(color.red, std::min(color.green, color.blue)); +} + +RGB SetSat(RGB color, int s) { + int min = std::min(color.red, std::min(color.green, color.blue)); + int max = std::max(color.red, std::max(color.green, color.blue)); + if (min == max) + return {0, 0, 0}; + + color.red = (color.red - min) * s / (max - min); + color.green = (color.green - min) * s / (max - min); + color.blue = (color.blue - min) * s / (max - min); + return color; +} + +void RGB_Blend(int blend_mode, + const uint8_t* src_scan, + const uint8_t* dest_scan, + int results[3]) { + RGB result = {0, 0, 0}; + RGB src; + src.red = src_scan[2]; + src.green = src_scan[1]; + src.blue = src_scan[0]; + RGB back; + back.red = dest_scan[2]; + back.green = dest_scan[1]; + back.blue = dest_scan[0]; + switch (blend_mode) { + case FXDIB_BLEND_HUE: + result = SetLum(SetSat(src, Sat(back)), Lum(back)); + break; + case FXDIB_BLEND_SATURATION: + result = SetLum(SetSat(back, Sat(src)), Lum(back)); + break; + case FXDIB_BLEND_COLOR: + result = SetLum(src, Lum(back)); + break; + case FXDIB_BLEND_LUMINOSITY: + result = SetLum(back, Lum(src)); + break; + } + results[0] = result.blue; + results[1] = result.green; + results[2] = result.red; +} + +int GetAlpha(uint8_t src_alpha, const uint8_t* clip_scan, int col) { + return clip_scan ? clip_scan[col] * src_alpha / 255 : src_alpha; +} + +void CompositeRow_AlphaToMask(uint8_t* dest_scan, + const uint8_t* src_scan, + int pixel_count, + const uint8_t* clip_scan, + uint8_t stride) { + src_scan += stride - 1; + for (int col = 0; col < pixel_count; ++col) { + int src_alpha = GetAlpha(*src_scan, clip_scan, col); + uint8_t back_alpha = *dest_scan; + if (!back_alpha) + *dest_scan = src_alpha; + else if (src_alpha) + *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; + ++dest_scan; + src_scan += stride; + } +} + +void CompositeRow_Rgb2Mask(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + const uint8_t* clip_scan) { + if (!clip_scan) { + memset(dest_scan, 0xff, width); + return; + } + for (int i = 0; i < width; ++i) { + *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan); + ++dest_scan; + ++clip_scan; + } +} + +uint8_t GetGray(const uint8_t* src_scan) { + return FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); +} + +uint8_t GetGrayWithBlend(const uint8_t* src_scan, + const uint8_t* dest_scan, + int blend_type) { + uint8_t gray = GetGray(src_scan); + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else if (blend_type) + gray = Blend(blend_type, *dest_scan, gray); + return gray; +} + +void CompositeRow_Argb2Graya(uint8_t* dest_scan, + const uint8_t* src_scan, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan, + uint8_t* dst_alpha_scan) { + uint8_t offset = src_alpha_scan ? 3 : 4; + for (int col = 0; col < pixel_count; ++col) { + const uint8_t* alpha_scan = + src_alpha_scan ? src_alpha_scan++ : &src_scan[3]; + uint8_t back_alpha = *dst_alpha_scan; + if (back_alpha == 0) { + int src_alpha = GetAlpha(*alpha_scan, clip_scan, col); + if (src_alpha) { + *dest_scan = GetGray(src_scan); + *dst_alpha_scan = src_alpha; + } + ++dest_scan; + ++dst_alpha_scan; + src_scan += offset; + continue; + } + uint8_t src_alpha = GetAlpha(*alpha_scan, clip_scan, col); + if (src_alpha == 0) { + ++dest_scan; + ++dst_alpha_scan; + src_scan += offset; + continue; + } + *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); + int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); + uint8_t gray = GetGray(src_scan); + // TODO(npm): Does this if really need src_alpha_scan or was that a bug? + if (blend_type && src_alpha_scan) { + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + } + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + ++dest_scan; + ++dst_alpha_scan; + src_scan += offset; + } +} + +void CompositeRow_Argb2Gray(uint8_t* dest_scan, + const uint8_t* src_scan, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan) { + uint8_t gray; + uint8_t offset = src_alpha_scan ? 3 : 4; + for (int col = 0; col < pixel_count; ++col) { + const uint8_t* alpha_scan = + src_alpha_scan ? src_alpha_scan++ : &src_scan[3]; + int src_alpha = GetAlpha(*alpha_scan, clip_scan, col); + if (src_alpha) { + gray = GetGrayWithBlend(src_scan, dest_scan, blend_type); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); + } + ++dest_scan; + src_scan += offset; + } +} + +void CompositeRow_Rgb2Gray(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_Bpp, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + uint8_t gray; + for (int col = 0; col < pixel_count; ++col) { + gray = GetGrayWithBlend(src_scan, dest_scan, blend_type); + if (clip_scan && clip_scan[col] < 255) + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); + else + *dest_scan = gray; + ++dest_scan; + src_scan += src_Bpp; + } +} + +void CompositeRow_Rgb2Graya(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_Bpp, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + for (int col = 0; col < pixel_count; ++col) { + if (blend_type && *dest_alpha_scan == 0) { + *dest_scan = GetGray(src_scan); + ++dest_scan; + ++dest_alpha_scan; + src_scan += src_Bpp; + continue; + } + int src_alpha = clip_scan ? clip_scan[col] : 255; + if (src_alpha == 255) { + *dest_scan = GetGrayWithBlend(src_scan, dest_scan, blend_type); + ++dest_scan; + *dest_alpha_scan = 255; + ++dest_alpha_scan; + src_scan += src_Bpp; + continue; + } + if (src_alpha == 0) { + ++dest_scan; + ++dest_alpha_scan; + src_scan += src_Bpp; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan = dest_alpha; + ++dest_alpha_scan; + int alpha_ratio = src_alpha * 255 / dest_alpha; + uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + ++dest_scan; + src_scan += src_Bpp; + } +} + +void CompositeRow_Argb2Argb(uint8_t* dest_scan, + const uint8_t* src_scan, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan, + const uint8_t* src_alpha_scan) { + int blended_colors[3]; + uint8_t dest_offset = dest_alpha_scan ? 3 : 4; + uint8_t src_offset = src_alpha_scan ? 3 : 4; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + bool has_src = !!src_alpha_scan; + bool has_dest = !!dest_alpha_scan; + for (int col = 0; col < pixel_count; ++col) { + uint8_t back_alpha = has_dest ? *dest_alpha_scan : dest_scan[3]; + const uint8_t* alpha_source = has_src ? src_alpha_scan++ : &src_scan[3]; + uint8_t src_alpha = GetAlpha(*alpha_source, clip_scan, col); + if (back_alpha == 0) { + if (!has_dest && !has_src) { + if (clip_scan) { + FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) | + (src_alpha << 24)); + } else { + FXARGB_COPY(dest_scan, src_scan); + } + } else if (has_dest) { + *dest_alpha_scan = src_alpha; + for (int i = 0; i < 3; ++i) { + *dest_scan = *src_scan++; + ++dest_scan; + } + ++dest_alpha_scan; + if (!has_src) + ++src_scan; + } else { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2], + src_scan[1], *src_scan)); + } + if (!has_dest) { + dest_scan += dest_offset; + src_scan += src_offset; + } + continue; + } + if (src_alpha == 0) { + dest_scan += dest_offset; + src_scan += src_offset; + if (has_dest) + ++dest_alpha_scan; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + if (has_dest) { + *dest_alpha_scan = dest_alpha; + ++dest_alpha_scan; + } else { + dest_scan[3] = dest_alpha; + } + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (bNonseparableBlend) + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + for (int color = 0; color < 3; ++color) { + if (blend_type) { + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, *dest_scan, *src_scan); + blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); + } + ++dest_scan; + ++src_scan; + } + if (!has_dest) + ++dest_scan; + if (!has_src) + ++src_scan; + } +} + +void CompositeRow_Rgb2Argb_Blend_NoClip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int src_Bpp, + uint8_t* dest_alpha_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; ++col) { + uint8_t* dest_alpha = dest_alpha_scan ? dest_alpha_scan : &dest_scan[3]; + uint8_t back_alpha = *dest_alpha; + if (back_alpha == 0) { + if (dest_alpha_scan) { + for (int i = 0; i < 3; ++i) { + *dest_scan = *src_scan++; + ++dest_scan; + } + *dest_alpha_scan = 0xff; + ++dest_alpha_scan; + } else { + if (src_Bpp == 4) { + FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); + } else { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], + src_scan[0])); + } + dest_scan += 4; + } + src_scan += src_Bpp; + continue; + } + *dest_alpha = 0xff; + if (bNonseparableBlend) + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + for (int color = 0; color < 3; ++color) { + int src_color = *src_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, *dest_scan, src_color); + *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); + ++dest_scan; + ++src_scan; + } + if (dest_alpha_scan) + ++dest_alpha_scan; + else + ++dest_scan; + src_scan += src_gap; + } +} + +void CompositeRow_Rgb2Argb_Blend_Clip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int src_Bpp, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int src_gap = src_Bpp - 3; + bool has_dest = !!dest_alpha_scan; + for (int col = 0; col < width; ++col) { + int src_alpha = *clip_scan++; + uint8_t back_alpha = has_dest ? *dest_alpha_scan : dest_scan[3]; + if (back_alpha == 0) { + for (int i = 0; i < 3; ++i) { + *dest_scan = *src_scan++; + ++dest_scan; + } + src_scan += src_gap; + if (has_dest) + dest_alpha_scan++; + else + dest_scan++; + continue; + } + if (src_alpha == 0) { + dest_scan += has_dest ? 3 : 4; + if (has_dest) + dest_alpha_scan++; + src_scan += src_Bpp; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + if (has_dest) + *dest_alpha_scan++ = dest_alpha; + else + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (bNonseparableBlend) + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + for (int color = 0; color < 3; color++) { + int src_color = *src_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, *dest_scan, src_color); + blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + src_scan++; + } + src_scan += src_gap; + if (!has_dest) + dest_scan++; + } +} + +void CompositeRow_Rgb2Argb_NoBlend_Clip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int src_Bpp, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + int src_gap = src_Bpp - 3; + if (dest_alpha_scan) { + for (int col = 0; col < width; col++) { + int src_alpha = clip_scan[col]; + if (src_alpha == 255) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_alpha_scan++ = 255; + src_scan += src_gap; + continue; + } + if (src_alpha == 0) { + dest_scan += 3; + dest_alpha_scan++; + src_scan += src_Bpp; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + for (int color = 0; color < 3; color++) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); + dest_scan++; + src_scan++; + } + src_scan += src_gap; + } + } else { + for (int col = 0; col < width; col++) { + int src_alpha = clip_scan[col]; + if (src_alpha == 255) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = 255; + src_scan += src_gap; + continue; + } + if (src_alpha == 0) { + dest_scan += 4; + src_scan += src_Bpp; + continue; + } + int back_alpha = dest_scan[3]; + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + for (int color = 0; color < 3; color++) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); + dest_scan++; + src_scan++; + } + dest_scan++; + src_scan += src_gap; + } + } +} + +void CompositeRow_Rgb2Argb_NoBlend_NoClip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int src_Bpp, + uint8_t* dest_alpha_scan) { + if (dest_alpha_scan) { + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_alpha_scan++ = 0xff; + src_scan += src_gap; + } + } else { + for (int col = 0; col < width; col++) { + if (src_Bpp == 4) { + FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); + } else { + FXARGB_SETDIB(dest_scan, + FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); + } + dest_scan += 4; + src_scan += src_Bpp; + } + } +} + +void CompositeRow_Argb2Rgb_Blend(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int dest_Bpp, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int dest_gap = dest_Bpp - 3; + if (src_alpha_scan) { + for (int col = 0; col < width; col++) { + uint8_t src_alpha; + if (clip_scan) { + src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; + } else { + src_alpha = *src_alpha_scan++; + } + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += 3; + continue; + } + if (bNonseparableBlend) { + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + } + for (int color = 0; color < 3; color++) { + int back_color = *dest_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, *src_scan); + *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + dest_scan++; + src_scan++; + } + dest_scan += dest_gap; + } + } else { + for (int col = 0; col < width; col++) { + uint8_t src_alpha; + if (clip_scan) { + src_alpha = src_scan[3] * (*clip_scan++) / 255; + } else { + src_alpha = src_scan[3]; + } + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += 4; + continue; + } + if (bNonseparableBlend) { + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + } + for (int color = 0; color < 3; color++) { + int back_color = *dest_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, *src_scan); + *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + dest_scan++; + src_scan++; + } + dest_scan += dest_gap; + src_scan++; + } + } +} + +void CompositeRow_Argb2Rgb_NoBlend(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int dest_Bpp, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan) { + int dest_gap = dest_Bpp - 3; + if (src_alpha_scan) { + for (int col = 0; col < width; col++) { + uint8_t src_alpha; + if (clip_scan) { + src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; + } else { + src_alpha = *src_alpha_scan++; + } + if (src_alpha == 255) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + dest_scan += dest_gap; + continue; + } + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += 3; + continue; + } + for (int color = 0; color < 3; color++) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); + dest_scan++; + src_scan++; + } + dest_scan += dest_gap; + } + } else { + for (int col = 0; col < width; col++) { + uint8_t src_alpha; + if (clip_scan) { + src_alpha = src_scan[3] * (*clip_scan++) / 255; + } else { + src_alpha = src_scan[3]; + } + if (src_alpha == 255) { + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + *dest_scan++ = *src_scan++; + dest_scan += dest_gap; + src_scan++; + continue; + } + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += 4; + continue; + } + for (int color = 0; color < 3; color++) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); + dest_scan++; + src_scan++; + } + dest_scan += dest_gap; + src_scan++; + } + } +} + +void CompositeRow_Rgb2Rgb_Blend_NoClip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int dest_Bpp, + int src_Bpp) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int dest_gap = dest_Bpp - 3; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + if (bNonseparableBlend) { + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + } + for (int color = 0; color < 3; color++) { + int back_color = *dest_scan; + int src_color = *src_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, src_color); + *dest_scan = blended; + dest_scan++; + src_scan++; + } + dest_scan += dest_gap; + src_scan += src_gap; + } +} + +void CompositeRow_Rgb2Rgb_Blend_Clip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int dest_Bpp, + int src_Bpp, + const uint8_t* clip_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int dest_gap = dest_Bpp - 3; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + uint8_t src_alpha = *clip_scan++; + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += src_Bpp; + continue; + } + if (bNonseparableBlend) { + RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); + } + for (int color = 0; color < 3; color++) { + int src_color = *src_scan; + int back_color = *dest_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, src_color); + *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + dest_scan++; + src_scan++; + } + dest_scan += dest_gap; + src_scan += src_gap; + } +} + +void CompositeRow_Rgb2Rgb_NoBlend_NoClip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int dest_Bpp, + int src_Bpp) { + if (dest_Bpp == src_Bpp) { + memcpy(dest_scan, src_scan, width * dest_Bpp); + return; + } + for (int col = 0; col < width; col++) { + dest_scan[0] = src_scan[0]; + dest_scan[1] = src_scan[1]; + dest_scan[2] = src_scan[2]; + dest_scan += dest_Bpp; + src_scan += src_Bpp; + } +} + +void CompositeRow_Rgb2Rgb_NoBlend_Clip(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int dest_Bpp, + int src_Bpp, + const uint8_t* clip_scan) { + for (int col = 0; col < width; col++) { + int src_alpha = clip_scan[col]; + if (src_alpha == 255) { + dest_scan[0] = src_scan[0]; + dest_scan[1] = src_scan[1]; + dest_scan[2] = src_scan[2]; + } else if (src_alpha) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); + dest_scan++; + src_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); + dest_scan++; + src_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); + dest_scan += dest_Bpp - 2; + src_scan += src_Bpp - 2; + continue; + } + dest_scan += dest_Bpp; + src_scan += src_Bpp; + } +} + +void CompositeRow_8bppPal2Gray(uint8_t* dest_scan, + const uint8_t* src_scan, + const uint8_t* pPalette, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan) { + if (src_alpha_scan) { + if (blend_type) { + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); + if (bNonseparableBlend) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + if (src_alpha) + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); + else + *dest_scan = gray; + dest_scan++; + src_scan++; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); + if (src_alpha) + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); + else + *dest_scan = gray; + dest_scan++; + src_scan++; + } + } else { + if (blend_type) { + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + if (bNonseparableBlend) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + if (clip_scan && clip_scan[col] < 255) + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); + else + *dest_scan = gray; + dest_scan++; + src_scan++; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + if (clip_scan && clip_scan[col] < 255) + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); + else + *dest_scan = gray; + dest_scan++; + src_scan++; + } + } +} + +void CompositeRow_8bppPal2Graya(uint8_t* dest_scan, + const uint8_t* src_scan, + const uint8_t* pPalette, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan, + const uint8_t* src_alpha_scan) { + if (src_alpha_scan) { + if (blend_type) { + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + src_scan++; + uint8_t back_alpha = *dest_alpha_scan; + if (back_alpha == 0) { + int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); + if (src_alpha) { + *dest_scan = gray; + *dest_alpha_scan = src_alpha; + } + dest_scan++; + dest_alpha_scan++; + continue; + } + uint8_t src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + *dest_alpha_scan = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); + if (bNonseparableBlend) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + dest_alpha_scan++; + dest_scan++; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + src_scan++; + uint8_t back_alpha = *dest_alpha_scan; + if (back_alpha == 0) { + int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); + if (src_alpha) { + *dest_scan = gray; + *dest_alpha_scan = src_alpha; + } + dest_scan++; + dest_alpha_scan++; + continue; + } + uint8_t src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col); + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; + int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); + dest_alpha_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + dest_scan++; + } + } else { + if (blend_type) { + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + src_scan++; + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = gray; + *dest_alpha_scan++ = 255; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (bNonseparableBlend) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + dest_scan++; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = pPalette[*src_scan]; + src_scan++; + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = gray; + *dest_alpha_scan++ = 255; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + dest_scan++; + } + } +} + +void CompositeRow_1bppPal2Gray(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + const uint8_t* pPalette, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + int reset_gray = pPalette[0]; + int set_gray = pPalette[1]; + if (blend_type) { + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = + (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) + ? set_gray + : reset_gray; + if (bNonseparableBlend) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + if (clip_scan && clip_scan[col] < 255) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); + } else { + *dest_scan = gray; + } + dest_scan++; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = + (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) + ? set_gray + : reset_gray; + if (clip_scan && clip_scan[col] < 255) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); + } else { + *dest_scan = gray; + } + dest_scan++; + } +} + +void CompositeRow_1bppPal2Graya(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + const uint8_t* pPalette, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + int reset_gray = pPalette[0]; + int set_gray = pPalette[1]; + if (blend_type) { + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = + (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) + ? set_gray + : reset_gray; + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = gray; + *dest_alpha_scan++ = 255; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (bNonseparableBlend) + gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; + else + gray = Blend(blend_type, *dest_scan, gray); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + dest_scan++; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + uint8_t gray = + (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) + ? set_gray + : reset_gray; + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = gray; + *dest_alpha_scan++ = 255; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); + dest_scan++; + } +} + +void CompositeRow_8bppRgb2Rgb_NoBlend(uint8_t* dest_scan, + const uint8_t* src_scan, + uint32_t* pPalette, + int pixel_count, + int DestBpp, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan) { + if (src_alpha_scan) { + int dest_gap = DestBpp - 3; + FX_ARGB argb = 0; + for (int col = 0; col < pixel_count; col++) { + argb = pPalette[*src_scan]; + int src_r = FXARGB_R(argb); + int src_g = FXARGB_G(argb); + int src_b = FXARGB_B(argb); + src_scan++; + uint8_t src_alpha = 0; + if (clip_scan) { + src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; + } else { + src_alpha = *src_alpha_scan++; + } + if (src_alpha == 255) { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + dest_scan += dest_gap; + continue; + } + if (src_alpha == 0) { + dest_scan += DestBpp; + continue; + } + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); + dest_scan++; + dest_scan += dest_gap; + } + } else { + FX_ARGB argb = 0; + for (int col = 0; col < pixel_count; col++) { + argb = pPalette[*src_scan]; + int src_r = FXARGB_R(argb); + int src_g = FXARGB_G(argb); + int src_b = FXARGB_B(argb); + if (clip_scan && clip_scan[col] < 255) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); + dest_scan++; + } else { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + } + if (DestBpp == 4) { + dest_scan++; + } + src_scan++; + } + } +} + +void CompositeRow_1bppRgb2Rgb_NoBlend(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + uint32_t* pPalette, + int pixel_count, + int DestBpp, + const uint8_t* clip_scan) { + int reset_r, reset_g, reset_b; + int set_r, set_g, set_b; + reset_r = FXARGB_R(pPalette[0]); + reset_g = FXARGB_G(pPalette[0]); + reset_b = FXARGB_B(pPalette[0]); + set_r = FXARGB_R(pPalette[1]); + set_g = FXARGB_G(pPalette[1]); + set_b = FXARGB_B(pPalette[1]); + for (int col = 0; col < pixel_count; col++) { + int src_r, src_g, src_b; + if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { + src_r = set_r; + src_g = set_g; + src_b = set_b; + } else { + src_r = reset_r; + src_g = reset_g; + src_b = reset_b; + } + if (clip_scan && clip_scan[col] < 255) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); + dest_scan++; + } else { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + } + if (DestBpp == 4) { + dest_scan++; + } + } +} + +void CompositeRow_8bppRgb2Argb_NoBlend(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + uint32_t* pPalette, + const uint8_t* clip_scan, + const uint8_t* src_alpha_scan) { + if (src_alpha_scan) { + for (int col = 0; col < width; col++) { + FX_ARGB argb = pPalette[*src_scan]; + src_scan++; + int src_r = FXARGB_R(argb); + int src_g = FXARGB_G(argb); + int src_b = FXARGB_B(argb); + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + if (clip_scan) { + int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); + } else { + FXARGB_SETDIB(dest_scan, + FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b)); + } + dest_scan += 4; + src_alpha_scan++; + continue; + } + uint8_t src_alpha; + if (clip_scan) { + src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; + } else { + src_alpha = *src_alpha_scan++; + } + if (src_alpha == 0) { + dest_scan += 4; + continue; + } + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + dest_scan++; + dest_scan++; + } + } else { + for (int col = 0; col < width; col++) { + FX_ARGB argb = pPalette[*src_scan]; + int src_r = FXARGB_R(argb); + int src_g = FXARGB_G(argb); + int src_b = FXARGB_B(argb); + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + *dest_scan++ = 255; + src_scan++; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan += 4; + src_scan++; + continue; + } + int back_alpha = dest_scan[3]; + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + dest_scan++; + dest_scan++; + src_scan++; + } + } +} + +void CompositeRow_1bppRgb2Argb_NoBlend(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + uint32_t* pPalette, + const uint8_t* clip_scan) { + int reset_r, reset_g, reset_b; + int set_r, set_g, set_b; + reset_r = FXARGB_R(pPalette[0]); + reset_g = FXARGB_G(pPalette[0]); + reset_b = FXARGB_B(pPalette[0]); + set_r = FXARGB_R(pPalette[1]); + set_g = FXARGB_G(pPalette[1]); + set_b = FXARGB_B(pPalette[1]); + for (int col = 0; col < width; col++) { + int src_r, src_g, src_b; + if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { + src_r = set_r; + src_g = set_g; + src_b = set_b; + } else { + src_r = reset_r; + src_g = reset_g; + src_b = reset_b; + } + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + *dest_scan++ = 255; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan += 4; + continue; + } + int back_alpha = dest_scan[3]; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + dest_scan++; + dest_scan++; + } +} + +void CompositeRow_1bppRgb2Rgba_NoBlend(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + uint32_t* pPalette, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + int reset_r, reset_g, reset_b; + int set_r, set_g, set_b; + reset_r = FXARGB_R(pPalette[0]); + reset_g = FXARGB_G(pPalette[0]); + reset_b = FXARGB_B(pPalette[0]); + set_r = FXARGB_R(pPalette[1]); + set_g = FXARGB_G(pPalette[1]); + set_b = FXARGB_B(pPalette[1]); + for (int col = 0; col < width; col++) { + int src_r, src_g, src_b; + if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { + src_r = set_r; + src_g = set_g; + src_b = set_b; + } else { + src_r = reset_r; + src_g = reset_g; + src_b = reset_b; + } + if (!clip_scan || clip_scan[col] == 255) { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + *dest_alpha_scan++ = 255; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan += 3; + dest_alpha_scan++; + continue; + } + int back_alpha = *dest_alpha_scan; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + dest_scan++; + } +} + +void CompositeRow_ByteMask2Argb(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); + dest_scan += 4; + continue; + } + if (src_alpha == 0) { + dest_scan += 4; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + RGB_Blend(blend_type, scan, dest_scan, blended_colors); + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); + dest_scan++; + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); + dest_scan++; + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); + } else if (blend_type) { + int blended = Blend(blend_type, *dest_scan, src_b); + blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_g); + blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_r); + blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + } + dest_scan += 2; + } +} + +void CompositeRow_ByteMask2Rgba(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int pixel_count, + int blend_type, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + uint8_t back_alpha = *dest_alpha_scan; + if (back_alpha == 0) { + *dest_scan++ = src_b; + *dest_scan++ = src_g; + *dest_scan++ = src_r; + *dest_alpha_scan++ = src_alpha; + continue; + } + if (src_alpha == 0) { + dest_scan += 3; + dest_alpha_scan++; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + RGB_Blend(blend_type, scan, dest_scan, blended_colors); + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); + dest_scan++; + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); + dest_scan++; + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); + dest_scan++; + } else if (blend_type) { + int blended = Blend(blend_type, *dest_scan, src_b); + blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_g); + blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_r); + blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + dest_scan++; + } + } +} + +void CompositeRow_ByteMask2Rgb(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int pixel_count, + int blend_type, + int Bpp, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + if (src_alpha == 0) { + dest_scan += Bpp; + continue; + } + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + RGB_Blend(blend_type, scan, dest_scan, blended_colors); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); + } else if (blend_type) { + int blended = Blend(blend_type, *dest_scan, src_b); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_g); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_r); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); + } + dest_scan += Bpp - 2; + } +} + +void CompositeRow_ByteMask2Mask(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int pixel_count, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + uint8_t back_alpha = *dest_scan; + if (!back_alpha) { + *dest_scan = src_alpha; + } else if (src_alpha) { + *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; + } + dest_scan++; + } +} + +void CompositeRow_ByteMask2Gray(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_gray, + int pixel_count, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + if (src_alpha) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); + } + dest_scan++; + } +} + +void CompositeRow_ByteMask2Graya(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_gray, + int pixel_count, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + uint8_t back_alpha = *dest_alpha_scan; + if (back_alpha == 0) { + *dest_scan++ = src_gray; + *dest_alpha_scan++ = src_alpha; + continue; + } + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); + dest_scan++; + } +} + +void CompositeRow_BitMask2Argb(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int src_left, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { + FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); + for (int col = 0; col < pixel_count; col++) { + if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { + FXARGB_SETDIB(dest_scan, argb); + } + dest_scan += 4; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan += 4; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); + dest_scan += 4; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + RGB_Blend(blend_type, scan, dest_scan, blended_colors); + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); + dest_scan++; + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); + dest_scan++; + *dest_scan = + FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); + } else if (blend_type) { + int blended = Blend(blend_type, *dest_scan, src_b); + blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_g); + blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_r); + blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + } + dest_scan += 2; + } +} + +void CompositeRow_BitMask2Rgb(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int src_left, + int pixel_count, + int blend_type, + int Bpp, + const uint8_t* clip_scan) { + if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { + for (int col = 0; col < pixel_count; col++) { + if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { + dest_scan[2] = src_r; + dest_scan[1] = src_g; + dest_scan[0] = src_b; + } + dest_scan += Bpp; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan += Bpp; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + if (src_alpha == 0) { + dest_scan += Bpp; + continue; + } + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + RGB_Blend(blend_type, scan, dest_scan, blended_colors); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); + } else if (blend_type) { + int blended = Blend(blend_type, *dest_scan, src_b); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_g); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); + dest_scan++; + blended = Blend(blend_type, *dest_scan, src_r); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); + } + dest_scan += Bpp - 2; + } +} + +void CompositeRow_BitMask2Mask(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_left, + int pixel_count, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan++; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + uint8_t back_alpha = *dest_scan; + if (!back_alpha) { + *dest_scan = src_alpha; + } else if (src_alpha) { + *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; + } + dest_scan++; + } +} + +void CompositeRow_BitMask2Gray(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_gray, + int src_left, + int pixel_count, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan++; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + if (src_alpha) { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); + } + dest_scan++; + } +} + +void CompositeRow_BitMask2Graya(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_gray, + int src_left, + int pixel_count, + const uint8_t* clip_scan, + uint8_t* dest_alpha_scan) { + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan++; + dest_alpha_scan++; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + uint8_t back_alpha = *dest_alpha_scan; + if (back_alpha == 0) { + *dest_scan++ = src_gray; + *dest_alpha_scan++ = src_alpha; + continue; + } + if (src_alpha == 0) { + dest_scan++; + dest_alpha_scan++; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + *dest_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); + dest_scan++; + } +} + +void CompositeRow_Argb2Argb_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < pixel_count; col++) { + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + if (clip_scan) { + int src_alpha = clip_scan[col] * src_scan[3] / 255; + dest_scan[3] = src_alpha; + dest_scan[0] = src_scan[2]; + dest_scan[1] = src_scan[1]; + dest_scan[2] = src_scan[0]; + } else { + FXARGB_RGBORDERCOPY(dest_scan, src_scan); + } + dest_scan += 4; + src_scan += 4; + continue; + } + uint8_t src_alpha; + if (clip_scan) { + src_alpha = clip_scan[col] * src_scan[3] / 255; + } else { + src_alpha = src_scan[3]; + } + if (src_alpha == 0) { + dest_scan += 4; + src_scan += 4; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (bNonseparableBlend) { + uint8_t dest_scan_o[3]; + dest_scan_o[0] = dest_scan[2]; + dest_scan_o[1] = dest_scan[1]; + dest_scan_o[2] = dest_scan[0]; + RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + if (blend_type) { + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, dest_scan[index], *src_scan); + blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); + dest_scan[index] = + FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); + } else { + dest_scan[index] = + FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); + } + src_scan++; + } + dest_scan += 4; + src_scan++; + } +} + +void CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int src_Bpp) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + if (src_Bpp == 4) { + FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); + } else { + FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], + src_scan[1], src_scan[0])); + } + dest_scan += 4; + src_scan += src_Bpp; + continue; + } + dest_scan[3] = 0xff; + if (bNonseparableBlend) { + uint8_t dest_scan_o[3]; + dest_scan_o[0] = dest_scan[2]; + dest_scan_o[1] = dest_scan[1]; + dest_scan_o[2] = dest_scan[0]; + RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + int src_color = *src_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, dest_scan[index], src_color); + dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); + src_scan++; + } + dest_scan += 4; + src_scan += src_gap; + } +} + +void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int dest_Bpp, + const uint8_t* clip_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + for (int col = 0; col < width; col++) { + uint8_t src_alpha; + if (clip_scan) { + src_alpha = src_scan[3] * (*clip_scan++) / 255; + } else { + src_alpha = src_scan[3]; + } + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += 4; + continue; + } + if (bNonseparableBlend) { + uint8_t dest_scan_o[3]; + dest_scan_o[0] = dest_scan[2]; + dest_scan_o[1] = dest_scan[1]; + dest_scan_o[2] = dest_scan[0]; + RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + int back_color = dest_scan[index]; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, *src_scan); + dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + src_scan++; + } + dest_scan += dest_Bpp; + src_scan++; + } +} + +void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int src_Bpp) { + for (int col = 0; col < width; col++) { + if (src_Bpp == 4) { + FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); + } else { + FXARGB_SETRGBORDERDIB( + dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); + } + dest_scan += 4; + src_scan += src_Bpp; + } +} + +void CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int dest_Bpp, + int src_Bpp) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + if (bNonseparableBlend) { + uint8_t dest_scan_o[3]; + dest_scan_o[0] = dest_scan[2]; + dest_scan_o[1] = dest_scan[1]; + dest_scan_o[2] = dest_scan[0]; + RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + int back_color = dest_scan[index]; + int src_color = *src_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, src_color); + dest_scan[index] = blended; + src_scan++; + } + dest_scan += dest_Bpp; + src_scan += src_gap; + } +} + +void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int dest_Bpp, + const uint8_t* clip_scan) { + for (int col = 0; col < width; col++) { + uint8_t src_alpha; + if (clip_scan) { + src_alpha = src_scan[3] * (*clip_scan++) / 255; + } else { + src_alpha = src_scan[3]; + } + if (src_alpha == 255) { + dest_scan[2] = *src_scan++; + dest_scan[1] = *src_scan++; + dest_scan[0] = *src_scan++; + dest_scan += dest_Bpp; + src_scan++; + continue; + } + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += 4; + continue; + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + dest_scan[index] = + FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha); + src_scan++; + } + dest_scan += dest_Bpp; + src_scan++; + } +} + +void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int dest_Bpp, + int src_Bpp) { + for (int col = 0; col < width; col++) { + dest_scan[2] = src_scan[0]; + dest_scan[1] = src_scan[1]; + dest_scan[0] = src_scan[2]; + dest_scan += dest_Bpp; + src_scan += src_Bpp; + } +} + +void CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int src_Bpp, + const uint8_t* clip_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + int src_alpha = *clip_scan++; + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + dest_scan[2] = *src_scan++; + dest_scan[1] = *src_scan++; + dest_scan[0] = *src_scan++; + src_scan += src_gap; + dest_scan += 4; + continue; + } + if (src_alpha == 0) { + dest_scan += 4; + src_scan += src_Bpp; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (bNonseparableBlend) { + uint8_t dest_scan_o[3]; + dest_scan_o[0] = dest_scan[2]; + dest_scan_o[1] = dest_scan[1]; + dest_scan_o[2] = dest_scan[0]; + RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + int src_color = *src_scan; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, dest_scan[index], src_color); + blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); + dest_scan[index] = + FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); + src_scan++; + } + dest_scan += 4; + src_scan += src_gap; + } +} + +void CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int blend_type, + int dest_Bpp, + int src_Bpp, + const uint8_t* clip_scan) { + int blended_colors[3]; + bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + uint8_t src_alpha = *clip_scan++; + if (src_alpha == 0) { + dest_scan += dest_Bpp; + src_scan += src_Bpp; + continue; + } + if (bNonseparableBlend) { + uint8_t dest_scan_o[3]; + dest_scan_o[0] = dest_scan[2]; + dest_scan_o[1] = dest_scan[1]; + dest_scan_o[2] = dest_scan[0]; + RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); + } + for (int color = 0; color < 3; color++) { + int index = 2 - color; + int src_color = *src_scan; + int back_color = dest_scan[index]; + int blended = bNonseparableBlend + ? blended_colors[color] + : Blend(blend_type, back_color, src_color); + dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + src_scan++; + } + dest_scan += dest_Bpp; + src_scan += src_gap; + } +} + +void CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int src_Bpp, + const uint8_t* clip_scan) { + int src_gap = src_Bpp - 3; + for (int col = 0; col < width; col++) { + int src_alpha = clip_scan[col]; + if (src_alpha == 255) { + dest_scan[2] = *src_scan++; + dest_scan[1] = *src_scan++; + dest_scan[0] = *src_scan++; + dest_scan[3] = 255; + dest_scan += 4; + src_scan += src_gap; + continue; + } + if (src_alpha == 0) { + dest_scan += 4; + src_scan += src_Bpp; + continue; + } + int back_alpha = dest_scan[3]; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + for (int color = 0; color < 3; color++) { + int index = 2 - color; + dest_scan[index] = + FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); + src_scan++; + } + dest_scan += 4; + src_scan += src_gap; + } +} + +void CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + int dest_Bpp, + int src_Bpp, + const uint8_t* clip_scan) { + for (int col = 0; col < width; col++) { + int src_alpha = clip_scan[col]; + if (src_alpha == 255) { + dest_scan[2] = src_scan[0]; + dest_scan[1] = src_scan[1]; + dest_scan[0] = src_scan[2]; + } else if (src_alpha) { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], *src_scan, src_alpha); + src_scan++; + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], *src_scan, src_alpha); + src_scan++; + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], *src_scan, src_alpha); + dest_scan += dest_Bpp; + src_scan += src_Bpp - 2; + continue; + } + dest_scan += dest_Bpp; + src_scan += src_Bpp; + } +} + +void CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + FX_ARGB* pPalette, + int pixel_count, + int DestBpp, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101; + int src_r = FXARGB_R(argb); + int src_g = FXARGB_G(argb); + int src_b = FXARGB_B(argb); + if (clip_scan && clip_scan[col] < 255) { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); + } else { + dest_scan[2] = src_b; + dest_scan[1] = src_g; + dest_scan[0] = src_r; + } + dest_scan += DestBpp; + src_scan++; + } +} + +void CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + FX_ARGB* pPalette, + int pixel_count, + int DestBpp, + const uint8_t* clip_scan) { + int reset_r, reset_g, reset_b; + int set_r, set_g, set_b; + if (pPalette) { + reset_r = FXARGB_R(pPalette[0]); + reset_g = FXARGB_G(pPalette[0]); + reset_b = FXARGB_B(pPalette[0]); + set_r = FXARGB_R(pPalette[1]); + set_g = FXARGB_G(pPalette[1]); + set_b = FXARGB_B(pPalette[1]); + } else { + reset_r = reset_g = reset_b = 0; + set_r = set_g = set_b = 255; + } + for (int col = 0; col < pixel_count; col++) { + int src_r, src_g, src_b; + if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { + src_r = set_r; + src_g = set_g; + src_b = set_b; + } else { + src_r = reset_r; + src_g = reset_g; + src_b = reset_b; + } + if (clip_scan && clip_scan[col] < 255) { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); + } else { + dest_scan[2] = src_b; + dest_scan[1] = src_g; + dest_scan[0] = src_r; + } + dest_scan += DestBpp; + } +} + +void CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + FX_ARGB* pPalette, + const uint8_t* clip_scan) { + for (int col = 0; col < width; col++) { + int src_r, src_g, src_b; + if (pPalette) { + FX_ARGB argb = pPalette[*src_scan]; + src_r = FXARGB_R(argb); + src_g = FXARGB_G(argb); + src_b = FXARGB_B(argb); + } else { + src_r = src_g = src_b = *src_scan; + } + if (!clip_scan || clip_scan[col] == 255) { + dest_scan[2] = src_b; + dest_scan[1] = src_g; + dest_scan[0] = src_r; + dest_scan[3] = 255; + src_scan++; + dest_scan += 4; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan += 4; + src_scan++; + continue; + } + int back_alpha = dest_scan[3]; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); + dest_scan += 4; + src_scan++; + } +} + +void CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + FX_ARGB* pPalette, + const uint8_t* clip_scan) { + int reset_r, reset_g, reset_b; + int set_r, set_g, set_b; + if (pPalette) { + reset_r = FXARGB_R(pPalette[0]); + reset_g = FXARGB_G(pPalette[0]); + reset_b = FXARGB_B(pPalette[0]); + set_r = FXARGB_R(pPalette[1]); + set_g = FXARGB_G(pPalette[1]); + set_b = FXARGB_B(pPalette[1]); + } else { + reset_r = reset_g = reset_b = 0; + set_r = set_g = set_b = 255; + } + for (int col = 0; col < width; col++) { + int src_r, src_g, src_b; + if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { + src_r = set_r; + src_g = set_g; + src_b = set_b; + } else { + src_r = reset_r; + src_g = reset_g; + src_b = reset_b; + } + if (!clip_scan || clip_scan[col] == 255) { + dest_scan[2] = src_b; + dest_scan[1] = src_g; + dest_scan[0] = src_r; + dest_scan[3] = 255; + dest_scan += 4; + continue; + } + int src_alpha = clip_scan[col]; + if (src_alpha == 0) { + dest_scan += 4; + continue; + } + int back_alpha = dest_scan[3]; + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); + dest_scan += 4; + } +} + +void CompositeRow_ByteMask2Argb_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETRGBORDERDIB(dest_scan, + FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); + dest_scan += 4; + continue; + } + if (src_alpha == 0) { + dest_scan += 4; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; + RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); + dest_scan[2] = + FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); + dest_scan[1] = + FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); + dest_scan[0] = + FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); + } else if (blend_type) { + int blended = Blend(blend_type, dest_scan[2], src_b); + blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); + blended = Blend(blend_type, dest_scan[1], src_g); + blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); + blended = Blend(blend_type, dest_scan[0], src_r); + blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); + } else { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); + } + dest_scan += 4; + } +} + +void CompositeRow_ByteMask2Rgb_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int pixel_count, + int blend_type, + int Bpp, + const uint8_t* clip_scan) { + for (int col = 0; col < pixel_count; col++) { + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; + } else { + src_alpha = mask_alpha * src_scan[col] / 255; + } + if (src_alpha == 0) { + dest_scan += Bpp; + continue; + } + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; + RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); + dest_scan[2] = + FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); + dest_scan[1] = + FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); + dest_scan[0] = + FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); + } else if (blend_type) { + int blended = Blend(blend_type, dest_scan[2], src_b); + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha); + blended = Blend(blend_type, dest_scan[1], src_g); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha); + blended = Blend(blend_type, dest_scan[0], src_r); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha); + } else { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); + } + dest_scan += Bpp; + } +} + +void CompositeRow_BitMask2Argb_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int src_left, + int pixel_count, + int blend_type, + const uint8_t* clip_scan) { + if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { + FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); + for (int col = 0; col < pixel_count; col++) { + if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { + FXARGB_SETRGBORDERDIB(dest_scan, argb); + } + dest_scan += 4; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan += 4; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETRGBORDERDIB(dest_scan, + FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); + dest_scan += 4; + continue; + } + uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; + RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); + dest_scan[2] = + FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); + dest_scan[1] = + FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); + dest_scan[0] = + FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); + } else if (blend_type) { + int blended = Blend(blend_type, dest_scan[2], src_b); + blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); + blended = Blend(blend_type, dest_scan[1], src_g); + blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); + blended = Blend(blend_type, dest_scan[0], src_r); + blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); + } else { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); + } + dest_scan += 4; + } +} + +void CompositeRow_BitMask2Rgb_RgbByteOrder(uint8_t* dest_scan, + const uint8_t* src_scan, + int mask_alpha, + int src_r, + int src_g, + int src_b, + int src_left, + int pixel_count, + int blend_type, + int Bpp, + const uint8_t* clip_scan) { + if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { + for (int col = 0; col < pixel_count; col++) { + if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { + dest_scan[2] = src_b; + dest_scan[1] = src_g; + dest_scan[0] = src_r; + } + dest_scan += Bpp; + } + return; + } + for (int col = 0; col < pixel_count; col++) { + if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { + dest_scan += Bpp; + continue; + } + int src_alpha; + if (clip_scan) { + src_alpha = mask_alpha * clip_scan[col] / 255; + } else { + src_alpha = mask_alpha; + } + if (src_alpha == 0) { + dest_scan += Bpp; + continue; + } + if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { + int blended_colors[3]; + uint8_t scan[3] = {static_cast(src_b), + static_cast(src_g), + static_cast(src_r)}; + uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; + RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); + dest_scan[2] = + FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); + dest_scan[1] = + FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); + dest_scan[0] = + FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); + } else if (blend_type) { + int back_color = dest_scan[2]; + int blended = Blend(blend_type, back_color, src_b); + dest_scan[2] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + back_color = dest_scan[1]; + blended = Blend(blend_type, back_color, src_g); + dest_scan[1] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + back_color = dest_scan[0]; + blended = Blend(blend_type, back_color, src_r); + dest_scan[0] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); + } else { + dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); + dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); + dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); + } + dest_scan += Bpp; + } +} + +} // namespace + +CFX_ScanlineCompositor::CFX_ScanlineCompositor() + : m_BlendType(FXDIB_BLEND_NORMAL), m_bRgbByteOrder(false) {} + +CFX_ScanlineCompositor::~CFX_ScanlineCompositor() {} + +bool CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, + FXDIB_Format src_format, + int32_t width, + uint32_t* pSrcPalette, + uint32_t mask_color, + int blend_type, + bool bClip, + bool bRgbByteOrder, + int alpha_flag) { + m_SrcFormat = src_format; + m_DestFormat = dest_format; + m_BlendType = blend_type; + m_bRgbByteOrder = bRgbByteOrder; + if ((dest_format & 0xff) == 1) + return false; + if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) { + InitSourceMask(alpha_flag, mask_color); + return true; + } + if ((~src_format & 0x0400) && (dest_format & 0x0400)) + return false; + if ((m_SrcFormat & 0xff) <= 8) { + if (dest_format == FXDIB_8bppMask) + return true; + + InitSourcePalette(src_format, dest_format, pSrcPalette); + m_iTransparency = + (dest_format == FXDIB_Argb ? 1 : 0) + (dest_format & 0x0200 ? 2 : 0) + + (dest_format & 0x0400 ? 4 : 0) + ((src_format & 0xff) == 1 ? 8 : 0); + return true; + } + m_iTransparency = + (src_format & 0x0200 ? 0 : 1) + (dest_format & 0x0200 ? 0 : 2) + + (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0) + (bClip ? 8 : 0) + + (src_format & 0x0400 ? 16 : 0) + (dest_format & 0x0400 ? 32 : 0); + return true; +} + +void CFX_ScanlineCompositor::InitSourceMask(int alpha_flag, + uint32_t mask_color) { + int mask_black = 0; + if (alpha_flag >> 8) { + m_MaskAlpha = alpha_flag & 0xff; + m_MaskRed = FXSYS_GetCValue(mask_color); + m_MaskGreen = FXSYS_GetMValue(mask_color); + m_MaskBlue = FXSYS_GetYValue(mask_color); + mask_black = FXSYS_GetKValue(mask_color); + } else { + m_MaskAlpha = FXARGB_A(mask_color); + m_MaskRed = FXARGB_R(mask_color); + m_MaskGreen = FXARGB_G(mask_color); + m_MaskBlue = FXARGB_B(mask_color); + } + if (m_DestFormat == FXDIB_8bppMask) + return; + + if ((m_DestFormat & 0xff) == 8) { + if (alpha_flag >> 8) { + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = + AdobeCMYK_to_sRGB1(m_MaskRed, m_MaskGreen, m_MaskBlue, mask_black); + m_MaskRed = FXRGB2GRAY(r, g, b); + } else { + m_MaskRed = FXRGB2GRAY(m_MaskRed, m_MaskGreen, m_MaskBlue); + } + if (m_DestFormat & 0x0400) + m_MaskRed = FX_CCOLOR(m_MaskRed); + return; + } + uint8_t* mask_color_p = (uint8_t*)&mask_color; + mask_color = + (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color); + if (alpha_flag >> 8) { + std::tie(mask_color_p[2], mask_color_p[1], mask_color_p[0]) = + AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], + mask_color_p[3]); + m_MaskRed = mask_color_p[2]; + m_MaskGreen = mask_color_p[1]; + m_MaskBlue = mask_color_p[0]; + } +} + +void CFX_ScanlineCompositor::InitSourcePalette(FXDIB_Format src_format, + FXDIB_Format dest_format, + const uint32_t* pSrcPalette) { + bool isSrcCmyk = !!(src_format & 0x0400); + bool isDstCmyk = !!(dest_format & 0x0400); + m_pSrcPalette = nullptr; + if (pSrcPalette) { + if ((dest_format & 0xff) == 8) { + int pal_count = 1 << (src_format & 0xff); + uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); + m_pSrcPalette.reset(reinterpret_cast(gray_pal)); + if (isSrcCmyk) { + for (int i = 0; i < pal_count; ++i) { + FX_CMYK cmyk = pSrcPalette[i]; + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), + FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); + *gray_pal++ = FXRGB2GRAY(r, g, b); + } + } else { + for (int i = 0; i < pal_count; ++i) { + FX_ARGB argb = pSrcPalette[i]; + *gray_pal++ = + FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); + } + } + return; + } + int palsize = 1 << (src_format & 0xff); + m_pSrcPalette.reset(FX_Alloc(uint32_t, palsize)); + uint32_t* pPalette = m_pSrcPalette.get(); + if (isDstCmyk == isSrcCmyk) { + memcpy(pPalette, pSrcPalette, palsize * sizeof(uint32_t)); + } else { + for (int i = 0; i < palsize; ++i) { + FX_CMYK cmyk = pSrcPalette[i]; + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), + FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); + pPalette[i] = FXARGB_MAKE(0xff, r, g, b); + } + } + return; + } + if ((dest_format & 0xff) == 8) { + int pal_count = 1 << (src_format & 0xff); + uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); + if (pal_count == 2) { + gray_pal[0] = 0; + gray_pal[1] = 255; + } else { + for (int i = 0; i < pal_count; ++i) + gray_pal[i] = i; + } + m_pSrcPalette.reset(reinterpret_cast(gray_pal)); + return; + } + int palsize = 1 << (src_format & 0xff); + m_pSrcPalette.reset(FX_Alloc(uint32_t, palsize)); + uint32_t* pPalette = m_pSrcPalette.get(); + if (palsize == 2) { + pPalette[0] = isSrcCmyk ? 255 : 0xff000000; + pPalette[1] = isSrcCmyk ? 0 : 0xffffffff; + } else { + for (int i = 0; i < palsize; ++i) + pPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101); + } + if (isSrcCmyk != isDstCmyk) { + for (int i = 0; i < palsize; ++i) { + FX_CMYK cmyk = pPalette[i]; + uint8_t r; + uint8_t g; + uint8_t b; + std::tie(r, g, b) = + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), + FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk)); + pPalette[i] = FXARGB_MAKE(0xff, r, g, b); + } + } +} + +void CFX_ScanlineCompositor::CompositeRgbBitmapLine( + uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + const uint8_t* clip_scan, + const uint8_t* src_extra_alpha, + uint8_t* dst_extra_alpha) { + int src_Bpp = (m_SrcFormat & 0xff) >> 3; + int dest_Bpp = (m_DestFormat & 0xff) >> 3; + if (m_bRgbByteOrder) { + switch (m_iTransparency) { + case 0: + case 4: + case 8: + case 12: + CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, + m_BlendType, clip_scan); + break; + case 1: + CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder( + dest_scan, src_scan, width, m_BlendType, src_Bpp); + break; + case 2: + case 10: + CompositeRow_Argb2Rgb_Blend_RgbByteOrder( + dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan); + break; + case 3: + CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder( + dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp); + break; + case 5: + CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, + width, src_Bpp); + break; + case 6: + case 14: + CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, + dest_Bpp, clip_scan); + break; + case 7: + CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder( + dest_scan, src_scan, width, dest_Bpp, src_Bpp); + break; + case 9: + CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder( + dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan); + break; + case 11: + CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, + m_BlendType, dest_Bpp, + src_Bpp, clip_scan); + break; + case 13: + CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder( + dest_scan, src_scan, width, src_Bpp, clip_scan); + break; + case 15: + CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder( + dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan); + break; + } + return; + } + if (m_DestFormat == FXDIB_8bppMask) { + if (m_SrcFormat & 0x0200) { + if (m_SrcFormat == FXDIB_Argb) { + CompositeRow_AlphaToMask(dest_scan, src_scan, width, clip_scan, 4); + } else { + CompositeRow_AlphaToMask(dest_scan, src_extra_alpha, width, clip_scan, + 1); + } + } else { + CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); + } + } else if ((m_DestFormat & 0xff) == 8) { + if (m_DestFormat & 0x0400) { + for (int i = 0; i < width; ++i) { + *dest_scan = ~*dest_scan; + dest_scan++; + } + } + if (m_SrcFormat & 0x0200) { + if (m_DestFormat & 0x0200) { + CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, + clip_scan, src_extra_alpha, dst_extra_alpha); + } else { + CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, + clip_scan, src_extra_alpha); + } + } else { + if (m_DestFormat & 0x0200) { + CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, + clip_scan, dst_extra_alpha); + } else { + CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, + clip_scan); + } + } + if (m_DestFormat & 0x0400) { + for (int i = 0; i < width; ++i) { + *dest_scan = ~*dest_scan; + dest_scan++; + } + } + } else { + switch (m_iTransparency) { + case 0: + case 4: + case 8: + case 4 + 8: { + CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, + clip_scan, dst_extra_alpha, src_extra_alpha); + } break; + case 1: + CompositeRow_Rgb2Argb_Blend_NoClip( + dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha); + break; + case 1 + 8: + CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, + m_BlendType, src_Bpp, clip_scan, + dst_extra_alpha); + break; + case 1 + 4: + CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, + src_Bpp, dst_extra_alpha); + break; + case 1 + 4 + 8: + CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, + clip_scan, dst_extra_alpha); + break; + case 2: + case 2 + 8: + CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, + dest_Bpp, clip_scan, src_extra_alpha); + break; + case 2 + 4: + case 2 + 4 + 8: + CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, + clip_scan, src_extra_alpha); + break; + case 1 + 2: + CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, + m_BlendType, dest_Bpp, src_Bpp); + break; + case 1 + 2 + 8: + CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, + dest_Bpp, src_Bpp, clip_scan); + break; + case 1 + 2 + 4: + CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, + dest_Bpp, src_Bpp); + break; + case 1 + 2 + 4 + 8: + CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, + src_Bpp, clip_scan); + break; + } + } +} + +void CFX_ScanlineCompositor::CompositePalBitmapLine( + uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + const uint8_t* clip_scan, + const uint8_t* src_extra_alpha, + uint8_t* dst_extra_alpha) { + if (m_bRgbByteOrder) { + if (m_SrcFormat == FXDIB_1bppRgb) { + if (m_DestFormat == FXDIB_8bppRgb) { + return; + } + if (m_DestFormat == FXDIB_Argb) { + CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder( + dest_scan, src_scan, src_left, width, m_pSrcPalette.get(), + clip_scan); + } else { + CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder( + dest_scan, src_scan, src_left, m_pSrcPalette.get(), width, + (m_DestFormat & 0xff) >> 3, clip_scan); + } + } else { + if (m_DestFormat == FXDIB_8bppRgb) { + return; + } + if (m_DestFormat == FXDIB_Argb) { + CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder( + dest_scan, src_scan, width, m_pSrcPalette.get(), clip_scan); + } else { + CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder( + dest_scan, src_scan, m_pSrcPalette.get(), width, + (m_DestFormat & 0xff) >> 3, clip_scan); + } + } + return; + } + if (m_DestFormat == FXDIB_8bppMask) { + CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); + return; + } + if ((m_DestFormat & 0xff) == 8) { + if (m_iTransparency & 8) { + if (m_DestFormat & 0x0200) { + CompositeRow_1bppPal2Graya( + dest_scan, src_scan, src_left, + reinterpret_cast(m_pSrcPalette.get()), width, + m_BlendType, clip_scan, dst_extra_alpha); + } else { + CompositeRow_1bppPal2Gray( + dest_scan, src_scan, src_left, + reinterpret_cast(m_pSrcPalette.get()), width, + m_BlendType, clip_scan); + } + } else { + if (m_DestFormat & 0x0200) + CompositeRow_8bppPal2Graya( + dest_scan, src_scan, + reinterpret_cast(m_pSrcPalette.get()), width, + m_BlendType, clip_scan, dst_extra_alpha, src_extra_alpha); + else + CompositeRow_8bppPal2Gray( + dest_scan, src_scan, + reinterpret_cast(m_pSrcPalette.get()), width, + m_BlendType, clip_scan, src_extra_alpha); + } + } else { + switch (m_iTransparency) { + case 1 + 2: + CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, + m_pSrcPalette.get(), clip_scan, + src_extra_alpha); + break; + case 1 + 2 + 8: + CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, + m_pSrcPalette.get(), clip_scan); + break; + case 0: + CompositeRow_8bppRgb2Rgb_NoBlend( + dest_scan, src_scan, m_pSrcPalette.get(), width, + (m_DestFormat & 0xff) >> 3, clip_scan, src_extra_alpha); + break; + case 0 + 8: + CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, + m_pSrcPalette.get(), width, + (m_DestFormat & 0xff) >> 3, clip_scan); + break; + case 0 + 2: + CompositeRow_8bppRgb2Rgb_NoBlend( + dest_scan, src_scan, m_pSrcPalette.get(), width, + (m_DestFormat & 0xff) >> 3, clip_scan, src_extra_alpha); + break; + case 0 + 2 + 8: + CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, + m_pSrcPalette.get(), clip_scan, + dst_extra_alpha); + break; + break; + } + } +} + +void CFX_ScanlineCompositor::CompositeByteMaskLine(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + const uint8_t* clip_scan, + uint8_t* dst_extra_alpha) { + if (m_DestFormat == FXDIB_8bppMask) { + CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, + clip_scan); + } else if ((m_DestFormat & 0xff) == 8) { + if (m_DestFormat & 0x0200) { + CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + width, clip_scan, dst_extra_alpha); + } else { + CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + width, clip_scan); + } + } else if (m_bRgbByteOrder) { + if (m_DestFormat == FXDIB_Argb) { + CompositeRow_ByteMask2Argb_RgbByteOrder( + dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, + width, m_BlendType, clip_scan); + } else { + CompositeRow_ByteMask2Rgb_RgbByteOrder( + dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, + width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); + } + return; + } else if (m_DestFormat == FXDIB_Argb) { + CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + m_MaskGreen, m_MaskBlue, width, m_BlendType, + clip_scan); + } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { + CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + m_MaskGreen, m_MaskBlue, width, m_BlendType, + (m_DestFormat & 0xff) >> 3, clip_scan); + } else if (m_DestFormat == FXDIB_Rgba) { + CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + m_MaskGreen, m_MaskBlue, width, m_BlendType, + clip_scan, dst_extra_alpha); + } +} + +void CFX_ScanlineCompositor::CompositeBitMaskLine(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + const uint8_t* clip_scan, + uint8_t* dst_extra_alpha) { + if (m_DestFormat == FXDIB_8bppMask) { + CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, + clip_scan); + } else if ((m_DestFormat & 0xff) == 8) { + if (m_DestFormat & 0x0200) { + CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + src_left, width, clip_scan, dst_extra_alpha); + } else { + CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + src_left, width, clip_scan); + } + } else if (m_bRgbByteOrder) { + if (m_DestFormat == FXDIB_Argb) { + CompositeRow_BitMask2Argb_RgbByteOrder( + dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, + src_left, width, m_BlendType, clip_scan); + } else { + CompositeRow_BitMask2Rgb_RgbByteOrder( + dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, + src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); + } + return; + } else if (m_DestFormat == FXDIB_Argb) { + CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, + m_MaskGreen, m_MaskBlue, src_left, width, + m_BlendType, clip_scan); + } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { + CompositeRow_BitMask2Rgb( + dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, + src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); + } +} diff --git a/core/fxge/dib/cfx_scanlinecompositor.h b/core/fxge/dib/cfx_scanlinecompositor.h new file mode 100644 index 0000000000000000000000000000000000000000..75ab578128a21d65db0609cf0992fcd7a8af08d8 --- /dev/null +++ b/core/fxge/dib/cfx_scanlinecompositor.h @@ -0,0 +1,77 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CFX_SCANLINECOMPOSITOR_H_ +#define CORE_FXGE_DIB_CFX_SCANLINECOMPOSITOR_H_ + +#include + +#include "core/fxge/dib/cfx_dibsource.h" + +class CFX_ScanlineCompositor { + public: + CFX_ScanlineCompositor(); + + ~CFX_ScanlineCompositor(); + + bool Init(FXDIB_Format dest_format, + FXDIB_Format src_format, + int32_t width, + uint32_t* pSrcPalette, + uint32_t mask_color, + int blend_type, + bool bClip, + bool bRgbByteOrder, + int alpha_flag); + + void CompositeRgbBitmapLine(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + const uint8_t* clip_scan, + const uint8_t* src_extra_alpha, + uint8_t* dst_extra_alpha); + + void CompositePalBitmapLine(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + const uint8_t* clip_scan, + const uint8_t* src_extra_alpha, + uint8_t* dst_extra_alpha); + + void CompositeByteMaskLine(uint8_t* dest_scan, + const uint8_t* src_scan, + int width, + const uint8_t* clip_scan, + uint8_t* dst_extra_alpha); + + void CompositeBitMaskLine(uint8_t* dest_scan, + const uint8_t* src_scan, + int src_left, + int width, + const uint8_t* clip_scan, + uint8_t* dst_extra_alpha); + + private: + void InitSourcePalette(FXDIB_Format src_format, + FXDIB_Format dest_format, + const uint32_t* pSrcPalette); + + void InitSourceMask(int alpha_flag, uint32_t mask_color); + + int m_iTransparency; + FXDIB_Format m_SrcFormat; + FXDIB_Format m_DestFormat; + std::unique_ptr m_pSrcPalette; + int m_MaskAlpha; + int m_MaskRed; + int m_MaskGreen; + int m_MaskBlue; + int m_BlendType; + bool m_bRgbByteOrder; +}; + +#endif // CORE_FXGE_DIB_CFX_SCANLINECOMPOSITOR_H_ diff --git a/core/fxge/dib/cstretchengine.cpp b/core/fxge/dib/cstretchengine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68039597301090b825e86430616adce919e9073f --- /dev/null +++ b/core/fxge/dib/cstretchengine.cpp @@ -0,0 +1,750 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/dib/cstretchengine.h" + +#include +#include + +#include "core/fxcrt/ifx_pauseindicator.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/dib/cfx_dibsource.h" +#include "core/fxge/dib/ifx_scanlinecomposer.h" +#include "core/fxge/fx_dib.h" + +namespace { + +const int kMaxDestValue = 16711680; + +} // namespace + +CStretchEngine::CWeightTable::CWeightTable() + : m_DestMin(0), + m_ItemSize(0), + m_dwWeightTablesSize(0) {} + +CStretchEngine::CWeightTable::~CWeightTable() {} + +size_t CStretchEngine::CWeightTable::GetPixelWeightSize() const { + return m_ItemSize / sizeof(int) - 2; +} + +bool CStretchEngine::CWeightTable::Calc(int dest_len, + int dest_min, + int dest_max, + int src_len, + int src_min, + int src_max, + int flags) { + m_WeightTables.clear(); + m_dwWeightTablesSize = 0; + const double scale = static_cast(src_len) / dest_len; + const double base = dest_len < 0 ? src_len : 0; + const int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1; + m_ItemSize = + sizeof(int) * 2 + + static_cast(sizeof(int) * + (ceil(fabs(static_cast(scale))) + ext_size)); + + m_DestMin = dest_min; + if (dest_max - dest_min > static_cast((1U << 30) - 4) / m_ItemSize) + return false; + + m_dwWeightTablesSize = (dest_max - dest_min) * m_ItemSize + 4; + m_WeightTables.resize(m_dwWeightTablesSize); + if ((flags & FXDIB_NOSMOOTH) != 0 || fabs(static_cast(scale)) < 1.0f) { + for (int dest_pixel = dest_min; dest_pixel < dest_max; ++dest_pixel) { + PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); + double src_pos = dest_pixel * scale + scale / 2 + base; + if (flags & FXDIB_INTERPOL) { + pixel_weights.m_SrcStart = + static_cast(floor(static_cast(src_pos) - 1.0f / 2)); + pixel_weights.m_SrcEnd = + static_cast(floor(static_cast(src_pos) + 1.0f / 2)); + pixel_weights.m_SrcStart = std::max(pixel_weights.m_SrcStart, src_min); + pixel_weights.m_SrcEnd = std::min(pixel_weights.m_SrcEnd, src_max - 1); + if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { + pixel_weights.m_Weights[0] = 65536; + } else { + pixel_weights.m_Weights[1] = + FXSYS_round(static_cast( + src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * + 65536); + pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; + } + } else if (flags & FXDIB_BICUBIC_INTERPOL) { + pixel_weights.m_SrcStart = + static_cast(floor(static_cast(src_pos) - 1.0f / 2)); + pixel_weights.m_SrcEnd = + static_cast(floor(static_cast(src_pos) + 1.0f / 2)); + int start = pixel_weights.m_SrcStart - 1; + int end = pixel_weights.m_SrcEnd + 1; + start = std::max(start, src_min); + end = std::min(end, src_max - 1); + if (pixel_weights.m_SrcStart < src_min) { + src_pos += src_min - pixel_weights.m_SrcStart; + pixel_weights.m_SrcStart = src_min; + } + pixel_weights.m_SrcEnd = std::min(pixel_weights.m_SrcEnd, src_max - 1); + int weight = FXSYS_round( + static_cast(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * + 256); + if (start == end) { + pixel_weights.m_Weights[0] = + (SDP_Table[256 + weight] + SDP_Table[weight] + + SDP_Table[256 - weight] + SDP_Table[512 - weight]) + << 8; + } else if ((start == pixel_weights.m_SrcStart && + (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd || + end == pixel_weights.m_SrcEnd) && + start < end) || + (start < pixel_weights.m_SrcStart && + pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd && + end == pixel_weights.m_SrcEnd)) { + if (start < pixel_weights.m_SrcStart) { + pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; + pixel_weights.m_Weights[1] = + (SDP_Table[weight] + SDP_Table[256 - weight] + + SDP_Table[512 - weight]) + << 8; + } else { + if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { + pixel_weights.m_Weights[0] = + (SDP_Table[256 + weight] + SDP_Table[weight] + + SDP_Table[256 - weight]) + << 8; + pixel_weights.m_Weights[1] = SDP_Table[512 - weight] << 8; + } else { + pixel_weights.m_Weights[0] = + (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; + pixel_weights.m_Weights[1] = + (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; + } + } + if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { + pixel_weights.m_SrcEnd = end; + } + if (start < pixel_weights.m_SrcStart) { + pixel_weights.m_SrcStart = start; + } + } else if (start == pixel_weights.m_SrcStart && + start < pixel_weights.m_SrcEnd && + pixel_weights.m_SrcEnd < end) { + pixel_weights.m_Weights[0] = + (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; + pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8; + pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8; + pixel_weights.m_SrcEnd = end; + } else if (start < pixel_weights.m_SrcStart && + pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd && + pixel_weights.m_SrcEnd == end) { + pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; + pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; + pixel_weights.m_Weights[2] = + (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; + pixel_weights.m_SrcStart = start; + } else { + pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; + pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; + pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8; + pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8; + pixel_weights.m_SrcStart = start; + pixel_weights.m_SrcEnd = end; + } + } else { + int pixel_pos = static_cast(floor(static_cast(src_pos))); + pixel_weights.m_SrcStart = std::max(pixel_pos, src_min); + pixel_weights.m_SrcEnd = std::min(pixel_pos, src_max - 1); + pixel_weights.m_Weights[0] = 65536; + } + } + return true; + } + + for (int dest_pixel = dest_min; dest_pixel < dest_max; ++dest_pixel) { + PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); + double src_start = dest_pixel * scale + base; + double src_end = src_start + scale; + int start_i = floor(std::min(src_start, src_end)); + int end_i = floor(std::max(src_start, src_end)); + start_i = std::max(start_i, src_min); + end_i = std::min(end_i, src_max - 1); + if (start_i > end_i) { + start_i = std::min(start_i, src_max - 1); + pixel_weights.m_SrcStart = start_i; + pixel_weights.m_SrcEnd = start_i; + continue; + } + pixel_weights.m_SrcStart = start_i; + pixel_weights.m_SrcEnd = end_i; + for (int j = start_i; j <= end_i; ++j) { + double dest_start = (j - base) / scale; + double dest_end = (j + 1 - base) / scale; + if (dest_start > dest_end) + std::swap(dest_start, dest_end); + double area_start = std::max(dest_start, static_cast(dest_pixel)); + double area_end = std::min(dest_end, static_cast(dest_pixel + 1)); + double weight = std::max(0.0, area_end - area_start); + if (weight == 0 && j == end_i) { + --pixel_weights.m_SrcEnd; + break; + } + size_t idx = j - start_i; + if (idx >= GetPixelWeightSize()) + return false; + + pixel_weights.m_Weights[idx] = FXSYS_round(weight * 65536); + } + } + return true; +} + +PixelWeight* CStretchEngine::CWeightTable::GetPixelWeight(int pixel) const { + ASSERT(pixel >= m_DestMin); + return reinterpret_cast(const_cast( + m_WeightTables.data() + (pixel - m_DestMin) * m_ItemSize)); +} + +int* CStretchEngine::CWeightTable::GetValueFromPixelWeight(PixelWeight* pWeight, + int index) const { + if (index < pWeight->m_SrcStart) + return nullptr; + + size_t idx = index - pWeight->m_SrcStart; + return idx < GetPixelWeightSize() ? &pWeight->m_Weights[idx] : nullptr; +} + +CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap, + FXDIB_Format dest_format, + int dest_width, + int dest_height, + const FX_RECT& clip_rect, + const RetainPtr& pSrcBitmap, + int flags) { + m_State = 0; + m_DestFormat = dest_format; + m_DestBpp = dest_format & 0xff; + m_SrcBpp = pSrcBitmap->GetFormat() & 0xff; + m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200; + m_pSrcPalette = pSrcBitmap->GetPalette(); + m_pDestBitmap = pDestBitmap; + m_DestWidth = dest_width; + m_DestHeight = dest_height; + m_DestClip = clip_rect; + uint32_t size = clip_rect.Width(); + if (size && m_DestBpp > static_cast(INT_MAX / size)) + return; + + size *= m_DestBpp; + if (size > INT_MAX - 31) + return; + + size += 31; + size = size / 32 * 4; + m_DestScanline.resize(size); + if (dest_format == FXDIB_Rgb32) + std::fill(m_DestScanline.begin(), m_DestScanline.end(), 255); + m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4; + m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4; + m_pSource = pSrcBitmap; + m_SrcWidth = pSrcBitmap->GetWidth(); + m_SrcHeight = pSrcBitmap->GetHeight(); + m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4; + if ((flags & FXDIB_NOSMOOTH) == 0) { + bool bInterpol = flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL; + if (!bInterpol && abs(dest_width) != 0 && + abs(dest_height) / 8 < static_cast(m_SrcWidth) * + m_SrcHeight / abs(dest_width)) { + flags = FXDIB_INTERPOL; + } + m_Flags = flags; + } else { + m_Flags = FXDIB_NOSMOOTH; + if (flags & FXDIB_DOWNSAMPLE) + m_Flags |= FXDIB_DOWNSAMPLE; + } + double scale_x = static_cast(m_SrcWidth) / m_DestWidth; + double scale_y = static_cast(m_SrcHeight) / m_DestHeight; + double base_x = m_DestWidth > 0 ? 0.0f : m_DestWidth; + double base_y = m_DestHeight > 0 ? 0.0f : m_DestHeight; + double src_left = scale_x * (clip_rect.left + base_x); + double src_right = scale_x * (clip_rect.right + base_x); + double src_top = scale_y * (clip_rect.top + base_y); + double src_bottom = scale_y * (clip_rect.bottom + base_y); + if (src_left > src_right) + std::swap(src_left, src_right); + if (src_top > src_bottom) + std::swap(src_top, src_bottom); + m_SrcClip.left = static_cast(floor(src_left)); + m_SrcClip.right = static_cast(ceil(src_right)); + m_SrcClip.top = static_cast(floor(src_top)); + m_SrcClip.bottom = static_cast(ceil(src_bottom)); + FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight); + m_SrcClip.Intersect(src_rect); + if (m_SrcBpp == 1) { + if (m_DestBpp == 8) + m_TransMethod = 1; + else + m_TransMethod = 2; + } else if (m_SrcBpp == 8) { + if (m_DestBpp == 8) { + if (!m_bHasAlpha) + m_TransMethod = 3; + else + m_TransMethod = 4; + } else { + if (!m_bHasAlpha) + m_TransMethod = 5; + else + m_TransMethod = 6; + } + } else { + if (!m_bHasAlpha) + m_TransMethod = 7; + else + m_TransMethod = 8; + } +} + +CStretchEngine::~CStretchEngine() {} + +bool CStretchEngine::Continue(IFX_PauseIndicator* pPause) { + while (m_State == 1) { + if (ContinueStretchHorz(pPause)) + return true; + + m_State = 2; + StretchVert(); + } + return false; +} + +bool CStretchEngine::StartStretchHorz() { + if (m_DestWidth == 0 || m_InterPitch == 0 || m_DestScanline.empty()) + return false; + + if (m_SrcClip.Height() == 0 || + m_SrcClip.Height() > (1 << 29) / m_InterPitch) { + return false; + } + + m_InterBuf.resize(m_SrcClip.Height() * m_InterPitch); + if (m_pSource && m_bHasAlpha && m_pSource->m_pAlphaMask) { + m_ExtraAlphaBuf.resize(m_SrcClip.Height(), m_ExtraMaskPitch); + uint32_t size = (m_DestClip.Width() * 8 + 31) / 32 * 4; + m_DestMaskScanline.resize(size); + } + bool ret = + m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right, + m_SrcWidth, m_SrcClip.left, m_SrcClip.right, m_Flags); + if (!ret) + return false; + + m_CurRow = m_SrcClip.top; + m_State = 1; + return true; +} + +bool CStretchEngine::ContinueStretchHorz(IFX_PauseIndicator* pPause) { + if (!m_DestWidth) + return false; + if (m_pSource->SkipToScanline(m_CurRow, pPause)) + return true; + + int Bpp = m_DestBpp / 8; + static const int kStrechPauseRows = 10; + int rows_to_go = kStrechPauseRows; + for (; m_CurRow < m_SrcClip.bottom; ++m_CurRow) { + if (rows_to_go == 0) { + if (pPause && pPause->NeedToPauseNow()) + return true; + + rows_to_go = kStrechPauseRows; + } + + const uint8_t* src_scan = m_pSource->GetScanline(m_CurRow); + uint8_t* dest_scan = + m_InterBuf.data() + (m_CurRow - m_SrcClip.top) * m_InterPitch; + const uint8_t* src_scan_mask = nullptr; + uint8_t* dest_scan_mask = nullptr; + if (!m_ExtraAlphaBuf.empty()) { + src_scan_mask = m_pSource->m_pAlphaMask->GetScanline(m_CurRow); + dest_scan_mask = m_ExtraAlphaBuf.data() + + (m_CurRow - m_SrcClip.top) * m_ExtraMaskPitch; + } + // TODO(npm): reduce duplicated code here + switch (m_TransMethod) { + case 1: + case 2: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_a = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + if (src_scan[j / 8] & (1 << (7 - j % 8))) + dest_a += pixel_weight * 255; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) + dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue); + *dest_scan++ = static_cast(dest_a >> 16); + } + break; + } + case 3: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_a = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + dest_a += pixel_weight * src_scan[j]; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) + dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue); + *dest_scan++ = static_cast(dest_a >> 16); + } + break; + } + case 4: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_a = 0; + int dest_r = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + pixel_weight = pixel_weight * src_scan_mask[j] / 255; + dest_r += pixel_weight * src_scan[j]; + dest_a += pixel_weight; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_r = pdfium::clamp(dest_r, 0, kMaxDestValue); + dest_a = pdfium::clamp(dest_a, 0, 65536); + } + *dest_scan++ = static_cast(dest_r >> 16); + *dest_scan_mask++ = static_cast((dest_a * 255) >> 16); + } + break; + } + case 5: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_r_y = 0; + int dest_g_m = 0; + int dest_b_c = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]; + if (m_DestFormat == FXDIB_Rgb) { + dest_r_y += pixel_weight * static_cast(argb_cmyk >> 16); + dest_g_m += pixel_weight * static_cast(argb_cmyk >> 8); + dest_b_c += pixel_weight * static_cast(argb_cmyk); + } else { + dest_b_c += pixel_weight * static_cast(argb_cmyk >> 24); + dest_g_m += pixel_weight * static_cast(argb_cmyk >> 16); + dest_r_y += pixel_weight * static_cast(argb_cmyk >> 8); + } + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue); + dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue); + dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue); + } + *dest_scan++ = static_cast(dest_b_c >> 16); + *dest_scan++ = static_cast(dest_g_m >> 16); + *dest_scan++ = static_cast(dest_r_y >> 16); + } + break; + } + case 6: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_a = 0; + int dest_r_y = 0; + int dest_g_m = 0; + int dest_b_c = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + pixel_weight = pixel_weight * src_scan_mask[j] / 255; + unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]; + if (m_DestFormat == FXDIB_Rgba) { + dest_r_y += pixel_weight * static_cast(argb_cmyk >> 16); + dest_g_m += pixel_weight * static_cast(argb_cmyk >> 8); + dest_b_c += pixel_weight * static_cast(argb_cmyk); + } else { + dest_b_c += pixel_weight * static_cast(argb_cmyk >> 24); + dest_g_m += pixel_weight * static_cast(argb_cmyk >> 16); + dest_r_y += pixel_weight * static_cast(argb_cmyk >> 8); + } + dest_a += pixel_weight; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue); + dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue); + dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue); + dest_a = pdfium::clamp(dest_a, 0, 65536); + } + *dest_scan++ = static_cast(dest_b_c >> 16); + *dest_scan++ = static_cast(dest_g_m >> 16); + *dest_scan++ = static_cast(dest_r_y >> 16); + *dest_scan_mask++ = static_cast((dest_a * 255) >> 16); + } + break; + } + case 7: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_r_y = 0; + int dest_g_m = 0; + int dest_b_c = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + const uint8_t* src_pixel = src_scan + j * Bpp; + dest_b_c += pixel_weight * (*src_pixel++); + dest_g_m += pixel_weight * (*src_pixel++); + dest_r_y += pixel_weight * (*src_pixel); + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue); + dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue); + dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue); + } + *dest_scan++ = static_cast((dest_b_c) >> 16); + *dest_scan++ = static_cast((dest_g_m) >> 16); + *dest_scan++ = static_cast((dest_r_y) >> 16); + dest_scan += Bpp - 3; + } + break; + } + case 8: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + PixelWeight* pWeights = m_WeightTable.GetPixelWeight(col); + int dest_a = 0; + int dest_r_y = 0; + int dest_g_m = 0; + int dest_b_c = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = m_WeightTable.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return false; + + int pixel_weight = *pWeight; + const uint8_t* src_pixel = src_scan + j * Bpp; + if (m_DestFormat == FXDIB_Argb) { + pixel_weight = pixel_weight * src_pixel[3] / 255; + } else { + pixel_weight = pixel_weight * src_scan_mask[j] / 255; + } + dest_b_c += pixel_weight * (*src_pixel++); + dest_g_m += pixel_weight * (*src_pixel++); + dest_r_y += pixel_weight * (*src_pixel); + dest_a += pixel_weight; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue); + dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue); + dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue); + dest_a = pdfium::clamp(dest_a, 0, 65536); + } + *dest_scan++ = static_cast((dest_b_c) >> 16); + *dest_scan++ = static_cast((dest_g_m) >> 16); + *dest_scan++ = static_cast((dest_r_y) >> 16); + if (m_DestFormat == FXDIB_Argb) + *dest_scan = static_cast((dest_a * 255) >> 16); + if (dest_scan_mask) + *dest_scan_mask++ = static_cast((dest_a * 255) >> 16); + dest_scan += Bpp - 3; + } + break; + } + } + rows_to_go--; + } + return false; +} + +void CStretchEngine::StretchVert() { + if (m_DestHeight == 0) + return; + + CWeightTable table; + bool ret = table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, + m_SrcHeight, m_SrcClip.top, m_SrcClip.bottom, m_Flags); + if (!ret) + return; + + const int DestBpp = m_DestBpp / 8; + for (int row = m_DestClip.top; row < m_DestClip.bottom; ++row) { + unsigned char* dest_scan = m_DestScanline.data(); + unsigned char* dest_scan_mask = m_DestMaskScanline.data(); + PixelWeight* pWeights = table.GetPixelWeight(row); + switch (m_TransMethod) { + case 1: + case 2: + case 3: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + unsigned char* src_scan = + m_InterBuf.data() + (col - m_DestClip.left) * DestBpp; + int dest_a = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = table.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return; + + int pixel_weight = *pWeight; + dest_a += + pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch]; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) + dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue); + *dest_scan = static_cast(dest_a >> 16); + dest_scan += DestBpp; + } + break; + } + case 4: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + unsigned char* src_scan = + m_InterBuf.data() + (col - m_DestClip.left) * DestBpp; + unsigned char* src_scan_mask = + m_ExtraAlphaBuf.data() + (col - m_DestClip.left); + int dest_a = 0; + int dest_k = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = table.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return; + + int pixel_weight = *pWeight; + dest_k += + pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch]; + dest_a += pixel_weight * + src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch]; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_k = pdfium::clamp(dest_k, 0, kMaxDestValue); + dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue); + } + *dest_scan = static_cast(dest_k >> 16); + dest_scan += DestBpp; + *dest_scan_mask++ = static_cast(dest_a >> 16); + } + break; + } + case 5: + case 7: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + unsigned char* src_scan = + m_InterBuf.data() + (col - m_DestClip.left) * DestBpp; + int dest_r_y = 0; + int dest_g_m = 0; + int dest_b_c = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = table.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return; + + int pixel_weight = *pWeight; + const uint8_t* src_pixel = + src_scan + (j - m_SrcClip.top) * m_InterPitch; + dest_b_c += pixel_weight * (*src_pixel++); + dest_g_m += pixel_weight * (*src_pixel++); + dest_r_y += pixel_weight * (*src_pixel); + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue); + dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue); + dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue); + } + dest_scan[0] = static_cast((dest_b_c) >> 16); + dest_scan[1] = static_cast((dest_g_m) >> 16); + dest_scan[2] = static_cast((dest_r_y) >> 16); + dest_scan += DestBpp; + } + break; + } + case 6: + case 8: { + for (int col = m_DestClip.left; col < m_DestClip.right; ++col) { + unsigned char* src_scan = + m_InterBuf.data() + (col - m_DestClip.left) * DestBpp; + unsigned char* src_scan_mask = nullptr; + if (m_DestFormat != FXDIB_Argb) + src_scan_mask = m_ExtraAlphaBuf.data() + (col - m_DestClip.left); + int dest_a = 0; + int dest_r_y = 0; + int dest_g_m = 0; + int dest_b_c = 0; + for (int j = pWeights->m_SrcStart; j <= pWeights->m_SrcEnd; ++j) { + int* pWeight = table.GetValueFromPixelWeight(pWeights, j); + if (!pWeight) + return; + + int pixel_weight = *pWeight; + const uint8_t* src_pixel = + src_scan + (j - m_SrcClip.top) * m_InterPitch; + int mask_v = 255; + if (src_scan_mask) + mask_v = src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch]; + dest_b_c += pixel_weight * (*src_pixel++); + dest_g_m += pixel_weight * (*src_pixel++); + dest_r_y += pixel_weight * (*src_pixel); + if (m_DestFormat == FXDIB_Argb) + dest_a += pixel_weight * (*(src_pixel + 1)); + else + dest_a += pixel_weight * mask_v; + } + if (m_Flags & FXDIB_BICUBIC_INTERPOL) { + dest_r_y = pdfium::clamp(dest_r_y, 0, kMaxDestValue); + dest_g_m = pdfium::clamp(dest_g_m, 0, kMaxDestValue); + dest_b_c = pdfium::clamp(dest_b_c, 0, kMaxDestValue); + dest_a = pdfium::clamp(dest_a, 0, kMaxDestValue); + } + if (dest_a) { + int r = static_cast(dest_r_y) * 255 / dest_a; + int g = static_cast(dest_g_m) * 255 / dest_a; + int b = static_cast(dest_b_c) * 255 / dest_a; + dest_scan[0] = pdfium::clamp(b, 0, 255); + dest_scan[1] = pdfium::clamp(g, 0, 255); + dest_scan[2] = pdfium::clamp(r, 0, 255); + } + if (m_DestFormat == FXDIB_Argb) + dest_scan[3] = static_cast((dest_a) >> 16); + else + *dest_scan_mask = static_cast((dest_a) >> 16); + dest_scan += DestBpp; + if (dest_scan_mask) + dest_scan_mask++; + } + break; + } + } + m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_DestScanline.data(), + m_DestMaskScanline.data()); + } +} diff --git a/core/fxge/dib/cstretchengine.h b/core/fxge/dib/cstretchengine.h new file mode 100644 index 0000000000000000000000000000000000000000..8ce8351304977eb7c2ee6e1257156f972e9aa5a1 --- /dev/null +++ b/core/fxge/dib/cstretchengine.h @@ -0,0 +1,87 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_CSTRETCHENGINE_H_ +#define CORE_FXGE_DIB_CSTRETCHENGINE_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/fx_dib.h" + +class IFX_PauseIndicator; +class IFX_ScanlineComposer; + +class CStretchEngine { + public: + CStretchEngine(IFX_ScanlineComposer* pDestBitmap, + FXDIB_Format dest_format, + int dest_width, + int dest_height, + const FX_RECT& clip_rect, + const RetainPtr& pSrcBitmap, + int flags); + ~CStretchEngine(); + + bool Continue(IFX_PauseIndicator* pPause); + + bool StartStretchHorz(); + bool ContinueStretchHorz(IFX_PauseIndicator* pPause); + void StretchVert(); + + class CWeightTable { + public: + CWeightTable(); + ~CWeightTable(); + + bool Calc(int dest_len, + int dest_min, + int dest_max, + int src_len, + int src_min, + int src_max, + int flags); + PixelWeight* GetPixelWeight(int pixel) const; + int* GetValueFromPixelWeight(PixelWeight* pWeight, int index) const; + size_t GetPixelWeightSize() const; + + private: + int m_DestMin; + int m_ItemSize; + std::vector m_WeightTables; + size_t m_dwWeightTablesSize; + }; + + FXDIB_Format m_DestFormat; + int m_DestBpp; + int m_SrcBpp; + int m_bHasAlpha; + UnownedPtr m_pDestBitmap; + int m_DestWidth; + int m_DestHeight; + FX_RECT m_DestClip; + std::vector m_DestScanline; + std::vector m_DestMaskScanline; + FX_RECT m_SrcClip; + RetainPtr m_pSource; + uint32_t* m_pSrcPalette; + int m_SrcWidth; + int m_SrcHeight; + int m_SrcPitch; + int m_InterPitch; + int m_ExtraMaskPitch; + std::vector m_InterBuf; + std::vector m_ExtraAlphaBuf; + int m_TransMethod; + int m_Flags; + CWeightTable m_WeightTable; + int m_CurRow; + int m_State; +}; + +#endif // CORE_FXGE_DIB_CSTRETCHENGINE_H_ diff --git a/core/fxge/dib/cstretchengine_unittest.cpp b/core/fxge/dib/cstretchengine_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c7e0342deb44965d64c55328350d9598a2f136e --- /dev/null +++ b/core/fxge/dib/cstretchengine_unittest.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxge/dib/cstretchengine.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/render/cpdf_dibsource.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxge/fx_dib.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +TEST(CStretchEngine, OverflowInCtor) { + FX_RECT clip_rect; + std::unique_ptr dict_obj = + pdfium::MakeUnique(); + dict_obj->SetNewFor("Width", 71000); + dict_obj->SetNewFor("Height", 12500); + std::unique_ptr stream = + pdfium::MakeUnique(nullptr, 0, std::move(dict_obj)); + auto dib_source = pdfium::MakeRetain(); + dib_source->Load(nullptr, stream.get()); + CStretchEngine engine(nullptr, FXDIB_8bppRgb, 500, 500, clip_rect, dib_source, + 0); + EXPECT_EQ(FXDIB_INTERPOL, engine.m_Flags); +} diff --git a/core/fxge/dib/dib_int.h b/core/fxge/dib/dib_int.h deleted file mode 100644 index 000003a9c6eb8ff4f4dd9303d2db4cf2a0163fbb..0000000000000000000000000000000000000000 --- a/core/fxge/dib/dib_int.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXGE_DIB_DIB_INT_H_ -#define CORE_FXGE_DIB_DIB_INT_H_ - -#include - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxge/fx_dib.h" - -class IFX_ScanlineComposer; - -extern const int16_t SDP_Table[513]; - -class CPDF_FixedMatrix { - public: - CPDF_FixedMatrix(const CFX_Matrix& src, int bits) { - base = 1 << bits; - a = FXSYS_round(src.a * base); - b = FXSYS_round(src.b * base); - c = FXSYS_round(src.c * base); - d = FXSYS_round(src.d * base); - e = FXSYS_round(src.e * base); - f = FXSYS_round(src.f * base); - } - inline void Transform(int x, int y, int& x1, int& y1) { - x1 = (a * x + c * y + e + base / 2) / base; - y1 = (b * x + d * y + f + base / 2) / base; - } - int a, b, c, d, e, f; - int base; -}; -#define FPDF_HUGE_IMAGE_SIZE 60000000 -struct PixelWeight { - int m_SrcStart; - int m_SrcEnd; - int m_Weights[1]; -}; - -class CWeightTable { - public: - CWeightTable(); - ~CWeightTable(); - - bool Calc(int dest_len, - int dest_min, - int dest_max, - int src_len, - int src_min, - int src_max, - int flags); - PixelWeight* GetPixelWeight(int pixel) const; - int* GetValueFromPixelWeight(PixelWeight* pWeight, int index) const; - size_t GetPixelWeightSize() const; - - private: - int m_DestMin; - int m_ItemSize; - uint8_t* m_pWeightTables; - size_t m_dwWeightTablesSize; -}; - -class CStretchEngine { - public: - CStretchEngine(IFX_ScanlineComposer* pDestBitmap, - FXDIB_Format dest_format, - int dest_width, - int dest_height, - const FX_RECT& clip_rect, - const CFX_DIBSource* pSrcBitmap, - int flags); - ~CStretchEngine(); - - bool Continue(IFX_Pause* pPause); - - bool StartStretchHorz(); - bool ContinueStretchHorz(IFX_Pause* pPause); - void StretchVert(); - - FXDIB_Format m_DestFormat; - int m_DestBpp; - int m_SrcBpp; - int m_bHasAlpha; - IFX_ScanlineComposer* m_pDestBitmap; - int m_DestWidth, m_DestHeight; - FX_RECT m_DestClip; - uint8_t* m_pDestScanline; - uint8_t* m_pDestMaskScanline; - FX_RECT m_SrcClip; - const CFX_DIBSource* m_pSource; - uint32_t* m_pSrcPalette; - int m_SrcWidth; - int m_SrcHeight; - int m_SrcPitch; - int m_InterPitch; - int m_ExtraMaskPitch; - uint8_t* m_pInterBuf; - uint8_t* m_pExtraAlphaBuf; - int m_TransMethod; - int m_Flags; - CWeightTable m_WeightTable; - int m_CurRow; - int m_State; -}; - -FX_RECT FXDIB_SwapClipBox(FX_RECT& clip, - int width, - int height, - bool bFlipX, - bool bFlipY); - -#endif // CORE_FXGE_DIB_DIB_INT_H_ diff --git a/core/fxge/dib/fx_dib_composite.cpp b/core/fxge/dib/fx_dib_composite.cpp deleted file mode 100644 index 072ebbddd592f96dc2f8c5c11658f5a97cf48eaf..0000000000000000000000000000000000000000 --- a/core/fxge/dib/fx_dib_composite.cpp +++ /dev/null @@ -1,5040 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcodec/fx_codec.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/dib/dib_int.h" -#include "core/fxge/ge/cfx_cliprgn.h" - -namespace { - -const uint8_t color_sqrt[256] = { - 0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26, - 0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46, - 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C, - 0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, - 0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, - 0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, - 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, - 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, - 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, - 0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF, - 0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, - 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE, - 0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, - 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, - 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4, - 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, - 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1, - 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, - 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, - 0xFD, 0xFE, 0xFE, 0xFF}; - -int Blend(int blend_mode, int back_color, int src_color) { - switch (blend_mode) { - case FXDIB_BLEND_NORMAL: - return src_color; - case FXDIB_BLEND_MULTIPLY: - return src_color * back_color / 255; - case FXDIB_BLEND_SCREEN: - return src_color + back_color - src_color * back_color / 255; - case FXDIB_BLEND_OVERLAY: - return Blend(FXDIB_BLEND_HARDLIGHT, src_color, back_color); - case FXDIB_BLEND_DARKEN: - return src_color < back_color ? src_color : back_color; - case FXDIB_BLEND_LIGHTEN: - return src_color > back_color ? src_color : back_color; - case FXDIB_BLEND_COLORDODGE: { - if (src_color == 255) { - return src_color; - } - int result = back_color * 255 / (255 - src_color); - if (result > 255) { - return 255; - } - return result; - } - case FXDIB_BLEND_COLORBURN: { - if (src_color == 0) { - return src_color; - } - int result = (255 - back_color) * 255 / src_color; - if (result > 255) { - result = 255; - } - return 255 - result; - } - case FXDIB_BLEND_HARDLIGHT: - if (src_color < 128) { - return (src_color * back_color * 2) / 255; - } - return Blend(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255); - case FXDIB_BLEND_SOFTLIGHT: { - if (src_color < 128) { - return back_color - - (255 - 2 * src_color) * back_color * (255 - back_color) / 255 / - 255; - } - return back_color + - (2 * src_color - 255) * (color_sqrt[back_color] - back_color) / - 255; - } - case FXDIB_BLEND_DIFFERENCE: - return back_color < src_color ? src_color - back_color - : back_color - src_color; - case FXDIB_BLEND_EXCLUSION: - return back_color + src_color - 2 * back_color * src_color / 255; - } - return src_color; -} - -struct RGB { - int red; - int green; - int blue; -}; - -int Lum(RGB color) { - return (color.red * 30 + color.green * 59 + color.blue * 11) / 100; -} - -RGB ClipColor(RGB color) { - int l = Lum(color); - int n = color.red; - if (color.green < n) { - n = color.green; - } - if (color.blue < n) { - n = color.blue; - } - int x = color.red; - if (color.green > x) { - x = color.green; - } - if (color.blue > x) { - x = color.blue; - } - if (n < 0) { - color.red = l + ((color.red - l) * l / (l - n)); - color.green = l + ((color.green - l) * l / (l - n)); - color.blue = l + ((color.blue - l) * l / (l - n)); - } - if (x > 255) { - color.red = l + ((color.red - l) * (255 - l) / (x - l)); - color.green = l + ((color.green - l) * (255 - l) / (x - l)); - color.blue = l + ((color.blue - l) * (255 - l) / (x - l)); - } - return color; -} - -RGB SetLum(RGB color, int l) { - int d = l - Lum(color); - color.red += d; - color.green += d; - color.blue += d; - return ClipColor(color); -} - -int Sat(RGB color) { - int n = color.red; - if (color.green < n) { - n = color.green; - } - if (color.blue < n) { - n = color.blue; - } - int x = color.red; - if (color.green > x) { - x = color.green; - } - if (color.blue > x) { - x = color.blue; - } - return x - n; -} - -RGB SetSat(RGB color, int s) { - int* max = &color.red; - int* mid = &color.red; - int* min = &color.red; - if (color.green > *max) { - max = &color.green; - } - if (color.blue > *max) { - max = &color.blue; - } - if (color.green < *min) { - min = &color.green; - } - if (color.blue < *min) { - min = &color.blue; - } - if (*max == *min) { - color.red = 0; - color.green = 0; - color.blue = 0; - return color; - } - if (max == &color.red) { - if (min == &color.green) { - mid = &color.blue; - } else { - mid = &color.green; - } - } else if (max == &color.green) { - if (min == &color.red) { - mid = &color.blue; - } else { - mid = &color.red; - } - } else { - if (min == &color.green) { - mid = &color.red; - } else { - mid = &color.green; - } - } - if (*max > *min) { - *mid = (*mid - *min) * s / (*max - *min); - *max = s; - *min = 0; - } - return color; -} - -void RGB_Blend(int blend_mode, - const uint8_t* src_scan, - uint8_t* dest_scan, - int results[3]) { - RGB src; - RGB back; - RGB result = {0, 0, 0}; - src.red = src_scan[2]; - src.green = src_scan[1]; - src.blue = src_scan[0]; - back.red = dest_scan[2]; - back.green = dest_scan[1]; - back.blue = dest_scan[0]; - switch (blend_mode) { - case FXDIB_BLEND_HUE: - result = SetLum(SetSat(src, Sat(back)), Lum(back)); - break; - case FXDIB_BLEND_SATURATION: - result = SetLum(SetSat(back, Sat(src)), Lum(back)); - break; - case FXDIB_BLEND_COLOR: - result = SetLum(src, Lum(back)); - break; - case FXDIB_BLEND_LUMINOSITY: - result = SetLum(back, Lum(src)); - break; - } - results[0] = result.blue; - results[1] = result.green; - results[2] = result.red; -} - -void CompositeRow_Argb2Mask(uint8_t* dest_scan, - const uint8_t* src_scan, - int pixel_count, - const uint8_t* clip_scan) { - src_scan += 3; - for (int col = 0; col < pixel_count; col++) { - int src_alpha = *src_scan; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - uint8_t back_alpha = *dest_scan; - if (!back_alpha) { - *dest_scan = src_alpha; - } else if (src_alpha) { - *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; - } - dest_scan++; - src_scan += 4; - } -} - -void CompositeRow_Rgba2Mask(uint8_t* dest_scan, - const uint8_t* src_alpha_scan, - int pixel_count, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - uint8_t back_alpha = *dest_scan; - if (!back_alpha) { - *dest_scan = src_alpha; - } else if (src_alpha) { - *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; - } - dest_scan++; - } -} - -void CompositeRow_Rgb2Mask(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - const uint8_t* clip_scan) { - if (clip_scan) { - for (int i = 0; i < width; i++) { - *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan); - dest_scan++; - clip_scan++; - } - } else { - FXSYS_memset(dest_scan, 0xff, width); - } -} - -void CompositeRow_Argb2Graya(uint8_t* dest_scan, - const uint8_t* src_scan, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan, - uint8_t* dst_alpha_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = nullptr; - if (pIccTransform) - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - if (src_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = *dst_alpha_scan; - if (back_alpha == 0) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, - 1); - } else { - *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - *dst_alpha_scan = src_alpha; - } - dest_scan++; - dst_alpha_scan++; - src_scan += 3; - continue; - } - uint8_t src_alpha = *src_alpha_scan++; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha == 0) { - dest_scan++; - dst_alpha_scan++; - src_scan += 3; - continue; - } - *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); - int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); - uint8_t gray; - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - } else { - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - dst_alpha_scan++; - src_scan += 3; - } - } else { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = *dst_alpha_scan; - if (back_alpha == 0) { - int src_alpha = src_scan[3]; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, - 1); - } else { - *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - *dst_alpha_scan = src_alpha; - } - dest_scan++; - dst_alpha_scan++; - src_scan += 4; - continue; - } - uint8_t src_alpha = src_scan[3]; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha == 0) { - dest_scan++; - dst_alpha_scan++; - src_scan += 4; - continue; - } - *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); - int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); - uint8_t gray; - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - dst_alpha_scan++; - src_scan += 4; - } - } - return; - } - if (src_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = *dst_alpha_scan; - if (back_alpha == 0) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, - 1); - } else { - *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - *dst_alpha_scan = src_alpha; - } - dest_scan++; - dst_alpha_scan++; - src_scan += 3; - continue; - } - uint8_t src_alpha = *src_alpha_scan++; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha == 0) { - dest_scan++; - dst_alpha_scan++; - src_scan += 3; - continue; - } - *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); - int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); - uint8_t gray; - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - dst_alpha_scan++; - src_scan += 3; - } - } else { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = *dst_alpha_scan; - if (back_alpha == 0) { - int src_alpha = src_scan[3]; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, - 1); - } else { - *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - *dst_alpha_scan = src_alpha; - } - dest_scan++; - dst_alpha_scan++; - src_scan += 4; - continue; - } - uint8_t src_alpha = src_scan[3]; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha == 0) { - dest_scan++; - dst_alpha_scan++; - src_scan += 4; - continue; - } - *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha); - int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan); - uint8_t gray; - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - dst_alpha_scan++; - src_scan += 4; - } - } -} - -void CompositeRow_Argb2Gray(uint8_t* dest_scan, - const uint8_t* src_scan, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = nullptr; - uint8_t gray; - if (pIccTransform) - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - if (src_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - } - dest_scan++; - src_scan += 3; - } - } else { - for (int col = 0; col < pixel_count; col++) { - int src_alpha = src_scan[3]; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - } - dest_scan++; - src_scan += 4; - } - } - return; - } - if (src_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - } - dest_scan++; - src_scan += 3; - } - } else { - for (int col = 0; col < pixel_count; col++) { - int src_alpha = src_scan[3]; - if (clip_scan) - src_alpha = clip_scan[col] * src_alpha / 255; - - if (src_alpha) { - if (pIccTransform) - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - else - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - } - dest_scan++; - src_scan += 4; - } - } -} - -void CompositeRow_Rgb2Gray(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_Bpp, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = nullptr; - uint8_t gray; - if (pIccTransform) { - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - } - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - } else { - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); - } else { - *dest_scan = gray; - } - dest_scan++; - src_scan += src_Bpp; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - } else { - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); - } else { - *dest_scan = gray; - } - dest_scan++; - src_scan += src_Bpp; - } -} - -void CompositeRow_Rgb2Graya(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_Bpp, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = nullptr; - if (pIccTransform) { - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - } - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - int back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1); - } else { - *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - dest_scan++; - dest_alpha_scan++; - src_scan += src_Bpp; - continue; - } - int src_alpha = 255; - if (clip_scan) { - src_alpha = clip_scan[col]; - } - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - src_scan += src_Bpp; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - uint8_t gray; - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - } else { - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - src_scan += src_Bpp; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - int src_alpha = 255; - if (clip_scan) { - src_alpha = clip_scan[col]; - } - if (src_alpha == 255) { - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1); - } else { - *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - dest_scan++; - *dest_alpha_scan++ = 255; - src_scan += src_Bpp; - continue; - } - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - src_scan += src_Bpp; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - uint8_t gray; - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1); - } else { - gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan); - } - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - src_scan += src_Bpp; - } -} - -void CompositeRow_Argb2Argb(uint8_t* dest_scan, - const uint8_t* src_scan, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan, - const uint8_t* src_alpha_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - if (!dest_alpha_scan) { - if (!src_alpha_scan) { - uint8_t back_alpha = 0; - for (int col = 0; col < pixel_count; col++) { - back_alpha = dest_scan[3]; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * src_scan[3] / 255; - FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) | - (src_alpha << 24)); - } else { - FXARGB_COPY(dest_scan, src_scan); - } - dest_scan += 4; - src_scan += 4; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * src_scan[3] / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += 4; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - if (blend_type) { - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, *src_scan); - blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); - } - dest_scan++; - src_scan++; - } - dest_scan++; - src_scan++; - } - } else { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; - FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2], - src_scan[1], *src_scan)); - } else { - FXARGB_SETDIB(dest_scan, - FXARGB_MAKE((*src_alpha_scan << 24), src_scan[2], - src_scan[1], *src_scan)); - } - dest_scan += 4; - src_scan += 3; - src_alpha_scan++; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; - } else { - src_alpha = *src_alpha_scan++; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += 3; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - if (blend_type) { - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, *src_scan); - blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); - } - dest_scan++; - src_scan++; - } - dest_scan++; - } - } - } else { - if (src_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; - *dest_alpha_scan = src_alpha; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - } else { - *dest_alpha_scan = *src_alpha_scan; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - } - dest_alpha_scan++; - src_alpha_scan++; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; - } else { - src_alpha = *src_alpha_scan++; - } - if (src_alpha == 0) { - dest_scan += 3; - src_scan += 3; - dest_alpha_scan++; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - if (blend_type) { - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, *src_scan); - blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); - } - dest_scan++; - src_scan++; - } - } - } else { - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * src_scan[3] / 255; - *dest_alpha_scan = src_alpha; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - } else { - *dest_alpha_scan = src_scan[3]; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - } - dest_alpha_scan++; - src_scan++; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * src_scan[3] / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 0) { - dest_scan += 3; - src_scan += 4; - dest_alpha_scan++; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - if (blend_type) { - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, *src_scan); - blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); - } - dest_scan++; - src_scan++; - } - src_scan++; - } - } - } -} - -void CompositeRow_Rgb2Argb_Blend_NoClip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int src_Bpp, - uint8_t* dest_alpha_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int src_gap = src_Bpp - 3; - if (dest_alpha_scan) { - for (int col = 0; col < width; col++) { - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_alpha_scan++ = 0xff; - src_scan += src_gap; - continue; - } - *dest_alpha_scan++ = 0xff; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, src_color); - *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); - dest_scan++; - src_scan++; - } - src_scan += src_gap; - } - } else { - for (int col = 0; col < width; col++) { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - if (src_Bpp == 4) { - FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); - } else { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], - src_scan[0])); - } - dest_scan += 4; - src_scan += src_Bpp; - continue; - } - dest_scan[3] = 0xff; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, src_color); - *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); - dest_scan++; - src_scan++; - } - dest_scan++; - src_scan += src_gap; - } - } -} - -void CompositeRow_Rgb2Argb_Blend_Clip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int src_Bpp, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int src_gap = src_Bpp - 3; - if (dest_alpha_scan) { - for (int col = 0; col < width; col++) { - int src_alpha = *clip_scan++; - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - src_scan += src_gap; - dest_alpha_scan++; - continue; - } - if (src_alpha == 0) { - dest_scan += 3; - dest_alpha_scan++; - src_scan += src_Bpp; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, src_color); - blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - src_scan++; - } - src_scan += src_gap; - } - } else { - for (int col = 0; col < width; col++) { - int src_alpha = *clip_scan++; - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - src_scan += src_gap; - dest_scan++; - continue; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += src_Bpp; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, src_color); - blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - src_scan++; - } - dest_scan++; - src_scan += src_gap; - } - } -} - -void CompositeRow_Rgb2Argb_NoBlend_Clip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int src_Bpp, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - int src_gap = src_Bpp - 3; - if (dest_alpha_scan) { - for (int col = 0; col < width; col++) { - int src_alpha = clip_scan[col]; - if (src_alpha == 255) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_alpha_scan++ = 255; - src_scan += src_gap; - continue; - } - if (src_alpha == 0) { - dest_scan += 3; - dest_alpha_scan++; - src_scan += src_Bpp; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - for (int color = 0; color < 3; color++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); - dest_scan++; - src_scan++; - } - src_scan += src_gap; - } - } else { - for (int col = 0; col < width; col++) { - int src_alpha = clip_scan[col]; - if (src_alpha == 255) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = 255; - src_scan += src_gap; - continue; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += src_Bpp; - continue; - } - int back_alpha = dest_scan[3]; - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - for (int color = 0; color < 3; color++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio); - dest_scan++; - src_scan++; - } - dest_scan++; - src_scan += src_gap; - } - } -} - -void CompositeRow_Rgb2Argb_NoBlend_NoClip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int src_Bpp, - uint8_t* dest_alpha_scan) { - if (dest_alpha_scan) { - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_alpha_scan++ = 0xff; - src_scan += src_gap; - } - } else { - for (int col = 0; col < width; col++) { - if (src_Bpp == 4) { - FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); - } else { - FXARGB_SETDIB(dest_scan, - FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); - } - dest_scan += 4; - src_scan += src_Bpp; - } - } -} - -void CompositeRow_Argb2Rgb_Blend(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int dest_gap = dest_Bpp - 3; - if (src_alpha_scan) { - for (int col = 0; col < width; col++) { - uint8_t src_alpha; - if (clip_scan) { - src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; - } else { - src_alpha = *src_alpha_scan++; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += 3; - continue; - } - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int back_color = *dest_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, *src_scan); - *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - dest_scan++; - src_scan++; - } - dest_scan += dest_gap; - } - } else { - for (int col = 0; col < width; col++) { - uint8_t src_alpha; - if (clip_scan) { - src_alpha = src_scan[3] * (*clip_scan++) / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += 4; - continue; - } - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int back_color = *dest_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, *src_scan); - *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - dest_scan++; - src_scan++; - } - dest_scan += dest_gap; - src_scan++; - } - } -} - -void CompositeRow_Argb2Rgb_NoBlend(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan) { - int dest_gap = dest_Bpp - 3; - if (src_alpha_scan) { - for (int col = 0; col < width; col++) { - uint8_t src_alpha; - if (clip_scan) { - src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; - } else { - src_alpha = *src_alpha_scan++; - } - if (src_alpha == 255) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - dest_scan += dest_gap; - continue; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += 3; - continue; - } - for (int color = 0; color < 3; color++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); - dest_scan++; - src_scan++; - } - dest_scan += dest_gap; - } - } else { - for (int col = 0; col < width; col++) { - uint8_t src_alpha; - if (clip_scan) { - src_alpha = src_scan[3] * (*clip_scan++) / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 255) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - dest_scan += dest_gap; - src_scan++; - continue; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += 4; - continue; - } - for (int color = 0; color < 3; color++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); - dest_scan++; - src_scan++; - } - dest_scan += dest_gap; - src_scan++; - } - } -} - -void CompositeRow_Rgb2Rgb_Blend_NoClip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - int src_Bpp) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int dest_gap = dest_Bpp - 3; - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int back_color = *dest_scan; - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, src_color); - *dest_scan = blended; - dest_scan++; - src_scan++; - } - dest_scan += dest_gap; - src_scan += src_gap; - } -} - -void CompositeRow_Rgb2Rgb_Blend_Clip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - int src_Bpp, - const uint8_t* clip_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int dest_gap = dest_Bpp - 3; - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - uint8_t src_alpha = *clip_scan++; - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += src_Bpp; - continue; - } - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int src_color = *src_scan; - int back_color = *dest_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, src_color); - *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - dest_scan++; - src_scan++; - } - dest_scan += dest_gap; - src_scan += src_gap; - } -} - -void CompositeRow_Rgb2Rgb_NoBlend_NoClip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - int src_Bpp) { - if (dest_Bpp == src_Bpp) { - FXSYS_memcpy(dest_scan, src_scan, width * dest_Bpp); - return; - } - for (int col = 0; col < width; col++) { - dest_scan[0] = src_scan[0]; - dest_scan[1] = src_scan[1]; - dest_scan[2] = src_scan[2]; - dest_scan += dest_Bpp; - src_scan += src_Bpp; - } -} - -void CompositeRow_Rgb2Rgb_NoBlend_Clip(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - int src_Bpp, - const uint8_t* clip_scan) { - for (int col = 0; col < width; col++) { - int src_alpha = clip_scan[col]; - if (src_alpha == 255) { - dest_scan[0] = src_scan[0]; - dest_scan[1] = src_scan[1]; - dest_scan[2] = src_scan[2]; - } else if (src_alpha) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); - dest_scan++; - src_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); - dest_scan++; - src_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha); - dest_scan += dest_Bpp - 2; - src_scan += src_Bpp - 2; - continue; - } - dest_scan += dest_Bpp; - src_scan += src_Bpp; - } -} - -void CompositeRow_Argb2Argb_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan, - const uint8_t* src_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - uint8_t* dp = src_cache_scan; - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_alpha_scan) { - if (dest_alpha_scan) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, pixel_count); - } else { - for (int col = 0; col < pixel_count; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - dp[3] = *src_alpha_scan++; - src_scan += 3; - dp += 4; - } - src_alpha_scan = nullptr; - } - } else { - if (dest_alpha_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - 1); - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * src_scan[3] / 255; - *dest_alpha_scan = src_alpha; - *dest_scan++ = *src_cache_scan++; - *dest_scan++ = *src_cache_scan++; - *dest_scan++ = *src_cache_scan++; - } else { - *dest_alpha_scan = src_scan[3]; - *dest_scan++ = *src_cache_scan++; - *dest_scan++ = *src_cache_scan++; - *dest_scan++ = *src_cache_scan++; - } - dest_alpha_scan++; - src_scan += 4; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * src_scan[3] / 255; - } else { - src_alpha = src_scan[3]; - } - src_scan += 4; - if (src_alpha == 0) { - dest_scan += 3; - src_cache_scan += 3; - dest_alpha_scan++; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - if (blend_type) { - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, *dest_scan, *src_cache_scan); - blended = FXDIB_ALPHA_MERGE(*src_cache_scan, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, alpha_ratio); - } - dest_scan++; - src_cache_scan++; - } - } - return; - } - for (int col = 0; col < pixel_count; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - dp[3] = src_scan[3]; - src_scan += 4; - dp += 4; - } - } - CompositeRow_Argb2Argb(dest_scan, src_cache_scan, pixel_count, blend_type, - clip_scan, dest_alpha_scan, src_alpha_scan); -} - -void CompositeRow_Rgb2Argb_Blend_NoClip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int src_Bpp, - uint8_t* dest_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_cache_scan, width, - blend_type, 3, dest_alpha_scan); -} - -void CompositeRow_Rgb2Argb_Blend_Clip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int src_Bpp, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type, - 3, clip_scan, dest_alpha_scan); -} - -void CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int src_Bpp, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_cache_scan, width, 3, - clip_scan, dest_alpha_scan); -} - -void CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int src_Bpp, - uint8_t* dest_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_cache_scan, width, 3, - dest_alpha_scan); -} - -void CompositeRow_Argb2Rgb_Blend_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_alpha_scan) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int dest_gap = dest_Bpp - 3; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1); - uint8_t src_alpha; - if (clip_scan) { - src_alpha = src_scan[3] * (*clip_scan++) / 255; - } else { - src_alpha = src_scan[3]; - } - src_scan += 4; - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_cache_scan += 3; - continue; - } - if (bNonseparableBlend) { - RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors); - } - for (int color = 0; color < 3; color++) { - int back_color = *dest_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, *src_cache_scan); - *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - dest_scan++; - src_cache_scan++; - } - dest_scan += dest_gap; - } - return; - } - CompositeRow_Argb2Rgb_Blend(dest_scan, src_cache_scan, width, blend_type, - dest_Bpp, clip_scan, src_alpha_scan); -} - -void CompositeRow_Argb2Rgb_NoBlend_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_alpha_scan) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - int dest_gap = dest_Bpp - 3; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1); - uint8_t src_alpha; - if (clip_scan) { - src_alpha = src_scan[3] * (*clip_scan++) / 255; - } else { - src_alpha = src_scan[3]; - } - src_scan += 4; - if (src_alpha == 255) { - *dest_scan++ = *src_cache_scan++; - *dest_scan++ = *src_cache_scan++; - *dest_scan++ = *src_cache_scan++; - dest_scan += dest_gap; - continue; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_cache_scan += 3; - continue; - } - for (int color = 0; color < 3; color++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, src_alpha); - dest_scan++; - src_cache_scan++; - } - dest_scan += dest_gap; - } - return; - } - CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_cache_scan, width, dest_Bpp, - clip_scan, src_alpha_scan); -} - -void CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - int src_Bpp, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_cache_scan, width, - blend_type, dest_Bpp, 3); -} - -void CompositeRow_Rgb2Rgb_Blend_Clip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - int src_Bpp, - const uint8_t* clip_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type, - dest_Bpp, 3, clip_scan); -} - -void CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - int src_Bpp, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_cache_scan, width, - dest_Bpp, 3); -} - -void CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - int src_Bpp, - const uint8_t* clip_scan, - uint8_t* src_cache_scan, - void* pIccTransform) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - if (src_Bpp == 3) { - pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, - width); - } else { - uint8_t* dp = src_cache_scan; - for (int col = 0; col < width; col++) { - pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1); - src_scan += 4; - dp += 3; - } - } - CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_cache_scan, width, dest_Bpp, - 3, clip_scan); -} - -void CompositeRow_8bppPal2Gray(uint8_t* dest_scan, - const uint8_t* src_scan, - const uint8_t* pPalette, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan) { - if (src_alpha_scan) { - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - int src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - if (src_alpha) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - } else { - *dest_scan = gray; - } - dest_scan++; - src_scan++; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - int src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - if (src_alpha) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - } else { - *dest_scan = gray; - } - dest_scan++; - src_scan++; - } - } else { - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); - } else { - *dest_scan = gray; - } - dest_scan++; - src_scan++; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); - } else { - *dest_scan = gray; - } - dest_scan++; - src_scan++; - } - } -} - -void CompositeRow_8bppPal2Graya(uint8_t* dest_scan, - const uint8_t* src_scan, - const uint8_t* pPalette, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan, - const uint8_t* src_alpha_scan) { - if (src_alpha_scan) { - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - src_scan++; - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - if (src_alpha) { - *dest_scan = gray; - *dest_alpha_scan = src_alpha; - } - dest_scan++; - dest_alpha_scan++; - continue; - } - uint8_t src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - *dest_alpha_scan = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_alpha_scan++; - dest_scan++; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - src_scan++; - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - int src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - if (src_alpha) { - *dest_scan = gray; - *dest_alpha_scan = src_alpha; - } - dest_scan++; - dest_alpha_scan++; - continue; - } - uint8_t src_alpha = *src_alpha_scan++; - if (clip_scan) { - src_alpha = clip_scan[col] * src_alpha / 255; - } - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; - int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan); - dest_alpha_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - } - } else { - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - src_scan++; - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = gray; - *dest_alpha_scan++ = 255; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = pPalette[*src_scan]; - src_scan++; - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = gray; - *dest_alpha_scan++ = 255; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - } - } -} - -void CompositeRow_1bppPal2Gray(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - const uint8_t* pPalette, - int pixel_count, - int blend_type, - const uint8_t* clip_scan) { - int reset_gray = pPalette[0]; - int set_gray = pPalette[1]; - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = - (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) - ? set_gray - : reset_gray; - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); - } else { - *dest_scan = gray; - } - dest_scan++; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = - (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) - ? set_gray - : reset_gray; - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]); - } else { - *dest_scan = gray; - } - dest_scan++; - } -} - -void CompositeRow_1bppPal2Graya(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - const uint8_t* pPalette, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - int reset_gray = pPalette[0]; - int set_gray = pPalette[1]; - if (blend_type) { - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = - (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) - ? set_gray - : reset_gray; - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = gray; - *dest_alpha_scan++ = 255; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) - gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan; - else - gray = Blend(blend_type, *dest_scan, gray); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - uint8_t gray = - (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) - ? set_gray - : reset_gray; - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = gray; - *dest_alpha_scan++ = 255; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio); - dest_scan++; - } -} - -void CompositeRow_8bppRgb2Rgb_NoBlend(uint8_t* dest_scan, - const uint8_t* src_scan, - uint32_t* pPalette, - int pixel_count, - int DestBpp, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan) { - if (src_alpha_scan) { - int dest_gap = DestBpp - 3; - FX_ARGB argb = 0; - for (int col = 0; col < pixel_count; col++) { - argb = pPalette[*src_scan]; - int src_r = FXARGB_R(argb); - int src_g = FXARGB_G(argb); - int src_b = FXARGB_B(argb); - src_scan++; - uint8_t src_alpha = 0; - if (clip_scan) { - src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255; - } else { - src_alpha = *src_alpha_scan++; - } - if (src_alpha == 255) { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - dest_scan += dest_gap; - continue; - } - if (src_alpha == 0) { - dest_scan += DestBpp; - continue; - } - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); - dest_scan++; - dest_scan += dest_gap; - } - } else { - FX_ARGB argb = 0; - for (int col = 0; col < pixel_count; col++) { - argb = pPalette[*src_scan]; - int src_r = FXARGB_R(argb); - int src_g = FXARGB_G(argb); - int src_b = FXARGB_B(argb); - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); - dest_scan++; - } else { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - } - if (DestBpp == 4) { - dest_scan++; - } - src_scan++; - } - } -} - -void CompositeRow_1bppRgb2Rgb_NoBlend(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - uint32_t* pPalette, - int pixel_count, - int DestBpp, - const uint8_t* clip_scan) { - int reset_r, reset_g, reset_b; - int set_r, set_g, set_b; - reset_r = FXARGB_R(pPalette[0]); - reset_g = FXARGB_G(pPalette[0]); - reset_b = FXARGB_B(pPalette[0]); - set_r = FXARGB_R(pPalette[1]); - set_g = FXARGB_G(pPalette[1]); - set_b = FXARGB_B(pPalette[1]); - for (int col = 0; col < pixel_count; col++) { - int src_r, src_g, src_b; - if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { - src_r = set_r; - src_g = set_g; - src_b = set_b; - } else { - src_r = reset_r; - src_g = reset_g; - src_b = reset_b; - } - if (clip_scan && clip_scan[col] < 255) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]); - dest_scan++; - } else { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - } - if (DestBpp == 4) { - dest_scan++; - } - } -} - -void CompositeRow_8bppRgb2Argb_NoBlend(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - uint32_t* pPalette, - const uint8_t* clip_scan, - const uint8_t* src_alpha_scan) { - if (src_alpha_scan) { - for (int col = 0; col < width; col++) { - FX_ARGB argb = pPalette[*src_scan]; - src_scan++; - int src_r = FXARGB_R(argb); - int src_g = FXARGB_G(argb); - int src_b = FXARGB_B(argb); - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255; - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); - } else { - FXARGB_SETDIB(dest_scan, - FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b)); - } - dest_scan += 4; - src_alpha_scan++; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255; - } else { - src_alpha = *src_alpha_scan++; - } - if (src_alpha == 0) { - dest_scan += 4; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - dest_scan++; - dest_scan++; - } - } else { - for (int col = 0; col < width; col++) { - FX_ARGB argb = pPalette[*src_scan]; - int src_r = FXARGB_R(argb); - int src_g = FXARGB_G(argb); - int src_b = FXARGB_B(argb); - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - *dest_scan++ = 255; - src_scan++; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan += 4; - src_scan++; - continue; - } - int back_alpha = dest_scan[3]; - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - dest_scan++; - dest_scan++; - src_scan++; - } - } -} - -void CompositeRow_1bppRgb2Argb_NoBlend(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - uint32_t* pPalette, - const uint8_t* clip_scan) { - int reset_r, reset_g, reset_b; - int set_r, set_g, set_b; - reset_r = FXARGB_R(pPalette[0]); - reset_g = FXARGB_G(pPalette[0]); - reset_b = FXARGB_B(pPalette[0]); - set_r = FXARGB_R(pPalette[1]); - set_g = FXARGB_G(pPalette[1]); - set_b = FXARGB_B(pPalette[1]); - for (int col = 0; col < width; col++) { - int src_r, src_g, src_b; - if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { - src_r = set_r; - src_g = set_g; - src_b = set_b; - } else { - src_r = reset_r; - src_g = reset_g; - src_b = reset_b; - } - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - *dest_scan++ = 255; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan += 4; - continue; - } - int back_alpha = dest_scan[3]; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - dest_scan++; - dest_scan++; - } -} - -void CompositeRow_1bppRgb2Rgba_NoBlend(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - uint32_t* pPalette, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - int reset_r, reset_g, reset_b; - int set_r, set_g, set_b; - reset_r = FXARGB_R(pPalette[0]); - reset_g = FXARGB_G(pPalette[0]); - reset_b = FXARGB_B(pPalette[0]); - set_r = FXARGB_R(pPalette[1]); - set_g = FXARGB_G(pPalette[1]); - set_b = FXARGB_B(pPalette[1]); - for (int col = 0; col < width; col++) { - int src_r, src_g, src_b; - if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { - src_r = set_r; - src_g = set_g; - src_b = set_b; - } else { - src_r = reset_r; - src_g = reset_g; - src_b = reset_b; - } - if (!clip_scan || clip_scan[col] == 255) { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - *dest_alpha_scan++ = 255; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan += 3; - dest_alpha_scan++; - continue; - } - int back_alpha = *dest_alpha_scan; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - dest_scan++; - } -} - -void CompositeRow_ByteMask2Argb(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int pixel_count, - int blend_type, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); - dest_scan += 4; - continue; - } - if (src_alpha == 0) { - dest_scan += 4; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - RGB_Blend(blend_type, scan, dest_scan, blended_colors); - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); - dest_scan++; - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); - dest_scan++; - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); - } else if (blend_type) { - int blended = Blend(blend_type, *dest_scan, src_b); - blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_g); - blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_r); - blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - } - dest_scan += 2; - } -} - -void CompositeRow_ByteMask2Rgba(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int pixel_count, - int blend_type, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - *dest_scan++ = src_b; - *dest_scan++ = src_g; - *dest_scan++ = src_r; - *dest_alpha_scan++ = src_alpha; - continue; - } - if (src_alpha == 0) { - dest_scan += 3; - dest_alpha_scan++; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - RGB_Blend(blend_type, scan, dest_scan, blended_colors); - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); - dest_scan++; - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); - dest_scan++; - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); - dest_scan++; - } else if (blend_type) { - int blended = Blend(blend_type, *dest_scan, src_b); - blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_g); - blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_r); - blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - dest_scan++; - } - } -} - -void CompositeRow_ByteMask2Rgb(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int pixel_count, - int blend_type, - int Bpp, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - if (src_alpha == 0) { - dest_scan += Bpp; - continue; - } - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - RGB_Blend(blend_type, scan, dest_scan, blended_colors); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); - } else if (blend_type) { - int blended = Blend(blend_type, *dest_scan, src_b); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_g); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_r); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); - } - dest_scan += Bpp - 2; - } -} - -void CompositeRow_ByteMask2Mask(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int pixel_count, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - uint8_t back_alpha = *dest_scan; - if (!back_alpha) { - *dest_scan = src_alpha; - } else if (src_alpha) { - *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; - } - dest_scan++; - } -} - -void CompositeRow_ByteMask2Gray(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_gray, - int pixel_count, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - if (src_alpha) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); - } - dest_scan++; - } -} - -void CompositeRow_ByteMask2Graya(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_gray, - int pixel_count, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - *dest_scan++ = src_gray; - *dest_alpha_scan++ = src_alpha; - continue; - } - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); - dest_scan++; - } -} - -void CompositeRow_BitMask2Argb(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int src_left, - int pixel_count, - int blend_type, - const uint8_t* clip_scan) { - if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { - FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); - for (int col = 0; col < pixel_count; col++) { - if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { - FXARGB_SETDIB(dest_scan, argb); - } - dest_scan += 4; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan += 4; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); - dest_scan += 4; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - RGB_Blend(blend_type, scan, dest_scan, blended_colors); - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio); - dest_scan++; - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio); - dest_scan++; - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio); - } else if (blend_type) { - int blended = Blend(blend_type, *dest_scan, src_b); - blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_g); - blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_r); - blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - } - dest_scan += 2; - } -} - -void CompositeRow_BitMask2Rgb(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int src_left, - int pixel_count, - int blend_type, - int Bpp, - const uint8_t* clip_scan) { - if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { - for (int col = 0; col < pixel_count; col++) { - if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { - dest_scan[2] = src_r; - dest_scan[1] = src_g; - dest_scan[0] = src_b; - } - dest_scan += Bpp; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan += Bpp; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - if (src_alpha == 0) { - dest_scan += Bpp; - continue; - } - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - RGB_Blend(blend_type, scan, dest_scan, blended_colors); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha); - } else if (blend_type) { - int blended = Blend(blend_type, *dest_scan, src_b); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_g); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); - dest_scan++; - blended = Blend(blend_type, *dest_scan, src_r); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha); - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); - } - dest_scan += Bpp - 2; - } -} - -void CompositeRow_BitMask2Mask(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_left, - int pixel_count, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan++; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - uint8_t back_alpha = *dest_scan; - if (!back_alpha) { - *dest_scan = src_alpha; - } else if (src_alpha) { - *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255; - } - dest_scan++; - } -} - -void CompositeRow_BitMask2Gray(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_gray, - int src_left, - int pixel_count, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan++; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - if (src_alpha) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha); - } - dest_scan++; - } -} - -void CompositeRow_BitMask2Graya(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_gray, - int src_left, - int pixel_count, - const uint8_t* clip_scan, - uint8_t* dest_alpha_scan) { - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan++; - dest_alpha_scan++; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - uint8_t back_alpha = *dest_alpha_scan; - if (back_alpha == 0) { - *dest_scan++ = src_gray; - *dest_alpha_scan++ = src_alpha; - continue; - } - if (src_alpha == 0) { - dest_scan++; - dest_alpha_scan++; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio); - dest_scan++; - } -} - -void CompositeRow_Argb2Argb_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int pixel_count, - int blend_type, - const uint8_t* clip_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < pixel_count; col++) { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - if (clip_scan) { - int src_alpha = clip_scan[col] * src_scan[3] / 255; - dest_scan[3] = src_alpha; - dest_scan[0] = src_scan[2]; - dest_scan[1] = src_scan[1]; - dest_scan[2] = src_scan[0]; - } else { - FXARGB_RGBORDERCOPY(dest_scan, src_scan); - } - dest_scan += 4; - src_scan += 4; - continue; - } - uint8_t src_alpha; - if (clip_scan) { - src_alpha = clip_scan[col] * src_scan[3] / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += 4; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - uint8_t dest_scan_o[3]; - dest_scan_o[0] = dest_scan[2]; - dest_scan_o[1] = dest_scan[1]; - dest_scan_o[2] = dest_scan[0]; - RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - if (blend_type) { - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, dest_scan[index], *src_scan); - blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha); - dest_scan[index] = - FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); - } else { - dest_scan[index] = - FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); - } - src_scan++; - } - dest_scan += 4; - src_scan++; - } -} - -void CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int src_Bpp) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - if (src_Bpp == 4) { - FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); - } else { - FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], - src_scan[1], src_scan[0])); - } - dest_scan += 4; - src_scan += src_Bpp; - continue; - } - dest_scan[3] = 0xff; - if (bNonseparableBlend) { - uint8_t dest_scan_o[3]; - dest_scan_o[0] = dest_scan[2]; - dest_scan_o[1] = dest_scan[1]; - dest_scan_o[2] = dest_scan[0]; - RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, dest_scan[index], src_color); - dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); - src_scan++; - } - dest_scan += 4; - src_scan += src_gap; - } -} - -void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - const uint8_t* clip_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - for (int col = 0; col < width; col++) { - uint8_t src_alpha; - if (clip_scan) { - src_alpha = src_scan[3] * (*clip_scan++) / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += 4; - continue; - } - if (bNonseparableBlend) { - uint8_t dest_scan_o[3]; - dest_scan_o[0] = dest_scan[2]; - dest_scan_o[1] = dest_scan[1]; - dest_scan_o[2] = dest_scan[0]; - RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - int back_color = dest_scan[index]; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, *src_scan); - dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - src_scan++; - } - dest_scan += dest_Bpp; - src_scan++; - } -} - -void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int src_Bpp) { - for (int col = 0; col < width; col++) { - if (src_Bpp == 4) { - FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan)); - } else { - FXARGB_SETRGBORDERDIB( - dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0])); - } - dest_scan += 4; - src_scan += src_Bpp; - } -} - -void CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - int src_Bpp) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - if (bNonseparableBlend) { - uint8_t dest_scan_o[3]; - dest_scan_o[0] = dest_scan[2]; - dest_scan_o[1] = dest_scan[1]; - dest_scan_o[2] = dest_scan[0]; - RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - int back_color = dest_scan[index]; - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, src_color); - dest_scan[index] = blended; - src_scan++; - } - dest_scan += dest_Bpp; - src_scan += src_gap; - } -} - -void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - const uint8_t* clip_scan) { - for (int col = 0; col < width; col++) { - uint8_t src_alpha; - if (clip_scan) { - src_alpha = src_scan[3] * (*clip_scan++) / 255; - } else { - src_alpha = src_scan[3]; - } - if (src_alpha == 255) { - dest_scan[2] = *src_scan++; - dest_scan[1] = *src_scan++; - dest_scan[0] = *src_scan++; - dest_scan += dest_Bpp; - src_scan++; - continue; - } - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += 4; - continue; - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - dest_scan[index] = - FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha); - src_scan++; - } - dest_scan += dest_Bpp; - src_scan++; - } -} - -void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - int src_Bpp) { - for (int col = 0; col < width; col++) { - dest_scan[2] = src_scan[0]; - dest_scan[1] = src_scan[1]; - dest_scan[0] = src_scan[2]; - dest_scan += dest_Bpp; - src_scan += src_Bpp; - } -} - -void CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int src_Bpp, - const uint8_t* clip_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - int src_alpha = *clip_scan++; - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - dest_scan[2] = *src_scan++; - dest_scan[1] = *src_scan++; - dest_scan[0] = *src_scan++; - src_scan += src_gap; - dest_scan += 4; - continue; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += src_Bpp; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (bNonseparableBlend) { - uint8_t dest_scan_o[3]; - dest_scan_o[0] = dest_scan[2]; - dest_scan_o[1] = dest_scan[1]; - dest_scan_o[2] = dest_scan[0]; - RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - int src_color = *src_scan; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, dest_scan[index], src_color); - blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha); - dest_scan[index] = - FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio); - src_scan++; - } - dest_scan += 4; - src_scan += src_gap; - } -} - -void CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int blend_type, - int dest_Bpp, - int src_Bpp, - const uint8_t* clip_scan) { - int blended_colors[3]; - bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE; - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - uint8_t src_alpha = *clip_scan++; - if (src_alpha == 0) { - dest_scan += dest_Bpp; - src_scan += src_Bpp; - continue; - } - if (bNonseparableBlend) { - uint8_t dest_scan_o[3]; - dest_scan_o[0] = dest_scan[2]; - dest_scan_o[1] = dest_scan[1]; - dest_scan_o[2] = dest_scan[0]; - RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors); - } - for (int color = 0; color < 3; color++) { - int index = 2 - color; - int src_color = *src_scan; - int back_color = dest_scan[index]; - int blended = bNonseparableBlend - ? blended_colors[color] - : Blend(blend_type, back_color, src_color); - dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - src_scan++; - } - dest_scan += dest_Bpp; - src_scan += src_gap; - } -} - -void CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int src_Bpp, - const uint8_t* clip_scan) { - int src_gap = src_Bpp - 3; - for (int col = 0; col < width; col++) { - int src_alpha = clip_scan[col]; - if (src_alpha == 255) { - dest_scan[2] = *src_scan++; - dest_scan[1] = *src_scan++; - dest_scan[0] = *src_scan++; - dest_scan[3] = 255; - dest_scan += 4; - src_scan += src_gap; - continue; - } - if (src_alpha == 0) { - dest_scan += 4; - src_scan += src_Bpp; - continue; - } - int back_alpha = dest_scan[3]; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - for (int color = 0; color < 3; color++) { - int index = 2 - color; - dest_scan[index] = - FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio); - src_scan++; - } - dest_scan += 4; - src_scan += src_gap; - } -} - -void CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - int dest_Bpp, - int src_Bpp, - const uint8_t* clip_scan) { - for (int col = 0; col < width; col++) { - int src_alpha = clip_scan[col]; - if (src_alpha == 255) { - dest_scan[2] = src_scan[0]; - dest_scan[1] = src_scan[1]; - dest_scan[0] = src_scan[2]; - } else if (src_alpha) { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], *src_scan, src_alpha); - src_scan++; - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], *src_scan, src_alpha); - src_scan++; - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], *src_scan, src_alpha); - dest_scan += dest_Bpp; - src_scan += src_Bpp - 2; - continue; - } - dest_scan += dest_Bpp; - src_scan += src_Bpp; - } -} - -void CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - FX_ARGB* pPalette, - int pixel_count, - int DestBpp, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101; - int src_r = FXARGB_R(argb); - int src_g = FXARGB_G(argb); - int src_b = FXARGB_B(argb); - if (clip_scan && clip_scan[col] < 255) { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); - } else { - dest_scan[2] = src_b; - dest_scan[1] = src_g; - dest_scan[0] = src_r; - } - dest_scan += DestBpp; - src_scan++; - } -} - -void CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - FX_ARGB* pPalette, - int pixel_count, - int DestBpp, - const uint8_t* clip_scan) { - int reset_r, reset_g, reset_b; - int set_r, set_g, set_b; - if (pPalette) { - reset_r = FXARGB_R(pPalette[0]); - reset_g = FXARGB_G(pPalette[0]); - reset_b = FXARGB_B(pPalette[0]); - set_r = FXARGB_R(pPalette[1]); - set_g = FXARGB_G(pPalette[1]); - set_b = FXARGB_B(pPalette[1]); - } else { - reset_r = reset_g = reset_b = 0; - set_r = set_g = set_b = 255; - } - for (int col = 0; col < pixel_count; col++) { - int src_r, src_g, src_b; - if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { - src_r = set_r; - src_g = set_g; - src_b = set_b; - } else { - src_r = reset_r; - src_g = reset_g; - src_b = reset_b; - } - if (clip_scan && clip_scan[col] < 255) { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]); - } else { - dest_scan[2] = src_b; - dest_scan[1] = src_g; - dest_scan[0] = src_r; - } - dest_scan += DestBpp; - } -} - -void CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - FX_ARGB* pPalette, - const uint8_t* clip_scan) { - for (int col = 0; col < width; col++) { - int src_r, src_g, src_b; - if (pPalette) { - FX_ARGB argb = pPalette[*src_scan]; - src_r = FXARGB_R(argb); - src_g = FXARGB_G(argb); - src_b = FXARGB_B(argb); - } else { - src_r = src_g = src_b = *src_scan; - } - if (!clip_scan || clip_scan[col] == 255) { - dest_scan[2] = src_b; - dest_scan[1] = src_g; - dest_scan[0] = src_r; - dest_scan[3] = 255; - src_scan++; - dest_scan += 4; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan += 4; - src_scan++; - continue; - } - int back_alpha = dest_scan[3]; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); - dest_scan += 4; - src_scan++; - } -} - -void CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - FX_ARGB* pPalette, - const uint8_t* clip_scan) { - int reset_r, reset_g, reset_b; - int set_r, set_g, set_b; - if (pPalette) { - reset_r = FXARGB_R(pPalette[0]); - reset_g = FXARGB_G(pPalette[0]); - reset_b = FXARGB_B(pPalette[0]); - set_r = FXARGB_R(pPalette[1]); - set_g = FXARGB_G(pPalette[1]); - set_b = FXARGB_B(pPalette[1]); - } else { - reset_r = reset_g = reset_b = 0; - set_r = set_g = set_b = 255; - } - for (int col = 0; col < width; col++) { - int src_r, src_g, src_b; - if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) { - src_r = set_r; - src_g = set_g; - src_b = set_b; - } else { - src_r = reset_r; - src_g = reset_g; - src_b = reset_b; - } - if (!clip_scan || clip_scan[col] == 255) { - dest_scan[2] = src_b; - dest_scan[1] = src_g; - dest_scan[0] = src_r; - dest_scan[3] = 255; - dest_scan += 4; - continue; - } - int src_alpha = clip_scan[col]; - if (src_alpha == 0) { - dest_scan += 4; - continue; - } - int back_alpha = dest_scan[3]; - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); - dest_scan += 4; - } -} - -void CompositeRow_ByteMask2Argb_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int pixel_count, - int blend_type, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETRGBORDERDIB(dest_scan, - FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); - dest_scan += 4; - continue; - } - if (src_alpha == 0) { - dest_scan += 4; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; - RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); - dest_scan[2] = - FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); - dest_scan[1] = - FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); - dest_scan[0] = - FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); - } else if (blend_type) { - int blended = Blend(blend_type, dest_scan[2], src_b); - blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); - blended = Blend(blend_type, dest_scan[1], src_g); - blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); - blended = Blend(blend_type, dest_scan[0], src_r); - blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); - } else { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); - } - dest_scan += 4; - } -} - -void CompositeRow_ByteMask2Rgb_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int pixel_count, - int blend_type, - int Bpp, - const uint8_t* clip_scan) { - for (int col = 0; col < pixel_count; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255; - } else { - src_alpha = mask_alpha * src_scan[col] / 255; - } - if (src_alpha == 0) { - dest_scan += Bpp; - continue; - } - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; - RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); - dest_scan[2] = - FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); - dest_scan[1] = - FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); - dest_scan[0] = - FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); - } else if (blend_type) { - int blended = Blend(blend_type, dest_scan[2], src_b); - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha); - blended = Blend(blend_type, dest_scan[1], src_g); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha); - blended = Blend(blend_type, dest_scan[0], src_r); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha); - } else { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); - } - dest_scan += Bpp; - } -} - -void CompositeRow_BitMask2Argb_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int src_left, - int pixel_count, - int blend_type, - const uint8_t* clip_scan) { - if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { - FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b); - for (int col = 0; col < pixel_count; col++) { - if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { - FXARGB_SETRGBORDERDIB(dest_scan, argb); - } - dest_scan += 4; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan += 4; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETRGBORDERDIB(dest_scan, - FXARGB_MAKE(src_alpha, src_r, src_g, src_b)); - dest_scan += 4; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; - RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); - dest_scan[2] = - FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio); - dest_scan[1] = - FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio); - dest_scan[0] = - FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio); - } else if (blend_type) { - int blended = Blend(blend_type, dest_scan[2], src_b); - blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha); - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio); - blended = Blend(blend_type, dest_scan[1], src_g); - blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio); - blended = Blend(blend_type, dest_scan[0], src_r); - blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio); - } else { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio); - } - dest_scan += 4; - } -} - -void CompositeRow_BitMask2Rgb_RgbByteOrder(uint8_t* dest_scan, - const uint8_t* src_scan, - int mask_alpha, - int src_r, - int src_g, - int src_b, - int src_left, - int pixel_count, - int blend_type, - int Bpp, - const uint8_t* clip_scan) { - if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) { - for (int col = 0; col < pixel_count; col++) { - if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) { - dest_scan[2] = src_b; - dest_scan[1] = src_g; - dest_scan[0] = src_r; - } - dest_scan += Bpp; - } - return; - } - for (int col = 0; col < pixel_count; col++) { - if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) { - dest_scan += Bpp; - continue; - } - int src_alpha; - if (clip_scan) { - src_alpha = mask_alpha * clip_scan[col] / 255; - } else { - src_alpha = mask_alpha; - } - if (src_alpha == 0) { - dest_scan += Bpp; - continue; - } - if (blend_type >= FXDIB_BLEND_NONSEPARABLE) { - int blended_colors[3]; - uint8_t scan[3] = {static_cast(src_b), - static_cast(src_g), - static_cast(src_r)}; - uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]}; - RGB_Blend(blend_type, scan, dest_scan_o, blended_colors); - dest_scan[2] = - FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha); - dest_scan[1] = - FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha); - dest_scan[0] = - FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha); - } else if (blend_type) { - int back_color = dest_scan[2]; - int blended = Blend(blend_type, back_color, src_b); - dest_scan[2] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - back_color = dest_scan[1]; - blended = Blend(blend_type, back_color, src_g); - dest_scan[1] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - back_color = dest_scan[0]; - blended = Blend(blend_type, back_color, src_r); - dest_scan[0] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha); - } else { - dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha); - dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha); - dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha); - } - dest_scan += Bpp; - } -} - -bool ScanlineCompositor_InitSourceMask(FXDIB_Format dest_format, - int alpha_flag, - uint32_t mask_color, - int& mask_alpha, - int& mask_red, - int& mask_green, - int& mask_blue, - int& mask_black, - CCodec_IccModule* pIccModule, - void* pIccTransform) { - if (alpha_flag >> 8) { - mask_alpha = alpha_flag & 0xff; - mask_red = FXSYS_GetCValue(mask_color); - mask_green = FXSYS_GetMValue(mask_color); - mask_blue = FXSYS_GetYValue(mask_color); - mask_black = FXSYS_GetKValue(mask_color); - } else { - mask_alpha = FXARGB_A(mask_color); - mask_red = FXARGB_R(mask_color); - mask_green = FXARGB_G(mask_color); - mask_blue = FXARGB_B(mask_color); - } - if (dest_format == FXDIB_8bppMask) { - return true; - } - if ((dest_format & 0xff) == 8) { - if (pIccTransform) { - mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) - : FXARGB_TODIB(mask_color); - uint8_t* gray_p = (uint8_t*)&mask_color; - pIccModule->TranslateScanline(pIccTransform, gray_p, gray_p, 1); - mask_red = dest_format & 0x0400 ? FX_CCOLOR(gray_p[0]) : gray_p[0]; - } else { - if (alpha_flag >> 8) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(mask_red, mask_green, mask_blue, mask_black, r, g, - b); - mask_red = FXRGB2GRAY(r, g, b); - } else { - mask_red = FXRGB2GRAY(mask_red, mask_green, mask_blue); - } - if (dest_format & 0x0400) { - mask_red = FX_CCOLOR(mask_red); - } - } - } else { - uint8_t* mask_color_p = (uint8_t*)&mask_color; - mask_color = - (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color); - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, mask_color_p, mask_color_p, - 1); - mask_red = mask_color_p[2]; - mask_green = mask_color_p[1]; - mask_blue = mask_color_p[0]; - } else if (alpha_flag >> 8) { - AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], - mask_color_p[3], mask_color_p[2], mask_color_p[1], - mask_color_p[0]); - mask_red = mask_color_p[2]; - mask_green = mask_color_p[1]; - mask_blue = mask_color_p[0]; - } - } - return true; -} - -void ScanlineCompositor_InitSourcePalette(FXDIB_Format src_format, - FXDIB_Format dest_format, - uint32_t*& pDestPalette, - uint32_t* pSrcPalette, - CCodec_IccModule* pIccModule, - void* pIccTransform) { - bool isSrcCmyk = !!(src_format & 0x0400); - bool isDstCmyk = !!(dest_format & 0x0400); - pDestPalette = nullptr; - if (pIccTransform) { - if (pSrcPalette) { - if ((dest_format & 0xff) == 8) { - int pal_count = 1 << (src_format & 0xff); - uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); - pDestPalette = (uint32_t*)gray_pal; - for (int i = 0; i < pal_count; i++) { - uint32_t color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) - : FXARGB_TODIB(pSrcPalette[i]); - pIccModule->TranslateScanline(pIccTransform, gray_pal, - (const uint8_t*)&color, 1); - gray_pal++; - } - } else { - int palsize = 1 << (src_format & 0xff); - pDestPalette = FX_Alloc(uint32_t, palsize); - for (int i = 0; i < palsize; i++) { - uint32_t color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) - : FXARGB_TODIB(pSrcPalette[i]); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&color, - (const uint8_t*)&color, 1); - pDestPalette[i] = - isDstCmyk ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - } - } - } else { - int pal_count = 1 << (src_format & 0xff); - uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); - if (pal_count == 2) { - gray_pal[0] = 0; - gray_pal[1] = 255; - } else { - for (int i = 0; i < pal_count; i++) { - gray_pal[i] = i; - } - } - if ((dest_format & 0xff) == 8) { - pIccModule->TranslateScanline(pIccTransform, gray_pal, gray_pal, - pal_count); - pDestPalette = (uint32_t*)gray_pal; - } else { - pDestPalette = FX_Alloc(uint32_t, pal_count); - for (int i = 0; i < pal_count; i++) { - pIccModule->TranslateScanline( - pIccTransform, (uint8_t*)&pDestPalette[i], &gray_pal[i], 1); - pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(pDestPalette[i]) - : FXARGB_TODIB(pDestPalette[i]); - } - FX_Free(gray_pal); - } - } - } else { - if (pSrcPalette) { - if ((dest_format & 0xff) == 8) { - int pal_count = 1 << (src_format & 0xff); - uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); - pDestPalette = (uint32_t*)gray_pal; - if (isSrcCmyk) { - for (int i = 0; i < pal_count; i++) { - FX_CMYK cmyk = pSrcPalette[i]; - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), - FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, - g, b); - *gray_pal++ = FXRGB2GRAY(r, g, b); - } - } else { - for (int i = 0; i < pal_count; i++) { - FX_ARGB argb = pSrcPalette[i]; - *gray_pal++ = - FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); - } - } - } else { - int palsize = 1 << (src_format & 0xff); - pDestPalette = FX_Alloc(uint32_t, palsize); - if (isDstCmyk == isSrcCmyk) { - FXSYS_memcpy(pDestPalette, pSrcPalette, palsize * sizeof(uint32_t)); - } else { - for (int i = 0; i < palsize; i++) { - FX_CMYK cmyk = pSrcPalette[i]; - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), - FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, - g, b); - pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b); - } - } - } - } else { - if ((dest_format & 0xff) == 8) { - int pal_count = 1 << (src_format & 0xff); - uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count); - if (pal_count == 2) { - gray_pal[0] = 0; - gray_pal[1] = 255; - } else { - for (int i = 0; i < pal_count; i++) { - gray_pal[i] = i; - } - } - pDestPalette = (uint32_t*)gray_pal; - } else { - int palsize = 1 << (src_format & 0xff); - pDestPalette = FX_Alloc(uint32_t, palsize); - if (palsize == 2) { - pDestPalette[0] = isSrcCmyk ? 255 : 0xff000000; - pDestPalette[1] = isSrcCmyk ? 0 : 0xffffffff; - } else { - for (int i = 0; i < palsize; i++) { - pDestPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101); - } - } - if (isSrcCmyk != isDstCmyk) { - for (int i = 0; i < palsize; i++) { - FX_CMYK cmyk = pDestPalette[i]; - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), - FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, - g, b); - pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b); - } - } - } - } - } -} - -} // namespace - -CFX_ScanlineCompositor::CFX_ScanlineCompositor() { - m_pSrcPalette = nullptr; - m_pCacheScanline = nullptr; - m_CacheSize = 0; - m_bRgbByteOrder = false; - m_BlendType = FXDIB_BLEND_NORMAL; - m_pIccTransform = nullptr; -} - -CFX_ScanlineCompositor::~CFX_ScanlineCompositor() { - FX_Free(m_pSrcPalette); - FX_Free(m_pCacheScanline); -} - -bool CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, - FXDIB_Format src_format, - int32_t width, - uint32_t* pSrcPalette, - uint32_t mask_color, - int blend_type, - bool bClip, - bool bRgbByteOrder, - int alpha_flag, - void* pIccTransform) { - m_SrcFormat = src_format; - m_DestFormat = dest_format; - m_BlendType = blend_type; - m_bRgbByteOrder = bRgbByteOrder; - CCodec_IccModule* pIccModule = nullptr; - if (CFX_GEModule::Get()->GetCodecModule()) { - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - } - if (!pIccModule) { - pIccTransform = nullptr; - } - m_pIccTransform = pIccTransform; - if ((dest_format & 0xff) == 1) { - return false; - } - if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) { - return ScanlineCompositor_InitSourceMask( - dest_format, alpha_flag, mask_color, m_MaskAlpha, m_MaskRed, - m_MaskGreen, m_MaskBlue, m_MaskBlack, pIccModule, pIccTransform); - } - if (!pIccTransform && (~src_format & 0x0400) && (dest_format & 0x0400)) { - return false; - } - if ((m_SrcFormat & 0xff) <= 8) { - if (dest_format == FXDIB_8bppMask) { - return true; - } - ScanlineCompositor_InitSourcePalette(src_format, dest_format, m_pSrcPalette, - pSrcPalette, pIccModule, - pIccTransform); - m_Transparency = - (dest_format == FXDIB_Argb ? 1 : 0) + (dest_format & 0x0200 ? 2 : 0) + - (dest_format & 0x0400 ? 4 : 0) + ((src_format & 0xff) == 1 ? 8 : 0); - return true; - } - m_Transparency = (src_format & 0x0200 ? 0 : 1) + - (dest_format & 0x0200 ? 0 : 2) + - (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0) + - (bClip ? 8 : 0) + (src_format & 0x0400 ? 16 : 0) + - (dest_format & 0x0400 ? 32 : 0) + (pIccTransform ? 64 : 0); - return true; -} - -void CFX_ScanlineCompositor::CompositeRgbBitmapLine( - uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - const uint8_t* clip_scan, - const uint8_t* src_extra_alpha, - uint8_t* dst_extra_alpha) { - int src_Bpp = (m_SrcFormat & 0xff) >> 3; - int dest_Bpp = (m_DestFormat & 0xff) >> 3; - if (m_bRgbByteOrder) { - switch (m_Transparency) { - case 0: - case 4: - case 8: - case 12: - CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, - m_BlendType, clip_scan); - break; - case 1: - CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder( - dest_scan, src_scan, width, m_BlendType, src_Bpp); - break; - case 2: - case 10: - CompositeRow_Argb2Rgb_Blend_RgbByteOrder( - dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan); - break; - case 3: - CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder( - dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp); - break; - case 5: - CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, - width, src_Bpp); - break; - case 6: - case 14: - CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, - dest_Bpp, clip_scan); - break; - case 7: - CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder( - dest_scan, src_scan, width, dest_Bpp, src_Bpp); - break; - case 9: - CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder( - dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan); - break; - case 11: - CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, - m_BlendType, dest_Bpp, - src_Bpp, clip_scan); - break; - case 13: - CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder( - dest_scan, src_scan, width, src_Bpp, clip_scan); - break; - case 15: - CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder( - dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan); - break; - } - return; - } - if (m_DestFormat == FXDIB_8bppMask) { - if (m_SrcFormat & 0x0200) { - if (m_SrcFormat == FXDIB_Argb) { - CompositeRow_Argb2Mask(dest_scan, src_scan, width, clip_scan); - } else { - CompositeRow_Rgba2Mask(dest_scan, src_extra_alpha, width, clip_scan); - } - } else { - CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); - } - } else if ((m_DestFormat & 0xff) == 8) { - if (m_DestFormat & 0x0400) { - for (int i = 0; i < width; i++) { - *dest_scan = ~*dest_scan; - dest_scan++; - } - } - if (m_SrcFormat & 0x0200) { - if (m_DestFormat & 0x0200) { - CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, - clip_scan, src_extra_alpha, dst_extra_alpha, - m_pIccTransform); - } else { - CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, - clip_scan, src_extra_alpha, m_pIccTransform); - } - } else { - if (m_DestFormat & 0x0200) { - CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, - clip_scan, dst_extra_alpha, m_pIccTransform); - } else { - CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, - clip_scan, m_pIccTransform); - } - } - if (m_DestFormat & 0x0400) { - for (int i = 0; i < width; i++) { - *dest_scan = ~*dest_scan; - dest_scan++; - } - } - } else { - int dest_Size = width * dest_Bpp + 4; - if (dest_Size > m_CacheSize) { - m_pCacheScanline = FX_Realloc(uint8_t, m_pCacheScanline, dest_Size); - if (!m_pCacheScanline) { - return; - } - m_CacheSize = dest_Size; - } - switch (m_Transparency) { - case 0: - case 4: - case 8: - case 4 + 8: { - CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, - clip_scan, dst_extra_alpha, src_extra_alpha); - } break; - case 64: - case 4 + 64: - case 8 + 64: - case 4 + 8 + 64: { - CompositeRow_Argb2Argb_Transform( - dest_scan, src_scan, width, m_BlendType, clip_scan, dst_extra_alpha, - src_extra_alpha, m_pCacheScanline, m_pIccTransform); - } break; - case 1: - CompositeRow_Rgb2Argb_Blend_NoClip( - dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha); - break; - case 1 + 64: - CompositeRow_Rgb2Argb_Blend_NoClip_Transform( - dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha, - m_pCacheScanline, m_pIccTransform); - break; - case 1 + 8: - CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, - m_BlendType, src_Bpp, clip_scan, - dst_extra_alpha); - break; - case 1 + 8 + 64: - CompositeRow_Rgb2Argb_Blend_Clip_Transform( - dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan, - dst_extra_alpha, m_pCacheScanline, m_pIccTransform); - break; - case 1 + 4: - CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, - src_Bpp, dst_extra_alpha); - break; - case 1 + 4 + 64: - CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform( - dest_scan, src_scan, width, src_Bpp, dst_extra_alpha, - m_pCacheScanline, m_pIccTransform); - break; - case 1 + 4 + 8: - CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, - clip_scan, dst_extra_alpha); - break; - case 1 + 4 + 8 + 64: - CompositeRow_Rgb2Argb_NoBlend_Clip_Transform( - dest_scan, src_scan, width, src_Bpp, clip_scan, dst_extra_alpha, - m_pCacheScanline, m_pIccTransform); - break; - case 2: - case 2 + 8: - CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, - dest_Bpp, clip_scan, src_extra_alpha); - break; - case 2 + 64: - case 2 + 8 + 64: - CompositeRow_Argb2Rgb_Blend_Transform( - dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan, - src_extra_alpha, m_pCacheScanline, m_pIccTransform); - break; - case 2 + 4: - case 2 + 4 + 8: - CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, - clip_scan, src_extra_alpha); - break; - case 2 + 4 + 64: - case 2 + 4 + 8 + 64: - CompositeRow_Argb2Rgb_NoBlend_Transform( - dest_scan, src_scan, width, dest_Bpp, clip_scan, src_extra_alpha, - m_pCacheScanline, m_pIccTransform); - break; - case 1 + 2: - CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, - m_BlendType, dest_Bpp, src_Bpp); - break; - case 1 + 2 + 64: - CompositeRow_Rgb2Rgb_Blend_NoClip_Transform( - dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, - m_pCacheScanline, m_pIccTransform); - break; - case 1 + 2 + 8: - CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, - dest_Bpp, src_Bpp, clip_scan); - break; - case 1 + 2 + 8 + 64: - CompositeRow_Rgb2Rgb_Blend_Clip_Transform( - dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, - clip_scan, m_pCacheScanline, m_pIccTransform); - break; - case 1 + 2 + 4: - CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, - dest_Bpp, src_Bpp); - break; - case 1 + 2 + 4 + 64: - CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform( - dest_scan, src_scan, width, dest_Bpp, src_Bpp, m_pCacheScanline, - m_pIccTransform); - break; - case 1 + 2 + 4 + 8: - CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, - src_Bpp, clip_scan); - break; - case 1 + 2 + 4 + 8 + 64: - CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform( - dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan, - m_pCacheScanline, m_pIccTransform); - break; - } - } -} - -void CFX_ScanlineCompositor::CompositePalBitmapLine( - uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - const uint8_t* clip_scan, - const uint8_t* src_extra_alpha, - uint8_t* dst_extra_alpha) { - if (m_bRgbByteOrder) { - if (m_SrcFormat == FXDIB_1bppRgb) { - if (m_DestFormat == FXDIB_8bppRgb) { - return; - } - if (m_DestFormat == FXDIB_Argb) { - CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder( - dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan); - } else { - CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder( - dest_scan, src_scan, src_left, m_pSrcPalette, width, - (m_DestFormat & 0xff) >> 3, clip_scan); - } - } else { - if (m_DestFormat == FXDIB_8bppRgb) { - return; - } - if (m_DestFormat == FXDIB_Argb) { - CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder( - dest_scan, src_scan, width, m_pSrcPalette, clip_scan); - } else { - CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder( - dest_scan, src_scan, m_pSrcPalette, width, - (m_DestFormat & 0xff) >> 3, clip_scan); - } - } - return; - } - if (m_DestFormat == FXDIB_8bppMask) { - CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan); - return; - } - if ((m_DestFormat & 0xff) == 8) { - if (m_Transparency & 8) { - if (m_DestFormat & 0x0200) { - CompositeRow_1bppPal2Graya(dest_scan, src_scan, src_left, - (const uint8_t*)m_pSrcPalette, width, - m_BlendType, clip_scan, dst_extra_alpha); - } else { - CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left, - (const uint8_t*)m_pSrcPalette, width, - m_BlendType, clip_scan); - } - } else { - if (m_DestFormat & 0x0200) - CompositeRow_8bppPal2Graya( - dest_scan, src_scan, (const uint8_t*)m_pSrcPalette, width, - m_BlendType, clip_scan, dst_extra_alpha, src_extra_alpha); - else - CompositeRow_8bppPal2Gray(dest_scan, src_scan, - (const uint8_t*)m_pSrcPalette, width, - m_BlendType, clip_scan, src_extra_alpha); - } - } else { - switch (m_Transparency) { - case 1 + 2: - CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, - m_pSrcPalette, clip_scan, - src_extra_alpha); - break; - case 1 + 2 + 8: - CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, - m_pSrcPalette, clip_scan); - break; - case 0: - CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, - width, (m_DestFormat & 0xff) >> 3, - clip_scan, src_extra_alpha); - break; - case 0 + 8: - CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, - m_pSrcPalette, width, - (m_DestFormat & 0xff) >> 3, clip_scan); - break; - case 0 + 2: - CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, - width, (m_DestFormat & 0xff) >> 3, - clip_scan, src_extra_alpha); - break; - case 0 + 2 + 8: - CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, - m_pSrcPalette, clip_scan, - dst_extra_alpha); - break; - break; - } - } -} - -void CFX_ScanlineCompositor::CompositeByteMaskLine(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - const uint8_t* clip_scan, - uint8_t* dst_extra_alpha) { - if (m_DestFormat == FXDIB_8bppMask) { - CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, - clip_scan); - } else if ((m_DestFormat & 0xff) == 8) { - if (m_DestFormat & 0x0200) { - CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - width, clip_scan, dst_extra_alpha); - } else { - CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - width, clip_scan); - } - } else if (m_bRgbByteOrder) { - if (m_DestFormat == FXDIB_Argb) { - CompositeRow_ByteMask2Argb_RgbByteOrder( - dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, - width, m_BlendType, clip_scan); - } else { - CompositeRow_ByteMask2Rgb_RgbByteOrder( - dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, - width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); - } - return; - } else if (m_DestFormat == FXDIB_Argb) { - CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - m_MaskGreen, m_MaskBlue, width, m_BlendType, - clip_scan); - } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { - CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - m_MaskGreen, m_MaskBlue, width, m_BlendType, - (m_DestFormat & 0xff) >> 3, clip_scan); - } else if (m_DestFormat == FXDIB_Rgba) { - CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - m_MaskGreen, m_MaskBlue, width, m_BlendType, - clip_scan, dst_extra_alpha); - } -} - -void CFX_ScanlineCompositor::CompositeBitMaskLine(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - const uint8_t* clip_scan, - uint8_t* dst_extra_alpha) { - if (m_DestFormat == FXDIB_8bppMask) { - CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, - clip_scan); - } else if ((m_DestFormat & 0xff) == 8) { - if (m_DestFormat & 0x0200) { - CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - src_left, width, clip_scan, dst_extra_alpha); - } else { - CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - src_left, width, clip_scan); - } - } else if (m_bRgbByteOrder) { - if (m_DestFormat == FXDIB_Argb) { - CompositeRow_BitMask2Argb_RgbByteOrder( - dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, - src_left, width, m_BlendType, clip_scan); - } else { - CompositeRow_BitMask2Rgb_RgbByteOrder( - dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, - src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); - } - return; - } else if (m_DestFormat == FXDIB_Argb) { - CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, - m_MaskGreen, m_MaskBlue, src_left, width, - m_BlendType, clip_scan); - } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) { - CompositeRow_BitMask2Rgb( - dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, - src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan); - } -} - -bool CFX_DIBitmap::CompositeBitmap(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top, - int blend_type, - const CFX_ClipRgn* pClipRgn, - bool bRgbByteOrder, - void* pIccTransform) { - if (!m_pBuffer) { - return false; - } - ASSERT(!pSrcBitmap->IsAlphaMask()); - ASSERT(m_bpp >= 8); - if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) { - return false; - } - GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), - pSrcBitmap->GetHeight(), src_left, src_top, pClipRgn); - if (width == 0 || height == 0) { - return true; - } - const CFX_DIBitmap* pClipMask = nullptr; - FX_RECT clip_box; - if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { - ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); - pClipMask = pClipRgn->GetMask().GetObject(); - clip_box = pClipRgn->GetBox(); - } - CFX_ScanlineCompositor compositor; - if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, - pSrcBitmap->GetPalette(), 0, blend_type, - pClipMask != nullptr, bRgbByteOrder, 0, pIccTransform)) { - return false; - } - int dest_Bpp = m_bpp / 8; - int src_Bpp = pSrcBitmap->GetBPP() / 8; - bool bRgb = src_Bpp > 1 && !pSrcBitmap->IsCmykImage(); - CFX_DIBitmap* pSrcAlphaMask = pSrcBitmap->m_pAlphaMask; - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = - m_pBuffer + (dest_top + row) * m_Pitch + dest_left * dest_Bpp; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp; - const uint8_t* src_scan_extra_alpha = - pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left - : nullptr; - uint8_t* dst_scan_extra_alpha = - m_pAlphaMask - ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left - : nullptr; - const uint8_t* clip_scan = nullptr; - if (pClipMask) { - clip_scan = pClipMask->m_pBuffer + - (dest_top + row - clip_box.top) * pClipMask->m_Pitch + - (dest_left - clip_box.left); - } - if (bRgb) { - compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, - src_scan_extra_alpha, - dst_scan_extra_alpha); - } else { - compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, - clip_scan, src_scan_extra_alpha, - dst_scan_extra_alpha); - } - } - return true; -} - -bool CFX_DIBitmap::CompositeMask(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pMask, - uint32_t color, - int src_left, - int src_top, - int blend_type, - const CFX_ClipRgn* pClipRgn, - bool bRgbByteOrder, - int alpha_flag, - void* pIccTransform) { - if (!m_pBuffer) { - return false; - } - ASSERT(pMask->IsAlphaMask()); - ASSERT(m_bpp >= 8); - if (!pMask->IsAlphaMask() || m_bpp < 8) { - return false; - } - GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), - pMask->GetHeight(), src_left, src_top, pClipRgn); - if (width == 0 || height == 0) { - return true; - } - int src_alpha = - (uint8_t)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); - if (src_alpha == 0) { - return true; - } - const CFX_DIBitmap* pClipMask = nullptr; - FX_RECT clip_box; - if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { - ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); - pClipMask = pClipRgn->GetMask().GetObject(); - clip_box = pClipRgn->GetBox(); - } - int src_bpp = pMask->GetBPP(); - int Bpp = GetBPP() / 8; - CFX_ScanlineCompositor compositor; - if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, nullptr, color, - blend_type, pClipMask != nullptr, bRgbByteOrder, - alpha_flag, pIccTransform)) { - return false; - } - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = - m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp; - const uint8_t* src_scan = pMask->GetScanline(src_top + row); - uint8_t* dst_scan_extra_alpha = - m_pAlphaMask - ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left - : nullptr; - const uint8_t* clip_scan = nullptr; - if (pClipMask) { - clip_scan = pClipMask->m_pBuffer + - (dest_top + row - clip_box.top) * pClipMask->m_Pitch + - (dest_left - clip_box.left); - } - if (src_bpp == 1) { - compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, - clip_scan, dst_scan_extra_alpha); - } else { - compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, - clip_scan, dst_scan_extra_alpha); - } - } - return true; -} - -bool CFX_DIBitmap::CompositeRect(int left, - int top, - int width, - int height, - uint32_t color, - int alpha_flag, - void* pIccTransform) { - if (!m_pBuffer) { - return false; - } - int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); - if (src_alpha == 0) { - return true; - } - FX_RECT rect(left, top, left + width, top + height); - rect.Intersect(0, 0, m_Width, m_Height); - if (rect.IsEmpty()) { - return true; - } - width = rect.Width(); - uint32_t dst_color; - if (alpha_flag >> 8) { - dst_color = FXCMYK_TODIB(color); - } else { - dst_color = FXARGB_TODIB(color); - } - uint8_t* color_p = (uint8_t*)&dst_color; - if (m_bpp == 8) { - uint8_t gray = 255; - if (!IsAlphaMask()) { - if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && - CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - pIccModule->TranslateScanline(pIccTransform, &gray, color_p, 1); - } else { - if (alpha_flag >> 8) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3], r, - g, b); - gray = FXRGB2GRAY(r, g, b); - } else { - gray = (uint8_t)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]); - } - } - if (IsCmykImage()) { - gray = ~gray; - } - } - for (int row = rect.top; row < rect.bottom; row++) { - uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left; - if (src_alpha == 255) { - FXSYS_memset(dest_scan, gray, width); - } else { - for (int col = 0; col < width; col++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); - dest_scan++; - } - } - } - return true; - } - if (m_bpp == 1) { - ASSERT(!IsCmykImage() && (uint8_t)(alpha_flag >> 8) == 0); - int left_shift = rect.left % 8; - int right_shift = rect.right % 8; - int new_width = rect.right / 8 - rect.left / 8; - int index = 0; - if (m_pPalette) { - for (int i = 0; i < 2; i++) { - if (m_pPalette.get()[i] == color) { - index = i; - } - } - } else { - index = ((uint8_t)color == 0xff) ? 1 : 0; - } - for (int row = rect.top; row < rect.bottom; row++) { - uint8_t* dest_scan_top = (uint8_t*)GetScanline(row) + rect.left / 8; - uint8_t* dest_scan_top_r = (uint8_t*)GetScanline(row) + rect.right / 8; - uint8_t left_flag = *dest_scan_top & (255 << (8 - left_shift)); - uint8_t right_flag = *dest_scan_top_r & (255 >> right_shift); - if (new_width) { - FXSYS_memset(dest_scan_top + 1, index ? 255 : 0, new_width - 1); - if (!index) { - *dest_scan_top &= left_flag; - *dest_scan_top_r &= right_flag; - } else { - *dest_scan_top |= ~left_flag; - *dest_scan_top_r |= ~right_flag; - } - } else { - if (!index) { - *dest_scan_top &= left_flag | right_flag; - } else { - *dest_scan_top |= ~(left_flag | right_flag); - } - } - } - return true; - } - ASSERT(m_bpp >= 24); - if (m_bpp < 24) { - return false; - } - if (pIccTransform && CFX_GEModule::Get()->GetCodecModule()) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1); - } else { - if (alpha_flag >> 8 && !IsCmykImage()) { - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), - color_p[2], color_p[1], color_p[0]); - } else if (!(alpha_flag >> 8) && IsCmykImage()) { - return false; - } - } - if (!IsCmykImage()) { - color_p[3] = (uint8_t)src_alpha; - } - int Bpp = m_bpp / 8; - bool bAlpha = HasAlpha(); - bool bArgb = GetFormat() == FXDIB_Argb; - if (src_alpha == 255) { - for (int row = rect.top; row < rect.bottom; row++) { - uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp; - uint8_t* dest_scan_alpha = - m_pAlphaMask ? (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left - : nullptr; - if (dest_scan_alpha) { - FXSYS_memset(dest_scan_alpha, 0xff, width); - } - if (Bpp == 4) { - uint32_t* scan = (uint32_t*)dest_scan; - for (int col = 0; col < width; col++) { - *scan++ = dst_color; - } - } else { - for (int col = 0; col < width; col++) { - *dest_scan++ = color_p[0]; - *dest_scan++ = color_p[1]; - *dest_scan++ = color_p[2]; - } - } - } - return true; - } - for (int row = rect.top; row < rect.bottom; row++) { - uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp; - if (bAlpha) { - if (bArgb) { - for (int col = 0; col < width; col++) { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], - color_p[1], color_p[0])); - dest_scan += 4; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio); - dest_scan++; - *dest_scan++ = dest_alpha; - } - } else { - uint8_t* dest_scan_alpha = - (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left; - for (int col = 0; col < width; col++) { - uint8_t back_alpha = *dest_scan_alpha; - if (back_alpha == 0) { - *dest_scan_alpha++ = src_alpha; - FXSYS_memcpy(dest_scan, color_p, Bpp); - dest_scan += Bpp; - continue; - } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - *dest_scan_alpha++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - for (int comps = 0; comps < Bpp; comps++) { - *dest_scan = - FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio); - dest_scan++; - } - } - } - } else { - for (int col = 0; col < width; col++) { - for (int comps = 0; comps < Bpp; comps++) { - if (comps == 3) { - *dest_scan++ = 255; - continue; - } - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha); - dest_scan++; - } - } - } - } - return true; -} - -CFX_BitmapComposer::CFX_BitmapComposer() { - m_pScanlineV = nullptr; - m_pScanlineAlphaV = nullptr; - m_pClipScanV = nullptr; - m_pAddClipScan = nullptr; - m_bRgbByteOrder = false; - m_BlendType = FXDIB_BLEND_NORMAL; -} - -CFX_BitmapComposer::~CFX_BitmapComposer() { - FX_Free(m_pScanlineV); - FX_Free(m_pScanlineAlphaV); - FX_Free(m_pClipScanV); - FX_Free(m_pAddClipScan); -} - -void CFX_BitmapComposer::Compose(CFX_DIBitmap* pDest, - const CFX_ClipRgn* pClipRgn, - int bitmap_alpha, - uint32_t mask_color, - FX_RECT& dest_rect, - bool bVertical, - bool bFlipX, - bool bFlipY, - bool bRgbByteOrder, - int alpha_flag, - void* pIccTransform, - int blend_type) { - m_pBitmap = pDest; - m_pClipRgn = pClipRgn; - m_DestLeft = dest_rect.left; - m_DestTop = dest_rect.top; - m_DestWidth = dest_rect.Width(); - m_DestHeight = dest_rect.Height(); - m_BitmapAlpha = bitmap_alpha; - m_MaskColor = mask_color; - m_pClipMask = nullptr; - if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { - m_pClipMask = pClipRgn->GetMask().GetObject(); - } - m_bVertical = bVertical; - m_bFlipX = bFlipX; - m_bFlipY = bFlipY; - m_AlphaFlag = alpha_flag; - m_pIccTransform = pIccTransform; - m_bRgbByteOrder = bRgbByteOrder; - m_BlendType = blend_type; -} -bool CFX_BitmapComposer::SetInfo(int width, - int height, - FXDIB_Format src_format, - uint32_t* pSrcPalette) { - m_SrcFormat = src_format; - if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, - m_MaskColor, FXDIB_BLEND_NORMAL, - m_pClipMask != nullptr || (m_BitmapAlpha < 255), - m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) { - return false; - } - if (m_bVertical) { - m_pScanlineV = FX_Alloc(uint8_t, m_pBitmap->GetBPP() / 8 * width + 4); - m_pClipScanV = FX_Alloc(uint8_t, m_pBitmap->GetHeight()); - if (m_pBitmap->m_pAlphaMask) { - m_pScanlineAlphaV = FX_Alloc(uint8_t, width + 4); - } - } - if (m_BitmapAlpha < 255) { - m_pAddClipScan = FX_Alloc( - uint8_t, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth()); - } - return true; -} - -void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan, - const uint8_t* src_scan, - int dest_width, - const uint8_t* clip_scan, - const uint8_t* src_extra_alpha, - uint8_t* dst_extra_alpha) { - if (m_BitmapAlpha < 255) { - if (clip_scan) { - for (int i = 0; i < dest_width; i++) { - m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255; - } - } else { - FXSYS_memset(m_pAddClipScan, m_BitmapAlpha, dest_width); - } - clip_scan = m_pAddClipScan; - } - if (m_SrcFormat == FXDIB_8bppMask) { - m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, - clip_scan, dst_extra_alpha); - } else if ((m_SrcFormat & 0xff) == 8) { - m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, - clip_scan, src_extra_alpha, - dst_extra_alpha); - } else { - m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, - clip_scan, src_extra_alpha, - dst_extra_alpha); - } -} - -void CFX_BitmapComposer::ComposeScanline(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha) { - if (m_bVertical) { - ComposeScanlineV(line, scanline, scan_extra_alpha); - return; - } - const uint8_t* clip_scan = nullptr; - if (m_pClipMask) - clip_scan = m_pClipMask->GetBuffer() + - (m_DestTop + line - m_pClipRgn->GetBox().top) * - m_pClipMask->GetPitch() + - (m_DestLeft - m_pClipRgn->GetBox().left); - uint8_t* dest_scan = (uint8_t*)m_pBitmap->GetScanline(line + m_DestTop) + - m_DestLeft * m_pBitmap->GetBPP() / 8; - uint8_t* dest_alpha_scan = - m_pBitmap->m_pAlphaMask - ? (uint8_t*)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) + - m_DestLeft - : nullptr; - DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, - dest_alpha_scan); -} - -void CFX_BitmapComposer::ComposeScanlineV(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha) { - int i; - int Bpp = m_pBitmap->GetBPP() / 8; - int dest_pitch = m_pBitmap->GetPitch(); - int dest_alpha_pitch = - m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0; - int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line); - uint8_t* dest_buf = - m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch; - uint8_t* dest_alpha_buf = m_pBitmap->m_pAlphaMask - ? m_pBitmap->m_pAlphaMask->GetBuffer() + - dest_x + m_DestTop * dest_alpha_pitch - : nullptr; - if (m_bFlipY) { - dest_buf += dest_pitch * (m_DestHeight - 1); - dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1); - } - int y_step = dest_pitch; - int y_alpha_step = dest_alpha_pitch; - if (m_bFlipY) { - y_step = -y_step; - y_alpha_step = -y_alpha_step; - } - uint8_t* src_scan = m_pScanlineV; - uint8_t* dest_scan = dest_buf; - for (i = 0; i < m_DestHeight; i++) { - for (int j = 0; j < Bpp; j++) { - *src_scan++ = dest_scan[j]; - } - dest_scan += y_step; - } - uint8_t* src_alpha_scan = m_pScanlineAlphaV; - uint8_t* dest_alpha_scan = dest_alpha_buf; - if (dest_alpha_scan) { - for (i = 0; i < m_DestHeight; i++) { - *src_alpha_scan++ = *dest_alpha_scan; - dest_alpha_scan += y_alpha_step; - } - } - uint8_t* clip_scan = nullptr; - if (m_pClipMask) { - clip_scan = m_pClipScanV; - int clip_pitch = m_pClipMask->GetPitch(); - const uint8_t* src_clip = - m_pClipMask->GetBuffer() + - (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch + - (dest_x - m_pClipRgn->GetBox().left); - if (m_bFlipY) { - src_clip += clip_pitch * (m_DestHeight - 1); - clip_pitch = -clip_pitch; - } - for (i = 0; i < m_DestHeight; i++) { - clip_scan[i] = *src_clip; - src_clip += clip_pitch; - } - } - DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha, - m_pScanlineAlphaV); - src_scan = m_pScanlineV; - dest_scan = dest_buf; - for (i = 0; i < m_DestHeight; i++) { - for (int j = 0; j < Bpp; j++) { - dest_scan[j] = *src_scan++; - } - dest_scan += y_step; - } - src_alpha_scan = m_pScanlineAlphaV; - dest_alpha_scan = dest_alpha_buf; - if (dest_alpha_scan) { - for (i = 0; i < m_DestHeight; i++) { - *dest_alpha_scan = *src_alpha_scan++; - dest_alpha_scan += y_alpha_step; - } - } -} diff --git a/core/fxge/dib/fx_dib_convert.cpp b/core/fxge/dib/fx_dib_convert.cpp deleted file mode 100644 index aad3f343e209a538f78a58504681536748f6f8b3..0000000000000000000000000000000000000000 --- a/core/fxge/dib/fx_dib_convert.cpp +++ /dev/null @@ -1,911 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include - -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" -#include "core/fxge/fx_dib.h" -#include "third_party/base/ptr_util.h" - -class CFX_Palette { - public: - CFX_Palette(); - ~CFX_Palette(); - - bool BuildPalette(const CFX_DIBSource* pBitmap); - uint32_t* GetPalette() const { return m_pPalette; } - uint32_t* GetColorLut() const { return m_cLut; } - uint32_t* GetAmountLut() const { return m_aLut; } - int32_t Getlut() const { return m_lut; } - - protected: - uint32_t* m_pPalette; - uint32_t* m_cLut; - uint32_t* m_aLut; - int m_lut; -}; -int _Partition(uint32_t* alut, uint32_t* clut, int l, int r) { - uint32_t p_a = alut[l]; - uint32_t p_c = clut[l]; - while (l < r) { - while (l < r && alut[r] >= p_a) { - r--; - } - if (l < r) { - alut[l] = alut[r]; - clut[l++] = clut[r]; - } - while (l < r && alut[l] <= p_a) { - l++; - } - if (l < r) { - alut[r] = alut[l]; - clut[r--] = clut[l]; - } - } - alut[l] = p_a; - clut[l] = p_c; - return l; -} - -void _Qsort(uint32_t* alut, uint32_t* clut, int l, int r) { - if (l < r) { - int pI = _Partition(alut, clut, l, r); - _Qsort(alut, clut, l, pI - 1); - _Qsort(alut, clut, pI + 1, r); - } -} - -void _ColorDecode(uint32_t pal_v, uint8_t& r, uint8_t& g, uint8_t& b) { - r = (uint8_t)((pal_v & 0xf00) >> 4); - g = (uint8_t)(pal_v & 0x0f0); - b = (uint8_t)((pal_v & 0x00f) << 4); -} - -void _Obtain_Pal(uint32_t* aLut, - uint32_t* cLut, - uint32_t* dest_pal, - uint32_t lut) { - uint32_t lut_1 = lut - 1; - for (int row = 0; row < 256; row++) { - int lut_offset = lut_1 - row; - if (lut_offset < 0) { - lut_offset += 256; - } - uint32_t color = cLut[lut_offset]; - uint8_t r; - uint8_t g; - uint8_t b; - _ColorDecode(color, r, g, b); - dest_pal[row] = ((uint32_t)r << 16) | ((uint32_t)g << 8) | b | 0xff000000; - aLut[lut_offset] = row; - } -} - -CFX_Palette::CFX_Palette() { - m_pPalette = nullptr; - m_cLut = nullptr; - m_aLut = nullptr; - m_lut = 0; -} - -CFX_Palette::~CFX_Palette() { - FX_Free(m_pPalette); - FX_Free(m_cLut); - FX_Free(m_aLut); - m_lut = 0; -} - -bool CFX_Palette::BuildPalette(const CFX_DIBSource* pBitmap) { - if (!pBitmap) { - return false; - } - FX_Free(m_pPalette); - m_pPalette = FX_Alloc(uint32_t, 256); - int bpp = pBitmap->GetBPP() / 8; - int width = pBitmap->GetWidth(); - int height = pBitmap->GetHeight(); - FX_Free(m_cLut); - m_cLut = nullptr; - FX_Free(m_aLut); - m_aLut = nullptr; - m_cLut = FX_Alloc(uint32_t, 4096); - m_aLut = FX_Alloc(uint32_t, 4096); - int row, col; - m_lut = 0; - for (row = 0; row < height; row++) { - uint8_t* scan_line = (uint8_t*)pBitmap->GetScanline(row); - for (col = 0; col < width; col++) { - uint8_t* src_port = scan_line + col * bpp; - uint32_t b = src_port[0] & 0xf0; - uint32_t g = src_port[1] & 0xf0; - uint32_t r = src_port[2] & 0xf0; - uint32_t index = (r << 4) + g + (b >> 4); - m_aLut[index]++; - } - } - for (row = 0; row < 4096; row++) { - if (m_aLut[row] != 0) { - m_aLut[m_lut] = m_aLut[row]; - m_cLut[m_lut] = row; - m_lut++; - } - } - _Qsort(m_aLut, m_cLut, 0, m_lut - 1); - _Obtain_Pal(m_aLut, m_cLut, m_pPalette, m_lut); - return true; -} - -bool ConvertBuffer_1bppMask2Gray(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - uint8_t set_gray, reset_gray; - set_gray = 0xff; - reset_gray = 0x00; - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - FXSYS_memset(dest_scan, reset_gray, width); - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); - for (int col = src_left; col < src_left + width; col++) { - if (src_scan[col / 8] & (1 << (7 - col % 8))) { - *dest_scan = set_gray; - } - dest_scan++; - } - } - return true; -} - -bool ConvertBuffer_8bppMask2Gray(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; - FXSYS_memcpy(dest_scan, src_scan, width); - } - return true; -} - -bool ConvertBuffer_1bppPlt2Gray(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - uint32_t* src_plt = pSrcBitmap->GetPalette(); - uint8_t gray[2]; - uint8_t reset_r; - uint8_t reset_g; - uint8_t reset_b; - uint8_t set_r; - uint8_t set_g; - uint8_t set_b; - if (pSrcBitmap->IsCmykImage()) { - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]), - FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]), - reset_r, reset_g, reset_b); - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]), - FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]), - set_r, set_g, set_b); - } else { - reset_r = FXARGB_R(src_plt[0]); - reset_g = FXARGB_G(src_plt[0]); - reset_b = FXARGB_B(src_plt[0]); - set_r = FXARGB_R(src_plt[1]); - set_g = FXARGB_G(src_plt[1]); - set_b = FXARGB_B(src_plt[1]); - } - gray[0] = FXRGB2GRAY(reset_r, reset_g, reset_b); - gray[1] = FXRGB2GRAY(set_r, set_g, set_b); - - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - FXSYS_memset(dest_scan, gray[0], width); - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); - for (int col = src_left; col < src_left + width; col++) { - if (src_scan[col / 8] & (1 << (7 - col % 8))) { - *dest_scan = gray[1]; - } - dest_scan++; - } - } - return true; -} - -bool ConvertBuffer_8bppPlt2Gray(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - uint32_t* src_plt = pSrcBitmap->GetPalette(); - uint8_t gray[256]; - if (pSrcBitmap->IsCmykImage()) { - uint8_t r; - uint8_t g; - uint8_t b; - for (size_t i = 0; i < FX_ArraySize(gray); i++) { - AdobeCMYK_to_sRGB1( - FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]), - FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), r, g, b); - gray[i] = FXRGB2GRAY(r, g, b); - } - } else { - for (size_t i = 0; i < FX_ArraySize(gray); i++) { - gray[i] = FXRGB2GRAY(FXARGB_R(src_plt[i]), FXARGB_G(src_plt[i]), - FXARGB_B(src_plt[i])); - } - } - - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; - for (int col = 0; col < width; col++) { - *dest_scan++ = gray[*src_scan++]; - } - } - return true; -} - -bool ConvertBuffer_RgbOrCmyk2Gray(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - int Bpp = pSrcBitmap->GetBPP() / 8; - if (pSrcBitmap->IsCmykImage()) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * 4; - for (int col = 0; col < width; col++) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue((uint32_t)src_scan[0]), - FXSYS_GetMValue((uint32_t)src_scan[1]), - FXSYS_GetYValue((uint32_t)src_scan[2]), - FXSYS_GetKValue((uint32_t)src_scan[3]), r, g, b); - *dest_scan++ = FXRGB2GRAY(r, g, b); - src_scan += 4; - } - } - } else { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; - for (int col = 0; col < width; col++) { - *dest_scan++ = FXRGB2GRAY(src_scan[2], src_scan[1], src_scan[0]); - src_scan += Bpp; - } - } - } - return true; -} - -void ConvertBuffer_IndexCopy(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - if (pSrcBitmap->GetBPP() == 1) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - FXSYS_memset(dest_scan, 0, width); - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); - for (int col = src_left; col < src_left + width; col++) { - if (src_scan[col / 8] & (1 << (7 - col % 8))) { - *dest_scan = 1; - } - dest_scan++; - } - } - } else { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left; - FXSYS_memcpy(dest_scan, src_scan, width); - } - } -} - -bool ConvertBuffer_Plt2PltRgb8(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top, - uint32_t* dst_plt) { - ConvertBuffer_IndexCopy(dest_buf, dest_pitch, width, height, pSrcBitmap, - src_left, src_top); - uint32_t* src_plt = pSrcBitmap->GetPalette(); - int plt_size = pSrcBitmap->GetPaletteSize(); - if (pSrcBitmap->IsCmykImage()) { - for (int i = 0; i < plt_size; i++) { - uint8_t r; - uint8_t g; - uint8_t b; - AdobeCMYK_to_sRGB1( - FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]), - FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), r, g, b); - dst_plt[i] = FXARGB_MAKE(0xff, r, g, b); - } - } else { - FXSYS_memcpy(dst_plt, src_plt, plt_size * 4); - } - return true; -} - -bool ConvertBuffer_Rgb2PltRgb8(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top, - uint32_t* dst_plt) { - int bpp = pSrcBitmap->GetBPP() / 8; - CFX_Palette palette; - palette.BuildPalette(pSrcBitmap); - uint32_t* cLut = palette.GetColorLut(); - uint32_t* aLut = palette.GetAmountLut(); - if (!cLut || !aLut) { - return false; - } - int lut = palette.Getlut(); - uint32_t* pPalette = palette.GetPalette(); - if (lut > 256) { - int err, min_err; - int lut_256 = lut - 256; - for (int row = 0; row < lut_256; row++) { - min_err = 1000000; - uint8_t r, g, b; - _ColorDecode(cLut[row], r, g, b); - int clrindex = 0; - for (int col = 0; col < 256; col++) { - uint32_t p_color = *(pPalette + col); - int d_r = r - (uint8_t)(p_color >> 16); - int d_g = g - (uint8_t)(p_color >> 8); - int d_b = b - (uint8_t)(p_color); - err = d_r * d_r + d_g * d_g + d_b * d_b; - if (err < min_err) { - min_err = err; - clrindex = col; - } - } - aLut[row] = clrindex; - } - } - int32_t lut_1 = lut - 1; - for (int row = 0; row < height; row++) { - uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left; - uint8_t* dest_scan = dest_buf + row * dest_pitch; - for (int col = 0; col < width; col++) { - uint8_t* src_port = src_scan + col * bpp; - int r = src_port[2] & 0xf0; - int g = src_port[1] & 0xf0; - int b = src_port[0] & 0xf0; - uint32_t clrindex = (r << 4) + g + (b >> 4); - for (int i = lut_1; i >= 0; i--) - if (clrindex == cLut[i]) { - *(dest_scan + col) = (uint8_t)(aLut[i]); - break; - } - } - } - FXSYS_memcpy(dst_plt, pPalette, sizeof(uint32_t) * 256); - return true; -} - -bool ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format, - uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - int comps = (dst_format & 0xff) / 8; - uint8_t set_gray, reset_gray; - set_gray = 0xff; - reset_gray = 0x00; - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); - for (int col = src_left; col < src_left + width; col++) { - if (src_scan[col / 8] & (1 << (7 - col % 8))) { - dest_scan[0] = set_gray; - dest_scan[1] = set_gray; - dest_scan[2] = set_gray; - } else { - dest_scan[0] = reset_gray; - dest_scan[1] = reset_gray; - dest_scan[2] = reset_gray; - } - dest_scan += comps; - } - } - return true; -} - -bool ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format, - uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - int comps = (dst_format & 0xff) / 8; - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; - uint8_t src_pixel; - for (int col = 0; col < width; col++) { - src_pixel = *src_scan++; - *dest_scan++ = src_pixel; - *dest_scan++ = src_pixel; - *dest_scan = src_pixel; - dest_scan += comps - 2; - } - } - return true; -} - -bool ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format, - uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - int comps = (dst_format & 0xff) / 8; - uint32_t* src_plt = pSrcBitmap->GetPalette(); - uint32_t plt[2]; - uint8_t* bgr_ptr = (uint8_t*)plt; - if (pSrcBitmap->IsCmykImage()) { - plt[0] = FXCMYK_TODIB(src_plt[0]); - plt[1] = FXCMYK_TODIB(src_plt[1]); - } else { - bgr_ptr[0] = FXARGB_B(src_plt[0]); - bgr_ptr[1] = FXARGB_G(src_plt[0]); - bgr_ptr[2] = FXARGB_R(src_plt[0]); - bgr_ptr[3] = FXARGB_B(src_plt[1]); - bgr_ptr[4] = FXARGB_G(src_plt[1]); - bgr_ptr[5] = FXARGB_R(src_plt[1]); - } - - if (pSrcBitmap->IsCmykImage()) { - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]), - FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]), - bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]); - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]), - FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]), - bgr_ptr[5], bgr_ptr[4], bgr_ptr[3]); - } - - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); - for (int col = src_left; col < src_left + width; col++) { - if (src_scan[col / 8] & (1 << (7 - col % 8))) { - *dest_scan++ = bgr_ptr[3]; - *dest_scan++ = bgr_ptr[4]; - *dest_scan = bgr_ptr[5]; - } else { - *dest_scan++ = bgr_ptr[0]; - *dest_scan++ = bgr_ptr[1]; - *dest_scan = bgr_ptr[2]; - } - dest_scan += comps - 2; - } - } - return true; -} - -bool ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format, - uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - int comps = (dst_format & 0xff) / 8; - uint32_t* src_plt = pSrcBitmap->GetPalette(); - uint32_t plt[256]; - uint8_t* bgr_ptr = (uint8_t*)plt; - if (!pSrcBitmap->IsCmykImage()) { - for (int i = 0; i < 256; i++) { - *bgr_ptr++ = FXARGB_B(src_plt[i]); - *bgr_ptr++ = FXARGB_G(src_plt[i]); - *bgr_ptr++ = FXARGB_R(src_plt[i]); - } - bgr_ptr = (uint8_t*)plt; - } - - if (pSrcBitmap->IsCmykImage()) { - for (int i = 0; i < 256; i++) { - AdobeCMYK_to_sRGB1( - FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]), - FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), bgr_ptr[2], - bgr_ptr[1], bgr_ptr[0]); - bgr_ptr += 3; - } - bgr_ptr = (uint8_t*)plt; - } - - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left; - for (int col = 0; col < width; col++) { - uint8_t* src_pixel = bgr_ptr + 3 * (*src_scan++); - *dest_scan++ = *src_pixel++; - *dest_scan++ = *src_pixel++; - *dest_scan = *src_pixel++; - dest_scan += comps - 2; - } - } - return true; -} - -bool ConvertBuffer_24bppRgb2Rgb24(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * 3; - FXSYS_memcpy(dest_scan, src_scan, width * 3); - } - return true; -} - -bool ConvertBuffer_32bppRgb2Rgb24(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * 4; - for (int col = 0; col < width; col++) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - src_scan++; - } - } - return true; -} - -bool ConvertBuffer_Rgb2Rgb32(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - int comps = pSrcBitmap->GetBPP() / 8; - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * comps; - for (int col = 0; col < width; col++) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - dest_scan++; - src_scan += comps - 3; - } - } - return true; -} - -bool ConvertBuffer_32bppCmyk2Rgb32(uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * dest_pitch; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * 4; - for (int col = 0; col < width; col++) { - AdobeCMYK_to_sRGB1(src_scan[0], src_scan[1], src_scan[2], src_scan[3], - dest_scan[2], dest_scan[1], dest_scan[0]); - dest_scan += 4; - src_scan += 4; - } - } - return true; -} - -bool ConvertBuffer(FXDIB_Format dest_format, - uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top, - std::unique_ptr* p_pal) { - FXDIB_Format src_format = pSrcBitmap->GetFormat(); - switch (dest_format) { - case FXDIB_Invalid: - case FXDIB_1bppCmyk: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - ASSERT(false); - return false; - case FXDIB_8bppMask: { - if ((src_format & 0xff) == 1) { - if (pSrcBitmap->GetPalette()) { - return ConvertBuffer_1bppPlt2Gray(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - return ConvertBuffer_1bppMask2Gray(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - if ((src_format & 0xff) == 8) { - if (pSrcBitmap->GetPalette()) { - return ConvertBuffer_8bppPlt2Gray(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - return ConvertBuffer_8bppMask2Gray(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - if ((src_format & 0xff) >= 24) { - return ConvertBuffer_RgbOrCmyk2Gray(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - return false; - } - case FXDIB_8bppRgb: - case FXDIB_8bppRgba: { - if ((src_format & 0xff) == 8 && !pSrcBitmap->GetPalette()) { - return ConvertBuffer(FXDIB_8bppMask, dest_buf, dest_pitch, width, - height, pSrcBitmap, src_left, src_top, p_pal); - } - p_pal->reset(FX_Alloc(uint32_t, 256)); - if (((src_format & 0xff) == 1 || (src_format & 0xff) == 8) && - pSrcBitmap->GetPalette()) { - return ConvertBuffer_Plt2PltRgb8(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top, - p_pal->get()); - } - if ((src_format & 0xff) >= 24) { - return ConvertBuffer_Rgb2PltRgb8(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top, - p_pal->get()); - } - return false; - } - case FXDIB_Rgb: - case FXDIB_Rgba: { - if ((src_format & 0xff) == 1) { - if (pSrcBitmap->GetPalette()) { - return ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - return ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - if ((src_format & 0xff) == 8) { - if (pSrcBitmap->GetPalette()) { - return ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - return ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - if ((src_format & 0xff) == 24) { - return ConvertBuffer_24bppRgb2Rgb24(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - if ((src_format & 0xff) == 32) { - return ConvertBuffer_32bppRgb2Rgb24(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - return false; - } - case FXDIB_Argb: - case FXDIB_Rgb32: { - if ((src_format & 0xff) == 1) { - if (pSrcBitmap->GetPalette()) { - return ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - return ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - if ((src_format & 0xff) == 8) { - if (pSrcBitmap->GetPalette()) { - return ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - return ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch, - width, height, pSrcBitmap, src_left, - src_top); - } - if ((src_format & 0xff) >= 24) { - if (src_format & 0x0400) { - return ConvertBuffer_32bppCmyk2Rgb32(dest_buf, dest_pitch, width, - height, pSrcBitmap, src_left, - src_top); - } - return ConvertBuffer_Rgb2Rgb32(dest_buf, dest_pitch, width, height, - pSrcBitmap, src_left, src_top); - } - return false; - } - default: - return false; - } -} - -std::unique_ptr CFX_DIBSource::CloneConvert( - FXDIB_Format dest_format) const { - if (dest_format == GetFormat()) - return Clone(nullptr); - - std::unique_ptr pClone = pdfium::MakeUnique(); - if (!pClone->Create(m_Width, m_Height, dest_format)) - return nullptr; - - CFX_MaybeOwned pSrcAlpha; - if (HasAlpha()) { - if (GetFormat() == FXDIB_Argb) - pSrcAlpha = CloneAlphaMask(); - else - pSrcAlpha = m_pAlphaMask; - - if (!pSrcAlpha) - return nullptr; - } - bool ret = true; - if (dest_format & 0x0200) { - if (dest_format == FXDIB_Argb) { - ret = pSrcAlpha - ? pClone->LoadChannel(FXDIB_Alpha, pSrcAlpha.Get(), FXDIB_Alpha) - : pClone->LoadChannel(FXDIB_Alpha, 0xff); - } else { - ret = pClone->SetAlphaMask(pSrcAlpha.Get()); - } - } - if (!ret) - return nullptr; - - std::unique_ptr pal_8bpp; - if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(), - m_Width, m_Height, this, 0, 0, &pal_8bpp)) { - return nullptr; - } - if (pal_8bpp) - pClone->SetPalette(pal_8bpp.get()); - - return pClone; -} - -bool CFX_DIBitmap::ConvertFormat(FXDIB_Format dest_format) { - FXDIB_Format src_format = GetFormat(); - if (dest_format == src_format) - return true; - - if (dest_format == FXDIB_8bppMask && src_format == FXDIB_8bppRgb && - !m_pPalette) { - m_AlphaFlag = 1; - return true; - } - if (dest_format == FXDIB_Argb && src_format == FXDIB_Rgb32) { - m_AlphaFlag = 2; - for (int row = 0; row < m_Height; row++) { - uint8_t* scanline = m_pBuffer + row * m_Pitch + 3; - for (int col = 0; col < m_Width; col++) { - *scanline = 0xff; - scanline += 4; - } - } - return true; - } - int dest_bpp = dest_format & 0xff; - int dest_pitch = (dest_bpp * m_Width + 31) / 32 * 4; - uint8_t* dest_buf = FX_TryAlloc(uint8_t, dest_pitch * m_Height + 4); - if (!dest_buf) { - return false; - } - CFX_DIBitmap* pAlphaMask = nullptr; - if (dest_format == FXDIB_Argb) { - FXSYS_memset(dest_buf, 0xff, dest_pitch * m_Height + 4); - if (m_pAlphaMask) { - for (int row = 0; row < m_Height; row++) { - uint8_t* pDstScanline = dest_buf + row * dest_pitch + 3; - const uint8_t* pSrcScanline = m_pAlphaMask->GetScanline(row); - for (int col = 0; col < m_Width; col++) { - *pDstScanline = *pSrcScanline++; - pDstScanline += 4; - } - } - } - } else if (dest_format & 0x0200) { - if (src_format == FXDIB_Argb) { - pAlphaMask = CloneAlphaMask().release(); - if (!pAlphaMask) { - FX_Free(dest_buf); - return false; - } - } else { - if (!m_pAlphaMask) { - if (!BuildAlphaMask()) { - FX_Free(dest_buf); - return false; - } - pAlphaMask = m_pAlphaMask; - m_pAlphaMask = nullptr; - } else { - pAlphaMask = m_pAlphaMask; - } - } - } - bool ret = false; - std::unique_ptr pal_8bpp; - ret = ConvertBuffer(dest_format, dest_buf, dest_pitch, m_Width, m_Height, - this, 0, 0, &pal_8bpp); - if (!ret) { - if (pAlphaMask != m_pAlphaMask) - delete pAlphaMask; - FX_Free(dest_buf); - return false; - } - if (m_pAlphaMask && pAlphaMask != m_pAlphaMask) - delete m_pAlphaMask; - m_pAlphaMask = pAlphaMask; - m_pPalette = std::move(pal_8bpp); - if (!m_bExtBuf) - FX_Free(m_pBuffer); - m_bExtBuf = false; - m_pBuffer = dest_buf; - m_bpp = (uint8_t)dest_format; - m_AlphaFlag = (uint8_t)(dest_format >> 8); - m_Pitch = dest_pitch; - return true; -} diff --git a/core/fxge/dib/fx_dib_engine.cpp b/core/fxge/dib/fx_dib_engine.cpp deleted file mode 100644 index c004aac538d715d37eae929be0b10c29abd7055c..0000000000000000000000000000000000000000 --- a/core/fxge/dib/fx_dib_engine.cpp +++ /dev/null @@ -1,1007 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include - -#include "core/fxge/dib/dib_int.h" -#include "core/fxge/fx_dib.h" -#include "third_party/base/ptr_util.h" - -namespace { - -bool SourceSizeWithinLimit(int width, int height) { - const int kMaxProgressiveStretchPixels = 1000000; - return !height || width < kMaxProgressiveStretchPixels / height; -} - -FXDIB_Format GetStretchedFormat(const CFX_DIBSource& src) { - FXDIB_Format format = src.GetFormat(); - if (format == FXDIB_1bppMask) - return FXDIB_8bppMask; - if (format == FXDIB_1bppRgb) - return FXDIB_8bppRgb; - if (format == FXDIB_8bppRgb && src.GetPalette()) - return FXDIB_Rgb; - return format; -} - -} // namespace - -CWeightTable::CWeightTable() - : m_DestMin(0), - m_ItemSize(0), - m_pWeightTables(nullptr), - m_dwWeightTablesSize(0) {} - -CWeightTable::~CWeightTable() { - FX_Free(m_pWeightTables); -} - -size_t CWeightTable::GetPixelWeightSize() const { - return m_ItemSize / sizeof(int) - 2; -} - -bool CWeightTable::Calc(int dest_len, - int dest_min, - int dest_max, - int src_len, - int src_min, - int src_max, - int flags) { - FX_Free(m_pWeightTables); - m_pWeightTables = nullptr; - m_dwWeightTablesSize = 0; - const double scale = (FX_FLOAT)src_len / (FX_FLOAT)dest_len; - const double base = dest_len < 0 ? (FX_FLOAT)(src_len) : 0; - const int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1; - m_ItemSize = - sizeof(int) * 2 + - (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + ext_size)); - m_DestMin = dest_min; - if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) - return false; - - m_dwWeightTablesSize = (dest_max - dest_min) * m_ItemSize + 4; - m_pWeightTables = FX_TryAlloc(uint8_t, m_dwWeightTablesSize); - if (!m_pWeightTables) - return false; - - if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { - for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { - PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); - double src_pos = dest_pixel * scale + scale / 2 + base; - if (flags & FXDIB_INTERPOL) { - pixel_weights.m_SrcStart = - (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); - pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); - if (pixel_weights.m_SrcStart < src_min) { - pixel_weights.m_SrcStart = src_min; - } - if (pixel_weights.m_SrcEnd >= src_max) { - pixel_weights.m_SrcEnd = src_max - 1; - } - if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { - pixel_weights.m_Weights[0] = 65536; - } else { - pixel_weights.m_Weights[1] = FXSYS_round( - (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * - 65536); - pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; - } - } else if (flags & FXDIB_BICUBIC_INTERPOL) { - pixel_weights.m_SrcStart = - (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); - pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); - int start = pixel_weights.m_SrcStart - 1; - int end = pixel_weights.m_SrcEnd + 1; - if (start < src_min) { - start = src_min; - } - if (end >= src_max) { - end = src_max - 1; - } - if (pixel_weights.m_SrcStart < src_min) { - src_pos += src_min - pixel_weights.m_SrcStart; - pixel_weights.m_SrcStart = src_min; - } - if (pixel_weights.m_SrcEnd >= src_max) { - pixel_weights.m_SrcEnd = src_max - 1; - } - int weight; - weight = FXSYS_round( - (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 256); - if (start == end) { - pixel_weights.m_Weights[0] = - (SDP_Table[256 + weight] + SDP_Table[weight] + - SDP_Table[256 - weight] + SDP_Table[512 - weight]) - << 8; - } else if ((start == pixel_weights.m_SrcStart && - (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd || - end == pixel_weights.m_SrcEnd) && - start < end) || - (start < pixel_weights.m_SrcStart && - pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd && - end == pixel_weights.m_SrcEnd)) { - if (start < pixel_weights.m_SrcStart) { - pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; - pixel_weights.m_Weights[1] = - (SDP_Table[weight] + SDP_Table[256 - weight] + - SDP_Table[512 - weight]) - << 8; - } else { - if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { - pixel_weights.m_Weights[0] = - (SDP_Table[256 + weight] + SDP_Table[weight] + - SDP_Table[256 - weight]) - << 8; - pixel_weights.m_Weights[1] = SDP_Table[512 - weight] << 8; - } else { - pixel_weights.m_Weights[0] = - (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; - pixel_weights.m_Weights[1] = - (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; - } - } - if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { - pixel_weights.m_SrcEnd = end; - } - if (start < pixel_weights.m_SrcStart) { - pixel_weights.m_SrcStart = start; - } - } else if (start == pixel_weights.m_SrcStart && - start < pixel_weights.m_SrcEnd && - pixel_weights.m_SrcEnd < end) { - pixel_weights.m_Weights[0] = - (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; - pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8; - pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8; - pixel_weights.m_SrcEnd = end; - } else if (start < pixel_weights.m_SrcStart && - pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd && - pixel_weights.m_SrcEnd == end) { - pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; - pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; - pixel_weights.m_Weights[2] = - (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; - pixel_weights.m_SrcStart = start; - } else { - pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; - pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; - pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8; - pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8; - pixel_weights.m_SrcStart = start; - pixel_weights.m_SrcEnd = end; - } - } else { - pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = - (int)FXSYS_floor((FX_FLOAT)src_pos); - if (pixel_weights.m_SrcStart < src_min) { - pixel_weights.m_SrcStart = src_min; - } - if (pixel_weights.m_SrcEnd >= src_max) { - pixel_weights.m_SrcEnd = src_max - 1; - } - pixel_weights.m_Weights[0] = 65536; - } - } - return true; - } - - for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { - PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); - double src_start = dest_pixel * scale + base; - double src_end = src_start + scale; - int start_i, end_i; - if (src_start < src_end) { - start_i = (int)FXSYS_floor((FX_FLOAT)src_start); - end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); - } else { - start_i = (int)FXSYS_floor((FX_FLOAT)src_end); - end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); - } - if (start_i < src_min) { - start_i = src_min; - } - if (end_i >= src_max) { - end_i = src_max - 1; - } - if (start_i > end_i) { - if (start_i >= src_max) { - start_i = src_max - 1; - } - pixel_weights.m_SrcStart = start_i; - pixel_weights.m_SrcEnd = start_i; - continue; - } - pixel_weights.m_SrcStart = start_i; - pixel_weights.m_SrcEnd = end_i; - for (int j = start_i; j <= end_i; j++) { - double dest_start = ((FX_FLOAT)j - base) / scale; - double dest_end = ((FX_FLOAT)(j + 1) - base) / scale; - if (dest_start > dest_end) { - double temp = dest_start; - dest_start = dest_end; - dest_end = temp; - } - double area_start = dest_start > (FX_FLOAT)(dest_pixel) - ? dest_start - : (FX_FLOAT)(dest_pixel); - double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) - ? (FX_FLOAT)(dest_pixel + 1) - : dest_end; - double weight = area_start >= area_end ? 0.0f : area_end - area_start; - if (weight == 0 && j == end_i) { - pixel_weights.m_SrcEnd--; - break; - } - size_t idx = j - start_i; - if (idx >= GetPixelWeightSize()) - return false; - pixel_weights.m_Weights[idx] = FXSYS_round((FX_FLOAT)(weight * 65536)); - } - } - return true; -} - -PixelWeight* CWeightTable::GetPixelWeight(int pixel) const { - ASSERT(pixel >= m_DestMin); - return reinterpret_cast(m_pWeightTables + - (pixel - m_DestMin) * m_ItemSize); -} - -int* CWeightTable::GetValueFromPixelWeight(PixelWeight* pWeight, - int index) const { - if (index < pWeight->m_SrcStart) - return nullptr; - - size_t idx = index - pWeight->m_SrcStart; - return idx < GetPixelWeightSize() ? &pWeight->m_Weights[idx] : nullptr; -} - -CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap, - FXDIB_Format dest_format, - int dest_width, - int dest_height, - const FX_RECT& clip_rect, - const CFX_DIBSource* pSrcBitmap, - int flags) { - m_State = 0; - m_DestFormat = dest_format; - m_DestBpp = dest_format & 0xff; - m_SrcBpp = pSrcBitmap->GetFormat() & 0xff; - m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200; - m_pSrcPalette = pSrcBitmap->GetPalette(); - m_pDestBitmap = pDestBitmap; - m_DestWidth = dest_width; - m_DestHeight = dest_height; - m_pInterBuf = nullptr; - m_pExtraAlphaBuf = nullptr; - m_pDestMaskScanline = nullptr; - m_DestClip = clip_rect; - uint32_t size = clip_rect.Width(); - if (size && m_DestBpp > (int)(INT_MAX / size)) { - return; - } - size *= m_DestBpp; - if (size > INT_MAX - 31) { - return; - } - size += 31; - size = size / 32 * 4; - m_pDestScanline = FX_TryAlloc(uint8_t, size); - if (!m_pDestScanline) { - return; - } - if (dest_format == FXDIB_Rgb32) { - FXSYS_memset(m_pDestScanline, 255, size); - } - m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4; - m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4; - m_pInterBuf = nullptr; - m_pSource = pSrcBitmap; - m_SrcWidth = pSrcBitmap->GetWidth(); - m_SrcHeight = pSrcBitmap->GetHeight(); - m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4; - if ((flags & FXDIB_NOSMOOTH) == 0) { - bool bInterpol = flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL; - if (!bInterpol && FXSYS_abs(dest_width) != 0 && - FXSYS_abs(dest_height) / 8 < static_cast(m_SrcWidth) * - m_SrcHeight / FXSYS_abs(dest_width)) { - flags = FXDIB_INTERPOL; - } - m_Flags = flags; - } else { - m_Flags = FXDIB_NOSMOOTH; - if (flags & FXDIB_DOWNSAMPLE) { - m_Flags |= FXDIB_DOWNSAMPLE; - } - } - double scale_x = (FX_FLOAT)m_SrcWidth / (FX_FLOAT)m_DestWidth; - double scale_y = (FX_FLOAT)m_SrcHeight / (FX_FLOAT)m_DestHeight; - double base_x = m_DestWidth > 0 ? 0.0f : (FX_FLOAT)(m_DestWidth); - double base_y = m_DestHeight > 0 ? 0.0f : (FX_FLOAT)(m_DestHeight); - double src_left = scale_x * ((FX_FLOAT)(clip_rect.left) + base_x); - double src_right = scale_x * ((FX_FLOAT)(clip_rect.right) + base_x); - double src_top = scale_y * ((FX_FLOAT)(clip_rect.top) + base_y); - double src_bottom = scale_y * ((FX_FLOAT)(clip_rect.bottom) + base_y); - if (src_left > src_right) { - double temp = src_left; - src_left = src_right; - src_right = temp; - } - if (src_top > src_bottom) { - double temp = src_top; - src_top = src_bottom; - src_bottom = temp; - } - m_SrcClip.left = (int)FXSYS_floor((FX_FLOAT)src_left); - m_SrcClip.right = (int)FXSYS_ceil((FX_FLOAT)src_right); - m_SrcClip.top = (int)FXSYS_floor((FX_FLOAT)src_top); - m_SrcClip.bottom = (int)FXSYS_ceil((FX_FLOAT)src_bottom); - FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight); - m_SrcClip.Intersect(src_rect); - if (m_SrcBpp == 1) { - if (m_DestBpp == 8) { - m_TransMethod = 1; - } else { - m_TransMethod = 2; - } - } else if (m_SrcBpp == 8) { - if (m_DestBpp == 8) { - if (!m_bHasAlpha) { - m_TransMethod = 3; - } else { - m_TransMethod = 4; - } - } else { - if (!m_bHasAlpha) { - m_TransMethod = 5; - } else { - m_TransMethod = 6; - } - } - } else { - if (!m_bHasAlpha) { - m_TransMethod = 7; - } else { - m_TransMethod = 8; - } - } -} - -CStretchEngine::~CStretchEngine() { - FX_Free(m_pDestScanline); - FX_Free(m_pInterBuf); - FX_Free(m_pExtraAlphaBuf); - FX_Free(m_pDestMaskScanline); -} - -bool CStretchEngine::Continue(IFX_Pause* pPause) { - while (m_State == 1) { - if (ContinueStretchHorz(pPause)) { - return true; - } - m_State = 2; - StretchVert(); - } - return false; -} - -bool CStretchEngine::StartStretchHorz() { - if (m_DestWidth == 0 || m_InterPitch == 0 || !m_pDestScanline) - return false; - - if (m_SrcClip.Height() == 0 || - m_SrcClip.Height() > (1 << 29) / m_InterPitch) { - return false; - } - - m_pInterBuf = FX_TryAlloc(unsigned char, m_SrcClip.Height() * m_InterPitch); - if (!m_pInterBuf) - return false; - - if (m_pSource && m_bHasAlpha && m_pSource->m_pAlphaMask) { - m_pExtraAlphaBuf = - FX_Alloc2D(unsigned char, m_SrcClip.Height(), m_ExtraMaskPitch); - uint32_t size = (m_DestClip.Width() * 8 + 31) / 32 * 4; - m_pDestMaskScanline = FX_TryAlloc(unsigned char, size); - if (!m_pDestMaskScanline) - return false; - } - bool ret = - m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right, - m_SrcWidth, m_SrcClip.left, m_SrcClip.right, m_Flags); - if (!ret) - return false; - - m_CurRow = m_SrcClip.top; - m_State = 1; - return true; -} - -bool CStretchEngine::ContinueStretchHorz(IFX_Pause* pPause) { - if (!m_DestWidth) - return false; - - if (m_pSource->SkipToScanline(m_CurRow, pPause)) - return true; - - int Bpp = m_DestBpp / 8; - static const int kStrechPauseRows = 10; - int rows_to_go = kStrechPauseRows; - for (; m_CurRow < m_SrcClip.bottom; m_CurRow++) { - if (rows_to_go == 0) { - if (pPause && pPause->NeedToPauseNow()) - return true; - - rows_to_go = kStrechPauseRows; - } - - const uint8_t* src_scan = m_pSource->GetScanline(m_CurRow); - uint8_t* dest_scan = - m_pInterBuf + (m_CurRow - m_SrcClip.top) * m_InterPitch; - const uint8_t* src_scan_mask = nullptr; - uint8_t* dest_scan_mask = nullptr; - if (m_pExtraAlphaBuf) { - src_scan_mask = m_pSource->m_pAlphaMask->GetScanline(m_CurRow); - dest_scan_mask = - m_pExtraAlphaBuf + (m_CurRow - m_SrcClip.top) * m_ExtraMaskPitch; - } - switch (m_TransMethod) { - case 1: - case 2: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_a = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - if (src_scan[j / 8] & (1 << (7 - j % 8))) { - dest_a += pixel_weight * 255; - } - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; - } - *dest_scan++ = (uint8_t)(dest_a >> 16); - } - break; - } - case 3: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_a = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - dest_a += pixel_weight * src_scan[j]; - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; - } - *dest_scan++ = (uint8_t)(dest_a >> 16); - } - break; - } - case 4: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_a = 0, dest_r = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - pixel_weight = pixel_weight * src_scan_mask[j] / 255; - dest_r += pixel_weight * src_scan[j]; - dest_a += pixel_weight; - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_r = dest_r < 0 ? 0 : dest_r > 16711680 ? 16711680 : dest_r; - dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a; - } - *dest_scan++ = (uint8_t)(dest_r >> 16); - *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); - } - break; - } - case 5: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]; - if (m_DestFormat == FXDIB_Rgb) { - dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16); - dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 8); - dest_b_c += pixel_weight * (uint8_t)argb_cmyk; - } else { - dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >> 24); - dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 16); - dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 8); - } - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_r_y = - dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; - dest_g_m = - dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; - dest_b_c = - dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; - } - *dest_scan++ = (uint8_t)(dest_b_c >> 16); - *dest_scan++ = (uint8_t)(dest_g_m >> 16); - *dest_scan++ = (uint8_t)(dest_r_y >> 16); - } - break; - } - case 6: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - pixel_weight = pixel_weight * src_scan_mask[j] / 255; - unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]; - if (m_DestFormat == FXDIB_Rgba) { - dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16); - dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 8); - dest_b_c += pixel_weight * (uint8_t)argb_cmyk; - } else { - dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >> 24); - dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 16); - dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 8); - } - dest_a += pixel_weight; - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_b_c = - dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; - dest_g_m = - dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; - dest_r_y = - dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; - dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a; - } - *dest_scan++ = (uint8_t)(dest_b_c >> 16); - *dest_scan++ = (uint8_t)(dest_g_m >> 16); - *dest_scan++ = (uint8_t)(dest_r_y >> 16); - *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); - } - break; - } - case 7: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - const uint8_t* src_pixel = src_scan + j * Bpp; - dest_b_c += pixel_weight * (*src_pixel++); - dest_g_m += pixel_weight * (*src_pixel++); - dest_r_y += pixel_weight * (*src_pixel); - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_b_c = - dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; - dest_g_m = - dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; - dest_r_y = - dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; - } - *dest_scan++ = (uint8_t)((dest_b_c) >> 16); - *dest_scan++ = (uint8_t)((dest_g_m) >> 16); - *dest_scan++ = (uint8_t)((dest_r_y) >> 16); - dest_scan += Bpp - 3; - } - break; - } - case 8: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); - int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = - m_WeightTable.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return false; - - int pixel_weight = *pWeight; - const uint8_t* src_pixel = src_scan + j * Bpp; - if (m_DestFormat == FXDIB_Argb) { - pixel_weight = pixel_weight * src_pixel[3] / 255; - } else { - pixel_weight = pixel_weight * src_scan_mask[j] / 255; - } - dest_b_c += pixel_weight * (*src_pixel++); - dest_g_m += pixel_weight * (*src_pixel++); - dest_r_y += pixel_weight * (*src_pixel); - dest_a += pixel_weight; - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_r_y = - dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; - dest_g_m = - dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; - dest_b_c = - dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; - dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a; - } - *dest_scan++ = (uint8_t)((dest_b_c) >> 16); - *dest_scan++ = (uint8_t)((dest_g_m) >> 16); - *dest_scan++ = (uint8_t)((dest_r_y) >> 16); - if (m_DestFormat == FXDIB_Argb) { - *dest_scan = (uint8_t)((dest_a * 255) >> 16); - } - if (dest_scan_mask) { - *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); - } - dest_scan += Bpp - 3; - } - break; - } - } - rows_to_go--; - } - return false; -} - -void CStretchEngine::StretchVert() { - if (m_DestHeight == 0) - return; - - CWeightTable table; - bool ret = table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, - m_SrcHeight, m_SrcClip.top, m_SrcClip.bottom, m_Flags); - if (!ret) - return; - - const int DestBpp = m_DestBpp / 8; - for (int row = m_DestClip.top; row < m_DestClip.bottom; row++) { - unsigned char* dest_scan = m_pDestScanline; - unsigned char* dest_scan_mask = m_pDestMaskScanline; - PixelWeight* pPixelWeights = table.GetPixelWeight(row); - switch (m_TransMethod) { - case 1: - case 2: - case 3: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - unsigned char* src_scan = - m_pInterBuf + (col - m_DestClip.left) * DestBpp; - int dest_a = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return; - - int pixel_weight = *pWeight; - dest_a += - pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch]; - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; - } - *dest_scan = (uint8_t)(dest_a >> 16); - dest_scan += DestBpp; - } - break; - } - case 4: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - unsigned char* src_scan = - m_pInterBuf + (col - m_DestClip.left) * DestBpp; - unsigned char* src_scan_mask = - m_pExtraAlphaBuf + (col - m_DestClip.left); - int dest_a = 0, dest_k = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return; - - int pixel_weight = *pWeight; - dest_k += - pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch]; - dest_a += pixel_weight * - src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch]; - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_k = dest_k < 0 ? 0 : dest_k > 16711680 ? 16711680 : dest_k; - dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; - } - *dest_scan = (uint8_t)(dest_k >> 16); - dest_scan += DestBpp; - *dest_scan_mask++ = (uint8_t)(dest_a >> 16); - } - break; - } - case 5: - case 7: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - unsigned char* src_scan = - m_pInterBuf + (col - m_DestClip.left) * DestBpp; - int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return; - - int pixel_weight = *pWeight; - const uint8_t* src_pixel = - src_scan + (j - m_SrcClip.top) * m_InterPitch; - dest_b_c += pixel_weight * (*src_pixel++); - dest_g_m += pixel_weight * (*src_pixel++); - dest_r_y += pixel_weight * (*src_pixel); - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_r_y = - dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; - dest_g_m = - dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; - dest_b_c = - dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; - } - dest_scan[0] = (uint8_t)((dest_b_c) >> 16); - dest_scan[1] = (uint8_t)((dest_g_m) >> 16); - dest_scan[2] = (uint8_t)((dest_r_y) >> 16); - dest_scan += DestBpp; - } - break; - } - case 6: - case 8: { - for (int col = m_DestClip.left; col < m_DestClip.right; col++) { - unsigned char* src_scan = - m_pInterBuf + (col - m_DestClip.left) * DestBpp; - unsigned char* src_scan_mask = nullptr; - if (m_DestFormat != FXDIB_Argb) { - src_scan_mask = m_pExtraAlphaBuf + (col - m_DestClip.left); - } - int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int* pWeight = table.GetValueFromPixelWeight(pPixelWeights, j); - if (!pWeight) - return; - - int pixel_weight = *pWeight; - const uint8_t* src_pixel = - src_scan + (j - m_SrcClip.top) * m_InterPitch; - int mask_v = 255; - if (src_scan_mask) { - mask_v = src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch]; - } - dest_b_c += pixel_weight * (*src_pixel++); - dest_g_m += pixel_weight * (*src_pixel++); - dest_r_y += pixel_weight * (*src_pixel); - if (m_DestFormat == FXDIB_Argb) { - dest_a += pixel_weight * (*(src_pixel + 1)); - } else { - dest_a += pixel_weight * mask_v; - } - } - if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - dest_r_y = - dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; - dest_g_m = - dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; - dest_b_c = - dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; - dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; - } - if (dest_a) { - int r = ((uint32_t)dest_r_y) * 255 / dest_a; - int g = ((uint32_t)dest_g_m) * 255 / dest_a; - int b = ((uint32_t)dest_b_c) * 255 / dest_a; - dest_scan[0] = b > 255 ? 255 : b < 0 ? 0 : b; - dest_scan[1] = g > 255 ? 255 : g < 0 ? 0 : g; - dest_scan[2] = r > 255 ? 255 : r < 0 ? 0 : r; - } - if (m_DestFormat == FXDIB_Argb) { - dest_scan[3] = (uint8_t)((dest_a) >> 16); - } else { - *dest_scan_mask = (uint8_t)((dest_a) >> 16); - } - dest_scan += DestBpp; - if (dest_scan_mask) { - dest_scan_mask++; - } - } - break; - } - } - m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_pDestScanline, - m_pDestMaskScanline); - } -} - -CFX_ImageStretcher::CFX_ImageStretcher(IFX_ScanlineComposer* pDest, - const CFX_DIBSource* pSource, - int dest_width, - int dest_height, - const FX_RECT& bitmap_rect, - uint32_t flags) - : m_pDest(pDest), - m_pSource(pSource), - m_Flags(flags), - m_bFlipX(false), - m_bFlipY(false), - m_DestWidth(dest_width), - m_DestHeight(dest_height), - m_ClipRect(bitmap_rect), - m_DestFormat(GetStretchedFormat(*pSource)), - m_DestBPP(m_DestFormat & 0xff), - m_LineIndex(0) {} - -CFX_ImageStretcher::~CFX_ImageStretcher() { -} - -bool CFX_ImageStretcher::Start() { - if (m_DestWidth == 0 || m_DestHeight == 0) - return false; - - if (m_pSource->GetFormat() == FXDIB_1bppRgb && m_pSource->GetPalette()) { - FX_ARGB pal[256]; - int a0, r0, g0, b0, a1, r1, g1, b1; - ArgbDecode(m_pSource->GetPaletteEntry(0), a0, r0, g0, b0); - ArgbDecode(m_pSource->GetPaletteEntry(1), a1, r1, g1, b1); - for (int i = 0; i < 256; i++) { - int a = a0 + (a1 - a0) * i / 255; - int r = r0 + (r1 - r0) * i / 255; - int g = g0 + (g1 - g0) * i / 255; - int b = b0 + (b1 - b0) * i / 255; - pal[i] = ArgbEncode(a, r, g, b); - } - if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat, - pal)) { - return false; - } - } else if (m_pSource->GetFormat() == FXDIB_1bppCmyk && - m_pSource->GetPalette()) { - FX_CMYK pal[256]; - int c0, m0, y0, k0, c1, m1, y1, k1; - CmykDecode(m_pSource->GetPaletteEntry(0), c0, m0, y0, k0); - CmykDecode(m_pSource->GetPaletteEntry(1), c1, m1, y1, k1); - for (int i = 0; i < 256; i++) { - int c = c0 + (c1 - c0) * i / 255; - int m = m0 + (m1 - m0) * i / 255; - int y = y0 + (y1 - y0) * i / 255; - int k = k0 + (k1 - k0) * i / 255; - pal[i] = CmykEncode(c, m, y, k); - } - if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat, - pal)) { - return false; - } - } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), - m_DestFormat, nullptr)) { - return false; - } - - if (m_Flags & FXDIB_DOWNSAMPLE) - return StartQuickStretch(); - return StartStretch(); -} - -bool CFX_ImageStretcher::Continue(IFX_Pause* pPause) { - if (m_Flags & FXDIB_DOWNSAMPLE) - return ContinueQuickStretch(pPause); - return ContinueStretch(pPause); -} - -bool CFX_ImageStretcher::StartStretch() { - m_pStretchEngine = pdfium::MakeUnique( - m_pDest, m_DestFormat, m_DestWidth, m_DestHeight, m_ClipRect, m_pSource, - m_Flags); - m_pStretchEngine->StartStretchHorz(); - if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { - m_pStretchEngine->Continue(nullptr); - return false; - } - return true; -} - -bool CFX_ImageStretcher::ContinueStretch(IFX_Pause* pPause) { - return m_pStretchEngine && m_pStretchEngine->Continue(pPause); -} - -bool CFX_ImageStretcher::StartQuickStretch() { - if (m_DestWidth < 0) { - m_bFlipX = true; - m_DestWidth = -m_DestWidth; - } - if (m_DestHeight < 0) { - m_bFlipY = true; - m_DestHeight = -m_DestHeight; - } - uint32_t size = m_ClipRect.Width(); - if (size && m_DestBPP > (int)(INT_MAX / size)) { - return false; - } - size *= m_DestBPP; - m_pScanline.reset(FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4)); - if (m_pSource->m_pAlphaMask) - m_pMaskScanline.reset(FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4)); - - if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { - ContinueQuickStretch(nullptr); - return false; - } - return true; -} - -bool CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) { - if (!m_pScanline) - return false; - - int result_width = m_ClipRect.Width(); - int result_height = m_ClipRect.Height(); - int src_height = m_pSource->GetHeight(); - for (; m_LineIndex < result_height; m_LineIndex++) { - int dest_y; - int src_y; - if (m_bFlipY) { - dest_y = result_height - m_LineIndex - 1; - src_y = (m_DestHeight - (dest_y + m_ClipRect.top) - 1) * src_height / - m_DestHeight; - } else { - dest_y = m_LineIndex; - src_y = (dest_y + m_ClipRect.top) * src_height / m_DestHeight; - } - src_y = std::max(std::min(src_y, src_height - 1), 0); - - if (m_pSource->SkipToScanline(src_y, pPause)) - return true; - - m_pSource->DownSampleScanline(src_y, m_pScanline.get(), m_DestBPP, - m_DestWidth, m_bFlipX, m_ClipRect.left, - result_width); - if (m_pMaskScanline) { - m_pSource->m_pAlphaMask->DownSampleScanline( - src_y, m_pMaskScanline.get(), 1, m_DestWidth, m_bFlipX, - m_ClipRect.left, result_width); - } - m_pDest->ComposeScanline(dest_y, m_pScanline.get(), m_pMaskScanline.get()); - } - return false; -} diff --git a/core/fxge/dib/fx_dib_engine_unittest.cpp b/core/fxge/dib/fx_dib_engine_unittest.cpp deleted file mode 100644 index 705d761ca83f2401ae3f59a70310e3fd2e5d13bb..0000000000000000000000000000000000000000 --- a/core/fxge/dib/fx_dib_engine_unittest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 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. - -#include -#include - -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfapi/render/cpdf_dibsource.h" -#include "core/fxcrt/fx_memory.h" -#include "core/fxge/dib/dib_int.h" -#include "core/fxge/fx_dib.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/ptr_util.h" - -TEST(CStretchEngine, OverflowInCtor) { - FX_RECT clip_rect; - std::unique_ptr dict_obj = - pdfium::MakeUnique(); - dict_obj->SetNewFor("Width", 71000); - dict_obj->SetNewFor("Height", 12500); - std::unique_ptr stream = - pdfium::MakeUnique(nullptr, 0, std::move(dict_obj)); - CPDF_DIBSource dib_source; - dib_source.Load(nullptr, stream.get()); - CStretchEngine engine(nullptr, FXDIB_8bppRgb, 500, 500, clip_rect, - &dib_source, 0); - EXPECT_EQ(FXDIB_INTERPOL, engine.m_Flags); -} diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp index 96cae9d4e7bc4ac97664b6a85e38e02de86b51fa..68e06a6c5da44d3c97035f5cf2320ef501c7beaf 100644 --- a/core/fxge/dib/fx_dib_main.cpp +++ b/core/fxge/dib/fx_dib_main.cpp @@ -6,1642 +6,135 @@ #include "core/fxge/fx_dib.h" -#include - -#include -#include +#include #include -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/dib/dib_int.h" -#include "core/fxge/ge/cfx_cliprgn.h" +#include "core/fxcrt/fx_extension.h" #include "third_party/base/ptr_util.h" -void CmykDecode(uint32_t cmyk, int& c, int& m, int& y, int& k) { - c = FXSYS_GetCValue(cmyk); - m = FXSYS_GetMValue(cmyk); - y = FXSYS_GetYValue(cmyk); - k = FXSYS_GetKValue(cmyk); -} - -void ArgbDecode(uint32_t argb, int& a, int& r, int& g, int& b) { - a = FXARGB_A(argb); - r = FXARGB_R(argb); - g = FXARGB_G(argb); - b = FXARGB_B(argb); -} - -void ArgbDecode(uint32_t argb, int& a, FX_COLORREF& rgb) { - a = FXARGB_A(argb); - rgb = FXSYS_RGB(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); -} - -uint32_t ArgbEncode(int a, FX_COLORREF rgb) { - return FXARGB_MAKE(a, FXSYS_GetRValue(rgb), FXSYS_GetGValue(rgb), - FXSYS_GetBValue(rgb)); -} - -CFX_DIBSource::CFX_DIBSource() - : m_pAlphaMask(nullptr), - m_Width(0), - m_Height(0), - m_bpp(0), - m_AlphaFlag(0), - m_Pitch(0) {} - -CFX_DIBSource::~CFX_DIBSource() { - delete m_pAlphaMask; -} - -uint8_t* CFX_DIBSource::GetBuffer() const { - return nullptr; -} - -bool CFX_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const { - return false; -} - -CFX_DIBitmap::CFX_DIBitmap() { - m_bExtBuf = false; - m_pBuffer = nullptr; - m_pPalette = nullptr; -#ifdef _SKIA_SUPPORT_PATHS_ - m_nFormat = Format::kCleared; -#endif -} - -#define _MAX_OOM_LIMIT_ 12000000 -bool CFX_DIBitmap::Create(int width, +const int16_t SDP_Table[513] = { + 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255, 255, 255, 255, + 254, 254, 254, 254, 253, 253, 253, 252, 252, 252, 251, 251, 251, 250, 250, + 249, 249, 249, 248, 248, 247, 247, 246, 246, 245, 244, 244, 243, 243, 242, + 242, 241, 240, 240, 239, 238, 238, 237, 236, 236, 235, 234, 233, 233, 232, + 231, 230, 230, 229, 228, 227, 226, 226, 225, 224, 223, 222, 221, 220, 219, + 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, + 204, 203, 202, 201, 200, 199, 198, 196, 195, 194, 193, 192, 191, 190, 189, + 188, 186, 185, 184, 183, 182, 181, 179, 178, 177, 176, 175, 173, 172, 171, + 170, 169, 167, 166, 165, 164, 162, 161, 160, 159, 157, 156, 155, 154, 152, + 151, 150, 149, 147, 146, 145, 143, 142, 141, 140, 138, 137, 136, 134, 133, + 132, 130, 129, 128, 126, 125, 124, 122, 121, 120, 119, 117, 116, 115, 113, + 112, 111, 109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 95, 93, + 92, 91, 89, 88, 87, 85, 84, 83, 81, 80, 79, 77, 76, 75, 73, + 72, 71, 69, 68, 67, 66, 64, 63, 62, 60, 59, 58, 57, 55, 54, + 53, 52, 50, 49, 48, 47, 45, 44, 43, 42, 40, 39, 38, 37, 36, + 34, 33, 32, 31, 30, 28, 27, 26, 25, 24, 23, 21, 20, 19, 18, + 17, 16, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0, 0, -1, -2, -3, -4, -5, -6, -7, -7, -8, -9, -10, -11, + -12, -12, -13, -14, -15, -15, -16, -17, -17, -18, -19, -19, -20, -21, -21, + -22, -22, -23, -24, -24, -25, -25, -26, -26, -27, -27, -27, -28, -28, -29, + -29, -30, -30, -30, -31, -31, -31, -32, -32, -32, -33, -33, -33, -33, -34, + -34, -34, -34, -35, -35, -35, -35, -35, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37, -37, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -35, -35, -35, -35, -35, -35, -34, -34, -34, -34, -34, -33, -33, + -33, -33, -33, -32, -32, -32, -32, -31, -31, -31, -31, -30, -30, -30, -30, + -29, -29, -29, -29, -28, -28, -28, -27, -27, -27, -27, -26, -26, -26, -25, + -25, -25, -24, -24, -24, -23, -23, -23, -22, -22, -22, -22, -21, -21, -21, + -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16, + -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -12, -11, -11, -11, + -10, -10, -10, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -7, -6, + -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -3, -3, -3, -3, + -3, -2, -2, -2, -2, -2, -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, +}; + +FX_RECT FXDIB_SwapClipBox(FX_RECT& clip, + int width, int height, - FXDIB_Format format, - uint8_t* pBuffer, - int pitch) { - m_pBuffer = nullptr; - m_bpp = (uint8_t)format; - m_AlphaFlag = (uint8_t)(format >> 8); - m_Width = m_Height = m_Pitch = 0; - if (width <= 0 || height <= 0 || pitch < 0) { - return false; - } - if ((INT_MAX - 31) / width < (format & 0xff)) { - return false; - } - if (!pitch) { - pitch = (width * (format & 0xff) + 31) / 32 * 4; - } - if ((1 << 30) / pitch < height) { - return false; - } - if (pBuffer) { - m_pBuffer = pBuffer; - m_bExtBuf = true; - } else { - int size = pitch * height + 4; - int oomlimit = _MAX_OOM_LIMIT_; - if (oomlimit >= 0 && size >= oomlimit) { - m_pBuffer = FX_TryAlloc(uint8_t, size); - if (!m_pBuffer) { - return false; - } - } else { - m_pBuffer = FX_Alloc(uint8_t, size); - } - } - m_Width = width; - m_Height = height; - m_Pitch = pitch; - if (HasAlpha() && format != FXDIB_Argb) { - bool ret = true; - ret = BuildAlphaMask(); - if (!ret) { - if (!m_bExtBuf) { - FX_Free(m_pBuffer); - m_pBuffer = nullptr; - m_Width = m_Height = m_Pitch = 0; - return false; - } - } - } - return true; -} - -bool CFX_DIBitmap::Copy(const CFX_DIBSource* pSrc) { - if (m_pBuffer) - return false; - - if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat())) - return false; - - SetPalette(pSrc->GetPalette()); - SetAlphaMask(pSrc->m_pAlphaMask); - for (int row = 0; row < pSrc->GetHeight(); row++) - FXSYS_memcpy(m_pBuffer + row * m_Pitch, pSrc->GetScanline(row), m_Pitch); - - return true; -} - -CFX_DIBitmap::~CFX_DIBitmap() { - if (!m_bExtBuf) - FX_Free(m_pBuffer); - - m_pBuffer = nullptr; -} - -uint8_t* CFX_DIBitmap::GetBuffer() const { - return m_pBuffer; -} - -const uint8_t* CFX_DIBitmap::GetScanline(int line) const { - return m_pBuffer ? m_pBuffer + line * m_Pitch : nullptr; -} - -void CFX_DIBitmap::TakeOver(CFX_DIBitmap* pSrcBitmap) { - if (!m_bExtBuf) - FX_Free(m_pBuffer); - - delete m_pAlphaMask; - m_pBuffer = pSrcBitmap->m_pBuffer; - m_pPalette = std::move(pSrcBitmap->m_pPalette); - m_pAlphaMask = pSrcBitmap->m_pAlphaMask; - pSrcBitmap->m_pBuffer = nullptr; - pSrcBitmap->m_pAlphaMask = nullptr; - m_bpp = pSrcBitmap->m_bpp; - m_bExtBuf = pSrcBitmap->m_bExtBuf; - m_AlphaFlag = pSrcBitmap->m_AlphaFlag; - m_Width = pSrcBitmap->m_Width; - m_Height = pSrcBitmap->m_Height; - m_Pitch = pSrcBitmap->m_Pitch; -} - -std::unique_ptr CFX_DIBSource::Clone(const FX_RECT* pClip) const { - FX_RECT rect(0, 0, m_Width, m_Height); - if (pClip) { - rect.Intersect(*pClip); - if (rect.IsEmpty()) - return nullptr; - } - auto pNewBitmap = pdfium::MakeUnique(); - if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat())) - return nullptr; - - pNewBitmap->SetPalette(m_pPalette.get()); - pNewBitmap->SetAlphaMask(m_pAlphaMask, pClip); - if (GetBPP() == 1 && rect.left % 8 != 0) { - int left_shift = rect.left % 32; - int right_shift = 32 - left_shift; - int dword_count = pNewBitmap->m_Pitch / 4; - for (int row = rect.top; row < rect.bottom; row++) { - uint32_t* src_scan = (uint32_t*)GetScanline(row) + rect.left / 32; - uint32_t* dest_scan = (uint32_t*)pNewBitmap->GetScanline(row - rect.top); - for (int i = 0; i < dword_count; i++) { - dest_scan[i] = - (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift); - } - } - } else { - int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8; - if (m_Pitch < (uint32_t)copy_len) - copy_len = m_Pitch; - - for (int row = rect.top; row < rect.bottom; row++) { - const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8; - uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top); - FXSYS_memcpy(dest_scan, src_scan, copy_len); - } - } - return pNewBitmap; -} - -void CFX_DIBSource::BuildPalette() { - if (m_pPalette) - return; - - if (GetBPP() == 1) { - m_pPalette.reset(FX_Alloc(uint32_t, 2)); - if (IsCmykImage()) { - m_pPalette.get()[0] = 0xff; - m_pPalette.get()[1] = 0; - } else { - m_pPalette.get()[0] = 0xff000000; - m_pPalette.get()[1] = 0xffffffff; - } - } else if (GetBPP() == 8) { - m_pPalette.reset(FX_Alloc(uint32_t, 256)); - if (IsCmykImage()) { - for (int i = 0; i < 256; i++) - m_pPalette.get()[i] = 0xff - i; - } else { - for (int i = 0; i < 256; i++) - m_pPalette.get()[i] = 0xff000000 | (i * 0x10101); - } - } -} - -bool CFX_DIBSource::BuildAlphaMask() { - if (m_pAlphaMask) { - return true; - } - m_pAlphaMask = new CFX_DIBitmap; - if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) { - delete m_pAlphaMask; - m_pAlphaMask = nullptr; - return false; - } - FXSYS_memset(m_pAlphaMask->GetBuffer(), 0xff, - m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch()); - return true; -} - -uint32_t CFX_DIBSource::GetPaletteEntry(int index) const { - ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask()); - if (m_pPalette) { - return m_pPalette.get()[index]; - } - if (IsCmykImage()) { - if (GetBPP() == 1) { - return index ? 0 : 0xff; - } - return 0xff - index; - } - if (GetBPP() == 1) { - return index ? 0xffffffff : 0xff000000; - } - return index * 0x10101 | 0xff000000; -} - -void CFX_DIBSource::SetPaletteEntry(int index, uint32_t color) { - ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask()); - if (!m_pPalette) { - BuildPalette(); - } - m_pPalette.get()[index] = color; -} - -int CFX_DIBSource::FindPalette(uint32_t color) const { - ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask()); - if (!m_pPalette) { - if (IsCmykImage()) { - if (GetBPP() == 1) { - return ((uint8_t)color == 0xff) ? 0 : 1; - } - return 0xff - (uint8_t)color; - } - if (GetBPP() == 1) { - return ((uint8_t)color == 0xff) ? 1 : 0; - } - return (uint8_t)color; - } - int palsize = (1 << GetBPP()); - for (int i = 0; i < palsize; i++) - if (m_pPalette.get()[i] == color) { - return i; - } - return -1; -} - -void CFX_DIBitmap::Clear(uint32_t color) { - if (!m_pBuffer) { - return; - } - switch (GetFormat()) { - case FXDIB_1bppMask: - FXSYS_memset(m_pBuffer, (color & 0xff000000) ? 0xff : 0, - m_Pitch * m_Height); - break; - case FXDIB_1bppRgb: { - int index = FindPalette(color); - FXSYS_memset(m_pBuffer, index ? 0xff : 0, m_Pitch * m_Height); - break; - } - case FXDIB_8bppMask: - FXSYS_memset(m_pBuffer, color >> 24, m_Pitch * m_Height); - break; - case FXDIB_8bppRgb: { - int index = FindPalette(color); - FXSYS_memset(m_pBuffer, index, m_Pitch * m_Height); - break; - } - case FXDIB_Rgb: - case FXDIB_Rgba: { - int a, r, g, b; - ArgbDecode(color, a, r, g, b); - if (r == g && g == b) { - FXSYS_memset(m_pBuffer, r, m_Pitch * m_Height); - } else { - int byte_pos = 0; - for (int col = 0; col < m_Width; col++) { - m_pBuffer[byte_pos++] = b; - m_pBuffer[byte_pos++] = g; - m_pBuffer[byte_pos++] = r; - } - for (int row = 1; row < m_Height; row++) { - FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch); - } - } - break; - } - case FXDIB_Rgb32: - case FXDIB_Argb: { - color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); -#ifdef _SKIA_SUPPORT_ - if (FXDIB_Rgb32 == GetFormat() && !IsCmykImage()) { - color |= 0xFF000000; - } -#endif - for (int i = 0; i < m_Width; i++) { - ((uint32_t*)m_pBuffer)[i] = color; - } - for (int row = 1; row < m_Height; row++) { - FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch); - } - break; - } - default: - break; - } -} - -void CFX_DIBSource::GetOverlapRect(int& dest_left, - int& dest_top, - int& width, - int& height, - int src_width, - int src_height, - int& src_left, - int& src_top, - const CFX_ClipRgn* pClipRgn) { - if (width == 0 || height == 0) { - return; - } - ASSERT(width > 0 && height > 0); - if (dest_left > m_Width || dest_top > m_Height) { - width = 0; - height = 0; - return; - } - int x_offset = dest_left - src_left; - int y_offset = dest_top - src_top; - FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height); - FX_RECT src_bound(0, 0, src_width, src_height); - src_rect.Intersect(src_bound); - FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset, - src_rect.right + x_offset, src_rect.bottom + y_offset); - FX_RECT dest_bound(0, 0, m_Width, m_Height); - dest_rect.Intersect(dest_bound); - if (pClipRgn) { - dest_rect.Intersect(pClipRgn->GetBox()); - } - dest_left = dest_rect.left; - dest_top = dest_rect.top; - src_left = dest_left - x_offset; - src_top = dest_top - y_offset; - width = dest_rect.right - dest_rect.left; - height = dest_rect.bottom - dest_rect.top; -} - -bool CFX_DIBitmap::TransferBitmap(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - if (!m_pBuffer) - return false; - - GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), - pSrcBitmap->GetHeight(), src_left, src_top, nullptr); - if (width == 0 || height == 0) - return true; - - FXDIB_Format dest_format = GetFormat(); - FXDIB_Format src_format = pSrcBitmap->GetFormat(); - if (dest_format == src_format) { - if (GetBPP() == 1) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = m_pBuffer + (dest_top + row) * m_Pitch; - const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); - for (int col = 0; col < width; col++) { - if (src_scan[(src_left + col) / 8] & - (1 << (7 - (src_left + col) % 8))) { - dest_scan[(dest_left + col) / 8] |= 1 - << (7 - (dest_left + col) % 8); - } else { - dest_scan[(dest_left + col) / 8] &= - ~(1 << (7 - (dest_left + col) % 8)); - } - } - } - } else { - int Bpp = GetBPP() / 8; - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = - m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp; - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; - FXSYS_memcpy(dest_scan, src_scan, width * Bpp); - } - } - } else { - if (m_pPalette) - return false; - - if (m_bpp == 8) - dest_format = FXDIB_8bppMask; - - uint8_t* dest_buf = - m_pBuffer + dest_top * m_Pitch + dest_left * GetBPP() / 8; - std::unique_ptr d_plt; - if (!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height, - pSrcBitmap, src_left, src_top, &d_plt)) { - return false; - } - } - return true; -} - -bool CFX_DIBitmap::TransferMask(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pMask, - uint32_t color, - int src_left, - int src_top, - int alpha_flag, - void* pIccTransform) { - if (!m_pBuffer) { - return false; - } - ASSERT(HasAlpha() && (m_bpp >= 24)); - ASSERT(pMask->IsAlphaMask()); - if (!HasAlpha() || !pMask->IsAlphaMask() || m_bpp < 24) { - return false; - } - GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), - pMask->GetHeight(), src_left, src_top, nullptr); - if (width == 0 || height == 0) { - return true; - } - int src_bpp = pMask->GetBPP(); - int alpha; - uint32_t dst_color; - if (alpha_flag >> 8) { - alpha = alpha_flag & 0xff; - dst_color = FXCMYK_TODIB(color); + bool bFlipX, + bool bFlipY) { + FX_RECT rect; + if (bFlipY) { + rect.left = height - clip.top; + rect.right = height - clip.bottom; } else { - alpha = FXARGB_A(color); - dst_color = FXARGB_TODIB(color); + rect.left = clip.top; + rect.right = clip.bottom; } - uint8_t* color_p = (uint8_t*)&dst_color; - if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && - CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - CCodec_IccModule* pIccModule = - CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1); + if (bFlipX) { + rect.top = width - clip.left; + rect.bottom = width - clip.right; } else { - if (alpha_flag >> 8 && !IsCmykImage()) { - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), - color_p[2], color_p[1], color_p[0]); - } else if (!(alpha_flag >> 8) && IsCmykImage()) { - return false; - } - } - if (!IsCmykImage()) { - color_p[3] = (uint8_t)alpha; + rect.top = clip.left; + rect.bottom = clip.right; } - if (GetFormat() == FXDIB_Argb) { - for (int row = 0; row < height; row++) { - uint32_t* dest_pos = - (uint32_t*)(m_pBuffer + (dest_top + row) * m_Pitch + dest_left * 4); - const uint8_t* src_scan = pMask->GetScanline(src_top + row); - if (src_bpp == 1) { - for (int col = 0; col < width; col++) { - int src_bitpos = src_left + col; - if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) { - *dest_pos = dst_color; - } else { - *dest_pos = 0; - } - dest_pos++; - } - } else { - src_scan += src_left; - dst_color = FXARGB_TODIB(dst_color); - dst_color &= 0xffffff; - for (int col = 0; col < width; col++) { - FXARGB_SETDIB(dest_pos++, - dst_color | ((alpha * (*src_scan++) / 255) << 24)); - } - } - } - } else { - int comps = m_bpp / 8; - for (int row = 0; row < height; row++) { - uint8_t* dest_color_pos = - m_pBuffer + (dest_top + row) * m_Pitch + dest_left * comps; - uint8_t* dest_alpha_pos = - (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left; - const uint8_t* src_scan = pMask->GetScanline(src_top + row); - if (src_bpp == 1) { - for (int col = 0; col < width; col++) { - int src_bitpos = src_left + col; - if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) { - FXSYS_memcpy(dest_color_pos, color_p, comps); - *dest_alpha_pos = 0xff; - } else { - FXSYS_memset(dest_color_pos, 0, comps); - *dest_alpha_pos = 0; - } - dest_color_pos += comps; - dest_alpha_pos++; - } - } else { - src_scan += src_left; - for (int col = 0; col < width; col++) { - FXSYS_memcpy(dest_color_pos, color_p, comps); - dest_color_pos += comps; - *dest_alpha_pos++ = (alpha * (*src_scan++) / 255); - } - } - } - } - return true; + rect.Normalize(); + return rect; } -void CFX_DIBSource::SetPalette(const uint32_t* pSrc) { - static const uint32_t kPaletteSize = 256; - if (!pSrc || GetBPP() > 8) { - m_pPalette.reset(); - return; - } - uint32_t pal_size = 1 << GetBPP(); - if (!m_pPalette) - m_pPalette.reset(FX_Alloc(uint32_t, pal_size)); - pal_size = std::min(pal_size, kPaletteSize); - FXSYS_memcpy(m_pPalette.get(), pSrc, pal_size * sizeof(uint32_t)); -} - -void CFX_DIBSource::GetPalette(uint32_t* pal, int alpha) const { - ASSERT(GetBPP() <= 8 && !IsCmykImage()); - if (GetBPP() == 1) { - pal[0] = ((m_pPalette ? m_pPalette.get()[0] : 0xff000000) & 0xffffff) | - (alpha << 24); - pal[1] = ((m_pPalette ? m_pPalette.get()[1] : 0xffffffff) & 0xffffff) | - (alpha << 24); - return; - } - if (m_pPalette) { - for (int i = 0; i < 256; i++) { - pal[i] = (m_pPalette.get()[i] & 0x00ffffff) | (alpha << 24); - } - } else { - for (int i = 0; i < 256; i++) { - pal[i] = (i * 0x10101) | (alpha << 24); - } - } -} - -std::unique_ptr CFX_DIBSource::CloneAlphaMask( - const FX_RECT* pClip) const { - ASSERT(GetFormat() == FXDIB_Argb); - FX_RECT rect(0, 0, m_Width, m_Height); - if (pClip) { - rect.Intersect(*pClip); - if (rect.IsEmpty()) - return nullptr; - } - auto pMask = pdfium::MakeUnique(); - if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask)) - return nullptr; - - for (int row = rect.top; row < rect.bottom; row++) { - const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3; - uint8_t* dest_scan = - const_cast(pMask->GetScanline(row - rect.top)); - for (int col = rect.left; col < rect.right; col++) { - *dest_scan++ = *src_scan; - src_scan += 4; - } - } - return pMask; -} - -bool CFX_DIBSource::SetAlphaMask(const CFX_DIBSource* pAlphaMask, - const FX_RECT* pClip) { - if (!HasAlpha() || GetFormat() == FXDIB_Argb) - return false; - - if (!pAlphaMask) { - m_pAlphaMask->Clear(0xff000000); - return true; - } - FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height); - if (pClip) { - rect.Intersect(*pClip); - if (rect.IsEmpty() || rect.Width() != m_Width || - rect.Height() != m_Height) { - return false; - } - } else { - if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height) - return false; - } - for (int row = 0; row < m_Height; row++) { - FXSYS_memcpy(const_cast(m_pAlphaMask->GetScanline(row)), - pAlphaMask->GetScanline(row + rect.top) + rect.left, - m_pAlphaMask->m_Pitch); - } - return true; -} - -const int g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3}; -bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, - CFX_DIBSource* pSrcBitmap, - FXDIB_Channel srcChannel) { - if (!m_pBuffer) - return false; - - CFX_MaybeOwned pSrcClone(pSrcBitmap); - int srcOffset; - if (srcChannel == FXDIB_Alpha) { - if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask()) - return false; - - if (pSrcBitmap->GetBPP() == 1) { - pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask); - if (!pSrcClone) - return false; - } - srcOffset = pSrcBitmap->GetFormat() == FXDIB_Argb ? 3 : 0; - } else { - if (pSrcBitmap->IsAlphaMask()) - return false; - - if (pSrcBitmap->GetBPP() < 24) { - if (pSrcBitmap->IsCmykImage()) { - pSrcClone = pSrcBitmap->CloneConvert(static_cast( - (pSrcBitmap->GetFormat() & 0xff00) | 0x20)); - } else { - pSrcClone = pSrcBitmap->CloneConvert(static_cast( - (pSrcBitmap->GetFormat() & 0xff00) | 0x18)); - } - if (!pSrcClone) - return false; - } - srcOffset = g_ChannelOffset[srcChannel]; - } - int destOffset = 0; - if (destChannel == FXDIB_Alpha) { - if (IsAlphaMask()) { - if (!ConvertFormat(FXDIB_8bppMask)) - return false; - } else { - if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) - return false; - - if (GetFormat() == FXDIB_Argb) - destOffset = 3; - } - } else { - if (IsAlphaMask()) - return false; - - if (GetBPP() < 24) { - if (HasAlpha()) { - if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) - return false; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) { -#else - } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) { -#endif - return false; - } - } - destOffset = g_ChannelOffset[destChannel]; - } - if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) { - CFX_MaybeOwned pAlphaMask(pSrcClone->m_pAlphaMask); - if (pSrcClone->GetWidth() != m_Width || - pSrcClone->GetHeight() != m_Height) { - if (pAlphaMask) { - pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height); - if (!pAlphaMask) - return false; - } - } - pSrcClone = std::move(pAlphaMask); - srcOffset = 0; - } else if (pSrcClone->GetWidth() != m_Width || - pSrcClone->GetHeight() != m_Height) { - std::unique_ptr pSrcMatched = - pSrcClone->StretchTo(m_Width, m_Height); - if (!pSrcMatched) - return false; - - pSrcClone = std::move(pSrcMatched); - } - CFX_DIBitmap* pDst = this; - if (destChannel == FXDIB_Alpha && m_pAlphaMask) { - pDst = m_pAlphaMask; - destOffset = 0; - } - int srcBytes = pSrcClone->GetBPP() / 8; - int destBytes = pDst->GetBPP() / 8; - for (int row = 0; row < m_Height; row++) { - uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset; - const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset; - for (int col = 0; col < m_Width; col++) { - *dest_pos = *src_pos; - dest_pos += destBytes; - src_pos += srcBytes; - } - } - return true; +std::tuple ArgbDecode(FX_ARGB argb) { + return std::make_tuple(FXARGB_A(argb), FXARGB_R(argb), FXARGB_G(argb), + FXARGB_B(argb)); } -bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value) { - if (!m_pBuffer) { - return false; - } - int destOffset; - if (destChannel == FXDIB_Alpha) { - if (IsAlphaMask()) { - if (!ConvertFormat(FXDIB_8bppMask)) { - return false; - } - destOffset = 0; - } else { - destOffset = 0; - if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) { - return false; - } - if (GetFormat() == FXDIB_Argb) { - destOffset = 3; - } - } - } else { - if (IsAlphaMask()) { - return false; - } - if (GetBPP() < 24) { - if (HasAlpha()) { - if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) { - return false; - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) { -#else - } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) { -#endif - return false; - } - } - destOffset = g_ChannelOffset[destChannel]; - } - int Bpp = GetBPP() / 8; - if (Bpp == 1) { - FXSYS_memset(m_pBuffer, value, m_Height * m_Pitch); - return true; - } - if (destChannel == FXDIB_Alpha && m_pAlphaMask) { - FXSYS_memset(m_pAlphaMask->GetBuffer(), value, - m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch()); - return true; - } - for (int row = 0; row < m_Height; row++) { - uint8_t* scan_line = m_pBuffer + row * m_Pitch + destOffset; - for (int col = 0; col < m_Width; col++) { - *scan_line = value; - scan_line += Bpp; - } - } - return true; +std::pair ArgbToColorRef(FX_ARGB argb) { + return {FXARGB_A(argb), + FXSYS_RGB(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb))}; } -bool CFX_DIBitmap::MultiplyAlpha(CFX_DIBSource* pSrcBitmap) { - if (!m_pBuffer) - return false; - - ASSERT(pSrcBitmap->IsAlphaMask()); - if (!pSrcBitmap->IsAlphaMask()) - return false; - - if (!IsAlphaMask() && !HasAlpha()) - return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha); - - CFX_MaybeOwned pSrcClone( - static_cast(pSrcBitmap)); - if (pSrcBitmap->GetWidth() != m_Width || - pSrcBitmap->GetHeight() != m_Height) { - pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height); - if (!pSrcClone) - return false; - } - if (IsAlphaMask()) { - if (!ConvertFormat(FXDIB_8bppMask)) - return false; - - for (int row = 0; row < m_Height; row++) { - uint8_t* dest_scan = m_pBuffer + m_Pitch * row; - uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row; - if (pSrcClone->GetBPP() == 1) { - for (int col = 0; col < m_Width; col++) { - if (!((1 << (7 - col % 8)) & src_scan[col / 8])) - dest_scan[col] = 0; - } - } else { - for (int col = 0; col < m_Width; col++) { - *dest_scan = (*dest_scan) * src_scan[col] / 255; - dest_scan++; - } - } - } - } else { - if (GetFormat() == FXDIB_Argb) { - if (pSrcClone->GetBPP() == 1) - return false; - - for (int row = 0; row < m_Height; row++) { - uint8_t* dest_scan = m_pBuffer + m_Pitch * row + 3; - uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row; - for (int col = 0; col < m_Width; col++) { - *dest_scan = (*dest_scan) * src_scan[col] / 255; - dest_scan += 4; - } - } - } else { - m_pAlphaMask->MultiplyAlpha(pSrcClone.Get()); - } - } - return true; +uint32_t ArgbEncode(int a, FX_COLORREF rgb) { + return FXARGB_MAKE(a, FXSYS_GetRValue(rgb), FXSYS_GetGValue(rgb), + FXSYS_GetBValue(rgb)); } -bool CFX_DIBitmap::GetGrayData(void* pIccTransform) { - if (!m_pBuffer) { - return false; - } - switch (GetFormat()) { - case FXDIB_1bppRgb: { - if (!m_pPalette) { - return false; - } - uint8_t gray[2]; - for (int i = 0; i < 2; i++) { - int r = static_cast(m_pPalette.get()[i] >> 16); - int g = static_cast(m_pPalette.get()[i] >> 8); - int b = static_cast(m_pPalette.get()[i]); - gray[i] = static_cast(FXRGB2GRAY(r, g, b)); - } - CFX_DIBitmap* pMask = new CFX_DIBitmap; - if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) { - delete pMask; - return false; - } - FXSYS_memset(pMask->GetBuffer(), gray[0], pMask->GetPitch() * m_Height); - for (int row = 0; row < m_Height; row++) { - uint8_t* src_pos = m_pBuffer + row * m_Pitch; - uint8_t* dest_pos = (uint8_t*)pMask->GetScanline(row); - for (int col = 0; col < m_Width; col++) { - if (src_pos[col / 8] & (1 << (7 - col % 8))) { - *dest_pos = gray[1]; - } - dest_pos++; - } - } - TakeOver(pMask); - delete pMask; - break; - } - case FXDIB_8bppRgb: { - if (!m_pPalette) { - return false; - } - uint8_t gray[256]; - for (int i = 0; i < 256; i++) { - int r = static_cast(m_pPalette.get()[i] >> 16); - int g = static_cast(m_pPalette.get()[i] >> 8); - int b = static_cast(m_pPalette.get()[i]); - gray[i] = static_cast(FXRGB2GRAY(r, g, b)); - } - CFX_DIBitmap* pMask = new CFX_DIBitmap; - if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) { - delete pMask; - return false; - } - for (int row = 0; row < m_Height; row++) { - uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch(); - uint8_t* src_pos = m_pBuffer + row * m_Pitch; - for (int col = 0; col < m_Width; col++) { - *dest_pos++ = gray[*src_pos++]; - } - } - TakeOver(pMask); - delete pMask; - break; - } - case FXDIB_Rgb: { - CFX_DIBitmap* pMask = new CFX_DIBitmap; - if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) { - delete pMask; - return false; - } - for (int row = 0; row < m_Height; row++) { - uint8_t* src_pos = m_pBuffer + row * m_Pitch; - uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch(); - for (int col = 0; col < m_Width; col++) { - *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos); - src_pos += 3; - } - } - TakeOver(pMask); - delete pMask; - break; - } - case FXDIB_Rgb32: { - CFX_DIBitmap* pMask = new CFX_DIBitmap; - if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) { - delete pMask; - return false; - } - for (int row = 0; row < m_Height; row++) { - uint8_t* src_pos = m_pBuffer + row * m_Pitch; - uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch(); - for (int col = 0; col < m_Width; col++) { - *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos); - src_pos += 4; - } - } - TakeOver(pMask); - delete pMask; - break; - } - default: - return false; - } - return true; -} +FX_ARGB StringToFXARGB(const WideStringView& wsValue) { + uint8_t r = 0, g = 0, b = 0; + if (wsValue.GetLength() == 0) + return 0xff000000; -bool CFX_DIBitmap::MultiplyAlpha(int alpha) { - if (!m_pBuffer) { - return false; - } - switch (GetFormat()) { - case FXDIB_1bppMask: - if (!ConvertFormat(FXDIB_8bppMask)) { - return false; - } - MultiplyAlpha(alpha); - break; - case FXDIB_8bppMask: { - for (int row = 0; row < m_Height; row++) { - uint8_t* scan_line = m_pBuffer + row * m_Pitch; - for (int col = 0; col < m_Width; col++) { - scan_line[col] = scan_line[col] * alpha / 255; - } - } - break; - } - case FXDIB_Argb: { - for (int row = 0; row < m_Height; row++) { - uint8_t* scan_line = m_pBuffer + row * m_Pitch + 3; - for (int col = 0; col < m_Width; col++) { - *scan_line = (*scan_line) * alpha / 255; - scan_line += 4; - } - } - break; - } - default: - if (HasAlpha()) { - m_pAlphaMask->MultiplyAlpha(alpha); - } else if (IsCmykImage()) { - if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) { - return false; - } - m_pAlphaMask->MultiplyAlpha(alpha); - } else { - if (!ConvertFormat(FXDIB_Argb)) { - return false; - } - MultiplyAlpha(alpha); - } - break; - } - return true; -} + int cc = 0; + const wchar_t* str = wsValue.unterminated_c_str(); + int len = wsValue.GetLength(); + while (FXSYS_iswspace(str[cc]) && cc < len) + cc++; -uint32_t CFX_DIBitmap::GetPixel(int x, int y) const { - if (!m_pBuffer) { - return 0; - } - uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8; - switch (GetFormat()) { - case FXDIB_1bppMask: { - if ((*pos) & (1 << (7 - x % 8))) { - return 0xff000000; - } - return 0; - } - case FXDIB_1bppRgb: { - if ((*pos) & (1 << (7 - x % 8))) { - return m_pPalette ? m_pPalette.get()[1] : 0xffffffff; - } - return m_pPalette ? m_pPalette.get()[0] : 0xff000000; - } - case FXDIB_8bppMask: - return (*pos) << 24; - case FXDIB_8bppRgb: - return m_pPalette ? m_pPalette.get()[*pos] - : (0xff000000 | ((*pos) * 0x10101)); - case FXDIB_Rgb: - case FXDIB_Rgba: - case FXDIB_Rgb32: - return FXARGB_GETDIB(pos) | 0xff000000; - case FXDIB_Argb: - return FXARGB_GETDIB(pos); - default: - break; - } - return 0; -} + if (cc >= len) + return 0xff000000; -void CFX_DIBitmap::SetPixel(int x, int y, uint32_t color) { - if (!m_pBuffer) { - return; - } - if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) { - return; - } - uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8; - switch (GetFormat()) { - case FXDIB_1bppMask: - if (color >> 24) { - *pos |= 1 << (7 - x % 8); - } else { - *pos &= ~(1 << (7 - x % 8)); - } - break; - case FXDIB_1bppRgb: - if (m_pPalette) { - if (color == m_pPalette.get()[1]) { - *pos |= 1 << (7 - x % 8); - } else { - *pos &= ~(1 << (7 - x % 8)); - } - } else { - if (color == 0xffffffff) { - *pos |= 1 << (7 - x % 8); - } else { - *pos &= ~(1 << (7 - x % 8)); - } - } + while (cc < len) { + if (str[cc] == ',' || !FXSYS_isDecimalDigit(str[cc])) break; - case FXDIB_8bppMask: - *pos = (uint8_t)(color >> 24); - break; - case FXDIB_8bppRgb: { - if (m_pPalette) { - for (int i = 0; i < 256; i++) { - if (m_pPalette.get()[i] == color) { - *pos = (uint8_t)i; - return; - } - } - *pos = 0; - } else { - *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); - } - break; - } - case FXDIB_Rgb: - case FXDIB_Rgb32: { - int alpha = FXARGB_A(color); - pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255; - pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255; - pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255; - break; - } - case FXDIB_Rgba: { - pos[0] = FXARGB_B(color); - pos[1] = FXARGB_G(color); - pos[2] = FXARGB_R(color); - break; - } - case FXDIB_Argb: - FXARGB_SETDIB(pos, color); - break; - default: - break; - } -} -void CFX_DIBitmap::DownSampleScanline(int line, - uint8_t* dest_scan, - int dest_bpp, - int dest_width, - bool bFlipX, - int clip_left, - int clip_width) const { - if (!m_pBuffer) { - return; - } - int src_Bpp = m_bpp / 8; - uint8_t* scanline = m_pBuffer + line * m_Pitch; - if (src_Bpp == 0) { - for (int i = 0; i < clip_width; i++) { - uint32_t dest_x = clip_left + i; - uint32_t src_x = dest_x * m_Width / dest_width; - if (bFlipX) { - src_x = m_Width - src_x - 1; - } - src_x %= m_Width; - dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0; - } - } else if (src_Bpp == 1) { - for (int i = 0; i < clip_width; i++) { - uint32_t dest_x = clip_left + i; - uint32_t src_x = dest_x * m_Width / dest_width; - if (bFlipX) { - src_x = m_Width - src_x - 1; - } - src_x %= m_Width; - int dest_pos = i; - if (m_pPalette) { - if (!IsCmykImage()) { - dest_pos *= 3; - FX_ARGB argb = m_pPalette.get()[scanline[src_x]]; - dest_scan[dest_pos] = FXARGB_B(argb); - dest_scan[dest_pos + 1] = FXARGB_G(argb); - dest_scan[dest_pos + 2] = FXARGB_R(argb); - } else { - dest_pos *= 4; - FX_CMYK cmyk = m_pPalette.get()[scanline[src_x]]; - dest_scan[dest_pos] = FXSYS_GetCValue(cmyk); - dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk); - dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk); - dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk); - } - } else { - dest_scan[dest_pos] = scanline[src_x]; - } - } - } else { - for (int i = 0; i < clip_width; i++) { - uint32_t dest_x = clip_left + i; - uint32_t src_x = - bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp - : (dest_x * m_Width / dest_width) * src_Bpp; - src_x %= m_Width * src_Bpp; - int dest_pos = i * src_Bpp; - for (int b = 0; b < src_Bpp; b++) { - dest_scan[dest_pos + b] = scanline[src_x + b]; - } - } + r = r * 10 + str[cc] - '0'; + cc++; } -} + if (cc < len && str[cc] == ',') { + cc++; + while (FXSYS_iswspace(str[cc]) && cc < len) + cc++; -// TODO(weili): Split this function into two for handling CMYK and RGB -// colors separately. -bool CFX_DIBitmap::ConvertColorScale(uint32_t forecolor, uint32_t backcolor) { - ASSERT(!IsAlphaMask()); - if (!m_pBuffer || IsAlphaMask()) { - return false; - } - // Values used for CMYK colors. - int fc = 0; - int fm = 0; - int fy = 0; - int fk = 0; - int bc = 0; - int bm = 0; - int by = 0; - int bk = 0; - // Values used for RGB colors. - int fr = 0; - int fg = 0; - int fb = 0; - int br = 0; - int bg = 0; - int bb = 0; - bool isCmykImage = IsCmykImage(); - if (isCmykImage) { - fc = FXSYS_GetCValue(forecolor); - fm = FXSYS_GetMValue(forecolor); - fy = FXSYS_GetYValue(forecolor); - fk = FXSYS_GetKValue(forecolor); - bc = FXSYS_GetCValue(backcolor); - bm = FXSYS_GetMValue(backcolor); - by = FXSYS_GetYValue(backcolor); - bk = FXSYS_GetKValue(backcolor); - } else { - fr = FXSYS_GetRValue(forecolor); - fg = FXSYS_GetGValue(forecolor); - fb = FXSYS_GetBValue(forecolor); - br = FXSYS_GetRValue(backcolor); - bg = FXSYS_GetGValue(backcolor); - bb = FXSYS_GetBValue(backcolor); - } - if (m_bpp <= 8) { - if (isCmykImage) { - if (forecolor == 0xff && backcolor == 0 && !m_pPalette) { - return true; - } - } else if (forecolor == 0 && backcolor == 0xffffff && !m_pPalette) { - return true; - } - if (!m_pPalette) { - BuildPalette(); - } - int size = 1 << m_bpp; - if (isCmykImage) { - for (int i = 0; i < size; i++) { - uint8_t b, g, r; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette.get()[i]), - FXSYS_GetMValue(m_pPalette.get()[i]), - FXSYS_GetYValue(m_pPalette.get()[i]), - FXSYS_GetKValue(m_pPalette.get()[i]), r, g, b); - int gray = 255 - FXRGB2GRAY(r, g, b); - m_pPalette.get()[i] = CmykEncode( - bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255, - by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255); - } - } else { - for (int i = 0; i < size; i++) { - int gray = FXRGB2GRAY(FXARGB_R(m_pPalette.get()[i]), - FXARGB_G(m_pPalette.get()[i]), - FXARGB_B(m_pPalette.get()[i])); - m_pPalette.get()[i] = FXARGB_MAKE(0xff, br + (fr - br) * gray / 255, - bg + (fg - bg) * gray / 255, - bb + (fb - bb) * gray / 255); - } - } - return true; - } - if (isCmykImage) { - if (forecolor == 0xff && backcolor == 0x00) { - for (int row = 0; row < m_Height; row++) { - uint8_t* scanline = m_pBuffer + row * m_Pitch; - for (int col = 0; col < m_Width; col++) { - uint8_t b, g, r; - AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3], - r, g, b); - *scanline++ = 0; - *scanline++ = 0; - *scanline++ = 0; - *scanline++ = 255 - FXRGB2GRAY(r, g, b); - } - } - return true; - } - } else if (forecolor == 0 && backcolor == 0xffffff) { - for (int row = 0; row < m_Height; row++) { - uint8_t* scanline = m_pBuffer + row * m_Pitch; - int gap = m_bpp / 8 - 2; - for (int col = 0; col < m_Width; col++) { - int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]); - *scanline++ = gray; - *scanline++ = gray; - *scanline = gray; - scanline += gap; - } - } - return true; - } - if (isCmykImage) { - for (int row = 0; row < m_Height; row++) { - uint8_t* scanline = m_pBuffer + row * m_Pitch; - for (int col = 0; col < m_Width; col++) { - uint8_t b, g, r; - AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3], - r, g, b); - int gray = 255 - FXRGB2GRAY(r, g, b); - *scanline++ = bc + (fc - bc) * gray / 255; - *scanline++ = bm + (fm - bm) * gray / 255; - *scanline++ = by + (fy - by) * gray / 255; - *scanline++ = bk + (fk - bk) * gray / 255; - } - } - } else { - for (int row = 0; row < m_Height; row++) { - uint8_t* scanline = m_pBuffer + row * m_Pitch; - int gap = m_bpp / 8 - 2; - for (int col = 0; col < m_Width; col++) { - int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]); - *scanline++ = bb + (fb - bb) * gray / 255; - *scanline++ = bg + (fg - bg) * gray / 255; - *scanline = br + (fr - br) * gray / 255; - scanline += gap; - } - } - } - return true; -} - -std::unique_ptr CFX_DIBSource::FlipImage(bool bXFlip, - bool bYFlip) const { - auto pFlipped = pdfium::MakeUnique(); - if (!pFlipped->Create(m_Width, m_Height, GetFormat())) - return nullptr; + while (cc < len) { + if (str[cc] == ',' || !FXSYS_isDecimalDigit(str[cc])) + break; - pFlipped->SetPalette(m_pPalette.get()); - uint8_t* pDestBuffer = pFlipped->GetBuffer(); - int Bpp = m_bpp / 8; - for (int row = 0; row < m_Height; row++) { - const uint8_t* src_scan = GetScanline(row); - uint8_t* dest_scan = - pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row); - if (!bXFlip) { - FXSYS_memcpy(dest_scan, src_scan, m_Pitch); - continue; + g = g * 10 + str[cc] - '0'; + cc++; } - if (m_bpp == 1) { - FXSYS_memset(dest_scan, 0, m_Pitch); - for (int col = 0; col < m_Width; col++) - if (src_scan[col / 8] & (1 << (7 - col % 8))) { - int dest_col = m_Width - col - 1; - dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8)); - } - } else { - dest_scan += (m_Width - 1) * Bpp; - if (Bpp == 1) { - for (int col = 0; col < m_Width; col++) { - *dest_scan = *src_scan; - dest_scan--; - src_scan++; - } - } else if (Bpp == 3) { - for (int col = 0; col < m_Width; col++) { - dest_scan[0] = src_scan[0]; - dest_scan[1] = src_scan[1]; - dest_scan[2] = src_scan[2]; - dest_scan -= 3; - src_scan += 3; - } - } else { - ASSERT(Bpp == 4); - for (int col = 0; col < m_Width; col++) { - *(uint32_t*)dest_scan = *(uint32_t*)src_scan; - dest_scan -= 4; - src_scan += 4; - } - } - } - } - if (m_pAlphaMask) { - pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer(); - uint32_t dest_pitch = pFlipped->m_pAlphaMask->GetPitch(); - for (int row = 0; row < m_Height; row++) { - const uint8_t* src_scan = m_pAlphaMask->GetScanline(row); - uint8_t* dest_scan = - pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row); - if (!bXFlip) { - FXSYS_memcpy(dest_scan, src_scan, dest_pitch); - continue; - } - dest_scan += (m_Width - 1); - for (int col = 0; col < m_Width; col++) { - *dest_scan = *src_scan; - dest_scan--; - src_scan++; - } - } - } - return pFlipped; -} + if (cc < len && str[cc] == ',') { + cc++; + while (FXSYS_iswspace(str[cc]) && cc < len) + cc++; -CFX_DIBExtractor::CFX_DIBExtractor(const CFX_DIBSource* pSrc) { - if (pSrc->GetBuffer()) { - m_pBitmap = pdfium::MakeUnique(); - if (!m_pBitmap->Create(pSrc->GetWidth(), pSrc->GetHeight(), - pSrc->GetFormat(), pSrc->GetBuffer())) { - m_pBitmap.reset(); - return; - } - m_pBitmap->SetPalette(pSrc->GetPalette()); - m_pBitmap->SetAlphaMask(pSrc->m_pAlphaMask); - } else { - m_pBitmap = pSrc->Clone(); - } -} - -CFX_DIBExtractor::~CFX_DIBExtractor() {} - -CFX_FilteredDIB::CFX_FilteredDIB() : m_pSrc(nullptr) {} - -CFX_FilteredDIB::~CFX_FilteredDIB() { - if (m_bAutoDropSrc) { - delete m_pSrc; - } -} - -void CFX_FilteredDIB::LoadSrc(const CFX_DIBSource* pSrc, bool bAutoDropSrc) { - m_pSrc = pSrc; - m_bAutoDropSrc = bAutoDropSrc; - m_Width = pSrc->GetWidth(); - m_Height = pSrc->GetHeight(); - FXDIB_Format format = GetDestFormat(); - m_bpp = (uint8_t)format; - m_AlphaFlag = (uint8_t)(format >> 8); - m_Pitch = (m_Width * (format & 0xff) + 31) / 32 * 4; - m_pPalette.reset(GetDestPalette()); - m_Scanline.resize(m_Pitch); -} - -const uint8_t* CFX_FilteredDIB::GetScanline(int line) const { - TranslateScanline(m_pSrc->GetScanline(line), &m_Scanline); - return m_Scanline.data(); -} - -void CFX_FilteredDIB::DownSampleScanline(int line, - uint8_t* dest_scan, - int dest_bpp, - int dest_width, - bool bFlipX, - int clip_left, - int clip_width) const { - m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX, - clip_left, clip_width); - TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp); -} - -CFX_ImageRenderer::CFX_ImageRenderer() { - m_Status = 0; - m_pIccTransform = nullptr; - m_bRgbByteOrder = false; - m_BlendType = FXDIB_BLEND_NORMAL; -} - -CFX_ImageRenderer::~CFX_ImageRenderer() {} - -bool CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice, - const CFX_ClipRgn* pClipRgn, - const CFX_DIBSource* pSource, - int bitmap_alpha, - uint32_t mask_color, - const CFX_Matrix* pMatrix, - uint32_t dib_flags, - bool bRgbByteOrder, - int alpha_flag, - void* pIccTransform, - int blend_type) { - m_Matrix = *pMatrix; - CFX_FloatRect image_rect_f = m_Matrix.GetUnitRect(); - FX_RECT image_rect = image_rect_f.GetOuterRect(); - m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(), - pDevice->GetHeight()); - m_ClipBox.Intersect(image_rect); - if (m_ClipBox.IsEmpty()) - return false; - - m_pDevice = pDevice; - m_pClipRgn = pClipRgn; - m_MaskColor = mask_color; - m_BitmapAlpha = bitmap_alpha; - m_Matrix = *pMatrix; - m_Flags = dib_flags; - m_AlphaFlag = alpha_flag; - m_pIccTransform = pIccTransform; - m_bRgbByteOrder = bRgbByteOrder; - m_BlendType = blend_type; - - if ((FXSYS_fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) || - (FXSYS_fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) { - if (FXSYS_fabs(m_Matrix.a) < FXSYS_fabs(m_Matrix.b) / 20 && - FXSYS_fabs(m_Matrix.d) < FXSYS_fabs(m_Matrix.c) / 20 && - FXSYS_fabs(m_Matrix.a) < 0.5f && FXSYS_fabs(m_Matrix.d) < 0.5f) { - int dest_width = image_rect.Width(); - int dest_height = image_rect.Height(); - FX_RECT bitmap_clip = m_ClipBox; - bitmap_clip.Offset(-image_rect.left, -image_rect.top); - bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height, - m_Matrix.c > 0, m_Matrix.b < 0); - m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, - true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder, - alpha_flag, pIccTransform, m_BlendType); - m_Stretcher = pdfium::MakeUnique( - &m_Composer, pSource, dest_height, dest_width, bitmap_clip, - dib_flags); - if (!m_Stretcher->Start()) - return false; - - m_Status = 1; - return true; - } - m_Status = 2; - m_pTransformer.reset( - new CFX_ImageTransformer(pSource, &m_Matrix, dib_flags, &m_ClipBox)); - m_pTransformer->Start(); - return true; - } - - int dest_width = image_rect.Width(); - if (m_Matrix.a < 0) - dest_width = -dest_width; + while (cc < len) { + if (str[cc] == ',' || !FXSYS_isDecimalDigit(str[cc])) + break; - int dest_height = image_rect.Height(); - if (m_Matrix.d > 0) - dest_height = -dest_height; - - if (dest_width == 0 || dest_height == 0) - return false; - - FX_RECT bitmap_clip = m_ClipBox; - bitmap_clip.Offset(-image_rect.left, -image_rect.top); - m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, - false, false, false, m_bRgbByteOrder, alpha_flag, - pIccTransform, m_BlendType); - m_Status = 1; - m_Stretcher = pdfium::MakeUnique( - &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags); - return m_Stretcher->Start(); -} - -bool CFX_ImageRenderer::Continue(IFX_Pause* pPause) { - if (m_Status == 1) - return m_Stretcher->Continue(pPause); - - if (m_Status == 2) { - if (m_pTransformer->Continue(pPause)) - return true; - - std::unique_ptr pBitmap(m_pTransformer->DetachBitmap()); - if (!pBitmap || !pBitmap->GetBuffer()) - return false; - - if (pBitmap->IsAlphaMask()) { - if (m_BitmapAlpha != 255) { - if (m_AlphaFlag >> 8) { - m_AlphaFlag = - (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) | - ((m_AlphaFlag >> 8) << 8)); - } else { - m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha); - } + b = b * 10 + str[cc] - '0'; + cc++; } - m_pDevice->CompositeMask( - m_pTransformer->result().left, m_pTransformer->result().top, - pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap.get(), m_MaskColor, - 0, 0, m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_AlphaFlag, - m_pIccTransform); - } else { - if (m_BitmapAlpha != 255) - pBitmap->MultiplyAlpha(m_BitmapAlpha); - m_pDevice->CompositeBitmap( - m_pTransformer->result().left, m_pTransformer->result().top, - pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap.get(), 0, 0, - m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_pIccTransform); } - return false; - } - return false; -} - -CFX_BitmapStorer::CFX_BitmapStorer() { -} - -CFX_BitmapStorer::~CFX_BitmapStorer() { -} - -std::unique_ptr CFX_BitmapStorer::Detach() { - return std::move(m_pBitmap); -} - -void CFX_BitmapStorer::Replace(std::unique_ptr pBitmap) { - m_pBitmap = std::move(pBitmap); -} - -void CFX_BitmapStorer::ComposeScanline(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha) { - uint8_t* dest_buf = const_cast(m_pBitmap->GetScanline(line)); - uint8_t* dest_alpha_buf = - m_pBitmap->m_pAlphaMask - ? const_cast(m_pBitmap->m_pAlphaMask->GetScanline(line)) - : nullptr; - if (dest_buf) - FXSYS_memcpy(dest_buf, scanline, m_pBitmap->GetPitch()); - - if (dest_alpha_buf) { - FXSYS_memcpy(dest_alpha_buf, scan_extra_alpha, - m_pBitmap->m_pAlphaMask->GetPitch()); - } -} - -bool CFX_BitmapStorer::SetInfo(int width, - int height, - FXDIB_Format src_format, - uint32_t* pSrcPalette) { - m_pBitmap = pdfium::MakeUnique(); - if (!m_pBitmap->Create(width, height, src_format)) { - m_pBitmap.reset(); - return false; } - if (pSrcPalette) - m_pBitmap->SetPalette(pSrcPalette); - return true; + return (0xff << 24) | (r << 16) | (g << 8) | b; } diff --git a/core/fxge/dib/fx_dib_transform.cpp b/core/fxge/dib/fx_dib_transform.cpp deleted file mode 100644 index bd882729413e43d279bb09b9f32aa54aa28e95ef..0000000000000000000000000000000000000000 --- a/core/fxge/dib/fx_dib_transform.cpp +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/dib/dib_int.h" - -#include -#include - -#include "core/fxge/fx_dib.h" -#include "third_party/base/ptr_util.h" - -namespace { - -uint8_t bilinear_interpol(const uint8_t* buf, - int row_offset_l, - int row_offset_r, - int src_col_l, - int src_col_r, - int res_x, - int res_y, - int bpp, - int c_offset) { - int i_resx = 255 - res_x; - int col_bpp_l = src_col_l * bpp; - int col_bpp_r = src_col_r * bpp; - const uint8_t* buf_u = buf + row_offset_l + c_offset; - const uint8_t* buf_d = buf + row_offset_r + c_offset; - const uint8_t* src_pos0 = buf_u + col_bpp_l; - const uint8_t* src_pos1 = buf_u + col_bpp_r; - const uint8_t* src_pos2 = buf_d + col_bpp_l; - const uint8_t* src_pos3 = buf_d + col_bpp_r; - uint8_t r_pos_0 = (*src_pos0 * i_resx + *src_pos1 * res_x) >> 8; - uint8_t r_pos_1 = (*src_pos2 * i_resx + *src_pos3 * res_x) >> 8; - return (r_pos_0 * (255 - res_y) + r_pos_1 * res_y) >> 8; -} - -uint8_t bicubic_interpol(const uint8_t* buf, - int pitch, - int pos_pixel[], - int u_w[], - int v_w[], - int res_x, - int res_y, - int bpp, - int c_offset) { - int s_result = 0; - for (int i = 0; i < 4; i++) { - int a_result = 0; - for (int j = 0; j < 4; j++) { - a_result += u_w[j] * (*(uint8_t*)(buf + pos_pixel[i + 4] * pitch + - pos_pixel[j] * bpp + c_offset)); - } - s_result += a_result * v_w[i]; - } - s_result >>= 16; - return (uint8_t)(s_result < 0 ? 0 : s_result > 255 ? 255 : s_result); -} - -void bicubic_get_pos_weight(int pos_pixel[], - int u_w[], - int v_w[], - int src_col_l, - int src_row_l, - int res_x, - int res_y, - int stretch_width, - int stretch_height) { - pos_pixel[0] = src_col_l - 1; - pos_pixel[1] = src_col_l; - pos_pixel[2] = src_col_l + 1; - pos_pixel[3] = src_col_l + 2; - pos_pixel[4] = src_row_l - 1; - pos_pixel[5] = src_row_l; - pos_pixel[6] = src_row_l + 1; - pos_pixel[7] = src_row_l + 2; - for (int i = 0; i < 4; i++) { - if (pos_pixel[i] < 0) { - pos_pixel[i] = 0; - } - if (pos_pixel[i] >= stretch_width) { - pos_pixel[i] = stretch_width - 1; - } - if (pos_pixel[i + 4] < 0) { - pos_pixel[i + 4] = 0; - } - if (pos_pixel[i + 4] >= stretch_height) { - pos_pixel[i + 4] = stretch_height - 1; - } - } - u_w[0] = SDP_Table[256 + res_x]; - u_w[1] = SDP_Table[res_x]; - u_w[2] = SDP_Table[256 - res_x]; - u_w[3] = SDP_Table[512 - res_x]; - v_w[0] = SDP_Table[256 + res_y]; - v_w[1] = SDP_Table[res_y]; - v_w[2] = SDP_Table[256 - res_y]; - v_w[3] = SDP_Table[512 - res_y]; -} - -FXDIB_Format GetTransformedFormat(const CFX_DIBSource* pDrc) { - FXDIB_Format format = pDrc->GetFormat(); - if (pDrc->IsAlphaMask()) { - format = FXDIB_8bppMask; - } else if (format >= 1025) { - format = FXDIB_Cmyka; - } else if (format <= 32 || format == FXDIB_Argb) { - format = FXDIB_Argb; - } else { - format = FXDIB_Rgba; - } - return format; -} - -} // namespace - -const int16_t SDP_Table[513] = { - 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255, 255, 255, 255, - 254, 254, 254, 254, 253, 253, 253, 252, 252, 252, 251, 251, 251, 250, 250, - 249, 249, 249, 248, 248, 247, 247, 246, 246, 245, 244, 244, 243, 243, 242, - 242, 241, 240, 240, 239, 238, 238, 237, 236, 236, 235, 234, 233, 233, 232, - 231, 230, 230, 229, 228, 227, 226, 226, 225, 224, 223, 222, 221, 220, 219, - 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, - 204, 203, 202, 201, 200, 199, 198, 196, 195, 194, 193, 192, 191, 190, 189, - 188, 186, 185, 184, 183, 182, 181, 179, 178, 177, 176, 175, 173, 172, 171, - 170, 169, 167, 166, 165, 164, 162, 161, 160, 159, 157, 156, 155, 154, 152, - 151, 150, 149, 147, 146, 145, 143, 142, 141, 140, 138, 137, 136, 134, 133, - 132, 130, 129, 128, 126, 125, 124, 122, 121, 120, 119, 117, 116, 115, 113, - 112, 111, 109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 95, 93, - 92, 91, 89, 88, 87, 85, 84, 83, 81, 80, 79, 77, 76, 75, 73, - 72, 71, 69, 68, 67, 66, 64, 63, 62, 60, 59, 58, 57, 55, 54, - 53, 52, 50, 49, 48, 47, 45, 44, 43, 42, 40, 39, 38, 37, 36, - 34, 33, 32, 31, 30, 28, 27, 26, 25, 24, 23, 21, 20, 19, 18, - 17, 16, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, - 1, 0, 0, -1, -2, -3, -4, -5, -6, -7, -7, -8, -9, -10, -11, - -12, -12, -13, -14, -15, -15, -16, -17, -17, -18, -19, -19, -20, -21, -21, - -22, -22, -23, -24, -24, -25, -25, -26, -26, -27, -27, -27, -28, -28, -29, - -29, -30, -30, -30, -31, -31, -31, -32, -32, -32, -33, -33, -33, -33, -34, - -34, -34, -34, -35, -35, -35, -35, -35, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -35, -35, -35, -35, -35, -35, -34, -34, -34, -34, -34, -33, -33, - -33, -33, -33, -32, -32, -32, -32, -31, -31, -31, -31, -30, -30, -30, -30, - -29, -29, -29, -29, -28, -28, -28, -27, -27, -27, -27, -26, -26, -26, -25, - -25, -25, -24, -24, -24, -23, -23, -23, -22, -22, -22, -22, -21, -21, -21, - -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16, - -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -12, -11, -11, -11, - -10, -10, -10, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -7, -6, - -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -3, -3, -3, -3, - -3, -2, -2, -2, -2, -2, -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, -}; - -class CFX_BilinearMatrix : public CPDF_FixedMatrix { - public: - CFX_BilinearMatrix(const CFX_Matrix& src, int bits) - : CPDF_FixedMatrix(src, bits) {} - inline void Transform(int x, - int y, - int& x1, - int& y1, - int& res_x, - int& res_y) { - x1 = a * x + c * y + e + base / 2; - y1 = b * x + d * y + f + base / 2; - res_x = x1 % base; - res_y = y1 % base; - if (res_x < 0 && res_x > -base) { - res_x = base + res_x; - } - if (res_y < 0 && res_x > -base) { - res_y = base + res_y; - } - x1 /= base; - y1 /= base; - } -}; - -std::unique_ptr CFX_DIBSource::SwapXY( - bool bXFlip, - bool bYFlip, - const FX_RECT* pDestClip) const { - FX_RECT dest_clip(0, 0, m_Height, m_Width); - if (pDestClip) - dest_clip.Intersect(*pDestClip); - if (dest_clip.IsEmpty()) - return nullptr; - - auto pTransBitmap = pdfium::MakeUnique(); - int result_height = dest_clip.Height(); - int result_width = dest_clip.Width(); - if (!pTransBitmap->Create(result_width, result_height, GetFormat())) - return nullptr; - - pTransBitmap->SetPalette(m_pPalette.get()); - int dest_pitch = pTransBitmap->GetPitch(); - uint8_t* dest_buf = pTransBitmap->GetBuffer(); - int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left; - int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right; - int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top; - int col_end = bYFlip ? m_Width - dest_clip.top : dest_clip.bottom; - if (GetBPP() == 1) { - FXSYS_memset(dest_buf, 0xff, dest_pitch * result_height); - for (int row = row_start; row < row_end; row++) { - const uint8_t* src_scan = GetScanline(row); - int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) - - dest_clip.left; - uint8_t* dest_scan = dest_buf; - if (bYFlip) { - dest_scan += (result_height - 1) * dest_pitch; - } - int dest_step = bYFlip ? -dest_pitch : dest_pitch; - for (int col = col_start; col < col_end; col++) { - if (!(src_scan[col / 8] & (1 << (7 - col % 8)))) { - dest_scan[dest_col / 8] &= ~(1 << (7 - dest_col % 8)); - } - dest_scan += dest_step; - } - } - } else { - int nBytes = GetBPP() / 8; - int dest_step = bYFlip ? -dest_pitch : dest_pitch; - if (nBytes == 3) { - dest_step -= 2; - } - for (int row = row_start; row < row_end; row++) { - int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) - - dest_clip.left; - uint8_t* dest_scan = dest_buf + dest_col * nBytes; - if (bYFlip) { - dest_scan += (result_height - 1) * dest_pitch; - } - if (nBytes == 4) { - uint32_t* src_scan = (uint32_t*)GetScanline(row) + col_start; - for (int col = col_start; col < col_end; col++) { - *(uint32_t*)dest_scan = *src_scan++; - dest_scan += dest_step; - } - } else { - const uint8_t* src_scan = GetScanline(row) + col_start * nBytes; - if (nBytes == 1) { - for (int col = col_start; col < col_end; col++) { - *dest_scan = *src_scan++; - dest_scan += dest_step; - } - } else { - for (int col = col_start; col < col_end; col++) { - *dest_scan++ = *src_scan++; - *dest_scan++ = *src_scan++; - *dest_scan = *src_scan++; - dest_scan += dest_step; - } - } - } - } - } - if (m_pAlphaMask) { - dest_pitch = pTransBitmap->m_pAlphaMask->GetPitch(); - dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer(); - int dest_step = bYFlip ? -dest_pitch : dest_pitch; - for (int row = row_start; row < row_end; row++) { - int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) - - dest_clip.left; - uint8_t* dest_scan = dest_buf + dest_col; - if (bYFlip) { - dest_scan += (result_height - 1) * dest_pitch; - } - const uint8_t* src_scan = m_pAlphaMask->GetScanline(row) + col_start; - for (int col = col_start; col < col_end; col++) { - *dest_scan = *src_scan++; - dest_scan += dest_step; - } - } - } - return pTransBitmap; -} - -#define FIX16_005 0.05f -FX_RECT FXDIB_SwapClipBox(FX_RECT& clip, - int width, - int height, - bool bFlipX, - bool bFlipY) { - FX_RECT rect; - if (bFlipY) { - rect.left = height - clip.top; - rect.right = height - clip.bottom; - } else { - rect.left = clip.top; - rect.right = clip.bottom; - } - if (bFlipX) { - rect.top = width - clip.left; - rect.bottom = width - clip.right; - } else { - rect.top = clip.left; - rect.bottom = clip.right; - } - rect.Normalize(); - return rect; -} - -std::unique_ptr CFX_DIBSource::TransformTo( - const CFX_Matrix* pDestMatrix, - int& result_left, - int& result_top, - uint32_t flags, - const FX_RECT* pDestClip) const { - CFX_ImageTransformer transformer(this, pDestMatrix, flags, pDestClip); - transformer.Start(); - transformer.Continue(nullptr); - result_left = transformer.result().left; - result_top = transformer.result().top; - return transformer.DetachBitmap(); -} - -std::unique_ptr CFX_DIBSource::StretchTo( - int dest_width, - int dest_height, - uint32_t flags, - const FX_RECT* pClip) const { - FX_RECT clip_rect(0, 0, FXSYS_abs(dest_width), FXSYS_abs(dest_height)); - if (pClip) - clip_rect.Intersect(*pClip); - - if (clip_rect.IsEmpty()) - return nullptr; - - if (dest_width == m_Width && dest_height == m_Height) - return Clone(&clip_rect); - - CFX_BitmapStorer storer; - CFX_ImageStretcher stretcher(&storer, this, dest_width, dest_height, - clip_rect, flags); - if (stretcher.Start()) - stretcher.Continue(nullptr); - - return storer.Detach(); -} - -CFX_ImageTransformer::CFX_ImageTransformer(const CFX_DIBSource* pSrc, - const CFX_Matrix* pMatrix, - int flags, - const FX_RECT* pClip) - : m_pSrc(pSrc), - m_pMatrix(pMatrix), - m_pClip(pClip), - m_Flags(flags), - m_Status(0) {} - -CFX_ImageTransformer::~CFX_ImageTransformer() {} - -bool CFX_ImageTransformer::Start() { - CFX_FloatRect unit_rect = m_pMatrix->GetUnitRect(); - FX_RECT result_rect = unit_rect.GetClosestRect(); - FX_RECT result_clip = result_rect; - if (m_pClip) - result_clip.Intersect(*m_pClip); - - if (result_clip.IsEmpty()) - return false; - - m_result = result_clip; - if (FXSYS_fabs(m_pMatrix->a) < FXSYS_fabs(m_pMatrix->b) / 20 && - FXSYS_fabs(m_pMatrix->d) < FXSYS_fabs(m_pMatrix->c) / 20 && - FXSYS_fabs(m_pMatrix->a) < 0.5f && FXSYS_fabs(m_pMatrix->d) < 0.5f) { - int dest_width = result_rect.Width(); - int dest_height = result_rect.Height(); - result_clip.Offset(-result_rect.left, -result_rect.top); - result_clip = FXDIB_SwapClipBox(result_clip, dest_width, dest_height, - m_pMatrix->c > 0, m_pMatrix->b < 0); - m_Stretcher = pdfium::MakeUnique( - &m_Storer, m_pSrc, dest_height, dest_width, result_clip, m_Flags); - m_Stretcher->Start(); - m_Status = 1; - return true; - } - if (FXSYS_fabs(m_pMatrix->b) < FIX16_005 && - FXSYS_fabs(m_pMatrix->c) < FIX16_005) { - int dest_width = m_pMatrix->a > 0 ? (int)FXSYS_ceil(m_pMatrix->a) - : (int)FXSYS_floor(m_pMatrix->a); - int dest_height = m_pMatrix->d > 0 ? (int)-FXSYS_ceil(m_pMatrix->d) - : (int)-FXSYS_floor(m_pMatrix->d); - result_clip.Offset(-result_rect.left, -result_rect.top); - m_Stretcher = pdfium::MakeUnique( - &m_Storer, m_pSrc, dest_width, dest_height, result_clip, m_Flags); - m_Stretcher->Start(); - m_Status = 2; - return true; - } - int stretch_width = (int)FXSYS_ceil(FXSYS_sqrt2(m_pMatrix->a, m_pMatrix->b)); - int stretch_height = (int)FXSYS_ceil(FXSYS_sqrt2(m_pMatrix->c, m_pMatrix->d)); - CFX_Matrix stretch2dest(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, - (FX_FLOAT)(stretch_height)); - stretch2dest.Concat( - CFX_Matrix(m_pMatrix->a / stretch_width, m_pMatrix->b / stretch_width, - m_pMatrix->c / stretch_height, m_pMatrix->d / stretch_height, - m_pMatrix->e, m_pMatrix->f)); - m_dest2stretch.SetReverse(stretch2dest); - - CFX_FloatRect clip_rect_f(result_clip); - m_dest2stretch.TransformRect(clip_rect_f); - m_StretchClip = clip_rect_f.GetOuterRect(); - m_StretchClip.Intersect(0, 0, stretch_width, stretch_height); - m_Stretcher = pdfium::MakeUnique( - &m_Storer, m_pSrc, stretch_width, stretch_height, m_StretchClip, m_Flags); - m_Stretcher->Start(); - m_Status = 3; - return true; -} - -bool CFX_ImageTransformer::Continue(IFX_Pause* pPause) { - if (m_Status == 1) { - if (m_Stretcher->Continue(pPause)) - return true; - - if (m_Storer.GetBitmap()) { - m_Storer.Replace( - m_Storer.GetBitmap()->SwapXY(m_pMatrix->c > 0, m_pMatrix->b < 0)); - } - return false; - } - - if (m_Status == 2) - return m_Stretcher->Continue(pPause); - - if (m_Status != 3) - return false; - - if (m_Stretcher->Continue(pPause)) - return true; - - int stretch_width = m_StretchClip.Width(); - int stretch_height = m_StretchClip.Height(); - if (!m_Storer.GetBitmap()) - return false; - - const uint8_t* stretch_buf = m_Storer.GetBitmap()->GetBuffer(); - const uint8_t* stretch_buf_mask = nullptr; - if (m_Storer.GetBitmap()->m_pAlphaMask) - stretch_buf_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetBuffer(); - - int stretch_pitch = m_Storer.GetBitmap()->GetPitch(); - std::unique_ptr pTransformed(new CFX_DIBitmap); - FXDIB_Format transformF = GetTransformedFormat(m_Stretcher->source()); - if (!pTransformed->Create(m_result.Width(), m_result.Height(), transformF)) - return false; - - pTransformed->Clear(0); - if (pTransformed->m_pAlphaMask) - pTransformed->m_pAlphaMask->Clear(0); - - CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, (FX_FLOAT)(m_result.left), - (FX_FLOAT)(m_result.top)); - result2stretch.Concat(m_dest2stretch); - result2stretch.Translate(-m_StretchClip.left, -m_StretchClip.top); - if (!stretch_buf_mask && pTransformed->m_pAlphaMask) { - pTransformed->m_pAlphaMask->Clear(0xff000000); - } else if (pTransformed->m_pAlphaMask) { - int stretch_pitch_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetPitch(); - if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos_mask = - (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 && - src_row_l <= stretch_height) { - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - int src_col_r = src_col_l + 1; - int src_row_r = src_row_l + 1; - if (src_col_r == stretch_width) { - src_col_r--; - } - if (src_row_r == stretch_height) { - src_row_r--; - } - int row_offset_l = src_row_l * stretch_pitch_mask; - int row_offset_r = src_row_r * stretch_pitch_mask; - *dest_pos_mask = - bilinear_interpol(stretch_buf_mask, row_offset_l, row_offset_r, - src_col_l, src_col_r, res_x, res_y, 1, 0); - } - dest_pos_mask++; - } - } - } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos_mask = - (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 && - src_row_l <= stretch_height) { - int pos_pixel[8]; - int u_w[4], v_w[4]; - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l, - res_x, res_y, stretch_width, stretch_height); - *dest_pos_mask = - bicubic_interpol(stretch_buf_mask, stretch_pitch_mask, - pos_pixel, u_w, v_w, res_x, res_y, 1, 0); - } - dest_pos_mask++; - } - } - } else { - CPDF_FixedMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos_mask = - (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col, src_row; - result2stretch_fix.Transform(col, row, src_col, src_row); - if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 && - src_row <= stretch_height) { - if (src_col == stretch_width) { - src_col--; - } - if (src_row == stretch_height) { - src_row--; - } - *dest_pos_mask = - stretch_buf_mask[src_row * stretch_pitch_mask + src_col]; - } - dest_pos_mask++; - } - } - } - } - if (m_Storer.GetBitmap()->IsAlphaMask()) { - if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 && - src_row_l <= stretch_height) { - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - int src_col_r = src_col_l + 1; - int src_row_r = src_row_l + 1; - if (src_col_r == stretch_width) { - src_col_r--; - } - if (src_row_r == stretch_height) { - src_row_r--; - } - int row_offset_l = src_row_l * stretch_pitch; - int row_offset_r = src_row_r * stretch_pitch; - *dest_scan = - bilinear_interpol(stretch_buf, row_offset_l, row_offset_r, - src_col_l, src_col_r, res_x, res_y, 1, 0); - } - dest_scan++; - } - } - } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 && - src_row_l <= stretch_height) { - int pos_pixel[8]; - int u_w[4], v_w[4]; - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l, - res_x, res_y, stretch_width, stretch_height); - *dest_scan = bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, - u_w, v_w, res_x, res_y, 1, 0); - } - dest_scan++; - } - } - } else { - CPDF_FixedMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col, src_row; - result2stretch_fix.Transform(col, row, src_col, src_row); - if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 && - src_row <= stretch_height) { - if (src_col == stretch_width) { - src_col--; - } - if (src_row == stretch_height) { - src_row--; - } - const uint8_t* src_pixel = - stretch_buf + stretch_pitch * src_row + src_col; - *dest_scan = *src_pixel; - } - dest_scan++; - } - } - } - } else { - int Bpp = m_Storer.GetBitmap()->GetBPP() / 8; - if (Bpp == 1) { - uint32_t argb[256]; - FX_ARGB* pPal = m_Storer.GetBitmap()->GetPalette(); - if (pPal) { - for (int i = 0; i < 256; i++) { - argb[i] = pPal[i]; - } - } else { - if (m_Storer.GetBitmap()->IsCmykImage()) { - for (int i = 0; i < 256; i++) { - argb[i] = 255 - i; - } - } else { - for (int i = 0; i < 256; i++) { - argb[i] = 0xff000000 | (i * 0x010101); - } - } - } - int destBpp = pTransformed->GetBPP() / 8; - if (!(m_Flags & FXDIB_DOWNSAMPLE) && - !(m_Flags & FXDIB_BICUBIC_INTERPOL)) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && - src_row_l >= 0 && src_row_l <= stretch_height) { - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - int src_col_r = src_col_l + 1; - int src_row_r = src_row_l + 1; - if (src_col_r == stretch_width) { - src_col_r--; - } - if (src_row_r == stretch_height) { - src_row_r--; - } - int row_offset_l = src_row_l * stretch_pitch; - int row_offset_r = src_row_r * stretch_pitch; - uint32_t r_bgra_cmyk = argb[bilinear_interpol( - stretch_buf, row_offset_l, row_offset_r, src_col_l, src_col_r, - res_x, res_y, 1, 0)]; - if (transformF == FXDIB_Rgba) { - dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24); - dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16); - dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8); - } else { - *(uint32_t*)dest_pos = r_bgra_cmyk; - } - } - dest_pos += destBpp; - } - } - } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && - src_row_l >= 0 && src_row_l <= stretch_height) { - int pos_pixel[8]; - int u_w[4], v_w[4]; - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l, - res_x, res_y, stretch_width, - stretch_height); - uint32_t r_bgra_cmyk = - argb[bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, - u_w, v_w, res_x, res_y, 1, 0)]; - if (transformF == FXDIB_Rgba) { - dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24); - dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16); - dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8); - } else { - *(uint32_t*)dest_pos = r_bgra_cmyk; - } - } - dest_pos += destBpp; - } - } - } else { - CPDF_FixedMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col, src_row; - result2stretch_fix.Transform(col, row, src_col, src_row); - if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 && - src_row <= stretch_height) { - if (src_col == stretch_width) { - src_col--; - } - if (src_row == stretch_height) { - src_row--; - } - uint32_t r_bgra_cmyk = - argb[stretch_buf[src_row * stretch_pitch + src_col]]; - if (transformF == FXDIB_Rgba) { - dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24); - dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16); - dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8); - } else { - *(uint32_t*)dest_pos = r_bgra_cmyk; - } - } - dest_pos += destBpp; - } - } - } - } else { - bool bHasAlpha = m_Storer.GetBitmap()->HasAlpha(); - int destBpp = pTransformed->GetBPP() / 8; - if (!(m_Flags & FXDIB_DOWNSAMPLE) && - !(m_Flags & FXDIB_BICUBIC_INTERPOL)) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && - src_row_l >= 0 && src_row_l <= stretch_height) { - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - int src_col_r = src_col_l + 1; - int src_row_r = src_row_l + 1; - if (src_col_r == stretch_width) { - src_col_r--; - } - if (src_row_r == stretch_height) { - src_row_r--; - } - int row_offset_l = src_row_l * stretch_pitch; - int row_offset_r = src_row_r * stretch_pitch; - uint8_t r_pos_red_y_r = - bilinear_interpol(stretch_buf, row_offset_l, row_offset_r, - src_col_l, src_col_r, res_x, res_y, Bpp, 2); - uint8_t r_pos_green_m_r = - bilinear_interpol(stretch_buf, row_offset_l, row_offset_r, - src_col_l, src_col_r, res_x, res_y, Bpp, 1); - uint8_t r_pos_blue_c_r = - bilinear_interpol(stretch_buf, row_offset_l, row_offset_r, - src_col_l, src_col_r, res_x, res_y, Bpp, 0); - if (bHasAlpha) { - if (transformF != FXDIB_Argb) { - if (transformF == FXDIB_Rgba) { - dest_pos[0] = r_pos_blue_c_r; - dest_pos[1] = r_pos_green_m_r; - dest_pos[2] = r_pos_red_y_r; - } else { - r_pos_k_r = bilinear_interpol( - stretch_buf, row_offset_l, row_offset_r, src_col_l, - src_col_r, res_x, res_y, Bpp, 3); - *(uint32_t*)dest_pos = - FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } - } else { - uint8_t r_pos_a_r = bilinear_interpol( - stretch_buf, row_offset_l, row_offset_r, src_col_l, - src_col_r, res_x, res_y, Bpp, 3); - *(uint32_t*)dest_pos = FXARGB_TODIB( - FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r, - r_pos_blue_c_r)); - } - } else { - r_pos_k_r = 0xff; - if (transformF == FXDIB_Cmyka) { - r_pos_k_r = bilinear_interpol( - stretch_buf, row_offset_l, row_offset_r, src_col_l, - src_col_r, res_x, res_y, Bpp, 3); - *(uint32_t*)dest_pos = - FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } else { - *(uint32_t*)dest_pos = FXARGB_TODIB( - FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r, - r_pos_blue_c_r)); - } - } - } - dest_pos += destBpp; - } - } - } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) { - CFX_BilinearMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0; - result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x, - res_y); - if (src_col_l >= 0 && src_col_l <= stretch_width && - src_row_l >= 0 && src_row_l <= stretch_height) { - int pos_pixel[8]; - int u_w[4], v_w[4]; - if (src_col_l == stretch_width) { - src_col_l--; - } - if (src_row_l == stretch_height) { - src_row_l--; - } - bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l, - res_x, res_y, stretch_width, - stretch_height); - uint8_t r_pos_red_y_r = - bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w, - v_w, res_x, res_y, Bpp, 2); - uint8_t r_pos_green_m_r = - bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w, - v_w, res_x, res_y, Bpp, 1); - uint8_t r_pos_blue_c_r = - bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w, - v_w, res_x, res_y, Bpp, 0); - if (bHasAlpha) { - if (transformF != FXDIB_Argb) { - if (transformF == FXDIB_Rgba) { - dest_pos[0] = r_pos_blue_c_r; - dest_pos[1] = r_pos_green_m_r; - dest_pos[2] = r_pos_red_y_r; - } else { - r_pos_k_r = - bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, - u_w, v_w, res_x, res_y, Bpp, 3); - *(uint32_t*)dest_pos = - FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } - } else { - uint8_t r_pos_a_r = - bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, - u_w, v_w, res_x, res_y, Bpp, 3); - *(uint32_t*)dest_pos = FXARGB_TODIB( - FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r, - r_pos_blue_c_r)); - } - } else { - r_pos_k_r = 0xff; - if (transformF == FXDIB_Cmyka) { - r_pos_k_r = - bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, - u_w, v_w, res_x, res_y, Bpp, 3); - *(uint32_t*)dest_pos = - FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } else { - *(uint32_t*)dest_pos = FXARGB_TODIB( - FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r, - r_pos_blue_c_r)); - } - } - } - dest_pos += destBpp; - } - } - } else { - CPDF_FixedMatrix result2stretch_fix(result2stretch, 8); - for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row); - for (int col = 0; col < m_result.Width(); col++) { - int src_col, src_row; - result2stretch_fix.Transform(col, row, src_col, src_row); - if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 && - src_row <= stretch_height) { - if (src_col == stretch_width) { - src_col--; - } - if (src_row == stretch_height) { - src_row--; - } - const uint8_t* src_pos = - stretch_buf + src_row * stretch_pitch + src_col * Bpp; - if (bHasAlpha) { - if (transformF != FXDIB_Argb) { - if (transformF == FXDIB_Rgba) { - dest_pos[0] = src_pos[0]; - dest_pos[1] = src_pos[1]; - dest_pos[2] = src_pos[2]; - } else { - *(uint32_t*)dest_pos = FXCMYK_TODIB(CmykEncode( - src_pos[0], src_pos[1], src_pos[2], src_pos[3])); - } - } else { - *(uint32_t*)dest_pos = FXARGB_TODIB(FXARGB_MAKE( - src_pos[3], src_pos[2], src_pos[1], src_pos[0])); - } - } else { - if (transformF == FXDIB_Cmyka) { - *(uint32_t*)dest_pos = FXCMYK_TODIB(CmykEncode( - src_pos[0], src_pos[1], src_pos[2], src_pos[3])); - } else { - *(uint32_t*)dest_pos = FXARGB_TODIB( - FXARGB_MAKE(0xff, src_pos[2], src_pos[1], src_pos[0])); - } - } - } - dest_pos += destBpp; - } - } - } - } - } - m_Storer.Replace(std::move(pTransformed)); - return false; -} - -std::unique_ptr CFX_ImageTransformer::DetachBitmap() { - return m_Storer.Detach(); -} diff --git a/core/fxge/dib/ifx_scanlinecomposer.h b/core/fxge/dib/ifx_scanlinecomposer.h new file mode 100644 index 0000000000000000000000000000000000000000..7b070c02ff890df2fb33f25ef4d19093d4adfc3a --- /dev/null +++ b/core/fxge/dib/ifx_scanlinecomposer.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_DIB_IFX_SCANLINECOMPOSER_H_ +#define CORE_FXGE_DIB_IFX_SCANLINECOMPOSER_H_ + +#include "core/fxge/fx_dib.h" + +class IFX_ScanlineComposer { + public: + virtual ~IFX_ScanlineComposer() {} + + virtual void ComposeScanline(int line, + const uint8_t* scanline, + const uint8_t* scan_extra_alpha) = 0; + + virtual bool SetInfo(int width, + int height, + FXDIB_Format src_format, + uint32_t* pSrcPalette) = 0; +}; + +#endif // CORE_FXGE_DIB_IFX_SCANLINECOMPOSER_H_ diff --git a/core/fxge/freetype/DEPS b/core/fxge/freetype/DEPS index 26546f7920cf74569f43c70ba4f207968acb68da..a942c2774184dc82e523e39fd2919d6ce8290461 100644 --- a/core/fxge/freetype/DEPS +++ b/core/fxge/freetype/DEPS @@ -1,3 +1,4 @@ include_rules = [ - '+third_party/freetype/src' + '+third_party/freetype/include', + '+third_party/freetype/src/src', ] diff --git a/core/fxge/freetype/fx_freetype.cpp b/core/fxge/freetype/fx_freetype.cpp index 6aa59fee68a0e89561459da9d7116cb9e7ca24bd..b0f56ab66c39ffe1cc19b6a308acca8f2932da2f 100644 --- a/core/fxge/freetype/fx_freetype.cpp +++ b/core/fxge/freetype/fx_freetype.cpp @@ -6,7 +6,7 @@ #include "core/fxge/fx_freetype.h" -#include "third_party/freetype/src/psnames/pstables.h" +#include "third_party/freetype/include/pstables.h" static int xyq_search_node(char* glyph_name, int name_offset, diff --git a/core/fxge/fx_dib.h b/core/fxge/fx_dib.h index 14be05fafe8e2bbbfcb5ae80b8909c865b8102c7..f7626afd35541fe47cad29ac6f00b262fe527b38 100644 --- a/core/fxge/fx_dib.h +++ b/core/fxge/fx_dib.h @@ -7,53 +7,56 @@ #ifndef CORE_FXGE_FX_DIB_H_ #define CORE_FXGE_FX_DIB_H_ -#include -#include +#include +#include -#include "core/fxcrt/cfx_shared_copy_on_write.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/widestring.h" enum FXDIB_Format { FXDIB_Invalid = 0, - FXDIB_1bppMask = 0x101, FXDIB_1bppRgb = 0x001, - FXDIB_1bppCmyk = 0x401, - FXDIB_8bppMask = 0x108, FXDIB_8bppRgb = 0x008, - FXDIB_8bppRgba = 0x208, - FXDIB_8bppCmyk = 0x408, - FXDIB_8bppCmyka = 0x608, FXDIB_Rgb = 0x018, - FXDIB_Rgba = 0x218, FXDIB_Rgb32 = 0x020, + FXDIB_1bppMask = 0x101, + FXDIB_8bppMask = 0x108, + FXDIB_8bppRgba = 0x208, + FXDIB_Rgba = 0x218, FXDIB_Argb = 0x220, + FXDIB_1bppCmyk = 0x401, + FXDIB_8bppCmyk = 0x408, FXDIB_Cmyk = 0x420, + FXDIB_8bppCmyka = 0x608, FXDIB_Cmyka = 0x620, }; -enum FXDIB_Channel { - FXDIB_Red = 1, - FXDIB_Green, - FXDIB_Blue, - FXDIB_Cyan, - FXDIB_Magenta, - FXDIB_Yellow, - FXDIB_Black, - FXDIB_Alpha +struct PixelWeight { + int m_SrcStart; + int m_SrcEnd; + int m_Weights[1]; }; +typedef uint32_t FX_ARGB; +typedef uint32_t FX_COLORREF; +typedef uint32_t FX_CMYK; +class CFX_ClipRgn; +class CFX_DIBSource; +class CStretchEngine; + +extern const int16_t SDP_Table[513]; + #define FXDIB_DOWNSAMPLE 0x04 #define FXDIB_INTERPOL 0x20 #define FXDIB_BICUBIC_INTERPOL 0x80 #define FXDIB_NOSMOOTH 0x100 + #define FXDIB_BLEND_NORMAL 0 #define FXDIB_BLEND_MULTIPLY 1 #define FXDIB_BLEND_SCREEN 2 #define FXDIB_BLEND_OVERLAY 3 #define FXDIB_BLEND_DARKEN 4 #define FXDIB_BLEND_LIGHTEN 5 - #define FXDIB_BLEND_COLORDODGE 6 #define FXDIB_BLEND_COLORBURN 7 #define FXDIB_BLEND_HARDLIGHT 8 @@ -66,34 +69,34 @@ enum FXDIB_Channel { #define FXDIB_BLEND_COLOR 23 #define FXDIB_BLEND_LUMINOSITY 24 #define FXDIB_BLEND_UNSUPPORTED -1 -typedef uint32_t FX_ARGB; -typedef uint32_t FX_COLORREF; -typedef uint32_t FX_CMYK; -class CFX_ClipRgn; -class CFX_DIBSource; -class CFX_DIBitmap; -class CStretchEngine; #define FXSYS_RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16)) #define FXSYS_GetRValue(rgb) ((rgb)&0xff) #define FXSYS_GetGValue(rgb) (((rgb) >> 8) & 0xff) #define FXSYS_GetBValue(rgb) (((rgb) >> 16) & 0xff) -#define FX_CCOLOR(val) (255 - (val)) -#define FXSYS_CMYK(c, m, y, k) (((c) << 24) | ((m) << 16) | ((y) << 8) | (k)) + #define FXSYS_GetCValue(cmyk) ((uint8_t)((cmyk) >> 24) & 0xff) #define FXSYS_GetMValue(cmyk) ((uint8_t)((cmyk) >> 16) & 0xff) #define FXSYS_GetYValue(cmyk) ((uint8_t)((cmyk) >> 8) & 0xff) #define FXSYS_GetKValue(cmyk) ((uint8_t)(cmyk)&0xff) -void CmykDecode(FX_CMYK cmyk, int& c, int& m, int& y, int& k); + inline FX_CMYK CmykEncode(int c, int m, int y, int k) { return (c << 24) | (m << 16) | (y << 8) | k; } -void ArgbDecode(FX_ARGB argb, int& a, int& r, int& g, int& b); -void ArgbDecode(FX_ARGB argb, int& a, FX_COLORREF& rgb); + +// Returns tuple a, r, g, b +std::tuple ArgbDecode(FX_ARGB argb); + +// Returns pair a, rgb +std::pair ArgbToColorRef(FX_ARGB argb); + inline FX_ARGB ArgbEncode(int a, int r, int g, int b) { return (a << 24) | (r << 16) | (g << 8) | b; } FX_ARGB ArgbEncode(int a, FX_COLORREF rgb); + +FX_ARGB StringToFXARGB(const WideStringView& view); + #define FXARGB_A(argb) ((uint8_t)((argb) >> 24)) #define FXARGB_R(argb) ((uint8_t)((argb) >> 16)) #define FXARGB_G(argb) ((uint8_t)((argb) >> 8)) @@ -102,21 +105,10 @@ FX_ARGB ArgbEncode(int a, FX_COLORREF rgb); (((uint32_t)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) #define FXARGB_MUL_ALPHA(argb, alpha) \ (((((argb) >> 24) * (alpha) / 255) << 24) | ((argb)&0xffffff)) + #define FXRGB2GRAY(r, g, b) (((b)*11 + (g)*59 + (r)*30) / 100) -#define FXCMYK2GRAY(c, m, y, k) \ - (((255 - (c)) * (255 - (k)) * 30 + (255 - (m)) * (255 - (k)) * 59 + \ - (255 - (y)) * (255 - (k)) * 11) / \ - 25500) #define FXDIB_ALPHA_MERGE(backdrop, source, source_alpha) \ (((backdrop) * (255 - (source_alpha)) + (source) * (source_alpha)) / 255) -#define FXDIB_ALPHA_UNION(dest, src) ((dest) + (src) - (dest) * (src) / 255) -#define FXCMYK_GETDIB(p) \ - ((((uint8_t*)(p))[0] << 24 | (((uint8_t*)(p))[1] << 16) | \ - (((uint8_t*)(p))[2] << 8) | ((uint8_t*)(p))[3])) -#define FXCMYK_SETDIB(p, cmyk) ((uint8_t*)(p))[0] = (uint8_t)((cmyk) >> 24), \ - ((uint8_t*)(p))[1] = (uint8_t)((cmyk) >> 16), \ - ((uint8_t*)(p))[2] = (uint8_t)((cmyk) >> 8), \ - ((uint8_t*)(p))[3] = (uint8_t)(cmyk)) #define FXARGB_GETDIB(p) \ ((((uint8_t*)(p))[0]) | (((uint8_t*)(p))[1] << 8) | \ (((uint8_t*)(p))[2] << 16) | (((uint8_t*)(p))[3] << 24)) @@ -125,29 +117,11 @@ FX_ARGB ArgbEncode(int a, FX_COLORREF rgb); ((uint8_t*)(p))[1] = (uint8_t)((argb) >> 8), \ ((uint8_t*)(p))[2] = (uint8_t)((argb) >> 16), \ ((uint8_t*)(p))[3] = (uint8_t)((argb) >> 24) -#define FXARGB_COPY(dest, src) \ - *(uint8_t*)(dest) = *(uint8_t*)(src), \ - *((uint8_t*)(dest) + 1) = *((uint8_t*)(src) + 1), \ - *((uint8_t*)(dest) + 2) = *((uint8_t*)(src) + 2), \ - *((uint8_t*)(dest) + 3) = *((uint8_t*)(src) + 3) -#define FXCMYK_COPY(dest, src) \ - *(uint8_t*)(dest) = *(uint8_t*)(src), \ - *((uint8_t*)(dest) + 1) = *((uint8_t*)(src) + 1), \ - *((uint8_t*)(dest) + 2) = *((uint8_t*)(src) + 2), \ - *((uint8_t*)(dest) + 3) = *((uint8_t*)(src) + 3) #define FXARGB_SETRGBORDERDIB(p, argb) \ ((uint8_t*)(p))[3] = (uint8_t)(argb >> 24), \ ((uint8_t*)(p))[0] = (uint8_t)((argb) >> 16), \ ((uint8_t*)(p))[1] = (uint8_t)((argb) >> 8), \ ((uint8_t*)(p))[2] = (uint8_t)(argb) -#define FXARGB_GETRGBORDERDIB(p) \ - (((uint8_t*)(p))[2]) | (((uint8_t*)(p))[1] << 8) | \ - (((uint8_t*)(p))[0] << 16) | (((uint8_t*)(p))[3] << 24) -#define FXARGB_RGBORDERCOPY(dest, src) \ - *((uint8_t*)(dest) + 3) = *((uint8_t*)(src) + 3), \ - *(uint8_t*)(dest) = *((uint8_t*)(src) + 2), \ - *((uint8_t*)(dest) + 1) = *((uint8_t*)(src) + 1), \ - *((uint8_t*)(dest) + 2) = *((uint8_t*)(src)) #define FXARGB_TODIB(argb) (argb) #define FXCMYK_TODIB(cmyk) \ ((uint8_t)((cmyk) >> 24) | ((uint8_t)((cmyk) >> 16)) << 8 | \ @@ -155,543 +129,11 @@ FX_ARGB ArgbEncode(int a, FX_COLORREF rgb); #define FXARGB_TOBGRORDERDIB(argb) \ ((uint8_t)(argb >> 16) | ((uint8_t)(argb >> 8)) << 8 | \ ((uint8_t)(argb)) << 16 | ((uint8_t)(argb >> 24) << 24)) -#define FXGETFLAG_COLORTYPE(flag) (uint8_t)((flag) >> 8) -#define FXGETFLAG_ALPHA_FILL(flag) (uint8_t)(flag) - -bool ConvertBuffer(FXDIB_Format dest_format, - uint8_t* dest_buf, - int dest_pitch, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top, - std::unique_ptr* pal); - -class CFX_DIBSource { - public: - virtual ~CFX_DIBSource(); - - virtual uint8_t* GetBuffer() const; - virtual const uint8_t* GetScanline(int line) const = 0; - virtual bool SkipToScanline(int line, IFX_Pause* pPause) const; - virtual void DownSampleScanline(int line, - uint8_t* dest_scan, - int dest_bpp, - int dest_width, - bool bFlipX, - int clip_left, - int clip_width) const = 0; - - int GetWidth() const { return m_Width; } - int GetHeight() const { return m_Height; } - - FXDIB_Format GetFormat() const { - return (FXDIB_Format)(m_AlphaFlag * 0x100 + m_bpp); - } - uint32_t GetPitch() const { return m_Pitch; } - uint32_t* GetPalette() const { return m_pPalette.get(); } - int GetBPP() const { return m_bpp; } - - // TODO(thestig): Investigate this. Given the possible values of FXDIB_Format, - // it feels as though this should be implemented as !!(m_AlphaFlag & 1) and - // IsOpaqueImage() below should never be able to return true. - bool IsAlphaMask() const { return m_AlphaFlag == 1; } - bool HasAlpha() const { return !!(m_AlphaFlag & 2); } - bool IsOpaqueImage() const { return !(m_AlphaFlag & 3); } - bool IsCmykImage() const { return !!(m_AlphaFlag & 4); } - - int GetPaletteSize() const { - return IsAlphaMask() ? 0 : (m_bpp == 1 ? 2 : (m_bpp == 8 ? 256 : 0)); - } - - uint32_t GetPaletteEntry(int index) const; - - void SetPaletteEntry(int index, uint32_t color); - uint32_t GetPaletteArgb(int index) const { return GetPaletteEntry(index); } - void SetPaletteArgb(int index, uint32_t color) { - SetPaletteEntry(index, color); - } - - // Copies into internally-owned palette. - void SetPalette(const uint32_t* pSrcPal); - - std::unique_ptr Clone(const FX_RECT* pClip = nullptr) const; - std::unique_ptr CloneConvert(FXDIB_Format format) const; - std::unique_ptr StretchTo(int dest_width, - int dest_height, - uint32_t flags = 0, - const FX_RECT* pClip = nullptr) const; - std::unique_ptr TransformTo( - const CFX_Matrix* pMatrix, - int& left, - int& top, - uint32_t flags = 0, - const FX_RECT* pClip = nullptr) const; - std::unique_ptr SwapXY(bool bXFlip, - bool bYFlip, - const FX_RECT* pClip = nullptr) const; - std::unique_ptr FlipImage(bool bXFlip, bool bYFlip) const; - - std::unique_ptr CloneAlphaMask( - const FX_RECT* pClip = nullptr) const; - - // Copies into internally-owned mask. - bool SetAlphaMask(const CFX_DIBSource* pAlphaMask, - const FX_RECT* pClip = nullptr); - - - void GetOverlapRect(int& dest_left, - int& dest_top, - int& width, - int& height, - int src_width, - int src_height, - int& src_left, - int& src_top, - const CFX_ClipRgn* pClipRgn); - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - void DebugVerifyBitmapIsPreMultiplied(void* buffer = nullptr) const; -#endif - - CFX_DIBitmap* m_pAlphaMask; - - protected: - CFX_DIBSource(); - - void BuildPalette(); - bool BuildAlphaMask(); - int FindPalette(uint32_t color) const; - void GetPalette(uint32_t* pal, int alpha) const; - - int m_Width; - int m_Height; - int m_bpp; - uint32_t m_AlphaFlag; - uint32_t m_Pitch; - // TODO(weili): Use std::vector for this. - std::unique_ptr m_pPalette; -}; - -class CFX_DIBitmap : public CFX_DIBSource { - public: - CFX_DIBitmap(); - explicit CFX_DIBitmap(const CFX_DIBitmap& src); - ~CFX_DIBitmap() override; - - bool Create(int width, - int height, - FXDIB_Format format, - uint8_t* pBuffer = nullptr, - int pitch = 0); - - bool Copy(const CFX_DIBSource* pSrc); - - // CFX_DIBSource - uint8_t* GetBuffer() const override; - const uint8_t* GetScanline(int line) const override; - void DownSampleScanline(int line, - uint8_t* dest_scan, - int dest_bpp, - int dest_width, - bool bFlipX, - int clip_left, - int clip_width) const override; - - void TakeOver(CFX_DIBitmap* pSrcBitmap); - - bool ConvertFormat(FXDIB_Format format); - - void Clear(uint32_t color); - - uint32_t GetPixel(int x, int y) const; - - void SetPixel(int x, int y, uint32_t color); - bool LoadChannel(FXDIB_Channel destChannel, - CFX_DIBSource* pSrcBitmap, - FXDIB_Channel srcChannel); - - bool LoadChannel(FXDIB_Channel destChannel, int value); - - bool MultiplyAlpha(int alpha); - - bool MultiplyAlpha(CFX_DIBSource* pAlphaMask); - - bool TransferBitmap(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top); - - bool CompositeBitmap(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top, - int blend_type = FXDIB_BLEND_NORMAL, - const CFX_ClipRgn* pClipRgn = nullptr, - bool bRgbByteOrder = false, - void* pIccTransform = nullptr); - - bool TransferMask(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pMask, - uint32_t color, - int src_left, - int src_top, - int alpha_flag = 0, - void* pIccTransform = nullptr); - - bool CompositeMask(int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pMask, - uint32_t color, - int src_left, - int src_top, - int blend_type = FXDIB_BLEND_NORMAL, - const CFX_ClipRgn* pClipRgn = nullptr, - bool bRgbByteOrder = false, - int alpha_flag = 0, - void* pIccTransform = nullptr); - - bool CompositeRect(int dest_left, - int dest_top, - int width, - int height, - uint32_t color, - int alpha_flag = 0, - void* pIccTransform = nullptr); - - bool ConvertColorScale(uint32_t forecolor, uint32_t backcolor); - -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ - void PreMultiply(); -#endif -#if defined _SKIA_SUPPORT_PATHS_ - void UnPreMultiply(); -#endif - - protected: - bool GetGrayData(void* pIccTransform = nullptr); - -#if defined _SKIA_SUPPORT_PATHS_ - enum class Format { kCleared, kPreMultiplied, kUnPreMultiplied }; -#endif - - uint8_t* m_pBuffer; -#if defined _SKIA_SUPPORT_PATHS_ - Format m_nFormat; -#endif - bool m_bExtBuf; -}; - -class CFX_DIBExtractor { - public: - explicit CFX_DIBExtractor(const CFX_DIBSource* pSrc); - ~CFX_DIBExtractor(); - - CFX_DIBitmap* GetBitmap() { return m_pBitmap.get(); } - - private: - std::unique_ptr m_pBitmap; -}; - -typedef CFX_SharedCopyOnWrite CFX_DIBitmapRef; - -class CFX_FilteredDIB : public CFX_DIBSource { - public: - CFX_FilteredDIB(); - ~CFX_FilteredDIB() override; - - void LoadSrc(const CFX_DIBSource* pSrc, bool bAutoDropSrc = false); - - virtual FXDIB_Format GetDestFormat() = 0; - - virtual uint32_t* GetDestPalette() = 0; - - virtual void TranslateScanline(const uint8_t* src_buf, - std::vector* dest_buf) const = 0; - - virtual void TranslateDownSamples(uint8_t* dest_buf, - const uint8_t* src_buf, - int pixels, - int Bpp) const = 0; - - protected: - // CFX_DIBSource - const uint8_t* GetScanline(int line) const override; - void DownSampleScanline(int line, - uint8_t* dest_scan, - int dest_bpp, - int dest_width, +FX_RECT FXDIB_SwapClipBox(FX_RECT& clip, + int width, + int height, bool bFlipX, - int clip_left, - int clip_width) const override; - - const CFX_DIBSource* m_pSrc; - bool m_bAutoDropSrc; - mutable std::vector m_Scanline; -}; - -class IFX_ScanlineComposer { - public: - virtual ~IFX_ScanlineComposer() {} - - virtual void ComposeScanline(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha = nullptr) = 0; - - virtual bool SetInfo(int width, - int height, - FXDIB_Format src_format, - uint32_t* pSrcPalette) = 0; -}; - -class CFX_ScanlineCompositor { - public: - CFX_ScanlineCompositor(); - - ~CFX_ScanlineCompositor(); - - bool Init(FXDIB_Format dest_format, - FXDIB_Format src_format, - int32_t width, - uint32_t* pSrcPalette, - uint32_t mask_color, - int blend_type, - bool bClip, - bool bRgbByteOrder = false, - int alpha_flag = 0, - void* pIccTransform = nullptr); - - void CompositeRgbBitmapLine(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - const uint8_t* clip_scan, - const uint8_t* src_extra_alpha = nullptr, - uint8_t* dst_extra_alpha = nullptr); - - void CompositePalBitmapLine(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - const uint8_t* clip_scan, - const uint8_t* src_extra_alpha = nullptr, - uint8_t* dst_extra_alpha = nullptr); - - void CompositeByteMaskLine(uint8_t* dest_scan, - const uint8_t* src_scan, - int width, - const uint8_t* clip_scan, - uint8_t* dst_extra_alpha = nullptr); - - void CompositeBitMaskLine(uint8_t* dest_scan, - const uint8_t* src_scan, - int src_left, - int width, - const uint8_t* clip_scan, - uint8_t* dst_extra_alpha = nullptr); - - protected: - int m_Transparency; - FXDIB_Format m_SrcFormat, m_DestFormat; - uint32_t* m_pSrcPalette; - - int m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, m_MaskBlack; - int m_BlendType; - void* m_pIccTransform; - uint8_t* m_pCacheScanline; - int m_CacheSize; - bool m_bRgbByteOrder; -}; - -class CFX_BitmapComposer : public IFX_ScanlineComposer { - public: - CFX_BitmapComposer(); - ~CFX_BitmapComposer() override; - - void Compose(CFX_DIBitmap* pDest, - const CFX_ClipRgn* pClipRgn, - int bitmap_alpha, - uint32_t mask_color, - FX_RECT& dest_rect, - bool bVertical, - bool bFlipX, - bool bFlipY, - bool bRgbByteOrder = false, - int alpha_flag = 0, - void* pIccTransform = nullptr, - int blend_type = FXDIB_BLEND_NORMAL); - - // IFX_ScanlineComposer - bool SetInfo(int width, - int height, - FXDIB_Format src_format, - uint32_t* pSrcPalette) override; - - void ComposeScanline(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha) override; - - protected: - void DoCompose(uint8_t* dest_scan, - const uint8_t* src_scan, - int dest_width, - const uint8_t* clip_scan, - const uint8_t* src_extra_alpha = nullptr, - uint8_t* dst_extra_alpha = nullptr); - CFX_DIBitmap* m_pBitmap; - const CFX_ClipRgn* m_pClipRgn; - FXDIB_Format m_SrcFormat; - int m_DestLeft, m_DestTop, m_DestWidth, m_DestHeight, m_BitmapAlpha; - uint32_t m_MaskColor; - const CFX_DIBitmap* m_pClipMask; - CFX_ScanlineCompositor m_Compositor; - bool m_bVertical, m_bFlipX, m_bFlipY; - int m_AlphaFlag; - void* m_pIccTransform; - bool m_bRgbByteOrder; - int m_BlendType; - void ComposeScanlineV(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha = nullptr); - uint8_t* m_pScanlineV; - uint8_t* m_pClipScanV; - uint8_t* m_pAddClipScan; - uint8_t* m_pScanlineAlphaV; -}; - -class CFX_BitmapStorer : public IFX_ScanlineComposer { - public: - CFX_BitmapStorer(); - ~CFX_BitmapStorer() override; - - // IFX_ScanlineComposer - void ComposeScanline(int line, - const uint8_t* scanline, - const uint8_t* scan_extra_alpha) override; - bool SetInfo(int width, - int height, - FXDIB_Format src_format, - uint32_t* pSrcPalette) override; - - CFX_DIBitmap* GetBitmap() { return m_pBitmap.get(); } - std::unique_ptr Detach(); - void Replace(std::unique_ptr pBitmap); - - private: - std::unique_ptr m_pBitmap; -}; - -class CFX_ImageStretcher { - public: - CFX_ImageStretcher(IFX_ScanlineComposer* pDest, - const CFX_DIBSource* pSource, - int dest_width, - int dest_height, - const FX_RECT& bitmap_rect, - uint32_t flags); - ~CFX_ImageStretcher(); - - bool Start(); - bool Continue(IFX_Pause* pPause); - - const CFX_DIBSource* source() { return m_pSource; } - - private: - bool StartQuickStretch(); - bool StartStretch(); - bool ContinueQuickStretch(IFX_Pause* pPause); - bool ContinueStretch(IFX_Pause* pPause); - - IFX_ScanlineComposer* const m_pDest; - const CFX_DIBSource* const m_pSource; - std::unique_ptr m_pStretchEngine; - std::unique_ptr m_pScanline; - std::unique_ptr m_pMaskScanline; - const uint32_t m_Flags; - bool m_bFlipX; - bool m_bFlipY; - int m_DestWidth; - int m_DestHeight; - FX_RECT m_ClipRect; - const FXDIB_Format m_DestFormat; - const int m_DestBPP; - int m_LineIndex; -}; - -class CFX_ImageTransformer { - public: - CFX_ImageTransformer(const CFX_DIBSource* pSrc, - const CFX_Matrix* pMatrix, - int flags, - const FX_RECT* pClip); - ~CFX_ImageTransformer(); - - bool Start(); - bool Continue(IFX_Pause* pPause); - - const FX_RECT& result() const { return m_result; } - std::unique_ptr DetachBitmap(); - - private: - const CFX_DIBSource* const m_pSrc; - const CFX_Matrix* const m_pMatrix; - const FX_RECT* const m_pClip; - FX_RECT m_StretchClip; - FX_RECT m_result; - CFX_Matrix m_dest2stretch; - std::unique_ptr m_Stretcher; - CFX_BitmapStorer m_Storer; - const uint32_t m_Flags; - int m_Status; -}; - -class CFX_ImageRenderer { - public: - CFX_ImageRenderer(); - ~CFX_ImageRenderer(); - - bool Start(CFX_DIBitmap* pDevice, - const CFX_ClipRgn* pClipRgn, - const CFX_DIBSource* pSource, - int bitmap_alpha, - uint32_t mask_color, - const CFX_Matrix* pMatrix, - uint32_t dib_flags, - bool bRgbByteOrder = false, - int alpha_flag = 0, - void* pIccTransform = nullptr, - int blend_type = FXDIB_BLEND_NORMAL); - - bool Continue(IFX_Pause* pPause); - - protected: - CFX_DIBitmap* m_pDevice; - const CFX_ClipRgn* m_pClipRgn; - int m_BitmapAlpha; - uint32_t m_MaskColor; - CFX_Matrix m_Matrix; - std::unique_ptr m_pTransformer; - std::unique_ptr m_Stretcher; - CFX_BitmapComposer m_Composer; - int m_Status; - FX_RECT m_ClipBox; - uint32_t m_Flags; - int m_AlphaFlag; - void* m_pIccTransform; - bool m_bRgbByteOrder; - int m_BlendType; -}; + bool bFlipY); #endif // CORE_FXGE_FX_DIB_H_ diff --git a/core/fxge/fx_font.h b/core/fxge/fx_font.h index 07392fa07f3d0b3b35dd3d054cb8362ffa963676..c617376757cff3866586a99c74be70eeb2092f3e 100644 --- a/core/fxge/fx_font.h +++ b/core/fxge/fx_font.h @@ -12,53 +12,30 @@ #include #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/cfx_substfont.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" #include "core/fxge/fx_freetype.h" -typedef struct FT_FaceRec_* FXFT_Face; -typedef void* FXFT_Library; - -class CFX_FaceCache; -class CFX_GlyphBitmap; -class CFX_PathData; -class CFX_SizeGlyphCache; - #if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ class SkTypeface; using CFX_TypeFace = SkTypeface; #endif -/* Character sets for the font */ -#define FXFONT_ANSI_CHARSET 0 -#define FXFONT_DEFAULT_CHARSET 1 -#define FXFONT_SYMBOL_CHARSET 2 -#define FXFONT_SHIFTJIS_CHARSET 128 -#define FXFONT_HANGUL_CHARSET 129 -#define FXFONT_GB2312_CHARSET 134 -#define FXFONT_CHINESEBIG5_CHARSET 136 -#define FXFONT_THAI_CHARSET 222 -#define FXFONT_EASTEUROPE_CHARSET 238 -#define FXFONT_RUSSIAN_CHARSET 204 -#define FXFONT_GREEK_CHARSET 161 -#define FXFONT_TURKISH_CHARSET 162 -#define FXFONT_HEBREW_CHARSET 177 -#define FXFONT_ARABIC_CHARSET 178 -#define FXFONT_BALTIC_CHARSET 186 -#define FXFONT_JOHAB_CHARSET 130 -#define FXFONT_VIETNAMESE_CHARSET 163 - /* Font pitch and family flags */ -#define FXFONT_FF_FIXEDPITCH 1 +#define FXFONT_FF_FIXEDPITCH (1 << 0) #define FXFONT_FF_ROMAN (1 << 4) #define FXFONT_FF_SCRIPT (4 << 4) /* Typical weight values */ #define FXFONT_FW_NORMAL 400 #define FXFONT_FW_BOLD 700 +#define FXFONT_FW_BOLD_BOLD 900 /* Font styles as defined in PDF 1.7 Table 5.20 */ +#define FXFONT_NORMAL (0) #define FXFONT_FIXED_PITCH (1 << 0) #define FXFONT_SERIF (1 << 1) #define FXFONT_SYMBOLIC (1 << 2) @@ -76,13 +53,6 @@ using CFX_TypeFace = SkTypeface; #define FXFONT_EXACTMATCH 0x80000000 #endif // PDF_ENABLE_XFA -#define CHARSET_FLAG_ANSI 1 -#define CHARSET_FLAG_SYMBOL 2 -#define CHARSET_FLAG_SHIFTJIS 4 -#define CHARSET_FLAG_BIG5 8 -#define CHARSET_FLAG_GB 16 -#define CHARSET_FLAG_KOREAN 32 - #define GET_TT_SHORT(w) (uint16_t)(((w)[0] << 8) | (w)[1]) #define GET_TT_LONG(w) \ (uint32_t)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) @@ -98,135 +68,21 @@ class ScopedFontTransform { FT_Face m_Face; }; -class CFX_Font { - public: - CFX_Font(); - ~CFX_Font(); - - void LoadSubst(const CFX_ByteString& face_name, - bool bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int CharsetCP, - bool bVertical); - - bool LoadEmbedded(const uint8_t* data, uint32_t size); - FXFT_Face GetFace() const { return m_Face; } - CFX_SubstFont* GetSubstFont() const { return m_pSubstFont.get(); } - -#ifdef PDF_ENABLE_XFA - bool LoadFile(const CFX_RetainPtr& pFile, - int nFaceIndex = 0, - int* pFaceCount = nullptr); - - bool LoadClone(const CFX_Font* pFont); - void SetFace(FXFT_Face face); - void SetSubstFont(std::unique_ptr subst) { - m_pSubstFont = std::move(subst); - } -#endif // PDF_ENABLE_XFA - - const CFX_GlyphBitmap* LoadGlyphBitmap(uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias, - int& text_flags) const; - const CFX_PathData* LoadGlyphPath(uint32_t glyph_index, int dest_width) const; - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - CFX_TypeFace* GetDeviceCache() const; -#endif - - int GetGlyphWidth(uint32_t glyph_index); - int GetAscent() const; - int GetDescent() const; - bool GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox); - bool IsItalic() const; - bool IsBold() const; - bool IsFixedWidth() const; - bool IsVertical() const { return m_bVertical; } - CFX_ByteString GetPsName() const; - CFX_ByteString GetFamilyName() const; - CFX_ByteString GetFaceName() const; - bool IsTTFont() const; - bool GetBBox(FX_RECT& bbox); - int GetHeight() const; - int GetULPos() const; - int GetULthickness() const; - int GetMaxAdvanceWidth() const; - bool IsEmbedded() const { return m_bEmbedded; } - uint8_t* GetSubData() const { return m_pGsubData; } - void SetSubData(uint8_t* data) { m_pGsubData = data; } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - void* GetPlatformFont() const { return m_pPlatformFont; } - void SetPlatformFont(void* font) { m_pPlatformFont = font; } -#endif - uint8_t* GetFontData() const { return m_pFontData; } - uint32_t GetSize() const { return m_dwSize; } - void AdjustMMParams(int glyph_index, int width, int weight) const; - - static const size_t kAngleSkewArraySize = 30; - static const char s_AngleSkew[kAngleSkewArraySize]; - static const size_t kWeightPowArraySize = 100; - static const uint8_t s_WeightPow[kWeightPowArraySize]; - static const uint8_t s_WeightPow_11[kWeightPowArraySize]; - static const uint8_t s_WeightPow_SHIFTJIS[kWeightPowArraySize]; - -#ifdef PDF_ENABLE_XFA - protected: - bool m_bShallowCopy; - FXFT_StreamRec* m_pOwnedStream; -#endif // PDF_ENABLE_XFA - - private: - friend class CFX_FaceCache; - CFX_PathData* LoadGlyphPathImpl(uint32_t glyph_index, - int dest_width = 0) const; - CFX_FaceCache* GetFaceCache() const; - void ReleasePlatformResource(); - void DeleteFace(); - void ClearFaceCache(); - - FXFT_Face m_Face; - mutable CFX_FaceCache* m_FaceCache; // not owned. - std::unique_ptr m_pSubstFont; - std::vector m_pFontDataAllocation; - uint8_t* m_pFontData; - uint8_t* m_pGsubData; - uint32_t m_dwSize; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - void* m_pPlatformFont; -#endif - bool m_bEmbedded; - bool m_bVertical; -}; - -class CFX_FontFaceInfo { - public: - CFX_FontFaceInfo(CFX_ByteString filePath, - CFX_ByteString faceName, - CFX_ByteString fontTables, - uint32_t fontOffset, - uint32_t fileSize); - - const CFX_ByteString m_FilePath; - const CFX_ByteString m_FaceName; - const CFX_ByteString m_FontTables; - const uint32_t m_FontOffset; - const uint32_t m_FileSize; - uint32_t m_Styles; - uint32_t m_Charsets; -}; - class CFX_GlyphBitmap { public: + CFX_GlyphBitmap(); + ~CFX_GlyphBitmap(); + int m_Top; int m_Left; - CFX_DIBitmap m_Bitmap; + RetainPtr m_pBitmap; }; +inline CFX_GlyphBitmap::CFX_GlyphBitmap() + : m_pBitmap(pdfium::MakeRetain()) {} + +inline CFX_GlyphBitmap::~CFX_GlyphBitmap() = default; + class FXTEXT_GLYPHPOS { public: FXTEXT_GLYPHPOS(); @@ -240,13 +96,48 @@ class FXTEXT_GLYPHPOS { FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, int anti_alias, - FX_FLOAT retinaScaleX = 1.0f, - FX_FLOAT retinaScaleY = 1.0f); - -CFX_ByteString GetNameFromTT(const uint8_t* name_table, - uint32_t name_table_size, - uint32_t name); - -int PDF_GetStandardFontName(CFX_ByteString* name); + float retinaScaleX, + float retinaScaleY); + +ByteString GetNameFromTT(const uint8_t* name_table, + uint32_t name_table_size, + uint32_t name); + +int PDF_GetStandardFontName(ByteString* name); + +inline bool FontStyleIsBold(uint32_t style) { + return !!(style & FXFONT_BOLD); +} +inline bool FontStyleIsItalic(uint32_t style) { + return !!(style & FXFONT_ITALIC); +} +inline bool FontStyleIsFixedPitch(uint32_t style) { + return !!(style & FXFONT_FIXED_PITCH); +} +inline bool FontStyleIsSymbolic(uint32_t style) { + return !!(style & FXFONT_SYMBOLIC); +} +inline bool FontStyleIsNonSymbolic(uint32_t style) { + return !!(style & FXFONT_NONSYMBOLIC); +} +inline bool FontStyleIsAllCaps(uint32_t style) { + return !!(style & FXFONT_ALLCAP); +} +inline bool FontStyleIsSerif(uint32_t style) { + return !!(style & FXFONT_SERIF); +} +inline bool FontStyleIsScript(uint32_t style) { + return !!(style & FXFONT_SCRIPT); +} + +inline bool FontFamilyIsFixedPitch(uint32_t family) { + return !!(family & FXFONT_FF_FIXEDPITCH); +} +inline bool FontFamilyIsRoman(uint32_t family) { + return !!(family & FXFONT_FF_ROMAN); +} +inline bool FontFamilyIsScript(int32_t family) { + return !!(family & FXFONT_FF_SCRIPT); +} #endif // CORE_FXGE_FX_FONT_H_ diff --git a/core/fxge/fx_freetype.h b/core/fxge/fx_freetype.h index 8ead6b755cc45f0d4ec63739fe42bd555ee2a711..8a5fd5dda3427afd4822b5396488cb3c17450229 100644 --- a/core/fxge/fx_freetype.h +++ b/core/fxge/fx_freetype.h @@ -15,9 +15,20 @@ #include FT_OUTLINE_H #include FT_TRUETYPE_TABLES_H -#ifdef __cplusplus -extern "C" { -#endif +using FXFT_Face = struct FT_FaceRec_*; +using FXFT_Library = void*; + +using FXFT_MM_Var = FT_MM_Var*; +using FXFT_Open_Args = FT_Open_Args; +using FXFT_StreamRec = FT_StreamRec; +using FXFT_Stream = FT_StreamRec*; +using FXFT_BBox = FT_BBox; +using FXFT_Glyph = FT_Glyph; +using FXFT_CharMap = FT_CharMap; + +using FXFT_Matrix = FT_Matrix; +using FXFT_Vector = FT_Vector; +using FXFT_Outline_Funcs = FT_Outline_Funcs; #define FXFT_ENCODING_UNICODE FT_ENCODING_UNICODE #define FXFT_ENCODING_ADOBE_STANDARD FT_ENCODING_ADOBE_STANDARD @@ -30,135 +41,142 @@ extern "C" { #define FXFT_ENCODING_BIG5 FT_ENCODING_BIG5 #define FXFT_ENCODING_SJIS FT_ENCODING_SJIS #define FXFT_ENCODING_JOHAB FT_ENCODING_JOHAB -#define FXFT_ENCODING_WANSUNG FT_ENCODING_WANSUNG + #define FXFT_LOAD_NO_SCALE FT_LOAD_NO_SCALE #define FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH \ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH +#define FXFT_LOAD_NO_BITMAP FT_LOAD_NO_BITMAP + #define FXFT_RENDER_MODE_LCD FT_RENDER_MODE_LCD #define FXFT_RENDER_MODE_MONO FT_RENDER_MODE_MONO #define FXFT_RENDER_MODE_NORMAL FT_RENDER_MODE_NORMAL -#define FXFT_LOAD_IGNORE_TRANSFORM FT_LOAD_IGNORE_TRANSFORM -#define FXFT_LOAD_NO_BITMAP FT_LOAD_NO_BITMAP -#define FXFT_LOAD_NO_HINTING FT_LOAD_NO_HINTING + #define FXFT_PIXEL_MODE_MONO FT_PIXEL_MODE_MONO + #define FXFT_STYLE_FLAG_ITALIC FT_STYLE_FLAG_ITALIC #define FXFT_STYLE_FLAG_BOLD FT_STYLE_FLAG_BOLD + #define FXFT_FACE_FLAG_SFNT FT_FACE_FLAG_SFNT #define FXFT_FACE_FLAG_TRICKY (1L << 13) -typedef FT_MM_Var* FXFT_MM_Var; -typedef FT_Bitmap* FXFT_Bitmap; -#define FXFT_Matrix FT_Matrix -#define FXFT_Vector FT_Vector -#define FXFT_Outline_Funcs FT_Outline_Funcs -typedef FT_Open_Args FXFT_Open_Args; -typedef FT_StreamRec FXFT_StreamRec; -typedef FT_StreamRec* FXFT_Stream; -typedef FT_BBox FXFT_BBox; -typedef FT_Glyph FXFT_Glyph; -typedef FT_CharMap FXFT_CharMap; + #define FXFT_GLYPH_BBOX_PIXELS FT_GLYPH_BBOX_PIXELS -#define FXFT_Open_Face(library, args, index, face) \ - FT_Open_Face((FT_Library)(library), args, index, (FT_Face*)(face)) -#define FXFT_Done_Face(face) FT_Done_Face((FT_Face)(face)) -#define FXFT_Done_FreeType(library) FT_Done_FreeType((FT_Library)(library)) -#define FXFT_Init_FreeType(library) FT_Init_FreeType((FT_Library*)(library)) -#define FXFT_New_Memory_Face(library, base, size, index, face) \ - FT_New_Memory_Face((FT_Library)(library), base, size, index, (FT_Face*)(face)) -#define FXFT_New_Face(library, filename, index, face) \ - FT_New_Face((FT_Library)(library), filename, index, (FT_Face*)(face)) -#define FXFT_Get_Face_FreeType(face) ((FT_Face)face)->driver->root.library -#define FXFT_Select_Charmap(face, encoding) \ - FT_Select_Charmap((FT_Face)face, (FT_Encoding)encoding) + +#define FXFT_Open_Face(library, args, index, face) \ + FT_Open_Face(static_cast(library), args, index, \ + static_cast(face)) +#define FXFT_Done_Face(face) FT_Done_Face(static_cast(face)) +#define FXFT_Done_FreeType(library) \ + FT_Done_FreeType(static_cast(library)) +#define FXFT_Init_FreeType(library) \ + FT_Init_FreeType(reinterpret_cast(library)) +#define FXFT_Library_Version(library, amajor, aminor, apatch) \ + FT_Library_Version(reinterpret_cast(library), amajor, aminor, \ + apatch) +#define FXFT_New_Memory_Face(library, base, size, index, face) \ + FT_New_Memory_Face(static_cast(library), base, size, index, \ + static_cast(face)) +#define FXFT_New_Face(library, filename, index, face) \ + FT_New_Face(static_cast(library), filename, index, \ + static_cast(face)) +#define FXFT_Select_Charmap(face, encoding) \ + FT_Select_Charmap(static_cast(face), \ + static_cast(encoding)) #define FXFT_Set_Charmap(face, charmap) \ - FT_Set_Charmap((FT_Face)face, (FT_CharMap)charmap) + FT_Set_Charmap(static_cast(face), static_cast(charmap)) #define FXFT_Load_Glyph(face, glyph_index, flags) \ - FT_Load_Glyph((FT_Face)face, glyph_index, flags) -#define FXFT_Get_Char_Index(face, code) FT_Get_Char_Index((FT_Face)face, code) + FT_Load_Glyph(static_cast(face), glyph_index, flags) +#define FXFT_Get_Char_Index(face, code) \ + FT_Get_Char_Index(static_cast(face), code) #define FXFT_Get_Glyph_Name(face, index, buffer, size) \ - FT_Get_Glyph_Name((FT_Face)face, index, buffer, size) -#define FXFT_Get_Name_Index(face, name) FT_Get_Name_Index((FT_Face)face, name) + FT_Get_Glyph_Name(static_cast(face), index, buffer, size) +#define FXFT_Get_Name_Index(face, name) \ + FT_Get_Name_Index(static_cast(face), name) #define FXFT_Has_Glyph_Names(face) \ - (((FT_Face)face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES) -#define FXFT_Get_Postscript_Name(face) FT_Get_Postscript_Name((FT_Face)face) + (static_cast(face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES) +#define FXFT_Get_Postscript_Name(face) \ + FT_Get_Postscript_Name(static_cast(face)) #define FXFT_Load_Sfnt_Table(face, tag, offset, buffer, length) \ - FT_Load_Sfnt_Table((FT_Face)face, tag, offset, buffer, length) + FT_Load_Sfnt_Table(static_cast(face), tag, offset, buffer, length) #define FXFT_Get_First_Char(face, glyph_index) \ - FT_Get_First_Char((FT_Face)face, glyph_index) + FT_Get_First_Char(static_cast(face), glyph_index) #define FXFT_Get_Next_Char(face, code, glyph_index) \ - FT_Get_Next_Char((FT_Face)face, code, glyph_index) + FT_Get_Next_Char(static_cast(face), code, glyph_index) #define FXFT_Clear_Face_External_Stream(face) \ - (((FT_Face)face)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM) + (static_cast(face)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM) #define FXFT_Get_Face_External_Stream(face) \ - (((FT_Face)face)->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM) + (static_cast(face)->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM) #define FXFT_Is_Face_TT_OT(face) \ - (((FT_Face)face)->face_flags & FT_FACE_FLAG_SFNT) + (static_cast(face)->face_flags & FT_FACE_FLAG_SFNT) #define FXFT_Is_Face_Tricky(face) \ - (((FT_Face)face)->face_flags & FXFT_FACE_FLAG_TRICKY) + (static_cast(face)->face_flags & FXFT_FACE_FLAG_TRICKY) #define FXFT_Is_Face_fixedwidth(face) \ - (((FT_Face)face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH) -#define FXFT_Get_Face_Stream_Base(face) ((FT_Face)face)->stream->base -#define FXFT_Get_Face_Stream_Size(face) ((FT_Face)face)->stream->size -#define FXFT_Get_Face_Family_Name(face) ((FT_Face)face)->family_name -#define FXFT_Get_Face_Style_Name(face) ((FT_Face)face)->style_name -#define FXFT_Get_Face_Numfaces(face) ((FT_Face)face)->num_faces -#define FXFT_Get_Face_Faceindex(face) ((FT_Face)face)->face_index + (static_cast(face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH) +#define FXFT_Get_Face_Stream_Base(face) static_cast(face)->stream->base +#define FXFT_Get_Face_Stream_Size(face) static_cast(face)->stream->size +#define FXFT_Get_Face_Family_Name(face) static_cast(face)->family_name +#define FXFT_Get_Face_Style_Name(face) static_cast(face)->style_name #define FXFT_Is_Face_Italic(face) \ - (((FT_Face)face)->style_flags & FT_STYLE_FLAG_ITALIC) + (static_cast(face)->style_flags & FT_STYLE_FLAG_ITALIC) #define FXFT_Is_Face_Bold(face) \ - (((FT_Face)face)->style_flags & FT_STYLE_FLAG_BOLD) -#define FXFT_Get_Face_Charmaps(face) ((FT_Face)face)->charmaps + (static_cast(face)->style_flags & FT_STYLE_FLAG_BOLD) +#define FXFT_Get_Face_Charmaps(face) static_cast(face)->charmaps #define FXFT_Get_Glyph_HoriBearingX(face) \ - ((FT_Face)face)->glyph->metrics.horiBearingX + static_cast(face)->glyph->metrics.horiBearingX #define FXFT_Get_Glyph_HoriBearingY(face) \ - ((FT_Face)face)->glyph->metrics.horiBearingY -#define FXFT_Get_Glyph_Width(face) ((FT_Face)face)->glyph->metrics.width -#define FXFT_Get_Glyph_Height(face) ((FT_Face)face)->glyph->metrics.height -#define FXFT_Get_Face_CharmapCount(face) ((FT_Face)face)->num_charmaps -#define FXFT_Get_Charmap_Encoding(charmap) ((FT_CharMap)charmap)->encoding -#define FXFT_Get_Face_Charmap(face) ((FT_Face)face)->charmap -#define FXFT_Get_Charmap_PlatformID(charmap) ((FT_CharMap)charmap)->platform_id -#define FXFT_Get_Charmap_EncodingID(charmap) ((FT_CharMap)charmap)->encoding_id -#define FXFT_Get_Face_UnitsPerEM(face) ((FT_Face)face)->units_per_EM -#define FXFT_Get_Face_xMin(face) ((FT_Face)face)->bbox.xMin -#define FXFT_Get_Face_xMax(face) ((FT_Face)face)->bbox.xMax -#define FXFT_Get_Face_yMin(face) ((FT_Face)face)->bbox.yMin -#define FXFT_Get_Face_yMax(face) ((FT_Face)face)->bbox.yMax -#define FXFT_Get_Face_Height(face) ((FT_Face)face)->height -#define FXFT_Get_Face_UnderLineThickness(face) \ - ((FT_Face)face)->underline_thickness -#define FXFT_Get_Face_UnderLinePosition(face) \ - ((FT_Face)face)->underline_position -#define FXFT_Get_Face_MaxAdvanceWidth(face) ((FT_Face)face)->max_advance_width -#define FXFT_Get_Face_Ascender(face) ((FT_Face)face)->ascender -#define FXFT_Get_Face_Descender(face) ((FT_Face)face)->descender + static_cast(face)->glyph->metrics.horiBearingY +#define FXFT_Get_Glyph_Width(face) \ + static_cast(face)->glyph->metrics.width +#define FXFT_Get_Glyph_Height(face) \ + static_cast(face)->glyph->metrics.height +#define FXFT_Get_Face_CharmapCount(face) \ + static_cast(face)->num_charmaps +#define FXFT_Get_Charmap_Encoding(charmap) \ + static_cast(charmap)->encoding +#define FXFT_Get_Face_Charmap(face) static_cast(face)->charmap +#define FXFT_Get_Charmap_PlatformID(charmap) \ + static_cast(charmap)->platform_id +#define FXFT_Get_Charmap_EncodingID(charmap) \ + static_cast(charmap)->encoding_id +#define FXFT_Get_Face_UnitsPerEM(face) static_cast(face)->units_per_EM +#define FXFT_Get_Face_xMin(face) static_cast(face)->bbox.xMin +#define FXFT_Get_Face_xMax(face) static_cast(face)->bbox.xMax +#define FXFT_Get_Face_yMin(face) static_cast(face)->bbox.yMin +#define FXFT_Get_Face_yMax(face) static_cast(face)->bbox.yMax +#define FXFT_Get_Face_Height(face) static_cast(face)->height +#define FXFT_Get_Face_Ascender(face) static_cast(face)->ascender +#define FXFT_Get_Face_Descender(face) static_cast(face)->descender #define FXFT_Get_Glyph_HoriAdvance(face) \ - ((FT_Face)face)->glyph->metrics.horiAdvance + static_cast(face)->glyph->metrics.horiAdvance #define FXFT_Get_MM_Axis(var, index) &static_cast(var)->axis[index] -#define FXFT_Get_MM_Axis_Min(axis) ((FT_Var_Axis*)axis)->minimum -#define FXFT_Get_MM_Axis_Max(axis) ((FT_Var_Axis*)axis)->maximum -#define FXFT_Get_MM_Axis_Def(axis) ((FT_Var_Axis*)axis)->def -#define FXFT_Alloc(library, size) \ - ((FT_Library)library)->memory->alloc(((FT_Library)library)->memory, size) -#define FXFT_Free(face, p) \ - ((FT_Face)face)->memory->free(((FT_Face)face)->memory, p) +#define FXFT_Get_MM_Axis_Min(axis) static_cast(axis)->minimum +#define FXFT_Get_MM_Axis_Max(axis) static_cast(axis)->maximum +#define FXFT_Get_MM_Axis_Def(axis) static_cast(axis)->def +#define FXFT_Free(face, p) \ + static_cast(face)->memory->free(static_cast(face)->memory, \ + p) #define FXFT_Get_Glyph_Outline(face) &static_cast(face)->glyph->outline -#define FXFT_Get_Outline_Bbox(outline, cbox) FT_Outline_Get_CBox(outline, cbox) -#define FXFT_Render_Glyph(face, mode) \ - FT_Render_Glyph(((FT_Face)face)->glyph, (enum FT_Render_Mode_)mode) -#define FXFT_Get_MM_Var(face, p) FT_Get_MM_Var((FT_Face)face, p) +#define FXFT_Render_Glyph(face, mode) \ + FT_Render_Glyph(static_cast(face)->glyph, \ + static_cast(mode)) +#define FXFT_Get_MM_Var(face, p) FT_Get_MM_Var(static_cast(face), p) #define FXFT_Set_MM_Design_Coordinates(face, n, p) \ - FT_Set_MM_Design_Coordinates((FT_Face)face, n, p) -#define FXFT_Set_Pixel_Sizes(face, w, h) FT_Set_Pixel_Sizes((FT_Face)face, w, h) -#define FXFT_Set_Transform(face, m, d) FT_Set_Transform((FT_Face)face, m, d) + FT_Set_MM_Design_Coordinates(static_cast(face), n, p) +#define FXFT_Set_Pixel_Sizes(face, w, h) \ + FT_Set_Pixel_Sizes(static_cast(face), w, h) +#define FXFT_Set_Transform(face, m, d) \ + FT_Set_Transform(static_cast(face), m, d) #define FXFT_Outline_Embolden(outline, s) FT_Outline_Embolden(outline, s) #define FXFT_Get_Glyph_Bitmap(face) &static_cast(face)->glyph->bitmap -#define FXFT_Get_Bitmap_Width(bitmap) ((FT_Bitmap*)bitmap)->width -#define FXFT_Get_Bitmap_Rows(bitmap) ((FT_Bitmap*)bitmap)->rows -#define FXFT_Get_Bitmap_PixelMode(bitmap) ((FT_Bitmap*)bitmap)->pixel_mode -#define FXFT_Get_Bitmap_Pitch(bitmap) ((FT_Bitmap*)bitmap)->pitch -#define FXFT_Get_Bitmap_Buffer(bitmap) ((FT_Bitmap*)bitmap)->buffer -#define FXFT_Get_Glyph_BitmapLeft(face) ((FT_Face)face)->glyph->bitmap_left -#define FXFT_Get_Glyph_BitmapTop(face) ((FT_Face)face)->glyph->bitmap_top +#define FXFT_Get_Bitmap_Width(bitmap) static_cast(bitmap)->width +#define FXFT_Get_Bitmap_Rows(bitmap) static_cast(bitmap)->rows +#define FXFT_Get_Bitmap_PixelMode(bitmap) \ + static_cast(bitmap)->pixel_mode +#define FXFT_Get_Bitmap_Pitch(bitmap) static_cast(bitmap)->pitch +#define FXFT_Get_Bitmap_Buffer(bitmap) static_cast(bitmap)->buffer +#define FXFT_Get_Glyph_BitmapLeft(face) \ + static_cast(face)->glyph->bitmap_left +#define FXFT_Get_Glyph_BitmapTop(face) \ + static_cast(face)->glyph->bitmap_top #define FXFT_Outline_Decompose(outline, funcs, params) \ FT_Outline_Decompose(outline, funcs, params) #define FXFT_Set_Char_Size(face, char_width, char_height, horz_resolution, \ @@ -170,11 +188,9 @@ typedef FT_CharMap FXFT_CharMap; FT_Glyph_Get_CBox(glyph, bbox_mode, acbox) #define FXFT_Done_Glyph(glyph) FT_Done_Glyph(glyph) #define FXFT_Library_SetLcdFilter(library, filter) \ - FT_Library_SetLcdFilter((FT_Library)(library), filter) + FT_Library_SetLcdFilter(static_cast(library), filter) + int FXFT_unicode_from_adobe_name(const char* glyph_name); void FXFT_adobe_name_from_unicode(char* name, wchar_t unicode); -#ifdef __cplusplus -}; -#endif #endif // CORE_FXGE_FX_FREETYPE_H_ diff --git a/core/fxge/fx_ge_fontmap.cpp b/core/fxge/fx_ge_fontmap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e3d8abea3a8f94a0d153047dfc12c466d256a81 --- /dev/null +++ b/core/fxge/fx_ge_fontmap.cpp @@ -0,0 +1,80 @@ +// 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 + +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/ifx_systemfontinfo.h" + +static ByteString GetStringFromTable(const uint8_t* string_ptr, + uint32_t string_ptr_length, + uint16_t offset, + uint16_t length) { + if (string_ptr_length < static_cast(offset + length)) { + return ByteString(); + } + return ByteString(string_ptr + offset, length); +} + +ByteString GetNameFromTT(const uint8_t* name_table, + uint32_t name_table_size, + uint32_t name_id) { + if (!name_table || name_table_size < 6) { + return ByteString(); + } + uint32_t name_count = GET_TT_SHORT(name_table + 2); + uint32_t string_offset = GET_TT_SHORT(name_table + 4); + // We will ignore the possibility of overlap of structures and + // string table as if it's all corrupt there's not a lot we can do. + if (name_table_size < string_offset) { + return ByteString(); + } + + const uint8_t* string_ptr = name_table + string_offset; + uint32_t string_ptr_size = name_table_size - string_offset; + name_table += 6; + name_table_size -= 6; + if (name_table_size < name_count * 12) { + return ByteString(); + } + + for (uint32_t i = 0; i < name_count; i++, name_table += 12) { + if (GET_TT_SHORT(name_table + 6) == name_id && + GET_TT_SHORT(name_table) == 1 && GET_TT_SHORT(name_table + 2) == 0) { + return GetStringFromTable(string_ptr, string_ptr_size, + GET_TT_SHORT(name_table + 10), + GET_TT_SHORT(name_table + 8)); + } + } + return ByteString(); +} +#ifdef PDF_ENABLE_XFA +void* IFX_SystemFontInfo::MapFontByUnicode(uint32_t dwUnicode, + int weight, + bool bItalic, + int pitch_family) { + return nullptr; +} +#endif // PDF_ENABLE_XFA + +int IFX_SystemFontInfo::GetFaceIndex(void* hFont) { + return 0; +} + +extern "C" { +unsigned long _FTStreamRead(FXFT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count); +void _FTStreamClose(FXFT_Stream stream); +}; + +#if _FX_OS_ == _FX_OS_ANDROID_ +std::unique_ptr IFX_SystemFontInfo::CreateDefault( + const char** pUnused) { + return nullptr; +} +#endif diff --git a/core/fxge/fx_ge_linux.cpp b/core/fxge/fx_ge_linux.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5069f332a122fca78436c0cc61aae3ff8ddd92f --- /dev/null +++ b/core/fxge/fx_ge_linux.cpp @@ -0,0 +1,163 @@ +// 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 +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_folderfontinfo.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/ifx_systemfontinfo.h" +#include "third_party/base/ptr_util.h" + +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ +namespace { + +const size_t kLinuxGpNameSize = 6; + +const char* const g_LinuxGpFontList[][kLinuxGpNameSize] = { + {"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", + "VL Gothic regular"}, + {"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", nullptr, + "VL Gothic regular"}, + {"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", nullptr, + "VL Gothic regular"}, + {"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", nullptr, + "VL Gothic regular"}, +}; + +const char* const g_LinuxGbFontList[] = { + "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN", +}; + +const char* const g_LinuxB5FontList[] = { + "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW", +}; + +const char* const g_LinuxHGFontList[] = { + "UnDotum", +}; + +size_t GetJapanesePreference(const char* facearr, + int weight, + int pitch_family) { + ByteString face = facearr; + if (face.Contains("Gothic") || + face.Contains("\x83\x53\x83\x56\x83\x62\x83\x4e")) { + if (face.Contains("PGothic") || + face.Contains("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e")) { + return 0; + } + return 1; + } + if (face.Contains("Mincho") || face.Contains("\x96\xbe\x92\xa9")) { + if (face.Contains("PMincho") || face.Contains("\x82\x6f\x96\xbe\x92\xa9")) { + return 2; + } + return 3; + } + if (!FontFamilyIsRoman(pitch_family) && weight > 400) + return 0; + + return 2; +} + +class CFX_LinuxFontInfo : public CFX_FolderFontInfo { + public: + CFX_LinuxFontInfo() {} + ~CFX_LinuxFontInfo() override {} + + void* MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family) override; + bool ParseFontCfg(const char** pUserPaths); +}; + +void* CFX_LinuxFontInfo::MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* cstr_face) { + void* font = GetSubstFont(cstr_face); + if (font) + return font; + + bool bCJK = true; + switch (charset) { + case FX_CHARSET_ShiftJIS: { + size_t index = GetJapanesePreference(cstr_face, weight, pitch_family); + ASSERT(index < FX_ArraySize(g_LinuxGpFontList)); + for (size_t i = 0; i < kLinuxGpNameSize; i++) { + auto it = m_FontList.find(g_LinuxGpFontList[index][i]); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + case FX_CHARSET_ChineseSimplified: { + for (const char* name : g_LinuxGbFontList) { + auto it = m_FontList.find(name); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + case FX_CHARSET_ChineseTraditional: { + for (const char* name : g_LinuxB5FontList) { + auto it = m_FontList.find(name); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + case FX_CHARSET_Hangul: { + for (const char* name : g_LinuxHGFontList) { + auto it = m_FontList.find(name); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + default: + bCJK = false; + break; + } + return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); +} + +bool CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) { + if (!pUserPaths) + return false; + + for (const char** pPath = pUserPaths; *pPath; ++pPath) + AddPath(*pPath); + return true; +} + +} // namespace + +std::unique_ptr IFX_SystemFontInfo::CreateDefault( + const char** pUserPaths) { + auto pInfo = pdfium::MakeUnique(); + if (!pInfo->ParseFontCfg(pUserPaths)) { + pInfo->AddPath("/usr/share/fonts"); + pInfo->AddPath("/usr/share/X11/fonts/Type1"); + pInfo->AddPath("/usr/share/X11/fonts/TTF"); + pInfo->AddPath("/usr/local/share/fonts"); + } + return std::move(pInfo); +} + +void CFX_GEModule::InitPlatform() { + m_pFontMgr->SetSystemFontInfo( + IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths)); +} + +void CFX_GEModule::DestroyPlatform() {} +#endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ diff --git a/core/fxge/ge/fx_ge_text.cpp b/core/fxge/fx_ge_text.cpp similarity index 78% rename from core/fxge/ge/fx_ge_text.cpp rename to core/fxge/fx_ge_text.cpp index 669969db0bccfdb804559f9339fbd8fdf7876f8e..147e712e571a39dd8e2bd3631be6b1c69820be30 100644 --- a/core/fxge/ge/fx_ge_text.cpp +++ b/core/fxge/fx_ge_text.cpp @@ -8,11 +8,10 @@ #include #include -#include "core/fxcodec/fx_codec.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxge/cfx_pathdata.h" +#include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" #include "core/fxge/ifx_renderdevicedriver.h" namespace { @@ -45,8 +44,8 @@ ScopedFontTransform::~ScopedFontTransform() { FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, int anti_alias, - FX_FLOAT retinaScaleX, - FX_FLOAT retinaScaleY) { + float retinaScaleX, + float retinaScaleY) { FX_RECT rect(0, 0, 0, 0); bool bStarted = false; for (const FXTEXT_GLYPHPOS& glyph : glyphs) { @@ -59,7 +58,7 @@ FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, if (!char_left.IsValid()) continue; - FX_SAFE_INT32 char_width = pGlyph->m_Bitmap.GetWidth(); + FX_SAFE_INT32 char_width = pGlyph->m_pBitmap->GetWidth(); char_width /= retinaScaleX; if (anti_alias == FXFT_RENDER_MODE_LCD) char_width /= 3; @@ -75,7 +74,7 @@ FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, if (!char_top.IsValid()) continue; - FX_SAFE_INT32 char_height = pGlyph->m_Bitmap.GetHeight(); + FX_SAFE_INT32 char_height = pGlyph->m_pBitmap->GetHeight(); char_height /= retinaScaleY; if (!char_height.IsValid()) continue; @@ -104,23 +103,3 @@ FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, } return rect; } - -CFX_SizeGlyphCache::CFX_SizeGlyphCache() {} - -CFX_SizeGlyphCache::~CFX_SizeGlyphCache() { - for (const auto& pair : m_GlyphMap) { - delete pair.second; - } - m_GlyphMap.clear(); -} - -void _CFX_UniqueKeyGen::Generate(int count, ...) { - va_list argList; - va_start(argList, count); - for (int i = 0; i < count; i++) { - int p = va_arg(argList, int); - ((uint32_t*)m_Key)[i] = p; - } - va_end(argList); - m_KeyLen = count * sizeof(uint32_t); -} diff --git a/core/fxge/ge/fx_ge_text_embeddertest.cpp b/core/fxge/fx_ge_text_embeddertest.cpp similarity index 100% rename from core/fxge/ge/fx_ge_text_embeddertest.cpp rename to core/fxge/fx_ge_text_embeddertest.cpp diff --git a/core/fxge/ge/cfx_cliprgn.cpp b/core/fxge/ge/cfx_cliprgn.cpp deleted file mode 100644 index ea3eb51f1823e9e688697571233bd944be949669..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_cliprgn.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2016 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 "core/fxge/ge/cfx_cliprgn.h" - -CFX_ClipRgn::CFX_ClipRgn(int width, int height) - : m_Type(RectI), m_Box(0, 0, width, height) {} - -CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) { - m_Type = src.m_Type; - m_Box = src.m_Box; - m_Mask = src.m_Mask; -} - -CFX_ClipRgn::~CFX_ClipRgn() {} - -void CFX_ClipRgn::Reset(const FX_RECT& rect) { - m_Type = RectI; - m_Box = rect; - m_Mask.SetNull(); -} - -void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) { - if (m_Type == RectI) { - m_Box.Intersect(rect); - return; - } - if (m_Type == MaskF) { - IntersectMaskRect(rect, m_Box, m_Mask); - return; - } -} - -void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, - FX_RECT mask_rect, - CFX_DIBitmapRef Mask) { - const CFX_DIBitmap* mask_dib = Mask.GetObject(); - m_Type = MaskF; - m_Box = rect; - m_Box.Intersect(mask_rect); - if (m_Box.IsEmpty()) { - m_Type = RectI; - return; - } - if (m_Box == mask_rect) { - m_Mask = Mask; - return; - } - CFX_DIBitmap* new_dib = m_Mask.Emplace(); - new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); - for (int row = m_Box.top; row < m_Box.bottom; row++) { - uint8_t* dest_scan = - new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top); - uint8_t* src_scan = - mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top); - for (int col = m_Box.left; col < m_Box.right; col++) - dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; - } -} - -void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) { - const CFX_DIBitmap* mask_dib = Mask.GetObject(); - ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask); - FX_RECT mask_box(left, top, left + mask_dib->GetWidth(), - top + mask_dib->GetHeight()); - if (m_Type == RectI) { - IntersectMaskRect(m_Box, mask_box, Mask); - return; - } - if (m_Type == MaskF) { - FX_RECT new_box = m_Box; - new_box.Intersect(mask_box); - if (new_box.IsEmpty()) { - m_Type = RectI; - m_Mask.SetNull(); - m_Box = new_box; - return; - } - CFX_DIBitmapRef new_mask; - CFX_DIBitmap* new_dib = new_mask.Emplace(); - new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); - const CFX_DIBitmap* old_dib = m_Mask.GetObject(); - for (int row = new_box.top; row < new_box.bottom; row++) { - uint8_t* old_scan = - old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch(); - uint8_t* mask_scan = - mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch(); - uint8_t* new_scan = - new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); - for (int col = new_box.left; col < new_box.right; col++) { - new_scan[col - new_box.left] = - old_scan[col - m_Box.left] * mask_scan[col - left] / 255; - } - } - m_Box = new_box; - m_Mask = new_mask; - return; - } - ASSERT(false); -} diff --git a/core/fxge/ge/cfx_cliprgn.h b/core/fxge/ge/cfx_cliprgn.h deleted file mode 100644 index f3fd5856b6e780c7ae4ba306d096d546911767dd..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_cliprgn.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 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 CORE_FXGE_GE_CFX_CLIPRGN_H_ -#define CORE_FXGE_GE_CFX_CLIPRGN_H_ - -#include "core/fxge/fx_dib.h" - -class CFX_ClipRgn { - public: - enum ClipType { RectI, MaskF }; - - CFX_ClipRgn(int device_width, int device_height); - CFX_ClipRgn(const CFX_ClipRgn& src); - ~CFX_ClipRgn(); - - ClipType GetType() const { return m_Type; } - const FX_RECT& GetBox() const { return m_Box; } - CFX_DIBitmapRef GetMask() const { return m_Mask; } - - void Reset(const FX_RECT& rect); - void IntersectRect(const FX_RECT& rect); - void IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask); - - private: - void IntersectMaskRect(FX_RECT rect, FX_RECT mask_box, CFX_DIBitmapRef Mask); - - ClipType m_Type; - FX_RECT m_Box; - CFX_DIBitmapRef m_Mask; -}; - -#endif // CORE_FXGE_GE_CFX_CLIPRGN_H_ diff --git a/core/fxge/ge/cfx_facecache.cpp b/core/fxge/ge/cfx_facecache.cpp deleted file mode 100644 index 314c95b8b201e582bc7266465e7931aed667286c..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_facecache.cpp +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_facecache.h" - -#include -#include -#include - -#include "core/fxge/cfx_fontmgr.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" -#include "third_party/base/numerics/safe_math.h" - -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ -#include "third_party/skia/include/core/SkStream.h" -#include "third_party/skia/include/core/SkTypeface.h" -#endif - -namespace { - -constexpr uint32_t kInvalidGlyphIndex = static_cast(-1); - -void GammaAdjust(uint8_t* pData, - int nHeight, - int src_pitch, - const uint8_t* gammaTable) { - int count = nHeight * src_pitch; - for (int i = 0; i < count; i++) - pData[i] = gammaTable[pData[i]]; -} - -void ContrastAdjust(uint8_t* pDataIn, - uint8_t* pDataOut, - int nWidth, - int nHeight, - int nSrcRowBytes, - int nDstRowBytes) { - int col, row, temp; - int max = 0, min = 255; - FX_FLOAT rate; - for (row = 0; row < nHeight; row++) { - uint8_t* pRow = pDataIn + row * nSrcRowBytes; - for (col = 0; col < nWidth; col++) { - temp = *pRow++; - max = std::max(temp, max); - min = std::min(temp, min); - } - } - temp = max - min; - if (temp == 0 || temp == 255) { - int rowbytes = std::min(FXSYS_abs(nSrcRowBytes), nDstRowBytes); - for (row = 0; row < nHeight; row++) { - FXSYS_memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, - rowbytes); - } - return; - } - rate = 255.f / temp; - for (row = 0; row < nHeight; row++) { - uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes; - uint8_t* pDstRow = pDataOut + row * nDstRowBytes; - for (col = 0; col < nWidth; col++) { - temp = static_cast((*(pSrcRow++) - min) * rate + 0.5); - temp = std::min(temp, 255); - temp = std::max(temp, 0); - *pDstRow++ = (uint8_t)temp; - } - } -} -} // namespace - -CFX_FaceCache::CFX_FaceCache(FXFT_Face face) - : m_Face(face) -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ - , - m_pTypeface(nullptr) -#endif -{ -} - -CFX_FaceCache::~CFX_FaceCache() { -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ - SkSafeUnref(m_pTypeface); -#endif -} - -CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph(const CFX_Font* pFont, - uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias) { - if (!m_Face) - return nullptr; - - FXFT_Matrix ft_matrix; - ft_matrix.xx = (signed long)(pMatrix->a / 64 * 65536); - ft_matrix.xy = (signed long)(pMatrix->c / 64 * 65536); - ft_matrix.yx = (signed long)(pMatrix->b / 64 * 65536); - ft_matrix.yy = (signed long)(pMatrix->d / 64 * 65536); - bool bUseCJKSubFont = false; - const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); - if (pSubstFont) { - bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle; - int skew = 0; - if (bUseCJKSubFont) - skew = pSubstFont->m_bItalicCJK ? -15 : 0; - else - skew = pSubstFont->m_ItalicAngle; - if (skew) { - // |skew| is nonpositive so |-skew| is used as the index. We need to make - // sure |skew| != INT_MIN since -INT_MIN is undefined. - if (skew <= 0 && skew != std::numeric_limits::min() && - static_cast(-skew) < CFX_Font::kAngleSkewArraySize) { - skew = -CFX_Font::s_AngleSkew[-skew]; - } else { - skew = -58; - } - if (pFont->IsVertical()) - ft_matrix.yx += ft_matrix.yy * skew / 100; - else - ft_matrix.xy -= ft_matrix.xx * skew / 100; - } - if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { - pFont->AdjustMMParams(glyph_index, dest_width, - pFont->GetSubstFont()->m_Weight); - } - } - ScopedFontTransform scoped_transform(m_Face, &ft_matrix); - int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) - ? FXFT_LOAD_NO_BITMAP - : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); - int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - if (error) { - // if an error is returned, try to reload glyphs without hinting. - if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) - return nullptr; - - load_flags |= FT_LOAD_NO_HINTING; - error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - - if (error) - return nullptr; - } - int weight = 0; - if (bUseCJKSubFont) - weight = pSubstFont->m_WeightCJK; - else - weight = pSubstFont ? pSubstFont->m_Weight : 0; - if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && - weight > 400) { - uint32_t index = (weight - 400) / 10; - if (index >= CFX_Font::kWeightPowArraySize) - return nullptr; - pdfium::base::CheckedNumeric level = 0; - if (pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) - level = CFX_Font::s_WeightPow_SHIFTJIS[index] * 2; - else - level = CFX_Font::s_WeightPow_11[index]; - - level = level * (FXSYS_abs(static_cast(ft_matrix.xx)) + - FXSYS_abs(static_cast(ft_matrix.xy))) / - 36655; - FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), - level.ValueOrDefault(0)); - } - FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(), - FT_LCD_FILTER_DEFAULT); - error = FXFT_Render_Glyph(m_Face, anti_alias); - if (error) - return nullptr; - int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); - int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); - if (bmwidth > 2048 || bmheight > 2048) - return nullptr; - int dib_width = bmwidth; - CFX_GlyphBitmap* pGlyphBitmap = new CFX_GlyphBitmap; - pGlyphBitmap->m_Bitmap.Create( - dib_width, bmheight, - anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); - pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); - pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); - int dest_pitch = pGlyphBitmap->m_Bitmap.GetPitch(); - int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); - uint8_t* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); - uint8_t* pSrcBuf = - (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); - if (anti_alias != FXFT_RENDER_MODE_MONO && - FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == - FXFT_PIXEL_MODE_MONO) { - int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; - for (int i = 0; i < bmheight; i++) { - for (int n = 0; n < bmwidth; n++) { - uint8_t data = - (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; - for (int b = 0; b < bytes; b++) - pDestBuf[i * dest_pitch + n * bytes + b] = data; - } - } - } else { - FXSYS_memset(pDestBuf, 0, dest_pitch * bmheight); - if (anti_alias == FXFT_RENDER_MODE_MONO && - FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == - FXFT_PIXEL_MODE_MONO) { - int rowbytes = - FXSYS_abs(src_pitch) > dest_pitch ? dest_pitch : FXSYS_abs(src_pitch); - for (int row = 0; row < bmheight; row++) { - FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, - rowbytes); - } - } else { - ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, - dest_pitch); - GammaAdjust(pDestBuf, bmheight, dest_pitch, - CFX_GEModule::Get()->GetTextGammaTable()); - } - } - return pGlyphBitmap; -} - -const CFX_PathData* CFX_FaceCache::LoadGlyphPath(const CFX_Font* pFont, - uint32_t glyph_index, - int dest_width) { - if (!m_Face || glyph_index == kInvalidGlyphIndex || dest_width < 0) - return nullptr; - - uint32_t key = glyph_index; - auto* pSubstFont = pFont->GetSubstFont(); - if (pSubstFont) { - if (pSubstFont->m_Weight < 0 || pSubstFont->m_ItalicAngle < 0) - return nullptr; - uint32_t weight = static_cast(pSubstFont->m_Weight); - uint32_t angle = static_cast(pSubstFont->m_ItalicAngle); - uint32_t key_modifier = (weight / 16) << 15; - key_modifier += (angle / 2) << 21; - key_modifier += (static_cast(dest_width) / 16) << 25; - if (pFont->IsVertical()) - key_modifier += 1U << 31; - key += key_modifier; - } - auto it = m_PathMap.find(key); - if (it != m_PathMap.end()) - return it->second.get(); - - CFX_PathData* pGlyphPath = pFont->LoadGlyphPathImpl(glyph_index, dest_width); - m_PathMap[key] = std::unique_ptr(pGlyphPath); - return pGlyphPath; -} - -const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(const CFX_Font* pFont, - uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias, - int& text_flags) { - if (glyph_index == kInvalidGlyphIndex) - return nullptr; - - _CFX_UniqueKeyGen keygen; - int nMatrixA = static_cast(pMatrix->a * 10000); - int nMatrixB = static_cast(pMatrix->b * 10000); - int nMatrixC = static_cast(pMatrix->c * 10000); - int nMatrixD = static_cast(pMatrix->d * 10000); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ - if (pFont->GetSubstFont()) { - keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); - } else { - keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias); - } -#else - if (text_flags & FXTEXT_NO_NATIVETEXT) { - if (pFont->GetSubstFont()) { - keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, - pFont->IsVertical()); - } else { - keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias); - } - } else { - if (pFont->GetSubstFont()) { - keygen.Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), - 3); - } else { - keygen.Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, 3); - } - } -#endif - CFX_ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \ - defined _SKIA_SUPPORT_PATHS_ - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, - bFontStyle, dest_width, anti_alias); -#else - if (text_flags & FXTEXT_NO_NATIVETEXT) { - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, - bFontStyle, dest_width, anti_alias); - } - CFX_GlyphBitmap* pGlyphBitmap; - auto it = m_SizeMap.find(FaceGlyphsKey); - if (it != m_SizeMap.end()) { - CFX_SizeGlyphCache* pSizeCache = it->second.get(); - auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); - if (it2 != pSizeCache->m_GlyphMap.end()) - return it2->second; - - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, - dest_width, anti_alias); - if (pGlyphBitmap) { - pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap; - return pGlyphBitmap; - } - } else { - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, - dest_width, anti_alias); - if (pGlyphBitmap) { - CFX_SizeGlyphCache* pSizeCache = new CFX_SizeGlyphCache; - m_SizeMap[FaceGlyphsKey] = - std::unique_ptr(pSizeCache); - pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap; - return pGlyphBitmap; - } - } - if (pFont->GetSubstFont()) { - keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); - } else { - keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias); - } - CFX_ByteString FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen); - text_flags |= FXTEXT_NO_NATIVETEXT; - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, - bFontStyle, dest_width, anti_alias); -#endif -} - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ -CFX_TypeFace* CFX_FaceCache::GetDeviceCache(const CFX_Font* pFont) { - if (!m_pTypeface) { - m_pTypeface = - SkTypeface::MakeFromStream( - new SkMemoryStream(pFont->GetFontData(), pFont->GetSize())) - .release(); - } - return m_pTypeface; -} -#endif - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ -void CFX_FaceCache::InitPlatform() {} -#endif - -CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap( - const CFX_Font* pFont, - const CFX_Matrix* pMatrix, - const CFX_ByteString& FaceGlyphsKey, - uint32_t glyph_index, - bool bFontStyle, - int dest_width, - int anti_alias) { - CFX_SizeGlyphCache* pSizeCache; - auto it = m_SizeMap.find(FaceGlyphsKey); - if (it == m_SizeMap.end()) { - pSizeCache = new CFX_SizeGlyphCache; - m_SizeMap[FaceGlyphsKey] = std::unique_ptr(pSizeCache); - } else { - pSizeCache = it->second.get(); - } - auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); - if (it2 != pSizeCache->m_GlyphMap.end()) - return it2->second; - - CFX_GlyphBitmap* pGlyphBitmap = RenderGlyph(pFont, glyph_index, bFontStyle, - pMatrix, dest_width, anti_alias); - pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap; - return pGlyphBitmap; -} diff --git a/core/fxge/ge/cfx_folderfontinfo.cpp b/core/fxge/ge/cfx_folderfontinfo.cpp deleted file mode 100644 index 776a37319b3cad82ce9b7bb3418bf25881cd79e4..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_folderfontinfo.cpp +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2016 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 "core/fxge/ge/cfx_folderfontinfo.h" - -#include - -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/fx_font.h" - -#include "third_party/base/stl_util.h" - -namespace { - -const struct { - const FX_CHAR* m_pName; - const FX_CHAR* m_pSubstName; -} Base14Substs[] = { - {"Courier", "Courier New"}, - {"Courier-Bold", "Courier New Bold"}, - {"Courier-BoldOblique", "Courier New Bold Italic"}, - {"Courier-Oblique", "Courier New Italic"}, - {"Helvetica", "Arial"}, - {"Helvetica-Bold", "Arial Bold"}, - {"Helvetica-BoldOblique", "Arial Bold Italic"}, - {"Helvetica-Oblique", "Arial Italic"}, - {"Times-Roman", "Times New Roman"}, - {"Times-Bold", "Times New Roman Bold"}, - {"Times-BoldItalic", "Times New Roman Bold Italic"}, - {"Times-Italic", "Times New Roman Italic"}, -}; - -CFX_ByteString FPDF_ReadStringFromFile(FXSYS_FILE* pFile, uint32_t size) { - CFX_ByteString buffer; - if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) - return CFX_ByteString(); - buffer.ReleaseBuffer(size); - return buffer; -} - -CFX_ByteString FPDF_LoadTableFromTT(FXSYS_FILE* pFile, - const uint8_t* pTables, - uint32_t nTables, - uint32_t tag) { - for (uint32_t i = 0; i < nTables; i++) { - const uint8_t* p = pTables + i * 16; - if (GET_TT_LONG(p) == tag) { - uint32_t offset = GET_TT_LONG(p + 8); - uint32_t size = GET_TT_LONG(p + 12); - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - return FPDF_ReadStringFromFile(pFile, size); - } - } - return CFX_ByteString(); -} - -uint32_t GetCharset(int charset) { - switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: - return CHARSET_FLAG_SHIFTJIS; - case FXFONT_GB2312_CHARSET: - return CHARSET_FLAG_GB; - case FXFONT_CHINESEBIG5_CHARSET: - return CHARSET_FLAG_BIG5; - case FXFONT_HANGUL_CHARSET: - return CHARSET_FLAG_KOREAN; - case FXFONT_SYMBOL_CHARSET: - return CHARSET_FLAG_SYMBOL; - case FXFONT_ANSI_CHARSET: - return CHARSET_FLAG_ANSI; - default: - break; - } - return 0; -} - -int32_t GetSimilarValue(int weight, - bool bItalic, - int pitch_family, - uint32_t style) { - int32_t iSimilarValue = 0; - if (!!(style & FXFONT_BOLD) == (weight > 400)) - iSimilarValue += 16; - if (!!(style & FXFONT_ITALIC) == bItalic) - iSimilarValue += 16; - if (!!(style & FXFONT_SERIF) == !!(pitch_family & FXFONT_FF_ROMAN)) - iSimilarValue += 16; - if (!!(style & FXFONT_SCRIPT) == !!(pitch_family & FXFONT_FF_SCRIPT)) - iSimilarValue += 8; - if (!!(style & FXFONT_FIXED_PITCH) == - !!(pitch_family & FXFONT_FF_FIXEDPITCH)) { - iSimilarValue += 8; - } - return iSimilarValue; -} - -} // namespace - -CFX_FolderFontInfo::CFX_FolderFontInfo() {} - -CFX_FolderFontInfo::~CFX_FolderFontInfo() { - for (const auto& pair : m_FontList) - delete pair.second; -} - -void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) { - m_PathList.push_back(CFX_ByteString(path)); -} - -bool CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { - m_pMapper = pMapper; - for (const auto& path : m_PathList) - ScanPath(path); - return true; -} - -void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) { - FX_FileHandle* handle = FX_OpenFolder(path.c_str()); - if (!handle) - return; - - CFX_ByteString filename; - bool bFolder; - while (FX_GetNextFile(handle, &filename, &bFolder)) { - if (bFolder) { - if (filename == "." || filename == "..") - continue; - } else { - CFX_ByteString ext = filename.Right(4); - ext.MakeUpper(); - if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") - continue; - } - - CFX_ByteString fullpath = path; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - fullpath += "\\"; -#else - fullpath += "/"; -#endif - - fullpath += filename; - bFolder ? ScanPath(fullpath) : ScanFile(fullpath); - } - FX_CloseFolder(handle); -} - -void CFX_FolderFontInfo::ScanFile(const CFX_ByteString& path) { - FXSYS_FILE* pFile = FXSYS_fopen(path.c_str(), "rb"); - if (!pFile) - return; - - FXSYS_fseek(pFile, 0, FXSYS_SEEK_END); - - uint32_t filesize = FXSYS_ftell(pFile); - uint8_t buffer[16]; - FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); - - size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); - if (readCnt != 1) { - FXSYS_fclose(pFile); - return; - } - - if (GET_TT_LONG(buffer) == kTableTTCF) { - uint32_t nFaces = GET_TT_LONG(buffer + 8); - if (nFaces > std::numeric_limits::max() / 4) { - FXSYS_fclose(pFile); - return; - } - uint32_t face_bytes = nFaces * 4; - uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); - readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile); - if (readCnt != face_bytes) { - FX_Free(offsets); - FXSYS_fclose(pFile); - return; - } - for (uint32_t i = 0; i < nFaces; i++) { - uint8_t* p = offsets + i * 4; - ReportFace(path, pFile, filesize, GET_TT_LONG(p)); - } - FX_Free(offsets); - } else { - ReportFace(path, pFile, filesize, 0); - } - FXSYS_fclose(pFile); -} - -void CFX_FolderFontInfo::ReportFace(const CFX_ByteString& path, - FXSYS_FILE* pFile, - uint32_t filesize, - uint32_t offset) { - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - char buffer[16]; - if (!FXSYS_fread(buffer, 12, 1, pFile)) - return; - - uint32_t nTables = GET_TT_SHORT(buffer + 4); - CFX_ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16); - if (tables.IsEmpty()) - return; - - CFX_ByteString names = - FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x6e616d65); - if (names.IsEmpty()) - return; - - CFX_ByteString facename = - GetNameFromTT(names.raw_str(), names.GetLength(), 1); - if (facename.IsEmpty()) - return; - - CFX_ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2); - if (style != "Regular") - facename += " " + style; - - if (pdfium::ContainsKey(m_FontList, facename)) - return; - - CFX_FontFaceInfo* pInfo = - new CFX_FontFaceInfo(path, facename, tables, offset, filesize); - CFX_ByteString os2 = - FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x4f532f32); - if (os2.GetLength() >= 86) { - const uint8_t* p = os2.raw_str() + 78; - uint32_t codepages = GET_TT_LONG(p); - if (codepages & (1 << 17)) { - m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; - } - if (codepages & (1 << 18)) { - m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_GB; - } - if (codepages & (1 << 20)) { - m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_BIG5; - } - if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { - m_pMapper->AddInstalledFont(facename, FXFONT_HANGUL_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; - } - if (codepages & (1 << 31)) { - m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; - } - } - m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_ANSI; - pInfo->m_Styles = 0; - if (style.Find("Bold") > -1) - pInfo->m_Styles |= FXFONT_BOLD; - if (style.Find("Italic") > -1 || style.Find("Oblique") > -1) - pInfo->m_Styles |= FXFONT_ITALIC; - if (facename.Find("Serif") > -1) - pInfo->m_Styles |= FXFONT_SERIF; - - m_FontList[facename] = pInfo; -} - -void* CFX_FolderFontInfo::GetSubstFont(const CFX_ByteString& face) { - for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs); - iBaseFont++) { - if (face == Base14Substs[iBaseFont].m_pName) - return GetFont(Base14Substs[iBaseFont].m_pSubstName); - } - return nullptr; -} - -void* CFX_FolderFontInfo::FindFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const FX_CHAR* family, - bool bMatchName) { - CFX_FontFaceInfo* pFind = nullptr; - if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) - return GetFont("Courier New"); - uint32_t charset_flag = GetCharset(charset); - int32_t iBestSimilar = 0; - for (const auto& it : m_FontList) { - const CFX_ByteString& bsName = it.first; - CFX_FontFaceInfo* pFont = it.second; - if (!(pFont->m_Charsets & charset_flag) && - charset != FXFONT_DEFAULT_CHARSET) { - continue; - } - int32_t index = bsName.Find(family); - if (bMatchName && index < 0) - continue; - int32_t iSimilarValue = - GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles); - if (iSimilarValue > iBestSimilar) { - iBestSimilar = iSimilarValue; - pFind = pFont; - } - } - return pFind; -} - -void* CFX_FolderFontInfo::MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const FX_CHAR* family, - int& iExact) { - return nullptr; -} - -#ifdef PDF_ENABLE_XFA -void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, - int weight, - bool bItalic, - int pitch_family) { - return nullptr; -} -#endif // PDF_ENABLE_XFA - -void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) { - auto it = m_FontList.find(face); - return it != m_FontList.end() ? it->second : nullptr; -} - -uint32_t CFX_FolderFontInfo::GetFontData(void* hFont, - uint32_t table, - uint8_t* buffer, - uint32_t size) { - if (!hFont) - return 0; - - const CFX_FontFaceInfo* pFont = static_cast(hFont); - uint32_t datasize = 0; - uint32_t offset = 0; - if (table == 0) { - datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; - } else if (table == kTableTTCF) { - datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; - } else { - uint32_t nTables = pFont->m_FontTables.GetLength() / 16; - for (uint32_t i = 0; i < nTables; i++) { - const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16; - if (GET_TT_LONG(p) == table) { - offset = GET_TT_LONG(p + 8); - datasize = GET_TT_LONG(p + 12); - } - } - } - - if (!datasize || size < datasize) - return datasize; - - FXSYS_FILE* pFile = FXSYS_fopen(pFont->m_FilePath.c_str(), "rb"); - if (!pFile) - return 0; - - if (FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET) < 0 || - FXSYS_fread(buffer, datasize, 1, pFile) != 1) { - datasize = 0; - } - FXSYS_fclose(pFile); - return datasize; -} - -void CFX_FolderFontInfo::DeleteFont(void* hFont) {} -bool CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { - if (!hFont) - return false; - CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont; - name = pFont->m_FaceName; - return true; -} - -bool CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) { - return false; -} diff --git a/core/fxge/ge/cfx_folderfontinfo.h b/core/fxge/ge/cfx_folderfontinfo.h deleted file mode 100644 index d031eef3d06a79e0843f9804c18989fe0f59c640..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_folderfontinfo.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2016 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 CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ -#define CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ - -#include -#include - -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/ifx_systemfontinfo.h" - -class CFX_FolderFontInfo : public IFX_SystemFontInfo { - public: - CFX_FolderFontInfo(); - ~CFX_FolderFontInfo() override; - - void AddPath(const CFX_ByteStringC& path); - - // IFX_SytemFontInfo: - bool EnumFontList(CFX_FontMapper* pMapper) override; - void* MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const FX_CHAR* face, - int& bExact) override; -#ifdef PDF_ENABLE_XFA - void* MapFontByUnicode(uint32_t dwUnicode, - int weight, - bool bItalic, - int pitch_family) override; -#endif // PDF_ENABLE_XFA - void* GetFont(const FX_CHAR* face) override; - uint32_t GetFontData(void* hFont, - uint32_t table, - uint8_t* buffer, - uint32_t size) override; - void DeleteFont(void* hFont) override; - bool GetFaceName(void* hFont, CFX_ByteString& name) override; - bool GetFontCharset(void* hFont, int& charset) override; - - protected: - void ScanPath(const CFX_ByteString& path); - void ScanFile(const CFX_ByteString& path); - void ReportFace(const CFX_ByteString& path, - FXSYS_FILE* pFile, - uint32_t filesize, - uint32_t offset); - void* GetSubstFont(const CFX_ByteString& face); - void* FindFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const FX_CHAR* family, - bool bMatchName); - - std::map m_FontList; - std::vector m_PathList; - CFX_FontMapper* m_pMapper; -}; - -#endif // CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ diff --git a/core/fxge/ge/cfx_fontmapper.cpp b/core/fxge/ge/cfx_fontmapper.cpp deleted file mode 100644 index 064fc9610aaecec2d9eaa43ac62ded98a3e18f05..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_fontmapper.cpp +++ /dev/null @@ -1,820 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_fontmapper.h" - -#include -#include -#include - -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/ifx_systemfontinfo.h" - -#include "third_party/base/stl_util.h" - -#define FX_FONT_STYLE_None 0x00 -#define FX_FONT_STYLE_Bold 0x01 -#define FX_FONT_STYLE_Italic 0x02 -#define FX_FONT_STYLE_BoldBold 0x04 - -namespace { - -const int kNumStandardFonts = 14; - -const FX_CHAR* const g_Base14FontNames[kNumStandardFonts] = { - "Courier", - "Courier-Bold", - "Courier-BoldOblique", - "Courier-Oblique", - "Helvetica", - "Helvetica-Bold", - "Helvetica-BoldOblique", - "Helvetica-Oblique", - "Times-Roman", - "Times-Bold", - "Times-BoldItalic", - "Times-Italic", - "Symbol", - "ZapfDingbats", -}; - -const struct AltFontName { - const FX_CHAR* m_pName; - int m_Index; -} g_AltFontNames[] = { - {"Arial", 4}, - {"Arial,Bold", 5}, - {"Arial,BoldItalic", 6}, - {"Arial,Italic", 7}, - {"Arial-Bold", 5}, - {"Arial-BoldItalic", 6}, - {"Arial-BoldItalicMT", 6}, - {"Arial-BoldMT", 5}, - {"Arial-Italic", 7}, - {"Arial-ItalicMT", 7}, - {"ArialBold", 5}, - {"ArialBoldItalic", 6}, - {"ArialItalic", 7}, - {"ArialMT", 4}, - {"ArialMT,Bold", 5}, - {"ArialMT,BoldItalic", 6}, - {"ArialMT,Italic", 7}, - {"ArialRoundedMTBold", 5}, - {"Courier", 0}, - {"Courier,Bold", 1}, - {"Courier,BoldItalic", 2}, - {"Courier,Italic", 3}, - {"Courier-Bold", 1}, - {"Courier-BoldOblique", 2}, - {"Courier-Oblique", 3}, - {"CourierBold", 1}, - {"CourierBoldItalic", 2}, - {"CourierItalic", 3}, - {"CourierNew", 0}, - {"CourierNew,Bold", 1}, - {"CourierNew,BoldItalic", 2}, - {"CourierNew,Italic", 3}, - {"CourierNew-Bold", 1}, - {"CourierNew-BoldItalic", 2}, - {"CourierNew-Italic", 3}, - {"CourierNewBold", 1}, - {"CourierNewBoldItalic", 2}, - {"CourierNewItalic", 3}, - {"CourierNewPS-BoldItalicMT", 2}, - {"CourierNewPS-BoldMT", 1}, - {"CourierNewPS-ItalicMT", 3}, - {"CourierNewPSMT", 0}, - {"CourierStd", 0}, - {"CourierStd-Bold", 1}, - {"CourierStd-BoldOblique", 2}, - {"CourierStd-Oblique", 3}, - {"Helvetica", 4}, - {"Helvetica,Bold", 5}, - {"Helvetica,BoldItalic", 6}, - {"Helvetica,Italic", 7}, - {"Helvetica-Bold", 5}, - {"Helvetica-BoldItalic", 6}, - {"Helvetica-BoldOblique", 6}, - {"Helvetica-Italic", 7}, - {"Helvetica-Oblique", 7}, - {"HelveticaBold", 5}, - {"HelveticaBoldItalic", 6}, - {"HelveticaItalic", 7}, - {"Symbol", 12}, - {"SymbolMT", 12}, - {"Times-Bold", 9}, - {"Times-BoldItalic", 10}, - {"Times-Italic", 11}, - {"Times-Roman", 8}, - {"TimesBold", 9}, - {"TimesBoldItalic", 10}, - {"TimesItalic", 11}, - {"TimesNewRoman", 8}, - {"TimesNewRoman,Bold", 9}, - {"TimesNewRoman,BoldItalic", 10}, - {"TimesNewRoman,Italic", 11}, - {"TimesNewRoman-Bold", 9}, - {"TimesNewRoman-BoldItalic", 10}, - {"TimesNewRoman-Italic", 11}, - {"TimesNewRomanBold", 9}, - {"TimesNewRomanBoldItalic", 10}, - {"TimesNewRomanItalic", 11}, - {"TimesNewRomanPS", 8}, - {"TimesNewRomanPS-Bold", 9}, - {"TimesNewRomanPS-BoldItalic", 10}, - {"TimesNewRomanPS-BoldItalicMT", 10}, - {"TimesNewRomanPS-BoldMT", 9}, - {"TimesNewRomanPS-Italic", 11}, - {"TimesNewRomanPS-ItalicMT", 11}, - {"TimesNewRomanPSMT", 8}, - {"TimesNewRomanPSMT,Bold", 9}, - {"TimesNewRomanPSMT,BoldItalic", 10}, - {"TimesNewRomanPSMT,Italic", 11}, - {"ZapfDingbats", 13}, -}; - -const struct AltFontFamily { - const FX_CHAR* m_pFontName; - const FX_CHAR* m_pFontFamily; -} g_AltFontFamilies[] = { - {"AGaramondPro", "Adobe Garamond Pro"}, - {"BankGothicBT-Medium", "BankGothic Md BT"}, - {"ForteMT", "Forte"}, -}; - -const struct FX_FontStyle { - const FX_CHAR* style; - int32_t len; -} g_FontStyles[] = { - {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7}, -}; - -const struct CODEPAGE_MAP { - uint16_t codepage; - uint8_t charset; -} g_Codepage2CharsetTable[] = { - {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, - {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, - {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, - {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, - {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, - {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, - {10081, 86}, -}; - -int CompareFontFamilyString(const void* key, const void* element) { - CFX_ByteString str_key((const FX_CHAR*)key); - const AltFontFamily* family = reinterpret_cast(element); - if (str_key.Find(family->m_pFontName) != -1) - return 0; - return FXSYS_stricmp(reinterpret_cast(key), - family->m_pFontName); -} - -int CompareString(const void* key, const void* element) { - return FXSYS_stricmp(reinterpret_cast(key), - reinterpret_cast(element)->m_pName); -} - -CFX_ByteString TT_NormalizeName(const FX_CHAR* family) { - CFX_ByteString norm(family); - norm.Remove(' '); - norm.Remove('-'); - norm.Remove(','); - int pos = norm.Find('+'); - if (pos > 0) - norm = norm.Left(pos); - norm.MakeLower(); - return norm; -} - -uint8_t GetCharsetFromCodePage(uint16_t codepage) { - const CODEPAGE_MAP* pEnd = - g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); - const CODEPAGE_MAP* pCharmap = - std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, - [](const CODEPAGE_MAP& charset, uint16_t page) { - return charset.codepage < page; - }); - if (pCharmap < pEnd && codepage == pCharmap->codepage) - return pCharmap->charset; - return FXFONT_DEFAULT_CHARSET; -} - -CFX_ByteString GetFontFamily(CFX_ByteString fontName, int nStyle) { - if (fontName.Find("Script") >= 0) { - if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) - fontName = "ScriptMTBold"; - else if (fontName.Find("Palace") >= 0) - fontName = "PalaceScriptMT"; - else if (fontName.Find("French") >= 0) - fontName = "FrenchScriptMT"; - else if (fontName.Find("FreeStyle") >= 0) - fontName = "FreeStyleScript"; - return fontName; - } - AltFontFamily* found = reinterpret_cast(FXSYS_bsearch( - fontName.c_str(), g_AltFontFamilies, FX_ArraySize(g_AltFontFamilies), - sizeof(AltFontFamily), CompareFontFamilyString)); - return found ? CFX_ByteString(found->m_pFontFamily) : fontName; -} - -CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) { - CFX_ByteTextBuf buf; - if (!iLen || iLen <= iIndex) - return buf.MakeString(); - while (iIndex < iLen) { - if (pStyle[iIndex] == ',') - break; - buf.AppendChar(pStyle[iIndex]); - ++iIndex; - } - return buf.MakeString(); -} - -int32_t GetStyleType(const CFX_ByteString& bsStyle, bool bReverse) { - int32_t iLen = bsStyle.GetLength(); - if (!iLen) - return -1; - int iSize = FX_ArraySize(g_FontStyles); - const FX_FontStyle* pStyle = nullptr; - for (int i = iSize - 1; i >= 0; --i) { - pStyle = g_FontStyles + i; - if (!pStyle || pStyle->len > iLen) - continue; - - if (bReverse) { - if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) - return i; - } else { - if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) - return i; - } - } - return -1; -} - -bool CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) { - if (name == "MyriadPro") { - PitchFamily &= ~FXFONT_FF_ROMAN; - return true; - } - return false; -} - -void UpdatePitchFamily(uint32_t flags, int& PitchFamily) { - if (flags & FXFONT_SERIF) - PitchFamily |= FXFONT_FF_ROMAN; - if (flags & FXFONT_SCRIPT) - PitchFamily |= FXFONT_FF_SCRIPT; - if (flags & FXFONT_FIXED_PITCH) - PitchFamily |= FXFONT_FF_FIXEDPITCH; -} - -} // namespace - -CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) - : m_bListLoaded(false), m_pFontMgr(mgr) { - m_MMFaces[0] = nullptr; - m_MMFaces[1] = nullptr; - FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); -} - -CFX_FontMapper::~CFX_FontMapper() { - for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { - if (m_FoxitFaces[i]) - FXFT_Done_Face(m_FoxitFaces[i]); - } - if (m_MMFaces[0]) - FXFT_Done_Face(m_MMFaces[0]); - if (m_MMFaces[1]) - FXFT_Done_Face(m_MMFaces[1]); -} - -void CFX_FontMapper::SetSystemFontInfo( - std::unique_ptr pFontInfo) { - if (!pFontInfo) - return; - - m_pFontInfo = std::move(pFontInfo); -} - -CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { - if (!m_pFontInfo) - return CFX_ByteString(); - - uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); - if (!size) - return CFX_ByteString(); - - std::vector buffer(size); - uint8_t* buffer_ptr = buffer.data(); - uint32_t bytes_read = - m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); - return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) - : CFX_ByteString(); -} - -void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { - if (!m_pFontInfo) - return; - - m_FaceArray.push_back({name, static_cast(charset)}); - if (name == m_LastFamily) - return; - - const uint8_t* ptr = name.raw_str(); - bool bLocalized = false; - for (int i = 0; i < name.GetLength(); i++) { - if (ptr[i] > 0x80) { - bLocalized = true; - break; - } - } - - if (bLocalized) { - void* hFont = m_pFontInfo->GetFont(name.c_str()); - if (!hFont) { - int iExact; - hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, - name.c_str(), iExact); - if (!hFont) - return; - } - - CFX_ByteString new_name = GetPSNameFromTT(hFont); - if (!new_name.IsEmpty()) - m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); - m_pFontInfo->DeleteFont(hFont); - } - m_InstalledTTFonts.push_back(name); - m_LastFamily = name; -} - -void CFX_FontMapper::LoadInstalledFonts() { - if (!m_pFontInfo || m_bListLoaded) - return; - - m_pFontInfo->EnumFontList(this); - m_bListLoaded = true; -} - -CFX_ByteString CFX_FontMapper::MatchInstalledFonts( - const CFX_ByteString& norm_name) { - LoadInstalledFonts(); - int i; - for (i = pdfium::CollectionSize(m_InstalledTTFonts) - 1; i >= 0; i--) { - CFX_ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); - if (norm1 == norm_name) - return m_InstalledTTFonts[i]; - } - for (i = pdfium::CollectionSize(m_LocalizedTTFonts) - 1; i >= 0; i--) { - CFX_ByteString norm1 = - TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str()); - if (norm1 == norm_name) - return m_LocalizedTTFonts[i].second; - } - return CFX_ByteString(); -} - -FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, - int iBaseFont, - int italic_angle, - int weight, - int picthfamily) { - if (iBaseFont < kNumStandardFonts) { - if (m_FoxitFaces[iBaseFont]) - return m_FoxitFaces[iBaseFont]; - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { - m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[iBaseFont]; - } - } - pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; - pSubstFont->m_ItalicAngle = italic_angle; - if (weight) - pSubstFont->m_Weight = weight; - if (picthfamily & FXFONT_FF_ROMAN) { - pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; - pSubstFont->m_Family = "Chrome Serif"; - if (m_MMFaces[1]) - return m_MMFaces[1]; - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); - m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[1]; - } - pSubstFont->m_Family = "Chrome Sans"; - if (m_MMFaces[0]) - return m_MMFaces[0]; - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); - m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[0]; -} - -FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, - bool bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int WindowCP, - CFX_SubstFont* pSubstFont) { - if (!(flags & FXFONT_USEEXTERNATTR)) { - weight = FXFONT_FW_NORMAL; - italic_angle = 0; - } - CFX_ByteString SubstName = name; - SubstName.Remove(' '); - if (bTrueType && name[0] == '@') - SubstName = name.Mid(1); - PDF_GetStandardFontName(&SubstName); - if (SubstName == "Symbol" && !bTrueType) { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0); - } - if (SubstName == "ZapfDingbats") { - pSubstFont->m_Family = "Chrome Dingbats"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0); - } - int iBaseFont = 0; - CFX_ByteString family; - CFX_ByteString style; - bool bHasComma = false; - bool bHasHyphen = false; - int find = SubstName.Find(",", 0); - if (find >= 0) { - family = SubstName.Left(find); - PDF_GetStandardFontName(&family); - style = SubstName.Mid(find + 1); - bHasComma = true; - } else { - family = SubstName; - } - for (; iBaseFont < 12; iBaseFont++) { - if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) - break; - } - int PitchFamily = 0; - bool bItalic = false; - uint32_t nStyle = 0; - bool bStyleAvail = false; - if (iBaseFont < 12) { - if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) - nStyle |= FX_FONT_STYLE_Bold; - if ((iBaseFont % 4) / 2) - nStyle |= FX_FONT_STYLE_Italic; - if (iBaseFont < 4) - PitchFamily |= FXFONT_FF_FIXEDPITCH; - if (iBaseFont >= 8) - PitchFamily |= FXFONT_FF_ROMAN; - } else { - iBaseFont = kNumStandardFonts; - if (!bHasComma) { - find = family.ReverseFind('-'); - if (find >= 0) { - style = family.Mid(find + 1); - family = family.Left(find); - bHasHyphen = true; - } - } - if (!bHasHyphen) { - int nLen = family.GetLength(); - int32_t nRet = GetStyleType(family, true); - if (nRet > -1) { - family = family.Left(nLen - g_FontStyles[nRet].len); - if (nRet == 0) - nStyle |= FX_FONT_STYLE_Bold; - else if (nRet == 1) - nStyle |= FX_FONT_STYLE_Italic; - else if (nRet == 2) - nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); - } - } - UpdatePitchFamily(flags, PitchFamily); - } - if (!style.IsEmpty()) { - int nLen = style.GetLength(); - const FX_CHAR* pStyle = style.c_str(); - int i = 0; - bool bFirstItem = true; - CFX_ByteString buf; - while (i < nLen) { - buf = ParseStyle(pStyle, nLen, i); - int32_t nRet = GetStyleType(buf, false); - if ((i && !bStyleAvail) || (!i && nRet < 0)) { - family = SubstName; - iBaseFont = kNumStandardFonts; - break; - } - if (nRet >= 0) { - bStyleAvail = true; - } - if (nRet == 1) { - if (bFirstItem) { - nStyle |= FX_FONT_STYLE_Italic; - } else { - family = SubstName; - iBaseFont = kNumStandardFonts; - } - break; - } - if (nRet == 0) { - if (nStyle & FX_FONT_STYLE_Bold) - nStyle |= FX_FONT_STYLE_BoldBold; - else - nStyle |= FX_FONT_STYLE_Bold; - bFirstItem = false; - } else if (nRet == 2) { - nStyle |= FX_FONT_STYLE_Italic; - if (nStyle & FX_FONT_STYLE_Bold) - nStyle |= FX_FONT_STYLE_BoldBold; - else - nStyle |= FX_FONT_STYLE_Bold; - bFirstItem = false; - } - i += buf.GetLength() + 1; - } - } - weight = weight ? weight : FXFONT_FW_NORMAL; - int old_weight = weight; - if (nStyle) { - weight = - nStyle & FX_FONT_STYLE_BoldBold - ? 900 - : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (nStyle & FX_FONT_STYLE_Italic) - bItalic = true; - int iExact = 0; - int Charset = FXFONT_ANSI_CHARSET; - if (WindowCP) - Charset = GetCharsetFromCodePage(WindowCP); - else if (iBaseFont == kNumStandardFonts && (flags & FXFONT_SYMBOLIC)) - Charset = FXFONT_SYMBOL_CHARSET; - bool bCJK = - (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET || - Charset == FXFONT_HANGUL_CHARSET || - Charset == FXFONT_CHINESEBIG5_CHARSET); - if (!m_pFontInfo) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - family = GetFontFamily(family, nStyle); - CFX_ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); - if (match.IsEmpty() && family != SubstName && - (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) { - match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); - } - if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) { - if (!bCJK) { - if (!CheckSupportThirdPartFont(family, PitchFamily)) { - bItalic = italic_angle != 0; - weight = old_weight; - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ - if (SubstName.Find("Narrow") > 0 || SubstName.Find("Condensed") > 0) - family = "LiberationSansNarrow"; -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0) - family = "RobotoCondensed"; -#else - if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0) - family = "ArialNarrow"; -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ - } else { - pSubstFont->m_bSubstCJK = true; - if (nStyle) - pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL; - if (nStyle & FX_FONT_STYLE_Italic) - pSubstFont->m_bItalicCJK = true; - } - } else { - italic_angle = 0; - weight = - nStyle & FX_FONT_STYLE_BoldBold - ? 900 - : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) { - if (!match.IsEmpty()) - family = match; - if (iBaseFont < kNumStandardFonts) { - if (nStyle && !(iBaseFont % 4)) { - if ((nStyle & 0x3) == 1) - iBaseFont += 1; - if ((nStyle & 0x3) == 2) - iBaseFont += 3; - if ((nStyle & 0x3) == 3) - iBaseFont += 2; - } - family = g_Base14FontNames[iBaseFont]; - } - } else { - if (flags & FXFONT_ITALIC) - bItalic = true; - } - iExact = !match.IsEmpty(); - void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, - family.c_str(), iExact); - if (iExact) - pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; - if (!hFont) { -#ifdef PDF_ENABLE_XFA - if (flags & FXFONT_EXACTMATCH) - return nullptr; -#endif // PDF_ENABLE_XFA - if (bCJK) { - bItalic = italic_angle != 0; - weight = old_weight; - } - if (!match.IsEmpty()) { - hFont = m_pFontInfo->GetFont(match.c_str()); - if (!hFont) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - } else { - if (Charset == FXFONT_SYMBOL_CHARSET) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - if (SubstName == "Symbol") { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight, - PitchFamily); - } -#endif - return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, - weight, italic_angle, 0, pSubstFont); - } - if (Charset == FXFONT_ANSI_CHARSET) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - - auto it = - std::find_if(m_FaceArray.begin(), m_FaceArray.end(), - [Charset](const FaceData& face) { - return face.charset == static_cast(Charset); - }); - if (it == m_FaceArray.end()) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - hFont = m_pFontInfo->GetFont(it->name.c_str()); - } - } - if (!hFont) - return nullptr; - - m_pFontInfo->GetFaceName(hFont, SubstName); - if (Charset == FXFONT_DEFAULT_CHARSET) - m_pFontInfo->GetFontCharset(hFont, Charset); - uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); - uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); - if (font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - FXFT_Face face = nullptr; - if (ttc_size) - face = GetCachedTTCFace(hFont, kTableTTCF, ttc_size, font_size); - else - face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); - if (!face) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - pSubstFont->m_Family = SubstName; - pSubstFont->m_Charset = Charset; - bool bNeedUpdateWeight = false; - if (FXFT_Is_Face_Bold(face)) - bNeedUpdateWeight = weight != FXFONT_FW_BOLD; - else - bNeedUpdateWeight = weight != FXFONT_FW_NORMAL; - if (bNeedUpdateWeight) - pSubstFont->m_Weight = weight; - if (bItalic && !FXFT_Is_Face_Italic(face)) { - if (italic_angle == 0) - italic_angle = -12; - else if (FXSYS_abs(italic_angle) < 5) - italic_angle = 0; - pSubstFont->m_ItalicAngle = italic_angle; - } - m_pFontInfo->DeleteFont(hFont); - return face; -} - -#ifdef PDF_ENABLE_XFA -FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, - uint32_t flags, - int weight, - int italic_angle) { - if (!m_pFontInfo) - return nullptr; - - bool bItalic = (flags & FXFONT_ITALIC) != 0; - int PitchFamily = 0; - UpdatePitchFamily(flags, PitchFamily); - void* hFont = - m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); - if (!hFont) - return nullptr; - - uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); - uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); - if (font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - FXFT_Face face = nullptr; - if (ttc_size) { - face = GetCachedTTCFace(hFont, 0x74746366, ttc_size, font_size); - } else { - CFX_ByteString SubstName; - m_pFontInfo->GetFaceName(hFont, SubstName); - face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); - } - m_pFontInfo->DeleteFont(hFont); - return face; -} -#endif // PDF_ENABLE_XFA - -int CFX_FontMapper::GetFaceSize() const { - return pdfium::CollectionSize(m_FaceArray); -} - -bool CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { - for (size_t i = 0; i < MM_FACE_COUNT; ++i) { - if (m_MMFaces[i] == face) - return true; - } - for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { - if (m_FoxitFaces[i] == face) - return true; - } - return false; -} - -FXFT_Face CFX_FontMapper::GetCachedTTCFace(void* hFont, - const uint32_t tableTTCF, - uint32_t ttc_size, - uint32_t font_size) { - FXFT_Face face; - uint8_t buffer[1024]; - m_pFontInfo->GetFontData(hFont, tableTTCF, buffer, FX_ArraySize(buffer)); - uint32_t* pBuffer = reinterpret_cast(buffer); - uint32_t checksum = 0; - for (int i = 0; i < 256; i++) - checksum += pBuffer[i]; - uint8_t* pFontData; - face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, - pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, ttc_size); - m_pFontInfo->GetFontData(hFont, tableTTCF, pFontData, ttc_size); - face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, - ttc_size - font_size); - } - return face; -} - -FXFT_Face CFX_FontMapper::GetCachedFace(void* hFont, - CFX_ByteString SubstName, - int weight, - bool bItalic, - uint32_t font_size) { - FXFT_Face face; - uint8_t* pFontData; - face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, font_size); - m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); - face = - m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, - font_size, m_pFontInfo->GetFaceIndex(hFont)); - } - return face; -} - -int PDF_GetStandardFontName(CFX_ByteString* name) { - AltFontName* found = static_cast( - FXSYS_bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames), - sizeof(AltFontName), CompareString)); - if (!found) - return -1; - - *name = g_Base14FontNames[found->m_Index]; - return found->m_Index; -} diff --git a/core/fxge/ge/cfx_fontmgr.cpp b/core/fxge/ge/cfx_fontmgr.cpp deleted file mode 100644 index 64f647e3f603e0904f0d48c612cfdd3bb10b2328..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_fontmgr.cpp +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_fontmgr.h" - -#include -#include - -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fontdata/chromefontdata/chromefontdata.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/ge/cttfontdesc.h" -#include "core/fxge/ifx_systemfontinfo.h" -#include "third_party/base/ptr_util.h" - -namespace { - -struct BuiltinFont { - const uint8_t* m_pFontData; - uint32_t m_dwSize; -}; - -const BuiltinFont g_FoxitFonts[14] = { - {g_FoxitFixedFontData, 17597}, - {g_FoxitFixedBoldFontData, 18055}, - {g_FoxitFixedBoldItalicFontData, 19151}, - {g_FoxitFixedItalicFontData, 18746}, - {g_FoxitSansFontData, 15025}, - {g_FoxitSansBoldFontData, 16344}, - {g_FoxitSansBoldItalicFontData, 16418}, - {g_FoxitSansItalicFontData, 16339}, - {g_FoxitSerifFontData, 19469}, - {g_FoxitSerifBoldFontData, 19395}, - {g_FoxitSerifBoldItalicFontData, 20733}, - {g_FoxitSerifItalicFontData, 21227}, - {g_FoxitSymbolFontData, 16729}, - {g_FoxitDingbatsFontData, 29513}, -}; - -const BuiltinFont g_MMFonts[2] = { - {g_FoxitSerifMMFontData, 113417}, - {g_FoxitSansMMFontData, 66919}, -}; - -CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name, - int weight, - bool bItalic) { - CFX_ByteString key(face_name); - key += ','; - key += CFX_ByteString::FormatInteger(weight); - key += bItalic ? 'I' : 'N'; - return key; -} - -CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { - CFX_ByteString key; - key.Format("%d:%d", ttc_size, checksum); - return key; -} - -int GetTTCIndex(const uint8_t* pFontData, - uint32_t ttc_size, - uint32_t font_offset) { - int face_index = 0; - const uint8_t* p = pFontData + 8; - uint32_t nfont = GET_TT_LONG(p); - uint32_t index; - for (index = 0; index < nfont; index++) { - p = pFontData + 12 + index * 4; - if (GET_TT_LONG(p) == font_offset) - break; - } - if (index >= nfont) - face_index = 0; - else - face_index = index; - return face_index; -} - -} // namespace - -CFX_FontMgr::CFX_FontMgr() - : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { - m_pBuiltinMapper = pdfium::MakeUnique(this); -} - -CFX_FontMgr::~CFX_FontMgr() { - for (const auto& pair : m_FaceMap) - delete pair.second; - - // |m_pBuiltinMapper| references |m_FTLibrary|, so it has to be destroyed - // first. - m_pBuiltinMapper.reset(); - FXFT_Done_FreeType(m_FTLibrary); -} - -void CFX_FontMgr::InitFTLibrary() { - if (m_FTLibrary) - return; - FXFT_Init_FreeType(&m_FTLibrary); - m_FTLibrarySupportsHinting = - FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != - FT_Err_Unimplemented_Feature; -} - -void CFX_FontMgr::SetSystemFontInfo( - std::unique_ptr pFontInfo) { - m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); -} - -FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, - bool bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int CharsetCP, - CFX_SubstFont* pSubstFont) { - InitFTLibrary(); - return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, - italic_angle, CharsetCP, pSubstFont); -} - -FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, - int weight, - bool bItalic, - uint8_t*& pFontData) { - auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); - if (it == m_FaceMap.end()) - return nullptr; - - CTTFontDesc* pFontDesc = it->second; - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount++; - return pFontDesc->m_SingleFace; -} - -FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, - int weight, - bool bItalic, - uint8_t* pData, - uint32_t size, - int face_index) { - CTTFontDesc* pFontDesc = new CTTFontDesc; - pFontDesc->m_Type = 1; - pFontDesc->m_SingleFace = nullptr; - pFontDesc->m_pFontData = pData; - pFontDesc->m_RefCount = 1; - - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - int ret = FXFT_New_Memory_Face(library, pData, size, face_index, - &pFontDesc->m_SingleFace); - if (ret) { - delete pFontDesc; - return nullptr; - } - ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace, 64, 64); - if (ret) { - delete pFontDesc; - return nullptr; - } - m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc; - return pFontDesc->m_SingleFace; -} - -FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, - uint32_t checksum, - int font_offset, - uint8_t*& pFontData) { - auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); - if (it == m_FaceMap.end()) - return nullptr; - - CTTFontDesc* pFontDesc = it->second; - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount++; - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - if (!pFontDesc->m_TTCFaces[face_index]) { - pFontDesc->m_TTCFaces[face_index] = - GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - } - return pFontDesc->m_TTCFaces[face_index]; -} - -FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, - uint32_t checksum, - uint8_t* pData, - uint32_t size, - int font_offset) { - CTTFontDesc* pFontDesc = new CTTFontDesc; - pFontDesc->m_Type = 2; - pFontDesc->m_pFontData = pData; - for (int i = 0; i < 16; i++) - pFontDesc->m_TTCFaces[i] = nullptr; - pFontDesc->m_RefCount++; - m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc; - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - pFontDesc->m_TTCFaces[face_index] = - GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - return pFontDesc->m_TTCFaces[face_index]; -} - -FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, - uint32_t size, - int face_index) { - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - FXFT_Face face = nullptr; - if (FXFT_New_Memory_Face(library, pData, size, face_index, &face)) - return nullptr; - return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; -} - -FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) { - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - FXFT_Face face = nullptr; - if (FXFT_New_Face(library, filename, face_index, &face)) - return nullptr; - return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; -} - -void CFX_FontMgr::ReleaseFace(FXFT_Face face) { - if (!face) - return; - bool bNeedFaceDone = true; - auto it = m_FaceMap.begin(); - while (it != m_FaceMap.end()) { - auto temp = it++; - int nRet = temp->second->ReleaseFace(face); - if (nRet == -1) - continue; - bNeedFaceDone = false; - if (nRet == 0) - m_FaceMap.erase(temp); - break; - } - if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) - FXFT_Done_Face(face); -} - -bool CFX_FontMgr::GetBuiltinFont(size_t index, - const uint8_t** pFontData, - uint32_t* size) { - if (index < FX_ArraySize(g_FoxitFonts)) { - *pFontData = g_FoxitFonts[index].m_pFontData; - *size = g_FoxitFonts[index].m_dwSize; - return true; - } - index -= FX_ArraySize(g_FoxitFonts); - if (index < FX_ArraySize(g_MMFonts)) { - *pFontData = g_MMFonts[index].m_pFontData; - *size = g_MMFonts[index].m_dwSize; - return true; - } - return false; -} diff --git a/core/fxge/ge/cfx_gemodule.cpp b/core/fxge/ge/cfx_gemodule.cpp deleted file mode 100644 index ed6d6cb32e67c9f8faae66d7182107009be025e6..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_gemodule.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_gemodule.h" - -#include "core/fxge/cfx_fontcache.h" -#include "core/fxge/cfx_fontmgr.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" -#include "core/fxge/ge/fx_text_int.h" - -namespace { - -CFX_GEModule* g_pGEModule = nullptr; - -} // namespace - -CFX_GEModule::CFX_GEModule() - : m_FTLibrary(nullptr), - m_pFontCache(nullptr), - m_pFontMgr(new CFX_FontMgr), - m_pCodecModule(nullptr), - m_pPlatformData(nullptr), - m_pUserFontPaths(nullptr) {} - -CFX_GEModule::~CFX_GEModule() { - delete m_pFontCache; - DestroyPlatform(); -} - -// static -CFX_GEModule* CFX_GEModule::Get() { - if (!g_pGEModule) - g_pGEModule = new CFX_GEModule(); - return g_pGEModule; -} - -// static -void CFX_GEModule::Destroy() { - ASSERT(g_pGEModule); - delete g_pGEModule; - g_pGEModule = nullptr; -} - -void CFX_GEModule::Init(const char** userFontPaths, - CCodec_ModuleMgr* pCodecModule) { - ASSERT(g_pGEModule); - m_pCodecModule = pCodecModule; - m_pUserFontPaths = userFontPaths; - InitPlatform(); - SetTextGamma(2.2f); -} - -CFX_FontCache* CFX_GEModule::GetFontCache() { - if (!m_pFontCache) - m_pFontCache = new CFX_FontCache(); - return m_pFontCache; -} - -void CFX_GEModule::SetTextGamma(FX_FLOAT gammaValue) { - gammaValue /= 2.2f; - for (int i = 0; i < 256; ++i) { - m_GammaValue[i] = static_cast( - FXSYS_pow(static_cast(i) / 255, gammaValue) * 255.0f + 0.5f); - } -} - -const uint8_t* CFX_GEModule::GetTextGammaTable() const { - return m_GammaValue; -} diff --git a/core/fxge/ge/cfx_graphstate.cpp b/core/fxge/ge/cfx_graphstate.cpp deleted file mode 100644 index 6357aa51a413081c43479b1da4fff28e4ddab259..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_graphstate.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_graphstate.h" - -#include "core/fpdfapi/parser/cpdf_array.h" - -CFX_GraphState::CFX_GraphState() {} - -CFX_GraphState::CFX_GraphState(const CFX_GraphState& that) - : m_Ref(that.m_Ref) {} - -CFX_GraphState::~CFX_GraphState() {} - -void CFX_GraphState::Emplace() { - m_Ref.Emplace(); -} - -void CFX_GraphState::SetLineDash(CPDF_Array* pArray, - FX_FLOAT phase, - FX_FLOAT scale) { - CFX_GraphStateData* pData = m_Ref.GetPrivateCopy(); - pData->m_DashPhase = phase * scale; - pData->SetDashCount(static_cast(pArray->GetCount())); - for (size_t i = 0; i < pArray->GetCount(); i++) - pData->m_DashArray[i] = pArray->GetNumberAt(i) * scale; -} - -FX_FLOAT CFX_GraphState::GetLineWidth() const { - return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineWidth : 1.f; -} - -void CFX_GraphState::SetLineWidth(FX_FLOAT width) { - m_Ref.GetPrivateCopy()->m_LineWidth = width; -} - -CFX_GraphStateData::LineCap CFX_GraphState::GetLineCap() const { - return m_Ref.GetObject()->m_LineCap; -} -void CFX_GraphState::SetLineCap(CFX_GraphStateData::LineCap cap) { - m_Ref.GetPrivateCopy()->m_LineCap = cap; -} - -CFX_GraphStateData::LineJoin CFX_GraphState::GetLineJoin() const { - return m_Ref.GetObject()->m_LineJoin; -} - -void CFX_GraphState::SetLineJoin(CFX_GraphStateData::LineJoin join) { - m_Ref.GetPrivateCopy()->m_LineJoin = join; -} - -FX_FLOAT CFX_GraphState::GetMiterLimit() const { - return m_Ref.GetObject() ? m_Ref.GetObject()->m_MiterLimit : 10.f; -} - -void CFX_GraphState::SetMiterLimit(FX_FLOAT limit) { - m_Ref.GetPrivateCopy()->m_MiterLimit = limit; -} diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp deleted file mode 100644 index daa67ccc91bd37972668573c47c4dac092bf0d31..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_renderdevice.cpp +++ /dev/null @@ -1,1112 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_renderdevice.h" - -#include -#include -#include -#include - -#include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/cfx_facecache.h" -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/ifx_renderdevicedriver.h" - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ -#include "third_party/skia/include/core/SkTypes.h" -#endif - -namespace { - -void AdjustGlyphSpace(std::vector* pGlyphAndPos) { - ASSERT(pGlyphAndPos->size() > 1); - std::vector& glyphs = *pGlyphAndPos; - bool bVertical = glyphs.back().m_Origin.x == glyphs.front().m_Origin.x; - if (!bVertical && (glyphs.back().m_Origin.y != glyphs.front().m_Origin.y)) - return; - - for (size_t i = glyphs.size() - 1; i > 1; --i) { - FXTEXT_GLYPHPOS& next = glyphs[i]; - int next_origin = bVertical ? next.m_Origin.y : next.m_Origin.x; - FX_FLOAT next_origin_f = bVertical ? next.m_fOrigin.y : next.m_fOrigin.x; - - FXTEXT_GLYPHPOS& current = glyphs[i - 1]; - int& current_origin = bVertical ? current.m_Origin.y : current.m_Origin.x; - FX_FLOAT current_origin_f = - bVertical ? current.m_fOrigin.y : current.m_fOrigin.x; - - int space = next_origin - current_origin; - FX_FLOAT space_f = next_origin_f - current_origin_f; - FX_FLOAT error = - FXSYS_fabs(space_f) - FXSYS_fabs(static_cast(space)); - if (error > 0.5f) - current_origin += space > 0 ? -1 : 1; - } -} - -const uint8_t g_TextGammaAdjust[256] = { - 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, - 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, - 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, - 255, -}; - -int TextGammaAdjust(int value) { - ASSERT(value >= 0); - ASSERT(value <= 255); - return g_TextGammaAdjust[value]; -} - -int CalcAlpha(int src, int alpha) { - return src * alpha / 255; -} - -void Merge(uint8_t src, int channel, int alpha, uint8_t* dest) { - *dest = FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(src, alpha)); -} - -void MergeGammaAdjust(uint8_t src, int channel, int alpha, uint8_t* dest) { - *dest = - FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(TextGammaAdjust(src), alpha)); -} - -void MergeGammaAdjustBgr(const uint8_t* src, - int r, - int g, - int b, - int a, - uint8_t* dest) { - MergeGammaAdjust(src[0], b, a, &dest[0]); - MergeGammaAdjust(src[1], g, a, &dest[1]); - MergeGammaAdjust(src[2], r, a, &dest[2]); -} - -void MergeGammaAdjustRgb(const uint8_t* src, - int r, - int g, - int b, - int a, - uint8_t* dest) { - MergeGammaAdjust(src[2], b, a, &dest[0]); - MergeGammaAdjust(src[1], g, a, &dest[1]); - MergeGammaAdjust(src[0], r, a, &dest[2]); -} - -int AverageRgb(const uint8_t* src) { - return (src[0] + src[1] + src[2]) / 3; -} - -uint8_t CalculateDestAlpha(uint8_t back_alpha, int src_alpha) { - return back_alpha + src_alpha - back_alpha * src_alpha / 255; -} - -void ApplyDestAlpha(uint8_t back_alpha, - int src_alpha, - int r, - int g, - int b, - uint8_t* dest) { - uint8_t dest_alpha = CalculateDestAlpha(back_alpha, src_alpha); - int alpha_ratio = src_alpha * 255 / dest_alpha; - dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, alpha_ratio); - dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, alpha_ratio); - dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, alpha_ratio); - dest[3] = dest_alpha; -} - -void NormalizeRgbDst(int src_value, int r, int g, int b, int a, uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, src_alpha); - dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, src_alpha); - dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, src_alpha); -} - -void NormalizeRgbSrc(int src_value, int r, int g, int b, int a, uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - if (src_alpha == 0) - return; - - dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, src_alpha); - dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, src_alpha); - dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, src_alpha); -} - -void NormalizeArgbDest(int src_value, - int r, - int g, - int b, - int a, - uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - uint8_t back_alpha = dest[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); - } else if (src_alpha != 0) { - ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); - } -} - -void NormalizeArgbSrc(int src_value, - int r, - int g, - int b, - int a, - uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - if (src_alpha == 0) - return; - - uint8_t back_alpha = dest[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); - } else { - ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); - } -} - -void NextPixel(uint8_t** src_scan, uint8_t** dst_scan, int bpp) { - *src_scan += 3; - *dst_scan += bpp; -} - -void SetAlpha(uint8_t* alpha) { - alpha[3] = 255; -} - -void SetAlphaDoNothing(uint8_t* alpha) {} - -void DrawNormalTextHelper(CFX_DIBitmap* bitmap, - const CFX_DIBitmap* pGlyph, - int nrows, - int left, - int top, - int start_col, - int end_col, - bool bNormal, - bool bBGRStripe, - int x_subpixel, - int a, - int r, - int g, - int b) { - const bool has_alpha = bitmap->GetFormat() == FXDIB_Argb; - uint8_t* src_buf = pGlyph->GetBuffer(); - int src_pitch = pGlyph->GetPitch(); - uint8_t* dest_buf = bitmap->GetBuffer(); - int dest_pitch = bitmap->GetPitch(); - const int Bpp = has_alpha ? 4 : bitmap->GetBPP() / 8; - auto* pNormalizeSrcFunc = has_alpha ? &NormalizeArgbSrc : &NormalizeRgbDst; - auto* pNormalizeDstFunc = has_alpha ? &NormalizeArgbDest : &NormalizeRgbSrc; - auto* pSetAlpha = has_alpha ? &SetAlpha : &SetAlphaDoNothing; - - for (int row = 0; row < nrows; row++) { - int dest_row = row + top; - if (dest_row < 0 || dest_row >= bitmap->GetHeight()) - continue; - - uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; - uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; - if (bBGRStripe) { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col++) { - if (has_alpha) { - Merge(src_scan[2], r, a, &dest_scan[2]); - Merge(src_scan[1], g, a, &dest_scan[1]); - Merge(src_scan[0], b, a, &dest_scan[0]); - } else { - MergeGammaAdjustBgr(&src_scan[0], r, g, b, a, &dest_scan[0]); - } - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else if (x_subpixel == 1) { - MergeGammaAdjust(src_scan[1], r, a, &dest_scan[2]); - MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); - if (start_col > left) - MergeGammaAdjust(src_scan[-1], b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col - 1; col++) { - MergeGammaAdjustBgr(&src_scan[-1], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else { - MergeGammaAdjust(src_scan[0], r, a, &dest_scan[2]); - if (start_col > left) { - MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); - MergeGammaAdjust(src_scan[-2], b, a, &dest_scan[0]); - } - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col - 1; col++) { - MergeGammaAdjustBgr(&src_scan[-2], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - } - } - } else { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col++) { - if (bNormal) { - int src_value = AverageRgb(&src_scan[0]); - pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); - } else { - MergeGammaAdjustRgb(&src_scan[0], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else if (x_subpixel == 1) { - if (bNormal) { - int src_value = start_col > left ? AverageRgb(&src_scan[-1]) - : (src_scan[0] + src_scan[1]) / 3; - pNormalizeSrcFunc(src_value, r, g, b, a, dest_scan); - } else { - if (start_col > left) - MergeGammaAdjust(src_scan[-1], r, a, &dest_scan[2]); - MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); - MergeGammaAdjust(src_scan[1], b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col; col++) { - if (bNormal) { - int src_value = AverageRgb(&src_scan[-1]); - pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); - } else { - MergeGammaAdjustRgb(&src_scan[-1], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else { - if (bNormal) { - int src_value = - start_col > left ? AverageRgb(&src_scan[-2]) : src_scan[0] / 3; - pNormalizeSrcFunc(src_value, r, g, b, a, dest_scan); - } else { - if (start_col > left) { - MergeGammaAdjust(src_scan[-2], r, a, &dest_scan[2]); - MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); - } - MergeGammaAdjust(src_scan[0], b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col; col++) { - if (bNormal) { - int src_value = AverageRgb(&src_scan[-2]); - pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); - } else { - MergeGammaAdjustRgb(&src_scan[-2], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - } - } - } - } -} - -bool ShouldDrawDeviceText(const CFX_Font* pFont, uint32_t text_flags) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (text_flags & FXFONT_CIDFONT) - return false; - - const CFX_ByteString bsPsName = pFont->GetPsName(); - if (bsPsName.Find("+ZJHL") != -1) - return false; - - if (bsPsName == "CNAAJI+cmex10") - return false; -#endif - return true; -} - -} // namespace - -FXTEXT_CHARPOS::FXTEXT_CHARPOS() - : m_GlyphIndex(0), - m_FontCharWidth(0), -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_ExtGID(0), -#endif - m_FallbackFontPosition(0), - m_bGlyphAdjust(false), - m_bFontStyle(false) { -} - -FXTEXT_CHARPOS::FXTEXT_CHARPOS(const FXTEXT_CHARPOS&) = default; - -FXTEXT_CHARPOS::~FXTEXT_CHARPOS(){}; - -CFX_RenderDevice::CFX_RenderDevice() - : m_pBitmap(nullptr), - m_Width(0), - m_Height(0), - m_bpp(0), - m_RenderCaps(0), - m_DeviceClass(0) {} - -CFX_RenderDevice::~CFX_RenderDevice() { -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - Flush(); -#endif -} - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ -void CFX_RenderDevice::Flush() { - m_pDeviceDriver.reset(); -} -#endif - -void CFX_RenderDevice::SetDeviceDriver( - std::unique_ptr pDriver) { - m_pDeviceDriver = std::move(pDriver); - InitDeviceInfo(); -} - -void CFX_RenderDevice::InitDeviceInfo() { - m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); - m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); - m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); - m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); - m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); - if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { - m_ClipBox.left = 0; - m_ClipBox.top = 0; - m_ClipBox.right = m_Width; - m_ClipBox.bottom = m_Height; - } -} - -void CFX_RenderDevice::SaveState() { - m_pDeviceDriver->SaveState(); -} - -void CFX_RenderDevice::RestoreState(bool bKeepSaved) { - m_pDeviceDriver->RestoreState(bKeepSaved); - UpdateClipBox(); -} - -int CFX_RenderDevice::GetDeviceCaps(int caps_id) const { - return m_pDeviceDriver->GetDeviceCaps(caps_id); -} -CFX_Matrix CFX_RenderDevice::GetCTM() const { - return m_pDeviceDriver->GetCTM(); -} - -bool CFX_RenderDevice::CreateCompatibleBitmap(CFX_DIBitmap* pDIB, - int width, - int height) const { - if (m_RenderCaps & FXRC_CMYK_OUTPUT) { - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT - ? FXDIB_Cmyka - : FXDIB_Cmyk); - } - if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) - return pDIB->Create(width, height, FXDIB_8bppMask); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_PATHS_ - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT - ? FXDIB_Argb - : FXDIB_Rgb32); -#else - return pDIB->Create( - width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); -#endif -} - -bool CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - int fill_mode) { - if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, - fill_mode)) { - return false; - } - UpdateClipBox(); - return true; -} - -bool CFX_RenderDevice::SetClip_PathStroke( - const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState) { - if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, - pGraphState)) { - return false; - } - UpdateClipBox(); - return true; -} - -bool CFX_RenderDevice::SetClip_Rect(const FX_RECT& rect) { - CFX_PathData path; - path.AppendRect(rect.left, rect.bottom, rect.right, rect.top); - if (!SetClip_PathFill(&path, nullptr, FXFILL_WINDING)) - return false; - - UpdateClipBox(); - return true; -} - -void CFX_RenderDevice::UpdateClipBox() { - if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) - return; - m_ClipBox.left = 0; - m_ClipBox.top = 0; - m_ClipBox.right = m_Width; - m_ClipBox.bottom = m_Height; -} - -bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState, - uint32_t fill_color, - uint32_t stroke_color, - int fill_mode, - int blend_type) { - uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0; - uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0; - const std::vector& pPoints = pPathData->GetPoints(); - if (stroke_alpha == 0 && pPoints.size() == 2) { - CFX_PointF pos1 = pPoints[0].m_Point; - CFX_PointF pos2 = pPoints[1].m_Point; - if (pObject2Device) { - pos1 = pObject2Device->Transform(pos1); - pos2 = pObject2Device->Transform(pos2); - } - DrawCosmeticLine(pos1.x, pos1.y, pos2.x, pos2.y, fill_color, fill_mode, - blend_type); - return true; - } - - if ((pPoints.size() == 5 || pPoints.size() == 4) && stroke_alpha == 0) { - CFX_FloatRect rect_f; - if (!(fill_mode & FXFILL_RECT_AA) && - pPathData->IsRect(pObject2Device, &rect_f)) { - FX_RECT rect_i = rect_f.GetOuterRect(); - - // Depending on the top/bottom, left/right values of the rect it's - // possible to overflow the Width() and Height() calculations. Check that - // the rect will have valid dimension before continuing. - if (!rect_i.Valid()) - return false; - - int width = (int)FXSYS_ceil(rect_f.right - rect_f.left); - if (width < 1) { - width = 1; - if (rect_i.left == rect_i.right) - rect_i.right++; - } - int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom); - if (height < 1) { - height = 1; - if (rect_i.bottom == rect_i.top) - rect_i.bottom++; - } - if (rect_i.Width() >= width + 1) { - if (rect_f.left - (FX_FLOAT)(rect_i.left) > - (FX_FLOAT)(rect_i.right) - rect_f.right) { - rect_i.left++; - } else { - rect_i.right--; - } - } - if (rect_i.Height() >= height + 1) { - if (rect_f.top - (FX_FLOAT)(rect_i.top) > - (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) { - rect_i.top++; - } else { - rect_i.bottom--; - } - } - if (FillRectWithBlend(&rect_i, fill_color, blend_type)) - return true; - } - } - if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && - !(fill_mode & FX_FILL_TEXT_MODE)) { - CFX_PathData newPath; - bool bThin = false; - bool setIdentity = false; - if (pPathData->GetZeroAreaPath(pObject2Device, - !!m_pDeviceDriver->GetDriverType(), &newPath, - &bThin, &setIdentity)) { - CFX_GraphStateData graphState; - graphState.m_LineWidth = 0.0f; - - uint32_t strokecolor = fill_color; - if (bThin) - strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); - - const CFX_Matrix* pMatrix = nullptr; - if (pObject2Device && !pObject2Device->IsIdentity() && !setIdentity) - pMatrix = pObject2Device; - - int smooth_path = FX_ZEROAREA_FILL; - if (fill_mode & FXFILL_NOPATHSMOOTH) - smooth_path |= FXFILL_NOPATHSMOOTH; - - m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, - smooth_path, blend_type); - } - } - if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && - (fill_mode & FX_FILL_STROKE)) { - if (m_RenderCaps & FXRC_FILLSTROKE_PATH) { - return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, - fill_color, stroke_color, fill_mode, - blend_type); - } - return DrawFillStrokePath(pPathData, pObject2Device, pGraphState, - fill_color, stroke_color, fill_mode, blend_type); - } - return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, - fill_color, stroke_color, fill_mode, - blend_type); -} - -// This can be removed once PDFium entirely relies on Skia -bool CFX_RenderDevice::DrawFillStrokePath(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState, - uint32_t fill_color, - uint32_t stroke_color, - int fill_mode, - int blend_type) { - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - CFX_FloatRect bbox; - if (pGraphState) { - bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, - pGraphState->m_MiterLimit); - } else { - bbox = pPathData->GetBoundingBox(); - } - if (pObject2Device) - pObject2Device->TransformRect(bbox); - - CFX_Matrix ctm = GetCTM(); - FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); - FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); - FX_RECT rect = bbox.GetOuterRect(); - CFX_DIBitmap bitmap, Backdrop; - if (!CreateCompatibleBitmap(&bitmap, FXSYS_round(rect.Width() * fScaleX), - FXSYS_round(rect.Height() * fScaleY))) { - return false; - } - if (bitmap.HasAlpha()) { - bitmap.Clear(0); - Backdrop.Copy(&bitmap); - } else { - if (!m_pDeviceDriver->GetDIBits(&bitmap, rect.left, rect.top)) - return false; - Backdrop.Copy(&bitmap); - } - CFX_FxgeDevice bitmap_device; - bitmap_device.Attach(&bitmap, false, &Backdrop, true); - CFX_Matrix matrix; - if (pObject2Device) - matrix = *pObject2Device; - matrix.Translate(-rect.left, -rect.top); - matrix.Concat(CFX_Matrix(fScaleX, 0, 0, fScaleY, 0, 0)); - if (!bitmap_device.GetDeviceDriver()->DrawPath( - pPathData, &matrix, pGraphState, fill_color, stroke_color, fill_mode, - blend_type)) { - return false; - } -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - bitmap_device.GetDeviceDriver()->Flush(); -#endif - FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), - FXSYS_round(rect.Height() * fScaleY)); - return m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, rect.left, rect.top, - FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::SetPixel(int x, int y, uint32_t color) { - if (m_pDeviceDriver->SetPixel(x, y, color)) - return true; - - FX_RECT rect(x, y, x + 1, y + 1); - return FillRectWithBlend(&rect, color, FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::FillRectWithBlend(const FX_RECT* pRect, - uint32_t fill_color, - int blend_type) { - if (m_pDeviceDriver->FillRectWithBlend(pRect, fill_color, blend_type)) - return true; - - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - - CFX_DIBitmap bitmap; - if (!CreateCompatibleBitmap(&bitmap, pRect->Width(), pRect->Height())) - return false; - - if (!m_pDeviceDriver->GetDIBits(&bitmap, pRect->left, pRect->top)) - return false; - - if (!bitmap.CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, - 0, nullptr)) { - return false; - } - FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); - m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, pRect->left, pRect->top, - FXDIB_BLEND_NORMAL); - return true; -} - -bool CFX_RenderDevice::DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, - uint32_t color, - int fill_mode, - int blend_type) { - if ((color >= 0xff000000) && - m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, blend_type)) { - return true; - } - CFX_GraphStateData graph_state; - CFX_PathData path; - path.AppendPoint(CFX_PointF(x1, y1), FXPT_TYPE::MoveTo, false); - path.AppendPoint(CFX_PointF(x2, y2), FXPT_TYPE::LineTo, false); - return m_pDeviceDriver->DrawPath(&path, nullptr, &graph_state, 0, color, - fill_mode, blend_type); -} - -bool CFX_RenderDevice::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - return m_pDeviceDriver->GetDIBits(pBitmap, left, top); -} - -CFX_DIBitmap* CFX_RenderDevice::GetBackDrop() { - return m_pDeviceDriver->GetBackDrop(); -} - -bool CFX_RenderDevice::SetDIBitsWithBlend(const CFX_DIBSource* pBitmap, - int left, - int top, - int blend_mode) { - ASSERT(!pBitmap->IsAlphaMask()); - CFX_Matrix ctm = GetCTM(); - FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); - FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); - FX_RECT dest_rect(left, top, - FXSYS_round(left + pBitmap->GetWidth() / fScaleX), - FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); - dest_rect.Intersect(m_ClipBox); - if (dest_rect.IsEmpty()) - return true; - FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, - dest_rect.left - left + dest_rect.Width(), - dest_rect.top - top + dest_rect.Height()); - src_rect.left = FXSYS_round(src_rect.left * fScaleX); - src_rect.top = FXSYS_round(src_rect.top * fScaleY); - src_rect.right = FXSYS_round(src_rect.right * fScaleX); - src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); - if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) || - (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) { - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); - int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); - CFX_DIBitmap background; - if (!background.Create( - bg_pixel_width, bg_pixel_height, - (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { - return false; - } - if (!m_pDeviceDriver->GetDIBits(&background, dest_rect.left, - dest_rect.top)) { - return false; - } - if (!background.CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, - pBitmap, src_rect.left, src_rect.top, - blend_mode, nullptr, false, nullptr)) { - return false; - } - FX_RECT rect(0, 0, bg_pixel_width, bg_pixel_height); - return m_pDeviceDriver->SetDIBits(&background, 0, &rect, dest_rect.left, - dest_rect.top, FXDIB_BLEND_NORMAL); - } - return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, - dest_rect.top, blend_mode); -} - -bool CFX_RenderDevice::StretchDIBitsWithFlagsAndBlend( - const CFX_DIBSource* pBitmap, - int left, - int top, - int dest_width, - int dest_height, - uint32_t flags, - int blend_mode) { - FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); - FX_RECT clip_box = m_ClipBox; - clip_box.Intersect(dest_rect); - if (clip_box.IsEmpty()) - return true; - return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width, - dest_height, &clip_box, flags, - blend_mode); -} - -bool CFX_RenderDevice::SetBitMask(const CFX_DIBSource* pBitmap, - int left, - int top, - uint32_t argb) { - FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); - return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, - FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::StretchBitMask(const CFX_DIBSource* pBitmap, - int left, - int top, - int dest_width, - int dest_height, - uint32_t color) { - return StretchBitMaskWithFlags(pBitmap, left, top, dest_width, dest_height, - color, 0); -} - -bool CFX_RenderDevice::StretchBitMaskWithFlags(const CFX_DIBSource* pBitmap, - int left, - int top, - int dest_width, - int dest_height, - uint32_t argb, - uint32_t flags) { - FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); - FX_RECT clip_box = m_ClipBox; - clip_box.Intersect(dest_rect); - return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, - dest_height, &clip_box, flags, - FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::StartDIBitsWithBlend(const CFX_DIBSource* pBitmap, - int bitmap_alpha, - uint32_t argb, - const CFX_Matrix* pMatrix, - uint32_t flags, - void*& handle, - int blend_mode) { - return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, - flags, handle, blend_mode); -} - -bool CFX_RenderDevice::ContinueDIBits(void* handle, IFX_Pause* pPause) { - return m_pDeviceDriver->ContinueDIBits(handle, pPause); -} - -void CFX_RenderDevice::CancelDIBits(void* handle) { - m_pDeviceDriver->CancelDIBits(handle); -} - -#ifdef _SKIA_SUPPORT_ -void CFX_RenderDevice::DebugVerifyBitmapIsPreMultiplied() const { - SkASSERT(0); -} - -bool CFX_RenderDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, - int left, - int top, - int bitmap_alpha, - int blend_type) { - return m_pDeviceDriver->SetBitsWithMask(pBitmap, pMask, left, top, - bitmap_alpha, blend_type); -} -#endif - -bool CFX_RenderDevice::DrawNormalText(int nChars, - const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, - FX_FLOAT font_size, - const CFX_Matrix* pText2Device, - uint32_t fill_color, - uint32_t text_flags) { - int nativetext_flags = text_flags; - if (m_DeviceClass != FXDC_DISPLAY) { - if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { - if (ShouldDrawDeviceText(pFont, text_flags) && - m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, - font_size, fill_color)) { - return true; - } - } - if (FXARGB_A(fill_color) < 255) - return false; - } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { - if (ShouldDrawDeviceText(pFont, text_flags) && - m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, - font_size, fill_color)) { - return true; - } - } - CFX_Matrix char2device; - CFX_Matrix text2Device; - if (pText2Device) { - char2device = *pText2Device; - text2Device = *pText2Device; - } - - char2device.Scale(font_size, -font_size); - if (FXSYS_fabs(char2device.a) + FXSYS_fabs(char2device.b) > 50 * 1.0f || - ((m_DeviceClass == FXDC_PRINTER) && - !(text_flags & FXTEXT_PRINTIMAGETEXT))) { - if (pFont->GetFace()) { - int nPathFlags = - (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; - return DrawTextPath(nChars, pCharPos, pFont, font_size, pText2Device, - nullptr, nullptr, fill_color, 0, nullptr, nPathFlags); - } - } - int anti_alias = FXFT_RENDER_MODE_MONO; - bool bNormal = false; - if ((text_flags & FXTEXT_NOSMOOTH) == 0) { - if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { - if (!CFX_GEModule::Get()->GetFontMgr()->FTLibrarySupportsHinting()) { - // Some Freetype implementations (like the one packaged with Fedora) do - // not support hinting due to patents 6219025, 6239783, 6307566, - // 6225973, 6243070, 6393145, 6421054, 6282327, and 6624828; the latest - // one expires 10/7/19. This makes LCD antialiasing very ugly, so we - // instead fall back on NORMAL antialiasing. - anti_alias = FXFT_RENDER_MODE_NORMAL; - } else if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { - anti_alias = FXFT_RENDER_MODE_LCD; - bNormal = true; - } else if (m_bpp < 16) { - anti_alias = FXFT_RENDER_MODE_NORMAL; - } else { - anti_alias = FXFT_RENDER_MODE_LCD; - - bool bClearType = false; - if (pFont->GetFace()) - bClearType = !!(text_flags & FXTEXT_CLEARTYPE); - bNormal = !bClearType; - } - } - } - std::vector glyphs(nChars); - CFX_Matrix matrixCTM = GetCTM(); - FX_FLOAT scale_x = FXSYS_fabs(matrixCTM.a); - FX_FLOAT scale_y = FXSYS_fabs(matrixCTM.d); - CFX_Matrix deviceCtm = char2device; - CFX_Matrix m(scale_x, 0, 0, scale_y, 0, 0); - deviceCtm.Concat(m); - text2Device.Concat(m); - - for (size_t i = 0; i < glyphs.size(); ++i) { - FXTEXT_GLYPHPOS& glyph = glyphs[i]; - const FXTEXT_CHARPOS& charpos = pCharPos[i]; - - glyph.m_fOrigin = text2Device.Transform(charpos.m_Origin); - if (anti_alias < FXFT_RENDER_MODE_LCD) - glyph.m_Origin.x = FXSYS_round(glyph.m_fOrigin.x); - else - glyph.m_Origin.x = static_cast(FXSYS_floor(glyph.m_fOrigin.x)); - glyph.m_Origin.y = FXSYS_round(glyph.m_fOrigin.y); - - if (charpos.m_bGlyphAdjust) { - CFX_Matrix new_matrix( - charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); - new_matrix.Concat(deviceCtm); - glyph.m_pGlyph = pFont->LoadGlyphBitmap( - charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, - charpos.m_FontCharWidth, anti_alias, nativetext_flags); - } else { - glyph.m_pGlyph = pFont->LoadGlyphBitmap( - charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, - charpos.m_FontCharWidth, anti_alias, nativetext_flags); - } - } - if (anti_alias < FXFT_RENDER_MODE_LCD && glyphs.size() > 1) - AdjustGlyphSpace(&glyphs); - - FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(glyphs, anti_alias); - if (scale_x > 1 && scale_y > 1) { - bmp_rect1.left--; - bmp_rect1.top--; - bmp_rect1.right++; - bmp_rect1.bottom++; - } - FX_RECT bmp_rect(FXSYS_round((FX_FLOAT)(bmp_rect1.left) / scale_x), - FXSYS_round((FX_FLOAT)(bmp_rect1.top) / scale_y), - FXSYS_round((FX_FLOAT)bmp_rect1.right / scale_x), - FXSYS_round((FX_FLOAT)bmp_rect1.bottom / scale_y)); - bmp_rect.Intersect(m_ClipBox); - if (bmp_rect.IsEmpty()) - return true; - int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); - int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); - int pixel_left = FXSYS_round(bmp_rect.left * scale_x); - int pixel_top = FXSYS_round(bmp_rect.top * scale_y); - if (anti_alias == FXFT_RENDER_MODE_MONO) { - CFX_DIBitmap bitmap; - if (!bitmap.Create(pixel_width, pixel_height, FXDIB_1bppMask)) - return false; - bitmap.Clear(0); - for (const FXTEXT_GLYPHPOS& glyph : glyphs) { - if (!glyph.m_pGlyph) - continue; - const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; - bitmap.TransferBitmap( - glyph.m_Origin.x + glyph.m_pGlyph->m_Left - pixel_left, - glyph.m_Origin.y - glyph.m_pGlyph->m_Top - pixel_top, - pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); - } - return SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color); - } - CFX_DIBitmap bitmap; - if (m_bpp == 8) { - if (!bitmap.Create(pixel_width, pixel_height, FXDIB_8bppMask)) - return false; - } else { - if (!CreateCompatibleBitmap(&bitmap, pixel_width, pixel_height)) - return false; - } - if (!bitmap.HasAlpha() && !bitmap.IsAlphaMask()) { - bitmap.Clear(0xFFFFFFFF); - if (!GetDIBits(&bitmap, bmp_rect.left, bmp_rect.top)) - return false; - } else { - bitmap.Clear(0); - if (bitmap.m_pAlphaMask) - bitmap.m_pAlphaMask->Clear(0); - } - int dest_width = pixel_width; - int a = 0; - int r = 0; - int g = 0; - int b = 0; - if (anti_alias == FXFT_RENDER_MODE_LCD) - ArgbDecode(fill_color, a, r, g, b); - - for (const FXTEXT_GLYPHPOS& glyph : glyphs) { - if (!glyph.m_pGlyph) - continue; - - pdfium::base::CheckedNumeric left = glyph.m_Origin.x; - left += glyph.m_pGlyph->m_Left; - left -= pixel_left; - if (!left.IsValid()) - return false; - - pdfium::base::CheckedNumeric top = glyph.m_Origin.y; - top -= glyph.m_pGlyph->m_Top; - top -= pixel_top; - if (!top.IsValid()) - return false; - - const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; - int ncols = pGlyph->GetWidth(); - int nrows = pGlyph->GetHeight(); - if (anti_alias == FXFT_RENDER_MODE_NORMAL) { - if (!bitmap.CompositeMask(left.ValueOrDie(), top.ValueOrDie(), ncols, - nrows, pGlyph, fill_color, 0, 0, - FXDIB_BLEND_NORMAL, nullptr, false, 0, - nullptr)) { - return false; - } - continue; - } - bool bBGRStripe = !!(text_flags & FXTEXT_BGR_STRIPE); - ncols /= 3; - int x_subpixel = static_cast(glyph.m_fOrigin.x * 3) % 3; - int start_col = - pdfium::base::ValueOrDieForType(pdfium::base::CheckMax(left, 0)); - pdfium::base::CheckedNumeric end_col_safe = left; - end_col_safe += ncols; - if (!end_col_safe.IsValid()) - return false; - - int end_col = - std::min(static_cast(end_col_safe.ValueOrDie()), dest_width); - if (start_col >= end_col) - continue; - - DrawNormalTextHelper(&bitmap, pGlyph, nrows, left.ValueOrDie(), - top.ValueOrDie(), start_col, end_col, bNormal, - bBGRStripe, x_subpixel, a, r, g, b); - } - if (bitmap.IsAlphaMask()) - SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color); - else - SetDIBits(&bitmap, bmp_rect.left, bmp_rect.top); - return true; -} - -bool CFX_RenderDevice::DrawTextPath(int nChars, - const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, - FX_FLOAT font_size, - const CFX_Matrix* pText2User, - const CFX_Matrix* pUser2Device, - const CFX_GraphStateData* pGraphState, - uint32_t fill_color, - FX_ARGB stroke_color, - CFX_PathData* pClippingPath, - int nFlag) { - for (int iChar = 0; iChar < nChars; iChar++) { - const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; - CFX_Matrix matrix; - if (charpos.m_bGlyphAdjust) { - matrix = CFX_Matrix(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], - 0, 0); - } - matrix.Concat(CFX_Matrix(font_size, 0, 0, font_size, charpos.m_Origin.x, - charpos.m_Origin.y)); - const CFX_PathData* pPath = - pFont->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth); - if (!pPath) - continue; - - matrix.Concat(*pText2User); - - CFX_PathData TransformedPath(*pPath); - TransformedPath.Transform(&matrix); - if (fill_color || stroke_color) { - int fill_mode = nFlag; - if (fill_color) - fill_mode |= FXFILL_WINDING; - fill_mode |= FX_FILL_TEXT_MODE; - if (!DrawPathWithBlend(&TransformedPath, pUser2Device, pGraphState, - fill_color, stroke_color, fill_mode, - FXDIB_BLEND_NORMAL)) { - return false; - } - } - if (pClippingPath) - pClippingPath->Append(&TransformedPath, pUser2Device); - } - return true; -} diff --git a/core/fxge/ge/cfx_substfont.cpp b/core/fxge/ge/cfx_substfont.cpp deleted file mode 100644 index 475372e3d90060de1a756bf3c345c45de418654b..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cfx_substfont.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 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 "core/fxge/cfx_substfont.h" - -#include "core/fxge/fx_font.h" - -CFX_SubstFont::CFX_SubstFont() - : m_Charset(FXFONT_ANSI_CHARSET), - m_SubstFlags(0), - m_Weight(0), - m_ItalicAngle(0), - m_bSubstCJK(false), - m_WeightCJK(0), - m_bItalicCJK(false) {} diff --git a/core/fxge/ge/cttfontdesc.cpp b/core/fxge/ge/cttfontdesc.cpp deleted file mode 100644 index 269abfe7f7421dd2617bca6512590d37c8364673..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cttfontdesc.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 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 "core/fxge/ge/cttfontdesc.h" - -#include "core/fxge/fx_freetype.h" - -CTTFontDesc::~CTTFontDesc() { - if (m_Type == 1) { - if (m_SingleFace) - FXFT_Done_Face(m_SingleFace); - } else if (m_Type == 2) { - for (int i = 0; i < 16; i++) { - if (m_TTCFaces[i]) - FXFT_Done_Face(m_TTCFaces[i]); - } - } - FX_Free(m_pFontData); -} - -int CTTFontDesc::ReleaseFace(FXFT_Face face) { - if (m_Type == 1) { - if (m_SingleFace != face) - return -1; - } else if (m_Type == 2) { - int i; - for (i = 0; i < 16; i++) { - if (m_TTCFaces[i] == face) - break; - } - if (i == 16) - return -1; - } - m_RefCount--; - if (m_RefCount) - return m_RefCount; - delete this; - return 0; -} diff --git a/core/fxge/ge/cttfontdesc.h b/core/fxge/ge/cttfontdesc.h deleted file mode 100644 index d756cb947a29171f62691c3e86526da0db6316c6..0000000000000000000000000000000000000000 --- a/core/fxge/ge/cttfontdesc.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2016 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 CORE_FXGE_GE_CTTFONTDESC_H_ -#define CORE_FXGE_GE_CTTFONTDESC_H_ - -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_font.h" - -#define FX_FONT_FLAG_SERIF 0x01 -#define FX_FONT_FLAG_FIXEDPITCH 0x02 -#define FX_FONT_FLAG_ITALIC 0x04 -#define FX_FONT_FLAG_BOLD 0x08 -#define FX_FONT_FLAG_SYMBOLIC_SYMBOL 0x10 -#define FX_FONT_FLAG_SYMBOLIC_DINGBATS 0x20 -#define FX_FONT_FLAG_MULTIPLEMASTER 0x40 - -class CTTFontDesc { - public: - CTTFontDesc() : m_Type(0), m_pFontData(nullptr), m_RefCount(0) {} - ~CTTFontDesc(); - // ret < 0, releaseface not appropriate for this object. - // ret == 0, object released - // ret > 0, object still alive, other referrers. - int ReleaseFace(FXFT_Face face); - - int m_Type; - - union { - FXFT_Face m_SingleFace; - FXFT_Face m_TTCFaces[16]; - }; - uint8_t* m_pFontData; - int m_RefCount; -}; - -#endif // CORE_FXGE_GE_CTTFONTDESC_H_ diff --git a/core/fxge/ge/fx_ge_fontmap.cpp b/core/fxge/ge/fx_ge_fontmap.cpp deleted file mode 100644 index 7ac4fada5cc0e871411f6737f70aa6c58c070e3a..0000000000000000000000000000000000000000 --- a/core/fxge/ge/fx_ge_fontmap.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/ifx_systemfontinfo.h" - -static CFX_ByteString GetStringFromTable(const uint8_t* string_ptr, - uint32_t string_ptr_length, - uint16_t offset, - uint16_t length) { - if (string_ptr_length < static_cast(offset + length)) { - return CFX_ByteString(); - } - return CFX_ByteString(string_ptr + offset, length); -} - -CFX_ByteString GetNameFromTT(const uint8_t* name_table, - uint32_t name_table_size, - uint32_t name_id) { - if (!name_table || name_table_size < 6) { - return CFX_ByteString(); - } - uint32_t name_count = GET_TT_SHORT(name_table + 2); - uint32_t string_offset = GET_TT_SHORT(name_table + 4); - // We will ignore the possibility of overlap of structures and - // string table as if it's all corrupt there's not a lot we can do. - if (name_table_size < string_offset) { - return CFX_ByteString(); - } - - const uint8_t* string_ptr = name_table + string_offset; - uint32_t string_ptr_size = name_table_size - string_offset; - name_table += 6; - name_table_size -= 6; - if (name_table_size < name_count * 12) { - return CFX_ByteString(); - } - - for (uint32_t i = 0; i < name_count; i++, name_table += 12) { - if (GET_TT_SHORT(name_table + 6) == name_id && - GET_TT_SHORT(name_table) == 1 && GET_TT_SHORT(name_table + 2) == 0) { - return GetStringFromTable(string_ptr, string_ptr_size, - GET_TT_SHORT(name_table + 10), - GET_TT_SHORT(name_table + 8)); - } - } - return CFX_ByteString(); -} -#ifdef PDF_ENABLE_XFA -void* IFX_SystemFontInfo::MapFontByUnicode(uint32_t dwUnicode, - int weight, - bool bItalic, - int pitch_family) { - return nullptr; -} -#endif // PDF_ENABLE_XFA - -int IFX_SystemFontInfo::GetFaceIndex(void* hFont) { - return 0; -} - -extern "C" { -unsigned long _FTStreamRead(FXFT_Stream stream, - unsigned long offset, - unsigned char* buffer, - unsigned long count); -void _FTStreamClose(FXFT_Stream stream); -}; - -#if _FX_OS_ == _FX_ANDROID_ -std::unique_ptr IFX_SystemFontInfo::CreateDefault( - const char** pUnused) { - return nullptr; -} -#endif - -CFX_FontFaceInfo::CFX_FontFaceInfo(CFX_ByteString filePath, - CFX_ByteString faceName, - CFX_ByteString fontTables, - uint32_t fontOffset, - uint32_t fileSize) - : m_FilePath(filePath), - m_FaceName(faceName), - m_FontTables(fontTables), - m_FontOffset(fontOffset), - m_FileSize(fileSize), - m_Styles(0), - m_Charsets(0) {} diff --git a/core/fxge/ge/fx_ge_linux.cpp b/core/fxge/ge/fx_ge_linux.cpp deleted file mode 100644 index e7086bb4e0a145764e7fd139f703a17c5577de94..0000000000000000000000000000000000000000 --- a/core/fxge/ge/fx_ge_linux.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" -#include "core/fxge/ifx_systemfontinfo.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ -namespace { - -const size_t kLinuxGpNameSize = 6; - -const FX_CHAR* const g_LinuxGpFontList[][kLinuxGpNameSize] = { - {"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", - "VL Gothic regular"}, - {"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", nullptr, - "VL Gothic regular"}, - {"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", nullptr, - "VL Gothic regular"}, - {"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", nullptr, - "VL Gothic regular"}, -}; - -const FX_CHAR* const g_LinuxGbFontList[] = { - "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN", -}; - -const FX_CHAR* const g_LinuxB5FontList[] = { - "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW", -}; - -const FX_CHAR* const g_LinuxHGFontList[] = { - "UnDotum", -}; - -size_t GetJapanesePreference(const FX_CHAR* facearr, - int weight, - int pitch_family) { - CFX_ByteString face = facearr; - if (face.Find("Gothic") >= 0 || - face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - if (face.Find("PGothic") >= 0 || - face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - return 0; - } - return 1; - } - if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { - if (face.Find("PMincho") >= 0 || - face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { - return 2; - } - return 3; - } - if (!(pitch_family & FXFONT_FF_ROMAN) && weight > 400) - return 0; - - return 2; -} - -class CFX_LinuxFontInfo : public CFX_FolderFontInfo { - public: - CFX_LinuxFontInfo() {} - ~CFX_LinuxFontInfo() override {} - - void* MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const FX_CHAR* family, - int& iExact) override; - bool ParseFontCfg(const char** pUserPaths); -}; - -void* CFX_LinuxFontInfo::MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const FX_CHAR* cstr_face, - int& iExact) { - void* font = GetSubstFont(cstr_face); - if (font) { - iExact = 1; - return font; - } - bool bCJK = true; - switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: { - size_t index = GetJapanesePreference(cstr_face, weight, pitch_family); - ASSERT(index < FX_ArraySize(g_LinuxGpFontList)); - for (size_t i = 0; i < kLinuxGpNameSize; i++) { - auto it = m_FontList.find(g_LinuxGpFontList[index][i]); - if (it != m_FontList.end()) - return it->second; - } - break; - } - case FXFONT_GB2312_CHARSET: { - for (size_t i = 0; i < FX_ArraySize(g_LinuxGbFontList); ++i) { - auto it = m_FontList.find(g_LinuxGbFontList[i]); - if (it != m_FontList.end()) - return it->second; - } - break; - } - case FXFONT_CHINESEBIG5_CHARSET: { - for (size_t i = 0; i < FX_ArraySize(g_LinuxB5FontList); ++i) { - auto it = m_FontList.find(g_LinuxB5FontList[i]); - if (it != m_FontList.end()) - return it->second; - } - break; - } - case FXFONT_HANGUL_CHARSET: { - for (size_t i = 0; i < FX_ArraySize(g_LinuxHGFontList); ++i) { - auto it = m_FontList.find(g_LinuxHGFontList[i]); - if (it != m_FontList.end()) - return it->second; - } - break; - } - default: - bCJK = false; - break; - } - return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); -} - -bool CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) { - if (!pUserPaths) - return false; - - for (const char** pPath = pUserPaths; *pPath; ++pPath) - AddPath(*pPath); - return true; -} - -} // namespace - -std::unique_ptr IFX_SystemFontInfo::CreateDefault( - const char** pUserPaths) { - CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo; - if (!pInfo->ParseFontCfg(pUserPaths)) { - pInfo->AddPath("/usr/share/fonts"); - pInfo->AddPath("/usr/share/X11/fonts/Type1"); - pInfo->AddPath("/usr/share/X11/fonts/TTF"); - pInfo->AddPath("/usr/local/share/fonts"); - } - return std::unique_ptr(pInfo); -} - -void CFX_GEModule::InitPlatform() { - m_pFontMgr->SetSystemFontInfo( - IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths)); -} - -void CFX_GEModule::DestroyPlatform() {} -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ diff --git a/core/fxge/ge/fx_text_int.h b/core/fxge/ge/fx_text_int.h deleted file mode 100644 index 4de6587d4117e62640dc345ff023f434194aa24d..0000000000000000000000000000000000000000 --- a/core/fxge/ge/fx_text_int.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXGE_GE_FX_TEXT_INT_H_ -#define CORE_FXGE_GE_FX_TEXT_INT_H_ - -#include - -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" - -struct _CFX_UniqueKeyGen { - void Generate(int count, ...); - FX_CHAR m_Key[128]; - int m_KeyLen; -}; - -class CFX_SizeGlyphCache { - public: - CFX_SizeGlyphCache(); - ~CFX_SizeGlyphCache(); - std::map m_GlyphMap; -}; - -#endif // CORE_FXGE_GE_FX_TEXT_INT_H_ diff --git a/core/fxge/ifx_renderdevicedriver.cpp b/core/fxge/ifx_renderdevicedriver.cpp index 77af00f4306cf564901547c405061b6948fe2d66..eae773d75c9a510f0677a7809df94e7b309db31f 100644 --- a/core/fxge/ifx_renderdevicedriver.cpp +++ b/core/fxge/ifx_renderdevicedriver.cpp @@ -8,7 +8,7 @@ #include "core/fxcrt/fx_coordinates.h" #include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/dib/cfx_dibitmap.h" IFX_RenderDeviceDriver::~IFX_RenderDeviceDriver() {} @@ -39,44 +39,37 @@ bool IFX_RenderDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, return false; } -bool IFX_RenderDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, +bool IFX_RenderDeviceDriver::DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, uint32_t color, int blend_type) { return false; } -bool IFX_RenderDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, +bool IFX_RenderDeviceDriver::GetDIBits(const RetainPtr& pBitmap, int left, int top) { return false; } -CFX_DIBitmap* IFX_RenderDeviceDriver::GetBackDrop() { - return nullptr; +RetainPtr IFX_RenderDeviceDriver::GetBackDrop() { + return RetainPtr(); } -bool IFX_RenderDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { +bool IFX_RenderDeviceDriver::ContinueDIBits(CFX_ImageRenderer* handle, + IFX_PauseIndicator* pPause) { return false; } -void IFX_RenderDeviceDriver::CancelDIBits(void* handle) {} - bool IFX_RenderDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) { return false; } -void* IFX_RenderDeviceDriver::GetPlatformSurface() const { - return nullptr; -} - int IFX_RenderDeviceDriver::GetDriverType() const { return 0; } @@ -91,12 +84,13 @@ bool IFX_RenderDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, return false; } -bool IFX_RenderDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, - int left, - int top, - int bitmap_alpha, - int blend_type) { +bool IFX_RenderDeviceDriver::SetBitsWithMask( + const RetainPtr& pBitmap, + const RetainPtr& pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { return false; } diff --git a/core/fxge/ifx_renderdevicedriver.h b/core/fxge/ifx_renderdevicedriver.h index fd35149e42e03c7d743050c17795c0cf853ba226..e9498bdf22aa858c3a785501c96abd87e3071521 100644 --- a/core/fxge/ifx_renderdevicedriver.h +++ b/core/fxge/ifx_renderdevicedriver.h @@ -7,17 +7,22 @@ #ifndef CORE_FXGE_IFX_RENDERDEVICEDRIVER_H_ #define CORE_FXGE_IFX_RENDERDEVICEDRIVER_H_ +#include + +#include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" class CFX_DIBitmap; class CFX_DIBSource; class CFX_Font; class CFX_GraphStateData; +class CFX_ImageRenderer; class CFX_Matrix; class CFX_PathData; class CPDF_ShadingPattern; class FXTEXT_CHARPOS; -class IFX_Pause; +class IFX_PauseIndicator; struct FX_RECT; class IFX_RenderDeviceDriver { @@ -49,23 +54,23 @@ class IFX_RenderDeviceDriver { virtual bool FillRectWithBlend(const FX_RECT* pRect, uint32_t fill_color, int blend_type); - virtual bool DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, + virtual bool DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, uint32_t color, int blend_type); virtual bool GetClipBox(FX_RECT* pRect) = 0; - virtual bool GetDIBits(CFX_DIBitmap* pBitmap, int left, int top); - virtual CFX_DIBitmap* GetBackDrop(); - virtual bool SetDIBits(const CFX_DIBSource* pBitmap, + virtual bool GetDIBits(const RetainPtr& pBitmap, + int left, + int top); + virtual RetainPtr GetBackDrop(); + virtual bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int dest_left, int dest_top, int blend_type) = 0; - virtual bool StretchDIBits(const CFX_DIBSource* pBitmap, + virtual bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -74,22 +79,21 @@ class IFX_RenderDeviceDriver { const FX_RECT* pClipRect, uint32_t flags, int blend_type) = 0; - virtual bool StartDIBits(const CFX_DIBSource* pBitmap, + virtual bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags, - void*& handle, + std::unique_ptr* handle, int blend_type) = 0; - virtual bool ContinueDIBits(void* handle, IFX_Pause* pPause); - virtual void CancelDIBits(void* handle); + virtual bool ContinueDIBits(CFX_ImageRenderer* handle, + IFX_PauseIndicator* pPause); virtual bool DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color); - virtual void* GetPlatformSurface() const; virtual int GetDriverType() const; virtual void ClearDriver(); virtual bool DrawShading(const CPDF_ShadingPattern* pPattern, @@ -97,8 +101,8 @@ class IFX_RenderDeviceDriver { const FX_RECT& clip_rect, int alpha, bool bAlphaMode); - virtual bool SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, + virtual bool SetBitsWithMask(const RetainPtr& pBitmap, + const RetainPtr& pMask, int left, int top, int bitmap_alpha, diff --git a/core/fxge/ifx_systemfontinfo.h b/core/fxge/ifx_systemfontinfo.h index 1ab0ab677c5af94eb129d618b6c08d791e9ef228..1ae097b9f96f537e56bac3d4cb3f4a178ad63fba 100644 --- a/core/fxge/ifx_systemfontinfo.h +++ b/core/fxge/ifx_systemfontinfo.h @@ -10,7 +10,6 @@ #include #include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/fx_font.h" const uint32_t kTableNAME = FXDWORD_GET_MSBFIRST("name"); const uint32_t kTableTTCF = FXDWORD_GET_MSBFIRST("ttcf"); @@ -20,15 +19,14 @@ class IFX_SystemFontInfo { static std::unique_ptr CreateDefault( const char** pUserPaths); - virtual ~IFX_SystemFontInfo() {} + virtual ~IFX_SystemFontInfo() = default; virtual bool EnumFontList(CFX_FontMapper* pMapper) = 0; virtual void* MapFont(int weight, bool bItalic, int charset, int pitch_family, - const FX_CHAR* face, - int& iExact) = 0; + const char* face) = 0; #ifdef PDF_ENABLE_XFA virtual void* MapFontByUnicode(uint32_t dwUnicode, @@ -37,13 +35,13 @@ class IFX_SystemFontInfo { int pitch_family); #endif // PDF_ENABLE_XFA - virtual void* GetFont(const FX_CHAR* face) = 0; + virtual void* GetFont(const char* face) = 0; virtual uint32_t GetFontData(void* hFont, uint32_t table, uint8_t* buffer, uint32_t size) = 0; - virtual bool GetFaceName(void* hFont, CFX_ByteString& name) = 0; - virtual bool GetFontCharset(void* hFont, int& charset) = 0; + virtual bool GetFaceName(void* hFont, ByteString* name) = 0; + virtual bool GetFontCharset(void* hFont, int* charset) = 0; virtual int GetFaceIndex(void* hFont); virtual void DeleteFont(void* hFont) = 0; }; diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index e536b6742f795069253a938941f5839c33da775a..ab8efff72c4b9f357bb80126f2dac1e9f2f33a9e 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -6,31 +6,34 @@ #include #include +#include "core/fpdfapi/page/cpdf_expintfunc.h" +#include "core/fpdfapi/page/cpdf_function.h" #include "core/fpdfapi/page/cpdf_meshstream.h" +#include "core/fpdfapi/page/cpdf_sampledfunc.h" #include "core/fpdfapi/page/cpdf_shadingpattern.h" -#include "core/fpdfapi/page/pageint.h" +#include "core/fpdfapi/page/cpdf_stitchfunc.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_memory.h" -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/dib/cfx_bitmapcomposer.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/dib/cfx_imagestretcher.h" #include "core/fxge/skia/fx_skia_device.h" - -#ifdef _SKIA_SUPPORT_PATHS_ -#include "core/fxge/ge/cfx_cliprgn.h" -#endif // _SKIA_SUPPORT_PATHS_ - +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" - #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkClipOp.h" +#include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/core/SkRSXform.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -38,6 +41,10 @@ #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/pathops/SkPathOps.h" +#ifdef _SKIA_SUPPORT_PATHS_ +#include "core/fxge/cfx_cliprgn.h" +#endif // _SKIA_SUPPORT_PATHS_ + #ifdef _SKIA_SUPPORT_ #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkColorPriv.h" @@ -48,12 +55,12 @@ namespace { #ifdef _SKIA_SUPPORT_PATHS_ -void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, +void RgbByteOrderTransferBitmap(const RetainPtr& pBitmap, int dest_left, int dest_top, int width, int height, - const CFX_DIBSource* pSrcBitmap, + const RetainPtr& pSrcBitmap, int src_left, int src_top) { if (!pBitmap) @@ -109,7 +116,7 @@ void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, } } } else { - ASSERT(false); + NOTREACHED(); } return; } @@ -144,13 +151,17 @@ void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, return; } - ASSERT(false); + NOTREACHED(); } #endif // _SKIA_SUPPORT_PATHS_ #define SHOW_SKIA_PATH 0 // set to 1 to print the path contents +#if SHOW_SKIA_PATH +#define SHOW_SKIA_PATH_SHORTHAND 0 // set to 1 for abbreviated path contents +#endif #define DRAW_SKIA_CLIP 0 // set to 1 to draw a green rectangle around the clip +#define SHOW_TEXT_GLYPHS 0 // set to 1 to print unichar equivalent of glyph #if SHOW_SKIA_PATH void DebugShowSkiaPaint(const SkPaint& paint) { @@ -161,69 +172,63 @@ void DebugShowSkiaPaint(const SkPaint& paint) { paint.getStrokeWidth()); } } - -void DebugShowCanvasMatrix(const SkCanvas* canvas) { - SkMatrix matrix = canvas->getTotalMatrix(); - SkScalar m[9]; - matrix.get9(m); - printf("matrix (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n", m[0], m[1], m[2], m[3], - m[4], m[5], m[6], m[7], m[8]); -} #endif // SHOW_SKIA_PATH void DebugShowSkiaPath(const SkPath& path) { #if SHOW_SKIA_PATH - char buffer[4096]; - sk_bzero(buffer, sizeof(buffer)); - SkMemoryWStream stream(buffer, sizeof(buffer)); +#if SHOW_SKIA_PATH_SHORTHAND + printf(" **\n"); +#else + SkDynamicMemoryWStream stream; path.dump(&stream, false, false); - printf("%s", buffer); + std::unique_ptr storage; + storage.reset(FX_Alloc(char, stream.bytesWritten())); + stream.copyTo(storage.get()); + printf("%.*s", (int)stream.bytesWritten(), storage.get()); +#endif // SHOW_SKIA_PATH_SHORTHAND #endif // SHOW_SKIA_PATH } -void DebugShowCanvasClip(const SkCanvas* canvas) { +void DebugShowCanvasClip(CFX_SkiaDeviceDriver* driver, const SkCanvas* canvas) { #if SHOW_SKIA_PATH - SkRect local; - SkIRect device; - canvas->getClipBounds(&local); + SkMatrix matrix = canvas->getTotalMatrix(); + SkScalar m[9]; + matrix.get9(m); + printf("matrix (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n", m[0], m[1], m[2], m[3], + m[4], m[5], m[6], m[7], m[8]); + SkRect local = canvas->getLocalClipBounds(); + SkIRect device = canvas->getDeviceClipBounds(); + printf("local bounds %g %g %g %g\n", local.fLeft, local.fTop, local.fRight, local.fBottom); - canvas->getClipDeviceBounds(&device); printf("device bounds %d %d %d %d\n", device.fLeft, device.fTop, device.fRight, device.fBottom); + FX_RECT clipBox; + driver->GetClipBox(&clipBox); + printf("reported bounds %d %d %d %d\n", clipBox.left, clipBox.top, + clipBox.right, clipBox.bottom); #endif // SHOW_SKIA_PATH } -#if SHOW_SKIA_PATH -void DebugShowSkiaPaint(const SkPaint& paint) { - if (SkPaint::kFill_Style == paint.getStyle()) { - printf("fill 0x%08x\n", paint.getColor()); - } else { - printf("stroke 0x%08x width %g\n", paint.getColor(), - paint.getStrokeWidth()); - } -} -#endif // SHOW_SKIA_PATH - -void DebugShowSkiaDrawPath(const SkCanvas* canvas, +void DebugShowSkiaDrawPath(CFX_SkiaDeviceDriver* driver, + const SkCanvas* canvas, const SkPaint& paint, const SkPath& path) { #if SHOW_SKIA_PATH DebugShowSkiaPaint(paint); - DebugShowCanvasMatrix(canvas); - DebugShowCanvasClip(canvas); + DebugShowCanvasClip(driver, canvas); DebugShowSkiaPath(path); printf("\n"); #endif // SHOW_SKIA_PATH } -void DebugShowSkiaDrawRect(const SkCanvas* canvas, +void DebugShowSkiaDrawRect(CFX_SkiaDeviceDriver* driver, + const SkCanvas* canvas, const SkPaint& paint, const SkRect& rect) { #if SHOW_SKIA_PATH DebugShowSkiaPaint(paint); - DebugShowCanvasMatrix(canvas); - DebugShowCanvasClip(canvas); + DebugShowCanvasClip(driver, canvas); printf("rect %g %g %g %g\n", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); #endif // SHOW_SKIA_PATH @@ -258,18 +263,18 @@ void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {} #endif // DRAW_SKIA_CLIP #ifdef _SKIA_SUPPORT_ -static void DebugValidate(const CFX_DIBitmap* bitmap, - const CFX_DIBitmap* device) { +static void DebugValidate(const RetainPtr& bitmap, + const RetainPtr& device) { if (bitmap) { SkASSERT(bitmap->GetBPP() == 8 || bitmap->GetBPP() == 32); if (bitmap->GetBPP() == 32) { - bitmap->DebugVerifyBitmapIsPreMultiplied(); + bitmap->DebugVerifyBitmapIsPreMultiplied(nullptr); } } if (device) { SkASSERT(device->GetBPP() == 8 || device->GetBPP() == 32); if (device->GetBPP() == 32) { - device->DebugVerifyBitmapIsPreMultiplied(); + device->DebugVerifyBitmapIsPreMultiplied(nullptr); } } } @@ -368,7 +373,7 @@ bool AddColors(const CPDF_ExpIntFunc* pFunc, SkTDArray* skColors) { return true; } -uint8_t FloatToByte(FX_FLOAT f) { +uint8_t FloatToByte(float f) { ASSERT(0 <= f && f <= 1); return (uint8_t)(f * 255.99f); } @@ -395,25 +400,25 @@ bool AddSamples(const CPDF_SampledFunc* pFunc, if (pFunc->GetSampleStream()->GetSize() < sampleCount * 3 * sampleSize / 8) return false; - FX_FLOAT colorsMin[3]; - FX_FLOAT colorsMax[3]; + float colorsMin[3]; + float colorsMax[3]; for (int i = 0; i < 3; ++i) { colorsMin[i] = pFunc->GetRange(i * 2); colorsMax[i] = pFunc->GetRange(i * 2 + 1); } const uint8_t* pSampleData = pFunc->GetSampleStream()->GetData(); for (uint32_t i = 0; i < sampleCount; ++i) { - FX_FLOAT floatColors[3]; + float floatColors[3]; for (uint32_t j = 0; j < 3; ++j) { int sample = GetBits32(pSampleData, (i * 3 + j) * sampleSize, sampleSize); - FX_FLOAT interp = (FX_FLOAT)sample / (sampleCount - 1); + float interp = (float)sample / (sampleCount - 1); floatColors[j] = colorsMin[j] + (colorsMax[j] - colorsMin[j]) * interp; } SkColor color = SkPackARGB32(0xFF, FloatToByte(floatColors[0]), FloatToByte(floatColors[1]), FloatToByte(floatColors[2])); skColors->push(color); - skPos->push((FX_FLOAT)i / (sampleCount - 1)); + skPos->push((float)i / (sampleCount - 1)); } return true; } @@ -421,7 +426,7 @@ bool AddSamples(const CPDF_SampledFunc* pFunc, bool AddStitching(const CPDF_StitchFunc* pFunc, SkTDArray* skColors, SkTDArray* skPos) { - FX_FLOAT boundsStart = pFunc->GetDomain(0); + float boundsStart = pFunc->GetDomain(0); const auto& subFunctions = pFunc->GetSubFunctions(); int subFunctionCount = subFunctions.size(); @@ -431,7 +436,7 @@ bool AddStitching(const CPDF_StitchFunc* pFunc, return false; if (!AddColors(pSubFunc, skColors)) return false; - FX_FLOAT boundsEnd = + float boundsEnd = i < subFunctionCount - 1 ? pFunc->GetBound(i + 1) : pFunc->GetDomain(1); skPos->push(boundsStart); skPos->push(boundsEnd); @@ -522,8 +527,10 @@ void ClipAngledGradient(const SkPoint pts[2], maxBounds = i; } } - ASSERT(minBounds >= 0); - ASSERT(maxBounds != minBounds && maxBounds >= 0); + if (minBounds < 0 || maxBounds < 0) + return; + if (minBounds == maxBounds) + return; // construct a clip parallel to the gradient that goes through // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the // gradient that goes through startEdgePt, endEdgePt. @@ -558,10 +565,9 @@ void SetBitmapPaint(bool isAlphaMask, paint->setAlpha(bitmap_alpha); } -bool Upsample(const CFX_DIBSource* pSource, +bool Upsample(const RetainPtr& pSource, std::unique_ptr& dst8Storage, std::unique_ptr& dst32Storage, - SkColorTable** ctPtr, SkBitmap* skBitmap, int* widthPtr, int* heightPtr, @@ -645,8 +651,7 @@ bool Upsample(const CFX_DIBSource* pSource, } SkImageInfo imageInfo = SkImageInfo::Make(width, height, colorType, alphaType); - skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr, - nullptr); + skBitmap->installPixels(imageInfo, buffer, rowBytes); *widthPtr = width; *heightPtr = height; return true; @@ -674,8 +679,9 @@ class SkiaState { // mark all cached state as uninitialized explicit SkiaState(CFX_SkiaDeviceDriver* pDriver) : m_pDriver(pDriver), - m_pFont(nullptr), + m_pTypeFace(nullptr), m_fontSize(0), + m_scaleX(0), m_fillColor(0), m_strokeColor(0), m_blendType(0), @@ -708,7 +714,7 @@ class SkiaState { if (Accumulator::kText == m_type || drawIndex != m_commandIndex || (Accumulator::kPath == m_type && DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode, - blend_type, m_pDriver->m_bGroupKnockout))) { + blend_type, m_pDriver->GetGroupKnockout()))) { Flush(); } if (Accumulator::kPath != m_type) { @@ -723,7 +729,7 @@ class SkiaState { m_fillColor = fill_color; m_strokeColor = stroke_color; m_blendType = blend_type; - m_groupKnockout = m_pDriver->m_bGroupKnockout; + m_groupKnockout = m_pDriver->GetGroupKnockout(); if (pMatrix) m_drawMatrix = *pMatrix; m_drawIndex = m_commandIndex; @@ -767,7 +773,7 @@ class SkiaState { #ifdef _SKIA_SUPPORT_PATHS_ m_pDriver->PreMultiply(); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowSkiaDrawPath(skCanvas, skPaint, *fillPath); + DebugShowSkiaDrawPath(m_pDriver.Get(), skCanvas, skPaint, *fillPath); skCanvas->drawPath(*fillPath, skPaint); } if (stroke_alpha) { @@ -776,7 +782,7 @@ class SkiaState { #ifdef _SKIA_SUPPORT_PATHS_ m_pDriver->PreMultiply(); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowSkiaDrawPath(skCanvas, skPaint, m_skPath); + DebugShowSkiaDrawPath(m_pDriver.Get(), skCanvas, skPaint, m_skPath); skCanvas->drawPath(m_skPath, skPaint); } skCanvas->restore(); @@ -784,26 +790,67 @@ class SkiaState { m_type = Accumulator::kNone; } + bool HasRSX(int nChars, + const FXTEXT_CHARPOS* pCharPos, + float* scaleXPtr, + bool* oneAtATimePtr) { + bool useRSXform = false; + bool oneAtATime = false; + float scaleX = 1; + for (int index = 0; index < nChars; ++index) { + const FXTEXT_CHARPOS& cp = pCharPos[index]; + if (!cp.m_bGlyphAdjust) + continue; + bool upright = 0 == cp.m_AdjustMatrix[1] && 0 == cp.m_AdjustMatrix[2]; + if (cp.m_AdjustMatrix[0] != cp.m_AdjustMatrix[3]) { + if (upright && 1 == cp.m_AdjustMatrix[3]) { + if (1 == scaleX) + scaleX = cp.m_AdjustMatrix[0]; + else if (scaleX != cp.m_AdjustMatrix[0]) + oneAtATime = true; + } else { + oneAtATime = true; + } + } else if (cp.m_AdjustMatrix[1] != -cp.m_AdjustMatrix[2]) { + oneAtATime = true; + } else { + useRSXform = true; + } + } + *oneAtATimePtr = oneAtATime; + *scaleXPtr = oneAtATime ? 1 : scaleX; + return oneAtATime ? false : useRSXform; + } + bool DrawText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pMatrix, - FX_FLOAT font_size, + float font_size, uint32_t color) { if (m_debugDisable) return false; Dump(__func__); + float scaleX = 1; + bool oneAtATime = false; + bool hasRSX = HasRSX(nChars, pCharPos, &scaleX, &oneAtATime); + if (oneAtATime) { + Flush(); + return false; + } int drawIndex = SkTMin(m_drawIndex, m_commands.count()); if (Accumulator::kPath == m_type || drawIndex != m_commandIndex || (Accumulator::kText == m_type && - FontChanged(pFont, pMatrix, font_size, color))) { + (FontChanged(pFont, pMatrix, font_size, scaleX, color) || + hasRSX == !m_rsxform.count()))) { Flush(); } if (Accumulator::kText != m_type) { m_positions.setCount(0); m_glyphs.setCount(0); - m_pFont = pFont; + m_pTypeFace = pFont->GetFace() ? pFont->GetDeviceCache() : nullptr; m_fontSize = font_size; + m_scaleX = scaleX; m_fillColor = color; m_drawMatrix = *pMatrix; m_drawIndex = m_commandIndex; @@ -812,6 +859,9 @@ class SkiaState { int count = m_positions.count(); m_positions.setCount(nChars + count); m_glyphs.setCount(nChars + count); + if (hasRSX) { + m_rsxform.setCount(nChars + count); + } SkScalar flip = m_fontSize < 0 ? -1 : 1; SkScalar vFlip = flip; if (pFont->IsVertical()) @@ -821,12 +871,33 @@ class SkiaState { m_positions[index + count] = {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip}; m_glyphs[index + count] = static_cast(cp.m_GlyphIndex); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + if (cp.m_ExtGID) + m_glyphs[index + count] = static_cast(cp.m_ExtGID); +#endif } SkPoint delta; if (MatrixOffset(pMatrix, &delta)) { for (int index = 0; index < nChars; ++index) m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip); } + if (hasRSX) { + for (int index = 0; index < nChars; ++index) { + const FXTEXT_CHARPOS& cp = pCharPos[index]; + SkRSXform* rsxform = &m_rsxform[index + count]; + if (cp.m_bGlyphAdjust) { + rsxform->fSCos = cp.m_AdjustMatrix[0]; + rsxform->fSSin = cp.m_AdjustMatrix[1]; + rsxform->fTx = cp.m_AdjustMatrix[0] * m_positions[index].fX; + rsxform->fTy = cp.m_AdjustMatrix[1] * m_positions[index].fY; + } else { + rsxform->fSCos = 1; + rsxform->fSSin = 0; + rsxform->fTx = m_positions[index].fX; + rsxform->fTy = m_positions[index].fY; + } + } + } return true; } @@ -835,12 +906,13 @@ class SkiaState { SkPaint skPaint; skPaint.setAntiAlias(true); skPaint.setColor(m_fillColor); - if (m_pFont->GetFace()) { // exclude placeholder test fonts - sk_sp typeface(SkSafeRef(m_pFont->GetDeviceCache())); + if (m_pTypeFace) { // exclude placeholder test fonts + sk_sp typeface(SkSafeRef(m_pTypeFace.Get())); skPaint.setTypeface(typeface); } skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); skPaint.setHinting(SkPaint::kNo_Hinting); + skPaint.setTextScaleX(m_scaleX); skPaint.setTextSize(SkTAbs(m_fontSize)); skPaint.setSubpixelText(true); SkCanvas* skCanvas = m_pDriver->SkiaCanvas(); @@ -851,25 +923,57 @@ class SkiaState { #ifdef _SKIA_SUPPORT_PATHS_ m_pDriver->PreMultiply(); #endif // _SKIA_SUPPORT_PATHS_ - skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2, - m_positions.begin(), skPaint); +#if SHOW_TEXT_GLYPHS + SkTDArray text; + text.setCount(m_glyphs.count()); + skPaint.glyphsToUnichars(m_glyphs.begin(), m_glyphs.count(), text.begin()); + for (size_t i = 0; i < m_glyphs.count(); ++i) + printf("%lc", m_glyphs[i]); + printf("\n"); +#endif + if (m_rsxform.count()) { + skCanvas->drawTextRSXform(m_glyphs.begin(), m_glyphs.count() * 2, + m_rsxform.begin(), nullptr, skPaint); + } else { + skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2, + m_positions.begin(), skPaint); + } skCanvas->restore(); m_drawIndex = INT_MAX; m_type = Accumulator::kNone; } + bool IsEmpty() { return !m_commands.count(); } + bool SetClipFill(const CFX_PathData* pPathData, const CFX_Matrix* pMatrix, int fill_mode) { if (m_debugDisable) return false; Dump(__func__); - SkPath skClipPath = BuildPath(pPathData); - skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE - ? SkPath::kEvenOdd_FillType - : SkPath::kWinding_FillType); - SkMatrix skMatrix = ToSkMatrix(*pMatrix); - skClipPath.transform(skMatrix); + SkPath skClipPath; + if (pPathData->GetPoints().size() == 5 || + pPathData->GetPoints().size() == 4) { + CFX_FloatRect rectf; + if (pPathData->IsRect(pMatrix, &rectf)) { + rectf.Intersect(CFX_FloatRect( + 0, 0, + static_cast(m_pDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(m_pDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT)))); + FX_RECT outer = rectf.GetOuterRect(); + // note that PDF's y-axis goes up; Skia's y-axis goes down + skClipPath.addRect({(float)outer.left, (float)outer.bottom, + (float)outer.right, (float)outer.top}); + } + } + if (skClipPath.isEmpty()) { + skClipPath = BuildPath(pPathData); + skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE + ? SkPath::kEvenOdd_FillType + : SkPath::kWinding_FillType); + SkMatrix skMatrix = ToSkMatrix(*pMatrix); + skClipPath.transform(skMatrix); + } return SetClip(skClipPath); } @@ -945,21 +1049,21 @@ class SkiaState { return false; Dump(__func__); int count = m_commands.count(); - if (m_commandIndex < count - 1) { - if (Clip::kSave == m_commands[m_commandIndex + 1]) { + if (m_commandIndex < count) { + if (Clip::kSave == m_commands[m_commandIndex]) { ++m_commandIndex; return true; } Flush(); AdjustClip(m_commandIndex); - m_commands[++m_commandIndex] = Clip::kSave; + m_commands[m_commandIndex] = Clip::kSave; m_clips[m_commandIndex] = m_skEmptyPath; } else { AdjustClip(m_commandIndex); m_commands.push(Clip::kSave); m_clips.push_back(m_skEmptyPath); - ++m_commandIndex; } + ++m_commandIndex; return true; } @@ -990,10 +1094,14 @@ class SkiaState { bool FontChanged(CFX_Font* pFont, const CFX_Matrix* pMatrix, - FX_FLOAT font_size, + float font_size, + float scaleX, uint32_t color) const { - return pFont != m_pFont || MatrixChanged(pMatrix, m_drawMatrix) || - font_size != m_fontSize || color != m_fillColor; + CFX_TypeFace* typeface = + pFont->GetFace() ? pFont->GetDeviceCache() : nullptr; + return typeface != m_pTypeFace || MatrixChanged(pMatrix, m_drawMatrix) || + font_size != m_fontSize || scaleX != m_scaleX || + color != m_fillColor; } bool MatrixChanged(const CFX_Matrix* pMatrix, @@ -1094,38 +1202,197 @@ class SkiaState { void Dump(const char* where) const { #if SHOW_SKIA_PATH - printf("\n%s\nSkia Save Count %d:\n", where, - m_pDriver->m_pCanvas->getSaveCount()); + if (m_debugDisable) + return; + printf( + "\n%s\nSkia Save Count %d Agg Save Stack/Count %d/%d" + " Cache Save Index/Count %d/%d\n", + where, m_pDriver->m_pCanvas->getSaveCount(), + (int)m_pDriver->m_StateStack.size(), AggSaveCount(m_pDriver), + m_commandIndex, CacheSaveCount(m_commands, m_commandIndex)); printf("Cache:\n"); +#if SHOW_SKIA_PATH_SHORTHAND + bool dumpedPath = false; +#endif for (int index = 0; index < m_commands.count(); ++index) { +#if SHOW_SKIA_PATH_SHORTHAND + if (Clip::kSave == m_commands[index] && dumpedPath) { + printf("\n"); + dumpedPath = false; + } +#endif DumpPrefix(index); switch (m_commands[index]) { case Clip::kSave: printf("Save %d\n", ++m_debugSaveCounter); break; case Clip::kPath: +#if SHOW_SKIA_PATH_SHORTHAND + printf("*"); + dumpedPath = true; +#else m_clips[index].dump(); +#endif break; default: printf("unknown\n"); } } +#if SHOW_SKIA_PATH_SHORTHAND + if (dumpedPath) + printf("\n"); +#endif DumpEndPrefix(); -#endif // SHOW_SKIA_PATH -#ifdef SK_DEBUG int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount(); int cacheSaveCount = 1; SkASSERT(m_clipIndex <= m_commands.count()); for (int index = 0; index < m_clipIndex; ++index) cacheSaveCount += Clip::kSave == m_commands[index]; SkASSERT(skCanvasSaveCount == cacheSaveCount); +#endif // SHOW_SKIA_PATH + } + +#if SHOW_SKIA_PATH + static int AggSaveCount(const UnownedPtr driver) { + FX_RECT last; + int aggSaveCount = 0; + bool foundLast = false; + for (int index = 0; index < (int)driver->m_StateStack.size(); ++index) { + if (!driver->m_StateStack[index]) { + continue; + } + if (driver->m_StateStack[index]->GetType() != CFX_ClipRgn::RectI) { + aggSaveCount += 1; + foundLast = false; + continue; + } + if (!foundLast || memcmp(&last, &driver->m_StateStack[index]->GetBox(), + sizeof(FX_RECT))) { + aggSaveCount += 1; + foundLast = true; + last = driver->m_StateStack[index]->GetBox(); + } + } + if (driver->m_pClipRgn) { + CFX_ClipRgn::ClipType clipType = driver->m_pClipRgn->GetType(); + if (clipType != CFX_ClipRgn::RectI || !foundLast || + memcmp(&last, &driver->m_pClipRgn->GetBox(), sizeof(FX_RECT))) { + aggSaveCount += 1; + } + } + return aggSaveCount; + } + + static int CacheSaveCount(const SkTDArray& commands, + int commandIndex) { + int cacheSaveCount = 0; + bool newPath = false; + for (int index = 0; index < commandIndex; ++index) { + if (Clip::kSave == commands[index]) { + newPath = true; + } else if (newPath) { + ++cacheSaveCount; + newPath = false; + } + } + return cacheSaveCount; + } #endif + + void DebugCheckClip() { +#if SHOW_SKIA_PATH + if (m_debugDisable) + return; + int aggSaveCount = AggSaveCount(m_pDriver); + int cacheSaveCount = CacheSaveCount(m_commands, m_commandIndex); + SkASSERT(m_clipIndex <= m_commands.count()); + if (aggSaveCount != cacheSaveCount) { + // may not signify a bug if counts don't match + printf("aggSaveCount %d != cacheSaveCount %d\n", aggSaveCount, + cacheSaveCount); + DumpClipStacks(); + } + for (int aggIndex = 0; aggIndex < (int)m_pDriver->m_StateStack.size(); + ++aggIndex) { + if (!m_pDriver->m_StateStack[aggIndex]) + continue; + if (m_pDriver->m_StateStack[aggIndex]->GetType() != CFX_ClipRgn::RectI) + continue; + const FX_RECT& aggRect = m_pDriver->m_StateStack[aggIndex]->GetBox(); + SkRect skRect = SkRect::MakeLTRB(aggRect.left, aggRect.top, aggRect.right, + aggRect.bottom); + bool foundMatch = false; + for (int skIndex = 0; skIndex < m_commandIndex; ++skIndex) { + if (Clip::kPath != m_commands[skIndex]) + continue; + const SkPath& clip = m_clips[skIndex]; + SkRect bounds; + if (!clip.isRect(&bounds)) + continue; + bounds.roundOut(&bounds); + if (skRect == bounds) { + foundMatch = true; + break; + } + } + if (!foundMatch) { + DumpClipStacks(); + SkASSERT(0); + } + } +#endif // SHOW_SKIA_PATH + } + +#if SHOW_SKIA_PATH + void DumpClipStacks() const { + if (m_debugDisable) + return; + printf("\ncache\n"); + for (int index = 0; index < m_commandIndex; ++index) { + DumpPrefix(index); + switch (m_commands[index]) { + case Clip::kSave: + printf("Save\n"); + break; + case Clip::kPath: + m_clips[index].dump(); + break; + default: + printf("unknown\n"); + } + } + printf("\nagg\n"); + for (int index = 0; index < (int)m_pDriver->m_StateStack.size(); ++index) { + if (!m_pDriver->m_StateStack[index]) { + printf("null\n"); + continue; + } + CFX_ClipRgn::ClipType clipType = + m_pDriver->m_StateStack[index]->GetType(); + const FX_RECT& box = m_pDriver->m_StateStack[index]->GetBox(); + printf("stack rect: %d,%d,%d,%d mask=%s\n", box.left, box.top, box.right, + box.bottom, + CFX_ClipRgn::MaskF == clipType + ? "1" + : CFX_ClipRgn::RectI == clipType ? "0" : "?"); + } + if (m_pDriver->m_pClipRgn) { + const FX_RECT& box = m_pDriver->m_pClipRgn->GetBox(); + CFX_ClipRgn::ClipType clipType = m_pDriver->m_pClipRgn->GetType(); + printf("clip rect: %d,%d,%d,%d mask=%s\n", box.left, box.top, box.right, + box.bottom, + CFX_ClipRgn::MaskF == clipType + ? "1" + : CFX_ClipRgn::RectI == clipType ? "0" : "?"); + } } +#endif // SHOW_SKIA_PATH private: SkTArray m_clips; // stack of clips that may be reused SkTDArray m_commands; // stack of clip-related commands SkTDArray m_positions; // accumulator for text positions + SkTDArray m_rsxform; // accumulator for txt rotate/scale/translate SkTDArray m_glyphs; // accumulator for text glyphs SkPath m_skPath; // accumulator for path contours SkPath m_skEmptyPath; // used as placehold in the clips array @@ -1133,9 +1400,10 @@ class SkiaState { CFX_GraphStateData m_clipState; CFX_GraphStateData m_drawState; CFX_Matrix m_clipMatrix; - CFX_SkiaDeviceDriver* m_pDriver; - CFX_Font* m_pFont; - FX_FLOAT m_fontSize; + UnownedPtr m_pDriver; + UnownedPtr m_pTypeFace; + float m_fontSize; + float m_scaleX; uint32_t m_fillColor; uint32_t m_strokeColor; int m_blendType; @@ -1148,10 +1416,16 @@ class SkiaState { bool m_groupKnockout; bool m_debugDisable; // turn off cache for debugging #if SHOW_SKIA_PATH + public: mutable int m_debugSaveCounter; + static int m_debugInitCounter; #endif }; +#if SHOW_SKIA_PATH +int SkiaState::m_debugInitCounter; +#endif + // convert a stroking path to scanlines void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, const CFX_GraphStateData* pGraphState, @@ -1187,27 +1461,28 @@ void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, inverse.set(SkMatrix::kMTransY, 0); SkVector deviceUnits[2] = {{0, 1}, {1, 0}}; inverse.mapPoints(deviceUnits, SK_ARRAY_COUNT(deviceUnits)); - FX_FLOAT width = + float width = SkTMax(pGraphState->m_LineWidth, SkTMin(deviceUnits[0].length(), deviceUnits[1].length())); if (pGraphState->m_DashArray) { int count = (pGraphState->m_DashCount + 1) / 2; - SkScalar* intervals = FX_Alloc2D(SkScalar, count, sizeof(SkScalar)); + std::unique_ptr intervals( + FX_Alloc2D(SkScalar, count, sizeof(SkScalar))); // Set dash pattern for (int i = 0; i < count; i++) { - FX_FLOAT on = pGraphState->m_DashArray[i * 2]; + float on = pGraphState->m_DashArray[i * 2]; if (on <= 0.000001f) on = 1.f / 10; - FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount - ? on - : pGraphState->m_DashArray[i * 2 + 1]; + float off = i * 2 + 1 == pGraphState->m_DashCount + ? on + : pGraphState->m_DashArray[i * 2 + 1]; if (off < 0) off = 0; - intervals[i * 2] = on; - intervals[i * 2 + 1] = off; + intervals.get()[i * 2] = on; + intervals.get()[i * 2 + 1] = off; } - spaint->setPathEffect( - SkDashPathEffect::Make(intervals, count * 2, pGraphState->m_DashPhase)); + spaint->setPathEffect(SkDashPathEffect::Make(intervals.get(), count * 2, + pGraphState->m_DashPhase)); } spaint->setStyle(SkPaint::kStroke_Style); spaint->setAntiAlias(true); @@ -1217,10 +1492,11 @@ void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, spaint->setStrokeJoin(join); } -CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, - bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, - bool bGroupKnockout) +CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver( + const RetainPtr& pBitmap, + bool bRgbByteOrder, + const RetainPtr& pOriDevice, + bool bGroupKnockout) : m_pBitmap(pBitmap), m_pOriDevice(pOriDevice), m_pRecorder(nullptr), @@ -1237,9 +1513,7 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap->GetBPP() == 8 ? kAlpha_8_SkColorType : kN32_SkColorType, kOpaque_SkAlphaType); - skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch(), - nullptr, // FIXME(caryclark) set color table - nullptr, nullptr); + skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch()); m_pCanvas = new SkCanvas(skBitmap); } @@ -1274,11 +1548,15 @@ void CFX_SkiaDeviceDriver::Flush() { m_pCache->Flush(); } +void CFX_SkiaDeviceDriver::PreMultiply() { + m_pBitmap->PreMultiply(); +} + bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) { if (m_pCache->DrawText(nChars, pCharPos, pFont, pObject2Device, font_size, color)) { @@ -1304,15 +1582,89 @@ bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, positions.setCount(nChars); SkTDArray glyphs; glyphs.setCount(nChars); + bool useRSXform = false; + bool oneAtATime = false; for (int index = 0; index < nChars; ++index) { const FXTEXT_CHARPOS& cp = pCharPos[index]; positions[index] = {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip}; + if (cp.m_bGlyphAdjust) { + useRSXform = true; + if (cp.m_AdjustMatrix[0] != cp.m_AdjustMatrix[3] || + cp.m_AdjustMatrix[1] != -cp.m_AdjustMatrix[2]) { + oneAtATime = true; + } + } glyphs[index] = static_cast(cp.m_GlyphIndex); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + if (cp.m_ExtGID) + glyphs[index] = static_cast(cp.m_ExtGID); +#endif } + if (oneAtATime) + useRSXform = false; +#if SHOW_TEXT_GLYPHS + SkTDArray text; + text.setCount(glyphs.count()); + paint.glyphsToUnichars(glyphs.begin(), glyphs.count(), text.begin()); + for (size_t i = 0; i < glyphs.count(); ++i) + printf("%lc", text[i]); + printf("\n"); +#endif #ifdef _SKIA_SUPPORT_PATHS_ m_pBitmap->PreMultiply(); #endif // _SKIA_SUPPORT_PATHS_ - m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); + if (useRSXform) { + SkTDArray xforms; + xforms.setCount(nChars); + for (int index = 0; index < nChars; ++index) { + const FXTEXT_CHARPOS& cp = pCharPos[index]; + SkRSXform* rsxform = &xforms[index]; + if (cp.m_bGlyphAdjust) { + rsxform->fSCos = cp.m_AdjustMatrix[0]; + rsxform->fSSin = cp.m_AdjustMatrix[1]; + rsxform->fTx = cp.m_AdjustMatrix[0] * positions[index].fX; + rsxform->fTy = cp.m_AdjustMatrix[1] * positions[index].fY; + } else { + rsxform->fSCos = 1; + rsxform->fSSin = 0; + rsxform->fTx = positions[index].fX; + rsxform->fTy = positions[index].fY; + } + } + m_pCanvas->drawTextRSXform(glyphs.begin(), nChars * 2, xforms.begin(), + nullptr, paint); + } else if (oneAtATime) { + for (int index = 0; index < nChars; ++index) { + const FXTEXT_CHARPOS& cp = pCharPos[index]; + if (cp.m_bGlyphAdjust) { + if (0 == cp.m_AdjustMatrix[1] && 0 == cp.m_AdjustMatrix[2] && + 1 == cp.m_AdjustMatrix[3]) { + paint.setTextScaleX(cp.m_AdjustMatrix[0]); + m_pCanvas->drawText(&glyphs[index], 1, positions[index].fX, + positions[index].fY, paint); + paint.setTextScaleX(1); + } else { + m_pCanvas->save(); + SkMatrix adjust; + adjust.reset(); + adjust.setScaleX(cp.m_AdjustMatrix[0]); + adjust.setSkewX(cp.m_AdjustMatrix[1]); + adjust.setSkewY(cp.m_AdjustMatrix[2]); + adjust.setScaleY(cp.m_AdjustMatrix[3]); + adjust.preTranslate(positions[index].fX, positions[index].fY); + m_pCanvas->concat(adjust); + m_pCanvas->drawText(&glyphs[index], 1, 0, 0, paint); + m_pCanvas->restore(); + } + } else { + m_pCanvas->drawText(&glyphs[index], 1, positions[index].fX, + positions[index].fY, paint); + } + } + } else { + m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), + paint); + } m_pCanvas->restore(); return true; @@ -1371,10 +1723,14 @@ int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const { } void CFX_SkiaDeviceDriver::SaveState() { + m_pCache->DebugCheckClip(); if (!m_pCache->ClipSave()) m_pCanvas->save(); #ifdef _SKIA_SUPPORT_PATHS_ +#if SHOW_SKIA_PATH + printf("SaveState %zd\n", m_StateStack.size()); +#endif std::unique_ptr pClip; if (m_pClipRgn) pClip = pdfium::MakeUnique(*m_pClipRgn); @@ -1383,16 +1739,24 @@ void CFX_SkiaDeviceDriver::SaveState() { } void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) { - if (!m_pCache->ClipRestore()) - m_pCanvas->restore(); - if (bKeepSaved && !m_pCache->ClipSave()) - m_pCanvas->save(); #ifdef _SKIA_SUPPORT_PATHS_ m_pClipRgn.reset(); if (m_StateStack.empty()) return; - +#else + if (m_pCache->IsEmpty()) + return; +#endif + if (!m_pCache->ClipRestore()) + m_pCanvas->restore(); + if (bKeepSaved && !m_pCache->ClipSave()) + m_pCanvas->save(); +#ifdef _SKIA_SUPPORT_PATHS_ +#if SHOW_SKIA_PATH + printf("RestoreState %zd %s\n", m_StateStack.size(), + bKeepSaved ? "bKeepSaved" : ""); +#endif if (bKeepSaved) { if (m_StateStack.back()) m_pClipRgn = pdfium::MakeUnique(*m_StateStack.back()); @@ -1400,6 +1764,7 @@ void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) { m_pClipRgn = std::move(m_StateStack.back()); m_StateStack.pop_back(); } + m_pCache->DebugCheckClip(); #endif // _SKIA_SUPPORT_PATHS_ } @@ -1409,8 +1774,7 @@ void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox, FX_RECT path_rect(clipBox.left, clipBox.top, clipBox.right + 1, clipBox.bottom + 1); path_rect.Intersect(m_pClipRgn->GetBox()); - CFX_DIBitmapRef mask; - CFX_DIBitmap* pThisLayer = mask.Emplace(); + auto pThisLayer = pdfium::MakeRetain(); pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); pThisLayer->Clear(0); @@ -1419,16 +1783,15 @@ void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox, SkColorType::kAlpha_8_SkColorType, kOpaque_SkAlphaType); SkBitmap bitmap; bitmap.installPixels(imageInfo, pThisLayer->GetBuffer(), - pThisLayer->GetPitch(), nullptr, nullptr, nullptr); - SkCanvas* canvas = new SkCanvas(bitmap); + pThisLayer->GetPitch()); + auto canvas = pdfium::MakeUnique(bitmap); canvas->translate( -path_rect.left, -path_rect.top); // FIXME(caryclark) wrong sign(s)? upside down? SkPaint paint; paint.setAntiAlias((m_FillFlags & FXFILL_NOPATHSMOOTH) == 0); canvas->drawPath(path, paint); - m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask); - delete canvas; + m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, pThisLayer); } #endif // _SKIA_SUPPORT_PATHS_ @@ -1452,9 +1815,9 @@ bool CFX_SkiaDeviceDriver::SetClip_PathFill( pPathData->GetPoints().size() == 4) { CFX_FloatRect rectf; if (pPathData->IsRect(deviceMatrix, &rectf)) { - rectf.Intersect( - CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH), - (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + rectf.Intersect(CFX_FloatRect(0, 0, + (float)GetDeviceCaps(FXDC_PIXEL_WIDTH), + (float)GetDeviceCaps(FXDC_PIXEL_HEIGHT))); // note that PDF's y-axis goes up; Skia's y-axis goes down if (!cached) { SkRect skClipRect = @@ -1467,7 +1830,7 @@ bool CFX_SkiaDeviceDriver::SetClip_PathFill( FX_RECT rect = rectf.GetOuterRect(); m_pClipRgn->IntersectRect(rect); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowCanvasClip(m_pCanvas); + DebugShowCanvasClip(this, m_pCanvas); return true; } } @@ -1487,7 +1850,7 @@ bool CFX_SkiaDeviceDriver::SetClip_PathFill( GetDeviceCaps(FXDC_PIXEL_HEIGHT)); SetClipMask(clipBox, skClipPath); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowCanvasClip(m_pCanvas); + DebugShowCanvasClip(this, m_pCanvas); return true; } @@ -1521,7 +1884,7 @@ bool CFX_SkiaDeviceDriver::SetClip_PathStroke( GetDeviceCaps(FXDC_PIXEL_HEIGHT)); SetClipMask(clipBox, dst_path); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowCanvasClip(m_pCanvas); + DebugShowCanvasClip(this, m_pCanvas); return true; } @@ -1574,7 +1937,7 @@ bool CFX_SkiaDeviceDriver::DrawPath( #ifdef _SKIA_SUPPORT_PATHS_ m_pBitmap->PreMultiply(); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowSkiaDrawPath(m_pCanvas, skPaint, *fillPath); + DebugShowSkiaDrawPath(this, m_pCanvas, skPaint, *fillPath); m_pCanvas->drawPath(*fillPath, skPaint); } if (pGraphState && stroke_alpha) { @@ -1583,17 +1946,15 @@ bool CFX_SkiaDeviceDriver::DrawPath( #ifdef _SKIA_SUPPORT_PATHS_ m_pBitmap->PreMultiply(); #endif // _SKIA_SUPPORT_PATHS_ - DebugShowSkiaDrawPath(m_pCanvas, skPaint, skPath); + DebugShowSkiaDrawPath(this, m_pCanvas, skPaint, skPath); m_pCanvas->drawPath(skPath, skPaint); } m_pCanvas->restore(); return true; } -bool CFX_SkiaDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, +bool CFX_SkiaDeviceDriver::DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, uint32_t color, int blend_type) { return false; @@ -1610,7 +1971,7 @@ bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, SkRect rect = SkRect::MakeLTRB(pRect->left, SkTMin(pRect->top, pRect->bottom), pRect->right, SkTMax(pRect->bottom, pRect->top)); - DebugShowSkiaDrawRect(m_pCanvas, spaint, rect); + DebugShowSkiaDrawRect(this, m_pCanvas, spaint, rect); m_pCanvas->drawRect(rect, spaint); return true; } @@ -1678,10 +2039,10 @@ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, SkPath skClip; SkPath skPath; if (kAxialShading == shadingType) { - FX_FLOAT start_x = pCoords->GetNumberAt(0); - FX_FLOAT start_y = pCoords->GetNumberAt(1); - FX_FLOAT end_x = pCoords->GetNumberAt(2); - FX_FLOAT end_y = pCoords->GetNumberAt(3); + float start_x = pCoords->GetNumberAt(0); + float start_y = pCoords->GetNumberAt(1); + float end_x = pCoords->GetNumberAt(2); + float end_y = pCoords->GetNumberAt(3); SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts)); paint.setShader(SkGradientShader::MakeLinear( @@ -1718,12 +2079,12 @@ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, skPath.addRect(skRect); skMatrix.setIdentity(); } else if (kRadialShading == shadingType) { - FX_FLOAT start_x = pCoords->GetNumberAt(0); - FX_FLOAT start_y = pCoords->GetNumberAt(1); - FX_FLOAT start_r = pCoords->GetNumberAt(2); - FX_FLOAT end_x = pCoords->GetNumberAt(3); - FX_FLOAT end_y = pCoords->GetNumberAt(4); - FX_FLOAT end_r = pCoords->GetNumberAt(5); + float start_x = pCoords->GetNumberAt(0); + float start_y = pCoords->GetNumberAt(1); + float start_r = pCoords->GetNumberAt(2); + float end_x = pCoords->GetNumberAt(3); + float end_y = pCoords->GetNumberAt(4); + float end_r = pCoords->GetNumberAt(5); SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; paint.setShader(SkGradientShader::MakeTwoPointConical( @@ -1766,11 +2127,11 @@ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, SkPoint tempCubics[4]; for (int i = 0; i < (int)SK_ARRAY_COUNT(tempCubics); i++) tempCubics[i] = cubics[(flag * 3 + i) % 12]; - FXSYS_memcpy(cubics, tempCubics, sizeof(tempCubics)); + memcpy(cubics, tempCubics, sizeof(tempCubics)); SkColor tempColors[2]; tempColors[0] = colors[flag]; tempColors[1] = colors[(flag + 1) % 4]; - FXSYS_memcpy(colors, tempColors, sizeof(tempColors)); + memcpy(colors, tempColors, sizeof(tempColors)); } for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++) { CFX_PointF point = stream.ReadCoords(); @@ -1778,9 +2139,9 @@ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, cubics[i].fY = point.y; } for (int i = iStartColor; i < (int)SK_ARRAY_COUNT(colors); i++) { - FX_FLOAT r; - FX_FLOAT g; - FX_FLOAT b; + float r; + float g; + float b; std::tie(r, g, b) = stream.ReadColor(); colors[i] = SkColorSetARGBInline(0xFF, (U8CPU)(r * 255), (U8CPU)(g * 255), (U8CPU)(b * 255)); @@ -1804,16 +2165,28 @@ uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const { } bool CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { +#ifdef _SKIA_SUPPORT_PATHS_ + if (!m_pClipRgn) { + pRect->left = pRect->top = 0; + pRect->right = GetDeviceCaps(FXDC_PIXEL_WIDTH); + pRect->bottom = GetDeviceCaps(FXDC_PIXEL_HEIGHT); + return true; + } + *pRect = m_pClipRgn->GetBox(); +#else // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead pRect->left = 0; pRect->top = 0; const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); pRect->right = canvasSize.width(); pRect->bottom = canvasSize.height(); +#endif return true; } -bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { +bool CFX_SkiaDeviceDriver::GetDIBits(const RetainPtr& pBitmap, + int left, + int top) { if (!m_pBitmap) return true; uint8_t* srcBuffer = m_pBitmap->GetBuffer(); @@ -1827,8 +2200,7 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { SkImageInfo srcImageInfo = SkImageInfo::Make( srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); SkBitmap skSrcBitmap; - skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes, nullptr, - nullptr, nullptr); + skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes); SkASSERT(pBitmap); uint8_t* dstBuffer = pBitmap->GetBuffer(); SkASSERT(dstBuffer); @@ -1838,8 +2210,7 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { SkImageInfo dstImageInfo = SkImageInfo::Make( dstWidth, dstHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); SkBitmap skDstBitmap; - skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes, nullptr, - nullptr, nullptr); + skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes); SkCanvas canvas(skDstBitmap); canvas.drawBitmap(skSrcBitmap, left, top, nullptr); return true; @@ -1850,7 +2221,7 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { m_pBitmap->UnPreMultiply(); FX_RECT rect(left, top, left + pBitmap->GetWidth(), top + pBitmap->GetHeight()); - std::unique_ptr pBack; + RetainPtr pBack; if (m_pOriDevice) { pBack = m_pOriDevice->Clone(&rect); if (!pBack) @@ -1869,20 +2240,20 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { top = std::min(top, 0); if (m_bRgbByteOrder) { RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(), - pBack.get(), left, top); + pBack, left, top); } else { - bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), - pBack.get(), left, top); + bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack, + left, top); } return bRet; #endif // _SKIA_SUPPORT_PATHS_ } -CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() { +RetainPtr CFX_SkiaDeviceDriver::GetBackDrop() { return m_pOriDevice; } -bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, +bool CFX_SkiaDeviceDriver::SetDIBits(const RetainPtr& pBitmap, uint32_t argb, const FX_RECT* pSrcRect, int left, @@ -1894,33 +2265,34 @@ bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, #ifdef _SKIA_SUPPORT_ CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), left, top + pBitmap->GetHeight()); - void* dummy; - return StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, blend_type); + std::unique_ptr dummy; + return StartDIBits(pBitmap, 0xFF, argb, &m, 0, &dummy, blend_type); #endif // _SKIA_SUPPORT_ #ifdef _SKIA_SUPPORT_PATHS_ Flush(); if (pBitmap->IsAlphaMask()) { - return m_pBitmap->CompositeMask( - left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb, - pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(), - m_bRgbByteOrder, 0, nullptr); + return m_pBitmap->CompositeMask(left, top, pSrcRect->Width(), + pSrcRect->Height(), pBitmap, argb, + pSrcRect->left, pSrcRect->top, blend_type, + m_pClipRgn.get(), m_bRgbByteOrder, 0); } return m_pBitmap->CompositeBitmap( left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left, - pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr); + pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder); #endif // _SKIA_SUPPORT_PATHS_ } -bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, - uint32_t argb, - int dest_left, - int dest_top, - int dest_width, - int dest_height, - const FX_RECT* pClipRect, - uint32_t flags, - int blend_type) { +bool CFX_SkiaDeviceDriver::StretchDIBits( + const RetainPtr& pSource, + uint32_t argb, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + const FX_RECT* pClipRect, + uint32_t flags, + int blend_type) { #ifdef _SKIA_SUPPORT_ m_pCache->FlushForDraw(); if (!m_pBitmap->GetBuffer()) @@ -1932,8 +2304,8 @@ bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom, pClipRect->right, pClipRect->top); m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true); - void* dummy; - bool result = StartDIBits(pSource, 0xFF, argb, &m, 0, dummy, blend_type); + std::unique_ptr dummy; + bool result = StartDIBits(pSource, 0xFF, argb, &m, 0, &dummy, blend_type); m_pCanvas->restore(); return result; @@ -1953,7 +2325,7 @@ bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, dest_clip.Intersect(*pClipRect); CFX_BitmapComposer composer; composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false, - false, false, m_bRgbByteOrder, 0, nullptr, blend_type); + false, false, m_bRgbByteOrder, 0, blend_type); dest_clip.Offset(-dest_rect.left, -dest_rect.top); CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height, dest_clip, flags); @@ -1963,23 +2335,23 @@ bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, #endif // _SKIA_SUPPORT_PATHS_ } -bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, - int bitmap_alpha, - uint32_t argb, - const CFX_Matrix* pMatrix, - uint32_t render_flags, - void*& handle, - int blend_type) { +bool CFX_SkiaDeviceDriver::StartDIBits( + const RetainPtr& pSource, + int bitmap_alpha, + uint32_t argb, + const CFX_Matrix* pMatrix, + uint32_t render_flags, + std::unique_ptr* handle, + int blend_type) { #ifdef _SKIA_SUPPORT_ m_pCache->FlushForDraw(); DebugValidate(m_pBitmap, m_pOriDevice); - SkColorTable* ct = nullptr; std::unique_ptr dst8Storage; std::unique_ptr dst32Storage; SkBitmap skBitmap; int width, height; - if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width, - &height, false)) { + if (!Upsample(pSource, dst8Storage, dst32Storage, &skBitmap, &width, &height, + false)) { return false; } m_pCanvas->save(); @@ -2007,8 +2379,6 @@ bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); } m_pCanvas->restore(); - if (ct) - ct->unref(); DebugValidate(m_pBitmap, m_pOriDevice); #endif // _SKIA_SUPPORT_ @@ -2017,15 +2387,15 @@ bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, if (!m_pBitmap->GetBuffer()) return true; m_pBitmap->UnPreMultiply(); - CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer; - pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, - pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr); - handle = pRenderer; + *handle = pdfium::MakeUnique( + m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, pMatrix, + render_flags, m_bRgbByteOrder); #endif // _SKIA_SUPPORT_PATHS_ return true; } -bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { +bool CFX_SkiaDeviceDriver::ContinueDIBits(CFX_ImageRenderer* handle, + IFX_PauseIndicator* pPause) { #ifdef _SKIA_SUPPORT_ m_pCache->FlushForDraw(); return false; @@ -2036,12 +2406,13 @@ bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { if (!m_pBitmap->GetBuffer()) { return true; } - return static_cast(handle)->Continue(pPause); + return handle->Continue(pPause); #endif // _SKIA_SUPPORT_PATHS_ } #if defined _SKIA_SUPPORT_ -void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { +void CFX_SkiaDeviceDriver::PreMultiply( + const RetainPtr& pDIBitmap) { pDIBitmap->PreMultiply(); } #endif // _SKIA_SUPPORT_ @@ -2068,7 +2439,7 @@ void CFX_DIBitmap::PreMultiply() { SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); unpremultiplied.readPixels(premultiplied); - this->DebugVerifyBitmapIsPreMultiplied(); + this->DebugVerifyBitmapIsPreMultiplied(nullptr); } #ifdef _SKIA_SUPPORT_PATHS_ @@ -2082,7 +2453,7 @@ void CFX_DIBitmap::UnPreMultiply() { m_nFormat = Format::kUnPreMultiplied; if (priorFormat != Format::kPreMultiplied) return; - this->DebugVerifyBitmapIsPreMultiplied(); + this->DebugVerifyBitmapIsPreMultiplied(nullptr); int height = this->GetHeight(); int width = this->GetWidth(); int rowBytes = this->GetPitch(); @@ -2097,24 +2468,23 @@ void CFX_DIBitmap::UnPreMultiply() { #endif // _SKIA_SUPPORT_PATHS_ #ifdef _SKIA_SUPPORT_ -bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource, - const CFX_DIBSource* pMask, - int bitmap_alpha, - const CFX_Matrix* pMatrix, - int blend_type) { +bool CFX_SkiaDeviceDriver::DrawBitsWithMask( + const RetainPtr& pSource, + const RetainPtr& pMask, + int bitmap_alpha, + const CFX_Matrix* pMatrix, + int blend_type) { DebugValidate(m_pBitmap, m_pOriDevice); - SkColorTable* srcCt = nullptr; - SkColorTable* maskCt = nullptr; std::unique_ptr src8Storage, mask8Storage; std::unique_ptr src32Storage, mask32Storage; SkBitmap skBitmap, skMask; int srcWidth, srcHeight, maskWidth, maskHeight; - if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap, - &srcWidth, &srcHeight, false)) { + if (!Upsample(pSource, src8Storage, src32Storage, &skBitmap, &srcWidth, + &srcHeight, false)) { return false; } - if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask, - &maskWidth, &maskHeight, true)) { + if (!Upsample(pMask, mask8Storage, mask32Storage, &skMask, &maskWidth, + &maskHeight, true)) { return false; } m_pCanvas->save(); @@ -2135,18 +2505,17 @@ bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource, SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)}; m_pCanvas->drawRect(r, paint); m_pCanvas->restore(); - if (srcCt) - srcCt->unref(); DebugValidate(m_pBitmap, m_pOriDevice); return true; } -bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, - int dest_left, - int dest_top, - int bitmap_alpha, - int blend_type) { +bool CFX_SkiaDeviceDriver::SetBitsWithMask( + const RetainPtr& pBitmap, + const RetainPtr& pMask, + int dest_left, + int dest_top, + int bitmap_alpha, + int blend_type) { if (!m_pBitmap || !m_pBitmap->GetBuffer()) return true; CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left, @@ -2169,34 +2538,31 @@ void CFX_SkiaDeviceDriver::Dump() const { #ifdef _SKIA_SUPPORT_ void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { if (m_pOriDevice) - m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(); + m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(nullptr); } #endif // _SKIA_SUPPORT_ -CFX_FxgeDevice::CFX_FxgeDevice() { -#ifdef _SKIA_SUPPORT_ - m_bOwnedBitmap = false; -#endif // _SKIA_SUPPORT_ -} +CFX_DefaultRenderDevice::CFX_DefaultRenderDevice() {} #ifdef _SKIA_SUPPORT_ -void CFX_FxgeDevice::Clear(uint32_t color) { +void CFX_DefaultRenderDevice::Clear(uint32_t color) { CFX_SkiaDeviceDriver* skDriver = static_cast(GetDeviceDriver()); skDriver->Clear(color); } -SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) { +SkPictureRecorder* CFX_DefaultRenderDevice::CreateRecorder(int size_x, + int size_y) { CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y); SetDeviceDriver(pdfium::WrapUnique(skDriver)); return skDriver->GetRecorder(); } #endif // _SKIA_SUPPORT_ -bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, - bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, - bool bGroupKnockout) { +bool CFX_DefaultRenderDevice::Attach(const RetainPtr& pBitmap, + bool bRgbByteOrder, + const RetainPtr& pOriDevice, + bool bGroupKnockout) { if (!pBitmap) return false; SetBitmap(pBitmap); @@ -2206,7 +2572,7 @@ bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, } #ifdef _SKIA_SUPPORT_ -bool CFX_FxgeDevice::AttachRecorder(SkPictureRecorder* recorder) { +bool CFX_DefaultRenderDevice::AttachRecorder(SkPictureRecorder* recorder) { if (!recorder) return false; SetDeviceDriver(pdfium::MakeUnique(recorder)); @@ -2214,14 +2580,13 @@ bool CFX_FxgeDevice::AttachRecorder(SkPictureRecorder* recorder) { } #endif // _SKIA_SUPPORT_ -bool CFX_FxgeDevice::Create(int width, - int height, - FXDIB_Format format, - CFX_DIBitmap* pOriDevice) { - m_bOwnedBitmap = true; - CFX_DIBitmap* pBitmap = new CFX_DIBitmap; +bool CFX_DefaultRenderDevice::Create( + int width, + int height, + FXDIB_Format format, + const RetainPtr& pOriDevice) { + auto pBitmap = pdfium::MakeRetain(); if (!pBitmap->Create(width, height, format)) { - delete pBitmap; return false; } SetBitmap(pBitmap); @@ -2230,17 +2595,12 @@ bool CFX_FxgeDevice::Create(int width, return true; } -CFX_FxgeDevice::~CFX_FxgeDevice() { -#ifdef _SKIA_SUPPORT_ - Flush(); - // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately - if (m_bOwnedBitmap && GetBitmap()) - delete GetBitmap(); -#endif // _SKIA_SUPPORT_ +CFX_DefaultRenderDevice::~CFX_DefaultRenderDevice() { + Flush(true); } #ifdef _SKIA_SUPPORT_ -void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { +void CFX_DefaultRenderDevice::DebugVerifyBitmapIsPreMultiplied() const { #ifdef SK_DEBUG CFX_SkiaDeviceDriver* skDriver = static_cast(GetDeviceDriver()); @@ -2249,12 +2609,13 @@ void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { #endif // SK_DEBUG } -bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, - int left, - int top, - int bitmap_alpha, - int blend_type) { +bool CFX_DefaultRenderDevice::SetBitsWithMask( + const RetainPtr& pBitmap, + const RetainPtr& pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { CFX_SkiaDeviceDriver* skDriver = static_cast(GetDeviceDriver()); if (skDriver) @@ -2286,834 +2647,3 @@ void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { } #endif // SK_DEBUG } - -#ifdef _SKIA_SUPPORT_PATHS_ -class CFX_Renderer { - private: - int m_Alpha, m_Red, m_Green, m_Blue, m_Gray; - uint32_t m_Color; - bool m_bFullCover; - bool m_bRgbByteOrder; - CFX_DIBitmap* m_pOriDevice; - FX_RECT m_ClipBox; - const CFX_DIBitmap* m_pClipMask; - CFX_DIBitmap* m_pDevice; - const CFX_ClipRgn* m_pClipRgn; - void (CFX_Renderer::*composite_span)(uint8_t*, - int, - int, - int, - uint8_t*, - int, - int, - uint8_t*, - uint8_t*); - - public: - void prepare(unsigned) {} - - void CompositeSpan(uint8_t* dest_scan, - uint8_t* ori_scan, - int Bpp, - bool bDestAlpha, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan) { - ASSERT(!m_pDevice->IsCmykImage()); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - if (Bpp) { - dest_scan += col_start * Bpp; - ori_scan += col_start * Bpp; - } else { - dest_scan += col_start / 8; - ori_scan += col_start / 8; - } - if (m_bRgbByteOrder) { - if (Bpp == 4 && bDestAlpha) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - uint8_t dest_alpha = - ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); - dest_scan++; - ori_scan++; - } else { - int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); - int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); - ori_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += 2; - } - } - return; - } - if (Bpp == 3 || Bpp == 4) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); - ori_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += Bpp - 2; - } - } - return; - } - if (Bpp == 4 && bDestAlpha) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - int src_alpha_covered = src_alpha * cover_scan[col] / 255; - if (src_alpha_covered == 0) { - dest_scan += 4; - continue; - } - if (cover_scan[col] == 255) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t cover = cover_scan[col]; - dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); - dest_scan += 2; - } - } - return; - } - if (Bpp == 3 || Bpp == 4) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - ori_scan += Bpp - 2; - continue; - } - int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); - ori_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan += Bpp - 2; - continue; - } - return; - } - if (Bpp == 1) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - if (m_bFullCover) { - *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); - } else { - int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); - dest_scan++; - } - } - } else { - int index = 0; - if (m_pDevice->GetPalette()) { - for (int i = 0; i < 2; i++) { - if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { - index = i; - } - } - } else { - index = ((uint8_t)m_Color == 0xff) ? 1 : 0; - } - uint8_t* dest_scan1 = dest_scan; - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (!index) { - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - } else { - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); - } - } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; - } - } - } - - void CompositeSpan1bpp(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - ASSERT(!m_bRgbByteOrder); - ASSERT(!m_pDevice->IsCmykImage()); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start / 8; - int index = 0; - if (m_pDevice->GetPalette()) { - for (int i = 0; i < 2; i++) { - if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { - index = i; - } - } - } else { - index = ((uint8_t)m_Color == 0xff) ? 1 : 0; - } - uint8_t* dest_scan1 = dest_scan; - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (!index) { - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - } else { - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); - } - } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; - } - } - - void CompositeSpanGray(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - ASSERT(!m_bRgbByteOrder); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start; - if (dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan = m_Gray; - *dest_extra_alpha_scan = m_Alpha; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); - dest_scan++; - continue; - } - } - dest_extra_alpha_scan++; - dest_scan++; - } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan = m_Gray; - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); - } - } - dest_scan++; - } - } - } - - void CompositeSpanARGB(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *(uint32_t*)dest_scan = m_Color; - } else { - uint8_t dest_alpha = - dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan += 2; - continue; - } - } - dest_scan += 4; - } - return; - } - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *(uint32_t*)dest_scan = m_Color; - } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t dest_alpha = - dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan += 2; - continue; - } - } - dest_scan += Bpp; - } - } - - void CompositeSpanRGB(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - if (Bpp == 4) { - *(uint32_t*)dest_scan = m_Color; - } else if (Bpp == 3) { - *dest_scan++ = m_Red; - *dest_scan++ = m_Green; - *dest_scan++ = m_Blue; - continue; - } - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan += Bpp - 2; - continue; - } - } - dest_scan += Bpp; - } - return; - } - if (Bpp == 3 && dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan++ = (uint8_t)m_Blue; - *dest_scan++ = (uint8_t)m_Green; - *dest_scan++ = (uint8_t)m_Red; - *dest_extra_alpha_scan++ = (uint8_t)m_Alpha; - continue; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - continue; - } - } - dest_extra_alpha_scan++; - dest_scan += Bpp; - } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - if (Bpp == 4) { - *(uint32_t*)dest_scan = m_Color; - } else if (Bpp == 3) { - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan++ = m_Red; - continue; - } - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - continue; - } - } - dest_scan += Bpp; - } - } - } - - void CompositeSpanCMYK(uint8_t* dest_scan, - int Bpp, - int span_left, - int span_len, - uint8_t* cover_scan, - int clip_left, - int clip_right, - uint8_t* clip_scan, - uint8_t* dest_extra_alpha_scan) { - ASSERT(!m_bRgbByteOrder); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * 4; - if (dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } - if (src_alpha) { - if (src_alpha == 255) { - *(FX_CMYK*)dest_scan = m_Color; - *dest_extra_alpha_scan = (uint8_t)m_Alpha; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); - dest_scan++; - continue; - } - } - dest_extra_alpha_scan++; - dest_scan += 4; - } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *(FX_CMYK*)dest_scan = m_Color; - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); - dest_scan++; - continue; - } - } - dest_scan += 4; - } - } - } - - template - void render(const Scanline& sl) { - if (!m_pOriDevice && !composite_span) { - return; - } - int y = sl.y(); - if (y < m_ClipBox.top || y >= m_ClipBox.bottom) { - return; - } - uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; - uint8_t* dest_scan_extra_alpha = nullptr; - CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask; - if (pAlphaMask) { - dest_scan_extra_alpha = - pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; - } - uint8_t* ori_scan = nullptr; - if (m_pOriDevice) { - ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; - } - int Bpp = m_pDevice->GetBPP() / 8; - bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - while (1) { - int x = span->x; - ASSERT(span->len > 0); - uint8_t* dest_pos = nullptr; - uint8_t* dest_extra_alpha_pos = nullptr; - uint8_t* ori_pos = nullptr; - if (Bpp) { - ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; - dest_pos = dest_scan + x * Bpp; - dest_extra_alpha_pos = - dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; - } else { - dest_pos = dest_scan + x / 8; - ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; - } - uint8_t* clip_pos = nullptr; - if (m_pClipMask) { - clip_pos = m_pClipMask->GetBuffer() + - (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - - m_ClipBox.left; - } - if (ori_pos) { - CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, - span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); - } else { - (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, - m_ClipBox.left, m_ClipBox.right, clip_pos, - dest_extra_alpha_pos); - } - if (--num_spans == 0) { - break; - } - ++span; - } - } - - bool Init(CFX_DIBitmap* pDevice, - CFX_DIBitmap* pOriDevice, - const CFX_ClipRgn* pClipRgn, - uint32_t color, - bool bFullCover, - bool bRgbByteOrder, - int alpha_flag = 0, - void* pIccTransform = nullptr) { - m_pDevice = pDevice; - m_pClipRgn = pClipRgn; - composite_span = nullptr; - m_bRgbByteOrder = bRgbByteOrder; - m_pOriDevice = pOriDevice; - if (m_pClipRgn) { - m_ClipBox = m_pClipRgn->GetBox(); - } else { - m_ClipBox.left = m_ClipBox.top = 0; - m_ClipBox.right = m_pDevice->GetWidth(); - m_ClipBox.bottom = m_pDevice->GetHeight(); - } - m_pClipMask = nullptr; - if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) { - m_pClipMask = m_pClipRgn->GetMask().GetObject(); - } - m_bFullCover = bFullCover; - bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); - bool bDeviceCMYK = pDevice->IsCmykImage(); - m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); - CCodec_IccModule* pIccModule = nullptr; - if (!CFX_GEModule::Get()->GetCodecModule() || - !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - pIccTransform = nullptr; - } else { - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - } - if (m_pDevice->GetBPP() == 8) { - ASSERT(!m_bRgbByteOrder); - composite_span = &CFX_Renderer::CompositeSpanGray; - if (m_pDevice->IsAlphaMask()) { - m_Gray = 255; - } else { - if (pIccTransform) { - uint8_t gray; - color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, &gray, - (const uint8_t*)&color, 1); - m_Gray = gray; - } else { - if (bObjectCMYK) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), - r, g, b); - m_Gray = FXRGB2GRAY(r, g, b); - } else { - m_Gray = - FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); - } - } - } - return true; - } - if (bDeviceCMYK) { - ASSERT(!m_bRgbByteOrder); - composite_span = &CFX_Renderer::CompositeSpanCMYK; - if (bObjectCMYK) { - m_Color = FXCMYK_TODIB(color); - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&m_Color, 1); - } - } else { - if (!pIccTransform) { - return false; - } - color = FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&color, 1); - } - m_Red = ((uint8_t*)&m_Color)[0]; - m_Green = ((uint8_t*)&m_Color)[1]; - m_Blue = ((uint8_t*)&m_Color)[2]; - m_Gray = ((uint8_t*)&m_Color)[3]; - } else { - composite_span = (pDevice->GetFormat() == FXDIB_Argb) - ? &CFX_Renderer::CompositeSpanARGB - : &CFX_Renderer::CompositeSpanRGB; - if (pIccTransform) { - color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&color, 1); - ((uint8_t*)&m_Color)[3] = m_Alpha; - m_Red = ((uint8_t*)&m_Color)[2]; - m_Green = ((uint8_t*)&m_Color)[1]; - m_Blue = ((uint8_t*)&m_Color)[0]; - if (m_bRgbByteOrder) { - m_Color = FXARGB_TODIB(m_Color); - m_Color = FXARGB_TOBGRORDERDIB(m_Color); - } - } else { - if (bObjectCMYK) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, - g, b); - m_Color = FXARGB_MAKE(m_Alpha, r, g, b); - if (m_bRgbByteOrder) { - m_Color = FXARGB_TOBGRORDERDIB(m_Color); - } else { - m_Color = FXARGB_TODIB(m_Color); - } - m_Red = r; - m_Green = g; - m_Blue = b; - } else { - if (m_bRgbByteOrder) { - m_Color = FXARGB_TOBGRORDERDIB(color); - } else { - m_Color = FXARGB_TODIB(color); - } - ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue); - } - } - } - if (m_pDevice->GetBPP() == 1) { - composite_span = &CFX_Renderer::CompositeSpan1bpp; - } - return true; - } -}; - -#endif // _SKIA_SUPPORT_PATHS_ diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h index ecb1104518284f8fb11ad0d02c4b9ef30482063e..7dfdef4de8cc9e92c92e63269159104083e93cbb 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h @@ -24,9 +24,9 @@ struct SkIRect; class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { public: - CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, + CFX_SkiaDeviceDriver(const RetainPtr& pBitmap, bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, + const RetainPtr& pOriDevice, bool bGroupKnockout); #ifdef _SKIA_SUPPORT_ explicit CFX_SkiaDeviceDriver(SkPictureRecorder* recorder); @@ -69,29 +69,29 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { int blend_type) override; /** Draw a single pixel (device dependant) line */ - bool DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, + bool DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, uint32_t color, int blend_type) override; bool GetClipBox(FX_RECT* pRect) override; /** Load device buffer into a DIB */ - bool GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) override; + bool GetDIBits(const RetainPtr& pBitmap, + int left, + int top) override; - CFX_DIBitmap* GetBackDrop() override; + RetainPtr GetBackDrop() override; - bool SetDIBits(const CFX_DIBSource* pBitmap, + bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int dest_left, int dest_top, int blend_type) override; #ifdef _SKIA_SUPPORT_ - bool SetBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, + bool SetBitsWithMask(const RetainPtr& pBitmap, + const RetainPtr& pMask, int dest_left, int dest_top, int bitmap_alpha, @@ -102,7 +102,7 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { void SetClipMask(const FX_RECT& clipBox, const SkPath& skClipPath); #endif - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -112,20 +112,19 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { uint32_t flags, int blend_type) override; - bool StartDIBits(const CFX_DIBSource* pBitmap, + bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags, - void*& handle, + std::unique_ptr* handle, int blend_type) override; - bool ContinueDIBits(void* handle, IFX_Pause* pPause) override; + bool ContinueDIBits(CFX_ImageRenderer* handle, + IFX_PauseIndicator* pPause) override; - void CancelDIBits(void* handle) override {} - - bool DrawBitsWithMask(const CFX_DIBSource* pBitmap, - const CFX_DIBSource* pMask, + bool DrawBitsWithMask(const RetainPtr& pBitmap, + const RetainPtr& pMask, int bitmap_alpha, const CFX_Matrix* pMatrix, int blend_type); @@ -134,7 +133,7 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) override; bool DrawShading(const CPDF_ShadingPattern* pPattern, @@ -151,17 +150,17 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { void Clear(uint32_t color); void Flush() override; SkPictureRecorder* GetRecorder() const { return m_pRecorder; } - void PreMultiply() { m_pBitmap->PreMultiply(); } - static void PreMultiply(CFX_DIBitmap* pDIBitmap); + void PreMultiply(); + static void PreMultiply(const RetainPtr& pDIBitmap); SkCanvas* SkiaCanvas() { return m_pCanvas; } void DebugVerifyBitmapIsPreMultiplied() const; void Dump() const; - private: - friend class SkiaState; + bool GetGroupKnockout() const { return m_bGroupKnockout; } - CFX_DIBitmap* m_pBitmap; - CFX_DIBitmap* m_pOriDevice; + private: + RetainPtr m_pBitmap; + RetainPtr m_pOriDevice; SkCanvas* m_pCanvas; SkPictureRecorder* const m_pRecorder; std::unique_ptr m_pCache; diff --git a/core/fxge/skia/fx_skia_device_unittest.cpp b/core/fxge/skia/fx_skia_device_unittest.cpp index afd47780d7f3fbca22a0ab9edf7fff18bb83744a..7cb28cfb494839b077b28e7e6087ee57e4962bcf 100644 --- a/core/fxge/skia/fx_skia_device_unittest.cpp +++ b/core/fxge/skia/fx_skia_device_unittest.cpp @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxge/skia/fx_skia_device.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/skia/fx_skia_device.h" #include "fpdfsdk/fsdk_define.h" #include "public/fpdfview.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -41,7 +41,7 @@ void CommonTest(CFX_SkiaDeviceDriver* driver, const State& state) { charPos[0].m_FontCharWidth = 4; CFX_Font font; - FX_FLOAT fontSize = 1; + float fontSize = 1; CFX_PathData clipPath, clipPath2; clipPath.AppendRect(0, 0, 3, 1); clipPath2.AppendRect(0, 0, 2, 1); @@ -124,8 +124,8 @@ void Harness(void (*Test)(CFX_SkiaDeviceDriver*, const State&), if (!bitmap) return; FPDFBitmap_FillRect(bitmap, 0, 0, w, h, 0x00000000); - CFX_FxgeDevice geDevice; - CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap); + CFX_DefaultRenderDevice geDevice; + RetainPtr pBitmap(CFXBitmapFromFPDFBitmap(bitmap)); geDevice.Attach(pBitmap, false, nullptr, false); CFX_SkiaDeviceDriver* driver = static_cast(geDevice.GetDeviceDriver()); diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp index 74fae088d98e0b248704b1b00f7188ce2373c79a..1513c07c684e53d25bba96d11d439791b3da2502 100644 --- a/core/fxge/win32/cfx_psrenderer.cpp +++ b/core/fxge/win32/cfx_psrenderer.cpp @@ -7,22 +7,83 @@ #include "core/fxge/win32/cfx_psrenderer.h" #include +#include +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcodec/codec/ccodec_faxmodule.h" +#include "core/fxcodec/codec/ccodec_flatemodule.h" +#include "core/fxcodec/codec/ccodec_jpegmodule.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" +#include "core/fxcrt/maybe_owned.h" #include "core/fxge/cfx_facecache.h" #include "core/fxge/cfx_fontcache.h" +#include "core/fxge/cfx_gemodule.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/dib/cfx_dibextractor.h" #include "core/fxge/win32/cpsoutput.h" #include "third_party/base/ptr_util.h" +namespace { + +void FaxCompressData(uint8_t* src_buf, + int width, + int height, + std::unique_ptr* dest_buf, + uint32_t* dest_size) { + if (width * height > 128) { + CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8, + dest_buf, dest_size); + FX_Free(src_buf); + } else { + dest_buf->reset(src_buf); + *dest_size = (width + 7) / 8 * height; + } +} + +void PSCompressData(int PSLevel, + uint8_t* src_buf, + uint32_t src_size, + uint8_t** output_buf, + uint32_t* output_size, + const char** filter) { + *output_buf = src_buf; + *output_size = src_size; + *filter = ""; + if (src_size < 1024) + return; + + CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); + uint8_t* dest_buf = nullptr; + uint32_t dest_size = src_size; + if (PSLevel >= 3) { + if (pEncoders->GetFlateModule()->Encode(src_buf, src_size, &dest_buf, + &dest_size)) { + *filter = "/FlateDecode filter "; + } + } else { + if (pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size, + &dest_buf, &dest_size)) { + *filter = "/RunLengthDecode filter "; + } + } + if (dest_size < src_size) { + *output_buf = dest_buf; + *output_size = dest_size; + } else { + *filter = nullptr; + FX_Free(dest_buf); + } +} + +} // namespace + struct PSGlyph { - CFX_Font* m_pFont; + UnownedPtr m_pFont; uint32_t m_GlyphIndex; bool m_bGlyphAdjust; - FX_FLOAT m_AdjustMatrix[4]; + float m_AdjustMatrix[4]; }; class CPSFont { @@ -31,33 +92,32 @@ class CPSFont { int m_nGlyphs; }; -CFX_PSRenderer::CFX_PSRenderer() { - m_pOutput = nullptr; - m_bColorSet = m_bGraphStateSet = false; - m_bInited = false; -} +CFX_PSRenderer::CFX_PSRenderer() + : m_pStream(nullptr), + m_bGraphStateSet(false), + m_bColorSet(false), + m_bInited(false) {} CFX_PSRenderer::~CFX_PSRenderer() {} -#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof(str) - 1) - -void CFX_PSRenderer::Init(CPSOutput* pOutput, +void CFX_PSRenderer::Init(const RetainPtr& pStream, int pslevel, int width, int height, bool bCmykOutput) { m_PSLevel = pslevel; - m_pOutput = pOutput; - m_ClipBox.left = m_ClipBox.top = 0; + m_pStream = pStream; + m_ClipBox.left = 0; + m_ClipBox.top = 0; m_ClipBox.right = width; m_ClipBox.bottom = height; m_bCmykOutput = bCmykOutput; } bool CFX_PSRenderer::StartRendering() { - if (m_bInited) { + if (m_bInited) return true; - } + static const char init_str[] = "\nsave\n/im/initmatrix load def\n" "/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load " @@ -72,30 +132,30 @@ bool CFX_PSRenderer::StartRendering() { "load def\n" "/cm/concat load def/Cm/currentmatrix load def/mx/matrix load " "def/sm/setmatrix load def\n"; - OUTPUT_PS(init_str); + m_pStream->WriteString(init_str); m_bInited = true; return true; } void CFX_PSRenderer::EndRendering() { - if (m_bInited) { - OUTPUT_PS("\nrestore\n"); - m_bInited = false; - } + if (!m_bInited) + return; + + m_pStream->WriteString("\nrestore\n"); + m_bInited = false; } void CFX_PSRenderer::SaveState() { StartRendering(); - OUTPUT_PS("q\n"); + m_pStream->WriteString("q\n"); m_ClipBoxStack.push_back(m_ClipBox); } void CFX_PSRenderer::RestoreState(bool bKeepSaved) { StartRendering(); + m_pStream->WriteString("Q\n"); if (bKeepSaved) - OUTPUT_PS("Q\nq\n"); - else - OUTPUT_PS("Q\n"); + m_pStream->WriteString("q\n"); m_bColorSet = false; m_bGraphStateSet = false; @@ -109,9 +169,8 @@ void CFX_PSRenderer::RestoreState(bool bKeepSaved) { void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, const CFX_Matrix* pObject2Device) { - CFX_ByteTextBuf buf; + std::ostringstream buf; size_t size = pPathData->GetPoints().size(); - buf.EstimateSize(size * 10); for (size_t i = 0; i < size; i++) { FXPT_TYPE type = pPathData->GetType(i); @@ -147,7 +206,7 @@ void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, } } } - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); } void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData, @@ -157,17 +216,17 @@ void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData, OutputPath(pPathData, pObject2Device); CFX_FloatRect rect = pPathData->GetBoundingBox(); if (pObject2Device) - pObject2Device->TransformRect(rect); + rect = pObject2Device->TransformRect(rect); m_ClipBox.left = static_cast(rect.left); m_ClipBox.right = static_cast(rect.left + rect.right); m_ClipBox.top = static_cast(rect.top + rect.bottom); m_ClipBox.bottom = static_cast(rect.bottom); - if ((fill_mode & 3) == FXFILL_WINDING) { - OUTPUT_PS("W n\n"); - } else { - OUTPUT_PS("W* n\n"); - } + + m_pStream->WriteString("W"); + if ((fill_mode & 3) != FXFILL_WINDING) + m_pStream->WriteString("*"); + m_pStream->WriteString(" n\n"); } void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData, @@ -176,22 +235,22 @@ void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData, StartRendering(); SetGraphState(pGraphState); if (pObject2Device) { - CFX_ByteTextBuf buf; + std::ostringstream buf; buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " " << pObject2Device->c << " " << pObject2Device->d << " " << pObject2Device->e << " " << pObject2Device->f << "]cm "; - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); } + OutputPath(pPathData, nullptr); CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth, pGraphState->m_MiterLimit); - pObject2Device->TransformRect(rect); - m_ClipBox.Intersect(rect.GetOuterRect()); - if (pObject2Device) { - OUTPUT_PS("strokepath W n sm\n"); - } else { - OUTPUT_PS("strokepath W n\n"); - } + m_ClipBox.Intersect(pObject2Device->TransformRect(rect).GetOuterRect()); + + m_pStream->WriteString("strokepath W n"); + if (pObject2Device) + m_pStream->WriteString(" sm"); + m_pStream->WriteString("\n"); } bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, @@ -203,68 +262,65 @@ bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, StartRendering(); int fill_alpha = FXARGB_A(fill_color); int stroke_alpha = FXARGB_A(stroke_color); - if (fill_alpha && fill_alpha < 255) { + if (fill_alpha && fill_alpha < 255) return false; - } - if (stroke_alpha && stroke_alpha < 255) { + if (stroke_alpha && stroke_alpha < 255) return false; - } - if (fill_alpha == 0 && stroke_alpha == 0) { + if (fill_alpha == 0 && stroke_alpha == 0) return false; - } + if (stroke_alpha) { SetGraphState(pGraphState); if (pObject2Device) { - CFX_ByteTextBuf buf; + std::ostringstream buf; buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " " << pObject2Device->c << " " << pObject2Device->d << " " << pObject2Device->e << " " << pObject2Device->f << "]cm "; - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); } } + OutputPath(pPathData, stroke_alpha ? nullptr : pObject2Device); if (fill_mode && fill_alpha) { SetColor(fill_color); if ((fill_mode & 3) == FXFILL_WINDING) { - if (stroke_alpha) { - OUTPUT_PS("q f Q "); - } else { - OUTPUT_PS("f"); - } + if (stroke_alpha) + m_pStream->WriteString("q f Q "); + else + m_pStream->WriteString("f"); } else if ((fill_mode & 3) == FXFILL_ALTERNATE) { - if (stroke_alpha) { - OUTPUT_PS("q F Q "); - } else { - OUTPUT_PS("F"); - } + if (stroke_alpha) + m_pStream->WriteString("q F Q "); + else + m_pStream->WriteString("F"); } } + if (stroke_alpha) { SetColor(stroke_color); - if (pObject2Device) { - OUTPUT_PS("s sm"); - } else { - OUTPUT_PS("s"); - } + m_pStream->WriteString("s"); + if (pObject2Device) + m_pStream->WriteString(" sm"); } - OUTPUT_PS("\n"); + + m_pStream->WriteString("\n"); return true; } void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { - CFX_ByteTextBuf buf; + std::ostringstream buf; if (!m_bGraphStateSet || m_CurGraphState.m_LineCap != pGraphState->m_LineCap) { buf << pGraphState->m_LineCap << " J\n"; } if (!m_bGraphStateSet || m_CurGraphState.m_DashCount != pGraphState->m_DashCount || - FXSYS_memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray, - sizeof(FX_FLOAT) * m_CurGraphState.m_DashCount)) { + memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray, + sizeof(float) * m_CurGraphState.m_DashCount)) { buf << "["; - for (int i = 0; i < pGraphState->m_DashCount; ++i) { + for (int i = 0; i < pGraphState->m_DashCount; ++i) buf << pGraphState->m_DashArray[i] << " "; - } + buf << "]" << pGraphState->m_DashPhase << " d\n"; } if (!m_bGraphStateSet || @@ -281,75 +337,22 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { } m_CurGraphState.Copy(*pGraphState); m_bGraphStateSet = true; - if (buf.GetSize()) { - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - } -} - -static void FaxCompressData(uint8_t* src_buf, - int width, - int height, - std::unique_ptr* dest_buf, - uint32_t* dest_size) { - if (width * height > 128) { - CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8, - dest_buf, dest_size); - FX_Free(src_buf); - } else { - dest_buf->reset(src_buf); - *dest_size = (width + 7) / 8 * height; - } -} - -static void PSCompressData(int PSLevel, - uint8_t* src_buf, - uint32_t src_size, - uint8_t** output_buf, - uint32_t* output_size, - const FX_CHAR** filter) { - *output_buf = src_buf; - *output_size = src_size; - *filter = ""; - if (src_size < 1024) { - return; - } - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - uint8_t* dest_buf = nullptr; - uint32_t dest_size = src_size; - if (PSLevel >= 3) { - if (pEncoders && - pEncoders->GetFlateModule()->Encode(src_buf, src_size, &dest_buf, - &dest_size)) { - *filter = "/FlateDecode filter "; - } - } else { - if (pEncoders && - pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size, - &dest_buf, &dest_size)) { - *filter = "/RunLengthDecode filter "; - } - } - if (dest_size < src_size) { - *output_buf = dest_buf; - *output_size = dest_size; - } else { - *filter = nullptr; - FX_Free(dest_buf); - } + if (buf.tellp()) + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); } -bool CFX_PSRenderer::SetDIBits(const CFX_DIBSource* pSource, +bool CFX_PSRenderer::SetDIBits(const RetainPtr& pSource, uint32_t color, int left, int top) { StartRendering(); - CFX_Matrix matrix((FX_FLOAT)(pSource->GetWidth()), 0.0f, 0.0f, - -(FX_FLOAT)(pSource->GetHeight()), (FX_FLOAT)(left), - (FX_FLOAT)(top + pSource->GetHeight())); + CFX_Matrix matrix((float)(pSource->GetWidth()), 0.0f, 0.0f, + -(float)(pSource->GetHeight()), (float)(left), + (float)(top + pSource->GetHeight())); return DrawDIBits(pSource, color, &matrix, 0); } -bool CFX_PSRenderer::StretchDIBits(const CFX_DIBSource* pSource, +bool CFX_PSRenderer::StretchDIBits(const RetainPtr& pSource, uint32_t color, int dest_left, int dest_top, @@ -357,13 +360,12 @@ bool CFX_PSRenderer::StretchDIBits(const CFX_DIBSource* pSource, int dest_height, uint32_t flags) { StartRendering(); - CFX_Matrix matrix((FX_FLOAT)(dest_width), 0.0f, 0.0f, - (FX_FLOAT)(-dest_height), (FX_FLOAT)(dest_left), - (FX_FLOAT)(dest_top + dest_height)); + CFX_Matrix matrix((float)(dest_width), 0.0f, 0.0f, (float)(-dest_height), + (float)(dest_left), (float)(dest_top + dest_height)); return DrawDIBits(pSource, color, &matrix, flags); } -bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, +bool CFX_PSRenderer::DrawDIBits(const RetainPtr& pSource, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags) { @@ -372,28 +374,32 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, (pMatrix->c == 0 && pMatrix->d == 0)) { return true; } - if (pSource->HasAlpha()) { + if (pSource->HasAlpha()) return false; - } + int alpha = FXARGB_A(color); if (pSource->IsAlphaMask() && (alpha < 255 || pSource->GetBPP() != 1)) return false; - OUTPUT_PS("q\n"); - CFX_ByteTextBuf buf; + m_pStream->WriteString("q\n"); + + std::ostringstream buf; buf << "[" << pMatrix->a << " " << pMatrix->b << " " << pMatrix->c << " " << pMatrix->d << " " << pMatrix->e << " " << pMatrix->f << "]cm "; + int width = pSource->GetWidth(); int height = pSource->GetHeight(); buf << width << " " << height; + if (pSource->GetBPP() == 1 && !pSource->GetPalette()) { int pitch = (width + 7) / 8; uint32_t src_size = height * pitch; uint8_t* src_buf = FX_Alloc(uint8_t, src_size); for (int row = 0; row < height; row++) { const uint8_t* src_scan = pSource->GetScanline(row); - FXSYS_memcpy(src_buf + row * pitch, src_scan, pitch); + memcpy(src_buf + row * pitch, src_scan, pitch); } + std::unique_ptr output_buf; uint32_t output_size; FaxCompressData(src_buf, width, height, &output_buf, &output_size); @@ -406,55 +412,56 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, } buf << width << " 0 0 -" << height << " 0 " << height << "]currentfile/ASCII85Decode filter "; + if (output_buf.get() != src_buf) { buf << "<>/CCITTFaxDecode filter "; } - if (pSource->IsAlphaMask()) { + if (pSource->IsAlphaMask()) buf << "iM\n"; - } else { + else buf << "false 1 colorimage\n"; - } - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); WritePSBinary(output_buf.get(), output_size); output_buf.release(); } else { CFX_DIBExtractor source_extractor(pSource); - CFX_MaybeOwned pConverted(source_extractor.GetBitmap()); - if (!pConverted.Get()) + RetainPtr pConverted = source_extractor.GetBitmap(); + if (!pConverted) return false; switch (pSource->GetFormat()) { case FXDIB_1bppRgb: case FXDIB_Rgb32: - pConverted = pConverted->CloneConvert(FXDIB_Rgb).release(); + pConverted = pConverted->CloneConvert(FXDIB_Rgb); break; case FXDIB_8bppRgb: if (pSource->GetPalette()) { - pConverted = pConverted->CloneConvert(FXDIB_Rgb).release(); + pConverted = pConverted->CloneConvert(FXDIB_Rgb); } break; case FXDIB_1bppCmyk: - pConverted = pConverted->CloneConvert(FXDIB_Cmyk).release(); + pConverted = pConverted->CloneConvert(FXDIB_Cmyk); break; case FXDIB_8bppCmyk: if (pSource->GetPalette()) { - pConverted = pConverted->CloneConvert(FXDIB_Cmyk).release(); + pConverted = pConverted->CloneConvert(FXDIB_Cmyk); } break; default: break; } if (!pConverted) { - OUTPUT_PS("\nQ\n"); + m_pStream->WriteString("\nQ\n"); return false; } + int bpp = pConverted->GetBPP() / 8; uint8_t* output_buf = nullptr; - FX_STRSIZE output_size = 0; - const FX_CHAR* filter = nullptr; + size_t output_size = 0; + const char* filter = nullptr; if ((m_PSLevel == 2 || flags & FXRENDER_IMAGE_LOSSY) && - CCodec_JpegModule::JpegEncode(pConverted.Get(), &output_buf, - &output_size)) { + CCodec_JpegModule::JpegEncode(pConverted, &output_buf, &output_size)) { filter = "/DCTDecode filter "; } if (!filter) { @@ -472,39 +479,40 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, src_scan += 3; } } else { - FXSYS_memcpy(dest_scan, src_scan, src_pitch); + memcpy(dest_scan, src_scan, src_pitch); } } uint8_t* compressed_buf; uint32_t compressed_size; PSCompressData(m_PSLevel, output_buf, output_size, &compressed_buf, &compressed_size, &filter); - if (output_buf != compressed_buf) { + if (output_buf != compressed_buf) FX_Free(output_buf); - } + output_buf = compressed_buf; output_size = compressed_size; } buf << " 8["; buf << width << " 0 0 -" << height << " 0 " << height << "]"; buf << "currentfile/ASCII85Decode filter "; - if (filter) { + if (filter) buf << filter; - } + buf << "false " << bpp; buf << " colorimage\n"; - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); + WritePSBinary(output_buf, output_size); FX_Free(output_buf); } - OUTPUT_PS("\nQ\n"); + m_pStream->WriteString("\nQ\n"); return true; } void CFX_PSRenderer::SetColor(uint32_t color) { bool bCMYK = false; if (bCMYK != m_bCmykOutput || !m_bColorSet || m_LastColor != color) { - CFX_ByteTextBuf buf; + std::ostringstream buf; if (bCMYK) { buf << FXSYS_GetCValue(color) / 255.0 << " " << FXSYS_GetMValue(color) / 255.0 << " " @@ -518,7 +526,7 @@ void CFX_PSRenderer::SetColor(uint32_t color) { m_bColorSet = true; m_LastColor = color; } - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); } } @@ -534,14 +542,14 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, pPSFont->m_Glyphs[j].m_GlyphIndex == charpos.m_GlyphIndex && ((!pPSFont->m_Glyphs[j].m_bGlyphAdjust && !charpos.m_bGlyphAdjust) || (pPSFont->m_Glyphs[j].m_bGlyphAdjust && charpos.m_bGlyphAdjust && - (FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] - - charpos.m_AdjustMatrix[0]) < 0.01 && - FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] - - charpos.m_AdjustMatrix[1]) < 0.01 && - FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] - - charpos.m_AdjustMatrix[2]) < 0.01 && - FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] - - charpos.m_AdjustMatrix[3]) < 0.01)))) { + (fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] - + charpos.m_AdjustMatrix[0]) < 0.01 && + fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] - + charpos.m_AdjustMatrix[1]) < 0.01 && + fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] - + charpos.m_AdjustMatrix[2]) < 0.01 && + fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] - + charpos.m_AdjustMatrix[3]) < 0.01)))) { *ps_fontnum = i; *ps_glyphindex = j; return; @@ -549,10 +557,11 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, } ++i; } + if (m_PSFontList.empty() || m_PSFontList.back()->m_nGlyphs == 256) { m_PSFontList.push_back(pdfium::MakeUnique()); m_PSFontList.back()->m_nGlyphs = 0; - CFX_ByteTextBuf buf; + std::ostringstream buf; buf << "8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n" "/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding " "exch/.notdef put}for\n" @@ -564,9 +573,10 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, "currentdict end\n"; buf << "/X" << static_cast(m_PSFontList.size() - 1) << " exch definefont pop\n"; - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - buf.Clear(); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); + buf.str(""); } + *ps_fontnum = m_PSFontList.size() - 1; CPSFont* pPSFont = m_PSFontList[*ps_fontnum].get(); int glyphindex = pPSFont->m_nGlyphs; @@ -598,7 +608,7 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, if (charpos.m_bGlyphAdjust) TransformedPath.Transform(&matrix); - CFX_ByteTextBuf buf; + std::ostringstream buf; buf << "/X" << *ps_fontnum << " Ff/CharProcs get begin/" << glyphindex << "{n "; for (size_t p = 0; p < TransformedPath.GetPoints().size(); p++) { @@ -625,26 +635,31 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, buf << "f}bind def end\n"; buf << "/X" << *ps_fontnum << " Ff/Encoding get " << glyphindex << "/" << glyphindex << " put\n"; - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); } bool CFX_PSRenderer::DrawText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) { - StartRendering(); - int alpha = FXARGB_A(color); - if (alpha < 255) - return false; + // Do not send zero or negative font sizes to printers. See crbug.com/767343. + if (font_size <= 0.0) + return true; if ((pObject2Device->a == 0 && pObject2Device->b == 0) || (pObject2Device->c == 0 && pObject2Device->d == 0)) { return true; } + + StartRendering(); + int alpha = FXARGB_A(color); + if (alpha < 255) + return false; + SetColor(color); - CFX_ByteTextBuf buf; + std::ostringstream buf; buf << "q[" << pObject2Device->a << " " << pObject2Device->b << " " << pObject2Device->c << " " << pObject2Device->d << " " << pObject2Device->e << " " << pObject2Device->f << "]cm\n"; @@ -661,12 +676,11 @@ bool CFX_PSRenderer::DrawText(int nChars, last_fontnum = ps_fontnum; } buf << pCharPos[i].m_Origin.x << " " << pCharPos[i].m_Origin.y << " m"; - CFX_ByteString hex; - hex.Format("<%02X>", ps_glyphindex); - buf << hex.AsStringC() << "Tj\n"; + ByteString hex = ByteString::Format("<%02X>", ps_glyphindex); + buf << hex.AsStringView() << "Tj\n"; } buf << "Q\n"; - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.str().c_str(), buf.tellp()); pCache->ReleaseCachedFace(pFont); return true; } @@ -674,13 +688,12 @@ bool CFX_PSRenderer::DrawText(int nChars, void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) { uint8_t* dest_buf; uint32_t dest_size; - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - if (pEncoders && - pEncoders->GetBasicModule()->A85Encode(data, len, &dest_buf, + CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); + if (pEncoders->GetBasicModule()->A85Encode(data, len, &dest_buf, &dest_size)) { - m_pOutput->OutputPS((const FX_CHAR*)dest_buf, dest_size); + m_pStream->WriteBlock(dest_buf, dest_size); FX_Free(dest_buf); } else { - m_pOutput->OutputPS((const FX_CHAR*)data, len); + m_pStream->WriteBlock(data, len); } } diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h index 163c6180af4c3e65dfb1f29669da90075657bfac..33829ead98a1c2df6f55ecb53d43605a13a62b8a 100644 --- a/core/fxge/win32/cfx_psrenderer.h +++ b/core/fxge/win32/cfx_psrenderer.h @@ -11,9 +11,10 @@ #include #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_stream.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" #include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/win32/cpsoutput.h" class CFX_DIBSource; class CFX_FaceCache; @@ -29,7 +30,7 @@ class CFX_PSRenderer { CFX_PSRenderer(); ~CFX_PSRenderer(); - void Init(CPSOutput* pOutput, + void Init(const RetainPtr& stream, int pslevel, int width, int height, @@ -51,18 +52,18 @@ class CFX_PSRenderer { uint32_t fill_color, uint32_t stroke_color, int fill_mode); - bool SetDIBits(const CFX_DIBSource* pBitmap, + bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top); - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, int dest_width, int dest_height, uint32_t flags); - bool DrawDIBits(const CFX_DIBSource* pBitmap, + bool DrawDIBits(const RetainPtr& pBitmap, uint32_t color, const CFX_Matrix* pMatrix, uint32_t flags); @@ -70,7 +71,7 @@ class CFX_PSRenderer { const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color); private: @@ -85,7 +86,7 @@ class CFX_PSRenderer { int* ps_glyphindex); void WritePSBinary(const uint8_t* data, int len); - CPSOutput* m_pOutput; + RetainPtr m_pStream; int m_PSLevel; CFX_GraphStateData m_CurGraphState; bool m_bGraphStateSet; diff --git a/core/fxge/win32/cfx_windowsdib.h b/core/fxge/win32/cfx_windowsdib.h index 2564b7fa36a4faf29095542f9cbab7ac7ee742f1..7c2447ded2d125471932dd224e334e7034c102f1 100644 --- a/core/fxge/win32/cfx_windowsdib.h +++ b/core/fxge/win32/cfx_windowsdib.h @@ -10,6 +10,10 @@ #ifndef _WINDOWS_ #include #endif + +#include "core/fxcrt/bytestring.h" +#include "core/fxge/dib/cfx_dibitmap.h" + #define WINDIB_OPEN_MEMORY 0x1 #define WINDIB_OPEN_PATHNAME 0x2 @@ -20,28 +24,32 @@ typedef struct WINDIB_Open_Args_ { size_t memory_size; - const FX_WCHAR* path_name; + const wchar_t* path_name; } WINDIB_Open_Args_; class CFX_WindowsDIB : public CFX_DIBitmap { public: - CFX_WindowsDIB(HDC hDC, int width, int height); + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + ~CFX_WindowsDIB() override; - static CFX_ByteString GetBitmapInfo(const CFX_DIBitmap* pBitmap); - static CFX_DIBitmap* LoadFromBuf(BITMAPINFO* pbmi, void* pData); - static HBITMAP GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC); - static CFX_DIBitmap* LoadFromFile(const FX_WCHAR* filename); - static CFX_DIBitmap* LoadFromFile(const FX_CHAR* filename); - static CFX_DIBitmap* LoadDIBitmap(WINDIB_Open_Args_ args); + static ByteString GetBitmapInfo(const RetainPtr& pBitmap); + static HBITMAP GetDDBitmap(const RetainPtr& pBitmap, HDC hDC); + + static RetainPtr LoadFromBuf(BITMAPINFO* pbmi, void* pData); + static RetainPtr LoadFromFile(const wchar_t* filename); + static RetainPtr LoadFromFile(const char* filename); + static RetainPtr LoadDIBitmap(WINDIB_Open_Args_ args); - HDC GetDC() const { return m_hMemDC; } HBITMAP GetWindowsBitmap() const { return m_hBitmap; } void LoadFromDevice(HDC hDC, int left, int top); void SetToDevice(HDC hDC, int left, int top); protected: + CFX_WindowsDIB(HDC hDC, int width, int height); + HDC m_hMemDC; HBITMAP m_hBitmap; HBITMAP m_hOldBitmap; diff --git a/core/fxge/win32/cpsoutput.cpp b/core/fxge/win32/cpsoutput.cpp index 76b37d7dacf1552b2922930d0efbb6b9730f5b48..83f2fc09c611b915239b34221d4c8cb6016cb9ae 100644 --- a/core/fxge/win32/cpsoutput.cpp +++ b/core/fxge/win32/cpsoutput.cpp @@ -10,26 +10,17 @@ #include "core/fxcrt/fx_system.h" -CPSOutput::CPSOutput(HDC hDC) { - m_hDC = hDC; -} +CPSOutput::CPSOutput(HDC hDC) : m_hDC(hDC) {} CPSOutput::~CPSOutput() {} -void CPSOutput::Release() { - delete this; -} - -void CPSOutput::OutputPS(const FX_CHAR* str, int len) { - if (len < 0) - len = static_cast(FXSYS_strlen(str)); - +bool CPSOutput::WriteBlock(const void* str, size_t len) { int sent_len = 0; while (len > 0) { - FX_CHAR buffer[1026]; - int send_len = std::min(len, 1024); + char buffer[1026]; + size_t send_len = std::min(len, static_cast(1024)); *(reinterpret_cast(buffer)) = send_len; - FXSYS_memcpy(buffer + 2, str + sent_len, send_len); + memcpy(buffer + 2, static_cast(str) + sent_len, send_len); // TODO(thestig/rbpotter): Do PASSTHROUGH for non-Chromium usage. // ExtEscape(m_hDC, PASSTHROUGH, send_len + 2, buffer, 0, nullptr); @@ -37,4 +28,9 @@ void CPSOutput::OutputPS(const FX_CHAR* str, int len) { sent_len += send_len; len -= send_len; } + return true; +} + +bool CPSOutput::WriteString(const ByteStringView& str) { + return WriteBlock(str.unterminated_c_str(), str.GetLength()); } diff --git a/core/fxge/win32/cpsoutput.h b/core/fxge/win32/cpsoutput.h index bc9225bd7e85e97e79f1fa48d62a574bcc6eb0ed..d140de95f4763eaf9dad6594c027417b6ff9fdab 100644 --- a/core/fxge/win32/cpsoutput.h +++ b/core/fxge/win32/cpsoutput.h @@ -9,17 +9,19 @@ #include +#include "core/fxcrt/fx_stream.h" #include "core/fxcrt/fx_system.h" -class CPSOutput { +class CPSOutput : public IFX_WriteStream { public: explicit CPSOutput(HDC hDC); - ~CPSOutput(); + ~CPSOutput() override; - // IFX_PSOutput - void Release(); - void OutputPS(const FX_CHAR* str, int len); + // IFX_Writestream + bool WriteBlock(const void* str, size_t len) override; + bool WriteString(const ByteStringView& str) override; + private: HDC m_hDC; }; diff --git a/core/fxge/win32/dwrite_int.h b/core/fxge/win32/dwrite_int.h index 86ead89947ab1852a6db7809957b401c511c41ec..7fbb929c08fec3d5a122a2b2f23356cda9839787 100644 --- a/core/fxge/win32/dwrite_int.h +++ b/core/fxge/win32/dwrite_int.h @@ -7,15 +7,19 @@ #ifndef CORE_FXGE_WIN32_DWRITE_INT_H_ #define CORE_FXGE_WIN32_DWRITE_INT_H_ +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/fx_dib.h" + #ifndef DECLSPEC_UUID -#if (_MSC_VER >= 1100) && defined(__cplusplus) +#if defined(__cplusplus) #define DECLSPEC_UUID(x) __declspec(uuid(x)) #else #define DECLSPEC_UUID(x) #endif #endif #ifndef DECLSPEC_NOVTABLE -#if (_MSC_VER >= 1100) && defined(__cplusplus) +#if defined(__cplusplus) #define DECLSPEC_NOVTABLE __declspec(novtable) #else #define DECLSPEC_NOVTABLE @@ -39,21 +43,22 @@ class CDWriteExt { void* DwCreateFontFaceFromStream(uint8_t* pData, uint32_t size, int simulation_style); - bool DwCreateRenderingTarget(CFX_DIBitmap* pSrc, void** renderTarget); + bool DwCreateRenderingTarget(const RetainPtr& pSrc, + void** renderTarget); void DwDeleteRenderingTarget(void* renderTarget); bool DwRendingString(void* renderTarget, CFX_ClipRgn* pClipRgn, FX_RECT& stringRect, CFX_Matrix* pMatrix, void* font, - FX_FLOAT font_size, + float font_size, FX_ARGB text_color, int glyph_count, unsigned short* glyph_indices, - FX_FLOAT baselineOriginX, - FX_FLOAT baselineOriginY, + float baselineOriginX, + float baselineOriginY, void* glyph_offsets, - FX_FLOAT* glyph_advances); + float* glyph_advances); void DwDeleteFont(void* pFont); protected: diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp index 92e9b41e064eaca644e2ad69a8a9470274097cdf..492b0b57df08b2d3b42ceb24b6158289681f9511 100644 --- a/core/fxge/win32/fx_win32_device.cpp +++ b/core/fxge/win32/fx_win32_device.cpp @@ -10,16 +10,19 @@ #include #include -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" +#include "core/fxcrt/fx_codepage.h" #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_windowsdevice.h" -#include "core/fxge/dib/dib_int.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxge/cfx_folderfontinfo.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_windowsrenderdevice.h" +#include "core/fxge/dib/cfx_dibextractor.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/dib/cstretchengine.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" -#include "core/fxge/ge/fx_text_int.h" #include "core/fxge/ifx_systemfontinfo.h" #include "core/fxge/win32/cfx_windowsdib.h" #include "core/fxge/win32/dwrite_int.h" @@ -34,15 +37,15 @@ namespace { const struct { - const FX_CHAR* m_pFaceName; - const FX_CHAR* m_pVariantName; + const char* m_pFaceName; + const char* m_pVariantName; } g_VariantNames[] = { {"DFKai-SB", "\x19\x6A\x77\x69\xD4\x9A"}, }; const struct { - const FX_CHAR* m_pName; - const FX_CHAR* m_pWinName; + const char* m_pName; + const char* m_pWinName; bool m_bBold; bool m_bItalic; } g_Base14Substs[] = { @@ -61,15 +64,15 @@ const struct { }; struct FontNameMap { - const FX_CHAR* m_pSubFontName; - const FX_CHAR* m_pSrcFontName; + const char* m_pSubFontName; + const char* m_pSrcFontName; }; const FontNameMap g_JpFontNameMap[] = { {"MS Mincho", "Heiseimin-W3"}, {"MS Gothic", "Jun101-Light"}, }; -bool GetSubFontName(CFX_ByteString* name) { +bool GetSubFontName(ByteString* name) { for (size_t i = 0; i < FX_ArraySize(g_JpFontNameMap); ++i) { if (!FXSYS_stricmp(name->c_str(), g_JpFontNameMap[i].m_pSrcFontName)) { *name = g_JpFontNameMap[i].m_pSubFontName; @@ -91,12 +94,11 @@ bool IsGDIEnabled() { HPEN CreatePen(const CFX_GraphStateData* pGraphState, const CFX_Matrix* pMatrix, uint32_t argb) { - FX_FLOAT width; - FX_FLOAT scale = 1.f; + float width; + float scale = 1.f; if (pMatrix) - scale = FXSYS_fabs(pMatrix->a) > FXSYS_fabs(pMatrix->b) - ? FXSYS_fabs(pMatrix->a) - : FXSYS_fabs(pMatrix->b); + scale = fabs(pMatrix->a) > fabs(pMatrix->b) ? fabs(pMatrix->a) + : fabs(pMatrix->b); if (pGraphState) { width = scale * pGraphState->m_LineWidth; } else { @@ -135,7 +137,7 @@ HPEN CreatePen(const CFX_GraphStateData* pGraphState, } int a; FX_COLORREF rgb; - ArgbDecode(argb, a, rgb); + std::tie(a, rgb) = ArgbToColorRef(argb); LOGBRUSH lb; lb.lbColor = rgb; lb.lbStyle = BS_SOLID; @@ -150,7 +152,7 @@ HPEN CreatePen(const CFX_GraphStateData* pGraphState, dashes[i] = std::max(dashes[i], 1U); } } - return ExtCreatePen(PenStyle, (DWORD)FXSYS_ceil(width), &lb, + return ExtCreatePen(PenStyle, (DWORD)ceil(width), &lb, pGraphState->m_DashCount, reinterpret_cast(dashes.data())); } @@ -158,7 +160,7 @@ HPEN CreatePen(const CFX_GraphStateData* pGraphState, HBRUSH CreateBrush(uint32_t argb) { int a; FX_COLORREF rgb; - ArgbDecode(argb, a, rgb); + std::tie(a, rgb) = ArgbToColorRef(argb); return CreateSolidBrush(rgb); } @@ -215,26 +217,26 @@ void SetPathToDC(HDC hDC, // altogether and replace by Skia code. struct rect_base { - FX_FLOAT x1; - FX_FLOAT y1; - FX_FLOAT x2; - FX_FLOAT y2; + float x1; + float y1; + float x2; + float y2; }; -unsigned clip_liang_barsky(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, +unsigned clip_liang_barsky(float x1, + float y1, + float x2, + float y2, const rect_base& clip_box, - FX_FLOAT* x, - FX_FLOAT* y) { - const FX_FLOAT nearzero = 1e-30f; - FX_FLOAT deltax = x2 - x1; - FX_FLOAT deltay = y2 - y1; + float* x, + float* y) { + const float nearzero = 1e-30f; + float deltax = x2 - x1; + float deltay = y2 - y1; unsigned np = 0; if (deltax == 0) deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; - FX_FLOAT xin, xout; + float xin, xout; if (deltax > 0) { xin = clip_box.x1; xout = clip_box.x2; @@ -242,10 +244,10 @@ unsigned clip_liang_barsky(FX_FLOAT x1, xin = clip_box.x2; xout = clip_box.x1; } - FX_FLOAT tinx = (xin - x1) / deltax; + float tinx = (xin - x1) / deltax; if (deltay == 0) deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; - FX_FLOAT yin, yout; + float yin, yout; if (deltay > 0) { yin = clip_box.y1; yout = clip_box.y2; @@ -253,8 +255,8 @@ unsigned clip_liang_barsky(FX_FLOAT x1, yin = clip_box.y2; yout = clip_box.y1; } - FX_FLOAT tiny = (yin - y1) / deltay; - FX_FLOAT tin1, tin2; + float tiny = (yin - y1) / deltay; + float tin1, tin2; if (tinx < tiny) { tin1 = tinx; tin2 = tiny; @@ -269,9 +271,9 @@ unsigned clip_liang_barsky(FX_FLOAT x1, ++np; } if (tin2 <= 1.0f) { - FX_FLOAT toutx = (xout - x1) / deltax; - FX_FLOAT touty = (yout - y1) / deltay; - FX_FLOAT tout1 = (toutx < touty) ? toutx : touty; + float toutx = (xout - x1) / deltax; + float touty = (yout - y1) / deltay; + float tout1 = (toutx < touty) ? toutx : touty; if (tin2 > 0 || tout1 > 0) { if (tin2 <= tout1) { if (tin2 > 0) { @@ -324,8 +326,7 @@ class CFX_Win32FallbackFontInfo final : public CFX_FolderFontInfo { bool bItalic, int charset, int pitch_family, - const FX_CHAR* family, - int& iExact) override; + const char* family) override; }; class CFX_Win32FontInfo final : public IFX_SystemFontInfo { @@ -339,30 +340,27 @@ class CFX_Win32FontInfo final : public IFX_SystemFontInfo { bool bItalic, int charset, int pitch_family, - const FX_CHAR* face, - int& iExact) override; - void* GetFont(const FX_CHAR* face) override { return nullptr; } + const char* face) override; + void* GetFont(const char* face) override { return nullptr; } uint32_t GetFontData(void* hFont, uint32_t table, uint8_t* buffer, uint32_t size) override; - bool GetFaceName(void* hFont, CFX_ByteString& name) override; - bool GetFontCharset(void* hFont, int& charset) override; + bool GetFaceName(void* hFont, ByteString* name) override; + bool GetFontCharset(void* hFont, int* charset) override; void DeleteFont(void* hFont) override; bool IsOpenTypeFromDiv(const LOGFONTA* plf); bool IsSupportFontFormDiv(const LOGFONTA* plf); void AddInstalledFont(const LOGFONTA* plf, uint32_t FontType); - void GetGBPreference(CFX_ByteString& face, int weight, int picth_family); - void GetJapanesePreference(CFX_ByteString& face, - int weight, - int picth_family); - CFX_ByteString FindFont(const CFX_ByteString& name); + void GetGBPreference(ByteString& face, int weight, int picth_family); + void GetJapanesePreference(ByteString& face, int weight, int picth_family); + ByteString FindFont(const ByteString& name); HDC m_hDC; - CFX_FontMapper* m_pMapper; - CFX_ByteString m_LastFamily; - CFX_ByteString m_KaiTi, m_FangSong; + UnownedPtr m_pMapper; + ByteString m_LastFamily; + ByteString m_KaiTi, m_FangSong; }; int CALLBACK FontEnumProc(const LOGFONTA* plf, @@ -426,8 +424,8 @@ bool CFX_Win32FontInfo::IsSupportFontFormDiv(const LOGFONTA* plf) { void CFX_Win32FontInfo::AddInstalledFont(const LOGFONTA* plf, uint32_t FontType) { - CFX_ByteString name(plf->lfFaceName); - if (name[0] == '@') + ByteString name(plf->lfFaceName); + if (name.GetLength() > 0 && name[0] == '@') return; if (name == m_LastFamily) { @@ -446,8 +444,8 @@ void CFX_Win32FontInfo::AddInstalledFont(const LOGFONTA* plf, bool CFX_Win32FontInfo::EnumFontList(CFX_FontMapper* pMapper) { m_pMapper = pMapper; LOGFONTA lf; - FXSYS_memset(&lf, 0, sizeof(LOGFONTA)); - lf.lfCharSet = FXFONT_DEFAULT_CHARSET; + memset(&lf, 0, sizeof(LOGFONTA)); + lf.lfCharSet = FX_CHARSET_Default; lf.lfFaceName[0] = 0; lf.lfPitchAndFamily = 0; EnumFontFamiliesExA(m_hDC, &lf, (FONTENUMPROCA)FontEnumProc, (uintptr_t) this, @@ -455,40 +453,38 @@ bool CFX_Win32FontInfo::EnumFontList(CFX_FontMapper* pMapper) { return true; } -CFX_ByteString CFX_Win32FontInfo::FindFont(const CFX_ByteString& name) { +ByteString CFX_Win32FontInfo::FindFont(const ByteString& name) { if (!m_pMapper) return name; for (size_t i = 0; i < m_pMapper->m_InstalledTTFonts.size(); ++i) { - CFX_ByteString thisname = m_pMapper->m_InstalledTTFonts[i]; + ByteString thisname = m_pMapper->m_InstalledTTFonts[i]; if (thisname.Left(name.GetLength()) == name) return m_pMapper->m_InstalledTTFonts[i]; } for (size_t i = 0; i < m_pMapper->m_LocalizedTTFonts.size(); ++i) { - CFX_ByteString thisname = m_pMapper->m_LocalizedTTFonts[i].first; + ByteString thisname = m_pMapper->m_LocalizedTTFonts[i].first; if (thisname.Left(name.GetLength()) == name) return m_pMapper->m_LocalizedTTFonts[i].second; } - return CFX_ByteString(); + return ByteString(); } void* CFX_Win32FallbackFontInfo::MapFont(int weight, bool bItalic, int charset, int pitch_family, - const FX_CHAR* cstr_face, - int& iExact) { + const char* cstr_face) { void* font = GetSubstFont(cstr_face); - if (font) { - iExact = 1; + if (font) return font; - } + bool bCJK = true; switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: - case FXFONT_GB2312_CHARSET: - case FXFONT_CHINESEBIG5_CHARSET: - case FXFONT_HANGUL_CHARSET: + case FX_CHARSET_ShiftJIS: + case FX_CHARSET_ChineseSimplified: + case FX_CHARSET_ChineseTraditional: + case FX_CHARSET_Hangul: break; default: bCJK = false; @@ -497,10 +493,10 @@ void* CFX_Win32FallbackFontInfo::MapFont(int weight, return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); } -void CFX_Win32FontInfo::GetGBPreference(CFX_ByteString& face, +void CFX_Win32FontInfo::GetGBPreference(ByteString& face, int weight, int picth_family) { - if (face.Find("KaiTi") >= 0 || face.Find("\xbf\xac") >= 0) { + if (face.Contains("KaiTi") || face.Contains("\xbf\xac")) { if (m_KaiTi.IsEmpty()) { m_KaiTi = FindFont("KaiTi"); if (m_KaiTi.IsEmpty()) { @@ -508,7 +504,7 @@ void CFX_Win32FontInfo::GetGBPreference(CFX_ByteString& face, } } face = m_KaiTi; - } else if (face.Find("FangSong") >= 0 || face.Find("\xb7\xc2\xcb\xce") >= 0) { + } else if (face.Contains("FangSong") || face.Contains("\xb7\xc2\xcb\xce")) { if (m_FangSong.IsEmpty()) { m_FangSong = FindFont("FangSong"); if (m_FangSong.IsEmpty()) { @@ -516,9 +512,9 @@ void CFX_Win32FontInfo::GetGBPreference(CFX_ByteString& face, } } face = m_FangSong; - } else if (face.Find("SimSun") >= 0 || face.Find("\xcb\xce") >= 0) { + } else if (face.Contains("SimSun") || face.Contains("\xcb\xce")) { face = "SimSun"; - } else if (face.Find("SimHei") >= 0 || face.Find("\xba\xda") >= 0) { + } else if (face.Contains("SimHei") || face.Contains("\xba\xda")) { face = "SimHei"; } else if (!(picth_family & FF_ROMAN) && weight > 550) { face = "SimHei"; @@ -527,18 +523,18 @@ void CFX_Win32FontInfo::GetGBPreference(CFX_ByteString& face, } } -void CFX_Win32FontInfo::GetJapanesePreference(CFX_ByteString& face, +void CFX_Win32FontInfo::GetJapanesePreference(ByteString& face, int weight, int picth_family) { - if (face.Find("Gothic") >= 0 || - face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - if (face.Find("PGothic") >= 0 || - face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { + if (face.Contains("Gothic") || + face.Contains("\x83\x53\x83\x56\x83\x62\x83\x4e")) { + if (face.Contains("PGothic") || + face.Contains("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e")) { face = "MS PGothic"; - } else if (face.Find("UI Gothic") >= 0) { + } else if (face.Contains("UI Gothic")) { face = "MS UI Gothic"; } else { - if (face.Find("HGSGothicM") >= 0 || face.Find("HGMaruGothicMPRO") >= 0) { + if (face.Contains("HGSGothicM") || face.Contains("HGMaruGothicMPRO")) { face = "MS PGothic"; } else { face = "MS Gothic"; @@ -546,9 +542,8 @@ void CFX_Win32FontInfo::GetJapanesePreference(CFX_ByteString& face, } return; } - if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { - if (face.Find("PMincho") >= 0 || - face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { + if (face.Contains("Mincho") || face.Contains("\x96\xbe\x92\xa9")) { + if (face.Contains("PMincho") || face.Contains("\x82\x6f\x96\xbe\x92\xa9")) { face = "MS PMincho"; } else { face = "MS Mincho"; @@ -569,29 +564,28 @@ void* CFX_Win32FontInfo::MapFont(int weight, bool bItalic, int charset, int pitch_family, - const FX_CHAR* cstr_face, - int& iExact) { - CFX_ByteString face = cstr_face; + const char* cstr_face) { + ByteString face = cstr_face; int iBaseFont; - for (iBaseFont = 0; iBaseFont < 12; iBaseFont++) - if (face == CFX_ByteStringC(g_Base14Substs[iBaseFont].m_pName)) { + for (iBaseFont = 0; iBaseFont < 12; iBaseFont++) { + if (face == ByteStringView(g_Base14Substs[iBaseFont].m_pName)) { face = g_Base14Substs[iBaseFont].m_pWinName; weight = g_Base14Substs[iBaseFont].m_bBold ? FW_BOLD : FW_NORMAL; bItalic = g_Base14Substs[iBaseFont].m_bItalic; - iExact = true; break; } - if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_SYMBOL_CHARSET) { - charset = FXFONT_DEFAULT_CHARSET; } + if (charset == FX_CHARSET_ANSI || charset == FX_CHARSET_Symbol) + charset = FX_CHARSET_Default; + int subst_pitch_family = pitch_family; switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: + case FX_CHARSET_ShiftJIS: subst_pitch_family = FF_ROMAN; break; - case FXFONT_CHINESEBIG5_CHARSET: - case FXFONT_HANGUL_CHARSET: - case FXFONT_GB2312_CHARSET: + case FX_CHARSET_ChineseTraditional: + case FX_CHARSET_Hangul: + case FX_CHARSET_ChineseSimplified: subst_pitch_family = 0; break; } @@ -605,34 +599,34 @@ void* CFX_Win32FontInfo::MapFont(int weight, if (face.EqualNoCase(facebuf)) return hFont; - CFX_WideString wsFace = CFX_WideString::FromLocal(facebuf); + WideString wsFace = WideString::FromLocal(facebuf); for (size_t i = 0; i < FX_ArraySize(g_VariantNames); ++i) { if (face != g_VariantNames[i].m_pFaceName) continue; const unsigned short* pName = reinterpret_cast( g_VariantNames[i].m_pVariantName); - FX_STRSIZE len = CFX_WideString::WStringLength(pName); - CFX_WideString wsName = CFX_WideString::FromUTF16LE(pName, len); + size_t len = WideString::WStringLength(pName); + WideString wsName = WideString::FromUTF16LE(pName, len); if (wsFace == wsName) return hFont; } ::DeleteObject(hFont); - if (charset == FXFONT_DEFAULT_CHARSET) + if (charset == FX_CHARSET_Default) return nullptr; switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: + case FX_CHARSET_ShiftJIS: GetJapanesePreference(face, weight, pitch_family); break; - case FXFONT_GB2312_CHARSET: + case FX_CHARSET_ChineseSimplified: GetGBPreference(face, weight, pitch_family); break; - case FXFONT_HANGUL_CHARSET: + case FX_CHARSET_Hangul: face = "Gulim"; break; - case FXFONT_CHINESEBIG5_CHARSET: - if (face.Find("MSung") >= 0) { + case FX_CHARSET_ChineseTraditional: + if (face.Contains("MSung")) { face = "MingLiU"; } else { face = "PMingLiU"; @@ -663,7 +657,7 @@ uint32_t CFX_Win32FontInfo::GetFontData(void* hFont, return size; } -bool CFX_Win32FontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { +bool CFX_Win32FontInfo::GetFaceName(void* hFont, ByteString* name) { char facebuf[100]; HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont); int ret = ::GetTextFaceA(m_hDC, 100, facebuf); @@ -671,22 +665,22 @@ bool CFX_Win32FontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { if (ret == 0) { return false; } - name = facebuf; + *name = facebuf; return true; } -bool CFX_Win32FontInfo::GetFontCharset(void* hFont, int& charset) { +bool CFX_Win32FontInfo::GetFontCharset(void* hFont, int* charset) { TEXTMETRIC tm; HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont); ::GetTextMetrics(m_hDC, &tm); ::SelectObject(m_hDC, hOldFont); - charset = tm.tmCharSet; + *charset = tm.tmCharSet; return true; } } // namespace -int g_pdfium_print_postscript_level = 0; +int g_pdfium_print_mode = WindowsPrintMode::kModeEmf; std::unique_ptr IFX_SystemFontInfo::CreateDefault( const char** pUnused) { @@ -700,9 +694,9 @@ std::unique_ptr IFX_SystemFontInfo::CreateDefault( CHAR windows_path[MAX_PATH] = {}; DWORD path_len = ::GetWindowsDirectoryA(windows_path, MAX_PATH); if (path_len > 0 && path_len < MAX_PATH) { - CFX_ByteString fonts_path(windows_path); + ByteString fonts_path(windows_path); fonts_path += "\\Fonts"; - pInfoFallback->AddPath(fonts_path.AsStringC()); + pInfoFallback->AddPath(fonts_path); } return std::unique_ptr(pInfoFallback); } @@ -782,12 +776,12 @@ void CGdiDeviceDriver::RestoreState(bool bKeepSaved) { SaveDC(m_hDC); } -bool CGdiDeviceDriver::GDI_SetDIBits(CFX_DIBitmap* pBitmap1, +bool CGdiDeviceDriver::GDI_SetDIBits(const RetainPtr& pBitmap1, const FX_RECT* pSrcRect, int left, int top) { if (m_DeviceClass == FXDC_PRINTER) { - std::unique_ptr pBitmap = pBitmap1->FlipImage(false, true); + RetainPtr pBitmap = pBitmap1->FlipImage(false, true); if (!pBitmap) return false; @@ -796,7 +790,7 @@ bool CGdiDeviceDriver::GDI_SetDIBits(CFX_DIBitmap* pBitmap1, int width = pSrcRect->Width(), height = pSrcRect->Height(); LPBYTE pBuffer = pBitmap->GetBuffer(); - CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap.get()); + ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); ((BITMAPINFOHEADER*)info.c_str())->biHeight *= -1; FX_RECT dst_rect(0, 0, width, height); dst_rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); @@ -806,15 +800,15 @@ bool CGdiDeviceDriver::GDI_SetDIBits(CFX_DIBitmap* pBitmap1, dst_height, pBuffer, (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS, SRCCOPY); } else { - CFX_MaybeOwned pBitmap(pBitmap1); + RetainPtr pBitmap = pBitmap1; if (pBitmap->IsCmykImage()) { - pBitmap = pBitmap->CloneConvert(FXDIB_Rgb).release(); + pBitmap = pBitmap->CloneConvert(FXDIB_Rgb); if (!pBitmap) return false; } int width = pSrcRect->Width(), height = pSrcRect->Height(); LPBYTE pBuffer = pBitmap->GetBuffer(); - CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap.Get()); + ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); ::SetDIBitsToDevice(m_hDC, left, top, width, height, pSrcRect->left, pBitmap->GetHeight() - pSrcRect->bottom, 0, pBitmap->GetHeight(), pBuffer, @@ -823,20 +817,21 @@ bool CGdiDeviceDriver::GDI_SetDIBits(CFX_DIBitmap* pBitmap1, return true; } -bool CGdiDeviceDriver::GDI_StretchDIBits(CFX_DIBitmap* pBitmap1, - int dest_left, - int dest_top, - int dest_width, - int dest_height, - uint32_t flags) { - CFX_DIBitmap* pBitmap = pBitmap1; +bool CGdiDeviceDriver::GDI_StretchDIBits( + const RetainPtr& pBitmap1, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + uint32_t flags) { + RetainPtr pBitmap = pBitmap1; if (!pBitmap || dest_width == 0 || dest_height == 0) return false; if (pBitmap->IsCmykImage() && !pBitmap->ConvertFormat(FXDIB_Rgb)) return false; - CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); + ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); if ((int64_t)abs(dest_width) * abs(dest_height) < (int64_t)pBitmap1->GetWidth() * pBitmap1->GetHeight() * 4 || (flags & FXDIB_INTERPOL) || (flags & FXDIB_BICUBIC_INTERPOL)) { @@ -844,14 +839,14 @@ bool CGdiDeviceDriver::GDI_StretchDIBits(CFX_DIBitmap* pBitmap1, } else { SetStretchBltMode(m_hDC, COLORONCOLOR); } - CFX_MaybeOwned pToStrechBitmap(pBitmap); + RetainPtr pToStrechBitmap = pBitmap; if (m_DeviceClass == FXDC_PRINTER && ((int64_t)pBitmap->GetWidth() * pBitmap->GetHeight() > (int64_t)abs(dest_width) * abs(dest_height))) { - pToStrechBitmap = pBitmap->StretchTo(dest_width, dest_height); + pToStrechBitmap = pBitmap->StretchTo(dest_width, dest_height, 0, nullptr); } - CFX_ByteString toStrechBitmapInfo = - CFX_WindowsDIB::GetBitmapInfo(pToStrechBitmap.Get()); + ByteString toStrechBitmapInfo = + CFX_WindowsDIB::GetBitmapInfo(pToStrechBitmap); ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0, pToStrechBitmap->GetWidth(), pToStrechBitmap->GetHeight(), pToStrechBitmap->GetBuffer(), @@ -860,14 +855,15 @@ bool CGdiDeviceDriver::GDI_StretchDIBits(CFX_DIBitmap* pBitmap1, return true; } -bool CGdiDeviceDriver::GDI_StretchBitMask(CFX_DIBitmap* pBitmap1, - int dest_left, - int dest_top, - int dest_width, - int dest_height, - uint32_t bitmap_color, - uint32_t flags) { - CFX_DIBitmap* pBitmap = pBitmap1; +bool CGdiDeviceDriver::GDI_StretchBitMask( + const RetainPtr& pBitmap1, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + uint32_t bitmap_color, + uint32_t flags) { + RetainPtr pBitmap = pBitmap1; if (!pBitmap || dest_width == 0 || dest_height == 0) return false; @@ -876,7 +872,7 @@ bool CGdiDeviceDriver::GDI_StretchBitMask(CFX_DIBitmap* pBitmap1, BITMAPINFOHEADER bmiHeader; uint32_t bmiColors[2]; } bmi; - FXSYS_memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER)); + memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biBitCount = 1; bmi.bmiHeader.biCompression = BI_RGB; @@ -924,14 +920,7 @@ bool CGdiDeviceDriver::GetClipBox(FX_RECT* pRect) { return !!(::GetClipBox(m_hDC, (RECT*)pRect)); } -void* CGdiDeviceDriver::GetPlatformSurface() const { - return (void*)m_hDC; -} - -void CGdiDeviceDriver::DrawLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2) { +void CGdiDeviceDriver::DrawLine(float x1, float y1, float x2, float y2) { if (!m_bMetafileDCType) { // EMF drawing is not bound to the DC. int startOutOfBoundsFlag = (x1 < 0) | ((x1 > m_Width) << 1) | ((y1 < 0) << 2) | ((y1 > m_Height) << 3); @@ -941,18 +930,18 @@ void CGdiDeviceDriver::DrawLine(FX_FLOAT x1, return; if (startOutOfBoundsFlag || endOutOfBoundsFlag) { - FX_FLOAT x[2]; - FX_FLOAT y[2]; + float x[2]; + float y[2]; int np; #ifdef _SKIA_SUPPORT_ // TODO(caryclark) temporary replacement of antigrain in line function // to permit removing antigrain altogether - rect_base rect = {0.0f, 0.0f, (FX_FLOAT)(m_Width), (FX_FLOAT)(m_Height)}; + rect_base rect = {0.0f, 0.0f, (float)(m_Width), (float)(m_Height)}; np = clip_liang_barsky(x1, y1, x2, y2, rect, x, y); #else - agg::rect_base rect(0.0f, 0.0f, (FX_FLOAT)(m_Width), - (FX_FLOAT)(m_Height)); - np = agg::clip_liang_barsky(x1, y1, x2, y2, rect, x, y); + agg::rect_base rect(0.0f, 0.0f, (float)(m_Width), + (float)(m_Height)); + np = agg::clip_liang_barsky(x1, y1, x2, y2, rect, x, y); #endif if (np == 0) return; @@ -990,18 +979,18 @@ bool CGdiDeviceDriver::DrawPath(const CFX_PathData* pPathData, !pPlatform->m_GdiplusExt.IsAvailable()) { CFX_FloatRect bbox_f = pPathData->GetBoundingBox(); if (pMatrix) - pMatrix->TransformRect(bbox_f); + bbox_f = pMatrix->TransformRect(bbox_f); FX_RECT bbox = bbox_f.GetInnerRect(); if (bbox.Width() <= 0) { - return DrawCosmeticLine( - (FX_FLOAT)(bbox.left), (FX_FLOAT)(bbox.top), (FX_FLOAT)(bbox.left), - (FX_FLOAT)(bbox.bottom + 1), fill_color, FXDIB_BLEND_NORMAL); + return DrawCosmeticLine(CFX_PointF(bbox.left, bbox.top), + CFX_PointF(bbox.left, bbox.bottom + 1), + fill_color, FXDIB_BLEND_NORMAL); } if (bbox.Height() <= 0) { - return DrawCosmeticLine((FX_FLOAT)(bbox.left), (FX_FLOAT)(bbox.top), - (FX_FLOAT)(bbox.right + 1), (FX_FLOAT)(bbox.top), - fill_color, FXDIB_BLEND_NORMAL); + return DrawCosmeticLine(CFX_PointF(bbox.left, bbox.top), + CFX_PointF(bbox.right + 1, bbox.top), fill_color, + FXDIB_BLEND_NORMAL); } } int fill_alpha = FXARGB_A(fill_color); @@ -1088,7 +1077,7 @@ bool CGdiDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, int alpha; FX_COLORREF rgb; - ArgbDecode(fill_color, alpha, rgb); + std::tie(alpha, rgb) = ArgbToColorRef(fill_color); if (alpha == 0) return true; @@ -1133,10 +1122,8 @@ bool CGdiDeviceDriver::SetClip_PathStroke( return ret; } -bool CGdiDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, +bool CGdiDeviceDriver::DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, uint32_t color, int blend_type) { if (blend_type != FXDIB_BLEND_NORMAL) @@ -1144,14 +1131,14 @@ bool CGdiDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, int a; FX_COLORREF rgb; - ArgbDecode(color, a, rgb); + std::tie(a, rgb) = ArgbToColorRef(color); if (a == 0) return true; HPEN hPen = CreatePen(PS_SOLID, 1, rgb); hPen = (HPEN)SelectObject(m_hDC, hPen); - MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), nullptr); - LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2)); + MoveToEx(m_hDC, FXSYS_round(ptMoveTo.x), FXSYS_round(ptMoveTo.y), nullptr); + LineTo(m_hDC, FXSYS_round(ptLineTo.x), FXSYS_round(ptLineTo.y)); hPen = (HPEN)SelectObject(m_hDC, hPen); DeleteObject(hPen); return true; @@ -1168,7 +1155,9 @@ CGdiDisplayDriver::CGdiDisplayDriver(HDC hDC) CGdiDisplayDriver::~CGdiDisplayDriver() {} -bool CGdiDisplayDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { +bool CGdiDisplayDriver::GetDIBits(const RetainPtr& pBitmap, + int left, + int top) { bool ret = false; int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); @@ -1178,7 +1167,7 @@ bool CGdiDisplayDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { BitBlt(hDCMemory, 0, 0, width, height, m_hDC, left, top, SRCCOPY); SelectObject(hDCMemory, holdbmp); BITMAPINFO bmi; - FXSYS_memset(&bmi, 0, sizeof bmi); + memset(&bmi, 0, sizeof bmi); bmi.bmiHeader.biSize = sizeof bmi.bmiHeader; bmi.bmiHeader.biBitCount = pBitmap->GetBPP(); bmi.bmiHeader.biHeight = -height; @@ -1188,12 +1177,12 @@ bool CGdiDisplayDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer(), &bmi, DIB_RGB_COLORS) == height; } else { - CFX_DIBitmap bitmap; - if (bitmap.Create(width, height, FXDIB_Rgb)) { + auto bitmap = pdfium::MakeRetain(); + if (bitmap->Create(width, height, FXDIB_Rgb)) { bmi.bmiHeader.biBitCount = 24; - ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap.GetBuffer(), &bmi, + ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap->GetBuffer(), &bmi, DIB_RGB_COLORS); - ret = pBitmap->TransferBitmap(0, 0, width, height, &bitmap, 0, 0); + ret = pBitmap->TransferBitmap(0, 0, width, height, bitmap, 0, 0); } else { ret = false; } @@ -1206,7 +1195,7 @@ bool CGdiDisplayDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { return ret; } -bool CGdiDisplayDriver::SetDIBits(const CFX_DIBSource* pSource, +bool CGdiDisplayDriver::SetDIBits(const RetainPtr& pSource, uint32_t color, const FX_RECT* pSrcRect, int left, @@ -1217,17 +1206,15 @@ bool CGdiDisplayDriver::SetDIBits(const CFX_DIBSource* pSource, int width = pSource->GetWidth(), height = pSource->GetHeight(); int alpha = FXARGB_A(color); if (pSource->GetBPP() != 1 || alpha != 255) { - CFX_DIBitmap background; - if (!background.Create(width, height, FXDIB_Rgb32) || - !GetDIBits(&background, left, top) || - !background.CompositeMask(0, 0, width, height, pSource, color, 0, 0, - FXDIB_BLEND_NORMAL, nullptr, false, 0, - nullptr)) { + auto background = pdfium::MakeRetain(); + if (!background->Create(width, height, FXDIB_Rgb32) || + !GetDIBits(background, left, top) || + !background->CompositeMask(0, 0, width, height, pSource, color, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, false, 0)) { return false; } FX_RECT src_rect(0, 0, width, height); - return SetDIBits(&background, 0, &src_rect, left, top, - FXDIB_BLEND_NORMAL); + return SetDIBits(background, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL); } FX_RECT clip_rect(left, top, left + pSrcRect->Width(), top + pSrcRect->Height()); @@ -1237,32 +1224,33 @@ bool CGdiDisplayDriver::SetDIBits(const CFX_DIBSource* pSource, } int width = pSrcRect->Width(), height = pSrcRect->Height(); if (pSource->HasAlpha()) { - CFX_DIBitmap bitmap; - if (!bitmap.Create(width, height, FXDIB_Rgb) || - !GetDIBits(&bitmap, left, top) || - !bitmap.CompositeBitmap(0, 0, width, height, pSource, pSrcRect->left, - pSrcRect->top, FXDIB_BLEND_NORMAL, nullptr, - false, nullptr)) { + auto bitmap = pdfium::MakeRetain(); + if (!bitmap->Create(width, height, FXDIB_Rgb) || + !GetDIBits(bitmap, left, top) || + !bitmap->CompositeBitmap(0, 0, width, height, pSource, pSrcRect->left, + pSrcRect->top, FXDIB_BLEND_NORMAL, nullptr, + false)) { return false; } FX_RECT src_rect(0, 0, width, height); - return SetDIBits(&bitmap, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL); + return SetDIBits(bitmap, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL); } CFX_DIBExtractor temp(pSource); - CFX_DIBitmap* pBitmap = temp.GetBitmap(); + RetainPtr pBitmap = temp.GetBitmap(); if (!pBitmap) return false; return GDI_SetDIBits(pBitmap, pSrcRect, left, top); } -bool CGdiDisplayDriver::UseFoxitStretchEngine(const CFX_DIBSource* pSource, - uint32_t color, - int dest_left, - int dest_top, - int dest_width, - int dest_height, - const FX_RECT* pClipRect, - int render_flags) { +bool CGdiDisplayDriver::UseFoxitStretchEngine( + const RetainPtr& pSource, + uint32_t color, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + const FX_RECT* pClipRect, + int render_flags) { FX_RECT bitmap_clip = *pClipRect; if (dest_width < 0) dest_left += dest_width; @@ -1271,17 +1259,17 @@ bool CGdiDisplayDriver::UseFoxitStretchEngine(const CFX_DIBSource* pSource, dest_top += dest_height; bitmap_clip.Offset(-dest_left, -dest_top); - std::unique_ptr pStretched( - pSource->StretchTo(dest_width, dest_height, render_flags, &bitmap_clip)); + RetainPtr pStretched = + pSource->StretchTo(dest_width, dest_height, render_flags, &bitmap_clip); if (!pStretched) return true; FX_RECT src_rect(0, 0, pStretched->GetWidth(), pStretched->GetHeight()); - return SetDIBits(pStretched.get(), color, &src_rect, pClipRect->left, + return SetDIBits(pStretched, color, &src_rect, pClipRect->left, pClipRect->top, FXDIB_BLEND_NORMAL); } -bool CGdiDisplayDriver::StretchDIBits(const CFX_DIBSource* pSource, +bool CGdiDisplayDriver::StretchDIBits(const RetainPtr& pSource, uint32_t color, int dest_left, int dest_top, @@ -1306,24 +1294,23 @@ bool CGdiDisplayDriver::StretchDIBits(const CFX_DIBSource* pSource, clip_rect.Intersect(*pClipRect); clip_rect.Offset(-image_rect.left, -image_rect.top); int clip_width = clip_rect.Width(), clip_height = clip_rect.Height(); - std::unique_ptr pStretched( + RetainPtr pStretched( pSource->StretchTo(dest_width, dest_height, flags, &clip_rect)); if (!pStretched) return true; - CFX_DIBitmap background; - if (!background.Create(clip_width, clip_height, FXDIB_Rgb32) || - !GetDIBits(&background, image_rect.left + clip_rect.left, + auto background = pdfium::MakeRetain(); + if (!background->Create(clip_width, clip_height, FXDIB_Rgb32) || + !GetDIBits(background, image_rect.left + clip_rect.left, image_rect.top + clip_rect.top) || - !background.CompositeMask( - 0, 0, clip_width, clip_height, pStretched.get(), color, 0, 0, - FXDIB_BLEND_NORMAL, nullptr, false, 0, nullptr)) { + !background->CompositeMask(0, 0, clip_width, clip_height, pStretched, + color, 0, 0, FXDIB_BLEND_NORMAL, nullptr, + false, 0)) { return false; } FX_RECT src_rect(0, 0, clip_width, clip_height); - return SetDIBits(&background, 0, &src_rect, - image_rect.left + clip_rect.left, + return SetDIBits(background, 0, &src_rect, image_rect.left + clip_rect.left, image_rect.top + clip_rect.top, FXDIB_BLEND_NORMAL); } if (pSource->HasAlpha()) { @@ -1331,7 +1318,7 @@ bool CGdiDisplayDriver::StretchDIBits(const CFX_DIBSource* pSource, (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); if (pPlatform->m_GdiplusExt.IsAvailable() && !pSource->IsCmykImage()) { CFX_DIBExtractor temp(pSource); - CFX_DIBitmap* pBitmap = temp.GetBitmap(); + RetainPtr pBitmap = temp.GetBitmap(); if (!pBitmap) return false; return pPlatform->m_GdiplusExt.StretchDIBits( @@ -1342,47 +1329,48 @@ bool CGdiDisplayDriver::StretchDIBits(const CFX_DIBSource* pSource, dest_width, dest_height, pClipRect, flags); } CFX_DIBExtractor temp(pSource); - CFX_DIBitmap* pBitmap = temp.GetBitmap(); + RetainPtr pBitmap = temp.GetBitmap(); if (!pBitmap) return false; return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width, dest_height, flags); } -bool CGdiDisplayDriver::StartDIBits(const CFX_DIBSource* pBitmap, +bool CGdiDisplayDriver::StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t render_flags, - void*& handle, + std::unique_ptr* handle, int blend_type) { return false; } -CFX_WindowsDevice::CFX_WindowsDevice(HDC hDC) { +CFX_WindowsRenderDevice::CFX_WindowsRenderDevice(HDC hDC) { SetDeviceDriver(pdfium::WrapUnique(CreateDriver(hDC))); } -CFX_WindowsDevice::~CFX_WindowsDevice() {} - -HDC CFX_WindowsDevice::GetDC() const { - IFX_RenderDeviceDriver* pRDD = GetDeviceDriver(); - return pRDD ? reinterpret_cast(pRDD->GetPlatformSurface()) : nullptr; -} +CFX_WindowsRenderDevice::~CFX_WindowsRenderDevice() {} // static -IFX_RenderDeviceDriver* CFX_WindowsDevice::CreateDriver(HDC hDC) { +IFX_RenderDeviceDriver* CFX_WindowsRenderDevice::CreateDriver(HDC hDC) { int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY); int obj_type = ::GetObjectType(hDC); bool use_printer = device_type == DT_RASPRINTER || - device_type == DT_PLOTTER || obj_type == OBJ_ENHMETADC; + device_type == DT_PLOTTER || + device_type == DT_CHARSTREAM || obj_type == OBJ_ENHMETADC; if (!use_printer) return new CGdiDisplayDriver(hDC); - if (g_pdfium_print_postscript_level == 2 || - g_pdfium_print_postscript_level == 3) { - return new CPSPrinterDriver(hDC, g_pdfium_print_postscript_level, false); - } - return new CGdiPrinterDriver(hDC); + if (g_pdfium_print_mode == WindowsPrintMode::kModeEmf) + return new CGdiPrinterDriver(hDC); + + if (g_pdfium_print_mode == WindowsPrintMode::kModeTextOnly) + return new CTextOnlyPrinterDriver(hDC); + + // Should be PostScript + ASSERT(g_pdfium_print_mode == WindowsPrintMode::kModePostScript2 || + g_pdfium_print_mode == WindowsPrintMode::kModePostScript3); + return new CPSPrinterDriver(hDC, g_pdfium_print_mode, false); } diff --git a/core/fxge/win32/fx_win32_dib.cpp b/core/fxge/win32/fx_win32_dib.cpp index 40c9ca6e311194e2f238e45f6e779b705873a59d..6416b5af3684ca72c614e638b74302a4452294b4 100644 --- a/core/fxge/win32/fx_win32_dib.cpp +++ b/core/fxge/win32/fx_win32_dib.cpp @@ -11,14 +11,15 @@ #include "core/fxge/win32/cfx_windowsdib.h" #include "core/fxge/win32/win32_int.h" -CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) { - CFX_ByteString result; +ByteString CFX_WindowsDIB::GetBitmapInfo( + const RetainPtr& pBitmap) { + ByteString result; int len = sizeof(BITMAPINFOHEADER); if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) { len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP()); } BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)result.GetBuffer(len); - FXSYS_memset(pbmih, 0, sizeof(BITMAPINFOHEADER)); + memset(pbmih, 0, sizeof(BITMAPINFOHEADER)); pbmih->biSize = sizeof(BITMAPINFOHEADER); pbmih->biBitCount = pBitmap->GetBPP(); pbmih->biCompression = BI_RGB; @@ -51,9 +52,9 @@ CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) { return result; } -CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, - LPVOID pData, - bool bAlpha) { +RetainPtr _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, + LPVOID pData, + bool bAlpha) { int width = pbmi->bmiHeader.biWidth; int height = pbmi->bmiHeader.biHeight; BOOL bBottomUp = true; @@ -62,24 +63,22 @@ CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, bBottomUp = false; } int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4; - CFX_DIBitmap* pBitmap = new CFX_DIBitmap; + auto pBitmap = pdfium::MakeRetain(); FXDIB_Format format = bAlpha ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200) : (FXDIB_Format)pbmi->bmiHeader.biBitCount; - bool ret = pBitmap->Create(width, height, format); - if (!ret) { - delete pBitmap; + if (!pBitmap->Create(width, height, format)) return nullptr; - } - FXSYS_memcpy(pBitmap->GetBuffer(), pData, pitch * height); + + memcpy(pBitmap->GetBuffer(), pData, pitch * height); if (bBottomUp) { uint8_t* temp_buf = FX_Alloc(uint8_t, pitch); int top = 0, bottom = height - 1; while (top < bottom) { - FXSYS_memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch); - FXSYS_memcpy(pBitmap->GetBuffer() + top * pitch, - pBitmap->GetBuffer() + bottom * pitch, pitch); - FXSYS_memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch); + memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch); + memcpy(pBitmap->GetBuffer() + top * pitch, + pBitmap->GetBuffer() + bottom * pitch, pitch); + memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch); top++; bottom--; } @@ -87,23 +86,23 @@ CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, temp_buf = nullptr; } if (pbmi->bmiHeader.biBitCount == 1) { - for (int i = 0; i < 2; i++) { - pBitmap->SetPaletteEntry(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000); - } + for (int i = 0; i < 2; i++) + pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000); } else if (pbmi->bmiHeader.biBitCount == 8) { - for (int i = 0; i < 256; i++) { - pBitmap->SetPaletteEntry(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000); - } + for (int i = 0; i < 256; i++) + pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000); } return pBitmap; } -CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) { +RetainPtr CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, + LPVOID pData) { return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, false); } -HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) { - CFX_ByteString info = GetBitmapInfo(pBitmap); +HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr& pBitmap, + HDC hDC) { + ByteString info = GetBitmapInfo(pBitmap); return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT, pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); @@ -116,7 +115,7 @@ void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) { h = bmp.bmHeight; } -CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) { +RetainPtr CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) { CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); if (pPlatform->m_GdiplusExt.IsAvailable()) { @@ -131,30 +130,28 @@ CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) { return nullptr; } HDC hDC = CreateCompatibleDC(nullptr); - int width, height; + int width; + int height; GetBitmapSize(hBitmap, width, height); - CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; + auto pDIBitmap = pdfium::MakeRetain(); if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { - delete pDIBitmap; DeleteDC(hDC); return nullptr; } - CFX_ByteString info = GetBitmapInfo(pDIBitmap); + ByteString info = GetBitmapInfo(pDIBitmap); int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); - if (!ret) { - delete pDIBitmap; - pDIBitmap = nullptr; - } DeleteDC(hDC); + if (!ret) + return nullptr; return pDIBitmap; } -CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_CHAR* filename) { - return LoadFromFile(CFX_WideString::FromLocal(filename).c_str()); +RetainPtr CFX_WindowsDIB::LoadFromFile(const char* filename) { + return LoadFromFile(WideString::FromLocal(filename).c_str()); } -CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) { +RetainPtr CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) { CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); if (pPlatform->m_GdiplusExt.IsAvailable()) { @@ -171,34 +168,33 @@ CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) { HDC hDC = CreateCompatibleDC(nullptr); int width, height; GetBitmapSize(hBitmap, width, height); - CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; + auto pDIBitmap = pdfium::MakeRetain(); if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { - delete pDIBitmap; DeleteDC(hDC); return nullptr; } - CFX_ByteString info = GetBitmapInfo(pDIBitmap); + ByteString info = GetBitmapInfo(pDIBitmap); int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); - if (!ret) { - delete pDIBitmap; - pDIBitmap = nullptr; - } DeleteDC(hDC); + if (!ret) + return nullptr; return pDIBitmap; } CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) { Create(width, height, FXDIB_Rgb, (uint8_t*)1); BITMAPINFOHEADER bmih; - FXSYS_memset(&bmih, 0, sizeof bmih); + memset(&bmih, 0, sizeof bmih); bmih.biSize = sizeof bmih; bmih.biBitCount = 24; bmih.biHeight = -height; bmih.biPlanes = 1; bmih.biWidth = width; - m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, - (LPVOID*)&m_pBuffer, nullptr, 0); + LPVOID pData = nullptr; + m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pData, + nullptr, 0); + m_pBuffer.Reset(static_cast(pData)); m_hMemDC = CreateCompatibleDC(hDC); m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap); } diff --git a/core/fxge/win32/fx_win32_dwrite.cpp b/core/fxge/win32/fx_win32_dwrite.cpp index dc0f5ed7459f3fbac418e896186980e8b4b7e2e4..4d4f45f947ad9bad8c13edc870f6ebf8064d174e 100644 --- a/core/fxge/win32/fx_win32_dwrite.cpp +++ b/core/fxge/win32/fx_win32_dwrite.cpp @@ -7,7 +7,7 @@ #include #include "core/fxcrt/fx_system.h" -#include "core/fxge/ge/cfx_cliprgn.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/win32/dwrite_int.h" typedef HRESULT(__stdcall* FuncType_DWriteCreateFactory)( @@ -103,7 +103,7 @@ class CDwFontContext { class CDwGdiTextRenderer { public: - CDwGdiTextRenderer(CFX_DIBitmap* pBitmap, + CDwGdiTextRenderer(const RetainPtr& pBitmap, IDWriteBitmapRenderTarget* bitmapRenderTarget, IDWriteRenderingParams* renderingParams); ~CDwGdiTextRenderer(); @@ -118,7 +118,7 @@ class CDwGdiTextRenderer { const COLORREF& textColor); private: - CFX_DIBitmap* pBitmap_; + RetainPtr pBitmap_; IDWriteBitmapRenderTarget* pRenderTarget_; IDWriteRenderingParams* pRenderingParams_; }; @@ -180,7 +180,7 @@ failed: return nullptr; } -bool CDWriteExt::DwCreateRenderingTarget(CFX_DIBitmap* pBitmap, +bool CDWriteExt::DwCreateRenderingTarget(const RetainPtr& pBitmap, void** renderTarget) { if (pBitmap->GetFormat() > FXDIB_Argb) { return false; @@ -227,14 +227,14 @@ bool CDWriteExt::DwRendingString(void* renderTarget, FX_RECT& stringRect, CFX_Matrix* pMatrix, void* font, - FX_FLOAT font_size, + float font_size, FX_ARGB text_color, int glyph_count, unsigned short* glyph_indices, - FX_FLOAT baselineOriginX, - FX_FLOAT baselineOriginY, + float baselineOriginX, + float baselineOriginY, void* glyph_offsets, - FX_FLOAT* glyph_advances) { + float* glyph_advances) { if (!renderTarget) { return true; } @@ -395,7 +395,7 @@ HRESULT CDwFontContext::Initialize() { } CDwGdiTextRenderer::CDwGdiTextRenderer( - CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, IDWriteBitmapRenderTarget* bitmapRenderTarget, IDWriteRenderingParams* renderingParams) : pBitmap_(pBitmap), @@ -426,13 +426,13 @@ STDMETHODIMP CDwGdiTextRenderer::DrawGlyphRun( HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC, OBJ_BITMAP); BITMAP bitmap; GetObject(hBitmap, sizeof bitmap, &bitmap); - CFX_DIBitmap dib; - dib.Create(bitmap.bmWidth, bitmap.bmHeight, - bitmap.bmBitsPixel == 24 ? FXDIB_Rgb : FXDIB_Rgb32, - (uint8_t*)bitmap.bmBits); - dib.CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), - text_bbox.Height(), pBitmap_, text_bbox.left, - text_bbox.top, FXDIB_BLEND_NORMAL, nullptr); + auto dib = pdfium::MakeRetain(); + dib->Create(bitmap.bmWidth, bitmap.bmHeight, + bitmap.bmBitsPixel == 24 ? FXDIB_Rgb : FXDIB_Rgb32, + (uint8_t*)bitmap.bmBits); + dib->CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), + text_bbox.Height(), pBitmap_, text_bbox.left, + text_bbox.top, FXDIB_BLEND_NORMAL, nullptr); hr = pRenderTarget_->DrawGlyphRun(baselineOriginX, baselineOriginY, measuringMode, glyphRun, pRenderingParams_, textColor); @@ -440,7 +440,7 @@ STDMETHODIMP CDwGdiTextRenderer::DrawGlyphRun( return hr; } pBitmap_->CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), - text_bbox.Height(), &dib, text_bbox.left, + text_bbox.Height(), dib, text_bbox.left, text_bbox.top, FXDIB_BLEND_NORMAL, pClipRgn); return hr; } diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp index 1be2a54b18f4e3b35f452472bfd5f80c7bc07a99..a617036ea7a35a5e1ead5a6b27e338cc32a4d92f 100644 --- a/core/fxge/win32/fx_win32_gdipext.cpp +++ b/core/fxge/win32/fx_win32_gdipext.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "core/fxcrt/fx_system.h" #include "core/fxge/cfx_gemodule.h" @@ -25,8 +26,65 @@ using std::max; #include // NOLINT -using namespace Gdiplus; // NOLINT -using namespace Gdiplus::DllExports; // NOLINT +// TODO(thestig): Remove the infrequently used ones. +using Gdiplus::CombineMode; +using Gdiplus::DashCap; +using Gdiplus::DashCapFlat; +using Gdiplus::DashCapRound; +using Gdiplus::FillModeAlternate; +using Gdiplus::FillModeWinding; +using Gdiplus::GdiplusStartupInput; +using Gdiplus::GdiplusStartupOutput; +using Gdiplus::GpBitmap; +using Gdiplus::GpBrush; +using Gdiplus::GpDashCap; +using Gdiplus::GpDashStyle; +using Gdiplus::GpFillMode; +using Gdiplus::GpFont; +using Gdiplus::GpFontCollection; +using Gdiplus::GpFontFamily; +using Gdiplus::GpGraphics; +using Gdiplus::GpImage; +using Gdiplus::GpLineCap; +using Gdiplus::GpLineJoin; +using Gdiplus::GpMatrix; +using Gdiplus::GpPath; +using Gdiplus::GpPen; +using Gdiplus::GpPoint; +using Gdiplus::GpPointF; +using Gdiplus::GpRect; +using Gdiplus::GpRegion; +using Gdiplus::GpSolidFill; +using Gdiplus::GpStatus; +using Gdiplus::GpStringFormat; +using Gdiplus::GpUnit; +using Gdiplus::ImageLockModeRead; +using Gdiplus::InterpolationMode; +using Gdiplus::InterpolationModeBilinear; +using Gdiplus::InterpolationModeHighQuality; +using Gdiplus::InterpolationModeNearestNeighbor; +using Gdiplus::LineCap; +using Gdiplus::LineCapFlat; +using Gdiplus::LineCapRound; +using Gdiplus::LineCapSquare; +using Gdiplus::LineJoin; +using Gdiplus::LineJoinBevel; +using Gdiplus::LineJoinMiterClipped; +using Gdiplus::LineJoinRound; +using Gdiplus::PaletteFlagsHasAlpha; +using Gdiplus::PathPointTypeBezier; +using Gdiplus::PathPointTypeCloseSubpath; +using Gdiplus::PathPointTypeLine; +using Gdiplus::PathPointTypeStart; +using Gdiplus::PixelOffsetMode; +using Gdiplus::PixelOffsetModeHalf; +using Gdiplus::REAL; +using Gdiplus::SmoothingMode; +using Gdiplus::SmoothingModeAntiAlias; +using Gdiplus::SmoothingModeNone; +using Gdiplus::TextRenderingHint; +using Gdiplus::UnitPixel; +using Gdiplus::UnitWorld; #define GdiFillType2Gdip(fill_type) \ (fill_type == ALTERNATE ? FillModeAlternate : FillModeWinding) @@ -111,6 +169,7 @@ enum { FuncId_GdipDrawString, FuncId_GdipSetPenTransform, }; + static LPCSTR g_GdipFuncNames[] = { "GdipCreatePath2", "GdipSetPenDashStyle", @@ -191,6 +250,10 @@ static LPCSTR g_GdipFuncNames[] = { "GdipDrawString", "GdipSetPenTransform", }; +static_assert(FX_ArraySize(g_GdipFuncNames) == + static_cast(FuncId_GdipSetPenTransform) + 1, + "g_GdipFuncNames has wrong size"); + typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePath2)(GDIPCONST GpPointF*, GDIPCONST BYTE*, INT, @@ -215,13 +278,13 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPageUnit)(GpGraphics* graphics, typedef GpStatus(WINGDIPAPI* FuncType_GdipSetSmoothingMode)( GpGraphics* graphics, SmoothingMode smoothingMode); -typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateSolidFill)(ARGB color, +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateSolidFill)(Gdiplus::ARGB color, GpSolidFill** brush); typedef GpStatus(WINGDIPAPI* FuncType_GdipFillPath)(GpGraphics* graphics, GpBrush* brush, GpPath* path); typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteBrush)(GpBrush* brush); -typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePen1)(ARGB color, +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePen1)(Gdiplus::ARGB color, REAL width, GpUnit unit, GpPen** pen); @@ -245,22 +308,22 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageHeight)(GpImage* image, UINT* height); typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePixelFormat)( GpImage* image, - PixelFormat* format); + Gdiplus::PixelFormat* format); typedef GpStatus(WINGDIPAPI* FuncType_GdipBitmapLockBits)( GpBitmap* bitmap, GDIPCONST GpRect* rect, UINT flags, - PixelFormat format, - BitmapData* lockedBitmapData); + Gdiplus::PixelFormat format, + Gdiplus::BitmapData* lockedBitmapData); typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePalette)( GpImage* image, - ColorPalette* palette, + Gdiplus::ColorPalette* palette, INT size); typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePaletteSize)(GpImage* image, INT* size); typedef GpStatus(WINGDIPAPI* FuncType_GdipBitmapUnlockBits)( GpBitmap* bitmap, - BitmapData* lockedBitmapData); + Gdiplus::BitmapData* lockedBitmapData); typedef GpStatus(WINGDIPAPI* FuncType_GdipDisposeImage)(GpImage* image); typedef GpStatus(WINGDIPAPI* FuncType_GdipFillRectangle)(GpGraphics* graphics, GpBrush* brush, @@ -272,12 +335,12 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromScan0)( INT width, INT height, INT stride, - PixelFormat format, + Gdiplus::PixelFormat format, BYTE* scan0, GpBitmap** bitmap); typedef GpStatus(WINGDIPAPI* FuncType_GdipSetImagePalette)( GpImage* image, - GDIPCONST ColorPalette* palette); + GDIPCONST Gdiplus::ColorPalette* palette); typedef GpStatus(WINGDIPAPI* FuncType_GdipSetInterpolationMode)( GpGraphics* graphics, InterpolationMode interpolationMode); @@ -290,7 +353,7 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromGdiDib)( GDIPCONST BITMAPINFO* gdiBitmapInfo, VOID* gdiBitmapData, GpBitmap** bitmap); -typedef Status(WINAPI* FuncType_GdiplusStartup)( +typedef Gdiplus::Status(WINAPI* FuncType_GdiplusStartup)( OUT uintptr_t* token, const GdiplusStartupInput* input, OUT GdiplusStartupOutput* output); @@ -354,7 +417,7 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFont)( GDIPCONST GpFontFamily* fontFamily, REAL emSize, INT style, - Unit unit, + Gdiplus::Unit unit, GpFont** font); typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontSize)(GpFont* font, REAL* size); @@ -371,7 +434,7 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawDriverString)( INT length, GDIPCONST GpFont* font, GDIPCONST GpBrush* brush, - GDIPCONST PointF* positions, + GDIPCONST Gdiplus::PointF* positions, INT flags, GDIPCONST GpMatrix* matrix); typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateMatrix2)(REAL m11, @@ -429,7 +492,7 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawString)( GDIPCONST WCHAR* str, INT length, GDIPCONST GpFont* font, - GDIPCONST RectF* layoutRect, + GDIPCONST Gdiplus::RectF* layoutRect, GDIPCONST GpStringFormat* stringFormat, GDIPCONST GpBrush* brush); typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenTransform)(GpPen* pen, @@ -457,14 +520,14 @@ static GpBrush* _GdipCreateBrush(DWORD argb) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; GpSolidFill* solidBrush = nullptr; - CallFunc(GdipCreateSolidFill)((ARGB)argb, &solidBrush); + CallFunc(GdipCreateSolidFill)((Gdiplus::ARGB)argb, &solidBrush); return solidBrush; } -static std::unique_ptr StretchMonoToGray( +static RetainPtr StretchMonoToGray( int dest_width, int dest_height, - const CFX_DIBitmap* pSource, + const RetainPtr& pSource, FX_RECT* pClipRect) { bool bFlipX = dest_width < 0; if (bFlipX) @@ -477,7 +540,7 @@ static std::unique_ptr StretchMonoToGray( int result_width = pClipRect->Width(); int result_height = pClipRect->Height(); int result_pitch = (result_width + 3) / 4 * 4; - auto pStretched = pdfium::MakeUnique(); + auto pStretched = pdfium::MakeRetain(); if (!pStretched->Create(result_width, result_height, FXDIB_8bppRgb)) return nullptr; @@ -518,7 +581,7 @@ static std::unique_ptr StretchMonoToGray( static void OutputImageMask(GpGraphics* pGraphics, BOOL bMonoDevice, - const CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, @@ -532,11 +595,11 @@ static void OutputImageMask(GpGraphics* pGraphics, int src_pitch = pBitmap->GetPitch(); uint8_t* scan0 = pBitmap->GetBuffer(); if (src_width == 1 && src_height == 1) { - if ((scan0[0] & 0x80) == 0) { + if ((scan0[0] & 0x80) == 0) return; - } + GpSolidFill* solidBrush; - CallFunc(GdipCreateSolidFill)((ARGB)argb, &solidBrush); + CallFunc(GdipCreateSolidFill)((Gdiplus::ARGB)argb, &solidBrush); if (dest_width < 0) { dest_width = -dest_width; dest_left -= dest_width; @@ -558,11 +621,11 @@ static void OutputImageMask(GpGraphics* pGraphics, image_rect.Normalize(); FX_RECT image_clip = image_rect; image_clip.Intersect(*pClipRect); - if (image_clip.IsEmpty()) { + if (image_clip.IsEmpty()) return; - } + image_clip.Offset(-image_rect.left, -image_rect.top); - std::unique_ptr pStretched; + RetainPtr pStretched; if (src_width * src_height > 10000) { pStretched = StretchMonoToGray(dest_width, dest_height, pBitmap, &image_clip); @@ -575,15 +638,18 @@ static void OutputImageMask(GpGraphics* pGraphics, (image_clip.Width() + 3) / 4 * 4, PixelFormat8bppIndexed, pStretched->GetBuffer(), &bitmap); - int a, r, g, b; - ArgbDecode(argb, a, r, g, b); + int a; + int r; + int g; + int b; + std::tie(a, r, g, b) = ArgbDecode(argb); UINT pal[258]; pal[0] = 0; pal[1] = 256; for (int i = 0; i < 256; i++) { pal[i + 2] = ArgbEncode(i * a / 255, r, g, b); } - CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)pal); + CallFunc(GdipSetImagePalette)(bitmap, (Gdiplus::ColorPalette*)pal); CallFunc(GdipDrawImageI)(pGraphics, bitmap, image_rect.left + image_clip.left, image_rect.top + image_clip.top); @@ -594,15 +660,16 @@ static void OutputImageMask(GpGraphics* pGraphics, CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, PixelFormat1bppIndexed, scan0, &bitmap); UINT palette[4] = {PaletteFlagsHasAlpha, 2, 0, argb}; - CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)palette); - Point destinationPoints[] = {Point(dest_left, dest_top), - Point(dest_left + dest_width, dest_top), - Point(dest_left, dest_top + dest_height)}; + CallFunc(GdipSetImagePalette)(bitmap, (Gdiplus::ColorPalette*)palette); + Gdiplus::Point destinationPoints[] = { + Gdiplus::Point(dest_left, dest_top), + Gdiplus::Point(dest_left + dest_width, dest_top), + Gdiplus::Point(dest_left, dest_top + dest_height)}; CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); CallFunc(GdipDisposeImage)(bitmap); } static void OutputImage(GpGraphics* pGraphics, - const CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, const FX_RECT* pSrcRect, int dest_left, int dest_top, @@ -613,11 +680,11 @@ static void OutputImage(GpGraphics* pGraphics, ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; if (pBitmap->GetBPP() == 1 && (pSrcRect->left % 8)) { FX_RECT new_rect(0, 0, src_width, src_height); - std::unique_ptr pCloned = pBitmap->Clone(pSrcRect); + RetainPtr pCloned = pBitmap->Clone(pSrcRect); if (!pCloned) return; - OutputImage(pGraphics, pCloned.get(), &new_rect, dest_left, dest_top, - dest_width, dest_height); + OutputImage(pGraphics, pCloned, &new_rect, dest_left, dest_top, dest_width, + dest_height); return; } int src_pitch = pBitmap->GetPitch(); @@ -644,10 +711,9 @@ static void OutputImage(GpGraphics* pGraphics, UINT pal[258]; pal[0] = 0; pal[1] = 256; - for (int i = 0; i < 256; i++) { - pal[i + 2] = pBitmap->GetPaletteEntry(i); - } - CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)pal); + for (int i = 0; i < 256; i++) + pal[i + 2] = pBitmap->GetPaletteArgb(i); + CallFunc(GdipSetImagePalette)(bitmap, (Gdiplus::ColorPalette*)pal); break; } case FXDIB_1bppRgb: { @@ -663,47 +729,47 @@ static void OutputImage(GpGraphics* pGraphics, if (dest_width < 0) { dest_width--; } - Point destinationPoints[] = {Point(dest_left, dest_top), - Point(dest_left + dest_width, dest_top), - Point(dest_left, dest_top + dest_height)}; + Gdiplus::Point destinationPoints[] = { + Gdiplus::Point(dest_left, dest_top), + Gdiplus::Point(dest_left + dest_width, dest_top), + Gdiplus::Point(dest_left, dest_top + dest_height)}; CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); CallFunc(GdipDisposeImage)(bitmap); } -CGdiplusExt::CGdiplusExt() { - m_hModule = nullptr; - m_GdiModule = nullptr; - for (size_t i = 0; i < sizeof g_GdipFuncNames / sizeof(LPCSTR); i++) { - m_Functions[i] = nullptr; - } - m_pGdiAddFontMemResourceEx = nullptr; - m_pGdiRemoveFontMemResourseEx = nullptr; + +CGdiplusExt::CGdiplusExt() {} + +CGdiplusExt::~CGdiplusExt() { + FreeLibrary(m_GdiModule); + FreeLibrary(m_hModule); } + void CGdiplusExt::Load() { - CFX_ByteString strPlusPath = ""; - FX_CHAR buf[MAX_PATH]; + char buf[MAX_PATH]; GetSystemDirectoryA(buf, MAX_PATH); - strPlusPath += buf; - strPlusPath += "\\"; - strPlusPath += "GDIPLUS.DLL"; - m_hModule = LoadLibraryA(strPlusPath.c_str()); - if (!m_hModule) { + ByteString dllpath = buf; + dllpath += "\\GDIPLUS.DLL"; + m_hModule = LoadLibraryA(dllpath.c_str()); + if (!m_hModule) return; - } - for (size_t i = 0; i < sizeof g_GdipFuncNames / sizeof(LPCSTR); i++) { + + m_Functions.resize(FX_ArraySize(g_GdipFuncNames)); + for (size_t i = 0; i < FX_ArraySize(g_GdipFuncNames); ++i) { m_Functions[i] = GetProcAddress(m_hModule, g_GdipFuncNames[i]); if (!m_Functions[i]) { m_hModule = nullptr; return; } } + uintptr_t gdiplusToken; GdiplusStartupInput gdiplusStartupInput; ((FuncType_GdiplusStartup)m_Functions[FuncId_GdiplusStartup])( &gdiplusToken, &gdiplusStartupInput, nullptr); m_GdiModule = LoadLibraryA("GDI32.DLL"); - if (!m_GdiModule) { + if (!m_GdiModule) return; - } + m_pGdiAddFontMemResourceEx = reinterpret_cast( GetProcAddress(m_GdiModule, "AddFontMemResourceEx")); @@ -711,7 +777,7 @@ void CGdiplusExt::Load() { reinterpret_cast( GetProcAddress(m_GdiModule, "RemoveFontMemResourceEx")); } -CGdiplusExt::~CGdiplusExt() {} + LPVOID CGdiplusExt::LoadMemFont(LPBYTE pData, uint32_t size) { GpFontCollection* pCollection = nullptr; CGdiplusExt& GdiplusExt = @@ -719,9 +785,9 @@ LPVOID CGdiplusExt::LoadMemFont(LPBYTE pData, uint32_t size) { CallFunc(GdipNewPrivateFontCollection)(&pCollection); GpStatus status = CallFunc(GdipPrivateAddMemoryFont)(pCollection, pData, size); - if (status == Ok) { + if (status == Gdiplus::Ok) return pCollection; - } + CallFunc(GdipDeletePrivateFontCollection)(&pCollection); return nullptr; } @@ -730,10 +796,11 @@ void CGdiplusExt::DeleteMemFont(LPVOID pCollection) { ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; CallFunc(GdipDeletePrivateFontCollection)((GpFontCollection**)&pCollection); } -bool CGdiplusExt::GdipCreateBitmap(CFX_DIBitmap* pBitmap, void** bitmap) { +bool CGdiplusExt::GdipCreateBitmap(const RetainPtr& pBitmap, + void** bitmap) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - PixelFormat format; + Gdiplus::PixelFormat format; switch (pBitmap->GetFormat()) { case FXDIB_Rgb: format = PixelFormat24bppRGB; @@ -750,22 +817,16 @@ bool CGdiplusExt::GdipCreateBitmap(CFX_DIBitmap* pBitmap, void** bitmap) { GpStatus status = CallFunc(GdipCreateBitmapFromScan0)( pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap->GetPitch(), format, pBitmap->GetBuffer(), (GpBitmap**)bitmap); - if (status == Ok) { - return true; - } - return false; + return status == Gdiplus::Ok; } bool CGdiplusExt::GdipCreateFromImage(void* bitmap, void** graphics) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; GpStatus status = CallFunc(GdipGetImageGraphicsContext)( (GpBitmap*)bitmap, (GpGraphics**)graphics); - if (status == Ok) { - return true; - } - return false; + return status == Gdiplus::Ok; } -bool CGdiplusExt::GdipCreateFontFamilyFromName(const FX_WCHAR* name, +bool CGdiplusExt::GdipCreateFontFamilyFromName(const wchar_t* name, void* pFontCollection, void** pFamily) { CGdiplusExt& GdiplusExt = @@ -773,13 +834,10 @@ bool CGdiplusExt::GdipCreateFontFamilyFromName(const FX_WCHAR* name, GpStatus status = CallFunc(GdipCreateFontFamilyFromName)( (GDIPCONST WCHAR*)name, (GpFontCollection*)pFontCollection, (GpFontFamily**)pFamily); - if (status == Ok) { - return true; - } - return false; + return status == Gdiplus::Ok; } bool CGdiplusExt::GdipCreateFontFromFamily(void* pFamily, - FX_FLOAT font_size, + float font_size, int fontstyle, int flag, void** pFont) { @@ -787,22 +845,15 @@ bool CGdiplusExt::GdipCreateFontFromFamily(void* pFamily, ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; GpStatus status = CallFunc(GdipCreateFont)((GpFontFamily*)pFamily, font_size, fontstyle, - Unit(flag), (GpFont**)pFont); - if (status == Ok) { - return true; - } - return false; + Gdiplus::Unit(flag), (GpFont**)pFont); + return status == Gdiplus::Ok; } -void CGdiplusExt::GdipGetFontSize(void* pFont, FX_FLOAT* size) { +void CGdiplusExt::GdipGetFontSize(void* pFont, float* size) { REAL get_size; CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - GpStatus status = CallFunc(GdipGetFontSize)((GpFont*)pFont, (REAL*)&get_size); - if (status == Ok) { - *size = (FX_FLOAT)get_size; - } else { - *size = 0; - } + GpStatus status = CallFunc(GdipGetFontSize)((GpFont*)pFont, &get_size); + *size = (status == Gdiplus::Ok) ? static_cast(get_size) : 0; } void CGdiplusExt::GdipSetTextRenderingHint(void* graphics, int mode) { CGdiplusExt& GdiplusExt = @@ -828,16 +879,15 @@ bool CGdiplusExt::GdipDrawDriverString(void* graphics, GpStatus status = CallFunc(GdipDrawDriverString)( (GpGraphics*)graphics, (GDIPCONST UINT16*)text, (INT)length, (GDIPCONST GpFont*)font, (GDIPCONST GpBrush*)brush, - (GDIPCONST PointF*)positions, (INT)flags, (GDIPCONST GpMatrix*)matrix); - if (status == Ok) { - return true; - } - return false; + (GDIPCONST Gdiplus::PointF*)positions, (INT)flags, + (GDIPCONST GpMatrix*)matrix); + return status == Gdiplus::Ok; } void CGdiplusExt::GdipCreateBrush(uint32_t fill_argb, void** pBrush) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - CallFunc(GdipCreateSolidFill)((ARGB)fill_argb, (GpSolidFill**)pBrush); + CallFunc(GdipCreateSolidFill)((Gdiplus::ARGB)fill_argb, + (GpSolidFill**)pBrush); } void CGdiplusExt::GdipDeleteBrush(void* pBrush) { CGdiplusExt& GdiplusExt = @@ -845,36 +895,36 @@ void CGdiplusExt::GdipDeleteBrush(void* pBrush) { CallFunc(GdipDeleteBrush)((GpSolidFill*)pBrush); } void* CGdiplusExt::GdipCreateFontFromCollection(void* pFontCollection, - FX_FLOAT font_size, + float font_size, int fontstyle) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; int numFamilies = 0; GpStatus status = CallFunc(GdipGetFontCollectionFamilyCount)( (GpFontCollection*)pFontCollection, &numFamilies); - if (status != Ok) { + if (status != Gdiplus::Ok) return nullptr; - } + GpFontFamily* family_list[1]; status = CallFunc(GdipGetFontCollectionFamilyList)( (GpFontCollection*)pFontCollection, 1, family_list, &numFamilies); - if (status != Ok) { + if (status != Gdiplus::Ok) return nullptr; - } + GpFont* pFont = nullptr; status = CallFunc(GdipCreateFont)(family_list[0], font_size, fontstyle, UnitPixel, &pFont); - if (status != Ok) { + if (status != Gdiplus::Ok) return nullptr; - } + return pFont; } -void CGdiplusExt::GdipCreateMatrix(FX_FLOAT a, - FX_FLOAT b, - FX_FLOAT c, - FX_FLOAT d, - FX_FLOAT e, - FX_FLOAT f, +void CGdiplusExt::GdipCreateMatrix(float a, + float b, + float c, + float d, + float e, + float f, void** matrix) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; @@ -912,7 +962,7 @@ void CGdiplusExt::GdipDeleteGraphics(void* graphics) { } bool CGdiplusExt::StretchBitMask(HDC hDC, BOOL bMonoDevice, - const CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, @@ -938,7 +988,7 @@ bool CGdiplusExt::StretchBitMask(HDC hDC, return true; } bool CGdiplusExt::StretchDIBits(HDC hDC, - const CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, @@ -972,17 +1022,16 @@ static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, bool bTextMode = false) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - FX_FLOAT width = pGraphState ? pGraphState->m_LineWidth : 1.0f; + float width = pGraphState ? pGraphState->m_LineWidth : 1.0f; if (!bTextMode) { - FX_FLOAT unit = - pMatrix ? 1.0f / ((pMatrix->GetXUnit() + pMatrix->GetYUnit()) / 2) - : 1.0f; - if (width < unit) { + float unit = pMatrix + ? 1.0f / ((pMatrix->GetXUnit() + pMatrix->GetYUnit()) / 2) + : 1.0f; + if (width < unit) width = unit; - } } GpPen* pPen = nullptr; - CallFunc(GdipCreatePen1)((ARGB)argb, width, UnitWorld, &pPen); + CallFunc(GdipCreatePen1)((Gdiplus::ARGB)argb, width, UnitWorld, &pPen); LineCap lineCap = LineCapFlat; DashCap dashCap = DashCapFlat; bool bDashExtend = false; @@ -1015,18 +1064,17 @@ static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, } CallFunc(GdipSetPenLineJoin)(pPen, lineJoin); if (pGraphState->m_DashCount) { - FX_FLOAT* pDashArray = FX_Alloc( - FX_FLOAT, pGraphState->m_DashCount + pGraphState->m_DashCount % 2); + float* pDashArray = FX_Alloc( + float, pGraphState->m_DashCount + pGraphState->m_DashCount % 2); int nCount = 0; - FX_FLOAT on_leftover = 0, off_leftover = 0; + float on_leftover = 0, off_leftover = 0; for (int i = 0; i < pGraphState->m_DashCount; i += 2) { - FX_FLOAT on_phase = pGraphState->m_DashArray[i]; - FX_FLOAT off_phase; - if (i == pGraphState->m_DashCount - 1) { + float on_phase = pGraphState->m_DashArray[i]; + float off_phase; + if (i == pGraphState->m_DashCount - 1) off_phase = on_phase; - } else { + else off_phase = pGraphState->m_DashArray[i + 1]; - } on_phase /= width; off_phase /= width; if (on_phase + off_phase <= 0.00002f) { @@ -1034,11 +1082,10 @@ static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, off_phase = 1.0f / 10; } if (bDashExtend) { - if (off_phase < 1) { + if (off_phase < 1) off_phase = 0; - } else { + else off_phase -= 1; - } on_phase += 1; } if (on_phase == 0 || off_phase == 0) { @@ -1057,13 +1104,12 @@ static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, } } CallFunc(GdipSetPenDashArray)(pPen, pDashArray, nCount); - FX_FLOAT phase = pGraphState->m_DashPhase; + float phase = pGraphState->m_DashPhase; if (bDashExtend) { - if (phase < 0.5f) { + if (phase < 0.5f) phase = 0; - } else { + else phase -= 0.5f; - } } CallFunc(GdipSetPenDashOffset)(pPen, phase); FX_Free(pDashArray); @@ -1072,7 +1118,7 @@ static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, CallFunc(GdipSetPenMiterLimit)(pPen, pGraphState->m_MiterLimit); return pPen; } -static bool IsSmallTriangle(PointF* points, +static bool IsSmallTriangle(Gdiplus::PointF* points, const CFX_Matrix* pMatrix, int& v1, int& v2) { @@ -1089,7 +1135,7 @@ static bool IsSmallTriangle(PointF* points, } CFX_PointF diff = p1 - p2; - FX_FLOAT distance_square = (diff.x * diff.x) + (diff.y * diff.y); + float distance_square = (diff.x * diff.x) + (diff.y * diff.y); if (distance_square < (1.0f * 2 + 1.0f / 4)) { v1 = i; v2 = pair1; @@ -1122,7 +1168,7 @@ bool CGdiplusExt::DrawPath(HDC hDC, pObject2Device->e, pObject2Device->f, &pMatrix); CallFunc(GdipSetWorldTransform)(pGraphics, pMatrix); } - PointF* points = FX_Alloc(PointF, pPoints.size()); + Gdiplus::PointF* points = FX_Alloc(Gdiplus::PointF, pPoints.size()); BYTE* types = FX_Alloc(BYTE, pPoints.size()); int nSubPathes = 0; bool bSubClose = false; @@ -1162,37 +1208,33 @@ bool CGdiplusExt::DrawPath(HDC hDC, continue; } if (!bSmooth && points[i].X != points[i - 1].X && - points[i].Y != points[i - 1].Y) { + points[i].Y != points[i - 1].Y) bSmooth = true; - } } else if (point_type == FXPT_TYPE::BezierTo) { types[i] = PathPointTypeBezier; bSmooth = true; } if (pPoints[i].m_CloseFigure) { - if (bSubClose) { + if (bSubClose) types[pos_subclose] &= ~PathPointTypeCloseSubpath; - } else { + else bSubClose = true; - } pos_subclose = i; types[i] |= PathPointTypeCloseSubpath; if (!bSmooth && points[i].X != points[startpoint].X && - points[i].Y != points[startpoint].Y) { + points[i].Y != points[startpoint].Y) bSmooth = true; - } } } if (fill_mode & FXFILL_NOPATHSMOOTH) { bSmooth = false; CallFunc(GdipSetSmoothingMode)(pGraphics, SmoothingModeNone); } else if (!(fill_mode & FXFILL_FULLCOVER)) { - if (!bSmooth && (fill_mode & 3)) { + if (!bSmooth && (fill_mode & 3)) bSmooth = true; - } - if (bSmooth || (pGraphState && pGraphState->m_LineWidth > 2)) { + + if (bSmooth || (pGraphState && pGraphState->m_LineWidth > 2)) CallFunc(GdipSetSmoothingMode)(pGraphics, SmoothingModeAntiAlias); - } } int new_fill_mode = fill_mode & 3; if (pPoints.size() == 4 && !pGraphState) { @@ -1246,9 +1288,8 @@ bool CGdiplusExt::DrawPath(HDC hDC, } CallFunc(GdipDeletePen)(pPen); } - if (pMatrix) { + if (pMatrix) CallFunc(GdipDeleteMatrix)(pMatrix); - } FX_Free(points); FX_Free(types); CallFunc(GdipDeletePath)(pGpPath); @@ -1283,39 +1324,36 @@ class GpStream final : public IStream { } // ISequentialStream - HRESULT STDMETHODCALLTYPE Read(void* Output, + HRESULT STDMETHODCALLTYPE Read(void* output, ULONG cb, ULONG* pcbRead) override { - size_t bytes_left; - size_t bytes_out; - if (pcbRead) { + if (pcbRead) *pcbRead = 0; - } - if (m_ReadPos == m_InterStream.GetLength()) { + + if (m_ReadPos >= m_InterStream.tellp()) return HRESULT_FROM_WIN32(ERROR_END_OF_MEDIA); - } - bytes_left = m_InterStream.GetLength() - m_ReadPos; - bytes_out = std::min(pdfium::base::checked_cast(cb), bytes_left); - FXSYS_memcpy(Output, m_InterStream.GetBuffer() + m_ReadPos, bytes_out); - m_ReadPos += (int32_t)bytes_out; - if (pcbRead) { + + size_t bytes_left = m_InterStream.tellp() - m_ReadPos; + size_t bytes_out = + std::min(pdfium::base::checked_cast(cb), bytes_left); + memcpy(output, m_InterStream.str().c_str() + m_ReadPos, bytes_out); + m_ReadPos += bytes_out; + if (pcbRead) *pcbRead = (ULONG)bytes_out; - } + return S_OK; } - HRESULT STDMETHODCALLTYPE Write(void const* Input, + HRESULT STDMETHODCALLTYPE Write(const void* input, ULONG cb, ULONG* pcbWritten) override { if (cb <= 0) { - if (pcbWritten) { + if (pcbWritten) *pcbWritten = 0; - } return S_OK; } - m_InterStream.InsertBlock(m_InterStream.GetLength(), Input, cb); - if (pcbWritten) { + m_InterStream.write(reinterpret_cast(input), cb); + if (pcbWritten) *pcbWritten = cb; - } return S_OK; } @@ -1347,8 +1385,8 @@ class GpStream final : public IStream { HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer) override { - long start = 0; - long new_read_position; + std::streamoff start; + std::streamoff new_read_position; switch (dwOrigin) { case STREAM_SEEK_SET: start = 0; @@ -1357,37 +1395,35 @@ class GpStream final : public IStream { start = m_ReadPos; break; case STREAM_SEEK_END: - start = m_InterStream.GetLength(); + start = m_InterStream.tellp(); break; default: return STG_E_INVALIDFUNCTION; - break; } - new_read_position = start + (long)liDistanceToMove.QuadPart; - if (new_read_position < 0 || - new_read_position > m_InterStream.GetLength()) { + new_read_position = start + liDistanceToMove.QuadPart; + if (new_read_position > m_InterStream.tellp()) return STG_E_SEEKERROR; - } + m_ReadPos = new_read_position; - if (lpNewFilePointer) { + if (lpNewFilePointer) lpNewFilePointer->QuadPart = m_ReadPos; - } + return S_OK; } HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag) override { - if (!pStatstg) { + if (!pStatstg) return STG_E_INVALIDFUNCTION; - } + ZeroMemory(pStatstg, sizeof(STATSTG)); - pStatstg->cbSize.QuadPart = m_InterStream.GetLength(); + pStatstg->cbSize.QuadPart = m_InterStream.tellp(); return S_OK; } private: LONG m_RefCount; - int m_ReadPos; - CFX_ByteTextBuf m_InterStream; + std::streamoff m_ReadPos; + std::ostringstream m_InterStream; }; typedef struct { @@ -1395,7 +1431,7 @@ typedef struct { int Stride; LPBYTE pScan0; GpBitmap* pBitmap; - BitmapData* pBitmapData; + Gdiplus::BitmapData* pBitmapData; GpStream* pStream; } PREVIEW3_DIBITMAP; @@ -1404,28 +1440,28 @@ static PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { GpStream* pStream = nullptr; CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - Status status = Ok; + Gdiplus::Status status = Gdiplus::Ok; if (args.flags == WINDIB_OPEN_PATHNAME) { status = CallFunc(GdipCreateBitmapFromFileICM)((wchar_t*)args.path_name, &pBitmap); } else { - if (args.memory_size == 0 || !args.memory_base) { + if (args.memory_size == 0 || !args.memory_base) return nullptr; - } + pStream = new GpStream; pStream->Write(args.memory_base, (ULONG)args.memory_size, nullptr); status = CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap); } - if (status != Ok) { - if (pStream) { + if (status != Gdiplus::Ok) { + if (pStream) pStream->Release(); - } + return nullptr; } UINT height, width; CallFunc(GdipGetImageHeight)(pBitmap, &height); CallFunc(GdipGetImageWidth)(pBitmap, &width); - PixelFormat pixel_format; + Gdiplus::PixelFormat pixel_format; CallFunc(GdipGetImagePixelFormat)(pBitmap, &pixel_format); int info_size = sizeof(BITMAPINFOHEADER); int bpp = 24; @@ -1449,8 +1485,8 @@ static PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { pbmih->biHeight = -(int)height; pbmih->biPlanes = 1; pbmih->biWidth = width; - Rect rect(0, 0, width, height); - BitmapData* pBitmapData = FX_Alloc(BitmapData, 1); + Gdiplus::Rect rect(0, 0, width, height); + Gdiplus::BitmapData* pBitmapData = FX_Alloc(Gdiplus::BitmapData, 1); CallFunc(GdipBitmapLockBits)(pBitmap, &rect, ImageLockModeRead, dest_pixel_format, pBitmapData); if (pixel_format == PixelFormat1bppIndexed || @@ -1463,7 +1499,7 @@ static PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { } pal; int size = 0; CallFunc(GdipGetImagePaletteSize)(pBitmap, &size); - CallFunc(GdipGetImagePalette)(pBitmap, (ColorPalette*)&pal, size); + CallFunc(GdipGetImagePalette)(pBitmap, (Gdiplus::ColorPalette*)&pal, size); int entries = pixel_format == PixelFormat1bppIndexed ? 2 : 256; for (int i = 0; i < entries; i++) { ppal[i] = pal.Entries[i] & 0x00ffffff; @@ -1486,33 +1522,34 @@ static void FreeDIBitmap(PREVIEW3_DIBITMAP* pInfo) { CallFunc(GdipDisposeImage)(pInfo->pBitmap); FX_Free(pInfo->pBitmapData); FX_Free((LPBYTE)pInfo->pbmi); - if (pInfo->pStream) { + if (pInfo->pStream) pInfo->pStream->Release(); - } FX_Free(pInfo); } -CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, - LPVOID pData, - bool bAlpha); -CFX_DIBitmap* CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) { +// TODO(tsepez): Really? Really? Move to header. +RetainPtr _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, + LPVOID pData, + bool bAlpha); + +RetainPtr CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) { PREVIEW3_DIBITMAP* pInfo = ::LoadDIBitmap(args); - if (!pInfo) { + if (!pInfo) return nullptr; - } + int height = abs(pInfo->pbmi->bmiHeader.biHeight); int width = pInfo->pbmi->bmiHeader.biWidth; int dest_pitch = (width * pInfo->pbmi->bmiHeader.biBitCount + 31) / 32 * 4; LPBYTE pData = FX_Alloc2D(BYTE, dest_pitch, height); if (dest_pitch == pInfo->Stride) { - FXSYS_memcpy(pData, pInfo->pScan0, dest_pitch * height); + memcpy(pData, pInfo->pScan0, dest_pitch * height); } else { for (int i = 0; i < height; i++) { - FXSYS_memcpy(pData + dest_pitch * i, pInfo->pScan0 + pInfo->Stride * i, - dest_pitch); + memcpy(pData + dest_pitch * i, pInfo->pScan0 + pInfo->Stride * i, + dest_pitch); } } - CFX_DIBitmap* pDIBitmap = _FX_WindowsDIB_LoadFromBuf( + RetainPtr pDIBitmap = _FX_WindowsDIB_LoadFromBuf( pInfo->pbmi, pData, pInfo->pbmi->bmiHeader.biBitCount == 32); FX_Free(pData); FreeDIBitmap(pInfo); diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp index cda83ebc95a289033aee3e3ae3e926b935a69b97..df9e8387d5f5035edf1736a892d8014fce8b62e5 100644 --- a/core/fxge/win32/fx_win32_print.cpp +++ b/core/fxge/win32/fx_win32_print.cpp @@ -11,10 +11,12 @@ #include #include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_windowsdevice.h" -#include "core/fxge/dib/dib_int.h" +#include "core/fxge/cfx_font.h" +#include "core/fxge/cfx_windowsrenderdevice.h" +#include "core/fxge/dib/cfx_dibextractor.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/dib/cstretchengine.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" #include "core/fxge/win32/cpsoutput.h" #include "core/fxge/win32/win32_int.h" #include "third_party/base/ptr_util.h" @@ -67,7 +69,7 @@ int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const { return CGdiDeviceDriver::GetDeviceCaps(caps_id); } -bool CGdiPrinterDriver::SetDIBits(const CFX_DIBSource* pSource, +bool CGdiPrinterDriver::SetDIBits(const RetainPtr& pSource, uint32_t color, const FX_RECT* pSrcRect, int left, @@ -87,14 +89,14 @@ bool CGdiPrinterDriver::SetDIBits(const CFX_DIBSource* pSource, return false; CFX_DIBExtractor temp(pSource); - CFX_DIBitmap* pBitmap = temp.GetBitmap(); + RetainPtr pBitmap = temp.GetBitmap(); if (!pBitmap) return false; return GDI_SetDIBits(pBitmap, pSrcRect, left, top); } -bool CGdiPrinterDriver::StretchDIBits(const CFX_DIBSource* pSource, +bool CGdiPrinterDriver::StretchDIBits(const RetainPtr& pSource, uint32_t color, int dest_left, int dest_top, @@ -109,7 +111,7 @@ bool CGdiPrinterDriver::StretchDIBits(const CFX_DIBSource* pSource, return false; if (dest_width < 0 || dest_height < 0) { - std::unique_ptr pFlipped = + RetainPtr pFlipped = pSource->FlipImage(dest_width < 0, dest_height < 0); if (!pFlipped) return false; @@ -119,13 +121,12 @@ bool CGdiPrinterDriver::StretchDIBits(const CFX_DIBSource* pSource, if (dest_height < 0) dest_top += dest_height; - return GDI_StretchBitMask(pFlipped.get(), dest_left, dest_top, - abs(dest_width), abs(dest_height), color, - flags); + return GDI_StretchBitMask(pFlipped, dest_left, dest_top, abs(dest_width), + abs(dest_height), color, flags); } CFX_DIBExtractor temp(pSource); - CFX_DIBitmap* pBitmap = temp.GetBitmap(); + RetainPtr pBitmap = temp.GetBitmap(); if (!pBitmap) return false; return GDI_StretchBitMask(pBitmap, dest_left, dest_top, dest_width, @@ -136,7 +137,7 @@ bool CGdiPrinterDriver::StretchDIBits(const CFX_DIBSource* pSource, return false; if (dest_width < 0 || dest_height < 0) { - std::unique_ptr pFlipped = + RetainPtr pFlipped = pSource->FlipImage(dest_width < 0, dest_height < 0); if (!pFlipped) return false; @@ -146,24 +147,24 @@ bool CGdiPrinterDriver::StretchDIBits(const CFX_DIBSource* pSource, if (dest_height < 0) dest_top += dest_height; - return GDI_StretchDIBits(pFlipped.get(), dest_left, dest_top, - abs(dest_width), abs(dest_height), flags); + return GDI_StretchDIBits(pFlipped, dest_left, dest_top, abs(dest_width), + abs(dest_height), flags); } CFX_DIBExtractor temp(pSource); - CFX_DIBitmap* pBitmap = temp.GetBitmap(); + RetainPtr pBitmap = temp.GetBitmap(); if (!pBitmap) return false; return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width, dest_height, flags); } -bool CGdiPrinterDriver::StartDIBits(const CFX_DIBSource* pSource, +bool CGdiPrinterDriver::StartDIBits(const RetainPtr& pSource, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t render_flags, - void*& handle, + std::unique_ptr* handle, int blend_type) { if (bitmap_alpha < 255 || pSource->HasAlpha() || (pSource->IsAlphaMask() && (pSource->GetBPP() != 1))) { @@ -171,8 +172,8 @@ bool CGdiPrinterDriver::StartDIBits(const CFX_DIBSource* pSource, } CFX_FloatRect unit_rect = pMatrix->GetUnitRect(); FX_RECT full_rect = unit_rect.GetOuterRect(); - if (FXSYS_fabs(pMatrix->b) < 0.5f && pMatrix->a != 0 && - FXSYS_fabs(pMatrix->c) < 0.5f && pMatrix->d != 0) { + if (fabs(pMatrix->b) < 0.5f && pMatrix->a != 0 && fabs(pMatrix->c) < 0.5f && + pMatrix->d != 0) { bool bFlipX = pMatrix->a < 0; bool bFlipY = pMatrix->d > 0; return StretchDIBits(pSource, color, @@ -182,15 +183,15 @@ bool CGdiPrinterDriver::StartDIBits(const CFX_DIBSource* pSource, bFlipY ? -full_rect.Height() : full_rect.Height(), nullptr, 0, blend_type); } - if (FXSYS_fabs(pMatrix->a) >= 0.5f || FXSYS_fabs(pMatrix->d) >= 0.5f) + if (fabs(pMatrix->a) >= 0.5f || fabs(pMatrix->d) >= 0.5f) return false; - std::unique_ptr pTransformed = + RetainPtr pTransformed = pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0); if (!pTransformed) return false; - return StretchDIBits(pTransformed.get(), color, full_rect.left, full_rect.top, + return StretchDIBits(pTransformed, color, full_rect.left, full_rect.top, full_rect.Width(), full_rect.Height(), nullptr, 0, blend_type); } @@ -199,7 +200,7 @@ bool CGdiPrinterDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) { #if defined(PDFIUM_PRINT_TEXT_WITH_GDI) if (!g_pdfium_print_text_with_gdi) @@ -209,7 +210,7 @@ bool CGdiPrinterDriver::DrawDeviceText(int nChars, return false; // Scale factor used to minimize the kerning problems caused by rounding - // errors below. Value choosen based on the title of https://crbug.com/18383 + // errors below. Value chosen based on the title of https://crbug.com/18383 const double kScaleFactor = 10; // Font @@ -230,8 +231,9 @@ bool CGdiPrinterDriver::DrawDeviceText(int nChars, lf.lfItalic = pFont->IsItalic(); lf.lfCharSet = DEFAULT_CHARSET; - const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode(); - int iNameLen = std::min(wsName.GetLength(), LF_FACESIZE - 1); + const WideString wsName = pFont->GetFaceName().UTF8Decode(); + size_t iNameLen = + std::min(wsName.GetLength(), static_cast(LF_FACESIZE - 1)); memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * iNameLen); lf.lfFaceName[iNameLen] = 0; @@ -280,14 +282,14 @@ bool CGdiPrinterDriver::DrawDeviceText(int nChars, // Color int iUnusedAlpha; FX_COLORREF rgb; - ArgbDecode(color, iUnusedAlpha, rgb); + std::tie(iUnusedAlpha, rgb) = ArgbToColorRef(color); SetTextColor(m_hDC, rgb); SetBkMode(m_hDC, TRANSPARENT); // Text - CFX_WideString wsText; + WideString wsText; std::vector spacing(nChars); - FX_FLOAT fPreviousOriginX = 0; + float fPreviousOriginX = 0; for (int i = 0; i < nChars; ++i) { // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary // values from PDFs. @@ -300,8 +302,8 @@ bool CGdiPrinterDriver::DrawDeviceText(int nChars, // Round the spacing to the nearest integer, but keep track of the rounding // error for calculating the next spacing value. - FX_FLOAT fOriginX = charpos.m_Origin.x * kScaleFactor; - FX_FLOAT fPixelSpacing = fOriginX - fPreviousOriginX; + float fOriginX = charpos.m_Origin.x * kScaleFactor; + float fPixelSpacing = fOriginX - fPreviousOriginX; spacing[i] = FXSYS_round(fPixelSpacing); fPreviousOriginX = fOriginX - (fPixelSpacing - spacing[i]); @@ -335,8 +337,9 @@ CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput) m_Width = ::GetDeviceCaps(m_hDC, HORZRES); m_Height = ::GetDeviceCaps(m_hDC, VERTRES); m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL); - m_pPSOutput = pdfium::MakeUnique(m_hDC); - m_PSRenderer.Init(m_pPSOutput.get(), pslevel, m_Width, m_Height, bCmykOutput); + + m_PSRenderer.Init(pdfium::MakeRetain(m_hDC), pslevel, m_Width, + m_Height, bCmykOutput); HRGN hRgn = ::CreateRectRgn(0, 0, 1, 1); int ret = ::GetClipRgn(hDC, hRgn); if (ret == 1) { @@ -349,10 +352,10 @@ CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput) for (uint32_t i = 0; i < pData->rdh.nCount; i++) { RECT* pRect = reinterpret_cast(pData->Buffer + pData->rdh.nRgnSize * i); - path.AppendRect(static_cast(pRect->left), - static_cast(pRect->bottom), - static_cast(pRect->right), - static_cast(pRect->top)); + path.AppendRect(static_cast(pRect->left), + static_cast(pRect->bottom), + static_cast(pRect->right), + static_cast(pRect->top)); } m_PSRenderer.SetClip_PathFill(&path, nullptr, FXFILL_WINDING); } @@ -436,7 +439,7 @@ bool CPSPrinterDriver::GetClipBox(FX_RECT* pRect) { return true; } -bool CPSPrinterDriver::SetDIBits(const CFX_DIBSource* pBitmap, +bool CPSPrinterDriver::SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int left, @@ -447,7 +450,7 @@ bool CPSPrinterDriver::SetDIBits(const CFX_DIBSource* pBitmap, return m_PSRenderer.SetDIBits(pBitmap, color, left, top); } -bool CPSPrinterDriver::StretchDIBits(const CFX_DIBSource* pBitmap, +bool CPSPrinterDriver::StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -462,12 +465,12 @@ bool CPSPrinterDriver::StretchDIBits(const CFX_DIBSource* pBitmap, dest_width, dest_height, flags); } -bool CPSPrinterDriver::StartDIBits(const CFX_DIBSource* pBitmap, +bool CPSPrinterDriver::StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t render_flags, - void*& handle, + std::unique_ptr* handle, int blend_type) { if (blend_type != FXDIB_BLEND_NORMAL) return false; @@ -475,7 +478,7 @@ bool CPSPrinterDriver::StartDIBits(const CFX_DIBSource* pBitmap, if (bitmap_alpha < 255) return false; - handle = nullptr; + *handle = nullptr; return m_PSRenderer.DrawDIBits(pBitmap, color, pMatrix, render_flags); } @@ -483,12 +486,164 @@ bool CPSPrinterDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) { return m_PSRenderer.DrawText(nChars, pCharPos, pFont, pObject2Device, font_size, color); } -void* CPSPrinterDriver::GetPlatformSurface() const { - return m_hDC; +CTextOnlyPrinterDriver::CTextOnlyPrinterDriver(HDC hDC) + : m_hDC(hDC), + m_Width(INT_MAX), + m_Height(INT_MAX), + m_HorzSize(INT_MAX), + m_VertSize(INT_MAX), + m_OriginY(0.0f), + m_SetOrigin(false) { + m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL); +} + +CTextOnlyPrinterDriver::~CTextOnlyPrinterDriver() { + EndRendering(); +} + +int CTextOnlyPrinterDriver::GetDeviceCaps(int caps_id) const { + switch (caps_id) { + case FXDC_DEVICE_CLASS: + return FXDC_PRINTER; + case FXDC_PIXEL_WIDTH: + return m_Width; + case FXDC_PIXEL_HEIGHT: + return m_Height; + case FXDC_BITS_PIXEL: + return m_nBitsPerPixel; + case FXDC_RENDER_CAPS: + return 0; + case FXDC_HORZ_SIZE: + return m_HorzSize; + case FXDC_VERT_SIZE: + return m_VertSize; + } + return 0; +} + +bool CTextOnlyPrinterDriver::SetClip_PathFill(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + int fill_mode) { + return true; +} + +bool CTextOnlyPrinterDriver::SetClip_PathStroke( + const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState) { + return false; +} + +bool CTextOnlyPrinterDriver::DrawPath(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + uint32_t stroke_color, + int fill_mode, + int blend_type) { + return false; +} + +bool CTextOnlyPrinterDriver::SetDIBits(const RetainPtr& pBitmap, + uint32_t color, + const FX_RECT* pSrcRect, + int left, + int top, + int blend_type) { + return false; +} + +bool CTextOnlyPrinterDriver::GetClipBox(FX_RECT* pRect) { + pRect->left = 0; + pRect->right = m_Width; + pRect->top = 0; + pRect->bottom = m_Height; + return true; +} + +bool CTextOnlyPrinterDriver::StretchDIBits( + const RetainPtr& pBitmap, + uint32_t color, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + const FX_RECT* pClipRect, + uint32_t flags, + int blend_type) { + return false; +} + +bool CTextOnlyPrinterDriver::StartDIBits( + const RetainPtr& pBitmap, + int bitmap_alpha, + uint32_t color, + const CFX_Matrix* pMatrix, + uint32_t render_flags, + std::unique_ptr* handle, + int blend_type) { + return false; +} + +bool CTextOnlyPrinterDriver::DrawDeviceText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + const CFX_Matrix* pObject2Device, + float font_size, + uint32_t color) { + if (g_pdfium_print_mode != 1) + return false; + if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont()) + return false; + + // Scale factor used to minimize the kerning problems caused by rounding + // errors below. Value chosen based on the title of https://crbug.com/18383 + const double kScaleFactor = 10; + + WideString wsText; + int totalLength = nChars; + + // Detect new lines and add clrf characters (since this is Windows only). + // These characters are removed by SkPDF, but the new line information is + // preserved in the text location. clrf characters seem to be ignored by + // label printers that use this driver. + if (m_SetOrigin && + FXSYS_round(m_OriginY) != FXSYS_round(pObject2Device->f * kScaleFactor)) { + wsText += L"\r\n"; + totalLength += 2; + } + m_OriginY = pObject2Device->f * kScaleFactor; + m_SetOrigin = true; + + // Text + for (int i = 0; i < nChars; ++i) { + // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary + // values from PDFs. + const FXTEXT_CHARPOS& charpos = pCharPos[i]; + ASSERT(charpos.m_AdjustMatrix[0] == 0); + ASSERT(charpos.m_AdjustMatrix[1] == 0); + ASSERT(charpos.m_AdjustMatrix[2] == 0); + ASSERT(charpos.m_AdjustMatrix[3] == 0); + ASSERT(charpos.m_Origin.y == 0); + + wsText += charpos.m_Unicode; + } + size_t len = totalLength; + ByteString text = ByteString::FromUnicode(wsText); + while (len > 0) { + char buffer[1026]; + size_t send_len = std::min(len, static_cast(1024)); + *(reinterpret_cast(buffer)) = send_len; + memcpy(buffer + 2, text.c_str(), send_len); + ::GdiComment(m_hDC, send_len + 2, reinterpret_cast(buffer)); + len -= send_len; + text.Right(len); + } + return true; } diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h index f8eae8730874e8fc657eb312c20848d2dd378cf8..d4f2597033d8e26f3adbd9beb004957875e397e4 100644 --- a/core/fxge/win32/win32_int.h +++ b/core/fxge/win32/win32_int.h @@ -10,13 +10,16 @@ #include #include +#include +#include "core/fxcrt/retain_ptr.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/ifx_renderdevicedriver.h" #include "core/fxge/win32/cfx_psrenderer.h" #include "core/fxge/win32/cpsoutput.h" #include "core/fxge/win32/dwrite_int.h" +class CFX_ImageRenderer; class FXTEXT_CHARPOS; struct WINDIB_Open_Args_; @@ -30,11 +33,12 @@ class CGdiplusExt { public: CGdiplusExt(); ~CGdiplusExt(); + void Load(); bool IsAvailable() { return !!m_hModule; } bool StretchBitMask(HDC hDC, BOOL bMonoDevice, - const CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, @@ -43,7 +47,7 @@ class CGdiplusExt { const FX_RECT* pClipRect, int flags); bool StretchDIBits(HDC hDC, - const CFX_DIBitmap* pBitmap, + const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, @@ -75,44 +79,44 @@ class CGdiplusExt { const void* matrix); void GdipCreateBrush(uint32_t fill_argb, void** pBrush); void GdipDeleteBrush(void* pBrush); - void GdipCreateMatrix(FX_FLOAT a, - FX_FLOAT b, - FX_FLOAT c, - FX_FLOAT d, - FX_FLOAT e, - FX_FLOAT f, + void GdipCreateMatrix(float a, + float b, + float c, + float d, + float e, + float f, void** matrix); void GdipDeleteMatrix(void* matrix); - bool GdipCreateFontFamilyFromName(const FX_WCHAR* name, + bool GdipCreateFontFamilyFromName(const wchar_t* name, void* pFontCollection, void** pFamily); void GdipDeleteFontFamily(void* pFamily); bool GdipCreateFontFromFamily(void* pFamily, - FX_FLOAT font_size, + float font_size, int fontstyle, int flag, void** pFont); void* GdipCreateFontFromCollection(void* pFontCollection, - FX_FLOAT font_size, + float font_size, int fontstyle); void GdipDeleteFont(void* pFont); - bool GdipCreateBitmap(CFX_DIBitmap* pBitmap, void** bitmap); + bool GdipCreateBitmap(const RetainPtr& pBitmap, void** bitmap); void GdipDisposeImage(void* bitmap); - void GdipGetFontSize(void* pFont, FX_FLOAT* size); + void GdipGetFontSize(void* pFont, float* size); void* GdiAddFontMemResourceEx(void* pFontdata, uint32_t size, void* pdv, uint32_t* num_face); bool GdiRemoveFontMemResourceEx(void* handle); - CFX_DIBitmap* LoadDIBitmap(WINDIB_Open_Args_ args); + RetainPtr LoadDIBitmap(WINDIB_Open_Args_ args); - FARPROC m_Functions[100]; - FuncType_GdiAddFontMemResourceEx m_pGdiAddFontMemResourceEx; - FuncType_GdiRemoveFontMemResourceEx m_pGdiRemoveFontMemResourseEx; + std::vector m_Functions; + FuncType_GdiAddFontMemResourceEx m_pGdiAddFontMemResourceEx = nullptr; + FuncType_GdiRemoveFontMemResourceEx m_pGdiRemoveFontMemResourseEx = nullptr; protected: - HMODULE m_hModule; - HMODULE m_GdiModule; + HMODULE m_hModule = nullptr; + HMODULE m_GdiModule = nullptr; }; class CWin32Platform { @@ -147,28 +151,25 @@ class CGdiDeviceDriver : public IFX_RenderDeviceDriver { bool FillRectWithBlend(const FX_RECT* pRect, uint32_t fill_color, int blend_type) override; - bool DrawCosmeticLine(FX_FLOAT x1, - FX_FLOAT y1, - FX_FLOAT x2, - FX_FLOAT y2, + bool DrawCosmeticLine(const CFX_PointF& ptMoveTo, + const CFX_PointF& ptLineTo, uint32_t color, int blend_type) override; bool GetClipBox(FX_RECT* pRect) override; - void* GetPlatformSurface() const override; - void DrawLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2); + void DrawLine(float x1, float y1, float x2, float y2); - bool GDI_SetDIBits(CFX_DIBitmap* pBitmap, + bool GDI_SetDIBits(const RetainPtr& pBitmap, const FX_RECT* pSrcRect, int left, int top); - bool GDI_StretchDIBits(CFX_DIBitmap* pBitmap, + bool GDI_StretchDIBits(const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, int dest_height, uint32_t flags); - bool GDI_StretchBitMask(CFX_DIBitmap* pBitmap, + bool GDI_StretchBitMask(const RetainPtr& pBitmap, int dest_left, int dest_top, int dest_width, @@ -191,14 +192,16 @@ class CGdiDisplayDriver : public CGdiDeviceDriver { ~CGdiDisplayDriver() override; protected: - bool GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) override; - bool SetDIBits(const CFX_DIBSource* pBitmap, + bool GetDIBits(const RetainPtr& pBitmap, + int left, + int top) override; + bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int left, int top, int blend_type) override; - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -207,14 +210,14 @@ class CGdiDisplayDriver : public CGdiDeviceDriver { const FX_RECT* pClipRect, uint32_t flags, int blend_type) override; - bool StartDIBits(const CFX_DIBSource* pBitmap, + bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t render_flags, - void*& handle, + std::unique_ptr* handle, int blend_type) override; - bool UseFoxitStretchEngine(const CFX_DIBSource* pSource, + bool UseFoxitStretchEngine(const RetainPtr& pSource, uint32_t color, int dest_left, int dest_top, @@ -231,13 +234,13 @@ class CGdiPrinterDriver : public CGdiDeviceDriver { protected: int GetDeviceCaps(int caps_id) const override; - bool SetDIBits(const CFX_DIBSource* pBitmap, + bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int left, int top, int blend_type) override; - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -246,18 +249,18 @@ class CGdiPrinterDriver : public CGdiDeviceDriver { const FX_RECT* pClipRect, uint32_t flags, int blend_type) override; - bool StartDIBits(const CFX_DIBSource* pBitmap, + bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t render_flags, - void*& handle, + std::unique_ptr* handle, int blend_type) override; bool DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) override; const int m_HorzSize; @@ -290,13 +293,13 @@ class CPSPrinterDriver : public IFX_RenderDeviceDriver { int fill_mode, int blend_type) override; bool GetClipBox(FX_RECT* pRect) override; - bool SetDIBits(const CFX_DIBSource* pBitmap, + bool SetDIBits(const RetainPtr& pBitmap, uint32_t color, const FX_RECT* pSrcRect, int left, int top, int blend_type) override; - bool StretchDIBits(const CFX_DIBSource* pBitmap, + bool StretchDIBits(const RetainPtr& pBitmap, uint32_t color, int dest_left, int dest_top, @@ -305,20 +308,19 @@ class CPSPrinterDriver : public IFX_RenderDeviceDriver { const FX_RECT* pClipRect, uint32_t flags, int blend_type) override; - bool StartDIBits(const CFX_DIBSource* pBitmap, + bool StartDIBits(const RetainPtr& pBitmap, int bitmap_alpha, uint32_t color, const CFX_Matrix* pMatrix, uint32_t render_flags, - void*& handle, + std::unique_ptr* handle, int blend_type) override; bool DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, const CFX_Matrix* pObject2Device, - FX_FLOAT font_size, + float font_size, uint32_t color) override; - void* GetPlatformSurface() const override; HDC m_hDC; bool m_bCmykOutput; @@ -327,8 +329,69 @@ class CPSPrinterDriver : public IFX_RenderDeviceDriver { int m_nBitsPerPixel; int m_HorzSize; int m_VertSize; - std::unique_ptr m_pPSOutput; CFX_PSRenderer m_PSRenderer; }; +class CTextOnlyPrinterDriver : public IFX_RenderDeviceDriver { + public: + explicit CTextOnlyPrinterDriver(HDC hDC); + ~CTextOnlyPrinterDriver() override; + + protected: + // IFX_RenderDeviceDriver + int GetDeviceCaps(int caps_id) const override; + void SaveState() override{}; + void RestoreState(bool bKeepSaved) override{}; + bool SetClip_PathFill(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + int fill_mode) override; + bool SetClip_PathStroke(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState) override; + bool DrawPath(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + uint32_t stroke_color, + int fill_mode, + int blend_type) override; + bool GetClipBox(FX_RECT* pRect) override; + bool SetDIBits(const RetainPtr& pBitmap, + uint32_t color, + const FX_RECT* pSrcRect, + int left, + int top, + int blend_type) override; + bool StretchDIBits(const RetainPtr& pBitmap, + uint32_t color, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + const FX_RECT* pClipRect, + uint32_t flags, + int blend_type) override; + bool StartDIBits(const RetainPtr& pBitmap, + int bitmap_alpha, + uint32_t color, + const CFX_Matrix* pMatrix, + uint32_t render_flags, + std::unique_ptr* handle, + int blend_type) override; + bool DrawDeviceText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + const CFX_Matrix* pObject2Device, + float font_size, + uint32_t color) override; + + HDC m_hDC; + int m_Width; + int m_Height; + int m_nBitsPerPixel; + int m_HorzSize; + int m_VertSize; + float m_OriginY; + bool m_SetOrigin; +}; #endif // CORE_FXGE_WIN32_WIN32_INT_H_ diff --git a/docs/code-coverage.md b/docs/code-coverage.md new file mode 100644 index 0000000000000000000000000000000000000000..200a674bb08fa5039a47dca567f246e7dbd5e66d --- /dev/null +++ b/docs/code-coverage.md @@ -0,0 +1,153 @@ +# Code Coverage Support for PDFium + +[TOC] + +This guide explains how to generate code coverage information for the PDFium +library on a local computer. + +## Prerequisites + +You will need the PDFium source code on your computer. You can see +the [README](/README.md) for instructions on checking out PDFium's source. + +The tools used for code coverage are known to work on Ubuntu 14.04. They should +work correctly on newer versions of Ubuntu and related Linux distros. They have +not been tested on Windows and Mac. + +### lcov + +The code coverage scripts depend on having a version of `lcov` of 1.11 or +greater available, which is enforced by the script. Unfortunately the default +version of `lcov` for Ubuntu 14.04 is 1.10, thus you will need to install a +newer version. + +You can build a newer version of `lcov` from source, which is +available [here](http://ltp.sourceforge.net/coverage/lcov.php). + +If you don't want to build from source and use an RPM based Linux, not +Ubuntu/Debian, then there are pre-built RPMs +available [here](http://downloads.sourceforge.net/ltp/lcov-1.13-1.noarch.rpm). + +For Ubuntu/Debian users these RPMs can be converted to .deb using `alien`. More +information about how to do this can be found in `man alien`. + +### llvm-cov + +The other external dependency for generating code coverage information is having +a version of `llvm-cov` that supports the `gcov` command. This should be all +versions of 3.5.0 or greater. + +Again, unfortunately, the default llvm-cov that comes with Ubuntu 14.04, 3.4, is +lower then what is needed. The 14.04 repositories do support having multiple +versions of the `llvm` package, and thus `llvm-cov`. Through your favourite +package manager you should be able to install any version of `llvm` of 3.5 or +greater and the coverage scripts should find it. + +## Generating Code Coverage + +### Setup + +This step assumes that you have already checked out the PDFium source code and +installed the proper versions of the external tools. If you have not, please +consult the above Prerequisites section. + +Before generating code coverage information, you will need to have a build +directory with coverage enabled. This can be done by running the `gn args` +command and adding `use_coverage = true` in the editor that is opened. If not +using the default directory, `out/Coverage`, then replace it with the correct +location in the following command. + +```shell +gn args out/Coverage +``` + +If you already have a build directory, you can append the coverage flag to the +existing `args.gn` as follows. If not using the default directory, +`out/Coverage`, then replace it with the correct location in the following +command. + +```shell +echo "use_coverage = true" >> out/Coverage/args.gn +``` + + +### Usage + +Generating code coverage information is done via the +`testing/tools/coverage/coverage_report.py` script. This script will build any binaries +that it needs, perform test runs, collect coverage data, and finally generate a +nice HTML coverage report. + +Running the script with no arguments, as below, will assume that you are +currently at the root of your PDFium checkout, the build directory to use is +`./out/Coverage/` and that HTML should be outputted to `./coverage_report/`. By +default, it will also only run `pdfium_unittests` and `pdfium_embeddertests` for +coverage data. This is because the other tests are known to take a long time to +run, so they are not included in the defaults. + +```shell +testing/tools/coverage/coverage_report.py +``` + +If the current working directory is not the root of your PDFium checkout, then +you will need to pass in `--source-directory` with the appropriate directory. If +you are using a different build directory, then `--build-directory` will need to +be passed in. Finally, if you want the HTML report in a different location then +you will need to pass in `--output-directory`. + +An example of all these flags being used: + +```shell +testing/tools/coverage/coverage_report.py \ + --source-directory ~/pdfium/pdfium \ + --build-directory ~/pdfium/pdfium/out/Debug_with_Coverage \ + --output-directory ~/Documents/PDFium_coverage +``` + +To run different tests then the default set, there are two ways to achieve +this. If you want to run everything, including tests that are known to take a +long time, then you just need to add the `--slow` flag. + +```shell +testing/tools/coverage/coverage_report.py --slow +``` + +If you want more fine grained control, including running just a single test, you +can specify the test names on the command line. The `--slow` flag is not needed +if you are explicitly invoking tests. The list of supported tests can be found +by running the script with `--help`. + +An example running the default tests explicitly: + +```shell +testing/tools/coverage/coverage_report.py pdfium_unittests pdfium_embeddertests +``` + +NOTE: +At the present time, there is no mechanism for combining data from different +invocations of `coverage_report.py`. Instead you must specify all of the tests +to be included in the report in a single invocation. + +There are additional developer debugging flags available, `--dry-run` and +`--verbose`. `--dry-run` will output a trace of commands that would have been +run, but doesn't actually execute them. `--verbose` turns on outputting +additional logging information. + +### Viewing + +Once the script has run, the output directory should contain a set of HTML files +containing the coverage report. + +These files are static HTML, so you can point your browser at them directly on +your local file system and they should render fine. You can also serve them via a +web server if you want, but how to achieve that is beyond the scope of this +documentation. + +## Issues + +For help with using the code coverage tools please contact the PDFium +maintainers via the PDFium +mailing [list](https://groups.google.com/forum/#!forum/pdfium). + +Please file bugs against the code coverage +support [here](https://bugs.chromium.org/p/pdfium/issues/list). diff --git a/docs/getting-started.md b/docs/getting-started.md index b80e56683b61af61809b401fd4e56b6f855b1dee..0cf2ff3d88ae1f3b25c6b2d78016036bdb5c1729 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -12,8 +12,8 @@ You will need the PDFium library on your computer. You can see the *** note You must compile PDFium without both V8 and XFA support for the examples -here to work. V8 can be compiled out by providing -`GYP_DEFINES="pdf_enable_v8=0 pdf_enable_xfa=0" build/gyp_pdfium`. +here to work. V8 can be disabled by setting `pdf_enable_v8 = false` in the +GN args. See the [V8 Getting Started][pdfium-v8] guide for how to initialize PDFium when V8 is compiled into the binary. @@ -73,8 +73,7 @@ the link line in order to compile. My build line was: ``` PDF_LIBS="-lpdfium -lfpdfapi -lfxge -lfpdfdoc -lfxcrt -lfx_agg \ -lfxcodec -lfx_lpng -lfx_libopenjpeg -lfx_lcms2 -lfx_freetype -ljpeg \ --lfx_zlib -lfdrm -lpdfwindow -lbigint -lformfiller -ljavascript \ --lfxedit" +-lfdrm -lpwl -lbigint -lformfiller -ljavascript -lfxedit" PDF_DIR= clang -I $PDF_DIR/public -o init init.c -L $PDF_DIR/out/Debug -lstdc++ -framework AppKit $PDF_LIBS diff --git a/docs/safetynet.md b/docs/safetynet.md new file mode 100644 index 0000000000000000000000000000000000000000..540f7db2ebd154f4cd59c341113e084be0ed94ac --- /dev/null +++ b/docs/safetynet.md @@ -0,0 +1,159 @@ +# SafetyNet - Performance regression detection for PDFium + +[TOC] + +This document explains how to use SafetyNet to detect performance regressions +in PDFium. + +## Comparing performance of two versions of PDFium + +safetynet_compare.py is a script that compares the performance between two +versions of pdfium. This can be used to verify if a given change has caused +or will cause any positive or negative changes in performance for a set of test +cases. + +The supported profilers are exclusive to Linux, so for now this can only be run +on Linux. + +An illustrative example is below, comparing the local code version to an older +version. Positive % changes mean an increase in time/instructions to run the +test - a regression, while negative % changes mean a decrease in +time/instructions, therefore an improvement. + +``` +$ testing/tools/safetynet_compare.py ~/test_pdfs --branch-before beef5e4 +================================================================================ + % Change Time after Test case +-------------------------------------------------------------------------------- + -0.1980% 45,703,820,326 ~/test_pdfs/PDF Reference 1-7.pdf + -0.5678% 42,038,814 ~/test_pdfs/Page 24 - PDF Reference 1-7.pdf + +0.2666% 10,983,158,809 ~/test_pdfs/Rival.pdf + +0.0447% 10,413,890,748 ~/test_pdfs/dynamic.pdf + -7.7228% 26,161,171 ~/test_pdfs/encrypted1234.pdf + -0.2763% 102,084,398 ~/test_pdfs/ghost.pdf + -3.7005% 10,800,642,262 ~/test_pdfs/musician.pdf + -0.2266% 45,691,618,789 ~/test_pdfs/no_metadata.pdf + +1.4440% 38,442,606,162 ~/test_pdfs/test7.pdf + +0.0335% 9,286,083 ~/test_pdfs/testbulletpoint.pdf +================================================================================ +Test cases run: 10 +Failed to measure: 0 +Regressions: 0 +Improvements: 2 +``` + +### Usage + +Run the safetynet_compare.py script in testing/tools to perform a comparison. +Pass one or more paths with test cases - each path can be either a .pdf file or +a directory containing .pdf files. Other files in those directories are +ignored. + +The following comparison modes are supported: + +1. Compare uncommitted changes against clean branch: +```shell +$ testing/tools/safetynet_compare.py path/to/pdfs +``` + +2. Compare current branch with another branch or commit: +```shell +$ testing/tools/safetynet_compare.py path/to/pdfs --branch-before another_branch +$ testing/tools/safetynet_compare.py path/to/pdfs --branch-before 1a3c5e7 +``` + +3. Compare two other branches or commits: +```shell +$ testing/tools/safetynet_compare.py path/to/pdfs --branch-after another_branch --branch-before yet_another_branch +$ testing/tools/safetynet_compare.py path/to/pdfs --branch-after 1a3c5e7 --branch-before 0b2d4f6 +$ testing/tools/safetynet_compare.py path/to/pdfs --branch-after another_branch --branch-before 0b2d4f6 +``` + +4. Compare two build flag configurations: +```shell +$ gn args out/BuildConfig1 +$ gn args out/BuildConfig2 +$ testing/tools/safetynet_compare.py path/to/pdfs --build-dir out/BuildConfig2 --build-dir-before out/BuildConfig1 +``` + +safetynet_compare.py takes care of checking out the appropriate branch, building +it, running the test cases and comparing results. + +### Profilers + +safetynet_compare.py uses callgrind as a profiler by default. Use --profiler +to specify another one. The supported ones are: + +#### perfstat + +Only works on Linux. +Make sure you have perf by typing in the terminal: +```shell +$ perf +``` + +This is a fast profiler, but uses sampling so it's slightly inaccurate. +Expect variations of up to 1%, which is below the cutoff to consider a +change significant. + +Use this when running over large test sets to get good enough results. + +#### callgrind + +Only works on Linux. +Make sure valgrind is installed: +```shell +$ valgrind +``` + +This is a slow and accurate profiler. Expect variations of around 100 +instructions. However, this takes about 50 times longer to run than perf stat. + +Use this when looking for small variations (< 1%). + +One advantage is that callgrind can generate `callgrind.out` files (by passing +--output-dir to safetynet_compare.py), which contain profiling information that +can be analyzed to find the cause of a regression. KCachegrind is a good +visualizer for these files. + +### Common Options + +Arguments commonly passed to safetynet_compare.py. + +* --profiler: described above. +* --build-dir: this specified the build config with a relative path from the +pdfium src directory to the build directory. Defaults to out/Release. +* --output-dir: where to place the profiling output files. These are +callgrind.out.[test_case] files for callgrind, perfstat does not produce them. +By default they are not written. +* --case-order: sort test case results according to this metric. Can be "after", +"before", "ratio" and "rating". If not specified, sort by path. +* --this-repo: use the repository where the script is instead of checking out a +temporary one. This is faster and does not require downloads. Although it +restores the state of the local repo, if the script is killed or crashes the +uncommitted changes can remain stashed and you may be on another branch. + +### Other Options + +Most of the time these don't need to be used. + +* --build-dir-before: if comparing different build dirs (say, to test what a +flag flip does), specify the build dir for the “before” branch here and the +build dir for the “after” branch with --build-dir. +* --interesting-section: only the interesting section should be measured instead +of all the execution of the test harness. This only works in debug, since in +release the delimiters are stripped out. This does not work to compare branches +that don’t have the callgrind delimiters, as it would otherwise be unfair to +compare a whole run vs the interesting section of another run. +* --machine-readable: output a json with the results that is easier to read by +code. +* --num-workers: how many workers to use to parallelize test case runs. Defaults +to # of CPUs in the machine. +* --threshold-significant: highlight differences that exceed this value. +Defaults to 0.02. +* --tmp-dir: directory in which temporary repos will be cloned and downloads +will be cached, if --this-repo is not enabled. Defaults to /tmp. + +## Setup a nightly job + +TODO: Complete with safetynet_job.py setup and usage. diff --git a/fpdfsdk/DEPS b/fpdfsdk/DEPS index e077225b17617ed85c2fd14774e038397a9bbf1e..95ddfe16cc469a242023f61bbac914f9674c12c6 100644 --- a/fpdfsdk/DEPS +++ b/fpdfsdk/DEPS @@ -1,9 +1,10 @@ include_rules = [ '+core', + '+fxjs', '+public', '+v8', '+xfa/fwl', - '+xfa/fxbarcode', + '+fxbarcode', '+xfa/fxfa', '+xfa/fxgraphics', ] diff --git a/fpdfsdk/cba_annotiterator.cpp b/fpdfsdk/cba_annotiterator.cpp index cc842babee2afa9dcf4f7cea778dba2a2884f11d..d1c9599cf66efbc28986a6cfa3d165f7919aa977 100644 --- a/fpdfsdk/cba_annotiterator.cpp +++ b/fpdfsdk/cba_annotiterator.cpp @@ -34,7 +34,7 @@ CBA_AnnotIterator::CBA_AnnotIterator(CPDFSDK_PageView* pPageView, m_pPageView(pPageView), m_nAnnotSubtype(nAnnotSubtype) { CPDF_Page* pPDFPage = m_pPageView->GetPDFPage(); - CFX_ByteString sTabs = pPDFPage->m_pFormDict->GetStringFor("Tabs"); + ByteString sTabs = pPDFPage->m_pFormDict->GetStringFor("Tabs"); if (sTabs == "R") m_eTabOrder = ROW; else if (sTabs == "C") @@ -73,7 +73,7 @@ CPDFSDK_Annot* CBA_AnnotIterator::GetPrevAnnot(CPDFSDK_Annot* pAnnot) { } void CBA_AnnotIterator::CollectAnnots(std::vector* pArray) { - for (auto pAnnot : m_pPageView->GetAnnotList()) { + for (auto* pAnnot : m_pPageView->GetAnnotList()) { if (pAnnot->GetAnnotSubtype() == m_nAnnotSubtype && !pAnnot->IsSignatureWidget()) { pArray->push_back(pAnnot); @@ -113,7 +113,7 @@ void CBA_AnnotIterator::GenerateResults() { while (!sa.empty()) { int nLeftTopIndex = -1; - FX_FLOAT fTop = 0.0f; + float fTop = 0.0f; for (int i = sa.size() - 1; i >= 0; i--) { CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]); if (rcAnnot.top > fTop) { @@ -129,7 +129,7 @@ void CBA_AnnotIterator::GenerateResults() { std::vector aSelect; for (size_t i = 0; i < sa.size(); ++i) { CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]); - FX_FLOAT fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f; + float fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f; if (fCenterY > rcLeftTop.bottom && fCenterY < rcLeftTop.top) aSelect.push_back(i); } @@ -145,7 +145,7 @@ void CBA_AnnotIterator::GenerateResults() { while (!sa.empty()) { int nLeftTopIndex = -1; - FX_FLOAT fLeft = -1.0f; + float fLeft = -1.0f; for (int i = sa.size() - 1; i >= 0; --i) { CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]); if (fLeft < 0) { @@ -164,7 +164,7 @@ void CBA_AnnotIterator::GenerateResults() { std::vector aSelect; for (size_t i = 0; i < sa.size(); ++i) { CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]); - FX_FLOAT fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f; + float fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f; if (fCenterX > rcLeftTop.left && fCenterX < rcLeftTop.right) aSelect.push_back(i); } diff --git a/fpdfsdk/cba_annotiterator.h b/fpdfsdk/cba_annotiterator.h index 5cbe8e3d57127e4d9bb3c89200598e1a47f69899..8f9768d1e2d535f3ac069fd3316ddc84af89b28e 100644 --- a/fpdfsdk/cba_annotiterator.h +++ b/fpdfsdk/cba_annotiterator.h @@ -12,6 +12,7 @@ #include "core/fpdfdoc/cpdf_annot.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" class CPDFSDK_Annot; class CPDFSDK_PageView; @@ -37,7 +38,7 @@ class CBA_AnnotIterator { std::vector* aSelect); TabOrder m_eTabOrder; - CPDFSDK_PageView* m_pPageView; + UnownedPtr m_pPageView; CPDF_Annot::Subtype m_nAnnotSubtype; std::vector m_Annots; }; diff --git a/fpdfsdk/cfx_systemhandler.cpp b/fpdfsdk/cfx_systemhandler.cpp index b6dc19d48f29e87274d60f61de1da0baaa61dca7..bbb029319c2a0b094bc4d9b248639858b500a387 100644 --- a/fpdfsdk/cfx_systemhandler.cpp +++ b/fpdfsdk/cfx_systemhandler.cpp @@ -9,6 +9,8 @@ #include #include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/cfx_fontmapper.h" #include "core/fxge/cfx_fontmgr.h" #include "core/fxge/cfx_gemodule.h" @@ -21,20 +23,26 @@ namespace { int CharSet2CP(int charset) { - if (charset == FXFONT_SHIFTJIS_CHARSET) - return 932; - if (charset == FXFONT_GB2312_CHARSET) - return 936; - if (charset == FXFONT_HANGUL_CHARSET) - return 949; - if (charset == FXFONT_CHINESEBIG5_CHARSET) - return 950; - return 0; + if (charset == FX_CHARSET_ShiftJIS) + return FX_CODEPAGE_ShiftJIS; + if (charset == FX_CHARSET_ChineseSimplified) + return FX_CODEPAGE_ChineseSimplified; + if (charset == FX_CHARSET_Hangul) + return FX_CODEPAGE_Hangul; + if (charset == FX_CHARSET_ChineseTraditional) + return FX_CODEPAGE_ChineseTraditional; + return FX_CODEPAGE_DefANSI; } } // namespace -void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect) { +CFX_SystemHandler::CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv) + : m_pFormFillEnv(pFormFillEnv) {} + +CFX_SystemHandler::~CFX_SystemHandler() {} + +void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget, + const CFX_FloatRect& rect) { CPDFSDK_PageView* pPageView = widget->GetPageView(); UnderlyingPageType* pPage = widget->GetUnderlyingPage(); if (!pPage || !pPageView) @@ -43,17 +51,15 @@ void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect) { CFX_Matrix page2device; pPageView->GetCurrentMatrix(page2device); - CFX_Matrix device2page; - device2page.SetReverse(page2device); + CFX_Matrix device2page = page2device.GetInverse(); - CFX_PointF left_top = device2page.Transform(CFX_PointF( - static_cast(rect.left), static_cast(rect.top))); - CFX_PointF right_bottom = device2page.Transform(CFX_PointF( - static_cast(rect.right), static_cast(rect.bottom))); + CFX_PointF left_top = device2page.Transform(CFX_PointF(rect.left, rect.top)); + CFX_PointF right_bottom = + device2page.Transform(CFX_PointF(rect.right, rect.bottom)); CFX_FloatRect rcPDF(left_top.x, right_bottom.y, right_bottom.x, left_top.y); rcPDF.Normalize(); - m_pFormFillEnv->Invalidate(pPage, rcPDF.ToFxRect()); + m_pFormFillEnv->Invalidate(pPage, rcPDF.GetOuterRect()); } void CFX_SystemHandler::OutputSelectedRect(CFFL_FormFiller* pFormFiller, @@ -84,7 +90,7 @@ void CFX_SystemHandler::SetCursor(int32_t nCursorType) { m_pFormFillEnv->SetCursor(nCursorType); } -bool CFX_SystemHandler::FindNativeTrueTypeFont(CFX_ByteString sFontFaceName) { +bool CFX_SystemHandler::FindNativeTrueTypeFont(ByteString sFontFaceName) { CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); if (!pFontMgr) return false; @@ -97,11 +103,11 @@ bool CFX_SystemHandler::FindNativeTrueTypeFont(CFX_ByteString sFontFaceName) { pFontMapper->LoadInstalledFonts(); for (const auto& font : pFontMapper->m_InstalledTTFonts) { - if (font.Compare(sFontFaceName.AsStringC())) + if (font.Compare(sFontFaceName.AsStringView())) return true; } for (const auto& fontPair : pFontMapper->m_LocalizedTTFonts) { - if (fontPair.first.Compare(sFontFaceName.AsStringC())) + if (fontPair.first.Compare(sFontFaceName.AsStringView())) return true; } return false; @@ -109,12 +115,12 @@ bool CFX_SystemHandler::FindNativeTrueTypeFont(CFX_ByteString sFontFaceName) { CPDF_Font* CFX_SystemHandler::AddNativeTrueTypeFontToPDF( CPDF_Document* pDoc, - CFX_ByteString sFontFaceName, + ByteString sFontFaceName, uint8_t nCharset) { if (!pDoc) return nullptr; - std::unique_ptr pFXFont(new CFX_Font); + auto pFXFont = pdfium::MakeUnique(); pFXFont->LoadSubst(sFontFaceName, true, 0, 0, 0, CharSet2CP(nCharset), false); return pDoc->AddFont(pFXFont.get(), nCharset, false); } @@ -127,15 +133,3 @@ int32_t CFX_SystemHandler::SetTimer(int32_t uElapse, void CFX_SystemHandler::KillTimer(int32_t nID) { m_pFormFillEnv->KillTimer(nID); } - -bool CFX_SystemHandler::IsSHIFTKeyDown(uint32_t nFlag) const { - return !!m_pFormFillEnv->IsSHIFTKeyDown(nFlag); -} - -bool CFX_SystemHandler::IsCTRLKeyDown(uint32_t nFlag) const { - return !!m_pFormFillEnv->IsCTRLKeyDown(nFlag); -} - -bool CFX_SystemHandler::IsALTKeyDown(uint32_t nFlag) const { - return !!m_pFormFillEnv->IsALTKeyDown(nFlag); -} diff --git a/fpdfsdk/cfx_systemhandler.h b/fpdfsdk/cfx_systemhandler.h index 82cfc531ca2be804ffd86ec9e5f9e8b063823f2e..f9138cc07894a8d315c1ed1a77d54600d0244be0 100644 --- a/fpdfsdk/cfx_systemhandler.h +++ b/fpdfsdk/cfx_systemhandler.h @@ -8,7 +8,9 @@ #define FPDFSDK_CFX_SYSTEMHANDLER_H_ #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" using TimerCallback = void (*)(int32_t idEvent); @@ -49,30 +51,23 @@ class CPDFSDK_Widget; class CFX_SystemHandler { public: - explicit CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv) - : m_pFormFillEnv(pFormFillEnv) {} - ~CFX_SystemHandler() {} + explicit CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv); + ~CFX_SystemHandler(); - void InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect); + void InvalidateRect(CPDFSDK_Widget* widget, const CFX_FloatRect& rect); void OutputSelectedRect(CFFL_FormFiller* pFormFiller, CFX_FloatRect& rect); bool IsSelectionImplemented() const; - void SetCursor(int32_t nCursorType); - - bool FindNativeTrueTypeFont(CFX_ByteString sFontFaceName); + bool FindNativeTrueTypeFont(ByteString sFontFaceName); CPDF_Font* AddNativeTrueTypeFontToPDF(CPDF_Document* pDoc, - CFX_ByteString sFontFaceName, + ByteString sFontFaceName, uint8_t nCharset); int32_t SetTimer(int32_t uElapse, TimerCallback lpTimerFunc); void KillTimer(int32_t nID); - bool IsSHIFTKeyDown(uint32_t nFlag) const; - bool IsCTRLKeyDown(uint32_t nFlag) const; - bool IsALTKeyDown(uint32_t nFlag) const; - private: - CPDFSDK_FormFillEnvironment* const m_pFormFillEnv; + UnownedPtr const m_pFormFillEnv; }; #endif // FPDFSDK_CFX_SYSTEMHANDLER_H_ diff --git a/fpdfsdk/cpdfsdk_annot.cpp b/fpdfsdk/cpdfsdk_annot.cpp index 4dcce48465342f86a8dfc4ff6515ee529aaf07c0..e105ed90fbeb45e8413e8334ac17ef9d39815363 100644 --- a/fpdfsdk/cpdfsdk_annot.cpp +++ b/fpdfsdk/cpdfsdk_annot.cpp @@ -23,7 +23,7 @@ const float kMinHeight = 1.0f; } // namespace CPDFSDK_Annot::CPDFSDK_Annot(CPDFSDK_PageView* pPageView) - : m_pPageView(pPageView), m_bSelected(false) {} + : m_pPageView(pPageView) {} CPDFSDK_Annot::~CPDFSDK_Annot() {} @@ -43,11 +43,11 @@ CPDFXFA_Page* CPDFSDK_Annot::GetPDFXFAPage() { #endif // PDF_ENABLE_XFA -FX_FLOAT CPDFSDK_Annot::GetMinWidth() const { +float CPDFSDK_Annot::GetMinWidth() const { return kMinWidth; } -FX_FLOAT CPDFSDK_Annot::GetMinHeight() const { +float CPDFSDK_Annot::GetMinHeight() const { return kMinHeight; } @@ -73,18 +73,6 @@ CFX_FloatRect CPDFSDK_Annot::GetRect() const { return CFX_FloatRect(); } -void CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - CPDF_RenderOptions* pOptions) {} - -bool CPDFSDK_Annot::IsSelected() { - return m_bSelected; -} - -void CPDFSDK_Annot::SetSelected(bool bSelected) { - m_bSelected = bSelected; -} - UnderlyingPageType* CPDFSDK_Annot::GetUnderlyingPage() { #ifdef PDF_ENABLE_XFA return GetPDFXFAPage(); diff --git a/fpdfsdk/cpdfsdk_annot.h b/fpdfsdk/cpdfsdk_annot.h index 36e7b56612ac9c3e42b2d705c386b6792590a11b..a6c4066ea59b9d50be49999d01695b1829d30e0c 100644 --- a/fpdfsdk/cpdfsdk_annot.h +++ b/fpdfsdk/cpdfsdk_annot.h @@ -10,8 +10,8 @@ #include "core/fpdfdoc/cpdf_aaction.h" #include "core/fpdfdoc/cpdf_annot.h" #include "core/fpdfdoc/cpdf_defaultappearance.h" -#include "core/fxcrt/cfx_observable.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/observable.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/cfx_systemhandler.h" #include "fpdfsdk/fsdk_common.h" #include "fpdfsdk/fsdk_define.h" @@ -22,7 +22,7 @@ class CPDF_Page; class CPDF_RenderOptions; class CPDFSDK_PageView; -class CPDFSDK_Annot : public CFX_Observable { +class CPDFSDK_Annot : public Observable { public: explicit CPDFSDK_Annot(CPDFSDK_PageView* pPageView); virtual ~CPDFSDK_Annot(); @@ -32,18 +32,14 @@ class CPDFSDK_Annot : public CFX_Observable { virtual CXFA_FFWidget* GetXFAWidget() const; #endif // PDF_ENABLE_XFA - virtual FX_FLOAT GetMinWidth() const; - virtual FX_FLOAT GetMinHeight() const; + virtual float GetMinWidth() const; + virtual float GetMinHeight() const; virtual int GetLayoutOrder() const; virtual CPDF_Annot* GetPDFAnnot() const; virtual CPDF_Annot::Subtype GetAnnotSubtype() const; virtual bool IsSignatureWidget() const; virtual CFX_FloatRect GetRect() const; - virtual void SetRect(const CFX_FloatRect& rect); - virtual void Annot_OnDraw(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - CPDF_RenderOptions* pOptions); UnderlyingPageType* GetUnderlyingPage(); CPDF_Page* GetPDFPage(); @@ -51,15 +47,10 @@ class CPDFSDK_Annot : public CFX_Observable { CPDFXFA_Page* GetPDFXFAPage(); #endif // PDF_ENABLE_XFA - void SetPage(CPDFSDK_PageView* pPageView); - CPDFSDK_PageView* GetPageView() const { return m_pPageView; } - - bool IsSelected(); - void SetSelected(bool bSelected); + CPDFSDK_PageView* GetPageView() const { return m_pPageView.Get(); } protected: - CPDFSDK_PageView* m_pPageView; - bool m_bSelected; + UnownedPtr const m_pPageView; }; #endif // FPDFSDK_CPDFSDK_ANNOT_H_ diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp index c4990674ded18d24cc08e43cad4023efaf8d6a7b..2966b4d19bb6b225fd41a1be364e4a28f4fb2693 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp +++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp @@ -17,23 +17,25 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_pageview.h" #include "fpdfsdk/cpdfsdk_widgethandler.h" +#include "third_party/base/ptr_util.h" #ifdef PDF_ENABLE_XFA #include "fpdfsdk/cpdfsdk_xfawidgethandler.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" #endif // PDF_ENABLE_XFA CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr( CPDFSDK_FormFillEnvironment* pFormFillEnv) - : m_pBAAnnotHandler(new CPDFSDK_BAAnnotHandler()), - m_pWidgetHandler(new CPDFSDK_WidgetHandler(pFormFillEnv)), + : m_pBAAnnotHandler(pdfium::MakeUnique()), + m_pWidgetHandler(pdfium::MakeUnique(pFormFillEnv)) #ifdef PDF_ENABLE_XFA - m_pXFAWidgetHandler(new CPDFSDK_XFAWidgetHandler(pFormFillEnv)), + , + m_pXFAWidgetHandler( + pdfium::MakeUnique(pFormFillEnv)) #endif // PDF_ENABLE_XFA - m_pFormFillEnv(pFormFillEnv) { - m_pWidgetHandler->SetFormFiller(m_pFormFillEnv->GetInteractiveFormFiller()); +{ } CPDFSDK_AnnotHandlerMgr::~CPDFSDK_AnnotHandlerMgr() {} @@ -74,6 +76,16 @@ void CPDFSDK_AnnotHandlerMgr::Annot_OnLoad(CPDFSDK_Annot* pAnnot) { GetAnnotHandler(pAnnot)->OnLoad(pAnnot); } +WideString CPDFSDK_AnnotHandlerMgr::Annot_GetSelectedText( + CPDFSDK_Annot* pAnnot) { + return GetAnnotHandler(pAnnot)->GetSelectedText(pAnnot); +} + +void CPDFSDK_AnnotHandlerMgr::Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) { + GetAnnotHandler(pAnnot)->ReplaceSelection(pAnnot, text); +} + IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler( CPDFSDK_Annot* pAnnot) const { return GetAnnotHandler(pAnnot->GetAnnotSubtype()); @@ -198,16 +210,16 @@ bool CPDFSDK_AnnotHandlerMgr::Annot_OnChar(CPDFSDK_Annot* pAnnot, bool CPDFSDK_AnnotHandlerMgr::Annot_OnKeyDown(CPDFSDK_Annot* pAnnot, int nKeyCode, int nFlag) { - if (m_pFormFillEnv->IsCTRLKeyDown(nFlag) || - m_pFormFillEnv->IsALTKeyDown(nFlag)) { + if (CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag) || + CPDFSDK_FormFillEnvironment::IsALTKeyDown(nFlag)) { return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag); } CPDFSDK_PageView* pPage = pAnnot->GetPageView(); CPDFSDK_Annot* pFocusAnnot = pPage->GetFocusAnnot(); if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) { - CPDFSDK_Annot::ObservedPtr pNext( - GetNextAnnot(pFocusAnnot, !m_pFormFillEnv->IsSHIFTKeyDown(nFlag))); + CPDFSDK_Annot::ObservedPtr pNext(GetNextAnnot( + pFocusAnnot, !CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag))); if (pNext && pNext.Get() != pFocusAnnot) { pPage->GetFormFillEnv()->SetFocusAnnot(&pNext); return true; diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h index cbda02cbedfa7b8f95293055973d3d2bd7d565b3..df4e1a224c013c0b45925b0e25f5b7e7d774a015 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.h +++ b/fpdfsdk/cpdfsdk_annothandlermgr.h @@ -11,8 +11,8 @@ #include #include "core/fpdfdoc/cpdf_annot.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/cpdfsdk_annot.h" class CFX_Matrix; @@ -42,6 +42,9 @@ class CPDFSDK_AnnotHandlerMgr { void Annot_OnCreate(CPDFSDK_Annot* pAnnot); void Annot_OnLoad(CPDFSDK_Annot* pAnnot); + WideString Annot_GetSelectedText(CPDFSDK_Annot* pAnnot); + void Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text); + IPDFSDK_AnnotHandler* GetAnnotHandler(CPDFSDK_Annot* pAnnot) const; void Annot_OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, @@ -111,8 +114,6 @@ class CPDFSDK_AnnotHandlerMgr { #ifdef PDF_ENABLE_XFA std::unique_ptr m_pXFAWidgetHandler; #endif // PDF_ENABLE_XFA - - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; }; #endif // FPDFSDK_CPDFSDK_ANNOTHANDLERMGR_H_ diff --git a/fpdfsdk/cpdfsdk_annotiteration.cpp b/fpdfsdk/cpdfsdk_annotiteration.cpp index dd99ade5092f5e659e6baa418f0f2b0791a17c04..d2569506584e4be800f51255c3877894f5c164da 100644 --- a/fpdfsdk/cpdfsdk_annotiteration.cpp +++ b/fpdfsdk/cpdfsdk_annotiteration.cpp @@ -33,7 +33,7 @@ CPDFSDK_AnnotIteration::CPDFSDK_AnnotIteration(CPDFSDK_PageView* pPageView, std::reverse(copiedList.begin(), copiedList.end()); m_List.reserve(copiedList.size()); - for (const auto& pAnnot : copiedList) + for (auto* pAnnot : copiedList) m_List.emplace_back(pAnnot); } diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp index 3eedf1502c03e1e0298b68e84a93059de282130a..a1578804cfd1f9ea4c4fc95aa8e66ddda9ddc45c 100644 --- a/fpdfsdk/cpdfsdk_baannot.cpp +++ b/fpdfsdk/cpdfsdk_baannot.cpp @@ -27,7 +27,7 @@ CPDFSDK_BAAnnot::CPDFSDK_BAAnnot(CPDF_Annot* pAnnot, CPDFSDK_BAAnnot::~CPDFSDK_BAAnnot() {} CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const { - return m_pAnnot; + return m_pAnnot.Get(); } CPDF_Annot* CPDFSDK_BAAnnot::GetPDFPopupAnnot() const { @@ -38,6 +38,13 @@ CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const { return m_pAnnot->GetAnnotDict(); } +CPDF_Dictionary* CPDFSDK_BAAnnot::GetAPDict() const { + CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); + if (!pAPDict) + pAPDict = m_pAnnot->GetAnnotDict()->SetNewFor("AP"); + return pAPDict; +} + void CPDFSDK_BAAnnot::SetRect(const CFX_FloatRect& rect) { ASSERT(rect.right - rect.left >= GetMinWidth()); ASSERT(rect.top - rect.bottom >= GetMinHeight()); @@ -54,10 +61,10 @@ CPDF_Annot::Subtype CPDFSDK_BAAnnot::GetAnnotSubtype() const { } void CPDFSDK_BAAnnot::DrawAppearance(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, + const CFX_Matrix& mtUser2Device, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) { - m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, + m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, mtUser2Device, mode, pOptions); } @@ -71,7 +78,7 @@ bool CPDFSDK_BAAnnot::IsAppearanceValid(CPDF_Annot::AppearanceMode mode) { return false; // Choose the right sub-ap - const FX_CHAR* ap_entry = "N"; + const char* ap_entry = "N"; if (mode == CPDF_Annot::Down) ap_entry = "D"; else if (mode == CPDF_Annot::Rollover) @@ -94,7 +101,7 @@ void CPDFSDK_BAAnnot::ClearCachedAP() { m_pAnnot->ClearCachedAP(); } -void CPDFSDK_BAAnnot::SetContents(const CFX_WideString& sContents) { +void CPDFSDK_BAAnnot::SetContents(const WideString& sContents) { if (sContents.IsEmpty()) { m_pAnnot->GetAnnotDict()->RemoveFor("Contents"); } else { @@ -103,11 +110,11 @@ void CPDFSDK_BAAnnot::SetContents(const CFX_WideString& sContents) { } } -CFX_WideString CPDFSDK_BAAnnot::GetContents() const { +WideString CPDFSDK_BAAnnot::GetContents() const { return m_pAnnot->GetAnnotDict()->GetUnicodeTextFor("Contents"); } -void CPDFSDK_BAAnnot::SetAnnotName(const CFX_WideString& sName) { +void CPDFSDK_BAAnnot::SetAnnotName(const WideString& sName) { if (sName.IsEmpty()) { m_pAnnot->GetAnnotDict()->RemoveFor("NM"); } else { @@ -116,13 +123,13 @@ void CPDFSDK_BAAnnot::SetAnnotName(const CFX_WideString& sName) { } } -CFX_WideString CPDFSDK_BAAnnot::GetAnnotName() const { +WideString CPDFSDK_BAAnnot::GetAnnotName() const { return m_pAnnot->GetAnnotDict()->GetUnicodeTextFor("NM"); } void CPDFSDK_BAAnnot::SetModifiedDate(const FX_SYSTEMTIME& st) { CPDFSDK_DateTime dt(st); - CFX_ByteString str = dt.ToPDFDateTimeString(); + ByteString str = dt.ToPDFDateTimeString(); if (str.IsEmpty()) m_pAnnot->GetAnnotDict()->RemoveFor("M"); else @@ -131,7 +138,7 @@ void CPDFSDK_BAAnnot::SetModifiedDate(const FX_SYSTEMTIME& st) { FX_SYSTEMTIME CPDFSDK_BAAnnot::GetModifiedDate() const { FX_SYSTEMTIME systime; - CFX_ByteString str = m_pAnnot->GetAnnotDict()->GetStringFor("M"); + ByteString str = m_pAnnot->GetAnnotDict()->GetStringFor("M"); CPDFSDK_DateTime dt(str); dt.ToSystemTime(systime); return systime; @@ -146,14 +153,14 @@ uint32_t CPDFSDK_BAAnnot::GetFlags() const { return m_pAnnot->GetAnnotDict()->GetIntegerFor("F"); } -void CPDFSDK_BAAnnot::SetAppState(const CFX_ByteString& str) { +void CPDFSDK_BAAnnot::SetAppState(const ByteString& str) { if (str.IsEmpty()) m_pAnnot->GetAnnotDict()->RemoveFor("AS"); else m_pAnnot->GetAnnotDict()->SetNewFor("AS", str, false); } -CFX_ByteString CPDFSDK_BAAnnot::GetAppState() const { +ByteString CPDFSDK_BAAnnot::GetAppState() const { return m_pAnnot->GetAnnotDict()->GetStringFor("AS"); } @@ -218,7 +225,7 @@ void CPDFSDK_BAAnnot::SetBorderStyle(BorderStyle nStyle) { BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const { CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDictFor("BS"); if (pBSDict) { - CFX_ByteString sBorderStyle = pBSDict->GetStringFor("S", "S"); + ByteString sBorderStyle = pBSDict->GetStringFor("S", "S"); if (sBorderStyle == "S") return BorderStyle::SOLID; if (sBorderStyle == "D") @@ -245,11 +252,11 @@ BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const { void CPDFSDK_BAAnnot::SetColor(FX_COLORREF color) { CPDF_Array* pArray = m_pAnnot->GetAnnotDict()->SetNewFor("C"); - pArray->AddNew(static_cast(FXSYS_GetRValue(color)) / + pArray->AddNew(static_cast(FXSYS_GetRValue(color)) / 255.0f); - pArray->AddNew(static_cast(FXSYS_GetGValue(color)) / + pArray->AddNew(static_cast(FXSYS_GetGValue(color)) / 255.0f); - pArray->AddNew(static_cast(FXSYS_GetBValue(color)) / + pArray->AddNew(static_cast(FXSYS_GetBValue(color)) / 255.0f); } @@ -261,28 +268,28 @@ bool CPDFSDK_BAAnnot::GetColor(FX_COLORREF& color) const { if (CPDF_Array* pEntry = m_pAnnot->GetAnnotDict()->GetArrayFor("C")) { size_t nCount = pEntry->GetCount(); if (nCount == 1) { - FX_FLOAT g = pEntry->GetNumberAt(0) * 255; + float g = pEntry->GetNumberAt(0) * 255; color = FXSYS_RGB((int)g, (int)g, (int)g); return true; } else if (nCount == 3) { - FX_FLOAT r = pEntry->GetNumberAt(0) * 255; - FX_FLOAT g = pEntry->GetNumberAt(1) * 255; - FX_FLOAT b = pEntry->GetNumberAt(2) * 255; + float r = pEntry->GetNumberAt(0) * 255; + float g = pEntry->GetNumberAt(1) * 255; + float b = pEntry->GetNumberAt(2) * 255; color = FXSYS_RGB((int)r, (int)g, (int)b); return true; } else if (nCount == 4) { - FX_FLOAT c = pEntry->GetNumberAt(0); - FX_FLOAT m = pEntry->GetNumberAt(1); - FX_FLOAT y = pEntry->GetNumberAt(2); - FX_FLOAT k = pEntry->GetNumberAt(3); + float c = pEntry->GetNumberAt(0); + float m = pEntry->GetNumberAt(1); + float y = pEntry->GetNumberAt(2); + float k = pEntry->GetNumberAt(3); - FX_FLOAT r = 1.0f - std::min(1.0f, c + k); - FX_FLOAT g = 1.0f - std::min(1.0f, m + k); - FX_FLOAT b = 1.0f - std::min(1.0f, y + k); + float r = 1.0f - std::min(1.0f, c + k); + float g = 1.0f - std::min(1.0f, m + k); + float b = 1.0f - std::min(1.0f, y + k); color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255)); @@ -293,50 +300,6 @@ bool CPDFSDK_BAAnnot::GetColor(FX_COLORREF& color) const { return false; } -void CPDFSDK_BAAnnot::WriteAppearance(const CFX_ByteString& sAPType, - const CFX_FloatRect& rcBBox, - const CFX_Matrix& matrix, - const CFX_ByteString& sContents, - const CFX_ByteString& sAPState) { - CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); - if (!pAPDict) - pAPDict = m_pAnnot->GetAnnotDict()->SetNewFor("AP"); - - CPDF_Stream* pStream = nullptr; - CPDF_Dictionary* pParentDict = nullptr; - if (sAPState.IsEmpty()) { - pParentDict = pAPDict; - pStream = pAPDict->GetStreamFor(sAPType); - } else { - CPDF_Dictionary* pAPTypeDict = pAPDict->GetDictFor(sAPType); - if (!pAPTypeDict) - pAPTypeDict = pAPDict->SetNewFor(sAPType); - - pParentDict = pAPTypeDict; - pStream = pAPTypeDict->GetStreamFor(sAPState); - } - - if (!pStream) { - CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); - pStream = pDoc->NewIndirect(); - pParentDict->SetNewFor(sAPType, pDoc, pStream->GetObjNum()); - } - - CPDF_Dictionary* pStreamDict = pStream->GetDict(); - if (!pStreamDict) { - auto pNewDict = pdfium::MakeUnique( - m_pAnnot->GetDocument()->GetByteStringPool()); - pStreamDict = pNewDict.get(); - pStreamDict->SetNewFor("Type", "XObject"); - pStreamDict->SetNewFor("Subtype", "Form"); - pStreamDict->SetNewFor("FormType", 1); - pStream->InitStream(nullptr, 0, std::move(pNewDict)); - } - pStreamDict->SetMatrixFor("Matrix", matrix); - pStreamDict->SetRectFor("BBox", rcBBox); - pStream->SetData((uint8_t*)sContents.c_str(), sContents.GetLength()); -} - bool CPDFSDK_BAAnnot::IsVisible() const { uint32_t nFlags = GetFlags(); return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || @@ -383,18 +346,17 @@ CPDF_Action CPDFSDK_BAAnnot::GetAAction(CPDF_AAction::AActionType eAAT) { if (eAAT == CPDF_AAction::ButtonUp) return GetAction(); - return CPDF_Action(); -} - -void CPDFSDK_BAAnnot::Annot_OnDraw(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - CPDF_RenderOptions* pOptions) { - m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal); - m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, - CPDF_Annot::Normal, nullptr); + return CPDF_Action(nullptr); } void CPDFSDK_BAAnnot::SetOpenState(bool bOpenState) { if (CPDF_Annot* pAnnot = m_pAnnot->GetPopupAnnot()) pAnnot->SetOpenState(bOpenState); } + +int CPDFSDK_BAAnnot::GetLayoutOrder() const { + if (m_pAnnot->GetSubtype() == CPDF_Annot::Subtype::POPUP) + return 1; + + return CPDFSDK_Annot::GetLayoutOrder(); +} diff --git a/fpdfsdk/cpdfsdk_baannot.h b/fpdfsdk/cpdfsdk_baannot.h index 2da5723eb4e6a374b4363e4804df225feef758a4..ac3c0cb384ccf27da316fc6eeb838f9ae7b7eeed 100644 --- a/fpdfsdk/cpdfsdk_baannot.h +++ b/fpdfsdk/cpdfsdk_baannot.h @@ -32,18 +32,17 @@ class CPDFSDK_BAAnnot : public CPDFSDK_Annot { void SetRect(const CFX_FloatRect& rect) override; CFX_FloatRect GetRect() const override; CPDF_Annot* GetPDFAnnot() const override; - void Annot_OnDraw(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - CPDF_RenderOptions* pOptions) override; CPDF_Dictionary* GetAnnotDict() const; CPDF_Annot* GetPDFPopupAnnot() const; - void SetContents(const CFX_WideString& sContents); - CFX_WideString GetContents() const; + CPDF_Dictionary* GetAPDict() const; - void SetAnnotName(const CFX_WideString& sName); - CFX_WideString GetAnnotName() const; + void SetContents(const WideString& sContents); + WideString GetContents() const; + + void SetAnnotName(const WideString& sName); + WideString GetAnnotName() const; void SetModifiedDate(const FX_SYSTEMTIME& st); FX_SYSTEMTIME GetModifiedDate() const; @@ -51,8 +50,8 @@ class CPDFSDK_BAAnnot : public CPDFSDK_Annot { void SetFlags(uint32_t nFlags); uint32_t GetFlags() const; - void SetAppState(const CFX_ByteString& str); - CFX_ByteString GetAppState() const; + void SetAppState(const ByteString& str); + ByteString GetAppState() const; void SetStructParent(int key); int GetStructParent() const; @@ -81,7 +80,7 @@ class CPDFSDK_BAAnnot : public CPDFSDK_Annot { virtual bool IsAppearanceValid(); virtual bool IsAppearanceValid(CPDF_Annot::AppearanceMode mode); virtual void DrawAppearance(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, + const CFX_Matrix& mtUser2Device, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions); @@ -91,16 +90,12 @@ class CPDFSDK_BAAnnot : public CPDFSDK_Annot { void ClearCachedAP(); - void WriteAppearance(const CFX_ByteString& sAPType, - const CFX_FloatRect& rcBBox, - const CFX_Matrix& matrix, - const CFX_ByteString& sContents, - const CFX_ByteString& sAPState = ""); - void SetOpenState(bool bState); + int GetLayoutOrder() const override; + protected: - CPDF_Annot* const m_pAnnot; + UnownedPtr const m_pAnnot; }; #endif // FPDFSDK_CPDFSDK_BAANNOT_H_ diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp index fa83932a81519e50dad1a6a12ab992dd20784e74..027527ec5f20b90f807e74290a0e8bf400054d53 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.cpp +++ b/fpdfsdk/cpdfsdk_baannothandler.cpp @@ -73,7 +73,7 @@ void CPDFSDK_BAAnnotHandler::OnDraw(CPDFSDK_PageView* pPageView, #endif // PDF_ENABLE_XFA if (bDrawAnnots && pAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP) { static_cast(pAnnot)->DrawAppearance( - pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); + pDevice, *pUser2Device, CPDF_Annot::Normal, nullptr); } } @@ -193,6 +193,13 @@ CFX_FloatRect CPDFSDK_BAAnnotHandler::GetViewBBox(CPDFSDK_PageView* pPageView, return pAnnot->GetRect(); } +WideString CPDFSDK_BAAnnotHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) { + return WideString(); +} + +void CPDFSDK_BAAnnotHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) {} + bool CPDFSDK_BAAnnotHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) { diff --git a/fpdfsdk/cpdfsdk_baannothandler.h b/fpdfsdk/cpdfsdk_baannothandler.h index d5f170f452805716ebd0b998d8de63f43bcc2cff..7bf8034a54ad7c92046260423b426620b9289844 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.h +++ b/fpdfsdk/cpdfsdk_baannothandler.h @@ -7,7 +7,6 @@ #ifndef FPDFSDK_CPDFSDK_BAANNOTHANDLER_H_ #define FPDFSDK_CPDFSDK_BAANNOTHANDLER_H_ -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" #include "fpdfsdk/ipdfsdk_annothandler.h" @@ -37,6 +36,8 @@ class CPDFSDK_BAAnnotHandler : public IPDFSDK_AnnotHandler { void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override; CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; + WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override; bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) override; diff --git a/fpdfsdk/cpdfsdk_datetime.cpp b/fpdfsdk/cpdfsdk_datetime.cpp index 72f50a6b44bcfd05230e0d117db9b5100a8a5fcd..332ae8e62ea195c49f2a72f35841afed6cb32fac 100644 --- a/fpdfsdk/cpdfsdk_datetime.cpp +++ b/fpdfsdk/cpdfsdk_datetime.cpp @@ -6,7 +6,7 @@ #include "fpdfsdk/cpdfsdk_datetime.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" namespace { @@ -63,7 +63,7 @@ CPDFSDK_DateTime::CPDFSDK_DateTime() { ResetDateTime(); } -CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) { +CPDFSDK_DateTime::CPDFSDK_DateTime(const ByteString& dtStr) { ResetDateTime(); FromPDFDateTimeString(dtStr); } @@ -129,7 +129,7 @@ time_t CPDFSDK_DateTime::ToTime_t() const { } CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( - const CFX_ByteString& dtStr) { + const ByteString& dtStr) { int strLength = dtStr.GetLength(); if (strLength <= 0) return *this; @@ -143,10 +143,10 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( int j = 0; int k = 0; - FX_CHAR ch; + char ch; while (i < strLength && j < 4) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -160,7 +160,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -174,7 +174,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -188,7 +188,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -202,7 +202,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -216,7 +216,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -237,7 +237,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -253,7 +253,7 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; - k = k * 10 + FXSYS_toDecimalDigit(ch); + k = k * 10 + FXSYS_DecimalCharToInt(ch); j++; if (!std::isdigit(ch)) break; @@ -263,34 +263,29 @@ CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( return *this; } -CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() { - CFX_ByteString str1; - str1.Format("%04d-%02u-%02u %02u:%02u:%02u ", m_year, m_month, m_day, m_hour, - m_minute, m_second); - if (m_tzHour < 0) - str1 += "-"; - else - str1 += "+"; - CFX_ByteString str2; - str2.Format("%02d:%02u", std::abs(static_cast(m_tzHour)), m_tzMinute); - return str1 + str2; +ByteString CPDFSDK_DateTime::ToCommonDateTimeString() { + return ByteString::Format("%04d-%02u-%02u %02u:%02u:%02u ", m_year, m_month, + m_day, m_hour, m_minute, m_second) + + (m_tzHour < 0 ? "-" : "+") + + ByteString::Format("%02d:%02u", std::abs(static_cast(m_tzHour)), + m_tzMinute); } -CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() { - CFX_ByteString dtStr; +ByteString CPDFSDK_DateTime::ToPDFDateTimeString() { + ByteString dtStr; char tempStr[32]; memset(tempStr, 0, sizeof(tempStr)); FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02u%02u%02u%02u%02u", m_year, m_month, m_day, m_hour, m_minute, m_second); - dtStr = CFX_ByteString(tempStr); + dtStr = ByteString(tempStr); if (m_tzHour < 0) - dtStr += CFX_ByteString("-"); + dtStr += ByteString("-"); else - dtStr += CFX_ByteString("+"); + dtStr += ByteString("+"); memset(tempStr, 0, sizeof(tempStr)); FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02u'", std::abs(static_cast(m_tzHour)), m_tzMinute); - dtStr += CFX_ByteString(tempStr); + dtStr += ByteString(tempStr); return dtStr; } diff --git a/fpdfsdk/cpdfsdk_datetime.h b/fpdfsdk/cpdfsdk_datetime.h index 6b612b27bc571a03780cb77fc41a1cb6708c55be..cbd3c36d4472734f3d957b30694d8c38b557b0af 100644 --- a/fpdfsdk/cpdfsdk_datetime.h +++ b/fpdfsdk/cpdfsdk_datetime.h @@ -7,7 +7,7 @@ #ifndef FPDFSDK_CPDFSDK_DATETIME_H_ #define FPDFSDK_CPDFSDK_DATETIME_H_ -#if _FX_OS_ == _FX_ANDROID_ +#if _FX_OS_ == _FX_OS_ANDROID_ #include #else #include @@ -18,16 +18,16 @@ class CPDFSDK_DateTime { public: CPDFSDK_DateTime(); - explicit CPDFSDK_DateTime(const CFX_ByteString& dtStr); + explicit CPDFSDK_DateTime(const ByteString& dtStr); explicit CPDFSDK_DateTime(const FX_SYSTEMTIME& st); CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime); bool operator==(const CPDFSDK_DateTime& datetime) const; bool operator!=(const CPDFSDK_DateTime& datetime) const; - CPDFSDK_DateTime& FromPDFDateTimeString(const CFX_ByteString& dtStr); - CFX_ByteString ToCommonDateTimeString(); - CFX_ByteString ToPDFDateTimeString(); + CPDFSDK_DateTime& FromPDFDateTimeString(const ByteString& dtStr); + ByteString ToCommonDateTimeString(); + ByteString ToPDFDateTimeString(); void ToSystemTime(FX_SYSTEMTIME& st); time_t ToTime_t() const; CPDFSDK_DateTime ToGMT() const; diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp index 4ef766d9f861f3e0a84ffa08420336b61d46746d..955c184e95bb63d0528efa30f77e87dba4e00ad6 100644 --- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp +++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp @@ -7,6 +7,7 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include +#include #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfdoc/cpdf_docjsactions.h" @@ -16,14 +17,14 @@ #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/fsdk_actionhandler.h" -#include "fpdfsdk/javascript/ijs_runtime.h" +#include "fxjs/ijs_runtime.h" #include "third_party/base/ptr_util.h" namespace { // NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken // since modifying the result would impact |bsUTF16LE|. -FPDF_WIDESTRING AsFPDFWideString(CFX_ByteString* bsUTF16LE) { +FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE) { return reinterpret_cast( bsUTF16LE->GetBuffer(bsUTF16LE->GetLength())); } @@ -35,7 +36,7 @@ CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment( FPDF_FORMFILLINFO* pFFinfo) : m_pInfo(pFFinfo), m_pUnderlyingDoc(pDoc), - m_pSysHandler(new CFX_SystemHandler(this)), + m_pSysHandler(pdfium::MakeUnique(this)), m_bChangeMask(false), m_bBeingDestroyed(false) {} @@ -60,25 +61,25 @@ CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() { m_pInfo->Release(m_pInfo); } -int CPDFSDK_FormFillEnvironment::JS_appAlert(const FX_WCHAR* Msg, - const FX_WCHAR* Title, +int CPDFSDK_FormFillEnvironment::JS_appAlert(const wchar_t* Msg, + const wchar_t* Title, uint32_t Type, uint32_t Icon) { if (!m_pInfo || !m_pInfo->m_pJsPlatform || !m_pInfo->m_pJsPlatform->app_alert) { return -1; } - CFX_ByteString bsMsg = CFX_WideString(Msg).UTF16LE_Encode(); - CFX_ByteString bsTitle = CFX_WideString(Title).UTF16LE_Encode(); + ByteString bsMsg = WideString(Msg).UTF16LE_Encode(); + ByteString bsTitle = WideString(Title).UTF16LE_Encode(); return m_pInfo->m_pJsPlatform->app_alert( m_pInfo->m_pJsPlatform, AsFPDFWideString(&bsMsg), AsFPDFWideString(&bsTitle), Type, Icon); } -int CPDFSDK_FormFillEnvironment::JS_appResponse(const FX_WCHAR* Question, - const FX_WCHAR* Title, - const FX_WCHAR* Default, - const FX_WCHAR* cLabel, +int CPDFSDK_FormFillEnvironment::JS_appResponse(const wchar_t* Question, + const wchar_t* Title, + const wchar_t* Default, + const wchar_t* cLabel, FPDF_BOOL bPassword, void* response, int length) { @@ -86,10 +87,10 @@ int CPDFSDK_FormFillEnvironment::JS_appResponse(const FX_WCHAR* Question, !m_pInfo->m_pJsPlatform->app_response) { return -1; } - CFX_ByteString bsQuestion = CFX_WideString(Question).UTF16LE_Encode(); - CFX_ByteString bsTitle = CFX_WideString(Title).UTF16LE_Encode(); - CFX_ByteString bsDefault = CFX_WideString(Default).UTF16LE_Encode(); - CFX_ByteString bsLabel = CFX_WideString(cLabel).UTF16LE_Encode(); + ByteString bsQuestion = WideString(Question).UTF16LE_Encode(); + ByteString bsTitle = WideString(Title).UTF16LE_Encode(); + ByteString bsDefault = WideString(Default).UTF16LE_Encode(); + ByteString bsLabel = WideString(cLabel).UTF16LE_Encode(); return m_pInfo->m_pJsPlatform->app_response( m_pInfo->m_pJsPlatform, AsFPDFWideString(&bsQuestion), AsFPDFWideString(&bsTitle), AsFPDFWideString(&bsDefault), @@ -104,54 +105,54 @@ void CPDFSDK_FormFillEnvironment::JS_appBeep(int nType) { m_pInfo->m_pJsPlatform->app_beep(m_pInfo->m_pJsPlatform, nType); } -CFX_WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() { +WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() { if (!m_pInfo || !m_pInfo->m_pJsPlatform || !m_pInfo->m_pJsPlatform->Field_browse) { - return CFX_WideString(); + return WideString(); } const int nRequiredLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, nullptr, 0); if (nRequiredLen <= 0) - return CFX_WideString(); + return WideString(); - std::unique_ptr pBuff(new char[nRequiredLen]); - memset(pBuff.get(), 0, nRequiredLen); + std::vector pBuff(nRequiredLen); const int nActualLen = m_pInfo->m_pJsPlatform->Field_browse( - m_pInfo->m_pJsPlatform, pBuff.get(), nRequiredLen); + m_pInfo->m_pJsPlatform, pBuff.data(), nRequiredLen); if (nActualLen <= 0 || nActualLen > nRequiredLen) - return CFX_WideString(); + return WideString(); - return CFX_WideString::FromLocal(CFX_ByteStringC(pBuff.get(), nActualLen)); + pBuff.resize(nActualLen); + return WideString::FromLocal(ByteStringView(pBuff)); } -CFX_WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() { +WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() { if (!m_pInfo || !m_pInfo->m_pJsPlatform || !m_pInfo->m_pJsPlatform->Doc_getFilePath) { - return CFX_WideString(); + return WideString(); } const int nRequiredLen = m_pInfo->m_pJsPlatform->Doc_getFilePath( m_pInfo->m_pJsPlatform, nullptr, 0); if (nRequiredLen <= 0) - return CFX_WideString(); + return WideString(); - std::unique_ptr pBuff(new char[nRequiredLen]); - memset(pBuff.get(), 0, nRequiredLen); + std::vector pBuff(nRequiredLen); const int nActualLen = m_pInfo->m_pJsPlatform->Doc_getFilePath( - m_pInfo->m_pJsPlatform, pBuff.get(), nRequiredLen); + m_pInfo->m_pJsPlatform, pBuff.data(), nRequiredLen); if (nActualLen <= 0 || nActualLen > nRequiredLen) - return CFX_WideString(); + return WideString(); - return CFX_WideString::FromLocal(CFX_ByteStringC(pBuff.get(), nActualLen)); + pBuff.resize(nActualLen); + return WideString::FromLocal(ByteStringView(pBuff)); } void CPDFSDK_FormFillEnvironment::JS_docSubmitForm(void* formData, int length, - const FX_WCHAR* URL) { + const wchar_t* URL) { if (!m_pInfo || !m_pInfo->m_pJsPlatform || !m_pInfo->m_pJsPlatform->Doc_submitForm) { return; } - CFX_ByteString bsDestination = CFX_WideString(URL).UTF16LE_Encode(); + ByteString bsDestination = WideString(URL).UTF16LE_Encode(); m_pInfo->m_pJsPlatform->Doc_submitForm(m_pInfo->m_pJsPlatform, formData, length, AsFPDFWideString(&bsDestination)); @@ -160,20 +161,20 @@ void CPDFSDK_FormFillEnvironment::JS_docSubmitForm(void* formData, void CPDFSDK_FormFillEnvironment::JS_docmailForm(void* mailData, int length, FPDF_BOOL bUI, - const FX_WCHAR* To, - const FX_WCHAR* Subject, - const FX_WCHAR* CC, - const FX_WCHAR* BCC, - const FX_WCHAR* Msg) { + const wchar_t* To, + const wchar_t* Subject, + const wchar_t* CC, + const wchar_t* BCC, + const wchar_t* Msg) { if (!m_pInfo || !m_pInfo->m_pJsPlatform || !m_pInfo->m_pJsPlatform->Doc_mail) { return; } - CFX_ByteString bsTo = CFX_WideString(To).UTF16LE_Encode(); - CFX_ByteString bsSubject = CFX_WideString(Subject).UTF16LE_Encode(); - CFX_ByteString bsCC = CFX_WideString(CC).UTF16LE_Encode(); - CFX_ByteString bsBcc = CFX_WideString(BCC).UTF16LE_Encode(); - CFX_ByteString bsMsg = CFX_WideString(Msg).UTF16LE_Encode(); + ByteString bsTo = WideString(To).UTF16LE_Encode(); + ByteString bsSubject = WideString(Subject).UTF16LE_Encode(); + ByteString bsCC = WideString(CC).UTF16LE_Encode(); + ByteString bsBcc = WideString(BCC).UTF16LE_Encode(); + ByteString bsMsg = WideString(Msg).UTF16LE_Encode(); m_pInfo->m_pJsPlatform->Doc_mail( m_pInfo->m_pJsPlatform, mailData, length, bUI, AsFPDFWideString(&bsTo), AsFPDFWideString(&bsSubject), AsFPDFWideString(&bsCC), @@ -219,7 +220,7 @@ CPDFSDK_AnnotHandlerMgr* CPDFSDK_FormFillEnvironment::GetAnnotHandlerMgr() { return m_pAnnotHandlerMgr.get(); } -CPDFSDK_ActionHandler* CPDFSDK_FormFillEnvironment::GetActionHander() { +CPDFSDK_ActionHandler* CPDFSDK_FormFillEnvironment::GetActionHandler() { if (!m_pActionHandler) m_pActionHandler = pdfium::MakeUnique(); return m_pActionHandler.get(); @@ -232,7 +233,7 @@ CPDFSDK_FormFillEnvironment::GetInteractiveFormFiller() { return m_pFormFiller.get(); } -void CPDFSDK_FormFillEnvironment::Invalidate(FPDF_PAGE page, +void CPDFSDK_FormFillEnvironment::Invalidate(UnderlyingPageType* page, const FX_RECT& rect) { if (m_pInfo && m_pInfo->FFI_Invalidate) { m_pInfo->FFI_Invalidate(m_pInfo, page, rect.left, rect.top, rect.right, @@ -241,7 +242,7 @@ void CPDFSDK_FormFillEnvironment::Invalidate(FPDF_PAGE page, } void CPDFSDK_FormFillEnvironment::OutputSelectedRect( - FPDF_PAGE page, + UnderlyingPageType* page, const CFX_FloatRect& rect) { if (m_pInfo && m_pInfo->FFI_OutputSelectedRect) { m_pInfo->FFI_OutputSelectedRect(m_pInfo, page, rect.left, rect.top, @@ -288,33 +289,14 @@ void CPDFSDK_FormFillEnvironment::OnChange() { m_pInfo->FFI_OnChange(m_pInfo); } -bool CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(uint32_t nFlag) const { - return (nFlag & FWL_EVENTFLAG_ShiftKey) != 0; -} - -bool CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(uint32_t nFlag) const { - return (nFlag & FWL_EVENTFLAG_ControlKey) != 0; -} - -bool CPDFSDK_FormFillEnvironment::IsALTKeyDown(uint32_t nFlag) const { - return (nFlag & FWL_EVENTFLAG_AltKey) != 0; -} - -FPDF_PAGE CPDFSDK_FormFillEnvironment::GetPage(FPDF_DOCUMENT document, - int nPageIndex) { - if (m_pInfo && m_pInfo->FFI_GetPage) - return m_pInfo->FFI_GetPage(m_pInfo, document, nPageIndex); - return nullptr; -} - -FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage(FPDF_DOCUMENT document) { +FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage( + UnderlyingDocumentType* document) { if (m_pInfo && m_pInfo->FFI_GetCurrentPage) return m_pInfo->FFI_GetCurrentPage(m_pInfo, document); return nullptr; } -void CPDFSDK_FormFillEnvironment::ExecuteNamedAction( - const FX_CHAR* namedAction) { +void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(const char* namedAction) { if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction) m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction); } @@ -327,7 +309,7 @@ void CPDFSDK_FormFillEnvironment::OnSetFieldInputFocus( m_pInfo->FFI_SetTextFieldFocus(m_pInfo, focusText, nTextLen, bFocus); } -void CPDFSDK_FormFillEnvironment::DoURIAction(const FX_CHAR* bsURI) { +void CPDFSDK_FormFillEnvironment::DoURIAction(const char* bsURI) { if (m_pInfo && m_pInfo->FFI_DoURIAction) m_pInfo->FFI_DoURIAction(m_pInfo, bsURI); } @@ -343,7 +325,7 @@ void CPDFSDK_FormFillEnvironment::DoGoToAction(int nPageIndex, } #ifdef PDF_ENABLE_XFA -void CPDFSDK_FormFillEnvironment::DisplayCaret(FPDF_PAGE page, +void CPDFSDK_FormFillEnvironment::DisplayCaret(CPDFXFA_Page* page, FPDF_BOOL bVisible, double left, double top, @@ -355,53 +337,49 @@ void CPDFSDK_FormFillEnvironment::DisplayCaret(FPDF_PAGE page, } } -int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex(FPDF_DOCUMENT document) { +int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex( + CPDFXFA_Context* document) { if (!m_pInfo || !m_pInfo->FFI_GetCurrentPageIndex) return -1; return m_pInfo->FFI_GetCurrentPageIndex(m_pInfo, document); } -void CPDFSDK_FormFillEnvironment::SetCurrentPage(FPDF_DOCUMENT document, +void CPDFSDK_FormFillEnvironment::SetCurrentPage(CPDFXFA_Context* document, int iCurPage) { if (m_pInfo && m_pInfo->FFI_SetCurrentPage) m_pInfo->FFI_SetCurrentPage(m_pInfo, document, iCurPage); } -CFX_WideString CPDFSDK_FormFillEnvironment::GetPlatform() { +WideString CPDFSDK_FormFillEnvironment::GetPlatform() { if (!m_pInfo || !m_pInfo->FFI_GetPlatform) - return L""; + return WideString(); int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0); if (nRequiredLen <= 0) - return L""; + return WideString(); - char* pbuff = new char[nRequiredLen]; - memset(pbuff, 0, nRequiredLen); - int nActualLen = m_pInfo->FFI_GetPlatform(m_pInfo, pbuff, nRequiredLen); - if (nActualLen <= 0 || nActualLen > nRequiredLen) { - delete[] pbuff; - return L""; - } - CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen); - CFX_WideString wsRet = CFX_WideString::FromUTF16LE( - (unsigned short*)bsRet.GetBuffer(bsRet.GetLength()), - bsRet.GetLength() / sizeof(unsigned short)); - delete[] pbuff; - return wsRet; + std::vector pBuff(nRequiredLen); + int nActualLen = + m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen); + if (nActualLen <= 0 || nActualLen > nRequiredLen) + return WideString(); + + return WideString::FromUTF16LE(reinterpret_cast(pBuff.data()), + nActualLen / sizeof(uint16_t)); } -void CPDFSDK_FormFillEnvironment::GotoURL(FPDF_DOCUMENT document, - const CFX_WideStringC& wsURL) { +void CPDFSDK_FormFillEnvironment::GotoURL(CPDFXFA_Context* document, + const WideStringView& wsURL) { if (!m_pInfo || !m_pInfo->FFI_GotoURL) return; - CFX_ByteString bsTo = CFX_WideString(wsURL).UTF16LE_Encode(); + ByteString bsTo = WideString(wsURL).UTF16LE_Encode(); FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(wsURL.GetLength()); m_pInfo->FFI_GotoURL(m_pInfo, document, pTo); - bsTo.ReleaseBuffer(); + bsTo.ReleaseBuffer(bsTo.GetStringLength()); } -void CPDFSDK_FormFillEnvironment::GetPageViewRect(FPDF_PAGE page, +void CPDFSDK_FormFillEnvironment::GetPageViewRect(CPDFXFA_Page* page, FS_RECTF& dstRect) { if (!m_pInfo || !m_pInfo->FFI_GetPageViewRect) return; @@ -411,14 +389,16 @@ void CPDFSDK_FormFillEnvironment::GetPageViewRect(FPDF_PAGE page, double right; double bottom; m_pInfo->FFI_GetPageViewRect(m_pInfo, page, &left, &top, &right, &bottom); + if (top < bottom) + std::swap(top, bottom); dstRect.left = static_cast(left); - dstRect.top = static_cast(top < bottom ? bottom : top); - dstRect.bottom = static_cast(top < bottom ? top : bottom); + dstRect.top = static_cast(top); + dstRect.bottom = static_cast(bottom); dstRect.right = static_cast(right); } -bool CPDFSDK_FormFillEnvironment::PopupMenu(FPDF_PAGE page, +bool CPDFSDK_FormFillEnvironment::PopupMenu(CPDFXFA_Page* page, FPDF_WIDGET hWidget, int menuFlag, CFX_PointF pt) { @@ -461,12 +441,12 @@ FPDF_FILEHANDLER* CPDFSDK_FormFillEnvironment::OpenFile(int fileType, return nullptr; } -CFX_RetainPtr -CPDFSDK_FormFillEnvironment::DownloadFromURL(const FX_WCHAR* url) { +RetainPtr CPDFSDK_FormFillEnvironment::DownloadFromURL( + const wchar_t* url) { if (!m_pInfo || !m_pInfo->FFI_DownloadFromURL) return nullptr; - CFX_ByteString bstrURL = CFX_WideString(url).UTF16LE_Encode(); + ByteString bstrURL = WideString(url).UTF16LE_Encode(); FPDF_WIDESTRING wsURL = (FPDF_WIDESTRING)bstrURL.GetBuffer(bstrURL.GetLength()); @@ -474,30 +454,30 @@ CPDFSDK_FormFillEnvironment::DownloadFromURL(const FX_WCHAR* url) { return MakeSeekableStream(fileHandler); } -CFX_WideString CPDFSDK_FormFillEnvironment::PostRequestURL( - const FX_WCHAR* wsURL, - const FX_WCHAR* wsData, - const FX_WCHAR* wsContentType, - const FX_WCHAR* wsEncode, - const FX_WCHAR* wsHeader) { +WideString CPDFSDK_FormFillEnvironment::PostRequestURL( + const wchar_t* wsURL, + const wchar_t* wsData, + const wchar_t* wsContentType, + const wchar_t* wsEncode, + const wchar_t* wsHeader) { if (!m_pInfo || !m_pInfo->FFI_PostRequestURL) return L""; - CFX_ByteString bsURL = CFX_WideString(wsURL).UTF16LE_Encode(); + ByteString bsURL = WideString(wsURL).UTF16LE_Encode(); FPDF_WIDESTRING URL = (FPDF_WIDESTRING)bsURL.GetBuffer(bsURL.GetLength()); - CFX_ByteString bsData = CFX_WideString(wsData).UTF16LE_Encode(); + ByteString bsData = WideString(wsData).UTF16LE_Encode(); FPDF_WIDESTRING data = (FPDF_WIDESTRING)bsData.GetBuffer(bsData.GetLength()); - CFX_ByteString bsContentType = CFX_WideString(wsContentType).UTF16LE_Encode(); + ByteString bsContentType = WideString(wsContentType).UTF16LE_Encode(); FPDF_WIDESTRING contentType = (FPDF_WIDESTRING)bsContentType.GetBuffer(bsContentType.GetLength()); - CFX_ByteString bsEncode = CFX_WideString(wsEncode).UTF16LE_Encode(); + ByteString bsEncode = WideString(wsEncode).UTF16LE_Encode(); FPDF_WIDESTRING encode = (FPDF_WIDESTRING)bsEncode.GetBuffer(bsEncode.GetLength()); - CFX_ByteString bsHeader = CFX_WideString(wsHeader).UTF16LE_Encode(); + ByteString bsHeader = WideString(wsHeader).UTF16LE_Encode(); FPDF_WIDESTRING header = (FPDF_WIDESTRING)bsHeader.GetBuffer(bsHeader.GetLength()); @@ -506,53 +486,48 @@ CFX_WideString CPDFSDK_FormFillEnvironment::PostRequestURL( m_pInfo->FFI_PostRequestURL(m_pInfo, URL, data, contentType, encode, header, &response); - CFX_WideString wsRet = CFX_WideString::FromUTF16LE( + WideString wsRet = WideString::FromUTF16LE( (FPDF_WIDESTRING)response.str, response.len / sizeof(FPDF_WIDESTRING)); FPDF_BStr_Clear(&response); return wsRet; } -FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(const FX_WCHAR* wsURL, - const FX_WCHAR* wsData, - const FX_WCHAR* wsEncode) { +FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(const wchar_t* wsURL, + const wchar_t* wsData, + const wchar_t* wsEncode) { if (!m_pInfo || !m_pInfo->FFI_PutRequestURL) return false; - CFX_ByteString bsURL = CFX_WideString(wsURL).UTF16LE_Encode(); + ByteString bsURL = WideString(wsURL).UTF16LE_Encode(); FPDF_WIDESTRING URL = (FPDF_WIDESTRING)bsURL.GetBuffer(bsURL.GetLength()); - CFX_ByteString bsData = CFX_WideString(wsData).UTF16LE_Encode(); + ByteString bsData = WideString(wsData).UTF16LE_Encode(); FPDF_WIDESTRING data = (FPDF_WIDESTRING)bsData.GetBuffer(bsData.GetLength()); - CFX_ByteString bsEncode = CFX_WideString(wsEncode).UTF16LE_Encode(); + ByteString bsEncode = WideString(wsEncode).UTF16LE_Encode(); FPDF_WIDESTRING encode = (FPDF_WIDESTRING)bsEncode.GetBuffer(bsEncode.GetLength()); return m_pInfo->FFI_PutRequestURL(m_pInfo, URL, data, encode); } -CFX_WideString CPDFSDK_FormFillEnvironment::GetLanguage() { +WideString CPDFSDK_FormFillEnvironment::GetLanguage() { if (!m_pInfo || !m_pInfo->FFI_GetLanguage) - return L""; + return WideString(); int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0); if (nRequiredLen <= 0) - return L""; + return WideString(); - char* pbuff = new char[nRequiredLen]; - memset(pbuff, 0, nRequiredLen); - int nActualLen = m_pInfo->FFI_GetLanguage(m_pInfo, pbuff, nRequiredLen); - if (nActualLen <= 0 || nActualLen > nRequiredLen) { - delete[] pbuff; - return L""; - } - CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen); - CFX_WideString wsRet = CFX_WideString::FromUTF16LE( - (FPDF_WIDESTRING)bsRet.GetBuffer(bsRet.GetLength()), - bsRet.GetLength() / sizeof(FPDF_WIDESTRING)); - delete[] pbuff; - return wsRet; + std::vector pBuff(nRequiredLen); + int nActualLen = + m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen); + if (nActualLen <= 0 || nActualLen > nRequiredLen) + return WideString(); + + return WideString::FromUTF16LE(reinterpret_cast(pBuff.data()), + nActualLen / sizeof(uint16_t)); } void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount, @@ -579,8 +554,10 @@ CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView( if (!renew) return nullptr; - CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(this, pUnderlyingPage); - m_PageMap[pUnderlyingPage].reset(pPageView); + auto pNew = pdfium::MakeUnique(this, pUnderlyingPage); + CPDFSDK_PageView* pPageView = pNew.get(); + m_PageMap[pUnderlyingPage] = std::move(pNew); + // Delay to load all the annotations, to avoid endless loop. pPageView->LoadFXAnnots(); return pPageView; @@ -588,13 +565,12 @@ CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView( CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() { UnderlyingPageType* pPage = - UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc)); + UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc.Get())); return pPage ? GetPageView(pPage, true) : nullptr; } CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) { - UnderlyingPageType* pTempPage = - UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); + UnderlyingPageType* pTempPage = GetPage(nIndex); if (!pTempPage) return nullptr; @@ -606,15 +582,10 @@ void CPDFSDK_FormFillEnvironment::ProcJavascriptFun() { CPDF_Document* pPDFDoc = GetPDFDocument(); CPDF_DocJSActions docJS(pPDFDoc); int iCount = docJS.CountJSActions(); - if (iCount < 1) - return; for (int i = 0; i < iCount; i++) { - CFX_ByteString csJSName; - CPDF_Action jsAction = docJS.GetJSAction(i, csJSName); - if (GetActionHander()) { - GetActionHander()->DoAction_JavaScript( - jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), this); - } + WideString csJSName; + CPDF_Action jsAction = docJS.GetJSActionAndName(i, &csJSName); + GetActionHandler()->DoAction_JavaScript(jsAction, csJSName, this); } } @@ -622,27 +593,26 @@ bool CPDFSDK_FormFillEnvironment::ProcOpenAction() { if (!m_pUnderlyingDoc) return false; - CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot(); + const CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot(); if (!pRoot) return false; CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction"); if (!pOpenAction) pOpenAction = pRoot->GetArrayFor("OpenAction"); - if (!pOpenAction) return false; if (pOpenAction->IsArray()) return true; - if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) { - CPDF_Action action(pDict); - if (GetActionHander()) - GetActionHander()->DoAction_DocOpen(action, this); - return true; - } - return false; + CPDF_Dictionary* pDict = pOpenAction->AsDictionary(); + if (!pDict) + return false; + + CPDF_Action action(pDict); + GetActionHandler()->DoAction_DocOpen(action, this); + return true; } void CPDFSDK_FormFillEnvironment::RemovePageView( @@ -673,7 +643,10 @@ void CPDFSDK_FormFillEnvironment::RemovePageView( } UnderlyingPageType* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) { - return UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); + if (!m_pInfo || !m_pInfo->FFI_GetPage) + return nullptr; + return UnderlyingFromFPDFPage( + m_pInfo->FFI_GetPage(m_pInfo, m_pUnderlyingDoc.Get(), nIndex)); } CPDFSDK_InterForm* CPDFSDK_FormFillEnvironment::GetInterForm() { @@ -702,59 +675,58 @@ bool CPDFSDK_FormFillEnvironment::SetFocusAnnot( if (!*pAnnot) return false; -#ifdef PDF_ENABLE_XFA - CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get()); -#endif // PDF_ENABLE_XFA CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView(); - if (pPageView && pPageView->IsValid()) { - CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); - if (!m_pFocusAnnot) { + if (!pPageView || !pPageView->IsValid()) + return false; + + CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); + if (m_pFocusAnnot) + return false; + #ifdef PDF_ENABLE_XFA - if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot)) - return false; + CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get()); + if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot)) + return false; #endif // PDF_ENABLE_XFA - if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0)) - return false; - if (!m_pFocusAnnot) { - m_pFocusAnnot.Reset(pAnnot->Get()); - return true; - } - } - } - return false; + if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0)) + return false; + if (m_pFocusAnnot) + return false; + + m_pFocusAnnot.Reset(pAnnot->Get()); + return true; } bool CPDFSDK_FormFillEnvironment::KillFocusAnnot(uint32_t nFlag) { - if (m_pFocusAnnot) { - CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); - CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get()); - m_pFocusAnnot.Reset(); + if (!m_pFocusAnnot) + return false; + + CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); + CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get()); + m_pFocusAnnot.Reset(); #ifdef PDF_ENABLE_XFA - CPDFSDK_Annot::ObservedPtr pNull; - if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot)) - return false; + CPDFSDK_Annot::ObservedPtr pNull; + if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot)) + return false; #endif // PDF_ENABLE_XFA - if (pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) { - if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) { - CPDFSDK_Widget* pWidget = - static_cast(pFocusAnnot.Get()); - int nFieldType = pWidget->GetFieldType(); - if (FIELDTYPE_TEXTFIELD == nFieldType || - FIELDTYPE_COMBOBOX == nFieldType) { - OnSetFieldInputFocus(nullptr, 0, false); - } - } - if (!m_pFocusAnnot) - return true; - } else { - m_pFocusAnnot.Reset(pFocusAnnot.Get()); + if (!pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) { + m_pFocusAnnot.Reset(pFocusAnnot.Get()); + return false; + } + + if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) { + CPDFSDK_Widget* pWidget = static_cast(pFocusAnnot.Get()); + FormFieldType fieldType = pWidget->GetFieldType(); + if (fieldType == FormFieldType::kTextField || + fieldType == FormFieldType::kComboBox) { + OnSetFieldInputFocus(nullptr, 0, false); } } - return false; + return !m_pFocusAnnot; } -bool CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) { +bool CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) const { return !!(GetPDFDocument()->GetUserPermissions() & nFlag); } diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.h b/fpdfsdk/cpdfsdk_formfillenvironment.h index eead8734f11940bfb507c90440fd26cb002dc886..31a1c5156c88e0d009726387834a11fda6dc13c6 100644 --- a/fpdfsdk/cpdfsdk_formfillenvironment.h +++ b/fpdfsdk/cpdfsdk_formfillenvironment.h @@ -14,7 +14,7 @@ #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfdoc/cpdf_occontext.h" -#include "core/fxcrt/cfx_observable.h" +#include "core/fxcrt/observable.h" #include "fpdfsdk/cfx_systemhandler.h" #include "fpdfsdk/cpdfsdk_annot.h" #include "fpdfsdk/fsdk_define.h" @@ -29,13 +29,34 @@ class CPDFSDK_InterForm; class CPDFSDK_PageView; class IJS_Runtime; +// The CPDFSDK_FormFillEnvironment is "owned" by the embedder across the +// C API as a FPDF_FormHandle, and may pop out of existence at any time, +// so long as the associated embedder-owned FPDF_Document outlives it. +// Pointers from objects in the FPDF_Document ownership hierarchy should +// be ObservedPtr<> so as to clear themselves when the embedder "exits" +// the form fill environment. Pointers from objects in this ownership +// heirarcy to objects in the FPDF_Document ownership hierarcy should be +// UnownedPtr<>, as should pointers from objects in this ownership +// hierarcy back to the form fill environment itself, so as to flag any +// lingering lifetime issues via the memory tools. + class CPDFSDK_FormFillEnvironment - : public CFX_Observable { + : public Observable { public: CPDFSDK_FormFillEnvironment(UnderlyingDocumentType* pDoc, FPDF_FORMFILLINFO* pFFinfo); ~CPDFSDK_FormFillEnvironment(); + static bool IsSHIFTKeyDown(uint32_t nFlag) { + return !!(nFlag & FWL_EVENTFLAG_ShiftKey); + } + static bool IsCTRLKeyDown(uint32_t nFlag) { + return !!(nFlag & FWL_EVENTFLAG_ControlKey); + } + static bool IsALTKeyDown(uint32_t nFlag) { + return !!(nFlag & FWL_EVENTFLAG_AltKey); + } + CPDFSDK_PageView* GetPageView(UnderlyingPageType* pPage, bool renew); CPDFSDK_PageView* GetPageView(int nIndex); CPDFSDK_PageView* GetCurrentView(); @@ -56,20 +77,18 @@ class CPDFSDK_FormFillEnvironment const CPDF_Document* pSrcDoc, const std::vector& arrSrcPages); - int GetPageCount() { return m_pUnderlyingDoc->GetPageCount(); } - bool GetPermissions(int nFlag); + int GetPageCount() const { return m_pUnderlyingDoc->GetPageCount(); } + bool GetPermissions(int nFlag) const; bool GetChangeMark() const { return m_bChangeMask; } void SetChangeMark() { m_bChangeMask = true; } void ClearChangeMark() { m_bChangeMask = false; } - UnderlyingPageType* GetPage(int nIndex); - void ProcJavascriptFun(); bool ProcOpenAction(); - void Invalidate(FPDF_PAGE page, const FX_RECT& rect); - void OutputSelectedRect(FPDF_PAGE page, const CFX_FloatRect& rect); + void Invalidate(UnderlyingPageType* page, const FX_RECT& rect); + void OutputSelectedRect(UnderlyingPageType* page, const CFX_FloatRect& rect); void SetCursor(int nCursorType); int SetTimer(int uElapse, TimerCallback lpTimerFunc); @@ -77,25 +96,21 @@ class CPDFSDK_FormFillEnvironment FX_SYSTEMTIME GetLocalTime() const; void OnChange(); - bool IsSHIFTKeyDown(uint32_t nFlag) const; - bool IsCTRLKeyDown(uint32_t nFlag) const; - bool IsALTKeyDown(uint32_t nFlag) const; - FPDF_PAGE GetPage(FPDF_DOCUMENT document, int nPageIndex); - FPDF_PAGE GetCurrentPage(FPDF_DOCUMENT document); + FPDF_PAGE GetCurrentPage(UnderlyingDocumentType* document); - void ExecuteNamedAction(const FX_CHAR* namedAction); + void ExecuteNamedAction(const char* namedAction); void OnSetFieldInputFocus(FPDF_WIDESTRING focusText, FPDF_DWORD nTextLen, bool bFocus); - void DoURIAction(const FX_CHAR* bsURI); + void DoURIAction(const char* bsURI); void DoGoToAction(int nPageIndex, int zoomMode, float* fPosArray, int sizeOfArray); UnderlyingDocumentType* GetUnderlyingDocument() const { - return m_pUnderlyingDoc; + return m_pUnderlyingDoc.Get(); } #ifdef PDF_ENABLE_XFA @@ -103,27 +118,27 @@ class CPDFSDK_FormFillEnvironment return m_pUnderlyingDoc ? m_pUnderlyingDoc->GetPDFDoc() : nullptr; } - CPDFXFA_Context* GetXFAContext() const { return m_pUnderlyingDoc; } + CPDFXFA_Context* GetXFAContext() const { return m_pUnderlyingDoc.Get(); } void ResetXFADocument() { m_pUnderlyingDoc = nullptr; } int GetPageViewCount() const { return m_PageMap.size(); } - void DisplayCaret(FPDF_PAGE page, + void DisplayCaret(CPDFXFA_Page* page, FPDF_BOOL bVisible, double left, double top, double right, double bottom); - int GetCurrentPageIndex(FPDF_DOCUMENT document); - void SetCurrentPage(FPDF_DOCUMENT document, int iCurPage); + int GetCurrentPageIndex(CPDFXFA_Context* document); + void SetCurrentPage(CPDFXFA_Context* document, int iCurPage); // TODO(dsinclair): This should probably change to PDFium? - CFX_WideString FFI_GetAppName() const { return CFX_WideString(L"Acrobat"); } + WideString FFI_GetAppName() const { return WideString(L"Acrobat"); } - CFX_WideString GetPlatform(); - void GotoURL(FPDF_DOCUMENT document, const CFX_WideStringC& wsURL); - void GetPageViewRect(FPDF_PAGE page, FS_RECTF& dstRect); - bool PopupMenu(FPDF_PAGE page, + WideString GetPlatform(); + void GotoURL(CPDFXFA_Context* document, const WideStringView& wsURL); + void GetPageViewRect(CPDFXFA_Page* page, FS_RECTF& dstRect); + bool PopupMenu(CPDFXFA_Page* page, FPDF_WIDGET hWidget, int menuFlag, CFX_PointF pt); @@ -141,45 +156,45 @@ class CPDFSDK_FormFillEnvironment FPDF_FILEHANDLER* OpenFile(int fileType, FPDF_WIDESTRING wsURL, const char* mode); - CFX_RetainPtr DownloadFromURL(const FX_WCHAR* url); - CFX_WideString PostRequestURL(const FX_WCHAR* wsURL, - const FX_WCHAR* wsData, - const FX_WCHAR* wsContentType, - const FX_WCHAR* wsEncode, - const FX_WCHAR* wsHeader); - FPDF_BOOL PutRequestURL(const FX_WCHAR* wsURL, - const FX_WCHAR* wsData, - const FX_WCHAR* wsEncode); - CFX_WideString GetLanguage(); + RetainPtr DownloadFromURL(const wchar_t* url); + WideString PostRequestURL(const wchar_t* wsURL, + const wchar_t* wsData, + const wchar_t* wsContentType, + const wchar_t* wsEncode, + const wchar_t* wsHeader); + FPDF_BOOL PutRequestURL(const wchar_t* wsURL, + const wchar_t* wsData, + const wchar_t* wsEncode); + WideString GetLanguage(); void PageEvent(int iPageCount, uint32_t dwEventType) const; #else // PDF_ENABLE_XFA - CPDF_Document* GetPDFDocument() const { return m_pUnderlyingDoc; } + CPDF_Document* GetPDFDocument() const { return m_pUnderlyingDoc.Get(); } #endif // PDF_ENABLE_XFA - int JS_appAlert(const FX_WCHAR* Msg, - const FX_WCHAR* Title, + int JS_appAlert(const wchar_t* Msg, + const wchar_t* Title, uint32_t Type, uint32_t Icon); - int JS_appResponse(const FX_WCHAR* Question, - const FX_WCHAR* Title, - const FX_WCHAR* Default, - const FX_WCHAR* cLabel, + int JS_appResponse(const wchar_t* Question, + const wchar_t* Title, + const wchar_t* Default, + const wchar_t* cLabel, FPDF_BOOL bPassword, void* response, int length); void JS_appBeep(int nType); - CFX_WideString JS_fieldBrowse(); - CFX_WideString JS_docGetFilePath(); - void JS_docSubmitForm(void* formData, int length, const FX_WCHAR* URL); + WideString JS_fieldBrowse(); + WideString JS_docGetFilePath(); + void JS_docSubmitForm(void* formData, int length, const wchar_t* URL); void JS_docmailForm(void* mailData, int length, FPDF_BOOL bUI, - const FX_WCHAR* To, - const FX_WCHAR* Subject, - const FX_WCHAR* CC, - const FX_WCHAR* BCC, - const FX_WCHAR* Msg); + const wchar_t* To, + const wchar_t* Subject, + const wchar_t* CC, + const wchar_t* BCC, + const wchar_t* Msg); void JS_docprint(FPDF_BOOL bUI, int nStart, int nEnd, @@ -191,7 +206,7 @@ class CPDFSDK_FormFillEnvironment void JS_docgotoPage(int nPageNum); bool IsJSInitiated() const { return m_pInfo && m_pInfo->m_pJsPlatform; } - CFX_ByteString GetAppName() const { return ""; } + ByteString GetAppName() const { return ""; } CFX_SystemHandler* GetSysHandler() const { return m_pSysHandler.get(); } FPDF_FORMFILLINFO* GetFormFillInfo() const { return m_pInfo; } @@ -199,18 +214,20 @@ class CPDFSDK_FormFillEnvironment CFFL_InteractiveFormFiller* GetInteractiveFormFiller(); CPDFSDK_AnnotHandlerMgr* GetAnnotHandlerMgr(); // Creates if not present. IJS_Runtime* GetJSRuntime(); // Creates if not present. - CPDFSDK_ActionHandler* GetActionHander(); // Creates if not present. + CPDFSDK_ActionHandler* GetActionHandler(); // Creates if not present. CPDFSDK_InterForm* GetInterForm(); // Creates if not present. private: + UnderlyingPageType* GetPage(int nIndex); + + FPDF_FORMFILLINFO* const m_pInfo; std::unique_ptr m_pAnnotHandlerMgr; std::unique_ptr m_pActionHandler; std::unique_ptr m_pJSRuntime; - FPDF_FORMFILLINFO* const m_pInfo; std::map> m_PageMap; std::unique_ptr m_pInterForm; CPDFSDK_Annot::ObservedPtr m_pFocusAnnot; - UnderlyingDocumentType* m_pUnderlyingDoc; + UnownedPtr m_pUnderlyingDoc; std::unique_ptr m_pFormFiller; std::unique_ptr m_pSysHandler; bool m_bChangeMask; diff --git a/fpdfsdk/cpdfsdk_interform.cpp b/fpdfsdk/cpdfsdk_interform.cpp index 4ebcf8a2f3d9ee2f1a53c19588f7596ad7bd833a..e19d47bb55879bd8d1f5fc778fa832c040de8584 100644 --- a/fpdfsdk/cpdfsdk_interform.cpp +++ b/fpdfsdk/cpdfsdk_interform.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include "core/fpdfapi/page/cpdf_page.h" @@ -19,7 +21,6 @@ #include "core/fpdfdoc/cpdf_interform.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" #include "fpdfsdk/cba_annotiterator.h" #include "fpdfsdk/cpdfsdk_annot.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" @@ -28,11 +29,9 @@ #include "fpdfsdk/formfiller/cffl_formfiller.h" #include "fpdfsdk/fsdk_actionhandler.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/fxedit/fxet_edit.h" #include "fpdfsdk/ipdfsdk_annothandler.h" -#include "fpdfsdk/javascript/ijs_event_context.h" -#include "fpdfsdk/javascript/ijs_runtime.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" +#include "fxjs/ijs_event_context.h" +#include "fxjs/ijs_runtime.h" #include "third_party/base/stl_util.h" #ifdef PDF_ENABLE_XFA @@ -40,24 +39,56 @@ #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h" #include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" #endif // PDF_ENABLE_XFA +namespace { + +bool IsFormFieldTypeComboOrText(FormFieldType fieldType) { + switch (fieldType) { + case FormFieldType::kComboBox: + case FormFieldType::kTextField: + return true; + default: + return false; + } +} + +#ifdef PDF_ENABLE_XFA +bool IsFormFieldTypeXFA(FormFieldType fieldType) { + switch (fieldType) { + case FormFieldType::kXFA: + case FormFieldType::kXFA_CheckBox: + case FormFieldType::kXFA_ComboBox: + case FormFieldType::kXFA_ImageField: + case FormFieldType::kXFA_ListBox: + case FormFieldType::kXFA_PushButton: + case FormFieldType::kXFA_Signature: + case FormFieldType::kXFA_TextField: + return true; + default: + return false; + } +} +#endif // PDF_ENABLE_XFA + +} // namespace + CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_FormFillEnvironment* pFormFillEnv) : m_pFormFillEnv(pFormFillEnv), - m_pInterForm(new CPDF_InterForm(m_pFormFillEnv->GetPDFDocument())), + m_pInterForm( + pdfium::MakeUnique(m_pFormFillEnv->GetPDFDocument())), #ifdef PDF_ENABLE_XFA m_bXfaCalculate(true), m_bXfaValidationsEnabled(true), #endif // PDF_ENABLE_XFA m_bCalculate(true), m_bBusy(false), - m_iHighlightAlpha(0) { + m_HighlightAlpha(0) { m_pInterForm->SetFormNotify(this); - for (int i = 0; i < kNumFieldTypes; ++i) - m_bNeedHightlight[i] = false; + RemoveAllHighLights(); } CPDFSDK_InterForm::~CPDFSDK_InterForm() { @@ -73,8 +104,8 @@ bool CPDFSDK_InterForm::HighlightWidgets() { CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget, bool bNext) const { - std::unique_ptr pIterator(new CBA_AnnotIterator( - pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET)); + auto pIterator = pdfium::MakeUnique( + pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET); if (bNext) return static_cast(pIterator->GetNextAnnot(pWidget)); @@ -116,7 +147,7 @@ CPDFSDK_Widget* CPDFSDK_InterForm::GetWidget(CPDF_FormControl* pControl) const { } void CPDFSDK_InterForm::GetWidgets( - const CFX_WideString& sFieldName, + const WideString& sFieldName, std::vector* widgets) const { for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) { CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName); @@ -237,8 +268,8 @@ void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) { if (!pField) continue; - int nType = pField->GetFieldType(); - if (nType != FIELDTYPE_COMBOBOX && nType != FIELDTYPE_TEXTFIELD) + FormFieldType fieldType = pField->GetFieldType(); + if (!IsFormFieldTypeComboOrText(fieldType)) continue; CPDF_AAction aAction = pField->GetAdditionalAction(); @@ -249,17 +280,17 @@ void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) { if (!action.GetDict()) continue; - CFX_WideString csJS = action.GetJavaScript(); + WideString csJS = action.GetJavaScript(); if (csJS.IsEmpty()) continue; IJS_EventContext* pContext = pRuntime->NewEventContext(); - CFX_WideString sOldValue = pField->GetValue(); - CFX_WideString sValue = sOldValue; + WideString sOldValue = pField->GetValue(); + WideString sValue = sOldValue; bool bRC = true; pContext->OnField_Calculate(pFormField, pField, sValue, bRC); - CFX_WideString sInfo; + WideString sInfo; bool bRet = pContext->RunScript(csJS, &sInfo); pRuntime->ReleaseEventContext(pContext); if (bRet && bRC && sValue.Compare(sOldValue) != 0) @@ -268,16 +299,16 @@ void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) { m_bBusy = false; } -CFX_WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField, - bool& bFormatted) { - CFX_WideString sValue = pFormField->GetValue(); +WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField, + bool& bFormatted) { + WideString sValue = pFormField->GetValue(); if (!m_pFormFillEnv->IsJSInitiated()) { bFormatted = false; return sValue; } IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime(); - if (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX && + if (pFormField->GetFieldType() == FormFieldType::kComboBox && pFormField->CountSelectedItems() > 0) { int index = pFormField->GetSelectedIndex(0); if (index >= 0) @@ -290,13 +321,13 @@ CFX_WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField, if (aAction.GetDict() && aAction.ActionExist(CPDF_AAction::Format)) { CPDF_Action action = aAction.GetAction(CPDF_AAction::Format); if (action.GetDict()) { - CFX_WideString script = action.GetJavaScript(); + WideString script = action.GetJavaScript(); if (!script.IsEmpty()) { - CFX_WideString Value = sValue; + WideString Value = sValue; IJS_EventContext* pContext = pRuntime->NewEventContext(); pContext->OnField_Format(pFormField, Value, true); - CFX_WideString sInfo; + WideString sInfo; bool bRet = pContext->RunScript(script, &sInfo); pRuntime->ReleaseEventContext(pContext); if (bRet) { @@ -310,7 +341,7 @@ CFX_WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField, } void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField, - const CFX_WideString* sValue, + const WideString* sValue, bool bValueChanged) { for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { CPDF_FormControl* pFormCtrl = pFormField->GetControl(i); @@ -321,22 +352,24 @@ void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField, } void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) { - auto formfiller = m_pFormFillEnv->GetInteractiveFormFiller(); + auto* formfiller = m_pFormFillEnv->GetInteractiveFormFiller(); for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { CPDF_FormControl* pFormCtrl = pFormField->GetControl(i); ASSERT(pFormCtrl); - if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) { - UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); - m_pFormFillEnv->Invalidate( - pPage, formfiller->GetViewBBox( - m_pFormFillEnv->GetPageView(pPage, false), pWidget)); - } + CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl); + if (!pWidget) + continue; + + UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); + FX_RECT rect = formfiller->GetViewBBox( + m_pFormFillEnv->GetPageView(pPage, false), pWidget); + m_pFormFillEnv->Invalidate(pPage, rect); } } bool CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField, - const CFX_WideString& csValue) { + const WideString& csValue) { CPDF_AAction aAction = pFormField->GetAdditionalAction(); if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::KeyStroke)) return true; @@ -345,18 +378,18 @@ bool CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField, if (!action.GetDict()) return true; - CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHander(); + CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler(); PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(0); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(0); + fa.bModifier = false; + fa.bShift = false; fa.sValue = csValue; - pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::KeyStroke, - m_pFormFillEnv, pFormField, fa); + pActionHandler->DoAction_FieldJavaScript( + action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, fa); return fa.bRC; } bool CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField, - const CFX_WideString& csValue) { + const WideString& csValue) { CPDF_AAction aAction = pFormField->GetAdditionalAction(); if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Validate)) return true; @@ -365,13 +398,13 @@ bool CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField, if (!action.GetDict()) return true; - CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHander(); + CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler(); PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(0); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(0); + fa.bModifier = false; + fa.bShift = false; fa.sValue = csValue; - pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::Validate, - m_pFormFillEnv, pFormField, fa); + pActionHandler->DoAction_FieldJavaScript( + action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, fa); return fa.bRC; } @@ -409,7 +442,7 @@ bool CPDFSDK_InterForm::DoAction_Hide(const CPDF_Action& action) { } bool CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) { - CFX_WideString sDestination = action.GetFilePath(); + WideString sDestination = action.GetFilePath(); if (sDestination.IsEmpty()) return false; @@ -433,30 +466,36 @@ bool CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) { return SubmitForm(sDestination, false); } -bool CPDFSDK_InterForm::SubmitFields(const CFX_WideString& csDestination, +bool CPDFSDK_InterForm::SubmitFields(const WideString& csDestination, const std::vector& fields, bool bIncludeOrExclude, bool bUrlEncoded) { - CFX_ByteTextBuf textBuf; - ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude, textBuf); + ByteString textBuf = ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude); + + size_t nBufSize = textBuf.GetLength(); + if (nBufSize == 0) + return false; - uint8_t* pBuffer = textBuf.GetBuffer(); - FX_STRSIZE nBufSize = textBuf.GetLength(); + uint8_t* pLocalBuffer = FX_Alloc(uint8_t, nBufSize); + memcpy(pLocalBuffer, textBuf.c_str(), nBufSize); + uint8_t* pBuffer = pLocalBuffer; - if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) + if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) { + FX_Free(pLocalBuffer); return false; + } m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str()); - return true; -} -bool CPDFSDK_InterForm::FDFToURLEncodedData(CFX_WideString csFDFFile, - CFX_WideString csTxtFile) { + if (pBuffer != pLocalBuffer) + FX_Free(pBuffer); + + FX_Free(pLocalBuffer); + return true; } -bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, - FX_STRSIZE& nBufSize) { +bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize) { std::unique_ptr pFDF = CFDF_Document::ParseMemory(pBuf, nBufSize); if (!pFDF) @@ -470,49 +509,46 @@ bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, if (!pFields) return false; - CFX_ByteTextBuf fdfEncodedData; + std::ostringstream fdfEncodedData; for (uint32_t i = 0; i < pFields->GetCount(); i++) { CPDF_Dictionary* pField = pFields->GetDictAt(i); if (!pField) continue; - CFX_WideString name; + WideString name; name = pField->GetUnicodeTextFor("T"); - CFX_ByteString name_b = CFX_ByteString::FromUnicode(name); - CFX_ByteString csBValue = pField->GetStringFor("V"); - CFX_WideString csWValue = PDF_DecodeText(csBValue); - CFX_ByteString csValue_b = CFX_ByteString::FromUnicode(csWValue); + ByteString name_b = ByteString::FromUnicode(name); + ByteString csBValue = pField->GetStringFor("V"); + WideString csWValue = PDF_DecodeText(csBValue); + ByteString csValue_b = ByteString::FromUnicode(csWValue); fdfEncodedData << name_b.GetBuffer(name_b.GetLength()); - name_b.ReleaseBuffer(); + name_b.ReleaseBuffer(name_b.GetStringLength()); fdfEncodedData << "="; fdfEncodedData << csValue_b.GetBuffer(csValue_b.GetLength()); - csValue_b.ReleaseBuffer(); + csValue_b.ReleaseBuffer(csValue_b.GetStringLength()); if (i != pFields->GetCount() - 1) fdfEncodedData << "&"; } - nBufSize = fdfEncodedData.GetLength(); + nBufSize = fdfEncodedData.tellp(); + if (nBufSize == 0) + return false; + pBuf = FX_Alloc(uint8_t, nBufSize); - FXSYS_memcpy(pBuf, fdfEncodedData.GetBuffer(), nBufSize); + memcpy(pBuf, fdfEncodedData.str().c_str(), nBufSize); return true; } -bool CPDFSDK_InterForm::ExportFieldsToFDFTextBuf( +ByteString CPDFSDK_InterForm::ExportFieldsToFDFTextBuf( const std::vector& fields, - bool bIncludeOrExclude, - CFX_ByteTextBuf& textBuf) { - std::unique_ptr pFDF = - m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath().AsStringC(), - fields, bIncludeOrExclude, false); - return pFDF ? pFDF->WriteBuf(textBuf) : false; -} + bool bIncludeOrExclude) { + std::unique_ptr pFDF = m_pInterForm->ExportToFDF( + m_pFormFillEnv->JS_docGetFilePath(), fields, bIncludeOrExclude, false); -CFX_WideString CPDFSDK_InterForm::GetTemporaryFileName( - const CFX_WideString& sFileExt) { - return L""; + return pFDF ? pFDF->WriteToString() : ByteString(); } -bool CPDFSDK_InterForm::SubmitForm(const CFX_WideString& sDestination, +bool CPDFSDK_InterForm::SubmitForm(const WideString& sDestination, bool bUrlEncoded) { if (sDestination.IsEmpty()) return false; @@ -520,31 +556,41 @@ bool CPDFSDK_InterForm::SubmitForm(const CFX_WideString& sDestination, if (!m_pFormFillEnv || !m_pInterForm) return false; - std::unique_ptr pFDFDoc = m_pInterForm->ExportToFDF( - m_pFormFillEnv->JS_docGetFilePath().AsStringC(), false); + std::unique_ptr pFDFDoc = + m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false); if (!pFDFDoc) return false; - CFX_ByteTextBuf FdfBuffer; - if (!pFDFDoc->WriteBuf(FdfBuffer)) + ByteString fdfBuffer = pFDFDoc->WriteToString(); + + if (fdfBuffer.IsEmpty()) return false; - uint8_t* pBuffer = FdfBuffer.GetBuffer(); - FX_STRSIZE nBufSize = FdfBuffer.GetLength(); - if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) + uint8_t* pLocalBuffer = FX_Alloc(uint8_t, fdfBuffer.GetLength()); + memcpy(pLocalBuffer, fdfBuffer.c_str(), fdfBuffer.GetLength()); + uint8_t* pBuffer = pLocalBuffer; + + size_t nBufSize = fdfBuffer.GetLength(); + if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) { + FX_Free(pLocalBuffer); return false; + } m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str()); - if (bUrlEncoded) + + if (pBuffer != pLocalBuffer) FX_Free(pBuffer); + FX_Free(pLocalBuffer); + return true; } -bool CPDFSDK_InterForm::ExportFormToFDFTextBuf(CFX_ByteTextBuf& textBuf) { - std::unique_ptr pFDF = m_pInterForm->ExportToFDF( - m_pFormFillEnv->JS_docGetFilePath().AsStringC(), false); - return pFDF && pFDF->WriteBuf(textBuf); +ByteString CPDFSDK_InterForm::ExportFormToFDFTextBuf() { + std::unique_ptr pFDF = + m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false); + + return pFDF ? pFDF->WriteToString() : ByteString(); } bool CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) { @@ -571,7 +617,7 @@ std::vector CPDFSDK_InterForm::GetFieldFromObjects( std::vector fields; for (CPDF_Object* pObject : objects) { if (pObject && pObject->IsString()) { - CFX_WideString csName = pObject->GetUnicodeText(); + WideString csName = pObject->GetUnicodeText(); CPDF_FormField* pField = m_pInterForm->GetField(0, csName); if (pField) fields.push_back(pField); @@ -581,9 +627,9 @@ std::vector CPDFSDK_InterForm::GetFieldFromObjects( } int CPDFSDK_InterForm::BeforeValueChange(CPDF_FormField* pField, - const CFX_WideString& csValue) { - int nType = pField->GetFieldType(); - if (nType != FIELDTYPE_COMBOBOX && nType != FIELDTYPE_TEXTFIELD) + const WideString& csValue) { + FormFieldType fieldType = pField->GetFieldType(); + if (!IsFormFieldTypeComboOrText(fieldType)) return 0; if (!OnKeyStrokeCommit(pField, csValue)) @@ -599,19 +645,19 @@ void CPDFSDK_InterForm::AfterValueChange(CPDF_FormField* pField) { #ifdef PDF_ENABLE_XFA SynchronizeField(pField, false); #endif // PDF_ENABLE_XFA - int nType = pField->GetFieldType(); - if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) { + FormFieldType fieldType = pField->GetFieldType(); + if (IsFormFieldTypeComboOrText(fieldType)) { OnCalculate(pField); bool bFormatted = false; - CFX_WideString sValue = OnFormat(pField, bFormatted); + WideString sValue = OnFormat(pField, bFormatted); ResetFieldAppearance(pField, bFormatted ? &sValue : nullptr, true); UpdateField(pField); } } int CPDFSDK_InterForm::BeforeSelectionChange(CPDF_FormField* pField, - const CFX_WideString& csValue) { - if (pField->GetFieldType() != FIELDTYPE_LISTBOX) + const WideString& csValue) { + if (pField->GetFieldType() != FormFieldType::kListBox) return 0; if (!OnKeyStrokeCommit(pField, csValue)) @@ -624,7 +670,7 @@ int CPDFSDK_InterForm::BeforeSelectionChange(CPDF_FormField* pField, } void CPDFSDK_InterForm::AfterSelectionChange(CPDF_FormField* pField) { - if (pField->GetFieldType() != FIELDTYPE_LISTBOX) + if (pField->GetFieldType() != FormFieldType::kListBox) return; OnCalculate(pField); @@ -633,8 +679,9 @@ void CPDFSDK_InterForm::AfterSelectionChange(CPDF_FormField* pField) { } void CPDFSDK_InterForm::AfterCheckedStatusChange(CPDF_FormField* pField) { - int nType = pField->GetFieldType(); - if (nType != FIELDTYPE_CHECKBOX && nType != FIELDTYPE_RADIOBUTTON) + FormFieldType fieldType = pField->GetFieldType(); + if (fieldType != FormFieldType::kCheckBox && + fieldType != FormFieldType::kRadioButton) return; OnCalculate(pField); @@ -657,40 +704,56 @@ void CPDFSDK_InterForm::AfterFormImportData(CPDF_InterForm* pForm) { OnCalculate(nullptr); } -bool CPDFSDK_InterForm::IsNeedHighLight(int nFieldType) { - if (nFieldType < 1 || nFieldType > kNumFieldTypes) +bool CPDFSDK_InterForm::IsNeedHighLight(FormFieldType fieldType) { + if (fieldType == FormFieldType::kUnknown) return false; - return m_bNeedHightlight[nFieldType - 1]; + +#ifdef PDF_ENABLE_XFA + // For the XFA fields, we need to return if the specific field type has + // highlight enabled or if the general XFA field type has it enabled. + if (IsFormFieldTypeXFA(fieldType)) { + if (!m_NeedsHighlight[static_cast(fieldType)]) + return m_NeedsHighlight[static_cast(FormFieldType::kXFA)]; + } +#endif // PDF_ENABLE_XFA + return m_NeedsHighlight[static_cast(fieldType)]; } -void CPDFSDK_InterForm::RemoveAllHighLight() { - for (int i = 0; i < kNumFieldTypes; ++i) - m_bNeedHightlight[i] = false; +void CPDFSDK_InterForm::RemoveAllHighLights() { + std::fill(m_HighlightColor, m_HighlightColor + kFormFieldTypeCount, + FXSYS_RGB(255, 255, 255)); + std::fill(m_NeedsHighlight, m_NeedsHighlight + kFormFieldTypeCount, false); } -void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, int nFieldType) { - if (nFieldType < 0 || nFieldType > kNumFieldTypes) +void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, + FormFieldType fieldType) { + if (fieldType == FormFieldType::kUnknown) return; - switch (nFieldType) { - case 0: { - for (int i = 0; i < kNumFieldTypes; ++i) { - m_aHighlightColor[i] = clr; - m_bNeedHightlight[i] = true; - } - break; - } - default: { - m_aHighlightColor[nFieldType - 1] = clr; - m_bNeedHightlight[nFieldType - 1] = true; - break; - } + + m_HighlightColor[static_cast(fieldType)] = clr; + m_NeedsHighlight[static_cast(fieldType)] = true; +} + +void CPDFSDK_InterForm::SetAllHighlightColors(FX_COLORREF clr) { + for (auto type : kFormFieldTypes) { + m_HighlightColor[static_cast(type)] = clr; + m_NeedsHighlight[static_cast(type)] = true; } } -FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(int nFieldType) { - if (nFieldType < 0 || nFieldType > kNumFieldTypes) +FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(FormFieldType fieldType) { + if (fieldType == FormFieldType::kUnknown) return FXSYS_RGB(255, 255, 255); - if (nFieldType == 0) - return m_aHighlightColor[0]; - return m_aHighlightColor[nFieldType - 1]; + +#ifdef PDF_ENABLE_XFA + // For the XFA fields, we need to return the specific field type highlight + // colour or the general XFA field type colour if present. + if (IsFormFieldTypeXFA(fieldType)) { + if (!m_NeedsHighlight[static_cast(fieldType)] && + m_NeedsHighlight[static_cast(FormFieldType::kXFA)]) { + return m_HighlightColor[static_cast(FormFieldType::kXFA)]; + } + } +#endif // PDF_ENABLE_XFA + return m_HighlightColor[static_cast(fieldType)]; } diff --git a/fpdfsdk/cpdfsdk_interform.h b/fpdfsdk/cpdfsdk_interform.h index 032399c84e46b728927b5e9ab82101a7ee47bf9c..ee960ff33cb0ee1d04b3c06643aafa48771a8269 100644 --- a/fpdfsdk/cpdfsdk_interform.h +++ b/fpdfsdk/cpdfsdk_interform.h @@ -13,7 +13,7 @@ #include "core/fpdfdoc/cpdf_action.h" #include "core/fpdfdoc/ipdf_formnotify.h" -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/unowned_ptr.h" #include "core/fxge/fx_dib.h" #include "fpdfsdk/cpdfsdk_widget.h" @@ -35,13 +35,15 @@ class CPDFSDK_InterForm : public IPDF_FormNotify { ~CPDFSDK_InterForm() override; CPDF_InterForm* GetInterForm() const { return m_pInterForm.get(); } - CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; } + CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { + return m_pFormFillEnv.Get(); + } bool HighlightWidgets(); CPDFSDK_Widget* GetSibling(CPDFSDK_Widget* pWidget, bool bNext) const; CPDFSDK_Widget* GetWidget(CPDF_FormControl* pControl) const; - void GetWidgets(const CFX_WideString& sFieldName, + void GetWidgets(const WideString& sFieldName, std::vector* widgets) const; void GetWidgets(CPDF_FormField* pField, std::vector* widgets) const; @@ -63,14 +65,13 @@ class CPDFSDK_InterForm : public IPDF_FormNotify { void SynchronizeField(CPDF_FormField* pFormField, bool bSynchronizeElse); #endif // PDF_ENABLE_XFA - bool OnKeyStrokeCommit(CPDF_FormField* pFormField, - const CFX_WideString& csValue); - bool OnValidate(CPDF_FormField* pFormField, const CFX_WideString& csValue); + bool OnKeyStrokeCommit(CPDF_FormField* pFormField, const WideString& csValue); + bool OnValidate(CPDF_FormField* pFormField, const WideString& csValue); void OnCalculate(CPDF_FormField* pFormField = nullptr); - CFX_WideString OnFormat(CPDF_FormField* pFormField, bool& bFormatted); + WideString OnFormat(CPDF_FormField* pFormField, bool& bFormatted); void ResetFieldAppearance(CPDF_FormField* pFormField, - const CFX_WideString* sValue, + const WideString* sValue, bool bValueChanged); void UpdateField(CPDF_FormField* pFormField); @@ -82,31 +83,31 @@ class CPDFSDK_InterForm : public IPDF_FormNotify { std::vector GetFieldFromObjects( const std::vector& objects) const; bool IsValidField(CPDF_Dictionary* pFieldDict); - bool SubmitFields(const CFX_WideString& csDestination, + bool SubmitFields(const WideString& csDestination, const std::vector& fields, bool bIncludeOrExclude, bool bUrlEncoded); - bool SubmitForm(const CFX_WideString& sDestination, bool bUrlEncoded); - bool ExportFormToFDFTextBuf(CFX_ByteTextBuf& textBuf); - bool ExportFieldsToFDFTextBuf(const std::vector& fields, - bool bIncludeOrExclude, - CFX_ByteTextBuf& textBuf); - CFX_WideString GetTemporaryFileName(const CFX_WideString& sFileExt); - - bool IsNeedHighLight(int nFieldType); - void RemoveAllHighLight(); - void SetHighlightAlpha(uint8_t alpha) { m_iHighlightAlpha = alpha; } - uint8_t GetHighlightAlpha() { return m_iHighlightAlpha; } - void SetHighlightColor(FX_COLORREF clr, int nFieldType); - FX_COLORREF GetHighlightColor(int nFieldType); + bool SubmitForm(const WideString& sDestination, bool bUrlEncoded); + ByteString ExportFormToFDFTextBuf(); + ByteString ExportFieldsToFDFTextBuf( + const std::vector& fields, + bool bIncludeOrExclude); + + bool IsNeedHighLight(FormFieldType fieldType); + void RemoveAllHighLights(); + void SetHighlightAlpha(uint8_t alpha) { m_HighlightAlpha = alpha; } + uint8_t GetHighlightAlpha() { return m_HighlightAlpha; } + void SetHighlightColor(FX_COLORREF clr, FormFieldType fieldType); + void SetAllHighlightColors(FX_COLORREF clr); + FX_COLORREF GetHighlightColor(FormFieldType fieldType); private: // IPDF_FormNotify: int BeforeValueChange(CPDF_FormField* pField, - const CFX_WideString& csValue) override; + const WideString& csValue) override; void AfterValueChange(CPDF_FormField* pField) override; int BeforeSelectionChange(CPDF_FormField* pField, - const CFX_WideString& csValue) override; + const WideString& csValue) override; void AfterSelectionChange(CPDF_FormField* pField) override; void AfterCheckedStatusChange(CPDF_FormField* pField) override; int BeforeFormReset(CPDF_InterForm* pForm) override; @@ -114,30 +115,26 @@ class CPDFSDK_InterForm : public IPDF_FormNotify { int BeforeFormImportData(CPDF_InterForm* pForm) override; void AfterFormImportData(CPDF_InterForm* pForm) override; - bool FDFToURLEncodedData(CFX_WideString csFDFFile, CFX_WideString csTxtFile); - bool FDFToURLEncodedData(uint8_t*& pBuf, FX_STRSIZE& nBufSize); + bool FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize); int GetPageIndexByAnnotDict(CPDF_Document* pDocument, CPDF_Dictionary* pAnnotDict) const; using CPDFSDK_WidgetMap = std::map; - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; // Not owned. + UnownedPtr m_pFormFillEnv; std::unique_ptr m_pInterForm; CPDFSDK_WidgetMap m_Map; #ifdef PDF_ENABLE_XFA std::map m_XFAMap; bool m_bXfaCalculate; bool m_bXfaValidationsEnabled; - static const int kNumFieldTypes = 7; -#else // PDF_ENABLE_XFA - static const int kNumFieldTypes = 6; #endif // PDF_ENABLE_XFA bool m_bCalculate; bool m_bBusy; - FX_COLORREF m_aHighlightColor[kNumFieldTypes]; - uint8_t m_iHighlightAlpha; - bool m_bNeedHightlight[kNumFieldTypes]; + uint8_t m_HighlightAlpha; + FX_COLORREF m_HighlightColor[kFormFieldTypeCount]; + bool m_NeedsHighlight[kFormFieldTypeCount]; }; #endif // FPDFSDK_CPDFSDK_INTERFORM_H_ diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp index c67948da9066572e4767c984030ec3b71417c0e9..c1b522123514a06b452c7ea43e95f4fa2c3b9a3b 100644 --- a/fpdfsdk/cpdfsdk_pageview.cpp +++ b/fpdfsdk/cpdfsdk_pageview.cpp @@ -13,8 +13,8 @@ #include "core/fpdfapi/render/cpdf_renderoptions.h" #include "core/fpdfdoc/cpdf_annotlist.h" #include "core/fpdfdoc/cpdf_interform.h" +#include "core/fxcrt/autorestorer.h" #include "fpdfsdk/cpdfsdk_annot.h" -#include "fpdfsdk/cpdfsdk_annothandlermgr.h" #include "fpdfsdk/cpdfsdk_annotiteration.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_interform.h" @@ -22,11 +22,11 @@ #ifdef PDF_ENABLE_XFA #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" -#include "xfa/fxfa/xfa_rendercontext.h" -#include "xfa/fxgraphics/cfx_graphics.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_rendercontext.h" +#include "xfa/fxgraphics/cxfa_graphics.h" #endif // PDF_ENABLE_XFA CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv, @@ -36,23 +36,17 @@ CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv, #ifndef PDF_ENABLE_XFA m_bOwnsPage(false), #endif // PDF_ENABLE_XFA - m_bEnterWidget(false), - m_bExitWidget(false), m_bOnWidget(false), m_bValid(false), m_bLocked(false), m_bBeingDestroyed(false) { CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); - if (pInterForm) { - CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); + CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); #ifdef PDF_ENABLE_XFA - if (page->GetPDFPage()) - pPDFInterForm->FixPageFields(page->GetPDFPage()); + if (page->GetPDFPage()) + pPDFInterForm->FixPageFields(page->GetPDFPage()); #else // PDF_ENABLE_XFA - pPDFInterForm->FixPageFields(page); -#endif // PDF_ENABLE_XFA - } -#ifndef PDF_ENABLE_XFA + pPDFInterForm->FixPageFields(page); m_page->SetView(this); #endif // PDF_ENABLE_XFA } @@ -94,20 +88,18 @@ void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice, if (!pPage) return; - if (pPage->GetContext()->GetDocType() == DOCTYPE_DYNAMIC_XFA) { - CFX_Graphics gs(pDevice); - CFX_RectF rectClip(static_cast(pClip.left), - static_cast(pClip.top), - static_cast(pClip.Width()), - static_cast(pClip.Height())); + if (pPage->GetContext()->GetFormType() == FormType::kXFAFull) { + CFX_RectF rectClip( + static_cast(pClip.left), static_cast(pClip.top), + static_cast(pClip.Width()), static_cast(pClip.Height())); + + CXFA_Graphics gs(pDevice); gs.SetClipRect(rectClip); - std::unique_ptr pRenderContext(new CXFA_RenderContext); - CXFA_RenderOptions renderOptions; - renderOptions.m_bHighlight = true; + CXFA_FFPageView* xfaView = pPage->GetXFAPageView(); - pRenderContext->StartRender(xfaView, &gs, *pUser2Device, renderOptions); - pRenderContext->DoRender(); - pRenderContext->StopRender(); + CXFA_RenderContext renderContext(xfaView, rectClip, *pUser2Device); + renderContext.DoRender(&gs); + CXFA_FFDocView* docView = xfaView->GetDocView(); if (!docView) return; @@ -116,7 +108,7 @@ void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice, return; // Render the focus widget docView->GetWidgetHandler()->RenderWidget(annot->GetXFAWidget(), &gs, - pUser2Device, false); + *pUser2Device, false); return; } #endif // PDF_ENABLE_XFA @@ -125,7 +117,8 @@ void CPDFSDK_PageView::PageView_OnDraw(CFX_RenderDevice* pDevice, CPDFSDK_AnnotIteration annotIteration(this, true); for (const auto& pSDKAnnot : annotIteration) { m_pFormFillEnv->GetAnnotHandlerMgr()->Annot_OnDraw( - this, pSDKAnnot.Get(), pDevice, pUser2Device, pOptions->m_bDrawAnnots); + this, pSDKAnnot.Get(), pDevice, pUser2Device, + pOptions->GetDrawAnnots()); } } @@ -181,16 +174,21 @@ CPDFSDK_Annot* CPDFSDK_PageView::AddAnnot(CXFA_FFWidget* pPDFAnnot) { bool CPDFSDK_PageView::DeleteAnnot(CPDFSDK_Annot* pAnnot) { if (!pAnnot) return false; + CPDFXFA_Page* pPage = pAnnot->GetPDFXFAPage(); - if (!pPage || (pPage->GetContext()->GetDocType() != DOCTYPE_STATIC_XFA && - pPage->GetContext()->GetDocType() != DOCTYPE_DYNAMIC_XFA)) + if (!pPage || !pPage->GetContext()->ContainsXFAForm()) return false; + CPDFSDK_Annot::ObservedPtr pObserved(pAnnot); if (GetFocusAnnot() == pAnnot) - m_pFormFillEnv->KillFocusAnnot(0); - CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pFormFillEnv->GetAnnotHandlerMgr(); - if (pAnnotHandler) - pAnnotHandler->ReleaseAnnot(pAnnot); + m_pFormFillEnv->KillFocusAnnot(0); // May invoke JS, invalidating pAnnot. + + if (pObserved) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandler = + m_pFormFillEnv->GetAnnotHandlerMgr(); + if (pAnnotHandler) + pAnnotHandler->ReleaseAnnot(pObserved.Get()); + } auto it = std::find(m_SDKAnnotArray.begin(), m_SDKAnnotArray.end(), pAnnot); if (it != m_SDKAnnotArray.end()) @@ -207,7 +205,7 @@ CPDF_Document* CPDFSDK_PageView::GetPDFDocument() { #ifdef PDF_ENABLE_XFA return m_page->GetContext()->GetPDFDoc(); #else // PDF_ENABLE_XFA - return m_page->m_pDocument; + return m_page->m_pDocument.Get(); #endif // PDF_ENABLE_XFA } return nullptr; @@ -242,6 +240,35 @@ CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByXFAWidget(CXFA_FFWidget* hWidget) { } #endif // PDF_ENABLE_XFA +WideString CPDFSDK_PageView::GetSelectedText() { + if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = + m_pFormFillEnv->GetAnnotHandlerMgr(); + return pAnnotHandlerMgr->Annot_GetSelectedText(pAnnot); + } + + return WideString(); +} + +void CPDFSDK_PageView::ReplaceSelection(const WideString& text) { + if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = + m_pFormFillEnv->GetAnnotHandlerMgr(); + pAnnotHandlerMgr->Annot_ReplaceSelection(pAnnot, text); + } +} + +bool CPDFSDK_PageView::OnFocus(const CFX_PointF& point, uint32_t nFlag) { + CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point)); + if (!pAnnot) { + m_pFormFillEnv->KillFocusAnnot(nFlag); + return false; + } + + m_pFormFillEnv->SetFocusAnnot(&pAnnot); + return true; +} + bool CPDFSDK_PageView::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point)); if (!pAnnot) { @@ -311,32 +338,46 @@ bool CPDFSDK_PageView::OnMouseMove(const CFX_PointF& point, int nFlag) { CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = m_pFormFillEnv->GetAnnotHandlerMgr(); CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXAnnotAtPoint(point)); + + if (m_bOnWidget && m_pCaptureWidget != pFXAnnot) + ExitWidget(pAnnotHandlerMgr, true, nFlag); + if (pFXAnnot) { - if (m_pCaptureWidget && m_pCaptureWidget != pFXAnnot) { - m_bExitWidget = true; - m_bEnterWidget = false; - pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag); - } - m_pCaptureWidget.Reset(pFXAnnot.Get()); - m_bOnWidget = true; - if (!m_bEnterWidget) { - m_bEnterWidget = true; - m_bExitWidget = false; - pAnnotHandlerMgr->Annot_OnMouseEnter(this, &pFXAnnot, nFlag); + if (!m_bOnWidget) { + EnterWidget(pAnnotHandlerMgr, &pFXAnnot, nFlag); + + // Annot_OnMouseEnter may have invalidated pFXAnnot. + if (!pFXAnnot) { + ExitWidget(pAnnotHandlerMgr, false, nFlag); + return true; + } } + pAnnotHandlerMgr->Annot_OnMouseMove(this, &pFXAnnot, nFlag, point); return true; } - if (m_bOnWidget) { - m_bOnWidget = false; - m_bExitWidget = true; - m_bEnterWidget = false; - if (m_pCaptureWidget) { + + return false; +} + +void CPDFSDK_PageView::EnterWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr, + CPDFSDK_Annot::ObservedPtr* pAnnot, + uint32_t nFlag) { + m_bOnWidget = true; + m_pCaptureWidget.Reset(pAnnot->Get()); + pAnnotHandlerMgr->Annot_OnMouseEnter(this, pAnnot, nFlag); +} + +void CPDFSDK_PageView::ExitWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr, + bool callExitCallback, + uint32_t nFlag) { + m_bOnWidget = false; + if (m_pCaptureWidget) { + if (callExitCallback) pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag); - m_pCaptureWidget.Reset(); - } + + m_pCaptureWidget.Reset(); } - return false; } bool CPDFSDK_PageView::OnMouseWheel(double deltaX, @@ -349,8 +390,8 @@ bool CPDFSDK_PageView::OnMouseWheel(double deltaX, CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = m_pFormFillEnv->GetAnnotHandlerMgr(); - return pAnnotHandlerMgr->Annot_OnMouseWheel(this, &pAnnot, nFlag, (int)deltaY, - point); + return pAnnotHandlerMgr->Annot_OnMouseWheel(this, &pAnnot, nFlag, + static_cast(deltaY), point); } bool CPDFSDK_PageView::OnChar(int nChar, uint32_t nFlag) { @@ -380,22 +421,22 @@ void CPDFSDK_PageView::LoadFXAnnots() { CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = m_pFormFillEnv->GetAnnotHandlerMgr(); - SetLock(true); + AutoRestorer lock(&m_bLocked); + m_bLocked = true; #ifdef PDF_ENABLE_XFA - CFX_RetainPtr protector(m_page); - if (m_pFormFillEnv->GetXFAContext()->GetDocType() == DOCTYPE_DYNAMIC_XFA) { + RetainPtr protector(m_page); + if (m_pFormFillEnv->GetXFAContext()->GetFormType() == FormType::kXFAFull) { CXFA_FFPageView* pageView = m_page->GetXFAPageView(); - std::unique_ptr pWidgetHander( + std::unique_ptr pWidgetHandler( pageView->CreateWidgetIterator( XFA_TRAVERSEWAY_Form, XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)); - if (!pWidgetHander) { - SetLock(false); + if (!pWidgetHandler) { return; } - while (CXFA_FFWidget* pXFAAnnot = pWidgetHander->MoveToNext()) { + while (CXFA_FFWidget* pXFAAnnot = pWidgetHandler->MoveToNext()) { CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pXFAAnnot, this); if (!pAnnot) continue; @@ -403,7 +444,6 @@ void CPDFSDK_PageView::LoadFXAnnots() { pAnnotHandlerMgr->Annot_OnLoad(pAnnot); } - SetLock(false); return; } #endif // PDF_ENABLE_XFA @@ -426,18 +466,16 @@ void CPDFSDK_PageView::LoadFXAnnots() { m_SDKAnnotArray.push_back(pAnnot); pAnnotHandlerMgr->Annot_OnLoad(pAnnot); } - - SetLock(false); } void CPDFSDK_PageView::UpdateRects(const std::vector& rects) { for (const auto& rc : rects) - m_pFormFillEnv->Invalidate(m_page, rc.ToFxRect()); + m_pFormFillEnv->Invalidate(m_page, rc.GetOuterRect()); } void CPDFSDK_PageView::UpdateView(CPDFSDK_Annot* pAnnot) { CFX_FloatRect rcWindow = pAnnot->GetRect(); - m_pFormFillEnv->Invalidate(m_page, rcWindow.ToFxRect()); + m_pFormFillEnv->Invalidate(m_page, rcWindow.GetOuterRect()); } int CPDFSDK_PageView::GetPageIndex() const { @@ -445,21 +483,18 @@ int CPDFSDK_PageView::GetPageIndex() const { return -1; #ifdef PDF_ENABLE_XFA - int nDocType = m_page->GetContext()->GetDocType(); - switch (nDocType) { - case DOCTYPE_DYNAMIC_XFA: { + switch (m_page->GetContext()->GetFormType()) { + case FormType::kXFAFull: { CXFA_FFPageView* pPageView = m_page->GetXFAPageView(); return pPageView ? pPageView->GetPageIndex() : -1; } - case DOCTYPE_STATIC_XFA: - case DOCTYPE_PDF: - return GetPageIndexForStaticPDF(); - default: - return -1; + case FormType::kNone: + case FormType::kAcroForm: + case FormType::kXFAForeground: + break; } -#else // PDF_ENABLE_XFA - return GetPageIndexForStaticPDF(); #endif // PDF_ENABLE_XFA + return GetPageIndexForStaticPDF(); } bool CPDFSDK_PageView::IsValidAnnot(const CPDF_Annot* p) const { @@ -486,7 +521,7 @@ CPDFSDK_Annot* CPDFSDK_PageView::GetFocusAnnot() { } int CPDFSDK_PageView::GetPageIndexForStaticPDF() const { - CPDF_Dictionary* pDict = GetPDFPage()->m_pFormDict; + CPDF_Dictionary* pDict = GetPDFPage()->m_pFormDict.Get(); CPDF_Document* pDoc = m_pFormFillEnv->GetPDFDocument(); return (pDoc && pDict) ? pDoc->GetPageIndex(pDict->GetObjNum()) : -1; } diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h index bcd5177c1a7ce07f53bb8439864e5a86673bd10b..03f3ab6318a4f92c531c4eee17f6ab2708e591ea 100644 --- a/fpdfsdk/cpdfsdk_pageview.h +++ b/fpdfsdk/cpdfsdk_pageview.h @@ -12,7 +12,9 @@ #include "core/fpdfapi/page/cpdf_page.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/cpdfsdk_annot.h" +#include "fpdfsdk/cpdfsdk_annothandlermgr.h" class CFX_RenderDevice; class CPDF_AnnotList; @@ -55,7 +57,14 @@ class CPDFSDK_PageView final : public CPDF_Page::View { CPDF_Page* GetPDFPage() const; CPDF_Document* GetPDFDocument(); - CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; } + CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { + return m_pFormFillEnv.Get(); + } + + WideString GetSelectedText(); + void ReplaceSelection(const WideString& text); + + bool OnFocus(const CFX_PointF& point, uint32_t nFlag); bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag); bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag); #ifdef PDF_ENABLE_XFA @@ -81,7 +90,6 @@ class CPDFSDK_PageView final : public CPDF_Page::View { void SetValid(bool bValid) { m_bValid = bValid; } bool IsValid() { return m_bValid; } - void SetLock(bool bLocked) { m_bLocked = bLocked; } bool IsLocked() { return m_bLocked; } void SetBeingDestroyed() { m_bBeingDestroyed = true; } @@ -98,17 +106,22 @@ class CPDFSDK_PageView final : public CPDF_Page::View { int GetPageIndexForStaticPDF() const; + void EnterWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr, + CPDFSDK_Annot::ObservedPtr* pAnnot, + uint32_t nFlag); + void ExitWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr, + bool callExitCallback, + uint32_t nFlag); + CFX_Matrix m_curMatrix; UnderlyingPageType* const m_page; std::unique_ptr m_pAnnotList; std::vector m_SDKAnnotArray; - CPDFSDK_FormFillEnvironment* const m_pFormFillEnv; // Not owned. + UnownedPtr const m_pFormFillEnv; CPDFSDK_Annot::ObservedPtr m_pCaptureWidget; #ifndef PDF_ENABLE_XFA bool m_bOwnsPage; #endif // PDF_ENABLE_XFA - bool m_bEnterWidget; - bool m_bExitWidget; bool m_bOnWidget; bool m_bValid; bool m_bLocked; diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp index cd86f7a0b5d22b57e75ef800ace4b2696ef3ce91..2adc46f722fbbf9a2eedbaf25f9861ae0b48610f 100644 --- a/fpdfsdk/cpdfsdk_widget.cpp +++ b/fpdfsdk/cpdfsdk_widget.cpp @@ -7,6 +7,7 @@ #include "fpdfsdk/cpdfsdk_widget.h" #include +#include #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" @@ -28,17 +29,17 @@ #include "fpdfsdk/formfiller/cba_fontmap.h" #include "fpdfsdk/fsdk_actionhandler.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/fxedit/fxet_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Edit.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" +#include "fpdfsdk/pwl/cpwl_appstream.h" +#include "fpdfsdk/pwl/cpwl_edit.h" #ifdef PDF_ENABLE_XFA #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/fxfa_widget.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_node.h" #endif // PDF_ENABLE_XFA namespace { @@ -57,7 +58,7 @@ CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot, CPDFSDK_InterForm* pInterForm) : CPDFSDK_BAAnnot(pAnnot, pPageView), m_pInterForm(pInterForm), - m_nAppAge(0), + m_nAppearanceAge(0), m_nValueAge(0) #ifdef PDF_ENABLE_XFA , @@ -72,11 +73,11 @@ CPDFSDK_Widget::~CPDFSDK_Widget() {} #ifdef PDF_ENABLE_XFA CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); - if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) { + if (pContext->GetFormType() == FormType::kXFAForeground) { if (!m_hMixXFAWidget) { if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) { - CFX_WideString sName; - if (GetFieldType() == FIELDTYPE_RADIOBUTTON) { + WideString sName; + if (GetFieldType() == FormFieldType::kRadioButton) { sName = GetAnnotName(); if (sName.IsEmpty()) sName = GetName(); @@ -88,36 +89,35 @@ CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const { m_hMixXFAWidget = pDocView->GetWidgetByName(sName, nullptr); } } - return m_hMixXFAWidget; + return m_hMixXFAWidget.Get(); } - return nullptr; } CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); - if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) { - if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) { - CFX_WideString sName = GetName(); - if (!sName.IsEmpty()) - return pDocView->GetWidgetByName(sName, nullptr); - } - } + if (pContext->GetFormType() != FormType::kXFAForeground) + return nullptr; - return nullptr; + CXFA_FFDocView* pDocView = pContext->GetXFADocView(); + if (!pDocView) + return nullptr; + + WideString sName = GetName(); + return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr; } CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const { CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); - if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) { - if (!m_pWidgetHandler) { - if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) - m_pWidgetHandler = pDocView->GetWidgetHandler(); - } - return m_pWidgetHandler; - } + if (pContext->GetFormType() != FormType::kXFAForeground) + return nullptr; - return nullptr; + if (!m_pWidgetHandler) { + CXFA_FFDocView* pDocView = pContext->GetXFADocView(); + if (pDocView) + m_pWidgetHandler = pDocView->GetWidgetHandler(); + } + return m_pWidgetHandler.Get(); } static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) { @@ -165,11 +165,8 @@ static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT, eEventType = XFA_EVENT_Exit; break; case CPDF_AAction::PageOpen: - break; case CPDF_AAction::PageClose: - break; case CPDF_AAction::PageVisible: - break; case CPDF_AAction::PageInvisible: break; case CPDF_AAction::KeyStroke: @@ -189,6 +186,9 @@ static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT, case CPDF_AAction::PrintDocument: case CPDF_AAction::DocumentPrinted: break; + case CPDF_AAction::NumberOfActions: + NOTREACHED(); + break; } return eEventType; @@ -205,18 +205,18 @@ bool CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) { XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT); - CXFA_WidgetAcc* pAcc; if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) && - GetFieldType() == FIELDTYPE_RADIOBUTTON) { + GetFieldType() == FormFieldType::kRadioButton) { if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) { - pAcc = hGroupWidget->GetDataAcc(); - if (pXFAWidgetHandler->HasEvent(pAcc, eEventType)) + if (pXFAWidgetHandler->HasEvent(hGroupWidget->GetNode()->GetWidgetAcc(), + eEventType)) { return true; + } } } - pAcc = hWidget->GetDataAcc(); - return pXFAWidgetHandler->HasEvent(pAcc, eEventType); + return pXFAWidgetHandler->HasEvent(hWidget->GetNode()->GetWidgetAcc(), + eEventType); } bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT, @@ -250,14 +250,14 @@ bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT, if (data.nSelEnd > data.nSelStart) param.m_wsNewText.Delete(data.nSelStart, data.nSelEnd - data.nSelStart); - for (int i = 0; i < data.sChange.GetLength(); i++) - param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]); - param.m_wsPrevText = data.sValue; + for (const auto& c : data.sChange) + param.m_wsNewText.Insert(data.nSelStart, c); + param.m_wsPrevText = data.sValue; if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) && - GetFieldType() == FIELDTYPE_RADIOBUTTON) { + GetFieldType() == FormFieldType::kRadioButton) { if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) { - CXFA_WidgetAcc* pAcc = hGroupWidget->GetDataAcc(); + CXFA_WidgetAcc* pAcc = hGroupWidget->GetNode()->GetWidgetAcc(); param.m_pTarget = pAcc; if (pXFAWidgetHandler->ProcessEvent(pAcc, ¶m) != XFA_EVENTERROR_Success) { @@ -265,7 +265,7 @@ bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT, } } } - CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc(); + CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc(); param.m_pTarget = pAcc; int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); @@ -280,48 +280,52 @@ void CPDFSDK_Widget::Synchronize(bool bSynchronizeElse) { if (!hWidget) return; - CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc(); + CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc(); if (!pWidgetAcc) return; CPDF_FormField* pFormField = GetFormField(); switch (GetFieldType()) { - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: { + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: { CPDF_FormControl* pFormCtrl = GetFormControl(); XFA_CHECKSTATE eCheckState = pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off; pWidgetAcc->SetCheckState(eCheckState, true); break; } - case FIELDTYPE_TEXTFIELD: - pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit); + case FormFieldType::kTextField: + pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue()); break; - case FIELDTYPE_LISTBOX: { + case FormFieldType::kListBox: { pWidgetAcc->ClearAllSelections(); for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) { int nIndex = pFormField->GetSelectedIndex(i); - if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems()) + if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false)) pWidgetAcc->SetItemState(nIndex, true, false, false, true); } break; } - case FIELDTYPE_COMBOBOX: { + case FormFieldType::kComboBox: { pWidgetAcc->ClearAllSelections(); for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) { int nIndex = pFormField->GetSelectedIndex(i); - if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems()) + if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false)) pWidgetAcc->SetItemState(nIndex, true, false, false, true); } - pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit); + pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue()); break; } + default: + break; } - if (bSynchronizeElse) - pWidgetAcc->ProcessValueChanged(); + if (bSynchronizeElse) { + CPDFXFA_Context* context = m_pPageView->GetFormFillEnv()->GetXFAContext(); + context->GetXFADocView()->ProcessValueChanged(pWidgetAcc); + } } void CPDFSDK_Widget::SynchronizeXFAValue() { @@ -358,36 +362,35 @@ void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView, ASSERT(pFormControl); switch (pFormField->GetFieldType()) { - case FIELDTYPE_CHECKBOX: { - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { + case FormFieldType::kCheckBox: { + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { pFormField->CheckControl( pFormField->GetControlIndex(pFormControl), pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true); } break; } - case FIELDTYPE_RADIOBUTTON: { + case FormFieldType::kRadioButton: { // TODO(weili): Check whether we need to handle checkbox and radio // button differently, otherwise, merge these two cases. - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { pFormField->CheckControl( pFormField->GetControlIndex(pFormControl), pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true); } break; } - case FIELDTYPE_TEXTFIELD: { - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { - CFX_WideString sValue; - pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display); - pFormField->SetValue(sValue, true); + case FormFieldType::kTextField: { + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { + pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display), + true); } break; } - case FIELDTYPE_LISTBOX: { + case FormFieldType::kListBox: { pFormField->ClearSelection(false); - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) { int nIndex = pWidgetAcc->GetSelectedItem(i); @@ -398,10 +401,10 @@ void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView, } break; } - case FIELDTYPE_COMBOBOX: { + case FormFieldType::kComboBox: { pFormField->ClearSelection(false); - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) { int nIndex = pWidgetAcc->GetSelectedItem(i); @@ -409,13 +412,13 @@ void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView, pFormField->SetItemSelection(nIndex, true, true); } } - - CFX_WideString sValue; - pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display); - pFormField->SetValue(sValue, true); + pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display), + true); } break; } + default: + break; } } @@ -426,36 +429,36 @@ void CPDFSDK_Widget::SynchronizeXFAItems(CXFA_FFDocView* pXFADocView, ASSERT(hWidget); switch (pFormField->GetFieldType()) { - case FIELDTYPE_LISTBOX: { + case FormFieldType::kListBox: { pFormField->ClearSelection(false); pFormField->ClearOptions(true); - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { - for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; i++) { - CFX_WideString swText; - pWidgetAcc->GetChoiceListItem(swText, i); - - pFormField->InsertOption(swText, i, true); + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { + for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz; + i++) { + pFormField->InsertOption( + pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, true); } } break; } - case FIELDTYPE_COMBOBOX: { + case FormFieldType::kComboBox: { pFormField->ClearSelection(false); pFormField->ClearOptions(false); - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { - for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; i++) { - CFX_WideString swText; - pWidgetAcc->GetChoiceListItem(swText, i); - - pFormField->InsertOption(swText, i, false); + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { + for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz; + i++) { + pFormField->InsertOption( + pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, false); } } pFormField->SetValue(L"", true); break; } + default: + break; } } #endif // PDF_ENABLE_XFA @@ -466,7 +469,7 @@ bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) { return false; // Choose the right sub-ap - const FX_CHAR* ap_entry = "N"; + const char* ap_entry = "N"; if (mode == CPDF_Annot::Down) ap_entry = "D"; else if (mode == CPDF_Annot::Rollover) @@ -479,34 +482,35 @@ bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) { if (!psub) return false; - int nFieldType = GetFieldType(); - switch (nFieldType) { - case FIELDTYPE_PUSHBUTTON: - case FIELDTYPE_COMBOBOX: - case FIELDTYPE_LISTBOX: - case FIELDTYPE_TEXTFIELD: - case FIELDTYPE_SIGNATURE: + FormFieldType fieldType = GetFieldType(); + switch (fieldType) { + case FormFieldType::kPushButton: + case FormFieldType::kComboBox: + case FormFieldType::kListBox: + case FormFieldType::kTextField: + case FormFieldType::kSignature: return psub->IsStream(); - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) { return !!pSubDict->GetStreamFor(GetAppState()); } return false; + default: + return true; } - return true; } -int CPDFSDK_Widget::GetFieldType() const { +FormFieldType CPDFSDK_Widget::GetFieldType() const { CPDF_FormField* pField = GetFormField(); - return pField ? pField->GetFieldType() : FIELDTYPE_UNKNOWN; + return pField ? pField->GetFieldType() : FormFieldType::kUnknown; } bool CPDFSDK_Widget::IsAppearanceValid() { #ifdef PDF_ENABLE_XFA CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext(); - int nDocType = pContext->GetDocType(); - if (nDocType != DOCTYPE_PDF && nDocType != DOCTYPE_STATIC_XFA) + FormType formType = pContext->GetFormType(); + if (formType == FormType::kXFAFull) return true; #endif // PDF_ENABLE_XFA return CPDFSDK_BAAnnot::IsAppearanceValid(); @@ -525,7 +529,7 @@ int CPDFSDK_Widget::GetFieldFlags() const { } bool CPDFSDK_Widget::IsSignatureWidget() const { - return GetFieldType() == FIELDTYPE_SIGNATURE; + return GetFieldType() == FormFieldType::kSignature; } CPDF_FormField* CPDFSDK_Widget::GetFormField() const { @@ -551,7 +555,7 @@ int CPDFSDK_Widget::GetRotate() const { } #ifdef PDF_ENABLE_XFA -CFX_WideString CPDFSDK_Widget::GetName() const { +WideString CPDFSDK_Widget::GetName() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetFullName(); } @@ -561,14 +565,14 @@ bool CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const { CPDF_FormControl* pFormCtrl = GetFormControl(); int iColorType = 0; color = ARGBToColorRef(pFormCtrl->GetBackgroundColor(iColorType)); - return iColorType != COLORTYPE_TRANSPARENT; + return iColorType != CFX_Color::kTransparent; } bool CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const { CPDF_FormControl* pFormCtrl = GetFormControl(); int iColorType = 0; color = ARGBToColorRef(pFormCtrl->GetBorderColor(iColorType)); - return iColorType != COLORTYPE_TRANSPARENT; + return iColorType != CFX_Color::kTransparent; } bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const { @@ -578,26 +582,24 @@ bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const { return false; FX_ARGB argb; - int iColorType = COLORTYPE_TRANSPARENT; + int iColorType = CFX_Color::kTransparent; da.GetColor(argb, iColorType); color = ARGBToColorRef(argb); - return iColorType != COLORTYPE_TRANSPARENT; + return iColorType != CFX_Color::kTransparent; } -FX_FLOAT CPDFSDK_Widget::GetFontSize() const { +float CPDFSDK_Widget::GetFontSize() const { CPDF_FormControl* pFormCtrl = GetFormControl(); CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance(); - CFX_ByteString csFont = ""; - FX_FLOAT fFontSize = 0.0f; - pDa.GetFont(csFont, fFontSize); - + float fFontSize; + pDa.GetFont(&fFontSize); return fFontSize; } int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const { #ifdef PDF_ENABLE_XFA if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { if (nIndex < pWidgetAcc->CountSelectedItems()) return pWidgetAcc->GetSelectedItem(nIndex); } @@ -608,28 +610,26 @@ int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const { } #ifdef PDF_ENABLE_XFA -CFX_WideString CPDFSDK_Widget::GetValue(bool bDisplay) const { +WideString CPDFSDK_Widget::GetValue(bool bDisplay) const { if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { - CFX_WideString sValue; - pWidgetAcc->GetValue( - sValue, bDisplay ? XFA_VALUEPICTURE_Display : XFA_VALUEPICTURE_Edit); - return sValue; + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { + return pWidgetAcc->GetValue(bDisplay ? XFA_VALUEPICTURE_Display + : XFA_VALUEPICTURE_Edit); } } #else -CFX_WideString CPDFSDK_Widget::GetValue() const { +WideString CPDFSDK_Widget::GetValue() const { #endif // PDF_ENABLE_XFA CPDF_FormField* pFormField = GetFormField(); return pFormField->GetValue(); } -CFX_WideString CPDFSDK_Widget::GetDefaultValue() const { +WideString CPDFSDK_Widget::GetDefaultValue() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetDefaultValue(); } -CFX_WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const { +WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetOptionLabel(nIndex); } @@ -642,8 +642,8 @@ int CPDFSDK_Widget::CountOptions() const { bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const { #ifdef PDF_ENABLE_XFA if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) { - if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems()) + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) { + if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false)) return pWidgetAcc->GetItemState(nIndex); return false; @@ -662,7 +662,7 @@ int CPDFSDK_Widget::GetTopVisibleIndex() const { bool CPDFSDK_Widget::IsChecked() const { #ifdef PDF_ENABLE_XFA if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) { - if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) + if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) return pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On; } #endif // PDF_ENABLE_XFA @@ -693,7 +693,7 @@ void CPDFSDK_Widget::SetCheck(bool bChecked, bool bNotify) { #endif // PDF_ENABLE_XFA } -void CPDFSDK_Widget::SetValue(const CFX_WideString& sValue, bool bNotify) { +void CPDFSDK_Widget::SetValue(const WideString& sValue, bool bNotify) { CPDF_FormField* pFormField = GetFormField(); pFormField->SetValue(sValue, bNotify); #ifdef PDF_ENABLE_XFA @@ -702,7 +702,7 @@ void CPDFSDK_Widget::SetValue(const CFX_WideString& sValue, bool bNotify) { #endif // PDF_ENABLE_XFA } -void CPDFSDK_Widget::SetDefaultValue(const CFX_WideString& sValue) {} +void CPDFSDK_Widget::SetDefaultValue(const WideString& sValue) {} void CPDFSDK_Widget::SetOptionSelection(int index, bool bSelected, bool bNotify) { @@ -740,10 +740,10 @@ bool CPDFSDK_Widget::IsAppModified() const { #ifdef PDF_ENABLE_XFA void CPDFSDK_Widget::ResetAppearance(bool bValueChanged) { switch (GetFieldType()) { - case FIELDTYPE_TEXTFIELD: - case FIELDTYPE_COMBOBOX: { + case FormFieldType::kTextField: + case FormFieldType::kComboBox: { bool bFormatted = false; - CFX_WideString sValue = OnFormat(bFormatted); + WideString sValue = OnFormat(bFormatted); ResetAppearance(bFormatted ? &sValue : nullptr, true); break; } @@ -754,43 +754,42 @@ void CPDFSDK_Widget::ResetAppearance(bool bValueChanged) { } #endif // PDF_ENABLE_XFA -void CPDFSDK_Widget::ResetAppearance(const CFX_WideString* sValue, +void CPDFSDK_Widget::ResetAppearance(const WideString* sValue, bool bValueChanged) { SetAppModified(); - m_nAppAge++; - if (m_nAppAge > 999999) - m_nAppAge = 0; + m_nAppearanceAge++; if (bValueChanged) m_nValueAge++; - int nFieldType = GetFieldType(); - - switch (nFieldType) { - case FIELDTYPE_PUSHBUTTON: - ResetAppearance_PushButton(); + CPWL_AppStream appStream(this, GetAPDict()); + switch (GetFieldType()) { + case FormFieldType::kPushButton: + appStream.SetAsPushButton(); + break; + case FormFieldType::kCheckBox: + appStream.SetAsCheckBox(); break; - case FIELDTYPE_CHECKBOX: - ResetAppearance_CheckBox(); + case FormFieldType::kRadioButton: + appStream.SetAsRadioButton(); break; - case FIELDTYPE_RADIOBUTTON: - ResetAppearance_RadioButton(); + case FormFieldType::kComboBox: + appStream.SetAsComboBox(sValue); break; - case FIELDTYPE_COMBOBOX: - ResetAppearance_ComboBox(sValue); + case FormFieldType::kListBox: + appStream.SetAsListBox(); break; - case FIELDTYPE_LISTBOX: - ResetAppearance_ListBox(); + case FormFieldType::kTextField: + appStream.SetAsTextField(sValue); break; - case FIELDTYPE_TEXTFIELD: - ResetAppearance_TextField(sValue); + default: break; } m_pAnnot->ClearCachedAP(); } -CFX_WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) { +WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) { CPDF_FormField* pFormField = GetFormField(); ASSERT(pFormField); return m_pInterForm->OnFormat(pFormField, bFormatted); @@ -803,13 +802,13 @@ void CPDFSDK_Widget::ResetFieldAppearance(bool bValueChanged) { } void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, + const CFX_Matrix& mtUser2Device, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) { - int nFieldType = GetFieldType(); + FormFieldType fieldType = GetFieldType(); - if ((nFieldType == FIELDTYPE_CHECKBOX || - nFieldType == FIELDTYPE_RADIOBUTTON) && + if ((fieldType == FormFieldType::kCheckBox || + fieldType == FormFieldType::kRadioButton) && mode == CPDF_Annot::Normal && !IsWidgetAppearanceValid(CPDF_Annot::Normal)) { CFX_PathData pathData; @@ -822,10 +821,10 @@ void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice, CFX_GraphStateData gsd; gsd.m_LineWidth = 0.0f; - pDevice->DrawPath(&pathData, pUser2Device, &gsd, 0, 0xFFAAAAAA, + pDevice->DrawPath(&pathData, &mtUser2Device, &gsd, 0, 0xFFAAAAAA, FXFILL_ALTERNATE); } else { - CPDFSDK_BAAnnot::DrawAppearance(pDevice, pUser2Device, mode, pOptions); + CPDFSDK_BAAnnot::DrawAppearance(pDevice, mtUser2Device, mode, pOptions); } } @@ -837,8 +836,8 @@ void CPDFSDK_Widget::UpdateField() { void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice, CPDFSDK_PageView* pPageView) { - int nFieldType = GetFieldType(); - if (!m_pInterForm->IsNeedHighLight(nFieldType)) + FormFieldType fieldType = GetFieldType(); + if (!m_pInterForm->IsNeedHighLight(fieldType)) return; CFX_Matrix page2device; @@ -858,791 +857,12 @@ void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice, FX_RECT rcDev = rcDevice.ToFxRect(); pDevice->FillRect( &rcDev, ArgbEncode(static_cast(m_pInterForm->GetHighlightAlpha()), - m_pInterForm->GetHighlightColor(nFieldType))); -} - -void CPDFSDK_Widget::ResetAppearance_PushButton() { - CPDF_FormControl* pControl = GetFormControl(); - CFX_FloatRect rcWindow = GetRotatedRect(); - int32_t nLayout = 0; - switch (pControl->GetTextPosition()) { - case TEXTPOS_ICON: - nLayout = PPBL_ICON; - break; - case TEXTPOS_BELOW: - nLayout = PPBL_ICONTOPLABELBOTTOM; - break; - case TEXTPOS_ABOVE: - nLayout = PPBL_LABELTOPICONBOTTOM; - break; - case TEXTPOS_RIGHT: - nLayout = PPBL_ICONLEFTLABELRIGHT; - break; - case TEXTPOS_LEFT: - nLayout = PPBL_LABELLEFTICONRIGHT; - break; - case TEXTPOS_OVERLAID: - nLayout = PPBL_LABELOVERICON; - break; - default: - nLayout = PPBL_LABEL; - break; - } - - CPWL_Color crBackground; - CPWL_Color crBorder; - int iColorType; - FX_FLOAT fc[4]; - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - CPWL_Color crLeftTop; - CPWL_Color crRightBottom; - - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth); - - CPWL_Color crText(COLORTYPE_GRAY, 0); - - FX_FLOAT fFontSize = 12.0f; - CFX_ByteString csNameTag; - - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - if (da.HasFont()) - da.GetFont(csNameTag, fFontSize); - - CFX_WideString csWCaption; - CFX_WideString csNormalCaption, csRolloverCaption, csDownCaption; - - if (pControl->HasMKEntry("CA")) - csNormalCaption = pControl->GetNormalCaption(); - - if (pControl->HasMKEntry("RC")) - csRolloverCaption = pControl->GetRolloverCaption(); - - if (pControl->HasMKEntry("AC")) - csDownCaption = pControl->GetDownCaption(); - - CPDF_Stream* pNormalIcon = nullptr; - CPDF_Stream* pRolloverIcon = nullptr; - CPDF_Stream* pDownIcon = nullptr; - - if (pControl->HasMKEntry("I")) - pNormalIcon = pControl->GetNormalIcon(); - - if (pControl->HasMKEntry("RI")) - pRolloverIcon = pControl->GetRolloverIcon(); - - if (pControl->HasMKEntry("IX")) - pDownIcon = pControl->GetDownIcon(); - - if (pNormalIcon) { - if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgA", false); - } - } - - if (pRolloverIcon) { - if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgB", false); - } - } - - if (pDownIcon) { - if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgC", false); - } - } - - CPDF_IconFit iconFit = pControl->GetIconFit(); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - font_map.SetAPType("N"); - - CFX_ByteString csAP = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder) + - CPWL_Utils::GetPushButtonAppStream( - iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, - pNormalIcon, iconFit, csNormalCaption, crText, fFontSize, nLayout); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP); - if (pNormalIcon) - AddImageToAppearance("N", pNormalIcon); - - CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode(); - if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) { - if (csRolloverCaption.IsEmpty() && !pRolloverIcon) { - csRolloverCaption = csNormalCaption; - pRolloverIcon = pNormalIcon; - } - - font_map.SetAPType("R"); - - csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, - nBorderStyle, dsBorder) + - CPWL_Utils::GetPushButtonAppStream( - iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, - pRolloverIcon, iconFit, csRolloverCaption, crText, fFontSize, - nLayout); - - WriteAppearance("R", GetRotatedRect(), GetMatrix(), csAP); - if (pRolloverIcon) - AddImageToAppearance("R", pRolloverIcon); - - if (csDownCaption.IsEmpty() && !pDownIcon) { - csDownCaption = csNormalCaption; - pDownIcon = pNormalIcon; - } - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CPWL_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - font_map.SetAPType("D"); - - csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, - nBorderStyle, dsBorder) + - CPWL_Utils::GetPushButtonAppStream( - iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, - pDownIcon, iconFit, csDownCaption, crText, fFontSize, nLayout); - - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP); - if (pDownIcon) - AddImageToAppearance("D", pDownIcon); - } else { - RemoveAppearance("D"); - RemoveAppearance("R"); - } -} - -void CPDFSDK_Widget::ResetAppearance_CheckBox() { - CPDF_FormControl* pControl = GetFormControl(); - CPWL_Color crBackground, crBorder, crText; - int iColorType; - FX_FLOAT fc[4]; - - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - CPWL_Color crLeftTop, crRightBottom; - - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcWindow = GetRotatedRect(); - CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth); - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - int32_t nStyle = 0; - CFX_WideString csWCaption = pControl->GetNormalCaption(); - if (csWCaption.GetLength() > 0) { - switch (csWCaption[0]) { - case L'l': - nStyle = PCS_CIRCLE; - break; - case L'8': - nStyle = PCS_CROSS; - break; - case L'u': - nStyle = PCS_DIAMOND; - break; - case L'n': - nStyle = PCS_SQUARE; - break; - case L'H': - nStyle = PCS_STAR; - break; - default: // L'4' - nStyle = PCS_CHECK; - break; - } - } else { - nStyle = PCS_CHECK; - } - - CFX_ByteString csAP_N_ON = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - - CFX_ByteString csAP_N_OFF = csAP_N_ON; - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CPWL_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - CFX_ByteString csAP_D_ON = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - - CFX_ByteString csAP_D_OFF = csAP_D_ON; - - csAP_N_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText); - csAP_D_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON, - pControl->GetCheckedAPState()); - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off"); - - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON, - pControl->GetCheckedAPState()); - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off"); - - CFX_ByteString csAS = GetAppState(); - if (csAS.IsEmpty()) - SetAppState("Off"); -} - -void CPDFSDK_Widget::ResetAppearance_RadioButton() { - CPDF_FormControl* pControl = GetFormControl(); - CPWL_Color crBackground, crBorder, crText; - int iColorType; - FX_FLOAT fc[4]; - - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - CPWL_Color crLeftTop; - CPWL_Color crRightBottom; - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcWindow = GetRotatedRect(); - CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth); - - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - int32_t nStyle = 0; - CFX_WideString csWCaption = pControl->GetNormalCaption(); - if (csWCaption.GetLength() > 0) { - switch (csWCaption[0]) { - default: // L'l': - nStyle = PCS_CIRCLE; - break; - case L'8': - nStyle = PCS_CROSS; - break; - case L'u': - nStyle = PCS_DIAMOND; - break; - case L'n': - nStyle = PCS_SQUARE; - break; - case L'H': - nStyle = PCS_STAR; - break; - case L'4': - nStyle = PCS_CHECK; - break; - } - } else { - nStyle = PCS_CIRCLE; - } - - CFX_ByteString csAP_N_ON; - - CFX_FloatRect rcCenter = - CPWL_Utils::DeflateRect(CPWL_Utils::GetCenterSquare(rcWindow), 1.0f); - - if (nStyle == PCS_CIRCLE) { - if (nBorderStyle == BorderStyle::BEVELED) { - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground - 0.25f; - } else if (nBorderStyle == BorderStyle::INSET) { - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5f); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75f); - } - - csAP_N_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBackground) + - CPWL_Utils::GetCircleBorderAppStream( - rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom, - nBorderStyle, dsBorder); - } else { - csAP_N_ON = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, - nBorderStyle, dsBorder); - } - - CFX_ByteString csAP_N_OFF = csAP_N_ON; - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CPWL_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - CFX_ByteString csAP_D_ON; - - if (nStyle == PCS_CIRCLE) { - CPWL_Color crBK = crBackground - 0.25f; - if (nBorderStyle == BorderStyle::BEVELED) { - crLeftTop = crBackground - 0.25f; - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1); - crBK = crBackground; - } else if (nBorderStyle == BorderStyle::INSET) { - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1); - } - - csAP_D_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBK) + - CPWL_Utils::GetCircleBorderAppStream( - rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom, - nBorderStyle, dsBorder); - } else { - csAP_D_ON = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - } - - CFX_ByteString csAP_D_OFF = csAP_D_ON; - - csAP_N_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText); - csAP_D_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON, - pControl->GetCheckedAPState()); - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off"); - - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON, - pControl->GetCheckedAPState()); - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off"); - - CFX_ByteString csAS = GetAppState(); - if (csAS.IsEmpty()) - SetAppState("Off"); -} - -void CPDFSDK_Widget::ResetAppearance_ComboBox(const CFX_WideString* sValue) { - CPDF_FormControl* pControl = GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - CFX_ByteTextBuf sBody, sLines; - - CFX_FloatRect rcClient = GetClientRect(); - CFX_FloatRect rcButton = rcClient; - rcButton.left = rcButton.right - 13; - rcButton.Normalize(); - - std::unique_ptr pEdit(new CFX_Edit); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - CFX_FloatRect rcEdit = rcClient; - rcEdit.right = rcButton.left; - rcEdit.Normalize(); - - pEdit->SetPlateRect(rcEdit); - pEdit->SetAlignmentV(1, true); - - FX_FLOAT fFontSize = GetFontSize(); - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - - if (sValue) { - pEdit->SetText(*sValue); - } else { - int32_t nCurSel = pField->GetSelectedIndex(0); - if (nCurSel < 0) - pEdit->SetText(pField->GetValue()); - else - pEdit->SetText(pField->GetOptionLabel(nCurSel)); - } - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - - CFX_ByteString sEdit = - CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF()); - if (sEdit.GetLength() > 0) { - sBody << "/Tx BMC\n" - << "q\n"; - if (rcContent.Width() > rcEdit.Width() || - rcContent.Height() > rcEdit.Height()) { - sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width() - << " " << rcEdit.Height() << " re\nW\nn\n"; - } - - CPWL_Color crText = GetTextPWLColor(); - sBody << "BT\n" - << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n" - << "Q\nEMC\n"; - } - - sBody << CPWL_Utils::GetDropButtonAppStream(rcButton); - - CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() + - sLines.AsStringC() + sBody.AsStringC(); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP); -} - -void CPDFSDK_Widget::ResetAppearance_ListBox() { - CPDF_FormControl* pControl = GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - CFX_FloatRect rcClient = GetClientRect(); - CFX_ByteTextBuf sBody, sLines; - - std::unique_ptr pEdit(new CFX_Edit); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f)); - - FX_FLOAT fFontSize = GetFontSize(); - - pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); - - pEdit->Initialize(); - - CFX_ByteTextBuf sList; - FX_FLOAT fy = rcClient.top; - - int32_t nTop = pField->GetTopVisibleIndex(); - int32_t nCount = pField->CountOptions(); - int32_t nSelCount = pField->CountSelectedItems(); - - for (int32_t i = nTop; i < nCount; ++i) { - bool bSelected = false; - for (int32_t j = 0; j < nSelCount; ++j) { - if (pField->GetSelectedIndex(j) == i) { - bSelected = true; - break; - } - } - - pEdit->SetText(pField->GetOptionLabel(i)); - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - FX_FLOAT fItemHeight = rcContent.Height(); - - if (bSelected) { - CFX_FloatRect rcItem = - CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy); - sList << "q\n" - << CPWL_Utils::GetColorAppStream( - CPWL_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, - 113.0f / 255.0f), - true) - << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width() - << " " << rcItem.Height() << " re f\n" - << "Q\n"; - - sList << "BT\n" - << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1), - true) - << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy)) - << "ET\n"; - } else { - CPWL_Color crText = GetTextPWLColor(); - sList << "BT\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy)) - << "ET\n"; - } - - fy -= fItemHeight; - } - - if (sList.GetSize() > 0) { - sBody << "/Tx BMC\n" - << "q\n" - << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width() - << " " << rcClient.Height() << " re\nW\nn\n"; - sBody << sList << "Q\nEMC\n"; - } - - CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() + - sLines.AsStringC() + sBody.AsStringC(); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP); -} - -void CPDFSDK_Widget::ResetAppearance_TextField(const CFX_WideString* sValue) { - CPDF_FormControl* pControl = GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - CFX_ByteTextBuf sBody, sLines; - - std::unique_ptr pEdit(new CFX_Edit); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - CFX_FloatRect rcClient = GetClientRect(); - pEdit->SetPlateRect(rcClient); - pEdit->SetAlignmentH(pControl->GetControlAlignment(), true); - - uint32_t dwFieldFlags = pField->GetFieldFlags(); - bool bMultiLine = (dwFieldFlags >> 12) & 1; - - if (bMultiLine) { - pEdit->SetMultiLine(true, true); - pEdit->SetAutoReturn(true, true); - } else { - pEdit->SetAlignmentV(1, true); - } - - uint16_t subWord = 0; - if ((dwFieldFlags >> 13) & 1) { - subWord = '*'; - pEdit->SetPasswordChar(subWord, true); - } - - int nMaxLen = pField->GetMaxLen(); - bool bCharArray = (dwFieldFlags >> 24) & 1; - FX_FLOAT fFontSize = GetFontSize(); - -#ifdef PDF_ENABLE_XFA - CFX_WideString sValueTmp; - if (!sValue && GetMixXFAWidget()) { - sValueTmp = GetValue(true); - sValue = &sValueTmp; - } -#endif // PDF_ENABLE_XFA - - if (nMaxLen > 0) { - if (bCharArray) { - pEdit->SetCharArray(nMaxLen); - - if (IsFloatZero(fFontSize)) { - fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0), - rcClient, nMaxLen); - } - } else { - if (sValue) - nMaxLen = sValue->GetLength(); - pEdit->SetLimitChar(nMaxLen); - } - } - - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - pEdit->SetText(sValue ? *sValue : pField->GetValue()); - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream( - pEdit.get(), CFX_PointF(), nullptr, !bCharArray, subWord); - - if (sEdit.GetLength() > 0) { - sBody << "/Tx BMC\n" - << "q\n"; - if (rcContent.Width() > rcClient.Width() || - rcContent.Height() > rcClient.Height()) { - sBody << rcClient.left << " " << rcClient.bottom << " " - << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n"; - } - CPWL_Color crText = GetTextPWLColor(); - sBody << "BT\n" - << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n" - << "Q\nEMC\n"; - } - - if (bCharArray) { - switch (GetBorderStyle()) { - case BorderStyle::SOLID: { - CFX_ByteString sColor = - CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false); - if (sColor.GetLength() > 0) { - sLines << "q\n" - << GetBorderWidth() << " w\n" - << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false) - << " 2 J 0 j\n"; - - for (int32_t i = 1; i < nMaxLen; ++i) { - sLines << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.bottom << " m\n" - << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.top << " l S\n"; - } - - sLines << "Q\n"; - } - break; - } - case BorderStyle::DASH: { - CFX_ByteString sColor = - CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false); - if (sColor.GetLength() > 0) { - CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0); - - sLines << "q\n" - << GetBorderWidth() << " w\n" - << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false) - << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] " - << dsBorder.nPhase << " d\n"; - - for (int32_t i = 1; i < nMaxLen; ++i) { - sLines << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.bottom << " m\n" - << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.top << " l S\n"; - } - - sLines << "Q\n"; - } - break; - } - default: - break; - } - } - - CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() + - sLines.AsStringC() + sBody.AsStringC(); - WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP); + m_pInterForm->GetHighlightColor(fieldType))); } CFX_FloatRect CPDFSDK_Widget::GetClientRect() const { CFX_FloatRect rcWindow = GetRotatedRect(); - FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth(); + float fBorderWidth = (float)GetBorderWidth(); switch (GetBorderStyle()) { case BorderStyle::BEVELED: case BorderStyle::INSET: @@ -1651,14 +871,13 @@ CFX_FloatRect CPDFSDK_Widget::GetClientRect() const { default: break; } - - return CPWL_Utils::DeflateRect(rcWindow, fBorderWidth); + return rcWindow.GetDeflated(fBorderWidth, fBorderWidth); } CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const { CFX_FloatRect rectAnnot = GetRect(); - FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left; - FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom; + float fWidth = rectAnnot.right - rectAnnot.left; + float fHeight = rectAnnot.top - rectAnnot.bottom; CPDF_FormControl* pControl = GetFormControl(); CFX_FloatRect rcPDFWindow; @@ -1677,58 +896,16 @@ CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const { return rcPDFWindow; } -CFX_ByteString CPDFSDK_Widget::GetBackgroundAppStream() const { - CPWL_Color crBackground = GetFillPWLColor(); - if (crBackground.nColorType != COLORTYPE_TRANSPARENT) - return CPWL_Utils::GetRectFillAppStream(GetRotatedRect(), crBackground); - - return ""; -} - -CFX_ByteString CPDFSDK_Widget::GetBorderAppStream() const { - CFX_FloatRect rcWindow = GetRotatedRect(); - CPWL_Color crBorder = GetBorderPWLColor(); - CPWL_Color crBackground = GetFillPWLColor(); - CPWL_Color crLeftTop, crRightBottom; - - FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - return CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); -} - CFX_Matrix CPDFSDK_Widget::GetMatrix() const { CFX_Matrix mt; CPDF_FormControl* pControl = GetFormControl(); CFX_FloatRect rcAnnot = GetRect(); - FX_FLOAT fWidth = rcAnnot.right - rcAnnot.left; - FX_FLOAT fHeight = rcAnnot.top - rcAnnot.bottom; + float fWidth = rcAnnot.right - rcAnnot.left; + float fHeight = rcAnnot.top - rcAnnot.bottom; switch (abs(pControl->GetRotation() % 360)) { - case 0: default: - mt = CFX_Matrix(1, 0, 0, 1, 0, 0); + case 0: break; case 90: mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0); @@ -1744,75 +921,47 @@ CFX_Matrix CPDFSDK_Widget::GetMatrix() const { return mt; } -CPWL_Color CPDFSDK_Widget::GetTextPWLColor() const { - CPWL_Color crText = CPWL_Color(COLORTYPE_GRAY, 0); +CFX_Color CPDFSDK_Widget::GetTextPWLColor() const { + CFX_Color crText = CFX_Color(CFX_Color::kGray, 0); CPDF_FormControl* pFormCtrl = GetFormControl(); CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance(); if (da.HasColor()) { int32_t iColorType; - FX_FLOAT fc[4]; + float fc[4]; da.GetColor(iColorType, fc); - crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); } return crText; } -CPWL_Color CPDFSDK_Widget::GetBorderPWLColor() const { - CPWL_Color crBorder; +CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const { + CFX_Color crBorder; CPDF_FormControl* pFormCtrl = GetFormControl(); int32_t iColorType; - FX_FLOAT fc[4]; + float fc[4]; pFormCtrl->GetOriginalBorderColor(iColorType, fc); if (iColorType > 0) - crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); return crBorder; } -CPWL_Color CPDFSDK_Widget::GetFillPWLColor() const { - CPWL_Color crFill; +CFX_Color CPDFSDK_Widget::GetFillPWLColor() const { + CFX_Color crFill; CPDF_FormControl* pFormCtrl = GetFormControl(); int32_t iColorType; - FX_FLOAT fc[4]; + float fc[4]; pFormCtrl->GetOriginalBackgroundColor(iColorType, fc); if (iColorType > 0) - crFill = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); return crFill; } -void CPDFSDK_Widget::AddImageToAppearance(const CFX_ByteString& sAPType, - CPDF_Stream* pImage) { - CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); - CPDF_Stream* pStream = pAPDict->GetStreamFor(sAPType); - CPDF_Dictionary* pStreamDict = pStream->GetDict(); - CFX_ByteString sImageAlias = "IMG"; - - if (CPDF_Dictionary* pImageDict = pImage->GetDict()) { - sImageAlias = pImageDict->GetStringFor("Name"); - if (sImageAlias.IsEmpty()) - sImageAlias = "IMG"; - } - - CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); - if (!pStreamResList) - pStreamResList = pStreamDict->SetNewFor("Resources"); - - CPDF_Dictionary* pXObject = - pStreamResList->SetNewFor("XObject"); - pXObject->SetNewFor(sImageAlias, pDoc, pImage->GetObjNum()); -} - -void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) { - if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP")) - pAPDict->RemoveFor(sAPType); -} - bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type, PDFSDK_FieldAction& data, CPDFSDK_PageView* pPageView) { @@ -1843,7 +992,7 @@ bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type, param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]); param.m_wsPrevText = data.sValue; - CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc(); + CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc(); param.m_pTarget = pAcc; int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m); @@ -1859,7 +1008,7 @@ bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type, CPDF_Action action = GetAAction(type); if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) { - CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander(); + CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler(); return pActionHandler->DoAction_Field(action, type, pFormFillEnv, GetFormField(), data); } @@ -1893,18 +1042,10 @@ CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) { break; } - return CPDF_Action(); + return CPDF_Action(nullptr); } -CFX_WideString CPDFSDK_Widget::GetAlternateName() const { +WideString CPDFSDK_Widget::GetAlternateName() const { CPDF_FormField* pFormField = GetFormField(); return pFormField->GetAlternateName(); } - -int32_t CPDFSDK_Widget::GetAppearanceAge() const { - return m_nAppAge; -} - -int32_t CPDFSDK_Widget::GetValueAge() const { - return m_nValueAge; -} diff --git a/fpdfsdk/cpdfsdk_widget.h b/fpdfsdk/cpdfsdk_widget.h index 21e51697064e019e8bb6c68f2dd54325cf3bf89b..4b1115043f21e9331d9a96f1f75cd70eef696443 100644 --- a/fpdfsdk/cpdfsdk_widget.h +++ b/fpdfsdk/cpdfsdk_widget.h @@ -14,9 +14,10 @@ #include "core/fpdfdoc/cpdf_annot.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_color.h" #include "fpdfsdk/cpdfsdk_baannot.h" #include "fpdfsdk/pdfsdk_fieldaction.h" -#include "fpdfsdk/pdfwindow/cpwl_color.h" class CFX_RenderDevice; class CPDF_Annot; @@ -70,23 +71,23 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { int GetLayoutOrder() const override; - int GetFieldType() const; + FormFieldType GetFieldType() const; int GetFieldFlags() const; int GetRotate() const; bool GetFillColor(FX_COLORREF& color) const; bool GetBorderColor(FX_COLORREF& color) const; bool GetTextColor(FX_COLORREF& color) const; - FX_FLOAT GetFontSize() const; + float GetFontSize() const; int GetSelectedIndex(int nIndex) const; #ifndef PDF_ENABLE_XFA - CFX_WideString GetValue() const; + WideString GetValue() const; #else - CFX_WideString GetValue(bool bDisplay = true) const; + WideString GetValue(bool bDisplay = true) const; #endif // PDF_ENABLE_XFA - CFX_WideString GetDefaultValue() const; - CFX_WideString GetOptionLabel(int nIndex) const; + WideString GetDefaultValue() const; + WideString GetOptionLabel(int nIndex) const; int CountOptions() const; bool IsOptionSelected(int nIndex) const; int GetTopVisibleIndex() const; @@ -94,13 +95,13 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { int GetAlignment() const; int GetMaxLen() const; #ifdef PDF_ENABLE_XFA - CFX_WideString GetName() const; + WideString GetName() const; #endif // PDF_ENABLE_XFA - CFX_WideString GetAlternateName() const; + WideString GetAlternateName() const; void SetCheck(bool bChecked, bool bNotify); - void SetValue(const CFX_WideString& sValue, bool bNotify); - void SetDefaultValue(const CFX_WideString& sValue); + void SetValue(const WideString& sValue, bool bNotify); + void SetDefaultValue(const WideString& sValue); void SetOptionSelection(int index, bool bSelected, bool bNotify); void ClearSelection(bool bNotify); void SetTopVisibleIndex(int index); @@ -108,16 +109,16 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { #ifdef PDF_ENABLE_XFA void ResetAppearance(bool bValueChanged); #endif // PDF_ENABLE_XFA - void ResetAppearance(const CFX_WideString* sValue, bool bValueChanged); + void ResetAppearance(const WideString* sValue, bool bValueChanged); void ResetFieldAppearance(bool bValueChanged); void UpdateField(); - CFX_WideString OnFormat(bool& bFormatted); + WideString OnFormat(bool& bFormatted); bool OnAAction(CPDF_AAction::AActionType type, PDFSDK_FieldAction& data, CPDFSDK_PageView* pPageView); - CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm; } + CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm.Get(); } CPDF_FormField* GetFormField() const; CPDF_FormControl* GetFormControl() const; static CPDF_FormControl* GetFormControl(CPDF_InterForm* pInterForm, @@ -129,45 +130,31 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { void ClearAppModified(); bool IsAppModified() const; - int32_t GetAppearanceAge() const; - int32_t GetValueAge() const; + uint32_t GetAppearanceAge() const { return m_nAppearanceAge; } + uint32_t GetValueAge() const { return m_nValueAge; } bool IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode); void DrawAppearance(CFX_RenderDevice* pDevice, - const CFX_Matrix* pUser2Device, + const CFX_Matrix& mtUser2Device, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) override; - private: - void ResetAppearance_PushButton(); - void ResetAppearance_CheckBox(); - void ResetAppearance_RadioButton(); - void ResetAppearance_ComboBox(const CFX_WideString* sValue); - void ResetAppearance_ListBox(); - void ResetAppearance_TextField(const CFX_WideString* sValue); - + CFX_Matrix GetMatrix() const; CFX_FloatRect GetClientRect() const; CFX_FloatRect GetRotatedRect() const; + CFX_Color GetTextPWLColor() const; + CFX_Color GetBorderPWLColor() const; + CFX_Color GetFillPWLColor() const; - CFX_ByteString GetBackgroundAppStream() const; - CFX_ByteString GetBorderAppStream() const; - CFX_Matrix GetMatrix() const; - - CPWL_Color GetTextPWLColor() const; - CPWL_Color GetBorderPWLColor() const; - CPWL_Color GetFillPWLColor() const; - - void AddImageToAppearance(const CFX_ByteString& sAPType, CPDF_Stream* pImage); - void RemoveAppearance(const CFX_ByteString& sAPType); - - CPDFSDK_InterForm* const m_pInterForm; + private: + UnownedPtr const m_pInterForm; bool m_bAppModified; - int32_t m_nAppAge; - int32_t m_nValueAge; + uint32_t m_nAppearanceAge; + uint32_t m_nValueAge; #ifdef PDF_ENABLE_XFA - mutable CXFA_FFWidget* m_hMixXFAWidget; - mutable CXFA_FFWidgetHandler* m_pWidgetHandler; + mutable UnownedPtr m_hMixXFAWidget; + mutable UnownedPtr m_pWidgetHandler; #endif // PDF_ENABLE_XFA }; diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp index e85d24c4e0bc21c3ddee9840243ab08c4bb01e34..dcce7b60178cedad51598d7878864020437b972f 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.cpp +++ b/fpdfsdk/cpdfsdk_widgethandler.cpp @@ -25,7 +25,8 @@ CPDFSDK_WidgetHandler::CPDFSDK_WidgetHandler( CPDFSDK_FormFillEnvironment* pFormFillEnv) - : m_pFormFillEnv(pFormFillEnv), m_pFormFiller(nullptr) {} + : m_pFormFillEnv(pFormFillEnv), + m_pFormFiller(pFormFillEnv->GetInteractiveFormFiller()) {} CPDFSDK_WidgetHandler::~CPDFSDK_WidgetHandler() {} @@ -42,12 +43,11 @@ bool CPDFSDK_WidgetHandler::CanAnswer(CPDFSDK_Annot* pAnnot) { if ((nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY) return false; - if (pWidget->GetFieldType() == FIELDTYPE_PUSHBUTTON) + if (pWidget->GetFieldType() == FormFieldType::kPushButton) return true; CPDF_Page* pPage = pWidget->GetPDFPage(); - CPDF_Document* pDocument = pPage->m_pDocument; - uint32_t dwPermissions = pDocument->GetUserPermissions(); + uint32_t dwPermissions = pPage->m_pDocument->GetUserPermissions(); return (dwPermissions & FPDFPERM_FILL_FORM) || (dwPermissions & FPDFPERM_ANNOT_FORM); } @@ -95,7 +95,7 @@ void CPDFSDK_WidgetHandler::OnDraw(CPDFSDK_PageView* pPageView, bool bDrawAnnots) { if (pAnnot->IsSignatureWidget()) { static_cast(pAnnot)->DrawAppearance( - pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); + pDevice, *pUser2Device, CPDF_Annot::Normal, nullptr); } else { if (m_pFormFiller) m_pFormFiller->OnDraw(pPageView, pAnnot, pDevice, pUser2Device); @@ -227,18 +227,23 @@ void CPDFSDK_WidgetHandler::OnLoad(CPDFSDK_Annot* pAnnot) { if (!pWidget->IsAppearanceValid()) pWidget->ResetAppearance(nullptr, false); - int nFieldType = pWidget->GetFieldType(); - if (nFieldType == FIELDTYPE_TEXTFIELD || nFieldType == FIELDTYPE_COMBOBOX) { + FormFieldType fieldType = pWidget->GetFieldType(); + if (fieldType == FormFieldType::kTextField || + fieldType == FormFieldType::kComboBox) { bool bFormatted = false; - CFX_WideString sValue = pWidget->OnFormat(bFormatted); - if (bFormatted && nFieldType == FIELDTYPE_COMBOBOX) + CPDFSDK_Annot::ObservedPtr pObserved(pWidget); + WideString sValue = pWidget->OnFormat(bFormatted); + if (!pObserved) + return; + + if (bFormatted && fieldType == FormFieldType::kComboBox) pWidget->ResetAppearance(&sValue, false); } #ifdef PDF_ENABLE_XFA CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); CPDFXFA_Context* pContext = pPageView->GetFormFillEnv()->GetXFAContext(); - if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) { + if (pContext->GetFormType() == FormType::kXFAForeground) { if (!pWidget->IsAppearanceValid() && !pWidget->GetValue().IsEmpty()) pWidget->ResetAppearance(false); } @@ -273,8 +278,20 @@ CFX_FloatRect CPDFSDK_WidgetHandler::GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) { if (!pAnnot->IsSignatureWidget() && m_pFormFiller) return CFX_FloatRect(m_pFormFiller->GetViewBBox(pPageView, pAnnot)); + return CFX_FloatRect(); +} + +WideString CPDFSDK_WidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) { + if (!pAnnot->IsSignatureWidget() && m_pFormFiller) + return m_pFormFiller->GetSelectedText(pAnnot); - return CFX_FloatRect(0, 0, 0, 0); + return WideString(); +} + +void CPDFSDK_WidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) { + if (!pAnnot->IsSignatureWidget() && m_pFormFiller) + m_pFormFiller->ReplaceSelection(pAnnot, text); } bool CPDFSDK_WidgetHandler::HitTest(CPDFSDK_PageView* pPageView, diff --git a/fpdfsdk/cpdfsdk_widgethandler.h b/fpdfsdk/cpdfsdk_widgethandler.h index 6e4d50b2727b02df090de137785b641cee2522ac..f8aa7de5bdb0805b1c4dba6163ea789708001abb 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.h +++ b/fpdfsdk/cpdfsdk_widgethandler.h @@ -7,8 +7,8 @@ #ifndef FPDFSDK_CPDFSDK_WIDGETHANDLER_H_ #define FPDFSDK_CPDFSDK_WIDGETHANDLER_H_ -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/ipdfsdk_annothandler.h" class CFFL_InteractiveFormFiller; @@ -37,6 +37,8 @@ class CPDFSDK_WidgetHandler : public IPDFSDK_AnnotHandler { void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override; CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; + WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override; bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) override; @@ -96,14 +98,13 @@ class CPDFSDK_WidgetHandler : public IPDFSDK_AnnotHandler { CPDFSDK_Annot::ObservedPtr* pNewAnnot) override; #endif // PDF_ENABLE_XFA - void SetFormFiller(CFFL_InteractiveFormFiller* pFiller) { - m_pFormFiller = pFiller; + CFFL_InteractiveFormFiller* GetFormFiller() const { + return m_pFormFiller.Get(); } - CFFL_InteractiveFormFiller* GetFormFiller() { return m_pFormFiller; } private: - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; - CFFL_InteractiveFormFiller* m_pFormFiller; + UnownedPtr const m_pFormFillEnv; + UnownedPtr const m_pFormFiller; }; #endif // FPDFSDK_CPDFSDK_WIDGETHANDLER_H_ diff --git a/fpdfsdk/cpdfsdk_xfawidget.cpp b/fpdfsdk/cpdfsdk_xfawidget.cpp index b30e5f3ac2ec0d90607e7142e057bf52403c1f46..af08023ef858cdf1486a46ee7db8259911917275 100644 --- a/fpdfsdk/cpdfsdk_xfawidget.cpp +++ b/fpdfsdk/cpdfsdk_xfawidget.cpp @@ -7,7 +7,7 @@ #include "fpdfsdk/cpdfsdk_xfawidget.h" #include "fpdfsdk/ipdfsdk_annothandler.h" -#include "xfa/fxfa/xfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidget.h" CPDFSDK_XFAWidget::CPDFSDK_XFAWidget(CXFA_FFWidget* pAnnot, CPDFSDK_PageView* pPageView, @@ -16,12 +16,14 @@ CPDFSDK_XFAWidget::CPDFSDK_XFAWidget(CXFA_FFWidget* pAnnot, m_pInterForm(pInterForm), m_hXFAWidget(pAnnot) {} +CPDFSDK_XFAWidget::~CPDFSDK_XFAWidget() {} + bool CPDFSDK_XFAWidget::IsXFAField() { return true; } CXFA_FFWidget* CPDFSDK_XFAWidget::GetXFAWidget() const { - return m_hXFAWidget; + return m_hXFAWidget.Get(); } CPDF_Annot::Subtype CPDFSDK_XFAWidget::GetAnnotSubtype() const { diff --git a/fpdfsdk/cpdfsdk_xfawidget.h b/fpdfsdk/cpdfsdk_xfawidget.h index 9d0be75f13aeaf6669ba9be89f191e7ff6d8ca79..d2635eb4e12c44b725d874aa9ca12f6a0c28b3a1 100644 --- a/fpdfsdk/cpdfsdk_xfawidget.h +++ b/fpdfsdk/cpdfsdk_xfawidget.h @@ -9,6 +9,7 @@ #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/cpdfsdk_annot.h" class CPDFSDK_InterForm; @@ -20,18 +21,19 @@ class CPDFSDK_XFAWidget : public CPDFSDK_Annot { CPDFSDK_XFAWidget(CXFA_FFWidget* pAnnot, CPDFSDK_PageView* pPageView, CPDFSDK_InterForm* pInterForm); - ~CPDFSDK_XFAWidget() override {} + ~CPDFSDK_XFAWidget() override; + // CPDFSDK_Annot: bool IsXFAField() override; CXFA_FFWidget* GetXFAWidget() const override; CPDF_Annot::Subtype GetAnnotSubtype() const override; CFX_FloatRect GetRect() const override; - CPDFSDK_InterForm* GetInterForm() { return m_pInterForm; } + CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm.Get(); } private: - CPDFSDK_InterForm* m_pInterForm; - CXFA_FFWidget* m_hXFAWidget; + UnownedPtr m_pInterForm; + UnownedPtr m_hXFAWidget; }; #endif // FPDFSDK_CPDFSDK_XFAWIDGET_H_ diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp index 653eb8ae43420e356034afb5e3ee2df0699f4540..897e16dfbfda98ddaeb11a13114521f4cb594b80 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp @@ -15,12 +15,13 @@ #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/fwl_widgethit.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" #include "xfa/fxfa/fxfa_basic.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" -#include "xfa/fxgraphics/cfx_graphics.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_graphics.h" CPDFSDK_XFAWidgetHandler::CPDFSDK_XFAWidgetHandler( CPDFSDK_FormFillEnvironment* pFormFillEnv) @@ -53,14 +54,14 @@ void CPDFSDK_XFAWidgetHandler::OnDraw(CPDFSDK_PageView* pPageView, ASSERT(pPageView); ASSERT(pAnnot); - CFX_Graphics gs(pDevice); + CXFA_Graphics gs(pDevice); CFX_Matrix mt = *pUser2Device; bool bIsHighlight = false; if (pPageView->GetFormFillEnv()->GetFocusAnnot() != pAnnot) bIsHighlight = true; - GetXFAWidgetHandler(pAnnot)->RenderWidget(pAnnot->GetXFAWidget(), &gs, &mt, + GetXFAWidgetHandler(pAnnot)->RenderWidget(pAnnot->GetXFAWidget(), &gs, mt, bIsHighlight); // to do highlight and shadow @@ -81,7 +82,8 @@ CFX_FloatRect CPDFSDK_XFAWidgetHandler::GetViewBBox(CPDFSDK_PageView* pPageView, ASSERT(pAnnot); CFX_RectF rcBBox; - XFA_Element eType = pAnnot->GetXFAWidget()->GetDataAcc()->GetUIType(); + XFA_Element eType = + pAnnot->GetXFAWidget()->GetNode()->GetWidgetAcc()->GetUIType(); if (eType == XFA_Element::Signature) rcBBox = pAnnot->GetXFAWidget()->GetBBox(XFA_WidgetStatus_Visible, true); else @@ -97,6 +99,23 @@ CFX_FloatRect CPDFSDK_XFAWidgetHandler::GetViewBBox(CPDFSDK_PageView* pPageView, return rcWidget; } +WideString CPDFSDK_XFAWidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) { + if (!pAnnot) + return WideString(); + + CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + return pWidgetHandler->GetSelectedText(pAnnot->GetXFAWidget()); +} + +void CPDFSDK_XFAWidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) { + if (!pAnnot) + return; + + CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + return pWidgetHandler->PasteText(pAnnot->GetXFAWidget(), text); +} + bool CPDFSDK_XFAWidgetHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) { diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.h b/fpdfsdk/cpdfsdk_xfawidgethandler.h index 3903103eeb2c529a7c90d29876483cf39240bd46..e0dccbe68562f9f0c15cd2dd9caafede09b3356f 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.h +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.h @@ -7,8 +7,8 @@ #ifndef FPDFSDK_CPDFSDK_XFAWIDGETHANDLER_H_ #define FPDFSDK_CPDFSDK_XFAWIDGETHANDLER_H_ -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/ipdfsdk_annothandler.h" class CFX_Matrix; @@ -32,6 +32,8 @@ class CPDFSDK_XFAWidgetHandler : public IPDFSDK_AnnotHandler { void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override; CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; + WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override; bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) override; @@ -92,7 +94,7 @@ class CPDFSDK_XFAWidgetHandler : public IPDFSDK_AnnotHandler { CXFA_FFWidgetHandler* GetXFAWidgetHandler(CPDFSDK_Annot* pAnnot); uint32_t GetFWLFlags(uint32_t dwFlag); - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; + UnownedPtr const m_pFormFillEnv; }; #endif // FPDFSDK_CPDFSDK_XFAWIDGETHANDLER_H_ diff --git a/fpdfsdk/formfiller/cba_fontmap.cpp b/fpdfsdk/formfiller/cba_fontmap.cpp index 750b41627e798fd790977191d05baf03f98b4be8..d67567661688eac85d7dfdaead92e9430b872b61 100644 --- a/fpdfsdk/formfiller/cba_fontmap.cpp +++ b/fpdfsdk/formfiller/cba_fontmap.cpp @@ -28,7 +28,7 @@ CBA_FontMap::CBA_FontMap(CPDFSDK_Annot* pAnnot, m_sAPType("N") { CPDF_Page* pPage = pAnnot->GetPDFPage(); - m_pDocument = pPage->m_pDocument; + m_pDocument = pPage->m_pDocument.Get(); m_pAnnotDict = pAnnot->GetPDFAnnot()->GetAnnotDict(); Initialize(); } @@ -38,14 +38,14 @@ CBA_FontMap::~CBA_FontMap() {} void CBA_FontMap::Reset() { Empty(); m_pDefaultFont = nullptr; - m_sDefaultFontName = ""; + m_sDefaultFontName.clear(); } void CBA_FontMap::Initialize() { - int32_t nCharset = FXFONT_DEFAULT_CHARSET; + int32_t nCharset = FX_CHARSET_Default; if (!m_pDefaultFont) { - m_pDefaultFont = GetAnnotDefaultFont(m_sDefaultFontName); + m_pDefaultFont = GetAnnotDefaultFont(&m_sDefaultFontName); if (m_pDefaultFont) { if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont()) { nCharset = pSubstFont->m_Charset; @@ -54,21 +54,21 @@ void CBA_FontMap::Initialize() { m_sDefaultFontName == "Wingdings2" || m_sDefaultFontName == "Wingdings3" || m_sDefaultFontName == "Webdings") - nCharset = FXFONT_SYMBOL_CHARSET; + nCharset = FX_CHARSET_Symbol; else - nCharset = FXFONT_ANSI_CHARSET; + nCharset = FX_CHARSET_ANSI; } - AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset); - AddFontToAnnotDict(m_pDefaultFont, m_sDefaultFontName); + AddFontData(m_pDefaultFont.Get(), m_sDefaultFontName, nCharset); + AddFontToAnnotDict(m_pDefaultFont.Get(), m_sDefaultFontName); } } - if (nCharset != FXFONT_ANSI_CHARSET) + if (nCharset != FX_CHARSET_ANSI) CPWL_FontMap::Initialize(); } void CBA_FontMap::SetDefaultFont(CPDF_Font* pFont, - const CFX_ByteString& sFontName) { + const ByteString& sFontName) { ASSERT(pFont); if (m_pDefaultFont) @@ -77,19 +77,19 @@ void CBA_FontMap::SetDefaultFont(CPDF_Font* pFont, m_pDefaultFont = pFont; m_sDefaultFontName = sFontName; - int32_t nCharset = FXFONT_DEFAULT_CHARSET; + int32_t nCharset = FX_CHARSET_Default; if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont()) nCharset = pSubstFont->m_Charset; - AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset); + AddFontData(m_pDefaultFont.Get(), m_sDefaultFontName, nCharset); } -CPDF_Font* CBA_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, +CPDF_Font* CBA_FontMap::FindFontSameCharset(ByteString* sFontAlias, int32_t nCharset) { if (m_pAnnotDict->GetStringFor("Subtype") != "Widget") return nullptr; CPDF_Document* pDocument = GetDocument(); - CPDF_Dictionary* pRootDict = pDocument->GetRoot(); + const CPDF_Dictionary* pRootDict = pDocument->GetRoot(); if (!pRootDict) return nullptr; @@ -105,11 +105,11 @@ CPDF_Font* CBA_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, } CPDF_Document* CBA_FontMap::GetDocument() { - return m_pDocument; + return m_pDocument.Get(); } CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict, - CFX_ByteString& sFontAlias, + ByteString* sFontAlias, int32_t nCharset) { if (!pResDict) return nullptr; @@ -121,7 +121,7 @@ CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict, CPDF_Document* pDocument = GetDocument(); CPDF_Font* pFind = nullptr; for (const auto& it : *pFonts) { - const CFX_ByteString& csKey = it.first; + const ByteString& csKey = it.first; if (!it.second) continue; @@ -138,20 +138,19 @@ CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict, if (!pSubst) continue; if (pSubst->m_Charset == nCharset) { - sFontAlias = csKey; + *sFontAlias = csKey; pFind = pFont; } } return pFind; } -void CBA_FontMap::AddedFont(CPDF_Font* pFont, - const CFX_ByteString& sFontAlias) { +void CBA_FontMap::AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias) { AddFontToAnnotDict(pFont, sFontAlias); } void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont, - const CFX_ByteString& sAlias) { + const ByteString& sAlias) { if (!pFont) return; @@ -167,7 +166,7 @@ void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont, CPDF_Stream* pStream = pAPDict->GetStreamFor(m_sAPType); if (!pStream) { pStream = m_pDocument->NewIndirect(); - pAPDict->SetNewFor(m_sAPType, m_pDocument, + pAPDict->SetNewFor(m_sAPType, m_pDocument.Get(), pStream->GetObjNum()); } @@ -185,64 +184,65 @@ void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont, CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictFor("Font"); if (!pStreamResFontList) { pStreamResFontList = m_pDocument->NewIndirect(); - pStreamResList->SetNewFor("Font", m_pDocument, + pStreamResList->SetNewFor("Font", m_pDocument.Get(), pStreamResFontList->GetObjNum()); } if (!pStreamResFontList->KeyExist(sAlias)) { pStreamResFontList->SetNewFor( - sAlias, m_pDocument, pFont->GetFontDict()->GetObjNum()); + sAlias, m_pDocument.Get(), pFont->GetFontDict()->GetObjNum()); } } -CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(CFX_ByteString& sAlias) { +CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(ByteString* sAlias) { CPDF_Dictionary* pAcroFormDict = nullptr; const bool bWidget = (m_pAnnotDict->GetStringFor("Subtype") == "Widget"); if (bWidget) { - if (CPDF_Dictionary* pRootDict = m_pDocument->GetRoot()) + const CPDF_Dictionary* pRootDict = m_pDocument->GetRoot(); + if (pRootDict) pAcroFormDict = pRootDict->GetDictFor("AcroForm"); } - CFX_ByteString sDA; - CPDF_Object* pObj = FPDF_GetFieldAttr(m_pAnnotDict, "DA"); + ByteString sDA; + CPDF_Object* pObj = FPDF_GetFieldAttr(m_pAnnotDict.Get(), "DA"); if (pObj) sDA = pObj->GetString(); if (bWidget) { if (sDA.IsEmpty()) { pObj = FPDF_GetFieldAttr(pAcroFormDict, "DA"); - sDA = pObj ? pObj->GetString() : CFX_ByteString(); + sDA = pObj ? pObj->GetString() : ByteString(); } } if (sDA.IsEmpty()) return nullptr; - CPDF_SimpleParser syntax(sDA.AsStringC()); + CPDF_SimpleParser syntax(sDA.AsStringView()); syntax.FindTagParamFromStart("Tf", 2); - CFX_ByteString sFontName(syntax.GetWord()); - sAlias = PDF_NameDecode(sFontName).Mid(1); - CPDF_Dictionary* pFontDict = nullptr; + ByteString sFontName(syntax.GetWord()); + ByteString sDecodedFontName = PDF_NameDecode(sFontName); + *sAlias = sDecodedFontName.Right(sDecodedFontName.GetLength() - 1); + + CPDF_Dictionary* pFontDict = nullptr; if (CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDictFor("AP")) { if (CPDF_Dictionary* pNormalDict = pAPDict->GetDictFor("N")) { if (CPDF_Dictionary* pNormalResDict = pNormalDict->GetDictFor("Resources")) { if (CPDF_Dictionary* pResFontDict = pNormalResDict->GetDictFor("Font")) - pFontDict = pResFontDict->GetDictFor(sAlias); + pFontDict = pResFontDict->GetDictFor(*sAlias); } } } - if (bWidget && !pFontDict && pAcroFormDict) { if (CPDF_Dictionary* pDRDict = pAcroFormDict->GetDictFor("DR")) { if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDictFor("Font")) - pFontDict = pDRFontDict->GetDictFor(sAlias); + pFontDict = pDRFontDict->GetDictFor(*sAlias); } } - return pFontDict ? m_pDocument->LoadFont(pFontDict) : nullptr; } -void CBA_FontMap::SetAPType(const CFX_ByteString& sAPType) { +void CBA_FontMap::SetAPType(const ByteString& sAPType) { m_sAPType = sAPType; Reset(); diff --git a/fpdfsdk/formfiller/cba_fontmap.h b/fpdfsdk/formfiller/cba_fontmap.h index c0e569a0d3f3773c7b98506809d4530b6f452f7e..45df8c82adcf820dd546c394645c353de96c6e99 100644 --- a/fpdfsdk/formfiller/cba_fontmap.h +++ b/fpdfsdk/formfiller/cba_fontmap.h @@ -7,7 +7,8 @@ #ifndef FPDFSDK_FORMFILLER_CBA_FONTMAP_H_ #define FPDFSDK_FORMFILLER_CBA_FONTMAP_H_ -#include "fpdfsdk/pdfwindow/PWL_FontMap.h" +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_font_map.h" class CPDF_Dictionary; class CPDFSDK_Annot; @@ -17,30 +18,29 @@ class CBA_FontMap : public CPWL_FontMap { CBA_FontMap(CPDFSDK_Annot* pAnnot, CFX_SystemHandler* pSystemHandler); ~CBA_FontMap() override; - void SetDefaultFont(CPDF_Font* pFont, const CFX_ByteString& sFontName); - void Reset(); - void SetAPType(const CFX_ByteString& sAPType); + void SetDefaultFont(CPDF_Font* pFont, const ByteString& sFontName); + void SetAPType(const ByteString& sAPType); private: // CPWL_FontMap: void Initialize() override; CPDF_Document* GetDocument() override; - CPDF_Font* FindFontSameCharset(CFX_ByteString& sFontAlias, + CPDF_Font* FindFontSameCharset(ByteString* sFontAlias, int32_t nCharset) override; - void AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias) override; + void AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias) override; CPDF_Font* FindResFontSameCharset(CPDF_Dictionary* pResDict, - CFX_ByteString& sFontAlias, + ByteString* sFontAlias, int32_t nCharset); - CPDF_Font* GetAnnotDefaultFont(CFX_ByteString& csNameTag); - void AddFontToAnnotDict(CPDF_Font* pFont, const CFX_ByteString& sAlias); - - CPDF_Document* m_pDocument; - CPDF_Dictionary* m_pAnnotDict; - CPDF_Font* m_pDefaultFont; - CFX_ByteString m_sDefaultFontName; - CFX_ByteString m_sAPType; + CPDF_Font* GetAnnotDefaultFont(ByteString* csNameTag); + void AddFontToAnnotDict(CPDF_Font* pFont, const ByteString& sAlias); + + UnownedPtr m_pDocument; + UnownedPtr m_pAnnotDict; + UnownedPtr m_pDefaultFont; + ByteString m_sDefaultFontName; + ByteString m_sAPType; }; #endif // FPDFSDK_FORMFILLER_CBA_FONTMAP_H_ diff --git a/fpdfsdk/formfiller/cffl_button.cpp b/fpdfsdk/formfiller/cffl_button.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dab0045373f3271a44832f94695331363a25f302 --- /dev/null +++ b/fpdfsdk/formfiller/cffl_button.cpp @@ -0,0 +1,103 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/formfiller/cffl_button.h" + +CFFL_Button::CFFL_Button(CPDFSDK_FormFillEnvironment* pApp, + CPDFSDK_Widget* pWidget) + : CFFL_FormFiller(pApp, pWidget), m_bMouseIn(false), m_bMouseDown(false) {} + +CFFL_Button::~CFFL_Button() {} + +void CFFL_Button::OnMouseEnter(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot) { + m_bMouseIn = true; + InvalidateRect(GetViewBBox(pPageView, pAnnot)); +} + +void CFFL_Button::OnMouseExit(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot) { + m_bMouseIn = false; + InvalidateRect(GetViewBBox(pPageView, pAnnot)); + EndTimer(); + ASSERT(m_pWidget); +} + +bool CFFL_Button::OnLButtonDown(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + uint32_t nFlags, + const CFX_PointF& point) { + if (!pAnnot->GetRect().Contains(point)) + return false; + + m_bMouseDown = true; + m_bValid = true; + InvalidateRect(GetViewBBox(pPageView, pAnnot)); + return true; +} + +bool CFFL_Button::OnLButtonUp(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + uint32_t nFlags, + const CFX_PointF& point) { + if (!pAnnot->GetRect().Contains(point)) + return false; + + m_bMouseDown = false; + m_pWidget->GetPDFPage(); + InvalidateRect(GetViewBBox(pPageView, pAnnot)); + return true; +} + +bool CFFL_Button::OnMouseMove(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + uint32_t nFlags, + const CFX_PointF& point) { + return true; +} + +void CFFL_Button::OnDraw(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + ASSERT(pPageView); + CPDFSDK_Widget* pWidget = static_cast(pAnnot); + CPDF_FormControl* pCtrl = pWidget->GetFormControl(); + if (pCtrl->GetHighlightingMode() != CPDF_FormControl::Push) { + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, + nullptr); + return; + } + if (m_bMouseDown) { + if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Down)) { + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Down, + nullptr); + } else { + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, + nullptr); + } + return; + } + if (m_bMouseIn) { + if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Rollover)) { + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Rollover, + nullptr); + } else { + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, + nullptr); + } + return; + } + + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, nullptr); +} + +void CFFL_Button::OnDrawDeactive(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + OnDraw(pPageView, pAnnot, pDevice, mtUser2Device); +} diff --git a/fpdfsdk/formfiller/cffl_button.h b/fpdfsdk/formfiller/cffl_button.h new file mode 100644 index 0000000000000000000000000000000000000000..ad2eb5bd273266482b8322f6914d52079b96e4f3 --- /dev/null +++ b/fpdfsdk/formfiller/cffl_button.h @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_FORMFILLER_CFFL_BUTTON_H_ +#define FPDFSDK_FORMFILLER_CFFL_BUTTON_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "fpdfsdk/formfiller/cffl_formfiller.h" + +class CFX_RenderDevice; +class CFX_Matrix; +class CPDFSDK_Annot; +class CPDFSDK_FormFillEnvironment; +class CPDFSDK_PageView; +class CPDFSDK_Widget; + +class CFFL_Button : public CFFL_FormFiller { + public: + CFFL_Button(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDFSDK_Widget* pWidget); + ~CFFL_Button() override; + + // CFFL_FormFiller + void OnMouseEnter(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot) override; + void OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; + bool OnLButtonDown(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + uint32_t nFlags, + const CFX_PointF& point) override; + bool OnLButtonUp(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + uint32_t nFlags, + const CFX_PointF& point) override; + bool OnMouseMove(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + uint32_t nFlags, + const CFX_PointF& point) override; + void OnDraw(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + void OnDrawDeactive(CPDFSDK_PageView* pPageView, + CPDFSDK_Annot* pAnnot, + CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + + private: + bool m_bMouseIn; + bool m_bMouseDown; +}; + +#endif // FPDFSDK_FORMFILLER_CFFL_BUTTON_H_ diff --git a/fpdfsdk/formfiller/cffl_checkbox.cpp b/fpdfsdk/formfiller/cffl_checkbox.cpp index c233c136c179fd9e1d56b37082556b3b3198a341..e9c72efd399e2898a29defb999ff336a4c9b3a73 100644 --- a/fpdfsdk/formfiller/cffl_checkbox.cpp +++ b/fpdfsdk/formfiller/cffl_checkbox.cpp @@ -9,7 +9,7 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cffl_formfiller.h" -#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h" +#include "fpdfsdk/pwl/cpwl_special_button.h" #include "public/fpdf_fwlevent.h" CFFL_CheckBox::CFFL_CheckBox(CPDFSDK_FormFillEnvironment* pApp, @@ -18,9 +18,8 @@ CFFL_CheckBox::CFFL_CheckBox(CPDFSDK_FormFillEnvironment* pApp, CFFL_CheckBox::~CFFL_CheckBox() {} -CPWL_Wnd* CFFL_CheckBox::NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) { - CPWL_CheckBox* pWnd = new CPWL_CheckBox(); +CPWL_Wnd* CFFL_CheckBox::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) { + auto* pWnd = new CPWL_CheckBox(); pWnd->Create(cp); pWnd->SetCheck(m_pWidget->IsChecked()); return pWnd; @@ -46,24 +45,27 @@ bool CFFL_CheckBox::OnChar(CPDFSDK_Annot* pAnnot, CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); ASSERT(pPageView); - bool bReset = false; - bool bExit = false; - CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget); - m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp( - &pObserved, pPageView, bReset, bExit, nFlags); + CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get()); + if (m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp( + &pObserved, pPageView, nFlags)) { + if (!pObserved) + m_pWidget = nullptr; + return true; + } if (!pObserved) { m_pWidget = nullptr; return true; } - if (bReset || bExit) - return true; CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); - if (CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, true)) - pWnd->SetCheck(!pWnd->IsChecked()); - CommitData(pPageView, nFlags); - return true; + CPWL_CheckBox* pWnd = GetCheckBox(pPageView, true); + if (pWnd) { + CPDFSDK_Widget* pWidget = static_cast(pAnnot); + pWnd->SetCheck(!pWidget->IsChecked()); + } + + return CommitData(pPageView, nFlags); } default: return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); @@ -76,41 +78,52 @@ bool CFFL_CheckBox::OnLButtonUp(CPDFSDK_PageView* pPageView, const CFX_PointF& point) { CFFL_Button::OnLButtonUp(pPageView, pAnnot, nFlags, point); - if (IsValid()) { - if (CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, true)) { - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; - pWnd->SetCheck(!pWidget->IsChecked()); - } + if (!IsValid()) + return true; - if (!CommitData(pPageView, nFlags)) - return false; + CPWL_CheckBox* pWnd = GetCheckBox(pPageView, true); + if (pWnd) { + CPDFSDK_Widget* pWidget = static_cast(pAnnot); + pWnd->SetCheck(!pWidget->IsChecked()); } - return true; + return CommitData(pPageView, nFlags); } bool CFFL_CheckBox::IsDataChanged(CPDFSDK_PageView* pPageView) { - CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, false); + CPWL_CheckBox* pWnd = GetCheckBox(pPageView, false); return pWnd && pWnd->IsChecked() != m_pWidget->IsChecked(); } void CFFL_CheckBox::SaveData(CPDFSDK_PageView* pPageView) { - if (CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, false)) { - bool bNewChecked = pWnd->IsChecked(); - - if (bNewChecked) { - CPDF_FormField* pField = m_pWidget->GetFormField(); - for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) { - if (CPDF_FormControl* pCtrl = pField->GetControl(i)) { - if (pCtrl->IsChecked()) { - break; - } + CPWL_CheckBox* pWnd = GetCheckBox(pPageView, false); + if (!pWnd) + return; + + bool bNewChecked = pWnd->IsChecked(); + if (bNewChecked) { + CPDF_FormField* pField = m_pWidget->GetFormField(); + for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) { + if (CPDF_FormControl* pCtrl = pField->GetControl(i)) { + if (pCtrl->IsChecked()) { + break; } } } - - m_pWidget->SetCheck(bNewChecked, false); - m_pWidget->UpdateField(); - SetChangeMark(); } + CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get()); + CFFL_CheckBox::ObservedPtr observed_this(this); + + m_pWidget->SetCheck(bNewChecked, false); + if (!observed_widget) + return; + m_pWidget->UpdateField(); + if (!observed_widget || !observed_this) + return; + SetChangeMark(); +} + +CPWL_CheckBox* CFFL_CheckBox::GetCheckBox(CPDFSDK_PageView* pPageView, + bool bNew) { + return static_cast(GetPDFWindow(pPageView, bNew)); } diff --git a/fpdfsdk/formfiller/cffl_checkbox.h b/fpdfsdk/formfiller/cffl_checkbox.h index 79ddc847cc8fcbb17d8406a0586892eb329e87cb..8ef3de6bca1fe4fb6c106b15ad3651351cb6415b 100644 --- a/fpdfsdk/formfiller/cffl_checkbox.h +++ b/fpdfsdk/formfiller/cffl_checkbox.h @@ -7,16 +7,17 @@ #ifndef FPDFSDK_FORMFILLER_CFFL_CHECKBOX_H_ #define FPDFSDK_FORMFILLER_CFFL_CHECKBOX_H_ -#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_button.h" + +class CPWL_CheckBox; class CFFL_CheckBox : public CFFL_Button { public: CFFL_CheckBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); ~CFFL_CheckBox() override; - // CFFL_Button - CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) override; + // CFFL_Button: + CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override; bool OnKeyDown(CPDFSDK_Annot* pAnnot, uint32_t nKeyCode, uint32_t nFlags) override; @@ -27,6 +28,9 @@ class CFFL_CheckBox : public CFFL_Button { const CFX_PointF& point) override; bool IsDataChanged(CPDFSDK_PageView* pPageView) override; void SaveData(CPDFSDK_PageView* pPageView) override; + + private: + CPWL_CheckBox* GetCheckBox(CPDFSDK_PageView* pPageView, bool bNew); }; #endif // FPDFSDK_FORMFILLER_CFFL_CHECKBOX_H_ diff --git a/fpdfsdk/formfiller/cffl_combobox.cpp b/fpdfsdk/formfiller/cffl_combobox.cpp index c8438a3a282f88808338a0cbd0cb2981ab385e2a..d9b12f5d3c8207c9ec77a04a7d318138d2100727 100644 --- a/fpdfsdk/formfiller/cffl_combobox.cpp +++ b/fpdfsdk/formfiller/cffl_combobox.cpp @@ -9,14 +9,14 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cba_fontmap.h" -#include "fpdfsdk/formfiller/cffl_formfiller.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/fsdk_common.h" -#include "fpdfsdk/pdfwindow/PWL_ComboBox.h" +#include "fpdfsdk/pwl/cpwl_combo_box.h" +#include "third_party/base/ptr_util.h" CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, - CPDFSDK_Annot* pAnnot) - : CFFL_FormFiller(pApp, pAnnot), m_pFontMap(nullptr) { + CPDFSDK_Widget* pWidget) + : CFFL_TextObject(pApp, pWidget) { m_State.nIndex = 0; m_State.nStart = 0; m_State.nEnd = 0; @@ -30,28 +30,20 @@ CFFL_ComboBox::~CFFL_ComboBox() { // The font map should be stored somewhere more appropriate so it will live // until the PWL_Edit is done with it. pdfium:566 DestroyWindows(); - delete m_pFontMap; } -PWL_CREATEPARAM CFFL_ComboBox::GetCreateParam() { - PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam(); - - int nFlags = m_pWidget->GetFieldFlags(); - if (nFlags & FIELDFLAG_EDIT) { +CPWL_Wnd::CreateParams CFFL_ComboBox::GetCreateParam() { + CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam(); + if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT) cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT; - } - if (!m_pFontMap) - m_pFontMap = new CBA_FontMap(m_pWidget, GetSystemHandler()); - cp.pFontMap = m_pFontMap; + cp.pFontMap = MaybeCreateFontMap(); cp.pFocusHandler = this; - return cp; } -CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) { - CPWL_ComboBox* pWnd = new CPWL_ComboBox(); +CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) { + auto* pWnd = new CPWL_ComboBox(); pWnd->AttachFFLData(this); pWnd->Create(cp); @@ -60,7 +52,7 @@ CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp, pWnd->SetFillerNotify(pFormFiller); int32_t nCurSel = m_pWidget->GetSelectedIndex(0); - CFX_WideString swText; + WideString swText; if (nCurSel < 0) swText = m_pWidget->GetValue(); else @@ -78,7 +70,7 @@ CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp, bool CFFL_ComboBox::OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) { - return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); + return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags); } bool CFFL_ComboBox::IsDataChanged(CPDFSDK_PageView* pPageView) { @@ -102,7 +94,7 @@ void CFFL_ComboBox::SaveData(CPDFSDK_PageView* pPageView) { if (!pWnd) return; - CFX_WideString swText = pWnd->GetText(); + WideString swText = pWnd->GetText(); int32_t nCurSel = pWnd->GetSelect(); bool bSetValue = false; @@ -116,11 +108,16 @@ void CFFL_ComboBox::SaveData(CPDFSDK_PageView* pPageView) { m_pWidget->GetSelectedIndex(0); m_pWidget->SetOptionSelection(nCurSel, true, false); } + CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get()); + CFFL_ComboBox::ObservedPtr observed_this(this); m_pWidget->ResetFieldAppearance(true); + if (!observed_widget) + return; m_pWidget->UpdateField(); + if (!observed_widget || !observed_this) + return; SetChangeMark(); - m_pWidget->GetPDFPage(); } @@ -135,7 +132,7 @@ void CFFL_ComboBox::GetActionData(CPDFSDK_PageView* pPageView, fa.bFieldFull = pEdit->IsTextFull(); int nSelStart = 0; int nSelEnd = 0; - pEdit->GetSel(nSelStart, nSelEnd); + pEdit->GetSelection(nSelStart, nSelEnd); fa.nSelEnd = nSelEnd; fa.nSelStart = nSelStart; fa.sValue = pEdit->GetText(); @@ -173,7 +170,7 @@ void CFFL_ComboBox::SetActionData(CPDFSDK_PageView* pPageView, if (CPWL_ComboBox* pComboBox = static_cast(GetPDFWindow(pPageView, false))) { if (CPWL_Edit* pEdit = pComboBox->GetEdit()) { - pEdit->SetSel(fa.nSelStart, fa.nSelEnd); + pEdit->SetSelection(fa.nSelStart, fa.nSelEnd); pEdit->ReplaceSel(fa.sChange); } } @@ -206,7 +203,7 @@ void CFFL_ComboBox::SaveState(CPDFSDK_PageView* pPageView) { m_State.nIndex = pComboBox->GetSelect(); if (CPWL_Edit* pEdit = pComboBox->GetEdit()) { - pEdit->GetSel(m_State.nStart, m_State.nEnd); + pEdit->GetSelection(m_State.nStart, m_State.nEnd); m_State.sValue = pEdit->GetText(); } } @@ -222,33 +219,12 @@ void CFFL_ComboBox::RestoreState(CPDFSDK_PageView* pPageView) { } else { if (CPWL_Edit* pEdit = pComboBox->GetEdit()) { pEdit->SetText(m_State.sValue); - pEdit->SetSel(m_State.nStart, m_State.nEnd); + pEdit->SetSelection(m_State.nStart, m_State.nEnd); } } } } -CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView, - bool bRestoreValue) { - if (bRestoreValue) - SaveState(pPageView); - - DestroyPDFWindow(pPageView); - - CPWL_Wnd* pRet = nullptr; - - if (bRestoreValue) { - RestoreState(pPageView); - pRet = GetPDFWindow(pPageView, false); - } else { - pRet = GetPDFWindow(pPageView, true); - } - - m_pWidget->UpdateField(); - - return pRet; -} - #ifdef PDF_ENABLE_XFA bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) { if (CPWL_ComboBox* pComboBox = @@ -260,25 +236,19 @@ bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) { } #endif // PDF_ENABLE_XFA -void CFFL_ComboBox::OnSetFocus(CPWL_Wnd* pWnd) { - ASSERT(m_pFormFillEnv); +void CFFL_ComboBox::OnSetFocus(CPWL_Edit* pEdit) { + pEdit->SetCharSet(FX_CHARSET_ChineseSimplified); + pEdit->SetReadyToInput(); - if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) { - CPWL_Edit* pEdit = (CPWL_Edit*)pWnd; - pEdit->SetCharSet(FXFONT_GB2312_CHARSET); - pEdit->SetCodePage(936); - - pEdit->SetReadyToInput(); - CFX_WideString wsText = pEdit->GetText(); - int nCharacters = wsText.GetLength(); - CFX_ByteString bsUTFText = wsText.UTF16LE_Encode(); - unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str(); - m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true); - } + WideString wsText = pEdit->GetText(); + int nCharacters = wsText.GetLength(); + ByteString bsUTFText = wsText.UTF16LE_Encode(); + auto* pBuffer = reinterpret_cast(bsUTFText.c_str()); + m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true); } -CFX_WideString CFFL_ComboBox::GetSelectExportText() { - CFX_WideString swRet; +WideString CFFL_ComboBox::GetSelectExportText() { + WideString swRet; int nExport = -1; CPDFSDK_PageView* pPageView = GetCurPageView(true); diff --git a/fpdfsdk/formfiller/cffl_combobox.h b/fpdfsdk/formfiller/cffl_combobox.h index aab10b90e14d7bfa421f5993f3950ae27c279d9b..bdc0934862bdf12833194823299b439ada2b2c1e 100644 --- a/fpdfsdk/formfiller/cffl_combobox.h +++ b/fpdfsdk/formfiller/cffl_combobox.h @@ -8,7 +8,7 @@ #define FPDFSDK_FORMFILLER_CFFL_COMBOBOX_H_ #include "core/fxcrt/fx_string.h" -#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_textobject.h" class CBA_FontMap; @@ -16,18 +16,18 @@ struct FFL_ComboBoxState { int nIndex; int nStart; int nEnd; - CFX_WideString sValue; + WideString sValue; }; -class CFFL_ComboBox : public CFFL_FormFiller, public IPWL_FocusHandler { +class CFFL_ComboBox : public CFFL_TextObject, + public CPWL_Wnd::FocusHandlerIface { public: - CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pWidget); + CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); ~CFFL_ComboBox() override; - // CFFL_FormFiller: - PWL_CREATEPARAM GetCreateParam() override; - CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) override; + // CFFL_TextObject: + CPWL_Wnd::CreateParams GetCreateParam() override; + CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override; bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override; bool IsDataChanged(CPDFSDK_PageView* pPageView) override; void SaveData(CPDFSDK_PageView* pPageView) override; @@ -42,21 +42,16 @@ class CFFL_ComboBox : public CFFL_FormFiller, public IPWL_FocusHandler { const PDFSDK_FieldAction& faNew) override; void SaveState(CPDFSDK_PageView* pPageView) override; void RestoreState(CPDFSDK_PageView* pPageView) override; - CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView, - bool bRestoreValue) override; - - // IPWL_FocusHandler: - void OnSetFocus(CPWL_Wnd* pWnd) override; - #ifdef PDF_ENABLE_XFA - // CFFL_FormFiller: bool IsFieldFull(CPDFSDK_PageView* pPageView) override; -#endif // PDF_ENABLE_XFA +#endif + + // CPWL_Wnd::FocusHandlerIface: + void OnSetFocus(CPWL_Edit* pEdit) override; private: - CFX_WideString GetSelectExportText(); + WideString GetSelectExportText(); - CBA_FontMap* m_pFontMap; FFL_ComboBoxState m_State; }; diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp index da6f9208e0465e17a0d3f8263f21ec5924968420..d3aa37e4d5d31a56d976b46a172a20fbe23330c8 100644 --- a/fpdfsdk/formfiller/cffl_formfiller.cpp +++ b/fpdfsdk/formfiller/cffl_formfiller.cpp @@ -6,6 +6,8 @@ #include "fpdfsdk/formfiller/cffl_formfiller.h" +#include + #include "core/fpdfapi/page/cpdf_page.h" #include "core/fxge/cfx_renderdevice.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" @@ -13,18 +15,19 @@ #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cba_fontmap.h" #include "fpdfsdk/fsdk_common.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#define GetRed(rgb) ((uint8_t)(rgb)) -#define GetGreen(rgb) ((uint8_t)(((uint16_t)(rgb)) >> 8)) -#define GetBlue(rgb) ((uint8_t)((rgb) >> 16)) +namespace { + +CPDFSDK_Widget* CPDFSDKAnnotToWidget(CPDFSDK_Annot* annot) { + return static_cast(annot); +} -#define FFL_HINT_ELAPSE 800 +} // namespace CFFL_FormFiller::CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDFSDK_Annot* pAnnot) - : m_pFormFillEnv(pFormFillEnv), m_pAnnot(pAnnot), m_bValid(false) { - m_pWidget = static_cast(pAnnot); + CPDFSDK_Widget* pWidget) + : m_pFormFillEnv(pFormFillEnv), m_pWidget(pWidget), m_bValid(false) { + ASSERT(m_pFormFillEnv); } CFFL_FormFiller::~CFFL_FormFiller() { @@ -34,7 +37,7 @@ CFFL_FormFiller::~CFFL_FormFiller() { void CFFL_FormFiller::DestroyWindows() { for (const auto& it : m_Maps) { CPWL_Wnd* pWnd = it.second; - CFFL_PrivateData* pData = (CFFL_PrivateData*)pWnd->GetAttachedData(); + auto* pData = static_cast(pWnd->GetAttachedData()); pWnd->InvalidateProvider(this); pWnd->Destroy(); delete pWnd; @@ -43,68 +46,53 @@ void CFFL_FormFiller::DestroyWindows() { m_Maps.clear(); } -void CFFL_FormFiller::SetWindowRect(CPDFSDK_PageView* pPageView, - const CFX_FloatRect& rcWindow) { - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { - pWnd->Move(CFX_FloatRect(rcWindow), true, false); - } -} - -CFX_FloatRect CFFL_FormFiller::GetWindowRect(CPDFSDK_PageView* pPageView) { - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { - return pWnd->GetWindowRect(); - } - - return CFX_FloatRect(0, 0, 0, 0); -} - FX_RECT CFFL_FormFiller::GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) { ASSERT(pPageView); ASSERT(pAnnot); CFX_FloatRect rcAnnot = m_pWidget->GetRect(); - - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { - CFX_FloatRect rcWindow = pWnd->GetWindowRect(); - rcAnnot = PWLtoFFL(rcWindow); - } + if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) + rcAnnot = PWLtoFFL(pWnd->GetWindowRect()); CFX_FloatRect rcWin = rcAnnot; - CFX_FloatRect rcFocus = GetFocusBox(pPageView); if (!rcFocus.IsEmpty()) rcWin.Union(rcFocus); - CFX_FloatRect rect = CPWL_Utils::InflateRect(rcWin, 1); - - return rect.GetOuterRect(); + if (!rcWin.IsEmpty()) { + rcWin.Inflate(1, 1); + rcWin.Normalize(); + } + return rcWin.GetOuterRect(); } void CFFL_FormFiller::OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { + const CFX_Matrix& mtUser2Device) { ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { CFX_Matrix mt = GetCurMatrix(); - mt.Concat(*pUser2Device); - pWnd->DrawAppearance(pDevice, &mt); - } else { - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; - if (CFFL_InteractiveFormFiller::IsVisible(pWidget)) - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, - nullptr); + mt.Concat(mtUser2Device); + pWnd->DrawAppearance(pDevice, mt); + return; } + + CPDFSDK_Widget* pWidget = CPDFSDKAnnotToWidget(pAnnot); + if (!CFFL_InteractiveFormFiller::IsVisible(pWidget)) + return; + + pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, nullptr); } void CFFL_FormFiller::OnDrawDeactive(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); + const CFX_Matrix& mtUser2Device) { + CPDFSDKAnnotToWidget(pAnnot)->DrawAppearance(pDevice, mtUser2Device, + CPDF_Annot::Normal, nullptr); } void CFFL_FormFiller::OnMouseEnter(CPDFSDK_PageView* pPageView, @@ -120,17 +108,16 @@ bool CFFL_FormFiller::OnLButtonDown(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, uint32_t nFlags, const CFX_PointF& point) { - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true)) { - m_bValid = true; - FX_RECT rect = GetViewBBox(pPageView, pAnnot); - InvalidateRect(rect); - if (!rect.Contains(static_cast(point.x), static_cast(point.y))) - return false; - - return pWnd->OnLButtonDown(WndtoPWL(pPageView, point), nFlags); - } + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true); + if (!pWnd) + return false; - return false; + m_bValid = true; + FX_RECT rect = GetViewBBox(pPageView, pAnnot); + InvalidateRect(rect); + if (!rect.Contains(static_cast(point.x), static_cast(point.y))) + return false; + return pWnd->OnLButtonDown(WndtoPWL(pPageView, point), nFlags); } bool CFFL_FormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView, @@ -162,9 +149,6 @@ bool CFFL_FormFiller::OnMouseMove(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, uint32_t nFlags, const CFX_PointF& point) { - if (m_ptOldPos != point) - m_ptOldPos = point; - CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); if (!pWnd) return false; @@ -212,31 +196,53 @@ bool CFFL_FormFiller::OnRButtonUp(CPDFSDK_PageView* pPageView, bool CFFL_FormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot, uint32_t nKeyCode, uint32_t nFlags) { - if (IsValid()) { - CPDFSDK_PageView* pPageView = GetCurPageView(true); - ASSERT(pPageView); + if (!IsValid()) + return false; - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { - return pWnd->OnKeyDown(nKeyCode, nFlags); - } - } + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); - return false; + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd && pWnd->OnKeyDown(nKeyCode, nFlags); } bool CFFL_FormFiller::OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) { - if (IsValid()) { - CPDFSDK_PageView* pPageView = GetCurPageView(true); - ASSERT(pPageView); + if (!IsValid()) + return false; - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { - return pWnd->OnChar(nChar, nFlags); - } - } + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); - return false; + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd && pWnd->OnChar(nChar, nFlags); +} + +WideString CFFL_FormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) { + if (!IsValid()) + return WideString(); + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd ? pWnd->GetSelectedText() : WideString(); +} + +void CFFL_FormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) { + if (!IsValid()) + return; + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + if (!pWnd) + return; + + pWnd->ReplaceSelection(text); } void CFFL_FormFiller::SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) { @@ -255,19 +261,16 @@ void CFFL_FormFiller::KillFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) { return; CPDFSDK_PageView* pPageView = GetCurPageView(false); - if (!pPageView) + if (!pPageView || !CommitData(pPageView, nFlag)) return; - - CommitData(pPageView, nFlag); - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) pWnd->KillFocus(); bool bDestroyPDFWindow; switch (m_pWidget->GetFieldType()) { - case FIELDTYPE_PUSHBUTTON: - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: + case FormFieldType::kPushButton: + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: bDestroyPDFWindow = true; break; default: @@ -281,36 +284,27 @@ bool CFFL_FormFiller::IsValid() const { return m_bValid; } -PWL_CREATEPARAM CFFL_FormFiller::GetCreateParam() { - ASSERT(m_pFormFillEnv); - - PWL_CREATEPARAM cp; +CPWL_Wnd::CreateParams CFFL_FormFiller::GetCreateParam() { + CPWL_Wnd::CreateParams cp; cp.pParentWnd = nullptr; cp.pProvider.Reset(this); cp.rcRectWnd = GetPDFWindowRect(); uint32_t dwCreateFlags = PWS_BORDER | PWS_BACKGROUND | PWS_VISIBLE; uint32_t dwFieldFlag = m_pWidget->GetFieldFlags(); - if (dwFieldFlag & FIELDFLAG_READONLY) { + if (dwFieldFlag & FIELDFLAG_READONLY) dwCreateFlags |= PWS_READONLY; - } FX_COLORREF color; - if (m_pWidget->GetFillColor(color)) { - cp.sBackgroundColor = - CPWL_Color(GetRed(color), GetGreen(color), GetBlue(color)); - } - - if (m_pWidget->GetBorderColor(color)) { - cp.sBorderColor = - CPWL_Color(GetRed(color), GetGreen(color), GetBlue(color)); - } + if (m_pWidget->GetFillColor(color)) + cp.sBackgroundColor = CFX_Color(color); + if (m_pWidget->GetBorderColor(color)) + cp.sBorderColor = CFX_Color(color); - cp.sTextColor = CPWL_Color(COLORTYPE_GRAY, 0); + cp.sTextColor = CFX_Color(CFX_Color::kGray, 0); - if (m_pWidget->GetTextColor(color)) { - cp.sTextColor = CPWL_Color(GetRed(color), GetGreen(color), GetBlue(color)); - } + if (m_pWidget->GetTextColor(color)) + cp.sTextColor = CFX_Color(color); cp.fFontSize = m_pWidget->GetFontSize(); cp.dwBorderWidth = m_pWidget->GetBorderWidth(); @@ -321,8 +315,6 @@ PWL_CREATEPARAM CFFL_FormFiller::GetCreateParam() { cp.sDash = CPWL_Dash(3, 3, 0); break; case BorderStyle::BEVELED: - cp.dwBorderWidth *= 2; - break; case BorderStyle::INSET: cp.dwBorderWidth *= 2; break; @@ -348,29 +340,27 @@ CPWL_Wnd* CFFL_FormFiller::GetPDFWindow(CPDFSDK_PageView* pPageView, if (!bNew) return pWnd; - if (found) { - CFFL_PrivateData* pPrivateData = (CFFL_PrivateData*)pWnd->GetAttachedData(); - if (pPrivateData->nWidgetAge != m_pWidget->GetAppearanceAge()) { - return ResetPDFWindow( - pPageView, m_pWidget->GetValueAge() == pPrivateData->nValueAge); - } - } else { - PWL_CREATEPARAM cp = GetCreateParam(); - cp.pAttachedWidget.Reset(m_pWidget); - - CFFL_PrivateData* pPrivateData = new CFFL_PrivateData; - pPrivateData->pWidget = m_pWidget; - pPrivateData->pPageView = pPageView; - pPrivateData->nWidgetAge = m_pWidget->GetAppearanceAge(); - pPrivateData->nValueAge = 0; + if (!found) { + CPWL_Wnd::CreateParams cp = GetCreateParam(); + cp.pAttachedWidget.Reset(m_pWidget.Get()); + auto* pPrivateData = new CFFL_PrivateData; + pPrivateData->pWidget = m_pWidget.Get(); + pPrivateData->pPageView = pPageView; + pPrivateData->nWidgetAppearanceAge = m_pWidget->GetAppearanceAge(); + pPrivateData->nWidgetValueAge = 0; cp.pAttachedData = pPrivateData; - - pWnd = NewPDFWindow(cp, pPageView); - m_Maps[pPageView] = pWnd; + CPWL_Wnd* pNewWnd = NewPDFWindow(cp); + m_Maps[pPageView] = pNewWnd; + return pNewWnd; } - return pWnd; + auto* pPrivateData = static_cast(pWnd->GetAttachedData()); + if (pPrivateData->nWidgetAppearanceAge == m_pWidget->GetAppearanceAge()) + return pWnd; + + return ResetPDFWindow( + pPageView, pPrivateData->nWidgetValueAge == m_pWidget->GetValueAge()); } void CFFL_FormFiller::DestroyPDFWindow(CPDFSDK_PageView* pPageView) { @@ -379,39 +369,30 @@ void CFFL_FormFiller::DestroyPDFWindow(CPDFSDK_PageView* pPageView) { return; CPWL_Wnd* pWnd = it->second; - CFFL_PrivateData* pData = (CFFL_PrivateData*)pWnd->GetAttachedData(); + auto* pData = static_cast(pWnd->GetAttachedData()); pWnd->Destroy(); delete pWnd; delete pData; - m_Maps.erase(it); } -CFX_Matrix CFFL_FormFiller::GetWindowMatrix(void* pAttachedData) { - if (CFFL_PrivateData* pPrivateData = (CFFL_PrivateData*)pAttachedData) { - if (pPrivateData->pPageView) { - CFX_Matrix mtPageView; - pPrivateData->pPageView->GetCurrentMatrix(mtPageView); - - CFX_Matrix mt = GetCurMatrix(); - mt.Concat(mtPageView); - - return mt; - } - } - return CFX_Matrix(1, 0, 0, 1, 0, 0); +CFX_Matrix CFFL_FormFiller::GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) { + CFX_Matrix mt; + auto* pPrivateData = static_cast(pAttached); + if (!pPrivateData || !pPrivateData->pPageView) + return mt; + + CFX_Matrix mtPageView; + pPrivateData->pPageView->GetCurrentMatrix(mtPageView); + mt = GetCurMatrix(); + mt.Concat(mtPageView); + return mt; } CFX_Matrix CFFL_FormFiller::GetCurMatrix() { CFX_Matrix mt; - CFX_FloatRect rcDA = m_pWidget->GetPDFAnnot()->GetRect(); - switch (m_pWidget->GetRotate()) { - default: - case 0: - mt = CFX_Matrix(1, 0, 0, 1, 0, 0); - break; case 90: mt = CFX_Matrix(0, 1, -1, 0, rcDA.right - rcDA.left, 0); break; @@ -422,6 +403,9 @@ CFX_Matrix CFFL_FormFiller::GetCurMatrix() { case 270: mt = CFX_Matrix(0, -1, 1, 0, 0, rcDA.top - rcDA.bottom); break; + case 0: + default: + break; } mt.e += rcDA.left; mt.f += rcDA.bottom; @@ -429,61 +413,42 @@ CFX_Matrix CFFL_FormFiller::GetCurMatrix() { return mt; } -CFX_WideString CFFL_FormFiller::LoadPopupMenuString(int nIndex) { - ASSERT(m_pFormFillEnv); - - return L""; -} - CFX_FloatRect CFFL_FormFiller::GetPDFWindowRect() const { CFX_FloatRect rectAnnot = m_pWidget->GetPDFAnnot()->GetRect(); - FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left; - FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom; + float fWidth = rectAnnot.right - rectAnnot.left; + float fHeight = rectAnnot.top - rectAnnot.bottom; if ((m_pWidget->GetRotate() / 90) & 0x01) - return CFX_FloatRect(0, 0, fHeight, fWidth); - + std::swap(fWidth, fHeight); return CFX_FloatRect(0, 0, fWidth, fHeight); } CPDFSDK_PageView* CFFL_FormFiller::GetCurPageView(bool renew) { - UnderlyingPageType* pPage = m_pAnnot->GetUnderlyingPage(); - return m_pFormFillEnv ? m_pFormFillEnv->GetPageView(pPage, renew) : nullptr; + UnderlyingPageType* pPage = m_pWidget->GetUnderlyingPage(); + return m_pFormFillEnv->GetPageView(pPage, renew); } CFX_FloatRect CFFL_FormFiller::GetFocusBox(CPDFSDK_PageView* pPageView) { - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) { - CFX_FloatRect rcFocus = FFLtoWnd(pPageView, PWLtoFFL(pWnd->GetFocusRect())); - CFX_FloatRect rcPage = pPageView->GetPDFPage()->GetPageBBox(); - if (rcPage.Contains(rcFocus)) - return rcFocus; - } - return CFX_FloatRect(0, 0, 0, 0); + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + if (!pWnd) + return CFX_FloatRect(); + + CFX_FloatRect rcFocus = FFLtoWnd(pPageView, PWLtoFFL(pWnd->GetFocusRect())); + return pPageView->GetPDFPage()->GetPageBBox().Contains(rcFocus) + ? rcFocus + : CFX_FloatRect(); } CFX_FloatRect CFFL_FormFiller::FFLtoPWL(const CFX_FloatRect& rect) { - CFX_Matrix mt; - mt.SetReverse(GetCurMatrix()); - - CFX_FloatRect temp = rect; - mt.TransformRect(temp); - - return temp; + return GetCurMatrix().GetInverse().TransformRect(rect); } CFX_FloatRect CFFL_FormFiller::PWLtoFFL(const CFX_FloatRect& rect) { - CFX_Matrix mt = GetCurMatrix(); - - CFX_FloatRect temp = rect; - mt.TransformRect(temp); - - return temp; + return GetCurMatrix().TransformRect(rect); } CFX_PointF CFFL_FormFiller::FFLtoPWL(const CFX_PointF& point) { - CFX_Matrix mt; - mt.SetReverse(GetCurMatrix()); - return mt.Transform(point); + return GetCurMatrix().GetInverse().Transform(point); } CFX_PointF CFFL_FormFiller::PWLtoFFL(const CFX_PointF& point) { @@ -501,33 +466,43 @@ CFX_FloatRect CFFL_FormFiller::FFLtoWnd(CPDFSDK_PageView* pPageView, } bool CFFL_FormFiller::CommitData(CPDFSDK_PageView* pPageView, uint32_t nFlag) { - if (IsDataChanged(pPageView)) { - bool bRC = true; - bool bExit = false; - CFFL_InteractiveFormFiller* pFormFiller = - m_pFormFillEnv->GetInteractiveFormFiller(); - CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget); - pFormFiller->OnKeyStrokeCommit(&pObserved, pPageView, bRC, bExit, nFlag); - if (!pObserved || bExit) - return true; - if (!bRC) { - ResetPDFWindow(pPageView, false); - return true; - } - pFormFiller->OnValidate(&pObserved, pPageView, bRC, bExit, nFlag); - if (!pObserved || bExit) - return true; - if (!bRC) { - ResetPDFWindow(pPageView, false); - return true; - } - SaveData(pPageView); - pFormFiller->OnCalculate(m_pWidget, pPageView, bExit, nFlag); - if (bExit) - return true; - - pFormFiller->OnFormat(m_pWidget, pPageView, bExit, nFlag); + if (!IsDataChanged(pPageView)) + return true; + + CFFL_InteractiveFormFiller* pFormFiller = + m_pFormFillEnv->GetInteractiveFormFiller(); + CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get()); + + if (!pFormFiller->OnKeyStrokeCommit(&pObserved, pPageView, nFlag)) { + if (!pObserved) + return false; + ResetPDFWindow(pPageView, false); + return true; } + if (!pObserved) + return false; + + if (!pFormFiller->OnValidate(&pObserved, pPageView, nFlag)) { + if (!pObserved) + return false; + ResetPDFWindow(pPageView, false); + return true; + } + if (!pObserved) + return false; + + SaveData(pPageView); // may invoking JS to delete this widget. + if (!pObserved) + return false; + + pFormFiller->OnCalculate(&pObserved, pPageView, nFlag); + if (!pObserved) + return false; + + pFormFiller->OnFormat(&pObserved, pPageView, nFlag); + if (!pObserved) + return false; + return true; } @@ -582,7 +557,7 @@ void CFFL_FormFiller::EscapeFiller(CPDFSDK_PageView* pPageView, bool bDestroyPDFWindow) { m_bValid = false; - InvalidateRect(GetViewBBox(pPageView, m_pWidget)); + InvalidateRect(GetViewBBox(pPageView, m_pWidget.Get())); if (bDestroyPDFWindow) DestroyPDFWindow(pPageView); } @@ -590,98 +565,3 @@ void CFFL_FormFiller::EscapeFiller(CPDFSDK_PageView* pPageView, void CFFL_FormFiller::InvalidateRect(const FX_RECT& rect) { m_pFormFillEnv->Invalidate(m_pWidget->GetUnderlyingPage(), rect); } - -CFFL_Button::CFFL_Button(CPDFSDK_FormFillEnvironment* pApp, - CPDFSDK_Annot* pWidget) - : CFFL_FormFiller(pApp, pWidget), m_bMouseIn(false), m_bMouseDown(false) {} - -CFFL_Button::~CFFL_Button() {} - -void CFFL_Button::OnMouseEnter(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot) { - m_bMouseIn = true; - InvalidateRect(GetViewBBox(pPageView, pAnnot)); -} - -void CFFL_Button::OnMouseExit(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot) { - m_bMouseIn = false; - - InvalidateRect(GetViewBBox(pPageView, pAnnot)); - EndTimer(); - ASSERT(m_pWidget); -} - -bool CFFL_Button::OnLButtonDown(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - uint32_t nFlags, - const CFX_PointF& point) { - if (!pAnnot->GetRect().Contains(point)) - return false; - - m_bMouseDown = true; - m_bValid = true; - InvalidateRect(GetViewBBox(pPageView, pAnnot)); - return true; -} - -bool CFFL_Button::OnLButtonUp(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - uint32_t nFlags, - const CFX_PointF& point) { - if (!pAnnot->GetRect().Contains(point)) - return false; - - m_bMouseDown = false; - m_pWidget->GetPDFPage(); - - InvalidateRect(GetViewBBox(pPageView, pAnnot)); - return true; -} - -bool CFFL_Button::OnMouseMove(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - uint32_t nFlags, - const CFX_PointF& point) { - ASSERT(m_pFormFillEnv); - return true; -} - -void CFFL_Button::OnDraw(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - ASSERT(pPageView); - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; - CPDF_FormControl* pCtrl = pWidget->GetFormControl(); - CPDF_FormControl::HighlightingMode eHM = pCtrl->GetHighlightingMode(); - - if (eHM != CPDF_FormControl::Push) { - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); - return; - } - - if (m_bMouseDown) { - if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Down)) - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Down, nullptr); - else - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, - nullptr); - } else if (m_bMouseIn) { - if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Rollover)) - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Rollover, - nullptr); - else - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, - nullptr); - } else { - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); - } -} - -void CFFL_Button::OnDrawDeactive(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - OnDraw(pPageView, pAnnot, pDevice, pUser2Device); -} diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h index c6b1e59786df4d3afffcd04fc25c933cb36cd24b..11a2f8c935a20ebfb89f00783ef7f5a4fdb6f959 100644 --- a/fpdfsdk/formfiller/cffl_formfiller.h +++ b/fpdfsdk/formfiller/cffl_formfiller.h @@ -9,6 +9,7 @@ #include +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/formfiller/cba_fontmap.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/pdfsdk_fieldaction.h" @@ -18,10 +19,11 @@ class CPDFSDK_FormFillEnvironment; class CPDFSDK_PageView; class CPDFSDK_Widget; -class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { +class CFFL_FormFiller : public CPWL_Wnd::ProviderIface, + public CPWL_TimerHandler { public: CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDFSDK_Annot* pAnnot); + CPDFSDK_Widget* pWidget); ~CFFL_FormFiller() override; virtual FX_RECT GetViewBBox(CPDFSDK_PageView* pPageView, @@ -29,11 +31,11 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { virtual void OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device); + const CFX_Matrix& mtUser2Device); virtual void OnDrawDeactive(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device); + const CFX_Matrix& mtUser2Device); virtual void OnMouseEnter(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot); virtual void OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot); @@ -73,6 +75,9 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { uint32_t nFlags); virtual bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags); + WideString GetSelectedText(CPDFSDK_Annot* pAnnot); + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text); + void SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag); void KillFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag); @@ -80,9 +85,8 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { void TimerProc() override; CFX_SystemHandler* GetSystemHandler() const override; - // IPWL_Provider - CFX_Matrix GetWindowMatrix(void* pAttachedData) override; - CFX_WideString LoadPopupMenuString(int nIndex) override; + // CPWL_Wnd::ProviderIface: + CFX_Matrix GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) override; virtual void GetActionData(CPDFSDK_PageView* pPageView, CPDF_AAction::AActionType type, @@ -111,10 +115,6 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { CFX_FloatRect FFLtoWnd(CPDFSDK_PageView* pPageView, const CFX_FloatRect& rect); - void SetWindowRect(CPDFSDK_PageView* pPageView, - const CFX_FloatRect& rcWindow); - CFX_FloatRect GetWindowRect(CPDFSDK_PageView* pPageView); - bool CommitData(CPDFSDK_PageView* pPageView, uint32_t nFlag); virtual bool IsDataChanged(CPDFSDK_PageView* pPageView); virtual void SaveData(CPDFSDK_PageView* pPageView); @@ -127,9 +127,8 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { void DestroyPDFWindow(CPDFSDK_PageView* pPageView); void EscapeFiller(CPDFSDK_PageView* pPageView, bool bDestroyPDFWindow); - virtual PWL_CREATEPARAM GetCreateParam(); - virtual CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) = 0; + virtual CPWL_Wnd::CreateParams GetCreateParam(); + virtual CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) = 0; virtual CFX_FloatRect GetFocusBox(CPDFSDK_PageView* pPageView); bool IsValid() const; @@ -138,8 +137,7 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { CPDFSDK_PageView* GetCurPageView(bool renew); void SetChangeMark(); - virtual void InvalidateRect(const FX_RECT& rect); - CPDFSDK_Annot* GetSDKAnnot() { return m_pAnnot; } + CPDFSDK_Annot* GetSDKAnnot() { return m_pWidget.Get(); } protected: using CFFL_PageView2PDFWindow = std::map; @@ -152,48 +150,12 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { // until the PWL_Edit is done with it. pdfium:566 void DestroyWindows(); - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; - CPDFSDK_Widget* m_pWidget; - CPDFSDK_Annot* m_pAnnot; + void InvalidateRect(const FX_RECT& rect); + + UnownedPtr const m_pFormFillEnv; + UnownedPtr m_pWidget; bool m_bValid; CFFL_PageView2PDFWindow m_Maps; - CFX_PointF m_ptOldPos; -}; - -class CFFL_Button : public CFFL_FormFiller { - public: - CFFL_Button(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDFSDK_Annot* pWidget); - ~CFFL_Button() override; - - // CFFL_FormFiller - void OnMouseEnter(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot) override; - void OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; - bool OnLButtonDown(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - uint32_t nFlags, - const CFX_PointF& point) override; - bool OnLButtonUp(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - uint32_t nFlags, - const CFX_PointF& point) override; - bool OnMouseMove(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - uint32_t nFlags, - const CFX_PointF& point) override; - void OnDraw(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - void OnDrawDeactive(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - - protected: - bool m_bMouseIn; - bool m_bMouseDown; }; #endif // FPDFSDK_FORMFILLER_CFFL_FORMFILLER_H_ diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp index a830d529cbabb1836db41191a37aaea7281c5e41..e74f902bd23ff834914d7ae4b47236f75a4061e6 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp @@ -8,6 +8,7 @@ #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fxcrt/autorestorer.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" @@ -22,9 +23,7 @@ #include "fpdfsdk/formfiller/cffl_pushbutton.h" #include "fpdfsdk/formfiller/cffl_radiobutton.h" #include "fpdfsdk/formfiller/cffl_textfield.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" - -#define FFL_MAXLISTBOXHEIGHT 140.0f +#include "third_party/base/stl_util.h" CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller( CPDFSDK_FormFillEnvironment* pFormFillEnv) @@ -46,7 +45,11 @@ FX_RECT CFFL_InteractiveFormFiller::GetViewBBox(CPDFSDK_PageView* pPageView, ASSERT(pPageView); CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot(); - CFX_FloatRect rcWin = CPWL_Utils::InflateRect(pPDFAnnot->GetRect(), 1); + CFX_FloatRect rcWin = pPDFAnnot->GetRect(); + if (!rcWin.IsEmpty()) { + rcWin.Inflate(1, 1); + rcWin.Normalize(); + } return rcWin.GetOuterRect(); } @@ -55,48 +58,50 @@ void CFFL_InteractiveFormFiller::OnDraw(CPDFSDK_PageView* pPageView, CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device) { ASSERT(pPageView); - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; - + CPDFSDK_Widget* pWidget = static_cast(pAnnot); if (!IsVisible(pWidget)) return; - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) { - if (pFormFiller->IsValid()) { - pFormFiller->OnDraw(pPageView, pAnnot, pDevice, pUser2Device); - pAnnot->GetPDFPage(); - - if (m_pFormFillEnv->GetFocusAnnot() == pAnnot) { - CFX_FloatRect rcFocus = pFormFiller->GetFocusBox(pPageView); - if (!rcFocus.IsEmpty()) { - CFX_PathData path; - path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), - FXPT_TYPE::MoveTo, false); - path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.bottom), - FXPT_TYPE::LineTo, false); - path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.bottom), - FXPT_TYPE::LineTo, false); - path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.top), - FXPT_TYPE::LineTo, false); - path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), - FXPT_TYPE::LineTo, false); - - CFX_GraphStateData gsd; - gsd.SetDashCount(1); - gsd.m_DashArray[0] = 1.0f; - gsd.m_DashPhase = 0; - gsd.m_LineWidth = 1.0f; - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, - ArgbEncode(255, 0, 0, 0), FXFILL_ALTERNATE); - } - } + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + if (pFormFiller && pFormFiller->IsValid()) { + pFormFiller->OnDraw(pPageView, pAnnot, pDevice, *pUser2Device); + pAnnot->GetPDFPage(); + + if (m_pFormFillEnv->GetFocusAnnot() != pAnnot) return; - } + + CFX_FloatRect rcFocus = pFormFiller->GetFocusBox(pPageView); + if (rcFocus.IsEmpty()) + return; + + CFX_PathData path; + path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::MoveTo, + false); + path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.bottom), + FXPT_TYPE::LineTo, false); + path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.bottom), + FXPT_TYPE::LineTo, false); + path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.top), FXPT_TYPE::LineTo, + false); + path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::LineTo, + false); + + CFX_GraphStateData gsd; + gsd.SetDashCount(1); + gsd.m_DashArray[0] = 1.0f; + gsd.m_DashPhase = 0; + gsd.m_LineWidth = 1.0f; + pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0), + FXFILL_ALTERNATE); + return; } - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) { - pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, pUser2Device); + pFormFiller = GetFormFiller(pAnnot, false); + if (pFormFiller) { + pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, *pUser2Device); } else { - pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr); + pWidget->DrawAppearance(pDevice, *pUser2Device, CPDF_Annot::Normal, + nullptr); } if (!IsReadOnly(pWidget) && IsFillingAllowed(pWidget)) @@ -117,13 +122,13 @@ void CFFL_InteractiveFormFiller::OnMouseEnter( if (pWidget->GetAAction(CPDF_AAction::CursorEnter).GetDict()) { m_bNotifying = true; - int nValueAge = pWidget->GetValueAge(); + uint32_t nValueAge = pWidget->GetValueAge(); pWidget->ClearAppModified(); ASSERT(pPageView); PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); pWidget->OnAAction(CPDF_AAction::CursorEnter, fa, pPageView); m_bNotifying = false; if (!(*pAnnot)) @@ -149,15 +154,14 @@ void CFFL_InteractiveFormFiller::OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); if (pWidget->GetAAction(CPDF_AAction::CursorExit).GetDict()) { m_bNotifying = true; - pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + uint32_t nValueAge = pWidget->GetValueAge(); pWidget->ClearAppModified(); ASSERT(pPageView); PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); pWidget->OnAAction(CPDF_AAction::CursorExit, fa, pPageView); m_bNotifying = false; if (!(*pAnnot)) @@ -186,15 +190,14 @@ bool CFFL_InteractiveFormFiller::OnLButtonDown( if (Annot_HitTest(pPageView, pAnnot->Get(), point) && pWidget->GetAAction(CPDF_AAction::ButtonDown).GetDict()) { m_bNotifying = true; - pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + uint32_t nValueAge = pWidget->GetValueAge(); pWidget->ClearAppModified(); ASSERT(pPageView); PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlags); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlags); + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlags); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlags); pWidget->OnAAction(CPDF_AAction::ButtonDown, fa, pPageView); m_bNotifying = false; if (!(*pAnnot)) @@ -211,10 +214,9 @@ bool CFFL_InteractiveFormFiller::OnLButtonDown( } } } - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false)) - return pFormFiller->OnLButtonDown(pPageView, pAnnot->Get(), nFlags, point); - - return false; + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); + return pFormFiller && + pFormFiller->OnLButtonDown(pPageView, pAnnot->Get(), nFlags, point); } bool CFFL_InteractiveFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView, @@ -224,70 +226,67 @@ bool CFFL_InteractiveFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView, ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + bool bSetFocus; switch (pWidget->GetFieldType()) { - case FIELDTYPE_PUSHBUTTON: - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: - if (GetViewBBox(pPageView, pAnnot->Get()) - .Contains((int)point.x, (int)point.y)) - m_pFormFillEnv->SetFocusAnnot(pAnnot); + case FormFieldType::kPushButton: + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: { + FX_RECT bbox = GetViewBBox(pPageView, pAnnot->Get()); + bSetFocus = + bbox.Contains(static_cast(point.x), static_cast(point.y)); break; + } default: - m_pFormFillEnv->SetFocusAnnot(pAnnot); + bSetFocus = true; break; } + if (bSetFocus) + m_pFormFillEnv->SetFocusAnnot(pAnnot); - bool bRet = false; - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false)) - bRet = pFormFiller->OnLButtonUp(pPageView, pAnnot->Get(), nFlags, point); - - if (m_pFormFillEnv->GetFocusAnnot() == pAnnot->Get()) { - bool bExit = false; - bool bReset = false; - OnButtonUp(pAnnot, pPageView, bReset, bExit, nFlags); - if (!pAnnot || bExit) - return true; + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); + bool bRet = pFormFiller && + pFormFiller->OnLButtonUp(pPageView, pAnnot->Get(), nFlags, point); + if (m_pFormFillEnv->GetFocusAnnot() != pAnnot->Get()) + return bRet; + if (OnButtonUp(pAnnot, pPageView, nFlags) || !pAnnot) + return true; #ifdef PDF_ENABLE_XFA - OnClick(pWidget, pPageView, bReset, bExit, nFlags); - if (!pAnnot || bExit) - return true; + if (OnClick(pAnnot, pPageView, nFlags) || !pAnnot) + return true; #endif // PDF_ENABLE_XFA - } return bRet; } -void CFFL_InteractiveFormFiller::OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot, +bool CFFL_InteractiveFormFiller::OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); - if (pWidget->GetAAction(CPDF_AAction::ButtonUp).GetDict()) { - m_bNotifying = true; + if (m_bNotifying) + return false; - int nAge = pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); - ASSERT(pPageView); + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->GetAAction(CPDF_AAction::ButtonUp).GetDict()) + return false; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); - pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView); - m_bNotifying = false; - if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) { - bExit = true; - return; - } - if (nAge != pWidget->GetAppearanceAge()) { - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { - pFormFiller->ResetPDFWindow(pPageView, - nValueAge == pWidget->GetValueAge()); - } - bReset = true; - } - } - } + m_bNotifying = true; + + uint32_t nAge = pWidget->GetAppearanceAge(); + uint32_t nValueAge = pWidget->GetValueAge(); + ASSERT(pPageView); + + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); + pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView); + m_bNotifying = false; + if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) + return true; + if (nAge == pWidget->GetAppearanceAge()) + return false; + + CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); + if (pFormFiller) + pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); + return true; } bool CFFL_InteractiveFormFiller::OnLButtonDblClk( @@ -350,11 +349,8 @@ bool CFFL_InteractiveFormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot, uint32_t nFlags) { ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) { - return pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags); - } - - return false; + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller && pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags); } bool CFFL_InteractiveFormFiller::OnChar(CPDFSDK_Annot* pAnnot, @@ -364,10 +360,8 @@ bool CFFL_InteractiveFormFiller::OnChar(CPDFSDK_Annot* pAnnot, if (nChar == FWL_VKEY_Tab) return true; - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) - return pFormFiller->OnChar(pAnnot, nChar, nFlags); - - return false; + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller && pFormFiller->OnChar(pAnnot, nChar, nFlags); } bool CFFL_InteractiveFormFiller::OnSetFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, @@ -380,9 +374,8 @@ bool CFFL_InteractiveFormFiller::OnSetFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); if (pWidget->GetAAction(CPDF_AAction::GetFocus).GetDict()) { m_bNotifying = true; - pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + uint32_t nValueAge = pWidget->GetValueAge(); pWidget->ClearAppModified(); CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, true); @@ -393,8 +386,8 @@ bool CFFL_InteractiveFormFiller::OnSetFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, ASSERT(pPageView); PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); pFormFiller->GetActionData(pPageView, CPDF_AAction::GetFocus, fa); pWidget->OnAAction(CPDF_AAction::GetFocus, fa, pPageView); m_bNotifying = false; @@ -422,29 +415,34 @@ bool CFFL_InteractiveFormFiller::OnKillFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, return false; ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false)) { - pFormFiller->KillFocusForAnnot(pAnnot->Get(), nFlag); - if (!m_bNotifying) { - CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); - if (pWidget->GetAAction(CPDF_AAction::LoseFocus).GetDict()) { - m_bNotifying = true; - pWidget->ClearAppModified(); - - CPDFSDK_PageView* pPageView = pWidget->GetPageView(); - ASSERT(pPageView); - - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); - pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa); - pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView); - m_bNotifying = false; - if (!(*pAnnot)) - return false; - } - } - } - return true; + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); + if (!pFormFiller) + return true; + + pFormFiller->KillFocusForAnnot(pAnnot->Get(), nFlag); + if (!(*pAnnot)) + return false; + + if (m_bNotifying) + return true; + + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->GetAAction(CPDF_AAction::LoseFocus).GetDict()) + return true; + + m_bNotifying = true; + pWidget->ClearAppModified(); + + CPDFSDK_PageView* pPageView = pWidget->GetPageView(); + ASSERT(pPageView); + + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); + pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa); + pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView); + m_bNotifying = false; + return !!(*pAnnot); } bool CFFL_InteractiveFormFiller::IsVisible(CPDFSDK_Widget* pWidget) { @@ -457,12 +455,11 @@ bool CFFL_InteractiveFormFiller::IsReadOnly(CPDFSDK_Widget* pWidget) { } bool CFFL_InteractiveFormFiller::IsFillingAllowed(CPDFSDK_Widget* pWidget) { - if (pWidget->GetFieldType() == FIELDTYPE_PUSHBUTTON) - return true; + if (pWidget->GetFieldType() == FormFieldType::kPushButton) + return false; CPDF_Page* pPage = pWidget->GetPDFPage(); - CPDF_Document* pDocument = pPage->m_pDocument; - uint32_t dwPermissions = pDocument->GetUserPermissions(); + uint32_t dwPermissions = pPage->m_pDocument->GetUserPermissions(); return (dwPermissions & FPDFPERM_FILL_FORM) || (dwPermissions & FPDFPERM_ANNOT_FORM) || (dwPermissions & FPDFPERM_MODIFY); @@ -478,29 +475,30 @@ CFFL_FormFiller* CFFL_InteractiveFormFiller::GetFormFiller( if (!bRegister) return nullptr; - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; - int nFieldType = pWidget->GetFieldType(); + // TODO(thestig): How do we know |pAnnot| is a CPDFSDK_Widget? + CPDFSDK_Widget* pWidget = static_cast(pAnnot); + FormFieldType fieldType = pWidget->GetFieldType(); CFFL_FormFiller* pFormFiller; - switch (nFieldType) { - case FIELDTYPE_PUSHBUTTON: - pFormFiller = new CFFL_PushButton(m_pFormFillEnv, pWidget); + switch (fieldType) { + case FormFieldType::kPushButton: + pFormFiller = new CFFL_PushButton(m_pFormFillEnv.Get(), pWidget); break; - case FIELDTYPE_CHECKBOX: - pFormFiller = new CFFL_CheckBox(m_pFormFillEnv, pWidget); + case FormFieldType::kCheckBox: + pFormFiller = new CFFL_CheckBox(m_pFormFillEnv.Get(), pWidget); break; - case FIELDTYPE_RADIOBUTTON: - pFormFiller = new CFFL_RadioButton(m_pFormFillEnv, pWidget); + case FormFieldType::kRadioButton: + pFormFiller = new CFFL_RadioButton(m_pFormFillEnv.Get(), pWidget); break; - case FIELDTYPE_TEXTFIELD: - pFormFiller = new CFFL_TextField(m_pFormFillEnv, pWidget); + case FormFieldType::kTextField: + pFormFiller = new CFFL_TextField(m_pFormFillEnv.Get(), pWidget); break; - case FIELDTYPE_LISTBOX: - pFormFiller = new CFFL_ListBox(m_pFormFillEnv, pWidget); + case FormFieldType::kListBox: + pFormFiller = new CFFL_ListBox(m_pFormFillEnv.Get(), pWidget); break; - case FIELDTYPE_COMBOBOX: - pFormFiller = new CFFL_ComboBox(m_pFormFillEnv, pWidget); + case FormFieldType::kComboBox: + pFormFiller = new CFFL_ComboBox(m_pFormFillEnv.Get(), pWidget); break; - case FIELDTYPE_UNKNOWN: + case FormFieldType::kUnknown: default: pFormFiller = nullptr; break; @@ -513,9 +511,20 @@ CFFL_FormFiller* CFFL_InteractiveFormFiller::GetFormFiller( return pFormFiller; } -void CFFL_InteractiveFormFiller::RemoveFormFiller(CPDFSDK_Annot* pAnnot) { - if (pAnnot) - UnRegisterFormFiller(pAnnot); +WideString CFFL_InteractiveFormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller ? pFormFiller->GetSelectedText(pAnnot) : WideString(); +} + +void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) { + ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + if (!pFormFiller) + return; + + pFormFiller->ReplaceSelection(pAnnot, text); } void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) { @@ -526,24 +535,22 @@ void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) { m_Maps.erase(it); } -void CFFL_InteractiveFormFiller::QueryWherePopup(void* pPrivateData, - FX_FLOAT fPopupMin, - FX_FLOAT fPopupMax, - int32_t& nRet, - FX_FLOAT& fPopupRet) { - CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData; +void CFFL_InteractiveFormFiller::QueryWherePopup( + CPWL_Wnd::PrivateData* pAttached, + float fPopupMin, + float fPopupMax, + bool* bBottom, + float* fPopupRet) { + auto* pData = static_cast(pAttached); + CPDFSDK_Widget* pWidget = pData->pWidget; + CPDF_Page* pPage = pWidget->GetPDFPage(); - CFX_FloatRect rcPageView(0, 0, 0, 0); - rcPageView.right = pData->pWidget->GetPDFPage()->GetPageWidth(); - rcPageView.bottom = pData->pWidget->GetPDFPage()->GetPageHeight(); + CFX_FloatRect rcPageView(0, pPage->GetPageHeight(), pPage->GetPageWidth(), 0); rcPageView.Normalize(); - CFX_FloatRect rcAnnot = pData->pWidget->GetRect(); - - FX_FLOAT fTop = 0.0f; - FX_FLOAT fBottom = 0.0f; - - CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pData->pWidget; + CFX_FloatRect rcAnnot = pWidget->GetRect(); + float fTop = 0.0f; + float fBottom = 0.0f; switch (pWidget->GetRotate() / 90) { default: case 0: @@ -564,308 +571,276 @@ void CFFL_InteractiveFormFiller::QueryWherePopup(void* pPrivateData, break; } - FX_FLOAT fFactHeight = 0; - bool bBottom = true; - FX_FLOAT fMaxListBoxHeight = 0; - if (fPopupMax > FFL_MAXLISTBOXHEIGHT) { - if (fPopupMin > FFL_MAXLISTBOXHEIGHT) { - fMaxListBoxHeight = fPopupMin; - } else { - fMaxListBoxHeight = FFL_MAXLISTBOXHEIGHT; - } - } else { - fMaxListBoxHeight = fPopupMax; - } + constexpr float kMaxListBoxHeight = 140; + const float fMaxListBoxHeight = + pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax); if (fBottom > fMaxListBoxHeight) { - fFactHeight = fMaxListBoxHeight; - bBottom = true; - } else { - if (fTop > fMaxListBoxHeight) { - fFactHeight = fMaxListBoxHeight; - bBottom = false; - } else { - if (fTop > fBottom) { - fFactHeight = fTop; - bBottom = false; - } else { - fFactHeight = fBottom; - bBottom = true; - } - } + *fPopupRet = fMaxListBoxHeight; + *bBottom = true; + return; + } + + if (fTop > fMaxListBoxHeight) { + *fPopupRet = fMaxListBoxHeight; + *bBottom = false; + return; } - nRet = bBottom ? 0 : 1; - fPopupRet = fFactHeight; + if (fTop > fBottom) { + *fPopupRet = fTop; + *bBottom = false; + } else { + *fPopupRet = fBottom; + *bBottom = true; + } } -void CFFL_InteractiveFormFiller::OnKeyStrokeCommit( +bool CFFL_InteractiveFormFiller::OnKeyStrokeCommit( CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bRC, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); - if (pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) { - ASSERT(pPageView); - m_bNotifying = true; - pWidget->ClearAppModified(); + if (m_bNotifying) + return true; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); - fa.bWillCommit = true; - fa.bKeyDown = true; - fa.bRC = true; - - CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); - pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa); - pFormFiller->SaveState(pPageView); - pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView); - if (!(*pAnnot)) - return; + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) + return true; - bRC = fa.bRC; - m_bNotifying = false; - } - } + ASSERT(pPageView); + m_bNotifying = true; + pWidget->ClearAppModified(); + + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); + fa.bWillCommit = true; + fa.bKeyDown = true; + fa.bRC = true; + + CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); + pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa); + pFormFiller->SaveState(pPageView); + pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView); + if (!(*pAnnot)) + return true; + + m_bNotifying = false; + return fa.bRC; } -void CFFL_InteractiveFormFiller::OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot, +bool CFFL_InteractiveFormFiller::OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bRC, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); - if (pWidget->GetAAction(CPDF_AAction::Validate).GetDict()) { - ASSERT(pPageView); - m_bNotifying = true; - pWidget->ClearAppModified(); + if (m_bNotifying) + return true; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); - fa.bKeyDown = true; - fa.bRC = true; - - CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); - pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa); - pFormFiller->SaveState(pPageView); - pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView); - if (!(*pAnnot)) - return; + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->GetAAction(CPDF_AAction::Validate).GetDict()) + return true; - bRC = fa.bRC; - m_bNotifying = false; - } - } + ASSERT(pPageView); + m_bNotifying = true; + pWidget->ClearAppModified(); + + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); + fa.bKeyDown = true; + fa.bRC = true; + + CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); + pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa); + pFormFiller->SaveState(pPageView); + pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView); + if (!(*pAnnot)) + return true; + + m_bNotifying = false; + return fa.bRC; } -void CFFL_InteractiveFormFiller::OnCalculate(CPDFSDK_Widget* pWidget, +void CFFL_InteractiveFormFiller::OnCalculate(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - ASSERT(pWidget); + if (m_bNotifying) + return; + + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (pWidget) { CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm(); pInterForm->OnCalculate(pWidget->GetFormField()); - m_bNotifying = false; } + m_bNotifying = false; } -void CFFL_InteractiveFormFiller::OnFormat(CPDFSDK_Widget* pWidget, +void CFFL_InteractiveFormFiller::OnFormat(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - ASSERT(pWidget); - CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm(); - - bool bFormatted = false; - CFX_WideString sValue = - pInterForm->OnFormat(pWidget->GetFormField(), bFormatted); + if (m_bNotifying) + return; - if (bExit) - return; + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + ASSERT(pWidget); + CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm(); - if (bFormatted) { - pInterForm->ResetFieldAppearance(pWidget->GetFormField(), &sValue, true); - pInterForm->UpdateField(pWidget->GetFormField()); - } + bool bFormatted = false; + WideString sValue = pInterForm->OnFormat(pWidget->GetFormField(), bFormatted); + if (!(*pAnnot)) + return; - m_bNotifying = false; + if (bFormatted) { + pInterForm->ResetFieldAppearance(pWidget->GetFormField(), &sValue, true); + pInterForm->UpdateField(pWidget->GetFormField()); } + + m_bNotifying = false; } #ifdef PDF_ENABLE_XFA -void CFFL_InteractiveFormFiller::OnClick(CPDFSDK_Widget* pWidget, +bool CFFL_InteractiveFormFiller::OnClick(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - if (pWidget->HasXFAAAction(PDFSDK_XFA_Click)) { - m_bNotifying = true; - int nAge = pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + if (m_bNotifying) + return false; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->HasXFAAAction(PDFSDK_XFA_Click)) + return false; - pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView); - m_bNotifying = false; + m_bNotifying = true; + uint32_t nAge = pWidget->GetAppearanceAge(); + uint32_t nValueAge = pWidget->GetValueAge(); - if (!IsValidAnnot(pPageView, pWidget)) { - bExit = true; - return; - } + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); - if (nAge != pWidget->GetAppearanceAge()) { - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { - pFormFiller->ResetPDFWindow(pPageView, - nValueAge == pWidget->GetValueAge()); - } + pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView); + m_bNotifying = false; + if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) + return true; + if (nAge == pWidget->GetAppearanceAge()) + return false; - bReset = true; - } - } - } + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) + pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); + return false; } -void CFFL_InteractiveFormFiller::OnFull(CPDFSDK_Widget* pWidget, +bool CFFL_InteractiveFormFiller::OnFull(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - if (pWidget->HasXFAAAction(PDFSDK_XFA_Full)) { - m_bNotifying = true; - int nAge = pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + if (m_bNotifying) + return false; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->HasXFAAAction(PDFSDK_XFA_Full)) + return false; - pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView); - m_bNotifying = false; + m_bNotifying = true; + uint32_t nAge = pWidget->GetAppearanceAge(); + uint32_t nValueAge = pWidget->GetValueAge(); - if (!IsValidAnnot(pPageView, pWidget)) { - bExit = true; - return; - } + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); - if (nAge != pWidget->GetAppearanceAge()) { - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { - pFormFiller->ResetPDFWindow(pPageView, - nValueAge == pWidget->GetValueAge()); - } + pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView); + m_bNotifying = false; + if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) + return true; + if (nAge == pWidget->GetAppearanceAge()) + return false; - bReset = true; - } - } - } + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) + pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); + + return true; } -void CFFL_InteractiveFormFiller::OnPopupPreOpen(void* pPrivateData, - bool& bExit, - uint32_t nFlag) { - CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData; +bool CFFL_InteractiveFormFiller::OnPopupPreOpen( + CPWL_Wnd::PrivateData* pAttached, + uint32_t nFlag) { + auto* pData = static_cast(pAttached); ASSERT(pData); ASSERT(pData->pWidget); - bool bTempReset = false; - bool bTempExit = false; - OnPreOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit, nFlag); - if (bTempReset || bTempExit) - bExit = true; + CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget); + return OnPreOpen(&pObserved, pData->pPageView, nFlag) || !pObserved; } -void CFFL_InteractiveFormFiller::OnPopupPostOpen(void* pPrivateData, - bool& bExit, - uint32_t nFlag) { - CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData; +bool CFFL_InteractiveFormFiller::OnPopupPostOpen( + CPWL_Wnd::PrivateData* pAttached, + uint32_t nFlag) { + auto* pData = static_cast(pAttached); ASSERT(pData); ASSERT(pData->pWidget); - bool bTempReset = false; - bool bTempExit = false; - OnPostOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit, nFlag); - if (bTempReset || bTempExit) - bExit = true; + CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget); + return OnPostOpen(&pObserved, pData->pPageView, nFlag) || !pObserved; } -void CFFL_InteractiveFormFiller::OnPreOpen(CPDFSDK_Widget* pWidget, +bool CFFL_InteractiveFormFiller::OnPreOpen(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - if (pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen)) { - m_bNotifying = true; - int nAge = pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + if (m_bNotifying) + return false; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen)) + return false; - pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView); - m_bNotifying = false; + m_bNotifying = true; + uint32_t nAge = pWidget->GetAppearanceAge(); + uint32_t nValueAge = pWidget->GetValueAge(); - if (!IsValidAnnot(pPageView, pWidget)) { - bExit = true; - return; - } + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); - if (nAge != pWidget->GetAppearanceAge()) { - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { - pFormFiller->ResetPDFWindow(pPageView, - nValueAge == pWidget->GetValueAge()); - } + pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView); + m_bNotifying = false; + if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) + return true; + if (nAge == pWidget->GetAppearanceAge()) + return false; - bReset = true; - } - } - } + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) + pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); + + return true; } -void CFFL_InteractiveFormFiller::OnPostOpen(CPDFSDK_Widget* pWidget, +bool CFFL_InteractiveFormFiller::OnPostOpen(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag) { - if (!m_bNotifying) { - if (pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen)) { - m_bNotifying = true; - int nAge = pWidget->GetAppearanceAge(); - int nValueAge = pWidget->GetValueAge(); + if (m_bNotifying) + return false; - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); + CPDFSDK_Widget* pWidget = static_cast(pAnnot->Get()); + if (!pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen)) + return false; - pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView); - m_bNotifying = false; + m_bNotifying = true; + uint32_t nAge = pWidget->GetAppearanceAge(); + uint32_t nValueAge = pWidget->GetValueAge(); - if (!IsValidAnnot(pPageView, pWidget)) { - bExit = true; - return; - } + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); - if (nAge != pWidget->GetAppearanceAge()) { - if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { - pFormFiller->ResetPDFWindow(pPageView, - nValueAge == pWidget->GetValueAge()); - } + pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView); + m_bNotifying = false; + if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) + return true; + if (nAge == pWidget->GetAppearanceAge()) + return false; - bReset = true; - } - } - } + if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) + pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); + + return true; } #endif // PDF_ENABLE_XFA @@ -874,95 +849,83 @@ bool CFFL_InteractiveFormFiller::IsValidAnnot(CPDFSDK_PageView* pPageView, return pPageView && pPageView->IsValidAnnot(pAnnot->GetPDFAnnot()); } -void CFFL_InteractiveFormFiller::OnBeforeKeyStroke( - void* pPrivateData, - CFX_WideString& strChange, - const CFX_WideString& strChangeEx, +std::pair CFFL_InteractiveFormFiller::OnBeforeKeyStroke( + CPWL_Wnd::PrivateData* pAttached, + WideString& strChange, + const WideString& strChangeEx, int nSelStart, int nSelEnd, bool bKeyDown, - bool& bRC, - bool& bExit, uint32_t nFlag) { - CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData; - ASSERT(pData->pWidget); + // Copy the private data since the window owning it may not survive. + CFFL_PrivateData privateData = *static_cast(pAttached); + ASSERT(privateData.pWidget); - CFFL_FormFiller* pFormFiller = GetFormFiller(pData->pWidget, false); + CFFL_FormFiller* pFormFiller = GetFormFiller(privateData.pWidget, false); #ifdef PDF_ENABLE_XFA - if (pFormFiller->IsFieldFull(pData->pPageView)) { - bool bFullExit = false; - bool bFullReset = false; - OnFull(pData->pWidget, pData->pPageView, bFullReset, bFullExit, nFlag); - - if (bFullReset || bFullExit) { - bExit = true; - return; - } + if (pFormFiller->IsFieldFull(privateData.pPageView)) { + CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget); + if (OnFull(&pObserved, privateData.pPageView, nFlag) || !pObserved) + return {true, true}; } #endif // PDF_ENABLE_XFA - if (!m_bNotifying) { - if (pData->pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) { - m_bNotifying = true; - int nAge = pData->pWidget->GetAppearanceAge(); - int nValueAge = pData->pWidget->GetValueAge(); - - CPDFSDK_FormFillEnvironment* pFormFillEnv = - pData->pPageView->GetFormFillEnv(); - - PDFSDK_FieldAction fa; - fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag); - fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag); - fa.sChange = strChange; - fa.sChangeEx = strChangeEx; - fa.bKeyDown = bKeyDown; - fa.bWillCommit = false; - fa.bRC = true; - fa.nSelStart = nSelStart; - fa.nSelEnd = nSelEnd; - - pFormFiller->GetActionData(pData->pPageView, CPDF_AAction::KeyStroke, fa); - pFormFiller->SaveState(pData->pPageView); - - CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget); - if (pData->pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, - pData->pPageView)) { - if (!pObserved || !IsValidAnnot(pData->pPageView, pData->pWidget)) { - bExit = true; - m_bNotifying = false; - return; - } - - if (nAge != pData->pWidget->GetAppearanceAge()) { - CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow( - pData->pPageView, nValueAge == pData->pWidget->GetValueAge()); - pData = (CFFL_PrivateData*)pWnd->GetAttachedData(); - bExit = true; - } - - if (fa.bRC) { - pFormFiller->SetActionData(pData->pPageView, CPDF_AAction::KeyStroke, - fa); - bRC = false; - } else { - pFormFiller->RestoreState(pData->pPageView); - bRC = false; - } - - if (pFormFillEnv->GetFocusAnnot() != pData->pWidget) { - pFormFiller->CommitData(pData->pPageView, nFlag); - bExit = true; - } - } else { - if (!IsValidAnnot(pData->pPageView, pData->pWidget)) { - bExit = true; - m_bNotifying = false; - return; - } - } + if (m_bNotifying || + !privateData.pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) { + return {true, false}; + } - m_bNotifying = false; - } + AutoRestorer restorer(&m_bNotifying); + m_bNotifying = true; + + uint32_t nAge = privateData.pWidget->GetAppearanceAge(); + uint32_t nValueAge = privateData.pWidget->GetValueAge(); + CPDFSDK_FormFillEnvironment* pFormFillEnv = + privateData.pPageView->GetFormFillEnv(); + + PDFSDK_FieldAction fa; + fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); + fa.sChange = strChange; + fa.sChangeEx = strChangeEx; + fa.bKeyDown = bKeyDown; + fa.bWillCommit = false; + fa.bRC = true; + fa.nSelStart = nSelStart; + fa.nSelEnd = nSelEnd; + pFormFiller->GetActionData(privateData.pPageView, CPDF_AAction::KeyStroke, + fa); + pFormFiller->SaveState(privateData.pPageView); + + CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget); + bool action_status = privateData.pWidget->OnAAction( + CPDF_AAction::KeyStroke, fa, privateData.pPageView); + + if (!pObserved || !IsValidAnnot(privateData.pPageView, privateData.pWidget)) + return {true, true}; + + if (!action_status) + return {true, false}; + + bool bExit = false; + if (nAge != privateData.pWidget->GetAppearanceAge()) { + CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow( + privateData.pPageView, nValueAge == privateData.pWidget->GetValueAge()); + if (!pWnd) + return {true, true}; + privateData = *static_cast(pWnd->GetAttachedData()); + bExit = true; } + if (fa.bRC) { + pFormFiller->SetActionData(privateData.pPageView, CPDF_AAction::KeyStroke, + fa); + } else { + pFormFiller->RestoreState(privateData.pPageView); + } + if (pFormFillEnv->GetFocusAnnot() == privateData.pWidget) + return {false, bExit}; + + pFormFiller->CommitData(privateData.pPageView, nFlag); + return {false, true}; } diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h index 90fd98c0e8c8a6aad9006a6975664b3cd11f3f3f..01927529f72006e5ad12453b6960c657a097206c 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h @@ -9,10 +9,12 @@ #include #include +#include +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/cpdfsdk_annot.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/pdfwindow/PWL_Edit.h" +#include "fpdfsdk/pwl/cpwl_edit.h" class CFFL_FormFiller; class CPDFSDK_FormFillEnvironment; @@ -79,57 +81,42 @@ class CFFL_InteractiveFormFiller : public IPWL_Filler_Notify { bool OnKillFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, uint32_t nFlag); CFFL_FormFiller* GetFormFiller(CPDFSDK_Annot* pAnnot, bool bRegister); - void RemoveFormFiller(CPDFSDK_Annot* pAnnot); + + WideString GetSelectedText(CPDFSDK_Annot* pAnnot); + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text); static bool IsVisible(CPDFSDK_Widget* pWidget); static bool IsReadOnly(CPDFSDK_Widget* pWidget); static bool IsFillingAllowed(CPDFSDK_Widget* pWidget); static bool IsValidAnnot(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot); - void OnKeyStrokeCommit(CPDFSDK_Annot::ObservedPtr* pWidget, + bool OnKeyStrokeCommit(CPDFSDK_Annot::ObservedPtr* pWidget, CPDFSDK_PageView* pPageView, - bool& bRC, - bool& bExit, uint32_t nFlag); - void OnValidate(CPDFSDK_Annot::ObservedPtr* pWidget, + bool OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bRC, - bool& bExit, uint32_t nFlag); - - void OnCalculate(CPDFSDK_Widget* pWidget, + void OnCalculate(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bExit, uint32_t nFlag); - void OnFormat(CPDFSDK_Widget* pWidget, + void OnFormat(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bExit, uint32_t nFlag); - void OnButtonUp(CPDFSDK_Annot::ObservedPtr* pWidget, + bool OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag); #ifdef PDF_ENABLE_XFA - void OnClick(CPDFSDK_Widget* pWidget, + bool OnClick(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag); - void OnFull(CPDFSDK_Widget* pWidget, + bool OnFull(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag); - void OnPreOpen(CPDFSDK_Widget* pWidget, + bool OnPreOpen(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag); - void OnPostOpen(CPDFSDK_Widget* pWidget, + bool OnPostOpen(CPDFSDK_Annot::ObservedPtr* pAnnot, CPDFSDK_PageView* pPageView, - bool& bReset, - bool& bExit, uint32_t nFlag); #endif // PDF_ENABLE_XFA @@ -138,40 +125,39 @@ class CFFL_InteractiveFormFiller : public IPWL_Filler_Notify { std::map>; // IPWL_Filler_Notify: - void QueryWherePopup(void* pPrivateData, - FX_FLOAT fPopupMin, - FX_FLOAT fPopupMax, - int32_t& nRet, - FX_FLOAT& fPopupRet) override; - void OnBeforeKeyStroke(void* pPrivateData, - CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - int nSelStart, - int nSelEnd, - bool bKeyDown, - bool& bRC, - bool& bExit, - uint32_t nFlag) override; + void QueryWherePopup(CPWL_Wnd::PrivateData* pAttached, + float fPopupMin, + float fPopupMax, + bool* bBottom, + float* fPopupRet) override; + // Returns {bRC, bExit}. + std::pair OnBeforeKeyStroke(CPWL_Wnd::PrivateData* pAttached, + WideString& strChange, + const WideString& strChangeEx, + int nSelStart, + int nSelEnd, + bool bKeyDown, + uint32_t nFlag) override; #ifdef PDF_ENABLE_XFA - void OnPopupPreOpen(void* pPrivateData, bool& bExit, uint32_t nFlag) override; - void OnPopupPostOpen(void* pPrivateData, - bool& bExit, + bool OnPopupPreOpen(CPWL_Wnd::PrivateData* pAttached, + uint32_t nFlag) override; + bool OnPopupPostOpen(CPWL_Wnd::PrivateData* pAttached, uint32_t nFlag) override; void SetFocusAnnotTab(CPDFSDK_Annot* pWidget, bool bSameField, bool bNext); #endif // PDF_ENABLE_XFA void UnRegisterFormFiller(CPDFSDK_Annot* pAnnot); - CPDFSDK_FormFillEnvironment* const m_pFormFillEnv; + UnownedPtr const m_pFormFillEnv; CFFL_Widget2Filler m_Maps; bool m_bNotifying; }; -class CFFL_PrivateData { +class CFFL_PrivateData : public CPWL_Wnd::PrivateData { public: CPDFSDK_Widget* pWidget; CPDFSDK_PageView* pPageView; - int nWidgetAge; - int nValueAge; + uint32_t nWidgetAppearanceAge; + uint32_t nWidgetValueAge; }; #endif // FPDFSDK_FORMFILLER_CFFL_INTERACTIVEFORMFILLER_H_ diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp index 556e0e17d71e8d3ba2ed3d6c37b3e1e968510f2d..e628e59cb8b3aeccd3107f4233ea845b2c790c72 100644 --- a/fpdfsdk/formfiller/cffl_listbox.cpp +++ b/fpdfsdk/formfiller/cffl_listbox.cpp @@ -9,46 +9,36 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cba_fontmap.h" -#include "fpdfsdk/formfiller/cffl_formfiller.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/fsdk_common.h" -#include "fpdfsdk/pdfwindow/PWL_ListBox.h" +#include "fpdfsdk/pwl/cpwl_list_box.h" #include "third_party/base/ptr_util.h" #define FFL_DEFAULTLISTBOXFONTSIZE 12.0f CFFL_ListBox::CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp, - CPDFSDK_Annot* pWidget) - : CFFL_FormFiller(pApp, pWidget) {} + CPDFSDK_Widget* pWidget) + : CFFL_TextObject(pApp, pWidget) {} CFFL_ListBox::~CFFL_ListBox() {} -PWL_CREATEPARAM CFFL_ListBox::GetCreateParam() { - PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam(); - +CPWL_Wnd::CreateParams CFFL_ListBox::GetCreateParam() { + CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam(); uint32_t dwFieldFlag = m_pWidget->GetFieldFlags(); - - if (dwFieldFlag & FIELDFLAG_MULTISELECT) { + if (dwFieldFlag & FIELDFLAG_MULTISELECT) cp.dwFlags |= PLBS_MULTIPLESEL; - } cp.dwFlags |= PWS_VSCROLL; if (cp.dwFlags & PWS_AUTOFONTSIZE) cp.fFontSize = FFL_DEFAULTLISTBOXFONTSIZE; - if (!m_pFontMap) { - m_pFontMap = pdfium::MakeUnique( - m_pWidget, m_pFormFillEnv->GetSysHandler()); - } - cp.pFontMap = m_pFontMap.get(); - + cp.pFontMap = MaybeCreateFontMap(); return cp; } -CPWL_Wnd* CFFL_ListBox::NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) { - CPWL_ListBox* pWnd = new CPWL_ListBox(); +CPWL_Wnd* CFFL_ListBox::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) { + auto* pWnd = new CPWL_ListBox(); pWnd->AttachFFLData(this); pWnd->Create(cp); pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller()); @@ -87,7 +77,7 @@ CPWL_Wnd* CFFL_ListBox::NewPDFWindow(const PWL_CREATEPARAM& cp, bool CFFL_ListBox::OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) { - return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); + return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags); } bool CFFL_ListBox::IsDataChanged(CPDFSDK_PageView* pPageView) { @@ -127,9 +117,18 @@ void CFFL_ListBox::SaveData(CPDFSDK_PageView* pPageView) { } else { m_pWidget->SetOptionSelection(pListBox->GetCurSel(), true, false); } + CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get()); + CFFL_ListBox::ObservedPtr observed_this(this); + m_pWidget->SetTopVisibleIndex(nNewTopIndex); + if (!observed_widget) + return; m_pWidget->ResetFieldAppearance(true); + if (!observed_widget) + return; m_pWidget->UpdateField(); + if (!observed_widget || !observed_this) + return; SetChangeMark(); } @@ -187,24 +186,3 @@ void CFFL_ListBox::RestoreState(CPDFSDK_PageView* pPageView) { for (const auto& item : m_State) pListBox->Select(item); } - -CPWL_Wnd* CFFL_ListBox::ResetPDFWindow(CPDFSDK_PageView* pPageView, - bool bRestoreValue) { - if (bRestoreValue) - SaveState(pPageView); - - DestroyPDFWindow(pPageView); - - CPWL_Wnd* pRet = nullptr; - - if (bRestoreValue) { - RestoreState(pPageView); - pRet = GetPDFWindow(pPageView, false); - } else { - pRet = GetPDFWindow(pPageView, true); - } - - m_pWidget->UpdateField(); - - return pRet; -} diff --git a/fpdfsdk/formfiller/cffl_listbox.h b/fpdfsdk/formfiller/cffl_listbox.h index 609f2c48096cb3970129a916dc71841bb00c8b30..014865d567a6b0007dbb179a29760f7a61ecd949 100644 --- a/fpdfsdk/formfiller/cffl_listbox.h +++ b/fpdfsdk/formfiller/cffl_listbox.h @@ -7,23 +7,21 @@ #ifndef FPDFSDK_FORMFILLER_CFFL_LISTBOX_H_ #define FPDFSDK_FORMFILLER_CFFL_LISTBOX_H_ -#include #include #include -#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_textobject.h" class CBA_FontMap; -class CFFL_ListBox : public CFFL_FormFiller { +class CFFL_ListBox : public CFFL_TextObject { public: - CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pWidget); + CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); ~CFFL_ListBox() override; - // CFFL_FormFiller - PWL_CREATEPARAM GetCreateParam() override; - CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) override; + // CFFL_TextObject: + CPWL_Wnd::CreateParams GetCreateParam() override; + CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override; bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override; bool IsDataChanged(CPDFSDK_PageView* pPageView) override; void SaveData(CPDFSDK_PageView* pPageView) override; @@ -32,11 +30,8 @@ class CFFL_ListBox : public CFFL_FormFiller { PDFSDK_FieldAction& fa) override; void SaveState(CPDFSDK_PageView* pPageView) override; void RestoreState(CPDFSDK_PageView* pPageView) override; - CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView, - bool bRestoreValue) override; private: - std::unique_ptr m_pFontMap; std::set m_OriginSelections; std::vector m_State; }; diff --git a/fpdfsdk/formfiller/cffl_pushbutton.cpp b/fpdfsdk/formfiller/cffl_pushbutton.cpp index 9b4121af9d10580fd94c89b308a23ea55e6e5370..7310da67611286c04f9e931a49a3a40af91297f0 100644 --- a/fpdfsdk/formfiller/cffl_pushbutton.cpp +++ b/fpdfsdk/formfiller/cffl_pushbutton.cpp @@ -7,31 +7,16 @@ #include "fpdfsdk/formfiller/cffl_pushbutton.h" #include "fpdfsdk/formfiller/cffl_formfiller.h" -#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h" +#include "fpdfsdk/pwl/cpwl_special_button.h" CFFL_PushButton::CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp, - CPDFSDK_Annot* pAnnot) - : CFFL_Button(pApp, pAnnot) {} + CPDFSDK_Widget* pWidget) + : CFFL_Button(pApp, pWidget) {} CFFL_PushButton::~CFFL_PushButton() {} -CPWL_Wnd* CFFL_PushButton::NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) { - CPWL_PushButton* pWnd = new CPWL_PushButton(); +CPWL_Wnd* CFFL_PushButton::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) { + auto* pWnd = new CPWL_PushButton(); pWnd->Create(cp); - return pWnd; } - -bool CFFL_PushButton::OnChar(CPDFSDK_Annot* pAnnot, - uint32_t nChar, - uint32_t nFlags) { - return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); -} - -void CFFL_PushButton::OnDraw(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CFFL_Button::OnDraw(pPageView, pAnnot, pDevice, pUser2Device); -} diff --git a/fpdfsdk/formfiller/cffl_pushbutton.h b/fpdfsdk/formfiller/cffl_pushbutton.h index 1d50595c87571eedd1ec863a08f33c2e89755310..7ee076764e3956ccfb3c748e84cfe53ad48cc4d0 100644 --- a/fpdfsdk/formfiller/cffl_pushbutton.h +++ b/fpdfsdk/formfiller/cffl_pushbutton.h @@ -7,21 +7,15 @@ #ifndef FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_ #define FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_ -#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_button.h" class CFFL_PushButton : public CFFL_Button { public: - CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pAnnot); + CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); ~CFFL_PushButton() override; - // CFFL_Button - CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) override; - bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override; - void OnDraw(CPDFSDK_PageView* pPageView, - CPDFSDK_Annot* pAnnot, - CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; + // CFFL_Button: + CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override; }; #endif // FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_ diff --git a/fpdfsdk/formfiller/cffl_radiobutton.cpp b/fpdfsdk/formfiller/cffl_radiobutton.cpp index e78160e5dcefda288ac778a44669741459fee10f..73ac44de46b56fde1c3238d2df4259698edc8b4b 100644 --- a/fpdfsdk/formfiller/cffl_radiobutton.cpp +++ b/fpdfsdk/formfiller/cffl_radiobutton.cpp @@ -9,22 +9,19 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cffl_formfiller.h" -#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h" +#include "fpdfsdk/pwl/cpwl_special_button.h" #include "public/fpdf_fwlevent.h" CFFL_RadioButton::CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp, - CPDFSDK_Annot* pWidget) + CPDFSDK_Widget* pWidget) : CFFL_Button(pApp, pWidget) {} CFFL_RadioButton::~CFFL_RadioButton() {} -CPWL_Wnd* CFFL_RadioButton::NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) { - CPWL_RadioButton* pWnd = new CPWL_RadioButton(); +CPWL_Wnd* CFFL_RadioButton::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) { + auto* pWnd = new CPWL_RadioButton(); pWnd->Create(cp); - pWnd->SetCheck(m_pWidget->IsChecked()); - return pWnd; } @@ -49,20 +46,18 @@ bool CFFL_RadioButton::OnChar(CPDFSDK_Annot* pAnnot, CPDFSDK_PageView* pPageView = pAnnot->GetPageView(); ASSERT(pPageView); - bool bReset = false; - bool bExit = false; - CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget); - m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp( - &pObserved, pPageView, bReset, bExit, nFlags); - if (!pObserved || bReset || bExit) + CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get()); + if (m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp( + &pObserved, pPageView, nFlags) || + !pObserved) { return true; + } CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); - if (CPWL_RadioButton* pWnd = - (CPWL_RadioButton*)GetPDFWindow(pPageView, true)) + CPWL_RadioButton* pWnd = GetRadioButton(pPageView, true); + if (pWnd) pWnd->SetCheck(true); - CommitData(pPageView, nFlags); - return true; + return CommitData(pPageView, nFlags); } default: return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); @@ -75,45 +70,51 @@ bool CFFL_RadioButton::OnLButtonUp(CPDFSDK_PageView* pPageView, const CFX_PointF& point) { CFFL_Button::OnLButtonUp(pPageView, pAnnot, nFlags, point); - if (IsValid()) { - if (CPWL_RadioButton* pWnd = - (CPWL_RadioButton*)GetPDFWindow(pPageView, true)) - pWnd->SetCheck(true); + if (!IsValid()) + return true; - if (!CommitData(pPageView, nFlags)) - return false; - } + CPWL_RadioButton* pWnd = GetRadioButton(pPageView, true); + if (pWnd) + pWnd->SetCheck(true); - return true; + return CommitData(pPageView, nFlags); } bool CFFL_RadioButton::IsDataChanged(CPDFSDK_PageView* pPageView) { - if (CPWL_RadioButton* pWnd = - (CPWL_RadioButton*)GetPDFWindow(pPageView, false)) { - return pWnd->IsChecked() != m_pWidget->IsChecked(); - } - - return false; + CPWL_RadioButton* pWnd = GetRadioButton(pPageView, false); + return pWnd && pWnd->IsChecked() != m_pWidget->IsChecked(); } void CFFL_RadioButton::SaveData(CPDFSDK_PageView* pPageView) { - if (CPWL_RadioButton* pWnd = - (CPWL_RadioButton*)GetPDFWindow(pPageView, false)) { - bool bNewChecked = pWnd->IsChecked(); - - if (bNewChecked) { - CPDF_FormField* pField = m_pWidget->GetFormField(); - for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) { - if (CPDF_FormControl* pCtrl = pField->GetControl(i)) { - if (pCtrl->IsChecked()) { - break; - } + CPWL_RadioButton* pWnd = GetRadioButton(pPageView, false); + if (!pWnd) + return; + + bool bNewChecked = pWnd->IsChecked(); + + if (bNewChecked) { + CPDF_FormField* pField = m_pWidget->GetFormField(); + for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) { + if (CPDF_FormControl* pCtrl = pField->GetControl(i)) { + if (pCtrl->IsChecked()) { + break; } } } - - m_pWidget->SetCheck(bNewChecked, false); - m_pWidget->UpdateField(); - SetChangeMark(); } + CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get()); + CFFL_RadioButton::ObservedPtr observed_this(this); + + m_pWidget->SetCheck(bNewChecked, false); + if (!observed_widget) + return; + m_pWidget->UpdateField(); + if (!observed_widget || !observed_this) + return; + SetChangeMark(); +} + +CPWL_RadioButton* CFFL_RadioButton::GetRadioButton(CPDFSDK_PageView* pPageView, + bool bNew) { + return static_cast(GetPDFWindow(pPageView, bNew)); } diff --git a/fpdfsdk/formfiller/cffl_radiobutton.h b/fpdfsdk/formfiller/cffl_radiobutton.h index 10ac37dcb8751e06e16b134a8f19ed4750ae0ae7..2838254708e856446f70d4bb3ae89efd5cf64a00 100644 --- a/fpdfsdk/formfiller/cffl_radiobutton.h +++ b/fpdfsdk/formfiller/cffl_radiobutton.h @@ -7,16 +7,17 @@ #ifndef FPDFSDK_FORMFILLER_CFFL_RADIOBUTTON_H_ #define FPDFSDK_FORMFILLER_CFFL_RADIOBUTTON_H_ -#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_button.h" + +class CPWL_RadioButton; class CFFL_RadioButton : public CFFL_Button { public: - CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pAnnot); + CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); ~CFFL_RadioButton() override; - // CFFL_Button - CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) override; + // CFFL_Button: + CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override; bool OnKeyDown(CPDFSDK_Annot* pAnnot, uint32_t nKeyCode, uint32_t nFlags) override; @@ -27,6 +28,9 @@ class CFFL_RadioButton : public CFFL_Button { const CFX_PointF& point) override; bool IsDataChanged(CPDFSDK_PageView* pPageView) override; void SaveData(CPDFSDK_PageView* pPageView) override; + + private: + CPWL_RadioButton* GetRadioButton(CPDFSDK_PageView* pPageView, bool bNew); }; #endif // FPDFSDK_FORMFILLER_CFFL_RADIOBUTTON_H_ diff --git a/fpdfsdk/formfiller/cffl_textfield.cpp b/fpdfsdk/formfiller/cffl_textfield.cpp index 91db0959dbec7104f84c75a5dfbf24fddb500468..ad8d27c916f4dde3837539e59f46d5a383044d05 100644 --- a/fpdfsdk/formfiller/cffl_textfield.cpp +++ b/fpdfsdk/formfiller/cffl_textfield.cpp @@ -13,8 +13,8 @@ #include "third_party/base/ptr_util.h" CFFL_TextField::CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, - CPDFSDK_Annot* pAnnot) - : CFFL_FormFiller(pApp, pAnnot) {} + CPDFSDK_Widget* pWidget) + : CFFL_TextObject(pApp, pWidget) {} CFFL_TextField::~CFFL_TextField() { for (const auto& it : m_Maps) @@ -26,36 +26,27 @@ CFFL_TextField::~CFFL_TextField() { DestroyWindows(); } -PWL_CREATEPARAM CFFL_TextField::GetCreateParam() { - PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam(); - +CPWL_Wnd::CreateParams CFFL_TextField::GetCreateParam() { + CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam(); int nFlags = m_pWidget->GetFieldFlags(); - - if (nFlags & FIELDFLAG_PASSWORD) { + if (nFlags & FIELDFLAG_PASSWORD) cp.dwFlags |= PES_PASSWORD; - } if (nFlags & FIELDFLAG_MULTILINE) { cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP; - - if (!(nFlags & FIELDFLAG_DONOTSCROLL)) { + if (!(nFlags & FIELDFLAG_DONOTSCROLL)) cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL; - } } else { cp.dwFlags |= PES_CENTER; - - if (!(nFlags & FIELDFLAG_DONOTSCROLL)) { + if (!(nFlags & FIELDFLAG_DONOTSCROLL)) cp.dwFlags |= PES_AUTOSCROLL; - } } - if (nFlags & FIELDFLAG_COMB) { + if (nFlags & FIELDFLAG_COMB) cp.dwFlags |= PES_CHARARRAY; - } - if (nFlags & FIELDFLAG_RICHTEXT) { + if (nFlags & FIELDFLAG_RICHTEXT) cp.dwFlags |= PES_RICH; - } cp.dwFlags |= PES_UNDO; @@ -71,26 +62,19 @@ PWL_CREATEPARAM CFFL_TextField::GetCreateParam() { cp.dwFlags |= PES_RIGHT; break; } - - if (!m_pFontMap) { - m_pFontMap = pdfium::MakeUnique( - m_pWidget, m_pFormFillEnv->GetSysHandler()); - } - cp.pFontMap = m_pFontMap.get(); + cp.pFontMap = MaybeCreateFontMap(); cp.pFocusHandler = this; - return cp; } -CPWL_Wnd* CFFL_TextField::NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) { - CPWL_Edit* pWnd = new CPWL_Edit(); +CPWL_Wnd* CFFL_TextField::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) { + auto* pWnd = new CPWL_Edit(); pWnd->AttachFFLData(this); pWnd->Create(cp); pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller()); int32_t nMaxLen = m_pWidget->GetMaxLen(); - CFX_WideString swValue = m_pWidget->GetValue(); + WideString swValue = m_pWidget->GetValue(); if (nMaxLen > 0) { if (pWnd->HasFlag(PES_CHARARRAY)) { @@ -109,26 +93,28 @@ bool CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) { switch (nChar) { - case FWL_VKEY_Return: - if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)) { - CPDFSDK_PageView* pPageView = GetCurPageView(true); - ASSERT(pPageView); - m_bValid = !m_bValid; - m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(), - pAnnot->GetRect().ToFxRect()); - - if (m_bValid) { - if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true)) - pWnd->SetFocus(); - } else { - if (CommitData(pPageView, nFlags)) { - DestroyPDFWindow(pPageView); - return true; - } - return false; - } + case FWL_VKEY_Return: { + if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE) + break; + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + m_bValid = !m_bValid; + m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(), + pAnnot->GetRect().GetOuterRect()); + + if (m_bValid) { + if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true)) + pWnd->SetFocus(); + break; } - break; + + if (!CommitData(pPageView, nFlags)) + return false; + + DestroyPDFWindow(pPageView); + return true; + } case FWL_VKEY_Escape: { CPDFSDK_PageView* pPageView = GetCurPageView(true); ASSERT(pPageView); @@ -137,26 +123,35 @@ bool CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot, } } - return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags); + return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags); } bool CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) { - if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, false)) - return pEdit->GetText() != m_pWidget->GetValue(); - - return false; + CPWL_Edit* pEdit = GetEdit(pPageView, false); + return pEdit && pEdit->GetText() != m_pWidget->GetValue(); } void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView) { - if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) { - CFX_WideString sOldValue = m_pWidget->GetValue(); - CFX_WideString sNewValue = pWnd->GetText(); - - m_pWidget->SetValue(sNewValue, false); - m_pWidget->ResetFieldAppearance(true); - m_pWidget->UpdateField(); - SetChangeMark(); - } + CPWL_Edit* pWnd = GetEdit(pPageView, false); + if (!pWnd) + return; + + WideString sOldValue = m_pWidget->GetValue(); + WideString sNewValue = pWnd->GetText(); + + CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get()); + CFFL_TextField::ObservedPtr observed_this(this); + + m_pWidget->SetValue(sNewValue, false); + if (!observed_widget) + return; + m_pWidget->ResetFieldAppearance(true); + if (!observed_widget) + return; + m_pWidget->UpdateField(); + if (!observed_widget || !observed_this) + return; + SetChangeMark(); } void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView, @@ -164,7 +159,7 @@ void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView, PDFSDK_FieldAction& fa) { switch (type) { case CPDF_AAction::KeyStroke: - if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) { + if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) { fa.bFieldFull = pWnd->IsTextFull(); fa.sValue = pWnd->GetText(); @@ -176,7 +171,7 @@ void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView, } break; case CPDF_AAction::Validate: - if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) { + if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) { fa.sValue = pWnd->GetText(); } break; @@ -194,9 +189,9 @@ void CFFL_TextField::SetActionData(CPDFSDK_PageView* pPageView, const PDFSDK_FieldAction& fa) { switch (type) { case CPDF_AAction::KeyStroke: - if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, false)) { + if (CPWL_Edit* pEdit = GetEdit(pPageView, false)) { pEdit->SetFocus(); - pEdit->SetSel(fa.nSelStart, fa.nSelEnd); + pEdit->SetSelection(fa.nSelStart, fa.nSelEnd); pEdit->ReplaceSel(fa.sChange); } break; @@ -223,64 +218,43 @@ bool CFFL_TextField::IsActionDataChanged(CPDF_AAction::AActionType type, void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView) { ASSERT(pPageView); - if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) { - pWnd->GetSel(m_State.nStart, m_State.nEnd); - m_State.sValue = pWnd->GetText(); - } + CPWL_Edit* pWnd = GetEdit(pPageView, false); + if (!pWnd) + return; + + pWnd->GetSelection(m_State.nStart, m_State.nEnd); + m_State.sValue = pWnd->GetText(); } void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView) { ASSERT(pPageView); - if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, true)) { - pWnd->SetText(m_State.sValue); - pWnd->SetSel(m_State.nStart, m_State.nEnd); - } -} - -CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView, - bool bRestoreValue) { - if (bRestoreValue) - SaveState(pPageView); - - DestroyPDFWindow(pPageView); - - CPWL_Wnd* pRet = nullptr; - - if (bRestoreValue) { - RestoreState(pPageView); - pRet = GetPDFWindow(pPageView, false); - } else { - pRet = GetPDFWindow(pPageView, true); - } - - m_pWidget->UpdateField(); + CPWL_Edit* pWnd = GetEdit(pPageView, true); + if (!pWnd) + return; - return pRet; + pWnd->SetText(m_State.sValue); + pWnd->SetSelection(m_State.nStart, m_State.nEnd); } #ifdef PDF_ENABLE_XFA bool CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) { - if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) { - return pWnd->IsTextFull(); - } - - return false; + CPWL_Edit* pWnd = GetEdit(pPageView, false); + return pWnd && pWnd->IsTextFull(); } #endif // PDF_ENABLE_XFA -void CFFL_TextField::OnSetFocus(CPWL_Wnd* pWnd) { - ASSERT(m_pFormFillEnv); - if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) { - CPWL_Edit* pEdit = (CPWL_Edit*)pWnd; - pEdit->SetCharSet(FXFONT_GB2312_CHARSET); - pEdit->SetCodePage(936); - - pEdit->SetReadyToInput(); - CFX_WideString wsText = pEdit->GetText(); - int nCharacters = wsText.GetLength(); - CFX_ByteString bsUTFText = wsText.UTF16LE_Encode(); - unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str(); - m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true); - } +void CFFL_TextField::OnSetFocus(CPWL_Edit* pEdit) { + pEdit->SetCharSet(FX_CHARSET_ChineseSimplified); + pEdit->SetReadyToInput(); + + WideString wsText = pEdit->GetText(); + int nCharacters = wsText.GetLength(); + ByteString bsUTFText = wsText.UTF16LE_Encode(); + auto* pBuffer = reinterpret_cast(bsUTFText.c_str()); + m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true); +} + +CPWL_Edit* CFFL_TextField::GetEdit(CPDFSDK_PageView* pPageView, bool bNew) { + return static_cast(GetPDFWindow(pPageView, bNew)); } diff --git a/fpdfsdk/formfiller/cffl_textfield.h b/fpdfsdk/formfiller/cffl_textfield.h index 29579f72a5f321153f27fe0f6d77f57dec14ba5b..49ffc0fc3353b6cd92fe011dee1d3e97388b760d 100644 --- a/fpdfsdk/formfiller/cffl_textfield.h +++ b/fpdfsdk/formfiller/cffl_textfield.h @@ -7,33 +7,32 @@ #ifndef FPDFSDK_FORMFILLER_CFFL_TEXTFIELD_H_ #define FPDFSDK_FORMFILLER_CFFL_TEXTFIELD_H_ -#include - -#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_textobject.h" #define BF_ALIGN_LEFT 0 #define BF_ALIGN_MIDDLE 1 #define BF_ALIGN_RIGHT 2 class CBA_FontMap; +class CPWL_Edit; struct FFL_TextFieldState { FFL_TextFieldState() : nStart(0), nEnd(0) {} int nStart; int nEnd; - CFX_WideString sValue; + WideString sValue; }; -class CFFL_TextField : public CFFL_FormFiller, public IPWL_FocusHandler { +class CFFL_TextField : public CFFL_TextObject, + public CPWL_Wnd::FocusHandlerIface { public: - CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pAnnot); + CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); ~CFFL_TextField() override; - // CFFL_FormFiller: - PWL_CREATEPARAM GetCreateParam() override; - CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp, - CPDFSDK_PageView* pPageView) override; + // CFFL_TextObject: + CPWL_Wnd::CreateParams GetCreateParam() override; + CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override; bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override; bool IsDataChanged(CPDFSDK_PageView* pPageView) override; void SaveData(CPDFSDK_PageView* pPageView) override; @@ -48,19 +47,16 @@ class CFFL_TextField : public CFFL_FormFiller, public IPWL_FocusHandler { const PDFSDK_FieldAction& faNew) override; void SaveState(CPDFSDK_PageView* pPageView) override; void RestoreState(CPDFSDK_PageView* pPageView) override; - CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView, - bool bRestoreValue) override; - - // IPWL_FocusHandler: - void OnSetFocus(CPWL_Wnd* pWnd) override; - #ifdef PDF_ENABLE_XFA - // CFFL_FormFiller: bool IsFieldFull(CPDFSDK_PageView* pPageView) override; -#endif // PDF_ENABLE_XFA +#endif + + // CPWL_Wnd::FocusHandlerIface: + void OnSetFocus(CPWL_Edit* pEdit) override; private: - std::unique_ptr m_pFontMap; + CPWL_Edit* GetEdit(CPDFSDK_PageView* pPageView, bool bNew); + FFL_TextFieldState m_State; }; diff --git a/fpdfsdk/formfiller/cffl_textobject.cpp b/fpdfsdk/formfiller/cffl_textobject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df2f5e5a929a34e78a15c249aac960b28d3732f5 --- /dev/null +++ b/fpdfsdk/formfiller/cffl_textobject.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/formfiller/cffl_textobject.h" + +CPWL_Wnd* CFFL_TextObject::ResetPDFWindow(CPDFSDK_PageView* pPageView, + bool bRestoreValue) { + if (bRestoreValue) + SaveState(pPageView); + + DestroyPDFWindow(pPageView); + if (bRestoreValue) + RestoreState(pPageView); + + CPWL_Wnd::ObservedPtr pRet(GetPDFWindow(pPageView, !bRestoreValue)); + m_pWidget->UpdateField(); // May invoke JS, invalidating |pRet|. + return pRet.Get(); +} + +CFFL_TextObject::CFFL_TextObject(CPDFSDK_FormFillEnvironment* pApp, + CPDFSDK_Widget* pWidget) + : CFFL_FormFiller(pApp, pWidget) {} + +CFFL_TextObject::~CFFL_TextObject() { + // Destroy view classes before this object's members are destroyed since + // the view classes have pointers to m_pFontMap that would be left dangling. + DestroyWindows(); +} + +CBA_FontMap* CFFL_TextObject::MaybeCreateFontMap() { + if (!m_pFontMap) { + m_pFontMap = + pdfium::MakeUnique(m_pWidget.Get(), GetSystemHandler()); + } + return m_pFontMap.get(); +} diff --git a/fpdfsdk/formfiller/cffl_textobject.h b/fpdfsdk/formfiller/cffl_textobject.h new file mode 100644 index 0000000000000000000000000000000000000000..fcb3c1b971f0c2350498cd67799291dddd0b8445 --- /dev/null +++ b/fpdfsdk/formfiller/cffl_textobject.h @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_ +#define FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_ + +#include + +#include "fpdfsdk/formfiller/cffl_formfiller.h" + +// Class to implement common functionality for CFFL_FormFiller sub-classes with +// text fields. +class CFFL_TextObject : public CFFL_FormFiller { + public: + // CFFL_FormFiller: + CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView, + bool bRestoreValue) override; + + protected: + CFFL_TextObject(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget); + ~CFFL_TextObject() override; + + CBA_FontMap* MaybeCreateFontMap(); + + private: + std::unique_ptr m_pFontMap; +}; + +#endif // FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_ diff --git a/fpdfsdk/fpdf_dataavail.cpp b/fpdfsdk/fpdf_dataavail.cpp index b1bc1e3bc07a63d45e59e8b61e25522774e11b92..b1a134d9148519f38881d4540f07f07632e8d9c4 100644 --- a/fpdfsdk/fpdf_dataavail.cpp +++ b/fpdfsdk/fpdf_dataavail.cpp @@ -11,7 +11,8 @@ #include "core/fpdfapi/parser/cpdf_data_avail.h" #include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/retain_ptr.h" #include "fpdfsdk/fsdk_define.h" #include "public/fpdf_formfill.h" #include "third_party/base/ptr_util.h" @@ -42,15 +43,15 @@ static_assert(CPDF_DataAvail::FormNotExist == PDF_FORM_NOTEXIST, namespace { -class CFPDF_FileAvailWrap : public CPDF_DataAvail::FileAvail { +class FPDF_FileAvailContext : public CPDF_DataAvail::FileAvail { public: - CFPDF_FileAvailWrap() : m_pfileAvail(nullptr) {} - ~CFPDF_FileAvailWrap() override {} + FPDF_FileAvailContext() : m_pfileAvail(nullptr) {} + ~FPDF_FileAvailContext() override {} void Set(FX_FILEAVAIL* pfileAvail) { m_pfileAvail = pfileAvail; } // CPDF_DataAvail::FileAvail: - bool IsDataAvail(FX_FILESIZE offset, uint32_t size) override { + bool IsDataAvail(FX_FILESIZE offset, size_t size) override { return !!m_pfileAvail->IsDataAvail(m_pfileAvail, offset, size); } @@ -58,12 +59,12 @@ class CFPDF_FileAvailWrap : public CPDF_DataAvail::FileAvail { FX_FILEAVAIL* m_pfileAvail; }; -class CFPDF_FileAccessWrap : public IFX_SeekableReadStream { +class FPDF_FileAccessContext : public IFX_SeekableReadStream { public: - static CFX_RetainPtr Create() { - return CFX_RetainPtr(new CFPDF_FileAccessWrap()); - } - ~CFPDF_FileAccessWrap() override {} + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + ~FPDF_FileAccessContext() override {} void Set(FPDF_FILEACCESS* pFile) { m_pFileAccess = pFile; } @@ -76,119 +77,115 @@ class CFPDF_FileAccessWrap : public IFX_SeekableReadStream { } private: - CFPDF_FileAccessWrap() : m_pFileAccess(nullptr) {} + FPDF_FileAccessContext() : m_pFileAccess(nullptr) {} FPDF_FILEACCESS* m_pFileAccess; }; -class CFPDF_DownloadHintsWrap : public CPDF_DataAvail::DownloadHints { +class FPDF_DownloadHintsContext : public CPDF_DataAvail::DownloadHints { public: - explicit CFPDF_DownloadHintsWrap(FX_DOWNLOADHINTS* pDownloadHints) { + explicit FPDF_DownloadHintsContext(FX_DOWNLOADHINTS* pDownloadHints) { m_pDownloadHints = pDownloadHints; } - ~CFPDF_DownloadHintsWrap() override {} + ~FPDF_DownloadHintsContext() override {} public: // IFX_DownloadHints - void AddSegment(FX_FILESIZE offset, uint32_t size) override { - m_pDownloadHints->AddSegment(m_pDownloadHints, offset, size); + void AddSegment(FX_FILESIZE offset, size_t size) override { + if (m_pDownloadHints) + m_pDownloadHints->AddSegment(m_pDownloadHints, offset, size); } private: FX_DOWNLOADHINTS* m_pDownloadHints; }; -class CFPDF_DataAvail { +class FPDF_AvailContext { public: - CFPDF_DataAvail() - : m_FileAvail(new CFPDF_FileAvailWrap), - m_FileRead(CFPDF_FileAccessWrap::Create()) {} - ~CFPDF_DataAvail() {} + FPDF_AvailContext() + : m_FileAvail(pdfium::MakeUnique()), + m_FileRead(pdfium::MakeRetain()) {} + ~FPDF_AvailContext() {} + std::unique_ptr m_FileAvail; + RetainPtr m_FileRead; std::unique_ptr m_pDataAvail; - std::unique_ptr m_FileAvail; - CFX_RetainPtr m_FileRead; }; -CFPDF_DataAvail* CFPDFDataAvailFromFPDFAvail(FPDF_AVAIL avail) { - return static_cast(avail); +FPDF_AvailContext* FPDFAvailContextFromFPDFAvail(FPDF_AVAIL avail) { + return static_cast(avail); } } // namespace -DLLEXPORT FPDF_AVAIL STDCALL FPDFAvail_Create(FX_FILEAVAIL* file_avail, - FPDF_FILEACCESS* file) { - CFPDF_DataAvail* pAvail = new CFPDF_DataAvail; +FPDF_EXPORT FPDF_AVAIL FPDF_CALLCONV FPDFAvail_Create(FX_FILEAVAIL* file_avail, + FPDF_FILEACCESS* file) { + auto pAvail = pdfium::MakeUnique(); pAvail->m_FileAvail->Set(file_avail); pAvail->m_FileRead->Set(file); pAvail->m_pDataAvail = pdfium::MakeUnique( pAvail->m_FileAvail.get(), pAvail->m_FileRead, true); - return pAvail; + return pAvail.release(); // Caller takes ownership. } -DLLEXPORT void STDCALL FPDFAvail_Destroy(FPDF_AVAIL avail) { - delete (CFPDF_DataAvail*)avail; +FPDF_EXPORT void FPDF_CALLCONV FPDFAvail_Destroy(FPDF_AVAIL avail) { + // Take ownership back from caller and destroy. + std::unique_ptr(FPDFAvailContextFromFPDFAvail(avail)); } -DLLEXPORT int STDCALL FPDFAvail_IsDocAvail(FPDF_AVAIL avail, - FX_DOWNLOADHINTS* hints) { - if (!avail || !hints) +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsDocAvail(FPDF_AVAIL avail, + FX_DOWNLOADHINTS* hints) { + if (!avail) return PDF_DATA_ERROR; - CFPDF_DownloadHintsWrap hints_wrap(hints); - return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsDocAvail( - &hints_wrap); + FPDF_DownloadHintsContext hints_context(hints); + return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsDocAvail( + &hints_context); } -DLLEXPORT FPDF_DOCUMENT STDCALL +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDFAvail_GetDocument(FPDF_AVAIL avail, FPDF_BYTESTRING password) { - CFPDF_DataAvail* pDataAvail = static_cast(avail); + auto* pDataAvail = FPDFAvailContextFromFPDFAvail(avail); if (!pDataAvail) return nullptr; - - std::unique_ptr pParser(new CPDF_Parser); - pParser->SetPassword(password); - - std::unique_ptr pDocument( - new CPDF_Document(std::move(pParser))); - CPDF_Parser::Error error = pDocument->GetParser()->StartLinearizedParse( - pDataAvail->m_pDataAvail->GetFileRead(), pDocument.get()); + CPDF_Parser::Error error; + std::unique_ptr document; + std::tie(error, document) = pDataAvail->m_pDataAvail->ParseDocument(password); if (error != CPDF_Parser::SUCCESS) { ProcessParseError(error); return nullptr; } - pDataAvail->m_pDataAvail->SetDocument(pDocument.get()); - CheckUnSupportError(pDocument.get(), FPDF_ERR_SUCCESS); - return FPDFDocumentFromCPDFDocument(pDocument.release()); + CheckUnSupportError(document.get(), FPDF_ERR_SUCCESS); + return FPDFDocumentFromCPDFDocument(document.release()); } -DLLEXPORT int STDCALL FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc) { +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc); return pDoc ? pDoc->GetParser()->GetFirstPageNo() : 0; } -DLLEXPORT int STDCALL FPDFAvail_IsPageAvail(FPDF_AVAIL avail, - int page_index, - FX_DOWNLOADHINTS* hints) { - if (!avail || !hints) +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsPageAvail(FPDF_AVAIL avail, + int page_index, + FX_DOWNLOADHINTS* hints) { + if (!avail) return PDF_DATA_ERROR; if (page_index < 0) return PDF_DATA_NOTAVAIL; - CFPDF_DownloadHintsWrap hints_wrap(hints); - return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsPageAvail( - page_index, &hints_wrap); + FPDF_DownloadHintsContext hints_context(hints); + return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsPageAvail( + page_index, &hints_context); } -DLLEXPORT int STDCALL FPDFAvail_IsFormAvail(FPDF_AVAIL avail, - FX_DOWNLOADHINTS* hints) { - if (!avail || !hints) +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsFormAvail(FPDF_AVAIL avail, + FX_DOWNLOADHINTS* hints) { + if (!avail) return PDF_FORM_ERROR; - CFPDF_DownloadHintsWrap hints_wrap(hints); - return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsFormAvail( - &hints_wrap); + FPDF_DownloadHintsContext hints_context(hints); + return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsFormAvail( + &hints_context); } -DLLEXPORT int STDCALL FPDFAvail_IsLinearized(FPDF_AVAIL avail) { +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsLinearized(FPDF_AVAIL avail) { if (!avail) return PDF_LINEARIZATION_UNKNOWN; - return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsLinearizedPDF(); + return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsLinearizedPDF(); } diff --git a/fpdfsdk/fpdf_dataavail_embeddertest.cpp b/fpdfsdk/fpdf_dataavail_embeddertest.cpp index c226a31b8e85462ac9c8f73e969774d3288e4d12..20841538527c05182eb70f8784e007bab7bf7895 100644 --- a/fpdfsdk/fpdf_dataavail_embeddertest.cpp +++ b/fpdfsdk/fpdf_dataavail_embeddertest.cpp @@ -12,10 +12,25 @@ #include "public/fpdfview.h" #include "testing/embedder_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/range_set.h" #include "testing/test_support.h" #include "testing/utils/path_service.h" namespace { + +class MockDownloadHints : public FX_DOWNLOADHINTS { + public: + static void SAddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) { + } + + MockDownloadHints() { + FX_DOWNLOADHINTS::version = 1; + FX_DOWNLOADHINTS::AddSegment = SAddSegment; + } + + ~MockDownloadHints() {} +}; + class TestAsyncLoader : public FX_DOWNLOADHINTS, FX_FILEAVAIL { public: explicit TestAsyncLoader(const std::string& file_name) { @@ -60,50 +75,25 @@ class TestAsyncLoader : public FX_DOWNLOADHINTS, FX_FILEAVAIL { } size_t max_already_available_bound() const { - return available_ranges_.empty() ? 0 : available_ranges_.rbegin()->second; + return available_ranges_.IsEmpty() + ? 0 + : available_ranges_.ranges().rbegin()->second; } - private: - void SetDataAvailable(size_t start, size_t size) { - if (size == 0) - return; - const auto range = std::make_pair(start, start + size); - if (available_ranges_.empty()) { - available_ranges_.insert(range); - return; - } - auto start_it = available_ranges_.upper_bound(range); - if (start_it != available_ranges_.begin()) - --start_it; // start now points to the key equal or lower than offset. - if (start_it->second < range.first) - ++start_it; // start element is entirely before current range, skip it. - - auto end_it = available_ranges_.upper_bound( - std::make_pair(range.second, range.second)); - if (start_it == end_it) { // No ranges to merge. - available_ranges_.insert(range); - return; + void FlushRequestedData() { + for (const auto& it : requested_segments_) { + SetDataAvailable(it.first, it.second); } + ClearRequestedSegments(); + } - --end_it; - - size_t new_start = std::min(start_it->first, range.first); - size_t new_end = std::max(end_it->second, range.second); - - available_ranges_.erase(start_it, ++end_it); - available_ranges_.insert(std::make_pair(new_start, new_end)); + private: + void SetDataAvailable(size_t start, size_t size) { + available_ranges_.Union(RangeSet::Range(start, start + size)); } bool CheckDataAlreadyAvailable(size_t start, size_t size) const { - if (size == 0) - return false; - const auto range = std::make_pair(start, start + size); - auto it = available_ranges_.upper_bound(range); - if (it == available_ranges_.begin()) - return false; // No ranges includes range.start(). - - --it; // Now it starts equal or before range.start(). - return it->second >= range.second; + return available_ranges_.Contains(RangeSet::Range(start, start + size)); } int GetBlockImpl(unsigned long pos, unsigned char* pBuf, unsigned long size) { @@ -158,14 +148,7 @@ class TestAsyncLoader : public FX_DOWNLOADHINTS, FX_FILEAVAIL { size_t max_requested_bound_ = 0; bool is_new_data_available_ = true; - using Range = std::pair; - struct range_compare { - bool operator()(const Range& lval, const Range& rval) const { - return lval.first < rval.first; - } - }; - using RangesContainer = std::set; - RangesContainer available_ranges_; + RangeSet available_ranges_; }; } // namespace @@ -175,13 +158,15 @@ class FPDFDataAvailEmbeddertest : public EmbedderTest {}; TEST_F(FPDFDataAvailEmbeddertest, TrailerUnterminated) { // Document must load without crashing but is too malformed to be available. EXPECT_FALSE(OpenDocument("trailer_unterminated.pdf")); - EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints_)); + MockDownloadHints hints; + EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints)); } TEST_F(FPDFDataAvailEmbeddertest, TrailerAsHexstring) { // Document must load without crashing but is too malformed to be available. EXPECT_FALSE(OpenDocument("trailer_as_hexstring.pdf")); - EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints_)); + MockDownloadHints hints; + EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints)); } TEST_F(FPDFDataAvailEmbeddertest, LoadUsingHintTables) { @@ -194,9 +179,29 @@ TEST_F(FPDFDataAvailEmbeddertest, LoadUsingHintTables) { // No new data available, to prevent load "Pages" node. loader.set_is_new_data_available(false); - FPDF_PAGE page = LoadPage(1); + FPDF_PAGE page = FPDF_LoadPage(document(), 1); EXPECT_TRUE(page); - UnloadPage(page); + FPDF_ClosePage(page); +} + +TEST_F(FPDFDataAvailEmbeddertest, CheckFormAvailIfLinearized) { + TestAsyncLoader loader("feature_linearized_loading.pdf"); + avail_ = FPDFAvail_Create(loader.file_avail(), loader.file_access()); + ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsDocAvail(avail_, loader.hints())); + document_ = FPDFAvail_GetDocument(avail_, nullptr); + ASSERT_TRUE(document_); + + // Prevent access to non requested data to coerce the parser to send new + // request for non available (non requested before) data. + loader.set_is_new_data_available(false); + loader.ClearRequestedSegments(); + + int status = PDF_FORM_NOTAVAIL; + while (status == PDF_FORM_NOTAVAIL) { + loader.FlushRequestedData(); + status = FPDFAvail_IsFormAvail(avail_, loader.hints()); + } + EXPECT_NE(PDF_FORM_ERROR, status); } TEST_F(FPDFDataAvailEmbeddertest, @@ -234,7 +239,35 @@ TEST_F(FPDFDataAvailEmbeddertest, // Prevent loading data, while page loading. loader.set_is_new_data_available(false); - FPDF_PAGE page = LoadPage(first_page_num); + FPDF_PAGE page = FPDF_LoadPage(document(), first_page_num); + EXPECT_TRUE(page); + FPDF_ClosePage(page); +} + +TEST_F(FPDFDataAvailEmbeddertest, LoadSecondPageIfLinearizedWithHints) { + TestAsyncLoader loader("feature_linearized_loading.pdf"); + avail_ = FPDFAvail_Create(loader.file_avail(), loader.file_access()); + ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsDocAvail(avail_, loader.hints())); + document_ = FPDFAvail_GetDocument(avail_, nullptr); + ASSERT_TRUE(document_); + + static constexpr uint32_t kSecondPageNum = 1; + + // Prevent access to non requested data to coerce the parser to send new + // request for non available (non requested before) data. + loader.set_is_new_data_available(false); + loader.ClearRequestedSegments(); + + int status = PDF_DATA_NOTAVAIL; + while (status == PDF_DATA_NOTAVAIL) { + loader.FlushRequestedData(); + status = FPDFAvail_IsPageAvail(avail_, kSecondPageNum, loader.hints()); + } + EXPECT_EQ(PDF_DATA_AVAIL, status); + + // Prevent loading data, while page loading. + loader.set_is_new_data_available(false); + FPDF_PAGE page = FPDF_LoadPage(document(), kSecondPageNum); EXPECT_TRUE(page); - UnloadPage(page); + FPDF_ClosePage(page); } diff --git a/fpdfsdk/fpdf_ext.cpp b/fpdfsdk/fpdf_ext.cpp index 3bcb0c04b66482a8fa4c8f011672e901bb2ed2c2..87605cfad6a8b79394769f09cd4645e6c109315d 100644 --- a/fpdfsdk/fpdf_ext.cpp +++ b/fpdfsdk/fpdf_ext.cpp @@ -14,9 +14,9 @@ #include "core/fpdfdoc/cpdf_annot.h" #include "core/fpdfdoc/cpdf_interform.h" #include "core/fpdfdoc/cpdf_metadata.h" -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_xml.h" +#include "core/fxcrt/xml/cxml_content.h" +#include "core/fxcrt/xml/cxml_element.h" #include "fpdfsdk/fsdk_define.h" #include "third_party/base/ptr_util.h" @@ -36,7 +36,7 @@ bool FPDF_UnSupportError(int nError) { return true; } -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info) { if (!unsp_info || unsp_info->version != 1) return false; @@ -52,7 +52,7 @@ void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot) { FPDF_UnSupportError(FPDF_UNSP_ANNOT_3DANNOT); } else if (nAnnotSubtype == CPDF_Annot::Subtype::SCREEN) { const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict(); - CFX_ByteString cbString; + ByteString cbString; if (pAnnotDict->KeyExist("IT")) cbString = pAnnotDict->GetStringFor("IT"); if (cbString.Compare("Img") != 0) @@ -67,7 +67,7 @@ void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot) { FPDF_UnSupportError(FPDF_UNSP_ANNOT_ATTACHMENT); } else if (nAnnotSubtype == CPDF_Annot::Subtype::WIDGET) { const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict(); - CFX_ByteString cbString; + ByteString cbString; if (pAnnotDict->KeyExist("FT")) cbString = pAnnotDict->GetStringFor("FT"); if (cbString.Compare("Sig") == 0) @@ -75,22 +75,23 @@ void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot) { } } -bool CheckSharedForm(const CXML_Element* pElement, CFX_ByteString cbName) { - int count = pElement->CountAttrs(); - int i = 0; - for (i = 0; i < count; i++) { - CFX_ByteString space, name; - CFX_WideString value; - pElement->GetAttrByIndex(i, space, name, value); +bool CheckSharedForm(const CXML_Element* pElement, ByteString cbName) { + size_t count = pElement->CountAttrs(); + for (size_t i = 0; i < count; ++i) { + ByteString space; + ByteString name; + WideString value; + pElement->GetAttrByIndex(i, &space, &name, &value); if (space == "xmlns" && name == "adhocwf" && value == L"http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/") { CXML_Element* pVersion = - pElement->GetElement("adhocwf", cbName.AsStringC()); + pElement->GetElement("adhocwf", cbName.AsStringView(), 0); if (!pVersion) continue; - CFX_WideString wsContent = pVersion->GetContent(0); - int nType = wsContent.GetInteger(); - switch (nType) { + CXML_Content* pContent = ToContent(pVersion->GetChild(0)); + if (!pContent) + continue; + switch (pContent->m_Content.GetInteger()) { case 1: FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_ACROBAT); break; @@ -104,14 +105,11 @@ bool CheckSharedForm(const CXML_Element* pElement, CFX_ByteString cbName) { } } - uint32_t nCount = pElement->CountChildren(); - for (i = 0; i < (int)nCount; i++) { - CXML_Element::ChildType childType = pElement->GetChildType(i); - if (childType == CXML_Element::Element) { - CXML_Element* pChild = pElement->GetElement(i); - if (CheckSharedForm(pChild, cbName)) - return true; - } + size_t nCount = pElement->CountChildren(); + for (size_t i = 0; i < nCount; ++i) { + CXML_Element* pChild = ToElement(pElement->GetChild(i)); + if (pChild && CheckSharedForm(pChild, cbName)) + return true; } return false; } @@ -126,9 +124,9 @@ void CheckUnSupportError(CPDF_Document* pDoc, uint32_t err_code) { return; // Portfolios and Packages - CPDF_Dictionary* pRootDict = pDoc->GetRoot(); + const CPDF_Dictionary* pRootDict = pDoc->GetRoot(); if (pRootDict) { - CFX_ByteString cbString; + ByteString cbString; if (pRootDict->KeyExist("Collection")) { FPDF_UnSupportError(FPDF_UNSP_DOC_PORTABLECOLLECTION); return; @@ -144,7 +142,7 @@ void CheckUnSupportError(CPDF_Document* pDoc, uint32_t err_code) { CPDF_Array* pArray = pJSDict ? pJSDict->GetArrayFor("Names") : nullptr; if (pArray) { for (size_t i = 0; i < pArray->GetCount(); i++) { - CFX_ByteString cbStr = pArray->GetStringAt(i); + ByteString cbStr = pArray->GetStringAt(i); if (cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0) { FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDREVIEW); return; @@ -169,12 +167,12 @@ void CheckUnSupportError(CPDF_Document* pDoc, uint32_t err_code) { #endif // PDF_ENABLE_XFA } -DLLEXPORT int STDCALL FPDFDoc_GetPageMode(FPDF_DOCUMENT document) { +FPDF_EXPORT int FPDF_CALLCONV FPDFDoc_GetPageMode(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return PAGEMODE_UNKNOWN; - CPDF_Dictionary* pRoot = pDoc->GetRoot(); + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); if (!pRoot) return PAGEMODE_UNKNOWN; @@ -182,7 +180,7 @@ DLLEXPORT int STDCALL FPDFDoc_GetPageMode(FPDF_DOCUMENT document) { if (!pName) return PAGEMODE_USENONE; - CFX_ByteString strPageMode = pName->GetString(); + ByteString strPageMode = pName->GetString(); if (strPageMode.IsEmpty() || strPageMode.EqualNoCase("UseNone")) return PAGEMODE_USENONE; if (strPageMode.EqualNoCase("UseOutlines")) diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp index e649bacf49755dd73814242025d4b9bb0f2466e5..4d066930069fd3fbc65ce09e49e0da462737d814 100644 --- a/fpdfsdk/fpdf_flatten.cpp +++ b/fpdfsdk/fpdf_flatten.cpp @@ -29,29 +29,25 @@ enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM }; namespace { -bool IsValiableRect(CFX_FloatRect rect, CFX_FloatRect rcPage) { - if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f) +bool IsValidRect(const CFX_FloatRect& rect, const CFX_FloatRect& rcPage) { + constexpr float kMinSize = 0.000001f; + if (rect.IsEmpty() || rect.Width() < kMinSize || rect.Height() < kMinSize) return false; - if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f && - rect.bottom == 0.0f) - return false; - - if (!rcPage.IsEmpty()) { - if (rect.left - rcPage.left < -10.000001f || - rect.right - rcPage.right > 10.000001f || - rect.top - rcPage.top > 10.000001f || - rect.bottom - rcPage.bottom < -10.000001f) - return false; - } + if (rcPage.IsEmpty()) + return true; - return true; + constexpr float kMinBorderSize = 10.000001f; + return rect.left - rcPage.left >= -kMinBorderSize && + rect.right - rcPage.right <= kMinBorderSize && + rect.top - rcPage.top <= kMinBorderSize && + rect.bottom - rcPage.bottom >= -kMinBorderSize; } void GetContentsRect(CPDF_Document* pDoc, CPDF_Dictionary* pDict, std::vector* pRectArray) { - std::unique_ptr pPDFPage(new CPDF_Page(pDoc, pDict, false)); + auto pPDFPage = pdfium::MakeUnique(pDoc, pDict, false); pPDFPage->ParseContent(); for (const auto& pPageObject : *pPDFPage->GetPageObjectList()) { @@ -60,7 +56,7 @@ void GetContentsRect(CPDF_Document* pDoc, rc.right = pPageObject->m_Right; rc.bottom = pPageObject->m_Bottom; rc.top = pPageObject->m_Top; - if (IsValiableRect(rc, pDict->GetRectFor("MediaBox"))) + if (IsValidRect(rc, pDict->GetRectFor("MediaBox"))) pRectArray->push_back(rc); } } @@ -77,7 +73,7 @@ void ParserStream(CPDF_Dictionary* pPageDic, else if (pStream->KeyExist("BBox")) rect = pStream->GetRectFor("BBox"); - if (IsValiableRect(rect, pPageDic->GetRectFor("MediaBox"))) + if (IsValidRect(rect, pPageDic->GetRectFor("MediaBox"))) pRectArray->push_back(rect); pObjectArray->push_back(pStream); @@ -96,13 +92,12 @@ int ParserAnnots(CPDF_Document* pSourceDoc, if (!pAnnots) return FLATTEN_NOTHINGTODO; - uint32_t dwSize = pAnnots->GetCount(); - for (int i = 0; i < (int)dwSize; i++) { - CPDF_Dictionary* pAnnotDic = ToDictionary(pAnnots->GetDirectObjectAt(i)); + for (const auto& pAnnot : *pAnnots) { + CPDF_Dictionary* pAnnotDic = ToDictionary(pAnnot->GetDirect()); if (!pAnnotDic) continue; - CFX_ByteString sSubtype = pAnnotDic->GetStringFor("Subtype"); + ByteString sSubtype = pAnnotDic->GetStringFor("Subtype"); if (sSubtype == "Popup") continue; @@ -110,27 +105,25 @@ int ParserAnnots(CPDF_Document* pSourceDoc, if (nAnnotFlag & ANNOTFLAG_HIDDEN) continue; - if (nUsage == FLAT_NORMALDISPLAY) { - if (nAnnotFlag & ANNOTFLAG_INVISIBLE) - continue; - + bool bParseStream; + if (nUsage == FLAT_NORMALDISPLAY) + bParseStream = !(nAnnotFlag & ANNOTFLAG_INVISIBLE); + else + bParseStream = !!(nAnnotFlag & ANNOTFLAG_PRINT); + if (bParseStream) ParserStream(pPageDic, pAnnotDic, pRectArray, pObjectArray); - } else { - if (nAnnotFlag & ANNOTFLAG_PRINT) - ParserStream(pPageDic, pAnnotDic, pRectArray, pObjectArray); - } } return FLATTEN_SUCCESS; } -FX_FLOAT GetMinMaxValue(const std::vector& array, - FPDF_TYPE type, - FPDF_VALUE value) { - size_t nRects = array.size(); - if (nRects <= 0) +float GetMinMaxValue(const std::vector& array, + FPDF_TYPE type, + FPDF_VALUE value) { + if (array.empty()) return 0.0f; - std::vector pArray(nRects); + size_t nRects = array.size(); + std::vector pArray(nRects); switch (value) { case LEFT: for (size_t i = 0; i < nRects; i++) @@ -149,11 +142,11 @@ FX_FLOAT GetMinMaxValue(const std::vector& array, pArray[i] = array[i].bottom; break; default: - // Not reachable. + NOTREACHED(); return 0.0f; } - FX_FLOAT fRet = pArray[0]; + float fRet = pArray[0]; if (type == MAX) { for (size_t i = 1; i < nRects; i++) fRet = std::max(fRet, pArray[i]); @@ -175,18 +168,18 @@ CFX_FloatRect CalculateRect(std::vector* pRectArray) { return rcRet; } -uint32_t NewIndirectContentsStream(const CFX_ByteString& key, +uint32_t NewIndirectContentsStream(const ByteString& key, CPDF_Document* pDocument) { CPDF_Stream* pNewContents = pDocument->NewIndirect( nullptr, 0, pdfium::MakeUnique(pDocument->GetByteStringPool())); - CFX_ByteString sStream; - sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); + ByteString sStream = + ByteString::Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); return pNewContents->GetObjNum(); } -void SetPageContents(const CFX_ByteString& key, +void SetPageContents(const ByteString& key, CPDF_Dictionary* pPage, CPDF_Document* pDocument) { CPDF_Array* pContentsArray = nullptr; @@ -204,13 +197,13 @@ void SetPageContents(const CFX_ByteString& key, pPage->ConvertToIndirectObjectFor("Contents", pDocument); if (!pContentsArray) { pContentsArray = pDocument->NewIndirect(); - CPDF_StreamAcc acc; - acc.LoadAllData(pContentsStream); - CFX_ByteString sStream = "q\n"; - CFX_ByteString sBody = - CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize()); + auto pAcc = pdfium::MakeRetain(pContentsStream); + pAcc->LoadAllDataFiltered(); + ByteString sStream = "q\n"; + ByteString sBody = ByteString(pAcc->GetData(), pAcc->GetSize()); sStream = sStream + sBody + "\nQ"; - pContentsStream->SetData(sStream.raw_str(), sStream.GetLength()); + pContentsStream->SetDataAndRemoveFilter(sStream.raw_str(), + sStream.GetLength()); pContentsArray->AddNew(pDocument, pContentsStream->GetObjNum()); pPage->SetNewFor("Contents", pDocument, @@ -228,26 +221,26 @@ CFX_Matrix GetMatrix(CFX_FloatRect rcAnnot, if (rcStream.IsEmpty()) return CFX_Matrix(); - matrix.TransformRect(rcStream); + rcStream = matrix.TransformRect(rcStream); rcStream.Normalize(); - FX_FLOAT a = rcAnnot.Width() / rcStream.Width(); - FX_FLOAT d = rcAnnot.Height() / rcStream.Height(); + float a = rcAnnot.Width() / rcStream.Width(); + float d = rcAnnot.Height() / rcStream.Height(); - FX_FLOAT e = rcAnnot.left - rcStream.left * a; - FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d; + float e = rcAnnot.left - rcStream.left * a; + float f = rcAnnot.bottom - rcStream.bottom * d; return CFX_Matrix(a, 0, 0, d, e, f); } } // namespace -DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!page) return FLATTEN_FAIL; - CPDF_Document* pDocument = pPage->m_pDocument; - CPDF_Dictionary* pPageDict = pPage->m_pFormDict; + CPDF_Document* pDocument = pPage->m_pDocument.Get(); + CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get(); if (!pDocument || !pPageDict) return FLATTEN_FAIL; @@ -305,15 +298,16 @@ DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { if (!pPageXObject) pPageXObject = pRes->SetNewFor("XObject"); - CFX_ByteString key = ""; - int nStreams = pdfium::CollectionSize(ObjectArray); - if (nStreams > 0) { - for (int iKey = 0; /*iKey < 100*/; iKey++) { - char sExtend[5] = {}; - FXSYS_itoa(iKey, sExtend, 10); - key = CFX_ByteString("FFT") + CFX_ByteString(sExtend); - if (!pPageXObject->KeyExist(key)) + ByteString key; + if (!ObjectArray.empty()) { + int i = 0; + while (i < INT_MAX) { + ByteString sKey = ByteString::Format("FFT%d", i); + if (!pPageXObject->KeyExist(sKey)) { + key = sKey; break; + } + ++i; } } @@ -327,12 +321,11 @@ DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { pNewOXbjectDic->SetNewFor("Type", "XObject"); pNewOXbjectDic->SetNewFor("Subtype", "Form"); pNewOXbjectDic->SetNewFor("FormType", 1); - pNewOXbjectDic->SetNewFor("Name", "FRM"); CFX_FloatRect rcBBox = pPageDict->GetRectFor("ArtBox"); pNewOXbjectDic->SetRectFor("BBox", rcBBox); } - for (int i = 0; i < nStreams; i++) { + for (size_t i = 0; i < ObjectArray.size(); ++i) { CPDF_Dictionary* pAnnotDic = ObjectArray[i]; if (!pAnnotDic) continue; @@ -340,7 +333,7 @@ DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { CFX_FloatRect rcAnnot = pAnnotDic->GetRectFor("Rect"); rcAnnot.Normalize(); - CFX_ByteString sAnnotState = pAnnotDic->GetStringFor("AS"); + ByteString sAnnotState = pAnnotDic->GetStringFor("AS"); CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDictFor("AP"); if (!pAnnotAP) continue; @@ -354,9 +347,8 @@ DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { if (!sAnnotState.IsEmpty()) { pAPStream = pAPDic->GetStreamFor(sAnnotState); } else { - auto it = pAPDic->begin(); - if (it != pAPDic->end()) { - CPDF_Object* pFirstObj = it->second.get(); + if (pAPDic->GetCount() > 0) { + CPDF_Object* pFirstObj = pAPDic->begin()->second.get(); if (pFirstObj) { if (pFirstObj->IsReference()) pFirstObj = pFirstObj->GetDirect(); @@ -397,32 +389,18 @@ DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { if (!pXObject) pXObject = pNewXORes->SetNewFor("XObject"); - CFX_ByteString sFormName; - sFormName.Format("F%d", i); + ByteString sFormName = ByteString::Format("F%d", i); pXObject->SetNewFor(sFormName, pDocument, pObj->GetObjNum()); - CPDF_StreamAcc acc; - acc.LoadAllData(pNewXObject); - - const uint8_t* pData = acc.GetData(); - CFX_ByteString sStream(pData, acc.GetSize()); + auto pAcc = pdfium::MakeRetain(pNewXObject); + pAcc->LoadAllDataFiltered(); + ByteString sStream(pAcc->GetData(), pAcc->GetSize()); CFX_Matrix matrix = pAPDic->GetMatrixFor("Matrix"); - if (matrix.IsIdentity()) { - matrix.a = 1.0f; - matrix.b = 0.0f; - matrix.c = 0.0f; - matrix.d = 1.0f; - matrix.e = 0.0f; - matrix.f = 0.0f; - } - - CFX_ByteString sTemp; CFX_Matrix m = GetMatrix(rcAnnot, rcStream, matrix); - sTemp.Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d, m.e, m.f, - sFormName.c_str()); - sStream += sTemp; - pNewXObject->SetData(sStream.raw_str(), sStream.GetLength()); + sStream += ByteString::Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d, + m.e, m.f, sFormName.c_str()); + pNewXObject->SetDataAndRemoveFilter(sStream.raw_str(), sStream.GetLength()); } pPageDict->RemoveFor("Annots"); return FLATTEN_SUCCESS; diff --git a/fpdfsdk/fpdf_flatten_embeddertest.cpp b/fpdfsdk/fpdf_flatten_embeddertest.cpp index d709f59053f7e5acf84c18b5ac079863e38fff2c..a8915fe60ce7e0e0fedb12916fa52096435efdbc 100644 --- a/fpdfsdk/fpdf_flatten_embeddertest.cpp +++ b/fpdfsdk/fpdf_flatten_embeddertest.cpp @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "core/fxcrt/fx_basic.h" #include "public/fpdf_flatten.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" diff --git a/fpdfsdk/fpdf_progressive.cpp b/fpdfsdk/fpdf_progressive.cpp index cc09d0763807fcd9f2a65e6cd4a78abbc588a7bc..730ba48162b95e58ff4e867739394d421151c99b 100644 --- a/fpdfsdk/fpdf_progressive.cpp +++ b/fpdfsdk/fpdf_progressive.cpp @@ -6,11 +6,13 @@ #include "public/fpdf_progressive.h" +#include + #include "core/fpdfapi/cpdf_pagerendercontext.h" #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/render/cpdf_progressiverenderer.h" #include "core/fxcrt/fx_memory.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_renderdevice.h" #include "fpdfsdk/fsdk_define.h" #include "fpdfsdk/fsdk_pauseadapter.h" @@ -18,25 +20,25 @@ #include "third_party/base/ptr_util.h" // These checks are here because core/ and public/ cannot depend on each other. -static_assert(CPDF_ProgressiveRenderer::Ready == FPDF_RENDER_READER, +static_assert(CPDF_ProgressiveRenderer::Ready == FPDF_RENDER_READY, "CPDF_ProgressiveRenderer::Ready value mismatch"); static_assert(CPDF_ProgressiveRenderer::ToBeContinued == - FPDF_RENDER_TOBECOUNTINUED, + FPDF_RENDER_TOBECONTINUED, "CPDF_ProgressiveRenderer::ToBeContinued value mismatch"); static_assert(CPDF_ProgressiveRenderer::Done == FPDF_RENDER_DONE, "CPDF_ProgressiveRenderer::Done value mismatch"); static_assert(CPDF_ProgressiveRenderer::Failed == FPDF_RENDER_FAILED, "CPDF_ProgressiveRenderer::Failed value mismatch"); -DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags, - IFSDK_PAUSE* pause) { +FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags, + IFSDK_PAUSE* pause) { if (!bitmap || !pause || pause->version != 1) return FPDF_RENDER_FAILED; @@ -44,17 +46,24 @@ DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, if (!pPage) return FPDF_RENDER_FAILED; - CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext; - pPage->SetRenderContext(pdfium::WrapUnique(pContext)); - CFX_FxgeDevice* pDevice = new CFX_FxgeDevice; - pContext->m_pDevice.reset(pDevice); - CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap); + auto pOwnedContext = pdfium::MakeUnique(); + CPDF_PageRenderContext* pContext = pOwnedContext.get(); + pPage->SetRenderContext(std::move(pOwnedContext)); + + RetainPtr pBitmap(CFXBitmapFromFPDFBitmap(bitmap)); + auto pOwnedDevice = pdfium::MakeUnique(); + CFX_DefaultRenderDevice* pDevice = pOwnedDevice.get(); + pContext->m_pDevice = std::move(pOwnedDevice); pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false); IFSDK_PAUSE_Adapter IPauseAdapter(pause); FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, rotate, flags, false, &IPauseAdapter); +#ifdef _SKIA_SUPPORT_PATHS_ + pDevice->Flush(false); + pBitmap->UnPreMultiply(); +#endif if (pContext->m_pRenderer) { return CPDF_ProgressiveRenderer::ToFPDFStatus( pContext->m_pRenderer->GetStatus()); @@ -62,8 +71,8 @@ DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, return FPDF_RENDER_FAILED; } -DLLEXPORT int STDCALL FPDF_RenderPage_Continue(FPDF_PAGE page, - IFSDK_PAUSE* pause) { +FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPage_Continue(FPDF_PAGE page, + IFSDK_PAUSE* pause) { if (!pause || pause->version != 1) return FPDF_RENDER_FAILED; @@ -75,21 +84,28 @@ DLLEXPORT int STDCALL FPDF_RenderPage_Continue(FPDF_PAGE page, if (pContext && pContext->m_pRenderer) { IFSDK_PAUSE_Adapter IPauseAdapter(pause); pContext->m_pRenderer->Continue(&IPauseAdapter); +#ifdef _SKIA_SUPPORT_PATHS_ + CFX_RenderDevice* pDevice = pContext->m_pDevice.get(); + pDevice->Flush(false); + pDevice->GetBitmap()->UnPreMultiply(); +#endif return CPDF_ProgressiveRenderer::ToFPDFStatus( pContext->m_pRenderer->GetStatus()); } return FPDF_RENDER_FAILED; } -DLLEXPORT void STDCALL FPDF_RenderPage_Close(FPDF_PAGE page) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage_Close(FPDF_PAGE page) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); - if (!pPage) - return; - - CPDF_PageRenderContext* pContext = pPage->GetRenderContext(); - if (!pContext) - return; - - pContext->m_pDevice->RestoreState(false); - pPage->SetRenderContext(nullptr); + if (pPage) { +#ifdef _SKIA_SUPPORT_PATHS_ + CPDF_PageRenderContext* pContext = pPage->GetRenderContext(); + if (pContext && pContext->m_pRenderer) { + CFX_RenderDevice* pDevice = pContext->m_pDevice.get(); + pDevice->Flush(true); + pDevice->GetBitmap()->UnPreMultiply(); + } +#endif + pPage->SetRenderContext(nullptr); + } } diff --git a/fpdfsdk/fpdf_searchex.cpp b/fpdfsdk/fpdf_searchex.cpp index f82db37b5a8fa0f0d32cbb1bbace7516295074a5..9d48cebf8ad64a34f357a57201af4aae4a127be4 100644 --- a/fpdfsdk/fpdf_searchex.cpp +++ b/fpdfsdk/fpdf_searchex.cpp @@ -8,10 +8,18 @@ #include "core/fpdftext/cpdf_textpage.h" -DLLEXPORT int STDCALL +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetCharIndexFromTextIndex(FPDF_TEXTPAGE text_page, int nTextIndex) { if (!text_page) return -1; return static_cast(text_page) ->CharIndexFromTextIndex(nTextIndex); } + +FPDF_EXPORT int FPDF_CALLCONV +FPDFText_GetTextIndexFromCharIndex(FPDF_TEXTPAGE text_page, int nCharIndex) { + if (!text_page) + return -1; + return static_cast(text_page)->TextIndexFromCharIndex( + nCharIndex); +} diff --git a/fpdfsdk/fpdf_structtree.cpp b/fpdfsdk/fpdf_structtree.cpp index 5a922a1c3b34c3db499bdaae18f03cd9c2ff410c..676824ef99de6ffc8f2bca7b46dc81ced2049762 100644 --- a/fpdfsdk/fpdf_structtree.cpp +++ b/fpdfsdk/fpdf_structtree.cpp @@ -8,82 +8,124 @@ #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfdoc/fpdf_tagged.h" +#include "core/fpdfdoc/cpdf_structelement.h" +#include "core/fpdfdoc/cpdf_structtree.h" #include "fpdfsdk/fsdk_define.h" namespace { -IPDF_StructTree* ToStructTree(FPDF_STRUCTTREE struct_tree) { - return reinterpret_cast(struct_tree); +CPDF_StructTree* ToStructTree(FPDF_STRUCTTREE struct_tree) { + return static_cast(struct_tree); } -IPDF_StructElement* ToStructTreeElement(FPDF_STRUCTELEMENT struct_element) { - return reinterpret_cast(struct_element); +CPDF_StructElement* ToStructTreeElement(FPDF_STRUCTELEMENT struct_element) { + return static_cast(struct_element); +} + +unsigned long WideStringToBuffer(const WideString& str, + void* buffer, + unsigned long buflen) { + if (str.IsEmpty()) + return 0; + + ByteString encodedStr = str.UTF16LE_Encode(); + const unsigned long len = encodedStr.GetLength(); + if (buffer && len <= buflen) + memcpy(buffer, encodedStr.c_str(), len); + return len; } } // namespace -DLLEXPORT FPDF_STRUCTTREE STDCALL FPDF_StructTree_GetForPage(FPDF_PAGE page) { +FPDF_EXPORT FPDF_STRUCTTREE FPDF_CALLCONV +FPDF_StructTree_GetForPage(FPDF_PAGE page) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return nullptr; - return IPDF_StructTree::LoadPage(pPage->m_pDocument, pPage->m_pFormDict) + return CPDF_StructTree::LoadPage(pPage->m_pDocument.Get(), + pPage->m_pFormDict.Get()) .release(); } -DLLEXPORT void STDCALL FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree) { - std::unique_ptr(ToStructTree(struct_tree)); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree) { + std::unique_ptr(ToStructTree(struct_tree)); } -DLLEXPORT int STDCALL +FPDF_EXPORT int FPDF_CALLCONV FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree) { - IPDF_StructTree* tree = ToStructTree(struct_tree); - return tree ? tree->CountTopElements() : -1; + CPDF_StructTree* tree = ToStructTree(struct_tree); + if (!tree) + return -1; + + pdfium::base::CheckedNumeric tmp_size = tree->CountTopElements(); + return tmp_size.ValueOrDefault(-1); } -DLLEXPORT FPDF_STRUCTELEMENT STDCALL +FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index) { - IPDF_StructTree* tree = ToStructTree(struct_tree); - if (!tree || index < 0 || index >= tree->CountTopElements()) + CPDF_StructTree* tree = ToStructTree(struct_tree); + if (!tree || index < 0 || + static_cast(index) >= tree->CountTopElements()) { return nullptr; - return tree->GetTopElement(index); + } + return tree->GetTopElement(static_cast(index)); } -DLLEXPORT unsigned long STDCALL +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element, void* buffer, unsigned long buflen) { - IPDF_StructElement* elem = ToStructTreeElement(struct_element); - if (!elem) - return 0; + CPDF_StructElement* elem = ToStructTreeElement(struct_element); + return (elem && elem->GetDict()) + ? WideStringToBuffer(elem->GetDict()->GetUnicodeTextFor("Alt"), + buffer, buflen) + : 0; +} - CPDF_Dictionary* dict = elem->GetDict(); - if (!dict) - return 0; +FPDF_EXPORT int FPDF_CALLCONV +FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element) { + CPDF_StructElement* elem = ToStructTreeElement(struct_element); + CPDF_Object* p = + (elem && elem->GetDict()) ? elem->GetDict()->GetObjectFor("K") : nullptr; + return p && p->IsNumber() ? p->GetInteger() : -1; +} - CFX_WideString str = elem->GetDict()->GetUnicodeTextFor("Alt"); - if (str.IsEmpty()) - return 0; +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element, + void* buffer, + unsigned long buflen) { + CPDF_StructElement* elem = ToStructTreeElement(struct_element); + return elem ? WideStringToBuffer(elem->GetType().UTF8Decode(), buffer, buflen) + : 0; +} - CFX_ByteString encodedStr = str.UTF16LE_Encode(); - const unsigned long len = encodedStr.GetLength(); - if (buffer && len <= buflen) - FXSYS_memcpy(buffer, encodedStr.c_str(), len); - return len; +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element, + void* buffer, + unsigned long buflen) { + CPDF_StructElement* elem = ToStructTreeElement(struct_element); + return elem + ? WideStringToBuffer(elem->GetTitle().UTF8Decode(), buffer, buflen) + : 0; } -DLLEXPORT int STDCALL +FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element) { - IPDF_StructElement* elem = ToStructTreeElement(struct_element); - return elem ? elem->CountKids() : -1; + CPDF_StructElement* elem = ToStructTreeElement(struct_element); + if (!elem) + return -1; + + pdfium::base::CheckedNumeric tmp_size = elem->CountKids(); + return tmp_size.ValueOrDefault(-1); } -DLLEXPORT FPDF_STRUCTELEMENT STDCALL +FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element, int index) { - IPDF_StructElement* elem = ToStructTreeElement(struct_element); - if (!elem || index < 0 || index >= elem->CountKids()) + CPDF_StructElement* elem = ToStructTreeElement(struct_element); + if (!elem || index < 0 || static_cast(index) >= elem->CountKids()) return nullptr; - return elem->GetKidIfElement(index); + return elem->GetKidIfElement(static_cast(index)); } diff --git a/fpdfsdk/fpdf_structtree_embeddertest.cpp b/fpdfsdk/fpdf_structtree_embeddertest.cpp index 58b317205761c2c931f3a1d737cbb8a23d4aeaf0..7ca81f7b2ef6d3f2cf890fc60242d346236fed57 100644 --- a/fpdfsdk/fpdf_structtree_embeddertest.cpp +++ b/fpdfsdk/fpdf_structtree_embeddertest.cpp @@ -6,8 +6,9 @@ #include "public/fpdf_structtree.h" #include "testing/embedder_test.h" #include "testing/test_support.h" +#include "third_party/base/optional.h" -class FPDFStructTreeEmbeddertest : public EmbedderTest, public TestSaver {}; +class FPDFStructTreeEmbeddertest : public EmbedderTest {}; TEST_F(FPDFStructTreeEmbeddertest, GetAltText) { ASSERT_TRUE(OpenDocument("tagged_alt_text.pdf")); @@ -24,6 +25,7 @@ TEST_F(FPDFStructTreeEmbeddertest, GetAltText) { EXPECT_EQ(nullptr, element); element = FPDF_StructTree_GetChildAtIndex(struct_tree, 0); ASSERT_NE(nullptr, element); + EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(element)); EXPECT_EQ(0U, FPDF_StructElement_GetAltText(element, nullptr, 0)); ASSERT_EQ(1, FPDF_StructElement_CountChildren(element)); @@ -34,6 +36,7 @@ TEST_F(FPDFStructTreeEmbeddertest, GetAltText) { EXPECT_EQ(nullptr, child_element); child_element = FPDF_StructElement_GetChildAtIndex(element, 0); ASSERT_NE(nullptr, child_element); + EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(child_element)); EXPECT_EQ(0U, FPDF_StructElement_GetAltText(child_element, nullptr, 0)); ASSERT_EQ(1, FPDF_StructElement_CountChildren(child_element)); @@ -44,6 +47,7 @@ TEST_F(FPDFStructTreeEmbeddertest, GetAltText) { EXPECT_EQ(nullptr, gchild_element); gchild_element = FPDF_StructElement_GetChildAtIndex(child_element, 0); ASSERT_NE(nullptr, gchild_element); + EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(gchild_element)); ASSERT_EQ(24U, FPDF_StructElement_GetAltText(gchild_element, nullptr, 0)); unsigned short buffer[12]; @@ -54,11 +58,12 @@ TEST_F(FPDFStructTreeEmbeddertest, GetAltText) { for (size_t i = 0; i < FX_ArraySize(buffer); ++i) EXPECT_EQ(0U, buffer[i]); + EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(gchild_element)); ASSERT_EQ(24U, FPDF_StructElement_GetAltText(gchild_element, buffer, sizeof(buffer))); - const FX_WCHAR kExpected[] = L"Black Image"; - EXPECT_EQ(CFX_WideString(kExpected), - CFX_WideString::FromUTF16LE(buffer, FXSYS_len(kExpected))); + const wchar_t kExpected[] = L"Black Image"; + EXPECT_EQ(WideString(kExpected), + WideString::FromUTF16LE(buffer, FXSYS_len(kExpected))); ASSERT_EQ(1, FPDF_StructElement_CountChildren(gchild_element)); FPDF_STRUCTELEMENT ggchild_element = @@ -68,3 +73,48 @@ TEST_F(FPDFStructTreeEmbeddertest, GetAltText) { FPDF_StructTree_Close(struct_tree); FPDF_ClosePage(page); } + +TEST_F(FPDFStructTreeEmbeddertest, GetMarkedContentID) { + ASSERT_TRUE(OpenDocument("marked_content_id.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + FPDF_STRUCTTREE struct_tree = FPDF_StructTree_GetForPage(page); + ASSERT_TRUE(struct_tree); + ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree)); + + FPDF_STRUCTELEMENT element = FPDF_StructTree_GetChildAtIndex(struct_tree, 0); + EXPECT_EQ(0, FPDF_StructElement_GetMarkedContentID(element)); + + FPDF_StructTree_Close(struct_tree); + FPDF_ClosePage(page); +} + +TEST_F(FPDFStructTreeEmbeddertest, GetType) { + ASSERT_TRUE(OpenDocument("tagged_alt_text.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + FPDF_STRUCTTREE struct_tree = FPDF_StructTree_GetForPage(page); + ASSERT_TRUE(struct_tree); + ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree)); + + FPDF_STRUCTELEMENT element = FPDF_StructTree_GetChildAtIndex(struct_tree, 0); + ASSERT_NE(nullptr, element); + + unsigned short buffer[12]; + memset(buffer, 0, sizeof(buffer)); + // Deliberately pass in a small buffer size to make sure |buffer| remains + // untouched. + ASSERT_EQ(18U, FPDF_StructElement_GetType(element, buffer, 1)); + for (size_t i = 0; i < FX_ArraySize(buffer); ++i) + EXPECT_EQ(0U, buffer[i]); + + ASSERT_EQ(18U, FPDF_StructElement_GetType(element, buffer, sizeof(buffer))); + const wchar_t kExpected[] = L"Document"; + EXPECT_EQ(WideString(kExpected), + WideString::FromUTF16LE(buffer, FXSYS_len(kExpected))); + + FPDF_StructTree_Close(struct_tree); + FPDF_ClosePage(page); +} diff --git a/fpdfsdk/fpdf_sysfontinfo.cpp b/fpdfsdk/fpdf_sysfontinfo.cpp index 1b62dc48ac4d4b70411185d74f9c7c0f2f2354f0..97d02e85f5edbfd9dd09ddf706b92eab521a759f 100644 --- a/fpdfsdk/fpdf_sysfontinfo.cpp +++ b/fpdfsdk/fpdf_sysfontinfo.cpp @@ -8,12 +8,28 @@ #include +#include "core/fxcrt/fx_codepage.h" #include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/cfx_fontmgr.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/fx_font.h" #include "core/fxge/ifx_systemfontinfo.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/pdfwindow/PWL_FontMap.h" +#include "fpdfsdk/pwl/cpwl_font_map.h" +#include "third_party/base/ptr_util.h" + +static_assert(FXFONT_ANSI_CHARSET == FX_CHARSET_ANSI, "Charset must match"); +static_assert(FXFONT_DEFAULT_CHARSET == FX_CHARSET_Default, + "Charset must match"); +static_assert(FXFONT_SYMBOL_CHARSET == FX_CHARSET_Symbol, "Charset must match"); +static_assert(FXFONT_SHIFTJIS_CHARSET == FX_CHARSET_ShiftJIS, + "Charset must match"); +static_assert(FXFONT_HANGEUL_CHARSET == FX_CHARSET_Hangul, + "Charset must match"); +static_assert(FXFONT_GB2312_CHARSET == FX_CHARSET_ChineseSimplified, + "Charset must match"); +static_assert(FXFONT_CHINESEBIG5_CHARSET == FX_CHARSET_ChineseTraditional, + "Charset must match"); class CFX_ExternalFontInfo final : public IFX_SystemFontInfo { public: @@ -35,15 +51,16 @@ class CFX_ExternalFontInfo final : public IFX_SystemFontInfo { bool bItalic, int charset, int pitch_family, - const FX_CHAR* family, - int& iExact) override { + const char* family) override { if (!m_pInfo->MapFont) return nullptr; + + int iExact; return m_pInfo->MapFont(m_pInfo, weight, bItalic, charset, pitch_family, family, &iExact); } - void* GetFont(const FX_CHAR* family) override { + void* GetFont(const char* family) override { if (!m_pInfo->GetFont) return nullptr; return m_pInfo->GetFont(m_pInfo, family); @@ -58,7 +75,7 @@ class CFX_ExternalFontInfo final : public IFX_SystemFontInfo { return m_pInfo->GetFontData(m_pInfo, hFont, table, buffer, size); } - bool GetFaceName(void* hFont, CFX_ByteString& name) override { + bool GetFaceName(void* hFont, ByteString* name) override { if (!m_pInfo->GetFaceName) return false; uint32_t size = m_pInfo->GetFaceName(m_pInfo, hFont, nullptr, 0); @@ -66,16 +83,16 @@ class CFX_ExternalFontInfo final : public IFX_SystemFontInfo { return false; char* buffer = FX_Alloc(char, size); size = m_pInfo->GetFaceName(m_pInfo, hFont, buffer, size); - name = CFX_ByteString(buffer, size); + *name = ByteString(buffer, size); FX_Free(buffer); return true; } - bool GetFontCharset(void* hFont, int& charset) override { + bool GetFontCharset(void* hFont, int* charset) override { if (!m_pInfo->GetFontCharset) return false; - charset = m_pInfo->GetFontCharset(m_pInfo, hFont); + *charset = m_pInfo->GetFontCharset(m_pInfo, hFont); return true; } @@ -88,34 +105,33 @@ class CFX_ExternalFontInfo final : public IFX_SystemFontInfo { FPDF_SYSFONTINFO* const m_pInfo; }; -DLLEXPORT void STDCALL FPDF_AddInstalledFont(void* mapper, - const char* name, - int charset) { - CFX_FontMapper* pMapper = reinterpret_cast(mapper); +FPDF_EXPORT void FPDF_CALLCONV FPDF_AddInstalledFont(void* mapper, + const char* name, + int charset) { + CFX_FontMapper* pMapper = static_cast(mapper); pMapper->AddInstalledFont(name, charset); } -DLLEXPORT void STDCALL FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfoExt) { +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfoExt) { if (pFontInfoExt->version != 1) return; CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo( - std::unique_ptr( - new CFX_ExternalFontInfo(pFontInfoExt))); + pdfium::MakeUnique(pFontInfoExt)); } -DLLEXPORT const FPDF_CharsetFontMap* STDCALL FPDF_GetDefaultTTFMap() { +FPDF_EXPORT const FPDF_CharsetFontMap* FPDF_CALLCONV FPDF_GetDefaultTTFMap() { return CPWL_FontMap::defaultTTFMap; } struct FPDF_SYSFONTINFO_DEFAULT : public FPDF_SYSFONTINFO { - IFX_SystemFontInfo* m_pFontInfo; + UnownedPtr m_pFontInfo; }; static void DefaultRelease(struct _FPDF_SYSFONTINFO* pThis) { auto* pDefault = static_cast(pThis); - // TODO(thestig): Should this be set to nullptr too? - delete pDefault->m_pFontInfo; + delete pDefault->m_pFontInfo.Release(); } static void DefaultEnumFonts(struct _FPDF_SYSFONTINFO* pThis, void* pMapper) { @@ -132,7 +148,7 @@ static void* DefaultMapFont(struct _FPDF_SYSFONTINFO* pThis, int* bExact) { auto* pDefault = static_cast(pThis); return pDefault->m_pFontInfo->MapFont(weight, !!bItalic, charset, - pitch_family, family, *bExact); + pitch_family, family); } void* DefaultGetFont(struct _FPDF_SYSFONTINFO* pThis, const char* family) { @@ -153,20 +169,22 @@ static unsigned long DefaultGetFaceName(struct _FPDF_SYSFONTINFO* pThis, void* hFont, char* buffer, unsigned long buf_size) { - CFX_ByteString name; + ByteString name; auto* pDefault = static_cast(pThis); - if (!pDefault->m_pFontInfo->GetFaceName(hFont, name)) + if (!pDefault->m_pFontInfo->GetFaceName(hFont, &name)) return 0; - if (name.GetLength() >= (long)buf_size) + if (name.GetLength() >= static_cast(buf_size)) return name.GetLength() + 1; - FXSYS_strcpy(buffer, name.c_str()); + + strncpy(buffer, name.c_str(), + (name.GetLength() + 1) * sizeof(ByteString::CharType)); return name.GetLength() + 1; } static int DefaultGetFontCharset(struct _FPDF_SYSFONTINFO* pThis, void* hFont) { int charset; auto* pDefault = static_cast(pThis); - if (!pDefault->m_pFontInfo->GetFontCharset(hFont, charset)) + if (!pDefault->m_pFontInfo->GetFontCharset(hFont, &charset)) return 0; return charset; } @@ -176,7 +194,7 @@ static void DefaultDeleteFont(struct _FPDF_SYSFONTINFO* pThis, void* hFont) { pDefault->m_pFontInfo->DeleteFont(hFont); } -DLLEXPORT FPDF_SYSFONTINFO* STDCALL FPDF_GetDefaultSystemFontInfo() { +FPDF_EXPORT FPDF_SYSFONTINFO* FPDF_CALLCONV FPDF_GetDefaultSystemFontInfo() { std::unique_ptr pFontInfo = IFX_SystemFontInfo::CreateDefault(nullptr); if (!pFontInfo) @@ -197,7 +215,7 @@ DLLEXPORT FPDF_SYSFONTINFO* STDCALL FPDF_GetDefaultSystemFontInfo() { return pFontInfoExt; } -DLLEXPORT void FPDF_FreeDefaultSystemFontInfo( - FPDF_SYSFONTINFO* pDefaultFontInfo) { +FPDF_EXPORT void FPDF_CALLCONV +FPDF_FreeDefaultSystemFontInfo(FPDF_SYSFONTINFO* pDefaultFontInfo) { FX_Free(static_cast(pDefaultFontInfo)); } diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp index 3427f4ea5854412ae4f2a0a9b0ab6f9e5ae9d660..565d90be4c7d2371a37b4ebcd7d0f4bd7726f697 100644 --- a/fpdfsdk/fpdf_transformpage.cpp +++ b/fpdfsdk/fpdf_transformpage.cpp @@ -6,6 +6,8 @@ #include "public/fpdf_transformpage.h" +#include +#include #include #include "core/fpdfapi/page/cpdf_clippath.h" @@ -23,7 +25,7 @@ namespace { void SetBoundingBox(CPDF_Page* page, - const CFX_ByteString& key, + const ByteString& key, float left, float bottom, float right, @@ -36,7 +38,7 @@ void SetBoundingBox(CPDF_Page* page, } bool GetBoundingBox(CPDF_Page* page, - const CFX_ByteString& key, + const ByteString& key, float* left, float* bottom, float* right, @@ -52,13 +54,17 @@ bool GetBoundingBox(CPDF_Page* page, return true; } +CPDF_Object* GetPageContent(CPDF_Dictionary* pPageDict) { + return pPageDict ? pPageDict->GetDirectObjectFor("Contents") : nullptr; +} + } // namespace -DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page, - float left, - float bottom, - float right, - float top) { +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetMediaBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return; @@ -66,11 +72,11 @@ DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page, SetBoundingBox(pPage, "MediaBox", left, bottom, right, top); } -DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page, - float left, - float bottom, - float right, - float top) { +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetCropBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return; @@ -78,96 +84,83 @@ DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page, SetBoundingBox(pPage, "CropBox", left, bottom, right, top); } -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page, - float* left, - float* bottom, - float* right, - float* top) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetMediaBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); return pPage && GetBoundingBox(pPage, "MediaBox", left, bottom, right, top); } -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetCropBox(FPDF_PAGE page, - float* left, - float* bottom, - float* right, - float* top) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetCropBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); return pPage && GetBoundingBox(pPage, "CropBox", left, bottom, right, top); } -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, - FS_MATRIX* matrix, - FS_RECTF* clipRect) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPage_TransFormWithClip(FPDF_PAGE page, + FS_MATRIX* matrix, + FS_RECTF* clipRect) { + if (!matrix && !clipRect) + return false; + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return false; - CFX_ByteTextBuf textBuf; + std::ostringstream textBuf; textBuf << "q "; - CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, - clipRect->top); - rect.Normalize(); - CFX_ByteString bsClipping; - bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, - rect.Width(), rect.Height()); - textBuf << bsClipping; - - CFX_ByteString bsMatix; - bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b, matrix->c, - matrix->d, matrix->e, matrix->f); - textBuf << bsMatix; - - CPDF_Dictionary* pPageDic = pPage->m_pFormDict; - CPDF_Object* pContentObj = - pPageDic ? pPageDic->GetObjectFor("Contents") : nullptr; - if (!pContentObj) - pContentObj = pPageDic ? pPageDic->GetArrayFor("Contents") : nullptr; + + if (clipRect) { + CFX_FloatRect rect = CFXFloatRectFromFSRECTF(*clipRect); + rect.Normalize(); + + textBuf << ByteString::Format("%f %f %f %f re W* n ", rect.left, + rect.bottom, rect.Width(), rect.Height()); + } + if (matrix) { + textBuf << ByteString::Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b, + matrix->c, matrix->d, matrix->e, matrix->f); + } + + CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get(); + CPDF_Object* pContentObj = GetPageContent(pPageDict); if (!pContentObj) return false; - CPDF_Document* pDoc = pPage->m_pDocument; + CPDF_Document* pDoc = pPage->m_pDocument.Get(); if (!pDoc) return false; CPDF_Stream* pStream = pDoc->NewIndirect( nullptr, 0, pdfium::MakeUnique(pDoc->GetByteStringPool())); - pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize()); + pStream->SetData(&textBuf); CPDF_Stream* pEndStream = pDoc->NewIndirect( nullptr, 0, pdfium::MakeUnique(pDoc->GetByteStringPool())); pEndStream->SetData((const uint8_t*)" Q", 2); - CPDF_Array* pContentArray = nullptr; - CPDF_Array* pArray = ToArray(pContentObj); - if (pArray) { - pContentArray = pArray; + if (CPDF_Array* pContentArray = ToArray(pContentObj)) { pContentArray->InsertNewAt(0, pDoc, pStream->GetObjNum()); pContentArray->AddNew(pDoc, pEndStream->GetObjNum()); - } else if (CPDF_Reference* pReference = ToReference(pContentObj)) { - CPDF_Object* pDirectObj = pReference->GetDirect(); - if (pDirectObj) { - CPDF_Array* pObjArray = pDirectObj->AsArray(); - if (pObjArray) { - pContentArray = pObjArray; - pContentArray->InsertNewAt(0, pDoc, - pStream->GetObjNum()); - pContentArray->AddNew(pDoc, pEndStream->GetObjNum()); - } else if (pDirectObj->IsStream()) { - pContentArray = pDoc->NewIndirect(); - pContentArray->AddNew(pDoc, pStream->GetObjNum()); - pContentArray->AddNew(pDoc, pDirectObj->GetObjNum()); - pContentArray->AddNew(pDoc, pEndStream->GetObjNum()); - pPageDic->SetNewFor("Contents", pDoc, - pContentArray->GetObjNum()); - } - } + } else if (pContentObj->IsStream() && !pContentObj->IsInline()) { + CPDF_Array* pContentArray = pDoc->NewIndirect(); + pContentArray->AddNew(pDoc, pStream->GetObjNum()); + pContentArray->AddNew(pDoc, pContentObj->GetObjNum()); + pContentArray->AddNew(pDoc, pEndStream->GetObjNum()); + pPageDict->SetNewFor("Contents", pDoc, + pContentArray->GetObjNum()); } // Need to transform the patterns as well. - CPDF_Dictionary* pRes = pPageDic->GetDictFor("Resources"); + CPDF_Dictionary* pRes = pPageDict->GetDictFor("Resources"); if (pRes) { CPDF_Dictionary* pPattenDict = pRes->GetDictFor("Pattern"); if (pPattenDict) { @@ -195,7 +188,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, return true; } -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object, double a, double b, @@ -206,8 +199,7 @@ FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object, CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object; if (!pPageObj) return; - CFX_Matrix matrix((FX_FLOAT)a, (FX_FLOAT)b, (FX_FLOAT)c, (FX_FLOAT)d, - (FX_FLOAT)e, (FX_FLOAT)f); + CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e, (float)f); // Special treatment to shading object, because the ClipPath for shading // object is already transformed. @@ -216,23 +208,24 @@ FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object, pPageObj->TransformGeneralState(matrix); } -DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left, - float bottom, - float right, - float top) { +FPDF_EXPORT FPDF_CLIPPATH FPDF_CALLCONV FPDF_CreateClipPath(float left, + float bottom, + float right, + float top) { CPDF_Path Path; Path.AppendRect(left, bottom, right, top); - CPDF_ClipPath* pNewClipPath = new CPDF_ClipPath(); + auto pNewClipPath = pdfium::MakeUnique(); pNewClipPath->AppendPath(Path, FXFILL_ALTERNATE, false); - return pNewClipPath; + return pNewClipPath.release(); // Caller takes ownership. } -DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath) { - delete (CPDF_ClipPath*)clipPath; +FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath) { + // Take ownership back from caller and destroy. + std::unique_ptr(static_cast(clipPath)); } -void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path) { +void OutputPath(std::ostringstream& buf, CPDF_Path path) { const CFX_PathData* pPathData = path.GetObject(); if (!pPathData) return; @@ -245,7 +238,7 @@ void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path) { return; } - CFX_ByteString temp; + ByteString temp; for (size_t i = 0; i < pPoints.size(); i++) { buf << pPoints[i].m_Point.x << " " << pPoints[i].m_Point.y; FXPT_TYPE point_type = pPoints[i].m_Type; @@ -269,69 +262,48 @@ void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path) { } } -DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page, - FPDF_CLIPPATH clipPath) { +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertClipPath(FPDF_PAGE page, + FPDF_CLIPPATH clipPath) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return; - CPDF_Dictionary* pPageDic = pPage->m_pFormDict; - CPDF_Object* pContentObj = - pPageDic ? pPageDic->GetObjectFor("Contents") : nullptr; - if (!pContentObj) - pContentObj = pPageDic ? pPageDic->GetArrayFor("Contents") : nullptr; + CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get(); + CPDF_Object* pContentObj = GetPageContent(pPageDict); if (!pContentObj) return; - CFX_ByteTextBuf strClip; + std::ostringstream strClip; CPDF_ClipPath* pClipPath = (CPDF_ClipPath*)clipPath; - uint32_t i; - for (i = 0; i < pClipPath->GetPathCount(); i++) { + for (size_t i = 0; i < pClipPath->GetPathCount(); ++i) { CPDF_Path path = pClipPath->GetPath(i); - int iClipType = pClipPath->GetClipType(i); if (path.GetPoints().empty()) { // Empty clipping (totally clipped out) strClip << "0 0 m W n "; } else { OutputPath(strClip, path); - if (iClipType == FXFILL_WINDING) + if (pClipPath->GetClipType(i) == FXFILL_WINDING) strClip << "W n\n"; else strClip << "W* n\n"; } } - CPDF_Document* pDoc = pPage->m_pDocument; + CPDF_Document* pDoc = pPage->m_pDocument.Get(); if (!pDoc) return; CPDF_Stream* pStream = pDoc->NewIndirect( nullptr, 0, pdfium::MakeUnique(pDoc->GetByteStringPool())); - pStream->SetData(strClip.GetBuffer(), strClip.GetSize()); + pStream->SetData(&strClip); - CPDF_Array* pArray = ToArray(pContentObj); - if (pArray) { + if (CPDF_Array* pArray = ToArray(pContentObj)) { pArray->InsertNewAt(0, pDoc, pStream->GetObjNum()); - return; - } - CPDF_Reference* pReference = ToReference(pContentObj); - if (!pReference) - return; - - CPDF_Object* pDirectObj = pReference->GetDirect(); - if (!pDirectObj) - return; - - CPDF_Array* pObjArray = pDirectObj->AsArray(); - if (pObjArray) { - pObjArray->InsertNewAt(0, pDoc, pStream->GetObjNum()); - return; - } - if (pDirectObj->IsStream()) { + } else if (pContentObj->IsStream() && !pContentObj->IsInline()) { CPDF_Array* pContentArray = pDoc->NewIndirect(); pContentArray->AddNew(pDoc, pStream->GetObjNum()); - pContentArray->AddNew(pDoc, pDirectObj->GetObjNum()); - pPageDic->SetNewFor("Contents", pDoc, - pContentArray->GetObjNum()); + pContentArray->AddNew(pDoc, pContentObj->GetObjNum()); + pPageDict->SetNewFor("Contents", pDoc, + pContentArray->GetObjNum()); } } diff --git a/fpdfsdk/fpdfannot.cpp b/fpdfsdk/fpdfannot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b0cb395749c2ab7da3f6bce119d50775664b21b --- /dev/null +++ b/fpdfsdk/fpdfannot.cpp @@ -0,0 +1,890 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "public/fpdf_annot.h" + +#include +#include + +#include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h" +#include "core/fpdfapi/page/cpdf_form.h" +#include "core/fpdfapi/page/cpdf_page.h" +#include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfdoc/cpdf_annot.h" +#include "core/fpdfdoc/cpdf_formfield.h" +#include "core/fpdfdoc/cpdf_interform.h" +#include "core/fpdfdoc/cpvt_generateap.h" +#include "core/fxge/cfx_color.h" +#include "fpdfsdk/fsdk_define.h" + +namespace { + +// These checks ensure the consistency of annotation subtype values across core/ +// and public. +static_assert(static_cast(CPDF_Annot::Subtype::UNKNOWN) == + FPDF_ANNOT_UNKNOWN, + "CPDF_Annot::UNKNOWN value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::TEXT) == FPDF_ANNOT_TEXT, + "CPDF_Annot::TEXT value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::LINK) == FPDF_ANNOT_LINK, + "CPDF_Annot::LINK value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::FREETEXT) == + FPDF_ANNOT_FREETEXT, + "CPDF_Annot::FREETEXT value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::LINE) == FPDF_ANNOT_LINE, + "CPDF_Annot::LINE value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::SQUARE) == + FPDF_ANNOT_SQUARE, + "CPDF_Annot::SQUARE value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::CIRCLE) == + FPDF_ANNOT_CIRCLE, + "CPDF_Annot::CIRCLE value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::POLYGON) == + FPDF_ANNOT_POLYGON, + "CPDF_Annot::POLYGON value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::POLYLINE) == + FPDF_ANNOT_POLYLINE, + "CPDF_Annot::POLYLINE value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::HIGHLIGHT) == + FPDF_ANNOT_HIGHLIGHT, + "CPDF_Annot::HIGHLIGHT value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::UNDERLINE) == + FPDF_ANNOT_UNDERLINE, + "CPDF_Annot::UNDERLINE value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::SQUIGGLY) == + FPDF_ANNOT_SQUIGGLY, + "CPDF_Annot::SQUIGGLY value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::STRIKEOUT) == + FPDF_ANNOT_STRIKEOUT, + "CPDF_Annot::STRIKEOUT value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::STAMP) == FPDF_ANNOT_STAMP, + "CPDF_Annot::STAMP value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::CARET) == FPDF_ANNOT_CARET, + "CPDF_Annot::CARET value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::INK) == FPDF_ANNOT_INK, + "CPDF_Annot::INK value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::POPUP) == FPDF_ANNOT_POPUP, + "CPDF_Annot::POPUP value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::FILEATTACHMENT) == + FPDF_ANNOT_FILEATTACHMENT, + "CPDF_Annot::FILEATTACHMENT value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::SOUND) == FPDF_ANNOT_SOUND, + "CPDF_Annot::SOUND value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::MOVIE) == FPDF_ANNOT_MOVIE, + "CPDF_Annot::MOVIE value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::WIDGET) == + FPDF_ANNOT_WIDGET, + "CPDF_Annot::WIDGET value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::SCREEN) == + FPDF_ANNOT_SCREEN, + "CPDF_Annot::SCREEN value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::PRINTERMARK) == + FPDF_ANNOT_PRINTERMARK, + "CPDF_Annot::PRINTERMARK value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::TRAPNET) == + FPDF_ANNOT_TRAPNET, + "CPDF_Annot::TRAPNET value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::WATERMARK) == + FPDF_ANNOT_WATERMARK, + "CPDF_Annot::WATERMARK value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::THREED) == + FPDF_ANNOT_THREED, + "CPDF_Annot::THREED value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::RICHMEDIA) == + FPDF_ANNOT_RICHMEDIA, + "CPDF_Annot::RICHMEDIA value mismatch"); +static_assert(static_cast(CPDF_Annot::Subtype::XFAWIDGET) == + FPDF_ANNOT_XFAWIDGET, + "CPDF_Annot::XFAWIDGET value mismatch"); + +// These checks ensure the consistency of annotation appearance mode values +// across core/ and public. +static_assert(static_cast(CPDF_Annot::AppearanceMode::Normal) == + FPDF_ANNOT_APPEARANCEMODE_NORMAL, + "CPDF_Annot::AppearanceMode::Normal value mismatch"); +static_assert(static_cast(CPDF_Annot::AppearanceMode::Rollover) == + FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, + "CPDF_Annot::AppearanceMode::Rollover value mismatch"); +static_assert(static_cast(CPDF_Annot::AppearanceMode::Down) == + FPDF_ANNOT_APPEARANCEMODE_DOWN, + "CPDF_Annot::AppearanceMode::Down value mismatch"); + +// These checks ensure the consistency of dictionary value types across core/ +// and public/. +static_assert(static_cast(CPDF_Object::Type::BOOLEAN) == + FPDF_OBJECT_BOOLEAN, + "CPDF_Object::BOOLEAN value mismatch"); +static_assert(static_cast(CPDF_Object::Type::NUMBER) == FPDF_OBJECT_NUMBER, + "CPDF_Object::NUMBER value mismatch"); +static_assert(static_cast(CPDF_Object::Type::STRING) == FPDF_OBJECT_STRING, + "CPDF_Object::STRING value mismatch"); +static_assert(static_cast(CPDF_Object::Type::NAME) == FPDF_OBJECT_NAME, + "CPDF_Object::NAME value mismatch"); +static_assert(static_cast(CPDF_Object::Type::ARRAY) == FPDF_OBJECT_ARRAY, + "CPDF_Object::ARRAY value mismatch"); +static_assert(static_cast(CPDF_Object::Type::DICTIONARY) == + FPDF_OBJECT_DICTIONARY, + "CPDF_Object::DICTIONARY value mismatch"); +static_assert(static_cast(CPDF_Object::Type::STREAM) == FPDF_OBJECT_STREAM, + "CPDF_Object::STREAM value mismatch"); +static_assert(static_cast(CPDF_Object::Type::NULLOBJ) == + FPDF_OBJECT_NULLOBJ, + "CPDF_Object::NULLOBJ value mismatch"); +static_assert(static_cast(CPDF_Object::Type::REFERENCE) == + FPDF_OBJECT_REFERENCE, + "CPDF_Object::REFERENCE value mismatch"); + +class CPDF_AnnotContext { + public: + CPDF_AnnotContext(CPDF_Dictionary* pAnnotDict, + CPDF_Page* pPage, + CPDF_Stream* pStream) + : m_pAnnotDict(pAnnotDict), m_pPage(pPage) { + SetForm(pStream); + } + ~CPDF_AnnotContext() {} + + bool HasForm() const { return !!m_pAnnotForm; } + + void SetForm(CPDF_Stream* pStream) { + if (!pStream) + return; + + // Reset the annotation matrix to be the identity matrix, since the + // appearance stream already takes matrix into account. + pStream->GetDict()->SetMatrixFor("Matrix", CFX_Matrix()); + + m_pAnnotForm = pdfium::MakeUnique( + m_pPage->m_pDocument.Get(), m_pPage->m_pResources.Get(), pStream); + m_pAnnotForm->ParseContent(); + } + + CPDF_Form* GetForm() const { return m_pAnnotForm.get(); } + CPDF_Dictionary* GetAnnotDict() const { return m_pAnnotDict.Get(); } + CPDF_Page* GetPage() const { return m_pPage.Get(); } + + private: + std::unique_ptr m_pAnnotForm; + UnownedPtr m_pAnnotDict; + UnownedPtr m_pPage; +}; + +CPDF_AnnotContext* CPDFAnnotContextFromFPDFAnnotation(FPDF_ANNOTATION annot) { + return static_cast(annot); +} + +bool HasAPStream(const CPDF_Dictionary* pAnnotDict) { + return !!FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); +} + +void UpdateContentStream(CPDF_Form* pForm, CPDF_Stream* pStream) { + ASSERT(pForm); + ASSERT(pStream); + + CPDF_PageContentGenerator generator(pForm); + std::ostringstream buf; + generator.ProcessPageObjects(&buf); + pStream->SetDataAndRemoveFilter(&buf); +} + +} // namespace + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) { + // The supported subtypes must also be communicated in the user doc. + return subtype == FPDF_ANNOT_CIRCLE || subtype == FPDF_ANNOT_HIGHLIGHT || + subtype == FPDF_ANNOT_INK || subtype == FPDF_ANNOT_POPUP || + subtype == FPDF_ANNOT_SQUARE || subtype == FPDF_ANNOT_SQUIGGLY || + subtype == FPDF_ANNOT_STAMP || subtype == FPDF_ANNOT_STRIKEOUT || + subtype == FPDF_ANNOT_TEXT || subtype == FPDF_ANNOT_UNDERLINE; +} + +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV +FPDFPage_CreateAnnot(FPDF_PAGE page, FPDF_ANNOTATION_SUBTYPE subtype) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage || !FPDFAnnot_IsSupportedSubtype(subtype)) + return nullptr; + + auto pDict = pdfium::MakeUnique( + pPage->m_pDocument->GetByteStringPool()); + pDict->SetNewFor("Type", "Annot"); + pDict->SetNewFor("Subtype", + CPDF_Annot::AnnotSubtypeToString( + static_cast(subtype))); + auto pNewAnnot = + pdfium::MakeUnique(pDict.get(), pPage, nullptr); + + CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots"); + if (!pAnnotList) + pAnnotList = pPage->m_pFormDict->SetNewFor("Annots"); + + pAnnotList->Add(std::move(pDict)); + return pNewAnnot.release(); +} + +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotCount(FPDF_PAGE page) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage || !pPage->m_pFormDict) + return 0; + + CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots"); + return pAnnots ? pAnnots->GetCount() : 0; +} + +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV FPDFPage_GetAnnot(FPDF_PAGE page, + int index) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage || !pPage->m_pFormDict || index < 0) + return nullptr; + + CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots"); + if (!pAnnots || static_cast(index) >= pAnnots->GetCount()) + return nullptr; + + CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(index)); + auto pNewAnnot = pdfium::MakeUnique(pDict, pPage, nullptr); + return pNewAnnot.release(); +} + +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotIndex(FPDF_PAGE page, + FPDF_ANNOTATION annot) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + if (!pPage || !pPage->m_pFormDict || !pAnnot || !pAnnot->GetAnnotDict()) + return -1; + + CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots"); + if (!pAnnots) + return -1; + + CPDF_Dictionary* pDict = pAnnot->GetAnnotDict(); + auto it = + std::find_if(pAnnots->begin(), pAnnots->end(), + [pDict](const std::unique_ptr& candidate) { + return candidate->GetDirect() == pDict; + }); + + if (it == pAnnots->end()) + return -1; + + return it - pAnnots->begin(); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_CloseAnnot(FPDF_ANNOTATION annot) { + delete CPDFAnnotContextFromFPDFAnnotation(annot); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_RemoveAnnot(FPDF_PAGE page, + int index) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage || !pPage->m_pFormDict || index < 0) + return false; + + CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots"); + if (!pAnnots || static_cast(index) >= pAnnots->GetCount()) + return false; + + pAnnots->RemoveAt(index); + return true; +} + +FPDF_EXPORT FPDF_ANNOTATION_SUBTYPE FPDF_CALLCONV +FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot) { + if (!annot) + return FPDF_ANNOT_UNKNOWN; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return FPDF_ANNOT_UNKNOWN; + + return static_cast( + CPDF_Annot::StringToAnnotSubtype(pAnnotDict->GetStringFor("Subtype"))); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_IsObjectSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) { + // The supported subtypes must also be communicated in the user doc. + return subtype == FPDF_ANNOT_INK || subtype == FPDF_ANNOT_STAMP; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_UpdateObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) { + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj); + if (!pAnnot || !pAnnot->GetAnnotDict() || !pAnnot->HasForm() || !pObj) + return false; + + // Check that the annotation type is supported by this method. + if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot))) + return false; + + // Check that the annotation already has an appearance stream, since an + // existing object is to be updated. + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(pAnnot->GetAnnotDict(), + CPDF_Annot::AppearanceMode::Normal); + if (!pStream) + return false; + + // Check that the object is already in this annotation's object list. + CPDF_Form* pForm = pAnnot->GetForm(); + CPDF_PageObjectList* pObjList = pForm->GetPageObjectList(); + auto it = + std::find_if(pObjList->begin(), pObjList->end(), + [pObj](const std::unique_ptr& candidate) { + return candidate.get() == pObj; + }); + if (it == pObjList->end()) + return false; + + // Update the content stream data in the annotation's AP stream. + UpdateContentStream(pForm, pStream); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_AppendObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) { + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj); + if (!pAnnot || !pObj) + return false; + + CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); + CPDF_Page* pPage = pAnnot->GetPage(); + if (!pAnnotDict || !pPage) + return false; + + // Check that the annotation type is supported by this method. + if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot))) + return false; + + // If the annotation does not have an AP stream yet, generate and set it. + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(pAnnot->GetAnnotDict(), + CPDF_Annot::AppearanceMode::Normal); + if (!pStream) { + CPVT_GenerateAP::GenerateEmptyAP(pPage->m_pDocument.Get(), pAnnotDict); + pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (!pStream) + return false; + } + + // Get the annotation's corresponding form object for parsing its AP stream. + if (!pAnnot->HasForm()) + pAnnot->SetForm(pStream); + + // Check that the object did not come from the same annotation. If this check + // succeeds, then it is assumed that the object came from + // FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj(). + // Note that an object that came from a different annotation must not be + // passed here, since an object cannot belong to more than one annotation. + CPDF_Form* pForm = pAnnot->GetForm(); + CPDF_PageObjectList* pObjList = pForm->GetPageObjectList(); + auto it = + std::find_if(pObjList->begin(), pObjList->end(), + [pObj](const std::unique_ptr& candidate) { + return candidate.get() == pObj; + }); + if (it != pObjList->end()) + return false; + + // Append the object to the object list. + std::unique_ptr pPageObjHolder(pObj); + pObjList->push_back(std::move(pPageObjHolder)); + + // Set the content stream data in the annotation's AP stream. + UpdateContentStream(pForm, pStream); + return true; +} + +FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetObjectCount(FPDF_ANNOTATION annot) { + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + if (!pAnnot || !pAnnot->GetAnnotDict()) + return 0; + + if (!pAnnot->HasForm()) { + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP( + pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); + if (!pStream) + return 0; + + pAnnot->SetForm(pStream); + } + return pdfium::CollectionSize(*pAnnot->GetForm()->GetPageObjectList()); +} + +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFAnnot_GetObject(FPDF_ANNOTATION annot, int index) { + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + if (!pAnnot || !pAnnot->GetAnnotDict() || index < 0) + return nullptr; + + if (!pAnnot->HasForm()) { + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP( + pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal); + if (!pStream) + return nullptr; + + pAnnot->SetForm(pStream); + } + + return pAnnot->GetForm()->GetPageObjectList()->GetPageObjectByIndex(index); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_RemoveObject(FPDF_ANNOTATION annot, int index) { + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + if (!pAnnot || !pAnnot->GetAnnotDict() || !pAnnot->HasForm() || index < 0) + return false; + + // Check that the annotation type is supported by this method. + if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot))) + return false; + + // Check that the annotation already has an appearance stream, since an + // existing object is to be deleted. + CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(pAnnot->GetAnnotDict(), + CPDF_Annot::AppearanceMode::Normal); + if (!pStream) + return false; + + CPDF_PageObjectList* pObjList = pAnnot->GetForm()->GetPageObjectList(); + if (static_cast(index) >= pObjList->size()) + return false; + + pObjList->erase(pObjList->begin() + index); + UpdateContentStream(pAnnot->GetForm(), pStream); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetColor(FPDF_ANNOTATION annot, + FPDFANNOT_COLORTYPE type, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + if (!annot || R > 255 || G > 255 || B > 255 || A > 255) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + // For annotations with their appearance streams already defined, the path + // stream's own color definitions take priority over the annotation color + // definitions set by this method, hence this method will simply fail. + if (HasAPStream(pAnnotDict)) + return false; + + // Set the opacity of the annotation. + pAnnotDict->SetNewFor("CA", A / 255.f); + + // Set the color of the annotation. + ByteString key = type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C"; + CPDF_Array* pColor = pAnnotDict->GetArrayFor(key); + if (pColor) + pColor->Clear(); + else + pColor = pAnnotDict->SetNewFor(key); + + pColor->AddNew(R / 255.f); + pColor->AddNew(G / 255.f); + pColor->AddNew(B / 255.f); + + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetColor(FPDF_ANNOTATION annot, + FPDFANNOT_COLORTYPE type, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A) { + if (!annot || !R || !G || !B || !A) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + // For annotations with their appearance streams already defined, the path + // stream's own color definitions take priority over the annotation color + // definitions retrieved by this method, hence this method will simply fail. + if (HasAPStream(pAnnotDict)) + return false; + + CPDF_Array* pColor = pAnnotDict->GetArrayFor( + type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C"); + *A = + (pAnnotDict->KeyExist("CA") ? pAnnotDict->GetNumberFor("CA") : 1) * 255.f; + if (!pColor) { + // Use default color. The default colors must be consistent with the ones + // used to generate AP. See calls to GetColorStringWithDefault() in + // CPVT_GenerateAP::Generate*AP(). + if (pAnnotDict->GetStringFor("Subtype") == "Highlight") { + *R = 255; + *G = 255; + *B = 0; + } else { + *R = 0; + *G = 0; + *B = 0; + } + return true; + } + + CFX_Color color = CFX_Color::ParseColor(*pColor); + switch (color.nColorType) { + case CFX_Color::kRGB: + *R = color.fColor1 * 255.f; + *G = color.fColor2 * 255.f; + *B = color.fColor3 * 255.f; + break; + case CFX_Color::kGray: + *R = 255.f * color.fColor1; + *G = 255.f * color.fColor1; + *B = 255.f * color.fColor1; + break; + case CFX_Color::kCMYK: + *R = 255.f * (1 - color.fColor1) * (1 - color.fColor4); + *G = 255.f * (1 - color.fColor2) * (1 - color.fColor4); + *B = 255.f * (1 - color.fColor3) * (1 - color.fColor4); + break; + case CFX_Color::kTransparent: + *R = 0; + *G = 0; + *B = 0; + break; + } + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot) { + if (!annot) + return false; + + FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot); + return subtype == FPDF_ANNOT_LINK || subtype == FPDF_ANNOT_HIGHLIGHT || + subtype == FPDF_ANNOT_UNDERLINE || subtype == FPDF_ANNOT_SQUIGGLY || + subtype == FPDF_ANNOT_STRIKEOUT; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot, + const FS_QUADPOINTSF* quadPoints) { + if (!annot || !quadPoints || !FPDFAnnot_HasAttachmentPoints(annot)) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + // Update the "QuadPoints" entry in the annotation dictionary. + CPDF_Array* pQuadPoints = pAnnotDict->GetArrayFor("QuadPoints"); + if (pQuadPoints) + pQuadPoints->Clear(); + else + pQuadPoints = pAnnotDict->SetNewFor("QuadPoints"); + + pQuadPoints->AddNew(quadPoints->x1); + pQuadPoints->AddNew(quadPoints->y1); + pQuadPoints->AddNew(quadPoints->x2); + pQuadPoints->AddNew(quadPoints->y2); + pQuadPoints->AddNew(quadPoints->x3); + pQuadPoints->AddNew(quadPoints->y3); + pQuadPoints->AddNew(quadPoints->x4); + pQuadPoints->AddNew(quadPoints->y4); + + // If the annotation's appearance stream is defined, and the new quadpoints + // defines a bigger bounding box than the appearance stream currently + // specifies, then update the "BBox" entry in the AP dictionary too, since it + // comes from annotation dictionary's "QuadPoints" entry. + CPDF_Stream* pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (pStream) { + CFX_FloatRect newRect = CPDF_Annot::RectFromQuadPoints(pAnnotDict); + if (newRect.Contains(pStream->GetDict()->GetRectFor("BBox"))) + pStream->GetDict()->SetRectFor("BBox", newRect); + } + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot, + FS_QUADPOINTSF* quadPoints) { + if (!annot || !FPDFAnnot_HasAttachmentPoints(annot) || !quadPoints) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + CPDF_Array* pArray = pAnnotDict->GetArrayFor("QuadPoints"); + if (!pArray) + return false; + + quadPoints->x1 = pArray->GetNumberAt(0); + quadPoints->y1 = pArray->GetNumberAt(1); + quadPoints->x2 = pArray->GetNumberAt(2); + quadPoints->y2 = pArray->GetNumberAt(3); + quadPoints->x3 = pArray->GetNumberAt(4); + quadPoints->y3 = pArray->GetNumberAt(5); + quadPoints->x4 = pArray->GetNumberAt(6); + quadPoints->y4 = pArray->GetNumberAt(7); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetRect(FPDF_ANNOTATION annot, + const FS_RECTF* rect) { + if (!annot || !rect) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + CFX_FloatRect newRect = CFXFloatRectFromFSRECTF(*rect); + + // Update the "Rect" entry in the annotation dictionary. + pAnnotDict->SetRectFor("Rect", newRect); + + // If the annotation's appearance stream is defined, the annotation is of a + // type that does not have quadpoints, and the new rectangle is bigger than + // the current bounding box, then update the "BBox" entry in the AP + // dictionary too, since its "BBox" entry comes from annotation dictionary's + // "Rect" entry. + if (FPDFAnnot_HasAttachmentPoints(annot)) + return true; + + CPDF_Stream* pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (pStream && newRect.Contains(pStream->GetDict()->GetRectFor("BBox"))) + pStream->GetDict()->SetRectFor("BBox", newRect); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot, + FS_RECTF* rect) { + if (!annot || !rect) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"), rect); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot, + FPDF_BYTESTRING key) { + if (!annot) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + return pAnnotDict->KeyExist(key); +} + +FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV +FPDFAnnot_GetValueType(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) { + if (!FPDFAnnot_HasKey(annot, key)) + return FPDF_OBJECT_UNKNOWN; + + auto* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + CPDF_Object* pObj = pAnnot->GetAnnotDict()->GetObjectFor(key); + return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_SetStringValue(FPDF_ANNOTATION annot, + FPDF_BYTESTRING key, + FPDF_WIDESTRING value) { + if (!annot) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + pAnnotDict->SetNewFor( + key, CFXByteStringFromFPDFWideString(value), false); + return true; +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAnnot_GetStringValue(FPDF_ANNOTATION annot, + FPDF_BYTESTRING key, + void* buffer, + unsigned long buflen) { + if (!annot) + return 0; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return 0; + + return Utf16EncodeMaybeCopyAndReturnLength(pAnnotDict->GetUnicodeTextFor(key), + buffer, buflen); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_SetAP(FPDF_ANNOTATION annot, + FPDF_ANNOT_APPEARANCEMODE appearanceMode, + FPDF_WIDESTRING value) { + if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT) + return false; + + if (!annot) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + constexpr const char* modeKeyForMode[] = {"N", "R", "D"}; + static_assert(FX_ArraySize(modeKeyForMode) == FPDF_ANNOT_APPEARANCEMODE_COUNT, + "length of modeKeyForMode should be equal to " + "FPDF_ANNOT_APPEARANCEMODE_COUNT"); + const char* modeKey = modeKeyForMode[appearanceMode]; + + CPDF_Dictionary* pApDict = pAnnotDict->GetDictFor("AP"); + + // If value is null, we're in remove mode. Otherwise, we're in add/update + // mode. + if (value) { + if (!pApDict) + pApDict = pAnnotDict->SetNewFor("AP"); + + ByteString newValue = CFXByteStringFromFPDFWideString(value); + auto pNewApStream = pdfium::MakeUnique(); + pNewApStream->SetData(newValue.raw_str(), newValue.GetLength()); + pApDict->SetFor(modeKey, std::move(pNewApStream)); + } else { + if (pApDict) { + if (appearanceMode == FPDF_ANNOT_APPEARANCEMODE_NORMAL) + pAnnotDict->RemoveFor("AP"); + else + pApDict->RemoveFor(modeKey); + } + } + + return true; +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAnnot_GetAP(FPDF_ANNOTATION annot, + FPDF_ANNOT_APPEARANCEMODE appearanceMode, + void* buffer, + unsigned long buflen) { + if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT) + return 0; + + if (!annot) + return 0; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return 0; + + CPDF_Annot::AppearanceMode mode = + static_cast(appearanceMode); + + CPDF_Stream* pStream = FPDFDOC_GetAnnotAPNoFallback(pAnnotDict, mode); + return Utf16EncodeMaybeCopyAndReturnLength( + pStream ? pStream->GetUnicodeText() : L"", buffer, buflen); +} + +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV +FPDFAnnot_GetLinkedAnnot(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) { + CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot); + if (!pAnnot || !pAnnot->GetAnnotDict()) + return nullptr; + + CPDF_Dictionary* pLinkedDict = pAnnot->GetAnnotDict()->GetDictFor(key); + if (!pLinkedDict || pLinkedDict->GetStringFor("Type") != "Annot") + return nullptr; + + auto pLinkedAnnot = pdfium::MakeUnique( + pLinkedDict, pAnnot->GetPage(), nullptr); + return pLinkedAnnot.release(); +} + +FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetFlags(FPDF_ANNOTATION annot) { + if (!annot) + return FPDF_ANNOT_FLAG_NONE; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + return pAnnotDict ? pAnnotDict->GetIntegerFor("F") : FPDF_ANNOT_FLAG_NONE; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetFlags(FPDF_ANNOTATION annot, + int flags) { + if (!annot) + return false; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return false; + + pAnnotDict->SetNewFor("F", flags); + return true; +} + +FPDF_EXPORT int FPDF_CALLCONV +FPDFAnnot_GetFormFieldFlags(FPDF_PAGE page, FPDF_ANNOTATION annot) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage || !annot) + return FPDF_FORMFLAG_NONE; + + CPDF_Dictionary* pAnnotDict = + CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict(); + if (!pAnnotDict) + return FPDF_FORMFLAG_NONE; + + CPDF_InterForm interform(pPage->m_pDocument.Get()); + CPDF_FormField* pFormField = interform.GetFieldByDict(pAnnotDict); + return pFormField ? pFormField->GetFieldFlags() : FPDF_FORMFLAG_NONE; +} + +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV +FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!hHandle || !pPage) + return nullptr; + + CPDF_InterForm interform(pPage->m_pDocument.Get()); + int annot_index = -1; + CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint( + pPage, CFX_PointF(static_cast(page_x), static_cast(page_y)), + &annot_index); + if (!pFormCtrl || annot_index == -1) + return nullptr; + return FPDFPage_GetAnnot(page, annot_index); +} diff --git a/fpdfsdk/fpdfannot_embeddertest.cpp b/fpdfsdk/fpdfannot_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b38bd87752e0b7f4ed946bbd958edebd1dd5e10c --- /dev/null +++ b/fpdfsdk/fpdfannot_embeddertest.cpp @@ -0,0 +1,1267 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "public/fpdf_annot.h" +#include "public/fpdf_edit.h" +#include "public/fpdfview.h" +#include "testing/embedder_test.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" +#include "testing/gtest/include/gtest/gtest.h" + +static constexpr char kContentsKey[] = "Contents"; + +class FPDFAnnotEmbeddertest : public EmbedderTest {}; + +std::wstring BufferToWString(const std::vector& buf) { + return GetPlatformWString(reinterpret_cast(buf.data())); +} + +std::string BufferToString(const std::vector& buf) { + return GetPlatformString(reinterpret_cast(buf.data())); +} + +TEST_F(FPDFAnnotEmbeddertest, RenderAnnotWithOnlyRolloverAP) { + // Open a file with one annotation and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // This annotation has a malformed appearance stream, which does not have its + // normal appearance defined, only its rollover appearance. In this case, its + // normal appearance should be generated, allowing the highlight annotation to + // still display. + FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle(), FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e"); + FPDFBitmap_Destroy(bitmap); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, ExtractHighlightLongContent) { + // Open a file with one annotation and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Check that there is a total of 1 annotation on its first page. + EXPECT_EQ(1, FPDFPage_GetAnnotCount(page)); + + // Check that the annotation is of type "highlight". + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot)); + + // Check that the annotation color is yellow. + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + EXPECT_TRUE( + FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A)); + EXPECT_EQ(255u, R); + EXPECT_EQ(255u, G); + EXPECT_EQ(0u, B); + EXPECT_EQ(255u, A); + + // Check that the author is correct. + static constexpr char kAuthorKey[] = "T"; + EXPECT_EQ(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(annot, kAuthorKey)); + unsigned long len = FPDFAnnot_GetStringValue(annot, kAuthorKey, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(28u, FPDFAnnot_GetStringValue(annot, kAuthorKey, buf.data(), len)); + EXPECT_STREQ(L"Jae Hyun Park", BufferToWString(buf).c_str()); + + // Check that the content is correct. + EXPECT_EQ(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(annot, kContentsKey)); + len = FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(2690u, + FPDFAnnot_GetStringValue(annot, kContentsKey, buf.data(), len)); + const wchar_t contents[] = + L"This is a note for that highlight annotation. Very long highlight " + "annotation. Long long long Long long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long longLong long longLong long longLong long longLong long " + "longLong long long. END"; + EXPECT_STREQ(contents, BufferToWString(buf).c_str()); + + // Check that the quadpoints are correct. + FS_QUADPOINTSF quadpoints; + ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &quadpoints)); + EXPECT_EQ(115.802643f, quadpoints.x1); + EXPECT_EQ(718.913940f, quadpoints.y1); + EXPECT_EQ(157.211182f, quadpoints.x4); + EXPECT_EQ(706.264465f, quadpoints.y4); + + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, ExtractInkMultiple) { + // Open a file with three annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Check that there is a total of 3 annotation on its first page. + EXPECT_EQ(3, FPDFPage_GetAnnotCount(page)); + + // Check that the third annotation is of type "ink". + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(annot); + EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot)); + + // Check that the annotation color is blue with opacity. + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + EXPECT_TRUE( + FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A)); + EXPECT_EQ(0u, R); + EXPECT_EQ(0u, G); + EXPECT_EQ(255u, B); + EXPECT_EQ(76u, A); + + // Check that there is no content. + EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0)); + + // Check that the rectange coordinates are correct. + // Note that upon rendering, the rectangle coordinates will be adjusted. + FS_RECTF rect; + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_EQ(351.820404f, rect.left); + EXPECT_EQ(583.830688f, rect.bottom); + EXPECT_EQ(475.336090f, rect.right); + EXPECT_EQ(681.535034f, rect.top); + + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, AddIllegalSubtypeAnnotation) { + // Open a file with one annotation and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Add an annotation with an illegal subtype. + ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1)); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, AddFirstTextAnnotation) { + // Open a file with no annotation and load its first page. + ASSERT_TRUE(OpenDocument("hello_world.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(0, FPDFPage_GetAnnotCount(page)); + + // Add a text annotation to the page. + FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT); + ASSERT_TRUE(annot); + + // Check that there is now 1 annotations on this page. + EXPECT_EQ(1, FPDFPage_GetAnnotCount(page)); + + // Check that the subtype of the annotation is correct. + EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot)); + FPDFPage_CloseAnnot(annot); + + annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot)); + + // Set the color of the annotation. + ASSERT_TRUE( + FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204)); + // Check that the color has been set correctly. + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + EXPECT_TRUE( + FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A)); + EXPECT_EQ(51u, R); + EXPECT_EQ(102u, G); + EXPECT_EQ(153u, B); + EXPECT_EQ(204u, A); + + // Change the color of the annotation. + ASSERT_TRUE( + FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 204, 153, 102, 51)); + // Check that the color has been set correctly. + EXPECT_TRUE( + FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A)); + EXPECT_EQ(204u, R); + EXPECT_EQ(153u, G); + EXPECT_EQ(102u, B); + EXPECT_EQ(51u, A); + + // Set the annotation rectangle. + FS_RECTF rect; + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_EQ(0.f, rect.left); + EXPECT_EQ(0.f, rect.right); + rect.left = 35; + rect.bottom = 150; + rect.right = 53; + rect.top = 165; + ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect)); + // Check that the annotation rectangle has been set correctly. + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_EQ(35.f, rect.left); + EXPECT_EQ(150.f, rect.bottom); + EXPECT_EQ(53.f, rect.right); + EXPECT_EQ(165.f, rect.top); + + // Set the content of the annotation. + static constexpr wchar_t contents[] = L"Hello! This is a customized content."; + std::unique_ptr text = + GetFPDFWideString(contents); + ASSERT_TRUE(FPDFAnnot_SetStringValue(annot, kContentsKey, text.get())); + // Check that the content has been set correctly. + unsigned long len = FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(74u, + FPDFAnnot_GetStringValue(annot, kContentsKey, buf.data(), len)); + EXPECT_STREQ(contents, BufferToWString(buf).c_str()); + + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, AddAndSaveUnderlineAnnotation) { + // Open a file with one annotation and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Check that there is a total of one annotation on its first page, and verify + // its quadpoints. + EXPECT_EQ(1, FPDFPage_GetAnnotCount(page)); + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + FS_QUADPOINTSF quadpoints; + ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &quadpoints)); + EXPECT_EQ(115.802643f, quadpoints.x1); + EXPECT_EQ(718.913940f, quadpoints.y1); + EXPECT_EQ(157.211182f, quadpoints.x4); + EXPECT_EQ(706.264465f, quadpoints.y4); + FPDFPage_CloseAnnot(annot); + + // Add an underline annotation to the page and set its quadpoints. + annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE); + ASSERT_TRUE(annot); + quadpoints.x1 = 140.802643f; + quadpoints.x3 = 140.802643f; + ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints)); + FPDFPage_CloseAnnot(annot); + + // Save the document, closing the page and document. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + // Open the saved document. + const char md5[] = "dba153419f67b7c0c0e3d22d3e8910d5"; + + OpenSavedDocument(); + page = LoadSavedPage(0); + VerifySavedRendering(page, 612, 792, md5); + + // Check that the saved document has 2 annotations on the first page + EXPECT_EQ(2, FPDFPage_GetAnnotCount(page)); + + // Check that the second annotation is an underline annotation and verify + // its quadpoints. + FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(page, 1); + ASSERT_TRUE(new_annot); + EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot)); + FS_QUADPOINTSF new_quadpoints; + ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(new_annot, &new_quadpoints)); + EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f); + EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f); + EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f); + EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f); + + FPDFPage_CloseAnnot(new_annot); + + CloseSavedPage(page); + CloseSavedDocument(); +} + +TEST_F(FPDFAnnotEmbeddertest, ModifyRectQuadpointsWithAP) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_original[] = "63af8432fab95a67cdebb7cd0e514941"; + const char md5_modified_highlight[] = "aec26075011349dec9bace891856b5f2"; + const char md5_modified_square[] = "057f57a32be95975775e5ec513fdcb56"; +#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const char md5_original[] = "0e27376094f11490f74c65f3dc3a42c5"; + const char md5_modified_highlight[] = "66f3caef3a7d488a4fa1ad37fc06310e"; + const char md5_modified_square[] = "a456dad0bc6801ee2d6408a4394af563"; +#else + const char md5_original[] = "0e27376094f11490f74c65f3dc3a42c5"; + const char md5_modified_highlight[] = "66f3caef3a7d488a4fa1ad37fc06310e"; + const char md5_modified_square[] = "a456dad0bc6801ee2d6408a4394af563"; +#endif + + // Open a file with four annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(4, FPDFPage_GetAnnotCount(page)); + + // Check that the original file renders correctly. + FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, md5_original); + FPDFBitmap_Destroy(bitmap); + + // Retrieve the highlight annotation which has its AP stream already defined. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot)); + + // Check that color cannot be set when an AP stream is defined already. + EXPECT_FALSE( + FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204)); + + // Verify its attachment points. + FS_QUADPOINTSF quadpoints; + ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &quadpoints)); + EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f); + EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f); + EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f); + EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f); + + // Check that updating the attachment points would succeed. + quadpoints.x1 -= 50.f; + quadpoints.x2 -= 50.f; + quadpoints.x3 -= 50.f; + quadpoints.x4 -= 50.f; + ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints)); + FS_QUADPOINTSF new_quadpoints; + ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &new_quadpoints)); + EXPECT_EQ(quadpoints.x1, new_quadpoints.x1); + EXPECT_EQ(quadpoints.y1, new_quadpoints.y1); + EXPECT_EQ(quadpoints.x4, new_quadpoints.x4); + EXPECT_EQ(quadpoints.y4, new_quadpoints.y4); + + // Check that updating quadpoints does not change the annotation's position. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, md5_original); + FPDFBitmap_Destroy(bitmap); + + // Verify its annotation rectangle. + FS_RECTF rect; + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_NEAR(67.7299f, rect.left, 0.001f); + EXPECT_NEAR(704.296f, rect.bottom, 0.001f); + EXPECT_NEAR(136.325f, rect.right, 0.001f); + EXPECT_NEAR(721.292f, rect.top, 0.001f); + + // Check that updating the rectangle would succeed. + rect.left -= 60.f; + rect.right -= 60.f; + ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect)); + FS_RECTF new_rect; + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect)); + EXPECT_EQ(rect.right, new_rect.right); + FPDFPage_CloseAnnot(annot); + + // Check that updating the rectangle changes the annotation's position. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, md5_modified_highlight); + FPDFBitmap_Destroy(bitmap); + + // Retrieve the square annotation which has its AP stream already defined. + annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(annot); + EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot)); + + // Check that updating the rectangle would succeed. + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + rect.left += 70.f; + rect.right += 70.f; + ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect)); + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect)); + EXPECT_EQ(rect.right, new_rect.right); + + // Check that updating the rectangle changes the square annotation's position. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, md5_modified_square); + FPDFBitmap_Destroy(bitmap); + + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, RemoveAnnotation) { + // Open a file with 3 annotations on its first page. + ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(3, FPDFPage_GetAnnotCount(page)); + + // Check that the annotations have the expected rectangle coordinates. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + FS_RECTF rect; + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_NEAR(86.1971f, rect.left, 0.001f); + FPDFPage_CloseAnnot(annot); + + annot = FPDFPage_GetAnnot(page, 1); + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_NEAR(149.8127f, rect.left, 0.001f); + FPDFPage_CloseAnnot(annot); + + annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_NEAR(351.8204f, rect.left, 0.001f); + FPDFPage_CloseAnnot(annot); + + // Check that nothing happens when attempting to remove an annotation with an + // out-of-bound index. + EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4)); + EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1)); + EXPECT_EQ(3, FPDFPage_GetAnnotCount(page)); + + // Remove the second annotation. + EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1)); + EXPECT_EQ(2, FPDFPage_GetAnnotCount(page)); + EXPECT_FALSE(FPDFPage_GetAnnot(page, 2)); + + // Save the document, closing the page and document. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + // TODO(npm): VerifySavedRendering changes annot rect dimensions by 1?? + // Open the saved document. + std::string new_file = GetString(); + FPDF_FILEACCESS file_access; + memset(&file_access, 0, sizeof(file_access)); + file_access.m_FileLen = new_file.size(); + file_access.m_GetBlock = GetBlockFromString; + file_access.m_Param = &new_file; + FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr); + ASSERT_TRUE(new_doc); + FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0); + ASSERT_TRUE(new_page); + + // Check that the saved document has 2 annotations on the first page. + EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page)); + + // Check that the remaining 2 annotations are the original 1st and 3rd ones by + // verifying their rectangle coordinates. + annot = FPDFPage_GetAnnot(new_page, 0); + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_NEAR(86.1971f, rect.left, 0.001f); + FPDFPage_CloseAnnot(annot); + + annot = FPDFPage_GetAnnot(new_page, 1); + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect)); + EXPECT_NEAR(351.8204f, rect.left, 0.001f); + FPDFPage_CloseAnnot(annot); + FPDF_ClosePage(new_page); + FPDF_CloseDocument(new_doc); +} + +TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_original[] = "c35408717759562d1f8bf33d317483d2"; + const char md5_modified_path[] = "cf3cea74bd46497520ff6c4d1ea228c8"; + const char md5_two_paths[] = "e8994452fc4385337bae5522354e10ff"; + const char md5_new_annot[] = "ee5372b31fede117fc83b9384598aa25"; +#else + const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e"; + const char md5_modified_path[] = "3f77b88ce6048e08e636c9a03921b2e5"; + const char md5_two_paths[] = "bffbf5ecd15862b9fe553c795400ff8e"; + const char md5_new_annot[] = "e020534c7eeea76be537c70d6e359a40"; +#endif + + // Open a file with two annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(2, FPDFPage_GetAnnotCount(page)); + + // Check that the page renders correctly. + FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_original); + FPDFBitmap_Destroy(bitmap); + + // Retrieve the stamp annotation which has its AP stream already defined. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Check that this annotation has one path object and retrieve it. + EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot)); + FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot, 1); + EXPECT_FALSE(path); + path = FPDFAnnot_GetObject(annot, 0); + EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path)); + EXPECT_TRUE(path); + + // Modify the color of the path object. + EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 0, 0, 0, 255)); + EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, path)); + + // Check that the page with the modified annotation renders correctly. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_modified_path); + FPDFBitmap_Destroy(bitmap); + + // Add a second path object to the same annotation. + FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84); + EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88)); + EXPECT_TRUE(FPDFPath_SetStrokeColor(dot, 255, 0, 0, 100)); + EXPECT_TRUE(FPDFPath_SetStrokeWidth(dot, 14)); + EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1)); + EXPECT_TRUE(FPDFAnnot_AppendObject(annot, dot)); + EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot)); + + // Check that the page with an annotation with two paths renders correctly. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_two_paths); + FPDFBitmap_Destroy(bitmap); + + // Delete the newly added path object. + EXPECT_TRUE(FPDFAnnot_RemoveObject(annot, 1)); + EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot)); + FPDFPage_CloseAnnot(annot); + + // Check that the page renders the same as before. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_modified_path); + FPDFBitmap_Destroy(bitmap); + + // Create another stamp annotation and set its annotation rectangle. + annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP); + ASSERT_TRUE(annot); + FS_RECTF rect; + rect.left = 200.f; + rect.bottom = 400.f; + rect.right = 500.f; + rect.top = 600.f; + EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect)); + + // Add a new path to the annotation. + FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500); + EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400)); + EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600)); + EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550)); + EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450)); + EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 0, 255, 255, 180)); + EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f)); + EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1)); + EXPECT_TRUE(FPDFAnnot_AppendObject(annot, check)); + EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot)); + + // Check that the annotation's bounding box came from its rectangle. + FS_RECTF new_rect; + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect)); + EXPECT_EQ(rect.left, new_rect.left); + EXPECT_EQ(rect.bottom, new_rect.bottom); + EXPECT_EQ(rect.right, new_rect.right); + EXPECT_EQ(rect.top, new_rect.top); + + // Save the document, closing the page and document. + FPDFPage_CloseAnnot(annot); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + // Open the saved document. + OpenSavedDocument(); + page = LoadSavedPage(0); + VerifySavedRendering(page, 595, 842, md5_new_annot); + + // Check that the document has a correct count of annotations and objects. + EXPECT_EQ(3, FPDFPage_GetAnnotCount(page)); + annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(annot); + EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot)); + + // Check that the new annotation's rectangle is as defined. + ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect)); + EXPECT_EQ(rect.left, new_rect.left); + EXPECT_EQ(rect.bottom, new_rect.bottom); + EXPECT_EQ(rect.right, new_rect.right); + EXPECT_EQ(rect.top, new_rect.top); + + FPDFPage_CloseAnnot(annot); + CloseSavedPage(page); + CloseSavedDocument(); +} + +TEST_F(FPDFAnnotEmbeddertest, ModifyAnnotationFlags) { + // Open a file with an annotation and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Check that the page renders correctly. + FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e"); + FPDFBitmap_Destroy(bitmap); + + // Retrieve the annotation. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Check that the original flag values are as expected. + int flags = FPDFAnnot_GetFlags(annot); + EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN); + EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT); + + // Set the HIDDEN flag. + flags |= FPDF_ANNOT_FLAG_HIDDEN; + EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags)); + flags = FPDFAnnot_GetFlags(annot); + EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN); + EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT); + + // Check that the page renders correctly without rendering the annotation. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, "1940568c9ba33bac5d0b1ee9558c76b3"); + FPDFBitmap_Destroy(bitmap); + + // Unset the HIDDEN flag. + EXPECT_TRUE(FPDFAnnot_SetFlags(annot, FPDF_ANNOT_FLAG_NONE)); + EXPECT_FALSE(FPDFAnnot_GetFlags(annot)); + flags &= ~FPDF_ANNOT_FLAG_HIDDEN; + EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags)); + flags = FPDFAnnot_GetFlags(annot); + EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN); + EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT); + + // Check that the page renders correctly as before. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e"); + FPDFBitmap_Destroy(bitmap); + + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, AddAndModifyImage) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_original[] = "c35408717759562d1f8bf33d317483d2"; + const char md5_new_image[] = "ff012f5697436dfcaec25b32d1333596"; + const char md5_modified_image[] = "86cf8cb2755a7a2046a543e66d9c1e61"; +#else + const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e"; + const char md5_new_image[] = "9ea8732dc9d579f68853f16892856208"; + const char md5_modified_image[] = "74239d2a8c55c9de1dbb9cd8781895aa"; +#endif + + // Open a file with two annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(2, FPDFPage_GetAnnotCount(page)); + + // Check that the page renders correctly. + FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_original); + FPDFBitmap_Destroy(bitmap); + + // Create a stamp annotation and set its annotation rectangle. + FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP); + ASSERT_TRUE(annot); + FS_RECTF rect; + rect.left = 200.f; + rect.bottom = 600.f; + rect.right = 400.f; + rect.top = 800.f; + EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect)); + + // Add a solid-color translucent image object to the new annotation. + constexpr int kBitmapSize = 200; + FPDF_BITMAP image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1); + FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize, 0xeeeecccc); + EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap)); + EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap)); + FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document()); + ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap)); + ASSERT_TRUE(FPDFImageObj_SetMatrix(image_object, kBitmapSize, 0, 0, + kBitmapSize, 0, 0)); + FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600); + EXPECT_TRUE(FPDFAnnot_AppendObject(annot, image_object)); + FPDFPage_CloseAnnot(annot); + + // Check that the page renders correctly with the new image object. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_new_image); + FPDFBitmap_Destroy(bitmap); + + // Retrieve the newly added stamp annotation and its image object. + annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(annot); + EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot)); + image_object = FPDFAnnot_GetObject(annot, 0); + EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object)); + + // Modify the image in the new annotation. + FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize, 0xff000000); + ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap)); + EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, image_object)); + FPDFPage_CloseAnnot(annot); + + // Save the document, closing the page and document. + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + FPDFBitmap_Destroy(image_bitmap); + + // Test that the saved document renders the modified image object correctly. + VerifySavedDocument(595, 842, md5_modified_image); +} + +TEST_F(FPDFAnnotEmbeddertest, AddAndModifyText) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_original[] = "c35408717759562d1f8bf33d317483d2"; + const char md5_new_text[] = "e5680ed048c2cfd9a1d27212cdf41286"; + const char md5_modified_text[] = "79f5cfb0b07caaf936f65f6a7a57ce77"; +#else + const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e"; + const char md5_new_text[] = "00b14fa2dc1c90d1b0d034e1608efef5"; + const char md5_modified_text[] = "076c8f24a09ddc0e49f7e758edead6f0"; +#endif + + // Open a file with two annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(2, FPDFPage_GetAnnotCount(page)); + + // Check that the page renders correctly. + FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_original); + FPDFBitmap_Destroy(bitmap); + + // Create a stamp annotation and set its annotation rectangle. + FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP); + ASSERT_TRUE(annot); + FS_RECTF rect; + rect.left = 200.f; + rect.bottom = 550.f; + rect.right = 450.f; + rect.top = 650.f; + EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect)); + + // Add a translucent text object to the new annotation. + FPDF_PAGEOBJECT text_object = + FPDFPageObj_NewTextObj(document(), "Arial", 12.0f); + EXPECT_TRUE(text_object); + std::unique_ptr text = + GetFPDFWideString(L"I'm a translucent text laying on other text."); + EXPECT_TRUE(FPDFText_SetText(text_object, text.get())); + EXPECT_TRUE(FPDFText_SetFillColor(text_object, 0, 0, 255, 150)); + FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600); + EXPECT_TRUE(FPDFAnnot_AppendObject(annot, text_object)); + FPDFPage_CloseAnnot(annot); + + // Check that the page renders correctly with the new text object. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_new_text); + FPDFBitmap_Destroy(bitmap); + + // Retrieve the newly added stamp annotation and its text object. + annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(annot); + EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot)); + text_object = FPDFAnnot_GetObject(annot, 0); + EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object)); + + // Modify the text in the new annotation. + std::unique_ptr new_text = + GetFPDFWideString(L"New text!"); + EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get())); + EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, text_object)); + FPDFPage_CloseAnnot(annot); + + // Check that the page renders correctly with the modified text object. + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_modified_text); + FPDFBitmap_Destroy(bitmap); + + // Remove the new annotation, and check that the page renders as before. + EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2)); + bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT); + CompareBitmap(bitmap, 595, 842, md5_original); + FPDFBitmap_Destroy(bitmap); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, GetSetStringValue) { + // Open a file with four annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Retrieve the first annotation. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Check that a non-existent key does not exist. + EXPECT_FALSE(FPDFAnnot_HasKey(annot, "none")); + + // Check that the string value of a non-string dictionary entry is empty. + static constexpr char kApKey[] = "AP"; + EXPECT_TRUE(FPDFAnnot_HasKey(annot, kApKey)); + EXPECT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, kApKey)); + EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot, kApKey, nullptr, 0)); + + // Check that the string value of the hash is correct. + static constexpr char kHashKey[] = "AAPL:Hash"; + EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot, kHashKey)); + unsigned long len = FPDFAnnot_GetStringValue(annot, kHashKey, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(66u, FPDFAnnot_GetStringValue(annot, kHashKey, buf.data(), len)); + EXPECT_STREQ(L"395fbcb98d558681742f30683a62a2ad", + BufferToWString(buf).c_str()); + + // Check that the string value of the modified date is correct. + static constexpr char kDateKey[] = "M"; + EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot, kHashKey)); + len = FPDFAnnot_GetStringValue(annot, kDateKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(44u, FPDFAnnot_GetStringValue(annot, kDateKey, buf.data(), len)); + EXPECT_STREQ(L"D:201706071721Z00'00'", BufferToWString(buf).c_str()); + + // Update the date entry for the annotation. + const wchar_t new_date[] = L"D:201706282359Z00'00'"; + std::unique_ptr text = + GetFPDFWideString(new_date); + EXPECT_TRUE(FPDFAnnot_SetStringValue(annot, kDateKey, text.get())); + + // Save the document, closing the page and document. + FPDFPage_CloseAnnot(annot); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + // Open the saved annotation. +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5[] = "4d64e61c9c0f8c60ab3cc3234bb73b1c"; +#else + const char md5[] = "c96ee1f316d7f5a1b154de9f9d467f01"; +#endif + OpenSavedDocument(); + page = LoadSavedPage(0); + VerifySavedRendering(page, 595, 842, md5); + FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(page, 0); + + // Check that the string value of the modified date is the newly-set value. + EXPECT_EQ(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(new_annot, kDateKey)); + len = FPDFAnnot_GetStringValue(new_annot, kDateKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(44u, + FPDFAnnot_GetStringValue(new_annot, kDateKey, buf.data(), len)); + EXPECT_STREQ(new_date, BufferToWString(buf).c_str()); + + FPDFPage_CloseAnnot(new_annot); + CloseSavedPage(page); + CloseSavedDocument(); +} + +TEST_F(FPDFAnnotEmbeddertest, GetSetAP) { + // Open a file with four annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Retrieve the first annotation. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Check that the string value of an AP returns the expected length. + unsigned long normal_len = + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0); + EXPECT_EQ(73970u, normal_len); + + // Check that the string value of an AP is not returned if the buffer is too + // small. The result buffer should be overwritten with an empty string. + std::vector buf(normal_len - 1); + // Write L"z" in the buffer to verify it's not overwritten. + wcscpy(reinterpret_cast(buf.data()), L"z"); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + buf.data(), buf.size())); + std::string ap = BufferToString(buf); + EXPECT_STREQ("z", ap.c_str()); + + // Check that the string value of an AP is returned through a buffer that is + // the right size. + buf.clear(); + buf.resize(normal_len); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + buf.data(), buf.size())); + ap = BufferToString(buf); + EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J")); + EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q")); + + // Check that the string value of an AP is returned through a buffer that is + // larger than necessary. + buf.clear(); + buf.resize(normal_len + 1); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + buf.data(), buf.size())); + ap = BufferToString(buf); + EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J")); + EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q")); + + // Check that getting an AP for a mode that does not have an AP returns an + // empty string. + unsigned long rollover_len = + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0); + EXPECT_EQ(2u, rollover_len); + + buf.clear(); + buf.resize(1000); + EXPECT_EQ(2u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, + buf.data(), buf.size())); + EXPECT_STREQ("", BufferToString(buf).c_str()); + + // Check that setting the AP for an invalid appearance mode fails. + std::unique_ptr apText = + GetFPDFWideString(L"new test ap"); + EXPECT_FALSE(FPDFAnnot_SetAP(annot, -1, apText.get())); + EXPECT_FALSE( + FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_COUNT, apText.get())); + EXPECT_FALSE(FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_COUNT + 1, + apText.get())); + + // Set the AP correctly now. + EXPECT_TRUE( + FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, apText.get())); + + // Check that the new annotation value is equal to the value we just set. + rollover_len = + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0); + EXPECT_EQ(24u, rollover_len); + buf.clear(); + buf.resize(rollover_len); + EXPECT_EQ(24u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, + buf.data(), buf.size())); + EXPECT_STREQ(L"new test ap", BufferToWString(buf).c_str()); + + // Check that the Normal AP was not touched when the Rollover AP was set. + buf.clear(); + buf.resize(normal_len); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + buf.data(), buf.size())); + ap = BufferToString(buf); + EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J")); + EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q")); + + // Save the modified document, then reopen it. + FPDFPage_CloseAnnot(annot); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + OpenSavedDocument(); + page = LoadSavedPage(0); + FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(page, 0); + + // Check that the new annotation value is equal to the value we set before + // saving. + rollover_len = FPDFAnnot_GetAP(new_annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, + nullptr, 0); + EXPECT_EQ(24u, rollover_len); + buf.clear(); + buf.resize(rollover_len); + EXPECT_EQ(24u, FPDFAnnot_GetAP(new_annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, + buf.data(), buf.size())); + EXPECT_STREQ(L"new test ap", BufferToWString(buf).c_str()); + + // Close saved document. + FPDFPage_CloseAnnot(new_annot); + CloseSavedPage(page); + CloseSavedDocument(); +} + +TEST_F(FPDFAnnotEmbeddertest, RemoveOptionalAP) { + // Open a file with four annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Retrieve the first annotation. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Set Down AP. Normal AP is already set. + std::unique_ptr apText = + GetFPDFWideString(L"new test ap"); + EXPECT_TRUE( + FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, apText.get())); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + nullptr, 0)); + EXPECT_EQ(24u, + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0)); + + // Check that setting the Down AP to null removes the Down entry but keeps + // Normal intact. + EXPECT_TRUE(FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr)); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + nullptr, 0)); + EXPECT_EQ(2u, + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0)); + + FPDFPage_CloseAnnot(annot); + FPDF_ClosePage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, RemoveRequiredAP) { + // Open a file with four annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Retrieve the first annotation. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Set Down AP. Normal AP is already set. + std::unique_ptr apText = + GetFPDFWideString(L"new test ap"); + EXPECT_TRUE( + FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, apText.get())); + EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, + nullptr, 0)); + EXPECT_EQ(24u, + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0)); + + // Check that setting the Normal AP to null removes the whole AP dictionary. + EXPECT_TRUE( + FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr)); + EXPECT_EQ( + 2u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0)); + EXPECT_EQ(2u, + FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0)); + + FPDFPage_CloseAnnot(annot); + FPDF_ClosePage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, ExtractLinkedAnnotations) { + // Open a file with annotations and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, nullptr)); + + // Retrieve the highlight annotation which has its popup defined. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot)); + EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot)); + static constexpr char kPopupKey[] = "Popup"; + ASSERT_TRUE(FPDFAnnot_HasKey(annot, kPopupKey)); + ASSERT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, kPopupKey)); + + // Retrieve and verify the popup of the highlight annotation. + FPDF_ANNOTATION popup = FPDFAnnot_GetLinkedAnnot(annot, kPopupKey); + ASSERT_TRUE(popup); + EXPECT_EQ(FPDF_ANNOT_POPUP, FPDFAnnot_GetSubtype(popup)); + EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page, popup)); + FS_RECTF rect; + ASSERT_TRUE(FPDFAnnot_GetRect(popup, &rect)); + EXPECT_NEAR(612.0f, rect.left, 0.001f); + EXPECT_NEAR(578.792, rect.bottom, 0.001f); + + // Attempting to retrieve |annot|'s "IRT"-linked annotation would fail, since + // "IRT" is not a key in |annot|'s dictionary. + static constexpr char kIRTKey[] = "IRT"; + ASSERT_FALSE(FPDFAnnot_HasKey(annot, kIRTKey)); + EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot, kIRTKey)); + + // Attempting to retrieve |annot|'s parent dictionary as an annotation would + // fail, since its parent is not an annotation. + static constexpr char kPKey[] = "P"; + ASSERT_TRUE(FPDFAnnot_HasKey(annot, kPKey)); + EXPECT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, kPKey)); + EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot, kPKey)); + + FPDFPage_CloseAnnot(popup); + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, GetFormFieldFlagsTextField) { + // Open file with form text fields. + ASSERT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Retrieve the first annotation: user-editable text field. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Check that the flag values are as expected. + int flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY); + FPDFPage_CloseAnnot(annot); + + // Retrieve the second annotation: read-only text field. + annot = FPDFPage_GetAnnot(page, 1); + ASSERT_TRUE(annot); + + // Check that the flag values are as expected. + flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY); + FPDFPage_CloseAnnot(annot); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, GetFormFieldFlagsComboBox) { + // Open file with form text fields. + ASSERT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Retrieve the first annotation: user-editable combobox. + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0); + ASSERT_TRUE(annot); + + // Check that the flag values are as expected. + int flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT); + FPDFPage_CloseAnnot(annot); + + // Retrieve the second annotation: regular combobox. + annot = FPDFPage_GetAnnot(page, 1); + ASSERT_TRUE(annot); + + // Check that the flag values are as expected. + flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO); + EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT); + FPDFPage_CloseAnnot(annot); + + // Retrieve the third annotation: read-only combobox. + annot = FPDFPage_GetAnnot(page, 2); + ASSERT_TRUE(annot); + + // Check that the flag values are as expected. + flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO); + EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT); + FPDFPage_CloseAnnot(annot); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotNull) { + // Open file with form text fields. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Attempt to get an annotation where no annotation exists on page. + FPDF_ANNOTATION annot = + FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 0, 0); + EXPECT_FALSE(annot); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotAndCheckFlagsTextField) { + // Open file with form text fields. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Retrieve user-editable text field annotation. + FPDF_ANNOTATION annot = + FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 118); + ASSERT_TRUE(annot); + + // Check that interactive form annotation flag values are as expected. + int flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY); + FPDFPage_CloseAnnot(annot); + + // Retrieve read-only text field annotation. + annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 202); + ASSERT_TRUE(annot); + + // Check that interactive form annotation flag values are as expected. + flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY); + FPDFPage_CloseAnnot(annot); + + UnloadPage(page); +} + +TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotAndCheckFlagsComboBox) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Retrieve user-editable combobox annotation. + FPDF_ANNOTATION annot = + FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 63); + ASSERT_TRUE(annot); + + // Check that interactive form annotation flag values are as expected. + int flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT); + FPDFPage_CloseAnnot(annot); + + // Retrieve regular combobox annotation. + annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 113); + ASSERT_TRUE(annot); + + // Check that interactive form annotation flag values are as expected. + flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO); + EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT); + FPDFPage_CloseAnnot(annot); + + // Retrieve read-only combobox annotation. + annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 213); + ASSERT_TRUE(annot); + + // Check that interactive form annotation flag values are as expected. + flags = FPDFAnnot_GetFormFieldFlags(page, annot); + EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY); + EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO); + EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT); + FPDFPage_CloseAnnot(annot); + + UnloadPage(page); +} diff --git a/fpdfsdk/fpdfattachment.cpp b/fpdfsdk/fpdfattachment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb835343e36bd82489bc30749dd77a01718b694d --- /dev/null +++ b/fpdfsdk/fpdfattachment.cpp @@ -0,0 +1,271 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "public/fpdf_attachment.h" + +#include +#include + +#include "core/fdrm/crypto/fx_crypt.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fpdfdoc/cpdf_filespec.h" +#include "core/fpdfdoc/cpdf_nametree.h" +#include "core/fxcrt/cfx_datetime.h" +#include "core/fxcrt/fx_extension.h" +#include "fpdfsdk/fsdk_define.h" + +namespace { + +constexpr char kChecksumKey[] = "CheckSum"; + +ByteString CFXByteStringHexDecode(const ByteString& bsHex) { + uint8_t* result = nullptr; + uint32_t size = 0; + HexDecode(bsHex.raw_str(), bsHex.GetLength(), &result, &size); + ByteString bsDecoded(result, size); + FX_Free(result); + return bsDecoded; +} + +ByteString GenerateMD5Base16(const void* contents, const unsigned long len) { + uint8_t digest[16]; + CRYPT_MD5Generate(reinterpret_cast(contents), len, digest); + char buf[32]; + for (int i = 0; i < 16; ++i) + FXSYS_IntToTwoHexChars(digest[i], &buf[i * 2]); + + return ByteString(buf, 32); +} + +} // namespace + +FPDF_EXPORT int FPDF_CALLCONV +FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc) + return 0; + + return CPDF_NameTree(pDoc, "EmbeddedFiles").GetCount(); +} + +FPDF_EXPORT FPDF_ATTACHMENT FPDF_CALLCONV +FPDFDoc_AddAttachment(FPDF_DOCUMENT document, FPDF_WIDESTRING name) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + WideString wsName = + WideString::FromUTF16LE(name, WideString::WStringLength(name)); + if (!pDoc || wsName.IsEmpty()) + return nullptr; + + CPDF_Dictionary* pRoot = pDoc->GetRoot(); + if (!pRoot) + return nullptr; + + // Retrieve the document's Names dictionary; create it if missing. + CPDF_Dictionary* pNames = pRoot->GetDictFor("Names"); + if (!pNames) { + pNames = pDoc->NewIndirect(); + pRoot->SetNewFor("Names", pDoc, pNames->GetObjNum()); + } + + // Create the EmbeddedFiles dictionary if missing. + if (!pNames->GetDictFor("EmbeddedFiles")) { + CPDF_Dictionary* pFiles = pDoc->NewIndirect(); + pFiles->SetNewFor("Names"); + pNames->SetNewFor("EmbeddedFiles", pDoc, + pFiles->GetObjNum()); + } + + // Set up the basic entries in the filespec dictionary. + CPDF_Dictionary* pFile = pDoc->NewIndirect(); + pFile->SetNewFor("Type", "Filespec"); + pFile->SetNewFor("UF", wsName); + pFile->SetNewFor("F", wsName); + + // Add the new attachment name and filespec into the document's EmbeddedFiles. + CPDF_NameTree nameTree(pDoc, "EmbeddedFiles"); + if (!nameTree.AddValueAndName( + pdfium::MakeUnique(pDoc, pFile->GetObjNum()), + wsName)) { + return nullptr; + } + + return pFile; +} + +FPDF_EXPORT FPDF_ATTACHMENT FPDF_CALLCONV +FPDFDoc_GetAttachment(FPDF_DOCUMENT document, int index) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc || index < 0) + return nullptr; + + CPDF_NameTree nameTree(pDoc, "EmbeddedFiles"); + if (static_cast(index) >= nameTree.GetCount()) + return nullptr; + + WideString csName; + return nameTree.LookupValueAndName(index, &csName); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFDoc_DeleteAttachment(FPDF_DOCUMENT document, int index) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc || index < 0) + return false; + + CPDF_NameTree nameTree(pDoc, "EmbeddedFiles"); + if (static_cast(index) >= nameTree.GetCount()) + return false; + + return nameTree.DeleteValueAndName(index); +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAttachment_GetName(FPDF_ATTACHMENT attachment, + void* buffer, + unsigned long buflen) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + return Utf16EncodeMaybeCopyAndReturnLength(CPDF_FileSpec(pFile).GetFileName(), + buffer, buflen); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAttachment_HasKey(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict(); + return pParamsDict ? pParamsDict->KeyExist(key) : 0; +} + +FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV +FPDFAttachment_GetValueType(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key) { + if (!FPDFAttachment_HasKey(attachment, key)) + return FPDF_OBJECT_UNKNOWN; + + CPDF_FileSpec spec(CPDFObjectFromFPDFAttachment(attachment)); + CPDF_Object* pObj = spec.GetParamsDict()->GetObjectFor(key); + return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAttachment_SetStringValue(FPDF_ATTACHMENT attachment, + FPDF_BYTESTRING key, + FPDF_WIDESTRING value) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return false; + + CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict(); + if (!pParamsDict) + return false; + + ByteString bsKey = key; + ByteString bsValue = CFXByteStringFromFPDFWideString(value); + bool bEncodedAsHex = bsKey == kChecksumKey; + if (bEncodedAsHex) + bsValue = CFXByteStringHexDecode(bsValue); + + pParamsDict->SetNewFor(bsKey, bsValue, bEncodedAsHex); + return true; +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment, + FPDF_BYTESTRING key, + void* buffer, + unsigned long buflen) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict(); + if (!pParamsDict) + return 0; + + ByteString bsKey = key; + WideString value = pParamsDict->GetUnicodeTextFor(bsKey); + if (bsKey == kChecksumKey && !value.IsEmpty()) { + CPDF_String* stringValue = pParamsDict->GetObjectFor(bsKey)->AsString(); + if (stringValue->IsHex()) { + ByteString encoded = PDF_EncodeString(stringValue->GetString(), true); + value = CPDF_String(nullptr, encoded, false).GetUnicodeText(); + } + } + + return Utf16EncodeMaybeCopyAndReturnLength(value, buffer, buflen); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAttachment_SetFile(FPDF_ATTACHMENT attachment, + FPDF_DOCUMENT document, + const void* contents, + const unsigned long len) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pFile || !pFile->IsDictionary() || !pDoc || len > INT_MAX) + return false; + + // An empty content must have a zero length. + if (!contents && len != 0) + return false; + + // Create a dictionary for the new embedded file stream. + auto pFileStreamDict = pdfium::MakeUnique(); + CPDF_Dictionary* pParamsDict = + pFileStreamDict->SetNewFor("Params"); + + // Set the size of the new file in the dictionary. + pFileStreamDict->SetNewFor("DL", static_cast(len)); + pParamsDict->SetNewFor("Size", static_cast(len)); + + // Set the creation date of the new attachment in the dictionary. + CFX_DateTime dateTime = CFX_DateTime::Now(); + pParamsDict->SetNewFor( + "CreationDate", + ByteString::Format("D:%d%02d%02d%02d%02d%02d", dateTime.GetYear(), + dateTime.GetMonth(), dateTime.GetDay(), + dateTime.GetHour(), dateTime.GetMinute(), + dateTime.GetSecond()), + false); + + // Set the checksum of the new attachment in the dictionary. + pParamsDict->SetNewFor( + kChecksumKey, CFXByteStringHexDecode(GenerateMD5Base16(contents, len)), + true); + + // Create the file stream and have the filespec dictionary link to it. + std::unique_ptr stream(FX_Alloc(uint8_t, len)); + memcpy(stream.get(), contents, len); + CPDF_Stream* pFileStream = pDoc->NewIndirect( + std::move(stream), len, std::move(pFileStreamDict)); + CPDF_Dictionary* pEFDict = + pFile->AsDictionary()->SetNewFor("EF"); + pEFDict->SetNewFor("F", pDoc, pFileStream->GetObjNum()); + return true; +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAttachment_GetFile(FPDF_ATTACHMENT attachment, + void* buffer, + unsigned long buflen) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + CPDF_Stream* pFileStream = CPDF_FileSpec(pFile).GetFileStream(); + if (!pFileStream) + return 0; + + return DecodeStreamMaybeCopyAndReturnLength(pFileStream, buffer, buflen); +} diff --git a/fpdfsdk/fpdfattachment_embeddertest.cpp b/fpdfsdk/fpdfattachment_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd9b5aebf38a3b25d0605ac60495da6b04f24138 --- /dev/null +++ b/fpdfsdk/fpdfattachment_embeddertest.cpp @@ -0,0 +1,260 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "public/fpdf_attachment.h" +#include "public/fpdfview.h" +#include "testing/embedder_test.h" + +static constexpr char kDateKey[] = "CreationDate"; +static constexpr char kChecksumKey[] = "CheckSum"; + +class FPDFAttachmentEmbeddertest : public EmbedderTest {}; + +TEST_F(FPDFAttachmentEmbeddertest, ExtractAttachments) { + // Open a file with two attachments. + ASSERT_TRUE(OpenDocument("embedded_attachments.pdf")); + EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document())); + + // Retrieve the first attachment. + FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0); + ASSERT_TRUE(attachment); + + // Check that the name of the first attachment is correct. + unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len)); + EXPECT_STREQ(L"1.txt", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Check that the content of the first attachment is correct. + len = FPDFAttachment_GetFile(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len)); + EXPECT_EQ(std::string("test"), std::string(buf.data(), 4)); + + // Check that a non-existent key does not exist. + EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none")); + + // Check that the string value of a non-string dictionary entry is empty. + static constexpr char kSizeKey[] = "Size"; + EXPECT_EQ(FPDF_OBJECT_NUMBER, + FPDFAttachment_GetValueType(attachment, kSizeKey)); + EXPECT_EQ(2u, + FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0)); + + // Check that the creation date of the first attachment is correct. + len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(), + len)); + EXPECT_STREQ(L"D:20170712214438-07'00'", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Retrieve the second attachment. + attachment = FPDFDoc_GetAttachment(document(), 1); + ASSERT_TRUE(attachment); + + // Retrieve the second attachment file. + len = FPDFAttachment_GetFile(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len)); + + // Check that the calculated checksum of the file data matches expectation. + const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18"; + const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>"; + const std::string generated_checksum = + GenerateMD5Base16(reinterpret_cast(buf.data()), len); + EXPECT_EQ(kCheckSum, generated_checksum); + + // Check that the stored checksum matches expectation. + len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey, + buf.data(), len)); + EXPECT_EQ(kCheckSumW, + GetPlatformWString(reinterpret_cast(buf.data()))); +} + +TEST_F(FPDFAttachmentEmbeddertest, AddAttachments) { + // Open a file with two attachments. + ASSERT_TRUE(OpenDocument("embedded_attachments.pdf")); + EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document())); + + // Check that adding an attachment with an empty name would fail. + EXPECT_FALSE(FPDFDoc_AddAttachment(document(), nullptr)); + + // Add an attachment to the beginning of the embedded file list. + std::unique_ptr file_name = + GetFPDFWideString(L"0.txt"); + FPDF_ATTACHMENT attachment = + FPDFDoc_AddAttachment(document(), file_name.get()); + + // Check that writing to a file with nullptr but non-zero bytes would fail. + EXPECT_FALSE(FPDFAttachment_SetFile(attachment, document(), nullptr, 10)); + + // Set the new attachment's file. + constexpr char kContents1[] = "Hello!"; + EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1, + strlen(kContents1))); + + // Verify the name of the new attachment (i.e. the first attachment). + attachment = FPDFDoc_GetAttachment(document(), 0); + ASSERT_TRUE(attachment); + unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len)); + EXPECT_STREQ(L"0.txt", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Verify the content of the new attachment (i.e. the first attachment). + len = FPDFAttachment_GetFile(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len)); + EXPECT_EQ(std::string(kContents1), std::string(buf.data(), 6)); + + // Add an attachment to the end of the embedded file list and set its file. + file_name = GetFPDFWideString(L"z.txt"); + attachment = FPDFDoc_AddAttachment(document(), file_name.get()); + constexpr char kContents2[] = "World!"; + EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2, + strlen(kContents2))); + EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document())); + + // Verify the name of the new attachment (i.e. the fourth attachment). + attachment = FPDFDoc_GetAttachment(document(), 3); + ASSERT_TRUE(attachment); + len = FPDFAttachment_GetName(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len)); + EXPECT_STREQ(L"z.txt", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Verify the content of the new attachment (i.e. the fourth attachment). + len = FPDFAttachment_GetFile(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len)); + EXPECT_EQ(std::string(kContents2), std::string(buf.data(), 6)); +} + +TEST_F(FPDFAttachmentEmbeddertest, AddAttachmentsWithParams) { + // Open a file with two attachments. + ASSERT_TRUE(OpenDocument("embedded_attachments.pdf")); + EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document())); + + // Add an attachment to the embedded file list. + std::unique_ptr file_name = + GetFPDFWideString(L"5.txt"); + FPDF_ATTACHMENT attachment = + FPDFDoc_AddAttachment(document(), file_name.get()); + constexpr char kContents[] = "Hello World!"; + EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents, + strlen(kContents))); + + // Set the date to be an arbitrary value. + constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'"; + std::unique_ptr ws_date = + GetFPDFWideString(kDateW); + EXPECT_TRUE( + FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get())); + + // Set the checksum to be an arbitrary value. + constexpr wchar_t kCheckSumW[] = L""; + std::unique_ptr ws_checksum = + GetFPDFWideString(kCheckSumW); + EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey, + ws_checksum.get())); + + // Verify the name of the new attachment (i.e. the second attachment). + attachment = FPDFDoc_GetAttachment(document(), 1); + ASSERT_TRUE(attachment); + unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len)); + EXPECT_STREQ(L"5.txt", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Verify the content of the new attachment. + len = FPDFAttachment_GetFile(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len)); + EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12)); + + // Verify the creation date of the new attachment. + len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(), + len)); + EXPECT_STREQ(kDateW, + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Verify the checksum of the new attachment. + len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey, + buf.data(), len)); + EXPECT_STREQ(kCheckSumW, + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Overwrite the existing file with empty content, and check that the checksum + // gets updated to the correct value. + EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0)); + EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0)); + len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey, + buf.data(), len)); + EXPECT_EQ(L"", + GetPlatformWString(reinterpret_cast(buf.data()))); +} + +TEST_F(FPDFAttachmentEmbeddertest, DeleteAttachment) { + // Open a file with two attachments. + ASSERT_TRUE(OpenDocument("embedded_attachments.pdf")); + EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document())); + + // Verify the name of the first attachment. + FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0); + unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len)); + EXPECT_STREQ(L"1.txt", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Delete the first attachment. + EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0)); + EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document())); + + // Verify the name of the new first attachment. + attachment = FPDFDoc_GetAttachment(document(), 0); + len = FPDFAttachment_GetName(attachment, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), len)); + EXPECT_STREQ(L"attached.pdf", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); +} diff --git a/fpdfsdk/fpdfcatalog.cpp b/fpdfsdk/fpdfcatalog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..493e5aea43f830fbad4ba3e4cf5e0cb938d42ebe --- /dev/null +++ b/fpdfsdk/fpdfcatalog.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "public/fpdf_catalog.h" + +#include "core/fpdfapi/parser/cpdf_document.h" +#include "fpdfsdk/fsdk_define.h" + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFCatalog_IsTagged(FPDF_DOCUMENT document) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc) + return false; + + const CPDF_Dictionary* pCatalog = pDoc->GetRoot(); + if (!pCatalog) + return false; + + const CPDF_Dictionary* pMarkInfo = pCatalog->GetDictFor("MarkInfo"); + return pMarkInfo && pMarkInfo->GetIntegerFor("Marked") != 0; +} diff --git a/fpdfsdk/fpdfcatalog_unittest.cpp b/fpdfsdk/fpdfcatalog_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13c063453be6b5f750f15ce65e9c4cbbd88b1c41 --- /dev/null +++ b/fpdfsdk/fpdfcatalog_unittest.cpp @@ -0,0 +1,95 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "public/fpdf_catalog.h" + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_parser.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" +#endif // PDF_ENABLE_XFA + +class CPDF_TestDocument : public CPDF_Document { + public: + CPDF_TestDocument() : CPDF_Document(nullptr) {} + + void SetRoot(CPDF_Dictionary* root) { + m_pRootDict = root; + GetRoot(); + } +}; + +#ifdef PDF_ENABLE_XFA +class CPDF_TestXFAContext : public CPDFXFA_Context { + public: + CPDF_TestXFAContext() + : CPDFXFA_Context(pdfium::MakeUnique()) {} + + void SetRoot(CPDF_Dictionary* root) { + reinterpret_cast(GetPDFDoc())->SetRoot(root); + } + + CPDF_IndirectObjectHolder* GetHolder() { return GetPDFDoc(); } +}; +using CPDF_TestPdfDocument = CPDF_TestXFAContext; +#else // PDF_ENABLE_XFA +using CPDF_TestPdfDocument = CPDF_TestDocument; +#endif // PDF_ENABLE_XFA + +class PDFCatalogTest : public testing::Test { + public: + void SetUp() override { + CPDF_ModuleMgr::Get()->Init(); + + m_pDoc = pdfium::MakeUnique(); + + // Setup the root directory. + m_pRootObj = pdfium::MakeUnique(); + } + + void TearDown() override { + m_pDoc.reset(); + CPDF_ModuleMgr::Destroy(); + } + + protected: + std::unique_ptr m_pDoc; + std::unique_ptr m_pRootObj; +}; + +TEST_F(PDFCatalogTest, IsTagged) { + // Null doc + EXPECT_FALSE(FPDFCatalog_IsTagged(nullptr)); + + // No root + m_pDoc->SetRoot(nullptr); + EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get())); + + // Empty root + m_pDoc->SetRoot(m_pRootObj.get()); + EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get())); + + // Root with other key + m_pRootObj->SetNewFor("OTHER_KEY", "other value", false); + EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get())); + + // Root with empty MarkInfo + CPDF_Dictionary* markInfoDict = + m_pRootObj->SetNewFor("MarkInfo"); + EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get())); + + // MarkInfo present but Marked is 0 + markInfoDict->SetNewFor("Marked", 0); + EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get())); + + // MarkInfo present and Marked is 1, PDF is considered tagged. + markInfoDict->SetNewFor("Marked", 1); + EXPECT_TRUE(FPDFCatalog_IsTagged(m_pDoc.get())); +} diff --git a/fpdfsdk/fpdfdoc.cpp b/fpdfsdk/fpdfdoc.cpp index f7d94c2f97cb937610dacd677acf79657a0aaca0..47ecf4223b050f60d8dae8a32e46d5c0a30d343a 100644 --- a/fpdfsdk/fpdfdoc.cpp +++ b/fpdfsdk/fpdfdoc.cpp @@ -24,7 +24,7 @@ namespace { CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, CPDF_Bookmark bookmark, - const CFX_WideString& title, + const WideString& title, std::set* visited) { // Return if already checked to avoid circular calling. if (pdfium::ContainsKey(*visited, bookmark.GetDict())) @@ -53,26 +53,16 @@ CPDF_LinkList* GetLinkList(CPDF_Page* page) { if (!page) return nullptr; - CPDF_Document* pDoc = page->m_pDocument; + CPDF_Document* pDoc = page->m_pDocument.Get(); std::unique_ptr* pHolder = pDoc->LinksContext(); if (!pHolder->get()) *pHolder = pdfium::MakeUnique(); return pHolder->get(); } -unsigned long Utf16EncodeMaybeCopyAndReturnLength(const CFX_WideString& text, - void* buffer, - unsigned long buflen) { - CFX_ByteString encodedText = text.UTF16LE_Encode(); - unsigned long len = encodedText.GetLength(); - if (buffer && len <= buflen) - FXSYS_memcpy(buffer, encodedText.c_str(), len); - return len; -} - } // namespace -DLLEXPORT FPDF_BOOKMARK STDCALL +FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) @@ -83,7 +73,7 @@ FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) { return tree.GetFirstChild(bookmark).GetDict(); } -DLLEXPORT FPDF_BOOKMARK STDCALL +FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) { if (!pDict) return nullptr; @@ -96,32 +86,31 @@ FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) { return tree.GetNextSibling(bookmark).GetDict(); } -DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict, - void* buffer, - unsigned long buflen) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict, void* buffer, unsigned long buflen) { if (!pDict) return 0; CPDF_Bookmark bookmark(ToDictionary(static_cast(pDict))); - CFX_WideString title = bookmark.GetTitle(); + WideString title = bookmark.GetTitle(); return Utf16EncodeMaybeCopyAndReturnLength(title, buffer, buflen); } -DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, - FPDF_WIDESTRING title) { +FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV +FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) { if (!title || title[0] == 0) return nullptr; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return nullptr; CPDF_BookmarkTree tree(pDoc); - FX_STRSIZE len = CFX_WideString::WStringLength(title); - CFX_WideString encodedTitle = CFX_WideString::FromUTF16LE(title, len); + size_t len = WideString::WStringLength(title); + WideString encodedTitle = WideString::FromUTF16LE(title, len); std::set visited; return FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict(); } -DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, - FPDF_BOOKMARK pDict) { +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFBookmark_GetDest(FPDF_DOCUMENT document, + FPDF_BOOKMARK pDict) { if (!pDict) return nullptr; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); @@ -139,14 +128,15 @@ DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, return action.GetDest(pDoc).GetObject(); } -DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK pDict) { +FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV +FPDFBookmark_GetAction(FPDF_BOOKMARK pDict) { if (!pDict) return nullptr; CPDF_Bookmark bookmark(ToDictionary(static_cast(pDict))); return bookmark.GetAction().GetDict(); } -DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION pDict) { +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION pDict) { if (!pDict) return PDFACTION_UNSUPPORTED; @@ -166,8 +156,8 @@ DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION pDict) { } } -DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, - FPDF_ACTION pDict) { +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFAction_GetDest(FPDF_DOCUMENT document, + FPDF_ACTION pDict) { if (!pDict) return nullptr; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); @@ -177,40 +167,40 @@ DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, return action.GetDest(pDoc).GetObject(); } -DLLEXPORT unsigned long STDCALL FPDFAction_GetFilePath(FPDF_ACTION pDict, - void* buffer, - unsigned long buflen) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAction_GetFilePath(FPDF_ACTION pDict, void* buffer, unsigned long buflen) { unsigned long type = FPDFAction_GetType(pDict); if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_LAUNCH) return 0; CPDF_Action action(ToDictionary(static_cast(pDict))); - CFX_ByteString path = action.GetFilePath().UTF8Encode(); + ByteString path = action.GetFilePath().UTF8Encode(); unsigned long len = path.GetLength() + 1; if (buffer && len <= buflen) - FXSYS_memcpy(buffer, path.c_str(), len); + memcpy(buffer, path.c_str(), len); return len; } -DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, - FPDF_ACTION pDict, - void* buffer, - unsigned long buflen) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAction_GetURIPath(FPDF_DOCUMENT document, + FPDF_ACTION pDict, + void* buffer, + unsigned long buflen) { if (!pDict) return 0; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 0; CPDF_Action action(ToDictionary(static_cast(pDict))); - CFX_ByteString path = action.GetURI(pDoc); + ByteString path = action.GetURI(pDoc); unsigned long len = path.GetLength() + 1; if (buffer && len <= buflen) - FXSYS_memcpy(buffer, path.c_str(), len); + memcpy(buffer, path.c_str(), len); return len; } -DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, - FPDF_DEST pDict) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST pDict) { if (!pDict) return 0; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); @@ -220,18 +210,36 @@ DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, return dest.GetPageIndex(pDoc); } -DLLEXPORT FPDF_BOOL STDCALL FPDFDest_GetLocationInPage(FPDF_DEST pDict, - FPDF_BOOL* hasXVal, - FPDF_BOOL* hasYVal, - FPDF_BOOL* hasZoomVal, - FS_FLOAT* x, - FS_FLOAT* y, - FS_FLOAT* zoom) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFDest_GetView(FPDF_DEST pDict, + unsigned long* pNumParams, + FS_FLOAT* pParams) { + if (!pDict) { + *pNumParams = 0; + return 0; + } + + CPDF_Dest dest(static_cast(pDict)); + unsigned long nParams = dest.GetNumParams(); + ASSERT(nParams <= 4); + *pNumParams = nParams; + for (unsigned long i = 0; i < nParams; ++i) + pParams[i] = dest.GetParam(i); + return dest.GetZoomMode(); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFDest_GetLocationInPage(FPDF_DEST pDict, + FPDF_BOOL* hasXVal, + FPDF_BOOL* hasYVal, + FPDF_BOOL* hasZoomVal, + FS_FLOAT* x, + FS_FLOAT* y, + FS_FLOAT* zoom) { if (!pDict) return false; - std::unique_ptr dest( - new CPDF_Dest(static_cast(pDict))); + auto dest = pdfium::MakeUnique(static_cast(pDict)); // FPDF_BOOL is an int, GetXYZ expects bools. bool bHasX; @@ -246,9 +254,9 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFDest_GetLocationInPage(FPDF_DEST pDict, return true; } -DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, - double x, - double y) { +FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFLink_GetLinkAtPoint(FPDF_PAGE page, + double x, + double y) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return nullptr; @@ -258,15 +266,15 @@ DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, return nullptr; return pLinkList - ->GetLinkAtPoint( - pPage, CFX_PointF(static_cast(x), static_cast(y)), - nullptr) + ->GetLinkAtPoint(pPage, + CFX_PointF(static_cast(x), static_cast(y)), + nullptr) .GetDict(); } -DLLEXPORT int STDCALL FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, - double x, - double y) { +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, + double x, + double y) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return -1; @@ -277,13 +285,13 @@ DLLEXPORT int STDCALL FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, int z_order = -1; pLinkList->GetLinkAtPoint( - pPage, CFX_PointF(static_cast(x), static_cast(y)), + pPage, CFX_PointF(static_cast(x), static_cast(y)), &z_order); return z_order; } -DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, - FPDF_LINK pDict) { +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFLink_GetDest(FPDF_DOCUMENT document, + FPDF_LINK pDict) { if (!pDict) return nullptr; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); @@ -300,7 +308,7 @@ DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, return action.GetDest(pDoc).GetObject(); } -DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK pDict) { +FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDFLink_GetAction(FPDF_LINK pDict) { if (!pDict) return nullptr; @@ -308,9 +316,9 @@ DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK pDict) { return link.GetAction().GetDict(); } -DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, - int* startPos, - FPDF_LINK* linkAnnot) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page, + int* startPos, + FPDF_LINK* linkAnnot) { if (!startPos || !linkAnnot) return false; CPDF_Page* pPage = CPDFPageFromFPDFPage(page); @@ -333,21 +341,17 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, return false; } -DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, - FS_RECTF* rect) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, + FS_RECTF* rect) { if (!linkAnnot || !rect) return false; CPDF_Dictionary* pAnnotDict = ToDictionary(static_cast(linkAnnot)); - CFX_FloatRect rt = pAnnotDict->GetRectFor("Rect"); - rect->left = rt.left; - rect->bottom = rt.bottom; - rect->right = rt.right; - rect->top = rt.top; + FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"), rect); return true; } -DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) { +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) { if (!linkAnnot) return 0; CPDF_Dictionary* pAnnotDict = @@ -358,9 +362,10 @@ DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) { return static_cast(pArray->GetCount() / 8); } -DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, - int quadIndex, - FS_QUADPOINTSF* quadPoints) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, + int quadIndex, + FS_QUADPOINTSF* quadPoints) { if (!linkAnnot || !quadPoints) return false; CPDF_Dictionary* pAnnotDict = @@ -386,33 +391,35 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, return true; } -DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT document, - FPDF_BYTESTRING tag, - void* buffer, - unsigned long buflen) { +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetMetaText(FPDF_DOCUMENT document, + FPDF_BYTESTRING tag, + void* buffer, + unsigned long buflen) { if (!tag) return 0; CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 0; - CPDF_Dictionary* pInfo = pDoc->GetInfo(); + pDoc->LoadDocumentInfo(); + const CPDF_Dictionary* pInfo = pDoc->GetInfo(); if (!pInfo) return 0; - CFX_WideString text = pInfo->GetUnicodeTextFor(tag); + WideString text = pInfo->GetUnicodeTextFor(tag); return Utf16EncodeMaybeCopyAndReturnLength(text, buffer, buflen); } -DLLEXPORT unsigned long STDCALL FPDF_GetPageLabel(FPDF_DOCUMENT document, - int page_index, - void* buffer, - unsigned long buflen) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_GetPageLabel(FPDF_DOCUMENT document, + int page_index, + void* buffer, + unsigned long buflen) { if (page_index < 0) return 0; // CPDF_PageLabel can deal with NULL |document|. CPDF_PageLabel label(CPDFDocumentFromFPDFDocument(document)); - CFX_WideString str; - if (!label.GetLabel(page_index, &str)) - return 0; - return Utf16EncodeMaybeCopyAndReturnLength(str, buffer, buflen); + Optional str = label.GetLabel(page_index); + return str.has_value() + ? Utf16EncodeMaybeCopyAndReturnLength(str.value(), buffer, buflen) + : 0; } diff --git a/fpdfsdk/fpdfdoc_embeddertest.cpp b/fpdfsdk/fpdfdoc_embeddertest.cpp index 3666687d4dadb55a6bb056c0e10f37ba79a7a4e6..d346330486131470ac8712d044508f3a693249b3 100644 --- a/fpdfsdk/fpdfdoc_embeddertest.cpp +++ b/fpdfsdk/fpdfdoc_embeddertest.cpp @@ -10,7 +10,6 @@ #include "public/fpdf_edit.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" @@ -43,6 +42,65 @@ TEST_F(FPDFDocEmbeddertest, DestGetPageIndex) { EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), dest)); } +TEST_F(FPDFDocEmbeddertest, DestGetView) { + EXPECT_TRUE(OpenDocument("named_dests.pdf")); + + unsigned long numParams; + FS_FLOAT params[4]; + + numParams = 42; + std::fill_n(params, 4, 42.4242f); + EXPECT_EQ(static_cast(PDFDEST_VIEW_UNKNOWN_MODE), + FPDFDest_GetView(nullptr, &numParams, params)); + EXPECT_EQ(0U, numParams); + EXPECT_FLOAT_EQ(42.4242f, params[0]); + + numParams = 42; + std::fill_n(params, 4, 42.4242f); + FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First"); + EXPECT_TRUE(dest); + EXPECT_EQ(static_cast(PDFDEST_VIEW_XYZ), + FPDFDest_GetView(dest, &numParams, params)); + EXPECT_EQ(3U, numParams); + EXPECT_FLOAT_EQ(0, params[0]); + EXPECT_FLOAT_EQ(0, params[1]); + EXPECT_FLOAT_EQ(1, params[2]); + EXPECT_FLOAT_EQ(42.4242f, params[3]); + + numParams = 42; + std::fill_n(params, 4, 42.4242f); + dest = FPDF_GetNamedDestByName(document(), "Next"); + EXPECT_TRUE(dest); + EXPECT_EQ(static_cast(PDFDEST_VIEW_FIT), + FPDFDest_GetView(dest, &numParams, params)); + EXPECT_EQ(0U, numParams); + EXPECT_FLOAT_EQ(42.4242f, params[0]); + + numParams = 42; + std::fill_n(params, 4, 42.4242f); + dest = FPDF_GetNamedDestByName(document(), "FirstAlternate"); + EXPECT_TRUE(dest); + EXPECT_EQ(static_cast(PDFDEST_VIEW_XYZ), + FPDFDest_GetView(dest, &numParams, params)); + EXPECT_EQ(3U, numParams); + EXPECT_FLOAT_EQ(200, params[0]); + EXPECT_FLOAT_EQ(400, params[1]); + EXPECT_FLOAT_EQ(800, params[2]); + EXPECT_FLOAT_EQ(42.4242f, params[3]); + + numParams = 42; + std::fill_n(params, 4, 42.4242f); + dest = FPDF_GetNamedDestByName(document(), "LastAlternate"); + EXPECT_TRUE(dest); + EXPECT_EQ(static_cast(PDFDEST_VIEW_XYZ), + FPDFDest_GetView(dest, &numParams, params)); + EXPECT_EQ(3U, numParams); + EXPECT_FLOAT_EQ(0, params[0]); + EXPECT_FLOAT_EQ(0, params[1]); + EXPECT_FLOAT_EQ(-200, params[2]); + EXPECT_FLOAT_EQ(42.4242f, params[3]); +} + TEST_F(FPDFDocEmbeddertest, DestGetLocationInPage) { EXPECT_TRUE(OpenDocument("named_dests.pdf")); @@ -126,16 +184,14 @@ TEST_F(FPDFDocEmbeddertest, Bookmarks) { FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr); EXPECT_TRUE(child); EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(L"A Good Beginning"), - CFX_WideString::FromUTF16LE(buf, 16)); + EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16)); EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), child)); FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child); EXPECT_TRUE(sibling); EXPECT_EQ(28u, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(L"A Good Ending"), - CFX_WideString::FromUTF16LE(buf, 13)); + EXPECT_EQ(WideString(L"A Good Ending"), WideString::FromUTF16LE(buf, 13)); EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), sibling)); } @@ -153,8 +209,7 @@ TEST_F(FPDFDocEmbeddertest, FindBookmarks) { // Check that the string matches. unsigned short buf[128]; EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(L"A Good Beginning"), - CFX_WideString::FromUTF16LE(buf, 16)); + EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16)); // Check that it is them same as the one returned by GetFirstChild. EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr)); @@ -183,6 +238,71 @@ TEST_F(FPDFDocEmbeddertest, DeletePage) { EXPECT_EQ(0, FPDF_GetPageCount(document())); } +TEST_F(FPDFDocEmbeddertest, GetMetaText) { + ASSERT_TRUE(OpenDocument("bug_601362.pdf")); + + // Invalid document / tag results in 0. + unsigned short buf[128]; + EXPECT_EQ(0u, FPDF_GetMetaText(document(), nullptr, buf, sizeof(buf))); + EXPECT_EQ(0u, FPDF_GetMetaText(nullptr, "", buf, sizeof(buf))); + + // Tags that do not eixst results in an empty wide string. + EXPECT_EQ(2u, FPDF_GetMetaText(document(), "", buf, sizeof(buf))); + EXPECT_EQ(2u, FPDF_GetMetaText(document(), "foo", buf, sizeof(buf))); + ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf))); + ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Author", buf, sizeof(buf))); + ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Subject", buf, sizeof(buf))); + ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Keywords", buf, sizeof(buf))); + ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Producer", buf, sizeof(buf))); + + constexpr wchar_t kExpectedCreator[] = L"Microsoft Word"; + ASSERT_EQ(30u, FPDF_GetMetaText(document(), "Creator", buf, sizeof(buf))); + EXPECT_EQ(WideString(kExpectedCreator), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreator))); + + constexpr wchar_t kExpectedCreationDate[] = L"D:20160411190039+00'00'"; + ASSERT_EQ(48u, + FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf))); + EXPECT_EQ(WideString(kExpectedCreationDate), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreationDate))); + + constexpr wchar_t kExpectedModDate[] = L"D:20160411190039+00'00'"; + ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf))); + EXPECT_EQ(WideString(kExpectedModDate), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate))); +} + +TEST_F(FPDFDocEmbeddertest, GetMetaTextSameObjectNumber) { + ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf")); + + // The PDF has been edited. It has two %%EOF markers, and 2 objects numbered + // (1 0). Both objects are /Info dictionaries, but contain different data. + // Make sure ModDate is the date of the last modification. + unsigned short buf[128]; + constexpr wchar_t kExpectedModDate[] = L"D:20170612232940-04'00'"; + ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf))); + EXPECT_EQ(WideString(kExpectedModDate), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate))); +} + +TEST_F(FPDFDocEmbeddertest, GetMetaTextInAttachmentFile) { + ASSERT_TRUE(OpenDocument("embedded_attachments.pdf")); + + // Make sure this is the date from the PDF itself and not the attached PDF. + unsigned short buf[128]; + constexpr wchar_t kExpectedModDate[] = L"D:20170712214448-07'00'"; + ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf))); + EXPECT_EQ(WideString(kExpectedModDate), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate))); +} + +TEST_F(FPDFDocEmbeddertest, GetMetaTextFromNewDocument) { + FPDF_DOCUMENT empty_doc = FPDF_CreateNewDocument(); + unsigned short buf[128]; + EXPECT_EQ(2u, FPDF_GetMetaText(empty_doc, "Title", buf, sizeof(buf))); + FPDF_CloseDocument(empty_doc); +} + TEST_F(FPDFDocEmbeddertest, NoPageLabels) { EXPECT_TRUE(OpenDocument("about_blank.pdf")); EXPECT_EQ(1, FPDF_GetPageCount(document())); @@ -194,44 +314,48 @@ TEST_F(FPDFDocEmbeddertest, GetPageLabels) { EXPECT_TRUE(OpenDocument("page_labels.pdf")); EXPECT_EQ(7, FPDF_GetPageCount(document())); + // We do not request labels, when use FPDFAvail_IsXXXAvail. + // Flush all data, to allow read labels. + SetWholeFileAvailable(); + unsigned short buf[128]; EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -2, buf, sizeof(buf))); EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -1, buf, sizeof(buf))); - const FX_WCHAR kExpectedPageLabel0[] = L"i"; + const wchar_t kExpectedPageLabel0[] = L"i"; ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 0, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel0), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0))); + EXPECT_EQ(WideString(kExpectedPageLabel0), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0))); - const FX_WCHAR kExpectedPageLabel1[] = L"ii"; + const wchar_t kExpectedPageLabel1[] = L"ii"; ASSERT_EQ(6u, FPDF_GetPageLabel(document(), 1, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel1), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1))); + EXPECT_EQ(WideString(kExpectedPageLabel1), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1))); - const FX_WCHAR kExpectedPageLabel2[] = L"1"; + const wchar_t kExpectedPageLabel2[] = L"1"; ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 2, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel2), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2))); + EXPECT_EQ(WideString(kExpectedPageLabel2), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2))); - const FX_WCHAR kExpectedPageLabel3[] = L"2"; + const wchar_t kExpectedPageLabel3[] = L"2"; ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 3, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel3), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3))); + EXPECT_EQ(WideString(kExpectedPageLabel3), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3))); - const FX_WCHAR kExpectedPageLabel4[] = L"zzA"; + const wchar_t kExpectedPageLabel4[] = L"zzA"; ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 4, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel4), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4))); + EXPECT_EQ(WideString(kExpectedPageLabel4), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4))); - const FX_WCHAR kExpectedPageLabel5[] = L"zzB"; + const wchar_t kExpectedPageLabel5[] = L"zzB"; ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 5, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel5), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5))); + EXPECT_EQ(WideString(kExpectedPageLabel5), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5))); - const FX_WCHAR kExpectedPageLabel6[] = L""; + const wchar_t kExpectedPageLabel6[] = L""; ASSERT_EQ(2u, FPDF_GetPageLabel(document(), 6, buf, sizeof(buf))); - EXPECT_EQ(CFX_WideString(kExpectedPageLabel6), - CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6))); + EXPECT_EQ(WideString(kExpectedPageLabel6), + WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6))); ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 7, buf, sizeof(buf))); ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 8, buf, sizeof(buf))); diff --git a/fpdfsdk/fpdfdoc_unittest.cpp b/fpdfsdk/fpdfdoc_unittest.cpp index c63d6c2e77fa825130619bdb6eea9075fa3073b0..b52cccf0980e4ee6c07b9baf476bdc11aae9e831 100644 --- a/fpdfsdk/fpdfdoc_unittest.cpp +++ b/fpdfsdk/fpdfdoc_unittest.cpp @@ -58,10 +58,7 @@ class PDFDocTest : public testing::Test { }; void SetUp() override { - // We don't need page module or render module, but - // initialize them to keep the code sane. - CPDF_ModuleMgr* module_mgr = CPDF_ModuleMgr::Get(); - module_mgr->InitPageModule(); + CPDF_ModuleMgr::Get()->Init(); m_pDoc = pdfium::MakeUnique(); m_pIndirectObjs = m_pDoc->GetHolder(); @@ -90,7 +87,7 @@ class PDFDocTest : public testing::Test { protected: std::unique_ptr m_pDoc; - CPDF_IndirectObjectHolder* m_pIndirectObjs; + UnownedPtr m_pIndirectObjs; std::unique_ptr m_pRootObj; }; @@ -119,25 +116,25 @@ TEST_F(PDFDocTest, FindBookmark) { auto bookmarks = CreateDictObjs(3); bookmarks[1].obj->SetNewFor("Title", L"Chapter 1"); - bookmarks[1].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[1].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[0].num); - bookmarks[1].obj->SetNewFor("Next", m_pIndirectObjs, + bookmarks[1].obj->SetNewFor("Next", m_pIndirectObjs.Get(), bookmarks[2].num); bookmarks[2].obj->SetNewFor("Title", L"Chapter 2"); - bookmarks[2].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[2].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[0].num); - bookmarks[2].obj->SetNewFor("Prev", m_pIndirectObjs, + bookmarks[2].obj->SetNewFor("Prev", m_pIndirectObjs.Get(), bookmarks[1].num); bookmarks[0].obj->SetNewFor("Type", "Outlines"); bookmarks[0].obj->SetNewFor("Count", 2); - bookmarks[0].obj->SetNewFor("First", m_pIndirectObjs, + bookmarks[0].obj->SetNewFor("First", m_pIndirectObjs.Get(), bookmarks[1].num); - bookmarks[0].obj->SetNewFor("Last", m_pIndirectObjs, + bookmarks[0].obj->SetNewFor("Last", m_pIndirectObjs.Get(), bookmarks[2].num); - m_pRootObj->SetNewFor("Outlines", m_pIndirectObjs, + m_pRootObj->SetNewFor("Outlines", m_pIndirectObjs.Get(), bookmarks[0].num); // Title with no match. @@ -162,25 +159,25 @@ TEST_F(PDFDocTest, FindBookmark) { auto bookmarks = CreateDictObjs(3); bookmarks[1].obj->SetNewFor("Title", L"Chapter 1"); - bookmarks[1].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[1].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[0].num); - bookmarks[1].obj->SetNewFor("First", m_pIndirectObjs, + bookmarks[1].obj->SetNewFor("First", m_pIndirectObjs.Get(), bookmarks[2].num); bookmarks[2].obj->SetNewFor("Title", L"Chapter 2"); - bookmarks[2].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[2].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[1].num); - bookmarks[2].obj->SetNewFor("First", m_pIndirectObjs, + bookmarks[2].obj->SetNewFor("First", m_pIndirectObjs.Get(), bookmarks[1].num); bookmarks[0].obj->SetNewFor("Type", "Outlines"); bookmarks[0].obj->SetNewFor("Count", 2); - bookmarks[0].obj->SetNewFor("First", m_pIndirectObjs, + bookmarks[0].obj->SetNewFor("First", m_pIndirectObjs.Get(), bookmarks[1].num); - bookmarks[0].obj->SetNewFor("Last", m_pIndirectObjs, + bookmarks[0].obj->SetNewFor("Last", m_pIndirectObjs.Get(), bookmarks[2].num); - m_pRootObj->SetNewFor("Outlines", m_pIndirectObjs, + m_pRootObj->SetNewFor("Outlines", m_pIndirectObjs.Get(), bookmarks[0].num); // Title with no match. @@ -197,31 +194,31 @@ TEST_F(PDFDocTest, FindBookmark) { auto bookmarks = CreateDictObjs(4); bookmarks[1].obj->SetNewFor("Title", L"Chapter 1"); - bookmarks[1].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[1].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[0].num); - bookmarks[1].obj->SetNewFor("Next", m_pIndirectObjs, + bookmarks[1].obj->SetNewFor("Next", m_pIndirectObjs.Get(), bookmarks[2].num); bookmarks[2].obj->SetNewFor("Title", L"Chapter 2"); - bookmarks[2].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[2].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[0].num); - bookmarks[2].obj->SetNewFor("Next", m_pIndirectObjs, + bookmarks[2].obj->SetNewFor("Next", m_pIndirectObjs.Get(), bookmarks[3].num); bookmarks[3].obj->SetNewFor("Title", L"Chapter 3"); - bookmarks[3].obj->SetNewFor("Parent", m_pIndirectObjs, + bookmarks[3].obj->SetNewFor("Parent", m_pIndirectObjs.Get(), bookmarks[0].num); - bookmarks[3].obj->SetNewFor("Next", m_pIndirectObjs, + bookmarks[3].obj->SetNewFor("Next", m_pIndirectObjs.Get(), bookmarks[1].num); bookmarks[0].obj->SetNewFor("Type", "Outlines"); bookmarks[0].obj->SetNewFor("Count", 2); - bookmarks[0].obj->SetNewFor("First", m_pIndirectObjs, + bookmarks[0].obj->SetNewFor("First", m_pIndirectObjs.Get(), bookmarks[1].num); - bookmarks[0].obj->SetNewFor("Last", m_pIndirectObjs, + bookmarks[0].obj->SetNewFor("Last", m_pIndirectObjs.Get(), bookmarks[2].num); - m_pRootObj->SetNewFor("Outlines", m_pIndirectObjs, + m_pRootObj->SetNewFor("Outlines", m_pIndirectObjs.Get(), bookmarks[0].num); // Title with no match. diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp index 53554a182231d089e4a0c54f63ab6dcf74bd205f..ee2fc7eb85c569c7d74aaac30a35bea58c4c5c53 100644 --- a/fpdfsdk/fpdfedit_embeddertest.cpp +++ b/fpdfsdk/fpdfedit_embeddertest.cpp @@ -4,14 +4,19 @@ #include #include +#include +#include #include "core/fpdfapi/font/cpdf_font.h" #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fxcrt/fx_system.h" #include "fpdfsdk/fsdk_define.h" +#include "public/cpp/fpdf_deleters.h" +#include "public/fpdf_annot.h" #include "public/fpdf_edit.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" @@ -19,7 +24,113 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" -class FPDFEditEmbeddertest : public EmbedderTest, public TestSaver {}; +class FPDFEditEmbeddertest : public EmbedderTest { + protected: + FPDF_DOCUMENT CreateNewDocument() { + document_ = FPDF_CreateNewDocument(); + cpdf_doc_ = CPDFDocumentFromFPDFDocument(document_); + return document_; + } + + void CheckFontDescriptor(CPDF_Dictionary* font_dict, + int font_type, + bool bold, + bool italic, + uint32_t size, + const uint8_t* data) { + CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor"); + ASSERT_TRUE(font_desc); + EXPECT_EQ("FontDescriptor", font_desc->GetStringFor("Type")); + EXPECT_EQ(font_dict->GetStringFor("BaseFont"), + font_desc->GetStringFor("FontName")); + + // Check that the font descriptor has the required keys according to spec + // 1.7 Table 5.19 + ASSERT_TRUE(font_desc->KeyExist("Flags")); + + int font_flags = font_desc->GetIntegerFor("Flags"); + EXPECT_EQ(bold, FontStyleIsBold(font_flags)); + EXPECT_EQ(italic, FontStyleIsItalic(font_flags)); + EXPECT_TRUE(FontStyleIsNonSymbolic(font_flags)); + ASSERT_TRUE(font_desc->KeyExist("FontBBox")); + + CPDF_Array* fontBBox = font_desc->GetArrayFor("FontBBox"); + ASSERT_TRUE(fontBBox); + EXPECT_EQ(4U, fontBBox->GetCount()); + // Check that the coordinates are in the preferred order according to spec + // 1.7 Section 3.8.4 + EXPECT_TRUE(fontBBox->GetIntegerAt(0) < fontBBox->GetIntegerAt(2)); + EXPECT_TRUE(fontBBox->GetIntegerAt(1) < fontBBox->GetIntegerAt(3)); + + EXPECT_TRUE(font_desc->KeyExist("ItalicAngle")); + EXPECT_TRUE(font_desc->KeyExist("Ascent")); + EXPECT_TRUE(font_desc->KeyExist("Descent")); + EXPECT_TRUE(font_desc->KeyExist("CapHeight")); + EXPECT_TRUE(font_desc->KeyExist("StemV")); + ByteString present("FontFile"); + ByteString absent("FontFile2"); + if (font_type == FPDF_FONT_TRUETYPE) + std::swap(present, absent); + EXPECT_TRUE(font_desc->KeyExist(present)); + EXPECT_FALSE(font_desc->KeyExist(absent)); + + // Check that the font stream is the one that was provided + CPDF_Stream* font_stream = font_desc->GetStreamFor(present); + ASSERT_EQ(size, font_stream->GetRawSize()); + if (font_type == FPDF_FONT_TRUETYPE) { + ASSERT_EQ(static_cast(size), + font_stream->GetDict()->GetIntegerFor("Length1")); + } + uint8_t* stream_data = font_stream->GetRawData(); + for (size_t j = 0; j < size; j++) + EXPECT_EQ(data[j], stream_data[j]) << " at byte " << j; + } + + void CheckCompositeFontWidths(CPDF_Array* widths_array, + CPDF_Font* typed_font) { + // Check that W array is in a format that conforms to PDF spec 1.7 section + // "Glyph Metrics in CIDFonts" (these checks are not + // implementation-specific). + EXPECT_GT(widths_array->GetCount(), 1U); + int num_cids_checked = 0; + int cur_cid = 0; + for (size_t idx = 0; idx < widths_array->GetCount(); idx++) { + int cid = widths_array->GetNumberAt(idx); + EXPECT_GE(cid, cur_cid); + ASSERT_FALSE(++idx == widths_array->GetCount()); + CPDF_Object* next = widths_array->GetObjectAt(idx); + if (next->IsArray()) { + // We are in the c [w1 w2 ...] case + CPDF_Array* arr = next->AsArray(); + int cnt = static_cast(arr->GetCount()); + size_t inner_idx = 0; + for (cur_cid = cid; cur_cid < cid + cnt; cur_cid++) { + int width = arr->GetNumberAt(inner_idx++); + EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid)) << " at cid " + << cur_cid; + } + num_cids_checked += cnt; + continue; + } + // Otherwise, are in the c_first c_last w case. + ASSERT_TRUE(next->IsNumber()); + int last_cid = next->AsNumber()->GetInteger(); + ASSERT_FALSE(++idx == widths_array->GetCount()); + int width = widths_array->GetNumberAt(idx); + for (cur_cid = cid; cur_cid <= last_cid; cur_cid++) { + EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid)) << " at cid " + << cur_cid; + } + num_cids_checked += last_cid - cid + 1; + } + // Make sure we have a good amount of cids described + EXPECT_GT(num_cids_checked, 900); + } + CPDF_Document* cpdf_doc() { return cpdf_doc_; } + + private: + CPDF_Document* cpdf_doc_; +}; namespace { @@ -36,15 +147,13 @@ const char kExpectedPDF[] = "<>\r\n" "endobj\r\n" "4 0 obj\r\n" - "<>/Rotate 0/Type/Page" + "<>>>" + "/Rotate 0/Type/Page" ">>\r\n" "endobj\r\n" "5 0 obj\r\n" - "<>stream\r\n" - // Character '_' is matching '\0' (see comment below). - "x\x9C\x3____\x1\r\n" - "endstream\r\n" + "<>\r\n" "endobj\r\n" "xref\r\n" "0 6\r\n" @@ -53,47 +162,28 @@ const char kExpectedPDF[] = "0000000066 00000 n\r\n" "0000000122 00000 n\r\n" "0000000192 00000 n\r\n" - "0000000301 00000 n\r\n" + "0000000311 00000 n\r\n" "trailer\r\n" "<<\r\n" "/Root 1 0 R\r\n" "/Info 3 0 R\r\n" "/Size 6/ID\\[<.*><.*>\\]>>\r\n" "startxref\r\n" - "379\r\n" + "354\r\n" "%%EOF\r\n"; -int GetBlockFromString(void* param, - unsigned long pos, - unsigned char* buf, - unsigned long size) { - std::string* new_file = static_cast(param); - if (!new_file || pos + size < pos) - return 0; - - unsigned long file_size = new_file->size(); - if (pos + size > file_size) - return 0; - - memcpy(buf, new_file->data() + pos, size); - return 1; -} - } // namespace TEST_F(FPDFEditEmbeddertest, EmptyCreation) { EXPECT_TRUE(CreateEmptyDocument()); FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0); EXPECT_NE(nullptr, page); + // The FPDFPage_GenerateContent call should do nothing. EXPECT_TRUE(FPDFPage_GenerateContent(page)); EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); - // The MatchesRegexp doesn't support embedded NUL ('\0') characters. They are - // replaced by '_' for the purpose of the test. - std::string result = GetString(); - std::replace(result.begin(), result.end(), '\0', '_'); - EXPECT_THAT(result, testing::MatchesRegex( - std::string(kExpectedPDF, sizeof(kExpectedPDF)))); + EXPECT_THAT(GetString(), testing::MatchesRegex(std::string( + kExpectedPDF, sizeof(kExpectedPDF)))); FPDF_ClosePage(page); } @@ -119,7 +209,7 @@ TEST_F(FPDFEditEmbeddertest, RasterizePDF) { // Add the bitmap to an image object and add the image object to the output // page. - FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImgeObj(temp_doc); + FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc); EXPECT_TRUE(FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap)); EXPECT_TRUE(FPDFImageObj_SetMatrix(temp_img, 612, 0, 0, 792, 0, 0)); FPDFPage_InsertObject(temp_page, temp_img); @@ -132,33 +222,13 @@ TEST_F(FPDFEditEmbeddertest, RasterizePDF) { // Get the generated content. Make sure it is at least as big as the original // PDF. - std::string new_file = GetString(); - EXPECT_GT(new_file.size(), 923U); - - // Read |new_file| in, and verify its rendered bitmap. - { - FPDF_FILEACCESS file_access; - memset(&file_access, 0, sizeof(file_access)); - file_access.m_FileLen = new_file.size(); - file_access.m_GetBlock = GetBlockFromString; - file_access.m_Param = &new_file; - - FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr); - EXPECT_EQ(1, FPDF_GetPageCount(document_)); - FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0); - EXPECT_NE(nullptr, new_page); - FPDF_BITMAP new_bitmap = RenderPage(new_page); - CompareBitmap(new_bitmap, 612, 792, kAllBlackMd5sum); - FPDF_ClosePage(new_page); - FPDF_CloseDocument(new_doc); - FPDFBitmap_Destroy(new_bitmap); - } + EXPECT_GT(GetString().size(), 923U); + VerifySavedDocument(612, 792, kAllBlackMd5sum); } TEST_F(FPDFEditEmbeddertest, AddPaths) { // Start with a blank page - FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); - FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792); + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); // We will first add a red rectangle FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20); @@ -171,7 +241,6 @@ TEST_F(FPDFEditEmbeddertest, AddPaths) { EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255)); EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0)); FPDFPage_InsertObject(page, red_rect); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); FPDF_BITMAP page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "66d02eaa6181e2c069ce2ea99beda497"); FPDFBitmap_Destroy(page_bitmap); @@ -179,9 +248,60 @@ TEST_F(FPDFEditEmbeddertest, AddPaths) { // Now add to that a green rectangle with some medium alpha FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40); EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 128)); + + // Make sure the type of the rectangle is a path. + EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(green_rect)); + + // Make sure we get back the same color we set previously. + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + EXPECT_TRUE(FPDFPath_GetFillColor(green_rect, &R, &G, &B, &A)); + EXPECT_EQ(0U, R); + EXPECT_EQ(255U, G); + EXPECT_EQ(0U, B); + EXPECT_EQ(128U, A); + + // Make sure the path has 5 points (1 FXPT_TYPE::MoveTo and 4 + // FXPT_TYPE::LineTo). + ASSERT_EQ(5, FPDFPath_CountSegments(green_rect)); + // Verify actual coordinates. + FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(green_rect, 0); + float x; + float y; + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(100, x); + EXPECT_EQ(100, y); + EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment)); + EXPECT_FALSE(FPDFPathSegment_GetClose(segment)); + segment = FPDFPath_GetPathSegment(green_rect, 1); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(100, x); + EXPECT_EQ(140, y); + EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment)); + EXPECT_FALSE(FPDFPathSegment_GetClose(segment)); + segment = FPDFPath_GetPathSegment(green_rect, 2); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(140, x); + EXPECT_EQ(140, y); + EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment)); + EXPECT_FALSE(FPDFPathSegment_GetClose(segment)); + segment = FPDFPath_GetPathSegment(green_rect, 3); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(140, x); + EXPECT_EQ(100, y); + EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment)); + EXPECT_FALSE(FPDFPathSegment_GetClose(segment)); + segment = FPDFPath_GetPathSegment(green_rect, 4); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(100, x); + EXPECT_EQ(100, y); + EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment)); + EXPECT_TRUE(FPDFPathSegment_GetClose(segment)); + EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0)); FPDFPage_InsertObject(page, green_rect); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "7b0b87604594e773add528fae567a558"); FPDFBitmap_Destroy(page_bitmap); @@ -193,8 +313,33 @@ TEST_F(FPDFEditEmbeddertest, AddPaths) { EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200)); EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100)); EXPECT_TRUE(FPDFPath_Close(black_path)); + + // Make sure the path has 3 points (1 FXPT_TYPE::MoveTo and 2 + // FXPT_TYPE::LineTo). + ASSERT_EQ(3, FPDFPath_CountSegments(black_path)); + // Verify actual coordinates. + segment = FPDFPath_GetPathSegment(black_path, 0); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(400, x); + EXPECT_EQ(100, y); + EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment)); + EXPECT_FALSE(FPDFPathSegment_GetClose(segment)); + segment = FPDFPath_GetPathSegment(black_path, 1); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(400, x); + EXPECT_EQ(200, y); + EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment)); + EXPECT_FALSE(FPDFPathSegment_GetClose(segment)); + segment = FPDFPath_GetPathSegment(black_path, 2); + EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y)); + EXPECT_EQ(300, x); + EXPECT_EQ(100, y); + EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment)); + EXPECT_TRUE(FPDFPathSegment_GetClose(segment)); + // Make sure out of bounds index access fails properly. + EXPECT_EQ(nullptr, FPDFPath_GetPathSegment(black_path, 3)); + FPDFPage_InsertObject(page, black_path); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "eadc8020a14dfcf091da2688733d8806"); FPDFBitmap_Destroy(page_bitmap); @@ -210,33 +355,45 @@ TEST_F(FPDFEditEmbeddertest, AddPaths) { EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400)); EXPECT_TRUE(FPDFPath_Close(blue_path)); FPDFPage_InsertObject(page, blue_path); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); page_bitmap = RenderPage(page); - CompareBitmap(page_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946"); + const char last_md5[] = "9823e1a21bd9b72b6a442ba4f12af946"; + CompareBitmap(page_bitmap, 612, 792, last_md5); FPDFBitmap_Destroy(page_bitmap); // Now save the result, closing the page and document - EXPECT_TRUE(FPDF_SaveAsCopy(doc, this, 0)); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); FPDF_ClosePage(page); - FPDF_CloseDocument(doc); - std::string new_file = GetString(); // Render the saved result - FPDF_FILEACCESS file_access; - memset(&file_access, 0, sizeof(file_access)); - file_access.m_FileLen = new_file.size(); - file_access.m_GetBlock = GetBlockFromString; - file_access.m_Param = &new_file; - FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr); - ASSERT_NE(nullptr, new_doc); - EXPECT_EQ(1, FPDF_GetPageCount(new_doc)); - FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0); - ASSERT_NE(nullptr, new_page); - FPDF_BITMAP new_bitmap = RenderPage(new_page); - CompareBitmap(new_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946"); - FPDFBitmap_Destroy(new_bitmap); - FPDF_ClosePage(new_page); - FPDF_CloseDocument(new_doc); + VerifySavedDocument(612, 792, last_md5); +} + +TEST_F(FPDFEditEmbeddertest, PathsPoints) { + CreateNewDocument(); + FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document_); + // This should fail gracefully, even if img is not a path. + ASSERT_EQ(-1, FPDFPath_CountSegments(img)); + + // This should fail gracefully, even if path is NULL. + ASSERT_EQ(-1, FPDFPath_CountSegments(nullptr)); + + // FPDFPath_GetPathSegment() with a non-path. + ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(img, 0)); + // FPDFPath_GetPathSegment() with a NULL path. + ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(nullptr, 0)); + float x; + float y; + // FPDFPathSegment_GetPoint() with a NULL segment. + EXPECT_FALSE(FPDFPathSegment_GetPoint(nullptr, &x, &y)); + + // FPDFPathSegment_GetType() with a NULL segment. + ASSERT_EQ(FPDF_SEGMENT_UNKNOWN, FPDFPathSegment_GetType(nullptr)); + + // FPDFPathSegment_GetClose() with a NULL segment. + EXPECT_FALSE(FPDFPathSegment_GetClose(nullptr)); + + FPDFPageObj_Destroy(img); } TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) { @@ -250,7 +407,6 @@ TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) { EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255)); EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0)); FPDFPage_InsertObject(page, red_rect); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); // Add a transparent triangle on top of other part of the text. FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50); @@ -260,24 +416,81 @@ TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) { EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10)); EXPECT_TRUE(FPDFPath_Close(black_path)); FPDFPage_InsertObject(page, black_path); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); // Render and check the result. Text is slightly different on Mac. FPDF_BITMAP bitmap = RenderPage(page); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - const char md5[] = "2f7c0deee10a9490538e195af64beb67"; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5[] = "f9e6fa74230f234286bfcada9f7606d8"; #else - const char md5[] = "17c942c76ff229200f2c98073bb60d85"; + const char md5[] = "aa71b09b93b55f467f1290e5111babee"; #endif CompareBitmap(bitmap, 200, 200, md5); FPDFBitmap_Destroy(bitmap); UnloadPage(page); } +TEST_F(FPDFEditEmbeddertest, EditOverExistingContent) { + // Load document with existing content + EXPECT_TRUE(OpenDocument("bug_717.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + + // Add a transparent rectangle on top of the existing content + FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(red_rect2, 255, 0, 0, 100)); + EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(page, red_rect2); + + // Add an opaque rectangle on top of the existing content + FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255)); + EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(page, red_rect); + + FPDF_BITMAP bitmap = RenderPage(page); + CompareBitmap(bitmap, 612, 792, "ad04e5bd0f471a9a564fb034bd0fb073"); + FPDFBitmap_Destroy(bitmap); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + + // Now save the result, closing the page and document + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + UnloadPage(page); + + OpenSavedDocument(); + page = LoadSavedPage(0); + VerifySavedRendering(page, 612, 792, "ad04e5bd0f471a9a564fb034bd0fb073"); + + ClearString(); + // Add another opaque rectangle on top of the existing content + FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 255)); + EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(page, green_rect); + + // Add another transparent rectangle on top of existing content + FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50); + EXPECT_TRUE(FPDFPath_SetFillColor(green_rect2, 0, 255, 0, 100)); + EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0)); + FPDFPage_InsertObject(page, green_rect2); + FPDF_BITMAP new_bitmap = RenderPageWithFlags(page, m_SavedForm, 0); + const char last_md5[] = "4b5b00f824620f8c9b8801ebb98e1cdd"; + CompareBitmap(new_bitmap, 612, 792, last_md5); + FPDFBitmap_Destroy(new_bitmap); + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + + // Now save the result, closing the page and document + EXPECT_TRUE(FPDF_SaveAsCopy(m_SavedDocument, this, 0)); + + CloseSavedPage(page); + CloseSavedDocument(); + + // Render the saved result + VerifySavedDocument(612, 792, last_md5); +} + TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) { // Start with a blank page - FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); - FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792); + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); // Add a large stroked rectangle (fill color should not affect it). FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400); @@ -286,7 +499,6 @@ TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) { EXPECT_TRUE(FPDFPath_SetStrokeWidth(rect, 15.0f)); EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1)); FPDFPage_InsertObject(page, rect); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); FPDF_BITMAP page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "64bd31f862a89e0a9e505a5af6efd506"); FPDFBitmap_Destroy(page_bitmap); @@ -301,7 +513,6 @@ TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) { EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f)); EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1)); FPDFPage_InsertObject(page, check); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "4b6f3b9d25c4e194821217d5016c3724"); FPDFBitmap_Destroy(page_bitmap); @@ -317,64 +528,70 @@ TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) { EXPECT_TRUE(FPDFPath_SetStrokeWidth(path, 10.5f)); EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1)); FPDFPage_InsertObject(page, path); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "ff3e6a22326754944cc6e56609acd73b"); FPDFBitmap_Destroy(page_bitmap); FPDF_ClosePage(page); - FPDF_CloseDocument(doc); } TEST_F(FPDFEditEmbeddertest, AddStandardFontText) { // Start with a blank page - FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); - FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792); + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); // Add some text to the page - FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(doc, "Arial", 12.0f); - EXPECT_TRUE(text1); - EXPECT_TRUE(FPDFText_SetText(text1, "I'm at the bottom of the page")); - FPDFPageObj_Transform(text1, 1, 0, 0, 1, 20, 20); - FPDFPage_InsertObject(page, text1); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); + FPDF_PAGEOBJECT text_object1 = + FPDFPageObj_NewTextObj(document(), "Arial", 12.0f); + EXPECT_TRUE(text_object1); + std::unique_ptr text1 = + GetFPDFWideString(L"I'm at the bottom of the page"); + EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get())); + FPDFPageObj_Transform(text_object1, 1, 0, 0, 1, 20, 20); + FPDFPage_InsertObject(page, text_object1); FPDF_BITMAP page_bitmap = RenderPage(page); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - const char md5[] = "e19c90395d73cb9f37a6c3b0e8b18a9e"; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5[] = "a4dddc1a3930fa694bbff9789dab4161"; #else - const char md5[] = "7c3a36ba7cec01688a16a14bfed9ecfc"; + const char md5[] = "eacaa24573b8ce997b3882595f096f00"; #endif CompareBitmap(page_bitmap, 612, 792, md5); FPDFBitmap_Destroy(page_bitmap); // Try another font - FPDF_PAGEOBJECT text2 = - FPDFPageObj_NewTextObj(doc, "TimesNewRomanBold", 15.0f); - EXPECT_TRUE(text2); - EXPECT_TRUE(FPDFText_SetText(text2, "Hi, I'm Bold. Times New Roman Bold.")); - FPDFPageObj_Transform(text2, 1, 0, 0, 1, 100, 600); - FPDFPage_InsertObject(page, text2); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); + FPDF_PAGEOBJECT text_object2 = + FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f); + EXPECT_TRUE(text_object2); + std::unique_ptr text2 = + GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold."); + EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get())); + FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600); + FPDFPage_InsertObject(page, text_object2); page_bitmap = RenderPage(page); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - const char md5_2[] = "8e1c43dca6be68d364dbc283f5521041"; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_2[] = "a5c4ace4c6f27644094813fe1441a21c"; +#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const char md5_2[] = "2587eac9a787e97a37636d54d11bd28d"; #else - const char md5_2[] = "e0e0873e3a2634a6394a431a51ce90ff"; + const char md5_2[] = "76fcc7d08aa15445efd2e2ceb7c6cc3b"; #endif CompareBitmap(page_bitmap, 612, 792, md5_2); FPDFBitmap_Destroy(page_bitmap); // And some randomly transformed text - FPDF_PAGEOBJECT text3 = FPDFPageObj_NewTextObj(doc, "Courier-Bold", 20.0f); - EXPECT_TRUE(text3); - EXPECT_TRUE(FPDFText_SetText(text3, "Can you read me? <:)>")); - FPDFPageObj_Transform(text3, 1, 1.5, 2, 0.5, 200, 200); - FPDFPage_InsertObject(page, text3); - EXPECT_TRUE(FPDFPage_GenerateContent(page)); + FPDF_PAGEOBJECT text_object3 = + FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f); + EXPECT_TRUE(text_object3); + std::unique_ptr text3 = + GetFPDFWideString(L"Can you read me? <:)>"); + EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get())); + FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200); + FPDFPage_InsertObject(page, text_object3); page_bitmap = RenderPage(page); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - const char md5_3[] = "c6e5df448428793c7e4b0c820bd8c85e"; +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_3[] = "40b3ef04f915ff4c4208948001763544"; +#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const char md5_3[] = "7cb61ec112cf400b489360d443ffc9d2"; #else - const char md5_3[] = "903ee10b6a9f0be51ecad0a1a0eeb171"; + const char md5_3[] = "b8a21668f1dab625af7c072e07fcefc4"; #endif CompareBitmap(page_bitmap, 612, 792, md5_3); FPDFBitmap_Destroy(page_bitmap); @@ -382,13 +599,65 @@ TEST_F(FPDFEditEmbeddertest, AddStandardFontText) { // TODO(npm): Why are there issues with text rotated by 90 degrees? // TODO(npm): FPDF_SaveAsCopy not giving the desired result after this. FPDF_ClosePage(page); - FPDF_CloseDocument(doc); +} + +TEST_F(FPDFEditEmbeddertest, GraphicsData) { + // New page + std::unique_ptr page( + FPDFPage_New(CreateNewDocument(), 0, 612, 792)); + + // Create a rect with nontrivial graphics + FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100); + FPDFPageObj_SetBlendMode(rect1, "Color"); + FPDFPage_InsertObject(page.get(), rect1); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + + // Check that the ExtGState was created + CPDF_Page* the_page = CPDFPageFromFPDFPage(page.get()); + CPDF_Dictionary* graphics_dict = + the_page->m_pResources->GetDictFor("ExtGState"); + ASSERT_TRUE(graphics_dict); + EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); + + // Add a text object causing no change to the graphics dictionary + FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f); + // Only alpha, the last component, matters for the graphics dictionary. And + // the default value is 255. + EXPECT_TRUE(FPDFText_SetFillColor(text1, 100, 100, 100, 255)); + FPDFPage_InsertObject(page.get(), text1); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); + + // Add a text object increasing the size of the graphics dictionary + FPDF_PAGEOBJECT text2 = + FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f); + FPDFPage_InsertObject(page.get(), text2); + FPDFPageObj_SetBlendMode(text2, "Darken"); + EXPECT_TRUE(FPDFText_SetFillColor(text2, 0, 0, 255, 150)); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(3, static_cast(graphics_dict->GetCount())); + + // Add a path that should reuse graphics + FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100); + FPDFPageObj_SetBlendMode(path, "Darken"); + EXPECT_TRUE(FPDFPath_SetFillColor(path, 200, 200, 100, 150)); + FPDFPage_InsertObject(page.get(), path); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(3, static_cast(graphics_dict->GetCount())); + + // Add a rect increasing the size of the graphics dictionary + FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100); + FPDFPageObj_SetBlendMode(rect2, "Darken"); + EXPECT_TRUE(FPDFPath_SetFillColor(rect2, 0, 0, 255, 150)); + EXPECT_TRUE(FPDFPath_SetStrokeColor(rect2, 0, 0, 0, 200)); + FPDFPage_InsertObject(page.get(), rect2); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(4, static_cast(graphics_dict->GetCount())); } TEST_F(FPDFEditEmbeddertest, DoubleGenerating) { // Start with a blank page - FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); - FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792); + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); // Add a red rectangle with some non-default alpha FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100); @@ -402,7 +671,7 @@ TEST_F(FPDFEditEmbeddertest, DoubleGenerating) { CPDF_Dictionary* graphics_dict = the_page->m_pResources->GetDictFor("ExtGState"); ASSERT_TRUE(graphics_dict); - EXPECT_EQ(1, static_cast(graphics_dict->GetCount())); + EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); // Check the bitmap FPDF_BITMAP page_bitmap = RenderPage(page); @@ -412,7 +681,7 @@ TEST_F(FPDFEditEmbeddertest, DoubleGenerating) { // Never mind, my new favorite color is blue, increase alpha EXPECT_TRUE(FPDFPath_SetFillColor(rect, 0, 0, 255, 180)); EXPECT_TRUE(FPDFPage_GenerateContent(page)); - EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); + EXPECT_EQ(3, static_cast(graphics_dict->GetCount())); // Check that bitmap displays changed content page_bitmap = RenderPage(page); @@ -421,16 +690,19 @@ TEST_F(FPDFEditEmbeddertest, DoubleGenerating) { // And now generate, without changes EXPECT_TRUE(FPDFPage_GenerateContent(page)); - EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); + EXPECT_EQ(3, static_cast(graphics_dict->GetCount())); page_bitmap = RenderPage(page); CompareBitmap(page_bitmap, 612, 792, "2e51656f5073b0bee611d9cd086aa09c"); FPDFBitmap_Destroy(page_bitmap); // Add some text to the page - FPDF_PAGEOBJECT text = FPDFPageObj_NewTextObj(doc, "Arial", 12.0f); - EXPECT_TRUE(FPDFText_SetText(text, "Something something #text# something")); - FPDFPageObj_Transform(text, 1, 0, 0, 1, 300, 300); - FPDFPage_InsertObject(page, text); + FPDF_PAGEOBJECT text_object = + FPDFPageObj_NewTextObj(document(), "Arial", 12.0f); + std::unique_ptr text = + GetFPDFWideString(L"Something something #text# something"); + EXPECT_TRUE(FPDFText_SetText(text_object, text.get())); + FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300); + FPDFPage_InsertObject(page, text_object); EXPECT_TRUE(FPDFPage_GenerateContent(page)); CPDF_Dictionary* font_dict = the_page->m_pResources->GetDictFor("Font"); ASSERT_TRUE(font_dict); @@ -438,68 +710,530 @@ TEST_F(FPDFEditEmbeddertest, DoubleGenerating) { // Generate yet again, check dicts are reasonably sized EXPECT_TRUE(FPDFPage_GenerateContent(page)); - EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); + EXPECT_EQ(3, static_cast(graphics_dict->GetCount())); EXPECT_EQ(1, static_cast(font_dict->GetCount())); FPDF_ClosePage(page); - FPDF_CloseDocument(doc); } -TEST_F(FPDFEditEmbeddertest, Type1Font) { - // Create a new document - FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); - CPDF_Document* document = reinterpret_cast(doc); - - // Get Times New Roman Bold as a Type 1 font - CPDF_Font* times_bold = CPDF_Font::GetStockFont(document, "Times-Bold"); - uint8_t* data = times_bold->m_Font.GetFontData(); - uint32_t size = times_bold->m_Font.GetSize(); - FPDF_FONT font = FPDFText_LoadType1Font(doc, data, size); - ASSERT_TRUE(font); - CPDF_Font* type1_font = reinterpret_cast(font); - EXPECT_TRUE(type1_font->IsType1Font()); - - // Check that the font dictionary has the required keys according to the spec - CPDF_Dictionary* font_dict = type1_font->GetFontDict(); +TEST_F(FPDFEditEmbeddertest, LoadSimpleType1Font) { + CreateNewDocument(); + // TODO(npm): use other fonts after disallowing loading any font as any type + const CPDF_Font* stock_font = + CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold"); + const uint8_t* data = stock_font->GetFont()->GetFontData(); + const uint32_t size = stock_font->GetFont()->GetSize(); + std::unique_ptr font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, false)); + ASSERT_TRUE(font.get()); + CPDF_Font* typed_font = static_cast(font.get()); + EXPECT_TRUE(typed_font->IsType1Font()); + + CPDF_Dictionary* font_dict = typed_font->GetFontDict(); EXPECT_EQ("Font", font_dict->GetStringFor("Type")); EXPECT_EQ("Type1", font_dict->GetStringFor("Subtype")); EXPECT_EQ("Times New Roman Bold", font_dict->GetStringFor("BaseFont")); ASSERT_TRUE(font_dict->KeyExist("FirstChar")); ASSERT_TRUE(font_dict->KeyExist("LastChar")); EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar")); - EXPECT_EQ(65532, font_dict->GetIntegerFor("LastChar")); - ASSERT_TRUE(font_dict->KeyExist("Widths")); + EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar")); + CPDF_Array* widths_array = font_dict->GetArrayFor("Widths"); - EXPECT_EQ(65501U, widths_array->GetCount()); + ASSERT_TRUE(widths_array); + ASSERT_EQ(224U, widths_array->GetCount()); EXPECT_EQ(250, widths_array->GetNumberAt(0)); - EXPECT_EQ(0, widths_array->GetNumberAt(8172)); - EXPECT_EQ(1000, widths_array->GetNumberAt(65500)); - ASSERT_TRUE(font_dict->KeyExist("FontDescriptor")); - CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor"); - EXPECT_EQ("FontDescriptor", font_desc->GetStringFor("Type")); - EXPECT_EQ(font_dict->GetStringFor("BaseFont"), - font_desc->GetStringFor("FontName")); - - // Check that the font descriptor has the required keys according to the spec - ASSERT_TRUE(font_desc->KeyExist("Flags")); - int font_flags = font_desc->GetIntegerFor("Flags"); - EXPECT_TRUE(font_flags & FXFONT_BOLD); - EXPECT_TRUE(font_flags & FXFONT_NONSYMBOLIC); - ASSERT_TRUE(font_desc->KeyExist("FontBBox")); - EXPECT_EQ(4U, font_desc->GetArrayFor("FontBBox")->GetCount()); - EXPECT_TRUE(font_desc->KeyExist("ItalicAngle")); - EXPECT_TRUE(font_desc->KeyExist("Ascent")); - EXPECT_TRUE(font_desc->KeyExist("Descent")); - EXPECT_TRUE(font_desc->KeyExist("CapHeight")); - EXPECT_TRUE(font_desc->KeyExist("StemV")); - ASSERT_TRUE(font_desc->KeyExist("FontFile")); - - // Check that the font stream is the one that was provided - CPDF_Stream* font_stream = font_desc->GetStreamFor("FontFile"); - ASSERT_EQ(size, font_stream->GetRawSize()); - uint8_t* stream_data = font_stream->GetRawData(); - for (size_t i = 0; i < size; i++) - EXPECT_EQ(data[i], stream_data[i]); - - // Close document - FPDF_CloseDocument(doc); + EXPECT_EQ(569, widths_array->GetNumberAt(11)); + EXPECT_EQ(500, widths_array->GetNumberAt(223)); + CheckFontDescriptor(font_dict, FPDF_FONT_TYPE1, true, false, size, data); +} + +TEST_F(FPDFEditEmbeddertest, LoadSimpleTrueTypeFont) { + CreateNewDocument(); + const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Courier"); + const uint8_t* data = stock_font->GetFont()->GetFontData(); + const uint32_t size = stock_font->GetFont()->GetSize(); + std::unique_ptr font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, false)); + ASSERT_TRUE(font.get()); + CPDF_Font* typed_font = static_cast(font.get()); + EXPECT_TRUE(typed_font->IsTrueTypeFont()); + + CPDF_Dictionary* font_dict = typed_font->GetFontDict(); + EXPECT_EQ("Font", font_dict->GetStringFor("Type")); + EXPECT_EQ("TrueType", font_dict->GetStringFor("Subtype")); + EXPECT_EQ("Courier New", font_dict->GetStringFor("BaseFont")); + ASSERT_TRUE(font_dict->KeyExist("FirstChar")); + ASSERT_TRUE(font_dict->KeyExist("LastChar")); + EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar")); + EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar")); + + CPDF_Array* widths_array = font_dict->GetArrayFor("Widths"); + ASSERT_TRUE(widths_array); + ASSERT_EQ(224U, widths_array->GetCount()); + EXPECT_EQ(600, widths_array->GetNumberAt(33)); + EXPECT_EQ(600, widths_array->GetNumberAt(74)); + EXPECT_EQ(600, widths_array->GetNumberAt(223)); + CheckFontDescriptor(font_dict, FPDF_FONT_TRUETYPE, false, false, size, data); +} + +TEST_F(FPDFEditEmbeddertest, LoadCIDType0Font) { + CreateNewDocument(); + const CPDF_Font* stock_font = + CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman"); + const uint8_t* data = stock_font->GetFont()->GetFontData(); + const uint32_t size = stock_font->GetFont()->GetSize(); + std::unique_ptr font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, 1)); + ASSERT_TRUE(font.get()); + CPDF_Font* typed_font = static_cast(font.get()); + EXPECT_TRUE(typed_font->IsCIDFont()); + + // Check font dictionary entries + CPDF_Dictionary* font_dict = typed_font->GetFontDict(); + EXPECT_EQ("Font", font_dict->GetStringFor("Type")); + EXPECT_EQ("Type0", font_dict->GetStringFor("Subtype")); + EXPECT_EQ("Times New Roman-Identity-H", font_dict->GetStringFor("BaseFont")); + EXPECT_EQ("Identity-H", font_dict->GetStringFor("Encoding")); + CPDF_Array* descendant_array = font_dict->GetArrayFor("DescendantFonts"); + ASSERT_TRUE(descendant_array); + EXPECT_EQ(1U, descendant_array->GetCount()); + + // Check the CIDFontDict + CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0); + EXPECT_EQ("Font", cidfont_dict->GetStringFor("Type")); + EXPECT_EQ("CIDFontType0", cidfont_dict->GetStringFor("Subtype")); + EXPECT_EQ("Times New Roman", cidfont_dict->GetStringFor("BaseFont")); + CPDF_Dictionary* cidinfo_dict = cidfont_dict->GetDictFor("CIDSystemInfo"); + ASSERT_TRUE(cidinfo_dict); + EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry")); + EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering")); + EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement")); + CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, size, data); + + // Check widths + CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W"); + ASSERT_TRUE(widths_array); + EXPECT_GT(widths_array->GetCount(), 1U); + CheckCompositeFontWidths(widths_array, typed_font); +} + +TEST_F(FPDFEditEmbeddertest, LoadCIDType2Font) { + CreateNewDocument(); + const CPDF_Font* stock_font = + CPDF_Font::GetStockFont(cpdf_doc(), "Helvetica-Oblique"); + const uint8_t* data = stock_font->GetFont()->GetFontData(); + const uint32_t size = stock_font->GetFont()->GetSize(); + + std::unique_ptr font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 1)); + ASSERT_TRUE(font.get()); + CPDF_Font* typed_font = static_cast(font.get()); + EXPECT_TRUE(typed_font->IsCIDFont()); + + // Check font dictionary entries + CPDF_Dictionary* font_dict = typed_font->GetFontDict(); + EXPECT_EQ("Font", font_dict->GetStringFor("Type")); + EXPECT_EQ("Type0", font_dict->GetStringFor("Subtype")); + EXPECT_EQ("Arial Italic", font_dict->GetStringFor("BaseFont")); + EXPECT_EQ("Identity-H", font_dict->GetStringFor("Encoding")); + CPDF_Array* descendant_array = font_dict->GetArrayFor("DescendantFonts"); + ASSERT_TRUE(descendant_array); + EXPECT_EQ(1U, descendant_array->GetCount()); + + // Check the CIDFontDict + CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0); + EXPECT_EQ("Font", cidfont_dict->GetStringFor("Type")); + EXPECT_EQ("CIDFontType2", cidfont_dict->GetStringFor("Subtype")); + EXPECT_EQ("Arial Italic", cidfont_dict->GetStringFor("BaseFont")); + CPDF_Dictionary* cidinfo_dict = cidfont_dict->GetDictFor("CIDSystemInfo"); + ASSERT_TRUE(cidinfo_dict); + EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry")); + EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering")); + EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement")); + CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, size, + data); + + // Check widths + CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W"); + ASSERT_TRUE(widths_array); + CheckCompositeFontWidths(widths_array, typed_font); +} + +TEST_F(FPDFEditEmbeddertest, NormalizeNegativeRotation) { + // Load document with a -90 degree rotation + EXPECT_TRUE(OpenDocument("bug_713197.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + + EXPECT_EQ(3, FPDFPage_GetRotation(page)); + UnloadPage(page); +} + +TEST_F(FPDFEditEmbeddertest, AddTrueTypeFontText) { + // Start with a blank page + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); + { + const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Arial"); + const uint8_t* data = stock_font->GetFont()->GetFontData(); + const uint32_t size = stock_font->GetFont()->GetSize(); + std::unique_ptr font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 0)); + ASSERT_TRUE(font.get()); + + // Add some text to the page + FPDF_PAGEOBJECT text_object = + FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f); + EXPECT_TRUE(text_object); + std::unique_ptr text = + GetFPDFWideString(L"I am testing my loaded font, WEE."); + EXPECT_TRUE(FPDFText_SetText(text_object, text.get())); + FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400); + FPDFPage_InsertObject(page, text_object); + FPDF_BITMAP page_bitmap = RenderPage(page); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5[] = "17d2b6cd574cf66170b09c8927529a94"; +#else + const char md5[] = "70592859010ffbf532a2237b8118bcc4"; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + CompareBitmap(page_bitmap, 612, 792, md5); + FPDFBitmap_Destroy(page_bitmap); + + // Add some more text, same font + FPDF_PAGEOBJECT text_object2 = + FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f); + std::unique_ptr text2 = + GetFPDFWideString(L"Bigger font size"); + EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get())); + FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200); + FPDFPage_InsertObject(page, text_object2); + } + FPDF_BITMAP page_bitmap2 = RenderPage(page); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_2[] = "8eded4193ff1f0f77b8b600a825e97ea"; +#else + const char md5_2[] = "c1d10cce1761c4a998a16b2562030568"; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + CompareBitmap(page_bitmap2, 612, 792, md5_2); + FPDFBitmap_Destroy(page_bitmap2); + + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + VerifySavedDocument(612, 792, md5_2); +} + +TEST_F(FPDFEditEmbeddertest, TransformAnnot) { + // Open a file with one annotation and load its first page. + ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf")); + FPDF_PAGE page = FPDF_LoadPage(document(), 0); + ASSERT_TRUE(page); + + // Add an underline annotation to the page without specifying its rectangle. + FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE); + ASSERT_TRUE(annot); + + // FPDFPage_TransformAnnots() should run without errors when modifying + // annotation rectangles. + FPDFPage_TransformAnnots(page, 1, 2, 3, 4, 5, 6); + + FPDFPage_CloseAnnot(annot); + UnloadPage(page); +} + +// TODO(npm): Add tests using Japanese fonts in other OS. +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ +TEST_F(FPDFEditEmbeddertest, AddCIDFontText) { + // Start with a blank page + FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); + CFX_Font CIDfont; + { + // First, get the data from the font + CIDfont.LoadSubst("IPAGothic", 1, 0, 400, 0, 932, 0); + EXPECT_EQ("IPAGothic", CIDfont.GetFaceName()); + const uint8_t* data = CIDfont.GetFontData(); + const uint32_t size = CIDfont.GetSize(); + + // Load the data into a FPDF_Font. + std::unique_ptr font( + FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 1)); + ASSERT_TRUE(font.get()); + + // Add some text to the page + FPDF_PAGEOBJECT text_object = + FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f); + ASSERT_TRUE(text_object); + std::wstring wstr = L"ABCDEFGhijklmnop."; + std::unique_ptr text = + GetFPDFWideString(wstr); + EXPECT_TRUE(FPDFText_SetText(text_object, text.get())); + FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 200); + FPDFPage_InsertObject(page, text_object); + + // And add some Japanese characters + FPDF_PAGEOBJECT text_object2 = + FPDFPageObj_CreateTextObj(document(), font.get(), 18.0f); + ASSERT_TRUE(text_object2); + std::wstring wstr2 = + L"\u3053\u3093\u306B\u3061\u306f\u4e16\u754C\u3002\u3053\u3053\u306B1" + L"\u756A"; + std::unique_ptr text2 = + GetFPDFWideString(wstr2); + EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get())); + FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 500); + FPDFPage_InsertObject(page, text_object2); + } + + // Check that the text renders properly. + FPDF_BITMAP page_bitmap = RenderPage(page); + const char md5[] = "c68cd79aa72bf83a7b25271370d46b21"; + CompareBitmap(page_bitmap, 612, 792, md5); + FPDFBitmap_Destroy(page_bitmap); + + // Save the document, close the page. + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + + VerifySavedDocument(612, 792, md5); +} +#endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ + +TEST_F(FPDFEditEmbeddertest, SaveAndRender) { + const char md5[] = "3c20472b0552c0c22b88ab1ed8c6202b"; + { + EXPECT_TRUE(OpenDocument("bug_779.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_NE(nullptr, page); + + // Now add a more complex blue path. + FPDF_PAGEOBJECT green_path = FPDFPageObj_CreateNewPath(20, 20); + EXPECT_TRUE(FPDFPath_SetFillColor(green_path, 0, 255, 0, 200)); + // TODO(npm): stroking will cause the MD5s to differ. + EXPECT_TRUE(FPDFPath_SetDrawMode(green_path, FPDF_FILLMODE_WINDING, 0)); + EXPECT_TRUE(FPDFPath_LineTo(green_path, 20, 63)); + EXPECT_TRUE(FPDFPath_BezierTo(green_path, 55, 55, 78, 78, 90, 90)); + EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 133)); + EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 33)); + EXPECT_TRUE(FPDFPath_BezierTo(green_path, 38, 33, 39, 36, 40, 40)); + EXPECT_TRUE(FPDFPath_Close(green_path)); + FPDFPage_InsertObject(page, green_path); + FPDF_BITMAP page_bitmap = RenderPage(page); + CompareBitmap(page_bitmap, 612, 792, md5); + FPDFBitmap_Destroy(page_bitmap); + + // Now save the result, closing the page and document + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + UnloadPage(page); + } + + VerifySavedDocument(612, 792, md5); +} + +TEST_F(FPDFEditEmbeddertest, ExtractImageBitmap) { + ASSERT_TRUE(OpenDocument("embedded_images.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + ASSERT_EQ(39, FPDFPage_CountObjects(page)); + + FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32); + EXPECT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + EXPECT_FALSE(FPDFImageObj_GetBitmap(obj)); + + obj = FPDFPage_GetObject(page, 33); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + FPDF_BITMAP bitmap = FPDFImageObj_GetBitmap(obj); + EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap)); + CompareBitmap(bitmap, 109, 88, "d65e98d968d196abf13f78aec655ffae"); + FPDFBitmap_Destroy(bitmap); + + obj = FPDFPage_GetObject(page, 34); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + bitmap = FPDFImageObj_GetBitmap(obj); + EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap)); + CompareBitmap(bitmap, 103, 75, "1287711c84dbef767c435d11697661d6"); + FPDFBitmap_Destroy(bitmap); + + obj = FPDFPage_GetObject(page, 35); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + bitmap = FPDFImageObj_GetBitmap(obj); + EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap)); + CompareBitmap(bitmap, 92, 68, "9c6d76cb1e37ef8514f9455d759391f3"); + FPDFBitmap_Destroy(bitmap); + + obj = FPDFPage_GetObject(page, 36); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + bitmap = FPDFImageObj_GetBitmap(obj); + EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap)); + CompareBitmap(bitmap, 79, 60, "15cb6a49a2e354ed0e9f45dd34e3da1a"); + FPDFBitmap_Destroy(bitmap); + + obj = FPDFPage_GetObject(page, 37); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + bitmap = FPDFImageObj_GetBitmap(obj); + EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap)); + CompareBitmap(bitmap, 126, 106, "be5a64ba7890d2657522af6524118534"); + FPDFBitmap_Destroy(bitmap); + + obj = FPDFPage_GetObject(page, 38); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + bitmap = FPDFImageObj_GetBitmap(obj); + EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap)); + CompareBitmap(bitmap, 194, 119, "f9e24207ee1bc0db6c543d33a5f12ec5"); + FPDFBitmap_Destroy(bitmap); + UnloadPage(page); +} + +TEST_F(FPDFEditEmbeddertest, GetImageData) { + EXPECT_TRUE(OpenDocument("embedded_images.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + ASSERT_EQ(39, FPDFPage_CountObjects(page)); + + // Retrieve an image object with flate-encoded data stream. + FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + + // Check that the raw image data has the correct length and hash value. + unsigned long len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0); + std::vector buf(len); + EXPECT_EQ(4091u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len)); + EXPECT_EQ("f73802327d2e88e890f653961bcda81a", + GenerateMD5Base16(reinterpret_cast(buf.data()), len)); + + // Check that the decoded image data has the correct length and hash value. + len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(28776u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len)); + EXPECT_EQ("cb3637934bb3b95a6e4ae1ea9eb9e56e", + GenerateMD5Base16(reinterpret_cast(buf.data()), len)); + + // Retrieve an image obejct with DCTDecode-encoded data stream. + obj = FPDFPage_GetObject(page, 37); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + + // Check that the raw image data has the correct length and hash value. + len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(4370u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len)); + EXPECT_EQ("6aae1f3710335023a9e12191be66b64b", + GenerateMD5Base16(reinterpret_cast(buf.data()), len)); + + // Check that the decoded image data has the correct length and hash value, + // which should be the same as those of the raw data, since this image is + // encoded by a single DCTDecode filter and decoding is a noop. + len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0); + buf.clear(); + buf.resize(len); + EXPECT_EQ(4370u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len)); + EXPECT_EQ("6aae1f3710335023a9e12191be66b64b", + GenerateMD5Base16(reinterpret_cast(buf.data()), len)); + + UnloadPage(page); +} + +TEST_F(FPDFEditEmbeddertest, DestroyPageObject) { + FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20); + ASSERT_TRUE(rect); + + // There should be no memory leaks with a call to FPDFPageObj_Destroy(). + FPDFPageObj_Destroy(rect); +} + +TEST_F(FPDFEditEmbeddertest, GetImageFilters) { + EXPECT_TRUE(OpenDocument("embedded_images.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Verify that retrieving the filter of a non-image object would fail. + FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32); + ASSERT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + ASSERT_EQ(0, FPDFImageObj_GetImageFilterCount(obj)); + EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0)); + + // Verify the returned filter string for an image object with a single filter. + obj = FPDFPage_GetObject(page, 33); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + ASSERT_EQ(1, FPDFImageObj_GetImageFilterCount(obj)); + unsigned long len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0); + std::vector buf(len); + static constexpr char kFlateDecode[] = "FlateDecode"; + EXPECT_EQ(sizeof(kFlateDecode), + FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len)); + EXPECT_STREQ(kFlateDecode, buf.data()); + EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0)); + + // Verify all the filters for an image object with a list of filters. + obj = FPDFPage_GetObject(page, 38); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + ASSERT_EQ(2, FPDFImageObj_GetImageFilterCount(obj)); + len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0); + buf.clear(); + buf.resize(len); + static constexpr char kASCIIHexDecode[] = "ASCIIHexDecode"; + EXPECT_EQ(sizeof(kASCIIHexDecode), + FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len)); + EXPECT_STREQ(kASCIIHexDecode, buf.data()); + + len = FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0); + buf.clear(); + buf.resize(len); + static constexpr char kDCTDecode[] = "DCTDecode"; + EXPECT_EQ(sizeof(kDCTDecode), + FPDFImageObj_GetImageFilter(obj, 1, buf.data(), len)); + EXPECT_STREQ(kDCTDecode, buf.data()); + + UnloadPage(page); +} + +TEST_F(FPDFEditEmbeddertest, GetImageMetadata) { + ASSERT_TRUE(OpenDocument("embedded_images.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Check that getting the metadata of a null object would fail. + FPDF_IMAGEOBJ_METADATA metadata; + EXPECT_FALSE(FPDFImageObj_GetImageMetadata(nullptr, page, &metadata)); + + // Check that receiving the metadata with a null metadata object would fail. + FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 35); + EXPECT_FALSE(FPDFImageObj_GetImageMetadata(obj, page, nullptr)); + + // Check that when retrieving an image object's metadata without passing in + // |page|, all values are correct, with the last two being default values. + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, nullptr, &metadata)); + EXPECT_EQ(7, metadata.marked_content_id); + EXPECT_EQ(92u, metadata.width); + EXPECT_EQ(68u, metadata.height); + EXPECT_NEAR(96.000000, metadata.horizontal_dpi, 0.001); + EXPECT_NEAR(96.000000, metadata.vertical_dpi, 0.001); + EXPECT_EQ(0u, metadata.bits_per_pixel); + EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace); + + // Verify the metadata of a bitmap image with indexed colorspace. + ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata)); + EXPECT_EQ(7, metadata.marked_content_id); + EXPECT_EQ(92u, metadata.width); + EXPECT_EQ(68u, metadata.height); + EXPECT_NEAR(96.000000, metadata.horizontal_dpi, 0.001); + EXPECT_NEAR(96.000000, metadata.vertical_dpi, 0.001); + EXPECT_EQ(1u, metadata.bits_per_pixel); + EXPECT_EQ(FPDF_COLORSPACE_INDEXED, metadata.colorspace); + + // Verify the metadata of an image with RGB colorspace. + obj = FPDFPage_GetObject(page, 37); + ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj)); + ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata)); + EXPECT_EQ(9, metadata.marked_content_id); + EXPECT_EQ(126u, metadata.width); + EXPECT_EQ(106u, metadata.height); + EXPECT_NEAR(162.173752, metadata.horizontal_dpi, 0.001); + EXPECT_NEAR(162.555878, metadata.vertical_dpi, 0.001); + EXPECT_EQ(24u, metadata.bits_per_pixel); + EXPECT_EQ(FPDF_COLORSPACE_DEVICERGB, metadata.colorspace); + + UnloadPage(page); } diff --git a/fpdfsdk/fpdfeditimg.cpp b/fpdfsdk/fpdfeditimg.cpp index 56875e233e13aedfa88aae5e0fa238a412dd96db..0d7ba56559c0352460d3c333d33fdad23de249f8 100644 --- a/fpdfsdk/fpdfeditimg.cpp +++ b/fpdfsdk/fpdfeditimg.cpp @@ -9,97 +9,296 @@ #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_imageobject.h" +#include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/render/cpdf_dibsource.h" #include "fpdfsdk/fsdk_define.h" #include "third_party/base/ptr_util.h" -DLLEXPORT FPDF_PAGEOBJECT STDCALL -FPDFPageObj_NewImgeObj(FPDF_DOCUMENT document) { - CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); - if (!pDoc) - return nullptr; +namespace { - CPDF_ImageObject* pImageObj = new CPDF_ImageObject; - pImageObj->SetOwnedImage(pdfium::MakeUnique(pDoc)); - return pImageObj; -} +// These checks ensure the consistency of colorspace values across core/ and +// public/. +static_assert(PDFCS_DEVICEGRAY == FPDF_COLORSPACE_DEVICEGRAY, + "PDFCS_DEVICEGRAY value mismatch"); +static_assert(PDFCS_DEVICERGB == FPDF_COLORSPACE_DEVICERGB, + "PDFCS_DEVICERGB value mismatch"); +static_assert(PDFCS_DEVICECMYK == FPDF_COLORSPACE_DEVICECMYK, + "PDFCS_DEVICECMYK value mismatch"); +static_assert(PDFCS_CALGRAY == FPDF_COLORSPACE_CALGRAY, + "PDFCS_CALGRAY value mismatch"); +static_assert(PDFCS_CALRGB == FPDF_COLORSPACE_CALRGB, + "PDFCS_CALRGB value mismatch"); +static_assert(PDFCS_LAB == FPDF_COLORSPACE_LAB, "PDFCS_LAB value mismatch"); +static_assert(PDFCS_ICCBASED == FPDF_COLORSPACE_ICCBASED, + "PDFCS_ICCBASED value mismatch"); +static_assert(PDFCS_SEPARATION == FPDF_COLORSPACE_SEPARATION, + "PDFCS_SEPARATION value mismatch"); +static_assert(PDFCS_DEVICEN == FPDF_COLORSPACE_DEVICEN, + "PDFCS_DEVICEN value mismatch"); +static_assert(PDFCS_INDEXED == FPDF_COLORSPACE_INDEXED, + "PDFCS_INDEXED value mismatch"); +static_assert(PDFCS_PATTERN == FPDF_COLORSPACE_PATTERN, + "PDFCS_PATTERN value mismatch"); -FPDF_BOOL FPDFImageObj_LoadJpegHelper(FPDF_PAGE* pages, - int nCount, - FPDF_PAGEOBJECT image_object, - FPDF_FILEACCESS* fileAccess, - bool inlineJpeg) { - if (!image_object || !fileAccess || !pages) +bool LoadJpegHelper(FPDF_PAGE* pages, + int nCount, + FPDF_PAGEOBJECT image_object, + FPDF_FILEACCESS* fileAccess, + bool inlineJpeg) { + if (!image_object || !fileAccess) return false; - CFX_RetainPtr pFile = - MakeSeekableReadStream(fileAccess); - CPDF_ImageObject* pImgObj = reinterpret_cast(image_object); - for (int index = 0; index < nCount; index++) { - CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]); - if (pPage) - pImgObj->GetImage()->ResetCache(pPage, nullptr); + RetainPtr pFile = MakeSeekableReadStream(fileAccess); + CPDF_ImageObject* pImgObj = static_cast(image_object); + + if (pages) { + for (int index = 0; index < nCount; index++) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]); + if (pPage) + pImgObj->GetImage()->ResetCache(pPage, nullptr); + } } if (inlineJpeg) pImgObj->GetImage()->SetJpegImageInline(pFile); else pImgObj->GetImage()->SetJpegImage(pFile); - + pImgObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL STDCALL +} // namespace + +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc) + return nullptr; + + auto pImageObj = pdfium::MakeUnique(); + pImageObj->SetImage(pdfium::MakeRetain(pDoc)); + return pImageObj.release(); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages, int nCount, FPDF_PAGEOBJECT image_object, FPDF_FILEACCESS* fileAccess) { - return FPDFImageObj_LoadJpegHelper(pages, nCount, image_object, fileAccess, - false); + return LoadJpegHelper(pages, nCount, image_object, fileAccess, false); } -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages, int nCount, FPDF_PAGEOBJECT image_object, FPDF_FILEACCESS* fileAccess) { - return FPDFImageObj_LoadJpegHelper(pages, nCount, image_object, fileAccess, - true); + return LoadJpegHelper(pages, nCount, image_object, fileAccess, true); } -DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object, - double a, - double b, - double c, - double d, - double e, - double f) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object, + double a, + double b, + double c, + double d, + double e, + double f) { if (!image_object) return false; - CPDF_ImageObject* pImgObj = reinterpret_cast(image_object); - pImgObj->set_matrix( - CFX_Matrix(static_cast(a), static_cast(b), - static_cast(c), static_cast(d), - static_cast(e), static_cast(f))); + CPDF_ImageObject* pImgObj = static_cast(image_object); + pImgObj->set_matrix(CFX_Matrix(static_cast(a), static_cast(b), + static_cast(c), static_cast(d), + static_cast(e), static_cast(f))); pImgObj->CalcBoundingBox(); + pImgObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetBitmap(FPDF_PAGE* pages, - int nCount, - FPDF_PAGEOBJECT image_object, - FPDF_BITMAP bitmap) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFImageObj_SetBitmap(FPDF_PAGE* pages, + int nCount, + FPDF_PAGEOBJECT image_object, + FPDF_BITMAP bitmap) { if (!image_object || !bitmap || !pages) return false; - CPDF_ImageObject* pImgObj = reinterpret_cast(image_object); + CPDF_ImageObject* pImgObj = static_cast(image_object); for (int index = 0; index < nCount; index++) { CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]); if (pPage) pImgObj->GetImage()->ResetCache(pPage, nullptr); } - pImgObj->GetImage()->SetImage(reinterpret_cast(bitmap)); + RetainPtr holder(CFXBitmapFromFPDFBitmap(bitmap)); + pImgObj->GetImage()->SetImage(holder); pImgObj->CalcBoundingBox(); + pImgObj->SetDirty(true); + return true; +} + +FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV +FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) { + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object); + if (!pObj || !pObj->IsImage()) + return nullptr; + + RetainPtr pImg = pObj->AsImage()->GetImage(); + if (!pImg) + return nullptr; + + RetainPtr pSource = pImg->LoadDIBSource(); + if (!pSource) + return nullptr; + + RetainPtr pBitmap; + // If the source image has a representation of 1 bit per pixel, then convert + // it to a grayscale bitmap having 1 byte per pixel, since bitmaps have no + // concept of bits. Otherwise, convert the source image to a bitmap directly, + // retaining its color representation. + if (pSource->GetBPP() == 1) + pBitmap = pSource->CloneConvert(FXDIB_8bppRgb); + else + pBitmap = pSource->Clone(nullptr); + + return pBitmap.Leak(); +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object, + void* buffer, + unsigned long buflen) { + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object); + if (!pObj || !pObj->IsImage()) + return 0; + + RetainPtr pImg = pObj->AsImage()->GetImage(); + if (!pImg) + return 0; + + CPDF_Stream* pImgStream = pImg->GetStream(); + if (!pImgStream) + return 0; + + return DecodeStreamMaybeCopyAndReturnLength(pImgStream, buffer, buflen); +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object, + void* buffer, + unsigned long buflen) { + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object); + if (!pObj || !pObj->IsImage()) + return 0; + + RetainPtr pImg = pObj->AsImage()->GetImage(); + if (!pImg) + return 0; + + CPDF_Stream* pImgStream = pImg->GetStream(); + if (!pImgStream) + return 0; + + uint32_t len = pImgStream->GetRawSize(); + if (buffer && buflen >= len) + memcpy(buffer, pImgStream->GetRawData(), len); + + return len; +} + +FPDF_EXPORT int FPDF_CALLCONV +FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) { + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object); + if (!pObj || !pObj->IsImage()) + return 0; + + RetainPtr pImg = pObj->AsImage()->GetImage(); + if (!pImg) + return 0; + + CPDF_Dictionary* pDict = pImg->GetDict(); + CPDF_Object* pFilter = pDict ? pDict->GetDirectObjectFor("Filter") : nullptr; + if (!pFilter) + return 0; + + if (pFilter->IsArray()) + return pFilter->AsArray()->GetCount(); + if (pFilter->IsName()) + return 1; + + return 0; +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object, + int index, + void* buffer, + unsigned long buflen) { + if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object)) + return 0; + + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object); + CPDF_Object* pFilter = + pObj->AsImage()->GetImage()->GetDict()->GetDirectObjectFor("Filter"); + ByteString bsFilter; + if (pFilter->IsName()) + bsFilter = pFilter->AsName()->GetString(); + else + bsFilter = pFilter->AsArray()->GetStringAt(index); + + unsigned long len = bsFilter.GetLength() + 1; + if (buffer && len <= buflen) + memcpy(buffer, bsFilter.c_str(), len); + return len; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object, + FPDF_PAGE page, + FPDF_IMAGEOBJ_METADATA* metadata) { + CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object); + if (!pObj || !pObj->IsImage() || !metadata) + return false; + + RetainPtr pImg = pObj->AsImage()->GetImage(); + if (!pImg) + return false; + + metadata->marked_content_id = pObj->m_ContentMark.GetMarkedContentID(); + + const int nPixelWidth = pImg->GetPixelWidth(); + const int nPixelHeight = pImg->GetPixelHeight(); + metadata->width = nPixelWidth; + metadata->height = nPixelHeight; + + const float nWidth = pObj->m_Right - pObj->m_Left; + const float nHeight = pObj->m_Top - pObj->m_Bottom; + constexpr int nPointsPerInch = 72; + if (nWidth != 0 && nHeight != 0) { + metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch; + metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch; + } + + metadata->bits_per_pixel = 0; + metadata->colorspace = FPDF_COLORSPACE_UNKNOWN; + + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage || !pPage->m_pDocument.Get() || !pImg->GetStream()) + return true; + + auto pSource = pdfium::MakeRetain(); + if (!pSource->StartLoadDIBSource(pPage->m_pDocument.Get(), pImg->GetStream(), + false, nullptr, + pPage->m_pPageResources.Get())) { + return true; + } + + metadata->bits_per_pixel = pSource->GetBPP(); + if (pSource->GetColorSpace()) + metadata->colorspace = pSource->GetColorSpace()->GetFamily(); + return true; } diff --git a/fpdfsdk/fpdfeditimg_unittest.cpp b/fpdfsdk/fpdfeditimg_unittest.cpp index ae4af2591e005d7cb2654f72f5a8ba4cad4733f1..fcc081ab7689096defb944ca4c30cf0030efc35a 100644 --- a/fpdfsdk/fpdfeditimg_unittest.cpp +++ b/fpdfsdk/fpdfeditimg_unittest.cpp @@ -8,10 +8,7 @@ #include "testing/gtest/include/gtest/gtest.h" class PDFEditTest : public testing::Test { - void SetUp() override { - CPDF_ModuleMgr* module_mgr = CPDF_ModuleMgr::Get(); - module_mgr->InitPageModule(); - } + void SetUp() override { CPDF_ModuleMgr::Get()->Init(); } void TearDown() override { CPDF_ModuleMgr::Destroy(); } }; @@ -19,40 +16,40 @@ class PDFEditTest : public testing::Test { TEST_F(PDFEditTest, InsertObjectWithInvalidPage) { FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); FPDF_PAGE page = FPDFPage_New(doc, 0, 100, 100); - EXPECT_EQ(0, FPDFPage_CountObject(page)); + EXPECT_EQ(0, FPDFPage_CountObjects(page)); FPDFPage_InsertObject(nullptr, nullptr); - EXPECT_EQ(0, FPDFPage_CountObject(page)); + EXPECT_EQ(0, FPDFPage_CountObjects(page)); FPDFPage_InsertObject(page, nullptr); - EXPECT_EQ(0, FPDFPage_CountObject(page)); + EXPECT_EQ(0, FPDFPage_CountObjects(page)); - FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImgeObj(doc); + FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImageObj(doc); FPDFPage_InsertObject(nullptr, page_image); - EXPECT_EQ(0, FPDFPage_CountObject(page)); + EXPECT_EQ(0, FPDFPage_CountObjects(page)); FPDF_ClosePage(page); FPDF_CloseDocument(doc); } -TEST_F(PDFEditTest, NewImgeObj) { +TEST_F(PDFEditTest, NewImageObj) { FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); FPDF_PAGE page = FPDFPage_New(doc, 0, 100, 100); - EXPECT_EQ(0, FPDFPage_CountObject(page)); + EXPECT_EQ(0, FPDFPage_CountObjects(page)); - FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImgeObj(doc); + FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImageObj(doc); FPDFPage_InsertObject(page, page_image); - EXPECT_EQ(1, FPDFPage_CountObject(page)); + EXPECT_EQ(1, FPDFPage_CountObjects(page)); EXPECT_TRUE(FPDFPage_GenerateContent(page)); FPDF_ClosePage(page); FPDF_CloseDocument(doc); } -TEST_F(PDFEditTest, NewImgeObjGenerateContent) { +TEST_F(PDFEditTest, NewImageObjGenerateContent) { FPDF_DOCUMENT doc = FPDF_CreateNewDocument(); FPDF_PAGE page = FPDFPage_New(doc, 0, 100, 100); - EXPECT_EQ(0, FPDFPage_CountObject(page)); + EXPECT_EQ(0, FPDFPage_CountObjects(page)); constexpr int kBitmapSize = 50; FPDF_BITMAP bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 0); @@ -60,12 +57,12 @@ TEST_F(PDFEditTest, NewImgeObjGenerateContent) { EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(bitmap)); EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(bitmap)); - FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImgeObj(doc); + FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImageObj(doc); ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, page_image, bitmap)); ASSERT_TRUE( FPDFImageObj_SetMatrix(page_image, kBitmapSize, 0, 0, kBitmapSize, 0, 0)); FPDFPage_InsertObject(page, page_image); - EXPECT_EQ(1, FPDFPage_CountObject(page)); + EXPECT_EQ(1, FPDFPage_CountObjects(page)); EXPECT_TRUE(FPDFPage_GenerateContent(page)); FPDFBitmap_Destroy(bitmap); diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp index 63740ba083f96c69b0718e158ad120ef7cf988ae..a032bf6607218cf815eb4e219c5eb4911250340f 100644 --- a/fpdfsdk/fpdfeditpage.cpp +++ b/fpdfsdk/fpdfeditpage.cpp @@ -26,6 +26,7 @@ #include "core/fpdfdoc/cpdf_annotlist.h" #include "fpdfsdk/fsdk_define.h" #include "public/fpdf_formfill.h" +#include "third_party/base/logging.h" #include "third_party/base/stl_util.h" #ifdef PDF_ENABLE_XFA @@ -33,7 +34,7 @@ #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" #endif // PDF_ENABLE_XFA -#if _FX_OS_ == _FX_ANDROID_ +#if _FX_OS_ == _FX_OS_ANDROID_ #include #else #include @@ -60,51 +61,83 @@ bool IsPageObject(CPDF_Page* pPage) { return pObject && !pObject->GetString().Compare("Page"); } +void CalcBoundingBox(CPDF_PageObject* pPageObj) { + switch (pPageObj->GetType()) { + case CPDF_PageObject::TEXT: { + break; + } + case CPDF_PageObject::PATH: { + CPDF_PathObject* pPathObj = pPageObj->AsPath(); + pPathObj->CalcBoundingBox(); + break; + } + case CPDF_PageObject::IMAGE: { + CPDF_ImageObject* pImageObj = pPageObj->AsImage(); + pImageObj->CalcBoundingBox(); + break; + } + case CPDF_PageObject::SHADING: { + CPDF_ShadingObject* pShadingObj = pPageObj->AsShading(); + pShadingObj->CalcBoundingBox(); + break; + } + case CPDF_PageObject::FORM: { + CPDF_FormObject* pFormObj = pPageObj->AsForm(); + pFormObj->CalcBoundingBox(); + break; + } + default: { + NOTREACHED(); + break; + } + } +} + } // namespace -DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument() { - CPDF_Document* pDoc = new CPDF_Document(nullptr); +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument() { + auto pDoc = pdfium::MakeUnique(nullptr); pDoc->CreateNewDoc(); - time_t currentTime; - - CFX_ByteString DateStr; + time_t currentTime; + ByteString DateStr; if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) { - if (-1 != time(¤tTime)) { + if (time(¤tTime) != -1) { tm* pTM = localtime(¤tTime); if (pTM) { - DateStr.Format("D:%04d%02d%02d%02d%02d%02d", pTM->tm_year + 1900, - pTM->tm_mon + 1, pTM->tm_mday, pTM->tm_hour, pTM->tm_min, - pTM->tm_sec); + DateStr = ByteString::Format( + "D:%04d%02d%02d%02d%02d%02d", pTM->tm_year + 1900, pTM->tm_mon + 1, + pTM->tm_mday, pTM->tm_hour, pTM->tm_min, pTM->tm_sec); } } } - CPDF_Dictionary* pInfoDict = nullptr; - pInfoDict = pDoc->GetInfo(); + CPDF_Dictionary* pInfoDict = pDoc->GetInfo(); if (pInfoDict) { if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) pInfoDict->SetNewFor("CreationDate", DateStr, false); pInfoDict->SetNewFor("Creator", L"PDFium"); } - return FPDFDocumentFromCPDFDocument(pDoc); + // Caller takes ownership of pDoc. + return FPDFDocumentFromCPDFDocument(pDoc.release()); } -DLLEXPORT void STDCALL FPDFPage_Delete(FPDF_DOCUMENT document, int page_index) { +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_Delete(FPDF_DOCUMENT document, + int page_index) { if (UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document)) pDoc->DeletePage(page_index); } -DLLEXPORT FPDF_PAGE STDCALL FPDFPage_New(FPDF_DOCUMENT document, - int page_index, - double width, - double height) { +FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDFPage_New(FPDF_DOCUMENT document, + int page_index, + double width, + double height) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return nullptr; - page_index = std::min(std::max(page_index, 0), pDoc->GetPageCount()); + page_index = pdfium::clamp(page_index, 0, pDoc->GetPageCount()); CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(page_index); if (!pPageDict) return nullptr; @@ -112,46 +145,31 @@ DLLEXPORT FPDF_PAGE STDCALL FPDFPage_New(FPDF_DOCUMENT document, CPDF_Array* pMediaBoxArray = pPageDict->SetNewFor("MediaBox"); pMediaBoxArray->AddNew(0); pMediaBoxArray->AddNew(0); - pMediaBoxArray->AddNew(static_cast(width)); - pMediaBoxArray->AddNew(static_cast(height)); + pMediaBoxArray->AddNew(static_cast(width)); + pMediaBoxArray->AddNew(static_cast(height)); pPageDict->SetNewFor("Rotate", 0); pPageDict->SetNewFor("Resources"); #ifdef PDF_ENABLE_XFA - CPDFXFA_Page* pPage = - new CPDFXFA_Page(static_cast(document), page_index); - pPage->LoadPDFPage(pPageDict); + auto pXFAPage = pdfium::MakeRetain( + static_cast(document), page_index); + pXFAPage->LoadPDFPage(pPageDict); + return pXFAPage.Leak(); // Caller takes ownership. #else // PDF_ENABLE_XFA - CPDF_Page* pPage = new CPDF_Page(pDoc, pPageDict, true); + auto pPage = pdfium::MakeUnique(pDoc, pPageDict, true); pPage->ParseContent(); + return pPage.release(); // Caller takes ownership. #endif // PDF_ENABLE_XFA - - return pPage; } -DLLEXPORT int STDCALL FPDFPage_GetRotation(FPDF_PAGE page) { +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetRotation(FPDF_PAGE page) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); - if (!IsPageObject(pPage)) - return -1; - - CPDF_Dictionary* pDict = pPage->m_pFormDict; - while (pDict) { - if (pDict->KeyExist("Rotate")) { - CPDF_Object* pRotateObj = pDict->GetObjectFor("Rotate")->GetDirect(); - return pRotateObj ? pRotateObj->GetInteger() / 90 : 0; - } - if (!pDict->KeyExist("Parent")) - break; - - pDict = ToDictionary(pDict->GetObjectFor("Parent")->GetDirect()); - } - - return 0; + return IsPageObject(pPage) ? pPage->GetPageRotation() : -1; } -DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page, - FPDF_PAGEOBJECT page_obj) { - CPDF_PageObject* pPageObj = reinterpret_cast(page_obj); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertObject(FPDF_PAGE page, + FPDF_PAGEOBJECT page_obj) { + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_obj); if (!pPageObj) return; @@ -159,65 +177,45 @@ DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page, CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!IsPageObject(pPage)) return; - + pPageObj->SetDirty(true); pPage->GetPageObjectList()->push_back(std::move(pPageObjHolder)); - switch (pPageObj->GetType()) { - case CPDF_PageObject::TEXT: { - break; - } - case CPDF_PageObject::PATH: { - CPDF_PathObject* pPathObj = pPageObj->AsPath(); - pPathObj->CalcBoundingBox(); - break; - } - case CPDF_PageObject::IMAGE: { - CPDF_ImageObject* pImageObj = pPageObj->AsImage(); - pImageObj->CalcBoundingBox(); - break; - } - case CPDF_PageObject::SHADING: { - CPDF_ShadingObject* pShadingObj = pPageObj->AsShading(); - pShadingObj->CalcBoundingBox(); - break; - } - case CPDF_PageObject::FORM: { - CPDF_FormObject* pFormObj = pPageObj->AsForm(); - pFormObj->CalcBoundingBox(); - break; - } - default: { - ASSERT(false); - break; - } - } + CalcBoundingBox(pPageObj); +} + +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObject(FPDF_PAGE page) { + return FPDFPage_CountObjects(page); } -DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page) { +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObjects(FPDF_PAGE page) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!IsPageObject(pPage)) return -1; return pdfium::CollectionSize(*pPage->GetPageObjectList()); } -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPage_GetObject(FPDF_PAGE page, - int index) { +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPage_GetObject(FPDF_PAGE page, + int index) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!IsPageObject(pPage)) return nullptr; return pPage->GetPageObjectList()->GetPageObjectByIndex(index); } -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_HasTransparency(FPDF_PAGE page) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_HasTransparency(FPDF_PAGE page) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); return pPage && pPage->BackgroundAlphaNeeded(); } -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDFPageObj_Destroy(FPDF_PAGEOBJECT page_obj) { + delete CPDFPageObjectFromFPDFPageObject(page_obj); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) { if (!pageObject) return false; - CPDF_PageObject* pPageObj = reinterpret_cast(pageObject); + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(pageObject); int blend_type = pPageObj->m_GeneralState.GetBlendType(); if (blend_type != FXDIB_BLEND_NORMAL) return true; @@ -237,7 +235,7 @@ FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) { if (pPageObj->IsForm()) { const CPDF_Form* pForm = pPageObj->AsForm()->form(); if (pForm) { - int trans = pForm->m_Transparency; + int trans = pForm->m_iTransparency; if ((trans & PDFTRANS_ISOLATED) || (trans & PDFTRANS_GROUP)) return true; } @@ -246,7 +244,15 @@ FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) { return false; } -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page) { +FPDF_EXPORT int FPDF_CALLCONV FPDFPageObj_GetType(FPDF_PAGEOBJECT pageObject) { + if (!pageObject) + return FPDF_PAGEOBJ_UNKNOWN; + + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(pageObject); + return pPageObj->GetType(); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GenerateContent(FPDF_PAGE page) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!IsPageObject(pPage)) return false; @@ -256,29 +262,40 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page) { return true; } -DLLEXPORT void STDCALL FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object, - double a, - double b, - double c, - double d, - double e, - double f) { - CPDF_PageObject* pPageObj = reinterpret_cast(page_object); +FPDF_EXPORT void FPDF_CALLCONV +FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object, + double a, + double b, + double c, + double d, + double e, + double f) { + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object); if (!pPageObj) return; - CFX_Matrix matrix((FX_FLOAT)a, (FX_FLOAT)b, (FX_FLOAT)c, (FX_FLOAT)d, - (FX_FLOAT)e, (FX_FLOAT)f); + CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e, (float)f); pPageObj->Transform(matrix); } -DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page, - double a, - double b, - double c, - double d, - double e, - double f) { +FPDF_EXPORT void FPDF_CALLCONV +FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page_object, + FPDF_BYTESTRING blend_mode) { + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object); + if (!pPageObj) + return; + + pPageObj->m_GeneralState.SetBlendMode(blend_mode); + pPageObj->SetDirty(true); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_TransformAnnots(FPDF_PAGE page, + double a, + double b, + double c, + double d, + double e, + double f) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return; @@ -286,30 +303,67 @@ DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page, CPDF_AnnotList AnnotList(pPage); for (size_t i = 0; i < AnnotList.Count(); ++i) { CPDF_Annot* pAnnot = AnnotList.GetAt(i); - CFX_FloatRect rect = pAnnot->GetRect(); // transformAnnots Rectangle - CFX_Matrix matrix((FX_FLOAT)a, (FX_FLOAT)b, (FX_FLOAT)c, (FX_FLOAT)d, - (FX_FLOAT)e, (FX_FLOAT)f); - matrix.TransformRect(rect); - - CPDF_Array* pRectArray = pAnnot->GetAnnotDict()->GetArrayFor("Rect"); - if (!pRectArray) - pRectArray = pAnnot->GetAnnotDict()->SetNewFor("Rect"); - - pRectArray->SetNewAt(0, rect.left); - pRectArray->SetNewAt(1, rect.bottom); - pRectArray->SetNewAt(2, rect.right); - pRectArray->SetNewAt(3, rect.top); + CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e, + (float)f); + CFX_FloatRect rect = matrix.TransformRect(pAnnot->GetRect()); + + CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); + CPDF_Array* pRectArray = pAnnotDict->GetArrayFor("Rect"); + if (pRectArray) + pRectArray->Clear(); + else + pRectArray = pAnnotDict->SetNewFor("Rect"); + + pRectArray->AddNew(rect.left); + pRectArray->AddNew(rect.bottom); + pRectArray->AddNew(rect.right); + pRectArray->AddNew(rect.top); // TODO(unknown): Transform AP's rectangle } } -DLLEXPORT void STDCALL FPDFPage_SetRotation(FPDF_PAGE page, int rotate) { +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetRotation(FPDF_PAGE page, + int rotate) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!IsPageObject(pPage)) return; - CPDF_Dictionary* pDict = pPage->m_pFormDict; rotate %= 4; - pDict->SetNewFor("Rotate", rotate * 90); + pPage->m_pFormDict->SetNewFor("Rotate", rotate * 90); +} + +FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + if (!page_object || R > 255 || G > 255 || B > 255 || A > 255) + return false; + + float rgb[3] = {R / 255.f, G / 255.f, B / 255.f}; + auto* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object); + pPageObj->m_GeneralState.SetFillAlpha(A / 255.f); + pPageObj->m_ColorState.SetFillColor( + CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); + pPageObj->SetDirty(true); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObj_GetBounds(FPDF_PAGEOBJECT pageObject, + float* left, + float* bottom, + float* right, + float* top) { + if (!pageObject) + return false; + + CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(pageObject); + CFX_FloatRect bbox = pPageObj->GetRect(); + *left = bbox.left; + *bottom = bbox.bottom; + *right = bbox.right; + *top = bbox.top; + return true; } diff --git a/fpdfsdk/fpdfeditpath.cpp b/fpdfsdk/fpdfeditpath.cpp index 074f083bb182992bbaf55393a8fa45ab174d4086..a291987dce943ce497c823dd0e2fcb4caf493df8 100644 --- a/fpdfsdk/fpdfeditpath.cpp +++ b/fpdfsdk/fpdfeditpath.cpp @@ -2,125 +2,210 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "public/fpdf_edit.h" #include "core/fpdfapi/page/cpdf_path.h" #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fxcrt/fx_system.h" +#include "fpdfsdk/fsdk_define.h" +#include "third_party/base/ptr_util.h" + +// These checks are here because core/ and public/ cannot depend on each other. +static_assert(CFX_GraphStateData::LineCapButt == FPDF_LINECAP_BUTT, + "CFX_GraphStateData::LineCapButt value mismatch"); +static_assert(CFX_GraphStateData::LineCapRound == FPDF_LINECAP_ROUND, + "CFX_GraphStateData::LineCapRound value mismatch"); +static_assert(CFX_GraphStateData::LineCapSquare == + FPDF_LINECAP_PROJECTING_SQUARE, + "CFX_GraphStateData::LineCapSquare value mismatch"); + +static_assert(CFX_GraphStateData::LineJoinMiter == FPDF_LINEJOIN_MITER, + "CFX_GraphStateData::LineJoinMiter value mismatch"); +static_assert(CFX_GraphStateData::LineJoinRound == FPDF_LINEJOIN_ROUND, + "CFX_GraphStateData::LineJoinRound value mismatch"); +static_assert(CFX_GraphStateData::LineJoinBevel == FPDF_LINEJOIN_BEVEL, + "CFX_GraphStateData::LineJoinBevel value mismatch"); -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewPath(float x, float y) { - CPDF_PathObject* pPathObj = new CPDF_PathObject; +static_assert(static_cast(FXPT_TYPE::LineTo) == FPDF_SEGMENT_LINETO, + "FXPT_TYPE::LineTo value mismatch"); +static_assert(static_cast(FXPT_TYPE::BezierTo) == FPDF_SEGMENT_BEZIERTO, + "FXPT_TYPE::BezierTo value mismatch"); +static_assert(static_cast(FXPT_TYPE::MoveTo) == FPDF_SEGMENT_MOVETO, + "FXPT_TYPE::MoveTo value mismatch"); + +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPageObj_CreateNewPath(float x, + float y) { + auto pPathObj = pdfium::MakeUnique(); pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::MoveTo, false); pPathObj->DefaultStates(); - return pPathObj; + return pPathObj.release(); // Caller takes ownership. } -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewRect(float x, - float y, - float w, - float h) { - CPDF_PathObject* pPathObj = new CPDF_PathObject; +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPageObj_CreateNewRect(float x, + float y, + float w, + float h) { + auto pPathObj = pdfium::MakeUnique(); pPathObj->m_Path.AppendRect(x, y, x + w, y + h); pPathObj->DefaultStates(); - return pPathObj; + return pPathObj.release(); // Caller takes ownership. } -DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, - unsigned int R, - unsigned int G, - unsigned int B, - unsigned int A) { - if (!path || R > 255 || G > 255 || B > 255 || A > 255) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj || R > 255 || G > 255 || B > 255 || A > 255) return false; - auto pPathObj = reinterpret_cast(path); + float rgb[3] = {R / 255.f, G / 255.f, B / 255.f}; pPathObj->m_GeneralState.SetStrokeAlpha(A / 255.f); - FX_FLOAT rgb[3] = {R / 255.f, G / 255.f, B / 255.f}; pPathObj->m_ColorState.SetStrokeColor( CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); + pPathObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width) { - if (!path || width < 0.0f) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPath_GetStrokeColor(FPDF_PAGEOBJECT path, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj || !R || !G || !B || !A) + return false; + + uint32_t strokeRGB = pPathObj->m_ColorState.GetStrokeRGB(); + *R = FXSYS_GetRValue(strokeRGB); + *G = FXSYS_GetGValue(strokeRGB); + *B = FXSYS_GetBValue(strokeRGB); + *A = static_cast( + (pPathObj->m_GeneralState.GetStrokeAlpha() * 255.f) + 0.5f); + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj || width < 0.0f) return false; - auto pPathObj = reinterpret_cast(path); pPathObj->m_GraphState.SetLineWidth(width); + pPathObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_SetFillColor(FPDF_PAGEOBJECT path, - unsigned int R, - unsigned int G, - unsigned int B, - unsigned int A) { - if (!path || R > 255 || G > 255 || B > 255 || A > 255) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetFillColor(FPDF_PAGEOBJECT path, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + return FPDFPageObj_SetFillColor(path, R, G, B, A); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_GetFillColor(FPDF_PAGEOBJECT path, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj || !R || !G || !B || !A) return false; - auto pPathObj = reinterpret_cast(path); - pPathObj->m_GeneralState.SetFillAlpha(A / 255.f); - FX_FLOAT rgb[3] = {R / 255.f, G / 255.f, B / 255.f}; - pPathObj->m_ColorState.SetFillColor( - CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); + uint32_t fillRGB = pPathObj->m_ColorState.GetFillRGB(); + *R = FXSYS_GetRValue(fillRGB); + *G = FXSYS_GetGValue(fillRGB); + *B = FXSYS_GetBValue(fillRGB); + *A = static_cast( + (pPathObj->m_GeneralState.GetFillAlpha() * 255.f) + 0.5f); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_MoveTo(FPDF_PAGEOBJECT path, float x, float y) { - if (!path) +FPDF_EXPORT int FPDF_CALLCONV FPDFPath_CountSegments(FPDF_PAGEOBJECT path) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) + return -1; + return pdfium::CollectionSize(pPathObj->m_Path.GetPoints()); +} + +FPDF_EXPORT FPDF_PATHSEGMENT FPDF_CALLCONV +FPDFPath_GetPathSegment(FPDF_PAGEOBJECT path, int index) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) + return nullptr; + + const std::vector& points = pPathObj->m_Path.GetPoints(); + return pdfium::IndexInBounds(points, index) ? &points[index] : nullptr; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_MoveTo(FPDF_PAGEOBJECT path, + float x, + float y) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) return false; - auto pPathObj = reinterpret_cast(path); pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::MoveTo, false); + pPathObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_LineTo(FPDF_PAGEOBJECT path, float x, float y) { - if (!path) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_LineTo(FPDF_PAGEOBJECT path, + float x, + float y) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) return false; - auto pPathObj = reinterpret_cast(path); pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::LineTo, false); + pPathObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_BezierTo(FPDF_PAGEOBJECT path, - float x1, - float y1, - float x2, - float y2, - float x3, - float y3) { - if (!path) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_BezierTo(FPDF_PAGEOBJECT path, + float x1, + float y1, + float x2, + float y2, + float x3, + float y3) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) return false; - auto pPathObj = reinterpret_cast(path); pPathObj->m_Path.AppendPoint(CFX_PointF(x1, y1), FXPT_TYPE::BezierTo, false); pPathObj->m_Path.AppendPoint(CFX_PointF(x2, y2), FXPT_TYPE::BezierTo, false); pPathObj->m_Path.AppendPoint(CFX_PointF(x3, y3), FXPT_TYPE::BezierTo, false); + pPathObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_Close(FPDF_PAGEOBJECT path) { - if (!path) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_Close(FPDF_PAGEOBJECT path) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) return false; - auto pPathObj = reinterpret_cast(path); if (pPathObj->m_Path.GetPoints().empty()) return false; pPathObj->m_Path.ClosePath(); + pPathObj->SetDirty(true); return true; } -DLLEXPORT FPDF_BOOL FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, - int fillmode, - FPDF_BOOL stroke) { - if (!path) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, + int fillmode, + FPDF_BOOL stroke) { + auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path); + if (!pPathObj) return false; - auto pPathObj = reinterpret_cast(path); - if (fillmode == FPDF_FILLMODE_ALTERNATE) pPathObj->m_FillType = FXFILL_ALTERNATE; else if (fillmode == FPDF_FILLMODE_WINDING) @@ -128,5 +213,65 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, else pPathObj->m_FillType = 0; pPathObj->m_bStroke = stroke != 0; + pPathObj->SetDirty(true); + return true; +} + +FPDF_EXPORT void FPDF_CALLCONV FPDFPath_SetLineJoin(FPDF_PAGEOBJECT path, + int line_join) { + if (!path) + return; + if (line_join < + static_cast(CFX_GraphStateData::LineJoin::LineJoinMiter) || + line_join > + static_cast(CFX_GraphStateData::LineJoin::LineJoinBevel)) { + return; + } + auto* pPathObj = CPDFPageObjectFromFPDFPageObject(path); + CFX_GraphStateData::LineJoin lineJoin = + static_cast(line_join); + pPathObj->m_GraphState.SetLineJoin(lineJoin); + pPathObj->SetDirty(true); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDFPath_SetLineCap(FPDF_PAGEOBJECT path, + int line_cap) { + if (!path) + return; + if (line_cap < static_cast(CFX_GraphStateData::LineCap::LineCapButt) || + line_cap > static_cast(CFX_GraphStateData::LineCap::LineCapSquare)) { + return; + } + auto* pPathObj = CPDFPageObjectFromFPDFPageObject(path); + CFX_GraphStateData::LineCap lineCap = + static_cast(line_cap); + pPathObj->m_GraphState.SetLineCap(lineCap); + pPathObj->SetDirty(true); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPathSegment_GetPoint(FPDF_PATHSEGMENT segment, float* x, float* y) { + auto* pPathPoint = FXPathPointFromFPDFPathSegment(segment); + if (!pPathPoint || !x || !y) + return false; + + *x = pPathPoint->m_Point.x; + *y = pPathPoint->m_Point.y; + return true; } + +FPDF_EXPORT int FPDF_CALLCONV +FPDFPathSegment_GetType(FPDF_PATHSEGMENT segment) { + auto* pPathPoint = FXPathPointFromFPDFPathSegment(segment); + + return pPathPoint ? static_cast(pPathPoint->m_Type) + : FPDF_SEGMENT_UNKNOWN; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPathSegment_GetClose(FPDF_PATHSEGMENT segment) { + auto* pPathPoint = FXPathPointFromFPDFPathSegment(segment); + + return pPathPoint ? pPathPoint->m_CloseFigure : false; +} diff --git a/fpdfsdk/fpdfeditpath_embeddertest.cpp b/fpdfsdk/fpdfeditpath_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59e5dbbabff4257ae5a27797f55c4a0e57e4d197 --- /dev/null +++ b/fpdfsdk/fpdfeditpath_embeddertest.cpp @@ -0,0 +1,63 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/fx_system.h" +#include "public/fpdf_edit.h" +#include "testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +class FPDFEditPathEmbedderTest : public EmbedderTest {}; + +TEST_F(FPDFEditPathEmbedderTest, VerifyCorrectColoursReturned) { + CreateEmptyDocument(); + FPDF_PAGE page = FPDFPage_New(document(), 0, 612, 792); + + for (size_t i = 0; i < 256; ++i) { + FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100); + EXPECT_TRUE(FPDFPath_SetFillColor(path, i, i, i, i)); + EXPECT_TRUE(FPDFPath_SetStrokeColor(path, i, i, i, i)); + EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 0)); + EXPECT_TRUE(FPDFPath_LineTo(path, 400, 200)); + EXPECT_TRUE(FPDFPath_LineTo(path, 300, 100)); + EXPECT_TRUE(FPDFPath_Close(path)); + + FPDFPage_InsertObject(page, path); + } + + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + FPDF_ClosePage(page); + page = nullptr; + + OpenSavedDocument(); + page = LoadSavedPage(0); + ASSERT(page); + + for (size_t i = 0; i < 256; ++i) { + FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, i); + ASSERT(path); + + EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path)); + + unsigned int r; + unsigned int g; + unsigned int b; + unsigned int a; + FPDFPath_GetFillColor(path, &r, &g, &b, &a); + EXPECT_EQ(i, r); + EXPECT_EQ(i, g); + EXPECT_EQ(i, b); + EXPECT_EQ(i, a); + + FPDFPath_GetStrokeColor(path, &r, &g, &b, &a); + EXPECT_EQ(i, r); + EXPECT_EQ(i, g); + EXPECT_EQ(i, b); + EXPECT_EQ(i, a); + } + + CloseSavedPage(page); + CloseSavedDocument(); +} diff --git a/fpdfsdk/fpdfedittext.cpp b/fpdfsdk/fpdfedittext.cpp index 8bf0a0ac467408184a2e20397ef6818049950d5f..22c6266ec19d9edb0e83d3a5ce448e43ba8a8190 100644 --- a/fpdfsdk/fpdfedittext.cpp +++ b/fpdfsdk/fpdfedittext.cpp @@ -2,11 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include +#include #include +#include #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/font/cpdf_font.h" #include "core/fpdfapi/font/cpdf_type1font.h" +#include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_textobject.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" @@ -15,92 +19,34 @@ #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fxcrt/fx_extension.h" #include "core/fxge/cfx_fontmgr.h" #include "core/fxge/fx_font.h" #include "fpdfsdk/fsdk_define.h" #include "public/fpdf_edit.h" -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_NewTextObj(FPDF_DOCUMENT document, - FPDF_BYTESTRING font, - float font_size) { - CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); - if (!pDoc) - return nullptr; - - CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc, CFX_ByteStringC(font)); - if (!pFont) - return nullptr; - - CPDF_TextObject* pTextObj = new CPDF_TextObject; - pTextObj->m_TextState.SetFont(pFont); - pTextObj->m_TextState.SetFontSize(font_size); - pTextObj->DefaultStates(); - return pTextObj; -} - -DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object, - FPDF_BYTESTRING text) { - if (!text_object) - return false; - - auto pTextObj = reinterpret_cast(text_object); - pTextObj->SetText(CFX_ByteString(text)); - return true; -} - -DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadType1Font(FPDF_DOCUMENT document, - const uint8_t* data, - uint32_t size) { - CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); - if (!pDoc || !data || size == 0) - return nullptr; +namespace { - auto pFont = pdfium::MakeUnique(); - - // TODO(npm): Maybe use FT_Get_X11_Font_Format to check format? - if (!pFont->LoadEmbedded(data, size)) - return nullptr; - - CPDF_Dictionary* fontDict = pDoc->NewIndirect(); - fontDict->SetNewFor("Type", "Font"); - fontDict->SetNewFor("Subtype", "Type1"); - CFX_ByteString name = pFont->GetFaceName(); - if (name.IsEmpty()) - name = "Unnamed"; - fontDict->SetNewFor("BaseFont", name); - - uint32_t glyphIndex; - int currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex); - fontDict->SetNewFor("FirstChar", currentChar); - int nextChar; - CPDF_Array* widthsArray = pDoc->NewIndirect(); - while (true) { - int width = pFont->GetGlyphWidth(glyphIndex); - widthsArray->AddNew(width); - nextChar = FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex); - if (glyphIndex == 0) - break; - for (int i = currentChar + 1; i < nextChar; i++) - widthsArray->AddNew(0); - currentChar = nextChar; - } - fontDict->SetNewFor("LastChar", currentChar); - fontDict->SetNewFor("Widths", pDoc, widthsArray->GetObjNum()); +CPDF_Dictionary* LoadFontDesc(CPDF_Document* pDoc, + const ByteString& font_name, + CFX_Font* pFont, + const uint8_t* data, + uint32_t size, + int font_type) { CPDF_Dictionary* fontDesc = pDoc->NewIndirect(); fontDesc->SetNewFor("Type", "FontDescriptor"); - fontDesc->SetNewFor("FontName", name); + fontDesc->SetNewFor("FontName", font_name); int flags = 0; if (FXFT_Is_Face_fixedwidth(pFont->GetFace())) flags |= FXFONT_FIXED_PITCH; - if (name.Find("Serif") > -1) + if (font_name.Contains("Serif")) flags |= FXFONT_SERIF; if (FXFT_Is_Face_Italic(pFont->GetFace())) flags |= FXFONT_ITALIC; if (FXFT_Is_Face_Bold(pFont->GetFace())) flags |= FXFONT_BOLD; - // TODO(npm): How do I know if a Type1 font is symbolic, script, allcap, - // smallcap + // TODO(npm): How do I know if a font is symbolic, script, allcap, smallcap flags |= FXFONT_NONSYMBOLIC; fontDesc->SetNewFor("Flags", flags); @@ -108,9 +54,9 @@ DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadType1Font(FPDF_DOCUMENT document, pFont->GetBBox(bbox); auto pBBox = pdfium::MakeUnique(); pBBox->AddNew(bbox.left); - pBBox->AddNew(bbox.bottom); - pBBox->AddNew(bbox.right); pBBox->AddNew(bbox.top); + pBBox->AddNew(bbox.right); + pBBox->AddNew(bbox.bottom); fontDesc->SetFor("FontBBox", std::move(pBBox)); // TODO(npm): calculate italic angle correctly @@ -125,8 +71,429 @@ DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadType1Font(FPDF_DOCUMENT document, CPDF_Stream* pStream = pDoc->NewIndirect(); pStream->SetData(data, size); - fontDesc->SetNewFor("FontFile", pDoc, pStream->GetObjNum()); + // TODO(npm): Lengths for Type1 fonts. + if (font_type == FPDF_FONT_TRUETYPE) { + pStream->GetDict()->SetNewFor("Length1", + static_cast(size)); + } + ByteString fontFile = font_type == FPDF_FONT_TYPE1 ? "FontFile" : "FontFile2"; + fontDesc->SetNewFor(fontFile, pDoc, pStream->GetObjNum()); + return fontDesc; +} + +const char ToUnicodeStart[] = + "/CIDInit /ProcSet findresource begin\n" + "12 dict begin\n" + "begincmap\n" + "/CIDSystemInfo\n" + "<> def\n" + "/CMapName /Adobe-Identity-H def\n" + "CMapType 2 def\n" + "1 begincodespacerange\n" + "<0000> \n" + "endcodespacerange\n"; + +const char ToUnicodeEnd[] = + "endcmap\n" + "CMapName currentdict /CMap defineresource pop\n" + "end\n" + "end\n"; + +void AddCharcode(std::ostringstream* pBuffer, uint32_t number) { + ASSERT(number <= 0xFFFF); + *pBuffer << "<"; + char ans[4]; + FXSYS_IntToFourHexChars(number, ans); + for (size_t i = 0; i < 4; ++i) + *pBuffer << ans[i]; + *pBuffer << ">"; +} + +// PDF spec 1.7 Section 5.9.2: "Unicode character sequences as expressed in +// UTF-16BE encoding." See https://en.wikipedia.org/wiki/UTF-16#Description +void AddUnicode(std::ostringstream* pBuffer, uint32_t unicode) { + if (unicode >= 0xD800 && unicode <= 0xDFFF) + unicode = 0; + + char ans[8]; + *pBuffer << "<"; + size_t numChars = FXSYS_ToUTF16BE(unicode, ans); + for (size_t i = 0; i < numChars; ++i) + *pBuffer << ans[i]; + *pBuffer << ">"; +} + +// Loads the charcode to unicode mapping into a stream +CPDF_Stream* LoadUnicode(CPDF_Document* pDoc, + const std::map& to_unicode) { + // A map charcode->unicode + std::map char_to_uni; + // A map to vector v of unicode characters of size (end + // - start + 1). This abbreviates: start->v[0], start+1->v[1], etc. PDF spec + // 1.7 Section 5.9.2 says that only the last byte of the unicode may change. + std::map, std::vector> + map_range_vector; + // A map -> unicode + // This abbreviates: start->unicode, start+1->unicode+1, etc. + // PDF spec 1.7 Section 5.9.2 says that only the last byte of the unicode may + // change. + std::map, uint32_t> map_range; + + // Calculate the maps + for (auto iter = to_unicode.begin(); iter != to_unicode.end(); ++iter) { + uint32_t firstCharcode = iter->first; + uint32_t firstUnicode = iter->second; + if (std::next(iter) == to_unicode.end() || + firstCharcode + 1 != std::next(iter)->first) { + char_to_uni[firstCharcode] = firstUnicode; + continue; + } + ++iter; + uint32_t curCharcode = iter->first; + uint32_t curUnicode = iter->second; + if (curCharcode % 256 == 0) { + char_to_uni[firstCharcode] = firstUnicode; + char_to_uni[curCharcode] = curUnicode; + continue; + } + const size_t maxExtra = 255 - (curCharcode % 256); + auto next_it = std::next(iter); + if (firstUnicode + 1 != curUnicode) { + // Consecutive charcodes mapping to non-consecutive unicodes + std::vector unicodes; + unicodes.push_back(firstUnicode); + unicodes.push_back(curUnicode); + for (size_t i = 0; i < maxExtra; ++i) { + if (next_it == to_unicode.end() || curCharcode + 1 != next_it->first) + break; + ++iter; + ++curCharcode; + unicodes.push_back(iter->second); + next_it = std::next(iter); + } + ASSERT(iter->first - firstCharcode + 1 == unicodes.size()); + map_range_vector[std::make_pair(firstCharcode, iter->first)] = unicodes; + continue; + } + // Consecutive charcodes mapping to consecutive unicodes + for (size_t i = 0; i < maxExtra; ++i) { + if (next_it == to_unicode.end() || curCharcode + 1 != next_it->first || + curUnicode + 1 != next_it->second) { + break; + } + ++iter; + ++curCharcode; + ++curUnicode; + next_it = std::next(iter); + } + map_range[std::make_pair(firstCharcode, curCharcode)] = firstUnicode; + } + std::ostringstream buffer; + buffer << ToUnicodeStart; + // Add maps to buffer + buffer << static_cast(char_to_uni.size()) << " beginbfchar\n"; + for (const auto& iter : char_to_uni) { + AddCharcode(&buffer, iter.first); + buffer << " "; + AddUnicode(&buffer, iter.second); + buffer << "\n"; + } + buffer << "endbfchar\n" + << static_cast(map_range_vector.size() + map_range.size()) + << " beginbfrange\n"; + for (const auto& iter : map_range_vector) { + const std::pair& charcodeRange = iter.first; + AddCharcode(&buffer, charcodeRange.first); + buffer << " "; + AddCharcode(&buffer, charcodeRange.second); + buffer << " ["; + const std::vector& unicodes = iter.second; + for (size_t i = 0; i < unicodes.size(); ++i) { + uint32_t uni = unicodes[i]; + AddUnicode(&buffer, uni); + if (i != unicodes.size() - 1) + buffer << " "; + } + buffer << "]\n"; + } + for (const auto& iter : map_range) { + const std::pair& charcodeRange = iter.first; + AddCharcode(&buffer, charcodeRange.first); + buffer << " "; + AddCharcode(&buffer, charcodeRange.second); + buffer << " "; + AddUnicode(&buffer, iter.second); + buffer << "\n"; + } + buffer << "endbfrange\n"; + buffer << ToUnicodeEnd; + // TODO(npm): Encrypt / Compress? + CPDF_Stream* stream = pDoc->NewIndirect(); + stream->SetData(&buffer); + return stream; +} + +const uint32_t kMaxSimpleFontChar = 0xFF; + +void* LoadSimpleFont(CPDF_Document* pDoc, + std::unique_ptr pFont, + const uint8_t* data, + uint32_t size, + int font_type) { + CPDF_Dictionary* fontDict = pDoc->NewIndirect(); + fontDict->SetNewFor("Type", "Font"); + fontDict->SetNewFor( + "Subtype", font_type == FPDF_FONT_TYPE1 ? "Type1" : "TrueType"); + ByteString name = pFont->GetFaceName(); + if (name.IsEmpty()) + name = "Unnamed"; + fontDict->SetNewFor("BaseFont", name); + + uint32_t glyphIndex; + uint32_t currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex); + if (currentChar > kMaxSimpleFontChar || glyphIndex == 0) + return nullptr; + fontDict->SetNewFor("FirstChar", static_cast(currentChar)); + CPDF_Array* widthsArray = pDoc->NewIndirect(); + while (true) { + widthsArray->AddNew(pFont->GetGlyphWidth(glyphIndex)); + uint32_t nextChar = + FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex); + // Simple fonts have 1-byte charcodes only. + if (nextChar > kMaxSimpleFontChar || glyphIndex == 0) + break; + for (uint32_t i = currentChar + 1; i < nextChar; i++) + widthsArray->AddNew(0); + currentChar = nextChar; + } + fontDict->SetNewFor("LastChar", static_cast(currentChar)); + fontDict->SetNewFor("Widths", pDoc, widthsArray->GetObjNum()); + CPDF_Dictionary* fontDesc = + LoadFontDesc(pDoc, name, pFont.get(), data, size, font_type); + fontDict->SetNewFor("FontDescriptor", pDoc, fontDesc->GetObjNum()); return pDoc->LoadFont(fontDict); } + +const uint32_t kMaxUnicode = 0x10FFFF; + +void* LoadCompositeFont(CPDF_Document* pDoc, + std::unique_ptr pFont, + const uint8_t* data, + uint32_t size, + int font_type) { + CPDF_Dictionary* fontDict = pDoc->NewIndirect(); + fontDict->SetNewFor("Type", "Font"); + fontDict->SetNewFor("Subtype", "Type0"); + // TODO(npm): Get the correct encoding, if it's not identity. + ByteString encoding = "Identity-H"; + fontDict->SetNewFor("Encoding", encoding); + ByteString name = pFont->GetFaceName(); + if (name.IsEmpty()) + name = "Unnamed"; + fontDict->SetNewFor( + "BaseFont", font_type == FPDF_FONT_TYPE1 ? name + "-" + encoding : name); + + CPDF_Dictionary* pCIDFont = pDoc->NewIndirect(); + pCIDFont->SetNewFor("Type", "Font"); + pCIDFont->SetNewFor("Subtype", font_type == FPDF_FONT_TYPE1 + ? "CIDFontType0" + : "CIDFontType2"); + pCIDFont->SetNewFor("BaseFont", name); + + // TODO(npm): Maybe use FT_Get_CID_Registry_Ordering_Supplement to get the + // CIDSystemInfo + CPDF_Dictionary* pCIDSystemInfo = pDoc->NewIndirect(); + pCIDSystemInfo->SetNewFor("Registry", "Adobe"); + pCIDSystemInfo->SetNewFor("Ordering", "Identity"); + pCIDSystemInfo->SetNewFor("Supplement", 0); + pCIDFont->SetNewFor("CIDSystemInfo", pDoc, + pCIDSystemInfo->GetObjNum()); + + CPDF_Dictionary* fontDesc = + LoadFontDesc(pDoc, name, pFont.get(), data, size, font_type); + pCIDFont->SetNewFor("FontDescriptor", pDoc, + fontDesc->GetObjNum()); + + uint32_t glyphIndex; + uint32_t currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex); + // If it doesn't have a single char, just fail + if (glyphIndex == 0 || currentChar > kMaxUnicode) + return nullptr; + + std::map to_unicode; + std::map widths; + while (true) { + if (currentChar > kMaxUnicode) + break; + + widths[glyphIndex] = pFont->GetGlyphWidth(glyphIndex); + to_unicode[glyphIndex] = currentChar; + currentChar = + FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex); + if (glyphIndex == 0) + break; + } + CPDF_Array* widthsArray = pDoc->NewIndirect(); + for (auto it = widths.begin(); it != widths.end(); ++it) { + int ch = it->first; + int w = it->second; + if (std::next(it) == widths.end()) { + // Only one char left, use format c [w] + auto oneW = pdfium::MakeUnique(); + oneW->AddNew(w); + widthsArray->AddNew(ch); + widthsArray->Add(std::move(oneW)); + break; + } + ++it; + int next_ch = it->first; + int next_w = it->second; + if (next_ch == ch + 1 && next_w == w) { + // The array can have a group c_first c_last w: all CIDs in the range from + // c_first to c_last will have width w + widthsArray->AddNew(ch); + ch = next_ch; + while (true) { + auto next_it = std::next(it); + if (next_it == widths.end() || next_it->first != it->first + 1 || + next_it->second != it->second) { + break; + } + ++it; + ch = it->first; + } + widthsArray->AddNew(ch); + widthsArray->AddNew(w); + continue; + } + // Otherwise we can have a group of the form c [w1 w2 ...]: c has width + // w1, c+1 has width w2, etc. + widthsArray->AddNew(ch); + auto curWidthArray = pdfium::MakeUnique(); + curWidthArray->AddNew(w); + curWidthArray->AddNew(next_w); + while (true) { + auto next_it = std::next(it); + if (next_it == widths.end() || next_it->first != it->first + 1) + break; + ++it; + curWidthArray->AddNew(static_cast(it->second)); + } + widthsArray->Add(std::move(curWidthArray)); + } + pCIDFont->SetNewFor("W", pDoc, widthsArray->GetObjNum()); + // TODO(npm): Support vertical writing + + auto pDescendant = pdfium::MakeUnique(); + pDescendant->AddNew(pDoc, pCIDFont->GetObjNum()); + fontDict->SetFor("DescendantFonts", std::move(pDescendant)); + CPDF_Stream* toUnicodeStream = LoadUnicode(pDoc, to_unicode); + fontDict->SetNewFor("ToUnicode", pDoc, + toUnicodeStream->GetObjNum()); + return pDoc->LoadFont(fontDict); +} + +} // namespace + +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFPageObj_NewTextObj(FPDF_DOCUMENT document, + FPDF_BYTESTRING font, + float font_size) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc) + return nullptr; + + CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc, ByteStringView(font)); + if (!pFont) + return nullptr; + + auto pTextObj = pdfium::MakeUnique(); + pTextObj->m_TextState.SetFont(pFont); + pTextObj->m_TextState.SetFontSize(font_size); + pTextObj->DefaultStates(); + return pTextObj.release(); // Caller takes ownership. +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_SetText(FPDF_PAGEOBJECT text_object, FPDF_WIDESTRING text) { + auto* pTextObj = static_cast(text_object); + if (!pTextObj) + return false; + + size_t len = WideString::WStringLength(text); + WideString encodedText = WideString::FromUTF16LE(text, len); + ByteString byteText; + for (wchar_t wc : encodedText) { + pTextObj->GetFont()->AppendChar( + &byteText, pTextObj->GetFont()->CharCodeFromUnicode(wc)); + } + pTextObj->SetText(byteText); + return true; +} + +FPDF_EXPORT FPDF_FONT FPDF_CALLCONV FPDFText_LoadFont(FPDF_DOCUMENT document, + const uint8_t* data, + uint32_t size, + int font_type, + FPDF_BOOL cid) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc || !data || size == 0 || + (font_type != FPDF_FONT_TYPE1 && font_type != FPDF_FONT_TRUETYPE)) { + return nullptr; + } + + auto pFont = pdfium::MakeUnique(); + + // TODO(npm): Maybe use FT_Get_X11_Font_Format to check format? Otherwise, we + // are allowing giving any font that can be loaded on freetype and setting it + // as any font type. + if (!pFont->LoadEmbedded(data, size)) + return nullptr; + + return cid ? LoadCompositeFont(pDoc, std::move(pFont), data, size, font_type) + : LoadSimpleFont(pDoc, std::move(pFont), data, size, font_type); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_SetFillColor(FPDF_PAGEOBJECT text_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + return FPDFPageObj_SetFillColor(text_object, R, G, B, A); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDFFont_Close(FPDF_FONT font) { + CPDF_Font* pFont = static_cast(font); + if (!pFont) + return; + + CPDF_Document* pDoc = pFont->GetDocument(); + if (!pDoc) + return; + + CPDF_DocPageData* pPageData = pDoc->GetPageData(); + if (!pPageData->IsForceClear()) + pPageData->ReleaseFont(pFont->GetFontDict()); +} + +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFPageObj_CreateTextObj(FPDF_DOCUMENT document, + FPDF_FONT font, + float font_size) { + CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + CPDF_Font* pFont = static_cast(font); + if (!pDoc || !pFont) + return nullptr; + + auto pTextObj = pdfium::MakeUnique(); + pTextObj->m_TextState.SetFont(pDoc->LoadFont(pFont->GetFontDict())); + pTextObj->m_TextState.SetFontSize(font_size); + pTextObj->DefaultStates(); + return pTextObj.release(); +} diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp index 57ff6b669c9fefcefe51faad563b7db1c73a91c5..10aecb3fde25850f2e208c6baf788439fc8fcf91 100644 --- a/fpdfsdk/fpdfformfill.cpp +++ b/fpdfsdk/fpdfformfill.cpp @@ -16,7 +16,7 @@ #include "core/fpdfdoc/cpdf_formfield.h" #include "core/fpdfdoc/cpdf_interform.h" #include "core/fpdfdoc/cpdf_occontext.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_interform.h" #include "fpdfsdk/cpdfsdk_pageview.h" @@ -29,11 +29,73 @@ #ifdef PDF_ENABLE_XFA #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +static_assert(static_cast(FormType::kNone) == FORMTYPE_NONE, + "None form types must match"); +static_assert(static_cast(FormType::kAcroForm) == FORMTYPE_ACRO_FORM, + "AcroForm form types must match"); +static_assert(static_cast(FormType::kXFAFull) == FORMTYPE_XFA_FULL, + "XFA full form types must match"); +static_assert(static_cast(FormType::kXFAForeground) == + FORMTYPE_XFA_FOREGROUND, + "XFA foreground form types must match"); #endif // PDF_ENABLE_XFA +static_assert(static_cast(FormFieldType::kUnknown) == + FPDF_FORMFIELD_UNKNOWN, + "Unknown form field types must match"); +static_assert(static_cast(FormFieldType::kPushButton) == + FPDF_FORMFIELD_PUSHBUTTON, + "PushButton form field types must match"); +static_assert(static_cast(FormFieldType::kCheckBox) == + FPDF_FORMFIELD_CHECKBOX, + "CheckBox form field types must match"); +static_assert(static_cast(FormFieldType::kRadioButton) == + FPDF_FORMFIELD_RADIOBUTTON, + "RadioButton form field types must match"); +static_assert(static_cast(FormFieldType::kComboBox) == + FPDF_FORMFIELD_COMBOBOX, + "ComboBox form field types must match"); +static_assert(static_cast(FormFieldType::kListBox) == + FPDF_FORMFIELD_LISTBOX, + "ListBox form field types must match"); +static_assert(static_cast(FormFieldType::kTextField) == + FPDF_FORMFIELD_TEXTFIELD, + "TextField form field types must match"); +static_assert(static_cast(FormFieldType::kSignature) == + FPDF_FORMFIELD_SIGNATURE, + "Signature form field types must match"); +#ifdef PDF_ENABLE_XFA +static_assert(static_cast(FormFieldType::kXFA) == FPDF_FORMFIELD_XFA, + "XFA form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_CheckBox) == + FPDF_FORMFIELD_XFA_CHECKBOX, + "XFA CheckBox form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_ComboBox) == + FPDF_FORMFIELD_XFA_COMBOBOX, + "XFA ComboBox form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_ImageField) == + FPDF_FORMFIELD_XFA_IMAGEFIELD, + "XFA ImageField form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_ListBox) == + FPDF_FORMFIELD_XFA_LISTBOX, + "XFA ListBox form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_PushButton) == + FPDF_FORMFIELD_XFA_PUSHBUTTON, + "XFA PushButton form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_Signature) == + FPDF_FORMFIELD_XFA_SIGNATURE, + "XFA Signature form field types must match"); +static_assert(static_cast(FormFieldType::kXFA_TextField) == + FPDF_FORMFIELD_XFA_TEXTFIELD, + "XFA TextField form field types must match"); +#endif // PDF_ENABLE_XFA +static_assert(kFormFieldTypeCount == FPDF_FORMFIELD_COUNT, + "Number of form field types must match"); + namespace { CPDFSDK_FormFillEnvironment* HandleToCPDFSDKEnvironment( @@ -59,12 +121,12 @@ CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle, } #ifdef PDF_ENABLE_XFA -std::vector* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) { - return reinterpret_cast*>(handle); +std::vector* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) { + return static_cast*>(handle); } -FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector* strings) { - return reinterpret_cast(strings); +FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector* strings) { + return static_cast(strings); } #endif // PDF_ENABLE_XFA @@ -102,67 +164,68 @@ void FFLCommon(FPDF_FORMHANDLE hHandle, pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate); FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y); - std::unique_ptr pDevice(new CFX_FxgeDevice); + auto pDevice = pdfium::MakeUnique(); #ifdef _SKIA_SUPPORT_ pDevice->AttachRecorder(static_cast(recorder)); #endif - pDevice->Attach(CFXBitmapFromFPDFBitmap(bitmap), false, nullptr, false); - pDevice->SaveState(); - pDevice->SetClip_Rect(clip); - - CPDF_RenderOptions options; - if (flags & FPDF_LCD_TEXT) - options.m_Flags |= RENDER_CLEARTYPE; - else - options.m_Flags &= ~RENDER_CLEARTYPE; - - // Grayscale output - if (flags & FPDF_GRAYSCALE) { - options.m_ColorMode = RENDER_COLOR_GRAY; - options.m_ForeColor = 0; - options.m_BackColor = 0xffffff; - } - options.m_AddFlags = flags >> 8; - options.m_bDrawAnnots = flags & FPDF_ANNOT; + RetainPtr holder(CFXBitmapFromFPDFBitmap(bitmap)); + pDevice->Attach(holder, false, nullptr, false); + { + CFX_RenderDevice::StateRestorer restorer(pDevice.get()); + pDevice->SetClip_Rect(clip); + + CPDF_RenderOptions options; + uint32_t option_flags = options.GetFlags(); + if (flags & FPDF_LCD_TEXT) + option_flags |= RENDER_CLEARTYPE; + else + option_flags &= ~RENDER_CLEARTYPE; + options.SetFlags(option_flags); + + // Grayscale output + if (flags & FPDF_GRAYSCALE) + options.SetColorMode(CPDF_RenderOptions::kGray); + + options.SetDrawAnnots(flags & FPDF_ANNOT); #ifdef PDF_ENABLE_XFA - options.m_pOCContext = - pdfium::MakeRetain(pPDFDoc, CPDF_OCContext::View); - if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true)) - pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip); + options.SetOCContext( + pdfium::MakeRetain(pPDFDoc, CPDF_OCContext::View)); + if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true)) + pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip); #else // PDF_ENABLE_XFA - options.m_pOCContext = pdfium::MakeRetain( - pPage->m_pDocument, CPDF_OCContext::View); - if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage)) - pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options); + options.SetOCContext(pdfium::MakeRetain( + pPage->m_pDocument.Get(), CPDF_OCContext::View)); + if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage)) + pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options); #endif // PDF_ENABLE_XFA - - pDevice->RestoreState(false); + } #ifdef _SKIA_SUPPORT_PATHS_ - pDevice->Flush(); - CFXBitmapFromFPDFBitmap(bitmap)->UnPreMultiply(); + pDevice->Flush(true); + holder->UnPreMultiply(); #endif } } // namespace -DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y) { +FPDF_EXPORT int FPDF_CALLCONV +FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { if (!hHandle) return -1; CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (pPage) { - CPDF_InterForm interform(pPage->m_pDocument); + CPDF_InterForm interform(pPage->m_pDocument.Get()); CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint( - pPage, CFX_PointF(static_cast(page_x), - static_cast(page_y)), + pPage, + CFX_PointF(static_cast(page_x), static_cast(page_y)), nullptr); if (!pFormCtrl) return -1; CPDF_FormField* pFormField = pFormCtrl->GetField(); - return pFormField ? pFormField->GetFieldType() : -1; + return pFormField ? static_cast(pFormField->GetFieldType()) : -1; } #ifdef PDF_ENABLE_XFA @@ -188,52 +251,40 @@ DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, if (!pWidgetIterator) return -1; - CXFA_FFWidget* pXFAAnnot = pWidgetIterator->MoveToNext(); - while (pXFAAnnot) { + CXFA_FFWidget* pXFAAnnot; + while ((pXFAAnnot = pWidgetIterator->MoveToNext()) != nullptr) { CFX_RectF rcBBox = pXFAAnnot->GetBBox(0); CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width, rcBBox.top + rcBBox.height); - rcWidget.left -= 1.0f; - rcWidget.right += 1.0f; - rcWidget.bottom -= 1.0f; - rcWidget.top += 1.0f; - - if (rcWidget.Contains(CFX_PointF(static_cast(page_x), - static_cast(page_y)))) { - return FPDF_FORMFIELD_XFA; + rcWidget.Inflate(1.0f, 1.0f); + if (rcWidget.Contains(CFX_PointF(static_cast(page_x), + static_cast(page_y)))) { + return static_cast(pXFAAnnot->GetFormFieldType()); } - pXFAAnnot = pWidgetIterator->MoveToNext(); } #endif // PDF_ENABLE_XFA return -1; } -DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y) { - return FPDFPage_HasFormFieldAtPoint(hHandle, page, page_x, page_y); -} - -DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y) { +FPDF_EXPORT int FPDF_CALLCONV +FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { if (!hHandle) return -1; CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return -1; - CPDF_InterForm interform(pPage->m_pDocument); + CPDF_InterForm interform(pPage->m_pDocument.Get()); int z_order = -1; (void)interform.GetControlAtPoint( - pPage, - CFX_PointF(static_cast(page_x), static_cast(page_y)), + pPage, CFX_PointF(static_cast(page_x), static_cast(page_y)), &z_order); return z_order; } -DLLEXPORT FPDF_FORMHANDLE STDCALL +FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, FPDF_FORMFILLINFO* formInfo) { #ifdef PDF_ENABLE_XFA @@ -256,23 +307,22 @@ FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, return pDocument->GetFormFillEnv(); #endif - CPDFSDK_FormFillEnvironment* pFormFillEnv = - new CPDFSDK_FormFillEnvironment(pDocument, formInfo); + auto pFormFillEnv = + pdfium::MakeUnique(pDocument, formInfo); #ifdef PDF_ENABLE_XFA - pDocument->SetFormFillEnv(pFormFillEnv); + pDocument->SetFormFillEnv(pFormFillEnv.get()); #endif // PDF_ENABLE_XFA - return pFormFillEnv; + return pFormFillEnv.release(); // Caller takes ownership. } -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) { - if (!hHandle) - return; - CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return; #ifdef PDF_ENABLE_XFA // Reset the focused annotations and remove the SDK document from the @@ -283,105 +333,141 @@ FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) { if (pFormFillEnv->GetXFAContext()) pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr); #endif // PDF_ENABLE_XFA - delete pFormFillEnv; } -DLLEXPORT FPDF_BOOL STDCALL FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier); } -DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; - return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier); + return pPageView->OnFocus(CFX_PointF(page_x, page_y), modifier); } -DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; + return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier); +} - CFX_PointF pt((FX_FLOAT)page_x, (FX_FLOAT)page_y); - return pPageView->OnLButtonUp(pt, modifier); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnLButtonUp(CFX_PointF(page_x, page_y), modifier); } #ifdef PDF_ENABLE_XFA -DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; return pPageView->OnRButtonDown(CFX_PointF(page_x, page_y), modifier); } -DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; - - CFX_PointF pt((FX_FLOAT)page_x, (FX_FLOAT)page_y); - return pPageView->OnRButtonUp(pt, modifier); + return pPageView->OnRButtonUp(CFX_PointF(page_x, page_y), modifier); } #endif // PDF_ENABLE_XFA -DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int nKeyCode, - int modifier) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nKeyCode, + int modifier) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; - return pPageView->OnKeyDown(nKeyCode, modifier); } -DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int nKeyCode, - int modifier) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nKeyCode, + int modifier) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; - return pPageView->OnKeyUp(nKeyCode, modifier); } -DLLEXPORT FPDF_BOOL STDCALL FORM_OnChar(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int nChar, - int modifier) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nChar, + int modifier) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return false; - return pPageView->OnChar(nChar, modifier); } -DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FORM_GetSelectedText(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + void* buffer, + unsigned long buflen) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return 0; + + WideString wide_str_form_text = pPageView->GetSelectedText(); + ByteString encoded_form_text = wide_str_form_text.UTF16LE_Encode(); + unsigned long form_text_len = encoded_form_text.GetLength(); + + if (buffer && buflen >= form_text_len) + memcpy(buffer, encoded_form_text.c_str(), form_text_len); + + return form_text_len; +} + +FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + FPDF_WIDESTRING wsText) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return; + + size_t len = WideString::WStringLength(wsText); + WideString wide_str_text = WideString::FromUTF16LE(wsText, len); + + pPageView->ReplaceSelection(wide_str_text); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) { CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); if (!pFormFillEnv) @@ -389,90 +475,86 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) { return pFormFillEnv->KillFocusAnnot(0); } -DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, - FPDF_BITMAP bitmap, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, + FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y, rotate, flags); } #ifdef _SKIA_SUPPORT_ -DLLEXPORT void STDCALL FPDF_FFLRecord(FPDF_FORMHANDLE hHandle, - FPDF_RECORDER recorder, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLRecord(FPDF_FORMHANDLE hHandle, + FPDF_RECORDER recorder, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y, rotate, flags); } #endif #ifdef PDF_ENABLE_XFA -DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Undo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { if (!hWidget || !document) return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; static_cast(hWidget)->Undo(); } -DLLEXPORT void STDCALL FPDF_Widget_Redo(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Redo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { if (!hWidget || !document) return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; static_cast(hWidget)->Redo(); } -DLLEXPORT void STDCALL FPDF_Widget_SelectAll(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_SelectAll(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { if (!hWidget || !document) return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; static_cast(hWidget)->SelectAll(); } -DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget, - FPDF_WIDESTRING wsText, - FPDF_DWORD* size) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Copy(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size) { if (!hWidget || !document) return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; - CFX_WideString wsCpText; - static_cast(hWidget)->Copy(wsCpText); + WideString wsCpText = + static_cast(hWidget)->Copy().value_or(WideString()); - CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode(); + ByteString bsCpText = wsCpText.UTF16LE_Encode(); uint32_t len = bsCpText.GetLength() / sizeof(unsigned short); if (!wsText) { *size = len; @@ -481,30 +563,29 @@ DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document, uint32_t real_size = len < *size ? len : *size; if (real_size > 0) { - FXSYS_memcpy((void*)wsText, - bsCpText.GetBuffer(real_size * sizeof(unsigned short)), - real_size * sizeof(unsigned short)); + memcpy((void*)wsText, + bsCpText.GetBuffer(real_size * sizeof(unsigned short)), + real_size * sizeof(unsigned short)); bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short)); } *size = real_size; } -DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget, - FPDF_WIDESTRING wsText, - FPDF_DWORD* size) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Cut(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size) { if (!hWidget || !document) return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; - CFX_WideString wsCpText; - static_cast(hWidget)->Cut(wsCpText); + WideString wsCpText = + static_cast(hWidget)->Cut().value_or(WideString()); - CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode(); + ByteString bsCpText = wsCpText.UTF16LE_Encode(); uint32_t len = bsCpText.GetLength() / sizeof(unsigned short); if (!wsText) { *size = len; @@ -513,31 +594,30 @@ DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document, uint32_t real_size = len < *size ? len : *size; if (real_size > 0) { - FXSYS_memcpy((void*)wsText, - bsCpText.GetBuffer(real_size * sizeof(unsigned short)), - real_size * sizeof(unsigned short)); + memcpy((void*)wsText, + bsCpText.GetBuffer(real_size * sizeof(unsigned short)), + real_size * sizeof(unsigned short)); bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short)); } *size = real_size; } -DLLEXPORT void STDCALL FPDF_Widget_Paste(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget, - FPDF_WIDESTRING wsText, - FPDF_DWORD size) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Paste(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD size) { if (!hWidget || !document) return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; - CFX_WideString wstr = CFX_WideString::FromUTF16LE(wsText, size); + WideString wstr = WideString::FromUTF16LE(wsText, size); static_cast(hWidget)->Paste(wstr); } -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document, FPDF_WIDGET hWidget, float x, @@ -547,18 +627,17 @@ FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document, return; CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + if (!pContext->ContainsXFAForm()) return; CFX_PointF ptPopup; ptPopup.x = x; ptPopup.y = y; - CFX_ByteStringC bs(bsText); + ByteStringView bs(bsText); static_cast(hWidget)->ReplaceSpellCheckWord(ptPopup, bs); } -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document, FPDF_WIDGET hWidget, float x, @@ -567,26 +646,28 @@ FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document, if (!hWidget || !document) return; - CPDFXFA_Context* pContext = static_cast(document); - if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic && - pContext->GetDocType() != XFA_DOCTYPE_Static) + auto* pContext = static_cast(document); + if (!pContext->ContainsXFAForm()) return; - std::vector* sSuggestWords = new std::vector; CFX_PointF ptPopup; ptPopup.x = x; ptPopup.y = y; - static_cast(hWidget) - ->GetSuggestWords(ptPopup, *sSuggestWords); - *stringHandle = ToFPDFStringHandle(sSuggestWords); + auto sSuggestWords = pdfium::MakeUnique>(); + static_cast(hWidget)->GetSuggestWords(ptPopup, + sSuggestWords.get()); + + // Caller takes ownership. + *stringHandle = ToFPDFStringHandle(sSuggestWords.release()); } -DLLEXPORT int STDCALL FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) { - std::vector* sSuggestWords = FromFPDFStringHandle(sHandle); +FPDF_EXPORT int FPDF_CALLCONV +FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) { + std::vector* sSuggestWords = FromFPDFStringHandle(sHandle); return sSuggestWords ? pdfium::CollectionSize(*sSuggestWords) : -1; } -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle, int index, FPDF_BYTESTRING bsText, @@ -598,7 +679,7 @@ FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle, if (index < 0 || index >= count) return false; - std::vector* sSuggestWords = FromFPDFStringHandle(sHandle); + std::vector* sSuggestWords = FromFPDFStringHandle(sHandle); uint32_t len = (*sSuggestWords)[index].GetLength(); if (!bsText) { *size = len; @@ -607,57 +688,67 @@ FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle, uint32_t real_size = len < *size ? len : *size; if (real_size > 0) - FXSYS_memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size); + memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size); *size = real_size; return true; } -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) { delete FromFPDFStringHandle(stringHandle); } -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle, FPDF_BYTESTRING bsText, FPDF_DWORD size) { if (!stringHandle || !bsText || size == 0) return false; - FromFPDFStringHandle(stringHandle)->push_back(CFX_ByteString(bsText, size)); + FromFPDFStringHandle(stringHandle)->push_back(ByteString(bsText, size)); return true; } #endif // PDF_ENABLE_XFA -DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, - int fieldType, - unsigned long color) { - if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle)) - pInterForm->SetHighlightColor(color, fieldType); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, + int fieldType, + unsigned long color) { + CPDFSDK_InterForm* interForm = FormHandleToInterForm(hHandle); + if (!interForm) + return; + + Optional cast_input = IntToFormFieldType(fieldType); + if (!cast_input) + return; + + if (cast_input.value() == FormFieldType::kUnknown) { + interForm->SetAllHighlightColors(color); + } else { + interForm->SetHighlightColor(color, cast_input.value()); + } } -DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, - unsigned char alpha) { +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha) { if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle)) pInterForm->SetHighlightAlpha(alpha); } -DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) { +FPDF_EXPORT void FPDF_CALLCONV +FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) { if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle)) - pInterForm->RemoveAllHighLight(); + pInterForm->RemoveAllHighLights(); } -DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page, - FPDF_FORMHANDLE hHandle) { +FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle) { if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page)) pPageView->SetValid(true); } -DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page, - FPDF_FORMHANDLE hHandle) { - if (!hHandle) - return; - +FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle) { CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); if (!pFormFillEnv) @@ -675,48 +766,47 @@ DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page, } } -DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) { +FPDF_EXPORT void FPDF_CALLCONV +FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) { CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); if (pFormFillEnv && pFormFillEnv->IsJSInitiated()) pFormFillEnv->ProcJavascriptFun(); } -DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) { +FPDF_EXPORT void FPDF_CALLCONV +FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) { CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); if (pFormFillEnv && pFormFillEnv->IsJSInitiated()) pFormFillEnv->ProcOpenAction(); } -DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, - int aaType) { +FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, + int aaType) { CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); if (!pFormFillEnv) return; CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument(); - CPDF_Dictionary* pDic = pDoc->GetRoot(); - if (!pDic) + const CPDF_Dictionary* pDict = pDoc->GetRoot(); + if (!pDict) return; - CPDF_AAction aa(pDic->GetDictFor("AA")); - if (aa.ActionExist((CPDF_AAction::AActionType)aaType)) { - CPDF_Action action = aa.GetAction((CPDF_AAction::AActionType)aaType); + CPDF_AAction aa(pDict->GetDictFor("AA")); + auto type = static_cast(aaType); + if (aa.ActionExist(type)) { + CPDF_Action action = aa.GetAction(type); CPDFSDK_ActionHandler* pActionHandler = - HandleToCPDFSDKEnvironment(hHandle)->GetActionHander(); - pActionHandler->DoAction_Document(action, (CPDF_AAction::AActionType)aaType, - pFormFillEnv); + HandleToCPDFSDKEnvironment(hHandle)->GetActionHandler(); + pActionHandler->DoAction_Document(action, type, pFormFillEnv); } } -DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page, - FPDF_FORMHANDLE hHandle, - int aaType) { - if (!hHandle) - return; - +FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle, + int aaType) { CPDFSDK_FormFillEnvironment* pFormFillEnv = HandleToCPDFSDKEnvironment(hHandle); if (!pFormFillEnv) @@ -730,20 +820,14 @@ DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page, if (!pFormFillEnv->GetPageView(pPage, false)) return; - CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander(); - CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict; + CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler(); + CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict.Get(); CPDF_AAction aa(pPageDict->GetDictFor("AA")); - if (FPDFPAGE_AACTION_OPEN == aaType) { - if (aa.ActionExist(CPDF_AAction::OpenPage)) { - CPDF_Action action = aa.GetAction(CPDF_AAction::OpenPage); - pActionHandler->DoAction_Page(action, CPDF_AAction::OpenPage, - pFormFillEnv); - } - } else { - if (aa.ActionExist(CPDF_AAction::ClosePage)) { - CPDF_Action action = aa.GetAction(CPDF_AAction::ClosePage); - pActionHandler->DoAction_Page(action, CPDF_AAction::ClosePage, - pFormFillEnv); - } + CPDF_AAction::AActionType type = aaType == FPDFPAGE_AACTION_OPEN + ? CPDF_AAction::OpenPage + : CPDF_AAction::ClosePage; + if (aa.ActionExist(type)) { + CPDF_Action action = aa.GetAction(type); + pActionHandler->DoAction_Page(action, type, pFormFillEnv); } } diff --git a/fpdfsdk/fpdfformfill_embeddertest.cpp b/fpdfsdk/fpdfformfill_embeddertest.cpp index 47f1a75efb87b8fa6dfd23762a03d57acda65e88..ae1c02ede17b1ea43c0a32dd2e22d01314f89095 100644 --- a/fpdfsdk/fpdfformfill_embeddertest.cpp +++ b/fpdfsdk/fpdfformfill_embeddertest.cpp @@ -2,7 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include +#include +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "public/cpp/fpdf_deleters.h" #include "public/fpdf_formfill.h" +#include "public/fpdf_fwlevent.h" #include "testing/embedder_test.h" #include "testing/embedder_test_mock_delegate.h" #include "testing/embedder_test_timer_handling_delegate.h" @@ -10,9 +19,291 @@ #include "testing/gtest/include/gtest/gtest.h" using testing::_; -using testing::Return; -class FPDFFormFillEmbeddertest : public EmbedderTest {}; +using FPDFFormFillEmbeddertest = EmbedderTest; + +// A base class for many related tests that involve clicking and typing into +// form fields. +class FPDFFormFillInteractiveEmbeddertest : public FPDFFormFillEmbeddertest { + protected: + FPDFFormFillInteractiveEmbeddertest() = default; + ~FPDFFormFillInteractiveEmbeddertest() override = default; + + void SetUp() override { + FPDFFormFillEmbeddertest::SetUp(); + ASSERT_TRUE(OpenDocument(GetDocumentName())); + page_ = LoadPage(0); + ASSERT_TRUE(page_); + FormSanityChecks(); + } + + void TearDown() override { + UnloadPage(page_); + FPDFFormFillEmbeddertest::TearDown(); + } + + // Returns the name of the PDF to use. + virtual const char* GetDocumentName() const = 0; + + // Returns the type of field(s) in the PDF. + virtual int GetFormType() const = 0; + + // Optionally do some sanity check on the document after loading. + virtual void FormSanityChecks() {} + + FPDF_PAGE page() { return page_; } + + int GetFormTypeAtPoint(const CFX_PointF& point) { + return FPDFPage_HasFormFieldAtPoint(form_handle(), page_, point.x, point.y); + } + + void ClickOnFormFieldAtPoint(const CFX_PointF& point) { + // Click on the text field or combobox as specified by coordinates. + FORM_OnMouseMove(form_handle(), page_, 0, point.x, point.y); + FORM_OnLButtonDown(form_handle(), page_, 0, point.x, point.y); + FORM_OnLButtonUp(form_handle(), page_, 0, point.x, point.y); + } + + void TypeTextIntoTextField(int num_chars, const CFX_PointF& point) { + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(point)); + ClickOnFormFieldAtPoint(point); + + // Type text starting with 'A' to as many chars as specified by |num_chars|. + for (int i = 0; i < num_chars; ++i) { + FORM_OnChar(form_handle(), page_, 'A' + i, 0); + } + } + + // Navigates to text field using the mouse and then selects text via the + // shift and specfied left or right arrow key. + void SelectTextWithKeyboard(int num_chars, + int arrow_key, + const CFX_PointF& point) { + // Navigate to starting position for selection. + ClickOnFormFieldAtPoint(point); + + // Hold down shift (and don't release until entire text is selected). + FORM_OnKeyDown(form_handle(), page_, FWL_VKEY_Shift, 0); + + // Select text char by char via left or right arrow key. + for (int i = 0; i < num_chars; ++i) { + FORM_OnKeyDown(form_handle(), page_, arrow_key, FWL_EVENTFLAG_ShiftKey); + FORM_OnKeyUp(form_handle(), page_, arrow_key, FWL_EVENTFLAG_ShiftKey); + } + FORM_OnKeyUp(form_handle(), page_, FWL_VKEY_Shift, 0); + } + + // Uses the mouse to navigate to text field and select text. + void SelectTextWithMouse(const CFX_PointF& start, const CFX_PointF& end) { + ASSERT(start.y == end.y); + + // Navigate to starting position and click mouse. + FORM_OnMouseMove(form_handle(), page_, 0, start.x, start.y); + FORM_OnLButtonDown(form_handle(), page_, 0, start.x, start.y); + + // Hold down mouse until reach end of desired selection. + FORM_OnMouseMove(form_handle(), page_, 0, end.x, end.y); + FORM_OnLButtonUp(form_handle(), page_, 0, end.x, end.y); + } + + void CheckSelection(const WideStringView& expected_string) { + // Calculate expected length for selected text. + int num_chars = expected_string.GetLength(); + + // Check actual selection against expected selection. + const unsigned long expected_length = + sizeof(unsigned short) * (num_chars + 1); + unsigned long sel_text_len = + FORM_GetSelectedText(form_handle(), page_, nullptr, 0); + ASSERT_EQ(expected_length, sel_text_len); + + std::vector buf(sel_text_len); + EXPECT_EQ(expected_length, FORM_GetSelectedText(form_handle(), page_, + buf.data(), sel_text_len)); + + EXPECT_EQ(expected_string, WideString::FromUTF16LE(buf.data(), num_chars)); + } + + private: + FPDF_PAGE page_ = nullptr; +}; + +class FPDFFormFillTextFormEmbeddertest + : public FPDFFormFillInteractiveEmbeddertest { + protected: + FPDFFormFillTextFormEmbeddertest() = default; + ~FPDFFormFillTextFormEmbeddertest() override = default; + + const char* GetDocumentName() const override { + // PDF with several form text fields: + // - "Text Box" - Regular text box with no special attributes. + // - "ReadOnly" - Ff: 1. + // - "CharLimit" - MaxLen: 10, V: Elephant. + return "text_form_multiple.pdf"; + } + + int GetFormType() const override { return FPDF_FORMFIELD_TEXTFIELD; } + + void FormSanityChecks() override { + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(CharLimitFormBegin())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(CharLimitFormEnd())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(RegularFormBegin())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(RegularFormEnd())); + } + + void SelectAllCharLimitFormTextWithMouse() { + SelectTextWithMouse(CharLimitFormEnd(), CharLimitFormBegin()); + } + + void SelectAllRegularFormTextWithMouse() { + SelectTextWithMouse(RegularFormEnd(), RegularFormBegin()); + } + + const CFX_PointF& CharLimitFormBegin() const { + static const CFX_PointF point = CharLimitFormAtX(kFormBeginX); + return point; + } + + const CFX_PointF& CharLimitFormEnd() const { + static const CFX_PointF point = CharLimitFormAtX(kFormEndX); + return point; + } + + const CFX_PointF& RegularFormBegin() const { + static const CFX_PointF point = RegularFormAtX(kFormBeginX); + return point; + } + + const CFX_PointF& RegularFormEnd() const { + static const CFX_PointF point = RegularFormAtX(kFormEndX); + return point; + } + + static CFX_PointF CharLimitFormAtX(float x) { + ASSERT(x >= kFormBeginX); + ASSERT(x <= kFormEndX); + return CFX_PointF(x, kCharLimitFormY); + } + + static CFX_PointF RegularFormAtX(float x) { + ASSERT(x >= kFormBeginX); + ASSERT(x <= kFormEndX); + return CFX_PointF(x, kRegularFormY); + } + + private: + static constexpr float kFormBeginX = 102.0; + static constexpr float kFormEndX = 195.0; + static constexpr float kCharLimitFormY = 60.0; + static constexpr float kRegularFormY = 115.0; +}; + +class FPDFFormFillComboBoxFormEmbeddertest + : public FPDFFormFillInteractiveEmbeddertest { + protected: + FPDFFormFillComboBoxFormEmbeddertest() = default; + ~FPDFFormFillComboBoxFormEmbeddertest() override = default; + + const char* GetDocumentName() const override { + // PDF with form comboboxes: + // - "Combo_Editable" - Ff: 393216, 3 options with pair values. + // - "Combo1" - Ff: 131072, 3 options with single values. + // - "Combo_ReadOnly" - Ff: 131073, 3 options with single values. + return "combobox_form.pdf"; + } + + int GetFormType() const override { return FPDF_FORMFIELD_COMBOBOX; } + + void FormSanityChecks() override { + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(EditableFormBegin())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(EditableFormEnd())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(EditableFormDropDown())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(NonEditableFormBegin())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(NonEditableFormEnd())); + EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(NonEditableFormDropDown())); + } + + void SelectEditableFormOption(int item_index) { + SelectOption(item_index, EditableFormDropDown()); + } + + void SelectNonEditableFormOption(int item_index) { + SelectOption(item_index, NonEditableFormDropDown()); + } + + void SelectAllEditableFormTextWithMouse() { + SelectTextWithMouse(EditableFormEnd(), EditableFormBegin()); + } + + const CFX_PointF& EditableFormBegin() const { + static const CFX_PointF point = EditableFormAtX(kFormBeginX); + return point; + } + + const CFX_PointF& EditableFormEnd() const { + static const CFX_PointF point = EditableFormAtX(kFormEndX); + return point; + } + + const CFX_PointF& EditableFormDropDown() const { + static const CFX_PointF point(kFormDropDownX, kEditableFormY); + return point; + } + + const CFX_PointF& NonEditableFormBegin() const { + static const CFX_PointF point = NonEditableFormAtX(kFormBeginX); + return point; + } + + const CFX_PointF& NonEditableFormEnd() const { + static const CFX_PointF point = NonEditableFormAtX(kFormEndX); + return point; + } + + const CFX_PointF& NonEditableFormDropDown() const { + static const CFX_PointF point(kFormDropDownX, kNonEditableFormY); + return point; + } + + static CFX_PointF EditableFormAtX(float x) { + ASSERT(x >= kFormBeginX); + ASSERT(x <= kFormEndX); + return CFX_PointF(x, kEditableFormY); + } + + static CFX_PointF NonEditableFormAtX(float x) { + ASSERT(x >= kFormBeginX); + ASSERT(x <= kFormEndX); + return CFX_PointF(x, kNonEditableFormY); + } + + private: + // Selects one of the pre-selected values from a combobox with three options. + // Options are specified by |item_index|, which is 0-based. + void SelectOption(int item_index, const CFX_PointF& point) { + // Only relevant for comboboxes with three choices and the same dimensions + // as those in combobox_form.pdf. + ASSERT(item_index >= 0); + ASSERT(item_index < 3); + + // Navigate to button for drop down and click mouse to reveal options. + ClickOnFormFieldAtPoint(point); + + // Calculate to Y-coordinate of dropdown option to be selected. + constexpr double kChoiceHeight = 15; + CFX_PointF option_point = point; + option_point.y -= kChoiceHeight * (item_index + 1); + + // Navigate to option and click mouse to select it. + ClickOnFormFieldAtPoint(option_point); + } + + static constexpr float kFormBeginX = 102.0; + static constexpr float kFormEndX = 183.0; + static constexpr float kFormDropDownX = 192.0; + static constexpr float kEditableFormY = 60.0; + static constexpr float kNonEditableFormY = 110.0; +}; TEST_F(FPDFFormFillEmbeddertest, FirstTest) { EmbedderTestMockDelegate mock; @@ -196,4 +487,888 @@ TEST_F(FPDFFormFillEmbeddertest, BUG_679649) { EXPECT_EQ(0u, alerts.size()); } +TEST_F(FPDFFormFillEmbeddertest, BUG_707673) { + EmbedderTestTimerHandlingDelegate delegate; + SetDelegate(&delegate); + + EXPECT_TRUE(OpenDocument("bug_707673.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + DoOpenActions(); + FORM_OnLButtonDown(form_handle(), page, 0, 140, 590); + FORM_OnLButtonUp(form_handle(), page, 0, 140, 590); + delegate.AdvanceTime(1000); + UnloadPage(page); + + const auto& alerts = delegate.GetAlerts(); + EXPECT_EQ(0u, alerts.size()); +} + +TEST_F(FPDFFormFillEmbeddertest, BUG_765384) { + EXPECT_TRUE(OpenDocument("bug_765384.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + DoOpenActions(); + FORM_OnLButtonDown(form_handle(), page, 0, 140, 590); + FORM_OnLButtonUp(form_handle(), page, 0, 140, 590); + UnloadPage(page); +} + #endif // PDF_ENABLE_V8 + +TEST_F(FPDFFormFillEmbeddertest, FormText) { +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + const char md5_1[] = "5f11dbe575fe197a37c3fb422559f8ff"; + const char md5_2[] = "35b1a4b679eafc749a0b6fda750c0e8d"; + const char md5_3[] = "65c64a7c355388f719a752aa1e23f6fe"; +#else + const char md5_1[] = "b890950d4b9bc163b1a96797f3004b53"; + const char md5_2[] = "11487d5597599a26e8912b9c1d9422cb"; + const char md5_3[] = "bffe0ecea9a533f217047ee41d6be466"; +#endif + { + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + std::unique_ptr bitmap1(RenderPage(page)); + CompareBitmap(bitmap1.get(), 300, 300, md5_1); + + // Click on the textfield + EXPECT_EQ(FPDF_FORMFIELD_TEXTFIELD, + FPDFPage_HasFormFieldAtPoint(form_handle(), page, 120.0, 120.0)); + FORM_OnMouseMove(form_handle(), page, 0, 120.0, 120.0); + FORM_OnLButtonDown(form_handle(), page, 0, 120.0, 120.0); + FORM_OnLButtonUp(form_handle(), page, 0, 120.0, 120.0); + + // Write "ABC" + FORM_OnChar(form_handle(), page, 65, 0); + FORM_OnChar(form_handle(), page, 66, 0); + FORM_OnChar(form_handle(), page, 67, 0); + std::unique_ptr bitmap2(RenderPage(page)); + CompareBitmap(bitmap2.get(), 300, 300, md5_2); + + // Take out focus by clicking out of the textfield + FORM_OnMouseMove(form_handle(), page, 0, 15.0, 15.0); + FORM_OnLButtonDown(form_handle(), page, 0, 15.0, 15.0); + FORM_OnLButtonUp(form_handle(), page, 0, 15.0, 15.0); + std::unique_ptr bitmap3(RenderPage(page)); + CompareBitmap(bitmap3.get(), 300, 300, md5_3); + + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + + // Close page + UnloadPage(page); + } + // Check saved document + VerifySavedDocument(300, 300, md5_3); +} + +TEST_F(FPDFFormFillEmbeddertest, HasFormInfoNone) { + EXPECT_TRUE(OpenDocument("hello_world.pdf")); + EXPECT_EQ(FORMTYPE_NONE, FPDF_GetFormType(document_)); +} + +TEST_F(FPDFFormFillEmbeddertest, HasFormInfoAcroForm) { + EXPECT_TRUE(OpenDocument("text_form.pdf")); + EXPECT_EQ(FORMTYPE_ACRO_FORM, FPDF_GetFormType(document_)); +} + +TEST_F(FPDFFormFillEmbeddertest, HasFormInfoXFAFull) { + EXPECT_TRUE(OpenDocument("simple_xfa.pdf")); + EXPECT_EQ(FORMTYPE_XFA_FULL, FPDF_GetFormType(document_)); +} + +TEST_F(FPDFFormFillEmbeddertest, HasFormInfoXFAForeground) { + EXPECT_TRUE(OpenDocument("bug_216.pdf")); + EXPECT_EQ(FORMTYPE_XFA_FOREGROUND, FPDF_GetFormType(document_)); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicKeyboard) { + // Test empty selection. + CheckSelection(L""); + + // Test basic selection. + TypeTextIntoTextField(3, RegularFormBegin()); + SelectTextWithKeyboard(3, FWL_VKEY_Left, RegularFormAtX(123.0)); + CheckSelection(L"ABC"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicMouse) { + // Test empty selection. + CheckSelection(L""); + + // Test basic selection. + TypeTextIntoTextField(3, RegularFormBegin()); + SelectTextWithMouse(RegularFormAtX(125.0), RegularFormBegin()); + CheckSelection(L"ABC"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextFragmentsKeyBoard) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Test selecting first character in forward direction. + SelectTextWithKeyboard(1, FWL_VKEY_Right, RegularFormBegin()); + CheckSelection(L"A"); + + // Test selecting entire long string in backwards direction. + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"ABCDEFGHIJKL"); + + // Test selecting middle section in backwards direction. + SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormAtX(170.0)); + CheckSelection(L"DEFGHI"); + + // Test selecting middle selection in forward direction. + SelectTextWithKeyboard(6, FWL_VKEY_Right, RegularFormAtX(125.0)); + CheckSelection(L"DEFGHI"); + + // Test selecting last character in backwards direction. + SelectTextWithKeyboard(1, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"L"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextFragmentsMouse) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Test selecting first character in forward direction. + SelectTextWithMouse(RegularFormBegin(), RegularFormAtX(106.0)); + CheckSelection(L"A"); + + // Test selecting entire long string in backwards direction. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"ABCDEFGHIJKL"); + + // Test selecting middle section in backwards direction. + SelectTextWithMouse(RegularFormAtX(170.0), RegularFormAtX(125.0)); + CheckSelection(L"DEFGHI"); + + // Test selecting middle selection in forward direction. + SelectTextWithMouse(RegularFormAtX(125.0), RegularFormAtX(170.0)); + CheckSelection(L"DEFGHI"); + + // Test selecting last character in backwards direction. + SelectTextWithMouse(RegularFormEnd(), RegularFormAtX(186.0)); + CheckSelection(L"L"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + GetSelectedTextEmptyAndBasicNormalComboBox) { + // Test empty selection. + CheckSelection(L""); + + // Non-editable comboboxes don't allow selection with keyboard. + SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(142.0)); + CheckSelection(L"Banana"); + + // Select other another provided option. + SelectNonEditableFormOption(0); + CheckSelection(L"Apple"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + GetSelectedTextEmptyAndBasicEditableComboBoxKeyboard) { + // Test empty selection. + CheckSelection(L""); + + // Test basic selection of text within user editable combobox using keyboard. + TypeTextIntoTextField(3, EditableFormBegin()); + SelectTextWithKeyboard(3, FWL_VKEY_Left, EditableFormAtX(128.0)); + CheckSelection(L"ABC"); + + // Select a provided option. + SelectEditableFormOption(1); + CheckSelection(L"Bar"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + GetSelectedTextEmptyAndBasicEditableComboBoxMouse) { + // Test empty selection. + CheckSelection(L""); + + // Test basic selection of text within user editable combobox using mouse. + TypeTextIntoTextField(3, EditableFormBegin()); + SelectTextWithMouse(EditableFormAtX(128.0), EditableFormBegin()); + CheckSelection(L"ABC"); + + // Select a provided option. + SelectEditableFormOption(2); + CheckSelection(L"Qux"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + GetSelectedTextFragmentsNormalComboBox) { + // Test selecting first character in forward direction. + SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(107.0)); + CheckSelection(L"B"); + + // Test selecting entire string in backwards direction. + SelectTextWithMouse(NonEditableFormAtX(142.0), NonEditableFormBegin()); + CheckSelection(L"Banana"); + + // Test selecting middle section in backwards direction. + SelectTextWithMouse(NonEditableFormAtX(135.0), NonEditableFormAtX(117.0)); + CheckSelection(L"nan"); + + // Test selecting middle section in forward direction. + SelectTextWithMouse(NonEditableFormAtX(117.0), NonEditableFormAtX(135.0)); + CheckSelection(L"nan"); + + // Test selecting last character in backwards direction. + SelectTextWithMouse(NonEditableFormAtX(142.0), NonEditableFormAtX(138.0)); + CheckSelection(L"a"); + + // Select another option and then reset selection as first three chars. + SelectNonEditableFormOption(2); + CheckSelection(L"Cherry"); + SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(122.0)); + CheckSelection(L"Che"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + GetSelectedTextFragmentsEditableComboBoxKeyboard) { + TypeTextIntoTextField(10, EditableFormBegin()); + + // Test selecting first character in forward direction. + SelectTextWithKeyboard(1, FWL_VKEY_Right, EditableFormBegin()); + CheckSelection(L"A"); + + // Test selecting entire long string in backwards direction. + SelectTextWithKeyboard(10, FWL_VKEY_Left, EditableFormEnd()); + CheckSelection(L"ABCDEFGHIJ"); + + // Test selecting middle section in backwards direction. + SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormAtX(168.0)); + CheckSelection(L"DEFGH"); + + // Test selecting middle selection in forward direction. + SelectTextWithKeyboard(5, FWL_VKEY_Right, EditableFormAtX(127.0)); + CheckSelection(L"DEFGH"); + + // Test selecting last character in backwards direction. + SelectTextWithKeyboard(1, FWL_VKEY_Left, EditableFormEnd()); + CheckSelection(L"J"); + + // Select a provided option and then reset selection as first two chars. + SelectEditableFormOption(0); + CheckSelection(L"Foo"); + SelectTextWithKeyboard(2, FWL_VKEY_Right, EditableFormBegin()); + CheckSelection(L"Fo"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + GetSelectedTextFragmentsEditableComboBoxMouse) { + TypeTextIntoTextField(10, EditableFormBegin()); + + // Test selecting first character in forward direction. + SelectTextWithMouse(EditableFormBegin(), EditableFormAtX(107.0)); + CheckSelection(L"A"); + + // Test selecting entire long string in backwards direction. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCDEFGHIJ"); + + // Test selecting middle section in backwards direction. + SelectTextWithMouse(EditableFormAtX(168.0), EditableFormAtX(127.0)); + CheckSelection(L"DEFGH"); + + // Test selecting middle selection in forward direction. + SelectTextWithMouse(EditableFormAtX(127.0), EditableFormAtX(168.0)); + CheckSelection(L"DEFGH"); + + // Test selecting last character in backwards direction. + SelectTextWithMouse(EditableFormEnd(), EditableFormAtX(174.0)); + CheckSelection(L"J"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldEntireSelection) { + // Select entire contents of text field. + TypeTextIntoTextField(12, RegularFormBegin()); + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"ABCDEFGHIJKL"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L""); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldSelectionMiddle) { + // Select middle section of text. + TypeTextIntoTextField(12, RegularFormBegin()); + SelectTextWithMouse(RegularFormAtX(170.0), RegularFormAtX(125.0)); + CheckSelection(L"DEFGHI"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"ABCJKL"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldSelectionLeft) { + // Select first few characters of text. + TypeTextIntoTextField(12, RegularFormBegin()); + SelectTextWithMouse(RegularFormBegin(), RegularFormAtX(132.0)); + CheckSelection(L"ABCD"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"EFGHIJKL"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldSelectionRight) { + // Select last few characters of text. + TypeTextIntoTextField(12, RegularFormBegin()); + SelectTextWithMouse(RegularFormEnd(), RegularFormAtX(165.0)); + CheckSelection(L"IJKL"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"ABCDEFGH"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteEmptyTextFieldSelection) { + // Do not select text. + TypeTextIntoTextField(12, RegularFormBegin()); + CheckSelection(L""); + + // Test that attempt to delete empty text selection has no effect. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"ABCDEFGHIJKL"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + DeleteEditableComboBoxEntireSelection) { + // Select entire contents of user-editable combobox text field. + TypeTextIntoTextField(10, EditableFormBegin()); + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCDEFGHIJ"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectAllEditableFormTextWithMouse(); + CheckSelection(L""); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + DeleteEditableComboBoxSelectionMiddle) { + // Select middle section of text. + TypeTextIntoTextField(10, EditableFormBegin()); + SelectTextWithMouse(EditableFormAtX(168.0), EditableFormAtX(127.0)); + CheckSelection(L"DEFGH"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCIJ"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + DeleteEditableComboBoxSelectionLeft) { + // Select first few characters of text. + TypeTextIntoTextField(10, EditableFormBegin()); + SelectTextWithMouse(EditableFormBegin(), EditableFormAtX(132.0)); + CheckSelection(L"ABCD"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"EFGHIJ"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + DeleteEditableComboBoxSelectionRight) { + // Select last few characters of text. + TypeTextIntoTextField(10, EditableFormBegin()); + SelectTextWithMouse(EditableFormEnd(), EditableFormAtX(152.0)); + CheckSelection(L"GHIJ"); + + // Test deleting current text selection. Select what remains after deletion to + // check that remaining text is as expected. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCDEF"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + DeleteEmptyEditableComboBoxSelection) { + // Do not select text. + TypeTextIntoTextField(10, EditableFormBegin()); + CheckSelection(L""); + + // Test that attempt to delete empty text selection has no effect. + FORM_ReplaceSelection(form_handle(), page(), nullptr); + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCDEFGHIJ"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInEmptyTextField) { + ClickOnFormFieldAtPoint(RegularFormBegin()); + + // Test inserting text into empty text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"Hello"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldLeft) { + TypeTextIntoTextField(8, RegularFormBegin()); + + // Click on the leftmost part of the text field. + ClickOnFormFieldAtPoint(RegularFormBegin()); + + // Test inserting text in front of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"HelloABCDEFGH"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldMiddle) { + TypeTextIntoTextField(8, RegularFormBegin()); + + // Click on the middle of the text field. + ClickOnFormFieldAtPoint(RegularFormAtX(134.0)); + + // Test inserting text in the middle of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"ABCDHelloEFGH"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldRight) { + TypeTextIntoTextField(8, RegularFormBegin()); + + // Click on the rightmost part of the text field. + ClickOnFormFieldAtPoint(RegularFormAtX(166.0)); + + // Test inserting text behind existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"ABCDEFGHHello"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select entire string in text field. + SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"ABCDEFGHIJKL"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"Hello"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select left portion of string in text field. + SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormAtX(148.0)); + CheckSelection(L"ABCDEF"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"HelloGHIJKL"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select middle portion of string in text field. + SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormAtX(171.0)); + CheckSelection(L"DEFGHI"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"ABCHelloJKL"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldRight) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select right portion of string in text field. + SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormEnd()); + CheckSelection(L"GHIJKL"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllRegularFormTextWithMouse(); + CheckSelection(L"ABCDEFHello"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextInEmptyEditableComboBox) { + ClickOnFormFieldAtPoint(EditableFormBegin()); + + // Test inserting text into empty user-editable combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"Hello"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextInPopulatedEditableComboBoxLeft) { + TypeTextIntoTextField(6, EditableFormBegin()); + + // Click on the leftmost part of the user-editable combobox. + ClickOnFormFieldAtPoint(EditableFormBegin()); + + // Test inserting text in front of existing text in user-editable combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"HelloABCDEF"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextInPopulatedEditableComboBoxMiddle) { + TypeTextIntoTextField(6, EditableFormBegin()); + + // Click on the middle of the user-editable combobox. + ClickOnFormFieldAtPoint(EditableFormAtX(126.0)); + + // Test inserting text in the middle of existing text in user-editable + // combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCHelloDEF"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextInPopulatedEditableComboBoxRight) { + TypeTextIntoTextField(6, EditableFormBegin()); + + // Click on the rightmost part of the user-editable combobox. + ClickOnFormFieldAtPoint(EditableFormEnd()); + + // Test inserting text behind existing text in user-editable combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCDEFHello"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) { + TypeTextIntoTextField(10, EditableFormBegin()); + + // Select entire string in user-editable combobox. + SelectTextWithKeyboard(10, FWL_VKEY_Left, EditableFormEnd()); + CheckSelection(L"ABCDEFGHIJ"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"Hello"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) { + TypeTextIntoTextField(10, EditableFormBegin()); + + // Select left portion of string in user-editable combobox. + SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormAtX(142.0)); + CheckSelection(L"ABCDE"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"HelloFGHIJ"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) { + TypeTextIntoTextField(10, EditableFormBegin()); + + // Select middle portion of string in user-editable combobox. + SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormAtX(167.0)); + CheckSelection(L"DEFGH"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCHelloIJ"); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) { + TypeTextIntoTextField(10, EditableFormBegin()); + + // Select right portion of string in user-editable combobox. + SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormEnd()); + CheckSelection(L"FGHIJ"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectAllEditableFormTextWithMouse(); + CheckSelection(L"ABCDEHello"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextInEmptyCharLimitTextFieldOverflow) { + // Click on the textfield. + ClickOnFormFieldAtPoint(CharLimitFormEnd()); + + // Delete pre-filled contents of text field with char limit. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"Elephant"); + FORM_ReplaceSelection(form_handle(), page(), nullptr); + + // Test inserting text into now empty text field so text to be inserted + // exceeds the char limit and is cut off. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"Hippopotam"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextInEmptyCharLimitTextFieldFit) { + // Click on the textfield. + ClickOnFormFieldAtPoint(CharLimitFormEnd()); + + // Delete pre-filled contents of text field with char limit. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"Elephant"); + FORM_ReplaceSelection(form_handle(), page(), nullptr); + + // Test inserting text into now empty text field so text to be inserted + // exceeds the char limit and is cut off. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Zebra"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"Zebra"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextInPopulatedCharLimitTextFieldLeft) { + // Click on the leftmost part of the text field. + ClickOnFormFieldAtPoint(CharLimitFormBegin()); + + // Test inserting text in front of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"HiElephant"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextInPopulatedCharLimitTextFieldMiddle) { + TypeTextIntoTextField(8, RegularFormBegin()); + + // Click on the middle of the text field. + ClickOnFormFieldAtPoint(CharLimitFormAtX(134.0)); + + // Test inserting text in the middle of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"ElephHiant"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextInPopulatedCharLimitTextFieldRight) { + TypeTextIntoTextField(8, RegularFormBegin()); + + // Click on the rightmost part of the text field. + ClickOnFormFieldAtPoint(CharLimitFormAtX(166.0)); + + // Test inserting text behind existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"ElephantHi"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select entire string in text field. + SelectTextWithKeyboard(12, FWL_VKEY_Left, CharLimitFormEnd()); + CheckSelection(L"Elephant"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"Hippopotam"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select left portion of string in text field. + SelectTextWithKeyboard(4, FWL_VKEY_Left, CharLimitFormAtX(122.0)); + CheckSelection(L"Elep"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"Hippophant"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select middle portion of string in text field. + SelectTextWithKeyboard(4, FWL_VKEY_Left, CharLimitFormAtX(136.0)); + CheckSelection(L"epha"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"ElHippopnt"); +} + +TEST_F(FPDFFormFillTextFormEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) { + TypeTextIntoTextField(12, RegularFormBegin()); + + // Select right portion of string in text field. + SelectTextWithKeyboard(4, FWL_VKEY_Left, CharLimitFormAtX(152.0)); + CheckSelection(L"hant"); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectAllCharLimitFormTextWithMouse(); + CheckSelection(L"ElepHippop"); +} diff --git a/fpdfsdk/fpdfppo.cpp b/fpdfsdk/fpdfppo.cpp index 4e06856455caa7c432c700f9472c19e4c9f316d3..d88f9102b9a8f1b3023f3d547d0f8d4335d4a67f 100644 --- a/fpdfsdk/fpdfppo.cpp +++ b/fpdfsdk/fpdfppo.cpp @@ -18,14 +18,14 @@ #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/fsdk_define.h" #include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" namespace { CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict, - const CFX_ByteString& bsSrcTag) { + const ByteString& bsSrcTag) { if (!pDict || bsSrcTag.IsEmpty()) return nullptr; if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type")) @@ -57,7 +57,7 @@ CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict, bool CopyInheritable(CPDF_Dictionary* pCurPageDict, CPDF_Dictionary* pSrcPageDict, - const CFX_ByteString& key) { + const ByteString& key) { if (pCurPageDict->KeyExist(key)) return true; @@ -69,54 +69,57 @@ bool CopyInheritable(CPDF_Dictionary* pCurPageDict, return true; } -bool ParserPageRangeString(CFX_ByteString rangstring, +bool ParserPageRangeString(ByteString rangstring, std::vector* pageArray, int nCount) { if (rangstring.IsEmpty()) return true; rangstring.Remove(' '); - int nLength = rangstring.GetLength(); - CFX_ByteString cbCompareString("0123456789-,"); - for (int i = 0; i < nLength; ++i) { - if (cbCompareString.Find(rangstring[i]) == -1) + size_t nLength = rangstring.GetLength(); + ByteString cbCompareString("0123456789-,"); + for (size_t i = 0; i < nLength; ++i) { + if (!cbCompareString.Contains(rangstring[i])) return false; } - CFX_ByteString cbMidRange; - int nStringFrom = 0; - int nStringTo = 0; + ByteString cbMidRange; + size_t nStringFrom = 0; + Optional nStringTo = 0; while (nStringTo < nLength) { nStringTo = rangstring.Find(',', nStringFrom); - if (nStringTo == -1) + if (!nStringTo.has_value()) nStringTo = nLength; - cbMidRange = rangstring.Mid(nStringFrom, nStringTo - nStringFrom); - int nMid = cbMidRange.Find('-'); - if (nMid == -1) { - long lPageNum = atol(cbMidRange.c_str()); - if (lPageNum <= 0 || lPageNum > nCount) + cbMidRange = rangstring.Mid(nStringFrom, nStringTo.value() - nStringFrom); + auto nMid = cbMidRange.Find('-'); + if (!nMid.has_value()) { + uint16_t pageNum = + pdfium::base::checked_cast(atoi(cbMidRange.c_str())); + if (pageNum <= 0 || pageNum > nCount) return false; - pageArray->push_back((uint16_t)lPageNum); + pageArray->push_back(pageNum); } else { - int nStartPageNum = atol(cbMidRange.Mid(0, nMid).c_str()); + uint16_t nStartPageNum = pdfium::base::checked_cast( + atoi(cbMidRange.Left(nMid.value()).c_str())); if (nStartPageNum == 0) return false; - ++nMid; - int nEnd = cbMidRange.GetLength() - nMid; + nMid = nMid.value() + 1; + size_t nEnd = cbMidRange.GetLength() - nMid.value(); if (nEnd == 0) return false; - int nEndPageNum = atol(cbMidRange.Mid(nMid, nEnd).c_str()); + uint16_t nEndPageNum = pdfium::base::checked_cast( + atoi(cbMidRange.Mid(nMid.value(), nEnd).c_str())); if (nStartPageNum < 0 || nStartPageNum > nEndPageNum || nEndPageNum > nCount) { return false; } - for (int i = nStartPageNum; i <= nEndPageNum; ++i) { + for (uint16_t i = nStartPageNum; i <= nEndPageNum; ++i) { pageArray->push_back(i); } } - nStringFrom = nStringTo + 1; + nStringFrom = nStringTo.value() + 1; } return true; } @@ -137,8 +140,8 @@ class CPDF_PageOrganizer { bool UpdateReference(CPDF_Object* pObj, ObjectNumberMap* pObjNumberMap); uint32_t GetNewObjId(ObjectNumberMap* pObjNumberMap, CPDF_Reference* pRef); - CPDF_Document* m_pDestPDFDoc; - CPDF_Document* m_pSrcPDFDoc; + UnownedPtr m_pDestPDFDoc; + UnownedPtr m_pSrcPDFDoc; }; CPDF_PageOrganizer::CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc, @@ -161,7 +164,7 @@ bool CPDF_PageOrganizer::PDFDocInit() { pDocInfoDict->SetNewFor("Producer", "PDFium", false); - CFX_ByteString cbRootType = pNewRoot->GetStringFor("Type", ""); + ByteString cbRootType = pNewRoot->GetStringFor("Type", ""); if (cbRootType.IsEmpty()) pNewRoot->SetNewFor("Type", "Catalog"); @@ -170,18 +173,18 @@ bool CPDF_PageOrganizer::PDFDocInit() { pElement ? ToDictionary(pElement->GetDirect()) : nullptr; if (!pNewPages) { pNewPages = m_pDestPDFDoc->NewIndirect(); - pNewRoot->SetNewFor("Pages", m_pDestPDFDoc, + pNewRoot->SetNewFor("Pages", m_pDestPDFDoc.Get(), pNewPages->GetObjNum()); } - CFX_ByteString cbPageType = pNewPages->GetStringFor("Type", ""); + ByteString cbPageType = pNewPages->GetStringFor("Type", ""); if (cbPageType.IsEmpty()) pNewPages->SetNewFor("Type", "Pages"); if (!pNewPages->GetArrayFor("Kids")) { pNewPages->SetNewFor("Count", 0); pNewPages->SetNewFor( - "Kids", m_pDestPDFDoc, + "Kids", m_pDestPDFDoc.Get(), m_pDestPDFDoc->NewIndirect()->GetObjNum()); } @@ -192,8 +195,7 @@ bool CPDF_PageOrganizer::ExportPage(const std::vector& pageNums, int nIndex) { int curpage = nIndex; auto pObjNumberMap = pdfium::MakeUnique(); - int nSize = pdfium::CollectionSize(pageNums); - for (int i = 0; i < nSize; ++i) { + for (size_t i = 0; i < pageNums.size(); ++i) { CPDF_Dictionary* pCurPageDict = m_pDestPDFDoc->CreateNewPage(curpage); CPDF_Dictionary* pSrcPageDict = m_pSrcPDFDoc->GetPage(pageNums[i] - 1); if (!pSrcPageDict || !pCurPageDict) @@ -201,7 +203,7 @@ bool CPDF_PageOrganizer::ExportPage(const std::vector& pageNums, // Clone the page dictionary for (const auto& it : *pSrcPageDict) { - const CFX_ByteString& cbSrcKeyStr = it.first; + const ByteString& cbSrcKeyStr = it.first; if (cbSrcKeyStr == "Type" || cbSrcKeyStr == "Parent") continue; @@ -210,16 +212,18 @@ bool CPDF_PageOrganizer::ExportPage(const std::vector& pageNums, } // inheritable item + // Even though some entries are required by the PDF spec, there exist + // PDFs that omit them. Set some defaults in this case. // 1 MediaBox - required if (!CopyInheritable(pCurPageDict, pSrcPageDict, "MediaBox")) { - // Search for "CropBox" in the source page dictionary, - // if it does not exists, use the default letter size. + // Search for "CropBox" in the source page dictionary. + // If it does not exist, use the default letter size. CPDF_Object* pInheritable = PageDictGetInheritableTag(pSrcPageDict, "CropBox"); if (pInheritable) { pCurPageDict->SetFor("MediaBox", pInheritable->Clone()); } else { - // Make the default size to be letter size (8.5'x11') + // Make the default size letter size (8.5"x11") CPDF_Array* pArray = pCurPageDict->SetNewFor("MediaBox"); pArray->AddNew(0); pArray->AddNew(0); @@ -229,8 +233,10 @@ bool CPDF_PageOrganizer::ExportPage(const std::vector& pageNums, } // 2 Resources - required - if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources")) - return false; + if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources")) { + // Use a default empty resources if it does not exist. + pCurPageDict->SetNewFor("Resources"); + } // 3 CropBox - optional CopyInheritable(pCurPageDict, pSrcPageDict, "CropBox"); @@ -256,14 +262,14 @@ bool CPDF_PageOrganizer::UpdateReference(CPDF_Object* pObj, uint32_t newobjnum = GetNewObjId(pObjNumberMap, pReference); if (newobjnum == 0) return false; - pReference->SetRef(m_pDestPDFDoc, newobjnum); + pReference->SetRef(m_pDestPDFDoc.Get(), newobjnum); break; } case CPDF_Object::DICTIONARY: { CPDF_Dictionary* pDict = pObj->AsDictionary(); auto it = pDict->begin(); while (it != pDict->end()) { - const CFX_ByteString& key = it->first; + const ByteString& key = it->first; CPDF_Object* pNextObj = it->second.get(); ++it; if (key == "Parent" || key == "Prev" || key == "First") @@ -322,7 +328,7 @@ uint32_t CPDF_PageOrganizer::GetNewObjId(ObjectNumberMap* pObjNumberMap, std::unique_ptr pClone = pDirect->Clone(); if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) { if (pDictClone->KeyExist("Type")) { - CFX_ByteString strType = pDictClone->GetStringFor("Type"); + ByteString strType = pDictClone->GetStringFor("Type"); if (!FXSYS_stricmp(strType.c_str(), "Pages")) return 4; if (!FXSYS_stricmp(strType.c_str(), "Page")) @@ -339,10 +345,10 @@ uint32_t CPDF_PageOrganizer::GetNewObjId(ObjectNumberMap* pObjNumberMap, return dwNewObjNum; } -DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, - FPDF_DOCUMENT src_doc, - FPDF_BYTESTRING pagerange, - int index) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc, + FPDF_DOCUMENT src_doc, + FPDF_BYTESTRING pagerange, + int index) { CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(dest_doc); if (!dest_doc) return false; @@ -366,8 +372,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, return pageOrg.PDFDocInit() && pageOrg.ExportPage(pageArray, index); } -DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, - FPDF_DOCUMENT src_doc) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc) { CPDF_Document* pDstDoc = CPDFDocumentFromFPDFDocument(dest_doc); if (!pDstDoc) return false; diff --git a/fpdfsdk/fpdfppo_embeddertest.cpp b/fpdfsdk/fpdfppo_embeddertest.cpp index 097231653419d8ebad9537374e8ffbe41113dd1e..c642b71ac0ad302778eb46cf646e056e5ab0cb1c 100644 --- a/fpdfsdk/fpdfppo_embeddertest.cpp +++ b/fpdfsdk/fpdfppo_embeddertest.cpp @@ -1,11 +1,11 @@ // Copyright 2016 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. +#include -#include "public/fpdf_ppo.h" - -#include "core/fxcrt/fx_basic.h" #include "public/fpdf_edit.h" +#include "public/fpdf_ppo.h" +#include "public/fpdf_save.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" #include "testing/gtest/include/gtest/gtest.h" @@ -15,6 +15,12 @@ namespace { class FPDFPPOEmbeddertest : public EmbedderTest {}; +int FakeBlockWriter(FPDF_FILEWRITE* pThis, + const void* pData, + unsigned long size) { + return size; +} + } // namespace TEST_F(FPDFPPOEmbeddertest, NoViewerPreferences) { @@ -36,13 +42,13 @@ TEST_F(FPDFPPOEmbeddertest, ViewerPreferences) { } TEST_F(FPDFPPOEmbeddertest, ImportPages) { - EXPECT_TRUE(OpenDocument("viewer_ref.pdf")); + ASSERT_TRUE(OpenDocument("viewer_ref.pdf")); FPDF_PAGE page = LoadPage(0); EXPECT_TRUE(page); FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument(); - EXPECT_TRUE(output_doc); + ASSERT_TRUE(output_doc); EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document())); EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1", 0)); EXPECT_EQ(1, FPDF_GetPageCount(output_doc)); @@ -51,6 +57,36 @@ TEST_F(FPDFPPOEmbeddertest, ImportPages) { UnloadPage(page); } +TEST_F(FPDFPPOEmbeddertest, BadRepeatViewerPref) { + ASSERT_TRUE(OpenDocument("repeat_viewer_ref.pdf")); + + FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument(); + EXPECT_TRUE(output_doc); + EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document())); + + FPDF_FILEWRITE writer; + writer.version = 1; + writer.WriteBlock = FakeBlockWriter; + + EXPECT_TRUE(FPDF_SaveAsCopy(output_doc, &writer, 0)); + FPDF_CloseDocument(output_doc); +} + +TEST_F(FPDFPPOEmbeddertest, BadCircularViewerPref) { + ASSERT_TRUE(OpenDocument("circular_viewer_ref.pdf")); + + FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument(); + EXPECT_TRUE(output_doc); + EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document())); + + FPDF_FILEWRITE writer; + writer.version = 1; + writer.WriteBlock = FakeBlockWriter; + + EXPECT_TRUE(FPDF_SaveAsCopy(output_doc, &writer, 0)); + FPDF_CloseDocument(output_doc); +} + TEST_F(FPDFPPOEmbeddertest, BadRanges) { EXPECT_TRUE(OpenDocument("viewer_ref.pdf")); @@ -95,7 +131,7 @@ TEST_F(FPDFPPOEmbeddertest, BUG_664284) { EXPECT_TRUE(OpenDocument("bug_664284.pdf")); FPDF_PAGE page = LoadPage(0); - EXPECT_TRUE(page); + ASSERT_NE(nullptr, page); FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument(); EXPECT_TRUE(output_doc); @@ -104,3 +140,81 @@ TEST_F(FPDFPPOEmbeddertest, BUG_664284) { UnloadPage(page); } + +TEST_F(FPDFPPOEmbeddertest, BUG_750568) { + const char* const kHashes[] = { + "64ad08132a1c5a166768298c8a578f57", "83b83e2f6bc80707d0a917c7634140b9", + "913cd3723a451e4e46fbc2c05702d1ee", "81fb7cfd4860f855eb468f73dfeb6d60"}; + + ASSERT_TRUE(OpenDocument("bug_750568.pdf")); + ASSERT_EQ(4, FPDF_GetPageCount(document())); + + for (size_t i = 0; i < 4; ++i) { + FPDF_PAGE page = LoadPage(i); + ASSERT_NE(nullptr, page); + + FPDF_BITMAP bitmap = RenderPage(page); + ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap)); + ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap)); + ASSERT_EQ(800, FPDFBitmap_GetStride(bitmap)); + + std::string digest = HashBitmap(bitmap); + FPDFBitmap_Destroy(bitmap); + UnloadPage(page); + EXPECT_EQ(kHashes[i], digest); + } + + FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument(); + ASSERT_TRUE(output_doc); + EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1,2,3,4", 0)); + ASSERT_EQ(4, FPDF_GetPageCount(output_doc)); + for (size_t i = 0; i < 4; ++i) { + FPDF_PAGE page = FPDF_LoadPage(output_doc, i); + ASSERT_NE(nullptr, page); + + FPDF_BITMAP bitmap = RenderPage(page); + ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap)); + ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap)); + ASSERT_EQ(800, FPDFBitmap_GetStride(bitmap)); + + std::string digest = HashBitmap(bitmap); + FPDFBitmap_Destroy(bitmap); + FPDF_ClosePage(page); + EXPECT_EQ(kHashes[i], digest); + } + FPDF_CloseDocument(output_doc); +} + +TEST_F(FPDFPPOEmbeddertest, ImportWithZeroLengthStream) { + EXPECT_TRUE(OpenDocument("zero_length_stream.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_NE(nullptr, page); + + FPDF_BITMAP bitmap = RenderPage(page); + ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap)); + ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap)); + ASSERT_EQ(800, FPDFBitmap_GetStride(bitmap)); + + std::string digest = HashBitmap(bitmap); + FPDFBitmap_Destroy(bitmap); + FPDF_ClosePage(page); + + FPDF_DOCUMENT new_doc = FPDF_CreateNewDocument(); + EXPECT_TRUE(new_doc); + EXPECT_TRUE(FPDF_ImportPages(new_doc, document(), "1", 0)); + + EXPECT_EQ(1, FPDF_GetPageCount(new_doc)); + FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0); + ASSERT_NE(nullptr, new_page); + FPDF_BITMAP new_bitmap = RenderPage(new_page); + ASSERT_EQ(200, FPDFBitmap_GetWidth(new_bitmap)); + ASSERT_EQ(200, FPDFBitmap_GetHeight(new_bitmap)); + ASSERT_EQ(800, FPDFBitmap_GetStride(new_bitmap)); + + std::string new_digest = HashBitmap(new_bitmap); + FPDFBitmap_Destroy(new_bitmap); + FPDF_ClosePage(new_page); + FPDF_CloseDocument(new_doc); + + EXPECT_EQ(digest, new_digest); +} diff --git a/fpdfsdk/fpdfsave.cpp b/fpdfsdk/fpdfsave.cpp index 0cfcd4af577c3a5ac480cb070c109fc0a1ae13e3..ddbc9945770622e5d029d8a260828083b8583f5f 100644 --- a/fpdfsdk/fpdfsave.cpp +++ b/fpdfsdk/fpdfsave.cpp @@ -16,73 +16,40 @@ #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/cpdf_string.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_extension.h" #include "fpdfsdk/fsdk_define.h" +#include "fpdfsdk/fsdk_filewriteadapter.h" #include "public/fpdf_edit.h" #ifdef PDF_ENABLE_XFA +#include "core/fxcrt/cfx_checksumcontext.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h" #include "public/fpdf_formfill.h" #include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/xfa_checksum.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_widgetacciterator.h" +#include "xfa/fxfa/parser/cxfa_object.h" #endif -#if _FX_OS_ == _FX_ANDROID_ +#if _FX_OS_ == _FX_OS_ANDROID_ #include #else #include #endif -class CFX_IFileWrite final : public IFX_WriteStream { - public: - static CFX_RetainPtr Create(); - bool Init(FPDF_FILEWRITE* pFileWriteStruct); - bool WriteBlock(const void* pData, size_t size) override; - - protected: - CFX_IFileWrite(); - ~CFX_IFileWrite() override {} - - FPDF_FILEWRITE* m_pFileWriteStruct; -}; - -CFX_RetainPtr CFX_IFileWrite::Create() { - return CFX_RetainPtr(new CFX_IFileWrite()); -} - -CFX_IFileWrite::CFX_IFileWrite() : m_pFileWriteStruct(nullptr) {} - -bool CFX_IFileWrite::Init(FPDF_FILEWRITE* pFileWriteStruct) { - if (!pFileWriteStruct) - return false; - - m_pFileWriteStruct = pFileWriteStruct; - return true; -} - -bool CFX_IFileWrite::WriteBlock(const void* pData, size_t size) { - if (!m_pFileWriteStruct) - return false; - - m_pFileWriteStruct->WriteBlock(m_pFileWriteStruct, pData, size); - return true; -} - namespace { #ifdef PDF_ENABLE_XFA -bool SaveXFADocumentData( - CPDFXFA_Context* pContext, - std::vector>* fileList) { +bool SaveXFADocumentData(CPDFXFA_Context* pContext, + std::vector>* fileList) { if (!pContext) return false; - if (pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA && - pContext->GetDocType() != DOCTYPE_STATIC_XFA) + if (!pContext->ContainsXFAForm()) return true; CXFA_FFDocView* pXFADocView = pContext->GetXFADocView(); @@ -93,7 +60,7 @@ bool SaveXFADocumentData( if (!pPDFDocument) return false; - CPDF_Dictionary* pRoot = pPDFDocument->GetRoot(); + const CPDF_Dictionary* pRoot = pPDFDocument->GetRoot(); if (!pRoot) return false; @@ -125,18 +92,17 @@ bool SaveXFADocumentData( else if (pPDFObj->GetString() == "template") iTemplate = i + 1; } - std::unique_ptr pChecksum(new CXFA_ChecksumContext); + auto pChecksum = pdfium::MakeUnique(); pChecksum->StartChecksum(); // template if (iTemplate > -1) { CPDF_Stream* pTemplateStream = pArray->GetStreamAt(iTemplate); - CPDF_StreamAcc streamAcc; - streamAcc.LoadAllData(pTemplateStream); - uint8_t* pData = (uint8_t*)streamAcc.GetData(); - uint32_t dwSize2 = streamAcc.GetSize(); - CFX_RetainPtr pTemplate = - IFX_MemoryStream::Create(pData, dwSize2); + auto pAcc = pdfium::MakeRetain(pTemplateStream); + pAcc->LoadAllDataFiltered(); + RetainPtr pTemplate = + pdfium::MakeRetain( + const_cast(pAcc->GetData()), pAcc->GetSize(), false); pChecksum->UpdateChecksum(pTemplate); } CPDF_Stream* pFormStream = nullptr; @@ -169,9 +135,12 @@ bool SaveXFADocumentData( } // L"datasets" { - CFX_RetainPtr pDsfileWrite = IFX_MemoryStream::Create(); - if (pXFADocView->GetDoc()->SavePackage(XFA_HASHCODE_Datasets, pDsfileWrite, - nullptr) && + RetainPtr pDsfileWrite = + pdfium::MakeRetain(false); + CXFA_FFDoc* ffdoc = pXFADocView->GetDoc(); + if (ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)), + pDsfileWrite, nullptr) && pDsfileWrite->GetSize() > 0) { // Datasets pChecksum->UpdateChecksum(pDsfileWrite); @@ -196,9 +165,13 @@ bool SaveXFADocumentData( } // L"form" { - CFX_RetainPtr pfileWrite = IFX_MemoryStream::Create(); - if (pXFADocView->GetDoc()->SavePackage(XFA_HASHCODE_Form, pfileWrite, - pChecksum.get()) && + RetainPtr pfileWrite = + pdfium::MakeRetain(false); + + CXFA_FFDoc* ffdoc = pXFADocView->GetDoc(); + if (ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)), + pfileWrite, pChecksum.get()) && pfileWrite->GetSize() > 0) { auto pDataDict = pdfium::MakeUnique( pPDFDocument->GetByteStringPool()); @@ -223,45 +196,42 @@ bool SendPostSaveToXFADoc(CPDFXFA_Context* pContext) { if (!pContext) return false; - if (pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA && - pContext->GetDocType() != DOCTYPE_STATIC_XFA) + if (!pContext->ContainsXFAForm()) return true; CXFA_FFDocView* pXFADocView = pContext->GetXFADocView(); if (!pXFADocView) return false; - CXFA_FFWidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); - std::unique_ptr pWidgetAccIterator( - pXFADocView->CreateWidgetAccIterator()); + CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler(); + std::unique_ptr pWidgetAccIterator = + pXFADocView->CreateWidgetAccIterator(); while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext()) { CXFA_EventParam preParam; preParam.m_eType = XFA_EVENT_PostSave; - pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); + pWidgetHandler->ProcessEvent(pWidgetAcc, &preParam); } pXFADocView->UpdateDocView(); pContext->ClearChangeMark(); return true; } -bool SendPreSaveToXFADoc( - CPDFXFA_Context* pContext, - std::vector>* fileList) { - if (pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA && - pContext->GetDocType() != DOCTYPE_STATIC_XFA) +bool SendPreSaveToXFADoc(CPDFXFA_Context* pContext, + std::vector>* fileList) { + if (!pContext->ContainsXFAForm()) return true; CXFA_FFDocView* pXFADocView = pContext->GetXFADocView(); if (!pXFADocView) return true; - CXFA_FFWidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); - std::unique_ptr pWidgetAccIterator( - pXFADocView->CreateWidgetAccIterator()); + CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler(); + std::unique_ptr pWidgetAccIterator = + pXFADocView->CreateWidgetAccIterator(); while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext()) { CXFA_EventParam preParam; preParam.m_eType = XFA_EVENT_PreSave; - pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); + pWidgetHandler->ProcessEvent(pWidgetAcc, &preParam); } pXFADocView->UpdateDocView(); return SaveXFADocumentData(pContext, fileList); @@ -279,24 +249,23 @@ bool FPDF_Doc_Save(FPDF_DOCUMENT document, #ifdef PDF_ENABLE_XFA CPDFXFA_Context* pContext = static_cast(document); - std::vector> fileList; + std::vector> fileList; SendPreSaveToXFADoc(pContext, &fileList); #endif // PDF_ENABLE_XFA if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY) flags = 0; - CPDF_Creator FileMaker(pPDFDoc); + CPDF_Creator fileMaker(pPDFDoc, + pdfium::MakeRetain(pFileWrite)); if (bSetVersion) - FileMaker.SetFileVersion(fileVerion); + fileMaker.SetFileVersion(fileVerion); if (flags == FPDF_REMOVE_SECURITY) { flags = 0; - FileMaker.RemoveSecurity(); + fileMaker.RemoveSecurity(); } - CFX_RetainPtr pStreamWrite = CFX_IFileWrite::Create(); - pStreamWrite->Init(pFileWrite); - bool bRet = FileMaker.Create(pStreamWrite, flags); + bool bRet = fileMaker.Create(flags); #ifdef PDF_ENABLE_XFA SendPostSaveToXFADoc(pContext); #endif // PDF_ENABLE_XFA @@ -305,15 +274,16 @@ bool FPDF_Doc_Save(FPDF_DOCUMENT document, } // namespace -DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveAsCopy(FPDF_DOCUMENT document, - FPDF_FILEWRITE* pFileWrite, - FPDF_DWORD flags) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document, + FPDF_FILEWRITE* pFileWrite, + FPDF_DWORD flags) { return FPDF_Doc_Save(document, pFileWrite, flags, false, 0); } -DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveWithVersion(FPDF_DOCUMENT document, - FPDF_FILEWRITE* pFileWrite, - FPDF_DWORD flags, - int fileVersion) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_SaveWithVersion(FPDF_DOCUMENT document, + FPDF_FILEWRITE* pFileWrite, + FPDF_DWORD flags, + int fileVersion) { return FPDF_Doc_Save(document, pFileWrite, flags, true, fileVersion); } diff --git a/fpdfsdk/fpdfsave_embeddertest.cpp b/fpdfsdk/fpdfsave_embeddertest.cpp index 918727027fe1a12bfdbe761531e789a506fe180f..3122be1b53ed5c47a379cc2421b7e7286b5f9aac 100644 --- a/fpdfsdk/fpdfsave_embeddertest.cpp +++ b/fpdfsdk/fpdfsave_embeddertest.cpp @@ -4,34 +4,32 @@ #include "public/fpdf_save.h" -#include +#include #include "core/fxcrt/fx_string.h" #include "public/fpdf_edit.h" #include "public/fpdf_ppo.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" -#include "testing/fx_string_testhelpers.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" -class FPDFSaveEmbedderTest : public EmbedderTest, public TestSaver {}; +class FPDFSaveEmbedderTest : public EmbedderTest {}; TEST_F(FPDFSaveEmbedderTest, SaveSimpleDoc) { EXPECT_TRUE(OpenDocument("hello_world.pdf")); EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); EXPECT_THAT(GetString(), testing::StartsWith("%PDF-1.7\r\n")); - EXPECT_EQ(843u, GetString().length()); + EXPECT_EQ(805u, GetString().length()); } TEST_F(FPDFSaveEmbedderTest, SaveSimpleDocWithVersion) { EXPECT_TRUE(OpenDocument("hello_world.pdf")); EXPECT_TRUE(FPDF_SaveWithVersion(document(), this, 0, 14)); EXPECT_THAT(GetString(), testing::StartsWith("%PDF-1.4\r\n")); - EXPECT_EQ(843u, GetString().length()); + EXPECT_EQ(805u, GetString().length()); } - TEST_F(FPDFSaveEmbedderTest, SaveSimpleDocWithBadVersion) { EXPECT_TRUE(OpenDocument("hello_world.pdf")); EXPECT_TRUE(FPDF_SaveWithVersion(document(), this, 0, -1)); @@ -61,6 +59,39 @@ TEST_F(FPDFSaveEmbedderTest, SaveCopiedDoc) { UnloadPage(page); } +TEST_F(FPDFSaveEmbedderTest, SaveLinearizedDoc) { + const int kPageCount = 3; + std::string original_md5[kPageCount]; + + EXPECT_TRUE(OpenDocument("linearized.pdf")); + for (int i = 0; i < kPageCount; ++i) { + FPDF_PAGE page = LoadPage(i); + FPDF_BITMAP bitmap = RenderPage(page); + EXPECT_EQ(612, FPDFBitmap_GetWidth(bitmap)); + EXPECT_EQ(792, FPDFBitmap_GetHeight(bitmap)); + original_md5[i] = HashBitmap(bitmap); + FPDFBitmap_Destroy(bitmap); + UnloadPage(page); + } + + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + EXPECT_THAT(GetString(), testing::StartsWith("%PDF-1.6\r\n")); + EXPECT_THAT(GetString(), testing::HasSubstr("/Root ")); + EXPECT_THAT(GetString(), testing::HasSubstr("/Info ")); + EXPECT_EQ(8219u, GetString().length()); + + // Make sure new document renders the same as the old one. + EXPECT_TRUE(OpenSavedDocument()); + for (int i = 0; i < kPageCount; ++i) { + FPDF_PAGE page = LoadSavedPage(i); + FPDF_BITMAP bitmap = RenderSavedPage(page); + EXPECT_EQ(original_md5[i], HashBitmap(bitmap)); + FPDFBitmap_Destroy(bitmap); + CloseSavedPage(page); + } + CloseSavedDocument(); +} + TEST_F(FPDFSaveEmbedderTest, BUG_342) { EXPECT_TRUE(OpenDocument("hello_world.pdf")); EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); diff --git a/fpdfsdk/fpdftext.cpp b/fpdfsdk/fpdftext.cpp index 0432afd7079a6051d3cfdada2bfbb2b3a07d61cd..68bf4f83d7b19ef9748ad45b7973a5048d26f889 100644 --- a/fpdfsdk/fpdftext.cpp +++ b/fpdfsdk/fpdftext.cpp @@ -29,6 +29,8 @@ namespace { +constexpr size_t kBytesPerCharacter = sizeof(unsigned short); + CPDF_TextPage* CPDFTextPageFromFPDFTextPage(FPDF_TEXTPAGE text_page) { return static_cast(text_page); } @@ -43,7 +45,7 @@ CPDF_LinkExtract* CPDFLinkExtractFromFPDFPageLink(FPDF_PAGELINK link) { } // namespace -DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page) { +FPDF_EXPORT FPDF_TEXTPAGE FPDF_CALLCONV FPDFText_LoadPage(FPDF_PAGE page) { CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page); if (!pPDFPage) return nullptr; @@ -53,7 +55,7 @@ DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page) { CPDFXFA_Context* pContext = pPage->GetContext(); CPDF_ViewerPreferences viewRef(pContext->GetPDFDoc()); #else // PDF_ENABLE_XFA - CPDF_ViewerPreferences viewRef(pPDFPage->m_pDocument); + CPDF_ViewerPreferences viewRef(pPDFPage->m_pDocument.Get()); #endif // PDF_ENABLE_XFA CPDF_TextPage* textpage = new CPDF_TextPage( @@ -63,11 +65,11 @@ DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page) { return textpage; } -DLLEXPORT void STDCALL FPDFText_ClosePage(FPDF_TEXTPAGE text_page) { +FPDF_EXPORT void FPDF_CALLCONV FPDFText_ClosePage(FPDF_TEXTPAGE text_page) { delete CPDFTextPageFromFPDFTextPage(text_page); } -DLLEXPORT int STDCALL FPDFText_CountChars(FPDF_TEXTPAGE text_page) { +FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountChars(FPDF_TEXTPAGE text_page) { if (!text_page) return -1; @@ -75,8 +77,8 @@ DLLEXPORT int STDCALL FPDFText_CountChars(FPDF_TEXTPAGE text_page) { return textpage->CountChars(); } -DLLEXPORT unsigned int STDCALL FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, - int index) { +FPDF_EXPORT unsigned int FPDF_CALLCONV +FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, int index) { if (!text_page) return 0; @@ -89,8 +91,8 @@ DLLEXPORT unsigned int STDCALL FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, return charinfo.m_Unicode; } -DLLEXPORT double STDCALL FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, - int index) { +FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, + int index) { if (!text_page) return 0; CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); @@ -103,68 +105,101 @@ DLLEXPORT double STDCALL FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, return charinfo.m_FontSize; } -DLLEXPORT void STDCALL FPDFText_GetCharBox(FPDF_TEXTPAGE text_page, - int index, - double* left, - double* right, - double* bottom, - double* top) { - if (!text_page) - return; +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetCharBox(FPDF_TEXTPAGE text_page, + int index, + double* left, + double* right, + double* bottom, + double* top) { + if (!text_page || index < 0) + return false; + CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); + if (index >= textpage->CountChars()) + return false; - if (index < 0 || index >= textpage->CountChars()) - return; FPDF_CHAR_INFO charinfo; textpage->GetCharInfo(index, &charinfo); *left = charinfo.m_CharBox.left; *right = charinfo.m_CharBox.right; *bottom = charinfo.m_CharBox.bottom; *top = charinfo.m_CharBox.top; + return true; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_GetCharOrigin(FPDF_TEXTPAGE text_page, + int index, + double* x, + double* y) { + if (!text_page) + return false; + CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); + + if (index < 0 || index >= textpage->CountChars()) + return false; + FPDF_CHAR_INFO charinfo; + textpage->GetCharInfo(index, &charinfo); + *x = charinfo.m_Origin.x; + *y = charinfo.m_Origin.y; + return true; } // select -DLLEXPORT int STDCALL FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page, - double x, - double y, - double xTolerance, - double yTolerance) { +FPDF_EXPORT int FPDF_CALLCONV +FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page, + double x, + double y, + double xTolerance, + double yTolerance) { if (!text_page) return -3; CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); return textpage->GetIndexAtPos( - CFX_PointF(static_cast(x), static_cast(y)), - CFX_SizeF(static_cast(xTolerance), - static_cast(yTolerance))); + CFX_PointF(static_cast(x), static_cast(y)), + CFX_SizeF(static_cast(xTolerance), + static_cast(yTolerance))); } -DLLEXPORT int STDCALL FPDFText_GetText(FPDF_TEXTPAGE text_page, - int start, - int count, - unsigned short* result) { - if (!text_page) +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetText(FPDF_TEXTPAGE page, + int char_start, + int char_count, + unsigned short* result) { + if (!page || char_start < 0 || char_count < 0 || !result) return 0; - CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); - if (start >= textpage->CountChars()) + CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(page); + int char_available = textpage->CountChars() - char_start; + if (char_available <= 0) return 0; - CFX_WideString str = textpage->GetPageText(start, count); - if (str.GetLength() > count) - str = str.Left(count); + char_count = std::min(char_count, char_available); + if (char_count == 0) { + // Writing out "", which has a character count of 1 due to the NUL. + *result = '\0'; + return 1; + } + + WideString str = textpage->GetPageText(char_start, char_count); - CFX_ByteString cbUTF16str = str.UTF16LE_Encode(); - FXSYS_memcpy(result, cbUTF16str.GetBuffer(cbUTF16str.GetLength()), - cbUTF16str.GetLength()); - cbUTF16str.ReleaseBuffer(cbUTF16str.GetLength()); + if (str.GetLength() > static_cast(char_count)) + str = str.Left(static_cast(char_count)); - return cbUTF16str.GetLength() / sizeof(unsigned short); + // UFT16LE_Encode doesn't handle surrogate pairs properly, so it is expected + // the number of items to stay the same. + ByteString byte_str = str.UTF16LE_Encode(); + size_t byte_str_len = byte_str.GetLength(); + int ret_count = byte_str_len / kBytesPerCharacter; + + ASSERT(ret_count <= char_count + 1); // +1 to account for the NUL terminator. + memcpy(result, byte_str.GetBuffer(byte_str_len), byte_str_len); + return ret_count; } -DLLEXPORT int STDCALL FPDFText_CountRects(FPDF_TEXTPAGE text_page, - int start, - int count) { +FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountRects(FPDF_TEXTPAGE text_page, + int start, + int count) { if (!text_page) return 0; @@ -172,47 +207,48 @@ DLLEXPORT int STDCALL FPDFText_CountRects(FPDF_TEXTPAGE text_page, return textpage->CountRects(start, count); } -DLLEXPORT void STDCALL FPDFText_GetRect(FPDF_TEXTPAGE text_page, - int rect_index, - double* left, - double* top, - double* right, - double* bottom) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetRect(FPDF_TEXTPAGE text_page, + int rect_index, + double* left, + double* top, + double* right, + double* bottom) { if (!text_page) - return; + return false; CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); CFX_FloatRect rect; - textpage->GetRect(rect_index, rect.left, rect.top, rect.right, rect.bottom); + bool result = textpage->GetRect(rect_index, &rect); + *left = rect.left; *top = rect.top; *right = rect.right; *bottom = rect.bottom; + return result; } -DLLEXPORT int STDCALL FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, - double left, - double top, - double right, - double bottom, - unsigned short* buffer, - int buflen) { +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, + double left, + double top, + double right, + double bottom, + unsigned short* buffer, + int buflen) { if (!text_page) return 0; CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page); - CFX_FloatRect rect((FX_FLOAT)left, (FX_FLOAT)bottom, (FX_FLOAT)right, - (FX_FLOAT)top); - CFX_WideString str = textpage->GetTextByRect(rect); + CFX_FloatRect rect((float)left, (float)bottom, (float)right, (float)top); + WideString str = textpage->GetTextByRect(rect); if (buflen <= 0 || !buffer) return str.GetLength(); - CFX_ByteString cbUTF16Str = str.UTF16LE_Encode(); + ByteString cbUTF16Str = str.UTF16LE_Encode(); int len = cbUTF16Str.GetLength() / sizeof(unsigned short); int size = buflen > len ? len : buflen; - FXSYS_memcpy(buffer, cbUTF16Str.GetBuffer(size * sizeof(unsigned short)), - size * sizeof(unsigned short)); + memcpy(buffer, cbUTF16Str.GetBuffer(size * sizeof(unsigned short)), + size * sizeof(unsigned short)); cbUTF16Str.ReleaseBuffer(size * sizeof(unsigned short)); return size; @@ -220,22 +256,24 @@ DLLEXPORT int STDCALL FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, // Search // -1 for end -DLLEXPORT FPDF_SCHHANDLE STDCALL FPDFText_FindStart(FPDF_TEXTPAGE text_page, - FPDF_WIDESTRING findwhat, - unsigned long flags, - int start_index) { +FPDF_EXPORT FPDF_SCHHANDLE FPDF_CALLCONV +FPDFText_FindStart(FPDF_TEXTPAGE text_page, + FPDF_WIDESTRING findwhat, + unsigned long flags, + int start_index) { if (!text_page) return nullptr; CPDF_TextPageFind* textpageFind = new CPDF_TextPageFind(CPDFTextPageFromFPDFTextPage(text_page)); - FX_STRSIZE len = CFX_WideString::WStringLength(findwhat); - textpageFind->FindFirst(CFX_WideString::FromUTF16LE(findwhat, len), flags, - start_index); + size_t len = WideString::WStringLength(findwhat); + textpageFind->FindFirst( + WideString::FromUTF16LE(findwhat, len), flags, + start_index >= 0 ? Optional(start_index) : Optional()); return textpageFind; } -DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindNext(FPDF_SCHHANDLE handle) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindNext(FPDF_SCHHANDLE handle) { if (!handle) return false; @@ -243,7 +281,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindNext(FPDF_SCHHANDLE handle) { return textpageFind->FindNext(); } -DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindPrev(FPDF_SCHHANDLE handle) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindPrev(FPDF_SCHHANDLE handle) { if (!handle) return false; @@ -251,7 +289,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindPrev(FPDF_SCHHANDLE handle) { return textpageFind->FindPrev(); } -DLLEXPORT int STDCALL FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle) { +FPDF_EXPORT int FPDF_CALLCONV +FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle) { if (!handle) return 0; @@ -259,7 +298,7 @@ DLLEXPORT int STDCALL FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle) { return textpageFind->GetCurOrder(); } -DLLEXPORT int STDCALL FPDFText_GetSchCount(FPDF_SCHHANDLE handle) { +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetSchCount(FPDF_SCHHANDLE handle) { if (!handle) return 0; @@ -267,7 +306,7 @@ DLLEXPORT int STDCALL FPDFText_GetSchCount(FPDF_SCHHANDLE handle) { return textpageFind->GetMatchedCount(); } -DLLEXPORT void STDCALL FPDFText_FindClose(FPDF_SCHHANDLE handle) { +FPDF_EXPORT void FPDF_CALLCONV FPDFText_FindClose(FPDF_SCHHANDLE handle) { if (!handle) return; @@ -277,7 +316,8 @@ DLLEXPORT void STDCALL FPDFText_FindClose(FPDF_SCHHANDLE handle) { } // web link -DLLEXPORT FPDF_PAGELINK STDCALL FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page) { +FPDF_EXPORT FPDF_PAGELINK FPDF_CALLCONV +FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page) { if (!text_page) return nullptr; @@ -287,7 +327,7 @@ DLLEXPORT FPDF_PAGELINK STDCALL FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page) { return pageLink; } -DLLEXPORT int STDCALL FPDFLink_CountWebLinks(FPDF_PAGELINK link_page) { +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountWebLinks(FPDF_PAGELINK link_page) { if (!link_page) return 0; @@ -295,16 +335,16 @@ DLLEXPORT int STDCALL FPDFLink_CountWebLinks(FPDF_PAGELINK link_page) { return pdfium::base::checked_cast(pageLink->CountLinks()); } -DLLEXPORT int STDCALL FPDFLink_GetURL(FPDF_PAGELINK link_page, - int link_index, - unsigned short* buffer, - int buflen) { - CFX_WideString wsUrl(L""); +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetURL(FPDF_PAGELINK link_page, + int link_index, + unsigned short* buffer, + int buflen) { + WideString wsUrl(L""); if (link_page && link_index >= 0) { CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page); wsUrl = pageLink->GetURL(link_index); } - CFX_ByteString cbUTF16URL = wsUrl.UTF16LE_Encode(); + ByteString cbUTF16URL = wsUrl.UTF16LE_Encode(); int required = cbUTF16URL.GetLength() / sizeof(unsigned short); if (!buffer || buflen <= 0) return required; @@ -312,13 +352,13 @@ DLLEXPORT int STDCALL FPDFLink_GetURL(FPDF_PAGELINK link_page, int size = std::min(required, buflen); if (size > 0) { int buf_size = size * sizeof(unsigned short); - FXSYS_memcpy(buffer, cbUTF16URL.GetBuffer(buf_size), buf_size); + memcpy(buffer, cbUTF16URL.GetBuffer(buf_size), buf_size); } return size; } -DLLEXPORT int STDCALL FPDFLink_CountRects(FPDF_PAGELINK link_page, - int link_index) { +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountRects(FPDF_PAGELINK link_page, + int link_index) { if (!link_page || link_index < 0) return 0; @@ -326,27 +366,28 @@ DLLEXPORT int STDCALL FPDFLink_CountRects(FPDF_PAGELINK link_page, return pdfium::CollectionSize(pageLink->GetRects(link_index)); } -DLLEXPORT void STDCALL FPDFLink_GetRect(FPDF_PAGELINK link_page, - int link_index, - int rect_index, - double* left, - double* top, - double* right, - double* bottom) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetRect(FPDF_PAGELINK link_page, + int link_index, + int rect_index, + double* left, + double* top, + double* right, + double* bottom) { if (!link_page || link_index < 0 || rect_index < 0) - return; + return false; CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page); std::vector rectArray = pageLink->GetRects(link_index); if (rect_index >= pdfium::CollectionSize(rectArray)) - return; + return false; *left = rectArray[rect_index].left; *right = rectArray[rect_index].right; *top = rectArray[rect_index].top; *bottom = rectArray[rect_index].bottom; + return true; } -DLLEXPORT void STDCALL FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page) { +FPDF_EXPORT void FPDF_CALLCONV FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page) { delete CPDFLinkExtractFromFPDFPageLink(link_page); } diff --git a/fpdfsdk/fpdftext_embeddertest.cpp b/fpdfsdk/fpdftext_embeddertest.cpp index 198ef8a7f2f1af23b434e79f20edbf902e2b4ff5..86d32a711a69e34575bba4b133c8da4472320ba3 100644 --- a/fpdfsdk/fpdftext_embeddertest.cpp +++ b/fpdfsdk/fpdftext_embeddertest.cpp @@ -4,7 +4,7 @@ #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_memory.h" #include "public/fpdf_text.h" #include "public/fpdfview.h" #include "testing/embedder_test.h" @@ -16,13 +16,12 @@ namespace { bool check_unsigned_shorts(const char* expected, const unsigned short* actual, size_t length) { - if (length > strlen(expected) + 1) { + if (length > strlen(expected) + 1) return false; - } + for (size_t i = 0; i < length; ++i) { - if (actual[i] != static_cast(expected[i])) { + if (actual[i] != static_cast(expected[i])) return false; - } } return true; } @@ -43,6 +42,19 @@ TEST_F(FPDFTextEmbeddertest, Text) { unsigned short fixed_buffer[128]; memset(fixed_buffer, 0xbd, sizeof(fixed_buffer)); + // Check that edge cases are handled gracefully + EXPECT_EQ(0, FPDFText_GetText(textpage, 0, 128, nullptr)); + EXPECT_EQ(0, FPDFText_GetText(textpage, -1, 128, fixed_buffer)); + EXPECT_EQ(0, FPDFText_GetText(textpage, 0, -1, fixed_buffer)); + EXPECT_EQ(1, FPDFText_GetText(textpage, 0, 0, fixed_buffer)); + EXPECT_EQ(0, fixed_buffer[0]); + + // Keep going and check the next case. + memset(fixed_buffer, 0xbd, sizeof(fixed_buffer)); + EXPECT_EQ(2, FPDFText_GetText(textpage, 0, 1, fixed_buffer)); + EXPECT_EQ(expected[0], fixed_buffer[0]); + EXPECT_EQ(0, fixed_buffer[1]); + // Check includes the terminating NUL that is provided. int num_chars = FPDFText_GetText(textpage, 0, 128, fixed_buffer); ASSERT_GE(num_chars, 0); @@ -58,6 +70,16 @@ TEST_F(FPDFTextEmbeddertest, Text) { << " at " << i; } + // Extracting using a buffer that will be completely filled. Small buffer is + // 12 elements long, since it will need 2 locations per displayed character in + // the expected string, plus 2 more for the terminating character. + static const char small_expected[] = "Hello"; + unsigned short small_buffer[12]; + memset(fixed_buffer, 0xbd, sizeof(fixed_buffer)); + EXPECT_EQ(6, FPDFText_GetText(textpage, 0, 5, small_buffer)); + EXPECT_TRUE(check_unsigned_shorts(small_expected, small_buffer, + sizeof(small_expected))); + EXPECT_EQ(12.0, FPDFText_GetFontSize(textpage, 0)); EXPECT_EQ(16.0, FPDFText_GetFontSize(textpage, 15)); @@ -65,12 +87,34 @@ TEST_F(FPDFTextEmbeddertest, Text) { double right = 0.0; double bottom = 0.0; double top = 0.0; - FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, &top); + EXPECT_FALSE(FPDFText_GetCharBox(nullptr, 4, &left, &right, &bottom, &top)); + EXPECT_DOUBLE_EQ(0.0, left); + EXPECT_DOUBLE_EQ(0.0, right); + EXPECT_DOUBLE_EQ(0.0, bottom); + EXPECT_DOUBLE_EQ(0.0, top); + EXPECT_FALSE(FPDFText_GetCharBox(textpage, -1, &left, &right, &bottom, &top)); + EXPECT_DOUBLE_EQ(0.0, left); + EXPECT_DOUBLE_EQ(0.0, right); + EXPECT_DOUBLE_EQ(0.0, bottom); + EXPECT_DOUBLE_EQ(0.0, top); + EXPECT_FALSE(FPDFText_GetCharBox(textpage, 55, &left, &right, &bottom, &top)); + EXPECT_DOUBLE_EQ(0.0, left); + EXPECT_DOUBLE_EQ(0.0, right); + EXPECT_DOUBLE_EQ(0.0, bottom); + EXPECT_DOUBLE_EQ(0.0, top); + + EXPECT_TRUE(FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, &top)); EXPECT_NEAR(41.071, left, 0.001); EXPECT_NEAR(46.243, right, 0.001); EXPECT_NEAR(49.844, bottom, 0.001); EXPECT_NEAR(55.520, top, 0.001); + double x = 0.0; + double y = 0.0; + EXPECT_TRUE(FPDFText_GetCharOrigin(textpage, 4, &x, &y)); + EXPECT_NEAR(40.664, x, 0.001); + EXPECT_NEAR(50.000, y, 0.001); + EXPECT_EQ(4, FPDFText_GetCharIndexAtPos(textpage, 42.0, 50.0, 1.0, 1.0)); EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 0.0, 0.0, 1.0, 1.0)); EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 199.0, 199.0, 1.0, 1.0)); @@ -87,7 +131,7 @@ TEST_F(FPDFTextEmbeddertest, Text) { right = 0.0; bottom = 0.0; top = 0.0; - FPDFText_GetRect(textpage, 1, &left, &top, &right, &bottom); + EXPECT_TRUE(FPDFText_GetRect(textpage, 1, &left, &top, &right, &bottom)); EXPECT_NEAR(20.847, left, 0.001); EXPECT_NEAR(135.167, right, 0.001); EXPECT_NEAR(96.655, bottom, 0.001); @@ -98,7 +142,7 @@ TEST_F(FPDFTextEmbeddertest, Text) { right = -1.0; bottom = -1.0; top = -1.0; - FPDFText_GetRect(textpage, -1, &left, &top, &right, &bottom); + EXPECT_FALSE(FPDFText_GetRect(textpage, -1, &left, &top, &right, &bottom)); EXPECT_EQ(0.0, left); EXPECT_EQ(0.0, right); EXPECT_EQ(0.0, bottom); @@ -108,7 +152,7 @@ TEST_F(FPDFTextEmbeddertest, Text) { right = -2.0; bottom = -2.0; top = -2.0; - FPDFText_GetRect(textpage, 2, &left, &top, &right, &bottom); + EXPECT_FALSE(FPDFText_GetRect(textpage, 2, &left, &top, &right, &bottom)); EXPECT_EQ(0.0, left); EXPECT_EQ(0.0, right); EXPECT_EQ(0.0, bottom); @@ -337,7 +381,7 @@ TEST_F(FPDFTextEmbeddertest, WebLinks) { double right = 0.0; double top = 0.0; double bottom = 0.0; - FPDFLink_GetRect(pagelink, 0, 0, &left, &top, &right, &bottom); + EXPECT_TRUE(FPDFLink_GetRect(pagelink, 0, 0, &left, &top, &right, &bottom)); EXPECT_NEAR(50.791, left, 0.001); EXPECT_NEAR(187.963, right, 0.001); EXPECT_NEAR(97.624, bottom, 0.001); @@ -348,7 +392,7 @@ TEST_F(FPDFTextEmbeddertest, WebLinks) { right = -1.0; top = -1.0; bottom = -1.0; - FPDFLink_GetRect(pagelink, 0, 1, &left, &top, &right, &bottom); + EXPECT_FALSE(FPDFLink_GetRect(pagelink, 0, 1, &left, &top, &right, &bottom)); EXPECT_EQ(-1.0, left); EXPECT_EQ(-1.0, right); EXPECT_EQ(-1.0, bottom); @@ -359,7 +403,7 @@ TEST_F(FPDFTextEmbeddertest, WebLinks) { right = -2.0; top = -2.0; bottom = -2.0; - FPDFLink_GetRect(pagelink, -1, 0, &left, &top, &right, &bottom); + EXPECT_FALSE(FPDFLink_GetRect(pagelink, -1, 0, &left, &top, &right, &bottom)); EXPECT_EQ(-2.0, left); EXPECT_EQ(-2.0, right); EXPECT_EQ(-2.0, bottom); @@ -370,6 +414,74 @@ TEST_F(FPDFTextEmbeddertest, WebLinks) { UnloadPage(page); } +TEST_F(FPDFTextEmbeddertest, WebLinksAcrossLines) { + EXPECT_TRUE(OpenDocument("weblinks_across_lines.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); + EXPECT_TRUE(textpage); + + FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage); + EXPECT_TRUE(pagelink); + + static const char* const kExpectedUrls[] = { + "http://example.com", // from "http://www.example.com?\r\nfoo" + "http://example.com/", // from "http://www.example.com/\r\nfoo" + "http://example.com/test-foo", // from "http://example.com/test-\r\nfoo" + "http://abc.com/test-foo", // from "http://abc.com/test-\r\n\r\nfoo" + // Next two links from "http://www.example.com/\r\nhttp://www.abc.com/" + "http://example.com/", "http://www.abc.com", + }; + static const int kNumLinks = static_cast(FX_ArraySize(kExpectedUrls)); + + EXPECT_EQ(kNumLinks, FPDFLink_CountWebLinks(pagelink)); + + unsigned short fixed_buffer[128]; + for (int i = 0; i < kNumLinks; i++) { + const size_t expected_len = strlen(kExpectedUrls[i]) + 1; + memset(fixed_buffer, 0, FX_ArraySize(fixed_buffer)); + EXPECT_EQ(static_cast(expected_len), + FPDFLink_GetURL(pagelink, i, nullptr, 0)); + EXPECT_EQ( + static_cast(expected_len), + FPDFLink_GetURL(pagelink, i, fixed_buffer, FX_ArraySize(fixed_buffer))); + EXPECT_TRUE( + check_unsigned_shorts(kExpectedUrls[i], fixed_buffer, expected_len)); + } + + FPDFLink_CloseWebLinks(pagelink); + FPDFText_ClosePage(textpage); + UnloadPage(page); +} + +TEST_F(FPDFTextEmbeddertest, WebLinksAcrossLinesBug) { + EXPECT_TRUE(OpenDocument("bug_650.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); + EXPECT_TRUE(textpage); + + FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage); + EXPECT_TRUE(pagelink); + + EXPECT_EQ(2, FPDFLink_CountWebLinks(pagelink)); + unsigned short fixed_buffer[128] = {0}; + static const char kExpectedUrl[] = + "http://tutorial45.com/learn-autocad-basics-day-166/"; + static const int kUrlSize = static_cast(sizeof(kExpectedUrl)); + + EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, nullptr, 0)); + EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, fixed_buffer, + FX_ArraySize(fixed_buffer))); + EXPECT_TRUE(check_unsigned_shorts(kExpectedUrl, fixed_buffer, kUrlSize)); + + FPDFLink_CloseWebLinks(pagelink); + FPDFText_ClosePage(textpage); + UnloadPage(page); +} + TEST_F(FPDFTextEmbeddertest, GetFontSize) { EXPECT_TRUE(OpenDocument("hello_world.pdf")); FPDF_PAGE page = LoadPage(0); @@ -405,3 +517,127 @@ TEST_F(FPDFTextEmbeddertest, ToUnicode) { FPDFText_ClosePage(textpage); UnloadPage(page); } + +TEST_F(FPDFTextEmbeddertest, Bug_921) { + EXPECT_TRUE(OpenDocument("bug_921.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); + EXPECT_TRUE(textpage); + + static constexpr unsigned int kData[] = { + 1095, 1077, 1083, 1086, 1074, 1077, 1095, 1077, 1089, 1082, 1086, 1077, + 32, 1089, 1090, 1088, 1072, 1076, 1072, 1085, 1080, 1077, 46, 32}; + static constexpr int kStartIndex = 238; + + ASSERT_EQ(268, FPDFText_CountChars(textpage)); + for (size_t i = 0; i < FX_ArraySize(kData); ++i) + EXPECT_EQ(kData[i], FPDFText_GetUnicode(textpage, kStartIndex + i)); + + unsigned short buffer[FX_ArraySize(kData) + 1]; + memset(buffer, 0xbd, sizeof(buffer)); + int count = + FPDFText_GetText(textpage, kStartIndex, FX_ArraySize(kData), buffer); + ASSERT_GT(count, 0); + ASSERT_EQ(FX_ArraySize(kData) + 1, static_cast(count)); + for (size_t i = 0; i < FX_ArraySize(kData); ++i) + EXPECT_EQ(kData[i], buffer[i]); + EXPECT_EQ(0, buffer[FX_ArraySize(kData)]); + + FPDFText_ClosePage(textpage); + UnloadPage(page); +} + +TEST_F(FPDFTextEmbeddertest, GetTextWithHyphen) { + EXPECT_TRUE(OpenDocument("bug_781804.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); + EXPECT_TRUE(textpage); + + // Check that soft hyphens are not included + // Expecting 'Veritaserum', except there is a \uFFFE where the hyphen was in + // the original text. This is a weird thing that Adobe does, which we + // replicate. + constexpr unsigned short soft_expected[] = { + 0x0056, 0x0065, 0x0072, 0x0069, 0x0074, 0x0061, 0xfffe, + 0x0073, 0x0065, 0x0072, 0x0075, 0x006D, 0x0000}; + { + constexpr int count = FX_ArraySize(soft_expected) - 1; + unsigned short buffer[FX_ArraySize(soft_expected)]; + memset(buffer, 0, sizeof(buffer)); + + EXPECT_EQ(count + 1, FPDFText_GetText(textpage, 0, count, buffer)); + for (int i = 0; i < count; i++) + EXPECT_EQ(soft_expected[i], buffer[i]); + } + + // Check that hard hyphens are included + { + // There isn't the \0 in the actual doc, but there is a \r\n, so need to + // add 1 to get aligned. + constexpr size_t offset = FX_ArraySize(soft_expected) + 1; + // Expecting 'User-\r\ngenerated', the - is a unicode character, so cannnot + // store in a char[]. + constexpr unsigned short hard_expected[] = { + 0x0055, 0x0073, 0x0065, 0x0072, 0x2010, 0x000d, 0x000a, 0x0067, 0x0065, + 0x006e, 0x0065, 0x0072, 0x0061, 0x0074, 0x0065, 0x0064, 0x0000}; + constexpr int count = FX_ArraySize(hard_expected) - 1; + unsigned short buffer[FX_ArraySize(hard_expected)]; + + EXPECT_EQ(count + 1, FPDFText_GetText(textpage, offset, count, buffer)); + for (int i = 0; i < count; i++) + EXPECT_EQ(hard_expected[i], buffer[i]); + } + + FPDFText_ClosePage(textpage); + UnloadPage(page); +} + +TEST_F(FPDFTextEmbeddertest, bug_782596) { + // If there is a regression in this test, it will only fail under ASAN + EXPECT_TRUE(OpenDocument("bug_782596.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); + EXPECT_TRUE(textpage); + FPDFText_ClosePage(textpage); + UnloadPage(page); +} + +TEST_F(FPDFTextEmbeddertest, ControlCharacters) { + EXPECT_TRUE(OpenDocument("control_characters.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_TRUE(page); + + FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); + EXPECT_TRUE(textpage); + + // Should not include the control characters in the output + static const char expected[] = "Hello, world!\r\nGoodbye, world!"; + unsigned short fixed_buffer[128]; + memset(fixed_buffer, 0xbd, sizeof(fixed_buffer)); + int num_chars = FPDFText_GetText(textpage, 0, 128, fixed_buffer); + + ASSERT_GE(num_chars, 0); + EXPECT_EQ(sizeof(expected), static_cast(num_chars)); + EXPECT_TRUE(check_unsigned_shorts(expected, fixed_buffer, sizeof(expected))); + + // Attempting to get a chunk of text after the control characters + static const char expected_substring[] = "Goodbye, world!"; + // Offset is the length of 'Hello, world!\r\n' + 2 control characters in the + // original stream + static const int offset = 17; + memset(fixed_buffer, 0xbd, sizeof(fixed_buffer)); + num_chars = FPDFText_GetText(textpage, offset, 128, fixed_buffer); + + ASSERT_GE(num_chars, 0); + EXPECT_EQ(sizeof(expected_substring), static_cast(num_chars)); + EXPECT_TRUE(check_unsigned_shorts(expected_substring, fixed_buffer, + sizeof(expected_substring))); + + FPDFText_ClosePage(textpage); + UnloadPage(page); +} diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp index 1e7a651aa8266dc6ad038e252ff3eea3b0a78e71..97fc02a23439535cce5c47c0aa7ccc23d58d16f5 100644 --- a/fpdfsdk/fpdfview.cpp +++ b/fpdfsdk/fpdfview.cpp @@ -8,11 +8,17 @@ #include #include +#include #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/cpdf_pagerendercontext.h" +#include "core/fpdfapi/page/cpdf_image.h" +#include "core/fpdfapi/page/cpdf_imageobject.h" #include "core/fpdfapi/page/cpdf_page.h" +#include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfapi/render/cpdf_progressiverenderer.h" @@ -21,18 +27,21 @@ #include "core/fpdfdoc/cpdf_nametree.h" #include "core/fpdfdoc/cpdf_occontext.h" #include "core/fpdfdoc/cpdf_viewerpreferences.h" -#include "core/fxcodec/fx_codec.h" #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/cfx_fxgedevice.h" +#include "core/fxcrt/fx_stream.h" +#include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_gemodule.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_pageview.h" #include "fpdfsdk/fsdk_define.h" #include "fpdfsdk/fsdk_pauseadapter.h" -#include "fpdfsdk/javascript/ijs_runtime.h" +#include "fxjs/ijs_runtime.h" +#include "public/fpdf_edit.h" #include "public/fpdf_ext.h" +#include "public/fpdf_formfill.h" #include "public/fpdf_progressive.h" +#include "third_party/base/allocator/partition_allocator/partition_alloc.h" #include "third_party/base/numerics/safe_conversions_impl.h" #include "third_party/base/ptr_util.h" @@ -40,34 +49,26 @@ #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h" -#include "public/fpdf_formfill.h" -#include "xfa/fxbarcode/BC_Library.h" +#include "fxbarcode/BC_Library.h" #endif // PDF_ENABLE_XFA -#ifdef PDF_ENABLE_XFA_BMP -#include "core/fxcodec/codec/ccodec_bmpmodule.h" -#endif - -#ifdef PDF_ENABLE_XFA_GIF -#include "core/fxcodec/codec/ccodec_gifmodule.h" -#endif - -#ifdef PDF_ENABLE_XFA_PNG -#include "core/fxcodec/codec/ccodec_pngmodule.h" -#endif - -#ifdef PDF_ENABLE_XFA_TIFF -#include "core/fxcodec/codec/ccodec_tiffmodule.h" -#endif - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#include "core/fxge/cfx_windowsdevice.h" +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#include "core/fxge/cfx_windowsrenderdevice.h" + +// These checks are here because core/ and public/ cannot depend on each other. +static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF, + "WindowsPrintMode::kModeEmf value mismatch"); +static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY, + "WindowsPrintMode::kModeTextOnly value mismatch"); +static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2, + "WindowsPrintMode::kModePostScript2 value mismatch"); +static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3, + "WindowsPrintMode::kModePostScript3 value mismatch"); #endif namespace { -// Also indicates whether library is currently initialized. -CCodec_ModuleMgr* g_pCodecModule = nullptr; +bool g_bLibraryInitialized = false; void RenderPageImpl(CPDF_PageRenderContext* pContext, CPDF_Page* pPage, @@ -79,42 +80,39 @@ void RenderPageImpl(CPDF_PageRenderContext* pContext, if (!pContext->m_pOptions) pContext->m_pOptions = pdfium::MakeUnique(); + uint32_t option_flags = pContext->m_pOptions->GetFlags(); if (flags & FPDF_LCD_TEXT) - pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE; + option_flags |= RENDER_CLEARTYPE; else - pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE; + option_flags &= ~RENDER_CLEARTYPE; if (flags & FPDF_NO_NATIVETEXT) - pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT; + option_flags |= RENDER_NO_NATIVETEXT; if (flags & FPDF_RENDER_LIMITEDIMAGECACHE) - pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE; + option_flags |= RENDER_LIMITEDIMAGECACHE; if (flags & FPDF_RENDER_FORCEHALFTONE) - pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE; + option_flags |= RENDER_FORCE_HALFTONE; #ifndef PDF_ENABLE_XFA if (flags & FPDF_RENDER_NO_SMOOTHTEXT) - pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH; + option_flags |= RENDER_NOTEXTSMOOTH; if (flags & FPDF_RENDER_NO_SMOOTHIMAGE) - pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH; + option_flags |= RENDER_NOIMAGESMOOTH; if (flags & FPDF_RENDER_NO_SMOOTHPATH) - pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH; + option_flags |= RENDER_NOPATHSMOOTH; #endif // PDF_ENABLE_XFA + pContext->m_pOptions->SetFlags(option_flags); // Grayscale output - if (flags & FPDF_GRAYSCALE) { - pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY; - pContext->m_pOptions->m_ForeColor = 0; - pContext->m_pOptions->m_BackColor = 0xffffff; - } + if (flags & FPDF_GRAYSCALE) + pContext->m_pOptions->SetColorMode(CPDF_RenderOptions::kGray); const CPDF_OCContext::UsageType usage = (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View; - pContext->m_pOptions->m_AddFlags = flags >> 8; - pContext->m_pOptions->m_pOCContext = - pdfium::MakeRetain(pPage->m_pDocument, usage); + pContext->m_pOptions->SetOCContext( + pdfium::MakeRetain(pPage->m_pDocument.Get(), usage)); pContext->m_pDevice->SaveState(); pContext->m_pDevice->SetClip_Rect(clipping_rect); - pContext->m_pContext = pdfium::MakeUnique(pPage); pContext->m_pContext->AppendLayer(pPage, &matrix); @@ -135,9 +133,8 @@ void RenderPageImpl(CPDF_PageRenderContext* pContext, class CPDF_CustomAccess final : public IFX_SeekableReadStream { public: - static CFX_RetainPtr Create(FPDF_FILEACCESS* pFileAccess) { - return CFX_RetainPtr(new CPDF_CustomAccess(pFileAccess)); - } + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); // IFX_SeekableReadStream FX_FILESIZE GetSize() override; @@ -169,16 +166,16 @@ bool CPDF_CustomAccess::ReadBlock(void* buffer, return false; } return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset, - reinterpret_cast(buffer), size); + static_cast(buffer), size); } #ifdef PDF_ENABLE_XFA -class CFPDF_FileStream : public IFX_SeekableStream { +class FPDF_FileHandlerContext : public IFX_SeekableStream { public: - static CFX_RetainPtr Create(FPDF_FILEHANDLER* pFS) { - return CFX_RetainPtr(new CFPDF_FileStream(pFS)); - } - ~CFPDF_FileStream() override; + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + ~FPDF_FileHandlerContext() override; // IFX_SeekableStream: FX_FILESIZE GetSize() override; @@ -192,39 +189,39 @@ class CFPDF_FileStream : public IFX_SeekableStream { void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; } protected: - explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS); + explicit FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS); FPDF_FILEHANDLER* m_pFS; FX_FILESIZE m_nCurPos; }; -CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) { +FPDF_FileHandlerContext::FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS) { m_pFS = pFS; m_nCurPos = 0; } -CFPDF_FileStream::~CFPDF_FileStream() { +FPDF_FileHandlerContext::~FPDF_FileHandlerContext() { if (m_pFS && m_pFS->Release) m_pFS->Release(m_pFS->clientData); } -FX_FILESIZE CFPDF_FileStream::GetSize() { +FX_FILESIZE FPDF_FileHandlerContext::GetSize() { if (m_pFS && m_pFS->GetSize) return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData); return 0; } -bool CFPDF_FileStream::IsEOF() { +bool FPDF_FileHandlerContext::IsEOF() { return m_nCurPos >= GetSize(); } -FX_FILESIZE CFPDF_FileStream::GetPosition() { +FX_FILESIZE FPDF_FileHandlerContext::GetPosition() { return m_nCurPos; } -bool CFPDF_FileStream::ReadBlock(void* buffer, - FX_FILESIZE offset, - size_t size) { +bool FPDF_FileHandlerContext::ReadBlock(void* buffer, + FX_FILESIZE offset, + size_t size) { if (!buffer || !size || !m_pFS->ReadBlock) return false; @@ -236,7 +233,7 @@ bool CFPDF_FileStream::ReadBlock(void* buffer, return false; } -size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) { +size_t FPDF_FileHandlerContext::ReadBlock(void* buffer, size_t size) { if (!buffer || !size || !m_pFS->ReadBlock) return 0; @@ -245,7 +242,7 @@ size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) { return 0; FX_FILESIZE dwAvail = nSize - m_nCurPos; if (dwAvail < (FX_FILESIZE)size) - size = (size_t)dwAvail; + size = static_cast(dwAvail); if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer, (FPDF_DWORD)size) == 0) { m_nCurPos += size; @@ -255,9 +252,9 @@ size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) { return 0; } -bool CFPDF_FileStream::WriteBlock(const void* buffer, - FX_FILESIZE offset, - size_t size) { +bool FPDF_FileHandlerContext::WriteBlock(const void* buffer, + FX_FILESIZE offset, + size_t size) { if (!m_pFS || !m_pFS->WriteBlock) return false; @@ -269,7 +266,7 @@ bool CFPDF_FileStream::WriteBlock(const void* buffer, return false; } -bool CFPDF_FileStream::Flush() { +bool FPDF_FileHandlerContext::Flush() { if (!m_pFS || !m_pFS->Flush) return true; @@ -277,6 +274,28 @@ bool CFPDF_FileStream::Flush() { } #endif // PDF_ENABLE_XFA +FPDF_DOCUMENT LoadDocumentImpl( + const RetainPtr& pFileAccess, + FPDF_BYTESTRING password) { + if (!pFileAccess) { + ProcessParseError(CPDF_Parser::FILE_ERROR); + return nullptr; + } + + auto pParser = pdfium::MakeUnique(); + pParser->SetPassword(password); + + auto pDocument = pdfium::MakeUnique(std::move(pParser)); + CPDF_Parser::Error error = + pDocument->GetParser()->StartParse(pFileAccess, pDocument.get()); + if (error != CPDF_Parser::SUCCESS) { + ProcessParseError(error); + return nullptr; + } + CheckUnSupportError(pDocument.get(), error); + return FPDFDocumentFromCPDFDocument(pDocument.release()); +} + } // namespace UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) { @@ -317,19 +336,101 @@ CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page) { #endif // PDF_ENABLE_XFA } +CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) { + auto* obj = CPDFPageObjectFromFPDFPageObject(page_object); + return obj ? obj->AsPath() : nullptr; +} + +CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) { + return static_cast(page_object); +} + +CPDF_Object* CPDFObjectFromFPDFAttachment(FPDF_ATTACHMENT attachment) { + return static_cast(attachment); +} + +ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) { + return WideString::FromUTF16LE(wide_string, + WideString::WStringLength(wide_string)) + .UTF8Encode(); +} + CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) { return static_cast(bitmap); } -CFX_RetainPtr MakeSeekableReadStream( +CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect) { + return CFX_FloatRect(rect.left, rect.bottom, rect.right, rect.top); +} + +void FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect, FS_RECTF* out_rect) { + out_rect->left = rect.left; + out_rect->top = rect.top; + out_rect->right = rect.right; + out_rect->bottom = rect.bottom; +} + +const FX_PATHPOINT* FXPathPointFromFPDFPathSegment(FPDF_PATHSEGMENT segment) { + return static_cast(segment); +} + +unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text, + void* buffer, + unsigned long buflen) { + ByteString encoded_text = text.UTF16LE_Encode(); + unsigned long len = encoded_text.GetLength(); + if (buffer && len <= buflen) + memcpy(buffer, encoded_text.c_str(), len); + return len; +} + +unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream, + void* buffer, + unsigned long buflen) { + ASSERT(stream); + uint8_t* data = stream->GetRawData(); + uint32_t len = stream->GetRawSize(); + CPDF_Dictionary* dict = stream->GetDict(); + CPDF_Object* decoder = dict ? dict->GetDirectObjectFor("Filter") : nullptr; + if (decoder && (decoder->IsArray() || decoder->IsName())) { + // Decode the stream if one or more stream filters are specified. + uint8_t* decoded_data = nullptr; + uint32_t decoded_len = 0; + ByteString dummy_last_decoder; + CPDF_Dictionary* dummy_last_param; + if (PDF_DataDecode(data, len, dict, dict->GetIntegerFor("DL"), false, + &decoded_data, &decoded_len, &dummy_last_decoder, + &dummy_last_param)) { + if (buffer && buflen >= decoded_len) + memcpy(buffer, decoded_data, decoded_len); + + // Free the buffer for the decoded data if it was allocated by + // PDF_DataDecode(). Note that for images with a single image-specific + // filter, |decoded_data| is directly assigned to be |data|, so + // |decoded_data| does not need to be freed. + if (decoded_data != data) + FX_Free(decoded_data); + + return decoded_len; + } + } + // Copy the raw data and return its length if there is no valid filter + // specified or if decoding failed. + if (buffer && buflen >= len) + memcpy(buffer, data, len); + + return len; +} + +RetainPtr MakeSeekableReadStream( FPDF_FILEACCESS* pFileAccess) { - return CPDF_CustomAccess::Create(pFileAccess); + return pdfium::MakeRetain(pFileAccess); } #ifdef PDF_ENABLE_XFA -CFX_RetainPtr MakeSeekableStream( +RetainPtr MakeSeekableStream( FPDF_FILEHANDLER* pFilehandler) { - return CFPDF_FileStream::Create(pFilehandler); + return pdfium::MakeRetain(pFilehandler); } #endif // PDF_ENABLE_XFA @@ -358,72 +459,46 @@ FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy) { } } -DLLEXPORT void STDCALL FPDF_InitLibrary() { +FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary() { FPDF_InitLibraryWithConfig(nullptr); } -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) { - if (g_pCodecModule) + if (g_bLibraryInitialized) return; - g_pCodecModule = new CCodec_ModuleMgr(); + FXMEM_InitializePartitionAlloc(); CFX_GEModule* pModule = CFX_GEModule::Get(); - pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr, g_pCodecModule); + pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr); CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get(); - pModuleMgr->SetCodecModule(g_pCodecModule); - pModuleMgr->InitPageModule(); - pModuleMgr->LoadEmbeddedGB1CMaps(); - pModuleMgr->LoadEmbeddedJapan1CMaps(); - pModuleMgr->LoadEmbeddedCNS1CMaps(); - pModuleMgr->LoadEmbeddedKorea1CMaps(); - -#ifdef PDF_ENABLE_XFA_BMP - pModuleMgr->GetCodecModule()->SetBmpModule( - pdfium::MakeUnique()); -#endif - -#ifdef PDF_ENABLE_XFA_GIF - pModuleMgr->GetCodecModule()->SetGifModule( - pdfium::MakeUnique()); -#endif - -#ifdef PDF_ENABLE_XFA_PNG - pModuleMgr->GetCodecModule()->SetPngModule( - pdfium::MakeUnique()); -#endif - -#ifdef PDF_ENABLE_XFA_TIFF - pModuleMgr->GetCodecModule()->SetTiffModule( - pdfium::MakeUnique()); -#endif + pModuleMgr->Init(); #ifdef PDF_ENABLE_XFA - FXJSE_Initialize(); BC_Library_Init(); #endif // PDF_ENABLE_XFA if (cfg && cfg->version >= 2) IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate); + + g_bLibraryInitialized = true; } -DLLEXPORT void STDCALL FPDF_DestroyLibrary() { - if (!g_pCodecModule) +FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary() { + if (!g_bLibraryInitialized) return; #ifdef PDF_ENABLE_XFA - BC_Library_Destory(); - FXJSE_Finalize(); + BC_Library_Destroy(); #endif // PDF_ENABLE_XFA CPDF_ModuleMgr::Destroy(); CFX_GEModule::Destroy(); - delete g_pCodecModule; - g_pCodecModule = nullptr; - IJS_Runtime::Destroy(); + + g_bLibraryInitialized = false; } #ifndef _WIN32 @@ -460,90 +535,78 @@ void ProcessParseError(CPDF_Parser::Error err) { SetLastError(err_code); } -DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy, - FPDF_BOOL enable) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy, + FPDF_BOOL enable) { return FSDK_SetSandBoxPolicy(policy, enable); } #if defined(_WIN32) #if defined(PDFIUM_PRINT_TEXT_WITH_GDI) -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) { g_pdfium_typeface_accessible_func = func; } -DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) { g_pdfium_print_text_with_gdi = !!use_gdi; } #endif // PDFIUM_PRINT_TEXT_WITH_GDI -DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) { - if (postscript_level != 0 && postscript_level != 2 && postscript_level != 3) +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_SetPrintPostscriptLevel(int postscript_level) { + return postscript_level != 1 && FPDF_SetPrintMode(postscript_level); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) { + if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_POSTSCRIPT3) return FALSE; - g_pdfium_print_postscript_level = postscript_level; + g_pdfium_print_mode = mode; return TRUE; } #endif // defined(_WIN32) -DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, - FPDF_BYTESTRING password) { +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV +FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password) { // NOTE: the creation of the file needs to be by the embedder on the // other side of this API. - CFX_RetainPtr pFileAccess = - IFX_SeekableReadStream::CreateFromFilename((const FX_CHAR*)file_path); - if (!pFileAccess) - return nullptr; - - auto pParser = pdfium::MakeUnique(); - pParser->SetPassword(password); - - auto pDocument = pdfium::MakeUnique(std::move(pParser)); - CPDF_Parser::Error error = - pDocument->GetParser()->StartParse(pFileAccess, pDocument.get()); - if (error != CPDF_Parser::SUCCESS) { - ProcessParseError(error); - return nullptr; - } - return FPDFDocumentFromCPDFDocument(pDocument.release()); + return LoadDocumentImpl(IFX_SeekableReadStream::CreateFromFilename(file_path), + password); } -#ifdef PDF_ENABLE_XFA -DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document, - int* docType) { +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document) { if (!document) return false; - CPDF_Document* pdfDoc = - (static_cast(document))->GetPDFDoc(); - if (!pdfDoc) - return false; + const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); + if (!pDoc) + return FORMTYPE_NONE; - CPDF_Dictionary* pRoot = pdfDoc->GetRoot(); + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); if (!pRoot) - return false; + return FORMTYPE_NONE; CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm"); if (!pAcroForm) - return false; + return FORMTYPE_NONE; CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA"); if (!pXFA) - return false; + return FORMTYPE_ACRO_FORM; - bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false); - *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA; - return true; + bool needsRendering = pRoot->GetBooleanFor("NeedsRendering", false); + return needsRendering ? FORMTYPE_XFA_FULL : FORMTYPE_XFA_FOREGROUND; } -DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) { - return document && (static_cast(document))->LoadXFADoc(); +#ifdef PDF_ENABLE_XFA +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document) { + return document && static_cast(document)->LoadXFADoc(); } #endif // PDF_ENABLE_XFA class CMemFile final : public IFX_SeekableReadStream { public: - static CFX_RetainPtr Create(uint8_t* pBuf, FX_FILESIZE size) { - return CFX_RetainPtr(new CMemFile(pBuf, size)); + static RetainPtr Create(const uint8_t* pBuf, FX_FILESIZE size) { + return RetainPtr(new CMemFile(pBuf, size)); } FX_FILESIZE GetSize() override { return m_size; } @@ -556,56 +619,33 @@ class CMemFile final : public IFX_SeekableReadStream { if (!newPos.IsValid() || newPos.ValueOrDie() > m_size) return false; - FXSYS_memcpy(buffer, m_pBuf + offset, size); + memcpy(buffer, m_pBuf + offset, size); return true; } private: - CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {} + CMemFile(const uint8_t* pBuf, FX_FILESIZE size) + : m_pBuf(pBuf), m_size(size) {} - uint8_t* const m_pBuf; + const uint8_t* const m_pBuf; const FX_FILESIZE m_size; }; -DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf, - int size, - FPDF_BYTESTRING password) { - CFX_RetainPtr pMemFile = CMemFile::Create((uint8_t*)data_buf, size); - auto pParser = pdfium::MakeUnique(); - pParser->SetPassword(password); - - auto pDocument = pdfium::MakeUnique(std::move(pParser)); - CPDF_Parser::Error error = - pDocument->GetParser()->StartParse(pMemFile, pDocument.get()); - if (error != CPDF_Parser::SUCCESS) { - ProcessParseError(error); - return nullptr; - } - CheckUnSupportError(pDocument.get(), error); - return FPDFDocumentFromCPDFDocument(pDocument.release()); +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV +FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password) { + return LoadDocumentImpl( + CMemFile::Create(static_cast(data_buf), size), password); } -DLLEXPORT FPDF_DOCUMENT STDCALL +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess, FPDF_BYTESTRING password) { - CFX_RetainPtr pFile = - CPDF_CustomAccess::Create(pFileAccess); - auto pParser = pdfium::MakeUnique(); - pParser->SetPassword(password); - - auto pDocument = pdfium::MakeUnique(std::move(pParser)); - CPDF_Parser::Error error = - pDocument->GetParser()->StartParse(pFile, pDocument.get()); - if (error != CPDF_Parser::SUCCESS) { - ProcessParseError(error); - return nullptr; - } - CheckUnSupportError(pDocument.get(), error); - return FPDFDocumentFromCPDFDocument(pDocument.release()); + return LoadDocumentImpl(pdfium::MakeRetain(pFileAccess), + password); } -DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, - int* fileVersion) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc, + int* fileVersion) { if (!fileVersion) return false; @@ -614,7 +654,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, if (!pDoc) return false; - CPDF_Parser* pParser = pDoc->GetParser(); + const CPDF_Parser* pParser = pDoc->GetParser(); if (!pParser) return false; @@ -624,7 +664,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, // jabdelmalek: changed return type from uint32_t to build on Linux (and match // header). -DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_GetDocPermissions(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); // https://bugs.chromium.org/p/pdfium/issues/detail?id=499 if (!pDoc) { @@ -638,7 +679,8 @@ DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) { return pDoc->GetUserPermissions(); } -DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) { +FPDF_EXPORT int FPDF_CALLCONV +FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc || !pDoc->GetParser()) return -1; @@ -647,13 +689,13 @@ DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) { return pDict ? pDict->GetIntegerFor("R") : -1; } -DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) { +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document) { UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document); return pDoc ? pDoc->GetPageCount() : 0; } -DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, - int page_index) { +FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document, + int page_index) { UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document); if (!pDoc) return nullptr; @@ -662,7 +704,7 @@ DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, return nullptr; #ifdef PDF_ENABLE_XFA - return pDoc->GetXFAPage(page_index); + return pDoc->GetXFAPage(page_index).Leak(); #else // PDF_ENABLE_XFA CPDF_Dictionary* pDict = pDoc->GetPage(page_index); if (!pDict) @@ -674,64 +716,258 @@ DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, #endif // PDF_ENABLE_XFA } -DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) { +FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page) { UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); return pPage ? pPage->GetPageWidth() : 0.0; } -DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) { +FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page) { UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); return pPage ? pPage->GetPageHeight() : 0.0; } -#if defined(_WIN32) -DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags) { +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page, + FS_RECTF* rect) { + if (!rect) + return false; + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) + return false; + + FSRECTFFromCFXFloatRect(pPage->GetPageBBox(), rect); + return true; +} + +#if defined(_WIN32) +namespace { + +const double kEpsilonSize = 0.01f; + +void GetScaling(CPDF_Page* pPage, + int size_x, + int size_y, + int rotate, + double* scale_x, + double* scale_y) { + ASSERT(pPage); + ASSERT(scale_x); + ASSERT(scale_y); + double page_width = pPage->GetPageWidth(); + double page_height = pPage->GetPageHeight(); + if (page_width < kEpsilonSize || page_height < kEpsilonSize) return; - CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext; - pPage->SetRenderContext(pdfium::WrapUnique(pContext)); + if (rotate % 2 == 0) { + *scale_x = size_x / page_width; + *scale_y = size_y / page_height; + } else { + *scale_x = size_y / page_width; + *scale_y = size_x / page_height; + } +} + +FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + const CFX_FloatRect& mask_box) { + double scale_x = 0.0f; + double scale_y = 0.0f; + GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y); + if (scale_x < kEpsilonSize || scale_y < kEpsilonSize) + return FX_RECT(); + + // Compute sizes in page points. Round down to catch the entire bitmap. + int start_x_bm = static_cast(mask_box.left * scale_x); + int start_y_bm = static_cast(mask_box.bottom * scale_y); + int size_x_bm = static_cast(mask_box.right * scale_x + 1.0f) - + static_cast(mask_box.left * scale_x); + int size_y_bm = static_cast(mask_box.top * scale_y + 1.0f) - + static_cast(mask_box.bottom * scale_y); + + // Get page rotation + int page_rotation = pPage->GetPageRotation(); + + // Compute offsets + int offset_x = 0; + int offset_y = 0; + if (size_x > size_y) + std::swap(size_x_bm, size_y_bm); + + switch ((rotate + page_rotation) % 4) { + case 0: + offset_x = start_x_bm + start_x; + offset_y = start_y + size_y - size_y_bm - start_y_bm; + break; + case 1: + offset_x = start_y_bm + start_x; + offset_y = start_x_bm + start_y; + break; + case 2: + offset_x = start_x + size_x - size_x_bm - start_x_bm; + offset_y = start_y_bm + start_y; + break; + case 3: + offset_x = start_x + size_x - size_x_bm - start_y_bm; + offset_y = start_y + size_y - size_y_bm - start_x_bm; + break; + } + return FX_RECT(offset_x, offset_y, offset_x + size_x_bm, + offset_y + size_y_bm); +} + +// Get a bitmap of just the mask section defined by |mask_box| from a full page +// bitmap |pBitmap|. +RetainPtr GetMaskBitmap(CPDF_Page* pPage, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + const RetainPtr& pSrc, + const CFX_FloatRect& mask_box, + FX_RECT* bitmap_area) { + ASSERT(bitmap_area); + *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x, + size_y, rotate, mask_box); + if (bitmap_area->IsEmpty()) + return nullptr; - std::unique_ptr pBitmap; - // TODO: This results in unnecessary rasterization of some PDFs due to - // HasImageMask() returning true. If any image on the page is a mask, the - // entire page gets rasterized and the spool size gets huge. - const bool bNewBitmap = - pPage->BackgroundAlphaNeeded() || pPage->HasImageMask(); - if (bNewBitmap) { - pBitmap = pdfium::MakeUnique(); + // Create a new bitmap to transfer part of the page bitmap to. + RetainPtr pDst = pdfium::MakeRetain(); + pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb); + pDst->Clear(0x00ffffff); + pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc, + bitmap_area->left, bitmap_area->top); + return pDst; +} + +void RenderBitmap(CFX_RenderDevice* device, + const RetainPtr& pSrc, + const FX_RECT& mask_area) { + int size_x_bm = mask_area.Width(); + int size_y_bm = mask_area.Height(); + if (size_x_bm == 0 || size_y_bm == 0) + return; + + // Create a new bitmap from the old one + RetainPtr pDst = pdfium::MakeRetain(); + pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32); + pDst->Clear(0xffffffff); + pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, false); + + if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { + device->StretchDIBits(pDst, mask_area.left, mask_area.top, size_x_bm, + size_y_bm); + } else { + device->SetDIBits(pDst, mask_area.left, mask_area.top); + } +} + +} // namespace + +FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage) + return; + pPage->SetRenderContext(pdfium::MakeUnique()); + CPDF_PageRenderContext* pContext = pPage->GetRenderContext(); + + RetainPtr pBitmap; + // Don't render the full page to bitmap for a mask unless there are a lot + // of masks. Full page bitmaps result in large spool sizes, so they should + // only be used when necessary. For large numbers of masks, rendering each + // individually is inefficient and unlikely to significantly improve spool + // size. TODO (rbpotter): Find out why this still breaks printing for some + // PDFs (see crbug.com/777837). + const bool bEnableImageMasks = false; + const bool bNewBitmap = pPage->BackgroundAlphaNeeded() || + (pPage->HasImageMask() && !bEnableImageMasks) || + pPage->GetMaskBoundingBoxes().size() > 100; + const bool bHasMask = pPage->HasImageMask() && !bNewBitmap; + if (bNewBitmap || bHasMask) { + pBitmap = pdfium::MakeRetain(); pBitmap->Create(size_x, size_y, FXDIB_Argb); pBitmap->Clear(0x00ffffff); - CFX_FxgeDevice* pDevice = new CFX_FxgeDevice; + CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice; pContext->m_pDevice = pdfium::WrapUnique(pDevice); - pDevice->Attach(pBitmap.get(), false, nullptr, false); + pDevice->Attach(pBitmap, false, nullptr, false); + if (bHasMask) { + pContext->m_pOptions = pdfium::MakeUnique(); + uint32_t option_flags = pContext->m_pOptions->GetFlags(); + option_flags |= RENDER_BREAKFORMASKS; + pContext->m_pOptions->SetFlags(option_flags); + } } else { - pContext->m_pDevice = pdfium::MakeUnique(dc); + pContext->m_pDevice = pdfium::MakeUnique(dc); } FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, rotate, flags, true, nullptr); - if (bNewBitmap) { - CFX_WindowsDevice WinDC(dc); + if (bHasMask) { + // Finish rendering the page to bitmap and copy the correct segments + // of the page to individual image mask bitmaps. + const std::vector& mask_boxes = + pPage->GetMaskBoundingBoxes(); + std::vector bitmap_areas(mask_boxes.size()); + std::vector> bitmaps(mask_boxes.size()); + for (size_t i = 0; i < mask_boxes.size(); i++) { + bitmaps[i] = + GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate, + pBitmap, mask_boxes[i], &bitmap_areas[i]); + pContext->m_pRenderer->Continue(nullptr); + } + + // Reset rendering context + pPage->SetRenderContext(nullptr); + + // Begin rendering to the printer. Add flag to indicate the renderer should + // pause after each image mask. + pPage->SetRenderContext(pdfium::MakeUnique()); + pContext = pPage->GetRenderContext(); + pContext->m_pDevice = pdfium::MakeUnique(dc); + pContext->m_pOptions = pdfium::MakeUnique(); + + uint32_t option_flags = pContext->m_pOptions->GetFlags(); + option_flags |= RENDER_BREAKFORMASKS; + pContext->m_pOptions->SetFlags(option_flags); + + FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, + rotate, flags, true, nullptr); + + // Render masks + for (size_t i = 0; i < mask_boxes.size(); i++) { + // Render the bitmap for the mask and free the bitmap. + if (bitmaps[i]) { // will be null if mask has zero area + RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]); + } + // Render the next portion of page. + pContext->m_pRenderer->Continue(nullptr); + } + } else if (bNewBitmap) { + CFX_WindowsRenderDevice WinDC(dc); if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { - std::unique_ptr pDst = pdfium::MakeUnique(); + auto pDst = pdfium::MakeRetain(); int pitch = pBitmap->GetPitch(); pDst->Create(size_x, size_y, FXDIB_Rgb32); - FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y); - pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap.get(), 0, 0, - FXDIB_BLEND_NORMAL, nullptr, false, nullptr); - WinDC.StretchDIBits(pDst.get(), 0, 0, size_x, size_y); + memset(pDst->GetBuffer(), -1, pitch * size_y); + pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, false); + WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y); } else { - WinDC.SetDIBits(pBitmap.get(), 0, 0); + WinDC.SetDIBits(pBitmap, 0, 0); } } @@ -739,14 +975,14 @@ DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, } #endif // defined(_WIN32) -DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { if (!bitmap) return; @@ -756,26 +992,28 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext; pPage->SetRenderContext(pdfium::WrapUnique(pContext)); - CFX_FxgeDevice* pDevice = new CFX_FxgeDevice; + + CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice; pContext->m_pDevice.reset(pDevice); - CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap); - pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false); + RetainPtr pBitmap(CFXBitmapFromFPDFBitmap(bitmap)); + pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false); FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, rotate, flags, true, nullptr); #ifdef _SKIA_SUPPORT_PATHS_ - pDevice->Flush(); + pDevice->Flush(true); pBitmap->UnPreMultiply(); #endif pPage->SetRenderContext(nullptr); } -DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap, - FPDF_PAGE page, - const FS_MATRIX* matrix, - const FS_RECTF* clipping, - int flags) { +FPDF_EXPORT void FPDF_CALLCONV +FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap, + FPDF_PAGE page, + const FS_MATRIX* matrix, + const FS_RECTF* clipping, + int flags) { if (!bitmap) return; @@ -785,41 +1023,42 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap, CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext; pPage->SetRenderContext(pdfium::WrapUnique(pContext)); - CFX_FxgeDevice* pDevice = new CFX_FxgeDevice; + + CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice; pContext->m_pDevice.reset(pDevice); - CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap); + + RetainPtr pBitmap(CFXBitmapFromFPDFBitmap(bitmap)); pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false); - CFX_Matrix transform_matrix = pPage->GetPageMatrix(); + CFX_FloatRect clipping_rect; + if (clipping) + clipping_rect = CFXFloatRectFromFSRECTF(*clipping); + FX_RECT clip_rect = clipping_rect.ToFxRect(); + + CFX_Matrix transform_matrix = pPage->GetDisplayMatrix( + 0, 0, pPage->GetPageWidth(), pPage->GetPageHeight(), 0); + if (matrix) { transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f)); } - - CFX_FloatRect clipping_rect; - if (clipping) { - clipping_rect.left = clipping->left; - clipping_rect.bottom = clipping->bottom; - clipping_rect.right = clipping->right; - clipping_rect.top = clipping->top; - } - RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(), - flags, true, nullptr); + RenderPageImpl(pContext, pPage, transform_matrix, clip_rect, flags, true, + nullptr); pPage->SetRenderContext(nullptr); } #ifdef _SKIA_SUPPORT_ -DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page, - int size_x, - int size_y) { +FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page, + int size_x, + int size_y) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return nullptr; CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext; pPage->SetRenderContext(pdfium::WrapUnique(pContext)); - CFX_FxgeDevice* skDevice = new CFX_FxgeDevice; + CFX_DefaultRenderDevice* skDevice = new CFX_DefaultRenderDevice; FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y); pContext->m_pDevice.reset(skDevice); FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true, @@ -829,12 +1068,13 @@ DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page, } #endif -DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page) { UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); if (!page) return; #ifdef PDF_ENABLE_XFA - pPage->Release(); + // Take it back across the API and throw it away. + RetainPtr().Unleak(pPage); #else // PDF_ENABLE_XFA CPDFSDK_PageView* pPageView = static_cast(pPage->GetView()); @@ -861,24 +1101,24 @@ DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) { #endif // PDF_ENABLE_XFA } -DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) { delete UnderlyingFromFPDFDocument(document); } -DLLEXPORT unsigned long STDCALL FPDF_GetLastError() { +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError() { return GetLastError(); } -DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int device_x, - int device_y, - double* page_x, - double* page_y) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int device_x, + int device_y, + double* page_x, + double* page_y) { if (!page || !page_x || !page_y) return; UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); @@ -888,27 +1128,25 @@ DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, #else // PDF_ENABLE_XFA CFX_Matrix page2device = pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate); - CFX_Matrix device2page; - device2page.SetReverse(page2device); - CFX_PointF pos = device2page.Transform(CFX_PointF( - static_cast(device_x), static_cast(device_y))); + CFX_PointF pos = page2device.GetInverse().Transform( + CFX_PointF(static_cast(device_x), static_cast(device_y))); *page_x = pos.x; *page_y = pos.y; #endif // PDF_ENABLE_XFA } -DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - double page_x, - double page_y, - int* device_x, - int* device_y) { +FPDF_EXPORT void FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + double page_x, + double page_y, + int* device_x, + int* device_y) { if (!device_x || !device_y) return; UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); @@ -921,28 +1159,28 @@ DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, CFX_Matrix page2device = pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate); CFX_PointF pos = page2device.Transform( - CFX_PointF(static_cast(page_x), static_cast(page_y))); + CFX_PointF(static_cast(page_x), static_cast(page_y))); *device_x = FXSYS_round(pos.x); *device_y = FXSYS_round(pos.y); #endif // PDF_ENABLE_XFA } -DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, - int height, - int alpha) { - auto pBitmap = pdfium::MakeUnique(); +FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width, + int height, + int alpha) { + auto pBitmap = pdfium::MakeRetain(); if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32)) return nullptr; - return pBitmap.release(); + return pBitmap.Leak(); } -DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, - int height, - int format, - void* first_scan, - int stride) { +FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width, + int height, + int format, + void* first_scan, + int stride) { FXDIB_Format fx_format; switch (format) { case FPDFBitmap_Gray: @@ -960,22 +1198,43 @@ DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, default: return nullptr; } - CFX_DIBitmap* pBitmap = new CFX_DIBitmap; - pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride); - return pBitmap; + auto pBitmap = pdfium::MakeRetain(); + pBitmap->Create(width, height, fx_format, static_cast(first_scan), + stride); + return pBitmap.Leak(); +} + +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap) { + if (!bitmap) + return FPDFBitmap_Unknown; + + FXDIB_Format format = CFXBitmapFromFPDFBitmap(bitmap)->GetFormat(); + switch (format) { + case FXDIB_8bppRgb: + case FXDIB_8bppMask: + return FPDFBitmap_Gray; + case FXDIB_Rgb: + return FPDFBitmap_BGR; + case FXDIB_Rgb32: + return FPDFBitmap_BGRx; + case FXDIB_Argb: + return FPDFBitmap_BGRA; + default: + return FPDFBitmap_Unknown; + } } -DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, - int left, - int top, - int width, - int height, - FPDF_DWORD color) { +FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap, + int left, + int top, + int width, + int height, + FPDF_DWORD color) { if (!bitmap) return; - CFX_FxgeDevice device; - CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap); + CFX_DefaultRenderDevice device; + RetainPtr pBitmap(CFXBitmapFromFPDFBitmap(bitmap)); device.Attach(pBitmap, false, nullptr, false); if (!pBitmap->HasAlpha()) color |= 0xFF000000; @@ -983,24 +1242,25 @@ DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, device.FillRect(&rect, color); } -DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) { +FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) { return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr; } -DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) { +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) { return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0; } -DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) { +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) { return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0; } -DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) { +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap) { return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0; } -DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) { - delete CFXBitmapFromFPDFBitmap(bitmap); +FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap) { + RetainPtr destroyer; + destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap)); } void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext, @@ -1023,10 +1283,10 @@ void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext, flags, bNeedToRestore, pause); } -DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, - int page_index, - double* width, - double* height) { +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, + int page_index, + double* width, + double* height) { UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document); if (!pDoc) return false; @@ -1035,7 +1295,7 @@ DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, int count = pDoc->GetPageCount(); if (page_index < 0 || page_index >= count) return false; - CPDFXFA_Page* pPage = pDoc->GetXFAPage(page_index); + RetainPtr pPage = pDoc->GetXFAPage(page_index); if (!pPage) return false; *width = pPage->GetPageWidth(); @@ -1053,7 +1313,7 @@ DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, return true; } -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) @@ -1062,7 +1322,8 @@ FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) { return viewRef.PrintScaling(); } -DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) { +FPDF_EXPORT int FPDF_CALLCONV +FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 1; @@ -1070,7 +1331,7 @@ DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) { return viewRef.NumCopies(); } -DLLEXPORT FPDF_PAGERANGE STDCALL +FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) @@ -1079,13 +1340,13 @@ FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) { return viewRef.PrintPageRange(); } -DLLEXPORT FPDF_DUPLEXTYPE STDCALL +FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return DuplexUndefined; CPDF_ViewerPreferences viewRef(pDoc); - CFX_ByteString duplex = viewRef.Duplex(); + ByteString duplex = viewRef.Duplex(); if ("Simplex" == duplex) return Simplex; if ("DuplexFlipShortEdge" == duplex) @@ -1095,16 +1356,17 @@ FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) { return DuplexUndefined; } -DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, - FPDF_BYTESTRING key, - char* buffer, - unsigned long length) { +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, + FPDF_BYTESTRING key, + char* buffer, + unsigned long length) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 0; CPDF_ViewerPreferences viewRef(pDoc); - CFX_ByteString bsVal; + ByteString bsVal; if (!viewRef.GenericName(key, &bsVal)) return 0; @@ -1114,12 +1376,13 @@ DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, return dwStringLen; } -DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) { +FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV +FPDF_CountNamedDests(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 0; - CPDF_Dictionary* pRoot = pDoc->GetRoot(); + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); if (!pRoot) return 0; @@ -1135,8 +1398,8 @@ DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) { return count.ValueOrDie(); } -DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document, - FPDF_BYTESTRING name) { +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV +FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) { if (!name || name[0] == 0) return nullptr; @@ -1145,34 +1408,29 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document, return nullptr; CPDF_NameTree name_tree(pDoc, "Dests"); - return name_tree.LookupNamedDest(pDoc, name); + return name_tree.LookupNamedDest(pDoc, PDF_DecodeText(ByteString(name))); } #ifdef PDF_ENABLE_XFA -DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) { +FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* str) { if (!str) return -1; - FXSYS_memset(str, 0, sizeof(FPDF_BSTR)); + memset(str, 0, sizeof(FPDF_BSTR)); return 0; } -DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str, - FPDF_LPCSTR bstr, - int length) { - if (!str) - return -1; - if (!bstr || !length) +FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* str, + FPDF_LPCSTR bstr, + int length) { + if (!str || !bstr || !length) return -1; + if (length == -1) - length = FXSYS_strlen(bstr); + length = strlen(bstr); if (length == 0) { - if (str->str) { - FX_Free(str->str); - str->str = nullptr; - } - str->len = 0; + FPDF_BStr_Clear(str); return 0; } @@ -1182,13 +1440,13 @@ DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str, str->str = FX_Alloc(char, length + 1); str->str[length] = 0; - FXSYS_memcpy(str->str, bstr, length); + memcpy(str->str, bstr, length); str->len = length; return 0; } -DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) { +FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* str) { if (!str) return -1; @@ -1201,10 +1459,10 @@ DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) { } #endif // PDF_ENABLE_XFA -DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, - int index, - void* buffer, - long* buflen) { +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document, + int index, + void* buffer, + long* buflen) { if (!buffer) *buflen = 0; @@ -1215,12 +1473,12 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, if (!pDoc) return nullptr; - CPDF_Dictionary* pRoot = pDoc->GetRoot(); + const CPDF_Dictionary* pRoot = pDoc->GetRoot(); if (!pRoot) return nullptr; CPDF_Object* pDestObj = nullptr; - CFX_ByteString bsName; + WideString wsName; CPDF_NameTree nameTree(pDoc, "Dests"); int count = nameTree.GetCount(); if (index >= count) { @@ -1235,6 +1493,7 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, index -= count; int i = 0; + ByteString bsName; for (const auto& it : *pDest) { bsName = it.first; pDestObj = it.second.get(); @@ -1244,8 +1503,9 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, break; i++; } + wsName = PDF_DecodeText(bsName); } else { - pDestObj = nameTree.LookupValue(index, bsName); + pDestObj = nameTree.LookupValueAndName(index, &wsName); } if (!pDestObj) return nullptr; @@ -1257,8 +1517,7 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, if (!pDestObj->IsArray()) return nullptr; - CFX_WideString wsName = PDF_DecodeText(bsName); - CFX_ByteString utf16Name = wsName.UTF16LE_Encode(); + ByteString utf16Name = wsName.UTF16LE_Encode(); int len = utf16Name.GetLength(); if (!buffer) { *buflen = len; diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c index 54a33252b369e43f082e444d22b283752ad23bbf..53d8776be05cdd2ecf1c09863bdcc63eb140a107 100644 --- a/fpdfsdk/fpdfview_c_api_test.c +++ b/fpdfsdk/fpdfview_c_api_test.c @@ -9,6 +9,9 @@ #include "fpdfsdk/fpdfview_c_api_test.h" +#include "public/fpdf_annot.h" +#include "public/fpdf_attachment.h" +#include "public/fpdf_catalog.h" #include "public/fpdf_dataavail.h" #include "public/fpdf_doc.h" #include "public/fpdf_edit.h" @@ -33,6 +36,56 @@ fnptr g_c_api_test_fnptr = NULL; // Extern, so can't know it doesn't change. // Function to call from gtest harness to ensure linker resolution. int CheckPDFiumCApi() { + // fpdf_annot.h + CHK(FPDFAnnot_IsSupportedSubtype); + CHK(FPDFPage_CreateAnnot); + CHK(FPDFPage_GetAnnotCount); + CHK(FPDFPage_GetAnnot); + CHK(FPDFPage_GetAnnotIndex); + CHK(FPDFPage_CloseAnnot); + CHK(FPDFPage_RemoveAnnot); + CHK(FPDFAnnot_GetSubtype); + CHK(FPDFAnnot_IsObjectSupportedSubtype); + CHK(FPDFAnnot_UpdateObject); + CHK(FPDFAnnot_AppendObject); + CHK(FPDFAnnot_GetObjectCount); + CHK(FPDFAnnot_GetObject); + CHK(FPDFAnnot_RemoveObject); + CHK(FPDFAnnot_SetColor); + CHK(FPDFAnnot_GetColor); + CHK(FPDFAnnot_HasAttachmentPoints); + CHK(FPDFAnnot_SetAttachmentPoints); + CHK(FPDFAnnot_GetAttachmentPoints); + CHK(FPDFAnnot_SetRect); + CHK(FPDFAnnot_GetRect); + CHK(FPDFAnnot_HasKey); + CHK(FPDFAnnot_GetValueType); + CHK(FPDFAnnot_SetStringValue); + CHK(FPDFAnnot_GetStringValue); + CHK(FPDFAnnot_SetAP); + CHK(FPDFAnnot_GetAP); + CHK(FPDFAnnot_GetLinkedAnnot); + CHK(FPDFAnnot_GetFlags); + CHK(FPDFAnnot_SetFlags); + CHK(FPDFAnnot_GetFormFieldFlags); + CHK(FPDFAnnot_GetFormFieldAtPoint); + + // fpdf_attachment.h + CHK(FPDFDoc_GetAttachmentCount); + CHK(FPDFDoc_AddAttachment); + CHK(FPDFDoc_GetAttachment); + CHK(FPDFDoc_DeleteAttachment); + CHK(FPDFAttachment_GetName); + CHK(FPDFAttachment_HasKey); + CHK(FPDFAttachment_GetValueType); + CHK(FPDFAttachment_SetStringValue); + CHK(FPDFAttachment_GetStringValue); + CHK(FPDFAttachment_SetFile); + CHK(FPDFAttachment_GetFile); + + // fpdf_catalog.h + CHK(FPDFCatalog_IsTagged); + // fpdf_dataavail.h CHK(FPDFAvail_Create); CHK(FPDFAvail_Destroy); @@ -56,6 +109,7 @@ int CheckPDFiumCApi() { CHK(FPDFAction_GetURIPath); CHK(FPDFDest_GetPageIndex); CHK(FPDFDest_GetLocationInPage); + CHK(FPDFDest_GetView); CHK(FPDFLink_GetLinkAtPoint); CHK(FPDFLink_GetLinkZOrderAtPoint); CHK(FPDFLink_GetDest); @@ -75,30 +129,53 @@ int CheckPDFiumCApi() { CHK(FPDFPage_SetRotation); CHK(FPDFPage_InsertObject); CHK(FPDFPage_CountObject); + CHK(FPDFPage_CountObjects); CHK(FPDFPage_GetObject); CHK(FPDFPage_HasTransparency); CHK(FPDFPage_GenerateContent); + CHK(FPDFPageObj_Destroy); CHK(FPDFPageObj_HasTransparency); + CHK(FPDFPageObj_GetBounds); + CHK(FPDFPageObj_GetType); + CHK(FPDFPageObj_SetBlendMode); CHK(FPDFPageObj_Transform); CHK(FPDFPage_TransformAnnots); - CHK(FPDFPageObj_NewImgeObj); + CHK(FPDFPageObj_NewImageObj); CHK(FPDFImageObj_LoadJpegFile); CHK(FPDFImageObj_LoadJpegFileInline); CHK(FPDFImageObj_SetMatrix); CHK(FPDFImageObj_SetBitmap); + CHK(FPDFImageObj_GetBitmap); + CHK(FPDFImageObj_GetImageDataDecoded); + CHK(FPDFImageObj_GetImageDataRaw); + CHK(FPDFImageObj_GetImageFilterCount); + CHK(FPDFImageObj_GetImageFilter); + CHK(FPDFImageObj_GetImageMetadata); CHK(FPDFPageObj_CreateNewPath); CHK(FPDFPageObj_CreateNewRect); CHK(FPDFPath_SetStrokeColor); + CHK(FPDFPath_GetStrokeColor); CHK(FPDFPath_SetStrokeWidth); CHK(FPDFPath_SetFillColor); + CHK(FPDFPath_GetFillColor); + CHK(FPDFPath_CountSegments); + CHK(FPDFPath_GetPathSegment); + CHK(FPDFPathSegment_GetPoint); + CHK(FPDFPathSegment_GetType); + CHK(FPDFPathSegment_GetClose); CHK(FPDFPath_MoveTo); CHK(FPDFPath_LineTo); CHK(FPDFPath_BezierTo); CHK(FPDFPath_Close); CHK(FPDFPath_SetDrawMode); + CHK(FPDFPath_SetLineCap); + CHK(FPDFPath_SetLineJoin); CHK(FPDFPageObj_NewTextObj); CHK(FPDFText_SetText); - CHK(FPDFText_LoadType1Font); + CHK(FPDFText_SetFillColor); + CHK(FPDFText_LoadFont); + CHK(FPDFFont_Close); + CHK(FPDFPageObj_CreateTextObj); // fpdf_ext.h CHK(FSDK_SetUnSpObjProcessHandler); @@ -119,6 +196,7 @@ int CheckPDFiumCApi() { CHK(FORM_DoDocumentAAction); CHK(FORM_DoPageAAction); CHK(FORM_OnMouseMove); + CHK(FORM_OnFocus); CHK(FORM_OnLButtonDown); CHK(FORM_OnLButtonUp); #ifdef PDF_ENABLE_XFA @@ -128,16 +206,20 @@ int CheckPDFiumCApi() { CHK(FORM_OnKeyDown); CHK(FORM_OnKeyUp); CHK(FORM_OnChar); + CHK(FORM_GetSelectedText); + CHK(FORM_ReplaceSelection); CHK(FORM_ForceToKillFocus); CHK(FPDFPage_HasFormFieldAtPoint); - CHK(FPDPage_HasFormFieldAtPoint); // DEPRECATED. Remove in the future. CHK(FPDFPage_FormFieldZOrderAtPoint); CHK(FPDF_SetFormFieldHighlightColor); CHK(FPDF_SetFormFieldHighlightAlpha); CHK(FPDF_RemoveFormFieldHighlight); CHK(FPDF_FFLDraw); +#ifdef _SKIA_SUPPORT_ + CHK(FPDF_FFLRecord); +#endif + CHK(FPDF_GetFormType); #ifdef PDF_ENABLE_XFA - CHK(FPDF_HasXFAField); CHK(FPDF_LoadXFA); CHK(FPDF_Widget_Undo); CHK(FPDF_Widget_Redo); @@ -168,6 +250,7 @@ int CheckPDFiumCApi() { // fpdf_searchex.h CHK(FPDFText_GetCharIndexFromTextIndex); + CHK(FPDFText_GetTextIndexFromCharIndex); // fpdf_structtree.h CHK(FPDF_StructTree_GetForPage); @@ -175,6 +258,9 @@ int CheckPDFiumCApi() { CHK(FPDF_StructTree_CountChildren); CHK(FPDF_StructTree_GetChildAtIndex); CHK(FPDF_StructElement_GetAltText); + CHK(FPDF_StructElement_GetMarkedContentID); + CHK(FPDF_StructElement_GetType); + CHK(FPDF_StructElement_GetTitle); CHK(FPDF_StructElement_CountChildren); CHK(FPDF_StructElement_GetChildAtIndex); @@ -192,6 +278,7 @@ int CheckPDFiumCApi() { CHK(FPDFText_GetUnicode); CHK(FPDFText_GetFontSize); CHK(FPDFText_GetCharBox); + CHK(FPDFText_GetCharOrigin); CHK(FPDFText_GetCharIndexAtPos); CHK(FPDFText_GetText); CHK(FPDFText_CountRects); @@ -226,6 +313,14 @@ int CheckPDFiumCApi() { CHK(FPDF_InitLibraryWithConfig); CHK(FPDF_DestroyLibrary); CHK(FPDF_SetSandBoxPolicy); +#if defined(_WIN32) +#if defined(PDFIUM_PRINT_TEXT_WITH_GDI) + CHK(FPDF_SetTypefaceAccessibleFunc); + CHK(FPDF_SetPrintTextWithGDI); +#endif + CHK(FPDF_SetPrintPostscriptLevel); + CHK(FPDF_SetPrintMode); +#endif CHK(FPDF_LoadDocument); CHK(FPDF_LoadMemDocument); CHK(FPDF_LoadCustomDocument); @@ -237,15 +332,23 @@ int CheckPDFiumCApi() { CHK(FPDF_LoadPage); CHK(FPDF_GetPageWidth); CHK(FPDF_GetPageHeight); + CHK(FPDF_GetPageBoundingBox); CHK(FPDF_GetPageSizeByIndex); +#ifdef _WIN32 + CHK(FPDF_RenderPage); +#endif CHK(FPDF_RenderPageBitmap); CHK(FPDF_RenderPageBitmapWithMatrix); +#ifdef _SKIA_SUPPORT_ + CHK(FPDF_RenderPageSkp); +#endif CHK(FPDF_ClosePage); CHK(FPDF_CloseDocument); CHK(FPDF_DeviceToPage); CHK(FPDF_PageToDevice); CHK(FPDFBitmap_Create); CHK(FPDFBitmap_CreateEx); + CHK(FPDFBitmap_GetFormat); CHK(FPDFBitmap_FillRect); CHK(FPDFBitmap_GetBuffer); CHK(FPDFBitmap_GetWidth); diff --git a/fpdfsdk/fpdfview_embeddertest.cpp b/fpdfsdk/fpdfview_embeddertest.cpp index 1d94b7255332c11d3371b564a4438490da0a472e..cca77c90310707706c2cb09256b96f6c7b4fb72a 100644 --- a/fpdfsdk/fpdfview_embeddertest.cpp +++ b/fpdfsdk/fpdfview_embeddertest.cpp @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include #include @@ -9,12 +10,38 @@ #include "public/fpdfview.h" #include "testing/embedder_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/utils/path_service.h" + +namespace { + +class MockDownloadHints : public FX_DOWNLOADHINTS { + public: + static void SAddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) { + } + + MockDownloadHints() { + FX_DOWNLOADHINTS::version = 1; + FX_DOWNLOADHINTS::AddSegment = SAddSegment; + } + + ~MockDownloadHints() {} +}; + +} // namespace TEST(fpdf, CApiTest) { EXPECT_TRUE(CheckPDFiumCApi()); } -class FPDFViewEmbeddertest : public EmbedderTest {}; +class FPDFViewEmbeddertest : public EmbedderTest { + protected: + void TestRenderPageBitmapWithMatrix(FPDF_PAGE page, + const int bitmap_width, + const int bitmap_height, + const FS_MATRIX& matrix, + const FS_RECTF& rect, + const char* expected_md5); +}; TEST_F(FPDFViewEmbeddertest, Document) { EXPECT_TRUE(OpenDocument("about_blank.pdf")); @@ -29,6 +56,12 @@ TEST_F(FPDFViewEmbeddertest, Document) { EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document())); } +TEST_F(FPDFViewEmbeddertest, LoadNonexistentDocument) { + FPDF_DOCUMENT doc = FPDF_LoadDocument("nonexistent_document.pdf", ""); + ASSERT_FALSE(doc); + EXPECT_EQ(static_cast(FPDF_GetLastError()), FPDF_ERR_FILE); +} + // See bug 465. TEST_F(FPDFViewEmbeddertest, EmptyDocument) { EXPECT_TRUE(CreateEmptyDocument()); @@ -63,12 +96,28 @@ TEST_F(FPDFViewEmbeddertest, EmptyDocument) { EXPECT_EQ(0u, FPDF_CountNamedDests(document())); } +TEST_F(FPDFViewEmbeddertest, LinearizedDocument) { + EXPECT_TRUE(OpenDocumentLinearized("feature_linearized_loading.pdf")); + int version; + EXPECT_TRUE(FPDF_GetFileVersion(document(), &version)); + EXPECT_EQ(16, version); +} + TEST_F(FPDFViewEmbeddertest, Page) { EXPECT_TRUE(OpenDocument("about_blank.pdf")); FPDF_PAGE page = LoadPage(0); EXPECT_NE(nullptr, page); + EXPECT_EQ(612.0, FPDF_GetPageWidth(page)); EXPECT_EQ(792.0, FPDF_GetPageHeight(page)); + + FS_RECTF rect; + EXPECT_TRUE(FPDF_GetPageBoundingBox(page, &rect)); + EXPECT_EQ(0.0, rect.left); + EXPECT_EQ(0.0, rect.bottom); + EXPECT_EQ(612.0, rect.right); + EXPECT_EQ(792.0, rect.top); + UnloadPage(page); EXPECT_EQ(nullptr, LoadPage(1)); } @@ -304,6 +353,14 @@ TEST_F(FPDFViewEmbeddertest, Hang_298) { // reference loop. Cross references will be rebuilt successfully. TEST_F(FPDFViewEmbeddertest, CrossRefV4Loop) { EXPECT_TRUE(OpenDocument("bug_xrefv4_loop.pdf")); + MockDownloadHints hints; + + // Make sure calling FPDFAvail_IsDocAvail() on this file does not infinite + // loop either. See bug 875. + int ret = PDF_DATA_NOTAVAIL; + while (ret == PDF_DATA_NOTAVAIL) + ret = FPDFAvail_IsDocAvail(avail_, &hints); + EXPECT_EQ(PDF_DATA_AVAIL, ret); } // The test should pass when circular references to ParseIndirectObject will not @@ -328,53 +385,217 @@ TEST_F(FPDFViewEmbeddertest, Hang_360) { EXPECT_FALSE(OpenDocument("bug_360.pdf")); } -TEST_F(FPDFViewEmbeddertest, FPDF_RenderPageBitmapWithMatrix) { - const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615"; - const char kTopLeftQuarterBlackMd5sum[] = "24e4d1ec06fa0258af758cfc8b2ad50a"; +void FPDFViewEmbeddertest::TestRenderPageBitmapWithMatrix( + FPDF_PAGE page, + const int bitmap_width, + const int bitmap_height, + const FS_MATRIX& matrix, + const FS_RECTF& rect, + const char* expected_md5) { + FPDF_BITMAP bitmap = FPDFBitmap_Create(bitmap_width, bitmap_height, 0); + FPDFBitmap_FillRect(bitmap, 0, 0, bitmap_width, bitmap_height, 0xFFFFFFFF); + FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0); + CompareBitmap(bitmap, bitmap_width, bitmap_height, expected_md5); + FPDFBitmap_Destroy(bitmap); +} - EXPECT_TRUE(OpenDocument("black.pdf")); +TEST_F(FPDFViewEmbeddertest, FPDF_RenderPageBitmapWithMatrix) { + const char kOriginalMD5[] = "0a90de37f52127619c3dfb642b5fa2fe"; + const char kClippedMD5[] = "a84cab93c102b9b9290fba3047ba702c"; + const char kTopLeftQuarterMD5[] = "f11a11137c8834389e31cf555a4a6979"; + const char kHoriStretchedMD5[] = "48ef9205941ed19691ccfa00d717187e"; + const char kRotated90ClockwiseMD5[] = "d8da2c7bf77521550d0f2752b9cf3482"; + const char kRotated180ClockwiseMD5[] = "0113386bb0bd45125bacc6dee78bfe78"; + const char kRotated270ClockwiseMD5[] = "a287e0f74ce203699cda89f9cc97a240"; + const char kMirrorHoriMD5[] = "6e8d7a6fde39d8e720fb9e620102918c"; + const char kMirrorVertMD5[] = "8f3a555ef9c0d5031831ae3715273707"; + const char kLargerTopLeftQuarterMD5[] = "172a2f4adafbadbe98017b1c025b9e27"; + const char kLargerMD5[] = "c806145641c3e6fc4e022c7065343749"; + const char kLargerClippedMD5[] = "091d3b1c7933c8f6945eb2cb41e588e9"; + const char kLargerRotatedMD5[] = "115f13353ebfc82ddb392d1f0059eb12"; + const char kLargerRotatedLandscapeMD5[] = "c901239d17d84ac84cb6f2124da71b0d"; + const char kLargerRotatedDiagonalMD5[] = "3d62417468bdaff0eb14391a0c30a3b1"; + const char kTileMD5[] = "0a190003c97220bf8877684c8d7e89cf"; + + EXPECT_TRUE(OpenDocument("rectangles.pdf")); FPDF_PAGE page = LoadPage(0); EXPECT_NE(nullptr, page); - const int width = static_cast(FPDF_GetPageWidth(page)); - const int height = static_cast(FPDF_GetPageHeight(page)); - EXPECT_EQ(612, width); - EXPECT_EQ(792, height); + const int page_width = static_cast(FPDF_GetPageWidth(page)); + const int page_height = static_cast(FPDF_GetPageHeight(page)); + EXPECT_EQ(200, page_width); + EXPECT_EQ(300, page_height); FPDF_BITMAP bitmap = RenderPage(page); - CompareBitmap(bitmap, width, height, kAllBlackMd5sum); + CompareBitmap(bitmap, page_width, page_height, kOriginalMD5); FPDFBitmap_Destroy(bitmap); + FS_RECTF page_rect{0, 0, page_width, page_height}; + // Try rendering with an identity matrix. The output should be the same as // the RenderPage() output. - FS_MATRIX matrix; - matrix.a = 1; - matrix.b = 0; - matrix.c = 0; - matrix.d = 1; - matrix.e = 0; - matrix.f = 0; + FS_MATRIX identity_matrix{1, 0, 0, 1, 0, 0}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, identity_matrix, + page_rect, kOriginalMD5); + + // Again render with an identity matrix but with a smaller clipping rect. + FS_RECTF middle_of_page_rect{page_width / 4, page_height / 4, + page_width * 3 / 4, page_height * 3 / 4}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, identity_matrix, + middle_of_page_rect, kClippedMD5); + + // Now render again with the image scaled smaller. + FS_MATRIX half_scale_matrix{0.5, 0, 0, 0.5, 0, 0}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + half_scale_matrix, page_rect, + kTopLeftQuarterMD5); + + // Now render again with the image scaled larger horizontally (the right half + // will be clipped). + FS_MATRIX stretch_x_matrix{2, 0, 0, 1, 0, 0}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + stretch_x_matrix, page_rect, + kHoriStretchedMD5); + + // Try a 90 degree rotation clockwise but with the same bitmap size, so part + // will be clipped. + FS_MATRIX rotate_90_matrix{0, 1, -1, 0, page_width, 0}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + rotate_90_matrix, page_rect, + kRotated90ClockwiseMD5); + + // 180 degree rotation clockwise. + FS_MATRIX rotate_180_matrix{-1, 0, 0, -1, page_width, page_height}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + rotate_180_matrix, page_rect, + kRotated180ClockwiseMD5); + + // 270 degree rotation clockwise. + FS_MATRIX rotate_270_matrix{0, -1, 1, 0, 0, page_width}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + rotate_270_matrix, page_rect, + kRotated270ClockwiseMD5); + + // Mirror horizontally. + FS_MATRIX mirror_hori_matrix{-1, 0, 0, 1, page_width, 0}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + mirror_hori_matrix, page_rect, kMirrorHoriMD5); + + // Mirror vertically. + FS_MATRIX mirror_vert_matrix{1, 0, 0, -1, 0, page_height}; + TestRenderPageBitmapWithMatrix(page, page_width, page_height, + mirror_vert_matrix, page_rect, kMirrorVertMD5); + + // Tests rendering to a larger bitmap + const int bitmap_width = page_width * 2; + const int bitmap_height = page_height * 2; + + // Render using an identity matrix and the whole bitmap area as clipping rect. + FS_RECTF bitmap_rect{0, 0, bitmap_width, bitmap_height}; + TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height, + identity_matrix, bitmap_rect, + kLargerTopLeftQuarterMD5); + + // Render using a scaling matrix to fill the larger bitmap. + FS_MATRIX double_scale_matrix{2, 0, 0, 2, 0, 0}; + TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height, + double_scale_matrix, bitmap_rect, kLargerMD5); + + // Render the larger image again but with clipping. + FS_RECTF middle_of_bitmap_rect{bitmap_width / 4, bitmap_height / 4, + bitmap_width * 3 / 4, bitmap_height * 3 / 4}; + TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height, + double_scale_matrix, middle_of_bitmap_rect, + kLargerClippedMD5); + + // On the larger bitmap, try a 90 degree rotation but with the same bitmap + // size, so part will be clipped. + FS_MATRIX rotate_90_scale_2_matrix{0, 2, -2, 0, bitmap_width, 0}; + TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height, + rotate_90_scale_2_matrix, bitmap_rect, + kLargerRotatedMD5); + + // On the larger bitmap, apply 90 degree rotation to a bitmap with the + // appropriate dimensions. + const int landscape_bitmap_width = bitmap_height; + const int landscape_bitmap_height = bitmap_width; + FS_RECTF landscape_bitmap_rect{0, 0, landscape_bitmap_width, + landscape_bitmap_height}; + FS_MATRIX landscape_rotate_90_scale_2_matrix{ + 0, 2, -2, 0, landscape_bitmap_width, 0}; + TestRenderPageBitmapWithMatrix( + page, landscape_bitmap_width, landscape_bitmap_height, + landscape_rotate_90_scale_2_matrix, landscape_bitmap_rect, + kLargerRotatedLandscapeMD5); + + // On the larger bitmap, apply 45 degree rotation to a bitmap with the + // appropriate dimensions. + const float sqrt2 = 1.41421356f; + const int diagonal_bitmap_size = ceil((bitmap_width + bitmap_height) / sqrt2); + FS_RECTF diagonal_bitmap_rect{0, 0, diagonal_bitmap_size, + diagonal_bitmap_size}; + FS_MATRIX rotate_45_scale_2_matrix{ + sqrt2, sqrt2, -sqrt2, sqrt2, bitmap_height / sqrt2, 0}; + TestRenderPageBitmapWithMatrix(page, diagonal_bitmap_size, + diagonal_bitmap_size, rotate_45_scale_2_matrix, + diagonal_bitmap_rect, + kLargerRotatedDiagonalMD5); + + // Render the (2, 1) tile of the page (third column, second row) when the page + // is divided in 50x50 pixel tiles. The tile is scaled by a factor of 7. + const float scale = 7.0; + const int tile_size = 50; + const int tile_x = 2; + const int tile_y = 1; + int tile_bitmap_size = scale * tile_size; + FS_RECTF tile_bitmap_rect{0, 0, tile_bitmap_size, tile_bitmap_size}; + FS_MATRIX tile_2_1_matrix{scale, + 0, + 0, + scale, + -tile_x * tile_bitmap_size, + -tile_y * tile_bitmap_size}; + TestRenderPageBitmapWithMatrix(page, tile_bitmap_size, tile_bitmap_size, + tile_2_1_matrix, tile_bitmap_rect, kTileMD5); - FS_RECTF rect; - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = height; + UnloadPage(page); +} - bitmap = FPDFBitmap_Create(width, height, 0); - FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF); - FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0); - CompareBitmap(bitmap, width, height, kAllBlackMd5sum); - FPDFBitmap_Destroy(bitmap); +class UnSupRecordDelegate : public EmbedderTest::Delegate { + public: + UnSupRecordDelegate() : type_(-1) {} + ~UnSupRecordDelegate() override {} - // Now render again with the image scaled. - matrix.a = 0.5; - matrix.d = 0.5; + void UnsupportedHandler(int type) override { type_ = type; } - bitmap = FPDFBitmap_Create(width, height, 0); - FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF); - FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0); - CompareBitmap(bitmap, width, height, kTopLeftQuarterBlackMd5sum); - FPDFBitmap_Destroy(bitmap); + int type_; +}; - UnloadPage(page); +TEST_F(FPDFViewEmbeddertest, UnSupportedOperations_NotFound) { + UnSupRecordDelegate delegate; + SetDelegate(&delegate); + ASSERT_TRUE(OpenDocument("hello_world.pdf")); + EXPECT_EQ(delegate.type_, -1); + SetDelegate(nullptr); +} + +TEST_F(FPDFViewEmbeddertest, UnSupportedOperations_LoadCustomDocument) { + UnSupRecordDelegate delegate; + SetDelegate(&delegate); + ASSERT_TRUE(OpenDocument("unsupported_feature.pdf")); + EXPECT_EQ(FPDF_UNSP_DOC_PORTABLECOLLECTION, delegate.type_); + SetDelegate(nullptr); +} + +TEST_F(FPDFViewEmbeddertest, UnSupportedOperations_LoadDocument) { + std::string file_path; + ASSERT_TRUE( + PathService::GetTestFilePath("unsupported_feature.pdf", &file_path)); + + UnSupRecordDelegate delegate; + SetDelegate(&delegate); + FPDF_DOCUMENT doc = FPDF_LoadDocument(file_path.c_str(), ""); + EXPECT_TRUE(doc != nullptr); + EXPECT_EQ(FPDF_UNSP_DOC_PORTABLECOLLECTION, delegate.type_); + FPDF_CloseDocument(doc); + SetDelegate(nullptr); } diff --git a/fpdfsdk/fpdfview_unittest.cpp b/fpdfsdk/fpdfview_unittest.cpp deleted file mode 100644 index 27680b3d4e135f91907cadcbcb64c5613f4f3aaf..0000000000000000000000000000000000000000 --- a/fpdfsdk/fpdfview_unittest.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 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. - -#include "public/fpdfview.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/test_support.h" - -TEST(FPDFView, DoubleInit) { - FPDF_InitLibrary(); - FPDF_InitLibrary(); - FPDF_DestroyLibrary(); -} - -TEST(FPDFView, DoubleDestroy) { - FPDF_InitLibrary(); - FPDF_DestroyLibrary(); - FPDF_DestroyLibrary(); -} diff --git a/fpdfsdk/fpdfxfa/DEPS b/fpdfsdk/fpdfxfa/DEPS index 1687e308b571ebcacd00e824a600c17413349617..5ba75f2f2b6263536767bd64fb91308159a52245 100644 --- a/fpdfsdk/fpdfxfa/DEPS +++ b/fpdfsdk/fpdfxfa/DEPS @@ -1,4 +1,5 @@ include_rules = [ '+fxjs', - '+xfa/fxbarcode', + '+fxbarcode', + '+xfa/fgas/font', ] diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp index 88c88a17480bb5f4714596ffb98b1720a050f032..d05e2f6b34f6d4872ee58c2cdce407df11516146 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp +++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp @@ -6,6 +6,7 @@ #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" +#include #include #include "core/fpdfapi/parser/cpdf_document.h" @@ -15,18 +16,19 @@ #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/ijs_runtime.h" +#include "fxjs/cjs_runtime.h" +#include "fxjs/ijs_runtime.h" #include "public/fpdf_formfill.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" +#include "xfa/fgas/font/cfgas_defaultfontmanager.h" #include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" -#include "xfa/fxfa/xfa_fontmgr.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_fontmgr.h" #ifndef _WIN32 extern void SetLastError(int err); @@ -34,15 +36,10 @@ extern int GetLastError(); #endif CPDFXFA_Context::CPDFXFA_Context(std::unique_ptr pPDFDoc) - : m_iDocType(DOCTYPE_PDF), - m_pPDFDoc(std::move(pPDFDoc)), - m_pFormFillEnv(nullptr), - m_pXFADocView(nullptr), - m_nLoadStatus(FXFA_LOADSTATUS_PRELOAD), - m_nPageCount(0), + : m_pPDFDoc(std::move(pPDFDoc)), + m_pXFAApp(pdfium::MakeUnique(this)), m_DocEnv(this) { - m_pXFAApp = pdfium::MakeUnique(this); - m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique()); + m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique()); } CPDFXFA_Context::~CPDFXFA_Context() { @@ -56,7 +53,7 @@ CPDFXFA_Context::~CPDFXFA_Context() { // Once we're deleted the FormFillEnvironment will point at a bad underlying // doc so we need to reset it ... m_pFormFillEnv->ResetXFADocument(); - m_pFormFillEnv = nullptr; + m_pFormFillEnv.Reset(); } m_nLoadStatus = FXFA_LOADSTATUS_CLOSED; @@ -65,9 +62,10 @@ CPDFXFA_Context::~CPDFXFA_Context() { void CPDFXFA_Context::CloseXFADoc() { if (!m_pXFADoc) return; + + m_pXFADocView = nullptr; m_pXFADoc->CloseDoc(); m_pXFADoc.reset(); - m_pXFADocView = nullptr; } void CPDFXFA_Context::SetFormFillEnv( @@ -78,7 +76,7 @@ void CPDFXFA_Context::SetFormFillEnv( if (m_pXFADoc && m_pXFADoc->GetXFADoc()) m_pXFADoc->GetXFADoc()->ClearLayoutData(); - m_pFormFillEnv = pFormFillEnv; + m_pFormFillEnv.Reset(pFormFillEnv); } bool CPDFXFA_Context::LoadXFADoc() { @@ -98,14 +96,8 @@ bool CPDFXFA_Context::LoadXFADoc() { return false; } - CXFA_FFDocHandler* pDocHandler = pApp->GetDocHandler(); - if (!pDocHandler) { - SetLastError(FPDF_ERR_XFALOAD); - return false; - } - m_pXFADoc->StartLoad(); - int iStatus = m_pXFADoc->DoLoad(nullptr); + int iStatus = m_pXFADoc->DoLoad(); if (iStatus != XFA_PARSESTATUS_Done) { CloseXFADoc(); SetLastError(FPDF_ERR_XFALOAD); @@ -114,19 +106,19 @@ bool CPDFXFA_Context::LoadXFADoc() { m_pXFADoc->StopLoad(); m_pXFADoc->GetXFADoc()->InitScriptContext(GetJSERuntime()); - if (m_pXFADoc->GetDocType() == XFA_DOCTYPE_Dynamic) - m_iDocType = DOCTYPE_DYNAMIC_XFA; + if (m_pXFADoc->GetFormType() == FormType::kXFAFull) + m_FormType = FormType::kXFAFull; else - m_iDocType = DOCTYPE_STATIC_XFA; + m_FormType = FormType::kXFAForeground; - m_pXFADocView = m_pXFADoc->CreateDocView(XFA_DOCVIEW_View); + m_pXFADocView = m_pXFADoc->CreateDocView(); if (m_pXFADocView->StartLayout() < 0) { CloseXFADoc(); SetLastError(FPDF_ERR_XFALAYOUT); return false; } - m_pXFADocView->DoLayout(nullptr); + m_pXFADocView->DoLayout(); m_pXFADocView->StopLayout(); m_nLoadStatus = FXFA_LOADSTATUS_LOADED; @@ -137,59 +129,53 @@ int CPDFXFA_Context::GetPageCount() const { if (!m_pPDFDoc && !m_pXFADoc) return 0; - switch (m_iDocType) { - case DOCTYPE_PDF: - case DOCTYPE_STATIC_XFA: + switch (m_FormType) { + case FormType::kNone: + case FormType::kAcroForm: + case FormType::kXFAForeground: if (m_pPDFDoc) return m_pPDFDoc->GetPageCount(); - case DOCTYPE_DYNAMIC_XFA: + case FormType::kXFAFull: if (m_pXFADoc) return m_pXFADocView->CountPageViews(); - default: - return 0; } + return 0; } -CPDFXFA_Page* CPDFXFA_Context::GetXFAPage(int page_index) { +RetainPtr CPDFXFA_Context::GetXFAPage(int page_index) { if (page_index < 0) return nullptr; - CPDFXFA_Page* pPage = nullptr; - int nCount = pdfium::CollectionSize(m_XFAPageList); - if (nCount > 0 && page_index < nCount) { - pPage = m_XFAPageList[page_index]; - if (pPage) { - pPage->Retain(); - return pPage; - } + if (pdfium::IndexInBounds(m_XFAPageList, page_index)) { + if (m_XFAPageList[page_index]) + return m_XFAPageList[page_index]; } else { m_nPageCount = GetPageCount(); m_XFAPageList.resize(m_nPageCount); } - pPage = new CPDFXFA_Page(this, page_index); - if (!pPage->LoadPage()) { - pPage->Release(); + auto pPage = pdfium::MakeRetain(this, page_index); + if (!pPage->LoadPage()) return nullptr; - } - if (page_index >= 0 && - page_index < pdfium::CollectionSize(m_XFAPageList)) { + + if (pdfium::IndexInBounds(m_XFAPageList, page_index)) m_XFAPageList[page_index] = pPage; - } + return pPage; } -CPDFXFA_Page* CPDFXFA_Context::GetXFAPage(CXFA_FFPageView* pPage) const { +RetainPtr CPDFXFA_Context::GetXFAPage( + CXFA_FFPageView* pPage) const { if (!pPage) return nullptr; if (!m_pXFADoc) return nullptr; - if (m_iDocType != DOCTYPE_DYNAMIC_XFA) + if (m_FormType != FormType::kXFAFull) return nullptr; - for (CPDFXFA_Page* pTempPage : m_XFAPageList) { + for (auto& pTempPage : m_XFAPageList) { if (pTempPage && pTempPage->GetXFAPageView() == pPage) return pTempPage; } @@ -203,20 +189,8 @@ void CPDFXFA_Context::DeletePage(int page_index) { if (m_pPDFDoc) m_pPDFDoc->DeletePage(page_index); - if (page_index < 0 || - page_index >= pdfium::CollectionSize(m_XFAPageList)) { - return; - } - if (CPDFXFA_Page* pPage = m_XFAPageList[page_index]) - pPage->Release(); -} - -void CPDFXFA_Context::RemovePage(CPDFXFA_Page* page) { - int page_index = page->GetPageIndex(); - if (page_index >= 0 && - page_index < pdfium::CollectionSize(m_XFAPageList)) { - m_XFAPageList[page_index] = nullptr; - } + if (pdfium::IndexInBounds(m_XFAPageList, page_index)) + m_XFAPageList[page_index].Reset(); } void CPDFXFA_Context::ClearChangeMark() { @@ -234,19 +208,19 @@ v8::Isolate* CPDFXFA_Context::GetJSERuntime() const { return runtime->GetIsolate(); } -CFX_WideString CPDFXFA_Context::GetAppTitle() const { +WideString CPDFXFA_Context::GetAppTitle() const { return L"PDFium"; } -CFX_WideString CPDFXFA_Context::GetAppName() { +WideString CPDFXFA_Context::GetAppName() { return m_pFormFillEnv ? m_pFormFillEnv->FFI_GetAppName() : L""; } -CFX_WideString CPDFXFA_Context::GetLanguage() { +WideString CPDFXFA_Context::GetLanguage() { return m_pFormFillEnv ? m_pFormFillEnv->GetLanguage() : L""; } -CFX_WideString CPDFXFA_Context::GetPlatform() { +WideString CPDFXFA_Context::GetPlatform() { return m_pFormFillEnv ? m_pFormFillEnv->GetPlatform() : L""; } @@ -255,8 +229,8 @@ void CPDFXFA_Context::Beep(uint32_t dwType) { m_pFormFillEnv->JS_appBeep(dwType); } -int32_t CPDFXFA_Context::MsgBox(const CFX_WideString& wsMessage, - const CFX_WideString& wsTitle, +int32_t CPDFXFA_Context::MsgBox(const WideString& wsMessage, + const WideString& wsTitle, uint32_t dwIconType, uint32_t dwButtonType) { if (!m_pFormFillEnv) @@ -307,43 +281,40 @@ int32_t CPDFXFA_Context::MsgBox(const CFX_WideString& wsMessage, return XFA_IDYes; } -CFX_WideString CPDFXFA_Context::Response(const CFX_WideString& wsQuestion, - const CFX_WideString& wsTitle, - const CFX_WideString& wsDefaultAnswer, - bool bMark) { - CFX_WideString wsAnswer; +WideString CPDFXFA_Context::Response(const WideString& wsQuestion, + const WideString& wsTitle, + const WideString& wsDefaultAnswer, + bool bMark) { if (!m_pFormFillEnv) - return wsAnswer; + return WideString(); int nLength = 2048; - char* pBuff = new char[nLength]; + std::vector pBuff(nLength); nLength = m_pFormFillEnv->JS_appResponse(wsQuestion.c_str(), wsTitle.c_str(), wsDefaultAnswer.c_str(), nullptr, - bMark, pBuff, nLength); - if (nLength > 0) { - nLength = nLength > 2046 ? 2046 : nLength; - pBuff[nLength] = 0; - pBuff[nLength + 1] = 0; - wsAnswer = CFX_WideString::FromUTF16LE( - reinterpret_cast(pBuff), - nLength / sizeof(unsigned short)); - } - delete[] pBuff; - return wsAnswer; + bMark, pBuff.data(), nLength); + if (nLength <= 0) + return WideString(); + + nLength = std::min(2046, nLength); + pBuff[nLength] = 0; + pBuff[nLength + 1] = 0; + return WideString::FromUTF16LE(reinterpret_cast(pBuff.data()), + nLength / sizeof(uint16_t)); } -CFX_RetainPtr CPDFXFA_Context::DownloadURL( - const CFX_WideString& wsURL) { +RetainPtr CPDFXFA_Context::DownloadURL( + const WideString& wsURL) { return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL.c_str()) : nullptr; } -bool CPDFXFA_Context::PostRequestURL(const CFX_WideString& wsURL, - const CFX_WideString& wsData, - const CFX_WideString& wsContentType, - const CFX_WideString& wsEncode, - const CFX_WideString& wsHeader, - CFX_WideString& wsResponse) { +bool CPDFXFA_Context::PostRequestURL(const WideString& wsURL, + const WideString& wsData, + const WideString& wsContentType, + const WideString& wsEncode, + const WideString& wsHeader, + WideString& wsResponse) { if (!m_pFormFillEnv) return false; @@ -353,9 +324,9 @@ bool CPDFXFA_Context::PostRequestURL(const CFX_WideString& wsURL, return true; } -bool CPDFXFA_Context::PutRequestURL(const CFX_WideString& wsURL, - const CFX_WideString& wsData, - const CFX_WideString& wsEncode) { +bool CPDFXFA_Context::PutRequestURL(const WideString& wsURL, + const WideString& wsData, + const WideString& wsEncode) { return m_pFormFillEnv && m_pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(), wsEncode.c_str()); @@ -364,6 +335,6 @@ bool CPDFXFA_Context::PutRequestURL(const CFX_WideString& wsURL, IFWL_AdapterTimerMgr* CPDFXFA_Context::GetTimerMgr() { CXFA_FWLAdapterTimerMgr* pAdapter = nullptr; if (m_pFormFillEnv) - pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv); + pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv.Get()); return pAdapter; } diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.h b/fpdfsdk/fpdfxfa/cpdfxfa_context.h index 9a2a517fb5aba65142a7371cd30cf79e676bba9f..acef8f2aa8b8b8ad8b7852df4955ebe2ef7e8ac3 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_context.h +++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.h @@ -10,12 +10,15 @@ #include #include +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/observable.h" +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h" -#include "xfa/fxfa/xfa_ffdoc.h" +#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" +#include "xfa/fxfa/cxfa_ffdoc.h" class CJS_Runtime; class CPDFSDK_FormFillEnvironment; -class CPDFXFA_Page; class CXFA_FFDocHandler; class IJS_EventContext; class IJS_Runtime; @@ -36,50 +39,52 @@ class CPDFXFA_Context : public IXFA_AppProvider { bool LoadXFADoc(); CPDF_Document* GetPDFDoc() { return m_pPDFDoc.get(); } CXFA_FFDoc* GetXFADoc() { return m_pXFADoc.get(); } - CXFA_FFDocView* GetXFADocView() { return m_pXFADocView; } - int GetDocType() const { return m_iDocType; } + CXFA_FFDocView* GetXFADocView() { return m_pXFADocView.Get(); } + FormType GetFormType() const { return m_FormType; } + bool ContainsXFAForm() const { + return m_FormType == FormType::kXFAFull || + m_FormType == FormType::kXFAForeground; + } v8::Isolate* GetJSERuntime() const; CXFA_FFApp* GetXFAApp() { return m_pXFAApp.get(); } - CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; } + CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { + return m_pFormFillEnv.Get(); + } void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void DeletePage(int page_index); int GetPageCount() const; - - CPDFXFA_Page* GetXFAPage(int page_index); - CPDFXFA_Page* GetXFAPage(CXFA_FFPageView* pPage) const; - - void RemovePage(CPDFXFA_Page* page); - + void DeletePage(int page_index); + RetainPtr GetXFAPage(int page_index); + RetainPtr GetXFAPage(CXFA_FFPageView* pPage) const; void ClearChangeMark(); // IFXA_AppProvider: - CFX_WideString GetLanguage() override; - CFX_WideString GetPlatform() override; - CFX_WideString GetAppName() override; - CFX_WideString GetAppTitle() const override; + WideString GetLanguage() override; + WideString GetPlatform() override; + WideString GetAppName() override; + WideString GetAppTitle() const override; void Beep(uint32_t dwType) override; - int32_t MsgBox(const CFX_WideString& wsMessage, - const CFX_WideString& wsTitle, + int32_t MsgBox(const WideString& wsMessage, + const WideString& wsTitle, uint32_t dwIconType, uint32_t dwButtonType) override; - CFX_WideString Response(const CFX_WideString& wsQuestion, - const CFX_WideString& wsTitle, - const CFX_WideString& wsDefaultAnswer, - bool bMark) override; - CFX_RetainPtr DownloadURL( - const CFX_WideString& wsURL) override; - bool PostRequestURL(const CFX_WideString& wsURL, - const CFX_WideString& wsData, - const CFX_WideString& wsContentType, - const CFX_WideString& wsEncode, - const CFX_WideString& wsHeader, - CFX_WideString& wsResponse) override; - bool PutRequestURL(const CFX_WideString& wsURL, - const CFX_WideString& wsData, - const CFX_WideString& wsEncode) override; + WideString Response(const WideString& wsQuestion, + const WideString& wsTitle, + const WideString& wsDefaultAnswer, + bool bMark) override; + RetainPtr DownloadURL( + const WideString& wsURL) override; + bool PostRequestURL(const WideString& wsURL, + const WideString& wsData, + const WideString& wsContentType, + const WideString& wsEncode, + const WideString& wsHeader, + WideString& wsResponse) override; + bool PutRequestURL(const WideString& wsURL, + const WideString& wsData, + const WideString& wsEncode) override; IFWL_AdapterTimerMgr* GetTimerMgr() override; @@ -93,22 +98,23 @@ class CPDFXFA_Context : public IXFA_AppProvider { } LoadStatus GetLoadStatus() const { return m_nLoadStatus; } - std::vector* GetXFAPageList() { return &m_XFAPageList; } + std::vector>* GetXFAPageList() { + return &m_XFAPageList; + } private: void CloseXFADoc(); - int m_iDocType; - + FormType m_FormType = FormType::kNone; std::unique_ptr m_pPDFDoc; std::unique_ptr m_pXFADoc; - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; // not owned. - CXFA_FFDocView* m_pXFADocView; // not owned. + Observable::ObservedPtr m_pFormFillEnv; + UnownedPtr m_pXFADocView; std::unique_ptr m_pXFAApp; std::unique_ptr m_pRuntime; - std::vector m_XFAPageList; - LoadStatus m_nLoadStatus; - int m_nPageCount; + std::vector> m_XFAPageList; + LoadStatus m_nLoadStatus = FXFA_LOADSTATUS_PRELOAD; + int m_nPageCount = 0; // Must be destroyed before |m_pFormFillEnv|. CPDFXFA_DocEnvironment m_DocEnv; diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp index 731b0cc2967b5570f35a6b838c81ee8eaf04b382..4ebe8f92b94465cd9e92404368250d4cdd3b35ba 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp +++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp @@ -11,16 +11,18 @@ #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/cpdf_string.h" -#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/retain_ptr.h" #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_interform.h" #include "fpdfsdk/cpdfsdk_pageview.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" -#include "fpdfsdk/javascript/ijs_runtime.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" +#include "fxjs/ijs_runtime.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_widgetacciterator.h" +#include "xfa/fxfa/parser/cxfa_submit.h" #define IDS_XFA_Validate_Input \ "At least one required field was empty. Please fill in the required " \ @@ -38,16 +40,11 @@ #define FXFA_XFA_ALL 0x01111111 CPDFXFA_DocEnvironment::CPDFXFA_DocEnvironment(CPDFXFA_Context* pContext) - : m_pContext(pContext), m_pJSEventContext(nullptr) { + : m_pContext(pContext) { ASSERT(m_pContext); } -CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() { - if (m_pJSEventContext && m_pContext->GetFormFillEnv()) { - m_pContext->GetFormFillEnv()->GetJSRuntime()->ReleaseEventContext( - m_pJSEventContext); - } -} +CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() {} void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) { if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv()) @@ -55,15 +52,14 @@ void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) { } void CPDFXFA_DocEnvironment::InvalidateRect(CXFA_FFPageView* pPageView, - const CFX_RectF& rt, - uint32_t dwFlags /* = 0 */) { + const CFX_RectF& rt) { if (!m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv()) return; - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA) + if (m_pContext->GetFormType() != FormType::kXFAFull) return; - CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pPageView); + RetainPtr pPage = m_pContext->GetXFAPage(pPageView); if (!pPage) return; @@ -71,8 +67,7 @@ void CPDFXFA_DocEnvironment::InvalidateRect(CXFA_FFPageView* pPageView, if (!pFormFillEnv) return; - pFormFillEnv->Invalidate(static_cast(pPage), - CFX_FloatRect::FromCFXRectF(rt).ToFxRect()); + pFormFillEnv->Invalidate(pPage.Get(), rt.ToFloatRect().ToFxRect()); } void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget, @@ -82,7 +77,7 @@ void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget, !m_pContext->GetFormFillEnv() || !m_pContext->GetXFADocView()) return; - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA) + if (m_pContext->GetFormType() != FormType::kXFAFull) return; CXFA_FFWidgetHandler* pWidgetHandler = @@ -94,7 +89,7 @@ void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget, if (!pPageView) return; - CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pPageView); + RetainPtr pPage = m_pContext->GetXFAPage(pPageView); if (!pPage) return; @@ -102,14 +97,14 @@ void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget, if (!pFormFillEnv) return; - CFX_FloatRect rcCaret = CFX_FloatRect::FromCFXRectF(*pRtAnchor); - pFormFillEnv->DisplayCaret((FPDF_PAGE)pPage, bVisible, rcCaret.left, - rcCaret.top, rcCaret.right, rcCaret.bottom); + CFX_FloatRect rcCaret = pRtAnchor->ToFloatRect(); + pFormFillEnv->DisplayCaret(pPage.Get(), bVisible, rcCaret.left, rcCaret.top, + rcCaret.right, rcCaret.bottom); } bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget, - FX_FLOAT fMinPopup, - FX_FLOAT fMaxPopup, + float fMinPopup, + float fMaxPopup, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) { if (!hWidget) @@ -119,22 +114,21 @@ bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget, if (!pXFAPageView) return false; - CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pXFAPageView); + RetainPtr pPage = m_pContext->GetXFAPage(pXFAPageView); if (!pPage) return false; - CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc(); - int nRotate = pWidgetAcc->GetRotate(); CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return false; FS_RECTF pageViewRect = {0.0f, 0.0f, 0.0f, 0.0f}; - pFormFillEnv->GetPageViewRect(pPage, pageViewRect); + pFormFillEnv->GetPageViewRect(pPage.Get(), pageViewRect); int t1; int t2; - CFX_FloatRect rcAnchor = CFX_FloatRect::FromCFXRectF(rtAnchor); + CFX_FloatRect rcAnchor = rtAnchor.ToFloatRect(); + int nRotate = hWidget->GetNode()->GetRotate(); switch (nRotate) { case 90: { t1 = (int)(pageViewRect.right - rcAnchor.right); @@ -185,13 +179,13 @@ bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget, dwPos = 1; } - FX_FLOAT fPopupHeight; + float fPopupHeight; if (t < fMinPopup) fPopupHeight = fMinPopup; else if (t > fMaxPopup) fPopupHeight = fMaxPopup; else - fPopupHeight = static_cast(t); + fPopupHeight = static_cast(t); switch (nRotate) { case 0: @@ -232,7 +226,7 @@ bool CPDFXFA_DocEnvironment::PopupMenu(CXFA_FFWidget* hWidget, if (!pXFAPageView) return false; - CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pXFAPageView); + RetainPtr pPage = m_pContext->GetXFAPage(pXFAPageView); if (!pPage) return false; @@ -254,7 +248,7 @@ bool CPDFXFA_DocEnvironment::PopupMenu(CXFA_FFWidget* hWidget, if (hWidget->CanSelectAll()) menuFlag |= FXFA_MENU_SELECTALL; - return pFormFillEnv->PopupMenu(pPage, hWidget, menuFlag, ptPopup); + return pFormFillEnv->PopupMenu(pPage.Get(), hWidget, menuFlag, ptPopup); } void CPDFXFA_DocEnvironment::PageViewEvent(CXFA_FFPageView* pPageView, @@ -278,54 +272,57 @@ void CPDFXFA_DocEnvironment::PageViewEvent(CXFA_FFPageView* pPageView, for (int iPageIter = 0; iPageIter < m_pContext->GetOriginalPageCount(); iPageIter++) { - CPDFXFA_Page* pPage = (*m_pContext->GetXFAPageList())[iPageIter]; + RetainPtr pPage = (*m_pContext->GetXFAPageList())[iPageIter]; if (!pPage) continue; - m_pContext->GetFormFillEnv()->RemovePageView(pPage); + m_pContext->GetFormFillEnv()->RemovePageView(pPage.Get()); pPage->SetXFAPageView(pXFADocView->GetPageView(iPageIter)); } int flag = (nNewCount < m_pContext->GetOriginalPageCount()) ? FXFA_PAGEVIEWEVENT_POSTREMOVED : FXFA_PAGEVIEWEVENT_POSTADDED; - int count = FXSYS_abs(nNewCount - m_pContext->GetOriginalPageCount()); + int count = abs(nNewCount - m_pContext->GetOriginalPageCount()); m_pContext->SetOriginalPageCount(nNewCount); pFormFillEnv->PageEvent(count, flag); } void CPDFXFA_DocEnvironment::WidgetPostAdd(CXFA_FFWidget* hWidget, - CXFA_WidgetAcc* pWidgetData) { - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || !hWidget) + CXFA_WidgetAcc* pWidgetAcc) { + if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget) return; CXFA_FFPageView* pPageView = hWidget->GetPageView(); if (!pPageView) return; - CPDFXFA_Page* pXFAPage = m_pContext->GetXFAPage(pPageView); + RetainPtr pXFAPage = m_pContext->GetXFAPage(pPageView); if (!pXFAPage) return; - m_pContext->GetFormFillEnv()->GetPageView(pXFAPage, true)->AddAnnot(hWidget); + m_pContext->GetFormFillEnv() + ->GetPageView(pXFAPage.Get(), true) + ->AddAnnot(hWidget); } void CPDFXFA_DocEnvironment::WidgetPreRemove(CXFA_FFWidget* hWidget, - CXFA_WidgetAcc* pWidgetData) { - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || !hWidget) + CXFA_WidgetAcc* pWidgetAcc) { + if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget) return; CXFA_FFPageView* pPageView = hWidget->GetPageView(); if (!pPageView) return; - CPDFXFA_Page* pXFAPage = m_pContext->GetXFAPage(pPageView); + RetainPtr pXFAPage = m_pContext->GetXFAPage(pPageView); if (!pXFAPage) return; CPDFSDK_PageView* pSdkPageView = - m_pContext->GetFormFillEnv()->GetPageView(pXFAPage, true); - if (CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget)) + m_pContext->GetFormFillEnv()->GetPageView(pXFAPage.Get(), true); + CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget); + if (pAnnot) pSdkPageView->DeleteAnnot(pAnnot); } @@ -338,20 +335,20 @@ int32_t CPDFXFA_DocEnvironment::CountPages(CXFA_FFDoc* hDoc) { int32_t CPDFXFA_DocEnvironment::GetCurrentPage(CXFA_FFDoc* hDoc) { if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv()) return -1; - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA) + if (m_pContext->GetFormType() != FormType::kXFAFull) return -1; CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return -1; - return pFormFillEnv->GetCurrentPageIndex(this); + return pFormFillEnv->GetCurrentPageIndex(m_pContext.Get()); } void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc, int32_t iCurPage) { if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv() || - m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || iCurPage < 0 || + m_pContext->GetFormType() != FormType::kXFAFull || iCurPage < 0 || iCurPage >= m_pContext->GetFormFillEnv()->GetPageCount()) { return; } @@ -359,7 +356,7 @@ void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc, CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return; - pFormFillEnv->SetCurrentPage(this, iCurPage); + pFormFillEnv->SetCurrentPage(m_pContext.Get(), iCurPage); } bool CPDFXFA_DocEnvironment::IsCalculationsEnabled(CXFA_FFDoc* hDoc) { @@ -382,53 +379,51 @@ void CPDFXFA_DocEnvironment::SetCalculationsEnabled(CXFA_FFDoc* hDoc, } } -void CPDFXFA_DocEnvironment::GetTitle(CXFA_FFDoc* hDoc, - CFX_WideString& wsTitle) { +void CPDFXFA_DocEnvironment::GetTitle(CXFA_FFDoc* hDoc, WideString& wsTitle) { if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc()) return; - CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo(); + const CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo(); if (!pInfoDict) return; - CFX_ByteString csTitle = pInfoDict->GetStringFor("Title"); + ByteString csTitle = pInfoDict->GetStringFor("Title"); wsTitle = wsTitle.FromLocal(csTitle.GetBuffer(csTitle.GetLength())); csTitle.ReleaseBuffer(csTitle.GetLength()); } void CPDFXFA_DocEnvironment::SetTitle(CXFA_FFDoc* hDoc, - const CFX_WideString& wsTitle) { + const WideString& wsTitle) { if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc()) return; - if (CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo()) + CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo(); + if (pInfoDict) pInfoDict->SetNewFor("Title", wsTitle); } void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc, - const CFX_WideString& wsFilePath, + const WideString& wsFilePath, bool bXDP) { if (hDoc != m_pContext->GetXFADoc()) return; - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA && - m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) { + if (!m_pContext->ContainsXFAForm()) return; - } CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return; int fileType = bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML; - CFX_ByteString bs = wsFilePath.UTF16LE_Encode(); + ByteString bs = wsFilePath.UTF16LE_Encode(); if (wsFilePath.IsEmpty()) { if (!pFormFillEnv->GetFormFillInfo() || !pFormFillEnv->GetFormFillInfo()->m_pJsPlatform) { return; } - CFX_WideString filepath = pFormFillEnv->JS_fieldBrowse(); + WideString filepath = pFormFillEnv->JS_fieldBrowse(); bs = filepath.UTF16LE_Encode(); } int len = bs.GetLength(); @@ -439,20 +434,20 @@ void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc, if (!pFileHandler) return; - CFX_RetainPtr fileWrite = - MakeSeekableStream(pFileHandler); - CFX_ByteString content; + RetainPtr fileWrite = MakeSeekableStream(pFileHandler); if (fileType == FXFA_SAVEAS_XML) { - content = "\r\n"; + ByteString content = "\r\n"; fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(), content.GetLength()); - m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Data, - fileWrite, nullptr); + CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc(); + ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Data)), fileWrite, + nullptr); } else if (fileType == FXFA_SAVEAS_XDP) { if (!m_pContext->GetPDFDoc()) return; - CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot(); + const CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot(); if (!pRoot) return; @@ -477,28 +472,32 @@ void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc, if (!pStream) continue; if (pPrePDFObj->GetString() == "form") { - m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Form, - fileWrite, nullptr); + CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc(); + ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)), + fileWrite, nullptr); continue; } if (pPrePDFObj->GetString() == "datasets") { - m_pContext->GetXFADocView()->GetDoc()->SavePackage( - XFA_HASHCODE_Datasets, fileWrite, nullptr); + CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc(); + ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)), + fileWrite, nullptr); continue; } if (i == size - 1) { - CFX_WideString wPath = CFX_WideString::FromUTF16LE( + WideString wPath = WideString::FromUTF16LE( reinterpret_cast(bs.c_str()), bs.GetLength() / sizeof(unsigned short)); - CFX_ByteString bPath = wPath.UTF8Encode(); + ByteString bPath = wPath.UTF8Encode(); const char* szFormat = "\n"; - content.Format(szFormat, bPath.c_str()); + ByteString content = ByteString::Format(szFormat, bPath.c_str()); fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(), content.GetLength()); } - std::unique_ptr pAcc(new CPDF_StreamAcc); - pAcc->LoadAllData(pStream); + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllDataFiltered(); fileWrite->WriteBlock(pAcc->GetData(), fileWrite->GetSize(), pAcc->GetSize()); } @@ -507,19 +506,19 @@ void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc, } void CPDFXFA_DocEnvironment::GotoURL(CXFA_FFDoc* hDoc, - const CFX_WideString& bsURL) { + const WideString& bsURL) { if (hDoc != m_pContext->GetXFADoc()) return; - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA) + if (m_pContext->GetFormType() != FormType::kXFAFull) return; CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return; - CFX_WideStringC str(bsURL.c_str()); - pFormFillEnv->GotoURL(this, str); + WideStringView str(bsURL.c_str()); + pFormFillEnv->GotoURL(m_pContext.Get(), str); } bool CPDFXFA_DocEnvironment::IsValidationsEnabled(CXFA_FFDoc* hDoc) { @@ -599,7 +598,7 @@ FX_ARGB CPDFXFA_DocEnvironment::GetHighlightColor(CXFA_FFDoc* hDoc) { return 0; return ArgbEncode(pInterForm->GetHighlightAlpha(), - pInterForm->GetHighlightColor(FPDF_FORMFIELD_XFA)); + pInterForm->GetHighlightColor(FormFieldType::kXFA)); } bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) { @@ -611,21 +610,19 @@ bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) { } bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() { - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA && - m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) { + if (!m_pContext->ContainsXFAForm()) return true; - } - if (!m_pContext->GetXFADocView()) + CXFA_FFDocView* docView = m_pContext->GetXFADocView(); + if (!docView) return true; - CXFA_FFWidgetHandler* pWidgetHandler = - m_pContext->GetXFADocView()->GetWidgetHandler(); + CXFA_FFWidgetHandler* pWidgetHandler = docView->GetWidgetHandler(); if (!pWidgetHandler) return true; - std::unique_ptr pWidgetAccIterator( - m_pContext->GetXFADocView()->CreateWidgetAccIterator()); + std::unique_ptr pWidgetAccIterator = + docView->CreateWidgetAccIterator(); if (pWidgetAccIterator) { CXFA_EventParam Param; Param.m_eType = XFA_EVENT_PreSubmit; @@ -633,23 +630,21 @@ bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() { pWidgetHandler->ProcessEvent(pWidgetAcc, &Param); } - pWidgetAccIterator.reset( - m_pContext->GetXFADocView()->CreateWidgetAccIterator()); + pWidgetAccIterator = docView->CreateWidgetAccIterator(); if (!pWidgetAccIterator) return true; CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext(); pWidgetAcc = pWidgetAccIterator->MoveToNext(); while (pWidgetAcc) { - int fRet = pWidgetAcc->ProcessValidate(-1); + int fRet = pWidgetAcc->GetNode()->ProcessValidate(docView, -1); if (fRet == XFA_EVENTERROR_Error) { CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return false; - CFX_WideString ws; - ws.FromLocal(IDS_XFA_Validate_Input); - CFX_ByteString bs = ws.UTF16LE_Encode(); + WideString ws = WideString::FromLocal(IDS_XFA_Validate_Input); + ByteString bs = ws.UTF16LE_Encode(); int len = bs.GetLength(); pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len), (FPDF_WIDESTRING)L"", 0, 1); @@ -658,14 +653,13 @@ bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() { } pWidgetAcc = pWidgetAccIterator->MoveToNext(); } - m_pContext->GetXFADocView()->UpdateDocView(); + docView->UpdateDocView(); return true; } void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() { - if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA && - m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) + if (!m_pContext->ContainsXFAForm()) return; if (!m_pContext->GetXFADocView()) @@ -676,8 +670,8 @@ void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() { if (!pWidgetHandler) return; - std::unique_ptr pWidgetAccIterator( - m_pContext->GetXFADocView()->CreateWidgetAccIterator()); + std::unique_ptr pWidgetAccIterator = + m_pContext->GetXFADocView()->CreateWidgetAccIterator(); if (!pWidgetAccIterator) return; @@ -691,24 +685,24 @@ void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() { m_pContext->GetXFADocView()->UpdateDocView(); } -bool CPDFXFA_DocEnvironment::SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) { +bool CPDFXFA_DocEnvironment::Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) { if (!NotifySubmit(true) || !m_pContext->GetXFADocView()) return false; m_pContext->GetXFADocView()->UpdateDocView(); - bool ret = SubmitDataInternal(hDoc, submit); + bool ret = SubmitInternal(hDoc, submit); NotifySubmit(false); return ret; } -CFX_RetainPtr CPDFXFA_DocEnvironment::OpenLinkedFile( +RetainPtr CPDFXFA_DocEnvironment::OpenLinkedFile( CXFA_FFDoc* hDoc, - const CFX_WideString& wsLink) { + const WideString& wsLink) { CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return nullptr; - CFX_ByteString bs = wsLink.UTF16LE_Encode(); + ByteString bs = wsLink.UTF16LE_Encode(); int len = bs.GetLength(); FPDF_FILEHANDLER* pFileHandler = pFormFillEnv->OpenFile(0, (FPDF_WIDESTRING)bs.GetBuffer(len), "rb"); @@ -726,19 +720,20 @@ bool CPDFXFA_DocEnvironment::ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler, if (!m_pContext->GetXFADocView()) return false; - CFX_ByteString content; CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return false; - CFX_RetainPtr fileStream = - MakeSeekableStream(pFileHandler); - + CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc(); + RetainPtr fileStream = MakeSeekableStream(pFileHandler); if (fileType == FXFA_SAVEAS_XML) { - const char kContent[] = "\r\n"; + static constexpr char kContent[] = + "\r\n"; fileStream->WriteBlock(kContent, 0, strlen(kContent)); - m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Data, fileStream, - nullptr); + + ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Data)), fileStream, + nullptr); return true; } @@ -754,7 +749,7 @@ bool CPDFXFA_DocEnvironment::ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler, return false; } - CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot(); + const CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot(); if (!pRoot) { fileStream->Flush(); return false; @@ -798,34 +793,35 @@ bool CPDFXFA_DocEnvironment::ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler, continue; if (pPrePDFObj->GetString() == "form" && !(flag & FXFA_FORM)) continue; + if (pPrePDFObj->GetString() == "form") { - m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Form, fileStream, - nullptr); + ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)), + fileStream, nullptr); } else if (pPrePDFObj->GetString() == "datasets") { - m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Datasets, fileStream, - nullptr); - } else { - // PDF,creator. + ffdoc->SavePackage( + ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)), + fileStream, nullptr); } } return true; } -void CPDFXFA_DocEnvironment::ToXFAContentFlags(CFX_WideString csSrcContent, +void CPDFXFA_DocEnvironment::ToXFAContentFlags(WideString csSrcContent, FPDF_DWORD& flag) { - if (csSrcContent.Find(L" config ", 0) != -1) + if (csSrcContent.Contains(L" config ")) flag |= FXFA_CONFIG; - if (csSrcContent.Find(L" template ", 0) != -1) + if (csSrcContent.Contains(L" template ")) flag |= FXFA_TEMPLATE; - if (csSrcContent.Find(L" localeSet ", 0) != -1) + if (csSrcContent.Contains(L" localeSet ")) flag |= FXFA_LOCALESET; - if (csSrcContent.Find(L" datasets ", 0) != -1) + if (csSrcContent.Contains(L" datasets ")) flag |= FXFA_DATASETS; - if (csSrcContent.Find(L" xmpmeta ", 0) != -1) + if (csSrcContent.Contains(L" xmpmeta ")) flag |= FXFA_XMPMETA; - if (csSrcContent.Find(L" xfdf ", 0) != -1) + if (csSrcContent.Contains(L" xfdf ")) flag |= FXFA_XFDF; - if (csSrcContent.Find(L" form ", 0) != -1) + if (csSrcContent.Contains(L" form ")) flag |= FXFA_FORM; if (flag == 0) { flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS | @@ -833,43 +829,40 @@ void CPDFXFA_DocEnvironment::ToXFAContentFlags(CFX_WideString csSrcContent, } } -bool CPDFXFA_DocEnvironment::MailToInfo(CFX_WideString& csURL, - CFX_WideString& csToAddress, - CFX_WideString& csCCAddress, - CFX_WideString& csBCCAddress, - CFX_WideString& csSubject, - CFX_WideString& csMsg) { - CFX_WideString srcURL = csURL; +bool CPDFXFA_DocEnvironment::MailToInfo(WideString& csURL, + WideString& csToAddress, + WideString& csCCAddress, + WideString& csBCCAddress, + WideString& csSubject, + WideString& csMsg) { + WideString srcURL = csURL; srcURL.TrimLeft(); if (srcURL.Left(7).CompareNoCase(L"mailto:") != 0) return false; - int pos = srcURL.Find(L'?', 0); - CFX_WideString tmp; - if (pos == -1) { - pos = srcURL.Find(L'@', 0); - if (pos == -1) + auto pos = srcURL.Find(L'?'); + WideString tmp; + if (!pos.has_value()) { + pos = srcURL.Find(L'@'); + if (!pos.has_value()) return false; tmp = srcURL.Right(csURL.GetLength() - 7); } else { - tmp = srcURL.Left(pos); + tmp = srcURL.Left(pos.value()); tmp = tmp.Right(tmp.GetLength() - 7); } - tmp.TrimLeft(); - tmp.TrimRight(); + tmp.Trim(); csToAddress = tmp; - srcURL = srcURL.Right(srcURL.GetLength() - (pos + 1)); + srcURL = srcURL.Right(srcURL.GetLength() - (pos.value() + 1)); while (!srcURL.IsEmpty()) { - srcURL.TrimLeft(); - srcURL.TrimRight(); - pos = srcURL.Find(L'&', 0); + srcURL.Trim(); + pos = srcURL.Find(L'&'); - tmp = (pos == -1) ? srcURL : srcURL.Left(pos); - tmp.TrimLeft(); - tmp.TrimRight(); + tmp = (!pos.has_value()) ? srcURL : srcURL.Left(pos.value()); + tmp.Trim(); if (tmp.GetLength() >= 3 && tmp.Left(3).CompareNoCase(L"cc=") == 0) { tmp = tmp.Right(tmp.GetLength() - 3); if (!csCCAddress.IsEmpty()) @@ -890,7 +883,9 @@ bool CPDFXFA_DocEnvironment::MailToInfo(CFX_WideString& csURL, tmp = tmp.Right(tmp.GetLength() - 5); csMsg += tmp; } - srcURL = (pos == -1) ? L"" : srcURL.Right(csURL.GetLength() - (pos + 1)); + srcURL = !pos.has_value() + ? L"" + : srcURL.Right(csURL.GetLength() - (pos.value() + 1)); } csToAddress.Replace(L",", L";"); csCCAddress.Replace(L",", L";"); @@ -898,41 +893,34 @@ bool CPDFXFA_DocEnvironment::MailToInfo(CFX_WideString& csURL, return true; } -bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc, - CXFA_Submit submit) { +bool CPDFXFA_DocEnvironment::SubmitInternal(CXFA_FFDoc* hDoc, + CXFA_Submit* submit) { CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); if (!pFormFillEnv) return false; - CFX_WideStringC csURLC; - submit.GetSubmitTarget(csURLC); - CFX_WideString csURL(csURLC); + WideString csURL = submit->GetSubmitTarget(); if (csURL.IsEmpty()) { - CFX_WideString ws; - ws.FromLocal("Submit cancelled."); - CFX_ByteString bs = ws.UTF16LE_Encode(); + WideString ws = WideString::FromLocal("Submit cancelled."); + ByteString bs = ws.UTF16LE_Encode(); int len = bs.GetLength(); - pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len), - (FPDF_WIDESTRING)L"", 0, 4); + pFormFillEnv->Alert(reinterpret_cast(bs.GetBuffer(len)), + reinterpret_cast(L""), 0, 4); bs.ReleaseBuffer(len); return false; } FPDF_FILEHANDLER* pFileHandler = nullptr; int fileFlag = -1; - switch (submit.GetSubmitFormat()) { - case XFA_ATTRIBUTEENUM_Xdp: { - CFX_WideStringC csContentC; - submit.GetSubmitXDPContent(csContentC); - CFX_WideString csContent; - csContent = csContentC; - csContent.TrimLeft(); - csContent.TrimRight(); - CFX_WideString space; - space.FromLocal(" "); + switch (submit->GetSubmitFormat()) { + case XFA_AttributeEnum::Xdp: { + WideString csContent = submit->GetSubmitXDPContent(); + csContent.Trim(); + + WideString space = WideString::FromLocal(" "); csContent = space + csContent + space; FPDF_DWORD flag = 0; - if (submit.IsSubmitEmbedPDF()) + if (submit->IsSubmitEmbedPDF()) flag |= FXFA_PDF; ToXFAContentFlags(csContent, flag); @@ -941,14 +929,14 @@ bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc, ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XDP, 0, flag); break; } - case XFA_ATTRIBUTEENUM_Xml: + case XFA_AttributeEnum::Xml: pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb"); fileFlag = FXFA_SAVEAS_XML; ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL); break; - case XFA_ATTRIBUTEENUM_Pdf: + case XFA_AttributeEnum::Pdf: break; - case XFA_ATTRIBUTEENUM_Urlencoded: + case XFA_AttributeEnum::Urlencoded: pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb"); fileFlag = FXFA_SAVEAS_XML; ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL); @@ -958,21 +946,22 @@ bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc, } if (!pFileHandler) return false; + if (csURL.Left(7).CompareNoCase(L"mailto:") == 0) { - CFX_WideString csToAddress; - CFX_WideString csCCAddress; - CFX_WideString csBCCAddress; - CFX_WideString csSubject; - CFX_WideString csMsg; + WideString csToAddress; + WideString csCCAddress; + WideString csBCCAddress; + WideString csSubject; + WideString csMsg; if (!MailToInfo(csURL, csToAddress, csCCAddress, csBCCAddress, csSubject, csMsg)) { return false; } - CFX_ByteString bsTo = CFX_WideString(csToAddress).UTF16LE_Encode(); - CFX_ByteString bsCC = CFX_WideString(csCCAddress).UTF16LE_Encode(); - CFX_ByteString bsBcc = CFX_WideString(csBCCAddress).UTF16LE_Encode(); - CFX_ByteString bsSubject = CFX_WideString(csSubject).UTF16LE_Encode(); - CFX_ByteString bsMsg = CFX_WideString(csMsg).UTF16LE_Encode(); + ByteString bsTo = WideString(csToAddress).UTF16LE_Encode(); + ByteString bsCC = WideString(csCCAddress).UTF16LE_Encode(); + ByteString bsBcc = WideString(csBCCAddress).UTF16LE_Encode(); + ByteString bsSubject = WideString(csSubject).UTF16LE_Encode(); + ByteString bsMsg = WideString(csMsg).UTF16LE_Encode(); FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(bsTo.GetLength()); FPDF_WIDESTRING pCC = (FPDF_WIDESTRING)bsCC.GetBuffer(bsCC.GetLength()); FPDF_WIDESTRING pBcc = (FPDF_WIDESTRING)bsBcc.GetBuffer(bsBcc.GetLength()); @@ -980,15 +969,15 @@ bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc, (FPDF_WIDESTRING)bsSubject.GetBuffer(bsSubject.GetLength()); FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength()); pFormFillEnv->EmailTo(pFileHandler, pTo, pSubject, pCC, pBcc, pMsg); - bsTo.ReleaseBuffer(); - bsCC.ReleaseBuffer(); - bsBcc.ReleaseBuffer(); - bsSubject.ReleaseBuffer(); - bsMsg.ReleaseBuffer(); + bsTo.ReleaseBuffer(bsTo.GetStringLength()); + bsCC.ReleaseBuffer(bsCC.GetStringLength()); + bsBcc.ReleaseBuffer(bsBcc.GetStringLength()); + bsSubject.ReleaseBuffer(bsSubject.GetStringLength()); + bsMsg.ReleaseBuffer(bsMsg.GetStringLength()); } else { // HTTP or FTP - CFX_WideString ws; - CFX_ByteString bs = csURL.UTF16LE_Encode(); + WideString ws; + ByteString bs = csURL.UTF16LE_Encode(); int len = bs.GetLength(); pFormFillEnv->UploadTo(pFileHandler, fileFlag, (FPDF_WIDESTRING)bs.GetBuffer(len)); @@ -997,35 +986,34 @@ bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc, return true; } -bool CPDFXFA_DocEnvironment::SetGlobalProperty( - CXFA_FFDoc* hDoc, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue) { +bool CPDFXFA_DocEnvironment::SetGlobalProperty(CXFA_FFDoc* hDoc, + const ByteStringView& szPropName, + CFXJSE_Value* pValue) { if (hDoc != m_pContext->GetXFADoc()) return false; - - if (m_pContext->GetFormFillEnv() && - m_pContext->GetFormFillEnv()->GetJSRuntime()) { - return m_pContext->GetFormFillEnv()->GetJSRuntime()->SetValueByName( - szPropName, pValue); + if (!m_pContext->GetFormFillEnv() || + !m_pContext->GetFormFillEnv()->GetJSRuntime()) { + return false; } - return false; + CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); + IJS_EventContext* pContext = pFormFillEnv->GetJSRuntime()->NewEventContext(); + bool bRet = pFormFillEnv->GetJSRuntime()->SetValueByName(szPropName, pValue); + pFormFillEnv->GetJSRuntime()->ReleaseEventContext(pContext); + return bRet; } -bool CPDFXFA_DocEnvironment::GetGlobalProperty( - CXFA_FFDoc* hDoc, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue) { +bool CPDFXFA_DocEnvironment::GetGlobalProperty(CXFA_FFDoc* hDoc, + const ByteStringView& szPropName, + CFXJSE_Value* pValue) { if (hDoc != m_pContext->GetXFADoc()) return false; if (!m_pContext->GetFormFillEnv() || !m_pContext->GetFormFillEnv()->GetJSRuntime()) { return false; } - CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv(); - if (!m_pJSEventContext) - m_pJSEventContext = pFormFillEnv->GetJSRuntime()->NewEventContext(); - - return pFormFillEnv->GetJSRuntime()->GetValueByName(szPropName, pValue); + IJS_EventContext* pContext = pFormFillEnv->GetJSRuntime()->NewEventContext(); + bool bRet = pFormFillEnv->GetJSRuntime()->GetValueByName(szPropName, pValue); + pFormFillEnv->GetJSRuntime()->ReleaseEventContext(pContext); + return bRet; } diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h index dc18d9a0c6193c41eaca38ca0fe1177486d8186a..9eabf8d6553f808718590a5043d48e15d860dec6 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h +++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h @@ -7,7 +7,8 @@ #ifndef FPDFSDK_FPDFXFA_CPDFXFA_DOCENVIRONMENT_H_ #define FPDFSDK_FPDFXFA_CPDFXFA_DOCENVIRONMENT_H_ -#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" #include "public/fpdfview.h" #include "xfa/fxfa/fxfa.h" @@ -21,18 +22,16 @@ class CPDFXFA_DocEnvironment : public IXFA_DocEnvironment { // IXFA_DocEnvironment void SetChangeMark(CXFA_FFDoc* hDoc) override; - // used in dynamic xfa, dwFlags refer to XFA_INVALIDATE_XXX macros. - void InvalidateRect(CXFA_FFPageView* pPageView, - const CFX_RectF& rt, - uint32_t dwFlags) override; - // show or hide caret + // Used in dynamic xfa. + void InvalidateRect(CXFA_FFPageView* pPageView, const CFX_RectF& rt) override; + // Show or hide caret. void DisplayCaret(CXFA_FFWidget* hWidget, bool bVisible, const CFX_RectF* pRtAnchor) override; // dwPos: (0:bottom 1:top) bool GetPopupPos(CXFA_FFWidget* hWidget, - FX_FLOAT fMinPopup, - FX_FLOAT fMaxPopup, + float fMinPopup, + float fMaxPopup, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) override; bool PopupMenu(CXFA_FFWidget* hWidget, CFX_PointF ptPopup) override; @@ -40,9 +39,9 @@ class CPDFXFA_DocEnvironment : public IXFA_DocEnvironment { // dwFlags XFA_PAGEVIEWEVENT_Added, XFA_PAGEVIEWEVENT_Removing void PageViewEvent(CXFA_FFPageView* pPageView, uint32_t dwFlags) override; void WidgetPostAdd(CXFA_FFWidget* hWidget, - CXFA_WidgetAcc* pWidgetData) override; + CXFA_WidgetAcc* pWidgetAcc) override; void WidgetPreRemove(CXFA_FFWidget* hWidget, - CXFA_WidgetAcc* pWidgetData) override; + CXFA_WidgetAcc* pWidgetAcc) override; // Host method int32_t CountPages(CXFA_FFDoc* hDoc) override; @@ -50,12 +49,12 @@ class CPDFXFA_DocEnvironment : public IXFA_DocEnvironment { void SetCurrentPage(CXFA_FFDoc* hDoc, int32_t iCurPage) override; bool IsCalculationsEnabled(CXFA_FFDoc* hDoc) override; void SetCalculationsEnabled(CXFA_FFDoc* hDoc, bool bEnabled) override; - void GetTitle(CXFA_FFDoc* hDoc, CFX_WideString& wsTitle) override; - void SetTitle(CXFA_FFDoc* hDoc, const CFX_WideString& wsTitle) override; + void GetTitle(CXFA_FFDoc* hDoc, WideString& wsTitle) override; + void SetTitle(CXFA_FFDoc* hDoc, const WideString& wsTitle) override; void ExportData(CXFA_FFDoc* hDoc, - const CFX_WideString& wsFilePath, + const WideString& wsFilePath, bool bXDP) override; - void GotoURL(CXFA_FFDoc* hDoc, const CFX_WideString& bsURL) override; + void GotoURL(CXFA_FFDoc* hDoc, const WideString& bsURL) override; bool IsValidationsEnabled(CXFA_FFDoc* hDoc) override; void SetValidationsEnabled(CXFA_FFDoc* hDoc, bool bEnabled) override; void SetFocusWidget(CXFA_FFDoc* hDoc, CXFA_FFWidget* hWidget) override; @@ -65,50 +64,37 @@ class CPDFXFA_DocEnvironment : public IXFA_DocEnvironment { uint32_t dwOptions) override; FX_ARGB GetHighlightColor(CXFA_FFDoc* hDoc) override; - /** - *Submit data to email, http, ftp. - * @param[in] hDoc The document handler. - * @param[in] eFormat Determines the format in which the data will be - *submitted. XFA_ATTRIBUTEENUM_Xdp, XFA_ATTRIBUTEENUM_Xml... - * @param[in] wsTarget The URL to which the data will be submitted. - * @param[in] eEncoding The encoding of text content. - * @param[in] pXDPContent Controls what subset of the data is submitted, used - *only when the format property is xdp. - * @param[in] bEmbedPDF, specifies whether PDF is embedded in the submitted - *content or not. - */ - bool SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) override; + bool Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) override; bool GetGlobalProperty(CXFA_FFDoc* hDoc, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue) override; bool SetGlobalProperty(CXFA_FFDoc* hDoc, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue) override; - CFX_RetainPtr OpenLinkedFile( + RetainPtr OpenLinkedFile( CXFA_FFDoc* hDoc, - const CFX_WideString& wsLink) override; + const WideString& wsLink) override; private: bool OnBeforeNotifySubmit(); void OnAfterNotifySubmit(); bool NotifySubmit(bool bPrevOrPost); - bool SubmitDataInternal(CXFA_FFDoc* hDoc, CXFA_Submit submit); - bool MailToInfo(CFX_WideString& csURL, - CFX_WideString& csToAddress, - CFX_WideString& csCCAddress, - CFX_WideString& csBCCAddress, - CFX_WideString& csSubject, - CFX_WideString& csMsg); + bool SubmitInternal(CXFA_FFDoc* hDoc, CXFA_Submit* submit); + bool MailToInfo(WideString& csURL, + WideString& csToAddress, + WideString& csCCAddress, + WideString& csBCCAddress, + WideString& csSubject, + WideString& csMsg); bool ExportSubmitFile(FPDF_FILEHANDLER* ppFileHandler, int fileType, FPDF_DWORD encodeType, FPDF_DWORD flag); - void ToXFAContentFlags(CFX_WideString csSrcContent, FPDF_DWORD& flag); + void ToXFAContentFlags(WideString csSrcContent, FPDF_DWORD& flag); - CPDFXFA_Context* const m_pContext; // Not owned. - IJS_EventContext* m_pJSEventContext; // Not owned. + UnownedPtr const m_pContext; }; #endif // FPDFSDK_FPDFXFA_CPDFXFA_DOCENVIRONMENT_H_ diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp index 8b5bb3d2791cabceb26d3983960d03e4c42396ae..fbea90d9a9f48fd2d38c8e5010d6e2ebdb09af0c 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp +++ b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp @@ -13,19 +13,13 @@ #include "fpdfsdk/fsdk_define.h" #include "public/fpdf_formfill.h" #include "third_party/base/ptr_util.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" CPDFXFA_Page::CPDFXFA_Page(CPDFXFA_Context* pContext, int page_index) - : m_pXFAPageView(nullptr), - m_pContext(pContext), - m_iPageIndex(page_index), - m_iRef(1) {} - -CPDFXFA_Page::~CPDFXFA_Page() { - if (m_pContext) - m_pContext->RemovePage(this); -} + : m_pXFAPageView(nullptr), m_pContext(pContext), m_iPageIndex(page_index) {} + +CPDFXFA_Page::~CPDFXFA_Page() {} bool CPDFXFA_Page::LoadPDFPage() { if (!m_pContext) @@ -70,18 +64,15 @@ bool CPDFXFA_Page::LoadPage() { if (!m_pContext || m_iPageIndex < 0) return false; - int iDocType = m_pContext->GetDocType(); - switch (iDocType) { - case DOCTYPE_PDF: - case DOCTYPE_STATIC_XFA: { + switch (m_pContext->GetFormType()) { + case FormType::kNone: + case FormType::kAcroForm: + case FormType::kXFAForeground: return LoadPDFPage(); - } - case DOCTYPE_DYNAMIC_XFA: { + case FormType::kXFAFull: return LoadXFAPageView(); - } - default: - return false; } + return false; } bool CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) { @@ -94,49 +85,37 @@ bool CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) { return true; } -FX_FLOAT CPDFXFA_Page::GetPageWidth() const { +float CPDFXFA_Page::GetPageWidth() const { if (!m_pPDFPage && !m_pXFAPageView) return 0.0f; - int nDocType = m_pContext->GetDocType(); - switch (nDocType) { - case DOCTYPE_DYNAMIC_XFA: { - if (m_pXFAPageView) - return m_pXFAPageView->GetPageViewRect().width; - break; - } - case DOCTYPE_STATIC_XFA: - case DOCTYPE_PDF: { + switch (m_pContext->GetFormType()) { + case FormType::kNone: + case FormType::kAcroForm: + case FormType::kXFAForeground: if (m_pPDFPage) return m_pPDFPage->GetPageWidth(); - break; - } - default: - return 0.0f; + case FormType::kXFAFull: + if (m_pXFAPageView) + return m_pXFAPageView->GetPageViewRect().width; } return 0.0f; } -FX_FLOAT CPDFXFA_Page::GetPageHeight() const { +float CPDFXFA_Page::GetPageHeight() const { if (!m_pPDFPage && !m_pXFAPageView) return 0.0f; - int nDocType = m_pContext->GetDocType(); - switch (nDocType) { - case DOCTYPE_PDF: - case DOCTYPE_STATIC_XFA: { + switch (m_pContext->GetFormType()) { + case FormType::kNone: + case FormType::kAcroForm: + case FormType::kXFAForeground: if (m_pPDFPage) return m_pPDFPage->GetPageHeight(); - break; - } - case DOCTYPE_DYNAMIC_XFA: { + case FormType::kXFAFull: if (m_pXFAPageView) return m_pXFAPageView->GetPageViewRect().height; - break; - } - default: - return 0.0f; } return 0.0f; @@ -154,12 +133,10 @@ void CPDFXFA_Page::DeviceToPage(int start_x, if (!m_pPDFPage && !m_pXFAPageView) return; - CFX_Matrix device2page; - device2page.SetReverse( - GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate)); - - CFX_PointF pos = device2page.Transform(CFX_PointF( - static_cast(device_x), static_cast(device_y))); + CFX_PointF pos = GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate) + .GetInverse() + .Transform(CFX_PointF(static_cast(device_x), + static_cast(device_y))); *page_x = pos.x; *page_y = pos.y; @@ -181,7 +158,7 @@ void CPDFXFA_Page::PageToDevice(int start_x, GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate); CFX_PointF pos = page2device.Transform( - CFX_PointF(static_cast(page_x), static_cast(page_y))); + CFX_PointF(static_cast(page_x), static_cast(page_y))); *device_x = FXSYS_round(pos.x); *device_y = FXSYS_round(pos.y); @@ -195,23 +172,17 @@ CFX_Matrix CPDFXFA_Page::GetDisplayMatrix(int xPos, if (!m_pPDFPage && !m_pXFAPageView) return CFX_Matrix(); - int nDocType = m_pContext->GetDocType(); - switch (nDocType) { - case DOCTYPE_DYNAMIC_XFA: { - if (m_pXFAPageView) { - return m_pXFAPageView->GetDisplayMatrix( - CFX_Rect(xPos, yPos, xSize, ySize), iRotate); - } - break; - } - case DOCTYPE_PDF: - case DOCTYPE_STATIC_XFA: { + switch (m_pContext->GetFormType()) { + case FormType::kNone: + case FormType::kAcroForm: + case FormType::kXFAForeground: if (m_pPDFPage) return m_pPDFPage->GetDisplayMatrix(xPos, yPos, xSize, ySize, iRotate); - break; - } - default: - return CFX_Matrix(); + case FormType::kXFAFull: + if (m_pXFAPageView) + return m_pXFAPageView->GetDisplayMatrix( + CFX_Rect(xPos, yPos, xSize, ySize), iRotate); } + return CFX_Matrix(); } diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_page.h b/fpdfsdk/fpdfxfa/cpdfxfa_page.h index 993885d59e923d0f2e61a21c111105d1ffa21445..f64d66b10c87ff6fc79e0dc97c387db1c3970b0a 100644 --- a/fpdfsdk/fpdfxfa/cpdfxfa_page.h +++ b/fpdfsdk/fpdfxfa/cpdfxfa_page.h @@ -10,6 +10,8 @@ #include #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CFX_Matrix; class CPDFXFA_Context; @@ -17,19 +19,14 @@ class CPDF_Dictionary; class CPDF_Page; class CXFA_FFPageView; -class CPDFXFA_Page { +class CPDFXFA_Page : public Retainable { public: - CPDFXFA_Page(CPDFXFA_Context* pContext, int page_index); - - void Retain() { m_iRef++; } - void Release() { - if (--m_iRef <= 0) - delete this; - } + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); bool LoadPage(); bool LoadPDFPage(CPDF_Dictionary* pageDict); - CPDFXFA_Context* GetContext() const { return m_pContext; } + CPDFXFA_Context* GetContext() const { return m_pContext.Get(); } int GetPageIndex() const { return m_iPageIndex; } CPDF_Page* GetPDFPage() const { return m_pPDFPage.get(); } CXFA_FFPageView* GetXFAPageView() const { return m_pXFAPageView; } @@ -38,8 +35,8 @@ class CPDFXFA_Page { m_pXFAPageView = pPageView; } - FX_FLOAT GetPageWidth() const; - FX_FLOAT GetPageHeight() const; + float GetPageWidth() const; + float GetPageHeight() const; void DeviceToPage(int start_x, int start_y, @@ -68,7 +65,8 @@ class CPDFXFA_Page { protected: // Refcounted class. - ~CPDFXFA_Page(); + CPDFXFA_Page(CPDFXFA_Context* pContext, int page_index); + ~CPDFXFA_Page() override; bool LoadPDFPage(); bool LoadXFAPageView(); @@ -76,9 +74,8 @@ class CPDFXFA_Page { private: std::unique_ptr m_pPDFPage; CXFA_FFPageView* m_pXFAPageView; - CPDFXFA_Context* const m_pContext; + UnownedPtr const m_pContext; const int m_iPageIndex; - int m_iRef; }; #endif // FPDFSDK_FPDFXFA_CPDFXFA_PAGE_H_ diff --git a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp index 39aa72be87069c96c65689de120f0c85093e1ca5..c7201c3fbd86dc61a9cf456f9b616aeedb060a9a 100644 --- a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp +++ b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp @@ -29,6 +29,12 @@ class CFWL_FWLAdapterTimerInfo : public CFWL_TimerInfo { std::vector* CXFA_FWLAdapterTimerMgr::s_TimerArray = nullptr; +CXFA_FWLAdapterTimerMgr::CXFA_FWLAdapterTimerMgr( + CPDFSDK_FormFillEnvironment* pFormFillEnv) + : m_pFormFillEnv(pFormFillEnv) {} + +CXFA_FWLAdapterTimerMgr::~CXFA_FWLAdapterTimerMgr() {} + void CXFA_FWLAdapterTimerMgr::Start(CFWL_Timer* pTimer, uint32_t dwElapse, bool bImmediately, @@ -66,7 +72,7 @@ void CXFA_FWLAdapterTimerMgr::TimerProc(int32_t idEvent) { if (!s_TimerArray) return; - for (const auto info : *s_TimerArray) { + for (auto* info : *s_TimerArray) { CFWL_FWLAdapterTimerInfo* pInfo = static_cast(info); if (pInfo->idEvent == idEvent) { diff --git a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h index fdb5635ff0a6eda0a837580670570fe5022ddbcc..d763f025ffe7ed42ffac0c0c7089e96befd44719 100644 --- a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h +++ b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h @@ -10,14 +10,15 @@ #include #include +#include "core/fxcrt/unowned_ptr.h" #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" #include "xfa/fwl/cfwl_timerinfo.h" #include "xfa/fwl/ifwl_adaptertimermgr.h" class CXFA_FWLAdapterTimerMgr : public IFWL_AdapterTimerMgr { public: - explicit CXFA_FWLAdapterTimerMgr(CPDFSDK_FormFillEnvironment* pFormFillEnv) - : m_pFormFillEnv(pFormFillEnv) {} + explicit CXFA_FWLAdapterTimerMgr(CPDFSDK_FormFillEnvironment* pFormFillEnv); + ~CXFA_FWLAdapterTimerMgr(); void Start(CFWL_Timer* pTimer, uint32_t dwElapse, @@ -29,7 +30,7 @@ class CXFA_FWLAdapterTimerMgr : public IFWL_AdapterTimerMgr { static void TimerProc(int32_t idEvent); static std::vector* s_TimerArray; - CPDFSDK_FormFillEnvironment* const m_pFormFillEnv; + UnownedPtr const m_pFormFillEnv; }; #endif // FPDFSDK_FPDFXFA_CXFA_FWLADAPTERTIMERMGR_H_ diff --git a/fpdfsdk/fsdk_actionhandler.cpp b/fpdfsdk/fsdk_actionhandler.cpp index dc99f32f3437f6f612aae731de7dd1e021cf58c8..de5c9313b53bb4fba6f32efb8303c3c86fb97082 100644 --- a/fpdfsdk/fsdk_actionhandler.cpp +++ b/fpdfsdk/fsdk_actionhandler.cpp @@ -7,6 +7,7 @@ #include "fpdfsdk/fsdk_actionhandler.h" #include +#include #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfdoc/cpdf_formfield.h" @@ -14,8 +15,9 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_interform.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/javascript/ijs_event_context.h" -#include "fpdfsdk/javascript/ijs_runtime.h" +#include "fxjs/ijs_event_context.h" +#include "fxjs/ijs_runtime.h" +#include "third_party/base/logging.h" #include "third_party/base/stl_util.h" bool CPDFSDK_ActionHandler::DoAction_DocOpen( @@ -27,10 +29,10 @@ bool CPDFSDK_ActionHandler::DoAction_DocOpen( bool CPDFSDK_ActionHandler::DoAction_JavaScript( const CPDF_Action& JsAction, - CFX_WideString csJSName, + WideString csJSName, CPDFSDK_FormFillEnvironment* pFormFillEnv) { if (JsAction.GetType() == CPDF_Action::JavaScript) { - CFX_WideString swJS = JsAction.GetJavaScript(); + WideString swJS = JsAction.GetJavaScript(); if (!swJS.IsEmpty()) { RunDocumentOpenJavaScript(pFormFillEnv, csJSName, swJS); return true; @@ -49,7 +51,7 @@ bool CPDFSDK_ActionHandler::DoAction_FieldJavaScript( ASSERT(pFormFillEnv); if (pFormFillEnv->IsJSInitiated() && JsAction.GetType() == CPDF_Action::JavaScript) { - CFX_WideString swJS = JsAction.GetJavaScript(); + WideString swJS = JsAction.GetJavaScript(); if (!swJS.IsEmpty()) { RunFieldJavaScript(pFormFillEnv, pFormField, type, data, swJS); return true; @@ -123,7 +125,7 @@ bool CPDFSDK_ActionHandler::ExecuteDocumentOpenAction( ASSERT(pFormFillEnv); if (action.GetType() == CPDF_Action::JavaScript) { if (pFormFillEnv->IsJSInitiated()) { - CFX_WideString swJS = action.GetJavaScript(); + WideString swJS = action.GetJavaScript(); if (!swJS.IsEmpty()) { RunDocumentOpenJavaScript(pFormFillEnv, L"", swJS); } @@ -154,13 +156,13 @@ bool CPDFSDK_ActionHandler::ExecuteLinkAction( ASSERT(pFormFillEnv); if (action.GetType() == CPDF_Action::JavaScript) { if (pFormFillEnv->IsJSInitiated()) { - CFX_WideString swJS = action.GetJavaScript(); + WideString swJS = action.GetJavaScript(); if (!swJS.IsEmpty()) { IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime(); IJS_EventContext* pContext = pRuntime->NewEventContext(); pContext->OnLink_MouseUp(pFormFillEnv); - CFX_WideString csInfo; + WideString csInfo; bool bRet = pContext->RunScript(swJS, &csInfo); pRuntime->ReleaseEventContext(pContext); if (!bRet) { @@ -195,7 +197,7 @@ bool CPDFSDK_ActionHandler::ExecuteDocumentPageAction( ASSERT(pFormFillEnv); if (action.GetType() == CPDF_Action::JavaScript) { if (pFormFillEnv->IsJSInitiated()) { - CFX_WideString swJS = action.GetJavaScript(); + WideString swJS = action.GetJavaScript(); if (!swJS.IsEmpty()) { RunDocumentPageJavaScript(pFormFillEnv, type, swJS); } @@ -242,7 +244,7 @@ bool CPDFSDK_ActionHandler::ExecuteFieldAction( ASSERT(pFormFillEnv); if (action.GetType() == CPDF_Action::JavaScript) { if (pFormFillEnv->IsJSInitiated()) { - CFX_WideString swJS = action.GetJavaScript(); + WideString swJS = action.GetJavaScript(); if (!swJS.IsEmpty()) { RunFieldJavaScript(pFormFillEnv, pFormField, type, data, swJS); if (!IsValidField(pFormFillEnv, pFormField->GetFieldDict())) @@ -278,11 +280,11 @@ bool CPDFSDK_ActionHandler::ExecuteScreenAction( ASSERT(pFormFillEnv); if (action.GetType() == CPDF_Action::JavaScript) { if (pFormFillEnv->IsJSInitiated()) { - CFX_WideString swJS = action.GetJavaScript(); + WideString swJS = action.GetJavaScript(); if (!swJS.IsEmpty()) { IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime(); IJS_EventContext* pContext = pRuntime->NewEventContext(); - CFX_WideString csInfo; + WideString csInfo; bool bRet = pContext->RunScript(swJS, &csInfo); pRuntime->ReleaseEventContext(pContext); if (!bRet) { @@ -317,13 +319,13 @@ bool CPDFSDK_ActionHandler::ExecuteBookMark( ASSERT(pFormFillEnv); if (action.GetType() == CPDF_Action::JavaScript) { if (pFormFillEnv->IsJSInitiated()) { - CFX_WideString swJS = action.GetJavaScript(); + WideString swJS = action.GetJavaScript(); if (!swJS.IsEmpty()) { IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime(); IJS_EventContext* pContext = pRuntime->NewEventContext(); pContext->OnBookmark_MouseUp(pBookmark); - CFX_WideString csInfo; + WideString csInfo; bool bRet = pContext->RunScript(swJS, &csInfo); pRuntime->ReleaseEventContext(pContext); if (!bRet) { @@ -386,7 +388,7 @@ void CPDFSDK_ActionHandler::DoAction_NoJs( DoAction_ImportData(action, pFormFillEnv); break; case CPDF_Action::JavaScript: - ASSERT(false); + NOTREACHED(); break; case CPDF_Action::SetOCGState: DoAction_SetOCGState(pFormFillEnv, action); @@ -420,19 +422,13 @@ void CPDFSDK_ActionHandler::DoAction_GoTo( int nPageIndex = MyDest.GetPageIndex(pPDFDocument); int nFitType = MyDest.GetZoomMode(); const CPDF_Array* pMyArray = ToArray(MyDest.GetObject()); - float* pPosAry = nullptr; - int sizeOfAry = 0; + std::vector posArray; if (pMyArray) { - pPosAry = new float[pMyArray->GetCount()]; - int j = 0; - for (size_t i = 2; i < pMyArray->GetCount(); i++) { - pPosAry[j++] = pMyArray->GetFloatAt(i); - } - sizeOfAry = j; + for (size_t i = 2; i < pMyArray->GetCount(); i++) + posArray.push_back(pMyArray->GetFloatAt(i)); } - - pFormFillEnv->DoGoToAction(nPageIndex, nFitType, pPosAry, sizeOfAry); - delete[] pPosAry; + pFormFillEnv->DoGoToAction(nPageIndex, nFitType, posArray.data(), + posArray.size()); } void CPDFSDK_ActionHandler::DoAction_GoToR( @@ -448,7 +444,7 @@ void CPDFSDK_ActionHandler::DoAction_URI( const CPDF_Action& action) { ASSERT(action.GetDict()); - CFX_ByteString sURI = action.GetURI(pFormFillEnv->GetPDFDocument()); + ByteString sURI = action.GetURI(pFormFillEnv->GetPDFDocument()); pFormFillEnv->DoURIAction(sURI.c_str()); } @@ -457,7 +453,7 @@ void CPDFSDK_ActionHandler::DoAction_Named( const CPDF_Action& action) { ASSERT(action.GetDict()); - CFX_ByteString csName = action.GetNamedAction(); + ByteString csName = action.GetNamedAction(); pFormFillEnv->ExecuteNamedAction(csName.c_str()); } @@ -470,7 +466,7 @@ void CPDFSDK_ActionHandler::RunFieldJavaScript( CPDF_FormField* pFormField, CPDF_AAction::AActionType type, PDFSDK_FieldAction& data, - const CFX_WideString& script) { + const WideString& script) { ASSERT(type != CPDF_AAction::Calculate); ASSERT(type != CPDF_AAction::Format); @@ -509,11 +505,11 @@ void CPDFSDK_ActionHandler::RunFieldJavaScript( data.sValue, data.bRC); break; default: - ASSERT(false); + NOTREACHED(); break; } - CFX_WideString csInfo; + WideString csInfo; bool bRet = pContext->RunScript(script, &csInfo); pRuntime->ReleaseEventContext(pContext); if (!bRet) { @@ -523,13 +519,13 @@ void CPDFSDK_ActionHandler::RunFieldJavaScript( void CPDFSDK_ActionHandler::RunDocumentOpenJavaScript( CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& sScriptName, - const CFX_WideString& script) { + const WideString& sScriptName, + const WideString& script) { IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime(); IJS_EventContext* pContext = pRuntime->NewEventContext(); pContext->OnDoc_Open(pFormFillEnv, sScriptName); - CFX_WideString csInfo; + WideString csInfo; bool bRet = pContext->RunScript(script, &csInfo); pRuntime->ReleaseEventContext(pContext); if (!bRet) { @@ -540,7 +536,7 @@ void CPDFSDK_ActionHandler::RunDocumentOpenJavaScript( void CPDFSDK_ActionHandler::RunDocumentPageJavaScript( CPDFSDK_FormFillEnvironment* pFormFillEnv, CPDF_AAction::AActionType type, - const CFX_WideString& script) { + const WideString& script) { IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime(); IJS_EventContext* pContext = pRuntime->NewEventContext(); switch (type) { @@ -572,11 +568,11 @@ void CPDFSDK_ActionHandler::RunDocumentPageJavaScript( pContext->OnPage_OutView(pFormFillEnv); break; default: - ASSERT(false); + NOTREACHED(); break; } - CFX_WideString csInfo; + WideString csInfo; bool bRet = pContext->RunScript(script, &csInfo); pRuntime->ReleaseEventContext(pContext); if (!bRet) { diff --git a/fpdfsdk/fsdk_actionhandler.h b/fpdfsdk/fsdk_actionhandler.h index 1c8dedefd70f4807e8a6b7a6744087d59e85164a..7457b4ed91690f50716f88d2289333dbd410db30 100644 --- a/fpdfsdk/fsdk_actionhandler.h +++ b/fpdfsdk/fsdk_actionhandler.h @@ -26,7 +26,7 @@ class CPDFSDK_ActionHandler { bool DoAction_DocOpen(const CPDF_Action& action, CPDFSDK_FormFillEnvironment* pFormFillEnv); bool DoAction_JavaScript(const CPDF_Action& JsAction, - CFX_WideString csJSName, + WideString csJSName, CPDFSDK_FormFillEnvironment* pFormFillEnv); bool DoAction_Page(const CPDF_Action& action, enum CPDF_AAction::AActionType eType, @@ -86,15 +86,15 @@ class CPDFSDK_ActionHandler { CPDFSDK_FormFillEnvironment* pFormFillEnv); void RunDocumentPageJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv, CPDF_AAction::AActionType type, - const CFX_WideString& script); + const WideString& script); void RunDocumentOpenJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& sScriptName, - const CFX_WideString& script); + const WideString& sScriptName, + const WideString& script); void RunFieldJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv, CPDF_FormField* pFormField, CPDF_AAction::AActionType type, PDFSDK_FieldAction& data, - const CFX_WideString& script); + const WideString& script); bool IsValidField(CPDFSDK_FormFillEnvironment* pFormFillEnv, CPDF_Dictionary* pFieldDict); diff --git a/fpdfsdk/fsdk_common.h b/fpdfsdk/fsdk_common.h index d8030261c71ffc3332f0a58ad210344521dcb4a9..78ecd98b4ab2cc104c9a2d3a80a25690304aabaa 100644 --- a/fpdfsdk/fsdk_common.h +++ b/fpdfsdk/fsdk_common.h @@ -10,7 +10,6 @@ // for all fields #define FIELDFLAG_READONLY 1 #define FIELDFLAG_REQUIRED 2 -#define FIELDFLAG_NOEXPORT 4 // for text fields #define FIELDFLAG_MULTILINE (1 << 12) #define FIELDFLAG_PASSWORD (1 << 13) @@ -20,14 +19,9 @@ #define FIELDFLAG_COMB (1 << 24) #define FIELDFLAG_RICHTEXT (1 << 25) // for button fileds -#define FIELDFLAG_NOTOGGLETOOFF (1 << 14) -#define FIELDFLAG_RADIO (1 << 15) -#define FIELDFLAG_PUSHBUTTON (1 << 16) #define FIELDFLAG_RADIOSINUNISON (1 << 27) // for choice fields -#define FIELDFLAG_COMBO (1 << 17) #define FIELDFLAG_EDIT (1 << 18) -#define FIELDFLAG_SORT (1 << 19) #define FIELDFLAG_MULTISELECT (1 << 21) #define FIELDFLAG_COMMITONSELCHANGE (1 << 26) diff --git a/fpdfsdk/fsdk_define.h b/fpdfsdk/fsdk_define.h index 9a115966dbb789151bc8b0e53719169adcd709ae..77c2315eddafa4a2665b4444d47b74cfb8bb14b1 100644 --- a/fpdfsdk/fsdk_define.h +++ b/fpdfsdk/fsdk_define.h @@ -8,6 +8,7 @@ #define FPDFSDK_FSDK_DEFINE_H_ #include "core/fpdfapi/parser/cpdf_parser.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" #include "public/fpdfview.h" @@ -22,18 +23,22 @@ class CPDF_Annot; class CPDF_Page; +class CPDF_PageObject; class CPDF_PageRenderContext; +class CPDF_PathObject; +class CPDF_Stream; class IFSDK_PAUSE_Adapter; +class FX_PATHPOINT; // Layering prevents fxcrt from knowing about FPDF_FILEACCESS, so this can't // be a static method of IFX_SeekableReadStream. -CFX_RetainPtr MakeSeekableReadStream( +RetainPtr MakeSeekableReadStream( FPDF_FILEACCESS* pFileAccess); #ifdef PDF_ENABLE_XFA // Layering prevents fxcrt from knowing about FPDF_FILEHANDLER, so this can't // be a static method of IFX_SeekableStream. -CFX_RetainPtr MakeSeekableStream( +RetainPtr MakeSeekableStream( FPDF_FILEHANDLER* pFileHandler); #endif // PDF_ENABLE_XFA @@ -60,8 +65,29 @@ FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc); CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page); +CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object); + +CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object); + +CPDF_Object* CPDFObjectFromFPDFAttachment(FPDF_ATTACHMENT attachment); + +ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string); + CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap); +CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect); +void FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect, FS_RECTF* out_rect); + +const FX_PATHPOINT* FXPathPointFromFPDFPathSegment(FPDF_PATHSEGMENT segment); + +unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text, + void* buffer, + unsigned long buflen); + +unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream, + void* buffer, + unsigned long buflen); + void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable); FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy); void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext, @@ -78,5 +104,10 @@ void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext, void CheckUnSupportError(CPDF_Document* pDoc, uint32_t err_code); void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot); void ProcessParseError(CPDF_Parser::Error err); +FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); #endif // FPDFSDK_FSDK_DEFINE_H_ diff --git a/fpdfsdk/fsdk_filewriteadapter.cpp b/fpdfsdk/fsdk_filewriteadapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fad058fb548f80f9e25fc1b8dcf50dea34cf135b --- /dev/null +++ b/fpdfsdk/fsdk_filewriteadapter.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/fsdk_filewriteadapter.h" + +FSDK_FileWriteAdapter::FSDK_FileWriteAdapter(FPDF_FILEWRITE* fileWriteStruct) + : fileWriteStruct_(fileWriteStruct) { + ASSERT(fileWriteStruct_); +} + +FSDK_FileWriteAdapter::~FSDK_FileWriteAdapter() {} + +bool FSDK_FileWriteAdapter::WriteBlock(const void* data, size_t size) { + return fileWriteStruct_->WriteBlock(fileWriteStruct_, data, size) != 0; +} + +bool FSDK_FileWriteAdapter::WriteString(const ByteStringView& str) { + return WriteBlock(str.unterminated_c_str(), str.GetLength()); +} diff --git a/fpdfsdk/fsdk_filewriteadapter.h b/fpdfsdk/fsdk_filewriteadapter.h new file mode 100644 index 0000000000000000000000000000000000000000..6bba1da9a7cbb89d459ff7008a00a290c0818729 --- /dev/null +++ b/fpdfsdk/fsdk_filewriteadapter.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_FSDK_FILEWRITEADAPTER_H_ +#define FPDFSDK_FSDK_FILEWRITEADAPTER_H_ + +#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/retain_ptr.h" +#include "public/fpdf_save.h" + +class FSDK_FileWriteAdapter : public IFX_WriteStream { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + bool WriteBlock(const void* data, size_t size) override; + bool WriteString(const ByteStringView& str) override; + + private: + explicit FSDK_FileWriteAdapter(FPDF_FILEWRITE* fileWriteStruct); + ~FSDK_FileWriteAdapter() override; + + FPDF_FILEWRITE* fileWriteStruct_; +}; + +#endif // FPDFSDK_FSDK_FILEWRITEADAPTER_H_ diff --git a/fpdfsdk/fsdk_pauseadapter.cpp b/fpdfsdk/fsdk_pauseadapter.cpp index 237266b88bec5cd0dd67be9107d8a3ec7d54ddd7..cf99253ff9e5f87c0736e940c3e94da0146d70b4 100644 --- a/fpdfsdk/fsdk_pauseadapter.cpp +++ b/fpdfsdk/fsdk_pauseadapter.cpp @@ -12,5 +12,5 @@ IFSDK_PAUSE_Adapter::IFSDK_PAUSE_Adapter(IFSDK_PAUSE* IPause) IFSDK_PAUSE_Adapter::~IFSDK_PAUSE_Adapter() {} bool IFSDK_PAUSE_Adapter::NeedToPauseNow() { - return m_IPause->NeedToPauseNow && m_IPause->NeedToPauseNow(m_IPause); + return m_IPause->NeedToPauseNow && m_IPause->NeedToPauseNow(m_IPause.Get()); } diff --git a/fpdfsdk/fsdk_pauseadapter.h b/fpdfsdk/fsdk_pauseadapter.h index bd302f2613653ee09ac82eb77a7b4f255191eb5b..a0d009874ed3a0ca956e10d9d4f5696206d43931 100644 --- a/fpdfsdk/fsdk_pauseadapter.h +++ b/fpdfsdk/fsdk_pauseadapter.h @@ -7,11 +7,12 @@ #ifndef FPDFSDK_FSDK_PAUSEADAPTER_H_ #define FPDFSDK_FSDK_PAUSEADAPTER_H_ -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/ifx_pauseindicator.h" +#include "core/fxcrt/unowned_ptr.h" #include "public/fpdf_progressive.h" -class IFSDK_PAUSE_Adapter : public IFX_Pause { +class IFSDK_PAUSE_Adapter : public IFX_PauseIndicator { public: explicit IFSDK_PAUSE_Adapter(IFSDK_PAUSE* IPause); ~IFSDK_PAUSE_Adapter() override; @@ -19,7 +20,7 @@ class IFSDK_PAUSE_Adapter : public IFX_Pause { bool NeedToPauseNow() override; private: - IFSDK_PAUSE* const m_IPause; + UnownedPtr const m_IPause; }; #endif // FPDFSDK_FSDK_PAUSEADAPTER_H_ diff --git a/fpdfsdk/fxedit/fx_edit.h b/fpdfsdk/fxedit/fx_edit.h deleted file mode 100644 index 6c9166709c9055cda8e21b5d673920a0efb15f69..0000000000000000000000000000000000000000 --- a/fpdfsdk/fxedit/fx_edit.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_FXEDIT_FX_EDIT_H_ -#define FPDFSDK_FXEDIT_FX_EDIT_H_ - -#include "core/fxcrt/fx_basic.h" - -class IPVT_FontMap; - -#define FX_EDIT_ISLATINWORD(u) \ - (u == 0x2D || (u <= 0x005A && u >= 0x0041) || \ - (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0)) - -CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord); - -#endif // FPDFSDK_FXEDIT_FX_EDIT_H_ diff --git a/fpdfsdk/fxedit/fxet_ap.cpp b/fpdfsdk/fxedit/fxet_ap.cpp deleted file mode 100644 index 448a539581c235e86666de55854a26bda54a7468..0000000000000000000000000000000000000000 --- a/fpdfsdk/fxedit/fxet_ap.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fpdfdoc/ipvt_fontmap.h" -#include "fpdfsdk/fxedit/fx_edit.h" -#include "fpdfsdk/fxedit/fxet_edit.h" - -CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord) { - CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex); - if (!pPDFFont) - return CFX_ByteString(); - - CFX_ByteString sWord; - if (SubWord > 0) { - Word = SubWord; - } else { - uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible() - ? pPDFFont->CharCodeFromUnicode(Word) - : pFontMap->CharCodeFromUnicode(nFontIndex, Word); - - if (dwCharCode > 0) { - pPDFFont->AppendChar(sWord, dwCharCode); - return sWord; - } - } - - pPDFFont->AppendChar(sWord, Word); - return sWord; -} diff --git a/fpdfsdk/fxedit/fxet_edit.cpp b/fpdfsdk/fxedit/fxet_edit.cpp deleted file mode 100644 index 1acc57795a06a0d9b429c52f1107663a8d2e81ba..0000000000000000000000000000000000000000 --- a/fpdfsdk/fxedit/fxet_edit.cpp +++ /dev/null @@ -1,2307 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/fxedit/fxet_edit.h" - -#include -#include -#include - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfapi/page/cpdf_pageobject.h" -#include "core/fpdfapi/page/cpdf_pageobjectholder.h" -#include "core/fpdfapi/page/cpdf_pathobject.h" -#include "core/fpdfapi/page/cpdf_textobject.h" -#include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fpdfapi/render/cpdf_renderoptions.h" -#include "core/fpdfapi/render/cpdf_textrenderer.h" -#include "core/fpdfdoc/cpvt_section.h" -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fpdfdoc/ipvt_fontmap.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/cfx_systemhandler.h" -#include "fpdfsdk/fxedit/fx_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Edit.h" -#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -const int kEditUndoMaxItems = 10000; - -CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { - if (strWords.GetLength() > 0) - return PDF_EncodeString(strWords) + " Tj\n"; - return CFX_ByteString(); -} - -CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - FX_FLOAT fFontSize) { - if (!pFontMap) - return CFX_ByteString(); - - CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); - if (sFontAlias.GetLength() <= 0 || fFontSize <= 0) - return CFX_ByteString(); - - CFX_ByteTextBuf sRet; - sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; - return sRet.MakeString(); -} - -void DrawTextString(CFX_RenderDevice* pDevice, - const CFX_PointF& pt, - CPDF_Font* pFont, - FX_FLOAT fFontSize, - CFX_Matrix* pUser2Device, - const CFX_ByteString& str, - FX_ARGB crTextFill, - int32_t nHorzScale) { - CFX_PointF pos = pUser2Device->Transform(pt); - - if (pFont) { - if (nHorzScale != 100) { - CFX_Matrix mt(nHorzScale / 100.0f, 0, 0, 1, 0, 0); - mt.Concat(*pUser2Device); - - CPDF_RenderOptions ro; - ro.m_Flags = RENDER_CLEARTYPE; - ro.m_ColorMode = RENDER_COLOR_NORMAL; - - CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize, - &mt, str, crTextFill, nullptr, &ro); - } else { - CPDF_RenderOptions ro; - ro.m_Flags = RENDER_CLEARTYPE; - ro.m_ColorMode = RENDER_COLOR_NORMAL; - - CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize, - pUser2Device, str, crTextFill, nullptr, - &ro); - } - } -} - -} // namespace - -CFX_Edit_Iterator::CFX_Edit_Iterator(CFX_Edit* pEdit, - CPDF_VariableText::Iterator* pVTIterator) - : m_pEdit(pEdit), m_pVTIterator(pVTIterator) {} - -CFX_Edit_Iterator::~CFX_Edit_Iterator() {} - -bool CFX_Edit_Iterator::NextWord() { - return m_pVTIterator->NextWord(); -} - -bool CFX_Edit_Iterator::PrevWord() { - return m_pVTIterator->PrevWord(); -} - -bool CFX_Edit_Iterator::GetWord(CPVT_Word& word) const { - ASSERT(m_pEdit); - - if (m_pVTIterator->GetWord(word)) { - word.ptWord = m_pEdit->VTToEdit(word.ptWord); - return true; - } - return false; -} - -bool CFX_Edit_Iterator::GetLine(CPVT_Line& line) const { - ASSERT(m_pEdit); - - if (m_pVTIterator->GetLine(line)) { - line.ptLine = m_pEdit->VTToEdit(line.ptLine); - return true; - } - return false; -} - -bool CFX_Edit_Iterator::GetSection(CPVT_Section& section) const { - ASSERT(m_pEdit); - - if (m_pVTIterator->GetSection(section)) { - section.rcSection = m_pEdit->VTToEdit(section.rcSection); - return true; - } - return false; -} - -void CFX_Edit_Iterator::SetAt(int32_t nWordIndex) { - m_pVTIterator->SetAt(nWordIndex); -} - -void CFX_Edit_Iterator::SetAt(const CPVT_WordPlace& place) { - m_pVTIterator->SetAt(place); -} - -const CPVT_WordPlace& CFX_Edit_Iterator::GetAt() const { - return m_pVTIterator->GetAt(); -} - -CFX_Edit_Provider::CFX_Edit_Provider(IPVT_FontMap* pFontMap) - : CPDF_VariableText::Provider(pFontMap), m_pFontMap(pFontMap) { - ASSERT(m_pFontMap); -} - -CFX_Edit_Provider::~CFX_Edit_Provider() {} - -IPVT_FontMap* CFX_Edit_Provider::GetFontMap() { - return m_pFontMap; -} - -int32_t CFX_Edit_Provider::GetCharWidth(int32_t nFontIndex, uint16_t word) { - if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) { - uint32_t charcode = word; - - if (pPDFFont->IsUnicodeCompatible()) - charcode = pPDFFont->CharCodeFromUnicode(word); - else - charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word); - - if (charcode != CPDF_Font::kInvalidCharCode) - return pPDFFont->GetCharWidthF(charcode); - } - - return 0; -} - -int32_t CFX_Edit_Provider::GetTypeAscent(int32_t nFontIndex) { - if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) - return pPDFFont->GetTypeAscent(); - - return 0; -} - -int32_t CFX_Edit_Provider::GetTypeDescent(int32_t nFontIndex) { - if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) - return pPDFFont->GetTypeDescent(); - - return 0; -} - -int32_t CFX_Edit_Provider::GetWordFontIndex(uint16_t word, - int32_t charset, - int32_t nFontIndex) { - return m_pFontMap->GetWordFontIndex(word, charset, nFontIndex); -} - -int32_t CFX_Edit_Provider::GetDefaultFontIndex() { - return 0; -} - -bool CFX_Edit_Provider::IsLatinWord(uint16_t word) { - return FX_EDIT_ISLATINWORD(word); -} - -CFX_Edit_Refresh::CFX_Edit_Refresh() {} - -CFX_Edit_Refresh::~CFX_Edit_Refresh() {} - -void CFX_Edit_Refresh::BeginRefresh() { - m_RefreshRects.Clear(); - m_OldLineRects = std::move(m_NewLineRects); -} - -void CFX_Edit_Refresh::Push(const CPVT_WordRange& linerange, - const CFX_FloatRect& rect) { - m_NewLineRects.Add(linerange, rect); -} - -void CFX_Edit_Refresh::NoAnalyse() { - { - for (int32_t i = 0, sz = m_OldLineRects.GetSize(); i < sz; i++) - if (CFX_Edit_LineRect* pOldRect = m_OldLineRects.GetAt(i)) - m_RefreshRects.Add(pOldRect->m_rcLine); - } - - { - for (int32_t i = 0, sz = m_NewLineRects.GetSize(); i < sz; i++) - if (CFX_Edit_LineRect* pNewRect = m_NewLineRects.GetAt(i)) - m_RefreshRects.Add(pNewRect->m_rcLine); - } -} - -void CFX_Edit_Refresh::AddRefresh(const CFX_FloatRect& rect) { - m_RefreshRects.Add(rect); -} - -const CFX_Edit_RectArray* CFX_Edit_Refresh::GetRefreshRects() const { - return &m_RefreshRects; -} - -void CFX_Edit_Refresh::EndRefresh() { - m_RefreshRects.Clear(); -} - -CFX_Edit_Undo::CFX_Edit_Undo(int32_t nBufsize) - : m_nCurUndoPos(0), - m_nBufSize(nBufsize), - m_bModified(false), - m_bVirgin(true), - m_bWorking(false) {} - -CFX_Edit_Undo::~CFX_Edit_Undo() { - Reset(); -} - -bool CFX_Edit_Undo::CanUndo() const { - return m_nCurUndoPos > 0; -} - -void CFX_Edit_Undo::Undo() { - m_bWorking = true; - if (m_nCurUndoPos > 0) { - m_UndoItemStack[m_nCurUndoPos - 1]->Undo(); - m_nCurUndoPos--; - m_bModified = (m_nCurUndoPos != 0); - } - m_bWorking = false; -} - -bool CFX_Edit_Undo::CanRedo() const { - return m_nCurUndoPos < m_UndoItemStack.size(); -} - -void CFX_Edit_Undo::Redo() { - m_bWorking = true; - if (m_nCurUndoPos < m_UndoItemStack.size()) { - m_UndoItemStack[m_nCurUndoPos]->Redo(); - m_nCurUndoPos++; - m_bModified = true; - } - m_bWorking = false; -} - -void CFX_Edit_Undo::AddItem(std::unique_ptr pItem) { - ASSERT(!m_bWorking); - ASSERT(pItem); - ASSERT(m_nBufSize > 1); - if (m_nCurUndoPos < m_UndoItemStack.size()) - RemoveTails(); - - if (m_UndoItemStack.size() >= m_nBufSize) { - RemoveHeads(); - m_bVirgin = false; - } - - m_UndoItemStack.push_back(std::move(pItem)); - m_nCurUndoPos = m_UndoItemStack.size(); - m_bModified = true; -} - -bool CFX_Edit_Undo::IsModified() const { - return m_bVirgin ? m_bModified : true; -} - -void CFX_Edit_Undo::RemoveHeads() { - ASSERT(m_UndoItemStack.size() > 1); - m_UndoItemStack.pop_front(); -} - -void CFX_Edit_Undo::RemoveTails() { - while (m_UndoItemStack.size() > m_nCurUndoPos) - m_UndoItemStack.pop_back(); -} - -void CFX_Edit_Undo::Reset() { - m_UndoItemStack.clear(); - m_nCurUndoPos = 0; -} - -CFX_Edit_UndoItem::CFX_Edit_UndoItem() : m_bFirst(true), m_bLast(true) {} - -CFX_Edit_UndoItem::~CFX_Edit_UndoItem() {} - -CFX_WideString CFX_Edit_UndoItem::GetUndoTitle() const { - return CFX_WideString(); -} - -void CFX_Edit_UndoItem::SetFirst(bool bFirst) { - m_bFirst = bFirst; -} - -void CFX_Edit_UndoItem::SetLast(bool bLast) { - m_bLast = bLast; -} - -bool CFX_Edit_UndoItem::IsLast() { - return m_bLast; -} - -CFX_Edit_GroupUndoItem::CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle) - : m_sTitle(sTitle) {} - -CFX_Edit_GroupUndoItem::~CFX_Edit_GroupUndoItem() {} - -void CFX_Edit_GroupUndoItem::AddUndoItem( - std::unique_ptr pUndoItem) { - pUndoItem->SetFirst(false); - pUndoItem->SetLast(false); - if (m_sTitle.IsEmpty()) - m_sTitle = pUndoItem->GetUndoTitle(); - - m_Items.push_back(std::move(pUndoItem)); -} - -void CFX_Edit_GroupUndoItem::UpdateItems() { - if (!m_Items.empty()) { - m_Items.front()->SetFirst(true); - m_Items.back()->SetLast(true); - } -} - -void CFX_Edit_GroupUndoItem::Undo() { - for (auto iter = m_Items.rbegin(); iter != m_Items.rend(); ++iter) - (*iter)->Undo(); -} - -void CFX_Edit_GroupUndoItem::Redo() { - for (auto iter = m_Items.begin(); iter != m_Items.end(); ++iter) - (*iter)->Redo(); -} - -CFX_WideString CFX_Edit_GroupUndoItem::GetUndoTitle() const { - return m_sTitle; -} - -CFXEU_InsertWord::CFXEU_InsertWord(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps) - : m_pEdit(pEdit), - m_wpOld(wpOldPlace), - m_wpNew(wpNewPlace), - m_Word(word), - m_nCharset(charset), - m_WordProps() { - if (pWordProps) - m_WordProps = *pWordProps; -} - -CFXEU_InsertWord::~CFXEU_InsertWord() {} - -void CFXEU_InsertWord::Redo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpOld); - m_pEdit->InsertWord(m_Word, m_nCharset, &m_WordProps, false, true); - } -} - -void CFXEU_InsertWord::Undo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpNew); - m_pEdit->Backspace(false, true); - } -} - -CFXEU_InsertReturn::CFXEU_InsertReturn(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps) - : m_pEdit(pEdit), - m_wpOld(wpOldPlace), - m_wpNew(wpNewPlace), - m_SecProps(), - m_WordProps() { - if (pSecProps) - m_SecProps = *pSecProps; - if (pWordProps) - m_WordProps = *pWordProps; -} - -CFXEU_InsertReturn::~CFXEU_InsertReturn() {} - -void CFXEU_InsertReturn::Redo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpOld); - m_pEdit->InsertReturn(&m_SecProps, &m_WordProps, false, true); - } -} - -void CFXEU_InsertReturn::Undo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpNew); - m_pEdit->Backspace(false, true); - } -} - -CFXEU_Backspace::CFXEU_Backspace(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_SecProps& SecProps, - const CPVT_WordProps& WordProps) - : m_pEdit(pEdit), - m_wpOld(wpOldPlace), - m_wpNew(wpNewPlace), - m_Word(word), - m_nCharset(charset), - m_SecProps(SecProps), - m_WordProps(WordProps) {} - -CFXEU_Backspace::~CFXEU_Backspace() {} - -void CFXEU_Backspace::Redo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpOld); - m_pEdit->Backspace(false, true); - } -} - -void CFXEU_Backspace::Undo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpNew); - if (m_wpNew.SecCmp(m_wpOld) != 0) { - m_pEdit->InsertReturn(&m_SecProps, &m_WordProps, false, true); - } else { - m_pEdit->InsertWord(m_Word, m_nCharset, &m_WordProps, false, true); - } - } -} - -CFXEU_Delete::CFXEU_Delete(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_SecProps& SecProps, - const CPVT_WordProps& WordProps, - bool bSecEnd) - : m_pEdit(pEdit), - m_wpOld(wpOldPlace), - m_wpNew(wpNewPlace), - m_Word(word), - m_nCharset(charset), - m_SecProps(SecProps), - m_WordProps(WordProps), - m_bSecEnd(bSecEnd) {} - -CFXEU_Delete::~CFXEU_Delete() {} - -void CFXEU_Delete::Redo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpOld); - m_pEdit->Delete(false, true); - } -} - -void CFXEU_Delete::Undo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpNew); - if (m_bSecEnd) { - m_pEdit->InsertReturn(&m_SecProps, &m_WordProps, false, true); - } else { - m_pEdit->InsertWord(m_Word, m_nCharset, &m_WordProps, false, true); - } - } -} - -CFXEU_Clear::CFXEU_Clear(CFX_Edit* pEdit, - const CPVT_WordRange& wrSel, - const CFX_WideString& swText) - : m_pEdit(pEdit), m_wrSel(wrSel), m_swText(swText) {} - -CFXEU_Clear::~CFXEU_Clear() {} - -void CFXEU_Clear::Redo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetSel(m_wrSel.BeginPos, m_wrSel.EndPos); - m_pEdit->Clear(false, true); - } -} - -void CFXEU_Clear::Undo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wrSel.BeginPos); - m_pEdit->InsertText(m_swText, FXFONT_DEFAULT_CHARSET, false, true); - m_pEdit->SetSel(m_wrSel.BeginPos, m_wrSel.EndPos); - } -} - -CFXEU_InsertText::CFXEU_InsertText(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - const CFX_WideString& swText, - int32_t charset) - : m_pEdit(pEdit), - m_wpOld(wpOldPlace), - m_wpNew(wpNewPlace), - m_swText(swText), - m_nCharset(charset) {} - -CFXEU_InsertText::~CFXEU_InsertText() {} - -void CFXEU_InsertText::Redo() { - if (m_pEdit && IsLast()) { - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpOld); - m_pEdit->InsertText(m_swText, m_nCharset, false, true); - } -} - -void CFXEU_InsertText::Undo() { - if (m_pEdit) { - m_pEdit->SelectNone(); - m_pEdit->SetSel(m_wpOld, m_wpNew); - m_pEdit->Clear(false, true); - } -} - -// static -CFX_ByteString CFX_Edit::GetEditAppearanceStream(CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange, - bool bContinuous, - uint16_t SubWord) { - CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); - if (pRange) - pIterator->SetAt(pRange->BeginPos); - else - pIterator->SetAt(0); - - CFX_ByteTextBuf sEditStream; - CFX_ByteTextBuf sWords; - int32_t nCurFontIndex = -1; - CFX_PointF ptOld; - CFX_PointF ptNew; - CPVT_WordPlace oldplace; - - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - if (pRange && place.WordCmp(pRange->EndPos) > 0) - break; - - if (bContinuous) { - if (place.LineCmp(oldplace) != 0) { - if (sWords.GetSize() > 0) { - sEditStream << GetWordRenderString(sWords.MakeString()); - sWords.Clear(); - } - - CPVT_Word word; - if (pIterator->GetWord(word)) { - ptNew = CFX_PointF(word.ptWord.x + ptOffset.x, - word.ptWord.y + ptOffset.y); - } else { - CPVT_Line line; - pIterator->GetLine(line); - ptNew = CFX_PointF(line.ptLine.x + ptOffset.x, - line.ptLine.y + ptOffset.y); - } - - if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { - sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y - << " Td\n"; - - ptOld = ptNew; - } - } - - CPVT_Word word; - if (pIterator->GetWord(word)) { - if (word.nFontIndex != nCurFontIndex) { - if (sWords.GetSize() > 0) { - sEditStream << GetWordRenderString(sWords.MakeString()); - sWords.Clear(); - } - sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex, - word.fFontSize); - nCurFontIndex = word.nFontIndex; - } - - sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex, - word.Word, SubWord); - } - - oldplace = place; - } else { - CPVT_Word word; - if (pIterator->GetWord(word)) { - ptNew = - CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y); - - if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { - sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y - << " Td\n"; - ptOld = ptNew; - } - - if (word.nFontIndex != nCurFontIndex) { - sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex, - word.fFontSize); - nCurFontIndex = word.nFontIndex; - } - - sEditStream << GetWordRenderString(GetPDFWordString( - pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord)); - } - } - } - - if (sWords.GetSize() > 0) { - sEditStream << GetWordRenderString(sWords.MakeString()); - sWords.Clear(); - } - - CFX_ByteTextBuf sAppStream; - if (sEditStream.GetSize() > 0) { - int32_t nHorzScale = pEdit->GetHorzScale(); - if (nHorzScale != 100) { - sAppStream << nHorzScale << " Tz\n"; - } - - FX_FLOAT fCharSpace = pEdit->GetCharSpace(); - if (!IsFloatZero(fCharSpace)) { - sAppStream << fCharSpace << " Tc\n"; - } - - sAppStream << sEditStream; - } - - return sAppStream.MakeString(); -} - -// static -CFX_ByteString CFX_Edit::GetSelectAppearanceStream( - CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange) { - if (!pRange || !pRange->IsExist()) - return CFX_ByteString(); - - CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); - pIterator->SetAt(pRange->BeginPos); - - CFX_ByteTextBuf sRet; - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - if (place.WordCmp(pRange->EndPos) > 0) - break; - - CPVT_Word word; - CPVT_Line line; - if (pIterator->GetWord(word) && pIterator->GetLine(line)) { - sRet << word.ptWord.x + ptOffset.x << " " - << line.ptLine.y + line.fLineDescent << " " << word.fWidth << " " - << line.fLineAscent - line.fLineDescent << " re\nf\n"; - } - } - - return sRet.MakeString(); -} - -// static -void CFX_Edit::DrawEdit(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - CFX_Edit* pEdit, - FX_COLORREF crTextFill, - const CFX_FloatRect& rcClip, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange, - CFX_SystemHandler* pSystemHandler, - CFFL_FormFiller* pFFLData) { - const bool bContinuous = - pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f; - uint16_t SubWord = pEdit->GetPasswordChar(); - FX_FLOAT fFontSize = pEdit->GetFontSize(); - CPVT_WordRange wrSelect = pEdit->GetSelectWordRange(); - int32_t nHorzScale = pEdit->GetHorzScale(); - - FX_COLORREF crCurFill = crTextFill; - FX_COLORREF crOldFill = crCurFill; - - bool bSelect = false; - const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); - const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113); - - CFX_ByteTextBuf sTextBuf; - int32_t nFontIndex = -1; - CFX_PointF ptBT; - pDevice->SaveState(); - if (!rcClip.IsEmpty()) { - CFX_FloatRect rcTemp = rcClip; - pUser2Device->TransformRect(rcTemp); - pDevice->SetClip_Rect(rcTemp.ToFxRect()); - } - - CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); - if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { - if (pRange) - pIterator->SetAt(pRange->BeginPos); - else - pIterator->SetAt(0); - - CPVT_WordPlace oldplace; - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - if (pRange && place.WordCmp(pRange->EndPos) > 0) - break; - - if (wrSelect.IsExist()) { - bSelect = place.WordCmp(wrSelect.BeginPos) > 0 && - place.WordCmp(wrSelect.EndPos) <= 0; - crCurFill = bSelect ? crWhite : crTextFill; - } - if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { - crCurFill = crTextFill; - crOldFill = crCurFill; - } - CPVT_Word word; - if (pIterator->GetWord(word)) { - if (bSelect) { - CPVT_Line line; - pIterator->GetLine(line); - - if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { - CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent, - word.ptWord.x + word.fWidth, - line.ptLine.y + line.fLineAscent); - rc.Intersect(rcClip); - pSystemHandler->OutputSelectedRect(pFFLData, rc); - } else { - CFX_PathData pathSelBK; - pathSelBK.AppendRect( - word.ptWord.x, line.ptLine.y + line.fLineDescent, - word.ptWord.x + word.fWidth, line.ptLine.y + line.fLineAscent); - - pDevice->DrawPath(&pathSelBK, pUser2Device, nullptr, crSelBK, 0, - FXFILL_WINDING); - } - } - - if (bContinuous) { - if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex || - crOldFill != crCurFill) { - if (sTextBuf.GetLength() > 0) { - DrawTextString( - pDevice, CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), - pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device, - sTextBuf.MakeString(), crOldFill, nHorzScale); - - sTextBuf.Clear(); - } - nFontIndex = word.nFontIndex; - ptBT = word.ptWord; - crOldFill = crCurFill; - } - - sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, - SubWord) - .AsStringC(); - } else { - DrawTextString( - pDevice, CFX_PointF(word.ptWord.x + ptOffset.x, - word.ptWord.y + ptOffset.y), - pFontMap->GetPDFFont(word.nFontIndex), fFontSize, pUser2Device, - GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord), - crCurFill, nHorzScale); - } - oldplace = place; - } - } - - if (sTextBuf.GetLength() > 0) { - DrawTextString(pDevice, - CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), - pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device, - sTextBuf.MakeString(), crOldFill, nHorzScale); - } - } - - pDevice->RestoreState(false); -} - -CFX_Edit::CFX_Edit() - : m_pVT(new CPDF_VariableText), - m_pNotify(nullptr), - m_pOprNotify(nullptr), - m_wpCaret(-1, -1, -1), - m_wpOldCaret(-1, -1, -1), - m_SelState(), - m_bEnableScroll(false), - m_Undo(kEditUndoMaxItems), - m_nAlignment(0), - m_bNotifyFlag(false), - m_bEnableOverflow(false), - m_bEnableRefresh(true), - m_rcOldContent(0.0f, 0.0f, 0.0f, 0.0f), - m_bEnableUndo(true), - m_bOprNotify(false), - m_pGroupUndoItem(nullptr) {} - -CFX_Edit::~CFX_Edit() { - ASSERT(!m_pGroupUndoItem); -} - -void CFX_Edit::Initialize() { - m_pVT->Initialize(); - SetCaret(m_pVT->GetBeginWordPlace()); - SetCaretOrigin(); -} - -void CFX_Edit::SetFontMap(IPVT_FontMap* pFontMap) { - m_pVTProvider = pdfium::MakeUnique(pFontMap); - m_pVT->SetProvider(m_pVTProvider.get()); -} - -void CFX_Edit::SetNotify(CPWL_EditCtrl* pNotify) { - m_pNotify = pNotify; -} - -void CFX_Edit::SetOprNotify(CPWL_Edit* pOprNotify) { - m_pOprNotify = pOprNotify; -} - -CFX_Edit_Iterator* CFX_Edit::GetIterator() { - if (!m_pIterator) { - m_pIterator = - pdfium::MakeUnique(this, m_pVT->GetIterator()); - } - return m_pIterator.get(); -} - -IPVT_FontMap* CFX_Edit::GetFontMap() { - return m_pVTProvider ? m_pVTProvider->GetFontMap() : nullptr; -} - -void CFX_Edit::SetPlateRect(const CFX_FloatRect& rect) { - m_pVT->SetPlateRect(rect); - m_ptScrollPos = CFX_PointF(rect.left, rect.top); - Paint(); -} - -void CFX_Edit::SetAlignmentH(int32_t nFormat, bool bPaint) { - m_pVT->SetAlignment(nFormat); - if (bPaint) - Paint(); -} - -void CFX_Edit::SetAlignmentV(int32_t nFormat, bool bPaint) { - m_nAlignment = nFormat; - if (bPaint) - Paint(); -} - -void CFX_Edit::SetPasswordChar(uint16_t wSubWord, bool bPaint) { - m_pVT->SetPasswordChar(wSubWord); - if (bPaint) - Paint(); -} - -void CFX_Edit::SetLimitChar(int32_t nLimitChar) { - m_pVT->SetLimitChar(nLimitChar); - Paint(); -} - -void CFX_Edit::SetCharArray(int32_t nCharArray) { - m_pVT->SetCharArray(nCharArray); - Paint(); -} - -void CFX_Edit::SetCharSpace(FX_FLOAT fCharSpace) { - m_pVT->SetCharSpace(fCharSpace); - Paint(); -} - -void CFX_Edit::SetMultiLine(bool bMultiLine, bool bPaint) { - m_pVT->SetMultiLine(bMultiLine); - if (bPaint) - Paint(); -} - -void CFX_Edit::SetAutoReturn(bool bAuto, bool bPaint) { - m_pVT->SetAutoReturn(bAuto); - if (bPaint) - Paint(); -} - -void CFX_Edit::SetAutoFontSize(bool bAuto, bool bPaint) { - m_pVT->SetAutoFontSize(bAuto); - if (bPaint) - Paint(); -} - -void CFX_Edit::SetFontSize(FX_FLOAT fFontSize) { - m_pVT->SetFontSize(fFontSize); - Paint(); -} - -void CFX_Edit::SetAutoScroll(bool bAuto, bool bPaint) { - m_bEnableScroll = bAuto; - if (bPaint) - Paint(); -} - -void CFX_Edit::SetTextOverflow(bool bAllowed, bool bPaint) { - m_bEnableOverflow = bAllowed; - if (bPaint) - Paint(); -} - -void CFX_Edit::SetSel(int32_t nStartChar, int32_t nEndChar) { - if (m_pVT->IsValid()) { - if (nStartChar == 0 && nEndChar < 0) { - SelectAll(); - } else if (nStartChar < 0) { - SelectNone(); - } else { - if (nStartChar < nEndChar) { - SetSel(m_pVT->WordIndexToWordPlace(nStartChar), - m_pVT->WordIndexToWordPlace(nEndChar)); - } else { - SetSel(m_pVT->WordIndexToWordPlace(nEndChar), - m_pVT->WordIndexToWordPlace(nStartChar)); - } - } - } -} - -void CFX_Edit::SetSel(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) { - if (m_pVT->IsValid()) { - SelectNone(); - - m_SelState.Set(begin, end); - - SetCaret(m_SelState.EndPos); - - if (m_SelState.IsExist()) { - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } else { - ScrollToCaret(); - SetCaretInfo(); - } - } -} - -void CFX_Edit::GetSel(int32_t& nStartChar, int32_t& nEndChar) const { - nStartChar = -1; - nEndChar = -1; - - if (m_pVT->IsValid()) { - if (m_SelState.IsExist()) { - if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) < 0) { - nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos); - nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos); - } else { - nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos); - nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos); - } - } else { - nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret); - nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret); - } - } -} - -int32_t CFX_Edit::GetCaret() const { - if (m_pVT->IsValid()) - return m_pVT->WordPlaceToWordIndex(m_wpCaret); - - return -1; -} - -CPVT_WordPlace CFX_Edit::GetCaretWordPlace() const { - return m_wpCaret; -} - -CFX_WideString CFX_Edit::GetText() const { - CFX_WideString swRet; - - if (!m_pVT->IsValid()) - return swRet; - - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(0); - - CPVT_Word wordinfo; - CPVT_WordPlace oldplace = pIterator->GetAt(); - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - - if (pIterator->GetWord(wordinfo)) - swRet += wordinfo.Word; - - if (oldplace.SecCmp(place) != 0) - swRet += L"\r\n"; - - oldplace = place; - } - - return swRet; -} - -CFX_WideString CFX_Edit::GetRangeText(const CPVT_WordRange& range) const { - CFX_WideString swRet; - - if (!m_pVT->IsValid()) - return swRet; - - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - CPVT_WordRange wrTemp = range; - m_pVT->UpdateWordPlace(wrTemp.BeginPos); - m_pVT->UpdateWordPlace(wrTemp.EndPos); - pIterator->SetAt(wrTemp.BeginPos); - - CPVT_Word wordinfo; - CPVT_WordPlace oldplace = wrTemp.BeginPos; - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - if (place.WordCmp(wrTemp.EndPos) > 0) - break; - - if (pIterator->GetWord(wordinfo)) - swRet += wordinfo.Word; - - if (oldplace.SecCmp(place) != 0) - swRet += L"\r\n"; - - oldplace = place; - } - - return swRet; -} - -CFX_WideString CFX_Edit::GetSelText() const { - return GetRangeText(m_SelState.ConvertToWordRange()); -} - -int32_t CFX_Edit::GetTotalWords() const { - return m_pVT->GetTotalWords(); -} - -int32_t CFX_Edit::GetTotalLines() const { - int32_t nLines = 1; - - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(0); - while (pIterator->NextLine()) - ++nLines; - - return nLines; -} - -CPVT_WordRange CFX_Edit::GetSelectWordRange() const { - return m_SelState.ConvertToWordRange(); -} - -void CFX_Edit::SetText(const CFX_WideString& sText) { - Empty(); - DoInsertText(CPVT_WordPlace(0, 0, -1), sText, FXFONT_DEFAULT_CHARSET); - Paint(); -} - -bool CFX_Edit::InsertWord(uint16_t word, int32_t charset) { - return InsertWord(word, charset, nullptr, true, true); -} - -bool CFX_Edit::InsertReturn() { - return InsertReturn(nullptr, nullptr, true, true); -} - -bool CFX_Edit::Backspace() { - return Backspace(true, true); -} - -bool CFX_Edit::Delete() { - return Delete(true, true); -} - -bool CFX_Edit::Clear() { - return Clear(true, true); -} - -bool CFX_Edit::InsertText(const CFX_WideString& sText, int32_t charset) { - return InsertText(sText, charset, true, true); -} - -FX_FLOAT CFX_Edit::GetFontSize() const { - return m_pVT->GetFontSize(); -} - -uint16_t CFX_Edit::GetPasswordChar() const { - return m_pVT->GetPasswordChar(); -} - -int32_t CFX_Edit::GetCharArray() const { - return m_pVT->GetCharArray(); -} - -CFX_FloatRect CFX_Edit::GetContentRect() const { - return VTToEdit(m_pVT->GetContentRect()); -} - -int32_t CFX_Edit::GetHorzScale() const { - return m_pVT->GetHorzScale(); -} - -FX_FLOAT CFX_Edit::GetCharSpace() const { - return m_pVT->GetCharSpace(); -} - -CPVT_WordRange CFX_Edit::GetWholeWordRange() const { - if (m_pVT->IsValid()) - return CPVT_WordRange(m_pVT->GetBeginWordPlace(), m_pVT->GetEndWordPlace()); - - return CPVT_WordRange(); -} - -CPVT_WordRange CFX_Edit::GetVisibleWordRange() const { - if (m_bEnableOverflow) - return GetWholeWordRange(); - - if (m_pVT->IsValid()) { - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - - CPVT_WordPlace place1 = - m_pVT->SearchWordPlace(EditToVT(CFX_PointF(rcPlate.left, rcPlate.top))); - CPVT_WordPlace place2 = m_pVT->SearchWordPlace( - EditToVT(CFX_PointF(rcPlate.right, rcPlate.bottom))); - - return CPVT_WordRange(place1, place2); - } - - return CPVT_WordRange(); -} - -CPVT_WordPlace CFX_Edit::SearchWordPlace(const CFX_PointF& point) const { - if (m_pVT->IsValid()) { - return m_pVT->SearchWordPlace(EditToVT(point)); - } - - return CPVT_WordPlace(); -} - -void CFX_Edit::Paint() { - if (m_pVT->IsValid()) { - RearrangeAll(); - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } -} - -void CFX_Edit::RearrangeAll() { - if (m_pVT->IsValid()) { - m_pVT->UpdateWordPlace(m_wpCaret); - m_pVT->RearrangeAll(); - m_pVT->UpdateWordPlace(m_wpCaret); - SetScrollInfo(); - SetContentChanged(); - } -} - -void CFX_Edit::RearrangePart(const CPVT_WordRange& range) { - if (m_pVT->IsValid()) { - m_pVT->UpdateWordPlace(m_wpCaret); - m_pVT->RearrangePart(range); - m_pVT->UpdateWordPlace(m_wpCaret); - SetScrollInfo(); - SetContentChanged(); - } -} - -void CFX_Edit::SetContentChanged() { - if (m_pNotify) { - CFX_FloatRect rcContent = m_pVT->GetContentRect(); - if (rcContent.Width() != m_rcOldContent.Width() || - rcContent.Height() != m_rcOldContent.Height()) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - m_pNotify->IOnContentChange(rcContent); - m_bNotifyFlag = false; - } - m_rcOldContent = rcContent; - } - } -} - -void CFX_Edit::SelectAll() { - if (m_pVT->IsValid()) { - m_SelState = CFX_Edit_Select(GetWholeWordRange()); - SetCaret(m_SelState.EndPos); - - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } -} - -void CFX_Edit::SelectNone() { - if (m_pVT->IsValid()) { - if (m_SelState.IsExist()) { - m_SelState.Default(); - Refresh(); - } - } -} - -bool CFX_Edit::IsSelected() const { - return m_SelState.IsExist(); -} - -CFX_PointF CFX_Edit::VTToEdit(const CFX_PointF& point) const { - CFX_FloatRect rcContent = m_pVT->GetContentRect(); - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - - FX_FLOAT fPadding = 0.0f; - - switch (m_nAlignment) { - case 0: - fPadding = 0.0f; - break; - case 1: - fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f; - break; - case 2: - fPadding = rcPlate.Height() - rcContent.Height(); - break; - } - - return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left), - point.y - (m_ptScrollPos.y + fPadding - rcPlate.top)); -} - -CFX_PointF CFX_Edit::EditToVT(const CFX_PointF& point) const { - CFX_FloatRect rcContent = m_pVT->GetContentRect(); - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - - FX_FLOAT fPadding = 0.0f; - - switch (m_nAlignment) { - case 0: - fPadding = 0.0f; - break; - case 1: - fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f; - break; - case 2: - fPadding = rcPlate.Height() - rcContent.Height(); - break; - } - - return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left), - point.y + (m_ptScrollPos.y + fPadding - rcPlate.top)); -} - -CFX_FloatRect CFX_Edit::VTToEdit(const CFX_FloatRect& rect) const { - CFX_PointF ptLeftBottom = VTToEdit(CFX_PointF(rect.left, rect.bottom)); - CFX_PointF ptRightTop = VTToEdit(CFX_PointF(rect.right, rect.top)); - - return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, - ptRightTop.y); -} - -void CFX_Edit::SetScrollInfo() { - if (m_pNotify) { - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - CFX_FloatRect rcContent = m_pVT->GetContentRect(); - - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, - rcContent.bottom, rcContent.top, - rcPlate.Height() / 3, rcPlate.Height()); - m_bNotifyFlag = false; - } - } -} - -void CFX_Edit::SetScrollPosX(FX_FLOAT fx) { - if (!m_bEnableScroll) - return; - - if (m_pVT->IsValid()) { - if (!IsFloatEqual(m_ptScrollPos.x, fx)) { - m_ptScrollPos.x = fx; - Refresh(); - } - } -} - -void CFX_Edit::SetScrollPosY(FX_FLOAT fy) { - if (!m_bEnableScroll) - return; - - if (m_pVT->IsValid()) { - if (!IsFloatEqual(m_ptScrollPos.y, fy)) { - m_ptScrollPos.y = fy; - Refresh(); - - if (m_pNotify) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - m_pNotify->IOnSetScrollPosY(fy); - m_bNotifyFlag = false; - } - } - } - } -} - -void CFX_Edit::SetScrollPos(const CFX_PointF& point) { - SetScrollPosX(point.x); - SetScrollPosY(point.y); - SetScrollLimit(); - SetCaretInfo(); -} - -CFX_PointF CFX_Edit::GetScrollPos() const { - return m_ptScrollPos; -} - -void CFX_Edit::SetScrollLimit() { - if (m_pVT->IsValid()) { - CFX_FloatRect rcContent = m_pVT->GetContentRect(); - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - - if (rcPlate.Width() > rcContent.Width()) { - SetScrollPosX(rcPlate.left); - } else { - if (IsFloatSmaller(m_ptScrollPos.x, rcContent.left)) { - SetScrollPosX(rcContent.left); - } else if (IsFloatBigger(m_ptScrollPos.x, - rcContent.right - rcPlate.Width())) { - SetScrollPosX(rcContent.right - rcPlate.Width()); - } - } - - if (rcPlate.Height() > rcContent.Height()) { - SetScrollPosY(rcPlate.top); - } else { - if (IsFloatSmaller(m_ptScrollPos.y, - rcContent.bottom + rcPlate.Height())) { - SetScrollPosY(rcContent.bottom + rcPlate.Height()); - } else if (IsFloatBigger(m_ptScrollPos.y, rcContent.top)) { - SetScrollPosY(rcContent.top); - } - } - } -} - -void CFX_Edit::ScrollToCaret() { - SetScrollLimit(); - - if (!m_pVT->IsValid()) - return; - - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(m_wpCaret); - - CFX_PointF ptHead; - CFX_PointF ptFoot; - CPVT_Word word; - CPVT_Line line; - if (pIterator->GetWord(word)) { - ptHead.x = word.ptWord.x + word.fWidth; - ptHead.y = word.ptWord.y + word.fAscent; - ptFoot.x = word.ptWord.x + word.fWidth; - ptFoot.y = word.ptWord.y + word.fDescent; - } else if (pIterator->GetLine(line)) { - ptHead.x = line.ptLine.x; - ptHead.y = line.ptLine.y + line.fLineAscent; - ptFoot.x = line.ptLine.x; - ptFoot.y = line.ptLine.y + line.fLineDescent; - } - - CFX_PointF ptHeadEdit = VTToEdit(ptHead); - CFX_PointF ptFootEdit = VTToEdit(ptFoot); - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - if (!IsFloatEqual(rcPlate.left, rcPlate.right)) { - if (IsFloatSmaller(ptHeadEdit.x, rcPlate.left) || - IsFloatEqual(ptHeadEdit.x, rcPlate.left)) { - SetScrollPosX(ptHead.x); - } else if (IsFloatBigger(ptHeadEdit.x, rcPlate.right)) { - SetScrollPosX(ptHead.x - rcPlate.Width()); - } - } - - if (!IsFloatEqual(rcPlate.top, rcPlate.bottom)) { - if (IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) || - IsFloatEqual(ptFootEdit.y, rcPlate.bottom)) { - if (IsFloatSmaller(ptHeadEdit.y, rcPlate.top)) { - SetScrollPosY(ptFoot.y + rcPlate.Height()); - } - } else if (IsFloatBigger(ptHeadEdit.y, rcPlate.top)) { - if (IsFloatBigger(ptFootEdit.y, rcPlate.bottom)) { - SetScrollPosY(ptHead.y); - } - } - } -} - -void CFX_Edit::Refresh() { - if (m_bEnableRefresh && m_pVT->IsValid()) { - m_Refresh.BeginRefresh(); - RefreshPushLineRects(GetVisibleWordRange()); - - m_Refresh.NoAnalyse(); - m_ptRefreshScrollPos = m_ptScrollPos; - - if (m_pNotify) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - if (const CFX_Edit_RectArray* pRects = m_Refresh.GetRefreshRects()) { - for (int32_t i = 0, sz = pRects->GetSize(); i < sz; i++) - m_pNotify->IOnInvalidateRect(pRects->GetAt(i)); - } - m_bNotifyFlag = false; - } - } - - m_Refresh.EndRefresh(); - } -} - -void CFX_Edit::RefreshPushLineRects(const CPVT_WordRange& wr) { - if (!m_pVT->IsValid()) - return; - - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - CPVT_WordPlace wpBegin = wr.BeginPos; - m_pVT->UpdateWordPlace(wpBegin); - CPVT_WordPlace wpEnd = wr.EndPos; - m_pVT->UpdateWordPlace(wpEnd); - pIterator->SetAt(wpBegin); - - CPVT_Line lineinfo; - do { - if (!pIterator->GetLine(lineinfo)) - break; - if (lineinfo.lineplace.LineCmp(wpEnd) > 0) - break; - - CFX_FloatRect rcLine(lineinfo.ptLine.x, - lineinfo.ptLine.y + lineinfo.fLineDescent, - lineinfo.ptLine.x + lineinfo.fLineWidth, - lineinfo.ptLine.y + lineinfo.fLineAscent); - - m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace, lineinfo.lineEnd), - VTToEdit(rcLine)); - } while (pIterator->NextLine()); -} - -void CFX_Edit::RefreshWordRange(const CPVT_WordRange& wr) { - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - CPVT_WordRange wrTemp = wr; - - m_pVT->UpdateWordPlace(wrTemp.BeginPos); - m_pVT->UpdateWordPlace(wrTemp.EndPos); - pIterator->SetAt(wrTemp.BeginPos); - - CPVT_Word wordinfo; - CPVT_Line lineinfo; - CPVT_WordPlace place; - - while (pIterator->NextWord()) { - place = pIterator->GetAt(); - if (place.WordCmp(wrTemp.EndPos) > 0) - break; - - pIterator->GetWord(wordinfo); - pIterator->GetLine(lineinfo); - - if (place.LineCmp(wrTemp.BeginPos) == 0 || - place.LineCmp(wrTemp.EndPos) == 0) { - CFX_FloatRect rcWord(wordinfo.ptWord.x, - lineinfo.ptLine.y + lineinfo.fLineDescent, - wordinfo.ptWord.x + wordinfo.fWidth, - lineinfo.ptLine.y + lineinfo.fLineAscent); - - if (m_pNotify) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - CFX_FloatRect rcRefresh = VTToEdit(rcWord); - m_pNotify->IOnInvalidateRect(&rcRefresh); - m_bNotifyFlag = false; - } - } - } else { - CFX_FloatRect rcLine(lineinfo.ptLine.x, - lineinfo.ptLine.y + lineinfo.fLineDescent, - lineinfo.ptLine.x + lineinfo.fLineWidth, - lineinfo.ptLine.y + lineinfo.fLineAscent); - - if (m_pNotify) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - CFX_FloatRect rcRefresh = VTToEdit(rcLine); - m_pNotify->IOnInvalidateRect(&rcRefresh); - m_bNotifyFlag = false; - } - } - - pIterator->NextLine(); - } - } -} - -void CFX_Edit::SetCaret(const CPVT_WordPlace& place) { - m_wpOldCaret = m_wpCaret; - m_wpCaret = place; -} - -void CFX_Edit::SetCaretInfo() { - if (m_pNotify) { - if (!m_bNotifyFlag) { - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(m_wpCaret); - - CFX_PointF ptHead; - CFX_PointF ptFoot; - CPVT_Word word; - CPVT_Line line; - if (pIterator->GetWord(word)) { - ptHead.x = word.ptWord.x + word.fWidth; - ptHead.y = word.ptWord.y + word.fAscent; - ptFoot.x = word.ptWord.x + word.fWidth; - ptFoot.y = word.ptWord.y + word.fDescent; - } else if (pIterator->GetLine(line)) { - ptHead.x = line.ptLine.x; - ptHead.y = line.ptLine.y + line.fLineAscent; - ptFoot.x = line.ptLine.x; - ptFoot.y = line.ptLine.y + line.fLineDescent; - } - - m_bNotifyFlag = true; - m_pNotify->IOnSetCaret(!m_SelState.IsExist(), VTToEdit(ptHead), - VTToEdit(ptFoot), m_wpCaret); - m_bNotifyFlag = false; - } - } -} - -void CFX_Edit::SetCaret(int32_t nPos) { - if (m_pVT->IsValid()) { - SelectNone(); - SetCaret(m_pVT->WordIndexToWordPlace(nPos)); - m_SelState.Set(m_wpCaret, m_wpCaret); - - ScrollToCaret(); - SetCaretOrigin(); - SetCaretInfo(); - } -} - -void CFX_Edit::OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - SelectNone(); - SetCaret(m_pVT->SearchWordPlace(EditToVT(point))); - m_SelState.Set(m_wpCaret, m_wpCaret); - - ScrollToCaret(); - SetCaretOrigin(); - SetCaretInfo(); - } -} - -void CFX_Edit::OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - SetCaret(m_pVT->SearchWordPlace(EditToVT(point))); - - if (m_wpCaret != m_wpOldCaret) { - m_SelState.SetEndPos(m_wpCaret); - - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } - } -} - -void CFX_Edit::OnVK_UP(bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - SetCaret(m_pVT->GetUpWordPlace(m_wpCaret, m_ptCaret)); - - if (bShift) { - if (m_SelState.IsExist()) - m_SelState.SetEndPos(m_wpCaret); - else - m_SelState.Set(m_wpOldCaret, m_wpCaret); - - if (m_wpOldCaret != m_wpCaret) { - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } - } else { - SelectNone(); - - ScrollToCaret(); - SetCaretInfo(); - } - } -} - -void CFX_Edit::OnVK_DOWN(bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - SetCaret(m_pVT->GetDownWordPlace(m_wpCaret, m_ptCaret)); - - if (bShift) { - if (m_SelState.IsExist()) - m_SelState.SetEndPos(m_wpCaret); - else - m_SelState.Set(m_wpOldCaret, m_wpCaret); - - if (m_wpOldCaret != m_wpCaret) { - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } - } else { - SelectNone(); - - ScrollToCaret(); - SetCaretInfo(); - } - } -} - -void CFX_Edit::OnVK_LEFT(bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - if (bShift) { - if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) && - m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) - SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); - - SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); - - if (m_SelState.IsExist()) - m_SelState.SetEndPos(m_wpCaret); - else - m_SelState.Set(m_wpOldCaret, m_wpCaret); - - if (m_wpOldCaret != m_wpCaret) { - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } - } else { - if (m_SelState.IsExist()) { - if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) < 0) - SetCaret(m_SelState.BeginPos); - else - SetCaret(m_SelState.EndPos); - - SelectNone(); - ScrollToCaret(); - SetCaretInfo(); - } else { - if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) && - m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) - SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); - - SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); - - ScrollToCaret(); - SetCaretOrigin(); - SetCaretInfo(); - } - } - } -} - -void CFX_Edit::OnVK_RIGHT(bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - if (bShift) { - SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); - - if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) && - m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret)) - SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); - - if (m_SelState.IsExist()) - m_SelState.SetEndPos(m_wpCaret); - else - m_SelState.Set(m_wpOldCaret, m_wpCaret); - - if (m_wpOldCaret != m_wpCaret) { - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } - } else { - if (m_SelState.IsExist()) { - if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) > 0) - SetCaret(m_SelState.BeginPos); - else - SetCaret(m_SelState.EndPos); - - SelectNone(); - ScrollToCaret(); - SetCaretInfo(); - } else { - SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); - - if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) && - m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret)) - SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); - - ScrollToCaret(); - SetCaretOrigin(); - SetCaretInfo(); - } - } - } -} - -void CFX_Edit::OnVK_HOME(bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - if (bShift) { - if (bCtrl) - SetCaret(m_pVT->GetBeginWordPlace()); - else - SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret)); - - if (m_SelState.IsExist()) - m_SelState.SetEndPos(m_wpCaret); - else - m_SelState.Set(m_wpOldCaret, m_wpCaret); - - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } else { - if (m_SelState.IsExist()) { - if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) < 0) - SetCaret(m_SelState.BeginPos); - else - SetCaret(m_SelState.EndPos); - - SelectNone(); - ScrollToCaret(); - SetCaretInfo(); - } else { - if (bCtrl) - SetCaret(m_pVT->GetBeginWordPlace()); - else - SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret)); - - ScrollToCaret(); - SetCaretOrigin(); - SetCaretInfo(); - } - } - } -} - -void CFX_Edit::OnVK_END(bool bShift, bool bCtrl) { - if (m_pVT->IsValid()) { - if (bShift) { - if (bCtrl) - SetCaret(m_pVT->GetEndWordPlace()); - else - SetCaret(m_pVT->GetLineEndPlace(m_wpCaret)); - - if (m_SelState.IsExist()) - m_SelState.SetEndPos(m_wpCaret); - else - m_SelState.Set(m_wpOldCaret, m_wpCaret); - - ScrollToCaret(); - Refresh(); - SetCaretInfo(); - } else { - if (m_SelState.IsExist()) { - if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) > 0) - SetCaret(m_SelState.BeginPos); - else - SetCaret(m_SelState.EndPos); - - SelectNone(); - ScrollToCaret(); - SetCaretInfo(); - } else { - if (bCtrl) - SetCaret(m_pVT->GetEndWordPlace()); - else - SetCaret(m_pVT->GetLineEndPlace(m_wpCaret)); - - ScrollToCaret(); - SetCaretOrigin(); - SetCaretInfo(); - } - } - } -} - -bool CFX_Edit::InsertWord(uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps, - bool bAddUndo, - bool bPaint) { - if (IsTextOverflow() || !m_pVT->IsValid()) - return false; - - m_pVT->UpdateWordPlace(m_wpCaret); - SetCaret(m_pVT->InsertWord(m_wpCaret, word, - GetCharSetFromUnicode(word, charset), pWordProps)); - m_SelState.Set(m_wpCaret, m_wpCaret); - if (m_wpCaret == m_wpOldCaret) - return false; - - if (bAddUndo && m_bEnableUndo) { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, word, charset, pWordProps)); - } - if (bPaint) - PaintInsertText(m_wpOldCaret, m_wpCaret); - - if (m_bOprNotify && m_pOprNotify) - m_pOprNotify->OnInsertWord(m_wpCaret, m_wpOldCaret); - - return true; -} - -bool CFX_Edit::InsertReturn(const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps, - bool bAddUndo, - bool bPaint) { - if (IsTextOverflow() || !m_pVT->IsValid()) - return false; - - m_pVT->UpdateWordPlace(m_wpCaret); - SetCaret(m_pVT->InsertSection(m_wpCaret, pSecProps, pWordProps)); - m_SelState.Set(m_wpCaret, m_wpCaret); - if (m_wpCaret == m_wpOldCaret) - return false; - - if (bAddUndo && m_bEnableUndo) { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, pSecProps, pWordProps)); - } - if (bPaint) { - RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret)); - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } - if (m_bOprNotify && m_pOprNotify) - m_pOprNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret); - - return true; -} - -bool CFX_Edit::Backspace(bool bAddUndo, bool bPaint) { - if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetBeginWordPlace()) - return false; - - CPVT_Section section; - CPVT_Word word; - if (bAddUndo) { - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(m_wpCaret); - pIterator->GetSection(section); - pIterator->GetWord(word); - } - m_pVT->UpdateWordPlace(m_wpCaret); - SetCaret(m_pVT->BackSpaceWord(m_wpCaret)); - m_SelState.Set(m_wpCaret, m_wpCaret); - if (m_wpCaret == m_wpOldCaret) - return false; - - if (bAddUndo && m_bEnableUndo) { - if (m_wpCaret.SecCmp(m_wpOldCaret) != 0) { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, - section.SecProps, section.WordProps)); - } else { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, - section.SecProps, word.WordProps)); - } - } - if (bPaint) { - RearrangePart(CPVT_WordRange(m_wpCaret, m_wpOldCaret)); - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } - if (m_bOprNotify && m_pOprNotify) - m_pOprNotify->OnBackSpace(m_wpCaret, m_wpOldCaret); - - return true; -} - -bool CFX_Edit::Delete(bool bAddUndo, bool bPaint) { - if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetEndWordPlace()) - return false; - - CPVT_Section section; - CPVT_Word word; - if (bAddUndo) { - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret)); - pIterator->GetSection(section); - pIterator->GetWord(word); - } - m_pVT->UpdateWordPlace(m_wpCaret); - bool bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret)); - SetCaret(m_pVT->DeleteWord(m_wpCaret)); - m_SelState.Set(m_wpCaret, m_wpCaret); - if (bAddUndo && m_bEnableUndo) { - if (bSecEnd) { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, - section.SecProps, section.WordProps, bSecEnd)); - } else { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, - section.SecProps, word.WordProps, bSecEnd)); - } - } - if (bPaint) { - RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret)); - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } - if (m_bOprNotify && m_pOprNotify) - m_pOprNotify->OnDelete(m_wpCaret, m_wpOldCaret); - - return true; -} - -bool CFX_Edit::Empty() { - if (m_pVT->IsValid()) { - m_pVT->DeleteWords(GetWholeWordRange()); - SetCaret(m_pVT->GetBeginWordPlace()); - - return true; - } - - return false; -} - -bool CFX_Edit::Clear(bool bAddUndo, bool bPaint) { - if (!m_pVT->IsValid() || !m_SelState.IsExist()) - return false; - - CPVT_WordRange range = m_SelState.ConvertToWordRange(); - if (bAddUndo && m_bEnableUndo) - AddEditUndoItem(pdfium::MakeUnique(this, range, GetSelText())); - - SelectNone(); - SetCaret(m_pVT->DeleteWords(range)); - m_SelState.Set(m_wpCaret, m_wpCaret); - if (bPaint) { - RearrangePart(range); - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } - if (m_bOprNotify && m_pOprNotify) - m_pOprNotify->OnClear(m_wpCaret, m_wpOldCaret); - - return true; -} - -bool CFX_Edit::InsertText(const CFX_WideString& sText, - int32_t charset, - bool bAddUndo, - bool bPaint) { - if (IsTextOverflow()) - return false; - - m_pVT->UpdateWordPlace(m_wpCaret); - SetCaret(DoInsertText(m_wpCaret, sText, charset)); - m_SelState.Set(m_wpCaret, m_wpCaret); - if (m_wpCaret == m_wpOldCaret) - return false; - - if (bAddUndo && m_bEnableUndo) { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, sText, charset)); - } - if (bPaint) - PaintInsertText(m_wpOldCaret, m_wpCaret); - - if (m_bOprNotify && m_pOprNotify) - m_pOprNotify->OnInsertText(m_wpCaret, m_wpOldCaret); - - return true; -} - -void CFX_Edit::PaintInsertText(const CPVT_WordPlace& wpOld, - const CPVT_WordPlace& wpNew) { - if (m_pVT->IsValid()) { - RearrangePart(CPVT_WordRange(wpOld, wpNew)); - ScrollToCaret(); - Refresh(); - SetCaretOrigin(); - SetCaretInfo(); - } -} - -bool CFX_Edit::Redo() { - if (m_bEnableUndo) { - if (m_Undo.CanRedo()) { - m_Undo.Redo(); - return true; - } - } - - return false; -} - -bool CFX_Edit::Undo() { - if (m_bEnableUndo) { - if (m_Undo.CanUndo()) { - m_Undo.Undo(); - return true; - } - } - - return false; -} - -void CFX_Edit::SetCaretOrigin() { - if (!m_pVT->IsValid()) - return; - - CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); - pIterator->SetAt(m_wpCaret); - CPVT_Word word; - CPVT_Line line; - if (pIterator->GetWord(word)) { - m_ptCaret.x = word.ptWord.x + word.fWidth; - m_ptCaret.y = word.ptWord.y; - } else if (pIterator->GetLine(line)) { - m_ptCaret.x = line.ptLine.x; - m_ptCaret.y = line.ptLine.y; - } -} - -int32_t CFX_Edit::WordPlaceToWordIndex(const CPVT_WordPlace& place) const { - if (m_pVT->IsValid()) - return m_pVT->WordPlaceToWordIndex(place); - - return -1; -} - -CPVT_WordPlace CFX_Edit::WordIndexToWordPlace(int32_t index) const { - if (m_pVT->IsValid()) - return m_pVT->WordIndexToWordPlace(index); - - return CPVT_WordPlace(); -} - -bool CFX_Edit::IsTextFull() const { - int32_t nTotalWords = m_pVT->GetTotalWords(); - int32_t nLimitChar = m_pVT->GetLimitChar(); - int32_t nCharArray = m_pVT->GetCharArray(); - - return IsTextOverflow() || (nLimitChar > 0 && nTotalWords >= nLimitChar) || - (nCharArray > 0 && nTotalWords >= nCharArray); -} - -bool CFX_Edit::IsTextOverflow() const { - if (!m_bEnableScroll && !m_bEnableOverflow) { - CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); - CFX_FloatRect rcContent = m_pVT->GetContentRect(); - - if (m_pVT->IsMultiLine() && GetTotalLines() > 1 && - IsFloatBigger(rcContent.Height(), rcPlate.Height())) { - return true; - } - - if (IsFloatBigger(rcContent.Width(), rcPlate.Width())) - return true; - } - - return false; -} - -bool CFX_Edit::CanUndo() const { - if (m_bEnableUndo) { - return m_Undo.CanUndo(); - } - - return false; -} - -bool CFX_Edit::CanRedo() const { - if (m_bEnableUndo) { - return m_Undo.CanRedo(); - } - - return false; -} - -void CFX_Edit::EnableRefresh(bool bRefresh) { - m_bEnableRefresh = bRefresh; -} - -void CFX_Edit::EnableUndo(bool bUndo) { - m_bEnableUndo = bUndo; -} - -void CFX_Edit::EnableOprNotify(bool bNotify) { - m_bOprNotify = bNotify; -} - -CPVT_WordPlace CFX_Edit::DoInsertText(const CPVT_WordPlace& place, - const CFX_WideString& sText, - int32_t charset) { - CPVT_WordPlace wp = place; - - if (m_pVT->IsValid()) { - for (int32_t i = 0, sz = sText.GetLength(); i < sz; i++) { - uint16_t word = sText[i]; - switch (word) { - case 0x0D: - wp = m_pVT->InsertSection(wp, nullptr, nullptr); - if (sText[i + 1] == 0x0A) - i++; - break; - case 0x0A: - wp = m_pVT->InsertSection(wp, nullptr, nullptr); - if (sText[i + 1] == 0x0D) - i++; - break; - case 0x09: - word = 0x20; - default: - wp = m_pVT->InsertWord(wp, word, GetCharSetFromUnicode(word, charset), - nullptr); - break; - } - } - } - - return wp; -} - -int32_t CFX_Edit::GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset) { - if (IPVT_FontMap* pFontMap = GetFontMap()) - return pFontMap->CharSetFromUnicode(word, nOldCharset); - return nOldCharset; -} - -void CFX_Edit::AddEditUndoItem( - std::unique_ptr pEditUndoItem) { - if (m_pGroupUndoItem) - m_pGroupUndoItem->AddUndoItem(std::move(pEditUndoItem)); - else - m_Undo.AddItem(std::move(pEditUndoItem)); -} - -CFX_Edit_LineRectArray::CFX_Edit_LineRectArray() {} - -CFX_Edit_LineRectArray::~CFX_Edit_LineRectArray() {} - -void CFX_Edit_LineRectArray::operator=(CFX_Edit_LineRectArray&& that) { - m_LineRects = std::move(that.m_LineRects); -} - -void CFX_Edit_LineRectArray::Add(const CPVT_WordRange& wrLine, - const CFX_FloatRect& rcLine) { - m_LineRects.push_back(pdfium::MakeUnique(wrLine, rcLine)); -} - -int32_t CFX_Edit_LineRectArray::GetSize() const { - return pdfium::CollectionSize(m_LineRects); -} - -CFX_Edit_LineRect* CFX_Edit_LineRectArray::GetAt(int32_t nIndex) const { - if (nIndex < 0 || nIndex >= GetSize()) - return nullptr; - - return m_LineRects[nIndex].get(); -} - -CFX_Edit_Select::CFX_Edit_Select() {} - -CFX_Edit_Select::CFX_Edit_Select(const CPVT_WordPlace& begin, - const CPVT_WordPlace& end) { - Set(begin, end); -} - -CFX_Edit_Select::CFX_Edit_Select(const CPVT_WordRange& range) { - Set(range.BeginPos, range.EndPos); -} - -CPVT_WordRange CFX_Edit_Select::ConvertToWordRange() const { - return CPVT_WordRange(BeginPos, EndPos); -} - -void CFX_Edit_Select::Default() { - BeginPos.Default(); - EndPos.Default(); -} - -void CFX_Edit_Select::Set(const CPVT_WordPlace& begin, - const CPVT_WordPlace& end) { - BeginPos = begin; - EndPos = end; -} - -void CFX_Edit_Select::SetBeginPos(const CPVT_WordPlace& begin) { - BeginPos = begin; -} - -void CFX_Edit_Select::SetEndPos(const CPVT_WordPlace& end) { - EndPos = end; -} - -bool CFX_Edit_Select::IsExist() const { - return BeginPos != EndPos; -} - -CFX_Edit_RectArray::CFX_Edit_RectArray() {} - -CFX_Edit_RectArray::~CFX_Edit_RectArray() {} - -void CFX_Edit_RectArray::Clear() { - m_Rects.clear(); -} - -void CFX_Edit_RectArray::Add(const CFX_FloatRect& rect) { - // check for overlapped area - for (const auto& pRect : m_Rects) { - if (pRect && pRect->Contains(rect)) - return; - } - m_Rects.push_back(pdfium::MakeUnique(rect)); -} - -int32_t CFX_Edit_RectArray::GetSize() const { - return pdfium::CollectionSize(m_Rects); -} - -CFX_FloatRect* CFX_Edit_RectArray::GetAt(int32_t nIndex) const { - if (nIndex < 0 || nIndex >= GetSize()) - return nullptr; - - return m_Rects[nIndex].get(); -} diff --git a/fpdfsdk/fxedit/fxet_edit.h b/fpdfsdk/fxedit/fxet_edit.h deleted file mode 100644 index ab83af2e3bc56afdbb2454d0aa3e3b6e188f7640..0000000000000000000000000000000000000000 --- a/fpdfsdk/fxedit/fxet_edit.h +++ /dev/null @@ -1,545 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_FXEDIT_FXET_EDIT_H_ -#define FPDFSDK_FXEDIT_FXET_EDIT_H_ - -#include -#include -#include - -#include "core/fpdfdoc/cpvt_secprops.h" -#include "core/fpdfdoc/cpvt_wordprops.h" -#include "fpdfsdk/fxedit/fx_edit.h" - -class CFFL_FormFiller; -class CFX_Edit; -class CFX_Edit_Iterator; -class CFX_Edit_Provider; -class CFX_RenderDevice; -class CFX_SystemHandler; -class CPDF_PageObjectHolder; -class CPDF_TextObject; -class CPWL_Edit; -class CPWL_EditCtrl; - -class IFX_Edit_UndoItem; - -struct CFX_Edit_LineRect { - CFX_Edit_LineRect(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine) - : m_wrLine(wrLine), m_rcLine(rcLine) {} - - CPVT_WordRange m_wrLine; - CFX_FloatRect m_rcLine; -}; - -class CFX_Edit_LineRectArray { - public: - CFX_Edit_LineRectArray(); - virtual ~CFX_Edit_LineRectArray(); - - void operator=(CFX_Edit_LineRectArray&& rects); - void Add(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine); - - int32_t GetSize() const; - CFX_Edit_LineRect* GetAt(int32_t nIndex) const; - - private: - std::vector> m_LineRects; -}; - -class CFX_Edit_RectArray { - public: - CFX_Edit_RectArray(); - virtual ~CFX_Edit_RectArray(); - - void Clear(); - void Add(const CFX_FloatRect& rect); - - int32_t GetSize() const; - CFX_FloatRect* GetAt(int32_t nIndex) const; - - private: - std::vector> m_Rects; -}; - -class CFX_Edit_Refresh { - public: - CFX_Edit_Refresh(); - virtual ~CFX_Edit_Refresh(); - - void BeginRefresh(); - void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect); - void NoAnalyse(); - void AddRefresh(const CFX_FloatRect& rect); - const CFX_Edit_RectArray* GetRefreshRects() const; - void EndRefresh(); - - private: - CFX_Edit_LineRectArray m_NewLineRects; - CFX_Edit_LineRectArray m_OldLineRects; - CFX_Edit_RectArray m_RefreshRects; -}; - -class CFX_Edit_Select { - public: - CFX_Edit_Select(); - CFX_Edit_Select(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); - explicit CFX_Edit_Select(const CPVT_WordRange& range); - - void Default(); - void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); - void SetBeginPos(const CPVT_WordPlace& begin); - void SetEndPos(const CPVT_WordPlace& end); - - CPVT_WordRange ConvertToWordRange() const; - bool IsExist() const; - - CPVT_WordPlace BeginPos; - CPVT_WordPlace EndPos; -}; - -class CFX_Edit_Undo { - public: - explicit CFX_Edit_Undo(int32_t nBufsize); - virtual ~CFX_Edit_Undo(); - - void AddItem(std::unique_ptr pItem); - void Undo(); - void Redo(); - bool CanUndo() const; - bool CanRedo() const; - bool IsModified() const; - void Reset(); - - private: - void RemoveHeads(); - void RemoveTails(); - - std::deque> m_UndoItemStack; - size_t m_nCurUndoPos; - size_t m_nBufSize; - bool m_bModified; - bool m_bVirgin; - bool m_bWorking; -}; - -class IFX_Edit_UndoItem { - public: - virtual ~IFX_Edit_UndoItem() {} - - virtual void Undo() = 0; - virtual void Redo() = 0; - virtual CFX_WideString GetUndoTitle() const = 0; -}; - -class CFX_Edit_UndoItem : public IFX_Edit_UndoItem { - public: - CFX_Edit_UndoItem(); - ~CFX_Edit_UndoItem() override; - - CFX_WideString GetUndoTitle() const override; - - void SetFirst(bool bFirst); - void SetLast(bool bLast); - bool IsLast(); - - private: - bool m_bFirst; - bool m_bLast; -}; - -class CFX_Edit_GroupUndoItem : public IFX_Edit_UndoItem { - public: - explicit CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle); - ~CFX_Edit_GroupUndoItem() override; - - // IFX_Edit_UndoItem - void Undo() override; - void Redo() override; - CFX_WideString GetUndoTitle() const override; - - void AddUndoItem(std::unique_ptr pUndoItem); - void UpdateItems(); - - private: - CFX_WideString m_sTitle; - std::vector> m_Items; -}; - -class CFXEU_InsertWord : public CFX_Edit_UndoItem { - public: - CFXEU_InsertWord(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps); - ~CFXEU_InsertWord() override; - - // CFX_Edit_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_Edit* m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - uint16_t m_Word; - int32_t m_nCharset; - CPVT_WordProps m_WordProps; -}; - -class CFXEU_InsertReturn : public CFX_Edit_UndoItem { - public: - CFXEU_InsertReturn(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps); - ~CFXEU_InsertReturn() override; - - // CFX_Edit_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_Edit* m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - CPVT_SecProps m_SecProps; - CPVT_WordProps m_WordProps; -}; - -class CFXEU_Backspace : public CFX_Edit_UndoItem { - public: - CFXEU_Backspace(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_SecProps& SecProps, - const CPVT_WordProps& WordProps); - ~CFXEU_Backspace() override; - - // CFX_Edit_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_Edit* m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - uint16_t m_Word; - int32_t m_nCharset; - CPVT_SecProps m_SecProps; - CPVT_WordProps m_WordProps; -}; - -class CFXEU_Delete : public CFX_Edit_UndoItem { - public: - CFXEU_Delete(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_SecProps& SecProps, - const CPVT_WordProps& WordProps, - bool bSecEnd); - ~CFXEU_Delete() override; - - // CFX_Edit_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_Edit* m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - uint16_t m_Word; - int32_t m_nCharset; - CPVT_SecProps m_SecProps; - CPVT_WordProps m_WordProps; - bool m_bSecEnd; -}; - -class CFXEU_Clear : public CFX_Edit_UndoItem { - public: - CFXEU_Clear(CFX_Edit* pEdit, - const CPVT_WordRange& wrSel, - const CFX_WideString& swText); - ~CFXEU_Clear() override; - - // CFX_Edit_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_Edit* m_pEdit; - - CPVT_WordRange m_wrSel; - CFX_WideString m_swText; -}; - -class CFXEU_InsertText : public CFX_Edit_UndoItem { - public: - CFXEU_InsertText(CFX_Edit* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - const CFX_WideString& swText, - int32_t charset); - ~CFXEU_InsertText() override; - - // CFX_Edit_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_Edit* m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - CFX_WideString m_swText; - int32_t m_nCharset; -}; - -class CFX_Edit { - public: - static CFX_ByteString GetEditAppearanceStream(CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange, - bool bContinuous, - uint16_t SubWord); - static CFX_ByteString GetSelectAppearanceStream(CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange); - static void DrawEdit(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - CFX_Edit* pEdit, - FX_COLORREF crTextFill, - const CFX_FloatRect& rcClip, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange, - CFX_SystemHandler* pSystemHandler, - CFFL_FormFiller* pFFLData); - - CFX_Edit(); - ~CFX_Edit(); - - void SetFontMap(IPVT_FontMap* pFontMap); - void SetNotify(CPWL_EditCtrl* pNotify); - void SetOprNotify(CPWL_Edit* pOprNotify); - - // Returns an iterator for the contents. Should not be released. - CFX_Edit_Iterator* GetIterator(); - IPVT_FontMap* GetFontMap(); - void Initialize(); - - // Set the bounding box of the text area. - void SetPlateRect(const CFX_FloatRect& rect); - void SetScrollPos(const CFX_PointF& point); - - // Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right]) - void SetAlignmentH(int32_t nFormat, bool bPaint); - // Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right]) - void SetAlignmentV(int32_t nFormat, bool bPaint); - - // Set the substitution character for hidden text. - void SetPasswordChar(uint16_t wSubWord, bool bPaint); - - // Set the maximum number of words in the text. - void SetLimitChar(int32_t nLimitChar); - void SetCharArray(int32_t nCharArray); - void SetCharSpace(FX_FLOAT fCharSpace); - void SetMultiLine(bool bMultiLine, bool bPaint); - void SetAutoReturn(bool bAuto, bool bPaint); - void SetAutoFontSize(bool bAuto, bool bPaint); - void SetAutoScroll(bool bAuto, bool bPaint); - void SetFontSize(FX_FLOAT fFontSize); - void SetTextOverflow(bool bAllowed, bool bPaint); - void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl); - void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl); - void OnVK_UP(bool bShift, bool bCtrl); - void OnVK_DOWN(bool bShift, bool bCtrl); - void OnVK_LEFT(bool bShift, bool bCtrl); - void OnVK_RIGHT(bool bShift, bool bCtrl); - void OnVK_HOME(bool bShift, bool bCtrl); - void OnVK_END(bool bShift, bool bCtrl); - void SetText(const CFX_WideString& sText); - bool InsertWord(uint16_t word, int32_t charset); - bool InsertReturn(); - bool Backspace(); - bool Delete(); - bool Clear(); - bool InsertText(const CFX_WideString& sText, int32_t charset); - bool Redo(); - bool Undo(); - int32_t WordPlaceToWordIndex(const CPVT_WordPlace& place) const; - CPVT_WordPlace WordIndexToWordPlace(int32_t index) const; - CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const; - int32_t GetCaret() const; - CPVT_WordPlace GetCaretWordPlace() const; - CFX_WideString GetSelText() const; - CFX_WideString GetText() const; - FX_FLOAT GetFontSize() const; - uint16_t GetPasswordChar() const; - CFX_PointF GetScrollPos() const; - int32_t GetCharArray() const; - CFX_FloatRect GetContentRect() const; - CFX_WideString GetRangeText(const CPVT_WordRange& range) const; - int32_t GetHorzScale() const; - FX_FLOAT GetCharSpace() const; - int32_t GetTotalWords() const; - void SetSel(int32_t nStartChar, int32_t nEndChar); - void GetSel(int32_t& nStartChar, int32_t& nEndChar) const; - void SelectAll(); - void SelectNone(); - bool IsSelected() const; - void Paint(); - void EnableRefresh(bool bRefresh); - void RefreshWordRange(const CPVT_WordRange& wr); - void SetCaret(int32_t nPos); - CPVT_WordRange GetWholeWordRange() const; - CPVT_WordRange GetSelectWordRange() const; - void EnableUndo(bool bUndo); - void EnableOprNotify(bool bNotify); - bool IsTextFull() const; - bool IsTextOverflow() const; - bool CanUndo() const; - bool CanRedo() const; - CPVT_WordRange GetVisibleWordRange() const; - - bool Empty(); - - CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place, - const CFX_WideString& sText, - int32_t charset); - int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset); - - int32_t GetTotalLines() const; - - private: - friend class CFX_Edit_Iterator; - friend class CFXEU_InsertWord; - friend class CFXEU_InsertReturn; - friend class CFXEU_Backspace; - friend class CFXEU_Delete; - friend class CFXEU_Clear; - friend class CFXEU_InsertText; - - void SetSel(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); - - void RearrangeAll(); - void RearrangePart(const CPVT_WordRange& range); - void ScrollToCaret(); - void SetScrollInfo(); - void SetScrollPosX(FX_FLOAT fx); - void SetScrollPosY(FX_FLOAT fy); - void SetScrollLimit(); - void SetContentChanged(); - - bool InsertWord(uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps, - bool bAddUndo, - bool bPaint); - bool InsertReturn(const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps, - bool bAddUndo, - bool bPaint); - bool Backspace(bool bAddUndo, bool bPaint); - bool Delete(bool bAddUndo, bool bPaint); - bool Clear(bool bAddUndo, bool bPaint); - bool InsertText(const CFX_WideString& sText, - int32_t charset, - bool bAddUndo, - bool bPaint); - void PaintInsertText(const CPVT_WordPlace& wpOld, - const CPVT_WordPlace& wpNew); - - inline CFX_PointF VTToEdit(const CFX_PointF& point) const; - inline CFX_PointF EditToVT(const CFX_PointF& point) const; - inline CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const; - - void Refresh(); - void RefreshPushLineRects(const CPVT_WordRange& wr); - - void SetCaret(const CPVT_WordPlace& place); - void SetCaretInfo(); - void SetCaretOrigin(); - - void AddEditUndoItem(std::unique_ptr pEditUndoItem); - - private: - std::unique_ptr m_pVT; - CPWL_EditCtrl* m_pNotify; - CPWL_Edit* m_pOprNotify; - std::unique_ptr m_pVTProvider; - CPVT_WordPlace m_wpCaret; - CPVT_WordPlace m_wpOldCaret; - CFX_Edit_Select m_SelState; - CFX_PointF m_ptScrollPos; - CFX_PointF m_ptRefreshScrollPos; - bool m_bEnableScroll; - std::unique_ptr m_pIterator; - CFX_Edit_Refresh m_Refresh; - CFX_PointF m_ptCaret; - CFX_Edit_Undo m_Undo; - int32_t m_nAlignment; - bool m_bNotifyFlag; - bool m_bEnableOverflow; - bool m_bEnableRefresh; - CFX_FloatRect m_rcOldContent; - bool m_bEnableUndo; - bool m_bOprNotify; - CFX_Edit_GroupUndoItem* m_pGroupUndoItem; -}; - -class CFX_Edit_Iterator { - public: - CFX_Edit_Iterator(CFX_Edit* pEdit, CPDF_VariableText::Iterator* pVTIterator); - ~CFX_Edit_Iterator(); - - bool NextWord(); - bool PrevWord(); - bool GetWord(CPVT_Word& word) const; - bool GetLine(CPVT_Line& line) const; - bool GetSection(CPVT_Section& section) const; - void SetAt(int32_t nWordIndex); - void SetAt(const CPVT_WordPlace& place); - const CPVT_WordPlace& GetAt() const; - - private: - CFX_Edit* m_pEdit; - CPDF_VariableText::Iterator* m_pVTIterator; -}; - -class CFX_Edit_Provider : public CPDF_VariableText::Provider { - public: - explicit CFX_Edit_Provider(IPVT_FontMap* pFontMap); - ~CFX_Edit_Provider() override; - - IPVT_FontMap* GetFontMap(); - - // CPDF_VariableText::Provider: - int32_t GetCharWidth(int32_t nFontIndex, uint16_t word) override; - int32_t GetTypeAscent(int32_t nFontIndex) override; - int32_t GetTypeDescent(int32_t nFontIndex) override; - int32_t GetWordFontIndex(uint16_t word, - int32_t charset, - int32_t nFontIndex) override; - int32_t GetDefaultFontIndex() override; - bool IsLatinWord(uint16_t word) override; - - private: - IPVT_FontMap* m_pFontMap; -}; - -#endif // FPDFSDK_FXEDIT_FXET_EDIT_H_ diff --git a/fpdfsdk/fxedit/fxet_list.cpp b/fpdfsdk/fxedit/fxet_list.cpp deleted file mode 100644 index 39877c955fe40aed8467e1217f5843d3f2321979..0000000000000000000000000000000000000000 --- a/fpdfsdk/fxedit/fxet_list.cpp +++ /dev/null @@ -1,784 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/fxedit/fxet_list.h" - -#include "core/fpdfdoc/cpvt_word.h" -#include "fpdfsdk/fxedit/fxet_edit.h" -#include "fpdfsdk/pdfwindow/PWL_ListBox.h" - -CFX_ListItem::CFX_ListItem() - : m_pEdit(new CFX_Edit), - m_bSelected(false), - m_rcListItem(0.0f, 0.0f, 0.0f, 0.0f) { - m_pEdit->SetAlignmentV(1, true); - m_pEdit->Initialize(); -} - -CFX_ListItem::~CFX_ListItem() { -} - -void CFX_ListItem::SetFontMap(IPVT_FontMap* pFontMap) { - m_pEdit->SetFontMap(pFontMap); -} - -CFX_Edit* CFX_ListItem::GetEdit() const { - return m_pEdit.get(); -} - -CFX_Edit_Iterator* CFX_ListItem::GetIterator() const { - return m_pEdit->GetIterator(); -} - -void CFX_ListItem::SetRect(const CLST_Rect& rect) { - m_rcListItem = rect; -} - -CLST_Rect CFX_ListItem::GetRect() const { - return m_rcListItem; -} - -bool CFX_ListItem::IsSelected() const { - return m_bSelected; -} - -void CFX_ListItem::SetSelect(bool bSelected) { - m_bSelected = bSelected; -} - -void CFX_ListItem::SetText(const CFX_WideString& text) { - m_pEdit->SetText(text); -} - -void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize) { - m_pEdit->SetFontSize(fFontSize); -} - -FX_FLOAT CFX_ListItem::GetItemHeight() const { - return m_pEdit->GetContentRect().Height(); -} - -uint16_t CFX_ListItem::GetFirstChar() const { - CPVT_Word word; - CFX_Edit_Iterator* pIterator = GetIterator(); - pIterator->SetAt(1); - pIterator->GetWord(word); - return word.Word; -} - -CFX_WideString CFX_ListItem::GetText() const { - return m_pEdit->GetText(); -} - -CFX_ListContainer::CFX_ListContainer() {} - -CFX_ListContainer::~CFX_ListContainer() {} - -void CFX_ListContainer::SetPlateRect(const CFX_FloatRect& rect) { - m_rcPlate = rect; -} - -CPLST_Select::CPLST_Select() {} - -CPLST_Select::~CPLST_Select() { - for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) - delete m_aItems.GetAt(i); - - m_aItems.RemoveAll(); -} - -void CPLST_Select::Add(int32_t nItemIndex) { - int32_t nIndex = Find(nItemIndex); - - if (nIndex < 0) { - m_aItems.Add(new CPLST_Select_Item(nItemIndex, 1)); - } else { - if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) { - pItem->nState = 1; - } - } -} - -void CPLST_Select::Add(int32_t nBeginIndex, int32_t nEndIndex) { - if (nBeginIndex > nEndIndex) { - int32_t nTemp = nEndIndex; - nEndIndex = nBeginIndex; - nBeginIndex = nTemp; - } - - for (int32_t i = nBeginIndex; i <= nEndIndex; i++) - Add(i); -} - -void CPLST_Select::Sub(int32_t nItemIndex) { - for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) { - if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) - if (pItem->nItemIndex == nItemIndex) - pItem->nState = -1; - } -} - -void CPLST_Select::Sub(int32_t nBeginIndex, int32_t nEndIndex) { - if (nBeginIndex > nEndIndex) { - int32_t nTemp = nEndIndex; - nEndIndex = nBeginIndex; - nBeginIndex = nTemp; - } - - for (int32_t i = nBeginIndex; i <= nEndIndex; i++) - Sub(i); -} - -int32_t CPLST_Select::Find(int32_t nItemIndex) const { - for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) { - if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) { - if (pItem->nItemIndex == nItemIndex) - return i; - } - } - - return -1; -} - -bool CPLST_Select::IsExist(int32_t nItemIndex) const { - return Find(nItemIndex) >= 0; -} - -int32_t CPLST_Select::GetCount() const { - return m_aItems.GetSize(); -} - -int32_t CPLST_Select::GetItemIndex(int32_t nIndex) const { - if (nIndex >= 0 && nIndex < m_aItems.GetSize()) - if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) - return pItem->nItemIndex; - - return -1; -} - -int32_t CPLST_Select::GetState(int32_t nIndex) const { - if (nIndex >= 0 && nIndex < m_aItems.GetSize()) - if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) - return pItem->nState; - - return 0; -} - -void CPLST_Select::DeselectAll() { - for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) { - if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) { - pItem->nState = -1; - } - } -} - -void CPLST_Select::Done() { - for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) { - if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) { - if (pItem->nState == -1) { - delete pItem; - m_aItems.RemoveAt(i); - } else { - pItem->nState = 0; - } - } - } -} - -CFX_ListCtrl::CFX_ListCtrl() - : m_pNotify(nullptr), - m_bNotifyFlag(false), - m_nSelItem(-1), - m_nFootIndex(-1), - m_bCtrlSel(false), - m_nCaretIndex(-1), - m_fFontSize(0.0f), - m_pFontMap(nullptr), - m_bMultiple(false) {} - -CFX_ListCtrl::~CFX_ListCtrl() { - Empty(); -} - -void CFX_ListCtrl::SetNotify(CPWL_List_Notify* pNotify) { - m_pNotify = pNotify; -} - -CFX_PointF CFX_ListCtrl::InToOut(const CFX_PointF& point) const { - CFX_FloatRect rcPlate = GetPlateRect(); - return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left), - point.y - (m_ptScrollPos.y - rcPlate.top)); -} - -CFX_PointF CFX_ListCtrl::OutToIn(const CFX_PointF& point) const { - CFX_FloatRect rcPlate = GetPlateRect(); - return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left), - point.y + (m_ptScrollPos.y - rcPlate.top)); -} - -CFX_FloatRect CFX_ListCtrl::InToOut(const CFX_FloatRect& rect) const { - CFX_PointF ptLeftBottom = InToOut(CFX_PointF(rect.left, rect.bottom)); - CFX_PointF ptRightTop = InToOut(CFX_PointF(rect.right, rect.top)); - return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, - ptRightTop.y); -} - -CFX_FloatRect CFX_ListCtrl::OutToIn(const CFX_FloatRect& rect) const { - CFX_PointF ptLeftBottom = OutToIn(CFX_PointF(rect.left, rect.bottom)); - CFX_PointF ptRightTop = OutToIn(CFX_PointF(rect.right, rect.top)); - return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, - ptRightTop.y); -} - -void CFX_ListCtrl::OnMouseDown(const CFX_PointF& point, - bool bShift, - bool bCtrl) { - int32_t nHitIndex = GetItemIndex(point); - - if (IsMultipleSel()) { - if (bCtrl) { - if (IsItemSelected(nHitIndex)) { - m_aSelItems.Sub(nHitIndex); - SelectItems(); - m_bCtrlSel = false; - } else { - m_aSelItems.Add(nHitIndex); - SelectItems(); - m_bCtrlSel = true; - } - - m_nFootIndex = nHitIndex; - } else if (bShift) { - m_aSelItems.DeselectAll(); - m_aSelItems.Add(m_nFootIndex, nHitIndex); - SelectItems(); - } else { - m_aSelItems.DeselectAll(); - m_aSelItems.Add(nHitIndex); - SelectItems(); - - m_nFootIndex = nHitIndex; - } - - SetCaret(nHitIndex); - } else { - SetSingleSelect(nHitIndex); - } - - if (!IsItemVisible(nHitIndex)) - ScrollToListItem(nHitIndex); -} - -void CFX_ListCtrl::OnMouseMove(const CFX_PointF& point, - bool bShift, - bool bCtrl) { - int32_t nHitIndex = GetItemIndex(point); - - if (IsMultipleSel()) { - if (bCtrl) { - if (m_bCtrlSel) - m_aSelItems.Add(m_nFootIndex, nHitIndex); - else - m_aSelItems.Sub(m_nFootIndex, nHitIndex); - - SelectItems(); - } else { - m_aSelItems.DeselectAll(); - m_aSelItems.Add(m_nFootIndex, nHitIndex); - SelectItems(); - } - - SetCaret(nHitIndex); - } else { - SetSingleSelect(nHitIndex); - } - - if (!IsItemVisible(nHitIndex)) - ScrollToListItem(nHitIndex); -} - -void CFX_ListCtrl::OnVK(int32_t nItemIndex, bool bShift, bool bCtrl) { - if (IsMultipleSel()) { - if (nItemIndex >= 0 && nItemIndex < GetCount()) { - if (bCtrl) { - } else if (bShift) { - m_aSelItems.DeselectAll(); - m_aSelItems.Add(m_nFootIndex, nItemIndex); - SelectItems(); - } else { - m_aSelItems.DeselectAll(); - m_aSelItems.Add(nItemIndex); - SelectItems(); - m_nFootIndex = nItemIndex; - } - - SetCaret(nItemIndex); - } - } else { - SetSingleSelect(nItemIndex); - } - - if (!IsItemVisible(nItemIndex)) - ScrollToListItem(nItemIndex); -} - -void CFX_ListCtrl::OnVK_UP(bool bShift, bool bCtrl) { - OnVK(IsMultipleSel() ? GetCaret() - 1 : GetSelect() - 1, bShift, bCtrl); -} - -void CFX_ListCtrl::OnVK_DOWN(bool bShift, bool bCtrl) { - OnVK(IsMultipleSel() ? GetCaret() + 1 : GetSelect() + 1, bShift, bCtrl); -} - -void CFX_ListCtrl::OnVK_LEFT(bool bShift, bool bCtrl) { - OnVK(0, bShift, bCtrl); -} - -void CFX_ListCtrl::OnVK_RIGHT(bool bShift, bool bCtrl) { - OnVK(GetCount() - 1, bShift, bCtrl); -} - -void CFX_ListCtrl::OnVK_HOME(bool bShift, bool bCtrl) { - OnVK(0, bShift, bCtrl); -} - -void CFX_ListCtrl::OnVK_END(bool bShift, bool bCtrl) { - OnVK(GetCount() - 1, bShift, bCtrl); -} - -bool CFX_ListCtrl::OnChar(uint16_t nChar, bool bShift, bool bCtrl) { - int32_t nIndex = GetLastSelected(); - int32_t nFindIndex = FindNext(nIndex, nChar); - - if (nFindIndex != nIndex) { - OnVK(nFindIndex, bShift, bCtrl); - return true; - } - return false; -} - -void CFX_ListCtrl::SetPlateRect(const CFX_FloatRect& rect) { - CFX_ListContainer::SetPlateRect(rect); - m_ptScrollPos.x = rect.left; - SetScrollPos(CFX_PointF(rect.left, rect.top)); - ReArrange(0); - InvalidateItem(-1); -} - -CFX_FloatRect CFX_ListCtrl::GetItemRect(int32_t nIndex) const { - return InToOut(GetItemRectInternal(nIndex)); -} - -CFX_FloatRect CFX_ListCtrl::GetItemRectInternal(int32_t nIndex) const { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { - CFX_FloatRect rcItem = pListItem->GetRect(); - rcItem.left = 0.0f; - rcItem.right = GetPlateRect().Width(); - return InnerToOuter(CLST_Rect(rcItem)); - } - - return CFX_FloatRect(); -} - -int32_t CFX_ListCtrl::GetCaret() const { - return m_nCaretIndex; -} - -int32_t CFX_ListCtrl::GetSelect() const { - return m_nSelItem; -} - -void CFX_ListCtrl::AddString(const CFX_WideString& str) { - AddItem(str); - ReArrange(GetCount() - 1); -} - -void CFX_ListCtrl::SetMultipleSelect(int32_t nItemIndex, bool bSelected) { - if (!IsValid(nItemIndex)) - return; - - if (bSelected != IsItemSelected(nItemIndex)) { - if (bSelected) { - SetItemSelect(nItemIndex, true); - InvalidateItem(nItemIndex); - } else { - SetItemSelect(nItemIndex, false); - InvalidateItem(nItemIndex); - } - } -} - -void CFX_ListCtrl::SetSingleSelect(int32_t nItemIndex) { - if (!IsValid(nItemIndex)) - return; - - if (m_nSelItem != nItemIndex) { - if (m_nSelItem >= 0) { - SetItemSelect(m_nSelItem, false); - InvalidateItem(m_nSelItem); - } - - SetItemSelect(nItemIndex, true); - InvalidateItem(nItemIndex); - m_nSelItem = nItemIndex; - } -} - -void CFX_ListCtrl::SetCaret(int32_t nItemIndex) { - if (!IsValid(nItemIndex)) - return; - - if (IsMultipleSel()) { - int32_t nOldIndex = m_nCaretIndex; - - if (nOldIndex != nItemIndex) { - m_nCaretIndex = nItemIndex; - InvalidateItem(nOldIndex); - InvalidateItem(nItemIndex); - } - } -} - -void CFX_ListCtrl::InvalidateItem(int32_t nItemIndex) { - if (m_pNotify) { - if (nItemIndex == -1) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - CFX_FloatRect rcRefresh = GetPlateRect(); - m_pNotify->IOnInvalidateRect(&rcRefresh); - m_bNotifyFlag = false; - } - } else { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - CFX_FloatRect rcRefresh = GetItemRect(nItemIndex); - rcRefresh.left -= 1.0f; - rcRefresh.right += 1.0f; - rcRefresh.bottom -= 1.0f; - rcRefresh.top += 1.0f; - - m_pNotify->IOnInvalidateRect(&rcRefresh); - m_bNotifyFlag = false; - } - } - } -} - -void CFX_ListCtrl::SelectItems() { - for (int32_t i = 0, sz = m_aSelItems.GetCount(); i < sz; i++) { - int32_t nItemIndex = m_aSelItems.GetItemIndex(i); - int32_t nState = m_aSelItems.GetState(i); - - switch (nState) { - case 1: - SetMultipleSelect(nItemIndex, true); - break; - case -1: - SetMultipleSelect(nItemIndex, false); - break; - } - } - - m_aSelItems.Done(); -} - -void CFX_ListCtrl::Select(int32_t nItemIndex) { - if (!IsValid(nItemIndex)) - return; - - if (IsMultipleSel()) { - m_aSelItems.Add(nItemIndex); - SelectItems(); - } else { - SetSingleSelect(nItemIndex); - } -} - -bool CFX_ListCtrl::IsItemVisible(int32_t nItemIndex) const { - CFX_FloatRect rcPlate = GetPlateRect(); - CFX_FloatRect rcItem = GetItemRect(nItemIndex); - - return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top; -} - -void CFX_ListCtrl::ScrollToListItem(int32_t nItemIndex) { - if (!IsValid(nItemIndex)) - return; - - CFX_FloatRect rcPlate = GetPlateRect(); - CFX_FloatRect rcItem = GetItemRectInternal(nItemIndex); - CFX_FloatRect rcItemCtrl = GetItemRect(nItemIndex); - - if (IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) { - if (IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) { - SetScrollPosY(rcItem.bottom + rcPlate.Height()); - } - } else if (IsFloatBigger(rcItemCtrl.top, rcPlate.top)) { - if (IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) { - SetScrollPosY(rcItem.top); - } - } -} - -void CFX_ListCtrl::SetScrollInfo() { - if (m_pNotify) { - CFX_FloatRect rcPlate = GetPlateRect(); - CFX_FloatRect rcContent = GetContentRectInternal(); - - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, - rcContent.bottom, rcContent.top, - GetFirstHeight(), rcPlate.Height()); - m_bNotifyFlag = false; - } - } -} - -void CFX_ListCtrl::SetScrollPos(const CFX_PointF& point) { - SetScrollPosY(point.y); -} - -void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy) { - if (!IsFloatEqual(m_ptScrollPos.y, fy)) { - CFX_FloatRect rcPlate = GetPlateRect(); - CFX_FloatRect rcContent = GetContentRectInternal(); - - if (rcPlate.Height() > rcContent.Height()) { - fy = rcPlate.top; - } else { - if (IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) { - fy = rcContent.bottom + rcPlate.Height(); - } else if (IsFloatBigger(fy, rcContent.top)) { - fy = rcContent.top; - } - } - - m_ptScrollPos.y = fy; - InvalidateItem(-1); - - if (m_pNotify) { - if (!m_bNotifyFlag) { - m_bNotifyFlag = true; - m_pNotify->IOnSetScrollPosY(fy); - m_bNotifyFlag = false; - } - } - } -} - -CFX_FloatRect CFX_ListCtrl::GetContentRectInternal() const { - return InnerToOuter(CFX_ListContainer::GetContentRect()); -} - -CFX_FloatRect CFX_ListCtrl::GetContentRect() const { - return InToOut(GetContentRectInternal()); -} - -void CFX_ListCtrl::ReArrange(int32_t nItemIndex) { - FX_FLOAT fPosY = 0.0f; - - if (CFX_ListItem* pPrevItem = m_aListItems.GetAt(nItemIndex - 1)) - fPosY = pPrevItem->GetRect().bottom; - - for (int32_t i = nItemIndex, sz = m_aListItems.GetSize(); i < sz; i++) { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { - FX_FLOAT fListItemHeight = pListItem->GetItemHeight(); - pListItem->SetRect(CLST_Rect(0.0f, fPosY, 0.0f, fPosY + fListItemHeight)); - fPosY += fListItemHeight; - } - } - - SetContentRect(CLST_Rect(0.0f, 0.0f, 0.0f, fPosY)); - SetScrollInfo(); -} - -void CFX_ListCtrl::SetTopItem(int32_t nIndex) { - if (IsValid(nIndex)) { - GetPlateRect(); - CFX_FloatRect rcItem = GetItemRectInternal(nIndex); - SetScrollPosY(rcItem.top); - } -} - -int32_t CFX_ListCtrl::GetTopItem() const { - int32_t nItemIndex = GetItemIndex(GetBTPoint()); - - if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1)) - nItemIndex += 1; - - return nItemIndex; -} - -void CFX_ListCtrl::Empty() { - for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) - delete m_aListItems.GetAt(i); - - m_aListItems.RemoveAll(); - - InvalidateItem(-1); -} - -void CFX_ListCtrl::Cancel() { - m_aSelItems.DeselectAll(); -} - -int32_t CFX_ListCtrl::GetItemIndex(const CFX_PointF& point) const { - CFX_PointF pt = OuterToInner(OutToIn(point)); - - bool bFirst = true; - bool bLast = true; - - for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { - CLST_Rect rcListItem = pListItem->GetRect(); - - if (IsFloatBigger(pt.y, rcListItem.top)) { - bFirst = false; - } - - if (IsFloatSmaller(pt.y, rcListItem.bottom)) { - bLast = false; - } - - if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) { - return i; - } - } - } - - if (bFirst) - return 0; - if (bLast) - return m_aListItems.GetSize() - 1; - - return -1; -} - -CFX_WideString CFX_ListCtrl::GetText() const { - if (IsMultipleSel()) - return GetItemText(m_nCaretIndex); - return GetItemText(m_nSelItem); -} - -void CFX_ListCtrl::SetFontMap(IPVT_FontMap* pFontMap) { - m_pFontMap = pFontMap; -} - -void CFX_ListCtrl::SetFontSize(FX_FLOAT fFontSize) { - m_fFontSize = fFontSize; -} - -void CFX_ListCtrl::AddItem(const CFX_WideString& str) { - CFX_ListItem* pListItem = new CFX_ListItem(); - pListItem->SetFontMap(m_pFontMap); - pListItem->SetFontSize(m_fFontSize); - pListItem->SetText(str); - m_aListItems.Add(pListItem); -} - -CFX_Edit* CFX_ListCtrl::GetItemEdit(int32_t nIndex) const { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { - return pListItem->GetEdit(); - } - - return nullptr; -} - -int32_t CFX_ListCtrl::GetCount() const { - return m_aListItems.GetSize(); -} - -CFX_FloatRect CFX_ListCtrl::GetPlateRect() const { - return CFX_ListContainer::GetPlateRect(); -} - -FX_FLOAT CFX_ListCtrl::GetFontSize() const { - return m_fFontSize; -} - -FX_FLOAT CFX_ListCtrl::GetFirstHeight() const { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(0)) { - return pListItem->GetItemHeight(); - } - - return 1.0f; -} - -int32_t CFX_ListCtrl::GetFirstSelected() const { - for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { - if (pListItem->IsSelected()) - return i; - } - } - return -1; -} - -int32_t CFX_ListCtrl::GetLastSelected() const { - for (int32_t i = m_aListItems.GetSize() - 1; i >= 0; i--) { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { - if (pListItem->IsSelected()) - return i; - } - } - return -1; -} - -FX_WCHAR CFX_ListCtrl::Toupper(FX_WCHAR c) const { - if ((c >= 'a') && (c <= 'z')) - c = c - ('a' - 'A'); - return c; -} - -int32_t CFX_ListCtrl::FindNext(int32_t nIndex, FX_WCHAR nChar) const { - int32_t nCircleIndex = nIndex; - - for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { - nCircleIndex++; - if (nCircleIndex >= sz) - nCircleIndex = 0; - - if (CFX_ListItem* pListItem = m_aListItems.GetAt(nCircleIndex)) { - if (Toupper(pListItem->GetFirstChar()) == Toupper(nChar)) - return nCircleIndex; - } - } - - return nCircleIndex; -} - -bool CFX_ListCtrl::IsItemSelected(int32_t nIndex) const { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) - return pListItem->IsSelected(); - return false; -} - -void CFX_ListCtrl::SetItemSelect(int32_t nItemIndex, bool bSelected) { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) { - pListItem->SetSelect(bSelected); - } -} - -void CFX_ListCtrl::SetMultipleSel(bool bMultiple) { - m_bMultiple = bMultiple; -} - -bool CFX_ListCtrl::IsMultipleSel() const { - return m_bMultiple; -} - -bool CFX_ListCtrl::IsValid(int32_t nItemIndex) const { - return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize(); -} - -CFX_WideString CFX_ListCtrl::GetItemText(int32_t nIndex) const { - if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { - return pListItem->GetText(); - } - - return L""; -} diff --git a/fpdfsdk/fxedit/fxet_list.h b/fpdfsdk/fxedit/fxet_list.h deleted file mode 100644 index 01e18bc000c1f897bbd7401125fcbfac74ce1a5d..0000000000000000000000000000000000000000 --- a/fpdfsdk/fxedit/fxet_list.h +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_FXEDIT_FXET_LIST_H_ -#define FPDFSDK_FXEDIT_FXET_LIST_H_ - -#include - -#include "core/fxcrt/fx_coordinates.h" -#include "fpdfsdk/fxedit/fx_edit.h" - -class CFX_Edit; -class CFX_Edit_Iterator; -class CPWL_List_Notify; - -class CLST_Rect : public CFX_FloatRect { - public: - CLST_Rect() { left = top = right = bottom = 0.0f; } - - CLST_Rect(FX_FLOAT other_left, - FX_FLOAT other_top, - FX_FLOAT other_right, - FX_FLOAT other_bottom) { - left = other_left; - top = other_top; - right = other_right; - bottom = other_bottom; - } - - explicit CLST_Rect(const CFX_FloatRect& rect) { - left = rect.left; - top = rect.top; - right = rect.right; - bottom = rect.bottom; - } - - ~CLST_Rect() {} - - void Default() { left = top = right = bottom = 0.0f; } - - const CLST_Rect operator=(const CFX_FloatRect& rect) { - left = rect.left; - top = rect.top; - right = rect.right; - bottom = rect.bottom; - - return *this; - } - - bool operator==(const CLST_Rect& rect) const { - return FXSYS_memcmp(this, &rect, sizeof(CLST_Rect)) == 0; - } - - bool operator!=(const CLST_Rect& rect) const { return !(*this == rect); } - - FX_FLOAT Width() const { return right - left; } - - FX_FLOAT Height() const { - if (top > bottom) - return top - bottom; - return bottom - top; - } - - CFX_PointF LeftTop() const { return CFX_PointF(left, top); } - - CFX_PointF RightBottom() const { return CFX_PointF(right, bottom); } - - const CLST_Rect operator+=(const CFX_PointF& point) { - left += point.x; - right += point.x; - top += point.y; - bottom += point.y; - - return *this; - } - - const CLST_Rect operator-=(const CFX_PointF& point) { - left -= point.x; - right -= point.x; - top -= point.y; - bottom -= point.y; - - return *this; - } - - CLST_Rect operator+(const CFX_PointF& point) const { - return CLST_Rect(left + point.x, top + point.y, right + point.x, - bottom + point.y); - } - - CLST_Rect operator-(const CFX_PointF& point) const { - return CLST_Rect(left - point.x, top - point.y, right - point.x, - bottom - point.y); - } -}; - -class CFX_ListItem final { - public: - CFX_ListItem(); - ~CFX_ListItem(); - - void SetFontMap(IPVT_FontMap* pFontMap); - CFX_Edit* GetEdit() const; - - void SetRect(const CLST_Rect& rect); - void SetSelect(bool bSelected); - void SetText(const CFX_WideString& text); - void SetFontSize(FX_FLOAT fFontSize); - CFX_WideString GetText() const; - - CLST_Rect GetRect() const; - bool IsSelected() const; - FX_FLOAT GetItemHeight() const; - uint16_t GetFirstChar() const; - - private: - CFX_Edit_Iterator* GetIterator() const; - - std::unique_ptr m_pEdit; - bool m_bSelected; - CLST_Rect m_rcListItem; -}; - -class CFX_ListContainer { - public: - CFX_ListContainer(); - virtual ~CFX_ListContainer(); - - virtual void SetPlateRect(const CFX_FloatRect& rect); - - CFX_FloatRect GetPlateRect() const { return m_rcPlate; } - void SetContentRect(const CLST_Rect& rect) { m_rcContent = rect; } - CLST_Rect GetContentRect() const { return m_rcContent; } - CFX_PointF GetBTPoint() const { - return CFX_PointF(m_rcPlate.left, m_rcPlate.top); - } - CFX_PointF GetETPoint() const { - return CFX_PointF(m_rcPlate.right, m_rcPlate.bottom); - } - - public: - CFX_PointF InnerToOuter(const CFX_PointF& point) const { - return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y); - } - CFX_PointF OuterToInner(const CFX_PointF& point) const { - return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y); - } - CFX_FloatRect InnerToOuter(const CLST_Rect& rect) const { - CFX_PointF ptLeftTop = InnerToOuter(CFX_PointF(rect.left, rect.top)); - CFX_PointF ptRightBottom = - InnerToOuter(CFX_PointF(rect.right, rect.bottom)); - return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x, - ptLeftTop.y); - } - CLST_Rect OuterToInner(const CFX_FloatRect& rect) const { - CFX_PointF ptLeftTop = OuterToInner(CFX_PointF(rect.left, rect.top)); - CFX_PointF ptRightBottom = - OuterToInner(CFX_PointF(rect.right, rect.bottom)); - return CLST_Rect(ptLeftTop.x, ptLeftTop.y, ptRightBottom.x, - ptRightBottom.y); - } - - private: - CFX_FloatRect m_rcPlate; - CLST_Rect m_rcContent; // positive forever! -}; - -template -class CLST_ArrayTemplate : public CFX_ArrayTemplate { - public: - bool IsEmpty() { return CFX_ArrayTemplate::GetSize() <= 0; } - TYPE GetAt(int32_t nIndex) const { - if (nIndex >= 0 && nIndex < CFX_ArrayTemplate::GetSize()) - return CFX_ArrayTemplate::GetAt(nIndex); - return nullptr; - } - void RemoveAt(int32_t nIndex) { - if (nIndex >= 0 && nIndex < CFX_ArrayTemplate::GetSize()) - CFX_ArrayTemplate::RemoveAt(nIndex); - } -}; - -struct CPLST_Select_Item { - CPLST_Select_Item(int32_t other_nItemIndex, int32_t other_nState) { - nItemIndex = other_nItemIndex; - nState = other_nState; - } - - int32_t nItemIndex; - int32_t nState; // 0:normal select -1:to deselect 1: to select -}; - -class CPLST_Select { - public: - CPLST_Select(); - virtual ~CPLST_Select(); - - public: - void Add(int32_t nItemIndex); - void Add(int32_t nBeginIndex, int32_t nEndIndex); - void Sub(int32_t nItemIndex); - void Sub(int32_t nBeginIndex, int32_t nEndIndex); - bool IsExist(int32_t nItemIndex) const; - int32_t Find(int32_t nItemIndex) const; - int32_t GetCount() const; - int32_t GetItemIndex(int32_t nIndex) const; - int32_t GetState(int32_t nIndex) const; - void Done(); - void DeselectAll(); - - private: - CFX_ArrayTemplate m_aItems; -}; - -class CFX_ListCtrl : protected CFX_ListContainer { - public: - CFX_ListCtrl(); - ~CFX_ListCtrl() override; - - // CFX_ListContainer - void SetPlateRect(const CFX_FloatRect& rect) override; - - void SetNotify(CPWL_List_Notify* pNotify); - void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl); - void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl); - void OnVK_UP(bool bShift, bool bCtrl); - void OnVK_DOWN(bool bShift, bool bCtrl); - void OnVK_LEFT(bool bShift, bool bCtrl); - void OnVK_RIGHT(bool bShift, bool bCtrl); - void OnVK_HOME(bool bShift, bool bCtrl); - void OnVK_END(bool bShift, bool bCtrl); - void OnVK(int32_t nItemIndex, bool bShift, bool bCtrl); - bool OnChar(uint16_t nChar, bool bShift, bool bCtrl); - - void SetScrollPos(const CFX_PointF& point); - void ScrollToListItem(int32_t nItemIndex); - CFX_FloatRect GetItemRect(int32_t nIndex) const; - int32_t GetCaret() const; - int32_t GetSelect() const; - int32_t GetTopItem() const; - CFX_FloatRect GetContentRect() const; - int32_t GetItemIndex(const CFX_PointF& point) const; - void AddString(const CFX_WideString& str); - void SetTopItem(int32_t nIndex); - void Select(int32_t nItemIndex); - void SetCaret(int32_t nItemIndex); - void Empty(); - void Cancel(); - CFX_WideString GetText() const; - - void SetFontMap(IPVT_FontMap* pFontMap); - void SetFontSize(FX_FLOAT fFontSize); - CFX_FloatRect GetPlateRect() const; - FX_FLOAT GetFontSize() const; - CFX_Edit* GetItemEdit(int32_t nIndex) const; - int32_t GetCount() const; - bool IsItemSelected(int32_t nIndex) const; - FX_FLOAT GetFirstHeight() const; - void SetMultipleSel(bool bMultiple); - bool IsMultipleSel() const; - bool IsValid(int32_t nItemIndex) const; - int32_t FindNext(int32_t nIndex, FX_WCHAR nChar) const; - int32_t GetFirstSelected() const; - - CFX_PointF InToOut(const CFX_PointF& point) const; - CFX_PointF OutToIn(const CFX_PointF& point) const; - CFX_FloatRect InToOut(const CFX_FloatRect& rect) const; - CFX_FloatRect OutToIn(const CFX_FloatRect& rect) const; - - private: - void ReArrange(int32_t nItemIndex); - CFX_FloatRect GetItemRectInternal(int32_t nIndex) const; - CFX_FloatRect GetContentRectInternal() const; - void SetMultipleSelect(int32_t nItemIndex, bool bSelected); - void SetSingleSelect(int32_t nItemIndex); - void InvalidateItem(int32_t nItemIndex); - void SelectItems(); - bool IsItemVisible(int32_t nItemIndex) const; - void SetScrollInfo(); - void SetScrollPosY(FX_FLOAT fy); - void AddItem(const CFX_WideString& str); - CFX_WideString GetItemText(int32_t nIndex) const; - void SetItemSelect(int32_t nItemIndex, bool bSelected); - int32_t GetLastSelected() const; - FX_WCHAR Toupper(FX_WCHAR c) const; - - CPWL_List_Notify* m_pNotify; - bool m_bNotifyFlag; - CFX_PointF m_ptScrollPos; - CPLST_Select m_aSelItems; // for multiple - int32_t m_nSelItem; // for single - int32_t m_nFootIndex; // for multiple - bool m_bCtrlSel; // for multiple - int32_t m_nCaretIndex; // for multiple - CLST_ArrayTemplate m_aListItems; - FX_FLOAT m_fFontSize; - IPVT_FontMap* m_pFontMap; - bool m_bMultiple; -}; - -#endif // FPDFSDK_FXEDIT_FXET_LIST_H_ diff --git a/fpdfsdk/ipdfsdk_annothandler.h b/fpdfsdk/ipdfsdk_annothandler.h index 636d161feae2ef78510b62e17ec07927ebbc7a55..bffeac658be10c56f086ecdd1ad2b3e94bf6792b 100644 --- a/fpdfsdk/ipdfsdk_annothandler.h +++ b/fpdfsdk/ipdfsdk_annothandler.h @@ -7,7 +7,6 @@ #ifndef FPDFSDK_IPDFSDK_ANNOTHANDLER_H_ #define FPDFSDK_IPDFSDK_ANNOTHANDLER_H_ -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_coordinates.h" #include "fpdfsdk/cpdfsdk_annot.h" @@ -36,6 +35,9 @@ class IPDFSDK_AnnotHandler { virtual void ReleaseAnnot(CPDFSDK_Annot* pAnnot) = 0; virtual CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) = 0; + virtual WideString GetSelectedText(CPDFSDK_Annot* pAnnot) = 0; + virtual void ReplaceSelection(CPDFSDK_Annot* pAnnot, + const WideString& text) = 0; virtual bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) = 0; diff --git a/fpdfsdk/javascript/Annot.cpp b/fpdfsdk/javascript/Annot.cpp deleted file mode 100644 index 41c71ec411f2a4be5a6aaba2c0411301540bf316..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Annot.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2016 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 "fpdfsdk/javascript/Annot.h" - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" - -namespace { - -CPDFSDK_BAAnnot* ToBAAnnot(CPDFSDK_Annot* annot) { - return static_cast(annot); -} - -} // namespace - -JSConstSpec CJS_Annot::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Annot::PropertySpecs[] = { - {"hidden", get_hidden_static, set_hidden_static}, - {"name", get_name_static, set_name_static}, - {"type", get_type_static, set_type_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_Annot::MethodSpecs[] = {{0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Annot, Annot) - -Annot::Annot(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} - -Annot::~Annot() {} - -bool Annot::hidden(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - if (!m_pAnnot) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CPDF_Annot* pPDFAnnot = ToBAAnnot(m_pAnnot.Get())->GetPDFAnnot(); - vp << CPDF_Annot::IsAnnotationHidden(pPDFAnnot->GetAnnotDict()); - return true; - } - - bool bHidden; - vp >> bHidden; // May invalidate m_pAnnot. - if (!m_pAnnot) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - - uint32_t flags = ToBAAnnot(m_pAnnot.Get())->GetFlags(); - if (bHidden) { - flags |= ANNOTFLAG_HIDDEN; - flags |= ANNOTFLAG_INVISIBLE; - flags |= ANNOTFLAG_NOVIEW; - flags &= ~ANNOTFLAG_PRINT; - } else { - flags &= ~ANNOTFLAG_HIDDEN; - flags &= ~ANNOTFLAG_INVISIBLE; - flags &= ~ANNOTFLAG_NOVIEW; - flags |= ANNOTFLAG_PRINT; - } - ToBAAnnot(m_pAnnot.Get())->SetFlags(flags); - return true; -} - -bool Annot::name(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - if (!m_pAnnot) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - vp << ToBAAnnot(m_pAnnot.Get())->GetAnnotName(); - return true; - } - - CFX_WideString annotName; - vp >> annotName; // May invalidate m_pAnnot. - if (!m_pAnnot) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - - ToBAAnnot(m_pAnnot.Get())->SetAnnotName(annotName); - return true; -} - -bool Annot::type(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pAnnot) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - vp << CPDF_Annot::AnnotSubtypeToString( - ToBAAnnot(m_pAnnot.Get())->GetAnnotSubtype()); - return true; -} - -void Annot::SetSDKAnnot(CPDFSDK_BAAnnot* annot) { - m_pAnnot.Reset(annot); -} diff --git a/fpdfsdk/javascript/Annot.h b/fpdfsdk/javascript/Annot.h deleted file mode 100644 index d9757fa51485f61a853903fd83898f11fcb43750..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Annot.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 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 FPDFSDK_JAVASCRIPT_ANNOT_H_ -#define FPDFSDK_JAVASCRIPT_ANNOT_H_ - -#include - -#include "fpdfsdk/cpdfsdk_baannot.h" -#include "fpdfsdk/javascript/JS_Define.h" - -class Annot : public CJS_EmbedObj { - public: - explicit Annot(CJS_Object* pJSObject); - ~Annot() override; - - bool hidden(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool type(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - - void SetSDKAnnot(CPDFSDK_BAAnnot* annot); - - private: - CPDFSDK_Annot::ObservedPtr m_pAnnot; -}; - -class CJS_Annot : public CJS_Object { - public: - explicit CJS_Annot(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Annot() override {} - - DECLARE_JS_CLASS(); - JS_STATIC_PROP(hidden, Annot); - JS_STATIC_PROP(name, Annot); - JS_STATIC_PROP(type, Annot); -}; - -#endif // FPDFSDK_JAVASCRIPT_ANNOT_H_ diff --git a/fpdfsdk/javascript/Consts.cpp b/fpdfsdk/javascript/Consts.cpp deleted file mode 100644 index 82f9b4c94573e27603e9114f5788455c2915443a..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Consts.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/Consts.h" - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" - -JSConstSpec CJS_Border::ConstSpecs[] = { - {"s", JSConstSpec::String, 0, "solid"}, - {"b", JSConstSpec::String, 0, "beveled"}, - {"d", JSConstSpec::String, 0, "dashed"}, - {"i", JSConstSpec::String, 0, "inset"}, - {"u", JSConstSpec::String, 0, "underline"}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Border, border) - -JSConstSpec CJS_Display::ConstSpecs[] = {{"visible", JSConstSpec::Number, 0, 0}, - {"hidden", JSConstSpec::Number, 1, 0}, - {"noPrint", JSConstSpec::Number, 2, 0}, - {"noView", JSConstSpec::Number, 3, 0}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Display, display) - -JSConstSpec CJS_Font::ConstSpecs[] = { - {"Times", JSConstSpec::String, 0, "Times-Roman"}, - {"TimesB", JSConstSpec::String, 0, "Times-Bold"}, - {"TimesI", JSConstSpec::String, 0, "Times-Italic"}, - {"TimesBI", JSConstSpec::String, 0, "Times-BoldItalic"}, - {"Helv", JSConstSpec::String, 0, "Helvetica"}, - {"HelvB", JSConstSpec::String, 0, "Helvetica-Bold"}, - {"HelvI", JSConstSpec::String, 0, "Helvetica-Oblique"}, - {"HelvBI", JSConstSpec::String, 0, "Helvetica-BoldOblique"}, - {"Cour", JSConstSpec::String, 0, "Courier"}, - {"CourB", JSConstSpec::String, 0, "Courier-Bold"}, - {"CourI", JSConstSpec::String, 0, "Courier-Oblique"}, - {"CourBI", JSConstSpec::String, 0, "Courier-BoldOblique"}, - {"Symbol", JSConstSpec::String, 0, "Symbol"}, - {"ZapfD", JSConstSpec::String, 0, "ZapfDingbats"}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Font, font) - -JSConstSpec CJS_Highlight::ConstSpecs[] = { - {"n", JSConstSpec::String, 0, "none"}, - {"i", JSConstSpec::String, 0, "invert"}, - {"p", JSConstSpec::String, 0, "push"}, - {"o", JSConstSpec::String, 0, "outline"}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Highlight, highlight) - -JSConstSpec CJS_Position::ConstSpecs[] = { - {"textOnly", JSConstSpec::Number, 0, 0}, - {"iconOnly", JSConstSpec::Number, 1, 0}, - {"iconTextV", JSConstSpec::Number, 2, 0}, - {"textIconV", JSConstSpec::Number, 3, 0}, - {"iconTextH", JSConstSpec::Number, 4, 0}, - {"textIconH", JSConstSpec::Number, 5, 0}, - {"overlay", JSConstSpec::Number, 6, 0}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Position, position) - -JSConstSpec CJS_ScaleHow::ConstSpecs[] = { - {"proportional", JSConstSpec::Number, 0, 0}, - {"anamorphic", JSConstSpec::Number, 1, 0}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_ScaleHow, scaleHow) - -JSConstSpec CJS_ScaleWhen::ConstSpecs[] = { - {"always", JSConstSpec::Number, 0, 0}, - {"never", JSConstSpec::Number, 1, 0}, - {"tooBig", JSConstSpec::Number, 2, 0}, - {"tooSmall", JSConstSpec::Number, 3, 0}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_ScaleWhen, scaleWhen) - -JSConstSpec CJS_Style::ConstSpecs[] = { - {"ch", JSConstSpec::String, 0, "check"}, - {"cr", JSConstSpec::String, 0, "cross"}, - {"di", JSConstSpec::String, 0, "diamond"}, - {"ci", JSConstSpec::String, 0, "circle"}, - {"st", JSConstSpec::String, 0, "star"}, - {"sq", JSConstSpec::String, 0, "square"}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Style, style) - -JSConstSpec CJS_Zoomtype::ConstSpecs[] = { - {"none", JSConstSpec::String, 0, "NoVary"}, - {"fitP", JSConstSpec::String, 0, "FitPage"}, - {"fitW", JSConstSpec::String, 0, "FitWidth"}, - {"fitH", JSConstSpec::String, 0, "FitHeight"}, - {"fitV", JSConstSpec::String, 0, "FitVisibleWidth"}, - {"pref", JSConstSpec::String, 0, "Preferred"}, - {"refW", JSConstSpec::String, 0, "ReflowWidth"}, - {0, JSConstSpec::Number, 0, 0}}; -IMPLEMENT_JS_CLASS_CONST(CJS_Zoomtype, zoomtype) - -#define GLOBAL_STRING(rt, name, value) \ - (rt)->DefineGlobalConst( \ - (name), [](const v8::FunctionCallbackInfo& info) { \ - info.GetReturnValue().Set( \ - CFXJS_Engine::CurrentEngineFromIsolate(info.GetIsolate()) \ - ->NewString(value)); \ - }) - -void CJS_GlobalConsts::DefineJSObjects(CJS_Runtime* pRuntime) { - GLOBAL_STRING(pRuntime, L"IDS_GREATER_THAN", - L"Invalid value: must be greater than or equal to % s."); - - GLOBAL_STRING(pRuntime, L"IDS_GT_AND_LT", - L"Invalid value: must be greater than or equal to % s " - L"and less than or equal to % s."); - - GLOBAL_STRING(pRuntime, L"IDS_LESS_THAN", - L"Invalid value: must be less than or equal to % s."); - - GLOBAL_STRING(pRuntime, L"IDS_INVALID_MONTH", L"**Invalid**"); - GLOBAL_STRING( - pRuntime, L"IDS_INVALID_DATE", - L"Invalid date / time: please ensure that the date / time exists.Field"); - - GLOBAL_STRING(pRuntime, L"IDS_INVALID_VALUE", - L"The value entered does not match the format of the field"); - - GLOBAL_STRING(pRuntime, L"IDS_AM", L"am"); - GLOBAL_STRING(pRuntime, L"IDS_PM", L"pm"); - GLOBAL_STRING(pRuntime, L"IDS_MONTH_INFO", - L"January[1] February[2] March[3] April[4] May[5] " - L"June[6] July[7] August[8] September[9] October[10] " - L"November[11] December[12] Sept[9] Jan[1] Feb[2] Mar[3] " - L"Apr[4] Jun[6] Jul[7] Aug[8] Sep[9] Oct[10] Nov[11] " - L"Dec[12]"); - - GLOBAL_STRING(pRuntime, L"IDS_STARTUP_CONSOLE_MSG", L"** ^ _ ^ **"); -} - -#define GLOBAL_ARRAY(rt, name, ...) \ - { \ - const FX_WCHAR* values[] = {__VA_ARGS__}; \ - v8::Local array = (rt)->NewArray(); \ - for (size_t i = 0; i < FX_ArraySize(values); ++i) \ - array->Set(i, (rt)->NewString(values[i])); \ - (rt)->SetConstArray((name), array); \ - (rt)->DefineGlobalConst( \ - (name), [](const v8::FunctionCallbackInfo& info) { \ - CJS_Runtime* pCurrentRuntime = \ - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); \ - if (pCurrentRuntime) \ - info.GetReturnValue().Set(pCurrentRuntime->GetConstArray(name)); \ - }); \ - } - -void CJS_GlobalArrays::DefineJSObjects(CJS_Runtime* pRuntime) { - GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_ENTRY_DOT_SEP", L"[+-]?\\d*\\.?\\d*"); - GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_COMMIT_DOT_SEP", - L"[+-]?\\d+(\\.\\d+)?", // -1.0 or -1 - L"[+-]?\\.\\d+", // -.1 - L"[+-]?\\d+\\."); // -1. - - GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_ENTRY_COMMA_SEP", L"[+-]?\\d*,?\\d*"); - GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_COMMIT_COMMA_SEP", - L"[+-]?\\d+([.,]\\d+)?", // -1,0 or -1 - L"[+-]?[.,]\\d+", // -,1 - L"[+-]?\\d+[.,]"); // -1, - - GLOBAL_ARRAY(pRuntime, L"RE_ZIP_ENTRY", L"\\d{0,5}"); - GLOBAL_ARRAY(pRuntime, L"RE_ZIP_COMMIT", L"\\d{5}"); - GLOBAL_ARRAY(pRuntime, L"RE_ZIP4_ENTRY", L"\\d{0,5}(\\.|[- ])?\\d{0,4}"); - GLOBAL_ARRAY(pRuntime, L"RE_ZIP4_COMMIT", L"\\d{5}(\\.|[- ])?\\d{4}"); - GLOBAL_ARRAY(pRuntime, L"RE_PHONE_ENTRY", - // 555-1234 or 408 555-1234 - L"\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", - - // (408 - L"\\(\\d{0,3}", - - // (408) 555-1234 - // (allow the addition of parens as an afterthought) - L"\\(\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", - - // (408 555-1234 - L"\\(\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", - - // 408) 555-1234 - L"\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", - - // international - L"011(\\.|[- \\d])*"); - - GLOBAL_ARRAY( - pRuntime, L"RE_PHONE_COMMIT", L"\\d{3}(\\.|[- ])?\\d{4}", // 555-1234 - L"\\d{3}(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", // 408 555-1234 - L"\\(\\d{3}\\)(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", // (408) 555-1234 - L"011(\\.|[- \\d])*"); // international - - GLOBAL_ARRAY(pRuntime, L"RE_SSN_ENTRY", - L"\\d{0,3}(\\.|[- ])?\\d{0,2}(\\.|[- ])?\\d{0,4}"); - - GLOBAL_ARRAY(pRuntime, L"RE_SSN_COMMIT", - L"\\d{3}(\\.|[- ])?\\d{2}(\\.|[- ])?\\d{4}"); -} diff --git a/fpdfsdk/javascript/Consts.h b/fpdfsdk/javascript/Consts.h deleted file mode 100644 index e358cb93418ea11c7c3dd132f8fc7d6a853c2330..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Consts.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_CONSTS_H_ -#define FPDFSDK_JAVASCRIPT_CONSTS_H_ - -#include "fpdfsdk/javascript/JS_Define.h" - -class CJS_Border : public CJS_Object { - public: - explicit CJS_Border(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Border() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_Display : public CJS_Object { - public: - explicit CJS_Display(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Display() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_Font : public CJS_Object { - public: - explicit CJS_Font(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Font() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_Highlight : public CJS_Object { - public: - explicit CJS_Highlight(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Highlight() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_Position : public CJS_Object { - public: - explicit CJS_Position(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Position() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_ScaleHow : public CJS_Object { - public: - explicit CJS_ScaleHow(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_ScaleHow() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_ScaleWhen : public CJS_Object { - public: - explicit CJS_ScaleWhen(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_ScaleWhen() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_Style : public CJS_Object { - public: - explicit CJS_Style(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Style() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_Zoomtype : public CJS_Object { - public: - explicit CJS_Zoomtype(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Zoomtype() override {} - - DECLARE_JS_CLASS_CONST(); -}; - -class CJS_GlobalConsts : public CJS_Object { - public: - static void DefineJSObjects(CJS_Runtime* pRuntime); -}; - -class CJS_GlobalArrays : public CJS_Object { - public: - static void DefineJSObjects(CJS_Runtime* pRuntmie); -}; - -#endif // FPDFSDK_JAVASCRIPT_CONSTS_H_ diff --git a/fpdfsdk/javascript/DEPS b/fpdfsdk/javascript/DEPS deleted file mode 100644 index 36a51aa92f4a7732a4c7aca1cf6da196a2dadc25..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - '+fxjs' -] diff --git a/fpdfsdk/javascript/Document.cpp b/fpdfsdk/javascript/Document.cpp deleted file mode 100644 index a45b8b9ea7cff3d42792e76985bf0bd37bbf4b3e..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Document.cpp +++ /dev/null @@ -1,1658 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/Document.h" - -#include -#include -#include - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfapi/page/cpdf_page.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_string.h" -#include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fpdfdoc/cpdf_interform.h" -#include "core/fpdfdoc/cpdf_nametree.h" -#include "fpdfsdk/cpdfsdk_annotiteration.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/cpdfsdk_interform.h" -#include "fpdfsdk/cpdfsdk_pageview.h" -#include "fpdfsdk/cpdfsdk_widget.h" -#include "fpdfsdk/javascript/Annot.h" -#include "fpdfsdk/javascript/Field.h" -#include "fpdfsdk/javascript/Icon.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/app.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/resource.h" -#include "third_party/base/numerics/safe_math.h" -#include "third_party/base/ptr_util.h" - -JSConstSpec CJS_PrintParamsObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_PrintParamsObj::PropertySpecs[] = {{0, 0, 0}}; - -JSMethodSpec CJS_PrintParamsObj::MethodSpecs[] = {{0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj) - -PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject) { - bUI = true; - nStart = 0; - nEnd = 0; - bSilent = false; - bShrinkToFit = false; - bPrintAsImage = false; - bReverse = false; - bAnnotations = true; -} - -#define MINWIDTH 5.0f -#define MINHEIGHT 5.0f - -JSConstSpec CJS_Document::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Document::PropertySpecs[] = { - {"ADBE", get_ADBE_static, set_ADBE_static}, - {"author", get_author_static, set_author_static}, - {"baseURL", get_baseURL_static, set_baseURL_static}, - {"bookmarkRoot", get_bookmarkRoot_static, set_bookmarkRoot_static}, - {"calculate", get_calculate_static, set_calculate_static}, - {"Collab", get_Collab_static, set_Collab_static}, - {"creationDate", get_creationDate_static, set_creationDate_static}, - {"creator", get_creator_static, set_creator_static}, - {"delay", get_delay_static, set_delay_static}, - {"dirty", get_dirty_static, set_dirty_static}, - {"documentFileName", get_documentFileName_static, - set_documentFileName_static}, - {"external", get_external_static, set_external_static}, - {"filesize", get_filesize_static, set_filesize_static}, - {"icons", get_icons_static, set_icons_static}, - {"info", get_info_static, set_info_static}, - {"keywords", get_keywords_static, set_keywords_static}, - {"layout", get_layout_static, set_layout_static}, - {"media", get_media_static, set_media_static}, - {"modDate", get_modDate_static, set_modDate_static}, - {"mouseX", get_mouseX_static, set_mouseX_static}, - {"mouseY", get_mouseY_static, set_mouseY_static}, - {"numFields", get_numFields_static, set_numFields_static}, - {"numPages", get_numPages_static, set_numPages_static}, - {"pageNum", get_pageNum_static, set_pageNum_static}, - {"pageWindowRect", get_pageWindowRect_static, set_pageWindowRect_static}, - {"path", get_path_static, set_path_static}, - {"producer", get_producer_static, set_producer_static}, - {"subject", get_subject_static, set_subject_static}, - {"title", get_title_static, set_title_static}, - {"URL", get_URL_static, set_URL_static}, - {"zoom", get_zoom_static, set_zoom_static}, - {"zoomType", get_zoomType_static, set_zoomType_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_Document::MethodSpecs[] = { - {"addAnnot", addAnnot_static}, - {"addField", addField_static}, - {"addLink", addLink_static}, - {"addIcon", addIcon_static}, - {"calculateNow", calculateNow_static}, - {"closeDoc", closeDoc_static}, - {"createDataObject", createDataObject_static}, - {"deletePages", deletePages_static}, - {"exportAsText", exportAsText_static}, - {"exportAsFDF", exportAsFDF_static}, - {"exportAsXFDF", exportAsXFDF_static}, - {"extractPages", extractPages_static}, - {"getAnnot", getAnnot_static}, - {"getAnnots", getAnnots_static}, - {"getAnnot3D", getAnnot3D_static}, - {"getAnnots3D", getAnnots3D_static}, - {"getField", getField_static}, - {"getIcon", getIcon_static}, - {"getLinks", getLinks_static}, - {"getNthFieldName", getNthFieldName_static}, - {"getOCGs", getOCGs_static}, - {"getPageBox", getPageBox_static}, - {"getPageNthWord", getPageNthWord_static}, - {"getPageNthWordQuads", getPageNthWordQuads_static}, - {"getPageNumWords", getPageNumWords_static}, - {"getPrintParams", getPrintParams_static}, - {"getURL", getURL_static}, - {"gotoNamedDest", gotoNamedDest_static}, - {"importAnFDF", importAnFDF_static}, - {"importAnXFDF", importAnXFDF_static}, - {"importTextData", importTextData_static}, - {"insertPages", insertPages_static}, - {"mailForm", mailForm_static}, - {"print", print_static}, - {"removeField", removeField_static}, - {"replacePages", replacePages_static}, - {"resetForm", resetForm_static}, - {"removeIcon", removeIcon_static}, - {"saveAs", saveAs_static}, - {"submitForm", submitForm_static}, - {"syncAnnotScan", syncAnnotScan_static}, - {"mailDoc", mailDoc_static}, - {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Document, Document) - -void CJS_Document::InitInstance(IJS_Runtime* pIRuntime) { - CJS_Runtime* pRuntime = static_cast(pIRuntime); - Document* pDoc = static_cast(GetEmbedObject()); - pDoc->SetFormFillEnv(pRuntime->GetFormFillEnv()); -} - -Document::Document(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject), - m_pFormFillEnv(nullptr), - m_cwBaseURL(L""), - m_bDelay(false) {} - -Document::~Document() { -} - -// the total number of fileds in document. -bool Document::numFields(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); - vp << static_cast(pPDFForm->CountFields(CFX_WideString())); - return true; -} - -bool Document::dirty(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (vp.IsGetting()) { - vp << !!m_pFormFillEnv->GetChangeMark(); - return true; - } - bool bChanged = false; - vp >> bChanged; - if (bChanged) - m_pFormFillEnv->SetChangeMark(); - else - m_pFormFillEnv->ClearChangeMark(); - - return true; -} - -bool Document::ADBE(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) - vp.GetJSValue()->SetNull(pRuntime); - - return true; -} - -bool Document::pageNum(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (vp.IsGetting()) { - if (CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetCurrentView()) - vp << pPageView->GetPageIndex(); - return true; - } - int iPageCount = m_pFormFillEnv->GetPageCount(); - int iPageNum = 0; - vp >> iPageNum; - if (iPageNum >= 0 && iPageNum < iPageCount) - m_pFormFillEnv->JS_docgotoPage(iPageNum); - else if (iPageNum >= iPageCount) - m_pFormFillEnv->JS_docgotoPage(iPageCount - 1); - else if (iPageNum < 0) - m_pFormFillEnv->JS_docgotoPage(0); - - return true; -} - -bool Document::addAnnot(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Not supported. - return true; -} - -bool Document::addField(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Not supported. - return true; -} - -bool Document::exportAsText(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::exportAsFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::exportAsXFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -// Maps a field object in PDF document to a JavaScript variable -// comment: -// note: the paremter cName, this is clue how to treat if the cName is not a -// valiable filed name in this document - -bool Document::getField(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CFX_WideString wideName = params[0].ToCFXWideString(pRuntime); - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); - if (pPDFForm->CountFields(wideName) <= 0) { - vRet.SetNull(pRuntime); - return true; - } - - v8::Local pFieldObj = - pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - if (pFieldObj.IsEmpty()) - return false; - - CJS_Field* pJSField = - static_cast(pRuntime->GetObjectPrivate(pFieldObj)); - Field* pField = static_cast(pJSField->GetEmbedObject()); - pField->AttachField(this, wideName); - vRet = CJS_Value(pRuntime, pJSField); - return true; -} - -// Gets the name of the nth field in the document -bool Document::getNthFieldName(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - int nIndex = params[0].ToInt(pRuntime); - if (nIndex < 0) { - sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); - return false; - } - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); - CPDF_FormField* pField = pPDFForm->GetField(nIndex, CFX_WideString()); - if (!pField) - return false; - - vRet = CJS_Value(pRuntime, pField->GetFullName().c_str()); - return true; -} - -bool Document::importAnFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::importAnXFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::importTextData(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -// exports the form data and mails the resulting fdf file as an attachment to -// all recipients. -// comment: need reader supports -bool Document::mailForm(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - int iLength = params.size(); - bool bUI = iLength > 0 ? params[0].ToBool(pRuntime) : true; - CFX_WideString cTo = iLength > 1 ? params[1].ToCFXWideString(pRuntime) : L""; - CFX_WideString cCc = iLength > 2 ? params[2].ToCFXWideString(pRuntime) : L""; - CFX_WideString cBcc = iLength > 3 ? params[3].ToCFXWideString(pRuntime) : L""; - CFX_WideString cSubject = - iLength > 4 ? params[4].ToCFXWideString(pRuntime) : L""; - CFX_WideString cMsg = iLength > 5 ? params[5].ToCFXWideString(pRuntime) : L""; - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CFX_ByteTextBuf textBuf; - if (!pInterForm->ExportFormToFDFTextBuf(textBuf)) - return false; - - pRuntime->BeginBlock(); - CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); - pFormFillEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI, - cTo.c_str(), cSubject.c_str(), cCc.c_str(), - cBcc.c_str(), cMsg.c_str()); - pRuntime->EndBlock(); - return true; -} - -bool Document::print(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - bool bUI = true; - int nStart = 0; - int nEnd = 0; - bool bSilent = false; - bool bShrinkToFit = false; - bool bPrintAsImage = false; - bool bReverse = false; - bool bAnnotations = false; - int nlength = params.size(); - if (nlength == 9) { - if (params[8].GetType() == CJS_Value::VT_object) { - v8::Local pObj = params[8].ToV8Object(pRuntime); - if (CFXJS_Engine::GetObjDefnID(pObj) == - CJS_PrintParamsObj::g_nObjDefnID) { - if (CJS_Object* pJSObj = params[8].ToCJSObject(pRuntime)) { - if (PrintParamsObj* pprintparamsObj = - static_cast(pJSObj->GetEmbedObject())) { - bUI = pprintparamsObj->bUI; - nStart = pprintparamsObj->nStart; - nEnd = pprintparamsObj->nEnd; - bSilent = pprintparamsObj->bSilent; - bShrinkToFit = pprintparamsObj->bShrinkToFit; - bPrintAsImage = pprintparamsObj->bPrintAsImage; - bReverse = pprintparamsObj->bReverse; - bAnnotations = pprintparamsObj->bAnnotations; - } - } - } - } - } else { - if (nlength >= 1) - bUI = params[0].ToBool(pRuntime); - if (nlength >= 2) - nStart = params[1].ToInt(pRuntime); - if (nlength >= 3) - nEnd = params[2].ToInt(pRuntime); - if (nlength >= 4) - bSilent = params[3].ToBool(pRuntime); - if (nlength >= 5) - bShrinkToFit = params[4].ToBool(pRuntime); - if (nlength >= 6) - bPrintAsImage = params[5].ToBool(pRuntime); - if (nlength >= 7) - bReverse = params[6].ToBool(pRuntime); - if (nlength >= 8) - bAnnotations = params[7].ToBool(pRuntime); - } - - if (m_pFormFillEnv) { - m_pFormFillEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, - bPrintAsImage, bReverse, bAnnotations); - return true; - } - return false; -} - -// removes the specified field from the document. -// comment: -// note: if the filed name is not rational, adobe is dumb for it. - -bool Document::removeField(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || - m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM))) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - CFX_WideString sFieldName = params[0].ToCFXWideString(pRuntime); - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - std::vector widgets; - pInterForm->GetWidgets(sFieldName, &widgets); - if (widgets.empty()) - return true; - - for (const auto& pAnnot : widgets) { - CPDFSDK_Widget* pWidget = static_cast(pAnnot.Get()); - if (!pWidget) - continue; - - CFX_FloatRect rcAnnot = pWidget->GetRect(); - --rcAnnot.left; - --rcAnnot.bottom; - ++rcAnnot.right; - ++rcAnnot.top; - - std::vector aRefresh(1, rcAnnot); - UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); - ASSERT(pPage); - - // If there is currently no pageview associated with the page being used - // do not create one. We may be in the process of tearing down the document - // and creating a new pageview at this point will cause bad things. - CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, false); - if (pPageView) { -#if PDF_ENABLE_XFA - pPageView->DeleteAnnot(pWidget); -#endif // PDF_ENABLE_XFA - pPageView->UpdateRects(aRefresh); - } - } - m_pFormFillEnv->SetChangeMark(); - - return true; -} - -// reset filed values within a document. -// comment: -// note: if the fields names r not rational, aodbe is dumb for it. - -bool Document::resetForm(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || - m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || - m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); - CJS_Array aName; - - if (params.empty()) { - pPDFForm->ResetForm(true); - m_pFormFillEnv->SetChangeMark(); - return true; - } - - switch (params[0].GetType()) { - default: - aName.Attach(params[0].ToV8Array(pRuntime)); - break; - case CJS_Value::VT_string: - aName.SetElement(pRuntime, 0, params[0]); - break; - } - - std::vector aFields; - for (int i = 0, isz = aName.GetLength(pRuntime); i < isz; ++i) { - CJS_Value valElement(pRuntime); - aName.GetElement(pRuntime, i, valElement); - CFX_WideString swVal = valElement.ToCFXWideString(pRuntime); - for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; ++j) - aFields.push_back(pPDFForm->GetField(j, swVal)); - } - - if (!aFields.empty()) { - pPDFForm->ResetForm(aFields, true, true); - m_pFormFillEnv->SetChangeMark(); - } - - return true; -} - -bool Document::saveAs(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::syncAnnotScan(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::submitForm(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int nSize = params.size(); - if (nSize < 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - - CJS_Array aFields; - CFX_WideString strURL; - bool bFDF = true; - bool bEmpty = false; - CJS_Value v = params[0]; - if (v.GetType() == CJS_Value::VT_string) { - strURL = params[0].ToCFXWideString(pRuntime); - if (nSize > 1) - bFDF = params[1].ToBool(pRuntime); - if (nSize > 2) - bEmpty = params[2].ToBool(pRuntime); - if (nSize > 3) - aFields.Attach(params[3].ToV8Array(pRuntime)); - } else if (v.GetType() == CJS_Value::VT_object) { - v8::Local pObj = params[0].ToV8Object(pRuntime); - v8::Local pValue = pRuntime->GetObjectProperty(pObj, L"cURL"); - if (!pValue.IsEmpty()) - strURL = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"bFDF"); - bFDF = CJS_Value(pRuntime, pValue).ToBool(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"bEmpty"); - bEmpty = CJS_Value(pRuntime, pValue).ToBool(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"aFields"); - aFields.Attach(CJS_Value(pRuntime, pValue).ToV8Array(pRuntime)); - } - - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); - if (aFields.GetLength(pRuntime) == 0 && bEmpty) { - if (pPDFInterForm->CheckRequiredFields(nullptr, true)) { - pRuntime->BeginBlock(); - pInterForm->SubmitForm(strURL, false); - pRuntime->EndBlock(); - } - return true; - } - - std::vector fieldObjects; - for (int i = 0, sz = aFields.GetLength(pRuntime); i < sz; ++i) { - CJS_Value valName(pRuntime); - aFields.GetElement(pRuntime, i, valName); - - CFX_WideString sName = valName.ToCFXWideString(pRuntime); - CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); - for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) { - CPDF_FormField* pField = pPDFForm->GetField(j, sName); - if (!bEmpty && pField->GetValue().IsEmpty()) - continue; - - fieldObjects.push_back(pField); - } - } - - if (pPDFInterForm->CheckRequiredFields(&fieldObjects, true)) { - pRuntime->BeginBlock(); - pInterForm->SubmitFields(strURL, fieldObjects, true, !bFDF); - pRuntime->EndBlock(); - } - return true; -} - -void Document::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) { - m_pFormFillEnv.Reset(pFormFillEnv); -} - -bool Document::bookmarkRoot(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::mailDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // TODO(tsepez): Check maximum number of allowed params. - bool bUI = true; - CFX_WideString cTo = L""; - CFX_WideString cCc = L""; - CFX_WideString cBcc = L""; - CFX_WideString cSubject = L""; - CFX_WideString cMsg = L""; - - if (params.size() >= 1) - bUI = params[0].ToBool(pRuntime); - if (params.size() >= 2) - cTo = params[1].ToCFXWideString(pRuntime); - if (params.size() >= 3) - cCc = params[2].ToCFXWideString(pRuntime); - if (params.size() >= 4) - cBcc = params[3].ToCFXWideString(pRuntime); - if (params.size() >= 5) - cSubject = params[4].ToCFXWideString(pRuntime); - if (params.size() >= 6) - cMsg = params[5].ToCFXWideString(pRuntime); - - if (params.size() >= 1 && params[0].GetType() == CJS_Value::VT_object) { - v8::Local pObj = params[0].ToV8Object(pRuntime); - - v8::Local pValue = pRuntime->GetObjectProperty(pObj, L"bUI"); - bUI = CJS_Value(pRuntime, pValue).ToBool(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"cTo"); - cTo = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"cCc"); - cCc = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"cBcc"); - cBcc = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"cSubject"); - cSubject = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); - - pValue = pRuntime->GetObjectProperty(pObj, L"cMsg"); - cMsg = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime); - } - - pRuntime->BeginBlock(); - CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); - pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), cSubject.c_str(), - cCc.c_str(), cBcc.c_str(), cMsg.c_str()); - pRuntime->EndBlock(); - return true; -} - -bool Document::author(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "Author", sError); -} - -bool Document::info(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); - if (!pDictionary) - return false; - - CFX_WideString cwAuthor = pDictionary->GetUnicodeTextFor("Author"); - CFX_WideString cwTitle = pDictionary->GetUnicodeTextFor("Title"); - CFX_WideString cwSubject = pDictionary->GetUnicodeTextFor("Subject"); - CFX_WideString cwKeywords = pDictionary->GetUnicodeTextFor("Keywords"); - CFX_WideString cwCreator = pDictionary->GetUnicodeTextFor("Creator"); - CFX_WideString cwProducer = pDictionary->GetUnicodeTextFor("Producer"); - CFX_WideString cwCreationDate = - pDictionary->GetUnicodeTextFor("CreationDate"); - CFX_WideString cwModDate = pDictionary->GetUnicodeTextFor("ModDate"); - CFX_WideString cwTrapped = pDictionary->GetUnicodeTextFor("Trapped"); - - v8::Local pObj = pRuntime->NewFxDynamicObj(-1); - pRuntime->PutObjectProperty(pObj, L"Author", - pRuntime->NewString(cwAuthor.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"Title", - pRuntime->NewString(cwTitle.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"Subject", - pRuntime->NewString(cwSubject.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"Keywords", - pRuntime->NewString(cwKeywords.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"Creator", - pRuntime->NewString(cwCreator.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"Producer", - pRuntime->NewString(cwProducer.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"CreationDate", - pRuntime->NewString(cwCreationDate.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"ModDate", - pRuntime->NewString(cwModDate.AsStringC())); - pRuntime->PutObjectProperty(pObj, L"Trapped", - pRuntime->NewString(cwTrapped.AsStringC())); - - // It's to be compatible to non-standard info dictionary. - for (const auto& it : *pDictionary) { - const CFX_ByteString& bsKey = it.first; - CPDF_Object* pValueObj = it.second.get(); - CFX_WideString wsKey = CFX_WideString::FromUTF8(bsKey.AsStringC()); - if (pValueObj->IsString() || pValueObj->IsName()) { - pRuntime->PutObjectProperty( - pObj, wsKey, - pRuntime->NewString(pValueObj->GetUnicodeText().AsStringC())); - } else if (pValueObj->IsNumber()) { - pRuntime->PutObjectProperty(pObj, wsKey, - pRuntime->NewNumber(pValueObj->GetNumber())); - } else if (pValueObj->IsBoolean()) { - pRuntime->PutObjectProperty( - pObj, wsKey, pRuntime->NewBoolean(!!pValueObj->GetInteger())); - } - } - vp << pObj; - return true; -} - -bool Document::getPropertyInternal(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - const CFX_ByteString& propName, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); - if (!pDictionary) - return false; - - if (vp.IsGetting()) { - vp << pDictionary->GetUnicodeTextFor(propName); - } else { - if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - CFX_WideString csProperty; - vp >> csProperty; - pDictionary->SetNewFor(propName, PDF_EncodeText(csProperty), - false); - m_pFormFillEnv->SetChangeMark(); - } - return true; -} - -bool Document::creationDate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "CreationDate", sError); -} - -bool Document::creator(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "Creator", sError); -} - -bool Document::delay(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (vp.IsGetting()) { - vp << m_bDelay; - return true; - } - if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - vp >> m_bDelay; - if (m_bDelay) { - m_DelayData.clear(); - return true; - } - std::list> DelayDataToProcess; - DelayDataToProcess.swap(m_DelayData); - for (const auto& pData : DelayDataToProcess) - Field::DoDelay(m_pFormFillEnv.Get(), pData.get()); - - return true; -} - -bool Document::keywords(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "Keywords", sError); -} - -bool Document::modDate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "ModDate", sError); -} - -bool Document::producer(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "Producer", sError); -} - -bool Document::subject(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return getPropertyInternal(pRuntime, vp, "Subject", sError); -} - -bool Document::title(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!m_pFormFillEnv || !m_pFormFillEnv->GetUnderlyingDocument()) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - return getPropertyInternal(pRuntime, vp, "Title", sError); -} - -bool Document::numPages(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - vp << m_pFormFillEnv->GetPageCount(); - return true; -} - -bool Document::external(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - // In Chrome case, should always return true. - if (vp.IsGetting()) { - vp << true; - } - return true; -} - -bool Document::filesize(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - vp << 0; - return true; -} - -bool Document::mouseX(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::mouseY(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::URL(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - vp << m_pFormFillEnv->JS_docGetFilePath(); - return true; -} - -bool Document::baseURL(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - vp << m_cwBaseURL; - } else { - vp >> m_cwBaseURL; - } - return true; -} - -bool Document::calculate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - if (vp.IsGetting()) { - vp << !!pInterForm->IsCalculateEnabled(); - return true; - } - bool bCalculate; - vp >> bCalculate; - pInterForm->EnableCalculate(bCalculate); - return true; -} - -bool Document::documentFileName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CFX_WideString wsFilePath = m_pFormFillEnv->JS_docGetFilePath(); - int32_t i = wsFilePath.GetLength() - 1; - for (; i >= 0; i--) { - if (wsFilePath.GetAt(i) == L'\\' || wsFilePath.GetAt(i) == L'/') - break; - } - if (i >= 0 && i < wsFilePath.GetLength() - 1) { - vp << (wsFilePath.GetBuffer(wsFilePath.GetLength()) + i + 1); - } else { - vp << L""; - } - return true; -} - -bool Document::path(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - vp << app::SysPathToPDFPath(m_pFormFillEnv->JS_docGetFilePath()); - return true; -} - -bool Document::pageWindowRect(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::layout(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::addLink(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::closeDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::getPageBox(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::getAnnot(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - int nPageNo = params[0].ToInt(pRuntime); - CFX_WideString swAnnotName = params[1].ToCFXWideString(pRuntime); - CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(nPageNo); - if (!pPageView) - return false; - - CPDFSDK_AnnotIteration annotIteration(pPageView, false); - CPDFSDK_BAAnnot* pSDKBAAnnot = nullptr; - for (const auto& pSDKAnnotCur : annotIteration) { - CPDFSDK_BAAnnot* pBAAnnot = - static_cast(pSDKAnnotCur.Get()); - if (pBAAnnot && pBAAnnot->GetAnnotName() == swAnnotName) { - pSDKBAAnnot = pBAAnnot; - break; - } - } - if (!pSDKBAAnnot) - return false; - - v8::Local pObj = - pRuntime->NewFxDynamicObj(CJS_Annot::g_nObjDefnID); - if (pObj.IsEmpty()) - return false; - - CJS_Annot* pJS_Annot = - static_cast(pRuntime->GetObjectPrivate(pObj)); - Annot* pAnnot = static_cast(pJS_Annot->GetEmbedObject()); - pAnnot->SetSDKAnnot(pSDKBAAnnot); - vRet = CJS_Value(pRuntime, pJS_Annot); - return true; -} - -bool Document::getAnnots(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - // TODO(tonikitoo): Add support supported parameters as per - // the PDF spec. - - int nPageNo = m_pFormFillEnv->GetPageCount(); - CJS_Array annots; - - for (int i = 0; i < nPageNo; ++i) { - CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(i); - if (!pPageView) - return false; - - CPDFSDK_AnnotIteration annotIteration(pPageView, false); - for (const auto& pSDKAnnotCur : annotIteration) { - if (!pSDKAnnotCur) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - v8::Local pObj = - pRuntime->NewFxDynamicObj(CJS_Annot::g_nObjDefnID); - if (pObj.IsEmpty()) - return false; - - CJS_Annot* pJS_Annot = - static_cast(pRuntime->GetObjectPrivate(pObj)); - Annot* pAnnot = static_cast(pJS_Annot->GetEmbedObject()); - pAnnot->SetSDKAnnot(static_cast(pSDKAnnotCur.Get())); - annots.SetElement(pRuntime, i, CJS_Value(pRuntime, pJS_Annot)); - } - } - vRet = CJS_Value(pRuntime, annots); - return true; -} - -bool Document::getAnnot3D(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - vRet.SetNull(pRuntime); - return true; -} - -bool Document::getAnnots3D(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::getOCGs(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::getLinks(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect) { - return (rect.left <= LinkRect.left && rect.top <= LinkRect.top && - rect.right >= LinkRect.right && rect.bottom >= LinkRect.bottom); -} - -bool Document::addIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString swIconName = params[0].ToCFXWideString(pRuntime); - if (params[1].GetType() != CJS_Value::VT_object) { - sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); - return false; - } - - v8::Local pJSIcon = params[1].ToV8Object(pRuntime); - if (pRuntime->GetObjDefnID(pJSIcon) != CJS_Icon::g_nObjDefnID) { - sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); - return false; - } - - if (!params[1].ToCJSObject(pRuntime)->GetEmbedObject()) { - sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); - return false; - } - - m_IconNames.push_back(swIconName); - return true; -} - -bool Document::icons(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - if (m_IconNames.empty()) { - vp.GetJSValue()->SetNull(pRuntime); - return true; - } - - CJS_Array Icons; - int i = 0; - for (const auto& name : m_IconNames) { - v8::Local pObj = - pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID); - if (pObj.IsEmpty()) - return false; - - CJS_Icon* pJS_Icon = - static_cast(pRuntime->GetObjectPrivate(pObj)); - Icon* pIcon = static_cast(pJS_Icon->GetEmbedObject()); - pIcon->SetIconName(name); - Icons.SetElement(pRuntime, i++, CJS_Value(pRuntime, pJS_Icon)); - } - - vp << Icons; - return true; -} - -bool Document::getIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString swIconName = params[0].ToCFXWideString(pRuntime); - auto it = std::find(m_IconNames.begin(), m_IconNames.end(), swIconName); - if (it == m_IconNames.end()) - return false; - - v8::Local pObj = - pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID); - if (pObj.IsEmpty()) - return false; - - CJS_Icon* pJS_Icon = static_cast(pRuntime->GetObjectPrivate(pObj)); - Icon* pIcon = static_cast(pJS_Icon->GetEmbedObject()); - pIcon->SetIconName(*it); - vRet = CJS_Value(pRuntime, pJS_Icon); - return true; -} - -bool Document::removeIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, no supported. - return true; -} - -bool Document::createDataObject(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not implemented. - return true; -} - -bool Document::media(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::calculateNow(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || - m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || - m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - m_pFormFillEnv->GetInterForm()->OnCalculate(); - return true; -} - -bool Document::Collab(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::getPageNthWord(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - - // TODO(tsepez): check maximum allowable params. - - int nPageNo = params.size() > 0 ? params[0].ToInt(pRuntime) : 0; - int nWordNo = params.size() > 1 ? params[1].ToInt(pRuntime) : 0; - bool bStrip = params.size() > 2 ? params[2].ToBool(pRuntime) : true; - - CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); - if (!pDocument) - return false; - - if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) { - sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); - return false; - } - - CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo); - if (!pPageDict) - return false; - - CPDF_Page page(pDocument, pPageDict, true); - page.ParseContent(); - - int nWords = 0; - CFX_WideString swRet; - for (auto& pPageObj : *page.GetPageObjectList()) { - if (pPageObj->IsText()) { - CPDF_TextObject* pTextObj = pPageObj->AsText(); - int nObjWords = CountWords(pTextObj); - if (nWords + nObjWords >= nWordNo) { - swRet = GetObjWordStr(pTextObj, nWordNo - nWords); - break; - } - nWords += nObjWords; - } - } - - if (bStrip) { - swRet.TrimLeft(); - swRet.TrimRight(); - } - - vRet = CJS_Value(pRuntime, swRet.c_str()); - return true; -} - -bool Document::getPageNthWordQuads(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - return false; -} - -bool Document::getPageNumWords(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) { - sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION); - return false; - } - int nPageNo = params.size() > 0 ? params[0].ToInt(pRuntime) : 0; - CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); - if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) { - sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); - return false; - } - - CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo); - if (!pPageDict) - return false; - - CPDF_Page page(pDocument, pPageDict, true); - page.ParseContent(); - - int nWords = 0; - for (auto& pPageObj : *page.GetPageObjectList()) { - if (pPageObj->IsText()) - nWords += CountWords(pPageObj->AsText()); - } - - vRet = CJS_Value(pRuntime, nWords); - return true; -} - -bool Document::getPrintParams(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - v8::Local pRetObj = - pRuntime->NewFxDynamicObj(CJS_PrintParamsObj::g_nObjDefnID); - if (pRetObj.IsEmpty()) - return false; - - // Not implemented yet. - - vRet = CJS_Value(pRuntime, pRetObj); - return true; -} - -#define ISLATINWORD(u) (u != 0x20 && u <= 0x28FF) - -int Document::CountWords(CPDF_TextObject* pTextObj) { - if (!pTextObj) - return 0; - - int nWords = 0; - - CPDF_Font* pFont = pTextObj->GetFont(); - if (!pFont) - return 0; - - bool bIsLatin = false; - - for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) { - uint32_t charcode = CPDF_Font::kInvalidCharCode; - FX_FLOAT kerning; - - pTextObj->GetCharInfo(i, &charcode, &kerning); - CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode); - - uint16_t unicode = 0; - if (swUnicode.GetLength() > 0) - unicode = swUnicode[0]; - - if (ISLATINWORD(unicode) && bIsLatin) - continue; - - bIsLatin = ISLATINWORD(unicode); - if (unicode != 0x20) - nWords++; - } - - return nWords; -} - -CFX_WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj, - int nWordIndex) { - CFX_WideString swRet; - - CPDF_Font* pFont = pTextObj->GetFont(); - if (!pFont) - return L""; - - int nWords = 0; - bool bIsLatin = false; - - for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) { - uint32_t charcode = CPDF_Font::kInvalidCharCode; - FX_FLOAT kerning; - - pTextObj->GetCharInfo(i, &charcode, &kerning); - CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode); - - uint16_t unicode = 0; - if (swUnicode.GetLength() > 0) - unicode = swUnicode[0]; - - if (ISLATINWORD(unicode) && bIsLatin) { - } else { - bIsLatin = ISLATINWORD(unicode); - if (unicode != 0x20) - nWords++; - } - - if (nWords - 1 == nWordIndex) - swRet += unicode; - } - - return swRet; -} - -bool Document::zoom(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -/** -(none, NoVary) -(fitP, FitPage) -(fitW, FitWidth) -(fitH, FitHeight) -(fitV, FitVisibleWidth) -(pref, Preferred) -(refW, ReflowWidth) -*/ - -bool Document::zoomType(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Document::deletePages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, no supported. - return true; -} - -bool Document::extractPages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::insertPages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::replacePages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::getURL(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Document::gotoNamedDest(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - if (!m_pFormFillEnv) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - CFX_WideString wideName = params[0].ToCFXWideString(pRuntime); - CFX_ByteString utf8Name = wideName.UTF8Encode(); - CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); - if (!pDocument) - return false; - - CPDF_NameTree nameTree(pDocument, "Dests"); - CPDF_Array* destArray = nameTree.LookupNamedDest(pDocument, utf8Name); - if (!destArray) - return false; - - CPDF_Dest dest(destArray); - const CPDF_Array* arrayObject = ToArray(dest.GetObject()); - - std::unique_ptr scrollPositionArray; - int scrollPositionArraySize = 0; - - if (arrayObject) { - scrollPositionArray.reset(new float[arrayObject->GetCount()]); - int j = 0; - for (size_t i = 2; i < arrayObject->GetCount(); i++) - scrollPositionArray[j++] = arrayObject->GetFloatAt(i); - scrollPositionArraySize = j; - } - - pRuntime->BeginBlock(); - m_pFormFillEnv->DoGoToAction(dest.GetPageIndex(pDocument), dest.GetZoomMode(), - scrollPositionArray.get(), - scrollPositionArraySize); - pRuntime->EndBlock(); - - return true; -} - -void Document::AddDelayData(CJS_DelayData* pData) { - m_DelayData.push_back(std::unique_ptr(pData)); -} - -void Document::DoFieldDelay(const CFX_WideString& sFieldName, - int nControlIndex) { - std::vector> DelayDataForFieldAndControlIndex; - auto iter = m_DelayData.begin(); - while (iter != m_DelayData.end()) { - auto old = iter++; - if ((*old)->sFieldName == sFieldName && - (*old)->nControlIndex == nControlIndex) { - DelayDataForFieldAndControlIndex.push_back(std::move(*old)); - m_DelayData.erase(old); - } - } - - for (const auto& pData : DelayDataForFieldAndControlIndex) - Field::DoDelay(m_pFormFillEnv.Get(), pData.get()); -} - -CJS_Document* Document::GetCJSDoc() const { - return static_cast(m_pJSObject); -} diff --git a/fpdfsdk/javascript/Document.h b/fpdfsdk/javascript/Document.h deleted file mode 100644 index 91ca778c790935ca64dd0704f3f4c93615f7c314..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Document.h +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_DOCUMENT_H_ -#define FPDFSDK_JAVASCRIPT_DOCUMENT_H_ - -#include -#include -#include - -#include "core/fpdfapi/page/cpdf_pageobject.h" -#include "core/fpdfapi/page/cpdf_textobject.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/javascript/JS_Define.h" - -class PrintParamsObj : public CJS_EmbedObj { - public: - explicit PrintParamsObj(CJS_Object* pJSObject); - ~PrintParamsObj() override {} - - public: - bool bUI; - int nStart; - int nEnd; - bool bSilent; - bool bShrinkToFit; - bool bPrintAsImage; - bool bReverse; - bool bAnnotations; -}; - -class CJS_PrintParamsObj : public CJS_Object { - public: - explicit CJS_PrintParamsObj(v8::Local pObject) - : CJS_Object(pObject) {} - ~CJS_PrintParamsObj() override {} - - DECLARE_JS_CLASS(); -}; - -struct CJS_AnnotObj; -struct CJS_DelayAnnot; -struct CJS_DelayData; - -class Document : public CJS_EmbedObj { - public: - explicit Document(CJS_Object* pJSObject); - ~Document() override; - - bool ADBE(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool author(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool baseURL(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool bookmarkRoot(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool calculate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool Collab(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool creationDate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool creator(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool delay(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool dirty(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool documentFileName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool external(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool filesize(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool icons(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool info(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool keywords(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool layout(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool media(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool modDate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool mouseX(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool mouseY(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool numFields(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool numPages(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool pageNum(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool pageWindowRect(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool path(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool producer(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool subject(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool title(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool zoom(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool zoomType(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - - bool addAnnot(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool addField(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool addLink(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool addIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool calculateNow(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool closeDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool createDataObject(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool deletePages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool exportAsText(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool exportAsFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool exportAsXFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool extractPages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getAnnot(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getAnnots(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getAnnot3D(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getAnnots3D(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getField(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getLinks(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getNthFieldName(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getOCGs(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getPageBox(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getPageNthWord(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getPageNthWordQuads(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getPageNumWords(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getPrintParams(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getURL(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool gotoNamedDest(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool importAnFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool importAnXFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool importTextData(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool insertPages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool mailForm(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool print(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool removeField(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool replacePages(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool resetForm(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool saveAs(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool submitForm(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool syncAnnotScan(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool mailDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool removeIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool URL(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - - void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv); - CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { - return m_pFormFillEnv.Get(); - } - void AddDelayData(CJS_DelayData* pData); - void DoFieldDelay(const CFX_WideString& sFieldName, int nControlIndex); - CJS_Document* GetCJSDoc() const; - - private: - bool IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect); - int CountWords(CPDF_TextObject* pTextObj); - CFX_WideString GetObjWordStr(CPDF_TextObject* pTextObj, int nWordIndex); - - bool getPropertyInternal(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - const CFX_ByteString& propName, - CFX_WideString& sError); - - CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; - CFX_WideString m_cwBaseURL; - std::list> m_DelayData; - // Needs to be a std::list for iterator stability. - std::list m_IconNames; - bool m_bDelay; -}; - -class CJS_Document : public CJS_Object { - public: - explicit CJS_Document(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Document() override {} - - // CJS_Object - void InitInstance(IJS_Runtime* pIRuntime) override; - - DECLARE_JS_CLASS(); - - JS_STATIC_PROP(ADBE, Document); - JS_STATIC_PROP(author, Document); - JS_STATIC_PROP(baseURL, Document); - JS_STATIC_PROP(bookmarkRoot, Document); - JS_STATIC_PROP(calculate, Document); - JS_STATIC_PROP(Collab, Document); - JS_STATIC_PROP(creationDate, Document); - JS_STATIC_PROP(creator, Document); - JS_STATIC_PROP(delay, Document); - JS_STATIC_PROP(dirty, Document); - JS_STATIC_PROP(documentFileName, Document); - JS_STATIC_PROP(external, Document); - JS_STATIC_PROP(filesize, Document); - JS_STATIC_PROP(icons, Document); - JS_STATIC_PROP(info, Document); - JS_STATIC_PROP(keywords, Document); - JS_STATIC_PROP(layout, Document); - JS_STATIC_PROP(media, Document); - JS_STATIC_PROP(modDate, Document); - JS_STATIC_PROP(mouseX, Document); - JS_STATIC_PROP(mouseY, Document); - JS_STATIC_PROP(numFields, Document); - JS_STATIC_PROP(numPages, Document); - JS_STATIC_PROP(pageNum, Document); - JS_STATIC_PROP(pageWindowRect, Document); - JS_STATIC_PROP(path, Document); - JS_STATIC_PROP(producer, Document); - JS_STATIC_PROP(subject, Document); - JS_STATIC_PROP(title, Document); - JS_STATIC_PROP(URL, Document); - JS_STATIC_PROP(zoom, Document); - JS_STATIC_PROP(zoomType, Document); - - JS_STATIC_METHOD(addAnnot, Document); - JS_STATIC_METHOD(addField, Document); - JS_STATIC_METHOD(addLink, Document); - JS_STATIC_METHOD(addIcon, Document); - JS_STATIC_METHOD(calculateNow, Document); - JS_STATIC_METHOD(closeDoc, Document); - JS_STATIC_METHOD(createDataObject, Document); - JS_STATIC_METHOD(deletePages, Document); - JS_STATIC_METHOD(exportAsText, Document); - JS_STATIC_METHOD(exportAsFDF, Document); - JS_STATIC_METHOD(exportAsXFDF, Document); - JS_STATIC_METHOD(extractPages, Document); - JS_STATIC_METHOD(getAnnot, Document); - JS_STATIC_METHOD(getAnnots, Document); - JS_STATIC_METHOD(getAnnot3D, Document); - JS_STATIC_METHOD(getAnnots3D, Document); - JS_STATIC_METHOD(getField, Document); - JS_STATIC_METHOD(getIcon, Document); - JS_STATIC_METHOD(getLinks, Document); - JS_STATIC_METHOD(getNthFieldName, Document); - JS_STATIC_METHOD(getOCGs, Document); - JS_STATIC_METHOD(getPageBox, Document); - JS_STATIC_METHOD(getPageNthWord, Document); - JS_STATIC_METHOD(getPageNthWordQuads, Document); - JS_STATIC_METHOD(getPageNumWords, Document); - JS_STATIC_METHOD(getPrintParams, Document); - JS_STATIC_METHOD(getURL, Document); - JS_STATIC_METHOD(gotoNamedDest, Document); - JS_STATIC_METHOD(importAnFDF, Document); - JS_STATIC_METHOD(importAnXFDF, Document); - JS_STATIC_METHOD(importTextData, Document); - JS_STATIC_METHOD(insertPages, Document); - JS_STATIC_METHOD(mailForm, Document); - JS_STATIC_METHOD(print, Document); - JS_STATIC_METHOD(removeField, Document); - JS_STATIC_METHOD(replacePages, Document); - JS_STATIC_METHOD(removeIcon, Document); - JS_STATIC_METHOD(resetForm, Document); - JS_STATIC_METHOD(saveAs, Document); - JS_STATIC_METHOD(submitForm, Document); - JS_STATIC_METHOD(syncAnnotScan, Document); - JS_STATIC_METHOD(mailDoc, Document); -}; - -#endif // FPDFSDK_JAVASCRIPT_DOCUMENT_H_ diff --git a/fpdfsdk/javascript/Field.cpp b/fpdfsdk/javascript/Field.cpp deleted file mode 100644 index f37b3d486bc1b99061da699f196b23c0870e2318..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Field.cpp +++ /dev/null @@ -1,3405 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/Field.h" - -#include -#include -#include -#include - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfapi/page/cpdf_page.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfdoc/cpdf_interform.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/cpdfsdk_interform.h" -#include "fpdfsdk/cpdfsdk_pageview.h" -#include "fpdfsdk/cpdfsdk_widget.h" -#include "fpdfsdk/javascript/Document.h" -#include "fpdfsdk/javascript/Icon.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/PublicMethods.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/color.h" - -namespace { - -bool SetWidgetDisplayStatus(CPDFSDK_Widget* pWidget, int value) { - if (!pWidget) - return false; - - uint32_t dwFlag = pWidget->GetFlags(); - switch (value) { - case 0: - dwFlag &= ~ANNOTFLAG_INVISIBLE; - dwFlag &= ~ANNOTFLAG_HIDDEN; - dwFlag &= ~ANNOTFLAG_NOVIEW; - dwFlag |= ANNOTFLAG_PRINT; - break; - case 1: - dwFlag &= ~ANNOTFLAG_INVISIBLE; - dwFlag &= ~ANNOTFLAG_NOVIEW; - dwFlag |= (ANNOTFLAG_HIDDEN | ANNOTFLAG_PRINT); - break; - case 2: - dwFlag &= ~ANNOTFLAG_INVISIBLE; - dwFlag &= ~ANNOTFLAG_PRINT; - dwFlag &= ~ANNOTFLAG_HIDDEN; - dwFlag &= ~ANNOTFLAG_NOVIEW; - break; - case 3: - dwFlag |= ANNOTFLAG_NOVIEW; - dwFlag |= ANNOTFLAG_PRINT; - dwFlag &= ~ANNOTFLAG_HIDDEN; - break; - } - - if (dwFlag != pWidget->GetFlags()) { - pWidget->SetFlags(dwFlag); - return true; - } - - return false; -} - -} // namespace - -JSConstSpec CJS_Field::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Field::PropertySpecs[] = { - {"alignment", get_alignment_static, set_alignment_static}, - {"borderStyle", get_borderStyle_static, set_borderStyle_static}, - {"buttonAlignX", get_buttonAlignX_static, set_buttonAlignX_static}, - {"buttonAlignY", get_buttonAlignY_static, set_buttonAlignY_static}, - {"buttonFitBounds", get_buttonFitBounds_static, set_buttonFitBounds_static}, - {"buttonPosition", get_buttonPosition_static, set_buttonPosition_static}, - {"buttonScaleHow", get_buttonScaleHow_static, set_buttonScaleHow_static}, - {"buttonScaleWhen", get_buttonScaleWhen_static, set_buttonScaleWhen_static}, - {"calcOrderIndex", get_calcOrderIndex_static, set_calcOrderIndex_static}, - {"charLimit", get_charLimit_static, set_charLimit_static}, - {"comb", get_comb_static, set_comb_static}, - {"commitOnSelChange", get_commitOnSelChange_static, - set_commitOnSelChange_static}, - {"currentValueIndices", get_currentValueIndices_static, - set_currentValueIndices_static}, - {"defaultStyle", get_defaultStyle_static, set_defaultStyle_static}, - {"defaultValue", get_defaultValue_static, set_defaultValue_static}, - {"doNotScroll", get_doNotScroll_static, set_doNotScroll_static}, - {"doNotSpellCheck", get_doNotSpellCheck_static, set_doNotSpellCheck_static}, - {"delay", get_delay_static, set_delay_static}, - {"display", get_display_static, set_display_static}, - {"doc", get_doc_static, set_doc_static}, - {"editable", get_editable_static, set_editable_static}, - {"exportValues", get_exportValues_static, set_exportValues_static}, - {"hidden", get_hidden_static, set_hidden_static}, - {"fileSelect", get_fileSelect_static, set_fileSelect_static}, - {"fillColor", get_fillColor_static, set_fillColor_static}, - {"lineWidth", get_lineWidth_static, set_lineWidth_static}, - {"highlight", get_highlight_static, set_highlight_static}, - {"multiline", get_multiline_static, set_multiline_static}, - {"multipleSelection", get_multipleSelection_static, - set_multipleSelection_static}, - {"name", get_name_static, set_name_static}, - {"numItems", get_numItems_static, set_numItems_static}, - {"page", get_page_static, set_page_static}, - {"password", get_password_static, set_password_static}, - {"print", get_print_static, set_print_static}, - {"radiosInUnison", get_radiosInUnison_static, set_radiosInUnison_static}, - {"readonly", get_readonly_static, set_readonly_static}, - {"rect", get_rect_static, set_rect_static}, - {"required", get_required_static, set_required_static}, - {"richText", get_richText_static, set_richText_static}, - {"richValue", get_richValue_static, set_richValue_static}, - {"rotation", get_rotation_static, set_rotation_static}, - {"strokeColor", get_strokeColor_static, set_strokeColor_static}, - {"style", get_style_static, set_style_static}, - {"submitName", get_submitName_static, set_submitName_static}, - {"textColor", get_textColor_static, set_textColor_static}, - {"textFont", get_textFont_static, set_textFont_static}, - {"textSize", get_textSize_static, set_textSize_static}, - {"type", get_type_static, set_type_static}, - {"userName", get_userName_static, set_userName_static}, - {"value", get_value_static, set_value_static}, - {"valueAsString", get_valueAsString_static, set_valueAsString_static}, - {"source", get_source_static, set_source_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_Field::MethodSpecs[] = { - {"browseForFileToSubmit", browseForFileToSubmit_static}, - {"buttonGetCaption", buttonGetCaption_static}, - {"buttonGetIcon", buttonGetIcon_static}, - {"buttonImportIcon", buttonImportIcon_static}, - {"buttonSetCaption", buttonSetCaption_static}, - {"buttonSetIcon", buttonSetIcon_static}, - {"checkThisBox", checkThisBox_static}, - {"clearItems", clearItems_static}, - {"defaultIsChecked", defaultIsChecked_static}, - {"deleteItemAt", deleteItemAt_static}, - {"getArray", getArray_static}, - {"getItemAt", getItemAt_static}, - {"getLock", getLock_static}, - {"insertItemAt", insertItemAt_static}, - {"isBoxChecked", isBoxChecked_static}, - {"isDefaultChecked", isDefaultChecked_static}, - {"setAction", setAction_static}, - {"setFocus", setFocus_static}, - {"setItems", setItems_static}, - {"setLock", setLock_static}, - {"signatureGetModifications", signatureGetModifications_static}, - {"signatureGetSeedValue", signatureGetSeedValue_static}, - {"signatureInfo", signatureInfo_static}, - {"signatureSetSeedValue", signatureSetSeedValue_static}, - {"signatureSign", signatureSign_static}, - {"signatureValidate", signatureValidate_static}, - {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Field, Field) - -CJS_DelayData::CJS_DelayData(FIELD_PROP prop, - int idx, - const CFX_WideString& name) - : eProp(prop), nControlIndex(idx), sFieldName(name) {} - -CJS_DelayData::~CJS_DelayData() {} - -void CJS_Field::InitInstance(IJS_Runtime* pIRuntime) { -} - -Field::Field(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject), - m_pJSDoc(nullptr), - m_pFormFillEnv(nullptr), - m_nFormControlIndex(-1), - m_bCanSet(false), - m_bDelay(false) {} - -Field::~Field() {} - -// note: iControlNo = -1, means not a widget. -void Field::ParseFieldName(const std::wstring& strFieldNameParsed, - std::wstring& strFieldName, - int& iControlNo) { - int iStart = strFieldNameParsed.find_last_of(L'.'); - if (iStart == -1) { - strFieldName = strFieldNameParsed; - iControlNo = -1; - return; - } - std::wstring suffixal = strFieldNameParsed.substr(iStart + 1); - iControlNo = FXSYS_wtoi(suffixal.c_str()); - if (iControlNo == 0) { - int iSpaceStart; - while ((iSpaceStart = suffixal.find_last_of(L" ")) != -1) { - suffixal.erase(iSpaceStart, 1); - } - - if (suffixal.compare(L"0") != 0) { - strFieldName = strFieldNameParsed; - iControlNo = -1; - return; - } - } - strFieldName = strFieldNameParsed.substr(0, iStart); -} - -bool Field::AttachField(Document* pDocument, - const CFX_WideString& csFieldName) { - m_pJSDoc = pDocument; - m_pFormFillEnv.Reset(pDocument->GetFormFillEnv()); - m_bCanSet = m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM) || - m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || - m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY); - - CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm(); - CFX_WideString swFieldNameTemp = csFieldName; - swFieldNameTemp.Replace(L"..", L"."); - - if (pInterForm->CountFields(swFieldNameTemp) <= 0) { - std::wstring strFieldName; - int iControlNo = -1; - ParseFieldName(swFieldNameTemp.c_str(), strFieldName, iControlNo); - if (iControlNo == -1) - return false; - - m_FieldName = strFieldName.c_str(); - m_nFormControlIndex = iControlNo; - return true; - } - - m_FieldName = swFieldNameTemp; - m_nFormControlIndex = -1; - - return true; -} - -std::vector Field::GetFormFields( - CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& csFieldName) { - std::vector fields; - CPDFSDK_InterForm* pReaderInterForm = pFormFillEnv->GetInterForm(); - CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm(); - for (int i = 0, sz = pInterForm->CountFields(csFieldName); i < sz; ++i) { - if (CPDF_FormField* pFormField = pInterForm->GetField(i, csFieldName)) - fields.push_back(pFormField); - } - return fields; -} - -std::vector Field::GetFormFields( - const CFX_WideString& csFieldName) const { - return Field::GetFormFields(m_pFormFillEnv.Get(), csFieldName); -} - -void Field::UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDF_FormField* pFormField, - bool bChangeMark, - bool bResetAP, - bool bRefresh) { - CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); - - if (bResetAP) { - std::vector widgets; - pInterForm->GetWidgets(pFormField, &widgets); - - int nFieldType = pFormField->GetFieldType(); - if (nFieldType == FIELDTYPE_COMBOBOX || nFieldType == FIELDTYPE_TEXTFIELD) { - for (auto& pObserved : widgets) { - if (pObserved) { - bool bFormatted = false; - CFX_WideString sValue = static_cast(pObserved.Get()) - ->OnFormat(bFormatted); - if (pObserved) { // Not redundant, may be clobbered by OnFormat. - static_cast(pObserved.Get()) - ->ResetAppearance(bFormatted ? &sValue : nullptr, false); - } - } - } - } else { - for (auto& pObserved : widgets) { - if (pObserved) { - static_cast(pObserved.Get()) - ->ResetAppearance(nullptr, false); - } - } - } - } - - if (bRefresh) { - // Refresh the widget list. The calls in |bResetAP| may have caused widgets - // to be removed from the list. We need to call |GetWidgets| again to be - // sure none of the widgets have been deleted. - std::vector widgets; - pInterForm->GetWidgets(pFormField, &widgets); - - // TODO(dsinclair): Determine if all widgets share the same - // CPDFSDK_InterForm. If that's the case, we can move the code to - // |GetFormFillEnv| out of the loop. - for (auto& pObserved : widgets) { - if (pObserved) { - CPDFSDK_Widget* pWidget = static_cast(pObserved.Get()); - pWidget->GetInterForm()->GetFormFillEnv()->UpdateAllViews(nullptr, - pWidget); - } - } - } - - if (bChangeMark) - pFormFillEnv->SetChangeMark(); -} - -void Field::UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDF_FormControl* pFormControl, - bool bChangeMark, - bool bResetAP, - bool bRefresh) { - ASSERT(pFormControl); - - CPDFSDK_InterForm* pForm = pFormFillEnv->GetInterForm(); - CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl); - - if (pWidget) { - if (bResetAP) { - int nFieldType = pWidget->GetFieldType(); - if (nFieldType == FIELDTYPE_COMBOBOX || - nFieldType == FIELDTYPE_TEXTFIELD) { - bool bFormatted = false; - CFX_WideString sValue = pWidget->OnFormat(bFormatted); - pWidget->ResetAppearance(bFormatted ? &sValue : nullptr, false); - } else { - pWidget->ResetAppearance(nullptr, false); - } - } - - if (bRefresh) { - CPDFSDK_InterForm* pInterForm = pWidget->GetInterForm(); - pInterForm->GetFormFillEnv()->UpdateAllViews(nullptr, pWidget); - } - } - - if (bChangeMark) - pFormFillEnv->SetChangeMark(); -} - -CPDFSDK_Widget* Field::GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDF_FormControl* pFormControl) { - CPDFSDK_InterForm* pInterForm = - static_cast(pFormFillEnv->GetInterForm()); - return pInterForm ? pInterForm->GetWidget(pFormControl) : nullptr; -} - -bool Field::ValueIsOccur(CPDF_FormField* pFormField, - CFX_WideString csOptLabel) { - for (int i = 0, sz = pFormField->CountOptions(); i < sz; i++) { - if (csOptLabel.Compare(pFormField->GetOptionLabel(i)) == 0) - return true; - } - - return false; -} - -CPDF_FormControl* Field::GetSmartFieldControl(CPDF_FormField* pFormField) { - if (!pFormField->CountControls() || - m_nFormControlIndex >= pFormField->CountControls()) - return nullptr; - - if (m_nFormControlIndex < 0) - return pFormField->GetControl(0); - - return pFormField->GetControl(m_nFormControlIndex); -} - -bool Field::alignment(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_ByteString alignStr; - vp >> alignStr; - - if (m_bDelay) { - AddDelay_String(FP_ALIGNMENT, alignStr); - } else { - Field::SetAlignment(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, alignStr); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - switch (pFormControl->GetControlAlignment()) { - case 1: - vp << L"center"; - break; - case 0: - vp << L"left"; - break; - case 2: - vp << L"right"; - break; - default: - vp << L""; - } - } - - return true; -} - -void Field::SetAlignment(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string) { - // Not supported. -} - -bool Field::borderStyle(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_ByteString strType = ""; - vp >> strType; - - if (m_bDelay) { - AddDelay_String(FP_BORDERSTYLE, strType); - } else { - Field::SetBorderStyle(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, strType); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (!pFormField) - return false; - - CPDFSDK_Widget* pWidget = - GetWidget(m_pFormFillEnv.Get(), GetSmartFieldControl(pFormField)); - if (!pWidget) - return false; - - switch (pWidget->GetBorderStyle()) { - case BorderStyle::SOLID: - vp << L"solid"; - break; - case BorderStyle::DASH: - vp << L"dashed"; - break; - case BorderStyle::BEVELED: - vp << L"beveled"; - break; - case BorderStyle::INSET: - vp << L"inset"; - break; - case BorderStyle::UNDERLINE: - vp << L"underline"; - break; - default: - vp << L""; - break; - } - } - - return true; -} - -void Field::SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string) { - ASSERT(pFormFillEnv); - - BorderStyle nBorderStyle = BorderStyle::SOLID; - if (string == "solid") - nBorderStyle = BorderStyle::SOLID; - else if (string == "beveled") - nBorderStyle = BorderStyle::BEVELED; - else if (string == "dashed") - nBorderStyle = BorderStyle::DASH; - else if (string == "inset") - nBorderStyle = BorderStyle::INSET; - else if (string == "underline") - nBorderStyle = BorderStyle::UNDERLINE; - else - return; - - std::vector FieldArray = - GetFormFields(pFormFillEnv, swFieldName); - for (CPDF_FormField* pFormField : FieldArray) { - if (nControlIndex < 0) { - bool bSet = false; - for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { - if (CPDFSDK_Widget* pWidget = - GetWidget(pFormFillEnv, pFormField->GetControl(i))) { - if (pWidget->GetBorderStyle() != nBorderStyle) { - pWidget->SetBorderStyle(nBorderStyle); - bSet = true; - } - } - } - if (bSet) - UpdateFormField(pFormFillEnv, pFormField, true, true, true); - } else { - if (nControlIndex >= pFormField->CountControls()) - return; - if (CPDF_FormControl* pFormControl = - pFormField->GetControl(nControlIndex)) { - if (CPDFSDK_Widget* pWidget = GetWidget(pFormFillEnv, pFormControl)) { - if (pWidget->GetBorderStyle() != nBorderStyle) { - pWidget->SetBorderStyle(nBorderStyle); - UpdateFormControl(pFormFillEnv, pFormControl, true, true, true); - } - } - } - } - } -} - -bool Field::buttonAlignX(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_BUTTONALIGNX, nVP); - } else { - Field::SetButtonAlignX(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CPDF_IconFit IconFit = pFormControl->GetIconFit(); - - FX_FLOAT fLeft, fBottom; - IconFit.GetIconPosition(fLeft, fBottom); - - vp << (int32_t)fLeft; - } - - return true; -} - -void Field::SetButtonAlignX(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::buttonAlignY(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_BUTTONALIGNY, nVP); - } else { - Field::SetButtonAlignY(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CPDF_IconFit IconFit = pFormControl->GetIconFit(); - - FX_FLOAT fLeft, fBottom; - IconFit.GetIconPosition(fLeft, fBottom); - - vp << (int32_t)fBottom; - } - - return true; -} - -void Field::SetButtonAlignY(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::buttonFitBounds(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - - if (m_bDelay) { - AddDelay_Bool(FP_BUTTONFITBOUNDS, bVP); - } else { - Field::SetButtonFitBounds(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, bVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - vp << pFormControl->GetIconFit().GetFittingBounds(); - } - - return true; -} - -void Field::SetButtonFitBounds(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::buttonPosition(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_BUTTONPOSITION, nVP); - } else { - Field::SetButtonPosition(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - vp << pFormControl->GetTextPosition(); - } - return true; -} - -void Field::SetButtonPosition(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::buttonScaleHow(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_BUTTONSCALEHOW, nVP); - } else { - Field::SetButtonScaleHow(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CPDF_IconFit IconFit = pFormControl->GetIconFit(); - if (IconFit.IsProportionalScale()) - vp << (int32_t)0; - else - vp << (int32_t)1; - } - - return true; -} - -void Field::SetButtonScaleHow(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::buttonScaleWhen(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_BUTTONSCALEWHEN, nVP); - } else { - Field::SetButtonScaleWhen(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CPDF_IconFit IconFit = pFormControl->GetIconFit(); - int ScaleM = IconFit.GetScaleMethod(); - switch (ScaleM) { - case CPDF_IconFit::Always: - vp << (int32_t)CPDF_IconFit::Always; - break; - case CPDF_IconFit::Bigger: - vp << (int32_t)CPDF_IconFit::Bigger; - break; - case CPDF_IconFit::Never: - vp << (int32_t)CPDF_IconFit::Never; - break; - case CPDF_IconFit::Smaller: - vp << (int32_t)CPDF_IconFit::Smaller; - break; - } - } - - return true; -} - -void Field::SetButtonScaleWhen(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::calcOrderIndex(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_CALCORDERINDEX, nVP); - } else { - Field::SetCalcOrderIndex(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX && - pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) { - return false; - } - - CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm(); - CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm(); - vp << (int32_t)pInterForm->FindFieldInCalculationOrder(pFormField); - } - - return true; -} - -void Field::SetCalcOrderIndex(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::charLimit(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - - if (m_bDelay) { - AddDelay_Int(FP_CHARLIMIT, nVP); - } else { - Field::SetCharLimit(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, nVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - vp << (int32_t)pFormField->GetMaxLen(); - } - return true; -} - -void Field::SetCharLimit(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::comb(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - - if (m_bDelay) { - AddDelay_Bool(FP_COMB, bVP); - } else { - Field::SetComb(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - bVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - if (pFormField->GetFieldFlags() & FIELDFLAG_COMB) - vp << true; - else - vp << false; - } - - return true; -} - -void Field::SetComb(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::commitOnSelChange(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - - if (m_bDelay) { - AddDelay_Bool(FP_COMMITONSELCHANGE, bVP); - } else { - Field::SetCommitOnSelChange(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, bVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX && - pFormField->GetFieldType() != FIELDTYPE_LISTBOX) { - return false; - } - - if (pFormField->GetFieldFlags() & FIELDFLAG_COMMITONSELCHANGE) - vp << true; - else - vp << false; - } - - return true; -} - -void Field::SetCommitOnSelChange(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::currentValueIndices(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - std::vector array; - if (vp.GetJSValue()->GetType() == CJS_Value::VT_number) { - int iSelecting = 0; - vp >> iSelecting; - array.push_back(iSelecting); - } else if (vp.GetJSValue()->IsArrayObject()) { - CJS_Array SelArray; - CJS_Value SelValue(pRuntime); - int iSelecting; - vp >> SelArray; - for (int i = 0, sz = SelArray.GetLength(pRuntime); i < sz; i++) { - SelArray.GetElement(pRuntime, i, SelValue); - iSelecting = SelValue.ToInt(pRuntime); - array.push_back(iSelecting); - } - } - - if (m_bDelay) { - AddDelay_WordArray(FP_CURRENTVALUEINDICES, array); - } else { - Field::SetCurrentValueIndices(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, array); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX && - pFormField->GetFieldType() != FIELDTYPE_LISTBOX) { - return false; - } - - if (pFormField->CountSelectedItems() == 1) { - vp << pFormField->GetSelectedIndex(0); - } else if (pFormField->CountSelectedItems() > 1) { - CJS_Array SelArray; - for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) { - SelArray.SetElement( - pRuntime, i, CJS_Value(pRuntime, pFormField->GetSelectedIndex(i))); - } - vp << SelArray; - } else { - vp << -1; - } - } - - return true; -} - -void Field::SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const std::vector& array) { - ASSERT(pFormFillEnv); - std::vector FieldArray = - GetFormFields(pFormFillEnv, swFieldName); - - for (CPDF_FormField* pFormField : FieldArray) { - int nFieldType = pFormField->GetFieldType(); - if (nFieldType == FIELDTYPE_COMBOBOX || nFieldType == FIELDTYPE_LISTBOX) { - uint32_t dwFieldFlags = pFormField->GetFieldFlags(); - pFormField->ClearSelection(true); - for (size_t i = 0; i < array.size(); ++i) { - if (i != 0 && !(dwFieldFlags & (1 << 21))) - break; - if (array[i] < static_cast(pFormField->CountOptions()) && - !pFormField->IsItemSelected(array[i])) { - pFormField->SetItemSelection(array[i], true); - } - } - UpdateFormField(pFormFillEnv, pFormField, true, true, true); - } - } -} - -bool Field::defaultStyle(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return false; -} - -void Field::SetDefaultStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex) { - // Not supported. -} - -bool Field::defaultValue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_WideString WideStr; - vp >> WideStr; - - if (m_bDelay) { - AddDelay_WideString(FP_DEFAULTVALUE, WideStr); - } else { - Field::SetDefaultValue(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, WideStr); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() == FIELDTYPE_PUSHBUTTON || - pFormField->GetFieldType() == FIELDTYPE_SIGNATURE) { - return false; - } - - vp << pFormField->GetDefaultValue(); - } - return true; -} - -void Field::SetDefaultValue(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_WideString& string) { - // Not supported. -} - -bool Field::doNotScroll(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - - if (m_bDelay) { - AddDelay_Bool(FP_DONOTSCROLL, bVP); - } else { - Field::SetDoNotScroll(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, bVP); - } - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - if (pFormField->GetFieldFlags() & FIELDFLAG_DONOTSCROLL) - vp << true; - else - vp << false; - } - - return true; -} - -void Field::SetDoNotScroll(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::doNotSpellCheck(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - } else { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD && - pFormField->GetFieldType() != FIELDTYPE_COMBOBOX) { - return false; - } - - if (pFormField->GetFieldFlags() & FIELDFLAG_DONOTSPELLCHECK) - vp << true; - else - vp << false; - } - - return true; -} - -void Field::SetDelay(bool bDelay) { - m_bDelay = bDelay; - - if (!m_bDelay) { - if (m_pJSDoc) - m_pJSDoc->DoFieldDelay(m_FieldName, m_nFormControlIndex); - } -} - -bool Field::delay(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsSetting()) { - vp << m_bDelay; - return true; - } - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - SetDelay(bVP); - return true; -} - -bool Field::display(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - if (m_bDelay) { - AddDelay_Int(FP_DISPLAY, nVP); - } else { - Field::SetDisplay(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - nVP); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - ASSERT(pFormField); - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDFSDK_Widget* pWidget = - pInterForm->GetWidget(GetSmartFieldControl(pFormField)); - if (!pWidget) - return false; - - uint32_t dwFlag = pWidget->GetFlags(); - if (ANNOTFLAG_INVISIBLE & dwFlag || ANNOTFLAG_HIDDEN & dwFlag) { - vp << (int32_t)1; - } else { - if (ANNOTFLAG_PRINT & dwFlag) { - if (ANNOTFLAG_NOVIEW & dwFlag) { - vp << (int32_t)3; - } else { - vp << (int32_t)0; - } - } else { - vp << (int32_t)2; - } - } - return true; -} - -void Field::SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); - std::vector FieldArray = - GetFormFields(pFormFillEnv, swFieldName); - for (CPDF_FormField* pFormField : FieldArray) { - if (nControlIndex < 0) { - bool bAnySet = false; - for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { - CPDF_FormControl* pFormControl = pFormField->GetControl(i); - ASSERT(pFormControl); - - CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl); - if (SetWidgetDisplayStatus(pWidget, number)) - bAnySet = true; - } - - if (bAnySet) - UpdateFormField(pFormFillEnv, pFormField, true, false, true); - } else { - if (nControlIndex >= pFormField->CountControls()) - return; - - CPDF_FormControl* pFormControl = pFormField->GetControl(nControlIndex); - if (!pFormControl) - return; - - CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl); - if (SetWidgetDisplayStatus(pWidget, number)) - UpdateFormControl(pFormFillEnv, pFormControl, true, false, true); - } - } -} - -bool Field::doc(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - vp << m_pJSDoc->GetCJSDoc(); - return true; -} - -bool Field::editable(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX) - return false; - - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_EDIT); - return true; -} - -bool Field::exportValues(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_CHECKBOX && - pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON) { - return false; - } - if (vp.IsSetting()) - return m_bCanSet && vp.GetJSValue()->IsArrayObject(); - - CJS_Array ExportValusArray; - if (m_nFormControlIndex < 0) { - for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { - CPDF_FormControl* pFormControl = pFormField->GetControl(i); - ExportValusArray.SetElement( - pRuntime, i, - CJS_Value(pRuntime, pFormControl->GetExportValue().c_str())); - } - } else { - if (m_nFormControlIndex >= pFormField->CountControls()) - return false; - - CPDF_FormControl* pFormControl = - pFormField->GetControl(m_nFormControlIndex); - if (!pFormControl) - return false; - - ExportValusArray.SetElement( - pRuntime, 0, - CJS_Value(pRuntime, pFormControl->GetExportValue().c_str())); - } - vp << ExportValusArray; - return true; -} - -bool Field::fileSelect(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - return true; - } - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT); - return true; -} - -bool Field::fillColor(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_Array crArray; - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - if (!vp.GetJSValue()->IsArrayObject()) - return false; - - vp >> crArray; - - CPWL_Color color; - color::ConvertArrayToPWLColor(pRuntime, crArray, &color); - if (m_bDelay) { - AddDelay_Color(FP_FILLCOLOR, color); - } else { - Field::SetFillColor(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, color); - } - return true; - } - CPDF_FormField* pFormField = FieldArray[0]; - ASSERT(pFormField); - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - int iColorType; - pFormControl->GetBackgroundColor(iColorType); - - CPWL_Color color; - if (iColorType == COLORTYPE_TRANSPARENT) { - color = CPWL_Color(COLORTYPE_TRANSPARENT); - } else if (iColorType == COLORTYPE_GRAY) { - color = - CPWL_Color(COLORTYPE_GRAY, pFormControl->GetOriginalBackgroundColor(0)); - } else if (iColorType == COLORTYPE_RGB) { - color = - CPWL_Color(COLORTYPE_RGB, pFormControl->GetOriginalBackgroundColor(0), - pFormControl->GetOriginalBackgroundColor(1), - pFormControl->GetOriginalBackgroundColor(2)); - } else if (iColorType == COLORTYPE_CMYK) { - color = - CPWL_Color(COLORTYPE_CMYK, pFormControl->GetOriginalBackgroundColor(0), - pFormControl->GetOriginalBackgroundColor(1), - pFormControl->GetOriginalBackgroundColor(2), - pFormControl->GetOriginalBackgroundColor(3)); - } else { - return false; - } - color::ConvertPWLColorToArray(pRuntime, color, &crArray); - vp << crArray; - return true; -} - -void Field::SetFillColor(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CPWL_Color& color) { - // Not supported. -} - -bool Field::hidden(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - if (m_bDelay) { - AddDelay_Bool(FP_HIDDEN, bVP); - } else { - Field::SetHidden(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - bVP); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - ASSERT(pFormField); - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDFSDK_Widget* pWidget = - pInterForm->GetWidget(GetSmartFieldControl(pFormField)); - if (!pWidget) - return false; - - uint32_t dwFlags = pWidget->GetFlags(); - if (ANNOTFLAG_INVISIBLE & dwFlags || ANNOTFLAG_HIDDEN & dwFlags) - vp << true; - else - vp << false; - - return true; -} - -void Field::SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - int display = b ? 1 /*Hidden*/ : 0 /*Visible*/; - SetDisplay(pFormFillEnv, swFieldName, nControlIndex, display); -} - -bool Field::highlight(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_ByteString strMode; - vp >> strMode; - - if (m_bDelay) { - AddDelay_String(FP_HIGHLIGHT, strMode); - } else { - Field::SetHighlight(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, strMode); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - int eHM = pFormControl->GetHighlightingMode(); - switch (eHM) { - case CPDF_FormControl::None: - vp << L"none"; - break; - case CPDF_FormControl::Push: - vp << L"push"; - break; - case CPDF_FormControl::Invert: - vp << L"invert"; - break; - case CPDF_FormControl::Outline: - vp << L"outline"; - break; - case CPDF_FormControl::Toggle: - vp << L"toggle"; - break; - } - return true; -} - -void Field::SetHighlight(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string) { - // Not supported. -} - -bool Field::lineWidth(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int iWidth; - vp >> iWidth; - - if (m_bDelay) { - AddDelay_Int(FP_LINEWIDTH, iWidth); - } else { - Field::SetLineWidth(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, iWidth); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - ASSERT(pFormField); - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - if (!pFormField->CountControls()) - return false; - - CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormField->GetControl(0)); - if (!pWidget) - return false; - - vp << (int32_t)pWidget->GetBorderWidth(); - return true; -} - -void Field::SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); - std::vector FieldArray = - GetFormFields(pFormFillEnv, swFieldName); - for (CPDF_FormField* pFormField : FieldArray) { - if (nControlIndex < 0) { - bool bSet = false; - for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { - CPDF_FormControl* pFormControl = pFormField->GetControl(i); - ASSERT(pFormControl); - - if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { - if (number != pWidget->GetBorderWidth()) { - pWidget->SetBorderWidth(number); - bSet = true; - } - } - } - if (bSet) - UpdateFormField(pFormFillEnv, pFormField, true, true, true); - } else { - if (nControlIndex >= pFormField->CountControls()) - return; - if (CPDF_FormControl* pFormControl = - pFormField->GetControl(nControlIndex)) { - if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { - if (number != pWidget->GetBorderWidth()) { - pWidget->SetBorderWidth(number); - UpdateFormControl(pFormFillEnv, pFormControl, true, true, true); - } - } - } - } - } -} - -bool Field::multiline(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - - if (m_bDelay) { - AddDelay_Bool(FP_MULTILINE, bVP); - } else { - Field::SetMultiline(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, bVP); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - if (pFormField->GetFieldFlags() & FIELDFLAG_MULTILINE) - vp << true; - else - vp << false; - - return true; -} - -void Field::SetMultiline(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::multipleSelection(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - if (m_bDelay) { - AddDelay_Bool(FP_MULTIPLESELECTION, bVP); - } else { - Field::SetMultipleSelection(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, bVP); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_LISTBOX) - return false; - - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_MULTISELECT); - return true; -} - -void Field::SetMultipleSelection(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::name(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - vp << m_FieldName; - return true; -} - -bool Field::numItems(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX && - pFormField->GetFieldType() != FIELDTYPE_LISTBOX) { - return false; - } - - vp << (int32_t)pFormField->CountOptions(); - return true; -} - -bool Field::page(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) { - sError = JSGetStringFromID(IDS_STRING_JSREADONLY); - return false; - } - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (!pFormField) - return false; - - std::vector widgets; - m_pFormFillEnv->GetInterForm()->GetWidgets(pFormField, &widgets); - if (widgets.empty()) { - vp << (int32_t)-1; - return true; - } - - CJS_Array PageArray; - int i = 0; - for (const auto& pObserved : widgets) { - if (!pObserved) { - sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT); - return false; - } - - auto pWidget = static_cast(pObserved.Get()); - CPDFSDK_PageView* pPageView = pWidget->GetPageView(); - if (!pPageView) - return false; - - PageArray.SetElement( - pRuntime, i, CJS_Value(pRuntime, (int32_t)pPageView->GetPageIndex())); - ++i; - } - - vp << PageArray; - return true; -} - -bool Field::password(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - if (m_bDelay) { - AddDelay_Bool(FP_PASSWORD, bVP); - } else { - Field::SetPassword(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - bVP); - } - return true; - } - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_PASSWORD); - return true; -} - -void Field::SetPassword(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b) { - // Not supported. -} - -bool Field::print(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - - for (CPDF_FormField* pFormField : FieldArray) { - if (m_nFormControlIndex < 0) { - bool bSet = false; - for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { - if (CPDFSDK_Widget* pWidget = - pInterForm->GetWidget(pFormField->GetControl(i))) { - uint32_t dwFlags = pWidget->GetFlags(); - if (bVP) - dwFlags |= ANNOTFLAG_PRINT; - else - dwFlags &= ~ANNOTFLAG_PRINT; - - if (dwFlags != pWidget->GetFlags()) { - pWidget->SetFlags(dwFlags); - bSet = true; - } - } - } - - if (bSet) - UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, false, true); - } else { - if (m_nFormControlIndex >= pFormField->CountControls()) - return false; - if (CPDF_FormControl* pFormControl = - pFormField->GetControl(m_nFormControlIndex)) { - if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { - uint32_t dwFlags = pWidget->GetFlags(); - if (bVP) - dwFlags |= ANNOTFLAG_PRINT; - else - dwFlags &= ~ANNOTFLAG_PRINT; - - if (dwFlags != pWidget->GetFlags()) { - pWidget->SetFlags(dwFlags); - UpdateFormControl(m_pFormFillEnv.Get(), - pFormField->GetControl(m_nFormControlIndex), - true, false, true); - } - } - } - } - } - return true; - } - - CPDF_FormField* pFormField = FieldArray[0]; - CPDFSDK_Widget* pWidget = - pInterForm->GetWidget(GetSmartFieldControl(pFormField)); - if (!pWidget) - return false; - - vp << !!(pWidget->GetFlags() & ANNOTFLAG_PRINT); - return true; -} - -bool Field::radiosInUnison(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - return true; - } - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON) - return false; - - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON); - return true; -} - -bool Field::readonly(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - return true; - } - vp << !!(FieldArray[0]->GetFieldFlags() & FIELDFLAG_READONLY); - return true; -} - -bool Field::rect(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_Value Upper_Leftx(pRuntime); - CJS_Value Upper_Lefty(pRuntime); - CJS_Value Lower_Rightx(pRuntime); - CJS_Value Lower_Righty(pRuntime); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - if (!vp.GetJSValue()->IsArrayObject()) - return false; - - CJS_Array rcArray; - vp >> rcArray; - rcArray.GetElement(pRuntime, 0, Upper_Leftx); - rcArray.GetElement(pRuntime, 1, Upper_Lefty); - rcArray.GetElement(pRuntime, 2, Lower_Rightx); - rcArray.GetElement(pRuntime, 3, Lower_Righty); - - FX_FLOAT pArray[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - pArray[0] = static_cast(Upper_Leftx.ToInt(pRuntime)); - pArray[1] = static_cast(Lower_Righty.ToInt(pRuntime)); - pArray[2] = static_cast(Lower_Rightx.ToInt(pRuntime)); - pArray[3] = static_cast(Upper_Lefty.ToInt(pRuntime)); - - CFX_FloatRect crRect(pArray); - if (m_bDelay) { - AddDelay_Rect(FP_RECT, crRect); - } else { - Field::SetRect(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - crRect); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDFSDK_Widget* pWidget = - pInterForm->GetWidget(GetSmartFieldControl(pFormField)); - if (!pWidget) - return false; - - CFX_FloatRect crRect = pWidget->GetRect(); - Upper_Leftx = CJS_Value(pRuntime, static_cast(crRect.left)); - Upper_Lefty = CJS_Value(pRuntime, static_cast(crRect.top)); - Lower_Rightx = CJS_Value(pRuntime, static_cast(crRect.right)); - Lower_Righty = CJS_Value(pRuntime, static_cast(crRect.bottom)); - - CJS_Array rcArray; - rcArray.SetElement(pRuntime, 0, Upper_Leftx); - rcArray.SetElement(pRuntime, 1, Upper_Lefty); - rcArray.SetElement(pRuntime, 2, Lower_Rightx); - rcArray.SetElement(pRuntime, 3, Lower_Righty); - vp << rcArray; - return true; -} - -void Field::SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_FloatRect& rect) { - CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); - std::vector FieldArray = - GetFormFields(pFormFillEnv, swFieldName); - for (CPDF_FormField* pFormField : FieldArray) { - if (nControlIndex < 0) { - bool bSet = false; - for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { - CPDF_FormControl* pFormControl = pFormField->GetControl(i); - ASSERT(pFormControl); - - if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { - CFX_FloatRect crRect = rect; - - CPDF_Page* pPDFPage = pWidget->GetPDFPage(); - crRect.Intersect(pPDFPage->GetPageBBox()); - - if (!crRect.IsEmpty()) { - CFX_FloatRect rcOld = pWidget->GetRect(); - if (crRect.left != rcOld.left || crRect.right != rcOld.right || - crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) { - pWidget->SetRect(crRect); - bSet = true; - } - } - } - } - - if (bSet) - UpdateFormField(pFormFillEnv, pFormField, true, true, true); - } else { - if (nControlIndex >= pFormField->CountControls()) - return; - if (CPDF_FormControl* pFormControl = - pFormField->GetControl(nControlIndex)) { - if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { - CFX_FloatRect crRect = rect; - - CPDF_Page* pPDFPage = pWidget->GetPDFPage(); - crRect.Intersect(pPDFPage->GetPageBBox()); - - if (!crRect.IsEmpty()) { - CFX_FloatRect rcOld = pWidget->GetRect(); - if (crRect.left != rcOld.left || crRect.right != rcOld.right || - crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) { - pWidget->SetRect(crRect); - UpdateFormControl(pFormFillEnv, pFormControl, true, true, true); - } - } - } - } - } - } -} - -bool Field::required(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - return true; - } - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() == FIELDTYPE_PUSHBUTTON) - return false; - - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_REQUIRED); - return true; -} - -bool Field::richText(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - bool bVP; - vp >> bVP; - if (m_bDelay) - AddDelay_Bool(FP_RICHTEXT, bVP); - - return true; - } - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) - return false; - - vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_RICHTEXT); - return true; -} - -bool Field::richValue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Field::rotation(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - if (m_bDelay) { - AddDelay_Int(FP_ROTATION, nVP); - } else { - Field::SetRotation(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - nVP); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - vp << (int32_t)pFormControl->GetRotation(); - return true; -} - -void Field::SetRotation(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::strokeColor(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_Array crArray; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - if (!vp.GetJSValue()->IsArrayObject()) - return false; - - vp >> crArray; - - CPWL_Color color; - color::ConvertArrayToPWLColor(pRuntime, crArray, &color); - if (m_bDelay) { - AddDelay_Color(FP_STROKECOLOR, color); - } else { - Field::SetStrokeColor(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, color); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - int iColorType; - pFormControl->GetBorderColor(iColorType); - - CPWL_Color color; - if (iColorType == COLORTYPE_TRANSPARENT) { - color = CPWL_Color(COLORTYPE_TRANSPARENT); - } else if (iColorType == COLORTYPE_GRAY) { - color = CPWL_Color(COLORTYPE_GRAY, pFormControl->GetOriginalBorderColor(0)); - } else if (iColorType == COLORTYPE_RGB) { - color = CPWL_Color(COLORTYPE_RGB, pFormControl->GetOriginalBorderColor(0), - pFormControl->GetOriginalBorderColor(1), - pFormControl->GetOriginalBorderColor(2)); - } else if (iColorType == COLORTYPE_CMYK) { - color = CPWL_Color(COLORTYPE_CMYK, pFormControl->GetOriginalBorderColor(0), - pFormControl->GetOriginalBorderColor(1), - pFormControl->GetOriginalBorderColor(2), - pFormControl->GetOriginalBorderColor(3)); - } else { - return false; - } - - color::ConvertPWLColorToArray(pRuntime, color, &crArray); - vp << crArray; - return true; -} - -void Field::SetStrokeColor(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CPWL_Color& color) { - // Not supported. -} - -bool Field::style(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_ByteString csBCaption; - vp >> csBCaption; - - if (m_bDelay) { - AddDelay_String(FP_STYLE, csBCaption); - } else { - Field::SetStyle(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - csBCaption); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON && - pFormField->GetFieldType() != FIELDTYPE_CHECKBOX) { - return false; - } - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CFX_WideString csWCaption = pFormControl->GetNormalCaption(); - CFX_ByteString csBCaption; - - switch (csWCaption[0]) { - case L'l': - csBCaption = "circle"; - break; - case L'8': - csBCaption = "cross"; - break; - case L'u': - csBCaption = "diamond"; - break; - case L'n': - csBCaption = "square"; - break; - case L'H': - csBCaption = "star"; - break; - default: // L'4' - csBCaption = "check"; - break; - } - vp << csBCaption; - return true; -} - -void Field::SetStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string) { - // Not supported. -} - -bool Field::submitName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool Field::textColor(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_Array crArray; - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - if (!vp.GetJSValue()->IsArrayObject()) - return false; - - vp >> crArray; - - CPWL_Color color; - color::ConvertArrayToPWLColor(pRuntime, crArray, &color); - if (m_bDelay) { - AddDelay_Color(FP_TEXTCOLOR, color); - } else { - Field::SetTextColor(m_pFormFillEnv.Get(), m_FieldName, - m_nFormControlIndex, color); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - int iColorType; - FX_ARGB color; - CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance(); - FieldAppearance.GetColor(color, iColorType); - - int32_t a; - int32_t r; - int32_t g; - int32_t b; - ArgbDecode(color, a, r, g, b); - - CPWL_Color crRet = - CPWL_Color(COLORTYPE_RGB, r / 255.0f, g / 255.0f, b / 255.0f); - - if (iColorType == COLORTYPE_TRANSPARENT) - crRet = CPWL_Color(COLORTYPE_TRANSPARENT); - - color::ConvertPWLColorToArray(pRuntime, crRet, &crArray); - vp << crArray; - return true; -} - -void Field::SetTextColor(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CPWL_Color& color) { - // Not supported. -} - -bool Field::textFont(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_ByteString csFontName; - vp >> csFontName; - if (csFontName.IsEmpty()) - return false; - - if (m_bDelay) { - AddDelay_String(FP_TEXTFONT, csFontName); - } else { - Field::SetTextFont(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - csFontName); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - ASSERT(pFormField); - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - int nFieldType = pFormField->GetFieldType(); - if (nFieldType != FIELDTYPE_PUSHBUTTON && nFieldType != FIELDTYPE_COMBOBOX && - nFieldType != FIELDTYPE_LISTBOX && nFieldType != FIELDTYPE_TEXTFIELD) { - return false; - } - CPDF_Font* pFont = pFormControl->GetDefaultControlFont(); - if (!pFont) - return false; - - vp << pFont->GetBaseFont(); - return true; -} - -void Field::SetTextFont(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string) { - // Not supported. -} - -bool Field::textSize(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - int nVP; - vp >> nVP; - if (m_bDelay) { - AddDelay_Int(FP_TEXTSIZE, nVP); - } else { - Field::SetTextSize(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - nVP); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - ASSERT(pFormField); - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance(); - - CFX_ByteString csFontNameTag; - FX_FLOAT fFontSize; - FieldAppearance.GetFont(csFontNameTag, fFontSize); - vp << (int)fFontSize; - return true; -} - -void Field::SetTextSize(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number) { - // Not supported. -} - -bool Field::type(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - switch (pFormField->GetFieldType()) { - case FIELDTYPE_UNKNOWN: - vp << L"unknown"; - break; - case FIELDTYPE_PUSHBUTTON: - vp << L"button"; - break; - case FIELDTYPE_CHECKBOX: - vp << L"checkbox"; - break; - case FIELDTYPE_RADIOBUTTON: - vp << L"radiobutton"; - break; - case FIELDTYPE_COMBOBOX: - vp << L"combobox"; - break; - case FIELDTYPE_LISTBOX: - vp << L"listbox"; - break; - case FIELDTYPE_TEXTFIELD: - vp << L"text"; - break; - case FIELDTYPE_SIGNATURE: - vp << L"signature"; - break; - default: - vp << L"unknown"; - break; - } - return true; -} - -bool Field::userName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - ASSERT(m_pFormFillEnv); - - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - CFX_WideString swName; - vp >> swName; - - if (m_bDelay) { - AddDelay_WideString(FP_USERNAME, swName); - } else { - Field::SetUserName(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - swName); - } - return true; - } - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - vp << FieldArray[0]->GetAlternateName(); - return true; -} - -void Field::SetUserName(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_WideString& string) { - // Not supported. -} - -bool Field::value(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - if (!m_bCanSet) - return false; - - std::vector strArray; - if (vp.GetJSValue()->IsArrayObject()) { - CJS_Array ValueArray; - vp.GetJSValue()->ConvertToArray(pRuntime, ValueArray); - for (int i = 0, sz = ValueArray.GetLength(pRuntime); i < sz; i++) { - CJS_Value ElementValue(pRuntime); - ValueArray.GetElement(pRuntime, i, ElementValue); - strArray.push_back(ElementValue.ToCFXWideString(pRuntime)); - } - } else { - CFX_WideString swValue; - vp >> swValue; - strArray.push_back(swValue); - } - - if (m_bDelay) { - AddDelay_WideStringArray(FP_VALUE, strArray); - } else { - Field::SetValue(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, - strArray); - } - return true; - } - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - switch (pFormField->GetFieldType()) { - case FIELDTYPE_PUSHBUTTON: - return false; - case FIELDTYPE_COMBOBOX: - case FIELDTYPE_TEXTFIELD: { - vp << pFormField->GetValue(); - } break; - case FIELDTYPE_LISTBOX: { - if (pFormField->CountSelectedItems() > 1) { - CJS_Array ValueArray; - CJS_Value ElementValue(pRuntime); - int iIndex; - for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) { - iIndex = pFormField->GetSelectedIndex(i); - ElementValue = - CJS_Value(pRuntime, pFormField->GetOptionValue(iIndex).c_str()); - if (FXSYS_wcslen(ElementValue.ToCFXWideString(pRuntime).c_str()) == - 0) { - ElementValue = - CJS_Value(pRuntime, pFormField->GetOptionLabel(iIndex).c_str()); - } - ValueArray.SetElement(pRuntime, i, ElementValue); - } - vp << ValueArray; - } else { - vp << pFormField->GetValue(); - } - } break; - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: { - bool bFind = false; - for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { - if (pFormField->GetControl(i)->IsChecked()) { - vp << pFormField->GetControl(i)->GetExportValue(); - bFind = true; - break; - } - } - if (!bFind) - vp << L"Off"; - } break; - default: - vp << pFormField->GetValue(); - break; - } - vp.GetJSValue()->MaybeCoerceToNumber(pRuntime); - return true; -} - -void Field::SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const std::vector& strArray) { - ASSERT(pFormFillEnv); - if (strArray.empty()) - return; - - std::vector FieldArray = - GetFormFields(pFormFillEnv, swFieldName); - - for (CPDF_FormField* pFormField : FieldArray) { - if (pFormField->GetFullName().Compare(swFieldName) != 0) - continue; - - switch (pFormField->GetFieldType()) { - case FIELDTYPE_TEXTFIELD: - case FIELDTYPE_COMBOBOX: - if (pFormField->GetValue() != strArray[0]) { - pFormField->SetValue(strArray[0], true); - UpdateFormField(pFormFillEnv, pFormField, true, false, true); - } - break; - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: { - if (pFormField->GetValue() != strArray[0]) { - pFormField->SetValue(strArray[0], true); - UpdateFormField(pFormFillEnv, pFormField, true, false, true); - } - } break; - case FIELDTYPE_LISTBOX: { - bool bModified = false; - for (const auto& str : strArray) { - if (!pFormField->IsItemSelected(pFormField->FindOption(str))) { - bModified = true; - break; - } - } - if (bModified) { - pFormField->ClearSelection(true); - for (const auto& str : strArray) { - int index = pFormField->FindOption(str); - if (!pFormField->IsItemSelected(index)) - pFormField->SetItemSelection(index, true, true); - } - UpdateFormField(pFormFillEnv, pFormField, true, false, true); - } - } break; - default: - break; - } - } -} - -bool Field::valueAsString(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() == FIELDTYPE_PUSHBUTTON) - return false; - - if (pFormField->GetFieldType() == FIELDTYPE_CHECKBOX) { - if (!pFormField->CountControls()) - return false; - - if (pFormField->GetControl(0)->IsChecked()) - vp << L"Yes"; - else - vp << L"Off"; - } else if (pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON && - !(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON)) { - for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { - if (pFormField->GetControl(i)->IsChecked()) { - vp << pFormField->GetControl(i)->GetExportValue().c_str(); - break; - } else { - vp << L"Off"; - } - } - } else if (pFormField->GetFieldType() == FIELDTYPE_LISTBOX && - (pFormField->CountSelectedItems() > 1)) { - vp << L""; - } else { - vp << pFormField->GetValue().c_str(); - } - - return true; -} - -bool Field::browseForFileToSubmit(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if ((pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT) && - (pFormField->GetFieldType() == FIELDTYPE_TEXTFIELD)) { - CFX_WideString wsFileName = m_pFormFillEnv->JS_fieldBrowse(); - if (!wsFileName.IsEmpty()) { - pFormField->SetValue(wsFileName); - UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true); - } - return true; - } - return false; -} - -bool Field::buttonGetCaption(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int nface = 0; - int iSize = params.size(); - if (iSize >= 1) - nface = params[0].ToInt(pRuntime); - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - if (nface == 0) - vRet = CJS_Value(pRuntime, pFormControl->GetNormalCaption().c_str()); - else if (nface == 1) - vRet = CJS_Value(pRuntime, pFormControl->GetDownCaption().c_str()); - else if (nface == 2) - vRet = CJS_Value(pRuntime, pFormControl->GetRolloverCaption().c_str()); - else - return false; - - return true; -} - -bool Field::buttonGetIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() >= 1) { - int nFace = params[0].ToInt(pRuntime); - if (nFace < 0 || nFace > 2) - return false; - } - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON) - return false; - - CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); - if (!pFormControl) - return false; - - v8::Local pObj = - pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID); - if (pObj.IsEmpty()) - return false; - - CJS_Icon* pJS_Icon = static_cast(pRuntime->GetObjectPrivate(pObj)); - vRet = CJS_Value(pRuntime, pJS_Icon); - return true; -} - -bool Field::buttonImportIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Field::buttonSetCaption(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::buttonSetIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::checkThisBox(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int iSize = params.size(); - if (iSize < 1) - return false; - - if (!m_bCanSet) - return false; - - int nWidget = params[0].ToInt(pRuntime); - bool bCheckit = true; - if (iSize >= 2) - bCheckit = params[1].ToBool(pRuntime); - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (pFormField->GetFieldType() != FIELDTYPE_CHECKBOX && - pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON) - return false; - if (nWidget < 0 || nWidget >= pFormField->CountControls()) - return false; - // TODO(weili): Check whether anything special needed for radio button, - // otherwise merge these branches. - if (pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON) - pFormField->CheckControl(nWidget, bCheckit, true); - else - pFormField->CheckControl(nWidget, bCheckit, true); - - UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true); - return true; -} - -bool Field::clearItems(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Field::defaultIsChecked(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (!m_bCanSet) - return false; - - int iSize = params.size(); - if (iSize < 1) - return false; - - int nWidget = params[0].ToInt(pRuntime); - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (nWidget < 0 || nWidget >= pFormField->CountControls()) - return false; - - vRet = CJS_Value(pRuntime, - pFormField->GetFieldType() == FIELDTYPE_CHECKBOX || - pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON); - - return true; -} - -bool Field::deleteItemAt(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Field::getArray(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - std::vector> swSort; - for (CPDF_FormField* pFormField : FieldArray) { - swSort.push_back(std::unique_ptr( - new CFX_WideString(pFormField->GetFullName()))); - } - - std::sort( - swSort.begin(), swSort.end(), - [](const std::unique_ptr& p1, - const std::unique_ptr& p2) { return *p1 < *p2; }); - - CJS_Array FormFieldArray; - - int j = 0; - for (const auto& pStr : swSort) { - v8::Local pObj = - pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - if (pObj.IsEmpty()) - return false; - - CJS_Field* pJSField = - static_cast(pRuntime->GetObjectPrivate(pObj)); - Field* pField = static_cast(pJSField->GetEmbedObject()); - pField->AttachField(m_pJSDoc, *pStr); - FormFieldArray.SetElement(pRuntime, j++, CJS_Value(pRuntime, pJSField)); - } - - vRet = CJS_Value(pRuntime, FormFieldArray); - return true; -} - -bool Field::getItemAt(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int iSize = params.size(); - int nIdx = -1; - if (iSize >= 1) - nIdx = params[0].ToInt(pRuntime); - - bool bExport = true; - if (iSize >= 2) - bExport = params[1].ToBool(pRuntime); - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if ((pFormField->GetFieldType() == FIELDTYPE_LISTBOX) || - (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX)) { - if (nIdx == -1 || nIdx > pFormField->CountOptions()) - nIdx = pFormField->CountOptions() - 1; - if (bExport) { - CFX_WideString strval = pFormField->GetOptionValue(nIdx); - if (strval.IsEmpty()) - vRet = CJS_Value(pRuntime, pFormField->GetOptionLabel(nIdx).c_str()); - else - vRet = CJS_Value(pRuntime, strval.c_str()); - } else { - vRet = CJS_Value(pRuntime, pFormField->GetOptionLabel(nIdx).c_str()); - } - } else { - return false; - } - - return true; -} - -bool Field::getLock(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::insertItemAt(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Field::isBoxChecked(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int nIndex = -1; - if (params.size() >= 1) - nIndex = params[0].ToInt(pRuntime); - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (nIndex < 0 || nIndex >= pFormField->CountControls()) { - return false; - } - - vRet = CJS_Value(pRuntime, - ((pFormField->GetFieldType() == FIELDTYPE_CHECKBOX || - pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON) && - pFormField->GetControl(nIndex)->IsChecked() != 0)); - return true; -} - -bool Field::isDefaultChecked(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int nIndex = -1; - if (params.size() >= 1) - nIndex = params[0].ToInt(pRuntime); - - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - if (nIndex < 0 || nIndex >= pFormField->CountControls()) - return false; - - vRet = CJS_Value(pRuntime, - ((pFormField->GetFieldType() == FIELDTYPE_CHECKBOX || - pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON) && - pFormField->GetControl(nIndex)->IsDefaultChecked() != 0)); - return true; -} - -bool Field::setAction(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Field::setFocus(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - std::vector FieldArray = GetFormFields(m_FieldName); - if (FieldArray.empty()) - return false; - - CPDF_FormField* pFormField = FieldArray[0]; - int32_t nCount = pFormField->CountControls(); - if (nCount < 1) - return false; - - CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); - CPDFSDK_Widget* pWidget = nullptr; - if (nCount == 1) { - pWidget = pInterForm->GetWidget(pFormField->GetControl(0)); - } else { - UnderlyingPageType* pPage = - UnderlyingFromFPDFPage(m_pFormFillEnv->GetCurrentPage( - m_pFormFillEnv->GetUnderlyingDocument())); - if (!pPage) - return false; - if (CPDFSDK_PageView* pCurPageView = - m_pFormFillEnv->GetPageView(pPage, true)) { - for (int32_t i = 0; i < nCount; i++) { - if (CPDFSDK_Widget* pTempWidget = - pInterForm->GetWidget(pFormField->GetControl(i))) { - if (pTempWidget->GetPDFPage() == pCurPageView->GetPDFPage()) { - pWidget = pTempWidget; - break; - } - } - } - } - } - - if (pWidget) { - CPDFSDK_Annot::ObservedPtr pObserved(pWidget); - m_pFormFillEnv->SetFocusAnnot(&pObserved); - } - - return true; -} - -bool Field::setItems(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool Field::setLock(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::signatureGetModifications(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::signatureGetSeedValue(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::signatureInfo(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::signatureSetSeedValue(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::signatureSign(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::signatureValidate(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool Field::source(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - vp << (CJS_Object*)nullptr; - } - - return true; -} - -void Field::AddDelay_Int(FIELD_PROP prop, int32_t n) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->num = n; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_Bool(FIELD_PROP prop, bool b) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->b = b; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_String(FIELD_PROP prop, const CFX_ByteString& string) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->string = string; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_WideString(FIELD_PROP prop, const CFX_WideString& string) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->widestring = string; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->rect = rect; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_Color(FIELD_PROP prop, const CPWL_Color& color) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->color = color; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_WordArray(FIELD_PROP prop, - const std::vector& array) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->wordarray = array; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::AddDelay_WideStringArray(FIELD_PROP prop, - const std::vector& array) { - CJS_DelayData* pNewData = - new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); - pNewData->widestringarray = array; - m_pJSDoc->AddDelayData(pNewData); -} - -void Field::DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CJS_DelayData* pData) { - ASSERT(pFormFillEnv); - switch (pData->eProp) { - case FP_ALIGNMENT: - Field::SetAlignment(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->string); - break; - case FP_BORDERSTYLE: - Field::SetBorderStyle(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->string); - break; - case FP_BUTTONALIGNX: - Field::SetButtonAlignX(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->num); - break; - case FP_BUTTONALIGNY: - Field::SetButtonAlignY(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->num); - break; - case FP_BUTTONFITBOUNDS: - Field::SetButtonFitBounds(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->b); - break; - case FP_BUTTONPOSITION: - Field::SetButtonPosition(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->num); - break; - case FP_BUTTONSCALEHOW: - Field::SetButtonScaleHow(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->num); - break; - case FP_BUTTONSCALEWHEN: - Field::SetButtonScaleWhen(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->num); - break; - case FP_CALCORDERINDEX: - Field::SetCalcOrderIndex(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->num); - break; - case FP_CHARLIMIT: - Field::SetCharLimit(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->num); - break; - case FP_COMB: - Field::SetComb(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->b); - break; - case FP_COMMITONSELCHANGE: - Field::SetCommitOnSelChange(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->b); - break; - case FP_CURRENTVALUEINDICES: - Field::SetCurrentValueIndices(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->wordarray); - break; - case FP_DEFAULTVALUE: - Field::SetDefaultValue(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->widestring); - break; - case FP_DONOTSCROLL: - Field::SetDoNotScroll(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->b); - break; - case FP_DISPLAY: - Field::SetDisplay(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->num); - break; - case FP_FILLCOLOR: - Field::SetFillColor(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->color); - break; - case FP_HIDDEN: - Field::SetHidden(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->b); - break; - case FP_HIGHLIGHT: - Field::SetHighlight(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->string); - break; - case FP_LINEWIDTH: - Field::SetLineWidth(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->num); - break; - case FP_MULTILINE: - Field::SetMultiline(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->b); - break; - case FP_MULTIPLESELECTION: - Field::SetMultipleSelection(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->b); - break; - case FP_PASSWORD: - Field::SetPassword(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->b); - break; - case FP_RECT: - Field::SetRect(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->rect); - break; - case FP_RICHTEXT: - // Not supported. - break; - case FP_RICHVALUE: - break; - case FP_ROTATION: - Field::SetRotation(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->num); - break; - case FP_STROKECOLOR: - Field::SetStrokeColor(pFormFillEnv, pData->sFieldName, - pData->nControlIndex, pData->color); - break; - case FP_STYLE: - Field::SetStyle(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->string); - break; - case FP_TEXTCOLOR: - Field::SetTextColor(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->color); - break; - case FP_TEXTFONT: - Field::SetTextFont(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->string); - break; - case FP_TEXTSIZE: - Field::SetTextSize(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->num); - break; - case FP_USERNAME: - Field::SetUserName(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->widestring); - break; - case FP_VALUE: - Field::SetValue(pFormFillEnv, pData->sFieldName, pData->nControlIndex, - pData->widestringarray); - break; - } -} - -void Field::AddField(CPDFSDK_FormFillEnvironment* pFormFillEnv, - int nPageIndex, - int nFieldType, - const CFX_WideString& sName, - const CFX_FloatRect& rcCoords) { - // Not supported. -} diff --git a/fpdfsdk/javascript/Field.h b/fpdfsdk/javascript/Field.h deleted file mode 100644 index 462c1271a16c7eb4bb0b0b3f34bc85002832946c..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Field.h +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_FIELD_H_ -#define FPDFSDK_JAVASCRIPT_FIELD_H_ - -#include -#include - -#include "core/fxcrt/cfx_observable.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" // For CPWL_Color. - -class CPDFSDK_Widget; -class Document; - -enum FIELD_PROP { - FP_ALIGNMENT, - FP_BORDERSTYLE, - FP_BUTTONALIGNX, - FP_BUTTONALIGNY, - FP_BUTTONFITBOUNDS, - FP_BUTTONPOSITION, - FP_BUTTONSCALEHOW, - FP_BUTTONSCALEWHEN, - FP_CALCORDERINDEX, - FP_CHARLIMIT, - FP_COMB, - FP_COMMITONSELCHANGE, - FP_CURRENTVALUEINDICES, - FP_DEFAULTVALUE, - FP_DONOTSCROLL, - FP_DISPLAY, - FP_FILLCOLOR, - FP_HIDDEN, - FP_HIGHLIGHT, - FP_LINEWIDTH, - FP_MULTILINE, - FP_MULTIPLESELECTION, - FP_PASSWORD, - FP_RECT, - FP_RICHTEXT, - FP_RICHVALUE, - FP_ROTATION, - FP_STROKECOLOR, - FP_STYLE, - FP_TEXTCOLOR, - FP_TEXTFONT, - FP_TEXTSIZE, - FP_USERNAME, - FP_VALUE -}; - -struct CJS_DelayData { - CJS_DelayData(FIELD_PROP prop, int idx, const CFX_WideString& name); - ~CJS_DelayData(); - - FIELD_PROP eProp; - int nControlIndex; - CFX_WideString sFieldName; - int32_t num; - bool b; - CFX_ByteString string; - CFX_WideString widestring; - CFX_FloatRect rect; - CPWL_Color color; - std::vector wordarray; - std::vector widestringarray; -}; - -class Field : public CJS_EmbedObj { - public: - explicit Field(CJS_Object* pJSObject); - ~Field() override; - - bool alignment(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool borderStyle(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool buttonAlignX(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool buttonAlignY(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool buttonFitBounds(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool buttonPosition(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool buttonScaleHow(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool buttonScaleWhen(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool calcOrderIndex(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool charLimit(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool comb(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool commitOnSelChange(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool currentValueIndices(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool defaultStyle(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool defaultValue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool doNotScroll(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool doNotSpellCheck(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool delay(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool display(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool doc(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool editable(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool exportValues(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool fileSelect(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool fillColor(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool hidden(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool highlight(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool lineWidth(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool multiline(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool multipleSelection(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool numItems(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool page(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool password(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool print(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool radiosInUnison(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool readonly(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool rect(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool required(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool richText(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool richValue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool rotation(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool strokeColor(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool style(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool submitName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool textColor(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool textFont(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool textSize(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool type(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool userName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool value(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool valueAsString(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool source(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - - bool browseForFileToSubmit(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool buttonGetCaption(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool buttonGetIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool buttonImportIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool buttonSetCaption(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool buttonSetIcon(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool checkThisBox(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool clearItems(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool defaultIsChecked(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool deleteItemAt(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getArray(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getItemAt(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool getLock(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool insertItemAt(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool isBoxChecked(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool isDefaultChecked(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool setAction(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool setFocus(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool setItems(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool setLock(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool signatureGetModifications(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool signatureGetSeedValue(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool signatureInfo(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool signatureSetSeedValue(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool signatureSign(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool signatureValidate(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - - static void SetAlignment(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string); - static void SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string); - static void SetButtonAlignX(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetButtonAlignY(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetButtonFitBounds(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetButtonPosition(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetButtonScaleHow(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetButtonScaleWhen(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetCalcOrderIndex(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetCharLimit(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetComb(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetCommitOnSelChange(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const std::vector& array); - static void SetDefaultStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex); - static void SetDefaultValue(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_WideString& string); - static void SetDoNotScroll(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetFillColor(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CPWL_Color& color); - static void SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetHighlight(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string); - static void SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetMultiline(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetMultipleSelection(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetPassword(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - bool b); - static void SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_FloatRect& rect); - static void SetRotation(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetStrokeColor(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CPWL_Color& color); - static void SetStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string); - static void SetTextColor(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CPWL_Color& color); - static void SetTextFont(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_ByteString& string); - static void SetTextSize(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - int number); - static void SetUserName(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const CFX_WideString& string); - static void SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& swFieldName, - int nControlIndex, - const std::vector& strArray); - - static void AddField(CPDFSDK_FormFillEnvironment* pFormFillEnv, - int nPageIndex, - int nFieldType, - const CFX_WideString& sName, - const CFX_FloatRect& rcCoords); - - static void UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDF_FormField* pFormField, - bool bChangeMark, - bool bResetAP, - bool bRefresh); - static void UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDF_FormControl* pFormControl, - bool bChangeMark, - bool bResetAP, - bool bRefresh); - - static CPDFSDK_Widget* GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CPDF_FormControl* pFormControl); - static std::vector GetFormFields( - CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& csFieldName); - - static void DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv, - CJS_DelayData* pData); - - bool AttachField(Document* pDocument, const CFX_WideString& csFieldName); - void SetDelay(bool bDelay); - - protected: - void ParseFieldName(const std::wstring& strFieldNameParsed, - std::wstring& strFieldName, - int& iControlNo); - std::vector GetFormFields( - const CFX_WideString& csFieldName) const; - CPDF_FormControl* GetSmartFieldControl(CPDF_FormField* pFormField); - bool ValueIsOccur(CPDF_FormField* pFormField, CFX_WideString csOptLabel); - - void AddDelay_Int(FIELD_PROP prop, int32_t n); - void AddDelay_Bool(FIELD_PROP prop, bool b); - void AddDelay_String(FIELD_PROP prop, const CFX_ByteString& string); - void AddDelay_WideString(FIELD_PROP prop, const CFX_WideString& string); - void AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect); - void AddDelay_Color(FIELD_PROP prop, const CPWL_Color& color); - void AddDelay_WordArray(FIELD_PROP prop, const std::vector& array); - void AddDelay_WideStringArray(FIELD_PROP prop, - const std::vector& array); - - void DoDelay(); - - public: - Document* m_pJSDoc; - CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; - CFX_WideString m_FieldName; - int m_nFormControlIndex; - bool m_bCanSet; - bool m_bDelay; -}; - -class CJS_Field : public CJS_Object { - public: - explicit CJS_Field(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Field() override {} - - void InitInstance(IJS_Runtime* pIRuntime) override; - - DECLARE_JS_CLASS(); - JS_STATIC_PROP(alignment, Field); - JS_STATIC_PROP(borderStyle, Field); - JS_STATIC_PROP(buttonAlignX, Field); - JS_STATIC_PROP(buttonAlignY, Field); - JS_STATIC_PROP(buttonFitBounds, Field); - JS_STATIC_PROP(buttonPosition, Field); - JS_STATIC_PROP(buttonScaleHow, Field); - JS_STATIC_PROP(buttonScaleWhen, Field); - JS_STATIC_PROP(calcOrderIndex, Field); - JS_STATIC_PROP(charLimit, Field); - JS_STATIC_PROP(comb, Field); - JS_STATIC_PROP(commitOnSelChange, Field); - JS_STATIC_PROP(currentValueIndices, Field); - JS_STATIC_PROP(defaultStyle, Field); - JS_STATIC_PROP(defaultValue, Field); - JS_STATIC_PROP(doNotScroll, Field); - JS_STATIC_PROP(doNotSpellCheck, Field); - JS_STATIC_PROP(delay, Field); - JS_STATIC_PROP(display, Field); - JS_STATIC_PROP(doc, Field); - JS_STATIC_PROP(editable, Field); - JS_STATIC_PROP(exportValues, Field); - JS_STATIC_PROP(fileSelect, Field); - JS_STATIC_PROP(fillColor, Field); - JS_STATIC_PROP(hidden, Field); - JS_STATIC_PROP(highlight, Field); - JS_STATIC_PROP(lineWidth, Field); - JS_STATIC_PROP(multiline, Field); - JS_STATIC_PROP(multipleSelection, Field); - JS_STATIC_PROP(name, Field); - JS_STATIC_PROP(numItems, Field); - JS_STATIC_PROP(page, Field); - JS_STATIC_PROP(password, Field); - JS_STATIC_PROP(print, Field); - JS_STATIC_PROP(radiosInUnison, Field); - JS_STATIC_PROP(readonly, Field); - JS_STATIC_PROP(rect, Field); - JS_STATIC_PROP(required, Field); - JS_STATIC_PROP(richText, Field); - JS_STATIC_PROP(richValue, Field); - JS_STATIC_PROP(rotation, Field); - JS_STATIC_PROP(strokeColor, Field); - JS_STATIC_PROP(style, Field); - JS_STATIC_PROP(submitName, Field); - JS_STATIC_PROP(textColor, Field); - JS_STATIC_PROP(textFont, Field); - JS_STATIC_PROP(textSize, Field); - JS_STATIC_PROP(type, Field); - JS_STATIC_PROP(userName, Field); - JS_STATIC_PROP(value, Field); - JS_STATIC_PROP(valueAsString, Field); - JS_STATIC_PROP(source, Field); - - JS_STATIC_METHOD(browseForFileToSubmit, Field); - JS_STATIC_METHOD(buttonGetCaption, Field); - JS_STATIC_METHOD(buttonGetIcon, Field); - JS_STATIC_METHOD(buttonImportIcon, Field); - JS_STATIC_METHOD(buttonSetCaption, Field); - JS_STATIC_METHOD(buttonSetIcon, Field); - JS_STATIC_METHOD(checkThisBox, Field); - JS_STATIC_METHOD(clearItems, Field); - JS_STATIC_METHOD(defaultIsChecked, Field); - JS_STATIC_METHOD(deleteItemAt, Field); - JS_STATIC_METHOD(getArray, Field); - JS_STATIC_METHOD(getItemAt, Field); - JS_STATIC_METHOD(getLock, Field); - JS_STATIC_METHOD(insertItemAt, Field); - JS_STATIC_METHOD(isBoxChecked, Field); - JS_STATIC_METHOD(isDefaultChecked, Field); - JS_STATIC_METHOD(setAction, Field); - JS_STATIC_METHOD(setFocus, Field); - JS_STATIC_METHOD(setItems, Field); - JS_STATIC_METHOD(setLock, Field); - JS_STATIC_METHOD(signatureGetModifications, Field); - JS_STATIC_METHOD(signatureGetSeedValue, Field); - JS_STATIC_METHOD(signatureInfo, Field); - JS_STATIC_METHOD(signatureSetSeedValue, Field); - JS_STATIC_METHOD(signatureSign, Field); - JS_STATIC_METHOD(signatureValidate, Field); -}; - -#endif // FPDFSDK_JAVASCRIPT_FIELD_H_ diff --git a/fpdfsdk/javascript/Icon.cpp b/fpdfsdk/javascript/Icon.cpp deleted file mode 100644 index fa2f92f3c913b8121b5cfb566cafe23eb507e429..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Icon.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/Icon.h" - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" - -JSConstSpec CJS_Icon::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Icon::PropertySpecs[] = { - {"name", get_name_static, set_name_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_Icon::MethodSpecs[] = {{0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Icon, Icon) - -Icon::Icon(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject), m_swIconName(L"") {} - -Icon::~Icon() {} - -bool Icon::name(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - vp << m_swIconName; - return true; -} diff --git a/fpdfsdk/javascript/Icon.h b/fpdfsdk/javascript/Icon.h deleted file mode 100644 index 5580678fd59c596ba70ee629bd89b375787fb99a..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/Icon.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_ICON_H_ -#define FPDFSDK_JAVASCRIPT_ICON_H_ - -#include "fpdfsdk/javascript/JS_Define.h" - -class CPDF_Stream; - -class Icon : public CJS_EmbedObj { - public: - explicit Icon(CJS_Object* pJSObject); - ~Icon() override; - - bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - CFX_WideString GetIconName() const { return m_swIconName; } - void SetIconName(CFX_WideString name) { m_swIconName = name; } - - private: - CFX_WideString m_swIconName; -}; - -class CJS_Icon : public CJS_Object { - public: - explicit CJS_Icon(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Icon() override {} - - DECLARE_JS_CLASS(); - JS_STATIC_PROP(name, Icon); -}; - -#endif // FPDFSDK_JAVASCRIPT_ICON_H_ diff --git a/fpdfsdk/javascript/JS_Define.h b/fpdfsdk/javascript/JS_Define.h deleted file mode 100644 index 375ca3ac35727be4a5f2ee8d90ca587984da44a1..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_Define.h +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_JS_DEFINE_H_ -#define FPDFSDK_JAVASCRIPT_JS_DEFINE_H_ - -#include - -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/resource.h" -#include "fxjs/fxjs_v8.h" - -struct JSConstSpec { - enum Type { Number = 0, String = 1 }; - - const char* pName; - Type eType; - double number; - const char* pStr; -}; - -struct JSPropertySpec { - const char* pName; - v8::AccessorGetterCallback pPropGet; - v8::AccessorSetterCallback pPropPut; -}; - -struct JSMethodSpec { - const char* pName; - v8::FunctionCallback pMethodCall; -}; - -template -void JSPropGetter(const char* prop_name_string, - const char* class_name_string, - v8::Local property, - const v8::PropertyCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - C* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - CFX_WideString sError; - CJS_PropValue value(pRuntime); - value.StartGetting(); - if (!(pObj->*M)(pRuntime, value, sError)) { - pRuntime->Error( - JSFormatErrorString(class_name_string, prop_name_string, sError)); - return; - } - info.GetReturnValue().Set(value.GetJSValue()->ToV8Value(pRuntime)); -} - -template -void JSPropSetter(const char* prop_name_string, - const char* class_name_string, - v8::Local property, - v8::Local value, - const v8::PropertyCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - C* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - CFX_WideString sError; - CJS_PropValue propValue(pRuntime, CJS_Value(pRuntime, value)); - propValue.StartSetting(); - if (!(pObj->*M)(pRuntime, propValue, sError)) { - pRuntime->Error( - JSFormatErrorString(class_name_string, prop_name_string, sError)); - } -} - -#define JS_STATIC_PROP(prop_name, class_name) \ - static void get_##prop_name##_static( \ - v8::Local property, \ - const v8::PropertyCallbackInfo& info) { \ - JSPropGetter(#prop_name, #class_name, \ - property, info); \ - } \ - static void set_##prop_name##_static( \ - v8::Local property, v8::Local value, \ - const v8::PropertyCallbackInfo& info) { \ - JSPropSetter(#prop_name, #class_name, \ - property, value, info); \ - } - -template &, - CJS_Value&, - CFX_WideString&)> -void JSMethod(const char* method_name_string, - const char* class_name_string, - const v8::FunctionCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - std::vector parameters; - for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) { - parameters.push_back(CJS_Value(pRuntime, info[i])); - } - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - C* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - CFX_WideString sError; - CJS_Value valueRes(pRuntime); - if (!(pObj->*M)(pRuntime, parameters, valueRes, sError)) { - pRuntime->Error( - JSFormatErrorString(class_name_string, method_name_string, sError)); - return; - } - info.GetReturnValue().Set(valueRes.ToV8Value(pRuntime)); -} - -#define JS_STATIC_METHOD(method_name, class_name) \ - static void method_name##_static( \ - const v8::FunctionCallbackInfo& info) { \ - JSMethod(#method_name, #class_name, \ - info); \ - } - -#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \ - static void method_name##_static( \ - const v8::FunctionCallbackInfo& info) { \ - JSMethod( \ - #method_name, #class_name, info); \ - } - -// All JS classes have a name, an object defintion ID, and the ability to -// register themselves with FXJS_V8. We never make a BASE class on its own -// because it can't really do anything. -#define DECLARE_JS_CLASS_BASE_PART() \ - static const char* g_pClassName; \ - static int g_nObjDefnID; \ - static void DefineJSObjects(CFXJS_Engine* pEngine, FXJSOBJTYPE eObjType); - -#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \ - const char* js_class_name::g_pClassName = #class_name; \ - int js_class_name::g_nObjDefnID = -1; - -// CONST classes provide constants, but not constructors, methods, or props. -#define DECLARE_JS_CLASS_CONST() \ - DECLARE_JS_CLASS_BASE_PART() \ - DECLARE_JS_CLASS_CONST_PART() - -#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \ - void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine, \ - FXJSOBJTYPE eObjType) { \ - g_nObjDefnID = pEngine->DefineObj(js_class_name::g_pClassName, eObjType, \ - nullptr, nullptr); \ - DefineConsts(pEngine); \ - } - -#define DECLARE_JS_CLASS_CONST_PART() \ - static JSConstSpec ConstSpecs[]; \ - static void DefineConsts(CFXJS_Engine* pEngine); - -#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \ - void js_class_name::DefineConsts(CFXJS_Engine* pEngine) { \ - for (size_t i = 0; i < FX_ArraySize(ConstSpecs) - 1; ++i) { \ - pEngine->DefineObjConst(g_nObjDefnID, ConstSpecs[i].pName, \ - ConstSpecs[i].eType == JSConstSpec::Number \ - ? pEngine->NewNumber(ConstSpecs[i].number) \ - : pEngine->NewString(ConstSpecs[i].pStr)); \ - } \ - } - -// Convenience macros for declaring classes without an alternate. -#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH() -#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name) - -// Rich JS classes provide constants, methods, properties, and the ability -// to construct native object state. -#define DECLARE_JS_CLASS_RICH() \ - DECLARE_JS_CLASS_BASE_PART() \ - DECLARE_JS_CLASS_CONST_PART() \ - DECLARE_JS_CLASS_RICH_PART() - -#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \ - IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \ - void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine, \ - FXJSOBJTYPE eObjType) { \ - g_nObjDefnID = pEngine->DefineObj(js_class_name::g_pClassName, eObjType, \ - JSConstructor, JSDestructor); \ - DefineConsts(pEngine); \ - DefineProps(pEngine); \ - DefineMethods(pEngine); \ - } - -#define DECLARE_JS_CLASS_RICH_PART() \ - static void JSConstructor(CFXJS_Engine* pEngine, v8::Local obj); \ - static void JSDestructor(CFXJS_Engine* pEngine, v8::Local obj); \ - static void DefineProps(CFXJS_Engine* pEngine); \ - static void DefineMethods(CFXJS_Engine* pEngine); \ - static JSPropertySpec PropertySpecs[]; \ - static JSMethodSpec MethodSpecs[]; - -#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \ - class_name) \ - void js_class_name::JSConstructor(CFXJS_Engine* pEngine, \ - v8::Local obj) { \ - CJS_Object* pObj = new js_class_name(obj); \ - pObj->SetEmbedObject(new class_alternate(pObj)); \ - pEngine->SetObjectPrivate(obj, (void*)pObj); \ - pObj->InitInstance(static_cast(pEngine)); \ - } \ - void js_class_name::JSDestructor(CFXJS_Engine* pEngine, \ - v8::Local obj) { \ - delete static_cast(pEngine->GetObjectPrivate(obj)); \ - } \ - void js_class_name::DefineProps(CFXJS_Engine* pEngine) { \ - for (size_t i = 0; i < FX_ArraySize(PropertySpecs) - 1; ++i) { \ - pEngine->DefineObjProperty(g_nObjDefnID, PropertySpecs[i].pName, \ - PropertySpecs[i].pPropGet, \ - PropertySpecs[i].pPropPut); \ - } \ - } \ - void js_class_name::DefineMethods(CFXJS_Engine* pEngine) { \ - for (size_t i = 0; i < FX_ArraySize(MethodSpecs) - 1; ++i) { \ - pEngine->DefineObjMethod(g_nObjDefnID, MethodSpecs[i].pName, \ - MethodSpecs[i].pMethodCall); \ - } \ - } - -// Special JS classes implement methods, props, and queries, but not consts. -#define DECLARE_SPECIAL_JS_CLASS() \ - DECLARE_JS_CLASS_BASE_PART() \ - DECLARE_JS_CLASS_CONST_PART() \ - DECLARE_JS_CLASS_RICH_PART() \ - DECLARE_SPECIAL_JS_CLASS_PART() - -#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \ - IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \ - IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \ - IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, class_name) \ - void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine, \ - FXJSOBJTYPE eObjType) { \ - g_nObjDefnID = pEngine->DefineObj(js_class_name::g_pClassName, eObjType, \ - JSConstructor, JSDestructor); \ - DefineConsts(pEngine); \ - DefineProps(pEngine); \ - DefineMethods(pEngine); \ - DefineAllProperties(pEngine); \ - } - -#define DECLARE_SPECIAL_JS_CLASS_PART() \ - static void queryprop_static( \ - v8::Local property, \ - const v8::PropertyCallbackInfo& info); \ - static void getprop_static(v8::Local property, \ - const v8::PropertyCallbackInfo& info); \ - static void putprop_static(v8::Local property, \ - v8::Local value, \ - const v8::PropertyCallbackInfo& info); \ - static void delprop_static( \ - v8::Local property, \ - const v8::PropertyCallbackInfo& info); \ - static void DefineAllProperties(CFXJS_Engine* pEngine); - -#define IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, \ - class_name) \ - void js_class_name::queryprop_static( \ - v8::Local property, \ - const v8::PropertyCallbackInfo& info) { \ - JSSpecialPropQuery(#class_name, property, info); \ - } \ - void js_class_name::getprop_static( \ - v8::Local property, \ - const v8::PropertyCallbackInfo& info) { \ - JSSpecialPropGet(#class_name, property, info); \ - } \ - void js_class_name::putprop_static( \ - v8::Local property, v8::Local value, \ - const v8::PropertyCallbackInfo& info) { \ - JSSpecialPropPut(#class_name, property, value, info); \ - } \ - void js_class_name::delprop_static( \ - v8::Local property, \ - const v8::PropertyCallbackInfo& info) { \ - JSSpecialPropDel(#class_name, property, info); \ - } \ - void js_class_name::DefineAllProperties(CFXJS_Engine* pEngine) { \ - pEngine->DefineObjAllProperties( \ - g_nObjDefnID, js_class_name::queryprop_static, \ - js_class_name::getprop_static, js_class_name::putprop_static, \ - js_class_name::delprop_static); \ - } - -template -void JSSpecialPropQuery(const char*, - v8::Local property, - const v8::PropertyCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - - Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - v8::String::Utf8Value utf8_value(property); - CFX_WideString propname = CFX_WideString::FromUTF8( - CFX_ByteStringC(*utf8_value, utf8_value.length())); - bool bRet = pObj->QueryProperty(propname.c_str()); - info.GetReturnValue().Set(bRet ? 4 : 0); -} - -template -void JSSpecialPropGet(const char* class_name, - v8::Local property, - const v8::PropertyCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - - Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - v8::String::Utf8Value utf8_value(property); - CFX_WideString propname = CFX_WideString::FromUTF8( - CFX_ByteStringC(*utf8_value, utf8_value.length())); - CFX_WideString sError; - CJS_PropValue value(pRuntime); - value.StartGetting(); - if (!pObj->DoProperty(pRuntime, propname.c_str(), value, sError)) { - pRuntime->Error(JSFormatErrorString(class_name, "GetProperty", sError)); - return; - } - info.GetReturnValue().Set(value.GetJSValue()->ToV8Value(pRuntime)); -} - -template -void JSSpecialPropPut(const char* class_name, - v8::Local property, - v8::Local value, - const v8::PropertyCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - - Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - v8::String::Utf8Value utf8_value(property); - CFX_WideString propname = CFX_WideString::FromUTF8( - CFX_ByteStringC(*utf8_value, utf8_value.length())); - CFX_WideString sError; - CJS_PropValue PropValue(pRuntime, CJS_Value(pRuntime, value)); - PropValue.StartSetting(); - if (!pObj->DoProperty(pRuntime, propname.c_str(), PropValue, sError)) { - pRuntime->Error(JSFormatErrorString(class_name, "PutProperty", sError)); - } -} - -template -void JSSpecialPropDel(const char* class_name, - v8::Local property, - const v8::PropertyCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - - CJS_Object* pJSObj = - static_cast(pRuntime->GetObjectPrivate(info.Holder())); - if (!pJSObj) - return; - - Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); - v8::String::Utf8Value utf8_value(property); - CFX_WideString propname = CFX_WideString::FromUTF8( - CFX_ByteStringC(*utf8_value, utf8_value.length())); - CFX_WideString sError; - if (!pObj->DelProperty(pRuntime, propname.c_str(), sError)) { - CFX_ByteString cbName; - cbName.Format("%s.%s", class_name, "DelProperty"); - // Probably a missing call to JSFX_Error(). - } -} - -template &, - CJS_Value&, - CFX_WideString&)> -void JSGlobalFunc(const char* func_name_string, - const v8::FunctionCallbackInfo& info) { - CJS_Runtime* pRuntime = - CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - if (!pRuntime) - return; - std::vector parameters; - for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) { - parameters.push_back(CJS_Value(pRuntime, info[i])); - } - CJS_Value valueRes(pRuntime); - CFX_WideString sError; - if (!(*F)(pRuntime, parameters, valueRes, sError)) { - pRuntime->Error(JSFormatErrorString(func_name_string, nullptr, sError)); - return; - } - info.GetReturnValue().Set(valueRes.ToV8Value(pRuntime)); -} - -#define JS_STATIC_GLOBAL_FUN(fun_name) \ - static void fun_name##_static( \ - const v8::FunctionCallbackInfo& info) { \ - JSGlobalFunc(#fun_name, info); \ - } - -#define JS_STATIC_DECLARE_GLOBAL_FUN() \ - static JSMethodSpec GlobalFunctionSpecs[]; \ - static void DefineJSObjects(CFXJS_Engine* pEngine) - -#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \ - void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine) { \ - for (size_t i = 0; i < FX_ArraySize(GlobalFunctionSpecs) - 1; ++i) { \ - pEngine->DefineGlobalMethod( \ - js_class_name::GlobalFunctionSpecs[i].pName, \ - js_class_name::GlobalFunctionSpecs[i].pMethodCall); \ - } \ - } - -#endif // FPDFSDK_JAVASCRIPT_JS_DEFINE_H_ diff --git a/fpdfsdk/javascript/JS_EventHandler.cpp b/fpdfsdk/javascript/JS_EventHandler.cpp deleted file mode 100644 index bd1c8e29d0d7d6e46d833bab2af00330e5bafe0f..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_EventHandler.cpp +++ /dev/null @@ -1,653 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/JS_EventHandler.h" - -#include "fpdfsdk/javascript/Document.h" -#include "fpdfsdk/javascript/Field.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" - -CJS_EventHandler::CJS_EventHandler(CJS_EventContext* pContext) - : m_pJSEventContext(pContext), - m_eEventType(JET_UNKNOWN), - m_bValid(false), - m_pWideStrChange(nullptr), - m_nCommitKey(-1), - m_bKeyDown(false), - m_bModifier(false), - m_bShift(false), - m_pISelEnd(nullptr), - m_nSelEndDu(0), - m_pISelStart(nullptr), - m_nSelStartDu(0), - m_bWillCommit(false), - m_pValue(nullptr), - m_bFieldFull(false), - m_pbRc(nullptr), - m_bRcDu(false), - m_pTargetBookMark(nullptr), - m_pTargetFormFillEnv(nullptr), - m_pTargetAnnot(nullptr) {} - -CJS_EventHandler::~CJS_EventHandler() {} - -void CJS_EventHandler::OnApp_Init() { - Initial(JET_APP_INIT); -} - -void CJS_EventHandler::OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) { - Initial(JET_DOC_OPEN); - m_pTargetFormFillEnv.Reset(pFormFillEnv); - m_strTargetName = strTargetName; -} - -void CJS_EventHandler::OnDoc_WillPrint( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_DOC_WILLPRINT); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnDoc_DidPrint( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_DOC_DIDPRINT); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnDoc_WillSave( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_DOC_WILLSAVE); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnDoc_DidSave( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_DOC_DIDSAVE); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnDoc_WillClose( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_DOC_WILLCLOSE); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_PAGE_OPEN); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_PAGE_CLOSE); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnPage_InView( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_PAGE_INVIEW); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnPage_OutView( - CPDFSDK_FormFillEnvironment* pFormFillEnv) { - Initial(JET_PAGE_OUTVIEW); - m_pTargetFormFillEnv.Reset(pFormFillEnv); -} - -void CJS_EventHandler::OnField_MouseEnter(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) { - Initial(JET_FIELD_MOUSEENTER); - - m_bModifier = bModifier; - m_bShift = bShift; - - m_strTargetName = pTarget->GetFullName(); -} - -void CJS_EventHandler::OnField_MouseExit(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) { - Initial(JET_FIELD_MOUSEEXIT); - - m_bModifier = bModifier; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); -} - -void CJS_EventHandler::OnField_MouseDown(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) { - Initial(JET_FIELD_MOUSEDOWN); - m_eEventType = JET_FIELD_MOUSEDOWN; - - m_bModifier = bModifier; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); -} - -void CJS_EventHandler::OnField_MouseUp(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) { - Initial(JET_FIELD_MOUSEUP); - - m_bModifier = bModifier; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); -} - -void CJS_EventHandler::OnField_Focus(bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - const CFX_WideString& Value) { - Initial(JET_FIELD_FOCUS); - - m_bModifier = bModifier; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); - m_pValue = (CFX_WideString*)&Value; -} - -void CJS_EventHandler::OnField_Blur(bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - const CFX_WideString& Value) { - Initial(JET_FIELD_BLUR); - - m_bModifier = bModifier; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); - m_pValue = (CFX_WideString*)&Value; -} - -void CJS_EventHandler::OnField_Keystroke(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - bool KeyDown, - bool bModifier, - int& nSelEnd, - int& nSelStart, - bool bShift, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool bWillCommit, - bool bFieldFull, - bool& bRc) { - Initial(JET_FIELD_KEYSTROKE); - - m_nCommitKey = 0; - m_pWideStrChange = &strChange; - m_WideStrChangeEx = strChangeEx; - m_bKeyDown = KeyDown; - m_bModifier = bModifier; - m_pISelEnd = &nSelEnd; - m_pISelStart = &nSelStart; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); - m_pValue = &Value; - m_bWillCommit = bWillCommit; - m_pbRc = &bRc; - m_bFieldFull = bFieldFull; -} - -void CJS_EventHandler::OnField_Validate(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - bool bKeyDown, - bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool& bRc) { - Initial(JET_FIELD_VALIDATE); - - m_pWideStrChange = &strChange; - m_WideStrChangeEx = strChangeEx; - m_bKeyDown = bKeyDown; - m_bModifier = bModifier; - m_bShift = bShift; - m_strTargetName = pTarget->GetFullName(); - m_pValue = &Value; - m_pbRc = &bRc; -} - -void CJS_EventHandler::OnField_Calculate(CPDF_FormField* pSource, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool& bRc) { - Initial(JET_FIELD_CALCULATE); - - if (pSource) - m_strSourceName = pSource->GetFullName(); - m_strTargetName = pTarget->GetFullName(); - m_pValue = &Value; - m_pbRc = &bRc; -} - -void CJS_EventHandler::OnField_Format(CPDF_FormField* pTarget, - CFX_WideString& Value, - bool bWillCommit) { - Initial(JET_FIELD_FORMAT); - - m_nCommitKey = 0; - m_strTargetName = pTarget->GetFullName(); - m_pValue = &Value; - m_bWillCommit = bWillCommit; -} - -void CJS_EventHandler::OnScreen_Focus(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_FOCUS); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_Blur(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_BLUR); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_Open(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_OPEN); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_Close(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_CLOSE); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_MouseDown(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_MOUSEDOWN); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_MouseUp(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_MOUSEUP); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_MouseEnter(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_MOUSEENTER); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_MouseExit(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_MOUSEEXIT); - - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_InView(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_INVIEW); - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnScreen_OutView(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) { - Initial(JET_SCREEN_OUTVIEW); - m_bModifier = bModifier; - m_bShift = bShift; - m_pTargetAnnot.Reset(pScreen); -} - -void CJS_EventHandler::OnLink_MouseUp( - CPDFSDK_FormFillEnvironment* pTargetFormFillEnv) { - Initial(JET_LINK_MOUSEUP); - m_pTargetFormFillEnv.Reset(pTargetFormFillEnv); -} - -void CJS_EventHandler::OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) { - Initial(JET_BOOKMARK_MOUSEUP); - m_pTargetBookMark = pBookMark; -} - -void CJS_EventHandler::OnMenu_Exec( - CPDFSDK_FormFillEnvironment* pTargetFormFillEnv, - const CFX_WideString& strTargetName) { - Initial(JET_MENU_EXEC); - m_pTargetFormFillEnv.Reset(pTargetFormFillEnv); - m_strTargetName = strTargetName; -} - -void CJS_EventHandler::OnExternal_Exec() { - Initial(JET_EXTERNAL_EXEC); -} - -void CJS_EventHandler::OnBatchExec( - CPDFSDK_FormFillEnvironment* pTargetFormFillEnv) { - Initial(JET_BATCH_EXEC); - m_pTargetFormFillEnv.Reset(pTargetFormFillEnv); -} - -void CJS_EventHandler::OnConsole_Exec() { - Initial(JET_CONSOLE_EXEC); -} - -void CJS_EventHandler::Initial(JS_EVENT_T type) { - m_eEventType = type; - - m_strTargetName = L""; - m_strSourceName = L""; - m_pWideStrChange = nullptr; - m_WideStrChangeDu = L""; - m_WideStrChangeEx = L""; - m_nCommitKey = -1; - m_bKeyDown = false; - m_bModifier = false; - m_bShift = false; - m_pISelEnd = nullptr; - m_nSelEndDu = 0; - m_pISelStart = nullptr; - m_nSelStartDu = 0; - m_bWillCommit = false; - m_pValue = nullptr; - m_bFieldFull = false; - m_pbRc = nullptr; - m_bRcDu = false; - - m_pTargetBookMark = nullptr; - m_pTargetFormFillEnv.Reset(); - m_pTargetAnnot.Reset(); - - m_bValid = true; -} - -void CJS_EventHandler::Destroy() { - m_bValid = false; -} - -bool CJS_EventHandler::IsValid() { - return m_bValid; -} - -CFX_WideString& CJS_EventHandler::Change() { - if (m_pWideStrChange) { - return *m_pWideStrChange; - } - return m_WideStrChangeDu; -} - -CFX_WideString CJS_EventHandler::ChangeEx() { - return m_WideStrChangeEx; -} - -int CJS_EventHandler::CommitKey() { - return m_nCommitKey; -} - -bool CJS_EventHandler::FieldFull() { - return m_bFieldFull; -} - -bool CJS_EventHandler::KeyDown() { - return m_bKeyDown; -} - -bool CJS_EventHandler::Modifier() { - return m_bModifier; -} - -const FX_WCHAR* CJS_EventHandler::Name() { - switch (m_eEventType) { - case JET_APP_INIT: - return L"Init"; - case JET_BATCH_EXEC: - return L"Exec"; - case JET_BOOKMARK_MOUSEUP: - return L"Mouse Up"; - case JET_CONSOLE_EXEC: - return L"Exec"; - case JET_DOC_DIDPRINT: - return L"DidPrint"; - case JET_DOC_DIDSAVE: - return L"DidSave"; - case JET_DOC_OPEN: - return L"Open"; - case JET_DOC_WILLCLOSE: - return L"WillClose"; - case JET_DOC_WILLPRINT: - return L"WillPrint"; - case JET_DOC_WILLSAVE: - return L"WillSave"; - case JET_EXTERNAL_EXEC: - return L"Exec"; - case JET_FIELD_FOCUS: - case JET_SCREEN_FOCUS: - return L"Focus"; - case JET_FIELD_BLUR: - case JET_SCREEN_BLUR: - return L"Blur"; - case JET_FIELD_MOUSEDOWN: - case JET_SCREEN_MOUSEDOWN: - return L"Mouse Down"; - case JET_FIELD_MOUSEUP: - case JET_SCREEN_MOUSEUP: - return L"Mouse Up"; - case JET_FIELD_MOUSEENTER: - case JET_SCREEN_MOUSEENTER: - return L"Mouse Enter"; - case JET_FIELD_MOUSEEXIT: - case JET_SCREEN_MOUSEEXIT: - return L"Mouse Exit"; - case JET_FIELD_CALCULATE: - return L"Calculate"; - case JET_FIELD_FORMAT: - return L"Format"; - case JET_FIELD_KEYSTROKE: - return L"Keystroke"; - case JET_FIELD_VALIDATE: - return L"Validate"; - case JET_LINK_MOUSEUP: - return L"Mouse Up"; - case JET_MENU_EXEC: - return L"Exec"; - case JET_PAGE_OPEN: - case JET_SCREEN_OPEN: - return L"Open"; - case JET_PAGE_CLOSE: - case JET_SCREEN_CLOSE: - return L"Close"; - case JET_SCREEN_INVIEW: - case JET_PAGE_INVIEW: - return L"InView"; - case JET_PAGE_OUTVIEW: - case JET_SCREEN_OUTVIEW: - return L"OutView"; - default: - return L""; - } -} - -const FX_WCHAR* CJS_EventHandler::Type() { - switch (m_eEventType) { - case JET_APP_INIT: - return L"App"; - case JET_BATCH_EXEC: - return L"Batch"; - case JET_BOOKMARK_MOUSEUP: - return L"BookMark"; - case JET_CONSOLE_EXEC: - return L"Console"; - case JET_DOC_DIDPRINT: - case JET_DOC_DIDSAVE: - case JET_DOC_OPEN: - case JET_DOC_WILLCLOSE: - case JET_DOC_WILLPRINT: - case JET_DOC_WILLSAVE: - return L"Doc"; - case JET_EXTERNAL_EXEC: - return L"External"; - case JET_FIELD_BLUR: - case JET_FIELD_FOCUS: - case JET_FIELD_MOUSEDOWN: - case JET_FIELD_MOUSEENTER: - case JET_FIELD_MOUSEEXIT: - case JET_FIELD_MOUSEUP: - case JET_FIELD_CALCULATE: - case JET_FIELD_FORMAT: - case JET_FIELD_KEYSTROKE: - case JET_FIELD_VALIDATE: - return L"Field"; - case JET_SCREEN_FOCUS: - case JET_SCREEN_BLUR: - case JET_SCREEN_OPEN: - case JET_SCREEN_CLOSE: - case JET_SCREEN_MOUSEDOWN: - case JET_SCREEN_MOUSEUP: - case JET_SCREEN_MOUSEENTER: - case JET_SCREEN_MOUSEEXIT: - case JET_SCREEN_INVIEW: - case JET_SCREEN_OUTVIEW: - return L"Screen"; - case JET_LINK_MOUSEUP: - return L"Link"; - case JET_MENU_EXEC: - return L"Menu"; - case JET_PAGE_OPEN: - case JET_PAGE_CLOSE: - case JET_PAGE_INVIEW: - case JET_PAGE_OUTVIEW: - return L"Page"; - default: - return L""; - } -} - -bool& CJS_EventHandler::Rc() { - if (m_pbRc) { - return *m_pbRc; - } - return m_bRcDu; -} - -int& CJS_EventHandler::SelEnd() { - if (m_pISelEnd) { - return *m_pISelEnd; - } - return m_nSelEndDu; -} - -int& CJS_EventHandler::SelStart() { - if (m_pISelStart) { - return *m_pISelStart; - } - return m_nSelStartDu; -} - -bool CJS_EventHandler::Shift() { - return m_bShift; -} - -Field* CJS_EventHandler::Source() { - CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime(); - v8::Local pDocObj = - pRuntime->NewFxDynamicObj(CJS_Document::g_nObjDefnID); - if (pDocObj.IsEmpty()) - return nullptr; - - v8::Local pFieldObj = - pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - if (pFieldObj.IsEmpty()) - return nullptr; - - CJS_Document* pJSDocument = - static_cast(pRuntime->GetObjectPrivate(pDocObj)); - CJS_Field* pJSField = - static_cast(pRuntime->GetObjectPrivate(pFieldObj)); - - Document* pDocument = static_cast(pJSDocument->GetEmbedObject()); - pDocument->SetFormFillEnv(m_pTargetFormFillEnv - ? m_pTargetFormFillEnv.Get() - : m_pJSEventContext->GetFormFillEnv()); - - Field* pField = static_cast(pJSField->GetEmbedObject()); - pField->AttachField(pDocument, m_strSourceName); - return pField; -} - -Field* CJS_EventHandler::Target_Field() { - CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime(); - v8::Local pDocObj = - pRuntime->NewFxDynamicObj(CJS_Document::g_nObjDefnID); - if (pDocObj.IsEmpty()) - return nullptr; - - v8::Local pFieldObj = - pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - if (pFieldObj.IsEmpty()) - return nullptr; - - CJS_Document* pJSDocument = - static_cast(pRuntime->GetObjectPrivate(pDocObj)); - CJS_Field* pJSField = - static_cast(pRuntime->GetObjectPrivate(pFieldObj)); - - Document* pDocument = static_cast(pJSDocument->GetEmbedObject()); - pDocument->SetFormFillEnv(m_pTargetFormFillEnv - ? m_pTargetFormFillEnv.Get() - : m_pJSEventContext->GetFormFillEnv()); - - Field* pField = static_cast(pJSField->GetEmbedObject()); - pField->AttachField(pDocument, m_strTargetName); - return pField; -} - -CFX_WideString& CJS_EventHandler::Value() { - return *m_pValue; -} - -bool CJS_EventHandler::WillCommit() { - return m_bWillCommit; -} - -CFX_WideString CJS_EventHandler::TargetName() { - return m_strTargetName; -} diff --git a/fpdfsdk/javascript/JS_EventHandler.h b/fpdfsdk/javascript/JS_EventHandler.h deleted file mode 100644 index b9836b04e479f43991abe06bdc1cbd7fdd69db02..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_EventHandler.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_JS_EVENTHANDLER_H_ -#define FPDFSDK_JAVASCRIPT_JS_EVENTHANDLER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" - -class CJS_EventContext; -class CPDFSDK_Annot; -class CPDF_Bookmark; -class CPDF_FormField; -class Field; - -enum JS_EVENT_T { - JET_UNKNOWN, - JET_APP_INIT, - JET_DOC_OPEN, - JET_DOC_WILLPRINT, - JET_DOC_DIDPRINT, - JET_DOC_WILLSAVE, - JET_DOC_DIDSAVE, - JET_DOC_WILLCLOSE, - JET_PAGE_OPEN, - JET_PAGE_CLOSE, - JET_PAGE_INVIEW, - JET_PAGE_OUTVIEW, - JET_FIELD_MOUSEDOWN, - JET_FIELD_MOUSEUP, - JET_FIELD_MOUSEENTER, - JET_FIELD_MOUSEEXIT, - JET_FIELD_FOCUS, - JET_FIELD_BLUR, - JET_FIELD_KEYSTROKE, - JET_FIELD_VALIDATE, - JET_FIELD_CALCULATE, - JET_FIELD_FORMAT, - JET_SCREEN_FOCUS, - JET_SCREEN_BLUR, - JET_SCREEN_OPEN, - JET_SCREEN_CLOSE, - JET_SCREEN_MOUSEDOWN, - JET_SCREEN_MOUSEUP, - JET_SCREEN_MOUSEENTER, - JET_SCREEN_MOUSEEXIT, - JET_SCREEN_INVIEW, - JET_SCREEN_OUTVIEW, - JET_BATCH_EXEC, - JET_MENU_EXEC, - JET_CONSOLE_EXEC, - JET_EXTERNAL_EXEC, - JET_BOOKMARK_MOUSEUP, - JET_LINK_MOUSEUP -}; - -class CJS_EventHandler { - public: - explicit CJS_EventHandler(CJS_EventContext* pContext); - virtual ~CJS_EventHandler(); - - void OnApp_Init(); - - void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName); - void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv); - - void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv); - - void OnField_Calculate(CPDF_FormField* pSource, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool& bRc); - void OnField_Format(CPDF_FormField* pTarget, - CFX_WideString& Value, - bool bWillCommit); - void OnField_Keystroke(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - bool KeyDown, - bool bModifier, - int& nSelEnd, - int& nSelStart, - bool bShift, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool bWillCommit, - bool bFieldFull, - bool& bRc); - void OnField_Validate(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - bool bKeyDown, - bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool& bRc); - - void OnField_MouseDown(bool bModifier, bool bShift, CPDF_FormField* pTarget); - void OnField_MouseEnter(bool bModifier, bool bShift, CPDF_FormField* pTarget); - void OnField_MouseExit(bool bModifier, bool bShift, CPDF_FormField* pTarget); - void OnField_MouseUp(bool bModifier, bool bShift, CPDF_FormField* pTarget); - void OnField_Blur(bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - const CFX_WideString& Value); - void OnField_Focus(bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - const CFX_WideString& Value); - - void OnScreen_Focus(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_Blur(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_Open(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_Close(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_MouseDown(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_MouseUp(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_MouseEnter(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_MouseExit(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_InView(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - void OnScreen_OutView(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); - - void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark); - void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv); - - void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName); - void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv); - void OnConsole_Exec(); - void OnExternal_Exec(); - - public: - void Initial(JS_EVENT_T type); - void Destroy(); - bool IsValid(); - - CFX_WideString& Change(); - CFX_WideString ChangeEx(); - int CommitKey(); - bool FieldFull(); - bool KeyDown(); - bool Modifier(); - const FX_WCHAR* Name(); - const FX_WCHAR* Type(); - bool& Rc(); - int& SelEnd(); - int& SelStart(); - bool Shift(); - Field* Source(); - Field* Target_Field(); - CFX_WideString& Value(); - bool WillCommit(); - CFX_WideString TargetName(); - - JS_EVENT_T EventType() { return m_eEventType; } - - public: - CJS_EventContext* const m_pJSEventContext; // Not Owned. - JS_EVENT_T m_eEventType; - bool m_bValid; - - CFX_WideString m_strTargetName; - CFX_WideString m_strSourceName; - CFX_WideString* m_pWideStrChange; - CFX_WideString m_WideStrChangeDu; - CFX_WideString m_WideStrChangeEx; - int m_nCommitKey; - bool m_bKeyDown; - bool m_bModifier; - bool m_bShift; - int* m_pISelEnd; - int m_nSelEndDu; - int* m_pISelStart; - int m_nSelStartDu; - bool m_bWillCommit; - CFX_WideString* m_pValue; - bool m_bFieldFull; - bool* m_pbRc; - bool m_bRcDu; - - CPDF_Bookmark* m_pTargetBookMark; - CPDFSDK_FormFillEnvironment::ObservedPtr m_pTargetFormFillEnv; - CPDFSDK_Annot::ObservedPtr m_pTargetAnnot; -}; - -#endif // FPDFSDK_JAVASCRIPT_JS_EVENTHANDLER_H_ diff --git a/fpdfsdk/javascript/JS_GlobalData.cpp b/fpdfsdk/javascript/JS_GlobalData.cpp deleted file mode 100644 index 68d929fb3a62f6a58059f7b173e25c3552a2f679..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_GlobalData.cpp +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/JS_GlobalData.h" - -#include - -#include "core/fdrm/crypto/fx_crypt.h" -#include "third_party/base/stl_util.h" - -#define JS_MAXGLOBALDATA (1024 * 4 - 8) - -#define READER_JS_GLOBALDATA_FILENAME L"Reader_JsGlobal.Data" -#define PHANTOM_JS_GLOBALDATA_FILENAME L"Phantom_JsGlobal.Data" -#define SDK_JS_GLOBALDATA_FILENAME L"SDK_JsGlobal.Data" - -namespace { - -const uint8_t JS_RC4KEY[] = { - 0x19, 0xa8, 0xe8, 0x01, 0xf6, 0xa8, 0xb6, 0x4d, 0x82, 0x04, 0x45, 0x6d, - 0xb4, 0xcf, 0xd7, 0x77, 0x67, 0xf9, 0x75, 0x9f, 0xf0, 0xe0, 0x1e, 0x51, - 0xee, 0x46, 0xfd, 0x0b, 0xc9, 0x93, 0x25, 0x55, 0x4a, 0xee, 0xe0, 0x16, - 0xd0, 0xdf, 0x8c, 0xfa, 0x2a, 0xa9, 0x49, 0xfd, 0x97, 0x1c, 0x0e, 0x22, - 0x13, 0x28, 0x7c, 0xaf, 0xc4, 0xfc, 0x9c, 0x12, 0x65, 0x8c, 0x4e, 0x5b, - 0x04, 0x75, 0x89, 0xc9, 0xb1, 0xed, 0x50, 0xca, 0x96, 0x6f, 0x1a, 0x7a, - 0xfe, 0x58, 0x5d, 0xec, 0x19, 0x4a, 0xf6, 0x35, 0x6a, 0x97, 0x14, 0x00, - 0x0e, 0xd0, 0x6b, 0xbb, 0xd5, 0x75, 0x55, 0x8b, 0x6e, 0x6b, 0x19, 0xa0, - 0xf8, 0x77, 0xd5, 0xa3}; - -// Returns true if non-empty, setting sPropName -bool TrimPropName(CFX_ByteString* sPropName) { - sPropName->TrimLeft(); - sPropName->TrimRight(); - return sPropName->GetLength() != 0; -} - -CJS_GlobalData* g_pInstance = nullptr; - -} // namespace - -// static -CJS_GlobalData* CJS_GlobalData::GetRetainedInstance( - CPDFSDK_FormFillEnvironment* pApp) { - if (!g_pInstance) { - g_pInstance = new CJS_GlobalData(); - } - ++g_pInstance->m_RefCount; - return g_pInstance; -} - -void CJS_GlobalData::Release() { - if (!--m_RefCount) { - delete g_pInstance; - g_pInstance = nullptr; - } -} - -CJS_GlobalData::CJS_GlobalData() - : m_RefCount(0), m_sFilePath(SDK_JS_GLOBALDATA_FILENAME) { - LoadGlobalPersistentVariables(); -} - -CJS_GlobalData::~CJS_GlobalData() { - SaveGlobalPersisitentVariables(); -} - -CJS_GlobalData::iterator CJS_GlobalData::FindGlobalVariable( - const CFX_ByteString& propname) { - for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end(); - ++it) { - if ((*it)->data.sKey == propname) - return it; - } - return m_arrayGlobalData.end(); -} - -CJS_GlobalData::const_iterator CJS_GlobalData::FindGlobalVariable( - const CFX_ByteString& propname) const { - for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end(); - ++it) { - if ((*it)->data.sKey == propname) - return it; - } - return m_arrayGlobalData.end(); -} - -CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable( - const CFX_ByteString& propname) { - auto iter = FindGlobalVariable(propname); - return iter != m_arrayGlobalData.end() ? iter->get() : nullptr; -} - -void CJS_GlobalData::SetGlobalVariableNumber(const CFX_ByteString& propname, - double dData) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return; - - if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { - pData->data.nType = JS_GlobalDataType::NUMBER; - pData->data.dData = dData; - return; - } - std::unique_ptr pNewData(new CJS_GlobalData_Element); - pNewData->data.sKey = sPropName; - pNewData->data.nType = JS_GlobalDataType::NUMBER; - pNewData->data.dData = dData; - m_arrayGlobalData.push_back(std::move(pNewData)); -} - -void CJS_GlobalData::SetGlobalVariableBoolean(const CFX_ByteString& propname, - bool bData) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return; - - if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { - pData->data.nType = JS_GlobalDataType::BOOLEAN; - pData->data.bData = bData; - return; - } - std::unique_ptr pNewData(new CJS_GlobalData_Element); - pNewData->data.sKey = sPropName; - pNewData->data.nType = JS_GlobalDataType::BOOLEAN; - pNewData->data.bData = bData; - m_arrayGlobalData.push_back(std::move(pNewData)); -} - -void CJS_GlobalData::SetGlobalVariableString(const CFX_ByteString& propname, - const CFX_ByteString& sData) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return; - - if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { - pData->data.nType = JS_GlobalDataType::STRING; - pData->data.sData = sData; - return; - } - std::unique_ptr pNewData(new CJS_GlobalData_Element); - pNewData->data.sKey = sPropName; - pNewData->data.nType = JS_GlobalDataType::STRING; - pNewData->data.sData = sData; - m_arrayGlobalData.push_back(std::move(pNewData)); -} - -void CJS_GlobalData::SetGlobalVariableObject( - const CFX_ByteString& propname, - const CJS_GlobalVariableArray& array) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return; - - if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { - pData->data.nType = JS_GlobalDataType::OBJECT; - pData->data.objData.Copy(array); - return; - } - std::unique_ptr pNewData(new CJS_GlobalData_Element); - pNewData->data.sKey = sPropName; - pNewData->data.nType = JS_GlobalDataType::OBJECT; - pNewData->data.objData.Copy(array); - m_arrayGlobalData.push_back(std::move(pNewData)); -} - -void CJS_GlobalData::SetGlobalVariableNull(const CFX_ByteString& propname) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return; - - if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { - pData->data.nType = JS_GlobalDataType::NULLOBJ; - return; - } - std::unique_ptr pNewData(new CJS_GlobalData_Element); - pNewData->data.sKey = sPropName; - pNewData->data.nType = JS_GlobalDataType::NULLOBJ; - m_arrayGlobalData.push_back(std::move(pNewData)); -} - -bool CJS_GlobalData::SetGlobalVariablePersistent(const CFX_ByteString& propname, - bool bPersistent) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return false; - - CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName); - if (!pData) - return false; - - pData->bPersistent = bPersistent; - return true; -} - -bool CJS_GlobalData::DeleteGlobalVariable(const CFX_ByteString& propname) { - CFX_ByteString sPropName(propname); - if (!TrimPropName(&sPropName)) - return false; - - auto iter = FindGlobalVariable(sPropName); - if (iter == m_arrayGlobalData.end()) - return false; - - m_arrayGlobalData.erase(iter); - return true; -} - -int32_t CJS_GlobalData::GetSize() const { - return pdfium::CollectionSize(m_arrayGlobalData); -} - -CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const { - if (index < 0 || index >= GetSize()) - return nullptr; - return m_arrayGlobalData[index].get(); -} - -void CJS_GlobalData::LoadGlobalPersistentVariables() { - uint8_t* pBuffer = nullptr; - int32_t nLength = 0; - - LoadFileBuffer(m_sFilePath.c_str(), pBuffer, nLength); - CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY)); - - if (pBuffer) { - uint8_t* p = pBuffer; - uint16_t wType = *((uint16_t*)p); - p += sizeof(uint16_t); - - if (wType == (uint16_t)(('X' << 8) | 'F')) { - uint16_t wVersion = *((uint16_t*)p); - p += sizeof(uint16_t); - - ASSERT(wVersion <= 2); - - uint32_t dwCount = *((uint32_t*)p); - p += sizeof(uint32_t); - - uint32_t dwSize = *((uint32_t*)p); - p += sizeof(uint32_t); - - if (dwSize == nLength - sizeof(uint16_t) * 2 - sizeof(uint32_t) * 2) { - for (int32_t i = 0, sz = dwCount; i < sz; i++) { - if (p > pBuffer + nLength) - break; - - uint32_t dwNameLen = *((uint32_t*)p); - p += sizeof(uint32_t); - - if (p + dwNameLen > pBuffer + nLength) - break; - - CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen); - p += sizeof(char) * dwNameLen; - - JS_GlobalDataType wDataType = - static_cast(*((uint16_t*)p)); - p += sizeof(uint16_t); - - switch (wDataType) { - case JS_GlobalDataType::NUMBER: { - double dData = 0; - switch (wVersion) { - case 1: { - uint32_t dwData = *((uint32_t*)p); - p += sizeof(uint32_t); - dData = dwData; - } break; - case 2: { - dData = *((double*)p); - p += sizeof(double); - } break; - } - SetGlobalVariableNumber(sEntry, dData); - SetGlobalVariablePersistent(sEntry, true); - } break; - case JS_GlobalDataType::BOOLEAN: { - uint16_t wData = *((uint16_t*)p); - p += sizeof(uint16_t); - SetGlobalVariableBoolean(sEntry, (bool)(wData == 1)); - SetGlobalVariablePersistent(sEntry, true); - } break; - case JS_GlobalDataType::STRING: { - uint32_t dwLength = *((uint32_t*)p); - p += sizeof(uint32_t); - - if (p + dwLength > pBuffer + nLength) - break; - - SetGlobalVariableString(sEntry, CFX_ByteString(p, dwLength)); - SetGlobalVariablePersistent(sEntry, true); - p += sizeof(char) * dwLength; - } break; - case JS_GlobalDataType::NULLOBJ: { - SetGlobalVariableNull(sEntry); - SetGlobalVariablePersistent(sEntry, true); - } - case JS_GlobalDataType::OBJECT: - break; - } - } - } - } - FX_Free(pBuffer); - } -} - -void CJS_GlobalData::SaveGlobalPersisitentVariables() { - uint32_t nCount = 0; - CFX_BinaryBuf sData; - for (const auto& pElement : m_arrayGlobalData) { - if (pElement->bPersistent) { - CFX_BinaryBuf sElement; - MakeByteString(pElement->data.sKey, &pElement->data, sElement); - if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA) - break; - - sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize()); - nCount++; - } - } - - CFX_BinaryBuf sFile; - uint16_t wType = (uint16_t)(('X' << 8) | 'F'); - sFile.AppendBlock(&wType, sizeof(uint16_t)); - uint16_t wVersion = 2; - sFile.AppendBlock(&wVersion, sizeof(uint16_t)); - sFile.AppendBlock(&nCount, sizeof(uint32_t)); - uint32_t dwSize = sData.GetSize(); - sFile.AppendBlock(&dwSize, sizeof(uint32_t)); - - sFile.AppendBlock(sData.GetBuffer(), sData.GetSize()); - - CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, - sizeof(JS_RC4KEY)); - WriteFileBuffer(m_sFilePath.c_str(), (const FX_CHAR*)sFile.GetBuffer(), - sFile.GetSize()); -} - -void CJS_GlobalData::LoadFileBuffer(const FX_WCHAR* sFilePath, - uint8_t*& pBuffer, - int32_t& nLength) { - // UnSupport. -} - -void CJS_GlobalData::WriteFileBuffer(const FX_WCHAR* sFilePath, - const FX_CHAR* pBuffer, - int32_t nLength) { - // UnSupport. -} - -void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, - CJS_KeyValue* pData, - CFX_BinaryBuf& sData) { - switch (pData->nType) { - case JS_GlobalDataType::NUMBER: { - uint32_t dwNameLen = (uint32_t)name.GetLength(); - sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); - sData.AppendString(name); - sData.AppendBlock(&pData->nType, sizeof(uint16_t)); - - double dData = pData->dData; - sData.AppendBlock(&dData, sizeof(double)); - } break; - case JS_GlobalDataType::BOOLEAN: { - uint32_t dwNameLen = (uint32_t)name.GetLength(); - sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); - sData.AppendString(name); - sData.AppendBlock(&pData->nType, sizeof(uint16_t)); - - uint16_t wData = (uint16_t)pData->bData; - sData.AppendBlock(&wData, sizeof(uint16_t)); - } break; - case JS_GlobalDataType::STRING: { - uint32_t dwNameLen = (uint32_t)name.GetLength(); - sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); - sData.AppendString(name); - sData.AppendBlock(&pData->nType, sizeof(uint16_t)); - - uint32_t dwDataLen = (uint32_t)pData->sData.GetLength(); - sData.AppendBlock(&dwDataLen, sizeof(uint32_t)); - sData.AppendString(pData->sData); - } break; - case JS_GlobalDataType::NULLOBJ: { - uint32_t dwNameLen = (uint32_t)name.GetLength(); - sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); - sData.AppendString(name); - sData.AppendBlock(&pData->nType, sizeof(uint32_t)); - } break; - default: - break; - } -} diff --git a/fpdfsdk/javascript/JS_GlobalData.h b/fpdfsdk/javascript/JS_GlobalData.h deleted file mode 100644 index c8947cd580780c69df32a2706bcad05351dd55a5..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_GlobalData.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_JS_GLOBALDATA_H_ -#define FPDFSDK_JAVASCRIPT_JS_GLOBALDATA_H_ - -#include -#include - -#include "core/fxcrt/fx_basic.h" -#include "fpdfsdk/javascript/JS_KeyValue.h" - -class CPDFSDK_FormFillEnvironment; - -class CJS_GlobalData_Element { - public: - CJS_GlobalData_Element() {} - ~CJS_GlobalData_Element() {} - - CJS_KeyValue data; - bool bPersistent; -}; - -class CJS_GlobalData { - public: - static CJS_GlobalData* GetRetainedInstance(CPDFSDK_FormFillEnvironment* pApp); - void Release(); - - void SetGlobalVariableNumber(const CFX_ByteString& propname, double dData); - void SetGlobalVariableBoolean(const CFX_ByteString& propname, bool bData); - void SetGlobalVariableString(const CFX_ByteString& propname, - const CFX_ByteString& sData); - void SetGlobalVariableObject(const CFX_ByteString& propname, - const CJS_GlobalVariableArray& array); - void SetGlobalVariableNull(const CFX_ByteString& propname); - bool SetGlobalVariablePersistent(const CFX_ByteString& propname, - bool bPersistent); - bool DeleteGlobalVariable(const CFX_ByteString& propname); - - int32_t GetSize() const; - CJS_GlobalData_Element* GetAt(int index) const; - - private: - using iterator = - std::vector>::iterator; - using const_iterator = - std::vector>::const_iterator; - - CJS_GlobalData(); - ~CJS_GlobalData(); - - void LoadGlobalPersistentVariables(); - void SaveGlobalPersisitentVariables(); - - CJS_GlobalData_Element* GetGlobalVariable(const CFX_ByteString& sPropname); - iterator FindGlobalVariable(const CFX_ByteString& sPropname); - const_iterator FindGlobalVariable(const CFX_ByteString& sPropname) const; - - void LoadFileBuffer(const FX_WCHAR* sFilePath, - uint8_t*& pBuffer, - int32_t& nLength); - void WriteFileBuffer(const FX_WCHAR* sFilePath, - const FX_CHAR* pBuffer, - int32_t nLength); - void MakeByteString(const CFX_ByteString& name, - CJS_KeyValue* pData, - CFX_BinaryBuf& sData); - - size_t m_RefCount; - std::vector> m_arrayGlobalData; - CFX_WideString m_sFilePath; -}; - -#endif // FPDFSDK_JAVASCRIPT_JS_GLOBALDATA_H_ diff --git a/fpdfsdk/javascript/JS_KeyValue.cpp b/fpdfsdk/javascript/JS_KeyValue.cpp deleted file mode 100644 index 7d1e575377a5795d74e838c82c9361a8cce8a960..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_KeyValue.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2016 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 "fpdfsdk/javascript/JS_KeyValue.h" - -CJS_GlobalVariableArray::CJS_GlobalVariableArray() {} - -CJS_GlobalVariableArray::~CJS_GlobalVariableArray() {} - -void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array) { - m_Array.clear(); - for (int i = 0, sz = array.Count(); i < sz; i++) { - CJS_KeyValue* pOldObjData = array.GetAt(i); - switch (pOldObjData->nType) { - case JS_GlobalDataType::NUMBER: { - CJS_KeyValue* pNewObjData = new CJS_KeyValue; - pNewObjData->sKey = pOldObjData->sKey; - pNewObjData->nType = pOldObjData->nType; - pNewObjData->dData = pOldObjData->dData; - Add(pNewObjData); - } break; - case JS_GlobalDataType::BOOLEAN: { - CJS_KeyValue* pNewObjData = new CJS_KeyValue; - pNewObjData->sKey = pOldObjData->sKey; - pNewObjData->nType = pOldObjData->nType; - pNewObjData->bData = pOldObjData->bData; - Add(pNewObjData); - } break; - case JS_GlobalDataType::STRING: { - CJS_KeyValue* pNewObjData = new CJS_KeyValue; - pNewObjData->sKey = pOldObjData->sKey; - pNewObjData->nType = pOldObjData->nType; - pNewObjData->sData = pOldObjData->sData; - Add(pNewObjData); - } break; - case JS_GlobalDataType::OBJECT: { - CJS_KeyValue* pNewObjData = new CJS_KeyValue; - pNewObjData->sKey = pOldObjData->sKey; - pNewObjData->nType = pOldObjData->nType; - pNewObjData->objData.Copy(pOldObjData->objData); - Add(pNewObjData); - } break; - case JS_GlobalDataType::NULLOBJ: { - CJS_KeyValue* pNewObjData = new CJS_KeyValue; - pNewObjData->sKey = pOldObjData->sKey; - pNewObjData->nType = pOldObjData->nType; - Add(pNewObjData); - } break; - } - } -} - -void CJS_GlobalVariableArray::Add(CJS_KeyValue* p) { - m_Array.push_back(std::unique_ptr(p)); -} - -int CJS_GlobalVariableArray::Count() const { - return m_Array.size(); -} - -CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const { - return m_Array.at(index).get(); -} - -CJS_KeyValue::CJS_KeyValue() {} - -CJS_KeyValue::~CJS_KeyValue() {} diff --git a/fpdfsdk/javascript/JS_KeyValue.h b/fpdfsdk/javascript/JS_KeyValue.h deleted file mode 100644 index a571588870938a4a57c33e5dc573f4c7d3996f69..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_KeyValue.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 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 FPDFSDK_JAVASCRIPT_JS_KEYVALUE_H_ -#define FPDFSDK_JAVASCRIPT_JS_KEYVALUE_H_ - -#include -#include - -#include "core/fxcrt/fx_basic.h" - -enum class JS_GlobalDataType { NUMBER = 0, BOOLEAN, STRING, OBJECT, NULLOBJ }; - -class CJS_KeyValue; - -class CJS_GlobalVariableArray { - public: - CJS_GlobalVariableArray(); - ~CJS_GlobalVariableArray(); - - void Add(CJS_KeyValue* p); - int Count() const; - CJS_KeyValue* GetAt(int index) const; - void Copy(const CJS_GlobalVariableArray& array); - - private: - std::vector> m_Array; -}; - -class CJS_KeyValue { - public: - CJS_KeyValue(); - ~CJS_KeyValue(); - - CFX_ByteString sKey; - JS_GlobalDataType nType; - double dData; - bool bData; - CFX_ByteString sData; - CJS_GlobalVariableArray objData; -}; - -#endif // FPDFSDK_JAVASCRIPT_JS_KEYVALUE_H_ diff --git a/fpdfsdk/javascript/JS_Object.cpp b/fpdfsdk/javascript/JS_Object.cpp deleted file mode 100644 index cd86889337e09bae20099bbbcf4b04c59e240e95..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_Object.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/JS_Object.h" - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/cjs_event_context.h" - -CJS_EmbedObj::CJS_EmbedObj(CJS_Object* pJSObject) : m_pJSObject(pJSObject) {} - -CJS_EmbedObj::~CJS_EmbedObj() { -} - -void FreeObject(const v8::WeakCallbackInfo& data) { - CJS_Object* pJSObj = data.GetParameter(); - delete pJSObj; - CFXJS_Engine::FreeObjectPrivate(data.GetInternalField(0)); -} - -void DisposeObject(const v8::WeakCallbackInfo& data) { - CJS_Object* pJSObj = data.GetParameter(); - pJSObj->Dispose(); - data.SetSecondPassCallback(FreeObject); -} - -CJS_Object::CJS_Object(v8::Local pObject) { - m_pIsolate = pObject->GetIsolate(); - m_pV8Object.Reset(m_pIsolate, pObject); -} - -CJS_Object::~CJS_Object() {} - -void CJS_Object::MakeWeak() { - m_pV8Object.SetWeak(this, DisposeObject, - v8::WeakCallbackType::kInternalFields); -} - -void CJS_Object::Dispose() { - m_pV8Object.Reset(); -} - -void CJS_Object::InitInstance(IJS_Runtime* pIRuntime) {} diff --git a/fpdfsdk/javascript/JS_Object.h b/fpdfsdk/javascript/JS_Object.h deleted file mode 100644 index 2e5c75c948b8a48c070b9dc43cb484db36680359..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_Object.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_JS_OBJECT_H_ -#define FPDFSDK_JAVASCRIPT_JS_OBJECT_H_ - -#include -#include - -#include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fxjs/fxjs_v8.h" - -class CJS_EventContext; -class CJS_Object; -class CPDFSDK_FormFillEnvironment; - -class CJS_EmbedObj { - public: - explicit CJS_EmbedObj(CJS_Object* pJSObject); - virtual ~CJS_EmbedObj(); - - CJS_Object* GetJSObject() const { return m_pJSObject; } - - protected: - CJS_Object* const m_pJSObject; -}; - -class CJS_Object { - public: - explicit CJS_Object(v8::Local pObject); - virtual ~CJS_Object(); - - void MakeWeak(); - void Dispose(); - - virtual void InitInstance(IJS_Runtime* pIRuntime); - - v8::Local ToV8Object() { return m_pV8Object.Get(m_pIsolate); } - - // Takes ownership of |pObj|. - void SetEmbedObject(CJS_EmbedObj* pObj) { m_pEmbedObj.reset(pObj); } - CJS_EmbedObj* GetEmbedObject() const { return m_pEmbedObj.get(); } - - v8::Isolate* GetIsolate() const { return m_pIsolate; } - - protected: - std::unique_ptr m_pEmbedObj; - v8::Global m_pV8Object; - v8::Isolate* m_pIsolate; -}; - - -#endif // FPDFSDK_JAVASCRIPT_JS_OBJECT_H_ diff --git a/fpdfsdk/javascript/JS_Runtime_Stub.cpp b/fpdfsdk/javascript/JS_Runtime_Stub.cpp deleted file mode 100644 index dcd8ceb97ccce19562701801b9b24e150453e20b..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_Runtime_Stub.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2015 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 - -#include "fpdfsdk/javascript/ijs_event_context.h" -#include "fpdfsdk/javascript/ijs_runtime.h" -#include "third_party/base/ptr_util.h" - -class CJS_EventContextStub final : public IJS_EventContext { - public: - CJS_EventContextStub() {} - ~CJS_EventContextStub() override {} - - // IJS_EventContext: - bool RunScript(const CFX_WideString& script, CFX_WideString* info) override { - return false; - } - - void OnApp_Init() override {} - void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) override {} - void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnField_MouseDown(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) override {} - void OnField_MouseEnter(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) override {} - void OnField_MouseExit(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) override {} - void OnField_MouseUp(bool bModifier, - bool bShift, - CPDF_FormField* pTarget) override {} - void OnField_Focus(bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - const CFX_WideString& Value) override {} - void OnField_Blur(bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - const CFX_WideString& Value) override {} - void OnField_Calculate(CPDF_FormField* pSource, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool& bRc) override {} - void OnField_Format(CPDF_FormField* pTarget, - CFX_WideString& Value, - bool bWillCommit) override {} - void OnField_Keystroke(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - bool KeyDown, - bool bModifier, - int& nSelEnd, - int& nSelStart, - bool bShift, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool bWillCommit, - bool bFieldFull, - bool& bRc) override {} - void OnField_Validate(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - bool bKeyDown, - bool bModifier, - bool bShift, - CPDF_FormField* pTarget, - CFX_WideString& Value, - bool& bRc) override {} - void OnScreen_Focus(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_Blur(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_Open(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_Close(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_MouseDown(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_MouseUp(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_MouseEnter(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_MouseExit(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_InView(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnScreen_OutView(bool bModifier, - bool bShift, - CPDFSDK_Annot* pScreen) override {} - void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) override {} - void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString&) override {} - void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} - void OnConsole_Exec() override {} - void OnExternal_Exec() override {} -}; - -class CJS_RuntimeStub final : public IJS_Runtime { - public: - explicit CJS_RuntimeStub(CPDFSDK_FormFillEnvironment* pFormFillEnv) - : m_pFormFillEnv(pFormFillEnv) {} - ~CJS_RuntimeStub() override {} - - IJS_EventContext* NewEventContext() override { - if (!m_pContext) - m_pContext = pdfium::MakeUnique(); - return m_pContext.get(); - } - - void ReleaseEventContext(IJS_EventContext* pContext) override {} - - CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override { - return m_pFormFillEnv; - } - -#ifdef PDF_ENABLE_XFA - bool GetValueByName(const CFX_ByteStringC&, CFXJSE_Value*) override { - return false; - } - - bool SetValueByName(const CFX_ByteStringC&, CFXJSE_Value*) override { - return false; - } -#endif // PDF_ENABLE_XFA - - int ExecuteScript(const CFX_WideString& script, - CFX_WideString* info) override { - return 0; - } - - protected: - CPDFSDK_FormFillEnvironment* m_pFormFillEnv; - std::unique_ptr m_pContext; -}; - -// static -void IJS_Runtime::Initialize(unsigned int slot, void* isolate) {} - -// static -void IJS_Runtime::Destroy() {} - -// static -IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) { - return new CJS_RuntimeStub(pFormFillEnv); -} diff --git a/fpdfsdk/javascript/JS_Value.cpp b/fpdfsdk/javascript/JS_Value.cpp deleted file mode 100644 index b0588475647617fedae8fd337efa9ef7bce5c659..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_Value.cpp +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/JS_Value.h" - -#include - -#include -#include -#include -#include - -#include "fpdfsdk/javascript/Document.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_Object.h" - -namespace { - -const uint32_t g_nan[2] = {0, 0x7FF80000}; - -double GetNan() { - return *(double*)g_nan; -} - -double -MakeDate(int year, int mon, int day, int hour, int min, int sec, int ms) { - return JS_MakeDate(JS_MakeDay(year, mon, day), - JS_MakeTime(hour, min, sec, ms)); -} - -} // namespace - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, v8::Local pValue) - : m_pValue(pValue) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const int& iValue) - : m_pValue(pRuntime->NewNumber(iValue)) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const bool& bValue) - : m_pValue(pRuntime->NewBoolean(bValue)) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const float& fValue) - : m_pValue(pRuntime->NewNumber(fValue)) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const double& dValue) - : m_pValue(pRuntime->NewNumber(dValue)) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pObj) { - if (pObj) - m_pValue = pObj->ToV8Object(); -} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr) - : m_pValue(pRuntime->NewString(pWstr)) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr) - : m_pValue(pRuntime->NewString(CFX_WideString::FromLocal(pStr).c_str())) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const CJS_Array& array) - : m_pValue(array.ToV8Array(pRuntime)) {} - -CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const CJS_Date& date) - : m_pValue(date.ToV8Date(pRuntime)) {} - -CJS_Value::~CJS_Value() {} - -CJS_Value::CJS_Value(const CJS_Value& other) = default; - -void CJS_Value::Attach(v8::Local pValue) { - m_pValue = pValue; -} - -void CJS_Value::Detach() { - m_pValue = v8::Local(); -} - -int CJS_Value::ToInt(CJS_Runtime* pRuntime) const { - return pRuntime->ToInt32(m_pValue); -} - -bool CJS_Value::ToBool(CJS_Runtime* pRuntime) const { - return pRuntime->ToBoolean(m_pValue); -} - -double CJS_Value::ToDouble(CJS_Runtime* pRuntime) const { - return pRuntime->ToDouble(m_pValue); -} - -float CJS_Value::ToFloat(CJS_Runtime* pRuntime) const { - return (float)ToDouble(pRuntime); -} - -CJS_Object* CJS_Value::ToCJSObject(CJS_Runtime* pRuntime) const { - v8::Local pObj = pRuntime->ToObject(m_pValue); - return static_cast(pRuntime->GetObjectPrivate(pObj)); -} - -v8::Local CJS_Value::ToV8Object(CJS_Runtime* pRuntime) const { - return pRuntime->ToObject(m_pValue); -} - -CFX_WideString CJS_Value::ToCFXWideString(CJS_Runtime* pRuntime) const { - return pRuntime->ToWideString(m_pValue); -} - -CFX_ByteString CJS_Value::ToCFXByteString(CJS_Runtime* pRuntime) const { - return CFX_ByteString::FromUnicode(ToCFXWideString(pRuntime)); -} - -v8::Local CJS_Value::ToV8Value(CJS_Runtime* pRuntime) const { - return m_pValue; -} - -v8::Local CJS_Value::ToV8Array(CJS_Runtime* pRuntime) const { - return pRuntime->ToArray(m_pValue); -} - -void CJS_Value::SetNull(CJS_Runtime* pRuntime) { - m_pValue = pRuntime->NewNull(); -} - -void CJS_Value::MaybeCoerceToNumber(CJS_Runtime* pRuntime) { - bool bAllowNaN = false; - if (GetType() == VT_string) { - CFX_ByteString bstr = ToCFXByteString(pRuntime); - if (bstr.GetLength() == 0) - return; - if (bstr == "NaN") - bAllowNaN = true; - } - v8::Isolate* pIsolate = pRuntime->GetIsolate(); - v8::TryCatch try_catch(pIsolate); - v8::MaybeLocal maybeNum = - m_pValue->ToNumber(pIsolate->GetCurrentContext()); - if (maybeNum.IsEmpty()) - return; - v8::Local num = maybeNum.ToLocalChecked(); - if (std::isnan(num->Value()) && !bAllowNaN) - return; - m_pValue = num; -} - -// static -CJS_Value::Type CJS_Value::GetValueType(v8::Local value) { - if (value.IsEmpty()) - return VT_unknown; - if (value->IsString()) - return VT_string; - if (value->IsNumber()) - return VT_number; - if (value->IsBoolean()) - return VT_boolean; - if (value->IsDate()) - return VT_date; - if (value->IsObject()) - return VT_object; - if (value->IsNull()) - return VT_null; - if (value->IsUndefined()) - return VT_undefined; - return VT_unknown; -} - -bool CJS_Value::IsArrayObject() const { - return !m_pValue.IsEmpty() && m_pValue->IsArray(); -} - -bool CJS_Value::IsDateObject() const { - return !m_pValue.IsEmpty() && m_pValue->IsDate(); -} - -bool CJS_Value::ConvertToArray(CJS_Runtime* pRuntime, CJS_Array& array) const { - if (!IsArrayObject()) - return false; - array.Attach(pRuntime->ToArray(m_pValue)); - return true; -} - -bool CJS_Value::ConvertToDate(CJS_Runtime* pRuntime, CJS_Date& date) const { - if (!IsDateObject()) - return false; - v8::Local mutable_value = m_pValue; - date.Attach(mutable_value.As()); - return true; -} - -CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime) - : m_bIsSetting(0), m_Value(pRuntime), m_pJSRuntime(pRuntime) {} - -CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime, const CJS_Value& value) - : m_bIsSetting(0), m_Value(value), m_pJSRuntime(pRuntime) {} - -CJS_PropValue::~CJS_PropValue() {} - -void CJS_PropValue::operator<<(int iValue) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, iValue); -} - -void CJS_PropValue::operator>>(int& iValue) const { - ASSERT(m_bIsSetting); - iValue = m_Value.ToInt(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(bool bValue) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, bValue); -} - -void CJS_PropValue::operator>>(bool& bValue) const { - ASSERT(m_bIsSetting); - bValue = m_Value.ToBool(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(double dValue) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, dValue); -} - -void CJS_PropValue::operator>>(double& dValue) const { - ASSERT(m_bIsSetting); - dValue = m_Value.ToDouble(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(CJS_Object* pObj) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, pObj); -} - -void CJS_PropValue::operator>>(CJS_Object*& ppObj) const { - ASSERT(m_bIsSetting); - ppObj = m_Value.ToCJSObject(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(CJS_Document* pJsDoc) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, pJsDoc); -} - -void CJS_PropValue::operator>>(CJS_Document*& ppJsDoc) const { - ASSERT(m_bIsSetting); - ppJsDoc = static_cast(m_Value.ToCJSObject(m_pJSRuntime)); -} - -void CJS_PropValue::operator<<(v8::Local pObj) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, pObj); -} - -void CJS_PropValue::operator>>(v8::Local& ppObj) const { - ASSERT(m_bIsSetting); - ppObj = m_Value.ToV8Object(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(CFX_ByteString str) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, str.c_str()); -} - -void CJS_PropValue::operator>>(CFX_ByteString& str) const { - ASSERT(m_bIsSetting); - str = m_Value.ToCFXByteString(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(const FX_WCHAR* str) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, str); -} - -void CJS_PropValue::operator>>(CFX_WideString& wide_string) const { - ASSERT(m_bIsSetting); - wide_string = m_Value.ToCFXWideString(m_pJSRuntime); -} - -void CJS_PropValue::operator<<(CFX_WideString wide_string) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, wide_string.c_str()); -} - -void CJS_PropValue::operator>>(CJS_Array& array) const { - ASSERT(m_bIsSetting); - m_Value.ConvertToArray(m_pJSRuntime, array); -} - -void CJS_PropValue::operator<<(CJS_Array& array) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, array.ToV8Array(m_pJSRuntime)); -} - -void CJS_PropValue::operator>>(CJS_Date& date) const { - ASSERT(m_bIsSetting); - m_Value.ConvertToDate(m_pJSRuntime, date); -} - -void CJS_PropValue::operator<<(CJS_Date& date) { - ASSERT(!m_bIsSetting); - m_Value = CJS_Value(m_pJSRuntime, date); -} - -CJS_Array::CJS_Array() {} - -CJS_Array::CJS_Array(const CJS_Array& other) = default; - -CJS_Array::~CJS_Array() {} - -void CJS_Array::Attach(v8::Local pArray) { - m_pArray = pArray; -} - -void CJS_Array::GetElement(CJS_Runtime* pRuntime, - unsigned index, - CJS_Value& value) const { - if (!m_pArray.IsEmpty()) - value.Attach(pRuntime->GetArrayElement(m_pArray, index)); -} - -void CJS_Array::SetElement(CJS_Runtime* pRuntime, - unsigned index, - const CJS_Value& value) { - if (m_pArray.IsEmpty()) - m_pArray = pRuntime->NewArray(); - - pRuntime->PutArrayElement(m_pArray, index, value.ToV8Value(pRuntime)); -} - -int CJS_Array::GetLength(CJS_Runtime* pRuntime) const { - if (m_pArray.IsEmpty()) - return 0; - return pRuntime->GetArrayLength(m_pArray); -} - -v8::Local CJS_Array::ToV8Array(CJS_Runtime* pRuntime) const { - if (m_pArray.IsEmpty()) - m_pArray = pRuntime->NewArray(); - - return m_pArray; -} - -CJS_Date::CJS_Date() {} - -CJS_Date::CJS_Date(CJS_Runtime* pRuntime, double dMsecTime) - : m_pDate(pRuntime->NewDate(dMsecTime)) {} - -CJS_Date::CJS_Date(CJS_Runtime* pRuntime, - int year, - int mon, - int day, - int hour, - int min, - int sec) - : m_pDate(pRuntime->NewDate(MakeDate(year, mon, day, hour, min, sec, 0))) {} - -CJS_Date::~CJS_Date() {} - -bool CJS_Date::IsValidDate(CJS_Runtime* pRuntime) const { - return !m_pDate.IsEmpty() && !JS_PortIsNan(pRuntime->ToDouble(m_pDate)); -} - -void CJS_Date::Attach(v8::Local pDate) { - m_pDate = pDate; -} - -int CJS_Date::GetYear(CJS_Runtime* pRuntime) const { - if (!IsValidDate(pRuntime)) - return 0; - - return JS_GetYearFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate))); -} - -void CJS_Date::SetYear(CJS_Runtime* pRuntime, int iYear) { - m_pDate = pRuntime->NewDate( - MakeDate(iYear, GetMonth(pRuntime), GetDay(pRuntime), GetHours(pRuntime), - GetMinutes(pRuntime), GetSeconds(pRuntime), 0)); -} - -int CJS_Date::GetMonth(CJS_Runtime* pRuntime) const { - if (!IsValidDate(pRuntime)) - return 0; - - return JS_GetMonthFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate))); -} - -void CJS_Date::SetMonth(CJS_Runtime* pRuntime, int iMonth) { - m_pDate = pRuntime->NewDate( - MakeDate(GetYear(pRuntime), iMonth, GetDay(pRuntime), GetHours(pRuntime), - GetMinutes(pRuntime), GetSeconds(pRuntime), 0)); -} - -int CJS_Date::GetDay(CJS_Runtime* pRuntime) const { - if (!IsValidDate(pRuntime)) - return 0; - - return JS_GetDayFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate))); -} - -void CJS_Date::SetDay(CJS_Runtime* pRuntime, int iDay) { - m_pDate = pRuntime->NewDate( - MakeDate(GetYear(pRuntime), GetMonth(pRuntime), iDay, GetHours(pRuntime), - GetMinutes(pRuntime), GetSeconds(pRuntime), 0)); -} - -int CJS_Date::GetHours(CJS_Runtime* pRuntime) const { - if (!IsValidDate(pRuntime)) - return 0; - - return JS_GetHourFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate))); -} - -void CJS_Date::SetHours(CJS_Runtime* pRuntime, int iHours) { - m_pDate = pRuntime->NewDate( - MakeDate(GetYear(pRuntime), GetMonth(pRuntime), GetDay(pRuntime), iHours, - GetMinutes(pRuntime), GetSeconds(pRuntime), 0)); -} - -int CJS_Date::GetMinutes(CJS_Runtime* pRuntime) const { - if (!IsValidDate(pRuntime)) - return 0; - - return JS_GetMinFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate))); -} - -void CJS_Date::SetMinutes(CJS_Runtime* pRuntime, int minutes) { - m_pDate = pRuntime->NewDate(MakeDate(GetYear(pRuntime), GetMonth(pRuntime), - GetDay(pRuntime), GetHours(pRuntime), - minutes, GetSeconds(pRuntime), 0)); -} - -int CJS_Date::GetSeconds(CJS_Runtime* pRuntime) const { - if (!IsValidDate(pRuntime)) - return 0; - - return JS_GetSecFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate))); -} - -void CJS_Date::SetSeconds(CJS_Runtime* pRuntime, int seconds) { - m_pDate = pRuntime->NewDate(MakeDate(GetYear(pRuntime), GetMonth(pRuntime), - GetDay(pRuntime), GetHours(pRuntime), - GetMinutes(pRuntime), seconds, 0)); -} - -double CJS_Date::ToDouble(CJS_Runtime* pRuntime) const { - return !m_pDate.IsEmpty() ? pRuntime->ToDouble(m_pDate) : 0.0; -} - -CFX_WideString CJS_Date::ToString(CJS_Runtime* pRuntime) const { - return !m_pDate.IsEmpty() ? pRuntime->ToWideString(m_pDate) - : CFX_WideString(); -} - -v8::Local CJS_Date::ToV8Date(CJS_Runtime* pRuntime) const { - return m_pDate; -} - -double _getLocalTZA() { - if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) - return 0; - time_t t = 0; - time(&t); - localtime(&t); -#if _MSC_VER >= 1900 - // In gcc and in Visual Studio prior to VS 2015 'timezone' is a global - // variable declared in time.h. That variable was deprecated and in VS 2015 - // is removed, with _get_timezone replacing it. - long timezone = 0; - _get_timezone(&timezone); -#endif - return (double)(-(timezone * 1000)); -} - -int _getDaylightSavingTA(double d) { - if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) - return 0; - time_t t = (time_t)(d / 1000); - struct tm* tmp = localtime(&t); - if (!tmp) - return 0; - if (tmp->tm_isdst > 0) - // One hour. - return (int)60 * 60 * 1000; - return 0; -} - -double _Mod(double x, double y) { - double r = fmod(x, y); - if (r < 0) - r += y; - return r; -} - -int _isfinite(double v) { -#if _MSC_VER - return ::_finite(v); -#else - return std::fabs(v) < std::numeric_limits::max(); -#endif -} - -double _toInteger(double n) { - return (n >= 0) ? FXSYS_floor(n) : -FXSYS_floor(-n); -} - -bool _isLeapYear(int year) { - return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0)); -} - -int _DayFromYear(int y) { - return (int)(365 * (y - 1970.0) + FXSYS_floor((y - 1969.0) / 4) - - FXSYS_floor((y - 1901.0) / 100) + - FXSYS_floor((y - 1601.0) / 400)); -} - -double _TimeFromYear(int y) { - return 86400000.0 * _DayFromYear(y); -} - -static const uint16_t daysMonth[12] = {0, 31, 59, 90, 120, 151, - 181, 212, 243, 273, 304, 334}; -static const uint16_t leapDaysMonth[12] = {0, 31, 60, 91, 121, 152, - 182, 213, 244, 274, 305, 335}; - -double _TimeFromYearMonth(int y, int m) { - const uint16_t* pMonth = _isLeapYear(y) ? leapDaysMonth : daysMonth; - return _TimeFromYear(y) + ((double)pMonth[m]) * 86400000; -} - -int _Day(double t) { - return (int)FXSYS_floor(t / 86400000); -} - -int _YearFromTime(double t) { - // estimate the time. - int y = 1970 + static_cast(t / (365.2425 * 86400000)); - if (_TimeFromYear(y) <= t) { - while (_TimeFromYear(y + 1) <= t) - y++; - } else { - while (_TimeFromYear(y) > t) - y--; - } - return y; -} - -int _DayWithinYear(double t) { - int year = _YearFromTime(t); - int day = _Day(t); - return day - _DayFromYear(year); -} - -int _MonthFromTime(double t) { - int day = _DayWithinYear(t); - int year = _YearFromTime(t); - if (0 <= day && day < 31) - return 0; - if (31 <= day && day < 59 + _isLeapYear(year)) - return 1; - if ((59 + _isLeapYear(year)) <= day && day < (90 + _isLeapYear(year))) - return 2; - if ((90 + _isLeapYear(year)) <= day && day < (120 + _isLeapYear(year))) - return 3; - if ((120 + _isLeapYear(year)) <= day && day < (151 + _isLeapYear(year))) - return 4; - if ((151 + _isLeapYear(year)) <= day && day < (181 + _isLeapYear(year))) - return 5; - if ((181 + _isLeapYear(year)) <= day && day < (212 + _isLeapYear(year))) - return 6; - if ((212 + _isLeapYear(year)) <= day && day < (243 + _isLeapYear(year))) - return 7; - if ((243 + _isLeapYear(year)) <= day && day < (273 + _isLeapYear(year))) - return 8; - if ((273 + _isLeapYear(year)) <= day && day < (304 + _isLeapYear(year))) - return 9; - if ((304 + _isLeapYear(year)) <= day && day < (334 + _isLeapYear(year))) - return 10; - if ((334 + _isLeapYear(year)) <= day && day < (365 + _isLeapYear(year))) - return 11; - - return -1; -} - -int _DateFromTime(double t) { - int day = _DayWithinYear(t); - int year = _YearFromTime(t); - int leap = _isLeapYear(year); - int month = _MonthFromTime(t); - switch (month) { - case 0: - return day + 1; - case 1: - return day - 30; - case 2: - return day - 58 - leap; - case 3: - return day - 89 - leap; - case 4: - return day - 119 - leap; - case 5: - return day - 150 - leap; - case 6: - return day - 180 - leap; - case 7: - return day - 211 - leap; - case 8: - return day - 242 - leap; - case 9: - return day - 272 - leap; - case 10: - return day - 303 - leap; - case 11: - return day - 333 - leap; - default: - return 0; - } -} - -double JS_GetDateTime() { - if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) - return 0; - time_t t = time(nullptr); - struct tm* pTm = localtime(&t); - - int year = pTm->tm_year + 1900; - double t1 = _TimeFromYear(year); - - return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 + - pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0; -} - -int JS_GetYearFromTime(double dt) { - return _YearFromTime(dt); -} - -int JS_GetMonthFromTime(double dt) { - return _MonthFromTime(dt); -} - -int JS_GetDayFromTime(double dt) { - return _DateFromTime(dt); -} - -int JS_GetHourFromTime(double dt) { - return (int)_Mod(floor(dt / (60 * 60 * 1000)), 24); -} - -int JS_GetMinFromTime(double dt) { - return (int)_Mod(floor(dt / (60 * 1000)), 60); -} - -int JS_GetSecFromTime(double dt) { - return (int)_Mod(floor(dt / 1000), 60); -} - -double JS_DateParse(const CFX_WideString& str) { - v8::Isolate* pIsolate = v8::Isolate::GetCurrent(); - v8::Isolate::Scope isolate_scope(pIsolate); - v8::HandleScope scope(pIsolate); - - v8::Local context = pIsolate->GetCurrentContext(); - - // Use the built-in object method. - v8::Local v = - context->Global() - ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date", - v8::NewStringType::kNormal) - .ToLocalChecked()) - .ToLocalChecked(); - if (v->IsObject()) { - v8::Local o = v->ToObject(context).ToLocalChecked(); - v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse", - v8::NewStringType::kNormal) - .ToLocalChecked()) - .ToLocalChecked(); - if (v->IsFunction()) { - v8::Local funC = v8::Local::Cast(v); - const int argc = 1; - v8::Local timeStr = - CJS_Runtime::CurrentRuntimeFromIsolate(pIsolate)->NewString( - str.AsStringC()); - v8::Local argv[argc] = {timeStr}; - v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked(); - if (v->IsNumber()) { - double date = v->ToNumber(context).ToLocalChecked()->Value(); - if (!_isfinite(date)) - return date; - return JS_LocalTime(date); - } - } - } - return 0; -} - -double JS_MakeDay(int nYear, int nMonth, int nDate) { - if (!_isfinite(nYear) || !_isfinite(nMonth) || !_isfinite(nDate)) - return GetNan(); - double y = _toInteger(nYear); - double m = _toInteger(nMonth); - double dt = _toInteger(nDate); - double ym = y + FXSYS_floor((double)m / 12); - double mn = _Mod(m, 12); - - double t = _TimeFromYearMonth((int)ym, (int)mn); - - if (_YearFromTime(t) != ym || _MonthFromTime(t) != mn || - _DateFromTime(t) != 1) - return GetNan(); - return _Day(t) + dt - 1; -} - -double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) { - if (!_isfinite(nHour) || !_isfinite(nMin) || !_isfinite(nSec) || - !_isfinite(nMs)) - return GetNan(); - - double h = _toInteger(nHour); - double m = _toInteger(nMin); - double s = _toInteger(nSec); - double milli = _toInteger(nMs); - - return h * 3600000 + m * 60000 + s * 1000 + milli; -} - -double JS_MakeDate(double day, double time) { - if (!_isfinite(day) || !_isfinite(time)) - return GetNan(); - - return day * 86400000 + time; -} - -bool JS_PortIsNan(double d) { - return d != d; -} - -double JS_LocalTime(double d) { - return d + _getLocalTZA() + _getDaylightSavingTA(d); -} - -std::vector JS_ExpandKeywordParams( - CJS_Runtime* pRuntime, - const std::vector& originals, - size_t nKeywords, - ...) { - ASSERT(nKeywords); - - std::vector result(nKeywords, CJS_Value(pRuntime)); - size_t size = std::min(originals.size(), nKeywords); - for (size_t i = 0; i < size; ++i) - result[i] = originals[i]; - - if (originals.size() != 1 || originals[0].GetType() != CJS_Value::VT_object || - originals[0].IsArrayObject()) { - return result; - } - v8::Local pObj = originals[0].ToV8Object(pRuntime); - result[0] = CJS_Value(pRuntime); // Make unknown. - - va_list ap; - va_start(ap, nKeywords); - for (size_t i = 0; i < nKeywords; ++i) { - const wchar_t* property = va_arg(ap, const wchar_t*); - v8::Local v8Value = pRuntime->GetObjectProperty(pObj, property); - if (!v8Value->IsUndefined()) - result[i] = CJS_Value(pRuntime, v8Value); - } - va_end(ap); - return result; -} diff --git a/fpdfsdk/javascript/JS_Value.h b/fpdfsdk/javascript/JS_Value.h deleted file mode 100644 index 313f0c3e7b78c421acbb6c8eea0a1beca0d7a48e..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/JS_Value.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_JS_VALUE_H_ -#define FPDFSDK_JAVASCRIPT_JS_VALUE_H_ - -#include - -#include "core/fxcrt/fx_basic.h" -#include "fxjs/fxjs_v8.h" - -class CJS_Array; -class CJS_Date; -class CJS_Document; -class CJS_Object; -class CJS_Runtime; - -class CJS_Value { - public: - enum Type { - VT_unknown, - VT_string, - VT_number, - VT_boolean, - VT_date, - VT_object, - VT_null, - VT_undefined - }; - - explicit CJS_Value(CJS_Runtime* pRuntime); - CJS_Value(CJS_Runtime* pRuntime, v8::Local pValue); - CJS_Value(CJS_Runtime* pRuntime, const int& iValue); - CJS_Value(CJS_Runtime* pRuntime, const double& dValue); - CJS_Value(CJS_Runtime* pRuntime, const float& fValue); - CJS_Value(CJS_Runtime* pRuntime, const bool& bValue); - CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pObj); - CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr); - CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr); - CJS_Value(CJS_Runtime* pRuntime, const CJS_Array& array); - CJS_Value(CJS_Runtime* pRuntime, const CJS_Date& date); - CJS_Value(CJS_Runtime* pRuntime, const CJS_Object* object); - CJS_Value(const CJS_Value& other); - - ~CJS_Value(); - - void SetNull(CJS_Runtime* pRuntime); - void SetValue(const CJS_Value& other); - void Attach(v8::Local pValue); - void Detach(); - - static Type GetValueType(v8::Local value); - Type GetType() const { return GetValueType(m_pValue); } - - int ToInt(CJS_Runtime* pRuntime) const; - bool ToBool(CJS_Runtime* pRuntime) const; - double ToDouble(CJS_Runtime* pRuntime) const; - float ToFloat(CJS_Runtime* pRuntime) const; - CJS_Object* ToCJSObject(CJS_Runtime* pRuntime) const; - CFX_WideString ToCFXWideString(CJS_Runtime* pRuntime) const; - CFX_ByteString ToCFXByteString(CJS_Runtime* pRuntime) const; - v8::Local ToV8Object(CJS_Runtime* pRuntime) const; - v8::Local ToV8Array(CJS_Runtime* pRuntime) const; - v8::Local ToV8Value(CJS_Runtime* pRuntime) const; - - // Replace the current |m_pValue| with a v8::Number if possible - // to make one from the current |m_pValue|. - void MaybeCoerceToNumber(CJS_Runtime* pRuntime); - - bool IsArrayObject() const; - bool IsDateObject() const; - bool ConvertToArray(CJS_Runtime* pRuntime, CJS_Array&) const; - bool ConvertToDate(CJS_Runtime* pRuntime, CJS_Date&) const; - - protected: - v8::Local m_pValue; -}; - -class CJS_PropValue { - public: - explicit CJS_PropValue(CJS_Runtime* pRuntime); - CJS_PropValue(CJS_Runtime* pRuntime, const CJS_Value&); - ~CJS_PropValue(); - - void StartSetting() { m_bIsSetting = true; } - void StartGetting() { m_bIsSetting = false; } - bool IsSetting() const { return m_bIsSetting; } - bool IsGetting() const { return !m_bIsSetting; } - CJS_Runtime* GetJSRuntime() const { return m_pJSRuntime; } - CJS_Value* GetJSValue() { return &m_Value; } - - // These calls may re-enter JS (and hence invalidate objects). - void operator<<(int val); - void operator>>(int&) const; - void operator<<(bool val); - void operator>>(bool&) const; - void operator<<(double val); - void operator>>(double&) const; - void operator<<(CJS_Object* pObj); - void operator>>(CJS_Object*& ppObj) const; - void operator<<(CJS_Document* pJsDoc); - void operator>>(CJS_Document*& ppJsDoc) const; - void operator<<(CFX_ByteString); - void operator>>(CFX_ByteString&) const; - void operator<<(CFX_WideString); - void operator>>(CFX_WideString&) const; - void operator<<(const FX_WCHAR* c_string); - void operator<<(v8::Local); - void operator>>(v8::Local&) const; - void operator>>(CJS_Array& array) const; - void operator<<(CJS_Array& array); - void operator<<(CJS_Date& date); - void operator>>(CJS_Date& date) const; - - private: - bool m_bIsSetting; - CJS_Value m_Value; - CJS_Runtime* const m_pJSRuntime; -}; - -class CJS_Array { - public: - CJS_Array(); - CJS_Array(const CJS_Array& other); - virtual ~CJS_Array(); - - void Attach(v8::Local pArray); - int GetLength(CJS_Runtime* pRuntime) const; - - // These two calls may re-enter JS (and hence invalidate objects). - void GetElement(CJS_Runtime* pRuntime, - unsigned index, - CJS_Value& value) const; - void SetElement(CJS_Runtime* pRuntime, - unsigned index, - const CJS_Value& value); - - v8::Local ToV8Array(CJS_Runtime* pRuntime) const; - - private: - mutable v8::Local m_pArray; -}; - -class CJS_Date { - public: - CJS_Date(); - CJS_Date(CJS_Runtime* pRuntime, double dMsec_time); - CJS_Date(CJS_Runtime* pRuntime, - int year, - int mon, - int day, - int hour, - int min, - int sec); - virtual ~CJS_Date(); - - void Attach(v8::Local pDate); - bool IsValidDate(CJS_Runtime* pRuntime) const; - - int GetYear(CJS_Runtime* pRuntime) const; - void SetYear(CJS_Runtime* pRuntime, int iYear); - - int GetMonth(CJS_Runtime* pRuntime) const; - void SetMonth(CJS_Runtime* pRuntime, int iMonth); - - int GetDay(CJS_Runtime* pRuntime) const; - void SetDay(CJS_Runtime* pRuntime, int iDay); - - int GetHours(CJS_Runtime* pRuntime) const; - void SetHours(CJS_Runtime* pRuntime, int iHours); - - int GetMinutes(CJS_Runtime* pRuntime) const; - void SetMinutes(CJS_Runtime* pRuntime, int minutes); - - int GetSeconds(CJS_Runtime* pRuntime) const; - void SetSeconds(CJS_Runtime* pRuntime, int seconds); - - v8::Local ToV8Date(CJS_Runtime* pRuntime) const; - double ToDouble(CJS_Runtime* pRuntime) const; - CFX_WideString ToString(CJS_Runtime* pRuntime) const; - - protected: - v8::Local m_pDate; -}; - -double JS_GetDateTime(); -int JS_GetYearFromTime(double dt); -int JS_GetMonthFromTime(double dt); -int JS_GetDayFromTime(double dt); -int JS_GetHourFromTime(double dt); -int JS_GetMinFromTime(double dt); -int JS_GetSecFromTime(double dt); -double JS_DateParse(const CFX_WideString& str); -double JS_MakeDay(int nYear, int nMonth, int nDay); -double JS_MakeTime(int nHour, int nMin, int nSec, int nMs); -double JS_MakeDate(double day, double time); -bool JS_PortIsNan(double d); -double JS_LocalTime(double d); - -// Some JS methods have the bizarre convention that they may also be called -// with a single argument which is an object containing the actual arguments -// as its properties. The varying arguments to this method are the property -// names as wchar_t string literals corresponding to each positional argument. -// The result will always contain |nKeywords| value, with unspecified ones -// being set to type VT_unknown. -std::vector JS_ExpandKeywordParams( - CJS_Runtime* pRuntime, - const std::vector& originals, - size_t nKeywords, - ...); - -#endif // FPDFSDK_JAVASCRIPT_JS_VALUE_H_ diff --git a/fpdfsdk/javascript/PublicMethods.cpp b/fpdfsdk/javascript/PublicMethods.cpp deleted file mode 100644 index 3bcbc341acf2b0b183135a25e95da67025c55e59..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/PublicMethods.cpp +++ /dev/null @@ -1,1801 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/PublicMethods.h" - -#include -#include -#include -#include -#include -#include - -#include "core/fpdfdoc/cpdf_interform.h" -#include "core/fxcrt/fx_ext.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/cpdfsdk_interform.h" -#include "fpdfsdk/javascript/Field.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/color.h" -#include "fpdfsdk/javascript/resource.h" -#include "fpdfsdk/javascript/util.h" - -#define DOUBLE_CORRECT 0.000000000000001 - -JSMethodSpec CJS_PublicMethods::GlobalFunctionSpecs[] = { - {"AFNumber_Format", AFNumber_Format_static}, - {"AFNumber_Keystroke", AFNumber_Keystroke_static}, - {"AFPercent_Format", AFPercent_Format_static}, - {"AFPercent_Keystroke", AFPercent_Keystroke_static}, - {"AFDate_FormatEx", AFDate_FormatEx_static}, - {"AFDate_KeystrokeEx", AFDate_KeystrokeEx_static}, - {"AFDate_Format", AFDate_Format_static}, - {"AFDate_Keystroke", AFDate_Keystroke_static}, - {"AFTime_FormatEx", AFTime_FormatEx_static}, - {"AFTime_KeystrokeEx", AFTime_KeystrokeEx_static}, - {"AFTime_Format", AFTime_Format_static}, - {"AFTime_Keystroke", AFTime_Keystroke_static}, - {"AFSpecial_Format", AFSpecial_Format_static}, - {"AFSpecial_Keystroke", AFSpecial_Keystroke_static}, - {"AFSpecial_KeystrokeEx", AFSpecial_KeystrokeEx_static}, - {"AFSimple", AFSimple_static}, - {"AFMakeNumber", AFMakeNumber_static}, - {"AFSimple_Calculate", AFSimple_Calculate_static}, - {"AFRange_Validate", AFRange_Validate_static}, - {"AFMergeChange", AFMergeChange_static}, - {"AFParseDateEx", AFParseDateEx_static}, - {"AFExtractNums", AFExtractNums_static}, - {0, 0}}; - -IMPLEMENT_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods) - -namespace { - -const FX_WCHAR* const months[] = {L"Jan", L"Feb", L"Mar", L"Apr", - L"May", L"Jun", L"Jul", L"Aug", - L"Sep", L"Oct", L"Nov", L"Dec"}; - -const FX_WCHAR* const fullmonths[] = {L"January", L"February", L"March", - L"April", L"May", L"June", - L"July", L"August", L"September", - L"October", L"November", L"December"}; - -CFX_ByteString StrTrim(const CFX_ByteString& pStr) { - CFX_ByteString result(pStr); - result.TrimLeft(' '); - result.TrimRight(' '); - return result; -} - -CFX_WideString StrTrim(const CFX_WideString& pStr) { - CFX_WideString result(pStr); - result.TrimLeft(' '); - result.TrimRight(' '); - return result; -} - -void AlertIfPossible(CJS_EventContext* pContext, const FX_WCHAR* swMsg) { - CPDFSDK_FormFillEnvironment* pFormFillEnv = pContext->GetFormFillEnv(); - if (pFormFillEnv) - pFormFillEnv->JS_appAlert(swMsg, nullptr, 0, 3); -} - -#if _FX_OS_ != _FX_ANDROID_ -CFX_ByteString CalculateString(double dValue, - int iDec, - int* iDec2, - bool* bNegative) { - *bNegative = dValue < 0; - if (*bNegative) - dValue = -dValue; - - // Make sure the number of precision characters will fit. - if (iDec > std::numeric_limits::digits10) - iDec = std::numeric_limits::digits10; - - std::stringstream ss; - ss << std::fixed << std::setprecision(iDec) << dValue; - std::string stringValue = ss.str(); - size_t iDecimalPos = stringValue.find("."); - *iDec2 = iDecimalPos == std::string::npos ? stringValue.size() - : static_cast(iDecimalPos); - return CFX_ByteString(stringValue.c_str()); -} -#endif - -} // namespace - -bool CJS_PublicMethods::IsNumber(const CFX_WideString& str) { - CFX_WideString sTrim = StrTrim(str); - const FX_WCHAR* pTrim = sTrim.c_str(); - const FX_WCHAR* p = pTrim; - bool bDot = false; - bool bKXJS = false; - - wchar_t c; - while ((c = *p) != L'\0') { - if (c == L'.' || c == L',') { - if (bDot) - return false; - bDot = true; - } else if (c == L'-' || c == L'+') { - if (p != pTrim) - return false; - } else if (c == L'e' || c == L'E') { - if (bKXJS) - return false; - - p++; - c = *p; - if (c == L'+' || c == L'-') { - bKXJS = true; - } else { - return false; - } - } else if (!FXSYS_iswdigit(c)) { - return false; - } - p++; - } - - return true; -} - -bool CJS_PublicMethods::maskSatisfied(wchar_t c_Change, wchar_t c_Mask) { - switch (c_Mask) { - case L'9': - return FXSYS_iswdigit(c_Change); - case L'A': - return FXSYS_iswalpha(c_Change); - case L'O': - return FXSYS_iswalnum(c_Change); - case L'X': - return true; - default: - return (c_Change == c_Mask); - } -} - -bool CJS_PublicMethods::isReservedMaskChar(wchar_t ch) { - return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X'; -} - -double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction, - double dValue1, - double dValue2) { - if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 || - FXSYS_wcsicmp(sFuction, L"SUM") == 0) { - return dValue1 + dValue2; - } - if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) { - return dValue1 * dValue2; - } - if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) { - return std::min(dValue1, dValue2); - } - if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) { - return std::max(dValue1, dValue2); - } - return dValue1; -} - -CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime, - CJS_Value val) { - CJS_Array StrArray; - if (val.IsArrayObject()) { - val.ConvertToArray(pRuntime, StrArray); - return StrArray; - } - CFX_WideString wsStr = val.ToCFXWideString(pRuntime); - CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr); - const char* p = t.c_str(); - - int ch = ','; - int nIndex = 0; - - while (*p) { - const char* pTemp = strchr(p, ch); - if (!pTemp) { - StrArray.SetElement( - pRuntime, nIndex, - CJS_Value(pRuntime, StrTrim(CFX_ByteString(p)).c_str())); - break; - } - - char* pSub = new char[pTemp - p + 1]; - strncpy(pSub, p, pTemp - p); - *(pSub + (pTemp - p)) = '\0'; - - StrArray.SetElement( - pRuntime, nIndex, - CJS_Value(pRuntime, StrTrim(CFX_ByteString(pSub)).c_str())); - delete[] pSub; - - nIndex++; - p = ++pTemp; - } - return StrArray; -} - -int CJS_PublicMethods::ParseStringInteger(const CFX_WideString& str, - int nStart, - int& nSkip, - int nMaxStep) { - int nRet = 0; - nSkip = 0; - for (int i = nStart, sz = str.GetLength(); i < sz; i++) { - if (i - nStart > 10) - break; - - FX_WCHAR c = str.GetAt(i); - if (!FXSYS_iswdigit(c)) - break; - - nRet = nRet * 10 + FXSYS_toDecimalDigit(c); - nSkip = i - nStart + 1; - if (nSkip >= nMaxStep) - break; - } - - return nRet; -} - -CFX_WideString CJS_PublicMethods::ParseStringString(const CFX_WideString& str, - int nStart, - int& nSkip) { - CFX_WideString swRet; - nSkip = 0; - for (int i = nStart, sz = str.GetLength(); i < sz; i++) { - FX_WCHAR c = str.GetAt(i); - if (!FXSYS_iswdigit(c)) - break; - - swRet += c; - nSkip = i - nStart + 1; - } - - return swRet; -} - -double CJS_PublicMethods::ParseNormalDate(const CFX_WideString& value, - bool* bWrongFormat) { - double dt = JS_GetDateTime(); - - int nYear = JS_GetYearFromTime(dt); - int nMonth = JS_GetMonthFromTime(dt) + 1; - int nDay = JS_GetDayFromTime(dt); - int nHour = JS_GetHourFromTime(dt); - int nMin = JS_GetMinFromTime(dt); - int nSec = JS_GetSecFromTime(dt); - - int number[3]; - - int nSkip = 0; - int nLen = value.GetLength(); - int nIndex = 0; - int i = 0; - while (i < nLen) { - if (nIndex > 2) - break; - - FX_WCHAR c = value.GetAt(i); - if (FXSYS_iswdigit(c)) { - number[nIndex++] = ParseStringInteger(value, i, nSkip, 4); - i += nSkip; - } else { - i++; - } - } - - if (nIndex == 2) { - // case2: month/day - // case3: day/month - if ((number[0] >= 1 && number[0] <= 12) && - (number[1] >= 1 && number[1] <= 31)) { - nMonth = number[0]; - nDay = number[1]; - } else if ((number[0] >= 1 && number[0] <= 31) && - (number[1] >= 1 && number[1] <= 12)) { - nDay = number[0]; - nMonth = number[1]; - } - - if (bWrongFormat) - *bWrongFormat = false; - } else if (nIndex == 3) { - // case1: year/month/day - // case2: month/day/year - // case3: day/month/year - - if (number[0] > 12 && (number[1] >= 1 && number[1] <= 12) && - (number[2] >= 1 && number[2] <= 31)) { - nYear = number[0]; - nMonth = number[1]; - nDay = number[2]; - } else if ((number[0] >= 1 && number[0] <= 12) && - (number[1] >= 1 && number[1] <= 31) && number[2] > 31) { - nMonth = number[0]; - nDay = number[1]; - nYear = number[2]; - } else if ((number[0] >= 1 && number[0] <= 31) && - (number[1] >= 1 && number[1] <= 12) && number[2] > 31) { - nDay = number[0]; - nMonth = number[1]; - nYear = number[2]; - } - - if (bWrongFormat) - *bWrongFormat = false; - } else { - if (bWrongFormat) - *bWrongFormat = true; - return dt; - } - - CFX_WideString swTemp; - swTemp.Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, nYear, nHour, nMin, nSec); - return JS_DateParse(swTemp); -} - -double CJS_PublicMethods::MakeRegularDate(const CFX_WideString& value, - const CFX_WideString& format, - bool* bWrongFormat) { - double dt = JS_GetDateTime(); - - if (format.IsEmpty() || value.IsEmpty()) - return dt; - - int nYear = JS_GetYearFromTime(dt); - int nMonth = JS_GetMonthFromTime(dt) + 1; - int nDay = JS_GetDayFromTime(dt); - int nHour = JS_GetHourFromTime(dt); - int nMin = JS_GetMinFromTime(dt); - int nSec = JS_GetSecFromTime(dt); - - int nYearSub = 99; // nYear - 2000; - - bool bPm = false; - bool bExit = false; - bool bBadFormat = false; - - int i = 0; - int j = 0; - - while (i < format.GetLength()) { - if (bExit) - break; - - FX_WCHAR c = format.GetAt(i); - switch (c) { - case ':': - case '.': - case '-': - case '\\': - case '/': - i++; - j++; - break; - - case 'y': - case 'm': - case 'd': - case 'H': - case 'h': - case 'M': - case 's': - case 't': { - int oldj = j; - int nSkip = 0; - int remaining = format.GetLength() - i - 1; - - if (remaining == 0 || format.GetAt(i + 1) != c) { - switch (c) { - case 'y': - i++; - j++; - break; - case 'm': - nMonth = ParseStringInteger(value, j, nSkip, 2); - i++; - j += nSkip; - break; - case 'd': - nDay = ParseStringInteger(value, j, nSkip, 2); - i++; - j += nSkip; - break; - case 'H': - nHour = ParseStringInteger(value, j, nSkip, 2); - i++; - j += nSkip; - break; - case 'h': - nHour = ParseStringInteger(value, j, nSkip, 2); - i++; - j += nSkip; - break; - case 'M': - nMin = ParseStringInteger(value, j, nSkip, 2); - i++; - j += nSkip; - break; - case 's': - nSec = ParseStringInteger(value, j, nSkip, 2); - i++; - j += nSkip; - break; - case 't': - bPm = (j < value.GetLength() && value.GetAt(j) == 'p'); - i++; - j++; - break; - } - } else if (remaining == 1 || format.GetAt(i + 2) != c) { - switch (c) { - case 'y': - nYear = ParseStringInteger(value, j, nSkip, 4); - i += 2; - j += nSkip; - break; - case 'm': - nMonth = ParseStringInteger(value, j, nSkip, 2); - i += 2; - j += nSkip; - break; - case 'd': - nDay = ParseStringInteger(value, j, nSkip, 2); - i += 2; - j += nSkip; - break; - case 'H': - nHour = ParseStringInteger(value, j, nSkip, 2); - i += 2; - j += nSkip; - break; - case 'h': - nHour = ParseStringInteger(value, j, nSkip, 2); - i += 2; - j += nSkip; - break; - case 'M': - nMin = ParseStringInteger(value, j, nSkip, 2); - i += 2; - j += nSkip; - break; - case 's': - nSec = ParseStringInteger(value, j, nSkip, 2); - i += 2; - j += nSkip; - break; - case 't': - bPm = (j + 1 < value.GetLength() && value.GetAt(j) == 'p' && - value.GetAt(j + 1) == 'm'); - i += 2; - j += 2; - break; - } - } else if (remaining == 2 || format.GetAt(i + 3) != c) { - switch (c) { - case 'm': { - CFX_WideString sMonth = ParseStringString(value, j, nSkip); - bool bFind = false; - for (int m = 0; m < 12; m++) { - if (sMonth.CompareNoCase(months[m]) == 0) { - nMonth = m + 1; - i += 3; - j += nSkip; - bFind = true; - break; - } - } - - if (!bFind) { - nMonth = ParseStringInteger(value, j, nSkip, 3); - i += 3; - j += nSkip; - } - } break; - case 'y': - break; - default: - i += 3; - j += 3; - break; - } - } else if (remaining == 3 || format.GetAt(i + 4) != c) { - switch (c) { - case 'y': - nYear = ParseStringInteger(value, j, nSkip, 4); - j += nSkip; - i += 4; - break; - case 'm': { - bool bFind = false; - - CFX_WideString sMonth = ParseStringString(value, j, nSkip); - sMonth.MakeLower(); - - for (int m = 0; m < 12; m++) { - CFX_WideString sFullMonths = fullmonths[m]; - sFullMonths.MakeLower(); - - if (sFullMonths.Find(sMonth.c_str(), 0) != -1) { - nMonth = m + 1; - i += 4; - j += nSkip; - bFind = true; - break; - } - } - - if (!bFind) { - nMonth = ParseStringInteger(value, j, nSkip, 4); - i += 4; - j += nSkip; - } - } break; - default: - i += 4; - j += 4; - break; - } - } else { - if (j >= value.GetLength() || format.GetAt(i) != value.GetAt(j)) { - bBadFormat = true; - bExit = true; - } - i++; - j++; - } - - if (oldj == j) { - bBadFormat = true; - bExit = true; - } - } - - break; - default: - if (value.GetLength() <= j) { - bExit = true; - } else if (format.GetAt(i) != value.GetAt(j)) { - bBadFormat = true; - bExit = true; - } - - i++; - j++; - break; - } - } - - if (bPm) - nHour += 12; - - if (nYear >= 0 && nYear <= nYearSub) - nYear += 2000; - - if (nMonth < 1 || nMonth > 12) - bBadFormat = true; - - if (nDay < 1 || nDay > 31) - bBadFormat = true; - - if (nHour < 0 || nHour > 24) - bBadFormat = true; - - if (nMin < 0 || nMin > 60) - bBadFormat = true; - - if (nSec < 0 || nSec > 60) - bBadFormat = true; - - double dRet = 0; - if (bBadFormat) { - dRet = ParseNormalDate(value, &bBadFormat); - } else { - dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay), - JS_MakeTime(nHour, nMin, nSec, 0)); - if (JS_PortIsNan(dRet)) - dRet = JS_DateParse(value); - } - - if (JS_PortIsNan(dRet)) - dRet = ParseNormalDate(value, &bBadFormat); - - if (bWrongFormat) - *bWrongFormat = bBadFormat; - - return dRet; -} - -CFX_WideString CJS_PublicMethods::MakeFormatDate(double dDate, - const CFX_WideString& format) { - CFX_WideString sRet = L"", sPart = L""; - - int nYear = JS_GetYearFromTime(dDate); - int nMonth = JS_GetMonthFromTime(dDate) + 1; - int nDay = JS_GetDayFromTime(dDate); - int nHour = JS_GetHourFromTime(dDate); - int nMin = JS_GetMinFromTime(dDate); - int nSec = JS_GetSecFromTime(dDate); - - int i = 0; - while (i < format.GetLength()) { - FX_WCHAR c = format.GetAt(i); - int remaining = format.GetLength() - i - 1; - sPart = L""; - switch (c) { - case 'y': - case 'm': - case 'd': - case 'H': - case 'h': - case 'M': - case 's': - case 't': - if (remaining == 0 || format.GetAt(i + 1) != c) { - switch (c) { - case 'y': - sPart += c; - break; - case 'm': - sPart.Format(L"%d", nMonth); - break; - case 'd': - sPart.Format(L"%d", nDay); - break; - case 'H': - sPart.Format(L"%d", nHour); - break; - case 'h': - sPart.Format(L"%d", nHour > 12 ? nHour - 12 : nHour); - break; - case 'M': - sPart.Format(L"%d", nMin); - break; - case 's': - sPart.Format(L"%d", nSec); - break; - case 't': - sPart += nHour > 12 ? 'p' : 'a'; - break; - } - i++; - } else if (remaining == 1 || format.GetAt(i + 2) != c) { - switch (c) { - case 'y': - sPart.Format(L"%02d", nYear - (nYear / 100) * 100); - break; - case 'm': - sPart.Format(L"%02d", nMonth); - break; - case 'd': - sPart.Format(L"%02d", nDay); - break; - case 'H': - sPart.Format(L"%02d", nHour); - break; - case 'h': - sPart.Format(L"%02d", nHour > 12 ? nHour - 12 : nHour); - break; - case 'M': - sPart.Format(L"%02d", nMin); - break; - case 's': - sPart.Format(L"%02d", nSec); - break; - case 't': - sPart = nHour > 12 ? L"pm" : L"am"; - break; - } - i += 2; - } else if (remaining == 2 || format.GetAt(i + 3) != c) { - switch (c) { - case 'm': - i += 3; - if (nMonth > 0 && nMonth <= 12) - sPart += months[nMonth - 1]; - break; - default: - i += 3; - sPart += c; - sPart += c; - sPart += c; - break; - } - } else if (remaining == 3 || format.GetAt(i + 4) != c) { - switch (c) { - case 'y': - sPart.Format(L"%04d", nYear); - i += 4; - break; - case 'm': - i += 4; - if (nMonth > 0 && nMonth <= 12) - sPart += fullmonths[nMonth - 1]; - break; - default: - i += 4; - sPart += c; - sPart += c; - sPart += c; - sPart += c; - break; - } - } else { - i++; - sPart += c; - } - break; - default: - i++; - sPart += c; - break; - } - - sRet += sPart; - } - - return sRet; -} - -// function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency, -// bCurrencyPrepend) -bool CJS_PublicMethods::AFNumber_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { -#if _FX_OS_ != _FX_ANDROID_ - if (params.size() != 6) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - CFX_WideString& Value = pEvent->Value(); - CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value)); - if (strValue.IsEmpty()) - return true; - - int iDec = params[0].ToInt(pRuntime); - int iSepStyle = params[1].ToInt(pRuntime); - int iNegStyle = params[2].ToInt(pRuntime); - // params[3] is iCurrStyle, it's not used. - CFX_WideString wstrCurrency = params[4].ToCFXWideString(pRuntime); - bool bCurrencyPrepend = params[5].ToBool(pRuntime); - - if (iDec < 0) - iDec = -iDec; - - if (iSepStyle < 0 || iSepStyle > 3) - iSepStyle = 0; - - if (iNegStyle < 0 || iNegStyle > 3) - iNegStyle = 0; - - // Processing decimal places - strValue.Replace(",", "."); - double dValue = atof(strValue.c_str()); - if (iDec > 0) - dValue += DOUBLE_CORRECT; - - // Calculating number string - bool bNegative; - int iDec2; - strValue = CalculateString(dValue, iDec, &iDec2, &bNegative); - if (strValue.IsEmpty()) { - dValue = 0; - strValue = CalculateString(dValue, iDec, &iDec2, &bNegative); - if (strValue.IsEmpty()) { - strValue = "0"; - iDec2 = 1; - } - } - - // Processing separator style - if (iDec2 < strValue.GetLength()) { - if (iSepStyle == 2 || iSepStyle == 3) - strValue.Replace(".", ","); - - if (iDec2 == 0) - strValue.Insert(iDec2, '0'); - } - if (iSepStyle == 0 || iSepStyle == 2) { - char cSeparator; - if (iSepStyle == 0) - cSeparator = ','; - else - cSeparator = '.'; - - for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) - strValue.Insert(iDecPositive, cSeparator); - } - - // Processing currency string - Value = CFX_WideString::FromLocal(strValue.AsStringC()); - - if (bCurrencyPrepend) - Value = wstrCurrency + Value; - else - Value = Value + wstrCurrency; - - // Processing negative style - if (bNegative) { - if (iNegStyle == 0) - Value = L"-" + Value; - else if (iNegStyle == 2 || iNegStyle == 3) - Value = L"(" + Value + L")"; - if (iNegStyle == 1 || iNegStyle == 3) { - if (Field* fTarget = pEvent->Target_Field()) { - CJS_Array arColor; - CJS_Value vColElm(pRuntime); - vColElm = CJS_Value(pRuntime, L"RGB"); - arColor.SetElement(pRuntime, 0, vColElm); - vColElm = CJS_Value(pRuntime, 1); - arColor.SetElement(pRuntime, 1, vColElm); - vColElm = CJS_Value(pRuntime, 0); - arColor.SetElement(pRuntime, 2, vColElm); - arColor.SetElement(pRuntime, 3, vColElm); - - CJS_PropValue vProp(pRuntime); - vProp.StartGetting(); - vProp << arColor; - vProp.StartSetting(); - fTarget->textColor(pRuntime, vProp, sError); // red - } - } - } else { - if (iNegStyle == 1 || iNegStyle == 3) { - if (Field* fTarget = pEvent->Target_Field()) { - CJS_Array arColor; - CJS_Value vColElm(pRuntime); - vColElm = CJS_Value(pRuntime, L"RGB"); - arColor.SetElement(pRuntime, 0, vColElm); - vColElm = CJS_Value(pRuntime, 0); - arColor.SetElement(pRuntime, 1, vColElm); - arColor.SetElement(pRuntime, 2, vColElm); - arColor.SetElement(pRuntime, 3, vColElm); - - CJS_PropValue vProp(pRuntime); - vProp.StartGetting(); - fTarget->textColor(pRuntime, vProp, sError); - - CJS_Array aProp; - vProp.GetJSValue()->ConvertToArray(pRuntime, aProp); - - CPWL_Color crProp; - CPWL_Color crColor; - color::ConvertArrayToPWLColor(pRuntime, aProp, &crProp); - color::ConvertArrayToPWLColor(pRuntime, arColor, &crColor); - - if (crColor != crProp) { - CJS_PropValue vProp2(pRuntime); - vProp2.StartGetting(); - vProp2 << arColor; - vProp2.StartSetting(); - fTarget->textColor(pRuntime, vProp2, sError); - } - } - } - } -#endif - return true; -} - -// function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency, -// bCurrencyPrepend) -bool CJS_PublicMethods::AFNumber_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 2) - return false; - - CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); - CJS_EventHandler* pEvent = pContext->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - CFX_WideString& val = pEvent->Value(); - CFX_WideString& wstrChange = pEvent->Change(); - CFX_WideString wstrValue = val; - - if (pEvent->WillCommit()) { - CFX_WideString swTemp = StrTrim(wstrValue); - if (swTemp.IsEmpty()) - return true; - - swTemp.Replace(L",", L"."); - if (!IsNumber(swTemp.c_str())) { - pEvent->Rc() = false; - sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE); - AlertIfPossible(pContext, sError.c_str()); - } - return true; // it happens after the last keystroke and before validating, - } - - CFX_WideString wstrSelected; - if (pEvent->SelStart() != -1) { - wstrSelected = wstrValue.Mid(pEvent->SelStart(), - pEvent->SelEnd() - pEvent->SelStart()); - } - - bool bHasSign = wstrValue.Find(L'-') != -1 && wstrSelected.Find(L'-') == -1; - if (bHasSign) { - // can't insert "change" in front to sign postion. - if (pEvent->SelStart() == 0) { - bool& bRc = pEvent->Rc(); - bRc = false; - return true; - } - } - - int iSepStyle = params[1].ToInt(pRuntime); - if (iSepStyle < 0 || iSepStyle > 3) - iSepStyle = 0; - const FX_WCHAR cSep = iSepStyle < 2 ? L'.' : L','; - - bool bHasSep = wstrValue.Find(cSep) != -1; - for (FX_STRSIZE i = 0; i < wstrChange.GetLength(); ++i) { - if (wstrChange[i] == cSep) { - if (bHasSep) { - bool& bRc = pEvent->Rc(); - bRc = false; - return true; - } - bHasSep = true; - continue; - } - if (wstrChange[i] == L'-') { - if (bHasSign) { - bool& bRc = pEvent->Rc(); - bRc = false; - return true; - } - // sign's position is not correct - if (i != 0) { - bool& bRc = pEvent->Rc(); - bRc = false; - return true; - } - if (pEvent->SelStart() != 0) { - bool& bRc = pEvent->Rc(); - bRc = false; - return true; - } - bHasSign = true; - continue; - } - - if (!FXSYS_iswdigit(wstrChange[i])) { - bool& bRc = pEvent->Rc(); - bRc = false; - return true; - } - } - - CFX_WideString wprefix = wstrValue.Mid(0, pEvent->SelStart()); - CFX_WideString wpostfix; - if (pEvent->SelEnd() < wstrValue.GetLength()) - wpostfix = wstrValue.Mid(pEvent->SelEnd()); - val = wprefix + wstrChange + wpostfix; - return true; -} - -// function AFPercent_Format(nDec, sepStyle) -bool CJS_PublicMethods::AFPercent_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { -#if _FX_OS_ != _FX_ANDROID_ - if (params.size() != 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - CFX_WideString& Value = pEvent->Value(); - CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value)); - if (strValue.IsEmpty()) - return true; - - int iDec = params[0].ToInt(pRuntime); - if (iDec < 0) - iDec = -iDec; - - int iSepStyle = params[1].ToInt(pRuntime); - if (iSepStyle < 0 || iSepStyle > 3) - iSepStyle = 0; - - // for processing decimal places - double dValue = atof(strValue.c_str()); - dValue *= 100; - if (iDec > 0) - dValue += DOUBLE_CORRECT; - - int iDec2; - int iNegative = 0; - strValue = fcvt(dValue, iDec, &iDec2, &iNegative); - if (strValue.IsEmpty()) { - dValue = 0; - strValue = fcvt(dValue, iDec, &iDec2, &iNegative); - } - - if (iDec2 < 0) { - for (int iNum = 0; iNum < abs(iDec2); iNum++) { - strValue = "0" + strValue; - } - iDec2 = 0; - } - int iMax = strValue.GetLength(); - if (iDec2 > iMax) { - for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) { - strValue += "0"; - } - iMax = iDec2 + 1; - } - - // for processing seperator style - if (iDec2 < iMax) { - if (iSepStyle == 0 || iSepStyle == 1) { - strValue.Insert(iDec2, '.'); - iMax++; - } else if (iSepStyle == 2 || iSepStyle == 3) { - strValue.Insert(iDec2, ','); - iMax++; - } - - if (iDec2 == 0) - strValue.Insert(iDec2, '0'); - } - if (iSepStyle == 0 || iSepStyle == 2) { - char cSeperator; - if (iSepStyle == 0) - cSeperator = ','; - else - cSeperator = '.'; - - for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) { - strValue.Insert(iDecPositive, cSeperator); - iMax++; - } - } - - // negative mark - if (iNegative) - strValue = "-" + strValue; - strValue += "%"; - Value = CFX_WideString::FromLocal(strValue.AsStringC()); -#endif - return true; -} -// AFPercent_Keystroke(nDec, sepStyle) -bool CJS_PublicMethods::AFPercent_Keystroke( - CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return AFNumber_Keystroke(pRuntime, params, vRet, sError); -} - -// function AFDate_FormatEx(cFormat) -bool CJS_PublicMethods::AFDate_FormatEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); - CJS_EventHandler* pEvent = pContext->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - CFX_WideString& val = pEvent->Value(); - CFX_WideString strValue = val; - if (strValue.IsEmpty()) - return true; - - CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime); - double dDate = 0.0f; - - if (strValue.Find(L"GMT") != -1) { - // for GMT format time - // such as "Tue Aug 11 14:24:16 GMT+08002009" - dDate = MakeInterDate(strValue); - } else { - dDate = MakeRegularDate(strValue, sFormat, nullptr); - } - - if (JS_PortIsNan(dDate)) { - CFX_WideString swMsg; - swMsg.Format(JSGetStringFromID(IDS_STRING_JSPARSEDATE).c_str(), - sFormat.c_str()); - AlertIfPossible(pContext, swMsg.c_str()); - return false; - } - - val = MakeFormatDate(dDate, sFormat); - return true; -} - -double CJS_PublicMethods::MakeInterDate(const CFX_WideString& strValue) { - std::vector wsArray; - CFX_WideString sTemp = L""; - for (int i = 0; i < strValue.GetLength(); ++i) { - FX_WCHAR c = strValue.GetAt(i); - if (c == L' ' || c == L':') { - wsArray.push_back(sTemp); - sTemp = L""; - continue; - } - sTemp += c; - } - wsArray.push_back(sTemp); - if (wsArray.size() != 8) - return 0; - - int nMonth = 1; - sTemp = wsArray[1]; - if (sTemp.Compare(L"Jan") == 0) - nMonth = 1; - else if (sTemp.Compare(L"Feb") == 0) - nMonth = 2; - else if (sTemp.Compare(L"Mar") == 0) - nMonth = 3; - else if (sTemp.Compare(L"Apr") == 0) - nMonth = 4; - else if (sTemp.Compare(L"May") == 0) - nMonth = 5; - else if (sTemp.Compare(L"Jun") == 0) - nMonth = 6; - else if (sTemp.Compare(L"Jul") == 0) - nMonth = 7; - else if (sTemp.Compare(L"Aug") == 0) - nMonth = 8; - else if (sTemp.Compare(L"Sep") == 0) - nMonth = 9; - else if (sTemp.Compare(L"Oct") == 0) - nMonth = 10; - else if (sTemp.Compare(L"Nov") == 0) - nMonth = 11; - else if (sTemp.Compare(L"Dec") == 0) - nMonth = 12; - - int nDay = FX_atof(wsArray[2].AsStringC()); - int nHour = FX_atof(wsArray[3].AsStringC()); - int nMin = FX_atof(wsArray[4].AsStringC()); - int nSec = FX_atof(wsArray[5].AsStringC()); - int nYear = FX_atof(wsArray[7].AsStringC()); - double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay), - JS_MakeTime(nHour, nMin, nSec, 0)); - if (JS_PortIsNan(dRet)) - dRet = JS_DateParse(strValue); - - return dRet; -} - -// AFDate_KeystrokeEx(cFormat) -bool CJS_PublicMethods::AFDate_KeystrokeEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = L"AFDate_KeystrokeEx's parameters' size r not correct"; - return false; - } - - CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); - CJS_EventHandler* pEvent = pContext->GetEventHandler(); - if (pEvent->WillCommit()) { - if (!pEvent->m_pValue) - return false; - - CFX_WideString strValue = pEvent->Value(); - if (strValue.IsEmpty()) - return true; - - CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime); - bool bWrongFormat = false; - double dRet = MakeRegularDate(strValue, sFormat, &bWrongFormat); - if (bWrongFormat || JS_PortIsNan(dRet)) { - CFX_WideString swMsg; - swMsg.Format(JSGetStringFromID(IDS_STRING_JSPARSEDATE).c_str(), - sFormat.c_str()); - AlertIfPossible(pContext, swMsg.c_str()); - pEvent->Rc() = false; - return true; - } - } - return true; -} - -bool CJS_PublicMethods::AFDate_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - int iIndex = params[0].ToInt(pRuntime); - const FX_WCHAR* cFormats[] = {L"m/d", - L"m/d/yy", - L"mm/dd/yy", - L"mm/yy", - L"d-mmm", - L"d-mmm-yy", - L"dd-mmm-yy", - L"yy-mm-dd", - L"mmm-yy", - L"mmmm-yy", - L"mmm d, yyyy", - L"mmmm d, yyyy", - L"m/d/yy h:MM tt", - L"m/d/yy HH:MM"}; - - if (iIndex < 0 || (static_cast(iIndex) >= FX_ArraySize(cFormats))) - iIndex = 0; - - std::vector newParams; - newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex])); - return AFDate_FormatEx(pRuntime, newParams, vRet, sError); -} - -// AFDate_KeystrokeEx(cFormat) -bool CJS_PublicMethods::AFDate_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - int iIndex = params[0].ToInt(pRuntime); - const FX_WCHAR* cFormats[] = {L"m/d", - L"m/d/yy", - L"mm/dd/yy", - L"mm/yy", - L"d-mmm", - L"d-mmm-yy", - L"dd-mmm-yy", - L"yy-mm-dd", - L"mmm-yy", - L"mmmm-yy", - L"mmm d, yyyy", - L"mmmm d, yyyy", - L"m/d/yy h:MM tt", - L"m/d/yy HH:MM"}; - - if (iIndex < 0 || (static_cast(iIndex) >= FX_ArraySize(cFormats))) - iIndex = 0; - - std::vector newParams; - newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex])); - return AFDate_KeystrokeEx(pRuntime, newParams, vRet, sError); -} - -// function AFTime_Format(ptf) -bool CJS_PublicMethods::AFTime_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - int iIndex = params[0].ToInt(pRuntime); - const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss", - L"h:MM:ss tt"}; - - if (iIndex < 0 || (static_cast(iIndex) >= FX_ArraySize(cFormats))) - iIndex = 0; - - std::vector newParams; - newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex])); - return AFDate_FormatEx(pRuntime, newParams, vRet, sError); -} - -bool CJS_PublicMethods::AFTime_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - int iIndex = params[0].ToInt(pRuntime); - const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss", - L"h:MM:ss tt"}; - - if (iIndex < 0 || (static_cast(iIndex) >= FX_ArraySize(cFormats))) - iIndex = 0; - - std::vector newParams; - newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex])); - return AFDate_KeystrokeEx(pRuntime, newParams, vRet, sError); -} - -bool CJS_PublicMethods::AFTime_FormatEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return AFDate_FormatEx(pRuntime, params, vRet, sError); -} - -bool CJS_PublicMethods::AFTime_KeystrokeEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return AFDate_KeystrokeEx(pRuntime, params, vRet, sError); -} - -// function AFSpecial_Format(psf) -bool CJS_PublicMethods::AFSpecial_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - CFX_WideString wsSource = pEvent->Value(); - CFX_WideString wsFormat; - switch (params[0].ToInt(pRuntime)) { - case 0: - wsFormat = L"99999"; - break; - case 1: - wsFormat = L"99999-9999"; - break; - case 2: - if (util::printx(L"9999999999", wsSource).GetLength() >= 10) - wsFormat = L"(999) 999-9999"; - else - wsFormat = L"999-9999"; - break; - case 3: - wsFormat = L"999-99-9999"; - break; - } - - pEvent->Value() = util::printx(wsFormat, wsSource); - return true; -} - -// function AFSpecial_KeystrokeEx(mask) -bool CJS_PublicMethods::AFSpecial_KeystrokeEx( - CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); - CJS_EventHandler* pEvent = pContext->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - CFX_WideString& valEvent = pEvent->Value(); - CFX_WideString wstrMask = params[0].ToCFXWideString(pRuntime); - if (wstrMask.IsEmpty()) - return true; - - if (pEvent->WillCommit()) { - if (valEvent.IsEmpty()) - return true; - - FX_STRSIZE iIndexMask = 0; - for (; iIndexMask < valEvent.GetLength(); ++iIndexMask) { - if (!maskSatisfied(valEvent[iIndexMask], wstrMask[iIndexMask])) - break; - } - - if (iIndexMask != wstrMask.GetLength() || - (iIndexMask != valEvent.GetLength() && wstrMask.GetLength() != 0)) { - AlertIfPossible( - pContext, JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str()); - pEvent->Rc() = false; - } - return true; - } - - CFX_WideString& wideChange = pEvent->Change(); - if (wideChange.IsEmpty()) - return true; - - CFX_WideString wChange = wideChange; - FX_STRSIZE iIndexMask = pEvent->SelStart(); - FX_STRSIZE combined_len = valEvent.GetLength() + wChange.GetLength() + - pEvent->SelStart() - pEvent->SelEnd(); - if (combined_len > wstrMask.GetLength()) { - AlertIfPossible(pContext, - JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG).c_str()); - pEvent->Rc() = false; - return true; - } - - if (iIndexMask >= wstrMask.GetLength() && !wChange.IsEmpty()) { - AlertIfPossible(pContext, - JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG).c_str()); - pEvent->Rc() = false; - return true; - } - - for (FX_STRSIZE i = 0; i < wChange.GetLength(); ++i) { - if (iIndexMask >= wstrMask.GetLength()) { - AlertIfPossible(pContext, - JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG).c_str()); - pEvent->Rc() = false; - return true; - } - FX_WCHAR wMask = wstrMask[iIndexMask]; - if (!isReservedMaskChar(wMask)) - wChange.SetAt(i, wMask); - - if (!maskSatisfied(wChange[i], wMask)) { - pEvent->Rc() = false; - return true; - } - iIndexMask++; - } - wideChange = wChange; - return true; -} - -// function AFSpecial_Keystroke(psf) -bool CJS_PublicMethods::AFSpecial_Keystroke( - CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - const char* cFormat = ""; - switch (params[0].ToInt(pRuntime)) { - case 0: - cFormat = "99999"; - break; - case 1: - cFormat = "999999999"; - break; - case 2: - if (pEvent->Value().GetLength() + pEvent->Change().GetLength() > 7) - cFormat = "9999999999"; - else - cFormat = "9999999"; - break; - case 3: - cFormat = "999999999"; - break; - } - - std::vector params2; - params2.push_back(CJS_Value(pRuntime, cFormat)); - return AFSpecial_KeystrokeEx(pRuntime, params2, vRet, sError); -} - -bool CJS_PublicMethods::AFMergeChange(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_EventHandler* pEventHandler = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - CFX_WideString swValue; - if (pEventHandler->m_pValue) - swValue = pEventHandler->Value(); - - if (pEventHandler->WillCommit()) { - vRet = CJS_Value(pRuntime, swValue.c_str()); - return true; - } - - CFX_WideString prefix, postfix; - - if (pEventHandler->SelStart() >= 0) - prefix = swValue.Mid(0, pEventHandler->SelStart()); - else - prefix = L""; - - if (pEventHandler->SelEnd() >= 0 && - pEventHandler->SelEnd() <= swValue.GetLength()) - postfix = swValue.Mid(pEventHandler->SelEnd(), - swValue.GetLength() - pEventHandler->SelEnd()); - else - postfix = L""; - - vRet = - CJS_Value(pRuntime, (prefix + pEventHandler->Change() + postfix).c_str()); - return true; -} - -bool CJS_PublicMethods::AFParseDateEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString sValue = params[0].ToCFXWideString(pRuntime); - CFX_WideString sFormat = params[1].ToCFXWideString(pRuntime); - double dDate = MakeRegularDate(sValue, sFormat, nullptr); - if (JS_PortIsNan(dDate)) { - CFX_WideString swMsg; - swMsg.Format(JSGetStringFromID(IDS_STRING_JSPARSEDATE).c_str(), - sFormat.c_str()); - AlertIfPossible(pRuntime->GetCurrentEventContext(), swMsg.c_str()); - return false; - } - - vRet = CJS_Value(pRuntime, dDate); - return true; -} - -bool CJS_PublicMethods::AFSimple(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 3) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - vRet = CJS_Value(pRuntime, static_cast(AF_Simple( - params[0].ToCFXWideString(pRuntime).c_str(), - params[1].ToDouble(pRuntime), - params[2].ToDouble(pRuntime)))); - - return true; -} - -bool CJS_PublicMethods::AFMakeNumber(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString ws = params[0].ToCFXWideString(pRuntime); - ws.Replace(L",", L"."); - vRet = CJS_Value(pRuntime, ws.c_str()); - vRet.MaybeCoerceToNumber(pRuntime); - if (vRet.GetType() != CJS_Value::VT_number) - vRet = CJS_Value(pRuntime, 0); - return true; -} - -bool CJS_PublicMethods::AFSimple_Calculate(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CJS_Value params1 = params[1]; - if (!params1.IsArrayObject() && params1.GetType() != CJS_Value::VT_string) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CPDFSDK_InterForm* pReaderInterForm = - pRuntime->GetFormFillEnv()->GetInterForm(); - CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm(); - - CFX_WideString sFunction = params[0].ToCFXWideString(pRuntime); - double dValue = wcscmp(sFunction.c_str(), L"PRD") == 0 ? 1.0 : 0.0; - - CJS_Array FieldNameArray = AF_MakeArrayFromList(pRuntime, params1); - int nFieldsCount = 0; - - for (int i = 0, isz = FieldNameArray.GetLength(pRuntime); i < isz; i++) { - CJS_Value jsValue(pRuntime); - FieldNameArray.GetElement(pRuntime, i, jsValue); - CFX_WideString wsFieldName = jsValue.ToCFXWideString(pRuntime); - - for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) { - if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) { - double dTemp = 0.0; - switch (pFormField->GetFieldType()) { - case FIELDTYPE_TEXTFIELD: - case FIELDTYPE_COMBOBOX: { - CFX_WideString trimmed = pFormField->GetValue(); - trimmed.TrimRight(); - trimmed.TrimLeft(); - dTemp = FX_atof(trimmed.AsStringC()); - } break; - case FIELDTYPE_PUSHBUTTON: { - dTemp = 0.0; - } break; - case FIELDTYPE_CHECKBOX: - case FIELDTYPE_RADIOBUTTON: { - dTemp = 0.0; - for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) { - if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) { - if (pFormCtrl->IsChecked()) { - CFX_WideString trimmed = pFormCtrl->GetExportValue(); - trimmed.TrimRight(); - trimmed.TrimLeft(); - dTemp = FX_atof(trimmed.AsStringC()); - break; - } - } - } - } break; - case FIELDTYPE_LISTBOX: { - if (pFormField->CountSelectedItems() <= 1) { - CFX_WideString trimmed = pFormField->GetValue(); - trimmed.TrimRight(); - trimmed.TrimLeft(); - dTemp = FX_atof(trimmed.AsStringC()); - } - } break; - default: - break; - } - - if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 || - wcscmp(sFunction.c_str(), L"MAX") == 0)) - dValue = dTemp; - - dValue = AF_Simple(sFunction.c_str(), dValue, dTemp); - - nFieldsCount++; - } - } - } - - if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0) - dValue /= nFieldsCount; - - dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) / - FXSYS_pow((double)10, (double)6); - - CJS_Value jsValue(pRuntime, dValue); - CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); - if (pContext->GetEventHandler()->m_pValue) - pContext->GetEventHandler()->Value() = jsValue.ToCFXWideString(pRuntime); - - return true; -} - -/* This function validates the current event to ensure that its value is -** within the specified range. */ - -bool CJS_PublicMethods::AFRange_Validate(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 4) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); - CJS_EventHandler* pEvent = pContext->GetEventHandler(); - if (!pEvent->m_pValue) - return false; - - if (pEvent->Value().IsEmpty()) - return true; - - double dEentValue = - atof(CFX_ByteString::FromUnicode(pEvent->Value()).c_str()); - bool bGreaterThan = params[0].ToBool(pRuntime); - double dGreaterThan = params[1].ToDouble(pRuntime); - bool bLessThan = params[2].ToBool(pRuntime); - double dLessThan = params[3].ToDouble(pRuntime); - CFX_WideString swMsg; - - if (bGreaterThan && bLessThan) { - if (dEentValue < dGreaterThan || dEentValue > dLessThan) - swMsg.Format(JSGetStringFromID(IDS_STRING_JSRANGE1).c_str(), - params[1].ToCFXWideString(pRuntime).c_str(), - params[3].ToCFXWideString(pRuntime).c_str()); - } else if (bGreaterThan) { - if (dEentValue < dGreaterThan) - swMsg.Format(JSGetStringFromID(IDS_STRING_JSRANGE2).c_str(), - params[1].ToCFXWideString(pRuntime).c_str()); - } else if (bLessThan) { - if (dEentValue > dLessThan) - swMsg.Format(JSGetStringFromID(IDS_STRING_JSRANGE3).c_str(), - params[3].ToCFXWideString(pRuntime).c_str()); - } - - if (!swMsg.IsEmpty()) { - AlertIfPossible(pContext, swMsg.c_str()); - pEvent->Rc() = false; - } - return true; -} - -bool CJS_PublicMethods::AFExtractNums(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString str = params[0].ToCFXWideString(pRuntime); - if (str.GetAt(0) == L'.' || str.GetAt(0) == L',') - str = L"0" + str; - - CFX_WideString sPart; - CJS_Array nums; - int nIndex = 0; - for (int i = 0, sz = str.GetLength(); i < sz; i++) { - FX_WCHAR wc = str.GetAt(i); - if (FXSYS_iswdigit(wc)) { - sPart += wc; - } else { - if (sPart.GetLength() > 0) { - nums.SetElement(pRuntime, nIndex, CJS_Value(pRuntime, sPart.c_str())); - sPart = L""; - nIndex++; - } - } - } - - if (sPart.GetLength() > 0) { - nums.SetElement(pRuntime, nIndex, CJS_Value(pRuntime, sPart.c_str())); - } - - if (nums.GetLength(pRuntime) > 0) - vRet = CJS_Value(pRuntime, nums); - else - vRet.SetNull(pRuntime); - - return true; -} diff --git a/fpdfsdk/javascript/PublicMethods.h b/fpdfsdk/javascript/PublicMethods.h deleted file mode 100644 index 060c74303a8dfef842cff37fc2a38478555a4ded..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/PublicMethods.h +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_PUBLICMETHODS_H_ -#define FPDFSDK_JAVASCRIPT_PUBLICMETHODS_H_ - -#include -#include - -#include "fpdfsdk/javascript/JS_Define.h" - -class CJS_PublicMethods : public CJS_Object { - public: - explicit CJS_PublicMethods(v8::Local pObject) - : CJS_Object(pObject) {} - ~CJS_PublicMethods() override {} - - static bool AFNumber_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFNumber_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFPercent_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFPercent_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFDate_FormatEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFDate_KeystrokeEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFDate_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFDate_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFTime_FormatEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); // - static bool AFTime_KeystrokeEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFTime_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFTime_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFSpecial_Format(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFSpecial_Keystroke(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFSpecial_KeystrokeEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); // - static bool AFSimple(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFMakeNumber(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFSimple_Calculate(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFRange_Validate(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFMergeChange(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFParseDateEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - static bool AFExtractNums(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - - JS_STATIC_GLOBAL_FUN(AFNumber_Format); - JS_STATIC_GLOBAL_FUN(AFNumber_Keystroke); - JS_STATIC_GLOBAL_FUN(AFPercent_Format); - JS_STATIC_GLOBAL_FUN(AFPercent_Keystroke); - JS_STATIC_GLOBAL_FUN(AFDate_FormatEx); - JS_STATIC_GLOBAL_FUN(AFDate_KeystrokeEx); - JS_STATIC_GLOBAL_FUN(AFDate_Format); - JS_STATIC_GLOBAL_FUN(AFDate_Keystroke); - JS_STATIC_GLOBAL_FUN(AFTime_FormatEx); - JS_STATIC_GLOBAL_FUN(AFTime_KeystrokeEx); - JS_STATIC_GLOBAL_FUN(AFTime_Format); - JS_STATIC_GLOBAL_FUN(AFTime_Keystroke); - JS_STATIC_GLOBAL_FUN(AFSpecial_Format); - JS_STATIC_GLOBAL_FUN(AFSpecial_Keystroke); - JS_STATIC_GLOBAL_FUN(AFSpecial_KeystrokeEx); - JS_STATIC_GLOBAL_FUN(AFSimple); - JS_STATIC_GLOBAL_FUN(AFMakeNumber); - JS_STATIC_GLOBAL_FUN(AFSimple_Calculate); - JS_STATIC_GLOBAL_FUN(AFRange_Validate); - JS_STATIC_GLOBAL_FUN(AFMergeChange); - JS_STATIC_GLOBAL_FUN(AFParseDateEx); - JS_STATIC_GLOBAL_FUN(AFExtractNums); - - JS_STATIC_DECLARE_GLOBAL_FUN(); - - static int ParseStringInteger(const CFX_WideString& string, - int nStart, - int& nSkip, - int nMaxStep); - static CFX_WideString ParseStringString(const CFX_WideString& string, - int nStart, - int& nSkip); - static double MakeRegularDate(const CFX_WideString& value, - const CFX_WideString& format, - bool* bWrongFormat); - static CFX_WideString MakeFormatDate(double dDate, - const CFX_WideString& format); - static double ParseNormalDate(const CFX_WideString& value, - bool* bWrongFormat); - static double MakeInterDate(const CFX_WideString& value); - - static bool IsNumber(const CFX_WideString& str); - - static bool maskSatisfied(wchar_t c_Change, wchar_t c_Mask); - static bool isReservedMaskChar(wchar_t ch); - - static double AF_Simple(const FX_WCHAR* sFuction, - double dValue1, - double dValue2); - static CJS_Array AF_MakeArrayFromList(CJS_Runtime* pRuntime, CJS_Value val); -}; - -#endif // FPDFSDK_JAVASCRIPT_PUBLICMETHODS_H_ diff --git a/fpdfsdk/javascript/app.cpp b/fpdfsdk/javascript/app.cpp deleted file mode 100644 index 3a8bf088f361fc04bb768227f416a6a61b1430dd..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/app.cpp +++ /dev/null @@ -1,790 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/app.h" - -#include -#include -#include - -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/cpdfsdk_interform.h" -#include "fpdfsdk/javascript/Document.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/resource.h" -#include "third_party/base/stl_util.h" - -class GlobalTimer { - public: - GlobalTimer(app* pObj, - CPDFSDK_FormFillEnvironment* pFormFillEnv, - CJS_Runtime* pRuntime, - int nType, - const CFX_WideString& script, - uint32_t dwElapse, - uint32_t dwTimeOut); - ~GlobalTimer(); - - static void Trigger(int nTimerID); - static void Cancel(int nTimerID); - - bool IsOneShot() const { return m_nType == 1; } - uint32_t GetTimeOut() const { return m_dwTimeOut; } - int GetTimerID() const { return m_nTimerID; } - CJS_Runtime* GetRuntime() const { return m_pRuntime.Get(); } - CFX_WideString GetJScript() const { return m_swJScript; } - - private: - using TimerMap = std::map; - static TimerMap* GetGlobalTimerMap(); - - uint32_t m_nTimerID; - app* const m_pEmbedObj; - bool m_bProcessing; - - // data - const int m_nType; // 0:Interval; 1:TimeOut - const uint32_t m_dwTimeOut; - const CFX_WideString m_swJScript; - CJS_Runtime::ObservedPtr m_pRuntime; - CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; -}; - -GlobalTimer::GlobalTimer(app* pObj, - CPDFSDK_FormFillEnvironment* pFormFillEnv, - CJS_Runtime* pRuntime, - int nType, - const CFX_WideString& script, - uint32_t dwElapse, - uint32_t dwTimeOut) - : m_nTimerID(0), - m_pEmbedObj(pObj), - m_bProcessing(false), - m_nType(nType), - m_dwTimeOut(dwTimeOut), - m_swJScript(script), - m_pRuntime(pRuntime), - m_pFormFillEnv(pFormFillEnv) { - CFX_SystemHandler* pHandler = m_pFormFillEnv->GetSysHandler(); - m_nTimerID = pHandler->SetTimer(dwElapse, Trigger); - if (m_nTimerID) - (*GetGlobalTimerMap())[m_nTimerID] = this; -} - -GlobalTimer::~GlobalTimer() { - if (!m_nTimerID) - return; - - if (GetRuntime()) - m_pFormFillEnv->GetSysHandler()->KillTimer(m_nTimerID); - - GetGlobalTimerMap()->erase(m_nTimerID); -} - -// static -void GlobalTimer::Trigger(int nTimerID) { - auto it = GetGlobalTimerMap()->find(nTimerID); - if (it == GetGlobalTimerMap()->end()) - return; - - GlobalTimer* pTimer = it->second; - if (pTimer->m_bProcessing) - return; - - pTimer->m_bProcessing = true; - if (pTimer->m_pEmbedObj) - pTimer->m_pEmbedObj->TimerProc(pTimer); - - // Timer proc may have destroyed timer, find it again. - it = GetGlobalTimerMap()->find(nTimerID); - if (it == GetGlobalTimerMap()->end()) - return; - - pTimer = it->second; - pTimer->m_bProcessing = false; - if (pTimer->IsOneShot()) - pTimer->m_pEmbedObj->CancelProc(pTimer); -} - -// static -void GlobalTimer::Cancel(int nTimerID) { - auto it = GetGlobalTimerMap()->find(nTimerID); - if (it == GetGlobalTimerMap()->end()) - return; - - GlobalTimer* pTimer = it->second; - pTimer->m_pEmbedObj->CancelProc(pTimer); -} - -// static -GlobalTimer::TimerMap* GlobalTimer::GetGlobalTimerMap() { - // Leak the timer array at shutdown. - static auto* s_TimerMap = new TimerMap; - return s_TimerMap; -} - -JSConstSpec CJS_TimerObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_TimerObj::PropertySpecs[] = {{0, 0, 0}}; - -JSMethodSpec CJS_TimerObj::MethodSpecs[] = {{0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj) - -TimerObj::TimerObj(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject), m_nTimerID(0) {} - -TimerObj::~TimerObj() {} - -void TimerObj::SetTimer(GlobalTimer* pTimer) { - m_nTimerID = pTimer->GetTimerID(); -} - -#define JS_STR_VIEWERTYPE L"pdfium" -#define JS_STR_VIEWERVARIATION L"Full" -#define JS_STR_PLATFORM L"WIN" -#define JS_STR_LANGUAGE L"ENU" -#define JS_NUM_VIEWERVERSION 8 -#ifdef PDF_ENABLE_XFA -#define JS_NUM_VIEWERVERSION_XFA 11 -#endif // PDF_ENABLE_XFA -#define JS_NUM_FORMSVERSION 7 - -JSConstSpec CJS_App::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_App::PropertySpecs[] = { - {"activeDocs", get_activeDocs_static, set_activeDocs_static}, - {"calculate", get_calculate_static, set_calculate_static}, - {"formsVersion", get_formsVersion_static, set_formsVersion_static}, - {"fs", get_fs_static, set_fs_static}, - {"fullscreen", get_fullscreen_static, set_fullscreen_static}, - {"language", get_language_static, set_language_static}, - {"media", get_media_static, set_media_static}, - {"platform", get_platform_static, set_platform_static}, - {"runtimeHighlight", get_runtimeHighlight_static, - set_runtimeHighlight_static}, - {"viewerType", get_viewerType_static, set_viewerType_static}, - {"viewerVariation", get_viewerVariation_static, set_viewerVariation_static}, - {"viewerVersion", get_viewerVersion_static, set_viewerVersion_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_App::MethodSpecs[] = {{"alert", alert_static}, - {"beep", beep_static}, - {"browseForDoc", browseForDoc_static}, - {"clearInterval", clearInterval_static}, - {"clearTimeOut", clearTimeOut_static}, - {"execDialog", execDialog_static}, - {"execMenuItem", execMenuItem_static}, - {"findComponent", findComponent_static}, - {"goBack", goBack_static}, - {"goForward", goForward_static}, - {"launchURL", launchURL_static}, - {"mailMsg", mailMsg_static}, - {"newFDF", newFDF_static}, - {"newDoc", newDoc_static}, - {"openDoc", openDoc_static}, - {"openFDF", openFDF_static}, - {"popUpMenuEx", popUpMenuEx_static}, - {"popUpMenu", popUpMenu_static}, - {"response", response_static}, - {"setInterval", setInterval_static}, - {"setTimeOut", setTimeOut_static}, - {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_App, app) - -app::app(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {} - -app::~app() { -} - -bool app::activeDocs(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_Document* pJSDocument = nullptr; - v8::Local pObj = pRuntime->GetThisObj(); - if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::g_nObjDefnID) - pJSDocument = static_cast(pRuntime->GetObjectPrivate(pObj)); - - CJS_Array aDocs; - aDocs.SetElement(pRuntime, 0, CJS_Value(pRuntime, pJSDocument)); - if (aDocs.GetLength(pRuntime) > 0) - vp << aDocs; - else - vp.GetJSValue()->SetNull(pRuntime); - - return true; -} - -bool app::calculate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - bool bVP; - vp >> bVP; - m_bCalculate = (bool)bVP; - pRuntime->GetFormFillEnv()->GetInterForm()->EnableCalculate( - (bool)m_bCalculate); - } else { - vp << (bool)m_bCalculate; - } - return true; -} - -bool app::formsVersion(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - vp << JS_NUM_FORMSVERSION; - return true; - } - - return false; -} - -bool app::viewerType(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - vp << JS_STR_VIEWERTYPE; - return true; - } - - return false; -} - -bool app::viewerVariation(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsGetting()) { - vp << JS_STR_VIEWERVARIATION; - return true; - } - - return false; -} - -bool app::viewerVersion(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; -#ifdef PDF_ENABLE_XFA - CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext(); - if (pXFAContext->GetDocType() == 1 || pXFAContext->GetDocType() == 2) { - vp << JS_NUM_VIEWERVERSION_XFA; - return true; - } -#endif // PDF_ENABLE_XFA - vp << JS_NUM_VIEWERVERSION; - return true; -} - -bool app::platform(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; -#ifdef PDF_ENABLE_XFA - CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); - if (!pFormFillEnv) - return false; - CFX_WideString platfrom = pFormFillEnv->GetPlatform(); - if (!platfrom.IsEmpty()) { - vp << platfrom; - return true; - } -#endif - vp << JS_STR_PLATFORM; - return true; -} - -bool app::language(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; -#ifdef PDF_ENABLE_XFA - CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); - if (!pFormFillEnv) - return false; - CFX_WideString language = pFormFillEnv->GetLanguage(); - if (!language.IsEmpty()) { - vp << language; - return true; - } -#endif - vp << JS_STR_LANGUAGE; - return true; -} - -// creates a new fdf object that contains no data -// comment: need reader support -// note: -// CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF(); -bool app::newFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} -// opens a specified pdf document and returns its document object -// comment:need reader support -// note: as defined in js reference, the proto of this function's fourth -// parmeters, how old an fdf document while do not show it. -// CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool -// bUserConv); - -bool app::openFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool app::alert(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - std::vector newParams = JS_ExpandKeywordParams( - pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle"); - - if (newParams[0].GetType() == CJS_Value::VT_unknown) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); - if (!pFormFillEnv) { - vRet = CJS_Value(pRuntime, 0); - return true; - } - - CFX_WideString swMsg; - if (newParams[0].GetType() == CJS_Value::VT_object) { - CJS_Array carray; - if (newParams[0].ConvertToArray(pRuntime, carray)) { - swMsg = L"["; - CJS_Value element(pRuntime); - for (int i = 0; i < carray.GetLength(pRuntime); ++i) { - if (i) - swMsg += L", "; - carray.GetElement(pRuntime, i, element); - swMsg += element.ToCFXWideString(pRuntime); - } - swMsg += L"]"; - } else { - swMsg = newParams[0].ToCFXWideString(pRuntime); - } - } else { - swMsg = newParams[0].ToCFXWideString(pRuntime); - } - - int iIcon = 0; - if (newParams[1].GetType() != CJS_Value::VT_unknown) - iIcon = newParams[1].ToInt(pRuntime); - - int iType = 0; - if (newParams[2].GetType() != CJS_Value::VT_unknown) - iType = newParams[2].ToInt(pRuntime); - - CFX_WideString swTitle; - if (newParams[3].GetType() != CJS_Value::VT_unknown) - swTitle = newParams[3].ToCFXWideString(pRuntime); - else - swTitle = JSGetStringFromID(IDS_STRING_JSALERT); - - pRuntime->BeginBlock(); - pFormFillEnv->KillFocusAnnot(0); - - vRet = CJS_Value(pRuntime, pFormFillEnv->JS_appAlert( - swMsg.c_str(), swTitle.c_str(), iType, iIcon)); - pRuntime->EndBlock(); - return true; -} - -bool app::beep(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() == 1) { - pRuntime->GetFormFillEnv()->JS_appBeep(params[0].ToInt(pRuntime)); - return true; - } - - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; -} - -bool app::findComponent(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool app::popUpMenuEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool app::fs(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError) { - return false; -} - -bool app::setInterval(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() > 2 || params.size() == 0) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString script = - params.size() > 0 ? params[0].ToCFXWideString(pRuntime) : L""; - if (script.IsEmpty()) { - sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE); - return true; - } - - uint32_t dwInterval = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000; - - GlobalTimer* timerRef = new GlobalTimer(this, pRuntime->GetFormFillEnv(), - pRuntime, 0, script, dwInterval, 0); - m_Timers.insert(std::unique_ptr(timerRef)); - - v8::Local pRetObj = - pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); - if (pRetObj.IsEmpty()) - return false; - - CJS_TimerObj* pJS_TimerObj = - static_cast(pRuntime->GetObjectPrivate(pRetObj)); - TimerObj* pTimerObj = static_cast(pJS_TimerObj->GetEmbedObject()); - pTimerObj->SetTimer(timerRef); - - vRet = CJS_Value(pRuntime, pRetObj); - return true; -} - -bool app::setTimeOut(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() > 2 || params.size() == 0) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - CFX_WideString script = params[0].ToCFXWideString(pRuntime); - if (script.IsEmpty()) { - sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE); - return true; - } - - uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000; - GlobalTimer* timerRef = - new GlobalTimer(this, pRuntime->GetFormFillEnv(), pRuntime, 1, script, - dwTimeOut, dwTimeOut); - m_Timers.insert(std::unique_ptr(timerRef)); - - v8::Local pRetObj = - pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); - if (pRetObj.IsEmpty()) - return false; - - CJS_TimerObj* pJS_TimerObj = - static_cast(pRuntime->GetObjectPrivate(pRetObj)); - TimerObj* pTimerObj = static_cast(pJS_TimerObj->GetEmbedObject()); - pTimerObj->SetTimer(timerRef); - vRet = CJS_Value(pRuntime, pRetObj); - return true; -} - -bool app::clearTimeOut(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - app::ClearTimerCommon(pRuntime, params[0]); - return true; -} - -bool app::clearInterval(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - app::ClearTimerCommon(pRuntime, params[0]); - return true; -} - -void app::ClearTimerCommon(CJS_Runtime* pRuntime, const CJS_Value& param) { - if (param.GetType() != CJS_Value::VT_object) - return; - - v8::Local pObj = param.ToV8Object(pRuntime); - if (CFXJS_Engine::GetObjDefnID(pObj) != CJS_TimerObj::g_nObjDefnID) - return; - - CJS_Object* pJSObj = param.ToCJSObject(pRuntime); - if (!pJSObj) - return; - - TimerObj* pTimerObj = static_cast(pJSObj->GetEmbedObject()); - if (!pTimerObj) - return; - - GlobalTimer::Cancel(pTimerObj->GetTimerID()); -} - -bool app::execMenuItem(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -void app::TimerProc(GlobalTimer* pTimer) { - CJS_Runtime* pRuntime = pTimer->GetRuntime(); - if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0)) - RunJsScript(pRuntime, pTimer->GetJScript()); -} - -void app::CancelProc(GlobalTimer* pTimer) { - m_Timers.erase(pdfium::FakeUniquePtr(pTimer)); -} - -void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) { - if (!pRuntime->IsBlocking()) { - IJS_EventContext* pContext = pRuntime->NewEventContext(); - pContext->OnExternal_Exec(); - CFX_WideString wtInfo; - pContext->RunScript(wsScript, &wtInfo); - pRuntime->ReleaseEventContext(pContext); - } -} - -bool app::goBack(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Not supported. - return true; -} - -bool app::goForward(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Not supported. - return true; -} - -bool app::mailMsg(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - std::vector newParams = - JS_ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", - L"cBcc", L"cSubject", L"cMsg"); - - if (newParams[0].GetType() == CJS_Value::VT_unknown) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - bool bUI = newParams[0].ToBool(pRuntime); - - CFX_WideString cTo; - if (newParams[1].GetType() != CJS_Value::VT_unknown) { - cTo = newParams[1].ToCFXWideString(pRuntime); - } else { - if (!bUI) { - // cTo parameter required when UI not invoked. - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - } - - CFX_WideString cCc; - if (newParams[2].GetType() != CJS_Value::VT_unknown) - cCc = newParams[2].ToCFXWideString(pRuntime); - - CFX_WideString cBcc; - if (newParams[3].GetType() != CJS_Value::VT_unknown) - cBcc = newParams[3].ToCFXWideString(pRuntime); - - CFX_WideString cSubject; - if (newParams[4].GetType() != CJS_Value::VT_unknown) - cSubject = newParams[4].ToCFXWideString(pRuntime); - - CFX_WideString cMsg; - if (newParams[5].GetType() != CJS_Value::VT_unknown) - cMsg = newParams[5].ToCFXWideString(pRuntime); - - pRuntime->BeginBlock(); - pRuntime->GetFormFillEnv()->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), - cSubject.c_str(), cCc.c_str(), - cBcc.c_str(), cMsg.c_str()); - pRuntime->EndBlock(); - return true; -} - -bool app::launchURL(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool app::runtimeHighlight(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - vp >> m_bRuntimeHighLight; - } else { - vp << m_bRuntimeHighLight; - } - return true; -} - -bool app::fullscreen(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return false; -} - -bool app::popUpMenu(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool app::browseForDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -CFX_WideString app::SysPathToPDFPath(const CFX_WideString& sOldPath) { - CFX_WideString sRet = L"/"; - - for (int i = 0, sz = sOldPath.GetLength(); i < sz; i++) { - wchar_t c = sOldPath.GetAt(i); - if (c == L':') { - } else { - if (c == L'\\') { - sRet += L"/"; - } else { - sRet += c; - } - } - } - - return sRet; -} - -bool app::newDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool app::openDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return false; -} - -bool app::response(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - std::vector newParams = - JS_ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle", - L"cDefault", L"bPassword", L"cLabel"); - - if (newParams[0].GetType() == CJS_Value::VT_unknown) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - CFX_WideString swQuestion = newParams[0].ToCFXWideString(pRuntime); - - CFX_WideString swTitle = L"PDF"; - if (newParams[1].GetType() != CJS_Value::VT_unknown) - swTitle = newParams[1].ToCFXWideString(pRuntime); - - CFX_WideString swDefault; - if (newParams[2].GetType() != CJS_Value::VT_unknown) - swDefault = newParams[2].ToCFXWideString(pRuntime); - - bool bPassword = false; - if (newParams[3].GetType() != CJS_Value::VT_unknown) - bPassword = newParams[3].ToBool(pRuntime); - - CFX_WideString swLabel; - if (newParams[4].GetType() != CJS_Value::VT_unknown) - swLabel = newParams[4].ToCFXWideString(pRuntime); - - const int MAX_INPUT_BYTES = 2048; - std::unique_ptr pBuff(new char[MAX_INPUT_BYTES + 2]); - memset(pBuff.get(), 0, MAX_INPUT_BYTES + 2); - - int nLengthBytes = pRuntime->GetFormFillEnv()->JS_appResponse( - swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(), - bPassword, pBuff.get(), MAX_INPUT_BYTES); - - if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES) { - sError = JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG); - return false; - } - - vRet = CJS_Value(pRuntime, CFX_WideString::FromUTF16LE( - reinterpret_cast(pBuff.get()), - nLengthBytes / sizeof(uint16_t)) - .c_str()); - - return true; -} - -bool app::media(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return false; -} - -bool app::execDialog(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} diff --git a/fpdfsdk/javascript/app.h b/fpdfsdk/javascript/app.h deleted file mode 100644 index 9e11b8241982aa790071a2bfebc1c55678eabe4a..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/app.h +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_APP_H_ -#define FPDFSDK_JAVASCRIPT_APP_H_ - -#include -#include -#include - -#include "fpdfsdk/javascript/JS_Define.h" - -class CJS_Runtime; -class GlobalTimer; - -class TimerObj : public CJS_EmbedObj { - public: - explicit TimerObj(CJS_Object* pJSObject); - ~TimerObj() override; - - void SetTimer(GlobalTimer* pTimer); - int GetTimerID() const { return m_nTimerID; } - - private: - int m_nTimerID; // Weak reference to GlobalTimer through global map. -}; - -class CJS_TimerObj : public CJS_Object { - public: - explicit CJS_TimerObj(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_TimerObj() override {} - - DECLARE_JS_CLASS(); -}; - -class app : public CJS_EmbedObj { - public: - explicit app(CJS_Object* pJSObject); - ~app() override; - - bool activeDocs(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool calculate(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool formsVersion(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool fs(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool fullscreen(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool language(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool media(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool platform(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool runtimeHighlight(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool viewerType(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool viewerVariation(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool viewerVersion(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - - bool alert(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool beep(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool browseForDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool clearInterval(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool clearTimeOut(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool execDialog(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool execMenuItem(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool findComponent(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool goBack(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool goForward(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool launchURL(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool mailMsg(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool newFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool newDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool openDoc(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool openFDF(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool popUpMenuEx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool popUpMenu(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool response(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool setInterval(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool setTimeOut(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - - void TimerProc(GlobalTimer* pTimer); - void CancelProc(GlobalTimer* pTimer); - - static CFX_WideString SysPathToPDFPath(const CFX_WideString& sOldPath); - - private: - // CJS_EmbedObj - void RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript); - - void ClearTimerCommon(CJS_Runtime* pRuntime, const CJS_Value& param); - - bool m_bCalculate; - bool m_bRuntimeHighLight; - std::unordered_set> m_Timers; -}; - -class CJS_App : public CJS_Object { - public: - explicit CJS_App(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_App() override {} - - DECLARE_JS_CLASS(); - - JS_STATIC_PROP(activeDocs, app); - JS_STATIC_PROP(calculate, app); - JS_STATIC_PROP(formsVersion, app); - JS_STATIC_PROP(fs, app); - JS_STATIC_PROP(fullscreen, app); - JS_STATIC_PROP(language, app); - JS_STATIC_PROP(media, app); - JS_STATIC_PROP(platform, app); - JS_STATIC_PROP(runtimeHighlight, app); - JS_STATIC_PROP(viewerType, app); - JS_STATIC_PROP(viewerVariation, app); - JS_STATIC_PROP(viewerVersion, app); - - JS_STATIC_METHOD(alert, app); - JS_STATIC_METHOD(beep, app); - JS_STATIC_METHOD(browseForDoc, app); - JS_STATIC_METHOD(clearInterval, app); - JS_STATIC_METHOD(clearTimeOut, app); - JS_STATIC_METHOD(execDialog, app); - JS_STATIC_METHOD(execMenuItem, app); - JS_STATIC_METHOD(findComponent, app); - JS_STATIC_METHOD(goBack, app); - JS_STATIC_METHOD(goForward, app); - JS_STATIC_METHOD(launchURL, app); - JS_STATIC_METHOD(mailMsg, app); - JS_STATIC_METHOD(newFDF, app); - JS_STATIC_METHOD(newDoc, app); - JS_STATIC_METHOD(openDoc, app); - JS_STATIC_METHOD(openFDF, app); - JS_STATIC_METHOD(popUpMenuEx, app); - JS_STATIC_METHOD(popUpMenu, app); - JS_STATIC_METHOD(response, app); - JS_STATIC_METHOD(setInterval, app); - JS_STATIC_METHOD(setTimeOut, app); -}; - -#endif // FPDFSDK_JAVASCRIPT_APP_H_ diff --git a/fpdfsdk/javascript/cjs_runtime.cpp b/fpdfsdk/javascript/cjs_runtime.cpp deleted file mode 100644 index 1ece0b6f79da5d5e2f3fc09add14f1e048fed8d6..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/cjs_runtime.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/cjs_runtime.h" - -#include - -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/javascript/Annot.h" -#include "fpdfsdk/javascript/Consts.h" -#include "fpdfsdk/javascript/Document.h" -#include "fpdfsdk/javascript/Field.h" -#include "fpdfsdk/javascript/Icon.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_GlobalData.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/PublicMethods.h" -#include "fpdfsdk/javascript/app.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/color.h" -#include "fpdfsdk/javascript/console.h" -#include "fpdfsdk/javascript/event.h" -#include "fpdfsdk/javascript/global.h" -#include "fpdfsdk/javascript/report.h" -#include "fpdfsdk/javascript/util.h" -#include "public/fpdf_formfill.h" -#include "third_party/base/stl_util.h" - -#ifdef PDF_ENABLE_XFA -#include "fxjs/cfxjse_value.h" -#endif // PDF_ENABLE_XFA - -// static -void IJS_Runtime::Initialize(unsigned int slot, void* isolate) { - FXJS_Initialize(slot, reinterpret_cast(isolate)); -} - -// static -void IJS_Runtime::Destroy() { - FXJS_Release(); -} - -// static -IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) { - return new CJS_Runtime(pFormFillEnv); -} - -// static -CJS_Runtime* CJS_Runtime::CurrentRuntimeFromIsolate(v8::Isolate* pIsolate) { - return static_cast( - CFXJS_Engine::CurrentEngineFromIsolate(pIsolate)); -} - -CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv) - : m_pFormFillEnv(pFormFillEnv), - m_bBlocking(false), - m_isolateManaged(false) { - v8::Isolate* pIsolate = nullptr; - - IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform; - if (pPlatform->version <= 2) { - unsigned int embedderDataSlot = 0; - v8::Isolate* pExternalIsolate = nullptr; - if (pPlatform->version == 2) { - pExternalIsolate = reinterpret_cast(pPlatform->m_isolate); - embedderDataSlot = pPlatform->m_v8EmbedderSlot; - } - FXJS_Initialize(embedderDataSlot, pExternalIsolate); - } - m_isolateManaged = FXJS_GetIsolate(&pIsolate); - SetIsolate(pIsolate); - -#ifdef PDF_ENABLE_XFA - v8::Isolate::Scope isolate_scope(pIsolate); - v8::HandleScope handle_scope(pIsolate); -#endif - - if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0) - DefineJSObjects(); - - IJS_EventContext* pContext = NewEventContext(); - InitializeEngine(); - ReleaseEventContext(pContext); - SetFormFillEnvToDocument(); -} - -CJS_Runtime::~CJS_Runtime() { - NotifyObservedPtrs(); - ReleaseEngine(); - if (m_isolateManaged) { - GetIsolate()->Dispose(); - SetIsolate(nullptr); - } -} - -void CJS_Runtime::DefineJSObjects() { - v8::Isolate::Scope isolate_scope(GetIsolate()); - v8::HandleScope handle_scope(GetIsolate()); - v8::Local context = v8::Context::New(GetIsolate()); - v8::Context::Scope context_scope(context); - - // The call order determines the "ObjDefID" assigned to each class. - // ObjDefIDs 0 - 2 - CJS_Border::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Display::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Font::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - - // ObjDefIDs 3 - 5 - CJS_Highlight::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Position::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_ScaleHow::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - - // ObjDefIDs 6 - 8 - CJS_ScaleWhen::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Style::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Zoomtype::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - - // ObjDefIDs 9 - 11 - CJS_App::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Color::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Console::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - - // ObjDefIDs 12 - 14 - CJS_Document::DefineJSObjects(this, FXJSOBJTYPE_GLOBAL); - CJS_Event::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Field::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); - - // ObjDefIDs 15 - 17 - CJS_Global::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - CJS_Icon::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); - CJS_Util::DefineJSObjects(this, FXJSOBJTYPE_STATIC); - - // ObjDefIDs 18 - 20 (these can't fail, return void). - CJS_PublicMethods::DefineJSObjects(this); - CJS_GlobalConsts::DefineJSObjects(this); - CJS_GlobalArrays::DefineJSObjects(this); - - // ObjDefIDs 21 - 23. - CJS_TimerObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); - CJS_PrintParamsObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); - CJS_Annot::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC); -} - -IJS_EventContext* CJS_Runtime::NewEventContext() { - m_EventContextArray.push_back( - std::unique_ptr(new CJS_EventContext(this))); - return m_EventContextArray.back().get(); -} - -void CJS_Runtime::ReleaseEventContext(IJS_EventContext* pContext) { - auto it = std::find(m_EventContextArray.begin(), m_EventContextArray.end(), - pdfium::FakeUniquePtr( - static_cast(pContext))); - if (it != m_EventContextArray.end()) - m_EventContextArray.erase(it); -} - -CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const { - return m_EventContextArray.empty() ? nullptr - : m_EventContextArray.back().get(); -} - -void CJS_Runtime::SetFormFillEnvToDocument() { - v8::Isolate::Scope isolate_scope(GetIsolate()); - v8::HandleScope handle_scope(GetIsolate()); - v8::Local context = NewLocalContext(); - v8::Context::Scope context_scope(context); - - v8::Local pThis = GetThisObj(); - if (pThis.IsEmpty()) - return; - - if (CFXJS_Engine::GetObjDefnID(pThis) != CJS_Document::g_nObjDefnID) - return; - - CJS_Document* pJSDocument = - static_cast(GetObjectPrivate(pThis)); - if (!pJSDocument) - return; - - Document* pDocument = static_cast(pJSDocument->GetEmbedObject()); - if (!pDocument) - return; - - pDocument->SetFormFillEnv(m_pFormFillEnv.Get()); -} - -CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const { - return m_pFormFillEnv.Get(); -} - -int CJS_Runtime::ExecuteScript(const CFX_WideString& script, - CFX_WideString* info) { - FXJSErr error = {}; - int nRet = Execute(script, &error); - if (nRet < 0) { - info->Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline, - error.message); - } - return nRet; -} - -bool CJS_Runtime::AddEventToSet(const FieldEvent& event) { - return m_FieldEventSet.insert(event).second; -} - -void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) { - m_FieldEventSet.erase(event); -} - -#ifdef PDF_ENABLE_XFA -CFX_WideString ChangeObjName(const CFX_WideString& str) { - CFX_WideString sRet = str; - sRet.Replace(L"_", L"."); - return sRet; -} -bool CJS_Runtime::GetValueByName(const CFX_ByteStringC& utf8Name, - CFXJSE_Value* pValue) { - const FX_CHAR* name = utf8Name.c_str(); - - v8::Isolate::Scope isolate_scope(GetIsolate()); - v8::HandleScope handle_scope(GetIsolate()); - v8::Local context = NewLocalContext(); - v8::Context::Scope context_scope(context); - - v8::Local propvalue = - context->Global()->Get(v8::String::NewFromUtf8( - GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength())); - - if (propvalue.IsEmpty()) { - pValue->SetUndefined(); - return false; - } - pValue->ForceSetValue(propvalue); - return true; -} -bool CJS_Runtime::SetValueByName(const CFX_ByteStringC& utf8Name, - CFXJSE_Value* pValue) { - if (utf8Name.IsEmpty() || !pValue) - return false; - const FX_CHAR* name = utf8Name.c_str(); - v8::Isolate* pIsolate = GetIsolate(); - v8::Isolate::Scope isolate_scope(pIsolate); - v8::HandleScope handle_scope(pIsolate); - v8::Local context = NewLocalContext(); - v8::Context::Scope context_scope(context); - - // v8::Local tmpCotext = - // v8::Local::New(GetIsolate(), m_context); - v8::Local propvalue = - v8::Local::New(GetIsolate(), pValue->DirectGetValue()); - context->Global()->Set( - v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString, - utf8Name.GetLength()), - propvalue); - return true; -} -#endif diff --git a/fpdfsdk/javascript/cjs_runtime.h b/fpdfsdk/javascript/cjs_runtime.h deleted file mode 100644 index 0bde51f9decdbeed6035dc05326c405763e7c667..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/cjs_runtime.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_CJS_RUNTIME_H_ -#define FPDFSDK_JAVASCRIPT_CJS_RUNTIME_H_ - -#include -#include -#include -#include -#include - -#include "core/fxcrt/cfx_observable.h" -#include "core/fxcrt/fx_basic.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/ijs_runtime.h" -#include "fxjs/fxjs_v8.h" - -class CJS_EventContext; - -class CJS_Runtime : public IJS_Runtime, - public CFXJS_Engine, - public CFX_Observable { - public: - using FieldEvent = std::pair; - - static CJS_Runtime* CurrentRuntimeFromIsolate(v8::Isolate* pIsolate); - - explicit CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv); - ~CJS_Runtime() override; - - // IJS_Runtime - IJS_EventContext* NewEventContext() override; - void ReleaseEventContext(IJS_EventContext* pContext) override; - CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override; - int ExecuteScript(const CFX_WideString& script, - CFX_WideString* info) override; - - CJS_EventContext* GetCurrentEventContext() const; - - // Returns true if the event isn't already found in the set. - bool AddEventToSet(const FieldEvent& event); - void RemoveEventFromSet(const FieldEvent& event); - - void BeginBlock() { m_bBlocking = true; } - void EndBlock() { m_bBlocking = false; } - bool IsBlocking() const { return m_bBlocking; } - -#ifdef PDF_ENABLE_XFA - bool GetValueByName(const CFX_ByteStringC& utf8Name, - CFXJSE_Value* pValue) override; - bool SetValueByName(const CFX_ByteStringC& utf8Name, - CFXJSE_Value* pValue) override; -#endif // PDF_ENABLE_XFA - - private: - void DefineJSObjects(); - void SetFormFillEnvToDocument(); - - std::vector> m_EventContextArray; - CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; - bool m_bBlocking; - bool m_isolateManaged; - std::set m_FieldEventSet; -}; - -#endif // FPDFSDK_JAVASCRIPT_CJS_RUNTIME_H_ diff --git a/fpdfsdk/javascript/color.cpp b/fpdfsdk/javascript/color.cpp deleted file mode 100644 index b5ccbadabf13865ab376808b9c2dfbafee28e401..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/color.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/color.h" - -#include - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" - -JSConstSpec CJS_Color::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Color::PropertySpecs[] = { - {"black", get_black_static, set_black_static}, - {"blue", get_blue_static, set_blue_static}, - {"cyan", get_cyan_static, set_cyan_static}, - {"dkGray", get_dkGray_static, set_dkGray_static}, - {"gray", get_gray_static, set_gray_static}, - {"green", get_green_static, set_green_static}, - {"ltGray", get_ltGray_static, set_ltGray_static}, - {"magenta", get_magenta_static, set_magenta_static}, - {"red", get_red_static, set_red_static}, - {"transparent", get_transparent_static, set_transparent_static}, - {"white", get_white_static, set_white_static}, - {"yellow", get_yellow_static, set_yellow_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_Color::MethodSpecs[] = {{"convert", convert_static}, - {"equal", equal_static}, - {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Color, color) - -color::color(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) { - m_crTransparent = CPWL_Color(COLORTYPE_TRANSPARENT); - m_crBlack = CPWL_Color(COLORTYPE_GRAY, 0); - m_crWhite = CPWL_Color(COLORTYPE_GRAY, 1); - m_crRed = CPWL_Color(COLORTYPE_RGB, 1, 0, 0); - m_crGreen = CPWL_Color(COLORTYPE_RGB, 0, 1, 0); - m_crBlue = CPWL_Color(COLORTYPE_RGB, 0, 0, 1); - m_crCyan = CPWL_Color(COLORTYPE_CMYK, 1, 0, 0, 0); - m_crMagenta = CPWL_Color(COLORTYPE_CMYK, 0, 1, 0, 0); - m_crYellow = CPWL_Color(COLORTYPE_CMYK, 0, 0, 1, 0); - m_crDKGray = CPWL_Color(COLORTYPE_GRAY, 0.25); - m_crGray = CPWL_Color(COLORTYPE_GRAY, 0.5); - m_crLTGray = CPWL_Color(COLORTYPE_GRAY, 0.75); -} - -color::~color() {} - -void color::ConvertPWLColorToArray(CJS_Runtime* pRuntime, - const CPWL_Color& color, - CJS_Array* array) { - switch (color.nColorType) { - case COLORTYPE_TRANSPARENT: - array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "T")); - break; - case COLORTYPE_GRAY: - array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "G")); - array->SetElement(pRuntime, 1, CJS_Value(pRuntime, color.fColor1)); - break; - case COLORTYPE_RGB: - array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "RGB")); - array->SetElement(pRuntime, 1, CJS_Value(pRuntime, color.fColor1)); - array->SetElement(pRuntime, 2, CJS_Value(pRuntime, color.fColor2)); - array->SetElement(pRuntime, 3, CJS_Value(pRuntime, color.fColor3)); - break; - case COLORTYPE_CMYK: - array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "CMYK")); - array->SetElement(pRuntime, 1, CJS_Value(pRuntime, color.fColor1)); - array->SetElement(pRuntime, 2, CJS_Value(pRuntime, color.fColor2)); - array->SetElement(pRuntime, 3, CJS_Value(pRuntime, color.fColor3)); - array->SetElement(pRuntime, 4, CJS_Value(pRuntime, color.fColor4)); - break; - } -} - -void color::ConvertArrayToPWLColor(CJS_Runtime* pRuntime, - const CJS_Array& array, - CPWL_Color* color) { - int nArrayLen = array.GetLength(pRuntime); - if (nArrayLen < 1) - return; - - CJS_Value value(pRuntime); - array.GetElement(pRuntime, 0, value); - CFX_ByteString sSpace = value.ToCFXByteString(pRuntime); - - double d1 = 0; - double d2 = 0; - double d3 = 0; - double d4 = 0; - - if (nArrayLen > 1) { - array.GetElement(pRuntime, 1, value); - d1 = value.ToDouble(pRuntime); - } - - if (nArrayLen > 2) { - array.GetElement(pRuntime, 2, value); - d2 = value.ToDouble(pRuntime); - } - - if (nArrayLen > 3) { - array.GetElement(pRuntime, 3, value); - d3 = value.ToDouble(pRuntime); - } - - if (nArrayLen > 4) { - array.GetElement(pRuntime, 4, value); - d4 = value.ToDouble(pRuntime); - } - - if (sSpace == "T") { - *color = CPWL_Color(COLORTYPE_TRANSPARENT); - } else if (sSpace == "G") { - *color = CPWL_Color(COLORTYPE_GRAY, (FX_FLOAT)d1); - } else if (sSpace == "RGB") { - *color = - CPWL_Color(COLORTYPE_RGB, (FX_FLOAT)d1, (FX_FLOAT)d2, (FX_FLOAT)d3); - } else if (sSpace == "CMYK") { - *color = CPWL_Color(COLORTYPE_CMYK, (FX_FLOAT)d1, (FX_FLOAT)d2, - (FX_FLOAT)d3, (FX_FLOAT)d4); - } -} - -bool color::transparent(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crTransparent); -} - -bool color::black(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crBlack); -} - -bool color::white(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crWhite); -} - -bool color::red(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crRed); -} - -bool color::green(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crGreen); -} - -bool color::blue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crBlue); -} - -bool color::cyan(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crCyan); -} - -bool color::magenta(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crMagenta); -} - -bool color::yellow(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crYellow); -} - -bool color::dkGray(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crDKGray); -} - -bool color::gray(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crGray); -} - -bool color::ltGray(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return PropertyHelper(pRuntime, vp, &m_crLTGray); -} - -bool color::PropertyHelper(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CPWL_Color* var) { - CJS_Array array; - if (vp.IsGetting()) { - ConvertPWLColorToArray(pRuntime, *var, &array); - vp << array; - return true; - } - if (!vp.GetJSValue()->ConvertToArray(pRuntime, array)) - return false; - - ConvertArrayToPWLColor(pRuntime, array, var); - return true; -} - -bool color::convert(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int iSize = params.size(); - if (iSize < 2) - return false; - - CJS_Array aSource; - if (!params[0].ConvertToArray(pRuntime, aSource)) - return false; - - CPWL_Color crSource; - ConvertArrayToPWLColor(pRuntime, aSource, &crSource); - - CFX_ByteString sDestSpace = params[1].ToCFXByteString(pRuntime); - int nColorType = COLORTYPE_TRANSPARENT; - - if (sDestSpace == "T") { - nColorType = COLORTYPE_TRANSPARENT; - } else if (sDestSpace == "G") { - nColorType = COLORTYPE_GRAY; - } else if (sDestSpace == "RGB") { - nColorType = COLORTYPE_RGB; - } else if (sDestSpace == "CMYK") { - nColorType = COLORTYPE_CMYK; - } - - CJS_Array aDest; - CPWL_Color crDest = crSource.ConvertColorType(nColorType); - ConvertPWLColorToArray(pRuntime, crDest, &aDest); - vRet = CJS_Value(pRuntime, aDest); - - return true; -} - -bool color::equal(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 2) - return false; - - CJS_Array array1; - CJS_Array array2; - if (!params[0].ConvertToArray(pRuntime, array1)) - return false; - if (!params[1].ConvertToArray(pRuntime, array2)) - return false; - - CPWL_Color color1; - CPWL_Color color2; - ConvertArrayToPWLColor(pRuntime, array1, &color1); - ConvertArrayToPWLColor(pRuntime, array2, &color2); - color1 = color1.ConvertColorType(color2.nColorType); - vRet = CJS_Value(pRuntime, color1 == color2); - return true; -} diff --git a/fpdfsdk/javascript/color.h b/fpdfsdk/javascript/color.h deleted file mode 100644 index 8d6187a17844c3c8b26ded0821a617636b2bd6c7..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/color.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_COLOR_H_ -#define FPDFSDK_JAVASCRIPT_COLOR_H_ - -#include - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class color : public CJS_EmbedObj { - public: - explicit color(CJS_Object* pJSObject); - ~color() override; - - bool black(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool blue(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool cyan(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool dkGray(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool gray(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool green(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool ltGray(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool magenta(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool red(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool transparent(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool white(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool yellow(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - - bool convert(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool equal(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - - static void ConvertPWLColorToArray(CJS_Runtime* pRuntime, - const CPWL_Color& color, - CJS_Array* array); - static void ConvertArrayToPWLColor(CJS_Runtime* pRuntime, - const CJS_Array& array, - CPWL_Color* color); - - private: - bool PropertyHelper(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CPWL_Color* val); - - CPWL_Color m_crTransparent; - CPWL_Color m_crBlack; - CPWL_Color m_crWhite; - CPWL_Color m_crRed; - CPWL_Color m_crGreen; - CPWL_Color m_crBlue; - CPWL_Color m_crCyan; - CPWL_Color m_crMagenta; - CPWL_Color m_crYellow; - CPWL_Color m_crDKGray; - CPWL_Color m_crGray; - CPWL_Color m_crLTGray; -}; - -class CJS_Color : public CJS_Object { - public: - explicit CJS_Color(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Color() override {} - - DECLARE_JS_CLASS(); - - JS_STATIC_PROP(black, color); - JS_STATIC_PROP(blue, color); - JS_STATIC_PROP(cyan, color); - JS_STATIC_PROP(dkGray, color); - JS_STATIC_PROP(gray, color); - JS_STATIC_PROP(green, color); - JS_STATIC_PROP(ltGray, color); - JS_STATIC_PROP(magenta, color); - JS_STATIC_PROP(red, color); - JS_STATIC_PROP(transparent, color); - JS_STATIC_PROP(white, color); - JS_STATIC_PROP(yellow, color); - - JS_STATIC_METHOD(convert, color); - JS_STATIC_METHOD(equal, color); -}; - -#endif // FPDFSDK_JAVASCRIPT_COLOR_H_ diff --git a/fpdfsdk/javascript/console.cpp b/fpdfsdk/javascript/console.cpp deleted file mode 100644 index e9d130820fe4dbef74a370cd0b0748e9e998f563..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/console.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/console.h" - -#include - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" - -JSConstSpec CJS_Console::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Console::PropertySpecs[] = {{0, 0, 0}}; - -JSMethodSpec CJS_Console::MethodSpecs[] = {{"clear", clear_static}, - {"hide", hide_static}, - {"println", println_static}, - {"show", show_static}, - {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Console, console) - -console::console(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} - -console::~console() {} - -bool console::clear(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool console::hide(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} - -bool console::println(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 1) { - return false; - } - return true; -} - -bool console::show(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - return true; -} diff --git a/fpdfsdk/javascript/console.h b/fpdfsdk/javascript/console.h deleted file mode 100644 index a7e4d8ed9bd41e183411cfb240304adfc2b6e919..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/console.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_CONSOLE_H_ -#define FPDFSDK_JAVASCRIPT_CONSOLE_H_ - -#include - -#include "fpdfsdk/javascript/JS_Define.h" - -class console : public CJS_EmbedObj { - public: - explicit console(CJS_Object* pJSObject); - ~console() override; - - public: - bool clear(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool hide(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool println(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool show(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); -}; - -class CJS_Console : public CJS_Object { - public: - explicit CJS_Console(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Console() override {} - - DECLARE_JS_CLASS(); - - JS_STATIC_METHOD(clear, console); - JS_STATIC_METHOD(hide, console); - JS_STATIC_METHOD(println, console); - JS_STATIC_METHOD(show, console); -}; - -#endif // FPDFSDK_JAVASCRIPT_CONSOLE_H_ diff --git a/fpdfsdk/javascript/event.cpp b/fpdfsdk/javascript/event.cpp deleted file mode 100644 index 2b00cbc10e326389e026469da597e34e8b8b120f..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/event.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/event.h" - -#include "fpdfsdk/javascript/Field.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" - -JSConstSpec CJS_Event::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Event::PropertySpecs[] = { - {"change", get_change_static, set_change_static}, - {"changeEx", get_changeEx_static, set_changeEx_static}, - {"commitKey", get_commitKey_static, set_commitKey_static}, - {"fieldFull", get_fieldFull_static, set_fieldFull_static}, - {"keyDown", get_keyDown_static, set_keyDown_static}, - {"modifier", get_modifier_static, set_modifier_static}, - {"name", get_name_static, set_name_static}, - {"rc", get_rc_static, set_rc_static}, - {"richChange", get_richChange_static, set_richChange_static}, - {"richChangeEx", get_richChangeEx_static, set_richChangeEx_static}, - {"richValue", get_richValue_static, set_richValue_static}, - {"selEnd", get_selEnd_static, set_selEnd_static}, - {"selStart", get_selStart_static, set_selStart_static}, - {"shift", get_shift_static, set_shift_static}, - {"source", get_source_static, set_source_static}, - {"target", get_target_static, set_target_static}, - {"targetName", get_targetName_static, set_targetName_static}, - {"type", get_type_static, set_type_static}, - {"value", get_value_static, set_value_static}, - {"willCommit", get_willCommit_static, set_willCommit_static}, - {0, 0, 0}}; - -JSMethodSpec CJS_Event::MethodSpecs[] = {{0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Event, event) - -event::event(CJS_Object* pJsObject) : CJS_EmbedObj(pJsObject) {} - -event::~event() {} - -bool event::change(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - CFX_WideString& wChange = pEvent->Change(); - if (vp.IsSetting()) { - if (vp.GetJSValue()->GetType() == CJS_Value::VT_string) - vp >> wChange; - return true; - } - vp << wChange; - return true; -} - -bool event::changeEx(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->ChangeEx(); - return true; -} - -bool event::commitKey(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->CommitKey(); - return true; -} - -bool event::fieldFull(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - if (!vp.IsGetting() && - wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) - return false; - - vp << pEvent->FieldFull(); - return true; -} - -bool event::keyDown(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->KeyDown(); - return true; -} - -bool event::modifier(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->Modifier(); - return true; -} - -bool event::name(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->Name(); - return true; -} - -bool event::rc(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - bool& bRc = pEvent->Rc(); - if (vp.IsSetting()) - vp >> bRc; - else - vp << bRc; - - return true; -} - -bool event::richChange(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool event::richChangeEx(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool event::richValue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - return true; -} - -bool event::selEnd(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) - return true; - - int& iSelEnd = pEvent->SelEnd(); - if (vp.IsSetting()) - vp >> iSelEnd; - else - vp << iSelEnd; - - return true; -} - -bool event::selStart(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) - return true; - - int& iSelStart = pEvent->SelStart(); - if (vp.IsSetting()) - vp >> iSelStart; - else - vp << iSelStart; - - return true; -} - -bool event::shift(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->Shift(); - return true; -} - -bool event::source(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->Source()->GetJSObject(); - return true; -} - -bool event::target(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->Target_Field()->GetJSObject(); - return true; -} - -bool event::targetName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->TargetName(); - return true; -} - -bool event::type(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->Type(); - return true; -} - -bool event::value(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - if (wcscmp((const wchar_t*)pEvent->Type(), L"Field") != 0) - return false; - - if (!pEvent->m_pValue) - return false; - - CFX_WideString& val = pEvent->Value(); - if (vp.IsSetting()) - vp >> val; - else - vp << val; - - return true; -} - -bool event::willCommit(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (!vp.IsGetting()) - return false; - - CJS_EventHandler* pEvent = - pRuntime->GetCurrentEventContext()->GetEventHandler(); - - vp << pEvent->WillCommit(); - return true; -} diff --git a/fpdfsdk/javascript/event.h b/fpdfsdk/javascript/event.h deleted file mode 100644 index 2be8a0adb2d455b87323841dbdc3539056dbdeed..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/event.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_EVENT_H_ -#define FPDFSDK_JAVASCRIPT_EVENT_H_ - -#include "fpdfsdk/javascript/JS_Define.h" - -class event : public CJS_EmbedObj { - public: - explicit event(CJS_Object* pJSObject); - ~event() override; - - public: - bool change(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool changeEx(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool commitKey(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool fieldFull(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool keyDown(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool modifier(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool rc(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool richChange(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool richChangeEx(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool richValue(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool selEnd(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool selStart(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool shift(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool source(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool target(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool targetName(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); - bool type(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool value(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError); - bool willCommit(CJS_Runtime* pRuntime, - CJS_PropValue& vp, - CFX_WideString& sError); -}; - -class CJS_Event : public CJS_Object { - public: - explicit CJS_Event(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Event() override {} - - DECLARE_JS_CLASS(); - JS_STATIC_PROP(change, event); - JS_STATIC_PROP(changeEx, event); - JS_STATIC_PROP(commitKey, event); - JS_STATIC_PROP(fieldFull, event); - JS_STATIC_PROP(keyDown, event); - JS_STATIC_PROP(modifier, event); - JS_STATIC_PROP(name, event); - JS_STATIC_PROP(rc, event); - JS_STATIC_PROP(richChange, event); - JS_STATIC_PROP(richChangeEx, event); - JS_STATIC_PROP(richValue, event); - JS_STATIC_PROP(selEnd, event); - JS_STATIC_PROP(selStart, event); - JS_STATIC_PROP(shift, event); - JS_STATIC_PROP(source, event); - JS_STATIC_PROP(target, event); - JS_STATIC_PROP(targetName, event); - JS_STATIC_PROP(type, event); - JS_STATIC_PROP(value, event); - JS_STATIC_PROP(willCommit, event); -}; - -#endif // FPDFSDK_JAVASCRIPT_EVENT_H_ diff --git a/fpdfsdk/javascript/global.cpp b/fpdfsdk/javascript/global.cpp deleted file mode 100644 index a450606b1a476bd60561d7af1b4925dc63b7dee0..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/global.cpp +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/global.h" - -#include - -#include "core/fxcrt/fx_ext.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_GlobalData.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/resource.h" - -JSConstSpec CJS_Global::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Global::PropertySpecs[] = {{0, 0, 0}}; - -JSMethodSpec CJS_Global::MethodSpecs[] = { - {"setPersistent", setPersistent_static}, - {0, 0}}; - -IMPLEMENT_SPECIAL_JS_CLASS(CJS_Global, JSGlobalAlternate, global); - -void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) { - CJS_Runtime* pRuntime = static_cast(pIRuntime); - JSGlobalAlternate* pGlobal = - static_cast(GetEmbedObject()); - pGlobal->Initial(pRuntime->GetFormFillEnv()); -} - -JSGlobalData::JSGlobalData() - : nType(JS_GlobalDataType::NUMBER), - dData(0), - bData(false), - sData(""), - bPersistent(false), - bDeleted(false) {} - -JSGlobalData::~JSGlobalData() { - pData.Reset(); -} - -JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject) - : CJS_EmbedObj(pJSObject), m_pFormFillEnv(nullptr) {} - -JSGlobalAlternate::~JSGlobalAlternate() { - DestroyGlobalPersisitentVariables(); - m_pGlobalData->Release(); -} - -void JSGlobalAlternate::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) { - m_pFormFillEnv.Reset(pFormFillEnv); - m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv); - UpdateGlobalPersistentVariables(); -} - -bool JSGlobalAlternate::QueryProperty(const FX_WCHAR* propname) { - return CFX_WideString(propname) != L"setPersistent"; -} - -bool JSGlobalAlternate::DelProperty(CJS_Runtime* pRuntime, - const FX_WCHAR* propname, - CFX_WideString& sError) { - auto it = m_mapGlobal.find(CFX_ByteString::FromUnicode(propname)); - if (it == m_mapGlobal.end()) - return false; - - it->second->bDeleted = true; - return true; -} - -bool JSGlobalAlternate::DoProperty(CJS_Runtime* pRuntime, - const FX_WCHAR* propname, - CJS_PropValue& vp, - CFX_WideString& sError) { - if (vp.IsSetting()) { - CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname); - switch (vp.GetJSValue()->GetType()) { - case CJS_Value::VT_number: { - double dData; - vp >> dData; - return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER, dData, - false, "", v8::Local(), false); - } - case CJS_Value::VT_boolean: { - bool bData; - vp >> bData; - return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0, - bData, "", v8::Local(), false); - } - case CJS_Value::VT_string: { - CFX_ByteString sData; - vp >> sData; - return SetGlobalVariables(sPropName, JS_GlobalDataType::STRING, 0, - false, sData, v8::Local(), false); - } - case CJS_Value::VT_object: { - v8::Local pData; - vp >> pData; - return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, - false, "", pData, false); - } - case CJS_Value::VT_null: { - return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, - false, "", v8::Local(), false); - } - case CJS_Value::VT_undefined: { - DelProperty(pRuntime, propname, sError); - return true; - } - default: - break; - } - } else { - auto it = m_mapGlobal.find(CFX_ByteString::FromUnicode(propname)); - if (it == m_mapGlobal.end()) { - vp.GetJSValue()->SetNull(pRuntime); - return true; - } - JSGlobalData* pData = it->second; - if (pData->bDeleted) { - vp.GetJSValue()->SetNull(pRuntime); - return true; - } - switch (pData->nType) { - case JS_GlobalDataType::NUMBER: - vp << pData->dData; - return true; - case JS_GlobalDataType::BOOLEAN: - vp << pData->bData; - return true; - case JS_GlobalDataType::STRING: - vp << pData->sData; - return true; - case JS_GlobalDataType::OBJECT: { - v8::Local obj = v8::Local::New( - vp.GetJSRuntime()->GetIsolate(), pData->pData); - vp << obj; - return true; - } - case JS_GlobalDataType::NULLOBJ: - vp.GetJSValue()->SetNull(pRuntime); - return true; - default: - break; - } - } - return false; -} - -bool JSGlobalAlternate::setPersistent(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() != 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - auto it = m_mapGlobal.find(params[0].ToCFXByteString(pRuntime)); - if (it != m_mapGlobal.end()) { - JSGlobalData* pData = it->second; - if (!pData->bDeleted) { - pData->bPersistent = params[1].ToBool(pRuntime); - return true; - } - } - - sError = JSGetStringFromID(IDS_STRING_JSNOGLOBAL); - return false; -} - -void JSGlobalAlternate::UpdateGlobalPersistentVariables() { - CJS_Runtime* pRuntime = - static_cast(CFXJS_Engine::CurrentEngineFromIsolate( - m_pJSObject->ToV8Object()->GetIsolate())); - - for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) { - CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i); - switch (pData->data.nType) { - case JS_GlobalDataType::NUMBER: - SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER, - pData->data.dData, false, "", - v8::Local(), pData->bPersistent == 1); - pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(), - pData->data.sKey.UTF8Decode(), - pRuntime->NewNumber(pData->data.dData)); - break; - case JS_GlobalDataType::BOOLEAN: - SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0, - pData->data.bData == 1, "", v8::Local(), - pData->bPersistent == 1); - pRuntime->PutObjectProperty( - m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(), - pRuntime->NewBoolean(pData->data.bData == 1)); - break; - case JS_GlobalDataType::STRING: - SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0, - false, pData->data.sData, v8::Local(), - pData->bPersistent == 1); - pRuntime->PutObjectProperty( - m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(), - pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringC())); - break; - case JS_GlobalDataType::OBJECT: { - v8::Local pObj = pRuntime->NewFxDynamicObj(-1); - PutObjectProperty(pObj, &pData->data); - SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0, - false, "", pObj, pData->bPersistent == 1); - pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(), - pData->data.sKey.UTF8Decode(), pObj); - } break; - case JS_GlobalDataType::NULLOBJ: - SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0, - false, "", v8::Local(), - pData->bPersistent == 1); - pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(), - pData->data.sKey.UTF8Decode(), - pRuntime->NewNull()); - break; - } - } -} - -void JSGlobalAlternate::CommitGlobalPersisitentVariables( - CJS_Runtime* pRuntime) { - for (auto it = m_mapGlobal.begin(); it != m_mapGlobal.end(); ++it) { - CFX_ByteString name = it->first; - JSGlobalData* pData = it->second; - if (pData->bDeleted) { - m_pGlobalData->DeleteGlobalVariable(name); - } else { - switch (pData->nType) { - case JS_GlobalDataType::NUMBER: - m_pGlobalData->SetGlobalVariableNumber(name, pData->dData); - m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); - break; - case JS_GlobalDataType::BOOLEAN: - m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData); - m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); - break; - case JS_GlobalDataType::STRING: - m_pGlobalData->SetGlobalVariableString(name, pData->sData); - m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); - break; - case JS_GlobalDataType::OBJECT: { - CJS_GlobalVariableArray array; - v8::Local obj = v8::Local::New( - GetJSObject()->GetIsolate(), pData->pData); - ObjectToArray(pRuntime, obj, array); - m_pGlobalData->SetGlobalVariableObject(name, array); - m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); - } break; - case JS_GlobalDataType::NULLOBJ: - m_pGlobalData->SetGlobalVariableNull(name); - m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); - break; - } - } - } -} - -void JSGlobalAlternate::ObjectToArray(CJS_Runtime* pRuntime, - v8::Local pObj, - CJS_GlobalVariableArray& array) { - std::vector pKeyList = pRuntime->GetObjectPropertyNames(pObj); - for (const auto& ws : pKeyList) { - CFX_ByteString sKey = ws.UTF8Encode(); - v8::Local v = pRuntime->GetObjectProperty(pObj, ws); - switch (CJS_Value::GetValueType(v)) { - case CJS_Value::VT_number: { - CJS_KeyValue* pObjElement = new CJS_KeyValue; - pObjElement->nType = JS_GlobalDataType::NUMBER; - pObjElement->sKey = sKey; - pObjElement->dData = pRuntime->ToDouble(v); - array.Add(pObjElement); - } break; - case CJS_Value::VT_boolean: { - CJS_KeyValue* pObjElement = new CJS_KeyValue; - pObjElement->nType = JS_GlobalDataType::BOOLEAN; - pObjElement->sKey = sKey; - pObjElement->dData = pRuntime->ToBoolean(v); - array.Add(pObjElement); - } break; - case CJS_Value::VT_string: { - CFX_ByteString sValue = - CJS_Value(pRuntime, v).ToCFXByteString(pRuntime); - CJS_KeyValue* pObjElement = new CJS_KeyValue; - pObjElement->nType = JS_GlobalDataType::STRING; - pObjElement->sKey = sKey; - pObjElement->sData = sValue; - array.Add(pObjElement); - } break; - case CJS_Value::VT_object: { - CJS_KeyValue* pObjElement = new CJS_KeyValue; - pObjElement->nType = JS_GlobalDataType::OBJECT; - pObjElement->sKey = sKey; - ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData); - array.Add(pObjElement); - } break; - case CJS_Value::VT_null: { - CJS_KeyValue* pObjElement = new CJS_KeyValue; - pObjElement->nType = JS_GlobalDataType::NULLOBJ; - pObjElement->sKey = sKey; - array.Add(pObjElement); - } break; - default: - break; - } - } -} - -void JSGlobalAlternate::PutObjectProperty(v8::Local pObj, - CJS_KeyValue* pData) { - CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate( - m_pJSObject->ToV8Object()->GetIsolate()); - - for (int i = 0, sz = pData->objData.Count(); i < sz; i++) { - CJS_KeyValue* pObjData = pData->objData.GetAt(i); - switch (pObjData->nType) { - case JS_GlobalDataType::NUMBER: - pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), - pRuntime->NewNumber(pObjData->dData)); - break; - case JS_GlobalDataType::BOOLEAN: - pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), - pRuntime->NewBoolean(pObjData->bData == 1)); - break; - case JS_GlobalDataType::STRING: - pRuntime->PutObjectProperty( - pObj, pObjData->sKey.UTF8Decode(), - pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringC())); - break; - case JS_GlobalDataType::OBJECT: { - v8::Local pNewObj = pRuntime->NewFxDynamicObj(-1); - PutObjectProperty(pNewObj, pObjData); - pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), pNewObj); - } break; - case JS_GlobalDataType::NULLOBJ: - pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), - pRuntime->NewNull()); - break; - } - } -} - -void JSGlobalAlternate::DestroyGlobalPersisitentVariables() { - for (const auto& pair : m_mapGlobal) { - delete pair.second; - } - m_mapGlobal.clear(); -} - -bool JSGlobalAlternate::SetGlobalVariables(const CFX_ByteString& propname, - JS_GlobalDataType nType, - double dData, - bool bData, - const CFX_ByteString& sData, - v8::Local pData, - bool bDefaultPersistent) { - if (propname.IsEmpty()) - return false; - - auto it = m_mapGlobal.find(propname); - if (it != m_mapGlobal.end()) { - JSGlobalData* pTemp = it->second; - if (pTemp->bDeleted || pTemp->nType != nType) { - pTemp->dData = 0; - pTemp->bData = 0; - pTemp->sData = ""; - pTemp->nType = nType; - } - - pTemp->bDeleted = false; - switch (nType) { - case JS_GlobalDataType::NUMBER: { - pTemp->dData = dData; - } break; - case JS_GlobalDataType::BOOLEAN: { - pTemp->bData = bData; - } break; - case JS_GlobalDataType::STRING: { - pTemp->sData = sData; - } break; - case JS_GlobalDataType::OBJECT: { - pTemp->pData.Reset(pData->GetIsolate(), pData); - } break; - case JS_GlobalDataType::NULLOBJ: - break; - default: - return false; - } - return true; - } - - JSGlobalData* pNewData = nullptr; - - switch (nType) { - case JS_GlobalDataType::NUMBER: { - pNewData = new JSGlobalData; - pNewData->nType = JS_GlobalDataType::NUMBER; - pNewData->dData = dData; - pNewData->bPersistent = bDefaultPersistent; - } break; - case JS_GlobalDataType::BOOLEAN: { - pNewData = new JSGlobalData; - pNewData->nType = JS_GlobalDataType::BOOLEAN; - pNewData->bData = bData; - pNewData->bPersistent = bDefaultPersistent; - } break; - case JS_GlobalDataType::STRING: { - pNewData = new JSGlobalData; - pNewData->nType = JS_GlobalDataType::STRING; - pNewData->sData = sData; - pNewData->bPersistent = bDefaultPersistent; - } break; - case JS_GlobalDataType::OBJECT: { - pNewData = new JSGlobalData; - pNewData->nType = JS_GlobalDataType::OBJECT; - pNewData->pData.Reset(pData->GetIsolate(), pData); - pNewData->bPersistent = bDefaultPersistent; - } break; - case JS_GlobalDataType::NULLOBJ: { - pNewData = new JSGlobalData; - pNewData->nType = JS_GlobalDataType::NULLOBJ; - pNewData->bPersistent = bDefaultPersistent; - } break; - default: - return false; - } - - m_mapGlobal[propname] = pNewData; - return true; -} diff --git a/fpdfsdk/javascript/global.h b/fpdfsdk/javascript/global.h deleted file mode 100644 index e313929beacf7d9b2fbb23669c7d08c335b3449f..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/global.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_GLOBAL_H_ -#define FPDFSDK_JAVASCRIPT_GLOBAL_H_ - -#include -#include - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_KeyValue.h" - -class CJS_GlobalData; -class CJS_GlobalVariableArray; -class CJS_KeyValue; - -struct JSGlobalData { - JSGlobalData(); - ~JSGlobalData(); - - JS_GlobalDataType nType; - double dData; - bool bData; - CFX_ByteString sData; - v8::Global pData; - bool bPersistent; - bool bDeleted; -}; - -class JSGlobalAlternate : public CJS_EmbedObj { - public: - explicit JSGlobalAlternate(CJS_Object* pJSObject); - ~JSGlobalAlternate() override; - - bool setPersistent(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool QueryProperty(const FX_WCHAR* propname); - bool DoProperty(CJS_Runtime* pRuntime, - const FX_WCHAR* propname, - CJS_PropValue& vp, - CFX_WideString& sError); - bool DelProperty(CJS_Runtime* pRuntime, - const FX_WCHAR* propname, - CFX_WideString& sError); - void Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv); - - private: - void UpdateGlobalPersistentVariables(); - void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime); - void DestroyGlobalPersisitentVariables(); - bool SetGlobalVariables(const CFX_ByteString& propname, - JS_GlobalDataType nType, - double dData, - bool bData, - const CFX_ByteString& sData, - v8::Local pData, - bool bDefaultPersistent); - void ObjectToArray(CJS_Runtime* pRuntime, - v8::Local pObj, - CJS_GlobalVariableArray& array); - void PutObjectProperty(v8::Local obj, CJS_KeyValue* pData); - - std::map m_mapGlobal; - CFX_WideString m_sFilePath; - CJS_GlobalData* m_pGlobalData; - CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; -}; - -class CJS_Global : public CJS_Object { - public: - explicit CJS_Global(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Global() override {} - - // CJS_Object - void InitInstance(IJS_Runtime* pIRuntime) override; - - DECLARE_SPECIAL_JS_CLASS(); - JS_SPECIAL_STATIC_METHOD(setPersistent, JSGlobalAlternate, global); -}; - -#endif // FPDFSDK_JAVASCRIPT_GLOBAL_H_ diff --git a/fpdfsdk/javascript/ijs_runtime.h b/fpdfsdk/javascript/ijs_runtime.h deleted file mode 100644 index babc41842cf68ff0df1443c098357ca9108869ca..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/ijs_runtime.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2016 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 FPDFSDK_JAVASCRIPT_IJS_RUNTIME_H_ -#define FPDFSDK_JAVASCRIPT_IJS_RUNTIME_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" - -#ifdef PDF_ENABLE_XFA -#include "fxjs/fxjse.h" -#endif // PDF_ENABLE_XFA - -class CPDFSDK_FormFillEnvironment; -class IJS_EventContext; - -// Owns the FJXS objects needed to actually execute JS. -class IJS_Runtime { - public: - static void Initialize(unsigned int slot, void* isolate); - static void Destroy(); - static IJS_Runtime* Create(CPDFSDK_FormFillEnvironment* pFormFillEnv); - virtual ~IJS_Runtime() {} - - virtual IJS_EventContext* NewEventContext() = 0; - virtual void ReleaseEventContext(IJS_EventContext* pContext) = 0; - virtual CPDFSDK_FormFillEnvironment* GetFormFillEnv() const = 0; - virtual int ExecuteScript(const CFX_WideString& script, - CFX_WideString* info) = 0; - -#ifdef PDF_ENABLE_XFA - virtual bool GetValueByName(const CFX_ByteStringC& utf8Name, - CFXJSE_Value* pValue) = 0; - virtual bool SetValueByName(const CFX_ByteStringC& utf8Name, - CFXJSE_Value* pValue) = 0; -#endif // PDF_ENABLE_XFA - - protected: - IJS_Runtime() {} -}; - -#endif // FPDFSDK_JAVASCRIPT_IJS_RUNTIME_H_ diff --git a/fpdfsdk/javascript/public_methods_embeddertest.cpp b/fpdfsdk/javascript/public_methods_embeddertest.cpp deleted file mode 100644 index 24793667b07008f6e83ea4b38b5f0013256032df..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/public_methods_embeddertest.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2015 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. - -#include - -#include "core/fxcrt/fx_string.h" -#include "fpdfsdk/javascript/PublicMethods.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/js_embedder_test.h" - -namespace { - -double RoundDownDate(double date) { - return date - fmod(date, 86400000); -} - -} // namespace - -class PublicMethodsEmbedderTest : public JSEmbedderTest {}; - -TEST_F(PublicMethodsEmbedderTest, MakeRegularDate) { - v8::Isolate::Scope isolate_scope(isolate()); - v8::HandleScope handle_scope(isolate()); - v8::Context::Scope context_scope(GetV8Context()); - bool bWrongFormat; - double date; - - // 1968 - bWrongFormat = false; - date = CJS_PublicMethods::MakeRegularDate(L"06/25/1968", L"mm/dd/yyyy", - &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(-47865600000, date); - EXPECT_FALSE(bWrongFormat); - - // 1968 - bWrongFormat = false; - date = CJS_PublicMethods::MakeRegularDate(L"25061968", L"ddmmyyyy", - &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(-47865600000, date); - EXPECT_FALSE(bWrongFormat); - - // 1968 - bWrongFormat = false; - date = CJS_PublicMethods::MakeRegularDate(L"19680625", L"yyyymmdd", - &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(-47865600000, date); - EXPECT_FALSE(bWrongFormat); - - // 1985 - bWrongFormat = false; - date = CJS_PublicMethods::MakeRegularDate(L"31121985", L"ddmmyyyy", - &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(504835200000.0, date); - EXPECT_FALSE(bWrongFormat); - - // 2085, the other '85. - bWrongFormat = false; - date = - CJS_PublicMethods::MakeRegularDate(L"311285", L"ddmmyy", &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(3660595200000.0, date); - EXPECT_FALSE(bWrongFormat); - - // 1995 - bWrongFormat = false; - date = CJS_PublicMethods::MakeRegularDate(L"01021995", L"ddmmyyyy", - &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(791596800000.0, date); - EXPECT_FALSE(bWrongFormat); - - // 2095, the other '95. - bWrongFormat = false; - date = - CJS_PublicMethods::MakeRegularDate(L"010295", L"ddmmyy", &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(3947356800000.0, date); - EXPECT_FALSE(bWrongFormat); - - // 2005 - bWrongFormat = false; - date = CJS_PublicMethods::MakeRegularDate(L"01022005", L"ddmmyyyy", - &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(1107216000000.0, date); - EXPECT_FALSE(bWrongFormat); - - // 2005 - bWrongFormat = false; - date = - CJS_PublicMethods::MakeRegularDate(L"010205", L"ddmmyy", &bWrongFormat); - date = RoundDownDate(date); - EXPECT_DOUBLE_EQ(1107216000000.0, date); - EXPECT_FALSE(bWrongFormat); -} - -TEST_F(PublicMethodsEmbedderTest, MakeFormatDate) { - v8::Isolate::Scope isolate_scope(isolate()); - v8::HandleScope handle_scope(isolate()); - v8::Context::Scope context_scope(GetV8Context()); - CFX_WideString formatted_date; - - // 1968-06-25 - formatted_date = CJS_PublicMethods::MakeFormatDate(-47952000000, L"ddmmyy"); - EXPECT_STREQ(L"250668", formatted_date.c_str()); - formatted_date = CJS_PublicMethods::MakeFormatDate(-47952000000, L"yy/mm/dd"); - EXPECT_STREQ(L"68/06/25", formatted_date.c_str()); - - // 1969-12-31 - formatted_date = CJS_PublicMethods::MakeFormatDate(-0.0001, L"ddmmyy"); - EXPECT_STREQ(L"311269", formatted_date.c_str()); - formatted_date = CJS_PublicMethods::MakeFormatDate(-0.0001, L"yy!mmdd"); - EXPECT_STREQ(L"69!1231", formatted_date.c_str()); - - // 1970-01-01 - formatted_date = CJS_PublicMethods::MakeFormatDate(0, L"ddmmyy"); - EXPECT_STREQ(L"010170", formatted_date.c_str()); - formatted_date = CJS_PublicMethods::MakeFormatDate(0, L"mm-yyyy-dd"); - EXPECT_STREQ(L"01-1970-01", formatted_date.c_str()); - - // 1985-12-31 - formatted_date = CJS_PublicMethods::MakeFormatDate(504835200000.0, L"ddmmyy"); - EXPECT_STREQ(L"311285", formatted_date.c_str()); - formatted_date = CJS_PublicMethods::MakeFormatDate(504835200000.0, L"yymmdd"); - EXPECT_STREQ(L"851231", formatted_date.c_str()); - - // 1995-02-01 - formatted_date = CJS_PublicMethods::MakeFormatDate(791596800000.0, L"ddmmyy"); - EXPECT_STREQ(L"010295", formatted_date.c_str()); - formatted_date = - CJS_PublicMethods::MakeFormatDate(791596800000.0, L"yyyymmdd"); - EXPECT_STREQ(L"19950201", formatted_date.c_str()); - - // 2005-02-01 - formatted_date = - CJS_PublicMethods::MakeFormatDate(1107216000000.0, L"ddmmyy"); - EXPECT_STREQ(L"010205", formatted_date.c_str()); - formatted_date = - CJS_PublicMethods::MakeFormatDate(1107216000000.0, L"yyyyddmm"); - EXPECT_STREQ(L"20050102", formatted_date.c_str()); - - // 2085-12-31 - formatted_date = - CJS_PublicMethods::MakeFormatDate(3660595200000.0, L"ddmmyy"); - EXPECT_STREQ(L"311285", formatted_date.c_str()); - formatted_date = - CJS_PublicMethods::MakeFormatDate(3660595200000.0, L"yyyydd"); - EXPECT_STREQ(L"208531", formatted_date.c_str()); - - // 2095-02-01 - formatted_date = - CJS_PublicMethods::MakeFormatDate(3947356800000.0, L"ddmmyy"); - EXPECT_STREQ(L"010295", formatted_date.c_str()); - formatted_date = - CJS_PublicMethods::MakeFormatDate(3947356800000.0, L"mmddyyyy"); - EXPECT_STREQ(L"02012095", formatted_date.c_str()); -} diff --git a/fpdfsdk/javascript/public_methods_unittest.cpp b/fpdfsdk/javascript/public_methods_unittest.cpp deleted file mode 100644 index ace0920e8f749faaaf23088c551f5957c7170f63..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/public_methods_unittest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 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. - -#include "fpdfsdk/javascript/PublicMethods.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/test_support.h" - -TEST(CJS_PublicMethods, IsNumber) { - // TODO(weili): Check whether results from case 0, 1, 10, 15 are intended. - struct { - const wchar_t* input; - bool expected; - } test_data[] = { - // Empty string. - {L"", true}, - // Only whitespaces. - {L" ", true}, - // Content with invalid characters. - {L"xyz00", false}, - {L"1%", false}, - // Hex string. - {L"0x234", false}, - // Signed numbers. - {L"+123", true}, - {L"-98765", true}, - // Numbers with whitespaces. - {L" 345 ", true}, - // Float numbers. - {L"-1e5", false}, - {L"-2e", false}, - {L"e-5", true}, - {L"0.023", true}, - {L".356089", true}, - {L"1e-9", true}, - {L"-1.23e+23", true}, - // Numbers with commas. - {L"1,000,000", false}, - {L"560,024", true}, - // Regular numbers. - {L"0", true}, - {L"0123", true}, - {L"9876123", true}, - }; - for (size_t i = 0; i < FX_ArraySize(test_data); ++i) { - EXPECT_EQ(test_data[i].expected, - CJS_PublicMethods::IsNumber(test_data[i].input)) - << "for case " << i; - } -} diff --git a/fpdfsdk/javascript/report.cpp b/fpdfsdk/javascript/report.cpp deleted file mode 100644 index c9c986d19552fd06bd545baa2c93702d7868f7f0..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/report.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/report.h" - -#include - -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" - -JSConstSpec CJS_Report::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Report::PropertySpecs[] = {{0, 0, 0}}; - -JSMethodSpec CJS_Report::MethodSpecs[] = {{"save", save_static}, - {"writeText", writeText_static}, - {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Report, Report) - -Report::Report(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} - -Report::~Report() {} - -bool Report::writeText(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} - -bool Report::save(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - // Unsafe, not supported. - return true; -} diff --git a/fpdfsdk/javascript/report.h b/fpdfsdk/javascript/report.h deleted file mode 100644 index c66db80fd1c24947dd3797b81009676a3da97fc4..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/report.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_REPORT_H_ -#define FPDFSDK_JAVASCRIPT_REPORT_H_ - -#include - -#include "fpdfsdk/javascript/JS_Define.h" - -class Report : public CJS_EmbedObj { - public: - explicit Report(CJS_Object* pJSObject); - ~Report() override; - - public: - bool save(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool writeText(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); -}; - -class CJS_Report : public CJS_Object { - public: - explicit CJS_Report(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Report() override {} - - DECLARE_JS_CLASS(); - - JS_STATIC_METHOD(save, Report) - JS_STATIC_METHOD(writeText, Report); -}; - -#endif // FPDFSDK_JAVASCRIPT_REPORT_H_ diff --git a/fpdfsdk/javascript/resource.cpp b/fpdfsdk/javascript/resource.cpp deleted file mode 100644 index 6113c5433856cfa5661f3ce78eb089ddcd38ccfc..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/resource.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/resource.h" - -CFX_WideString JSGetStringFromID(uint32_t id) { - switch (id) { - case IDS_STRING_JSALERT: - return L"Alert"; - case IDS_STRING_JSPARAMERROR: - return L"Incorrect number of parameters passed to function."; - case IDS_STRING_JSAFNUMBER_KEYSTROKE: - return L"The input value is invalid."; - case IDS_STRING_JSPARAM_TOOLONG: - return L"The input value is too long."; - case IDS_STRING_JSPARSEDATE: - return L"The input value can't be parsed as a valid date/time (%s)."; - case IDS_STRING_JSRANGE1: - return L"The input value must be greater than or equal to %s" - L" and less than or equal to %s."; - case IDS_STRING_JSRANGE2: - return L"The input value must be greater than or equal to %s."; - case IDS_STRING_JSRANGE3: - return L"The input value must be less than or equal to %s."; - case IDS_STRING_JSNOTSUPPORT: - return L"Operation not supported."; - case IDS_STRING_JSBUSY: - return L"System is busy."; - case IDS_STRING_JSEVENT: - return L"Duplicate formfield event found."; - case IDS_STRING_RUN: - return L"Script ran successfully."; - case IDS_STRING_JSPRINT1: - return L"The second parameter can't be converted to a Date."; - case IDS_STRING_JSPRINT2: - return L"The second parameter is an invalid Date!"; - case IDS_STRING_JSNOGLOBAL: - return L"Global value not found."; - case IDS_STRING_JSREADONLY: - return L"Cannot assign to readonly property."; - case IDS_STRING_JSTYPEERROR: - return L"Incorrect parameter type."; - case IDS_STRING_JSVALUEERROR: - return L"Incorrect parameter value."; - case IDS_STRING_JSNOPERMISSION: - return L"Permission denied."; - case IDS_STRING_JSBADOBJECT: - return L"Object no longer exists."; - default: - return L""; - } -} - -CFX_WideString JSFormatErrorString(const char* class_name, - const char* property_name, - const CFX_WideString& details) { - CFX_WideString result = CFX_WideString::FromLocal(class_name); - if (property_name) { - result += L"."; - result += CFX_WideString::FromLocal(property_name); - } - result += L": "; - result += details; - return result; -} diff --git a/fpdfsdk/javascript/resource.h b/fpdfsdk/javascript/resource.h deleted file mode 100644 index af7788ff7d3880c96bdd8ada2c7f5878bca33273..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/resource.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_RESOURCE_H_ -#define FPDFSDK_JAVASCRIPT_RESOURCE_H_ - -#include "core/fxcrt/fx_string.h" - -class CJS_EventContext; - -#define IDS_STRING_JSALERT 25613 -#define IDS_STRING_JSPARAMERROR 25614 -#define IDS_STRING_JSAFNUMBER_KEYSTROKE 25615 -#define IDS_STRING_JSPARAM_TOOLONG 25617 -#define IDS_STRING_JSPARSEDATE 25618 -#define IDS_STRING_JSRANGE1 25619 -#define IDS_STRING_JSRANGE2 25620 -#define IDS_STRING_JSRANGE3 25621 -#define IDS_STRING_JSNOTSUPPORT 25627 -#define IDS_STRING_JSBUSY 25628 -#define IDS_STRING_JSEVENT 25629 -#define IDS_STRING_RUN 25630 -#define IDS_STRING_JSPRINT1 25632 -#define IDS_STRING_JSPRINT2 25633 -#define IDS_STRING_JSNOGLOBAL 25635 -#define IDS_STRING_JSREADONLY 25636 -#define IDS_STRING_JSTYPEERROR 25637 -#define IDS_STRING_JSVALUEERROR 25638 -#define IDS_STRING_JSNOPERMISSION 25639 -#define IDS_STRING_JSBADOBJECT 25640 - -CFX_WideString JSGetStringFromID(uint32_t id); -CFX_WideString JSFormatErrorString(const char* class_name, - const char* property_name, - const CFX_WideString& details); - -#endif // FPDFSDK_JAVASCRIPT_RESOURCE_H_ diff --git a/fpdfsdk/javascript/util.cpp b/fpdfsdk/javascript/util.cpp deleted file mode 100644 index 3221cfb0cbb6d2b8828dc8bfeb7e14c6eff16f7e..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/util.cpp +++ /dev/null @@ -1,462 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/javascript/util.h" - -#include - -#include -#include -#include - -#include "core/fxcrt/fx_ext.h" -#include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/JS_Object.h" -#include "fpdfsdk/javascript/JS_Value.h" -#include "fpdfsdk/javascript/PublicMethods.h" -#include "fpdfsdk/javascript/cjs_event_context.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/resource.h" - -#if _FX_OS_ == _FX_ANDROID_ -#include -#endif - -JSConstSpec CJS_Util::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}}; - -JSPropertySpec CJS_Util::PropertySpecs[] = {{0, 0, 0}}; - -JSMethodSpec CJS_Util::MethodSpecs[] = { - {"printd", printd_static}, {"printf", printf_static}, - {"printx", printx_static}, {"scand", scand_static}, - {"byteToChar", byteToChar_static}, {0, 0}}; - -IMPLEMENT_JS_CLASS(CJS_Util, util) - -#define UTIL_INT 0 -#define UTIL_DOUBLE 1 -#define UTIL_STRING 2 - -namespace { - -// Map PDF-style directives to equivalent wcsftime directives. Not -// all have direct equivalents, though. -struct TbConvert { - const FX_WCHAR* lpszJSMark; - const FX_WCHAR* lpszCppMark; -}; - -// Map PDF-style directives lacking direct wcsftime directives to -// the value with which they will be replaced. -struct TbConvertAdditional { - const FX_WCHAR* lpszJSMark; - int iValue; -}; - -const TbConvert TbConvertTable[] = { - {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"}, - {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"}, - {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"}, - {L"TT", L"%p"}, -#if defined(_WIN32) - {L"tt", L"%p"}, {L"h", L"%#I"}, -#else - {L"tt", L"%P"}, {L"h", L"%l"}, -#endif -}; - -int ParseDataType(std::wstring* sFormat) { - bool bPercent = false; - for (size_t i = 0; i < sFormat->length(); ++i) { - wchar_t c = (*sFormat)[i]; - if (c == L'%') { - bPercent = true; - continue; - } - - if (bPercent) { - if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' || - c == L'u' || c == L'x' || c == L'X') { - return UTIL_INT; - } - if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || c == L'G') { - return UTIL_DOUBLE; - } - if (c == L's' || c == L'S') { - // Map s to S since we always deal internally - // with wchar_t strings. - (*sFormat)[i] = L'S'; - return UTIL_STRING; - } - if (c == L'.' || c == L'+' || c == L'-' || c == L'#' || c == L' ' || - FXSYS_iswdigit(c)) { - continue; - } - break; - } - } - - return -1; -} - -} // namespace - -util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} - -util::~util() {} - -bool util::printf(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int iSize = params.size(); - if (iSize < 1) - return false; - std::wstring c_ConvChar(params[0].ToCFXWideString(pRuntime).c_str()); - std::vector c_strConvers; - int iOffset = 0; - int iOffend = 0; - c_ConvChar.insert(c_ConvChar.begin(), L'S'); - while (iOffset != -1) { - iOffend = c_ConvChar.find(L"%", iOffset + 1); - std::wstring strSub; - if (iOffend == -1) - strSub = c_ConvChar.substr(iOffset); - else - strSub = c_ConvChar.substr(iOffset, iOffend - iOffset); - c_strConvers.push_back(strSub); - iOffset = iOffend; - } - - std::wstring c_strResult; - std::wstring c_strFormat; - for (int iIndex = 0; iIndex < (int)c_strConvers.size(); iIndex++) { - c_strFormat = c_strConvers[iIndex]; - if (iIndex == 0) { - c_strResult = c_strFormat; - continue; - } - - CFX_WideString strSegment; - if (iIndex >= iSize) { - c_strResult += c_strFormat; - continue; - } - - switch (ParseDataType(&c_strFormat)) { - case UTIL_INT: - strSegment.Format(c_strFormat.c_str(), params[iIndex].ToInt(pRuntime)); - break; - case UTIL_DOUBLE: - strSegment.Format(c_strFormat.c_str(), - params[iIndex].ToDouble(pRuntime)); - break; - case UTIL_STRING: - strSegment.Format(c_strFormat.c_str(), - params[iIndex].ToCFXWideString(pRuntime).c_str()); - break; - default: - strSegment.Format(L"%S", c_strFormat.c_str()); - break; - } - c_strResult += strSegment.GetBuffer(strSegment.GetLength() + 1); - } - - c_strResult.erase(c_strResult.begin()); - vRet = CJS_Value(pRuntime, c_strResult.c_str()); - return true; -} - -bool util::printd(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int iSize = params.size(); - if (iSize < 2) - return false; - - CJS_Value p1 = params[0]; - CJS_Value p2 = params[1]; - CJS_Date jsDate; - if (!p2.ConvertToDate(pRuntime, jsDate)) { - sError = JSGetStringFromID(IDS_STRING_JSPRINT1); - return false; - } - - if (!jsDate.IsValidDate(pRuntime)) { - sError = JSGetStringFromID(IDS_STRING_JSPRINT2); - return false; - } - - if (p1.GetType() == CJS_Value::VT_number) { - CFX_WideString swResult; - switch (p1.ToInt(pRuntime)) { - case 0: - swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", jsDate.GetYear(pRuntime), - jsDate.GetMonth(pRuntime) + 1, jsDate.GetDay(pRuntime), - jsDate.GetHours(pRuntime), jsDate.GetMinutes(pRuntime), - jsDate.GetSeconds(pRuntime)); - break; - case 1: - swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d", - jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1, - jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime), - jsDate.GetMinutes(pRuntime), - jsDate.GetSeconds(pRuntime)); - break; - case 2: - swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d", - jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1, - jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime), - jsDate.GetMinutes(pRuntime), - jsDate.GetSeconds(pRuntime)); - break; - default: - sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); - return false; - } - - vRet = CJS_Value(pRuntime, swResult.c_str()); - return true; - } - - if (p1.GetType() == CJS_Value::VT_string) { - if (iSize > 2 && params[2].ToBool(pRuntime)) { - sError = JSGetStringFromID(IDS_STRING_JSNOTSUPPORT); - return false; // currently, it doesn't support XFAPicture. - } - - // Convert PDF-style format specifiers to wcsftime specifiers. Remove any - // pre-existing %-directives before inserting our own. - std::basic_string cFormat = p1.ToCFXWideString(pRuntime).c_str(); - cFormat.erase(std::remove(cFormat.begin(), cFormat.end(), '%'), - cFormat.end()); - - for (size_t i = 0; i < FX_ArraySize(TbConvertTable); ++i) { - int iStart = 0; - int iEnd; - while ((iEnd = cFormat.find(TbConvertTable[i].lpszJSMark, iStart)) != - -1) { - cFormat.replace(iEnd, FXSYS_wcslen(TbConvertTable[i].lpszJSMark), - TbConvertTable[i].lpszCppMark); - iStart = iEnd; - } - } - - int iYear = jsDate.GetYear(pRuntime); - int iMonth = jsDate.GetMonth(pRuntime); - int iDay = jsDate.GetDay(pRuntime); - int iHour = jsDate.GetHours(pRuntime); - int iMin = jsDate.GetMinutes(pRuntime); - int iSec = jsDate.GetSeconds(pRuntime); - - TbConvertAdditional cTableAd[] = { - {L"m", iMonth + 1}, {L"d", iDay}, - {L"H", iHour}, {L"h", iHour > 12 ? iHour - 12 : iHour}, - {L"M", iMin}, {L"s", iSec}, - }; - - for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) { - wchar_t tszValue[16]; - CFX_WideString sValue; - sValue.Format(L"%d", cTableAd[i].iValue); - memcpy(tszValue, (wchar_t*)sValue.GetBuffer(sValue.GetLength() + 1), - (sValue.GetLength() + 1) * sizeof(wchar_t)); - - int iStart = 0; - int iEnd; - while ((iEnd = cFormat.find(cTableAd[i].lpszJSMark, iStart)) != -1) { - if (iEnd > 0) { - if (cFormat[iEnd - 1] == L'%') { - iStart = iEnd + 1; - continue; - } - } - cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[i].lpszJSMark), tszValue); - iStart = iEnd; - } - } - - struct tm time = {}; - time.tm_year = iYear - 1900; - time.tm_mon = iMonth; - time.tm_mday = iDay; - time.tm_hour = iHour; - time.tm_min = iMin; - time.tm_sec = iSec; - - wchar_t buf[64] = {}; - wcsftime(buf, 64, cFormat.c_str(), &time); - cFormat = buf; - vRet = CJS_Value(pRuntime, cFormat.c_str()); - return true; - } - - sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR); - return false; -} - -bool util::printx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 2) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - vRet = CJS_Value(pRuntime, printx(params[0].ToCFXWideString(pRuntime), - params[1].ToCFXWideString(pRuntime)) - .c_str()); - - return true; -} - -enum CaseMode { kPreserveCase, kUpperCase, kLowerCase }; - -static FX_WCHAR TranslateCase(FX_WCHAR input, CaseMode eMode) { - if (eMode == kLowerCase && input >= 'A' && input <= 'Z') - return input | 0x20; - if (eMode == kUpperCase && input >= 'a' && input <= 'z') - return input & ~0x20; - return input; -} - -CFX_WideString util::printx(const CFX_WideString& wsFormat, - const CFX_WideString& wsSource) { - CFX_WideString wsResult; - FX_STRSIZE iSourceIdx = 0; - FX_STRSIZE iFormatIdx = 0; - CaseMode eCaseMode = kPreserveCase; - bool bEscaped = false; - while (iFormatIdx < wsFormat.GetLength()) { - if (bEscaped) { - bEscaped = false; - wsResult += wsFormat[iFormatIdx]; - ++iFormatIdx; - continue; - } - switch (wsFormat[iFormatIdx]) { - case '\\': { - bEscaped = true; - ++iFormatIdx; - } break; - case '<': { - eCaseMode = kLowerCase; - ++iFormatIdx; - } break; - case '>': { - eCaseMode = kUpperCase; - ++iFormatIdx; - } break; - case '=': { - eCaseMode = kPreserveCase; - ++iFormatIdx; - } break; - case '?': { - if (iSourceIdx < wsSource.GetLength()) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iSourceIdx; - } - ++iFormatIdx; - } break; - case 'X': { - if (iSourceIdx < wsSource.GetLength()) { - if ((wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') || - (wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') || - (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iFormatIdx; - } - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - case 'A': { - if (iSourceIdx < wsSource.GetLength()) { - if ((wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') || - (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iFormatIdx; - } - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - case '9': { - if (iSourceIdx < wsSource.GetLength()) { - if (wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') { - wsResult += wsSource[iSourceIdx]; - ++iFormatIdx; - } - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - case '*': { - if (iSourceIdx < wsSource.GetLength()) { - wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); - ++iSourceIdx; - } else { - ++iFormatIdx; - } - } break; - default: { - wsResult += wsFormat[iFormatIdx]; - ++iFormatIdx; - } break; - } - } - return wsResult; -} - -bool util::scand(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - int iSize = params.size(); - if (iSize < 2) - return false; - - CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime); - CFX_WideString sDate = params[1].ToCFXWideString(pRuntime); - double dDate = JS_GetDateTime(); - if (sDate.GetLength() > 0) { - dDate = CJS_PublicMethods::MakeRegularDate(sDate, sFormat, nullptr); - } - - if (!JS_PortIsNan(dDate)) { - vRet = CJS_Value(pRuntime, CJS_Date(pRuntime, dDate)); - } else { - vRet.SetNull(pRuntime); - } - - return true; -} - -bool util::byteToChar(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError) { - if (params.size() < 1) { - sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR); - return false; - } - - int arg = params[0].ToInt(pRuntime); - if (arg < 0 || arg > 255) { - sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR); - return false; - } - - CFX_WideString wStr(static_cast(arg)); - vRet = CJS_Value(pRuntime, wStr.c_str()); - return true; -} diff --git a/fpdfsdk/javascript/util.h b/fpdfsdk/javascript/util.h deleted file mode 100644 index 98761b6f30b557fb94a0e85a561715334fb70501..0000000000000000000000000000000000000000 --- a/fpdfsdk/javascript/util.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_JAVASCRIPT_UTIL_H_ -#define FPDFSDK_JAVASCRIPT_UTIL_H_ - -#include -#include - -#include "fpdfsdk/javascript/JS_Define.h" - -class util : public CJS_EmbedObj { - public: - explicit util(CJS_Object* pJSObject); - ~util() override; - - bool printd(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool printf(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool printx(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool scand(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - bool byteToChar(CJS_Runtime* pRuntime, - const std::vector& params, - CJS_Value& vRet, - CFX_WideString& sError); - - static CFX_WideString printx(const CFX_WideString& cFormat, - const CFX_WideString& cSource); -}; - -class CJS_Util : public CJS_Object { - public: - explicit CJS_Util(v8::Local pObject) : CJS_Object(pObject) {} - ~CJS_Util() override {} - - DECLARE_JS_CLASS(); - - JS_STATIC_METHOD(printd, util); - JS_STATIC_METHOD(printf, util); - JS_STATIC_METHOD(printx, util); - JS_STATIC_METHOD(scand, util); - JS_STATIC_METHOD(byteToChar, util); -}; - -#endif // FPDFSDK_JAVASCRIPT_UTIL_H_ diff --git a/fpdfsdk/pdfsdk_fieldaction.h b/fpdfsdk/pdfsdk_fieldaction.h index 4ee56ac3f69846187cc20d74655b63c3510e7db9..aec5dcaa2748daf01c51ce8a856b0f6e6a478d70 100644 --- a/fpdfsdk/pdfsdk_fieldaction.h +++ b/fpdfsdk/pdfsdk_fieldaction.h @@ -25,12 +25,12 @@ struct PDFSDK_FieldAction { bool bModifier; bool bShift; int nCommitKey; - CFX_WideString sChange; - CFX_WideString sChangeEx; + WideString sChange; + WideString sChangeEx; bool bKeyDown; int nSelEnd; int nSelStart; - CFX_WideString sValue; + WideString sValue; bool bWillCommit; bool bFieldFull; bool bRC; diff --git a/fpdfsdk/pdfwindow/PWL_Button.cpp b/fpdfsdk/pdfwindow/PWL_Button.cpp deleted file mode 100644 index 96be4694548dc376c1d00b3cc4d529b0d6e77cb2..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Button.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_Button.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -CPWL_Button::CPWL_Button() : m_bMouseDown(false) {} - -CPWL_Button::~CPWL_Button() {} - -CFX_ByteString CPWL_Button::GetClassName() const { - return "CPWL_Button"; -} - -void CPWL_Button::OnCreate(PWL_CREATEPARAM& cp) { - cp.eCursorType = FXCT_HAND; -} - -bool CPWL_Button::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - m_bMouseDown = true; - SetCapture(); - - return true; -} - -bool CPWL_Button::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - ReleaseCapture(); - m_bMouseDown = false; - - return true; -} diff --git a/fpdfsdk/pdfwindow/PWL_Button.h b/fpdfsdk/pdfwindow/PWL_Button.h deleted file mode 100644 index 2d1193f89d50f13398dbfbf167d2ecec68a3538b..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Button.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_BUTTON_H_ -#define FPDFSDK_PDFWINDOW_PWL_BUTTON_H_ - -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CPWL_Button : public CPWL_Wnd { - public: - CPWL_Button(); - ~CPWL_Button() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - - protected: - bool m_bMouseDown; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_BUTTON_H_ diff --git a/fpdfsdk/pdfwindow/PWL_Caret.cpp b/fpdfsdk/pdfwindow/PWL_Caret.cpp deleted file mode 100644 index 3360bbf62a5d3d40e26f627f4b2d51480140ac3a..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Caret.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_Caret.h" - -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -#define PWL_CARET_FLASHINTERVAL 500 - -PWL_CARET_INFO::PWL_CARET_INFO() : bVisible(false) {} - -CPWL_Caret::CPWL_Caret() : m_bFlash(false), m_fWidth(0.4f), m_nDelay(0) {} - -CPWL_Caret::~CPWL_Caret() {} - -CFX_ByteString CPWL_Caret::GetClassName() const { - return "CPWL_Caret"; -} - -void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - GetCaretApp(sAppStream, CFX_PointF()); -} - -void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - if (IsVisible() && m_bFlash) { - CFX_FloatRect rcRect = GetCaretRect(); - CFX_FloatRect rcClip = GetClipRect(); - CFX_PathData path; - - FX_FLOAT fCaretX = rcRect.left + m_fWidth * 0.5f; - FX_FLOAT fCaretTop = rcRect.top; - FX_FLOAT fCaretBottom = rcRect.bottom; - if (!rcClip.IsEmpty()) { - rcRect.Intersect(rcClip); - if (rcRect.IsEmpty()) - return; - - fCaretTop = rcRect.top; - fCaretBottom = rcRect.bottom; - } - - path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom), FXPT_TYPE::MoveTo, - false); - path.AppendPoint(CFX_PointF(fCaretX, fCaretTop), FXPT_TYPE::LineTo, false); - - CFX_GraphStateData gsd; - gsd.m_LineWidth = m_fWidth; - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0), - FXFILL_ALTERNATE); - } -} - -void CPWL_Caret::GetCaretApp(CFX_ByteTextBuf& sAppStream, - const CFX_PointF& ptOffset) { - if (IsVisible() && m_bFlash) { - CFX_ByteTextBuf sCaret; - - CFX_FloatRect rcRect = GetCaretRect(); - CFX_FloatRect rcClip = GetClipRect(); - - rcRect = CPWL_Utils::OffsetRect(rcRect, ptOffset.x, ptOffset.y); - rcClip = CPWL_Utils::OffsetRect(rcClip, ptOffset.x, ptOffset.y); - - sCaret << "q\n"; - if (!rcClip.IsEmpty()) { - sCaret << rcClip.left << " " << rcClip.bottom + 2.5f << " " - << rcClip.right - rcClip.left << " " - << rcClip.top - rcClip.bottom - 4.5f << " re W n\n"; - } - sCaret << m_fWidth << " w\n0 G\n"; - sCaret << rcRect.left + m_fWidth / 2 << " " << rcRect.bottom << " m\n"; - sCaret << rcRect.left + m_fWidth / 2 << " " << rcRect.top << " l S\nQ\n"; - - sAppStream << sCaret; - } -} - -CFX_ByteString CPWL_Caret::GetCaretAppearanceStream( - const CFX_PointF& ptOffset) { - CFX_ByteTextBuf sCaret; - GetCaretApp(sCaret, ptOffset); - return sCaret.MakeString(); -} - -void CPWL_Caret::TimerProc() { - if (m_nDelay > 0) { - m_nDelay--; - } else { - m_bFlash = !m_bFlash; - InvalidateRect(); - } -} - -CFX_FloatRect CPWL_Caret::GetCaretRect() const { - return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth, - m_ptHead.y); -} - -void CPWL_Caret::SetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot) { - if (bVisible) { - if (IsVisible()) { - if (m_ptHead != ptHead || m_ptFoot != ptFoot) { - m_ptHead = ptHead; - m_ptFoot = ptFoot; - m_bFlash = true; - Move(m_rcInvalid, false, true); - } - } else { - m_ptHead = ptHead; - m_ptFoot = ptFoot; - EndTimer(); - BeginTimer(PWL_CARET_FLASHINTERVAL); - CPWL_Wnd::SetVisible(true); - m_bFlash = true; - Move(m_rcInvalid, false, true); - } - } else { - m_ptHead = CFX_PointF(); - m_ptFoot = CFX_PointF(); - m_bFlash = false; - if (IsVisible()) { - EndTimer(); - CPWL_Wnd::SetVisible(false); - } - } -} - -void CPWL_Caret::InvalidateRect(CFX_FloatRect* pRect) { - if (pRect) { - CFX_FloatRect rcRefresh = CPWL_Utils::InflateRect(*pRect, 0.5f); - rcRefresh.top += 1; - rcRefresh.bottom -= 1; - CPWL_Wnd::InvalidateRect(&rcRefresh); - } else { - CPWL_Wnd::InvalidateRect(pRect); - } -} diff --git a/fpdfsdk/pdfwindow/PWL_Caret.h b/fpdfsdk/pdfwindow/PWL_Caret.h deleted file mode 100644 index 60ebbdc8e1e54855c5717bca3432749dee5a4754..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Caret.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_CARET_H_ -#define FPDFSDK_PDFWINDOW_PWL_CARET_H_ - -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -struct PWL_CARET_INFO { - public: - PWL_CARET_INFO(); - - bool bVisible; - CFX_PointF ptHead; - CFX_PointF ptFoot; -}; - -class CPWL_Caret : public CPWL_Wnd { - public: - CPWL_Caret(); - ~CPWL_Caret() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override; - void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - void InvalidateRect(CFX_FloatRect* pRect = nullptr) override; - void SetVisible(bool bVisible) override {} - void TimerProc() override; - - void SetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot); - CFX_ByteString GetCaretAppearanceStream(const CFX_PointF& ptOffset); - void SetInvalidRect(CFX_FloatRect rc) { m_rcInvalid = rc; } - - private: - void GetCaretApp(CFX_ByteTextBuf& sAppStream, const CFX_PointF& ptOffset); - CFX_FloatRect GetCaretRect() const; - - bool m_bFlash; - CFX_PointF m_ptHead; - CFX_PointF m_ptFoot; - FX_FLOAT m_fWidth; - int32_t m_nDelay; - CFX_FloatRect m_rcInvalid; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_CARET_H_ diff --git a/fpdfsdk/pdfwindow/PWL_ComboBox.cpp b/fpdfsdk/pdfwindow/PWL_ComboBox.cpp deleted file mode 100644 index bc6909a07dde7a402de764c0cca62f88a383d40c..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_ComboBox.cpp +++ /dev/null @@ -1,626 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_ComboBox.h" - -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/fxedit/fxet_list.h" -#include "fpdfsdk/pdfwindow/PWL_Edit.h" -#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" -#include "fpdfsdk/pdfwindow/PWL_ListBox.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" -#include "public/fpdf_fwlevent.h" - -#define PWLCB_DEFAULTFONTSIZE 12.0f - -bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - if (!m_bMouseDown) - return true; - - ReleaseCapture(); - m_bMouseDown = false; - - if (!ClientHitTest(point)) - return true; - if (CPWL_Wnd* pParent = GetParentWindow()) - pParent->OnNotify(this, PNM_LBUTTONUP, 0, PWL_MAKEDWORD(point.x, point.y)); - - bool bExit = false; - OnNotifySelChanged(false, bExit, nFlag); - - return !bExit; -} - -bool CPWL_CBListBox::OnKeyDownWithExit(uint16_t nChar, - bool& bExit, - uint32_t nFlag) { - switch (nChar) { - case FWL_VKEY_Up: - case FWL_VKEY_Down: - case FWL_VKEY_Home: - case FWL_VKEY_Left: - case FWL_VKEY_End: - case FWL_VKEY_Right: - break; - default: - return false; - } - - switch (nChar) { - case FWL_VKEY_Up: - m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Down: - m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Home: - m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Left: - m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_End: - m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Right: - m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Delete: - break; - } - - OnNotifySelChanged(true, bExit, nFlag); - - return true; -} - -bool CPWL_CBListBox::OnCharWithExit(uint16_t nChar, - bool& bExit, - uint32_t nFlag) { - if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag))) - return false; - if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow()) - pComboBox->SetSelectText(); - - OnNotifySelChanged(true, bExit, nFlag); - - return true; -} - -void CPWL_CBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - CPWL_Wnd::GetThisAppearanceStream(sAppStream); - - CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect(); - - if (IsVisible() && !rectWnd.IsEmpty()) { - CFX_ByteTextBuf sButton; - - CFX_PointF ptCenter = GetCenterPoint(); - - CFX_PointF pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN, - ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN, - ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt3(ptCenter.x, - ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f); - - if (IsFloatBigger(rectWnd.right - rectWnd.left, - PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) && - IsFloatBigger(rectWnd.top - rectWnd.bottom, - PWL_CBBUTTON_TRIANGLE_HALFLEN)) { - sButton << "0 g\n"; - sButton << pt1.x << " " << pt1.y << " m\n"; - sButton << pt2.x << " " << pt2.y << " l\n"; - sButton << pt3.x << " " << pt3.y << " l\n"; - sButton << pt1.x << " " << pt1.y << " l f\n"; - - sAppStream << "q\n" << sButton << "Q\n"; - } - } -} - -void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - - CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect(); - - if (IsVisible() && !rectWnd.IsEmpty()) { - CFX_PointF ptCenter = GetCenterPoint(); - - CFX_PointF pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN, - ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN, - ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt3(ptCenter.x, - ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f); - - if (IsFloatBigger(rectWnd.right - rectWnd.left, - PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) && - IsFloatBigger(rectWnd.top - rectWnd.bottom, - PWL_CBBUTTON_TRIANGLE_HALFLEN)) { - CFX_PathData path; - path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false); - path.AppendPoint(pt2, FXPT_TYPE::LineTo, false); - path.AppendPoint(pt3, FXPT_TYPE::LineTo, false); - path.AppendPoint(pt1, FXPT_TYPE::LineTo, false); - - pDevice->DrawPath(&path, pUser2Device, nullptr, - PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0, - FXFILL_ALTERNATE); - } - } -} - -bool CPWL_CBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - SetCapture(); - - if (CPWL_Wnd* pParent = GetParentWindow()) { - pParent->OnNotify(this, PNM_LBUTTONDOWN, 0, - PWL_MAKEDWORD(point.x, point.y)); - } - - return true; -} - -bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - ReleaseCapture(); - - return true; -} - -CPWL_ComboBox::CPWL_ComboBox() - : m_pEdit(nullptr), - m_pButton(nullptr), - m_pList(nullptr), - m_bPopup(false), - m_nPopupWhere(0), - m_nSelectItem(-1), - m_pFillerNotify(nullptr) {} - -CFX_ByteString CPWL_ComboBox::GetClassName() const { - return "CPWL_ComboBox"; -} - -void CPWL_ComboBox::OnCreate(PWL_CREATEPARAM& cp) { - cp.dwFlags &= ~PWS_HSCROLL; - cp.dwFlags &= ~PWS_VSCROLL; -} - -void CPWL_ComboBox::SetFocus() { - if (m_pEdit) - m_pEdit->SetFocus(); -} - -void CPWL_ComboBox::KillFocus() { - SetPopup(false); - CPWL_Wnd::KillFocus(); -} - -CFX_WideString CPWL_ComboBox::GetText() const { - if (m_pEdit) { - return m_pEdit->GetText(); - } - return CFX_WideString(); -} - -void CPWL_ComboBox::SetText(const CFX_WideString& text) { - if (m_pEdit) - m_pEdit->SetText(text); -} - -void CPWL_ComboBox::AddString(const CFX_WideString& str) { - if (m_pList) - m_pList->AddString(str); -} - -int32_t CPWL_ComboBox::GetSelect() const { - return m_nSelectItem; -} - -void CPWL_ComboBox::SetSelect(int32_t nItemIndex) { - if (m_pList) - m_pList->Select(nItemIndex); - - m_pEdit->SetText(m_pList->GetText()); - m_nSelectItem = nItemIndex; -} - -void CPWL_ComboBox::SetEditSel(int32_t nStartChar, int32_t nEndChar) { - if (m_pEdit) - m_pEdit->SetSel(nStartChar, nEndChar); -} - -void CPWL_ComboBox::GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const { - nStartChar = -1; - nEndChar = -1; - - if (m_pEdit) - m_pEdit->GetSel(nStartChar, nEndChar); -} - -void CPWL_ComboBox::Clear() { - if (m_pEdit) - m_pEdit->Clear(); -} - -void CPWL_ComboBox::CreateChildWnd(const PWL_CREATEPARAM& cp) { - CreateEdit(cp); - CreateButton(cp); - CreateListBox(cp); -} - -void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) { - if (!m_pEdit) { - m_pEdit = new CPWL_CBEdit; - m_pEdit->AttachFFLData(m_pFormFiller); - - PWL_CREATEPARAM ecp = cp; - ecp.pParentWnd = this; - ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER | - PES_AUTOSCROLL | PES_UNDO; - - if (HasFlag(PWS_AUTOFONTSIZE)) - ecp.dwFlags |= PWS_AUTOFONTSIZE; - - if (!HasFlag(PCBS_ALLOWCUSTOMTEXT)) - ecp.dwFlags |= PWS_READONLY; - - ecp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0); - ecp.dwBorderWidth = 0; - ecp.nBorderStyle = BorderStyle::SOLID; - - m_pEdit->Create(ecp); - } -} - -void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) { - if (!m_pButton) { - m_pButton = new CPWL_CBButton; - - PWL_CREATEPARAM bcp = cp; - bcp.pParentWnd = this; - bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND; - bcp.sBackgroundColor = PWL_SCROLLBAR_BKCOLOR; - bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR; - bcp.dwBorderWidth = 2; - bcp.nBorderStyle = BorderStyle::BEVELED; - bcp.eCursorType = FXCT_ARROW; - - m_pButton->Create(bcp); - } -} - -void CPWL_ComboBox::CreateListBox(const PWL_CREATEPARAM& cp) { - if (!m_pList) { - m_pList = new CPWL_CBListBox; - m_pList->AttachFFLData(m_pFormFiller); - PWL_CREATEPARAM lcp = cp; - lcp.pParentWnd = this; - lcp.dwFlags = - PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL; - lcp.nBorderStyle = BorderStyle::SOLID; - lcp.dwBorderWidth = 1; - lcp.eCursorType = FXCT_ARROW; - lcp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0); - - if (cp.dwFlags & PWS_AUTOFONTSIZE) - lcp.fFontSize = PWLCB_DEFAULTFONTSIZE; - else - lcp.fFontSize = cp.fFontSize; - - if (cp.sBorderColor.nColorType == COLORTYPE_TRANSPARENT) - lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR; - - if (cp.sBackgroundColor.nColorType == COLORTYPE_TRANSPARENT) - lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR; - - m_pList->Create(lcp); - } -} - -void CPWL_ComboBox::RePosChildWnd() { - CFX_FloatRect rcClient = GetClientRect(); - - if (m_bPopup) { - CFX_FloatRect rclient = GetClientRect(); - CFX_FloatRect rcButton = rclient; - CFX_FloatRect rcEdit = rcClient; - CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect(); - - FX_FLOAT fOldWindowHeight = m_rcOldWindow.Height(); - FX_FLOAT fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2; - - switch (m_nPopupWhere) { - case 0: - rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH; - - if (rcButton.left < rclient.left) - rcButton.left = rclient.left; - - rcButton.bottom = rcButton.top - fOldClientHeight; - - rcEdit.right = rcButton.left - 1.0f; - - if (rcEdit.left < rclient.left) - rcEdit.left = rclient.left; - - if (rcEdit.right < rcEdit.left) - rcEdit.right = rcEdit.left; - - rcEdit.bottom = rcEdit.top - fOldClientHeight; - - rcList.top -= fOldWindowHeight; - - break; - case 1: - rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH; - - if (rcButton.left < rclient.left) - rcButton.left = rclient.left; - - rcButton.top = rcButton.bottom + fOldClientHeight; - - rcEdit.right = rcButton.left - 1.0f; - - if (rcEdit.left < rclient.left) - rcEdit.left = rclient.left; - - if (rcEdit.right < rcEdit.left) - rcEdit.right = rcEdit.left; - - rcEdit.top = rcEdit.bottom + fOldClientHeight; - - rcList.bottom += fOldWindowHeight; - - break; - } - - if (m_pButton) - m_pButton->Move(rcButton, true, false); - - if (m_pEdit) - m_pEdit->Move(rcEdit, true, false); - - if (m_pList) { - m_pList->SetVisible(true); - m_pList->Move(rcList, true, false); - m_pList->ScrollToListItem(m_nSelectItem); - } - } else { - CFX_FloatRect rcButton = rcClient; - - rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH; - - if (rcButton.left < rcClient.left) - rcButton.left = rcClient.left; - - if (m_pButton) - m_pButton->Move(rcButton, true, false); - - CFX_FloatRect rcEdit = rcClient; - rcEdit.right = rcButton.left - 1.0f; - - if (rcEdit.left < rcClient.left) - rcEdit.left = rcClient.left; - - if (rcEdit.right < rcEdit.left) - rcEdit.right = rcEdit.left; - - if (m_pEdit) - m_pEdit->Move(rcEdit, true, false); - - if (m_pList) - m_pList->SetVisible(false); - } -} - -void CPWL_ComboBox::SelectAll() { - if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT)) - m_pEdit->SelectAll(); -} - -CFX_FloatRect CPWL_ComboBox::GetFocusRect() const { - return CFX_FloatRect(); -} - -void CPWL_ComboBox::SetPopup(bool bPopup) { - if (!m_pList) - return; - if (bPopup == m_bPopup) - return; - FX_FLOAT fListHeight = m_pList->GetContentRect().Height(); - if (!IsFloatBigger(fListHeight, 0.0f)) - return; - - if (bPopup) { - if (m_pFillerNotify) { -#ifdef PDF_ENABLE_XFA - bool bExit = false; - m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, 0); - if (bExit) - return; -#endif // PDF_ENABLE_XFA - int32_t nWhere = 0; - FX_FLOAT fPopupRet = 0.0f; - FX_FLOAT fPopupMin = 0.0f; - if (m_pList->GetCount() > 3) - fPopupMin = - m_pList->GetFirstHeight() * 3 + m_pList->GetBorderWidth() * 2; - FX_FLOAT fPopupMax = fListHeight + m_pList->GetBorderWidth() * 2; - m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax, - nWhere, fPopupRet); - - if (IsFloatBigger(fPopupRet, 0.0f)) { - m_bPopup = bPopup; - - CFX_FloatRect rcWindow = CPWL_Wnd::GetWindowRect(); - m_rcOldWindow = rcWindow; - switch (nWhere) { - default: - case 0: - rcWindow.bottom -= fPopupRet; - break; - case 1: - rcWindow.top += fPopupRet; - break; - } - - m_nPopupWhere = nWhere; - Move(rcWindow, true, true); -#ifdef PDF_ENABLE_XFA - bExit = false; - m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, 0); - if (bExit) - return; -#endif // PDF_ENABLE_XFA - } - } - } else { - m_bPopup = bPopup; - Move(m_rcOldWindow, true, true); - } -} - -bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) { - if (!m_pList) - return false; - if (!m_pEdit) - return false; - - m_nSelectItem = -1; - - switch (nChar) { - case FWL_VKEY_Up: - if (m_pList->GetCurSel() > 0) { - bool bExit = false; -#ifdef PDF_ENABLE_XFA - if (m_pFillerNotify) { - m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag); - if (bExit) - return false; - bExit = false; - m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag); - if (bExit) - return false; - } -#endif // PDF_ENABLE_XFA - if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) { - if (bExit) - return false; - SetSelectText(); - } - } - return true; - case FWL_VKEY_Down: - if (m_pList->GetCurSel() < m_pList->GetCount() - 1) { - bool bExit = false; -#ifdef PDF_ENABLE_XFA - if (m_pFillerNotify) { - m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag); - if (bExit) - return false; - bExit = false; - m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag); - if (bExit) - return false; - } -#endif // PDF_ENABLE_XFA - if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) { - if (bExit) - return false; - SetSelectText(); - } - } - return true; - } - - if (HasFlag(PCBS_ALLOWCUSTOMTEXT)) - return m_pEdit->OnKeyDown(nChar, nFlag); - - return false; -} - -bool CPWL_ComboBox::OnChar(uint16_t nChar, uint32_t nFlag) { - if (!m_pList) - return false; - - if (!m_pEdit) - return false; - - m_nSelectItem = -1; - if (HasFlag(PCBS_ALLOWCUSTOMTEXT)) - return m_pEdit->OnChar(nChar, nFlag); - - bool bExit = false; -#ifdef PDF_ENABLE_XFA - if (m_pFillerNotify) { - m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag); - if (bExit) - return false; - - m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag); - if (bExit) - return false; - } -#endif // PDF_ENABLE_XFA - return m_pList->OnCharWithExit(nChar, bExit, nFlag) ? bExit : false; -} - -void CPWL_ComboBox::OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam, - intptr_t lParam) { - switch (msg) { - case PNM_LBUTTONDOWN: - if (pWnd == m_pButton) { - SetPopup(!m_bPopup); - return; - } - break; - case PNM_LBUTTONUP: - if (m_pEdit && m_pList) { - if (pWnd == m_pList) { - SetSelectText(); - SelectAll(); - m_pEdit->SetFocus(); - SetPopup(false); - return; - } - } - } - - CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); -} - -bool CPWL_ComboBox::IsPopup() const { - return m_bPopup; -} - -void CPWL_ComboBox::SetSelectText() { - m_pEdit->SelectAll(); - m_pEdit->ReplaceSel(m_pList->GetText()); - m_pEdit->SelectAll(); - m_nSelectItem = m_pList->GetCurSel(); -} - -void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) { - m_pFillerNotify = pNotify; - - if (m_pEdit) - m_pEdit->SetFillerNotify(pNotify); - - if (m_pList) - m_pList->SetFillerNotify(pNotify); -} diff --git a/fpdfsdk/pdfwindow/PWL_ComboBox.h b/fpdfsdk/pdfwindow/PWL_ComboBox.h deleted file mode 100644 index e1a8df7561a8cbdf559080153c607f35ea06df64..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_ComboBox.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_COMBOBOX_H_ -#define FPDFSDK_PDFWINDOW_PWL_COMBOBOX_H_ - -#include "fpdfsdk/pdfwindow/PWL_Edit.h" -#include "fpdfsdk/pdfwindow/PWL_ListBox.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CPWL_CBEdit : public CPWL_Edit { - public: - CPWL_CBEdit() {} - ~CPWL_CBEdit() override {} -}; - -class CPWL_CBListBox : public CPWL_ListBox { - public: - CPWL_CBListBox() {} - ~CPWL_CBListBox() override {} - - // CPWL_ListBox - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - - bool OnKeyDownWithExit(uint16_t nChar, bool& bExit, uint32_t nFlag); - bool OnCharWithExit(uint16_t nChar, bool& bExit, uint32_t nFlag); -}; - -#define PWL_COMBOBOX_BUTTON_WIDTH 13 - -class CPWL_CBButton : public CPWL_Wnd { - public: - CPWL_CBButton() {} - ~CPWL_CBButton() override {} - - // CPWL_Wnd - void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override; - void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; -}; - -class CPWL_ComboBox : public CPWL_Wnd { - public: - CPWL_ComboBox(); - ~CPWL_ComboBox() override {} - - CPWL_Edit* GetEdit() const { return m_pEdit; } - - // CPWL_Wnd: - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) override; - bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - void OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam = 0, - intptr_t lParam = 0) override; - void CreateChildWnd(const PWL_CREATEPARAM& cp) override; - void RePosChildWnd() override; - CFX_FloatRect GetFocusRect() const override; - void SetFocus() override; - void KillFocus() override; - - void SetFillerNotify(IPWL_Filler_Notify* pNotify); - - CFX_WideString GetText() const; - void SetText(const CFX_WideString& text); - void AddString(const CFX_WideString& str); - int32_t GetSelect() const; - void SetSelect(int32_t nItemIndex); - - void SetEditSel(int32_t nStartChar, int32_t nEndChar); - void GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const; - void Clear(); - void SelectAll(); - bool IsPopup() const; - - void SetSelectText(); - - void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; } - - private: - void CreateEdit(const PWL_CREATEPARAM& cp); - void CreateButton(const PWL_CREATEPARAM& cp); - void CreateListBox(const PWL_CREATEPARAM& cp); - void SetPopup(bool bPopup); - - CPWL_CBEdit* m_pEdit; - CPWL_CBButton* m_pButton; - CPWL_CBListBox* m_pList; - bool m_bPopup; - CFX_FloatRect m_rcOldWindow; - int32_t m_nPopupWhere; - int32_t m_nSelectItem; - IPWL_Filler_Notify* m_pFillerNotify; - CFFL_FormFiller* m_pFormFiller; // Not owned. -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_COMBOBOX_H_ diff --git a/fpdfsdk/pdfwindow/PWL_Edit.cpp b/fpdfsdk/pdfwindow/PWL_Edit.cpp deleted file mode 100644 index b77aad9ab04593a0352f6db14c161d14e04c7cd8..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Edit.cpp +++ /dev/null @@ -1,878 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_Edit.h" - -#include -#include - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fxcrt/fx_safe_types.h" -#include "core/fxcrt/fx_xml.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/fx_font.h" -#include "fpdfsdk/fxedit/fxet_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Caret.h" -#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" -#include "fpdfsdk/pdfwindow/PWL_FontMap.h" -#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" -#include "public/fpdf_fwlevent.h" -#include "third_party/base/stl_util.h" - -CPWL_Edit::CPWL_Edit() - : m_pFillerNotify(nullptr), m_bFocus(false), m_pFormFiller(nullptr) {} - -CPWL_Edit::~CPWL_Edit() { - ASSERT(m_bFocus == false); -} - -CFX_ByteString CPWL_Edit::GetClassName() const { - return PWL_CLASSNAME_EDIT; -} - -void CPWL_Edit::OnDestroy() {} - -void CPWL_Edit::SetText(const CFX_WideString& csText) { - CFX_WideString swText = csText; - if (!HasFlag(PES_RICH)) { - m_pEdit->SetText(swText); - return; - } - - CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText); - std::unique_ptr pXML( - CXML_Element::Parse(sValue.c_str(), sValue.GetLength())); - if (!pXML) { - m_pEdit->SetText(swText); - return; - } - - int32_t nCount = pXML->CountChildren(); - bool bFirst = true; - - swText.clear(); - - for (int32_t i = 0; i < nCount; i++) { - CXML_Element* pSubElement = pXML->GetElement(i); - if (!pSubElement) - continue; - - CFX_ByteString tag = pSubElement->GetTagName(); - if (tag.EqualNoCase("p")) { - int nChild = pSubElement->CountChildren(); - CFX_WideString swSection; - for (int32_t j = 0; j < nChild; j++) - swSection += pSubElement->GetContent(j); - - if (bFirst) - bFirst = false; - else - swText += FWL_VKEY_Return; - swText += swSection; - } - } - - m_pEdit->SetText(swText); -} - -void CPWL_Edit::RePosChildWnd() { - if (CPWL_ScrollBar* pVSB = GetVScrollBar()) { - CFX_FloatRect rcWindow = m_rcOldWindow; - CFX_FloatRect rcVScroll = - CFX_FloatRect(rcWindow.right, rcWindow.bottom, - rcWindow.right + PWL_SCROLLBAR_WIDTH, rcWindow.top); - pVSB->Move(rcVScroll, true, false); - } - - if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW)) - m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect( - GetClientRect(), 1.0f)); // +1 for caret beside border - - CPWL_EditCtrl::RePosChildWnd(); -} - -CFX_FloatRect CPWL_Edit::GetClientRect() const { - CFX_FloatRect rcClient = CPWL_Utils::DeflateRect( - GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth())); - - if (CPWL_ScrollBar* pVSB = GetVScrollBar()) { - if (pVSB->IsVisible()) { - rcClient.right -= PWL_SCROLLBAR_WIDTH; - } - } - - return rcClient; -} - -void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, bool bPaint) { - m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint); -} - -bool CPWL_Edit::CanSelectAll() const { - return GetSelectWordRange() != m_pEdit->GetWholeWordRange(); -} - -bool CPWL_Edit::CanClear() const { - return !IsReadOnly() && m_pEdit->IsSelected(); -} - -bool CPWL_Edit::CanCopy() const { - return !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && - m_pEdit->IsSelected(); -} - -bool CPWL_Edit::CanCut() const { - return CanCopy() && !IsReadOnly(); -} -void CPWL_Edit::CutText() { - if (!CanCut()) - return; - m_pEdit->Clear(); -} - -void CPWL_Edit::OnCreated() { - CPWL_EditCtrl::OnCreated(); - - if (CPWL_ScrollBar* pScroll = GetVScrollBar()) { - pScroll->RemoveFlag(PWS_AUTOTRANSPARENT); - pScroll->SetTransparency(255); - } - - SetParamByFlag(); - - m_rcOldWindow = GetWindowRect(); - - m_pEdit->SetOprNotify(this); - m_pEdit->EnableOprNotify(true); -} - -void CPWL_Edit::SetParamByFlag() { - if (HasFlag(PES_RIGHT)) { - m_pEdit->SetAlignmentH(2, false); - } else if (HasFlag(PES_MIDDLE)) { - m_pEdit->SetAlignmentH(1, false); - } else { - m_pEdit->SetAlignmentH(0, false); - } - - if (HasFlag(PES_BOTTOM)) { - m_pEdit->SetAlignmentV(2, false); - } else if (HasFlag(PES_CENTER)) { - m_pEdit->SetAlignmentV(1, false); - } else { - m_pEdit->SetAlignmentV(0, false); - } - - if (HasFlag(PES_PASSWORD)) { - m_pEdit->SetPasswordChar('*', false); - } - - m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), false); - m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), false); - m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), false); - m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), false); - m_pEdit->EnableUndo(HasFlag(PES_UNDO)); - - if (HasFlag(PES_TEXTOVERFLOW)) { - SetClipRect(CFX_FloatRect(0.0f, 0.0f, 0.0f, 0.0f)); - m_pEdit->SetTextOverflow(true, false); - } else { - if (m_pEditCaret) { - m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect( - GetClientRect(), 1.0f)); // +1 for caret beside border - } - } -} - -void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - CPWL_Wnd::GetThisAppearanceStream(sAppStream); - - CFX_FloatRect rcClient = GetClientRect(); - CFX_ByteTextBuf sLine; - - int32_t nCharArray = m_pEdit->GetCharArray(); - - if (nCharArray > 0) { - switch (GetBorderStyle()) { - case BorderStyle::SOLID: { - sLine << "q\n" - << GetBorderWidth() << " w\n" - << CPWL_Utils::GetColorAppStream(GetBorderColor(), false) - .AsStringC() - << " 2 J 0 j\n"; - - for (int32_t i = 1; i < nCharArray; i++) { - sLine << rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * i - << " " << rcClient.bottom << " m\n" - << rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * i - << " " << rcClient.top << " l S\n"; - } - - sLine << "Q\n"; - break; - } - case BorderStyle::DASH: { - sLine << "q\n" - << GetBorderWidth() << " w\n" - << CPWL_Utils::GetColorAppStream(GetBorderColor(), false) - .AsStringC() - << " 2 J 0 j\n" - << "[" << GetBorderDash().nDash << " " << GetBorderDash().nGap - << "] " << GetBorderDash().nPhase << " d\n"; - - for (int32_t i = 1; i < nCharArray; i++) { - sLine << rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * i - << " " << rcClient.bottom << " m\n" - << rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * i - << " " << rcClient.top << " l S\n"; - } - - sLine << "Q\n"; - break; - } - default: - break; - } - } - - sAppStream << sLine; - - CFX_ByteTextBuf sText; - CFX_PointF ptOffset; - CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange(); - CPVT_WordRange wrSelect = GetSelectWordRange(); - CPVT_WordRange wrVisible = - HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange(); - - CPVT_WordRange wrSelBefore(wrWhole.BeginPos, wrSelect.BeginPos); - CPVT_WordRange wrSelAfter(wrSelect.EndPos, wrWhole.EndPos); - CPVT_WordRange wrTemp = - CPWL_Utils::OverlapWordRange(GetSelectWordRange(), wrVisible); - CFX_ByteString sEditSel = - CPWL_Utils::GetEditSelAppStream(m_pEdit.get(), ptOffset, &wrTemp); - - if (sEditSel.GetLength() > 0) - sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR).AsStringC() - << sEditSel.AsStringC(); - - wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelBefore); - CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream( - m_pEdit.get(), ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY), - m_pEdit->GetPasswordChar()); - - if (sEditBefore.GetLength() > 0) - sText << "BT\n" - << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC() - << sEditBefore.AsStringC() << "ET\n"; - - wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelect); - CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream( - m_pEdit.get(), ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY), - m_pEdit->GetPasswordChar()); - - if (sEditMid.GetLength() > 0) - sText << "BT\n" - << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1)) - .AsStringC() - << sEditMid.AsStringC() << "ET\n"; - - wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelAfter); - CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream( - m_pEdit.get(), ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY), - m_pEdit->GetPasswordChar()); - - if (sEditAfter.GetLength() > 0) - sText << "BT\n" - << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC() - << sEditAfter.AsStringC() << "ET\n"; - - if (sText.GetLength() > 0) { - CFX_FloatRect rect = GetClientRect(); - sAppStream << "q\n/Tx BMC\n"; - - if (!HasFlag(PES_TEXTOVERFLOW)) - sAppStream << rect.left << " " << rect.bottom << " " - << rect.right - rect.left << " " << rect.top - rect.bottom - << " re W n\n"; - - sAppStream << sText; - - sAppStream << "EMC\nQ\n"; - } -} - -void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - - CFX_FloatRect rcClient = GetClientRect(); - CFX_ByteTextBuf sLine; - - int32_t nCharArray = m_pEdit->GetCharArray(); - FX_SAFE_INT32 nCharArraySafe = nCharArray; - nCharArraySafe -= 1; - nCharArraySafe *= 2; - - if (nCharArray > 0 && nCharArraySafe.IsValid()) { - switch (GetBorderStyle()) { - case BorderStyle::SOLID: { - CFX_GraphStateData gsd; - gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth(); - - CFX_PathData path; - - for (int32_t i = 0; i < nCharArray - 1; i++) { - path.AppendPoint( - CFX_PointF( - rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), - rcClient.bottom), - FXPT_TYPE::MoveTo, false); - path.AppendPoint( - CFX_PointF( - rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), - rcClient.top), - FXPT_TYPE::LineTo, false); - } - if (!path.GetPoints().empty()) { - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, - GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE); - } - break; - } - case BorderStyle::DASH: { - CFX_GraphStateData gsd; - gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth(); - - gsd.SetDashCount(2); - gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash; - gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap; - gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase; - - CFX_PathData path; - for (int32_t i = 0; i < nCharArray - 1; i++) { - path.AppendPoint( - CFX_PointF( - rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), - rcClient.bottom), - FXPT_TYPE::MoveTo, false); - path.AppendPoint( - CFX_PointF( - rcClient.left + - ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), - rcClient.top), - FXPT_TYPE::LineTo, false); - } - if (!path.GetPoints().empty()) { - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, - GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE); - } - break; - } - default: - break; - } - } - - CFX_FloatRect rcClip; - CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange(); - CPVT_WordRange* pRange = nullptr; - if (!HasFlag(PES_TEXTOVERFLOW)) { - rcClip = GetClientRect(); - pRange = &wrRange; - } - - CFX_SystemHandler* pSysHandler = GetSystemHandler(); - CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pEdit.get(), - GetTextColor().ToFXColor(GetTransparency()), rcClip, - CFX_PointF(), pRange, pSysHandler, m_pFormFiller); -} - -bool CPWL_Edit::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) { - if (m_bMouseDown) - InvalidateRect(); - - m_bMouseDown = true; - SetCapture(); - - m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - } - - return true; -} - -bool CPWL_Edit::OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDblClk(point, nFlag); - - if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) { - m_pEdit->SelectAll(); - } - - return true; -} - -bool CPWL_Edit::OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) { - if (m_bMouseDown) - return false; - - CPWL_Wnd::OnRButtonUp(point, nFlag); - - if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point)) - return true; - - CFX_SystemHandler* pSH = GetSystemHandler(); - if (!pSH) - return false; - - SetFocus(); - - return false; -} - -void CPWL_Edit::OnSetFocus() { - SetEditCaret(true); - if (!IsReadOnly()) { - if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler()) - pFocusHandler->OnSetFocus(this); - } - m_bFocus = true; -} - -void CPWL_Edit::OnKillFocus() { - ShowVScrollBar(false); - m_pEdit->SelectNone(); - SetCaret(false, CFX_PointF(), CFX_PointF()); - SetCharSet(FXFONT_ANSI_CHARSET); - m_bFocus = false; -} - -void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace) { - m_pEdit->SetCharSpace(fCharSpace); -} - -CFX_ByteString CPWL_Edit::GetSelectAppearanceStream( - const CFX_PointF& ptOffset) const { - CPVT_WordRange wr = GetSelectWordRange(); - return CPWL_Utils::GetEditSelAppStream(m_pEdit.get(), ptOffset, &wr); -} - -CPVT_WordRange CPWL_Edit::GetSelectWordRange() const { - if (m_pEdit->IsSelected()) { - int32_t nStart = -1; - int32_t nEnd = -1; - - m_pEdit->GetSel(nStart, nEnd); - - CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart); - CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd); - - return CPVT_WordRange(wpStart, wpEnd); - } - - return CPVT_WordRange(); -} - -CFX_ByteString CPWL_Edit::GetTextAppearanceStream( - const CFX_PointF& ptOffset) const { - CFX_ByteTextBuf sRet; - CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit.get(), ptOffset); - if (sEdit.GetLength() > 0) { - sRet << "BT\n" - << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC() - << sEdit.AsStringC() << "ET\n"; - } - return sRet.MakeString(); -} - -CFX_ByteString CPWL_Edit::GetCaretAppearanceStream( - const CFX_PointF& ptOffset) const { - if (m_pEditCaret) - return m_pEditCaret->GetCaretAppearanceStream(ptOffset); - - return CFX_ByteString(); -} - -CFX_PointF CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord) { - CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator(); - CPVT_WordPlace wpOld = pIterator->GetAt(); - pIterator->SetAt(wpWord); - - CFX_PointF pt; - CPVT_Word word; - if (pIterator->GetWord(word)) { - pt = CFX_PointF(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent); - } - pIterator->SetAt(wpOld); - return pt; -} - -bool CPWL_Edit::IsTextFull() const { - return m_pEdit->IsTextFull(); -} - -FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont, - const CFX_FloatRect& rcPlate, - int32_t nCharArray) { - if (pFont && !pFont->IsStandardFont()) { - FX_RECT rcBBox; - pFont->GetFontBBox(rcBBox); - - CFX_FloatRect rcCell = rcPlate; - FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width(); - FX_FLOAT ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height(); - - return xdiv < ydiv ? xdiv : ydiv; - } - - return 0.0f; -} - -void CPWL_Edit::SetCharArray(int32_t nCharArray) { - if (HasFlag(PES_CHARARRAY) && nCharArray > 0) { - m_pEdit->SetCharArray(nCharArray); - m_pEdit->SetTextOverflow(true, true); - - if (HasFlag(PWS_AUTOFONTSIZE)) { - if (IPVT_FontMap* pFontMap = GetFontMap()) { - FX_FLOAT fFontSize = GetCharArrayAutoFontSize( - pFontMap->GetPDFFont(0), GetClientRect(), nCharArray); - if (fFontSize > 0.0f) { - m_pEdit->SetAutoFontSize(false, true); - m_pEdit->SetFontSize(fFontSize); - } - } - } - } -} - -void CPWL_Edit::SetLimitChar(int32_t nLimitChar) { - m_pEdit->SetLimitChar(nLimitChar); -} - -void CPWL_Edit::ReplaceSel(const CFX_WideString& wsText) { - m_pEdit->Clear(); - m_pEdit->InsertText(wsText, FXFONT_DEFAULT_CHARSET); -} - -CFX_FloatRect CPWL_Edit::GetFocusRect() const { - return CFX_FloatRect(); -} - -void CPWL_Edit::ShowVScrollBar(bool bShow) { - if (CPWL_ScrollBar* pScroll = GetVScrollBar()) { - if (bShow) { - if (!pScroll->IsVisible()) { - pScroll->SetVisible(true); - CFX_FloatRect rcWindow = GetWindowRect(); - m_rcOldWindow = rcWindow; - rcWindow.right += PWL_SCROLLBAR_WIDTH; - Move(rcWindow, true, true); - } - } else { - if (pScroll->IsVisible()) { - pScroll->SetVisible(false); - Move(m_rcOldWindow, true, true); - } - } - } -} - -bool CPWL_Edit::IsVScrollBarVisible() const { - if (CPWL_ScrollBar* pScroll = GetVScrollBar()) { - return pScroll->IsVisible(); - } - - return false; -} - -bool CPWL_Edit::OnKeyDown(uint16_t nChar, uint32_t nFlag) { - if (m_bMouseDown) - return true; - - if (nChar == FWL_VKEY_Delete) { - if (m_pFillerNotify) { - bool bRC = true; - bool bExit = false; - CFX_WideString strChange; - CFX_WideString strChangeEx; - - int nSelStart = 0; - int nSelEnd = 0; - GetSel(nSelStart, nSelEnd); - - if (nSelStart == nSelEnd) - nSelEnd = nSelStart + 1; - m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), strChange, - strChangeEx, nSelStart, nSelEnd, true, - bRC, bExit, nFlag); - if (!bRC) - return false; - if (bExit) - return false; - } - } - - bool bRet = CPWL_EditCtrl::OnKeyDown(nChar, nFlag); - - // In case of implementation swallow the OnKeyDown event. - if (IsProceedtoOnChar(nChar, nFlag)) - return true; - - return bRet; -} - -/** -*In case of implementation swallow the OnKeyDown event. -*If the event is swallowed, implementation may do other unexpected things, which -*is not the control means to do. -*/ -bool CPWL_Edit::IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag) { - bool bCtrl = IsCTRLpressed(nFlag); - bool bAlt = IsALTpressed(nFlag); - if (bCtrl && !bAlt) { - // hot keys for edit control. - switch (nKeyCode) { - case 'C': - case 'V': - case 'X': - case 'A': - case 'Z': - return true; - default: - break; - } - } - // control characters. - switch (nKeyCode) { - case FWL_VKEY_Escape: - case FWL_VKEY_Back: - case FWL_VKEY_Return: - case FWL_VKEY_Space: - return true; - default: - return false; - } -} - -bool CPWL_Edit::OnChar(uint16_t nChar, uint32_t nFlag) { - if (m_bMouseDown) - return true; - - bool bRC = true; - bool bExit = false; - - if (!IsCTRLpressed(nFlag)) { - if (m_pFillerNotify) { - CFX_WideString swChange; - - int nSelStart = 0; - int nSelEnd = 0; - GetSel(nSelStart, nSelEnd); - - switch (nChar) { - case FWL_VKEY_Back: - if (nSelStart == nSelEnd) - nSelStart = nSelEnd - 1; - break; - case FWL_VKEY_Return: - break; - default: - swChange += nChar; - break; - } - - CFX_WideString strChangeEx; - m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), swChange, - strChangeEx, nSelStart, nSelEnd, true, - bRC, bExit, nFlag); - } - } - - if (!bRC) - return true; - if (bExit) - return false; - - if (IPVT_FontMap* pFontMap = GetFontMap()) { - int32_t nOldCharSet = GetCharSet(); - int32_t nNewCharSet = - pFontMap->CharSetFromUnicode(nChar, FXFONT_DEFAULT_CHARSET); - if (nOldCharSet != nNewCharSet) { - SetCharSet(nNewCharSet); - } - } - - return CPWL_EditCtrl::OnChar(nChar, nFlag); -} - -bool CPWL_Edit::OnMouseWheel(short zDelta, - const CFX_PointF& point, - uint32_t nFlag) { - if (HasFlag(PES_MULTILINE)) { - CFX_PointF ptScroll = GetScrollPos(); - - if (zDelta > 0) { - ptScroll.y += GetFontSize(); - } else { - ptScroll.y -= GetFontSize(); - } - SetScrollPos(ptScroll); - - return true; - } - - return false; -} - -void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace) { - if (HasFlag(PES_SPELLCHECK)) { - m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), - GetLatinWordsRange(place))); - } -} - -void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace) { - if (HasFlag(PES_SPELLCHECK)) { - m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), - GetLatinWordsRange(place))); - } -} - -void CPWL_Edit::OnDelete(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace) { - if (HasFlag(PES_SPELLCHECK)) { - m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), - GetLatinWordsRange(place))); - } -} - -void CPWL_Edit::OnClear(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace) { - if (HasFlag(PES_SPELLCHECK)) { - m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), - GetLatinWordsRange(place))); - } -} - -void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace) { - if (HasFlag(PES_SPELLCHECK)) { - m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), - GetLatinWordsRange(place))); - } -} - -void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace) { - if (HasFlag(PES_SPELLCHECK)) { - m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), - GetLatinWordsRange(place))); - } -} - -CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1, - const CPVT_WordRange& wr2) { - CPVT_WordRange wrRet; - - if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) { - wrRet.BeginPos = wr1.BeginPos; - } else { - wrRet.BeginPos = wr2.BeginPos; - } - - if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) { - wrRet.EndPos = wr2.EndPos; - } else { - wrRet.EndPos = wr1.EndPos; - } - - return wrRet; -} - -CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CFX_PointF& point) const { - return GetSameWordsRange(m_pEdit->SearchWordPlace(point), true, false); -} - -CPVT_WordRange CPWL_Edit::GetLatinWordsRange( - const CPVT_WordPlace& place) const { - return GetSameWordsRange(place, true, false); -} - -CPVT_WordRange CPWL_Edit::GetArabicWordsRange( - const CPVT_WordPlace& place) const { - return GetSameWordsRange(place, false, true); -} - -#define PWL_ISARABICWORD(word) \ - ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC)) - -CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace& place, - bool bLatin, - bool bArabic) const { - CPVT_WordRange range; - - CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator(); - CPVT_Word wordinfo; - CPVT_WordPlace wpStart(place), wpEnd(place); - pIterator->SetAt(place); - - if (bLatin) { - while (pIterator->NextWord()) { - if (!pIterator->GetWord(wordinfo) || - !FX_EDIT_ISLATINWORD(wordinfo.Word)) { - break; - } - - wpEnd = pIterator->GetAt(); - } - } else if (bArabic) { - while (pIterator->NextWord()) { - if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word)) - break; - - wpEnd = pIterator->GetAt(); - } - } - - pIterator->SetAt(place); - - if (bLatin) { - do { - if (!pIterator->GetWord(wordinfo) || - !FX_EDIT_ISLATINWORD(wordinfo.Word)) { - break; - } - - wpStart = pIterator->GetAt(); - } while (pIterator->PrevWord()); - } else if (bArabic) { - do { - if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word)) - break; - - wpStart = pIterator->GetAt(); - } while (pIterator->PrevWord()); - } - - range.Set(wpStart, wpEnd); - return range; -} diff --git a/fpdfsdk/pdfwindow/PWL_Edit.h b/fpdfsdk/pdfwindow/PWL_Edit.h deleted file mode 100644 index b6d01300f04659ab1c82d1b5684de91b62ba164b..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Edit.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_EDIT_H_ -#define FPDFSDK_PDFWINDOW_PWL_EDIT_H_ - -#include - -#include "core/fxcrt/fx_basic.h" -#include "fpdfsdk/fxedit/fx_edit.h" -#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CPDF_PageObjectHolder; -class CPDF_TextObject; -class IFX_Edit_UndoItem; - -class IPWL_Filler_Notify { - public: - virtual ~IPWL_Filler_Notify() {} - virtual void QueryWherePopup( - void* pPrivateData, - FX_FLOAT fPopupMin, - FX_FLOAT fPopupMax, - int32_t& nRet, - FX_FLOAT& fPopupRet) = 0; // nRet: (0:bottom 1:top) - virtual void OnBeforeKeyStroke(void* pPrivateData, - CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - int nSelStart, - int nSelEnd, - bool bKeyDown, - bool& bRC, - bool& bExit, - uint32_t nFlag) = 0; -#ifdef PDF_ENABLE_XFA - virtual void OnPopupPreOpen(void* pPrivateData, - bool& bExit, - uint32_t nFlag) = 0; - virtual void OnPopupPostOpen(void* pPrivateData, - bool& bExit, - uint32_t nFlag) = 0; -#endif // PDF_ENABLE_XFA -}; - -class CPWL_Edit : public CPWL_EditCtrl { - public: - CPWL_Edit(); - ~CPWL_Edit() override; - - // CPWL_EditCtrl - CFX_ByteString GetClassName() const override; - void OnDestroy() override; - void OnCreated() override; - void RePosChildWnd() override; - CFX_FloatRect GetClientRect() const override; - void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override; - void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) override; - bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnMouseWheel(short zDelta, - const CFX_PointF& point, - uint32_t nFlag) override; - bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - CFX_FloatRect GetFocusRect() const override; - void OnSetFocus() override; - void OnKillFocus() override; - - void SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat = PEAV_TOP, - bool bPaint = true); // 0:top 1:bottom 2:center - - void SetCharArray(int32_t nCharArray); - void SetLimitChar(int32_t nLimitChar); - - void SetCharSpace(FX_FLOAT fCharSpace); - - bool CanSelectAll() const; - bool CanClear() const; - bool CanCopy() const; - bool CanCut() const; - - void CutText(); - - void SetText(const CFX_WideString& csText); - void ReplaceSel(const CFX_WideString& csText); - - CFX_ByteString GetTextAppearanceStream(const CFX_PointF& ptOffset) const; - CFX_ByteString GetCaretAppearanceStream(const CFX_PointF& ptOffset) const; - CFX_ByteString GetSelectAppearanceStream(const CFX_PointF& ptOffset) const; - - bool IsTextFull() const; - - static FX_FLOAT GetCharArrayAutoFontSize(CPDF_Font* pFont, - const CFX_FloatRect& rcPlate, - int32_t nCharArray); - - void SetFillerNotify(IPWL_Filler_Notify* pNotify) { - m_pFillerNotify = pNotify; - } - - bool IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag); - void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; } - - void OnInsertWord(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace); - void OnInsertReturn(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace); - void OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace); - void OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace); - void OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace); - void OnInsertText(const CPVT_WordPlace& place, - const CPVT_WordPlace& oldplace); - - private: - CPVT_WordRange GetSelectWordRange() const; - virtual void ShowVScrollBar(bool bShow); - bool IsVScrollBarVisible() const; - void SetParamByFlag(); - - FX_FLOAT GetCharArrayAutoFontSize(int32_t nCharArray); - CFX_PointF GetWordRightBottomPoint(const CPVT_WordPlace& wpWord); - - CPVT_WordRange CombineWordRange(const CPVT_WordRange& wr1, - const CPVT_WordRange& wr2); - CPVT_WordRange GetLatinWordsRange(const CFX_PointF& point) const; - CPVT_WordRange GetLatinWordsRange(const CPVT_WordPlace& place) const; - CPVT_WordRange GetArabicWordsRange(const CPVT_WordPlace& place) const; - CPVT_WordRange GetSameWordsRange(const CPVT_WordPlace& place, - bool bLatin, - bool bArabic) const; - IPWL_Filler_Notify* m_pFillerNotify; - bool m_bFocus; - CFX_FloatRect m_rcOldWindow; - CFFL_FormFiller* m_pFormFiller; // Not owned. -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_EDIT_H_ diff --git a/fpdfsdk/pdfwindow/PWL_EditCtrl.cpp b/fpdfsdk/pdfwindow/PWL_EditCtrl.cpp deleted file mode 100644 index 4921ab7a08b64d23fe3c6477140f22adfbe42b83..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_EditCtrl.cpp +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" - -#include "core/fpdfdoc/cpvt_section.h" -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fxge/fx_font.h" -#include "fpdfsdk/fxedit/fxet_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Caret.h" -#include "fpdfsdk/pdfwindow/PWL_FontMap.h" -#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" -#include "public/fpdf_fwlevent.h" - -CPWL_EditCtrl::CPWL_EditCtrl() - : m_pEdit(new CFX_Edit), - m_pEditCaret(nullptr), - m_bMouseDown(false), - m_nCharSet(FXFONT_DEFAULT_CHARSET), - m_nCodePage(0) {} - -CPWL_EditCtrl::~CPWL_EditCtrl() {} - -void CPWL_EditCtrl::OnCreate(PWL_CREATEPARAM& cp) { - cp.eCursorType = FXCT_VBEAM; -} - -void CPWL_EditCtrl::OnCreated() { - SetFontSize(GetCreationParam().fFontSize); - - m_pEdit->SetFontMap(GetFontMap()); - m_pEdit->SetNotify(this); - m_pEdit->Initialize(); -} - -bool CPWL_EditCtrl::IsWndHorV() { - CFX_Matrix mt = GetWindowMatrix(); - return mt.Transform(CFX_PointF(1, 1)).y == mt.Transform(CFX_PointF(0, 1)).y; -} - -void CPWL_EditCtrl::SetCursor() { - if (IsValid()) { - if (CFX_SystemHandler* pSH = GetSystemHandler()) { - if (IsWndHorV()) - pSH->SetCursor(FXCT_VBEAM); - else - pSH->SetCursor(FXCT_HBEAM); - } - } -} - -void CPWL_EditCtrl::RePosChildWnd() { - m_pEdit->SetPlateRect(GetClientRect()); -} - -void CPWL_EditCtrl::OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam, - intptr_t lParam) { - CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); - - switch (msg) { - case PNM_SETSCROLLINFO: - switch (wParam) { - case SBT_VSCROLL: - if (CPWL_Wnd* pChild = GetVScrollBar()) { - pChild->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam); - } - break; - } - break; - case PNM_SETSCROLLPOS: - switch (wParam) { - case SBT_VSCROLL: - if (CPWL_Wnd* pChild = GetVScrollBar()) { - pChild->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam); - } - break; - } - break; - case PNM_SCROLLWINDOW: { - FX_FLOAT fPos = *(FX_FLOAT*)lParam; - switch (wParam) { - case SBT_VSCROLL: - m_pEdit->SetScrollPos(CFX_PointF(m_pEdit->GetScrollPos().x, fPos)); - break; - } - } break; - case PNM_SETCARETINFO: { - if (PWL_CARET_INFO* pCaretInfo = (PWL_CARET_INFO*)wParam) { - SetCaret(pCaretInfo->bVisible, pCaretInfo->ptHead, pCaretInfo->ptFoot); - } - } break; - } -} - -void CPWL_EditCtrl::CreateChildWnd(const PWL_CREATEPARAM& cp) { - if (!IsReadOnly()) - CreateEditCaret(cp); -} - -void CPWL_EditCtrl::CreateEditCaret(const PWL_CREATEPARAM& cp) { - if (m_pEditCaret) - return; - - m_pEditCaret = new CPWL_Caret; - m_pEditCaret->SetInvalidRect(GetClientRect()); - - PWL_CREATEPARAM ecp = cp; - ecp.pParentWnd = this; - ecp.dwFlags = PWS_CHILD | PWS_NOREFRESHCLIP; - ecp.dwBorderWidth = 0; - ecp.nBorderStyle = BorderStyle::SOLID; - ecp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0); - - m_pEditCaret->Create(ecp); -} - -void CPWL_EditCtrl::SetFontSize(FX_FLOAT fFontSize) { - m_pEdit->SetFontSize(fFontSize); -} - -FX_FLOAT CPWL_EditCtrl::GetFontSize() const { - return m_pEdit->GetFontSize(); -} - -bool CPWL_EditCtrl::OnKeyDown(uint16_t nChar, uint32_t nFlag) { - if (m_bMouseDown) - return true; - - bool bRet = CPWL_Wnd::OnKeyDown(nChar, nFlag); - - // FILTER - switch (nChar) { - default: - return false; - case FWL_VKEY_Delete: - case FWL_VKEY_Up: - case FWL_VKEY_Down: - case FWL_VKEY_Left: - case FWL_VKEY_Right: - case FWL_VKEY_Home: - case FWL_VKEY_End: - case FWL_VKEY_Insert: - case 'C': - case 'V': - case 'X': - case 'A': - case 'Z': - case 'c': - case 'v': - case 'x': - case 'a': - case 'z': - break; - } - - if (nChar == FWL_VKEY_Delete && m_pEdit->IsSelected()) - nChar = FWL_VKEY_Unknown; - - switch (nChar) { - case FWL_VKEY_Delete: - Delete(); - return true; - case FWL_VKEY_Insert: - if (IsSHIFTpressed(nFlag)) - PasteText(); - return true; - case FWL_VKEY_Up: - m_pEdit->OnVK_UP(IsSHIFTpressed(nFlag), false); - return true; - case FWL_VKEY_Down: - m_pEdit->OnVK_DOWN(IsSHIFTpressed(nFlag), false); - return true; - case FWL_VKEY_Left: - m_pEdit->OnVK_LEFT(IsSHIFTpressed(nFlag), false); - return true; - case FWL_VKEY_Right: - m_pEdit->OnVK_RIGHT(IsSHIFTpressed(nFlag), false); - return true; - case FWL_VKEY_Home: - m_pEdit->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - return true; - case FWL_VKEY_End: - m_pEdit->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - return true; - case FWL_VKEY_Unknown: - if (!IsSHIFTpressed(nFlag)) - Clear(); - else - CutText(); - return true; - default: - break; - } - - return bRet; -} - -bool CPWL_EditCtrl::OnChar(uint16_t nChar, uint32_t nFlag) { - if (m_bMouseDown) - return true; - - CPWL_Wnd::OnChar(nChar, nFlag); - - // FILTER - switch (nChar) { - case 0x0A: - case 0x1B: - return false; - default: - break; - } - - bool bCtrl = IsCTRLpressed(nFlag); - bool bAlt = IsALTpressed(nFlag); - bool bShift = IsSHIFTpressed(nFlag); - - uint16_t word = nChar; - - if (bCtrl && !bAlt) { - switch (nChar) { - case 'C' - 'A' + 1: - CopyText(); - return true; - case 'V' - 'A' + 1: - PasteText(); - return true; - case 'X' - 'A' + 1: - CutText(); - return true; - case 'A' - 'A' + 1: - SelectAll(); - return true; - case 'Z' - 'A' + 1: - if (bShift) - Redo(); - else - Undo(); - return true; - default: - if (nChar < 32) - return false; - } - } - - if (IsReadOnly()) - return true; - - if (m_pEdit->IsSelected() && word == FWL_VKEY_Back) - word = FWL_VKEY_Unknown; - - Clear(); - - switch (word) { - case FWL_VKEY_Back: - Backspace(); - break; - case FWL_VKEY_Return: - InsertReturn(); - break; - case FWL_VKEY_Unknown: - break; - default: - InsertWord(word, GetCharSet()); - break; - } - - return true; -} - -bool CPWL_EditCtrl::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - if (ClientHitTest(point)) { - if (m_bMouseDown) - InvalidateRect(); - - m_bMouseDown = true; - SetCapture(); - - m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - } - - return true; -} - -bool CPWL_EditCtrl::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - if (m_bMouseDown) { - // can receive keybord message - if (ClientHitTest(point) && !IsFocused()) - SetFocus(); - - ReleaseCapture(); - m_bMouseDown = false; - } - - return true; -} - -bool CPWL_EditCtrl::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnMouseMove(point, nFlag); - - if (m_bMouseDown) - m_pEdit->OnMouseMove(point, false, false); - - return true; -} - -CFX_FloatRect CPWL_EditCtrl::GetContentRect() const { - return m_pEdit->GetContentRect(); -} - -void CPWL_EditCtrl::SetEditCaret(bool bVisible) { - CFX_PointF ptHead; - CFX_PointF ptFoot; - if (bVisible) - GetCaretInfo(&ptHead, &ptFoot); - - CPVT_WordPlace wpTemp = m_pEdit->GetCaretWordPlace(); - IOnSetCaret(bVisible, ptHead, ptFoot, wpTemp); -} - -void CPWL_EditCtrl::GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const { - CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator(); - pIterator->SetAt(m_pEdit->GetCaret()); - CPVT_Word word; - CPVT_Line line; - if (pIterator->GetWord(word)) { - ptHead->x = word.ptWord.x + word.fWidth; - ptHead->y = word.ptWord.y + word.fAscent; - ptFoot->x = word.ptWord.x + word.fWidth; - ptFoot->y = word.ptWord.y + word.fDescent; - } else if (pIterator->GetLine(line)) { - ptHead->x = line.ptLine.x; - ptHead->y = line.ptLine.y + line.fLineAscent; - ptFoot->x = line.ptLine.x; - ptFoot->y = line.ptLine.y + line.fLineDescent; - } -} - -void CPWL_EditCtrl::SetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot) { - if (m_pEditCaret) { - if (!IsFocused() || m_pEdit->IsSelected()) - bVisible = false; - - m_pEditCaret->SetCaret(bVisible, ptHead, ptFoot); - } -} - -CFX_WideString CPWL_EditCtrl::GetText() const { - return m_pEdit->GetText(); -} - -void CPWL_EditCtrl::SetSel(int32_t nStartChar, int32_t nEndChar) { - m_pEdit->SetSel(nStartChar, nEndChar); -} - -void CPWL_EditCtrl::GetSel(int32_t& nStartChar, int32_t& nEndChar) const { - m_pEdit->GetSel(nStartChar, nEndChar); -} - -void CPWL_EditCtrl::Clear() { - if (!IsReadOnly()) - m_pEdit->Clear(); -} - -void CPWL_EditCtrl::SelectAll() { - m_pEdit->SelectAll(); -} - -void CPWL_EditCtrl::Paint() { - m_pEdit->Paint(); -} - -void CPWL_EditCtrl::EnableRefresh(bool bRefresh) { - m_pEdit->EnableRefresh(bRefresh); -} - -int32_t CPWL_EditCtrl::GetCaret() const { - return m_pEdit->GetCaret(); -} - -void CPWL_EditCtrl::SetCaret(int32_t nPos) { - m_pEdit->SetCaret(nPos); -} - -int32_t CPWL_EditCtrl::GetTotalWords() const { - return m_pEdit->GetTotalWords(); -} - -void CPWL_EditCtrl::SetScrollPos(const CFX_PointF& point) { - m_pEdit->SetScrollPos(point); -} - -CFX_PointF CPWL_EditCtrl::GetScrollPos() const { - return m_pEdit->GetScrollPos(); -} - -CPDF_Font* CPWL_EditCtrl::GetCaretFont() const { - int32_t nFontIndex = 0; - - CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator(); - pIterator->SetAt(m_pEdit->GetCaret()); - CPVT_Word word; - CPVT_Section section; - if (pIterator->GetWord(word)) { - nFontIndex = word.nFontIndex; - } else if (HasFlag(PES_RICH)) { - if (pIterator->GetSection(section)) { - nFontIndex = section.WordProps.nFontIndex; - } - } - - if (IPVT_FontMap* pFontMap = GetFontMap()) - return pFontMap->GetPDFFont(nFontIndex); - - return nullptr; -} - -FX_FLOAT CPWL_EditCtrl::GetCaretFontSize() const { - FX_FLOAT fFontSize = GetFontSize(); - - CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator(); - pIterator->SetAt(m_pEdit->GetCaret()); - CPVT_Word word; - CPVT_Section section; - if (pIterator->GetWord(word)) { - fFontSize = word.fFontSize; - } else if (HasFlag(PES_RICH)) { - if (pIterator->GetSection(section)) { - fFontSize = section.WordProps.fFontSize; - } - } - - return fFontSize; -} - -void CPWL_EditCtrl::SetText(const CFX_WideString& wsText) { - m_pEdit->SetText(wsText); -} - -void CPWL_EditCtrl::CopyText() {} - -void CPWL_EditCtrl::PasteText() {} - -void CPWL_EditCtrl::CutText() {} - -void CPWL_EditCtrl::ShowVScrollBar(bool bShow) {} - -void CPWL_EditCtrl::InsertText(const CFX_WideString& wsText) { - if (!IsReadOnly()) - m_pEdit->InsertText(wsText, FXFONT_DEFAULT_CHARSET); -} - -void CPWL_EditCtrl::InsertWord(uint16_t word, int32_t nCharset) { - if (!IsReadOnly()) - m_pEdit->InsertWord(word, nCharset); -} - -void CPWL_EditCtrl::InsertReturn() { - if (!IsReadOnly()) - m_pEdit->InsertReturn(); -} - -void CPWL_EditCtrl::Delete() { - if (!IsReadOnly()) - m_pEdit->Delete(); -} - -void CPWL_EditCtrl::Backspace() { - if (!IsReadOnly()) - m_pEdit->Backspace(); -} - -bool CPWL_EditCtrl::CanUndo() const { - return !IsReadOnly() && m_pEdit->CanUndo(); -} - -bool CPWL_EditCtrl::CanRedo() const { - return !IsReadOnly() && m_pEdit->CanRedo(); -} - -void CPWL_EditCtrl::Redo() { - if (CanRedo()) - m_pEdit->Redo(); -} - -void CPWL_EditCtrl::Undo() { - if (CanUndo()) - m_pEdit->Undo(); -} - -void CPWL_EditCtrl::IOnSetScrollInfoY(FX_FLOAT fPlateMin, - FX_FLOAT fPlateMax, - FX_FLOAT fContentMin, - FX_FLOAT fContentMax, - FX_FLOAT fSmallStep, - FX_FLOAT fBigStep) { - PWL_SCROLL_INFO Info; - - Info.fPlateWidth = fPlateMax - fPlateMin; - Info.fContentMin = fContentMin; - Info.fContentMax = fContentMax; - Info.fSmallStep = fSmallStep; - Info.fBigStep = fBigStep; - - OnNotify(this, PNM_SETSCROLLINFO, SBT_VSCROLL, (intptr_t)&Info); - - if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) || - IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) { - ShowVScrollBar(false); - } else { - ShowVScrollBar(true); - } -} - -void CPWL_EditCtrl::IOnSetScrollPosY(FX_FLOAT fy) { - OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&fy); -} - -void CPWL_EditCtrl::IOnSetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot, - const CPVT_WordPlace& place) { - PWL_CARET_INFO cInfo; - cInfo.bVisible = bVisible; - cInfo.ptHead = ptHead; - cInfo.ptFoot = ptFoot; - - OnNotify(this, PNM_SETCARETINFO, (intptr_t)&cInfo, (intptr_t) nullptr); -} - -void CPWL_EditCtrl::IOnCaretChange(const CPVT_SecProps& secProps, - const CPVT_WordProps& wordProps) {} - -void CPWL_EditCtrl::IOnContentChange(const CFX_FloatRect& rcContent) {} - -void CPWL_EditCtrl::IOnInvalidateRect(CFX_FloatRect* pRect) { - InvalidateRect(pRect); -} - -int32_t CPWL_EditCtrl::GetCharSet() const { - return m_nCharSet < 0 ? FXFONT_DEFAULT_CHARSET : m_nCharSet; -} - -void CPWL_EditCtrl::GetTextRange(const CFX_FloatRect& rect, - int32_t& nStartChar, - int32_t& nEndChar) const { - nStartChar = m_pEdit->WordPlaceToWordIndex( - m_pEdit->SearchWordPlace(CFX_PointF(rect.left, rect.top))); - nEndChar = m_pEdit->WordPlaceToWordIndex( - m_pEdit->SearchWordPlace(CFX_PointF(rect.right, rect.bottom))); -} - -CFX_WideString CPWL_EditCtrl::GetText(int32_t& nStartChar, - int32_t& nEndChar) const { - CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStartChar); - CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEndChar); - return m_pEdit->GetRangeText(CPVT_WordRange(wpStart, wpEnd)); -} - -void CPWL_EditCtrl::SetReadyToInput() { - if (m_bMouseDown) { - ReleaseCapture(); - m_bMouseDown = false; - } -} diff --git a/fpdfsdk/pdfwindow/PWL_EditCtrl.h b/fpdfsdk/pdfwindow/PWL_EditCtrl.h deleted file mode 100644 index 498570b3b0829f0cb56cf11b27771edfa3abad86..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_EditCtrl.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_EDITCTRL_H_ -#define FPDFSDK_PDFWINDOW_PWL_EDITCTRL_H_ - -#include - -#include "core/fxcrt/fx_string.h" -#include "fpdfsdk/fxedit/fx_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CFX_Edit; -class CPWL_Caret; -class CPWL_Edit; -class CPWL_EditCtrl; -struct CPVT_SecProps; -struct CPVT_WordPlace; -struct CPVT_WordProps; -struct CPVT_WordRange; - -enum PWL_EDIT_ALIGNFORMAT_H { PEAH_LEFT = 0, PEAH_MIDDLE, PEAH_RIGHT }; - -enum PWL_EDIT_ALIGNFORMAT_V { PEAV_TOP = 0, PEAV_CENTER, PEAV_BOTTOM }; - -class CPWL_EditCtrl : public CPWL_Wnd { - friend class CPWL_Edit_Notify; - - public: - CPWL_EditCtrl(); - ~CPWL_EditCtrl() override; - - CFX_FloatRect GetContentRect() const; - - CFX_WideString GetText() const; - void SetSel(int32_t nStartChar, int32_t nEndChar); - void GetSel(int32_t& nStartChar, int32_t& nEndChar) const; - void GetTextRange(const CFX_FloatRect& rect, - int32_t& nStartChar, - int32_t& nEndChar) const; - CFX_WideString GetText(int32_t& nStartChar, int32_t& nEndChar) const; - void Clear(); - void SelectAll(); - - int32_t GetCaret() const; - void SetCaret(int32_t nPos); - int32_t GetTotalWords() const; - - void Paint(); - - void EnableRefresh(bool bRefresh); - CFX_PointF GetScrollPos() const; - void SetScrollPos(const CFX_PointF& point); - - void SetCharSet(uint8_t nCharSet) { m_nCharSet = nCharSet; } - int32_t GetCharSet() const; - - void SetCodePage(int32_t nCodePage) { m_nCodePage = nCodePage; } - int32_t GetCodePage() const { return m_nCodePage; } - - CPDF_Font* GetCaretFont() const; - FX_FLOAT GetCaretFontSize() const; - - bool CanUndo() const; - bool CanRedo() const; - void Redo(); - void Undo(); - - void SetReadyToInput(); - - // CPWL_Wnd - void OnCreate(PWL_CREATEPARAM& cp) override; - void OnCreated() override; - bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; - void OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam = 0, - intptr_t lParam = 0) override; - void CreateChildWnd(const PWL_CREATEPARAM& cp) override; - void RePosChildWnd() override; - void SetFontSize(FX_FLOAT fFontSize) override; - FX_FLOAT GetFontSize() const override; - void SetCursor() override; - - void IOnSetScrollInfoY(FX_FLOAT fPlateMin, - FX_FLOAT fPlateMax, - FX_FLOAT fContentMin, - FX_FLOAT fContentMax, - FX_FLOAT fSmallStep, - FX_FLOAT fBigStep); - void IOnSetScrollPosY(FX_FLOAT fy); - void IOnSetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot, - const CPVT_WordPlace& place); - void IOnCaretChange(const CPVT_SecProps& secProps, - const CPVT_WordProps& wordProps); - void IOnContentChange(const CFX_FloatRect& rcContent); - void IOnInvalidateRect(CFX_FloatRect* pRect); - - protected: - void InsertText(const CFX_WideString& wsText); - void SetText(const CFX_WideString& wsText); - void CopyText(); - void PasteText(); - void CutText(); - void ShowVScrollBar(bool bShow); - void InsertWord(uint16_t word, int32_t nCharset); - void InsertReturn(); - - bool IsWndHorV(); - - void Delete(); - void Backspace(); - - void GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const; - void SetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot); - - void SetEditCaret(bool bVisible); - - std::unique_ptr m_pEdit; - CPWL_Caret* m_pEditCaret; - bool m_bMouseDown; - - private: - void CreateEditCaret(const PWL_CREATEPARAM& cp); - - int32_t m_nCharSet; - int32_t m_nCodePage; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_EDITCTRL_H_ diff --git a/fpdfsdk/pdfwindow/PWL_FontMap.cpp b/fpdfsdk/pdfwindow/PWL_FontMap.cpp deleted file mode 100644 index 9a2962cd5675cbab62de16864130354b148dedda..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_FontMap.cpp +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_FontMap.h" - -#include - -#include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfapi/font/cpdf_fontencoding.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_parser.h" -#include "core/fpdfdoc/ipvt_fontmap.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -const char kDefaultFontName[] = "Helvetica"; - -const char* const g_sDEStandardFontName[] = {"Courier", - "Courier-Bold", - "Courier-BoldOblique", - "Courier-Oblique", - "Helvetica", - "Helvetica-Bold", - "Helvetica-BoldOblique", - "Helvetica-Oblique", - "Times-Roman", - "Times-Bold", - "Times-Italic", - "Times-BoldItalic", - "Symbol", - "ZapfDingbats"}; - -} // namespace - -CPWL_FontMap::CPWL_FontMap(CFX_SystemHandler* pSystemHandler) - : m_pSystemHandler(pSystemHandler) { - ASSERT(m_pSystemHandler); -} - -CPWL_FontMap::~CPWL_FontMap() { - Empty(); -} - -CPDF_Document* CPWL_FontMap::GetDocument() { - if (!m_pPDFDoc) { - if (CPDF_ModuleMgr::Get()) { - m_pPDFDoc = pdfium::MakeUnique(nullptr); - m_pPDFDoc->CreateNewDoc(); - } - } - - return m_pPDFDoc.get(); -} - -CPDF_Font* CPWL_FontMap::GetPDFFont(int32_t nFontIndex) { - if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize(m_Data)) { - if (m_Data[nFontIndex]) - return m_Data[nFontIndex]->pFont; - } - return nullptr; -} - -CFX_ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) { - if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize(m_Data)) { - if (m_Data[nFontIndex]) - return m_Data[nFontIndex]->sFontName; - } - return CFX_ByteString(); -} - -bool CPWL_FontMap::KnowWord(int32_t nFontIndex, uint16_t word) { - if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize(m_Data)) { - if (m_Data[nFontIndex]) - return CharCodeFromUnicode(nFontIndex, word) >= 0; - } - return false; -} - -int32_t CPWL_FontMap::GetWordFontIndex(uint16_t word, - int32_t nCharset, - int32_t nFontIndex) { - if (nFontIndex > 0) { - if (KnowWord(nFontIndex, word)) - return nFontIndex; - } else { - if (const CPWL_FontMap_Data* pData = GetFontMapData(0)) { - if (nCharset == FXFONT_DEFAULT_CHARSET || - pData->nCharset == FXFONT_SYMBOL_CHARSET || - nCharset == pData->nCharset) { - if (KnowWord(0, word)) - return 0; - } - } - } - - int32_t nNewFontIndex = - GetFontIndex(GetNativeFontName(nCharset), nCharset, true); - if (nNewFontIndex >= 0) { - if (KnowWord(nNewFontIndex, word)) - return nNewFontIndex; - } - nNewFontIndex = - GetFontIndex("Arial Unicode MS", FXFONT_DEFAULT_CHARSET, false); - if (nNewFontIndex >= 0) { - if (KnowWord(nNewFontIndex, word)) - return nNewFontIndex; - } - return -1; -} - -int32_t CPWL_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) { - if (nFontIndex < 0 || nFontIndex >= pdfium::CollectionSize(m_Data)) - return -1; - - CPWL_FontMap_Data* pData = m_Data[nFontIndex].get(); - if (!pData || !pData->pFont) - return -1; - - if (pData->pFont->IsUnicodeCompatible()) - return pData->pFont->CharCodeFromUnicode(word); - - return word < 0xFF ? word : -1; -} - -CFX_ByteString CPWL_FontMap::GetNativeFontName(int32_t nCharset) { - for (const auto& pData : m_NativeFont) { - if (pData && pData->nCharset == nCharset) - return pData->sFontName; - } - - CFX_ByteString sNew = GetNativeFont(nCharset); - if (sNew.IsEmpty()) - return CFX_ByteString(); - - auto pNewData = pdfium::MakeUnique(); - pNewData->nCharset = nCharset; - pNewData->sFontName = sNew; - m_NativeFont.push_back(std::move(pNewData)); - return sNew; -} - -void CPWL_FontMap::Empty() { - m_Data.clear(); - m_NativeFont.clear(); -} - -void CPWL_FontMap::Initialize() { - GetFontIndex(kDefaultFontName, FXFONT_ANSI_CHARSET, false); -} - -bool CPWL_FontMap::IsStandardFont(const CFX_ByteString& sFontName) { - for (size_t i = 0; i < FX_ArraySize(g_sDEStandardFontName); ++i) { - if (sFontName == g_sDEStandardFontName[i]) - return true; - } - - return false; -} - -int32_t CPWL_FontMap::FindFont(const CFX_ByteString& sFontName, - int32_t nCharset) { - int32_t i = 0; - for (const auto& pData : m_Data) { - if (pData && - (nCharset == FXFONT_DEFAULT_CHARSET || nCharset == pData->nCharset) && - (sFontName.IsEmpty() || pData->sFontName == sFontName)) { - return i; - } - ++i; - } - return -1; -} - -int32_t CPWL_FontMap::GetFontIndex(const CFX_ByteString& sFontName, - int32_t nCharset, - bool bFind) { - int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset); - if (nFontIndex >= 0) - return nFontIndex; - - CFX_ByteString sAlias; - CPDF_Font* pFont = nullptr; - if (bFind) - pFont = FindFontSameCharset(sAlias, nCharset); - - if (!pFont) { - CFX_ByteString sTemp = sFontName; - pFont = AddFontToDocument(GetDocument(), sTemp, nCharset); - sAlias = EncodeFontAlias(sTemp, nCharset); - } - AddedFont(pFont, sAlias); - return AddFontData(pFont, sAlias, nCharset); -} - -CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, - int32_t nCharset) { - return nullptr; -} - -int32_t CPWL_FontMap::AddFontData(CPDF_Font* pFont, - const CFX_ByteString& sFontAlias, - int32_t nCharset) { - auto pNewData = pdfium::MakeUnique(); - pNewData->pFont = pFont; - pNewData->sFontName = sFontAlias; - pNewData->nCharset = nCharset; - m_Data.push_back(std::move(pNewData)); - return pdfium::CollectionSize(m_Data) - 1; -} - -void CPWL_FontMap::AddedFont(CPDF_Font* pFont, - const CFX_ByteString& sFontAlias) {} - -CFX_ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) { - if (nCharset == FXFONT_DEFAULT_CHARSET) - nCharset = GetNativeCharset(); - - CFX_ByteString sFontName = GetDefaultFontByCharset(nCharset); - if (!m_pSystemHandler->FindNativeTrueTypeFont(sFontName)) - return CFX_ByteString(); - - return sFontName; -} - -CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc, - CFX_ByteString& sFontName, - uint8_t nCharset) { - if (IsStandardFont(sFontName)) - return AddStandardFont(pDoc, sFontName); - - return AddSystemFont(pDoc, sFontName, nCharset); -} - -CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc, - CFX_ByteString& sFontName) { - if (!pDoc) - return nullptr; - - CPDF_Font* pFont = nullptr; - - if (sFontName == "ZapfDingbats") { - pFont = pDoc->AddStandardFont(sFontName.c_str(), nullptr); - } else { - CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI); - pFont = pDoc->AddStandardFont(sFontName.c_str(), &fe); - } - - return pFont; -} - -CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc, - CFX_ByteString& sFontName, - uint8_t nCharset) { - if (!pDoc) - return nullptr; - - if (sFontName.IsEmpty()) - sFontName = GetNativeFont(nCharset); - if (nCharset == FXFONT_DEFAULT_CHARSET) - nCharset = GetNativeCharset(); - - return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName, - nCharset); -} - -CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName, - int32_t nCharset) { - CFX_ByteString sPostfix; - sPostfix.Format("_%02X", nCharset); - return EncodeFontAlias(sFontName) + sPostfix; -} - -CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName) { - CFX_ByteString sRet = sFontName; - sRet.Remove(' '); - return sRet; -} - -const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const { - if (nIndex < 0 || nIndex >= pdfium::CollectionSize(m_Data)) - return nullptr; - - return m_Data[nIndex].get(); -} - -int32_t CPWL_FontMap::GetNativeCharset() { - uint8_t nCharset = FXFONT_ANSI_CHARSET; - int32_t iCodePage = FXSYS_GetACP(); - switch (iCodePage) { - case 932: // Japan - nCharset = FXFONT_SHIFTJIS_CHARSET; - break; - case 936: // Chinese (PRC, Singapore) - nCharset = FXFONT_GB2312_CHARSET; - break; - case 950: // Chinese (Taiwan; Hong Kong SAR, PRC) - nCharset = FXFONT_GB2312_CHARSET; - break; - case 1252: // Windows 3.1 Latin 1 (US, Western Europe) - nCharset = FXFONT_ANSI_CHARSET; - break; - case 874: // Thai - nCharset = FXFONT_THAI_CHARSET; - break; - case 949: // Korean - nCharset = FXFONT_HANGUL_CHARSET; - break; - case 1200: // Unicode (BMP of ISO 10646) - nCharset = FXFONT_ANSI_CHARSET; - break; - case 1250: // Windows 3.1 Eastern European - nCharset = FXFONT_EASTEUROPE_CHARSET; - break; - case 1251: // Windows 3.1 Cyrillic - nCharset = FXFONT_RUSSIAN_CHARSET; - break; - case 1253: // Windows 3.1 Greek - nCharset = FXFONT_GREEK_CHARSET; - break; - case 1254: // Windows 3.1 Turkish - nCharset = FXFONT_TURKISH_CHARSET; - break; - case 1255: // Hebrew - nCharset = FXFONT_HEBREW_CHARSET; - break; - case 1256: // Arabic - nCharset = FXFONT_ARABIC_CHARSET; - break; - case 1257: // Baltic - nCharset = FXFONT_BALTIC_CHARSET; - break; - case 1258: // Vietnamese - nCharset = FXFONT_VIETNAMESE_CHARSET; - break; - case 1361: // Korean(Johab) - nCharset = FXFONT_JOHAB_CHARSET; - break; - } - return nCharset; -} - -const FPDF_CharsetFontMap CPWL_FontMap::defaultTTFMap[] = { - {FXFONT_ANSI_CHARSET, "Helvetica"}, - {FXFONT_GB2312_CHARSET, "SimSun"}, - {FXFONT_CHINESEBIG5_CHARSET, "MingLiU"}, - {FXFONT_SHIFTJIS_CHARSET, "MS Gothic"}, - {FXFONT_HANGUL_CHARSET, "Batang"}, - {FXFONT_RUSSIAN_CHARSET, "Arial"}, -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - {FXFONT_EASTEUROPE_CHARSET, "Arial"}, -#else - {FXFONT_EASTEUROPE_CHARSET, "Tahoma"}, -#endif - {FXFONT_ARABIC_CHARSET, "Arial"}, - {-1, nullptr}}; - -CFX_ByteString CPWL_FontMap::GetDefaultFontByCharset(int32_t nCharset) { - int i = 0; - while (defaultTTFMap[i].charset != -1) { - if (nCharset == defaultTTFMap[i].charset) - return defaultTTFMap[i].fontname; - ++i; - } - return ""; -} - -int32_t CPWL_FontMap::CharSetFromUnicode(uint16_t word, int32_t nOldCharset) { - // to avoid CJK Font to show ASCII - if (word < 0x7F) - return FXFONT_ANSI_CHARSET; - // follow the old charset - if (nOldCharset != FXFONT_DEFAULT_CHARSET) - return nOldCharset; - - // find new charset - if ((word >= 0x4E00 && word <= 0x9FA5) || - (word >= 0xE7C7 && word <= 0xE7F3) || - (word >= 0x3000 && word <= 0x303F) || - (word >= 0x2000 && word <= 0x206F)) { - return FXFONT_GB2312_CHARSET; - } - - if (((word >= 0x3040) && (word <= 0x309F)) || - ((word >= 0x30A0) && (word <= 0x30FF)) || - ((word >= 0x31F0) && (word <= 0x31FF)) || - ((word >= 0xFF00) && (word <= 0xFFEF))) { - return FXFONT_SHIFTJIS_CHARSET; - } - - if (((word >= 0xAC00) && (word <= 0xD7AF)) || - ((word >= 0x1100) && (word <= 0x11FF)) || - ((word >= 0x3130) && (word <= 0x318F))) { - return FXFONT_HANGUL_CHARSET; - } - - if (word >= 0x0E00 && word <= 0x0E7F) - return FXFONT_THAI_CHARSET; - - if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF)) - return FXFONT_GREEK_CHARSET; - - if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC)) - return FXFONT_ARABIC_CHARSET; - - if (word >= 0x0590 && word <= 0x05FF) - return FXFONT_HEBREW_CHARSET; - - if (word >= 0x0400 && word <= 0x04FF) - return FXFONT_RUSSIAN_CHARSET; - - if (word >= 0x0100 && word <= 0x024F) - return FXFONT_EASTEUROPE_CHARSET; - - if (word >= 0x1E00 && word <= 0x1EFF) - return FXFONT_VIETNAMESE_CHARSET; - - return FXFONT_ANSI_CHARSET; -} diff --git a/fpdfsdk/pdfwindow/PWL_FontMap.h b/fpdfsdk/pdfwindow/PWL_FontMap.h deleted file mode 100644 index c14fcd7cd34a702e05a67cc506adb8d88e7b68ba..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_FontMap.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_FONTMAP_H_ -#define FPDFSDK_PDFWINDOW_PWL_FONTMAP_H_ - -#include -#include - -#include "core/fpdfdoc/ipvt_fontmap.h" -#include "core/fxge/fx_font.h" -#include "fpdfsdk/fxedit/fx_edit.h" -#include "public/fpdf_sysfontinfo.h" - -class CPDF_Document; -class CFX_SystemHandler; - -struct CPWL_FontMap_Data { - CPDF_Font* pFont; - int32_t nCharset; - CFX_ByteString sFontName; -}; - -struct CPWL_FontMap_Native { - int32_t nCharset; - CFX_ByteString sFontName; -}; - -class CPWL_FontMap : public IPVT_FontMap { - public: - explicit CPWL_FontMap(CFX_SystemHandler* pSystemHandler); - ~CPWL_FontMap() override; - - // IPVT_FontMap - CPDF_Font* GetPDFFont(int32_t nFontIndex) override; - CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override; - int32_t GetWordFontIndex(uint16_t word, - int32_t nCharset, - int32_t nFontIndex) override; - int32_t CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) override; - int32_t CharSetFromUnicode(uint16_t word, int32_t nOldCharset) override; - - const CPWL_FontMap_Data* GetFontMapData(int32_t nIndex) const; - static int32_t GetNativeCharset(); - CFX_ByteString GetNativeFontName(int32_t nCharset); - - static CFX_ByteString GetDefaultFontByCharset(int32_t nCharset); - static const FPDF_CharsetFontMap defaultTTFMap[]; - - protected: - virtual void Initialize(); - virtual CPDF_Document* GetDocument(); - virtual CPDF_Font* FindFontSameCharset(CFX_ByteString& sFontAlias, - int32_t nCharset); - virtual void AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias); - - bool KnowWord(int32_t nFontIndex, uint16_t word); - - void Empty(); - int32_t GetFontIndex(const CFX_ByteString& sFontName, - int32_t nCharset, - bool bFind); - int32_t AddFontData(CPDF_Font* pFont, - const CFX_ByteString& sFontAlias, - int32_t nCharset = FXFONT_DEFAULT_CHARSET); - - CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName, - int32_t nCharset); - CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName); - - std::vector> m_Data; - std::vector> m_NativeFont; - - private: - int32_t FindFont(const CFX_ByteString& sFontName, - int32_t nCharset = FXFONT_DEFAULT_CHARSET); - - CFX_ByteString GetNativeFont(int32_t nCharset); - CPDF_Font* AddFontToDocument(CPDF_Document* pDoc, - CFX_ByteString& sFontName, - uint8_t nCharset); - bool IsStandardFont(const CFX_ByteString& sFontName); - CPDF_Font* AddStandardFont(CPDF_Document* pDoc, CFX_ByteString& sFontName); - CPDF_Font* AddSystemFont(CPDF_Document* pDoc, - CFX_ByteString& sFontName, - uint8_t nCharset); - - std::unique_ptr m_pPDFDoc; - CFX_SystemHandler* const m_pSystemHandler; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_FONTMAP_H_ diff --git a/fpdfsdk/pdfwindow/PWL_Icon.cpp b/fpdfsdk/pdfwindow/PWL_Icon.cpp deleted file mode 100644 index b0d0c7686d9522d8f3bfae57d158a1f09fc469b5..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Icon.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_Icon.h" - -#include - -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -CPWL_Image::CPWL_Image() : m_pPDFStream(nullptr) {} - -CPWL_Image::~CPWL_Image() {} - -CFX_ByteString CPWL_Image::GetImageAppStream() { - CFX_ByteTextBuf sAppStream; - - CFX_ByteString sAlias = GetImageAlias(); - CFX_FloatRect rcPlate = GetClientRect(); - CFX_Matrix mt; - mt.SetReverse(GetImageMatrix()); - - FX_FLOAT fHScale = 1.0f; - FX_FLOAT fVScale = 1.0f; - GetScale(fHScale, fVScale); - - FX_FLOAT fx = 0.0f; - FX_FLOAT fy = 0.0f; - GetImageOffset(fx, fy); - - if (m_pPDFStream && sAlias.GetLength() > 0) { - sAppStream << "q\n"; - sAppStream << rcPlate.left << " " << rcPlate.bottom << " " - << rcPlate.right - rcPlate.left << " " - << rcPlate.top - rcPlate.bottom << " re W n\n"; - - sAppStream << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx - << " " << rcPlate.bottom + fy << " cm\n"; - sAppStream << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " " - << mt.e << " " << mt.f << " cm\n"; - - sAppStream << "0 g 0 G 1 w /" << sAlias.AsStringC() << " Do\n" - << "Q\n"; - } - - return sAppStream.MakeString(); -} - -void CPWL_Image::SetPDFStream(CPDF_Stream* pStream) { - m_pPDFStream = pStream; -} - -CPDF_Stream* CPWL_Image::GetPDFStream() { - return m_pPDFStream; -} - -void CPWL_Image::GetImageSize(FX_FLOAT& fWidth, FX_FLOAT& fHeight) { - fWidth = 0.0f; - fHeight = 0.0f; - - if (m_pPDFStream) { - if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) { - CFX_FloatRect rect = pDict->GetRectFor("BBox"); - - fWidth = rect.right - rect.left; - fHeight = rect.top - rect.bottom; - } - } -} - -CFX_Matrix CPWL_Image::GetImageMatrix() { - if (m_pPDFStream) { - if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) { - return pDict->GetMatrixFor("Matrix"); - } - } - - return CFX_Matrix(); -} - -CFX_ByteString CPWL_Image::GetImageAlias() { - if (!m_sImageAlias.IsEmpty()) - return m_sImageAlias; - - if (m_pPDFStream) { - if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) { - return pDict->GetStringFor("Name"); - } - } - - return CFX_ByteString(); -} - -void CPWL_Image::SetImageAlias(const FX_CHAR* sImageAlias) { - m_sImageAlias = sImageAlias; -} - -void CPWL_Image::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) { - fHScale = 1.0f; - fVScale = 1.0f; -} - -void CPWL_Image::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) { - x = 0.0f; - y = 0.0f; -} - -CPWL_Icon::CPWL_Icon() : m_pIconFit(nullptr) {} - -CPWL_Icon::~CPWL_Icon() {} - -CPDF_IconFit* CPWL_Icon::GetIconFit() { - return m_pIconFit; -} - -int32_t CPWL_Icon::GetScaleMethod() { - if (m_pIconFit) - return m_pIconFit->GetScaleMethod(); - - return 0; -} - -bool CPWL_Icon::IsProportionalScale() { - if (m_pIconFit) - return m_pIconFit->IsProportionalScale(); - - return false; -} - -void CPWL_Icon::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom) { - if (m_pIconFit) { - fLeft = 0.0f; - fBottom = 0.0f; - CPDF_Array* pA = m_pIconFit->GetDict() - ? m_pIconFit->GetDict()->GetArrayFor("A") - : nullptr; - if (pA) { - size_t dwCount = pA->GetCount(); - if (dwCount > 0) - fLeft = pA->GetNumberAt(0); - if (dwCount > 1) - fBottom = pA->GetNumberAt(1); - } - } else { - fLeft = 0.0f; - fBottom = 0.0f; - } -} - -void CPWL_Icon::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) { - fHScale = 1.0f; - fVScale = 1.0f; - - if (m_pPDFStream) { - FX_FLOAT fImageWidth, fImageHeight; - FX_FLOAT fPlateWidth, fPlateHeight; - - CFX_FloatRect rcPlate = GetClientRect(); - fPlateWidth = rcPlate.right - rcPlate.left; - fPlateHeight = rcPlate.top - rcPlate.bottom; - - GetImageSize(fImageWidth, fImageHeight); - - int32_t nScaleMethod = GetScaleMethod(); - - switch (nScaleMethod) { - default: - case 0: - fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); - fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); - break; - case 1: - if (fPlateWidth < fImageWidth) - fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); - if (fPlateHeight < fImageHeight) - fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); - break; - case 2: - if (fPlateWidth > fImageWidth) - fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); - if (fPlateHeight > fImageHeight) - fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); - break; - case 3: - break; - } - - FX_FLOAT fMinScale; - if (IsProportionalScale()) { - fMinScale = std::min(fHScale, fVScale); - fHScale = fMinScale; - fVScale = fMinScale; - } - } -} - -void CPWL_Icon::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) { - FX_FLOAT fLeft, fBottom; - - GetIconPosition(fLeft, fBottom); - x = 0.0f; - y = 0.0f; - - FX_FLOAT fImageWidth, fImageHeight; - GetImageSize(fImageWidth, fImageHeight); - - FX_FLOAT fHScale, fVScale; - GetScale(fHScale, fVScale); - - FX_FLOAT fImageFactWidth = fImageWidth * fHScale; - FX_FLOAT fImageFactHeight = fImageHeight * fVScale; - - FX_FLOAT fPlateWidth, fPlateHeight; - CFX_FloatRect rcPlate = GetClientRect(); - fPlateWidth = rcPlate.right - rcPlate.left; - fPlateHeight = rcPlate.top - rcPlate.bottom; - - x = (fPlateWidth - fImageFactWidth) * fLeft; - y = (fPlateHeight - fImageFactHeight) * fBottom; -} diff --git a/fpdfsdk/pdfwindow/PWL_Icon.h b/fpdfsdk/pdfwindow/PWL_Icon.h deleted file mode 100644 index 4b62db4c990f00c4085f938bcd2783f25b09cb3c..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Icon.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_ICON_H_ -#define FPDFSDK_PDFWINDOW_PWL_ICON_H_ - -#include "core/fxcrt/fx_string.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CPWL_Image : public CPWL_Wnd { - public: - CPWL_Image(); - ~CPWL_Image() override; - - virtual CFX_ByteString GetImageAppStream(); - - virtual void GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale); - virtual void GetImageOffset(FX_FLOAT& x, FX_FLOAT& y); - virtual CPDF_Stream* GetPDFStream(); - - public: - void SetPDFStream(CPDF_Stream* pStream); - void GetImageSize(FX_FLOAT& fWidth, FX_FLOAT& fHeight); - CFX_Matrix GetImageMatrix(); - CFX_ByteString GetImageAlias(); - void SetImageAlias(const FX_CHAR* sImageAlias); - - protected: - CPDF_Stream* m_pPDFStream; - CFX_ByteString m_sImageAlias; -}; - -class CPWL_Icon : public CPWL_Image { - public: - CPWL_Icon(); - ~CPWL_Icon() override; - - virtual CPDF_IconFit* GetIconFit(); - - // CPWL_Image - void GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) override; - void GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) override; - - int32_t GetScaleMethod(); - bool IsProportionalScale(); - void GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom); - - void SetIconFit(CPDF_IconFit* pIconFit) { m_pIconFit = pIconFit; } - - private: - CPDF_IconFit* m_pIconFit; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_ICON_H_ diff --git a/fpdfsdk/pdfwindow/PWL_ListBox.cpp b/fpdfsdk/pdfwindow/PWL_ListBox.cpp deleted file mode 100644 index ed96e203fdfea61521709f7f4fdea737bad68894..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_ListBox.cpp +++ /dev/null @@ -1,459 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_ListBox.h" - -#include "fpdfsdk/fxedit/fxet_edit.h" -#include "fpdfsdk/fxedit/fxet_list.h" -#include "fpdfsdk/pdfwindow/PWL_Edit.h" -#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" -#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" -#include "public/fpdf_fwlevent.h" -#include "third_party/base/ptr_util.h" - -CPWL_List_Notify::CPWL_List_Notify(CPWL_ListBox* pList) : m_pList(pList) { - ASSERT(m_pList); -} - -CPWL_List_Notify::~CPWL_List_Notify() {} - -void CPWL_List_Notify::IOnSetScrollInfoY(FX_FLOAT fPlateMin, - FX_FLOAT fPlateMax, - FX_FLOAT fContentMin, - FX_FLOAT fContentMax, - FX_FLOAT fSmallStep, - FX_FLOAT fBigStep) { - PWL_SCROLL_INFO Info; - - Info.fPlateWidth = fPlateMax - fPlateMin; - Info.fContentMin = fContentMin; - Info.fContentMax = fContentMax; - Info.fSmallStep = fSmallStep; - Info.fBigStep = fBigStep; - - m_pList->OnNotify(m_pList, PNM_SETSCROLLINFO, SBT_VSCROLL, (intptr_t)&Info); - - if (CPWL_ScrollBar* pScroll = m_pList->GetVScrollBar()) { - if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) || - IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) { - if (pScroll->IsVisible()) { - pScroll->SetVisible(false); - m_pList->RePosChildWnd(); - } - } else { - if (!pScroll->IsVisible()) { - pScroll->SetVisible(true); - m_pList->RePosChildWnd(); - } - } - } -} - -void CPWL_List_Notify::IOnSetScrollPosY(FX_FLOAT fy) { - m_pList->OnNotify(m_pList, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&fy); -} - -void CPWL_List_Notify::IOnInvalidateRect(CFX_FloatRect* pRect) { - m_pList->InvalidateRect(pRect); -} - -CPWL_ListBox::CPWL_ListBox() - : m_pList(new CFX_ListCtrl), - m_bMouseDown(false), - m_bHoverSel(false), - m_pFillerNotify(nullptr) {} - -CPWL_ListBox::~CPWL_ListBox() { -} - -CFX_ByteString CPWL_ListBox::GetClassName() const { - return "CPWL_ListBox"; -} - -void CPWL_ListBox::OnCreated() { - m_pList->SetFontMap(GetFontMap()); - m_pListNotify = pdfium::MakeUnique(this); - m_pList->SetNotify(m_pListNotify.get()); - - SetHoverSel(HasFlag(PLBS_HOVERSEL)); - m_pList->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL)); - m_pList->SetFontSize(GetCreationParam().fFontSize); - - m_bHoverSel = HasFlag(PLBS_HOVERSEL); -} - -void CPWL_ListBox::OnDestroy() { - // Make sure the notifier is removed from the list as we are about to - // destroy the notifier and don't want to leave a dangling pointer. - m_pList->SetNotify(nullptr); - m_pListNotify.reset(); -} - -void CPWL_ListBox::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - CPWL_Wnd::GetThisAppearanceStream(sAppStream); - - CFX_ByteTextBuf sListItems; - - CFX_FloatRect rcPlate = m_pList->GetPlateRect(); - for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) { - CFX_FloatRect rcItem = m_pList->GetItemRect(i); - - if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom) - continue; - - CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f); - if (m_pList->IsItemSelected(i)) { - sListItems << CPWL_Utils::GetRectFillAppStream(rcItem, - PWL_DEFAULT_SELBACKCOLOR) - .AsStringC(); - CFX_ByteString sItem = - CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset); - if (sItem.GetLength() > 0) { - sListItems << "BT\n" - << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELTEXTCOLOR) - .AsStringC() - << sItem.AsStringC() << "ET\n"; - } - } else { - CFX_ByteString sItem = - CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset); - if (sItem.GetLength() > 0) { - sListItems << "BT\n" - << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC() - << sItem.AsStringC() << "ET\n"; - } - } - } - - if (sListItems.GetLength() > 0) { - CFX_ByteTextBuf sClip; - CFX_FloatRect rcClient = GetClientRect(); - - sClip << "q\n"; - sClip << rcClient.left << " " << rcClient.bottom << " " - << rcClient.right - rcClient.left << " " - << rcClient.top - rcClient.bottom << " re W n\n"; - - sClip << sListItems << "Q\n"; - - sAppStream << "/Tx BMC\n" << sClip << "EMC\n"; - } -} - -void CPWL_ListBox::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - - CFX_FloatRect rcPlate = m_pList->GetPlateRect(); - CFX_FloatRect rcList = GetListRect(); - CFX_FloatRect rcClient = GetClientRect(); - - for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) { - CFX_FloatRect rcItem = m_pList->GetItemRect(i); - if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom) - continue; - - CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f); - if (CFX_Edit* pEdit = m_pList->GetItemEdit(i)) { - CFX_FloatRect rcContent = pEdit->GetContentRect(); - if (rcContent.Width() > rcClient.Width()) - rcItem.Intersect(rcList); - else - rcItem.Intersect(rcClient); - } - - if (m_pList->IsItemSelected(i)) { - CFX_SystemHandler* pSysHandler = GetSystemHandler(); - if (pSysHandler && pSysHandler->IsSelectionImplemented()) { - CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i), - GetTextColor().ToFXColor(255), rcList, ptOffset, - nullptr, pSysHandler, m_pFormFiller); - pSysHandler->OutputSelectedRect(m_pFormFiller, rcItem); - } else { - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcItem, - ArgbEncode(255, 0, 51, 113)); - CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i), - ArgbEncode(255, 255, 255, 255), rcList, ptOffset, - nullptr, pSysHandler, m_pFormFiller); - } - } else { - CFX_SystemHandler* pSysHandler = GetSystemHandler(); - CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i), - GetTextColor().ToFXColor(255), rcList, ptOffset, - nullptr, pSysHandler, nullptr); - } - } -} - -bool CPWL_ListBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) { - CPWL_Wnd::OnKeyDown(nChar, nFlag); - - switch (nChar) { - default: - return false; - case FWL_VKEY_Up: - case FWL_VKEY_Down: - case FWL_VKEY_Home: - case FWL_VKEY_Left: - case FWL_VKEY_End: - case FWL_VKEY_Right: - break; - } - - switch (nChar) { - case FWL_VKEY_Up: - m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Down: - m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Home: - m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Left: - m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_End: - m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Right: - m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - break; - case FWL_VKEY_Delete: - break; - } - - bool bExit = false; - OnNotifySelChanged(true, bExit, nFlag); - - return true; -} - -bool CPWL_ListBox::OnChar(uint16_t nChar, uint32_t nFlag) { - CPWL_Wnd::OnChar(nChar, nFlag); - - if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag))) - return false; - - bool bExit = false; - OnNotifySelChanged(true, bExit, nFlag); - - return true; -} - -bool CPWL_ListBox::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - if (ClientHitTest(point)) { - m_bMouseDown = true; - SetFocus(); - SetCapture(); - - m_pList->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - } - - return true; -} - -bool CPWL_ListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - if (m_bMouseDown) { - ReleaseCapture(); - m_bMouseDown = false; - } - - bool bExit = false; - OnNotifySelChanged(false, bExit, nFlag); - - return true; -} - -void CPWL_ListBox::SetHoverSel(bool bHoverSel) { - m_bHoverSel = bHoverSel; -} - -bool CPWL_ListBox::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnMouseMove(point, nFlag); - - if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point)) - m_pList->Select(m_pList->GetItemIndex(point)); - if (m_bMouseDown) - m_pList->OnMouseMove(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - - return true; -} - -void CPWL_ListBox::OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam, - intptr_t lParam) { - CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); - - FX_FLOAT fPos; - - switch (msg) { - case PNM_SETSCROLLINFO: - switch (wParam) { - case SBT_VSCROLL: - if (CPWL_Wnd* pChild = GetVScrollBar()) { - pChild->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam); - } - break; - } - break; - case PNM_SETSCROLLPOS: - switch (wParam) { - case SBT_VSCROLL: - if (CPWL_Wnd* pChild = GetVScrollBar()) { - pChild->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam); - } - break; - } - break; - case PNM_SCROLLWINDOW: - fPos = *(FX_FLOAT*)lParam; - switch (wParam) { - case SBT_VSCROLL: - m_pList->SetScrollPos(CFX_PointF(0, fPos)); - break; - } - break; - } -} - -void CPWL_ListBox::KillFocus() { - CPWL_Wnd::KillFocus(); -} - -void CPWL_ListBox::RePosChildWnd() { - CPWL_Wnd::RePosChildWnd(); - - m_pList->SetPlateRect(GetListRect()); -} - -void CPWL_ListBox::OnNotifySelChanged(bool bKeyDown, - bool& bExit, - uint32_t nFlag) { - if (!m_pFillerNotify) - return; - - bool bRC = true; - CFX_WideString swChange = GetText(); - CFX_WideString strChangeEx; - int nSelStart = 0; - int nSelEnd = swChange.GetLength(); - m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), swChange, strChangeEx, - nSelStart, nSelEnd, bKeyDown, bRC, bExit, - nFlag); -} - -CFX_FloatRect CPWL_ListBox::GetFocusRect() const { - if (m_pList->IsMultipleSel()) { - CFX_FloatRect rcCaret = m_pList->GetItemRect(m_pList->GetCaret()); - rcCaret.Intersect(GetClientRect()); - return rcCaret; - } - - return CPWL_Wnd::GetFocusRect(); -} - -void CPWL_ListBox::AddString(const CFX_WideString& str) { - m_pList->AddString(str); -} - -CFX_WideString CPWL_ListBox::GetText() const { - return m_pList->GetText(); -} - -void CPWL_ListBox::SetFontSize(FX_FLOAT fFontSize) { - m_pList->SetFontSize(fFontSize); -} - -FX_FLOAT CPWL_ListBox::GetFontSize() const { - return m_pList->GetFontSize(); -} - -void CPWL_ListBox::Select(int32_t nItemIndex) { - m_pList->Select(nItemIndex); -} - -void CPWL_ListBox::SetCaret(int32_t nItemIndex) { - m_pList->SetCaret(nItemIndex); -} - -void CPWL_ListBox::SetTopVisibleIndex(int32_t nItemIndex) { - m_pList->SetTopItem(nItemIndex); -} - -void CPWL_ListBox::ScrollToListItem(int32_t nItemIndex) { - m_pList->ScrollToListItem(nItemIndex); -} - -void CPWL_ListBox::ResetContent() { - m_pList->Empty(); -} - -void CPWL_ListBox::Reset() { - m_pList->Cancel(); -} - -bool CPWL_ListBox::IsMultipleSel() const { - return m_pList->IsMultipleSel(); -} - -int32_t CPWL_ListBox::GetCaretIndex() const { - return m_pList->GetCaret(); -} - -int32_t CPWL_ListBox::GetCurSel() const { - return m_pList->GetSelect(); -} - -bool CPWL_ListBox::IsItemSelected(int32_t nItemIndex) const { - return m_pList->IsItemSelected(nItemIndex); -} - -int32_t CPWL_ListBox::GetTopVisibleIndex() const { - m_pList->ScrollToListItem(m_pList->GetFirstSelected()); - return m_pList->GetTopItem(); -} - -int32_t CPWL_ListBox::GetCount() const { - return m_pList->GetCount(); -} - -int32_t CPWL_ListBox::FindNext(int32_t nIndex, FX_WCHAR nChar) const { - return m_pList->FindNext(nIndex, nChar); -} - -CFX_FloatRect CPWL_ListBox::GetContentRect() const { - return m_pList->GetContentRect(); -} - -FX_FLOAT CPWL_ListBox::GetFirstHeight() const { - return m_pList->GetFirstHeight(); -} - -CFX_FloatRect CPWL_ListBox::GetListRect() const { - return CPWL_Utils::DeflateRect( - GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth())); -} - -bool CPWL_ListBox::OnMouseWheel(short zDelta, - const CFX_PointF& point, - uint32_t nFlag) { - if (zDelta < 0) - m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - else - m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); - - bool bExit = false; - OnNotifySelChanged(false, bExit, nFlag); - return true; -} diff --git a/fpdfsdk/pdfwindow/PWL_ListBox.h b/fpdfsdk/pdfwindow/PWL_ListBox.h deleted file mode 100644 index f9108a17de0b5c21ee4d0b0b87a4ddac41d7890c..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_ListBox.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_LISTBOX_H_ -#define FPDFSDK_PDFWINDOW_PWL_LISTBOX_H_ - -#include - -#include "fpdfsdk/fxedit/fx_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CFX_ListCtrl; -class CPWL_List_Notify; -class CPWL_ListBox; -class IPWL_Filler_Notify; -struct CPVT_SecProps; -struct CPVT_WordPlace; -struct CPVT_WordProps; - -class CPWL_List_Notify { - public: - explicit CPWL_List_Notify(CPWL_ListBox* pList); - ~CPWL_List_Notify(); - - void IOnSetScrollInfoY(FX_FLOAT fPlateMin, - FX_FLOAT fPlateMax, - FX_FLOAT fContentMin, - FX_FLOAT fContentMax, - FX_FLOAT fSmallStep, - FX_FLOAT fBigStep); - void IOnSetScrollPosY(FX_FLOAT fy); - void IOnInvalidateRect(CFX_FloatRect* pRect); - - void IOnSetCaret(bool bVisible, - const CFX_PointF& ptHead, - const CFX_PointF& ptFoot, - const CPVT_WordPlace& place); - - private: - CPWL_ListBox* m_pList; -}; - -class CPWL_ListBox : public CPWL_Wnd { - public: - CPWL_ListBox(); - ~CPWL_ListBox() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void OnCreated() override; - void OnDestroy() override; - void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override; - void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; - bool OnMouseWheel(short zDelta, - const CFX_PointF& point, - uint32_t nFlag) override; - void KillFocus() override; - void OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam = 0, - intptr_t lParam = 0) override; - void RePosChildWnd() override; - CFX_FloatRect GetFocusRect() const override; - void SetFontSize(FX_FLOAT fFontSize) override; - FX_FLOAT GetFontSize() const override; - - virtual CFX_WideString GetText() const; - - void OnNotifySelChanged(bool bKeyDown, bool& bExit, uint32_t nFlag); - - void AddString(const CFX_WideString& str); - void SetTopVisibleIndex(int32_t nItemIndex); - void ScrollToListItem(int32_t nItemIndex); - void ResetContent(); - void Reset(); - void Select(int32_t nItemIndex); - void SetCaret(int32_t nItemIndex); - void SetHoverSel(bool bHoverSel); - - int32_t GetCount() const; - bool IsMultipleSel() const; - int32_t GetCaretIndex() const; - int32_t GetCurSel() const; - bool IsItemSelected(int32_t nItemIndex) const; - int32_t GetTopVisibleIndex() const; - int32_t FindNext(int32_t nIndex, FX_WCHAR nChar) const; - CFX_FloatRect GetContentRect() const; - FX_FLOAT GetFirstHeight() const; - CFX_FloatRect GetListRect() const; - - void SetFillerNotify(IPWL_Filler_Notify* pNotify) { - m_pFillerNotify = pNotify; - } - - void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; } - - protected: - std::unique_ptr m_pList; - std::unique_ptr m_pListNotify; - bool m_bMouseDown; - bool m_bHoverSel; - IPWL_Filler_Notify* m_pFillerNotify; - - private: - CFFL_FormFiller* m_pFormFiller; // Not owned. -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_LISTBOX_H_ diff --git a/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp b/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp deleted file mode 100644 index e3799366a5768ae2e99715bbedd50eece047c200..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp +++ /dev/null @@ -1,1175 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h" - -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -PWL_FLOATRANGE::PWL_FLOATRANGE() { - Default(); -} - -PWL_FLOATRANGE::PWL_FLOATRANGE(FX_FLOAT min, FX_FLOAT max) { - Set(min, max); -} - -void PWL_FLOATRANGE::Default() { - fMin = 0; - fMax = 0; -} - -void PWL_FLOATRANGE::Set(FX_FLOAT min, FX_FLOAT max) { - if (min > max) { - fMin = max; - fMax = min; - } else { - fMin = min; - fMax = max; - } -} - -bool PWL_FLOATRANGE::In(FX_FLOAT x) const { - return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) && - (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax)); -} - -FX_FLOAT PWL_FLOATRANGE::GetWidth() const { - return fMax - fMin; -} - -PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() { - Default(); -} - -void PWL_SCROLL_PRIVATEDATA::Default() { - ScrollRange.Default(); - fScrollPos = ScrollRange.fMin; - fClientWidth = 0; - fBigStep = 10; - fSmallStep = 1; -} - -void PWL_SCROLL_PRIVATEDATA::SetScrollRange(FX_FLOAT min, FX_FLOAT max) { - ScrollRange.Set(min, max); - - if (IsFloatSmaller(fScrollPos, ScrollRange.fMin)) - fScrollPos = ScrollRange.fMin; - if (IsFloatBigger(fScrollPos, ScrollRange.fMax)) - fScrollPos = ScrollRange.fMax; -} - -void PWL_SCROLL_PRIVATEDATA::SetClientWidth(FX_FLOAT width) { - fClientWidth = width; -} - -void PWL_SCROLL_PRIVATEDATA::SetSmallStep(FX_FLOAT step) { - fSmallStep = step; -} - -void PWL_SCROLL_PRIVATEDATA::SetBigStep(FX_FLOAT step) { - fBigStep = step; -} - -bool PWL_SCROLL_PRIVATEDATA::SetPos(FX_FLOAT pos) { - if (ScrollRange.In(pos)) { - fScrollPos = pos; - return true; - } - return false; -} - -void PWL_SCROLL_PRIVATEDATA::AddSmall() { - if (!SetPos(fScrollPos + fSmallStep)) - SetPos(ScrollRange.fMax); -} - -void PWL_SCROLL_PRIVATEDATA::SubSmall() { - if (!SetPos(fScrollPos - fSmallStep)) - SetPos(ScrollRange.fMin); -} - -void PWL_SCROLL_PRIVATEDATA::AddBig() { - if (!SetPos(fScrollPos + fBigStep)) - SetPos(ScrollRange.fMax); -} - -void PWL_SCROLL_PRIVATEDATA::SubBig() { - if (!SetPos(fScrollPos - fBigStep)) - SetPos(ScrollRange.fMin); -} - -CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, - PWL_SBBUTTON_TYPE eButtonType) { - m_eScrollBarType = eScrollBarType; - m_eSBButtonType = eButtonType; - - m_bMouseDown = false; -} - -CPWL_SBButton::~CPWL_SBButton() {} - -CFX_ByteString CPWL_SBButton::GetClassName() const { - return "CPWL_SBButton"; -} - -void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) { - cp.eCursorType = FXCT_ARROW; -} - -void CPWL_SBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - CPWL_Wnd::GetThisAppearanceStream(sAppStream); - - if (!IsVisible()) - return; - - CFX_ByteTextBuf sButton; - - CFX_FloatRect rectWnd = GetWindowRect(); - - if (rectWnd.IsEmpty()) - return; - - sAppStream << "q\n"; - - CFX_PointF ptCenter = GetCenterPoint(); - - switch (m_eScrollBarType) { - case SBT_HSCROLL: - switch (m_eSBButtonType) { - case PSBT_MIN: { - CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y); - CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y + PWL_TRIANGLE_HALFLEN); - CFX_PointF pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y - PWL_TRIANGLE_HALFLEN); - - if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && - rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { - sButton << "0 g\n"; - sButton << pt1.x << " " << pt1.y << " m\n"; - sButton << pt2.x << " " << pt2.y << " l\n"; - sButton << pt3.x << " " << pt3.y << " l\n"; - sButton << pt1.x << " " << pt1.y << " l f\n"; - - sAppStream << sButton; - } - } break; - case PSBT_MAX: { - CFX_PointF pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y); - CFX_PointF pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y + PWL_TRIANGLE_HALFLEN); - CFX_PointF pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y - PWL_TRIANGLE_HALFLEN); - - if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && - rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { - sButton << "0 g\n"; - sButton << pt1.x << " " << pt1.y << " m\n"; - sButton << pt2.x << " " << pt2.y << " l\n"; - sButton << pt3.x << " " << pt3.y << " l\n"; - sButton << pt1.x << " " << pt1.y << " l f\n"; - - sAppStream << sButton; - } - } break; - default: - break; - } - break; - case SBT_VSCROLL: - switch (m_eSBButtonType) { - case PSBT_MIN: { - CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN, - ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN, - ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt3(ptCenter.x, ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f); - - if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && - rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { - sButton << "0 g\n"; - sButton << pt1.x << " " << pt1.y << " m\n"; - sButton << pt2.x << " " << pt2.y << " l\n"; - sButton << pt3.x << " " << pt3.y << " l\n"; - sButton << pt1.x << " " << pt1.y << " l f\n"; - - sAppStream << sButton; - } - } break; - case PSBT_MAX: { - CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN, - ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN, - ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f); - CFX_PointF pt3(ptCenter.x, ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f); - - if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && - rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { - sButton << "0 g\n"; - sButton << pt1.x << " " << pt1.y << " m\n"; - sButton << pt2.x << " " << pt2.y << " l\n"; - sButton << pt3.x << " " << pt3.y << " l\n"; - sButton << pt1.x << " " << pt1.y << " l f\n"; - - sAppStream << sButton; - } - } break; - default: - break; - } - break; - default: - break; - } - - sAppStream << "Q\n"; -} - -void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - if (!IsVisible()) - return; - - CFX_FloatRect rectWnd = GetWindowRect(); - if (rectWnd.IsEmpty()) - return; - - CFX_PointF ptCenter = GetCenterPoint(); - int32_t nTransparency = GetTransparency(); - - switch (m_eScrollBarType) { - case SBT_HSCROLL: - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - switch (m_eSBButtonType) { - case PSBT_MIN: { - CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y); - CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y + PWL_TRIANGLE_HALFLEN); - CFX_PointF pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y - PWL_TRIANGLE_HALFLEN); - - if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && - rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { - CFX_PathData path; - path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false); - path.AppendPoint(pt2, FXPT_TYPE::LineTo, false); - path.AppendPoint(pt3, FXPT_TYPE::LineTo, false); - path.AppendPoint(pt1, FXPT_TYPE::LineTo, false); - - pDevice->DrawPath(&path, pUser2Device, nullptr, - PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency), - 0, FXFILL_ALTERNATE); - } - } break; - case PSBT_MAX: { - CFX_PointF pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y); - CFX_PointF pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y + PWL_TRIANGLE_HALFLEN); - CFX_PointF pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, - ptCenter.y - PWL_TRIANGLE_HALFLEN); - - if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 && - rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) { - CFX_PathData path; - path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false); - path.AppendPoint(pt2, FXPT_TYPE::LineTo, false); - path.AppendPoint(pt3, FXPT_TYPE::LineTo, false); - path.AppendPoint(pt1, FXPT_TYPE::LineTo, false); - - pDevice->DrawPath(&path, pUser2Device, nullptr, - PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency), - 0, FXFILL_ALTERNATE); - } - } break; - default: - break; - } - break; - case SBT_VSCROLL: - switch (m_eSBButtonType) { - case PSBT_MIN: { - // draw border - CFX_FloatRect rcDraw = rectWnd; - CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(nTransparency, 100, 100, 100), - 0.0f); - - // draw inner border - rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f); - CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(nTransparency, 255, 255, 255), - 1.0f); - - // draw background - - rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f); - - if (IsEnabled()) - CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw, - nTransparency, 80, 220); - else - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(255, 255, 255, 255)); - - // draw arrow - - if (rectWnd.top - rectWnd.bottom > 6.0f) { - FX_FLOAT fX = rectWnd.left + 1.5f; - FX_FLOAT fY = rectWnd.bottom; - CFX_PointF pts[7] = {CFX_PointF(fX + 2.5f, fY + 4.0f), - CFX_PointF(fX + 2.5f, fY + 3.0f), - CFX_PointF(fX + 4.5f, fY + 5.0f), - CFX_PointF(fX + 6.5f, fY + 3.0f), - CFX_PointF(fX + 6.5f, fY + 4.0f), - CFX_PointF(fX + 4.5f, fY + 6.0f), - CFX_PointF(fX + 2.5f, fY + 4.0f)}; - - if (IsEnabled()) - CPWL_Utils::DrawFillArea( - pDevice, pUser2Device, pts, 7, - ArgbEncode(nTransparency, 255, 255, 255)); - else - CPWL_Utils::DrawFillArea( - pDevice, pUser2Device, pts, 7, - PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255)); - } - } break; - case PSBT_MAX: { - // draw border - CFX_FloatRect rcDraw = rectWnd; - CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(nTransparency, 100, 100, 100), - 0.0f); - - // draw inner border - rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f); - CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(nTransparency, 255, 255, 255), - 1.0f); - - // draw background - rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f); - if (IsEnabled()) - CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw, - nTransparency, 80, 220); - else - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(255, 255, 255, 255)); - - // draw arrow - - if (rectWnd.top - rectWnd.bottom > 6.0f) { - FX_FLOAT fX = rectWnd.left + 1.5f; - FX_FLOAT fY = rectWnd.bottom; - - CFX_PointF pts[7] = {CFX_PointF(fX + 2.5f, fY + 5.0f), - CFX_PointF(fX + 2.5f, fY + 6.0f), - CFX_PointF(fX + 4.5f, fY + 4.0f), - CFX_PointF(fX + 6.5f, fY + 6.0f), - CFX_PointF(fX + 6.5f, fY + 5.0f), - CFX_PointF(fX + 4.5f, fY + 3.0f), - CFX_PointF(fX + 2.5f, fY + 5.0f)}; - - if (IsEnabled()) - CPWL_Utils::DrawFillArea( - pDevice, pUser2Device, pts, 7, - ArgbEncode(nTransparency, 255, 255, 255)); - else - CPWL_Utils::DrawFillArea( - pDevice, pUser2Device, pts, 7, - PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255)); - } - } break; - case PSBT_POS: { - // draw border - CFX_FloatRect rcDraw = rectWnd; - CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(nTransparency, 100, 100, 100), - 0.0f); - - // draw inner border - rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f); - CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(nTransparency, 255, 255, 255), - 1.0f); - - if (IsEnabled()) { - // draw shadow effect - - CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f); - CFX_PointF ptBottom = - CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f); - - ptTop.x += 1.5f; - ptBottom.x += 1.5f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 210, 210, 210), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 220, 220, 220), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 240, 240, 240), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 240, 240, 240), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 210, 210, 210), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 180, 180, 180), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 150, 150, 150), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 150, 150, 150), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 180, 180, 180), - 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, - ArgbEncode(nTransparency, 210, 210, 210), - 1.0f); - } else { - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw, - ArgbEncode(255, 255, 255, 255)); - } - - // draw friction - - if (rectWnd.Height() > 8.0f) { - FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120); - if (!IsEnabled()) - crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255); - - FX_FLOAT nFrictionWidth = 5.0f; - FX_FLOAT nFrictionHeight = 5.5f; - - CFX_PointF ptLeft = - CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f, - ptCenter.y - nFrictionHeight / 2.0f + 0.5f); - CFX_PointF ptRight = - CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f, - ptCenter.y - nFrictionHeight / 2.0f + 0.5f); - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, - crStroke, 1.0f); - - ptLeft.y += 2.0f; - ptRight.y += 2.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, - crStroke, 1.0f); - - ptLeft.y += 2.0f; - ptRight.y += 2.0f; - - CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, - crStroke, 1.0f); - } - } break; - default: - break; - } - break; - default: - break; - } -} - -bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - if (CPWL_Wnd* pParent = GetParentWindow()) - pParent->OnNotify(this, PNM_LBUTTONDOWN, 0, (intptr_t)&point); - - m_bMouseDown = true; - SetCapture(); - - return true; -} - -bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - if (CPWL_Wnd* pParent = GetParentWindow()) - pParent->OnNotify(this, PNM_LBUTTONUP, 0, (intptr_t)&point); - - m_bMouseDown = false; - ReleaseCapture(); - - return true; -} - -bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnMouseMove(point, nFlag); - - if (CPWL_Wnd* pParent = GetParentWindow()) { - pParent->OnNotify(this, PNM_MOUSEMOVE, 0, (intptr_t)&point); - } - - return true; -} - -CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType) - : m_sbType(sbType), - m_pMinButton(nullptr), - m_pMaxButton(nullptr), - m_pPosButton(nullptr), - m_bMouseDown(false), - m_bMinOrMax(false), - m_bNotifyForever(true) {} - -CPWL_ScrollBar::~CPWL_ScrollBar() {} - -CFX_ByteString CPWL_ScrollBar::GetClassName() const { - return "CPWL_ScrollBar"; -} - -void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) { - cp.eCursorType = FXCT_ARROW; -} - -void CPWL_ScrollBar::RePosChildWnd() { - CFX_FloatRect rcClient = GetClientRect(); - CFX_FloatRect rcMinButton, rcMaxButton; - FX_FLOAT fBWidth = 0; - - switch (m_sbType) { - case SBT_HSCROLL: - if (rcClient.right - rcClient.left > - PWL_SCROLLBAR_BUTTON_WIDTH * 2 + PWL_SCROLLBAR_POSBUTTON_MINWIDTH + - 2) { - rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom, - rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH, - rcClient.top); - rcMaxButton = - CFX_FloatRect(rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH, - rcClient.bottom, rcClient.right, rcClient.top); - } else { - fBWidth = (rcClient.right - rcClient.left - - PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) / - 2; - - if (fBWidth > 0) { - rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom, - rcClient.left + fBWidth, rcClient.top); - rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom, - rcClient.right, rcClient.top); - } else { - SetVisible(false); - } - } - break; - case SBT_VSCROLL: - if (IsFloatBigger(rcClient.top - rcClient.bottom, - PWL_SCROLLBAR_BUTTON_WIDTH * 2 + - PWL_SCROLLBAR_POSBUTTON_MINWIDTH + 2)) { - rcMinButton = CFX_FloatRect(rcClient.left, - rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH, - rcClient.right, rcClient.top); - rcMaxButton = - CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right, - rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH); - } else { - fBWidth = (rcClient.top - rcClient.bottom - - PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) / - 2; - - if (IsFloatBigger(fBWidth, 0)) { - rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth, - rcClient.right, rcClient.top); - rcMaxButton = - CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right, - rcClient.bottom + fBWidth); - } else { - SetVisible(false); - } - } - break; - } - - if (m_pMinButton) - m_pMinButton->Move(rcMinButton, true, false); - if (m_pMaxButton) - m_pMaxButton->Move(rcMaxButton, true, false); - MovePosButton(false); -} - -void CPWL_ScrollBar::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - CFX_FloatRect rectWnd = GetWindowRect(); - - if (IsVisible() && !rectWnd.IsEmpty()) { - CFX_ByteTextBuf sButton; - - sButton << "q\n"; - sButton << "0 w\n" - << CPWL_Utils::GetColorAppStream(GetBackgroundColor(), true) - .AsStringC(); - sButton << rectWnd.left << " " << rectWnd.bottom << " " - << rectWnd.right - rectWnd.left << " " - << rectWnd.top - rectWnd.bottom << " re b Q\n"; - - sAppStream << sButton; - } -} - -void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CFX_FloatRect rectWnd = GetWindowRect(); - - if (IsVisible() && !rectWnd.IsEmpty()) { - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rectWnd, - GetBackgroundColor(), GetTransparency()); - - CPWL_Utils::DrawStrokeLine( - pDevice, pUser2Device, - CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f), - CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f), - ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f); - - CPWL_Utils::DrawStrokeLine( - pDevice, pUser2Device, - CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f), - CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f), - ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f); - } -} - -bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonDown(point, nFlag); - - if (HasFlag(PWS_AUTOTRANSPARENT)) { - if (GetTransparency() != 255) { - SetTransparency(255); - InvalidateRect(); - } - } - - CFX_FloatRect rcMinArea, rcMaxArea; - - if (m_pPosButton && m_pPosButton->IsVisible()) { - CFX_FloatRect rcClient = GetClientRect(); - CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect(); - - switch (m_sbType) { - case SBT_HSCROLL: - rcMinArea = - CFX_FloatRect(rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH, - rcClient.bottom, rcPosButton.left, rcClient.top); - rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom, - rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH, - rcClient.top); - - break; - case SBT_VSCROLL: - rcMinArea = - CFX_FloatRect(rcClient.left, rcPosButton.top, rcClient.right, - rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH); - rcMaxArea = CFX_FloatRect(rcClient.left, - rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH, - rcClient.right, rcPosButton.bottom); - break; - } - - rcMinArea.Normalize(); - rcMaxArea.Normalize(); - - if (rcMinArea.Contains(point)) { - m_sData.SubBig(); - MovePosButton(true); - NotifyScrollWindow(); - } - - if (rcMaxArea.Contains(point)) { - m_sData.AddBig(); - MovePosButton(true); - NotifyScrollWindow(); - } - } - - return true; -} - -bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - CPWL_Wnd::OnLButtonUp(point, nFlag); - - if (HasFlag(PWS_AUTOTRANSPARENT)) { - if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) { - SetTransparency(PWL_SCROLLBAR_TRANSPARENCY); - InvalidateRect(); - } - } - - EndTimer(); - m_bMouseDown = false; - - return true; -} - -void CPWL_ScrollBar::OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam, - intptr_t lParam) { - CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); - - switch (msg) { - case PNM_LBUTTONDOWN: - if (pWnd == m_pMinButton) { - OnMinButtonLBDown(*(CFX_PointF*)lParam); - } - - if (pWnd == m_pMaxButton) { - OnMaxButtonLBDown(*(CFX_PointF*)lParam); - } - - if (pWnd == m_pPosButton) { - OnPosButtonLBDown(*(CFX_PointF*)lParam); - } - break; - case PNM_LBUTTONUP: - if (pWnd == m_pMinButton) { - OnMinButtonLBUp(*(CFX_PointF*)lParam); - } - - if (pWnd == m_pMaxButton) { - OnMaxButtonLBUp(*(CFX_PointF*)lParam); - } - - if (pWnd == m_pPosButton) { - OnPosButtonLBUp(*(CFX_PointF*)lParam); - } - break; - case PNM_MOUSEMOVE: - if (pWnd == m_pMinButton) { - OnMinButtonMouseMove(*(CFX_PointF*)lParam); - } - - if (pWnd == m_pMaxButton) { - OnMaxButtonMouseMove(*(CFX_PointF*)lParam); - } - - if (pWnd == m_pPosButton) { - OnPosButtonMouseMove(*(CFX_PointF*)lParam); - } - break; - case PNM_SETSCROLLINFO: { - PWL_SCROLL_INFO* pInfo = reinterpret_cast(lParam); - if (pInfo && *pInfo != m_OriginInfo) { - m_OriginInfo = *pInfo; - FX_FLOAT fMax = - pInfo->fContentMax - pInfo->fContentMin - pInfo->fPlateWidth; - fMax = fMax > 0.0f ? fMax : 0.0f; - SetScrollRange(0, fMax, pInfo->fPlateWidth); - SetScrollStep(pInfo->fBigStep, pInfo->fSmallStep); - } - } break; - case PNM_SETSCROLLPOS: { - FX_FLOAT fPos = *(FX_FLOAT*)lParam; - switch (m_sbType) { - case SBT_HSCROLL: - fPos = fPos - m_OriginInfo.fContentMin; - break; - case SBT_VSCROLL: - fPos = m_OriginInfo.fContentMax - fPos; - break; - } - SetScrollPos(fPos); - } break; - } -} - -void CPWL_ScrollBar::CreateButtons(const PWL_CREATEPARAM& cp) { - PWL_CREATEPARAM scp = cp; - scp.pParentWnd = this; - scp.dwBorderWidth = 2; - scp.nBorderStyle = BorderStyle::BEVELED; - - scp.dwFlags = - PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP; - - if (!m_pMinButton) { - m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN); - m_pMinButton->Create(scp); - } - - if (!m_pMaxButton) { - m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX); - m_pMaxButton->Create(scp); - } - - if (!m_pPosButton) { - m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS); - m_pPosButton->SetVisible(false); - m_pPosButton->Create(scp); - } -} - -FX_FLOAT CPWL_ScrollBar::GetScrollBarWidth() const { - if (!IsVisible()) - return 0; - - return PWL_SCROLLBAR_WIDTH; -} - -void CPWL_ScrollBar::SetScrollRange(FX_FLOAT fMin, - FX_FLOAT fMax, - FX_FLOAT fClientWidth) { - if (m_pPosButton) { - m_sData.SetScrollRange(fMin, fMax); - m_sData.SetClientWidth(fClientWidth); - - if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) { - m_pPosButton->SetVisible(false); - } else { - m_pPosButton->SetVisible(true); - MovePosButton(true); - } - } -} - -void CPWL_ScrollBar::SetScrollPos(FX_FLOAT fPos) { - FX_FLOAT fOldPos = m_sData.fScrollPos; - - m_sData.SetPos(fPos); - - if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) - MovePosButton(true); -} - -void CPWL_ScrollBar::SetScrollStep(FX_FLOAT fBigStep, FX_FLOAT fSmallStep) { - m_sData.SetBigStep(fBigStep); - m_sData.SetSmallStep(fSmallStep); -} - -void CPWL_ScrollBar::MovePosButton(bool bRefresh) { - ASSERT(m_pMinButton); - ASSERT(m_pMaxButton); - - if (m_pPosButton->IsVisible()) { - CFX_FloatRect rcClient; - CFX_FloatRect rcPosArea, rcPosButton; - - rcClient = GetClientRect(); - rcPosArea = GetScrollArea(); - - FX_FLOAT fLeft, fRight, fTop, fBottom; - - switch (m_sbType) { - case SBT_HSCROLL: - fLeft = TrueToFace(m_sData.fScrollPos); - fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth); - - if (fRight - fLeft < PWL_SCROLLBAR_POSBUTTON_MINWIDTH) - fRight = fLeft + PWL_SCROLLBAR_POSBUTTON_MINWIDTH; - - if (fRight > rcPosArea.right) { - fRight = rcPosArea.right; - fLeft = fRight - PWL_SCROLLBAR_POSBUTTON_MINWIDTH; - } - - rcPosButton = - CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top); - - break; - case SBT_VSCROLL: - fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth); - fTop = TrueToFace(m_sData.fScrollPos); - - if (IsFloatSmaller(fTop - fBottom, PWL_SCROLLBAR_POSBUTTON_MINWIDTH)) - fBottom = fTop - PWL_SCROLLBAR_POSBUTTON_MINWIDTH; - - if (IsFloatSmaller(fBottom, rcPosArea.bottom)) { - fBottom = rcPosArea.bottom; - fTop = fBottom + PWL_SCROLLBAR_POSBUTTON_MINWIDTH; - } - - rcPosButton = - CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop); - - break; - } - - m_pPosButton->Move(rcPosButton, true, bRefresh); - } -} - -void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) { - m_sData.SubSmall(); - MovePosButton(true); - NotifyScrollWindow(); - - m_bMinOrMax = true; - - EndTimer(); - BeginTimer(100); -} - -void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {} - -void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {} - -void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) { - m_sData.AddSmall(); - MovePosButton(true); - NotifyScrollWindow(); - - m_bMinOrMax = false; - - EndTimer(); - BeginTimer(100); -} - -void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {} - -void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {} - -void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) { - m_bMouseDown = true; - - if (m_pPosButton) { - CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect(); - - switch (m_sbType) { - case SBT_HSCROLL: - m_nOldPos = point.x; - m_fOldPosButton = rcPosButton.left; - break; - case SBT_VSCROLL: - m_nOldPos = point.y; - m_fOldPosButton = rcPosButton.top; - break; - } - } -} - -void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) { - if (m_bMouseDown) { - if (!m_bNotifyForever) - NotifyScrollWindow(); - } - m_bMouseDown = false; -} - -void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) { - FX_FLOAT fOldScrollPos = m_sData.fScrollPos; - - FX_FLOAT fNewPos = 0; - - switch (m_sbType) { - case SBT_HSCROLL: - if (FXSYS_fabs(point.x - m_nOldPos) < 1) - return; - fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos); - break; - case SBT_VSCROLL: - if (FXSYS_fabs(point.y - m_nOldPos) < 1) - return; - fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos); - break; - } - - if (m_bMouseDown) { - switch (m_sbType) { - case SBT_HSCROLL: - - if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) { - fNewPos = m_sData.ScrollRange.fMin; - } - - if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) { - fNewPos = m_sData.ScrollRange.fMax; - } - - m_sData.SetPos(fNewPos); - - break; - case SBT_VSCROLL: - - if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) { - fNewPos = m_sData.ScrollRange.fMin; - } - - if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) { - fNewPos = m_sData.ScrollRange.fMax; - } - - m_sData.SetPos(fNewPos); - - break; - } - - if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) { - MovePosButton(true); - - if (m_bNotifyForever) - NotifyScrollWindow(); - } - } -} - -void CPWL_ScrollBar::NotifyScrollWindow() { - if (CPWL_Wnd* pParent = GetParentWindow()) { - FX_FLOAT fPos; - switch (m_sbType) { - case SBT_HSCROLL: - fPos = m_OriginInfo.fContentMin + m_sData.fScrollPos; - break; - case SBT_VSCROLL: - fPos = m_OriginInfo.fContentMax - m_sData.fScrollPos; - break; - } - pParent->OnNotify(this, PNM_SCROLLWINDOW, (intptr_t)m_sbType, - (intptr_t)&fPos); - } -} - -CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const { - CFX_FloatRect rcClient = GetClientRect(); - CFX_FloatRect rcArea; - - if (!m_pMinButton || !m_pMaxButton) - return rcClient; - - CFX_FloatRect rcMin = m_pMinButton->GetWindowRect(); - CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect(); - - FX_FLOAT fMinWidth = rcMin.right - rcMin.left; - FX_FLOAT fMinHeight = rcMin.top - rcMin.bottom; - FX_FLOAT fMaxWidth = rcMax.right - rcMax.left; - FX_FLOAT fMaxHeight = rcMax.top - rcMax.bottom; - - switch (m_sbType) { - case SBT_HSCROLL: - if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) { - rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom, - rcClient.right - fMaxWidth - 1, rcClient.top); - } else { - rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom, - rcClient.left + fMinWidth + 1, rcClient.top); - } - break; - case SBT_VSCROLL: - if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) { - rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1, - rcClient.right, rcClient.top - fMaxHeight - 1); - } else { - rcArea = - CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1, - rcClient.right, rcClient.bottom + fMinHeight + 1); - } - break; - } - - rcArea.Normalize(); - - return rcArea; -} - -FX_FLOAT CPWL_ScrollBar::TrueToFace(FX_FLOAT fTrue) { - CFX_FloatRect rcPosArea; - rcPosArea = GetScrollArea(); - - FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth; - fFactWidth = fFactWidth == 0 ? 1 : fFactWidth; - - FX_FLOAT fFace = 0; - - switch (m_sbType) { - case SBT_HSCROLL: - fFace = rcPosArea.left + - fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth; - break; - case SBT_VSCROLL: - fFace = rcPosArea.top - - fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth; - break; - } - - return fFace; -} - -FX_FLOAT CPWL_ScrollBar::FaceToTrue(FX_FLOAT fFace) { - CFX_FloatRect rcPosArea; - rcPosArea = GetScrollArea(); - - FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth; - fFactWidth = fFactWidth == 0 ? 1 : fFactWidth; - - FX_FLOAT fTrue = 0; - - switch (m_sbType) { - case SBT_HSCROLL: - fTrue = (fFace - rcPosArea.left) * fFactWidth / - (rcPosArea.right - rcPosArea.left); - break; - case SBT_VSCROLL: - fTrue = (rcPosArea.top - fFace) * fFactWidth / - (rcPosArea.top - rcPosArea.bottom); - break; - } - - return fTrue; -} - -void CPWL_ScrollBar::CreateChildWnd(const PWL_CREATEPARAM& cp) { - CreateButtons(cp); -} - -void CPWL_ScrollBar::TimerProc() { - PWL_SCROLL_PRIVATEDATA sTemp = m_sData; - if (m_bMinOrMax) - m_sData.SubSmall(); - else - m_sData.AddSmall(); - - if (sTemp != m_sData) { - MovePosButton(true); - NotifyScrollWindow(); - } -} diff --git a/fpdfsdk/pdfwindow/PWL_ScrollBar.h b/fpdfsdk/pdfwindow/PWL_ScrollBar.h deleted file mode 100644 index 9546a9e577c77f9fe52cb9cb4fca4c10e8a6fd97..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_ScrollBar.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_SCROLLBAR_H_ -#define FPDFSDK_PDFWINDOW_PWL_SCROLLBAR_H_ - -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CPWL_SBButton; -class CPWL_ScrollBar; - -struct PWL_SCROLL_INFO { - public: - PWL_SCROLL_INFO() - : fContentMin(0.0f), - fContentMax(0.0f), - fPlateWidth(0.0f), - fBigStep(0.0f), - fSmallStep(0.0f) {} - - bool operator==(const PWL_SCROLL_INFO& that) const { - return fContentMin == that.fContentMin && fContentMax == that.fContentMax && - fPlateWidth == that.fPlateWidth && fBigStep == that.fBigStep && - fSmallStep == that.fSmallStep; - } - bool operator!=(const PWL_SCROLL_INFO& that) const { - return !(*this == that); - } - - FX_FLOAT fContentMin; - FX_FLOAT fContentMax; - FX_FLOAT fPlateWidth; - FX_FLOAT fBigStep; - FX_FLOAT fSmallStep; -}; - -enum PWL_SCROLLBAR_TYPE { SBT_HSCROLL, SBT_VSCROLL }; - -enum PWL_SBBUTTON_TYPE { PSBT_MIN, PSBT_MAX, PSBT_POS }; - -class CPWL_SBButton : public CPWL_Wnd { - public: - CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, - PWL_SBBUTTON_TYPE eButtonType); - ~CPWL_SBButton() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) override; - void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override; - void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; - - protected: - PWL_SCROLLBAR_TYPE m_eScrollBarType; - PWL_SBBUTTON_TYPE m_eSBButtonType; - - bool m_bMouseDown; -}; - -struct PWL_FLOATRANGE { - public: - PWL_FLOATRANGE(); - PWL_FLOATRANGE(FX_FLOAT min, FX_FLOAT max); - - bool operator==(const PWL_FLOATRANGE& that) const { - return fMin == that.fMin && fMax == that.fMax; - } - bool operator!=(const PWL_FLOATRANGE& that) const { return !(*this == that); } - - void Default(); - void Set(FX_FLOAT min, FX_FLOAT max); - bool In(FX_FLOAT x) const; - FX_FLOAT GetWidth() const; - - FX_FLOAT fMin; - FX_FLOAT fMax; -}; - -struct PWL_SCROLL_PRIVATEDATA { - public: - PWL_SCROLL_PRIVATEDATA(); - - bool operator==(const PWL_SCROLL_PRIVATEDATA& that) const { - return ScrollRange == that.ScrollRange && - fClientWidth == that.fClientWidth && fScrollPos == that.fScrollPos && - fBigStep == that.fBigStep && fSmallStep == that.fSmallStep; - } - bool operator!=(const PWL_SCROLL_PRIVATEDATA& that) const { - return !(*this == that); - } - - void Default(); - void SetScrollRange(FX_FLOAT min, FX_FLOAT max); - void SetClientWidth(FX_FLOAT width); - void SetSmallStep(FX_FLOAT step); - void SetBigStep(FX_FLOAT step); - bool SetPos(FX_FLOAT pos); - - void AddSmall(); - void SubSmall(); - void AddBig(); - void SubBig(); - - PWL_FLOATRANGE ScrollRange; - FX_FLOAT fClientWidth; - FX_FLOAT fScrollPos; - FX_FLOAT fBigStep; - FX_FLOAT fSmallStep; -}; - -class CPWL_ScrollBar : public CPWL_Wnd { - public: - explicit CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType = SBT_HSCROLL); - ~CPWL_ScrollBar() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) override; - void RePosChildWnd() override; - void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override; - void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - void OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam = 0, - intptr_t lParam = 0) override; - void CreateChildWnd(const PWL_CREATEPARAM& cp) override; - void TimerProc() override; - - FX_FLOAT GetScrollBarWidth() const; - PWL_SCROLLBAR_TYPE GetScrollBarType() const { return m_sbType; } - - void SetNotifyForever(bool bForever) { m_bNotifyForever = bForever; } - - protected: - void SetScrollRange(FX_FLOAT fMin, FX_FLOAT fMax, FX_FLOAT fClientWidth); - void SetScrollPos(FX_FLOAT fPos); - void MovePosButton(bool bRefresh); - void SetScrollStep(FX_FLOAT fBigStep, FX_FLOAT fSmallStep); - void NotifyScrollWindow(); - CFX_FloatRect GetScrollArea() const; - - private: - void CreateButtons(const PWL_CREATEPARAM& cp); - - void OnMinButtonLBDown(const CFX_PointF& point); - void OnMinButtonLBUp(const CFX_PointF& point); - void OnMinButtonMouseMove(const CFX_PointF& point); - - void OnMaxButtonLBDown(const CFX_PointF& point); - void OnMaxButtonLBUp(const CFX_PointF& point); - void OnMaxButtonMouseMove(const CFX_PointF& point); - - void OnPosButtonLBDown(const CFX_PointF& point); - void OnPosButtonLBUp(const CFX_PointF& point); - void OnPosButtonMouseMove(const CFX_PointF& point); - - FX_FLOAT TrueToFace(FX_FLOAT); - FX_FLOAT FaceToTrue(FX_FLOAT); - - PWL_SCROLLBAR_TYPE m_sbType; - PWL_SCROLL_INFO m_OriginInfo; - CPWL_SBButton* m_pMinButton; - CPWL_SBButton* m_pMaxButton; - CPWL_SBButton* m_pPosButton; - PWL_SCROLL_PRIVATEDATA m_sData; - bool m_bMouseDown; - bool m_bMinOrMax; - bool m_bNotifyForever; - FX_FLOAT m_nOldPos; - FX_FLOAT m_fOldPosButton; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_SCROLLBAR_H_ diff --git a/fpdfsdk/pdfwindow/PWL_SpecialButton.cpp b/fpdfsdk/pdfwindow/PWL_SpecialButton.cpp deleted file mode 100644 index 1c46c375a9d9d5ccab468485a85e16435f502c2e..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_SpecialButton.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_Button.h" -#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -CPWL_PushButton::CPWL_PushButton() {} - -CPWL_PushButton::~CPWL_PushButton() {} - -CFX_ByteString CPWL_PushButton::GetClassName() const { - return "CPWL_PushButton"; -} - -CFX_FloatRect CPWL_PushButton::GetFocusRect() const { - return CPWL_Utils::DeflateRect(GetWindowRect(), (FX_FLOAT)GetBorderWidth()); -} - -CPWL_CheckBox::CPWL_CheckBox() : m_bChecked(false) {} - -CPWL_CheckBox::~CPWL_CheckBox() {} - -CFX_ByteString CPWL_CheckBox::GetClassName() const { - return "CPWL_CheckBox"; -} - -void CPWL_CheckBox::SetCheck(bool bCheck) { - m_bChecked = bCheck; -} - -bool CPWL_CheckBox::IsChecked() const { - return m_bChecked; -} - -bool CPWL_CheckBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - if (IsReadOnly()) - return false; - - SetCheck(!IsChecked()); - return true; -} - -bool CPWL_CheckBox::OnChar(uint16_t nChar, uint32_t nFlag) { - SetCheck(!IsChecked()); - return true; -} - -CPWL_RadioButton::CPWL_RadioButton() : m_bChecked(false) {} - -CPWL_RadioButton::~CPWL_RadioButton() {} - -CFX_ByteString CPWL_RadioButton::GetClassName() const { - return "CPWL_RadioButton"; -} - -bool CPWL_RadioButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - if (IsReadOnly()) - return false; - - SetCheck(true); - return true; -} - -void CPWL_RadioButton::SetCheck(bool bCheck) { - m_bChecked = bCheck; -} - -bool CPWL_RadioButton::IsChecked() const { - return m_bChecked; -} - -bool CPWL_RadioButton::OnChar(uint16_t nChar, uint32_t nFlag) { - SetCheck(true); - return true; -} diff --git a/fpdfsdk/pdfwindow/PWL_SpecialButton.h b/fpdfsdk/pdfwindow/PWL_SpecialButton.h deleted file mode 100644 index 93f611b744622ffe0655d96a8663f6b4e76c9835..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_SpecialButton.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_SPECIALBUTTON_H_ -#define FPDFSDK_PDFWINDOW_PWL_SPECIALBUTTON_H_ - -#include "fpdfsdk/pdfwindow/PWL_Button.h" - -class CPWL_PushButton : public CPWL_Button { - public: - CPWL_PushButton(); - ~CPWL_PushButton() override; - - // CPWL_Button - CFX_ByteString GetClassName() const override; - CFX_FloatRect GetFocusRect() const override; -}; - -class CPWL_CheckBox : public CPWL_Button { - public: - CPWL_CheckBox(); - ~CPWL_CheckBox() override; - - // CPWL_Button - CFX_ByteString GetClassName() const override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - - void SetCheck(bool bCheck); - bool IsChecked() const; - - private: - bool m_bChecked; -}; - -class CPWL_RadioButton : public CPWL_Button { - public: - CPWL_RadioButton(); - ~CPWL_RadioButton() override; - - // CPWL_Button - CFX_ByteString GetClassName() const override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - - void SetCheck(bool bCheck); - bool IsChecked() const; - - private: - bool m_bChecked; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_SPECIALBUTTON_H_ diff --git a/fpdfsdk/pdfwindow/PWL_Utils.cpp b/fpdfsdk/pdfwindow/PWL_Utils.cpp deleted file mode 100644 index 45668b6a25fd37320df9cfea4653762b06960e8e..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Utils.cpp +++ /dev/null @@ -1,1172 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/PWL_Utils.h" - -#include -#include - -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/fxedit/fxet_edit.h" -#include "fpdfsdk/pdfwindow/PWL_Icon.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -CFX_FloatRect CPWL_Utils::OffsetRect(const CFX_FloatRect& rect, - FX_FLOAT x, - FX_FLOAT y) { - return CFX_FloatRect(rect.left + x, rect.bottom + y, rect.right + x, - rect.top + y); -} - -CPVT_WordRange CPWL_Utils::OverlapWordRange(const CPVT_WordRange& wr1, - const CPVT_WordRange& wr2) { - CPVT_WordRange wrRet; - - if (wr2.EndPos.WordCmp(wr1.BeginPos) < 0 || - wr2.BeginPos.WordCmp(wr1.EndPos) > 0) - return wrRet; - if (wr1.EndPos.WordCmp(wr2.BeginPos) < 0 || - wr1.BeginPos.WordCmp(wr2.EndPos) > 0) - return wrRet; - - if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) { - wrRet.BeginPos = wr2.BeginPos; - } else { - wrRet.BeginPos = wr1.BeginPos; - } - - if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) { - wrRet.EndPos = wr1.EndPos; - } else { - wrRet.EndPos = wr2.EndPos; - } - - return wrRet; -} - -CFX_ByteString CPWL_Utils::GetAP_Check(const CFX_FloatRect& crBBox) { - const FX_FLOAT fWidth = crBBox.right - crBBox.left; - const FX_FLOAT fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), - CFX_PointF(0.29f, 0.40f)}, - {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), - CFX_PointF(0.31f, 0.28f)}, - {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), - CFX_PointF(0.77f, 0.67f)}, - {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), - CFX_PointF(0.76f, 0.75f)}, - {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), - CFX_PointF(0.68f, 0.75f)}, - {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), - CFX_PointF(0.44f, 0.47f)}, - {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), - CFX_PointF(0.41f, 0.58f)}, - {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), - CFX_PointF(0.30f, 0.56f)}}; - - for (size_t i = 0; i < FX_ArraySize(pts); ++i) { - for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { - pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; - pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; - } - } - - CFX_ByteTextBuf csAP; - csAP << pts[0][0].x << " " << pts[0][0].y << " m\n"; - - for (size_t i = 0; i < FX_ArraySize(pts); ++i) { - size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0; - - FX_FLOAT px1 = pts[i][1].x - pts[i][0].x; - FX_FLOAT py1 = pts[i][1].y - pts[i][0].y; - FX_FLOAT px2 = pts[i][2].x - pts[nNext][0].x; - FX_FLOAT py2 = pts[i][2].y - pts[nNext][0].y; - - csAP << pts[i][0].x + px1 * FX_BEZIER << " " - << pts[i][0].y + py1 * FX_BEZIER << " " - << pts[nNext][0].x + px2 * FX_BEZIER << " " - << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " " - << pts[nNext][0].y << " c\n"; - } - - return csAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAP_Circle(const CFX_FloatRect& crBBox) { - CFX_ByteTextBuf csAP; - - FX_FLOAT fWidth = crBBox.right - crBBox.left; - FX_FLOAT fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); - CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); - CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); - CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); - - csAP << pt1.x << " " << pt1.y << " m\n"; - - FX_FLOAT px = pt2.x - pt1.x; - FX_FLOAT py = pt2.y - pt1.y; - - csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " - << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y - << " c\n"; - - px = pt3.x - pt2.x; - py = pt2.y - pt3.y; - - csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " - << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; - - px = pt3.x - pt4.x; - py = pt3.y - pt4.y; - - csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " " - << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y - << " c\n"; - - px = pt4.x - pt1.x; - py = pt1.y - pt4.y; - - csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " " - << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " c\n"; - - return csAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAP_Cross(const CFX_FloatRect& crBBox) { - CFX_ByteTextBuf csAP; - - csAP << crBBox.left << " " << crBBox.top << " m\n"; - csAP << crBBox.right << " " << crBBox.bottom << " l\n"; - csAP << crBBox.left << " " << crBBox.bottom << " m\n"; - csAP << crBBox.right << " " << crBBox.top << " l\n"; - - return csAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAP_Diamond(const CFX_FloatRect& crBBox) { - CFX_ByteTextBuf csAP; - - FX_FLOAT fWidth = crBBox.right - crBBox.left; - FX_FLOAT fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); - CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); - CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); - CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); - - csAP << pt1.x << " " << pt1.y << " m\n"; - csAP << pt2.x << " " << pt2.y << " l\n"; - csAP << pt3.x << " " << pt3.y << " l\n"; - csAP << pt4.x << " " << pt4.y << " l\n"; - csAP << pt1.x << " " << pt1.y << " l\n"; - - return csAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAP_Square(const CFX_FloatRect& crBBox) { - CFX_ByteTextBuf csAP; - - csAP << crBBox.left << " " << crBBox.top << " m\n"; - csAP << crBBox.right << " " << crBBox.top << " l\n"; - csAP << crBBox.right << " " << crBBox.bottom << " l\n"; - csAP << crBBox.left << " " << crBBox.bottom << " l\n"; - csAP << crBBox.left << " " << crBBox.top << " l\n"; - - return csAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAP_Star(const CFX_FloatRect& crBBox) { - CFX_ByteTextBuf csAP; - - FX_FLOAT fRadius = - (crBBox.top - crBBox.bottom) / (1 + (FX_FLOAT)cos(FX_PI / 5.0f)); - CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, - (crBBox.top + crBBox.bottom) / 2.0f); - - FX_FLOAT px[5], py[5]; - - FX_FLOAT fAngel = FX_PI / 10.0f; - - for (int32_t i = 0; i < 5; i++) { - px[i] = ptCenter.x + fRadius * (FX_FLOAT)cos(fAngel); - py[i] = ptCenter.y + fRadius * (FX_FLOAT)sin(fAngel); - - fAngel += FX_PI * 2 / 5.0f; - } - - csAP << px[0] << " " << py[0] << " m\n"; - - int32_t nNext = 0; - for (int32_t j = 0; j < 5; j++) { - nNext += 2; - if (nNext >= 5) - nNext -= 5; - csAP << px[nNext] << " " << py[nNext] << " l\n"; - } - - return csAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAP_HalfCircle(const CFX_FloatRect& crBBox, - FX_FLOAT fRotate) { - CFX_ByteTextBuf csAP; - - FX_FLOAT fWidth = crBBox.right - crBBox.left; - FX_FLOAT fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(-fWidth / 2, 0); - CFX_PointF pt2(0, fHeight / 2); - CFX_PointF pt3(fWidth / 2, 0); - - FX_FLOAT px, py; - - csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " - << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " - << crBBox.bottom + fHeight / 2 << " cm\n"; - - csAP << pt1.x << " " << pt1.y << " m\n"; - - px = pt2.x - pt1.x; - py = pt2.y - pt1.y; - - csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " - << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y - << " c\n"; - - px = pt3.x - pt2.x; - py = pt2.y - pt3.y; - - csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " - << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; - - return csAP.MakeString(); -} - -CFX_FloatRect CPWL_Utils::InflateRect(const CFX_FloatRect& rcRect, - FX_FLOAT fSize) { - if (rcRect.IsEmpty()) - return rcRect; - - CFX_FloatRect rcNew(rcRect.left - fSize, rcRect.bottom - fSize, - rcRect.right + fSize, rcRect.top + fSize); - rcNew.Normalize(); - return rcNew; -} - -CFX_FloatRect CPWL_Utils::DeflateRect(const CFX_FloatRect& rcRect, - FX_FLOAT fSize) { - if (rcRect.IsEmpty()) - return rcRect; - - CFX_FloatRect rcNew(rcRect.left + fSize, rcRect.bottom + fSize, - rcRect.right - fSize, rcRect.top - fSize); - rcNew.Normalize(); - return rcNew; -} - -CFX_FloatRect CPWL_Utils::ScaleRect(const CFX_FloatRect& rcRect, - FX_FLOAT fScale) { - FX_FLOAT fHalfWidth = (rcRect.right - rcRect.left) / 2.0f; - FX_FLOAT fHalfHeight = (rcRect.top - rcRect.bottom) / 2.0f; - - CFX_PointF ptCenter = CFX_PointF((rcRect.left + rcRect.right) / 2, - (rcRect.top + rcRect.bottom) / 2); - - return CFX_FloatRect( - ptCenter.x - fHalfWidth * fScale, ptCenter.y - fHalfHeight * fScale, - ptCenter.x + fHalfWidth * fScale, ptCenter.y + fHalfHeight * fScale); -} - -CFX_ByteString CPWL_Utils::GetRectFillAppStream(const CFX_FloatRect& rect, - const CPWL_Color& color) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sColor = GetColorAppStream(color, true); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << sColor; - sAppStream << rect.left << " " << rect.bottom << " " - << rect.right - rect.left << " " << rect.top - rect.bottom - << " re f\nQ\n"; - } - - return sAppStream.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetCircleFillAppStream(const CFX_FloatRect& rect, - const CPWL_Color& color) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sColor = GetColorAppStream(color, true); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << sColor << CPWL_Utils::GetAP_Circle(rect) << "f\nQ\n"; - } - return sAppStream.MakeString(); -} - -CFX_FloatRect CPWL_Utils::GetCenterSquare(const CFX_FloatRect& rect) { - FX_FLOAT fWidth = rect.right - rect.left; - FX_FLOAT fHeight = rect.top - rect.bottom; - - FX_FLOAT fCenterX = (rect.left + rect.right) / 2.0f; - FX_FLOAT fCenterY = (rect.top + rect.bottom) / 2.0f; - - FX_FLOAT fRadius = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2; - - return CFX_FloatRect(fCenterX - fRadius, fCenterY - fRadius, - fCenterX + fRadius, fCenterY + fRadius); -} - -CFX_ByteString CPWL_Utils::GetEditAppStream(CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange, - bool bContinuous, - uint16_t SubWord) { - return CFX_Edit::GetEditAppearanceStream(pEdit, ptOffset, pRange, bContinuous, - SubWord); -} - -CFX_ByteString CPWL_Utils::GetEditSelAppStream(CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange) { - return CFX_Edit::GetSelectAppearanceStream(pEdit, ptOffset, pRange); -} - -CFX_ByteString CPWL_Utils::GetPushButtonAppStream(const CFX_FloatRect& rcBBox, - IPVT_FontMap* pFontMap, - CPDF_Stream* pIconStream, - CPDF_IconFit& IconFit, - const CFX_WideString& sLabel, - const CPWL_Color& crText, - FX_FLOAT fFontSize, - int32_t nLayOut) { - const FX_FLOAT fAutoFontScale = 1.0f / 3.0f; - - std::unique_ptr pEdit(new CFX_Edit); - pEdit->SetFontMap(pFontMap); - pEdit->SetAlignmentH(1, true); - pEdit->SetAlignmentV(1, true); - pEdit->SetMultiLine(false, true); - pEdit->SetAutoReturn(false, true); - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - pEdit->SetText(sLabel); - - CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); - CPWL_Icon Icon; - PWL_CREATEPARAM cp; - cp.dwFlags = PWS_VISIBLE; - Icon.Create(cp); - Icon.SetIconFit(&IconFit); - Icon.SetPDFStream(pIconStream); - - CFX_FloatRect rcLabel = CFX_FloatRect(0, 0, 0, 0); - CFX_FloatRect rcIcon = CFX_FloatRect(0, 0, 0, 0); - FX_FLOAT fWidth = 0.0f; - FX_FLOAT fHeight = 0.0f; - - switch (nLayOut) { - case PPBL_LABEL: - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - break; - case PPBL_ICON: - rcIcon = rcBBox; - rcLabel = CFX_FloatRect(0, 0, 0, 0); - break; - case PPBL_ICONTOPLABELBOTTOM: - - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fHeight = rcBBox.top - rcBBox.bottom; - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcBBox.bottom + fHeight * fAutoFontScale); - rcIcon = - CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top); - } else { - fHeight = rcLabelContent.Height(); - - if (rcBBox.bottom + fHeight > rcBBox.top) { - rcIcon = CFX_FloatRect(0, 0, 0, 0); - rcLabel = rcBBox; - } else { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcBBox.bottom + fHeight); - rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, - rcBBox.top); - } - } - } else { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } - - break; - case PPBL_LABELTOPICONBOTTOM: - - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fHeight = rcBBox.top - rcBBox.bottom; - rcLabel = - CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale, - rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcLabel.bottom); - } else { - fHeight = rcLabelContent.Height(); - - if (rcBBox.bottom + fHeight > rcBBox.top) { - rcIcon = CFX_FloatRect(0, 0, 0, 0); - rcLabel = rcBBox; - } else { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight, - rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcLabel.bottom); - } - } - } else { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } - - break; - case PPBL_ICONLEFTLABELRIGHT: - - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fWidth = rcBBox.right - rcBBox.left; - rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale, - rcBBox.bottom, rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, - rcBBox.top); - - if (rcLabelContent.Width() < fWidth * fAutoFontScale) { - } else { - if (rcLabelContent.Width() < fWidth) { - rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(), - rcBBox.bottom, rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, - rcBBox.top); - } else { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } - } - } else { - fWidth = rcLabelContent.Width(); - - if (rcBBox.left + fWidth > rcBBox.right) { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } else { - rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom, - rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, - rcBBox.top); - } - } - } else { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } - - break; - case PPBL_LABELLEFTICONRIGHT: - - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fWidth = rcBBox.right - rcBBox.left; - rcLabel = - CFX_FloatRect(rcBBox.left, rcBBox.bottom, - rcBBox.left + fWidth * fAutoFontScale, rcBBox.top); - rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, - rcBBox.top); - - if (rcLabelContent.Width() < fWidth * fAutoFontScale) { - } else { - if (rcLabelContent.Width() < fWidth) { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, - rcBBox.left + rcLabelContent.Width(), - rcBBox.top); - rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, - rcBBox.top); - } else { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } - } - } else { - fWidth = rcLabelContent.Width(); - - if (rcBBox.left + fWidth > rcBBox.right) { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } else { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, - rcBBox.left + fWidth, rcBBox.top); - rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, - rcBBox.top); - } - } - } else { - rcLabel = rcBBox; - rcIcon = CFX_FloatRect(0, 0, 0, 0); - } - - break; - case PPBL_LABELOVERICON: - rcLabel = rcBBox; - rcIcon = rcBBox; - break; - } - - CFX_ByteTextBuf sAppStream, sTemp; - - if (!rcIcon.IsEmpty()) { - Icon.Move(rcIcon, false, false); - sTemp << Icon.GetImageAppStream(); - } - - Icon.Destroy(); - - if (!rcLabel.IsEmpty()) { - pEdit->SetPlateRect(rcLabel); - CFX_ByteString sEdit = - CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f)); - if (sEdit.GetLength() > 0) { - sTemp << "BT\n" - << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"; - } - } - - if (sTemp.GetSize() > 0) { - sAppStream << "q\n" - << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.right - rcBBox.left << " " - << rcBBox.top - rcBBox.bottom << " re W n\n"; - sAppStream << sTemp << "Q\n"; - } - return sAppStream.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetColorAppStream(const CPWL_Color& color, - const bool& bFillOrStroke) { - CFX_ByteTextBuf sColorStream; - - switch (color.nColorType) { - case COLORTYPE_RGB: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG") - << "\n"; - break; - case COLORTYPE_GRAY: - sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") - << "\n"; - break; - case COLORTYPE_CMYK: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " << color.fColor4 << " " - << (bFillOrStroke ? "k" : "K") << "\n"; - break; - } - - return sColorStream.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetBorderAppStream(const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPWL_Color& color, - const CPWL_Color& crLeftTop, - const CPWL_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sColor; - - FX_FLOAT fLeft = rect.left; - FX_FLOAT fRight = rect.right; - FX_FLOAT fTop = rect.top; - FX_FLOAT fBottom = rect.bottom; - - if (fWidth > 0.0f) { - FX_FLOAT fHalfWidth = fWidth / 2.0f; - - sAppStream << "q\n"; - - switch (nStyle) { - default: - case BorderStyle::SOLID: - sColor = CPWL_Utils::GetColorAppStream(color, true); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " - << fTop - fBottom << " re\n"; - sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " - << fRight - fLeft - fWidth * 2 << " " - << fTop - fBottom - fWidth * 2 << " re\n"; - sAppStream << "f*\n"; - } - break; - case BorderStyle::DASH: - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fWidth << " w" - << " [" << dash.nDash << " " << dash.nGap << "] " - << dash.nPhase << " d\n"; - sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 - << " m\n"; - sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 - << " l\n"; - sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 - << " l\n"; - sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 - << " l\n"; - sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 - << " l S\n"; - } - break; - case BorderStyle::BEVELED: - case BorderStyle::INSET: - sColor = CPWL_Utils::GetColorAppStream(crLeftTop, true); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth - << " m\n"; - sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth - << " l\n"; - sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth - << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l f\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crRightBottom, true); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth - << " m\n"; - sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth - << " l\n"; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l f\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(color, true); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " - << fTop - fBottom << " re\n"; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " - << fRight - fLeft - fHalfWidth * 2 << " " - << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; - } - break; - case BorderStyle::UNDERLINE: - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fWidth << " w\n"; - sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; - sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; - } - break; - } - - sAppStream << "Q\n"; - } - - return sAppStream.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetCircleBorderAppStream( - const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPWL_Color& color, - const CPWL_Color& crLeftTop, - const CPWL_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sColor; - - if (fWidth > 0.0f) { - sAppStream << "q\n"; - - switch (nStyle) { - default: - case BorderStyle::SOLID: - case BorderStyle::UNDERLINE: { - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fWidth << " w\n" << sColor - << CPWL_Utils::GetAP_Circle( - CPWL_Utils::DeflateRect(rect, fWidth / 2.0f)) - << " S\nQ\n"; - } - } break; - case BorderStyle::DASH: { - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fWidth << " w\n" - << "[" << dash.nDash << " " << dash.nGap << "] " - << dash.nPhase << " d\n" << sColor - << CPWL_Utils::GetAP_Circle( - CPWL_Utils::DeflateRect(rect, fWidth / 2.0f)) - << " S\nQ\n"; - } - } break; - case BorderStyle::BEVELED: { - FX_FLOAT fHalfWidth = fWidth / 2.0f; - - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fHalfWidth << " w\n" << sColor - << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fHalfWidth << " w\n" << sColor - << CPWL_Utils::GetAP_HalfCircle( - CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), - FX_PI / 4.0f) - << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fHalfWidth << " w\n" << sColor - << CPWL_Utils::GetAP_HalfCircle( - CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), - FX_PI * 5 / 4.0f) - << " S\nQ\n"; - } - } break; - case BorderStyle::INSET: { - FX_FLOAT fHalfWidth = fWidth / 2.0f; - - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fHalfWidth << " w\n" << sColor - << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fHalfWidth << " w\n" << sColor - << CPWL_Utils::GetAP_HalfCircle( - CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), - FX_PI / 4.0f) - << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" << fHalfWidth << " w\n" << sColor - << CPWL_Utils::GetAP_HalfCircle( - CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), - FX_PI * 5 / 4.0f) - << " S\nQ\n"; - } - } break; - } - - sAppStream << "Q\n"; - } - - return sAppStream.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Check(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText) { - CFX_ByteTextBuf sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Check(rcBBox) << "f\nQ\n"; - return sAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Circle(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText) { - CFX_ByteTextBuf sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Circle(rcBBox) << "f\nQ\n"; - return sAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Cross(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText) { - CFX_ByteTextBuf sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, false) - << CPWL_Utils::GetAP_Cross(rcBBox) << "S\nQ\n"; - return sAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Diamond(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText) { - CFX_ByteTextBuf sAP; - sAP << "q\n1 w\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Diamond(rcBBox) << "f\nQ\n"; - return sAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Square(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText) { - CFX_ByteTextBuf sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Square(rcBBox) << "f\nQ\n"; - return sAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Star(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText) { - CFX_ByteTextBuf sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Star(rcBBox) << "f\nQ\n"; - return sAP.MakeString(); -} - -CFX_ByteString CPWL_Utils::GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CPWL_Color& crText) { - CFX_FloatRect rcCenter = GetCenterSquare(rcBBox); - switch (nStyle) { - default: - case PCS_CHECK: - return GetAppStream_Check(rcCenter, crText); - case PCS_CIRCLE: - return GetAppStream_Circle(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - case PCS_CROSS: - return GetAppStream_Cross(rcCenter, crText); - case PCS_DIAMOND: - return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - case PCS_SQUARE: - return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - case PCS_STAR: - return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - } -} - -CFX_ByteString CPWL_Utils::GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CPWL_Color& crText) { - CFX_FloatRect rcCenter = GetCenterSquare(rcBBox); - switch (nStyle) { - default: - case PCS_CHECK: - return GetAppStream_Check(rcCenter, crText); - case PCS_CIRCLE: - return GetAppStream_Circle(ScaleRect(rcCenter, 1.0f / 2.0f), crText); - case PCS_CROSS: - return GetAppStream_Cross(rcCenter, crText); - case PCS_DIAMOND: - return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - case PCS_SQUARE: - return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - case PCS_STAR: - return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText); - } -} - -CFX_ByteString CPWL_Utils::GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { - CFX_ByteTextBuf sAppStream; - - if (!rcBBox.IsEmpty()) { - sAppStream << "q\n" - << CPWL_Utils::GetColorAppStream( - CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f, - 220.0f / 255.0f, 220.0f / 255.0f), - true); - sAppStream << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.right - rcBBox.left << " " - << rcBBox.top - rcBBox.bottom << " re f\n"; - sAppStream << "Q\n"; - - sAppStream << "q\n" - << CPWL_Utils::GetBorderAppStream( - rcBBox, 2, CPWL_Color(COLORTYPE_GRAY, 0), - CPWL_Color(COLORTYPE_GRAY, 1), - CPWL_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED, - CPWL_Dash(3, 0, 0)) - << "Q\n"; - - CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2, - (rcBBox.top + rcBBox.bottom) / 2); - if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) && - IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) { - sAppStream << "q\n" - << " 0 g\n"; - sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; - sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; - sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; - sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; - sAppStream << "Q\n"; - } - } - - return sAppStream.MakeString(); -} - -void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - const FX_COLORREF& color) { - CFX_PathData path; - CFX_FloatRect rcTemp(rect); - path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top); - pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_WINDING); -} - -void CPWL_Utils::DrawFillArea(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_PointF* pPts, - int32_t nCount, - const FX_COLORREF& color) { - CFX_PathData path; - path.AppendPoint(pPts[0], FXPT_TYPE::MoveTo, false); - for (int32_t i = 1; i < nCount; i++) - path.AppendPoint(pPts[i], FXPT_TYPE::LineTo, false); - - pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_ALTERNATE); -} - -void CPWL_Utils::DrawStrokeRect(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - const FX_COLORREF& color, - FX_FLOAT fWidth) { - CFX_PathData path; - CFX_FloatRect rcTemp(rect); - path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top); - - CFX_GraphStateData gsd; - gsd.m_LineWidth = fWidth; - - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE); -} - -void CPWL_Utils::DrawStrokeLine(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_PointF& ptMoveTo, - const CFX_PointF& ptLineTo, - const FX_COLORREF& color, - FX_FLOAT fWidth) { - CFX_PathData path; - path.AppendPoint(ptMoveTo, FXPT_TYPE::MoveTo, false); - path.AppendPoint(ptLineTo, FXPT_TYPE::LineTo, false); - - CFX_GraphStateData gsd; - gsd.m_LineWidth = fWidth; - - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE); -} - -void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - const CPWL_Color& color, - int32_t nTransparency) { - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rect, - color.ToFXColor(nTransparency)); -} - -void CPWL_Utils::DrawShadow(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - bool bVertical, - bool bHorizontal, - CFX_FloatRect rect, - int32_t nTransparency, - int32_t nStartGray, - int32_t nEndGray) { - FX_FLOAT fStepGray = 1.0f; - - if (bVertical) { - fStepGray = (nEndGray - nStartGray) / rect.Height(); - - for (FX_FLOAT fy = rect.bottom + 0.5f; fy <= rect.top - 0.5f; fy += 1.0f) { - int32_t nGray = nStartGray + (int32_t)(fStepGray * (fy - rect.bottom)); - CPWL_Utils::DrawStrokeLine( - pDevice, pUser2Device, CFX_PointF(rect.left, fy), - CFX_PointF(rect.right, fy), - ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f); - } - } - - if (bHorizontal) { - fStepGray = (nEndGray - nStartGray) / rect.Width(); - - for (FX_FLOAT fx = rect.left + 0.5f; fx <= rect.right - 0.5f; fx += 1.0f) { - int32_t nGray = nStartGray + (int32_t)(fStepGray * (fx - rect.left)); - CPWL_Utils::DrawStrokeLine( - pDevice, pUser2Device, CFX_PointF(fx, rect.bottom), - CFX_PointF(fx, rect.top), - ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f); - } - } -} - -void CPWL_Utils::DrawBorder(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPWL_Color& color, - const CPWL_Color& crLeftTop, - const CPWL_Color& crRightBottom, - BorderStyle nStyle, - int32_t nTransparency) { - FX_FLOAT fLeft = rect.left; - FX_FLOAT fRight = rect.right; - FX_FLOAT fTop = rect.top; - FX_FLOAT fBottom = rect.bottom; - - if (fWidth > 0.0f) { - FX_FLOAT fHalfWidth = fWidth / 2.0f; - - switch (nStyle) { - default: - case BorderStyle::SOLID: { - CFX_PathData path; - path.AppendRect(fLeft, fBottom, fRight, fTop); - path.AppendRect(fLeft + fWidth, fBottom + fWidth, fRight - fWidth, - fTop - fWidth); - pDevice->DrawPath(&path, pUser2Device, nullptr, - color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE); - break; - } - case BorderStyle::DASH: { - CFX_PathData path; - path.AppendPoint( - CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f), - FXPT_TYPE::MoveTo, false); - path.AppendPoint( - CFX_PointF(fLeft + fWidth / 2.0f, fTop - fWidth / 2.0f), - FXPT_TYPE::LineTo, false); - path.AppendPoint( - CFX_PointF(fRight - fWidth / 2.0f, fTop - fWidth / 2.0f), - FXPT_TYPE::LineTo, false); - path.AppendPoint( - CFX_PointF(fRight - fWidth / 2.0f, fBottom + fWidth / 2.0f), - FXPT_TYPE::LineTo, false); - path.AppendPoint( - CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f), - FXPT_TYPE::LineTo, false); - - CFX_GraphStateData gsd; - gsd.SetDashCount(2); - gsd.m_DashArray[0] = 3.0f; - gsd.m_DashArray[1] = 3.0f; - gsd.m_DashPhase = 0; - - gsd.m_LineWidth = fWidth; - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, - color.ToFXColor(nTransparency), FXFILL_WINDING); - break; - } - case BorderStyle::BEVELED: - case BorderStyle::INSET: { - CFX_GraphStateData gsd; - gsd.m_LineWidth = fHalfWidth; - - CFX_PathData pathLT; - - pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), - FXPT_TYPE::MoveTo, false); - pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fTop - fHalfWidth), - FXPT_TYPE::LineTo, false); - pathLT.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), - FXPT_TYPE::LineTo, false); - pathLT.AppendPoint( - CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2), - FXPT_TYPE::LineTo, false); - pathLT.AppendPoint( - CFX_PointF(fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2), - FXPT_TYPE::LineTo, false); - pathLT.AppendPoint( - CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2), - FXPT_TYPE::LineTo, false); - pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), - FXPT_TYPE::LineTo, false); - - pDevice->DrawPath(&pathLT, pUser2Device, &gsd, - crLeftTop.ToFXColor(nTransparency), 0, - FXFILL_ALTERNATE); - - CFX_PathData pathRB; - pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), - FXPT_TYPE::MoveTo, false); - pathRB.AppendPoint( - CFX_PointF(fRight - fHalfWidth, fBottom + fHalfWidth), - FXPT_TYPE::LineTo, false); - pathRB.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), - FXPT_TYPE::LineTo, false); - pathRB.AppendPoint( - CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2), - FXPT_TYPE::LineTo, false); - pathRB.AppendPoint( - CFX_PointF(fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2), - FXPT_TYPE::LineTo, false); - pathRB.AppendPoint( - CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2), - FXPT_TYPE::LineTo, false); - pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), - FXPT_TYPE::LineTo, false); - - pDevice->DrawPath(&pathRB, pUser2Device, &gsd, - crRightBottom.ToFXColor(nTransparency), 0, - FXFILL_ALTERNATE); - - CFX_PathData path; - - path.AppendRect(fLeft, fBottom, fRight, fTop); - path.AppendRect(fLeft + fHalfWidth, fBottom + fHalfWidth, - fRight - fHalfWidth, fTop - fHalfWidth); - - pDevice->DrawPath(&path, pUser2Device, &gsd, - color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE); - break; - } - case BorderStyle::UNDERLINE: { - CFX_PathData path; - path.AppendPoint(CFX_PointF(fLeft, fBottom + fWidth / 2), - FXPT_TYPE::MoveTo, false); - path.AppendPoint(CFX_PointF(fRight, fBottom + fWidth / 2), - FXPT_TYPE::LineTo, false); - - CFX_GraphStateData gsd; - gsd.m_LineWidth = fWidth; - - pDevice->DrawPath(&path, pUser2Device, &gsd, 0, - color.ToFXColor(nTransparency), FXFILL_ALTERNATE); - break; - } - } - } -} - diff --git a/fpdfsdk/pdfwindow/PWL_Utils.h b/fpdfsdk/pdfwindow/PWL_Utils.h deleted file mode 100644 index a4ecc19ee5275a57118de7bcae13fd16d9607826..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Utils.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_UTILS_H_ -#define FPDFSDK_PDFWINDOW_PWL_UTILS_H_ - -#include "core/fpdfdoc/cpvt_wordrange.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" - -class CFX_Edit; -struct CPWL_Color; - -#define PWL_MAKEDWORD(low, high) \ - ((uint32_t)((uint16_t)(low) | (uint32_t)(((uint16_t)(high)) << 16))) - -// checkbox & radiobutton style -#define PCS_CHECK 0 -#define PCS_CIRCLE 1 -#define PCS_CROSS 2 -#define PCS_DIAMOND 3 -#define PCS_SQUARE 4 -#define PCS_STAR 5 - -// pushbutton layout style -#define PPBL_LABEL 0 -#define PPBL_ICON 1 -#define PPBL_ICONTOPLABELBOTTOM 2 -#define PPBL_LABELTOPICONBOTTOM 3 -#define PPBL_ICONLEFTLABELRIGHT 4 -#define PPBL_LABELLEFTICONRIGHT 5 -#define PPBL_LABELOVERICON 6 - -class CPWL_Utils { - public: - static CFX_FloatRect InflateRect(const CFX_FloatRect& rcRect, FX_FLOAT fSize); - static CFX_FloatRect DeflateRect(const CFX_FloatRect& rcRect, FX_FLOAT fSize); - - static CPVT_WordRange OverlapWordRange(const CPVT_WordRange& wr1, - const CPVT_WordRange& wr2); - static CFX_FloatRect GetCenterSquare(const CFX_FloatRect& rect); - - static CFX_FloatRect OffsetRect(const CFX_FloatRect& rect, - FX_FLOAT x, - FX_FLOAT y); - - static CFX_ByteString GetColorAppStream(const CPWL_Color& color, - const bool& bFillOrStroke = true); - static CFX_ByteString GetBorderAppStream(const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPWL_Color& color, - const CPWL_Color& crLeftTop, - const CPWL_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash); - static CFX_ByteString GetCircleBorderAppStream( - const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPWL_Color& color, - const CPWL_Color& crLeftTop, - const CPWL_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash); - static CFX_ByteString GetRectFillAppStream(const CFX_FloatRect& rect, - const CPWL_Color& color); - static CFX_ByteString GetCircleFillAppStream(const CFX_FloatRect& rect, - const CPWL_Color& color); - static CFX_ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox, - IPVT_FontMap* pFontMap, - CPDF_Stream* pIconStream, - CPDF_IconFit& IconFit, - const CFX_WideString& sLabel, - const CPWL_Color& crText, - FX_FLOAT fFontSize, - int32_t nLayOut); - static CFX_ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CPWL_Color& crText); - static CFX_ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CPWL_Color& crText); - static CFX_ByteString GetEditAppStream(CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange = nullptr, - bool bContinuous = true, - uint16_t SubWord = 0); - static CFX_ByteString GetEditSelAppStream( - CFX_Edit* pEdit, - const CFX_PointF& ptOffset, - const CPVT_WordRange* pRange = nullptr); - static CFX_ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox); - - static void DrawFillRect(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - const CPWL_Color& color, - int32_t nTransparency); - static void DrawFillRect(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - const FX_COLORREF& color); - static void DrawStrokeRect(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - const FX_COLORREF& color, - FX_FLOAT fWidth); - static void DrawStrokeLine(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_PointF& ptMoveTo, - const CFX_PointF& ptLineTo, - const FX_COLORREF& color, - FX_FLOAT fWidth); - static void DrawBorder(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPWL_Color& color, - const CPWL_Color& crLeftTop, - const CPWL_Color& crRightBottom, - BorderStyle nStyle, - int32_t nTransparency); - static void DrawFillArea(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - const CFX_PointF* pPts, - int32_t nCount, - const FX_COLORREF& color); - static void DrawShadow(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - bool bVertical, - bool bHorizontal, - CFX_FloatRect rect, - int32_t nTransparency, - int32_t nStartGray, - int32_t nEndGray); - - private: - static CFX_FloatRect ScaleRect(const CFX_FloatRect& rcRect, FX_FLOAT fScale); - - static CFX_ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText); - static CFX_ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText); - static CFX_ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText); - static CFX_ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText); - static CFX_ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText); - static CFX_ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox, - const CPWL_Color& crText); - - static CFX_ByteString GetAP_Check(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Circle(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Cross(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Diamond(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Square(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Star(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, - FX_FLOAT fRotate); -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_UTILS_H_ diff --git a/fpdfsdk/pdfwindow/PWL_Wnd.cpp b/fpdfsdk/pdfwindow/PWL_Wnd.cpp deleted file mode 100644 index 14024dd5d42efc4d0035453dde0dede70902ea7c..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Wnd.cpp +++ /dev/null @@ -1,915 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include - -#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h" -#include "fpdfsdk/pdfwindow/PWL_Utils.h" -#include "fpdfsdk/pdfwindow/PWL_Wnd.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -static std::map& GetPWLTimeMap() { - // Leak the object at shutdown. - static auto timeMap = new std::map; - return *timeMap; -} - -PWL_CREATEPARAM::PWL_CREATEPARAM() - : rcRectWnd(0, 0, 0, 0), - pSystemHandler(nullptr), - pFontMap(nullptr), - pProvider(nullptr), - pFocusHandler(nullptr), - dwFlags(0), - sBackgroundColor(), - pAttachedWidget(nullptr), - nBorderStyle(BorderStyle::SOLID), - dwBorderWidth(1), - sBorderColor(), - sTextColor(), - nTransparency(255), - fFontSize(PWL_DEFAULT_FONTSIZE), - sDash(3, 0, 0), - pAttachedData(nullptr), - pParentWnd(nullptr), - pMsgControl(nullptr), - eCursorType(FXCT_ARROW), - mtChild(1, 0, 0, 1, 0, 0) {} - -PWL_CREATEPARAM::PWL_CREATEPARAM(const PWL_CREATEPARAM& other) = default; - -CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached, - CFX_SystemHandler* pSystemHandler) - : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) { - ASSERT(m_pAttached); - ASSERT(m_pSystemHandler); -} - -CPWL_Timer::~CPWL_Timer() { - KillPWLTimer(); -} - -int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) { - if (m_nTimerID != 0) - KillPWLTimer(); - m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc); - - GetPWLTimeMap()[m_nTimerID] = this; - return m_nTimerID; -} - -void CPWL_Timer::KillPWLTimer() { - if (m_nTimerID == 0) - return; - - m_pSystemHandler->KillTimer(m_nTimerID); - GetPWLTimeMap().erase(m_nTimerID); - m_nTimerID = 0; -} - -void CPWL_Timer::TimerProc(int32_t idEvent) { - auto it = GetPWLTimeMap().find(idEvent); - if (it == GetPWLTimeMap().end()) - return; - - CPWL_Timer* pTimer = it->second; - if (pTimer->m_pAttached) - pTimer->m_pAttached->TimerProc(); -} - -CPWL_TimerHandler::CPWL_TimerHandler() {} - -CPWL_TimerHandler::~CPWL_TimerHandler() {} - -void CPWL_TimerHandler::BeginTimer(int32_t nElapse) { - if (!m_pTimer) - m_pTimer = pdfium::MakeUnique(this, GetSystemHandler()); - - m_pTimer->SetPWLTimer(nElapse); -} - -void CPWL_TimerHandler::EndTimer() { - if (m_pTimer) - m_pTimer->KillPWLTimer(); -} - -void CPWL_TimerHandler::TimerProc() {} - -class CPWL_MsgControl { - friend class CPWL_Wnd; - - public: - explicit CPWL_MsgControl(CPWL_Wnd* pWnd) { - m_pCreatedWnd = pWnd; - Default(); - } - - ~CPWL_MsgControl() { Default(); } - - void Default() { - m_aMousePath.clear(); - m_aKeyboardPath.clear(); - m_pMainMouseWnd = nullptr; - m_pMainKeyboardWnd = nullptr; - } - - bool IsWndCreated(const CPWL_Wnd* pWnd) const { - return m_pCreatedWnd == pWnd; - } - - bool IsMainCaptureMouse(const CPWL_Wnd* pWnd) const { - return pWnd == m_pMainMouseWnd; - } - - bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const { - return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd); - } - - bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const { - return pWnd == m_pMainKeyboardWnd; - } - - bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const { - return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd); - } - - void SetFocus(CPWL_Wnd* pWnd) { - m_aKeyboardPath.clear(); - if (pWnd) { - m_pMainKeyboardWnd = pWnd; - CPWL_Wnd* pParent = pWnd; - while (pParent) { - m_aKeyboardPath.push_back(pParent); - pParent = pParent->GetParentWindow(); - } - pWnd->OnSetFocus(); - } - } - - void KillFocus() { - if (!m_aKeyboardPath.empty()) - if (CPWL_Wnd* pWnd = m_aKeyboardPath[0]) - pWnd->OnKillFocus(); - - m_pMainKeyboardWnd = nullptr; - m_aKeyboardPath.clear(); - } - - void SetCapture(CPWL_Wnd* pWnd) { - m_aMousePath.clear(); - if (pWnd) { - m_pMainMouseWnd = pWnd; - CPWL_Wnd* pParent = pWnd; - while (pParent) { - m_aMousePath.push_back(pParent); - pParent = pParent->GetParentWindow(); - } - } - } - - void ReleaseCapture() { - m_pMainMouseWnd = nullptr; - m_aMousePath.clear(); - } - - private: - std::vector m_aMousePath; - std::vector m_aKeyboardPath; - CPWL_Wnd* m_pCreatedWnd; - CPWL_Wnd* m_pMainMouseWnd; - CPWL_Wnd* m_pMainKeyboardWnd; -}; - -CPWL_Wnd::CPWL_Wnd() - : m_pVScrollBar(nullptr), - m_rcWindow(), - m_rcClip(), - m_bCreated(false), - m_bVisible(false), - m_bNotifying(false), - m_bEnabled(true) {} - -CPWL_Wnd::~CPWL_Wnd() { - ASSERT(m_bCreated == false); -} - -CFX_ByteString CPWL_Wnd::GetClassName() const { - return "CPWL_Wnd"; -} - -void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) { - if (!IsValid()) { - m_sPrivateParam = cp; - - OnCreate(m_sPrivateParam); - - m_sPrivateParam.rcRectWnd.Normalize(); - m_rcWindow = m_sPrivateParam.rcRectWnd; - m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f); - - CreateMsgControl(); - - if (m_sPrivateParam.pParentWnd) - m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD); - - PWL_CREATEPARAM ccp = m_sPrivateParam; - - ccp.dwFlags &= 0xFFFF0000L; // remove sub styles - ccp.mtChild = CFX_Matrix(1, 0, 0, 1, 0, 0); - - CreateScrollBar(ccp); - CreateChildWnd(ccp); - - m_bVisible = HasFlag(PWS_VISIBLE); - - OnCreated(); - - RePosChildWnd(); - m_bCreated = true; - } -} - -void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {} - -void CPWL_Wnd::OnCreated() {} - -void CPWL_Wnd::OnDestroy() {} - -void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) { - if (m_sPrivateParam.pFocusHandler == handler) - m_sPrivateParam.pFocusHandler = nullptr; -} - -void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) { - if (m_sPrivateParam.pProvider.Get() == provider) - m_sPrivateParam.pProvider.Reset(); -} - -void CPWL_Wnd::Destroy() { - KillFocus(); - OnDestroy(); - if (m_bCreated) { - for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) { - if (CPWL_Wnd* pChild = *it) { - *it = nullptr; - pChild->Destroy(); - delete pChild; - } - } - if (m_sPrivateParam.pParentWnd) - m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD); - - m_bCreated = false; - } - DestroyMsgControl(); - m_sPrivateParam.Reset(); - m_Children.clear(); - m_pVScrollBar = nullptr; -} - -void CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) { - if (IsValid()) { - CFX_FloatRect rcOld = GetWindowRect(); - - m_rcWindow = rcNew; - m_rcWindow.Normalize(); - - if (rcOld.left != rcNew.left || rcOld.right != rcNew.right || - rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) { - if (bReset) { - RePosChildWnd(); - } - } - if (bRefresh) { - InvalidateRectMove(rcOld, rcNew); - } - - m_sPrivateParam.rcRectWnd = m_rcWindow; - } -} - -void CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld, - const CFX_FloatRect& rcNew) { - CFX_FloatRect rcUnion = rcOld; - rcUnion.Union(rcNew); - - InvalidateRect(&rcUnion); -} - -void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) { - if (IsValid() && IsVisible()) { - GetThisAppearanceStream(sAppStream); - GetChildAppearanceStream(sAppStream); - } -} - -// if don't set,Get default apperance stream -void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) { - CFX_FloatRect rectWnd = GetWindowRect(); - if (!rectWnd.IsEmpty()) { - CFX_ByteTextBuf sThis; - - if (HasFlag(PWS_BACKGROUND)) - sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor()); - - if (HasFlag(PWS_BORDER)) { - sThis << CPWL_Utils::GetBorderAppStream( - rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(), - GetBorderLeftTopColor(GetBorderStyle()), - GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(), - GetBorderDash()); - } - - sAppStream << sThis; - } -} - -void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) { - for (CPWL_Wnd* pChild : m_Children) { - if (pChild) - pChild->GetAppearanceStream(sAppStream); - } -} - -void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - if (IsValid() && IsVisible()) { - DrawThisAppearance(pDevice, pUser2Device); - DrawChildAppearance(pDevice, pUser2Device); - } -} - -void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CFX_FloatRect rectWnd = GetWindowRect(); - if (!rectWnd.IsEmpty()) { - if (HasFlag(PWS_BACKGROUND)) { - CFX_FloatRect rcClient = CPWL_Utils::DeflateRect( - rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth())); - CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, - GetBackgroundColor(), GetTransparency()); - } - - if (HasFlag(PWS_BORDER)) - CPWL_Utils::DrawBorder(pDevice, pUser2Device, rectWnd, - (FX_FLOAT)GetBorderWidth(), GetBorderColor(), - GetBorderLeftTopColor(GetBorderStyle()), - GetBorderRightBottomColor(GetBorderStyle()), - GetBorderStyle(), GetTransparency()); - } -} - -void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - for (CPWL_Wnd* pChild : m_Children) { - if (!pChild) - continue; - - CFX_Matrix mt = pChild->GetChildMatrix(); - if (mt.IsIdentity()) { - pChild->DrawAppearance(pDevice, pUser2Device); - } else { - mt.Concat(*pUser2Device); - pChild->DrawAppearance(pDevice, &mt); - } - } -} - -void CPWL_Wnd::InvalidateRect(CFX_FloatRect* pRect) { - if (IsValid()) { - CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect(); - - if (!HasFlag(PWS_NOREFRESHCLIP)) { - CFX_FloatRect rcClip = GetClipRect(); - if (!rcClip.IsEmpty()) { - rcRefresh.Intersect(rcClip); - } - } - - FX_RECT rcWin = PWLtoWnd(rcRefresh); - rcWin.left -= PWL_INVALIDATE_INFLATE; - rcWin.top -= PWL_INVALIDATE_INFLATE; - rcWin.right += PWL_INVALIDATE_INFLATE; - rcWin.bottom += PWL_INVALIDATE_INFLATE; - - if (CFX_SystemHandler* pSH = GetSystemHandler()) { - if (CPDFSDK_Widget* widget = static_cast( - m_sPrivateParam.pAttachedWidget.Get())) { - pSH->InvalidateRect(widget, rcWin); - } - } - } -} - -#define PWL_IMPLEMENT_KEY_METHOD(key_method_name) \ - bool CPWL_Wnd::key_method_name(uint16_t nChar, uint32_t nFlag) { \ - if (!IsValid() || !IsVisible() || !IsEnabled()) \ - return false; \ - if (!IsWndCaptureKeyboard(this)) \ - return false; \ - for (const auto& pChild : m_Children) { \ - if (pChild && IsWndCaptureKeyboard(pChild)) \ - return pChild->key_method_name(nChar, nFlag); \ - } \ - return false; \ - } - -PWL_IMPLEMENT_KEY_METHOD(OnKeyDown) -PWL_IMPLEMENT_KEY_METHOD(OnChar) -#undef PWL_IMPLEMENT_KEY_METHOD - -#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name) \ - bool CPWL_Wnd::mouse_method_name(const CFX_PointF& point, uint32_t nFlag) { \ - if (!IsValid() || !IsVisible() || !IsEnabled()) \ - return false; \ - if (IsWndCaptureMouse(this)) { \ - for (const auto& pChild : m_Children) { \ - if (pChild && IsWndCaptureMouse(pChild)) { \ - return pChild->mouse_method_name(pChild->ParentToChild(point), \ - nFlag); \ - } \ - } \ - SetCursor(); \ - return false; \ - } \ - for (const auto& pChild : m_Children) { \ - if (pChild && pChild->WndHitTest(pChild->ParentToChild(point))) { \ - return pChild->mouse_method_name(pChild->ParentToChild(point), nFlag); \ - } \ - } \ - if (WndHitTest(point)) \ - SetCursor(); \ - return false; \ - } - -PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk) -PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown) -PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp) -PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown) -PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp) -PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove) -#undef PWL_IMPLEMENT_MOUSE_METHOD - -bool CPWL_Wnd::OnMouseWheel(short zDelta, - const CFX_PointF& point, - uint32_t nFlag) { - if (!IsValid() || !IsVisible() || !IsEnabled()) - return false; - - SetCursor(); - if (!IsWndCaptureKeyboard(this)) - return false; - - for (const auto& pChild : m_Children) { - if (pChild && IsWndCaptureKeyboard(pChild)) - return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point), nFlag); - } - return false; -} - -void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) { - m_Children.push_back(pWnd); -} - -void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) { - for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) { - if (*it && *it == pWnd) { - m_Children.erase(std::next(it).base()); - break; - } - } -} - -void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam, - intptr_t lParam) { - switch (msg) { - case PNM_ADDCHILD: - AddChild(pWnd); - break; - case PNM_REMOVECHILD: - RemoveChild(pWnd); - break; - default: - break; - } -} - -bool CPWL_Wnd::IsValid() const { - return m_bCreated; -} - -const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const { - return m_sPrivateParam; -} - -CPWL_Wnd* CPWL_Wnd::GetParentWindow() const { - return m_sPrivateParam.pParentWnd; -} - -CFX_FloatRect CPWL_Wnd::GetWindowRect() const { - return m_rcWindow; -} - -CFX_FloatRect CPWL_Wnd::GetClientRect() const { - CFX_FloatRect rcWindow = GetWindowRect(); - CFX_FloatRect rcClient = CPWL_Utils::DeflateRect( - rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth())); - if (CPWL_ScrollBar* pVSB = GetVScrollBar()) - rcClient.right -= pVSB->GetScrollBarWidth(); - - rcClient.Normalize(); - return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect(); -} - -CFX_PointF CPWL_Wnd::GetCenterPoint() const { - CFX_FloatRect rcClient = GetClientRect(); - return CFX_PointF((rcClient.left + rcClient.right) * 0.5f, - (rcClient.top + rcClient.bottom) * 0.5f); -} - -bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const { - return (m_sPrivateParam.dwFlags & dwFlags) != 0; -} - -void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) { - m_sPrivateParam.dwFlags &= ~dwFlags; -} - -void CPWL_Wnd::AddFlag(uint32_t dwFlags) { - m_sPrivateParam.dwFlags |= dwFlags; -} - -CPWL_Color CPWL_Wnd::GetBackgroundColor() const { - return m_sPrivateParam.sBackgroundColor; -} - -void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) { - m_sPrivateParam.sBackgroundColor = color; -} - -CPWL_Color CPWL_Wnd::GetTextColor() const { - return m_sPrivateParam.sTextColor; -} - -BorderStyle CPWL_Wnd::GetBorderStyle() const { - return m_sPrivateParam.nBorderStyle; -} - -void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) { - if (HasFlag(PWS_BORDER)) - m_sPrivateParam.nBorderStyle = nBorderStyle; -} - -int32_t CPWL_Wnd::GetBorderWidth() const { - if (HasFlag(PWS_BORDER)) - return m_sPrivateParam.dwBorderWidth; - - return 0; -} - -int32_t CPWL_Wnd::GetInnerBorderWidth() const { - return 0; -} - -CPWL_Color CPWL_Wnd::GetBorderColor() const { - if (HasFlag(PWS_BORDER)) - return m_sPrivateParam.sBorderColor; - - return CPWL_Color(); -} - -const CPWL_Dash& CPWL_Wnd::GetBorderDash() const { - return m_sPrivateParam.sDash; -} - -void* CPWL_Wnd::GetAttachedData() const { - return m_sPrivateParam.pAttachedData; -} - -CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const { - if (HasFlag(PWS_VSCROLL)) - return m_pVScrollBar; - - return nullptr; -} - -void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) { - CreateVScrollBar(cp); -} - -void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) { - if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) { - PWL_CREATEPARAM scp = cp; - - // flags - scp.dwFlags = - PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP; - - scp.pParentWnd = this; - scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR; - scp.eCursorType = FXCT_ARROW; - scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY; - - m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL); - m_pVScrollBar->Create(scp); - } -} - -void CPWL_Wnd::SetCapture() { - if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) - pMsgCtrl->SetCapture(this); -} - -void CPWL_Wnd::ReleaseCapture() { - for (const auto& pChild : m_Children) { - if (pChild) - pChild->ReleaseCapture(); - } - if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) - pMsgCtrl->ReleaseCapture(); -} - -void CPWL_Wnd::SetFocus() { - if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) { - if (!pMsgCtrl->IsMainCaptureKeyboard(this)) - pMsgCtrl->KillFocus(); - pMsgCtrl->SetFocus(this); - } -} - -void CPWL_Wnd::KillFocus() { - if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) { - if (pMsgCtrl->IsWndCaptureKeyboard(this)) - pMsgCtrl->KillFocus(); - } -} - -void CPWL_Wnd::OnSetFocus() {} - -void CPWL_Wnd::OnKillFocus() {} - -bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const { - return IsValid() && IsVisible() && GetWindowRect().Contains(point); -} - -bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const { - return IsValid() && IsVisible() && GetClientRect().Contains(point); -} - -const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const { - if (m_sPrivateParam.pParentWnd) - return m_sPrivateParam.pParentWnd->GetRootWnd(); - - return this; -} - -void CPWL_Wnd::SetVisible(bool bVisible) { - if (!IsValid()) - return; - - for (const auto& pChild : m_Children) { - if (pChild) - pChild->SetVisible(bVisible); - } - if (bVisible != m_bVisible) { - m_bVisible = bVisible; - RePosChildWnd(); - InvalidateRect(); - } -} - -void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) { - m_rcClip = rect; - m_rcClip.Normalize(); -} - -const CFX_FloatRect& CPWL_Wnd::GetClipRect() const { - return m_rcClip; -} - -bool CPWL_Wnd::IsReadOnly() const { - return HasFlag(PWS_READONLY); -} - -void CPWL_Wnd::RePosChildWnd() { - CFX_FloatRect rcContent = CPWL_Utils::DeflateRect( - GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth())); - - CPWL_ScrollBar* pVSB = GetVScrollBar(); - - CFX_FloatRect rcVScroll = - CFX_FloatRect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom, - rcContent.right - 1.0f, rcContent.top); - - if (pVSB) - pVSB->Move(rcVScroll, true, false); -} - -void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {} - -void CPWL_Wnd::SetCursor() { - if (IsValid()) { - if (CFX_SystemHandler* pSH = GetSystemHandler()) { - int32_t nCursorType = GetCreationParam().eCursorType; - pSH->SetCursor(nCursorType); - } - } -} - -void CPWL_Wnd::CreateMsgControl() { - if (!m_sPrivateParam.pMsgControl) - m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this); -} - -void CPWL_Wnd::DestroyMsgControl() { - if (CPWL_MsgControl* pMsgControl = GetMsgControl()) - if (pMsgControl->IsWndCreated(this)) - delete pMsgControl; -} - -CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const { - return m_sPrivateParam.pMsgControl; -} - -bool CPWL_Wnd::IsCaptureMouse() const { - return IsWndCaptureMouse(this); -} - -bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const { - if (CPWL_MsgControl* pCtrl = GetMsgControl()) - return pCtrl->IsWndCaptureMouse(pWnd); - - return false; -} - -bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const { - if (CPWL_MsgControl* pCtrl = GetMsgControl()) - return pCtrl->IsWndCaptureKeyboard(pWnd); - - return false; -} - -bool CPWL_Wnd::IsFocused() const { - if (CPWL_MsgControl* pCtrl = GetMsgControl()) - return pCtrl->IsMainCaptureKeyboard(this); - - return false; -} - -CFX_FloatRect CPWL_Wnd::GetFocusRect() const { - return CPWL_Utils::InflateRect(GetWindowRect(), 1); -} - -FX_FLOAT CPWL_Wnd::GetFontSize() const { - return m_sPrivateParam.fFontSize; -} - -void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) { - m_sPrivateParam.fFontSize = fFontSize; -} - -CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const { - return m_sPrivateParam.pSystemHandler; -} - -IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const { - return m_sPrivateParam.pFocusHandler; -} - -IPWL_Provider* CPWL_Wnd::GetProvider() const { - return m_sPrivateParam.pProvider.Get(); -} - -IPVT_FontMap* CPWL_Wnd::GetFontMap() const { - return m_sPrivateParam.pFontMap; -} - -CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const { - switch (nBorderStyle) { - case BorderStyle::BEVELED: - return CPWL_Color(COLORTYPE_GRAY, 1); - case BorderStyle::INSET: - return CPWL_Color(COLORTYPE_GRAY, 0.5f); - default: - return CPWL_Color(); - } -} - -CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const { - switch (nBorderStyle) { - case BorderStyle::BEVELED: - return GetBackgroundColor() / 2.0f; - case BorderStyle::INSET: - return CPWL_Color(COLORTYPE_GRAY, 0.75f); - default: - return CPWL_Color(); - } -} - -int32_t CPWL_Wnd::GetTransparency() { - return m_sPrivateParam.nTransparency; -} - -void CPWL_Wnd::SetTransparency(int32_t nTransparency) { - for (const auto& pChild : m_Children) { - if (pChild) - pChild->SetTransparency(nTransparency); - } - m_sPrivateParam.nTransparency = nTransparency; -} - -CFX_Matrix CPWL_Wnd::GetWindowMatrix() const { - CFX_Matrix mt = GetChildToRoot(); - if (IPWL_Provider* pProvider = GetProvider()) - mt.Concat(pProvider->GetWindowMatrix(GetAttachedData())); - return mt; -} - -FX_RECT CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const { - CFX_FloatRect rcTemp = rect; - CFX_Matrix mt = GetWindowMatrix(); - mt.TransformRect(rcTemp); - return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5), - (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5)); -} - -CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const { - CFX_Matrix mt = GetChildMatrix(); - if (mt.IsIdentity()) - return point; - - mt.SetReverse(mt); - return mt.Transform(point); -} - -CFX_FloatRect CPWL_Wnd::ParentToChild(const CFX_FloatRect& rect) const { - CFX_Matrix mt = GetChildMatrix(); - if (mt.IsIdentity()) - return rect; - - mt.SetReverse(mt); - CFX_FloatRect rc = rect; - mt.TransformRect(rc); - return rc; -} - -CFX_Matrix CPWL_Wnd::GetChildToRoot() const { - CFX_Matrix mt(1, 0, 0, 1, 0, 0); - if (HasFlag(PWS_CHILD)) { - const CPWL_Wnd* pParent = this; - while (pParent) { - mt.Concat(pParent->GetChildMatrix()); - pParent = pParent->GetParentWindow(); - } - } - return mt; -} - -CFX_Matrix CPWL_Wnd::GetChildMatrix() const { - if (HasFlag(PWS_CHILD)) - return m_sPrivateParam.mtChild; - - return CFX_Matrix(1, 0, 0, 1, 0, 0); -} - -void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) { - m_sPrivateParam.mtChild = mt; -} - -const CPWL_Wnd* CPWL_Wnd::GetFocused() const { - CPWL_MsgControl* pMsgCtrl = GetMsgControl(); - return pMsgCtrl ? pMsgCtrl->m_pMainKeyboardWnd : nullptr; -} - -void CPWL_Wnd::EnableWindow(bool bEnable) { - if (m_bEnabled == bEnable) - return; - - for (const auto& pChild : m_Children) { - if (pChild) - pChild->EnableWindow(bEnable); - } - m_bEnabled = bEnable; -} - -bool CPWL_Wnd::IsCTRLpressed(uint32_t nFlag) const { - CFX_SystemHandler* pSystemHandler = GetSystemHandler(); - return pSystemHandler && pSystemHandler->IsCTRLKeyDown(nFlag); -} - -bool CPWL_Wnd::IsSHIFTpressed(uint32_t nFlag) const { - CFX_SystemHandler* pSystemHandler = GetSystemHandler(); - return pSystemHandler && pSystemHandler->IsSHIFTKeyDown(nFlag); -} - -bool CPWL_Wnd::IsALTpressed(uint32_t nFlag) const { - CFX_SystemHandler* pSystemHandler = GetSystemHandler(); - return pSystemHandler && pSystemHandler->IsALTKeyDown(nFlag); -} diff --git a/fpdfsdk/pdfwindow/PWL_Wnd.h b/fpdfsdk/pdfwindow/PWL_Wnd.h deleted file mode 100644 index 55836d43a2ec944b95d0303b8907a093e5529650..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/PWL_Wnd.h +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_PWL_WND_H_ -#define FPDFSDK_PDFWINDOW_PWL_WND_H_ - -#include -#include - -#include "core/fpdfdoc/cpdf_formcontrol.h" -#include "core/fxcrt/cfx_observable.h" -#include "core/fxcrt/fx_basic.h" -#include "fpdfsdk/cfx_systemhandler.h" -#include "fpdfsdk/cpdfsdk_widget.h" -#include "fpdfsdk/pdfwindow/cpwl_color.h" - -class CPWL_MsgControl; -class CPWL_ScrollBar; -class CPWL_Timer; -class CPWL_TimerHandler; -class CPWL_Wnd; -class CFX_SystemHandler; -class IPVT_FontMap; -class IPWL_Provider; - -// window styles -#define PWS_CHILD 0x80000000L -#define PWS_BORDER 0x40000000L -#define PWS_BACKGROUND 0x20000000L -#define PWS_HSCROLL 0x10000000L -#define PWS_VSCROLL 0x08000000L -#define PWS_VISIBLE 0x04000000L -#define PWS_DISABLE 0x02000000L -#define PWS_READONLY 0x01000000L -#define PWS_AUTOFONTSIZE 0x00800000L -#define PWS_AUTOTRANSPARENT 0x00400000L -#define PWS_NOREFRESHCLIP 0x00200000L - -// edit and label styles -#define PES_MULTILINE 0x0001L -#define PES_PASSWORD 0x0002L -#define PES_LEFT 0x0004L -#define PES_RIGHT 0x0008L -#define PES_MIDDLE 0x0010L -#define PES_TOP 0x0020L -#define PES_BOTTOM 0x0040L -#define PES_CENTER 0x0080L -#define PES_CHARARRAY 0x0100L -#define PES_AUTOSCROLL 0x0200L -#define PES_AUTORETURN 0x0400L -#define PES_UNDO 0x0800L -#define PES_RICH 0x1000L -#define PES_SPELLCHECK 0x2000L -#define PES_TEXTOVERFLOW 0x4000L -#define PES_NOREAD 0x8000L - -// listbox styles -#define PLBS_MULTIPLESEL 0x0001L -#define PLBS_HOVERSEL 0x0008L - -// combobox styles -#define PCBS_ALLOWCUSTOMTEXT 0x0001L - -// richedit styles -#define PRES_MULTILINE 0x0001L -#define PRES_AUTORETURN 0x0002L -#define PRES_AUTOSCROLL 0x0004L -#define PRES_UNDO 0x0100L -#define PRES_MULTIPAGES 0x0200L -#define PRES_TEXTOVERFLOW 0x0400L - -// notification messages -#define PNM_ADDCHILD 0x00000000L -#define PNM_REMOVECHILD 0x00000001L -#define PNM_SETSCROLLINFO 0x00000002L -#define PNM_SETSCROLLPOS 0x00000003L -#define PNM_SCROLLWINDOW 0x00000004L -#define PNM_LBUTTONDOWN 0x00000005L -#define PNM_LBUTTONUP 0x00000006L -#define PNM_MOUSEMOVE 0x00000007L -#define PNM_NOTERESET 0x00000008L -#define PNM_SETCARETINFO 0x00000009L -#define PNM_SELCHANGED 0x0000000AL -#define PNM_NOTEEDITCHANGED 0x0000000BL - -#define PWL_CLASSNAME_EDIT "CPWL_Edit" - -struct CPWL_Dash { - CPWL_Dash() : nDash(0), nGap(0), nPhase(0) {} - CPWL_Dash(int32_t dash, int32_t gap, int32_t phase) - : nDash(dash), nGap(gap), nPhase(phase) {} - - void Reset() { - nDash = 0; - nGap = 0; - nPhase = 0; - } - - int32_t nDash; - int32_t nGap; - int32_t nPhase; -}; - -inline bool operator==(const CPWL_Color& c1, const CPWL_Color& c2) { - return c1.nColorType == c2.nColorType && c1.fColor1 - c2.fColor1 < 0.0001 && - c1.fColor1 - c2.fColor1 > -0.0001 && - c1.fColor2 - c2.fColor2 < 0.0001 && - c1.fColor2 - c2.fColor2 > -0.0001 && - c1.fColor3 - c2.fColor3 < 0.0001 && - c1.fColor3 - c2.fColor3 > -0.0001 && - c1.fColor4 - c2.fColor4 < 0.0001 && c1.fColor4 - c2.fColor4 > -0.0001; -} - -inline bool operator!=(const CPWL_Color& c1, const CPWL_Color& c2) { - return !(c1 == c2); -} - -#define PWL_SCROLLBAR_WIDTH 12.0f -#define PWL_SCROLLBAR_BUTTON_WIDTH 9.0f -#define PWL_SCROLLBAR_POSBUTTON_MINWIDTH 2.0f -#define PWL_SCROLLBAR_TRANSPARENCY 150 -#define PWL_SCROLLBAR_BKCOLOR \ - CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f) -#define PWL_DEFAULT_SELTEXTCOLOR CPWL_Color(COLORTYPE_RGB, 1, 1, 1) -#define PWL_DEFAULT_SELBACKCOLOR \ - CPWL_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f) -#define PWL_DEFAULT_BACKCOLOR PWL_DEFAULT_SELTEXTCOLOR -#define PWL_DEFAULT_TEXTCOLOR CPWL_Color(COLORTYPE_RGB, 0, 0, 0) -#define PWL_DEFAULT_FONTSIZE 9.0f -#define PWL_DEFAULT_BLACKCOLOR CPWL_Color(COLORTYPE_GRAY, 0) -#define PWL_DEFAULT_WHITECOLOR CPWL_Color(COLORTYPE_GRAY, 1) -#define PWL_DEFAULT_HEAVYGRAYCOLOR CPWL_Color(COLORTYPE_GRAY, 0.50) -#define PWL_DEFAULT_LIGHTGRAYCOLOR CPWL_Color(COLORTYPE_GRAY, 0.75) -#define PWL_TRIANGLE_HALFLEN 2.0f -#define PWL_CBBUTTON_TRIANGLE_HALFLEN 3.0f -#define PWL_INVALIDATE_INFLATE 2 - -class IPWL_Provider : public CFX_Observable { - public: - virtual ~IPWL_Provider() {} - - // get a matrix which map user space to CWnd client space - virtual CFX_Matrix GetWindowMatrix(void* pAttachedData) = 0; - - /* - 0 L"&Undo\tCtrl+Z" - 1 L"&Redo\tCtrl+Shift+Z" - 2 L"Cu&t\tCtrl+X" - 3 L"&Copy\tCtrl+C" - 4 L"&Paste\tCtrl+V" - 5 L"&Delete" - 6 L"&Select All\tCtrl+A" - */ - virtual CFX_WideString LoadPopupMenuString(int32_t nIndex) = 0; -}; - -class IPWL_FocusHandler { - public: - virtual ~IPWL_FocusHandler() {} - virtual void OnSetFocus(CPWL_Wnd* pWnd) = 0; -}; - -struct PWL_CREATEPARAM { - public: - PWL_CREATEPARAM(); - PWL_CREATEPARAM(const PWL_CREATEPARAM& other); - - void Reset() { - rcRectWnd.Reset(); - pSystemHandler = nullptr; - pFontMap = nullptr; - pProvider.Reset(); - pFocusHandler = nullptr; - dwFlags = 0; - sBackgroundColor.Reset(); - pAttachedWidget.Reset(); - nBorderStyle = BorderStyle::SOLID; - dwBorderWidth = 0; - sBorderColor.Reset(); - sTextColor.Reset(); - nTransparency = 0; - fFontSize = 0.0f; - sDash.Reset(); - pAttachedData = nullptr; - pParentWnd = nullptr; - pMsgControl = nullptr; - eCursorType = 0; - mtChild.SetIdentity(); - } - - CFX_FloatRect rcRectWnd; // required - CFX_SystemHandler* pSystemHandler; // required - IPVT_FontMap* pFontMap; // required - IPWL_Provider::ObservedPtr pProvider; // required - IPWL_FocusHandler* pFocusHandler; // optional - uint32_t dwFlags; // optional - CPWL_Color sBackgroundColor; // optional - CPDFSDK_Widget::ObservedPtr pAttachedWidget; // required - BorderStyle nBorderStyle; // optional - int32_t dwBorderWidth; // optional - CPWL_Color sBorderColor; // optional - CPWL_Color sTextColor; // optional - int32_t nTransparency; // optional - FX_FLOAT fFontSize; // optional - CPWL_Dash sDash; // optional - void* pAttachedData; // optional - CPWL_Wnd* pParentWnd; // ignore - CPWL_MsgControl* pMsgControl; // ignore - int32_t eCursorType; // ignore - CFX_Matrix mtChild; // ignore -}; - -class CPWL_Timer { - public: - CPWL_Timer(CPWL_TimerHandler* pAttached, CFX_SystemHandler* pSystemHandler); - virtual ~CPWL_Timer(); - - int32_t SetPWLTimer(int32_t nElapse); - void KillPWLTimer(); - static void TimerProc(int32_t idEvent); - - private: - int32_t m_nTimerID; - CPWL_TimerHandler* m_pAttached; - CFX_SystemHandler* m_pSystemHandler; -}; - -class CPWL_TimerHandler { - public: - CPWL_TimerHandler(); - virtual ~CPWL_TimerHandler(); - - void BeginTimer(int32_t nElapse); - void EndTimer(); - virtual void TimerProc(); - virtual CFX_SystemHandler* GetSystemHandler() const = 0; - - private: - std::unique_ptr m_pTimer; -}; - -class CPWL_Wnd : public CPWL_TimerHandler { - public: - CPWL_Wnd(); - ~CPWL_Wnd() override; - - virtual CFX_ByteString GetClassName() const; - virtual void InvalidateRect(CFX_FloatRect* pRect = nullptr); - - virtual bool OnKeyDown(uint16_t nChar, uint32_t nFlag); - virtual bool OnChar(uint16_t nChar, uint32_t nFlag); - virtual bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag); - virtual bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag); - virtual bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag); - virtual bool OnRButtonDown(const CFX_PointF& point, uint32_t nFlag); - virtual bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag); - virtual bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag); - virtual bool OnMouseWheel(short zDelta, - const CFX_PointF& point, - uint32_t nFlag); - virtual void OnNotify(CPWL_Wnd* pWnd, - uint32_t msg, - intptr_t wParam = 0, - intptr_t lParam = 0); - virtual void SetFocus(); - virtual void KillFocus(); - virtual void SetCursor(); - virtual void SetVisible(bool bVisible); - virtual void SetFontSize(FX_FLOAT fFontSize); - virtual FX_FLOAT GetFontSize() const; - - virtual CFX_FloatRect GetFocusRect() const; - virtual CFX_FloatRect GetClientRect() const; - - void InvalidateFocusHandler(IPWL_FocusHandler* handler); - void InvalidateProvider(IPWL_Provider* provider); - void Create(const PWL_CREATEPARAM& cp); - void Destroy(); - void Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh); - - void SetCapture(); - void ReleaseCapture(); - - void DrawAppearance(CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device); - - CPWL_Color GetBackgroundColor() const; - void SetBackgroundColor(const CPWL_Color& color); - CPWL_Color GetBorderColor() const; - CPWL_Color GetTextColor() const; - void SetTextColor(const CPWL_Color& color); - CPWL_Color GetBorderLeftTopColor(BorderStyle nBorderStyle) const; - CPWL_Color GetBorderRightBottomColor(BorderStyle nBorderStyle) const; - - void SetBorderStyle(BorderStyle eBorderStyle); - BorderStyle GetBorderStyle() const; - const CPWL_Dash& GetBorderDash() const; - - int32_t GetBorderWidth() const; - int32_t GetInnerBorderWidth() const; - CFX_FloatRect GetWindowRect() const; - CFX_PointF GetCenterPoint() const; - - bool IsVisible() const { return m_bVisible; } - bool HasFlag(uint32_t dwFlags) const; - void AddFlag(uint32_t dwFlags); - void RemoveFlag(uint32_t dwFlags); - - void SetClipRect(const CFX_FloatRect& rect); - const CFX_FloatRect& GetClipRect() const; - - CPWL_Wnd* GetParentWindow() const; - void* GetAttachedData() const; - - bool WndHitTest(const CFX_PointF& point) const; - bool ClientHitTest(const CFX_PointF& point) const; - bool IsCaptureMouse() const; - - void EnableWindow(bool bEnable); - bool IsEnabled() const { return m_bEnabled; } - const CPWL_Wnd* GetFocused() const; - bool IsFocused() const; - bool IsReadOnly() const; - CPWL_ScrollBar* GetVScrollBar() const; - - IPVT_FontMap* GetFontMap() const; - IPWL_Provider* GetProvider() const; - IPWL_FocusHandler* GetFocusHandler() const; - - int32_t GetTransparency(); - void SetTransparency(int32_t nTransparency); - - CFX_Matrix GetChildToRoot() const; - CFX_Matrix GetChildMatrix() const; - void SetChildMatrix(const CFX_Matrix& mt); - CFX_Matrix GetWindowMatrix() const; - - protected: - friend class CPWL_MsgControl; - - // CPWL_TimerHandler - CFX_SystemHandler* GetSystemHandler() const override; - - virtual void CreateChildWnd(const PWL_CREATEPARAM& cp); - virtual void RePosChildWnd(); - virtual void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream); - - virtual void DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device); - - virtual void OnCreate(PWL_CREATEPARAM& cp); - virtual void OnCreated(); - virtual void OnDestroy(); - - virtual void OnSetFocus(); - virtual void OnKillFocus(); - - void GetAppearanceStream(CFX_ByteTextBuf& sAppStream); - void SetNotifyFlag(bool bNotifying = true) { m_bNotifying = bNotifying; } - - bool IsValid() const; - const PWL_CREATEPARAM& GetCreationParam() const; - bool IsNotifying() const { return m_bNotifying; } - - void InvalidateRectMove(const CFX_FloatRect& rcOld, - const CFX_FloatRect& rcNew); - - bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const; - bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const; - const CPWL_Wnd* GetRootWnd() const; - - bool IsCTRLpressed(uint32_t nFlag) const; - bool IsSHIFTpressed(uint32_t nFlag) const; - bool IsALTpressed(uint32_t nFlag) const; - - private: - CFX_PointF ParentToChild(const CFX_PointF& point) const; - CFX_FloatRect ParentToChild(const CFX_FloatRect& rect) const; - - void GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream); - void DrawChildAppearance(CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device); - - FX_RECT PWLtoWnd(const CFX_FloatRect& rect) const; - - void AddChild(CPWL_Wnd* pWnd); - void RemoveChild(CPWL_Wnd* pWnd); - - void CreateScrollBar(const PWL_CREATEPARAM& cp); - void CreateVScrollBar(const PWL_CREATEPARAM& cp); - - void AdjustStyle(); - void CreateMsgControl(); - void DestroyMsgControl(); - - CPWL_MsgControl* GetMsgControl() const; - - std::vector m_Children; - PWL_CREATEPARAM m_sPrivateParam; - CPWL_ScrollBar* m_pVScrollBar; - CFX_FloatRect m_rcWindow; - CFX_FloatRect m_rcClip; - bool m_bCreated; - bool m_bVisible; - bool m_bNotifying; - bool m_bEnabled; -}; - -#endif // FPDFSDK_PDFWINDOW_PWL_WND_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_color.cpp b/fpdfsdk/pdfwindow/cpwl_color.cpp deleted file mode 100644 index 9c9ca3eff02b9ea6086c17c1727f2c858efedbeb..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/cpwl_color.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "fpdfsdk/pdfwindow/cpwl_color.h" - -#include - -namespace { - -bool InRange(FX_FLOAT comp) { - return comp >= 0.0f && comp <= 1.0f; -} - -CPWL_Color ConvertCMYK2GRAY(FX_FLOAT dC, - FX_FLOAT dM, - FX_FLOAT dY, - FX_FLOAT dK) { - if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK)) - return CPWL_Color(COLORTYPE_GRAY); - return CPWL_Color( - COLORTYPE_GRAY, - 1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK)); -} - -CPWL_Color ConvertGRAY2CMYK(FX_FLOAT dGray) { - if (!InRange(dGray)) - return CPWL_Color(COLORTYPE_CMYK); - return CPWL_Color(COLORTYPE_CMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray); -} - -CPWL_Color ConvertGRAY2RGB(FX_FLOAT dGray) { - if (!InRange(dGray)) - return CPWL_Color(COLORTYPE_RGB); - return CPWL_Color(COLORTYPE_RGB, dGray, dGray, dGray); -} - -CPWL_Color ConvertRGB2GRAY(FX_FLOAT dR, FX_FLOAT dG, FX_FLOAT dB) { - if (!InRange(dR) || !InRange(dG) || !InRange(dB)) - return CPWL_Color(COLORTYPE_GRAY); - return CPWL_Color(COLORTYPE_GRAY, 0.3f * dR + 0.59f * dG + 0.11f * dB); -} - -CPWL_Color ConvertCMYK2RGB(FX_FLOAT dC, FX_FLOAT dM, FX_FLOAT dY, FX_FLOAT dK) { - if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK)) - return CPWL_Color(COLORTYPE_RGB); - return CPWL_Color(COLORTYPE_RGB, 1.0f - std::min(1.0f, dC + dK), - 1.0f - std::min(1.0f, dM + dK), - 1.0f - std::min(1.0f, dY + dK)); -} - -CPWL_Color ConvertRGB2CMYK(FX_FLOAT dR, FX_FLOAT dG, FX_FLOAT dB) { - if (!InRange(dR) || !InRange(dG) || !InRange(dB)) - return CPWL_Color(COLORTYPE_CMYK); - - FX_FLOAT c = 1.0f - dR; - FX_FLOAT m = 1.0f - dG; - FX_FLOAT y = 1.0f - dB; - return CPWL_Color(COLORTYPE_CMYK, c, m, y, std::min(c, std::min(m, y))); -} - -} // namespace - -CPWL_Color CPWL_Color::ConvertColorType(int32_t nConvertColorType) const { - if (nColorType == nConvertColorType) - return *this; - - CPWL_Color ret; - switch (nColorType) { - case COLORTYPE_TRANSPARENT: - ret = *this; - ret.nColorType = COLORTYPE_TRANSPARENT; - break; - case COLORTYPE_GRAY: - switch (nConvertColorType) { - case COLORTYPE_RGB: - ret = ConvertGRAY2RGB(fColor1); - break; - case COLORTYPE_CMYK: - ret = ConvertGRAY2CMYK(fColor1); - break; - } - break; - case COLORTYPE_RGB: - switch (nConvertColorType) { - case COLORTYPE_GRAY: - ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3); - break; - case COLORTYPE_CMYK: - ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3); - break; - } - break; - case COLORTYPE_CMYK: - switch (nConvertColorType) { - case COLORTYPE_GRAY: - ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4); - break; - case COLORTYPE_RGB: - ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4); - break; - } - break; - } - return ret; -} - -FX_COLORREF CPWL_Color::ToFXColor(int32_t nTransparency) const { - CPWL_Color ret; - switch (nColorType) { - case COLORTYPE_TRANSPARENT: { - ret = CPWL_Color(COLORTYPE_TRANSPARENT, 0, 0, 0, 0); - break; - } - case COLORTYPE_GRAY: { - ret = ConvertGRAY2RGB(fColor1); - ret.fColor4 = nTransparency; - break; - } - case COLORTYPE_RGB: { - ret = CPWL_Color(COLORTYPE_RGB, fColor1, fColor2, fColor3); - ret.fColor4 = nTransparency; - break; - } - case COLORTYPE_CMYK: { - ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4); - ret.fColor4 = nTransparency; - break; - } - } - return ArgbEncode(ret.fColor4, static_cast(ret.fColor1 * 255), - static_cast(ret.fColor2 * 255), - static_cast(ret.fColor3 * 255)); -} - -CPWL_Color CPWL_Color::operator-(FX_FLOAT fColorSub) const { - CPWL_Color sRet(nColorType); - switch (nColorType) { - case COLORTYPE_TRANSPARENT: - sRet.nColorType = COLORTYPE_RGB; - sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f); - sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f); - sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f); - break; - case COLORTYPE_RGB: - case COLORTYPE_GRAY: - case COLORTYPE_CMYK: - sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f); - sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f); - sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f); - sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f); - break; - } - return sRet; -} - -CPWL_Color CPWL_Color::operator/(FX_FLOAT fColorDivide) const { - CPWL_Color sRet(nColorType); - switch (nColorType) { - case COLORTYPE_TRANSPARENT: - sRet.nColorType = COLORTYPE_RGB; - sRet.fColor1 = 1.0f / fColorDivide; - sRet.fColor2 = 1.0f / fColorDivide; - sRet.fColor3 = 1.0f / fColorDivide; - break; - case COLORTYPE_RGB: - case COLORTYPE_GRAY: - case COLORTYPE_CMYK: - sRet = *this; - sRet.fColor1 /= fColorDivide; - sRet.fColor2 /= fColorDivide; - sRet.fColor3 /= fColorDivide; - sRet.fColor4 /= fColorDivide; - break; - } - return sRet; -} diff --git a/fpdfsdk/pdfwindow/cpwl_color.h b/fpdfsdk/pdfwindow/cpwl_color.h deleted file mode 100644 index f1b34c7eb8362b1223cbe826f1e24132053f1f02..0000000000000000000000000000000000000000 --- a/fpdfsdk/pdfwindow/cpwl_color.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef FPDFSDK_PDFWINDOW_CPWL_COLOR_H_ -#define FPDFSDK_PDFWINDOW_CPWL_COLOR_H_ - -#include "core/fpdfdoc/cpdf_formcontrol.h" - -struct CPWL_Color { - CPWL_Color(int32_t type = COLORTYPE_TRANSPARENT, - FX_FLOAT color1 = 0.0f, - FX_FLOAT color2 = 0.0f, - FX_FLOAT color3 = 0.0f, - FX_FLOAT color4 = 0.0f) - : nColorType(type), - fColor1(color1), - fColor2(color2), - fColor3(color3), - fColor4(color4) {} - - CPWL_Color(int32_t r, int32_t g, int32_t b) - : nColorType(COLORTYPE_RGB), - fColor1(r / 255.0f), - fColor2(g / 255.0f), - fColor3(b / 255.0f), - fColor4(0) {} - - CPWL_Color operator/(FX_FLOAT fColorDivide) const; - CPWL_Color operator-(FX_FLOAT fColorSub) const; - - CPWL_Color ConvertColorType(int32_t other_nColorType) const; - - FX_COLORREF ToFXColor(int32_t nTransparency) const; - - void Reset() { - nColorType = COLORTYPE_TRANSPARENT; - fColor1 = 0.0f; - fColor2 = 0.0f; - fColor3 = 0.0f; - fColor4 = 0.0f; - } - - int32_t nColorType; - FX_FLOAT fColor1; - FX_FLOAT fColor2; - FX_FLOAT fColor3; - FX_FLOAT fColor4; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_COLOR_H_ diff --git a/fpdfsdk/pwl/README.md b/fpdfsdk/pwl/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1a73250d0efed7ce48c2675cd16d529cf512d8ec --- /dev/null +++ b/fpdfsdk/pwl/README.md @@ -0,0 +1,21 @@ +fpdfsdk/pwl is a Widget Library for AcroForms. + +CPWL_Wnd is the base class that widget classes extend. The derived widget +classes are controllers for each widget. The hierarchy is: + +* CPWL_Wnd + * CPWL_Button + * CPWL_CheckBox + * CPWL_PushButton + * CPWL_RadioButton + * CPWL_Caret + * CPWL_EditCtrl + * CPWL_Edit + * CPWL_Icon + * CPWL_ListBox + * CPWL_CBListBox (combo box) + * CPWL_ScrollBar + +Widgets are rendered to Appearance Streams, with the case all centralized in +CPWL_AppStream. + diff --git a/fpdfsdk/pwl/cpwl_appstream.cpp b/fpdfsdk/pwl/cpwl_appstream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..203a634bfa225a9a141e9f618b2e78869936d8aa --- /dev/null +++ b/fpdfsdk/pwl/cpwl_appstream.cpp @@ -0,0 +1,1993 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/pwl/cpwl_appstream.h" + +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fpdfdoc/cpvt_word.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fpdfsdk/cpdfsdk_pageview.h" +#include "fpdfsdk/cpdfsdk_widget.h" +#include "fpdfsdk/formfiller/cba_fontmap.h" +#include "fpdfsdk/pwl/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_edit_impl.h" +#include "fpdfsdk/pwl/cpwl_icon.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +namespace { + +// Checkbox & radiobutton styles. +enum class CheckStyle { kCheck = 0, kCircle, kCross, kDiamond, kSquare, kStar }; + +// Pushbutton layout styles. +enum class ButtonStyle { + kLabel = 0, + kIcon, + kIconTopLabelBottom, + kIconBottomLabelTop, + kIconLeftLabelRight, + kIconRightLabelLeft, + kLabelOverIcon +}; + +const char kAppendRectOperator[] = "re"; +const char kConcatMatrixOperator[] = "cm"; +const char kCurveToOperator[] = "c"; +const char kEndPathNoFillOrStrokeOperator[] = "n"; +const char kFillOperator[] = "f"; +const char kFillEvenOddOperator[] = "f*"; +const char kInvokeNamedXObjectOperator[] = "Do"; +const char kLineToOperator[] = "l"; +const char kMarkedSequenceBeginOperator[] = "BMC"; +const char kMarkedSequenceEndOperator[] = "EMC"; +const char kMoveTextPositionOperator[] = "Td"; +const char kMoveToOperator[] = "m"; +const char kSetCharacterSpacingOperator[] = "Tc"; +const char kSetCMYKOperator[] = "k"; +const char kSetCMKYStrokedOperator[] = "K"; +const char kSetDashOperator[] = "d"; +const char kSetGrayOperator[] = "g"; +const char kSetGrayStrokedOperator[] = "G"; +const char kSetLineCapStyleOperator[] = "J"; +const char kSetLineJoinStyleOperator[] = "j"; +const char kSetLineWidthOperator[] = "w"; +const char kSetNonZeroWindingClipOperator[] = "W"; +const char kSetRGBOperator[] = "rg"; +const char kSetRGBStrokedOperator[] = "RG"; +const char kSetTextFontAndSizeOperator[] = "Tf"; +const char kSetTextScaleHorizontalOperator[] = "Tz"; +const char kShowTextOperator[] = "Tj"; +const char kStateRestoreOperator[] = "Q"; +const char kStateSaveOperator[] = "q"; +const char kStrokeOperator[] = "S"; +const char kTextBeginOperator[] = "BT"; +const char kTextEndOperator[] = "ET"; + +class AutoClosedCommand { + public: + AutoClosedCommand(std::ostringstream* stream, + ByteString open, + ByteString close) + : stream_(stream), close_(close) { + *stream_ << open << "\n"; + } + + virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; } + + private: + std::ostringstream* stream_; + ByteString close_; +}; + +class AutoClosedQCommand : public AutoClosedCommand { + public: + explicit AutoClosedQCommand(std::ostringstream* stream) + : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {} + ~AutoClosedQCommand() override {} +}; + +ByteString GetColorAppStream(const CFX_Color& color, + const bool& bFillOrStroke) { + std::ostringstream sColorStream; + + switch (color.nColorType) { + case CFX_Color::kRGB: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " + << (bFillOrStroke ? kSetRGBOperator : kSetRGBStrokedOperator) + << "\n"; + break; + case CFX_Color::kGray: + sColorStream << color.fColor1 << " " + << (bFillOrStroke ? kSetGrayOperator + : kSetGrayStrokedOperator) + << "\n"; + break; + case CFX_Color::kCMYK: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " << color.fColor4 << " " + << (bFillOrStroke ? kSetCMYKOperator + : kSetCMKYStrokedOperator) + << "\n"; + break; + } + + return ByteString(sColorStream); +} + +ByteString GetAP_Check(const CFX_FloatRect& crBBox) { + const float fWidth = crBBox.right - crBBox.left; + const float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), + CFX_PointF(0.29f, 0.40f)}, + {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), + CFX_PointF(0.31f, 0.28f)}, + {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), + CFX_PointF(0.77f, 0.67f)}, + {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), + CFX_PointF(0.76f, 0.75f)}, + {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), + CFX_PointF(0.68f, 0.75f)}, + {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), + CFX_PointF(0.44f, 0.47f)}, + {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), + CFX_PointF(0.41f, 0.58f)}, + {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), + CFX_PointF(0.30f, 0.56f)}}; + + for (size_t i = 0; i < FX_ArraySize(pts); ++i) { + for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { + pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; + pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; + } + } + + std::ostringstream csAP; + csAP << pts[0][0].x << " " << pts[0][0].y << " " << kMoveToOperator << "\n"; + + for (size_t i = 0; i < FX_ArraySize(pts); ++i) { + size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0; + + float px1 = pts[i][1].x - pts[i][0].x; + float py1 = pts[i][1].y - pts[i][0].y; + float px2 = pts[i][2].x - pts[nNext][0].x; + float py2 = pts[i][2].y - pts[nNext][0].y; + + csAP << pts[i][0].x + px1 * FX_BEZIER << " " + << pts[i][0].y + py1 * FX_BEZIER << " " + << pts[nNext][0].x + px2 * FX_BEZIER << " " + << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " " + << pts[nNext][0].y << " " << kCurveToOperator << "\n"; + } + + return ByteString(csAP); +} + +ByteString GetAP_Circle(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); + CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); + CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); + CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); + + csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\n"; + + float px = pt2.x - pt1.x; + float py = pt2.y - pt1.y; + + csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " + << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y + << " " << kCurveToOperator << "\n"; + + px = pt3.x - pt2.x; + py = pt2.y - pt3.y; + + csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " + << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " " + << kCurveToOperator << "\n"; + + px = pt3.x - pt4.x; + py = pt3.y - pt4.y; + + csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " " + << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y + << " " << kCurveToOperator << "\n"; + + px = pt4.x - pt1.x; + py = pt1.y - pt4.y; + + csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " " + << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " " + << kCurveToOperator << "\n"; + + return ByteString(csAP); +} + +ByteString GetAP_Cross(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n"; + csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator + << "\n"; + csAP << crBBox.left << " " << crBBox.bottom << " " << kMoveToOperator << "\n"; + csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n"; + + return ByteString(csAP); +} + +ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); + CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); + CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); + CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); + + csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\n"; + csAP << pt2.x << " " << pt2.y << " " << kLineToOperator << "\n"; + csAP << pt3.x << " " << pt3.y << " " << kLineToOperator << "\n"; + csAP << pt4.x << " " << pt4.y << " " << kLineToOperator << "\n"; + csAP << pt1.x << " " << pt1.y << " " << kLineToOperator << "\n"; + + return ByteString(csAP); +} + +ByteString GetAP_Square(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n"; + csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n"; + csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator + << "\n"; + csAP << crBBox.left << " " << crBBox.bottom << " " << kLineToOperator << "\n"; + csAP << crBBox.left << " " << crBBox.top << " " << kLineToOperator << "\n"; + + return ByteString(csAP); +} + +ByteString GetAP_Star(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fRadius = (crBBox.top - crBBox.bottom) / (1 + (float)cos(FX_PI / 5.0f)); + CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, + (crBBox.top + crBBox.bottom) / 2.0f); + + float px[5]; + float py[5]; + float fAngel = FX_PI / 10.0f; + for (int32_t i = 0; i < 5; i++) { + px[i] = ptCenter.x + fRadius * (float)cos(fAngel); + py[i] = ptCenter.y + fRadius * (float)sin(fAngel); + fAngel += FX_PI * 2 / 5.0f; + } + + csAP << px[0] << " " << py[0] << " " << kMoveToOperator << "\n"; + + int32_t nNext = 0; + for (int32_t j = 0; j < 5; j++) { + nNext += 2; + if (nNext >= 5) + nNext -= 5; + csAP << px[nNext] << " " << py[nNext] << " " << kLineToOperator << "\n"; + } + + return ByteString(csAP); +} + +ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(-fWidth / 2, 0); + CFX_PointF pt2(0, fHeight / 2); + CFX_PointF pt3(fWidth / 2, 0); + + float px; + float py; + + csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " + << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " + << crBBox.bottom + fHeight / 2 << " " << kConcatMatrixOperator << "\n"; + + csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\n"; + + px = pt2.x - pt1.x; + py = pt2.y - pt1.y; + + csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " + << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y + << " " << kCurveToOperator << "\n"; + + px = pt3.x - pt2.x; + py = pt2.y - pt3.y; + + csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " + << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " " + << kCurveToOperator << "\n"; + + return ByteString(csAP); +} + +ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + { + AutoClosedQCommand q(&sAP); + sAP << GetColorAppStream(crText, true) << GetAP_Check(rcBBox) + << kFillOperator << "\n"; + } + return ByteString(sAP); +} + +ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + { + AutoClosedQCommand q(&sAP); + sAP << GetColorAppStream(crText, true) << GetAP_Circle(rcBBox) + << kFillOperator << "\n"; + } + return ByteString(sAP); +} + +ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + { + AutoClosedQCommand q(&sAP); + sAP << GetColorAppStream(crText, false) << GetAP_Cross(rcBBox) + << kStrokeOperator << "\n"; + } + return ByteString(sAP); +} + +ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + { + AutoClosedQCommand q(&sAP); + sAP << "1 " << kSetLineWidthOperator << "\n" + << GetColorAppStream(crText, true) << GetAP_Diamond(rcBBox) + << kFillOperator << "\n"; + } + return ByteString(sAP); +} + +ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + { + AutoClosedQCommand q(&sAP); + sAP << GetColorAppStream(crText, true) << GetAP_Square(rcBBox) + << kFillOperator << "\n"; + } + return ByteString(sAP); +} + +ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + { + AutoClosedQCommand q(&sAP); + sAP << GetColorAppStream(crText, true) << GetAP_Star(rcBBox) + << kFillOperator << "\n"; + } + return ByteString(sAP); +} + +ByteString GetCircleFillAppStream(const CFX_FloatRect& rect, + const CFX_Color& color) { + std::ostringstream sAppStream; + ByteString sColor = GetColorAppStream(color, true); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q(&sAppStream); + sAppStream << sColor << GetAP_Circle(rect) << kFillOperator << "\n"; + } + return ByteString(sAppStream); +} + +ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + const CPWL_Dash& dash) { + std::ostringstream sAppStream; + ByteString sColor; + + if (fWidth > 0.0f) { + AutoClosedQCommand q(&sAppStream); + + float fHalfWidth = fWidth / 2.0f; + CFX_FloatRect rect_by_2 = rect.GetDeflated(fHalfWidth, fHalfWidth); + + float div = fHalfWidth * 0.75f; + CFX_FloatRect rect_by_75 = rect.GetDeflated(div, div); + switch (nStyle) { + default: + case BorderStyle::SOLID: + case BorderStyle::UNDERLINE: { + sColor = GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_Circle(rect_by_2) << " " + << kStrokeOperator << "\n"; + } + } break; + case BorderStyle::DASH: { + sColor = GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fWidth << " " << kSetLineWidthOperator << "\n" + << "[" << dash.nDash << " " << dash.nGap << "] " + << dash.nPhase << " " << kSetDashOperator << "\n" + << sColor << GetAP_Circle(rect_by_2) << " " + << kStrokeOperator << "\n"; + } + } break; + case BorderStyle::BEVELED: { + sColor = GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_Circle(rect) << " " << kStrokeOperator + << "\n"; + } + + sColor = GetColorAppStream(crLeftTop, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f) + << " " << kStrokeOperator << "\n"; + } + + sColor = GetColorAppStream(crRightBottom, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f) + << " " << kStrokeOperator << "\n"; + } + } break; + case BorderStyle::INSET: { + sColor = GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_Circle(rect) << " " << kStrokeOperator + << "\n"; + } + + sColor = GetColorAppStream(crLeftTop, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f) + << " " << kStrokeOperator << "\n"; + } + + sColor = GetColorAppStream(crRightBottom, false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q2(&sAppStream); + sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f) + << " " << kStrokeOperator << "\n"; + } + } break; + } + } + return ByteString(sAppStream); +} + +ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, + CheckStyle nStyle, + const CFX_Color& crText) { + CFX_FloatRect rcCenter = rcBBox.GetCenterSquare(); + switch (nStyle) { + default: + case CheckStyle::kCheck: + return GetAppStream_Check(rcCenter, crText); + case CheckStyle::kCircle: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Circle(rcCenter, crText); + case CheckStyle::kCross: + return GetAppStream_Cross(rcCenter, crText); + case CheckStyle::kDiamond: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Diamond(rcCenter, crText); + case CheckStyle::kSquare: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Square(rcCenter, crText); + case CheckStyle::kStar: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Star(rcCenter, crText); + } +} + +ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, + CheckStyle nStyle, + const CFX_Color& crText) { + CFX_FloatRect rcCenter = rcBBox.GetCenterSquare(); + switch (nStyle) { + default: + case CheckStyle::kCheck: + return GetAppStream_Check(rcCenter, crText); + case CheckStyle::kCircle: + rcCenter.ScaleFromCenterPoint(1.0f / 2.0f); + return GetAppStream_Circle(rcCenter, crText); + case CheckStyle::kCross: + return GetAppStream_Cross(rcCenter, crText); + case CheckStyle::kDiamond: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Diamond(rcCenter, crText); + case CheckStyle::kSquare: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Square(rcCenter, crText); + case CheckStyle::kStar: + rcCenter.ScaleFromCenterPoint(2.0f / 3.0f); + return GetAppStream_Star(rcCenter, crText); + } +} + +ByteString GetFontSetString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + float fFontSize) { + if (!pFontMap) + return ByteString(); + + ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); + if (sFontAlias.GetLength() <= 0 || fFontSize <= 0) + return ByteString(); + + std::ostringstream sRet; + sRet << "/" << sFontAlias << " " << fFontSize << " " + << kSetTextFontAndSizeOperator << "\n"; + return ByteString(sRet); +} + +ByteString GetWordRenderString(const ByteString& strWords) { + if (strWords.GetLength() > 0) { + return PDF_EncodeString(strWords, false) + " " + kShowTextOperator + "\n"; + } + return ByteString(); +} + +ByteString GetEditAppStream(CPWL_EditImpl* pEdit, + const CFX_PointF& ptOffset, + bool bContinuous, + uint16_t SubWord) { + CPWL_EditImpl_Iterator* pIterator = pEdit->GetIterator(); + pIterator->SetAt(0); + + std::ostringstream sEditStream; + std::ostringstream sWords; + int32_t nCurFontIndex = -1; + CFX_PointF ptOld; + CFX_PointF ptNew; + CPVT_WordPlace oldplace; + + while (pIterator->NextWord()) { + CPVT_WordPlace place = pIterator->GetAt(); + if (bContinuous) { + if (place.LineCmp(oldplace) != 0) { + if (sWords.tellp() > 0) { + sEditStream << GetWordRenderString(ByteString(sWords)); + sWords.str(""); + } + + CPVT_Word word; + if (pIterator->GetWord(word)) { + ptNew = CFX_PointF(word.ptWord.x + ptOffset.x, + word.ptWord.y + ptOffset.y); + } else { + CPVT_Line line; + pIterator->GetLine(line); + ptNew = CFX_PointF(line.ptLine.x + ptOffset.x, + line.ptLine.y + ptOffset.y); + } + + if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { + sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " " + << kMoveTextPositionOperator << "\n"; + + ptOld = ptNew; + } + } + + CPVT_Word word; + if (pIterator->GetWord(word)) { + if (word.nFontIndex != nCurFontIndex) { + if (sWords.tellp() > 0) { + sEditStream << GetWordRenderString(ByteString(sWords)); + sWords.str(""); + } + sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex, + word.fFontSize); + nCurFontIndex = word.nFontIndex; + } + + sWords << pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord); + } + + oldplace = place; + } else { + CPVT_Word word; + if (pIterator->GetWord(word)) { + ptNew = + CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y); + + if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { + sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " " + << kMoveTextPositionOperator << "\n"; + ptOld = ptNew; + } + + if (word.nFontIndex != nCurFontIndex) { + sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex, + word.fFontSize); + nCurFontIndex = word.nFontIndex; + } + + sEditStream << GetWordRenderString( + pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord)); + } + } + } + + if (sWords.tellp() > 0) { + sEditStream << GetWordRenderString(ByteString(sWords)); + sWords.str(""); + } + + std::ostringstream sAppStream; + if (sEditStream.tellp() > 0) { + int32_t nHorzScale = pEdit->GetHorzScale(); + if (nHorzScale != 100) { + sAppStream << nHorzScale << " " << kSetTextScaleHorizontalOperator + << "\n"; + } + + float fCharSpace = pEdit->GetCharSpace(); + if (!IsFloatZero(fCharSpace)) { + sAppStream << fCharSpace << " " << kSetCharacterSpacingOperator << "\n"; + } + + sAppStream << sEditStream.str(); + } + + return ByteString(sAppStream); +} + +ByteString GenerateIconAppStream(CPDF_IconFit& fit, + CPDF_Stream* pIconStream, + const CFX_FloatRect& rcIcon) { + if (rcIcon.IsEmpty() || !pIconStream) + return ByteString(); + + CPWL_Icon icon; + CPWL_Wnd::CreateParams cp; + cp.dwFlags = PWS_VISIBLE; + icon.Create(cp); + icon.SetIconFit(&fit); + icon.SetPDFStream(pIconStream); + if (!icon.Move(rcIcon, false, false)) + return ByteString(); + + ByteString sAlias = icon.GetImageAlias(); + if (sAlias.GetLength() <= 0) + return ByteString(); + + CFX_FloatRect rcPlate = icon.GetClientRect(); + CFX_Matrix mt = icon.GetImageMatrix().GetInverse(); + + float fHScale; + float fVScale; + std::tie(fHScale, fVScale) = icon.GetScale(); + + float fx; + float fy; + std::tie(fx, fy) = icon.GetImageOffset(); + + std::ostringstream str; + { + AutoClosedQCommand q(&str); + str << rcPlate.left << " " << rcPlate.bottom << " " + << rcPlate.right - rcPlate.left << " " << rcPlate.top - rcPlate.bottom + << " " << kAppendRectOperator << " " << kSetNonZeroWindingClipOperator + << " " << kEndPathNoFillOrStrokeOperator << "\n"; + + str << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx << " " + << rcPlate.bottom + fy << " " << kConcatMatrixOperator << "\n"; + str << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " " << mt.e + << " " << mt.f << " " << kConcatMatrixOperator << "\n"; + + str << "0 " << kSetGrayOperator << " 0 " << kSetGrayStrokedOperator << " 1 " + << kSetLineWidthOperator << " /" << sAlias << " " + << kInvokeNamedXObjectOperator << "\n"; + } + icon.Destroy(); + + return ByteString(str); +} + +ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox, + IPVT_FontMap* pFontMap, + CPDF_Stream* pIconStream, + CPDF_IconFit& IconFit, + const WideString& sLabel, + const CFX_Color& crText, + float fFontSize, + ButtonStyle nLayOut) { + const float fAutoFontScale = 1.0f / 3.0f; + + auto pEdit = pdfium::MakeUnique(); + pEdit->SetFontMap(pFontMap); + pEdit->SetAlignmentH(1, true); + pEdit->SetAlignmentV(1, true); + pEdit->SetMultiLine(false, true); + pEdit->SetAutoReturn(false, true); + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + pEdit->SetText(sLabel); + + CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); + CFX_FloatRect rcLabel; + CFX_FloatRect rcIcon; + float fWidth = 0.0f; + float fHeight = 0.0f; + + switch (nLayOut) { + case ButtonStyle::kLabel: + rcLabel = rcBBox; + break; + case ButtonStyle::kIcon: + rcIcon = rcBBox; + break; + case ButtonStyle::kIconTopLabelBottom: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fHeight = rcBBox.top - rcBBox.bottom; + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcBBox.bottom + fHeight * fAutoFontScale); + rcIcon = + CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top); + } else { + fHeight = rcLabelContent.Height(); + + if (rcBBox.bottom + fHeight > rcBBox.top) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcBBox.bottom + fHeight); + rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, + rcBBox.top); + } + } + } else { + rcLabel = rcBBox; + } + break; + case ButtonStyle::kIconBottomLabelTop: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fHeight = rcBBox.top - rcBBox.bottom; + rcLabel = + CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale, + rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcLabel.bottom); + } else { + fHeight = rcLabelContent.Height(); + + if (rcBBox.bottom + fHeight > rcBBox.top) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight, + rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcLabel.bottom); + } + } + } else { + rcLabel = rcBBox; + } + break; + case ButtonStyle::kIconLeftLabelRight: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fWidth = rcBBox.right - rcBBox.left; + if (rcLabelContent.Width() < fWidth * fAutoFontScale) { + rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale, + rcBBox.bottom, rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, + rcBBox.top); + } else { + if (rcLabelContent.Width() < fWidth) { + rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(), + rcBBox.bottom, rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, + rcBBox.top); + } else { + rcLabel = rcBBox; + } + } + } else { + fWidth = rcLabelContent.Width(); + if (rcBBox.left + fWidth > rcBBox.right) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom, + rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, + rcBBox.top); + } + } + } else { + rcLabel = rcBBox; + } + break; + case ButtonStyle::kIconRightLabelLeft: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fWidth = rcBBox.right - rcBBox.left; + if (rcLabelContent.Width() < fWidth * fAutoFontScale) { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, + rcBBox.left + fWidth * fAutoFontScale, + rcBBox.top); + rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, + rcBBox.top); + } else { + if (rcLabelContent.Width() < fWidth) { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, + rcBBox.left + rcLabelContent.Width(), + rcBBox.top); + rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, + rcBBox.top); + } else { + rcLabel = rcBBox; + } + } + } else { + fWidth = rcLabelContent.Width(); + if (rcBBox.left + fWidth > rcBBox.right) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, + rcBBox.left + fWidth, rcBBox.top); + rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, + rcBBox.top); + } + } + } else { + rcLabel = rcBBox; + } + break; + case ButtonStyle::kLabelOverIcon: + rcLabel = rcBBox; + rcIcon = rcBBox; + break; + } + + std::ostringstream sTemp; + sTemp << GenerateIconAppStream(IconFit, pIconStream, rcIcon); + + if (!rcLabel.IsEmpty()) { + pEdit->SetPlateRect(rcLabel); + ByteString sEdit = + GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f), true, 0); + if (sEdit.GetLength() > 0) { + AutoClosedCommand bt(&sTemp, kTextBeginOperator, kTextEndOperator); + sTemp << GetColorAppStream(crText, true) << sEdit; + } + } + + if (sTemp.tellp() <= 0) + return ByteString(); + + std::ostringstream sAppStream; + { + AutoClosedQCommand q(&sAppStream); + sAppStream << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.right - rcBBox.left << " " + << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator + << " " << kSetNonZeroWindingClipOperator << " " + << kEndPathNoFillOrStrokeOperator << "\n"; + sAppStream << sTemp.str().c_str(); + } + return ByteString(sAppStream); +} + +ByteString GetBorderAppStreamInternal(const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + const CPWL_Dash& dash) { + std::ostringstream sAppStream; + ByteString sColor; + + float fLeft = rect.left; + float fRight = rect.right; + float fTop = rect.top; + float fBottom = rect.bottom; + + if (fWidth > 0.0f) { + float fHalfWidth = fWidth / 2.0f; + AutoClosedQCommand q(&sAppStream); + + switch (nStyle) { + default: + case BorderStyle::SOLID: + sColor = GetColorAppStream(color, true); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " + << fTop - fBottom << " " << kAppendRectOperator << "\n"; + sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " + << fRight - fLeft - fWidth * 2 << " " + << fTop - fBottom - fWidth * 2 << " " + << kAppendRectOperator << "\n"; + sAppStream << kFillEvenOddOperator << "\n"; + } + break; + case BorderStyle::DASH: + sColor = GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fWidth << " " << kSetLineWidthOperator << " [" + << dash.nDash << " " << dash.nGap << "] " << dash.nPhase + << " " << kSetDashOperator << "\n"; + sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " " + << kMoveToOperator << "\n"; + sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 << " " + << kLineToOperator << "\n"; + sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 << " " + << kLineToOperator << "\n"; + sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 + << " " << kLineToOperator << "\n"; + sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " " + << kLineToOperator << " " << kStrokeOperator << "\n"; + } + break; + case BorderStyle::BEVELED: + case BorderStyle::INSET: + sColor = GetColorAppStream(crLeftTop, true); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " + << kMoveToOperator << "\n"; + sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth << " " + << kLineToOperator << "\n"; + sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " " + << kLineToOperator << "\n"; + sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " " << kLineToOperator << "\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " " << kLineToOperator << "\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " " << kLineToOperator + << " " << kFillOperator << "\n"; + } + + sColor = GetColorAppStream(crRightBottom, true); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " " + << kMoveToOperator << "\n"; + sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth + << " " << kLineToOperator << "\n"; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " + << kLineToOperator << "\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " " << kLineToOperator + << "\n"; + sAppStream << fRight - fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " " << kLineToOperator + << "\n"; + sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " " << kLineToOperator << " " << kFillOperator << "\n"; + } + + sColor = GetColorAppStream(color, true); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " + << fTop - fBottom << " " << kAppendRectOperator << "\n"; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " + << fRight - fLeft - fHalfWidth * 2 << " " + << fTop - fBottom - fHalfWidth * 2 << " " + << kAppendRectOperator << " " << kFillEvenOddOperator + << "\n"; + } + break; + case BorderStyle::UNDERLINE: + sColor = GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"; + sAppStream << fLeft << " " << fBottom + fWidth / 2 << " " + << kMoveToOperator << "\n"; + sAppStream << fRight << " " << fBottom + fWidth / 2 << " " + << kLineToOperator << " " << kStrokeOperator << "\n"; + } + break; + } + } + + return ByteString(sAppStream); +} + +ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { + if (rcBBox.IsEmpty()) + return ByteString(); + + std::ostringstream sAppStream; + { + AutoClosedQCommand q(&sAppStream); + sAppStream << GetColorAppStream(CFX_Color(CFX_Color::kRGB, 220.0f / 255.0f, + 220.0f / 255.0f, 220.0f / 255.0f), + true) + << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.right - rcBBox.left << " " + << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator + << " " << kFillOperator << "\n"; + } + + { + AutoClosedQCommand q(&sAppStream); + sAppStream << GetBorderAppStreamInternal( + rcBBox, 2, CFX_Color(CFX_Color::kGray, 0), + CFX_Color(CFX_Color::kGray, 1), CFX_Color(CFX_Color::kGray, 0.5), + BorderStyle::BEVELED, CPWL_Dash(3, 0, 0)); + } + + CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2, + (rcBBox.top + rcBBox.bottom) / 2); + if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) && + IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) { + AutoClosedQCommand q(&sAppStream); + sAppStream << " 0 " << kSetGrayOperator << "\n" + << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " " + << kMoveToOperator << "\n" + << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " " + << kLineToOperator << "\n" + << ptCenter.x << " " << ptCenter.y - 1.5f << " " + << kLineToOperator << "\n" + << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " " + << kLineToOperator << " " << kFillOperator << "\n"; + } + + return ByteString(sAppStream); +} + +ByteString GetRectFillAppStream(const CFX_FloatRect& rect, + const CFX_Color& color) { + std::ostringstream sAppStream; + ByteString sColor = GetColorAppStream(color, true); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q(&sAppStream); + sAppStream << sColor << rect.left << " " << rect.bottom << " " + << rect.right - rect.left << " " << rect.top - rect.bottom << " " + << kAppendRectOperator << " " << kFillOperator << "\n"; + } + + return ByteString(sAppStream); +} + +} // namespace + +CPWL_AppStream::CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict) + : widget_(widget), dict_(dict) {} + +CPWL_AppStream::~CPWL_AppStream() {} + +void CPWL_AppStream::SetAsPushButton() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + ButtonStyle nLayout = ButtonStyle::kLabel; + switch (pControl->GetTextPosition()) { + case TEXTPOS_ICON: + nLayout = ButtonStyle::kIcon; + break; + case TEXTPOS_BELOW: + nLayout = ButtonStyle::kIconTopLabelBottom; + break; + case TEXTPOS_ABOVE: + nLayout = ButtonStyle::kIconBottomLabelTop; + break; + case TEXTPOS_RIGHT: + nLayout = ButtonStyle::kIconLeftLabelRight; + break; + case TEXTPOS_LEFT: + nLayout = ButtonStyle::kIconRightLabelLeft; + break; + case TEXTPOS_OVERLAID: + nLayout = ButtonStyle::kLabelOverIcon; + break; + default: + nLayout = ButtonStyle::kLabel; + break; + } + + CFX_Color crBackground; + CFX_Color crBorder; + int iColorType; + float fc[4]; + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 0.5); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CFX_Color crText(CFX_Color::kGray, 0); + ByteString csNameTag; + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + float fFontSize = 12.0f; + if (da.HasFont()) + csNameTag = da.GetFont(&fFontSize); + + WideString csWCaption; + WideString csNormalCaption; + WideString csRolloverCaption; + WideString csDownCaption; + if (pControl->HasMKEntry("CA")) + csNormalCaption = pControl->GetNormalCaption(); + + if (pControl->HasMKEntry("RC")) + csRolloverCaption = pControl->GetRolloverCaption(); + + if (pControl->HasMKEntry("AC")) + csDownCaption = pControl->GetDownCaption(); + + CPDF_Stream* pNormalIcon = nullptr; + CPDF_Stream* pRolloverIcon = nullptr; + CPDF_Stream* pDownIcon = nullptr; + if (pControl->HasMKEntry("I")) + pNormalIcon = pControl->GetNormalIcon(); + + if (pControl->HasMKEntry("RI")) + pRolloverIcon = pControl->GetRolloverIcon(); + + if (pControl->HasMKEntry("IX")) + pDownIcon = pControl->GetDownIcon(); + + if (pNormalIcon) { + if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgA", false); + } + } + + if (pRolloverIcon) { + if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgB", false); + } + } + + if (pDownIcon) { + if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgC", false); + } + } + + CPDF_IconFit iconFit = pControl->GetIconFit(); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + font_map.SetAPType("N"); + + ByteString csAP = + GetRectFillAppStream(rcWindow, crBackground) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder) + + GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient, + &font_map, pNormalIcon, iconFit, csNormalCaption, + crText, fFontSize, nLayout); + + Write("N", csAP, ""); + if (pNormalIcon) + AddImage("N", pNormalIcon); + + CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode(); + if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) { + if (csRolloverCaption.IsEmpty() && !pRolloverIcon) { + csRolloverCaption = csNormalCaption; + pRolloverIcon = pNormalIcon; + } + + font_map.SetAPType("R"); + + csAP = + GetRectFillAppStream(rcWindow, crBackground) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder) + + GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient, + &font_map, pRolloverIcon, iconFit, + csRolloverCaption, crText, fFontSize, nLayout); + + Write("R", csAP, ""); + if (pRolloverIcon) + AddImage("R", pRolloverIcon); + + if (csDownCaption.IsEmpty() && !pDownIcon) { + csDownCaption = csNormalCaption; + pDownIcon = pNormalIcon; + } + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(CFX_Color::kGray, 0); + crRightBottom = CFX_Color(CFX_Color::kGray, 1); + break; + } + default: + break; + } + + font_map.SetAPType("D"); + + csAP = + GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder) + + GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient, + &font_map, pDownIcon, iconFit, csDownCaption, + crText, fFontSize, nLayout); + + Write("D", csAP, ""); + if (pDownIcon) + AddImage("D", pDownIcon); + } else { + Remove("D"); + Remove("R"); + } +} + +void CPWL_AppStream::SetAsCheckBox() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_Color crBackground, crBorder, crText; + int iColorType; + float fc[4]; + + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop, crRightBottom; + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 0.5); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + + CheckStyle nStyle = CheckStyle::kCheck; + WideString csWCaption = pControl->GetNormalCaption(); + if (csWCaption.GetLength() > 0) { + switch (csWCaption[0]) { + case L'l': + nStyle = CheckStyle::kCircle; + break; + case L'8': + nStyle = CheckStyle::kCross; + break; + case L'u': + nStyle = CheckStyle::kDiamond; + break; + case L'n': + nStyle = CheckStyle::kSquare; + break; + case L'H': + nStyle = CheckStyle::kStar; + break; + case L'4': + default: + nStyle = CheckStyle::kCheck; + } + } + + ByteString csAP_N_ON = + GetRectFillAppStream(rcWindow, crBackground) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + + ByteString csAP_N_OFF = csAP_N_ON; + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(CFX_Color::kGray, 0); + crRightBottom = CFX_Color(CFX_Color::kGray, 1); + break; + } + default: + break; + } + + ByteString csAP_D_ON = + GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + + ByteString csAP_D_OFF = csAP_D_ON; + + csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); + csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); + + Write("N", csAP_N_ON, pControl->GetCheckedAPState()); + Write("N", csAP_N_OFF, "Off"); + + Write("D", csAP_D_ON, pControl->GetCheckedAPState()); + Write("D", csAP_D_OFF, "Off"); + + ByteString csAS = widget_->GetAppState(); + if (csAS.IsEmpty()) + widget_->SetAppState("Off"); +} + +void CPWL_AppStream::SetAsRadioButton() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_Color crBackground; + CFX_Color crBorder; + CFX_Color crText; + int iColorType; + float fc[4]; + + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 0.5); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + + CheckStyle nStyle = CheckStyle::kCircle; + WideString csWCaption = pControl->GetNormalCaption(); + if (csWCaption.GetLength() > 0) { + switch (csWCaption[0]) { + case L'8': + nStyle = CheckStyle::kCross; + break; + case L'u': + nStyle = CheckStyle::kDiamond; + break; + case L'n': + nStyle = CheckStyle::kSquare; + break; + case L'H': + nStyle = CheckStyle::kStar; + break; + case L'4': + nStyle = CheckStyle::kCheck; + break; + case L'l': + default: + nStyle = CheckStyle::kCircle; + } + } + + ByteString csAP_N_ON; + CFX_FloatRect rcCenter = rcWindow.GetCenterSquare().GetDeflated(1.0f, 1.0f); + if (nStyle == CheckStyle::kCircle) { + if (nBorderStyle == BorderStyle::BEVELED) { + crLeftTop = CFX_Color(CFX_Color::kGray, 1); + crRightBottom = crBackground - 0.25f; + } else if (nBorderStyle == BorderStyle::INSET) { + crLeftTop = CFX_Color(CFX_Color::kGray, 0.5f); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.75f); + } + + csAP_N_ON = + GetCircleFillAppStream(rcCenter, crBackground) + + GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } else { + csAP_N_ON = + GetRectFillAppStream(rcWindow, crBackground) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } + + ByteString csAP_N_OFF = csAP_N_ON; + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(CFX_Color::kGray, 0); + crRightBottom = CFX_Color(CFX_Color::kGray, 1); + break; + } + default: + break; + } + + ByteString csAP_D_ON; + + if (nStyle == CheckStyle::kCircle) { + CFX_Color crBK = crBackground - 0.25f; + if (nBorderStyle == BorderStyle::BEVELED) { + crLeftTop = crBackground - 0.25f; + crRightBottom = CFX_Color(CFX_Color::kGray, 1); + crBK = crBackground; + } else if (nBorderStyle == BorderStyle::INSET) { + crLeftTop = CFX_Color(CFX_Color::kGray, 0); + crRightBottom = CFX_Color(CFX_Color::kGray, 1); + } + + csAP_D_ON = + GetCircleFillAppStream(rcCenter, crBK) + + GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } else { + csAP_D_ON = + GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } + + ByteString csAP_D_OFF = csAP_D_ON; + + csAP_N_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); + csAP_D_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); + + Write("N", csAP_N_ON, pControl->GetCheckedAPState()); + Write("N", csAP_N_OFF, "Off"); + + Write("D", csAP_D_ON, pControl->GetCheckedAPState()); + Write("D", csAP_D_OFF, "Off"); + + ByteString csAS = widget_->GetAppState(); + if (csAS.IsEmpty()) + widget_->SetAppState("Off"); +} + +void CPWL_AppStream::SetAsComboBox(const WideString* sValue) { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + std::ostringstream sBody; + + CFX_FloatRect rcClient = widget_->GetClientRect(); + CFX_FloatRect rcButton = rcClient; + rcButton.left = rcButton.right - 13; + rcButton.Normalize(); + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + + CFX_FloatRect rcEdit = rcClient; + rcEdit.right = rcButton.left; + rcEdit.Normalize(); + + pEdit->SetPlateRect(rcEdit); + pEdit->SetAlignmentV(1, true); + + float fFontSize = widget_->GetFontSize(); + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + + if (sValue) { + pEdit->SetText(*sValue); + } else { + int32_t nCurSel = pField->GetSelectedIndex(0); + if (nCurSel < 0) + pEdit->SetText(pField->GetValue()); + else + pEdit->SetText(pField->GetOptionLabel(nCurSel)); + } + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + ByteString sEdit = GetEditAppStream(pEdit.get(), CFX_PointF(), true, 0); + if (sEdit.GetLength() > 0) { + sBody << "/Tx "; + AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator, + kMarkedSequenceEndOperator); + AutoClosedQCommand q(&sBody); + + if (rcContent.Width() > rcEdit.Width() || + rcContent.Height() > rcEdit.Height()) { + sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width() + << " " << rcEdit.Height() << " " << kAppendRectOperator << "\n" + << kSetNonZeroWindingClipOperator << "\n" + << kEndPathNoFillOrStrokeOperator << "\n"; + } + + CFX_Color crText = widget_->GetTextPWLColor(); + AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator); + sBody << GetColorAppStream(crText, true) << sEdit; + } + + sBody << GetDropButtonAppStream(rcButton); + Write("N", + GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody), + ""); +} + +void CPWL_AppStream::SetAsListBox() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + CFX_FloatRect rcClient = widget_->GetClientRect(); + std::ostringstream sBody; + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f)); + + float fFontSize = widget_->GetFontSize(); + pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); + pEdit->Initialize(); + + std::ostringstream sList; + float fy = rcClient.top; + + int32_t nTop = pField->GetTopVisibleIndex(); + int32_t nCount = pField->CountOptions(); + int32_t nSelCount = pField->CountSelectedItems(); + + for (int32_t i = nTop; i < nCount; ++i) { + bool bSelected = false; + for (int32_t j = 0; j < nSelCount; ++j) { + if (pField->GetSelectedIndex(j) == i) { + bSelected = true; + break; + } + } + + pEdit->SetText(pField->GetOptionLabel(i)); + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + float fItemHeight = rcContent.Height(); + + if (bSelected) { + CFX_FloatRect rcItem = + CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy); + { + AutoClosedQCommand q(&sList); + sList << GetColorAppStream(CFX_Color(CFX_Color::kRGB, 0, 51.0f / 255.0f, + 113.0f / 255.0f), + true) + << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width() + << " " << rcItem.Height() << " " << kAppendRectOperator << " " + << kFillOperator << "\n"; + } + + AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator); + sList << GetColorAppStream(CFX_Color(CFX_Color::kGray, 1), true) + << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0); + } else { + CFX_Color crText = widget_->GetTextPWLColor(); + + AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator); + sList << GetColorAppStream(crText, true) + << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0); + } + + fy -= fItemHeight; + } + + if (sList.tellp() > 0) { + sBody << "/Tx "; + AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator, + kMarkedSequenceEndOperator); + AutoClosedQCommand q(&sBody); + + sBody << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width() + << " " << rcClient.Height() << " " << kAppendRectOperator << "\n" + << kSetNonZeroWindingClipOperator << "\n" + << kEndPathNoFillOrStrokeOperator << "\n" + << sList.str(); + } + Write("N", + GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody), + ""); +} + +void CPWL_AppStream::SetAsTextField(const WideString* sValue) { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + std::ostringstream sBody; + std::ostringstream sLines; + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + + CFX_FloatRect rcClient = widget_->GetClientRect(); + pEdit->SetPlateRect(rcClient); + pEdit->SetAlignmentH(pControl->GetControlAlignment(), true); + + uint32_t dwFieldFlags = pField->GetFieldFlags(); + bool bMultiLine = (dwFieldFlags >> 12) & 1; + if (bMultiLine) { + pEdit->SetMultiLine(true, true); + pEdit->SetAutoReturn(true, true); + } else { + pEdit->SetAlignmentV(1, true); + } + + uint16_t subWord = 0; + if ((dwFieldFlags >> 13) & 1) { + subWord = '*'; + pEdit->SetPasswordChar(subWord, true); + } + + int nMaxLen = pField->GetMaxLen(); + bool bCharArray = (dwFieldFlags >> 24) & 1; + float fFontSize = widget_->GetFontSize(); + +#ifdef PDF_ENABLE_XFA + WideString sValueTmp; + if (!sValue && widget_->GetMixXFAWidget()) { + sValueTmp = widget_->GetValue(true); + sValue = &sValueTmp; + } +#endif // PDF_ENABLE_XFA + + if (nMaxLen > 0) { + if (bCharArray) { + pEdit->SetCharArray(nMaxLen); + + if (IsFloatZero(fFontSize)) { + fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0), + rcClient, nMaxLen); + } + } else { + if (sValue) + nMaxLen = sValue->GetLength(); + pEdit->SetLimitChar(nMaxLen); + } + } + + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + pEdit->SetText(sValue ? *sValue : pField->GetValue()); + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + ByteString sEdit = + GetEditAppStream(pEdit.get(), CFX_PointF(), !bCharArray, subWord); + + if (sEdit.GetLength() > 0) { + sBody << "/Tx "; + AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator, + kMarkedSequenceEndOperator); + AutoClosedQCommand q(&sBody); + + if (rcContent.Width() > rcClient.Width() || + rcContent.Height() > rcClient.Height()) { + sBody << rcClient.left << " " << rcClient.bottom << " " + << rcClient.Width() << " " << rcClient.Height() << " " + << kAppendRectOperator << "\n" + << kSetNonZeroWindingClipOperator << "\n" + << kEndPathNoFillOrStrokeOperator << "\n"; + } + CFX_Color crText = widget_->GetTextPWLColor(); + + AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator); + sBody << GetColorAppStream(crText, true) << sEdit; + } + + if (bCharArray) { + switch (widget_->GetBorderStyle()) { + case BorderStyle::SOLID: { + ByteString sColor = + GetColorAppStream(widget_->GetBorderPWLColor(), false); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q(&sLines); + sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator + << "\n" + << GetColorAppStream(widget_->GetBorderPWLColor(), false) + << " 2 " << kSetLineCapStyleOperator << " 0 " + << kSetLineJoinStyleOperator << "\n"; + + for (int32_t i = 1; i < nMaxLen; ++i) { + sLines << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.bottom << " " << kMoveToOperator << "\n" + << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.top << " " << kLineToOperator << " " + << kStrokeOperator << "\n"; + } + } + break; + } + case BorderStyle::DASH: { + ByteString sColor = + GetColorAppStream(widget_->GetBorderPWLColor(), false); + if (sColor.GetLength() > 0) { + CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0); + AutoClosedQCommand q(&sLines); + sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator + << "\n" + << GetColorAppStream(widget_->GetBorderPWLColor(), false) + << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] " + << dsBorder.nPhase << " " << kSetDashOperator << "\n"; + + for (int32_t i = 1; i < nMaxLen; ++i) { + sLines << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.bottom << " " << kMoveToOperator << "\n" + << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.top << " " << kLineToOperator << " " + << kStrokeOperator << "\n"; + } + } + break; + } + default: + break; + } + } + + Write("N", + GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sLines) + + ByteString(sBody), + ""); +} + +void CPWL_AppStream::AddImage(const ByteString& sAPType, CPDF_Stream* pImage) { + CPDF_Stream* pStream = dict_->GetStreamFor(sAPType); + CPDF_Dictionary* pStreamDict = pStream->GetDict(); + ByteString sImageAlias = "IMG"; + + if (CPDF_Dictionary* pImageDict = pImage->GetDict()) { + sImageAlias = pImageDict->GetStringFor("Name"); + if (sImageAlias.IsEmpty()) + sImageAlias = "IMG"; + } + + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); + if (!pStreamResList) + pStreamResList = pStreamDict->SetNewFor("Resources"); + + CPDF_Dictionary* pXObject = + pStreamResList->SetNewFor("XObject"); + pXObject->SetNewFor(sImageAlias, + widget_->GetPageView()->GetPDFDocument(), + pImage->GetObjNum()); +} + +void CPWL_AppStream::Write(const ByteString& sAPType, + const ByteString& sContents, + const ByteString& sAPState) { + CPDF_Stream* pStream = nullptr; + CPDF_Dictionary* pParentDict = nullptr; + if (sAPState.IsEmpty()) { + pParentDict = dict_.Get(); + pStream = dict_->GetStreamFor(sAPType); + } else { + CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType); + if (!pAPTypeDict) + pAPTypeDict = dict_->SetNewFor(sAPType); + + pParentDict = pAPTypeDict; + pStream = pAPTypeDict->GetStreamFor(sAPState); + } + + if (!pStream) { + CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument(); + pStream = doc->NewIndirect(); + pParentDict->SetNewFor(sAPType, doc, pStream->GetObjNum()); + } + + CPDF_Dictionary* pStreamDict = pStream->GetDict(); + if (!pStreamDict) { + auto pNewDict = pdfium::MakeUnique( + widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool()); + pStreamDict = pNewDict.get(); + pStreamDict->SetNewFor("Type", "XObject"); + pStreamDict->SetNewFor("Subtype", "Form"); + pStreamDict->SetNewFor("FormType", 1); + pStream->InitStream(nullptr, 0, std::move(pNewDict)); + } + pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix()); + pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect()); + pStream->SetDataAndRemoveFilter((uint8_t*)(sContents.c_str()), + sContents.GetLength()); +} + +void CPWL_AppStream::Remove(const ByteString& sAPType) { + dict_->RemoveFor(sAPType); +} + +ByteString CPWL_AppStream::GetBackgroundAppStream() const { + CFX_Color crBackground = widget_->GetFillPWLColor(); + if (crBackground.nColorType != CFX_Color::kTransparent) + return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground); + + return ByteString(); +} + +ByteString CPWL_AppStream::GetBorderAppStream() const { + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_Color crBorder = widget_->GetBorderPWLColor(); + CFX_Color crBackground = widget_->GetFillPWLColor(); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(CFX_Color::kGray, 0.5); + crRightBottom = CFX_Color(CFX_Color::kGray, 0.75); + break; + default: + break; + } + + return GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); +} diff --git a/fpdfsdk/pwl/cpwl_appstream.h b/fpdfsdk/pwl/cpwl_appstream.h new file mode 100644 index 0000000000000000000000000000000000000000..810e79c9e7a2b0bae7e685046da71cb6ce875204 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_appstream.h @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_PWL_CPWL_APPSTREAM_H_ +#define FPDFSDK_PWL_CPWL_APPSTREAM_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPDFSDK_Widget; +class CPDF_Dictionary; +class CPDF_Stream; + +class CPWL_AppStream { + public: + CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict); + ~CPWL_AppStream(); + + void SetAsPushButton(); + void SetAsCheckBox(); + void SetAsRadioButton(); + void SetAsComboBox(const WideString* sValue); + void SetAsListBox(); + void SetAsTextField(const WideString* sValue); + + private: + void AddImage(const ByteString& sAPType, CPDF_Stream* pImage); + void Write(const ByteString& sAPType, + const ByteString& sContents, + const ByteString& sAPState); + void Remove(const ByteString& sAPType); + + ByteString GetBackgroundAppStream() const; + ByteString GetBorderAppStream() const; + + UnownedPtr widget_; + UnownedPtr dict_; +}; + +#endif // FPDFSDK_PWL_CPWL_APPSTREAM_H_ diff --git a/fpdfsdk/pwl/cpwl_button.cpp b/fpdfsdk/pwl/cpwl_button.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c06a98fa6a8fa8b7feba2fffe2d08c901f1d506 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_button.cpp @@ -0,0 +1,34 @@ +// 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 "fpdfsdk/pwl/cpwl_button.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +CPWL_Button::CPWL_Button() : m_bMouseDown(false) {} + +CPWL_Button::~CPWL_Button() {} + +ByteString CPWL_Button::GetClassName() const { + return "CPWL_Button"; +} + +void CPWL_Button::OnCreate(CreateParams* pParamsToAdjust) { + pParamsToAdjust->eCursorType = FXCT_HAND; +} + +bool CPWL_Button::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + m_bMouseDown = true; + SetCapture(); + return true; +} + +bool CPWL_Button::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + ReleaseCapture(); + m_bMouseDown = false; + return true; +} diff --git a/fpdfsdk/pwl/cpwl_button.h b/fpdfsdk/pwl/cpwl_button.h new file mode 100644 index 0000000000000000000000000000000000000000..70f5ef19083be90388f401914a3b3ba8af19bcae --- /dev/null +++ b/fpdfsdk/pwl/cpwl_button.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 FPDFSDK_PWL_CPWL_BUTTON_H_ +#define FPDFSDK_PWL_CPWL_BUTTON_H_ + +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_Button : public CPWL_Wnd { + public: + CPWL_Button(); + ~CPWL_Button() override; + + // CPWL_Wnd + ByteString GetClassName() const override; + void OnCreate(CreateParams* pParamsToAdjust) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + + protected: + bool m_bMouseDown; +}; + +#endif // FPDFSDK_PWL_CPWL_BUTTON_H_ diff --git a/fpdfsdk/pwl/cpwl_caret.cpp b/fpdfsdk/pwl/cpwl_caret.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77a768afe0aa3d68d3a2cd57e3e2bbf85b567b16 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_caret.cpp @@ -0,0 +1,134 @@ +// 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 "fpdfsdk/pwl/cpwl_caret.h" + +#include + +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +#define PWL_CARET_FLASHINTERVAL 500 + +CPWL_Caret::CPWL_Caret() : m_bFlash(false), m_fWidth(0.4f), m_nDelay(0) {} + +CPWL_Caret::~CPWL_Caret() {} + +ByteString CPWL_Caret::GetClassName() const { + return "CPWL_Caret"; +} + +void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + if (!IsVisible() || !m_bFlash) + return; + + CFX_FloatRect rcRect = GetCaretRect(); + CFX_FloatRect rcClip = GetClipRect(); + CFX_PathData path; + + float fCaretX = rcRect.left + m_fWidth * 0.5f; + float fCaretTop = rcRect.top; + float fCaretBottom = rcRect.bottom; + if (!rcClip.IsEmpty()) { + rcRect.Intersect(rcClip); + if (rcRect.IsEmpty()) + return; + + fCaretTop = rcRect.top; + fCaretBottom = rcRect.bottom; + } + + path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom), FXPT_TYPE::MoveTo, false); + path.AppendPoint(CFX_PointF(fCaretX, fCaretTop), FXPT_TYPE::LineTo, false); + + CFX_GraphStateData gsd; + gsd.m_LineWidth = m_fWidth; + pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0), + FXFILL_ALTERNATE); +} + +void CPWL_Caret::TimerProc() { + if (m_nDelay > 0) { + --m_nDelay; + return; + } + + m_bFlash = !m_bFlash; + InvalidateRect(nullptr); + // Note, |this| may no longer be viable at this point. If more work needs + // to be done, add an observer. +} + +CFX_FloatRect CPWL_Caret::GetCaretRect() const { + return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth, + m_ptHead.y); +} + +void CPWL_Caret::SetCaret(bool bVisible, + const CFX_PointF& ptHead, + const CFX_PointF& ptFoot) { + if (!bVisible) { + m_ptHead = CFX_PointF(); + m_ptFoot = CFX_PointF(); + m_bFlash = false; + if (!IsVisible()) + return; + + EndTimer(); + CPWL_Wnd::SetVisible(false); + // Note, |this| may no longer be viable at this point. If more work needs + // to be done, check the return value of SetVisible(). + return; + } + + if (!IsVisible()) { + m_ptHead = ptHead; + m_ptFoot = ptFoot; + EndTimer(); + BeginTimer(PWL_CARET_FLASHINTERVAL); + + if (!CPWL_Wnd::SetVisible(true)) + return; + + m_bFlash = true; + Move(m_rcInvalid, false, true); + // Note, |this| may no longer be viable at this point. If more work needs + // to be done, check the return value of Move(). + return; + } + + if (m_ptHead == ptHead && m_ptFoot == ptFoot) + return; + + m_ptHead = ptHead; + m_ptFoot = ptFoot; + m_bFlash = true; + Move(m_rcInvalid, false, true); + // Note, |this| may no longer be viable at this point. If more work + // needs to be done, check the return value of Move(). +} + +bool CPWL_Caret::InvalidateRect(CFX_FloatRect* pRect) { + if (!pRect) { + return CPWL_Wnd::InvalidateRect(nullptr); + } + + CFX_FloatRect rcRefresh = *pRect; + if (!rcRefresh.IsEmpty()) { + rcRefresh.Inflate(0.5f, 0.5f); + rcRefresh.Normalize(); + } + rcRefresh.top += 1; + rcRefresh.bottom -= 1; + return CPWL_Wnd::InvalidateRect(&rcRefresh); +} + +bool CPWL_Caret::SetVisible(bool bVisible) { + return true; +} diff --git a/fpdfsdk/pwl/cpwl_caret.h b/fpdfsdk/pwl/cpwl_caret.h new file mode 100644 index 0000000000000000000000000000000000000000..d60a96419beab33ea07d75428c5dc1fe6ea16d0c --- /dev/null +++ b/fpdfsdk/pwl/cpwl_caret.h @@ -0,0 +1,41 @@ +// 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 FPDFSDK_PWL_CPWL_CARET_H_ +#define FPDFSDK_PWL_CPWL_CARET_H_ + +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_Caret : public CPWL_Wnd { + public: + CPWL_Caret(); + ~CPWL_Caret() override; + + // CPWL_Wnd + ByteString GetClassName() const override; + void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + bool InvalidateRect(CFX_FloatRect* pRect) override; + bool SetVisible(bool bVisible) override; + void TimerProc() override; + + void SetCaret(bool bVisible, + const CFX_PointF& ptHead, + const CFX_PointF& ptFoot); + void SetInvalidRect(CFX_FloatRect rc) { m_rcInvalid = rc; } + + private: + CFX_FloatRect GetCaretRect() const; + + bool m_bFlash; + CFX_PointF m_ptHead; + CFX_PointF m_ptFoot; + float m_fWidth; + int32_t m_nDelay; + CFX_FloatRect m_rcInvalid; +}; + +#endif // FPDFSDK_PWL_CPWL_CARET_H_ diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3adbebcadba57296da1d2aa34c027a9743508f5a --- /dev/null +++ b/fpdfsdk/pwl/cpwl_combo_box.cpp @@ -0,0 +1,584 @@ +// 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 "fpdfsdk/pwl/cpwl_combo_box.h" + +#include +#include + +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "fpdfsdk/pwl/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" +#include "fpdfsdk/pwl/cpwl_list_box.h" +#include "fpdfsdk/pwl/cpwl_list_impl.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "public/fpdf_fwlevent.h" + +namespace { + +constexpr float kComboBoxDefaultFontSize = 12.0f; +constexpr float kComboBoxTriangleHalfLength = 3.0f; +constexpr int kDefaultButtonWidth = 13; + +} // namespace + +bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + + if (!m_bMouseDown) + return true; + + ReleaseCapture(); + m_bMouseDown = false; + + if (!ClientHitTest(point)) + return true; + if (CPWL_Wnd* pParent = GetParentWindow()) + pParent->NotifyLButtonUp(this, point); + + return !OnNotifySelectionChanged(false, nFlag); +} + +bool CPWL_CBListBox::IsMovementKey(uint16_t nChar) const { + switch (nChar) { + case FWL_VKEY_Up: + case FWL_VKEY_Down: + case FWL_VKEY_Home: + case FWL_VKEY_Left: + case FWL_VKEY_End: + case FWL_VKEY_Right: + return true; + default: + return false; + } +} + +bool CPWL_CBListBox::OnMovementKeyDown(uint16_t nChar, uint32_t nFlag) { + ASSERT(IsMovementKey(nChar)); + + switch (nChar) { + case FWL_VKEY_Up: + m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Down: + m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Home: + m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Left: + m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_End: + m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Right: + m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + } + return OnNotifySelectionChanged(true, nFlag); +} + +bool CPWL_CBListBox::IsChar(uint16_t nChar, uint32_t nFlag) const { + return m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); +} + +bool CPWL_CBListBox::OnCharNotify(uint16_t nChar, uint32_t nFlag) { + if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow()) + pComboBox->SetSelectText(); + + return OnNotifySelectionChanged(true, nFlag); +} + +void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device); + + CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect(); + + if (!IsVisible() || rectWnd.IsEmpty()) + return; + + CFX_PointF ptCenter = GetCenterPoint(); + + static constexpr float kComboBoxTriangleQuarterLength = + kComboBoxTriangleHalfLength * 0.5; + CFX_PointF pt1(ptCenter.x - kComboBoxTriangleHalfLength, + ptCenter.y + kComboBoxTriangleQuarterLength); + CFX_PointF pt2(ptCenter.x + kComboBoxTriangleHalfLength, + ptCenter.y + kComboBoxTriangleQuarterLength); + CFX_PointF pt3(ptCenter.x, ptCenter.y - kComboBoxTriangleQuarterLength); + + if (IsFloatBigger(rectWnd.right - rectWnd.left, + kComboBoxTriangleHalfLength * 2) && + IsFloatBigger(rectWnd.top - rectWnd.bottom, + kComboBoxTriangleHalfLength)) { + CFX_PathData path; + path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false); + path.AppendPoint(pt2, FXPT_TYPE::LineTo, false); + path.AppendPoint(pt3, FXPT_TYPE::LineTo, false); + path.AppendPoint(pt1, FXPT_TYPE::LineTo, false); + + pDevice->DrawPath(&path, &mtUser2Device, nullptr, + PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0, + FXFILL_ALTERNATE); + } +} + +bool CPWL_CBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + + SetCapture(); + + if (CPWL_Wnd* pParent = GetParentWindow()) + pParent->NotifyLButtonDown(this, point); + + return true; +} + +bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + + ReleaseCapture(); + + return true; +} + +CPWL_ComboBox::CPWL_ComboBox() {} + +CPWL_ComboBox::~CPWL_ComboBox() {} + +ByteString CPWL_ComboBox::GetClassName() const { + return "CPWL_ComboBox"; +} + +void CPWL_ComboBox::OnCreate(CreateParams* pParamsToAdjust) { + pParamsToAdjust->dwFlags &= ~PWS_HSCROLL; + pParamsToAdjust->dwFlags &= ~PWS_VSCROLL; +} + +void CPWL_ComboBox::OnDestroy() { + // Until cleanup takes place in the virtual destructor for CPWL_Wnd + // subclasses, implement the virtual OnDestroy method that does the + // cleanup first, then invokes the superclass OnDestroy ... gee, + // like a dtor would. + m_pList.Release(); + m_pButton.Release(); + m_pEdit.Release(); + CPWL_Wnd::OnDestroy(); +} + +void CPWL_ComboBox::SetFocus() { + if (m_pEdit) + m_pEdit->SetFocus(); +} + +void CPWL_ComboBox::KillFocus() { + if (!SetPopup(false)) + return; + + CPWL_Wnd::KillFocus(); +} + +WideString CPWL_ComboBox::GetSelectedText() { + if (m_pEdit) + return m_pEdit->GetSelectedText(); + + return WideString(); +} + +void CPWL_ComboBox::ReplaceSelection(const WideString& text) { + if (m_pEdit) + m_pEdit->ReplaceSelection(text); +} + +WideString CPWL_ComboBox::GetText() const { + if (m_pEdit) { + return m_pEdit->GetText(); + } + return WideString(); +} + +void CPWL_ComboBox::SetText(const WideString& text) { + if (m_pEdit) + m_pEdit->SetText(text); +} + +void CPWL_ComboBox::AddString(const WideString& str) { + if (m_pList) + m_pList->AddString(str); +} + +int32_t CPWL_ComboBox::GetSelect() const { + return m_nSelectItem; +} + +void CPWL_ComboBox::SetSelect(int32_t nItemIndex) { + if (m_pList) + m_pList->Select(nItemIndex); + + m_pEdit->SetText(m_pList->GetText()); + m_nSelectItem = nItemIndex; +} + +void CPWL_ComboBox::SetEditSelection(int32_t nStartChar, int32_t nEndChar) { + if (m_pEdit) + m_pEdit->SetSelection(nStartChar, nEndChar); +} + +void CPWL_ComboBox::GetEditSelection(int32_t& nStartChar, + int32_t& nEndChar) const { + nStartChar = -1; + nEndChar = -1; + + if (m_pEdit) + m_pEdit->GetSelection(nStartChar, nEndChar); +} + +void CPWL_ComboBox::ClearSelection() { + if (m_pEdit) + m_pEdit->ClearSelection(); +} + +void CPWL_ComboBox::CreateChildWnd(const CreateParams& cp) { + CreateEdit(cp); + CreateButton(cp); + CreateListBox(cp); +} + +void CPWL_ComboBox::CreateEdit(const CreateParams& cp) { + if (m_pEdit) + return; + + m_pEdit = new CPWL_Edit(); + m_pEdit->AttachFFLData(m_pFormFiller.Get()); + + CreateParams ecp = cp; + ecp.pParentWnd = this; + ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER | + PES_AUTOSCROLL | PES_UNDO; + + if (HasFlag(PWS_AUTOFONTSIZE)) + ecp.dwFlags |= PWS_AUTOFONTSIZE; + + if (!HasFlag(PCBS_ALLOWCUSTOMTEXT)) + ecp.dwFlags |= PWS_READONLY; + + ecp.rcRectWnd = CFX_FloatRect(); + ecp.dwBorderWidth = 0; + ecp.nBorderStyle = BorderStyle::SOLID; + m_pEdit->Create(ecp); +} + +void CPWL_ComboBox::CreateButton(const CreateParams& cp) { + if (m_pButton) + return; + + m_pButton = new CPWL_CBButton; + + CreateParams bcp = cp; + bcp.pParentWnd = this; + bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND; + bcp.sBackgroundColor = CFX_Color(CFX_Color::kRGB, 220.0f / 255.0f, + 220.0f / 255.0f, 220.0f / 255.0f); + bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR; + bcp.dwBorderWidth = 2; + bcp.nBorderStyle = BorderStyle::BEVELED; + bcp.eCursorType = FXCT_ARROW; + m_pButton->Create(bcp); +} + +void CPWL_ComboBox::CreateListBox(const CreateParams& cp) { + if (m_pList) + return; + + m_pList = new CPWL_CBListBox(); + m_pList->AttachFFLData(m_pFormFiller.Get()); + + CreateParams lcp = cp; + lcp.pParentWnd = this; + lcp.dwFlags = + PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL; + lcp.nBorderStyle = BorderStyle::SOLID; + lcp.dwBorderWidth = 1; + lcp.eCursorType = FXCT_ARROW; + lcp.rcRectWnd = CFX_FloatRect(); + + lcp.fFontSize = + (cp.dwFlags & PWS_AUTOFONTSIZE) ? kComboBoxDefaultFontSize : cp.fFontSize; + + if (cp.sBorderColor.nColorType == CFX_Color::kTransparent) + lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR; + + if (cp.sBackgroundColor.nColorType == CFX_Color::kTransparent) + lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR; + + m_pList->Create(lcp); +} + +bool CPWL_ComboBox::RePosChildWnd() { + ObservedPtr thisObserved(this); + + const CFX_FloatRect rcClient = GetClientRect(); + if (m_bPopup) { + const float fOldWindowHeight = m_rcOldWindow.Height(); + const float fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2; + + CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect(); + CFX_FloatRect rcButton = rcClient; + rcButton.left = + std::max(rcButton.right - kDefaultButtonWidth, rcClient.left); + CFX_FloatRect rcEdit = rcClient; + rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left); + if (m_bBottom) { + rcButton.bottom = rcButton.top - fOldClientHeight; + rcEdit.bottom = rcEdit.top - fOldClientHeight; + rcList.top -= fOldWindowHeight; + } else { + rcButton.top = rcButton.bottom + fOldClientHeight; + rcEdit.top = rcEdit.bottom + fOldClientHeight; + rcList.bottom += fOldWindowHeight; + } + + if (m_pButton) { + m_pButton->Move(rcButton, true, false); + if (!thisObserved) + return false; + } + + if (m_pEdit) { + m_pEdit->Move(rcEdit, true, false); + if (!thisObserved) + return false; + } + + if (m_pList) { + if (!m_pList->SetVisible(true) || !thisObserved) + return false; + + if (!m_pList->Move(rcList, true, false) || !thisObserved) + return false; + + m_pList->ScrollToListItem(m_nSelectItem); + if (!thisObserved) + return false; + } + return true; + } + + CFX_FloatRect rcButton = rcClient; + rcButton.left = std::max(rcButton.right - kDefaultButtonWidth, rcClient.left); + + if (m_pButton) { + m_pButton->Move(rcButton, true, false); + if (!thisObserved) + return false; + } + + CFX_FloatRect rcEdit = rcClient; + rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left); + + if (m_pEdit) { + m_pEdit->Move(rcEdit, true, false); + if (!thisObserved) + return false; + } + + if (m_pList) { + m_pList->SetVisible(false); + if (!thisObserved) + return false; + } + + return true; +} + +void CPWL_ComboBox::SelectAll() { + if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT)) + m_pEdit->SelectAll(); +} + +CFX_FloatRect CPWL_ComboBox::GetFocusRect() const { + return CFX_FloatRect(); +} + +bool CPWL_ComboBox::SetPopup(bool bPopup) { + if (!m_pList) + return true; + if (bPopup == m_bPopup) + return true; + float fListHeight = m_pList->GetContentRect().Height(); + if (!IsFloatBigger(fListHeight, 0.0f)) + return true; + + if (!bPopup) { + m_bPopup = bPopup; + return Move(m_rcOldWindow, true, true); + } + + if (!m_pFillerNotify) + return true; + + ObservedPtr thisObserved(this); + +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), 0)) + return !!thisObserved; + if (!thisObserved) + return false; +#endif // PDF_ENABLE_XFA + + float fBorderWidth = m_pList->GetBorderWidth() * 2; + float fPopupMin = 0.0f; + if (m_pList->GetCount() > 3) + fPopupMin = m_pList->GetFirstHeight() * 3 + fBorderWidth; + float fPopupMax = fListHeight + fBorderWidth; + + bool bBottom; + float fPopupRet; + m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax, + &bBottom, &fPopupRet); + if (!IsFloatBigger(fPopupRet, 0.0f)) + return true; + + m_rcOldWindow = CPWL_Wnd::GetWindowRect(); + m_bPopup = bPopup; + m_bBottom = bBottom; + + CFX_FloatRect rcWindow = m_rcOldWindow; + if (bBottom) + rcWindow.bottom -= fPopupRet; + else + rcWindow.top += fPopupRet; + + if (!Move(rcWindow, true, true)) + return false; + +#ifdef PDF_ENABLE_XFA + m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), 0); + if (!thisObserved) + return false; +#endif // PDF_ENABLE_XFA + + return !!thisObserved; +} + +bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) { + if (!m_pList) + return false; + if (!m_pEdit) + return false; + + m_nSelectItem = -1; + + switch (nChar) { + case FWL_VKEY_Up: + if (m_pList->GetCurSel() > 0) { +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify) { + if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag)) + return false; + if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag)) + return false; + } +#endif // PDF_ENABLE_XFA + if (m_pList->IsMovementKey(nChar)) { + if (m_pList->OnMovementKeyDown(nChar, nFlag)) + return false; + SetSelectText(); + } + } + return true; + case FWL_VKEY_Down: + if (m_pList->GetCurSel() < m_pList->GetCount() - 1) { +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify) { + if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag)) + return false; + if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag)) + return false; + } +#endif // PDF_ENABLE_XFA + if (m_pList->IsMovementKey(nChar)) { + if (m_pList->OnMovementKeyDown(nChar, nFlag)) + return false; + SetSelectText(); + } + } + return true; + } + + if (HasFlag(PCBS_ALLOWCUSTOMTEXT)) + return m_pEdit->OnKeyDown(nChar, nFlag); + + return false; +} + +bool CPWL_ComboBox::OnChar(uint16_t nChar, uint32_t nFlag) { + if (!m_pList) + return false; + + if (!m_pEdit) + return false; + + m_nSelectItem = -1; + if (HasFlag(PCBS_ALLOWCUSTOMTEXT)) + return m_pEdit->OnChar(nChar, nFlag); + +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify) { + if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag)) + return false; + if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag)) + return false; + } +#endif // PDF_ENABLE_XFA + if (!m_pList->IsChar(nChar, nFlag)) + return false; + return m_pList->OnCharNotify(nChar, nFlag); +} + +void CPWL_ComboBox::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) { + if (child == m_pButton) { + SetPopup(!m_bPopup); + // Note, |this| may no longer be viable at this point. If more work needs to + // be done, check the return value of SetPopup(). + } +} + +void CPWL_ComboBox::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) { + if (!m_pEdit || !m_pList || child != m_pList) + return; + + SetSelectText(); + SelectAll(); + m_pEdit->SetFocus(); + SetPopup(false); + // Note, |this| may no longer be viable at this point. If more work needs to + // be done, check the return value of SetPopup(). +} + +bool CPWL_ComboBox::IsPopup() const { + return m_bPopup; +} + +void CPWL_ComboBox::SetSelectText() { + m_pEdit->SelectAll(); + m_pEdit->ReplaceSel(m_pList->GetText()); + m_pEdit->SelectAll(); + m_nSelectItem = m_pList->GetCurSel(); +} + +void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) { + m_pFillerNotify = pNotify; + + if (m_pEdit) + m_pEdit->SetFillerNotify(pNotify); + + if (m_pList) + m_pList->SetFillerNotify(pNotify); +} diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h new file mode 100644 index 0000000000000000000000000000000000000000..6db721369b8a3dd8428a03c069d43e8234501700 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_combo_box.h @@ -0,0 +1,103 @@ +// 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 FPDFSDK_PWL_CPWL_COMBO_BOX_H_ +#define FPDFSDK_PWL_CPWL_COMBO_BOX_H_ + +#include + +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_list_box.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_CBListBox : public CPWL_ListBox { + public: + CPWL_CBListBox() {} + ~CPWL_CBListBox() override {} + + // CPWL_ListBox + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + + bool IsMovementKey(uint16_t nChar) const; + bool OnMovementKeyDown(uint16_t nChar, uint32_t nFlag); + bool IsChar(uint16_t nChar, uint32_t nFlag) const; + bool OnCharNotify(uint16_t nChar, uint32_t nFlag); +}; + +class CPWL_CBButton : public CPWL_Wnd { + public: + CPWL_CBButton() {} + ~CPWL_CBButton() override {} + + // CPWL_Wnd + void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; +}; + +class CPWL_ComboBox : public CPWL_Wnd { + public: + CPWL_ComboBox(); + ~CPWL_ComboBox() override; + + CPWL_Edit* GetEdit() const { return m_pEdit.Get(); } + + // CPWL_Wnd: + ByteString GetClassName() const override; + void OnCreate(CreateParams* pParamsToAdjust) override; + void OnDestroy() override; + bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + void NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) override; + void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) override; + void CreateChildWnd(const CreateParams& cp) override; + bool RePosChildWnd() override; + CFX_FloatRect GetFocusRect() const override; + void SetFocus() override; + void KillFocus() override; + WideString GetSelectedText() override; + void ReplaceSelection(const WideString& text) override; + + void SetFillerNotify(IPWL_Filler_Notify* pNotify); + + WideString GetText() const; + void SetText(const WideString& text); + void AddString(const WideString& str); + int32_t GetSelect() const; + void SetSelect(int32_t nItemIndex); + + void SetEditSelection(int32_t nStartChar, int32_t nEndChar); + void GetEditSelection(int32_t& nStartChar, int32_t& nEndChar) const; + void ClearSelection(); + void SelectAll(); + bool IsPopup() const; + + void SetSelectText(); + + void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; } + + private: + void CreateEdit(const CreateParams& cp); + void CreateButton(const CreateParams& cp); + void CreateListBox(const CreateParams& cp); + + // Returns |true| iff this instance is still allocated. + bool SetPopup(bool bPopup); + + UnownedPtr m_pEdit; + UnownedPtr m_pButton; + UnownedPtr m_pList; + CFX_FloatRect m_rcOldWindow; + bool m_bPopup = false; + bool m_bBottom = true; + int32_t m_nSelectItem = -1; + UnownedPtr m_pFillerNotify; + UnownedPtr m_pFormFiller; +}; + +#endif // FPDFSDK_PWL_CPWL_COMBO_BOX_H_ diff --git a/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fd8eec1736ef08ff98b77f662d9706e0048a297 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp @@ -0,0 +1,348 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fpdfsdk/cba_annotiterator.h" +#include "fpdfsdk/cpdfsdk_annot.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" +#include "fpdfsdk/pwl/cpwl_combo_box.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CPWLComboBoxEditEmbeddertest : public EmbedderTest { + protected: + void SetUp() override { + EmbedderTest::SetUp(); + CreateAndInitializeFormComboboxPDF(); + } + + void TearDown() override { + UnloadPage(GetPage()); + EmbedderTest::TearDown(); + } + + void CreateAndInitializeFormComboboxPDF() { + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + m_page = LoadPage(0); + ASSERT_TRUE(m_page); + + m_pFormFillEnv = static_cast(form_handle()); + CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0), + CPDF_Annot::Subtype::WIDGET); + + // User editable combobox. + m_pAnnotEditable = iter.GetFirstAnnot(); + ASSERT_TRUE(m_pAnnotEditable); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotEditable->GetAnnotSubtype()); + + // Normal combobox with pre-selected value. + m_pAnnotNormal = iter.GetNextAnnot(m_pAnnotEditable); + ASSERT_TRUE(m_pAnnotNormal); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotNormal->GetAnnotSubtype()); + + // Read-only combobox. + CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnotNormal); + CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); + ASSERT_EQ(pAnnotReadOnly, pLastAnnot); + } + + void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotCombobox) { + CFFL_InteractiveFormFiller* pInteractiveFormFiller = + m_pFormFillEnv->GetInteractiveFormFiller(); + { + CPDFSDK_Annot::ObservedPtr pObserved(pAnnotCombobox); + EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0)); + } + + m_pFormFiller = + pInteractiveFormFiller->GetFormFiller(pAnnotCombobox, false); + ASSERT_TRUE(m_pFormFiller); + + CPWL_Wnd* pWindow = + m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false); + ASSERT_TRUE(pWindow); + ASSERT_EQ("CPWL_ComboBox", pWindow->GetClassName()); + m_pComboBox = static_cast(pWindow); + } + + void TypeTextIntoTextField(int num_chars) { + // Type text starting with 'A' to as many chars as specified by |num_chars|. + for (int i = 0; i < num_chars; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), + i + 'A', 0)); + } + } + + FPDF_PAGE GetPage() const { return m_page; } + CPWL_ComboBox* GetCPWLComboBox() const { return m_pComboBox; } + CFFL_FormFiller* GetCFFLFormFiller() const { return m_pFormFiller; } + CPDFSDK_Annot* GetCPDFSDKAnnotNormal() const { return m_pAnnotNormal; } + CPDFSDK_Annot* GetCPDFSDKAnnotUserEditable() const { + return m_pAnnotEditable; + } + CPDFSDK_FormFillEnvironment* GetCPDFSDKFormFillEnv() const { + return m_pFormFillEnv; + } + + private: + FPDF_PAGE m_page; + CPWL_ComboBox* m_pComboBox; + CFFL_FormFiller* m_pFormFiller; + CPDFSDK_Annot* m_pAnnotNormal; + CPDFSDK_Annot* m_pAnnotEditable; + CPDFSDK_FormFillEnvironment* m_pFormFillEnv; +}; + +TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextEmptyAndBasicNormal) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal()); + + // Automatically pre-filled with "Banana". + EXPECT_FALSE(GetCPWLComboBox()->GetText().IsEmpty()); + EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str()); + + // Check that selection is intially empty, then select entire word. + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + GetCPWLComboBox()->SetSelectText(); + EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str()); + + // Select other options. + GetCPWLComboBox()->SetSelect(0); + EXPECT_STREQ(L"Apple", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->SetSelect(2); + EXPECT_STREQ(L"Cherry", GetCPWLComboBox()->GetSelectedText().c_str()); + + // Verify that combobox text cannot be edited. + EXPECT_FALSE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotNormal(), 'a', 0)); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextFragmentsNormal) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal()); + EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str()); + + GetCPWLComboBox()->SetEditSelection(0, 0); + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + + GetCPWLComboBox()->SetEditSelection(0, 1); + EXPECT_STREQ(L"B", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(0, -1); + EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(-8, -1); + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + + GetCPWLComboBox()->SetEditSelection(4, 1); + EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(1, 4); + EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(5, 6); + EXPECT_STREQ(L"a", GetCPWLComboBox()->GetSelectedText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextEmptyAndBasicEditable) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty()); + + // Check selection is intially empty, then select a provided option. + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + GetCPWLComboBox()->SetSelect(0); + GetCPWLComboBox()->SetSelectText(); + EXPECT_STREQ(L"Foo", GetCPWLComboBox()->GetSelectedText().c_str()); + + // Select another option and then select last char of that option. + GetCPWLComboBox()->SetSelect(1); + EXPECT_STREQ(L"Bar", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->SetEditSelection(2, 3); + EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str()); + + // Type into editable combobox text field and select new text. + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'a', 0)); + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'b', 0)); + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'c', 0)); + + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + GetCPWLComboBox()->SetEditSelection(0, 5); + EXPECT_STREQ(L"Baabc", GetCPWLComboBox()->GetSelectedText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextFragmentsEditable) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(50); + + GetCPWLComboBox()->SetEditSelection(0, 0); + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + + GetCPWLComboBox()->SetEditSelection(0, 1); + EXPECT_STREQ(L"A", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(-8, -1); + EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty()); + + GetCPWLComboBox()->SetEditSelection(23, 12); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(12, 23); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(49, 50); + EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->SetEditSelection(49, 55); + EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEntireTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(50); + + GetCPWLComboBox()->SetEditSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->ReplaceSelection(L""); + EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(50); + + GetCPWLComboBox()->SetEditSelection(12, 23); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->ReplaceSelection(L""); + EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(50); + + GetCPWLComboBox()->SetEditSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->ReplaceSelection(L""); + EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(50); + + GetCPWLComboBox()->SetEditSelection(45, 50); + EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->ReplaceSelection(L""); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEmptyTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(50); + + GetCPWLComboBox()->ReplaceSelection(L""); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, InsertTextInEmptyEditableComboBox) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextInPopulatedEditableComboBoxLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + // Move cursor to beginning of user-editable combobox text field. + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(), + FWL_VKEY_Home, 0)); + + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextInPopulatedEditableComboBoxMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + // Move cursor to middle of user-editable combobox text field. + for (int i = 0; i < 5; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(), + FWL_VKEY_Left, 0)); + } + + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextInPopulatedEditableComboBoxRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"HelloFGHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(2, 7); + EXPECT_STREQ(L"CDEFG", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABHelloHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(5, 10); + EXPECT_STREQ(L"FGHIJ", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABCDEHello", GetCPWLComboBox()->GetText().c_str()); +} diff --git a/fpdfsdk/pwl/cpwl_edit.cpp b/fpdfsdk/pwl/cpwl_edit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c867ca456a9df9f2c3cdb39a5d40815d46fe09b --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit.cpp @@ -0,0 +1,726 @@ +// 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 "fpdfsdk/pwl/cpwl_edit.h" + +#include +#include +#include +#include + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfdoc/cpvt_word.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/xml/cxml_content.h" +#include "core/fxcrt/xml/cxml_element.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/fx_font.h" +#include "fpdfsdk/pwl/cpwl_caret.h" +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" +#include "fpdfsdk/pwl/cpwl_edit_impl.h" +#include "fpdfsdk/pwl/cpwl_font_map.h" +#include "fpdfsdk/pwl/cpwl_scroll_bar.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "public/fpdf_fwlevent.h" +#include "third_party/base/stl_util.h" + +CPWL_Edit::CPWL_Edit() : m_bFocus(false) {} + +CPWL_Edit::~CPWL_Edit() { + ASSERT(!m_bFocus); +} + +ByteString CPWL_Edit::GetClassName() const { + return PWL_CLASSNAME_EDIT; +} + +void CPWL_Edit::SetText(const WideString& csText) { + WideString swText = csText; + if (!HasFlag(PES_RICH)) { + m_pEdit->SetText(swText); + return; + } + + ByteString sValue = ByteString::FromUnicode(swText); + std::unique_ptr pXML( + CXML_Element::Parse(sValue.c_str(), sValue.GetLength())); + if (!pXML) { + m_pEdit->SetText(swText); + return; + } + swText.clear(); + + bool bFirst = true; + size_t nCount = pXML->CountChildren(); + for (size_t i = 0; i < nCount; ++i) { + CXML_Element* pSubElement = ToElement(pXML->GetChild(i)); + if (!pSubElement || !pSubElement->GetTagName().EqualNoCase("p")) + continue; + + WideString swSection; + size_t nSubChild = pSubElement->CountChildren(); + for (size_t j = 0; j < nSubChild; ++j) { + CXML_Content* pSubContent = ToContent(pSubElement->GetChild(j)); + if (pSubContent) + swSection += pSubContent->m_Content; + } + if (bFirst) + bFirst = false; + else + swText += FWL_VKEY_Return; + swText += swSection; + } + + m_pEdit->SetText(swText); +} + +bool CPWL_Edit::RePosChildWnd() { + if (CPWL_ScrollBar* pVSB = GetVScrollBar()) { + CFX_FloatRect rcWindow = m_rcOldWindow; + CFX_FloatRect rcVScroll = + CFX_FloatRect(rcWindow.right, rcWindow.bottom, + rcWindow.right + PWL_SCROLLBAR_WIDTH, rcWindow.top); + + ObservedPtr thisObserved(this); + + pVSB->Move(rcVScroll, true, false); + if (!thisObserved) + return false; + } + + if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW)) { + CFX_FloatRect rect = GetClientRect(); + if (!rect.IsEmpty()) { + // +1 for caret beside border + rect.Inflate(1.0f, 1.0f); + rect.Normalize(); + } + m_pEditCaret->SetClipRect(rect); + } + + return CPWL_EditCtrl::RePosChildWnd(); +} + +CFX_FloatRect CPWL_Edit::GetClientRect() const { + float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); + CFX_FloatRect rcClient = GetWindowRect().GetDeflated(width, width); + if (CPWL_ScrollBar* pVSB = GetVScrollBar()) { + if (pVSB->IsVisible()) { + rcClient.right -= PWL_SCROLLBAR_WIDTH; + } + } + + return rcClient; +} + +void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, bool bPaint) { + m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint); +} + +bool CPWL_Edit::CanSelectAll() const { + return GetSelectWordRange() != m_pEdit->GetWholeWordRange(); +} + +bool CPWL_Edit::CanCopy() const { + return !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && + m_pEdit->IsSelected(); +} + +bool CPWL_Edit::CanCut() const { + return CanCopy() && !IsReadOnly(); +} +void CPWL_Edit::CutText() { + if (!CanCut()) + return; + m_pEdit->ClearSelection(); +} + +void CPWL_Edit::OnCreated() { + CPWL_EditCtrl::OnCreated(); + + if (CPWL_ScrollBar* pScroll = GetVScrollBar()) { + pScroll->RemoveFlag(PWS_AUTOTRANSPARENT); + pScroll->SetTransparency(255); + } + + SetParamByFlag(); + + m_rcOldWindow = GetWindowRect(); + + m_pEdit->SetOperationNotify(this); +} + +void CPWL_Edit::SetParamByFlag() { + if (HasFlag(PES_RIGHT)) { + m_pEdit->SetAlignmentH(2, false); + } else if (HasFlag(PES_MIDDLE)) { + m_pEdit->SetAlignmentH(1, false); + } else { + m_pEdit->SetAlignmentH(0, false); + } + + if (HasFlag(PES_BOTTOM)) { + m_pEdit->SetAlignmentV(2, false); + } else if (HasFlag(PES_CENTER)) { + m_pEdit->SetAlignmentV(1, false); + } else { + m_pEdit->SetAlignmentV(0, false); + } + + if (HasFlag(PES_PASSWORD)) { + m_pEdit->SetPasswordChar('*', false); + } + + m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), false); + m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), false); + m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), false); + m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), false); + m_pEdit->EnableUndo(HasFlag(PES_UNDO)); + + if (HasFlag(PES_TEXTOVERFLOW)) { + SetClipRect(CFX_FloatRect()); + m_pEdit->SetTextOverflow(true, false); + } else { + if (m_pEditCaret) { + CFX_FloatRect rect = GetClientRect(); + if (!rect.IsEmpty()) { + // +1 for caret beside border + rect.Inflate(1.0f, 1.0f); + rect.Normalize(); + } + m_pEditCaret->SetClipRect(rect); + } + } +} + +void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device); + + CFX_FloatRect rcClient = GetClientRect(); + + int32_t nCharArray = m_pEdit->GetCharArray(); + FX_SAFE_INT32 nCharArraySafe = nCharArray; + nCharArraySafe -= 1; + nCharArraySafe *= 2; + + if (nCharArray > 0 && nCharArraySafe.IsValid()) { + switch (GetBorderStyle()) { + case BorderStyle::SOLID: { + CFX_GraphStateData gsd; + gsd.m_LineWidth = (float)GetBorderWidth(); + + CFX_PathData path; + + for (int32_t i = 0; i < nCharArray - 1; i++) { + path.AppendPoint( + CFX_PointF( + rcClient.left + + ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), + rcClient.bottom), + FXPT_TYPE::MoveTo, false); + path.AppendPoint( + CFX_PointF( + rcClient.left + + ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), + rcClient.top), + FXPT_TYPE::LineTo, false); + } + if (!path.GetPoints().empty()) { + pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0, + GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE); + } + break; + } + case BorderStyle::DASH: { + CFX_GraphStateData gsd; + gsd.m_LineWidth = (float)GetBorderWidth(); + + gsd.SetDashCount(2); + gsd.m_DashArray[0] = (float)GetBorderDash().nDash; + gsd.m_DashArray[1] = (float)GetBorderDash().nGap; + gsd.m_DashPhase = (float)GetBorderDash().nPhase; + + CFX_PathData path; + for (int32_t i = 0; i < nCharArray - 1; i++) { + path.AppendPoint( + CFX_PointF( + rcClient.left + + ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), + rcClient.bottom), + FXPT_TYPE::MoveTo, false); + path.AppendPoint( + CFX_PointF( + rcClient.left + + ((rcClient.right - rcClient.left) / nCharArray) * (i + 1), + rcClient.top), + FXPT_TYPE::LineTo, false); + } + if (!path.GetPoints().empty()) { + pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0, + GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE); + } + break; + } + default: + break; + } + } + + CFX_FloatRect rcClip; + CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange(); + CPVT_WordRange* pRange = nullptr; + if (!HasFlag(PES_TEXTOVERFLOW)) { + rcClip = GetClientRect(); + pRange = &wrRange; + } + + CFX_SystemHandler* pSysHandler = GetSystemHandler(); + CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pEdit.get(), + GetTextColor().ToFXColor(GetTransparency()), rcClip, + CFX_PointF(), pRange, pSysHandler, + m_pFormFiller.Get()); +} + +bool CPWL_Edit::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + + if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) { + if (m_bMouseDown && !InvalidateRect(nullptr)) + return true; + + m_bMouseDown = true; + SetCapture(); + + m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + } + + return true; +} + +bool CPWL_Edit::OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDblClk(point, nFlag); + + if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) { + m_pEdit->SelectAll(); + } + + return true; +} + +bool CPWL_Edit::OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) { + if (m_bMouseDown) + return false; + + CPWL_Wnd::OnRButtonUp(point, nFlag); + + if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point)) + return true; + + CFX_SystemHandler* pSH = GetSystemHandler(); + if (!pSH) + return false; + + SetFocus(); + + return false; +} + +void CPWL_Edit::OnSetFocus() { + ObservedPtr observed_ptr(this); + SetEditCaret(true); + if (!observed_ptr) + return; + + if (!IsReadOnly()) { + if (CPWL_Wnd::FocusHandlerIface* pFocusHandler = GetFocusHandler()) { + pFocusHandler->OnSetFocus(this); + if (!observed_ptr) + return; + } + } + m_bFocus = true; +} + +void CPWL_Edit::OnKillFocus() { + ObservedPtr observed_ptr(this); + + CPWL_ScrollBar* pScroll = GetVScrollBar(); + if (pScroll && pScroll->IsVisible()) { + pScroll->SetVisible(false); + if (!observed_ptr) + return; + + if (!Move(m_rcOldWindow, true, true)) + return; + } + + m_pEdit->SelectNone(); + if (!observed_ptr) + return; + + if (!SetCaret(false, CFX_PointF(), CFX_PointF())) + return; + + SetCharSet(FX_CHARSET_ANSI); + m_bFocus = false; +} + +void CPWL_Edit::SetCharSpace(float fCharSpace) { + m_pEdit->SetCharSpace(fCharSpace); +} + +CPVT_WordRange CPWL_Edit::GetSelectWordRange() const { + if (!m_pEdit->IsSelected()) + return CPVT_WordRange(); + + int32_t nStart = -1; + int32_t nEnd = -1; + + m_pEdit->GetSelection(nStart, nEnd); + + CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart); + CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd); + + return CPVT_WordRange(wpStart, wpEnd); +} + +CFX_PointF CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord) { + CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator(); + CPVT_WordPlace wpOld = pIterator->GetAt(); + pIterator->SetAt(wpWord); + + CFX_PointF pt; + CPVT_Word word; + if (pIterator->GetWord(word)) + pt = CFX_PointF(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent); + pIterator->SetAt(wpOld); + return pt; +} + +bool CPWL_Edit::IsTextFull() const { + return m_pEdit->IsTextFull(); +} + +float CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont, + const CFX_FloatRect& rcPlate, + int32_t nCharArray) { + if (!pFont || pFont->IsStandardFont()) + return 0.0f; + + FX_RECT rcBBox; + pFont->GetFontBBox(rcBBox); + + CFX_FloatRect rcCell = rcPlate; + float xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width(); + float ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height(); + + return xdiv < ydiv ? xdiv : ydiv; +} + +void CPWL_Edit::SetCharArray(int32_t nCharArray) { + if (!HasFlag(PES_CHARARRAY) || nCharArray <= 0) + return; + + m_pEdit->SetCharArray(nCharArray); + m_pEdit->SetTextOverflow(true, true); + + if (!HasFlag(PWS_AUTOFONTSIZE)) + return; + + IPVT_FontMap* pFontMap = GetFontMap(); + if (!pFontMap) + return; + + float fFontSize = GetCharArrayAutoFontSize(pFontMap->GetPDFFont(0), + GetClientRect(), nCharArray); + if (fFontSize <= 0.0f) + return; + + m_pEdit->SetAutoFontSize(false, true); + m_pEdit->SetFontSize(fFontSize); +} + +void CPWL_Edit::SetLimitChar(int32_t nLimitChar) { + m_pEdit->SetLimitChar(nLimitChar); +} + +void CPWL_Edit::ReplaceSel(const WideString& wsText) { + m_pEdit->ClearSelection(); + m_pEdit->InsertText(wsText, FX_CHARSET_Default); +} + +CFX_FloatRect CPWL_Edit::GetFocusRect() const { + return CFX_FloatRect(); +} + +bool CPWL_Edit::IsVScrollBarVisible() const { + CPWL_ScrollBar* pScroll = GetVScrollBar(); + return pScroll && pScroll->IsVisible(); +} + +bool CPWL_Edit::OnKeyDown(uint16_t nChar, uint32_t nFlag) { + if (m_bMouseDown) + return true; + + if (nChar == FWL_VKEY_Delete) { + if (m_pFillerNotify) { + WideString strChange; + WideString strChangeEx; + + int nSelStart = 0; + int nSelEnd = 0; + GetSelection(nSelStart, nSelEnd); + + if (nSelStart == nSelEnd) + nSelEnd = nSelStart + 1; + + CPWL_Wnd::ObservedPtr thisObserved(this); + + bool bRC; + bool bExit; + std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( + GetAttachedData(), strChange, strChangeEx, nSelStart, nSelEnd, true, + nFlag); + + if (!thisObserved) + return false; + + if (!bRC) + return false; + if (bExit) + return false; + } + } + + bool bRet = CPWL_EditCtrl::OnKeyDown(nChar, nFlag); + + // In case of implementation swallow the OnKeyDown event. + if (IsProceedtoOnChar(nChar, nFlag)) + return true; + + return bRet; +} + +// static +bool CPWL_Edit::IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag) { + bool bCtrl = IsCTRLpressed(nFlag); + bool bAlt = IsALTpressed(nFlag); + if (bCtrl && !bAlt) { + // hot keys for edit control. + switch (nKeyCode) { + case 'C': + case 'V': + case 'X': + case 'A': + case 'Z': + return true; + default: + break; + } + } + // control characters. + switch (nKeyCode) { + case FWL_VKEY_Escape: + case FWL_VKEY_Back: + case FWL_VKEY_Return: + case FWL_VKEY_Space: + return true; + default: + return false; + } +} + +bool CPWL_Edit::OnChar(uint16_t nChar, uint32_t nFlag) { + if (m_bMouseDown) + return true; + + bool bRC = true; + bool bExit = false; + + if (!IsCTRLpressed(nFlag)) { + if (m_pFillerNotify) { + WideString swChange; + + int nSelStart = 0; + int nSelEnd = 0; + GetSelection(nSelStart, nSelEnd); + + switch (nChar) { + case FWL_VKEY_Back: + if (nSelStart == nSelEnd) + nSelStart = nSelEnd - 1; + break; + case FWL_VKEY_Return: + break; + default: + swChange += nChar; + break; + } + + CPWL_Wnd::ObservedPtr thisObserved(this); + + WideString strChangeEx; + std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( + GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, true, + nFlag); + + if (!thisObserved) + return false; + } + } + + if (!bRC) + return true; + if (bExit) + return false; + + if (IPVT_FontMap* pFontMap = GetFontMap()) { + int32_t nOldCharSet = GetCharSet(); + int32_t nNewCharSet = + pFontMap->CharSetFromUnicode(nChar, FX_CHARSET_Default); + if (nOldCharSet != nNewCharSet) { + SetCharSet(nNewCharSet); + } + } + + return CPWL_EditCtrl::OnChar(nChar, nFlag); +} + +bool CPWL_Edit::OnMouseWheel(short zDelta, + const CFX_PointF& point, + uint32_t nFlag) { + if (!HasFlag(PES_MULTILINE)) + return false; + + CFX_PointF ptScroll = GetScrollPos(); + if (zDelta > 0) + ptScroll.y += GetFontSize(); + else + ptScroll.y -= GetFontSize(); + SetScrollPos(ptScroll); + return true; +} + +void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace) { + if (HasFlag(PES_SPELLCHECK)) { + m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), + GetLatinWordsRange(place))); + } +} + +void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace) { + if (HasFlag(PES_SPELLCHECK)) { + m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), + GetLatinWordsRange(place))); + } +} + +void CPWL_Edit::OnDelete(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace) { + if (HasFlag(PES_SPELLCHECK)) { + m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), + GetLatinWordsRange(place))); + } +} + +void CPWL_Edit::OnClear(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace) { + if (HasFlag(PES_SPELLCHECK)) { + m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), + GetLatinWordsRange(place))); + } +} + +void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace) { + if (HasFlag(PES_SPELLCHECK)) { + m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), + GetLatinWordsRange(place))); + } +} + +void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace) { + if (HasFlag(PES_SPELLCHECK)) { + m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace), + GetLatinWordsRange(place))); + } +} + +CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1, + const CPVT_WordRange& wr2) { + return CPVT_WordRange(std::min(wr1.BeginPos, wr2.BeginPos), + std::max(wr1.EndPos, wr2.EndPos)); +} + +CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CFX_PointF& point) const { + return GetSameWordsRange(m_pEdit->SearchWordPlace(point), true, false); +} + +CPVT_WordRange CPWL_Edit::GetLatinWordsRange( + const CPVT_WordPlace& place) const { + return GetSameWordsRange(place, true, false); +} + +#define PWL_ISARABICWORD(word) \ + ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC)) + +CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace& place, + bool bLatin, + bool bArabic) const { + CPVT_WordRange range; + + CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator(); + CPVT_Word wordinfo; + CPVT_WordPlace wpStart(place), wpEnd(place); + pIterator->SetAt(place); + + if (bLatin) { + while (pIterator->NextWord()) { + if (!pIterator->GetWord(wordinfo) || + !FX_EDIT_ISLATINWORD(wordinfo.Word)) { + break; + } + + wpEnd = pIterator->GetAt(); + } + } else if (bArabic) { + while (pIterator->NextWord()) { + if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word)) + break; + + wpEnd = pIterator->GetAt(); + } + } + + pIterator->SetAt(place); + + if (bLatin) { + do { + if (!pIterator->GetWord(wordinfo) || + !FX_EDIT_ISLATINWORD(wordinfo.Word)) { + break; + } + + wpStart = pIterator->GetAt(); + } while (pIterator->PrevWord()); + } else if (bArabic) { + do { + if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word)) + break; + + wpStart = pIterator->GetAt(); + } while (pIterator->PrevWord()); + } + + range.Set(wpStart, wpEnd); + return range; +} diff --git a/fpdfsdk/pwl/cpwl_edit.h b/fpdfsdk/pwl/cpwl_edit.h new file mode 100644 index 0000000000000000000000000000000000000000..3f9cd433f57328dddffceaaa04c000bbc1f963f0 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit.h @@ -0,0 +1,134 @@ +// 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 FPDFSDK_PWL_CPWL_EDIT_H_ +#define FPDFSDK_PWL_CPWL_EDIT_H_ + +#include + +#include "core/fpdfdoc/cpvt_wordrange.h" +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" + +#define PWL_CLASSNAME_EDIT "CPWL_Edit" + +class IPWL_Filler_Notify { + public: + virtual ~IPWL_Filler_Notify() {} + + // Must write to |bBottom| and |fPopupRet|. + virtual void QueryWherePopup(CPWL_Wnd::PrivateData* pAttached, + float fPopupMin, + float fPopupMax, + bool* bBottom, + float* fPopupRet) = 0; + virtual std::pair OnBeforeKeyStroke( + CPWL_Wnd::PrivateData* pAttached, + WideString& strChange, + const WideString& strChangeEx, + int nSelStart, + int nSelEnd, + bool bKeyDown, + uint32_t nFlag) = 0; +#ifdef PDF_ENABLE_XFA + virtual bool OnPopupPreOpen(CPWL_Wnd::PrivateData* pAttached, + uint32_t nFlag) = 0; + virtual bool OnPopupPostOpen(CPWL_Wnd::PrivateData* pAttached, + uint32_t nFlag) = 0; +#endif // PDF_ENABLE_XFA +}; + +class CPWL_Edit : public CPWL_EditCtrl { + public: + CPWL_Edit(); + ~CPWL_Edit() override; + + // CPWL_EditCtrl + ByteString GetClassName() const override; + void OnCreated() override; + bool RePosChildWnd() override; + CFX_FloatRect GetClientRect() const override; + void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) override; + bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnMouseWheel(short zDelta, + const CFX_PointF& point, + uint32_t nFlag) override; + bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + CFX_FloatRect GetFocusRect() const override; + void OnSetFocus() override; + void OnKillFocus() override; + + void SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat = PEAV_TOP, + bool bPaint = true); // 0:top 1:bottom 2:center + + void SetCharArray(int32_t nCharArray); + void SetLimitChar(int32_t nLimitChar); + + void SetCharSpace(float fCharSpace); + + bool CanSelectAll() const; + bool CanCopy() const; + bool CanCut() const; + + void CutText(); + + void SetText(const WideString& csText); + void ReplaceSel(const WideString& csText); + + bool IsTextFull() const; + + static float GetCharArrayAutoFontSize(CPDF_Font* pFont, + const CFX_FloatRect& rcPlate, + int32_t nCharArray); + + void SetFillerNotify(IPWL_Filler_Notify* pNotify) { + m_pFillerNotify = pNotify; + } + + void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; } + + void OnInsertWord(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace); + void OnInsertReturn(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace); + void OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace); + void OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace); + void OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace); + void OnInsertText(const CPVT_WordPlace& place, + const CPVT_WordPlace& oldplace); + + private: + // In case of implementation swallow the OnKeyDown event. If the event is + // swallowed, implementation may do other unexpected things, which is not the + // control means to do. + static bool IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag); + + CPVT_WordRange GetSelectWordRange() const; + bool IsVScrollBarVisible() const; + void SetParamByFlag(); + + float GetCharArrayAutoFontSize(int32_t nCharArray); + CFX_PointF GetWordRightBottomPoint(const CPVT_WordPlace& wpWord); + + CPVT_WordRange CombineWordRange(const CPVT_WordRange& wr1, + const CPVT_WordRange& wr2); + CPVT_WordRange GetLatinWordsRange(const CFX_PointF& point) const; + CPVT_WordRange GetLatinWordsRange(const CPVT_WordPlace& place) const; + CPVT_WordRange GetSameWordsRange(const CPVT_WordPlace& place, + bool bLatin, + bool bArabic) const; + + bool m_bFocus; + CFX_FloatRect m_rcOldWindow; + UnownedPtr m_pFillerNotify; + UnownedPtr m_pFormFiller; +}; + +#endif // FPDFSDK_PWL_CPWL_EDIT_H_ diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06b5dedbf0718c46256d320c042d23916f72445c --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp @@ -0,0 +1,431 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" + +#include "core/fpdfdoc/cpvt_word.h" +#include "core/fxge/fx_font.h" +#include "fpdfsdk/pwl/cpwl_caret.h" +#include "fpdfsdk/pwl/cpwl_edit_impl.h" +#include "fpdfsdk/pwl/cpwl_font_map.h" +#include "fpdfsdk/pwl/cpwl_scroll_bar.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "public/fpdf_fwlevent.h" + +CPWL_EditCtrl::CPWL_EditCtrl() + : m_pEdit(new CPWL_EditImpl), + m_pEditCaret(nullptr), + m_bMouseDown(false), + m_nCharSet(FX_CHARSET_Default) {} + +CPWL_EditCtrl::~CPWL_EditCtrl() {} + +void CPWL_EditCtrl::OnCreate(CreateParams* pParamsToAdjust) { + pParamsToAdjust->eCursorType = FXCT_VBEAM; +} + +void CPWL_EditCtrl::OnCreated() { + SetFontSize(GetCreationParams().fFontSize); + + m_pEdit->SetFontMap(GetFontMap()); + m_pEdit->SetNotify(this); + m_pEdit->Initialize(); +} + +bool CPWL_EditCtrl::IsWndHorV() { + CFX_Matrix mt = GetWindowMatrix(); + return mt.Transform(CFX_PointF(1, 1)).y == mt.Transform(CFX_PointF(0, 1)).y; +} + +void CPWL_EditCtrl::SetCursor() { + if (IsValid()) { + if (CFX_SystemHandler* pSH = GetSystemHandler()) { + if (IsWndHorV()) + pSH->SetCursor(FXCT_VBEAM); + else + pSH->SetCursor(FXCT_HBEAM); + } + } +} + +WideString CPWL_EditCtrl::GetSelectedText() { + if (m_pEdit) + return m_pEdit->GetSelectedText(); + + return WideString(); +} + +void CPWL_EditCtrl::ReplaceSelection(const WideString& text) { + if (!m_pEdit) + return; + + m_pEdit->ClearSelection(); + m_pEdit->InsertText(text, FX_CHARSET_Default); +} + +bool CPWL_EditCtrl::RePosChildWnd() { + m_pEdit->SetPlateRect(GetClientRect()); + return true; +} + +void CPWL_EditCtrl::SetScrollInfo(const PWL_SCROLL_INFO& info) { + if (CPWL_Wnd* pChild = GetVScrollBar()) + pChild->SetScrollInfo(info); +} + +void CPWL_EditCtrl::SetScrollPosition(float pos) { + if (CPWL_Wnd* pChild = GetVScrollBar()) + pChild->SetScrollPosition(pos); +} + +void CPWL_EditCtrl::ScrollWindowVertically(float pos) { + m_pEdit->SetScrollPos(CFX_PointF(m_pEdit->GetScrollPos().x, pos)); +} + +void CPWL_EditCtrl::CreateChildWnd(const CreateParams& cp) { + if (!IsReadOnly()) + CreateEditCaret(cp); +} + +void CPWL_EditCtrl::CreateEditCaret(const CreateParams& cp) { + if (m_pEditCaret) + return; + + m_pEditCaret = new CPWL_Caret; + m_pEditCaret->SetInvalidRect(GetClientRect()); + + CreateParams ecp = cp; + ecp.pParentWnd = this; + ecp.dwFlags = PWS_CHILD | PWS_NOREFRESHCLIP; + ecp.dwBorderWidth = 0; + ecp.nBorderStyle = BorderStyle::SOLID; + ecp.rcRectWnd = CFX_FloatRect(); + + m_pEditCaret->Create(ecp); +} + +void CPWL_EditCtrl::SetFontSize(float fFontSize) { + m_pEdit->SetFontSize(fFontSize); +} + +float CPWL_EditCtrl::GetFontSize() const { + return m_pEdit->GetFontSize(); +} + +bool CPWL_EditCtrl::OnKeyDown(uint16_t nChar, uint32_t nFlag) { + if (m_bMouseDown) + return true; + + bool bRet = CPWL_Wnd::OnKeyDown(nChar, nFlag); + + // FILTER + switch (nChar) { + default: + return false; + case FWL_VKEY_Delete: + case FWL_VKEY_Up: + case FWL_VKEY_Down: + case FWL_VKEY_Left: + case FWL_VKEY_Right: + case FWL_VKEY_Home: + case FWL_VKEY_End: + case FWL_VKEY_Insert: + case 'C': + case 'V': + case 'X': + case 'A': + case 'Z': + case 'c': + case 'v': + case 'x': + case 'a': + case 'z': + break; + } + + if (nChar == FWL_VKEY_Delete && m_pEdit->IsSelected()) + nChar = FWL_VKEY_Unknown; + + switch (nChar) { + case FWL_VKEY_Delete: + Delete(); + return true; + case FWL_VKEY_Insert: + if (IsSHIFTpressed(nFlag)) + PasteText(); + return true; + case FWL_VKEY_Up: + m_pEdit->OnVK_UP(IsSHIFTpressed(nFlag), false); + return true; + case FWL_VKEY_Down: + m_pEdit->OnVK_DOWN(IsSHIFTpressed(nFlag), false); + return true; + case FWL_VKEY_Left: + m_pEdit->OnVK_LEFT(IsSHIFTpressed(nFlag), false); + return true; + case FWL_VKEY_Right: + m_pEdit->OnVK_RIGHT(IsSHIFTpressed(nFlag), false); + return true; + case FWL_VKEY_Home: + m_pEdit->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + return true; + case FWL_VKEY_End: + m_pEdit->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + return true; + case FWL_VKEY_Unknown: + if (!IsSHIFTpressed(nFlag)) + ClearSelection(); + else + CutText(); + return true; + default: + break; + } + + return bRet; +} + +bool CPWL_EditCtrl::OnChar(uint16_t nChar, uint32_t nFlag) { + if (m_bMouseDown) + return true; + + CPWL_Wnd::OnChar(nChar, nFlag); + + // FILTER + switch (nChar) { + case 0x0A: + case 0x1B: + return false; + default: + break; + } + + bool bCtrl = IsCTRLpressed(nFlag); + bool bAlt = IsALTpressed(nFlag); + bool bShift = IsSHIFTpressed(nFlag); + + uint16_t word = nChar; + + if (bCtrl && !bAlt) { + switch (nChar) { + case 'C' - 'A' + 1: + CopyText(); + return true; + case 'V' - 'A' + 1: + PasteText(); + return true; + case 'X' - 'A' + 1: + CutText(); + return true; + case 'A' - 'A' + 1: + SelectAll(); + return true; + case 'Z' - 'A' + 1: + if (bShift) + Redo(); + else + Undo(); + return true; + default: + if (nChar < 32) + return false; + } + } + + if (IsReadOnly()) + return true; + + if (m_pEdit->IsSelected() && word == FWL_VKEY_Back) + word = FWL_VKEY_Unknown; + + ClearSelection(); + + switch (word) { + case FWL_VKEY_Back: + Backspace(); + break; + case FWL_VKEY_Return: + InsertReturn(); + break; + case FWL_VKEY_Unknown: + break; + default: + InsertWord(word, GetCharSet()); + break; + } + + return true; +} + +bool CPWL_EditCtrl::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + + if (ClientHitTest(point)) { + if (m_bMouseDown && !InvalidateRect(nullptr)) + return true; + + m_bMouseDown = true; + SetCapture(); + + m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + } + + return true; +} + +bool CPWL_EditCtrl::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + + if (m_bMouseDown) { + // can receive keybord message + if (ClientHitTest(point) && !IsFocused()) + SetFocus(); + + ReleaseCapture(); + m_bMouseDown = false; + } + + return true; +} + +bool CPWL_EditCtrl::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnMouseMove(point, nFlag); + + if (m_bMouseDown) + m_pEdit->OnMouseMove(point, false, false); + + return true; +} + +void CPWL_EditCtrl::SetEditCaret(bool bVisible) { + CFX_PointF ptHead; + CFX_PointF ptFoot; + if (bVisible) + GetCaretInfo(&ptHead, &ptFoot); + + SetCaret(bVisible, ptHead, ptFoot); + // Note, |this| may no longer be viable at this point. If more work needs to + // be done, check the return value of SetCaret(). +} + +void CPWL_EditCtrl::GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const { + CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator(); + pIterator->SetAt(m_pEdit->GetCaret()); + CPVT_Word word; + CPVT_Line line; + if (pIterator->GetWord(word)) { + ptHead->x = word.ptWord.x + word.fWidth; + ptHead->y = word.ptWord.y + word.fAscent; + ptFoot->x = word.ptWord.x + word.fWidth; + ptFoot->y = word.ptWord.y + word.fDescent; + } else if (pIterator->GetLine(line)) { + ptHead->x = line.ptLine.x; + ptHead->y = line.ptLine.y + line.fLineAscent; + ptFoot->x = line.ptLine.x; + ptFoot->y = line.ptLine.y + line.fLineDescent; + } +} + +bool CPWL_EditCtrl::SetCaret(bool bVisible, + const CFX_PointF& ptHead, + const CFX_PointF& ptFoot) { + if (!m_pEditCaret) + return true; + + if (!IsFocused() || m_pEdit->IsSelected()) + bVisible = false; + + ObservedPtr thisObserved(this); + m_pEditCaret->SetCaret(bVisible, ptHead, ptFoot); + if (!thisObserved) + return false; + + return true; +} + +WideString CPWL_EditCtrl::GetText() const { + return m_pEdit->GetText(); +} + +void CPWL_EditCtrl::SetSelection(int32_t nStartChar, int32_t nEndChar) { + m_pEdit->SetSelection(nStartChar, nEndChar); +} + +void CPWL_EditCtrl::GetSelection(int32_t& nStartChar, int32_t& nEndChar) const { + m_pEdit->GetSelection(nStartChar, nEndChar); +} + +void CPWL_EditCtrl::ClearSelection() { + if (!IsReadOnly()) + m_pEdit->ClearSelection(); +} + +void CPWL_EditCtrl::SelectAll() { + m_pEdit->SelectAll(); +} + +void CPWL_EditCtrl::SetScrollPos(const CFX_PointF& point) { + m_pEdit->SetScrollPos(point); +} + +CFX_PointF CPWL_EditCtrl::GetScrollPos() const { + return m_pEdit->GetScrollPos(); +} + +void CPWL_EditCtrl::CopyText() {} + +void CPWL_EditCtrl::PasteText() {} + +void CPWL_EditCtrl::CutText() {} + +void CPWL_EditCtrl::InsertWord(uint16_t word, int32_t nCharset) { + if (!IsReadOnly()) + m_pEdit->InsertWord(word, nCharset); +} + +void CPWL_EditCtrl::InsertReturn() { + if (!IsReadOnly()) + m_pEdit->InsertReturn(); +} + +void CPWL_EditCtrl::Delete() { + if (!IsReadOnly()) + m_pEdit->Delete(); +} + +void CPWL_EditCtrl::Backspace() { + if (!IsReadOnly()) + m_pEdit->Backspace(); +} + +bool CPWL_EditCtrl::CanUndo() const { + return !IsReadOnly() && m_pEdit->CanUndo(); +} + +bool CPWL_EditCtrl::CanRedo() const { + return !IsReadOnly() && m_pEdit->CanRedo(); +} + +void CPWL_EditCtrl::Redo() { + if (CanRedo()) + m_pEdit->Redo(); +} + +void CPWL_EditCtrl::Undo() { + if (CanUndo()) + m_pEdit->Undo(); +} + +int32_t CPWL_EditCtrl::GetCharSet() const { + return m_nCharSet < 0 ? FX_CHARSET_Default : m_nCharSet; +} + +void CPWL_EditCtrl::SetReadyToInput() { + if (m_bMouseDown) { + ReleaseCapture(); + m_bMouseDown = false; + } +} diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.h b/fpdfsdk/pwl/cpwl_edit_ctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..31140e30387f2bc0e1f8d26ea7eec4ece21747a3 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.h @@ -0,0 +1,96 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_PWL_CPWL_EDIT_CTRL_H_ +#define FPDFSDK_PWL_CPWL_EDIT_CTRL_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_EditImpl; +class CPWL_Caret; +struct CPVT_WordPlace; + +enum PWL_EDIT_ALIGNFORMAT_H { PEAH_LEFT = 0, PEAH_MIDDLE, PEAH_RIGHT }; + +enum PWL_EDIT_ALIGNFORMAT_V { PEAV_TOP = 0, PEAV_CENTER, PEAV_BOTTOM }; + +class CPWL_EditCtrl : public CPWL_Wnd { + public: + CPWL_EditCtrl(); + ~CPWL_EditCtrl() override; + + WideString GetText() const; + void SetSelection(int32_t nStartChar, int32_t nEndChar); + void GetSelection(int32_t& nStartChar, int32_t& nEndChar) const; + void ClearSelection(); + void SelectAll(); + + CFX_PointF GetScrollPos() const; + void SetScrollPos(const CFX_PointF& point); + + void SetCharSet(uint8_t nCharSet) { m_nCharSet = nCharSet; } + int32_t GetCharSet() const; + + bool CanUndo() const; + bool CanRedo() const; + void Redo(); + void Undo(); + + void SetReadyToInput(); + + // CPWL_Wnd: + void OnCreate(CreateParams* pParamsToAdjust) override; + void OnCreated() override; + bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; + void SetScrollInfo(const PWL_SCROLL_INFO& info) override; + void SetScrollPosition(float pos) override; + void ScrollWindowVertically(float pos) override; + void CreateChildWnd(const CreateParams& cp) override; + bool RePosChildWnd() override; + void SetFontSize(float fFontSize) override; + float GetFontSize() const override; + void SetCursor() override; + WideString GetSelectedText() override; + void ReplaceSelection(const WideString& text) override; + + bool SetCaret(bool bVisible, + const CFX_PointF& ptHead, + const CFX_PointF& ptFoot); + + protected: + void CopyText(); + void PasteText(); + void CutText(); + void InsertWord(uint16_t word, int32_t nCharset); + void InsertReturn(); + + bool IsWndHorV(); + + void Delete(); + void Backspace(); + + void GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const; + + void SetEditCaret(bool bVisible); + + std::unique_ptr m_pEdit; + CPWL_Caret* m_pEditCaret; + bool m_bMouseDown; + + private: + void CreateEditCaret(const CreateParams& cp); + + int32_t m_nCharSet; +}; + +#endif // FPDFSDK_PWL_CPWL_EDIT_CTRL_H_ diff --git a/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3f0d5dc0ebd454369ecc3dcb695dbb3554e2112 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp @@ -0,0 +1,421 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fpdfsdk/cba_annotiterator.h" +#include "fpdfsdk/cpdfsdk_annot.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/formfiller/cffl_formfiller.h" +#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CPWLEditEmbeddertest : public EmbedderTest { + protected: + void SetUp() override { + EmbedderTest::SetUp(); + CreateAndInitializeFormPDF(); + } + + void TearDown() override { + UnloadPage(GetPage()); + EmbedderTest::TearDown(); + } + + void CreateAndInitializeFormPDF() { + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + m_page = LoadPage(0); + ASSERT_TRUE(m_page); + + m_pFormFillEnv = static_cast(form_handle()); + CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0), + CPDF_Annot::Subtype::WIDGET); + // Normal text field. + m_pAnnot = iter.GetFirstAnnot(); + ASSERT_TRUE(m_pAnnot); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype()); + + // Read-only text field. + CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnot); + + // Pre-filled text field with char limit of 10. + m_pAnnotCharLimit = iter.GetNextAnnot(pAnnotReadOnly); + ASSERT_TRUE(m_pAnnotCharLimit); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, + m_pAnnotCharLimit->GetAnnotSubtype()); + CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); + ASSERT_EQ(m_pAnnotCharLimit, pLastAnnot); + } + + void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotTextField) { + CFFL_InteractiveFormFiller* pInteractiveFormFiller = + m_pFormFillEnv->GetInteractiveFormFiller(); + { + CPDFSDK_Annot::ObservedPtr pObserved(pAnnotTextField); + EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0)); + } + + m_pFormFiller = + pInteractiveFormFiller->GetFormFiller(pAnnotTextField, false); + ASSERT_TRUE(m_pFormFiller); + + CPWL_Wnd* pWindow = + m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false); + ASSERT_TRUE(pWindow); + ASSERT_EQ(PWL_CLASSNAME_EDIT, pWindow->GetClassName()); + + m_pEdit = static_cast(pWindow); + } + + void TypeTextIntoTextField(int num_chars) { + // Type text starting with 'A' to as many chars as specified by |num_chars|. + for (int i = 0; i < num_chars; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + } + + FPDF_PAGE GetPage() { return m_page; } + CPWL_Edit* GetCPWLEdit() { return m_pEdit; } + CFFL_FormFiller* GetCFFLFormFiller() { return m_pFormFiller; } + CPDFSDK_Annot* GetCPDFSDKAnnot() { return m_pAnnot; } + CPDFSDK_Annot* GetCPDFSDKAnnotCharLimit() { return m_pAnnotCharLimit; } + + private: + FPDF_PAGE m_page; + CPWL_Edit* m_pEdit; + CFFL_FormFiller* m_pFormFiller; + CPDFSDK_Annot* m_pAnnot; + CPDFSDK_Annot* m_pAnnotCharLimit; + CPDFSDK_FormFillEnvironment* m_pFormFillEnv; +}; + +TEST_F(CPWLEditEmbeddertest, TypeText) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0)); + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0)); + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'c', 0)); + + EXPECT_STREQ(L"abc", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, GetSelectedTextEmptyAndBasic) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + // Attempt to set selection before text has been typed to test that + // selection is identified as empty. + // + // Select from character index [0, 3) within form text field. + GetCPWLEdit()->SetSelection(0, 3); + EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty()); + + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0)); + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0)); + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'c', 0)); + GetCPWLEdit()->SetSelection(0, 2); + + EXPECT_STREQ(L"ab", GetCPWLEdit()->GetSelectedText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, GetSelectedTextFragments) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(50); + + GetCPWLEdit()->SetSelection(0, 0); + EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty()); + + GetCPWLEdit()->SetSelection(0, 1); + EXPECT_STREQ(L"A", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->SetSelection(-8, -1); + EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty()); + + GetCPWLEdit()->SetSelection(23, 12); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->SetSelection(12, 23); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->SetSelection(49, 50); + EXPECT_STREQ(L"r", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->SetSelection(49, 55); + EXPECT_STREQ(L"r", GetCPWLEdit()->GetSelectedText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteEntireTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(50); + + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->ReplaceSelection(L""); + EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(50); + + GetCPWLEdit()->SetSelection(12, 23); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->ReplaceSelection(L""); + EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(50); + + GetCPWLEdit()->SetSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->ReplaceSelection(L""); + EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(50); + + GetCPWLEdit()->SetSelection(45, 50); + EXPECT_STREQ(L"nopqr", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->ReplaceSelection(L""); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteEmptyTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(50); + + GetCPWLEdit()->ReplaceSelection(L""); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyTextField) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + // Move cursor to beginning of text field. + EXPECT_TRUE( + GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Home, 0)); + + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + // Move cursor to middle of text field. + for (int i = 0; i < 5; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Left, 0)); + } + + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"HelloFGHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(2, 7); + EXPECT_STREQ(L"CDEFG", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABHelloHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(5, 10); + EXPECT_STREQ(L"FGHIJ", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hello"); + EXPECT_STREQ(L"ABCDEHello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldOverflow) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L""); + + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldFit) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L""); + + GetCPWLEdit()->ReplaceSelection(L"Zebra"); + EXPECT_STREQ(L"Zebra", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"HiElephant", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + // Move cursor to middle of text field. + for (int i = 0; i < 5; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(), + FWL_VKEY_Right, 0)); + } + + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"ElephHiant", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + // Move cursor to end of text field. + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(), + FWL_VKEY_End, 0)); + + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"ElephantHi", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, 4); + EXPECT_STREQ(L"Elep", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"Hippophant", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(2, 6); + EXPECT_STREQ(L"epha", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"ElHippopnt", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(4, 8); + EXPECT_STREQ(L"hant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(L"Hippopotamus"); + EXPECT_STREQ(L"ElepHippop", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithEndCarriageFeed) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\r"); + EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithEndNewline) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\n"); + EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithEndCarriageFeedAndNewLine) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\r\n"); + EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithEndNewLineAndCarriageFeed) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\n\r"); + EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithBodyCarriageFeed) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\rBar"); + EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithBodyNewline) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\nBar"); + EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithBodyCarriageFeedAndNewLine) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\r\nBar"); + EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, SetTextWithBodyNewLineAndCarriageFeed) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->SetText(L"Foo\n\rBar"); + EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str()); +} diff --git a/fpdfsdk/pwl/cpwl_edit_impl.cpp b/fpdfsdk/pwl/cpwl_edit_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2a7b1dddfa060e6a16729a046597f1a322daf82 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_impl.cpp @@ -0,0 +1,1899 @@ +// 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 "fpdfsdk/pwl/cpwl_edit_impl.h" + +#include +#include +#include +#include + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fpdfapi/page/cpdf_pageobjectholder.h" +#include "core/fpdfapi/page/cpdf_pathobject.h" +#include "core/fpdfapi/page/cpdf_textobject.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fpdfapi/render/cpdf_renderoptions.h" +#include "core/fpdfapi/render/cpdf_textrenderer.h" +#include "core/fpdfdoc/cpvt_word.h" +#include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "fpdfsdk/cfx_systemhandler.h" +#include "fpdfsdk/pwl/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" +#include "fpdfsdk/pwl/cpwl_scroll_bar.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +const int kEditUndoMaxItems = 10000; + +void DrawTextString(CFX_RenderDevice* pDevice, + const CFX_PointF& pt, + CPDF_Font* pFont, + float fFontSize, + const CFX_Matrix& mtUser2Device, + const ByteString& str, + FX_ARGB crTextFill, + int32_t nHorzScale) { + if (!pFont) + return; + + CFX_PointF pos = mtUser2Device.Transform(pt); + CFX_Matrix mt; + if (nHorzScale == 100) { + mt = mtUser2Device; + } else { + mt = CFX_Matrix(nHorzScale / 100.0f, 0, 0, 1, 0, 0); + mt.Concat(mtUser2Device); + } + + CPDF_RenderOptions ro; + ro.SetFlags(RENDER_CLEARTYPE); + + ro.SetColorMode(CPDF_RenderOptions::kNormal); + CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize, + &mt, str, crTextFill, nullptr, &ro); +} + +} // namespace + +CPWL_EditImpl_Iterator::CPWL_EditImpl_Iterator( + CPWL_EditImpl* pEdit, + CPDF_VariableText::Iterator* pVTIterator) + : m_pEdit(pEdit), m_pVTIterator(pVTIterator) {} + +CPWL_EditImpl_Iterator::~CPWL_EditImpl_Iterator() {} + +bool CPWL_EditImpl_Iterator::NextWord() { + return m_pVTIterator->NextWord(); +} + +bool CPWL_EditImpl_Iterator::PrevWord() { + return m_pVTIterator->PrevWord(); +} + +bool CPWL_EditImpl_Iterator::GetWord(CPVT_Word& word) const { + ASSERT(m_pEdit); + + if (m_pVTIterator->GetWord(word)) { + word.ptWord = m_pEdit->VTToEdit(word.ptWord); + return true; + } + return false; +} + +bool CPWL_EditImpl_Iterator::GetLine(CPVT_Line& line) const { + ASSERT(m_pEdit); + + if (m_pVTIterator->GetLine(line)) { + line.ptLine = m_pEdit->VTToEdit(line.ptLine); + return true; + } + return false; +} + +void CPWL_EditImpl_Iterator::SetAt(int32_t nWordIndex) { + m_pVTIterator->SetAt(nWordIndex); +} + +void CPWL_EditImpl_Iterator::SetAt(const CPVT_WordPlace& place) { + m_pVTIterator->SetAt(place); +} + +const CPVT_WordPlace& CPWL_EditImpl_Iterator::GetAt() const { + return m_pVTIterator->GetWordPlace(); +} + +CPWL_EditImpl_Provider::CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap) + : CPDF_VariableText::Provider(pFontMap), m_pFontMap(pFontMap) { + ASSERT(m_pFontMap); +} + +CPWL_EditImpl_Provider::~CPWL_EditImpl_Provider() {} + +IPVT_FontMap* CPWL_EditImpl_Provider::GetFontMap() const { + return m_pFontMap; +} + +int32_t CPWL_EditImpl_Provider::GetCharWidth(int32_t nFontIndex, + uint16_t word) { + if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) { + uint32_t charcode = word; + + if (pPDFFont->IsUnicodeCompatible()) + charcode = pPDFFont->CharCodeFromUnicode(word); + else + charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word); + + if (charcode != CPDF_Font::kInvalidCharCode) + return pPDFFont->GetCharWidthF(charcode); + } + + return 0; +} + +int32_t CPWL_EditImpl_Provider::GetTypeAscent(int32_t nFontIndex) { + if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) + return pPDFFont->GetTypeAscent(); + + return 0; +} + +int32_t CPWL_EditImpl_Provider::GetTypeDescent(int32_t nFontIndex) { + if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) + return pPDFFont->GetTypeDescent(); + + return 0; +} + +int32_t CPWL_EditImpl_Provider::GetWordFontIndex(uint16_t word, + int32_t charset, + int32_t nFontIndex) { + return m_pFontMap->GetWordFontIndex(word, charset, nFontIndex); +} + +int32_t CPWL_EditImpl_Provider::GetDefaultFontIndex() { + return 0; +} + +bool CPWL_EditImpl_Provider::IsLatinWord(uint16_t word) { + return FX_EDIT_ISLATINWORD(word); +} + +CPWL_EditImpl_Refresh::CPWL_EditImpl_Refresh() {} + +CPWL_EditImpl_Refresh::~CPWL_EditImpl_Refresh() {} + +void CPWL_EditImpl_Refresh::BeginRefresh() { + m_RefreshRects.clear(); + m_OldLineRects = std::move(m_NewLineRects); +} + +void CPWL_EditImpl_Refresh::Push(const CPVT_WordRange& linerange, + const CFX_FloatRect& rect) { + m_NewLineRects.emplace_back(CPWL_EditImpl_LineRect(linerange, rect)); +} + +void CPWL_EditImpl_Refresh::NoAnalyse() { + for (const auto& lineRect : m_OldLineRects) + Add(lineRect.m_rcLine); + + for (const auto& lineRect : m_NewLineRects) + Add(lineRect.m_rcLine); +} + +std::vector* CPWL_EditImpl_Refresh::GetRefreshRects() { + return &m_RefreshRects; +} + +void CPWL_EditImpl_Refresh::EndRefresh() { + m_RefreshRects.clear(); +} + +void CPWL_EditImpl_Refresh::Add(const CFX_FloatRect& new_rect) { + // Check for overlapped area. + for (const auto& rect : m_RefreshRects) { + if (rect.Contains(new_rect)) + return; + } + m_RefreshRects.emplace_back(CFX_FloatRect(new_rect)); +} + +CPWL_EditImpl_Undo::CPWL_EditImpl_Undo() + : m_nCurUndoPos(0), m_bWorking(false) {} + +CPWL_EditImpl_Undo::~CPWL_EditImpl_Undo() {} + +bool CPWL_EditImpl_Undo::CanUndo() const { + return m_nCurUndoPos > 0; +} + +void CPWL_EditImpl_Undo::Undo() { + m_bWorking = true; + if (CanUndo()) { + m_UndoItemStack[m_nCurUndoPos - 1]->Undo(); + m_nCurUndoPos--; + } + m_bWorking = false; +} + +bool CPWL_EditImpl_Undo::CanRedo() const { + return m_nCurUndoPos < m_UndoItemStack.size(); +} + +void CPWL_EditImpl_Undo::Redo() { + m_bWorking = true; + if (CanRedo()) { + m_UndoItemStack[m_nCurUndoPos]->Redo(); + m_nCurUndoPos++; + } + m_bWorking = false; +} + +void CPWL_EditImpl_Undo::AddItem(std::unique_ptr pItem) { + ASSERT(!m_bWorking); + ASSERT(pItem); + if (CanRedo()) + RemoveTails(); + + if (m_UndoItemStack.size() >= kEditUndoMaxItems) + RemoveHeads(); + + m_UndoItemStack.push_back(std::move(pItem)); + m_nCurUndoPos = m_UndoItemStack.size(); +} + +void CPWL_EditImpl_Undo::RemoveHeads() { + ASSERT(m_UndoItemStack.size() > 1); + m_UndoItemStack.pop_front(); +} + +void CPWL_EditImpl_Undo::RemoveTails() { + while (CanRedo()) + m_UndoItemStack.pop_back(); +} + +CFXEU_InsertWord::CFXEU_InsertWord(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset) + : m_pEdit(pEdit), + m_wpOld(wpOldPlace), + m_wpNew(wpNewPlace), + m_Word(word), + m_nCharset(charset) { + ASSERT(m_pEdit); +} + +CFXEU_InsertWord::~CFXEU_InsertWord() {} + +void CFXEU_InsertWord::Redo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpOld); + m_pEdit->InsertWord(m_Word, m_nCharset, false, true); +} + +void CFXEU_InsertWord::Undo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpNew); + m_pEdit->Backspace(false, true); +} + +CFXEU_InsertReturn::CFXEU_InsertReturn(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace) + : m_pEdit(pEdit), m_wpOld(wpOldPlace), m_wpNew(wpNewPlace) { + ASSERT(m_pEdit); +} + +CFXEU_InsertReturn::~CFXEU_InsertReturn() {} + +void CFXEU_InsertReturn::Redo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpOld); + m_pEdit->InsertReturn(false, true); +} + +void CFXEU_InsertReturn::Undo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpNew); + m_pEdit->Backspace(false, true); +} + +CFXEU_Backspace::CFXEU_Backspace(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset) + : m_pEdit(pEdit), + m_wpOld(wpOldPlace), + m_wpNew(wpNewPlace), + m_Word(word), + m_nCharset(charset) { + ASSERT(m_pEdit); +} + +CFXEU_Backspace::~CFXEU_Backspace() {} + +void CFXEU_Backspace::Redo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpOld); + m_pEdit->Backspace(false, true); +} + +void CFXEU_Backspace::Undo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpNew); + if (m_wpNew.nSecIndex != m_wpOld.nSecIndex) + m_pEdit->InsertReturn(false, true); + else + m_pEdit->InsertWord(m_Word, m_nCharset, false, true); +} + +CFXEU_Delete::CFXEU_Delete(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset, + bool bSecEnd) + : m_pEdit(pEdit), + m_wpOld(wpOldPlace), + m_wpNew(wpNewPlace), + m_Word(word), + m_nCharset(charset), + m_bSecEnd(bSecEnd) { + ASSERT(m_pEdit); +} + +CFXEU_Delete::~CFXEU_Delete() {} + +void CFXEU_Delete::Redo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpOld); + m_pEdit->Delete(false, true); +} + +void CFXEU_Delete::Undo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpNew); + if (m_bSecEnd) + m_pEdit->InsertReturn(false, true); + else + m_pEdit->InsertWord(m_Word, m_nCharset, false, true); +} + +CFXEU_Clear::CFXEU_Clear(CPWL_EditImpl* pEdit, + const CPVT_WordRange& wrSel, + const WideString& swText) + : m_pEdit(pEdit), m_wrSel(wrSel), m_swText(swText) { + ASSERT(m_pEdit); +} + +CFXEU_Clear::~CFXEU_Clear() {} + +void CFXEU_Clear::Redo() { + m_pEdit->SelectNone(); + m_pEdit->SetSelection(m_wrSel.BeginPos, m_wrSel.EndPos); + m_pEdit->Clear(false, true); +} + +void CFXEU_Clear::Undo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wrSel.BeginPos); + m_pEdit->InsertText(m_swText, FX_CHARSET_Default, false, true); + m_pEdit->SetSelection(m_wrSel.BeginPos, m_wrSel.EndPos); +} + +CFXEU_InsertText::CFXEU_InsertText(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + const WideString& swText, + int32_t charset) + : m_pEdit(pEdit), + m_wpOld(wpOldPlace), + m_wpNew(wpNewPlace), + m_swText(swText), + m_nCharset(charset) { + ASSERT(m_pEdit); +} + +CFXEU_InsertText::~CFXEU_InsertText() {} + +void CFXEU_InsertText::Redo() { + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpOld); + m_pEdit->InsertText(m_swText, m_nCharset, false, true); +} + +void CFXEU_InsertText::Undo() { + m_pEdit->SelectNone(); + m_pEdit->SetSelection(m_wpOld, m_wpNew); + m_pEdit->Clear(false, true); +} + +// static +void CPWL_EditImpl::DrawEdit(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device, + CPWL_EditImpl* pEdit, + FX_COLORREF crTextFill, + const CFX_FloatRect& rcClip, + const CFX_PointF& ptOffset, + const CPVT_WordRange* pRange, + CFX_SystemHandler* pSystemHandler, + CFFL_FormFiller* pFFLData) { + const bool bContinuous = + pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f; + uint16_t SubWord = pEdit->GetPasswordChar(); + float fFontSize = pEdit->GetFontSize(); + CPVT_WordRange wrSelect = pEdit->GetSelectWordRange(); + int32_t nHorzScale = pEdit->GetHorzScale(); + + FX_COLORREF crCurFill = crTextFill; + FX_COLORREF crOldFill = crCurFill; + + bool bSelect = false; + static const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); + static const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113); + + std::ostringstream sTextBuf; + int32_t nFontIndex = -1; + CFX_PointF ptBT; + CFX_RenderDevice::StateRestorer restorer(pDevice); + if (!rcClip.IsEmpty()) + pDevice->SetClip_Rect(mtUser2Device.TransformRect(rcClip).ToFxRect()); + + CPWL_EditImpl_Iterator* pIterator = pEdit->GetIterator(); + IPVT_FontMap* pFontMap = pEdit->GetFontMap(); + if (!pFontMap) + return; + + if (pRange) + pIterator->SetAt(pRange->BeginPos); + else + pIterator->SetAt(0); + + CPVT_WordPlace oldplace; + while (pIterator->NextWord()) { + CPVT_WordPlace place = pIterator->GetAt(); + if (pRange && place > pRange->EndPos) + break; + + if (!wrSelect.IsEmpty()) { + bSelect = place > wrSelect.BeginPos && place <= wrSelect.EndPos; + crCurFill = bSelect ? crWhite : crTextFill; + } + if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { + crCurFill = crTextFill; + crOldFill = crCurFill; + } + CPVT_Word word; + if (pIterator->GetWord(word)) { + if (bSelect) { + CPVT_Line line; + pIterator->GetLine(line); + + if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { + CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent, + word.ptWord.x + word.fWidth, + line.ptLine.y + line.fLineAscent); + rc.Intersect(rcClip); + pSystemHandler->OutputSelectedRect(pFFLData, rc); + } else { + CFX_PathData pathSelBK; + pathSelBK.AppendRect(word.ptWord.x, line.ptLine.y + line.fLineDescent, + word.ptWord.x + word.fWidth, + line.ptLine.y + line.fLineAscent); + + pDevice->DrawPath(&pathSelBK, &mtUser2Device, nullptr, crSelBK, 0, + FXFILL_WINDING); + } + } + + if (bContinuous) { + if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex || + crOldFill != crCurFill) { + if (sTextBuf.tellp() > 0) { + DrawTextString( + pDevice, CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), + pFontMap->GetPDFFont(nFontIndex), fFontSize, mtUser2Device, + ByteString(sTextBuf), crOldFill, nHorzScale); + + sTextBuf.str(""); + } + nFontIndex = word.nFontIndex; + ptBT = word.ptWord; + crOldFill = crCurFill; + } + + sTextBuf << pEdit->GetPDFWordString(word.nFontIndex, word.Word, + SubWord); + } else { + DrawTextString( + pDevice, + CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y), + pFontMap->GetPDFFont(word.nFontIndex), fFontSize, mtUser2Device, + pEdit->GetPDFWordString(word.nFontIndex, word.Word, SubWord), + crCurFill, nHorzScale); + } + oldplace = place; + } + } + + if (sTextBuf.tellp() > 0) { + DrawTextString(pDevice, + CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), + pFontMap->GetPDFFont(nFontIndex), fFontSize, mtUser2Device, + ByteString(sTextBuf), crOldFill, nHorzScale); + } +} + +CPWL_EditImpl::CPWL_EditImpl() + : m_pVT(pdfium::MakeUnique()), + m_bEnableScroll(false), + m_nAlignment(0), + m_bNotifyFlag(false), + m_bEnableOverflow(false), + m_bEnableRefresh(true), + m_bEnableUndo(true) {} + +CPWL_EditImpl::~CPWL_EditImpl() {} + +void CPWL_EditImpl::Initialize() { + m_pVT->Initialize(); + SetCaret(m_pVT->GetBeginWordPlace()); + SetCaretOrigin(); +} + +void CPWL_EditImpl::SetFontMap(IPVT_FontMap* pFontMap) { + m_pVTProvider = pdfium::MakeUnique(pFontMap); + m_pVT->SetProvider(m_pVTProvider.get()); +} + +void CPWL_EditImpl::SetNotify(CPWL_EditCtrl* pNotify) { + m_pNotify = pNotify; +} + +void CPWL_EditImpl::SetOperationNotify(CPWL_Edit* pOperationNotify) { + m_pOperationNotify = pOperationNotify; +} + +CPWL_EditImpl_Iterator* CPWL_EditImpl::GetIterator() { + if (!m_pIterator) { + m_pIterator = + pdfium::MakeUnique(this, m_pVT->GetIterator()); + } + return m_pIterator.get(); +} + +IPVT_FontMap* CPWL_EditImpl::GetFontMap() { + return m_pVTProvider ? m_pVTProvider->GetFontMap() : nullptr; +} + +void CPWL_EditImpl::SetPlateRect(const CFX_FloatRect& rect) { + m_pVT->SetPlateRect(rect); + m_ptScrollPos = CFX_PointF(rect.left, rect.top); + Paint(); +} + +void CPWL_EditImpl::SetAlignmentH(int32_t nFormat, bool bPaint) { + m_pVT->SetAlignment(nFormat); + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetAlignmentV(int32_t nFormat, bool bPaint) { + m_nAlignment = nFormat; + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetPasswordChar(uint16_t wSubWord, bool bPaint) { + m_pVT->SetPasswordChar(wSubWord); + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetLimitChar(int32_t nLimitChar) { + m_pVT->SetLimitChar(nLimitChar); + Paint(); +} + +void CPWL_EditImpl::SetCharArray(int32_t nCharArray) { + m_pVT->SetCharArray(nCharArray); + Paint(); +} + +void CPWL_EditImpl::SetCharSpace(float fCharSpace) { + m_pVT->SetCharSpace(fCharSpace); + Paint(); +} + +void CPWL_EditImpl::SetMultiLine(bool bMultiLine, bool bPaint) { + m_pVT->SetMultiLine(bMultiLine); + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetAutoReturn(bool bAuto, bool bPaint) { + m_pVT->SetAutoReturn(bAuto); + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetAutoFontSize(bool bAuto, bool bPaint) { + m_pVT->SetAutoFontSize(bAuto); + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetFontSize(float fFontSize) { + m_pVT->SetFontSize(fFontSize); + Paint(); +} + +void CPWL_EditImpl::SetAutoScroll(bool bAuto, bool bPaint) { + m_bEnableScroll = bAuto; + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetTextOverflow(bool bAllowed, bool bPaint) { + m_bEnableOverflow = bAllowed; + if (bPaint) + Paint(); +} + +void CPWL_EditImpl::SetSelection(int32_t nStartChar, int32_t nEndChar) { + if (m_pVT->IsValid()) { + if (nStartChar == 0 && nEndChar < 0) { + SelectAll(); + } else if (nStartChar < 0) { + SelectNone(); + } else { + if (nStartChar < nEndChar) { + SetSelection(m_pVT->WordIndexToWordPlace(nStartChar), + m_pVT->WordIndexToWordPlace(nEndChar)); + } else { + SetSelection(m_pVT->WordIndexToWordPlace(nEndChar), + m_pVT->WordIndexToWordPlace(nStartChar)); + } + } + } +} + +void CPWL_EditImpl::SetSelection(const CPVT_WordPlace& begin, + const CPVT_WordPlace& end) { + if (!m_pVT->IsValid()) + return; + + SelectNone(); + m_SelState.Set(begin, end); + SetCaret(m_SelState.EndPos); + ScrollToCaret(); + if (!m_SelState.IsEmpty()) + Refresh(); + SetCaretInfo(); +} + +void CPWL_EditImpl::GetSelection(int32_t& nStartChar, int32_t& nEndChar) const { + nStartChar = -1; + nEndChar = -1; + if (!m_pVT->IsValid()) + return; + + if (m_SelState.IsEmpty()) { + nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret); + nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret); + return; + } + if (m_SelState.BeginPos < m_SelState.EndPos) { + nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos); + nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos); + return; + } + nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos); + nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos); +} + +int32_t CPWL_EditImpl::GetCaret() const { + if (m_pVT->IsValid()) + return m_pVT->WordPlaceToWordIndex(m_wpCaret); + + return -1; +} + +CPVT_WordPlace CPWL_EditImpl::GetCaretWordPlace() const { + return m_wpCaret; +} + +WideString CPWL_EditImpl::GetText() const { + WideString swRet; + if (!m_pVT->IsValid()) + return swRet; + + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(0); + + CPVT_Word wordinfo; + CPVT_WordPlace oldplace = pIterator->GetWordPlace(); + while (pIterator->NextWord()) { + CPVT_WordPlace place = pIterator->GetWordPlace(); + if (pIterator->GetWord(wordinfo)) + swRet += wordinfo.Word; + if (oldplace.nSecIndex != place.nSecIndex) + swRet += L"\r\n"; + oldplace = place; + } + return swRet; +} + +WideString CPWL_EditImpl::GetRangeText(const CPVT_WordRange& range) const { + WideString swRet; + if (!m_pVT->IsValid()) + return swRet; + + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + CPVT_WordRange wrTemp = range; + m_pVT->UpdateWordPlace(wrTemp.BeginPos); + m_pVT->UpdateWordPlace(wrTemp.EndPos); + pIterator->SetAt(wrTemp.BeginPos); + + CPVT_Word wordinfo; + CPVT_WordPlace oldplace = wrTemp.BeginPos; + while (pIterator->NextWord()) { + CPVT_WordPlace place = pIterator->GetWordPlace(); + if (place > wrTemp.EndPos) + break; + if (pIterator->GetWord(wordinfo)) + swRet += wordinfo.Word; + if (oldplace.nSecIndex != place.nSecIndex) + swRet += L"\r\n"; + oldplace = place; + } + return swRet; +} + +WideString CPWL_EditImpl::GetSelectedText() const { + return GetRangeText(m_SelState.ConvertToWordRange()); +} + +int32_t CPWL_EditImpl::GetTotalLines() const { + int32_t nLines = 1; + + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(0); + while (pIterator->NextLine()) + ++nLines; + + return nLines; +} + +CPVT_WordRange CPWL_EditImpl::GetSelectWordRange() const { + return m_SelState.ConvertToWordRange(); +} + +void CPWL_EditImpl::SetText(const WideString& sText) { + Empty(); + DoInsertText(CPVT_WordPlace(0, 0, -1), sText, FX_CHARSET_Default); + Paint(); +} + +bool CPWL_EditImpl::InsertWord(uint16_t word, int32_t charset) { + return InsertWord(word, charset, true, true); +} + +bool CPWL_EditImpl::InsertReturn() { + return InsertReturn(true, true); +} + +bool CPWL_EditImpl::Backspace() { + return Backspace(true, true); +} + +bool CPWL_EditImpl::Delete() { + return Delete(true, true); +} + +bool CPWL_EditImpl::ClearSelection() { + return Clear(true, true); +} + +bool CPWL_EditImpl::InsertText(const WideString& sText, int32_t charset) { + return InsertText(sText, charset, true, true); +} + +float CPWL_EditImpl::GetFontSize() const { + return m_pVT->GetFontSize(); +} + +uint16_t CPWL_EditImpl::GetPasswordChar() const { + return m_pVT->GetPasswordChar(); +} + +int32_t CPWL_EditImpl::GetCharArray() const { + return m_pVT->GetCharArray(); +} + +CFX_FloatRect CPWL_EditImpl::GetContentRect() const { + return VTToEdit(m_pVT->GetContentRect()); +} + +int32_t CPWL_EditImpl::GetHorzScale() const { + return m_pVT->GetHorzScale(); +} + +float CPWL_EditImpl::GetCharSpace() const { + return m_pVT->GetCharSpace(); +} + +CPVT_WordRange CPWL_EditImpl::GetWholeWordRange() const { + if (m_pVT->IsValid()) + return CPVT_WordRange(m_pVT->GetBeginWordPlace(), m_pVT->GetEndWordPlace()); + + return CPVT_WordRange(); +} + +CPVT_WordRange CPWL_EditImpl::GetVisibleWordRange() const { + if (m_bEnableOverflow) + return GetWholeWordRange(); + + if (m_pVT->IsValid()) { + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + + CPVT_WordPlace place1 = + m_pVT->SearchWordPlace(EditToVT(CFX_PointF(rcPlate.left, rcPlate.top))); + CPVT_WordPlace place2 = m_pVT->SearchWordPlace( + EditToVT(CFX_PointF(rcPlate.right, rcPlate.bottom))); + + return CPVT_WordRange(place1, place2); + } + + return CPVT_WordRange(); +} + +CPVT_WordPlace CPWL_EditImpl::SearchWordPlace(const CFX_PointF& point) const { + if (m_pVT->IsValid()) { + return m_pVT->SearchWordPlace(EditToVT(point)); + } + + return CPVT_WordPlace(); +} + +void CPWL_EditImpl::Paint() { + if (m_pVT->IsValid()) { + RearrangeAll(); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); + } +} + +void CPWL_EditImpl::RearrangeAll() { + if (m_pVT->IsValid()) { + m_pVT->UpdateWordPlace(m_wpCaret); + m_pVT->RearrangeAll(); + m_pVT->UpdateWordPlace(m_wpCaret); + SetScrollInfo(); + SetContentChanged(); + } +} + +void CPWL_EditImpl::RearrangePart(const CPVT_WordRange& range) { + if (m_pVT->IsValid()) { + m_pVT->UpdateWordPlace(m_wpCaret); + m_pVT->RearrangePart(range); + m_pVT->UpdateWordPlace(m_wpCaret); + SetScrollInfo(); + SetContentChanged(); + } +} + +void CPWL_EditImpl::SetContentChanged() { + if (m_pNotify) { + CFX_FloatRect rcContent = m_pVT->GetContentRect(); + if (rcContent.Width() != m_rcOldContent.Width() || + rcContent.Height() != m_rcOldContent.Height()) { + m_rcOldContent = rcContent; + } + } +} + +void CPWL_EditImpl::SelectAll() { + if (!m_pVT->IsValid()) + return; + m_SelState = CPWL_EditImpl_Select(GetWholeWordRange()); + SetCaret(m_SelState.EndPos); + ScrollToCaret(); + Refresh(); + SetCaretInfo(); +} + +void CPWL_EditImpl::SelectNone() { + if (!m_pVT->IsValid() || m_SelState.IsEmpty()) + return; + + m_SelState.Reset(); + Refresh(); +} + +bool CPWL_EditImpl::IsSelected() const { + return !m_SelState.IsEmpty(); +} + +CFX_PointF CPWL_EditImpl::VTToEdit(const CFX_PointF& point) const { + CFX_FloatRect rcContent = m_pVT->GetContentRect(); + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + + float fPadding = 0.0f; + + switch (m_nAlignment) { + case 0: + fPadding = 0.0f; + break; + case 1: + fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f; + break; + case 2: + fPadding = rcPlate.Height() - rcContent.Height(); + break; + } + + return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left), + point.y - (m_ptScrollPos.y + fPadding - rcPlate.top)); +} + +CFX_PointF CPWL_EditImpl::EditToVT(const CFX_PointF& point) const { + CFX_FloatRect rcContent = m_pVT->GetContentRect(); + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + + float fPadding = 0.0f; + + switch (m_nAlignment) { + case 0: + fPadding = 0.0f; + break; + case 1: + fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f; + break; + case 2: + fPadding = rcPlate.Height() - rcContent.Height(); + break; + } + + return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left), + point.y + (m_ptScrollPos.y + fPadding - rcPlate.top)); +} + +CFX_FloatRect CPWL_EditImpl::VTToEdit(const CFX_FloatRect& rect) const { + CFX_PointF ptLeftBottom = VTToEdit(CFX_PointF(rect.left, rect.bottom)); + CFX_PointF ptRightTop = VTToEdit(CFX_PointF(rect.right, rect.top)); + + return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, + ptRightTop.y); +} + +void CPWL_EditImpl::SetScrollInfo() { + if (!m_pNotify) + return; + + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + CFX_FloatRect rcContent = m_pVT->GetContentRect(); + if (m_bNotifyFlag) + return; + + AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + + PWL_SCROLL_INFO Info; + Info.fPlateWidth = rcPlate.top - rcPlate.bottom; + Info.fContentMin = rcContent.bottom; + Info.fContentMax = rcContent.top; + Info.fSmallStep = rcPlate.Height() / 3; + Info.fBigStep = rcPlate.Height(); + m_pNotify->SetScrollInfo(Info); +} + +void CPWL_EditImpl::SetScrollPosX(float fx) { + if (!m_bEnableScroll) + return; + + if (m_pVT->IsValid()) { + if (!IsFloatEqual(m_ptScrollPos.x, fx)) { + m_ptScrollPos.x = fx; + Refresh(); + } + } +} + +void CPWL_EditImpl::SetScrollPosY(float fy) { + if (!m_bEnableScroll) + return; + + if (m_pVT->IsValid()) { + if (!IsFloatEqual(m_ptScrollPos.y, fy)) { + m_ptScrollPos.y = fy; + Refresh(); + + if (m_pNotify) { + if (!m_bNotifyFlag) { + AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + m_pNotify->SetScrollPosition(fy); + } + } + } + } +} + +void CPWL_EditImpl::SetScrollPos(const CFX_PointF& point) { + SetScrollPosX(point.x); + SetScrollPosY(point.y); + SetScrollLimit(); + SetCaretInfo(); +} + +CFX_PointF CPWL_EditImpl::GetScrollPos() const { + return m_ptScrollPos; +} + +void CPWL_EditImpl::SetScrollLimit() { + if (m_pVT->IsValid()) { + CFX_FloatRect rcContent = m_pVT->GetContentRect(); + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + + if (rcPlate.Width() > rcContent.Width()) { + SetScrollPosX(rcPlate.left); + } else { + if (IsFloatSmaller(m_ptScrollPos.x, rcContent.left)) { + SetScrollPosX(rcContent.left); + } else if (IsFloatBigger(m_ptScrollPos.x, + rcContent.right - rcPlate.Width())) { + SetScrollPosX(rcContent.right - rcPlate.Width()); + } + } + + if (rcPlate.Height() > rcContent.Height()) { + SetScrollPosY(rcPlate.top); + } else { + if (IsFloatSmaller(m_ptScrollPos.y, + rcContent.bottom + rcPlate.Height())) { + SetScrollPosY(rcContent.bottom + rcPlate.Height()); + } else if (IsFloatBigger(m_ptScrollPos.y, rcContent.top)) { + SetScrollPosY(rcContent.top); + } + } + } +} + +void CPWL_EditImpl::ScrollToCaret() { + SetScrollLimit(); + + if (!m_pVT->IsValid()) + return; + + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(m_wpCaret); + + CFX_PointF ptHead; + CFX_PointF ptFoot; + CPVT_Word word; + CPVT_Line line; + if (pIterator->GetWord(word)) { + ptHead.x = word.ptWord.x + word.fWidth; + ptHead.y = word.ptWord.y + word.fAscent; + ptFoot.x = word.ptWord.x + word.fWidth; + ptFoot.y = word.ptWord.y + word.fDescent; + } else if (pIterator->GetLine(line)) { + ptHead.x = line.ptLine.x; + ptHead.y = line.ptLine.y + line.fLineAscent; + ptFoot.x = line.ptLine.x; + ptFoot.y = line.ptLine.y + line.fLineDescent; + } + + CFX_PointF ptHeadEdit = VTToEdit(ptHead); + CFX_PointF ptFootEdit = VTToEdit(ptFoot); + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + if (!IsFloatEqual(rcPlate.left, rcPlate.right)) { + if (IsFloatSmaller(ptHeadEdit.x, rcPlate.left) || + IsFloatEqual(ptHeadEdit.x, rcPlate.left)) { + SetScrollPosX(ptHead.x); + } else if (IsFloatBigger(ptHeadEdit.x, rcPlate.right)) { + SetScrollPosX(ptHead.x - rcPlate.Width()); + } + } + + if (!IsFloatEqual(rcPlate.top, rcPlate.bottom)) { + if (IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) || + IsFloatEqual(ptFootEdit.y, rcPlate.bottom)) { + if (IsFloatSmaller(ptHeadEdit.y, rcPlate.top)) { + SetScrollPosY(ptFoot.y + rcPlate.Height()); + } + } else if (IsFloatBigger(ptHeadEdit.y, rcPlate.top)) { + if (IsFloatBigger(ptFootEdit.y, rcPlate.bottom)) { + SetScrollPosY(ptHead.y); + } + } + } +} + +void CPWL_EditImpl::Refresh() { + if (m_bEnableRefresh && m_pVT->IsValid()) { + m_Refresh.BeginRefresh(); + RefreshPushLineRects(GetVisibleWordRange()); + + m_Refresh.NoAnalyse(); + m_ptRefreshScrollPos = m_ptScrollPos; + + if (m_pNotify) { + if (!m_bNotifyFlag) { + AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + if (std::vector* pRects = m_Refresh.GetRefreshRects()) { + for (auto& rect : *pRects) + m_pNotify->InvalidateRect(&rect); + } + } + } + + m_Refresh.EndRefresh(); + } +} + +void CPWL_EditImpl::RefreshPushLineRects(const CPVT_WordRange& wr) { + if (!m_pVT->IsValid()) + return; + + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + CPVT_WordPlace wpBegin = wr.BeginPos; + m_pVT->UpdateWordPlace(wpBegin); + CPVT_WordPlace wpEnd = wr.EndPos; + m_pVT->UpdateWordPlace(wpEnd); + pIterator->SetAt(wpBegin); + + CPVT_Line lineinfo; + do { + if (!pIterator->GetLine(lineinfo)) + break; + if (lineinfo.lineplace.LineCmp(wpEnd) > 0) + break; + + CFX_FloatRect rcLine(lineinfo.ptLine.x, + lineinfo.ptLine.y + lineinfo.fLineDescent, + lineinfo.ptLine.x + lineinfo.fLineWidth, + lineinfo.ptLine.y + lineinfo.fLineAscent); + + m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace, lineinfo.lineEnd), + VTToEdit(rcLine)); + } while (pIterator->NextLine()); +} + +void CPWL_EditImpl::RefreshWordRange(const CPVT_WordRange& wr) { + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + CPVT_WordRange wrTemp = wr; + + m_pVT->UpdateWordPlace(wrTemp.BeginPos); + m_pVT->UpdateWordPlace(wrTemp.EndPos); + pIterator->SetAt(wrTemp.BeginPos); + + CPVT_Word wordinfo; + CPVT_Line lineinfo; + CPVT_WordPlace place; + + while (pIterator->NextWord()) { + place = pIterator->GetWordPlace(); + if (place > wrTemp.EndPos) + break; + + pIterator->GetWord(wordinfo); + pIterator->GetLine(lineinfo); + if (place.LineCmp(wrTemp.BeginPos) == 0 || + place.LineCmp(wrTemp.EndPos) == 0) { + CFX_FloatRect rcWord(wordinfo.ptWord.x, + lineinfo.ptLine.y + lineinfo.fLineDescent, + wordinfo.ptWord.x + wordinfo.fWidth, + lineinfo.ptLine.y + lineinfo.fLineAscent); + + if (m_pNotify) { + if (!m_bNotifyFlag) { + AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + CFX_FloatRect rcRefresh = VTToEdit(rcWord); + m_pNotify->InvalidateRect(&rcRefresh); + } + } + } else { + CFX_FloatRect rcLine(lineinfo.ptLine.x, + lineinfo.ptLine.y + lineinfo.fLineDescent, + lineinfo.ptLine.x + lineinfo.fLineWidth, + lineinfo.ptLine.y + lineinfo.fLineAscent); + + if (m_pNotify) { + if (!m_bNotifyFlag) { + AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + CFX_FloatRect rcRefresh = VTToEdit(rcLine); + m_pNotify->InvalidateRect(&rcRefresh); + } + } + + pIterator->NextLine(); + } + } +} + +void CPWL_EditImpl::SetCaret(const CPVT_WordPlace& place) { + m_wpOldCaret = m_wpCaret; + m_wpCaret = place; +} + +void CPWL_EditImpl::SetCaretInfo() { + if (m_pNotify) { + if (!m_bNotifyFlag) { + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(m_wpCaret); + + CFX_PointF ptHead; + CFX_PointF ptFoot; + CPVT_Word word; + CPVT_Line line; + if (pIterator->GetWord(word)) { + ptHead.x = word.ptWord.x + word.fWidth; + ptHead.y = word.ptWord.y + word.fAscent; + ptFoot.x = word.ptWord.x + word.fWidth; + ptFoot.y = word.ptWord.y + word.fDescent; + } else if (pIterator->GetLine(line)) { + ptHead.x = line.ptLine.x; + ptHead.y = line.ptLine.y + line.fLineAscent; + ptFoot.x = line.ptLine.x; + ptFoot.y = line.ptLine.y + line.fLineDescent; + } + + AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + m_pNotify->SetCaret(m_SelState.IsEmpty(), VTToEdit(ptHead), + VTToEdit(ptFoot)); + } + } +} + +void CPWL_EditImpl::OnMouseDown(const CFX_PointF& point, + bool bShift, + bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + SelectNone(); + SetCaret(m_pVT->SearchWordPlace(EditToVT(point))); + m_SelState.Set(m_wpCaret, m_wpCaret); + ScrollToCaret(); + SetCaretOrigin(); + SetCaretInfo(); +} + +void CPWL_EditImpl::OnMouseMove(const CFX_PointF& point, + bool bShift, + bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + SetCaret(m_pVT->SearchWordPlace(EditToVT(point))); + if (m_wpCaret == m_wpOldCaret) + return; + + m_SelState.SetEndPos(m_wpCaret); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); +} + +void CPWL_EditImpl::OnVK_UP(bool bShift, bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + SetCaret(m_pVT->GetUpWordPlace(m_wpCaret, m_ptCaret)); + if (bShift) { + if (m_SelState.IsEmpty()) + m_SelState.Set(m_wpOldCaret, m_wpCaret); + else + m_SelState.SetEndPos(m_wpCaret); + + if (m_wpOldCaret != m_wpCaret) { + ScrollToCaret(); + Refresh(); + SetCaretInfo(); + } + } else { + SelectNone(); + ScrollToCaret(); + SetCaretInfo(); + } +} + +void CPWL_EditImpl::OnVK_DOWN(bool bShift, bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + SetCaret(m_pVT->GetDownWordPlace(m_wpCaret, m_ptCaret)); + if (bShift) { + if (m_SelState.IsEmpty()) + m_SelState.Set(m_wpOldCaret, m_wpCaret); + else + m_SelState.SetEndPos(m_wpCaret); + + if (m_wpOldCaret != m_wpCaret) { + ScrollToCaret(); + Refresh(); + SetCaretInfo(); + } + } else { + SelectNone(); + ScrollToCaret(); + SetCaretInfo(); + } +} + +void CPWL_EditImpl::OnVK_LEFT(bool bShift, bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + if (bShift) { + if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) && + m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) { + SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); + } + SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); + if (m_SelState.IsEmpty()) + m_SelState.Set(m_wpOldCaret, m_wpCaret); + else + m_SelState.SetEndPos(m_wpCaret); + + if (m_wpOldCaret != m_wpCaret) { + ScrollToCaret(); + Refresh(); + SetCaretInfo(); + } + } else { + if (!m_SelState.IsEmpty()) { + if (m_SelState.BeginPos < m_SelState.EndPos) + SetCaret(m_SelState.BeginPos); + else + SetCaret(m_SelState.EndPos); + + SelectNone(); + ScrollToCaret(); + SetCaretInfo(); + } else { + if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) && + m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) { + SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); + } + SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret)); + ScrollToCaret(); + SetCaretOrigin(); + SetCaretInfo(); + } + } +} + +void CPWL_EditImpl::OnVK_RIGHT(bool bShift, bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + if (bShift) { + SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); + if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) && + m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret)) + SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); + + if (m_SelState.IsEmpty()) + m_SelState.Set(m_wpOldCaret, m_wpCaret); + else + m_SelState.SetEndPos(m_wpCaret); + + if (m_wpOldCaret != m_wpCaret) { + ScrollToCaret(); + Refresh(); + SetCaretInfo(); + } + } else { + if (!m_SelState.IsEmpty()) { + if (m_SelState.BeginPos > m_SelState.EndPos) + SetCaret(m_SelState.BeginPos); + else + SetCaret(m_SelState.EndPos); + + SelectNone(); + ScrollToCaret(); + SetCaretInfo(); + } else { + SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); + if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) && + m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret)) { + SetCaret(m_pVT->GetNextWordPlace(m_wpCaret)); + } + ScrollToCaret(); + SetCaretOrigin(); + SetCaretInfo(); + } + } +} + +void CPWL_EditImpl::OnVK_HOME(bool bShift, bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + if (bShift) { + if (bCtrl) + SetCaret(m_pVT->GetBeginWordPlace()); + else + SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret)); + + if (m_SelState.IsEmpty()) + m_SelState.Set(m_wpOldCaret, m_wpCaret); + else + m_SelState.SetEndPos(m_wpCaret); + + ScrollToCaret(); + Refresh(); + SetCaretInfo(); + } else { + if (!m_SelState.IsEmpty()) { + SetCaret(std::min(m_SelState.BeginPos, m_SelState.EndPos)); + SelectNone(); + ScrollToCaret(); + SetCaretInfo(); + } else { + if (bCtrl) + SetCaret(m_pVT->GetBeginWordPlace()); + else + SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret)); + + ScrollToCaret(); + SetCaretOrigin(); + SetCaretInfo(); + } + } +} + +void CPWL_EditImpl::OnVK_END(bool bShift, bool bCtrl) { + if (!m_pVT->IsValid()) + return; + + if (bShift) { + if (bCtrl) + SetCaret(m_pVT->GetEndWordPlace()); + else + SetCaret(m_pVT->GetLineEndPlace(m_wpCaret)); + + if (m_SelState.IsEmpty()) + m_SelState.Set(m_wpOldCaret, m_wpCaret); + else + m_SelState.SetEndPos(m_wpCaret); + + ScrollToCaret(); + Refresh(); + SetCaretInfo(); + } else { + if (!m_SelState.IsEmpty()) { + SetCaret(std::max(m_SelState.BeginPos, m_SelState.EndPos)); + SelectNone(); + ScrollToCaret(); + SetCaretInfo(); + } else { + if (bCtrl) + SetCaret(m_pVT->GetEndWordPlace()); + else + SetCaret(m_pVT->GetLineEndPlace(m_wpCaret)); + + ScrollToCaret(); + SetCaretOrigin(); + SetCaretInfo(); + } + } +} + +bool CPWL_EditImpl::InsertWord(uint16_t word, + int32_t charset, + bool bAddUndo, + bool bPaint) { + if (IsTextOverflow() || !m_pVT->IsValid()) + return false; + + m_pVT->UpdateWordPlace(m_wpCaret); + SetCaret( + m_pVT->InsertWord(m_wpCaret, word, GetCharSetFromUnicode(word, charset))); + m_SelState.Set(m_wpCaret, m_wpCaret); + if (m_wpCaret == m_wpOldCaret) + return false; + + if (bAddUndo && m_bEnableUndo) { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, word, charset)); + } + if (bPaint) + PaintInsertText(m_wpOldCaret, m_wpCaret); + + if (m_pOperationNotify) + m_pOperationNotify->OnInsertWord(m_wpCaret, m_wpOldCaret); + + return true; +} + +bool CPWL_EditImpl::InsertReturn(bool bAddUndo, bool bPaint) { + if (IsTextOverflow() || !m_pVT->IsValid()) + return false; + + m_pVT->UpdateWordPlace(m_wpCaret); + SetCaret(m_pVT->InsertSection(m_wpCaret)); + m_SelState.Set(m_wpCaret, m_wpCaret); + if (m_wpCaret == m_wpOldCaret) + return false; + + if (bAddUndo && m_bEnableUndo) { + AddEditUndoItem( + pdfium::MakeUnique(this, m_wpOldCaret, m_wpCaret)); + } + if (bPaint) { + RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret)); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); + } + if (m_pOperationNotify) + m_pOperationNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret); + + return true; +} + +bool CPWL_EditImpl::Backspace(bool bAddUndo, bool bPaint) { + if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetBeginWordPlace()) + return false; + + CPVT_Word word; + if (bAddUndo) { + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(m_wpCaret); + pIterator->GetWord(word); + } + m_pVT->UpdateWordPlace(m_wpCaret); + SetCaret(m_pVT->BackSpaceWord(m_wpCaret)); + m_SelState.Set(m_wpCaret, m_wpCaret); + if (m_wpCaret == m_wpOldCaret) + return false; + + if (bAddUndo && m_bEnableUndo) { + if (m_wpCaret.nSecIndex != m_wpOldCaret.nSecIndex) { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset)); + } else { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset)); + } + } + if (bPaint) { + RearrangePart(CPVT_WordRange(m_wpCaret, m_wpOldCaret)); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); + } + if (m_pOperationNotify) + m_pOperationNotify->OnBackSpace(m_wpCaret, m_wpOldCaret); + + return true; +} + +bool CPWL_EditImpl::Delete(bool bAddUndo, bool bPaint) { + if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetEndWordPlace()) + return false; + + CPVT_Word word; + if (bAddUndo) { + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret)); + pIterator->GetWord(word); + } + m_pVT->UpdateWordPlace(m_wpCaret); + bool bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret)); + SetCaret(m_pVT->DeleteWord(m_wpCaret)); + m_SelState.Set(m_wpCaret, m_wpCaret); + if (bAddUndo && m_bEnableUndo) { + if (bSecEnd) { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, bSecEnd)); + } else { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, bSecEnd)); + } + } + if (bPaint) { + RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret)); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); + } + if (m_pOperationNotify) + m_pOperationNotify->OnDelete(m_wpCaret, m_wpOldCaret); + + return true; +} + +bool CPWL_EditImpl::Empty() { + if (m_pVT->IsValid()) { + m_pVT->DeleteWords(GetWholeWordRange()); + SetCaret(m_pVT->GetBeginWordPlace()); + + return true; + } + + return false; +} + +bool CPWL_EditImpl::Clear(bool bAddUndo, bool bPaint) { + if (!m_pVT->IsValid() || m_SelState.IsEmpty()) + return false; + + CPVT_WordRange range = m_SelState.ConvertToWordRange(); + if (bAddUndo && m_bEnableUndo) { + AddEditUndoItem( + pdfium::MakeUnique(this, range, GetSelectedText())); + } + + SelectNone(); + SetCaret(m_pVT->DeleteWords(range)); + m_SelState.Set(m_wpCaret, m_wpCaret); + if (bPaint) { + RearrangePart(range); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); + } + if (m_pOperationNotify) + m_pOperationNotify->OnClear(m_wpCaret, m_wpOldCaret); + + return true; +} + +bool CPWL_EditImpl::InsertText(const WideString& sText, + int32_t charset, + bool bAddUndo, + bool bPaint) { + if (IsTextOverflow()) + return false; + + m_pVT->UpdateWordPlace(m_wpCaret); + SetCaret(DoInsertText(m_wpCaret, sText, charset)); + m_SelState.Set(m_wpCaret, m_wpCaret); + if (m_wpCaret == m_wpOldCaret) + return false; + + if (bAddUndo && m_bEnableUndo) { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, sText, charset)); + } + if (bPaint) + PaintInsertText(m_wpOldCaret, m_wpCaret); + + if (m_pOperationNotify) + m_pOperationNotify->OnInsertText(m_wpCaret, m_wpOldCaret); + + return true; +} + +void CPWL_EditImpl::PaintInsertText(const CPVT_WordPlace& wpOld, + const CPVT_WordPlace& wpNew) { + if (m_pVT->IsValid()) { + RearrangePart(CPVT_WordRange(wpOld, wpNew)); + ScrollToCaret(); + Refresh(); + SetCaretOrigin(); + SetCaretInfo(); + } +} + +bool CPWL_EditImpl::Redo() { + if (m_bEnableUndo) { + if (m_Undo.CanRedo()) { + m_Undo.Redo(); + return true; + } + } + + return false; +} + +bool CPWL_EditImpl::Undo() { + if (m_bEnableUndo) { + if (m_Undo.CanUndo()) { + m_Undo.Undo(); + return true; + } + } + + return false; +} + +void CPWL_EditImpl::SetCaretOrigin() { + if (!m_pVT->IsValid()) + return; + + CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator(); + pIterator->SetAt(m_wpCaret); + CPVT_Word word; + CPVT_Line line; + if (pIterator->GetWord(word)) { + m_ptCaret.x = word.ptWord.x + word.fWidth; + m_ptCaret.y = word.ptWord.y; + } else if (pIterator->GetLine(line)) { + m_ptCaret.x = line.ptLine.x; + m_ptCaret.y = line.ptLine.y; + } +} + +CPVT_WordPlace CPWL_EditImpl::WordIndexToWordPlace(int32_t index) const { + if (m_pVT->IsValid()) + return m_pVT->WordIndexToWordPlace(index); + + return CPVT_WordPlace(); +} + +bool CPWL_EditImpl::IsTextFull() const { + int32_t nTotalWords = m_pVT->GetTotalWords(); + int32_t nLimitChar = m_pVT->GetLimitChar(); + int32_t nCharArray = m_pVT->GetCharArray(); + + return IsTextOverflow() || (nLimitChar > 0 && nTotalWords >= nLimitChar) || + (nCharArray > 0 && nTotalWords >= nCharArray); +} + +bool CPWL_EditImpl::IsTextOverflow() const { + if (!m_bEnableScroll && !m_bEnableOverflow) { + CFX_FloatRect rcPlate = m_pVT->GetPlateRect(); + CFX_FloatRect rcContent = m_pVT->GetContentRect(); + + if (m_pVT->IsMultiLine() && GetTotalLines() > 1 && + IsFloatBigger(rcContent.Height(), rcPlate.Height())) { + return true; + } + + if (IsFloatBigger(rcContent.Width(), rcPlate.Width())) + return true; + } + + return false; +} + +bool CPWL_EditImpl::CanUndo() const { + if (m_bEnableUndo) { + return m_Undo.CanUndo(); + } + + return false; +} + +bool CPWL_EditImpl::CanRedo() const { + if (m_bEnableUndo) { + return m_Undo.CanRedo(); + } + + return false; +} + +void CPWL_EditImpl::EnableRefresh(bool bRefresh) { + m_bEnableRefresh = bRefresh; +} + +void CPWL_EditImpl::EnableUndo(bool bUndo) { + m_bEnableUndo = bUndo; +} + +CPVT_WordPlace CPWL_EditImpl::DoInsertText(const CPVT_WordPlace& place, + const WideString& sText, + int32_t charset) { + CPVT_WordPlace wp = place; + + if (m_pVT->IsValid()) { + for (int32_t i = 0, sz = sText.GetLength(); i < sz; i++) { + uint16_t word = sText[i]; + switch (word) { + case 0x0D: + wp = m_pVT->InsertSection(wp); + if (i + 1 < sz && sText[i + 1] == 0x0A) + i++; + break; + case 0x0A: + wp = m_pVT->InsertSection(wp); + break; + case 0x09: + word = 0x20; + default: + wp = + m_pVT->InsertWord(wp, word, GetCharSetFromUnicode(word, charset)); + break; + } + } + } + + return wp; +} + +int32_t CPWL_EditImpl::GetCharSetFromUnicode(uint16_t word, + int32_t nOldCharset) { + if (IPVT_FontMap* pFontMap = GetFontMap()) + return pFontMap->CharSetFromUnicode(word, nOldCharset); + return nOldCharset; +} + +void CPWL_EditImpl::AddEditUndoItem( + std::unique_ptr pEditUndoItem) { + m_Undo.AddItem(std::move(pEditUndoItem)); +} + +ByteString CPWL_EditImpl::GetPDFWordString(int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord) { + IPVT_FontMap* pFontMap = GetFontMap(); + CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex); + if (!pPDFFont) + return ByteString(); + + ByteString sWord; + if (SubWord > 0) { + Word = SubWord; + } else { + uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible() + ? pPDFFont->CharCodeFromUnicode(Word) + : pFontMap->CharCodeFromUnicode(nFontIndex, Word); + if (dwCharCode > 0) { + pPDFFont->AppendChar(&sWord, dwCharCode); + return sWord; + } + } + pPDFFont->AppendChar(&sWord, Word); + return sWord; +} + +CPWL_EditImpl_Select::CPWL_EditImpl_Select() {} + +CPWL_EditImpl_Select::CPWL_EditImpl_Select(const CPVT_WordRange& range) { + Set(range.BeginPos, range.EndPos); +} + +CPVT_WordRange CPWL_EditImpl_Select::ConvertToWordRange() const { + return CPVT_WordRange(BeginPos, EndPos); +} + +void CPWL_EditImpl_Select::Reset() { + BeginPos.Reset(); + EndPos.Reset(); +} + +void CPWL_EditImpl_Select::Set(const CPVT_WordPlace& begin, + const CPVT_WordPlace& end) { + BeginPos = begin; + EndPos = end; +} + +void CPWL_EditImpl_Select::SetEndPos(const CPVT_WordPlace& end) { + EndPos = end; +} + +bool CPWL_EditImpl_Select::IsEmpty() const { + return BeginPos == EndPos; +} diff --git a/fpdfsdk/pwl/cpwl_edit_impl.h b/fpdfsdk/pwl/cpwl_edit_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..38477db4277584ddd90ec1611c8c13835097bf52 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_impl.h @@ -0,0 +1,439 @@ +// 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 FPDFSDK_PWL_CPWL_EDIT_IMPL_H_ +#define FPDFSDK_PWL_CPWL_EDIT_IMPL_H_ + +#include +#include +#include + +#include "core/fpdfdoc/cpdf_variabletext.h" +#include "core/fpdfdoc/cpvt_wordrange.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/fx_dib.h" + +#define FX_EDIT_ISLATINWORD(u) \ + (u == 0x2D || (u <= 0x005A && u >= 0x0041) || \ + (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0)) + +class CFFL_FormFiller; +class CPWL_EditImpl; +class CPWL_EditImpl_Iterator; +class CPWL_EditImpl_Provider; +class CFX_RenderDevice; +class CFX_SystemHandler; +class CPWL_Edit; +class CPWL_EditCtrl; +class IFX_Edit_UndoItem; + +struct CPWL_EditImpl_LineRect { + CPWL_EditImpl_LineRect(const CPVT_WordRange& wrLine, + const CFX_FloatRect& rcLine) + : m_wrLine(wrLine), m_rcLine(rcLine) {} + + CPVT_WordRange m_wrLine; + CFX_FloatRect m_rcLine; +}; + +class CPWL_EditImpl_Refresh { + public: + CPWL_EditImpl_Refresh(); + ~CPWL_EditImpl_Refresh(); + + void BeginRefresh(); + void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect); + void NoAnalyse(); + std::vector* GetRefreshRects(); + void EndRefresh(); + + private: + void Add(const CFX_FloatRect& new_rect); + + std::vector m_NewLineRects; + std::vector m_OldLineRects; + std::vector m_RefreshRects; +}; + +class CPWL_EditImpl_Select { + public: + CPWL_EditImpl_Select(); + explicit CPWL_EditImpl_Select(const CPVT_WordRange& range); + + void Reset(); + void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); + void SetEndPos(const CPVT_WordPlace& end); + + CPVT_WordRange ConvertToWordRange() const; + bool IsEmpty() const; + + CPVT_WordPlace BeginPos; + CPVT_WordPlace EndPos; +}; + +class CPWL_EditImpl_Undo { + public: + CPWL_EditImpl_Undo(); + ~CPWL_EditImpl_Undo(); + + void AddItem(std::unique_ptr pItem); + void Undo(); + void Redo(); + bool CanUndo() const; + bool CanRedo() const; + + private: + void RemoveHeads(); + void RemoveTails(); + + std::deque> m_UndoItemStack; + size_t m_nCurUndoPos; + bool m_bWorking; +}; + +class IFX_Edit_UndoItem { + public: + virtual ~IFX_Edit_UndoItem() {} + + virtual void Undo() = 0; + virtual void Redo() = 0; +}; + +class CFXEU_InsertWord : public IFX_Edit_UndoItem { + public: + CFXEU_InsertWord(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset); + ~CFXEU_InsertWord() override; + + // IFX_Edit_UndoItem: + void Redo() override; + void Undo() override; + + private: + UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; + uint16_t m_Word; + int32_t m_nCharset; +}; + +class CFXEU_InsertReturn : public IFX_Edit_UndoItem { + public: + CFXEU_InsertReturn(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace); + ~CFXEU_InsertReturn() override; + + // IFX_Edit_UndoItem: + void Redo() override; + void Undo() override; + + private: + UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; +}; + +class CFXEU_Backspace : public IFX_Edit_UndoItem { + public: + CFXEU_Backspace(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset); + ~CFXEU_Backspace() override; + + // IFX_Edit_UndoItem: + void Redo() override; + void Undo() override; + + private: + UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; + uint16_t m_Word; + int32_t m_nCharset; +}; + +class CFXEU_Delete : public IFX_Edit_UndoItem { + public: + CFXEU_Delete(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset, + bool bSecEnd); + ~CFXEU_Delete() override; + + // IFX_Edit_UndoItem: + void Redo() override; + void Undo() override; + + private: + UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; + uint16_t m_Word; + int32_t m_nCharset; + bool m_bSecEnd; +}; + +class CFXEU_Clear : public IFX_Edit_UndoItem { + public: + CFXEU_Clear(CPWL_EditImpl* pEdit, + const CPVT_WordRange& wrSel, + const WideString& swText); + ~CFXEU_Clear() override; + + // IFX_Edit_UndoItem: + void Redo() override; + void Undo() override; + + private: + UnownedPtr m_pEdit; + + CPVT_WordRange m_wrSel; + WideString m_swText; +}; + +class CFXEU_InsertText : public IFX_Edit_UndoItem { + public: + CFXEU_InsertText(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + const WideString& swText, + int32_t charset); + ~CFXEU_InsertText() override; + + // IFX_Edit_UndoItem: + void Redo() override; + void Undo() override; + + private: + UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; + WideString m_swText; + int32_t m_nCharset; +}; + +class CPWL_EditImpl { + public: + static void DrawEdit(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device, + CPWL_EditImpl* pEdit, + FX_COLORREF crTextFill, + const CFX_FloatRect& rcClip, + const CFX_PointF& ptOffset, + const CPVT_WordRange* pRange, + CFX_SystemHandler* pSystemHandler, + CFFL_FormFiller* pFFLData); + + CPWL_EditImpl(); + ~CPWL_EditImpl(); + + void SetFontMap(IPVT_FontMap* pFontMap); + void SetNotify(CPWL_EditCtrl* pNotify); + void SetOperationNotify(CPWL_Edit* pOperationNotify); + + // Returns an iterator for the contents. Should not be released. + CPWL_EditImpl_Iterator* GetIterator(); + IPVT_FontMap* GetFontMap(); + void Initialize(); + + // Set the bounding box of the text area. + void SetPlateRect(const CFX_FloatRect& rect); + void SetScrollPos(const CFX_PointF& point); + + // Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right]) + void SetAlignmentH(int32_t nFormat, bool bPaint); + // Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right]) + void SetAlignmentV(int32_t nFormat, bool bPaint); + + // Set the substitution character for hidden text. + void SetPasswordChar(uint16_t wSubWord, bool bPaint); + + // Set the maximum number of words in the text. + void SetLimitChar(int32_t nLimitChar); + void SetCharArray(int32_t nCharArray); + void SetCharSpace(float fCharSpace); + void SetMultiLine(bool bMultiLine, bool bPaint); + void SetAutoReturn(bool bAuto, bool bPaint); + void SetAutoFontSize(bool bAuto, bool bPaint); + void SetAutoScroll(bool bAuto, bool bPaint); + void SetFontSize(float fFontSize); + void SetTextOverflow(bool bAllowed, bool bPaint); + void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl); + void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl); + void OnVK_UP(bool bShift, bool bCtrl); + void OnVK_DOWN(bool bShift, bool bCtrl); + void OnVK_LEFT(bool bShift, bool bCtrl); + void OnVK_RIGHT(bool bShift, bool bCtrl); + void OnVK_HOME(bool bShift, bool bCtrl); + void OnVK_END(bool bShift, bool bCtrl); + void SetText(const WideString& sText); + bool InsertWord(uint16_t word, int32_t charset); + bool InsertReturn(); + bool Backspace(); + bool Delete(); + bool ClearSelection(); + bool InsertText(const WideString& sText, int32_t charset); + bool Redo(); + bool Undo(); + CPVT_WordPlace WordIndexToWordPlace(int32_t index) const; + CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const; + int32_t GetCaret() const; + CPVT_WordPlace GetCaretWordPlace() const; + WideString GetSelectedText() const; + WideString GetText() const; + float GetFontSize() const; + uint16_t GetPasswordChar() const; + CFX_PointF GetScrollPos() const; + int32_t GetCharArray() const; + CFX_FloatRect GetContentRect() const; + WideString GetRangeText(const CPVT_WordRange& range) const; + int32_t GetHorzScale() const; + float GetCharSpace() const; + void SetSelection(int32_t nStartChar, int32_t nEndChar); + void GetSelection(int32_t& nStartChar, int32_t& nEndChar) const; + void SelectAll(); + void SelectNone(); + bool IsSelected() const; + void Paint(); + void EnableRefresh(bool bRefresh); + void RefreshWordRange(const CPVT_WordRange& wr); + CPVT_WordRange GetWholeWordRange() const; + CPVT_WordRange GetSelectWordRange() const; + void EnableUndo(bool bUndo); + bool IsTextFull() const; + bool IsTextOverflow() const; + bool CanUndo() const; + bool CanRedo() const; + CPVT_WordRange GetVisibleWordRange() const; + + bool Empty(); + + CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place, + const WideString& sText, + int32_t charset); + int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset); + + int32_t GetTotalLines() const; + + ByteString GetPDFWordString(int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord); + + void SetSelection(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); + + bool Delete(bool bAddUndo, bool bPaint); + bool Clear(bool bAddUndo, bool bPaint); + bool InsertText(const WideString& sText, + int32_t charset, + bool bAddUndo, + bool bPaint); + bool InsertWord(uint16_t word, int32_t charset, bool bAddUndo, bool bPaint); + bool InsertReturn(bool bAddUndo, bool bPaint); + bool Backspace(bool bAddUndo, bool bPaint); + void SetCaret(const CPVT_WordPlace& place); + + CFX_PointF VTToEdit(const CFX_PointF& point) const; + + private: + void RearrangeAll(); + void RearrangePart(const CPVT_WordRange& range); + void ScrollToCaret(); + void SetScrollInfo(); + void SetScrollPosX(float fx); + void SetScrollPosY(float fy); + void SetScrollLimit(); + void SetContentChanged(); + + void PaintInsertText(const CPVT_WordPlace& wpOld, + const CPVT_WordPlace& wpNew); + + CFX_PointF EditToVT(const CFX_PointF& point) const; + CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const; + + void Refresh(); + void RefreshPushLineRects(const CPVT_WordRange& wr); + + void SetCaretInfo(); + void SetCaretOrigin(); + + void AddEditUndoItem(std::unique_ptr pEditUndoItem); + + std::unique_ptr m_pVT; + UnownedPtr m_pNotify; + UnownedPtr m_pOperationNotify; + std::unique_ptr m_pVTProvider; + CPVT_WordPlace m_wpCaret; + CPVT_WordPlace m_wpOldCaret; + CPWL_EditImpl_Select m_SelState; + CFX_PointF m_ptScrollPos; + CFX_PointF m_ptRefreshScrollPos; + bool m_bEnableScroll; + std::unique_ptr m_pIterator; + CPWL_EditImpl_Refresh m_Refresh; + CFX_PointF m_ptCaret; + CPWL_EditImpl_Undo m_Undo; + int32_t m_nAlignment; + bool m_bNotifyFlag; + bool m_bEnableOverflow; + bool m_bEnableRefresh; + CFX_FloatRect m_rcOldContent; + bool m_bEnableUndo; +}; + +class CPWL_EditImpl_Iterator { + public: + CPWL_EditImpl_Iterator(CPWL_EditImpl* pEdit, + CPDF_VariableText::Iterator* pVTIterator); + ~CPWL_EditImpl_Iterator(); + + bool NextWord(); + bool PrevWord(); + bool GetWord(CPVT_Word& word) const; + bool GetLine(CPVT_Line& line) const; + void SetAt(int32_t nWordIndex); + void SetAt(const CPVT_WordPlace& place); + const CPVT_WordPlace& GetAt() const; + + private: + UnownedPtr m_pEdit; + CPDF_VariableText::Iterator* m_pVTIterator; +}; + +class CPWL_EditImpl_Provider : public CPDF_VariableText::Provider { + public: + explicit CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap); + ~CPWL_EditImpl_Provider() override; + + IPVT_FontMap* GetFontMap() const; + + // CPDF_VariableText::Provider: + int32_t GetCharWidth(int32_t nFontIndex, uint16_t word) override; + int32_t GetTypeAscent(int32_t nFontIndex) override; + int32_t GetTypeDescent(int32_t nFontIndex) override; + int32_t GetWordFontIndex(uint16_t word, + int32_t charset, + int32_t nFontIndex) override; + int32_t GetDefaultFontIndex() override; + bool IsLatinWord(uint16_t word) override; + + private: + IPVT_FontMap* m_pFontMap; +}; + +#endif // FPDFSDK_PWL_CPWL_EDIT_IMPL_H_ diff --git a/fpdfsdk/pwl/cpwl_font_map.cpp b/fpdfsdk/pwl/cpwl_font_map.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e5556ebb0a0ec52391674a65d8cbece437a72ca --- /dev/null +++ b/fpdfsdk/pwl/cpwl_font_map.cpp @@ -0,0 +1,408 @@ +// 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 "fpdfsdk/pwl/cpwl_font_map.h" + +#include + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/font/cpdf_fontencoding.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_parser.h" +#include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/fx_codepage.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +const char kDefaultFontName[] = "Helvetica"; + +const char* const g_sDEStandardFontName[] = {"Courier", + "Courier-Bold", + "Courier-BoldOblique", + "Courier-Oblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-BoldOblique", + "Helvetica-Oblique", + "Times-Roman", + "Times-Bold", + "Times-Italic", + "Times-BoldItalic", + "Symbol", + "ZapfDingbats"}; + +} // namespace + +CPWL_FontMap::CPWL_FontMap(CFX_SystemHandler* pSystemHandler) + : m_pSystemHandler(pSystemHandler) { + ASSERT(m_pSystemHandler); +} + +CPWL_FontMap::~CPWL_FontMap() { + Empty(); +} + +CPDF_Document* CPWL_FontMap::GetDocument() { + if (!m_pPDFDoc) { + if (CPDF_ModuleMgr::Get()) { + m_pPDFDoc = pdfium::MakeUnique(nullptr); + m_pPDFDoc->CreateNewDoc(); + } + } + return m_pPDFDoc.get(); +} + +CPDF_Font* CPWL_FontMap::GetPDFFont(int32_t nFontIndex) { + if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex]) + return m_Data[nFontIndex]->pFont; + + return nullptr; +} + +ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) { + if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex]) + return m_Data[nFontIndex]->sFontName; + + return ByteString(); +} + +bool CPWL_FontMap::KnowWord(int32_t nFontIndex, uint16_t word) { + return pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex] && + CharCodeFromUnicode(nFontIndex, word) >= 0; +} + +int32_t CPWL_FontMap::GetWordFontIndex(uint16_t word, + int32_t nCharset, + int32_t nFontIndex) { + if (nFontIndex > 0) { + if (KnowWord(nFontIndex, word)) + return nFontIndex; + } else { + if (const CPWL_FontMap_Data* pData = GetFontMapData(0)) { + if (nCharset == FX_CHARSET_Default || + pData->nCharset == FX_CHARSET_Symbol || nCharset == pData->nCharset) { + if (KnowWord(0, word)) + return 0; + } + } + } + + int32_t nNewFontIndex = + GetFontIndex(GetNativeFontName(nCharset), nCharset, true); + if (nNewFontIndex >= 0) { + if (KnowWord(nNewFontIndex, word)) + return nNewFontIndex; + } + nNewFontIndex = GetFontIndex("Arial Unicode MS", FX_CHARSET_Default, false); + if (nNewFontIndex >= 0) { + if (KnowWord(nNewFontIndex, word)) + return nNewFontIndex; + } + return -1; +} + +int32_t CPWL_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) { + if (!pdfium::IndexInBounds(m_Data, nFontIndex)) + return -1; + + CPWL_FontMap_Data* pData = m_Data[nFontIndex].get(); + if (!pData || !pData->pFont) + return -1; + + if (pData->pFont->IsUnicodeCompatible()) + return pData->pFont->CharCodeFromUnicode(word); + + return word < 0xFF ? word : -1; +} + +ByteString CPWL_FontMap::GetNativeFontName(int32_t nCharset) { + for (const auto& pData : m_NativeFont) { + if (pData && pData->nCharset == nCharset) + return pData->sFontName; + } + + ByteString sNew = GetNativeFont(nCharset); + if (sNew.IsEmpty()) + return ByteString(); + + auto pNewData = pdfium::MakeUnique(); + pNewData->nCharset = nCharset; + pNewData->sFontName = sNew; + m_NativeFont.push_back(std::move(pNewData)); + return sNew; +} + +void CPWL_FontMap::Empty() { + m_Data.clear(); + m_NativeFont.clear(); +} + +void CPWL_FontMap::Initialize() { + GetFontIndex(kDefaultFontName, FX_CHARSET_ANSI, false); +} + +bool CPWL_FontMap::IsStandardFont(const ByteString& sFontName) { + for (const char* name : g_sDEStandardFontName) { + if (sFontName == name) + return true; + } + + return false; +} + +int32_t CPWL_FontMap::FindFont(const ByteString& sFontName, int32_t nCharset) { + int32_t i = 0; + for (const auto& pData : m_Data) { + if (pData && + (nCharset == FX_CHARSET_Default || nCharset == pData->nCharset) && + (sFontName.IsEmpty() || pData->sFontName == sFontName)) { + return i; + } + ++i; + } + return -1; +} + +int32_t CPWL_FontMap::GetFontIndex(const ByteString& sFontName, + int32_t nCharset, + bool bFind) { + int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset); + if (nFontIndex >= 0) + return nFontIndex; + + ByteString sAlias; + CPDF_Font* pFont = bFind ? FindFontSameCharset(&sAlias, nCharset) : nullptr; + if (!pFont) { + ByteString sTemp = sFontName; + pFont = AddFontToDocument(GetDocument(), sTemp, nCharset); + sAlias = EncodeFontAlias(sTemp, nCharset); + } + AddedFont(pFont, sAlias); + return AddFontData(pFont, sAlias, nCharset); +} + +CPDF_Font* CPWL_FontMap::FindFontSameCharset(ByteString* sFontAlias, + int32_t nCharset) { + return nullptr; +} + +int32_t CPWL_FontMap::AddFontData(CPDF_Font* pFont, + const ByteString& sFontAlias, + int32_t nCharset) { + auto pNewData = pdfium::MakeUnique(); + pNewData->pFont = pFont; + pNewData->sFontName = sFontAlias; + pNewData->nCharset = nCharset; + m_Data.push_back(std::move(pNewData)); + return pdfium::CollectionSize(m_Data) - 1; +} + +void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias) {} + +ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) { + if (nCharset == FX_CHARSET_Default) + nCharset = GetNativeCharset(); + + ByteString sFontName = GetDefaultFontByCharset(nCharset); + if (!m_pSystemHandler->FindNativeTrueTypeFont(sFontName)) + return ByteString(); + + return sFontName; +} + +CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc, + ByteString& sFontName, + uint8_t nCharset) { + if (IsStandardFont(sFontName)) + return AddStandardFont(pDoc, sFontName); + + return AddSystemFont(pDoc, sFontName, nCharset); +} + +CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc, + ByteString& sFontName) { + if (!pDoc) + return nullptr; + + CPDF_Font* pFont = nullptr; + + if (sFontName == "ZapfDingbats") { + pFont = pDoc->AddStandardFont(sFontName.c_str(), nullptr); + } else { + CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI); + pFont = pDoc->AddStandardFont(sFontName.c_str(), &fe); + } + + return pFont; +} + +CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc, + ByteString& sFontName, + uint8_t nCharset) { + if (!pDoc) + return nullptr; + + if (sFontName.IsEmpty()) + sFontName = GetNativeFont(nCharset); + if (nCharset == FX_CHARSET_Default) + nCharset = GetNativeCharset(); + + return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName, + nCharset); +} + +ByteString CPWL_FontMap::EncodeFontAlias(const ByteString& sFontName, + int32_t nCharset) { + return EncodeFontAlias(sFontName) + ByteString::Format("_%02X", nCharset); +} + +ByteString CPWL_FontMap::EncodeFontAlias(const ByteString& sFontName) { + ByteString sRet = sFontName; + sRet.Remove(' '); + return sRet; +} + +const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const { + return pdfium::IndexInBounds(m_Data, nIndex) ? m_Data[nIndex].get() : nullptr; +} + +int32_t CPWL_FontMap::GetNativeCharset() { + uint8_t nCharset = FX_CHARSET_ANSI; + int32_t iCodePage = FXSYS_GetACP(); + switch (iCodePage) { + case FX_CODEPAGE_ShiftJIS: + nCharset = FX_CHARSET_ShiftJIS; + break; + case FX_CODEPAGE_ChineseSimplified: + nCharset = FX_CHARSET_ChineseSimplified; + break; + case FX_CODEPAGE_ChineseTraditional: + nCharset = FX_CHARSET_ChineseTraditional; + break; + case FX_CODEPAGE_MSWin_WesternEuropean: + nCharset = FX_CHARSET_ANSI; + break; + case FX_CODEPAGE_MSDOS_Thai: + nCharset = FX_CHARSET_Thai; + break; + case FX_CODEPAGE_Hangul: + nCharset = FX_CHARSET_Hangul; + break; + case FX_CODEPAGE_UTF16LE: + nCharset = FX_CHARSET_ANSI; + break; + case FX_CODEPAGE_MSWin_EasternEuropean: + nCharset = FX_CHARSET_MSWin_EasternEuropean; + break; + case FX_CODEPAGE_MSWin_Cyrillic: + nCharset = FX_CHARSET_MSWin_Cyrillic; + break; + case FX_CODEPAGE_MSWin_Greek: + nCharset = FX_CHARSET_MSWin_Greek; + break; + case FX_CODEPAGE_MSWin_Turkish: + nCharset = FX_CHARSET_MSWin_Turkish; + break; + case FX_CODEPAGE_MSWin_Hebrew: + nCharset = FX_CHARSET_MSWin_Hebrew; + break; + case FX_CODEPAGE_MSWin_Arabic: + nCharset = FX_CHARSET_MSWin_Arabic; + break; + case FX_CODEPAGE_MSWin_Baltic: + nCharset = FX_CHARSET_MSWin_Baltic; + break; + case FX_CODEPAGE_MSWin_Vietnamese: + nCharset = FX_CHARSET_MSWin_Vietnamese; + break; + case FX_CODEPAGE_Johab: + nCharset = FX_CHARSET_Johab; + break; + } + return nCharset; +} + +const FPDF_CharsetFontMap CPWL_FontMap::defaultTTFMap[] = { + {FX_CHARSET_ANSI, "Helvetica"}, + {FX_CHARSET_ChineseSimplified, "SimSun"}, + {FX_CHARSET_ChineseTraditional, "MingLiU"}, + {FX_CHARSET_ShiftJIS, "MS Gothic"}, + {FX_CHARSET_Hangul, "Batang"}, + {FX_CHARSET_MSWin_Cyrillic, "Arial"}, +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ || _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + {FX_CHARSET_MSWin_EasternEuropean, "Arial"}, +#else + {FX_CHARSET_MSWin_EasternEuropean, "Tahoma"}, +#endif + {FX_CHARSET_MSWin_Arabic, "Arial"}, + {-1, nullptr}}; + +ByteString CPWL_FontMap::GetDefaultFontByCharset(int32_t nCharset) { + int i = 0; + while (defaultTTFMap[i].charset != -1) { + if (nCharset == defaultTTFMap[i].charset) + return defaultTTFMap[i].fontname; + ++i; + } + return ""; +} + +int32_t CPWL_FontMap::CharSetFromUnicode(uint16_t word, int32_t nOldCharset) { + // to avoid CJK Font to show ASCII + if (word < 0x7F) + return FX_CHARSET_ANSI; + // follow the old charset + if (nOldCharset != FX_CHARSET_Default) + return nOldCharset; + + // find new charset + if ((word >= 0x4E00 && word <= 0x9FA5) || + (word >= 0xE7C7 && word <= 0xE7F3) || + (word >= 0x3000 && word <= 0x303F) || + (word >= 0x2000 && word <= 0x206F)) { + return FX_CHARSET_ChineseSimplified; + } + + if (((word >= 0x3040) && (word <= 0x309F)) || + ((word >= 0x30A0) && (word <= 0x30FF)) || + ((word >= 0x31F0) && (word <= 0x31FF)) || + ((word >= 0xFF00) && (word <= 0xFFEF))) { + return FX_CHARSET_ShiftJIS; + } + + if (((word >= 0xAC00) && (word <= 0xD7AF)) || + ((word >= 0x1100) && (word <= 0x11FF)) || + ((word >= 0x3130) && (word <= 0x318F))) { + return FX_CHARSET_Hangul; + } + + if (word >= 0x0E00 && word <= 0x0E7F) + return FX_CHARSET_Thai; + + if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF)) + return FX_CHARSET_MSWin_Greek; + + if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC)) + return FX_CHARSET_MSWin_Arabic; + + if (word >= 0x0590 && word <= 0x05FF) + return FX_CHARSET_MSWin_Hebrew; + + if (word >= 0x0400 && word <= 0x04FF) + return FX_CHARSET_MSWin_Cyrillic; + + if (word >= 0x0100 && word <= 0x024F) + return FX_CHARSET_MSWin_EasternEuropean; + + if (word >= 0x1E00 && word <= 0x1EFF) + return FX_CHARSET_MSWin_Vietnamese; + + return FX_CHARSET_ANSI; +} diff --git a/fpdfsdk/pwl/cpwl_font_map.h b/fpdfsdk/pwl/cpwl_font_map.h new file mode 100644 index 0000000000000000000000000000000000000000..592c3fafed57468d2ed419fd57f40232b0ae9865 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_font_map.h @@ -0,0 +1,93 @@ +// 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 FPDFSDK_PWL_CPWL_FONT_MAP_H_ +#define FPDFSDK_PWL_CPWL_FONT_MAP_H_ + +#include +#include + +#include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/fx_codepage.h" +#include "public/fpdf_sysfontinfo.h" + +class CPDF_Document; +class CFX_SystemHandler; + +struct CPWL_FontMap_Data { + CPDF_Font* pFont; + int32_t nCharset; + ByteString sFontName; +}; + +struct CPWL_FontMap_Native { + int32_t nCharset; + ByteString sFontName; +}; + +class CPWL_FontMap : public IPVT_FontMap { + public: + explicit CPWL_FontMap(CFX_SystemHandler* pSystemHandler); + ~CPWL_FontMap() override; + + // IPVT_FontMap + CPDF_Font* GetPDFFont(int32_t nFontIndex) override; + ByteString GetPDFFontAlias(int32_t nFontIndex) override; + int32_t GetWordFontIndex(uint16_t word, + int32_t nCharset, + int32_t nFontIndex) override; + int32_t CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) override; + int32_t CharSetFromUnicode(uint16_t word, int32_t nOldCharset) override; + + const CPWL_FontMap_Data* GetFontMapData(int32_t nIndex) const; + static int32_t GetNativeCharset(); + ByteString GetNativeFontName(int32_t nCharset); + + static ByteString GetDefaultFontByCharset(int32_t nCharset); + static const FPDF_CharsetFontMap defaultTTFMap[]; + + protected: + virtual void Initialize(); + virtual CPDF_Document* GetDocument(); + virtual CPDF_Font* FindFontSameCharset(ByteString* sFontAlias, + int32_t nCharset); + virtual void AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias); + + bool KnowWord(int32_t nFontIndex, uint16_t word); + + void Empty(); + int32_t GetFontIndex(const ByteString& sFontName, + int32_t nCharset, + bool bFind); + int32_t AddFontData(CPDF_Font* pFont, + const ByteString& sFontAlias, + int32_t nCharset = FX_CHARSET_Default); + + ByteString EncodeFontAlias(const ByteString& sFontName, int32_t nCharset); + ByteString EncodeFontAlias(const ByteString& sFontName); + + std::vector> m_Data; + std::vector> m_NativeFont; + + private: + int32_t FindFont(const ByteString& sFontName, + int32_t nCharset = FX_CHARSET_Default); + + ByteString GetNativeFont(int32_t nCharset); + CPDF_Font* AddFontToDocument(CPDF_Document* pDoc, + ByteString& sFontName, + uint8_t nCharset); + bool IsStandardFont(const ByteString& sFontName); + CPDF_Font* AddStandardFont(CPDF_Document* pDoc, ByteString& sFontName); + CPDF_Font* AddSystemFont(CPDF_Document* pDoc, + ByteString& sFontName, + uint8_t nCharset); + + std::unique_ptr m_pPDFDoc; + UnownedPtr const m_pSystemHandler; +}; + +#endif // FPDFSDK_PWL_CPWL_FONT_MAP_H_ diff --git a/fpdfsdk/pwl/cpwl_icon.cpp b/fpdfsdk/pwl/cpwl_icon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7669b3d2016c129a6ae0cc0e92537dd34034bfe --- /dev/null +++ b/fpdfsdk/pwl/cpwl_icon.cpp @@ -0,0 +1,131 @@ +// 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 "fpdfsdk/pwl/cpwl_icon.h" + +#include +#include + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +CPWL_Icon::CPWL_Icon() : m_pPDFStream(nullptr), m_pIconFit(nullptr) {} + +CPWL_Icon::~CPWL_Icon() {} + +std::pair CPWL_Icon::GetImageSize() { + if (!m_pPDFStream) + return {0.0f, 0.0f}; + + CPDF_Dictionary* pDict = m_pPDFStream->GetDict(); + if (!pDict) + return {0.0f, 0.0f}; + + CFX_FloatRect rect = pDict->GetRectFor("BBox"); + return {rect.right - rect.left, rect.top - rect.bottom}; +} + +CFX_Matrix CPWL_Icon::GetImageMatrix() { + if (!m_pPDFStream) + return CFX_Matrix(); + if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) + return pDict->GetMatrixFor("Matrix"); + return CFX_Matrix(); +} + +ByteString CPWL_Icon::GetImageAlias() { + if (!m_pPDFStream) + return ByteString(); + if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) + return pDict->GetStringFor("Name"); + return ByteString(); +} + +std::pair CPWL_Icon::GetIconPosition() { + if (!m_pIconFit) + return {0.0f, 0.0f}; + + CPDF_Array* pA = + m_pIconFit->GetDict() ? m_pIconFit->GetDict()->GetArrayFor("A") : nullptr; + if (!pA) + return {0.0f, 0.0f}; + + size_t dwCount = pA->GetCount(); + return {dwCount > 0 ? pA->GetNumberAt(0) : 0.0f, + dwCount > 1 ? pA->GetNumberAt(1) : 0.0f}; +} + +std::pair CPWL_Icon::GetScale() { + float fHScale = 1.0f; + float fVScale = 1.0f; + + if (!m_pPDFStream) + return {fHScale, fVScale}; + + CFX_FloatRect rcPlate = GetClientRect(); + float fPlateWidth = rcPlate.right - rcPlate.left; + float fPlateHeight = rcPlate.top - rcPlate.bottom; + + float fImageWidth; + float fImageHeight; + std::tie(fImageWidth, fImageHeight) = GetImageSize(); + + int32_t nScaleMethod = m_pIconFit ? m_pIconFit->GetScaleMethod() : 0; + + switch (nScaleMethod) { + default: + case 0: + fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); + fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); + break; + case 1: + if (fPlateWidth < fImageWidth) + fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); + if (fPlateHeight < fImageHeight) + fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); + break; + case 2: + if (fPlateWidth > fImageWidth) + fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); + if (fPlateHeight > fImageHeight) + fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); + break; + case 3: + break; + } + + float fMinScale; + if (m_pIconFit && m_pIconFit->IsProportionalScale()) { + fMinScale = std::min(fHScale, fVScale); + fHScale = fMinScale; + fVScale = fMinScale; + } + return {fHScale, fVScale}; +} + +std::pair CPWL_Icon::GetImageOffset() { + float fLeft; + float fBottom; + std::tie(fLeft, fBottom) = GetIconPosition(); + + float fImageWidth; + float fImageHeight; + std::tie(fImageWidth, fImageHeight) = GetImageSize(); + + float fHScale, fVScale; + std::tie(fHScale, fVScale) = GetScale(); + + float fImageFactWidth = fImageWidth * fHScale; + float fImageFactHeight = fImageHeight * fVScale; + + CFX_FloatRect rcPlate = GetClientRect(); + float fPlateWidth = rcPlate.right - rcPlate.left; + float fPlateHeight = rcPlate.top - rcPlate.bottom; + + return {(fPlateWidth - fImageFactWidth) * fLeft, + (fPlateHeight - fImageFactHeight) * fBottom}; +} diff --git a/fpdfsdk/pwl/cpwl_icon.h b/fpdfsdk/pwl/cpwl_icon.h new file mode 100644 index 0000000000000000000000000000000000000000..df88465a5a611cb79e16678910b52a2599f906a8 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_icon.h @@ -0,0 +1,44 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_PWL_CPWL_ICON_H_ +#define FPDFSDK_PWL_CPWL_ICON_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_Icon : public CPWL_Wnd { + public: + CPWL_Icon(); + ~CPWL_Icon() override; + + void SetIconFit(CPDF_IconFit* pIconFit) { m_pIconFit = pIconFit; } + void SetPDFStream(CPDF_Stream* pStream) { m_pPDFStream = pStream; } + + // horizontal scale, vertical scale + std::pair GetScale(); + + // x, y + std::pair GetImageOffset(); + + CFX_Matrix GetImageMatrix(); + ByteString GetImageAlias(); + + private: + // left, bottom + std::pair GetIconPosition(); + + // width, height + std::pair GetImageSize(); + + UnownedPtr m_pPDFStream; + UnownedPtr m_pIconFit; +}; + +#endif // FPDFSDK_PWL_CPWL_ICON_H_ diff --git a/fpdfsdk/pwl/cpwl_list_box.cpp b/fpdfsdk/pwl/cpwl_list_box.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7c02e4692e55a043b9d586b5242a97ef132d030 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_box.cpp @@ -0,0 +1,385 @@ +// 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 "fpdfsdk/pwl/cpwl_list_box.h" + +#include + +#include "core/fxge/cfx_renderdevice.h" +#include "fpdfsdk/pwl/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" +#include "fpdfsdk/pwl/cpwl_edit_impl.h" +#include "fpdfsdk/pwl/cpwl_list_impl.h" +#include "fpdfsdk/pwl/cpwl_scroll_bar.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "public/fpdf_fwlevent.h" +#include "third_party/base/ptr_util.h" + +CPWL_List_Notify::CPWL_List_Notify(CPWL_ListBox* pList) : m_pList(pList) { + ASSERT(m_pList); +} + +CPWL_List_Notify::~CPWL_List_Notify() {} + +void CPWL_List_Notify::IOnSetScrollInfoY(float fPlateMin, + float fPlateMax, + float fContentMin, + float fContentMax, + float fSmallStep, + float fBigStep) { + PWL_SCROLL_INFO Info; + Info.fPlateWidth = fPlateMax - fPlateMin; + Info.fContentMin = fContentMin; + Info.fContentMax = fContentMax; + Info.fSmallStep = fSmallStep; + Info.fBigStep = fBigStep; + m_pList->SetScrollInfo(Info); + + CPWL_ScrollBar* pScroll = m_pList->GetVScrollBar(); + if (!pScroll) + return; + + if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) || + IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) { + if (pScroll->IsVisible()) { + pScroll->SetVisible(false); + m_pList->RePosChildWnd(); + } + } else { + if (!pScroll->IsVisible()) { + pScroll->SetVisible(true); + m_pList->RePosChildWnd(); + } + } +} + +void CPWL_List_Notify::IOnSetScrollPosY(float fy) { + m_pList->SetScrollPosition(fy); +} + +void CPWL_List_Notify::IOnInvalidateRect(CFX_FloatRect* pRect) { + m_pList->InvalidateRect(pRect); +} + +CPWL_ListBox::CPWL_ListBox() + : m_pList(new CPWL_ListCtrl), + m_bMouseDown(false), + m_bHoverSel(false), + m_pFillerNotify(nullptr) {} + +CPWL_ListBox::~CPWL_ListBox() {} + +ByteString CPWL_ListBox::GetClassName() const { + return "CPWL_ListBox"; +} + +void CPWL_ListBox::OnCreated() { + m_pList->SetFontMap(GetFontMap()); + m_pListNotify = pdfium::MakeUnique(this); + m_pList->SetNotify(m_pListNotify.get()); + + SetHoverSel(HasFlag(PLBS_HOVERSEL)); + m_pList->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL)); + m_pList->SetFontSize(GetCreationParams().fFontSize); + + m_bHoverSel = HasFlag(PLBS_HOVERSEL); +} + +void CPWL_ListBox::OnDestroy() { + // Make sure the notifier is removed from the list as we are about to + // destroy the notifier and don't want to leave a dangling pointer. + m_pList->SetNotify(nullptr); + m_pListNotify.reset(); +} + +void CPWL_ListBox::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device); + + CFX_FloatRect rcPlate = m_pList->GetPlateRect(); + CFX_FloatRect rcList = GetListRect(); + CFX_FloatRect rcClient = GetClientRect(); + + for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) { + CFX_FloatRect rcItem = m_pList->GetItemRect(i); + if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom) + continue; + + CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f); + if (CPWL_EditImpl* pEdit = m_pList->GetItemEdit(i)) { + CFX_FloatRect rcContent = pEdit->GetContentRect(); + if (rcContent.Width() > rcClient.Width()) + rcItem.Intersect(rcList); + else + rcItem.Intersect(rcClient); + } + + if (m_pList->IsItemSelected(i)) { + CFX_SystemHandler* pSysHandler = GetSystemHandler(); + if (pSysHandler && pSysHandler->IsSelectionImplemented()) { + CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pList->GetItemEdit(i), + GetTextColor().ToFXColor(255), rcList, ptOffset, + nullptr, pSysHandler, m_pFormFiller.Get()); + pSysHandler->OutputSelectedRect(m_pFormFiller.Get(), rcItem); + } else { + pDevice->DrawFillRect(&mtUser2Device, rcItem, + ArgbEncode(255, 0, 51, 113)); + CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pList->GetItemEdit(i), + ArgbEncode(255, 255, 255, 255), rcList, + ptOffset, nullptr, pSysHandler, + m_pFormFiller.Get()); + } + } else { + CFX_SystemHandler* pSysHandler = GetSystemHandler(); + CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pList->GetItemEdit(i), + GetTextColor().ToFXColor(255), rcList, ptOffset, + nullptr, pSysHandler, nullptr); + } + } +} + +bool CPWL_ListBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) { + CPWL_Wnd::OnKeyDown(nChar, nFlag); + + switch (nChar) { + default: + return false; + case FWL_VKEY_Up: + case FWL_VKEY_Down: + case FWL_VKEY_Home: + case FWL_VKEY_Left: + case FWL_VKEY_End: + case FWL_VKEY_Right: + break; + } + + switch (nChar) { + case FWL_VKEY_Up: + m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Down: + m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Home: + m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Left: + m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_End: + m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Right: + m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + break; + case FWL_VKEY_Delete: + break; + } + OnNotifySelectionChanged(true, nFlag); + return true; +} + +bool CPWL_ListBox::OnChar(uint16_t nChar, uint32_t nFlag) { + CPWL_Wnd::OnChar(nChar, nFlag); + + if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag))) + return false; + + OnNotifySelectionChanged(true, nFlag); + return true; +} + +bool CPWL_ListBox::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + + if (ClientHitTest(point)) { + m_bMouseDown = true; + SetFocus(); + SetCapture(); + + m_pList->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + } + + return true; +} + +bool CPWL_ListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + + if (m_bMouseDown) { + ReleaseCapture(); + m_bMouseDown = false; + } + OnNotifySelectionChanged(false, nFlag); + return true; +} + +void CPWL_ListBox::SetHoverSel(bool bHoverSel) { + m_bHoverSel = bHoverSel; +} + +bool CPWL_ListBox::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnMouseMove(point, nFlag); + + if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point)) + m_pList->Select(m_pList->GetItemIndex(point)); + if (m_bMouseDown) + m_pList->OnMouseMove(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + + return true; +} + +void CPWL_ListBox::SetScrollInfo(const PWL_SCROLL_INFO& info) { + if (CPWL_Wnd* pChild = GetVScrollBar()) + pChild->SetScrollInfo(info); +} + +void CPWL_ListBox::SetScrollPosition(float pos) { + if (CPWL_Wnd* pChild = GetVScrollBar()) + pChild->SetScrollPosition(pos); +} + +void CPWL_ListBox::ScrollWindowVertically(float pos) { + m_pList->SetScrollPos(CFX_PointF(0, pos)); +} + +void CPWL_ListBox::KillFocus() { + CPWL_Wnd::KillFocus(); +} + +bool CPWL_ListBox::RePosChildWnd() { + if (!CPWL_Wnd::RePosChildWnd()) + return false; + + m_pList->SetPlateRect(GetListRect()); + return true; +} + +bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown, uint32_t nFlag) { + if (!m_pFillerNotify) + return false; + + CPWL_Wnd::ObservedPtr thisObserved(this); + + WideString swChange = GetText(); + WideString strChangeEx; + int nSelStart = 0; + int nSelEnd = swChange.GetLength(); + bool bRC; + bool bExit; + std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( + GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, bKeyDown, + nFlag); + + if (!thisObserved) + return false; + + return bExit; +} + +CFX_FloatRect CPWL_ListBox::GetFocusRect() const { + if (m_pList->IsMultipleSel()) { + CFX_FloatRect rcCaret = m_pList->GetItemRect(m_pList->GetCaret()); + rcCaret.Intersect(GetClientRect()); + return rcCaret; + } + + return CPWL_Wnd::GetFocusRect(); +} + +void CPWL_ListBox::AddString(const WideString& str) { + m_pList->AddString(str); +} + +WideString CPWL_ListBox::GetText() const { + return m_pList->GetText(); +} + +void CPWL_ListBox::SetFontSize(float fFontSize) { + m_pList->SetFontSize(fFontSize); +} + +float CPWL_ListBox::GetFontSize() const { + return m_pList->GetFontSize(); +} + +void CPWL_ListBox::Select(int32_t nItemIndex) { + m_pList->Select(nItemIndex); +} + +void CPWL_ListBox::SetCaret(int32_t nItemIndex) { + m_pList->SetCaret(nItemIndex); +} + +void CPWL_ListBox::SetTopVisibleIndex(int32_t nItemIndex) { + m_pList->SetTopItem(nItemIndex); +} + +void CPWL_ListBox::ScrollToListItem(int32_t nItemIndex) { + m_pList->ScrollToListItem(nItemIndex); +} + +void CPWL_ListBox::ResetContent() { + m_pList->Empty(); +} + +void CPWL_ListBox::Reset() { + m_pList->Cancel(); +} + +bool CPWL_ListBox::IsMultipleSel() const { + return m_pList->IsMultipleSel(); +} + +int32_t CPWL_ListBox::GetCaretIndex() const { + return m_pList->GetCaret(); +} + +int32_t CPWL_ListBox::GetCurSel() const { + return m_pList->GetSelect(); +} + +bool CPWL_ListBox::IsItemSelected(int32_t nItemIndex) const { + return m_pList->IsItemSelected(nItemIndex); +} + +int32_t CPWL_ListBox::GetTopVisibleIndex() const { + m_pList->ScrollToListItem(m_pList->GetFirstSelected()); + return m_pList->GetTopItem(); +} + +int32_t CPWL_ListBox::GetCount() const { + return m_pList->GetCount(); +} + +int32_t CPWL_ListBox::FindNext(int32_t nIndex, wchar_t nChar) const { + return m_pList->FindNext(nIndex, nChar); +} + +CFX_FloatRect CPWL_ListBox::GetContentRect() const { + return m_pList->GetContentRect(); +} + +float CPWL_ListBox::GetFirstHeight() const { + return m_pList->GetFirstHeight(); +} + +CFX_FloatRect CPWL_ListBox::GetListRect() const { + float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); + return GetWindowRect().GetDeflated(width, width); +} + +bool CPWL_ListBox::OnMouseWheel(short zDelta, + const CFX_PointF& point, + uint32_t nFlag) { + if (zDelta < 0) + m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + else + m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)); + + OnNotifySelectionChanged(false, nFlag); + return true; +} diff --git a/fpdfsdk/pwl/cpwl_list_box.h b/fpdfsdk/pwl/cpwl_list_box.h new file mode 100644 index 0000000000000000000000000000000000000000..9a725d14e3930e3fa9f4bdaf38d4cb691200e26e --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_box.h @@ -0,0 +1,108 @@ +// 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 FPDFSDK_PWL_CPWL_LIST_BOX_H_ +#define FPDFSDK_PWL_CPWL_LIST_BOX_H_ + +#include + +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_ListCtrl; +class CPWL_List_Notify; +class CPWL_ListBox; +class IPWL_Filler_Notify; +struct CPVT_WordPlace; + +class CPWL_List_Notify { + public: + explicit CPWL_List_Notify(CPWL_ListBox* pList); + ~CPWL_List_Notify(); + + void IOnSetScrollInfoY(float fPlateMin, + float fPlateMax, + float fContentMin, + float fContentMax, + float fSmallStep, + float fBigStep); + void IOnSetScrollPosY(float fy); + void IOnInvalidateRect(CFX_FloatRect* pRect); + + private: + UnownedPtr m_pList; +}; + +class CPWL_ListBox : public CPWL_Wnd { + public: + CPWL_ListBox(); + ~CPWL_ListBox() override; + + // CPWL_Wnd + ByteString GetClassName() const override; + void OnCreated() override; + void OnDestroy() override; + void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; + bool OnMouseWheel(short zDelta, + const CFX_PointF& point, + uint32_t nFlag) override; + void KillFocus() override; + void SetScrollInfo(const PWL_SCROLL_INFO& info) override; + void SetScrollPosition(float pos) override; + void ScrollWindowVertically(float pos) override; + bool RePosChildWnd() override; + CFX_FloatRect GetFocusRect() const override; + void SetFontSize(float fFontSize) override; + float GetFontSize() const override; + + virtual WideString GetText() const; + + bool OnNotifySelectionChanged(bool bKeyDown, uint32_t nFlag); + + void AddString(const WideString& str); + void SetTopVisibleIndex(int32_t nItemIndex); + void ScrollToListItem(int32_t nItemIndex); + void ResetContent(); + void Reset(); + void Select(int32_t nItemIndex); + void SetCaret(int32_t nItemIndex); + void SetHoverSel(bool bHoverSel); + + int32_t GetCount() const; + bool IsMultipleSel() const; + int32_t GetCaretIndex() const; + int32_t GetCurSel() const; + bool IsItemSelected(int32_t nItemIndex) const; + int32_t GetTopVisibleIndex() const; + int32_t FindNext(int32_t nIndex, wchar_t nChar) const; + CFX_FloatRect GetContentRect() const; + float GetFirstHeight() const; + CFX_FloatRect GetListRect() const; + + void SetFillerNotify(IPWL_Filler_Notify* pNotify) { + m_pFillerNotify = pNotify; + } + + void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; } + + protected: + std::unique_ptr m_pList; + std::unique_ptr m_pListNotify; + bool m_bMouseDown; + bool m_bHoverSel; + UnownedPtr m_pFillerNotify; + + private: + UnownedPtr m_pFormFiller; +}; + +#endif // FPDFSDK_PWL_CPWL_LIST_BOX_H_ diff --git a/fpdfsdk/pwl/cpwl_list_impl.cpp b/fpdfsdk/pwl/cpwl_list_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da455d06cbe6b7d598cfd0a240a4434c58213ae8 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_impl.cpp @@ -0,0 +1,637 @@ +// 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 "fpdfsdk/pwl/cpwl_list_impl.h" + +#include +#include + +#include "core/fpdfdoc/cpvt_word.h" +#include "core/fxcrt/fx_extension.h" +#include "fpdfsdk/pwl/cpwl_edit_impl.h" +#include "fpdfsdk/pwl/cpwl_list_box.h" +#include "third_party/base/stl_util.h" + +CPWL_ListCtrl::Item::Item() + : m_pEdit(new CPWL_EditImpl), + m_bSelected(false), + m_rcListItem(0.0f, 0.0f, 0.0f, 0.0f) { + m_pEdit->SetAlignmentV(1, true); + m_pEdit->Initialize(); +} + +CPWL_ListCtrl::Item::~Item() {} + +void CPWL_ListCtrl::Item::SetFontMap(IPVT_FontMap* pFontMap) { + m_pEdit->SetFontMap(pFontMap); +} + +void CPWL_ListCtrl::Item::SetText(const WideString& text) { + m_pEdit->SetText(text); +} + +void CPWL_ListCtrl::Item::SetFontSize(float fFontSize) { + m_pEdit->SetFontSize(fFontSize); +} + +float CPWL_ListCtrl::Item::GetItemHeight() const { + return m_pEdit->GetContentRect().Height(); +} + +uint16_t CPWL_ListCtrl::Item::GetFirstChar() const { + CPVT_Word word; + CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator(); + pIterator->SetAt(1); + pIterator->GetWord(word); + return word.Word; +} + +WideString CPWL_ListCtrl::Item::GetText() const { + return m_pEdit->GetText(); +} + +CPLST_Select::CPLST_Select() {} + +CPLST_Select::~CPLST_Select() {} + +void CPLST_Select::Add(int32_t nItemIndex) { + m_Items[nItemIndex] = SELECTING; +} + +void CPLST_Select::Add(int32_t nBeginIndex, int32_t nEndIndex) { + if (nBeginIndex > nEndIndex) + std::swap(nBeginIndex, nEndIndex); + + for (int32_t i = nBeginIndex; i <= nEndIndex; ++i) + Add(i); +} + +void CPLST_Select::Sub(int32_t nItemIndex) { + auto it = m_Items.find(nItemIndex); + if (it != m_Items.end()) + it->second = DESELECTING; +} + +void CPLST_Select::Sub(int32_t nBeginIndex, int32_t nEndIndex) { + if (nBeginIndex > nEndIndex) + std::swap(nBeginIndex, nEndIndex); + + for (int32_t i = nBeginIndex; i <= nEndIndex; ++i) + Sub(i); +} + +void CPLST_Select::DeselectAll() { + for (auto& item : m_Items) + item.second = DESELECTING; +} + +void CPLST_Select::Done() { + auto it = m_Items.begin(); + while (it != m_Items.end()) { + if (it->second == DESELECTING) + it = m_Items.erase(it); + else + (it++)->second = NORMAL; + } +} + +CPWL_ListCtrl::CPWL_ListCtrl() + : m_pNotify(nullptr), + m_bNotifyFlag(false), + m_nSelItem(-1), + m_nFootIndex(-1), + m_bCtrlSel(false), + m_nCaretIndex(-1), + m_fFontSize(0.0f), + m_pFontMap(nullptr), + m_bMultiple(false) {} + +CPWL_ListCtrl::~CPWL_ListCtrl() { + Empty(); +} + +CFX_PointF CPWL_ListCtrl::InToOut(const CFX_PointF& point) const { + CFX_FloatRect rcPlate = m_rcPlate; + return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left), + point.y - (m_ptScrollPos.y - rcPlate.top)); +} + +CFX_PointF CPWL_ListCtrl::OutToIn(const CFX_PointF& point) const { + CFX_FloatRect rcPlate = m_rcPlate; + return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left), + point.y + (m_ptScrollPos.y - rcPlate.top)); +} + +CFX_FloatRect CPWL_ListCtrl::InToOut(const CFX_FloatRect& rect) const { + CFX_PointF ptLeftBottom = InToOut(CFX_PointF(rect.left, rect.bottom)); + CFX_PointF ptRightTop = InToOut(CFX_PointF(rect.right, rect.top)); + return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, + ptRightTop.y); +} + +CFX_FloatRect CPWL_ListCtrl::OutToIn(const CFX_FloatRect& rect) const { + CFX_PointF ptLeftBottom = OutToIn(CFX_PointF(rect.left, rect.bottom)); + CFX_PointF ptRightTop = OutToIn(CFX_PointF(rect.right, rect.top)); + return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, + ptRightTop.y); +} + +CFX_PointF CPWL_ListCtrl::InnerToOuter(const CFX_PointF& point) const { + return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y); +} + +CFX_PointF CPWL_ListCtrl::OuterToInner(const CFX_PointF& point) const { + return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y); +} + +CFX_FloatRect CPWL_ListCtrl::InnerToOuter(const CFX_FloatRect& rect) const { + CFX_PointF ptLeftTop = InnerToOuter(CFX_PointF(rect.left, rect.top)); + CFX_PointF ptRightBottom = InnerToOuter(CFX_PointF(rect.right, rect.bottom)); + return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x, + ptLeftTop.y); +} + +CFX_FloatRect CPWL_ListCtrl::OuterToInner(const CFX_FloatRect& rect) const { + CFX_PointF ptLeftTop = OuterToInner(CFX_PointF(rect.left, rect.top)); + CFX_PointF ptRightBottom = OuterToInner(CFX_PointF(rect.right, rect.bottom)); + return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x, + ptLeftTop.y); +} + +void CPWL_ListCtrl::OnMouseDown(const CFX_PointF& point, + bool bShift, + bool bCtrl) { + int32_t nHitIndex = GetItemIndex(point); + + if (IsMultipleSel()) { + if (bCtrl) { + if (IsItemSelected(nHitIndex)) { + m_aSelItems.Sub(nHitIndex); + SelectItems(); + m_bCtrlSel = false; + } else { + m_aSelItems.Add(nHitIndex); + SelectItems(); + m_bCtrlSel = true; + } + + m_nFootIndex = nHitIndex; + } else if (bShift) { + m_aSelItems.DeselectAll(); + m_aSelItems.Add(m_nFootIndex, nHitIndex); + SelectItems(); + } else { + m_aSelItems.DeselectAll(); + m_aSelItems.Add(nHitIndex); + SelectItems(); + + m_nFootIndex = nHitIndex; + } + + SetCaret(nHitIndex); + } else { + SetSingleSelect(nHitIndex); + } + + if (!IsItemVisible(nHitIndex)) + ScrollToListItem(nHitIndex); +} + +void CPWL_ListCtrl::OnMouseMove(const CFX_PointF& point, + bool bShift, + bool bCtrl) { + int32_t nHitIndex = GetItemIndex(point); + + if (IsMultipleSel()) { + if (bCtrl) { + if (m_bCtrlSel) + m_aSelItems.Add(m_nFootIndex, nHitIndex); + else + m_aSelItems.Sub(m_nFootIndex, nHitIndex); + + SelectItems(); + } else { + m_aSelItems.DeselectAll(); + m_aSelItems.Add(m_nFootIndex, nHitIndex); + SelectItems(); + } + + SetCaret(nHitIndex); + } else { + SetSingleSelect(nHitIndex); + } + + if (!IsItemVisible(nHitIndex)) + ScrollToListItem(nHitIndex); +} + +void CPWL_ListCtrl::OnVK(int32_t nItemIndex, bool bShift, bool bCtrl) { + if (IsMultipleSel()) { + if (nItemIndex >= 0 && nItemIndex < GetCount()) { + if (bCtrl) { + } else if (bShift) { + m_aSelItems.DeselectAll(); + m_aSelItems.Add(m_nFootIndex, nItemIndex); + SelectItems(); + } else { + m_aSelItems.DeselectAll(); + m_aSelItems.Add(nItemIndex); + SelectItems(); + m_nFootIndex = nItemIndex; + } + + SetCaret(nItemIndex); + } + } else { + SetSingleSelect(nItemIndex); + } + + if (!IsItemVisible(nItemIndex)) + ScrollToListItem(nItemIndex); +} + +void CPWL_ListCtrl::OnVK_UP(bool bShift, bool bCtrl) { + OnVK(IsMultipleSel() ? GetCaret() - 1 : GetSelect() - 1, bShift, bCtrl); +} + +void CPWL_ListCtrl::OnVK_DOWN(bool bShift, bool bCtrl) { + OnVK(IsMultipleSel() ? GetCaret() + 1 : GetSelect() + 1, bShift, bCtrl); +} + +void CPWL_ListCtrl::OnVK_LEFT(bool bShift, bool bCtrl) { + OnVK(0, bShift, bCtrl); +} + +void CPWL_ListCtrl::OnVK_RIGHT(bool bShift, bool bCtrl) { + OnVK(GetCount() - 1, bShift, bCtrl); +} + +void CPWL_ListCtrl::OnVK_HOME(bool bShift, bool bCtrl) { + OnVK(0, bShift, bCtrl); +} + +void CPWL_ListCtrl::OnVK_END(bool bShift, bool bCtrl) { + OnVK(GetCount() - 1, bShift, bCtrl); +} + +bool CPWL_ListCtrl::OnChar(uint16_t nChar, bool bShift, bool bCtrl) { + int32_t nIndex = GetLastSelected(); + int32_t nFindIndex = FindNext(nIndex, nChar); + + if (nFindIndex != nIndex) { + OnVK(nFindIndex, bShift, bCtrl); + return true; + } + return false; +} + +void CPWL_ListCtrl::SetPlateRect(const CFX_FloatRect& rect) { + m_rcPlate = rect; + m_ptScrollPos.x = rect.left; + SetScrollPos(CFX_PointF(rect.left, rect.top)); + ReArrange(0); + InvalidateItem(-1); +} + +CFX_FloatRect CPWL_ListCtrl::GetItemRect(int32_t nIndex) const { + return InToOut(GetItemRectInternal(nIndex)); +} + +CFX_FloatRect CPWL_ListCtrl::GetItemRectInternal(int32_t nIndex) const { + if (!pdfium::IndexInBounds(m_ListItems, nIndex) || !m_ListItems[nIndex]) + return CFX_FloatRect(); + + CFX_FloatRect rcItem = m_ListItems[nIndex]->GetRect(); + rcItem.left = 0.0f; + rcItem.right = m_rcPlate.Width(); + return InnerToOuter(rcItem); +} + +void CPWL_ListCtrl::AddString(const WideString& str) { + AddItem(str); + ReArrange(GetCount() - 1); +} + +void CPWL_ListCtrl::SetMultipleSelect(int32_t nItemIndex, bool bSelected) { + if (!IsValid(nItemIndex)) + return; + + if (bSelected != IsItemSelected(nItemIndex)) { + if (bSelected) { + SetItemSelect(nItemIndex, true); + InvalidateItem(nItemIndex); + } else { + SetItemSelect(nItemIndex, false); + InvalidateItem(nItemIndex); + } + } +} + +void CPWL_ListCtrl::SetSingleSelect(int32_t nItemIndex) { + if (!IsValid(nItemIndex)) + return; + + if (m_nSelItem != nItemIndex) { + if (m_nSelItem >= 0) { + SetItemSelect(m_nSelItem, false); + InvalidateItem(m_nSelItem); + } + + SetItemSelect(nItemIndex, true); + InvalidateItem(nItemIndex); + m_nSelItem = nItemIndex; + } +} + +void CPWL_ListCtrl::SetCaret(int32_t nItemIndex) { + if (!IsValid(nItemIndex)) + return; + + if (IsMultipleSel()) { + int32_t nOldIndex = m_nCaretIndex; + + if (nOldIndex != nItemIndex) { + m_nCaretIndex = nItemIndex; + InvalidateItem(nOldIndex); + InvalidateItem(nItemIndex); + } + } +} + +void CPWL_ListCtrl::InvalidateItem(int32_t nItemIndex) { + if (m_pNotify) { + if (nItemIndex == -1) { + if (!m_bNotifyFlag) { + m_bNotifyFlag = true; + CFX_FloatRect rcRefresh = m_rcPlate; + m_pNotify->IOnInvalidateRect(&rcRefresh); + m_bNotifyFlag = false; + } + } else { + if (!m_bNotifyFlag) { + m_bNotifyFlag = true; + CFX_FloatRect rcRefresh = GetItemRect(nItemIndex); + rcRefresh.left -= 1.0f; + rcRefresh.right += 1.0f; + rcRefresh.bottom -= 1.0f; + rcRefresh.top += 1.0f; + + m_pNotify->IOnInvalidateRect(&rcRefresh); + m_bNotifyFlag = false; + } + } + } +} + +void CPWL_ListCtrl::SelectItems() { + for (const auto& item : m_aSelItems) { + if (item.second != CPLST_Select::NORMAL) + SetMultipleSelect(item.first, item.second == CPLST_Select::SELECTING); + } + m_aSelItems.Done(); +} + +void CPWL_ListCtrl::Select(int32_t nItemIndex) { + if (!IsValid(nItemIndex)) + return; + + if (IsMultipleSel()) { + m_aSelItems.Add(nItemIndex); + SelectItems(); + } else { + SetSingleSelect(nItemIndex); + } +} + +bool CPWL_ListCtrl::IsItemVisible(int32_t nItemIndex) const { + CFX_FloatRect rcPlate = m_rcPlate; + CFX_FloatRect rcItem = GetItemRect(nItemIndex); + + return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top; +} + +void CPWL_ListCtrl::ScrollToListItem(int32_t nItemIndex) { + if (!IsValid(nItemIndex)) + return; + + CFX_FloatRect rcPlate = m_rcPlate; + CFX_FloatRect rcItem = GetItemRectInternal(nItemIndex); + CFX_FloatRect rcItemCtrl = GetItemRect(nItemIndex); + + if (IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) { + if (IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) { + SetScrollPosY(rcItem.bottom + rcPlate.Height()); + } + } else if (IsFloatBigger(rcItemCtrl.top, rcPlate.top)) { + if (IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) { + SetScrollPosY(rcItem.top); + } + } +} + +void CPWL_ListCtrl::SetScrollInfo() { + if (m_pNotify) { + CFX_FloatRect rcPlate = m_rcPlate; + CFX_FloatRect rcContent = GetContentRectInternal(); + + if (!m_bNotifyFlag) { + m_bNotifyFlag = true; + m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, + rcContent.bottom, rcContent.top, + GetFirstHeight(), rcPlate.Height()); + m_bNotifyFlag = false; + } + } +} + +void CPWL_ListCtrl::SetScrollPos(const CFX_PointF& point) { + SetScrollPosY(point.y); +} + +void CPWL_ListCtrl::SetScrollPosY(float fy) { + if (!IsFloatEqual(m_ptScrollPos.y, fy)) { + CFX_FloatRect rcPlate = m_rcPlate; + CFX_FloatRect rcContent = GetContentRectInternal(); + + if (rcPlate.Height() > rcContent.Height()) { + fy = rcPlate.top; + } else { + if (IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) { + fy = rcContent.bottom + rcPlate.Height(); + } else if (IsFloatBigger(fy, rcContent.top)) { + fy = rcContent.top; + } + } + + m_ptScrollPos.y = fy; + InvalidateItem(-1); + + if (m_pNotify) { + if (!m_bNotifyFlag) { + m_bNotifyFlag = true; + m_pNotify->IOnSetScrollPosY(fy); + m_bNotifyFlag = false; + } + } + } +} + +CFX_FloatRect CPWL_ListCtrl::GetContentRectInternal() const { + return InnerToOuter(m_rcContent); +} + +CFX_FloatRect CPWL_ListCtrl::GetContentRect() const { + return InToOut(GetContentRectInternal()); +} + +void CPWL_ListCtrl::ReArrange(int32_t nItemIndex) { + float fPosY = 0.0f; + if (pdfium::IndexInBounds(m_ListItems, nItemIndex - 1) && + m_ListItems[nItemIndex - 1]) { + fPosY = m_ListItems[nItemIndex - 1]->GetRect().bottom; + } + for (const auto& pListItem : m_ListItems) { + if (pListItem) { + float fListItemHeight = pListItem->GetItemHeight(); + pListItem->SetRect( + CFX_FloatRect(0.0f, fPosY + fListItemHeight, 0.0f, fPosY)); + fPosY += fListItemHeight; + } + } + SetContentRect(CFX_FloatRect(0.0f, fPosY, 0.0f, 0.0f)); + SetScrollInfo(); +} + +void CPWL_ListCtrl::SetTopItem(int32_t nIndex) { + if (IsValid(nIndex)) { + CFX_FloatRect rcItem = GetItemRectInternal(nIndex); + SetScrollPosY(rcItem.top); + } +} + +int32_t CPWL_ListCtrl::GetTopItem() const { + int32_t nItemIndex = GetItemIndex(GetBTPoint()); + if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1)) + nItemIndex += 1; + + return nItemIndex; +} + +void CPWL_ListCtrl::Empty() { + m_ListItems.clear(); + InvalidateItem(-1); +} + +void CPWL_ListCtrl::Cancel() { + m_aSelItems.DeselectAll(); +} + +int32_t CPWL_ListCtrl::GetItemIndex(const CFX_PointF& point) const { + CFX_PointF pt = OuterToInner(OutToIn(point)); + bool bFirst = true; + bool bLast = true; + for (const auto& pListItem : m_ListItems) { + if (!pListItem) + continue; + CFX_FloatRect rcListItem = pListItem->GetRect(); + if (IsFloatBigger(pt.y, rcListItem.top)) + bFirst = false; + if (IsFloatSmaller(pt.y, rcListItem.bottom)) + bLast = false; + if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) + return &pListItem - &m_ListItems.front(); + } + if (bFirst) + return 0; + if (bLast) + return pdfium::CollectionSize(m_ListItems) - 1; + return -1; +} + +WideString CPWL_ListCtrl::GetText() const { + if (IsMultipleSel()) + return GetItemText(m_nCaretIndex); + return GetItemText(m_nSelItem); +} + +void CPWL_ListCtrl::AddItem(const WideString& str) { + auto pListItem = pdfium::MakeUnique(); + pListItem->SetFontMap(m_pFontMap.Get()); + pListItem->SetFontSize(m_fFontSize); + pListItem->SetText(str); + m_ListItems.push_back(std::move(pListItem)); +} + +CPWL_EditImpl* CPWL_ListCtrl::GetItemEdit(int32_t nIndex) const { + if (!pdfium::IndexInBounds(m_ListItems, nIndex) || !m_ListItems[nIndex]) + return nullptr; + return m_ListItems[nIndex]->GetEdit(); +} + +int32_t CPWL_ListCtrl::GetCount() const { + return pdfium::CollectionSize(m_ListItems); +} + +float CPWL_ListCtrl::GetFirstHeight() const { + if (m_ListItems.empty() || !m_ListItems.front()) + return 1.0f; + return m_ListItems.front()->GetItemHeight(); +} + +int32_t CPWL_ListCtrl::GetFirstSelected() const { + int32_t i = 0; + for (const auto& pListItem : m_ListItems) { + if (pListItem && pListItem->IsSelected()) + return i; + ++i; + } + return -1; +} + +int32_t CPWL_ListCtrl::GetLastSelected() const { + for (auto iter = m_ListItems.rbegin(); iter != m_ListItems.rend(); ++iter) { + if (*iter && (*iter)->IsSelected()) + return &*iter - &m_ListItems.front(); + } + return -1; +} + +int32_t CPWL_ListCtrl::FindNext(int32_t nIndex, wchar_t nChar) const { + int32_t nCircleIndex = nIndex; + int32_t sz = pdfium::CollectionSize(m_ListItems); + for (int32_t i = 0; i < sz; i++) { + nCircleIndex++; + if (nCircleIndex >= sz) + nCircleIndex = 0; + + if (Item* pListItem = m_ListItems[nCircleIndex].get()) { + if (FXSYS_toupper(pListItem->GetFirstChar()) == FXSYS_toupper(nChar)) + return nCircleIndex; + } + } + + return nCircleIndex; +} + +bool CPWL_ListCtrl::IsItemSelected(int32_t nIndex) const { + return pdfium::IndexInBounds(m_ListItems, nIndex) && m_ListItems[nIndex] && + m_ListItems[nIndex]->IsSelected(); +} + +void CPWL_ListCtrl::SetItemSelect(int32_t nIndex, bool bSelected) { + if (pdfium::IndexInBounds(m_ListItems, nIndex) && m_ListItems[nIndex]) + m_ListItems[nIndex]->SetSelect(bSelected); +} + +bool CPWL_ListCtrl::IsValid(int32_t nItemIndex) const { + return pdfium::IndexInBounds(m_ListItems, nItemIndex); +} + +WideString CPWL_ListCtrl::GetItemText(int32_t nIndex) const { + if (pdfium::IndexInBounds(m_ListItems, nIndex) && m_ListItems[nIndex]) + return m_ListItems[nIndex]->GetText(); + return L""; +} diff --git a/fpdfsdk/pwl/cpwl_list_impl.h b/fpdfsdk/pwl/cpwl_list_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..e39a9c8b2099ecd56a73942e51934bd216a16d84 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_impl.h @@ -0,0 +1,169 @@ +// 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 FPDFSDK_PWL_CPWL_LIST_IMPL_H_ +#define FPDFSDK_PWL_CPWL_LIST_IMPL_H_ + +#include +#include +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/unowned_ptr.h" + +class CPWL_EditImpl; +class CPWL_EditImpl_Iterator; +class CPWL_List_Notify; +class IPVT_FontMap; + +class CPLST_Select { + public: + enum State { DESELECTING = -1, NORMAL = 0, SELECTING = 1 }; + using const_iterator = std::map::const_iterator; + + CPLST_Select(); + virtual ~CPLST_Select(); + + void Add(int32_t nItemIndex); + void Add(int32_t nBeginIndex, int32_t nEndIndex); + void Sub(int32_t nItemIndex); + void Sub(int32_t nBeginIndex, int32_t nEndIndex); + void DeselectAll(); + void Done(); + + const_iterator begin() const { return m_Items.begin(); } + const_iterator end() const { return m_Items.end(); } + + private: + std::map m_Items; +}; + +class CPWL_ListCtrl { + public: + CPWL_ListCtrl(); + ~CPWL_ListCtrl(); + + void SetNotify(CPWL_List_Notify* pNotify) { m_pNotify = pNotify; } + void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl); + void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl); + void OnVK_UP(bool bShift, bool bCtrl); + void OnVK_DOWN(bool bShift, bool bCtrl); + void OnVK_LEFT(bool bShift, bool bCtrl); + void OnVK_RIGHT(bool bShift, bool bCtrl); + void OnVK_HOME(bool bShift, bool bCtrl); + void OnVK_END(bool bShift, bool bCtrl); + bool OnChar(uint16_t nChar, bool bShift, bool bCtrl); + + void SetScrollPos(const CFX_PointF& point); + void ScrollToListItem(int32_t nItemIndex); + CFX_FloatRect GetItemRect(int32_t nIndex) const; + int32_t GetCaret() const { return m_nCaretIndex; } + int32_t GetSelect() const { return m_nSelItem; } + int32_t GetTopItem() const; + void SetContentRect(const CFX_FloatRect& rect) { m_rcContent = rect; } + CFX_FloatRect GetContentRect() const; + + int32_t GetItemIndex(const CFX_PointF& point) const; + void AddString(const WideString& str); + void SetTopItem(int32_t nIndex); + void Select(int32_t nItemIndex); + void SetCaret(int32_t nItemIndex); + void Empty(); + void Cancel(); + WideString GetText() const; + + void SetFontMap(IPVT_FontMap* pFontMap) { m_pFontMap = pFontMap; } + void SetFontSize(float fFontSize) { m_fFontSize = fFontSize; } + CFX_FloatRect GetPlateRect() const { return m_rcPlate; } + void SetPlateRect(const CFX_FloatRect& rect); + + float GetFontSize() const { return m_fFontSize; } + CPWL_EditImpl* GetItemEdit(int32_t nIndex) const; + int32_t GetCount() const; + bool IsItemSelected(int32_t nIndex) const; + float GetFirstHeight() const; + void SetMultipleSel(bool bMultiple) { m_bMultiple = bMultiple; } + bool IsMultipleSel() const { return m_bMultiple; } + int32_t FindNext(int32_t nIndex, wchar_t nChar) const; + int32_t GetFirstSelected() const; + + private: + class Item { + public: + Item(); + ~Item(); + + void SetFontMap(IPVT_FontMap* pFontMap); + CPWL_EditImpl* GetEdit() const { return m_pEdit.get(); } + + void SetRect(const CFX_FloatRect& rect) { m_rcListItem = rect; } + void SetSelect(bool bSelected) { m_bSelected = bSelected; } + void SetText(const WideString& text); + void SetFontSize(float fFontSize); + WideString GetText() const; + + CFX_FloatRect GetRect() const { return m_rcListItem; } + bool IsSelected() const { return m_bSelected; } + float GetItemHeight() const; + uint16_t GetFirstChar() const; + + private: + CPWL_EditImpl_Iterator* GetIterator() const; + + std::unique_ptr m_pEdit; + bool m_bSelected; + CFX_FloatRect m_rcListItem; + }; + + CFX_PointF InToOut(const CFX_PointF& point) const; + CFX_PointF OutToIn(const CFX_PointF& point) const; + CFX_FloatRect InToOut(const CFX_FloatRect& rect) const; + CFX_FloatRect OutToIn(const CFX_FloatRect& rect) const; + + CFX_PointF InnerToOuter(const CFX_PointF& point) const; + CFX_PointF OuterToInner(const CFX_PointF& point) const; + CFX_FloatRect InnerToOuter(const CFX_FloatRect& rect) const; + CFX_FloatRect OuterToInner(const CFX_FloatRect& rect) const; + + void OnVK(int32_t nItemIndex, bool bShift, bool bCtrl); + bool IsValid(int32_t nItemIndex) const; + + void ReArrange(int32_t nItemIndex); + CFX_FloatRect GetItemRectInternal(int32_t nIndex) const; + CFX_FloatRect GetContentRectInternal() const; + void SetMultipleSelect(int32_t nItemIndex, bool bSelected); + void SetSingleSelect(int32_t nItemIndex); + void InvalidateItem(int32_t nItemIndex); + void SelectItems(); + bool IsItemVisible(int32_t nItemIndex) const; + void SetScrollInfo(); + void SetScrollPosY(float fy); + void AddItem(const WideString& str); + WideString GetItemText(int32_t nIndex) const; + void SetItemSelect(int32_t nItemIndex, bool bSelected); + int32_t GetLastSelected() const; + CFX_PointF GetBTPoint() const { + return CFX_PointF(m_rcPlate.left, m_rcPlate.top); + } + + CFX_FloatRect m_rcPlate; + CFX_FloatRect m_rcContent; + UnownedPtr m_pNotify; + bool m_bNotifyFlag; + CFX_PointF m_ptScrollPos; + CPLST_Select m_aSelItems; // for multiple + int32_t m_nSelItem; // for single + int32_t m_nFootIndex; // for multiple + bool m_bCtrlSel; // for multiple + int32_t m_nCaretIndex; // for multiple + std::vector> m_ListItems; + float m_fFontSize; + UnownedPtr m_pFontMap; + bool m_bMultiple; +}; + +#endif // FPDFSDK_PWL_CPWL_LIST_IMPL_H_ diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.cpp b/fpdfsdk/pwl/cpwl_scroll_bar.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65a51e37e8bbd07a98966893c9341c20ca0d554f --- /dev/null +++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp @@ -0,0 +1,930 @@ +// 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 "fpdfsdk/pwl/cpwl_scroll_bar.h" + +#include +#include +#include + +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +namespace { + +constexpr float kButtonWidth = 9.0f; +constexpr float kPosButtonMinWidth = 2.0f; +constexpr float kScrollBarTriangleHalfLength = 2.0f; + +} // namespace + +#define PWL_DEFAULT_HEAVYGRAYCOLOR CFX_Color(CFX_Color::kGray, 0.50) + +PWL_FLOATRANGE::PWL_FLOATRANGE() { + Default(); +} + +PWL_FLOATRANGE::PWL_FLOATRANGE(float min, float max) { + Set(min, max); +} + +void PWL_FLOATRANGE::Default() { + fMin = 0; + fMax = 0; +} + +void PWL_FLOATRANGE::Set(float min, float max) { + if (min > max) { + fMin = max; + fMax = min; + } else { + fMin = min; + fMax = max; + } +} + +bool PWL_FLOATRANGE::In(float x) const { + return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) && + (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax)); +} + +float PWL_FLOATRANGE::GetWidth() const { + return fMax - fMin; +} + +PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() { + Default(); +} + +void PWL_SCROLL_PRIVATEDATA::Default() { + ScrollRange.Default(); + fScrollPos = ScrollRange.fMin; + fClientWidth = 0; + fBigStep = 10; + fSmallStep = 1; +} + +void PWL_SCROLL_PRIVATEDATA::SetScrollRange(float min, float max) { + ScrollRange.Set(min, max); + + if (IsFloatSmaller(fScrollPos, ScrollRange.fMin)) + fScrollPos = ScrollRange.fMin; + if (IsFloatBigger(fScrollPos, ScrollRange.fMax)) + fScrollPos = ScrollRange.fMax; +} + +void PWL_SCROLL_PRIVATEDATA::SetClientWidth(float width) { + fClientWidth = width; +} + +void PWL_SCROLL_PRIVATEDATA::SetSmallStep(float step) { + fSmallStep = step; +} + +void PWL_SCROLL_PRIVATEDATA::SetBigStep(float step) { + fBigStep = step; +} + +bool PWL_SCROLL_PRIVATEDATA::SetPos(float pos) { + if (ScrollRange.In(pos)) { + fScrollPos = pos; + return true; + } + return false; +} + +void PWL_SCROLL_PRIVATEDATA::AddSmall() { + if (!SetPos(fScrollPos + fSmallStep)) + SetPos(ScrollRange.fMax); +} + +void PWL_SCROLL_PRIVATEDATA::SubSmall() { + if (!SetPos(fScrollPos - fSmallStep)) + SetPos(ScrollRange.fMin); +} + +void PWL_SCROLL_PRIVATEDATA::AddBig() { + if (!SetPos(fScrollPos + fBigStep)) + SetPos(ScrollRange.fMax); +} + +void PWL_SCROLL_PRIVATEDATA::SubBig() { + if (!SetPos(fScrollPos - fBigStep)) + SetPos(ScrollRange.fMin); +} + +CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, + PWL_SBBUTTON_TYPE eButtonType) { + m_eScrollBarType = eScrollBarType; + m_eSBButtonType = eButtonType; + + m_bMouseDown = false; +} + +CPWL_SBButton::~CPWL_SBButton() {} + +ByteString CPWL_SBButton::GetClassName() const { + return "CPWL_SBButton"; +} + +void CPWL_SBButton::OnCreate(CreateParams* pParamsToAdjust) { + pParamsToAdjust->eCursorType = FXCT_ARROW; +} + +void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + if (!IsVisible()) + return; + + CFX_FloatRect rectWnd = GetWindowRect(); + if (rectWnd.IsEmpty()) + return; + + CFX_PointF ptCenter = GetCenterPoint(); + int32_t nTransparency = GetTransparency(); + + if (m_eScrollBarType == SBT_HSCROLL) { + CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device); + + CFX_PointF pt1; + CFX_PointF pt2; + CFX_PointF pt3; + static constexpr float kScrollBarTriangleQuarterLength = + kScrollBarTriangleHalfLength * 0.5; + if (m_eSBButtonType == PSBT_MIN) { + pt1 = + CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength, ptCenter.y); + pt2 = CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength, + ptCenter.y + kScrollBarTriangleHalfLength); + pt3 = CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength, + ptCenter.y - kScrollBarTriangleHalfLength); + } else if (m_eSBButtonType == PSBT_MAX) { + pt1 = + CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength, ptCenter.y); + pt2 = CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength, + ptCenter.y + kScrollBarTriangleHalfLength); + pt3 = CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength, + ptCenter.y - kScrollBarTriangleHalfLength); + } + + if (rectWnd.right - rectWnd.left > kScrollBarTriangleHalfLength * 2 && + rectWnd.top - rectWnd.bottom > kScrollBarTriangleHalfLength) { + CFX_PathData path; + path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false); + path.AppendPoint(pt2, FXPT_TYPE::LineTo, false); + path.AppendPoint(pt3, FXPT_TYPE::LineTo, false); + path.AppendPoint(pt1, FXPT_TYPE::LineTo, false); + + pDevice->DrawPath(&path, &mtUser2Device, nullptr, + PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency), 0, + FXFILL_ALTERNATE); + } + return; + } + + // draw border + pDevice->DrawStrokeRect(&mtUser2Device, rectWnd, + ArgbEncode(nTransparency, 100, 100, 100), 0.0f); + pDevice->DrawStrokeRect(&mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f), + ArgbEncode(nTransparency, 255, 255, 255), 1.0f); + + if (m_eSBButtonType != PSBT_POS) { + // draw background + if (IsEnabled()) { + pDevice->DrawShadow(&mtUser2Device, true, false, + rectWnd.GetDeflated(1.0f, 1.0f), nTransparency, 80, + 220); + } else { + pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(1.0f, 1.0f), + ArgbEncode(255, 255, 255, 255)); + } + + // draw arrow + if (rectWnd.top - rectWnd.bottom > 6.0f) { + float fX = rectWnd.left + 1.5f; + float fY = rectWnd.bottom; + std::vector pts; + if (m_eSBButtonType == PSBT_MIN) { + pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f)); + pts.push_back(CFX_PointF(fX + 2.5f, fY + 3.0f)); + pts.push_back(CFX_PointF(fX + 4.5f, fY + 5.0f)); + pts.push_back(CFX_PointF(fX + 6.5f, fY + 3.0f)); + pts.push_back(CFX_PointF(fX + 6.5f, fY + 4.0f)); + pts.push_back(CFX_PointF(fX + 4.5f, fY + 6.0f)); + pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f)); + } else { + pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f)); + pts.push_back(CFX_PointF(fX + 2.5f, fY + 6.0f)); + pts.push_back(CFX_PointF(fX + 4.5f, fY + 4.0f)); + pts.push_back(CFX_PointF(fX + 6.5f, fY + 6.0f)); + pts.push_back(CFX_PointF(fX + 6.5f, fY + 5.0f)); + pts.push_back(CFX_PointF(fX + 4.5f, fY + 3.0f)); + pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f)); + } + pDevice->DrawFillArea(&mtUser2Device, pts.data(), 7, + IsEnabled() + ? ArgbEncode(nTransparency, 255, 255, 255) + : PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255)); + } + return; + } + + if (IsEnabled()) { + // draw shadow effect + CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f); + CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f); + + ptTop.x += 1.5f; + ptBottom.x += 1.5f; + + const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210), + ArgbEncode(nTransparency, 220, 220, 220), + ArgbEncode(nTransparency, 240, 240, 240), + ArgbEncode(nTransparency, 240, 240, 240), + ArgbEncode(nTransparency, 210, 210, 210), + ArgbEncode(nTransparency, 180, 180, 180), + ArgbEncode(nTransparency, 150, 150, 150), + ArgbEncode(nTransparency, 150, 150, 150), + ArgbEncode(nTransparency, 180, 180, 180), + ArgbEncode(nTransparency, 210, 210, 210)}; + for (FX_COLORREF ref : refs) { + pDevice->DrawStrokeLine(&mtUser2Device, ptTop, ptBottom, ref, 1.0f); + + ptTop.x += 1.0f; + ptBottom.x += 1.0f; + } + } else { + pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f), + ArgbEncode(255, 255, 255, 255)); + } + + // draw friction + if (rectWnd.Height() <= 8.0f) + return; + + FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120); + if (!IsEnabled()) + crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255); + + float nFrictionWidth = 5.0f; + float nFrictionHeight = 5.5f; + + CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f, + ptCenter.y - nFrictionHeight / 2.0f + 0.5f); + CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f, + ptCenter.y - nFrictionHeight / 2.0f + 0.5f); + + for (size_t i = 0; i < 3; ++i) { + pDevice->DrawStrokeLine(&mtUser2Device, ptLeft, ptRight, crStroke, 1.0f); + ptLeft.y += 2.0f; + ptRight.y += 2.0f; + } +} + +bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + + if (CPWL_Wnd* pParent = GetParentWindow()) + pParent->NotifyLButtonDown(this, point); + + m_bMouseDown = true; + SetCapture(); + + return true; +} + +bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + + if (CPWL_Wnd* pParent = GetParentWindow()) + pParent->NotifyLButtonUp(this, point); + + m_bMouseDown = false; + ReleaseCapture(); + + return true; +} + +bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnMouseMove(point, nFlag); + + if (CPWL_Wnd* pParent = GetParentWindow()) + pParent->NotifyMouseMove(this, point); + + return true; +} + +CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType) + : m_sbType(sbType), + m_pMinButton(nullptr), + m_pMaxButton(nullptr), + m_pPosButton(nullptr), + m_bMouseDown(false), + m_bMinOrMax(false), + m_bNotifyForever(true) {} + +CPWL_ScrollBar::~CPWL_ScrollBar() {} + +ByteString CPWL_ScrollBar::GetClassName() const { + return "CPWL_ScrollBar"; +} + +void CPWL_ScrollBar::OnCreate(CreateParams* pParamsToAdjust) { + pParamsToAdjust->eCursorType = FXCT_ARROW; +} + +void CPWL_ScrollBar::OnDestroy() { + // Until cleanup takes place in the virtual destructor for CPWL_Wnd + // subclasses, implement the virtual OnDestroy method that does the + // cleanup first, then invokes the superclass OnDestroy ... gee, + // like a dtor would. + m_pMinButton.Release(); + m_pMaxButton.Release(); + m_pPosButton.Release(); + CPWL_Wnd::OnDestroy(); +} + +bool CPWL_ScrollBar::RePosChildWnd() { + CFX_FloatRect rcClient = GetClientRect(); + CFX_FloatRect rcMinButton, rcMaxButton; + float fBWidth = 0; + + switch (m_sbType) { + case SBT_HSCROLL: + if (rcClient.right - rcClient.left > + kButtonWidth * 2 + kPosButtonMinWidth + 2) { + rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom, + rcClient.left + kButtonWidth, rcClient.top); + rcMaxButton = + CFX_FloatRect(rcClient.right - kButtonWidth, rcClient.bottom, + rcClient.right, rcClient.top); + } else { + fBWidth = (rcClient.right - rcClient.left - kPosButtonMinWidth - 2) / 2; + + if (fBWidth > 0) { + rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom, + rcClient.left + fBWidth, rcClient.top); + rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom, + rcClient.right, rcClient.top); + } else { + if (!SetVisible(false)) + return false; + } + } + break; + case SBT_VSCROLL: + if (IsFloatBigger(rcClient.top - rcClient.bottom, + kButtonWidth * 2 + kPosButtonMinWidth + 2)) { + rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - kButtonWidth, + rcClient.right, rcClient.top); + rcMaxButton = + CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right, + rcClient.bottom + kButtonWidth); + } else { + fBWidth = (rcClient.top - rcClient.bottom - kPosButtonMinWidth - 2) / 2; + + if (IsFloatBigger(fBWidth, 0)) { + rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth, + rcClient.right, rcClient.top); + rcMaxButton = + CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right, + rcClient.bottom + fBWidth); + } else { + if (!SetVisible(false)) + return false; + } + } + break; + } + + ObservedPtr thisObserved(this); + + if (m_pMinButton) { + m_pMinButton->Move(rcMinButton, true, false); + if (!thisObserved) + return false; + } + + if (m_pMaxButton) { + m_pMaxButton->Move(rcMaxButton, true, false); + if (!thisObserved) + return false; + } + + if (!MovePosButton(false)) + return false; + + return true; +} + +void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + CFX_FloatRect rectWnd = GetWindowRect(); + + if (IsVisible() && !rectWnd.IsEmpty()) { + pDevice->DrawFillRect(&mtUser2Device, rectWnd, GetBackgroundColor(), + GetTransparency()); + + pDevice->DrawStrokeLine( + &mtUser2Device, CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f), + CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f), + ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f); + + pDevice->DrawStrokeLine( + &mtUser2Device, CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f), + CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f), + ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f); + } +} + +bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonDown(point, nFlag); + + if (HasFlag(PWS_AUTOTRANSPARENT)) { + if (GetTransparency() != 255) { + SetTransparency(255); + if (!InvalidateRect(nullptr)) + return true; + } + } + + CFX_FloatRect rcMinArea, rcMaxArea; + + if (m_pPosButton && m_pPosButton->IsVisible()) { + CFX_FloatRect rcClient = GetClientRect(); + CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect(); + + switch (m_sbType) { + case SBT_HSCROLL: + rcMinArea = CFX_FloatRect(rcClient.left + kButtonWidth, rcClient.bottom, + rcPosButton.left, rcClient.top); + rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom, + rcClient.right - kButtonWidth, rcClient.top); + + break; + case SBT_VSCROLL: + rcMinArea = CFX_FloatRect(rcClient.left, rcPosButton.top, + rcClient.right, rcClient.top - kButtonWidth); + rcMaxArea = CFX_FloatRect(rcClient.left, rcClient.bottom + kButtonWidth, + rcClient.right, rcPosButton.bottom); + break; + } + + rcMinArea.Normalize(); + rcMaxArea.Normalize(); + + if (rcMinArea.Contains(point)) { + m_sData.SubBig(); + if (!MovePosButton(true)) + return true; + NotifyScrollWindow(); + } + + if (rcMaxArea.Contains(point)) { + m_sData.AddBig(); + if (!MovePosButton(true)) + return true; + NotifyScrollWindow(); + } + } + + return true; +} + +bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + CPWL_Wnd::OnLButtonUp(point, nFlag); + + if (HasFlag(PWS_AUTOTRANSPARENT)) { + if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) { + SetTransparency(PWL_SCROLLBAR_TRANSPARENCY); + if (!InvalidateRect(nullptr)) + return true; + } + } + + EndTimer(); + m_bMouseDown = false; + + return true; +} + +void CPWL_ScrollBar::SetScrollInfo(const PWL_SCROLL_INFO& info) { + if (info == m_OriginInfo) + return; + + m_OriginInfo = info; + float fMax = + std::max(0.0f, info.fContentMax - info.fContentMin - info.fPlateWidth); + SetScrollRange(0, fMax, info.fPlateWidth); + SetScrollStep(info.fBigStep, info.fSmallStep); +} + +void CPWL_ScrollBar::SetScrollPosition(float pos) { + switch (m_sbType) { + case SBT_HSCROLL: + pos = pos - m_OriginInfo.fContentMin; + break; + case SBT_VSCROLL: + pos = m_OriginInfo.fContentMax - pos; + break; + } + SetScrollPos(pos); +} + +void CPWL_ScrollBar::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) { + if (child == m_pMinButton) + OnMinButtonLBDown(pos); + else if (child == m_pMaxButton) + OnMaxButtonLBDown(pos); + else if (child == m_pPosButton) + OnPosButtonLBDown(pos); +} + +void CPWL_ScrollBar::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) { + if (child == m_pMinButton) + OnMinButtonLBUp(pos); + else if (child == m_pMaxButton) + OnMaxButtonLBUp(pos); + else if (child == m_pPosButton) + OnPosButtonLBUp(pos); +} + +void CPWL_ScrollBar::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) { + if (child == m_pMinButton) + OnMinButtonMouseMove(pos); + else if (child == m_pMaxButton) + OnMaxButtonMouseMove(pos); + else if (child == m_pPosButton) + OnPosButtonMouseMove(pos); +} + +void CPWL_ScrollBar::CreateButtons(const CreateParams& cp) { + CreateParams scp = cp; + scp.pParentWnd = this; + scp.dwBorderWidth = 2; + scp.nBorderStyle = BorderStyle::BEVELED; + + scp.dwFlags = + PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP; + + if (!m_pMinButton) { + m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN); + m_pMinButton->Create(scp); + } + + if (!m_pMaxButton) { + m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX); + m_pMaxButton->Create(scp); + } + + if (!m_pPosButton) { + m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS); + + ObservedPtr thisObserved(this); + if (!m_pPosButton->SetVisible(false) || !thisObserved) + return; + m_pPosButton->Create(scp); + } +} + +float CPWL_ScrollBar::GetScrollBarWidth() const { + if (!IsVisible()) + return 0; + + return PWL_SCROLLBAR_WIDTH; +} + +void CPWL_ScrollBar::SetScrollRange(float fMin, + float fMax, + float fClientWidth) { + if (!m_pPosButton) + return; + + m_sData.SetScrollRange(fMin, fMax); + m_sData.SetClientWidth(fClientWidth); + + ObservedPtr thisObserved(this); + + if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) { + m_pPosButton->SetVisible(false); + // Note, |this| may no longer be viable at this point. If more work needs + // to be done, check thisObserved. + return; + } + + if (!m_pPosButton->SetVisible(true) || !thisObserved) + return; + + MovePosButton(true); + // Note, |this| may no longer be viable at this point. If more work needs + // to be done, check the return value of MovePosButton(). +} + +void CPWL_ScrollBar::SetScrollPos(float fPos) { + float fOldPos = m_sData.fScrollPos; + m_sData.SetPos(fPos); + if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) { + MovePosButton(true); + // Note, |this| may no longer be viable at this point. If more work needs + // to be done, check the return value of MovePosButton(). + } +} + +void CPWL_ScrollBar::SetScrollStep(float fBigStep, float fSmallStep) { + m_sData.SetBigStep(fBigStep); + m_sData.SetSmallStep(fSmallStep); +} + +bool CPWL_ScrollBar::MovePosButton(bool bRefresh) { + ASSERT(m_pMinButton); + ASSERT(m_pMaxButton); + + if (m_pPosButton->IsVisible()) { + CFX_FloatRect rcClient; + CFX_FloatRect rcPosArea, rcPosButton; + + rcClient = GetClientRect(); + rcPosArea = GetScrollArea(); + + float fLeft, fRight, fTop, fBottom; + + switch (m_sbType) { + case SBT_HSCROLL: + fLeft = TrueToFace(m_sData.fScrollPos); + fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth); + + if (fRight - fLeft < kPosButtonMinWidth) + fRight = fLeft + kPosButtonMinWidth; + + if (fRight > rcPosArea.right) { + fRight = rcPosArea.right; + fLeft = fRight - kPosButtonMinWidth; + } + + rcPosButton = + CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top); + + break; + case SBT_VSCROLL: + fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth); + fTop = TrueToFace(m_sData.fScrollPos); + + if (IsFloatSmaller(fTop - fBottom, kPosButtonMinWidth)) + fBottom = fTop - kPosButtonMinWidth; + + if (IsFloatSmaller(fBottom, rcPosArea.bottom)) { + fBottom = rcPosArea.bottom; + fTop = fBottom + kPosButtonMinWidth; + } + + rcPosButton = + CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop); + + break; + } + + ObservedPtr thisObserved(this); + + m_pPosButton->Move(rcPosButton, true, bRefresh); + if (!thisObserved) + return false; + } + + return true; +} + +void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) { + m_sData.SubSmall(); + if (!MovePosButton(true)) + return; + NotifyScrollWindow(); + + m_bMinOrMax = true; + + EndTimer(); + BeginTimer(100); +} + +void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {} + +void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {} + +void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) { + m_sData.AddSmall(); + if (!MovePosButton(true)) + return; + NotifyScrollWindow(); + + m_bMinOrMax = false; + + EndTimer(); + BeginTimer(100); +} + +void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {} + +void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {} + +void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) { + m_bMouseDown = true; + + if (m_pPosButton) { + CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect(); + + switch (m_sbType) { + case SBT_HSCROLL: + m_nOldPos = point.x; + m_fOldPosButton = rcPosButton.left; + break; + case SBT_VSCROLL: + m_nOldPos = point.y; + m_fOldPosButton = rcPosButton.top; + break; + } + } +} + +void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) { + if (m_bMouseDown) { + if (!m_bNotifyForever) + NotifyScrollWindow(); + } + m_bMouseDown = false; +} + +void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) { + float fOldScrollPos = m_sData.fScrollPos; + + float fNewPos = 0; + + switch (m_sbType) { + case SBT_HSCROLL: + if (fabs(point.x - m_nOldPos) < 1) + return; + fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos); + break; + case SBT_VSCROLL: + if (fabs(point.y - m_nOldPos) < 1) + return; + fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos); + break; + } + + if (m_bMouseDown) { + switch (m_sbType) { + case SBT_HSCROLL: + + if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) { + fNewPos = m_sData.ScrollRange.fMin; + } + + if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) { + fNewPos = m_sData.ScrollRange.fMax; + } + + m_sData.SetPos(fNewPos); + + break; + case SBT_VSCROLL: + + if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) { + fNewPos = m_sData.ScrollRange.fMin; + } + + if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) { + fNewPos = m_sData.ScrollRange.fMax; + } + + m_sData.SetPos(fNewPos); + + break; + } + + if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) { + if (!MovePosButton(true)) + return; + + if (m_bNotifyForever) + NotifyScrollWindow(); + } + } +} + +void CPWL_ScrollBar::NotifyScrollWindow() { + CPWL_Wnd* pParent = GetParentWindow(); + if (!pParent || m_sbType != SBT_VSCROLL) + return; + + pParent->ScrollWindowVertically(m_OriginInfo.fContentMax - + m_sData.fScrollPos); +} + +CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const { + CFX_FloatRect rcClient = GetClientRect(); + CFX_FloatRect rcArea; + + if (!m_pMinButton || !m_pMaxButton) + return rcClient; + + CFX_FloatRect rcMin = m_pMinButton->GetWindowRect(); + CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect(); + + float fMinWidth = rcMin.right - rcMin.left; + float fMinHeight = rcMin.top - rcMin.bottom; + float fMaxWidth = rcMax.right - rcMax.left; + float fMaxHeight = rcMax.top - rcMax.bottom; + + switch (m_sbType) { + case SBT_HSCROLL: + if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) { + rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom, + rcClient.right - fMaxWidth - 1, rcClient.top); + } else { + rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom, + rcClient.left + fMinWidth + 1, rcClient.top); + } + break; + case SBT_VSCROLL: + if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) { + rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1, + rcClient.right, rcClient.top - fMaxHeight - 1); + } else { + rcArea = + CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1, + rcClient.right, rcClient.bottom + fMinHeight + 1); + } + break; + } + + rcArea.Normalize(); + + return rcArea; +} + +float CPWL_ScrollBar::TrueToFace(float fTrue) { + CFX_FloatRect rcPosArea; + rcPosArea = GetScrollArea(); + + float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth; + fFactWidth = fFactWidth == 0 ? 1 : fFactWidth; + + float fFace = 0; + + switch (m_sbType) { + case SBT_HSCROLL: + fFace = rcPosArea.left + + fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth; + break; + case SBT_VSCROLL: + fFace = rcPosArea.top - + fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth; + break; + } + + return fFace; +} + +float CPWL_ScrollBar::FaceToTrue(float fFace) { + CFX_FloatRect rcPosArea; + rcPosArea = GetScrollArea(); + + float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth; + fFactWidth = fFactWidth == 0 ? 1 : fFactWidth; + + float fTrue = 0; + + switch (m_sbType) { + case SBT_HSCROLL: + fTrue = (fFace - rcPosArea.left) * fFactWidth / + (rcPosArea.right - rcPosArea.left); + break; + case SBT_VSCROLL: + fTrue = (rcPosArea.top - fFace) * fFactWidth / + (rcPosArea.top - rcPosArea.bottom); + break; + } + + return fTrue; +} + +void CPWL_ScrollBar::CreateChildWnd(const CreateParams& cp) { + CreateButtons(cp); +} + +void CPWL_ScrollBar::TimerProc() { + PWL_SCROLL_PRIVATEDATA sTemp = m_sData; + if (m_bMinOrMax) + m_sData.SubSmall(); + else + m_sData.AddSmall(); + + if (sTemp != m_sData) { + if (!MovePosButton(true)) + return; + NotifyScrollWindow(); + } +} diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h new file mode 100644 index 0000000000000000000000000000000000000000..69217323ff3fc12a6311467ae9b4343aafa81f08 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_scroll_bar.h @@ -0,0 +1,186 @@ +// 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 FPDFSDK_PWL_CPWL_SCROLL_BAR_H_ +#define FPDFSDK_PWL_CPWL_SCROLL_BAR_H_ + +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_SBButton; +class CPWL_ScrollBar; + +struct PWL_SCROLL_INFO { + public: + PWL_SCROLL_INFO() + : fContentMin(0.0f), + fContentMax(0.0f), + fPlateWidth(0.0f), + fBigStep(0.0f), + fSmallStep(0.0f) {} + + bool operator==(const PWL_SCROLL_INFO& that) const { + return fContentMin == that.fContentMin && fContentMax == that.fContentMax && + fPlateWidth == that.fPlateWidth && fBigStep == that.fBigStep && + fSmallStep == that.fSmallStep; + } + bool operator!=(const PWL_SCROLL_INFO& that) const { + return !(*this == that); + } + + float fContentMin; + float fContentMax; + float fPlateWidth; + float fBigStep; + float fSmallStep; +}; + +enum PWL_SCROLLBAR_TYPE { SBT_HSCROLL, SBT_VSCROLL }; + +enum PWL_SBBUTTON_TYPE { PSBT_MIN, PSBT_MAX, PSBT_POS }; + +class CPWL_SBButton : public CPWL_Wnd { + public: + CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, + PWL_SBBUTTON_TYPE eButtonType); + ~CPWL_SBButton() override; + + // CPWL_Wnd + ByteString GetClassName() const override; + void OnCreate(CreateParams* pParamsToAdjust) override; + void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; + + protected: + PWL_SCROLLBAR_TYPE m_eScrollBarType; + PWL_SBBUTTON_TYPE m_eSBButtonType; + + bool m_bMouseDown; +}; + +struct PWL_FLOATRANGE { + public: + PWL_FLOATRANGE(); + PWL_FLOATRANGE(float min, float max); + + bool operator==(const PWL_FLOATRANGE& that) const { + return fMin == that.fMin && fMax == that.fMax; + } + bool operator!=(const PWL_FLOATRANGE& that) const { return !(*this == that); } + + void Default(); + void Set(float min, float max); + bool In(float x) const; + float GetWidth() const; + + float fMin; + float fMax; +}; + +struct PWL_SCROLL_PRIVATEDATA { + public: + PWL_SCROLL_PRIVATEDATA(); + + bool operator==(const PWL_SCROLL_PRIVATEDATA& that) const { + return ScrollRange == that.ScrollRange && + fClientWidth == that.fClientWidth && fScrollPos == that.fScrollPos && + fBigStep == that.fBigStep && fSmallStep == that.fSmallStep; + } + bool operator!=(const PWL_SCROLL_PRIVATEDATA& that) const { + return !(*this == that); + } + + void Default(); + void SetScrollRange(float min, float max); + void SetClientWidth(float width); + void SetSmallStep(float step); + void SetBigStep(float step); + bool SetPos(float pos); + + void AddSmall(); + void SubSmall(); + void AddBig(); + void SubBig(); + + PWL_FLOATRANGE ScrollRange; + float fClientWidth; + float fScrollPos; + float fBigStep; + float fSmallStep; +}; + +class CPWL_ScrollBar : public CPWL_Wnd { + public: + explicit CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType = SBT_HSCROLL); + ~CPWL_ScrollBar() override; + + // CPWL_Wnd: + ByteString GetClassName() const override; + void OnCreate(CreateParams* pParamsToAdjust) override; + void OnDestroy() override; + bool RePosChildWnd() override; + void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + void SetScrollInfo(const PWL_SCROLL_INFO& info) override; + void SetScrollPosition(float pos) override; + void NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) override; + void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) override; + void NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) override; + void CreateChildWnd(const CreateParams& cp) override; + void TimerProc() override; + + float GetScrollBarWidth() const; + PWL_SCROLLBAR_TYPE GetScrollBarType() const { return m_sbType; } + + void SetNotifyForever(bool bForever) { m_bNotifyForever = bForever; } + + protected: + void SetScrollRange(float fMin, float fMax, float fClientWidth); + void SetScrollPos(float fPos); + + // Returns |true| iff this instance is still allocated. + bool MovePosButton(bool bRefresh); + void SetScrollStep(float fBigStep, float fSmallStep); + void NotifyScrollWindow(); + CFX_FloatRect GetScrollArea() const; + + private: + void CreateButtons(const CreateParams& cp); + + void OnMinButtonLBDown(const CFX_PointF& point); + void OnMinButtonLBUp(const CFX_PointF& point); + void OnMinButtonMouseMove(const CFX_PointF& point); + + void OnMaxButtonLBDown(const CFX_PointF& point); + void OnMaxButtonLBUp(const CFX_PointF& point); + void OnMaxButtonMouseMove(const CFX_PointF& point); + + void OnPosButtonLBDown(const CFX_PointF& point); + void OnPosButtonLBUp(const CFX_PointF& point); + void OnPosButtonMouseMove(const CFX_PointF& point); + + float TrueToFace(float); + float FaceToTrue(float); + + PWL_SCROLLBAR_TYPE m_sbType; + PWL_SCROLL_INFO m_OriginInfo; + UnownedPtr m_pMinButton; + UnownedPtr m_pMaxButton; + UnownedPtr m_pPosButton; + PWL_SCROLL_PRIVATEDATA m_sData; + bool m_bMouseDown; + bool m_bMinOrMax; + bool m_bNotifyForever; + float m_nOldPos; + float m_fOldPosButton; +}; + +#endif // FPDFSDK_PWL_CPWL_SCROLL_BAR_H_ diff --git a/fpdfsdk/pwl/cpwl_special_button.cpp b/fpdfsdk/pwl/cpwl_special_button.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddca67e5d1d0e9a5088124491b833778d914608b --- /dev/null +++ b/fpdfsdk/pwl/cpwl_special_button.cpp @@ -0,0 +1,80 @@ +// 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 "fpdfsdk/pwl/cpwl_special_button.h" +#include "fpdfsdk/pwl/cpwl_button.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +CPWL_PushButton::CPWL_PushButton() {} + +CPWL_PushButton::~CPWL_PushButton() {} + +ByteString CPWL_PushButton::GetClassName() const { + return "CPWL_PushButton"; +} + +CFX_FloatRect CPWL_PushButton::GetFocusRect() const { + return GetWindowRect().GetDeflated(static_cast(GetBorderWidth()), + static_cast(GetBorderWidth())); +} + +CPWL_CheckBox::CPWL_CheckBox() : m_bChecked(false) {} + +CPWL_CheckBox::~CPWL_CheckBox() {} + +ByteString CPWL_CheckBox::GetClassName() const { + return "CPWL_CheckBox"; +} + +void CPWL_CheckBox::SetCheck(bool bCheck) { + m_bChecked = bCheck; +} + +bool CPWL_CheckBox::IsChecked() const { + return m_bChecked; +} + +bool CPWL_CheckBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + if (IsReadOnly()) + return false; + + SetCheck(!IsChecked()); + return true; +} + +bool CPWL_CheckBox::OnChar(uint16_t nChar, uint32_t nFlag) { + SetCheck(!IsChecked()); + return true; +} + +CPWL_RadioButton::CPWL_RadioButton() : m_bChecked(false) {} + +CPWL_RadioButton::~CPWL_RadioButton() {} + +ByteString CPWL_RadioButton::GetClassName() const { + return "CPWL_RadioButton"; +} + +bool CPWL_RadioButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + if (IsReadOnly()) + return false; + + SetCheck(true); + return true; +} + +void CPWL_RadioButton::SetCheck(bool bCheck) { + m_bChecked = bCheck; +} + +bool CPWL_RadioButton::IsChecked() const { + return m_bChecked; +} + +bool CPWL_RadioButton::OnChar(uint16_t nChar, uint32_t nFlag) { + SetCheck(true); + return true; +} diff --git a/fpdfsdk/pwl/cpwl_special_button.h b/fpdfsdk/pwl/cpwl_special_button.h new file mode 100644 index 0000000000000000000000000000000000000000..076b5298ed440ae64b21340bdc776fa99d399f9c --- /dev/null +++ b/fpdfsdk/pwl/cpwl_special_button.h @@ -0,0 +1,56 @@ +// 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 FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_ +#define FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_ + +#include "fpdfsdk/pwl/cpwl_button.h" + +class CPWL_PushButton : public CPWL_Button { + public: + CPWL_PushButton(); + ~CPWL_PushButton() override; + + // CPWL_Button + ByteString GetClassName() const override; + CFX_FloatRect GetFocusRect() const override; +}; + +class CPWL_CheckBox : public CPWL_Button { + public: + CPWL_CheckBox(); + ~CPWL_CheckBox() override; + + // CPWL_Button + ByteString GetClassName() const override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + + void SetCheck(bool bCheck); + bool IsChecked() const; + + private: + bool m_bChecked; +}; + +class CPWL_RadioButton : public CPWL_Button { + public: + CPWL_RadioButton(); + ~CPWL_RadioButton() override; + + // CPWL_Button + ByteString GetClassName() const override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + + void SetCheck(bool bCheck); + bool IsChecked() const; + + private: + bool m_bChecked; +}; + +#endif // FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_ diff --git a/fpdfsdk/pwl/cpwl_timer.cpp b/fpdfsdk/pwl/cpwl_timer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34f81fc433aabdd3f9b6e3f2b49beb8d24161e27 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_timer.cpp @@ -0,0 +1,62 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/pwl/cpwl_timer.h" + +#include + +#include "fpdfsdk/cfx_systemhandler.h" +#include "fpdfsdk/pwl/cpwl_timer_handler.h" + +namespace { + +std::map& GetPWLTimeMap() { + // Leak the object at shutdown. + static auto* timeMap = new std::map; + return *timeMap; +} + +} // namespace + +CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached, + CFX_SystemHandler* pSystemHandler) + : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) { + ASSERT(m_pAttached); + ASSERT(m_pSystemHandler); +} + +CPWL_Timer::~CPWL_Timer() { + KillPWLTimer(); +} + +int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) { + if (m_nTimerID != 0) + KillPWLTimer(); + m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc); + + GetPWLTimeMap()[m_nTimerID] = this; + return m_nTimerID; +} + +void CPWL_Timer::KillPWLTimer() { + if (m_nTimerID == 0) + return; + + m_pSystemHandler->KillTimer(m_nTimerID); + GetPWLTimeMap().erase(m_nTimerID); + m_nTimerID = 0; +} + +// static +void CPWL_Timer::TimerProc(int32_t idEvent) { + auto it = GetPWLTimeMap().find(idEvent); + if (it == GetPWLTimeMap().end()) + return; + + CPWL_Timer* pTimer = it->second; + if (pTimer->m_pAttached) + pTimer->m_pAttached->TimerProc(); +} diff --git a/fpdfsdk/pwl/cpwl_timer.h b/fpdfsdk/pwl/cpwl_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..6e082abd4bbb42c739785cf3a57ef234c2141799 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_timer.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_PWL_CPWL_TIMER_H_ +#define FPDFSDK_PWL_CPWL_TIMER_H_ + +#include "core/fxcrt/unowned_ptr.h" + +class CFX_SystemHandler; +class CPWL_TimerHandler; + +class CPWL_Timer { + public: + CPWL_Timer(CPWL_TimerHandler* pAttached, CFX_SystemHandler* pSystemHandler); + virtual ~CPWL_Timer(); + + static void TimerProc(int32_t idEvent); + + int32_t SetPWLTimer(int32_t nElapse); + void KillPWLTimer(); + + private: + int32_t m_nTimerID; + UnownedPtr m_pAttached; + UnownedPtr m_pSystemHandler; +}; + +#endif // FPDFSDK_PWL_CPWL_TIMER_H_ diff --git a/fpdfsdk/pwl/cpwl_timer_handler.cpp b/fpdfsdk/pwl/cpwl_timer_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33af306deb5e25fe4fb30db31b4f5389e4dd3b74 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_timer_handler.cpp @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/pwl/cpwl_timer_handler.h" + +#include "fpdfsdk/pwl/cpwl_timer.h" +#include "third_party/base/ptr_util.h" + +CPWL_TimerHandler::CPWL_TimerHandler() {} + +CPWL_TimerHandler::~CPWL_TimerHandler() {} + +void CPWL_TimerHandler::BeginTimer(int32_t nElapse) { + if (!m_pTimer) + m_pTimer = pdfium::MakeUnique(this, GetSystemHandler()); + m_pTimer->SetPWLTimer(nElapse); +} + +void CPWL_TimerHandler::EndTimer() { + if (m_pTimer) + m_pTimer->KillPWLTimer(); +} + +void CPWL_TimerHandler::TimerProc() {} diff --git a/fpdfsdk/pwl/cpwl_timer_handler.h b/fpdfsdk/pwl/cpwl_timer_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..f208e1cdf61796855c32149bc98f17534a6ec963 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_timer_handler.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_ +#define FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_ + +#include + +class CFX_SystemHandler; +class CPWL_Timer; + +class CPWL_TimerHandler { + public: + CPWL_TimerHandler(); + virtual ~CPWL_TimerHandler(); + + virtual void TimerProc(); + virtual CFX_SystemHandler* GetSystemHandler() const = 0; + + void BeginTimer(int32_t nElapse); + void EndTimer(); + + private: + std::unique_ptr m_pTimer; +}; + +#endif // FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_ diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..368db74ec4deceb2b8c1f2c29c251dff0185cf2f --- /dev/null +++ b/fpdfsdk/pwl/cpwl_wnd.cpp @@ -0,0 +1,801 @@ +// 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 "fpdfsdk/pwl/cpwl_wnd.h" + +#include +#include +#include + +#include "core/fxge/cfx_renderdevice.h" +#include "fpdfsdk/pwl/cpwl_scroll_bar.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +constexpr float kDefaultFontSize = 9.0f; + +} // namespace + +CPWL_Wnd::CreateParams::CreateParams() + : rcRectWnd(0, 0, 0, 0), + pSystemHandler(nullptr), + pFontMap(nullptr), + pProvider(nullptr), + pFocusHandler(nullptr), + dwFlags(0), + sBackgroundColor(), + pAttachedWidget(nullptr), + nBorderStyle(BorderStyle::SOLID), + dwBorderWidth(1), + sBorderColor(), + sTextColor(), + nTransparency(255), + fFontSize(kDefaultFontSize), + sDash(3, 0, 0), + pAttachedData(nullptr), + pParentWnd(nullptr), + pMsgControl(nullptr), + eCursorType(FXCT_ARROW) {} + +CPWL_Wnd::CreateParams::CreateParams(const CreateParams& other) = default; + +CPWL_Wnd::CreateParams::~CreateParams() = default; + +class CPWL_MsgControl : public Observable { + public: + explicit CPWL_MsgControl(CPWL_Wnd* pWnd) : m_pCreatedWnd(pWnd) {} + ~CPWL_MsgControl() {} + + bool IsWndCreated(const CPWL_Wnd* pWnd) const { + return m_pCreatedWnd == pWnd; + } + + bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const { + return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd); + } + + bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const { + return pWnd == m_pMainKeyboardWnd; + } + + bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const { + return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd); + } + + void SetFocus(CPWL_Wnd* pWnd) { + m_aKeyboardPath.clear(); + if (!pWnd) + return; + + m_pMainKeyboardWnd = pWnd; + CPWL_Wnd* pParent = pWnd; + while (pParent) { + m_aKeyboardPath.push_back(pParent); + pParent = pParent->GetParentWindow(); + } + // Note, pWnd may get destroyed in the OnSetFocus call. + pWnd->OnSetFocus(); + } + + void KillFocus() { + ObservedPtr observed_ptr(this); + if (!m_aKeyboardPath.empty()) + if (CPWL_Wnd* pWnd = m_aKeyboardPath[0]) + pWnd->OnKillFocus(); + if (!observed_ptr) + return; + + m_pMainKeyboardWnd = nullptr; + m_aKeyboardPath.clear(); + } + + void SetCapture(CPWL_Wnd* pWnd) { + m_aMousePath.clear(); + if (pWnd) { + CPWL_Wnd* pParent = pWnd; + while (pParent) { + m_aMousePath.push_back(pParent); + pParent = pParent->GetParentWindow(); + } + } + } + + void ReleaseCapture() { + m_aMousePath.clear(); + } + + CPWL_Wnd* GetFocusedWindow() const { return m_pMainKeyboardWnd.Get(); } + + private: + std::vector m_aMousePath; + std::vector m_aKeyboardPath; + UnownedPtr m_pCreatedWnd; + UnownedPtr m_pMainKeyboardWnd; +}; + +CPWL_Wnd::CPWL_Wnd() + : m_rcWindow(), + m_rcClip(), + m_bCreated(false), + m_bVisible(false), + m_bNotifying(false), + m_bEnabled(true) {} + +CPWL_Wnd::~CPWL_Wnd() { + ASSERT(!m_bCreated); +} + +ByteString CPWL_Wnd::GetClassName() const { + return "CPWL_Wnd"; +} + +void CPWL_Wnd::Create(const CreateParams& cp) { + if (IsValid()) + return; + + m_CreationParams = cp; + OnCreate(&m_CreationParams); + m_CreationParams.rcRectWnd.Normalize(); + m_rcWindow = m_CreationParams.rcRectWnd; + m_rcClip = m_rcWindow; + if (!m_rcClip.IsEmpty()) { + m_rcClip.Inflate(1.0f, 1.0f); + m_rcClip.Normalize(); + } + CreateMsgControl(); + if (m_CreationParams.pParentWnd) + m_CreationParams.pParentWnd->AddChild(this); + + CreateParams ccp = m_CreationParams; + ccp.dwFlags &= 0xFFFF0000L; // remove sub styles + CreateScrollBar(ccp); + CreateChildWnd(ccp); + m_bVisible = HasFlag(PWS_VISIBLE); + OnCreated(); + if (!RePosChildWnd()) + return; + + m_bCreated = true; +} + +void CPWL_Wnd::OnCreate(CreateParams* pParamsToAdjust) {} + +void CPWL_Wnd::OnCreated() {} + +void CPWL_Wnd::OnDestroy() {} + +void CPWL_Wnd::InvalidateFocusHandler(FocusHandlerIface* handler) { + if (m_CreationParams.pFocusHandler == handler) + m_CreationParams.pFocusHandler = nullptr; +} + +void CPWL_Wnd::InvalidateProvider(ProviderIface* provider) { + if (m_CreationParams.pProvider.Get() == provider) + m_CreationParams.pProvider.Reset(); +} + +void CPWL_Wnd::Destroy() { + KillFocus(); + OnDestroy(); + if (m_bCreated) { + m_pVScrollBar = nullptr; + for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) { + CPWL_Wnd* pChild = *it; + if (pChild) { + *it = nullptr; + pChild->Destroy(); + delete pChild; + } + } + if (m_CreationParams.pParentWnd) + m_CreationParams.pParentWnd->RemoveChild(this); + + m_bCreated = false; + } + DestroyMsgControl(); + m_Children.clear(); +} + +bool CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) { + if (!IsValid()) + return true; + + CFX_FloatRect rcOld = GetWindowRect(); + m_rcWindow = rcNew; + m_rcWindow.Normalize(); + + if (bReset) { + if (rcOld.left != rcNew.left || rcOld.right != rcNew.right || + rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) { + if (!RePosChildWnd()) + return false; + } + } + if (bRefresh && !InvalidateRectMove(rcOld, rcNew)) + return false; + + m_CreationParams.rcRectWnd = m_rcWindow; + return true; +} + +bool CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld, + const CFX_FloatRect& rcNew) { + CFX_FloatRect rcUnion = rcOld; + rcUnion.Union(rcNew); + + return InvalidateRect(&rcUnion); +} + +void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + if (IsValid() && IsVisible()) { + DrawThisAppearance(pDevice, mtUser2Device); + DrawChildAppearance(pDevice, mtUser2Device); + } +} + +void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + CFX_FloatRect rectWnd = GetWindowRect(); + if (rectWnd.IsEmpty()) + return; + + if (HasFlag(PWS_BACKGROUND)) { + float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); + pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(width, width), + GetBackgroundColor(), GetTransparency()); + } + + if (HasFlag(PWS_BORDER)) { + pDevice->DrawBorder(&mtUser2Device, rectWnd, + static_cast(GetBorderWidth()), GetBorderColor(), + GetBorderLeftTopColor(GetBorderStyle()), + GetBorderRightBottomColor(GetBorderStyle()), + GetBorderStyle(), GetTransparency()); + } +} + +void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device) { + for (CPWL_Wnd* pChild : m_Children) { + if (!pChild) + continue; + + CFX_Matrix mt = pChild->GetChildMatrix(); + if (mt.IsIdentity()) { + pChild->DrawAppearance(pDevice, mtUser2Device); + } else { + mt.Concat(mtUser2Device); + pChild->DrawAppearance(pDevice, mt); + } + } +} + +bool CPWL_Wnd::InvalidateRect(CFX_FloatRect* pRect) { + ObservedPtr thisObserved(this); + if (!IsValid()) + return true; + + CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect(); + + if (!HasFlag(PWS_NOREFRESHCLIP)) { + CFX_FloatRect rcClip = GetClipRect(); + if (!rcClip.IsEmpty()) { + rcRefresh.Intersect(rcClip); + } + } + + CFX_FloatRect rcWin = PWLtoWnd(rcRefresh); + rcWin.Inflate(1, 1); + rcWin.Normalize(); + + if (CFX_SystemHandler* pSH = GetSystemHandler()) { + if (CPDFSDK_Widget* widget = static_cast( + m_CreationParams.pAttachedWidget.Get())) { + pSH->InvalidateRect(widget, rcWin); + if (!thisObserved) + return false; + } + } + + return true; +} + +#define PWL_IMPLEMENT_KEY_METHOD(key_method_name) \ + bool CPWL_Wnd::key_method_name(uint16_t nChar, uint32_t nFlag) { \ + if (!IsValid() || !IsVisible() || !IsEnabled()) \ + return false; \ + if (!IsWndCaptureKeyboard(this)) \ + return false; \ + for (auto* pChild : m_Children) { \ + if (pChild && IsWndCaptureKeyboard(pChild)) \ + return pChild->key_method_name(nChar, nFlag); \ + } \ + return false; \ + } + +PWL_IMPLEMENT_KEY_METHOD(OnKeyDown) +PWL_IMPLEMENT_KEY_METHOD(OnChar) +#undef PWL_IMPLEMENT_KEY_METHOD + +#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name) \ + bool CPWL_Wnd::mouse_method_name(const CFX_PointF& point, uint32_t nFlag) { \ + if (!IsValid() || !IsVisible() || !IsEnabled()) \ + return false; \ + if (IsWndCaptureMouse(this)) { \ + for (auto* pChild : m_Children) { \ + if (pChild && IsWndCaptureMouse(pChild)) { \ + return pChild->mouse_method_name(pChild->ParentToChild(point), \ + nFlag); \ + } \ + } \ + SetCursor(); \ + return false; \ + } \ + for (auto* pChild : m_Children) { \ + if (pChild && pChild->WndHitTest(pChild->ParentToChild(point))) { \ + return pChild->mouse_method_name(pChild->ParentToChild(point), nFlag); \ + } \ + } \ + if (WndHitTest(point)) \ + SetCursor(); \ + return false; \ + } + +PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk) +PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown) +PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp) +PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown) +PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp) +PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove) +#undef PWL_IMPLEMENT_MOUSE_METHOD + +WideString CPWL_Wnd::GetSelectedText() { + return WideString(); +} + +void CPWL_Wnd::ReplaceSelection(const WideString& text) {} + +bool CPWL_Wnd::OnMouseWheel(short zDelta, + const CFX_PointF& point, + uint32_t nFlag) { + if (!IsValid() || !IsVisible() || !IsEnabled()) + return false; + + SetCursor(); + if (!IsWndCaptureKeyboard(this)) + return false; + + for (auto* pChild : m_Children) { + if (pChild && IsWndCaptureKeyboard(pChild)) + return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point), nFlag); + } + return false; +} + +void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) { + m_Children.push_back(pWnd); +} + +void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) { + for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) { + if (*it && *it == pWnd) { + m_Children.erase(std::next(it).base()); + break; + } + } +} + +void CPWL_Wnd::SetScrollInfo(const PWL_SCROLL_INFO& info) {} + +void CPWL_Wnd::SetScrollPosition(float pos) {} + +void CPWL_Wnd::ScrollWindowVertically(float pos) {} + +void CPWL_Wnd::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {} + +void CPWL_Wnd::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {} + +void CPWL_Wnd::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {} + +CPWL_Wnd* CPWL_Wnd::GetParentWindow() const { + return m_CreationParams.pParentWnd; +} + +CFX_FloatRect CPWL_Wnd::GetWindowRect() const { + return m_rcWindow; +} + +CFX_FloatRect CPWL_Wnd::GetClientRect() const { + CFX_FloatRect rcWindow = GetWindowRect(); + + float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); + CFX_FloatRect rcClient = rcWindow.GetDeflated(width, width); + if (CPWL_ScrollBar* pVSB = GetVScrollBar()) + rcClient.right -= pVSB->GetScrollBarWidth(); + + rcClient.Normalize(); + return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect(); +} + +CFX_PointF CPWL_Wnd::GetCenterPoint() const { + CFX_FloatRect rcClient = GetClientRect(); + return CFX_PointF((rcClient.left + rcClient.right) * 0.5f, + (rcClient.top + rcClient.bottom) * 0.5f); +} + +bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const { + return (m_CreationParams.dwFlags & dwFlags) != 0; +} + +void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) { + m_CreationParams.dwFlags &= ~dwFlags; +} + +void CPWL_Wnd::AddFlag(uint32_t dwFlags) { + m_CreationParams.dwFlags |= dwFlags; +} + +CFX_Color CPWL_Wnd::GetBackgroundColor() const { + return m_CreationParams.sBackgroundColor; +} + +void CPWL_Wnd::SetBackgroundColor(const CFX_Color& color) { + m_CreationParams.sBackgroundColor = color; +} + +CFX_Color CPWL_Wnd::GetTextColor() const { + return m_CreationParams.sTextColor; +} + +BorderStyle CPWL_Wnd::GetBorderStyle() const { + return m_CreationParams.nBorderStyle; +} + +void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) { + if (HasFlag(PWS_BORDER)) + m_CreationParams.nBorderStyle = nBorderStyle; +} + +int32_t CPWL_Wnd::GetBorderWidth() const { + return HasFlag(PWS_BORDER) ? m_CreationParams.dwBorderWidth : 0; +} + +int32_t CPWL_Wnd::GetInnerBorderWidth() const { + return 0; +} + +CFX_Color CPWL_Wnd::GetBorderColor() const { + return HasFlag(PWS_BORDER) ? m_CreationParams.sBorderColor : CFX_Color(); +} + +const CPWL_Dash& CPWL_Wnd::GetBorderDash() const { + return m_CreationParams.sDash; +} + +CPWL_Wnd::PrivateData* CPWL_Wnd::GetAttachedData() const { + return m_CreationParams.pAttachedData.Get(); +} + +CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const { + return HasFlag(PWS_VSCROLL) ? m_pVScrollBar.Get() : nullptr; +} + +void CPWL_Wnd::CreateScrollBar(const CreateParams& cp) { + CreateVScrollBar(cp); +} + +void CPWL_Wnd::CreateVScrollBar(const CreateParams& cp) { + if (m_pVScrollBar || !HasFlag(PWS_VSCROLL)) + return; + + CreateParams scp = cp; + + // flags + scp.dwFlags = + PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP; + + scp.pParentWnd = this; + scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR; + scp.eCursorType = FXCT_ARROW; + scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY; + + m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL); + m_pVScrollBar->Create(scp); +} + +void CPWL_Wnd::SetCapture() { + if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) + pMsgCtrl->SetCapture(this); +} + +void CPWL_Wnd::ReleaseCapture() { + for (auto* pChild : m_Children) { + if (pChild) + pChild->ReleaseCapture(); + } + if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) + pMsgCtrl->ReleaseCapture(); +} + +void CPWL_Wnd::SetFocus() { + if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) { + if (!pMsgCtrl->IsMainCaptureKeyboard(this)) + pMsgCtrl->KillFocus(); + pMsgCtrl->SetFocus(this); + } +} + +void CPWL_Wnd::KillFocus() { + if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) { + if (pMsgCtrl->IsWndCaptureKeyboard(this)) + pMsgCtrl->KillFocus(); + } +} + +void CPWL_Wnd::OnSetFocus() {} + +void CPWL_Wnd::OnKillFocus() {} + +bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const { + return IsValid() && IsVisible() && GetWindowRect().Contains(point); +} + +bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const { + return IsValid() && IsVisible() && GetClientRect().Contains(point); +} + +const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const { + auto* pParent = m_CreationParams.pParentWnd; + return pParent ? pParent->GetRootWnd() : this; +} + +bool CPWL_Wnd::SetVisible(bool bVisible) { + if (!IsValid()) + return true; + + ObservedPtr thisObserved(this); + + for (auto* pChild : m_Children) { + if (pChild) { + pChild->SetVisible(bVisible); + if (!thisObserved) + return false; + } + } + + if (bVisible != m_bVisible) { + m_bVisible = bVisible; + if (!RePosChildWnd()) + return false; + + if (!InvalidateRect(nullptr)) + return false; + } + return true; +} + +void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) { + m_rcClip = rect; + m_rcClip.Normalize(); +} + +const CFX_FloatRect& CPWL_Wnd::GetClipRect() const { + return m_rcClip; +} + +bool CPWL_Wnd::IsReadOnly() const { + return HasFlag(PWS_READONLY); +} + +bool CPWL_Wnd::RePosChildWnd() { + CPWL_ScrollBar* pVSB = GetVScrollBar(); + if (!pVSB) + return true; + + CFX_FloatRect rcContent = GetWindowRect(); + if (!rcContent.IsEmpty()) { + float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); + rcContent.Deflate(width, width); + rcContent.Normalize(); + } + CFX_FloatRect rcVScroll = + CFX_FloatRect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom, + rcContent.right - 1.0f, rcContent.top); + + ObservedPtr thisObserved(this); + + pVSB->Move(rcVScroll, true, false); + if (!thisObserved) + return false; + + return true; +} + +void CPWL_Wnd::CreateChildWnd(const CreateParams& cp) {} + +void CPWL_Wnd::SetCursor() { + if (IsValid()) { + if (CFX_SystemHandler* pSH = GetSystemHandler()) { + int32_t nCursorType = GetCreationParams().eCursorType; + pSH->SetCursor(nCursorType); + } + } +} + +void CPWL_Wnd::CreateMsgControl() { + if (!m_CreationParams.pMsgControl) + m_CreationParams.pMsgControl = new CPWL_MsgControl(this); +} + +void CPWL_Wnd::DestroyMsgControl() { + CPWL_MsgControl* pMsgControl = GetMsgControl(); + if (pMsgControl && pMsgControl->IsWndCreated(this)) + delete pMsgControl; +} + +CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const { + return m_CreationParams.pMsgControl; +} + +bool CPWL_Wnd::IsCaptureMouse() const { + return IsWndCaptureMouse(this); +} + +bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const { + CPWL_MsgControl* pCtrl = GetMsgControl(); + return pCtrl ? pCtrl->IsWndCaptureMouse(pWnd) : false; +} + +bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const { + CPWL_MsgControl* pCtrl = GetMsgControl(); + return pCtrl ? pCtrl->IsWndCaptureKeyboard(pWnd) : false; +} + +bool CPWL_Wnd::IsFocused() const { + CPWL_MsgControl* pCtrl = GetMsgControl(); + return pCtrl ? pCtrl->IsMainCaptureKeyboard(this) : false; +} + +CFX_FloatRect CPWL_Wnd::GetFocusRect() const { + CFX_FloatRect rect = GetWindowRect(); + if (!rect.IsEmpty()) { + rect.Inflate(1.0f, 1.0f); + rect.Normalize(); + } + return rect; +} + +float CPWL_Wnd::GetFontSize() const { + return m_CreationParams.fFontSize; +} + +void CPWL_Wnd::SetFontSize(float fFontSize) { + m_CreationParams.fFontSize = fFontSize; +} + +CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const { + return m_CreationParams.pSystemHandler; +} + +CPWL_Wnd::FocusHandlerIface* CPWL_Wnd::GetFocusHandler() const { + return m_CreationParams.pFocusHandler.Get(); +} + +CPWL_Wnd::ProviderIface* CPWL_Wnd::GetProvider() const { + return m_CreationParams.pProvider.Get(); +} + +IPVT_FontMap* CPWL_Wnd::GetFontMap() const { + return m_CreationParams.pFontMap; +} + +CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const { + switch (nBorderStyle) { + case BorderStyle::BEVELED: + return CFX_Color(CFX_Color::kGray, 1); + case BorderStyle::INSET: + return CFX_Color(CFX_Color::kGray, 0.5f); + default: + return CFX_Color(); + } +} + +CFX_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const { + switch (nBorderStyle) { + case BorderStyle::BEVELED: + return GetBackgroundColor() / 2.0f; + case BorderStyle::INSET: + return CFX_Color(CFX_Color::kGray, 0.75f); + default: + return CFX_Color(); + } +} + +int32_t CPWL_Wnd::GetTransparency() { + return m_CreationParams.nTransparency; +} + +void CPWL_Wnd::SetTransparency(int32_t nTransparency) { + for (auto* pChild : m_Children) { + if (pChild) + pChild->SetTransparency(nTransparency); + } + m_CreationParams.nTransparency = nTransparency; +} + +CFX_Matrix CPWL_Wnd::GetWindowMatrix() const { + CFX_Matrix mt = GetChildToRoot(); + if (ProviderIface* pProvider = GetProvider()) + mt.Concat(pProvider->GetWindowMatrix(GetAttachedData())); + return mt; +} + +CFX_FloatRect CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const { + CFX_Matrix mt = GetWindowMatrix(); + return mt.TransformRect(rect); +} + +CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const { + CFX_Matrix mt = GetChildMatrix(); + if (mt.IsIdentity()) + return point; + + CFX_Matrix inverse = mt.GetInverse(); + if (!inverse.IsIdentity()) + mt = inverse; + return mt.Transform(point); +} + +CFX_FloatRect CPWL_Wnd::ParentToChild(const CFX_FloatRect& rect) const { + CFX_Matrix mt = GetChildMatrix(); + if (mt.IsIdentity()) + return rect; + + CFX_Matrix inverse = mt.GetInverse(); + if (!inverse.IsIdentity()) + mt = inverse; + + return mt.TransformRect(rect); +} + +CFX_Matrix CPWL_Wnd::GetChildToRoot() const { + CFX_Matrix mt; + if (HasFlag(PWS_CHILD)) { + const CPWL_Wnd* pParent = this; + while (pParent) { + mt.Concat(pParent->GetChildMatrix()); + pParent = pParent->GetParentWindow(); + } + } + return mt; +} + +CFX_Matrix CPWL_Wnd::GetChildMatrix() const { + return HasFlag(PWS_CHILD) ? m_CreationParams.mtChild : CFX_Matrix(); +} + +void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) { + m_CreationParams.mtChild = mt; +} + +const CPWL_Wnd* CPWL_Wnd::GetFocused() const { + CPWL_MsgControl* pMsgCtrl = GetMsgControl(); + return pMsgCtrl ? pMsgCtrl->GetFocusedWindow() : nullptr; +} + +void CPWL_Wnd::EnableWindow(bool bEnable) { + if (m_bEnabled == bEnable) + return; + + for (auto* pChild : m_Children) { + if (pChild) + pChild->EnableWindow(bEnable); + } + m_bEnabled = bEnable; +} diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h new file mode 100644 index 0000000000000000000000000000000000000000..ba52420ade2b4e97f9c68f77bb73468593c6584b --- /dev/null +++ b/fpdfsdk/pwl/cpwl_wnd.h @@ -0,0 +1,326 @@ +// 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 FPDFSDK_PWL_CPWL_WND_H_ +#define FPDFSDK_PWL_CPWL_WND_H_ + +#include +#include + +#include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fxcrt/observable.h" +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_color.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/cpdfsdk_widget.h" +#include "fpdfsdk/pwl/cpwl_timer.h" +#include "fpdfsdk/pwl/cpwl_timer_handler.h" + +class CPWL_Edit; +class CPWL_MsgControl; +class CPWL_ScrollBar; +class CFX_SystemHandler; +class IPVT_FontMap; +struct PWL_SCROLL_INFO; + +// window styles +#define PWS_CHILD 0x80000000L +#define PWS_BORDER 0x40000000L +#define PWS_BACKGROUND 0x20000000L +#define PWS_HSCROLL 0x10000000L +#define PWS_VSCROLL 0x08000000L +#define PWS_VISIBLE 0x04000000L +#define PWS_READONLY 0x01000000L +#define PWS_AUTOFONTSIZE 0x00800000L +#define PWS_AUTOTRANSPARENT 0x00400000L +#define PWS_NOREFRESHCLIP 0x00200000L + +// edit and label styles +#define PES_MULTILINE 0x0001L +#define PES_PASSWORD 0x0002L +#define PES_LEFT 0x0004L +#define PES_RIGHT 0x0008L +#define PES_MIDDLE 0x0010L +#define PES_TOP 0x0020L +#define PES_BOTTOM 0x0040L +#define PES_CENTER 0x0080L +#define PES_CHARARRAY 0x0100L +#define PES_AUTOSCROLL 0x0200L +#define PES_AUTORETURN 0x0400L +#define PES_UNDO 0x0800L +#define PES_RICH 0x1000L +#define PES_SPELLCHECK 0x2000L +#define PES_TEXTOVERFLOW 0x4000L +#define PES_NOREAD 0x8000L + +// listbox styles +#define PLBS_MULTIPLESEL 0x0001L +#define PLBS_HOVERSEL 0x0008L + +// combobox styles +#define PCBS_ALLOWCUSTOMTEXT 0x0001L + +struct CPWL_Dash { + CPWL_Dash() : nDash(0), nGap(0), nPhase(0) {} + CPWL_Dash(int32_t dash, int32_t gap, int32_t phase) + : nDash(dash), nGap(gap), nPhase(phase) {} + + void Reset() { + nDash = 0; + nGap = 0; + nPhase = 0; + } + + int32_t nDash; + int32_t nGap; + int32_t nPhase; +}; + +inline bool operator==(const CFX_Color& c1, const CFX_Color& c2) { + return c1.nColorType == c2.nColorType && c1.fColor1 - c2.fColor1 < 0.0001 && + c1.fColor1 - c2.fColor1 > -0.0001 && + c1.fColor2 - c2.fColor2 < 0.0001 && + c1.fColor2 - c2.fColor2 > -0.0001 && + c1.fColor3 - c2.fColor3 < 0.0001 && + c1.fColor3 - c2.fColor3 > -0.0001 && + c1.fColor4 - c2.fColor4 < 0.0001 && c1.fColor4 - c2.fColor4 > -0.0001; +} + +inline bool operator!=(const CFX_Color& c1, const CFX_Color& c2) { + return !(c1 == c2); +} + +#define PWL_SCROLLBAR_WIDTH 12.0f +#define PWL_SCROLLBAR_TRANSPARENCY 150 +#define PWL_DEFAULT_BLACKCOLOR CFX_Color(CFX_Color::kGray, 0) +#define PWL_DEFAULT_WHITECOLOR CFX_Color(CFX_Color::kGray, 1) + +class CPWL_Wnd : public CPWL_TimerHandler, public Observable { + public: + class PrivateData { + protected: + ~PrivateData() {} + }; + + class ProviderIface : public Observable { + public: + virtual ~ProviderIface() {} + + // get a matrix which map user space to CWnd client space + virtual CFX_Matrix GetWindowMatrix(PrivateData* pAttached) = 0; + }; + + class FocusHandlerIface { + public: + virtual ~FocusHandlerIface() {} + virtual void OnSetFocus(CPWL_Edit* pEdit) = 0; + }; + + class CreateParams { + public: + CreateParams(); + CreateParams(const CreateParams& other); + ~CreateParams(); + + CFX_FloatRect rcRectWnd; // required + CFX_SystemHandler* pSystemHandler; // required + IPVT_FontMap* pFontMap; // required + ProviderIface::ObservedPtr pProvider; // required + UnownedPtr pFocusHandler; // optional + uint32_t dwFlags; // optional + CFX_Color sBackgroundColor; // optional + CPDFSDK_Widget::ObservedPtr pAttachedWidget; // required + BorderStyle nBorderStyle; // optional + int32_t dwBorderWidth; // optional + CFX_Color sBorderColor; // optional + CFX_Color sTextColor; // optional + int32_t nTransparency; // optional + float fFontSize; // optional + CPWL_Dash sDash; // optional + UnownedPtr pAttachedData; // optional + CPWL_Wnd* pParentWnd; // ignore + CPWL_MsgControl* pMsgControl; // ignore + int32_t eCursorType; // ignore + CFX_Matrix mtChild; // ignore + }; + + CPWL_Wnd(); + ~CPWL_Wnd() override; + + virtual ByteString GetClassName() const; + + // Returns |true| iff this instance is still allocated. + virtual bool InvalidateRect(CFX_FloatRect* pRect); + + virtual bool OnKeyDown(uint16_t nChar, uint32_t nFlag); + virtual bool OnChar(uint16_t nChar, uint32_t nFlag); + virtual bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag); + virtual bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag); + virtual bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag); + virtual bool OnRButtonDown(const CFX_PointF& point, uint32_t nFlag); + virtual bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag); + virtual bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag); + virtual bool OnMouseWheel(short zDelta, + const CFX_PointF& point, + uint32_t nFlag); + virtual void SetScrollInfo(const PWL_SCROLL_INFO& info); + virtual void SetScrollPosition(float pos); + virtual void ScrollWindowVertically(float pos); + virtual void NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos); + virtual void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos); + virtual void NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos); + virtual void SetFocus(); + virtual void KillFocus(); + virtual void SetCursor(); + + // Returns |true| iff this instance is still allocated. + virtual bool SetVisible(bool bVisible); + virtual void SetFontSize(float fFontSize); + virtual float GetFontSize() const; + + virtual WideString GetSelectedText(); + virtual void ReplaceSelection(const WideString& text); + virtual CFX_FloatRect GetFocusRect() const; + virtual CFX_FloatRect GetClientRect() const; + + void InvalidateFocusHandler(FocusHandlerIface* handler); + void InvalidateProvider(ProviderIface* provider); + void Create(const CreateParams& cp); + void Destroy(); + bool Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh); + + void SetCapture(); + void ReleaseCapture(); + + void DrawAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device); + + CFX_Color GetBackgroundColor() const; + void SetBackgroundColor(const CFX_Color& color); + CFX_Color GetBorderColor() const; + CFX_Color GetTextColor() const; + void SetTextColor(const CFX_Color& color); + CFX_Color GetBorderLeftTopColor(BorderStyle nBorderStyle) const; + CFX_Color GetBorderRightBottomColor(BorderStyle nBorderStyle) const; + + void SetBorderStyle(BorderStyle eBorderStyle); + BorderStyle GetBorderStyle() const; + const CPWL_Dash& GetBorderDash() const; + + int32_t GetBorderWidth() const; + int32_t GetInnerBorderWidth() const; + CFX_FloatRect GetWindowRect() const; + CFX_PointF GetCenterPoint() const; + + bool IsVisible() const { return m_bVisible; } + bool HasFlag(uint32_t dwFlags) const; + void AddFlag(uint32_t dwFlags); + void RemoveFlag(uint32_t dwFlags); + + void SetClipRect(const CFX_FloatRect& rect); + const CFX_FloatRect& GetClipRect() const; + + CPWL_Wnd* GetParentWindow() const; + PrivateData* GetAttachedData() const; + + bool WndHitTest(const CFX_PointF& point) const; + bool ClientHitTest(const CFX_PointF& point) const; + bool IsCaptureMouse() const; + + void EnableWindow(bool bEnable); + bool IsEnabled() const { return m_bEnabled; } + const CPWL_Wnd* GetFocused() const; + bool IsFocused() const; + bool IsReadOnly() const; + CPWL_ScrollBar* GetVScrollBar() const; + + IPVT_FontMap* GetFontMap() const; + ProviderIface* GetProvider() const; + FocusHandlerIface* GetFocusHandler() const; + + int32_t GetTransparency(); + void SetTransparency(int32_t nTransparency); + + CFX_Matrix GetChildToRoot() const; + CFX_Matrix GetChildMatrix() const; + void SetChildMatrix(const CFX_Matrix& mt); + CFX_Matrix GetWindowMatrix() const; + + virtual void OnSetFocus(); + virtual void OnKillFocus(); + + protected: + // CPWL_TimerHandler + CFX_SystemHandler* GetSystemHandler() const override; + + virtual void CreateChildWnd(const CreateParams& cp); + + // Returns |true| iff this instance is still allocated. + virtual bool RePosChildWnd(); + + virtual void DrawThisAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device); + + virtual void OnCreate(CreateParams* pParamsToAdjust); + virtual void OnCreated(); + virtual void OnDestroy(); + + void SetNotifyFlag(bool bNotifying = true) { m_bNotifying = bNotifying; } + bool IsNotifying() const { return m_bNotifying; } + bool IsValid() const { return m_bCreated; } + const CreateParams& GetCreationParams() const { return m_CreationParams; } + + // Returns |true| iff this instance is still allocated. + bool InvalidateRectMove(const CFX_FloatRect& rcOld, + const CFX_FloatRect& rcNew); + + bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const; + bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const; + const CPWL_Wnd* GetRootWnd() const; + + static bool IsCTRLpressed(uint32_t nFlag) { + return CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); + } + static bool IsSHIFTpressed(uint32_t nFlag) { + return CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); + } + static bool IsALTpressed(uint32_t nFlag) { + return CPDFSDK_FormFillEnvironment::IsALTKeyDown(nFlag); + } + + private: + CFX_PointF ParentToChild(const CFX_PointF& point) const; + CFX_FloatRect ParentToChild(const CFX_FloatRect& rect) const; + + void DrawChildAppearance(CFX_RenderDevice* pDevice, + const CFX_Matrix& mtUser2Device); + + CFX_FloatRect PWLtoWnd(const CFX_FloatRect& rect) const; + + void AddChild(CPWL_Wnd* pWnd); + void RemoveChild(CPWL_Wnd* pWnd); + + void CreateScrollBar(const CreateParams& cp); + void CreateVScrollBar(const CreateParams& cp); + + void AdjustStyle(); + void CreateMsgControl(); + void DestroyMsgControl(); + + CPWL_MsgControl* GetMsgControl() const; + + CreateParams m_CreationParams; + std::vector m_Children; + UnownedPtr m_pVScrollBar; + CFX_FloatRect m_rcWindow; + CFX_FloatRect m_rcClip; + bool m_bCreated; + bool m_bVisible; + bool m_bNotifying; + bool m_bEnabled; +}; + +#endif // FPDFSDK_PWL_CPWL_WND_H_ diff --git a/fxbarcode/BC_Library.cpp b/fxbarcode/BC_Library.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d658ef3ecea6c982cc1fe3670290fbc6463352c --- /dev/null +++ b/fxbarcode/BC_Library.cpp @@ -0,0 +1,37 @@ +// 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 "fxbarcode/BC_Library.h" + +#include + +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/datamatrix/BC_ErrorCorrection.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" + +void BC_Library_Init() { + CBC_QRCoderErrorCorrectionLevel::Initialize(); + CBC_QRCoderMode::Initialize(); + CBC_QRCoderVersion::Initialize(); + CBC_ReedSolomonGF256::Initialize(); + CBC_SymbolInfo::Initialize(); + CBC_ErrorCorrection::Initialize(); + CBC_PDF417HighLevelEncoder::Initialize(); +} + +void BC_Library_Destroy() { + CBC_QRCoderErrorCorrectionLevel::Finalize(); + CBC_QRCoderMode::Finalize(); + CBC_QRCoderVersion::Finalize(); + CBC_ReedSolomonGF256::Finalize(); + CBC_SymbolInfo::Finalize(); + CBC_ErrorCorrection::Finalize(); + CBC_PDF417HighLevelEncoder::Finalize(); +} diff --git a/xfa/fxbarcode/BC_Library.h b/fxbarcode/BC_Library.h similarity index 83% rename from xfa/fxbarcode/BC_Library.h rename to fxbarcode/BC_Library.h index 47ef9d1532e0f66caa3e545380aa69ff9ac53bfc..4e98743d9155471759e7673061a9cbae33153394 100644 --- a/xfa/fxbarcode/BC_Library.h +++ b/fxbarcode/BC_Library.h @@ -4,8 +4,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_BC_LIBRARY_H_ -#define XFA_FXBARCODE_BC_LIBRARY_H_ +#ifndef FXBARCODE_BC_LIBRARY_H_ +#define FXBARCODE_BC_LIBRARY_H_ enum BC_TEXT_LOC { BC_TEXT_LOC_NONE = 0, @@ -33,6 +33,6 @@ enum BC_TYPE { }; void BC_Library_Init(); -void BC_Library_Destory(); +void BC_Library_Destroy(); -#endif // XFA_FXBARCODE_BC_LIBRARY_H_ +#endif // FXBARCODE_BC_LIBRARY_H_ diff --git a/fxbarcode/BC_TwoDimWriter.cpp b/fxbarcode/BC_TwoDimWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6852fee35c62ca10ea6e305863a12ebacdbd3b26 --- /dev/null +++ b/fxbarcode/BC_TwoDimWriter.cpp @@ -0,0 +1,112 @@ +// 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 + +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "fxbarcode/BC_TwoDimWriter.h" +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/ptr_util.h" + +CBC_TwoDimWriter::CBC_TwoDimWriter() : m_iCorrectLevel(1), m_bFixedSize(true) {} + +CBC_TwoDimWriter::~CBC_TwoDimWriter() {} + +void CBC_TwoDimWriter::RenderDeviceResult(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + CFX_GraphStateData stateData; + CFX_PathData path; + path.AppendRect(0, 0, (float)m_Width, (float)m_Height); + device->DrawPath(&path, matrix, &stateData, m_backgroundColor, + m_backgroundColor, FXFILL_ALTERNATE); + int32_t leftPos = 0; + int32_t topPos = 0; + if (m_bFixedSize) { + leftPos = (m_Width - m_output->GetWidth()) / 2; + topPos = (m_Height - m_output->GetHeight()) / 2; + } + CFX_Matrix matri = *matrix; + if (m_Width < m_output->GetWidth() && m_Height < m_output->GetHeight()) { + CFX_Matrix matriScale((float)m_Width / (float)m_output->GetWidth(), 0.0, + 0.0, (float)m_Height / (float)m_output->GetHeight(), + 0.0, 0.0); + matriScale.Concat(*matrix); + matri = matriScale; + } + for (int32_t x = 0; x < m_output->GetWidth(); x++) { + for (int32_t y = 0; y < m_output->GetHeight(); y++) { + CFX_PathData rect; + rect.AppendRect((float)leftPos + x, (float)topPos + y, + (float)(leftPos + x + 1), (float)(topPos + y + 1)); + if (m_output->Get(x, y)) { + CFX_GraphStateData data; + device->DrawPath(&rect, &matri, &data, m_barColor, 0, FXFILL_WINDING); + } + } + } +} + +int32_t CBC_TwoDimWriter::GetErrorCorrectionLevel() const { + return m_iCorrectLevel; +} + +bool CBC_TwoDimWriter::RenderResult(uint8_t* code, + int32_t codeWidth, + int32_t codeHeight) { + int32_t inputWidth = codeWidth; + int32_t inputHeight = codeHeight; + int32_t tempWidth = inputWidth + 2; + int32_t tempHeight = inputHeight + 2; + float moduleHSize = std::min(m_ModuleWidth, m_ModuleHeight); + moduleHSize = std::min(moduleHSize, 8.0f); + moduleHSize = std::max(moduleHSize, 1.0f); + pdfium::base::CheckedNumeric scaledWidth = tempWidth; + pdfium::base::CheckedNumeric scaledHeight = tempHeight; + scaledWidth *= moduleHSize; + scaledHeight *= moduleHSize; + + int32_t outputWidth = scaledWidth.ValueOrDie(); + int32_t outputHeight = scaledHeight.ValueOrDie(); + if (m_bFixedSize) { + if (m_Width < outputWidth || m_Height < outputHeight) { + return false; + } + } else { + if (m_Width > outputWidth || m_Height > outputHeight) { + outputWidth = + (int32_t)(outputWidth * ceil((float)m_Width / (float)outputWidth)); + outputHeight = + (int32_t)(outputHeight * ceil((float)m_Height / (float)outputHeight)); + } + } + int32_t multiX = (int32_t)ceil((float)outputWidth / (float)tempWidth); + int32_t multiY = (int32_t)ceil((float)outputHeight / (float)tempHeight); + if (m_bFixedSize) { + multiX = std::min(multiX, multiY); + multiY = multiX; + } + int32_t leftPadding = std::max((outputWidth - (inputWidth * multiX)) / 2, 0); + int32_t topPadding = std::max((outputHeight - (inputHeight * multiY)) / 2, 0); + m_output = pdfium::MakeUnique(); + m_output->Init(outputWidth, outputHeight); + for (int32_t inputY = 0, outputY = topPadding; + (inputY < inputHeight) && (outputY < outputHeight - multiY); + inputY++, outputY += multiY) { + for (int32_t inputX = 0, outputX = leftPadding; + (inputX < inputWidth) && (outputX < outputWidth - multiX); + inputX++, outputX += multiX) { + if (code[inputX + inputY * inputWidth] == 1 && + !m_output->SetRegion(outputX, outputY, multiX, multiY)) { + return false; + } + } + } + return true; +} diff --git a/fxbarcode/BC_TwoDimWriter.h b/fxbarcode/BC_TwoDimWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..e554805fcf108799b4dacc989b7fa323d0f5c63a --- /dev/null +++ b/fxbarcode/BC_TwoDimWriter.h @@ -0,0 +1,37 @@ +// 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 FXBARCODE_BC_TWODIMWRITER_H_ +#define FXBARCODE_BC_TWODIMWRITER_H_ + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "fxbarcode/BC_Writer.h" + +class CBC_CommonBitMatrix; +class CFX_RenderDevice; + +class CBC_TwoDimWriter : public CBC_Writer { + public: + CBC_TwoDimWriter(); + ~CBC_TwoDimWriter() override; + + virtual bool RenderResult(uint8_t* code, + int32_t codeWidth, + int32_t codeHeight); + virtual void RenderDeviceResult(CFX_RenderDevice* device, + const CFX_Matrix* matrix); + virtual bool SetErrorCorrectionLevel(int32_t level) = 0; + int32_t GetErrorCorrectionLevel() const; + + protected: + int32_t m_iCorrectLevel; + bool m_bFixedSize; + std::unique_ptr m_output; +}; + +#endif // FXBARCODE_BC_TWODIMWRITER_H_ diff --git a/fxbarcode/BC_UtilCodingConvert.cpp b/fxbarcode/BC_UtilCodingConvert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77c52f20747ce0a4ac3f4694df56bd86042a2892 --- /dev/null +++ b/fxbarcode/BC_UtilCodingConvert.cpp @@ -0,0 +1,51 @@ +// 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 "fxbarcode/BC_UtilCodingConvert.h" + +CBC_UtilCodingConvert::CBC_UtilCodingConvert() {} + +CBC_UtilCodingConvert::~CBC_UtilCodingConvert() {} + +void CBC_UtilCodingConvert::UnicodeToLocale(const WideString& src, + ByteString& dst) { + dst = ByteString::FromUnicode(src); +} + +void CBC_UtilCodingConvert::LocaleToUtf8(const ByteString& src, + ByteString& dst) { + WideString unicode = WideString::FromLocal(src.AsStringView()); + dst = unicode.UTF8Encode(); +} + +void CBC_UtilCodingConvert::LocaleToUtf8(const ByteString& src, + std::vector& dst) { + WideString unicode = WideString::FromLocal(src.AsStringView()); + ByteString utf8 = unicode.UTF8Encode(); + dst = std::vector(utf8.begin(), utf8.end()); +} + +void CBC_UtilCodingConvert::Utf8ToLocale(const std::vector& src, + ByteString& dst) { + ByteString utf8; + for (uint8_t value : src) + utf8 += value; + + WideString unicode = WideString::FromUTF8(utf8.AsStringView()); + dst = ByteString::FromUnicode(unicode); +} + +void CBC_UtilCodingConvert::Utf8ToLocale(const uint8_t* src, + int32_t count, + ByteString& dst) { + WideString unicode = WideString::FromUTF8(ByteStringView(src, count)); + dst = ByteString::FromUnicode(unicode); +} + +void CBC_UtilCodingConvert::UnicodeToUTF8(const WideString& src, + ByteString& dst) { + dst = src.UTF8Encode(); +} diff --git a/fxbarcode/BC_UtilCodingConvert.h b/fxbarcode/BC_UtilCodingConvert.h new file mode 100644 index 0000000000000000000000000000000000000000..8600cd14b594fddf135605b9ce9c5de82c960078 --- /dev/null +++ b/fxbarcode/BC_UtilCodingConvert.h @@ -0,0 +1,30 @@ +// 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 FXBARCODE_BC_UTILCODINGCONVERT_H_ +#define FXBARCODE_BC_UTILCODINGCONVERT_H_ + +#include + +#include "core/fxcrt/fx_string.h" + +class CBC_UtilCodingConvert { + public: + CBC_UtilCodingConvert(); + virtual ~CBC_UtilCodingConvert(); + static void UnicodeToLocale(const WideString& source, ByteString& result); + static void LocaleToUtf8(const ByteString& source, ByteString& result); + static void LocaleToUtf8(const ByteString& source, + std::vector& result); + static void Utf8ToLocale(const std::vector& source, + ByteString& result); + static void Utf8ToLocale(const uint8_t* source, + int32_t count, + ByteString& result); + static void UnicodeToUTF8(const WideString& source, ByteString& result); +}; + +#endif // FXBARCODE_BC_UTILCODINGCONVERT_H_ diff --git a/fxbarcode/BC_Utils.cpp b/fxbarcode/BC_Utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d09e247365ffa802db1deb9fd3064b074b996c6 --- /dev/null +++ b/fxbarcode/BC_Utils.cpp @@ -0,0 +1,33 @@ +// 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 + +#include "fxbarcode/utils.h" + +bool BC_FX_ByteString_Replace(ByteString& dst, + uint32_t first, + uint32_t last, + int32_t count, + char c) { + if (first > last || count <= 0) { + return false; + } + dst.Delete(first, last - first); + for (int32_t i = 0; i < count; i++) { + dst.InsertAtFront(c); + } + return true; +} + +void BC_FX_ByteString_Append(ByteString& dst, int32_t count, char c) { + for (int32_t i = 0; i < count; i++) + dst += c; +} +void BC_FX_ByteString_Append(ByteString& dst, const std::vector& ba) { + for (uint8_t value : ba) + dst += value; +} diff --git a/xfa/fxbarcode/BC_Writer.cpp b/fxbarcode/BC_Writer.cpp similarity index 85% rename from xfa/fxbarcode/BC_Writer.cpp rename to fxbarcode/BC_Writer.cpp index 73163522cb1adb89e31c87763d29b0166242896b..5c8e0cf3b74bf7813cb5d200fca154579ff34e21 100644 --- a/xfa/fxbarcode/BC_Writer.cpp +++ b/fxbarcode/BC_Writer.cpp @@ -4,7 +4,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxbarcode/BC_Writer.h" +#include "fxbarcode/BC_Writer.h" CBC_Writer::CBC_Writer() { m_CharEncoding = 0; @@ -49,8 +49,10 @@ void CBC_Writer::SetBackgroundColor(FX_ARGB backgroundColor) { void CBC_Writer::SetBarcodeColor(FX_ARGB foregroundColor) { m_barColor = foregroundColor; } -CFX_DIBitmap* CBC_Writer::CreateDIBitmap(int32_t width, int32_t height) { - CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; + +RetainPtr CBC_Writer::CreateDIBitmap(int32_t width, + int32_t height) { + auto pDIBitmap = pdfium::MakeRetain(); pDIBitmap->Create(width, height, m_colorSpace); return pDIBitmap; } diff --git a/xfa/fxbarcode/BC_Writer.h b/fxbarcode/BC_Writer.h similarity index 79% rename from xfa/fxbarcode/BC_Writer.h rename to fxbarcode/BC_Writer.h index 90ea06a3971465f36f5d6251faecd7cd3c12bdf5..565c03f1a55ed1b1f0ce479b2e0b923882c2d4e8 100644 --- a/xfa/fxbarcode/BC_Writer.h +++ b/fxbarcode/BC_Writer.h @@ -4,12 +4,13 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_BC_WRITER_H_ -#define XFA_FXBARCODE_BC_WRITER_H_ +#ifndef FXBARCODE_BC_WRITER_H_ +#define FXBARCODE_BC_WRITER_H_ #include "core/fxcrt/fx_string.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/utils.h" +#include "fxbarcode/utils.h" class CBC_Writer { public: @@ -24,7 +25,7 @@ class CBC_Writer { virtual void SetBarcodeColor(FX_ARGB foregroundColor); protected: - CFX_DIBitmap* CreateDIBitmap(int32_t width, int32_t height); + RetainPtr CreateDIBitmap(int32_t width, int32_t height); int32_t m_CharEncoding; int32_t m_ModuleHeight; int32_t m_ModuleWidth; @@ -35,4 +36,4 @@ class CBC_Writer { FX_ARGB m_backgroundColor; }; -#endif // XFA_FXBARCODE_BC_WRITER_H_ +#endif // FXBARCODE_BC_WRITER_H_ diff --git a/fxbarcode/DEPS b/fxbarcode/DEPS new file mode 100644 index 0000000000000000000000000000000000000000..35a265a6c3503a788b2a5c07c4566f89fbe13c74 --- /dev/null +++ b/fxbarcode/DEPS @@ -0,0 +1,6 @@ +include_rules = [ + '+core/fxcodec', + '+core/fxcrt', + '+core/fxge', + '+third_party/bigint', +] diff --git a/fxbarcode/cbc_codabar.cpp b/fxbarcode/cbc_codabar.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0795ff295d0a6f53aa623cf5bc50e0332b80fb60 --- /dev/null +++ b/fxbarcode/cbc_codabar.cpp @@ -0,0 +1,84 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_codabar.h" + +#include + +#include "fxbarcode/oned/BC_OnedCodaBarWriter.h" +#include "third_party/base/ptr_util.h" + +CBC_Codabar::CBC_Codabar() + : CBC_OneCode(pdfium::MakeUnique()) {} + +CBC_Codabar::~CBC_Codabar() {} + +bool CBC_Codabar::SetStartChar(char start) { + return GetOnedCodaBarWriter()->SetStartChar(start); +} + +bool CBC_Codabar::SetEndChar(char end) { + return GetOnedCodaBarWriter()->SetEndChar(end); +} + +bool CBC_Codabar::SetTextLocation(BC_TEXT_LOC location) { + return GetOnedCodaBarWriter()->SetTextLocation(location); +} + +bool CBC_Codabar::SetWideNarrowRatio(int8_t ratio) { + return GetOnedCodaBarWriter()->SetWideNarrowRatio(ratio); +} + +bool CBC_Codabar::Encode(const WideStringView& contents) { + if (contents.IsEmpty()) + return false; + + BCFORMAT format = BCFORMAT_CODABAR; + int32_t outWidth = 0; + int32_t outHeight = 0; + WideString filtercontents = GetOnedCodaBarWriter()->FilterContents(contents); + ByteString byteString = filtercontents.UTF8Encode(); + m_renderContents = filtercontents; + auto* pWriter = GetOnedCodaBarWriter(); + std::unique_ptr data( + pWriter->Encode(byteString, format, outWidth, outHeight)); + if (!data) + return false; + + return pWriter->RenderResult(filtercontents.AsStringView(), data.get(), + outWidth); +} + +bool CBC_Codabar::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + auto* pWriter = GetOnedCodaBarWriter(); + WideString renderCon = + pWriter->encodedContents(m_renderContents.AsStringView()); + return pWriter->RenderDeviceResult(device, matrix, renderCon.AsStringView()); +} + +BC_TYPE CBC_Codabar::GetType() { + return BC_CODABAR; +} + +CBC_OnedCodaBarWriter* CBC_Codabar::GetOnedCodaBarWriter() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_codabar.h b/fxbarcode/cbc_codabar.h new file mode 100644 index 0000000000000000000000000000000000000000..827fc28d0f7807e609f61ae913054ddd1d12d088 --- /dev/null +++ b/fxbarcode/cbc_codabar.h @@ -0,0 +1,39 @@ +// Copyright 2016 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 FXBARCODE_CBC_CODABAR_H_ +#define FXBARCODE_CBC_CODABAR_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_onecode.h" + +class CBC_OnedCodaBarWriter; + +class CBC_Codabar : public CBC_OneCode { + public: + CBC_Codabar(); + ~CBC_Codabar() override; + + // CBC_OneCode: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + bool SetStartChar(char start); + bool SetEndChar(char end); + bool SetTextLocation(BC_TEXT_LOC location); + bool SetWideNarrowRatio(int8_t ratio); + + private: + CBC_OnedCodaBarWriter* GetOnedCodaBarWriter(); + + WideString m_renderContents; +}; + +#endif // FXBARCODE_CBC_CODABAR_H_ diff --git a/fxbarcode/cbc_code128.cpp b/fxbarcode/cbc_code128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ba623542dc30630d8cc9195736285ccdb907d19 --- /dev/null +++ b/fxbarcode/cbc_code128.cpp @@ -0,0 +1,73 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_code128.h" + +#include + +#include "fxbarcode/oned/BC_OnedCode128Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_Code128::CBC_Code128(BC_TYPE type) + : CBC_OneCode(pdfium::MakeUnique(type)) {} + +CBC_Code128::~CBC_Code128() {} + +bool CBC_Code128::SetTextLocation(BC_TEXT_LOC location) { + return GetOnedCode128Writer()->SetTextLocation(location); +} + +bool CBC_Code128::Encode(const WideStringView& contents) { + if (contents.IsEmpty()) + return false; + + BCFORMAT format = BCFORMAT_CODE_128; + int32_t outWidth = 0; + int32_t outHeight = 0; + auto* pWriter = GetOnedCode128Writer(); + WideString content(contents); + if (contents.GetLength() % 2 && pWriter->GetType() == BC_CODE128_C) + content += '0'; + + WideString encodeContents = pWriter->FilterContents(content.AsStringView()); + m_renderContents = encodeContents; + ByteString byteString = encodeContents.UTF8Encode(); + std::unique_ptr data( + pWriter->Encode(byteString, format, outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(encodeContents.AsStringView(), data.get(), + outWidth); +} + +bool CBC_Code128::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + return GetOnedCode128Writer()->RenderDeviceResult( + device, matrix, m_renderContents.AsStringView()); +} + +BC_TYPE CBC_Code128::GetType() { + return BC_CODE128; +} + +CBC_OnedCode128Writer* CBC_Code128::GetOnedCode128Writer() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_code128.h b/fxbarcode/cbc_code128.h new file mode 100644 index 0000000000000000000000000000000000000000..b057aff2afd4b3efd46ea1f71bf08b70a25577a3 --- /dev/null +++ b/fxbarcode/cbc_code128.h @@ -0,0 +1,36 @@ +// Copyright 2016 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 FXBARCODE_CBC_CODE128_H_ +#define FXBARCODE_CBC_CODE128_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_onecode.h" + +class CBC_OnedCode128Writer; + +class CBC_Code128 : public CBC_OneCode { + public: + explicit CBC_Code128(BC_TYPE type); + ~CBC_Code128() override; + + // CBC_OneCode: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + bool SetTextLocation(BC_TEXT_LOC loction); + + private: + CBC_OnedCode128Writer* GetOnedCode128Writer(); + + WideString m_renderContents; +}; + +#endif // FXBARCODE_CBC_CODE128_H_ diff --git a/fxbarcode/cbc_code39.cpp b/fxbarcode/cbc_code39.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9715c258284c6186799f0c00f79aff09061541c1 --- /dev/null +++ b/fxbarcode/cbc_code39.cpp @@ -0,0 +1,77 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_code39.h" + +#include + +#include "fxbarcode/oned/BC_OnedCode39Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_Code39::CBC_Code39() + : CBC_OneCode(pdfium::MakeUnique()) {} + +CBC_Code39::~CBC_Code39() {} + +bool CBC_Code39::Encode(const WideStringView& contents) { + if (contents.IsEmpty()) + return false; + + BCFORMAT format = BCFORMAT_CODE_39; + int32_t outWidth = 0; + int32_t outHeight = 0; + auto* pWriter = GetOnedCode39Writer(); + WideString filtercontents = pWriter->FilterContents(contents); + WideString renderContents = pWriter->RenderTextContents(contents); + m_renderContents = renderContents; + ByteString byteString = filtercontents.UTF8Encode(); + std::unique_ptr data( + pWriter->Encode(byteString, format, outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(renderContents.AsStringView(), data.get(), + outWidth); +} + +bool CBC_Code39::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + auto* pWriter = GetOnedCode39Writer(); + WideString renderCon; + if (!pWriter->encodedContents(m_renderContents.AsStringView(), &renderCon)) + return false; + return pWriter->RenderDeviceResult(device, matrix, renderCon.AsStringView()); +} + +BC_TYPE CBC_Code39::GetType() { + return BC_CODE39; +} + +bool CBC_Code39::SetTextLocation(BC_TEXT_LOC location) { + return GetOnedCode39Writer()->SetTextLocation(location); +} + +bool CBC_Code39::SetWideNarrowRatio(int8_t ratio) { + return GetOnedCode39Writer()->SetWideNarrowRatio(ratio); +} + +CBC_OnedCode39Writer* CBC_Code39::GetOnedCode39Writer() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_code39.h b/fxbarcode/cbc_code39.h new file mode 100644 index 0000000000000000000000000000000000000000..937673c740696b794d898cd7a206a420d7b255ae --- /dev/null +++ b/fxbarcode/cbc_code39.h @@ -0,0 +1,38 @@ +// Copyright 2016 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 FXBARCODE_CBC_CODE39_H_ +#define FXBARCODE_CBC_CODE39_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_onecode.h" + +class CBC_OnedCode39Writer; + +class CBC_Code39 : public CBC_OneCode { + public: + CBC_Code39(); + ~CBC_Code39() override; + + // CBC_OneCode: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + bool SetTextLocation(BC_TEXT_LOC location); + bool SetWideNarrowRatio(int8_t ratio); + + private: + CBC_OnedCode39Writer* GetOnedCode39Writer(); + + WideString m_renderContents; +}; + +#endif // FXBARCODE_CBC_CODE39_H_ diff --git a/fxbarcode/cbc_codebase.cpp b/fxbarcode/cbc_codebase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2278f931e86c1ddfeeea05902197d62b69484a1a --- /dev/null +++ b/fxbarcode/cbc_codebase.cpp @@ -0,0 +1,59 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_codebase.h" + +#include + +#include "fxbarcode/BC_Writer.h" + +CBC_CodeBase::CBC_CodeBase(std::unique_ptr pWriter) + : m_pBCWriter(std::move(pWriter)) {} + +CBC_CodeBase::~CBC_CodeBase() {} + +bool CBC_CodeBase::SetCharEncoding(int32_t encoding) { + return m_pBCWriter->SetCharEncoding(encoding); +} + +bool CBC_CodeBase::SetModuleHeight(int32_t moduleHeight) { + return m_pBCWriter->SetModuleHeight(moduleHeight); +} + +bool CBC_CodeBase::SetModuleWidth(int32_t moduleWidth) { + return m_pBCWriter->SetModuleWidth(moduleWidth); +} + +bool CBC_CodeBase::SetHeight(int32_t height) { + return m_pBCWriter->SetHeight(height); +} + +bool CBC_CodeBase::SetWidth(int32_t width) { + return m_pBCWriter->SetWidth(width); +} + +void CBC_CodeBase::SetBackgroundColor(FX_ARGB backgroundColor) { + m_pBCWriter->SetBackgroundColor(backgroundColor); +} + +void CBC_CodeBase::SetBarcodeColor(FX_ARGB foregroundColor) { + m_pBCWriter->SetBarcodeColor(foregroundColor); +} diff --git a/fxbarcode/cbc_codebase.h b/fxbarcode/cbc_codebase.h new file mode 100644 index 0000000000000000000000000000000000000000..aab98da32b30ef3a0af13d9c9f1b7eb2d167204d --- /dev/null +++ b/fxbarcode/cbc_codebase.h @@ -0,0 +1,45 @@ +// Copyright 2016 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 FXBARCODE_CBC_CODEBASE_H_ +#define FXBARCODE_CBC_CODEBASE_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/BC_Library.h" + +class CBC_Reader; +class CBC_Writer; +class CFX_DIBitmap; +class CFX_Matrix; +class CFX_RenderDevice; + +class CBC_CodeBase { + public: + explicit CBC_CodeBase(std::unique_ptr pWriter); + virtual ~CBC_CodeBase(); + + virtual BC_TYPE GetType() = 0; + virtual bool Encode(const WideStringView& contents) = 0; + virtual bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) = 0; + + bool SetCharEncoding(int32_t encoding); + bool SetModuleHeight(int32_t moduleHeight); + bool SetModuleWidth(int32_t moduleWidth); + bool SetHeight(int32_t height); + bool SetWidth(int32_t width); + void SetBackgroundColor(FX_ARGB backgroundColor); + void SetBarcodeColor(FX_ARGB foregroundColor); + + protected: + std::unique_ptr m_pBCWriter; +}; + +#endif // FXBARCODE_CBC_CODEBASE_H_ diff --git a/fxbarcode/cbc_datamatrix.cpp b/fxbarcode/cbc_datamatrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9e23fa7ae5286173cb554999611627ed389dfdf --- /dev/null +++ b/fxbarcode/cbc_datamatrix.cpp @@ -0,0 +1,57 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_datamatrix.h" + +#include + +#include "fxbarcode/datamatrix/BC_DataMatrixWriter.h" +#include "third_party/base/ptr_util.h" + +CBC_DataMatrix::CBC_DataMatrix() + : CBC_CodeBase(pdfium::MakeUnique()) {} + +CBC_DataMatrix::~CBC_DataMatrix() {} + +bool CBC_DataMatrix::Encode(const WideStringView& contents) { + int32_t outWidth = 0; + int32_t outHeight = 0; + auto* pWriter = GetDataMatrixWriter(); + std::unique_ptr data( + pWriter->Encode(WideString(contents), outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(data.get(), outWidth, outHeight); +} + +bool CBC_DataMatrix::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + GetDataMatrixWriter()->RenderDeviceResult(device, matrix); + return true; +} + +BC_TYPE CBC_DataMatrix::GetType() { + return BC_DATAMATRIX; +} + +CBC_DataMatrixWriter* CBC_DataMatrix::GetDataMatrixWriter() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_datamatrix.h b/fxbarcode/cbc_datamatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..3fe1c09326a27661b26231d2cc2d376fc6a6f0e7 --- /dev/null +++ b/fxbarcode/cbc_datamatrix.h @@ -0,0 +1,32 @@ +// Copyright 2016 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 FXBARCODE_CBC_DATAMATRIX_H_ +#define FXBARCODE_CBC_DATAMATRIX_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_codebase.h" + +class CBC_DataMatrixWriter; + +class CBC_DataMatrix : public CBC_CodeBase { + public: + CBC_DataMatrix(); + ~CBC_DataMatrix() override; + + // CBC_OneCode: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + private: + CBC_DataMatrixWriter* GetDataMatrixWriter(); +}; + +#endif // FXBARCODE_CBC_DATAMATRIX_H_ diff --git a/fxbarcode/cbc_ean13.cpp b/fxbarcode/cbc_ean13.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16725323f428a312c628ceb8720436f7805778b9 --- /dev/null +++ b/fxbarcode/cbc_ean13.cpp @@ -0,0 +1,84 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_ean13.h" + +#include + +#include "fxbarcode/oned/BC_OnedEAN13Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_EAN13::CBC_EAN13() + : CBC_OneCode(pdfium::MakeUnique()) {} + +CBC_EAN13::~CBC_EAN13() {} + +WideString CBC_EAN13::Preprocess(const WideStringView& contents) { + auto* pWriter = GetOnedEAN13Writer(); + WideString encodeContents = pWriter->FilterContents(contents); + int32_t length = encodeContents.GetLength(); + if (length <= 12) { + for (int32_t i = 0; i < 12 - length; i++) + encodeContents = wchar_t('0') + encodeContents; + + ByteString byteString = encodeContents.UTF8Encode(); + int32_t checksum = pWriter->CalcChecksum(byteString); + byteString += checksum - 0 + '0'; + encodeContents = byteString.UTF8Decode(); + } + if (length > 13) + encodeContents = encodeContents.Left(13); + + return encodeContents; +} + +bool CBC_EAN13::Encode(const WideStringView& contents) { + if (contents.IsEmpty()) + return false; + + BCFORMAT format = BCFORMAT_EAN_13; + int32_t outWidth = 0; + int32_t outHeight = 0; + WideString encodeContents = Preprocess(contents); + ByteString byteString = encodeContents.UTF8Encode(); + m_renderContents = encodeContents; + auto* pWriter = GetOnedEAN13Writer(); + std::unique_ptr data( + pWriter->Encode(byteString, format, outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(encodeContents.AsStringView(), data.get(), + outWidth); +} + +bool CBC_EAN13::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + return GetOnedEAN13Writer()->RenderDeviceResult( + device, matrix, m_renderContents.AsStringView()); +} + +BC_TYPE CBC_EAN13::GetType() { + return BC_EAN13; +} + +CBC_OnedEAN13Writer* CBC_EAN13::GetOnedEAN13Writer() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_ean13.h b/fxbarcode/cbc_ean13.h new file mode 100644 index 0000000000000000000000000000000000000000..609f8b0dc2ff1015fdf9ffbdb749766c1090b085 --- /dev/null +++ b/fxbarcode/cbc_ean13.h @@ -0,0 +1,36 @@ +// Copyright 2016 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 FXBARCODE_CBC_EAN13_H_ +#define FXBARCODE_CBC_EAN13_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_onecode.h" + +class CBC_OnedEAN13Writer; + +class CBC_EAN13 : public CBC_OneCode { + public: + CBC_EAN13(); + ~CBC_EAN13() override; + + // CBC_OneCode: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + private: + CBC_OnedEAN13Writer* GetOnedEAN13Writer(); + WideString Preprocess(const WideStringView& contents); + + WideString m_renderContents; +}; + +#endif // FXBARCODE_CBC_EAN13_H_ diff --git a/fxbarcode/cbc_ean8.cpp b/fxbarcode/cbc_ean8.cpp new file mode 100644 index 0000000000000000000000000000000000000000..796f3a526bb35e10b4fdb00ec94c352a861eb7a8 --- /dev/null +++ b/fxbarcode/cbc_ean8.cpp @@ -0,0 +1,82 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_ean8.h" + +#include + +#include "fxbarcode/oned/BC_OnedEAN8Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_EAN8::CBC_EAN8() : CBC_OneCode(pdfium::MakeUnique()) {} + +CBC_EAN8::~CBC_EAN8() {} + +WideString CBC_EAN8::Preprocess(const WideStringView& contents) { + auto* pWriter = GetOnedEAN8Writer(); + WideString encodeContents = pWriter->FilterContents(contents); + int32_t length = encodeContents.GetLength(); + if (length <= 7) { + for (int32_t i = 0; i < 7 - length; i++) + encodeContents = wchar_t('0') + encodeContents; + + ByteString byteString = encodeContents.UTF8Encode(); + int32_t checksum = pWriter->CalcChecksum(byteString); + encodeContents += wchar_t(checksum - 0 + '0'); + } + if (length > 8) + encodeContents = encodeContents.Left(8); + + return encodeContents; +} + +bool CBC_EAN8::Encode(const WideStringView& contents) { + if (contents.IsEmpty()) + return false; + + BCFORMAT format = BCFORMAT_EAN_8; + int32_t outWidth = 0; + int32_t outHeight = 0; + WideString encodeContents = Preprocess(contents); + ByteString byteString = encodeContents.UTF8Encode(); + m_renderContents = encodeContents; + auto* pWriter = GetOnedEAN8Writer(); + std::unique_ptr data( + pWriter->Encode(byteString, format, outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(encodeContents.AsStringView(), data.get(), + outWidth); +} + +bool CBC_EAN8::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + return GetOnedEAN8Writer()->RenderDeviceResult( + device, matrix, m_renderContents.AsStringView()); +} + +BC_TYPE CBC_EAN8::GetType() { + return BC_EAN8; +} + +CBC_OnedEAN8Writer* CBC_EAN8::GetOnedEAN8Writer() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_ean8.h b/fxbarcode/cbc_ean8.h new file mode 100644 index 0000000000000000000000000000000000000000..4127650c44dbebdd7e131cc79a52e1ed88be84cb --- /dev/null +++ b/fxbarcode/cbc_ean8.h @@ -0,0 +1,34 @@ +// Copyright 2016 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 FXBARCODE_CBC_EAN8_H_ +#define FXBARCODE_CBC_EAN8_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_onecode.h" + +class CBC_OnedEAN8Writer; + +class CBC_EAN8 : public CBC_OneCode { + public: + CBC_EAN8(); + ~CBC_EAN8() override; + + // CBC_OneCode: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + private: + CBC_OnedEAN8Writer* GetOnedEAN8Writer(); + WideString Preprocess(const WideStringView& contents); + WideString m_renderContents; +}; + +#endif // FXBARCODE_CBC_EAN8_H_ diff --git a/fxbarcode/cbc_onecode.cpp b/fxbarcode/cbc_onecode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb8cb05ef87704ca1077d5773a11765f3e4253d0 --- /dev/null +++ b/fxbarcode/cbc_onecode.cpp @@ -0,0 +1,71 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_onecode.h" + +#include + +#include "fxbarcode/oned/BC_OneDimWriter.h" + +CBC_OneCode::CBC_OneCode(std::unique_ptr pWriter) + : CBC_CodeBase(std::move(pWriter)) {} + +CBC_OneCode::~CBC_OneCode() {} + +bool CBC_OneCode::CheckContentValidity(const WideStringView& contents) { + return GetOneDimWriter()->CheckContentValidity(contents); +} + +WideString CBC_OneCode::FilterContents(const WideStringView& contents) { + return GetOneDimWriter()->FilterContents(contents); +} + +void CBC_OneCode::SetPrintChecksum(bool checksum) { + GetOneDimWriter()->SetPrintChecksum(checksum); +} + +void CBC_OneCode::SetDataLength(int32_t length) { + GetOneDimWriter()->SetDataLength(length); +} + +void CBC_OneCode::SetCalChecksum(bool calc) { + GetOneDimWriter()->SetCalcChecksum(calc); +} + +bool CBC_OneCode::SetFont(CFX_Font* cFont) { + return GetOneDimWriter()->SetFont(cFont); +} + +void CBC_OneCode::SetFontSize(float size) { + GetOneDimWriter()->SetFontSize(size); +} + +void CBC_OneCode::SetFontStyle(int32_t style) { + GetOneDimWriter()->SetFontStyle(style); +} + +void CBC_OneCode::SetFontColor(FX_ARGB color) { + GetOneDimWriter()->SetFontColor(color); +} + +CBC_OneDimWriter* CBC_OneCode::GetOneDimWriter() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_onecode.h b/fxbarcode/cbc_onecode.h new file mode 100644 index 0000000000000000000000000000000000000000..eae618ec6b19a2f1b50406be7da065da2c15e56e --- /dev/null +++ b/fxbarcode/cbc_onecode.h @@ -0,0 +1,39 @@ +// Copyright 2016 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 FXBARCODE_CBC_ONECODE_H_ +#define FXBARCODE_CBC_ONECODE_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/cbc_codebase.h" + +class CBC_OneDimWriter; +class CFX_Font; + +class CBC_OneCode : public CBC_CodeBase { + public: + explicit CBC_OneCode(std::unique_ptr pWriter); + ~CBC_OneCode() override; + + virtual bool CheckContentValidity(const WideStringView& contents); + virtual WideString FilterContents(const WideStringView& contents); + + virtual void SetPrintChecksum(bool checksum); + virtual void SetDataLength(int32_t length); + virtual void SetCalChecksum(bool calc); + virtual bool SetFont(CFX_Font* cFont); + virtual void SetFontSize(float size); + virtual void SetFontStyle(int32_t style); + virtual void SetFontColor(FX_ARGB color); + + private: + CBC_OneDimWriter* GetOneDimWriter(); +}; + +#endif // FXBARCODE_CBC_ONECODE_H_ diff --git a/fxbarcode/cbc_pdf417i.cpp b/fxbarcode/cbc_pdf417i.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e7e063a4434aa9233c9afa4e629bf94eb248f93 --- /dev/null +++ b/fxbarcode/cbc_pdf417i.cpp @@ -0,0 +1,66 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_pdf417i.h" + +#include + +#include "fxbarcode/pdf417/BC_PDF417Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_PDF417I::CBC_PDF417I() + : CBC_CodeBase(pdfium::MakeUnique()) {} + +CBC_PDF417I::~CBC_PDF417I() {} + +bool CBC_PDF417I::SetErrorCorrectionLevel(int32_t level) { + GetPDF417Writer()->SetErrorCorrectionLevel(level); + return true; +} + +void CBC_PDF417I::SetTruncated(bool truncated) { + GetPDF417Writer()->SetTruncated(truncated); +} + +bool CBC_PDF417I::Encode(const WideStringView& contents) { + int32_t outWidth = 0; + int32_t outHeight = 0; + auto* pWriter = GetPDF417Writer(); + std::unique_ptr data( + pWriter->Encode(WideString(contents), outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(data.get(), outWidth, outHeight); +} + +bool CBC_PDF417I::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + GetPDF417Writer()->RenderDeviceResult(device, matrix); + return true; +} + +BC_TYPE CBC_PDF417I::GetType() { + return BC_PDF417; +} + +CBC_PDF417Writer* CBC_PDF417I::GetPDF417Writer() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_pdf417i.h b/fxbarcode/cbc_pdf417i.h new file mode 100644 index 0000000000000000000000000000000000000000..5bd7a26eeb8617a5ec43ad03cfd850e10232d866 --- /dev/null +++ b/fxbarcode/cbc_pdf417i.h @@ -0,0 +1,35 @@ +// Copyright 2016 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 FXBARCODE_CBC_PDF417I_H_ +#define FXBARCODE_CBC_PDF417I_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_codebase.h" + +class CBC_PDF417Writer; + +class CBC_PDF417I : public CBC_CodeBase { + public: + CBC_PDF417I(); + ~CBC_PDF417I() override; + + // CBC_CodeBase: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + bool SetErrorCorrectionLevel(int32_t level); + void SetTruncated(bool truncated); + + private: + CBC_PDF417Writer* GetPDF417Writer(); +}; + +#endif // FXBARCODE_CBC_PDF417I_H_ diff --git a/fxbarcode/cbc_qrcode.cpp b/fxbarcode/cbc_qrcode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f3a65ef3a5da9cd1f9f1cfea9451fb7e24ba064 --- /dev/null +++ b/fxbarcode/cbc_qrcode.cpp @@ -0,0 +1,64 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_qrcode.h" + +#include + +#include "fxbarcode/qrcode/BC_QRCodeWriter.h" +#include "third_party/base/ptr_util.h" + +CBC_QRCode::CBC_QRCode() + : CBC_CodeBase(pdfium::MakeUnique()) {} + +CBC_QRCode::~CBC_QRCode() {} + +bool CBC_QRCode::SetErrorCorrectionLevel(int32_t level) { + if (level < 0 || level > 3) + return false; + return GetQRCodeWriter()->SetErrorCorrectionLevel(level); +} + +bool CBC_QRCode::Encode(const WideStringView& contents) { + int32_t outWidth = 0; + int32_t outHeight = 0; + CBC_QRCodeWriter* pWriter = GetQRCodeWriter(); + std::unique_ptr data( + pWriter->Encode(WideString(contents), pWriter->GetErrorCorrectionLevel(), + outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(data.get(), outWidth, outHeight); +} + +bool CBC_QRCode::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + GetQRCodeWriter()->RenderDeviceResult(device, matrix); + return true; +} + +BC_TYPE CBC_QRCode::GetType() { + return BC_QR_CODE; +} + +CBC_QRCodeWriter* CBC_QRCode::GetQRCodeWriter() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_qrcode.h b/fxbarcode/cbc_qrcode.h new file mode 100644 index 0000000000000000000000000000000000000000..509de8a8d822d2616c8538e271cfca1581cfcfc2 --- /dev/null +++ b/fxbarcode/cbc_qrcode.h @@ -0,0 +1,34 @@ +// Copyright 2016 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 FXBARCODE_CBC_QRCODE_H_ +#define FXBARCODE_CBC_QRCODE_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_codebase.h" + +class CBC_QRCodeWriter; + +class CBC_QRCode : public CBC_CodeBase { + public: + CBC_QRCode(); + ~CBC_QRCode() override; + + // CBC_CodeBase: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + bool SetErrorCorrectionLevel(int32_t level); + + private: + CBC_QRCodeWriter* GetQRCodeWriter(); +}; + +#endif // FXBARCODE_CBC_QRCODE_H_ diff --git a/fxbarcode/cbc_upca.cpp b/fxbarcode/cbc_upca.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69cedce5805b0065090c96efc585b50f36f0cdcf --- /dev/null +++ b/fxbarcode/cbc_upca.cpp @@ -0,0 +1,85 @@ +// Copyright 2016 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 +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/cbc_upca.h" + +#include + +#include "fxbarcode/oned/BC_OnedUPCAWriter.h" +#include "third_party/base/ptr_util.h" + +CBC_UPCA::CBC_UPCA() : CBC_OneCode(pdfium::MakeUnique()) {} + +CBC_UPCA::~CBC_UPCA() {} + +WideString CBC_UPCA::Preprocess(const WideStringView& contents) { + CBC_OnedUPCAWriter* pWriter = GetOnedUPCAWriter(); + WideString encodeContents = pWriter->FilterContents(contents); + int32_t length = encodeContents.GetLength(); + if (length <= 11) { + for (int32_t i = 0; i < 11 - length; i++) + encodeContents = wchar_t('0') + encodeContents; + + ByteString byteString = encodeContents.UTF8Encode(); + int32_t checksum = pWriter->CalcChecksum(byteString); + byteString += checksum - 0 + '0'; + encodeContents = byteString.UTF8Decode(); + } + if (length > 12) + encodeContents = encodeContents.Left(12); + + return encodeContents; +} + +bool CBC_UPCA::Encode(const WideStringView& contents) { + if (contents.IsEmpty()) + return false; + + BCFORMAT format = BCFORMAT_UPC_A; + int32_t outWidth = 0; + int32_t outHeight = 0; + WideString encodeContents = Preprocess(contents); + ByteString byteString = encodeContents.UTF8Encode(); + m_renderContents = encodeContents; + + CBC_OnedUPCAWriter* pWriter = GetOnedUPCAWriter(); + pWriter->Init(); + std::unique_ptr data( + pWriter->Encode(byteString, format, outWidth, outHeight)); + if (!data) + return false; + return pWriter->RenderResult(encodeContents.AsStringView(), data.get(), + outWidth); +} + +bool CBC_UPCA::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) { + return GetOnedUPCAWriter()->RenderDeviceResult( + device, matrix, m_renderContents.AsStringView()); +} + +BC_TYPE CBC_UPCA::GetType() { + return BC_UPCA; +} + +CBC_OnedUPCAWriter* CBC_UPCA::GetOnedUPCAWriter() { + return static_cast(m_pBCWriter.get()); +} diff --git a/fxbarcode/cbc_upca.h b/fxbarcode/cbc_upca.h new file mode 100644 index 0000000000000000000000000000000000000000..29c4d7d9e64ed1d847d64846969f617d862e371e --- /dev/null +++ b/fxbarcode/cbc_upca.h @@ -0,0 +1,34 @@ +// Copyright 2016 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 FXBARCODE_CBC_UPCA_H_ +#define FXBARCODE_CBC_UPCA_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/cbc_onecode.h" + +class CBC_OnedUPCAWriter; + +class CBC_UPCA : public CBC_OneCode { + public: + CBC_UPCA(); + ~CBC_UPCA() override; + + // CBC_CodeBase: + bool Encode(const WideStringView& contents) override; + bool RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matrix) override; + BC_TYPE GetType() override; + + private: + CBC_OnedUPCAWriter* GetOnedUPCAWriter(); + WideString Preprocess(const WideStringView& contents); + WideString m_renderContents; +}; + +#endif // FXBARCODE_CBC_UPCA_H_ diff --git a/fxbarcode/common/BC_CommonBitArray.cpp b/fxbarcode/common/BC_CommonBitArray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10da9bef1b4990937ced6f75fae111c38e102d91 --- /dev/null +++ b/fxbarcode/common/BC_CommonBitArray.cpp @@ -0,0 +1,90 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/BC_CommonBitArray.h" + +#include + +#include "fxbarcode/utils.h" + +CBC_CommonBitArray::CBC_CommonBitArray(CBC_CommonBitArray* array) { + m_size = array->GetSize(); + m_bits = array->GetBits(); +} + +CBC_CommonBitArray::CBC_CommonBitArray() { + m_bits.resize(1); + m_size = 0; +} + +CBC_CommonBitArray::CBC_CommonBitArray(int32_t size) { + m_bits.resize((size + 31) >> 5); + m_size = size; +} + +CBC_CommonBitArray::~CBC_CommonBitArray() {} + +size_t CBC_CommonBitArray::GetSize() { + return m_size; +} + +std::vector& CBC_CommonBitArray::GetBits() { + return m_bits; +} + +size_t CBC_CommonBitArray::GetSizeInBytes() { + return (m_size + 7) >> 3; +} + +bool CBC_CommonBitArray::Get(size_t i) { + return (m_bits[i >> 5] & (1 << (i & 0x1f))) != 0; +} + +void CBC_CommonBitArray::Set(size_t i) { + m_bits[i >> 5] |= 1 << (i & 0x1F); +} + +void CBC_CommonBitArray::Flip(size_t i) { + m_bits[i >> 5] ^= 1 << (i & 0x1F); +} + +void CBC_CommonBitArray::SetBulk(size_t i, int32_t newBits) { + m_bits[i >> 5] = newBits; +} + +void CBC_CommonBitArray::Clear() { + for (auto& value : m_bits) + value = 0; +} + +int32_t* CBC_CommonBitArray::GetBitArray() { + return m_bits.data(); +} + +void CBC_CommonBitArray::Reverse() { + std::vector newBits(m_bits.size()); + for (size_t i = 0; i < m_size; i++) { + if (Get(m_size - i - 1)) + newBits[i >> 5] |= 1 << (i & 0x1F); + } + m_bits = std::move(newBits); +} diff --git a/fxbarcode/common/BC_CommonBitArray.h b/fxbarcode/common/BC_CommonBitArray.h new file mode 100644 index 0000000000000000000000000000000000000000..163db86273ac439b7f8ce143bc071473f6a35be0 --- /dev/null +++ b/fxbarcode/common/BC_CommonBitArray.h @@ -0,0 +1,37 @@ +// 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 FXBARCODE_COMMON_BC_COMMONBITARRAY_H_ +#define FXBARCODE_COMMON_BC_COMMONBITARRAY_H_ + +#include + +#include + +class CBC_CommonBitArray { + public: + explicit CBC_CommonBitArray(CBC_CommonBitArray* array); + explicit CBC_CommonBitArray(int32_t size); + CBC_CommonBitArray(); + virtual ~CBC_CommonBitArray(); + + size_t GetSize(); + size_t GetSizeInBytes(); + std::vector& GetBits(); + int32_t* GetBitArray(); + bool Get(size_t i); + void Set(size_t i); + void Flip(size_t i); + void SetBulk(size_t i, int32_t newBits); + void Reverse(); + void Clear(); + + private: + size_t m_size; + std::vector m_bits; +}; + +#endif // FXBARCODE_COMMON_BC_COMMONBITARRAY_H_ diff --git a/fxbarcode/common/BC_CommonBitMatrix.cpp b/fxbarcode/common/BC_CommonBitMatrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6fe447db6f808ad31fca5224cd3a3ba3b8731732 --- /dev/null +++ b/fxbarcode/common/BC_CommonBitMatrix.cpp @@ -0,0 +1,107 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/BC_CommonBitMatrix.h" + +#include "fxbarcode/common/BC_CommonBitArray.h" +#include "fxbarcode/utils.h" +#include "third_party/base/ptr_util.h" + +CBC_CommonBitMatrix::CBC_CommonBitMatrix() {} + +void CBC_CommonBitMatrix::Init(int32_t dimension) { + m_width = dimension; + m_height = dimension; + int32_t rowSize = (m_height + 31) >> 5; + m_rowSize = rowSize; + m_bits = FX_Alloc2D(int32_t, m_rowSize, m_height); + memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t)); +} + +void CBC_CommonBitMatrix::Init(int32_t width, int32_t height) { + m_width = width; + m_height = height; + int32_t rowSize = (width + 31) >> 5; + m_rowSize = rowSize; + m_bits = FX_Alloc2D(int32_t, m_rowSize, m_height); + memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t)); +} + +CBC_CommonBitMatrix::~CBC_CommonBitMatrix() { + FX_Free(m_bits); +} + +bool CBC_CommonBitMatrix::Get(int32_t x, int32_t y) const { + int32_t offset = y * m_rowSize + (x >> 5); + if (offset >= m_rowSize * m_height || offset < 0) + return false; + return ((((uint32_t)m_bits[offset]) >> (x & 0x1f)) & 1) != 0; +} + +void CBC_CommonBitMatrix::Set(int32_t x, int32_t y) { + int32_t offset = y * m_rowSize + (x >> 5); + if (offset >= m_rowSize * m_height || offset < 0) + return; + m_bits[offset] |= 1 << (x & 0x1f); +} + +void CBC_CommonBitMatrix::Flip(int32_t x, int32_t y) { + int32_t offset = y * m_rowSize + (x >> 5); + m_bits[offset] ^= 1 << (x & 0x1f); +} + +void CBC_CommonBitMatrix::Clear() { + memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t)); +} + +bool CBC_CommonBitMatrix::SetRegion(int32_t left, + int32_t top, + int32_t width, + int32_t height) { + if (top < 0 || left < 0 || height < 1 || width < 1) + return false; + + int32_t right = left + width; + int32_t bottom = top + height; + if (m_height < bottom || m_width < right) + return false; + + for (int32_t y = top; y < bottom; y++) { + int32_t offset = y * m_rowSize; + for (int32_t x = left; x < right; x++) + m_bits[offset + (x >> 5)] |= 1 << (x & 0x1f); + } + return true; +} + +void CBC_CommonBitMatrix::SetRow(int32_t y, CBC_CommonBitArray* row) { + int32_t l = y * m_rowSize; + for (int32_t i = 0; i < m_rowSize; i++) { + m_bits[l] = row->GetBitArray()[i]; + l++; + } +} + +void CBC_CommonBitMatrix::SetCol(int32_t y, CBC_CommonBitArray* col) { + for (size_t i = 0; i < col->GetBits().size(); ++i) + m_bits[i * m_rowSize + y] = col->GetBitArray()[i]; +} diff --git a/fxbarcode/common/BC_CommonBitMatrix.h b/fxbarcode/common/BC_CommonBitMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..67c0f888cc4ac91db8488be5223124b0d672479b --- /dev/null +++ b/fxbarcode/common/BC_CommonBitMatrix.h @@ -0,0 +1,43 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_COMMON_BC_COMMONBITMATRIX_H_ +#define FXBARCODE_COMMON_BC_COMMONBITMATRIX_H_ + +#include + +#include "core/fxcrt/fx_system.h" + +class CBC_CommonBitArray; + +class CBC_CommonBitMatrix { + public: + CBC_CommonBitMatrix(); + ~CBC_CommonBitMatrix(); + + void Init(int32_t dimension); + void Init(int32_t width, int32_t height); + + bool Get(int32_t x, int32_t y) const; + void Set(int32_t x, int32_t y); + void Flip(int32_t x, int32_t y); + void Clear(); + bool SetRegion(int32_t left, int32_t top, int32_t width, int32_t height); + void SetRow(int32_t y, CBC_CommonBitArray* row); + CBC_CommonBitArray* GetCol(int32_t y, CBC_CommonBitArray* row); + void SetCol(int32_t y, CBC_CommonBitArray* col); + int32_t GetWidth() const { return m_width; } + int32_t GetHeight() const { return m_height; } + int32_t* GetBits() const { return m_bits; } + + private: + int32_t m_width = 0; + int32_t m_height = 0; + int32_t m_rowSize = 0; + int32_t* m_bits = nullptr; +}; + +#endif // FXBARCODE_COMMON_BC_COMMONBITMATRIX_H_ diff --git a/xfa/fxbarcode/common/BC_CommonByteArray.cpp b/fxbarcode/common/BC_CommonByteArray.cpp similarity index 82% rename from xfa/fxbarcode/common/BC_CommonByteArray.cpp rename to fxbarcode/common/BC_CommonByteArray.cpp index 050ecb0bf8442569774573e86afe93a472834655..d66568c59637d96bc5d1a77ca5b216432310f734 100644 --- a/xfa/fxbarcode/common/BC_CommonByteArray.cpp +++ b/fxbarcode/common/BC_CommonByteArray.cpp @@ -19,10 +19,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "fxbarcode/common/BC_CommonByteArray.h" #include -#include "xfa/fxbarcode/common/BC_CommonByteArray.h" +#include "core/fxcrt/fx_memory.h" CBC_CommonByteArray::CBC_CommonByteArray() { m_bytes = nullptr; @@ -32,13 +33,13 @@ CBC_CommonByteArray::CBC_CommonByteArray() { CBC_CommonByteArray::CBC_CommonByteArray(int32_t size) { m_size = size; m_bytes = FX_Alloc(uint8_t, size); - FXSYS_memset(m_bytes, 0, size); + memset(m_bytes, 0, size); m_index = 0; } CBC_CommonByteArray::CBC_CommonByteArray(uint8_t* byteArray, int32_t size) { m_size = size; m_bytes = FX_Alloc(uint8_t, size); - FXSYS_memcpy(m_bytes, byteArray, size); + memcpy(m_bytes, byteArray, size); m_index = size; } CBC_CommonByteArray::~CBC_CommonByteArray() { @@ -68,24 +69,26 @@ void CBC_CommonByteArray::Reserve(int32_t capacity) { if (!m_bytes || m_size < capacity) { uint8_t* newArray = FX_Alloc(uint8_t, capacity); if (m_bytes) { - FXSYS_memcpy(newArray, m_bytes, m_size); - FXSYS_memset(newArray + m_size, 0, capacity - m_size); + memcpy(newArray, m_bytes, m_size); + memset(newArray + m_size, 0, capacity - m_size); } else { - FXSYS_memset(newArray, 0, capacity); + memset(newArray, 0, capacity); } FX_Free(m_bytes); m_bytes = newArray; m_size = capacity; } } -void CBC_CommonByteArray::Set(uint8_t* source, int32_t offset, int32_t count) { +void CBC_CommonByteArray::Set(const uint8_t* source, + int32_t offset, + int32_t count) { FX_Free(m_bytes); m_bytes = FX_Alloc(uint8_t, count); m_size = count; - FXSYS_memcpy(m_bytes, source + offset, count); + memcpy(m_bytes, source + offset, count); m_index = count; } -void CBC_CommonByteArray::Set(CFX_ArrayTemplate* source, +void CBC_CommonByteArray::Set(std::vector* source, int32_t offset, int32_t count) { FX_Free(m_bytes); diff --git a/fxbarcode/common/BC_CommonByteArray.h b/fxbarcode/common/BC_CommonByteArray.h new file mode 100644 index 0000000000000000000000000000000000000000..285a567c8effc40ef7a11086d90b42b495976a87 --- /dev/null +++ b/fxbarcode/common/BC_CommonByteArray.h @@ -0,0 +1,38 @@ +// 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 FXBARCODE_COMMON_BC_COMMONBYTEARRAY_H_ +#define FXBARCODE_COMMON_BC_COMMONBYTEARRAY_H_ + +#include + +#include + +// TODO(weili): The usage of this class should be replaced by +// std::vector. +class CBC_CommonByteArray { + public: + CBC_CommonByteArray(); + explicit CBC_CommonByteArray(int32_t size); + CBC_CommonByteArray(uint8_t* byteArray, int32_t size); + virtual ~CBC_CommonByteArray(); + + int32_t At(int32_t index) const; + int32_t Size() const; + bool IsEmpty() const; + void Set(int32_t index, int32_t value); + void AppendByte(int32_t value); + void Reserve(int32_t capacity); + void Set(const uint8_t* source, int32_t offset, int32_t count); + void Set(std::vector* source, int32_t offset, int32_t count); + + private: + int32_t m_size; + int32_t m_index; + uint8_t* m_bytes; +}; + +#endif // FXBARCODE_COMMON_BC_COMMONBYTEARRAY_H_ diff --git a/xfa/fxbarcode/common/BC_CommonByteMatrix.cpp b/fxbarcode/common/BC_CommonByteMatrix.cpp similarity index 94% rename from xfa/fxbarcode/common/BC_CommonByteMatrix.cpp rename to fxbarcode/common/BC_CommonByteMatrix.cpp index 0e7ce80e29c477c2d406ee6a35a0242c35494903..2ab1e9ac506030cdab762cae7bf637f768ab286f 100644 --- a/xfa/fxbarcode/common/BC_CommonByteMatrix.cpp +++ b/fxbarcode/common/BC_CommonByteMatrix.cpp @@ -21,7 +21,7 @@ */ #include "core/fxcrt/fx_memory.h" -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" CBC_CommonByteMatrix::CBC_CommonByteMatrix(int32_t width, int32_t height) { m_height = height; @@ -30,7 +30,7 @@ CBC_CommonByteMatrix::CBC_CommonByteMatrix(int32_t width, int32_t height) { } void CBC_CommonByteMatrix::Init() { m_bytes = FX_Alloc2D(uint8_t, m_height, m_width); - FXSYS_memset(m_bytes, 0xff, m_height * m_width); + memset(m_bytes, 0xff, m_height * m_width); } CBC_CommonByteMatrix::~CBC_CommonByteMatrix() { FX_Free(m_bytes); diff --git a/xfa/fxbarcode/common/BC_CommonByteMatrix.h b/fxbarcode/common/BC_CommonByteMatrix.h similarity index 82% rename from xfa/fxbarcode/common/BC_CommonByteMatrix.h rename to fxbarcode/common/BC_CommonByteMatrix.h index 13cf5c330e74e6120e97a1797d6f9670899f26a3..9f13a376d10a4e5ab070d3b717eed8fe4fc25f87 100644 --- a/xfa/fxbarcode/common/BC_CommonByteMatrix.h +++ b/fxbarcode/common/BC_CommonByteMatrix.h @@ -4,8 +4,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_COMMON_BC_COMMONBYTEMATRIX_H_ -#define XFA_FXBARCODE_COMMON_BC_COMMONBYTEMATRIX_H_ +#ifndef FXBARCODE_COMMON_BC_COMMONBYTEMATRIX_H_ +#define FXBARCODE_COMMON_BC_COMMONBYTEMATRIX_H_ #include @@ -32,4 +32,4 @@ class CBC_CommonByteMatrix { int32_t m_height; }; -#endif // XFA_FXBARCODE_COMMON_BC_COMMONBYTEMATRIX_H_ +#endif // FXBARCODE_COMMON_BC_COMMONBYTEMATRIX_H_ diff --git a/fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp b/fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2be74c7fa3fc730e9c66394a0baaa1defb488ad4 --- /dev/null +++ b/fxbarcode/common/reedsolomon/BC_ReedSolomon.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 +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/reedsolomon/BC_ReedSolomon.h" + +#include +#include + +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h" +#include "third_party/base/ptr_util.h" + +CBC_ReedSolomonEncoder::CBC_ReedSolomonEncoder(CBC_ReedSolomonGF256* field) + : m_field(field) {} + +CBC_ReedSolomonEncoder::~CBC_ReedSolomonEncoder() {} + +void CBC_ReedSolomonEncoder::Init() { + m_cachedGenerators.push_back( + pdfium::MakeUnique(m_field.Get(), 1)); +} + +CBC_ReedSolomonGF256Poly* CBC_ReedSolomonEncoder::BuildGenerator( + size_t degree) { + if (degree >= m_cachedGenerators.size()) { + CBC_ReedSolomonGF256Poly* lastGenerator = m_cachedGenerators.back().get(); + for (size_t d = m_cachedGenerators.size(); d <= degree; ++d) { + std::vector temp = {1, m_field->Exp(d - 1)}; + CBC_ReedSolomonGF256Poly temp_poly; + if (!temp_poly.Init(m_field.Get(), &temp)) + return nullptr; + + auto nextGenerator = lastGenerator->Multiply(&temp_poly); + if (!nextGenerator) + return nullptr; + + lastGenerator = nextGenerator.get(); + m_cachedGenerators.push_back(std::move(nextGenerator)); + } + } + return m_cachedGenerators[degree].get(); +} + +bool CBC_ReedSolomonEncoder::Encode(std::vector* toEncode, + size_t ecBytes) { + if (ecBytes == 0) + return false; + + if (toEncode->size() <= ecBytes) + return false; + + CBC_ReedSolomonGF256Poly* generator = BuildGenerator(ecBytes); + if (!generator) + return false; + + size_t dataBytes = toEncode->size() - ecBytes; + std::vector infoCoefficients(dataBytes); + for (size_t x = 0; x < dataBytes; x++) + infoCoefficients[x] = (*toEncode)[x]; + + CBC_ReedSolomonGF256Poly info; + if (!info.Init(m_field.Get(), &infoCoefficients)) + return false; + + auto infoTemp = info.MultiplyByMonomial(ecBytes, 1); + if (!infoTemp) + return false; + + auto remainder = infoTemp->Divide(generator); + if (!remainder) + return false; + + const auto& coefficients = remainder->GetCoefficients(); + size_t numZeroCoefficients = + ecBytes > coefficients.size() ? ecBytes - coefficients.size() : 0; + for (size_t i = 0; i < numZeroCoefficients; i++) + (*toEncode)[dataBytes + i] = 0; + for (size_t y = 0; y < coefficients.size(); y++) + (*toEncode)[dataBytes + numZeroCoefficients + y] = coefficients[y]; + return true; +} diff --git a/fxbarcode/common/reedsolomon/BC_ReedSolomon.h b/fxbarcode/common/reedsolomon/BC_ReedSolomon.h new file mode 100644 index 0000000000000000000000000000000000000000..e45c8a49762912504adddc5b02e9237833792719 --- /dev/null +++ b/fxbarcode/common/reedsolomon/BC_ReedSolomon.h @@ -0,0 +1,33 @@ +// 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 FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMON_H_ +#define FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMON_H_ + +#include +#include + +#include "core/fxcrt/unowned_ptr.h" + +class CBC_ReedSolomonGF256; +class CBC_ReedSolomonGF256Poly; + +class CBC_ReedSolomonEncoder { + public: + explicit CBC_ReedSolomonEncoder(CBC_ReedSolomonGF256* field); + ~CBC_ReedSolomonEncoder(); + + void Init(); + bool Encode(std::vector* toEncode, size_t ecBytes); + + private: + CBC_ReedSolomonGF256Poly* BuildGenerator(size_t degree); + + UnownedPtr const m_field; + std::vector> m_cachedGenerators; +}; + +#endif // FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMON_H_ diff --git a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp similarity index 85% rename from xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp rename to fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp index ce84d8e08d098a41332b84ff01944c99fd0ebb29..3f761054c4caab37f5aa01cb3d019b3c09ea4374 100644 --- a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp +++ b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.cpp @@ -20,10 +20,12 @@ * limitations under the License. */ -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include + +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h" #include "third_party/base/ptr_util.h" -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h" CBC_ReedSolomonGF256* CBC_ReedSolomonGF256::QRCodeField = nullptr; CBC_ReedSolomonGF256* CBC_ReedSolomonGF256::DataMatrixField = nullptr; @@ -72,7 +74,7 @@ CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256::GetOne() const { return m_one.get(); } -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256::BuildMonomial( +std::unique_ptr CBC_ReedSolomonGF256::BuildMonomial( int32_t degree, int32_t coefficient, int32_t& e) { @@ -81,18 +83,18 @@ CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256::BuildMonomial( return nullptr; } if (coefficient == 0) { - CBC_ReedSolomonGF256Poly* temp = m_zero->Clone(e); - if (e != BCExceptionNO) - return nullptr; + auto temp = m_zero->Clone(); + if (!temp) + e = BCExceptionGeneric; return temp; } - CFX_ArrayTemplate coefficients; - coefficients.SetSize(degree + 1); + std::vector coefficients(degree + 1); coefficients[0] = coefficient; - CBC_ReedSolomonGF256Poly* temp = new CBC_ReedSolomonGF256Poly(); - temp->Init(this, &coefficients, e); - if (e != BCExceptionNO) + auto temp = pdfium::MakeUnique(); + if (!temp->Init(this, &coefficients)) { + e = BCExceptionGeneric; return nullptr; + } return temp; } diff --git a/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h new file mode 100644 index 0000000000000000000000000000000000000000..693d943042bbf58fe272b1d355adfdc69b22af62 --- /dev/null +++ b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h @@ -0,0 +1,46 @@ +// 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 FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256_H_ +#define FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256_H_ + +#include + +#include "fxbarcode/utils.h" + +class CBC_ReedSolomonGF256Poly; + +class CBC_ReedSolomonGF256 { + public: + explicit CBC_ReedSolomonGF256(int32_t primitive); + ~CBC_ReedSolomonGF256(); + + static void Initialize(); + static void Finalize(); + + CBC_ReedSolomonGF256Poly* GetZero() const; + CBC_ReedSolomonGF256Poly* GetOne() const; + std::unique_ptr BuildMonomial(int32_t degree, + int32_t coefficient, + int32_t& e); + static int32_t AddOrSubtract(int32_t a, int32_t b); + int32_t Exp(int32_t a); + int32_t Log(int32_t a, int32_t& e); + int32_t Inverse(int32_t a, int32_t& e); + int32_t Multiply(int32_t a, int32_t b); + void Init(); + + static CBC_ReedSolomonGF256* QRCodeField; + static CBC_ReedSolomonGF256* DataMatrixField; + + private: + int32_t m_expTable[256]; + int32_t m_logTable[256]; + std::unique_ptr m_zero; + std::unique_ptr m_one; +}; + +#endif // FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256_H_ diff --git a/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef83691d4f609a2a57ac715cef35798d754c8ca7 --- /dev/null +++ b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp @@ -0,0 +1,240 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h" + +#include +#include + +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CBC_ReedSolomonGF256Poly::CBC_ReedSolomonGF256Poly(CBC_ReedSolomonGF256* field, + int32_t coefficients) { + if (!field) + return; + + m_field = field; + m_coefficients.push_back(coefficients); +} + +CBC_ReedSolomonGF256Poly::CBC_ReedSolomonGF256Poly() { + m_field = nullptr; +} + +bool CBC_ReedSolomonGF256Poly::Init(CBC_ReedSolomonGF256* field, + const std::vector* coefficients) { + if (!coefficients || coefficients->empty()) + return false; + + m_field = field; + size_t coefficientsLength = coefficients->size(); + if (coefficientsLength > 1 && coefficients->front() == 0) { + size_t firstNonZero = 1; + while (firstNonZero < coefficientsLength && + (*coefficients)[firstNonZero] == 0) { + firstNonZero++; + } + if (firstNonZero == coefficientsLength) { + m_coefficients = m_field->GetZero()->GetCoefficients(); + } else { + m_coefficients.resize(coefficientsLength - firstNonZero); + for (size_t i = firstNonZero, j = 0; i < coefficientsLength; i++, j++) + m_coefficients[j] = (*coefficients)[i]; + } + } else { + m_coefficients = *coefficients; + } + return true; +} + +const std::vector& CBC_ReedSolomonGF256Poly::GetCoefficients() const { + return m_coefficients; +} + +int32_t CBC_ReedSolomonGF256Poly::GetDegree() const { + return pdfium::CollectionSize(m_coefficients) - 1; +} + +bool CBC_ReedSolomonGF256Poly::IsZero() const { + return m_coefficients.front() == 0; +} + +int32_t CBC_ReedSolomonGF256Poly::GetCoefficients(int32_t degree) const { + return m_coefficients[m_coefficients.size() - 1 - degree]; +} + +int32_t CBC_ReedSolomonGF256Poly::EvaluateAt(int32_t a) { + if (a == 0) + return GetCoefficients(0); + + size_t size = m_coefficients.size(); + if (a == 1) { + int32_t result = 0; + for (size_t i = 0; i < size; i++) + result = CBC_ReedSolomonGF256::AddOrSubtract(result, m_coefficients[i]); + return result; + } + int32_t result = m_coefficients[0]; + for (size_t j = 1; j < size; j++) { + result = CBC_ReedSolomonGF256::AddOrSubtract(m_field->Multiply(a, result), + m_coefficients[j]); + } + return result; +} + +std::unique_ptr CBC_ReedSolomonGF256Poly::Clone() + const { + auto temp = pdfium::MakeUnique(); + if (!temp->Init(m_field.Get(), &m_coefficients)) + return nullptr; + return temp; +} + +std::unique_ptr +CBC_ReedSolomonGF256Poly::AddOrSubtract(const CBC_ReedSolomonGF256Poly* other) { + if (IsZero()) + return other->Clone(); + if (other->IsZero()) + return Clone(); + + std::vector smallerCoefficients = m_coefficients; + std::vector largerCoefficients = other->GetCoefficients(); + if (smallerCoefficients.size() > largerCoefficients.size()) + std::swap(smallerCoefficients, largerCoefficients); + + std::vector sumDiff(largerCoefficients.size()); + size_t lengthDiff = largerCoefficients.size() - smallerCoefficients.size(); + for (size_t i = 0; i < lengthDiff; i++) + sumDiff[i] = largerCoefficients[i]; + + for (size_t j = lengthDiff; j < largerCoefficients.size(); j++) { + sumDiff[j] = CBC_ReedSolomonGF256::AddOrSubtract( + smallerCoefficients[j - lengthDiff], largerCoefficients[j]); + } + auto temp = pdfium::MakeUnique(); + if (!temp->Init(m_field.Get(), &sumDiff)) + return nullptr; + return temp; +} + +std::unique_ptr CBC_ReedSolomonGF256Poly::Multiply( + const CBC_ReedSolomonGF256Poly* other) { + if (IsZero() || other->IsZero()) + return m_field->GetZero()->Clone(); + + const std::vector& aCoefficients = m_coefficients; + const std::vector& bCoefficients = other->GetCoefficients(); + size_t aLength = aCoefficients.size(); + size_t bLength = bCoefficients.size(); + std::vector product(aLength + bLength - 1); + for (size_t i = 0; i < aLength; i++) { + int32_t aCoeff = aCoefficients[i]; + for (size_t j = 0; j < bLength; j++) { + product[i + j] = CBC_ReedSolomonGF256::AddOrSubtract( + product[i + j], m_field->Multiply(aCoeff, bCoefficients[j])); + } + } + auto temp = pdfium::MakeUnique(); + if (!temp->Init(m_field.Get(), &product)) + return nullptr; + return temp; +} + +std::unique_ptr CBC_ReedSolomonGF256Poly::Multiply( + int32_t scalar) { + if (scalar == 0) + return m_field->GetZero()->Clone(); + if (scalar == 1) + return Clone(); + + size_t size = m_coefficients.size(); + std::vector product(size); + for (size_t i = 0; i < size; i++) + product[i] = m_field->Multiply(m_coefficients[i], scalar); + + auto temp = pdfium::MakeUnique(); + if (!temp->Init(m_field.Get(), &product)) + return nullptr; + return temp; +} + +std::unique_ptr +CBC_ReedSolomonGF256Poly::MultiplyByMonomial(int32_t degree, + int32_t coefficient) const { + if (degree < 0) + return nullptr; + if (coefficient == 0) + return m_field->GetZero()->Clone(); + + size_t size = m_coefficients.size(); + std::vector product(size + degree); + for (size_t i = 0; i < size; i++) + product[i] = m_field->Multiply(m_coefficients[i], coefficient); + + auto temp = pdfium::MakeUnique(); + if (!temp->Init(m_field.Get(), &product)) + return nullptr; + return temp; +} + +std::unique_ptr CBC_ReedSolomonGF256Poly::Divide( + const CBC_ReedSolomonGF256Poly* other) { + if (other->IsZero()) + return nullptr; + + auto quotient = m_field->GetZero()->Clone(); + if (!quotient) + return nullptr; + auto remainder = Clone(); + if (!remainder) + return nullptr; + + int e = BCExceptionNO; + int32_t denominatorLeadingTerm = other->GetCoefficients(other->GetDegree()); + int32_t inverseDenominatorLeadingTeam = + m_field->Inverse(denominatorLeadingTerm, e); + if (e != BCExceptionNO) + return nullptr; + while (remainder->GetDegree() >= other->GetDegree() && !remainder->IsZero()) { + int32_t degreeDifference = remainder->GetDegree() - other->GetDegree(); + int32_t scale = + m_field->Multiply(remainder->GetCoefficients((remainder->GetDegree())), + inverseDenominatorLeadingTeam); + auto term = other->MultiplyByMonomial(degreeDifference, scale); + if (!term) + return nullptr; + auto iteratorQuotient = m_field->BuildMonomial(degreeDifference, scale, e); + if (e != BCExceptionNO) + return nullptr; + quotient = quotient->AddOrSubtract(iteratorQuotient.get()); + if (!quotient) + return nullptr; + remainder = remainder->AddOrSubtract(term.get()); + if (!remainder) + return nullptr; + } + return remainder; +} + +CBC_ReedSolomonGF256Poly::~CBC_ReedSolomonGF256Poly() {} diff --git a/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h new file mode 100644 index 0000000000000000000000000000000000000000..810b4782bb07a9c66dea08fc4442fc3ae1490803 --- /dev/null +++ b/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256POLY_H_ +#define FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256POLY_H_ + +#include +#include + +#include "core/fxcrt/unowned_ptr.h" + +class CBC_ReedSolomonGF256; + +class CBC_ReedSolomonGF256Poly final { + public: + CBC_ReedSolomonGF256Poly(CBC_ReedSolomonGF256* field, int32_t coefficients); + CBC_ReedSolomonGF256Poly(); + ~CBC_ReedSolomonGF256Poly(); + bool Init(CBC_ReedSolomonGF256* field, + const std::vector* coefficients); + + int32_t GetCoefficients(int32_t degree) const; + const std::vector& GetCoefficients() const; + int32_t GetDegree() const; + bool IsZero() const; + int32_t EvaluateAt(int32_t a); + std::unique_ptr AddOrSubtract( + const CBC_ReedSolomonGF256Poly* other); + std::unique_ptr Multiply( + const CBC_ReedSolomonGF256Poly* other); + std::unique_ptr Multiply(int32_t scalar); + std::unique_ptr MultiplyByMonomial( + int32_t degree, + int32_t coefficient) const; + std::unique_ptr Divide( + const CBC_ReedSolomonGF256Poly* other); + std::unique_ptr Clone() const; + + private: + UnownedPtr m_field; + std::vector m_coefficients; +}; + +#endif // FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256POLY_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp b/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp similarity index 76% rename from xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp rename to fxbarcode/datamatrix/BC_ASCIIEncoder.cpp index 00d8fc1615739c9f0a52b9686c0ae716fc511cc8..e6b7a2b35be913f02e15eb74f66324828ea9da0a 100644 --- a/xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp +++ b/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp @@ -20,13 +20,13 @@ * limitations under the License. */ -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" +#include "fxbarcode/datamatrix/BC_ASCIIEncoder.h" + +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" CBC_ASCIIEncoder::CBC_ASCIIEncoder() {} CBC_ASCIIEncoder::~CBC_ASCIIEncoder() {} @@ -37,16 +37,15 @@ void CBC_ASCIIEncoder::Encode(CBC_EncoderContext& context, int32_t& e) { int32_t n = CBC_HighLevelEncoder::determineConsecutiveDigitCount( context.m_msg, context.m_pos); if (n >= 2) { - FX_WCHAR code = - encodeASCIIDigits(context.m_msg.GetAt(context.m_pos), - context.m_msg.GetAt(context.m_pos + 1), e); + wchar_t code = encodeASCIIDigits(context.m_msg[context.m_pos], + context.m_msg[context.m_pos + 1], e); if (e != BCExceptionNO) { return; } context.writeCodeword(code); context.m_pos += 2; } else { - FX_WCHAR c = context.getCurrentChar(); + wchar_t c = context.getCurrentChar(); int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( context.m_msg, context.m_pos, getEncodingMode()); if (newMode != getEncodingMode()) { @@ -77,21 +76,21 @@ void CBC_ASCIIEncoder::Encode(CBC_EncoderContext& context, int32_t& e) { } } else if (CBC_HighLevelEncoder::isExtendedASCII(c)) { context.writeCodeword(CBC_HighLevelEncoder::UPPER_SHIFT); - context.writeCodeword((FX_WCHAR)(c - 128 + 1)); + context.writeCodeword((wchar_t)(c - 128 + 1)); context.m_pos++; } else { - context.writeCodeword((FX_WCHAR)(c + 1)); + context.writeCodeword((wchar_t)(c + 1)); context.m_pos++; } } } -FX_WCHAR CBC_ASCIIEncoder::encodeASCIIDigits(FX_WCHAR digit1, - FX_WCHAR digit2, - int32_t& e) { +wchar_t CBC_ASCIIEncoder::encodeASCIIDigits(wchar_t digit1, + wchar_t digit2, + int32_t& e) { if (CBC_HighLevelEncoder::isDigit(digit1) && CBC_HighLevelEncoder::isDigit(digit2)) { int32_t num = (digit1 - 48) * 10 + (digit2 - 48); - return (FX_WCHAR)(num + 130); + return (wchar_t)(num + 130); } e = BCExceptionIllegalArgumentNotGigits; return 0; diff --git a/fxbarcode/datamatrix/BC_ASCIIEncoder.h b/fxbarcode/datamatrix/BC_ASCIIEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..6eb3a50669da874a6298ad2be4b2ba8f37be3c7b --- /dev/null +++ b/fxbarcode/datamatrix/BC_ASCIIEncoder.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 FXBARCODE_DATAMATRIX_BC_ASCIIENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_ASCIIENCODER_H_ + +#include "fxbarcode/datamatrix/BC_Encoder.h" + +class CBC_EncoderContext; + +class CBC_ASCIIEncoder : public CBC_Encoder { + public: + CBC_ASCIIEncoder(); + ~CBC_ASCIIEncoder() override; + + // CBC_Encoder + int32_t getEncodingMode() override; + void Encode(CBC_EncoderContext& context, int32_t& e) override; + + private: + static wchar_t encodeASCIIDigits(wchar_t digit1, wchar_t digit2, int32_t& e); +}; + +#endif // FXBARCODE_DATAMATRIX_BC_ASCIIENCODER_H_ diff --git a/fxbarcode/datamatrix/BC_Base256Encoder.cpp b/fxbarcode/datamatrix/BC_Base256Encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7dd69c0f75474930af3ec04e35cace326633e09 --- /dev/null +++ b/fxbarcode/datamatrix/BC_Base256Encoder.cpp @@ -0,0 +1,86 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_Base256Encoder.h" + +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" + +CBC_Base256Encoder::CBC_Base256Encoder() {} +CBC_Base256Encoder::~CBC_Base256Encoder() {} +int32_t CBC_Base256Encoder::getEncodingMode() { + return BASE256_ENCODATION; +} +void CBC_Base256Encoder::Encode(CBC_EncoderContext& context, int32_t& e) { + WideString buffer; + buffer += L'\0'; + while (context.hasMoreCharacters()) { + wchar_t c = context.getCurrentChar(); + buffer += c; + context.m_pos++; + int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( + context.m_msg, context.m_pos, getEncodingMode()); + if (newMode != getEncodingMode()) { + context.signalEncoderChange(newMode); + break; + } + } + int32_t dataCount = buffer.GetLength() - 1; + char buf[128]; + FXSYS_itoa(dataCount, buf, 10); + buffer.SetAt(0, static_cast(*buf) - '0'); + int32_t lengthFieldSize = 1; + int32_t currentSize = + context.getCodewordCount() + dataCount + lengthFieldSize; + context.updateSymbolInfo(currentSize, e); + if (e != BCExceptionNO) { + return; + } + bool mustPad = (context.m_symbolInfo->dataCapacity() - currentSize) > 0; + if (context.hasMoreCharacters() || mustPad) { + if (dataCount <= 249) { + buffer.SetAt(0, static_cast(dataCount)); + } else if (dataCount > 249 && dataCount <= 1555) { + buffer.SetAt(0, static_cast((dataCount / 250) + 249)); + buffer.Insert(1, static_cast(dataCount % 250)); + } else { + e = BCExceptionIllegalStateMessageLengthInvalid; + return; + } + } + for (const auto& c : buffer) { + context.writeCodeword(randomize255State(c, context.getCodewordCount() + 1)); + } +} +wchar_t CBC_Base256Encoder::randomize255State(wchar_t ch, + int32_t codewordPosition) { + int32_t pseudoRandom = ((149 * codewordPosition) % 255) + 1; + int32_t tempVariable = ch + pseudoRandom; + if (tempVariable <= 255) { + return static_cast(tempVariable); + } else { + return static_cast(tempVariable - 256); + } +} diff --git a/fxbarcode/datamatrix/BC_Base256Encoder.h b/fxbarcode/datamatrix/BC_Base256Encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..65abf5966239b3a1d05e94d90b45f8db7ac544d5 --- /dev/null +++ b/fxbarcode/datamatrix/BC_Base256Encoder.h @@ -0,0 +1,25 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_DATAMATRIX_BC_BASE256ENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_BASE256ENCODER_H_ + +#include "fxbarcode/datamatrix/BC_Encoder.h" + +class CBC_Base256Encoder : public CBC_Encoder { + public: + CBC_Base256Encoder(); + ~CBC_Base256Encoder() override; + + // CBC_Encoder + int32_t getEncodingMode() override; + void Encode(CBC_EncoderContext& context, int32_t& e) override; + + private: + static wchar_t randomize255State(wchar_t ch, int32_t codewordPosition); +}; + +#endif // FXBARCODE_DATAMATRIX_BC_BASE256ENCODER_H_ diff --git a/fxbarcode/datamatrix/BC_C40Encoder.cpp b/fxbarcode/datamatrix/BC_C40Encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb8b11cc508a500ec644ee9069e4b420a297dff1 --- /dev/null +++ b/fxbarcode/datamatrix/BC_C40Encoder.cpp @@ -0,0 +1,211 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_C40Encoder.h" + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" + +namespace { + +WideString EncodeToC40Codewords(const WideString& sb, int32_t startPos) { + wchar_t c1 = sb[startPos]; + wchar_t c2 = sb[startPos + 1]; + wchar_t c3 = sb[startPos + 2]; + int32_t v = (1600 * c1) + (40 * c2) + c3 + 1; + wchar_t cw[2]; + cw[0] = static_cast(v / 256); + cw[1] = static_cast(v % 256); + return WideString(cw, FX_ArraySize(cw)); +} + +} // namespace + +CBC_C40Encoder::CBC_C40Encoder() {} +CBC_C40Encoder::~CBC_C40Encoder() {} +int32_t CBC_C40Encoder::getEncodingMode() { + return C40_ENCODATION; +} +void CBC_C40Encoder::Encode(CBC_EncoderContext& context, int32_t& e) { + WideString buffer; + while (context.hasMoreCharacters()) { + wchar_t c = context.getCurrentChar(); + context.m_pos++; + int32_t lastCharSize = encodeChar(c, buffer, e); + if (e != BCExceptionNO) { + return; + } + int32_t unwritten = (buffer.GetLength() / 3) * 2; + int32_t curCodewordCount = context.getCodewordCount() + unwritten; + context.updateSymbolInfo(curCodewordCount, e); + if (e != BCExceptionNO) { + return; + } + int32_t available = context.m_symbolInfo->dataCapacity() - curCodewordCount; + if (!context.hasMoreCharacters()) { + if ((buffer.GetLength() % 3) == 2) { + if (available < 2 || available > 2) { + lastCharSize = BacktrackOneCharacter(&context, &buffer, lastCharSize); + if (lastCharSize < 0) { + e = BCExceptionGeneric; + return; + } + } + } + while ((buffer.GetLength() % 3) == 1 && + ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) { + lastCharSize = BacktrackOneCharacter(&context, &buffer, lastCharSize); + if (lastCharSize < 0) { + e = BCExceptionGeneric; + return; + } + } + break; + } + int32_t count = buffer.GetLength(); + if ((count % 3) == 0) { + int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( + context.m_msg, context.m_pos, getEncodingMode()); + if (newMode != getEncodingMode()) { + context.signalEncoderChange(newMode); + break; + } + } + } + handleEOD(context, buffer, e); +} +void CBC_C40Encoder::writeNextTriplet(CBC_EncoderContext& context, + WideString& buffer) { + context.writeCodewords(EncodeToC40Codewords(buffer, 0)); + buffer.Delete(0, 3); +} +void CBC_C40Encoder::handleEOD(CBC_EncoderContext& context, + WideString& buffer, + int32_t& e) { + int32_t unwritten = (buffer.GetLength() / 3) * 2; + int32_t rest = buffer.GetLength() % 3; + int32_t curCodewordCount = context.getCodewordCount() + unwritten; + context.updateSymbolInfo(curCodewordCount, e); + if (e != BCExceptionNO) { + return; + } + int32_t available = context.m_symbolInfo->dataCapacity() - curCodewordCount; + if (rest == 2) { + buffer += (wchar_t)'\0'; + while (buffer.GetLength() >= 3) { + writeNextTriplet(context, buffer); + } + if (context.hasMoreCharacters()) { + context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH); + } + } else if (available == 1 && rest == 1) { + while (buffer.GetLength() >= 3) { + writeNextTriplet(context, buffer); + } + if (context.hasMoreCharacters()) { + context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH); + } + context.m_pos--; + } else if (rest == 0) { + while (buffer.GetLength() >= 3) { + writeNextTriplet(context, buffer); + } + if (available > 0 || context.hasMoreCharacters()) { + context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH); + } + } else { + e = BCExceptionIllegalStateUnexpectedCase; + return; + } + context.signalEncoderChange(ASCII_ENCODATION); +} +int32_t CBC_C40Encoder::encodeChar(wchar_t c, WideString& sb, int32_t& e) { + if (c == ' ') { + sb += (wchar_t)'\3'; + return 1; + } else if ((c >= '0') && (c <= '9')) { + sb += (wchar_t)(c - 48 + 4); + return 1; + } else if ((c >= 'A') && (c <= 'Z')) { + sb += (wchar_t)(c - 65 + 14); + return 1; + } else if (c <= 0x1f) { + sb += (wchar_t)'\0'; + sb += c; + return 2; + } else if ((c >= '!') && (c <= '/')) { + sb += (wchar_t)'\1'; + sb += (wchar_t)(c - 33); + return 2; + } else if ((c >= ':') && (c <= '@')) { + sb += (wchar_t)'\1'; + sb += (wchar_t)(c - 58 + 15); + return 2; + } else if ((c >= '[') && (c <= '_')) { + sb += (wchar_t)'\1'; + sb += (wchar_t)(c - 91 + 22); + return 2; + } else if ((c >= 60) && (c <= 0x7f)) { + sb += (wchar_t)'\2'; + sb += (wchar_t)(c - 96); + return 2; + } else if (c >= 80) { + sb += (wchar_t)'\1'; + sb += (wchar_t)0x001e; + int32_t len = 2; + len += encodeChar((c - 128), sb, e); + if (e != BCExceptionNO) + return 0; + return len; + } else { + e = BCExceptionIllegalArgument; + return 0; + } +} + +int32_t CBC_C40Encoder::BacktrackOneCharacter(CBC_EncoderContext* context, + WideString* buffer, + int32_t lastCharSize) { + if (context->m_pos < 1) + return -1; + + int32_t count = buffer->GetLength(); + if (count < lastCharSize) + return -1; + + buffer->Delete(count - lastCharSize, lastCharSize); + context->m_pos--; + wchar_t c = context->getCurrentChar(); + int32_t e = BCExceptionNO; + WideString removed; + int32_t len = encodeChar(c, removed, e); + if (e != BCExceptionNO) + return -1; + + ASSERT(len > 0); + context->resetSymbolInfo(); + return len; +} diff --git a/fxbarcode/datamatrix/BC_C40Encoder.h b/fxbarcode/datamatrix/BC_C40Encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..5ddad92009d7bab38fbfb3edb75796bfa918cce5 --- /dev/null +++ b/fxbarcode/datamatrix/BC_C40Encoder.h @@ -0,0 +1,39 @@ +// 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 FXBARCODE_DATAMATRIX_BC_C40ENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_C40ENCODER_H_ + +#include "core/fxcrt/widestring.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" + +class CBC_C40Encoder : public CBC_Encoder { + public: + CBC_C40Encoder(); + ~CBC_C40Encoder() override; + + // CBC_Encoder + int32_t getEncodingMode() override; + void Encode(CBC_EncoderContext& context, int32_t& e) override; + + static void writeNextTriplet(CBC_EncoderContext& context, WideString& buffer); + + virtual void handleEOD(CBC_EncoderContext& context, + WideString& buffer, + int32_t& e); + virtual int32_t encodeChar(wchar_t c, WideString& sb, int32_t& e); + + private: + // Moves back by 1 position in |context| and adjusts |buffer| accordingly + // using |lastCharSize|. Returns the length of the current character in + // |context| after adjusting the position. If the character cannot be encoded, + // return -1. + int32_t BacktrackOneCharacter(CBC_EncoderContext* context, + WideString* buffer, + int32_t lastCharSize); +}; + +#endif // FXBARCODE_DATAMATRIX_BC_C40ENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp b/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp similarity index 76% rename from xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp rename to fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp index e580bb583f7a3f6cb81c4250273b1794969e0f71..7a18d03839d5014f593af99a2f3fe73cf99f90d9 100644 --- a/xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp +++ b/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.cpp @@ -20,21 +20,20 @@ * limitations under the License. */ -#include "xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" +#include "fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" CBC_DataMatrixSymbolInfo144::CBC_DataMatrixSymbolInfo144() - : CBC_SymbolInfo(false, 1558, 620, 22, 22, 36) { - m_rsBlockData = -1; - m_rsBlockError = 62; -} + : CBC_SymbolInfo(1558, 620, 22, 22, 36, -1, 62) {} + CBC_DataMatrixSymbolInfo144::~CBC_DataMatrixSymbolInfo144() {} -int32_t CBC_DataMatrixSymbolInfo144::getInterleavedBlockCount() { + +int32_t CBC_DataMatrixSymbolInfo144::getInterleavedBlockCount() const { return 10; } + int32_t CBC_DataMatrixSymbolInfo144getDataLengthForInterleavedBlock( int32_t index) { - return (index <= 8) ? 156 : 155; + return index <= 8 ? 156 : 155; } diff --git a/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h b/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h new file mode 100644 index 0000000000000000000000000000000000000000..0a1c529bb2bc05b3d37d0f0819a55ffc7c0020b7 --- /dev/null +++ b/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h @@ -0,0 +1,20 @@ +// 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 FXBARCODE_DATAMATRIX_BC_DATAMATRIXSYMBOLINFO144_H_ +#define FXBARCODE_DATAMATRIX_BC_DATAMATRIXSYMBOLINFO144_H_ + +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" + +class CBC_DataMatrixSymbolInfo144 : public CBC_SymbolInfo { + public: + CBC_DataMatrixSymbolInfo144(); + ~CBC_DataMatrixSymbolInfo144() override; + + int32_t getInterleavedBlockCount() const override; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_DATAMATRIXSYMBOLINFO144_H_ diff --git a/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp b/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4f9ad34797947896feee5f7258de4c629c6ea98 --- /dev/null +++ b/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp @@ -0,0 +1,149 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_DataMatrixWriter.h" + +#include + +#include "fxbarcode/BC_TwoDimWriter.h" +#include "fxbarcode/BC_UtilCodingConvert.h" +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/datamatrix/BC_ASCIIEncoder.h" +#include "fxbarcode/datamatrix/BC_Base256Encoder.h" +#include "fxbarcode/datamatrix/BC_C40Encoder.h" +#include "fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h" +#include "fxbarcode/datamatrix/BC_DefaultPlacement.h" +#include "fxbarcode/datamatrix/BC_EdifactEncoder.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_ErrorCorrection.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/datamatrix/BC_TextEncoder.h" +#include "fxbarcode/datamatrix/BC_X12Encoder.h" +#include "third_party/base/ptr_util.h" + +namespace { + +std::unique_ptr encodeLowLevel( + CBC_DefaultPlacement* placement, + CBC_SymbolInfo* symbolInfo) { + int32_t symbolWidth = symbolInfo->getSymbolDataWidth(); + ASSERT(symbolWidth); + int32_t symbolHeight = symbolInfo->getSymbolDataHeight(); + ASSERT(symbolHeight); + int32_t width = symbolInfo->getSymbolWidth(); + ASSERT(width); + int32_t height = symbolInfo->getSymbolHeight(); + ASSERT(height); + + auto matrix = pdfium::MakeUnique(width, height); + matrix->Init(); + int32_t matrixY = 0; + for (int32_t y = 0; y < symbolHeight; y++) { + int32_t matrixX; + if ((y % symbolInfo->matrixHeight()) == 0) { + matrixX = 0; + for (int32_t x = 0; x < width; x++) { + matrix->Set(matrixX, matrixY, x % 2 == 0); + matrixX++; + } + matrixY++; + } + matrixX = 0; + for (int32_t x = 0; x < symbolWidth; x++) { + if (x % symbolInfo->matrixWidth() == 0) { + matrix->Set(matrixX, matrixY, true); + matrixX++; + } + matrix->Set(matrixX, matrixY, placement->getBit(x, y)); + matrixX++; + if (x % symbolInfo->matrixWidth() == symbolInfo->matrixWidth() - 1) { + matrix->Set(matrixX, matrixY, y % 2 == 0); + matrixX++; + } + } + matrixY++; + if (y % symbolInfo->matrixHeight() == symbolInfo->matrixHeight() - 1) { + matrixX = 0; + for (int32_t x = 0; x < width; x++) { + matrix->Set(matrixX, matrixY, true); + matrixX++; + } + matrixY++; + } + } + return matrix; +} + +} // namespace + +CBC_DataMatrixWriter::CBC_DataMatrixWriter() {} + +CBC_DataMatrixWriter::~CBC_DataMatrixWriter() {} + +bool CBC_DataMatrixWriter::SetErrorCorrectionLevel(int32_t level) { + m_iCorrectLevel = level; + return true; +} + +uint8_t* CBC_DataMatrixWriter::Encode(const WideString& contents, + int32_t& outWidth, + int32_t& outHeight) { + if (outWidth < 0 || outHeight < 0) + return nullptr; + + WideString ecLevel; + int32_t e = BCExceptionNO; + WideString encoded = + CBC_HighLevelEncoder::encodeHighLevel(contents, ecLevel, false, e); + if (e != BCExceptionNO) + return nullptr; + CBC_SymbolInfo* symbolInfo = + CBC_SymbolInfo::lookup(encoded.GetLength(), false, e); + if (e != BCExceptionNO) + return nullptr; + WideString codewords = + CBC_ErrorCorrection::encodeECC200(encoded, symbolInfo, e); + if (e != BCExceptionNO) + return nullptr; + + int32_t width = symbolInfo->getSymbolDataWidth(); + ASSERT(width); + int32_t height = symbolInfo->getSymbolDataHeight(); + ASSERT(height); + + auto placement = + pdfium::MakeUnique(codewords, width, height); + placement->place(); + auto bytematrix = encodeLowLevel(placement.get(), symbolInfo); + if (!bytematrix) + return nullptr; + + outWidth = bytematrix->GetWidth(); + outHeight = bytematrix->GetHeight(); + uint8_t* result = FX_Alloc2D(uint8_t, outWidth, outHeight); + memcpy(result, bytematrix->GetArray(), outWidth * outHeight); + return result; +} diff --git a/fxbarcode/datamatrix/BC_DataMatrixWriter.h b/fxbarcode/datamatrix/BC_DataMatrixWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..ba2c54762e8d081cfae9659c627596973903a550 --- /dev/null +++ b/fxbarcode/datamatrix/BC_DataMatrixWriter.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 FXBARCODE_DATAMATRIX_BC_DATAMATRIXWRITER_H_ +#define FXBARCODE_DATAMATRIX_BC_DATAMATRIXWRITER_H_ + +#include "fxbarcode/BC_TwoDimWriter.h" + +class CBC_CommonByteMatrix; +class CBC_DefaultPlacement; +class CBC_SymbolInfo; + +class CBC_DataMatrixWriter : public CBC_TwoDimWriter { + public: + CBC_DataMatrixWriter(); + ~CBC_DataMatrixWriter() override; + + uint8_t* Encode(const WideString& contents, + int32_t& outWidth, + int32_t& outHeight); + + // CBC_TwoDimWriter + bool SetErrorCorrectionLevel(int32_t level) override; + + private: + int32_t m_iCorrectLevel; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_DATAMATRIXWRITER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_DefaultPlacement.cpp b/fxbarcode/datamatrix/BC_DefaultPlacement.cpp similarity index 92% rename from xfa/fxbarcode/datamatrix/BC_DefaultPlacement.cpp rename to fxbarcode/datamatrix/BC_DefaultPlacement.cpp index e7eef07b4716b01a6ae4fe645d6b4cc7f10f4a7d..3f1b35864f5112bea4ef02e565eef1709285c1bf 100644 --- a/xfa/fxbarcode/datamatrix/BC_DefaultPlacement.cpp +++ b/fxbarcode/datamatrix/BC_DefaultPlacement.cpp @@ -20,30 +20,29 @@ * limitations under the License. */ -#include "xfa/fxbarcode/datamatrix/BC_DefaultPlacement.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_DefaultPlacement.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" -CBC_DefaultPlacement::CBC_DefaultPlacement(CFX_WideString codewords, +CBC_DefaultPlacement::CBC_DefaultPlacement(WideString codewords, int32_t numcols, int32_t numrows) { m_codewords = codewords; m_numcols = numcols; m_numrows = numrows; - m_bits.SetSize(numcols * numrows); + m_bits.resize(numcols * numrows); for (int32_t i = 0; i < numcols * numrows; i++) { m_bits[i] = (uint8_t)2; } } -CBC_DefaultPlacement::~CBC_DefaultPlacement() { - m_bits.RemoveAll(); -} +CBC_DefaultPlacement::~CBC_DefaultPlacement() {} + int32_t CBC_DefaultPlacement::getNumrows() { return m_numrows; } int32_t CBC_DefaultPlacement::getNumcols() { return m_numcols; } -CFX_ArrayTemplate& CBC_DefaultPlacement::getBits() { +std::vector& CBC_DefaultPlacement::getBits() { return m_bits; } bool CBC_DefaultPlacement::getBit(int32_t col, int32_t row) { @@ -108,7 +107,7 @@ void CBC_DefaultPlacement::module(int32_t row, col += m_numcols; row += 4 - ((m_numcols + 4) % 8); } - int32_t v = m_codewords.GetAt(pos); + int32_t v = m_codewords[pos]; v &= 1 << (8 - bit); setBit(col, row, v != 0); } diff --git a/fxbarcode/datamatrix/BC_DefaultPlacement.h b/fxbarcode/datamatrix/BC_DefaultPlacement.h new file mode 100644 index 0000000000000000000000000000000000000000..12ea852136ce27e89a14eb6dc8ae5c4717ec2d75 --- /dev/null +++ b/fxbarcode/datamatrix/BC_DefaultPlacement.h @@ -0,0 +1,40 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_DATAMATRIX_BC_DEFAULTPLACEMENT_H_ +#define FXBARCODE_DATAMATRIX_BC_DEFAULTPLACEMENT_H_ + +#include + +#include "core/fxcrt/fx_string.h" + +class CBC_DefaultPlacement { + public: + CBC_DefaultPlacement(WideString codewords, int32_t numcols, int32_t numrows); + virtual ~CBC_DefaultPlacement(); + + int32_t getNumrows(); + int32_t getNumcols(); + std::vector& getBits(); + bool getBit(int32_t col, int32_t row); + void setBit(int32_t col, int32_t row, bool bit); + bool hasBit(int32_t col, int32_t row); + void place(); + + private: + WideString m_codewords; + int32_t m_numrows; + int32_t m_numcols; + std::vector m_bits; + void module(int32_t row, int32_t col, int32_t pos, int32_t bit); + void utah(int32_t row, int32_t col, int32_t pos); + void corner1(int32_t pos); + void corner2(int32_t pos); + void corner3(int32_t pos); + void corner4(int32_t pos); +}; + +#endif // FXBARCODE_DATAMATRIX_BC_DEFAULTPLACEMENT_H_ diff --git a/fxbarcode/datamatrix/BC_EdifactEncoder.cpp b/fxbarcode/datamatrix/BC_EdifactEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41180dcf510fcc4a6aa165e39b36829307e3b6f1 --- /dev/null +++ b/fxbarcode/datamatrix/BC_EdifactEncoder.cpp @@ -0,0 +1,157 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_EdifactEncoder.h" + +#include + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" + +namespace { + +WideString EncodeToEdifactCodewords(const WideString& sb, int32_t startPos) { + int32_t len = sb.GetLength() - startPos; + if (len == 0) + return WideString(); + + wchar_t c1 = sb[startPos]; + wchar_t c2 = len >= 2 ? sb[startPos + 1] : 0; + wchar_t c3 = len >= 3 ? sb[startPos + 2] : 0; + wchar_t c4 = len >= 4 ? sb[startPos + 3] : 0; + int32_t v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4; + constexpr int32_t kBuflen = 3; + wchar_t cw[kBuflen]; + cw[0] = static_cast((v >> 16) & 255); + cw[1] = static_cast((v >> 8) & 255); + cw[2] = static_cast(v & 255); + return WideString(cw, std::min(len, kBuflen)); +} + +bool HandleEOD(CBC_EncoderContext* context, const WideString& buffer) { + int32_t count = buffer.GetLength(); + if (count == 0) + return true; + if (count > 4) + return false; + + if (count == 1) { + int32_t e = BCExceptionNO; + context->updateSymbolInfo(e); + if (e != BCExceptionNO) + return false; + + int32_t available = + context->m_symbolInfo->dataCapacity() - context->getCodewordCount(); + int32_t remaining = context->getRemainingCharacters(); + if (remaining == 0 && available <= 2) + return true; + } + + int32_t restChars = count - 1; + WideString encoded = EncodeToEdifactCodewords(buffer, 0); + if (encoded.IsEmpty()) + return false; + + bool endOfSymbolReached = !context->hasMoreCharacters(); + bool restInAscii = endOfSymbolReached && restChars <= 2; + if (restChars <= 2) { + int32_t e = BCExceptionNO; + context->updateSymbolInfo(context->getCodewordCount() + restChars, e); + if (e != BCExceptionNO) + return false; + + int32_t available = + context->m_symbolInfo->dataCapacity() - context->getCodewordCount(); + if (available >= 3) { + restInAscii = false; + context->updateSymbolInfo( + context->getCodewordCount() + encoded.GetLength(), e); + if (e != BCExceptionNO) + return false; + } + } + + if (restInAscii) { + context->resetSymbolInfo(); + context->m_pos -= restChars; + } else { + context->writeCodewords(encoded); + } + context->signalEncoderChange(ASCII_ENCODATION); + return true; +} + +void encodeChar(wchar_t c, WideString* sb, int32_t& e) { + if (c >= ' ' && c <= '?') { + *sb += c; + } else if (c >= '@' && c <= '^') { + *sb += (wchar_t)(c - 64); + } else { + e = BCExceptionIllegalArgument; + } +} + +} // namespace + +CBC_EdifactEncoder::CBC_EdifactEncoder() {} + +CBC_EdifactEncoder::~CBC_EdifactEncoder() {} + +int32_t CBC_EdifactEncoder::getEncodingMode() { + return EDIFACT_ENCODATION; +} + +void CBC_EdifactEncoder::Encode(CBC_EncoderContext& context, int32_t& e) { + WideString buffer; + while (context.hasMoreCharacters()) { + wchar_t c = context.getCurrentChar(); + encodeChar(c, &buffer, e); + if (e != BCExceptionNO) { + return; + } + context.m_pos++; + int32_t count = buffer.GetLength(); + if (count >= 4) { + WideString encoded = EncodeToEdifactCodewords(buffer, 0); + if (encoded.IsEmpty()) { + e = BCExceptionGeneric; + return; + } + context.writeCodewords(encoded); + buffer.Delete(0, 4); + int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( + context.m_msg, context.m_pos, getEncodingMode()); + if (newMode != getEncodingMode()) { + context.signalEncoderChange(ASCII_ENCODATION); + break; + } + } + } + buffer += static_cast(31); + if (!HandleEOD(&context, buffer)) + e = BCExceptionGeneric; +} diff --git a/fxbarcode/datamatrix/BC_EdifactEncoder.h b/fxbarcode/datamatrix/BC_EdifactEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..eb59222d4f13fa45ee3ef01945a711ea4c38cffb --- /dev/null +++ b/fxbarcode/datamatrix/BC_EdifactEncoder.h @@ -0,0 +1,22 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_DATAMATRIX_BC_EDIFACTENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_EDIFACTENCODER_H_ + +#include "fxbarcode/datamatrix/BC_Encoder.h" + +class CBC_EdifactEncoder : public CBC_Encoder { + public: + CBC_EdifactEncoder(); + ~CBC_EdifactEncoder() override; + + // CBC_Encoder + int32_t getEncodingMode() override; + void Encode(CBC_EncoderContext& context, int32_t& e) override; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_EDIFACTENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_Encoder.cpp b/fxbarcode/datamatrix/BC_Encoder.cpp similarity index 86% rename from xfa/fxbarcode/datamatrix/BC_Encoder.cpp rename to fxbarcode/datamatrix/BC_Encoder.cpp index bf815bdfa7dbba0a100b579ce3229a6aaacee79c..9403904f325b5a0d48a61eedb31cd1f5cbbbc881 100644 --- a/xfa/fxbarcode/datamatrix/BC_Encoder.cpp +++ b/fxbarcode/datamatrix/BC_Encoder.cpp @@ -4,7 +4,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" CBC_Encoder::CBC_Encoder() {} CBC_Encoder::~CBC_Encoder() {} diff --git a/fxbarcode/datamatrix/BC_Encoder.h b/fxbarcode/datamatrix/BC_Encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..be1730f0c29e70e2065a45413612a6db62ebbbbf --- /dev/null +++ b/fxbarcode/datamatrix/BC_Encoder.h @@ -0,0 +1,23 @@ +// 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 FXBARCODE_DATAMATRIX_BC_ENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_ENCODER_H_ + +#include + +class CBC_EncoderContext; + +class CBC_Encoder { + public: + CBC_Encoder(); + virtual ~CBC_Encoder(); + + virtual int32_t getEncodingMode() = 0; + virtual void Encode(CBC_EncoderContext& context, int32_t& e) = 0; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_ENCODER_H_ diff --git a/fxbarcode/datamatrix/BC_EncoderContext.cpp b/fxbarcode/datamatrix/BC_EncoderContext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe0a497d581c5c52b2d326b1a986c7a943c79e26 --- /dev/null +++ b/fxbarcode/datamatrix/BC_EncoderContext.cpp @@ -0,0 +1,108 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_EncoderContext.h" + +#include "fxbarcode/BC_UtilCodingConvert.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" + +CBC_EncoderContext::CBC_EncoderContext(const WideString& msg, + const WideString& ecLevel, + int32_t& e) { + ByteString dststr; + CBC_UtilCodingConvert::UnicodeToUTF8(msg, dststr); + WideString sb; + size_t c = dststr.GetLength(); + for (size_t i = 0; i < c; i++) { + wchar_t ch = static_cast(dststr[i] & 0xff); + if (ch == '?' && dststr[i] != '?') { + e = BCExceptionCharactersOutsideISO88591Encoding; + } + sb += ch; + } + m_msg = sb; + m_allowRectangular = true; + m_newEncoding = -1; + m_pos = 0; + m_symbolInfo = nullptr; + m_skipAtEnd = 0; +} + +CBC_EncoderContext::~CBC_EncoderContext() {} + +void CBC_EncoderContext::setAllowRectangular(bool allow) { + m_allowRectangular = allow; +} + +void CBC_EncoderContext::setSkipAtEnd(int32_t count) { + m_skipAtEnd = count; +} +wchar_t CBC_EncoderContext::getCurrentChar() { + return m_msg[m_pos]; +} +wchar_t CBC_EncoderContext::getCurrent() { + return m_msg[m_pos]; +} + +void CBC_EncoderContext::writeCodewords(const WideString& codewords) { + m_codewords += codewords; +} + +void CBC_EncoderContext::writeCodeword(wchar_t codeword) { + m_codewords += codeword; +} +size_t CBC_EncoderContext::getCodewordCount() { + return m_codewords.GetLength(); +} +void CBC_EncoderContext::signalEncoderChange(int32_t encoding) { + m_newEncoding = encoding; +} +void CBC_EncoderContext::resetEncoderSignal() { + m_newEncoding = -1; +} +bool CBC_EncoderContext::hasMoreCharacters() { + return m_pos < getTotalMessageCharCount(); +} +size_t CBC_EncoderContext::getRemainingCharacters() { + return getTotalMessageCharCount() - m_pos; +} +void CBC_EncoderContext::updateSymbolInfo(int32_t& e) { + updateSymbolInfo(getCodewordCount(), e); +} +void CBC_EncoderContext::updateSymbolInfo(int32_t len, int32_t& e) { + if (!m_symbolInfo || len > m_symbolInfo->dataCapacity()) { + m_symbolInfo = CBC_SymbolInfo::lookup(len, m_allowRectangular, e); + if (e != BCExceptionNO) + return; + } +} + +void CBC_EncoderContext::resetSymbolInfo() { + m_allowRectangular = true; +} + +size_t CBC_EncoderContext::getTotalMessageCharCount() { + return m_msg.GetLength() - m_skipAtEnd; +} diff --git a/fxbarcode/datamatrix/BC_EncoderContext.h b/fxbarcode/datamatrix/BC_EncoderContext.h new file mode 100644 index 0000000000000000000000000000000000000000..c0ddb20b7b750fcd6aa7f1c7a5d008341f16b89e --- /dev/null +++ b/fxbarcode/datamatrix/BC_EncoderContext.h @@ -0,0 +1,50 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_DATAMATRIX_BC_ENCODERCONTEXT_H_ +#define FXBARCODE_DATAMATRIX_BC_ENCODERCONTEXT_H_ + +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxcrt/widestring.h" + +class CBC_SymbolInfo; + +class CBC_EncoderContext { + public: + CBC_EncoderContext(const WideString& msg, + const WideString& ecLevel, + int32_t& e); + ~CBC_EncoderContext(); + + void setAllowRectangular(bool allow); + void setSkipAtEnd(int32_t count); + wchar_t getCurrentChar(); + wchar_t getCurrent(); + void writeCodewords(const WideString& codewords); + void writeCodeword(wchar_t codeword); + size_t getCodewordCount(); + void signalEncoderChange(int32_t encoding); + void resetEncoderSignal(); + bool hasMoreCharacters(); + size_t getRemainingCharacters(); + void updateSymbolInfo(int32_t& e); + void updateSymbolInfo(int32_t len, int32_t& e); + void resetSymbolInfo(); + + WideString m_msg; + WideString m_codewords; + size_t m_pos; + int32_t m_newEncoding; + UnownedPtr m_symbolInfo; + + private: + size_t getTotalMessageCharCount(); + + bool m_allowRectangular; // Force square when false. + size_t m_skipAtEnd; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_ENCODERCONTEXT_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_ErrorCorrection.cpp b/fxbarcode/datamatrix/BC_ErrorCorrection.cpp similarity index 77% rename from xfa/fxbarcode/datamatrix/BC_ErrorCorrection.cpp rename to fxbarcode/datamatrix/BC_ErrorCorrection.cpp index 17eec1ee4f1ed1c01d2f6553940fdf9856548294..35077ee62850adbeb200b4426c5b40a89d8baea7 100644 --- a/xfa/fxbarcode/datamatrix/BC_ErrorCorrection.cpp +++ b/fxbarcode/datamatrix/BC_ErrorCorrection.cpp @@ -20,10 +20,13 @@ * limitations under the License. */ -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" +#include "fxbarcode/datamatrix/BC_ErrorCorrection.h" + +#include + +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" namespace { @@ -116,29 +119,26 @@ void CBC_ErrorCorrection::Initialize() { void CBC_ErrorCorrection::Finalize() {} CBC_ErrorCorrection::CBC_ErrorCorrection() {} CBC_ErrorCorrection::~CBC_ErrorCorrection() {} -CFX_WideString CBC_ErrorCorrection::encodeECC200(CFX_WideString codewords, - CBC_SymbolInfo* symbolInfo, - int32_t& e) { - if (codewords.GetLength() != symbolInfo->m_dataCapacity) { +WideString CBC_ErrorCorrection::encodeECC200(WideString codewords, + CBC_SymbolInfo* symbolInfo, + int32_t& e) { + if (pdfium::base::checked_cast(codewords.GetLength()) != + symbolInfo->dataCapacity()) { e = BCExceptionIllegalArgument; - return CFX_WideString(); + return WideString(); } - CFX_WideString sb; + WideString sb; sb += codewords; int32_t blockCount = symbolInfo->getInterleavedBlockCount(); if (blockCount == 1) { - CFX_WideString ecc = - createECCBlock(codewords, symbolInfo->m_errorCodewords, e); + WideString ecc = createECCBlock(codewords, symbolInfo->errorCodewords(), e); if (e != BCExceptionNO) - return CFX_WideString(); + return WideString(); sb += ecc; } else { - CFX_ArrayTemplate dataSizes; - dataSizes.SetSize(blockCount); - CFX_ArrayTemplate errorSizes; - errorSizes.SetSize(blockCount); - CFX_ArrayTemplate startPos; - startPos.SetSize(blockCount); + std::vector dataSizes(blockCount); + std::vector errorSizes(blockCount); + std::vector startPos(blockCount); for (int32_t i = 0; i < blockCount; i++) { dataSizes[i] = symbolInfo->getDataLengthForInterleavedBlock(i + 1); errorSizes[i] = symbolInfo->getErrorLengthForInterleavedBlock(i + 1); @@ -148,32 +148,32 @@ CFX_WideString CBC_ErrorCorrection::encodeECC200(CFX_WideString codewords, } } for (int32_t block = 0; block < blockCount; block++) { - CFX_WideString temp; - for (int32_t d = block; d < symbolInfo->m_dataCapacity; d += blockCount) { - temp += (FX_WCHAR)codewords.GetAt(d); + WideString temp; + for (int32_t d = block; d < symbolInfo->dataCapacity(); d += blockCount) { + temp += (wchar_t)codewords[d]; } - CFX_WideString ecc = createECCBlock(temp, errorSizes[block], e); + WideString ecc = createECCBlock(temp, errorSizes[block], e); if (e != BCExceptionNO) - return CFX_WideString(); + return WideString(); int32_t pos = 0; for (int32_t l = block; l < errorSizes[block] * blockCount; l += blockCount) { - sb.SetAt(symbolInfo->m_dataCapacity + l, ecc.GetAt(pos++)); + sb.SetAt(symbolInfo->dataCapacity() + l, ecc[pos++]); } } } return sb; } -CFX_WideString CBC_ErrorCorrection::createECCBlock(CFX_WideString codewords, - int32_t numECWords, - int32_t& e) { +WideString CBC_ErrorCorrection::createECCBlock(WideString codewords, + int32_t numECWords, + int32_t& e) { return createECCBlock(codewords, 0, codewords.GetLength(), numECWords, e); } -CFX_WideString CBC_ErrorCorrection::createECCBlock(CFX_WideString codewords, - int32_t start, - int32_t len, - int32_t numECWords, - int32_t& e) { +WideString CBC_ErrorCorrection::createECCBlock(WideString codewords, + int32_t start, + int32_t len, + int32_t numECWords, + int32_t& e) { static const size_t kFactorTableNum = sizeof(FACTOR_SETS) / sizeof(int32_t); size_t table = 0; while (table < kFactorTableNum && FACTOR_SETS[table] != numECWords) @@ -181,12 +181,12 @@ CFX_WideString CBC_ErrorCorrection::createECCBlock(CFX_WideString codewords, if (table >= kFactorTableNum) { e = BCExceptionIllegalArgument; - return CFX_WideString(); + return WideString(); } uint16_t* ecc = FX_Alloc(uint16_t, numECWords); - FXSYS_memset(ecc, 0, numECWords * sizeof(uint16_t)); + memset(ecc, 0, numECWords * sizeof(uint16_t)); for (int32_t l = start; l < start + len; l++) { - uint16_t m = ecc[numECWords - 1] ^ codewords.GetAt(l); + uint16_t m = ecc[numECWords - 1] ^ codewords[l]; for (int32_t k = numECWords - 1; k > 0; k--) { if (m != 0 && FACTORS[table][k] != 0) { ecc[k] = (uint16_t)(ecc[k - 1] ^ @@ -201,9 +201,9 @@ CFX_WideString CBC_ErrorCorrection::createECCBlock(CFX_WideString codewords, ecc[0] = 0; } } - CFX_WideString strecc; + WideString strecc; for (int32_t j = 0; j < numECWords; j++) { - strecc += (FX_WCHAR)ecc[numECWords - j - 1]; + strecc += (wchar_t)ecc[numECWords - j - 1]; } FX_Free(ecc); return strecc; diff --git a/fxbarcode/datamatrix/BC_ErrorCorrection.h b/fxbarcode/datamatrix/BC_ErrorCorrection.h new file mode 100644 index 0000000000000000000000000000000000000000..361b205ef40bcc9ce7d2a5319388e5e6ad00af4b --- /dev/null +++ b/fxbarcode/datamatrix/BC_ErrorCorrection.h @@ -0,0 +1,41 @@ +// 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 FXBARCODE_DATAMATRIX_BC_ERRORCORRECTION_H_ +#define FXBARCODE_DATAMATRIX_BC_ERRORCORRECTION_H_ + +#include "core/fxcrt/widestring.h" + +class CBC_SymbolInfo; + +class CBC_ErrorCorrection { + public: + CBC_ErrorCorrection(); + virtual ~CBC_ErrorCorrection(); + + static void Initialize(); + static void Finalize(); + static WideString encodeECC200(WideString codewords, + CBC_SymbolInfo* symbolInfo, + int32_t& e); + + private: + static int32_t MODULO_VALUE; + static int32_t LOG[256]; + static int32_t ALOG[256]; + + private: + static WideString createECCBlock(WideString codewords, + int32_t numECWords, + int32_t& e); + static WideString createECCBlock(WideString codewords, + int32_t start, + int32_t len, + int32_t numECWords, + int32_t& e); +}; + +#endif // FXBARCODE_DATAMATRIX_BC_ERRORCORRECTION_H_ diff --git a/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp b/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56a8847066abc8cd5d7d81c98c4dd1c864040c37 --- /dev/null +++ b/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp @@ -0,0 +1,348 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" + +#include +#include +#include + +#include "fxbarcode/BC_UtilCodingConvert.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_ASCIIEncoder.h" +#include "fxbarcode/datamatrix/BC_Base256Encoder.h" +#include "fxbarcode/datamatrix/BC_C40Encoder.h" +#include "fxbarcode/datamatrix/BC_EdifactEncoder.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/datamatrix/BC_TextEncoder.h" +#include "fxbarcode/datamatrix/BC_X12Encoder.h" +#include "fxbarcode/utils.h" +#include "third_party/base/ptr_util.h" + +const wchar_t CBC_HighLevelEncoder::LATCH_TO_C40 = 230; +const wchar_t CBC_HighLevelEncoder::LATCH_TO_BASE256 = 231; +const wchar_t CBC_HighLevelEncoder::UPPER_SHIFT = 235; +const wchar_t CBC_HighLevelEncoder::LATCH_TO_ANSIX12 = 238; +const wchar_t CBC_HighLevelEncoder::LATCH_TO_TEXT = 239; +const wchar_t CBC_HighLevelEncoder::LATCH_TO_EDIFACT = 240; +const wchar_t CBC_HighLevelEncoder::C40_UNLATCH = 254; +const wchar_t CBC_HighLevelEncoder::X12_UNLATCH = 254; +const wchar_t CBC_HighLevelEncoder::PAD = 129; +const wchar_t CBC_HighLevelEncoder::MACRO_05 = 236; +const wchar_t CBC_HighLevelEncoder::MACRO_06 = 237; +const wchar_t CBC_HighLevelEncoder::MACRO_05_HEADER[] = L"[)>05"; +const wchar_t CBC_HighLevelEncoder::MACRO_06_HEADER[] = L"[)>06"; +const wchar_t CBC_HighLevelEncoder::MACRO_TRAILER = 0x0004; + +CBC_HighLevelEncoder::CBC_HighLevelEncoder() {} +CBC_HighLevelEncoder::~CBC_HighLevelEncoder() {} + +std::vector& CBC_HighLevelEncoder::getBytesForMessage(WideString msg) { + ByteString bytestr; + CBC_UtilCodingConvert::UnicodeToUTF8(msg, bytestr); + m_bytearray.insert(m_bytearray.end(), bytestr.begin(), bytestr.end()); + return m_bytearray; +} + +// static +WideString CBC_HighLevelEncoder::encodeHighLevel(WideString msg, + WideString ecLevel, + bool allowRectangular, + int32_t& e) { + CBC_EncoderContext context(msg, ecLevel, e); + if (e != BCExceptionNO) + return WideString(); + + context.setAllowRectangular(allowRectangular); + if ((msg.Left(6) == MACRO_05_HEADER) && (msg.Last() == MACRO_TRAILER)) { + context.writeCodeword(MACRO_05); + context.setSkipAtEnd(2); + context.m_pos += 6; + } else if ((msg.Left(6) == MACRO_06_HEADER) && + (msg.Last() == MACRO_TRAILER)) { + context.writeCodeword(MACRO_06); + context.setSkipAtEnd(2); + context.m_pos += 6; + } + + std::vector> encoders; + encoders.push_back(pdfium::MakeUnique()); + encoders.push_back(pdfium::MakeUnique()); + encoders.push_back(pdfium::MakeUnique()); + encoders.push_back(pdfium::MakeUnique()); + encoders.push_back(pdfium::MakeUnique()); + encoders.push_back(pdfium::MakeUnique()); + int32_t encodingMode = ASCII_ENCODATION; + while (context.hasMoreCharacters()) { + encoders[encodingMode]->Encode(context, e); + if (e != BCExceptionNO) + return L""; + + if (context.m_newEncoding >= 0) { + encodingMode = context.m_newEncoding; + context.resetEncoderSignal(); + } + } + int32_t len = context.m_codewords.GetLength(); + context.updateSymbolInfo(e); + if (e != BCExceptionNO) + return L""; + + int32_t capacity = context.m_symbolInfo->dataCapacity(); + if (len < capacity) { + if (encodingMode != ASCII_ENCODATION && + encodingMode != BASE256_ENCODATION) { + context.writeCodeword(0x00fe); + } + } + WideString codewords = context.m_codewords; + if (pdfium::base::checked_cast(codewords.GetLength()) < capacity) { + codewords += PAD; + } + while (pdfium::base::checked_cast(codewords.GetLength()) < + capacity) { + codewords += (randomize253State( + PAD, pdfium::base::checked_cast(codewords.GetLength()) + 1)); + } + return codewords; +} +int32_t CBC_HighLevelEncoder::lookAheadTest(WideString msg, + int32_t startpos, + int32_t currentMode) { + if (startpos >= pdfium::base::checked_cast(msg.GetLength())) { + return currentMode; + } + std::vector charCounts; + if (currentMode == ASCII_ENCODATION) { + charCounts.push_back(0); + charCounts.push_back(1); + charCounts.push_back(1); + charCounts.push_back(1); + charCounts.push_back(1); + charCounts.push_back(1.25f); + } else { + charCounts.push_back(1); + charCounts.push_back(2); + charCounts.push_back(2); + charCounts.push_back(2); + charCounts.push_back(2); + charCounts.push_back(2.25f); + charCounts[currentMode] = 0; + } + int32_t charsProcessed = 0; + while (true) { + if ((startpos + charsProcessed) == + pdfium::base::checked_cast(msg.GetLength())) { + int32_t min = std::numeric_limits::max(); + std::vector mins(6); + std::vector intCharCounts(6); + min = findMinimums(charCounts, intCharCounts, min, mins); + int32_t minCount = getMinimumCount(mins); + if (intCharCounts[ASCII_ENCODATION] == min) { + return ASCII_ENCODATION; + } + if (minCount == 1 && mins[BASE256_ENCODATION] > 0) { + return BASE256_ENCODATION; + } + if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) { + return EDIFACT_ENCODATION; + } + if (minCount == 1 && mins[TEXT_ENCODATION] > 0) { + return TEXT_ENCODATION; + } + if (minCount == 1 && mins[X12_ENCODATION] > 0) { + return X12_ENCODATION; + } + return C40_ENCODATION; + } + wchar_t c = msg[startpos + charsProcessed]; + charsProcessed++; + if (isDigit(c)) { + charCounts[ASCII_ENCODATION] += 0.5; + } else if (isExtendedASCII(c)) { + charCounts[ASCII_ENCODATION] = (float)ceil(charCounts[ASCII_ENCODATION]); + charCounts[ASCII_ENCODATION] += 2; + } else { + charCounts[ASCII_ENCODATION] = (float)ceil(charCounts[ASCII_ENCODATION]); + charCounts[ASCII_ENCODATION]++; + } + if (isNativeC40(c)) { + charCounts[C40_ENCODATION] += 2.0f / 3.0f; + } else if (isExtendedASCII(c)) { + charCounts[C40_ENCODATION] += 8.0f / 3.0f; + } else { + charCounts[C40_ENCODATION] += 4.0f / 3.0f; + } + if (isNativeText(c)) { + charCounts[TEXT_ENCODATION] += 2.0f / 3.0f; + } else if (isExtendedASCII(c)) { + charCounts[TEXT_ENCODATION] += 8.0f / 3.0f; + } else { + charCounts[TEXT_ENCODATION] += 4.0f / 3.0f; + } + if (isNativeX12(c)) { + charCounts[X12_ENCODATION] += 2.0f / 3.0f; + } else if (isExtendedASCII(c)) { + charCounts[X12_ENCODATION] += 13.0f / 3.0f; + } else { + charCounts[X12_ENCODATION] += 10.0f / 3.0f; + } + if (isNativeEDIFACT(c)) { + charCounts[EDIFACT_ENCODATION] += 3.0f / 4.0f; + } else if (isExtendedASCII(c)) { + charCounts[EDIFACT_ENCODATION] += 17.0f / 4.0f; + } else { + charCounts[EDIFACT_ENCODATION] += 13.0f / 4.0f; + } + charCounts[BASE256_ENCODATION]++; + if (charsProcessed >= 4) { + std::vector intCharCounts(6); + std::vector mins(6); + findMinimums(charCounts, intCharCounts, + std::numeric_limits::max(), mins); + int32_t minCount = getMinimumCount(mins); + if (intCharCounts[ASCII_ENCODATION] < intCharCounts[BASE256_ENCODATION] && + intCharCounts[ASCII_ENCODATION] < intCharCounts[C40_ENCODATION] && + intCharCounts[ASCII_ENCODATION] < intCharCounts[TEXT_ENCODATION] && + intCharCounts[ASCII_ENCODATION] < intCharCounts[X12_ENCODATION] && + intCharCounts[ASCII_ENCODATION] < intCharCounts[EDIFACT_ENCODATION]) { + return ASCII_ENCODATION; + } + if (intCharCounts[BASE256_ENCODATION] < intCharCounts[ASCII_ENCODATION] || + (mins[C40_ENCODATION] + mins[TEXT_ENCODATION] + mins[X12_ENCODATION] + + mins[EDIFACT_ENCODATION]) == 0) { + return BASE256_ENCODATION; + } + if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) { + return EDIFACT_ENCODATION; + } + if (minCount == 1 && mins[TEXT_ENCODATION] > 0) { + return TEXT_ENCODATION; + } + if (minCount == 1 && mins[X12_ENCODATION] > 0) { + return X12_ENCODATION; + } + if (intCharCounts[C40_ENCODATION] + 1 < intCharCounts[ASCII_ENCODATION] && + intCharCounts[C40_ENCODATION] + 1 < + intCharCounts[BASE256_ENCODATION] && + intCharCounts[C40_ENCODATION] + 1 < + intCharCounts[EDIFACT_ENCODATION] && + intCharCounts[C40_ENCODATION] + 1 < intCharCounts[TEXT_ENCODATION]) { + if (intCharCounts[C40_ENCODATION] < intCharCounts[X12_ENCODATION]) { + return C40_ENCODATION; + } + if (intCharCounts[C40_ENCODATION] == intCharCounts[X12_ENCODATION]) { + int32_t p = startpos + charsProcessed + 1; + int32_t checked_length = + pdfium::base::checked_cast(msg.GetLength()); + while (p < checked_length) { + wchar_t tc = msg[p]; + if (isX12TermSep(tc)) { + return X12_ENCODATION; + } + if (!isNativeX12(tc)) { + break; + } + p++; + } + return C40_ENCODATION; + } + } + } + } +} +bool CBC_HighLevelEncoder::isDigit(wchar_t ch) { + return ch >= '0' && ch <= '9'; +} +bool CBC_HighLevelEncoder::isExtendedASCII(wchar_t ch) { + return ch >= 128 && ch <= 255; +} +int32_t CBC_HighLevelEncoder::determineConsecutiveDigitCount(WideString msg, + int32_t startpos) { + int32_t count = 0; + int32_t len = msg.GetLength(); + int32_t idx = startpos; + if (idx < len) { + wchar_t ch = msg[idx]; + while (isDigit(ch) && idx < len) { + count++; + idx++; + if (idx < len) { + ch = msg[idx]; + } + } + } + return count; +} + +wchar_t CBC_HighLevelEncoder::randomize253State(wchar_t ch, + int32_t codewordPosition) { + int32_t pseudoRandom = ((149 * codewordPosition) % 253) + 1; + int32_t tempVariable = ch + pseudoRandom; + return tempVariable <= 254 ? (wchar_t)tempVariable + : (wchar_t)(tempVariable - 254); +} +int32_t CBC_HighLevelEncoder::findMinimums(std::vector& charCounts, + std::vector& intCharCounts, + int32_t min, + std::vector& mins) { + for (size_t l = 0; l < mins.size(); l++) + mins[l] = 0; + + for (size_t i = 0; i < 6; i++) { + intCharCounts[i] = static_cast(ceil(charCounts[i])); + int32_t current = intCharCounts[i]; + if (min > current) { + min = current; + for (size_t j = 0; j < mins.size(); j++) + mins[j] = 0; + } + if (min == current) + mins[i]++; + } + return min; +} +int32_t CBC_HighLevelEncoder::getMinimumCount(std::vector& mins) { + int32_t minCount = 0; + for (int32_t i = 0; i < 6; i++) { + minCount += mins[i]; + } + return minCount; +} +bool CBC_HighLevelEncoder::isNativeC40(wchar_t ch) { + return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'); +} +bool CBC_HighLevelEncoder::isNativeText(wchar_t ch) { + return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z'); +} +bool CBC_HighLevelEncoder::isNativeX12(wchar_t ch) { + return isX12TermSep(ch) || (ch == ' ') || (ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'Z'); +} +bool CBC_HighLevelEncoder::isX12TermSep(wchar_t ch) { + return (ch == '\r') || (ch == '*') || (ch == '>'); +} +bool CBC_HighLevelEncoder::isNativeEDIFACT(wchar_t ch) { + return ch >= ' ' && ch <= '^'; +} diff --git a/fxbarcode/datamatrix/BC_HighLevelEncoder.h b/fxbarcode/datamatrix/BC_HighLevelEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..50cfc8c59286dcbb2621583e37efbd1f1f3d4688 --- /dev/null +++ b/fxbarcode/datamatrix/BC_HighLevelEncoder.h @@ -0,0 +1,72 @@ +// 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 FXBARCODE_DATAMATRIX_BC_HIGHLEVELENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_HIGHLEVELENCODER_H_ + +#include + +#include "core/fxcrt/widestring.h" + +#define ASCII_ENCODATION 0 +#define C40_ENCODATION 1 +#define TEXT_ENCODATION 2 +#define X12_ENCODATION 3 +#define EDIFACT_ENCODATION 4 +#define BASE256_ENCODATION 5 + +class CBC_HighLevelEncoder { + public: + CBC_HighLevelEncoder(); + ~CBC_HighLevelEncoder(); + + std::vector& getBytesForMessage(WideString msg); + + static WideString encodeHighLevel(WideString msg, + WideString ecLevel, + bool allowRectangular, + int32_t& e); + static int32_t lookAheadTest(WideString msg, + int32_t startpos, + int32_t currentMode); + static bool isDigit(wchar_t ch); + static bool isExtendedASCII(wchar_t ch); + static int32_t determineConsecutiveDigitCount(WideString msg, + int32_t startpos); + + static const wchar_t LATCH_TO_C40; + static const wchar_t LATCH_TO_BASE256; + static const wchar_t UPPER_SHIFT; + static const wchar_t LATCH_TO_ANSIX12; + static const wchar_t LATCH_TO_TEXT; + static const wchar_t LATCH_TO_EDIFACT; + static const wchar_t C40_UNLATCH; + static const wchar_t X12_UNLATCH; + + private: + static wchar_t randomize253State(wchar_t ch, int32_t codewordPosition); + static int32_t findMinimums(std::vector& charCounts, + std::vector& intCharCounts, + int32_t min, + std::vector& mins); + static int32_t getMinimumCount(std::vector& mins); + static bool isNativeC40(wchar_t ch); + static bool isNativeText(wchar_t ch); + static bool isNativeX12(wchar_t ch); + static bool isX12TermSep(wchar_t ch); + static bool isNativeEDIFACT(wchar_t ch); + + static const wchar_t PAD; + static const wchar_t MACRO_05; + static const wchar_t MACRO_06; + static const wchar_t MACRO_05_HEADER[]; + static const wchar_t MACRO_06_HEADER[]; + static const wchar_t MACRO_TRAILER; + + std::vector m_bytearray; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_HIGHLEVELENCODER_H_ diff --git a/fxbarcode/datamatrix/BC_SymbolInfo.cpp b/fxbarcode/datamatrix/BC_SymbolInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4d99d2e1c4ebc94d285f67addae1c762385c6e1 --- /dev/null +++ b/fxbarcode/datamatrix/BC_SymbolInfo.cpp @@ -0,0 +1,194 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2006 Jeremias Maerki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/utils.h" + +namespace { + +const size_t kSymbolsCount = 30; + +CBC_SymbolInfo* g_symbols[kSymbolsCount] = { + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; + +} // namespace + +void CBC_SymbolInfo::Initialize() { + g_symbols[0] = new CBC_SymbolInfo(3, 5, 8, 8, 1); + g_symbols[1] = new CBC_SymbolInfo(5, 7, 10, 10, 1); + g_symbols[2] = new CBC_SymbolInfo(5, 7, 16, 6, 1); + g_symbols[3] = new CBC_SymbolInfo(8, 10, 12, 12, 1); + g_symbols[4] = new CBC_SymbolInfo(10, 11, 14, 6, 2); + g_symbols[5] = new CBC_SymbolInfo(12, 12, 14, 14, 1); + g_symbols[6] = new CBC_SymbolInfo(16, 14, 24, 10, 1); + g_symbols[7] = new CBC_SymbolInfo(18, 14, 16, 16, 1); + g_symbols[8] = new CBC_SymbolInfo(22, 18, 18, 18, 1); + g_symbols[9] = new CBC_SymbolInfo(22, 18, 16, 10, 2); + g_symbols[10] = new CBC_SymbolInfo(30, 20, 20, 20, 1); + g_symbols[11] = new CBC_SymbolInfo(32, 24, 16, 14, 2); + g_symbols[12] = new CBC_SymbolInfo(36, 24, 22, 22, 1); + g_symbols[13] = new CBC_SymbolInfo(44, 28, 24, 24, 1); + g_symbols[14] = new CBC_SymbolInfo(49, 28, 22, 14, 2); + g_symbols[15] = new CBC_SymbolInfo(62, 36, 14, 14, 4); + g_symbols[16] = new CBC_SymbolInfo(86, 42, 16, 16, 4); + g_symbols[17] = new CBC_SymbolInfo(114, 48, 18, 18, 4); + g_symbols[18] = new CBC_SymbolInfo(144, 56, 20, 20, 4); + g_symbols[19] = new CBC_SymbolInfo(174, 68, 22, 22, 4); + g_symbols[20] = new CBC_SymbolInfo(204, 84, 24, 24, 4, 102, 42); + g_symbols[21] = new CBC_SymbolInfo(280, 112, 14, 14, 16, 140, 56); + g_symbols[22] = new CBC_SymbolInfo(368, 144, 16, 16, 16, 92, 36); + g_symbols[23] = new CBC_SymbolInfo(456, 192, 18, 18, 16, 114, 48); + g_symbols[24] = new CBC_SymbolInfo(576, 224, 20, 20, 16, 144, 56); + g_symbols[25] = new CBC_SymbolInfo(696, 272, 22, 22, 16, 174, 68); + g_symbols[26] = new CBC_SymbolInfo(816, 336, 24, 24, 16, 136, 56); + g_symbols[27] = new CBC_SymbolInfo(1050, 408, 18, 18, 36, 175, 68); + g_symbols[28] = new CBC_SymbolInfo(1304, 496, 20, 20, 36, 163, 62); + g_symbols[29] = new CBC_DataMatrixSymbolInfo144(); +} + +void CBC_SymbolInfo::Finalize() { + for (size_t i = 0; i < kSymbolsCount; i++) { + delete g_symbols[i]; + g_symbols[i] = nullptr; + } +} + +CBC_SymbolInfo::CBC_SymbolInfo(int32_t dataCapacity, + int32_t errorCodewords, + int32_t matrixWidth, + int32_t matrixHeight, + int32_t dataRegions) + : CBC_SymbolInfo(dataCapacity, + errorCodewords, + matrixWidth, + matrixHeight, + dataRegions, + dataCapacity, + errorCodewords) {} + +CBC_SymbolInfo::CBC_SymbolInfo(int32_t dataCapacity, + int32_t errorCodewords, + int32_t matrixWidth, + int32_t matrixHeight, + int32_t dataRegions, + int32_t rsBlockData, + int32_t rsBlockError) + : m_rectangular(matrixWidth != matrixHeight), + m_dataCapacity(dataCapacity), + m_errorCodewords(errorCodewords), + m_matrixWidth(matrixWidth), + m_matrixHeight(matrixHeight), + m_dataRegions(dataRegions), + m_rsBlockData(rsBlockData), + m_rsBlockError(rsBlockError) {} + +CBC_SymbolInfo::~CBC_SymbolInfo() {} + +CBC_SymbolInfo* CBC_SymbolInfo::lookup(int32_t dataCodewords, + bool allowRectangular, + int32_t& e) { + for (size_t i = 0; i < kSymbolsCount; i++) { + CBC_SymbolInfo* symbol = g_symbols[i]; + if (symbol->m_rectangular && !allowRectangular) + continue; + + if (dataCodewords <= symbol->dataCapacity()) + return symbol; + } + e = BCExceptionIllegalDataCodewords; + return nullptr; +} + +int32_t CBC_SymbolInfo::getHorizontalDataRegions() const { + switch (m_dataRegions) { + case 1: + return 1; + case 2: + return 2; + case 4: + return 2; + case 16: + return 4; + case 36: + return 6; + default: + NOTREACHED(); + return 0; + } +} + +int32_t CBC_SymbolInfo::getVerticalDataRegions() const { + switch (m_dataRegions) { + case 1: + return 1; + case 2: + return 1; + case 4: + return 2; + case 16: + return 4; + case 36: + return 6; + default: + NOTREACHED(); + return 0; + } +} + +int32_t CBC_SymbolInfo::getSymbolDataWidth() const { + return getHorizontalDataRegions() * m_matrixWidth; +} + +int32_t CBC_SymbolInfo::getSymbolDataHeight() const { + return getVerticalDataRegions() * m_matrixHeight; +} + +int32_t CBC_SymbolInfo::getSymbolWidth() const { + return getSymbolDataWidth() + (getHorizontalDataRegions() * 2); +} + +int32_t CBC_SymbolInfo::getSymbolHeight() const { + return getSymbolDataHeight() + (getVerticalDataRegions() * 2); +} + +int32_t CBC_SymbolInfo::getCodewordCount() const { + return m_dataCapacity + m_errorCodewords; +} + +int32_t CBC_SymbolInfo::getInterleavedBlockCount() const { + return m_dataCapacity / m_rsBlockData; +} + +int32_t CBC_SymbolInfo::getDataLengthForInterleavedBlock(int32_t index) const { + return m_rsBlockData; +} + +int32_t CBC_SymbolInfo::getErrorLengthForInterleavedBlock(int32_t index) const { + return m_rsBlockError; +} diff --git a/fxbarcode/datamatrix/BC_SymbolInfo.h b/fxbarcode/datamatrix/BC_SymbolInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..fe3e24c817313888f73b2bd3741761b2829069f5 --- /dev/null +++ b/fxbarcode/datamatrix/BC_SymbolInfo.h @@ -0,0 +1,66 @@ +// 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 FXBARCODE_DATAMATRIX_BC_SYMBOLINFO_H_ +#define FXBARCODE_DATAMATRIX_BC_SYMBOLINFO_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" + +class CBC_SymbolInfo { + public: + CBC_SymbolInfo(int32_t dataCapacity, + int32_t errorCodewords, + int32_t matrixWidth, + int32_t matrixHeight, + int32_t dataRegions); + virtual ~CBC_SymbolInfo(); + + static void Initialize(); + static void Finalize(); + static void overrideSymbolSet(CBC_SymbolInfo* override); + static CBC_SymbolInfo* lookup(int32_t dataCodewords, + bool allowRectangular, + int32_t& e); + + int32_t getSymbolDataWidth() const; + int32_t getSymbolDataHeight() const; + int32_t getSymbolWidth() const; + int32_t getSymbolHeight() const; + int32_t getCodewordCount() const; + virtual int32_t getInterleavedBlockCount() const; + int32_t getDataLengthForInterleavedBlock(int32_t index) const; + int32_t getErrorLengthForInterleavedBlock(int32_t index) const; + + int32_t dataCapacity() const { return m_dataCapacity; } + int32_t errorCodewords() const { return m_errorCodewords; } + int32_t matrixWidth() const { return m_matrixWidth; } + int32_t matrixHeight() const { return m_matrixHeight; } + + protected: + CBC_SymbolInfo(int32_t dataCapacity, + int32_t errorCodewords, + int32_t matrixWidth, + int32_t matrixHeight, + int32_t dataRegions, + int32_t rsBlockData, + int32_t rsBlockError); + + private: + int32_t getHorizontalDataRegions() const; + int32_t getVerticalDataRegions() const; + + const bool m_rectangular; + const int32_t m_dataCapacity; + const int32_t m_errorCodewords; + const int32_t m_matrixWidth; + const int32_t m_matrixHeight; + const int32_t m_dataRegions; + const int32_t m_rsBlockData; + const int32_t m_rsBlockError; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_SYMBOLINFO_H_ diff --git a/fxbarcode/datamatrix/BC_TextEncoder.cpp b/fxbarcode/datamatrix/BC_TextEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a78310ed21bd1255d11aefebbc4d242ff4e975f0 --- /dev/null +++ b/fxbarcode/datamatrix/BC_TextEncoder.cpp @@ -0,0 +1,95 @@ +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_TextEncoder.h" + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_C40Encoder.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" + +CBC_TextEncoder::CBC_TextEncoder() {} +CBC_TextEncoder::~CBC_TextEncoder() {} +int32_t CBC_TextEncoder::getEncodingMode() { + return TEXT_ENCODATION; +} +int32_t CBC_TextEncoder::encodeChar(wchar_t c, WideString& sb, int32_t& e) { + if (c == ' ') { + sb += (wchar_t)'\3'; + return 1; + } + if (c >= '0' && c <= '9') { + sb += (wchar_t)(c - 48 + 4); + return 1; + } + if (c >= 'a' && c <= 'z') { + sb += (wchar_t)(c - 97 + 14); + return 1; + } + if (c <= 0x1f) { + sb += (wchar_t)'\0'; + sb += c; + return 2; + } + if (c >= '!' && c <= '/') { + sb += (wchar_t)'\1'; + sb += (wchar_t)(c - 33); + return 2; + } + if (c >= ':' && c <= '@') { + sb += (wchar_t)'\1'; + sb += (wchar_t)(c - 58 + 15); + return 2; + } + if (c >= '[' && c <= '_') { + sb += (wchar_t)'\1'; + sb += (wchar_t)(c - 91 + 22); + return 2; + } + if (c == 0x0060) { + sb += (wchar_t)'\2'; + sb += (wchar_t)(c - 96); + return 2; + } + if (c >= 'A' && c <= 'Z') { + sb += (wchar_t)'\2'; + sb += (wchar_t)(c - 65 + 1); + return 2; + } + if (c >= '{' && c <= 0x007f) { + sb += (wchar_t)'\2'; + sb += (wchar_t)(c - 123 + 27); + return 2; + } + if (c >= 0x0080) { + sb += (wchar_t)'\1'; + sb += (wchar_t)0x001e; + int32_t len = 2; + len += encodeChar((wchar_t)(c - 128), sb, e); + if (e != BCExceptionNO) + return -1; + return len; + } + e = BCExceptionIllegalArgument; + return -1; +} diff --git a/fxbarcode/datamatrix/BC_TextEncoder.h b/fxbarcode/datamatrix/BC_TextEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..9d4cdafe10e4f573f3a2da4d861b4e8032fb87cd --- /dev/null +++ b/fxbarcode/datamatrix/BC_TextEncoder.h @@ -0,0 +1,22 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_DATAMATRIX_BC_TEXTENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_TEXTENCODER_H_ + +#include "fxbarcode/datamatrix/BC_C40Encoder.h" + +class CBC_TextEncoder : public CBC_C40Encoder { + public: + CBC_TextEncoder(); + ~CBC_TextEncoder() override; + + // CBC_C40Encoder + int32_t getEncodingMode() override; + int32_t encodeChar(wchar_t c, WideString& sb, int32_t& e) override; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_TEXTENCODER_H_ diff --git a/fxbarcode/datamatrix/BC_X12Encoder.cpp b/fxbarcode/datamatrix/BC_X12Encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a080a71eacab21c031c9303e99f9ba6ec72a7026 --- /dev/null +++ b/fxbarcode/datamatrix/BC_X12Encoder.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 +// Original code is licensed as follows: +/* + * Copyright 2006-2007 Jeremias Maerki. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/datamatrix/BC_X12Encoder.h" + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/datamatrix/BC_C40Encoder.h" +#include "fxbarcode/datamatrix/BC_Encoder.h" +#include "fxbarcode/datamatrix/BC_EncoderContext.h" +#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h" +#include "fxbarcode/datamatrix/BC_SymbolInfo.h" +#include "fxbarcode/utils.h" + +CBC_X12Encoder::CBC_X12Encoder() {} +CBC_X12Encoder::~CBC_X12Encoder() {} +int32_t CBC_X12Encoder::getEncodingMode() { + return X12_ENCODATION; +} +void CBC_X12Encoder::Encode(CBC_EncoderContext& context, int32_t& e) { + WideString buffer; + while (context.hasMoreCharacters()) { + wchar_t c = context.getCurrentChar(); + context.m_pos++; + encodeChar(c, buffer, e); + if (e != BCExceptionNO) { + return; + } + int32_t count = buffer.GetLength(); + if ((count % 3) == 0) { + writeNextTriplet(context, buffer); + int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( + context.m_msg, context.m_pos, getEncodingMode()); + if (newMode != getEncodingMode()) { + context.signalEncoderChange(newMode); + break; + } + } + } + handleEOD(context, buffer, e); +} +void CBC_X12Encoder::handleEOD(CBC_EncoderContext& context, + WideString& buffer, + int32_t& e) { + context.updateSymbolInfo(e); + if (e != BCExceptionNO) { + return; + } + int32_t available = + context.m_symbolInfo->dataCapacity() - context.getCodewordCount(); + int32_t count = buffer.GetLength(); + if (count == 2) { + context.writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH); + context.m_pos -= 2; + context.signalEncoderChange(ASCII_ENCODATION); + } else if (count == 1) { + context.m_pos--; + if (available > 1) { + context.writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH); + } + context.signalEncoderChange(ASCII_ENCODATION); + } +} +int32_t CBC_X12Encoder::encodeChar(wchar_t c, WideString& sb, int32_t& e) { + if (c == '\r') { + sb += (wchar_t)'\0'; + } else if (c == '*') { + sb += (wchar_t)'\1'; + } else if (c == '>') { + sb += (wchar_t)'\2'; + } else if (c == ' ') { + sb += (wchar_t)'\3'; + } else if (c >= '0' && c <= '9') { + sb += (wchar_t)(c - 48 + 4); + } else if (c >= 'A' && c <= 'Z') { + sb += (wchar_t)(c - 65 + 14); + } else { + e = BCExceptionIllegalArgument; + return -1; + } + return 1; +} diff --git a/fxbarcode/datamatrix/BC_X12Encoder.h b/fxbarcode/datamatrix/BC_X12Encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..324b78bdccb770af242f1b52f479b503316a7764 --- /dev/null +++ b/fxbarcode/datamatrix/BC_X12Encoder.h @@ -0,0 +1,26 @@ +// 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 FXBARCODE_DATAMATRIX_BC_X12ENCODER_H_ +#define FXBARCODE_DATAMATRIX_BC_X12ENCODER_H_ + +#include "fxbarcode/datamatrix/BC_C40Encoder.h" + +class CBC_X12Encoder : public CBC_C40Encoder { + public: + CBC_X12Encoder(); + ~CBC_X12Encoder() override; + + // CBC_C40Encoder + int32_t getEncodingMode() override; + void Encode(CBC_EncoderContext& context, int32_t& e) override; + void handleEOD(CBC_EncoderContext& context, + WideString& buffer, + int32_t& e) override; + int32_t encodeChar(wchar_t c, WideString& sb, int32_t& e) override; +}; + +#endif // FXBARCODE_DATAMATRIX_BC_X12ENCODER_H_ diff --git a/fxbarcode/oned/BC_OneDimWriter.cpp b/fxbarcode/oned/BC_OneDimWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0fa23bb91e52bf78675367e81baa11873e25b5a0 --- /dev/null +++ b/fxbarcode/oned/BC_OneDimWriter.cpp @@ -0,0 +1,340 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OneDimWriter.h" + +#include +#include +#include + +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_font.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/cfx_unicodeencodingex.h" +#include "fxbarcode/BC_Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_OneDimWriter::CBC_OneDimWriter() { + m_locTextLoc = BC_TEXT_LOC_BELOWEMBED; + m_bPrintChecksum = true; + m_iDataLenth = 0; + m_bCalcChecksum = false; + m_pFont = nullptr; + m_fFontSize = 10; + m_iFontStyle = 0; + m_fontColor = 0xff000000; + m_iContentLen = 0; + m_bLeftPadding = false; + m_bRightPadding = false; +} + +CBC_OneDimWriter::~CBC_OneDimWriter() {} + +void CBC_OneDimWriter::SetPrintChecksum(bool checksum) { + m_bPrintChecksum = checksum; +} + +void CBC_OneDimWriter::SetDataLength(int32_t length) { + m_iDataLenth = length; +} + +void CBC_OneDimWriter::SetCalcChecksum(bool state) { + m_bCalcChecksum = state; +} + +bool CBC_OneDimWriter::SetFont(CFX_Font* cFont) { + if (!cFont) + return false; + + m_pFont = cFont; + return true; +} + +void CBC_OneDimWriter::SetFontSize(float size) { + m_fFontSize = size; +} + +void CBC_OneDimWriter::SetFontStyle(int32_t style) { + m_iFontStyle = style; +} + +void CBC_OneDimWriter::SetFontColor(FX_ARGB color) { + m_fontColor = color; +} + +wchar_t CBC_OneDimWriter::Upper(wchar_t ch) { + if (ch >= 'a' && ch <= 'z') { + ch = ch - ('a' - 'A'); + } + return ch; +} + +uint8_t* CBC_OneDimWriter::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + outHeight = 1; + return EncodeImpl(contents, outWidth); +} + +uint8_t* CBC_OneDimWriter::Encode(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight) { + return EncodeWithHint(contents, format, outWidth, outHeight, 0); +} + +int32_t CBC_OneDimWriter::AppendPattern(uint8_t* target, + int32_t pos, + const int8_t* pattern, + int32_t patternLength, + int32_t startColor, + int32_t& e) { + if (startColor != 0 && startColor != 1) { + e = BCExceptionValueMustBeEither0or1; + return 0; + } + uint8_t color = (uint8_t)startColor; + int32_t numAdded = 0; + for (int32_t i = 0; i < patternLength; i++) { + for (int32_t j = 0; j < pattern[i]; j++) { + target[pos++] = color; + numAdded += 1; + } + color ^= 1; + } + return numAdded; +} + +void CBC_OneDimWriter::CalcTextInfo(const ByteString& text, + FXTEXT_CHARPOS* charPos, + CFX_Font* cFont, + float geWidth, + int32_t fontSize, + float& charsLen) { + std::unique_ptr encoding = + FX_CreateFontEncodingEx(cFont, FXFM_ENCODING_NONE); + + size_t length = text.GetLength(); + uint32_t* pCharCode = FX_Alloc(uint32_t, text.GetLength()); + float charWidth = 0; + for (size_t j = 0; j < length; j++) { + pCharCode[j] = encoding->CharCodeFromUnicode(text[j]); + int32_t glyp_code = encoding->GlyphFromCharCode(pCharCode[j]); + int32_t glyp_value = cFont->GetGlyphWidth(glyp_code); + float temp = (float)((glyp_value)*fontSize / 1000.0); + charWidth += temp; + } + charsLen = charWidth; + float leftPositon = (float)(geWidth - charsLen) / 2.0f; + if (leftPositon < 0 && geWidth == 0) { + leftPositon = 0; + } + float penX = 0.0; + float penY = (float)abs(cFont->GetDescent()) * (float)fontSize / 1000.0f; + float left = leftPositon; + float top = 0.0; + charPos[0].m_Origin = CFX_PointF(penX + left, penY + top); + charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[0]); + charPos[0].m_FontCharWidth = cFont->GetGlyphWidth(charPos[0].m_GlyphIndex); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + charPos[0].m_ExtGID = charPos[0].m_GlyphIndex; +#endif + penX += (float)(charPos[0].m_FontCharWidth) * (float)fontSize / 1000.0f; + for (size_t i = 1; i < length; i++) { + charPos[i].m_Origin = CFX_PointF(penX + left, penY + top); + charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[i]); + charPos[i].m_FontCharWidth = cFont->GetGlyphWidth(charPos[i].m_GlyphIndex); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + charPos[i].m_ExtGID = charPos[i].m_GlyphIndex; +#endif + penX += (float)(charPos[i].m_FontCharWidth) * (float)fontSize / 1000.0f; + } + FX_Free(pCharCode); +} + +void CBC_OneDimWriter::ShowDeviceChars(CFX_RenderDevice* device, + const CFX_Matrix* matrix, + const ByteString str, + float geWidth, + FXTEXT_CHARPOS* pCharPos, + float locX, + float locY, + int32_t barWidth) { + int32_t iFontSize = (int32_t)fabs(m_fFontSize); + int32_t iTextHeight = iFontSize + 1; + CFX_FloatRect rect((float)locX, (float)locY, (float)(locX + geWidth), + (float)(locY + iTextHeight)); + if (geWidth != m_Width) { + rect.right -= 1; + } + FX_RECT re = matrix->TransformRect(rect).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, (float)locX, + (float)(locY + iFontSize)); + if (matrix) { + affine_matrix.Concat(*matrix); + } + device->DrawNormalText(str.GetLength(), pCharPos, m_pFont.Get(), + static_cast(iFontSize), &affine_matrix, + m_fontColor, FXTEXT_CLEARTYPE); +} + +bool CBC_OneDimWriter::ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) { + if (!device || !m_pFont) + return false; + + ByteString str = FX_UTF8Encode(contents); + int32_t iLen = str.GetLength(); + std::vector charpos(iLen); + float charsLen = 0; + float geWidth = 0; + if (m_locTextLoc == BC_TEXT_LOC_ABOVEEMBED || + m_locTextLoc == BC_TEXT_LOC_BELOWEMBED) { + geWidth = 0; + } else if (m_locTextLoc == BC_TEXT_LOC_ABOVE || + m_locTextLoc == BC_TEXT_LOC_BELOW) { + geWidth = (float)barWidth; + } + int32_t iFontSize = (int32_t)fabs(m_fFontSize); + int32_t iTextHeight = iFontSize + 1; + CalcTextInfo(str, charpos.data(), m_pFont.Get(), geWidth, iFontSize, + charsLen); + if (charsLen < 1) + return true; + + int32_t locX = 0; + int32_t locY = 0; + switch (m_locTextLoc) { + case BC_TEXT_LOC_ABOVEEMBED: + locX = (int32_t)(barWidth - charsLen) / 2; + locY = 0; + geWidth = charsLen; + break; + case BC_TEXT_LOC_ABOVE: + locX = 0; + locY = 0; + geWidth = (float)barWidth; + break; + case BC_TEXT_LOC_BELOWEMBED: + locX = (int32_t)(barWidth - charsLen) / 2; + locY = m_Height - iTextHeight; + geWidth = charsLen; + break; + case BC_TEXT_LOC_BELOW: + default: + locX = 0; + locY = m_Height - iTextHeight; + geWidth = (float)barWidth; + break; + } + ShowDeviceChars(device, matrix, str, geWidth, charpos.data(), (float)locX, + (float)locY, barWidth); + return true; +} + +bool CBC_OneDimWriter::RenderDeviceResult(CFX_RenderDevice* device, + const CFX_Matrix* matrix, + const WideStringView& contents) { + if (m_output.empty()) + return false; + + CFX_GraphStateData stateData; + CFX_PathData path; + path.AppendRect(0, 0, static_cast(m_Width), + static_cast(m_Height)); + device->DrawPath(&path, matrix, &stateData, m_backgroundColor, + m_backgroundColor, FXFILL_ALTERNATE); + CFX_Matrix scaledMatrix(m_outputHScale, 0.0, 0.0, + static_cast(m_Height), 0.0, 0.0); + scaledMatrix.Concat(*matrix); + for (auto& rect : m_output) { + CFX_GraphStateData data; + device->DrawPath(&rect, &scaledMatrix, &data, m_barColor, 0, + FXFILL_WINDING); + } + + return m_locTextLoc == BC_TEXT_LOC_NONE || !contents.Contains(' ') || + ShowChars(contents, device, matrix, m_barWidth, m_multiple); +} + +bool CBC_OneDimWriter::RenderResult(const WideStringView& contents, + uint8_t* code, + int32_t codeLength) { + if (codeLength < 1) + return false; + + m_ModuleHeight = std::max(m_ModuleHeight, 20); + const int32_t codeOldLength = codeLength; + const int32_t leftPadding = m_bLeftPadding ? 7 : 0; + const int32_t rightPadding = m_bRightPadding ? 7 : 0; + codeLength += leftPadding; + codeLength += rightPadding; + m_outputHScale = + m_Width > 0 ? static_cast(m_Width) / static_cast(codeLength) + : 1.0; + m_multiple = 1; + const int32_t outputHeight = 1; + const int32_t outputWidth = codeLength; + m_barWidth = m_Width; + + m_output.clear(); + for (int32_t inputX = 0, outputX = leftPadding * m_multiple; + inputX < codeOldLength; ++inputX, outputX += m_multiple) { + if (code[inputX] != 1) + continue; + + if (outputX >= outputWidth) + return true; + + if (outputX + m_multiple > outputWidth && outputWidth - outputX > 0) { + RenderVerticalBars(outputX, outputWidth - outputX, outputHeight); + return true; + } + + RenderVerticalBars(outputX, m_multiple, outputHeight); + } + return true; +} + +void CBC_OneDimWriter::RenderVerticalBars(int32_t outputX, + int32_t width, + int32_t height) { + for (int i = 0; i < width; ++i) { + float x = outputX + i; + CFX_PathData rect; + rect.AppendRect(x, 0.0f, x + 1, static_cast(height)); + m_output.push_back(rect); + } +} + +WideString CBC_OneDimWriter::RenderTextContents( + const WideStringView& contents) { + return WideString(); +} diff --git a/fxbarcode/oned/BC_OneDimWriter.h b/fxbarcode/oned/BC_OneDimWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..a597d860f664dddd86577784995ddd55dbebb822 --- /dev/null +++ b/fxbarcode/oned/BC_OneDimWriter.h @@ -0,0 +1,103 @@ +// 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 FXBARCODE_ONED_BC_ONEDIMWRITER_H_ +#define FXBARCODE_ONED_BC_ONEDIMWRITER_H_ + +#include +#include + +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxge/cfx_renderdevice.h" +#include "fxbarcode/BC_Library.h" +#include "fxbarcode/BC_Writer.h" + +class CFX_Font; +class CFX_PathData; +class CFX_RenderDevice; + +class CBC_OneDimWriter : public CBC_Writer { + public: + CBC_OneDimWriter(); + ~CBC_OneDimWriter() override; + + virtual bool RenderResult(const WideStringView& contents, + uint8_t* code, + int32_t codeLength); + virtual bool CheckContentValidity(const WideStringView& contents) = 0; + virtual WideString FilterContents(const WideStringView& contents) = 0; + virtual WideString RenderTextContents(const WideStringView& contents); + virtual void SetPrintChecksum(bool checksum); + virtual void SetDataLength(int32_t length); + virtual void SetCalcChecksum(bool state); + virtual void SetFontSize(float size); + virtual void SetFontStyle(int32_t style); + virtual void SetFontColor(FX_ARGB color); + + uint8_t* Encode(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight); + bool RenderDeviceResult(CFX_RenderDevice* device, + const CFX_Matrix* matrix, + const WideStringView& contents); + bool SetFont(CFX_Font* cFont); + + protected: + virtual uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints); + virtual uint8_t* EncodeImpl(const ByteString& contents, + int32_t& outLength) = 0; + virtual void CalcTextInfo(const ByteString& text, + FXTEXT_CHARPOS* charPos, + CFX_Font* cFont, + float geWidth, + int32_t fontSize, + float& charsLen); + virtual bool ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple); + virtual void ShowDeviceChars(CFX_RenderDevice* device, + const CFX_Matrix* matrix, + const ByteString str, + float geWidth, + FXTEXT_CHARPOS* pCharPos, + float locX, + float locY, + int32_t barWidth); + virtual int32_t AppendPattern(uint8_t* target, + int32_t pos, + const int8_t* pattern, + int32_t patternLength, + int32_t startColor, + int32_t& e); + + wchar_t Upper(wchar_t ch); + void RenderVerticalBars(int32_t outputX, int32_t width, int32_t height); + + bool m_bPrintChecksum; + int32_t m_iDataLenth; + bool m_bCalcChecksum; + UnownedPtr m_pFont; + float m_fFontSize; + int32_t m_iFontStyle; + uint32_t m_fontColor; + BC_TEXT_LOC m_locTextLoc; + size_t m_iContentLen; + bool m_bLeftPadding; + bool m_bRightPadding; + std::vector m_output; + int32_t m_barWidth; + int32_t m_multiple; + float m_outputHScale; +}; + +#endif // FXBARCODE_ONED_BC_ONEDIMWRITER_H_ diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter.cpp b/fxbarcode/oned/BC_OnedCodaBarWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42990f7f3a994b5b47a76428ce0396231678c03c --- /dev/null +++ b/fxbarcode/oned/BC_OnedCodaBarWriter.cpp @@ -0,0 +1,207 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OnedCodaBarWriter.h" + +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/common/BC_CommonBitArray.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" +#include "third_party/base/stl_util.h" + +namespace { + +const char kOnedCodaAlphabet[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '-', '$', ':', '/', '.', '+', + 'A', 'B', 'C', 'D', 'T', 'N'}; + +const int8_t kOnedCodaCharacterEncoding[] = { + 0x03, 0x06, 0x09, 0x60, 0x12, 0x42, 0x21, 0x24, 0x30, 0x48, 0x0c, + 0x18, 0x45, 0x51, 0x54, 0x15, 0x1A, 0x29, 0x0B, 0x0E, 0x1A, 0x29}; +static_assert(FX_ArraySize(kOnedCodaCharacterEncoding) == 22, "Wrong size"); +static_assert(FX_ArraySize(kOnedCodaCharacterEncoding) == + FX_ArraySize(kOnedCodaAlphabet), + "Wrong size"); + +const char kStartEndChars[] = {'A', 'B', 'C', 'D', 'T', 'N', '*', 'E', + 'a', 'b', 'c', 'd', 't', 'n', 'e'}; +const char kCOntentChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '-', '$', '/', ':', '+', '.'}; + +} // namespace + +CBC_OnedCodaBarWriter::CBC_OnedCodaBarWriter() + : m_chStart('A'), m_chEnd('B'), m_iWideNarrRatio(2) {} + +CBC_OnedCodaBarWriter::~CBC_OnedCodaBarWriter() {} + +bool CBC_OnedCodaBarWriter::SetStartChar(char start) { + if (!pdfium::ContainsValue(kStartEndChars, start)) + return false; + + m_chStart = start; + return true; +} + +bool CBC_OnedCodaBarWriter::SetEndChar(char end) { + if (!pdfium::ContainsValue(kStartEndChars, end)) + return false; + + m_chEnd = end; + return true; +} + +void CBC_OnedCodaBarWriter::SetDataLength(int32_t length) { + m_iDataLenth = length + 2; +} + +bool CBC_OnedCodaBarWriter::SetTextLocation(BC_TEXT_LOC location) { + if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { + return false; + } + m_locTextLoc = location; + return true; +} + +bool CBC_OnedCodaBarWriter::SetWideNarrowRatio(int8_t ratio) { + if (ratio < 2 || ratio > 3) + return false; + + m_iWideNarrRatio = ratio; + return true; +} + +bool CBC_OnedCodaBarWriter::FindChar(wchar_t ch, bool isContent) { + if (ch > 0x7F) + return false; + + char narrow_ch = static_cast(ch); + return pdfium::ContainsValue(kCOntentChars, narrow_ch) || + (isContent && pdfium::ContainsValue(kStartEndChars, narrow_ch)); +} + +bool CBC_OnedCodaBarWriter::CheckContentValidity( + const WideStringView& contents) { + return std::all_of( + contents.begin(), contents.end(), + [this](const wchar_t& ch) { return this->FindChar(ch, false); }); +} + +WideString CBC_OnedCodaBarWriter::FilterContents( + const WideStringView& contents) { + WideString filtercontents; + wchar_t ch; + for (size_t index = 0; index < contents.GetLength(); index++) { + ch = contents[index]; + if (ch > 175) { + index++; + continue; + } + if (!FindChar(ch, true)) + continue; + filtercontents += ch; + } + return filtercontents; +} + +uint8_t* CBC_OnedCodaBarWriter::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + if (format != BCFORMAT_CODABAR) + return nullptr; + return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight, + hints); +} + +uint8_t* CBC_OnedCodaBarWriter::EncodeImpl(const ByteString& contents, + int32_t& outLength) { + ByteString data = m_chStart + contents + m_chEnd; + m_iContentLen = data.GetLength(); + uint8_t* result = FX_Alloc2D(uint8_t, m_iWideNarrRatio * 7, data.GetLength()); + char ch; + int32_t position = 0; + for (size_t index = 0; index < data.GetLength(); index++) { + ch = data[index]; + if (((ch >= 'a') && (ch <= 'z'))) { + ch = ch - 32; + } + switch (ch) { + case 'T': + ch = 'A'; + break; + case 'N': + ch = 'B'; + break; + case '*': + ch = 'C'; + break; + case 'E': + ch = 'D'; + break; + default: + break; + } + int8_t code = 0; + for (size_t i = 0; i < FX_ArraySize(kOnedCodaAlphabet); i++) { + if (ch == kOnedCodaAlphabet[i]) { + code = kOnedCodaCharacterEncoding[i]; + break; + } + } + uint8_t color = 1; + int32_t counter = 0; + int32_t bit = 0; + while (bit < 7) { + result[position] = color; + position++; + if (((code >> (6 - bit)) & 1) == 0 || counter == m_iWideNarrRatio - 1) { + color = !color; + bit++; + counter = 0; + } else { + counter++; + } + } + if (index < data.GetLength() - 1) { + result[position] = 0; + position++; + } + } + outLength = position; + return result; +} + +WideString CBC_OnedCodaBarWriter::encodedContents( + const WideStringView& contents) { + WideString strStart(static_cast(m_chStart)); + WideString strEnd(static_cast(m_chEnd)); + return strStart + contents + strEnd; +} + +bool CBC_OnedCodaBarWriter::RenderResult(const WideStringView& contents, + uint8_t* code, + int32_t codeLength) { + return CBC_OneDimWriter::RenderResult( + encodedContents(contents).AsStringView(), code, codeLength); +} diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter.h b/fxbarcode/oned/BC_OnedCodaBarWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..ab354ef0a7d782d92b2867001145d0c30ca1db21 --- /dev/null +++ b/fxbarcode/oned/BC_OnedCodaBarWriter.h @@ -0,0 +1,48 @@ +// 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 FXBARCODE_ONED_BC_ONEDCODABARWRITER_H_ +#define FXBARCODE_ONED_BC_ONEDCODABARWRITER_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/BC_Library.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +class CBC_OnedCodaBarWriter : public CBC_OneDimWriter { + public: + CBC_OnedCodaBarWriter(); + ~CBC_OnedCodaBarWriter() override; + + // CBC_OneDimWriter + uint8_t* EncodeImpl(const ByteString& contents, int32_t& outLength) override; + uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) override; + bool RenderResult(const WideStringView& contents, + uint8_t* code, + int32_t codeLength) override; + bool CheckContentValidity(const WideStringView& contents) override; + WideString FilterContents(const WideStringView& contents) override; + void SetDataLength(int32_t length) override; + + virtual bool SetStartChar(char start); + virtual bool SetEndChar(char end); + virtual bool SetTextLocation(BC_TEXT_LOC location); + virtual bool SetWideNarrowRatio(int8_t ratio); + virtual bool FindChar(wchar_t ch, bool isContent); + + WideString encodedContents(const WideStringView& contents); + + private: + char m_chStart; + char m_chEnd; + int8_t m_iWideNarrRatio; +}; + +#endif // FXBARCODE_ONED_BC_ONEDCODABARWRITER_H_ diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp b/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f498449f754a7eea6e4f33dbec9df987d39fdbac --- /dev/null +++ b/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp @@ -0,0 +1,148 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxbarcode/oned/BC_OnedCodaBarWriter.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// 3 wide and 4 narrow modules per delimiter. One space between them. +const int kModulesForDelimiters = (3 * 2 + 4 * 1) * 2 + 1; + +// 2 wide and 5 narrow modules per number, '_' or '$'. 1 space between chars. +const int kModulesPerNumber = 2 * 2 + 5 * 1 + 1; + +// 3 wide and 4 narrow modules per number, '_' or '$'. 1 space between chars. +const int kModulesPerPunctuation = 3 * 2 + 4 * 1 + 1; + +TEST(OnedCodaBarWriterTest, Encode) { + CBC_OnedCodaBarWriter writer; + int32_t width; + int32_t height; + + uint8_t* encoded = writer.Encode("", BCFORMAT_CODABAR, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ(kModulesForDelimiters, width); + const char* expected = + "# ## # # " // A Start + "# # # ##"; // B End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("123", BCFORMAT_CODABAR, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ(kModulesForDelimiters + 3 * kModulesPerNumber, width); + expected = + "# ## # # " // A Start + "# # ## # " // 1 + "# # # ## " // 2 + "## # # # " // 3 + "# # # ##"; // B End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("-$./:+", BCFORMAT_CODABAR, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ(kModulesForDelimiters + 2 * kModulesPerNumber + + 4 * kModulesPerPunctuation, + width); + expected = + "# ## # # " // A Start + "# # ## # " // - + "# ## # # " // $ + "## ## ## # " // . + "## ## # ## " // / + "## # ## ## " // : + "# ## ## ## " // + + "# # # ##"; // B End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("456.987987987/001", BCFORMAT_CODABAR, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ(kModulesForDelimiters + 15 * kModulesPerNumber + + 2 * kModulesPerPunctuation, + width); + expected = + "# ## # # " // A Start + "# ## # # " // 4 + "## # # # " // 5 + "# # # ## " // 6 + "## ## ## # " // . + "## # # # " // 9 + "# ## # # " // 8 + "# # ## # " // 7 + "## # # # " // 9 + "# ## # # " // 8 + "# # ## # " // 7 + "## # # # " // 9 + "# ## # # " // 8 + "# # ## # " // 7 + "## ## # ## " // / + "# # # ## " // 0 + "# # # ## " // 0 + "# # ## # " // 1 + "# # # ##"; // B End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +TEST(OnedCodaBarWriterTest, SetDelimiters) { + CBC_OnedCodaBarWriter writer; + int32_t width; + int32_t height; + + EXPECT_TRUE(writer.SetStartChar('A')); + EXPECT_TRUE(writer.SetStartChar('B')); + EXPECT_TRUE(writer.SetStartChar('C')); + EXPECT_TRUE(writer.SetStartChar('D')); + EXPECT_TRUE(writer.SetStartChar('E')); + EXPECT_TRUE(writer.SetStartChar('N')); + EXPECT_TRUE(writer.SetStartChar('T')); + EXPECT_TRUE(writer.SetStartChar('*')); + EXPECT_FALSE(writer.SetStartChar('V')); + EXPECT_FALSE(writer.SetStartChar('0')); + EXPECT_FALSE(writer.SetStartChar('\0')); + EXPECT_FALSE(writer.SetStartChar('@')); + + EXPECT_TRUE(writer.SetEndChar('A')); + EXPECT_TRUE(writer.SetEndChar('B')); + EXPECT_TRUE(writer.SetEndChar('C')); + EXPECT_TRUE(writer.SetEndChar('D')); + EXPECT_TRUE(writer.SetEndChar('E')); + EXPECT_TRUE(writer.SetEndChar('N')); + EXPECT_TRUE(writer.SetEndChar('T')); + EXPECT_TRUE(writer.SetEndChar('*')); + EXPECT_FALSE(writer.SetEndChar('V')); + EXPECT_FALSE(writer.SetEndChar('0')); + EXPECT_FALSE(writer.SetEndChar('\0')); + EXPECT_FALSE(writer.SetEndChar('@')); + + writer.SetStartChar('N'); + writer.SetEndChar('*'); + + uint8_t* encoded = writer.Encode("987", BCFORMAT_CODABAR, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ(kModulesForDelimiters + 3 * kModulesPerNumber, width); + const char* expected = + "# # # ## " // N (same as B) Start + "## # # # " // 9 + "# ## # # " // 8 + "# # ## # " // 7 + "# # # ##"; // * (same as C) End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +} // namespace diff --git a/fxbarcode/oned/BC_OnedCode128Writer.cpp b/fxbarcode/oned/BC_OnedCode128Writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50d3fb65a64e619b7f88a0838b9571fae3cbd425 --- /dev/null +++ b/fxbarcode/oned/BC_OnedCode128Writer.cpp @@ -0,0 +1,209 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OnedCode128Writer.h" + +#include +#include + +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +namespace { + +constexpr size_t kPatternSize = 7; + +const int8_t CODE_PATTERNS[107][kPatternSize] = { + {2, 1, 2, 2, 2, 2, 0}, {2, 2, 2, 1, 2, 2, 0}, {2, 2, 2, 2, 2, 1, 0}, + {1, 2, 1, 2, 2, 3, 0}, {1, 2, 1, 3, 2, 2, 0}, {1, 3, 1, 2, 2, 2, 0}, + {1, 2, 2, 2, 1, 3, 0}, {1, 2, 2, 3, 1, 2, 0}, {1, 3, 2, 2, 1, 2, 0}, + {2, 2, 1, 2, 1, 3, 0}, {2, 2, 1, 3, 1, 2, 0}, {2, 3, 1, 2, 1, 2, 0}, + {1, 1, 2, 2, 3, 2, 0}, {1, 2, 2, 1, 3, 2, 0}, {1, 2, 2, 2, 3, 1, 0}, + {1, 1, 3, 2, 2, 2, 0}, {1, 2, 3, 1, 2, 2, 0}, {1, 2, 3, 2, 2, 1, 0}, + {2, 2, 3, 2, 1, 1, 0}, {2, 2, 1, 1, 3, 2, 0}, {2, 2, 1, 2, 3, 1, 0}, + {2, 1, 3, 2, 1, 2, 0}, {2, 2, 3, 1, 1, 2, 0}, {3, 1, 2, 1, 3, 1, 0}, + {3, 1, 1, 2, 2, 2, 0}, {3, 2, 1, 1, 2, 2, 0}, {3, 2, 1, 2, 2, 1, 0}, + {3, 1, 2, 2, 1, 2, 0}, {3, 2, 2, 1, 1, 2, 0}, {3, 2, 2, 2, 1, 1, 0}, + {2, 1, 2, 1, 2, 3, 0}, {2, 1, 2, 3, 2, 1, 0}, {2, 3, 2, 1, 2, 1, 0}, + {1, 1, 1, 3, 2, 3, 0}, {1, 3, 1, 1, 2, 3, 0}, {1, 3, 1, 3, 2, 1, 0}, + {1, 1, 2, 3, 1, 3, 0}, {1, 3, 2, 1, 1, 3, 0}, {1, 3, 2, 3, 1, 1, 0}, + {2, 1, 1, 3, 1, 3, 0}, {2, 3, 1, 1, 1, 3, 0}, {2, 3, 1, 3, 1, 1, 0}, + {1, 1, 2, 1, 3, 3, 0}, {1, 1, 2, 3, 3, 1, 0}, {1, 3, 2, 1, 3, 1, 0}, + {1, 1, 3, 1, 2, 3, 0}, {1, 1, 3, 3, 2, 1, 0}, {1, 3, 3, 1, 2, 1, 0}, + {3, 1, 3, 1, 2, 1, 0}, {2, 1, 1, 3, 3, 1, 0}, {2, 3, 1, 1, 3, 1, 0}, + {2, 1, 3, 1, 1, 3, 0}, {2, 1, 3, 3, 1, 1, 0}, {2, 1, 3, 1, 3, 1, 0}, + {3, 1, 1, 1, 2, 3, 0}, {3, 1, 1, 3, 2, 1, 0}, {3, 3, 1, 1, 2, 1, 0}, + {3, 1, 2, 1, 1, 3, 0}, {3, 1, 2, 3, 1, 1, 0}, {3, 3, 2, 1, 1, 1, 0}, + {3, 1, 4, 1, 1, 1, 0}, {2, 2, 1, 4, 1, 1, 0}, {4, 3, 1, 1, 1, 1, 0}, + {1, 1, 1, 2, 2, 4, 0}, {1, 1, 1, 4, 2, 2, 0}, {1, 2, 1, 1, 2, 4, 0}, + {1, 2, 1, 4, 2, 1, 0}, {1, 4, 1, 1, 2, 2, 0}, {1, 4, 1, 2, 2, 1, 0}, + {1, 1, 2, 2, 1, 4, 0}, {1, 1, 2, 4, 1, 2, 0}, {1, 2, 2, 1, 1, 4, 0}, + {1, 2, 2, 4, 1, 1, 0}, {1, 4, 2, 1, 1, 2, 0}, {1, 4, 2, 2, 1, 1, 0}, + {2, 4, 1, 2, 1, 1, 0}, {2, 2, 1, 1, 1, 4, 0}, {4, 1, 3, 1, 1, 1, 0}, + {2, 4, 1, 1, 1, 2, 0}, {1, 3, 4, 1, 1, 1, 0}, {1, 1, 1, 2, 4, 2, 0}, + {1, 2, 1, 1, 4, 2, 0}, {1, 2, 1, 2, 4, 1, 0}, {1, 1, 4, 2, 1, 2, 0}, + {1, 2, 4, 1, 1, 2, 0}, {1, 2, 4, 2, 1, 1, 0}, {4, 1, 1, 2, 1, 2, 0}, + {4, 2, 1, 1, 1, 2, 0}, {4, 2, 1, 2, 1, 1, 0}, {2, 1, 2, 1, 4, 1, 0}, + {2, 1, 4, 1, 2, 1, 0}, {4, 1, 2, 1, 2, 1, 0}, {1, 1, 1, 1, 4, 3, 0}, + {1, 1, 1, 3, 4, 1, 0}, {1, 3, 1, 1, 4, 1, 0}, {1, 1, 4, 1, 1, 3, 0}, + {1, 1, 4, 3, 1, 1, 0}, {4, 1, 1, 1, 1, 3, 0}, {4, 1, 1, 3, 1, 1, 0}, + {1, 1, 3, 1, 4, 1, 0}, {1, 1, 4, 1, 3, 1, 0}, {3, 1, 1, 1, 4, 1, 0}, + {4, 1, 1, 1, 3, 1, 0}, {2, 1, 1, 4, 1, 2, 0}, {2, 1, 1, 2, 1, 4, 0}, + {2, 1, 1, 2, 3, 2, 0}, {2, 3, 3, 1, 1, 1, 2}}; + +const int32_t CODE_START_B = 104; +const int32_t CODE_START_C = 105; +const int32_t CODE_STOP = 106; + +} // namespace + +CBC_OnedCode128Writer::CBC_OnedCode128Writer(BC_TYPE type) + : m_codeFormat(type) { + assert(m_codeFormat == BC_CODE128_B || m_codeFormat == BC_CODE128_C); +} + +CBC_OnedCode128Writer::~CBC_OnedCode128Writer() {} + +bool CBC_OnedCode128Writer::CheckContentValidity( + const WideStringView& contents) { + for (const auto& ch : contents) { + int32_t patternIndex = static_cast(ch); + if (patternIndex < 32 || patternIndex > 126 || patternIndex == 34) + return false; + } + return true; +} + +WideString CBC_OnedCode128Writer::FilterContents( + const WideStringView& contents) { + WideString filterChineseChar; + for (size_t i = 0; i < contents.GetLength(); i++) { + wchar_t ch = contents[i]; + if (ch > 175) { + i++; + continue; + } + filterChineseChar += ch; + } + const wchar_t limit = m_codeFormat == BC_CODE128_B ? 126 : 106; + WideString filtercontents; + for (const auto& ch : filterChineseChar) { + if (ch >= 32 && ch <= limit) + filtercontents += ch; + } + return filtercontents; +} + +bool CBC_OnedCode128Writer::SetTextLocation(BC_TEXT_LOC location) { + if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { + return false; + } + m_locTextLoc = location; + return true; +} + +uint8_t* CBC_OnedCode128Writer::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + if (format != BCFORMAT_CODE_128) + return nullptr; + return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight, + hints); +} + +uint8_t* CBC_OnedCode128Writer::EncodeImpl(const ByteString& contents, + int32_t& outLength) { + if (contents.GetLength() < 1 || contents.GetLength() > 80) + return nullptr; + + std::vector patterns; + int32_t checkSum = 0; + if (m_codeFormat == BC_CODE128_B) + checkSum = Encode128B(contents, &patterns); + else + checkSum = Encode128C(contents, &patterns); + + checkSum %= 103; + patterns.push_back(checkSum); + patterns.push_back(CODE_STOP); + m_iContentLen = contents.GetLength() + 3; + int32_t codeWidth = 0; + for (const auto& patternIndex : patterns) { + const int8_t* pattern = CODE_PATTERNS[patternIndex]; + for (size_t i = 0; i < kPatternSize; ++i) + codeWidth += pattern[i]; + } + outLength = codeWidth; + std::unique_ptr result(FX_Alloc(uint8_t, outLength)); + int32_t pos = 0; + for (size_t i = 0; i < patterns.size(); ++i) { + const int8_t* pattern = CODE_PATTERNS[patterns[i]]; + int32_t e = BCExceptionNO; + pos += AppendPattern(result.get(), pos, pattern, kPatternSize, 1, e); + if (e != BCExceptionNO) + return nullptr; + } + return result.release(); +} + +// static +int32_t CBC_OnedCode128Writer::Encode128B(const ByteString& contents, + std::vector* patterns) { + int32_t checkWeight = 1; + patterns->push_back(CODE_START_B); + int32_t checkSum = CODE_START_B * checkWeight; + for (size_t position = 0; position < contents.GetLength(); position++) { + int32_t patternIndex = contents[position] - ' '; + patterns->push_back(patternIndex); + checkSum += patternIndex * checkWeight++; + } + return checkSum; +} + +// static +int32_t CBC_OnedCode128Writer::Encode128C(const ByteString& contents, + std::vector* patterns) { + int32_t checkWeight = 1; + patterns->push_back(CODE_START_C); + int32_t checkSum = CODE_START_C * checkWeight; + size_t position = 0; + while (position < contents.GetLength()) { + int32_t patternIndex; + char ch = contents[position]; + if (std::isdigit(ch)) { + patternIndex = FXSYS_atoi( + contents.Mid(position, contents.IsValidIndex(position + 1) ? 2 : 1) + .c_str()); + ++position; + if (position < contents.GetLength() && std::isdigit(contents[position])) + ++position; + } else { + patternIndex = static_cast(ch); + ++position; + } + patterns->push_back(patternIndex); + checkSum += patternIndex * checkWeight++; + } + return checkSum; +} diff --git a/fxbarcode/oned/BC_OnedCode128Writer.h b/fxbarcode/oned/BC_OnedCode128Writer.h new file mode 100644 index 0000000000000000000000000000000000000000..3edb65a72a019863831afa8a23b2f5fb1847e800 --- /dev/null +++ b/fxbarcode/oned/BC_OnedCode128Writer.h @@ -0,0 +1,45 @@ +// 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 FXBARCODE_ONED_BC_ONEDCODE128WRITER_H_ +#define FXBARCODE_ONED_BC_ONEDCODE128WRITER_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +class CBC_OnedCode128Writer : public CBC_OneDimWriter { + public: + explicit CBC_OnedCode128Writer(BC_TYPE type); + ~CBC_OnedCode128Writer() override; + + // Exposed for testing. + static int32_t Encode128B(const ByteString& contents, + std::vector* patterns); + static int32_t Encode128C(const ByteString& contents, + std::vector* patterns); + + // CBC_OneDimWriter + uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) override; + uint8_t* EncodeImpl(const ByteString& contents, int32_t& outLength) override; + bool CheckContentValidity(const WideStringView& contents) override; + WideString FilterContents(const WideStringView& contents) override; + + bool SetTextLocation(BC_TEXT_LOC location); + + BC_TYPE GetType() const { return m_codeFormat; } + + private: + const BC_TYPE m_codeFormat; +}; + +#endif // FXBARCODE_ONED_BC_ONEDCODE128WRITER_H_ diff --git a/fxbarcode/oned/BC_OnedCode128Writer_unittest.cpp b/fxbarcode/oned/BC_OnedCode128Writer_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbff8041ccd306ef47b7d6239a4dc19808d90757 --- /dev/null +++ b/fxbarcode/oned/BC_OnedCode128Writer_unittest.cpp @@ -0,0 +1,127 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxbarcode/oned/BC_OnedCode128Writer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +struct TestCase { + const char* input; + int32_t checksum; + int32_t patterns[7]; + size_t num_patterns; +}; + +TEST(OnedCode128WriterTest, Encode128B) { + char buf[100]; + TestCase kTestCases[] = { + {"", 104, {104}, 1}, + {"a", 169, {104, 65}, 2}, + {"1", 121, {104, 17}, 2}, + {"a1", 203, {104, 65, 17}, 3}, + {"ab", 301, {104, 65, 66}, 3}, + {"12", 157, {104, 17, 18}, 3}, + {"abc", 502, {104, 65, 66, 67}, 4}, + {"123", 214, {104, 17, 18, 19}, 4}, + {"abc123", 774, {104, 65, 66, 67, 17, 18, 19}, 7}, + {"ABC123", 582, {104, 33, 34, 35, 17, 18, 19}, 7}, + {"321ABC", 722, {104, 19, 18, 17, 33, 34, 35}, 7}, + {"XYZ", 448, {104, 56, 57, 58}, 4}, + }; + for (size_t i = 0; i < FX_ArraySize(kTestCases); ++i) { + FXSYS_snprintf(buf, sizeof(buf) - 1, "Test case %zu", i); + SCOPED_TRACE(buf); + const TestCase& test_case = kTestCases[i]; + std::vector patterns; + int32_t checksum = + CBC_OnedCode128Writer::Encode128B(test_case.input, &patterns); + EXPECT_EQ(test_case.checksum, checksum); + ASSERT_EQ(test_case.num_patterns, patterns.size()); + for (size_t j = 0; j < patterns.size(); ++j) { + FXSYS_snprintf(buf, sizeof(buf) - 1, "Comparison %zu", j); + SCOPED_TRACE(buf); + EXPECT_EQ(test_case.patterns[j], patterns[j]); + } + } +} + +TEST(OnedCode128WriterTest, Encode128C) { + char buf[100]; + TestCase kTestCases[] = { + {"", 105, {105}, 1}, + {"a", 202, {105, 97}, 2}, + {"1", 106, {105, 1}, 2}, + {"a1", 204, {105, 97, 1}, 3}, + {"ab", 398, {105, 97, 98}, 3}, + {"12", 117, {105, 12}, 2}, + {"abc", 695, {105, 97, 98, 99}, 4}, + {"123", 123, {105, 12, 3}, 3}, + {"abc123", 758, {105, 97, 98, 99, 12, 3}, 6}, + {"ABC123", 566, {105, 65, 66, 67, 12, 3}, 6}, + {"321ABC", 933, {105, 32, 1, 65, 66, 67}, 6}, + {"XYZ", 641, {105, 88, 89, 90}, 4}, + }; + for (size_t i = 0; i < FX_ArraySize(kTestCases); ++i) { + FXSYS_snprintf(buf, sizeof(buf) - 1, "Test case %zu", i); + SCOPED_TRACE(buf); + const TestCase& test_case = kTestCases[i]; + std::vector patterns; + int32_t checksum = + CBC_OnedCode128Writer::Encode128C(test_case.input, &patterns); + EXPECT_EQ(test_case.checksum, checksum); + ASSERT_EQ(test_case.num_patterns, patterns.size()); + for (size_t j = 0; j < patterns.size(); ++j) { + FXSYS_snprintf(buf, sizeof(buf) - 1, "Comparison %zu", j); + SCOPED_TRACE(buf); + EXPECT_EQ(test_case.patterns[j], patterns[j]); + } + } +} + +TEST(OnedCode128WriterTest, CheckContentValidity) { + { + CBC_OnedCode128Writer writer(BC_CODE128_B); + EXPECT_TRUE(writer.CheckContentValidity(L"")); + EXPECT_TRUE(writer.CheckContentValidity(L"foo")); + EXPECT_TRUE(writer.CheckContentValidity(L"xyz")); + EXPECT_FALSE(writer.CheckContentValidity(L"\"")); + EXPECT_FALSE(writer.CheckContentValidity(L"f\x10oo")); + EXPECT_FALSE(writer.CheckContentValidity(L"bar\x7F")); + EXPECT_FALSE(writer.CheckContentValidity(L"qux\x88")); + } + { + CBC_OnedCode128Writer writer(BC_CODE128_C); + EXPECT_TRUE(writer.CheckContentValidity(L"")); + EXPECT_TRUE(writer.CheckContentValidity(L"foo")); + EXPECT_TRUE(writer.CheckContentValidity(L"xyz")); + EXPECT_FALSE(writer.CheckContentValidity(L"\"")); + EXPECT_FALSE(writer.CheckContentValidity(L"f\x10oo")); + EXPECT_FALSE(writer.CheckContentValidity(L"bar\x7F")); + EXPECT_FALSE(writer.CheckContentValidity(L"qux\x88")); + } +} + +TEST(OnedCode128WriterTest, FilterContents) { + { + CBC_OnedCode128Writer writer(BC_CODE128_B); + EXPECT_STREQ(L"", writer.FilterContents(L"").c_str()); + EXPECT_STREQ(L"foo", writer.FilterContents(L"foo\x10").c_str()); + EXPECT_STREQ(L"fool", writer.FilterContents(L"foo\x10l").c_str()); + EXPECT_STREQ(L"foo", writer.FilterContents(L"foo\x10\x7F").c_str()); + EXPECT_STREQ(L"foo", writer.FilterContents(L"foo\x10\x7F\x88").c_str()); + EXPECT_STREQ(L"bar", writer.FilterContents(L"bar\x10\x7F\x88").c_str()); + } + { + CBC_OnedCode128Writer writer(BC_CODE128_C); + EXPECT_STREQ(L"", writer.FilterContents(L"").c_str()); + EXPECT_STREQ(L"f", writer.FilterContents(L"foo\x10").c_str()); + EXPECT_STREQ(L"f", writer.FilterContents(L"foo\x10l").c_str()); + EXPECT_STREQ(L"f", writer.FilterContents(L"foo\x10\x7F").c_str()); + EXPECT_STREQ(L"f", writer.FilterContents(L"foo\x10\x7F\x88").c_str()); + EXPECT_STREQ(L"ba", writer.FilterContents(L"bar\x10\x7F\x88").c_str()); + } +} + +} // namespace diff --git a/fxbarcode/oned/BC_OnedCode39Writer.cpp b/fxbarcode/oned/BC_OnedCode39Writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f04dc195eace53d4d7fa0d3d4c2b6f88387024f6 --- /dev/null +++ b/fxbarcode/oned/BC_OnedCode39Writer.cpp @@ -0,0 +1,258 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OnedCode39Writer.h" + +#include + +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +namespace { + +const char kOnedCode39Alphabet[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', '-', '.', ' ', '*', '$', '/', '+', '%'}; +constexpr size_t kOnedCode39AlphabetLen = FX_ArraySize(kOnedCode39Alphabet); + +const char kOnedCode39Checksum[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', '-', '.', ' ', '$', '/', '+', '%'}; +static_assert(FX_ArraySize(kOnedCode39Checksum) == 43, "Wrong size"); + +const int16_t kOnedCode39CharacterEncoding[] = { + 0x0034, 0x0121, 0x0061, 0x0160, 0x0031, 0x0130, 0x0070, 0x0025, 0x0124, + 0x0064, 0x0109, 0x0049, 0x0148, 0x0019, 0x0118, 0x0058, 0x000D, 0x010C, + 0x004C, 0x001C, 0x0103, 0x0043, 0x0142, 0x0013, 0x0112, 0x0052, 0x0007, + 0x0106, 0x0046, 0x0016, 0x0181, 0x00C1, 0x01C0, 0x0091, 0x0190, 0x00D0, + 0x0085, 0x0184, 0x00C4, 0x0094, 0x00A8, 0x00A2, 0x008A, 0x002A}; +static_assert(FX_ArraySize(kOnedCode39CharacterEncoding) == 44, "Wrong size"); + +} // namespace + +CBC_OnedCode39Writer::CBC_OnedCode39Writer() : m_iWideNarrRatio(3) {} + +CBC_OnedCode39Writer::~CBC_OnedCode39Writer() {} + +bool CBC_OnedCode39Writer::CheckContentValidity( + const WideStringView& contents) { + for (size_t i = 0; i < contents.GetLength(); i++) { + wchar_t ch = contents[i]; + if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || + ch == L'-' || ch == L'.' || ch == L' ' || ch == L'*' || ch == L'$' || + ch == L'/' || ch == L'+' || ch == L'%') { + continue; + } + return false; + } + return true; +} + +WideString CBC_OnedCode39Writer::FilterContents( + const WideStringView& contents) { + WideString filtercontents; + for (size_t i = 0; i < contents.GetLength(); i++) { + wchar_t ch = contents[i]; + if (ch == L'*' && (i == 0 || i == contents.GetLength() - 1)) { + continue; + } + if (ch > 175) { + i++; + continue; + } + ch = Upper(ch); + if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || + ch == L'-' || ch == L'.' || ch == L' ' || ch == L'*' || ch == L'$' || + ch == L'/' || ch == L'+' || ch == L'%') { + filtercontents += ch; + } + } + return filtercontents; +} + +WideString CBC_OnedCode39Writer::RenderTextContents( + const WideStringView& contents) { + WideString renderContents; + for (size_t i = 0; i < contents.GetLength(); i++) { + wchar_t ch = contents[i]; + if (ch == L'*' && (i == 0 || i == contents.GetLength() - 1)) { + continue; + } + if (ch > 175) { + i++; + continue; + } + if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'Z') || + (ch >= L'a' && ch <= L'z') || ch == L'-' || ch == L'.' || ch == L' ' || + ch == L'*' || ch == L'$' || ch == L'/' || ch == L'+' || ch == L'%') { + renderContents += ch; + } + } + return renderContents; +} + +bool CBC_OnedCode39Writer::SetTextLocation(BC_TEXT_LOC location) { + if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { + return false; + } + m_locTextLoc = location; + return true; +} +bool CBC_OnedCode39Writer::SetWideNarrowRatio(int8_t ratio) { + if (ratio < 2 || ratio > 3) + return false; + + m_iWideNarrRatio = ratio; + return true; +} + +uint8_t* CBC_OnedCode39Writer::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + if (format != BCFORMAT_CODE_39) + return nullptr; + return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight, + hints); +} + +void CBC_OnedCode39Writer::ToIntArray(int16_t a, int8_t* toReturn) { + for (int32_t i = 0; i < 9; i++) { + toReturn[i] = (a & (1 << i)) == 0 ? 1 : m_iWideNarrRatio; + } +} + +char CBC_OnedCode39Writer::CalcCheckSum(const ByteString& contents) { + if (contents.GetLength() > 80) + return '*'; + + int32_t checksum = 0; + for (const auto& c : contents) { + size_t j = 0; + for (; j < kOnedCode39AlphabetLen; j++) { + if (kOnedCode39Alphabet[j] == c) { + if (c != '*') + checksum += j; + break; + } + } + if (j >= kOnedCode39AlphabetLen) + return '*'; + } + return kOnedCode39Checksum[checksum % FX_ArraySize(kOnedCode39Checksum)]; +} + +uint8_t* CBC_OnedCode39Writer::EncodeImpl(const ByteString& contents, + int32_t& outlength) { + char checksum = CalcCheckSum(contents); + if (checksum == '*') + return nullptr; + + int8_t widths[9] = {0}; + int32_t wideStrideNum = 3; + int32_t narrStrideNum = 9 - wideStrideNum; + ByteString encodedContents = contents; + if (m_bCalcChecksum) + encodedContents += checksum; + m_iContentLen = encodedContents.GetLength(); + int32_t codeWidth = (wideStrideNum * m_iWideNarrRatio + narrStrideNum) * 2 + + 1 + m_iContentLen; + for (size_t j = 0; j < m_iContentLen; j++) { + for (size_t i = 0; i < kOnedCode39AlphabetLen; i++) { + if (kOnedCode39Alphabet[i] != encodedContents[j]) + continue; + + ToIntArray(kOnedCode39CharacterEncoding[i], widths); + for (size_t k = 0; k < 9; k++) + codeWidth += widths[k]; + } + } + outlength = codeWidth; + std::unique_ptr result(FX_Alloc(uint8_t, codeWidth)); + ToIntArray(kOnedCode39CharacterEncoding[39], widths); + int32_t e = BCExceptionNO; + int32_t pos = AppendPattern(result.get(), 0, widths, 9, 1, e); + if (e != BCExceptionNO) + return nullptr; + + int8_t narrowWhite[] = {1}; + pos += AppendPattern(result.get(), pos, narrowWhite, 1, 0, e); + if (e != BCExceptionNO) + return nullptr; + + for (int32_t l = m_iContentLen - 1; l >= 0; l--) { + for (size_t i = 0; i < kOnedCode39AlphabetLen; i++) { + if (kOnedCode39Alphabet[i] != encodedContents[l]) + continue; + + ToIntArray(kOnedCode39CharacterEncoding[i], widths); + pos += AppendPattern(result.get(), pos, widths, 9, 1, e); + if (e != BCExceptionNO) + return nullptr; + } + pos += AppendPattern(result.get(), pos, narrowWhite, 1, 0, e); + if (e != BCExceptionNO) + return nullptr; + } + ToIntArray(kOnedCode39CharacterEncoding[39], widths); + pos += AppendPattern(result.get(), pos, widths, 9, 1, e); + if (e != BCExceptionNO) + return nullptr; + + auto* result_ptr = result.get(); + for (int32_t i = 0; i < codeWidth / 2; i++) { + result_ptr[i] ^= result_ptr[codeWidth - 1 - i]; + result_ptr[codeWidth - 1 - i] ^= result_ptr[i]; + result_ptr[i] ^= result_ptr[codeWidth - 1 - i]; + } + return result.release(); +} + +bool CBC_OnedCode39Writer::encodedContents(const WideStringView& contents, + WideString* result) { + *result = WideString(contents); + if (m_bCalcChecksum && m_bPrintChecksum) { + WideString checksumContent = FilterContents(contents); + ByteString str = checksumContent.UTF8Encode(); + char checksum; + checksum = CalcCheckSum(str); + if (checksum == '*') + return false; + str += checksum; + *result += checksum; + } + return true; +} + +bool CBC_OnedCode39Writer::RenderResult(const WideStringView& contents, + uint8_t* code, + int32_t codeLength) { + WideString encodedCon; + if (!encodedContents(contents, &encodedCon)) + return false; + return CBC_OneDimWriter::RenderResult(encodedCon.AsStringView(), code, + codeLength); +} diff --git a/fxbarcode/oned/BC_OnedCode39Writer.h b/fxbarcode/oned/BC_OnedCode39Writer.h new file mode 100644 index 0000000000000000000000000000000000000000..90611c005dced5667af76a2f58275255a209b38e --- /dev/null +++ b/fxbarcode/oned/BC_OnedCode39Writer.h @@ -0,0 +1,44 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_ONED_BC_ONEDCODE39WRITER_H_ +#define FXBARCODE_ONED_BC_ONEDCODE39WRITER_H_ + +#include "fxbarcode/BC_Library.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +class CBC_OnedCode39Writer : public CBC_OneDimWriter { + public: + CBC_OnedCode39Writer(); + ~CBC_OnedCode39Writer() override; + + // CBC_OneDimWriter + uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) override; + uint8_t* EncodeImpl(const ByteString& contents, int32_t& outLength) override; + bool RenderResult(const WideStringView& contents, + uint8_t* code, + int32_t codeLength) override; + bool CheckContentValidity(const WideStringView& contents) override; + WideString FilterContents(const WideStringView& contents) override; + WideString RenderTextContents(const WideStringView& contents) override; + + virtual bool SetTextLocation(BC_TEXT_LOC loction); + virtual bool SetWideNarrowRatio(int8_t ratio); + + bool encodedContents(const WideStringView& contents, WideString* result); + + private: + void ToIntArray(int16_t a, int8_t* toReturn); + char CalcCheckSum(const ByteString& contents); + + int8_t m_iWideNarrRatio; +}; + +#endif // FXBARCODE_ONED_BC_ONEDCODE39WRITER_H_ diff --git a/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp b/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27a0410637365094a8024647d946900f250f4030 --- /dev/null +++ b/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp @@ -0,0 +1,184 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "fxbarcode/oned/BC_OnedCode39Writer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// 3 wide and 6 narrow modules per char. 1 space between chars. +const int MODULES_PER_CHAR = 3 * 3 + 6 * 1 + 1; + +// '*' is added as the first and last char. +const int DELIMITER_CHARS = 2; + +// Last char may serve as checksum. +const int CHECKSUM_CHARS = 1; + +TEST(OnedCode39WriterTest, SetWideNarrowRatio) { + // Code 39 barcodes encode strings of any size into modules in a + // unidimensional disposition. + // Each module is either: a narrow bar, a narrow space, a wide + // bar, or a wide space. Accepted wide-to-narrow ratios are between 2 and 3. + // This writer in particular only takes integer ratios, so it's either 2 or 3. + CBC_OnedCode39Writer writer; + EXPECT_FALSE(writer.SetWideNarrowRatio(0)); + EXPECT_FALSE(writer.SetWideNarrowRatio(1)); + EXPECT_TRUE(writer.SetWideNarrowRatio(2)); + EXPECT_TRUE(writer.SetWideNarrowRatio(3)); + EXPECT_FALSE(writer.SetWideNarrowRatio(4)); + EXPECT_FALSE(writer.SetWideNarrowRatio(100)); + + writer.SetWideNarrowRatio(3); + + int32_t width; + int32_t height; + uint8_t* encoded; + const char* expected; + + encoded = writer.Encode("PDFIUM", BCFORMAT_CODE_39, width, height); + expected = + "# # ### ### # " // * Start + "# ### ### # # " // P + "# # ### # ### " // D + "# ### ### # # " // F + "# ### # ### # " // I + "### # # # ### " // U + "### ### # # # " // M + "# # ### ### #"; // * End + FX_Free(encoded); + + writer.SetWideNarrowRatio(2); + + encoded = writer.Encode("PDFIUM", BCFORMAT_CODE_39, width, height); + expected = + "# # ## ## # " // * Start + "# ## ## # # " // P + "# # ## # ## " // D + "# ## ## # # " // F + "# ## # ## # " // I + "## # # # ## " // U + "## ## # # # " // M + "# # ## ## #"; // * End + FX_Free(encoded); +} + +TEST(OnedCode39WriterTest, Encode) { + CBC_OnedCode39Writer writer; + int32_t width; + int32_t height; + uint8_t* encoded; + const char* expected; + + encoded = writer.Encode("", BCFORMAT_CODE_39, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ((0 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width); + expected = + "# # ### ### # " // * Start + "# # ### ### #"; // * End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("123", BCFORMAT_CODE_39, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ((3 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width); + expected = + "# # ### ### # " // * Start + "### # # # ### " // 1 + "# ### # # ### " // 2 + "### ### # # # " // 3 + "# # ### ### #"; // * End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("PDFIUM", BCFORMAT_CODE_39, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ((6 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width); + expected = + "# # ### ### # " // * Start + "# ### ### # # " // P + "# # ### # ### " // D + "# ### ### # # " // F + "# ### # ### # " // I + "### # # # ### " // U + "### ### # # # " // M + "# # ### ### #"; // * End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("A -$%./+Z", BCFORMAT_CODE_39, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ((9 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width); + expected = + "# # ### ### # " // * Start + "### # # # ### " // A + "# ### # ### # " // Space + "# # # ### ### " // - + "# # # # # " // $ + "# # # # # " // % + "### # # ### # " // . + "# # # # # " // / + "# # # # # " // + + "# ### ### # # " // Z + "# # ### ### #"; // * End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +TEST(OnedCode39WriterTest, Checksum) { + CBC_OnedCode39Writer writer; + int32_t width; + int32_t height; + uint8_t* encoded; + const char* expected; + + writer.SetCalcChecksum(true); + + encoded = writer.Encode("123", BCFORMAT_CODE_39, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ((3 + CHECKSUM_CHARS + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, + width); + expected = + "# # ### ### # " // * Start + "### # # # ### " // 1 (1) + "# ### # # ### " // 2 (2) + "### ### # # # " // 3 (3) + "# ### ### # # " // 6 (6 = (1 + 2 + 3) % 43) + "# # ### ### #"; // * End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("PDFIUM", BCFORMAT_CODE_39, width, height); + EXPECT_EQ(1, height); + EXPECT_EQ((6 + CHECKSUM_CHARS + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, + width); + expected = + "# # ### ### # " // * Start + "# ### ### # # " // P (25) + "# # ### # ### " // D (13) + "# ### ### # # " // F (15) + "# ### # ### # " // I (18) + "### # # # ### " // U (30) + "### ### # # # " // M (22) + "### # # ### # " // . (37 = (25 + 13 + 15 + 18 + 30 + 22) % 43) + "# # ### ### #"; // * End + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +} // namespace diff --git a/fxbarcode/oned/BC_OnedEAN13Writer.cpp b/fxbarcode/oned/BC_OnedEAN13Writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6315bcdbb40e2d53038cb501906631a4b9d134f --- /dev/null +++ b/fxbarcode/oned/BC_OnedEAN13Writer.cpp @@ -0,0 +1,224 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OnedEAN13Writer.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" +#include "fxbarcode/oned/BC_OnedEANChecksum.h" + +namespace { + +const int8_t kFirstDigitEncodings[10] = {0x00, 0x0B, 0x0D, 0xE, 0x13, + 0x19, 0x1C, 0x15, 0x16, 0x1A}; +const int8_t kOnedEAN13StartPattern[3] = {1, 1, 1}; +const int8_t kOnedEAN13MiddlePattern[5] = {1, 1, 1, 1, 1}; +const int8_t kOnedEAN13LPattern[10][4] = { + {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, + {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}}; +const int8_t L_AND_G_PATTERNS[20][4] = { + {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, + {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}, + {1, 1, 2, 3}, {1, 2, 2, 2}, {2, 2, 1, 2}, {1, 1, 4, 1}, {2, 3, 1, 1}, + {1, 3, 2, 1}, {4, 1, 1, 1}, {2, 1, 3, 1}, {3, 1, 2, 1}, {2, 1, 1, 3}}; + +} // namespace + +CBC_OnedEAN13Writer::CBC_OnedEAN13Writer() { + m_bLeftPadding = true; + m_codeWidth = 3 + (7 * 6) + 5 + (7 * 6) + 3; +} +CBC_OnedEAN13Writer::~CBC_OnedEAN13Writer() {} + +bool CBC_OnedEAN13Writer::CheckContentValidity(const WideStringView& contents) { + return std::all_of(contents.begin(), contents.end(), std::iswdigit); +} + +WideString CBC_OnedEAN13Writer::FilterContents(const WideStringView& contents) { + WideString filtercontents; + wchar_t ch; + for (size_t i = 0; i < contents.GetLength(); i++) { + ch = contents[i]; + if (ch > 175) { + i++; + continue; + } + if (ch >= '0' && ch <= '9') { + filtercontents += ch; + } + } + return filtercontents; +} + +int32_t CBC_OnedEAN13Writer::CalcChecksum(const ByteString& contents) { + return EANCalcChecksum(contents); +} + +uint8_t* CBC_OnedEAN13Writer::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + if (format != BCFORMAT_EAN_13) + return nullptr; + return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight, + hints); +} + +uint8_t* CBC_OnedEAN13Writer::EncodeImpl(const ByteString& contents, + int32_t& outLength) { + if (contents.GetLength() != 13) + return nullptr; + + m_iDataLenth = 13; + int32_t firstDigit = FXSYS_DecimalCharToInt(contents.First()); + int32_t parities = kFirstDigitEncodings[firstDigit]; + outLength = m_codeWidth; + std::unique_ptr result( + FX_Alloc(uint8_t, m_codeWidth)); + int32_t pos = 0; + int32_t e = BCExceptionNO; + pos += AppendPattern(result.get(), pos, kOnedEAN13StartPattern, 3, 1, e); + if (e != BCExceptionNO) + return nullptr; + + int32_t i = 0; + for (i = 1; i <= 6; i++) { + int32_t digit = FXSYS_DecimalCharToInt(contents[i]); + if ((parities >> (6 - i) & 1) == 1) { + digit += 10; + } + pos += AppendPattern(result.get(), pos, L_AND_G_PATTERNS[digit], 4, 0, e); + if (e != BCExceptionNO) + return nullptr; + } + pos += AppendPattern(result.get(), pos, kOnedEAN13MiddlePattern, 5, 0, e); + if (e != BCExceptionNO) + return nullptr; + + for (i = 7; i <= 12; i++) { + int32_t digit = FXSYS_DecimalCharToInt(contents[i]); + pos += AppendPattern(result.get(), pos, kOnedEAN13LPattern[digit], 4, 1, e); + if (e != BCExceptionNO) + return nullptr; + } + pos += AppendPattern(result.get(), pos, kOnedEAN13StartPattern, 3, 1, e); + if (e != BCExceptionNO) + return nullptr; + return result.release(); +} + +bool CBC_OnedEAN13Writer::ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) { + if (!device) + return false; + + int32_t leftPadding = 7 * multiple; + int32_t leftPosition = 3 * multiple + leftPadding; + ByteString str = FX_UTF8Encode(contents); + int32_t iLen = str.GetLength(); + std::vector charpos(iLen); + int32_t iFontSize = (int32_t)fabs(m_fFontSize); + int32_t iTextHeight = iFontSize + 1; + ByteString tempStr = str.Mid(1, 6); + int32_t strWidth = multiple * 42; + + CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect((float)leftPosition, (float)(m_Height - iTextHeight), + (float)(leftPosition + strWidth - 0.5), (float)m_Height); + matr.Concat(*matrix); + FX_RECT re = matr.TransformRect(rect).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + CFX_FloatRect rect1( + (float)(leftPosition + 47 * multiple), (float)(m_Height - iTextHeight), + (float)(leftPosition + 47 * multiple + strWidth - 0.5), (float)m_Height); + CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + matr1.Concat(*matrix); + re = matr1.TransformRect(rect1).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + int32_t strWidth1 = multiple * 7; + CFX_Matrix matr2(m_outputHScale, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); + CFX_FloatRect rect2(0.0f, (float)(m_Height - iTextHeight), + (float)strWidth1 - 0.5f, (float)m_Height); + matr2.Concat(*matrix); + re = matr2.TransformRect(rect2).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + + float blank = 0.0; + iLen = tempStr.GetLength(); + strWidth = (int32_t)(strWidth * m_outputHScale); + + CalcTextInfo(tempStr, &charpos[1], m_pFont.Get(), (float)strWidth, iFontSize, + blank); + { + CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, + (float)leftPosition * m_outputHScale, + (float)(m_Height - iTextHeight) + iFontSize); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, &charpos[1], m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + tempStr = str.Mid(7, 6); + iLen = tempStr.GetLength(); + CalcTextInfo(tempStr, &charpos[7], m_pFont.Get(), (float)strWidth, iFontSize, + blank); + { + CFX_Matrix affine_matrix1( + 1.0, 0.0, 0.0, -1.0, + (float)(leftPosition + 47 * multiple) * m_outputHScale, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, &charpos[7], m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + tempStr = str.Left(1); + iLen = tempStr.GetLength(); + strWidth = multiple * 7; + strWidth = (int32_t)(strWidth * m_outputHScale); + + CalcTextInfo(tempStr, charpos.data(), m_pFont.Get(), (float)strWidth, + iFontSize, blank); + { + CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, 0.0, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, charpos.data(), m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + return true; +} diff --git a/fxbarcode/oned/BC_OnedEAN13Writer.h b/fxbarcode/oned/BC_OnedEAN13Writer.h new file mode 100644 index 0000000000000000000000000000000000000000..c874610a6426cfabbeff5dd06a622bb5dbebcc79 --- /dev/null +++ b/fxbarcode/oned/BC_OnedEAN13Writer.h @@ -0,0 +1,45 @@ +// 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 FXBARCODE_ONED_BC_ONEDEAN13WRITER_H_ +#define FXBARCODE_ONED_BC_ONEDEAN13WRITER_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +class CFX_DIBitmap; +class CFX_RenderDevice; + +class CBC_OnedEAN13Writer : public CBC_OneDimWriter { + public: + CBC_OnedEAN13Writer(); + ~CBC_OnedEAN13Writer() override; + + // CBC_OneDimWriter + uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) override; + uint8_t* EncodeImpl(const ByteString& contents, int32_t& outLength) override; + bool CheckContentValidity(const WideStringView& contents) override; + WideString FilterContents(const WideStringView& contents) override; + + int32_t CalcChecksum(const ByteString& contents); + + protected: + bool ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) override; + + private: + int32_t m_codeWidth; +}; + +#endif // FXBARCODE_ONED_BC_ONEDEAN13WRITER_H_ diff --git a/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp b/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..932e1f42c8514ff2712a89717f28db41936cf7ec --- /dev/null +++ b/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp @@ -0,0 +1,98 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxbarcode/oned/BC_OnedEAN13Writer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +TEST(OnedEAN13WriterTest, Encode) { + CBC_OnedEAN13Writer writer; + int32_t width; + int32_t height; + uint8_t* encoded; + const char* expected; + + // EAN-13 barcodes encode 13-digit numbers into 95 modules in a unidimensional + // disposition. + encoded = writer.Encode("", BCFORMAT_EAN_13, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("123", BCFORMAT_EAN_13, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("123456789012", BCFORMAT_EAN_13, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("12345678901234", BCFORMAT_EAN_13, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("1234567890128", BCFORMAT_EAN_13, width, height); + EXPECT_NE(nullptr, encoded); + EXPECT_EQ(1, height); + EXPECT_EQ(95, width); + + expected = + "# #" // Start + // 1 implicit by LLGLGG in next 6 digits + " # ##" // 2 L + " #### #" // 3 L + " ### #" // 4 G + " ## #" // 5 L + " # #" // 6 G + " # #" // 7 G + " # # " // Middle + "# # " // 8 R + "### # " // 9 R + "### # " // 0 R + "## ## " // 1 R + "## ## " // 2 R + "# # " // 8 R + "# #"; // End + for (int i = 0; i < 95; i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("7776665554440", BCFORMAT_EAN_13, width, height); + EXPECT_NE(nullptr, encoded); + EXPECT_EQ(1, height); + EXPECT_EQ(95, width); + + expected = + "# #" // Start + // 7 implicit by LGLGLG in next 6 digits + " ### ##" // 7 L + " # #" // 7 G + " # ####" // 6 L + " # #" // 6 G + " # ####" // 6 L + " ### #" // 5 G + " # # " // Middle + "# ### " // 5 R + "# ### " // 5 R + "# ### " // 4 R + "# ### " // 4 R + "# ### " // 4 R + "### # " // 0 R + "# #"; // End + for (int i = 0; i < 95; i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +TEST(OnedEAN13WriterTest, Checksum) { + CBC_OnedEAN13Writer writer; + EXPECT_EQ(0, writer.CalcChecksum("")); + EXPECT_EQ(6, writer.CalcChecksum("123")); + EXPECT_EQ(8, writer.CalcChecksum("123456789012")); + EXPECT_EQ(0, writer.CalcChecksum("777666555444")); +} + +} // namespace diff --git a/fxbarcode/oned/BC_OnedEAN8Writer.cpp b/fxbarcode/oned/BC_OnedEAN8Writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..988528ed09a787da78963c3c8adc6f2318afaf00 --- /dev/null +++ b/fxbarcode/oned/BC_OnedEAN8Writer.cpp @@ -0,0 +1,200 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OnedEAN8Writer.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" +#include "fxbarcode/oned/BC_OnedEANChecksum.h" + +namespace { + +const int8_t kOnedEAN8StartPattern[3] = {1, 1, 1}; +const int8_t kOnedEAN8MiddlePattern[5] = {1, 1, 1, 1, 1}; +const int8_t kOnedEAN8LPattern[10][4] = { + {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, + {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}}; + +} // namespace + +CBC_OnedEAN8Writer::CBC_OnedEAN8Writer() { + m_iDataLenth = 8; + m_codeWidth = 3 + (7 * 4) + 5 + (7 * 4) + 3; +} + +CBC_OnedEAN8Writer::~CBC_OnedEAN8Writer() {} + +void CBC_OnedEAN8Writer::SetDataLength(int32_t length) { + m_iDataLenth = 8; +} + +bool CBC_OnedEAN8Writer::SetTextLocation(BC_TEXT_LOC location) { + if (location == BC_TEXT_LOC_BELOWEMBED) { + m_locTextLoc = location; + return true; + } + return false; +} + +bool CBC_OnedEAN8Writer::CheckContentValidity(const WideStringView& contents) { + return std::all_of(contents.begin(), contents.end(), std::iswdigit); +} + +WideString CBC_OnedEAN8Writer::FilterContents(const WideStringView& contents) { + WideString filtercontents; + wchar_t ch; + for (size_t i = 0; i < contents.GetLength(); i++) { + ch = contents[i]; + if (ch > 175) { + i++; + continue; + } + if (ch >= '0' && ch <= '9') { + filtercontents += ch; + } + } + return filtercontents; +} + +int32_t CBC_OnedEAN8Writer::CalcChecksum(const ByteString& contents) { + return EANCalcChecksum(contents); +} + +uint8_t* CBC_OnedEAN8Writer::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + if (format != BCFORMAT_EAN_8) + return nullptr; + return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight, + hints); +} + +uint8_t* CBC_OnedEAN8Writer::EncodeImpl(const ByteString& contents, + int32_t& outLength) { + if (contents.GetLength() != 8) + return nullptr; + + outLength = m_codeWidth; + std::unique_ptr result( + FX_Alloc(uint8_t, m_codeWidth)); + int32_t pos = 0; + int32_t e = BCExceptionNO; + pos += AppendPattern(result.get(), pos, kOnedEAN8StartPattern, 3, 1, e); + if (e != BCExceptionNO) + return nullptr; + + int32_t i = 0; + for (i = 0; i <= 3; i++) { + int32_t digit = FXSYS_DecimalCharToInt(contents[i]); + pos += AppendPattern(result.get(), pos, kOnedEAN8LPattern[digit], 4, 0, e); + if (e != BCExceptionNO) + return nullptr; + } + pos += AppendPattern(result.get(), pos, kOnedEAN8MiddlePattern, 5, 0, e); + if (e != BCExceptionNO) + return nullptr; + + for (i = 4; i <= 7; i++) { + int32_t digit = FXSYS_DecimalCharToInt(contents[i]); + pos += AppendPattern(result.get(), pos, kOnedEAN8LPattern[digit], 4, 1, e); + if (e != BCExceptionNO) + return nullptr; + } + pos += AppendPattern(result.get(), pos, kOnedEAN8StartPattern, 3, 1, e); + if (e != BCExceptionNO) + return nullptr; + return result.release(); +} + +bool CBC_OnedEAN8Writer::ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) { + if (!device) + return false; + + int32_t leftPosition = 3 * multiple; + ByteString str = FX_UTF8Encode(contents); + size_t iLength = str.GetLength(); + std::vector charpos(iLength); + ByteString tempStr = str.Left(4); + size_t iLen = tempStr.GetLength(); + int32_t strWidth = 7 * multiple * 4; + float blank = 0.0; + + int32_t iFontSize = (int32_t)fabs(m_fFontSize); + int32_t iTextHeight = iFontSize + 1; + + CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect((float)leftPosition, (float)(m_Height - iTextHeight), + (float)(leftPosition + strWidth - 0.5), (float)m_Height); + matr.Concat(*matrix); + FX_RECT re = matr.TransformRect(rect).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect1( + (float)(leftPosition + 33 * multiple), (float)(m_Height - iTextHeight), + (float)(leftPosition + 33 * multiple + strWidth - 0.5), (float)m_Height); + matr1.Concat(*matrix); + re = matr1.TransformRect(rect1).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + strWidth = (int32_t)(strWidth * m_outputHScale); + + CalcTextInfo(tempStr, charpos.data(), m_pFont.Get(), (float)strWidth, + iFontSize, blank); + { + CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, + (float)leftPosition * m_outputHScale, + (float)(m_Height - iTextHeight + iFontSize)); + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, charpos.data(), m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + tempStr = str.Mid(4, 4); + iLen = tempStr.GetLength(); + CalcTextInfo(tempStr, &charpos[4], m_pFont.Get(), (float)strWidth, iFontSize, + blank); + { + CFX_Matrix affine_matrix1( + 1.0, 0.0, 0.0, -1.0, + (float)(leftPosition + 33 * multiple) * m_outputHScale, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, &charpos[4], m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + return true; +} diff --git a/fxbarcode/oned/BC_OnedEAN8Writer.h b/fxbarcode/oned/BC_OnedEAN8Writer.h new file mode 100644 index 0000000000000000000000000000000000000000..77a3602f67184cd4ab36f002dc5f9a93f5f365e0 --- /dev/null +++ b/fxbarcode/oned/BC_OnedEAN8Writer.h @@ -0,0 +1,48 @@ +// 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 FXBARCODE_ONED_BC_ONEDEAN8WRITER_H_ +#define FXBARCODE_ONED_BC_ONEDEAN8WRITER_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/BC_Library.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +class CFX_DIBitmap; +class CFX_RenderDevice; + +class CBC_OnedEAN8Writer : public CBC_OneDimWriter { + public: + CBC_OnedEAN8Writer(); + ~CBC_OnedEAN8Writer() override; + + // CBC_OneDimWriter + uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) override; + uint8_t* EncodeImpl(const ByteString& contents, int32_t& outLength) override; + bool CheckContentValidity(const WideStringView& contents) override; + WideString FilterContents(const WideStringView& contents) override; + void SetDataLength(int32_t length) override; + + bool SetTextLocation(BC_TEXT_LOC location); + int32_t CalcChecksum(const ByteString& contents); + + protected: + bool ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) override; + + private: + int32_t m_codeWidth; +}; + +#endif // FXBARCODE_ONED_BC_ONEDEAN8WRITER_H_ diff --git a/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp b/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16a1df6c2800520996065a8ab808d2ce86c5c612 --- /dev/null +++ b/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp @@ -0,0 +1,88 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxbarcode/oned/BC_OnedEAN8Writer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +TEST(OnedEAN8WriterTest, Encode) { + CBC_OnedEAN8Writer writer; + int32_t width; + int32_t height; + uint8_t* encoded; + const char* expected; + + // EAN-8 barcodes encode 8-digit numbers into 67 modules in a unidimensional + // disposition. + encoded = writer.Encode("", BCFORMAT_EAN_8, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("123", BCFORMAT_EAN_8, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("1234567", BCFORMAT_EAN_8, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("123456789", BCFORMAT_EAN_8, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("12345670", BCFORMAT_EAN_8, width, height); + EXPECT_NE(nullptr, encoded); + EXPECT_EQ(1, height); + EXPECT_EQ(67, width); + + expected = + "# #" // Start + " ## #" // 1 L + " # ##" // 2 L + " #### #" // 3 L + " # ##" // 4 L + " # # " // Middle + "# ### " // 5 R + "# # " // 6 R + "# # " // 7 R + "### # " // 0 R + "# #"; // End + for (int i = 0; i < 67; i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("99441104", BCFORMAT_EAN_8, width, height); + EXPECT_NE(nullptr, encoded); + EXPECT_EQ(1, height); + EXPECT_EQ(67, width); + + expected = + "# #" // Start + " # ##" // 9 L + " # ##" // 9 L + " # ##" // 4 L + " # ##" // 4 L + " # # " // Middle + "## ## " // 1 R + "## ## " // 1 R + "### # " // 0 R + "# ### " // 4 R + "# #"; // End + for (int i = 0; i < 67; i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +TEST(OnedEAN8WriterTest, Checksum) { + CBC_OnedEAN8Writer writer; + EXPECT_EQ(0, writer.CalcChecksum("")); + EXPECT_EQ(6, writer.CalcChecksum("123")); + EXPECT_EQ(0, writer.CalcChecksum("1234567")); + EXPECT_EQ(4, writer.CalcChecksum("9944110")); +} + +} // namespace diff --git a/fxbarcode/oned/BC_OnedEANChecksum.cpp b/fxbarcode/oned/BC_OnedEANChecksum.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b290c62926f5d096277c6577ca391ce6d2005378 --- /dev/null +++ b/fxbarcode/oned/BC_OnedEANChecksum.cpp @@ -0,0 +1,21 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxbarcode/oned/BC_OnedEANChecksum.h" + +#include "core/fxcrt/fx_extension.h" + +int32_t EANCalcChecksum(const ByteString& contents) { + int32_t odd = 0; + int32_t even = 0; + size_t parity = 1; + for (size_t i = contents.GetLength(); i > 0; i--) { + if (parity % 2) + odd += FXSYS_DecimalCharToInt(contents[i - 1]); + else + even += FXSYS_DecimalCharToInt(contents[i - 1]); + parity++; + } + return (10 - (odd * 3 + even) % 10) % 10; +} diff --git a/fxbarcode/oned/BC_OnedEANChecksum.h b/fxbarcode/oned/BC_OnedEANChecksum.h new file mode 100644 index 0000000000000000000000000000000000000000..5dd24bc269c8bd060c9991c143bdc511d6ca42f6 --- /dev/null +++ b/fxbarcode/oned/BC_OnedEANChecksum.h @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FXBARCODE_ONED_BC_ONEDEANCHECKSUM_H_ +#define FXBARCODE_ONED_BC_ONEDEANCHECKSUM_H_ + +#include "core/fxcrt/fx_string.h" + +int32_t EANCalcChecksum(const ByteString& contents); + +#endif // FXBARCODE_ONED_BC_ONEDEANCHECKSUM_H_ diff --git a/fxbarcode/oned/BC_OnedUPCAWriter.cpp b/fxbarcode/oned/BC_OnedUPCAWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..025f8515265363e384079bef54eaeccc673e1e64 --- /dev/null +++ b/fxbarcode/oned/BC_OnedUPCAWriter.cpp @@ -0,0 +1,214 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/oned/BC_OnedUPCAWriter.h" + +#include + +#include "core/fxcrt/fx_extension.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "fxbarcode/BC_Writer.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" +#include "fxbarcode/oned/BC_OnedEAN13Writer.h" +#include "third_party/base/ptr_util.h" + +CBC_OnedUPCAWriter::CBC_OnedUPCAWriter() { + m_bLeftPadding = true; + m_bRightPadding = true; +} + +void CBC_OnedUPCAWriter::Init() { + m_subWriter = pdfium::MakeUnique(); +} + +CBC_OnedUPCAWriter::~CBC_OnedUPCAWriter() {} + +bool CBC_OnedUPCAWriter::CheckContentValidity(const WideStringView& contents) { + for (size_t i = 0; i < contents.GetLength(); ++i) { + if (contents[i] < '0' || contents[i] > '9') + return false; + } + return true; +} + +WideString CBC_OnedUPCAWriter::FilterContents(const WideStringView& contents) { + WideString filtercontents; + wchar_t ch; + for (size_t i = 0; i < contents.GetLength(); i++) { + ch = contents[i]; + if (ch > 175) { + i++; + continue; + } + if (ch >= '0' && ch <= '9') { + filtercontents += ch; + } + } + return filtercontents; +} + +int32_t CBC_OnedUPCAWriter::CalcChecksum(const ByteString& contents) { + int32_t odd = 0; + int32_t even = 0; + size_t j = 1; + for (size_t i = contents.GetLength(); i > 0; i--) { + if (j % 2) { + odd += FXSYS_DecimalCharToInt(contents[i - 1]); + } else { + even += FXSYS_DecimalCharToInt(contents[i - 1]); + } + j++; + } + int32_t checksum = (odd * 3 + even) % 10; + checksum = (10 - checksum) % 10; + return checksum; +} + +uint8_t* CBC_OnedUPCAWriter::EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) { + if (format != BCFORMAT_UPC_A) + return nullptr; + + ByteString toEAN13String = '0' + contents; + m_iDataLenth = 13; + return m_subWriter->EncodeWithHint(toEAN13String, BCFORMAT_EAN_13, outWidth, + outHeight, hints); +} + +uint8_t* CBC_OnedUPCAWriter::EncodeImpl(const ByteString& contents, + int32_t& outLength) { + return nullptr; +} + +bool CBC_OnedUPCAWriter::ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) { + if (!device) + return false; + + int32_t leftPadding = 7 * multiple; + int32_t leftPosition = 10 * multiple + leftPadding; + ByteString str = FX_UTF8Encode(contents); + int32_t iLen = str.GetLength(); + std::vector charpos(iLen); + ByteString tempStr = str.Mid(1, 5); + float strWidth = (float)35 * multiple; + float blank = 0.0; + + iLen = tempStr.GetLength(); + int32_t iFontSize = (int32_t)fabs(m_fFontSize); + int32_t iTextHeight = iFontSize + 1; + + CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect((float)leftPosition, (float)(m_Height - iTextHeight), + (float)(leftPosition + strWidth - 0.5), (float)m_Height); + matr.Concat(*matrix); + FX_RECT re = matr.TransformRect(rect).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect1((float)(leftPosition + 40 * multiple), + (float)(m_Height - iTextHeight), + (float)((leftPosition + 40 * multiple) + strWidth - 0.5), + (float)m_Height); + matr1.Concat(*matrix); + re = matr1.TransformRect(rect1).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + float strWidth1 = (float)multiple * 7; + CFX_Matrix matr2(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect2(0.0, (float)(m_Height - iTextHeight), + (float)strWidth1 - 1, (float)m_Height); + matr2.Concat(*matrix); + re = matr2.TransformRect(rect2).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + CFX_Matrix matr3(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); + CFX_FloatRect rect3((float)(leftPosition + 85 * multiple), + (float)(m_Height - iTextHeight), + (float)((leftPosition + 85 * multiple) + strWidth1 - 0.5), + (float)m_Height); + matr3.Concat(*matrix); + re = matr3.TransformRect(rect3).GetOuterRect(); + device->FillRect(&re, m_backgroundColor); + strWidth = strWidth * m_outputHScale; + + CalcTextInfo(tempStr, &charpos[1], m_pFont.Get(), strWidth, iFontSize, blank); + { + CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, + (float)leftPosition * m_outputHScale, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, &charpos[1], m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + tempStr = str.Mid(6, 5); + iLen = tempStr.GetLength(); + CalcTextInfo(tempStr, &charpos[6], m_pFont.Get(), strWidth, iFontSize, blank); + { + CFX_Matrix affine_matrix1( + 1.0, 0.0, 0.0, -1.0, + (float)(leftPosition + 40 * multiple) * m_outputHScale, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, &charpos[6], m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + tempStr = str.Left(1); + iLen = tempStr.GetLength(); + strWidth = (float)multiple * 7; + strWidth = strWidth * m_outputHScale; + + CalcTextInfo(tempStr, charpos.data(), m_pFont.Get(), strWidth, iFontSize, + blank); + { + CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, 0, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, charpos.data(), m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + tempStr = str.Mid(11, 1); + iLen = tempStr.GetLength(); + CalcTextInfo(tempStr, &charpos[11], m_pFont.Get(), strWidth, iFontSize, + blank); + { + CFX_Matrix affine_matrix1( + 1.0, 0.0, 0.0, -1.0, + (float)(leftPosition + 85 * multiple) * m_outputHScale, + (float)(m_Height - iTextHeight + iFontSize)); + if (matrix) + affine_matrix1.Concat(*matrix); + device->DrawNormalText(iLen, &charpos[11], m_pFont.Get(), + static_cast(iFontSize), &affine_matrix1, + m_fontColor, FXTEXT_CLEARTYPE); + } + return true; +} diff --git a/fxbarcode/oned/BC_OnedUPCAWriter.h b/fxbarcode/oned/BC_OnedUPCAWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..a854ef466598a343f6fe4389b39007c787940ad3 --- /dev/null +++ b/fxbarcode/oned/BC_OnedUPCAWriter.h @@ -0,0 +1,50 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_ONED_BC_ONEDUPCAWRITER_H_ +#define FXBARCODE_ONED_BC_ONEDUPCAWRITER_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/oned/BC_OneDimWriter.h" + +class CBC_OnedEAN13Writer; +class CFX_DIBitmap; +class CFX_Matrix; +class CFX_RenderDevice; + +class CBC_OnedUPCAWriter : public CBC_OneDimWriter { + public: + CBC_OnedUPCAWriter(); + ~CBC_OnedUPCAWriter() override; + + // CBC_OneDimWriter + uint8_t* EncodeWithHint(const ByteString& contents, + BCFORMAT format, + int32_t& outWidth, + int32_t& outHeight, + int32_t hints) override; + uint8_t* EncodeImpl(const ByteString& contents, int32_t& outLength) override; + bool CheckContentValidity(const WideStringView& contents) override; + WideString FilterContents(const WideStringView& contents) override; + + void Init(); + int32_t CalcChecksum(const ByteString& contents); + + protected: + bool ShowChars(const WideStringView& contents, + CFX_RenderDevice* device, + const CFX_Matrix* matrix, + int32_t barWidth, + int32_t multiple) override; + + private: + std::unique_ptr m_subWriter; +}; + +#endif // FXBARCODE_ONED_BC_ONEDUPCAWRITER_H_ diff --git a/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp b/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d9f6c5e611a177548bd6c2fc8a74bf73b02b5ab --- /dev/null +++ b/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp @@ -0,0 +1,96 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxbarcode/oned/BC_OnedUPCAWriter.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +TEST(OnedUPCAWriterTest, Encode) { + CBC_OnedUPCAWriter writer; + int32_t width; + int32_t height; + + // TODO(hnakashima): CBC_OnedUPCAWriter is unique in that it needs to be + // Init()'d. Get rid of this call. + writer.Init(); + + // UPCA barcodes encode 12-digit numbers into 95 modules in a unidimensional + // disposition. + uint8_t* encoded = writer.Encode("", BCFORMAT_UPC_A, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("123", BCFORMAT_UPC_A, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("12345678901", BCFORMAT_UPC_A, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("1234567890123", BCFORMAT_UPC_A, width, height); + EXPECT_EQ(nullptr, encoded); + FX_Free(encoded); + + encoded = writer.Encode("123456789012", BCFORMAT_UPC_A, width, height); + const char* expected = + "# #" // Start + " ## #" // 1 L + " # ##" // 2 L + " #### #" // 3 L + " # ##" // 4 L + " ## #" // 5 L + " # ####" // 6 L + " # # " // Middle + "# # " // 7 R + "# # " // 8 R + "### # " // 9 R + "### # " // 0 R + "## ## " // 1 R + "## ## " // 2 R + "# #"; // End + EXPECT_NE(nullptr, encoded); + EXPECT_EQ(1, height); + EXPECT_EQ(static_cast(strlen(expected)), width); + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); + + encoded = writer.Encode("777666555440", BCFORMAT_UPC_A, width, height); + expected = + "# #" // Start + " ### ##" // 7 L + " ### ##" // 7 L + " ### ##" // 7 L + " # ####" // 6 L + " # ####" // 6 L + " # ####" // 6 L + " # # " // Middle + "# ### " // 5 R + "# ### " // 5 R + "# ### " // 5 R + "# ### " // 4 R + "# ### " // 4 R + "### # " // 0 R + "# #"; // End + EXPECT_NE(nullptr, encoded); + EXPECT_EQ(1, height); + EXPECT_EQ(static_cast(strlen(expected)), width); + for (size_t i = 0; i < strlen(expected); i++) { + EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i; + } + FX_Free(encoded); +} + +TEST(OnedUPCAWriterTest, Checksum) { + CBC_OnedUPCAWriter writer; + EXPECT_EQ(0, writer.CalcChecksum("")); + EXPECT_EQ(6, writer.CalcChecksum("123")); + EXPECT_EQ(2, writer.CalcChecksum("12345678901")); + EXPECT_EQ(0, writer.CalcChecksum("77766655544")); +} + +} // namespace diff --git a/xfa/fxbarcode/pdf417/BC_PDF417.cpp b/fxbarcode/pdf417/BC_PDF417.cpp similarity index 93% rename from xfa/fxbarcode/pdf417/BC_PDF417.cpp rename to fxbarcode/pdf417/BC_PDF417.cpp index 2f01564b11abf75fe3c49415d5088c76a2aa622a..9b73b49a2626c869b59002339ef809b900dc4176 100644 --- a/xfa/fxbarcode/pdf417/BC_PDF417.cpp +++ b/fxbarcode/pdf417/BC_PDF417.cpp @@ -20,15 +20,15 @@ * limitations under the License. */ -#include "xfa/fxbarcode/pdf417/BC_PDF417.h" +#include "fxbarcode/pdf417/BC_PDF417.h" +#include "fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h" +#include "fxbarcode/pdf417/BC_PDF417BarcodeRow.h" +#include "fxbarcode/pdf417/BC_PDF417Compaction.h" +#include "fxbarcode/pdf417/BC_PDF417ErrorCorrection.h" +#include "fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" +#include "fxbarcode/utils.h" #include "third_party/base/ptr_util.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" -#include "xfa/fxbarcode/utils.h" const int32_t CBC_PDF417::CODEWORD_TABLE[][929] = { {0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470, @@ -399,48 +399,49 @@ CBC_BarcodeMatrix* CBC_PDF417::getBarcodeMatrix() { return m_barcodeMatrix.get(); } -void CBC_PDF417::generateBarcodeLogic(CFX_WideString msg, - int32_t errorCorrectionLevel, - int32_t& e) { +bool CBC_PDF417::generateBarcodeLogic(WideString msg, + int32_t errorCorrectionLevel) { int32_t errorCorrectionCodeWords = CBC_PDF417ErrorCorrection::getErrorCorrectionCodewordCount( - errorCorrectionLevel, e); - if (e != BCExceptionNO) - return; - CFX_WideString highLevel = + errorCorrectionLevel); + if (errorCorrectionCodeWords < 0) + return false; + + int32_t e = BCExceptionNO; + WideString highLevel = CBC_PDF417HighLevelEncoder::encodeHighLevel(msg, m_compaction, e); if (e != BCExceptionNO) - return; + return false; int32_t sourceCodeWords = highLevel.GetLength(); - CFX_ArrayTemplate* dimension = - determineDimensions(sourceCodeWords, errorCorrectionCodeWords, e); - if (e != BCExceptionNO) - return; - int32_t cols = dimension->GetAt(0); - int32_t rows = dimension->GetAt(1); - delete dimension; + std::vector dimensions = + determineDimensions(sourceCodeWords, errorCorrectionCodeWords); + if (dimensions.size() != 2) + return false; + int32_t cols = dimensions[0]; + int32_t rows = dimensions[1]; int32_t pad = getNumberOfPadCodewords(sourceCodeWords, errorCorrectionCodeWords, cols, rows); - if (sourceCodeWords + errorCorrectionCodeWords + 1 > 929) { - e = BCExceptionEncodedMessageContainsTooManyCodeWords; - return; - } + if (sourceCodeWords + errorCorrectionCodeWords + 1 > 929) + return false; + int32_t n = sourceCodeWords + pad + 1; - CFX_WideString sb; - sb += (FX_WCHAR)n; + WideString sb; + sb += (wchar_t)n; sb += highLevel; - for (int32_t i = 0; i < pad; i++) { - sb += (FX_WCHAR)900; + for (int32_t i = 0; i < pad; i++) + sb += (wchar_t)900; + + WideString dataCodewords(sb); + WideString ec; + if (!CBC_PDF417ErrorCorrection::generateErrorCorrection( + dataCodewords, errorCorrectionLevel, &ec)) { + return false; } - CFX_WideString dataCodewords(sb); - CFX_WideString ec = CBC_PDF417ErrorCorrection::generateErrorCorrection( - dataCodewords, errorCorrectionLevel, e); - if (e != BCExceptionNO) - return; - CFX_WideString fullCodewords = dataCodewords + ec; + WideString fullCodewords = dataCodewords + ec; m_barcodeMatrix = pdfium::MakeUnique(rows, cols); encodeLowLevel(fullCodewords, cols, rows, errorCorrectionLevel, m_barcodeMatrix.get()); + return true; } void CBC_PDF417::setDimensions(int32_t maxCols, @@ -497,7 +498,7 @@ void CBC_PDF417::encodeChar(int32_t pattern, logic->addBar(last, width); } -void CBC_PDF417::encodeLowLevel(CFX_WideString fullCodewords, +void CBC_PDF417::encodeLowLevel(WideString fullCodewords, int32_t c, int32_t r, int32_t errorCorrectionLevel, @@ -522,7 +523,7 @@ void CBC_PDF417::encodeLowLevel(CFX_WideString fullCodewords, int32_t pattern = CODEWORD_TABLE[cluster][left]; encodeChar(pattern, 17, logic->getCurrentRow()); for (int32_t x = 0; x < c; x++) { - pattern = CODEWORD_TABLE[cluster][fullCodewords.GetAt(idx)]; + pattern = CODEWORD_TABLE[cluster][fullCodewords[idx]]; encodeChar(pattern, 17, logic->getCurrentRow()); idx++; } @@ -536,49 +537,41 @@ void CBC_PDF417::encodeLowLevel(CFX_WideString fullCodewords, } } -CFX_ArrayTemplate* CBC_PDF417::determineDimensions( +std::vector CBC_PDF417::determineDimensions( int32_t sourceCodeWords, - int32_t errorCorrectionCodeWords, - int32_t& e) { - FX_FLOAT ratio = 0.0f; - CFX_ArrayTemplate* dimension = nullptr; + int32_t errorCorrectionCodeWords) const { + std::vector dimensions; + float ratio = 0.0f; for (int32_t cols = m_minCols; cols <= m_maxCols; cols++) { int32_t rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, cols); - if (rows < m_minRows) { + if (rows < m_minRows) break; - } - if (rows > m_maxRows) { + if (rows > m_maxRows) continue; - } - FX_FLOAT newRatio = + float newRatio = ((17 * cols + 69) * DEFAULT_MODULE_WIDTH) / (rows * HEIGHT); - if (dimension && + if (!dimensions.empty() && fabsf(newRatio - PREFERRED_RATIO) > fabsf(ratio - PREFERRED_RATIO)) { continue; } ratio = newRatio; - delete dimension; - dimension = new CFX_ArrayTemplate; - dimension->Add(cols); - dimension->Add(rows); + dimensions.resize(2); + dimensions[0] = cols; + dimensions[1] = rows; } - if (!dimension) { + if (dimensions.empty()) { int32_t rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, m_minCols); if (rows < m_minRows) { - dimension = new CFX_ArrayTemplate; - dimension->Add(m_minCols); - dimension->Add(m_minRows); + dimensions.resize(2); + dimensions[0] = m_minCols; + dimensions[1] = m_minRows; } else if (rows >= 3 && rows <= 90) { - dimension = new CFX_ArrayTemplate; - dimension->Add(m_minCols); - dimension->Add(rows); + dimensions.resize(2); + dimensions[0] = m_minCols; + dimensions[1] = rows; } } - if (!dimension) { - e = BCExceptionUnableToFitMessageInColumns; - return nullptr; - } - return dimension; + return dimensions; } diff --git a/fxbarcode/pdf417/BC_PDF417.h b/fxbarcode/pdf417/BC_PDF417.h new file mode 100644 index 0000000000000000000000000000000000000000..6014df0e3be15fb32e08f9617177290368b1945b --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417.h @@ -0,0 +1,66 @@ +// 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 FXBARCODE_PDF417_BC_PDF417_H_ +#define FXBARCODE_PDF417_BC_PDF417_H_ + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "fxbarcode/pdf417/BC_PDF417Compaction.h" + +class CBC_BarcodeRow; +class CBC_BarcodeMatrix; + +class CBC_PDF417 { + public: + CBC_PDF417(); + explicit CBC_PDF417(bool compact); + virtual ~CBC_PDF417(); + + CBC_BarcodeMatrix* getBarcodeMatrix(); + bool generateBarcodeLogic(WideString msg, int32_t errorCorrectionLevel); + void setDimensions(int32_t maxCols, + int32_t minCols, + int32_t maxRows, + int32_t minRows); + void setCompaction(Compaction compaction); + void setCompact(bool compact); + + private: + static const int32_t START_PATTERN = 0x1fea8; + static const int32_t STOP_PATTERN = 0x3fa29; + static const int32_t CODEWORD_TABLE[][929]; + static constexpr float PREFERRED_RATIO = 3.0f; + static constexpr float DEFAULT_MODULE_WIDTH = 0.357f; + static constexpr float HEIGHT = 2.0f; + + static int32_t calculateNumberOfRows(int32_t m, int32_t k, int32_t c); + static int32_t getNumberOfPadCodewords(int32_t m, + int32_t k, + int32_t c, + int32_t r); + static void encodeChar(int32_t pattern, int32_t len, CBC_BarcodeRow* logic); + void encodeLowLevel(WideString fullCodewords, + int32_t c, + int32_t r, + int32_t errorCorrectionLevel, + CBC_BarcodeMatrix* logic); + std::vector determineDimensions( + int32_t sourceCodeWords, + int32_t errorCorrectionCodeWords) const; + + std::unique_ptr m_barcodeMatrix; + bool m_compact; + Compaction m_compaction; + int32_t m_minCols; + int32_t m_maxCols; + int32_t m_maxRows; + int32_t m_minRows; +}; + +#endif // FXBARCODE_PDF417_BC_PDF417_H_ diff --git a/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp b/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca492b3c19a736c8b5488cc0db6e0d1e9d5126c9 --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp @@ -0,0 +1,73 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h" +#include "fxbarcode/pdf417/BC_PDF417BarcodeRow.h" +#include "third_party/base/ptr_util.h" + +CBC_BarcodeMatrix::CBC_BarcodeMatrix(int32_t height, int32_t width) { + m_matrix.resize(height + 2); + for (size_t i = 0; i < m_matrix.size(); ++i) + m_matrix[i] = pdfium::MakeUnique((width + 4) * 17 + 1); + + m_width = width * 17; + m_height = height + 2; + m_currentRow = 0; + m_outHeight = 0; + m_outWidth = 0; +} + +CBC_BarcodeMatrix::~CBC_BarcodeMatrix() {} + +void CBC_BarcodeMatrix::set(int32_t x, int32_t y, uint8_t value) { + m_matrix[y]->set(x, value); +} +void CBC_BarcodeMatrix::setMatrix(int32_t x, int32_t y, bool black) { + set(x, y, (uint8_t)(black ? 1 : 0)); +} +void CBC_BarcodeMatrix::startRow() { + ++m_currentRow; +} +std::vector& CBC_BarcodeMatrix::getMatrix() { + return getScaledMatrix(1, 1); +} +std::vector& CBC_BarcodeMatrix::getScaledMatrix(int32_t scale) { + return getScaledMatrix(scale, scale); +} +std::vector& CBC_BarcodeMatrix::getScaledMatrix(int32_t xScale, + int32_t yScale) { + size_t yMax = m_height * yScale; + std::vector bytearray = m_matrix[0]->getScaledRow(xScale); + size_t xMax = bytearray.size(); + m_matrixOut.resize(xMax * yMax); + m_outWidth = xMax; + m_outHeight = yMax; + int32_t k = 0; + for (size_t i = 0; i < yMax; i++) { + if (i != 0) + bytearray = m_matrix[i / yScale]->getScaledRow(xScale); + k = i * xMax; + for (size_t l = 0; l < xMax; l++) + m_matrixOut[k + l] = bytearray[l]; + } + return m_matrixOut; +} diff --git a/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h b/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..71ada98872d0f444c0cf5f39f4b39f349d7e663a --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h @@ -0,0 +1,41 @@ +// 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 FXBARCODE_PDF417_BC_PDF417BARCODEMATRIX_H_ +#define FXBARCODE_PDF417_BC_PDF417BARCODEMATRIX_H_ + +#include +#include + +class CBC_BarcodeRow; + +class CBC_BarcodeMatrix { + public: + CBC_BarcodeMatrix(); + CBC_BarcodeMatrix(int32_t height, int32_t width); + virtual ~CBC_BarcodeMatrix(); + + CBC_BarcodeRow* getCurrentRow() const { return m_matrix[m_currentRow].get(); } + int32_t getWidth() const { return m_outWidth; } + int32_t getHeight() const { return m_outHeight; } + void set(int32_t x, int32_t y, uint8_t value); + void setMatrix(int32_t x, int32_t y, bool black); + void startRow(); + std::vector& getMatrix(); + std::vector& getScaledMatrix(int32_t scale); + std::vector& getScaledMatrix(int32_t xScale, int32_t yScale); + + private: + std::vector> m_matrix; + std::vector m_matrixOut; + int32_t m_currentRow; + int32_t m_height; + int32_t m_width; + int32_t m_outWidth; + int32_t m_outHeight; +}; + +#endif // FXBARCODE_PDF417_BC_PDF417BARCODEMATRIX_H_ diff --git a/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp b/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0c251f708f8420ede14ae0d0bd66d78b477d63e --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp @@ -0,0 +1,52 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2011 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/pdf417/BC_PDF417BarcodeRow.h" + +CBC_BarcodeRow::CBC_BarcodeRow(size_t width) + : m_row(width), m_currentLocation(0) {} + +CBC_BarcodeRow::~CBC_BarcodeRow() {} + +void CBC_BarcodeRow::set(int32_t x, uint8_t value) { + m_row[x] = value; +} + +void CBC_BarcodeRow::set(int32_t x, bool black) { + m_row[x] = black ? 1 : 0; +} + +void CBC_BarcodeRow::addBar(bool black, int32_t width) { + for (int32_t ii = 0; ii < width; ii++) + set(m_currentLocation++, black); +} + +std::vector& CBC_BarcodeRow::getRow() { + return m_row; +} + +std::vector& CBC_BarcodeRow::getScaledRow(int32_t scale) { + m_output.resize(m_row.size() * scale); + for (size_t i = 0; i < m_output.size(); i++) + m_output[i] = m_row[i / scale]; + return m_output; +} diff --git a/fxbarcode/pdf417/BC_PDF417BarcodeRow.h b/fxbarcode/pdf417/BC_PDF417BarcodeRow.h new file mode 100644 index 0000000000000000000000000000000000000000..d49d0eb9c29535546ad27287d86db53cf718a45a --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417BarcodeRow.h @@ -0,0 +1,31 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_PDF417_BC_PDF417BARCODEROW_H_ +#define FXBARCODE_PDF417_BC_PDF417BARCODEROW_H_ + +#include + +#include + +class CBC_BarcodeRow { + public: + explicit CBC_BarcodeRow(size_t width); + virtual ~CBC_BarcodeRow(); + + void set(int32_t x, uint8_t value); + void set(int32_t x, bool black); + void addBar(bool black, int32_t width); + std::vector& getRow(); + std::vector& getScaledRow(int32_t scale); + + private: + std::vector m_row; + std::vector m_output; + int32_t m_currentLocation; +}; + +#endif // FXBARCODE_PDF417_BC_PDF417BARCODEROW_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417Compaction.cpp b/fxbarcode/pdf417/BC_PDF417Compaction.cpp similarity index 94% rename from xfa/fxbarcode/pdf417/BC_PDF417Compaction.cpp rename to fxbarcode/pdf417/BC_PDF417Compaction.cpp index d3a1663eb67619e312f671aaf86462ff1dbe143c..d0ed8780fae426d6fec17a8c568bddda53cd1b2f 100644 --- a/xfa/fxbarcode/pdf417/BC_PDF417Compaction.cpp +++ b/fxbarcode/pdf417/BC_PDF417Compaction.cpp @@ -20,7 +20,7 @@ * limitations under the License. */ -#include "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h" +#include "fxbarcode/pdf417/BC_PDF417Compaction.h" CBC_Compaction::CBC_Compaction() {} CBC_Compaction::~CBC_Compaction() {} diff --git a/fxbarcode/pdf417/BC_PDF417Compaction.h b/fxbarcode/pdf417/BC_PDF417Compaction.h new file mode 100644 index 0000000000000000000000000000000000000000..7f4795a7e5ea885f907c9df179d8cde22b2f965c --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417Compaction.h @@ -0,0 +1,18 @@ +// 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 FXBARCODE_PDF417_BC_PDF417COMPACTION_H_ +#define FXBARCODE_PDF417_BC_PDF417COMPACTION_H_ + +class CBC_Compaction; +enum Compaction { AUTO, TEXT, BYTES, NUMERIC }; +class CBC_Compaction { + public: + CBC_Compaction(); + virtual ~CBC_Compaction(); +}; + +#endif // FXBARCODE_PDF417_BC_PDF417COMPACTION_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp b/fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp similarity index 86% rename from xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp rename to fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp index bdec403970599897dda82adb31287c1c500a0bb7..ade3eb584d333030b1e6a630d28b29410fdc8342 100644 --- a/xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp +++ b/fxbarcode/pdf417/BC_PDF417ErrorCorrection.cpp @@ -20,8 +20,9 @@ * limitations under the License. */ -#include "xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h" -#include "xfa/fxbarcode/utils.h" +#include "fxbarcode/pdf417/BC_PDF417ErrorCorrection.h" + +#include namespace { @@ -124,68 +125,43 @@ const uint16_t* const EC_COEFFICIENTS[9] = { CBC_PDF417ErrorCorrection::CBC_PDF417ErrorCorrection() {} CBC_PDF417ErrorCorrection::~CBC_PDF417ErrorCorrection() {} int32_t CBC_PDF417ErrorCorrection::getErrorCorrectionCodewordCount( - int32_t errorCorrectionLevel, - int32_t& e) { - if (errorCorrectionLevel < 0 || errorCorrectionLevel > 8) { - e = BCExceptionErrorCorrectionLevelMustBeBetween0And8; + int32_t errorCorrectionLevel) { + if (errorCorrectionLevel < 0 || errorCorrectionLevel > 8) return -1; - } return 1 << (errorCorrectionLevel + 1); } -int32_t CBC_PDF417ErrorCorrection::getRecommendedMinimumErrorCorrectionLevel( - int32_t n, - int32_t& e) { - if (n <= 0) { - e = BCExceptionIllegalArgumentnMustBeAbove0; - return -1; - } - if (n <= 40) { - return 2; - } - if (n <= 160) { - return 3; - } - if (n <= 320) { - return 4; - } - if (n <= 863) { - return 5; - } - e = BCExceptionNoRecommendationPossible; - return -1; -} - -CFX_WideString CBC_PDF417ErrorCorrection::generateErrorCorrection( - CFX_WideString dataCodewords, +bool CBC_PDF417ErrorCorrection::generateErrorCorrection( + const WideString& dataCodewords, int32_t errorCorrectionLevel, - int32_t& e) { - int32_t k = getErrorCorrectionCodewordCount(errorCorrectionLevel, e); - if (e != BCExceptionNO) - return L" "; - FX_WCHAR* ech = FX_Alloc(FX_WCHAR, k); - FXSYS_memset(ech, 0, k * sizeof(FX_WCHAR)); + WideString* result) { + assert(result); + assert(result->IsEmpty()); + + int32_t k = getErrorCorrectionCodewordCount(errorCorrectionLevel); + if (k < 0) + return false; + + std::vector ech(k); int32_t sld = dataCodewords.GetLength(); for (int32_t i = 0; i < sld; i++) { - int32_t t1 = (dataCodewords.GetAt(i) + ech[k - 1]) % 929; + int32_t t1 = (dataCodewords[i] + ech[k - 1]) % 929; int32_t t2; int32_t t3; for (int32_t j = k - 1; j >= 1; j--) { t2 = (t1 * EC_COEFFICIENTS[errorCorrectionLevel][j]) % 929; t3 = 929 - t2; - ech[j] = (FX_WCHAR)((ech[j - 1] + t3) % 929); + ech[j] = (wchar_t)((ech[j - 1] + t3) % 929); } t2 = (t1 * EC_COEFFICIENTS[errorCorrectionLevel][0]) % 929; t3 = 929 - t2; - ech[0] = (FX_WCHAR)(t3 % 929); + ech[0] = (wchar_t)(t3 % 929); } - CFX_WideString sb; + result->Reserve(k); for (int32_t j = k - 1; j >= 0; j--) { - if (ech[j] != 0) { - ech[j] = (FX_WCHAR)(929 - ech[j]); - } - sb += (FX_WCHAR)ech[j]; + if (ech[j] != 0) + ech[j] = static_cast(929) - ech[j]; + *result += ech[j]; } - FX_Free(ech); - return sb; + return true; } diff --git a/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h b/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h new file mode 100644 index 0000000000000000000000000000000000000000..3e28162653c96db955a7981fd16f5ecd9d014cbb --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h @@ -0,0 +1,25 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_PDF417_BC_PDF417ERRORCORRECTION_H_ +#define FXBARCODE_PDF417_BC_PDF417ERRORCORRECTION_H_ + +#include + +#include "core/fxcrt/fx_string.h" + +class CBC_PDF417ErrorCorrection { + public: + CBC_PDF417ErrorCorrection(); + virtual ~CBC_PDF417ErrorCorrection(); + + static int32_t getErrorCorrectionCodewordCount(int32_t errorCorrectionLevel); + static bool generateErrorCorrection(const WideString& dataCodewords, + int32_t errorCorrectionLevel, + WideString* result); +}; + +#endif // FXBARCODE_PDF417_BC_PDF417ERRORCORRECTION_H_ diff --git a/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..059287a66569082f837445b9bb70c5358568b023 --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp @@ -0,0 +1,424 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" + +#include "fxbarcode/BC_UtilCodingConvert.h" +#include "fxbarcode/pdf417/BC_PDF417Compaction.h" +#include "fxbarcode/utils.h" +#include "third_party/bigint/BigIntegerLibrary.hh" + +#define SUBMODE_ALPHA 0 +#define SUBMODE_LOWER 1 +#define SUBMODE_MIXED 2 + +int32_t CBC_PDF417HighLevelEncoder::TEXT_COMPACTION = 0; +int32_t CBC_PDF417HighLevelEncoder::BYTE_COMPACTION = 1; +int32_t CBC_PDF417HighLevelEncoder::NUMERIC_COMPACTION = 2; +int32_t CBC_PDF417HighLevelEncoder::SUBMODE_PUNCTUATION = 3; +int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_TEXT = 900; +int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_BYTE_PADDED = 901; +int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_NUMERIC = 902; +int32_t CBC_PDF417HighLevelEncoder::SHIFT_TO_BYTE = 913; +int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_BYTE = 924; +uint8_t CBC_PDF417HighLevelEncoder::TEXT_MIXED_RAW[] = { + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, + 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0}; +uint8_t CBC_PDF417HighLevelEncoder::TEXT_PUNCTUATION_RAW[] = { + 59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, + 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0}; +int32_t CBC_PDF417HighLevelEncoder::MIXED[128] = {0}; +int32_t CBC_PDF417HighLevelEncoder::PUNCTUATION[128] = {0}; + +void CBC_PDF417HighLevelEncoder::Initialize() { + Inverse(); +} + +void CBC_PDF417HighLevelEncoder::Finalize() {} + +WideString CBC_PDF417HighLevelEncoder::encodeHighLevel(WideString wideMsg, + Compaction compaction, + int32_t& e) { + ByteString bytes; + CBC_UtilCodingConvert::UnicodeToUTF8(wideMsg, bytes); + WideString msg; + int32_t len = bytes.GetLength(); + for (int32_t i = 0; i < len; i++) { + wchar_t ch = (wchar_t)(bytes[i] & 0xff); + if (ch == '?' && bytes[i] != '?') { + e = BCExceptionCharactersOutsideISO88591Encoding; + return WideString(); + } + msg += ch; + } + std::vector byteArr(bytes.begin(), bytes.end()); + WideString sb; + len = msg.GetLength(); + int32_t p = 0; + int32_t textSubMode = SUBMODE_ALPHA; + if (compaction == TEXT) { + encodeText(msg, p, len, sb, textSubMode); + } else if (compaction == BYTES) { + encodeBinary(&byteArr, p, byteArr.size(), BYTE_COMPACTION, sb); + } else if (compaction == NUMERIC) { + sb += (wchar_t)LATCH_TO_NUMERIC; + encodeNumeric(msg, p, len, sb); + } else { + int32_t encodingMode = LATCH_TO_TEXT; + while (p < len) { + int32_t n = determineConsecutiveDigitCount(msg, p); + if (n >= 13) { + sb += (wchar_t)LATCH_TO_NUMERIC; + encodingMode = NUMERIC_COMPACTION; + textSubMode = SUBMODE_ALPHA; + encodeNumeric(msg, p, n, sb); + p += n; + } else { + int32_t t = determineConsecutiveTextCount(msg, p); + if (t >= 5 || n == len) { + if (encodingMode != TEXT_COMPACTION) { + sb += (wchar_t)LATCH_TO_TEXT; + encodingMode = TEXT_COMPACTION; + textSubMode = SUBMODE_ALPHA; + } + textSubMode = encodeText(msg, p, t, sb, textSubMode); + p += t; + } else { + int32_t b = determineConsecutiveBinaryCount(msg, &byteArr, p, e); + if (e != BCExceptionNO) + return L" "; + if (b == 0) { + b = 1; + } + if (b == 1 && encodingMode == TEXT_COMPACTION) { + encodeBinary(&byteArr, p, 1, TEXT_COMPACTION, sb); + } else { + encodeBinary(&byteArr, p, b, encodingMode, sb); + encodingMode = BYTE_COMPACTION; + textSubMode = SUBMODE_ALPHA; + } + p += b; + } + } + } + } + return sb; +} + +void CBC_PDF417HighLevelEncoder::Inverse() { + for (size_t l = 0; l < FX_ArraySize(MIXED); ++l) + MIXED[l] = -1; + + for (uint8_t i = 0; i < FX_ArraySize(TEXT_MIXED_RAW); ++i) { + uint8_t b = TEXT_MIXED_RAW[i]; + if (b != 0) + MIXED[b] = i; + } + + for (size_t l = 0; l < FX_ArraySize(PUNCTUATION); ++l) + PUNCTUATION[l] = -1; + + for (uint8_t i = 0; i < FX_ArraySize(TEXT_PUNCTUATION_RAW); ++i) { + uint8_t b = TEXT_PUNCTUATION_RAW[i]; + if (b != 0) + PUNCTUATION[b] = i; + } +} + +int32_t CBC_PDF417HighLevelEncoder::encodeText(WideString msg, + int32_t startpos, + int32_t count, + WideString& sb, + int32_t initialSubmode) { + WideString tmp; + int32_t submode = initialSubmode; + int32_t idx = 0; + while (true) { + wchar_t ch = msg[startpos + idx]; + switch (submode) { + case SUBMODE_ALPHA: + if (isAlphaUpper(ch)) { + if (ch == ' ') + tmp += (wchar_t)26; + else + tmp += (wchar_t)(ch - 65); + break; + } + if (isAlphaLower(ch)) { + submode = SUBMODE_LOWER; + tmp += (wchar_t)27; + continue; + } + if (isMixed(ch)) { + submode = SUBMODE_MIXED; + tmp += (wchar_t)28; + continue; + } + tmp += (wchar_t)29; + tmp += PUNCTUATION[ch]; + break; + case SUBMODE_LOWER: + if (isAlphaLower(ch)) { + if (ch == ' ') { + tmp += (wchar_t)26; + } else { + tmp += (wchar_t)(ch - 97); + } + break; + } + if (isAlphaUpper(ch)) { + tmp += (wchar_t)27; + tmp += (wchar_t)(ch - 65); + break; + } + if (isMixed(ch)) { + submode = SUBMODE_MIXED; + tmp += (wchar_t)28; + continue; + } + + tmp += (wchar_t)29; + tmp += PUNCTUATION[ch]; + break; + case SUBMODE_MIXED: + if (isMixed(ch)) { + tmp += MIXED[ch]; + break; + } + if (isAlphaUpper(ch)) { + submode = SUBMODE_ALPHA; + tmp += (wchar_t)28; + continue; + } + if (isAlphaLower(ch)) { + submode = SUBMODE_LOWER; + tmp += (wchar_t)27; + continue; + } + if (startpos + idx + 1 < count) { + wchar_t next = msg[startpos + idx + 1]; + if (isPunctuation(next)) { + submode = SUBMODE_PUNCTUATION; + tmp += (wchar_t)25; + continue; + } + } + tmp += (wchar_t)29; + tmp += PUNCTUATION[ch]; + break; + default: + if (isPunctuation(ch)) { + tmp += PUNCTUATION[ch]; + break; + } + submode = SUBMODE_ALPHA; + tmp += (wchar_t)29; + continue; + } + idx++; + if (idx >= count) { + break; + } + } + wchar_t h = 0; + int32_t len = tmp.GetLength(); + for (int32_t i = 0; i < len; i++) { + bool odd = (i % 2) != 0; + if (odd) { + h = (wchar_t)((h * 30) + tmp[i]); + sb += h; + } else { + h = tmp[i]; + } + } + if ((len % 2) != 0) { + sb += (wchar_t)((h * 30) + 29); + } + return submode; +} +void CBC_PDF417HighLevelEncoder::encodeBinary(std::vector* bytes, + int32_t startpos, + int32_t count, + int32_t startmode, + WideString& sb) { + if (count == 1 && startmode == TEXT_COMPACTION) { + sb += (wchar_t)SHIFT_TO_BYTE; + } + int32_t idx = startpos; + int32_t i = 0; + if (count >= 6) { + sb += (wchar_t)LATCH_TO_BYTE; + wchar_t chars[5]; + while ((startpos + count - idx) >= 6) { + int64_t t = 0; + for (i = 0; i < 6; i++) { + t <<= 8; + t += (*bytes)[idx + i] & 0xff; + } + for (i = 0; i < 5; i++) { + chars[i] = (wchar_t)(t % 900); + t /= 900; + } + for (i = 4; i >= 0; i--) { + sb += (chars[i]); + } + idx += 6; + } + } + if (idx < startpos + count) { + sb += (wchar_t)LATCH_TO_BYTE_PADDED; + } + for (i = idx; i < startpos + count; i++) { + int32_t ch = (*bytes)[i] & 0xff; + sb += (wchar_t)ch; + } +} +void CBC_PDF417HighLevelEncoder::encodeNumeric(WideString msg, + int32_t startpos, + int32_t count, + WideString& sb) { + int32_t idx = 0; + BigInteger num900 = 900; + while (idx < count) { + WideString tmp; + int32_t len = 44 < count - idx ? 44 : count - idx; + ByteString part = + ((wchar_t)'1' + msg.Mid(startpos + idx, len)).UTF8Encode(); + BigInteger bigint = stringToBigInteger(part.c_str()); + do { + int32_t c = (bigint % num900).toInt(); + tmp += (wchar_t)(c); + bigint = bigint / num900; + } while (!bigint.isZero()); + for (int32_t i = tmp.GetLength() - 1; i >= 0; i--) { + sb += tmp[i]; + } + idx += len; + } +} +bool CBC_PDF417HighLevelEncoder::isDigit(wchar_t ch) { + return ch >= '0' && ch <= '9'; +} +bool CBC_PDF417HighLevelEncoder::isAlphaUpper(wchar_t ch) { + return ch == ' ' || (ch >= 'A' && ch <= 'Z'); +} +bool CBC_PDF417HighLevelEncoder::isAlphaLower(wchar_t ch) { + return ch == ' ' || (ch >= 'a' && ch <= 'z'); +} +bool CBC_PDF417HighLevelEncoder::isMixed(wchar_t ch) { + return MIXED[ch] != -1; +} +bool CBC_PDF417HighLevelEncoder::isPunctuation(wchar_t ch) { + return PUNCTUATION[ch] != -1; +} +bool CBC_PDF417HighLevelEncoder::isText(wchar_t ch) { + return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126); +} +int32_t CBC_PDF417HighLevelEncoder::determineConsecutiveDigitCount( + WideString msg, + int32_t startpos) { + int32_t count = 0; + int32_t len = msg.GetLength(); + int32_t idx = startpos; + if (idx < len) { + wchar_t ch = msg[idx]; + while (isDigit(ch) && idx < len) { + count++; + idx++; + if (idx < len) { + ch = msg[idx]; + } + } + } + return count; +} +int32_t CBC_PDF417HighLevelEncoder::determineConsecutiveTextCount( + WideString msg, + int32_t startpos) { + int32_t len = msg.GetLength(); + int32_t idx = startpos; + while (idx < len) { + wchar_t ch = msg[idx]; + int32_t numericCount = 0; + while (numericCount < 13 && isDigit(ch) && idx < len) { + numericCount++; + idx++; + if (idx < len) { + ch = msg[idx]; + } + } + if (numericCount >= 13) { + return idx - startpos - numericCount; + } + if (numericCount > 0) { + continue; + } + ch = msg[idx]; + if (!isText(ch)) { + break; + } + idx++; + } + return idx - startpos; +} +int32_t CBC_PDF417HighLevelEncoder::determineConsecutiveBinaryCount( + WideString msg, + std::vector* bytes, + int32_t startpos, + int32_t& e) { + int32_t len = msg.GetLength(); + int32_t idx = startpos; + while (idx < len) { + wchar_t ch = msg[idx]; + int32_t numericCount = 0; + while (numericCount < 13 && isDigit(ch)) { + numericCount++; + int32_t i = idx + numericCount; + if (i >= len) { + break; + } + ch = msg[i]; + } + if (numericCount >= 13) { + return idx - startpos; + } + int32_t textCount = 0; + while (textCount < 5 && isText(ch)) { + textCount++; + int32_t i = idx + textCount; + if (i >= len) { + break; + } + ch = msg[i]; + } + if (textCount >= 5) { + return idx - startpos; + } + ch = msg[idx]; + if ((*bytes)[idx] == 63 && ch != '?') { + e = BCExceptionNonEncodableCharacterDetected; + return -1; + } + idx++; + } + return idx - startpos; +} diff --git a/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..2701c810fbbdcfaf45048e67a3bf5aa30a37bd66 --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h @@ -0,0 +1,75 @@ +// 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 FXBARCODE_PDF417_BC_PDF417HIGHLEVELENCODER_H_ +#define FXBARCODE_PDF417_BC_PDF417HIGHLEVELENCODER_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "fxbarcode/pdf417/BC_PDF417Compaction.h" + +class CBC_PDF417HighLevelEncoder { + public: + static WideString encodeHighLevel(WideString msg, + Compaction compaction, + int32_t& e); + static void Inverse(); + static void Initialize(); + static void Finalize(); + + private: + static int32_t TEXT_COMPACTION; + static int32_t BYTE_COMPACTION; + static int32_t NUMERIC_COMPACTION; + static int32_t SUBMODE_PUNCTUATION; + static int32_t LATCH_TO_TEXT; + static int32_t LATCH_TO_BYTE_PADDED; + static int32_t LATCH_TO_NUMERIC; + static int32_t SHIFT_TO_BYTE; + static int32_t LATCH_TO_BYTE; + static uint8_t TEXT_MIXED_RAW[]; + static uint8_t TEXT_PUNCTUATION_RAW[]; + static int32_t MIXED[128]; + static int32_t PUNCTUATION[128]; + static int32_t encodeText(WideString msg, + int32_t startpos, + int32_t count, + WideString& sb, + int32_t initialSubmode); + static void encodeBinary(std::vector* bytes, + int32_t startpos, + int32_t count, + int32_t startmode, + WideString& sb); + static void encodeNumeric(WideString msg, + int32_t startpos, + int32_t count, + WideString& sb); + static bool isDigit(wchar_t ch); + static bool isAlphaUpper(wchar_t ch); + static bool isAlphaLower(wchar_t ch); + static bool isMixed(wchar_t ch); + static bool isPunctuation(wchar_t ch); + static bool isText(wchar_t ch); + static int32_t determineConsecutiveDigitCount(WideString msg, + int32_t startpos); + static int32_t determineConsecutiveTextCount(WideString msg, + int32_t startpos); + static int32_t determineConsecutiveBinaryCount(WideString msg, + std::vector* bytes, + int32_t startpos, + int32_t& e); + + friend class PDF417HighLevelEncoder_EncodeNumeric_Test; + friend class PDF417HighLevelEncoder_EncodeBinary_Test; + friend class PDF417HighLevelEncoder_EncodeText_Test; + friend class PDF417HighLevelEncoder_ConsecutiveDigitCount_Test; + friend class PDF417HighLevelEncoder_ConsecutiveTextCount_Test; + friend class PDF417HighLevelEncoder_ConsecutiveBinaryCount_Test; +}; + +#endif // FXBARCODE_PDF417_BC_PDF417HIGHLEVELENCODER_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp similarity index 92% rename from xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp rename to fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp index 2cd60fef4133289d59af06d68892adac26de91d1..ad4a59af40e1d80e6925b9ed846c9867e12b78d8 100644 --- a/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp +++ b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp @@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "core/fxcrt/fx_basic.h" -#include "testing/fx_string_testhelpers.h" +#include "fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" #include "testing/gtest/include/gtest/gtest.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" TEST(PDF417HighLevelEncoder, EncodeHighLevel) { // TODO(tsepez): implement test cases. @@ -43,14 +41,14 @@ TEST(PDF417HighLevelEncoder, EncodeBinary) { CBC_PDF417HighLevelEncoder::Initialize(); for (size_t i = 0; i < FX_ArraySize(encode_binary_cases); ++i) { EncodeBinaryCase* ptr = &encode_binary_cases[i]; - CFX_ArrayTemplate input_array; + std::vector input_array; size_t input_length = strlen(ptr->input); - input_array.SetSize(input_length); + input_array.resize(input_length); for (size_t j = 0; j < input_length; ++j) { - input_array.SetAt(j, ptr->input[j]); + input_array[j] = ptr->input[j]; } - CFX_WideString expected(ptr->expected, ptr->expected_length); - CFX_WideString result; + WideString expected(ptr->expected, ptr->expected_length); + WideString result; CBC_PDF417HighLevelEncoder::encodeBinary( &input_array, ptr->offset, ptr->count, ptr->startmode, result); EXPECT_EQ(expected, result) << " for case number " << i; @@ -111,9 +109,9 @@ TEST(PDF417HighLevelEncoder, EncodeNumeric) { CBC_PDF417HighLevelEncoder::Initialize(); for (size_t i = 0; i < FX_ArraySize(encode_numeric_cases); ++i) { EncodeNumericCase* ptr = &encode_numeric_cases[i]; - CFX_WideString input(ptr->input); - CFX_WideString expected(ptr->expected, ptr->expected_length); - CFX_WideString result; + WideString input(ptr->input); + WideString expected(ptr->expected, ptr->expected_length); + WideString result; CBC_PDF417HighLevelEncoder::encodeNumeric(input, ptr->offset, ptr->count, result); EXPECT_EQ(expected, result) << " for case number " << i; @@ -158,7 +156,7 @@ TEST(PDF417HighLevelEncoder, ConsecutiveDigitCount) { CBC_PDF417HighLevelEncoder::Initialize(); for (size_t i = 0; i < FX_ArraySize(consecutive_digit_cases); ++i) { ConsecutiveDigitCase* ptr = &consecutive_digit_cases[i]; - CFX_WideString input(ptr->input); + WideString input(ptr->input); int actual_count = CBC_PDF417HighLevelEncoder::determineConsecutiveDigitCount(input, ptr->offset); @@ -219,7 +217,7 @@ TEST(PDF417HighLevelEncoder, ConsecutiveTextCount) { CBC_PDF417HighLevelEncoder::Initialize(); for (size_t i = 0; i < FX_ArraySize(consecutive_text_cases); ++i) { ConsecutiveTextCase* ptr = &consecutive_text_cases[i]; - CFX_WideString input(ptr->input); + WideString input(ptr->input); int actual_count = CBC_PDF417HighLevelEncoder::determineConsecutiveTextCount(input, ptr->offset); diff --git a/fxbarcode/pdf417/BC_PDF417Writer.cpp b/fxbarcode/pdf417/BC_PDF417Writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fec9747374003839c01fbe50d3fca60a1597984 --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417Writer.cpp @@ -0,0 +1,111 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/pdf417/BC_PDF417Writer.h" + +#include + +#include "fxbarcode/BC_TwoDimWriter.h" +#include "fxbarcode/common/BC_CommonBitArray.h" +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/pdf417/BC_PDF417.h" +#include "fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h" +#include "fxbarcode/pdf417/BC_PDF417Compaction.h" + +CBC_PDF417Writer::CBC_PDF417Writer() { + m_bFixedSize = false; +} +CBC_PDF417Writer::~CBC_PDF417Writer() { + m_bTruncated = true; +} +bool CBC_PDF417Writer::SetErrorCorrectionLevel(int32_t level) { + if (level < 0 || level > 8) { + return false; + } + m_iCorrectLevel = level; + return true; +} +void CBC_PDF417Writer::SetTruncated(bool truncated) { + m_bTruncated = truncated; +} + +uint8_t* CBC_PDF417Writer::Encode(const WideString& contents, + int32_t& outWidth, + int32_t& outHeight) { + CBC_PDF417 encoder; + int32_t col = (m_Width / m_ModuleWidth - 69) / 17; + int32_t row = m_Height / (m_ModuleWidth * 20); + if (row >= 3 && row <= 90 && col >= 1 && col <= 30) + encoder.setDimensions(col, col, row, row); + else if (col >= 1 && col <= 30) + encoder.setDimensions(col, col, 90, 3); + else if (row >= 3 && row <= 90) + encoder.setDimensions(30, 1, row, row); + if (!encoder.generateBarcodeLogic(contents, m_iCorrectLevel)) + return nullptr; + + int32_t lineThickness = 2; + int32_t aspectRatio = 4; + CBC_BarcodeMatrix* barcodeMatrix = encoder.getBarcodeMatrix(); + std::vector originalScale = barcodeMatrix->getScaledMatrix( + lineThickness, aspectRatio * lineThickness); + int32_t width = outWidth; + int32_t height = outHeight; + outWidth = barcodeMatrix->getWidth(); + outHeight = barcodeMatrix->getHeight(); + bool rotated = false; + if ((height > width) ^ (outWidth < outHeight)) { + rotateArray(originalScale, outHeight, outWidth); + rotated = true; + int32_t temp = outHeight; + outHeight = outWidth; + outWidth = temp; + } + int32_t scaleX = width / outWidth; + int32_t scaleY = height / outHeight; + int32_t scale = std::min(scaleX, scaleY); + if (scale > 1) { + originalScale = barcodeMatrix->getScaledMatrix( + scale * lineThickness, scale * aspectRatio * lineThickness); + if (rotated) { + rotateArray(originalScale, outHeight, outWidth); + int32_t temp = outHeight; + outHeight = outWidth; + outWidth = temp; + } + } + uint8_t* result = FX_Alloc2D(uint8_t, outHeight, outWidth); + memcpy(result, originalScale.data(), outHeight * outWidth); + return result; +} + +void CBC_PDF417Writer::rotateArray(std::vector& bitarray, + int32_t height, + int32_t width) { + std::vector temp = bitarray; + for (int32_t ii = 0; ii < height; ii++) { + int32_t inverseii = height - ii - 1; + for (int32_t jj = 0; jj < width; jj++) { + bitarray[jj * height + inverseii] = temp[ii * width + jj]; + } + } +} diff --git a/fxbarcode/pdf417/BC_PDF417Writer.h b/fxbarcode/pdf417/BC_PDF417Writer.h new file mode 100644 index 0000000000000000000000000000000000000000..ef5961653ec4a68a7bd4e0b8a3fa6697bbec9f14 --- /dev/null +++ b/fxbarcode/pdf417/BC_PDF417Writer.h @@ -0,0 +1,37 @@ +// 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 FXBARCODE_PDF417_BC_PDF417WRITER_H_ +#define FXBARCODE_PDF417_BC_PDF417WRITER_H_ + +#include + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "fxbarcode/BC_TwoDimWriter.h" + +class CBC_PDF417Writer : public CBC_TwoDimWriter { + public: + CBC_PDF417Writer(); + ~CBC_PDF417Writer() override; + + uint8_t* Encode(const WideString& contents, + int32_t& outWidth, + int32_t& outHeight); + + // CBC_TwoDimWriter + bool SetErrorCorrectionLevel(int32_t level) override; + + void SetTruncated(bool truncated); + + private: + void rotateArray(std::vector& bitarray, + int32_t width, + int32_t height); + bool m_bTruncated; +}; + +#endif // FXBARCODE_PDF417_BC_PDF417WRITER_H_ diff --git a/fxbarcode/qrcode/BC_QRCodeWriter.cpp b/fxbarcode/qrcode/BC_QRCodeWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb35af3867ce49097b6c4c204ae5e53c8f116b94 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCodeWriter.cpp @@ -0,0 +1,88 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/BC_TwoDimWriter.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/qrcode/BC_QRCodeWriter.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderEncoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" + +CBC_QRCodeWriter::CBC_QRCodeWriter() { + m_bFixedSize = true; + m_iCorrectLevel = 1; +} + +CBC_QRCodeWriter::~CBC_QRCodeWriter() {} + +void CBC_QRCodeWriter::ReleaseAll() { + delete CBC_ReedSolomonGF256::QRCodeField; + CBC_ReedSolomonGF256::QRCodeField = nullptr; + delete CBC_ReedSolomonGF256::DataMatrixField; + CBC_ReedSolomonGF256::DataMatrixField = nullptr; + CBC_QRCoderMode::Destroy(); + CBC_QRCoderErrorCorrectionLevel::Destroy(); + CBC_QRCoderVersion::Destroy(); +} + +bool CBC_QRCodeWriter::SetErrorCorrectionLevel(int32_t level) { + if (level < 0 || level > 3) { + return false; + } + m_iCorrectLevel = level; + return true; +} + +uint8_t* CBC_QRCodeWriter::Encode(const WideString& contents, + int32_t ecLevel, + int32_t& outWidth, + int32_t& outHeight) { + CBC_QRCoderErrorCorrectionLevel* ec = nullptr; + switch (ecLevel) { + case 0: + ec = CBC_QRCoderErrorCorrectionLevel::L; + break; + case 1: + ec = CBC_QRCoderErrorCorrectionLevel::M; + break; + case 2: + ec = CBC_QRCoderErrorCorrectionLevel::Q; + break; + case 3: + ec = CBC_QRCoderErrorCorrectionLevel::H; + break; + default: + return nullptr; + } + CBC_QRCoder qr; + if (!CBC_QRCoderEncoder::Encode(contents, ec, &qr)) + return nullptr; + + outWidth = qr.GetMatrixWidth(); + outHeight = qr.GetMatrixWidth(); + uint8_t* result = FX_Alloc2D(uint8_t, outWidth, outHeight); + memcpy(result, qr.GetMatrix()->GetArray(), outWidth * outHeight); + return result; +} diff --git a/fxbarcode/qrcode/BC_QRCodeWriter.h b/fxbarcode/qrcode/BC_QRCodeWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..3b3efc90ca28112b2f6eb6e547044f2dbc0ecd1b --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCodeWriter.h @@ -0,0 +1,29 @@ +// 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 FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ +#define FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ + +#include "fxbarcode/BC_TwoDimWriter.h" + +class CBC_TwoDimWriter; +class CBC_QRCodeWriter : public CBC_TwoDimWriter { + public: + CBC_QRCodeWriter(); + ~CBC_QRCodeWriter() override; + + static void ReleaseAll(); + + uint8_t* Encode(const WideString& contents, + int32_t ecLevel, + int32_t& outWidth, + int32_t& outHeight); + + // CBC_TwoDimWriter + bool SetErrorCorrectionLevel(int32_t level) override; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoder.cpp b/fxbarcode/qrcode/BC_QRCoder.cpp similarity index 88% rename from xfa/fxbarcode/qrcode/BC_QRCoder.cpp rename to fxbarcode/qrcode/BC_QRCoder.cpp index a5c849780dbc3ac404e959e7e05d1e4112ac8909..b0a24fa27c4f0a3983b33c2251bd01754cdaccff 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoder.cpp +++ b/fxbarcode/qrcode/BC_QRCoder.cpp @@ -22,11 +22,11 @@ #include -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMode.h" -#include "xfa/fxbarcode/utils.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/utils.h" CBC_QRCoder::CBC_QRCoder() : m_mode(nullptr), @@ -42,11 +42,11 @@ CBC_QRCoder::CBC_QRCoder() CBC_QRCoder::~CBC_QRCoder() {} CBC_QRCoderMode* CBC_QRCoder::GetMode() const { - return m_mode; + return m_mode.Get(); } -CBC_QRCoderErrorCorrectionLevel* CBC_QRCoder::GetECLevel() const { - return m_ecLevel; +const CBC_QRCoderErrorCorrectionLevel* CBC_QRCoder::GetECLevel() const { + return m_ecLevel.Get(); } int32_t CBC_QRCoder::GetVersion() const { @@ -104,7 +104,7 @@ void CBC_QRCoder::SetMode(CBC_QRCoderMode* value) { m_mode = value; } -void CBC_QRCoder::SetECLevel(CBC_QRCoderErrorCorrectionLevel* ecLevel) { +void CBC_QRCoder::SetECLevel(const CBC_QRCoderErrorCorrectionLevel* ecLevel) { m_ecLevel = ecLevel; } diff --git a/xfa/fxbarcode/qrcode/BC_QRCoder.h b/fxbarcode/qrcode/BC_QRCoder.h similarity index 79% rename from xfa/fxbarcode/qrcode/BC_QRCoder.h rename to fxbarcode/qrcode/BC_QRCoder.h index 5e949920a7664bb005851e2d9498c2cf07654248..af53ded49dd238d31bd997cda8ef25a9b1fe190b 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoder.h +++ b/fxbarcode/qrcode/BC_QRCoder.h @@ -4,11 +4,13 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODER_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODER_H_ +#ifndef FXBARCODE_QRCODE_BC_QRCODER_H_ +#define FXBARCODE_QRCODE_BC_QRCODER_H_ #include +#include "core/fxcrt/unowned_ptr.h" + class CBC_QRCoderErrorCorrectionLevel; class CBC_QRCoderMode; class CBC_CommonByteMatrix; @@ -23,7 +25,7 @@ class CBC_QRCoder { static bool IsValidMaskPattern(int32_t maskPattern); CBC_QRCoderMode* GetMode() const; - CBC_QRCoderErrorCorrectionLevel* GetECLevel() const; + const CBC_QRCoderErrorCorrectionLevel* GetECLevel() const; int32_t GetVersion() const; int32_t GetMatrixWidth() const; int32_t GetMaskPattern() const; @@ -37,7 +39,7 @@ class CBC_QRCoder { bool IsValid(); void SetMode(CBC_QRCoderMode* value); - void SetECLevel(CBC_QRCoderErrorCorrectionLevel* ecLevel); + void SetECLevel(const CBC_QRCoderErrorCorrectionLevel* ecLevel); void SetVersion(int32_t version); void SetMatrixWidth(int32_t width); void SetMaskPattern(int32_t pattern); @@ -48,8 +50,8 @@ class CBC_QRCoder { void SetMatrix(std::unique_ptr pMatrix); private: - CBC_QRCoderMode* m_mode; - CBC_QRCoderErrorCorrectionLevel* m_ecLevel; + UnownedPtr m_mode; + UnownedPtr m_ecLevel; int32_t m_version; int32_t m_matrixWidth; int32_t m_maskPattern; @@ -60,4 +62,4 @@ class CBC_QRCoder { std::unique_ptr m_matrix; }; -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODER_H_ +#endif // FXBARCODE_QRCODE_BC_QRCODER_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderBitVector.cpp b/fxbarcode/qrcode/BC_QRCoderBitVector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a41ad0910d3612edb263d395e350abaad0057b0 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBitVector.cpp @@ -0,0 +1,105 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" + +#include "core/fxcrt/fx_memory.h" +#include "fxbarcode/utils.h" + +CBC_QRCoderBitVector::CBC_QRCoderBitVector() {} + +CBC_QRCoderBitVector::~CBC_QRCoderBitVector() {} + +int32_t CBC_QRCoderBitVector::At(size_t index, int32_t& e) const { + if (index >= m_sizeInBits) { + e = BCExceptionBadIndexException; + return 0; + } + int32_t value = m_array[index >> 3] & 0xff; + return (value >> (7 - (index & 0x7))) & 1; +} + +size_t CBC_QRCoderBitVector::sizeInBytes() const { + return (m_sizeInBits + 7) >> 3; +} + +size_t CBC_QRCoderBitVector::Size() const { + return m_sizeInBits; +} + +void CBC_QRCoderBitVector::AppendBit(int32_t bit) { + ASSERT(bit == 0 || bit == 1); + int32_t numBitsInLastByte = m_sizeInBits & 0x7; + if (numBitsInLastByte == 0) { + AppendByte(0); + m_sizeInBits -= 8; + } + m_array[m_sizeInBits >> 3] |= (bit << (7 - numBitsInLastByte)); + ++m_sizeInBits; +} + +void CBC_QRCoderBitVector::AppendBits(int32_t value, int32_t numBits) { + ASSERT(numBits > 0); + ASSERT(numBits <= 32); + + int32_t numBitsLeft = numBits; + while (numBitsLeft > 0) { + if ((m_sizeInBits & 0x7) == 0 && numBitsLeft >= 8) { + AppendByte(static_cast((value >> (numBitsLeft - 8)) & 0xff)); + numBitsLeft -= 8; + } else { + AppendBit((value >> (numBitsLeft - 1)) & 1); + --numBitsLeft; + } + } +} + +void CBC_QRCoderBitVector::AppendBitVector(CBC_QRCoderBitVector* bits) { + int32_t size = bits->Size(); + for (int32_t i = 0; i < size; i++) { + int e = BCExceptionNO; + int32_t num = bits->At(i, e); + ASSERT(e == BCExceptionNO); + AppendBit(num); + } +} + +bool CBC_QRCoderBitVector::XOR(const CBC_QRCoderBitVector* other) { + if (m_sizeInBits != other->Size()) + return false; + + const auto* pOther = other->GetArray(); + for (size_t i = 0; i < sizeInBytes(); ++i) + m_array[i] ^= pOther[i]; + return true; +} + +const uint8_t* CBC_QRCoderBitVector::GetArray() const { + return m_array.data(); +} + +void CBC_QRCoderBitVector::AppendByte(int8_t value) { + if ((m_sizeInBits >> 3) == m_array.size()) + m_array.push_back(0); + m_array[m_sizeInBits >> 3] = value; + m_sizeInBits += 8; +} diff --git a/fxbarcode/qrcode/BC_QRCoderBitVector.h b/fxbarcode/qrcode/BC_QRCoderBitVector.h new file mode 100644 index 0000000000000000000000000000000000000000..0ebeb60ab8a33ba23ce703a94cad17acbc5a4a0d --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBitVector.h @@ -0,0 +1,37 @@ +// 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 FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ +#define FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ + +#include +#include + +#include + +class CBC_QRCoderBitVector { + public: + CBC_QRCoderBitVector(); + ~CBC_QRCoderBitVector(); + + const uint8_t* GetArray() const; + int32_t At(size_t index, int32_t& e) const; + size_t Size() const; + size_t sizeInBytes() const; + + void AppendBit(int32_t bit); + void AppendBits(int32_t value, int32_t numBits); + void AppendBitVector(CBC_QRCoderBitVector* bits); + bool XOR(const CBC_QRCoderBitVector* other); + + private: + void AppendByte(int8_t value); + + size_t m_sizeInBits = 0; + std::vector m_array; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp b/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp similarity index 78% rename from xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp rename to fxbarcode/qrcode/BC_QRCoderBlockPair.cpp index 8dc73c4be4a010f1447ec527e42ae9b51c8a3478..9ac93e9b14f74baab81324a8bd67dd719ad7d8bd 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp +++ b/fxbarcode/qrcode/BC_QRCoderBlockPair.cpp @@ -20,17 +20,13 @@ * limitations under the License. */ -#include "xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.h" +#include "fxbarcode/qrcode/BC_QRCoderBlockPair.h" #include -#include "xfa/fxbarcode/common/BC_CommonByteArray.h" +#include "fxbarcode/common/BC_CommonByteArray.h" -CBC_QRCoderBlockPair::CBC_QRCoderBlockPair( - std::unique_ptr data, - std::unique_ptr errorCorrection) - : m_dataBytes(std::move(data)), - m_errorCorrectionBytes(std::move(errorCorrection)) {} +CBC_QRCoderBlockPair::CBC_QRCoderBlockPair() {} CBC_QRCoderBlockPair::~CBC_QRCoderBlockPair() {} @@ -42,3 +38,10 @@ const CBC_CommonByteArray* CBC_QRCoderBlockPair::GetErrorCorrectionBytes() const { return m_errorCorrectionBytes.get(); } + +void CBC_QRCoderBlockPair::SetData( + std::unique_ptr data, + std::unique_ptr errorCorrection) { + m_dataBytes = std::move(data); + m_errorCorrectionBytes = std::move(errorCorrection); +} diff --git a/fxbarcode/qrcode/BC_QRCoderBlockPair.h b/fxbarcode/qrcode/BC_QRCoderBlockPair.h new file mode 100644 index 0000000000000000000000000000000000000000..9d571f34107e8463da36d25b2c24947b11dc57e1 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderBlockPair.h @@ -0,0 +1,29 @@ +// 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 FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ +#define FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ + +#include + +class CBC_CommonByteArray; + +class CBC_QRCoderBlockPair { + public: + CBC_QRCoderBlockPair(); + ~CBC_QRCoderBlockPair(); + + const CBC_CommonByteArray* GetDataBytes() const; + const CBC_CommonByteArray* GetErrorCorrectionBytes() const; + void SetData(std::unique_ptr data, + std::unique_ptr errorCorrection); + + private: + std::unique_ptr m_dataBytes; + std::unique_ptr m_errorCorrectionBytes; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp b/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28f46882d9c1b2fc7ea1da9c76d1d8bb1dd5eb44 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderECBlocks.h" + +#include "fxbarcode/qrcode/BC_QRCoderECBlocksData.h" + +CBC_QRCoderECBlocks::CBC_QRCoderECBlocks(const CBC_QRCoderECBlockData& data) + : m_data(data) {} + +CBC_QRCoderECBlocks::~CBC_QRCoderECBlocks() {} + +int32_t CBC_QRCoderECBlocks::GetECCodeWordsPerBlock() const { + return m_data.ecCodeWordsPerBlock; +} + +int32_t CBC_QRCoderECBlocks::GetNumBlocks() const { + return m_data.count1 + m_data.count2; +} + +int32_t CBC_QRCoderECBlocks::GetTotalECCodeWords() const { + return GetECCodeWordsPerBlock() * GetNumBlocks(); +} + +int32_t CBC_QRCoderECBlocks::GetTotalDataCodeWords() const { + return m_data.count1 * (m_data.dataCodeWords1 + GetECCodeWordsPerBlock()) + + m_data.count2 * (m_data.dataCodeWords2 + GetECCodeWordsPerBlock()); +} diff --git a/fxbarcode/qrcode/BC_QRCoderECBlocks.h b/fxbarcode/qrcode/BC_QRCoderECBlocks.h new file mode 100644 index 0000000000000000000000000000000000000000..6c4f1cd9a710247d00914b830354faaeb0260449 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECBlocks.h @@ -0,0 +1,31 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ +#define FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ + +#include + +#include + +struct CBC_QRCoderECBlockData; + +class CBC_QRCoderECBlocks { + public: + explicit CBC_QRCoderECBlocks(const CBC_QRCoderECBlockData& data); + ~CBC_QRCoderECBlocks(); + + int32_t GetNumBlocks() const; + int32_t GetTotalECCodeWords() const; + int32_t GetTotalDataCodeWords() const; + + private: + int32_t GetECCodeWordsPerBlock() const; + + const CBC_QRCoderECBlockData& m_data; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderECBlocksData.cpp b/fxbarcode/qrcode/BC_QRCoderECBlocksData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26ff7483734a629ea3837bd611896ef38a53499d --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECBlocksData.cpp @@ -0,0 +1,180 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderECBlocksData.h" + +const CBC_QRCoderECBlockData g_ECBData[40][4] = { + {{7, 1, 19, 0, 0}, {10, 1, 16, 0, 0}, {13, 1, 13, 0, 0}, {17, 1, 9, 0, 0}}, + {{10, 1, 34, 0, 0}, + {16, 1, 28, 0, 0}, + {22, 1, 22, 0, 0}, + {28, 1, 16, 0, 0}}, + {{15, 1, 55, 0, 0}, + {26, 1, 44, 0, 0}, + {18, 2, 17, 0, 0}, + {22, 2, 13, 0, 0}}, + {{20, 1, 80, 0, 0}, {18, 2, 32, 0, 0}, {26, 2, 24, 0, 0}, {16, 4, 9, 0, 0}}, + {{26, 1, 108, 0, 0}, + {24, 2, 43, 0, 0}, + {18, 2, 15, 2, 16}, + {22, 2, 11, 2, 12}}, + {{18, 2, 68, 0, 0}, + {16, 4, 27, 0, 0}, + {24, 4, 19, 0, 0}, + {28, 4, 15, 0, 0}}, + {{20, 2, 78, 0, 0}, + {18, 4, 31, 0, 0}, + {18, 2, 14, 4, 15}, + {26, 4, 13, 1, 14}}, + {{24, 2, 97, 0, 0}, + {22, 2, 38, 2, 39}, + {22, 4, 18, 2, 19}, + {26, 4, 14, 2, 15}}, + {{30, 2, 116, 0, 0}, + {22, 3, 36, 2, 37}, + {20, 4, 16, 4, 17}, + {24, 4, 12, 4, 13}}, + {{18, 2, 68, 2, 69}, + {26, 4, 43, 1, 44}, + {24, 6, 19, 2, 20}, + {28, 6, 15, 2, 16}}, + {{20, 4, 81, 0, 0}, + {30, 1, 50, 4, 51}, + {28, 4, 22, 4, 23}, + {24, 3, 12, 8, 13}}, + {{24, 2, 92, 2, 93}, + {22, 6, 36, 2, 37}, + {26, 4, 20, 6, 21}, + {28, 7, 14, 4, 15}}, + {{26, 4, 107, 0, 0}, + {22, 8, 37, 1, 38}, + {24, 8, 20, 4, 21}, + {22, 12, 11, 4, 12}}, + {{30, 3, 115, 1, 116}, + {24, 4, 40, 5, 41}, + {20, 11, 16, 5, 17}, + {24, 11, 12, 5, 13}}, + {{22, 5, 87, 1, 88}, + {24, 5, 41, 5, 42}, + {30, 5, 24, 7, 25}, + {24, 11, 12, 7, 13}}, + {{24, 5, 98, 1, 99}, + {28, 7, 45, 3, 46}, + {24, 15, 19, 2, 20}, + {30, 3, 15, 13, 16}}, + {{28, 1, 107, 5, 108}, + {28, 10, 46, 1, 47}, + {28, 1, 22, 15, 23}, + {28, 2, 14, 17, 15}}, + {{30, 5, 120, 1, 121}, + {26, 9, 43, 4, 44}, + {28, 17, 22, 1, 23}, + {28, 2, 14, 19, 15}}, + {{28, 3, 113, 4, 114}, + {26, 3, 44, 11, 45}, + {26, 17, 21, 4, 22}, + {26, 9, 13, 16, 14}}, + {{28, 3, 107, 5, 108}, + {26, 3, 41, 13, 42}, + {30, 15, 24, 5, 25}, + {28, 15, 15, 10, 16}}, + {{28, 4, 116, 4, 117}, + {26, 17, 42, 0, 0}, + {28, 17, 22, 6, 23}, + {30, 19, 16, 6, 17}}, + {{28, 2, 111, 7, 112}, + {28, 17, 46, 0, 0}, + {30, 7, 24, 16, 25}, + {24, 34, 13, 0, 0}}, + {{30, 4, 121, 5, 122}, + {28, 4, 47, 14, 48}, + {30, 11, 24, 14, 25}, + {30, 16, 15, 14, 16}}, + {{30, 6, 117, 4, 118}, + {28, 6, 45, 14, 46}, + {30, 11, 24, 16, 25}, + {30, 30, 16, 2, 17}}, + {{26, 8, 106, 4, 107}, + {28, 8, 47, 13, 48}, + {30, 7, 24, 22, 25}, + {30, 22, 15, 13, 16}}, + {{28, 10, 114, 2, 115}, + {28, 19, 46, 4, 47}, + {28, 28, 22, 6, 23}, + {30, 33, 16, 4, 17}}, + {{30, 8, 122, 4, 123}, + {28, 22, 45, 3, 46}, + {30, 8, 23, 26, 24}, + {30, 12, 15, 28, 16}}, + {{30, 3, 117, 10, 118}, + {28, 3, 45, 23, 46}, + {30, 4, 24, 31, 25}, + {30, 11, 15, 31, 16}}, + {{30, 7, 116, 7, 117}, + {28, 21, 45, 7, 46}, + {30, 1, 23, 37, 24}, + {30, 19, 15, 26, 16}}, + {{30, 5, 115, 10, 116}, + {28, 19, 47, 10, 48}, + {30, 15, 24, 25, 25}, + {30, 23, 15, 25, 16}}, + {{30, 13, 115, 3, 116}, + {28, 2, 46, 29, 47}, + {30, 42, 24, 1, 25}, + {30, 23, 15, 28, 16}}, + {{30, 17, 115, 0, 0}, + {28, 10, 46, 23, 47}, + {30, 10, 24, 35, 25}, + {30, 19, 15, 35, 16}}, + {{30, 17, 115, 1, 116}, + {28, 14, 46, 21, 47}, + {30, 29, 24, 19, 25}, + {30, 11, 15, 46, 16}}, + {{30, 13, 115, 6, 116}, + {28, 14, 46, 23, 47}, + {30, 44, 24, 7, 25}, + {30, 59, 16, 1, 17}}, + {{30, 12, 121, 7, 122}, + {28, 12, 47, 26, 48}, + {30, 39, 24, 14, 25}, + {30, 22, 15, 41, 16}}, + {{30, 6, 121, 14, 122}, + {28, 6, 47, 34, 48}, + {30, 46, 24, 10, 25}, + {30, 2, 15, 64, 16}}, + {{30, 17, 122, 4, 123}, + {28, 29, 46, 14, 47}, + {30, 49, 24, 10, 25}, + {30, 24, 15, 46, 16}}, + {{30, 4, 122, 18, 123}, + {28, 13, 46, 32, 47}, + {30, 48, 24, 14, 25}, + {30, 42, 15, 32, 16}}, + {{30, 20, 117, 4, 118}, + {28, 40, 47, 7, 48}, + {30, 43, 24, 22, 25}, + {30, 10, 15, 67, 16}}, + {{30, 19, 118, 6, 119}, + {28, 18, 47, 31, 48}, + {30, 34, 24, 34, 25}, + {30, 20, 15, 61, 16}}, +}; diff --git a/fxbarcode/qrcode/BC_QRCoderECBlocksData.h b/fxbarcode/qrcode/BC_QRCoderECBlocksData.h new file mode 100644 index 0000000000000000000000000000000000000000..7ed4ca468948e927c1b13c7b7820de8dd68a7b73 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderECBlocksData.h @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERECBLOCKSDATA_H_ +#define FXBARCODE_QRCODE_BC_QRCODERECBLOCKSDATA_H_ + +#include + +struct CBC_QRCoderECBlockData { + uint8_t ecCodeWordsPerBlock; + uint8_t count1; + uint8_t dataCodeWords1; + uint8_t count2; + uint8_t dataCodeWords2; +}; + +extern const CBC_QRCoderECBlockData g_ECBData[40][4]; + +#endif // FXBARCODE_QRCODE_BC_QRCODERECBLOCKSDATA_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderEncoder.cpp b/fxbarcode/qrcode/BC_QRCoderEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a44dfc39f6d8b02500bab81197fb5dc557c08f3a --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderEncoder.cpp @@ -0,0 +1,618 @@ +// 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 +// Original code is licensed as follows: +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderEncoder.h" + +#include +#include +#include + +#include "fxbarcode/BC_UtilCodingConvert.h" +#include "fxbarcode/common/BC_CommonByteArray.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomon.h" +#include "fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/qrcode/BC_QRCoderBlockPair.h" +#include "fxbarcode/qrcode/BC_QRCoderECBlocks.h" +#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h" +#include "fxbarcode/qrcode/BC_QRCoderMatrixUtil.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" +#include "third_party/base/ptr_util.h" + +using ModeStringPair = std::pair; + +namespace { + +// This is a mapping for an ASCII table, starting at an index of 32. +const int8_t g_alphaNumericTable[] = { + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 32-47 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 48-63 + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 64-79 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; + +int32_t GetAlphaNumericCode(int32_t code) { + if (code < 32) + return -1; + size_t code_index = static_cast(code - 32); + if (code_index >= FX_ArraySize(g_alphaNumericTable)) + return -1; + return g_alphaNumericTable[code_index]; +} + +void AppendNumericBytes(const ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t length = content.GetLength(); + int32_t i = 0; + while (i < length) { + int32_t num1 = content[i] - '0'; + if (i + 2 < length) { + int32_t num2 = content[i + 1] - '0'; + int32_t num3 = content[i + 2] - '0'; + bits->AppendBits(num1 * 100 + num2 * 10 + num3, 10); + i += 3; + } else if (i + 1 < length) { + int32_t num2 = content[i + 1] - '0'; + bits->AppendBits(num1 * 10 + num2, 7); + i += 2; + } else { + bits->AppendBits(num1, 4); + i++; + } + } +} + +void AppendAlphaNumericBytes(const ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t length = content.GetLength(); + int32_t i = 0; + while (i < length) { + int32_t code1 = GetAlphaNumericCode(content[i]); + if (code1 == -1) { + e = BCExceptionInvalidateCharacter; + return; + } + if (i + 1 < length) { + int32_t code2 = GetAlphaNumericCode(content[i + 1]); + if (code2 == -1) { + e = BCExceptionInvalidateCharacter; + return; + } + bits->AppendBits(code1 * 45 + code2, 11); + i += 2; + } else { + bits->AppendBits(code1, 6); + i++; + } + } +} + +void AppendGBKBytes(const ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + int32_t length = content.GetLength(); + uint32_t value = 0; + for (int32_t i = 0; i < length; i += 2) { + value = (uint32_t)(content[i] << 8 | content[i + 1]); + if (value <= 0xAAFE && value >= 0xA1A1) { + value -= 0xA1A1; + } else if (value <= 0xFAFE && value >= 0xB0A1) { + value -= 0xA6A1; + } else { + e = BCExceptionInvalidateCharacter; + return; + } + value = (uint32_t)((value >> 8) * 0x60) + (uint32_t)(value & 0xff); + bits->AppendBits(value, 13); + } +} + +void Append8BitBytes(const ByteString& content, + CBC_QRCoderBitVector* bits, + ByteString encoding, + int32_t& e) { + for (size_t i = 0; i < content.GetLength(); i++) + bits->AppendBits(content[i], 8); +} + +void AppendKanjiBytes(const ByteString& content, + CBC_QRCoderBitVector* bits, + int32_t& e) { + std::vector bytes; + uint32_t value = 0; + for (size_t i = 0; i < bytes.size(); i += 2) { + value = (uint32_t)((content[i] << 8) | content[i + 1]); + if (value <= 0x9ffc && value >= 0x8140) { + value -= 0x8140; + } else if (value <= 0xebbf && value >= 0xe040) { + value -= 0xc140; + } else { + e = BCExceptionInvalidateCharacter; + return; + } + value = (uint32_t)((value >> 8) * 0xc0) + (uint32_t)(value & 0xff); + bits->AppendBits(value, 13); + } +} + +void AppendModeInfo(CBC_QRCoderMode* mode, CBC_QRCoderBitVector* bits) { + bits->AppendBits(mode->GetBits(), 4); + if (mode == CBC_QRCoderMode::sGBK) + bits->AppendBits(1, 4); +} + +bool AppendLengthInfo(int32_t numLetters, + int32_t version, + CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits) { + int32_t e = BCExceptionNO; + const auto* qcv = CBC_QRCoderVersion::GetVersionForNumber(version); + if (!qcv) + return false; + int32_t numBits = mode->GetCharacterCountBits(qcv->GetVersionNumber(), e); + if (e != BCExceptionNO) + return false; + if (numBits > ((1 << numBits) - 1)) + return true; + + if (mode == CBC_QRCoderMode::sGBK) + bits->AppendBits(numLetters / 2, numBits); + bits->AppendBits(numLetters, numBits); + return true; +} + +void AppendBytes(const ByteString& content, + CBC_QRCoderMode* mode, + CBC_QRCoderBitVector* bits, + ByteString encoding, + int32_t& e) { + if (mode == CBC_QRCoderMode::sNUMERIC) + AppendNumericBytes(content, bits, e); + else if (mode == CBC_QRCoderMode::sALPHANUMERIC) + AppendAlphaNumericBytes(content, bits, e); + else if (mode == CBC_QRCoderMode::sBYTE) + Append8BitBytes(content, bits, encoding, e); + else if (mode == CBC_QRCoderMode::sKANJI) + AppendKanjiBytes(content, bits, e); + else if (mode == CBC_QRCoderMode::sGBK) + AppendGBKBytes(content, bits, e); + else + e = BCExceptionUnsupportedMode; +} + +bool InitQRCode(int32_t numInputBytes, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoderMode* mode, + CBC_QRCoder* qrCode) { + qrCode->SetECLevel(ecLevel); + qrCode->SetMode(mode); + for (int32_t i = 1; i <= CBC_QRCoderVersion::kMaxVersion; ++i) { + const auto* version = CBC_QRCoderVersion::GetVersionForNumber(i); + int32_t numBytes = version->GetTotalCodeWords(); + const auto* ecBlocks = version->GetECBlocksForLevel(*ecLevel); + int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); + int32_t numRSBlocks = ecBlocks->GetNumBlocks(); + int32_t numDataBytes = numBytes - numEcBytes; + if (numDataBytes >= numInputBytes + 3) { + qrCode->SetVersion(i); + qrCode->SetNumTotalBytes(numBytes); + qrCode->SetNumDataBytes(numDataBytes); + qrCode->SetNumRSBlocks(numRSBlocks); + qrCode->SetNumECBytes(numEcBytes); + qrCode->SetMatrixWidth(version->GetDimensionForVersion()); + return true; + } + } + return false; +} + +std::unique_ptr GenerateECBytes( + CBC_CommonByteArray* dataBytes, + int32_t numEcBytesInBlock) { + int32_t numDataBytes = dataBytes->Size(); + std::vector toEncode(numDataBytes + numEcBytesInBlock); + for (int32_t i = 0; i < numDataBytes; ++i) + toEncode[i] = dataBytes->At(i); + CBC_ReedSolomonEncoder encode(CBC_ReedSolomonGF256::QRCodeField); + encode.Init(); + if (!encode.Encode(&toEncode, numEcBytesInBlock)) + return nullptr; + auto ecBytes = pdfium::MakeUnique(numEcBytesInBlock); + for (int32_t i = 0; i < numEcBytesInBlock; ++i) + ecBytes->Set(i, toEncode[numDataBytes + i]); + return ecBytes; +} + +int32_t GetSpanByVersion(CBC_QRCoderMode* modeFirst, + CBC_QRCoderMode* modeSecond, + int32_t versionNum, + int32_t& e) { + if (versionNum == 0) + return 0; + + if (modeFirst == CBC_QRCoderMode::sALPHANUMERIC && + modeSecond == CBC_QRCoderMode::sBYTE) { + if (versionNum >= 1 && versionNum <= 9) + return 11; + if (versionNum >= 10 && versionNum <= 26) + return 15; + if (versionNum >= 27 && versionNum <= CBC_QRCoderVersion::kMaxVersion) + return 16; + e = BCExceptionNoSuchVersion; + return 0; + } + if (modeSecond == CBC_QRCoderMode::sALPHANUMERIC && + modeFirst == CBC_QRCoderMode::sNUMERIC) { + if (versionNum >= 1 && versionNum <= 9) + return 13; + if (versionNum >= 10 && versionNum <= 26) + return 15; + if (versionNum >= 27 && versionNum <= CBC_QRCoderVersion::kMaxVersion) + return 17; + e = BCExceptionNoSuchVersion; + return 0; + } + if (modeSecond == CBC_QRCoderMode::sBYTE && + modeFirst == CBC_QRCoderMode::sNUMERIC) { + if (versionNum >= 1 && versionNum <= 9) + return 6; + if (versionNum >= 10 && versionNum <= 26) + return 8; + if (versionNum >= 27 && versionNum <= CBC_QRCoderVersion::kMaxVersion) + return 9; + e = BCExceptionNoSuchVersion; + return 0; + } + return -1; +} + +int32_t CalculateMaskPenalty(CBC_CommonByteMatrix* matrix) { + return CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(matrix) + + CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(matrix) + + CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(matrix) + + CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(matrix); +} + +int32_t ChooseMaskPattern(CBC_QRCoderBitVector* bits, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, + int32_t version, + CBC_CommonByteMatrix* matrix, + int32_t& e) { + int32_t minPenalty = 65535; + int32_t bestMaskPattern = -1; + for (int32_t maskPattern = 0; maskPattern < CBC_QRCoder::kNumMaskPatterns; + maskPattern++) { + CBC_QRCoderMatrixUtil::BuildMatrix(bits, ecLevel, version, maskPattern, + matrix, e); + if (e != BCExceptionNO) + return 0; + int32_t penalty = CalculateMaskPenalty(matrix); + if (penalty < minPenalty) { + minPenalty = penalty; + bestMaskPattern = maskPattern; + } + } + return bestMaskPattern; +} + +void GetNumDataBytesAndNumECBytesForBlockID(int32_t numTotalBytes, + int32_t numDataBytes, + int32_t numRSBlocks, + int32_t blockID, + int32_t& numDataBytesInBlock, + int32_t& numECBytesInBlock) { + if (blockID >= numRSBlocks) + return; + + int32_t numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; + int32_t numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; + int32_t numTotalBytesInGroup1 = numTotalBytes / numRSBlocks; + int32_t numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; + int32_t numDataBytesInGroup1 = numDataBytes / numRSBlocks; + int32_t numDataBytesInGroup2 = numDataBytesInGroup1 + 1; + int32_t numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; + int32_t numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; + if (blockID < numRsBlocksInGroup1) { + numDataBytesInBlock = numDataBytesInGroup1; + numECBytesInBlock = numEcBytesInGroup1; + } else { + numDataBytesInBlock = numDataBytesInGroup2; + numECBytesInBlock = numEcBytesInGroup2; + } +} + +bool TerminateBits(int32_t numDataBytes, CBC_QRCoderBitVector* bits) { + size_t capacity = numDataBytes << 3; + if (bits->Size() > capacity) + return false; + + for (int32_t i = 0; i < 4 && bits->Size() < capacity; ++i) + bits->AppendBit(0); + + int32_t numBitsInLastByte = bits->Size() % 8; + if (numBitsInLastByte > 0) { + int32_t numPaddingBits = 8 - numBitsInLastByte; + for (int32_t j = 0; j < numPaddingBits; ++j) + bits->AppendBit(0); + } + + if (bits->Size() % 8 != 0) + return false; + + int32_t numPaddingBytes = numDataBytes - bits->sizeInBytes(); + for (int32_t k = 0; k < numPaddingBytes; ++k) + bits->AppendBits(k % 2 ? 0x11 : 0xec, 8); + return bits->Size() == capacity; +} + +void MergeString(std::vector* result, + int32_t versionNum, + int32_t& e) { + size_t mergeNum = 0; + for (size_t i = 0; i + 1 < result->size(); i++) { + auto& element1 = (*result)[i]; + auto& element2 = (*result)[i + 1]; + if (element1.first == CBC_QRCoderMode::sALPHANUMERIC) { + int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sALPHANUMERIC, + CBC_QRCoderMode::sBYTE, versionNum, e); + if (e != BCExceptionNO) + return; + if (element2.first == CBC_QRCoderMode::sBYTE && tmp >= 0 && + element1.second.GetLength() < static_cast(tmp)) { + element2.second = element1.second + element2.second; + result->erase(result->begin() + i); + i--; + mergeNum++; + } + } else if (element1.first == CBC_QRCoderMode::sBYTE) { + if (element2.first == CBC_QRCoderMode::sBYTE) { + element1.second += element2.second; + result->erase(result->begin() + i + 1); + i--; + mergeNum++; + } + } else if (element1.first == CBC_QRCoderMode::sNUMERIC) { + int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, + CBC_QRCoderMode::sBYTE, versionNum, e); + if (e != BCExceptionNO) + return; + if (element2.first == CBC_QRCoderMode::sBYTE && tmp >= 0 && + element1.second.GetLength() < static_cast(tmp)) { + element2.second = element1.second + element2.second; + result->erase(result->begin() + i); + i--; + mergeNum++; + } + tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, + CBC_QRCoderMode::sALPHANUMERIC, versionNum, e); + if (e != BCExceptionNO) + return; + if (element2.first == CBC_QRCoderMode::sALPHANUMERIC && tmp >= 0 && + element1.second.GetLength() < static_cast(tmp)) { + element2.second = element1.second + element2.second; + result->erase(result->begin() + i); + i--; + mergeNum++; + } + } + } + if (mergeNum != 0) + MergeString(result, versionNum, e); +} + +void SplitString(const ByteString& content, + std::vector* result) { + size_t index = 0; + while (index < content.GetLength()) { + uint8_t c = static_cast(content[index]); + if (!((c >= 0xA1 && c <= 0xAA) || (c >= 0xB0 && c <= 0xFA))) + break; + index += 2; + } + if (index) + result->push_back({CBC_QRCoderMode::sGBK, content.Left(index)}); + if (index >= content.GetLength()) + return; + + size_t flag = index; + while (GetAlphaNumericCode(content[index]) == -1 && + index < content.GetLength()) { + uint8_t c = static_cast(content[index]); + if (((c >= 0xA1 && c <= 0xAA) || (c >= 0xB0 && c <= 0xFA))) + break; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + bool high = !!IsDBCSLeadByte(content[index]); +#else + bool high = content[index] > 127; +#endif + ++index; + if (high) + ++index; + } + if (index != flag) { + result->push_back( + {CBC_QRCoderMode::sBYTE, content.Mid(flag, index - flag)}); + } + flag = index; + if (index >= content.GetLength()) + return; + + while (index < content.GetLength() && isdigit(content[index])) + ++index; + + if (index != flag) { + result->push_back( + {CBC_QRCoderMode::sNUMERIC, content.Mid(flag, index - flag)}); + } + flag = index; + if (index >= content.GetLength()) + return; + + while (index < content.GetLength() && + GetAlphaNumericCode(content[index]) != -1) { + ++index; + } + if (index != flag) { + result->push_back( + {CBC_QRCoderMode::sALPHANUMERIC, content.Mid(flag, index - flag)}); + } + flag = index; + if (index < content.GetLength()) + SplitString(content.Right(content.GetLength() - index), result); +} + +CBC_QRCoderMode* ChooseMode(const ByteString& content, ByteString encoding) { + if (encoding.Compare("SHIFT_JIS") == 0) + return CBC_QRCoderMode::sKANJI; + + bool hasNumeric = false; + bool hasAlphaNumeric = false; + for (size_t i = 0; i < content.GetLength(); i++) { + if (isdigit(content[i])) { + hasNumeric = true; + } else if (GetAlphaNumericCode(content[i]) != -1) { + hasAlphaNumeric = true; + } else { + return CBC_QRCoderMode::sBYTE; + } + } + if (hasAlphaNumeric) + return CBC_QRCoderMode::sALPHANUMERIC; + if (hasNumeric) + return CBC_QRCoderMode::sNUMERIC; + return CBC_QRCoderMode::sBYTE; +} + +bool InterleaveWithECBytes(CBC_QRCoderBitVector* bits, + int32_t numTotalBytes, + int32_t numDataBytes, + int32_t numRSBlocks, + CBC_QRCoderBitVector* result) { + ASSERT(numTotalBytes >= 0); + ASSERT(numDataBytes >= 0); + if (bits->sizeInBytes() != static_cast(numDataBytes)) + return false; + + int32_t dataBytesOffset = 0; + int32_t maxNumDataBytes = 0; + int32_t maxNumEcBytes = 0; + std::vector blocks(numRSBlocks); + for (int32_t i = 0; i < numRSBlocks; i++) { + int32_t numDataBytesInBlock; + int32_t numEcBytesInBlosk; + GetNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, + numRSBlocks, i, numDataBytesInBlock, + numEcBytesInBlosk); + auto dataBytes = pdfium::MakeUnique(); + dataBytes->Set(bits->GetArray(), dataBytesOffset, numDataBytesInBlock); + std::unique_ptr ecBytes = + GenerateECBytes(dataBytes.get(), numEcBytesInBlosk); + if (!ecBytes) + return false; + + maxNumDataBytes = std::max(maxNumDataBytes, dataBytes->Size()); + maxNumEcBytes = std::max(maxNumEcBytes, ecBytes->Size()); + blocks[i].SetData(std::move(dataBytes), std::move(ecBytes)); + dataBytesOffset += numDataBytesInBlock; + } + if (numDataBytes != dataBytesOffset) + return false; + + for (int32_t x = 0; x < maxNumDataBytes; x++) { + for (size_t j = 0; j < blocks.size(); j++) { + const CBC_CommonByteArray* dataBytes = blocks[j].GetDataBytes(); + if (x < dataBytes->Size()) + result->AppendBits(dataBytes->At(x), 8); + } + } + for (int32_t y = 0; y < maxNumEcBytes; y++) { + for (size_t l = 0; l < blocks.size(); l++) { + const CBC_CommonByteArray* ecBytes = blocks[l].GetErrorCorrectionBytes(); + if (y < ecBytes->Size()) + result->AppendBits(ecBytes->At(y), 8); + } + } + return static_cast(numTotalBytes) == result->sizeInBytes(); +} + +} // namespace + +CBC_QRCoderEncoder::CBC_QRCoderEncoder() {} + +CBC_QRCoderEncoder::~CBC_QRCoderEncoder() {} + +// static +bool CBC_QRCoderEncoder::Encode(const WideString& content, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode) { + ByteString encoding = "utf8"; + ByteString utf8Data; + CBC_UtilCodingConvert::UnicodeToUTF8(content, utf8Data); + CBC_QRCoderMode* mode = ChooseMode(utf8Data, encoding); + CBC_QRCoderBitVector dataBits; + int32_t e = BCExceptionNO; + AppendBytes(utf8Data, mode, &dataBits, encoding, e); + if (e != BCExceptionNO) + return false; + int32_t numInputBytes = dataBits.sizeInBytes(); + if (!InitQRCode(numInputBytes, ecLevel, mode, qrCode)) + return false; + CBC_QRCoderBitVector headerAndDataBits; + AppendModeInfo(mode, &headerAndDataBits); + int32_t numLetters = mode == CBC_QRCoderMode::sBYTE ? dataBits.sizeInBytes() + : content.GetLength(); + if (!AppendLengthInfo(numLetters, qrCode->GetVersion(), mode, + &headerAndDataBits)) { + return false; + } + headerAndDataBits.AppendBitVector(&dataBits); + if (!TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits)) + return false; + CBC_QRCoderBitVector finalBits; + if (!InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), + qrCode->GetNumDataBytes(), + qrCode->GetNumRSBlocks(), &finalBits)) { + return false; + } + + auto matrix = pdfium::MakeUnique( + qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth()); + matrix->Init(); + int32_t maskPattern = ChooseMaskPattern( + &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); + if (e != BCExceptionNO) + return false; + + qrCode->SetMaskPattern(maskPattern); + CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), + qrCode->GetVersion(), + qrCode->GetMaskPattern(), matrix.get(), e); + if (e != BCExceptionNO) + return false; + + qrCode->SetMatrix(std::move(matrix)); + return qrCode->IsValid(); +} diff --git a/fxbarcode/qrcode/BC_QRCoderEncoder.h b/fxbarcode/qrcode/BC_QRCoderEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..3acbd1bde840afade88e40d65efa9240379c3b71 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderEncoder.h @@ -0,0 +1,28 @@ +// 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 FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ +#define FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ + +#include +#include + +#include "core/fxcrt/fx_string.h" + +class CBC_QRCoder; +class CBC_QRCoderErrorCorrectionLevel; + +class CBC_QRCoderEncoder { + public: + CBC_QRCoderEncoder(); + ~CBC_QRCoderEncoder(); + + static bool Encode(const WideString& content, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, + CBC_QRCoder* qrCode); +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp similarity index 96% rename from xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp rename to fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp index a5450cf085d6b494b9d22fd4cd9e57aab9bb15e2..6fb323370545c08a71093d2ada72ce38f3803a98 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp +++ b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.cpp @@ -20,7 +20,7 @@ * limitations under the License. */ -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::L = nullptr; CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::M = nullptr; @@ -30,7 +30,7 @@ CBC_QRCoderErrorCorrectionLevel* CBC_QRCoderErrorCorrectionLevel::H = nullptr; CBC_QRCoderErrorCorrectionLevel::CBC_QRCoderErrorCorrectionLevel( int32_t ordinal, int32_t bits, - const FX_CHAR* name) + const char* name) : m_ordinal(ordinal), m_bits(bits), m_name(name) {} CBC_QRCoderErrorCorrectionLevel::~CBC_QRCoderErrorCorrectionLevel() {} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h similarity index 75% rename from xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h rename to fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h index e433ee11272b92b20d693baae65b0669fcac463e..ff7563ccfe10c8f502d632a629af90c09ba327b2 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h +++ b/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h @@ -4,8 +4,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ +#ifndef FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ +#define FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ #include "core/fxcrt/fx_string.h" @@ -25,17 +25,17 @@ class CBC_QRCoderErrorCorrectionLevel { int32_t Ordinal() const { return m_ordinal; } int32_t GetBits() const { return m_bits; } - CFX_ByteString GetName() const { return m_name; } + ByteString GetName() const { return m_name; } private: CBC_QRCoderErrorCorrectionLevel(int32_t ordinal, int32_t bits, - const FX_CHAR* name); + const char* name); CBC_QRCoderErrorCorrectionLevel(); int32_t m_ordinal; int32_t m_bits; - CFX_ByteString m_name; + ByteString m_name; }; -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ +#endif // FXBARCODE_QRCODE_BC_QRCODERERRORCORRECTIONLEVEL_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp b/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp similarity index 96% rename from xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp rename to fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp index 7953701bb2c20fc78091916a5148c92ab355c8e9..cdf1e4caf90f267d1c1e872d95d95c14cf32bd94 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp +++ b/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp @@ -20,11 +20,11 @@ * limitations under the License. */ -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h" -#include "xfa/fxbarcode/utils.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h" +#include "fxbarcode/utils.h" CBC_QRCoderMaskUtil::CBC_QRCoderMaskUtil() {} CBC_QRCoderMaskUtil::~CBC_QRCoderMaskUtil() {} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h b/fxbarcode/qrcode/BC_QRCoderMaskUtil.h similarity index 86% rename from xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h rename to fxbarcode/qrcode/BC_QRCoderMaskUtil.h index 9fbe073e7e986f0dd22f85287b3486222d7211df..63fccbb8e45df5ca9e18ec28ff43eedfc9f7ff7e 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h +++ b/fxbarcode/qrcode/BC_QRCoderMaskUtil.h @@ -4,8 +4,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ +#ifndef FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ +#define FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ class CBC_CommonByteMatrix; class CBC_QRCoderMaskUtil { public: @@ -24,4 +24,4 @@ class CBC_QRCoderMaskUtil { bool isHorizontal); }; -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ +#endif // FXBARCODE_QRCODE_BC_QRCODERMASKUTIL_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp similarity index 92% rename from xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp rename to fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp index d48d81c091b39f4e71c07e5c8e4831948a527734..d5b7bcd69d0f64264ae8bb2252bd5bda2a3f5f83 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp +++ b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.cpp @@ -20,13 +20,13 @@ * limitations under the License. */ -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h" -#include "xfa/fxbarcode/utils.h" +#include "fxbarcode/common/BC_CommonByteMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoder.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h" +#include "fxbarcode/qrcode/BC_QRCoderMatrixUtil.h" +#include "fxbarcode/utils.h" const int32_t CBC_QRCoderMatrixUtil::POSITION_DETECTION_PATTERN[7][7] = { {1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, @@ -85,7 +85,7 @@ void CBC_QRCoderMatrixUtil::ClearMatrix(CBC_CommonByteMatrix* matrix, } void CBC_QRCoderMatrixUtil::BuildMatrix( CBC_QRCoderBitVector* dataBits, - CBC_QRCoderErrorCorrectionLevel* ecLevel, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t version, int32_t maskPattern, CBC_CommonByteMatrix* matrix, @@ -130,8 +130,9 @@ void CBC_QRCoderMatrixUtil::EmbedBasicPatterns(int32_t version, if (e != BCExceptionNO) return; } + void CBC_QRCoderMatrixUtil::EmbedTypeInfo( - CBC_QRCoderErrorCorrectionLevel* ecLevel, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t maskPattern, CBC_CommonByteMatrix* matrix, int32_t& e) { @@ -140,11 +141,11 @@ void CBC_QRCoderMatrixUtil::EmbedTypeInfo( return; } CBC_QRCoderBitVector typeInfoBits; - typeInfoBits.Init(); MakeTypeInfoBits(ecLevel, maskPattern, &typeInfoBits, e); if (e != BCExceptionNO) return; - for (int32_t i = 0; i < typeInfoBits.Size(); i++) { + + for (size_t i = 0; i < typeInfoBits.Size(); i++) { int32_t bit = typeInfoBits.At(typeInfoBits.Size() - 1 - i, e); if (e != BCExceptionNO) return; @@ -162,6 +163,7 @@ void CBC_QRCoderMatrixUtil::EmbedTypeInfo( } } } + void CBC_QRCoderMatrixUtil::MaybeEmbedVersionInfo(int32_t version, CBC_CommonByteMatrix* matrix, int32_t& e) { @@ -173,7 +175,6 @@ void CBC_QRCoderMatrixUtil::MaybeEmbedVersionInfo(int32_t version, return; } CBC_QRCoderBitVector versionInfoBits; - versionInfoBits.Init(); MakeVersionInfoBits(version, &versionInfoBits, e); if (e != BCExceptionNO) return; @@ -197,7 +198,7 @@ void CBC_QRCoderMatrixUtil::EmbedDataBits(CBC_QRCoderBitVector* dataBits, e = BCExceptionNullPointer; return; } - int32_t bitIndex = 0; + size_t bitIndex = 0; int32_t direction = -1; int32_t x = matrix->GetWidth() - 1; int32_t y = matrix->GetHeight() - 1; @@ -253,7 +254,7 @@ int32_t CBC_QRCoderMatrixUtil::CalculateBCHCode(int32_t value, int32_t poly) { return value; } void CBC_QRCoderMatrixUtil::MakeTypeInfoBits( - CBC_QRCoderErrorCorrectionLevel* ecLevel, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t maskPattern, CBC_QRCoderBitVector* bits, int32_t& e) { @@ -266,23 +267,16 @@ void CBC_QRCoderMatrixUtil::MakeTypeInfoBits( return; } int32_t typeInfo = (ecLevel->GetBits() << 3) | maskPattern; - if (e != BCExceptionNO) - return; - bits->AppendBits(typeInfo, 5, e); + bits->AppendBits(typeInfo, 5); int32_t bchCode = CalculateBCHCode(typeInfo, TYPE_INFO_POLY); - if (e != BCExceptionNO) - return; - bits->AppendBits(bchCode, 10, e); + bits->AppendBits(bchCode, 10); CBC_QRCoderBitVector maskBits; - maskBits.Init(); - maskBits.AppendBits(TYPE_INFO_MASK_PATTERN, 15, e); - if (e != BCExceptionNO) + maskBits.AppendBits(TYPE_INFO_MASK_PATTERN, 15); + if (!bits->XOR(&maskBits)) { + e = BCExceptionGeneric; return; - bits->XOR(&maskBits, e); - if (e != BCExceptionNO) - return; - if (bits->Size() != 15) - e = BCExceptionBitSizeNot15; + } + ASSERT(bits->Size() == 15); } void CBC_QRCoderMatrixUtil::MakeVersionInfoBits(int32_t version, @@ -292,17 +286,11 @@ void CBC_QRCoderMatrixUtil::MakeVersionInfoBits(int32_t version, e = BCExceptionNullPointer; return; } - bits->AppendBits(version, 6, e); - if (e != BCExceptionNO) - return; + bits->AppendBits(version, 6); int32_t bchCode = CalculateBCHCode(version, VERSION_INFO_POLY); - bits->AppendBits(bchCode, 12, e); - if (e != BCExceptionNO) - return; - - if (bits->Size() != 18) - e = BCExceptionBitSizeNot18; + bits->AppendBits(bchCode, 12); + ASSERT(bits->Size() == 18); } bool CBC_QRCoderMatrixUtil::IsEmpty(int32_t value) { diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h similarity index 91% rename from xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h rename to fxbarcode/qrcode/BC_QRCoderMatrixUtil.h index 3ce4b7510bea0cc19d0d1754963324d20ef76bf5..23fe0df8dabcc23ee7f8260d1f23c420b6b86b56 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h +++ b/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h @@ -4,30 +4,20 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ +#ifndef FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ +#define FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ class CBC_CommonByteMatrix; class CBC_QRCoderErrorCorrectionLevel; class CBC_QRCoderBitVector; -class CBC_QRCoderMatrixUtil { - private: - static const int32_t POSITION_DETECTION_PATTERN[7][7]; - static const int32_t VERTICAL_SEPARATION_PATTERN[7][1]; - static const int32_t HORIZONTAL_SEPARATION_PATTERN[1][8]; - static const int32_t POSITION_ADJUSTMENT_PATTERN[5][5]; - static const int32_t POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[40][7]; - static const int32_t TYPE_INFO_COORDINATES[15][2]; - static const int32_t VERSION_INFO_POLY; - static const int32_t TYPE_INFO_POLY; - static const int32_t TYPE_INFO_MASK_PATTERN; +class CBC_QRCoderMatrixUtil { public: CBC_QRCoderMatrixUtil(); virtual ~CBC_QRCoderMatrixUtil(); static void ClearMatrix(CBC_CommonByteMatrix* matrix, int32_t& e); static void BuildMatrix(CBC_QRCoderBitVector* dataBits, - CBC_QRCoderErrorCorrectionLevel* ecLevel, + const CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t version, int32_t maskPattern, CBC_CommonByteMatrix* matrix, @@ -35,7 +25,7 @@ class CBC_QRCoderMatrixUtil { static void EmbedBasicPatterns(int32_t version, CBC_CommonByteMatrix* matrix, int32_t& e); - static void EmbedTypeInfo(CBC_QRCoderErrorCorrectionLevel* ecLevel, + static void EmbedTypeInfo(const CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t maskPattern, CBC_CommonByteMatrix* matrix, int32_t& e); @@ -48,7 +38,7 @@ class CBC_QRCoderMatrixUtil { int32_t& e); static int32_t FindMSBSet(int32_t value); static int32_t CalculateBCHCode(int32_t code, int32_t poly); - static void MakeTypeInfoBits(CBC_QRCoderErrorCorrectionLevel* ecLevel, + static void MakeTypeInfoBits(const CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t maskPattern, CBC_QRCoderBitVector* bits, int32_t& e); @@ -82,6 +72,17 @@ class CBC_QRCoderMatrixUtil { static void MaybeEmbedPositionAdjustmentPatterns(int32_t version, CBC_CommonByteMatrix* matrix, int32_t& e); + + private: + static const int32_t POSITION_DETECTION_PATTERN[7][7]; + static const int32_t VERTICAL_SEPARATION_PATTERN[7][1]; + static const int32_t HORIZONTAL_SEPARATION_PATTERN[1][8]; + static const int32_t POSITION_ADJUSTMENT_PATTERN[5][5]; + static const int32_t POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[40][7]; + static const int32_t TYPE_INFO_COORDINATES[15][2]; + static const int32_t VERSION_INFO_POLY; + static const int32_t TYPE_INFO_POLY; + static const int32_t TYPE_INFO_MASK_PATTERN; }; -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ +#endif // FXBARCODE_QRCODE_BC_QRCODERMATRIXUTIL_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderMode.cpp b/fxbarcode/qrcode/BC_QRCoderMode.cpp similarity index 92% rename from xfa/fxbarcode/qrcode/BC_QRCoderMode.cpp rename to fxbarcode/qrcode/BC_QRCoderMode.cpp index a1283dda9366ccb5a8b6024fbb3983c1b9f8a655..0f8c227843fc0c0a4d13b0d5ae026c4a26fa9a1a 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderMode.cpp +++ b/fxbarcode/qrcode/BC_QRCoderMode.cpp @@ -20,12 +20,11 @@ * limitations under the License. */ -#include "xfa/fxbarcode/qrcode/BC_QRCoderMode.h" +#include "fxbarcode/qrcode/BC_QRCoderMode.h" #include -#include "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h" -#include "xfa/fxbarcode/utils.h" +#include "fxbarcode/utils.h" CBC_QRCoderMode* CBC_QRCoderMode::sBYTE = nullptr; CBC_QRCoderMode* CBC_QRCoderMode::sNUMERIC = nullptr; @@ -40,7 +39,7 @@ CBC_QRCoderMode* CBC_QRCoderMode::sSTRUCTURED_APPEND = nullptr; CBC_QRCoderMode::CBC_QRCoderMode(std::vector charCountBits, int32_t bits, - CFX_ByteString name) + ByteString name) : m_characterCountBitsForVersions(std::move(charCountBits)), m_bits(bits), m_name(name) {} @@ -108,17 +107,16 @@ int32_t CBC_QRCoderMode::GetBits() const { return m_bits; } -CFX_ByteString CBC_QRCoderMode::GetName() const { +ByteString CBC_QRCoderMode::GetName() const { return m_name; } -int32_t CBC_QRCoderMode::GetCharacterCountBits(CBC_QRCoderVersion* version, +int32_t CBC_QRCoderMode::GetCharacterCountBits(int32_t number, int32_t& e) const { if (m_characterCountBitsForVersions.empty()) { e = BCExceptionCharacterNotThisMode; return 0; } - int32_t number = version->GetVersionNumber(); int32_t offset; if (number <= 9) { offset = 0; diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderMode.h b/fxbarcode/qrcode/BC_QRCoderMode.h similarity index 76% rename from xfa/fxbarcode/qrcode/BC_QRCoderMode.h rename to fxbarcode/qrcode/BC_QRCoderMode.h index f876d81f039eb6a2320dc6ee58c1f0efcea04827..9f2844da977b327b1eb43c9f6904336a41ce17d0 100644 --- a/xfa/fxbarcode/qrcode/BC_QRCoderMode.h +++ b/fxbarcode/qrcode/BC_QRCoderMode.h @@ -4,8 +4,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERMODE_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERMODE_H_ +#ifndef FXBARCODE_QRCODE_BC_QRCODERMODE_H_ +#define FXBARCODE_QRCODE_BC_QRCODERMODE_H_ #include @@ -13,8 +13,6 @@ #include "core/fxcrt/fx_string.h" -class CBC_QRCoderVersion; - class CBC_QRCoderMode { public: virtual ~CBC_QRCoderMode(); @@ -24,9 +22,9 @@ class CBC_QRCoderMode { static CBC_QRCoderMode* ForBits(int32_t bits, int32_t& e); static void Destroy(); - int32_t GetCharacterCountBits(CBC_QRCoderVersion* version, int32_t& e) const; + int32_t GetCharacterCountBits(int32_t number, int32_t& e) const; int32_t GetBits() const; - CFX_ByteString GetName() const; + ByteString GetName() const; static CBC_QRCoderMode* sBYTE; static CBC_QRCoderMode* sNUMERIC; @@ -43,11 +41,11 @@ class CBC_QRCoderMode { CBC_QRCoderMode(); CBC_QRCoderMode(std::vector charCountBits, int32_t bits, - CFX_ByteString name); + ByteString name); std::vector m_characterCountBitsForVersions; const int32_t m_bits; - const CFX_ByteString m_name; + const ByteString m_name; }; -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERMODE_H_ +#endif // FXBARCODE_QRCODE_BC_QRCODERMODE_H_ diff --git a/fxbarcode/qrcode/BC_QRCoderVersion.cpp b/fxbarcode/qrcode/BC_QRCoderVersion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7da603359df72fa63e3ef902ad1cd1c2ffaa17dd --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderVersion.cpp @@ -0,0 +1,99 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com +// Original code is licensed as follows: +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fxbarcode/qrcode/BC_QRCoderVersion.h" + +#include +#include + +#include "fxbarcode/common/BC_CommonBitMatrix.h" +#include "fxbarcode/qrcode/BC_QRCoderBitVector.h" +#include "fxbarcode/qrcode/BC_QRCoderECBlocksData.h" +#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" +#include "fxbarcode/utils.h" +#include "third_party/base/ptr_util.h" + +namespace { + +std::vector>* g_VERSION = nullptr; + +} // namespace + +CBC_QRCoderVersion::CBC_QRCoderVersion(int32_t versionNumber, + const CBC_QRCoderECBlockData data[4]) + : m_versionNumber(versionNumber) { + m_ecBlocksArray[0] = pdfium::MakeUnique(data[0]); + m_ecBlocksArray[1] = pdfium::MakeUnique(data[1]); + m_ecBlocksArray[2] = pdfium::MakeUnique(data[2]); + m_ecBlocksArray[3] = pdfium::MakeUnique(data[3]); + m_totalCodeWords = m_ecBlocksArray[0]->GetTotalDataCodeWords(); +} + +CBC_QRCoderVersion::~CBC_QRCoderVersion() { +} + +// static +void CBC_QRCoderVersion::Initialize() { + g_VERSION = new std::vector>(); +} + +// static +void CBC_QRCoderVersion::Finalize() { + delete g_VERSION; + g_VERSION = nullptr; +} + +// static +const CBC_QRCoderVersion* CBC_QRCoderVersion::GetVersionForNumber( + int32_t versionNumber) { + if (g_VERSION->empty()) { + for (int i = 0; i < kMaxVersion; ++i) { + g_VERSION->push_back( + pdfium::MakeUnique(i + 1, g_ECBData[i])); + } + } + if (versionNumber < 1 || versionNumber > kMaxVersion) + return nullptr; + return (*g_VERSION)[versionNumber - 1].get(); +} + +// static +void CBC_QRCoderVersion::Destroy() { + g_VERSION->clear(); +} + +int32_t CBC_QRCoderVersion::GetVersionNumber() const { + return m_versionNumber; +} + +int32_t CBC_QRCoderVersion::GetTotalCodeWords() const { + return m_totalCodeWords; +} + +int32_t CBC_QRCoderVersion::GetDimensionForVersion() const { + return 17 + 4 * m_versionNumber; +} + +const CBC_QRCoderECBlocks* CBC_QRCoderVersion::GetECBlocksForLevel( + const CBC_QRCoderErrorCorrectionLevel& ecLevel) const { + return m_ecBlocksArray[ecLevel.Ordinal()].get(); +} diff --git a/fxbarcode/qrcode/BC_QRCoderVersion.h b/fxbarcode/qrcode/BC_QRCoderVersion.h new file mode 100644 index 0000000000000000000000000000000000000000..bfa213ccbb5c37da29fe022e6c99418384581158 --- /dev/null +++ b/fxbarcode/qrcode/BC_QRCoderVersion.h @@ -0,0 +1,43 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ +#define FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ + +#include +#include + +#include "fxbarcode/qrcode/BC_QRCoderECBlocks.h" + +class CBC_QRCoderErrorCorrectionLevel; + +class CBC_QRCoderVersion { + public: + static constexpr int32_t kMaxVersion = 40; + + CBC_QRCoderVersion(int32_t versionNumber, + const CBC_QRCoderECBlockData data[4]); + ~CBC_QRCoderVersion(); + + static void Initialize(); + static void Finalize(); + + static const CBC_QRCoderVersion* GetVersionForNumber(int32_t versionNumber); + static void Destroy(); + + int32_t GetVersionNumber() const; + int32_t GetTotalCodeWords() const; + int32_t GetDimensionForVersion() const; + const CBC_QRCoderECBlocks* GetECBlocksForLevel( + const CBC_QRCoderErrorCorrectionLevel& ecLevel) const; + + private: + const int32_t m_versionNumber; + int32_t m_totalCodeWords; + std::unique_ptr m_ecBlocksArray[4]; +}; + +#endif // FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ diff --git a/fxbarcode/utils.h b/fxbarcode/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..2303af44b0c4f7b8559a32bb89cf6740d1789a27 --- /dev/null +++ b/fxbarcode/utils.h @@ -0,0 +1,70 @@ +// 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 FXBARCODE_UTILS_H_ +#define FXBARCODE_UTILS_H_ + +#include + +#include + +#include "core/fxcrt/fx_string.h" + +bool BC_FX_ByteString_Replace(ByteString& dst, + uint32_t first, + uint32_t last, + int32_t count, + char c); +void BC_FX_ByteString_Append(ByteString& dst, int32_t count, char c); +void BC_FX_ByteString_Append(ByteString& dst, const std::vector& ba); + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +#include +#elif _FX_OS_ == _FX_OS_MACOSX_ || _FX_OS_ == _FX_OS_LINUX_ +#include +#endif + +enum BCFORMAT { + BCFORMAT_UNSPECIFY = -1, + BCFORMAT_CODABAR, + BCFORMAT_CODE_39, + BCFORMAT_CODE_128, + BCFORMAT_CODE_128B, + BCFORMAT_CODE_128C, + BCFORMAT_EAN_8, + BCFORMAT_UPC_A, + BCFORMAT_EAN_13, + BCFORMAT_PDF_417, + BCFORMAT_DATAMATRIX, + BCFORMAT_QR_CODE +}; + +#define BCExceptionNO 0 +#define BCExceptionIllegalArgument 16 +#define BCExceptionDegreeIsNegative 31 +#define BCExceptionAIsZero 37 +#define BCExceptionValueMustBeEither0or1 50 +#define BCExceptionBadIndexException 52 +#define BCExceptionNoSuchVersion 58 +#define BCExceptionUnsupportedMode 64 +#define BCExceptionInvalidateCharacter 65 +#define BCExceptionInvalidateMaskPattern 68 +#define BCExceptionNullPointer 69 +#define BCExceptionBadMask 70 +#define BCExceptionInvalidateImageData 73 +#define BCExceptionHeight_8BeZero 74 +#define BCExceptionCharacterNotThisMode 75 +#define BCExceptionInvalidateData 77 +#define BCExceptionCharactersOutsideISO88591Encoding 87 +#define BCExceptionIllegalDataCodewords 88 +#define BCExceptionIllegalStateUnexpectedCase 90 +#define BCExceptionIllegalStateMessageLengthInvalid 92 +#define BCExceptionIllegalArgumentNotGigits 93 +#define BCExceptionIllegalStateIllegalMode 94 +#define BCExceptionNonEncodableCharacterDetected 96 +#define BCExceptionGeneric 107 + +#endif // FXBARCODE_UTILS_H_ diff --git a/fxjs/CJX_Define.h b/fxjs/CJX_Define.h new file mode 100644 index 0000000000000000000000000000000000000000..4a26fd4d23db304727cfd66ce60c20e305a48a50 --- /dev/null +++ b/fxjs/CJX_Define.h @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJX_DEFINE_H_ +#define FXJS_CJX_DEFINE_H_ + +#include + +#include "fxjs/cjs_return.h" +#include "fxjs/cjs_v8.h" + +template >& params)> +CJS_Return JSMethod(C* node, + CJS_V8* runtime, + const std::vector>& params) { + return (node->*M)(runtime, params); +} + +#define JS_METHOD(method_name, class_name) \ + static CJS_Return method_name##_static( \ + CJX_Object* node, CJS_V8* runtime, \ + const std::vector>& params) { \ + return JSMethod( \ + static_cast(node), runtime, params); \ + } \ + CJS_Return method_name(CJS_V8* runtime, \ + const std::vector>& params) + +#define JS_PROP(prop_name) \ + void prop_name(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute) + +#endif // FXJS_CJX_DEFINE_H_ diff --git a/fxjs/DEPS b/fxjs/DEPS index 633eeed5613b8b7e8a54debeddc2004526b83e19..4cc93f9474061484d20b7569b99453a984d19f49 100644 --- a/fxjs/DEPS +++ b/fxjs/DEPS @@ -1,4 +1,11 @@ include_rules = [ + '+core/fdrm', + '+core/fpdfapi', + '+core/fpdfdoc', '+core/fxcrt', + '+core/fxge', + '+public', + '+fpdfsdk', '+v8/include', + '+xfa/fxfa' ] diff --git a/fxjs/JS_Define.cpp b/fxjs/JS_Define.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90f755742241134821fb6ef458ac3045bbb708da --- /dev/null +++ b/fxjs/JS_Define.cpp @@ -0,0 +1,308 @@ +// 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 "fxjs/JS_Define.h" + +#include + +#include +#include +#include +#include + +#include "fxjs/cjs_document.h" +#include "fxjs/cjs_object.h" + +namespace { + +double GetLocalTZA() { + if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) + return 0; + time_t t = 0; + time(&t); + localtime(&t); +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + // In gcc 'timezone' is a global variable declared in time.h. In VC++, that + // variable was removed in VC++ 2015, with _get_timezone replacing it. + long timezone = 0; + _get_timezone(&timezone); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + return (double)(-(timezone * 1000)); +} + +int GetDaylightSavingTA(double d) { + if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) + return 0; + time_t t = (time_t)(d / 1000); + struct tm* tmp = localtime(&t); + if (!tmp) + return 0; + if (tmp->tm_isdst > 0) + // One hour. + return (int)60 * 60 * 1000; + return 0; +} + +double Mod(double x, double y) { + double r = fmod(x, y); + if (r < 0) + r += y; + return r; +} + +bool IsLeapYear(int year) { + return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0)); +} + +int DayFromYear(int y) { + return (int)(365 * (y - 1970.0) + floor((y - 1969.0) / 4) - + floor((y - 1901.0) / 100) + floor((y - 1601.0) / 400)); +} + +double TimeFromYear(int y) { + return 86400000.0 * DayFromYear(y); +} + +static const uint16_t daysMonth[12] = {0, 31, 59, 90, 120, 151, + 181, 212, 243, 273, 304, 334}; +static const uint16_t leapDaysMonth[12] = {0, 31, 60, 91, 121, 152, + 182, 213, 244, 274, 305, 335}; + +double TimeFromYearMonth(int y, int m) { + const uint16_t* pMonth = IsLeapYear(y) ? leapDaysMonth : daysMonth; + return TimeFromYear(y) + ((double)pMonth[m]) * 86400000; +} + +int Day(double t) { + return static_cast(floor(t / 86400000.0)); +} + +int YearFromTime(double t) { + // estimate the time. + int y = 1970 + static_cast(t / (365.2425 * 86400000.0)); + if (TimeFromYear(y) <= t) { + while (TimeFromYear(y + 1) <= t) + y++; + } else { + while (TimeFromYear(y) > t) + y--; + } + return y; +} + +int DayWithinYear(double t) { + int year = YearFromTime(t); + int day = Day(t); + return day - DayFromYear(year); +} + +int MonthFromTime(double t) { + int day = DayWithinYear(t); + int year = YearFromTime(t); + if (0 <= day && day < 31) + return 0; + if (31 <= day && day < 59 + IsLeapYear(year)) + return 1; + if ((59 + IsLeapYear(year)) <= day && day < (90 + IsLeapYear(year))) + return 2; + if ((90 + IsLeapYear(year)) <= day && day < (120 + IsLeapYear(year))) + return 3; + if ((120 + IsLeapYear(year)) <= day && day < (151 + IsLeapYear(year))) + return 4; + if ((151 + IsLeapYear(year)) <= day && day < (181 + IsLeapYear(year))) + return 5; + if ((181 + IsLeapYear(year)) <= day && day < (212 + IsLeapYear(year))) + return 6; + if ((212 + IsLeapYear(year)) <= day && day < (243 + IsLeapYear(year))) + return 7; + if ((243 + IsLeapYear(year)) <= day && day < (273 + IsLeapYear(year))) + return 8; + if ((273 + IsLeapYear(year)) <= day && day < (304 + IsLeapYear(year))) + return 9; + if ((304 + IsLeapYear(year)) <= day && day < (334 + IsLeapYear(year))) + return 10; + if ((334 + IsLeapYear(year)) <= day && day < (365 + IsLeapYear(year))) + return 11; + + return -1; +} + +int DateFromTime(double t) { + int day = DayWithinYear(t); + int year = YearFromTime(t); + int leap = IsLeapYear(year); + int month = MonthFromTime(t); + switch (month) { + case 0: + return day + 1; + case 1: + return day - 30; + case 2: + return day - 58 - leap; + case 3: + return day - 89 - leap; + case 4: + return day - 119 - leap; + case 5: + return day - 150 - leap; + case 6: + return day - 180 - leap; + case 7: + return day - 211 - leap; + case 8: + return day - 242 - leap; + case 9: + return day - 272 - leap; + case 10: + return day - 303 - leap; + case 11: + return day - 333 - leap; + default: + return 0; + } +} + +} // namespace + +double JS_GetDateTime() { + if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) + return 0; + time_t t = time(nullptr); + struct tm* pTm = localtime(&t); + + int year = pTm->tm_year + 1900; + double t1 = TimeFromYear(year); + + return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 + + pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0; +} + +int JS_GetYearFromTime(double dt) { + return YearFromTime(dt); +} + +int JS_GetMonthFromTime(double dt) { + return MonthFromTime(dt); +} + +int JS_GetDayFromTime(double dt) { + return DateFromTime(dt); +} + +int JS_GetHourFromTime(double dt) { + return (int)Mod(floor(dt / (60 * 60 * 1000)), 24); +} + +int JS_GetMinFromTime(double dt) { + return (int)Mod(floor(dt / (60 * 1000)), 60); +} + +int JS_GetSecFromTime(double dt) { + return (int)Mod(floor(dt / 1000), 60); +} + +double JS_LocalTime(double d) { + return d + GetLocalTZA() + GetDaylightSavingTA(d); +} + +double JS_DateParse(const WideString& str) { + v8::Isolate* pIsolate = v8::Isolate::GetCurrent(); + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope scope(pIsolate); + + v8::Local context = pIsolate->GetCurrentContext(); + + // Use the built-in object method. + v8::Local v = + context->Global() + ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date", + v8::NewStringType::kNormal) + .ToLocalChecked()) + .ToLocalChecked(); + if (v->IsObject()) { + v8::Local o = v->ToObject(context).ToLocalChecked(); + v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse", + v8::NewStringType::kNormal) + .ToLocalChecked()) + .ToLocalChecked(); + if (v->IsFunction()) { + v8::Local funC = v8::Local::Cast(v); + const int argc = 1; + v8::Local timeStr = + CJS_Runtime::CurrentRuntimeFromIsolate(pIsolate)->NewString( + str.AsStringView()); + v8::Local argv[argc] = {timeStr}; + v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked(); + if (v->IsNumber()) { + double date = v->ToNumber(context).ToLocalChecked()->Value(); + if (!std::isfinite(date)) + return date; + return JS_LocalTime(date); + } + } + } + return 0; +} + +double JS_MakeDay(int nYear, int nMonth, int nDate) { + double y = static_cast(nYear); + double m = static_cast(nMonth); + double dt = static_cast(nDate); + double ym = y + floor(m / 12); + double mn = Mod(m, 12); + double t = TimeFromYearMonth(static_cast(ym), static_cast(mn)); + if (YearFromTime(t) != ym || MonthFromTime(t) != mn || DateFromTime(t) != 1) + return std::nan(""); + + return Day(t) + dt - 1; +} + +double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) { + double h = static_cast(nHour); + double m = static_cast(nMin); + double s = static_cast(nSec); + double milli = static_cast(nMs); + return h * 3600000 + m * 60000 + s * 1000 + milli; +} + +double JS_MakeDate(double day, double time) { + if (!std::isfinite(day) || !std::isfinite(time)) + return std::nan(""); + + return day * 86400000 + time; +} + +std::vector> ExpandKeywordParams( + CJS_Runtime* pRuntime, + const std::vector>& originals, + size_t nKeywords, + ...) { + ASSERT(nKeywords); + + std::vector> result(nKeywords, v8::Local()); + size_t size = std::min(originals.size(), nKeywords); + for (size_t i = 0; i < size; ++i) + result[i] = originals[i]; + + if (originals.size() != 1 || !originals[0]->IsObject() || + originals[0]->IsArray()) { + return result; + } + result[0] = v8::Local(); // Make unknown. + + v8::Local pObj = pRuntime->ToObject(originals[0]); + va_list ap; + va_start(ap, nKeywords); + for (size_t i = 0; i < nKeywords; ++i) { + const wchar_t* property = va_arg(ap, const wchar_t*); + v8::Local v8Value = pRuntime->GetObjectProperty(pObj, property); + if (!v8Value->IsUndefined()) + result[i] = v8Value; + } + va_end(ap); + + return result; +} diff --git a/fxjs/JS_Define.h b/fxjs/JS_Define.h new file mode 100644 index 0000000000000000000000000000000000000000..6de56f40e05946bd4449a1dc95375759874da679 --- /dev/null +++ b/fxjs/JS_Define.h @@ -0,0 +1,166 @@ +// 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 FXJS_JS_DEFINE_H_ +#define FXJS_JS_DEFINE_H_ + +#include + +#include "fxjs/cjs_object.h" +#include "fxjs/cjs_return.h" +#include "fxjs/fxjs_v8.h" +#include "fxjs/js_resources.h" + +double JS_GetDateTime(); +int JS_GetYearFromTime(double dt); +int JS_GetMonthFromTime(double dt); +int JS_GetDayFromTime(double dt); +int JS_GetHourFromTime(double dt); +int JS_GetMinFromTime(double dt); +int JS_GetSecFromTime(double dt); +double JS_LocalTime(double d); +double JS_DateParse(const WideString& str); +double JS_MakeDay(int nYear, int nMonth, int nDay); +double JS_MakeTime(int nHour, int nMin, int nSec, int nMs); +double JS_MakeDate(double day, double time); + +// Some JS methods have the bizarre convention that they may also be called +// with a single argument which is an object containing the actual arguments +// as its properties. The varying arguments to this method are the property +// names as wchar_t string literals corresponding to each positional argument. +// The result will always contain |nKeywords| value, with unspecified ones +// being set to type VT_unknown. +std::vector> ExpandKeywordParams( + CJS_Runtime* pRuntime, + const std::vector>& originals, + size_t nKeywords, + ...); + +// All JS classes have a name, an object defintion ID, and the ability to +// register themselves with FXJS_V8. We never make a BASE class on its own +// because it can't really do anything. + +// Rich JS classes provide constants, methods, properties, and the ability +// to construct native object state. + +template +static void JSConstructor(CFXJS_Engine* pEngine, v8::Local obj) { + CJS_Object* pObj = new T(obj); + pObj->SetEmbedObject(new A(pObj)); + pEngine->SetObjectPrivate(obj, pObj); + pObj->InitInstance(static_cast(pEngine)); +} + +template +static void JSDestructor(CFXJS_Engine* pEngine, v8::Local obj) { + delete static_cast(pEngine->GetObjectPrivate(obj)); +} + +template +void JSPropGetter(const char* prop_name_string, + const char* class_name_string, + v8::Local property, + const v8::PropertyCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + C* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = (pObj->*M)(pRuntime); + if (result.HasError()) { + pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string, + result.Error())); + return; + } + + if (result.HasReturn()) + info.GetReturnValue().Set(result.Return()); +} + +template )> +void JSPropSetter(const char* prop_name_string, + const char* class_name_string, + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + C* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = (pObj->*M)(pRuntime, value); + if (result.HasError()) { + pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string, + result.Error())); + } +} + +template >&)> +void JSMethod(const char* method_name_string, + const char* class_name_string, + const v8::FunctionCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + std::vector> parameters; + for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) + parameters.push_back(info[i]); + + C* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = (pObj->*M)(pRuntime, parameters); + if (result.HasError()) { + pRuntime->Error(JSFormatErrorString(class_name_string, method_name_string, + result.Error())); + return; + } + + if (result.HasReturn()) + info.GetReturnValue().Set(result.Return()); +} + +#define JS_STATIC_PROP(err_name, prop_name, class_name) \ + static void get_##prop_name##_static( \ + v8::Local property, \ + const v8::PropertyCallbackInfo& info) { \ + JSPropGetter( \ + #err_name, #class_name, property, info); \ + } \ + static void set_##prop_name##_static( \ + v8::Local property, v8::Local value, \ + const v8::PropertyCallbackInfo& info) { \ + JSPropSetter( \ + #err_name, #class_name, property, value, info); \ + } + +#define JS_STATIC_METHOD(method_name, class_name) \ + static void method_name##_static( \ + const v8::FunctionCallbackInfo& info) { \ + JSMethod(#method_name, #class_name, \ + info); \ + } + +#endif // FXJS_JS_DEFINE_H_ diff --git a/fxjs/README b/fxjs/README new file mode 100644 index 0000000000000000000000000000000000000000..adc5827dbed436bd2904a043152cf23f72eff1c3 --- /dev/null +++ b/fxjs/README @@ -0,0 +1,33 @@ +There are two separate wrappers for V8 here. One is called FXJS, and +it is used by the non-XFA code. The other is called FXJSE, and it is +used only by the XFA code. Additionally FXJSE may request services +from FXJS to bridge the two. + +Both the FXJS and FXJSE binding code needs to be replaced by something +saner, perhaps Gin or perhaps some IDL. See + https://bugs.chromium.org/p/pdfium/issues/detail?id=716 +for progress on the issue. + +FXJS binds objects by sticking a pointer to a CFXJS_PerObjectData in +the V8 object's internal slot. FXJSE binds objects by sticking a +pointer to either an actual v8 function object or a CFXJSE_HostObject +in the V8 object's internal slot, depending upon whether the object +represents (in some notion) a "class" or an "instance". Also, V8 objects +bound in one library may unexpectedly arrive at the other given a script +that's trying to mess with us. + +To distinguish these cases, we use two internal slots for all bound +objects, regardless of the FXJS/FXJSE distinction. Slot 0 is the +tag and contains either: + kPerObjectDataTag for FXJS objects, or + g_FXJSETagString for FXJSE Host objects, or + One of 4 specific FXJSE_CLASS_DESCRIPTOR globals for FXJSE classes: + GlobalClassDescriptor + NormalClassDescriptor + VariablesClassDescriptor + formcalc_fm2js_descriptor + +Slot 1's contents are determined by these tags: + kPerObjectDataTag means to expect a CFXJS_PerObjectData. + g_FXJSETagString means to expect a CFXJSE_HostObject. + A FXJSE_CLASS_DESCRIPTOR pointer means to expect a v8 function. diff --git a/fxjs/cfxjse_arguments.cpp b/fxjs/cfxjse_arguments.cpp index 75904cbbead882e34de0b85c418d07f02d8472f6..663996ce884f6059f462cc6a261f491fe640ddaa 100644 --- a/fxjs/cfxjse_arguments.cpp +++ b/fxjs/cfxjse_arguments.cpp @@ -8,20 +8,23 @@ #include "fxjs/cfxjse_context.h" #include "fxjs/cfxjse_value.h" +#include "third_party/base/ptr_util.h" -v8::Isolate* CFXJSE_Arguments::GetRuntime() const { - return m_pRetValue->GetIsolate(); -} +CFXJSE_Arguments::CFXJSE_Arguments( + const v8::FunctionCallbackInfo* pInfo, + CFXJSE_Value* pRetValue) + : m_pInfo(pInfo), m_pRetValue(pRetValue) {} + +CFXJSE_Arguments::~CFXJSE_Arguments() {} int32_t CFXJSE_Arguments::GetLength() const { return m_pInfo->Length(); } std::unique_ptr CFXJSE_Arguments::GetValue(int32_t index) const { - std::unique_ptr lpArgValue( - new CFXJSE_Value(v8::Isolate::GetCurrent())); - lpArgValue->ForceSetValue((*m_pInfo)[index]); - return lpArgValue; + auto pArgValue = pdfium::MakeUnique(v8::Isolate::GetCurrent()); + pArgValue->ForceSetValue((*m_pInfo)[index]); + return pArgValue; } bool CFXJSE_Arguments::GetBoolean(int32_t index) const { @@ -32,14 +35,14 @@ int32_t CFXJSE_Arguments::GetInt32(int32_t index) const { return static_cast((*m_pInfo)[index]->NumberValue()); } -FX_FLOAT CFXJSE_Arguments::GetFloat(int32_t index) const { - return static_cast((*m_pInfo)[index]->NumberValue()); +float CFXJSE_Arguments::GetFloat(int32_t index) const { + return static_cast((*m_pInfo)[index]->NumberValue()); } -CFX_ByteString CFXJSE_Arguments::GetUTF8String(int32_t index) const { +ByteString CFXJSE_Arguments::GetUTF8String(int32_t index) const { v8::Local hString = (*m_pInfo)[index]->ToString(); - v8::String::Utf8Value szStringVal(hString); - return CFX_ByteString(*szStringVal); + v8::String::Utf8Value szStringVal(m_pInfo->GetIsolate(), hString); + return ByteString(*szStringVal); } CFXJSE_HostObject* CFXJSE_Arguments::GetObject(int32_t index, @@ -51,6 +54,6 @@ CFXJSE_HostObject* CFXJSE_Arguments::GetObject(int32_t index, return FXJSE_RetrieveObjectBinding(hValue.As(), pClass); } -CFXJSE_Value* CFXJSE_Arguments::GetReturnValue() { - return m_pRetValue; +CFXJSE_Value* CFXJSE_Arguments::GetReturnValue() const { + return m_pRetValue.Get(); } diff --git a/fxjs/cfxjse_arguments.h b/fxjs/cfxjse_arguments.h index 51e1981d03fc667de3d7947353ded916321a3ce4..92a36c842e79791ff314c0e0f423da41753b999f 100644 --- a/fxjs/cfxjse_arguments.h +++ b/fxjs/cfxjse_arguments.h @@ -9,30 +9,29 @@ #include +#include "core/fxcrt/unowned_ptr.h" +#include "fxjs/cfxjse_class.h" #include "fxjs/fxjse.h" -class CFXJSE_Class; - class CFXJSE_Arguments { public: CFXJSE_Arguments(const v8::FunctionCallbackInfo* pInfo, - CFXJSE_Value* pRetValue) - : m_pInfo(pInfo), m_pRetValue(pRetValue) {} + CFXJSE_Value* pRetValue); + ~CFXJSE_Arguments(); - v8::Isolate* GetRuntime() const; int32_t GetLength() const; std::unique_ptr GetValue(int32_t index) const; bool GetBoolean(int32_t index) const; int32_t GetInt32(int32_t index) const; - FX_FLOAT GetFloat(int32_t index) const; - CFX_ByteString GetUTF8String(int32_t index) const; + float GetFloat(int32_t index) const; + ByteString GetUTF8String(int32_t index) const; CFXJSE_HostObject* GetObject(int32_t index, CFXJSE_Class* pClass = nullptr) const; - CFXJSE_Value* GetReturnValue(); + CFXJSE_Value* GetReturnValue() const; private: const v8::FunctionCallbackInfo* m_pInfo; - CFXJSE_Value* m_pRetValue; + UnownedPtr m_pRetValue; }; #endif // FXJS_CFXJSE_ARGUMENTS_H_ diff --git a/fxjs/cfxjse_class.cpp b/fxjs/cfxjse_class.cpp index fd97b575ed539d8ca342d69917926c1bf87f794e..dd2181b853a70115f55796c4b768b07e80424235 100644 --- a/fxjs/cfxjse_class.cpp +++ b/fxjs/cfxjse_class.cpp @@ -7,9 +7,14 @@ #include "fxjs/cfxjse_class.h" #include +#include +#include "fxjs/cfxjse_arguments.h" #include "fxjs/cfxjse_context.h" #include "fxjs/cfxjse_value.h" +#include "fxjs/cjs_return.h" +#include "fxjs/js_resources.h" +#include "third_party/base/ptr_util.h" namespace { @@ -21,73 +26,16 @@ void V8FunctionCallback_Wrapper( if (!lpFunctionInfo) return; - CFX_ByteStringC szFunctionName(lpFunctionInfo->name); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); - lpThisValue->ForceSetValue(info.This()); - std::unique_ptr lpRetValue(new CFXJSE_Value(info.GetIsolate())); + ByteStringView szFunctionName(lpFunctionInfo->name); + auto lpThisValue = pdfium::MakeUnique(info.GetIsolate()); + lpThisValue->ForceSetValue(info.Holder()); + auto lpRetValue = pdfium::MakeUnique(info.GetIsolate()); CFXJSE_Arguments impl(&info, lpRetValue.get()); lpFunctionInfo->callbackProc(lpThisValue.get(), szFunctionName, impl); if (!lpRetValue->DirectGetValue().IsEmpty()) info.GetReturnValue().Set(lpRetValue->DirectGetValue()); } -void V8ClassGlobalConstructorCallback_Wrapper( - const v8::FunctionCallbackInfo& info) { - const FXJSE_CLASS_DESCRIPTOR* lpClassDefinition = - static_cast( - info.Data().As()->Value()); - if (!lpClassDefinition) - return; - - CFX_ByteStringC szFunctionName(lpClassDefinition->name); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); - lpThisValue->ForceSetValue(info.This()); - std::unique_ptr lpRetValue(new CFXJSE_Value(info.GetIsolate())); - CFXJSE_Arguments impl(&info, lpRetValue.get()); - lpClassDefinition->constructor(lpThisValue.get(), szFunctionName, impl); - if (!lpRetValue->DirectGetValue().IsEmpty()) - info.GetReturnValue().Set(lpRetValue->DirectGetValue()); -} - -void V8GetterCallback_Wrapper(v8::Local property, - const v8::PropertyCallbackInfo& info) { - const FXJSE_PROPERTY_DESCRIPTOR* lpPropertyInfo = - static_cast( - info.Data().As()->Value()); - if (!lpPropertyInfo) - return; - - CFX_ByteStringC szPropertyName(lpPropertyInfo->name); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); - std::unique_ptr lpPropValue( - new CFXJSE_Value(info.GetIsolate())); - lpThisValue->ForceSetValue(info.This()); - lpPropertyInfo->getProc(lpThisValue.get(), szPropertyName, lpPropValue.get()); - info.GetReturnValue().Set(lpPropValue->DirectGetValue()); -} - -void V8SetterCallback_Wrapper(v8::Local property, - v8::Local value, - const v8::PropertyCallbackInfo& info) { - const FXJSE_PROPERTY_DESCRIPTOR* lpPropertyInfo = - static_cast( - info.Data().As()->Value()); - if (!lpPropertyInfo) - return; - - CFX_ByteStringC szPropertyName(lpPropertyInfo->name); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); - std::unique_ptr lpPropValue( - new CFXJSE_Value(info.GetIsolate())); - lpThisValue->ForceSetValue(info.This()); - lpPropValue->ForceSetValue(value); - lpPropertyInfo->setProc(lpThisValue.get(), szPropertyName, lpPropValue.get()); -} - void V8ConstructorCallback_Wrapper( const v8::FunctionCallbackInfo& info) { if (!info.IsConstructCall()) @@ -99,8 +47,8 @@ void V8ConstructorCallback_Wrapper( if (!lpClassDefinition) return; - ASSERT(info.This()->InternalFieldCount()); - info.This()->SetAlignedPointerInInternalField(0, nullptr); + ASSERT(info.Holder()->InternalFieldCount()); + info.Holder()->SetAlignedPointerInInternalField(0, nullptr); } void Context_GlobalObjToString( @@ -111,15 +59,14 @@ void Context_GlobalObjToString( return; if (info.This() == info.Holder() && lpClass->name) { - CFX_ByteString szStringVal; - szStringVal.Format("[object %s]", lpClass->name); + ByteString szStringVal = ByteString::Format("[object %s]", lpClass->name); info.GetReturnValue().Set(v8::String::NewFromUtf8( info.GetIsolate(), szStringVal.c_str(), v8::String::kNormalString, szStringVal.GetLength())); return; } v8::Local local_str = - info.This() + info.Holder() ->ObjectProtoToString(info.GetIsolate()->GetCurrentContext()) .FromMaybe(v8::Local()); info.GetReturnValue().Set(local_str); @@ -133,23 +80,29 @@ void DynPropGetterAdapter_MethodCallback( v8::Local hPropName = hCallBackInfo->GetInternalField(1).As(); ASSERT(lpClass && !hPropName.IsEmpty()); - v8::String::Utf8Value szPropName(hPropName); - CFX_ByteStringC szFxPropName = *szPropName; - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); - lpThisValue->ForceSetValue(info.This()); - std::unique_ptr lpRetValue(new CFXJSE_Value(info.GetIsolate())); - CFXJSE_Arguments impl(&info, lpRetValue.get()); - lpClass->dynMethodCall(lpThisValue.get(), szFxPropName, impl); - if (!lpRetValue->DirectGetValue().IsEmpty()) - info.GetReturnValue().Set(lpRetValue->DirectGetValue()); + + v8::String::Utf8Value szPropName(info.GetIsolate(), hPropName); + WideString szFxPropName = WideString::FromUTF8(*szPropName); + + CJS_Return result = lpClass->dynMethodCall(info, szFxPropName); + if (result.HasError()) { + WideString err = JSFormatErrorString(*szPropName, "", result.Error()); + v8::MaybeLocal str = v8::String::NewFromUtf8( + info.GetIsolate(), ByteString::FromUnicode(err).c_str(), + v8::NewStringType::kNormal); + info.GetIsolate()->ThrowException(str.ToLocalChecked()); + return; + } + if (result.HasReturn()) + info.GetReturnValue().Set(result.Return()); } void DynPropGetterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue) { ASSERT(lpClass); + int32_t nPropType = lpClass->dynPropTypeGetter == nullptr ? FXJSE_ClassPropType_Property @@ -183,7 +136,7 @@ void DynPropGetterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, void DynPropSetterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue) { ASSERT(lpClass); int32_t nPropType = @@ -198,7 +151,7 @@ void DynPropSetterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, bool DynPropQueryAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName) { + const ByteStringView& szPropName) { ASSERT(lpClass); int32_t nPropType = lpClass->dynPropTypeGetter == nullptr @@ -207,34 +160,17 @@ bool DynPropQueryAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, return nPropType != FXJSE_ClassPropType_None; } -bool DynPropDeleterAdapter(const FXJSE_CLASS_DESCRIPTOR* lpClass, - CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName) { - ASSERT(lpClass); - int32_t nPropType = - lpClass->dynPropTypeGetter == nullptr - ? FXJSE_ClassPropType_Property - : lpClass->dynPropTypeGetter(pObject, szPropName, false); - if (nPropType != FXJSE_ClassPropType_Method) { - if (lpClass->dynPropDeleter) - return lpClass->dynPropDeleter(pObject, szPropName); - return nPropType != FXJSE_ClassPropType_Property; - } - return false; -} - void NamedPropertyQueryCallback( v8::Local property, const v8::PropertyCallbackInfo& info) { - v8::Local thisObject = info.This(); + v8::Local thisObject = info.Holder(); const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast( info.Data().As()->Value()); v8::Isolate* pIsolate = info.GetIsolate(); v8::HandleScope scope(pIsolate); - v8::String::Utf8Value szPropName(property); - CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); + v8::String::Utf8Value szPropName(pIsolate, property); + ByteStringView szFxPropName(*szPropName, szPropName.length()); + auto lpThisValue = pdfium::MakeUnique(info.GetIsolate()); lpThisValue->ForceSetValue(thisObject); if (DynPropQueryAdapter(lpClass, lpThisValue.get(), szFxPropName)) { info.GetReturnValue().Set(v8::DontDelete); @@ -244,35 +180,17 @@ void NamedPropertyQueryCallback( info.GetReturnValue().Set(iV8Absent); } -void NamedPropertyDeleterCallback( - v8::Local property, - const v8::PropertyCallbackInfo& info) { - v8::Local thisObject = info.This(); - const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast( - info.Data().As()->Value()); - v8::Isolate* pIsolate = info.GetIsolate(); - v8::HandleScope scope(pIsolate); - v8::String::Utf8Value szPropName(property); - CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); - lpThisValue->ForceSetValue(thisObject); - info.GetReturnValue().Set( - !!DynPropDeleterAdapter(lpClass, lpThisValue.get(), szFxPropName)); -} - void NamedPropertyGetterCallback( v8::Local property, const v8::PropertyCallbackInfo& info) { - v8::Local thisObject = info.This(); + v8::Local thisObject = info.Holder(); const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast( info.Data().As()->Value()); - v8::String::Utf8Value szPropName(property); - CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); + v8::String::Utf8Value szPropName(info.GetIsolate(), property); + ByteStringView szFxPropName(*szPropName, szPropName.length()); + auto lpThisValue = pdfium::MakeUnique(info.GetIsolate()); lpThisValue->ForceSetValue(thisObject); - std::unique_ptr lpNewValue(new CFXJSE_Value(info.GetIsolate())); + auto lpNewValue = pdfium::MakeUnique(info.GetIsolate()); DynPropGetterAdapter(lpClass, lpThisValue.get(), szFxPropName, lpNewValue.get()); info.GetReturnValue().Set(lpNewValue->DirectGetValue()); @@ -282,16 +200,15 @@ void NamedPropertySetterCallback( v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info) { - v8::Local thisObject = info.This(); + v8::Local thisObject = info.Holder(); const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast( info.Data().As()->Value()); - v8::String::Utf8Value szPropName(property); - CFX_ByteStringC szFxPropName(*szPropName, szPropName.length()); - std::unique_ptr lpThisValue( - new CFXJSE_Value(info.GetIsolate())); + v8::String::Utf8Value szPropName(info.GetIsolate(), property); + ByteStringView szFxPropName(*szPropName, szPropName.length()); + auto lpThisValue = pdfium::MakeUnique(info.GetIsolate()); lpThisValue->ForceSetValue(thisObject); - std::unique_ptr lpNewValue(new CFXJSE_Value(info.GetIsolate())); + auto lpNewValue = pdfium::MakeUnique(info.GetIsolate()); lpNewValue->ForceSetValue(value); DynPropSetterAdapter(lpClass, lpThisValue.get(), szFxPropName, lpNewValue.get()); @@ -300,15 +217,7 @@ void NamedPropertySetterCallback( void NamedPropertyEnumeratorCallback( const v8::PropertyCallbackInfo& info) { - const FXJSE_CLASS_DESCRIPTOR* lpClass = static_cast( - info.Data().As()->Value()); - v8::Isolate* pIsolate = info.GetIsolate(); - v8::Local newArray = v8::Array::New(pIsolate, lpClass->propNum); - for (int i = 0; i < lpClass->propNum; i++) { - newArray->Set( - i, v8::String::NewFromUtf8(pIsolate, lpClass->properties[i].name)); - } - info.GetReturnValue().Set(newArray); + info.GetReturnValue().Set(v8::Array::New(info.GetIsolate())); } } // namespace @@ -321,13 +230,13 @@ CFXJSE_Class* CFXJSE_Class::Create( if (!lpContext || !lpClassDefinition) return nullptr; - CFXJSE_Class* pClass = - GetClassFromContext(lpContext, lpClassDefinition->name); - if (pClass) - return pClass; + CFXJSE_Class* pExistingClass = + lpContext->GetClassByName(lpClassDefinition->name); + if (pExistingClass) + return pExistingClass; - v8::Isolate* pIsolate = lpContext->m_pIsolate; - pClass = new CFXJSE_Class(lpContext); + v8::Isolate* pIsolate = lpContext->GetIsolate(); + auto pClass = pdfium::MakeUnique(lpContext); pClass->m_szClassName = lpClassDefinition->name; pClass->m_lpClassDefinition = lpClassDefinition; CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate); @@ -337,25 +246,11 @@ CFXJSE_Class* CFXJSE_Class::Create( pIsolate, const_cast(lpClassDefinition))); hFunctionTemplate->SetClassName( v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name)); - hFunctionTemplate->InstanceTemplate()->SetInternalFieldCount(1); + hFunctionTemplate->InstanceTemplate()->SetInternalFieldCount(2); v8::Local hObjectTemplate = hFunctionTemplate->InstanceTemplate(); SetUpNamedPropHandler(pIsolate, hObjectTemplate, lpClassDefinition); - if (lpClassDefinition->propNum) { - for (int32_t i = 0; i < lpClassDefinition->propNum; i++) { - hObjectTemplate->SetNativeDataProperty( - v8::String::NewFromUtf8(pIsolate, - lpClassDefinition->properties[i].name), - lpClassDefinition->properties[i].getProc ? V8GetterCallback_Wrapper - : nullptr, - lpClassDefinition->properties[i].setProc ? V8SetterCallback_Wrapper - : nullptr, - v8::External::New(pIsolate, const_cast( - lpClassDefinition->properties + i)), - static_cast(v8::DontDelete)); - } - } if (lpClassDefinition->methNum) { for (int32_t i = 0; i < lpClassDefinition->methNum; i++) { v8::Local fun = v8::FunctionTemplate::New( @@ -369,27 +264,7 @@ CFXJSE_Class* CFXJSE_Class::Create( static_cast(v8::ReadOnly | v8::DontDelete)); } } - if (lpClassDefinition->constructor) { - if (bIsJSGlobal) { - hObjectTemplate->Set( - v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name), - v8::FunctionTemplate::New( - pIsolate, V8ClassGlobalConstructorCallback_Wrapper, - v8::External::New(pIsolate, const_cast( - lpClassDefinition))), - static_cast(v8::ReadOnly | v8::DontDelete)); - } else { - v8::Local hLocalContext = - v8::Local::New(pIsolate, lpContext->m_hContext); - FXJSE_GetGlobalObjectFromContext(hLocalContext) - ->Set(v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name), - v8::Function::New( - pIsolate, V8ClassGlobalConstructorCallback_Wrapper, - v8::External::New(pIsolate, - const_cast( - lpClassDefinition)))); - } - } + if (bIsJSGlobal) { v8::Local fun = v8::FunctionTemplate::New( pIsolate, Context_GlobalObjToString, @@ -398,19 +273,10 @@ CFXJSE_Class* CFXJSE_Class::Create( fun->RemovePrototype(); hObjectTemplate->Set(v8::String::NewFromUtf8(pIsolate, "toString"), fun); } - pClass->m_hTemplate.Reset(lpContext->m_pIsolate, hFunctionTemplate); - lpContext->m_rgClasses.push_back(std::unique_ptr(pClass)); - return pClass; -} - -// static -CFXJSE_Class* CFXJSE_Class::GetClassFromContext(CFXJSE_Context* pContext, - const CFX_ByteStringC& szName) { - for (const auto& pClass : pContext->m_rgClasses) { - if (pClass->m_szClassName == szName) - return pClass.get(); - } - return nullptr; + pClass->m_hTemplate.Reset(lpContext->GetIsolate(), hFunctionTemplate); + CFXJSE_Class* pResult = pClass.get(); + lpContext->AddClass(std::move(pClass)); + return pResult; } // static @@ -421,8 +287,7 @@ void CFXJSE_Class::SetUpNamedPropHandler( v8::NamedPropertyHandlerConfiguration configuration( lpClassDefinition->dynPropGetter ? NamedPropertyGetterCallback : 0, lpClassDefinition->dynPropSetter ? NamedPropertySetterCallback : 0, - lpClassDefinition->dynPropTypeGetter ? NamedPropertyQueryCallback : 0, - lpClassDefinition->dynPropDeleter ? NamedPropertyDeleterCallback : 0, + lpClassDefinition->dynPropTypeGetter ? NamedPropertyQueryCallback : 0, 0, NamedPropertyEnumeratorCallback, v8::External::New(pIsolate, const_cast(lpClassDefinition)), diff --git a/fxjs/cfxjse_class.h b/fxjs/cfxjse_class.h index 1b3528a5c00d48970b1aaaf065c00724ba6fba5a..056525f30b75fea00f28a4ff82e7f935c0cddff7 100644 --- a/fxjs/cfxjse_class.h +++ b/fxjs/cfxjse_class.h @@ -7,7 +7,7 @@ #ifndef FXJS_CFXJSE_CLASS_H_ #define FXJS_CFXJSE_CLASS_H_ -#include "fxjs/cfxjse_arguments.h" +#include "core/fxcrt/unowned_ptr.h" #include "fxjs/fxjse.h" #include "v8/include/v8.h" @@ -18,25 +18,23 @@ class CFXJSE_Class { public: static CFXJSE_Class* Create(CFXJSE_Context* pContext, const FXJSE_CLASS_DESCRIPTOR* lpClassDefintion, - bool bIsJSGlobal = false); - static CFXJSE_Class* GetClassFromContext(CFXJSE_Context* pContext, - const CFX_ByteStringC& szName); + bool bIsJSGlobal); + static void SetUpNamedPropHandler( v8::Isolate* pIsolate, v8::Local& hObjectTemplate, const FXJSE_CLASS_DESCRIPTOR* lpClassDefinition); + explicit CFXJSE_Class(CFXJSE_Context* lpContext); ~CFXJSE_Class(); - CFXJSE_Context* GetContext() { return m_pContext; } + CFXJSE_Context* GetContext() const { return m_pContext.Get(); } v8::Global& GetTemplate() { return m_hTemplate; } protected: - explicit CFXJSE_Class(CFXJSE_Context* lpContext); - - CFX_ByteString m_szClassName; - const FXJSE_CLASS_DESCRIPTOR* m_lpClassDefinition; - CFXJSE_Context* m_pContext; + ByteString m_szClassName; + UnownedPtr m_lpClassDefinition; + UnownedPtr m_pContext; v8::Global m_hTemplate; friend class CFXJSE_Context; friend class CFXJSE_Value; diff --git a/fxjs/cfxjse_context.cpp b/fxjs/cfxjse_context.cpp index d82f875e0f037ad5f3876730a9d6093d01ae03f9..bf9bee8652ca8988a024cf31b086cdbc65243f1e 100644 --- a/fxjs/cfxjse_context.cpp +++ b/fxjs/cfxjse_context.cpp @@ -6,12 +6,15 @@ #include "fxjs/cfxjse_context.h" +#include + #include "fxjs/cfxjse_class.h" #include "fxjs/cfxjse_value.h" +#include "third_party/base/ptr_util.h" namespace { -const FX_CHAR szCompatibleModeScript[] = +const char szCompatibleModeScript[] = "(function(global, list) {\n" " 'use strict';\n" " var objname;\n" @@ -38,6 +41,50 @@ const FX_CHAR szCompatibleModeScript[] = " }\n" "}(this, {String: ['substr', 'toUpperCase']}));"; +wchar_t g_FXJSETagString[] = L"FXJSE_HostObject"; + +v8::Local CreateReturnValue(v8::Isolate* pIsolate, + v8::TryCatch& trycatch) { + v8::Local hReturnValue = v8::Object::New(pIsolate); + if (trycatch.HasCaught()) { + v8::Local hException = trycatch.Exception(); + v8::Local hMessage = trycatch.Message(); + if (hException->IsObject()) { + v8::Local hValue; + hValue = hException.As()->Get( + v8::String::NewFromUtf8(pIsolate, "name")); + if (hValue->IsString() || hValue->IsStringObject()) + hReturnValue->Set(0, hValue); + else + hReturnValue->Set(0, v8::String::NewFromUtf8(pIsolate, "Error")); + + hValue = hException.As()->Get( + v8::String::NewFromUtf8(pIsolate, "message")); + if (hValue->IsString() || hValue->IsStringObject()) + hReturnValue->Set(1, hValue); + else + hReturnValue->Set(1, hMessage->Get()); + } else { + hReturnValue->Set(0, v8::String::NewFromUtf8(pIsolate, "Error")); + hReturnValue->Set(1, hMessage->Get()); + } + hReturnValue->Set(2, hException); + hReturnValue->Set(3, v8::Integer::New(pIsolate, hMessage->GetLineNumber())); + hReturnValue->Set(4, hMessage->GetSourceLine()); + v8::Maybe maybe_int = + hMessage->GetStartColumn(pIsolate->GetCurrentContext()); + hReturnValue->Set(5, v8::Integer::New(pIsolate, maybe_int.FromMaybe(0))); + maybe_int = hMessage->GetEndColumn(pIsolate->GetCurrentContext()); + hReturnValue->Set(6, v8::Integer::New(pIsolate, maybe_int.FromMaybe(0))); + } + return hReturnValue; +} + +v8::Local GetGlobalObjectFromContext( + v8::Local hContext) { + return hContext->Global()->GetPrototype().As(); +} + } // namespace // Note, not in the anonymous namespace due to the friend call @@ -63,109 +110,69 @@ class CFXJSE_ScopeUtil_IsolateHandleContext { void* operator new(size_t size) = delete; void operator delete(void*, size_t) = delete; - CFXJSE_Context* m_context; + UnownedPtr m_context; CFXJSE_ScopeUtil_IsolateHandle m_parent; v8::Context::Scope m_cscope; }; -v8::Local FXJSE_GetGlobalObjectFromContext( - const v8::Local& hContext) { - return hContext->Global()->GetPrototype().As(); -} - void FXJSE_UpdateObjectBinding(v8::Local& hObject, CFXJSE_HostObject* lpNewBinding) { ASSERT(!hObject.IsEmpty()); - ASSERT(hObject->InternalFieldCount() > 0); - hObject->SetAlignedPointerInInternalField(0, - static_cast(lpNewBinding)); + ASSERT(hObject->InternalFieldCount() == 2); + hObject->SetAlignedPointerInInternalField(0, g_FXJSETagString); + hObject->SetAlignedPointerInInternalField(1, lpNewBinding); } -CFXJSE_HostObject* FXJSE_RetrieveObjectBinding( - const v8::Local& hJSObject, - CFXJSE_Class* lpClass) { +CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local hJSObject, + CFXJSE_Class* lpClass) { ASSERT(!hJSObject.IsEmpty()); if (!hJSObject->IsObject()) return nullptr; v8::Local hObject = hJSObject; - if (hObject->InternalFieldCount() == 0) { + if (hObject->InternalFieldCount() != 2) { v8::Local hProtoObject = hObject->GetPrototype(); if (hProtoObject.IsEmpty() || !hProtoObject->IsObject()) return nullptr; hObject = hProtoObject.As(); - if (hObject->InternalFieldCount() == 0) + if (hObject->InternalFieldCount() != 2) return nullptr; } + if (hObject->GetAlignedPointerFromInternalField(0) != g_FXJSETagString) + return nullptr; if (lpClass) { v8::Local hClass = v8::Local::New( - lpClass->GetContext()->GetRuntime(), lpClass->GetTemplate()); + lpClass->GetContext()->GetIsolate(), lpClass->GetTemplate()); if (!hClass->HasInstance(hObject)) return nullptr; } return static_cast( - hObject->GetAlignedPointerFromInternalField(0)); -} - -v8::Local FXJSE_CreateReturnValue(v8::Isolate* pIsolate, - v8::TryCatch& trycatch) { - v8::Local hReturnValue = v8::Object::New(pIsolate); - if (trycatch.HasCaught()) { - v8::Local hException = trycatch.Exception(); - v8::Local hMessage = trycatch.Message(); - if (hException->IsObject()) { - v8::Local hValue; - hValue = hException.As()->Get( - v8::String::NewFromUtf8(pIsolate, "name")); - if (hValue->IsString() || hValue->IsStringObject()) - hReturnValue->Set(0, hValue); - else - hReturnValue->Set(0, v8::String::NewFromUtf8(pIsolate, "Error")); - - hValue = hException.As()->Get( - v8::String::NewFromUtf8(pIsolate, "message")); - if (hValue->IsString() || hValue->IsStringObject()) - hReturnValue->Set(1, hValue); - else - hReturnValue->Set(1, hMessage->Get()); - } else { - hReturnValue->Set(0, v8::String::NewFromUtf8(pIsolate, "Error")); - hReturnValue->Set(1, hMessage->Get()); - } - hReturnValue->Set(2, hException); - hReturnValue->Set(3, v8::Integer::New(pIsolate, hMessage->GetLineNumber())); - hReturnValue->Set(4, hMessage->GetSourceLine()); - v8::Maybe maybe_int = - hMessage->GetStartColumn(pIsolate->GetCurrentContext()); - hReturnValue->Set(5, v8::Integer::New(pIsolate, maybe_int.FromMaybe(0))); - maybe_int = hMessage->GetEndColumn(pIsolate->GetCurrentContext()); - hReturnValue->Set(6, v8::Integer::New(pIsolate, maybe_int.FromMaybe(0))); - } - return hReturnValue; + hObject->GetAlignedPointerFromInternalField(1)); } // static -CFXJSE_Context* CFXJSE_Context::Create( +std::unique_ptr CFXJSE_Context::Create( v8::Isolate* pIsolate, - const FXJSE_CLASS_DESCRIPTOR* lpGlobalClass, - CFXJSE_HostObject* lpGlobalObject) { + const FXJSE_CLASS_DESCRIPTOR* pGlobalClass, + CFXJSE_HostObject* pGlobalObject) { CFXJSE_ScopeUtil_IsolateHandle scope(pIsolate); - CFXJSE_Context* pContext = new CFXJSE_Context(pIsolate); - CFXJSE_Class* lpGlobalClassObj = nullptr; + auto pContext = pdfium::MakeUnique(pIsolate); v8::Local hObjectTemplate; - if (lpGlobalClass) { - lpGlobalClassObj = CFXJSE_Class::Create(pContext, lpGlobalClass, true); - ASSERT(lpGlobalClassObj); + if (pGlobalClass) { + CFXJSE_Class* pGlobalClassObj = + CFXJSE_Class::Create(pContext.get(), pGlobalClass, true); + ASSERT(pGlobalClassObj); v8::Local hFunctionTemplate = v8::Local::New(pIsolate, - lpGlobalClassObj->m_hTemplate); + pGlobalClassObj->m_hTemplate); hObjectTemplate = hFunctionTemplate->InstanceTemplate(); } else { hObjectTemplate = v8::ObjectTemplate::New(pIsolate); - hObjectTemplate->SetInternalFieldCount(1); + hObjectTemplate->SetInternalFieldCount(2); } + hObjectTemplate->Set( v8::Symbol::GetToStringTag(pIsolate), v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal) @@ -175,9 +182,8 @@ CFXJSE_Context* CFXJSE_Context::Create( v8::Local hRootContext = v8::Local::New( pIsolate, CFXJSE_RuntimeData::Get(pIsolate)->m_hRootContext); hNewContext->SetSecurityToken(hRootContext->GetSecurityToken()); - v8::Local hGlobalObject = - FXJSE_GetGlobalObjectFromContext(hNewContext); - FXJSE_UpdateObjectBinding(hGlobalObject, lpGlobalObject); + v8::Local hGlobalObject = GetGlobalObjectFromContext(hNewContext); + FXJSE_UpdateObjectBinding(hGlobalObject, pGlobalObject); pContext->m_hContext.Reset(pIsolate, hNewContext); return pContext; } @@ -187,22 +193,38 @@ CFXJSE_Context::CFXJSE_Context(v8::Isolate* pIsolate) : m_pIsolate(pIsolate) {} CFXJSE_Context::~CFXJSE_Context() {} std::unique_ptr CFXJSE_Context::GetGlobalObject() { - std::unique_ptr pValue(new CFXJSE_Value(m_pIsolate)); - + auto pValue = pdfium::MakeUnique(m_pIsolate); CFXJSE_ScopeUtil_IsolateHandleContext scope(this); v8::Local hContext = v8::Local::New(m_pIsolate, m_hContext); - v8::Local hGlobalObject = hContext->Global(); + v8::Local hGlobalObject = GetGlobalObjectFromContext(hContext); pValue->ForceSetValue(hGlobalObject); - return pValue; } +v8::Local CFXJSE_Context::GetContext() { + return v8::Local::New(m_pIsolate, m_hContext); +} + +void CFXJSE_Context::AddClass(std::unique_ptr pClass) { + m_rgClasses.push_back(std::move(pClass)); +} + +CFXJSE_Class* CFXJSE_Context::GetClassByName( + const ByteStringView& szName) const { + auto pClass = + std::find_if(m_rgClasses.begin(), m_rgClasses.end(), + [szName](const std::unique_ptr& item) { + return szName == item->m_szClassName; + }); + return pClass != m_rgClasses.end() ? pClass->get() : nullptr; +} + void CFXJSE_Context::EnableCompatibleMode() { ExecuteScript(szCompatibleModeScript, nullptr, nullptr); } -bool CFXJSE_Context::ExecuteScript(const FX_CHAR* szScript, +bool CFXJSE_Context::ExecuteScript(const char* szScript, CFXJSE_Value* lpRetValue, CFXJSE_Value* lpNewThisObject) { CFXJSE_ScopeUtil_IsolateHandleContext scope(this); @@ -221,7 +243,7 @@ bool CFXJSE_Context::ExecuteScript(const FX_CHAR* szScript, } if (lpRetValue) { lpRetValue->m_hValue.Reset(m_pIsolate, - FXJSE_CreateReturnValue(m_pIsolate, trycatch)); + CreateReturnValue(m_pIsolate, trycatch)); } return false; } @@ -246,7 +268,7 @@ bool CFXJSE_Context::ExecuteScript(const FX_CHAR* szScript, } if (lpRetValue) { lpRetValue->m_hValue.Reset(m_pIsolate, - FXJSE_CreateReturnValue(m_pIsolate, trycatch)); + CreateReturnValue(m_pIsolate, trycatch)); } return false; } diff --git a/fxjs/cfxjse_context.h b/fxjs/cfxjse_context.h index a6945147704fa4d9dcdb1597dc6ed4e274daa704..48816eb62974341358527e4fc47e8e94db1263d0 100644 --- a/fxjs/cfxjse_context.h +++ b/fxjs/cfxjse_context.h @@ -10,7 +10,6 @@ #include #include -#include "core/fxcrt/fx_basic.h" #include "fxjs/fxjse.h" #include "v8/include/v8.h" @@ -20,28 +19,29 @@ struct FXJSE_CLASS_DESCRIPTOR; class CFXJSE_Context { public: - static CFXJSE_Context* Create( + static std::unique_ptr Create( v8::Isolate* pIsolate, - const FXJSE_CLASS_DESCRIPTOR* lpGlobalClass = nullptr, - CFXJSE_HostObject* lpGlobalObject = nullptr); + const FXJSE_CLASS_DESCRIPTOR* pGlobalClass, + CFXJSE_HostObject* pGlobalObject); + explicit CFXJSE_Context(v8::Isolate* pIsolate); ~CFXJSE_Context(); - v8::Isolate* GetRuntime() { return m_pIsolate; } + v8::Isolate* GetIsolate() const { return m_pIsolate; } + v8::Local GetContext(); std::unique_ptr GetGlobalObject(); + void AddClass(std::unique_ptr pClass); + CFXJSE_Class* GetClassByName(const ByteStringView& szName) const; void EnableCompatibleMode(); - bool ExecuteScript(const FX_CHAR* szScript, + bool ExecuteScript(const char* szScript, CFXJSE_Value* lpRetValue, CFXJSE_Value* lpNewThisObject = nullptr); protected: - friend class CFXJSE_Class; friend class CFXJSE_ScopeUtil_IsolateHandleContext; CFXJSE_Context(); CFXJSE_Context(const CFXJSE_Context&); - explicit CFXJSE_Context(v8::Isolate* pIsolate); - CFXJSE_Context& operator=(const CFXJSE_Context&); v8::Global m_hContext; @@ -49,17 +49,10 @@ class CFXJSE_Context { std::vector> m_rgClasses; }; -v8::Local FXJSE_CreateReturnValue(v8::Isolate* pIsolate, - v8::TryCatch& trycatch); - -v8::Local FXJSE_GetGlobalObjectFromContext( - const v8::Local& hContext); - void FXJSE_UpdateObjectBinding(v8::Local& hObject, CFXJSE_HostObject* lpNewBinding = nullptr); -CFXJSE_HostObject* FXJSE_RetrieveObjectBinding( - const v8::Local& hJSObject, - CFXJSE_Class* lpClass = nullptr); +CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local hJSObject, + CFXJSE_Class* lpClass = nullptr); #endif // FXJS_CFXJSE_CONTEXT_H_ diff --git a/fxjs/cfxjse_engine.cpp b/fxjs/cfxjse_engine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..325895f56644833d4f5443d57f669ee337534065 --- /dev/null +++ b/fxjs/cfxjse_engine.cpp @@ -0,0 +1,755 @@ +// 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 "fxjs/cfxjse_engine.h" + +#include + +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_class.h" +#include "fxjs/cfxjse_resolveprocessor.h" +#include "fxjs/cfxjse_value.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodehelper.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#include "xfa/fxfa/parser/cxfa_thisproxy.h" +#include "xfa/fxfa/parser/cxfa_treelist.h" +#include "xfa/fxfa/parser/xfa_basic_data.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { + "Root", // name + nullptr, // methods + 0, // method count + CFXJSE_Engine::GlobalPropTypeGetter, + CFXJSE_Engine::GlobalPropertyGetter, + CFXJSE_Engine::GlobalPropertySetter, + CFXJSE_Engine::NormalMethodCall, +}; + +const FXJSE_CLASS_DESCRIPTOR NormalClassDescriptor = { + "XFAObject", // name + nullptr, // methods + 0, // method count + CFXJSE_Engine::NormalPropTypeGetter, + CFXJSE_Engine::NormalPropertyGetter, + CFXJSE_Engine::NormalPropertySetter, + CFXJSE_Engine::NormalMethodCall, +}; + +const FXJSE_CLASS_DESCRIPTOR VariablesClassDescriptor = { + "XFAScriptObject", // name + nullptr, // methods + 0, // method count + CFXJSE_Engine::NormalPropTypeGetter, + CFXJSE_Engine::GlobalPropertyGetter, + CFXJSE_Engine::GlobalPropertySetter, + CFXJSE_Engine::NormalMethodCall, +}; + +const char kFormCalcRuntime[] = "pfm_rt"; + +CXFA_ThisProxy* ToThisProxy(CFXJSE_Value* pValue, CFXJSE_Class* pClass) { + return static_cast(pValue->ToHostObject(pClass)); +} + +} // namespace + +// static +CXFA_Object* CFXJSE_Engine::ToObject( + const v8::FunctionCallbackInfo& info) { + if (!info.Holder()->IsObject()) + return nullptr; + + CFXJSE_HostObject* hostObj = + FXJSE_RetrieveObjectBinding(info.Holder().As(), nullptr); + if (!hostObj || hostObj->type() != CFXJSE_HostObject::kXFA) + return nullptr; + return static_cast(hostObj); +} + +// static. +CXFA_Object* CFXJSE_Engine::ToObject(CFXJSE_Value* pValue, + CFXJSE_Class* pClass) { + CFXJSE_HostObject* pHostObj = pValue->ToHostObject(pClass); + if (!pHostObj || pHostObj->type() != CFXJSE_HostObject::kXFA) + return nullptr; + return static_cast(pHostObj); +} + +CFXJSE_Engine::CFXJSE_Engine(CXFA_Document* pDocument, v8::Isolate* pIsolate) + : CJS_V8(pIsolate), + m_pDocument(pDocument), + m_JsContext(CFXJSE_Context::Create(pIsolate, + &GlobalClassDescriptor, + pDocument->GetRoot())), + m_pJsClass(nullptr), + m_eScriptType(CXFA_Script::Type::Unknown), + m_pScriptNodeArray(nullptr), + m_ResolveProcessor(pdfium::MakeUnique()), + m_pThisObject(nullptr), + m_eRunAtType(XFA_AttributeEnum::Client) { + RemoveBuiltInObjs(m_JsContext.get()); + m_JsContext->EnableCompatibleMode(); + + // Don't know if this can happen before we remove the builtin objs and set + // compatibility mode. + m_pJsClass = + CFXJSE_Class::Create(m_JsContext.get(), &NormalClassDescriptor, false); +} + +CFXJSE_Engine::~CFXJSE_Engine() { + for (const auto& pair : m_mapVariableToContext) + delete ToThisProxy(pair.second->GetGlobalObject().get(), nullptr); +} + +bool CFXJSE_Engine::RunScript(CXFA_Script::Type eScriptType, + const WideStringView& wsScript, + CFXJSE_Value* hRetValue, + CXFA_Object* pThisObject) { + ByteString btScript; + AutoRestorer typeRestorer(&m_eScriptType); + m_eScriptType = eScriptType; + if (eScriptType == CXFA_Script::Type::Formcalc) { + if (!m_FM2JSContext) { + m_FM2JSContext = pdfium::MakeUnique( + GetIsolate(), m_JsContext.get(), m_pDocument.Get()); + } + CFX_WideTextBuf wsJavaScript; + if (!CFXJSE_FormCalcContext::Translate(wsScript, &wsJavaScript)) { + hRetValue->SetUndefined(); + return false; + } + btScript = FX_UTF8Encode(wsJavaScript.AsStringView()); + } else { + btScript = FX_UTF8Encode(wsScript); + } + AutoRestorer nodeRestorer(&m_pThisObject); + m_pThisObject = pThisObject; + CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : nullptr; + return m_JsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue); +} + +bool CFXJSE_Engine::QueryNodeByFlag(CXFA_Node* refNode, + const WideStringView& propname, + CFXJSE_Value* pValue, + uint32_t dwFlag, + bool bSetting) { + if (!refNode) + return false; + + XFA_RESOLVENODE_RS resolveRs; + if (!ResolveObjects(refNode, propname, &resolveRs, dwFlag, nullptr)) + return false; + if (resolveRs.dwFlags == XFA_ResolveNode_RSType_Nodes) { + pValue->Assign(GetJSValueFromMap(resolveRs.objects.front())); + return true; + } + if (resolveRs.dwFlags == XFA_ResolveNode_RSType_Attribute) { + const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = resolveRs.pScriptAttribute; + if (lpAttributeInfo) { + CJX_Object* jsObject = resolveRs.objects.front()->JSObject(); + (jsObject->*(lpAttributeInfo->callback))(pValue, bSetting, + lpAttributeInfo->attribute); + } + } + return true; +} + +void CFXJSE_Engine::GlobalPropertySetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + CFXJSE_Value* pValue) { + CXFA_Object* lpOrginalNode = ToObject(pObject, nullptr); + CXFA_Document* pDoc = lpOrginalNode->GetDocument(); + CFXJSE_Engine* lpScriptContext = pDoc->GetScriptContext(); + CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); + if (lpOrginalNode->IsVariablesThis()) + pRefNode = ToNode(lpScriptContext->GetVariablesThis(lpOrginalNode)); + + WideString wsPropName = WideString::FromUTF8(szPropName); + if (lpScriptContext->QueryNodeByFlag( + pRefNode, wsPropName.AsStringView(), pValue, + XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Attributes, + true)) { + return; + } + if (lpOrginalNode->IsVariablesThis()) { + if (pValue && pValue->IsUndefined()) { + pObject->SetObjectOwnProperty(szPropName, pValue); + return; + } + } + CXFA_FFNotify* pNotify = pDoc->GetNotify(); + if (!pNotify) + return; + + pNotify->GetDocEnvironment()->SetGlobalProperty(pNotify->GetHDOC(), + szPropName, pValue); +} + +void CFXJSE_Engine::GlobalPropertyGetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + CFXJSE_Value* pValue) { + CXFA_Object* pOriginalObject = ToObject(pObject, nullptr); + CXFA_Document* pDoc = pOriginalObject->GetDocument(); + CFXJSE_Engine* lpScriptContext = pDoc->GetScriptContext(); + WideString wsPropName = WideString::FromUTF8(szPropName); + if (lpScriptContext->GetType() == CXFA_Script::Type::Formcalc) { + if (szPropName == kFormCalcRuntime) { + lpScriptContext->m_FM2JSContext->GlobalPropertyGetter(pValue); + return; + } + XFA_HashCode uHashCode = static_cast( + FX_HashCode_GetW(wsPropName.AsStringView(), false)); + if (uHashCode != XFA_HASHCODE_Layout) { + CXFA_Object* pObj = + lpScriptContext->GetDocument()->GetXFAObject(uHashCode); + if (pObj) { + pValue->Assign(lpScriptContext->GetJSValueFromMap(pObj)); + return; + } + } + } + + CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); + if (pOriginalObject->IsVariablesThis()) + pRefNode = ToNode(lpScriptContext->GetVariablesThis(pOriginalObject)); + + if (lpScriptContext->QueryNodeByFlag( + pRefNode, wsPropName.AsStringView(), pValue, + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Attributes, + false)) { + return; + } + + if (lpScriptContext->QueryNodeByFlag( + pRefNode, wsPropName.AsStringView(), pValue, + XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings, false)) { + return; + } + + CXFA_Object* pScriptObject = + lpScriptContext->GetVariablesThis(pOriginalObject, true); + if (pScriptObject && lpScriptContext->QueryVariableValue( + pScriptObject->AsNode(), szPropName, pValue, true)) { + return; + } + + CXFA_FFNotify* pNotify = pDoc->GetNotify(); + if (!pNotify) + return; + + pNotify->GetDocEnvironment()->GetGlobalProperty(pNotify->GetHDOC(), + szPropName, pValue); +} + +int32_t CFXJSE_Engine::GlobalPropTypeGetter(CFXJSE_Value* pOriginalValue, + const ByteStringView& szPropName, + bool bQueryIn) { + CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); + if (!pObject) + return FXJSE_ClassPropType_None; + + CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext(); + pObject = lpScriptContext->GetVariablesThis(pObject); + WideString wsPropName = WideString::FromUTF8(szPropName); + if (pObject->JSObject()->HasMethod(wsPropName)) + return FXJSE_ClassPropType_Method; + + return FXJSE_ClassPropType_Property; +} + +void CFXJSE_Engine::NormalPropertyGetter(CFXJSE_Value* pOriginalValue, + const ByteStringView& szPropName, + CFXJSE_Value* pReturnValue) { + CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); + if (!pOriginalObject) { + pReturnValue->SetUndefined(); + return; + } + + WideString wsPropName = WideString::FromUTF8(szPropName); + CFXJSE_Engine* lpScriptContext = + pOriginalObject->GetDocument()->GetScriptContext(); + CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); + if (wsPropName == L"xfa") { + CFXJSE_Value* pValue = lpScriptContext->GetJSValueFromMap( + lpScriptContext->GetDocument()->GetRoot()); + pReturnValue->Assign(pValue); + return; + } + + bool bRet = lpScriptContext->QueryNodeByFlag( + ToNode(pObject), wsPropName.AsStringView(), pReturnValue, + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Attributes, + false); + if (bRet) + return; + + if (pObject == lpScriptContext->GetThisObject() || + (lpScriptContext->GetType() == CXFA_Script::Type::Javascript && + !lpScriptContext->IsStrictScopeInJavaScript())) { + bRet = lpScriptContext->QueryNodeByFlag( + ToNode(pObject), wsPropName.AsStringView(), pReturnValue, + XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings, false); + } + if (bRet) + return; + + CXFA_Object* pScriptObject = + lpScriptContext->GetVariablesThis(pOriginalObject, true); + if (pScriptObject) { + bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject), + szPropName, pReturnValue, true); + } + if (!bRet) + pReturnValue->SetUndefined(); +} + +void CFXJSE_Engine::NormalPropertySetter(CFXJSE_Value* pOriginalValue, + const ByteStringView& szPropName, + CFXJSE_Value* pReturnValue) { + CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); + if (!pOriginalObject) + return; + + CFXJSE_Engine* lpScriptContext = + pOriginalObject->GetDocument()->GetScriptContext(); + CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); + WideString wsPropName = WideString::FromUTF8(szPropName); + const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = XFA_GetScriptAttributeByName( + pObject->GetElementType(), wsPropName.AsStringView()); + if (lpAttributeInfo) { + CJX_Object* jsObject = pObject->JSObject(); + (jsObject->*(lpAttributeInfo->callback))(pReturnValue, true, + lpAttributeInfo->attribute); + return; + } + + if (pObject->IsNode()) { + if (wsPropName[0] == '#') + wsPropName = wsPropName.Right(wsPropName.GetLength() - 1); + + CXFA_Node* pNode = ToNode(pObject); + CXFA_Node* pPropOrChild = nullptr; + XFA_Element eType = CXFA_Node::NameToElement(wsPropName); + if (eType != XFA_Element::Unknown) { + pPropOrChild = + pNode->JSObject()->GetOrCreateProperty(0, eType); + } else { + pPropOrChild = pNode->GetFirstChildByName(wsPropName.AsStringView()); + } + + if (pPropOrChild) { + const XFA_SCRIPTATTRIBUTEINFO* lpAttrInfo = XFA_GetScriptAttributeByName( + pPropOrChild->GetElementType(), L"{default}"); + if (lpAttrInfo) { + pPropOrChild->JSObject()->Script_Som_DefaultValue( + pReturnValue, true, XFA_Attribute::Unknown); + return; + } + } + } + + CXFA_Object* pScriptObject = + lpScriptContext->GetVariablesThis(pOriginalObject, true); + if (pScriptObject) { + lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName, + pReturnValue, false); + } +} + +int32_t CFXJSE_Engine::NormalPropTypeGetter(CFXJSE_Value* pOriginalValue, + const ByteStringView& szPropName, + bool bQueryIn) { + CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); + if (!pObject) + return FXJSE_ClassPropType_None; + + CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext(); + pObject = lpScriptContext->GetVariablesThis(pObject); + XFA_Element eType = pObject->GetElementType(); + WideString wsPropName = WideString::FromUTF8(szPropName); + if (pObject->JSObject()->HasMethod(wsPropName)) + return FXJSE_ClassPropType_Method; + + if (bQueryIn && + !XFA_GetScriptAttributeByName(eType, wsPropName.AsStringView())) { + return FXJSE_ClassPropType_None; + } + return FXJSE_ClassPropType_Property; +} + +CJS_Return CFXJSE_Engine::NormalMethodCall( + const v8::FunctionCallbackInfo& info, + const WideString& functionName) { + CXFA_Object* pObject = ToObject(info); + if (!pObject) + return CJS_Return(false); + + CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext(); + pObject = lpScriptContext->GetVariablesThis(pObject); + + std::vector> parameters; + for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) + parameters.push_back(info[i]); + + return pObject->JSObject()->RunMethod(functionName, parameters); +} + +bool CFXJSE_Engine::IsStrictScopeInJavaScript() { + return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); +} + +CXFA_Script::Type CFXJSE_Engine::GetType() { + return m_eScriptType; +} + +CFXJSE_Context* CFXJSE_Engine::CreateVariablesContext(CXFA_Node* pScriptNode, + CXFA_Node* pSubform) { + if (!pScriptNode || !pSubform) + return nullptr; + + auto pNewContext = + CFXJSE_Context::Create(GetIsolate(), &VariablesClassDescriptor, + new CXFA_ThisProxy(pSubform, pScriptNode)); + RemoveBuiltInObjs(pNewContext.get()); + pNewContext->EnableCompatibleMode(); + CFXJSE_Context* pResult = pNewContext.get(); + m_mapVariableToContext[pScriptNode] = std::move(pNewContext); + return pResult; +} + +CXFA_Object* CFXJSE_Engine::GetVariablesThis(CXFA_Object* pObject, + bool bScriptNode) { + if (!pObject->IsVariablesThis()) + return pObject; + + CXFA_ThisProxy* pProxy = static_cast(pObject); + return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); +} + +bool CFXJSE_Engine::RunVariablesScript(CXFA_Node* pScriptNode) { + if (!pScriptNode) + return false; + + if (pScriptNode->GetElementType() != XFA_Element::Script) + return true; + + CXFA_Node* pParent = pScriptNode->GetParent(); + if (!pParent || pParent->GetElementType() != XFA_Element::Variables) + return false; + + auto it = m_mapVariableToContext.find(pScriptNode); + if (it != m_mapVariableToContext.end() && it->second) + return true; + + CXFA_Node* pTextNode = pScriptNode->GetFirstChild(); + if (!pTextNode) + return false; + + Optional wsScript = + pTextNode->JSObject()->TryCData(XFA_Attribute::Value, true); + if (!wsScript) + return false; + + ByteString btScript = wsScript->UTF8Encode(); + auto hRetValue = pdfium::MakeUnique(GetIsolate()); + CXFA_Node* pThisObject = pParent->GetParent(); + CFXJSE_Context* pVariablesContext = + CreateVariablesContext(pScriptNode, pThisObject); + AutoRestorer nodeRestorer(&m_pThisObject); + m_pThisObject = pThisObject; + return pVariablesContext->ExecuteScript(btScript.c_str(), hRetValue.get()); +} + +bool CFXJSE_Engine::QueryVariableValue(CXFA_Node* pScriptNode, + const ByteStringView& szPropName, + CFXJSE_Value* pValue, + bool bGetter) { + if (!pScriptNode || pScriptNode->GetElementType() != XFA_Element::Script) + return false; + + CXFA_Node* variablesNode = pScriptNode->GetParent(); + if (!variablesNode || + variablesNode->GetElementType() != XFA_Element::Variables) + return false; + + auto it = m_mapVariableToContext.find(pScriptNode); + if (it == m_mapVariableToContext.end() || !it->second) + return false; + + CFXJSE_Context* pVariableContext = it->second.get(); + std::unique_ptr pObject = pVariableContext->GetGlobalObject(); + auto hVariableValue = pdfium::MakeUnique(GetIsolate()); + if (!bGetter) { + pObject->SetObjectOwnProperty(szPropName, pValue); + return true; + } + if (pObject->HasObjectOwnProperty(szPropName, false)) { + pObject->GetObjectProperty(szPropName, hVariableValue.get()); + if (hVariableValue->IsFunction()) + pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); + else if (bGetter) + pValue->Assign(hVariableValue.get()); + else + hVariableValue.get()->Assign(pValue); + return true; + } + return false; +} + +void CFXJSE_Engine::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { + static const ByteStringView OBJ_NAME[2] = {"Number", "Date"}; + std::unique_ptr pObject = pContext->GetGlobalObject(); + auto hProp = pdfium::MakeUnique(GetIsolate()); + for (int i = 0; i < 2; ++i) { + if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) + pObject->DeleteObjectProperty(OBJ_NAME[i]); + } +} + +CFXJSE_Class* CFXJSE_Engine::GetJseNormalClass() { + return m_pJsClass; +} + +bool CFXJSE_Engine::ResolveObjects(CXFA_Object* refObject, + const WideStringView& wsExpression, + XFA_RESOLVENODE_RS* resolveNodeRS, + uint32_t dwStyles, + CXFA_Node* bindNode) { + if (wsExpression.IsEmpty()) + return false; + + if (m_eScriptType != CXFA_Script::Type::Formcalc || + (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { + m_upObjectArray.clear(); + } + if (refObject && refObject->IsNode() && + (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { + m_upObjectArray.push_back(refObject->AsNode()); + } + + bool bNextCreate = false; + if (dwStyles & XFA_RESOLVENODE_CreateNode) + m_ResolveProcessor->GetNodeHelper()->SetCreateNodeType(bindNode); + + m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = nullptr; + m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1; + + CFXJSE_ResolveNodeData rndFind(this); + int32_t nStart = 0; + int32_t nLevel = 0; + + std::vector findObjects; + findObjects.push_back(refObject ? refObject : m_pDocument->GetRoot()); + int32_t nNodes = 0; + while (true) { + nNodes = pdfium::CollectionSize(findObjects); + int32_t i = 0; + rndFind.m_dwStyles = dwStyles; + m_ResolveProcessor->SetCurStart(nStart); + nStart = m_ResolveProcessor->GetFilter(wsExpression, nStart, rndFind); + if (nStart < 1) { + if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) { + CXFA_Node* pDataNode = nullptr; + nStart = m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart; + if (nStart != -1) { + pDataNode = m_pDocument->GetNotBindNode(findObjects); + if (pDataNode) { + findObjects.clear(); + findObjects.push_back(pDataNode); + break; + } + } else { + pDataNode = findObjects.front()->AsNode(); + findObjects.clear(); + findObjects.push_back(pDataNode); + break; + } + dwStyles |= XFA_RESOLVENODE_Bind; + findObjects.clear(); + findObjects.push_back( + m_ResolveProcessor->GetNodeHelper()->m_pAllStartParent); + continue; + } + break; + } + if (bNextCreate) { + bool bCreate = + m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( + rndFind.m_wsName, rndFind.m_wsCondition, + nStart == + pdfium::base::checked_cast(wsExpression.GetLength()), + this); + if (bCreate) + continue; + + break; + } + + std::vector retObjects; + while (i < nNodes) { + bool bDataBind = false; + if (((dwStyles & XFA_RESOLVENODE_Bind) || + (dwStyles & XFA_RESOLVENODE_CreateNode)) && + nNodes > 1) { + CFXJSE_ResolveNodeData rndBind(nullptr); + m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind); + m_ResolveProcessor->SetIndexDataBind(rndBind.m_wsCondition, i, nNodes); + bDataBind = true; + } + rndFind.m_CurObject = findObjects[i++]; + rndFind.m_nLevel = nLevel; + rndFind.m_dwFlag = XFA_ResolveNode_RSType_Nodes; + if (!m_ResolveProcessor->Resolve(rndFind)) + continue; + + if (rndFind.m_dwFlag == XFA_ResolveNode_RSType_Attribute && + rndFind.m_pScriptAttribute && + nStart < + pdfium::base::checked_cast(wsExpression.GetLength())) { + auto pValue = pdfium::MakeUnique(GetIsolate()); + CJX_Object* jsObject = rndFind.m_Objects.front()->JSObject(); + (jsObject->*(rndFind.m_pScriptAttribute->callback))( + pValue.get(), false, rndFind.m_pScriptAttribute->attribute); + rndFind.m_Objects.front() = ToObject(pValue.get(), nullptr); + } + if (!m_upObjectArray.empty()) + m_upObjectArray.pop_back(); + retObjects.insert(retObjects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + rndFind.m_Objects.clear(); + if (bDataBind) + break; + } + findObjects.clear(); + + nNodes = pdfium::CollectionSize(retObjects); + if (nNodes < 1) { + if (dwStyles & XFA_RESOLVENODE_CreateNode) { + bNextCreate = true; + if (!m_ResolveProcessor->GetNodeHelper()->m_pCreateParent) { + m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = + ToNode(rndFind.m_CurObject); + m_ResolveProcessor->GetNodeHelper()->m_iCreateCount = 1; + } + bool bCreate = + m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( + rndFind.m_wsName, rndFind.m_wsCondition, + nStart == pdfium::base::checked_cast( + wsExpression.GetLength()), + this); + if (bCreate) + continue; + } + break; + } + + findObjects = + std::vector(retObjects.begin(), retObjects.end()); + rndFind.m_Objects.clear(); + if (nLevel == 0) + dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); + + nLevel++; + } + + if (!bNextCreate) { + resolveNodeRS->dwFlags = rndFind.m_dwFlag; + if (nNodes > 0) { + resolveNodeRS->objects.insert(resolveNodeRS->objects.end(), + findObjects.begin(), findObjects.end()); + } + if (rndFind.m_dwFlag == XFA_ResolveNode_RSType_Attribute) { + resolveNodeRS->pScriptAttribute = rndFind.m_pScriptAttribute; + return 1; + } + } + if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind | + XFA_RESOLVENODE_BindNew)) { + CXFA_NodeHelper* helper = m_ResolveProcessor->GetNodeHelper(); + if (helper->m_pCreateParent) + resolveNodeRS->objects.push_back(helper->m_pCreateParent); + else + helper->CreateNode_ForCondition(rndFind.m_wsCondition); + + resolveNodeRS->dwFlags = helper->m_iCreateFlag; + if (resolveNodeRS->dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) { + if (helper->m_iCurAllStart != -1) + resolveNodeRS->dwFlags = XFA_ResolveNode_RSType_CreateNodeMidAll; + } + + if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) + resolveNodeRS->dwFlags = XFA_ResolveNode_RSType_ExistNodes; + + return !resolveNodeRS->objects.empty(); + } + return nNodes > 0; +} + +void CFXJSE_Engine::AddToCacheList(std::unique_ptr pList) { + m_CacheList.push_back(std::move(pList)); +} + +CFXJSE_Value* CFXJSE_Engine::GetJSValueFromMap(CXFA_Object* pObject) { + if (!pObject) + return nullptr; + if (pObject->IsNode()) + RunVariablesScript(pObject->AsNode()); + + auto iter = m_mapObjectToValue.find(pObject); + if (iter != m_mapObjectToValue.end()) + return iter->second.get(); + + auto jsValue = pdfium::MakeUnique(GetIsolate()); + jsValue->SetObject(pObject, m_pJsClass); + + CFXJSE_Value* pValue = jsValue.get(); + m_mapObjectToValue.insert(std::make_pair(pObject, std::move(jsValue))); + return pValue; +} + +int32_t CFXJSE_Engine::GetIndexByName(CXFA_Node* refNode) { + CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); + return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, + lpNodeHelper->NodeIsProperty(refNode), false); +} + +int32_t CFXJSE_Engine::GetIndexByClassName(CXFA_Node* refNode) { + CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); + return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, + lpNodeHelper->NodeIsProperty(refNode), true); +} + +WideString CFXJSE_Engine::GetSomExpression(CXFA_Node* refNode) { + CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); + return lpNodeHelper->GetNameExpression(refNode, true, XFA_LOGIC_Transparent); +} + +void CFXJSE_Engine::SetNodesOfRunScript(std::vector* pArray) { + m_pScriptNodeArray = pArray; +} + +void CFXJSE_Engine::AddNodesOfRunScript(CXFA_Node* pNode) { + if (m_pScriptNodeArray && !pdfium::ContainsValue(*m_pScriptNodeArray, pNode)) + m_pScriptNodeArray->push_back(pNode); +} diff --git a/fxjs/cfxjse_engine.h b/fxjs/cfxjse_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..0b360bdbb224cc70d2b6a3d940200a16665c7707 --- /dev/null +++ b/fxjs/cfxjse_engine.h @@ -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 + +#ifndef FXJS_CFXJSE_ENGINE_H_ +#define FXJS_CFXJSE_ENGINE_H_ + +#include +#include +#include + +#include "fxjs/cfxjse_formcalc_context.h" +#include "fxjs/cjs_v8.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +#define XFA_RESOLVENODE_TagName 0x0002 + +class CXFA_List; +class CFXJSE_ResolveProcessor; + +class CFXJSE_Engine : public CJS_V8 { + public: + static CXFA_Object* ToObject(const v8::FunctionCallbackInfo& info); + static CXFA_Object* ToObject(CFXJSE_Value* pValue, CFXJSE_Class* pClass); + static void GlobalPropertyGetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + CFXJSE_Value* pValue); + static void GlobalPropertySetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + CFXJSE_Value* pValue); + static void NormalPropertyGetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + CFXJSE_Value* pValue); + static void NormalPropertySetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + CFXJSE_Value* pValue); + static CJS_Return NormalMethodCall( + const v8::FunctionCallbackInfo& info, + const WideString& functionName); + static int32_t NormalPropTypeGetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + bool bQueryIn); + static int32_t GlobalPropTypeGetter(CFXJSE_Value* pObject, + const ByteStringView& szPropName, + bool bQueryIn); + + explicit CFXJSE_Engine(CXFA_Document* pDocument, v8::Isolate* pIsolate); + ~CFXJSE_Engine() override; + + void SetEventParam(CXFA_EventParam param) { m_eventParam = param; } + CXFA_EventParam* GetEventParam() { return &m_eventParam; } + bool RunScript(CXFA_Script::Type eScriptType, + const WideStringView& wsScript, + CFXJSE_Value* pRetValue, + CXFA_Object* pThisObject); + + bool ResolveObjects(CXFA_Object* refObject, + const WideStringView& wsExpression, + XFA_RESOLVENODE_RS* resolveNodeRS, + uint32_t dwStyles, + CXFA_Node* bindNode); + CFXJSE_Value* GetJSValueFromMap(CXFA_Object* pObject); + void AddToCacheList(std::unique_ptr pList); + CXFA_Object* GetThisObject() const { return m_pThisObject; } + + int32_t GetIndexByName(CXFA_Node* refNode); + int32_t GetIndexByClassName(CXFA_Node* refNode); + WideString GetSomExpression(CXFA_Node* refNode); + + void SetNodesOfRunScript(std::vector* pArray); + void AddNodesOfRunScript(CXFA_Node* pNode); + CFXJSE_Class* GetJseNormalClass(); + + void SetRunAtType(XFA_AttributeEnum eRunAt) { m_eRunAtType = eRunAt; } + bool IsRunAtClient() { return m_eRunAtType != XFA_AttributeEnum::Server; } + + CXFA_Script::Type GetType(); + std::vector* GetUpObjectArray() { return &m_upObjectArray; } + CXFA_Document* GetDocument() const { return m_pDocument.Get(); } + + private: + CFXJSE_Context* CreateVariablesContext(CXFA_Node* pScriptNode, + CXFA_Node* pSubform); + void RemoveBuiltInObjs(CFXJSE_Context* pContext) const; + bool QueryNodeByFlag(CXFA_Node* refNode, + const WideStringView& propname, + CFXJSE_Value* pValue, + uint32_t dwFlag, + bool bSetting); + bool IsStrictScopeInJavaScript(); + CXFA_Object* GetVariablesThis(CXFA_Object* pObject, bool bScriptNode = false); + bool QueryVariableValue(CXFA_Node* pScriptNode, + const ByteStringView& szPropName, + CFXJSE_Value* pValue, + bool bGetter); + bool RunVariablesScript(CXFA_Node* pScriptNode); + + UnownedPtr const m_pDocument; + std::unique_ptr m_JsContext; + CFXJSE_Class* m_pJsClass; + CXFA_Script::Type m_eScriptType; + std::map> m_mapObjectToValue; + std::map> + m_mapVariableToContext; + CXFA_EventParam m_eventParam; + std::vector m_upObjectArray; + // CacheList holds the List items so we can clean them up when we're done. + std::vector> m_CacheList; + std::vector* m_pScriptNodeArray; + std::unique_ptr m_ResolveProcessor; + std::unique_ptr m_FM2JSContext; + CXFA_Object* m_pThisObject; + XFA_AttributeEnum m_eRunAtType; +}; + +#endif // FXJS_CFXJSE_ENGINE_H_ diff --git a/fxjs/cfxjse_formcalc_context.cpp b/fxjs/cfxjse_formcalc_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c46b9a68dcaabe6490905a856ed32f9a35b8be40 --- /dev/null +++ b/fxjs/cfxjse_formcalc_context.cpp @@ -0,0 +1,6254 @@ +// 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 "fxjs/cfxjse_formcalc_context.h" + +#include + +#include +#include +#include + +#include "core/fxcrt/cfx_decimal.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_random.h" +#include "fxjs/cfxjse_class.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" +#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_timezoneprovider.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +const double kFinancialPrecision = 0.00000001; + +struct XFA_FMHtmlReserveCode { + uint32_t m_uCode; + const wchar_t* m_htmlReserve; +}; + +// Sorted by m_htmlReserve +XFA_FMHtmlReserveCode reservesForDecode[] = { + {198, L"AElig"}, {193, L"Aacute"}, {194, L"Acirc"}, + {192, L"Agrave"}, {913, L"Alpha"}, {197, L"Aring"}, + {195, L"Atilde"}, {196, L"Auml"}, {914, L"Beta"}, + {199, L"Ccedil"}, {935, L"Chi"}, {8225, L"Dagger"}, + {916, L"Delta"}, {208, L"ETH"}, {201, L"Eacute"}, + {202, L"Ecirc"}, {200, L"Egrave"}, {917, L"Epsilon"}, + {919, L"Eta"}, {203, L"Euml"}, {915, L"Gamma"}, + {922, L"Kappa"}, {923, L"Lambda"}, {924, L"Mu"}, + {209, L"Ntilde"}, {925, L"Nu"}, {338, L"OElig"}, + {211, L"Oacute"}, {212, L"Ocirc"}, {210, L"Ograve"}, + {937, L"Omega"}, {927, L"Omicron"}, {216, L"Oslash"}, + {213, L"Otilde"}, {214, L"Ouml"}, {934, L"Phi"}, + {928, L"Pi"}, {936, L"Psi"}, {929, L"Rho"}, + {352, L"Scaron"}, {931, L"Sigma"}, {222, L"THORN"}, + {932, L"Tau"}, {920, L"Theta"}, {218, L"Uacute"}, + {219, L"Ucirc"}, {217, L"Ugrave"}, {933, L"Upsilon"}, + {220, L"Uuml"}, {926, L"Xi"}, {221, L"Yacute"}, + {376, L"Yuml"}, {918, L"Zeta"}, {225, L"aacute"}, + {226, L"acirc"}, {180, L"acute"}, {230, L"aelig"}, + {224, L"agrave"}, {8501, L"alefsym"}, {945, L"alpha"}, + {38, L"amp"}, {8743, L"and"}, {8736, L"ang"}, + {39, L"apos"}, {229, L"aring"}, {8776, L"asymp"}, + {227, L"atilde"}, {228, L"auml"}, {8222, L"bdquo"}, + {946, L"beta"}, {166, L"brvbar"}, {8226, L"bull"}, + {8745, L"cap"}, {231, L"ccedil"}, {184, L"cedil"}, + {162, L"cent"}, {967, L"chi"}, {710, L"circ"}, + {9827, L"clubs"}, {8773, L"cong"}, {169, L"copy"}, + {8629, L"crarr"}, {8746, L"cup"}, {164, L"current"}, + {8659, L"dArr"}, {8224, L"dagger"}, {8595, L"darr"}, + {176, L"deg"}, {948, L"delta"}, {9830, L"diams"}, + {247, L"divide"}, {233, L"eacute"}, {234, L"ecirc"}, + {232, L"egrave"}, {8709, L"empty"}, {8195, L"emsp"}, + {8194, L"ensp"}, {949, L"epsilon"}, {8801, L"equiv"}, + {951, L"eta"}, {240, L"eth"}, {235, L"euml"}, + {8364, L"euro"}, {8707, L"exist"}, {402, L"fnof"}, + {8704, L"forall"}, {189, L"frac12"}, {188, L"frac14"}, + {190, L"frac34"}, {8260, L"frasl"}, {947, L"gamma"}, + {8805, L"ge"}, {62, L"gt"}, {8660, L"hArr"}, + {8596, L"harr"}, {9829, L"hearts"}, {8230, L"hellip"}, + {237, L"iacute"}, {238, L"icirc"}, {161, L"iexcl"}, + {236, L"igrave"}, {8465, L"image"}, {8734, L"infin"}, + {8747, L"int"}, {953, L"iota"}, {191, L"iquest"}, + {8712, L"isin"}, {239, L"iuml"}, {954, L"kappa"}, + {8656, L"lArr"}, {205, L"lacute"}, {955, L"lambda"}, + {9001, L"lang"}, {171, L"laquo"}, {8592, L"larr"}, + {8968, L"lceil"}, {206, L"lcirc"}, {8220, L"ldquo"}, + {8804, L"le"}, {8970, L"lfloor"}, {204, L"lgrave"}, + {921, L"lota"}, {8727, L"lowast"}, {9674, L"loz"}, + {8206, L"lrm"}, {8249, L"lsaquo"}, {8216, L"lsquo"}, + {60, L"lt"}, {207, L"luml"}, {175, L"macr"}, + {8212, L"mdash"}, {181, L"micro"}, {183, L"middot"}, + {8722, L"minus"}, {956, L"mu"}, {8711, L"nabla"}, + {160, L"nbsp"}, {8211, L"ndash"}, {8800, L"ne"}, + {8715, L"ni"}, {172, L"not"}, {8713, L"notin"}, + {8836, L"nsub"}, {241, L"ntilde"}, {957, L"nu"}, + {243, L"oacute"}, {244, L"ocirc"}, {339, L"oelig"}, + {242, L"ograve"}, {8254, L"oline"}, {969, L"omega"}, + {959, L"omicron"}, {8853, L"oplus"}, {8744, L"or"}, + {170, L"ordf"}, {186, L"ordm"}, {248, L"oslash"}, + {245, L"otilde"}, {8855, L"otimes"}, {246, L"ouml"}, + {182, L"para"}, {8706, L"part"}, {8240, L"permil"}, + {8869, L"perp"}, {966, L"phi"}, {960, L"pi"}, + {982, L"piv"}, {177, L"plusmn"}, {8242, L"prime"}, + {8719, L"prod"}, {8733, L"prop"}, {968, L"psi"}, + {163, L"pund"}, {34, L"quot"}, {8658, L"rArr"}, + {8730, L"radic"}, {9002, L"rang"}, {187, L"raquo"}, + {8594, L"rarr"}, {8969, L"rceil"}, {8476, L"real"}, + {174, L"reg"}, {8971, L"rfloor"}, {961, L"rho"}, + {8207, L"rlm"}, {8250, L"rsaquo"}, {8217, L"rsquo"}, + {353, L"saron"}, {8218, L"sbquo"}, {8901, L"sdot"}, + {167, L"sect"}, {173, L"shy"}, {963, L"sigma"}, + {962, L"sigmaf"}, {8764, L"sim"}, {9824, L"spades"}, + {8834, L"sub"}, {8838, L"sube"}, {8721, L"sum"}, + {8835, L"sup"}, {185, L"sup1"}, {178, L"sup2"}, + {179, L"sup3"}, {8839, L"supe"}, {223, L"szlig"}, + {964, L"tau"}, {8221, L"tdquo"}, {8756, L"there4"}, + {952, L"theta"}, {977, L"thetasym"}, {8201, L"thinsp"}, + {254, L"thorn"}, {732, L"tilde"}, {215, L"times"}, + {8482, L"trade"}, {8657, L"uArr"}, {250, L"uacute"}, + {8593, L"uarr"}, {251, L"ucirc"}, {249, L"ugrave"}, + {168, L"uml"}, {978, L"upsih"}, {965, L"upsilon"}, + {252, L"uuml"}, {8472, L"weierp"}, {958, L"xi"}, + {253, L"yacute"}, {165, L"yen"}, {255, L"yuml"}, + {950, L"zeta"}, {8205, L"zwj"}, {8204, L"zwnj"}, +}; + +// Sorted by m_uCode +const XFA_FMHtmlReserveCode reservesForEncode[] = { + {34, L"quot"}, {38, L"amp"}, {39, L"apos"}, + {60, L"lt"}, {62, L"gt"}, {160, L"nbsp"}, + {161, L"iexcl"}, {162, L"cent"}, {163, L"pund"}, + {164, L"current"}, {165, L"yen"}, {166, L"brvbar"}, + {167, L"sect"}, {168, L"uml"}, {169, L"copy"}, + {170, L"ordf"}, {171, L"laquo"}, {172, L"not"}, + {173, L"shy"}, {174, L"reg"}, {175, L"macr"}, + {176, L"deg"}, {177, L"plusmn"}, {178, L"sup2"}, + {179, L"sup3"}, {180, L"acute"}, {181, L"micro"}, + {182, L"para"}, {183, L"middot"}, {184, L"cedil"}, + {185, L"sup1"}, {186, L"ordm"}, {187, L"raquo"}, + {188, L"frac14"}, {189, L"frac12"}, {190, L"frac34"}, + {191, L"iquest"}, {192, L"Agrave"}, {193, L"Aacute"}, + {194, L"Acirc"}, {195, L"Atilde"}, {196, L"Auml"}, + {197, L"Aring"}, {198, L"AElig"}, {199, L"Ccedil"}, + {200, L"Egrave"}, {201, L"Eacute"}, {202, L"Ecirc"}, + {203, L"Euml"}, {204, L"lgrave"}, {205, L"lacute"}, + {206, L"lcirc"}, {207, L"luml"}, {208, L"ETH"}, + {209, L"Ntilde"}, {210, L"Ograve"}, {211, L"Oacute"}, + {212, L"Ocirc"}, {213, L"Otilde"}, {214, L"Ouml"}, + {215, L"times"}, {216, L"Oslash"}, {217, L"Ugrave"}, + {218, L"Uacute"}, {219, L"Ucirc"}, {220, L"Uuml"}, + {221, L"Yacute"}, {222, L"THORN"}, {223, L"szlig"}, + {224, L"agrave"}, {225, L"aacute"}, {226, L"acirc"}, + {227, L"atilde"}, {228, L"auml"}, {229, L"aring"}, + {230, L"aelig"}, {231, L"ccedil"}, {232, L"egrave"}, + {233, L"eacute"}, {234, L"ecirc"}, {235, L"euml"}, + {236, L"igrave"}, {237, L"iacute"}, {238, L"icirc"}, + {239, L"iuml"}, {240, L"eth"}, {241, L"ntilde"}, + {242, L"ograve"}, {243, L"oacute"}, {244, L"ocirc"}, + {245, L"otilde"}, {246, L"ouml"}, {247, L"divide"}, + {248, L"oslash"}, {249, L"ugrave"}, {250, L"uacute"}, + {251, L"ucirc"}, {252, L"uuml"}, {253, L"yacute"}, + {254, L"thorn"}, {255, L"yuml"}, {338, L"OElig"}, + {339, L"oelig"}, {352, L"Scaron"}, {353, L"saron"}, + {376, L"Yuml"}, {402, L"fnof"}, {710, L"circ"}, + {732, L"tilde"}, {913, L"Alpha"}, {914, L"Beta"}, + {915, L"Gamma"}, {916, L"Delta"}, {917, L"Epsilon"}, + {918, L"Zeta"}, {919, L"Eta"}, {920, L"Theta"}, + {921, L"lota"}, {922, L"Kappa"}, {923, L"Lambda"}, + {924, L"Mu"}, {925, L"Nu"}, {926, L"Xi"}, + {927, L"Omicron"}, {928, L"Pi"}, {929, L"Rho"}, + {931, L"Sigma"}, {932, L"Tau"}, {933, L"Upsilon"}, + {934, L"Phi"}, {935, L"Chi"}, {936, L"Psi"}, + {937, L"Omega"}, {945, L"alpha"}, {946, L"beta"}, + {947, L"gamma"}, {948, L"delta"}, {949, L"epsilon"}, + {950, L"zeta"}, {951, L"eta"}, {952, L"theta"}, + {953, L"iota"}, {954, L"kappa"}, {955, L"lambda"}, + {956, L"mu"}, {957, L"nu"}, {958, L"xi"}, + {959, L"omicron"}, {960, L"pi"}, {961, L"rho"}, + {962, L"sigmaf"}, {963, L"sigma"}, {964, L"tau"}, + {965, L"upsilon"}, {966, L"phi"}, {967, L"chi"}, + {968, L"psi"}, {969, L"omega"}, {977, L"thetasym"}, + {978, L"upsih"}, {982, L"piv"}, {8194, L"ensp"}, + {8195, L"emsp"}, {8201, L"thinsp"}, {8204, L"zwnj"}, + {8205, L"zwj"}, {8206, L"lrm"}, {8207, L"rlm"}, + {8211, L"ndash"}, {8212, L"mdash"}, {8216, L"lsquo"}, + {8217, L"rsquo"}, {8218, L"sbquo"}, {8220, L"ldquo"}, + {8221, L"tdquo"}, {8222, L"bdquo"}, {8224, L"dagger"}, + {8225, L"Dagger"}, {8226, L"bull"}, {8230, L"hellip"}, + {8240, L"permil"}, {8242, L"prime"}, {8249, L"lsaquo"}, + {8250, L"rsaquo"}, {8254, L"oline"}, {8260, L"frasl"}, + {8364, L"euro"}, {8465, L"image"}, {8472, L"weierp"}, + {8476, L"real"}, {8482, L"trade"}, {8501, L"alefsym"}, + {8592, L"larr"}, {8593, L"uarr"}, {8594, L"rarr"}, + {8595, L"darr"}, {8596, L"harr"}, {8629, L"crarr"}, + {8656, L"lArr"}, {8657, L"uArr"}, {8658, L"rArr"}, + {8659, L"dArr"}, {8660, L"hArr"}, {8704, L"forall"}, + {8706, L"part"}, {8707, L"exist"}, {8709, L"empty"}, + {8711, L"nabla"}, {8712, L"isin"}, {8713, L"notin"}, + {8715, L"ni"}, {8719, L"prod"}, {8721, L"sum"}, + {8722, L"minus"}, {8727, L"lowast"}, {8730, L"radic"}, + {8733, L"prop"}, {8734, L"infin"}, {8736, L"ang"}, + {8743, L"and"}, {8744, L"or"}, {8745, L"cap"}, + {8746, L"cup"}, {8747, L"int"}, {8756, L"there4"}, + {8764, L"sim"}, {8773, L"cong"}, {8776, L"asymp"}, + {8800, L"ne"}, {8801, L"equiv"}, {8804, L"le"}, + {8805, L"ge"}, {8834, L"sub"}, {8835, L"sup"}, + {8836, L"nsub"}, {8838, L"sube"}, {8839, L"supe"}, + {8853, L"oplus"}, {8855, L"otimes"}, {8869, L"perp"}, + {8901, L"sdot"}, {8968, L"lceil"}, {8969, L"rceil"}, + {8970, L"lfloor"}, {8971, L"rfloor"}, {9001, L"lang"}, + {9002, L"rang"}, {9674, L"loz"}, {9824, L"spades"}, + {9827, L"clubs"}, {9829, L"hearts"}, {9830, L"diams"}, +}; + +const FXJSE_FUNCTION_DESCRIPTOR formcalc_fm2js_functions[] = { + {"Abs", CFXJSE_FormCalcContext::Abs}, + {"Avg", CFXJSE_FormCalcContext::Avg}, + {"Ceil", CFXJSE_FormCalcContext::Ceil}, + {"Count", CFXJSE_FormCalcContext::Count}, + {"Floor", CFXJSE_FormCalcContext::Floor}, + {"Max", CFXJSE_FormCalcContext::Max}, + {"Min", CFXJSE_FormCalcContext::Min}, + {"Mod", CFXJSE_FormCalcContext::Mod}, + {"Round", CFXJSE_FormCalcContext::Round}, + {"Sum", CFXJSE_FormCalcContext::Sum}, + {"Date", CFXJSE_FormCalcContext::Date}, + {"Date2Num", CFXJSE_FormCalcContext::Date2Num}, + {"DateFmt", CFXJSE_FormCalcContext::DateFmt}, + {"IsoDate2Num", CFXJSE_FormCalcContext::IsoDate2Num}, + {"IsoTime2Num", CFXJSE_FormCalcContext::IsoTime2Num}, + {"LocalDateFmt", CFXJSE_FormCalcContext::LocalDateFmt}, + {"LocalTimeFmt", CFXJSE_FormCalcContext::LocalTimeFmt}, + {"Num2Date", CFXJSE_FormCalcContext::Num2Date}, + {"Num2GMTime", CFXJSE_FormCalcContext::Num2GMTime}, + {"Num2Time", CFXJSE_FormCalcContext::Num2Time}, + {"Time", CFXJSE_FormCalcContext::Time}, + {"Time2Num", CFXJSE_FormCalcContext::Time2Num}, + {"TimeFmt", CFXJSE_FormCalcContext::TimeFmt}, + {"Apr", CFXJSE_FormCalcContext::Apr}, + {"Cterm", CFXJSE_FormCalcContext::CTerm}, + {"FV", CFXJSE_FormCalcContext::FV}, + {"Ipmt", CFXJSE_FormCalcContext::IPmt}, + {"NPV", CFXJSE_FormCalcContext::NPV}, + {"Pmt", CFXJSE_FormCalcContext::Pmt}, + {"PPmt", CFXJSE_FormCalcContext::PPmt}, + {"PV", CFXJSE_FormCalcContext::PV}, + {"Rate", CFXJSE_FormCalcContext::Rate}, + {"Term", CFXJSE_FormCalcContext::Term}, + {"Choose", CFXJSE_FormCalcContext::Choose}, + {"Exists", CFXJSE_FormCalcContext::Exists}, + {"HasValue", CFXJSE_FormCalcContext::HasValue}, + {"Oneof", CFXJSE_FormCalcContext::Oneof}, + {"Within", CFXJSE_FormCalcContext::Within}, + {"If", CFXJSE_FormCalcContext::If}, + {"Eval", CFXJSE_FormCalcContext::Eval}, + {"Translate", CFXJSE_FormCalcContext::eval_translation}, + {"Ref", CFXJSE_FormCalcContext::Ref}, + {"UnitType", CFXJSE_FormCalcContext::UnitType}, + {"UnitValue", CFXJSE_FormCalcContext::UnitValue}, + {"At", CFXJSE_FormCalcContext::At}, + {"Concat", CFXJSE_FormCalcContext::Concat}, + {"Decode", CFXJSE_FormCalcContext::Decode}, + {"Encode", CFXJSE_FormCalcContext::Encode}, + {"Format", CFXJSE_FormCalcContext::Format}, + {"Left", CFXJSE_FormCalcContext::Left}, + {"Len", CFXJSE_FormCalcContext::Len}, + {"Lower", CFXJSE_FormCalcContext::Lower}, + {"Ltrim", CFXJSE_FormCalcContext::Ltrim}, + {"Parse", CFXJSE_FormCalcContext::Parse}, + {"Replace", CFXJSE_FormCalcContext::Replace}, + {"Right", CFXJSE_FormCalcContext::Right}, + {"Rtrim", CFXJSE_FormCalcContext::Rtrim}, + {"Space", CFXJSE_FormCalcContext::Space}, + {"Str", CFXJSE_FormCalcContext::Str}, + {"Stuff", CFXJSE_FormCalcContext::Stuff}, + {"Substr", CFXJSE_FormCalcContext::Substr}, + {"Uuid", CFXJSE_FormCalcContext::Uuid}, + {"Upper", CFXJSE_FormCalcContext::Upper}, + {"WordNum", CFXJSE_FormCalcContext::WordNum}, + {"Get", CFXJSE_FormCalcContext::Get}, + {"Post", CFXJSE_FormCalcContext::Post}, + {"Put", CFXJSE_FormCalcContext::Put}, + {"pos_op", CFXJSE_FormCalcContext::positive_operator}, + {"neg_op", CFXJSE_FormCalcContext::negative_operator}, + {"log_or_op", CFXJSE_FormCalcContext::logical_or_operator}, + {"log_and_op", CFXJSE_FormCalcContext::logical_and_operator}, + {"log_not_op", CFXJSE_FormCalcContext::logical_not_operator}, + {"eq_op", CFXJSE_FormCalcContext::equality_operator}, + {"neq_op", CFXJSE_FormCalcContext::notequality_operator}, + {"lt_op", CFXJSE_FormCalcContext::less_operator}, + {"le_op", CFXJSE_FormCalcContext::lessequal_operator}, + {"gt_op", CFXJSE_FormCalcContext::greater_operator}, + {"ge_op", CFXJSE_FormCalcContext::greaterequal_operator}, + {"plus_op", CFXJSE_FormCalcContext::plus_operator}, + {"minus_op", CFXJSE_FormCalcContext::minus_operator}, + {"mul_op", CFXJSE_FormCalcContext::multiple_operator}, + {"div_op", CFXJSE_FormCalcContext::divide_operator}, + {"asgn_val_op", CFXJSE_FormCalcContext::assign_value_operator}, + {"dot_acc", CFXJSE_FormCalcContext::dot_accessor}, + {"dotdot_acc", CFXJSE_FormCalcContext::dotdot_accessor}, + {"concat_obj", CFXJSE_FormCalcContext::concat_fm_object}, + {"is_obj", CFXJSE_FormCalcContext::is_fm_object}, + {"is_ary", CFXJSE_FormCalcContext::is_fm_array}, + {"get_val", CFXJSE_FormCalcContext::get_fm_value}, + {"get_jsobj", CFXJSE_FormCalcContext::get_fm_jsobj}, + {"var_filter", CFXJSE_FormCalcContext::fm_var_filter}, +}; + +const FXJSE_CLASS_DESCRIPTOR formcalc_fm2js_descriptor = { + "XFA_FM2JS_FormCalcClass", // name + formcalc_fm2js_functions, // methods + FX_ArraySize(formcalc_fm2js_functions), // number of methods + nullptr, // dynamic prop type + nullptr, // dynamic prop getter + nullptr, // dynamic prop setter + nullptr, // dynamic prop method call +}; + +const uint8_t g_sAltTable_Date[] = { + 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255, + 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255, +}; +static_assert(FX_ArraySize(g_sAltTable_Date) == L'a' - L'A' + 1, + "Invalid g_sAltTable_Date size."); + +const uint8_t g_sAltTable_Time[] = { + 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255, + 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255, + 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255, +}; +static_assert(FX_ArraySize(g_sAltTable_Time) == L'a' - L'A' + 1, + "Invalid g_sAltTable_Time size."); + +void AlternateDateTimeSymbols(WideString& wsPattern, + const WideString& wsAltSymbols, + const uint8_t* pAltTable) { + int32_t nLength = wsPattern.GetLength(); + bool bInConstRange = false; + bool bEscape = false; + int32_t i = 0; + while (i < nLength) { + wchar_t wc = wsPattern[i]; + if (wc == L'\'') { + bInConstRange = !bInConstRange; + if (bEscape) { + i++; + } else { + wsPattern.Delete(i); + nLength--; + } + bEscape = !bEscape; + continue; + } + if (!bInConstRange && wc >= L'A' && wc <= L'a') { + uint8_t nAlt = pAltTable[wc - L'A']; + if (nAlt != 255) + wsPattern.SetAt(i, wsAltSymbols[nAlt]); + } + i++; + bEscape = false; + } +} + +bool PatternStringType(const ByteStringView& szPattern, uint32_t& patternType) { + WideString wsPattern = WideString::FromUTF8(szPattern); + if (L"datetime" == wsPattern.Left(8)) { + patternType = XFA_VT_DATETIME; + return true; + } + if (L"date" == wsPattern.Left(4)) { + auto pos = wsPattern.Find(L"time"); + patternType = + pos.has_value() && pos.value() != 0 ? XFA_VT_DATETIME : XFA_VT_DATE; + return true; + } + if (L"time" == wsPattern.Left(4)) { + patternType = XFA_VT_TIME; + return true; + } + if (L"text" == wsPattern.Left(4)) { + patternType = XFA_VT_TEXT; + return true; + } + if (L"num" == wsPattern.Left(3)) { + if (L"integer" == wsPattern.Mid(4, 7)) { + patternType = XFA_VT_INTEGER; + } else if (L"decimal" == wsPattern.Mid(4, 7)) { + patternType = XFA_VT_DECIMAL; + } else if (L"currency" == wsPattern.Mid(4, 8)) { + patternType = XFA_VT_FLOAT; + } else if (L"percent" == wsPattern.Mid(4, 7)) { + patternType = XFA_VT_FLOAT; + } else { + patternType = XFA_VT_FLOAT; + } + return true; + } + + patternType = XFA_VT_NULL; + wsPattern.MakeLower(); + const wchar_t* pData = wsPattern.c_str(); + int32_t iLength = wsPattern.GetLength(); + int32_t iIndex = 0; + bool bSingleQuotation = false; + wchar_t patternChar; + while (iIndex < iLength) { + patternChar = pData[iIndex]; + if (patternChar == 0x27) { + bSingleQuotation = !bSingleQuotation; + } else if (!bSingleQuotation && + (patternChar == 'y' || patternChar == 'j')) { + patternType = XFA_VT_DATE; + iIndex++; + wchar_t timePatternChar; + while (iIndex < iLength) { + timePatternChar = pData[iIndex]; + if (timePatternChar == 0x27) { + bSingleQuotation = !bSingleQuotation; + } else if (!bSingleQuotation && timePatternChar == 't') { + patternType = XFA_VT_DATETIME; + break; + } + iIndex++; + } + break; + } else if (!bSingleQuotation && + (patternChar == 'h' || patternChar == 'k')) { + patternType = XFA_VT_TIME; + break; + } else if (!bSingleQuotation && + (patternChar == 'a' || patternChar == 'x' || + patternChar == 'o' || patternChar == '0')) { + patternType = XFA_VT_TEXT; + if (patternChar == 'x' || patternChar == 'o' || patternChar == '0') { + break; + } + } else if (!bSingleQuotation && + (patternChar == 'z' || patternChar == 's' || + patternChar == 'e' || patternChar == 'v' || + patternChar == '8' || patternChar == ',' || + patternChar == '.' || patternChar == '$')) { + patternType = XFA_VT_FLOAT; + if (patternChar == 'v' || patternChar == '8' || patternChar == '$') { + break; + } + } + iIndex++; + } + if (patternType == XFA_VT_NULL) { + patternType = XFA_VT_TEXT | XFA_VT_FLOAT; + } + return false; +} + +CFXJSE_FormCalcContext* ToJSContext(CFXJSE_Value* pValue, + CFXJSE_Class* pClass) { + CFXJSE_HostObject* pHostObj = pValue->ToHostObject(pClass); + if (!pHostObj || pHostObj->type() != CFXJSE_HostObject::kFM2JS) + return nullptr; + return static_cast(pHostObj); +} + +bool IsWhitespace(char c) { + return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A || + c == 0x0D; +} + +IFX_Locale* LocaleFromString(CXFA_Document* pDoc, + CXFA_LocaleMgr* pMgr, + const ByteStringView& szLocale) { + if (!szLocale.IsEmpty()) + return pMgr->GetLocaleByName(WideString::FromUTF8(szLocale)); + + CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); + ASSERT(pThisNode); + return pThisNode->GetLocale(); +} + +WideString FormatFromString(IFX_Locale* pLocale, + const ByteStringView& szFormat) { + if (!szFormat.IsEmpty()) + return WideString::FromUTF8(szFormat); + + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default); +} + +FX_LOCALEDATETIMESUBCATEGORY SubCategoryFromInt(int32_t iStyle) { + switch (iStyle) { + case 1: + return FX_LOCALEDATETIMESUBCATEGORY_Short; + case 3: + return FX_LOCALEDATETIMESUBCATEGORY_Long; + case 4: + return FX_LOCALEDATETIMESUBCATEGORY_Full; + case 0: + case 2: + default: + return FX_LOCALEDATETIMESUBCATEGORY_Medium; + } +} + +bool IsPartOfNumber(char ch) { + return std::isdigit(ch) || ch == '-' || ch == '.'; +} + +bool IsPartOfNumberW(wchar_t ch) { + return std::iswdigit(ch) || ch == L'-' || ch == L'.'; +} + +ByteString GUIDString(bool bSeparator) { + uint8_t data[16]; + FX_Random_GenerateMT(reinterpret_cast(data), 4); + data[6] = (data[6] & 0x0F) | 0x40; + + ByteString bsStr; + char* pBuf = bsStr.GetBuffer(40); + for (int32_t i = 0; i < 16; ++i, pBuf += 2) { + if (bSeparator && (i == 4 || i == 6 || i == 8 || i == 10)) + *pBuf++ = L'-'; + + FXSYS_IntToTwoHexChars(data[i], pBuf); + } + bsStr.ReleaseBuffer(bSeparator ? 36 : 32); + return bsStr; +} + +double ByteStringToDouble(const ByteStringView& szStringVal) { + WideString wsValue = WideString::FromUTF8(szStringVal); + wsValue.Trim(); + + int32_t cc = 0; + bool bNegative = false; + + const wchar_t* str = wsValue.c_str(); + int32_t len = wsValue.GetLength(); + if (str[0] == '+') { + cc++; + } else if (str[0] == '-') { + bNegative = true; + cc++; + } + + int32_t nIntegralLen = 0; + int64_t nIntegral = 0; + while (cc < len) { + if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' || + nIntegralLen > 17) { + break; + } + if (!FXSYS_isDecimalDigit(str[cc])) { + return 0; + } + nIntegral = nIntegral * 10 + str[cc] - '0'; + cc++; + nIntegralLen++; + } + nIntegral = bNegative ? -nIntegral : nIntegral; + + int32_t scale = 0; + double fraction = 0.0; + uint32_t dwFractional = 0; + if (cc < len && str[cc] == '.') { + cc++; + while (cc < len) { + fraction += XFA_GetFractionalScale(scale) * (str[cc] - '0'); + scale++; + cc++; + if (cc == len) + break; + if (scale == XFA_GetMaxFractionalScale() || str[cc] == 'E' || + str[cc] == 'e') { + break; + } + if (!FXSYS_isDecimalDigit(str[cc])) + return 0; + } + dwFractional = static_cast(fraction * 4294967296.0); + } + + int32_t nExponent = 0; + bool bExpSign = false; + 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 (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) + return 0; + + nExponent = nExponent * 10 + str[cc] - '0'; + cc++; + } + nExponent = bExpSign ? -nExponent : nExponent; + } + + double dValue = dwFractional / 4294967296.0; + dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); + if (nExponent != 0) + dValue *= FXSYS_pow(10, static_cast(nExponent)); + + return dValue; +} + +} // namespace + +// static +void CFXJSE_FormCalcContext::Abs(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Abs"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + double dValue = ValueToDouble(pThis, argOne.get()); + if (dValue < 0) + dValue = -dValue; + + args.GetReturnValue()->SetDouble(dValue); +} + +// static +void CFXJSE_FormCalcContext::Avg(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1) { + args.GetReturnValue()->SetNull(); + return; + } + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + uint32_t uCount = 0; + double dSum = 0.0; + for (int32_t i = 0; i < argc; i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (!argValue->IsArray()) { + dSum += ValueToDouble(pThis, argValue.get()); + uCount++; + continue; + } + + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + + if (iLength > 2) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + auto defaultPropValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get()); + if (defaultPropValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, defaultPropValue.get()); + uCount++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, newPropertyValue.get()); + uCount++; + } + } + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dSum / uCount); +} + +// static +void CFXJSE_FormCalcContext::Ceil(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Ceil"); + return; + } + + std::unique_ptr argValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetFloat(ceil(ValueToFloat(pThis, argValue.get()))); +} + +// static +void CFXJSE_FormCalcContext::Count(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + int32_t iCount = 0; + for (int32_t i = 0; i < args.GetLength(); i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (!newPropertyValue->IsNull()) + iCount++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + iCount += newPropertyValue->IsNull() ? 0 : 1; + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (!newPropertyValue->IsNull()) + iCount++; + } else { + iCount++; + } + } + args.GetReturnValue()->SetInteger(iCount); +} + +// static +void CFXJSE_FormCalcContext::Floor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Floor"); + return; + } + + std::unique_ptr argValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetFloat(floor(ValueToFloat(pThis, argValue.get()))); +} + +// static +void CFXJSE_FormCalcContext::Max(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + uint32_t uCount = 0; + double dMaxValue = 0.0; + for (int32_t i = 0; i < args.GetLength(); i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } else { + uCount++; + double dValue = ValueToDouble(pThis, argValue.get()); + dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dMaxValue); +} + +// static +void CFXJSE_FormCalcContext::Min(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + uint32_t uCount = 0; + double dMinValue = 0.0; + for (int32_t i = 0; i < args.GetLength(); i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + uCount++; + double dValue = ValueToDouble(pThis, newPropertyValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } else { + uCount++; + double dValue = ValueToDouble(pThis, argValue.get()); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dMinValue); +} + +// static +void CFXJSE_FormCalcContext::Mod(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 2) { + pContext->ThrowParamCountMismatchException(L"Mod"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + std::unique_ptr argTwo = args.GetValue(1); + if (argOne->IsNull() || argTwo->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + bool argOneResult; + double dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult); + bool argTwoResult; + double dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult); + if (!argOneResult || !argTwoResult) { + pContext->ThrowArgumentMismatchException(); + return; + } + + if (dDivisor == 0.0) { + pContext->ThrowDivideByZeroException(); + return; + } + + args.GetReturnValue()->SetDouble(dDividend - + dDivisor * (int32_t)(dDividend / dDivisor)); +} + +// static +void CFXJSE_FormCalcContext::Round(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + pContext->ThrowParamCountMismatchException(L"Round"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + bool dValueRet; + double dValue = ExtractDouble(pThis, argOne.get(), &dValueRet); + if (!dValueRet) { + pContext->ThrowArgumentMismatchException(); + return; + } + + uint8_t uPrecision = 0; + if (argc > 1) { + std::unique_ptr argTwo = args.GetValue(1); + if (argTwo->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + bool dPrecisionRet; + double dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet); + if (!dPrecisionRet) { + pContext->ThrowArgumentMismatchException(); + return; + } + + uPrecision = static_cast(pdfium::clamp(dPrecision, 0.0, 12.0)); + } + + CFX_Decimal decimalValue(static_cast(dValue), uPrecision); + args.GetReturnValue()->SetDouble(decimalValue); +} + +// static +void CFXJSE_FormCalcContext::Sum(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + uint32_t uCount = 0; + double dSum = 0.0; + for (int32_t i = 0; i < argc; i++) { + std::unique_ptr argValue = args.GetValue(i); + if (argValue->IsNull()) + continue; + + if (argValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + argValue->GetObjectPropertyByIdx(1, propertyValue.get()); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, jsObjectValue.get()); + uCount++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, newPropertyValue.get()); + uCount++; + } + } + } else if (argValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); + if (newPropertyValue->IsNull()) + continue; + + dSum += ValueToDouble(pThis, argValue.get()); + uCount++; + } else { + dSum += ValueToDouble(pThis, argValue.get()); + uCount++; + } + } + if (uCount == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetDouble(dSum); +} + +// static +void CFXJSE_FormCalcContext::Date(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 0) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Date"); + return; + } + + time_t currentTime; + time(¤tTime); + struct tm* pTmStruct = gmtime(¤tTime); + + args.GetReturnValue()->SetInteger(DateString2Num( + ByteString::Format("%d%02d%02d", pTmStruct->tm_year + 1900, + pTmStruct->tm_mon + 1, pTmStruct->tm_mday) + .AsStringView())); +} + +// static +void CFXJSE_FormCalcContext::Date2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Date2Num"); + return; + } + + std::unique_ptr dateValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, dateValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString dateString = ValueToUTF8String(dateValue.get()); + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, formatValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + formatString = ValueToUTF8String(formatValue.get()); + } + + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, localValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + localString = ValueToUTF8String(localValue.get()); + } + + ByteString szIsoDateString = + Local2IsoDate(pThis, dateString.AsStringView(), + formatString.AsStringView(), localString.AsStringView()); + args.GetReturnValue()->SetInteger( + DateString2Num(szIsoDateString.AsStringView())); +} + +// static +void CFXJSE_FormCalcContext::DateFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Date2Num"); + return; + } + + int32_t iStyle = 0; + if (argc > 0) { + std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); + if (argStyle->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); + if (iStyle < 0 || iStyle > 4) + iStyle = 0; + } + + ByteString szLocal; + if (argc > 1) { + std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); + if (argLocal->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + szLocal = ValueToUTF8String(argLocal.get()); + } + + ByteString formatStr = + GetStandardDateFormat(pThis, iStyle, szLocal.AsStringView()); + args.GetReturnValue()->SetString(formatStr.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::IsoDate2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr) + ->ThrowParamCountMismatchException(L"IsoDate2Num"); + return; + } + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + ByteString szArgString = ValueToUTF8String(argOne.get()); + args.GetReturnValue()->SetInteger(DateString2Num(szArgString.AsStringView())); +} + +// static +void CFXJSE_FormCalcContext::IsoTime2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"IsoTime2Num"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + CXFA_Document* pDoc = pContext->GetDocument(); + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + ByteString szArgString = ValueToUTF8String(argOne.get()); + auto pos = szArgString.Find('T', 0); + if (!pos.has_value() || pos.value() == szArgString.GetLength() - 1) { + args.GetReturnValue()->SetInteger(0); + return; + } + szArgString = szArgString.Right(szArgString.GetLength() - (pos.value() + 1)); + + CXFA_LocaleValue timeValue( + XFA_VT_TIME, WideString::FromUTF8(szArgString.AsStringView()), pMgr); + if (!timeValue.IsValid()) { + args.GetReturnValue()->SetInteger(0); + return; + } + + CFX_DateTime uniTime = timeValue.GetTime(); + int32_t hour = uniTime.GetHour(); + int32_t min = uniTime.GetMinute(); + int32_t second = uniTime.GetSecond(); + int32_t milSecond = uniTime.GetMillisecond(); + + // TODO(dsinclair): See if there is other time conversion code in pdfium and + // consolidate. + int32_t mins = hour * 60 + min; + mins -= (pMgr->GetDefLocale()->GetTimeZone().tzHour * 60); + while (mins > 1440) + mins -= 1440; + while (mins < 0) + mins += 1440; + hour = mins / 60; + min = mins % 60; + + args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 + + second * 1000 + milSecond + 1); +} + +// static +void CFXJSE_FormCalcContext::LocalDateFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc > 2) { + ToJSContext(pThis, nullptr) + ->ThrowParamCountMismatchException(L"LocalDateFmt"); + return; + } + + int32_t iStyle = 0; + if (argc > 0) { + std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); + if (argStyle->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); + if (iStyle > 4 || iStyle < 0) + iStyle = 0; + } + + ByteString szLocal; + if (argc > 1) { + std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); + if (argLocal->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + szLocal = ValueToUTF8String(argLocal.get()); + } + + ByteString formatStr = + GetLocalDateFormat(pThis, iStyle, szLocal.AsStringView(), false); + args.GetReturnValue()->SetString(formatStr.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::LocalTimeFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc > 2) { + ToJSContext(pThis, nullptr) + ->ThrowParamCountMismatchException(L"LocalTimeFmt"); + return; + } + + int32_t iStyle = 0; + if (argc > 0) { + std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); + if (argStyle->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); + if (iStyle > 4 || iStyle < 0) + iStyle = 0; + } + + ByteString szLocal; + if (argc > 1) { + std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); + if (argLocal->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + szLocal = ValueToUTF8String(argLocal.get()); + } + + ByteString formatStr = + GetLocalTimeFormat(pThis, iStyle, szLocal.AsStringView(), false); + args.GetReturnValue()->SetString(formatStr.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Num2Date(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Num2Date"); + return; + } + + std::unique_ptr dateValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, dateValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + int32_t dDate = (int32_t)ValueToFloat(pThis, dateValue.get()); + if (dDate < 1) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, formatValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + formatString = ValueToUTF8String(formatValue.get()); + } + + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, localValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + localString = ValueToUTF8String(localValue.get()); + } + + int32_t iYear = 1900; + int32_t iMonth = 1; + int32_t iDay = 1; + int32_t i = 0; + while (dDate > 0) { + if (iMonth == 2) { + if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) { + if (dDate > 29) { + ++iMonth; + if (iMonth > 12) { + iMonth = 1; + ++i; + } + iDay = 1; + dDate -= 29; + } else { + iDay += static_cast(dDate) - 1; + dDate = 0; + } + } else { + if (dDate > 28) { + ++iMonth; + if (iMonth > 12) { + iMonth = 1; + ++i; + } + iDay = 1; + dDate -= 28; + } else { + iDay += static_cast(dDate) - 1; + dDate = 0; + } + } + } else if (iMonth < 8) { + if ((iMonth % 2 == 0)) { + if (dDate > 30) { + ++iMonth; + if (iMonth > 12) { + iMonth = 1; + ++i; + } + iDay = 1; + dDate -= 30; + } else { + iDay += static_cast(dDate) - 1; + dDate = 0; + } + } else { + if (dDate > 31) { + ++iMonth; + if (iMonth > 12) { + iMonth = 1; + ++i; + } + iDay = 1; + dDate -= 31; + } else { + iDay += static_cast(dDate) - 1; + dDate = 0; + } + } + } else { + if (iMonth % 2 != 0) { + if (dDate > 30) { + ++iMonth; + if (iMonth > 12) { + iMonth = 1; + ++i; + } + iDay = 1; + dDate -= 30; + } else { + iDay += static_cast(dDate) - 1; + dDate = 0; + } + } else { + if (dDate > 31) { + ++iMonth; + if (iMonth > 12) { + iMonth = 1; + ++i; + } + iDay = 1; + dDate -= 31; + } else { + iDay += static_cast(dDate) - 1; + dDate = 0; + } + } + } + } + + ByteString szLocalDateString = IsoDate2Local( + pThis, + ByteString::Format("%d%02d%02d", iYear + i, iMonth, iDay).AsStringView(), + formatString.AsStringView(), localString.AsStringView()); + args.GetReturnValue()->SetString(szLocalDateString.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Num2GMTime(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr) + ->ThrowParamCountMismatchException(L"Num2GMTime"); + return; + } + + std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); + if (timeValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get()); + if (abs(iTime) < 1.0) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (formatValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + formatString = ValueToUTF8String(formatValue.get()); + } + + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (localValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + localString = ValueToUTF8String(localValue.get()); + } + + ByteString szGMTTimeString = + Num2AllTime(pThis, iTime, formatString.AsStringView(), + localString.AsStringView(), true); + args.GetReturnValue()->SetString(szGMTTimeString.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Num2Time(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Num2Time"); + return; + } + + std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); + if (timeValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + float fTime = ValueToFloat(pThis, timeValue.get()); + if (fabs(fTime) < 1.0) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (formatValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + formatString = ValueToUTF8String(formatValue.get()); + } + + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (localValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + localString = ValueToUTF8String(localValue.get()); + } + + ByteString szLocalTimeString = Num2AllTime(pThis, static_cast(fTime), + formatString.AsStringView(), + localString.AsStringView(), false); + args.GetReturnValue()->SetString(szLocalTimeString.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Time(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 0) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Time"); + return; + } + + time_t now; + time(&now); + + struct tm* pGmt = gmtime(&now); + args.GetReturnValue()->SetInteger( + (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000); +} + +// static +void CFXJSE_FormCalcContext::Time2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Time2Num"); + return; + } + + ByteString timeString; + std::unique_ptr timeValue = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, timeValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + timeString = ValueToUTF8String(timeValue.get()); + + ByteString formatString; + if (argc > 1) { + std::unique_ptr formatValue = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, formatValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + formatString = ValueToUTF8String(formatValue.get()); + } + + ByteString localString; + if (argc > 2) { + std::unique_ptr localValue = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, localValue.get())) { + args.GetReturnValue()->SetNull(); + return; + } + localString = ValueToUTF8String(localValue.get()); + } + + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + IFX_Locale* pLocale = nullptr; + if (localString.IsEmpty()) { + CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); + ASSERT(pThisNode); + pLocale = pThisNode->GetLocale(); + } else { + pLocale = + pMgr->GetLocaleByName(WideString::FromUTF8(localString.AsStringView())); + } + + WideString wsFormat; + if (formatString.IsEmpty()) + wsFormat = pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default); + else + wsFormat = WideString::FromUTF8(formatString.AsStringView()); + + wsFormat = L"time{" + wsFormat + L"}"; + CXFA_LocaleValue localeValue(XFA_VT_TIME, + WideString::FromUTF8(timeString.AsStringView()), + wsFormat, pLocale, pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetInteger(0); + return; + } + + CFX_DateTime uniTime = localeValue.GetTime(); + int32_t hour = uniTime.GetHour(); + int32_t min = uniTime.GetMinute(); + int32_t second = uniTime.GetSecond(); + int32_t milSecond = uniTime.GetMillisecond(); + int32_t mins = hour * 60 + min; + + mins -= (CXFA_TimeZoneProvider().GetTimeZone().tzHour * 60); + while (mins > 1440) + mins -= 1440; + + while (mins < 0) + mins += 1440; + + hour = mins / 60; + min = mins % 60; + args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 + + second * 1000 + milSecond + 1); +} + +// static +void CFXJSE_FormCalcContext::TimeFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"TimeFmt"); + return; + } + + int32_t iStyle = 0; + if (argc > 0) { + std::unique_ptr argStyle = GetSimpleValue(pThis, args, 0); + if (argStyle->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); + if (iStyle > 4 || iStyle < 0) + iStyle = 0; + } + + ByteString szLocal; + if (argc > 1) { + std::unique_ptr argLocal = GetSimpleValue(pThis, args, 1); + if (argLocal->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + szLocal = ValueToUTF8String(argLocal.get()); + } + + ByteString formatStr = + GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringView()); + args.GetReturnValue()->SetString(formatStr.AsStringView()); +} + +// static +bool CFXJSE_FormCalcContext::IsIsoDateFormat(const char* pData, + int32_t iLength, + int32_t& iStyle, + int32_t& iYear, + int32_t& iMonth, + int32_t& iDay) { + iYear = 0; + iMonth = 1; + iDay = 1; + + if (iLength < 4) + return false; + + char strYear[5]; + strYear[4] = '\0'; + for (int32_t i = 0; i < 4; ++i) { + if (!std::isdigit(pData[i])) + return false; + + strYear[i] = pData[i]; + } + iYear = FXSYS_atoi(strYear); + iStyle = 0; + if (iLength == 4) + return true; + + iStyle = pData[4] == '-' ? 1 : 0; + + char strTemp[3]; + strTemp[2] = '\0'; + int32_t iPosOff = iStyle == 0 ? 4 : 5; + if (!std::isdigit(pData[iPosOff]) || !std::isdigit(pData[iPosOff + 1])) + return false; + + strTemp[0] = pData[iPosOff]; + strTemp[1] = pData[iPosOff + 1]; + iMonth = FXSYS_atoi(strTemp); + if (iMonth > 12 || iMonth < 1) + return false; + + if (iStyle == 0) { + iPosOff += 2; + if (iLength == 6) + return true; + } else { + iPosOff += 3; + if (iLength == 7) + return true; + } + if (!std::isdigit(pData[iPosOff]) || !std::isdigit(pData[iPosOff + 1])) + return false; + + strTemp[0] = pData[iPosOff]; + strTemp[1] = pData[iPosOff + 1]; + iDay = FXSYS_atoi(strTemp); + if (iPosOff + 2 < iLength) + return false; + + if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) { + if (iMonth == 2 && iDay > 29) + return false; + } else { + if (iMonth == 2 && iDay > 28) + return false; + } + if (iMonth != 2) { + if (iMonth < 8) { + if (iDay > (iMonth % 2 == 0 ? 30 : 31)) + return false; + } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) { + return false; + } + } + return true; +} + +// static +bool CFXJSE_FormCalcContext::IsIsoTimeFormat(const char* pData, + int32_t iLength, + int32_t& iHour, + int32_t& iMinute, + int32_t& iSecond, + int32_t& iMilliSecond, + int32_t& iZoneHour, + int32_t& iZoneMinute) { + iHour = 0; + iMinute = 0; + iSecond = 0; + iMilliSecond = 0; + iZoneHour = 0; + iZoneMinute = 0; + if (!pData) + return false; + + char strTemp[3]; + strTemp[2] = '\0'; + int32_t iZone = 0; + int32_t i = 0; + while (i < iLength) { + if (!std::isdigit(pData[i]) && pData[i] != ':') { + iZone = i; + break; + } + ++i; + } + if (i == iLength) + iZone = iLength; + + int32_t iPos = 0; + int32_t iIndex = 0; + while (iIndex < iZone) { + if (!std::isdigit(pData[iIndex])) + return false; + + strTemp[0] = pData[iIndex]; + if (!std::isdigit(pData[iIndex + 1])) + return false; + + strTemp[1] = pData[iIndex + 1]; + if (FXSYS_atoi(strTemp) > 60) + return false; + + if (pData[2] == ':') { + if (iPos == 0) { + iHour = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 1) { + iMinute = FXSYS_atoi(strTemp); + ++iPos; + } else { + iSecond = FXSYS_atoi(strTemp); + } + iIndex += 3; + } else { + if (iPos == 0) { + iHour = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 1) { + iMinute = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 2) { + iSecond = FXSYS_atoi(strTemp); + ++iPos; + } + iIndex += 2; + } + } + + if (iIndex < iLength && pData[iIndex] == '.') { + constexpr int kSubSecondLength = 3; + if (iIndex + kSubSecondLength >= iLength) + return false; + + ++iIndex; + char strSec[kSubSecondLength + 1]; + for (int i = 0; i < kSubSecondLength; ++i) { + char c = pData[iIndex + i]; + if (!std::isdigit(c)) + return false; + strSec[i] = c; + } + strSec[kSubSecondLength] = '\0'; + + iMilliSecond = FXSYS_atoi(strSec); + if (iMilliSecond > 100) { + iMilliSecond = 0; + return false; + } + iIndex += kSubSecondLength; + } + + if (iIndex < iLength && FXSYS_tolower(pData[iIndex]) == 'z') + return true; + + int32_t iSign = 1; + if (iIndex < iLength) { + if (pData[iIndex] == '+') { + ++iIndex; + } else if (pData[iIndex] == '-') { + iSign = -1; + ++iIndex; + } + } + iPos = 0; + while (iIndex < iLength) { + if (!std::isdigit(pData[iIndex])) + return false; + + strTemp[0] = pData[iIndex]; + if (!std::isdigit(pData[iIndex + 1])) + return false; + + strTemp[1] = pData[iIndex + 1]; + if (FXSYS_atoi(strTemp) > 60) + return false; + + if (pData[2] == ':') { + if (iPos == 0) { + iZoneHour = FXSYS_atoi(strTemp); + } else if (iPos == 1) { + iZoneMinute = FXSYS_atoi(strTemp); + } + iIndex += 3; + } else { + if (!iPos) { + iZoneHour = FXSYS_atoi(strTemp); + ++iPos; + } else if (iPos == 1) { + iZoneMinute = FXSYS_atoi(strTemp); + ++iPos; + } + iIndex += 2; + } + } + if (iIndex < iLength) + return false; + + iZoneHour *= iSign; + return true; +} + +// static +bool CFXJSE_FormCalcContext::IsIsoDateTimeFormat(const char* pData, + int32_t iLength, + int32_t& iYear, + int32_t& iMonth, + int32_t& iDay, + int32_t& iHour, + int32_t& iMinute, + int32_t& iSecond, + int32_t& iMillionSecond, + int32_t& iZoneHour, + int32_t& iZoneMinute) { + iYear = 0; + iMonth = 0; + iDay = 0; + iHour = 0; + iMinute = 0; + iSecond = 0; + if (!pData) + return false; + + int32_t iIndex = 0; + while (pData[iIndex] != 'T' && pData[iIndex] != 't') { + if (iIndex >= iLength) + return false; + ++iIndex; + } + if (iIndex != 8 && iIndex != 10) + return false; + + int32_t iStyle = -1; + if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay)) + return false; + if (pData[iIndex] != 'T' && pData[iIndex] != 't') + return true; + + ++iIndex; + if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) && + (iLength - iIndex != 15)) { + return true; + } + return IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute, + iSecond, iMillionSecond, iZoneHour, iZoneMinute); +} + +// static +ByteString CFXJSE_FormCalcContext::Local2IsoDate( + CFXJSE_Value* pThis, + const ByteStringView& szDate, + const ByteStringView& szFormat, + const ByteStringView& szLocale) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return ByteString(); + + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + IFX_Locale* pLocale = LocaleFromString(pDoc, pMgr, szLocale); + if (!pLocale) + return ByteString(); + + WideString wsFormat = FormatFromString(pLocale, szFormat); + CFX_DateTime dt = CXFA_LocaleValue(XFA_VT_DATE, WideString::FromUTF8(szDate), + wsFormat, pLocale, pMgr) + .GetDate(); + + return ByteString::Format("%4d-%02d-%02d", dt.GetYear(), dt.GetMonth(), + dt.GetDay()); +} + +// static +ByteString CFXJSE_FormCalcContext::IsoDate2Local( + CFXJSE_Value* pThis, + const ByteStringView& szDate, + const ByteStringView& szFormat, + const ByteStringView& szLocale) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return ByteString(); + + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + IFX_Locale* pLocale = LocaleFromString(pDoc, pMgr, szLocale); + if (!pLocale) + return ByteString(); + + WideString wsFormat = FormatFromString(pLocale, szFormat); + WideString wsRet; + CXFA_LocaleValue(XFA_VT_DATE, WideString::FromUTF8(szDate), pMgr) + .FormatPatterns(wsRet, wsFormat, pLocale, XFA_VALUEPICTURE_Display); + return wsRet.UTF8Encode(); +} + +// static +ByteString CFXJSE_FormCalcContext::IsoTime2Local( + CFXJSE_Value* pThis, + const ByteStringView& szTime, + const ByteStringView& szFormat, + const ByteStringView& szLocale) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return ByteString(); + + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + IFX_Locale* pLocale = LocaleFromString(pDoc, pMgr, szLocale); + if (!pLocale) + return ByteString(); + + WideString wsFormat = { + L"time{", FormatFromString(pLocale, szFormat).AsStringView(), L"}"}; + CXFA_LocaleValue widgetValue(XFA_VT_TIME, WideString::FromUTF8(szTime), pMgr); + WideString wsRet; + widgetValue.FormatPatterns(wsRet, wsFormat, pLocale, + XFA_VALUEPICTURE_Display); + return wsRet.UTF8Encode(); +} + +// static +int32_t CFXJSE_FormCalcContext::DateString2Num( + const ByteStringView& szDateString) { + int32_t iLength = szDateString.GetLength(); + int32_t iYear = 0; + int32_t iMonth = 0; + int32_t iDay = 0; + if (iLength <= 10) { + int32_t iStyle = -1; + if (!IsIsoDateFormat(szDateString.unterminated_c_str(), iLength, iStyle, + iYear, iMonth, iDay)) { + return 0; + } + } else { + int32_t iHour = 0; + int32_t iMinute = 0; + int32_t iSecond = 0; + int32_t iMilliSecond = 0; + int32_t iZoneHour = 0; + int32_t iZoneMinute = 0; + if (!IsIsoDateTimeFormat(szDateString.unterminated_c_str(), iLength, iYear, + iMonth, iDay, iHour, iMinute, iSecond, + iMilliSecond, iZoneHour, iZoneMinute)) { + return 0; + } + } + + float dDays = 0; + int32_t i = 1; + if (iYear < 1900) + return 0; + + while (iYear - i >= 1900) { + dDays += + ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400)) + ? 366 + : 365; + ++i; + } + i = 1; + while (i < iMonth) { + if (i == 2) + dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28; + else if (i <= 7) + dDays += (i % 2 == 0) ? 30 : 31; + else + dDays += (i % 2 == 0) ? 31 : 30; + + ++i; + } + i = 0; + while (iDay - i > 0) { + dDays += 1; + ++i; + } + return (int32_t)dDays; +} + +// static +ByteString CFXJSE_FormCalcContext::GetLocalDateFormat( + CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocale, + bool bStandard) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return ByteString(); + + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + IFX_Locale* pLocale = LocaleFromString(pDoc, pMgr, szLocale); + if (!pLocale) + return ByteString(); + + WideString strRet = pLocale->GetDatePattern(SubCategoryFromInt(iStyle)); + if (!bStandard) { + AlternateDateTimeSymbols(strRet, pLocale->GetDateTimeSymbols(), + g_sAltTable_Date); + } + return strRet.UTF8Encode(); +} + +// static +ByteString CFXJSE_FormCalcContext::GetLocalTimeFormat( + CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocale, + bool bStandard) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return ByteString(); + + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + IFX_Locale* pLocale = LocaleFromString(pDoc, pMgr, szLocale); + if (!pLocale) + return ByteString(); + + WideString strRet = pLocale->GetTimePattern(SubCategoryFromInt(iStyle)); + if (!bStandard) { + AlternateDateTimeSymbols(strRet, pLocale->GetDateTimeSymbols(), + g_sAltTable_Time); + } + return strRet.UTF8Encode(); +} + +// static +ByteString CFXJSE_FormCalcContext::GetStandardDateFormat( + CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocalStr) { + return GetLocalDateFormat(pThis, iStyle, szLocalStr, true); +} + +// static +ByteString CFXJSE_FormCalcContext::GetStandardTimeFormat( + CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocalStr) { + return GetLocalTimeFormat(pThis, iStyle, szLocalStr, true); +} + +// static +ByteString CFXJSE_FormCalcContext::Num2AllTime(CFXJSE_Value* pThis, + int32_t iTime, + const ByteStringView& szFormat, + const ByteStringView& szLocale, + bool bGM) { + int32_t iHour = 0; + int32_t iMin = 0; + int32_t iSec = 0; + iHour = static_cast(iTime) / 3600000; + iMin = (static_cast(iTime) - iHour * 3600000) / 60000; + iSec = (static_cast(iTime) - iHour * 3600000 - iMin * 60000) / 1000; + + if (!bGM) { + int32_t iZoneHour = 0; + int32_t iZoneMin = 0; + int32_t iZoneSec = 0; + GetLocalTimeZone(iZoneHour, iZoneMin, iZoneSec); + iHour += iZoneHour; + iMin += iZoneMin; + iSec += iZoneSec; + } + + return IsoTime2Local( + pThis, + ByteString::Format("%02d:%02d:%02d", iHour, iMin, iSec).AsStringView(), + szFormat, szLocale); +} + +// static +void CFXJSE_FormCalcContext::GetLocalTimeZone(int32_t& iHour, + int32_t& iMin, + int32_t& iSec) { + time_t now; + time(&now); + + struct tm* pGmt = gmtime(&now); + struct tm* pLocal = localtime(&now); + iHour = pLocal->tm_hour - pGmt->tm_hour; + iMin = pLocal->tm_min - pGmt->tm_min; + iSec = pLocal->tm_sec - pGmt->tm_sec; +} + +// static +void CFXJSE_FormCalcContext::Apr(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"Apr"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + double nPrincipal = ValueToDouble(pThis, argOne.get()); + double nPayment = ValueToDouble(pThis, argTwo.get()); + double nPeriods = ValueToDouble(pThis, argThree.get()); + if (nPrincipal <= 0 || nPayment <= 0 || nPeriods <= 0) { + pContext->ThrowArgumentMismatchException(); + return; + } + + double r = 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal); + double nTemp = 1; + for (int32_t i = 0; i < nPeriods; ++i) + nTemp *= (1 + r); + + double nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal; + while (fabs(nRet) > kFinancialPrecision) { + double nDerivative = + ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) - + (r * nTemp * nPeriods * (nTemp / (1 + r)))) / + ((nTemp - 1) * (nTemp - 1)); + if (nDerivative == 0) { + args.GetReturnValue()->SetNull(); + return; + } + + r = r - nRet / nDerivative; + nTemp = 1; + for (int32_t i = 0; i < nPeriods; ++i) { + nTemp *= (1 + r); + } + nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal; + } + args.GetReturnValue()->SetDouble(r * 12); +} + +// static +void CFXJSE_FormCalcContext::CTerm(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"CTerm"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + float nRate = ValueToFloat(pThis, argOne.get()); + float nFutureValue = ValueToFloat(pThis, argTwo.get()); + float nInitAmount = ValueToFloat(pThis, argThree.get()); + if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + args.GetReturnValue()->SetFloat(log((float)(nFutureValue / nInitAmount)) / + log((float)(1 + nRate))); +} + +// static +void CFXJSE_FormCalcContext::FV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"FV"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + double nAmount = ValueToDouble(pThis, argOne.get()); + double nRate = ValueToDouble(pThis, argTwo.get()); + double nPeriod = ValueToDouble(pThis, argThree.get()); + if ((nRate < 0) || (nPeriod <= 0) || (nAmount <= 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + double dResult = 0; + if (nRate) { + double nTemp = 1; + for (int i = 0; i < nPeriod; ++i) { + nTemp *= 1 + nRate; + } + dResult = nAmount * (nTemp - 1) / nRate; + } else { + dResult = nAmount * nPeriod; + } + + args.GetReturnValue()->SetDouble(dResult); +} + +// static +void CFXJSE_FormCalcContext::IPmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 5) { + pContext->ThrowParamCountMismatchException(L"IPmt"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + std::unique_ptr argFour = GetSimpleValue(pThis, args, 3); + std::unique_ptr argFive = GetSimpleValue(pThis, args, 4); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) || + ValueIsNull(pThis, argFive.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + float nPrincipalAmount = ValueToFloat(pThis, argOne.get()); + float nRate = ValueToFloat(pThis, argTwo.get()); + float nPayment = ValueToFloat(pThis, argThree.get()); + float nFirstMonth = ValueToFloat(pThis, argFour.get()); + float nNumberOfMonths = ValueToFloat(pThis, argFive.get()); + if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) || + (nFirstMonth < 0) || (nNumberOfMonths < 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + float nRateOfMonth = nRate / 12; + int32_t iNums = + (int32_t)((log10((float)(nPayment / nPrincipalAmount)) - + log10((float)(nPayment / nPrincipalAmount - nRateOfMonth))) / + log10((float)(1 + nRateOfMonth))); + int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums); + + if (nPayment < nPrincipalAmount * nRateOfMonth) { + args.GetReturnValue()->SetFloat(0); + return; + } + + int32_t i = 0; + for (i = 0; i < nFirstMonth - 1; ++i) + nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth; + + float nSum = 0; + for (; i < iEnd; ++i) { + nSum += nPrincipalAmount * nRateOfMonth; + nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth; + } + args.GetReturnValue()->SetFloat(nSum); +} + +// static +void CFXJSE_FormCalcContext::NPV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + int32_t argc = args.GetLength(); + if (argc < 3) { + pContext->ThrowParamCountMismatchException(L"NPV"); + return; + } + + std::vector> argValues; + for (int32_t i = 0; i < argc; i++) { + argValues.push_back(GetSimpleValue(pThis, args, i)); + if (ValueIsNull(pThis, argValues[i].get())) { + args.GetReturnValue()->SetNull(); + return; + } + } + + double nRate = ValueToDouble(pThis, argValues[0].get()); + if (nRate <= 0) { + pContext->ThrowArgumentMismatchException(); + return; + } + + std::vector data(argc - 1); + for (int32_t i = 1; i < argc; i++) + data.push_back(ValueToDouble(pThis, argValues[i].get())); + + double nSum = 0; + int32_t iIndex = 0; + for (int32_t i = 0; i < argc - 1; i++) { + double nTemp = 1; + for (int32_t j = 0; j <= i; j++) + nTemp *= 1 + nRate; + + double nNum = data[iIndex++]; + nSum += nNum / nTemp; + } + args.GetReturnValue()->SetDouble(nSum); +} + +// static +void CFXJSE_FormCalcContext::Pmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"Pmt"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + float nPrincipal = ValueToFloat(pThis, argOne.get()); + float nRate = ValueToFloat(pThis, argTwo.get()); + float nPeriods = ValueToFloat(pThis, argThree.get()); + if ((nPrincipal <= 0) || (nRate <= 0) || (nPeriods <= 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + float nTmp = 1 + nRate; + float nSum = nTmp; + for (int32_t i = 0; i < nPeriods - 1; ++i) + nSum *= nTmp; + + args.GetReturnValue()->SetFloat((nPrincipal * nRate * nSum) / (nSum - 1)); +} + +// static +void CFXJSE_FormCalcContext::PPmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 5) { + pContext->ThrowParamCountMismatchException(L"PPmt"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + std::unique_ptr argFour = GetSimpleValue(pThis, args, 3); + std::unique_ptr argFive = GetSimpleValue(pThis, args, 4); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) || + ValueIsNull(pThis, argFive.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + float nPrincipalAmount = ValueToFloat(pThis, argOne.get()); + float nRate = ValueToFloat(pThis, argTwo.get()); + float nPayment = ValueToFloat(pThis, argThree.get()); + float nFirstMonth = ValueToFloat(pThis, argFour.get()); + float nNumberOfMonths = ValueToFloat(pThis, argFive.get()); + if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) || + (nFirstMonth < 0) || (nNumberOfMonths < 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + float nRateOfMonth = nRate / 12; + int32_t iNums = + (int32_t)((log10((float)(nPayment / nPrincipalAmount)) - + log10((float)(nPayment / nPrincipalAmount - nRateOfMonth))) / + log10((float)(1 + nRateOfMonth))); + int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums); + if (nPayment < nPrincipalAmount * nRateOfMonth) { + pContext->ThrowArgumentMismatchException(); + return; + } + + int32_t i = 0; + for (i = 0; i < nFirstMonth - 1; ++i) + nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth; + + float nTemp = 0; + float nSum = 0; + for (; i < iEnd; ++i) { + nTemp = nPayment - nPrincipalAmount * nRateOfMonth; + nSum += nTemp; + nPrincipalAmount -= nTemp; + } + args.GetReturnValue()->SetFloat(nSum); +} + +// static +void CFXJSE_FormCalcContext::PV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"PV"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + double nAmount = ValueToDouble(pThis, argOne.get()); + double nRate = ValueToDouble(pThis, argTwo.get()); + double nPeriod = ValueToDouble(pThis, argThree.get()); + if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + double nTemp = 1; + for (int32_t i = 0; i < nPeriod; ++i) + nTemp *= 1 + nRate; + + nTemp = 1 / nTemp; + args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate)); +} + +// static +void CFXJSE_FormCalcContext::Rate(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"Rate"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + float nFuture = ValueToFloat(pThis, argOne.get()); + float nPresent = ValueToFloat(pThis, argTwo.get()); + float nTotalNumber = ValueToFloat(pThis, argThree.get()); + if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + args.GetReturnValue()->SetFloat( + FXSYS_pow((float)(nFuture / nPresent), (float)(1 / nTotalNumber)) - 1); +} + +// static +void CFXJSE_FormCalcContext::Term(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 3) { + pContext->ThrowParamCountMismatchException(L"Term"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || + ValueIsNull(pThis, argThree.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + float nMount = ValueToFloat(pThis, argOne.get()); + float nRate = ValueToFloat(pThis, argTwo.get()); + float nFuture = ValueToFloat(pThis, argThree.get()); + if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) { + pContext->ThrowArgumentMismatchException(); + return; + } + + args.GetReturnValue()->SetFloat(log((float)(nFuture / nMount * nRate) + 1) / + log((float)(1 + nRate))); +} + +// static +void CFXJSE_FormCalcContext::Choose(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + int32_t argc = args.GetLength(); + if (argc < 2) { + pContext->ThrowParamCountMismatchException(L"Choose"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get()); + if (iIndex < 1) { + args.GetReturnValue()->SetString(""); + return; + } + + bool bFound = false; + bool bStopCounterFlags = false; + int32_t iArgIndex = 1; + int32_t iValueIndex = 0; + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) { + std::unique_ptr argIndexValue = args.GetValue(iArgIndex); + if (argIndexValue->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argIndexValue->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength > 3) + bStopCounterFlags = true; + + iValueIndex += (iLength - 2); + if (iValueIndex >= iIndex) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get()); + argIndexValue->GetObjectPropertyByIdx( + (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + } else { + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), newPropertyValue.get()); + } + ByteString bsChosen = ValueToUTF8String(newPropertyValue.get()); + args.GetReturnValue()->SetString(bsChosen.AsStringView()); + bFound = true; + } + } else { + iValueIndex++; + if (iValueIndex == iIndex) { + ByteString bsChosen = ValueToUTF8String(argIndexValue.get()); + args.GetReturnValue()->SetString(bsChosen.AsStringView()); + bFound = true; + } + } + iArgIndex++; + } + if (!bFound) + args.GetReturnValue()->SetString(""); +} + +// static +void CFXJSE_FormCalcContext::Exists(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Exists"); + return; + } + args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject()); +} + +// static +void CFXJSE_FormCalcContext::HasValue(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"HasValue"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (!argOne->IsString()) { + args.GetReturnValue()->SetInteger(argOne->IsNumber() || + argOne->IsBoolean()); + return; + } + + ByteString valueStr = argOne->ToString(); + valueStr.TrimLeft(); + args.GetReturnValue()->SetInteger(!valueStr.IsEmpty()); +} + +// static +void CFXJSE_FormCalcContext::Oneof(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() < 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Oneof"); + return; + } + + bool bFlags = false; + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::vector> parameterValues; + unfoldArgs(pThis, args, ¶meterValues, 1); + for (const auto& value : parameterValues) { + if (simpleValueCompare(pThis, argOne.get(), value.get())) { + bFlags = true; + break; + } + } + + args.GetReturnValue()->SetInteger(bFlags); +} + +// static +void CFXJSE_FormCalcContext::Within(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Within"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetUndefined(); + return; + } + + std::unique_ptr argLow = GetSimpleValue(pThis, args, 1); + std::unique_ptr argHigh = GetSimpleValue(pThis, args, 2); + if (argOne->IsNumber()) { + float oneNumber = ValueToFloat(pThis, argOne.get()); + float lowNumber = ValueToFloat(pThis, argLow.get()); + float heightNumber = ValueToFloat(pThis, argHigh.get()); + args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) && + (oneNumber <= heightNumber)); + return; + } + + ByteString oneString = ValueToUTF8String(argOne.get()); + ByteString lowString = ValueToUTF8String(argLow.get()); + ByteString heightString = ValueToUTF8String(argHigh.get()); + args.GetReturnValue()->SetInteger( + (oneString.Compare(lowString.AsStringView()) >= 0) && + (oneString.Compare(heightString.AsStringView()) <= 0)); +} + +// static +void CFXJSE_FormCalcContext::If(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"If"); + return; + } + + args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean() + ? GetSimpleValue(pThis, args, 1).get() + : GetSimpleValue(pThis, args, 2).get()); +} + +// static +void CFXJSE_FormCalcContext::Eval(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"Eval"); + return; + } + + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + std::unique_ptr scriptValue = GetSimpleValue(pThis, args, 0); + ByteString utf8ScriptString = ValueToUTF8String(scriptValue.get()); + if (utf8ScriptString.IsEmpty()) { + args.GetReturnValue()->SetNull(); + return; + } + + CFX_WideTextBuf wsJavaScriptBuf; + if (!CFXJSE_FormCalcContext::Translate( + WideString::FromUTF8(utf8ScriptString.AsStringView()).AsStringView(), + &wsJavaScriptBuf)) { + pContext->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr pNewContext( + CFXJSE_Context::Create(pIsolate, nullptr, nullptr)); + + auto returnValue = pdfium::MakeUnique(pIsolate); + pNewContext->ExecuteScript( + FX_UTF8Encode(wsJavaScriptBuf.AsStringView()).c_str(), returnValue.get()); + + args.GetReturnValue()->Assign(returnValue.get()); +} + +// static +void CFXJSE_FormCalcContext::Ref(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"Ref"); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() && + !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) { + pContext->ThrowArgumentMismatchException(); + return; + } + + if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) { + args.GetReturnValue()->Assign(argOne.get()); + return; + } + + std::vector> values; + for (int32_t i = 0; i < 3; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); + + int intVal = 3; + if (argOne->IsNull()) { + // TODO(dsinclair): Why is this 4 when the others are all 3? + intVal = 4; + values[2]->SetNull(); + } else if (argOne->IsArray()) { +#ifndef NDEBUG + auto lengthValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectProperty("length", lengthValue.get()); + ASSERT(lengthValue->ToInteger() >= 3); +#endif + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectPropertyByIdx(1, propertyValue.get()); + argOne->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (!propertyValue->IsNull() || jsObjectValue->IsNull()) { + pContext->ThrowArgumentMismatchException(); + return; + } + + values[2]->Assign(jsObjectValue.get()); + } else if (argOne->IsObject()) { + values[2]->Assign(argOne.get()); + } + + values[0]->SetInteger(intVal); + values[1]->SetNull(); + args.GetReturnValue()->SetArray(values); +} + +// static +void CFXJSE_FormCalcContext::UnitType(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"UnitType"); + return; + } + + std::unique_ptr unitspanValue = GetSimpleValue(pThis, args, 0); + if (unitspanValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString unitspanString = ValueToUTF8String(unitspanValue.get()); + if (unitspanString.IsEmpty()) { + args.GetReturnValue()->SetString("in"); + return; + } + + enum XFA_FM2JS_VALUETYPE_ParserStatus { + VALUETYPE_START, + VALUETYPE_HAVEINVALIDCHAR, + VALUETYPE_HAVEDIGIT, + VALUETYPE_HAVEDIGITWHITE, + VALUETYPE_ISCM, + VALUETYPE_ISMM, + VALUETYPE_ISPT, + VALUETYPE_ISMP, + VALUETYPE_ISIN, + }; + unitspanString.MakeLower(); + WideString wsTypeString = WideString::FromUTF8(unitspanString.AsStringView()); + const wchar_t* pData = wsTypeString.c_str(); + int32_t u = 0; + int32_t uLen = wsTypeString.GetLength(); + while (IsWhitespace(pData[u])) + u++; + + XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START; + wchar_t typeChar; + // TODO(dsinclair): Cleanup this parser, figure out what the various checks + // are for. + while (u < uLen) { + typeChar = pData[u]; + if (IsWhitespace(typeChar)) { + if (eParserStatus != VALUETYPE_HAVEDIGIT && + eParserStatus != VALUETYPE_HAVEDIGITWHITE) { + eParserStatus = VALUETYPE_ISIN; + break; + } + eParserStatus = VALUETYPE_HAVEDIGITWHITE; + } else if (IsPartOfNumberW(typeChar)) { + if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) { + eParserStatus = VALUETYPE_ISIN; + break; + } + eParserStatus = VALUETYPE_HAVEDIGIT; + } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) { + wchar_t nextChar = pData[u + 1]; + if ((eParserStatus == VALUETYPE_START || + eParserStatus == VALUETYPE_HAVEDIGIT || + eParserStatus == VALUETYPE_HAVEDIGITWHITE) && + !IsPartOfNumberW(nextChar)) { + eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT; + break; + } + eParserStatus = VALUETYPE_HAVEINVALIDCHAR; + } else if (typeChar == 'm' && (u + 1 < uLen)) { + wchar_t nextChar = pData[u + 1]; + if ((eParserStatus == VALUETYPE_START || + eParserStatus == VALUETYPE_HAVEDIGIT || + eParserStatus == VALUETYPE_HAVEDIGITWHITE) && + !IsPartOfNumberW(nextChar)) { + eParserStatus = VALUETYPE_ISMM; + if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' && + pData[u + 2] == 'l' && pData[u + 3] == 'l' && + pData[u + 4] == 'i' && pData[u + 5] == 'p')) { + eParserStatus = VALUETYPE_ISMP; + } + break; + } + } else { + eParserStatus = VALUETYPE_HAVEINVALIDCHAR; + } + u++; + } + switch (eParserStatus) { + case VALUETYPE_ISCM: + args.GetReturnValue()->SetString("cm"); + break; + case VALUETYPE_ISMM: + args.GetReturnValue()->SetString("mm"); + break; + case VALUETYPE_ISPT: + args.GetReturnValue()->SetString("pt"); + break; + case VALUETYPE_ISMP: + args.GetReturnValue()->SetString("mp"); + break; + default: + args.GetReturnValue()->SetString("in"); + break; + } +} + +// static +void CFXJSE_FormCalcContext::UnitValue(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"UnitValue"); + return; + } + + std::unique_ptr unitspanValue = GetSimpleValue(pThis, args, 0); + if (unitspanValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString unitspanString = ValueToUTF8String(unitspanValue.get()); + const char* pData = unitspanString.c_str(); + if (!pData) { + args.GetReturnValue()->SetInteger(0); + return; + } + + size_t u = 0; + while (IsWhitespace(pData[u])) + ++u; + + while (u < unitspanString.GetLength()) { + if (!IsPartOfNumber(pData[u])) + break; + ++u; + } + + char* pTemp = nullptr; + double dFirstNumber = strtod(pData, &pTemp); + while (IsWhitespace(pData[u])) + ++u; + + size_t uLen = unitspanString.GetLength(); + ByteString strFirstUnit; + while (u < uLen) { + if (pData[u] == ' ') + break; + + strFirstUnit += pData[u]; + ++u; + } + strFirstUnit.MakeLower(); + + ByteString strUnit; + if (argc > 1) { + std::unique_ptr unitValue = GetSimpleValue(pThis, args, 1); + ByteString unitTempString = ValueToUTF8String(unitValue.get()); + const char* pChar = unitTempString.c_str(); + size_t uVal = 0; + while (IsWhitespace(pChar[uVal])) + ++uVal; + + while (uVal < unitTempString.GetLength()) { + if (!std::isdigit(pChar[uVal]) && pChar[uVal] != '.') + break; + ++uVal; + } + while (IsWhitespace(pChar[uVal])) + ++uVal; + + size_t uValLen = unitTempString.GetLength(); + while (uVal < uValLen) { + if (pChar[uVal] == ' ') + break; + + strUnit += pChar[uVal]; + ++uVal; + } + strUnit.MakeLower(); + } else { + strUnit = strFirstUnit; + } + + double dResult = 0; + if (strFirstUnit == "in" || strFirstUnit == "inches") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber * 25.4; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber * 2.54; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 72; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber / 72000; + else + dResult = dFirstNumber; + } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber / 10; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 25.4 / 72; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber / 25.4 / 72000; + else + dResult = dFirstNumber / 25.4; + } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber * 10; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 2.54 / 72; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber / 2.54 / 72000; + else + dResult = dFirstNumber / 2.54; + } else if (strFirstUnit == "pt" || strFirstUnit == "points") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber / 72 * 25.4; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber / 72 * 2.54; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber * 1000; + else + dResult = dFirstNumber / 72; + } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") { + if (strUnit == "mm" || strUnit == "millimeters") + dResult = dFirstNumber / 72000 * 25.4; + else if (strUnit == "cm" || strUnit == "centimeters") + dResult = dFirstNumber / 72000 * 2.54; + else if (strUnit == "pt" || strUnit == "points") + dResult = dFirstNumber / 1000; + else if (strUnit == "mp" || strUnit == "millipoints") + dResult = dFirstNumber; + else + dResult = dFirstNumber / 72000; + } + args.GetReturnValue()->SetDouble(dResult); +} + +// static +void CFXJSE_FormCalcContext::At(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"At"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString stringTwo = ValueToUTF8String(argTwo.get()); + if (stringTwo.IsEmpty()) { + args.GetReturnValue()->SetInteger(1); + return; + } + + ByteString stringOne = ValueToUTF8String(argOne.get()); + auto pos = stringOne.Find(stringTwo.AsStringView()); + args.GetReturnValue()->SetInteger(pos.has_value() ? pos.value() + 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::Concat(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Concat"); + return; + } + + ByteString resultString; + bool bAllNull = true; + for (int32_t i = 0; i < argc; i++) { + std::unique_ptr value = GetSimpleValue(pThis, args, i); + if (ValueIsNull(pThis, value.get())) + continue; + + bAllNull = false; + resultString += ValueToUTF8String(value.get()); + } + + if (bAllNull) { + args.GetReturnValue()->SetNull(); + return; + } + + args.GetReturnValue()->SetString(resultString.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Decode(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Decode"); + return; + } + + if (argc == 1) { + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + WideString decoded = DecodeURL( + WideString::FromUTF8(ValueToUTF8String(argOne.get()).AsStringView())); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(decoded.AsStringView()).AsStringView()); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString toDecodeString = ValueToUTF8String(argOne.get()); + ByteString identifyString = ValueToUTF8String(argTwo.get()); + WideString decoded; + + WideString toDecodeWideString = + WideString::FromUTF8(toDecodeString.AsStringView()); + + if (identifyString.EqualNoCase("html")) + decoded = DecodeHTML(toDecodeWideString); + else if (identifyString.EqualNoCase("xml")) + decoded = DecodeXML(toDecodeWideString); + else + decoded = DecodeURL(toDecodeWideString); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(decoded.AsStringView()).AsStringView()); +} + +// static +WideString CFXJSE_FormCalcContext::DecodeURL(const WideString& wsURLString) { + const wchar_t* pData = wsURLString.c_str(); + size_t i = 0; + CFX_WideTextBuf wsResultBuf; + while (i < wsURLString.GetLength()) { + wchar_t ch = pData[i]; + if ('%' != ch) { + wsResultBuf.AppendChar(ch); + ++i; + continue; + } + + wchar_t chTemp = 0; + int32_t iCount = 0; + while (iCount < 2) { + ++i; + ch = pData[i]; + if (ch <= '9' && ch >= '0') { + // TODO(dsinclair): Premultiply and add rather then scale. + chTemp += (ch - '0') * (!iCount ? 16 : 1); + } else if (ch <= 'F' && ch >= 'A') { + chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1); + } else if (ch <= 'f' && ch >= 'a') { + chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1); + } else { + return WideString(); + } + ++iCount; + } + wsResultBuf.AppendChar(chTemp); + ++i; + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +// static +WideString CFXJSE_FormCalcContext::DecodeHTML(const WideString& wsHTMLString) { + wchar_t strString[9]; + size_t iStrIndex = 0; + size_t iLen = wsHTMLString.GetLength(); + size_t i = 0; + int32_t iCode = 0; + const wchar_t* pData = wsHTMLString.c_str(); + CFX_WideTextBuf wsResultBuf; + while (i < iLen) { + wchar_t ch = pData[i]; + if (ch != '&') { + wsResultBuf.AppendChar(ch); + ++i; + continue; + } + + ++i; + ch = pData[i]; + if (ch == '#') { + ++i; + ch = pData[i]; + if (ch != 'x' && ch != 'X') { + return WideString(); + } + + ++i; + ch = pData[i]; + if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || + (ch <= 'F' && ch >= 'A')) { + while (ch != ';' && i < iLen) { + if (ch >= '0' && ch <= '9') { + iCode += ch - '0'; + } else if (ch <= 'f' && ch >= 'a') { + iCode += ch - 'a' + 10; + } else if (ch <= 'F' && ch >= 'A') { + iCode += ch - 'A' + 10; + } else { + return WideString(); + } + ++i; + // TODO(dsinclair): Postmultiply seems wrong, start at zero + // and pre-multiply then can remove the post divide. + iCode *= 16; + ch = pData[i]; + } + iCode /= 16; + } + } else { + while (ch != ';' && i < iLen) { + strString[iStrIndex++] = ch; + ++i; + ch = pData[i]; + } + strString[iStrIndex] = 0; + } + uint32_t iData = 0; + if (HTMLSTR2Code(strString, &iData)) { + wsResultBuf.AppendChar((wchar_t)iData); + } else { + wsResultBuf.AppendChar(iCode); + } + iStrIndex = 0; + strString[iStrIndex] = 0; + ++i; + } + wsResultBuf.AppendChar(0); + + return wsResultBuf.MakeString(); +} + +// static +WideString CFXJSE_FormCalcContext::DecodeXML(const WideString& wsXMLString) { + wchar_t strString[9]; + int32_t iStrIndex = 0; + int32_t iLen = wsXMLString.GetLength(); + int32_t i = 0; + int32_t iCode = 0; + wchar_t ch = 0; + const wchar_t* pData = wsXMLString.c_str(); + CFX_WideTextBuf wsResultBuf; + while (i < iLen) { + ch = pData[i]; + if (ch != '&') { + wsResultBuf.AppendChar(ch); + ++i; + continue; + } + + // TODO(dsinclair): This is very similar to DecodeHTML, can they be + // combined? + ++i; + ch = pData[i]; + if (ch == '#') { + ++i; + ch = pData[i]; + if (ch != 'x' && ch != 'X') { + return WideString(); + } + + ++i; + ch = pData[i]; + if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || + (ch <= 'F' && ch >= 'A')) { + while (ch != ';') { + if (ch >= '0' && ch <= '9') { + iCode += ch - '0'; + } else if (ch <= 'f' && ch >= 'a') { + iCode += ch - 'a' + 10; + } else if (ch <= 'F' && ch >= 'A') { + iCode += ch - 'A' + 10; + } else { + return WideString(); + } + ++i; + iCode *= 16; + ch = pData[i]; + } + iCode /= 16; + } + } else { + while (ch != ';' && i < iLen) { + strString[iStrIndex++] = ch; + ++i; + ch = pData[i]; + } + strString[iStrIndex] = 0; + } + + const wchar_t* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"}; + int32_t iIndex = 0; + while (iIndex < 5) { + if (memcmp(strString, strName[iIndex], wcslen(strName[iIndex])) == 0) { + break; + } + ++iIndex; + } + switch (iIndex) { + case 0: + wsResultBuf.AppendChar('"'); + break; + case 1: + wsResultBuf.AppendChar('&'); + break; + case 2: + wsResultBuf.AppendChar('\''); + break; + case 3: + wsResultBuf.AppendChar('<'); + break; + case 4: + wsResultBuf.AppendChar('>'); + break; + default: + wsResultBuf.AppendChar(iCode); + break; + } + iStrIndex = 0; + strString[iStrIndex] = 0; + ++i; + iCode = 0; + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +// static +void CFXJSE_FormCalcContext::Encode(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Encode"); + return; + } + + if (argc == 1) { + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + WideString encoded = EncodeURL(ValueToUTF8String(argOne.get())); + args.GetReturnValue()->SetString( + FX_UTF8Encode(encoded.AsStringView()).AsStringView()); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString toEncodeString = ValueToUTF8String(argOne.get()); + ByteString identifyString = ValueToUTF8String(argTwo.get()); + WideString encoded; + if (identifyString.EqualNoCase("html")) + encoded = EncodeHTML(toEncodeString); + else if (identifyString.EqualNoCase("xml")) + encoded = EncodeXML(toEncodeString); + else + encoded = EncodeURL(toEncodeString); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(encoded.AsStringView()).AsStringView()); +} + +// static +WideString CFXJSE_FormCalcContext::EncodeURL(const ByteString& szURLString) { + WideString wsURLString = WideString::FromUTF8(szURLString.AsStringView()); + CFX_WideTextBuf wsResultBuf; + wchar_t strEncode[4]; + strEncode[0] = '%'; + strEncode[3] = 0; + wchar_t strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}', + '|', '\\', '^', '~', '[', ']', '`'}; + wchar_t strReserved[] = {';', '/', '?', ':', '@', '=', '&'}; + wchar_t strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','}; + const wchar_t* strCode = L"0123456789abcdef"; + for (auto ch : wsURLString) { + int32_t i = 0; + int32_t iCount = FX_ArraySize(strUnsafe); + while (i < iCount) { + if (ch == strUnsafe[i]) { + int32_t iIndex = ch / 16; + strEncode[1] = strCode[iIndex]; + strEncode[2] = strCode[ch - iIndex * 16]; + wsResultBuf << strEncode; + break; + } + ++i; + } + if (i < iCount) + continue; + + i = 0; + iCount = FX_ArraySize(strReserved); + while (i < iCount) { + if (ch == strReserved[i]) { + int32_t iIndex = ch / 16; + strEncode[1] = strCode[iIndex]; + strEncode[2] = strCode[ch - iIndex * 16]; + wsResultBuf << strEncode; + break; + } + ++i; + } + if (i < iCount) + continue; + + i = 0; + iCount = FX_ArraySize(strSpecial); + while (i < iCount) { + if (ch == strSpecial[i]) { + wsResultBuf.AppendChar(ch); + break; + } + ++i; + } + if (i < iCount) + continue; + + if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) { + int32_t iIndex = ch / 16; + strEncode[1] = strCode[iIndex]; + strEncode[2] = strCode[ch - iIndex * 16]; + wsResultBuf << strEncode; + } else if (ch >= 0x20 && ch <= 0x7e) { + wsResultBuf.AppendChar(ch); + } else { + const wchar_t iRadix = 16; + WideString strTmp; + while (ch >= iRadix) { + wchar_t tmp = strCode[ch % iRadix]; + ch /= iRadix; + strTmp += tmp; + } + strTmp += strCode[ch]; + int32_t iLen = strTmp.GetLength(); + if (iLen < 2) + break; + + int32_t iIndex = 0; + if (iLen % 2 != 0) { + strEncode[1] = '0'; + strEncode[2] = strTmp[iLen - 1]; + iIndex = iLen - 2; + } else { + strEncode[1] = strTmp[iLen - 1]; + strEncode[2] = strTmp[iLen - 2]; + iIndex = iLen - 3; + } + wsResultBuf << strEncode; + while (iIndex > 0) { + strEncode[1] = strTmp[iIndex]; + strEncode[2] = strTmp[iIndex - 1]; + iIndex -= 2; + wsResultBuf << strEncode; + } + } + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +// static +WideString CFXJSE_FormCalcContext::EncodeHTML(const ByteString& szHTMLString) { + WideString wsHTMLString = WideString::FromUTF8(szHTMLString.AsStringView()); + const wchar_t* strCode = L"0123456789abcdef"; + wchar_t strEncode[9]; + strEncode[0] = '&'; + strEncode[1] = '#'; + strEncode[2] = 'x'; + strEncode[5] = ';'; + strEncode[6] = 0; + strEncode[7] = ';'; + strEncode[8] = 0; + CFX_WideTextBuf wsResultBuf; + int32_t iLen = wsHTMLString.GetLength(); + int32_t i = 0; + const wchar_t* pData = wsHTMLString.c_str(); + while (i < iLen) { + uint32_t ch = pData[i]; + WideString htmlReserve; + if (HTMLCode2STR(ch, &htmlReserve)) { + wsResultBuf.AppendChar(L'&'); + wsResultBuf << htmlReserve; + wsResultBuf.AppendChar(L';'); + } else if (ch >= 32 && ch <= 126) { + wsResultBuf.AppendChar((wchar_t)ch); + } else if (ch < 256) { + int32_t iIndex = ch / 16; + strEncode[3] = strCode[iIndex]; + strEncode[4] = strCode[ch - iIndex * 16]; + strEncode[5] = ';'; + strEncode[6] = 0; + wsResultBuf << strEncode; + } else { + int32_t iBigByte = ch / 256; + int32_t iLittleByte = ch % 256; + strEncode[3] = strCode[iBigByte / 16]; + strEncode[4] = strCode[iBigByte % 16]; + strEncode[5] = strCode[iLittleByte / 16]; + strEncode[6] = strCode[iLittleByte % 16]; + wsResultBuf << strEncode; + } + ++i; + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +// static +WideString CFXJSE_FormCalcContext::EncodeXML(const ByteString& szXMLString) { + WideString wsXMLString = WideString::FromUTF8(szXMLString.AsStringView()); + CFX_WideTextBuf wsResultBuf; + wchar_t strEncode[9]; + strEncode[0] = '&'; + strEncode[1] = '#'; + strEncode[2] = 'x'; + strEncode[5] = ';'; + strEncode[6] = 0; + strEncode[7] = ';'; + strEncode[8] = 0; + const wchar_t* strCode = L"0123456789abcdef"; + for (const auto& ch : wsXMLString) { + switch (ch) { + case '"': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"quot"); + wsResultBuf.AppendChar(';'); + break; + case '&': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"amp"); + wsResultBuf.AppendChar(';'); + break; + case '\'': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"apos"); + wsResultBuf.AppendChar(';'); + break; + case '<': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"lt"); + wsResultBuf.AppendChar(';'); + break; + case '>': + wsResultBuf.AppendChar('&'); + wsResultBuf << WideStringView(L"gt"); + wsResultBuf.AppendChar(';'); + break; + default: { + if (ch >= 32 && ch <= 126) { + wsResultBuf.AppendChar(ch); + } else if (ch < 256) { + int32_t iIndex = ch / 16; + strEncode[3] = strCode[iIndex]; + strEncode[4] = strCode[ch - iIndex * 16]; + strEncode[5] = ';'; + strEncode[6] = 0; + wsResultBuf << strEncode; + } else { + int32_t iBigByte = ch / 256; + int32_t iLittleByte = ch % 256; + strEncode[3] = strCode[iBigByte / 16]; + strEncode[4] = strCode[iBigByte % 16]; + strEncode[5] = strCode[iLittleByte / 16]; + strEncode[6] = strCode[iLittleByte % 16]; + wsResultBuf << strEncode; + } + break; + } + } + } + wsResultBuf.AppendChar(0); + return wsResultBuf.MakeString(); +} + +// static +bool CFXJSE_FormCalcContext::HTMLSTR2Code(const WideStringView& pData, + uint32_t* iCode) { + auto cmpFunc = [](const XFA_FMHtmlReserveCode& iter, + const WideStringView& val) { + // TODO(tsepez): check usage of c_str() below. + return wcscmp(val.unterminated_c_str(), iter.m_htmlReserve) > 0; + }; + const XFA_FMHtmlReserveCode* result = + std::lower_bound(std::begin(reservesForDecode), + std::end(reservesForDecode), pData, cmpFunc); + if (result != std::end(reservesForEncode) && + !wcscmp(pData.unterminated_c_str(), result->m_htmlReserve)) { + *iCode = result->m_uCode; + return true; + } + return false; +} + +// static +bool CFXJSE_FormCalcContext::HTMLCode2STR(uint32_t iCode, + WideString* wsHTMLReserve) { + auto cmpFunc = [](const XFA_FMHtmlReserveCode iter, const uint32_t& val) { + return iter.m_uCode < val; + }; + const XFA_FMHtmlReserveCode* result = + std::lower_bound(std::begin(reservesForEncode), + std::end(reservesForEncode), iCode, cmpFunc); + if (result != std::end(reservesForEncode) && result->m_uCode == iCode) { + *wsHTMLReserve = result->m_htmlReserve; + return true; + } + return false; +} + +// static +void CFXJSE_FormCalcContext::Format(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() < 2) { + pContext->ThrowParamCountMismatchException(L"Format"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + ByteString szPattern = ValueToUTF8String(argOne.get()); + + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + ByteString szValue = ValueToUTF8String(argTwo.get()); + + CXFA_Document* pDoc = pContext->GetDocument(); + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); + ASSERT(pThisNode); + + IFX_Locale* pLocale = pThisNode->GetLocale(); + uint32_t patternType; + WideString wsPattern = WideString::FromUTF8(szPattern.AsStringView()); + WideString wsValue = WideString::FromUTF8(szValue.AsStringView()); + if (!PatternStringType(szPattern.AsStringView(), patternType)) { + switch (patternType) { + case XFA_VT_DATETIME: { + auto iTChar = wsPattern.Find(L'T'); + if (!iTChar.has_value()) { + args.GetReturnValue()->SetString(""); + return; + } + WideString wsDatePattern(L"date{"); + wsDatePattern += wsPattern.Left(iTChar.value()) + L"} "; + + WideString wsTimePattern(L"time{"); + wsTimePattern += + wsPattern.Right(wsPattern.GetLength() - (iTChar.value() + 1)) + + L"}"; + wsPattern = wsDatePattern + wsTimePattern; + } break; + case XFA_VT_DATE: { + wsPattern = L"date{" + wsPattern + L"}"; + } break; + case XFA_VT_TIME: { + wsPattern = L"time{" + wsPattern + L"}"; + } break; + case XFA_VT_TEXT: { + wsPattern = L"text{" + wsPattern + L"}"; + } break; + case XFA_VT_FLOAT: { + wsPattern = L"num{" + wsPattern + L"}"; + } break; + default: { + WideString wsTestPattern; + wsTestPattern = L"num{" + wsPattern + L"}"; + CXFA_LocaleValue tempLocaleValue(XFA_VT_FLOAT, wsValue, wsTestPattern, + pLocale, pMgr); + if (tempLocaleValue.IsValid()) { + wsPattern = wsTestPattern; + patternType = XFA_VT_FLOAT; + } else { + wsTestPattern = L"text{" + wsPattern + L"}"; + wsPattern = wsTestPattern; + patternType = XFA_VT_TEXT; + } + } break; + } + } + CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, pMgr); + WideString wsRet; + if (!localeValue.FormatPatterns(wsRet, wsPattern, pLocale, + XFA_VALUEPICTURE_Display)) { + args.GetReturnValue()->SetString(""); + return; + } + + args.GetReturnValue()->SetString(wsRet.UTF8Encode().AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Left(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Left"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if ((ValueIsNull(pThis, argOne.get())) || + (ValueIsNull(pThis, argTwo.get()))) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString sourceString = ValueToUTF8String(argOne.get()); + int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get())); + args.GetReturnValue()->SetString(sourceString.Left(count).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Len(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Len"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString sourceString = ValueToUTF8String(argOne.get()); + args.GetReturnValue()->SetInteger(sourceString.GetLength()); +} + +// static +void CFXJSE_FormCalcContext::Lower(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Lower"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + CFX_WideTextBuf lowStringBuf; + ByteString argString = ValueToUTF8String(argOne.get()); + WideString wsArgString = WideString::FromUTF8(argString.AsStringView()); + const wchar_t* pData = wsArgString.c_str(); + size_t i = 0; + while (i < argString.GetLength()) { + int32_t ch = pData[i]; + if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE)) + ch += 32; + else if (ch == 0x100 || ch == 0x102 || ch == 0x104) + ch += 1; + + lowStringBuf.AppendChar(ch); + ++i; + } + lowStringBuf.AppendChar(0); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(lowStringBuf.AsStringView()).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Ltrim(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Ltrim"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString sourceString = ValueToUTF8String(argOne.get()); + sourceString.TrimLeft(); + args.GetReturnValue()->SetString(sourceString.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Parse(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 2) { + pContext->ThrowParamCountMismatchException(L"Parse"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if (ValueIsNull(pThis, argTwo.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString szPattern = ValueToUTF8String(argOne.get()); + ByteString szValue = ValueToUTF8String(argTwo.get()); + CXFA_Document* pDoc = pContext->GetDocument(); + CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); + CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); + ASSERT(pThisNode); + + IFX_Locale* pLocale = pThisNode->GetLocale(); + WideString wsPattern = WideString::FromUTF8(szPattern.AsStringView()); + WideString wsValue = WideString::FromUTF8(szValue.AsStringView()); + uint32_t patternType; + if (PatternStringType(szPattern.AsStringView(), patternType)) { + CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, + pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetString( + localeValue.GetValue().UTF8Encode().AsStringView()); + return; + } + + switch (patternType) { + case XFA_VT_DATETIME: { + auto iTChar = wsPattern.Find(L'T'); + if (!iTChar.has_value()) { + args.GetReturnValue()->SetString(""); + return; + } + WideString wsDatePattern(L"date{" + wsPattern.Left(iTChar.value()) + + L"} "); + WideString wsTimePattern( + L"time{" + + wsPattern.Right(wsPattern.GetLength() - (iTChar.value() + 1)) + L"}"); + wsPattern = wsDatePattern + wsTimePattern; + CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, + pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetString( + localeValue.GetValue().UTF8Encode().AsStringView()); + return; + } + case XFA_VT_DATE: { + wsPattern = L"date{" + wsPattern + L"}"; + CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, + pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetString( + localeValue.GetValue().UTF8Encode().AsStringView()); + return; + } + case XFA_VT_TIME: { + wsPattern = L"time{" + wsPattern + L"}"; + CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, + pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetString( + localeValue.GetValue().UTF8Encode().AsStringView()); + return; + } + case XFA_VT_TEXT: { + wsPattern = L"text{" + wsPattern + L"}"; + CXFA_LocaleValue localeValue(XFA_VT_TEXT, wsValue, wsPattern, pLocale, + pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetString( + localeValue.GetValue().UTF8Encode().AsStringView()); + return; + } + case XFA_VT_FLOAT: { + wsPattern = L"num{" + wsPattern + L"}"; + CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsPattern, pLocale, + pMgr); + if (!localeValue.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum()); + return; + } + default: { + WideString wsTestPattern; + wsTestPattern = L"num{" + wsPattern + L"}"; + CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsTestPattern, + pLocale, pMgr); + if (localeValue.IsValid()) { + args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum()); + return; + } + + wsTestPattern = L"text{" + wsPattern + L"}"; + CXFA_LocaleValue localeValue2(XFA_VT_TEXT, wsValue, wsTestPattern, + pLocale, pMgr); + if (!localeValue2.IsValid()) { + args.GetReturnValue()->SetString(""); + return; + } + args.GetReturnValue()->SetString( + localeValue2.GetValue().UTF8Encode().AsStringView()); + return; + } + } +} + +// static +void CFXJSE_FormCalcContext::Replace(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 2 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Replace"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + ByteString oneString; + ByteString twoString; + if (!ValueIsNull(pThis, argOne.get()) && !ValueIsNull(pThis, argTwo.get())) { + oneString = ValueToUTF8String(argOne.get()); + twoString = ValueToUTF8String(argTwo.get()); + } + + ByteString threeString; + if (argc > 2) { + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + threeString = ValueToUTF8String(argThree.get()); + } + + size_t iFindLen = twoString.GetLength(); + std::ostringstream resultString; + size_t iFindIndex = 0; + for (size_t u = 0; u < oneString.GetLength(); ++u) { + char ch = static_cast(oneString[u]); + if (ch != static_cast(twoString[iFindIndex])) { + resultString << ch; + continue; + } + + size_t iTemp = u + 1; + ++iFindIndex; + while (iFindIndex < iFindLen) { + uint8_t chTemp = oneString[iTemp]; + if (chTemp != twoString[iFindIndex]) { + iFindIndex = 0; + break; + } + + ++iTemp; + ++iFindIndex; + } + if (iFindIndex == iFindLen) { + resultString << threeString; + u += iFindLen - 1; + iFindIndex = 0; + } else { + resultString << ch; + } + } + resultString << '\0'; + args.GetReturnValue()->SetString(ByteStringView(resultString.str().c_str())); +} + +// static +void CFXJSE_FormCalcContext::Right(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Right"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + if ((ValueIsNull(pThis, argOne.get())) || + (ValueIsNull(pThis, argTwo.get()))) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString sourceString = ValueToUTF8String(argOne.get()); + int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get())); + args.GetReturnValue()->SetString(sourceString.Right(count).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Rtrim(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Rtrim"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + ByteString sourceString = ValueToUTF8String(argOne.get()); + sourceString.TrimRight(); + args.GetReturnValue()->SetString(sourceString.AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Space(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Space"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + int32_t count = std::max(0, ValueToInteger(pThis, argOne.get())); + std::ostringstream spaceString; + int32_t index = 0; + while (index < count) { + spaceString << ' '; + index++; + } + spaceString << '\0'; + args.GetReturnValue()->SetString(ByteStringView(spaceString.str().c_str())); +} + +// static +void CFXJSE_FormCalcContext::Str(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Str"); + return; + } + + std::unique_ptr numberValue = GetSimpleValue(pThis, args, 0); + if (numberValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + float fNumber = ValueToFloat(pThis, numberValue.get()); + + int32_t iWidth = 10; + if (argc > 1) { + std::unique_ptr widthValue = GetSimpleValue(pThis, args, 1); + iWidth = static_cast(ValueToFloat(pThis, widthValue.get())); + } + + int32_t iPrecision = 0; + if (argc > 2) { + std::unique_ptr precisionValue = + GetSimpleValue(pThis, args, 2); + iPrecision = std::max( + 0, static_cast(ValueToFloat(pThis, precisionValue.get()))); + } + + ByteString formatStr = "%"; + if (iPrecision) { + formatStr += "."; + formatStr += ByteString::FormatInteger(iPrecision); + } + formatStr += "f"; + ByteString numberString = ByteString::Format(formatStr.c_str(), fNumber); + + const char* pData = numberString.c_str(); + int32_t iLength = numberString.GetLength(); + int32_t u = 0; + while (u < iLength) { + if (pData[u] == '.') + break; + + ++u; + } + + std::ostringstream resultBuf; + if (u > iWidth || (iPrecision + u) >= iWidth) { + int32_t i = 0; + while (i < iWidth) { + resultBuf << '*'; + ++i; + } + resultBuf << '\0'; + args.GetReturnValue()->SetString(ByteStringView(resultBuf.str().c_str())); + return; + } + + if (u == iLength) { + if (iLength > iWidth) { + int32_t i = 0; + while (i < iWidth) { + resultBuf << '*'; + ++i; + } + } else { + int32_t i = 0; + while (i < iWidth - iLength) { + resultBuf << ' '; + ++i; + } + resultBuf << pData; + } + args.GetReturnValue()->SetString(ByteStringView(resultBuf.str().c_str())); + return; + } + + int32_t iLeavingSpace = iWidth - u - iPrecision; + if (iPrecision != 0) + iLeavingSpace--; + + int32_t i = 0; + while (i < iLeavingSpace) { + resultBuf << ' '; + ++i; + } + i = 0; + while (i < u) { + resultBuf << pData[i]; + ++i; + } + if (iPrecision != 0) + resultBuf << '.'; + + u++; + i = 0; + while (u < iLength) { + if (i >= iPrecision) + break; + + resultBuf << pData[u]; + ++i; + ++u; + } + while (i < iPrecision) { + resultBuf << '0'; + ++i; + } + resultBuf << '\0'; + args.GetReturnValue()->SetString(ByteStringView(resultBuf.str().c_str())); +} + +// static +void CFXJSE_FormCalcContext::Stuff(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 3 || argc > 4) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Stuff"); + return; + } + + ByteString sourceString; + ByteString insertString; + int32_t iLength = 0; + int32_t iStart = 0; + int32_t iDelete = 0; + std::unique_ptr sourceValue = GetSimpleValue(pThis, args, 0); + std::unique_ptr startValue = GetSimpleValue(pThis, args, 1); + std::unique_ptr deleteValue = GetSimpleValue(pThis, args, 2); + if (!sourceValue->IsNull() && !startValue->IsNull() && + !deleteValue->IsNull()) { + sourceString = ValueToUTF8String(sourceValue.get()); + iLength = sourceString.GetLength(); + iStart = pdfium::clamp( + static_cast(ValueToFloat(pThis, startValue.get())), 1, + iLength); + iDelete = std::max( + 0, static_cast(ValueToFloat(pThis, deleteValue.get()))); + } + + if (argc > 3) { + std::unique_ptr insertValue = GetSimpleValue(pThis, args, 3); + insertString = ValueToUTF8String(insertValue.get()); + } + + iStart -= 1; + std::ostringstream resultString; + int32_t i = 0; + while (i < iStart) { + resultString << static_cast(sourceString[i]); + ++i; + } + resultString << insertString.AsStringView(); + i = iStart + iDelete; + while (i < iLength) { + resultString << static_cast(sourceString[i]); + ++i; + } + resultString << '\0'; + args.GetReturnValue()->SetString(ByteStringView(resultString.str().c_str())); +} + +// static +void CFXJSE_FormCalcContext::Substr(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Substr"); + return; + } + + std::unique_ptr stringValue = GetSimpleValue(pThis, args, 0); + std::unique_ptr startValue = GetSimpleValue(pThis, args, 1); + std::unique_ptr endValue = GetSimpleValue(pThis, args, 2); + if (ValueIsNull(pThis, stringValue.get()) || + (ValueIsNull(pThis, startValue.get())) || + (ValueIsNull(pThis, endValue.get()))) { + args.GetReturnValue()->SetNull(); + return; + } + + int32_t iStart = 0; + int32_t iCount = 0; + ByteString szSourceStr = ValueToUTF8String(stringValue.get()); + int32_t iLength = szSourceStr.GetLength(); + if (iLength == 0) { + args.GetReturnValue()->SetString(""); + return; + } + + iStart = pdfium::clamp( + iLength, 1, static_cast(ValueToFloat(pThis, startValue.get()))); + iCount = + std::max(0, static_cast(ValueToFloat(pThis, endValue.get()))); + + iStart -= 1; + args.GetReturnValue()->SetString( + szSourceStr.Mid(iStart, iCount).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Uuid(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 0 || argc > 1) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Uuid"); + return; + } + + int32_t iNum = 0; + if (argc > 0) { + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + iNum = static_cast(ValueToFloat(pThis, argOne.get())); + } + args.GetReturnValue()->SetString(GUIDString(!!iNum).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Upper(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 2) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Upper"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (ValueIsNull(pThis, argOne.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + CFX_WideTextBuf upperStringBuf; + ByteString argString = ValueToUTF8String(argOne.get()); + WideString wsArgString = WideString::FromUTF8(argString.AsStringView()); + const wchar_t* pData = wsArgString.c_str(); + size_t i = 0; + while (i < wsArgString.GetLength()) { + int32_t ch = pData[i]; + if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE)) + ch -= 32; + else if (ch == 0x101 || ch == 0x103 || ch == 0x105) + ch -= 1; + + upperStringBuf.AppendChar(ch); + ++i; + } + upperStringBuf.AppendChar(0); + + args.GetReturnValue()->SetString( + FX_UTF8Encode(upperStringBuf.AsStringView()).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::WordNum(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + int32_t argc = args.GetLength(); + if (argc < 1 || argc > 3) { + ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"WordNum"); + return; + } + + std::unique_ptr numberValue = GetSimpleValue(pThis, args, 0); + if (numberValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + float fNumber = ValueToFloat(pThis, numberValue.get()); + + int32_t iIdentifier = 0; + if (argc > 1) { + std::unique_ptr identifierValue = + GetSimpleValue(pThis, args, 1); + if (identifierValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + iIdentifier = + static_cast(ValueToFloat(pThis, identifierValue.get())); + } + + ByteString localeString; + if (argc > 2) { + std::unique_ptr localeValue = GetSimpleValue(pThis, args, 2); + if (localeValue->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + localeString = ValueToUTF8String(localeValue.get()); + } + + if (fNumber < 0.0f || fNumber > 922337203685477550.0f) { + args.GetReturnValue()->SetString("*"); + return; + } + + args.GetReturnValue()->SetString( + WordUS(ByteString::Format("%.2f", fNumber), iIdentifier).AsStringView()); +} + +// static +ByteString CFXJSE_FormCalcContext::TrillionUS(const ByteStringView& szData) { + std::ostringstream strBuf; + ByteStringView pUnits[] = {"zero", "one", "two", "three", "four", + "five", "six", "seven", "eight", "nine"}; + ByteStringView pCapUnits[] = {"Zero", "One", "Two", "Three", "Four", + "Five", "Six", "Seven", "Eight", "Nine"}; + ByteStringView pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", + "Eighteen", "Nineteen"}; + ByteStringView pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty", + "Sixty", "Seventy", "Eighty", "Ninety"}; + ByteStringView pComm[] = {" Hundred ", " Thousand ", " Million ", " Billion ", + "Trillion"}; + const char* pData = szData.unterminated_c_str(); + int32_t iLength = szData.GetLength(); + int32_t iComm = 0; + if (iLength > 12) + iComm = 4; + else if (iLength > 9) + iComm = 3; + else if (iLength > 6) + iComm = 2; + else if (iLength > 3) + iComm = 1; + + int32_t iFirstCount = iLength % 3; + if (iFirstCount == 0) + iFirstCount = 3; + + int32_t iIndex = 0; + if (iFirstCount == 3) { + if (pData[iIndex] != '0') { + strBuf << pCapUnits[pData[iIndex] - '0']; + strBuf << pComm[0]; + } + if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } else { + if (pData[iIndex + 1] > '1') { + strBuf << pLastTens[pData[iIndex + 1] - '2']; + strBuf << "-"; + strBuf << pUnits[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '1') { + strBuf << pTens[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } + } + iIndex += 3; + } else if (iFirstCount == 2) { + if (pData[iIndex] == '0') { + strBuf << pCapUnits[pData[iIndex + 1] - '0']; + } else { + if (pData[iIndex] > '1') { + strBuf << pLastTens[pData[iIndex] - '2']; + strBuf << "-"; + strBuf << pUnits[pData[iIndex + 1] - '0']; + } else if (pData[iIndex] == '1') { + strBuf << pTens[pData[iIndex + 1] - '0']; + } else if (pData[iIndex] == '0') { + strBuf << pCapUnits[pData[iIndex + 1] - '0']; + } + } + iIndex += 2; + } else if (iFirstCount == 1) { + strBuf << pCapUnits[pData[iIndex] - '0']; + iIndex += 1; + } + if (iLength > 3 && iFirstCount > 0) { + strBuf << pComm[iComm]; + --iComm; + } + while (iIndex < iLength) { + if (pData[iIndex] != '0') { + strBuf << pCapUnits[pData[iIndex] - '0']; + strBuf << pComm[0]; + } + if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } else { + if (pData[iIndex + 1] > '1') { + strBuf << pLastTens[pData[iIndex + 1] - '2']; + strBuf << "-"; + strBuf << pUnits[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '1') { + strBuf << pTens[pData[iIndex + 2] - '0']; + } else if (pData[iIndex + 1] == '0') { + strBuf << pCapUnits[pData[iIndex + 2] - '0']; + } + } + if (iIndex < iLength - 3) { + strBuf << pComm[iComm]; + --iComm; + } + iIndex += 3; + } + return ByteString(strBuf); +} + +// static +ByteString CFXJSE_FormCalcContext::WordUS(const ByteString& szData, + int32_t iStyle) { + const char* pData = szData.c_str(); + int32_t iLength = szData.GetLength(); + if (iStyle < 0 || iStyle > 2) { + return ByteString(); + } + + std::ostringstream strBuf; + + int32_t iIndex = 0; + while (iIndex < iLength) { + if (pData[iIndex] == '.') + break; + ++iIndex; + } + int32_t iInteger = iIndex; + iIndex = 0; + while (iIndex < iInteger) { + int32_t iCount = (iInteger - iIndex) % 12; + if (!iCount && iInteger - iIndex > 0) + iCount = 12; + + strBuf << TrillionUS(ByteStringView(pData + iIndex, iCount)); + iIndex += iCount; + if (iIndex < iInteger) + strBuf << " Trillion "; + } + + if (iStyle > 0) + strBuf << " Dollars"; + + if (iStyle > 1 && iInteger < iLength) { + strBuf << " And "; + iIndex = iInteger + 1; + while (iIndex < iLength) { + int32_t iCount = (iLength - iIndex) % 12; + if (!iCount && iLength - iIndex > 0) + iCount = 12; + + strBuf << TrillionUS(ByteStringView(pData + iIndex, iCount)); + iIndex += iCount; + if (iIndex < iLength) + strBuf << " Trillion "; + } + strBuf << " Cents"; + } + return ByteString(strBuf); +} + +// static +void CFXJSE_FormCalcContext::Get(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"Get"); + return; + } + + CXFA_Document* pDoc = pContext->GetDocument(); + if (!pDoc) + return; + + IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider(); + if (!pAppProvider) + return; + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + ByteString urlString = ValueToUTF8String(argOne.get()); + RetainPtr pFile = + pAppProvider->DownloadURL(WideString::FromUTF8(urlString.AsStringView())); + if (!pFile) + return; + + int32_t size = pFile->GetSize(); + std::vector dataBuf(size); + pFile->ReadBlock(dataBuf.data(), size); + args.GetReturnValue()->SetString(ByteStringView(dataBuf)); +} + +// static +void CFXJSE_FormCalcContext::Post(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + int32_t argc = args.GetLength(); + if (argc < 2 || argc > 5) { + pContext->ThrowParamCountMismatchException(L"Post"); + return; + } + + CXFA_Document* pDoc = pContext->GetDocument(); + if (!pDoc) + return; + + IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider(); + if (!pAppProvider) + return; + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + ByteString bsURL = ValueToUTF8String(argOne.get()); + + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + ByteString bsData = ValueToUTF8String(argTwo.get()); + + ByteString bsContentType; + if (argc > 2) { + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + bsContentType = ValueToUTF8String(argThree.get()); + } + + ByteString bsEncode; + if (argc > 3) { + std::unique_ptr argFour = GetSimpleValue(pThis, args, 3); + bsEncode = ValueToUTF8String(argFour.get()); + } + + ByteString bsHeader; + if (argc > 4) { + std::unique_ptr argFive = GetSimpleValue(pThis, args, 4); + bsHeader = ValueToUTF8String(argFive.get()); + } + + WideString decodedResponse; + if (!pAppProvider->PostRequestURL( + WideString::FromUTF8(bsURL.AsStringView()), + WideString::FromUTF8(bsData.AsStringView()), + WideString::FromUTF8(bsContentType.AsStringView()), + WideString::FromUTF8(bsEncode.AsStringView()), + WideString::FromUTF8(bsHeader.AsStringView()), decodedResponse)) { + pContext->ThrowServerDeniedException(); + return; + } + args.GetReturnValue()->SetString(decodedResponse.UTF8Encode().AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::Put(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + int32_t argc = args.GetLength(); + if (argc < 2 || argc > 3) { + pContext->ThrowParamCountMismatchException(L"Put"); + return; + } + + CXFA_Document* pDoc = pContext->GetDocument(); + if (!pDoc) + return; + + IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider(); + if (!pAppProvider) + return; + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + ByteString bsURL = ValueToUTF8String(argOne.get()); + + std::unique_ptr argTwo = GetSimpleValue(pThis, args, 1); + ByteString bsData = ValueToUTF8String(argTwo.get()); + + ByteString bsEncode; + if (argc > 2) { + std::unique_ptr argThree = GetSimpleValue(pThis, args, 2); + bsEncode = ValueToUTF8String(argThree.get()); + } + + if (!pAppProvider->PutRequestURL( + WideString::FromUTF8(bsURL.AsStringView()), + WideString::FromUTF8(bsData.AsStringView()), + WideString::FromUTF8(bsEncode.AsStringView()))) { + pContext->ThrowServerDeniedException(); + return; + } + + args.GetReturnValue()->SetString(""); +} + +// static +void CFXJSE_FormCalcContext::assign_value_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 2) { + pContext->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr lValue = args.GetValue(0); + std::unique_ptr rValue = GetSimpleValue(pThis, args, 1); + if (lValue->IsArray()) { + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + auto leftLengthValue = pdfium::MakeUnique(pIsolate); + lValue->GetObjectProperty("length", leftLengthValue.get()); + int32_t iLeftLength = leftLengthValue->ToInteger(); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto propertyValue = pdfium::MakeUnique(pIsolate); + lValue->GetObjectPropertyByIdx(1, propertyValue.get()); + if (propertyValue->IsNull()) { + for (int32_t i = 2; i < iLeftLength; i++) { + lValue->GetObjectPropertyByIdx(i, jsObjectValue.get()); + if (!SetObjectDefaultValue(jsObjectValue.get(), rValue.get())) { + pContext->ThrowNoDefaultPropertyException(szFuncName); + return; + } + } + } else { + for (int32_t i = 2; i < iLeftLength; i++) { + lValue->GetObjectPropertyByIdx(i, jsObjectValue.get()); + jsObjectValue->SetObjectProperty( + propertyValue->ToString().AsStringView(), rValue.get()); + } + } + } else if (lValue->IsObject()) { + if (!SetObjectDefaultValue(lValue.get(), rValue.get())) { + pContext->ThrowNoDefaultPropertyException(szFuncName); + return; + } + } + args.GetReturnValue()->Assign(rValue.get()); +} + +// static +void CFXJSE_FormCalcContext::logical_or_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() && argSecond->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + float first = ValueToFloat(pThis, argFirst.get()); + float second = ValueToFloat(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first || second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::logical_and_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() && argSecond->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + float first = ValueToFloat(pThis, argFirst.get()); + float second = ValueToFloat(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first && second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::equality_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + if (fm_ref_equal(pThis, args)) { + args.GetReturnValue()->SetInteger(1); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() || argSecond->IsNull()) { + args.GetReturnValue()->SetInteger( + (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0); + return; + } + + if (argFirst->IsString() && argSecond->IsString()) { + args.GetReturnValue()->SetInteger(argFirst->ToString() == + argSecond->ToString()); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first == second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::notequality_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + if (fm_ref_equal(pThis, args)) { + args.GetReturnValue()->SetInteger(0); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() || argSecond->IsNull()) { + args.GetReturnValue()->SetInteger( + (argFirst->IsNull() && argSecond->IsNull()) ? 0 : 1); + return; + } + + if (argFirst->IsString() && argSecond->IsString()) { + args.GetReturnValue()->SetInteger(argFirst->ToString() != + argSecond->ToString()); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger(first != second); +} + +// static +bool CFXJSE_FormCalcContext::fm_ref_equal(CFXJSE_Value* pThis, + CFXJSE_Arguments& args) { + std::unique_ptr argFirst = args.GetValue(0); + std::unique_ptr argSecond = args.GetValue(1); + if (!argFirst->IsArray() || !argSecond->IsArray()) + return false; + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + auto firstFlagValue = pdfium::MakeUnique(pIsolate); + auto secondFlagValue = pdfium::MakeUnique(pIsolate); + argFirst->GetObjectPropertyByIdx(0, firstFlagValue.get()); + argSecond->GetObjectPropertyByIdx(0, secondFlagValue.get()); + if (firstFlagValue->ToInteger() != 3 || secondFlagValue->ToInteger() != 3) + return false; + + auto firstJSObject = pdfium::MakeUnique(pIsolate); + auto secondJSObject = pdfium::MakeUnique(pIsolate); + argFirst->GetObjectPropertyByIdx(2, firstJSObject.get()); + argSecond->GetObjectPropertyByIdx(2, secondJSObject.get()); + if (firstJSObject->IsNull() || secondJSObject->IsNull()) + return false; + + return (firstJSObject->ToHostObject(nullptr) == + secondJSObject->ToHostObject(nullptr)); +} + +// static +void CFXJSE_FormCalcContext::less_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() || argSecond->IsNull()) { + args.GetReturnValue()->SetInteger(0); + return; + } + + if (argFirst->IsString() && argSecond->IsString()) { + int result = + argFirst->ToString().Compare(argSecond->ToString().AsStringView()) < 0; + args.GetReturnValue()->SetInteger(result); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first < second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::lessequal_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() || argSecond->IsNull()) { + args.GetReturnValue()->SetInteger( + (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0); + return; + } + + if (argFirst->IsString() && argSecond->IsString()) { + int result = + argFirst->ToString().Compare(argSecond->ToString().AsStringView()) <= 0; + args.GetReturnValue()->SetInteger(result); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first <= second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::greater_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() || argSecond->IsNull()) { + args.GetReturnValue()->SetInteger(0); + return; + } + + if (argFirst->IsString() && argSecond->IsString()) { + int result = + argFirst->ToString().Compare(argSecond->ToString().AsStringView()) > 0; + args.GetReturnValue()->SetInteger(result); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first > second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::greaterequal_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() || argSecond->IsNull()) { + args.GetReturnValue()->SetInteger( + (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0); + return; + } + + if (argFirst->IsString() && argSecond->IsString()) { + int result = + argFirst->ToString().Compare(argSecond->ToString().AsStringView()) >= 0; + args.GetReturnValue()->SetInteger(result); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetInteger((first >= second) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::plus_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = args.GetValue(0); + std::unique_ptr argSecond = args.GetValue(1); + if (ValueIsNull(pThis, argFirst.get()) && + ValueIsNull(pThis, argSecond.get())) { + args.GetReturnValue()->SetNull(); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetDouble(first + second); +} + +// static +void CFXJSE_FormCalcContext::minus_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() && argSecond->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetDouble(first - second); +} + +// static +void CFXJSE_FormCalcContext::multiple_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 2) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() && argSecond->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + double second = ValueToDouble(pThis, argSecond.get()); + args.GetReturnValue()->SetDouble(first * second); +} + +// static +void CFXJSE_FormCalcContext::divide_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 2) { + pContext->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argFirst = GetSimpleValue(pThis, args, 0); + std::unique_ptr argSecond = GetSimpleValue(pThis, args, 1); + if (argFirst->IsNull() && argSecond->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + double second = ValueToDouble(pThis, argSecond.get()); + if (second == 0.0) { + pContext->ThrowDivideByZeroException(); + return; + } + + double first = ValueToDouble(pThis, argFirst.get()); + args.GetReturnValue()->SetDouble(first / second); +} + +// static +void CFXJSE_FormCalcContext::positive_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + args.GetReturnValue()->SetDouble(0.0 + ValueToDouble(pThis, argOne.get())); +} + +// static +void CFXJSE_FormCalcContext::negative_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + args.GetReturnValue()->SetDouble(0.0 - ValueToDouble(pThis, argOne.get())); +} + +// static +void CFXJSE_FormCalcContext::logical_not_operator( + CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + if (argOne->IsNull()) { + args.GetReturnValue()->SetNull(); + return; + } + + double first = ValueToDouble(pThis, argOne.get()); + args.GetReturnValue()->SetInteger((first == 0.0) ? 1 : 0); +} + +// static +void CFXJSE_FormCalcContext::dot_accessor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + int32_t argc = args.GetLength(); + if (argc < 4 || argc > 5) { + pContext->ThrowCompilerErrorException(); + return; + } + + bool bIsStar = true; + int32_t iIndexValue = 0; + if (argc > 4) { + bIsStar = false; + iIndexValue = ValueToInteger(pThis, args.GetValue(4).get()); + } + + ByteString szName = args.GetUTF8String(2); + ByteString szSomExp = GenerateSomExpression( + szName.AsStringView(), args.GetInt32(3), iIndexValue, bIsStar); + + std::unique_ptr argAccessor = args.GetValue(0); + if (argAccessor->IsArray()) { + auto pLengthValue = pdfium::MakeUnique(pIsolate); + argAccessor->GetObjectProperty("length", pLengthValue.get()); + int32_t iLength = pLengthValue->ToInteger(); + if (iLength < 3) { + pContext->ThrowArgumentMismatchException(); + return; + } + + auto hJSObjValue = pdfium::MakeUnique(pIsolate); + std::vector>> resolveValues( + iLength - 2); + bool bAttribute = false; + int32_t iCounter = 0; + for (int32_t i = 2; i < iLength; i++) { + argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get()); + + XFA_RESOLVENODE_RS resolveNodeRS; + if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringView(), + &resolveNodeRS, true, szName.IsEmpty())) { + ParseResolveResult(pThis, resolveNodeRS, hJSObjValue.get(), + &resolveValues[i - 2], &bAttribute); + iCounter += resolveValues[i - 2].size(); + } + } + if (iCounter < 1) { + pContext->ThrowPropertyNotInObjectException( + WideString::FromUTF8(szName.AsStringView()), + WideString::FromUTF8(szSomExp.AsStringView())); + return; + } + + std::vector> values; + for (int32_t i = 0; i < iCounter + 2; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); + + values[0]->SetInteger(1); + if (bAttribute) + values[1]->SetString(szName.AsStringView()); + else + values[1]->SetNull(); + + int32_t iIndex = 2; + for (int32_t i = 0; i < iLength - 2; i++) { + for (size_t j = 0; j < resolveValues[i].size(); j++) { + values[iIndex]->Assign(resolveValues[i][j].get()); + iIndex++; + } + } + args.GetReturnValue()->SetArray(values); + return; + } + + XFA_RESOLVENODE_RS resolveNodeRS; + bool iRet = false; + ByteString bsAccessorName = args.GetUTF8String(1); + if (argAccessor->IsObject() || + (argAccessor->IsNull() && bsAccessorName.IsEmpty())) { + iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringView(), + &resolveNodeRS, true, szName.IsEmpty()); + } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() && + GetObjectForName(pThis, argAccessor.get(), + bsAccessorName.AsStringView())) { + iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringView(), + &resolveNodeRS, true, szName.IsEmpty()); + } + if (!iRet) { + pContext->ThrowPropertyNotInObjectException( + WideString::FromUTF8(szName.AsStringView()), + WideString::FromUTF8(szSomExp.AsStringView())); + return; + } + + std::vector> resolveValues; + bool bAttribute = false; + ParseResolveResult(pThis, resolveNodeRS, argAccessor.get(), &resolveValues, + &bAttribute); + + std::vector> values; + for (size_t i = 0; i < resolveValues.size() + 2; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); + + values[0]->SetInteger(1); + if (bAttribute) + values[1]->SetString(szName.AsStringView()); + else + values[1]->SetNull(); + + for (size_t i = 0; i < resolveValues.size(); i++) + values[i + 2]->Assign(resolveValues[i].get()); + + args.GetReturnValue()->SetArray(values); +} + +// static +void CFXJSE_FormCalcContext::dotdot_accessor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + int32_t argc = args.GetLength(); + if (argc < 4 || argc > 5) { + pContext->ThrowCompilerErrorException(); + return; + } + + bool bIsStar = true; + int32_t iIndexValue = 0; + if (argc > 4) { + bIsStar = false; + iIndexValue = ValueToInteger(pThis, args.GetValue(4).get()); + } + + ByteString szName = args.GetUTF8String(2); + ByteString szSomExp = GenerateSomExpression( + szName.AsStringView(), args.GetInt32(3), iIndexValue, bIsStar); + + std::unique_ptr argAccessor = args.GetValue(0); + if (argAccessor->IsArray()) { + auto pLengthValue = pdfium::MakeUnique(pIsolate); + argAccessor->GetObjectProperty("length", pLengthValue.get()); + int32_t iLength = pLengthValue->ToInteger(); + if (iLength < 3) { + pContext->ThrowArgumentMismatchException(); + return; + } + + int32_t iCounter = 0; + + std::vector>> resolveValues( + iLength - 2); + auto hJSObjValue = pdfium::MakeUnique(pIsolate); + bool bAttribute = false; + for (int32_t i = 2; i < iLength; i++) { + argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get()); + XFA_RESOLVENODE_RS resolveNodeRS; + if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringView(), + &resolveNodeRS, false, false)) { + ParseResolveResult(pThis, resolveNodeRS, hJSObjValue.get(), + &resolveValues[i - 2], &bAttribute); + iCounter += resolveValues[i - 2].size(); + } + } + if (iCounter < 1) { + pContext->ThrowPropertyNotInObjectException( + WideString::FromUTF8(szName.AsStringView()), + WideString::FromUTF8(szSomExp.AsStringView())); + return; + } + + std::vector> values; + for (int32_t i = 0; i < iCounter + 2; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); + + values[0]->SetInteger(1); + if (bAttribute) + values[1]->SetString(szName.AsStringView()); + else + values[1]->SetNull(); + + int32_t iIndex = 2; + for (int32_t i = 0; i < iLength - 2; i++) { + for (size_t j = 0; j < resolveValues[i].size(); j++) { + values[iIndex]->Assign(resolveValues[i][j].get()); + iIndex++; + } + } + args.GetReturnValue()->SetArray(values); + return; + } + + XFA_RESOLVENODE_RS resolveNodeRS; + bool iRet = false; + ByteString bsAccessorName = args.GetUTF8String(1); + if (argAccessor->IsObject() || + (argAccessor->IsNull() && bsAccessorName.IsEmpty())) { + iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringView(), + &resolveNodeRS, false, false); + } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() && + GetObjectForName(pThis, argAccessor.get(), + bsAccessorName.AsStringView())) { + iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringView(), + &resolveNodeRS, false, false); + } + if (!iRet) { + pContext->ThrowPropertyNotInObjectException( + WideString::FromUTF8(szName.AsStringView()), + WideString::FromUTF8(szSomExp.AsStringView())); + return; + } + + std::vector> resolveValues; + bool bAttribute = false; + ParseResolveResult(pThis, resolveNodeRS, argAccessor.get(), &resolveValues, + &bAttribute); + + std::vector> values; + for (size_t i = 0; i < resolveValues.size() + 2; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); + + values[0]->SetInteger(1); + if (bAttribute) + values[1]->SetString(szName.AsStringView()); + else + values[1]->SetNull(); + + for (size_t i = 0; i < resolveValues.size(); i++) + values[i + 2]->Assign(resolveValues[i].get()); + + args.GetReturnValue()->SetArray(values); +} + +// static +void CFXJSE_FormCalcContext::eval_translation(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 1) { + pContext->ThrowParamCountMismatchException(L"Eval"); + return; + } + + std::unique_ptr argOne = GetSimpleValue(pThis, args, 0); + ByteString argString = ValueToUTF8String(argOne.get()); + if (argString.IsEmpty()) { + pContext->ThrowArgumentMismatchException(); + return; + } + + WideString scriptString = WideString::FromUTF8(argString.AsStringView()); + CFX_WideTextBuf wsJavaScriptBuf; + if (!CFXJSE_FormCalcContext::Translate(scriptString.AsStringView(), + &wsJavaScriptBuf)) { + pContext->ThrowCompilerErrorException(); + return; + } + + args.GetReturnValue()->SetString( + FX_UTF8Encode(wsJavaScriptBuf.AsStringView()).AsStringView()); +} + +// static +void CFXJSE_FormCalcContext::is_fm_object(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + args.GetReturnValue()->SetBoolean(false); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + args.GetReturnValue()->SetBoolean(argOne->IsObject()); +} + +// static +void CFXJSE_FormCalcContext::is_fm_array(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + args.GetReturnValue()->SetBoolean(false); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + args.GetReturnValue()->SetBoolean(argOne->IsArray()); +} + +// static +void CFXJSE_FormCalcContext::get_fm_value(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 1) { + pContext->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (argOne->IsArray()) { + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectPropertyByIdx(1, propertyValue.get()); + argOne->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), args.GetReturnValue()); + return; + } + + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + args.GetReturnValue()); + return; + } + + if (argOne->IsObject()) { + GetObjectDefaultValue(argOne.get(), args.GetReturnValue()); + return; + } + + args.GetReturnValue()->Assign(argOne.get()); +} + +// static +void CFXJSE_FormCalcContext::get_fm_jsobj(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + if (args.GetLength() != 1) { + ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); + return; + } + + std::unique_ptr argOne = args.GetValue(0); + if (!argOne->IsArray()) { + args.GetReturnValue()->Assign(argOne.get()); + return; + } + +#ifndef NDEBUG + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + auto lengthValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectProperty("length", lengthValue.get()); + ASSERT(lengthValue->ToInteger() >= 3); +#endif + + argOne->GetObjectPropertyByIdx(2, args.GetReturnValue()); +} + +// static +void CFXJSE_FormCalcContext::fm_var_filter(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + if (args.GetLength() != 1) { + pContext->ThrowCompilerErrorException(); + return; + } + + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + std::unique_ptr argOne = args.GetValue(0); + if (!argOne->IsArray()) { + std::unique_ptr simpleValue = GetSimpleValue(pThis, args, 0); + args.GetReturnValue()->Assign(simpleValue.get()); + return; + } + +#ifndef NDEBUG + auto lengthValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectProperty("length", lengthValue.get()); + ASSERT(lengthValue->ToInteger() >= 3); +#endif + + auto flagsValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectPropertyByIdx(0, flagsValue.get()); + int32_t iFlags = flagsValue->ToInteger(); + if (iFlags != 3 && iFlags != 4) { + std::unique_ptr simpleValue = GetSimpleValue(pThis, args, 0); + args.GetReturnValue()->Assign(simpleValue.get()); + return; + } + + if (iFlags == 4) { + std::vector> values; + for (int32_t i = 0; i < 3; i++) + values.push_back(pdfium::MakeUnique(pIsolate)); + + values[0]->SetInteger(3); + values[1]->SetNull(); + values[2]->SetNull(); + args.GetReturnValue()->SetArray(values); + return; + } + + auto objectValue = pdfium::MakeUnique(pIsolate); + argOne->GetObjectPropertyByIdx(2, objectValue.get()); + if (objectValue->IsNull()) { + pContext->ThrowCompilerErrorException(); + return; + } + args.GetReturnValue()->Assign(argOne.get()); +} + +// static +void CFXJSE_FormCalcContext::concat_fm_object(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args) { + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + uint32_t iLength = 0; + int32_t argc = args.GetLength(); + std::vector> argValues; + for (int32_t i = 0; i < argc; i++) { + argValues.push_back(args.GetValue(i)); + if (argValues[i]->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValues[i]->GetObjectProperty("length", lengthValue.get()); + int32_t length = lengthValue->ToInteger(); + iLength = iLength + ((length > 2) ? (length - 2) : 0); + } + iLength += 1; + } + + std::vector> returnValues; + for (int32_t i = 0; i < (int32_t)iLength; i++) + returnValues.push_back(pdfium::MakeUnique(pIsolate)); + + int32_t index = 0; + for (int32_t i = 0; i < argc; i++) { + if (argValues[i]->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argValues[i]->GetObjectProperty("length", lengthValue.get()); + + int32_t length = lengthValue->ToInteger(); + for (int32_t j = 2; j < length; j++) { + argValues[i]->GetObjectPropertyByIdx(j, returnValues[index].get()); + index++; + } + } + returnValues[index]->Assign(argValues[i].get()); + index++; + } + args.GetReturnValue()->SetArray(returnValues); +} + +// static +std::unique_ptr CFXJSE_FormCalcContext::GetSimpleValue( + CFXJSE_Value* pThis, + CFXJSE_Arguments& args, + uint32_t index) { + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + ASSERT(index < (uint32_t)args.GetLength()); + + std::unique_ptr argIndex = args.GetValue(index); + if (!argIndex->IsArray() && !argIndex->IsObject()) + return argIndex; + + if (argIndex->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argIndex->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + auto simpleValue = pdfium::MakeUnique(pIsolate); + if (iLength < 3) { + simpleValue.get()->SetUndefined(); + return simpleValue; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + argIndex->GetObjectPropertyByIdx(1, propertyValue.get()); + argIndex->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), simpleValue.get()); + return simpleValue; + } + + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + simpleValue.get()); + return simpleValue; + } + + auto defaultValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(argIndex.get(), defaultValue.get()); + return defaultValue; +} + +// static +bool CFXJSE_FormCalcContext::ValueIsNull(CFXJSE_Value* pThis, + CFXJSE_Value* arg) { + if (!arg || arg->IsNull()) + return true; + + if (!arg->IsArray() && !arg->IsObject()) + return false; + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + if (arg->IsArray()) { + int32_t iLength = hvalue_get_array_length(pThis, arg); + if (iLength < 3) + return true; + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + arg->GetObjectPropertyByIdx(1, propertyValue.get()); + arg->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + auto defaultValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(jsObjectValue.get(), defaultValue.get()); + return defaultValue->IsNull(); + } + + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + newPropertyValue.get()); + return newPropertyValue->IsNull(); + } + + auto defaultValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(arg, defaultValue.get()); + return defaultValue->IsNull(); +} + +// static +int32_t CFXJSE_FormCalcContext::hvalue_get_array_length(CFXJSE_Value* pThis, + CFXJSE_Value* arg) { + if (!arg || !arg->IsArray()) + return 0; + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + auto lengthValue = pdfium::MakeUnique(pIsolate); + arg->GetObjectProperty("length", lengthValue.get()); + return lengthValue->ToInteger(); +} + +// static +bool CFXJSE_FormCalcContext::simpleValueCompare(CFXJSE_Value* pThis, + CFXJSE_Value* firstValue, + CFXJSE_Value* secondValue) { + if (!firstValue) + return false; + + if (firstValue->IsString()) { + ByteString firstString = ValueToUTF8String(firstValue); + ByteString secondString = ValueToUTF8String(secondValue); + return firstString == secondString; + } + if (firstValue->IsNumber()) { + float first = ValueToFloat(pThis, firstValue); + float second = ValueToFloat(pThis, secondValue); + return first == second; + } + if (firstValue->IsBoolean()) + return firstValue->ToBoolean() == secondValue->ToBoolean(); + + return firstValue->IsNull() && secondValue && secondValue->IsNull(); +} + +// static +void CFXJSE_FormCalcContext::unfoldArgs( + CFXJSE_Value* pThis, + CFXJSE_Arguments& args, + std::vector>* resultValues, + int32_t iStart) { + resultValues->clear(); + + int32_t iCount = 0; + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + int32_t argc = args.GetLength(); + std::vector> argsValue; + for (int32_t i = 0; i < argc - iStart; i++) { + argsValue.push_back(args.GetValue(i + iStart)); + if (argsValue[i]->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argsValue[i]->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + iCount += ((iLength > 2) ? (iLength - 2) : 0); + } else { + iCount += 1; + } + } + + for (int32_t i = 0; i < iCount; i++) + resultValues->push_back(pdfium::MakeUnique(pIsolate)); + + int32_t index = 0; + for (int32_t i = 0; i < argc - iStart; i++) { + if (argsValue[i]->IsArray()) { + auto lengthValue = pdfium::MakeUnique(pIsolate); + argsValue[i]->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength < 3) + continue; + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + argsValue[i]->GetObjectPropertyByIdx(1, propertyValue.get()); + if (propertyValue->IsNull()) { + for (int32_t j = 2; j < iLength; j++) { + argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get()); + GetObjectDefaultValue(jsObjectValue.get(), + (*resultValues)[index].get()); + index++; + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + propertyValue->ToString().AsStringView(), + (*resultValues)[index].get()); + index++; + } + } + } else if (argsValue[i]->IsObject()) { + GetObjectDefaultValue(argsValue[i].get(), (*resultValues)[index].get()); + index++; + } else { + (*resultValues)[index]->Assign(argsValue[i].get()); + index++; + } + } +} + +// static +void CFXJSE_FormCalcContext::GetObjectDefaultValue( + CFXJSE_Value* pValue, + CFXJSE_Value* pDefaultValue) { + CXFA_Node* pNode = ToNode(CFXJSE_Engine::ToObject(pValue, nullptr)); + if (!pNode) { + pDefaultValue->SetNull(); + return; + } + pNode->JSObject()->Script_Som_DefaultValue(pDefaultValue, false, + XFA_Attribute::Unknown); +} + +// static +bool CFXJSE_FormCalcContext::SetObjectDefaultValue(CFXJSE_Value* pValue, + CFXJSE_Value* hNewValue) { + CXFA_Node* pNode = ToNode(CFXJSE_Engine::ToObject(pValue, nullptr)); + if (!pNode) + return false; + + pNode->JSObject()->Script_Som_DefaultValue(hNewValue, true, + XFA_Attribute::Unknown); + return true; +} + +// static +ByteString CFXJSE_FormCalcContext::GenerateSomExpression( + const ByteStringView& szName, + int32_t iIndexFlags, + int32_t iIndexValue, + bool bIsStar) { + if (bIsStar) + return ByteString(szName, "[*]"); + + if (iIndexFlags == 0) + return ByteString(szName); + + if (iIndexFlags == 1 || iIndexValue == 0) { + return ByteString(szName, "[") + ByteString::FormatInteger(iIndexValue) + + "]"; + } + ByteString szSomExp; + if (iIndexFlags == 2) { + szSomExp = (iIndexValue < 0) ? (szName + "[-") : (szName + "[+"); + iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue; + szSomExp += ByteString::FormatInteger(iIndexValue); + szSomExp += "]"; + } else { + szSomExp = (iIndexValue < 0) ? (szName + "[") : (szName + "[-"); + iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue; + szSomExp += ByteString::FormatInteger(iIndexValue); + szSomExp += "]"; + } + return szSomExp; +} + +// static +bool CFXJSE_FormCalcContext::GetObjectForName( + CFXJSE_Value* pThis, + CFXJSE_Value* accessorValue, + const ByteStringView& szAccessorName) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return false; + + CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext(); + XFA_RESOLVENODE_RS resolveNodeRS; + uint32_t dwFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; + bool iRet = pScriptContext->ResolveObjects( + pScriptContext->GetThisObject(), + WideString::FromUTF8(szAccessorName).AsStringView(), &resolveNodeRS, + dwFlags, nullptr); + if (iRet && resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + accessorValue->Assign( + pScriptContext->GetJSValueFromMap(resolveNodeRS.objects.front())); + return true; + } + return false; +} + +// static +bool CFXJSE_FormCalcContext::ResolveObjects(CFXJSE_Value* pThis, + CFXJSE_Value* pRefValue, + const ByteStringView& bsSomExp, + XFA_RESOLVENODE_RS* resolveNodeRS, + bool bdotAccessor, + bool bHasNoResolveName) { + CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); + if (!pDoc) + return false; + + WideString wsSomExpression = WideString::FromUTF8(bsSomExp); + CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext(); + CXFA_Object* pNode = nullptr; + uint32_t dFlags = 0UL; + if (bdotAccessor) { + if (pRefValue && pRefValue->IsNull()) { + pNode = pScriptContext->GetThisObject(); + dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; + } else { + pNode = CFXJSE_Engine::ToObject(pRefValue, nullptr); + ASSERT(pNode); + if (bHasNoResolveName) { + WideString wsName; + if (CXFA_Node* pXFANode = pNode->AsNode()) { + Optional ret = + pXFANode->JSObject()->TryAttribute(XFA_Attribute::Name, false); + if (ret) + wsName = *ret; + } + if (wsName.IsEmpty()) + wsName = L"#" + pNode->GetClassName(); + + wsSomExpression = wsName + wsSomExpression; + dFlags = XFA_RESOLVENODE_Siblings; + } else { + dFlags = (bsSomExp == "*") + ? (XFA_RESOLVENODE_Children) + : (XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | + XFA_RESOLVENODE_Properties); + } + } + } else { + pNode = CFXJSE_Engine::ToObject(pRefValue, nullptr); + dFlags = XFA_RESOLVENODE_AnyChild; + } + return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringView(), + resolveNodeRS, dFlags, nullptr); +} + +// static +void CFXJSE_FormCalcContext::ParseResolveResult( + CFXJSE_Value* pThis, + const XFA_RESOLVENODE_RS& resolveNodeRS, + CFXJSE_Value* pParentValue, + std::vector>* resultValues, + bool* bAttribute) { + ASSERT(bAttribute); + + resultValues->clear(); + + CFXJSE_FormCalcContext* pContext = ToJSContext(pThis, nullptr); + v8::Isolate* pIsolate = pContext->GetScriptRuntime(); + + if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + *bAttribute = false; + CFXJSE_Engine* pScriptContext = pContext->GetDocument()->GetScriptContext(); + for (CXFA_Object* pObject : resolveNodeRS.objects) { + resultValues->push_back(pdfium::MakeUnique(pIsolate)); + resultValues->back()->Assign(pScriptContext->GetJSValueFromMap(pObject)); + } + return; + } + + *bAttribute = true; + if (resolveNodeRS.pScriptAttribute && + resolveNodeRS.pScriptAttribute->eValueType == XFA_ScriptType::Object) { + for (CXFA_Object* pObject : resolveNodeRS.objects) { + auto pValue = pdfium::MakeUnique(pIsolate); + CJX_Object* jsObject = pObject->JSObject(); + (jsObject->*(resolveNodeRS.pScriptAttribute->callback))( + pValue.get(), false, resolveNodeRS.pScriptAttribute->attribute); + + resultValues->push_back(std::move(pValue)); + *bAttribute = false; + } + } + if (!*bAttribute) + return; + if (!pParentValue || !pParentValue->IsObject()) + return; + + resultValues->push_back(pdfium::MakeUnique(pIsolate)); + resultValues->back()->Assign(pParentValue); +} + +// static +int32_t CFXJSE_FormCalcContext::ValueToInteger(CFXJSE_Value* pThis, + CFXJSE_Value* pValue) { + if (!pValue) + return 0; + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + if (pValue->IsArray()) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + pValue->GetObjectPropertyByIdx(1, propertyValue.get()); + pValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + return ValueToInteger(pThis, newPropertyValue.get()); + } + + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + newPropertyValue.get()); + return ValueToInteger(pThis, newPropertyValue.get()); + } + if (pValue->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(pValue, newPropertyValue.get()); + return ValueToInteger(pThis, newPropertyValue.get()); + } + if (pValue->IsString()) + return FXSYS_atoi(pValue->ToString().c_str()); + return pValue->ToInteger(); +} + +// static +float CFXJSE_FormCalcContext::ValueToFloat(CFXJSE_Value* pThis, + CFXJSE_Value* arg) { + if (!arg) + return 0.0f; + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + if (arg->IsArray()) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + arg->GetObjectPropertyByIdx(1, propertyValue.get()); + arg->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + return ValueToFloat(pThis, newPropertyValue.get()); + } + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + newPropertyValue.get()); + return ValueToFloat(pThis, newPropertyValue.get()); + } + if (arg->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(arg, newPropertyValue.get()); + return ValueToFloat(pThis, newPropertyValue.get()); + } + if (arg->IsString()) { + return static_cast( + ByteStringToDouble(arg->ToString().AsStringView())); + } + if (arg->IsUndefined()) + return 0; + + return arg->ToFloat(); +} + +// static +double CFXJSE_FormCalcContext::ValueToDouble(CFXJSE_Value* pThis, + CFXJSE_Value* arg) { + if (!arg) + return 0; + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + if (arg->IsArray()) { + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + arg->GetObjectPropertyByIdx(1, propertyValue.get()); + arg->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) { + GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); + return ValueToDouble(pThis, newPropertyValue.get()); + } + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + newPropertyValue.get()); + return ValueToDouble(pThis, newPropertyValue.get()); + } + if (arg->IsObject()) { + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + GetObjectDefaultValue(arg, newPropertyValue.get()); + return ValueToDouble(pThis, newPropertyValue.get()); + } + if (arg->IsString()) + return ByteStringToDouble(arg->ToString().AsStringView()); + if (arg->IsUndefined()) + return 0; + return arg->ToDouble(); +} + +// static. +double CFXJSE_FormCalcContext::ExtractDouble(CFXJSE_Value* pThis, + CFXJSE_Value* src, + bool* ret) { + ASSERT(ret); + *ret = true; + + if (!src) + return 0; + + if (!src->IsArray()) + return ValueToDouble(pThis, src); + + v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); + auto lengthValue = pdfium::MakeUnique(pIsolate); + src->GetObjectProperty("length", lengthValue.get()); + int32_t iLength = lengthValue->ToInteger(); + if (iLength <= 2) { + *ret = false; + return 0.0; + } + + auto propertyValue = pdfium::MakeUnique(pIsolate); + auto jsObjectValue = pdfium::MakeUnique(pIsolate); + src->GetObjectPropertyByIdx(1, propertyValue.get()); + src->GetObjectPropertyByIdx(2, jsObjectValue.get()); + if (propertyValue->IsNull()) + return ValueToDouble(pThis, jsObjectValue.get()); + + auto newPropertyValue = pdfium::MakeUnique(pIsolate); + jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringView(), + newPropertyValue.get()); + return ValueToDouble(pThis, newPropertyValue.get()); +} + +// static +ByteString CFXJSE_FormCalcContext::ValueToUTF8String(CFXJSE_Value* arg) { + if (!arg || arg->IsNull() || arg->IsUndefined()) + return ByteString(); + if (arg->IsBoolean()) + return arg->ToBoolean() ? "1" : "0"; + return arg->ToString(); +} + +// static. +bool CFXJSE_FormCalcContext::Translate(const WideStringView& wsFormcalc, + CFX_WideTextBuf* wsJavascript) { + if (wsFormcalc.IsEmpty()) { + wsJavascript->Clear(); + return true; + } + + CXFA_FMParser parser(wsFormcalc); + std::unique_ptr func = parser.Parse(); + if (!func || parser.HasError()) + return false; + + CXFA_FMToJavaScriptDepth::Reset(); + if (!func->ToJavaScript(*wsJavascript)) + return false; + + wsJavascript->AppendChar(0); + + return !CXFA_IsTooBig(*wsJavascript); +} + +CFXJSE_FormCalcContext::CFXJSE_FormCalcContext(v8::Isolate* pScriptIsolate, + CFXJSE_Context* pScriptContext, + CXFA_Document* pDoc) + : CFXJSE_HostObject(kFM2JS), + m_pIsolate(pScriptIsolate), + m_pFMClass(CFXJSE_Class::Create(pScriptContext, + &formcalc_fm2js_descriptor, + false)), + m_pValue(pdfium::MakeUnique(pScriptIsolate)), + m_pDocument(pDoc) { + m_pValue.get()->SetObject(this, m_pFMClass); +} + +CFXJSE_FormCalcContext::~CFXJSE_FormCalcContext() {} + +void CFXJSE_FormCalcContext::GlobalPropertyGetter(CFXJSE_Value* pValue) { + pValue->Assign(m_pValue.get()); +} + +void CFXJSE_FormCalcContext::ThrowNoDefaultPropertyException( + const ByteStringView& name) const { + // TODO(tsepez): check usage of c_str() below. + ThrowException(L"%.16S doesn't have a default property.", + name.unterminated_c_str()); +} + +void CFXJSE_FormCalcContext::ThrowCompilerErrorException() const { + ThrowException(L"Compiler error."); +} + +void CFXJSE_FormCalcContext::ThrowDivideByZeroException() const { + ThrowException(L"Divide by zero."); +} + +void CFXJSE_FormCalcContext::ThrowServerDeniedException() const { + ThrowException(L"Server does not permit operation."); +} + +void CFXJSE_FormCalcContext::ThrowPropertyNotInObjectException( + const WideString& name, + const WideString& exp) const { + ThrowException( + L"An attempt was made to reference property '%.16s' of a non-object " + L"in SOM expression %.16s.", + name.c_str(), exp.c_str()); +} + +void CFXJSE_FormCalcContext::ThrowParamCountMismatchException( + const WideString& method) const { + ThrowException(L"Incorrect number of parameters calling method '%.16s'.", + method.c_str()); +} + +void CFXJSE_FormCalcContext::ThrowArgumentMismatchException() const { + ThrowException(L"Argument mismatch in property or function argument."); +} + +void CFXJSE_FormCalcContext::ThrowException(const wchar_t* str, ...) const { + va_list arg_ptr; + va_start(arg_ptr, str); + WideString wsMessage = WideString::FormatV(str, arg_ptr); + va_end(arg_ptr); + + ASSERT(!wsMessage.IsEmpty()); + FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView()); +} diff --git a/fxjs/cfxjse_formcalc_context.h b/fxjs/cfxjse_formcalc_context.h new file mode 100644 index 0000000000000000000000000000000000000000..51e3178c13009ab8cbec7848da17e294dde955c2 --- /dev/null +++ b/fxjs/cfxjse_formcalc_context.h @@ -0,0 +1,445 @@ +// 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 FXJS_CFXJSE_FORMCALC_CONTEXT_H_ +#define FXJS_CFXJSE_FORMCALC_CONTEXT_H_ + +#include +#include + +#include "fxjs/cfxjse_arguments.h" +#include "fxjs/cfxjse_context.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +class CFX_WideTextBuf; +class CXFA_Document; + +class CFXJSE_FormCalcContext : public CFXJSE_HostObject { + public: + CFXJSE_FormCalcContext(v8::Isolate* pScriptIsolate, + CFXJSE_Context* pScriptContext, + CXFA_Document* pDoc); + ~CFXJSE_FormCalcContext() override; + + static void Abs(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Avg(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Ceil(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Count(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Floor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Max(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Min(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Mod(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Round(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Sum(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Date(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Date2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void DateFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void IsoDate2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void IsoTime2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void LocalDateFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void LocalTimeFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Num2Date(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Num2GMTime(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Num2Time(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Time(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Time2Num(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void TimeFmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + + static bool IsIsoDateFormat(const char* pData, + int32_t iLength, + int32_t& iStyle, + int32_t& iYear, + int32_t& iMonth, + int32_t& iDay); + static bool IsIsoTimeFormat(const char* pData, + int32_t iLength, + int32_t& iHour, + int32_t& iMinute, + int32_t& iSecond, + int32_t& iMilliSecond, + int32_t& iZoneHour, + int32_t& iZoneMinute); + static bool IsIsoDateTimeFormat(const char* pData, + int32_t iLength, + int32_t& iYear, + int32_t& iMonth, + int32_t& iDay, + int32_t& iHour, + int32_t& iMinute, + int32_t& iSecond, + int32_t& iMillionSecond, + int32_t& iZoneHour, + int32_t& iZoneMinute); + static ByteString Local2IsoDate(CFXJSE_Value* pThis, + const ByteStringView& szDate, + const ByteStringView& szFormat, + const ByteStringView& szLocale); + static ByteString IsoDate2Local(CFXJSE_Value* pThis, + const ByteStringView& szDate, + const ByteStringView& szFormat, + const ByteStringView& szLocale); + static ByteString IsoTime2Local(CFXJSE_Value* pThis, + const ByteStringView& szTime, + const ByteStringView& szFormat, + const ByteStringView& szLocale); + static int32_t DateString2Num(const ByteStringView& szDateString); + static ByteString GetLocalDateFormat(CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocalStr, + bool bStandard); + static ByteString GetLocalTimeFormat(CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocalStr, + bool bStandard); + static ByteString GetStandardDateFormat(CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocalStr); + static ByteString GetStandardTimeFormat(CFXJSE_Value* pThis, + int32_t iStyle, + const ByteStringView& szLocalStr); + static ByteString Num2AllTime(CFXJSE_Value* pThis, + int32_t iTime, + const ByteStringView& szFormat, + const ByteStringView& szLocale, + bool bGM); + static void GetLocalTimeZone(int32_t& iHour, int32_t& iMin, int32_t& iSec); + + static void Apr(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void CTerm(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void FV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void IPmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void NPV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Pmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void PPmt(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void PV(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Rate(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Term(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Choose(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Exists(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void HasValue(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Oneof(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Within(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void If(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Eval(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Ref(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void UnitType(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void UnitValue(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + + static void At(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Concat(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Decode(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static WideString DecodeURL(const WideString& wsURLString); + static WideString DecodeHTML(const WideString& wsHTMLString); + static WideString DecodeXML(const WideString& wsXMLString); + static void Encode(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static WideString EncodeURL(const ByteString& szURLString); + static WideString EncodeHTML(const ByteString& szHTMLString); + static WideString EncodeXML(const ByteString& szXMLString); + static bool HTMLSTR2Code(const WideStringView& pData, uint32_t* iCode); + static bool HTMLCode2STR(uint32_t iCode, WideString* wsHTMLReserve); + static void Format(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Left(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Len(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Lower(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Ltrim(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Parse(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Replace(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Right(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Rtrim(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Space(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Str(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Stuff(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Substr(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Uuid(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Upper(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void WordNum(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static ByteString TrillionUS(const ByteStringView& szData); + static ByteString WordUS(const ByteString& szData, int32_t iStyle); + + static void Get(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Post(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void Put(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void assign_value_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void logical_or_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void logical_and_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void equality_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void notequality_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static bool fm_ref_equal(CFXJSE_Value* pThis, CFXJSE_Arguments& args); + static void less_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void lessequal_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void greater_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void greaterequal_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void plus_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void minus_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void multiple_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void divide_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void positive_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void negative_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void logical_not_operator(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void dot_accessor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void dotdot_accessor(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void eval_translation(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void is_fm_object(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void is_fm_array(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void get_fm_value(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void get_fm_jsobj(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void fm_var_filter(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + static void concat_fm_object(CFXJSE_Value* pThis, + const ByteStringView& szFuncName, + CFXJSE_Arguments& args); + + static int32_t hvalue_get_array_length(CFXJSE_Value* pThis, + CFXJSE_Value* arg); + static bool simpleValueCompare(CFXJSE_Value* pThis, + CFXJSE_Value* firstValue, + CFXJSE_Value* secondValue); + static void unfoldArgs( + CFXJSE_Value* pThis, + CFXJSE_Arguments& args, + std::vector>* resultValues, + int32_t iStart = 0); + static void GetObjectDefaultValue(CFXJSE_Value* pObjectValue, + CFXJSE_Value* pDefaultValue); + static bool SetObjectDefaultValue(CFXJSE_Value* pObjectValue, + CFXJSE_Value* pNewValue); + static ByteString GenerateSomExpression(const ByteStringView& szName, + int32_t iIndexFlags, + int32_t iIndexValue, + bool bIsStar); + static bool GetObjectForName(CFXJSE_Value* pThis, + CFXJSE_Value* accessorValue, + const ByteStringView& szAccessorName); + static bool ResolveObjects(CFXJSE_Value* pThis, + CFXJSE_Value* pParentValue, + const ByteStringView& bsSomExp, + XFA_RESOLVENODE_RS* resolveNodeRS, + bool bdotAccessor, + bool bHasNoResolveName); + static void ParseResolveResult( + CFXJSE_Value* pThis, + const XFA_RESOLVENODE_RS& resolveNodeRS, + CFXJSE_Value* pParentValue, + std::vector>* resultValues, + bool* bAttribute); + + static std::unique_ptr GetSimpleValue(CFXJSE_Value* pThis, + CFXJSE_Arguments& args, + uint32_t index); + static bool ValueIsNull(CFXJSE_Value* pThis, CFXJSE_Value* pValue); + static int32_t ValueToInteger(CFXJSE_Value* pThis, CFXJSE_Value* pValue); + static float ValueToFloat(CFXJSE_Value* pThis, CFXJSE_Value* pValue); + static double ValueToDouble(CFXJSE_Value* pThis, CFXJSE_Value* pValue); + static ByteString ValueToUTF8String(CFXJSE_Value* pValue); + static double ExtractDouble(CFXJSE_Value* pThis, + CFXJSE_Value* src, + bool* ret); + + static bool Translate(const WideStringView& wsFormcalc, + CFX_WideTextBuf* wsJavascript); + + void GlobalPropertyGetter(CFXJSE_Value* pValue); + + private: + v8::Isolate* GetScriptRuntime() const { return m_pIsolate; } + CXFA_Document* GetDocument() const { return m_pDocument.Get(); } + + void ThrowNoDefaultPropertyException(const ByteStringView& name) const; + void ThrowCompilerErrorException() const; + void ThrowDivideByZeroException() const; + void ThrowServerDeniedException() const; + void ThrowPropertyNotInObjectException(const WideString& name, + const WideString& exp) const; + void ThrowArgumentMismatchException() const; + void ThrowParamCountMismatchException(const WideString& method) const; + void ThrowException(const wchar_t* str, ...) const; + + v8::Isolate* m_pIsolate; + CFXJSE_Class* m_pFMClass; + std::unique_ptr m_pValue; + UnownedPtr const m_pDocument; +}; + +#endif // FXJS_CFXJSE_FORMCALC_CONTEXT_H_ diff --git a/fxjs/cfxjse_formcalc_context_embeddertest.cpp b/fxjs/cfxjse_formcalc_context_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d48d5cc44521d6449282336bc1ccd959794e6d02 --- /dev/null +++ b/fxjs/cfxjse_formcalc_context_embeddertest.cpp @@ -0,0 +1,1446 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/xfa_js_embedder_test.h" + +class CFXJSE_FormCalcContextEmbedderTest : public XFAJSEmbedderTest {}; + +// TODO(dsinclair): Comment out tests are broken and need to be fixed. + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, TranslateEmpty) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + const char input[] = ""; + EXPECT_TRUE(Execute(input)); + // TODO(dsinclair): This should probably throw as a blank formcalc script + // is invalid. +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, TranslateNumber) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + const char input[] = "123"; + EXPECT_TRUE(Execute(input)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(123, value->ToInteger()) << "Program: " << input; +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Numeric) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"123 + 456", 579}, + {"2 - 3 * 10 / 2 + 7", -6}, + {"10 * 3 + 5 * 4", 50}, + {"(5 - \"abc\") * 3", 15}, + {"\"100\" / 10e1", 1}, + {"5 + null + 3", 8}, + // {"if (\"abc\") then\n" + // " 10\n" + // "else\n" + // " 20\n" + // "endif", + // 20}, + // {"3 / 0 + 1", 0}, + {"-(17)", -17}, + {"-(-17)", 17}, + {"+(17)", 17}, + {"+(-17)", -17}, + {"if (1 < 2) then\n1\nendif", 1}, + {"if (\"abc\" > \"def\") then\n" + " 1 and 0\n" + "else\n" + " 0\n" + "endif", + 0}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Strings) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + {"\"abc\"", "abc"}, + {"concat(\"The total is \", 2, \" dollars and \", 57, \" cents.\")", + "The total is 2 dollars and 57 cents."}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Booleans) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + bool result; + } tests[] = {{"0 and 1 or 2 > 1", true}, + {"2 < 3 not 1 == 1", false}, + {"\"abc\" | 2", true}, + {"1 or 0", true}, + {"0 | 0", false}, + {"0 or 1 | 0 or 0", true}, + {"1 and 0", false}, + // {"0 & 0", true}, // TODO(dsinclair) Confirm with Reader. + {"0 and 1 & 0 and 0", false}, + {"not(\"true\")", true}, + {"not(1)", false}, + {"3 == 3", true}, + {"3 <> 4", true}, + {"\"abc\" eq \"def\"", false}, + {"\"def\" ne \"abc\"", true}, + {"5 + 5 == 10", true}, + {"5 + 5 <> \"10\"", false}, + {"3 < 3", false}, + {"3 > 4", false}, + {"\"abc\" <= \"def\"", true}, + {"\"def\" > \"abc\"", true}, + {"12 >= 12", true}, + {"\"true\" < \"false\"", false}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program; + EXPECT_EQ(tests[i].result, value->ToBoolean()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Abs) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"Abs(1.03)", 1.03f}, {"Abs(-1.03)", 1.03f}, {"Abs(0)", 0.0f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Avg) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"Avg(0, 32, 16)", 16.0f}, {"Avg(2.5, 17, null)", 9.75f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ceil) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Ceil(2.5875)", 3}, {"Ceil(-5.9)", -5}, {"Ceil(\"abc\")", 0}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Count) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Count(\"Tony\", \"Blue\", 41)", 3}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Floor) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Floor(21.3409873)", 21}, + {"Floor(5.999965342)", 5}, + {"Floor(3.2 * 15)", 48}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Max) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Max(234, 15, 107)", 234}, + {"Max(\"abc\", 15, \"Tony Blue\")", 15}, + {"Max(\"abc\")", 0}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Min) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Min(234, 15, 107)", 15}, + // TODO(dsinclair): Verify with Reader; I believe this should + // have a return of 0. + // {"Min(\"abc\", 15, \"Tony Blue\")", 15}, + {"Min(\"abc\")", 0}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Mod) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Mod(64, -3)", 1}, {"Mod(-13, 3)", -1}, {"Mod(\"abc\", 2)", 0}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Round) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"Round(12.389764537, 4)", 12.3898f}, + {"Round(20/3, 2)", 6.67f}, + {"Round(8.9897, \"abc\")", 9.0f}, + {"Round(FV(400, 0.10/12, 30*12), 2)", 904195.17f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()) << "Program: " << tests[i].program; + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Sum) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"Sum(2, 4, 6, 8)", 20}, + {"Sum(-2, 4, -6, 8)", 4}, + {"Sum(4, 16, \"abc\", 19)", 39}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +// TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Date) { +// ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); +// +// TODO(dsinclair): Make compatible with windows. +// time_t seconds = time(nullptr); +// int days = seconds / (60 * 60 * 24); + +// EXPECT_TRUE(Execute("Date()")); + +// CFXJSE_Value* value = GetValue(); +// EXPECT_TRUE(value->IsNumber()); +// EXPECT_EQ(days, value->ToInteger()); +// } + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Date2Num) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = { + // {"Date2Num(\"Mar 15, 1996\")", 35138}, + {"Date2Num(\"1/1/1900\", \"D/M/YYYY\")", 1}, + {"Date2Num(\"03/15/96\", \"MM/DD/YY\")", 35138}, + // {"Date2Num(\"Aug 1, 1996\", \"MMM D, YYYY\")", 35277}, + {"Date2Num(\"96-08-20\", \"YY-MM-DD\", \"fr_FR\")", 35296}, + {"Date2Num(\"1/3/00\", \"D/M/YY\") - Date2Num(\"1/2/00\", \"D/M/YY\")", + 29}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DateFmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + // {"DateFmt(1)", "M/D/YY"}, + // {"DateFmt(2, \"fr_CA\")", "YY-MM-DD"}, + {"DateFmt(3, \"de_DE\")", "D. MMMM YYYY"}, + // {"DateFmt(4, \"fr_FR\")", "EEE D' MMMM YYYY"} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, IsoDate2Num) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"IsoDate2Num(\"1900\")", 1}, + {"IsoDate2Num(\"1900-01\")", 1}, + {"IsoDate2Num(\"1900-01-01\")", 1}, + {"IsoDate2Num(\"19960315T20:20:20\")", 35138}, + {"IsoDate2Num(\"2000-03-01\") - IsoDate2Num(\"20000201\")", 29}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_IsoTime2Num) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"IsoTime2Num(\"00:00:00Z\")", 1}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, LocalDateFmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {// {"LocalDateFmt(1, \"de_DE\")", "tt.MM.uu"}, + // {"LocalDateFmt(2, \"fr_CA\")", "aa-MM-jj"}, + {"LocalDateFmt(3, \"de_CH\")", "t. MMMM jjjj"}, + {"LocalDateFmt(4, \"fr_FR\")", "EEEE j MMMM aaaa"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_LocalTimeFmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"LocalTimeFmt(1, \"de_DE\")", "HH:mm"}, + {"LocalTimeFmt(2, \"fr_CA\")", "HH:mm::ss"}, + {"LocalTimeFmt(3, \"de_CH\")", "HH:mm:ss z"}, + {"LocalTimeFmt(4, \"fr_FR\")", "HH' h 'mm z"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Num2Date) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + {"Num2Date(1, \"DD/MM/YYYY\")", "01/01/1900"}, + {"Num2Date(35139, \"DD-MMM-YYYY\", \"de_DE\")", "16-Mrz-1996"}, + // {"Num2Date(Date2Num(\"Mar 15, 2000\") - Date2Num(\"98-03-15\", " + // "\"YY-MM-DD\", \"fr_CA\"))", + // "Jan 1, 1902"} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()) << "Program: " << tests[i].program; + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Num2GMTime) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {// Broken on Windows only. + {"Num2GMTime(1, \"HH:MM:SS\")", "00:00:00"}, + // Below broken on other platforms. + {"Num2GMTime(65593001, \"HH:MM:SS Z\")", "18:13:13 GMT"}, + {"Num2GMTime(43993001, TimeFmt(4, \"de_DE\"), \"de_DE\")", + "12.13 Uhr GMT"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +// TODO(dsinclair): Broken on Mac ... +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Num2Time) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Num2Time(1, \"HH:MM:SS\")", "00:00:00"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +// TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Time) { +// ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); +// TODO(dsinclair): Make compatible with windows. +// struct timeval tp; +// gettimeofday(&tp, nullptr); + +// EXPECT_TRUE(Execute("Time()")); + +// CFXJSE_Value* value = GetValue(); +// EXPECT_TRUE(value->IsInteger()); +// EXPECT_EQ(tp.tv_sec * 1000L + tp.tv_usec / 1000, value->ToInteger()) +// << "Program: Time()"; +// } + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Time2Num) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = { + // {"Time2Num(\"00:00:00 GMT\", \"HH:MM:SS Z\")", 1}, + {"Time2Num(\"13:13:13 GMT\", \"HH:MM:SS Z\", \"fr_FR\")", 47593001}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, TimeFmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + // {"TimeFmt(1)", "h::MM A"}, + {"TimeFmt(2, \"fr_CA\")", "HH:MM:SS"}, + {"TimeFmt(3, \"fr_FR\")", "HH:MM:SS Z"}, + // {"TimeFmt(4, \"de_DE\")", "H.MM' Uhr 'Z"} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Apr) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"Apr(35000, 269.50, 360)", 0.08515404566f}, + {"Apr(210000 * 0.75, 850 + 110, 25 * 26)", 0.07161332404f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, CTerm) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = { + // {"CTerm(0.02, 1000, 100)", 116.2767474515f}, + {"CTerm(0.10, 500000, 12000)", 39.13224648502f}, + // {"CTerm(0.0275 + 0.0025, 1000000, 55000 * 0.10)", 176.02226044975f} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, FV) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"FV(400, 0.10 / 12, 30 * 12)", 904195.16991842445f}, + {"FV(1000, 0.075 / 4, 10 * 4)", 58791.96145535981f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, IPmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"IPmt(30000, 0.085, 295.50, 7, 3)", 624.8839283142f}, + {"IPmt(160000, 0.0475, 980, 24, 12)", 7103.80833569485f}, + {"IPmt(15000, 0.065, 65.50, 15, 1)", 0.0f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_NPV) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"NPV(0.065, 5000)", 4694.83568075117f}, + {"NPV(0.10, 500, 1500, 4000, 10000)", 11529.60863329007f}, + {"NPV(0.0275 / 12, 50, 60, 40, 100, 25)", 273.14193838457f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()) << "Program: " << tests[i].program; + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Pmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {// {"Pmt(150000, 0.0475 / 12, 25 * 12)", 855.17604207164f}, + {"Pmt(25000, 0.085, 12)", 3403.82145169876f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, PPmt) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = { + {"PPmt(30000, 0.085, 295.50, 7, 3)", 261.6160716858f}, + {"PPmt(160000, 0.0475, 980, 24, 12)", 4656.19166430515f}, + // {"PPmt(15000, 0.065, 65.50, 15, 1)", 0.0f} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, PV) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = { + {"PV(400, 0.10 / 12, 30 * 12)", 45580.32799074439f}, + // {"PV(1000, 0.075 / 4, 10 * 4)", 58791.96145535981f} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Rate) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {{"Rate(12000, 8000, 5)", 0.0844717712f}, + {"Rate(10000, 0.25 * 5000, 4 * 12)", 0.04427378243f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Term) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = {// {"Term(475, .05, 1500)", 3.00477517728f}, + {"Term(2500, 0.0275 + 0.0025, 5000)", 1.97128786369f}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Choose) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + {"Choose(3, \"Taxes\", \"Price\", \"Person\", \"Teller\")", "Person"}, + {"Choose(2, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)", "9"}, + {"Choose(20/3, \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\")", + "F"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Exists) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + EXPECT_TRUE(Execute("Exists(\"hello world\")")); + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_FALSE(value->ToBoolean()); +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, HasValue) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + bool result; + } tests[] = {{"HasValue(2)", true}, {"HasValue(\" \")", false}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program; + EXPECT_EQ(tests[i].result, value->ToBoolean()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Oneof) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + bool result; + } tests[] = { + {"Oneof(3, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)", true}, + {"Oneof(\"John\", \"Bill\", \"Gary\", \"Joan\", \"John\", \"Lisa\")", + true}, + {"Oneof(3, 1, 25)", false}, + {"Oneof(3, 3, null)", true}, + {"Oneof(3, null, null)", false}, + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program; + EXPECT_EQ(tests[i].result, value->ToBoolean()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Within) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + bool result; + } tests[] = {{"Within(\"C\", \"A\", \"D\")", true}, + {"Within(1.5, 0, 2)", true}, + {"Within(-1, 0, 2)", false}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()) << "Program: " << tests[i].program; + EXPECT_EQ(tests[i].result, value->ToBoolean()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Eval) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"eval(\"10*3+5*4\")", 50}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Null) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Null()", "null"}, + {"Concat(\"ABC\", Null(), \"DEF\")", "ABCDEF"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } + + EXPECT_TRUE(Execute("Null() + 5")); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(5, value->ToInteger()); +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ref) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Ref(\"10*3+5*4\")", "10*3+5*4"}, {"Ref(\"hello\")", "hello"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, UnitType) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"UnitType(\"36 in\")", "in"}, + {"UnitType(\"2.54centimeters\")", "cm"}, + {"UnitType(\"picas\")", "pt"}, + {"UnitType(\"2.cm\")", "cm"}, + {"UnitType(\"2.zero cm\")", "in"}, + {"UnitType(\"kilometers\")", "in"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, UnitValue) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + float result; + } tests[] = { + {"UnitValue(\"2in\")", 2.0f}, {"UnitValue(\"2in\", \"cm\")", 5.08f}, + // {"UnitValue(\"6\", \"pt\")", 432f}, + // {"UnitType(\"A\", \"cm\")", 0.0f}, + // {"UnitType(\"5.08cm\", \"kilograms\")", 2.0f} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(tests[i].result, value->ToFloat()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, At) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = {{"At(\"ABCDEFGH\", \"AB\")", 1}, + {"At(\"ABCDEFGH\", \"F\")", 6}, + {"At(23412931298471, 29)", 5}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Concat) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Concat(\"ABC\", \"DEF\")", "ABCDEF"}, + {"Concat(\"Tony\", Space(1), \"Blue\")", "Tony Blue"}, + {"Concat(\"You owe \", WordNum(1154.67, 2), \".\")", + "You owe One Thousand One Hundred Fifty-four Dollars And " + "Sixty-seven Cents."}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Decode) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + {"Decode(\"ÆÁÂÁÂ\", \"html\")", "ÆÁÂÁÂ"}, + // {"Decode(\"~!@#$%%^&*()_+|`{"}[]<>?,./;':\", " + // "\"xml\")", + // "~!@#$%%^&*()_+|`{" + // "}[]<>?,./;':"} + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Encode) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + {"Encode(\"\"\"hello, world!\"\"\", \"url\")", + "%%22hello,%%20world!%%22"}, + {"Encode(\"ÁÂÃÄÅÆ\", \"html\")", "ÁÂÃÄÅÆ"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Format) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Format(\"MMM D, YYYY\", \"20020901\")", "Sep 1, 2002"}, + {"Format(\"$9,999,999.99\", 1234567.89)", "$1,234,567.89"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Left) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Left(\"ABCDEFGH\", 3)", "ABC"}, + {"Left(\"Tony Blue\", 5)", "Tony "}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Len) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + int result; + } tests[] = { + {"Len(\"ABCDEFGH\")", 8}, {"Len(4)", 1}, {"Len(Str(4.532, 6, 4))", 6}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsInteger()); + EXPECT_EQ(tests[i].result, value->ToInteger()) + << "Program: " << tests[i].program; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Lower) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Lower(\"ABC\")", "abc"}, + {"Lower(\"21 Main St.\")", "21 main st."}, + {"Lower(15)", "15"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Ltrim) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Ltrim(\" ABCD\")", "ABCD"}, + {"Ltrim(Rtrim(\" Tony Blue \"))", "Tony Blue"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Parse) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Parse(\"MMM D, YYYY\", \"Sep 1, 2002\")", "2002-09-01"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } + + EXPECT_TRUE(Execute("Parse(\"$9,999,999.99\", \"$1,234,567.89\")")); + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsNumber()); + EXPECT_FLOAT_EQ(1234567.89f, value->ToFloat()); +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Replace) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Replace(\"Tony Blue\", \"Tony\", \"Chris\")", "Chris Blue"}, + {"Replace(\"ABCDEFGH\", \"D\")", "ABCEFGH"}, + {"Replace(\"ABCDEFGH\", \"d\")", "ABCDEFGH"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Right) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Right(\"ABCDEFGH\", 3)", "FGH"}, + {"Right(\"Tony Blue\", 5)", " Blue"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Rtrim) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Rtrim(\"ABCD \")", "ABCD"}, + {"Rtrim(\"Tony Blue \t\")", "Tony Blue"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Space) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Space(5)", " "}, + {"Concat(\"Tony\", Space(1), \"Blue\")", "Tony Blue"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Str) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Str(2.456)", " 2"}, + {"Str(4.532, 6, 4)", "4.5320"}, + {"Str(234.458, 4)", " 234"}, + {"Str(31.2345, 4, 2)", "****"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Stuff) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Stuff(\"TonyBlue\", 5, 0, \" \")", "Tony Blue"}, + {"Stuff(\"ABCDEFGH\", 4, 2)", "ABCFGH"}, + {"Stuff(\"members-list@myweb.com\", 0, 0, \"cc:\")", + "cc:members-list@myweb.com"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Substr) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Substr(\"ABCDEFG\", 3, 4)", "CDEF"}, + {"Substr(3214, 2, 1)", "2"}, + {"Substr(\"ABCDEFG\", 5, 0)", ""}, + {"Substr(\"21 Waterloo St.\", 4, 5)", "Water"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Uuid) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + EXPECT_TRUE(Execute("Uuid()")); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Upper) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = {{"Upper(\"abc\")", "ABC"}, + {"Upper(\"21 Main St.\")", "21 MAIN ST."}, + {"Upper(15)", "15"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, WordNum) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + struct { + const char* program; + const char* result; + } tests[] = { + // {"WordNum(123.45)", + // "One Hundred and Twenty-three"}, // This looks like it's wrong in the + // // Formcalc document. + // {"WordNum(123.45, 1)", "One Hundred and Twenty-three Dollars"}, + {"WordNum(1154.67, 2)", + "One Thousand One Hundred Fifty-four Dollars And Sixty-seven Cents"}, + {"WordNum(43, 2)", "Forty-three Dollars And Zero Cents"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE(Execute(tests[i].program)); + + CFXJSE_Value* value = GetValue(); + EXPECT_TRUE(value->IsString()); + EXPECT_STREQ(tests[i].result, value->ToString().c_str()) + << "Program: " << tests[i].program << " Result: '" + << value->ToString().c_str() << "'"; + } +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Get) { + // TODO(dsinclair): Is this supported? +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Post) { + // TODO(dsinclair): Is this supported? +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, Put) { + // TODO(dsinclair): Is this supported? +} + +TEST_F(CFXJSE_FormCalcContextEmbedderTest, InvalidFunctions) { + ASSERT_TRUE(OpenDocument("simple_xfa.pdf")); + + const char* const tests[] = { + "F()", "()", "()()()", "Round(2.0)()", + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_FALSE(ExecuteSilenceFailure(tests[i])); + } +} diff --git a/fxjs/cfxjse_isolatetracker.cpp b/fxjs/cfxjse_isolatetracker.cpp deleted file mode 100644 index 0dd4158714067b08dc627d18f663ce53d2996660..0000000000000000000000000000000000000000 --- a/fxjs/cfxjse_isolatetracker.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 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 "fxjs/cfxjse_isolatetracker.h" - -#include -#include - -CFXJSE_IsolateTracker::CFXJSE_IsolateTracker() {} - -CFXJSE_IsolateTracker::~CFXJSE_IsolateTracker() {} - -void CFXJSE_IsolateTracker::Append( - v8::Isolate* pIsolate, - std::unique_ptr alloc) { - m_OwnedIsolates.push_back(pIsolate); - m_AllocatorMap[pIsolate] = std::move(alloc); -} - -void CFXJSE_IsolateTracker::Remove( - v8::Isolate* pIsolate, - CFXJSE_IsolateTracker::DisposeCallback lpfnDisposeCallback) { - auto it = std::find(m_OwnedIsolates.begin(), m_OwnedIsolates.end(), pIsolate); - bool bFound = it != m_OwnedIsolates.end(); - if (bFound) - m_OwnedIsolates.erase(it); - lpfnDisposeCallback(pIsolate, bFound); - - m_AllocatorMap.erase(pIsolate); -} - -void CFXJSE_IsolateTracker::RemoveAll( - CFXJSE_IsolateTracker::DisposeCallback lpfnDisposeCallback) { - for (v8::Isolate* pIsolate : m_OwnedIsolates) - lpfnDisposeCallback(pIsolate, true); - - m_OwnedIsolates.clear(); - m_AllocatorMap.clear(); -} diff --git a/fxjs/cfxjse_isolatetracker.h b/fxjs/cfxjse_isolatetracker.h index 5340d9b5c0a62d336e9778692ae82e05bd104444..2bb16ca7bacd4ac1d79bada0ba856ba2b60de7f0 100644 --- a/fxjs/cfxjse_isolatetracker.h +++ b/fxjs/cfxjse_isolatetracker.h @@ -52,24 +52,4 @@ class CFXJSE_ScopeUtil_IsolateHandleRootContext { v8::Context::Scope m_cscope; }; -class CFXJSE_IsolateTracker { - public: - typedef void (*DisposeCallback)(v8::Isolate*, bool bOwnedIsolate); - - CFXJSE_IsolateTracker(); - ~CFXJSE_IsolateTracker(); - - void Append(v8::Isolate* pIsolate, - std::unique_ptr alloc); - void Remove(v8::Isolate* pIsolate, DisposeCallback lpfnDisposeCallback); - void RemoveAll(DisposeCallback lpfnDisposeCallback); - - static CFXJSE_IsolateTracker* g_pInstance; - - protected: - std::vector m_OwnedIsolates; - std::map> - m_AllocatorMap; -}; - #endif // FXJS_CFXJSE_ISOLATETRACKER_H_ diff --git a/fxjs/cfxjse_resolveprocessor.cpp b/fxjs/cfxjse_resolveprocessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ca0838a7f5eb4f52a8305583d6ede2584150d5f --- /dev/null +++ b/fxjs/cfxjse_resolveprocessor.cpp @@ -0,0 +1,746 @@ +// 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 "fxjs/cfxjse_resolveprocessor.h" + +#include +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodehelper.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#include "xfa/fxfa/parser/cxfa_occur.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +CFXJSE_ResolveProcessor::CFXJSE_ResolveProcessor() + : m_iCurStart(0), m_pNodeHelper(pdfium::MakeUnique()) {} + +CFXJSE_ResolveProcessor::~CFXJSE_ResolveProcessor() {} + +bool CFXJSE_ResolveProcessor::Resolve(CFXJSE_ResolveNodeData& rnd) { + if (!rnd.m_CurObject) + return false; + + if (!rnd.m_CurObject->IsNode()) { + if (rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) { + return ResolveForAttributeRs(rnd.m_CurObject, rnd, + rnd.m_wsName.AsStringView()); + } + return false; + } + if (rnd.m_dwStyles & XFA_RESOLVENODE_AnyChild) + return ResolveAnyChild(rnd); + + if (rnd.m_wsName.GetLength()) { + wchar_t wch = rnd.m_wsName[0]; + switch (wch) { + case '$': + return ResolveDollar(rnd); + case '!': + return ResolveExcalmatory(rnd); + case '#': + return ResolveNumberSign(rnd); + case '*': + return ResolveAsterisk(rnd); + // TODO(dsinclair): We could probably remove this. + case '.': + return ResolveAnyChild(rnd); + default: + break; + } + } + if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) { + rnd.m_Objects.push_back(rnd.m_pSC->GetThisObject()); + return true; + } + if (rnd.m_CurObject->GetElementType() == XFA_Element::Xfa) { + CXFA_Object* pObjNode = + rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName); + if (pObjNode) { + rnd.m_Objects.push_back(pObjNode); + } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) { + rnd.m_Objects.push_back(rnd.m_CurObject); + } else if ((rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) && + ResolveForAttributeRs(rnd.m_CurObject, rnd, + rnd.m_wsName.AsStringView())) { + return true; + } + if (!rnd.m_Objects.empty()) + FilterCondition(rnd, rnd.m_wsCondition); + + return !rnd.m_Objects.empty(); + } + if (!ResolveNormal(rnd) && rnd.m_uHashName == XFA_HASHCODE_Xfa) + rnd.m_Objects.push_back(rnd.m_pSC->GetDocument()->GetRoot()); + + return !rnd.m_Objects.empty(); +} + +bool CFXJSE_ResolveProcessor::ResolveAnyChild(CFXJSE_ResolveNodeData& rnd) { + WideString wsName = rnd.m_wsName; + WideString wsCondition = rnd.m_wsCondition; + CXFA_Node* findNode = nullptr; + bool bClassName = false; + if (wsName.GetLength() && wsName[0] == '#') { + bClassName = true; + wsName = wsName.Right(wsName.GetLength() - 1); + } + findNode = m_pNodeHelper->ResolveNodes_GetOneChild( + ToNode(rnd.m_CurObject), wsName.c_str(), bClassName); + if (!findNode) + return false; + + if (wsCondition.IsEmpty()) { + rnd.m_Objects.push_back(findNode); + return !rnd.m_Objects.empty(); + } + + std::vector tempNodes; + for (auto* pObject : rnd.m_Objects) + tempNodes.push_back(pObject->AsNode()); + m_pNodeHelper->CountSiblings(findNode, XFA_LOGIC_Transparent, &tempNodes, + bClassName); + rnd.m_Objects = std::vector(tempNodes.begin(), tempNodes.end()); + FilterCondition(rnd, wsCondition); + return !rnd.m_Objects.empty(); +} + +bool CFXJSE_ResolveProcessor::ResolveDollar(CFXJSE_ResolveNodeData& rnd) { + WideString wsName = rnd.m_wsName; + WideString wsCondition = rnd.m_wsCondition; + int32_t iNameLen = wsName.GetLength(); + if (iNameLen == 1) { + rnd.m_Objects.push_back(rnd.m_CurObject); + return true; + } + if (rnd.m_nLevel > 0) + return false; + + XFA_HashCode dwNameHash = static_cast(FX_HashCode_GetW( + WideStringView(wsName.c_str() + 1, iNameLen - 1), false)); + if (dwNameHash == XFA_HASHCODE_Xfa) { + rnd.m_Objects.push_back(rnd.m_pSC->GetDocument()->GetRoot()); + } else { + CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash); + if (pObjNode) + rnd.m_Objects.push_back(pObjNode); + } + if (!rnd.m_Objects.empty()) + FilterCondition(rnd, wsCondition); + + return !rnd.m_Objects.empty(); +} + +bool CFXJSE_ResolveProcessor::ResolveExcalmatory(CFXJSE_ResolveNodeData& rnd) { + if (rnd.m_nLevel > 0) + return false; + + CXFA_Node* datasets = + ToNode(rnd.m_pSC->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); + if (!datasets) + return false; + + CFXJSE_ResolveNodeData rndFind(rnd.m_pSC); + rndFind.m_CurObject = datasets; + rndFind.m_wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1); + rndFind.m_uHashName = static_cast( + FX_HashCode_GetW(rndFind.m_wsName.AsStringView(), false)); + rndFind.m_nLevel = rnd.m_nLevel + 1; + rndFind.m_dwStyles = XFA_RESOLVENODE_Children; + rndFind.m_wsCondition = rnd.m_wsCondition; + Resolve(rndFind); + + rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + return !rnd.m_Objects.empty(); +} + +bool CFXJSE_ResolveProcessor::ResolveNumberSign(CFXJSE_ResolveNodeData& rnd) { + WideString wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1); + WideString wsCondition = rnd.m_wsCondition; + CXFA_Node* curNode = ToNode(rnd.m_CurObject); + if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView())) + return true; + + CFXJSE_ResolveNodeData rndFind(rnd.m_pSC); + rndFind.m_nLevel = rnd.m_nLevel + 1; + rndFind.m_dwStyles = rnd.m_dwStyles; + rndFind.m_dwStyles |= XFA_RESOLVENODE_TagName; + rndFind.m_dwStyles &= ~XFA_RESOLVENODE_Attributes; + rndFind.m_wsName = wsName; + rndFind.m_uHashName = static_cast( + FX_HashCode_GetW(rndFind.m_wsName.AsStringView(), false)); + rndFind.m_wsCondition = wsCondition; + rndFind.m_CurObject = curNode; + ResolveNormal(rndFind); + if (rndFind.m_Objects.empty()) + return false; + + if (wsCondition.GetLength() == 0 && + pdfium::ContainsValue(rndFind.m_Objects, curNode)) { + rnd.m_Objects.push_back(curNode); + } else { + rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + } + return !rnd.m_Objects.empty(); +} + +bool CFXJSE_ResolveProcessor::ResolveForAttributeRs( + CXFA_Object* curNode, + CFXJSE_ResolveNodeData& rnd, + const WideStringView& strAttr) { + const XFA_SCRIPTATTRIBUTEINFO* lpScriptAttribute = + XFA_GetScriptAttributeByName(curNode->GetElementType(), strAttr); + if (!lpScriptAttribute) + return false; + + rnd.m_pScriptAttribute = lpScriptAttribute; + rnd.m_Objects.push_back(curNode); + rnd.m_dwFlag = XFA_ResolveNode_RSType_Attribute; + return true; +} + +bool CFXJSE_ResolveProcessor::ResolveNormal(CFXJSE_ResolveNodeData& rnd) { + if (rnd.m_nLevel > 32 || !rnd.m_CurObject->IsNode()) + return false; + + CXFA_Node* curNode = rnd.m_CurObject->AsNode(); + size_t nNum = rnd.m_Objects.size(); + uint32_t dwStyles = rnd.m_dwStyles; + WideString& wsName = rnd.m_wsName; + XFA_HashCode uNameHash = rnd.m_uHashName; + WideString& wsCondition = rnd.m_wsCondition; + + CFXJSE_ResolveNodeData rndFind(rnd.m_pSC); + rndFind.m_wsName = rnd.m_wsName; + rndFind.m_wsCondition = rnd.m_wsCondition; + rndFind.m_nLevel = rnd.m_nLevel + 1; + rndFind.m_uHashName = uNameHash; + + std::vector children; + std::vector properties; + CXFA_Node* pVariablesNode = nullptr; + CXFA_Node* pPageSetNode = nullptr; + for (CXFA_Node* pChild = curNode->GetFirstChild(); pChild; + pChild = pChild->GetNextSibling()) { + if (pChild->GetElementType() == XFA_Element::Variables) { + pVariablesNode = pChild; + continue; + } + if (pChild->GetElementType() == XFA_Element::PageSet) { + pPageSetNode = pChild; + continue; + } + if (curNode->HasProperty(pChild->GetElementType())) + properties.push_back(pChild); + else + children.push_back(pChild); + } + if ((dwStyles & XFA_RESOLVENODE_Properties) && pVariablesNode) { + if (pVariablesNode->GetClassHashCode() == uNameHash) { + rnd.m_Objects.push_back(pVariablesNode); + } else { + rndFind.m_CurObject = pVariablesNode; + SetStylesForChild(dwStyles, rndFind); + WideString wsSaveCondition = rndFind.m_wsCondition; + rndFind.m_wsCondition.clear(); + ResolveNormal(rndFind); + rndFind.m_wsCondition = wsSaveCondition; + rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + rndFind.m_Objects.clear(); + } + if (rnd.m_Objects.size() > nNum) { + FilterCondition(rnd, wsCondition); + return !rnd.m_Objects.empty(); + } + } + + if (dwStyles & XFA_RESOLVENODE_Children) { + bool bSetFlag = false; + if (pPageSetNode && (dwStyles & XFA_RESOLVENODE_Properties)) + children.push_back(pPageSetNode); + + for (CXFA_Node* child : children) { + if (dwStyles & XFA_RESOLVENODE_TagName) { + if (child->GetClassHashCode() == uNameHash) + rnd.m_Objects.push_back(child); + } else if (child->GetNameHash() == uNameHash) { + rnd.m_Objects.push_back(child); + } + + if (m_pNodeHelper->NodeIsTransparent(child) && + child->GetElementType() != XFA_Element::PageSet) { + if (!bSetFlag) { + SetStylesForChild(dwStyles, rndFind); + bSetFlag = true; + } + rndFind.m_CurObject = child; + + WideString wsSaveCondition = rndFind.m_wsCondition; + rndFind.m_wsCondition.clear(); + ResolveNormal(rndFind); + + rndFind.m_wsCondition = wsSaveCondition; + rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + rndFind.m_Objects.clear(); + } + } + if (rnd.m_Objects.size() > nNum) { + if (!(dwStyles & XFA_RESOLVENODE_ALL)) { + std::vector upArrayNodes; + if (m_pNodeHelper->NodeIsTransparent(ToNode(curNode))) { + m_pNodeHelper->CountSiblings(ToNode(rnd.m_Objects[0]), + XFA_LOGIC_Transparent, &upArrayNodes, + !!(dwStyles & XFA_RESOLVENODE_TagName)); + } + if (upArrayNodes.size() > rnd.m_Objects.size()) { + CXFA_Object* pSaveObject = rnd.m_Objects.front(); + rnd.m_Objects = std::vector(upArrayNodes.begin(), + upArrayNodes.end()); + rnd.m_Objects.front() = pSaveObject; + } + } + FilterCondition(rnd, wsCondition); + return !rnd.m_Objects.empty(); + } + } + if (dwStyles & XFA_RESOLVENODE_Attributes) { + if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView())) + return 1; + } + if (dwStyles & XFA_RESOLVENODE_Properties) { + for (CXFA_Node* pChildProperty : properties) { + if (pChildProperty->IsUnnamed()) { + if (pChildProperty->GetClassHashCode() == uNameHash) + rnd.m_Objects.push_back(pChildProperty); + continue; + } + if (pChildProperty->GetNameHash() == uNameHash && + pChildProperty->GetElementType() != XFA_Element::Extras && + pChildProperty->GetElementType() != XFA_Element::Items) { + rnd.m_Objects.push_back(pChildProperty); + } + } + if (rnd.m_Objects.size() > nNum) { + FilterCondition(rnd, wsCondition); + return !rnd.m_Objects.empty(); + } + + CXFA_Node* pProp = nullptr; + if (XFA_Element::Subform == curNode->GetElementType() && + XFA_HASHCODE_Occur == uNameHash) { + CXFA_Node* pInstanceManager = + curNode->AsNode()->GetInstanceMgrOfSubform(); + if (pInstanceManager) { + pProp = pInstanceManager->JSObject()->GetOrCreateProperty( + 0, XFA_Element::Occur); + } + } else { + XFA_Element eType = CXFA_Node::NameToElement(wsName); + if (eType == XFA_Element::PageSet) { + pProp = curNode->AsNode()->JSObject()->GetProperty(0, eType); + } else if (eType != XFA_Element::Unknown) { + pProp = curNode->AsNode()->JSObject()->GetOrCreateProperty( + 0, eType); + } + } + if (pProp) { + rnd.m_Objects.push_back(pProp); + return !rnd.m_Objects.empty(); + } + } + + CXFA_Node* parentNode = m_pNodeHelper->ResolveNodes_GetParent( + curNode->AsNode(), XFA_LOGIC_NoTransparent); + uint32_t uCurClassHash = curNode->GetClassHashCode(); + if (!parentNode) { + if (uCurClassHash == uNameHash) { + rnd.m_Objects.push_back(curNode->AsNode()); + FilterCondition(rnd, wsCondition); + if (!rnd.m_Objects.empty()) + return true; + } + return false; + } + + if (dwStyles & XFA_RESOLVENODE_Siblings) { + CXFA_Node* child = parentNode->GetFirstChild(); + uint32_t dwSubStyles = + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties; + if (dwStyles & XFA_RESOLVENODE_TagName) + dwSubStyles |= XFA_RESOLVENODE_TagName; + if (dwStyles & XFA_RESOLVENODE_ALL) + dwSubStyles |= XFA_RESOLVENODE_ALL; + + rndFind.m_dwStyles = dwSubStyles; + while (child) { + if (child == curNode) { + if (dwStyles & XFA_RESOLVENODE_TagName) { + if (uCurClassHash == uNameHash) + rnd.m_Objects.push_back(curNode); + } else { + if (child->GetNameHash() == uNameHash) { + rnd.m_Objects.push_back(curNode); + if (rnd.m_nLevel == 0 && wsCondition.GetLength() == 0) { + rnd.m_Objects.clear(); + rnd.m_Objects.push_back(curNode); + return true; + } + } + } + child = child->GetNextSibling(); + continue; + } + + if (dwStyles & XFA_RESOLVENODE_TagName) { + if (child->GetClassHashCode() == uNameHash) + rnd.m_Objects.push_back(child); + } else if (child->GetNameHash() == uNameHash) { + rnd.m_Objects.push_back(child); + } + + bool bInnerSearch = false; + if (parentNode->HasProperty(child->GetElementType())) { + if ((child->GetElementType() == XFA_Element::Variables || + child->GetElementType() == XFA_Element::PageSet)) { + bInnerSearch = true; + } + } else if (m_pNodeHelper->NodeIsTransparent(child)) { + bInnerSearch = true; + } + if (bInnerSearch) { + rndFind.m_CurObject = child; + WideString wsOriginCondition = rndFind.m_wsCondition; + rndFind.m_wsCondition.clear(); + + uint32_t dwOriginStyle = rndFind.m_dwStyles; + rndFind.m_dwStyles = dwOriginStyle | XFA_RESOLVENODE_ALL; + ResolveNormal(rndFind); + + rndFind.m_dwStyles = dwOriginStyle; + rndFind.m_wsCondition = wsOriginCondition; + rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + rndFind.m_Objects.clear(); + } + child = child->GetNextSibling(); + } + if (rnd.m_Objects.size() > nNum) { + if (m_pNodeHelper->NodeIsTransparent(parentNode)) { + std::vector upArrayNodes; + m_pNodeHelper->CountSiblings(ToNode(rnd.m_Objects.front()), + XFA_LOGIC_Transparent, &upArrayNodes, + !!(dwStyles & XFA_RESOLVENODE_TagName)); + if (upArrayNodes.size() > rnd.m_Objects.size()) { + CXFA_Object* pSaveObject = rnd.m_Objects.front(); + rnd.m_Objects = std::vector(upArrayNodes.begin(), + upArrayNodes.end()); + rnd.m_Objects.front() = pSaveObject; + } + } + FilterCondition(rnd, wsCondition); + return !rnd.m_Objects.empty(); + } + } + + if (dwStyles & XFA_RESOLVENODE_Parent) { + uint32_t dwSubStyles = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Properties; + if (dwStyles & XFA_RESOLVENODE_TagName) + dwSubStyles |= XFA_RESOLVENODE_TagName; + if (dwStyles & XFA_RESOLVENODE_ALL) + dwSubStyles |= XFA_RESOLVENODE_ALL; + + rndFind.m_dwStyles = dwSubStyles; + rndFind.m_CurObject = parentNode; + rnd.m_pSC->GetUpObjectArray()->push_back(parentNode); + ResolveNormal(rndFind); + rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(), + rndFind.m_Objects.end()); + rndFind.m_Objects.clear(); + if (rnd.m_Objects.size() > nNum) + return true; + } + return false; +} + +bool CFXJSE_ResolveProcessor::ResolveAsterisk(CFXJSE_ResolveNodeData& rnd) { + CXFA_Node* curNode = ToNode(rnd.m_CurObject); + std::vector array = + curNode->GetNodeList(XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties, + XFA_Element::Unknown); + rnd.m_Objects.insert(rnd.m_Objects.end(), array.begin(), array.end()); + return !rnd.m_Objects.empty(); +} + +int32_t CFXJSE_ResolveProcessor::GetFilter(const WideStringView& wsExpression, + int32_t nStart, + CFXJSE_ResolveNodeData& rnd) { + ASSERT(nStart > -1); + + int32_t iLength = wsExpression.GetLength(); + if (nStart >= iLength) + return 0; + + WideString& wsName = rnd.m_wsName; + WideString& wsCondition = rnd.m_wsCondition; + wchar_t* pNameBuf = wsName.GetBuffer(iLength - nStart); + wchar_t* pConditionBuf = wsCondition.GetBuffer(iLength - nStart); + int32_t nNameCount = 0; + int32_t nConditionCount = 0; + std::vector stack; + int32_t nType = -1; + const wchar_t* pSrc = wsExpression.unterminated_c_str(); + wchar_t wPrev = 0; + wchar_t wCur; + bool bIsCondition = false; + while (nStart < iLength) { + wCur = pSrc[nStart++]; + if (wCur == '.') { + if (wPrev == '\\') { + pNameBuf[nNameCount - 1] = wPrev = '.'; + continue; + } + if (nNameCount == 0) { + rnd.m_dwStyles |= XFA_RESOLVENODE_AnyChild; + continue; + } + + wchar_t wLookahead = nStart < iLength ? pSrc[nStart] : 0; + if (wLookahead != '[' && wLookahead != '(' && nType < 0) + break; + } + if (wCur == '[' || wCur == '(') { + bIsCondition = true; + } else if (wCur == '.' && nStart < iLength && + (pSrc[nStart] == '[' || pSrc[nStart] == '(')) { + bIsCondition = true; + } + if (bIsCondition) + pConditionBuf[nConditionCount++] = wCur; + else + pNameBuf[nNameCount++] = wCur; + + if ((nType == 0 && wCur == ']') || (nType == 1 && wCur == ')') || + (nType == 2 && wCur == '"')) { + nType = stack.empty() ? -1 : stack.back(); + if (!stack.empty()) + stack.pop_back(); + } else if (wCur == '[') { + stack.push_back(nType); + nType = 0; + } else if (wCur == '(') { + stack.push_back(nType); + nType = 1; + } else if (wCur == '"') { + stack.push_back(nType); + nType = 2; + } + wPrev = wCur; + } + if (!stack.empty()) + return -1; + + wsName.ReleaseBuffer(nNameCount); + wsName.Trim(); + wsCondition.ReleaseBuffer(nConditionCount); + wsCondition.Trim(); + rnd.m_uHashName = + static_cast(FX_HashCode_GetW(wsName.AsStringView(), false)); + return nStart; +} + +void CFXJSE_ResolveProcessor::ConditionArray(int32_t iCurIndex, + WideString wsCondition, + int32_t iFoundCount, + CFXJSE_ResolveNodeData& rnd) { + int32_t iLen = wsCondition.GetLength(); + bool bRelative = false; + bool bAll = false; + int32_t i = 1; + for (; i < iLen; ++i) { + wchar_t ch = wsCondition[i]; + if (ch == ' ') + continue; + if (ch == '+' || ch == '-') + bRelative = true; + else if (ch == '*') + bAll = true; + + break; + } + if (bAll) { + if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { + if (rnd.m_dwStyles & XFA_RESOLVENODE_Bind) { + m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurObject); + m_pNodeHelper->m_iCreateCount = 1; + rnd.m_Objects.clear(); + m_pNodeHelper->m_iCurAllStart = -1; + m_pNodeHelper->m_pAllStartParent = nullptr; + } else if (m_pNodeHelper->m_iCurAllStart == -1) { + m_pNodeHelper->m_iCurAllStart = m_iCurStart; + m_pNodeHelper->m_pAllStartParent = ToNode(rnd.m_CurObject); + } + } else if (rnd.m_dwStyles & XFA_RESOLVENODE_BindNew) { + if (m_pNodeHelper->m_iCurAllStart == -1) + m_pNodeHelper->m_iCurAllStart = m_iCurStart; + } + return; + } + if (iFoundCount == 1 && !iLen) + return; + + int32_t iIndex = wsCondition.Mid(i, iLen - 1 - i).GetInteger(); + if (bRelative) + iIndex += iCurIndex; + + if (iFoundCount <= iIndex || iIndex < 0) { + if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { + m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurObject); + m_pNodeHelper->m_iCreateCount = iIndex - iFoundCount + 1; + } + rnd.m_Objects.clear(); + } else { + CXFA_Object* ret = rnd.m_Objects[iIndex]; + rnd.m_Objects.clear(); + rnd.m_Objects.push_back(ret); + } +} + +void CFXJSE_ResolveProcessor::DoPredicateFilter(int32_t iCurIndex, + WideString wsCondition, + int32_t iFoundCount, + CFXJSE_ResolveNodeData& rnd) { + ASSERT(iFoundCount == pdfium::CollectionSize(rnd.m_Objects)); + WideString wsExpression; + CXFA_Script::Type eLangType = CXFA_Script::Type::Unknown; + if (wsCondition.Left(2) == L".[" && wsCondition.Last() == L']') + eLangType = CXFA_Script::Type::Formcalc; + else if (wsCondition.Left(2) == L".(" && wsCondition.Last() == L')') + eLangType = CXFA_Script::Type::Javascript; + else + return; + + CFXJSE_Engine* pContext = rnd.m_pSC; + wsExpression = wsCondition.Mid(2, wsCondition.GetLength() - 3); + for (int32_t i = iFoundCount - 1; i >= 0; i--) { + auto pRetValue = pdfium::MakeUnique(rnd.m_pSC->GetIsolate()); + bool bRet = pContext->RunScript(eLangType, wsExpression.AsStringView(), + pRetValue.get(), rnd.m_Objects[i]); + if (!bRet || !pRetValue->ToBoolean()) + rnd.m_Objects.erase(rnd.m_Objects.begin() + i); + } +} + +void CFXJSE_ResolveProcessor::FilterCondition(CFXJSE_ResolveNodeData& rnd, + WideString wsCondition) { + int32_t iCurrIndex = 0; + const std::vector* pArray = rnd.m_pSC->GetUpObjectArray(); + if (!pArray->empty()) { + CXFA_Node* curNode = pArray->back(); + bool bIsProperty = m_pNodeHelper->NodeIsProperty(curNode); + if (curNode->IsUnnamed() || + (bIsProperty && curNode->GetElementType() != XFA_Element::PageSet)) { + iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent, + bIsProperty, true); + } else { + iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent, + bIsProperty, false); + } + } + + int32_t iFoundCount = pdfium::CollectionSize(rnd.m_Objects); + wsCondition.Trim(); + + int32_t iLen = wsCondition.GetLength(); + if (!iLen) { + if (rnd.m_dwStyles & XFA_RESOLVENODE_ALL) + return; + if (iFoundCount == 1) + return; + + if (iFoundCount <= iCurrIndex) { + if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { + m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurObject); + m_pNodeHelper->m_iCreateCount = iCurrIndex - iFoundCount + 1; + } + rnd.m_Objects.clear(); + return; + } + + CXFA_Object* ret = rnd.m_Objects[iCurrIndex]; + rnd.m_Objects.clear(); + rnd.m_Objects.push_back(ret); + return; + } + + wchar_t wTypeChar = wsCondition[0]; + switch (wTypeChar) { + case '[': + ConditionArray(iCurrIndex, wsCondition, iFoundCount, rnd); + return; + case '.': + if (iLen > 1 && (wsCondition[1] == '[' || wsCondition[1] == '(')) + DoPredicateFilter(iCurrIndex, wsCondition, iFoundCount, rnd); + return; + case '(': + case '"': + default: + return; + } +} +void CFXJSE_ResolveProcessor::SetStylesForChild(uint32_t dwParentStyles, + CFXJSE_ResolveNodeData& rnd) { + uint32_t dwSubStyles = XFA_RESOLVENODE_Children; + if (dwParentStyles & XFA_RESOLVENODE_TagName) + dwSubStyles |= XFA_RESOLVENODE_TagName; + + dwSubStyles &= ~XFA_RESOLVENODE_Parent; + dwSubStyles &= ~XFA_RESOLVENODE_Siblings; + dwSubStyles &= ~XFA_RESOLVENODE_Properties; + dwSubStyles |= XFA_RESOLVENODE_ALL; + rnd.m_dwStyles = dwSubStyles; +} + +void CFXJSE_ResolveProcessor::SetIndexDataBind(WideString& wsNextCondition, + int32_t& iIndex, + int32_t iCount) { + if (m_pNodeHelper->CreateNode_ForCondition(wsNextCondition)) { + if (m_pNodeHelper->m_eLastCreateType == XFA_Element::DataGroup) { + iIndex = 0; + } else { + iIndex = iCount - 1; + } + } else { + iIndex = iCount - 1; + } +} + +CFXJSE_ResolveNodeData::CFXJSE_ResolveNodeData(CFXJSE_Engine* pSC) + : m_pSC(pSC), + m_CurObject(nullptr), + m_wsName(), + m_uHashName(XFA_HASHCODE_None), + m_wsCondition(), + m_nLevel(0), + m_Objects(), + m_dwStyles(XFA_RESOLVENODE_Children), + m_pScriptAttribute(nullptr), + m_dwFlag(XFA_ResolveNode_RSType_Nodes) {} + +CFXJSE_ResolveNodeData::~CFXJSE_ResolveNodeData() {} diff --git a/fxjs/cfxjse_resolveprocessor.h b/fxjs/cfxjse_resolveprocessor.h new file mode 100644 index 0000000000000000000000000000000000000000..71aba6efa84dca8f056e680e69e5ba3bbb2b43c9 --- /dev/null +++ b/fxjs/cfxjse_resolveprocessor.h @@ -0,0 +1,77 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CFXJSE_RESOLVEPROCESSOR_H_ +#define FXJS_CFXJSE_RESOLVEPROCESSOR_H_ + +#include +#include + +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +class CXFA_NodeHelper; +class CFXJSE_Engine; + +class CFXJSE_ResolveNodeData { + public: + explicit CFXJSE_ResolveNodeData(CFXJSE_Engine* pSC); + ~CFXJSE_ResolveNodeData(); + + CFXJSE_Engine* m_pSC; + CXFA_Object* m_CurObject; + WideString m_wsName; + XFA_HashCode m_uHashName; + WideString m_wsCondition; + int32_t m_nLevel; + std::vector m_Objects; // Not owned. + uint32_t m_dwStyles; + const XFA_SCRIPTATTRIBUTEINFO* m_pScriptAttribute; + XFA_ResolveNode_RSType m_dwFlag; +}; + +class CFXJSE_ResolveProcessor { + public: + CFXJSE_ResolveProcessor(); + ~CFXJSE_ResolveProcessor(); + + bool Resolve(CFXJSE_ResolveNodeData& rnd); + int32_t GetFilter(const WideStringView& wsExpression, + int32_t nStart, + CFXJSE_ResolveNodeData& rnd); + void SetIndexDataBind(WideString& wsNextCondition, + int32_t& iIndex, + int32_t iCount); + void SetCurStart(int32_t start) { m_iCurStart = start; } + + CXFA_NodeHelper* GetNodeHelper() const { return m_pNodeHelper.get(); } + + private: + bool ResolveForAttributeRs(CXFA_Object* curNode, + CFXJSE_ResolveNodeData& rnd, + const WideStringView& strAttr); + bool ResolveAnyChild(CFXJSE_ResolveNodeData& rnd); + bool ResolveDollar(CFXJSE_ResolveNodeData& rnd); + bool ResolveExcalmatory(CFXJSE_ResolveNodeData& rnd); + bool ResolveNumberSign(CFXJSE_ResolveNodeData& rnd); + bool ResolveAsterisk(CFXJSE_ResolveNodeData& rnd); + bool ResolveNormal(CFXJSE_ResolveNodeData& rnd); + void SetStylesForChild(uint32_t dwParentStyles, CFXJSE_ResolveNodeData& rnd); + + void ConditionArray(int32_t iCurIndex, + WideString wsCondition, + int32_t iFoundCount, + CFXJSE_ResolveNodeData& rnd); + void DoPredicateFilter(int32_t iCurIndex, + WideString wsCondition, + int32_t iFoundCount, + CFXJSE_ResolveNodeData& rnd); + void FilterCondition(CFXJSE_ResolveNodeData& rnd, WideString wsCondition); + + int32_t m_iCurStart; + std::unique_ptr m_pNodeHelper; +}; + +#endif // FXJS_CFXJSE_RESOLVEPROCESSOR_H_ diff --git a/fxjs/cfxjse_runtimedata.cpp b/fxjs/cfxjse_runtimedata.cpp index b8df9ce0b315468cacb3236a58e8fa4958ee265c..b5c2de929774e87e2ebe55b589ed1c53da247c87 100644 --- a/fxjs/cfxjse_runtimedata.cpp +++ b/fxjs/cfxjse_runtimedata.cpp @@ -11,67 +11,6 @@ #include "fxjs/cfxjse_isolatetracker.h" #include "fxjs/fxjs_v8.h" -namespace { - -// Duplicates fpdfsdk's cjs_runtime.h, but keeps XFA from depending on it. -// TODO(tsepez): make a single version of this. -class FXJSE_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { - void* Allocate(size_t length) override { return calloc(1, length); } - void* AllocateUninitialized(size_t length) override { return malloc(length); } - void Free(void* data, size_t length) override { free(data); } -}; - -void Runtime_DisposeCallback(v8::Isolate* pIsolate, bool bOwned) { - if (FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate)) - delete pData; - if (bOwned) - pIsolate->Dispose(); -} - -void KillV8() { - v8::V8::Dispose(); -} - -} // namespace - -void FXJSE_Initialize() { - if (!CFXJSE_IsolateTracker::g_pInstance) - CFXJSE_IsolateTracker::g_pInstance = new CFXJSE_IsolateTracker; - - static bool bV8Initialized = false; - if (bV8Initialized) - return; - - bV8Initialized = true; - atexit(KillV8); -} - -void FXJSE_Finalize() { - if (!CFXJSE_IsolateTracker::g_pInstance) - return; - - CFXJSE_IsolateTracker::g_pInstance->RemoveAll(Runtime_DisposeCallback); - delete CFXJSE_IsolateTracker::g_pInstance; - CFXJSE_IsolateTracker::g_pInstance = nullptr; -} - -v8::Isolate* FXJSE_Runtime_Create_Own() { - std::unique_ptr allocator( - new FXJSE_ArrayBufferAllocator()); - v8::Isolate::CreateParams params; - params.array_buffer_allocator = allocator.get(); - v8::Isolate* pIsolate = v8::Isolate::New(params); - ASSERT(pIsolate && CFXJSE_IsolateTracker::g_pInstance); - CFXJSE_IsolateTracker::g_pInstance->Append(pIsolate, std::move(allocator)); - return pIsolate; -} - -void FXJSE_Runtime_Release(v8::Isolate* pIsolate) { - if (!pIsolate) - return; - CFXJSE_IsolateTracker::g_pInstance->Remove(pIsolate, Runtime_DisposeCallback); -} - CFXJSE_RuntimeData::CFXJSE_RuntimeData(v8::Isolate* pIsolate) : m_pIsolate(pIsolate) {} @@ -82,6 +21,7 @@ std::unique_ptr CFXJSE_RuntimeData::Create( std::unique_ptr pRuntimeData( new CFXJSE_RuntimeData(pIsolate)); CFXJSE_ScopeUtil_IsolateHandle scope(pIsolate); + v8::Local hFuncTemplate = v8::FunctionTemplate::New(pIsolate); v8::Local hGlobalTemplate = @@ -90,9 +30,11 @@ std::unique_ptr CFXJSE_RuntimeData::Create( v8::Symbol::GetToStringTag(pIsolate), v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal) .ToLocalChecked()); + v8::Local hContext = v8::Context::New(pIsolate, 0, hGlobalTemplate); hContext->SetSecurityToken(v8::External::New(pIsolate, pIsolate)); + pRuntimeData->m_hRootContextGlobalTemplate.Reset(pIsolate, hFuncTemplate); pRuntimeData->m_hRootContext.Reset(pIsolate, hContext); return pRuntimeData; @@ -100,10 +42,9 @@ std::unique_ptr CFXJSE_RuntimeData::Create( CFXJSE_RuntimeData* CFXJSE_RuntimeData::Get(v8::Isolate* pIsolate) { FXJS_PerIsolateData::SetUp(pIsolate); + FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); if (!pData->m_pFXJSERuntimeData) pData->m_pFXJSERuntimeData = CFXJSE_RuntimeData::Create(pIsolate); return pData->m_pFXJSERuntimeData.get(); } - -CFXJSE_IsolateTracker* CFXJSE_IsolateTracker::g_pInstance = nullptr; diff --git a/fxjs/cfxjse_value.cpp b/fxjs/cfxjse_value.cpp index 68c82e5deb3b7bc1437c3fdac7dba59438e892f0..d07b3565d3d5121d262f9367aa55b8e91c0e4e39 100644 --- a/fxjs/cfxjse_value.cpp +++ b/fxjs/cfxjse_value.cpp @@ -13,8 +13,8 @@ namespace { -double ftod(FX_FLOAT fNumber) { - static_assert(sizeof(FX_FLOAT) == 4, "FX_FLOAT of incorrect size"); +double ftod(float fNumber) { + static_assert(sizeof(float) == 4, "float of incorrect size"); uint32_t nFloatBits = (uint32_t&)fNumber; uint8_t nExponent = (uint8_t)(nFloatBits >> 23); @@ -52,13 +52,13 @@ double ftod(FX_FLOAT fNumber) { } // namespace -void FXJSE_ThrowMessage(const CFX_ByteStringC& utf8Message) { +void FXJSE_ThrowMessage(const ByteStringView& utf8Message) { v8::Isolate* pIsolate = v8::Isolate::GetCurrent(); ASSERT(pIsolate); CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate); v8::Local hMessage = v8::String::NewFromUtf8( - pIsolate, utf8Message.c_str(), v8::String::kNormalString, + pIsolate, utf8Message.unterminated_c_str(), v8::String::kNormalString, utf8Message.GetLength()); v8::Local hError = v8::Exception::Error(hMessage); pIsolate->ThrowException(hError); @@ -83,20 +83,9 @@ CFXJSE_HostObject* CFXJSE_Value::ToHostObject(CFXJSE_Class* lpClass) const { void CFXJSE_Value::SetObject(CFXJSE_HostObject* lpObject, CFXJSE_Class* pClass) { - if (!pClass) { - ASSERT(!lpObject); - SetJSObject(); - return; - } - SetHostObject(lpObject, pClass); -} - -void CFXJSE_Value::SetHostObject(CFXJSE_HostObject* lpObject, - CFXJSE_Class* lpClass) { CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); - ASSERT(lpClass); v8::Local hClass = - v8::Local::New(m_pIsolate, lpClass->m_hTemplate); + v8::Local::New(m_pIsolate, pClass->m_hTemplate); v8::Local hObject = hClass->InstanceTemplate()->NewInstance(); FXJSE_UpdateObjectBinding(hObject, lpObject); m_hValue.Reset(m_pIsolate, hObject); @@ -120,13 +109,13 @@ void CFXJSE_Value::SetDate(double dDouble) { m_hValue.Reset(m_pIsolate, hDate); } -void CFXJSE_Value::SetFloat(FX_FLOAT fFloat) { +void CFXJSE_Value::SetFloat(float fFloat) { CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate); v8::Local pValue = v8::Number::New(m_pIsolate, ftod(fFloat)); m_hValue.Reset(m_pIsolate, pValue); } -bool CFXJSE_Value::SetObjectProperty(const CFX_ByteStringC& szPropName, +bool CFXJSE_Value::SetObjectProperty(const ByteStringView& szPropName, CFXJSE_Value* lpPropValue) { ASSERT(lpPropValue); CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); @@ -138,13 +127,13 @@ bool CFXJSE_Value::SetObjectProperty(const CFX_ByteStringC& szPropName, v8::Local hPropValue = v8::Local::New(m_pIsolate, lpPropValue->DirectGetValue()); return (bool)hObject.As()->Set( - v8::String::NewFromUtf8(m_pIsolate, szPropName.c_str(), + v8::String::NewFromUtf8(m_pIsolate, szPropName.unterminated_c_str(), v8::String::kNormalString, szPropName.GetLength()), hPropValue); } -bool CFXJSE_Value::GetObjectProperty(const CFX_ByteStringC& szPropName, +bool CFXJSE_Value::GetObjectProperty(const ByteStringView& szPropName, CFXJSE_Value* lpPropValue) { ASSERT(lpPropValue); CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); @@ -155,8 +144,8 @@ bool CFXJSE_Value::GetObjectProperty(const CFX_ByteStringC& szPropName, v8::Local hPropValue = hObject.As()->Get(v8::String::NewFromUtf8( - m_pIsolate, szPropName.c_str(), v8::String::kNormalString, - szPropName.GetLength())); + m_pIsolate, szPropName.unterminated_c_str(), + v8::String::kNormalString, szPropName.GetLength())); lpPropValue->ForceSetValue(hPropValue); return true; } @@ -187,7 +176,7 @@ bool CFXJSE_Value::GetObjectPropertyByIdx(uint32_t uPropIdx, return true; } -bool CFXJSE_Value::DeleteObjectProperty(const CFX_ByteStringC& szPropName) { +bool CFXJSE_Value::DeleteObjectProperty(const ByteStringView& szPropName) { CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); v8::Local hObject = v8::Local::New(m_pIsolate, m_hValue); @@ -195,12 +184,12 @@ bool CFXJSE_Value::DeleteObjectProperty(const CFX_ByteStringC& szPropName) { return false; hObject.As()->Delete(v8::String::NewFromUtf8( - m_pIsolate, szPropName.c_str(), v8::String::kNormalString, + m_pIsolate, szPropName.unterminated_c_str(), v8::String::kNormalString, szPropName.GetLength())); return true; } -bool CFXJSE_Value::HasObjectOwnProperty(const CFX_ByteStringC& szPropName, +bool CFXJSE_Value::HasObjectOwnProperty(const ByteStringView& szPropName, bool bUseTypeGetter) { CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); v8::Local hObject = @@ -209,7 +198,7 @@ bool CFXJSE_Value::HasObjectOwnProperty(const CFX_ByteStringC& szPropName, return false; v8::Local hKey = v8::String::NewFromUtf8( - m_pIsolate, szPropName.c_str(), v8::String::kNormalString, + m_pIsolate, szPropName.unterminated_c_str(), v8::String::kNormalString, szPropName.GetLength()); return hObject.As()->HasRealNamedProperty(hKey) || (bUseTypeGetter && @@ -218,7 +207,7 @@ bool CFXJSE_Value::HasObjectOwnProperty(const CFX_ByteStringC& szPropName, .FromMaybe(false)); } -bool CFXJSE_Value::SetObjectOwnProperty(const CFX_ByteStringC& szPropName, +bool CFXJSE_Value::SetObjectOwnProperty(const ByteStringView& szPropName, CFXJSE_Value* lpPropValue) { ASSERT(lpPropValue); CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); @@ -232,7 +221,7 @@ bool CFXJSE_Value::SetObjectOwnProperty(const CFX_ByteStringC& szPropName, return hObject.As() ->DefineOwnProperty( m_pIsolate->GetCurrentContext(), - v8::String::NewFromUtf8(m_pIsolate, szPropName.c_str(), + v8::String::NewFromUtf8(m_pIsolate, szPropName.unterminated_c_str(), v8::String::kNormalString, szPropName.GetLength()), pValue) @@ -272,79 +261,6 @@ bool CFXJSE_Value::SetFunctionBind(CFXJSE_Value* lpOldFunction, return true; } -#define FXJSE_INVALID_PTR ((void*)(intptr_t)-1) -bool CFXJSE_Value::Call(CFXJSE_Value* lpReceiver, - CFXJSE_Value* lpRetValue, - uint32_t nArgCount, - CFXJSE_Value** lpArgs) { - CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); - v8::Local hFunctionValue = - v8::Local::New(m_pIsolate, DirectGetValue()); - v8::Local hFunctionObject = - !hFunctionValue.IsEmpty() && hFunctionValue->IsObject() - ? hFunctionValue.As() - : v8::Local(); - - v8::TryCatch trycatch(m_pIsolate); - if (hFunctionObject.IsEmpty() || !hFunctionObject->IsCallable()) { - if (lpRetValue) - lpRetValue->ForceSetValue(FXJSE_CreateReturnValue(m_pIsolate, trycatch)); - return false; - } - - v8::Local hReturnValue; - v8::Local* lpLocalArgs = NULL; - if (nArgCount) { - lpLocalArgs = FX_Alloc(v8::Local, nArgCount); - for (uint32_t i = 0; i < nArgCount; i++) { - new (lpLocalArgs + i) v8::Local; - CFXJSE_Value* lpArg = lpArgs[i]; - if (lpArg) { - lpLocalArgs[i] = - v8::Local::New(m_pIsolate, lpArg->DirectGetValue()); - } - if (lpLocalArgs[i].IsEmpty()) { - lpLocalArgs[i] = v8::Undefined(m_pIsolate); - } - } - } - - bool bRetValue = true; - if (lpReceiver == FXJSE_INVALID_PTR) { - v8::MaybeLocal maybe_retvalue = - hFunctionObject->CallAsConstructor(m_pIsolate->GetCurrentContext(), - nArgCount, lpLocalArgs); - hReturnValue = maybe_retvalue.FromMaybe(v8::Local()); - } else { - v8::Local hReceiver; - if (lpReceiver) { - hReceiver = - v8::Local::New(m_pIsolate, lpReceiver->DirectGetValue()); - } - if (hReceiver.IsEmpty() || !hReceiver->IsObject()) - hReceiver = v8::Object::New(m_pIsolate); - - v8::MaybeLocal maybe_retvalue = hFunctionObject->CallAsFunction( - m_pIsolate->GetCurrentContext(), hReceiver, nArgCount, lpLocalArgs); - hReturnValue = maybe_retvalue.FromMaybe(v8::Local()); - } - - if (trycatch.HasCaught()) { - hReturnValue = FXJSE_CreateReturnValue(m_pIsolate, trycatch); - bRetValue = false; - } - - if (lpRetValue) - lpRetValue->ForceSetValue(hReturnValue); - - if (lpLocalArgs) { - for (uint32_t i = 0; i < nArgCount; i++) - lpLocalArgs[i].~Local(); - FX_Free(lpLocalArgs); - } - return bRetValue; -} - bool CFXJSE_Value::IsUndefined() const { if (m_hValue.IsEmpty()) return false; @@ -442,11 +358,11 @@ bool CFXJSE_Value::ToBoolean() const { return static_cast(hValue->BooleanValue()); } -FX_FLOAT CFXJSE_Value::ToFloat() const { +float CFXJSE_Value::ToFloat() const { ASSERT(!m_hValue.IsEmpty()); CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); v8::Local hValue = v8::Local::New(m_pIsolate, m_hValue); - return static_cast(hValue->NumberValue()); + return static_cast(hValue->NumberValue()); } double CFXJSE_Value::ToDouble() const { @@ -463,13 +379,13 @@ int32_t CFXJSE_Value::ToInteger() const { return static_cast(hValue->NumberValue()); } -CFX_ByteString CFXJSE_Value::ToString() const { +ByteString CFXJSE_Value::ToString() const { ASSERT(!m_hValue.IsEmpty()); CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); v8::Local hValue = v8::Local::New(m_pIsolate, m_hValue); v8::Local hString = hValue->ToString(); - v8::String::Utf8Value hStringVal(hString); - return CFX_ByteString(*hStringVal); + v8::String::Utf8Value hStringVal(m_pIsolate, hString); + return ByteString(*hStringVal); } void CFXJSE_Value::SetUndefined() { @@ -502,7 +418,7 @@ void CFXJSE_Value::SetDouble(double dDouble) { m_hValue.Reset(m_pIsolate, hValue); } -void CFXJSE_Value::SetString(const CFX_ByteStringC& szString) { +void CFXJSE_Value::SetString(const ByteStringView& szString) { CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate); v8::Local hValue = v8::String::NewFromUtf8( m_pIsolate, reinterpret_cast(szString.raw_str()), @@ -510,8 +426,3 @@ void CFXJSE_Value::SetString(const CFX_ByteStringC& szString) { m_hValue.Reset(m_pIsolate, hValue); } -void CFXJSE_Value::SetJSObject() { - CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate); - v8::Local hValue = v8::Object::New(m_pIsolate); - m_hValue.Reset(m_pIsolate, hValue); -} diff --git a/fxjs/cfxjse_value.h b/fxjs/cfxjse_value.h index f2ebdc1c25629771ffbd110bbb3e2f95026bf4c4..52bb036b95d27d3b2698ff74296d928e210a5e89 100644 --- a/fxjs/cfxjse_value.h +++ b/fxjs/cfxjse_value.h @@ -35,12 +35,12 @@ class CFXJSE_Value { bool IsFunction() const; bool IsDate() const; bool ToBoolean() const; - FX_FLOAT ToFloat() const; + float ToFloat() const; double ToDouble() const; int32_t ToInteger() const; - CFX_ByteString ToString() const; - CFX_WideString ToWideString() const { - return CFX_WideString::FromUTF8(ToString().AsStringC()); + ByteString ToString() const; + WideString ToWideString() const { + return WideString::FromUTF8(ToString().AsStringView()); } CFXJSE_HostObject* ToHostObject(CFXJSE_Class* lpClass) const; @@ -49,31 +49,25 @@ class CFXJSE_Value { void SetBoolean(bool bBoolean); void SetInteger(int32_t nInteger); void SetDouble(double dDouble); - void SetString(const CFX_ByteStringC& szString); - void SetFloat(FX_FLOAT fFloat); - void SetJSObject(); + void SetString(const ByteStringView& szString); + void SetFloat(float fFloat); void SetObject(CFXJSE_HostObject* lpObject, CFXJSE_Class* pClass); - void SetHostObject(CFXJSE_HostObject* lpObject, CFXJSE_Class* lpClass); void SetArray(const std::vector>& values); void SetDate(double dDouble); - bool GetObjectProperty(const CFX_ByteStringC& szPropName, + bool GetObjectProperty(const ByteStringView& szPropName, CFXJSE_Value* lpPropValue); - bool SetObjectProperty(const CFX_ByteStringC& szPropName, + bool SetObjectProperty(const ByteStringView& szPropName, CFXJSE_Value* lpPropValue); bool GetObjectPropertyByIdx(uint32_t uPropIdx, CFXJSE_Value* lpPropValue); bool SetObjectProperty(uint32_t uPropIdx, CFXJSE_Value* lpPropValue); - bool DeleteObjectProperty(const CFX_ByteStringC& szPropName); - bool HasObjectOwnProperty(const CFX_ByteStringC& szPropName, + bool DeleteObjectProperty(const ByteStringView& szPropName); + bool HasObjectOwnProperty(const ByteStringView& szPropName, bool bUseTypeGetter); - bool SetObjectOwnProperty(const CFX_ByteStringC& szPropName, + bool SetObjectOwnProperty(const ByteStringView& szPropName, CFXJSE_Value* lpPropValue); bool SetFunctionBind(CFXJSE_Value* lpOldFunction, CFXJSE_Value* lpNewThis); - bool Call(CFXJSE_Value* lpReceiver, - CFXJSE_Value* lpRetValue, - uint32_t nArgCount, - CFXJSE_Value** lpArgs); v8::Isolate* GetIsolate() const { return m_pIsolate; } const v8::Global& DirectGetValue() const { return m_hValue; } diff --git a/fxjs/cjs_annot.cpp b/fxjs/cjs_annot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69eccefa2762acc8dbf4943a351bc5ac3ef20db8 --- /dev/null +++ b/fxjs/cjs_annot.cpp @@ -0,0 +1,111 @@ +// Copyright 2016 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 "fxjs/cjs_annot.h" + +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_object.h" +#include "fxjs/js_resources.h" + +namespace { + +CPDFSDK_BAAnnot* ToBAAnnot(CPDFSDK_Annot* annot) { + return static_cast(annot); +} + +} // namespace + +const JSPropertySpec CJS_Annot::PropertySpecs[] = { + {"hidden", get_hidden_static, set_hidden_static}, + {"name", get_name_static, set_name_static}, + {"type", get_type_static, set_type_static}}; + +int CJS_Annot::ObjDefnID = -1; + +// static +int CJS_Annot::GetObjDefnID() { + return ObjDefnID; +} + +// static +void CJS_Annot::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("Annot", FXJSOBJTYPE_DYNAMIC, + JSConstructor, + JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); +} + +Annot::Annot(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} + +Annot::~Annot() {} + +CJS_Return Annot::get_hidden(CJS_Runtime* pRuntime) { + if (!m_pAnnot) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDF_Annot* pPDFAnnot = ToBAAnnot(m_pAnnot.Get())->GetPDFAnnot(); + return CJS_Return(pRuntime->NewBoolean( + CPDF_Annot::IsAnnotationHidden(pPDFAnnot->GetAnnotDict()))); +} + +CJS_Return Annot::set_hidden(CJS_Runtime* pRuntime, v8::Local vp) { + // May invalidate m_pAnnot. + bool bHidden = pRuntime->ToBoolean(vp); + if (!m_pAnnot) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + uint32_t flags = ToBAAnnot(m_pAnnot.Get())->GetFlags(); + if (bHidden) { + flags |= ANNOTFLAG_HIDDEN; + flags |= ANNOTFLAG_INVISIBLE; + flags |= ANNOTFLAG_NOVIEW; + flags &= ~ANNOTFLAG_PRINT; + } else { + flags &= ~ANNOTFLAG_HIDDEN; + flags &= ~ANNOTFLAG_INVISIBLE; + flags &= ~ANNOTFLAG_NOVIEW; + flags |= ANNOTFLAG_PRINT; + } + ToBAAnnot(m_pAnnot.Get())->SetFlags(flags); + + return CJS_Return(true); +} + +CJS_Return Annot::get_name(CJS_Runtime* pRuntime) { + if (!m_pAnnot) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return( + pRuntime->NewString(ToBAAnnot(m_pAnnot.Get())->GetAnnotName().c_str())); +} + +CJS_Return Annot::set_name(CJS_Runtime* pRuntime, v8::Local vp) { + // May invalidate m_pAnnot. + WideString annotName = pRuntime->ToWideString(vp); + if (!m_pAnnot) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + ToBAAnnot(m_pAnnot.Get())->SetAnnotName(annotName); + return CJS_Return(true); +} + +CJS_Return Annot::get_type(CJS_Runtime* pRuntime) { + if (!m_pAnnot) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return(pRuntime->NewString( + WideString::FromLocal(CPDF_Annot::AnnotSubtypeToString( + ToBAAnnot(m_pAnnot.Get())->GetAnnotSubtype()) + .c_str()) + .c_str())); +} + +CJS_Return Annot::set_type(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +void Annot::SetSDKAnnot(CPDFSDK_BAAnnot* annot) { + m_pAnnot.Reset(annot); +} diff --git a/fxjs/cjs_annot.h b/fxjs/cjs_annot.h new file mode 100644 index 0000000000000000000000000000000000000000..18124f6216adedde21bf485d78173c800bdfae9a --- /dev/null +++ b/fxjs/cjs_annot.h @@ -0,0 +1,50 @@ +// Copyright 2016 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 FXJS_CJS_ANNOT_H_ +#define FXJS_CJS_ANNOT_H_ + +#include "fpdfsdk/cpdfsdk_baannot.h" +#include "fxjs/JS_Define.h" + +class Annot : public CJS_EmbedObj { + public: + explicit Annot(CJS_Object* pJSObject); + ~Annot() override; + + CJS_Return get_hidden(CJS_Runtime* pRuntime); + CJS_Return set_hidden(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_name(CJS_Runtime* pRuntime); + CJS_Return set_name(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_type(CJS_Runtime* pRuntime); + CJS_Return set_type(CJS_Runtime* pRuntime, v8::Local vp); + + void SetSDKAnnot(CPDFSDK_BAAnnot* annot); + + private: + CPDFSDK_Annot::ObservedPtr m_pAnnot; +}; + +class CJS_Annot : public CJS_Object { + public: + static int GetObjDefnID(); + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Annot(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Annot() override {} + + JS_STATIC_PROP(hidden, hidden, Annot); + JS_STATIC_PROP(name, name, Annot); + JS_STATIC_PROP(type, type, Annot); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; +}; + +#endif // FXJS_CJS_ANNOT_H_ diff --git a/fxjs/cjs_app.cpp b/fxjs/cjs_app.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32cac22153f0d0a581dd1d55ca429a58c41ff19c --- /dev/null +++ b/fxjs/cjs_app.cpp @@ -0,0 +1,577 @@ +// 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 "fxjs/cjs_app.h" + +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fxjs/cjs_document.h" +#include "fxjs/cjs_timerobj.h" +#include "fxjs/global_timer.h" +#include "fxjs/ijs_event_context.h" +#include "fxjs/js_resources.h" + +namespace { + +bool IsTypeKnown(v8::Local value) { + return !value.IsEmpty() && + (value->IsString() || value->IsNumber() || value->IsBoolean() || + value->IsDate() || value->IsObject() || value->IsNull() || + value->IsUndefined()); +} + +} // namespace + +#define JS_STR_VIEWERTYPE L"pdfium" +#define JS_STR_VIEWERVARIATION L"Full" +#define JS_STR_PLATFORM L"WIN" +#define JS_STR_LANGUAGE L"ENU" +#define JS_NUM_VIEWERVERSION 8 +#ifdef PDF_ENABLE_XFA +#define JS_NUM_VIEWERVERSION_XFA 11 +#endif // PDF_ENABLE_XFA +#define JS_NUM_FORMSVERSION 7 + +const JSPropertySpec CJS_App::PropertySpecs[] = { + {"activeDocs", get_active_docs_static, set_active_docs_static}, + {"calculate", get_calculate_static, set_calculate_static}, + {"formsVersion", get_forms_version_static, set_forms_version_static}, + {"fs", get_fs_static, set_fs_static}, + {"fullscreen", get_fullscreen_static, set_fullscreen_static}, + {"language", get_language_static, set_language_static}, + {"media", get_media_static, set_media_static}, + {"platform", get_platform_static, set_platform_static}, + {"runtimeHighlight", get_runtime_highlight_static, + set_runtime_highlight_static}, + {"viewerType", get_viewer_type_static, set_viewer_type_static}, + {"viewerVariation", get_viewer_variation_static, + set_viewer_variation_static}, + {"viewerVersion", get_viewer_version_static, set_viewer_version_static}}; + +const JSMethodSpec CJS_App::MethodSpecs[] = { + {"alert", alert_static}, + {"beep", beep_static}, + {"browseForDoc", browseForDoc_static}, + {"clearInterval", clearInterval_static}, + {"clearTimeOut", clearTimeOut_static}, + {"execDialog", execDialog_static}, + {"execMenuItem", execMenuItem_static}, + {"findComponent", findComponent_static}, + {"goBack", goBack_static}, + {"goForward", goForward_static}, + {"launchURL", launchURL_static}, + {"mailMsg", mailMsg_static}, + {"newFDF", newFDF_static}, + {"newDoc", newDoc_static}, + {"openDoc", openDoc_static}, + {"openFDF", openFDF_static}, + {"popUpMenuEx", popUpMenuEx_static}, + {"popUpMenu", popUpMenu_static}, + {"response", response_static}, + {"setInterval", setInterval_static}, + {"setTimeOut", setTimeOut_static}}; + +int CJS_App::ObjDefnID = -1; + +// static +void CJS_App::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("app", FXJSOBJTYPE_STATIC, JSConstructor, + JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +app::app(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {} + +app::~app() {} + +CJS_Return app::get_active_docs(CJS_Runtime* pRuntime) { + CJS_Document* pJSDocument = nullptr; + v8::Local pObj = pRuntime->GetThisObj(); + if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::GetObjDefnID()) + pJSDocument = static_cast(pRuntime->GetObjectPrivate(pObj)); + + v8::Local aDocs = pRuntime->NewArray(); + pRuntime->PutArrayElement( + aDocs, 0, + pJSDocument ? v8::Local(pJSDocument->ToV8Object()) + : v8::Local()); + if (pRuntime->GetArrayLength(aDocs) > 0) + return CJS_Return(aDocs); + return CJS_Return(pRuntime->NewUndefined()); +} + +CJS_Return app::set_active_docs(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::get_calculate(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewBoolean(m_bCalculate)); +} + +CJS_Return app::set_calculate(CJS_Runtime* pRuntime, v8::Local vp) { + m_bCalculate = pRuntime->ToBoolean(vp); + pRuntime->GetFormFillEnv()->GetInterForm()->EnableCalculate(m_bCalculate); + return CJS_Return(true); +} + +CJS_Return app::get_forms_version(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewNumber(JS_NUM_FORMSVERSION)); +} + +CJS_Return app::set_forms_version(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::get_viewer_type(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewString(JS_STR_VIEWERTYPE)); +} + +CJS_Return app::set_viewer_type(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::get_viewer_variation(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewString(JS_STR_VIEWERVARIATION)); +} + +CJS_Return app::set_viewer_variation(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::get_viewer_version(CJS_Runtime* pRuntime) { +#ifdef PDF_ENABLE_XFA + CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext(); + if (pXFAContext->ContainsXFAForm()) + return CJS_Return(pRuntime->NewNumber(JS_NUM_VIEWERVERSION_XFA)); +#endif // PDF_ENABLE_XFA + return CJS_Return(pRuntime->NewNumber(JS_NUM_VIEWERVERSION)); +} + +CJS_Return app::set_viewer_version(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::get_platform(CJS_Runtime* pRuntime) { +#ifdef PDF_ENABLE_XFA + CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); + if (!pFormFillEnv) + return CJS_Return(false); + + WideString platfrom = pFormFillEnv->GetPlatform(); + if (!platfrom.IsEmpty()) + return CJS_Return(pRuntime->NewString(platfrom.c_str())); +#endif + return CJS_Return(pRuntime->NewString(JS_STR_PLATFORM)); +} + +CJS_Return app::set_platform(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::get_language(CJS_Runtime* pRuntime) { +#ifdef PDF_ENABLE_XFA + CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); + if (!pFormFillEnv) + return CJS_Return(false); + + WideString language = pFormFillEnv->GetLanguage(); + if (!language.IsEmpty()) + return CJS_Return(pRuntime->NewString(language.c_str())); +#endif + return CJS_Return(pRuntime->NewString(JS_STR_LANGUAGE)); +} + +CJS_Return app::set_language(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +// creates a new fdf object that contains no data +// comment: need reader support +// note: +// CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF(); +CJS_Return app::newFDF(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +// opens a specified pdf document and returns its document object +// comment:need reader support +// note: as defined in js reference, the proto of this function's fourth +// parmeters, how old an fdf document while do not show it. +// CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool +// bUserConv); + +CJS_Return app::openFDF(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return app::alert(CJS_Runtime* pRuntime, + const std::vector>& params) { + std::vector> newParams = ExpandKeywordParams( + pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle"); + + if (!IsTypeKnown(newParams[0])) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); + if (!pFormFillEnv) + return CJS_Return(pRuntime->NewNumber(0)); + + WideString swMsg; + if (newParams[0]->IsArray()) { + v8::Local carray = pRuntime->ToArray(newParams[0]); + swMsg = L"["; + for (size_t i = 0; i < pRuntime->GetArrayLength(carray); ++i) { + if (i) + swMsg += L", "; + + swMsg += pRuntime->ToWideString(pRuntime->GetArrayElement(carray, i)); + } + swMsg += L"]"; + } else { + swMsg = pRuntime->ToWideString(newParams[0]); + } + + int iIcon = 0; + if (IsTypeKnown(newParams[1])) + iIcon = pRuntime->ToInt32(newParams[1]); + + int iType = 0; + if (IsTypeKnown(newParams[2])) + iType = pRuntime->ToInt32(newParams[2]); + + WideString swTitle; + if (IsTypeKnown(newParams[3])) + swTitle = pRuntime->ToWideString(newParams[3]); + else + swTitle = JSGetStringFromID(JSMessage::kAlert); + + pRuntime->BeginBlock(); + pFormFillEnv->KillFocusAnnot(0); + + v8::Local ret = pRuntime->NewNumber( + pFormFillEnv->JS_appAlert(swMsg.c_str(), swTitle.c_str(), iType, iIcon)); + pRuntime->EndBlock(); + + return CJS_Return(ret); +} + +CJS_Return app::beep(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() == 1) { + pRuntime->GetFormFillEnv()->JS_appBeep(pRuntime->ToInt32(params[0])); + return CJS_Return(true); + } + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); +} + +CJS_Return app::findComponent(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return app::popUpMenuEx(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return app::get_fs(CJS_Runtime* pRuntime) { + return CJS_Return(false); +} + +CJS_Return app::set_fs(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::setInterval(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() > 2 || params.size() == 0) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString script = + params.size() > 0 ? pRuntime->ToWideString(params[0]) : L""; + if (script.IsEmpty()) + return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError)); + + uint32_t dwInterval = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 1000; + GlobalTimer* timerRef = new GlobalTimer(this, pRuntime->GetFormFillEnv(), + pRuntime, 0, script, dwInterval, 0); + m_Timers.insert(std::unique_ptr(timerRef)); + + v8::Local pRetObj = + pRuntime->NewFxDynamicObj(CJS_TimerObj::GetObjDefnID()); + if (pRetObj.IsEmpty()) + return CJS_Return(false); + + CJS_TimerObj* pJS_TimerObj = + static_cast(pRuntime->GetObjectPrivate(pRetObj)); + TimerObj* pTimerObj = static_cast(pJS_TimerObj->GetEmbedObject()); + pTimerObj->SetTimer(timerRef); + + return CJS_Return(pRetObj); +} + +CJS_Return app::setTimeOut(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() > 2 || params.size() == 0) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString script = pRuntime->ToWideString(params[0]); + if (script.IsEmpty()) + return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError)); + + uint32_t dwTimeOut = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 1000; + GlobalTimer* timerRef = + new GlobalTimer(this, pRuntime->GetFormFillEnv(), pRuntime, 1, script, + dwTimeOut, dwTimeOut); + m_Timers.insert(std::unique_ptr(timerRef)); + + v8::Local pRetObj = + pRuntime->NewFxDynamicObj(CJS_TimerObj::GetObjDefnID()); + if (pRetObj.IsEmpty()) + return CJS_Return(false); + + CJS_TimerObj* pJS_TimerObj = + static_cast(pRuntime->GetObjectPrivate(pRetObj)); + TimerObj* pTimerObj = static_cast(pJS_TimerObj->GetEmbedObject()); + pTimerObj->SetTimer(timerRef); + + return CJS_Return(pRetObj); +} + +CJS_Return app::clearTimeOut(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + app::ClearTimerCommon(pRuntime, params[0]); + return CJS_Return(true); +} + +CJS_Return app::clearInterval(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + app::ClearTimerCommon(pRuntime, params[0]); + return CJS_Return(true); +} + +void app::ClearTimerCommon(CJS_Runtime* pRuntime, v8::Local param) { + if (!param->IsObject()) + return; + + v8::Local pObj = pRuntime->ToObject(param); + if (CFXJS_Engine::GetObjDefnID(pObj) != CJS_TimerObj::GetObjDefnID()) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(pObj)); + if (!pJSObj) + return; + + TimerObj* pTimerObj = static_cast(pJSObj->GetEmbedObject()); + if (!pTimerObj) + return; + + GlobalTimer::Cancel(pTimerObj->GetTimerID()); +} + +CJS_Return app::execMenuItem(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +void app::TimerProc(GlobalTimer* pTimer) { + CJS_Runtime* pRuntime = pTimer->GetRuntime(); + if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0)) + RunJsScript(pRuntime, pTimer->GetJScript()); +} + +void app::CancelProc(GlobalTimer* pTimer) { + m_Timers.erase(pdfium::FakeUniquePtr(pTimer)); +} + +void app::RunJsScript(CJS_Runtime* pRuntime, const WideString& wsScript) { + if (!pRuntime->IsBlocking()) { + IJS_EventContext* pContext = pRuntime->NewEventContext(); + pContext->OnExternal_Exec(); + WideString wtInfo; + pContext->RunScript(wsScript, &wtInfo); + pRuntime->ReleaseEventContext(pContext); + } +} + +CJS_Return app::goBack(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Not supported. + return CJS_Return(true); +} + +CJS_Return app::goForward(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Not supported. + return CJS_Return(true); +} + +CJS_Return app::mailMsg(CJS_Runtime* pRuntime, + const std::vector>& params) { + std::vector> newParams = + ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc", L"cBcc", + L"cSubject", L"cMsg"); + + if (!IsTypeKnown(newParams[0])) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + bool bUI = pRuntime->ToBoolean(newParams[0]); + WideString cTo; + if (IsTypeKnown(newParams[1])) { + cTo = pRuntime->ToWideString(newParams[1]); + } else { + // cTo parameter required when UI not invoked. + if (!bUI) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + } + + WideString cCc; + if (IsTypeKnown(newParams[2])) + cCc = pRuntime->ToWideString(newParams[2]); + + WideString cBcc; + if (IsTypeKnown(newParams[3])) + cBcc = pRuntime->ToWideString(newParams[3]); + + WideString cSubject; + if (IsTypeKnown(newParams[4])) + cSubject = pRuntime->ToWideString(newParams[4]); + + WideString cMsg; + if (IsTypeKnown(newParams[5])) + cMsg = pRuntime->ToWideString(newParams[5]); + + pRuntime->BeginBlock(); + pRuntime->GetFormFillEnv()->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), + cSubject.c_str(), cCc.c_str(), + cBcc.c_str(), cMsg.c_str()); + pRuntime->EndBlock(); + return CJS_Return(true); +} + +CJS_Return app::launchURL(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return app::get_runtime_highlight(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewBoolean(m_bRuntimeHighLight)); +} + +CJS_Return app::set_runtime_highlight(CJS_Runtime* pRuntime, + v8::Local vp) { + m_bRuntimeHighLight = pRuntime->ToBoolean(vp); + return CJS_Return(true); +} + +CJS_Return app::get_fullscreen(CJS_Runtime* pRuntime) { + return CJS_Return(false); +} + +CJS_Return app::set_fullscreen(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::popUpMenu(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return app::browseForDoc(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +WideString app::SysPathToPDFPath(const WideString& sOldPath) { + WideString sRet = L"/"; + for (const wchar_t& c : sOldPath) { + if (c != L':') + sRet += (c == L'\\') ? L'/' : c; + } + return sRet; +} + +CJS_Return app::newDoc(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return app::openDoc(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return app::response(CJS_Runtime* pRuntime, + const std::vector>& params) { + std::vector> newParams = + ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle", + L"cDefault", L"bPassword", L"cLabel"); + + if (!IsTypeKnown(newParams[0])) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString swQuestion = pRuntime->ToWideString(newParams[0]); + WideString swTitle = L"PDF"; + if (IsTypeKnown(newParams[1])) + swTitle = pRuntime->ToWideString(newParams[1]); + + WideString swDefault; + if (IsTypeKnown(newParams[2])) + swDefault = pRuntime->ToWideString(newParams[2]); + + bool bPassword = false; + if (IsTypeKnown(newParams[3])) + bPassword = pRuntime->ToBoolean(newParams[3]); + + WideString swLabel; + if (IsTypeKnown(newParams[4])) + swLabel = pRuntime->ToWideString(newParams[4]); + + const int MAX_INPUT_BYTES = 2048; + std::vector pBuff(MAX_INPUT_BYTES + 2); + int nLengthBytes = pRuntime->GetFormFillEnv()->JS_appResponse( + swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(), + bPassword, pBuff.data(), MAX_INPUT_BYTES); + + if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES) + return CJS_Return(JSGetStringFromID(JSMessage::kParamTooLongError)); + + return CJS_Return(pRuntime->NewString( + WideString::FromUTF16LE(reinterpret_cast(pBuff.data()), + nLengthBytes / sizeof(uint16_t)) + .c_str())); +} + +CJS_Return app::get_media(CJS_Runtime* pRuntime) { + return CJS_Return(false); +} + +CJS_Return app::set_media(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return app::execDialog(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} diff --git a/fxjs/cjs_app.h b/fxjs/cjs_app.h new file mode 100644 index 0000000000000000000000000000000000000000..703c7052d33346bfb5d249fa0ee604ceeb9d5b66 --- /dev/null +++ b/fxjs/cjs_app.h @@ -0,0 +1,169 @@ +// 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 FXJS_CJS_APP_H_ +#define FXJS_CJS_APP_H_ + +#include +#include +#include + +#include "fxjs/JS_Define.h" + +class CJS_Runtime; +class GlobalTimer; + +class app : public CJS_EmbedObj { + public: + explicit app(CJS_Object* pJSObject); + ~app() override; + + CJS_Return get_active_docs(CJS_Runtime* pRuntime); + CJS_Return set_active_docs(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_calculate(CJS_Runtime* pRuntime); + CJS_Return set_calculate(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_forms_version(CJS_Runtime* pRuntime); + CJS_Return set_forms_version(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_fs(CJS_Runtime* pRuntime); + CJS_Return set_fs(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_fullscreen(CJS_Runtime* pRuntime); + CJS_Return set_fullscreen(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_language(CJS_Runtime* pRuntime); + CJS_Return set_language(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_media(CJS_Runtime* pRuntime); + CJS_Return set_media(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_platform(CJS_Runtime* pRuntime); + CJS_Return set_platform(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_runtime_highlight(CJS_Runtime* pRuntime); + CJS_Return set_runtime_highlight(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_viewer_type(CJS_Runtime* pRuntime); + CJS_Return set_viewer_type(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_viewer_variation(CJS_Runtime* pRuntime); + CJS_Return set_viewer_variation(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_viewer_version(CJS_Runtime* pRuntime); + CJS_Return set_viewer_version(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return alert(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return beep(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return browseForDoc(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return clearInterval(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return clearTimeOut(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return execDialog(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return execMenuItem(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return findComponent(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return goBack(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return goForward(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return launchURL(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return mailMsg(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return newFDF(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return newDoc(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return openDoc(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return openFDF(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return popUpMenuEx(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return popUpMenu(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return response(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return setInterval(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return setTimeOut(CJS_Runtime* pRuntime, + const std::vector>& params); + + void TimerProc(GlobalTimer* pTimer); + void CancelProc(GlobalTimer* pTimer); + + static WideString SysPathToPDFPath(const WideString& sOldPath); + + private: + // CJS_EmbedObj + void RunJsScript(CJS_Runtime* pRuntime, const WideString& wsScript); + + void ClearTimerCommon(CJS_Runtime* pRuntime, v8::Local param); + + bool m_bCalculate; + bool m_bRuntimeHighLight; + std::set> m_Timers; +}; + +class CJS_App : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_App(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_App() override {} + + JS_STATIC_PROP(activeDocs, active_docs, app); + JS_STATIC_PROP(calculate, calculate, app); + JS_STATIC_PROP(formsVersion, forms_version, app); + JS_STATIC_PROP(fs, fs, app); + JS_STATIC_PROP(fullscreen, fullscreen, app); + JS_STATIC_PROP(language, language, app); + JS_STATIC_PROP(media, media, app); + JS_STATIC_PROP(platform, platform, app); + JS_STATIC_PROP(runtimeHighlight, runtime_highlight, app); + JS_STATIC_PROP(viewerType, viewer_type, app); + JS_STATIC_PROP(viewerVariation, viewer_variation, app); + JS_STATIC_PROP(viewerVersion, viewer_version, app); + + JS_STATIC_METHOD(alert, app); + JS_STATIC_METHOD(beep, app); + JS_STATIC_METHOD(browseForDoc, app); + JS_STATIC_METHOD(clearInterval, app); + JS_STATIC_METHOD(clearTimeOut, app); + JS_STATIC_METHOD(execDialog, app); + JS_STATIC_METHOD(execMenuItem, app); + JS_STATIC_METHOD(findComponent, app); + JS_STATIC_METHOD(goBack, app); + JS_STATIC_METHOD(goForward, app); + JS_STATIC_METHOD(launchURL, app); + JS_STATIC_METHOD(mailMsg, app); + JS_STATIC_METHOD(newFDF, app); + JS_STATIC_METHOD(newDoc, app); + JS_STATIC_METHOD(openDoc, app); + JS_STATIC_METHOD(openFDF, app); + JS_STATIC_METHOD(popUpMenuEx, app); + JS_STATIC_METHOD(popUpMenu, app); + JS_STATIC_METHOD(response, app); + JS_STATIC_METHOD(setInterval, app); + JS_STATIC_METHOD(setTimeOut, app); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_APP_H_ diff --git a/fxjs/cjs_border.cpp b/fxjs/cjs_border.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95693f4c3985e69cd03a7aee6f2e29fa4faa0424 --- /dev/null +++ b/fxjs/cjs_border.cpp @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_border.h" + +const JSConstSpec CJS_Border::ConstSpecs[] = { + {"s", JSConstSpec::String, 0, "solid"}, + {"b", JSConstSpec::String, 0, "beveled"}, + {"d", JSConstSpec::String, 0, "dashed"}, + {"i", JSConstSpec::String, 0, "inset"}, + {"u", JSConstSpec::String, 0, "underline"}}; + +int CJS_Border::ObjDefnID = -1; + +// static +void CJS_Border::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("border", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_border.h b/fxjs/cjs_border.h new file mode 100644 index 0000000000000000000000000000000000000000..b3fcef7f21c464842efb8758d619da4ef49aaf99 --- /dev/null +++ b/fxjs/cjs_border.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_BORDER_H_ +#define FXJS_CJS_BORDER_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Border : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Border(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Border() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_BORDER_H_ diff --git a/fxjs/cjs_color.cpp b/fxjs/cjs_color.cpp new file mode 100644 index 0000000000000000000000000000000000000000..58a98dd8ff006ab17d6f5a10a4908229a598015b --- /dev/null +++ b/fxjs/cjs_color.cpp @@ -0,0 +1,302 @@ +// 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 "fxjs/cjs_color.h" + +#include + +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_object.h" +#include "fxjs/cjs_runtime.h" + +const JSPropertySpec CJS_Color::PropertySpecs[] = { + {"black", get_black_static, set_black_static}, + {"blue", get_blue_static, set_blue_static}, + {"cyan", get_cyan_static, set_cyan_static}, + {"dkGray", get_dark_gray_static, set_dark_gray_static}, + {"gray", get_gray_static, set_gray_static}, + {"green", get_green_static, set_green_static}, + {"ltGray", get_light_gray_static, set_light_gray_static}, + {"magenta", get_magenta_static, set_magenta_static}, + {"red", get_red_static, set_red_static}, + {"transparent", get_transparent_static, set_transparent_static}, + {"white", get_white_static, set_white_static}, + {"yellow", get_yellow_static, set_yellow_static}}; + +const JSMethodSpec CJS_Color::MethodSpecs[] = {{"convert", convert_static}, + {"equal", equal_static}}; + +int CJS_Color::ObjDefnID = -1; + +// static +void CJS_Color::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("color", FXJSOBJTYPE_STATIC, + JSConstructor, + JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +// static +v8::Local color::ConvertPWLColorToArray(CJS_Runtime* pRuntime, + const CFX_Color& color) { + v8::Local array; + switch (color.nColorType) { + case CFX_Color::kTransparent: + array = pRuntime->NewArray(); + pRuntime->PutArrayElement(array, 0, pRuntime->NewString(L"T")); + break; + case CFX_Color::kGray: + array = pRuntime->NewArray(); + pRuntime->PutArrayElement(array, 0, pRuntime->NewString(L"G")); + pRuntime->PutArrayElement(array, 1, pRuntime->NewNumber(color.fColor1)); + break; + case CFX_Color::kRGB: + array = pRuntime->NewArray(); + pRuntime->PutArrayElement(array, 0, pRuntime->NewString(L"RGB")); + pRuntime->PutArrayElement(array, 1, pRuntime->NewNumber(color.fColor1)); + pRuntime->PutArrayElement(array, 2, pRuntime->NewNumber(color.fColor2)); + pRuntime->PutArrayElement(array, 3, pRuntime->NewNumber(color.fColor3)); + break; + case CFX_Color::kCMYK: + array = pRuntime->NewArray(); + pRuntime->PutArrayElement(array, 0, pRuntime->NewString(L"CMYK")); + pRuntime->PutArrayElement(array, 1, pRuntime->NewNumber(color.fColor1)); + pRuntime->PutArrayElement(array, 2, pRuntime->NewNumber(color.fColor2)); + pRuntime->PutArrayElement(array, 3, pRuntime->NewNumber(color.fColor3)); + pRuntime->PutArrayElement(array, 4, pRuntime->NewNumber(color.fColor4)); + break; + } + return array; +} + +// static +CFX_Color color::ConvertArrayToPWLColor(CJS_Runtime* pRuntime, + v8::Local array) { + int nArrayLen = pRuntime->GetArrayLength(array); + if (nArrayLen < 1) + return CFX_Color(); + + WideString sSpace = + pRuntime->ToWideString(pRuntime->GetArrayElement(array, 0)); + if (sSpace == L"T") + return CFX_Color(CFX_Color::kTransparent); + + float d1 = 0; + if (nArrayLen > 1) { + d1 = static_cast( + pRuntime->ToDouble(pRuntime->GetArrayElement(array, 1))); + } + + if (sSpace == L"G") + return CFX_Color(CFX_Color::kGray, d1); + + float d2 = 0; + float d3 = 0; + if (nArrayLen > 2) { + d2 = static_cast( + pRuntime->ToDouble(pRuntime->GetArrayElement(array, 2))); + } + if (nArrayLen > 3) { + d3 = static_cast( + pRuntime->ToDouble(pRuntime->GetArrayElement(array, 3))); + } + + if (sSpace == L"RGB") + return CFX_Color(CFX_Color::kRGB, d1, d2, d3); + + float d4 = 0; + if (nArrayLen > 4) { + d4 = static_cast( + pRuntime->ToDouble(pRuntime->GetArrayElement(array, 4))); + } + if (sSpace == L"CMYK") + return CFX_Color(CFX_Color::kCMYK, d1, d2, d3, d4); + + return CFX_Color(); +} + +color::color(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) { + m_crTransparent = CFX_Color(CFX_Color::kTransparent); + m_crBlack = CFX_Color(CFX_Color::kGray, 0); + m_crWhite = CFX_Color(CFX_Color::kGray, 1); + m_crRed = CFX_Color(CFX_Color::kRGB, 1, 0, 0); + m_crGreen = CFX_Color(CFX_Color::kRGB, 0, 1, 0); + m_crBlue = CFX_Color(CFX_Color::kRGB, 0, 0, 1); + m_crCyan = CFX_Color(CFX_Color::kCMYK, 1, 0, 0, 0); + m_crMagenta = CFX_Color(CFX_Color::kCMYK, 0, 1, 0, 0); + m_crYellow = CFX_Color(CFX_Color::kCMYK, 0, 0, 1, 0); + m_crDKGray = CFX_Color(CFX_Color::kGray, 0.25); + m_crGray = CFX_Color(CFX_Color::kGray, 0.5); + m_crLTGray = CFX_Color(CFX_Color::kGray, 0.75); +} + +color::~color() {} + +CJS_Return color::get_transparent(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crTransparent); +} + +CJS_Return color::set_transparent(CJS_Runtime* pRuntime, + v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crTransparent); +} + +CJS_Return color::get_black(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crBlack); +} + +CJS_Return color::set_black(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crBlack); +} + +CJS_Return color::get_white(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crWhite); +} + +CJS_Return color::set_white(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crWhite); +} + +CJS_Return color::get_red(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crRed); +} + +CJS_Return color::set_red(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crRed); +} + +CJS_Return color::get_green(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crGreen); +} + +CJS_Return color::set_green(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crGreen); +} + +CJS_Return color::get_blue(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crBlue); +} + +CJS_Return color::set_blue(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crBlue); +} + +CJS_Return color::get_cyan(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crCyan); +} + +CJS_Return color::set_cyan(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crCyan); +} + +CJS_Return color::get_magenta(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crMagenta); +} + +CJS_Return color::set_magenta(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crMagenta); +} + +CJS_Return color::get_yellow(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crYellow); +} + +CJS_Return color::set_yellow(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crYellow); +} + +CJS_Return color::get_dark_gray(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crDKGray); +} + +CJS_Return color::set_dark_gray(CJS_Runtime* pRuntime, + v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crDKGray); +} + +CJS_Return color::get_gray(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crGray); +} + +CJS_Return color::set_gray(CJS_Runtime* pRuntime, v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crGray); +} + +CJS_Return color::get_light_gray(CJS_Runtime* pRuntime) { + return GetPropertyHelper(pRuntime, &m_crLTGray); +} + +CJS_Return color::set_light_gray(CJS_Runtime* pRuntime, + v8::Local vp) { + return SetPropertyHelper(pRuntime, vp, &m_crLTGray); +} + +CJS_Return color::GetPropertyHelper(CJS_Runtime* pRuntime, CFX_Color* var) { + v8::Local array = ConvertPWLColorToArray(pRuntime, *var); + if (array.IsEmpty()) + return CJS_Return(pRuntime->NewArray()); + return CJS_Return(array); +} + +CJS_Return color::SetPropertyHelper(CJS_Runtime* pRuntime, + v8::Local vp, + CFX_Color* var) { + if (vp.IsEmpty() || !vp->IsArray()) + return CJS_Return(false); + + *var = ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(vp)); + return CJS_Return(true); +} + +CJS_Return color::convert(CJS_Runtime* pRuntime, + const std::vector>& params) { + int iSize = params.size(); + if (iSize < 2) + return CJS_Return(false); + if (params[0].IsEmpty() || !params[0]->IsArray()) + return CJS_Return(false); + + WideString sDestSpace = pRuntime->ToWideString(params[1]); + int nColorType = CFX_Color::kTransparent; + if (sDestSpace == L"T") + nColorType = CFX_Color::kTransparent; + else if (sDestSpace == L"G") + nColorType = CFX_Color::kGray; + else if (sDestSpace == L"RGB") + nColorType = CFX_Color::kRGB; + else if (sDestSpace == L"CMYK") + nColorType = CFX_Color::kCMYK; + + CFX_Color color = + ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(params[0])); + + v8::Local array = + ConvertPWLColorToArray(pRuntime, color.ConvertColorType(nColorType)); + if (array.IsEmpty()) + return CJS_Return(pRuntime->NewArray()); + return CJS_Return(array); +} + +CJS_Return color::equal(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 2) + return CJS_Return(false); + if (params[0].IsEmpty() || !params[0]->IsArray() || params[1].IsEmpty() || + !params[1]->IsArray()) { + return CJS_Return(false); + } + + CFX_Color color1 = + ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(params[0])); + CFX_Color color2 = + ConvertArrayToPWLColor(pRuntime, pRuntime->ToArray(params[1])); + + color1 = color1.ConvertColorType(color2.nColorType); + return CJS_Return(pRuntime->NewBoolean(color1 == color2)); +} diff --git a/fxjs/cjs_color.h b/fxjs/cjs_color.h new file mode 100644 index 0000000000000000000000000000000000000000..5f7c1e5e30f7d181e63c93d3cb906a7a618d0190 --- /dev/null +++ b/fxjs/cjs_color.h @@ -0,0 +1,115 @@ +// 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 FXJS_CJS_COLOR_H_ +#define FXJS_CJS_COLOR_H_ + +#include + +#include "fpdfsdk/pwl/cpwl_wnd.h" +#include "fxjs/JS_Define.h" + +class color : public CJS_EmbedObj { + public: + static v8::Local ConvertPWLColorToArray(CJS_Runtime* pRuntime, + const CFX_Color& color); + static CFX_Color ConvertArrayToPWLColor(CJS_Runtime* pRuntime, + v8::Local array); + + explicit color(CJS_Object* pJSObject); + ~color() override; + + CJS_Return get_black(CJS_Runtime* pRuntime); + CJS_Return set_black(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_blue(CJS_Runtime* pRuntime); + CJS_Return set_blue(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_cyan(CJS_Runtime* pRuntime); + CJS_Return set_cyan(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_dark_gray(CJS_Runtime* pRuntime); + CJS_Return set_dark_gray(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_gray(CJS_Runtime* pRuntime); + CJS_Return set_gray(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_green(CJS_Runtime* pRuntime); + CJS_Return set_green(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_light_gray(CJS_Runtime* pRuntime); + CJS_Return set_light_gray(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_magenta(CJS_Runtime* pRuntime); + CJS_Return set_magenta(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_red(CJS_Runtime* pRuntime); + CJS_Return set_red(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_transparent(CJS_Runtime* pRuntime); + CJS_Return set_transparent(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_white(CJS_Runtime* pRuntime); + CJS_Return set_white(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_yellow(CJS_Runtime* pRuntime); + CJS_Return set_yellow(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return convert(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return equal(CJS_Runtime* pRuntime, + const std::vector>& params); + + private: + CJS_Return GetPropertyHelper(CJS_Runtime* pRuntime, CFX_Color* val); + CJS_Return SetPropertyHelper(CJS_Runtime* pRuntime, + v8::Local vp, + CFX_Color* val); + + CFX_Color m_crTransparent; + CFX_Color m_crBlack; + CFX_Color m_crWhite; + CFX_Color m_crRed; + CFX_Color m_crGreen; + CFX_Color m_crBlue; + CFX_Color m_crCyan; + CFX_Color m_crMagenta; + CFX_Color m_crYellow; + CFX_Color m_crDKGray; + CFX_Color m_crGray; + CFX_Color m_crLTGray; +}; + +class CJS_Color : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Color(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Color() override {} + + JS_STATIC_PROP(black, black, color); + JS_STATIC_PROP(blue, blue, color); + JS_STATIC_PROP(cyan, cyan, color); + JS_STATIC_PROP(dkGray, dark_gray, color); + JS_STATIC_PROP(gray, gray, color); + JS_STATIC_PROP(green, green, color); + JS_STATIC_PROP(ltGray, light_gray, color); + JS_STATIC_PROP(magenta, magenta, color); + JS_STATIC_PROP(red, red, color); + JS_STATIC_PROP(transparent, transparent, color); + JS_STATIC_PROP(white, white, color); + JS_STATIC_PROP(yellow, yellow, color); + + JS_STATIC_METHOD(convert, color); + JS_STATIC_METHOD(equal, color); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_COLOR_H_ diff --git a/fxjs/cjs_console.cpp b/fxjs/cjs_console.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1921cd2069fb0895419f2978d2370d2ed2acf569 --- /dev/null +++ b/fxjs/cjs_console.cpp @@ -0,0 +1,53 @@ +// 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 "fxjs/cjs_console.h" + +#include + +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_object.h" + +const JSMethodSpec CJS_Console::MethodSpecs[] = {{"clear", clear_static}, + {"hide", hide_static}, + {"println", println_static}, + {"show", show_static}}; + +int CJS_Console::ObjDefnID = -1; + +// static +void CJS_Console::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("console", FXJSOBJTYPE_STATIC, + JSConstructor, + JSDestructor); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +console::console(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} + +console::~console() {} + +CJS_Return console::clear(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return console::hide(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return console::println(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(params.size() > 0); +} + +CJS_Return console::show(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} diff --git a/fxjs/cjs_console.h b/fxjs/cjs_console.h new file mode 100644 index 0000000000000000000000000000000000000000..43a55bc7b00977dcf4bddfac7248052a8ad0e1ac --- /dev/null +++ b/fxjs/cjs_console.h @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_CONSOLE_H_ +#define FXJS_CJS_CONSOLE_H_ + +#include + +#include "fxjs/JS_Define.h" + +class console : public CJS_EmbedObj { + public: + explicit console(CJS_Object* pJSObject); + ~console() override; + + public: + CJS_Return clear(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return hide(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return println(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return show(CJS_Runtime* pRuntime, + const std::vector>& params); +}; + +class CJS_Console : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Console(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Console() override {} + + JS_STATIC_METHOD(clear, console); + JS_STATIC_METHOD(hide, console); + JS_STATIC_METHOD(println, console); + JS_STATIC_METHOD(show, console); + + private: + static int ObjDefnID; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_CONSOLE_H_ diff --git a/fxjs/cjs_delaydata.cpp b/fxjs/cjs_delaydata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7e1f7800455d67747ceda1fb001871545a9db14 --- /dev/null +++ b/fxjs/cjs_delaydata.cpp @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_delaydata.h" + +CJS_DelayData::CJS_DelayData(FIELD_PROP prop, int idx, const WideString& name) + : eProp(prop), nControlIndex(idx), sFieldName(name) {} + +CJS_DelayData::~CJS_DelayData() {} diff --git a/fxjs/cjs_delaydata.h b/fxjs/cjs_delaydata.h new file mode 100644 index 0000000000000000000000000000000000000000..deeb65d56fbd4f358322ae6c637146c7dff430e1 --- /dev/null +++ b/fxjs/cjs_delaydata.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_DELAYDATA_H_ +#define FXJS_CJS_DELAYDATA_H_ + +#include +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/widestring.h" +#include "core/fxge/cfx_color.h" +#include "fxjs/cjs_field.h" + +struct CJS_DelayData { + CJS_DelayData(FIELD_PROP prop, int idx, const WideString& name); + ~CJS_DelayData(); + + FIELD_PROP eProp; + int nControlIndex; + WideString sFieldName; + int32_t num; + bool b; + ByteString string; + WideString widestring; + CFX_FloatRect rect; + CFX_Color color; + std::vector wordarray; + std::vector widestringarray; +}; + +#endif // FXJS_CJS_DELAYDATA_H_ diff --git a/fxjs/cjs_display.cpp b/fxjs/cjs_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6970bfcb5174c3c270cf6130af019bcfa0a24c5f --- /dev/null +++ b/fxjs/cjs_display.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_display.h" + +const JSConstSpec CJS_Display::ConstSpecs[] = { + {"visible", JSConstSpec::Number, 0, 0}, + {"hidden", JSConstSpec::Number, 1, 0}, + {"noPrint", JSConstSpec::Number, 2, 0}, + {"noView", JSConstSpec::Number, 3, 0}}; + +int CJS_Display::ObjDefnID = -1; + +// static +void CJS_Display::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("display", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_display.h b/fxjs/cjs_display.h new file mode 100644 index 0000000000000000000000000000000000000000..7b13c38cbe0cc17b9f333b3a338d4f733802851a --- /dev/null +++ b/fxjs/cjs_display.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_DISPLAY_H_ +#define FXJS_CJS_DISPLAY_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Display : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Display(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Display() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_DISPLAY_H_ diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4eca2f175e0b31648eb172478021fd727690edb --- /dev/null +++ b/fxjs/cjs_document.cpp @@ -0,0 +1,1499 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_document.h" + +#include + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/page/cpdf_pageobject.h" +#include "core/fpdfapi/page/cpdf_textobject.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfdoc/cpdf_interform.h" +#include "core/fpdfdoc/cpdf_nametree.h" +#include "fpdfsdk/cpdfsdk_annotiteration.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fpdfsdk/cpdfsdk_pageview.h" +#include "fxjs/cjs_annot.h" +#include "fxjs/cjs_app.h" +#include "fxjs/cjs_delaydata.h" +#include "fxjs/cjs_field.h" +#include "fxjs/cjs_icon.h" +#include "fxjs/cjs_printparamsobj.h" +#include "fxjs/js_resources.h" + +const JSPropertySpec CJS_Document::PropertySpecs[] = { + {"ADBE", get_ADBE_static, set_ADBE_static}, + {"author", get_author_static, set_author_static}, + {"baseURL", get_base_URL_static, set_base_URL_static}, + {"bookmarkRoot", get_bookmark_root_static, set_bookmark_root_static}, + {"calculate", get_calculate_static, set_calculate_static}, + {"Collab", get_collab_static, set_collab_static}, + {"creationDate", get_creation_date_static, set_creation_date_static}, + {"creator", get_creator_static, set_creator_static}, + {"delay", get_delay_static, set_delay_static}, + {"dirty", get_dirty_static, set_dirty_static}, + {"documentFileName", get_document_file_name_static, + set_document_file_name_static}, + {"external", get_external_static, set_external_static}, + {"filesize", get_filesize_static, set_filesize_static}, + {"icons", get_icons_static, set_icons_static}, + {"info", get_info_static, set_info_static}, + {"keywords", get_keywords_static, set_keywords_static}, + {"layout", get_layout_static, set_layout_static}, + {"media", get_media_static, set_media_static}, + {"modDate", get_mod_date_static, set_mod_date_static}, + {"mouseX", get_mouse_x_static, set_mouse_x_static}, + {"mouseY", get_mouse_y_static, set_mouse_y_static}, + {"numFields", get_num_fields_static, set_num_fields_static}, + {"numPages", get_num_pages_static, set_num_pages_static}, + {"pageNum", get_page_num_static, set_page_num_static}, + {"pageWindowRect", get_page_window_rect_static, + set_page_window_rect_static}, + {"path", get_path_static, set_path_static}, + {"producer", get_producer_static, set_producer_static}, + {"subject", get_subject_static, set_subject_static}, + {"title", get_title_static, set_title_static}, + {"URL", get_URL_static, set_URL_static}, + {"zoom", get_zoom_static, set_zoom_static}, + {"zoomType", get_zoom_type_static, set_zoom_type_static}}; + +const JSMethodSpec CJS_Document::MethodSpecs[] = { + {"addAnnot", addAnnot_static}, + {"addField", addField_static}, + {"addLink", addLink_static}, + {"addIcon", addIcon_static}, + {"calculateNow", calculateNow_static}, + {"closeDoc", closeDoc_static}, + {"createDataObject", createDataObject_static}, + {"deletePages", deletePages_static}, + {"exportAsText", exportAsText_static}, + {"exportAsFDF", exportAsFDF_static}, + {"exportAsXFDF", exportAsXFDF_static}, + {"extractPages", extractPages_static}, + {"getAnnot", getAnnot_static}, + {"getAnnots", getAnnots_static}, + {"getAnnot3D", getAnnot3D_static}, + {"getAnnots3D", getAnnots3D_static}, + {"getField", getField_static}, + {"getIcon", getIcon_static}, + {"getLinks", getLinks_static}, + {"getNthFieldName", getNthFieldName_static}, + {"getOCGs", getOCGs_static}, + {"getPageBox", getPageBox_static}, + {"getPageNthWord", getPageNthWord_static}, + {"getPageNthWordQuads", getPageNthWordQuads_static}, + {"getPageNumWords", getPageNumWords_static}, + {"getPrintParams", getPrintParams_static}, + {"getURL", getURL_static}, + {"gotoNamedDest", gotoNamedDest_static}, + {"importAnFDF", importAnFDF_static}, + {"importAnXFDF", importAnXFDF_static}, + {"importTextData", importTextData_static}, + {"insertPages", insertPages_static}, + {"mailForm", mailForm_static}, + {"print", print_static}, + {"removeField", removeField_static}, + {"replacePages", replacePages_static}, + {"resetForm", resetForm_static}, + {"removeIcon", removeIcon_static}, + {"saveAs", saveAs_static}, + {"submitForm", submitForm_static}, + {"syncAnnotScan", syncAnnotScan_static}, + {"mailDoc", mailDoc_static}}; + +int CJS_Document::ObjDefnID = -1; + +// static +int CJS_Document::GetObjDefnID() { + return ObjDefnID; +} + +// static +void CJS_Document::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("Document", FXJSOBJTYPE_GLOBAL, + JSConstructor, + JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +void CJS_Document::InitInstance(IJS_Runtime* pIRuntime) { + CJS_Runtime* pRuntime = static_cast(pIRuntime); + Document* pDoc = static_cast(GetEmbedObject()); + pDoc->SetFormFillEnv(pRuntime->GetFormFillEnv()); +} + +Document::Document(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject), + m_pFormFillEnv(nullptr), + m_cwBaseURL(L""), + m_bDelay(false) {} + +Document::~Document() {} + +// The total number of fields in document. +CJS_Return Document::get_num_fields(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); + return CJS_Return(pRuntime->NewNumber( + static_cast(pPDFForm->CountFields(WideString())))); +} + +CJS_Return Document::set_num_fields(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::get_dirty(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return(pRuntime->NewBoolean(!!m_pFormFillEnv->GetChangeMark())); +} + +CJS_Return Document::set_dirty(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + pRuntime->ToBoolean(vp) ? m_pFormFillEnv->SetChangeMark() + : m_pFormFillEnv->ClearChangeMark(); + return CJS_Return(true); +} + +CJS_Return Document::get_ADBE(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewUndefined()); +} + +CJS_Return Document::set_ADBE(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::get_page_num(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetCurrentView(); + if (!pPageView) + return CJS_Return(pRuntime->NewUndefined()); + return CJS_Return(pRuntime->NewNumber(pPageView->GetPageIndex())); +} + +CJS_Return Document::set_page_num(CJS_Runtime* pRuntime, + v8::Local vp) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + int iPageCount = m_pFormFillEnv->GetPageCount(); + int iPageNum = pRuntime->ToInt32(vp); + if (iPageNum >= 0 && iPageNum < iPageCount) + m_pFormFillEnv->JS_docgotoPage(iPageNum); + else if (iPageNum >= iPageCount) + m_pFormFillEnv->JS_docgotoPage(iPageCount - 1); + else if (iPageNum < 0) + m_pFormFillEnv->JS_docgotoPage(0); + + return CJS_Return(true); +} + +CJS_Return Document::addAnnot(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Not supported. + return CJS_Return(true); +} + +CJS_Return Document::addField(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Not supported. + return CJS_Return(true); +} + +CJS_Return Document::exportAsText( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::exportAsFDF( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::exportAsXFDF( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::getField(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + WideString wideName = pRuntime->ToWideString(params[0]); + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); + if (pPDFForm->CountFields(wideName) <= 0) + return CJS_Return(pRuntime->NewUndefined()); + + v8::Local pFieldObj = + pRuntime->NewFxDynamicObj(CJS_Field::GetObjDefnID()); + if (pFieldObj.IsEmpty()) + return CJS_Return(false); + + CJS_Field* pJSField = + static_cast(pRuntime->GetObjectPrivate(pFieldObj)); + Field* pField = static_cast(pJSField->GetEmbedObject()); + pField->AttachField(this, wideName); + if (!pJSField) + return CJS_Return(false); + + return CJS_Return(pJSField->ToV8Object()); +} + +// Gets the name of the nth field in the document +CJS_Return Document::getNthFieldName( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + int nIndex = pRuntime->ToInt32(params[0]); + if (nIndex < 0) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); + CPDF_FormField* pField = pPDFForm->GetField(nIndex, WideString()); + if (!pField) + return CJS_Return(false); + return CJS_Return(pRuntime->NewString(pField->GetFullName().c_str())); +} + +CJS_Return Document::importAnFDF( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::importAnXFDF( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::importTextData( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +// exports the form data and mails the resulting fdf file as an attachment to +// all recipients. +// comment: need reader supports +CJS_Return Document::mailForm(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + + int iLength = params.size(); + bool bUI = iLength > 0 ? pRuntime->ToBoolean(params[0]) : true; + WideString cTo = iLength > 1 ? pRuntime->ToWideString(params[1]) : L""; + WideString cCc = iLength > 2 ? pRuntime->ToWideString(params[2]) : L""; + WideString cBcc = iLength > 3 ? pRuntime->ToWideString(params[3]) : L""; + WideString cSubject = iLength > 4 ? pRuntime->ToWideString(params[4]) : L""; + WideString cMsg = iLength > 5 ? pRuntime->ToWideString(params[5]) : L""; + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + ByteString sTextBuf = pInterForm->ExportFormToFDFTextBuf(); + if (sTextBuf.GetLength() == 0) + return CJS_Return(false); + + size_t nBufSize = sTextBuf.GetLength(); + char* pMutableBuf = FX_Alloc(char, nBufSize); + memcpy(pMutableBuf, sTextBuf.c_str(), nBufSize); + + pRuntime->BeginBlock(); + CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); + pFormFillEnv->JS_docmailForm(pMutableBuf, nBufSize, bUI, cTo.c_str(), + cSubject.c_str(), cCc.c_str(), cBcc.c_str(), + cMsg.c_str()); + pRuntime->EndBlock(); + FX_Free(pMutableBuf); + return CJS_Return(true); +} + +CJS_Return Document::print(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + bool bUI = true; + int nStart = 0; + int nEnd = 0; + bool bSilent = false; + bool bShrinkToFit = false; + bool bPrintAsImage = false; + bool bReverse = false; + bool bAnnotations = false; + int nlength = params.size(); + if (nlength == 9) { + if (params[8]->IsObject()) { + v8::Local pObj = pRuntime->ToObject(params[8]); + if (CFXJS_Engine::GetObjDefnID(pObj) == + CJS_PrintParamsObj::GetObjDefnID()) { + v8::Local pObj = pRuntime->ToObject(params[8]); + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(pObj)); + if (pJSObj) { + if (PrintParamsObj* pprintparamsObj = + static_cast(pJSObj->GetEmbedObject())) { + bUI = pprintparamsObj->bUI; + nStart = pprintparamsObj->nStart; + nEnd = pprintparamsObj->nEnd; + bSilent = pprintparamsObj->bSilent; + bShrinkToFit = pprintparamsObj->bShrinkToFit; + bPrintAsImage = pprintparamsObj->bPrintAsImage; + bReverse = pprintparamsObj->bReverse; + bAnnotations = pprintparamsObj->bAnnotations; + } + } + } + } + } else { + if (nlength >= 1) + bUI = pRuntime->ToBoolean(params[0]); + if (nlength >= 2) + nStart = pRuntime->ToInt32(params[1]); + if (nlength >= 3) + nEnd = pRuntime->ToInt32(params[2]); + if (nlength >= 4) + bSilent = pRuntime->ToBoolean(params[3]); + if (nlength >= 5) + bShrinkToFit = pRuntime->ToBoolean(params[4]); + if (nlength >= 6) + bPrintAsImage = pRuntime->ToBoolean(params[5]); + if (nlength >= 7) + bReverse = pRuntime->ToBoolean(params[6]); + if (nlength >= 8) + bAnnotations = pRuntime->ToBoolean(params[7]); + } + + if (!m_pFormFillEnv) + return CJS_Return(false); + + m_pFormFillEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, + bPrintAsImage, bReverse, bAnnotations); + return CJS_Return(true); +} + +// removes the specified field from the document. +// comment: +// note: if the filed name is not rational, adobe is dumb for it. + +CJS_Return Document::removeField( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || + m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM))) + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + + WideString sFieldName = pRuntime->ToWideString(params[0]); + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + std::vector widgets; + pInterForm->GetWidgets(sFieldName, &widgets); + if (widgets.empty()) + return CJS_Return(true); + + for (const auto& pAnnot : widgets) { + CPDFSDK_Widget* pWidget = static_cast(pAnnot.Get()); + if (!pWidget) + continue; + + CFX_FloatRect rcAnnot = pWidget->GetRect(); + --rcAnnot.left; + --rcAnnot.bottom; + ++rcAnnot.right; + ++rcAnnot.top; + + std::vector aRefresh(1, rcAnnot); + UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); + ASSERT(pPage); + + // If there is currently no pageview associated with the page being used + // do not create one. We may be in the process of tearing down the document + // and creating a new pageview at this point will cause bad things. + CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, false); + if (pPageView) { +#if PDF_ENABLE_XFA + pPageView->DeleteAnnot(pWidget); +#endif // PDF_ENABLE_XFA + pPageView->UpdateRects(aRefresh); + } + } + m_pFormFillEnv->SetChangeMark(); + + return CJS_Return(true); +} + +// reset filed values within a document. +// comment: +// note: if the fields names r not rational, aodbe is dumb for it. + +CJS_Return Document::resetForm( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || + m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || + m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) { + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + } + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); + if (params.empty()) { + pPDFForm->ResetForm(true); + m_pFormFillEnv->SetChangeMark(); + return CJS_Return(true); + } + + v8::Local array; + if (params[0]->IsString()) { + array = pRuntime->NewArray(); + pRuntime->PutArrayElement(array, 0, params[0]); + } else { + array = pRuntime->ToArray(params[0]); + } + + std::vector aFields; + for (size_t i = 0; i < pRuntime->GetArrayLength(array); ++i) { + WideString swVal = + pRuntime->ToWideString(pRuntime->GetArrayElement(array, i)); + for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; ++j) + aFields.push_back(pPDFForm->GetField(j, swVal)); + } + + if (!aFields.empty()) { + pPDFForm->ResetForm(aFields, true, true); + m_pFormFillEnv->SetChangeMark(); + } + + return CJS_Return(true); +} + +CJS_Return Document::saveAs(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::syncAnnotScan( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Document::submitForm( + CJS_Runtime* pRuntime, + const std::vector>& params) { + int nSize = params.size(); + if (nSize < 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + v8::Local aFields; + WideString strURL; + bool bFDF = true; + bool bEmpty = false; + if (params[0]->IsString()) { + strURL = pRuntime->ToWideString(params[0]); + if (nSize > 1) + bFDF = pRuntime->ToBoolean(params[1]); + if (nSize > 2) + bEmpty = pRuntime->ToBoolean(params[2]); + if (nSize > 3) + aFields = pRuntime->ToArray(params[3]); + } else if (params[0]->IsObject()) { + v8::Local pObj = pRuntime->ToObject(params[0]); + v8::Local pValue = pRuntime->GetObjectProperty(pObj, L"cURL"); + if (!pValue.IsEmpty()) + strURL = pRuntime->ToWideString(pValue); + + bFDF = pRuntime->ToBoolean(pRuntime->GetObjectProperty(pObj, L"bFDF")); + bEmpty = pRuntime->ToBoolean(pRuntime->GetObjectProperty(pObj, L"bEmpty")); + aFields = pRuntime->ToArray(pRuntime->GetObjectProperty(pObj, L"aFields")); + } + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm(); + + if (pRuntime->GetArrayLength(aFields) == 0 && bEmpty) { + if (pPDFInterForm->CheckRequiredFields(nullptr, true)) { + pRuntime->BeginBlock(); + pInterForm->SubmitForm(strURL, false); + pRuntime->EndBlock(); + } + return CJS_Return(true); + } + + std::vector fieldObjects; + for (size_t i = 0; i < pRuntime->GetArrayLength(aFields); ++i) { + WideString sName = + pRuntime->ToWideString(pRuntime->GetArrayElement(aFields, i)); + CPDF_InterForm* pPDFForm = pInterForm->GetInterForm(); + for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) { + CPDF_FormField* pField = pPDFForm->GetField(j, sName); + if (!bEmpty && pField->GetValue().IsEmpty()) + continue; + + fieldObjects.push_back(pField); + } + } + + if (pPDFInterForm->CheckRequiredFields(&fieldObjects, true)) { + pRuntime->BeginBlock(); + pInterForm->SubmitFields(strURL, fieldObjects, true, !bFDF); + pRuntime->EndBlock(); + } + return CJS_Return(true); +} + +void Document::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) { + m_pFormFillEnv.Reset(pFormFillEnv); +} + +CJS_Return Document::get_bookmark_root(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_bookmark_root(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::mailDoc(CJS_Runtime* pRuntime, + const std::vector>& params) { + // TODO(tsepez): Check maximum number of allowed params. + bool bUI = true; + WideString cTo = L""; + WideString cCc = L""; + WideString cBcc = L""; + WideString cSubject = L""; + WideString cMsg = L""; + + if (params.size() >= 1) + bUI = pRuntime->ToBoolean(params[0]); + if (params.size() >= 2) + cTo = pRuntime->ToWideString(params[1]); + if (params.size() >= 3) + cCc = pRuntime->ToWideString(params[2]); + if (params.size() >= 4) + cBcc = pRuntime->ToWideString(params[3]); + if (params.size() >= 5) + cSubject = pRuntime->ToWideString(params[4]); + if (params.size() >= 6) + cMsg = pRuntime->ToWideString(params[5]); + + if (params.size() >= 1 && params[0]->IsObject()) { + v8::Local pObj = pRuntime->ToObject(params[0]); + bUI = pRuntime->ToBoolean(pRuntime->GetObjectProperty(pObj, L"bUI")); + cTo = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cTo")); + cCc = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cCc")); + cBcc = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cBcc")); + cSubject = + pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cSubject")); + cMsg = pRuntime->ToWideString(pRuntime->GetObjectProperty(pObj, L"cMsg")); + } + + pRuntime->BeginBlock(); + CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv(); + pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), cSubject.c_str(), + cCc.c_str(), cBcc.c_str(), cMsg.c_str()); + pRuntime->EndBlock(); + return CJS_Return(true); +} + +CJS_Return Document::get_author(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "Author"); +} + +CJS_Return Document::set_author(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "Author"); +} + +CJS_Return Document::get_info(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + const auto* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); + if (!pDictionary) + return CJS_Return(false); + + WideString cwAuthor = pDictionary->GetUnicodeTextFor("Author"); + WideString cwTitle = pDictionary->GetUnicodeTextFor("Title"); + WideString cwSubject = pDictionary->GetUnicodeTextFor("Subject"); + WideString cwKeywords = pDictionary->GetUnicodeTextFor("Keywords"); + WideString cwCreator = pDictionary->GetUnicodeTextFor("Creator"); + WideString cwProducer = pDictionary->GetUnicodeTextFor("Producer"); + WideString cwCreationDate = pDictionary->GetUnicodeTextFor("CreationDate"); + WideString cwModDate = pDictionary->GetUnicodeTextFor("ModDate"); + WideString cwTrapped = pDictionary->GetUnicodeTextFor("Trapped"); + + v8::Local pObj = pRuntime->NewFxDynamicObj(-1); + pRuntime->PutObjectProperty(pObj, L"Author", + pRuntime->NewString(cwAuthor.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"Title", + pRuntime->NewString(cwTitle.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"Subject", + pRuntime->NewString(cwSubject.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"Keywords", + pRuntime->NewString(cwKeywords.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"Creator", + pRuntime->NewString(cwCreator.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"Producer", + pRuntime->NewString(cwProducer.AsStringView())); + pRuntime->PutObjectProperty( + pObj, L"CreationDate", + pRuntime->NewString(cwCreationDate.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"ModDate", + pRuntime->NewString(cwModDate.AsStringView())); + pRuntime->PutObjectProperty(pObj, L"Trapped", + pRuntime->NewString(cwTrapped.AsStringView())); + + // It's to be compatible to non-standard info dictionary. + for (const auto& it : *pDictionary) { + const ByteString& bsKey = it.first; + CPDF_Object* pValueObj = it.second.get(); + WideString wsKey = WideString::FromUTF8(bsKey.AsStringView()); + if (pValueObj->IsString() || pValueObj->IsName()) { + pRuntime->PutObjectProperty( + pObj, wsKey, + pRuntime->NewString(pValueObj->GetUnicodeText().AsStringView())); + } else if (pValueObj->IsNumber()) { + pRuntime->PutObjectProperty(pObj, wsKey, + pRuntime->NewNumber(pValueObj->GetNumber())); + } else if (pValueObj->IsBoolean()) { + pRuntime->PutObjectProperty( + pObj, wsKey, pRuntime->NewBoolean(!!pValueObj->GetInteger())); + } + } + return CJS_Return(pObj); +} + +CJS_Return Document::set_info(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::getPropertyInternal(CJS_Runtime* pRuntime, + const ByteString& propName) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); + if (!pDictionary) + return CJS_Return(false); + return CJS_Return( + pRuntime->NewString(pDictionary->GetUnicodeTextFor(propName).c_str())); +} + +CJS_Return Document::setPropertyInternal(CJS_Runtime* pRuntime, + v8::Local vp, + const ByteString& propName) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo(); + if (!pDictionary) + return CJS_Return(false); + + if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + + WideString csProperty = pRuntime->ToWideString(vp); + pDictionary->SetNewFor(propName, PDF_EncodeText(csProperty), + false); + m_pFormFillEnv->SetChangeMark(); + return CJS_Return(true); +} + +CJS_Return Document::get_creation_date(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "CreationDate"); +} + +CJS_Return Document::set_creation_date(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "CreationDate"); +} + +CJS_Return Document::get_creator(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "Creator"); +} + +CJS_Return Document::set_creator(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "Creator"); +} + +CJS_Return Document::get_delay(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return(pRuntime->NewBoolean(m_bDelay)); +} + +CJS_Return Document::set_delay(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + + m_bDelay = pRuntime->ToBoolean(vp); + if (m_bDelay) { + m_DelayData.clear(); + return CJS_Return(true); + } + + std::list> DelayDataToProcess; + DelayDataToProcess.swap(m_DelayData); + for (const auto& pData : DelayDataToProcess) + Field::DoDelay(m_pFormFillEnv.Get(), pData.get()); + + return CJS_Return(true); +} + +CJS_Return Document::get_keywords(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "Keywords"); +} + +CJS_Return Document::set_keywords(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "Keywords"); +} + +CJS_Return Document::get_mod_date(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "ModDate"); +} + +CJS_Return Document::set_mod_date(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "ModDate"); +} + +CJS_Return Document::get_producer(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "Producer"); +} + +CJS_Return Document::set_producer(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "Producer"); +} + +CJS_Return Document::get_subject(CJS_Runtime* pRuntime) { + return getPropertyInternal(pRuntime, "Subject"); +} + +CJS_Return Document::set_subject(CJS_Runtime* pRuntime, + v8::Local vp) { + return setPropertyInternal(pRuntime, vp, "Subject"); +} + +CJS_Return Document::get_title(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv || !m_pFormFillEnv->GetUnderlyingDocument()) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return getPropertyInternal(pRuntime, "Title"); +} + +CJS_Return Document::set_title(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_pFormFillEnv || !m_pFormFillEnv->GetUnderlyingDocument()) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return setPropertyInternal(pRuntime, vp, "Title"); +} + +CJS_Return Document::get_num_pages(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return(pRuntime->NewNumber(m_pFormFillEnv->GetPageCount())); +} + +CJS_Return Document::set_num_pages(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::get_external(CJS_Runtime* pRuntime) { + // In Chrome case, should always return true. + return CJS_Return(pRuntime->NewBoolean(true)); +} + +CJS_Return Document::set_external(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::get_filesize(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewNumber(0)); +} + +CJS_Return Document::set_filesize(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::get_mouse_x(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_mouse_x(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::get_mouse_y(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_mouse_y(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::get_URL(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return( + pRuntime->NewString(m_pFormFillEnv->JS_docGetFilePath().c_str())); +} + +CJS_Return Document::set_URL(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::get_base_URL(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewString(m_cwBaseURL.c_str())); +} + +CJS_Return Document::set_base_URL(CJS_Runtime* pRuntime, + v8::Local vp) { + m_cwBaseURL = pRuntime->ToWideString(vp); + return CJS_Return(true); +} + +CJS_Return Document::get_calculate(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + return CJS_Return(pRuntime->NewBoolean(!!pInterForm->IsCalculateEnabled())); +} + +CJS_Return Document::set_calculate(CJS_Runtime* pRuntime, + v8::Local vp) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + pInterForm->EnableCalculate(pRuntime->ToBoolean(vp)); + return CJS_Return(true); +} + +CJS_Return Document::get_document_file_name(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + WideString wsFilePath = m_pFormFillEnv->JS_docGetFilePath(); + size_t i = wsFilePath.GetLength(); + for (; i > 0; i--) { + if (wsFilePath[i - 1] == L'\\' || wsFilePath[i - 1] == L'/') + break; + } + + if (i > 0 && i < wsFilePath.GetLength()) { + return CJS_Return( + pRuntime->NewString(wsFilePath.GetBuffer(wsFilePath.GetLength()) + i)); + } + return CJS_Return(pRuntime->NewString(L"")); +} + +CJS_Return Document::set_document_file_name(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::get_path(CJS_Runtime* pRuntime) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return(pRuntime->NewString( + app::SysPathToPDFPath(m_pFormFillEnv->JS_docGetFilePath()).c_str())); +} + +CJS_Return Document::set_path(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::get_page_window_rect(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_page_window_rect(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::get_layout(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_layout(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::addLink(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Document::closeDoc(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Document::getPageBox( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Document::getAnnot(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + int nPageNo = pRuntime->ToInt32(params[0]); + WideString swAnnotName = pRuntime->ToWideString(params[1]); + CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(nPageNo); + if (!pPageView) + return CJS_Return(false); + + CPDFSDK_AnnotIteration annotIteration(pPageView, false); + CPDFSDK_BAAnnot* pSDKBAAnnot = nullptr; + for (const auto& pSDKAnnotCur : annotIteration) { + CPDFSDK_BAAnnot* pBAAnnot = + static_cast(pSDKAnnotCur.Get()); + if (pBAAnnot && pBAAnnot->GetAnnotName() == swAnnotName) { + pSDKBAAnnot = pBAAnnot; + break; + } + } + if (!pSDKBAAnnot) + return CJS_Return(false); + + v8::Local pObj = + pRuntime->NewFxDynamicObj(CJS_Annot::GetObjDefnID()); + if (pObj.IsEmpty()) + return CJS_Return(false); + + CJS_Annot* pJS_Annot = + static_cast(pRuntime->GetObjectPrivate(pObj)); + if (!pJS_Annot) + return CJS_Return(false); + + Annot* pAnnot = static_cast(pJS_Annot->GetEmbedObject()); + pAnnot->SetSDKAnnot(pSDKBAAnnot); + + return CJS_Return(pJS_Annot->ToV8Object()); +} + +CJS_Return Document::getAnnots( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + // TODO(tonikitoo): Add support supported parameters as per + // the PDF spec. + + int nPageNo = m_pFormFillEnv->GetPageCount(); + v8::Local annots = pRuntime->NewArray(); + for (int i = 0; i < nPageNo; ++i) { + CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(i); + if (!pPageView) + return CJS_Return(false); + + CPDFSDK_AnnotIteration annotIteration(pPageView, false); + for (const auto& pSDKAnnotCur : annotIteration) { + if (!pSDKAnnotCur) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + v8::Local pObj = + pRuntime->NewFxDynamicObj(CJS_Annot::GetObjDefnID()); + if (pObj.IsEmpty()) + return CJS_Return(false); + + CJS_Annot* pJS_Annot = + static_cast(pRuntime->GetObjectPrivate(pObj)); + Annot* pAnnot = static_cast(pJS_Annot->GetEmbedObject()); + pAnnot->SetSDKAnnot(static_cast(pSDKAnnotCur.Get())); + pRuntime->PutArrayElement( + annots, i, + pJS_Annot ? v8::Local(pJS_Annot->ToV8Object()) + : v8::Local()); + } + } + return CJS_Return(annots); +} + +CJS_Return Document::getAnnot3D( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(pRuntime->NewUndefined()); +} + +CJS_Return Document::getAnnots3D( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Document::getOCGs(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Document::getLinks(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect) { + return (rect.left <= LinkRect.left && rect.top <= LinkRect.top && + rect.right >= LinkRect.right && rect.bottom >= LinkRect.bottom); +} + +CJS_Return Document::addIcon(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString swIconName = pRuntime->ToWideString(params[0]); + if (!params[1]->IsObject()) + return CJS_Return(JSGetStringFromID(JSMessage::kTypeError)); + + v8::Local pJSIcon = pRuntime->ToObject(params[1]); + if (CFXJS_Engine::GetObjDefnID(pJSIcon) != CJS_Icon::GetObjDefnID()) + return CJS_Return(JSGetStringFromID(JSMessage::kTypeError)); + + v8::Local pObj = pRuntime->ToObject(params[1]); + CJS_Object* obj = static_cast(pRuntime->GetObjectPrivate(pObj)); + if (!obj->GetEmbedObject()) + return CJS_Return(JSGetStringFromID(JSMessage::kTypeError)); + + m_IconNames.push_back(swIconName); + return CJS_Return(true); +} + +CJS_Return Document::get_icons(CJS_Runtime* pRuntime) { + if (m_IconNames.empty()) + return CJS_Return(pRuntime->NewUndefined()); + + v8::Local Icons = pRuntime->NewArray(); + int i = 0; + for (const auto& name : m_IconNames) { + v8::Local pObj = + pRuntime->NewFxDynamicObj(CJS_Icon::GetObjDefnID()); + if (pObj.IsEmpty()) + return CJS_Return(false); + + CJS_Icon* pJS_Icon = + static_cast(pRuntime->GetObjectPrivate(pObj)); + Icon* pIcon = static_cast(pJS_Icon->GetEmbedObject()); + pIcon->SetIconName(name); + pRuntime->PutArrayElement(Icons, i++, + pJS_Icon + ? v8::Local(pJS_Icon->ToV8Object()) + : v8::Local()); + } + return CJS_Return(Icons); +} + +CJS_Return Document::set_icons(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Document::getIcon(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString swIconName = pRuntime->ToWideString(params[0]); + auto it = std::find(m_IconNames.begin(), m_IconNames.end(), swIconName); + if (it == m_IconNames.end()) + return CJS_Return(false); + + v8::Local pObj = + pRuntime->NewFxDynamicObj(CJS_Icon::GetObjDefnID()); + if (pObj.IsEmpty()) + return CJS_Return(false); + + CJS_Icon* pJS_Icon = static_cast(pRuntime->GetObjectPrivate(pObj)); + if (!pJS_Icon) + return CJS_Return(false); + + Icon* pIcon = static_cast(pJS_Icon->GetEmbedObject()); + pIcon->SetIconName(*it); + return CJS_Return(pJS_Icon->ToV8Object()); +} + +CJS_Return Document::removeIcon( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, no supported. + return CJS_Return(true); +} + +CJS_Return Document::createDataObject( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not implemented. + return CJS_Return(true); +} + +CJS_Return Document::get_media(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_media(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::calculateNow( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) || + m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || + m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) { + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + } + + m_pFormFillEnv->GetInterForm()->OnCalculate(); + return CJS_Return(true); +} + +CJS_Return Document::get_collab(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_collab(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::getPageNthWord( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + + // TODO(tsepez): check maximum allowable params. + + int nPageNo = params.size() > 0 ? pRuntime->ToInt32(params[0]) : 0; + int nWordNo = params.size() > 1 ? pRuntime->ToInt32(params[1]) : 0; + bool bStrip = params.size() > 2 ? pRuntime->ToBoolean(params[2]) : true; + + CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); + if (!pDocument) + return CJS_Return(false); + + if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo); + if (!pPageDict) + return CJS_Return(false); + + CPDF_Page page(pDocument, pPageDict, true); + page.ParseContent(); + + int nWords = 0; + WideString swRet; + for (auto& pPageObj : *page.GetPageObjectList()) { + if (pPageObj->IsText()) { + CPDF_TextObject* pTextObj = pPageObj->AsText(); + int nObjWords = CountWords(pTextObj); + if (nWords + nObjWords >= nWordNo) { + swRet = GetObjWordStr(pTextObj, nWordNo - nWords); + break; + } + nWords += nObjWords; + } + } + + if (bStrip) + swRet.Trim(); + return CJS_Return(pRuntime->NewString(swRet.c_str())); +} + +CJS_Return Document::getPageNthWordQuads( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + return CJS_Return(false); +} + +CJS_Return Document::getPageNumWords( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) + return CJS_Return(JSGetStringFromID(JSMessage::kPermissionError)); + + int nPageNo = params.size() > 0 ? pRuntime->ToInt32(params[0]) : 0; + CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); + if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo); + if (!pPageDict) + return CJS_Return(false); + + CPDF_Page page(pDocument, pPageDict, true); + page.ParseContent(); + + int nWords = 0; + for (auto& pPageObj : *page.GetPageObjectList()) { + if (pPageObj->IsText()) + nWords += CountWords(pPageObj->AsText()); + } + + return CJS_Return(pRuntime->NewNumber(nWords)); +} + +CJS_Return Document::getPrintParams( + CJS_Runtime* pRuntime, + const std::vector>& params) { + v8::Local pRetObj = + pRuntime->NewFxDynamicObj(CJS_PrintParamsObj::GetObjDefnID()); + if (pRetObj.IsEmpty()) + return CJS_Return(false); + + // Not implemented yet. + + return CJS_Return(pRetObj); +} + +#define ISLATINWORD(u) (u != 0x20 && u <= 0x28FF) + +int Document::CountWords(CPDF_TextObject* pTextObj) { + if (!pTextObj) + return 0; + + int nWords = 0; + + CPDF_Font* pFont = pTextObj->GetFont(); + if (!pFont) + return 0; + + bool bIsLatin = false; + + for (size_t i = 0, sz = pTextObj->CountChars(); i < sz; ++i) { + uint32_t charcode = CPDF_Font::kInvalidCharCode; + float kerning; + + pTextObj->GetCharInfo(i, &charcode, &kerning); + WideString swUnicode = pFont->UnicodeFromCharCode(charcode); + + uint16_t unicode = 0; + if (swUnicode.GetLength() > 0) + unicode = swUnicode[0]; + + if (ISLATINWORD(unicode) && bIsLatin) + continue; + + bIsLatin = ISLATINWORD(unicode); + if (unicode != 0x20) + nWords++; + } + + return nWords; +} + +WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj, int nWordIndex) { + WideString swRet; + + CPDF_Font* pFont = pTextObj->GetFont(); + if (!pFont) + return L""; + + int nWords = 0; + bool bIsLatin = false; + + for (size_t i = 0, sz = pTextObj->CountChars(); i < sz; ++i) { + uint32_t charcode = CPDF_Font::kInvalidCharCode; + float kerning; + + pTextObj->GetCharInfo(i, &charcode, &kerning); + WideString swUnicode = pFont->UnicodeFromCharCode(charcode); + + uint16_t unicode = 0; + if (swUnicode.GetLength() > 0) + unicode = swUnicode[0]; + + if (ISLATINWORD(unicode) && bIsLatin) { + } else { + bIsLatin = ISLATINWORD(unicode); + if (unicode != 0x20) + nWords++; + } + + if (nWords - 1 == nWordIndex) + swRet += unicode; + } + + return swRet; +} + +CJS_Return Document::get_zoom(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_zoom(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::get_zoom_type(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Document::set_zoom_type(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Document::deletePages( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::extractPages( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::insertPages( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::replacePages( + CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::getURL(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Document::gotoNamedDest( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (!m_pFormFillEnv) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + WideString wideName = pRuntime->ToWideString(params[0]); + CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); + if (!pDocument) + return CJS_Return(false); + + CPDF_NameTree nameTree(pDocument, "Dests"); + CPDF_Array* destArray = nameTree.LookupNamedDest(pDocument, wideName); + if (!destArray) + return CJS_Return(false); + + CPDF_Dest dest(destArray); + const CPDF_Array* arrayObject = ToArray(dest.GetObject()); + std::vector scrollPositionArray; + if (arrayObject) { + for (size_t i = 2; i < arrayObject->GetCount(); i++) + scrollPositionArray.push_back(arrayObject->GetFloatAt(i)); + } + pRuntime->BeginBlock(); + m_pFormFillEnv->DoGoToAction(dest.GetPageIndex(pDocument), dest.GetZoomMode(), + scrollPositionArray.data(), + scrollPositionArray.size()); + pRuntime->EndBlock(); + return CJS_Return(true); +} + +void Document::AddDelayData(CJS_DelayData* pData) { + m_DelayData.push_back(std::unique_ptr(pData)); +} + +void Document::DoFieldDelay(const WideString& sFieldName, int nControlIndex) { + std::vector> delayed_data; + auto iter = m_DelayData.begin(); + while (iter != m_DelayData.end()) { + auto old = iter++; + if ((*old)->sFieldName == sFieldName && + (*old)->nControlIndex == nControlIndex) { + delayed_data.push_back(std::move(*old)); + m_DelayData.erase(old); + } + } + + for (const auto& pData : delayed_data) + Field::DoDelay(m_pFormFillEnv.Get(), pData.get()); +} + +CJS_Document* Document::GetCJSDoc() const { + return static_cast(m_pJSObject.Get()); +} diff --git a/fxjs/cjs_document.h b/fxjs/cjs_document.h new file mode 100644 index 0000000000000000000000000000000000000000..edfaf962005509202ba1df051dec7e7c46bc9ae8 --- /dev/null +++ b/fxjs/cjs_document.h @@ -0,0 +1,330 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_DOCUMENT_H_ +#define FXJS_CJS_DOCUMENT_H_ + +#include +#include +#include + +#include "fxjs/JS_Define.h" + +class CJS_Document; +class CPDF_TextObject; + +struct CJS_DelayData; + +class Document : public CJS_EmbedObj { + public: + explicit Document(CJS_Object* pJSObject); + ~Document() override; + + CJS_Return get_ADBE(CJS_Runtime* pRuntime); + CJS_Return set_ADBE(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_author(CJS_Runtime* pRuntime); + CJS_Return set_author(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_base_URL(CJS_Runtime* pRuntime); + CJS_Return set_base_URL(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_bookmark_root(CJS_Runtime* pRuntime); + CJS_Return set_bookmark_root(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_calculate(CJS_Runtime* pRuntime); + CJS_Return set_calculate(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_collab(CJS_Runtime* pRuntime); + CJS_Return set_collab(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_creation_date(CJS_Runtime* pRuntime); + CJS_Return set_creation_date(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_creator(CJS_Runtime* pRuntime); + CJS_Return set_creator(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_delay(CJS_Runtime* pRuntime); + CJS_Return set_delay(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_dirty(CJS_Runtime* pRuntime); + CJS_Return set_dirty(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_document_file_name(CJS_Runtime* pRuntime); + CJS_Return set_document_file_name(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_external(CJS_Runtime* pRuntime); + CJS_Return set_external(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_filesize(CJS_Runtime* pRuntime); + CJS_Return set_filesize(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_icons(CJS_Runtime* pRuntime); + CJS_Return set_icons(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_info(CJS_Runtime* pRuntime); + CJS_Return set_info(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_keywords(CJS_Runtime* pRuntime); + CJS_Return set_keywords(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_layout(CJS_Runtime* pRuntime); + CJS_Return set_layout(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_media(CJS_Runtime* pRuntime); + CJS_Return set_media(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_mod_date(CJS_Runtime* pRuntime); + CJS_Return set_mod_date(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_mouse_x(CJS_Runtime* pRuntime); + CJS_Return set_mouse_x(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_mouse_y(CJS_Runtime* pRuntime); + CJS_Return set_mouse_y(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_num_fields(CJS_Runtime* pRuntime); + CJS_Return set_num_fields(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_num_pages(CJS_Runtime* pRuntime); + CJS_Return set_num_pages(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_page_num(CJS_Runtime* pRuntime); + CJS_Return set_page_num(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_page_window_rect(CJS_Runtime* pRuntime); + CJS_Return set_page_window_rect(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_path(CJS_Runtime* pRuntime); + CJS_Return set_path(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_producer(CJS_Runtime* pRuntime); + CJS_Return set_producer(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_subject(CJS_Runtime* pRuntime); + CJS_Return set_subject(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_title(CJS_Runtime* pRuntime); + CJS_Return set_title(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_zoom(CJS_Runtime* pRuntime); + CJS_Return set_zoom(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_zoom_type(CJS_Runtime* pRuntime); + CJS_Return set_zoom_type(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_URL(CJS_Runtime* pRuntime); + CJS_Return set_URL(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return addAnnot(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return addField(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return addLink(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return addIcon(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return calculateNow(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return closeDoc(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return createDataObject(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return deletePages(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return exportAsText(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return exportAsFDF(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return exportAsXFDF(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return extractPages(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getAnnot(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getAnnots(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getAnnot3D(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getAnnots3D(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getField(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getIcon(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getLinks(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getNthFieldName(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getOCGs(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getPageBox(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getPageNthWord(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getPageNthWordQuads( + CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getPageNumWords(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getPrintParams(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getURL(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return gotoNamedDest(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return importAnFDF(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return importAnXFDF(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return importTextData(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return insertPages(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return mailForm(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return print(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return removeField(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return replacePages(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return resetForm(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return saveAs(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return submitForm(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return syncAnnotScan(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return mailDoc(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return removeIcon(CJS_Runtime* pRuntime, + const std::vector>& params); + + void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv); + CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { + return m_pFormFillEnv.Get(); + } + void AddDelayData(CJS_DelayData* pData); + void DoFieldDelay(const WideString& sFieldName, int nControlIndex); + CJS_Document* GetCJSDoc() const; + + private: + bool IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect); + int CountWords(CPDF_TextObject* pTextObj); + WideString GetObjWordStr(CPDF_TextObject* pTextObj, int nWordIndex); + + CJS_Return getPropertyInternal(CJS_Runtime* pRuntime, + const ByteString& propName); + CJS_Return setPropertyInternal(CJS_Runtime* pRuntime, + v8::Local vp, + const ByteString& propName); + + CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; + WideString m_cwBaseURL; + std::list> m_DelayData; + // Needs to be a std::list for iterator stability. + std::list m_IconNames; + bool m_bDelay; +}; + +class CJS_Document : public CJS_Object { + public: + static int GetObjDefnID(); + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Document(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Document() override {} + + // CJS_Object + void InitInstance(IJS_Runtime* pIRuntime) override; + + JS_STATIC_PROP(ADBE, ADBE, Document); + JS_STATIC_PROP(author, author, Document); + JS_STATIC_PROP(baseURL, base_URL, Document); + JS_STATIC_PROP(bookmarkRoot, bookmark_root, Document); + JS_STATIC_PROP(calculate, calculate, Document); + JS_STATIC_PROP(Collab, collab, Document); + JS_STATIC_PROP(creationDate, creation_date, Document); + JS_STATIC_PROP(creator, creator, Document); + JS_STATIC_PROP(delay, delay, Document); + JS_STATIC_PROP(dirty, dirty, Document); + JS_STATIC_PROP(documentFileName, document_file_name, Document); + JS_STATIC_PROP(external, external, Document); + JS_STATIC_PROP(filesize, filesize, Document); + JS_STATIC_PROP(icons, icons, Document); + JS_STATIC_PROP(info, info, Document); + JS_STATIC_PROP(keywords, keywords, Document); + JS_STATIC_PROP(layout, layout, Document); + JS_STATIC_PROP(media, media, Document); + JS_STATIC_PROP(modDate, mod_date, Document); + JS_STATIC_PROP(mouseX, mouse_x, Document); + JS_STATIC_PROP(mouseY, mouse_y, Document); + JS_STATIC_PROP(numFields, num_fields, Document); + JS_STATIC_PROP(numPages, num_pages, Document); + JS_STATIC_PROP(pageNum, page_num, Document); + JS_STATIC_PROP(pageWindowRect, page_window_rect, Document); + JS_STATIC_PROP(path, path, Document); + JS_STATIC_PROP(producer, producer, Document); + JS_STATIC_PROP(subject, subject, Document); + JS_STATIC_PROP(title, title, Document); + JS_STATIC_PROP(URL, URL, Document); + JS_STATIC_PROP(zoom, zoom, Document); + JS_STATIC_PROP(zoomType, zoom_type, Document); + + JS_STATIC_METHOD(addAnnot, Document); + JS_STATIC_METHOD(addField, Document); + JS_STATIC_METHOD(addLink, Document); + JS_STATIC_METHOD(addIcon, Document); + JS_STATIC_METHOD(calculateNow, Document); + JS_STATIC_METHOD(closeDoc, Document); + JS_STATIC_METHOD(createDataObject, Document); + JS_STATIC_METHOD(deletePages, Document); + JS_STATIC_METHOD(exportAsText, Document); + JS_STATIC_METHOD(exportAsFDF, Document); + JS_STATIC_METHOD(exportAsXFDF, Document); + JS_STATIC_METHOD(extractPages, Document); + JS_STATIC_METHOD(getAnnot, Document); + JS_STATIC_METHOD(getAnnots, Document); + JS_STATIC_METHOD(getAnnot3D, Document); + JS_STATIC_METHOD(getAnnots3D, Document); + JS_STATIC_METHOD(getField, Document); + JS_STATIC_METHOD(getIcon, Document); + JS_STATIC_METHOD(getLinks, Document); + JS_STATIC_METHOD(getNthFieldName, Document); + JS_STATIC_METHOD(getOCGs, Document); + JS_STATIC_METHOD(getPageBox, Document); + JS_STATIC_METHOD(getPageNthWord, Document); + JS_STATIC_METHOD(getPageNthWordQuads, Document); + JS_STATIC_METHOD(getPageNumWords, Document); + JS_STATIC_METHOD(getPrintParams, Document); + JS_STATIC_METHOD(getURL, Document); + JS_STATIC_METHOD(gotoNamedDest, Document); + JS_STATIC_METHOD(importAnFDF, Document); + JS_STATIC_METHOD(importAnXFDF, Document); + JS_STATIC_METHOD(importTextData, Document); + JS_STATIC_METHOD(insertPages, Document); + JS_STATIC_METHOD(mailForm, Document); + JS_STATIC_METHOD(print, Document); + JS_STATIC_METHOD(removeField, Document); + JS_STATIC_METHOD(replacePages, Document); + JS_STATIC_METHOD(removeIcon, Document); + JS_STATIC_METHOD(resetForm, Document); + JS_STATIC_METHOD(saveAs, Document); + JS_STATIC_METHOD(submitForm, Document); + JS_STATIC_METHOD(syncAnnotScan, Document); + JS_STATIC_METHOD(mailDoc, Document); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_DOCUMENT_H_ diff --git a/fxjs/cjs_embedobj.cpp b/fxjs/cjs_embedobj.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbebd6311bbee405169221f777788131dac70dd1 --- /dev/null +++ b/fxjs/cjs_embedobj.cpp @@ -0,0 +1,13 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_embedobj.h" + +#include "fxjs/cjs_object.h" + +CJS_EmbedObj::CJS_EmbedObj(CJS_Object* pJSObject) : m_pJSObject(pJSObject) {} + +CJS_EmbedObj::~CJS_EmbedObj() {} diff --git a/fxjs/cjs_embedobj.h b/fxjs/cjs_embedobj.h new file mode 100644 index 0000000000000000000000000000000000000000..82e549e32144ab1deaf01d9592133314c4497263 --- /dev/null +++ b/fxjs/cjs_embedobj.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_EMBEDOBJ_H_ +#define FXJS_CJS_EMBEDOBJ_H_ + +#include "core/fxcrt/unowned_ptr.h" + +class CJS_Object; + +class CJS_EmbedObj { + public: + explicit CJS_EmbedObj(CJS_Object* pJSObject); + virtual ~CJS_EmbedObj(); + + CJS_Object* GetJSObject() const { return m_pJSObject.Get(); } + + protected: + UnownedPtr const m_pJSObject; +}; + +#endif // FXJS_CJS_EMBEDOBJ_H_ diff --git a/fxjs/cjs_event.cpp b/fxjs/cjs_event.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fb988f4a6f98344e2075cf5feac11f2d51ce777 --- /dev/null +++ b/fxjs/cjs_event.cpp @@ -0,0 +1,307 @@ +// 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 "fxjs/cjs_event.h" + +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_field.h" +#include "fxjs/cjs_object.h" + +const JSPropertySpec CJS_Event::PropertySpecs[] = { + {"change", get_change_static, set_change_static}, + {"changeEx", get_change_ex_static, set_change_ex_static}, + {"commitKey", get_commit_key_static, set_commit_key_static}, + {"fieldFull", get_field_full_static, set_field_full_static}, + {"keyDown", get_key_down_static, set_key_down_static}, + {"modifier", get_modifier_static, set_modifier_static}, + {"name", get_name_static, set_name_static}, + {"rc", get_rc_static, set_rc_static}, + {"richChange", get_rich_change_static, set_rich_change_static}, + {"richChangeEx", get_rich_change_ex_static, set_rich_change_ex_static}, + {"richValue", get_rich_value_static, set_rich_value_static}, + {"selEnd", get_sel_end_static, set_sel_end_static}, + {"selStart", get_sel_start_static, set_sel_start_static}, + {"shift", get_shift_static, set_shift_static}, + {"source", get_source_static, set_source_static}, + {"target", get_target_static, set_target_static}, + {"targetName", get_target_name_static, set_target_name_static}, + {"type", get_type_static, set_type_static}, + {"value", get_value_static, set_value_static}, + {"willCommit", get_will_commit_static, set_will_commit_static}}; + +int CJS_Event::ObjDefnID = -1; + +// static +void CJS_Event::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("event", FXJSOBJTYPE_STATIC, + JSConstructor, + JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); +} + +event::event(CJS_Object* pJsObject) : CJS_EmbedObj(pJsObject) {} + +event::~event() {} + +CJS_Return event::get_change(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewString(pEvent->Change().c_str())); +} + +CJS_Return event::set_change(CJS_Runtime* pRuntime, v8::Local vp) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (vp->IsString()) { + WideString& wChange = pEvent->Change(); + wChange = pRuntime->ToWideString(vp); + } + return CJS_Return(true); +} + +CJS_Return event::get_change_ex(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + return CJS_Return(pRuntime->NewString(pEvent->ChangeEx().c_str())); +} + +CJS_Return event::set_change_ex(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_commit_key(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + return CJS_Return(pRuntime->NewNumber(pEvent->CommitKey())); +} + +CJS_Return event::set_commit_key(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_field_full(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean(pEvent->FieldFull())); +} + +CJS_Return event::set_field_full(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_key_down(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewBoolean(pEvent->KeyDown())); +} + +CJS_Return event::set_key_down(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_modifier(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewBoolean(pEvent->Modifier())); +} + +CJS_Return event::set_modifier(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_name(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewString(pEvent->Name())); +} + +CJS_Return event::set_name(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_rc(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewBoolean(pEvent->Rc())); +} + +CJS_Return event::set_rc(CJS_Runtime* pRuntime, v8::Local vp) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + pEvent->Rc() = pRuntime->ToBoolean(vp); + return CJS_Return(true); +} + +CJS_Return event::get_rich_change(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return event::set_rich_change(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return event::get_rich_change_ex(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return event::set_rich_change_ex(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return event::get_rich_value(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return event::set_rich_value(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return event::get_sel_end(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) + return CJS_Return(true); + + return CJS_Return(pRuntime->NewNumber(pEvent->SelEnd())); +} + +CJS_Return event::set_sel_end(CJS_Runtime* pRuntime, v8::Local vp) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) + return CJS_Return(true); + + pEvent->SetSelEnd(pRuntime->ToInt32(vp)); + return CJS_Return(true); +} + +CJS_Return event::get_sel_start(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) + return CJS_Return(true); + + return CJS_Return(pRuntime->NewNumber(pEvent->SelStart())); +} + +CJS_Return event::set_sel_start(CJS_Runtime* pRuntime, + v8::Local vp) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0) + return CJS_Return(true); + + pEvent->SetSelStart(pRuntime->ToInt32(vp)); + return CJS_Return(true); +} + +CJS_Return event::get_shift(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewBoolean(pEvent->Shift())); +} + +CJS_Return event::set_shift(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_source(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pEvent->Source()->GetJSObject()->ToV8Object()); +} + +CJS_Return event::set_source(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_target(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pEvent->Target_Field()->GetJSObject()->ToV8Object()); +} + +CJS_Return event::set_target(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_target_name(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewString(pEvent->TargetName().c_str())); +} + +CJS_Return event::set_target_name(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_type(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewString(pEvent->Type())); +} + +CJS_Return event::set_type(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return event::get_value(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Type(), L"Field") != 0) + return CJS_Return(false); + + if (!pEvent->m_pValue) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewString(pEvent->Value().c_str())); +} + +CJS_Return event::set_value(CJS_Runtime* pRuntime, v8::Local vp) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + if (wcscmp((const wchar_t*)pEvent->Type(), L"Field") != 0) + return CJS_Return(false); + + if (!pEvent->m_pValue) + return CJS_Return(false); + + pEvent->Value() = pRuntime->ToWideString(vp); + return CJS_Return(true); +} + +CJS_Return event::get_will_commit(CJS_Runtime* pRuntime) { + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + return CJS_Return(pRuntime->NewBoolean(pEvent->WillCommit())); +} + +CJS_Return event::set_will_commit(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} diff --git a/fxjs/cjs_event.h b/fxjs/cjs_event.h new file mode 100644 index 0000000000000000000000000000000000000000..4ae5fa234fa82036a7b8ecc450790f515040796b --- /dev/null +++ b/fxjs/cjs_event.h @@ -0,0 +1,111 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_EVENT_H_ +#define FXJS_CJS_EVENT_H_ + +#include "fxjs/JS_Define.h" + +class event : public CJS_EmbedObj { + public: + explicit event(CJS_Object* pJSObject); + ~event() override; + + CJS_Return get_change(CJS_Runtime* pRuntime); + CJS_Return set_change(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_change_ex(CJS_Runtime* pRuntime); + CJS_Return set_change_ex(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_commit_key(CJS_Runtime* pRuntime); + CJS_Return set_commit_key(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_field_full(CJS_Runtime* pRuntime); + CJS_Return set_field_full(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_key_down(CJS_Runtime* pRuntime); + CJS_Return set_key_down(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_modifier(CJS_Runtime* pRuntime); + CJS_Return set_modifier(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_name(CJS_Runtime* pRuntime); + CJS_Return set_name(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rc(CJS_Runtime* pRuntime); + CJS_Return set_rc(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rich_change(CJS_Runtime* pRuntime); + CJS_Return set_rich_change(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rich_change_ex(CJS_Runtime* pRuntime); + CJS_Return set_rich_change_ex(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rich_value(CJS_Runtime* pRuntime); + CJS_Return set_rich_value(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_sel_end(CJS_Runtime* pRuntime); + CJS_Return set_sel_end(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_sel_start(CJS_Runtime* pRuntime); + CJS_Return set_sel_start(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_shift(CJS_Runtime* pRuntime); + CJS_Return set_shift(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_source(CJS_Runtime* pRuntime); + CJS_Return set_source(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_target(CJS_Runtime* pRuntime); + CJS_Return set_target(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_target_name(CJS_Runtime* pRuntime); + CJS_Return set_target_name(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_type(CJS_Runtime* pRuntime); + CJS_Return set_type(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_value(CJS_Runtime* pRuntime); + CJS_Return set_value(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_will_commit(CJS_Runtime* pRuntime); + CJS_Return set_will_commit(CJS_Runtime* pRuntime, v8::Local vp); +}; + +class CJS_Event : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Event(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Event() override {} + + JS_STATIC_PROP(change, change, event); + JS_STATIC_PROP(changeEx, change_ex, event); + JS_STATIC_PROP(commitKey, commit_key, event); + JS_STATIC_PROP(fieldFull, field_full, event); + JS_STATIC_PROP(keyDown, key_down, event); + JS_STATIC_PROP(modifier, modifier, event); + JS_STATIC_PROP(name, name, event); + JS_STATIC_PROP(rc, rc, event); + JS_STATIC_PROP(richChange, rich_change, event); + JS_STATIC_PROP(richChangeEx, rich_change_ex, event); + JS_STATIC_PROP(richValue, rich_value, event); + JS_STATIC_PROP(selEnd, sel_end, event); + JS_STATIC_PROP(selStart, sel_start, event); + JS_STATIC_PROP(shift, shift, event); + JS_STATIC_PROP(source, source, event); + JS_STATIC_PROP(target, target, event); + JS_STATIC_PROP(targetName, target_name, event); + JS_STATIC_PROP(type, type, event); + JS_STATIC_PROP(value, value, event); + JS_STATIC_PROP(willCommit, will_commit, event); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; +}; + +#endif // FXJS_CJS_EVENT_H_ diff --git a/fpdfsdk/javascript/cjs_event_context.cpp b/fxjs/cjs_event_context.cpp similarity index 86% rename from fpdfsdk/javascript/cjs_event_context.cpp rename to fxjs/cjs_event_context.cpp index abfb6da36faccd118077d9b7627fc5b3fa720af2..d2f270b1c4ee03b9f6a8355b08c77f222ff7dc81 100644 --- a/fpdfsdk/javascript/cjs_event_context.cpp +++ b/fxjs/cjs_event_context.cpp @@ -4,11 +4,13 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "fpdfsdk/javascript/cjs_event_context.h" +#include "fxjs/cjs_event_context.h" -#include "fpdfsdk/javascript/JS_EventHandler.h" -#include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/javascript/resource.h" +#include "core/fxcrt/autorestorer.h" +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_runtime.h" +#include "fxjs/js_resources.h" CJS_EventContext::CJS_EventContext(CJS_Runtime* pRuntime) : m_pRuntime(pRuntime), @@ -23,30 +25,29 @@ CPDFSDK_FormFillEnvironment* CJS_EventContext::GetFormFillEnv() { return m_pRuntime->GetFormFillEnv(); } -bool CJS_EventContext::RunScript(const CFX_WideString& script, - CFX_WideString* info) { +bool CJS_EventContext::RunScript(const WideString& script, WideString* info) { v8::Isolate::Scope isolate_scope(m_pRuntime->GetIsolate()); v8::HandleScope handle_scope(m_pRuntime->GetIsolate()); v8::Local context = m_pRuntime->NewLocalContext(); v8::Context::Scope context_scope(context); if (m_bBusy) { - *info = JSGetStringFromID(IDS_STRING_JSBUSY); + *info = JSGetStringFromID(JSMessage::kBusyError); return false; } - CFX_AutoRestorer restorer(&m_bBusy); + AutoRestorer restorer(&m_bBusy); m_bBusy = true; ASSERT(m_pEventHandler->IsValid()); CJS_Runtime::FieldEvent event(m_pEventHandler->TargetName(), m_pEventHandler->EventType()); if (!m_pRuntime->AddEventToSet(event)) { - *info = JSGetStringFromID(IDS_STRING_JSEVENT); + *info = JSGetStringFromID(JSMessage::kDuplicateEventError); return false; } - CFX_WideString sErrorMessage; + WideString sErrorMessage; int nRet = 0; if (script.GetLength() > 0) nRet = m_pRuntime->ExecuteScript(script.c_str(), &sErrorMessage); @@ -54,7 +55,7 @@ bool CJS_EventContext::RunScript(const CFX_WideString& script, if (nRet < 0) *info += sErrorMessage; else - *info = JSGetStringFromID(IDS_STRING_RUN); + *info = JSGetStringFromID(JSMessage::kRunSuccess); m_pRuntime->RemoveEventFromSet(event); m_pEventHandler->Destroy(); @@ -66,7 +67,7 @@ void CJS_EventContext::OnApp_Init() { } void CJS_EventContext::OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) { + const WideString& strTargetName) { m_pEventHandler->OnDoc_Open(pFormFillEnv, strTargetName); } @@ -140,39 +141,39 @@ void CJS_EventContext::OnField_MouseUp(bool bModifier, void CJS_EventContext::OnField_Focus(bool bModifier, bool bShift, CPDF_FormField* pTarget, - const CFX_WideString& Value) { + const WideString& Value) { m_pEventHandler->OnField_Focus(bModifier, bShift, pTarget, Value); } void CJS_EventContext::OnField_Blur(bool bModifier, bool bShift, CPDF_FormField* pTarget, - const CFX_WideString& Value) { + const WideString& Value) { m_pEventHandler->OnField_Blur(bModifier, bShift, pTarget, Value); } void CJS_EventContext::OnField_Calculate(CPDF_FormField* pSource, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool& bRc) { m_pEventHandler->OnField_Calculate(pSource, pTarget, Value, bRc); } void CJS_EventContext::OnField_Format(CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool bWillCommit) { m_pEventHandler->OnField_Format(pTarget, Value, bWillCommit); } -void CJS_EventContext::OnField_Keystroke(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, +void CJS_EventContext::OnField_Keystroke(WideString& strChange, + const WideString& strChangeEx, bool bKeyDown, bool bModifier, int& nSelEnd, int& nSelStart, bool bShift, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool bWillCommit, bool bFieldFull, bool& bRc) { @@ -181,13 +182,13 @@ void CJS_EventContext::OnField_Keystroke(CFX_WideString& strChange, pTarget, Value, bWillCommit, bFieldFull, bRc); } -void CJS_EventContext::OnField_Validate(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, +void CJS_EventContext::OnField_Validate(WideString& strChange, + const WideString& strChangeEx, bool bKeyDown, bool bModifier, bool bShift, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool& bRc) { m_pEventHandler->OnField_Validate(strChange, strChangeEx, bKeyDown, bModifier, bShift, pTarget, Value, bRc); @@ -275,6 +276,6 @@ void CJS_EventContext::OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) { } void CJS_EventContext::OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) { + const WideString& strTargetName) { m_pEventHandler->OnMenu_Exec(pFormFillEnv, strTargetName); } diff --git a/fpdfsdk/javascript/cjs_event_context.h b/fxjs/cjs_event_context.h similarity index 82% rename from fpdfsdk/javascript/cjs_event_context.h rename to fxjs/cjs_event_context.h index 7bfe52816d9cb49113dfe0cde9c88c8c3ec6333c..f9572909e859ba6f6dac26157365c078689e6248 100644 --- a/fpdfsdk/javascript/cjs_event_context.h +++ b/fxjs/cjs_event_context.h @@ -4,14 +4,15 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef FPDFSDK_JAVASCRIPT_CJS_EVENT_CONTEXT_H_ -#define FPDFSDK_JAVASCRIPT_CJS_EVENT_CONTEXT_H_ +#ifndef FXJS_CJS_EVENT_CONTEXT_H_ +#define FXJS_CJS_EVENT_CONTEXT_H_ #include #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" -#include "fpdfsdk/javascript/ijs_event_context.h" +#include "core/fxcrt/unowned_ptr.h" +#include "fxjs/ijs_event_context.h" class CJS_EventHandler; class CJS_Runtime; @@ -23,10 +24,10 @@ class CJS_EventContext : public IJS_EventContext { ~CJS_EventContext() override; // IJS_EventContext - bool RunScript(const CFX_WideString& script, CFX_WideString* info) override; + bool RunScript(const WideString& script, WideString* info) override; void OnApp_Init() override; void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) override; + const WideString& strTargetName) override; void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override; void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override; void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override; @@ -51,37 +52,37 @@ class CJS_EventContext : public IJS_EventContext { void OnField_Focus(bool bModifier, bool bShift, CPDF_FormField* pTarget, - const CFX_WideString& Value) override; + const WideString& Value) override; void OnField_Blur(bool bModifier, bool bShift, CPDF_FormField* pTarget, - const CFX_WideString& Value) override; + const WideString& Value) override; void OnField_Calculate(CPDF_FormField* pSource, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool& bRc) override; void OnField_Format(CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool bWillCommit) override; - void OnField_Keystroke(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, + void OnField_Keystroke(WideString& strChange, + const WideString& strChangeEx, bool bKeyDown, bool bModifier, int& nSelEnd, int& nSelStart, bool bShift, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool bWillCommit, bool bFieldFull, bool& bRc) override; - void OnField_Validate(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, + void OnField_Validate(WideString& strChange, + const WideString& strChangeEx, bool bKeyDown, bool bModifier, bool bShift, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool& bRc) override; void OnScreen_Focus(bool bModifier, bool bShift, @@ -116,20 +117,20 @@ class CJS_EventContext : public IJS_EventContext { void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) override; void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) override; void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) override; + const WideString& strTargetName) override; void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) override; void OnConsole_Exec() override; void OnExternal_Exec() override; - CJS_Runtime* GetJSRuntime() const { return m_pRuntime; } + CJS_Runtime* GetJSRuntime() const { return m_pRuntime.Get(); } CJS_EventHandler* GetEventHandler() const { return m_pEventHandler.get(); } CPDFSDK_FormFillEnvironment* GetFormFillEnv(); private: - CJS_Runtime* const m_pRuntime; + UnownedPtr const m_pRuntime; std::unique_ptr m_pEventHandler; bool m_bBusy; }; -#endif // FPDFSDK_JAVASCRIPT_CJS_EVENT_CONTEXT_H_ +#endif // FXJS_CJS_EVENT_CONTEXT_H_ diff --git a/fxjs/cjs_event_context_stub.cpp b/fxjs/cjs_event_context_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0517ab2c49605db2d96fee21305580c5f941afc1 --- /dev/null +++ b/fxjs/cjs_event_context_stub.cpp @@ -0,0 +1,12 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_event_context_stub.h" + +bool CJS_EventContextStub::RunScript(const WideString& script, + WideString* info) { + return false; +} diff --git a/fxjs/cjs_event_context_stub.h b/fxjs/cjs_event_context_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..bc853694dfef6c965ede482b159df8d3add411aa --- /dev/null +++ b/fxjs/cjs_event_context_stub.h @@ -0,0 +1,118 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_EVENT_CONTEXT_STUB_H_ +#define FXJS_CJS_EVENT_CONTEXT_STUB_H_ + +#include "fxjs/ijs_event_context.h" + +class CJS_EventContextStub final : public IJS_EventContext { + public: + CJS_EventContextStub() {} + ~CJS_EventContextStub() override {} + + // IJS_EventContext: + bool RunScript(const WideString& script, WideString* info) override; + + void OnApp_Init() override {} + void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& strTargetName) override {} + void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnField_MouseDown(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) override {} + void OnField_MouseEnter(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) override {} + void OnField_MouseExit(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) override {} + void OnField_MouseUp(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) override {} + void OnField_Focus(bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + const WideString& Value) override {} + void OnField_Blur(bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + const WideString& Value) override {} + void OnField_Calculate(CPDF_FormField* pSource, + CPDF_FormField* pTarget, + WideString& Value, + bool& bRc) override {} + void OnField_Format(CPDF_FormField* pTarget, + WideString& Value, + bool bWillCommit) override {} + void OnField_Keystroke(WideString& strChange, + const WideString& strChangeEx, + bool KeyDown, + bool bModifier, + int& nSelEnd, + int& nSelStart, + bool bShift, + CPDF_FormField* pTarget, + WideString& Value, + bool bWillCommit, + bool bFieldFull, + bool& bRc) override {} + void OnField_Validate(WideString& strChange, + const WideString& strChangeEx, + bool bKeyDown, + bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + WideString& Value, + bool& bRc) override {} + void OnScreen_Focus(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_Blur(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_Open(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_Close(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_MouseDown(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_MouseUp(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_MouseEnter(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_MouseExit(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_InView(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnScreen_OutView(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) override {} + void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) override {} + void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString&) override {} + void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {} + void OnConsole_Exec() override {} + void OnExternal_Exec() override {} +}; + +#endif // FXJS_CJS_EVENT_CONTEXT_STUB_H_ diff --git a/fxjs/cjs_eventhandler.cpp b/fxjs/cjs_eventhandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb150b247bf3402dd8d1338b3351136c7a22af71 --- /dev/null +++ b/fxjs/cjs_eventhandler.cpp @@ -0,0 +1,654 @@ +// 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 "fxjs/cjs_eventhandler.h" + +#include "core/fpdfdoc/cpdf_formfield.h" +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_document.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_field.h" +#include "fxjs/cjs_object.h" +#include "fxjs/cjs_runtime.h" + +CJS_EventHandler::CJS_EventHandler(CJS_EventContext* pContext) + : m_pJSEventContext(pContext), + m_eEventType(JET_UNKNOWN), + m_bValid(false), + m_pWideStrChange(nullptr), + m_nCommitKey(-1), + m_bKeyDown(false), + m_bModifier(false), + m_bShift(false), + m_pISelEnd(nullptr), + m_nSelEndDu(0), + m_pISelStart(nullptr), + m_nSelStartDu(0), + m_bWillCommit(false), + m_pValue(nullptr), + m_bFieldFull(false), + m_pbRc(nullptr), + m_bRcDu(false), + m_pTargetBookMark(nullptr), + m_pTargetFormFillEnv(nullptr), + m_pTargetAnnot(nullptr) {} + +CJS_EventHandler::~CJS_EventHandler() {} + +void CJS_EventHandler::OnApp_Init() { + Initial(JET_APP_INIT); +} + +void CJS_EventHandler::OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& strTargetName) { + Initial(JET_DOC_OPEN); + m_pTargetFormFillEnv.Reset(pFormFillEnv); + m_strTargetName = strTargetName; +} + +void CJS_EventHandler::OnDoc_WillPrint( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_DOC_WILLPRINT); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnDoc_DidPrint( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_DOC_DIDPRINT); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnDoc_WillSave( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_DOC_WILLSAVE); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnDoc_DidSave( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_DOC_DIDSAVE); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnDoc_WillClose( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_DOC_WILLCLOSE); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_PAGE_OPEN); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_PAGE_CLOSE); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnPage_InView( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_PAGE_INVIEW); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnPage_OutView( + CPDFSDK_FormFillEnvironment* pFormFillEnv) { + Initial(JET_PAGE_OUTVIEW); + m_pTargetFormFillEnv.Reset(pFormFillEnv); +} + +void CJS_EventHandler::OnField_MouseEnter(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) { + Initial(JET_FIELD_MOUSEENTER); + + m_bModifier = bModifier; + m_bShift = bShift; + + m_strTargetName = pTarget->GetFullName(); +} + +void CJS_EventHandler::OnField_MouseExit(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) { + Initial(JET_FIELD_MOUSEEXIT); + + m_bModifier = bModifier; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); +} + +void CJS_EventHandler::OnField_MouseDown(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) { + Initial(JET_FIELD_MOUSEDOWN); + m_eEventType = JET_FIELD_MOUSEDOWN; + + m_bModifier = bModifier; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); +} + +void CJS_EventHandler::OnField_MouseUp(bool bModifier, + bool bShift, + CPDF_FormField* pTarget) { + Initial(JET_FIELD_MOUSEUP); + + m_bModifier = bModifier; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); +} + +void CJS_EventHandler::OnField_Focus(bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + const WideString& Value) { + Initial(JET_FIELD_FOCUS); + + m_bModifier = bModifier; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); + m_pValue = (WideString*)&Value; +} + +void CJS_EventHandler::OnField_Blur(bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + const WideString& Value) { + Initial(JET_FIELD_BLUR); + + m_bModifier = bModifier; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); + m_pValue = (WideString*)&Value; +} + +void CJS_EventHandler::OnField_Keystroke(WideString& strChange, + const WideString& strChangeEx, + bool KeyDown, + bool bModifier, + int& nSelEnd, + int& nSelStart, + bool bShift, + CPDF_FormField* pTarget, + WideString& Value, + bool bWillCommit, + bool bFieldFull, + bool& bRc) { + Initial(JET_FIELD_KEYSTROKE); + + m_nCommitKey = 0; + m_pWideStrChange = &strChange; + m_WideStrChangeEx = strChangeEx; + m_bKeyDown = KeyDown; + m_bModifier = bModifier; + m_pISelEnd = &nSelEnd; + m_pISelStart = &nSelStart; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); + m_pValue = &Value; + m_bWillCommit = bWillCommit; + m_pbRc = &bRc; + m_bFieldFull = bFieldFull; +} + +void CJS_EventHandler::OnField_Validate(WideString& strChange, + const WideString& strChangeEx, + bool bKeyDown, + bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + WideString& Value, + bool& bRc) { + Initial(JET_FIELD_VALIDATE); + + m_pWideStrChange = &strChange; + m_WideStrChangeEx = strChangeEx; + m_bKeyDown = bKeyDown; + m_bModifier = bModifier; + m_bShift = bShift; + m_strTargetName = pTarget->GetFullName(); + m_pValue = &Value; + m_pbRc = &bRc; +} + +void CJS_EventHandler::OnField_Calculate(CPDF_FormField* pSource, + CPDF_FormField* pTarget, + WideString& Value, + bool& bRc) { + Initial(JET_FIELD_CALCULATE); + + if (pSource) + m_strSourceName = pSource->GetFullName(); + m_strTargetName = pTarget->GetFullName(); + m_pValue = &Value; + m_pbRc = &bRc; +} + +void CJS_EventHandler::OnField_Format(CPDF_FormField* pTarget, + WideString& Value, + bool bWillCommit) { + Initial(JET_FIELD_FORMAT); + + m_nCommitKey = 0; + m_strTargetName = pTarget->GetFullName(); + m_pValue = &Value; + m_bWillCommit = bWillCommit; +} + +void CJS_EventHandler::OnScreen_Focus(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_FOCUS); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_Blur(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_BLUR); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_Open(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_OPEN); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_Close(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_CLOSE); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_MouseDown(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_MOUSEDOWN); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_MouseUp(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_MOUSEUP); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_MouseEnter(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_MOUSEENTER); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_MouseExit(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_MOUSEEXIT); + + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_InView(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_INVIEW); + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnScreen_OutView(bool bModifier, + bool bShift, + CPDFSDK_Annot* pScreen) { + Initial(JET_SCREEN_OUTVIEW); + m_bModifier = bModifier; + m_bShift = bShift; + m_pTargetAnnot.Reset(pScreen); +} + +void CJS_EventHandler::OnLink_MouseUp( + CPDFSDK_FormFillEnvironment* pTargetFormFillEnv) { + Initial(JET_LINK_MOUSEUP); + m_pTargetFormFillEnv.Reset(pTargetFormFillEnv); +} + +void CJS_EventHandler::OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) { + Initial(JET_BOOKMARK_MOUSEUP); + m_pTargetBookMark = pBookMark; +} + +void CJS_EventHandler::OnMenu_Exec( + CPDFSDK_FormFillEnvironment* pTargetFormFillEnv, + const WideString& strTargetName) { + Initial(JET_MENU_EXEC); + m_pTargetFormFillEnv.Reset(pTargetFormFillEnv); + m_strTargetName = strTargetName; +} + +void CJS_EventHandler::OnExternal_Exec() { + Initial(JET_EXTERNAL_EXEC); +} + +void CJS_EventHandler::OnBatchExec( + CPDFSDK_FormFillEnvironment* pTargetFormFillEnv) { + Initial(JET_BATCH_EXEC); + m_pTargetFormFillEnv.Reset(pTargetFormFillEnv); +} + +void CJS_EventHandler::OnConsole_Exec() { + Initial(JET_CONSOLE_EXEC); +} + +void CJS_EventHandler::Initial(JS_EVENT_T type) { + m_eEventType = type; + + m_strTargetName = L""; + m_strSourceName = L""; + m_pWideStrChange = nullptr; + m_WideStrChangeDu = L""; + m_WideStrChangeEx = L""; + m_nCommitKey = -1; + m_bKeyDown = false; + m_bModifier = false; + m_bShift = false; + m_pISelEnd = nullptr; + m_nSelEndDu = 0; + m_pISelStart = nullptr; + m_nSelStartDu = 0; + m_bWillCommit = false; + m_pValue = nullptr; + m_bFieldFull = false; + m_pbRc = nullptr; + m_bRcDu = false; + + m_pTargetBookMark = nullptr; + m_pTargetFormFillEnv.Reset(); + m_pTargetAnnot.Reset(); + + m_bValid = true; +} + +void CJS_EventHandler::Destroy() { + m_bValid = false; +} + +bool CJS_EventHandler::IsValid() const { + return m_bValid; +} + +WideString& CJS_EventHandler::Change() { + if (m_pWideStrChange) { + return *m_pWideStrChange; + } + return m_WideStrChangeDu; +} + +const WideString& CJS_EventHandler::ChangeEx() { + return m_WideStrChangeEx; +} + +int CJS_EventHandler::CommitKey() const { + return m_nCommitKey; +} + +bool CJS_EventHandler::FieldFull() const { + return m_bFieldFull; +} + +bool CJS_EventHandler::KeyDown() const { + return m_bKeyDown; +} + +bool CJS_EventHandler::Modifier() const { + return m_bModifier; +} + +const wchar_t* CJS_EventHandler::Name() const { + switch (m_eEventType) { + case JET_APP_INIT: + return L"Init"; + case JET_BATCH_EXEC: + return L"Exec"; + case JET_BOOKMARK_MOUSEUP: + return L"Mouse Up"; + case JET_CONSOLE_EXEC: + return L"Exec"; + case JET_DOC_DIDPRINT: + return L"DidPrint"; + case JET_DOC_DIDSAVE: + return L"DidSave"; + case JET_DOC_OPEN: + return L"Open"; + case JET_DOC_WILLCLOSE: + return L"WillClose"; + case JET_DOC_WILLPRINT: + return L"WillPrint"; + case JET_DOC_WILLSAVE: + return L"WillSave"; + case JET_EXTERNAL_EXEC: + return L"Exec"; + case JET_FIELD_FOCUS: + case JET_SCREEN_FOCUS: + return L"Focus"; + case JET_FIELD_BLUR: + case JET_SCREEN_BLUR: + return L"Blur"; + case JET_FIELD_MOUSEDOWN: + case JET_SCREEN_MOUSEDOWN: + return L"Mouse Down"; + case JET_FIELD_MOUSEUP: + case JET_SCREEN_MOUSEUP: + return L"Mouse Up"; + case JET_FIELD_MOUSEENTER: + case JET_SCREEN_MOUSEENTER: + return L"Mouse Enter"; + case JET_FIELD_MOUSEEXIT: + case JET_SCREEN_MOUSEEXIT: + return L"Mouse Exit"; + case JET_FIELD_CALCULATE: + return L"Calculate"; + case JET_FIELD_FORMAT: + return L"Format"; + case JET_FIELD_KEYSTROKE: + return L"Keystroke"; + case JET_FIELD_VALIDATE: + return L"Validate"; + case JET_LINK_MOUSEUP: + return L"Mouse Up"; + case JET_MENU_EXEC: + return L"Exec"; + case JET_PAGE_OPEN: + case JET_SCREEN_OPEN: + return L"Open"; + case JET_PAGE_CLOSE: + case JET_SCREEN_CLOSE: + return L"Close"; + case JET_SCREEN_INVIEW: + case JET_PAGE_INVIEW: + return L"InView"; + case JET_PAGE_OUTVIEW: + case JET_SCREEN_OUTVIEW: + return L"OutView"; + default: + return L""; + } +} + +const wchar_t* CJS_EventHandler::Type() const { + switch (m_eEventType) { + case JET_APP_INIT: + return L"App"; + case JET_BATCH_EXEC: + return L"Batch"; + case JET_BOOKMARK_MOUSEUP: + return L"BookMark"; + case JET_CONSOLE_EXEC: + return L"Console"; + case JET_DOC_DIDPRINT: + case JET_DOC_DIDSAVE: + case JET_DOC_OPEN: + case JET_DOC_WILLCLOSE: + case JET_DOC_WILLPRINT: + case JET_DOC_WILLSAVE: + return L"Doc"; + case JET_EXTERNAL_EXEC: + return L"External"; + case JET_FIELD_BLUR: + case JET_FIELD_FOCUS: + case JET_FIELD_MOUSEDOWN: + case JET_FIELD_MOUSEENTER: + case JET_FIELD_MOUSEEXIT: + case JET_FIELD_MOUSEUP: + case JET_FIELD_CALCULATE: + case JET_FIELD_FORMAT: + case JET_FIELD_KEYSTROKE: + case JET_FIELD_VALIDATE: + return L"Field"; + case JET_SCREEN_FOCUS: + case JET_SCREEN_BLUR: + case JET_SCREEN_OPEN: + case JET_SCREEN_CLOSE: + case JET_SCREEN_MOUSEDOWN: + case JET_SCREEN_MOUSEUP: + case JET_SCREEN_MOUSEENTER: + case JET_SCREEN_MOUSEEXIT: + case JET_SCREEN_INVIEW: + case JET_SCREEN_OUTVIEW: + return L"Screen"; + case JET_LINK_MOUSEUP: + return L"Link"; + case JET_MENU_EXEC: + return L"Menu"; + case JET_PAGE_OPEN: + case JET_PAGE_CLOSE: + case JET_PAGE_INVIEW: + case JET_PAGE_OUTVIEW: + return L"Page"; + default: + return L""; + } +} + +bool& CJS_EventHandler::Rc() { + return m_pbRc ? *m_pbRc : m_bRcDu; +} + +int CJS_EventHandler::SelEnd() const { + return m_pISelEnd ? *m_pISelEnd : m_nSelEndDu; +} + +int CJS_EventHandler::SelStart() const { + return m_pISelStart ? *m_pISelStart : m_nSelStartDu; +} + +void CJS_EventHandler::SetSelEnd(int value) { + int& target = m_pISelEnd ? *m_pISelEnd : m_nSelEndDu; + target = value; +} + +void CJS_EventHandler::SetSelStart(int value) { + int& target = m_pISelStart ? *m_pISelStart : m_nSelStartDu; + target = value; +} + +bool CJS_EventHandler::Shift() const { + return m_bShift; +} + +Field* CJS_EventHandler::Source() { + CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime(); + v8::Local pDocObj = + pRuntime->NewFxDynamicObj(CJS_Document::GetObjDefnID()); + if (pDocObj.IsEmpty()) + return nullptr; + + v8::Local pFieldObj = + pRuntime->NewFxDynamicObj(CJS_Field::GetObjDefnID()); + if (pFieldObj.IsEmpty()) + return nullptr; + + CJS_Document* pJSDocument = + static_cast(pRuntime->GetObjectPrivate(pDocObj)); + CJS_Field* pJSField = + static_cast(pRuntime->GetObjectPrivate(pFieldObj)); + + Document* pDocument = static_cast(pJSDocument->GetEmbedObject()); + pDocument->SetFormFillEnv(m_pTargetFormFillEnv + ? m_pTargetFormFillEnv.Get() + : m_pJSEventContext->GetFormFillEnv()); + + Field* pField = static_cast(pJSField->GetEmbedObject()); + pField->AttachField(pDocument, m_strSourceName); + return pField; +} + +Field* CJS_EventHandler::Target_Field() { + CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime(); + v8::Local pDocObj = + pRuntime->NewFxDynamicObj(CJS_Document::GetObjDefnID()); + if (pDocObj.IsEmpty()) + return nullptr; + + v8::Local pFieldObj = + pRuntime->NewFxDynamicObj(CJS_Field::GetObjDefnID()); + if (pFieldObj.IsEmpty()) + return nullptr; + + CJS_Document* pJSDocument = + static_cast(pRuntime->GetObjectPrivate(pDocObj)); + CJS_Field* pJSField = + static_cast(pRuntime->GetObjectPrivate(pFieldObj)); + + Document* pDocument = static_cast(pJSDocument->GetEmbedObject()); + pDocument->SetFormFillEnv(m_pTargetFormFillEnv + ? m_pTargetFormFillEnv.Get() + : m_pJSEventContext->GetFormFillEnv()); + + Field* pField = static_cast(pJSField->GetEmbedObject()); + pField->AttachField(pDocument, m_strTargetName); + return pField; +} + +WideString& CJS_EventHandler::Value() { + return *m_pValue; +} + +bool CJS_EventHandler::WillCommit() const { + return m_bWillCommit; +} + +const WideString& CJS_EventHandler::TargetName() const { + return m_strTargetName; +} diff --git a/fxjs/cjs_eventhandler.h b/fxjs/cjs_eventhandler.h new file mode 100644 index 0000000000000000000000000000000000000000..87ce1dcca0a6878f5bfa78f588ec8dd37b761f90 --- /dev/null +++ b/fxjs/cjs_eventhandler.h @@ -0,0 +1,197 @@ +// 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 FXJS_CJS_EVENTHANDLER_H_ +#define FXJS_CJS_EVENTHANDLER_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" + +class CJS_EventContext; +class CPDFSDK_Annot; +class CPDF_Bookmark; +class CPDF_FormField; +class Field; + +enum JS_EVENT_T { + JET_UNKNOWN, + JET_APP_INIT, + JET_DOC_OPEN, + JET_DOC_WILLPRINT, + JET_DOC_DIDPRINT, + JET_DOC_WILLSAVE, + JET_DOC_DIDSAVE, + JET_DOC_WILLCLOSE, + JET_PAGE_OPEN, + JET_PAGE_CLOSE, + JET_PAGE_INVIEW, + JET_PAGE_OUTVIEW, + JET_FIELD_MOUSEDOWN, + JET_FIELD_MOUSEUP, + JET_FIELD_MOUSEENTER, + JET_FIELD_MOUSEEXIT, + JET_FIELD_FOCUS, + JET_FIELD_BLUR, + JET_FIELD_KEYSTROKE, + JET_FIELD_VALIDATE, + JET_FIELD_CALCULATE, + JET_FIELD_FORMAT, + JET_SCREEN_FOCUS, + JET_SCREEN_BLUR, + JET_SCREEN_OPEN, + JET_SCREEN_CLOSE, + JET_SCREEN_MOUSEDOWN, + JET_SCREEN_MOUSEUP, + JET_SCREEN_MOUSEENTER, + JET_SCREEN_MOUSEEXIT, + JET_SCREEN_INVIEW, + JET_SCREEN_OUTVIEW, + JET_BATCH_EXEC, + JET_MENU_EXEC, + JET_CONSOLE_EXEC, + JET_EXTERNAL_EXEC, + JET_BOOKMARK_MOUSEUP, + JET_LINK_MOUSEUP +}; + +class CJS_EventHandler { + public: + explicit CJS_EventHandler(CJS_EventContext* pContext); + virtual ~CJS_EventHandler(); + + void OnApp_Init(); + + void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& strTargetName); + void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv); + + void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv); + + void OnField_Calculate(CPDF_FormField* pSource, + CPDF_FormField* pTarget, + WideString& Value, + bool& bRc); + void OnField_Format(CPDF_FormField* pTarget, + WideString& Value, + bool bWillCommit); + void OnField_Keystroke(WideString& strChange, + const WideString& strChangeEx, + bool KeyDown, + bool bModifier, + int& nSelEnd, + int& nSelStart, + bool bShift, + CPDF_FormField* pTarget, + WideString& Value, + bool bWillCommit, + bool bFieldFull, + bool& bRc); + void OnField_Validate(WideString& strChange, + const WideString& strChangeEx, + bool bKeyDown, + bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + WideString& Value, + bool& bRc); + + void OnField_MouseDown(bool bModifier, bool bShift, CPDF_FormField* pTarget); + void OnField_MouseEnter(bool bModifier, bool bShift, CPDF_FormField* pTarget); + void OnField_MouseExit(bool bModifier, bool bShift, CPDF_FormField* pTarget); + void OnField_MouseUp(bool bModifier, bool bShift, CPDF_FormField* pTarget); + void OnField_Blur(bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + const WideString& Value); + void OnField_Focus(bool bModifier, + bool bShift, + CPDF_FormField* pTarget, + const WideString& Value); + + void OnScreen_Focus(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_Blur(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_Open(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_Close(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_MouseDown(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_MouseUp(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_MouseEnter(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_MouseExit(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_InView(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + void OnScreen_OutView(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen); + + void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark); + void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv); + + void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& strTargetName); + void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv); + void OnConsole_Exec(); + void OnExternal_Exec(); + + void Initial(JS_EVENT_T type); + void Destroy(); + bool IsValid() const; + + WideString& Change(); + const WideString& ChangeEx(); + int CommitKey() const; + bool FieldFull() const; + bool KeyDown() const; + bool Modifier() const; + const wchar_t* Name() const; + const wchar_t* Type() const; + bool& Rc(); + int SelEnd() const; + int SelStart() const; + void SetSelEnd(int value); + void SetSelStart(int value); + bool Shift() const; + Field* Source(); + Field* Target_Field(); + WideString& Value(); + bool WillCommit() const; + const WideString& TargetName() const; + + JS_EVENT_T EventType() const { return m_eEventType; } + + UnownedPtr const m_pJSEventContext; + JS_EVENT_T m_eEventType; + bool m_bValid; + + WideString m_strTargetName; + WideString m_strSourceName; + UnownedPtr m_pWideStrChange; + WideString m_WideStrChangeDu; + WideString m_WideStrChangeEx; + int m_nCommitKey; + bool m_bKeyDown; + bool m_bModifier; + bool m_bShift; + int* m_pISelEnd; + int m_nSelEndDu; + int* m_pISelStart; + int m_nSelStartDu; + bool m_bWillCommit; + UnownedPtr m_pValue; + bool m_bFieldFull; + bool* m_pbRc; + bool m_bRcDu; + + UnownedPtr m_pTargetBookMark; + CPDFSDK_FormFillEnvironment::ObservedPtr m_pTargetFormFillEnv; + CPDFSDK_Annot::ObservedPtr m_pTargetAnnot; +}; + +#endif // FXJS_CJS_EVENTHANDLER_H_ diff --git a/fxjs/cjs_field.cpp b/fxjs/cjs_field.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f06be0091faf1013df42526c696a8f5f8b73b0c --- /dev/null +++ b/fxjs/cjs_field.cpp @@ -0,0 +1,2673 @@ +// 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 "fxjs/cjs_field.h" + +#include +#include + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfdoc/cpdf_formfield.h" +#include "core/fpdfdoc/cpdf_interform.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fpdfsdk/cpdfsdk_pageview.h" +#include "fpdfsdk/cpdfsdk_widget.h" +#include "fxjs/cjs_color.h" +#include "fxjs/cjs_delaydata.h" +#include "fxjs/cjs_document.h" +#include "fxjs/cjs_icon.h" +#include "fxjs/js_resources.h" + +namespace { + +bool SetWidgetDisplayStatus(CPDFSDK_Widget* pWidget, int value) { + if (!pWidget) + return false; + + uint32_t dwFlag = pWidget->GetFlags(); + switch (value) { + case 0: + dwFlag &= ~ANNOTFLAG_INVISIBLE; + dwFlag &= ~ANNOTFLAG_HIDDEN; + dwFlag &= ~ANNOTFLAG_NOVIEW; + dwFlag |= ANNOTFLAG_PRINT; + break; + case 1: + dwFlag &= ~ANNOTFLAG_INVISIBLE; + dwFlag &= ~ANNOTFLAG_NOVIEW; + dwFlag |= (ANNOTFLAG_HIDDEN | ANNOTFLAG_PRINT); + break; + case 2: + dwFlag &= ~ANNOTFLAG_INVISIBLE; + dwFlag &= ~ANNOTFLAG_PRINT; + dwFlag &= ~ANNOTFLAG_HIDDEN; + dwFlag &= ~ANNOTFLAG_NOVIEW; + break; + case 3: + dwFlag |= ANNOTFLAG_NOVIEW; + dwFlag |= ANNOTFLAG_PRINT; + dwFlag &= ~ANNOTFLAG_HIDDEN; + break; + } + + if (dwFlag != pWidget->GetFlags()) { + pWidget->SetFlags(dwFlag); + return true; + } + + return false; +} + +} // namespace + +const JSPropertySpec CJS_Field::PropertySpecs[] = { + {"alignment", get_alignment_static, set_alignment_static}, + {"borderStyle", get_border_style_static, set_border_style_static}, + {"buttonAlignX", get_button_align_x_static, set_button_align_x_static}, + {"buttonAlignY", get_button_align_y_static, set_button_align_y_static}, + {"buttonFitBounds", get_button_fit_bounds_static, + set_button_fit_bounds_static}, + {"buttonPosition", get_button_position_static, set_button_position_static}, + {"buttonScaleHow", get_button_scale_how_static, + set_button_scale_how_static}, + {"buttonScaleWhen", get_button_scale_when_static, + set_button_scale_when_static}, + {"calcOrderIndex", get_calc_order_index_static, + set_calc_order_index_static}, + {"charLimit", get_char_limit_static, set_char_limit_static}, + {"comb", get_comb_static, set_comb_static}, + {"commitOnSelChange", get_commit_on_sel_change_static, + set_commit_on_sel_change_static}, + {"currentValueIndices", get_current_value_indices_static, + set_current_value_indices_static}, + {"defaultStyle", get_default_style_static, set_default_style_static}, + {"defaultValue", get_default_value_static, set_default_value_static}, + {"doNotScroll", get_do_not_scroll_static, set_do_not_scroll_static}, + {"doNotSpellCheck", get_do_not_spell_check_static, + set_do_not_spell_check_static}, + {"delay", get_delay_static, set_delay_static}, + {"display", get_display_static, set_display_static}, + {"doc", get_doc_static, set_doc_static}, + {"editable", get_editable_static, set_editable_static}, + {"exportValues", get_export_values_static, set_export_values_static}, + {"hidden", get_hidden_static, set_hidden_static}, + {"fileSelect", get_file_select_static, set_file_select_static}, + {"fillColor", get_fill_color_static, set_fill_color_static}, + {"lineWidth", get_line_width_static, set_line_width_static}, + {"highlight", get_highlight_static, set_highlight_static}, + {"multiline", get_multiline_static, set_multiline_static}, + {"multipleSelection", get_multiple_selection_static, + set_multiple_selection_static}, + {"name", get_name_static, set_name_static}, + {"numItems", get_num_items_static, set_num_items_static}, + {"page", get_page_static, set_page_static}, + {"password", get_password_static, set_password_static}, + {"print", get_print_static, set_print_static}, + {"radiosInUnison", get_radios_in_unison_static, + set_radios_in_unison_static}, + {"readonly", get_readonly_static, set_readonly_static}, + {"rect", get_rect_static, set_rect_static}, + {"required", get_required_static, set_required_static}, + {"richText", get_rich_text_static, set_rich_text_static}, + {"richValue", get_rich_value_static, set_rich_value_static}, + {"rotation", get_rotation_static, set_rotation_static}, + {"strokeColor", get_stroke_color_static, set_stroke_color_static}, + {"style", get_style_static, set_style_static}, + {"submitName", get_submit_name_static, set_submit_name_static}, + {"textColor", get_text_color_static, set_text_color_static}, + {"textFont", get_text_font_static, set_text_font_static}, + {"textSize", get_text_size_static, set_text_size_static}, + {"type", get_type_static, set_type_static}, + {"userName", get_user_name_static, set_user_name_static}, + {"value", get_value_static, set_value_static}, + {"valueAsString", get_value_as_string_static, set_value_as_string_static}, + {"source", get_source_static, set_source_static}}; + +const JSMethodSpec CJS_Field::MethodSpecs[] = { + {"browseForFileToSubmit", browseForFileToSubmit_static}, + {"buttonGetCaption", buttonGetCaption_static}, + {"buttonGetIcon", buttonGetIcon_static}, + {"buttonImportIcon", buttonImportIcon_static}, + {"buttonSetCaption", buttonSetCaption_static}, + {"buttonSetIcon", buttonSetIcon_static}, + {"checkThisBox", checkThisBox_static}, + {"clearItems", clearItems_static}, + {"defaultIsChecked", defaultIsChecked_static}, + {"deleteItemAt", deleteItemAt_static}, + {"getArray", getArray_static}, + {"getItemAt", getItemAt_static}, + {"getLock", getLock_static}, + {"insertItemAt", insertItemAt_static}, + {"isBoxChecked", isBoxChecked_static}, + {"isDefaultChecked", isDefaultChecked_static}, + {"setAction", setAction_static}, + {"setFocus", setFocus_static}, + {"setItems", setItems_static}, + {"setLock", setLock_static}, + {"signatureGetModifications", signatureGetModifications_static}, + {"signatureGetSeedValue", signatureGetSeedValue_static}, + {"signatureInfo", signatureInfo_static}, + {"signatureSetSeedValue", signatureSetSeedValue_static}, + {"signatureSign", signatureSign_static}, + {"signatureValidate", signatureValidate_static}}; + +int CJS_Field::ObjDefnID = -1; + +// static +int CJS_Field::GetObjDefnID() { + return ObjDefnID; +} + +// static +void CJS_Field::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("Field", FXJSOBJTYPE_DYNAMIC, + JSConstructor, + JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +void CJS_Field::InitInstance(IJS_Runtime* pIRuntime) {} + +Field::Field(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject), + m_pJSDoc(nullptr), + m_pFormFillEnv(nullptr), + m_nFormControlIndex(-1), + m_bCanSet(false), + m_bDelay(false) {} + +Field::~Field() {} + +// note: iControlNo = -1, means not a widget. +void Field::ParseFieldName(const std::wstring& strFieldNameParsed, + std::wstring& strFieldName, + int& iControlNo) { + int iStart = strFieldNameParsed.find_last_of(L'.'); + if (iStart == -1) { + strFieldName = strFieldNameParsed; + iControlNo = -1; + return; + } + std::wstring suffixal = strFieldNameParsed.substr(iStart + 1); + iControlNo = FXSYS_wtoi(suffixal.c_str()); + if (iControlNo == 0) { + int iSpaceStart; + while ((iSpaceStart = suffixal.find_last_of(L" ")) != -1) { + suffixal.erase(iSpaceStart, 1); + } + + if (suffixal.compare(L"0") != 0) { + strFieldName = strFieldNameParsed; + iControlNo = -1; + return; + } + } + strFieldName = strFieldNameParsed.substr(0, iStart); +} + +bool Field::AttachField(Document* pDocument, const WideString& csFieldName) { + m_pJSDoc = pDocument; + m_pFormFillEnv.Reset(pDocument->GetFormFillEnv()); + m_bCanSet = m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM) || + m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) || + m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY); + + CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm(); + WideString swFieldNameTemp = csFieldName; + swFieldNameTemp.Replace(L"..", L"."); + + if (pInterForm->CountFields(swFieldNameTemp) <= 0) { + std::wstring strFieldName; + int iControlNo = -1; + ParseFieldName(swFieldNameTemp.c_str(), strFieldName, iControlNo); + if (iControlNo == -1) + return false; + + m_FieldName = strFieldName.c_str(); + m_nFormControlIndex = iControlNo; + return true; + } + + m_FieldName = swFieldNameTemp; + m_nFormControlIndex = -1; + + return true; +} + +std::vector Field::GetFormFields( + CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& csFieldName) { + std::vector fields; + CPDFSDK_InterForm* pReaderInterForm = pFormFillEnv->GetInterForm(); + CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm(); + for (int i = 0, sz = pInterForm->CountFields(csFieldName); i < sz; ++i) { + if (CPDF_FormField* pFormField = pInterForm->GetField(i, csFieldName)) + fields.push_back(pFormField); + } + return fields; +} + +std::vector Field::GetFormFields( + const WideString& csFieldName) const { + return Field::GetFormFields(m_pFormFillEnv.Get(), csFieldName); +} + +void Field::UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDF_FormField* pFormField, + bool bChangeMark, + bool bResetAP, + bool bRefresh) { + CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); + + if (bResetAP) { + std::vector widgets; + pInterForm->GetWidgets(pFormField, &widgets); + + FormFieldType fieldType = pFormField->GetFieldType(); + if (fieldType == FormFieldType::kComboBox || + fieldType == FormFieldType::kTextField) { + for (auto& pObserved : widgets) { + if (pObserved) { + bool bFormatted = false; + WideString sValue = static_cast(pObserved.Get()) + ->OnFormat(bFormatted); + if (pObserved) { // Not redundant, may be clobbered by OnFormat. + static_cast(pObserved.Get()) + ->ResetAppearance(bFormatted ? &sValue : nullptr, false); + } + } + } + } else { + for (auto& pObserved : widgets) { + if (pObserved) { + static_cast(pObserved.Get()) + ->ResetAppearance(nullptr, false); + } + } + } + } + + if (bRefresh) { + // Refresh the widget list. The calls in |bResetAP| may have caused widgets + // to be removed from the list. We need to call |GetWidgets| again to be + // sure none of the widgets have been deleted. + std::vector widgets; + pInterForm->GetWidgets(pFormField, &widgets); + + // TODO(dsinclair): Determine if all widgets share the same + // CPDFSDK_InterForm. If that's the case, we can move the code to + // |GetFormFillEnv| out of the loop. + for (auto& pObserved : widgets) { + if (pObserved) { + CPDFSDK_Widget* pWidget = static_cast(pObserved.Get()); + pWidget->GetInterForm()->GetFormFillEnv()->UpdateAllViews(nullptr, + pWidget); + } + } + } + + if (bChangeMark) + pFormFillEnv->SetChangeMark(); +} + +void Field::UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDF_FormControl* pFormControl, + bool bChangeMark, + bool bResetAP, + bool bRefresh) { + ASSERT(pFormControl); + + CPDFSDK_InterForm* pForm = pFormFillEnv->GetInterForm(); + CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl); + + if (pWidget) { + CPDFSDK_Widget::ObservedPtr observed_widget(pWidget); + if (bResetAP) { + FormFieldType fieldType = pWidget->GetFieldType(); + if (fieldType == FormFieldType::kComboBox || + fieldType == FormFieldType::kTextField) { + bool bFormatted = false; + WideString sValue = pWidget->OnFormat(bFormatted); + if (!observed_widget) + return; + pWidget->ResetAppearance(bFormatted ? &sValue : nullptr, false); + } else { + pWidget->ResetAppearance(nullptr, false); + } + if (!observed_widget) + return; + } + + if (bRefresh) { + CPDFSDK_InterForm* pInterForm = pWidget->GetInterForm(); + pInterForm->GetFormFillEnv()->UpdateAllViews(nullptr, pWidget); + } + } + + if (bChangeMark) + pFormFillEnv->SetChangeMark(); +} + +CPDFSDK_Widget* Field::GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDF_FormControl* pFormControl) { + CPDFSDK_InterForm* pInterForm = + static_cast(pFormFillEnv->GetInterForm()); + return pInterForm ? pInterForm->GetWidget(pFormControl) : nullptr; +} + +bool Field::ValueIsOccur(CPDF_FormField* pFormField, WideString csOptLabel) { + for (int i = 0, sz = pFormField->CountOptions(); i < sz; i++) { + if (csOptLabel.Compare(pFormField->GetOptionLabel(i)) == 0) + return true; + } + + return false; +} + +CPDF_FormControl* Field::GetSmartFieldControl(CPDF_FormField* pFormField) { + if (!pFormField->CountControls() || + m_nFormControlIndex >= pFormField->CountControls()) + return nullptr; + if (m_nFormControlIndex < 0) + return pFormField->GetControl(0); + return pFormField->GetControl(m_nFormControlIndex); +} + +CJS_Return Field::get_alignment(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + switch (pFormControl->GetControlAlignment()) { + case 0: + return CJS_Return(pRuntime->NewString(L"left")); + case 1: + return CJS_Return(pRuntime->NewString(L"center")); + case 2: + return CJS_Return(pRuntime->NewString(L"right")); + } + return CJS_Return(pRuntime->NewString(L"")); +} + +CJS_Return Field::set_alignment(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_border_style(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (!pFormField) + return CJS_Return(false); + + CPDFSDK_Widget* pWidget = + GetWidget(m_pFormFillEnv.Get(), GetSmartFieldControl(pFormField)); + if (!pWidget) + return CJS_Return(false); + + switch (pWidget->GetBorderStyle()) { + case BorderStyle::SOLID: + return CJS_Return(pRuntime->NewString(L"solid")); + case BorderStyle::DASH: + return CJS_Return(pRuntime->NewString(L"dashed")); + case BorderStyle::BEVELED: + return CJS_Return(pRuntime->NewString(L"beveled")); + case BorderStyle::INSET: + return CJS_Return(pRuntime->NewString(L"inset")); + case BorderStyle::UNDERLINE: + return CJS_Return(pRuntime->NewString(L"underline")); + } + return CJS_Return(pRuntime->NewString(L"")); +} + +CJS_Return Field::set_border_style(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + + if (!m_bCanSet) + return CJS_Return(false); + + ByteString byte_str = ByteString::FromUnicode(pRuntime->ToWideString(vp)); + if (m_bDelay) { + AddDelay_String(FP_BORDERSTYLE, byte_str); + } else { + Field::SetBorderStyle(m_pFormFillEnv.Get(), m_FieldName, + m_nFormControlIndex, byte_str); + } + return CJS_Return(true); +} + +void Field::SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const ByteString& string) { + ASSERT(pFormFillEnv); + + BorderStyle nBorderStyle = BorderStyle::SOLID; + if (string == "solid") + nBorderStyle = BorderStyle::SOLID; + else if (string == "beveled") + nBorderStyle = BorderStyle::BEVELED; + else if (string == "dashed") + nBorderStyle = BorderStyle::DASH; + else if (string == "inset") + nBorderStyle = BorderStyle::INSET; + else if (string == "underline") + nBorderStyle = BorderStyle::UNDERLINE; + else + return; + + std::vector FieldArray = + GetFormFields(pFormFillEnv, swFieldName); + for (CPDF_FormField* pFormField : FieldArray) { + if (nControlIndex < 0) { + bool bSet = false; + for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { + if (CPDFSDK_Widget* pWidget = + GetWidget(pFormFillEnv, pFormField->GetControl(i))) { + if (pWidget->GetBorderStyle() != nBorderStyle) { + pWidget->SetBorderStyle(nBorderStyle); + bSet = true; + } + } + } + if (bSet) + UpdateFormField(pFormFillEnv, pFormField, true, true, true); + } else { + if (nControlIndex >= pFormField->CountControls()) + return; + if (CPDF_FormControl* pFormControl = + pFormField->GetControl(nControlIndex)) { + if (CPDFSDK_Widget* pWidget = GetWidget(pFormFillEnv, pFormControl)) { + if (pWidget->GetBorderStyle() != nBorderStyle) { + pWidget->SetBorderStyle(nBorderStyle); + UpdateFormControl(pFormFillEnv, pFormControl, true, true, true); + } + } + } + } + } +} + +CJS_Return Field::get_button_align_x(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + CPDF_IconFit IconFit = pFormControl->GetIconFit(); + + float fLeft; + float fBottom; + IconFit.GetIconPosition(fLeft, fBottom); + + return CJS_Return(pRuntime->NewNumber(static_cast(fLeft))); +} + +CJS_Return Field::set_button_align_x(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_button_align_y(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + CPDF_IconFit IconFit = pFormControl->GetIconFit(); + + float fLeft; + float fBottom; + IconFit.GetIconPosition(fLeft, fBottom); + + return CJS_Return(pRuntime->NewNumber(static_cast(fBottom))); +} + +CJS_Return Field::set_button_align_y(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_button_fit_bounds(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + return CJS_Return( + pRuntime->NewBoolean(pFormControl->GetIconFit().GetFittingBounds())); +} + +CJS_Return Field::set_button_fit_bounds(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_button_position(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewNumber(pFormControl->GetTextPosition())); +} + +CJS_Return Field::set_button_position(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_button_scale_how(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + pFormControl->GetIconFit().IsProportionalScale() ? 0 : 1)); +} + +CJS_Return Field::set_button_scale_how(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_button_scale_when(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + CPDF_IconFit IconFit = pFormControl->GetIconFit(); + int ScaleM = IconFit.GetScaleMethod(); + switch (ScaleM) { + case CPDF_IconFit::Always: + return CJS_Return( + pRuntime->NewNumber(static_cast(CPDF_IconFit::Always))); + case CPDF_IconFit::Bigger: + return CJS_Return( + pRuntime->NewNumber(static_cast(CPDF_IconFit::Bigger))); + case CPDF_IconFit::Never: + return CJS_Return( + pRuntime->NewNumber(static_cast(CPDF_IconFit::Never))); + case CPDF_IconFit::Smaller: + return CJS_Return( + pRuntime->NewNumber(static_cast(CPDF_IconFit::Smaller))); + } + return CJS_Return(true); +} + +CJS_Return Field::set_button_scale_when(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_calc_order_index(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kComboBox && + pFormField->GetFieldType() != FormFieldType::kTextField) { + return CJS_Return(false); + } + + CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm(); + CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm(); + return CJS_Return(pRuntime->NewNumber(static_cast( + pInterForm->FindFieldInCalculationOrder(pFormField)))); +} + +CJS_Return Field::set_calc_order_index(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_char_limit(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + return CJS_Return( + pRuntime->NewNumber(static_cast(pFormField->GetMaxLen()))); +} + +CJS_Return Field::set_char_limit(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_comb(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + return CJS_Return( + pRuntime->NewBoolean(!!(pFormField->GetFieldFlags() & FIELDFLAG_COMB))); +} + +CJS_Return Field::set_comb(CJS_Runtime* pRuntime, v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_commit_on_sel_change(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kComboBox && + pFormField->GetFieldType() != FormFieldType::kListBox) { + return CJS_Return(false); + } + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_COMMITONSELCHANGE))); +} + +CJS_Return Field::set_commit_on_sel_change(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_current_value_indices(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kComboBox && + pFormField->GetFieldType() != FormFieldType::kListBox) { + return CJS_Return(false); + } + + int count = pFormField->CountSelectedItems(); + if (count <= 0) + return CJS_Return(pRuntime->NewNumber(-1)); + if (count == 1) + return CJS_Return(pRuntime->NewNumber(pFormField->GetSelectedIndex(0))); + + v8::Local SelArray = pRuntime->NewArray(); + for (int i = 0; i < count; i++) { + pRuntime->PutArrayElement( + SelArray, i, pRuntime->NewNumber(pFormField->GetSelectedIndex(i))); + } + if (SelArray.IsEmpty()) + return CJS_Return(pRuntime->NewArray()); + return CJS_Return(SelArray); +} + +CJS_Return Field::set_current_value_indices(CJS_Runtime* pRuntime, + v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + + std::vector array; + if (vp->IsNumber()) { + array.push_back(pRuntime->ToInt32(vp)); + } else if (!vp.IsEmpty() && vp->IsArray()) { + v8::Local SelArray = pRuntime->ToArray(vp); + for (size_t i = 0; i < pRuntime->GetArrayLength(SelArray); i++) { + array.push_back( + pRuntime->ToInt32(pRuntime->GetArrayElement(SelArray, i))); + } + } + + if (m_bDelay) { + AddDelay_WordArray(FP_CURRENTVALUEINDICES, array); + } else { + Field::SetCurrentValueIndices(m_pFormFillEnv.Get(), m_FieldName, + m_nFormControlIndex, array); + } + return CJS_Return(true); +} + +void Field::SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const std::vector& array) { + ASSERT(pFormFillEnv); + std::vector FieldArray = + GetFormFields(pFormFillEnv, swFieldName); + + for (CPDF_FormField* pFormField : FieldArray) { + FormFieldType fieldType = pFormField->GetFieldType(); + if (fieldType == FormFieldType::kComboBox || + fieldType == FormFieldType::kListBox) { + uint32_t dwFieldFlags = pFormField->GetFieldFlags(); + pFormField->ClearSelection(true); + for (size_t i = 0; i < array.size(); ++i) { + if (i != 0 && !(dwFieldFlags & (1 << 21))) + break; + if (array[i] < static_cast(pFormField->CountOptions()) && + !pFormField->IsItemSelected(array[i])) { + pFormField->SetItemSelection(array[i], true); + } + } + UpdateFormField(pFormFillEnv, pFormField, true, true, true); + } + } +} + +CJS_Return Field::get_default_style(CJS_Runtime* pRuntime) { + return CJS_Return(false); +} + +CJS_Return Field::set_default_style(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return Field::get_default_value(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() == FormFieldType::kPushButton || + pFormField->GetFieldType() == FormFieldType::kSignature) { + return CJS_Return(false); + } + + return CJS_Return(pRuntime->NewString(pFormField->GetDefaultValue().c_str())); +} + +CJS_Return Field::set_default_value(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_do_not_scroll(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_DONOTSCROLL))); +} + +CJS_Return Field::set_do_not_scroll(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_do_not_spell_check(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField && + pFormField->GetFieldType() != FormFieldType::kComboBox) { + return CJS_Return(false); + } + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_DONOTSPELLCHECK))); +} + +CJS_Return Field::set_do_not_spell_check(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +void Field::SetDelay(bool bDelay) { + m_bDelay = bDelay; + + if (m_bDelay) + return; + if (m_pJSDoc) + m_pJSDoc->DoFieldDelay(m_FieldName, m_nFormControlIndex); +} + +CJS_Return Field::get_delay(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewBoolean(m_bDelay)); +} + +CJS_Return Field::set_delay(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + + SetDelay(pRuntime->ToBoolean(vp)); + return CJS_Return(true); +} + +CJS_Return Field::get_display(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + ASSERT(pFormField); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDFSDK_Widget* pWidget = + pInterForm->GetWidget(GetSmartFieldControl(pFormField)); + if (!pWidget) + return CJS_Return(false); + + uint32_t dwFlag = pWidget->GetFlags(); + if (ANNOTFLAG_INVISIBLE & dwFlag || ANNOTFLAG_HIDDEN & dwFlag) + return CJS_Return(pRuntime->NewNumber(1)); + + if (ANNOTFLAG_PRINT & dwFlag) { + if (ANNOTFLAG_NOVIEW & dwFlag) + return CJS_Return(pRuntime->NewNumber(3)); + return CJS_Return(pRuntime->NewNumber(0)); + } + return CJS_Return(pRuntime->NewNumber(2)); +} + +CJS_Return Field::set_display(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + + if (m_bDelay) { + AddDelay_Int(FP_DISPLAY, pRuntime->ToInt32(vp)); + } else { + Field::SetDisplay(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, + pRuntime->ToInt32(vp)); + } + return CJS_Return(true); +} + +void Field::SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + int number) { + CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); + std::vector FieldArray = + GetFormFields(pFormFillEnv, swFieldName); + for (CPDF_FormField* pFormField : FieldArray) { + if (nControlIndex < 0) { + bool bAnySet = false; + for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { + CPDF_FormControl* pFormControl = pFormField->GetControl(i); + ASSERT(pFormControl); + + CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl); + if (SetWidgetDisplayStatus(pWidget, number)) + bAnySet = true; + } + + if (bAnySet) + UpdateFormField(pFormFillEnv, pFormField, true, false, true); + } else { + if (nControlIndex >= pFormField->CountControls()) + return; + + CPDF_FormControl* pFormControl = pFormField->GetControl(nControlIndex); + if (!pFormControl) + return; + + CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl); + if (SetWidgetDisplayStatus(pWidget, number)) + UpdateFormControl(pFormFillEnv, pFormControl, true, false, true); + } + } +} + +CJS_Return Field::get_doc(CJS_Runtime* pRuntime) { + return CJS_Return(m_pJSDoc->GetCJSDoc()->ToV8Object()); +} + +CJS_Return Field::set_doc(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return Field::get_editable(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kComboBox) + return CJS_Return(false); + + return CJS_Return( + pRuntime->NewBoolean(!!(pFormField->GetFieldFlags() & FIELDFLAG_EDIT))); +} + +CJS_Return Field::set_editable(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_export_values(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kCheckBox && + pFormField->GetFieldType() != FormFieldType::kRadioButton) { + return CJS_Return(false); + } + + v8::Local ExportValuesArray = pRuntime->NewArray(); + if (m_nFormControlIndex < 0) { + for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { + CPDF_FormControl* pFormControl = pFormField->GetControl(i); + pRuntime->PutArrayElement( + ExportValuesArray, i, + pRuntime->NewString(pFormControl->GetExportValue().c_str())); + } + } else { + if (m_nFormControlIndex >= pFormField->CountControls()) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = + pFormField->GetControl(m_nFormControlIndex); + if (!pFormControl) + return CJS_Return(false); + + pRuntime->PutArrayElement( + ExportValuesArray, 0, + pRuntime->NewString(pFormControl->GetExportValue().c_str())); + } + return CJS_Return(ExportValuesArray); +} + +CJS_Return Field::set_export_values(CJS_Runtime* pRuntime, + v8::Local vp) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kCheckBox && + pFormField->GetFieldType() != FormFieldType::kRadioButton) { + return CJS_Return(false); + } + + return CJS_Return(m_bCanSet && !vp.IsEmpty() && vp->IsArray()); +} + +CJS_Return Field::get_file_select(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT))); +} + +CJS_Return Field::set_file_select(CJS_Runtime* pRuntime, + v8::Local vp) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_fill_color(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + ASSERT(pFormField); + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + int iColorType; + pFormControl->GetBackgroundColor(iColorType); + + CFX_Color color; + if (iColorType == CFX_Color::kTransparent) { + color = CFX_Color(CFX_Color::kTransparent); + } else if (iColorType == CFX_Color::kGray) { + color = CFX_Color(CFX_Color::kGray, + pFormControl->GetOriginalBackgroundColor(0)); + } else if (iColorType == CFX_Color::kRGB) { + color = + CFX_Color(CFX_Color::kRGB, pFormControl->GetOriginalBackgroundColor(0), + pFormControl->GetOriginalBackgroundColor(1), + pFormControl->GetOriginalBackgroundColor(2)); + } else if (iColorType == CFX_Color::kCMYK) { + color = + CFX_Color(CFX_Color::kCMYK, pFormControl->GetOriginalBackgroundColor(0), + pFormControl->GetOriginalBackgroundColor(1), + pFormControl->GetOriginalBackgroundColor(2), + pFormControl->GetOriginalBackgroundColor(3)); + } else { + return CJS_Return(false); + } + + v8::Local array = color::ConvertPWLColorToArray(pRuntime, color); + if (array.IsEmpty()) + return CJS_Return(pRuntime->NewArray()); + return CJS_Return(array); +} + +CJS_Return Field::set_fill_color(CJS_Runtime* pRuntime, + v8::Local vp) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + if (!m_bCanSet) + return CJS_Return(false); + if (vp.IsEmpty() || !vp->IsArray()) + return CJS_Return(false); + return CJS_Return(true); +} + +CJS_Return Field::get_hidden(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + ASSERT(pFormField); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDFSDK_Widget* pWidget = + pInterForm->GetWidget(GetSmartFieldControl(pFormField)); + if (!pWidget) + return CJS_Return(false); + + uint32_t dwFlags = pWidget->GetFlags(); + return CJS_Return(pRuntime->NewBoolean(ANNOTFLAG_INVISIBLE & dwFlags || + ANNOTFLAG_HIDDEN & dwFlags)); +} + +CJS_Return Field::set_hidden(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + + if (m_bDelay) { + AddDelay_Bool(FP_HIDDEN, pRuntime->ToBoolean(vp)); + } else { + Field::SetHidden(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, + pRuntime->ToBoolean(vp)); + } + return CJS_Return(true); +} + +void Field::SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + bool b) { + int display = b ? 1 /*Hidden*/ : 0 /*Visible*/; + SetDisplay(pFormFillEnv, swFieldName, nControlIndex, display); +} + +CJS_Return Field::get_highlight(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + int eHM = pFormControl->GetHighlightingMode(); + switch (eHM) { + case CPDF_FormControl::None: + return CJS_Return(pRuntime->NewString(L"none")); + case CPDF_FormControl::Push: + return CJS_Return(pRuntime->NewString(L"push")); + case CPDF_FormControl::Invert: + return CJS_Return(pRuntime->NewString(L"invert")); + case CPDF_FormControl::Outline: + return CJS_Return(pRuntime->NewString(L"outline")); + case CPDF_FormControl::Toggle: + return CJS_Return(pRuntime->NewString(L"toggle")); + } + return CJS_Return(true); +} + +CJS_Return Field::set_highlight(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_line_width(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + ASSERT(pFormField); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + if (!pFormField->CountControls()) + return CJS_Return(false); + + CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormField->GetControl(0)); + if (!pWidget) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewNumber(pWidget->GetBorderWidth())); +} + +CJS_Return Field::set_line_width(CJS_Runtime* pRuntime, + v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + + if (m_bDelay) { + AddDelay_Int(FP_LINEWIDTH, pRuntime->ToInt32(vp)); + } else { + Field::SetLineWidth(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, + pRuntime->ToInt32(vp)); + } + return CJS_Return(true); +} + +void Field::SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + int number) { + CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); + std::vector FieldArray = + GetFormFields(pFormFillEnv, swFieldName); + for (CPDF_FormField* pFormField : FieldArray) { + if (nControlIndex < 0) { + bool bSet = false; + for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { + CPDF_FormControl* pFormControl = pFormField->GetControl(i); + ASSERT(pFormControl); + + if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { + if (number != pWidget->GetBorderWidth()) { + pWidget->SetBorderWidth(number); + bSet = true; + } + } + } + if (bSet) + UpdateFormField(pFormFillEnv, pFormField, true, true, true); + } else { + if (nControlIndex >= pFormField->CountControls()) + return; + if (CPDF_FormControl* pFormControl = + pFormField->GetControl(nControlIndex)) { + if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { + if (number != pWidget->GetBorderWidth()) { + pWidget->SetBorderWidth(number); + UpdateFormControl(pFormFillEnv, pFormControl, true, true, true); + } + } + } + } + } +} + +CJS_Return Field::get_multiline(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_MULTILINE))); +} + +CJS_Return Field::set_multiline(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_multiple_selection(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kListBox) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_MULTISELECT))); +} + +CJS_Return Field::set_multiple_selection(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_name(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewString(m_FieldName.c_str())); +} + +CJS_Return Field::set_name(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return Field::get_num_items(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kComboBox && + pFormField->GetFieldType() != FormFieldType::kListBox) { + return CJS_Return(false); + } + + return CJS_Return(pRuntime->NewNumber(pFormField->CountOptions())); +} + +CJS_Return Field::set_num_items(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return Field::get_page(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (!pFormField) + return CJS_Return(false); + + std::vector widgets; + m_pFormFillEnv->GetInterForm()->GetWidgets(pFormField, &widgets); + if (widgets.empty()) + return CJS_Return(pRuntime->NewNumber(-1)); + + v8::Local PageArray = pRuntime->NewArray(); + int i = 0; + for (const auto& pObserved : widgets) { + if (!pObserved) + return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError)); + + auto* pWidget = static_cast(pObserved.Get()); + CPDFSDK_PageView* pPageView = pWidget->GetPageView(); + if (!pPageView) + return CJS_Return(false); + + pRuntime->PutArrayElement( + PageArray, i, + pRuntime->NewNumber(static_cast(pPageView->GetPageIndex()))); + ++i; + } + return CJS_Return(PageArray); +} + +CJS_Return Field::set_page(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError)); +} + +CJS_Return Field::get_password(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_PASSWORD))); +} + +CJS_Return Field::set_password(CJS_Runtime* pRuntime, v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_print(CJS_Runtime* pRuntime) { + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + CPDFSDK_Widget* pWidget = + pInterForm->GetWidget(GetSmartFieldControl(pFormField)); + if (!pWidget) + return CJS_Return(false); + + return CJS_Return( + pRuntime->NewBoolean(!!(pWidget->GetFlags() & ANNOTFLAG_PRINT))); +} + +CJS_Return Field::set_print(CJS_Runtime* pRuntime, v8::Local vp) { + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + if (!m_bCanSet) + return CJS_Return(false); + + for (CPDF_FormField* pFormField : FieldArray) { + if (m_nFormControlIndex < 0) { + bool bSet = false; + for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { + if (CPDFSDK_Widget* pWidget = + pInterForm->GetWidget(pFormField->GetControl(i))) { + uint32_t dwFlags = pWidget->GetFlags(); + if (pRuntime->ToBoolean(vp)) + dwFlags |= ANNOTFLAG_PRINT; + else + dwFlags &= ~ANNOTFLAG_PRINT; + + if (dwFlags != pWidget->GetFlags()) { + pWidget->SetFlags(dwFlags); + bSet = true; + } + } + } + + if (bSet) + UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, false, true); + + continue; + } + + if (m_nFormControlIndex >= pFormField->CountControls()) + return CJS_Return(false); + + if (CPDF_FormControl* pFormControl = + pFormField->GetControl(m_nFormControlIndex)) { + if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { + uint32_t dwFlags = pWidget->GetFlags(); + if (pRuntime->ToBoolean(vp)) + dwFlags |= ANNOTFLAG_PRINT; + else + dwFlags &= ~ANNOTFLAG_PRINT; + + if (dwFlags != pWidget->GetFlags()) { + pWidget->SetFlags(dwFlags); + UpdateFormControl(m_pFormFillEnv.Get(), + pFormField->GetControl(m_nFormControlIndex), true, + false, true); + } + } + } + } + return CJS_Return(true); +} + +CJS_Return Field::get_radios_in_unison(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kRadioButton) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON))); +} + +CJS_Return Field::set_radios_in_unison(CJS_Runtime* pRuntime, + v8::Local vp) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_readonly(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(FieldArray[0]->GetFieldFlags() & FIELDFLAG_READONLY))); +} + +CJS_Return Field::set_readonly(CJS_Runtime* pRuntime, v8::Local vp) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_rect(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDFSDK_Widget* pWidget = + pInterForm->GetWidget(GetSmartFieldControl(pFormField)); + if (!pWidget) + return CJS_Return(false); + + CFX_FloatRect crRect = pWidget->GetRect(); + v8::Local rcArray = pRuntime->NewArray(); + pRuntime->PutArrayElement( + rcArray, 0, pRuntime->NewNumber(static_cast(crRect.left))); + pRuntime->PutArrayElement( + rcArray, 1, pRuntime->NewNumber(static_cast(crRect.top))); + pRuntime->PutArrayElement( + rcArray, 2, pRuntime->NewNumber(static_cast(crRect.right))); + pRuntime->PutArrayElement( + rcArray, 3, pRuntime->NewNumber(static_cast(crRect.bottom))); + + return CJS_Return(rcArray); +} + +CJS_Return Field::set_rect(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + if (vp.IsEmpty() || !vp->IsArray()) + return CJS_Return(false); + + v8::Local rcArray = pRuntime->ToArray(vp); + if (pRuntime->GetArrayLength(rcArray) < 4) + return CJS_Return(false); + + float pArray[4]; + pArray[0] = static_cast( + pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 0))); + pArray[1] = static_cast( + pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 1))); + pArray[2] = static_cast( + pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 2))); + pArray[3] = static_cast( + pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 3))); + + CFX_FloatRect crRect(pArray); + if (m_bDelay) { + AddDelay_Rect(FP_RECT, crRect); + } else { + Field::SetRect(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, + crRect); + } + return CJS_Return(true); +} + +void Field::SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const CFX_FloatRect& rect) { + CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm(); + std::vector FieldArray = + GetFormFields(pFormFillEnv, swFieldName); + for (CPDF_FormField* pFormField : FieldArray) { + if (nControlIndex < 0) { + bool bSet = false; + for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) { + CPDF_FormControl* pFormControl = pFormField->GetControl(i); + ASSERT(pFormControl); + + if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { + CFX_FloatRect crRect = rect; + + CPDF_Page* pPDFPage = pWidget->GetPDFPage(); + crRect.Intersect(pPDFPage->GetPageBBox()); + + if (!crRect.IsEmpty()) { + CFX_FloatRect rcOld = pWidget->GetRect(); + if (crRect.left != rcOld.left || crRect.right != rcOld.right || + crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) { + pWidget->SetRect(crRect); + bSet = true; + } + } + } + } + + if (bSet) + UpdateFormField(pFormFillEnv, pFormField, true, true, true); + + continue; + } + + if (nControlIndex >= pFormField->CountControls()) + return; + if (CPDF_FormControl* pFormControl = + pFormField->GetControl(nControlIndex)) { + if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) { + CFX_FloatRect crRect = rect; + + CPDF_Page* pPDFPage = pWidget->GetPDFPage(); + crRect.Intersect(pPDFPage->GetPageBBox()); + + if (!crRect.IsEmpty()) { + CFX_FloatRect rcOld = pWidget->GetRect(); + if (crRect.left != rcOld.left || crRect.right != rcOld.right || + crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) { + pWidget->SetRect(crRect); + UpdateFormControl(pFormFillEnv, pFormControl, true, true, true); + } + } + } + } + } +} + +CJS_Return Field::get_required(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() == FormFieldType::kPushButton) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_REQUIRED))); +} + +CJS_Return Field::set_required(CJS_Runtime* pRuntime, v8::Local vp) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_rich_text(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kTextField) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + !!(pFormField->GetFieldFlags() & FIELDFLAG_RICHTEXT))); +} + +CJS_Return Field::set_rich_text(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_rich_value(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Field::set_rich_value(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Field::get_rotation(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewNumber(pFormControl->GetRotation())); +} + +CJS_Return Field::set_rotation(CJS_Runtime* pRuntime, v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_stroke_color(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + int iColorType; + pFormControl->GetBorderColor(iColorType); + + CFX_Color color; + if (iColorType == CFX_Color::kTransparent) { + color = CFX_Color(CFX_Color::kTransparent); + } else if (iColorType == CFX_Color::kGray) { + color = + CFX_Color(CFX_Color::kGray, pFormControl->GetOriginalBorderColor(0)); + } else if (iColorType == CFX_Color::kRGB) { + color = CFX_Color(CFX_Color::kRGB, pFormControl->GetOriginalBorderColor(0), + pFormControl->GetOriginalBorderColor(1), + pFormControl->GetOriginalBorderColor(2)); + } else if (iColorType == CFX_Color::kCMYK) { + color = CFX_Color(CFX_Color::kCMYK, pFormControl->GetOriginalBorderColor(0), + pFormControl->GetOriginalBorderColor(1), + pFormControl->GetOriginalBorderColor(2), + pFormControl->GetOriginalBorderColor(3)); + } else { + return CJS_Return(false); + } + + v8::Local array = color::ConvertPWLColorToArray(pRuntime, color); + if (array.IsEmpty()) + return CJS_Return(pRuntime->NewArray()); + return CJS_Return(array); +} + +CJS_Return Field::set_stroke_color(CJS_Runtime* pRuntime, + v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + if (vp.IsEmpty() || !vp->IsArray()) + return CJS_Return(false); + return CJS_Return(true); +} + +CJS_Return Field::get_style(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kRadioButton && + pFormField->GetFieldType() != FormFieldType::kCheckBox) { + return CJS_Return(false); + } + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + WideString csWCaption = pFormControl->GetNormalCaption(); + ByteString csBCaption; + + switch (csWCaption[0]) { + case L'l': + csBCaption = "circle"; + break; + case L'8': + csBCaption = "cross"; + break; + case L'u': + csBCaption = "diamond"; + break; + case L'n': + csBCaption = "square"; + break; + case L'H': + csBCaption = "star"; + break; + default: // L'4' + csBCaption = "check"; + break; + } + return CJS_Return( + pRuntime->NewString(WideString::FromLocal(csBCaption.c_str()).c_str())); +} + +CJS_Return Field::set_style(CJS_Runtime* pRuntime, v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_submit_name(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Field::set_submit_name(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(true); +} + +CJS_Return Field::get_text_color(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + int iColorType; + FX_ARGB color; + CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance(); + FieldAppearance.GetColor(color, iColorType); + + int32_t a; + int32_t r; + int32_t g; + int32_t b; + std::tie(a, r, g, b) = ArgbDecode(color); + + CFX_Color crRet = + CFX_Color(CFX_Color::kRGB, r / 255.0f, g / 255.0f, b / 255.0f); + + if (iColorType == CFX_Color::kTransparent) + crRet = CFX_Color(CFX_Color::kTransparent); + + v8::Local array = color::ConvertPWLColorToArray(pRuntime, crRet); + if (array.IsEmpty()) + return CJS_Return(pRuntime->NewArray()); + return CJS_Return(array); +} + +CJS_Return Field::set_text_color(CJS_Runtime* pRuntime, + v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + if (vp.IsEmpty() || !vp->IsArray()) + return CJS_Return(false); + return CJS_Return(true); +} + +CJS_Return Field::get_text_font(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + ASSERT(pFormField); + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + FormFieldType fieldType = pFormField->GetFieldType(); + if (fieldType != FormFieldType::kPushButton && + fieldType != FormFieldType::kComboBox && + fieldType != FormFieldType::kListBox && + fieldType != FormFieldType::kTextField) { + return CJS_Return(false); + } + + CPDF_Font* pFont = pFormControl->GetDefaultControlFont(); + if (!pFont) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewString( + WideString::FromLocal(pFont->GetBaseFont().c_str()).c_str())); +} + +CJS_Return Field::set_text_font(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + + if (!m_bCanSet) + return CJS_Return(false); + return CJS_Return( + !ByteString::FromUnicode(pRuntime->ToWideString(vp)).IsEmpty()); +} + +CJS_Return Field::get_text_size(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + ASSERT(pFormField); + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + float fFontSize; + CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance(); + FieldAppearance.GetFont(&fFontSize); + return CJS_Return(pRuntime->NewNumber(static_cast(fFontSize))); +} + +CJS_Return Field::set_text_size(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_type(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + switch (pFormField->GetFieldType()) { + case FormFieldType::kUnknown: + return CJS_Return(pRuntime->NewString(L"unknown")); + case FormFieldType::kPushButton: + return CJS_Return(pRuntime->NewString(L"button")); + case FormFieldType::kCheckBox: + return CJS_Return(pRuntime->NewString(L"checkbox")); + case FormFieldType::kRadioButton: + return CJS_Return(pRuntime->NewString(L"radiobutton")); + case FormFieldType::kComboBox: + return CJS_Return(pRuntime->NewString(L"combobox")); + case FormFieldType::kListBox: + return CJS_Return(pRuntime->NewString(L"listbox")); + case FormFieldType::kTextField: + return CJS_Return(pRuntime->NewString(L"text")); + case FormFieldType::kSignature: + return CJS_Return(pRuntime->NewString(L"signature")); + default: + return CJS_Return(pRuntime->NewString(L"unknown")); + } +} + +CJS_Return Field::set_type(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return Field::get_user_name(CJS_Runtime* pRuntime) { + ASSERT(m_pFormFillEnv); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + return CJS_Return( + pRuntime->NewString(FieldArray[0]->GetAlternateName().c_str())); +} + +CJS_Return Field::set_user_name(CJS_Runtime* pRuntime, + v8::Local vp) { + ASSERT(m_pFormFillEnv); + return CJS_Return(m_bCanSet); +} + +CJS_Return Field::get_value(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + v8::Local ret; + + CPDF_FormField* pFormField = FieldArray[0]; + switch (pFormField->GetFieldType()) { + case FormFieldType::kPushButton: + return CJS_Return(false); + case FormFieldType::kComboBox: + case FormFieldType::kTextField: + ret = pRuntime->NewString(pFormField->GetValue().c_str()); + break; + case FormFieldType::kListBox: { + if (pFormField->CountSelectedItems() > 1) { + v8::Local ValueArray = pRuntime->NewArray(); + v8::Local ElementValue; + int iIndex; + for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) { + iIndex = pFormField->GetSelectedIndex(i); + ElementValue = + pRuntime->NewString(pFormField->GetOptionValue(iIndex).c_str()); + if (wcslen(pRuntime->ToWideString(ElementValue).c_str()) == 0) { + ElementValue = + pRuntime->NewString(pFormField->GetOptionLabel(iIndex).c_str()); + } + pRuntime->PutArrayElement(ValueArray, i, ElementValue); + } + ret = ValueArray; + } else { + ret = pRuntime->NewString(pFormField->GetValue().c_str()); + } + break; + } + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: { + bool bFind = false; + for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { + if (pFormField->GetControl(i)->IsChecked()) { + ret = pRuntime->NewString( + pFormField->GetControl(i)->GetExportValue().c_str()); + bFind = true; + break; + } + } + if (!bFind) + ret = pRuntime->NewString(L"Off"); + + break; + } + default: + ret = pRuntime->NewString(pFormField->GetValue().c_str()); + break; + } + return CJS_Return(pRuntime->MaybeCoerceToNumber(ret)); +} + +CJS_Return Field::set_value(CJS_Runtime* pRuntime, v8::Local vp) { + if (!m_bCanSet) + return CJS_Return(false); + + std::vector strArray; + if (!vp.IsEmpty() && vp->IsArray()) { + v8::Local ValueArray = pRuntime->ToArray(vp); + for (size_t i = 0; i < pRuntime->GetArrayLength(ValueArray); i++) { + strArray.push_back( + pRuntime->ToWideString(pRuntime->GetArrayElement(ValueArray, i))); + } + } else { + strArray.push_back(pRuntime->ToWideString(vp)); + } + + if (m_bDelay) { + AddDelay_WideStringArray(FP_VALUE, strArray); + } else { + Field::SetValue(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex, + strArray); + } + return CJS_Return(true); +} + +void Field::SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const std::vector& strArray) { + ASSERT(pFormFillEnv); + if (strArray.empty()) + return; + + std::vector FieldArray = + GetFormFields(pFormFillEnv, swFieldName); + + for (CPDF_FormField* pFormField : FieldArray) { + if (pFormField->GetFullName().Compare(swFieldName) != 0) + continue; + + switch (pFormField->GetFieldType()) { + case FormFieldType::kTextField: + case FormFieldType::kComboBox: + if (pFormField->GetValue() != strArray[0]) { + pFormField->SetValue(strArray[0], true); + UpdateFormField(pFormFillEnv, pFormField, true, false, true); + } + break; + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: + if (pFormField->GetValue() != strArray[0]) { + pFormField->SetValue(strArray[0], true); + UpdateFormField(pFormFillEnv, pFormField, true, false, true); + } + break; + case FormFieldType::kListBox: { + bool bModified = false; + for (const auto& str : strArray) { + if (!pFormField->IsItemSelected(pFormField->FindOption(str))) { + bModified = true; + break; + } + } + if (bModified) { + pFormField->ClearSelection(true); + for (const auto& str : strArray) { + int index = pFormField->FindOption(str); + if (!pFormField->IsItemSelected(index)) + pFormField->SetItemSelection(index, true, true); + } + UpdateFormField(pFormFillEnv, pFormField, true, false, true); + } + break; + } + default: + break; + } + } +} + +CJS_Return Field::get_value_as_string(CJS_Runtime* pRuntime) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() == FormFieldType::kPushButton) + return CJS_Return(false); + + if (pFormField->GetFieldType() == FormFieldType::kCheckBox) { + if (!pFormField->CountControls()) + return CJS_Return(false); + return CJS_Return(pRuntime->NewString( + pFormField->GetControl(0)->IsChecked() ? L"Yes" : L"Off")); + } + + if (pFormField->GetFieldType() == FormFieldType::kRadioButton && + !(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON)) { + for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { + if (pFormField->GetControl(i)->IsChecked()) { + return CJS_Return(pRuntime->NewString( + pFormField->GetControl(i)->GetExportValue().c_str())); + } + } + return CJS_Return(pRuntime->NewString(L"Off")); + } + + if (pFormField->GetFieldType() == FormFieldType::kListBox && + (pFormField->CountSelectedItems() > 1)) { + return CJS_Return(pRuntime->NewString(L"")); + } + return CJS_Return(pRuntime->NewString(pFormField->GetValue().c_str())); +} + +CJS_Return Field::set_value_as_string(CJS_Runtime* pRuntime, + v8::Local vp) { + return CJS_Return(false); +} + +CJS_Return Field::browseForFileToSubmit( + CJS_Runtime* pRuntime, + const std::vector>& params) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if ((pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT) && + (pFormField->GetFieldType() == FormFieldType::kTextField)) { + WideString wsFileName = m_pFormFillEnv->JS_fieldBrowse(); + if (!wsFileName.IsEmpty()) { + pFormField->SetValue(wsFileName); + UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true); + } + return CJS_Return(true); + } + return CJS_Return(false); +} + +CJS_Return Field::buttonGetCaption( + CJS_Runtime* pRuntime, + const std::vector>& params) { + int nface = 0; + int iSize = params.size(); + if (iSize >= 1) + nface = pRuntime->ToInt32(params[0]); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + if (nface == 0) { + return CJS_Return( + pRuntime->NewString(pFormControl->GetNormalCaption().c_str())); + } else if (nface == 1) { + return CJS_Return( + pRuntime->NewString(pFormControl->GetDownCaption().c_str())); + } else if (nface == 2) { + return CJS_Return( + pRuntime->NewString(pFormControl->GetRolloverCaption().c_str())); + } + return CJS_Return(false); +} + +CJS_Return Field::buttonGetIcon( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() >= 1) { + int nFace = pRuntime->ToInt32(params[0]); + if (nFace < 0 || nFace > 2) + return CJS_Return(false); + } + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kPushButton) + return CJS_Return(false); + + CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField); + if (!pFormControl) + return CJS_Return(false); + + v8::Local pObj = + pRuntime->NewFxDynamicObj(CJS_Icon::GetObjDefnID()); + if (pObj.IsEmpty()) + return CJS_Return(false); + + CJS_Icon* pJS_Icon = static_cast(pRuntime->GetObjectPrivate(pObj)); + if (!pJS_Icon) + return CJS_Return(false); + return CJS_Return(pJS_Icon->ToV8Object()); +} + +CJS_Return Field::buttonImportIcon( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Field::buttonSetCaption( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::buttonSetIcon( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::checkThisBox( + CJS_Runtime* pRuntime, + const std::vector>& params) { + int iSize = params.size(); + if (iSize < 1) + return CJS_Return(false); + + if (!m_bCanSet) + return CJS_Return(false); + + int nWidget = pRuntime->ToInt32(params[0]); + bool bCheckit = true; + if (iSize >= 2) + bCheckit = pRuntime->ToBoolean(params[1]); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (pFormField->GetFieldType() != FormFieldType::kCheckBox && + pFormField->GetFieldType() != FormFieldType::kRadioButton) { + return CJS_Return(false); + } + if (nWidget < 0 || nWidget >= pFormField->CountControls()) + return CJS_Return(false); + // TODO(weili): Check whether anything special needed for radio button, + // otherwise merge these branches. + if (pFormField->GetFieldType() == FormFieldType::kRadioButton) + pFormField->CheckControl(nWidget, bCheckit, true); + else + pFormField->CheckControl(nWidget, bCheckit, true); + + UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true); + return CJS_Return(true); +} + +CJS_Return Field::clearItems(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Field::defaultIsChecked( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (!m_bCanSet) + return CJS_Return(false); + + int iSize = params.size(); + if (iSize < 1) + return CJS_Return(false); + + int nWidget = pRuntime->ToInt32(params[0]); + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (nWidget < 0 || nWidget >= pFormField->CountControls()) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + pFormField->GetFieldType() == FormFieldType::kCheckBox || + pFormField->GetFieldType() == FormFieldType::kRadioButton)); +} + +CJS_Return Field::deleteItemAt( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Field::getArray(CJS_Runtime* pRuntime, + const std::vector>& params) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + std::vector> swSort; + for (CPDF_FormField* pFormField : FieldArray) { + swSort.push_back( + std::unique_ptr(new WideString(pFormField->GetFullName()))); + } + + std::sort(swSort.begin(), swSort.end(), + [](const std::unique_ptr& p1, + const std::unique_ptr& p2) { return *p1 < *p2; }); + + v8::Local FormFieldArray = pRuntime->NewArray(); + int j = 0; + for (const auto& pStr : swSort) { + v8::Local pObj = + pRuntime->NewFxDynamicObj(CJS_Field::GetObjDefnID()); + if (pObj.IsEmpty()) + return CJS_Return(false); + + CJS_Field* pJSField = + static_cast(pRuntime->GetObjectPrivate(pObj)); + Field* pField = static_cast(pJSField->GetEmbedObject()); + pField->AttachField(m_pJSDoc, *pStr); + pRuntime->PutArrayElement(FormFieldArray, j++, + pJSField + ? v8::Local(pJSField->ToV8Object()) + : v8::Local()); + } + return CJS_Return(FormFieldArray); +} + +CJS_Return Field::getItemAt(CJS_Runtime* pRuntime, + const std::vector>& params) { + int iSize = params.size(); + int nIdx = -1; + if (iSize >= 1) + nIdx = pRuntime->ToInt32(params[0]); + + bool bExport = true; + if (iSize >= 2) + bExport = pRuntime->ToBoolean(params[1]); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if ((pFormField->GetFieldType() == FormFieldType::kListBox) || + (pFormField->GetFieldType() == FormFieldType::kComboBox)) { + if (nIdx == -1 || nIdx > pFormField->CountOptions()) + nIdx = pFormField->CountOptions() - 1; + if (bExport) { + WideString strval = pFormField->GetOptionValue(nIdx); + if (strval.IsEmpty()) { + return CJS_Return( + pRuntime->NewString(pFormField->GetOptionLabel(nIdx).c_str())); + } + return CJS_Return(pRuntime->NewString(strval.c_str())); + } + return CJS_Return( + pRuntime->NewString(pFormField->GetOptionLabel(nIdx).c_str())); + } + return CJS_Return(false); +} + +CJS_Return Field::getLock(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::insertItemAt( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Field::isBoxChecked( + CJS_Runtime* pRuntime, + const std::vector>& params) { + int nIndex = -1; + if (params.size() >= 1) + nIndex = pRuntime->ToInt32(params[0]); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (nIndex < 0 || nIndex >= pFormField->CountControls()) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + ((pFormField->GetFieldType() == FormFieldType::kCheckBox || + pFormField->GetFieldType() == FormFieldType::kRadioButton) && + pFormField->GetControl(nIndex)->IsChecked() != 0))); +} + +CJS_Return Field::isDefaultChecked( + CJS_Runtime* pRuntime, + const std::vector>& params) { + int nIndex = -1; + if (params.size() >= 1) + nIndex = pRuntime->ToInt32(params[0]); + + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + if (nIndex < 0 || nIndex >= pFormField->CountControls()) + return CJS_Return(false); + + return CJS_Return(pRuntime->NewBoolean( + ((pFormField->GetFieldType() == FormFieldType::kCheckBox || + pFormField->GetFieldType() == FormFieldType::kRadioButton) && + pFormField->GetControl(nIndex)->IsDefaultChecked() != 0))); +} + +CJS_Return Field::setAction(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Field::setFocus(CJS_Runtime* pRuntime, + const std::vector>& params) { + std::vector FieldArray = GetFormFields(m_FieldName); + if (FieldArray.empty()) + return CJS_Return(false); + + CPDF_FormField* pFormField = FieldArray[0]; + int32_t nCount = pFormField->CountControls(); + if (nCount < 1) + return CJS_Return(false); + + CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm(); + CPDFSDK_Widget* pWidget = nullptr; + if (nCount == 1) { + pWidget = pInterForm->GetWidget(pFormField->GetControl(0)); + } else { + UnderlyingPageType* pPage = + UnderlyingFromFPDFPage(m_pFormFillEnv->GetCurrentPage( + m_pFormFillEnv->GetUnderlyingDocument())); + if (!pPage) + return CJS_Return(false); + if (CPDFSDK_PageView* pCurPageView = + m_pFormFillEnv->GetPageView(pPage, true)) { + for (int32_t i = 0; i < nCount; i++) { + if (CPDFSDK_Widget* pTempWidget = + pInterForm->GetWidget(pFormField->GetControl(i))) { + if (pTempWidget->GetPDFPage() == pCurPageView->GetPDFPage()) { + pWidget = pTempWidget; + break; + } + } + } + } + } + + if (pWidget) { + CPDFSDK_Annot::ObservedPtr pObserved(pWidget); + m_pFormFillEnv->SetFocusAnnot(&pObserved); + } + + return CJS_Return(true); +} + +CJS_Return Field::setItems(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return Field::setLock(CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::signatureGetModifications( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::signatureGetSeedValue( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::signatureInfo( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::signatureSetSeedValue( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::signatureSign( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::signatureValidate( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return CJS_Return(false); +} + +CJS_Return Field::get_source(CJS_Runtime* pRuntime) { + return CJS_Return(true); +} + +CJS_Return Field::set_source(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(true); +} + +void Field::AddDelay_Int(FIELD_PROP prop, int32_t n) { + CJS_DelayData* pNewData = + new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); + pNewData->num = n; + m_pJSDoc->AddDelayData(pNewData); +} + +void Field::AddDelay_Bool(FIELD_PROP prop, bool b) { + CJS_DelayData* pNewData = + new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); + pNewData->b = b; + m_pJSDoc->AddDelayData(pNewData); +} + +void Field::AddDelay_String(FIELD_PROP prop, const ByteString& string) { + CJS_DelayData* pNewData = + new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); + pNewData->string = string; + m_pJSDoc->AddDelayData(pNewData); +} + +void Field::AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect) { + CJS_DelayData* pNewData = + new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); + pNewData->rect = rect; + m_pJSDoc->AddDelayData(pNewData); +} + +void Field::AddDelay_WordArray(FIELD_PROP prop, + const std::vector& array) { + CJS_DelayData* pNewData = + new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); + pNewData->wordarray = array; + m_pJSDoc->AddDelayData(pNewData); +} + +void Field::AddDelay_WideStringArray(FIELD_PROP prop, + const std::vector& array) { + CJS_DelayData* pNewData = + new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName); + pNewData->widestringarray = array; + m_pJSDoc->AddDelayData(pNewData); +} + +void Field::DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CJS_DelayData* pData) { + ASSERT(pFormFillEnv); + switch (pData->eProp) { + case FP_BORDERSTYLE: + Field::SetBorderStyle(pFormFillEnv, pData->sFieldName, + pData->nControlIndex, pData->string); + break; + case FP_CURRENTVALUEINDICES: + Field::SetCurrentValueIndices(pFormFillEnv, pData->sFieldName, + pData->nControlIndex, pData->wordarray); + break; + case FP_DISPLAY: + Field::SetDisplay(pFormFillEnv, pData->sFieldName, pData->nControlIndex, + pData->num); + break; + case FP_HIDDEN: + Field::SetHidden(pFormFillEnv, pData->sFieldName, pData->nControlIndex, + pData->b); + break; + case FP_LINEWIDTH: + Field::SetLineWidth(pFormFillEnv, pData->sFieldName, pData->nControlIndex, + pData->num); + break; + case FP_RECT: + Field::SetRect(pFormFillEnv, pData->sFieldName, pData->nControlIndex, + pData->rect); + break; + case FP_VALUE: + Field::SetValue(pFormFillEnv, pData->sFieldName, pData->nControlIndex, + pData->widestringarray); + break; + default: + NOTREACHED(); + } +} diff --git a/fxjs/cjs_field.h b/fxjs/cjs_field.h new file mode 100644 index 0000000000000000000000000000000000000000..8116e073cfe6c2d66a55e3612453582f039df1d1 --- /dev/null +++ b/fxjs/cjs_field.h @@ -0,0 +1,438 @@ +// 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 FXJS_CJS_FIELD_H_ +#define FXJS_CJS_FIELD_H_ + +#include +#include + +#include "fxjs/JS_Define.h" + +class CPDF_FormControl; +class CPDFSDK_Widget; +class Document; +struct CJS_DelayData; + +enum FIELD_PROP { + FP_BORDERSTYLE, + FP_CURRENTVALUEINDICES, + FP_DISPLAY, + FP_HIDDEN, + FP_LINEWIDTH, + FP_RECT, + FP_VALUE +}; + +class Field : public CJS_EmbedObj { + public: + static void DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CJS_DelayData* pData); + + explicit Field(CJS_Object* pJSObject); + ~Field() override; + + CJS_Return get_alignment(CJS_Runtime* pRuntime); + CJS_Return set_alignment(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_border_style(CJS_Runtime* pRuntime); + CJS_Return set_border_style(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_button_align_x(CJS_Runtime* pRuntime); + CJS_Return set_button_align_x(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_button_align_y(CJS_Runtime* pRuntime); + CJS_Return set_button_align_y(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_button_fit_bounds(CJS_Runtime* pRuntime); + CJS_Return set_button_fit_bounds(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_button_position(CJS_Runtime* pRuntime); + CJS_Return set_button_position(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_button_scale_how(CJS_Runtime* pRuntime); + CJS_Return set_button_scale_how(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_button_scale_when(CJS_Runtime* pRuntime); + CJS_Return set_button_scale_when(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_calc_order_index(CJS_Runtime* pRuntime); + CJS_Return set_calc_order_index(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_char_limit(CJS_Runtime* pRuntime); + CJS_Return set_char_limit(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_comb(CJS_Runtime* pRuntime); + CJS_Return set_comb(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_commit_on_sel_change(CJS_Runtime* pRuntime); + CJS_Return set_commit_on_sel_change(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_current_value_indices(CJS_Runtime* pRuntime); + CJS_Return set_current_value_indices(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_default_style(CJS_Runtime* pRuntime); + CJS_Return set_default_style(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_default_value(CJS_Runtime* pRuntime); + CJS_Return set_default_value(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_do_not_scroll(CJS_Runtime* pRuntime); + CJS_Return set_do_not_scroll(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_do_not_spell_check(CJS_Runtime* pRuntime); + CJS_Return set_do_not_spell_check(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_delay(CJS_Runtime* pRuntime); + CJS_Return set_delay(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_display(CJS_Runtime* pRuntime); + CJS_Return set_display(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_doc(CJS_Runtime* pRuntime); + CJS_Return set_doc(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_editable(CJS_Runtime* pRuntime); + CJS_Return set_editable(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_export_values(CJS_Runtime* pRuntime); + CJS_Return set_export_values(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_file_select(CJS_Runtime* pRuntime); + CJS_Return set_file_select(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_fill_color(CJS_Runtime* pRuntime); + CJS_Return set_fill_color(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_hidden(CJS_Runtime* pRuntime); + CJS_Return set_hidden(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_highlight(CJS_Runtime* pRuntime); + CJS_Return set_highlight(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_line_width(CJS_Runtime* pRuntime); + CJS_Return set_line_width(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_multiline(CJS_Runtime* pRuntime); + CJS_Return set_multiline(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_multiple_selection(CJS_Runtime* pRuntime); + CJS_Return set_multiple_selection(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_name(CJS_Runtime* pRuntime); + CJS_Return set_name(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_num_items(CJS_Runtime* pRuntime); + CJS_Return set_num_items(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_page(CJS_Runtime* pRuntime); + CJS_Return set_page(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_password(CJS_Runtime* pRuntime); + CJS_Return set_password(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_print(CJS_Runtime* pRuntime); + CJS_Return set_print(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_radios_in_unison(CJS_Runtime* pRuntime); + CJS_Return set_radios_in_unison(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_readonly(CJS_Runtime* pRuntime); + CJS_Return set_readonly(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rect(CJS_Runtime* pRuntime); + CJS_Return set_rect(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_required(CJS_Runtime* pRuntime); + CJS_Return set_required(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rich_text(CJS_Runtime* pRuntime); + CJS_Return set_rich_text(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rich_value(CJS_Runtime* pRuntime); + CJS_Return set_rich_value(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_rotation(CJS_Runtime* pRuntime); + CJS_Return set_rotation(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_stroke_color(CJS_Runtime* pRuntime); + CJS_Return set_stroke_color(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_style(CJS_Runtime* pRuntime); + CJS_Return set_style(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_submit_name(CJS_Runtime* pRuntime); + CJS_Return set_submit_name(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_text_color(CJS_Runtime* pRuntime); + CJS_Return set_text_color(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_text_font(CJS_Runtime* pRuntime); + CJS_Return set_text_font(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_text_size(CJS_Runtime* pRuntime); + CJS_Return set_text_size(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_type(CJS_Runtime* pRuntime); + CJS_Return set_type(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_user_name(CJS_Runtime* pRuntime); + CJS_Return set_user_name(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_value(CJS_Runtime* pRuntime); + CJS_Return set_value(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return get_value_as_string(CJS_Runtime* pRuntime); + CJS_Return set_value_as_string(CJS_Runtime* pRuntime, + v8::Local vp); + + CJS_Return get_source(CJS_Runtime* pRuntime); + CJS_Return set_source(CJS_Runtime* pRuntime, v8::Local vp); + + CJS_Return browseForFileToSubmit( + CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return buttonGetCaption(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return buttonGetIcon(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return buttonImportIcon(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return buttonSetCaption(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return buttonSetIcon(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return checkThisBox(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return clearItems(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return defaultIsChecked(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return deleteItemAt(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getArray(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getItemAt(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return getLock(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return insertItemAt(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return isBoxChecked(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return isDefaultChecked(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return setAction(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return setFocus(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return setItems(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return setLock(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return signatureGetModifications( + CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return signatureGetSeedValue( + CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return signatureInfo(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return signatureSetSeedValue( + CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return signatureSign(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return signatureValidate(CJS_Runtime* pRuntime, + const std::vector>& params); + + bool AttachField(Document* pDocument, const WideString& csFieldName); + + private: + static void SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const ByteString& string); + static void SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const std::vector& array); + static void SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + int number); + static void SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + bool b); + static void SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + int number); + static void SetMultiline(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + bool b); + static void SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const CFX_FloatRect& rect); + static void SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& swFieldName, + int nControlIndex, + const std::vector& strArray); + + static void UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDF_FormField* pFormField, + bool bChangeMark, + bool bResetAP, + bool bRefresh); + static void UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDF_FormControl* pFormControl, + bool bChangeMark, + bool bResetAP, + bool bRefresh); + + static CPDFSDK_Widget* GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv, + CPDF_FormControl* pFormControl); + static std::vector GetFormFields( + CPDFSDK_FormFillEnvironment* pFormFillEnv, + const WideString& csFieldName); + + void SetDelay(bool bDelay); + void ParseFieldName(const std::wstring& strFieldNameParsed, + std::wstring& strFieldName, + int& iControlNo); + std::vector GetFormFields( + const WideString& csFieldName) const; + CPDF_FormControl* GetSmartFieldControl(CPDF_FormField* pFormField); + bool ValueIsOccur(CPDF_FormField* pFormField, WideString csOptLabel); + + void AddDelay_Int(FIELD_PROP prop, int32_t n); + void AddDelay_Bool(FIELD_PROP prop, bool b); + void AddDelay_String(FIELD_PROP prop, const ByteString& string); + void AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect); + void AddDelay_WordArray(FIELD_PROP prop, const std::vector& array); + void AddDelay_WideStringArray(FIELD_PROP prop, + const std::vector& array); + + void DoDelay(); + + Document* m_pJSDoc; + CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; + WideString m_FieldName; + int m_nFormControlIndex; + bool m_bCanSet; + bool m_bDelay; +}; + +class CJS_Field : public CJS_Object { + public: + static int GetObjDefnID(); + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Field(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Field() override {} + + void InitInstance(IJS_Runtime* pIRuntime) override; + + JS_STATIC_PROP(alignment, alignment, Field); + JS_STATIC_PROP(borderStyle, border_style, Field); + JS_STATIC_PROP(buttonAlignX, button_align_x, Field); + JS_STATIC_PROP(buttonAlignY, button_align_y, Field); + JS_STATIC_PROP(buttonFitBounds, button_fit_bounds, Field); + JS_STATIC_PROP(buttonPosition, button_position, Field); + JS_STATIC_PROP(buttonScaleHow, button_scale_how, Field); + JS_STATIC_PROP(ButtonScaleWhen, button_scale_when, Field); + JS_STATIC_PROP(calcOrderIndex, calc_order_index, Field); + JS_STATIC_PROP(charLimit, char_limit, Field); + JS_STATIC_PROP(comb, comb, Field); + JS_STATIC_PROP(commitOnSelChange, commit_on_sel_change, Field); + JS_STATIC_PROP(currentValueIndices, current_value_indices, Field); + JS_STATIC_PROP(defaultStyle, default_style, Field); + JS_STATIC_PROP(defaultValue, default_value, Field); + JS_STATIC_PROP(doNotScroll, do_not_scroll, Field); + JS_STATIC_PROP(doNotSpellCheck, do_not_spell_check, Field); + JS_STATIC_PROP(delay, delay, Field); + JS_STATIC_PROP(display, display, Field); + JS_STATIC_PROP(doc, doc, Field); + JS_STATIC_PROP(editable, editable, Field); + JS_STATIC_PROP(exportValues, export_values, Field); + JS_STATIC_PROP(fileSelect, file_select, Field); + JS_STATIC_PROP(fillColor, fill_color, Field); + JS_STATIC_PROP(hidden, hidden, Field); + JS_STATIC_PROP(highlight, highlight, Field); + JS_STATIC_PROP(lineWidth, line_width, Field); + JS_STATIC_PROP(multiline, multiline, Field); + JS_STATIC_PROP(multipleSelection, multiple_selection, Field); + JS_STATIC_PROP(name, name, Field); + JS_STATIC_PROP(numItems, num_items, Field); + JS_STATIC_PROP(page, page, Field); + JS_STATIC_PROP(password, password, Field); + JS_STATIC_PROP(print, print, Field); + JS_STATIC_PROP(radiosInUnison, radios_in_unison, Field); + JS_STATIC_PROP(readonly, readonly, Field); + JS_STATIC_PROP(rect, rect, Field); + JS_STATIC_PROP(required, required, Field); + JS_STATIC_PROP(richText, rich_text, Field); + JS_STATIC_PROP(richValue, rich_value, Field); + JS_STATIC_PROP(rotation, rotation, Field); + JS_STATIC_PROP(strokeColor, stroke_color, Field); + JS_STATIC_PROP(style, style, Field); + JS_STATIC_PROP(submitName, submit_name, Field); + JS_STATIC_PROP(textColor, text_color, Field); + JS_STATIC_PROP(textFont, text_font, Field); + JS_STATIC_PROP(textSize, text_size, Field); + JS_STATIC_PROP(type, type, Field); + JS_STATIC_PROP(userName, user_name, Field); + JS_STATIC_PROP(value, value, Field); + JS_STATIC_PROP(valueAsString, value_as_string, Field); + JS_STATIC_PROP(source, source, Field); + + JS_STATIC_METHOD(browseForFileToSubmit, Field); + JS_STATIC_METHOD(buttonGetCaption, Field); + JS_STATIC_METHOD(buttonGetIcon, Field); + JS_STATIC_METHOD(buttonImportIcon, Field); + JS_STATIC_METHOD(buttonSetCaption, Field); + JS_STATIC_METHOD(buttonSetIcon, Field); + JS_STATIC_METHOD(checkThisBox, Field); + JS_STATIC_METHOD(clearItems, Field); + JS_STATIC_METHOD(defaultIsChecked, Field); + JS_STATIC_METHOD(deleteItemAt, Field); + JS_STATIC_METHOD(getArray, Field); + JS_STATIC_METHOD(getItemAt, Field); + JS_STATIC_METHOD(getLock, Field); + JS_STATIC_METHOD(insertItemAt, Field); + JS_STATIC_METHOD(isBoxChecked, Field); + JS_STATIC_METHOD(isDefaultChecked, Field); + JS_STATIC_METHOD(setAction, Field); + JS_STATIC_METHOD(setFocus, Field); + JS_STATIC_METHOD(setItems, Field); + JS_STATIC_METHOD(setLock, Field); + JS_STATIC_METHOD(signatureGetModifications, Field); + JS_STATIC_METHOD(signatureGetSeedValue, Field); + JS_STATIC_METHOD(signatureInfo, Field); + JS_STATIC_METHOD(signatureSetSeedValue, Field); + JS_STATIC_METHOD(signatureSign, Field); + JS_STATIC_METHOD(signatureValidate, Field); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_FIELD_H_ diff --git a/fxjs/cjs_font.cpp b/fxjs/cjs_font.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54b392f9a7843f94f19dfab4273512b82af20f67 --- /dev/null +++ b/fxjs/cjs_font.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_font.h" + +const JSConstSpec CJS_Font::ConstSpecs[] = { + {"Times", JSConstSpec::String, 0, "Times-Roman"}, + {"TimesB", JSConstSpec::String, 0, "Times-Bold"}, + {"TimesI", JSConstSpec::String, 0, "Times-Italic"}, + {"TimesBI", JSConstSpec::String, 0, "Times-BoldItalic"}, + {"Helv", JSConstSpec::String, 0, "Helvetica"}, + {"HelvB", JSConstSpec::String, 0, "Helvetica-Bold"}, + {"HelvI", JSConstSpec::String, 0, "Helvetica-Oblique"}, + {"HelvBI", JSConstSpec::String, 0, "Helvetica-BoldOblique"}, + {"Cour", JSConstSpec::String, 0, "Courier"}, + {"CourB", JSConstSpec::String, 0, "Courier-Bold"}, + {"CourI", JSConstSpec::String, 0, "Courier-Oblique"}, + {"CourBI", JSConstSpec::String, 0, "Courier-BoldOblique"}, + {"Symbol", JSConstSpec::String, 0, "Symbol"}, + {"ZapfD", JSConstSpec::String, 0, "ZapfDingbats"}}; + +int CJS_Font::ObjDefnID = -1; + +// static +void CJS_Font::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("font", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_font.h b/fxjs/cjs_font.h new file mode 100644 index 0000000000000000000000000000000000000000..31edf06836c74769ec01b0578a44d2b44ec55f22 --- /dev/null +++ b/fxjs/cjs_font.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_FONT_H_ +#define FXJS_CJS_FONT_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Font : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Font(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Font() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_FONT_H_ diff --git a/fxjs/cjs_global.cpp b/fxjs/cjs_global.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb66488d8ef5939300bc8b2ae533c313d8c19a65 --- /dev/null +++ b/fxjs/cjs_global.cpp @@ -0,0 +1,615 @@ +// 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 "fxjs/cjs_global.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_globaldata.h" +#include "fxjs/cjs_keyvalue.h" +#include "fxjs/cjs_object.h" +#include "fxjs/js_resources.h" + +namespace { + +WideString PropFromV8Prop(v8::Isolate* pIsolate, + v8::Local property) { + v8::String::Utf8Value utf8_value(pIsolate, property); + return WideString::FromUTF8(ByteStringView(*utf8_value, utf8_value.length())); +} + +template +void JSSpecialPropQuery(const char*, + v8::Local property, + const v8::PropertyCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = + pObj->QueryProperty(PropFromV8Prop(info.GetIsolate(), property).c_str()); + info.GetReturnValue().Set(!result.HasError() ? 4 : 0); +} + +template +void JSSpecialPropGet(const char* class_name, + v8::Local property, + const v8::PropertyCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = pObj->GetProperty( + pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str()); + if (result.HasError()) { + pRuntime->Error( + JSFormatErrorString(class_name, "GetProperty", result.Error())); + return; + } + + if (result.HasReturn()) + info.GetReturnValue().Set(result.Return()); +} + +template +void JSSpecialPropPut(const char* class_name, + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = pObj->SetProperty( + pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str(), value); + if (result.HasError()) { + pRuntime->Error( + JSFormatErrorString(class_name, "PutProperty", result.Error())); + } +} + +template +void JSSpecialPropDel(const char* class_name, + v8::Local property, + const v8::PropertyCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + CJS_Object* pJSObj = + static_cast(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + + Alt* pObj = reinterpret_cast(pJSObj->GetEmbedObject()); + CJS_Return result = pObj->DelProperty( + pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str()); + if (result.HasError()) { + // TODO(dsinclair): Should this set the pRuntime->Error result? + // ByteString cbName = + // ByteString::Format("%s.%s", class_name, "DelProperty"); + } +} + +struct JSGlobalData { + JSGlobalData(); + ~JSGlobalData(); + + JS_GlobalDataType nType; + double dData; + bool bData; + ByteString sData; + v8::Global pData; + bool bPersistent; + bool bDeleted; +}; + +class JSGlobalAlternate : public CJS_EmbedObj { + public: + explicit JSGlobalAlternate(CJS_Object* pJSObject); + ~JSGlobalAlternate() override; + + CJS_Return setPersistent(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return QueryProperty(const wchar_t* propname); + CJS_Return GetProperty(CJS_Runtime* pRuntime, const wchar_t* propname); + CJS_Return SetProperty(CJS_Runtime* pRuntime, + const wchar_t* propname, + v8::Local vp); + CJS_Return DelProperty(CJS_Runtime* pRuntime, const wchar_t* propname); + void Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv); + + private: + void UpdateGlobalPersistentVariables(); + void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime); + void DestroyGlobalPersisitentVariables(); + CJS_Return SetGlobalVariables(const ByteString& propname, + JS_GlobalDataType nType, + double dData, + bool bData, + const ByteString& sData, + v8::Local pData, + bool bDefaultPersistent); + void ObjectToArray(CJS_Runtime* pRuntime, + v8::Local pObj, + CJS_GlobalVariableArray& array); + void PutObjectProperty(v8::Local obj, CJS_KeyValue* pData); + + std::map> m_MapGlobal; + WideString m_sFilePath; + CJS_GlobalData* m_pGlobalData; + CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; +}; + +} // namespace + +const JSMethodSpec CJS_Global::MethodSpecs[] = { + {"setPersistent", setPersistent_static}}; + +int CJS_Global::ObjDefnID = -1; + +// static +void CJS_Global::setPersistent_static( + const v8::FunctionCallbackInfo& info) { + JSMethod( + "setPersistent", "global", info); +} + +// static +void CJS_Global::queryprop_static( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + JSSpecialPropQuery("global", property, info); +} + +// static +void CJS_Global::getprop_static( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + JSSpecialPropGet("global", property, info); +} + +// static +void CJS_Global::putprop_static( + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info) { + JSSpecialPropPut("global", property, value, info); +} + +// static +void CJS_Global::delprop_static( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + JSSpecialPropDel("global", property, info); +} + +// static +void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) { + pEngine->DefineObjAllProperties( + ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static, + CJS_Global::putprop_static, CJS_Global::delprop_static); +} + +// static +void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC, + JSConstructor, + JSDestructor); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); + DefineAllProperties(pEngine); +} + +void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) { + CJS_Runtime* pRuntime = static_cast(pIRuntime); + JSGlobalAlternate* pGlobal = + static_cast(GetEmbedObject()); + pGlobal->Initial(pRuntime->GetFormFillEnv()); +} + +JSGlobalData::JSGlobalData() + : nType(JS_GlobalDataType::NUMBER), + dData(0), + bData(false), + sData(""), + bPersistent(false), + bDeleted(false) {} + +JSGlobalData::~JSGlobalData() { + pData.Reset(); +} + +JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject), m_pFormFillEnv(nullptr) {} + +JSGlobalAlternate::~JSGlobalAlternate() { + DestroyGlobalPersisitentVariables(); + m_pGlobalData->Release(); +} + +void JSGlobalAlternate::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) { + m_pFormFillEnv.Reset(pFormFillEnv); + m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv); + UpdateGlobalPersistentVariables(); +} + +CJS_Return JSGlobalAlternate::QueryProperty(const wchar_t* propname) { + return CJS_Return(WideString(propname) != L"setPersistent"); +} + +CJS_Return JSGlobalAlternate::DelProperty(CJS_Runtime* pRuntime, + const wchar_t* propname) { + auto it = m_MapGlobal.find(ByteString::FromUnicode(propname)); + if (it == m_MapGlobal.end()) + return CJS_Return(false); + + it->second->bDeleted = true; + return CJS_Return(true); +} + +CJS_Return JSGlobalAlternate::GetProperty(CJS_Runtime* pRuntime, + const wchar_t* propname) { + auto it = m_MapGlobal.find(ByteString::FromUnicode(propname)); + if (it == m_MapGlobal.end()) + return CJS_Return(true); + + JSGlobalData* pData = it->second.get(); + if (pData->bDeleted) + return CJS_Return(true); + + switch (pData->nType) { + case JS_GlobalDataType::NUMBER: + return CJS_Return(pRuntime->NewNumber(pData->dData)); + case JS_GlobalDataType::BOOLEAN: + return CJS_Return(pRuntime->NewBoolean(pData->bData)); + case JS_GlobalDataType::STRING: + return CJS_Return(pRuntime->NewString( + WideString::FromLocal(pData->sData.c_str()).c_str())); + case JS_GlobalDataType::OBJECT: + return CJS_Return( + v8::Local::New(pRuntime->GetIsolate(), pData->pData)); + case JS_GlobalDataType::NULLOBJ: + return CJS_Return(pRuntime->NewNull()); + default: + break; + } + return CJS_Return(false); +} + +CJS_Return JSGlobalAlternate::SetProperty(CJS_Runtime* pRuntime, + const wchar_t* propname, + v8::Local vp) { + ByteString sPropName = ByteString::FromUnicode(propname); + if (vp->IsNumber()) { + return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER, + pRuntime->ToDouble(vp), false, "", + v8::Local(), false); + } + if (vp->IsBoolean()) { + return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0, + pRuntime->ToBoolean(vp), "", + v8::Local(), false); + } + if (vp->IsString()) { + return SetGlobalVariables( + sPropName, JS_GlobalDataType::STRING, 0, false, + ByteString::FromUnicode(pRuntime->ToWideString(vp)), + v8::Local(), false); + } + if (vp->IsObject()) { + return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, false, + "", pRuntime->ToObject(vp), false); + } + if (vp->IsNull()) { + return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, false, + "", v8::Local(), false); + } + if (vp->IsUndefined()) { + DelProperty(pRuntime, propname); + return CJS_Return(true); + } + return CJS_Return(false); +} + +CJS_Return JSGlobalAlternate::setPersistent( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + auto it = m_MapGlobal.find( + ByteString::FromUnicode(pRuntime->ToWideString(params[0]))); + if (it == m_MapGlobal.end() || it->second->bDeleted) + return CJS_Return(JSGetStringFromID(JSMessage::kGlobalNotFoundError)); + + it->second->bPersistent = pRuntime->ToBoolean(params[1]); + return CJS_Return(true); +} + +void JSGlobalAlternate::UpdateGlobalPersistentVariables() { + CJS_Runtime* pRuntime = + static_cast(CFXJS_Engine::CurrentEngineFromIsolate( + m_pJSObject->ToV8Object()->GetIsolate())); + + for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) { + CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i); + switch (pData->data.nType) { + case JS_GlobalDataType::NUMBER: + SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER, + pData->data.dData, false, "", + v8::Local(), pData->bPersistent == 1); + pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(), + pData->data.sKey.UTF8Decode(), + pRuntime->NewNumber(pData->data.dData)); + break; + case JS_GlobalDataType::BOOLEAN: + SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0, + pData->data.bData == 1, "", v8::Local(), + pData->bPersistent == 1); + pRuntime->PutObjectProperty( + m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(), + pRuntime->NewBoolean(pData->data.bData == 1)); + break; + case JS_GlobalDataType::STRING: + SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0, + false, pData->data.sData, v8::Local(), + pData->bPersistent == 1); + pRuntime->PutObjectProperty( + m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(), + pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView())); + break; + case JS_GlobalDataType::OBJECT: { + v8::Local pObj = pRuntime->NewFxDynamicObj(-1); + if (!pObj.IsEmpty()) { + PutObjectProperty(pObj, &pData->data); + SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0, + false, "", pObj, pData->bPersistent == 1); + pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(), + pData->data.sKey.UTF8Decode(), pObj); + } + } break; + case JS_GlobalDataType::NULLOBJ: + SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0, + false, "", v8::Local(), + pData->bPersistent == 1); + pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(), + pData->data.sKey.UTF8Decode(), + pRuntime->NewNull()); + break; + } + } +} + +void JSGlobalAlternate::CommitGlobalPersisitentVariables( + CJS_Runtime* pRuntime) { + for (const auto& iter : m_MapGlobal) { + ByteString name = iter.first; + JSGlobalData* pData = iter.second.get(); + if (pData->bDeleted) { + m_pGlobalData->DeleteGlobalVariable(name); + continue; + } + switch (pData->nType) { + case JS_GlobalDataType::NUMBER: + m_pGlobalData->SetGlobalVariableNumber(name, pData->dData); + m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); + break; + case JS_GlobalDataType::BOOLEAN: + m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData); + m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); + break; + case JS_GlobalDataType::STRING: + m_pGlobalData->SetGlobalVariableString(name, pData->sData); + m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); + break; + case JS_GlobalDataType::OBJECT: { + CJS_GlobalVariableArray array; + v8::Local obj = v8::Local::New( + GetJSObject()->GetIsolate(), pData->pData); + ObjectToArray(pRuntime, obj, array); + m_pGlobalData->SetGlobalVariableObject(name, array); + m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); + } break; + case JS_GlobalDataType::NULLOBJ: + m_pGlobalData->SetGlobalVariableNull(name); + m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent); + break; + } + } +} + +void JSGlobalAlternate::ObjectToArray(CJS_Runtime* pRuntime, + v8::Local pObj, + CJS_GlobalVariableArray& array) { + std::vector pKeyList = pRuntime->GetObjectPropertyNames(pObj); + for (const auto& ws : pKeyList) { + ByteString sKey = ws.UTF8Encode(); + v8::Local v = pRuntime->GetObjectProperty(pObj, ws); + if (v->IsNumber()) { + CJS_KeyValue* pObjElement = new CJS_KeyValue; + pObjElement->nType = JS_GlobalDataType::NUMBER; + pObjElement->sKey = sKey; + pObjElement->dData = pRuntime->ToDouble(v); + array.Add(pObjElement); + continue; + } + if (v->IsBoolean()) { + CJS_KeyValue* pObjElement = new CJS_KeyValue; + pObjElement->nType = JS_GlobalDataType::BOOLEAN; + pObjElement->sKey = sKey; + pObjElement->dData = pRuntime->ToBoolean(v); + array.Add(pObjElement); + continue; + } + if (v->IsString()) { + ByteString sValue = ByteString::FromUnicode(pRuntime->ToWideString(v)); + CJS_KeyValue* pObjElement = new CJS_KeyValue; + pObjElement->nType = JS_GlobalDataType::STRING; + pObjElement->sKey = sKey; + pObjElement->sData = sValue; + array.Add(pObjElement); + continue; + } + if (v->IsObject()) { + CJS_KeyValue* pObjElement = new CJS_KeyValue; + pObjElement->nType = JS_GlobalDataType::OBJECT; + pObjElement->sKey = sKey; + ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData); + array.Add(pObjElement); + continue; + } + if (v->IsNull()) { + CJS_KeyValue* pObjElement = new CJS_KeyValue; + pObjElement->nType = JS_GlobalDataType::NULLOBJ; + pObjElement->sKey = sKey; + array.Add(pObjElement); + } + } +} + +void JSGlobalAlternate::PutObjectProperty(v8::Local pObj, + CJS_KeyValue* pData) { + CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate( + m_pJSObject->ToV8Object()->GetIsolate()); + + for (int i = 0, sz = pData->objData.Count(); i < sz; i++) { + CJS_KeyValue* pObjData = pData->objData.GetAt(i); + switch (pObjData->nType) { + case JS_GlobalDataType::NUMBER: + pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), + pRuntime->NewNumber(pObjData->dData)); + break; + case JS_GlobalDataType::BOOLEAN: + pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), + pRuntime->NewBoolean(pObjData->bData == 1)); + break; + case JS_GlobalDataType::STRING: + pRuntime->PutObjectProperty( + pObj, pObjData->sKey.UTF8Decode(), + pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView())); + break; + case JS_GlobalDataType::OBJECT: { + v8::Local pNewObj = pRuntime->NewFxDynamicObj(-1); + if (!pNewObj.IsEmpty()) { + PutObjectProperty(pNewObj, pObjData); + pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), + pNewObj); + } + } break; + case JS_GlobalDataType::NULLOBJ: + pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), + pRuntime->NewNull()); + break; + } + } +} + +void JSGlobalAlternate::DestroyGlobalPersisitentVariables() { + m_MapGlobal.clear(); +} + +CJS_Return JSGlobalAlternate::SetGlobalVariables(const ByteString& propname, + JS_GlobalDataType nType, + double dData, + bool bData, + const ByteString& sData, + v8::Local pData, + bool bDefaultPersistent) { + if (propname.IsEmpty()) + return CJS_Return(false); + + auto it = m_MapGlobal.find(propname); + if (it != m_MapGlobal.end()) { + JSGlobalData* pTemp = it->second.get(); + if (pTemp->bDeleted || pTemp->nType != nType) { + pTemp->dData = 0; + pTemp->bData = 0; + pTemp->sData.clear(); + pTemp->nType = nType; + } + pTemp->bDeleted = false; + switch (nType) { + case JS_GlobalDataType::NUMBER: + pTemp->dData = dData; + break; + case JS_GlobalDataType::BOOLEAN: + pTemp->bData = bData; + break; + case JS_GlobalDataType::STRING: + pTemp->sData = sData; + break; + case JS_GlobalDataType::OBJECT: + pTemp->pData.Reset(pData->GetIsolate(), pData); + break; + case JS_GlobalDataType::NULLOBJ: + break; + default: + return CJS_Return(false); + } + return CJS_Return(true); + } + + auto pNewData = pdfium::MakeUnique(); + switch (nType) { + case JS_GlobalDataType::NUMBER: + pNewData->nType = JS_GlobalDataType::NUMBER; + pNewData->dData = dData; + pNewData->bPersistent = bDefaultPersistent; + break; + case JS_GlobalDataType::BOOLEAN: + pNewData->nType = JS_GlobalDataType::BOOLEAN; + pNewData->bData = bData; + pNewData->bPersistent = bDefaultPersistent; + break; + case JS_GlobalDataType::STRING: + pNewData->nType = JS_GlobalDataType::STRING; + pNewData->sData = sData; + pNewData->bPersistent = bDefaultPersistent; + break; + case JS_GlobalDataType::OBJECT: + pNewData->nType = JS_GlobalDataType::OBJECT; + pNewData->pData.Reset(pData->GetIsolate(), pData); + pNewData->bPersistent = bDefaultPersistent; + break; + case JS_GlobalDataType::NULLOBJ: + pNewData->nType = JS_GlobalDataType::NULLOBJ; + pNewData->bPersistent = bDefaultPersistent; + break; + default: + return CJS_Return(false); + } + m_MapGlobal[propname] = std::move(pNewData); + return CJS_Return(true); +} diff --git a/fxjs/cjs_global.h b/fxjs/cjs_global.h new file mode 100644 index 0000000000000000000000000000000000000000..203d6e969de0326f1056deb6485877a072369327 --- /dev/null +++ b/fxjs/cjs_global.h @@ -0,0 +1,42 @@ +// 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 FXJS_CJS_GLOBAL_H_ +#define FXJS_CJS_GLOBAL_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Global : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + static void DefineAllProperties(CFXJS_Engine* pEngine); + + static void queryprop_static( + v8::Local property, + const v8::PropertyCallbackInfo& info); + static void getprop_static(v8::Local property, + const v8::PropertyCallbackInfo& info); + static void putprop_static(v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info); + static void delprop_static(v8::Local property, + const v8::PropertyCallbackInfo& info); + + static void setPersistent_static( + const v8::FunctionCallbackInfo& info); + + explicit CJS_Global(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Global() override {} + + // CJS_Object + void InitInstance(IJS_Runtime* pIRuntime) override; + + private: + static int ObjDefnID; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_GLOBAL_H_ diff --git a/fxjs/cjs_globalarrays.cpp b/fxjs/cjs_globalarrays.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7857161205cd279316b1647a23dbb1dda36fe099 --- /dev/null +++ b/fxjs/cjs_globalarrays.cpp @@ -0,0 +1,74 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_globalarrays.h" + +#define GLOBAL_ARRAY(rt, name, ...) \ + { \ + const wchar_t* values[] = {__VA_ARGS__}; \ + v8::Local array = (rt)->NewArray(); \ + for (size_t i = 0; i < FX_ArraySize(values); ++i) \ + array->Set(i, (rt)->NewString(values[i])); \ + (rt)->SetConstArray((name), array); \ + (rt)->DefineGlobalConst( \ + (name), [](const v8::FunctionCallbackInfo& info) { \ + CJS_Runtime* pCurrentRuntime = \ + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); \ + if (pCurrentRuntime) \ + info.GetReturnValue().Set(pCurrentRuntime->GetConstArray(name)); \ + }); \ + } + +// static +void CJS_GlobalArrays::DefineJSObjects(CJS_Runtime* pRuntime) { + GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_ENTRY_DOT_SEP", L"[+-]?\\d*\\.?\\d*"); + GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_COMMIT_DOT_SEP", + L"[+-]?\\d+(\\.\\d+)?", // -1.0 or -1 + L"[+-]?\\.\\d+", // -.1 + L"[+-]?\\d+\\."); // -1. + + GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_ENTRY_COMMA_SEP", L"[+-]?\\d*,?\\d*"); + GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_COMMIT_COMMA_SEP", + L"[+-]?\\d+([.,]\\d+)?", // -1,0 or -1 + L"[+-]?[.,]\\d+", // -,1 + L"[+-]?\\d+[.,]"); // -1, + + GLOBAL_ARRAY(pRuntime, L"RE_ZIP_ENTRY", L"\\d{0,5}"); + GLOBAL_ARRAY(pRuntime, L"RE_ZIP_COMMIT", L"\\d{5}"); + GLOBAL_ARRAY(pRuntime, L"RE_ZIP4_ENTRY", L"\\d{0,5}(\\.|[- ])?\\d{0,4}"); + GLOBAL_ARRAY(pRuntime, L"RE_ZIP4_COMMIT", L"\\d{5}(\\.|[- ])?\\d{4}"); + GLOBAL_ARRAY(pRuntime, L"RE_PHONE_ENTRY", + // 555-1234 or 408 555-1234 + L"\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", + + // (408 + L"\\(\\d{0,3}", + + // (408) 555-1234 + // (allow the addition of parens as an afterthought) + L"\\(\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", + + // (408 555-1234 + L"\\(\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", + + // 408) 555-1234 + L"\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}", + + // international + L"011(\\.|[- \\d])*"); + + GLOBAL_ARRAY( + pRuntime, L"RE_PHONE_COMMIT", L"\\d{3}(\\.|[- ])?\\d{4}", // 555-1234 + L"\\d{3}(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", // 408 555-1234 + L"\\(\\d{3}\\)(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", // (408) 555-1234 + L"011(\\.|[- \\d])*"); // international + + GLOBAL_ARRAY(pRuntime, L"RE_SSN_ENTRY", + L"\\d{0,3}(\\.|[- ])?\\d{0,2}(\\.|[- ])?\\d{0,4}"); + + GLOBAL_ARRAY(pRuntime, L"RE_SSN_COMMIT", + L"\\d{3}(\\.|[- ])?\\d{2}(\\.|[- ])?\\d{4}"); +} diff --git a/fxjs/cjs_globalarrays.h b/fxjs/cjs_globalarrays.h new file mode 100644 index 0000000000000000000000000000000000000000..297b97b614649d111aa2144a564136b482bc17a8 --- /dev/null +++ b/fxjs/cjs_globalarrays.h @@ -0,0 +1,17 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_GLOBALARRAYS_H_ +#define FXJS_CJS_GLOBALARRAYS_H_ + +#include "fxjs/JS_Define.h" + +class CJS_GlobalArrays : public CJS_Object { + public: + static void DefineJSObjects(CJS_Runtime* pRuntmie); +}; + +#endif // FXJS_CJS_GLOBALARRAYS_H_ diff --git a/fxjs/cjs_globalconsts.cpp b/fxjs/cjs_globalconsts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..598479780a0c1b909b0d1bcdc17b1ad00117f4b5 --- /dev/null +++ b/fxjs/cjs_globalconsts.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_globalconsts.h" + +#define GLOBAL_STRING(rt, name, value) \ + (rt)->DefineGlobalConst( \ + (name), [](const v8::FunctionCallbackInfo& info) { \ + info.GetReturnValue().Set( \ + CFXJS_Engine::CurrentEngineFromIsolate(info.GetIsolate()) \ + ->NewString(value)); \ + }) + +// static +void CJS_GlobalConsts::DefineJSObjects(CJS_Runtime* pRuntime) { + GLOBAL_STRING(pRuntime, L"IDS_GREATER_THAN", + L"Invalid value: must be greater than or equal to % s."); + + GLOBAL_STRING(pRuntime, L"IDS_GT_AND_LT", + L"Invalid value: must be greater than or equal to % s " + L"and less than or equal to % s."); + + GLOBAL_STRING(pRuntime, L"IDS_LESS_THAN", + L"Invalid value: must be less than or equal to % s."); + + GLOBAL_STRING(pRuntime, L"IDS_INVALID_MONTH", L"**Invalid**"); + GLOBAL_STRING( + pRuntime, L"IDS_INVALID_DATE", + L"Invalid date / time: please ensure that the date / time exists.Field"); + + GLOBAL_STRING(pRuntime, L"IDS_INVALID_VALUE", + L"The value entered does not match the format of the field"); + + GLOBAL_STRING(pRuntime, L"IDS_AM", L"am"); + GLOBAL_STRING(pRuntime, L"IDS_PM", L"pm"); + GLOBAL_STRING(pRuntime, L"IDS_MONTH_INFO", + L"January[1] February[2] March[3] April[4] May[5] " + L"June[6] July[7] August[8] September[9] October[10] " + L"November[11] December[12] Sept[9] Jan[1] Feb[2] Mar[3] " + L"Apr[4] Jun[6] Jul[7] Aug[8] Sep[9] Oct[10] Nov[11] " + L"Dec[12]"); + + GLOBAL_STRING(pRuntime, L"IDS_STARTUP_CONSOLE_MSG", L"** ^ _ ^ **"); +} diff --git a/fxjs/cjs_globalconsts.h b/fxjs/cjs_globalconsts.h new file mode 100644 index 0000000000000000000000000000000000000000..8c6618ee6fce913b92a4c898fc232f70e3eb8b28 --- /dev/null +++ b/fxjs/cjs_globalconsts.h @@ -0,0 +1,17 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_GLOBALCONSTS_H_ +#define FXJS_CJS_GLOBALCONSTS_H_ + +#include "fxjs/JS_Define.h" + +class CJS_GlobalConsts : public CJS_Object { + public: + static void DefineJSObjects(CJS_Runtime* pRuntime); +}; + +#endif // FXJS_CJS_GLOBALCONSTS_H_ diff --git a/fxjs/cjs_globaldata.cpp b/fxjs/cjs_globaldata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a78bce55c35af03ac6e269e9caef68eeffdf3d46 --- /dev/null +++ b/fxjs/cjs_globaldata.cpp @@ -0,0 +1,396 @@ +// 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 "fxjs/cjs_globaldata.h" + +#include + +#include "core/fdrm/crypto/fx_crypt.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +#define JS_MAXGLOBALDATA (1024 * 4 - 8) + +#define READER_JS_GLOBALDATA_FILENAME L"Reader_JsGlobal.Data" +#define PHANTOM_JS_GLOBALDATA_FILENAME L"Phantom_JsGlobal.Data" +#define SDK_JS_GLOBALDATA_FILENAME L"SDK_JsGlobal.Data" + +namespace { + +const uint8_t JS_RC4KEY[] = { + 0x19, 0xa8, 0xe8, 0x01, 0xf6, 0xa8, 0xb6, 0x4d, 0x82, 0x04, 0x45, 0x6d, + 0xb4, 0xcf, 0xd7, 0x77, 0x67, 0xf9, 0x75, 0x9f, 0xf0, 0xe0, 0x1e, 0x51, + 0xee, 0x46, 0xfd, 0x0b, 0xc9, 0x93, 0x25, 0x55, 0x4a, 0xee, 0xe0, 0x16, + 0xd0, 0xdf, 0x8c, 0xfa, 0x2a, 0xa9, 0x49, 0xfd, 0x97, 0x1c, 0x0e, 0x22, + 0x13, 0x28, 0x7c, 0xaf, 0xc4, 0xfc, 0x9c, 0x12, 0x65, 0x8c, 0x4e, 0x5b, + 0x04, 0x75, 0x89, 0xc9, 0xb1, 0xed, 0x50, 0xca, 0x96, 0x6f, 0x1a, 0x7a, + 0xfe, 0x58, 0x5d, 0xec, 0x19, 0x4a, 0xf6, 0x35, 0x6a, 0x97, 0x14, 0x00, + 0x0e, 0xd0, 0x6b, 0xbb, 0xd5, 0x75, 0x55, 0x8b, 0x6e, 0x6b, 0x19, 0xa0, + 0xf8, 0x77, 0xd5, 0xa3}; + +// Returns true if non-empty, setting sPropName +bool TrimPropName(ByteString* sPropName) { + sPropName->Trim(); + return sPropName->GetLength() != 0; +} + +CJS_GlobalData* g_pInstance = nullptr; + +} // namespace + +// static +CJS_GlobalData* CJS_GlobalData::GetRetainedInstance( + CPDFSDK_FormFillEnvironment* pApp) { + if (!g_pInstance) { + g_pInstance = new CJS_GlobalData(); + } + ++g_pInstance->m_RefCount; + return g_pInstance; +} + +void CJS_GlobalData::Release() { + if (!--m_RefCount) { + delete g_pInstance; + g_pInstance = nullptr; + } +} + +CJS_GlobalData::CJS_GlobalData() + : m_RefCount(0), m_sFilePath(SDK_JS_GLOBALDATA_FILENAME) { + LoadGlobalPersistentVariables(); +} + +CJS_GlobalData::~CJS_GlobalData() { + SaveGlobalPersisitentVariables(); +} + +CJS_GlobalData::iterator CJS_GlobalData::FindGlobalVariable( + const ByteString& propname) { + for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end(); + ++it) { + if ((*it)->data.sKey == propname) + return it; + } + return m_arrayGlobalData.end(); +} + +CJS_GlobalData::const_iterator CJS_GlobalData::FindGlobalVariable( + const ByteString& propname) const { + for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end(); + ++it) { + if ((*it)->data.sKey == propname) + return it; + } + return m_arrayGlobalData.end(); +} + +CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable( + const ByteString& propname) { + auto iter = FindGlobalVariable(propname); + return iter != m_arrayGlobalData.end() ? iter->get() : nullptr; +} + +void CJS_GlobalData::SetGlobalVariableNumber(const ByteString& propname, + double dData) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return; + + if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { + pData->data.nType = JS_GlobalDataType::NUMBER; + pData->data.dData = dData; + return; + } + auto pNewData = pdfium::MakeUnique(); + pNewData->data.sKey = sPropName; + pNewData->data.nType = JS_GlobalDataType::NUMBER; + pNewData->data.dData = dData; + m_arrayGlobalData.push_back(std::move(pNewData)); +} + +void CJS_GlobalData::SetGlobalVariableBoolean(const ByteString& propname, + bool bData) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return; + + if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { + pData->data.nType = JS_GlobalDataType::BOOLEAN; + pData->data.bData = bData; + return; + } + auto pNewData = pdfium::MakeUnique(); + pNewData->data.sKey = sPropName; + pNewData->data.nType = JS_GlobalDataType::BOOLEAN; + pNewData->data.bData = bData; + m_arrayGlobalData.push_back(std::move(pNewData)); +} + +void CJS_GlobalData::SetGlobalVariableString(const ByteString& propname, + const ByteString& sData) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return; + + if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { + pData->data.nType = JS_GlobalDataType::STRING; + pData->data.sData = sData; + return; + } + auto pNewData = pdfium::MakeUnique(); + pNewData->data.sKey = sPropName; + pNewData->data.nType = JS_GlobalDataType::STRING; + pNewData->data.sData = sData; + m_arrayGlobalData.push_back(std::move(pNewData)); +} + +void CJS_GlobalData::SetGlobalVariableObject( + const ByteString& propname, + const CJS_GlobalVariableArray& array) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return; + + if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { + pData->data.nType = JS_GlobalDataType::OBJECT; + pData->data.objData.Copy(array); + return; + } + auto pNewData = pdfium::MakeUnique(); + pNewData->data.sKey = sPropName; + pNewData->data.nType = JS_GlobalDataType::OBJECT; + pNewData->data.objData.Copy(array); + m_arrayGlobalData.push_back(std::move(pNewData)); +} + +void CJS_GlobalData::SetGlobalVariableNull(const ByteString& propname) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return; + + if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) { + pData->data.nType = JS_GlobalDataType::NULLOBJ; + return; + } + auto pNewData = pdfium::MakeUnique(); + pNewData->data.sKey = sPropName; + pNewData->data.nType = JS_GlobalDataType::NULLOBJ; + m_arrayGlobalData.push_back(std::move(pNewData)); +} + +bool CJS_GlobalData::SetGlobalVariablePersistent(const ByteString& propname, + bool bPersistent) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return false; + + CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName); + if (!pData) + return false; + + pData->bPersistent = bPersistent; + return true; +} + +bool CJS_GlobalData::DeleteGlobalVariable(const ByteString& propname) { + ByteString sPropName(propname); + if (!TrimPropName(&sPropName)) + return false; + + auto iter = FindGlobalVariable(sPropName); + if (iter == m_arrayGlobalData.end()) + return false; + + m_arrayGlobalData.erase(iter); + return true; +} + +int32_t CJS_GlobalData::GetSize() const { + return pdfium::CollectionSize(m_arrayGlobalData); +} + +CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const { + if (index < 0 || index >= GetSize()) + return nullptr; + return m_arrayGlobalData[index].get(); +} + +void CJS_GlobalData::LoadGlobalPersistentVariables() { + uint8_t* pBuffer = nullptr; + int32_t nLength = 0; + + LoadFileBuffer(m_sFilePath.c_str(), pBuffer, nLength); + CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY)); + + if (pBuffer) { + uint8_t* p = pBuffer; + uint16_t wType = *((uint16_t*)p); + p += sizeof(uint16_t); + + if (wType == (uint16_t)(('X' << 8) | 'F')) { + uint16_t wVersion = *((uint16_t*)p); + p += sizeof(uint16_t); + + ASSERT(wVersion <= 2); + + uint32_t dwCount = *((uint32_t*)p); + p += sizeof(uint32_t); + + uint32_t dwSize = *((uint32_t*)p); + p += sizeof(uint32_t); + + if (dwSize == nLength - sizeof(uint16_t) * 2 - sizeof(uint32_t) * 2) { + for (int32_t i = 0, sz = dwCount; i < sz; i++) { + if (p > pBuffer + nLength) + break; + + uint32_t dwNameLen = *((uint32_t*)p); + p += sizeof(uint32_t); + + if (p + dwNameLen > pBuffer + nLength) + break; + + ByteString sEntry = ByteString(p, dwNameLen); + p += sizeof(char) * dwNameLen; + + JS_GlobalDataType wDataType = + static_cast(*((uint16_t*)p)); + p += sizeof(uint16_t); + + switch (wDataType) { + case JS_GlobalDataType::NUMBER: { + double dData = 0; + switch (wVersion) { + case 1: { + uint32_t dwData = *((uint32_t*)p); + p += sizeof(uint32_t); + dData = dwData; + } break; + case 2: { + dData = *((double*)p); + p += sizeof(double); + } break; + } + SetGlobalVariableNumber(sEntry, dData); + SetGlobalVariablePersistent(sEntry, true); + } break; + case JS_GlobalDataType::BOOLEAN: { + uint16_t wData = *((uint16_t*)p); + p += sizeof(uint16_t); + SetGlobalVariableBoolean(sEntry, (bool)(wData == 1)); + SetGlobalVariablePersistent(sEntry, true); + } break; + case JS_GlobalDataType::STRING: { + uint32_t dwLength = *((uint32_t*)p); + p += sizeof(uint32_t); + + if (p + dwLength > pBuffer + nLength) + break; + + SetGlobalVariableString(sEntry, ByteString(p, dwLength)); + SetGlobalVariablePersistent(sEntry, true); + p += sizeof(char) * dwLength; + } break; + case JS_GlobalDataType::NULLOBJ: { + SetGlobalVariableNull(sEntry); + SetGlobalVariablePersistent(sEntry, true); + } + case JS_GlobalDataType::OBJECT: + break; + } + } + } + } + FX_Free(pBuffer); + } +} + +void CJS_GlobalData::SaveGlobalPersisitentVariables() { + uint32_t nCount = 0; + CFX_BinaryBuf sData; + for (const auto& pElement : m_arrayGlobalData) { + if (pElement->bPersistent) { + CFX_BinaryBuf sElement; + MakeByteString(pElement->data.sKey, &pElement->data, sElement); + if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA) + break; + + sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize()); + nCount++; + } + } + + CFX_BinaryBuf sFile; + uint16_t wType = (uint16_t)(('X' << 8) | 'F'); + sFile.AppendBlock(&wType, sizeof(uint16_t)); + uint16_t wVersion = 2; + sFile.AppendBlock(&wVersion, sizeof(uint16_t)); + sFile.AppendBlock(&nCount, sizeof(uint32_t)); + uint32_t dwSize = sData.GetSize(); + sFile.AppendBlock(&dwSize, sizeof(uint32_t)); + + sFile.AppendBlock(sData.GetBuffer(), sData.GetSize()); + + CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, + sizeof(JS_RC4KEY)); + WriteFileBuffer(m_sFilePath.c_str(), + reinterpret_cast(sFile.GetBuffer()), sFile.GetSize()); +} + +void CJS_GlobalData::LoadFileBuffer(const wchar_t* sFilePath, + uint8_t*& pBuffer, + int32_t& nLength) { + // UnSupport. +} + +void CJS_GlobalData::WriteFileBuffer(const wchar_t* sFilePath, + const char* pBuffer, + int32_t nLength) { + // UnSupport. +} + +void CJS_GlobalData::MakeByteString(const ByteString& name, + CJS_KeyValue* pData, + CFX_BinaryBuf& sData) { + switch (pData->nType) { + case JS_GlobalDataType::NUMBER: { + uint32_t dwNameLen = (uint32_t)name.GetLength(); + sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); + sData.AppendString(name); + sData.AppendBlock(&pData->nType, sizeof(uint16_t)); + + double dData = pData->dData; + sData.AppendBlock(&dData, sizeof(double)); + } break; + case JS_GlobalDataType::BOOLEAN: { + uint32_t dwNameLen = (uint32_t)name.GetLength(); + sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); + sData.AppendString(name); + sData.AppendBlock(&pData->nType, sizeof(uint16_t)); + + uint16_t wData = (uint16_t)pData->bData; + sData.AppendBlock(&wData, sizeof(uint16_t)); + } break; + case JS_GlobalDataType::STRING: { + uint32_t dwNameLen = (uint32_t)name.GetLength(); + sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); + sData.AppendString(name); + sData.AppendBlock(&pData->nType, sizeof(uint16_t)); + + uint32_t dwDataLen = (uint32_t)pData->sData.GetLength(); + sData.AppendBlock(&dwDataLen, sizeof(uint32_t)); + sData.AppendString(pData->sData); + } break; + case JS_GlobalDataType::NULLOBJ: { + uint32_t dwNameLen = (uint32_t)name.GetLength(); + sData.AppendBlock(&dwNameLen, sizeof(uint32_t)); + sData.AppendString(name); + sData.AppendBlock(&pData->nType, sizeof(uint32_t)); + } break; + default: + break; + } +} diff --git a/fxjs/cjs_globaldata.h b/fxjs/cjs_globaldata.h new file mode 100644 index 0000000000000000000000000000000000000000..b9a4b2123ed7d67e284b43ea73144b63c29703ab --- /dev/null +++ b/fxjs/cjs_globaldata.h @@ -0,0 +1,77 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_GLOBALDATA_H_ +#define FXJS_CJS_GLOBALDATA_H_ + +#include +#include + +#include "core/fxcrt/cfx_binarybuf.h" +#include "fxjs/cjs_keyvalue.h" + +class CPDFSDK_FormFillEnvironment; + +class CJS_GlobalData_Element { + public: + CJS_GlobalData_Element() {} + ~CJS_GlobalData_Element() {} + + CJS_KeyValue data; + bool bPersistent; +}; + +class CJS_GlobalData { + public: + static CJS_GlobalData* GetRetainedInstance(CPDFSDK_FormFillEnvironment* pApp); + void Release(); + + void SetGlobalVariableNumber(const ByteString& propname, double dData); + void SetGlobalVariableBoolean(const ByteString& propname, bool bData); + void SetGlobalVariableString(const ByteString& propname, + const ByteString& sData); + void SetGlobalVariableObject(const ByteString& propname, + const CJS_GlobalVariableArray& array); + void SetGlobalVariableNull(const ByteString& propname); + bool SetGlobalVariablePersistent(const ByteString& propname, + bool bPersistent); + bool DeleteGlobalVariable(const ByteString& propname); + + int32_t GetSize() const; + CJS_GlobalData_Element* GetAt(int index) const; + + private: + using iterator = + std::vector>::iterator; + using const_iterator = + std::vector>::const_iterator; + + CJS_GlobalData(); + ~CJS_GlobalData(); + + void LoadGlobalPersistentVariables(); + void SaveGlobalPersisitentVariables(); + + CJS_GlobalData_Element* GetGlobalVariable(const ByteString& sPropname); + iterator FindGlobalVariable(const ByteString& sPropname); + const_iterator FindGlobalVariable(const ByteString& sPropname) const; + + void LoadFileBuffer(const wchar_t* sFilePath, + uint8_t*& pBuffer, + int32_t& nLength); + void WriteFileBuffer(const wchar_t* sFilePath, + const char* pBuffer, + int32_t nLength); + void MakeByteString(const ByteString& name, + CJS_KeyValue* pData, + CFX_BinaryBuf& sData); + + size_t m_RefCount; + std::vector> m_arrayGlobalData; + WideString m_sFilePath; +}; + +#endif // FXJS_CJS_GLOBALDATA_H_ diff --git a/fxjs/cjs_globalvariablearray.cpp b/fxjs/cjs_globalvariablearray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bf9f1b3052ffa5965bbaf5f44c5fed5b58da182 --- /dev/null +++ b/fxjs/cjs_globalvariablearray.cpp @@ -0,0 +1,68 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_globalvariablearray.h" + +#include "fxjs/cjs_keyvalue.h" + +CJS_GlobalVariableArray::CJS_GlobalVariableArray() {} + +CJS_GlobalVariableArray::~CJS_GlobalVariableArray() {} + +void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array) { + m_Array.clear(); + for (int i = 0, sz = array.Count(); i < sz; i++) { + CJS_KeyValue* pOldObjData = array.GetAt(i); + switch (pOldObjData->nType) { + case JS_GlobalDataType::NUMBER: { + CJS_KeyValue* pNewObjData = new CJS_KeyValue; + pNewObjData->sKey = pOldObjData->sKey; + pNewObjData->nType = pOldObjData->nType; + pNewObjData->dData = pOldObjData->dData; + Add(pNewObjData); + } break; + case JS_GlobalDataType::BOOLEAN: { + CJS_KeyValue* pNewObjData = new CJS_KeyValue; + pNewObjData->sKey = pOldObjData->sKey; + pNewObjData->nType = pOldObjData->nType; + pNewObjData->bData = pOldObjData->bData; + Add(pNewObjData); + } break; + case JS_GlobalDataType::STRING: { + CJS_KeyValue* pNewObjData = new CJS_KeyValue; + pNewObjData->sKey = pOldObjData->sKey; + pNewObjData->nType = pOldObjData->nType; + pNewObjData->sData = pOldObjData->sData; + Add(pNewObjData); + } break; + case JS_GlobalDataType::OBJECT: { + CJS_KeyValue* pNewObjData = new CJS_KeyValue; + pNewObjData->sKey = pOldObjData->sKey; + pNewObjData->nType = pOldObjData->nType; + pNewObjData->objData.Copy(pOldObjData->objData); + Add(pNewObjData); + } break; + case JS_GlobalDataType::NULLOBJ: { + CJS_KeyValue* pNewObjData = new CJS_KeyValue; + pNewObjData->sKey = pOldObjData->sKey; + pNewObjData->nType = pOldObjData->nType; + Add(pNewObjData); + } break; + } + } +} + +void CJS_GlobalVariableArray::Add(CJS_KeyValue* p) { + m_Array.push_back(std::unique_ptr(p)); +} + +int CJS_GlobalVariableArray::Count() const { + return m_Array.size(); +} + +CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const { + return m_Array.at(index).get(); +} diff --git a/fxjs/cjs_globalvariablearray.h b/fxjs/cjs_globalvariablearray.h new file mode 100644 index 0000000000000000000000000000000000000000..a249f60be98fa0cbece9b7f20ba1e59798c48c0b --- /dev/null +++ b/fxjs/cjs_globalvariablearray.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_GLOBALVARIABLEARRAY_H_ +#define FXJS_CJS_GLOBALVARIABLEARRAY_H_ + +#include +#include + +class CJS_KeyValue; + +class CJS_GlobalVariableArray { + public: + CJS_GlobalVariableArray(); + ~CJS_GlobalVariableArray(); + + void Add(CJS_KeyValue* p); + int Count() const; + CJS_KeyValue* GetAt(int index) const; + void Copy(const CJS_GlobalVariableArray& array); + + private: + std::vector> m_Array; +}; + +#endif // FXJS_CJS_GLOBALVARIABLEARRAY_H_ diff --git a/fxjs/cjs_highlight.cpp b/fxjs/cjs_highlight.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e60a5a819eaf2716b8063642739cf1e40f33eff8 --- /dev/null +++ b/fxjs/cjs_highlight.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_highlight.h" + +const JSConstSpec CJS_Highlight::ConstSpecs[] = { + {"n", JSConstSpec::String, 0, "none"}, + {"i", JSConstSpec::String, 0, "invert"}, + {"p", JSConstSpec::String, 0, "push"}, + {"o", JSConstSpec::String, 0, "outline"}}; + +int CJS_Highlight::ObjDefnID = -1; + +// static +void CJS_Highlight::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("highlight", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_highlight.h b/fxjs/cjs_highlight.h new file mode 100644 index 0000000000000000000000000000000000000000..74091d341d6d56cda2f86778b8cbb8833bbfdc80 --- /dev/null +++ b/fxjs/cjs_highlight.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_HIGHLIGHT_H_ +#define FXJS_CJS_HIGHLIGHT_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Highlight : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Highlight(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Highlight() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_HIGHLIGHT_H_ diff --git a/fxjs/cjs_icon.cpp b/fxjs/cjs_icon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b56f70cdcc97159bd2e2f921f9cc905e6e7a4a2 --- /dev/null +++ b/fxjs/cjs_icon.cpp @@ -0,0 +1,38 @@ +// 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 "fxjs/cjs_icon.h" + +const JSPropertySpec CJS_Icon::PropertySpecs[] = { + {"name", get_name_static, set_name_static}}; + +int CJS_Icon::ObjDefnID = -1; + +// static +int CJS_Icon::GetObjDefnID() { + return ObjDefnID; +} + +// static +void CJS_Icon::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("Icon", FXJSOBJTYPE_DYNAMIC, + JSConstructor, JSDestructor); + DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs)); +} + +Icon::Icon(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject), m_swIconName(L"") {} + +Icon::~Icon() {} + +CJS_Return Icon::get_name(CJS_Runtime* pRuntime) { + return CJS_Return(pRuntime->NewString(m_swIconName.c_str())); +} + +CJS_Return Icon::set_name(CJS_Runtime* pRuntime, v8::Local vp) { + return CJS_Return(false); +} diff --git a/fxjs/cjs_icon.h b/fxjs/cjs_icon.h new file mode 100644 index 0000000000000000000000000000000000000000..05b84384b3bbb9b11e52d00af9cba688b704bd71 --- /dev/null +++ b/fxjs/cjs_icon.h @@ -0,0 +1,42 @@ +// 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 FXJS_CJS_ICON_H_ +#define FXJS_CJS_ICON_H_ + +#include "fxjs/JS_Define.h" + +class Icon : public CJS_EmbedObj { + public: + explicit Icon(CJS_Object* pJSObject); + ~Icon() override; + + CJS_Return get_name(CJS_Runtime* pRuntime); + CJS_Return set_name(CJS_Runtime* pRuntime, v8::Local vp); + + WideString GetIconName() const { return m_swIconName; } + void SetIconName(WideString name) { m_swIconName = name; } + + private: + WideString m_swIconName; +}; + +class CJS_Icon : public CJS_Object { + public: + static int GetObjDefnID(); + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Icon(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Icon() override {} + + JS_STATIC_PROP(name, name, Icon); + + private: + static int ObjDefnID; + static const JSPropertySpec PropertySpecs[]; +}; + +#endif // FXJS_CJS_ICON_H_ diff --git a/fxjs/cjs_keyvalue.cpp b/fxjs/cjs_keyvalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fda3d6fb20997760ea98fe89cc14b20786add06 --- /dev/null +++ b/fxjs/cjs_keyvalue.cpp @@ -0,0 +1,11 @@ +// Copyright 2016 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 "fxjs/cjs_keyvalue.h" + +CJS_KeyValue::CJS_KeyValue() {} + +CJS_KeyValue::~CJS_KeyValue() {} diff --git a/fxjs/cjs_keyvalue.h b/fxjs/cjs_keyvalue.h new file mode 100644 index 0000000000000000000000000000000000000000..a1fd314de440c08dac9095e42714fa266ab927a0 --- /dev/null +++ b/fxjs/cjs_keyvalue.h @@ -0,0 +1,28 @@ +// Copyright 2016 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 FXJS_CJS_KEYVALUE_H_ +#define FXJS_CJS_KEYVALUE_H_ + +#include "core/fxcrt/fx_string.h" +#include "fxjs/cjs_globalvariablearray.h" + +enum class JS_GlobalDataType { NUMBER = 0, BOOLEAN, STRING, OBJECT, NULLOBJ }; + +class CJS_KeyValue { + public: + CJS_KeyValue(); + ~CJS_KeyValue(); + + ByteString sKey; + JS_GlobalDataType nType; + double dData; + bool bData; + ByteString sData; + CJS_GlobalVariableArray objData; +}; + +#endif // FXJS_CJS_KEYVALUE_H_ diff --git a/fxjs/cjs_object.cpp b/fxjs/cjs_object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1e5ce1c947972145402d8b0d0297a375f04ec02 --- /dev/null +++ b/fxjs/cjs_object.cpp @@ -0,0 +1,50 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_object.h" + +// static +void CJS_Object::DefineConsts(CFXJS_Engine* pEngine, + int objId, + const JSConstSpec consts[], + size_t count) { + for (size_t i = 0; i < count; ++i) { + pEngine->DefineObjConst( + objId, consts[i].pName, + consts[i].eType == JSConstSpec::Number + ? pEngine->NewNumber(consts[i].number).As() + : pEngine->NewString(consts[i].pStr).As()); + } +} + +// static +void CJS_Object::DefineProps(CFXJS_Engine* pEngine, + int objId, + const JSPropertySpec props[], + size_t count) { + for (size_t i = 0; i < count; ++i) { + pEngine->DefineObjProperty(objId, props[i].pName, props[i].pPropGet, + props[i].pPropPut); + } +} + +// static +void CJS_Object::DefineMethods(CFXJS_Engine* pEngine, + int objId, + const JSMethodSpec methods[], + size_t count) { + for (size_t i = 0; i < count; ++i) + pEngine->DefineObjMethod(objId, methods[i].pName, methods[i].pMethodCall); +} + +CJS_Object::CJS_Object(v8::Local pObject) { + m_pIsolate = pObject->GetIsolate(); + m_pV8Object.Reset(m_pIsolate, pObject); +} + +CJS_Object::~CJS_Object() {} + +void CJS_Object::InitInstance(IJS_Runtime* pIRuntime) {} diff --git a/fxjs/cjs_object.h b/fxjs/cjs_object.h new file mode 100644 index 0000000000000000000000000000000000000000..d929a014963a6c6db5a72938972850927318637a --- /dev/null +++ b/fxjs/cjs_object.h @@ -0,0 +1,71 @@ +// 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 FXJS_CJS_OBJECT_H_ +#define FXJS_CJS_OBJECT_H_ + +#include + +#include "fpdfsdk/fsdk_define.h" +#include "fxjs/cjs_embedobj.h" +#include "fxjs/cjs_runtime.h" +#include "fxjs/fxjs_v8.h" + +struct JSConstSpec { + enum Type { Number = 0, String = 1 }; + + const char* pName; + Type eType; + double number; + const char* pStr; +}; + +struct JSPropertySpec { + const char* pName; + v8::AccessorGetterCallback pPropGet; + v8::AccessorSetterCallback pPropPut; +}; + +struct JSMethodSpec { + const char* pName; + v8::FunctionCallback pMethodCall; +}; + +class CJS_Object { + public: + static void DefineConsts(CFXJS_Engine* pEngine, + int objId, + const JSConstSpec consts[], + size_t count); + static void DefineProps(CFXJS_Engine* pEngine, + int objId, + const JSPropertySpec props[], + size_t count); + static void DefineMethods(CFXJS_Engine* pEngine, + int objId, + const JSMethodSpec methods[], + size_t count); + + explicit CJS_Object(v8::Local pObject); + virtual ~CJS_Object(); + + virtual void InitInstance(IJS_Runtime* pIRuntime); + + v8::Local ToV8Object() { return m_pV8Object.Get(m_pIsolate); } + + // Takes ownership of |pObj|. + void SetEmbedObject(CJS_EmbedObj* pObj) { m_pEmbedObj.reset(pObj); } + CJS_EmbedObj* GetEmbedObject() const { return m_pEmbedObj.get(); } + + v8::Isolate* GetIsolate() const { return m_pIsolate; } + + protected: + std::unique_ptr m_pEmbedObj; + v8::Global m_pV8Object; + v8::Isolate* m_pIsolate; +}; + +#endif // FXJS_CJS_OBJECT_H_ diff --git a/fxjs/cjs_position.cpp b/fxjs/cjs_position.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16e4ab093b22814ff62aacd74ea0ff604433d799 --- /dev/null +++ b/fxjs/cjs_position.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_position.h" + +const JSConstSpec CJS_Position::ConstSpecs[] = { + {"textOnly", JSConstSpec::Number, 0, 0}, + {"iconOnly", JSConstSpec::Number, 1, 0}, + {"iconTextV", JSConstSpec::Number, 2, 0}, + {"textIconV", JSConstSpec::Number, 3, 0}, + {"iconTextH", JSConstSpec::Number, 4, 0}, + {"textIconH", JSConstSpec::Number, 5, 0}, + {"overlay", JSConstSpec::Number, 6, 0}}; + +int CJS_Position::ObjDefnID = -1; + +// static +void CJS_Position::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("position", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_position.h b/fxjs/cjs_position.h new file mode 100644 index 0000000000000000000000000000000000000000..7557f01ab790d54dd1b8751d6f7e146c8a788f4a --- /dev/null +++ b/fxjs/cjs_position.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_POSITION_H_ +#define FXJS_CJS_POSITION_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Position : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Position(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Position() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_POSITION_H_ diff --git a/fxjs/cjs_printparamsobj.cpp b/fxjs/cjs_printparamsobj.cpp new file mode 100644 index 0000000000000000000000000000000000000000..296c2417361a9a447a78daf3788d84a23e51d01e --- /dev/null +++ b/fxjs/cjs_printparamsobj.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_printparamsobj.h" + +int CJS_PrintParamsObj::ObjDefnID = -1; + +// static +int CJS_PrintParamsObj::GetObjDefnID() { + return ObjDefnID; +} + +// static +void CJS_PrintParamsObj::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("PrintParamsObj", FXJSOBJTYPE_DYNAMIC, + JSConstructor, + JSDestructor); +} + +PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject) { + bUI = true; + nStart = 0; + nEnd = 0; + bSilent = false; + bShrinkToFit = false; + bPrintAsImage = false; + bReverse = false; + bAnnotations = true; +} diff --git a/fxjs/cjs_printparamsobj.h b/fxjs/cjs_printparamsobj.h new file mode 100644 index 0000000000000000000000000000000000000000..a0c91b0d438c94a2d389a324ee07a8615783a6c1 --- /dev/null +++ b/fxjs/cjs_printparamsobj.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_PRINTPARAMSOBJ_H_ +#define FXJS_CJS_PRINTPARAMSOBJ_H_ + +#include "fxjs/JS_Define.h" + +class PrintParamsObj : public CJS_EmbedObj { + public: + explicit PrintParamsObj(CJS_Object* pJSObject); + ~PrintParamsObj() override {} + + public: + bool bUI; + int nStart; + int nEnd; + bool bSilent; + bool bShrinkToFit; + bool bPrintAsImage; + bool bReverse; + bool bAnnotations; +}; + +class CJS_PrintParamsObj : public CJS_Object { + public: + static int GetObjDefnID(); + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_PrintParamsObj(v8::Local pObject) + : CJS_Object(pObject) {} + ~CJS_PrintParamsObj() override {} + + private: + static int ObjDefnID; +}; + +#endif // FXJS_CJS_PRINTPARAMSOBJ_H_ diff --git a/fxjs/cjs_publicmethods.cpp b/fxjs/cjs_publicmethods.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45eae7f8d272949e2e8aeef3ac4458d2a5502322 --- /dev/null +++ b/fxjs/cjs_publicmethods.cpp @@ -0,0 +1,1740 @@ +// 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 "fxjs/cjs_publicmethods.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/fpdfdoc/cpdf_interform.h" +#include "core/fxcrt/fx_extension.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_color.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_field.h" +#include "fxjs/cjs_object.h" +#include "fxjs/cjs_runtime.h" +#include "fxjs/cjs_util.h" +#include "fxjs/js_resources.h" + +// static +const JSMethodSpec CJS_PublicMethods::GlobalFunctionSpecs[] = { + {"AFNumber_Format", AFNumber_Format_static}, + {"AFNumber_Keystroke", AFNumber_Keystroke_static}, + {"AFPercent_Format", AFPercent_Format_static}, + {"AFPercent_Keystroke", AFPercent_Keystroke_static}, + {"AFDate_FormatEx", AFDate_FormatEx_static}, + {"AFDate_KeystrokeEx", AFDate_KeystrokeEx_static}, + {"AFDate_Format", AFDate_Format_static}, + {"AFDate_Keystroke", AFDate_Keystroke_static}, + {"AFTime_FormatEx", AFTime_FormatEx_static}, + {"AFTime_KeystrokeEx", AFTime_KeystrokeEx_static}, + {"AFTime_Format", AFTime_Format_static}, + {"AFTime_Keystroke", AFTime_Keystroke_static}, + {"AFSpecial_Format", AFSpecial_Format_static}, + {"AFSpecial_Keystroke", AFSpecial_Keystroke_static}, + {"AFSpecial_KeystrokeEx", AFSpecial_KeystrokeEx_static}, + {"AFSimple", AFSimple_static}, + {"AFMakeNumber", AFMakeNumber_static}, + {"AFSimple_Calculate", AFSimple_Calculate_static}, + {"AFRange_Validate", AFRange_Validate_static}, + {"AFMergeChange", AFMergeChange_static}, + {"AFParseDateEx", AFParseDateEx_static}, + {"AFExtractNums", AFExtractNums_static}, +}; + +namespace { + +#if _FX_OS_ != _FX_OS_ANDROID_ +constexpr double kDoubleCorrect = 0.000000000000001; +#endif + +const wchar_t* const kMonths[] = {L"Jan", L"Feb", L"Mar", L"Apr", + L"May", L"Jun", L"Jul", L"Aug", + L"Sep", L"Oct", L"Nov", L"Dec"}; + +const wchar_t* const kFullMonths[] = {L"January", L"February", L"March", + L"April", L"May", L"June", + L"July", L"August", L"September", + L"October", L"November", L"December"}; + +template +T StrTrim(const T& str) { + T result = str; + result.Trim(' '); + return result; +} + +void AlertIfPossible(CJS_EventContext* pContext, const wchar_t* swMsg) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = pContext->GetFormFillEnv(); + if (pFormFillEnv) + pFormFillEnv->JS_appAlert(swMsg, nullptr, 0, 3); +} + +#if _FX_OS_ != _FX_OS_ANDROID_ +ByteString CalculateString(double dValue, + int iDec, + int* iDec2, + bool* bNegative) { + *bNegative = dValue < 0; + if (*bNegative) + dValue = -dValue; + + // Make sure the number of precision characters will fit. + iDec = std::min(iDec, std::numeric_limits::digits10); + + std::stringstream ss; + ss << std::fixed << std::setprecision(iDec) << dValue; + std::string value = ss.str(); + size_t pos = value.find('.'); + *iDec2 = pos == std::string::npos ? value.size() : static_cast(pos); + return ByteString(value.c_str()); +} +#endif + +WideString CalcMergedString(const CJS_EventHandler* event, + const WideString& value, + const WideString& change) { + WideString prefix = value.Left(event->SelStart()); + WideString postfix; + int end = event->SelEnd(); + if (end >= 0 && static_cast(end) < value.GetLength()) + postfix = value.Right(value.GetLength() - static_cast(end)); + return prefix + change + postfix; +} + +template >&)> +void JSGlobalFunc(const char* func_name_string, + const v8::FunctionCallbackInfo& info) { + CJS_Runtime* pRuntime = + CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); + if (!pRuntime) + return; + + std::vector> parameters; + for (int i = 0; i < info.Length(); ++i) + parameters.push_back(info[i]); + + CJS_Return result = (*F)(pRuntime, parameters); + if (result.HasError()) { + pRuntime->Error( + JSFormatErrorString(func_name_string, nullptr, result.Error())); + return; + } + + if (result.HasReturn()) + info.GetReturnValue().Set(result.Return()); +} + +int WithinBoundsOrZero(int value, size_t size) { + return value >= 0 && static_cast(value) < size ? value : 0; +} + +int ValidStyleOrZero(int style) { + return WithinBoundsOrZero(style, 4); +} + +bool IsDigitSeparatorOrDecimalMark(int c) { + return c == '.' || c == ','; +} + +#if _FX_OS_ != _FX_OS_ANDROID_ +bool IsStyleWithDigitSeparator(int style) { + return style == 0 || style == 2; +} + +char DigitSeparatorForStyle(int style) { + ASSERT(IsStyleWithDigitSeparator(style)); + return style == 0 ? ',' : '.'; +} +#endif + +bool IsStyleWithCommaDecimalMark(int style) { + return style >= 2; +} + +char DecimalMarkForStyle(int style) { + return IsStyleWithCommaDecimalMark(style) ? ',' : '.'; +} + +#if _FX_OS_ != _FX_OS_ANDROID_ +void NormalizeDecimalMark(ByteString* str) { + str->Replace(",", "."); +} +#endif + +void NormalizeDecimalMarkW(WideString* str) { + str->Replace(L",", L"."); +} + +bool IsValidMonth(int m) { + return m >= 1 && m <= 12; +} + +// TODO(thestig): Should this take the month into consideration? +bool IsValidDay(int d) { + return d >= 1 && d <= 31; +} + +// TODO(thestig): Should 24 be allowed? Similarly, 60 for minutes and seconds. +bool IsValid24Hour(int h) { + return h >= 0 && h <= 24; +} + +bool IsValidMinute(int m) { + return m >= 0 && m <= 60; +} + +bool IsValidSecond(int s) { + return s >= 0 && s <= 60; +} + +} // namespace + +CJS_PublicMethods::CJS_PublicMethods(v8::Local pObject) + : CJS_Object(pObject) {} + +CJS_PublicMethods::~CJS_PublicMethods() {} + +// static +void CJS_PublicMethods::DefineJSObjects(CFXJS_Engine* pEngine) { + for (const auto& spec : GlobalFunctionSpecs) + pEngine->DefineGlobalMethod(spec.pName, spec.pMethodCall); +} + +#define JS_STATIC_GLOBAL_FUN(fun_name) \ + void CJS_PublicMethods::fun_name##_static( \ + const v8::FunctionCallbackInfo& info) { \ + JSGlobalFunc(#fun_name, info); \ + } + +JS_STATIC_GLOBAL_FUN(AFNumber_Format); +JS_STATIC_GLOBAL_FUN(AFNumber_Keystroke); +JS_STATIC_GLOBAL_FUN(AFPercent_Format); +JS_STATIC_GLOBAL_FUN(AFPercent_Keystroke); +JS_STATIC_GLOBAL_FUN(AFDate_FormatEx); +JS_STATIC_GLOBAL_FUN(AFDate_KeystrokeEx); +JS_STATIC_GLOBAL_FUN(AFDate_Format); +JS_STATIC_GLOBAL_FUN(AFDate_Keystroke); +JS_STATIC_GLOBAL_FUN(AFTime_FormatEx); +JS_STATIC_GLOBAL_FUN(AFTime_KeystrokeEx); +JS_STATIC_GLOBAL_FUN(AFTime_Format); +JS_STATIC_GLOBAL_FUN(AFTime_Keystroke); +JS_STATIC_GLOBAL_FUN(AFSpecial_Format); +JS_STATIC_GLOBAL_FUN(AFSpecial_Keystroke); +JS_STATIC_GLOBAL_FUN(AFSpecial_KeystrokeEx); +JS_STATIC_GLOBAL_FUN(AFSimple); +JS_STATIC_GLOBAL_FUN(AFMakeNumber); +JS_STATIC_GLOBAL_FUN(AFSimple_Calculate); +JS_STATIC_GLOBAL_FUN(AFRange_Validate); +JS_STATIC_GLOBAL_FUN(AFMergeChange); +JS_STATIC_GLOBAL_FUN(AFParseDateEx); +JS_STATIC_GLOBAL_FUN(AFExtractNums); + +bool CJS_PublicMethods::IsNumber(const WideString& str) { + WideString sTrim = StrTrim(str); + const wchar_t* pTrim = sTrim.c_str(); + const wchar_t* p = pTrim; + bool bDot = false; + bool bKXJS = false; + + wchar_t c; + while ((c = *p) != L'\0') { + if (IsDigitSeparatorOrDecimalMark(c)) { + if (bDot) + return false; + bDot = true; + } else if (c == L'-' || c == L'+') { + if (p != pTrim) + return false; + } else if (c == L'e' || c == L'E') { + if (bKXJS) + return false; + + p++; + c = *p; + if (c != L'+' && c != L'-') + return false; + bKXJS = true; + } else if (!std::iswdigit(c)) { + return false; + } + p++; + } + + return true; +} + +bool CJS_PublicMethods::MaskSatisfied(wchar_t c_Change, wchar_t c_Mask) { + switch (c_Mask) { + case L'9': + return !!std::iswdigit(c_Change); + case L'A': + return FXSYS_iswalpha(c_Change); + case L'O': + return FXSYS_iswalnum(c_Change); + case L'X': + return true; + default: + return (c_Change == c_Mask); + } +} + +bool CJS_PublicMethods::IsReservedMaskChar(wchar_t ch) { + return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X'; +} + +double CJS_PublicMethods::AF_Simple(const wchar_t* sFuction, + double dValue1, + double dValue2) { + if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 || + FXSYS_wcsicmp(sFuction, L"SUM") == 0) { + return dValue1 + dValue2; + } + if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) + return dValue1 * dValue2; + if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) + return std::min(dValue1, dValue2); + if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) + return std::max(dValue1, dValue2); + return dValue1; +} + +v8::Local CJS_PublicMethods::AF_MakeArrayFromList( + CJS_Runtime* pRuntime, + v8::Local val) { + if (!val.IsEmpty() && val->IsArray()) + return pRuntime->ToArray(val); + + WideString wsStr = pRuntime->ToWideString(val); + ByteString t = ByteString::FromUnicode(wsStr); + const char* p = t.c_str(); + + int nIndex = 0; + v8::Local StrArray = pRuntime->NewArray(); + while (*p) { + const char* pTemp = strchr(p, ','); + if (!pTemp) { + pRuntime->PutArrayElement( + StrArray, nIndex, + pRuntime->NewString(StrTrim(ByteString(p)).c_str())); + break; + } + + pRuntime->PutArrayElement( + StrArray, nIndex, + pRuntime->NewString(StrTrim(ByteString(p, pTemp - p)).c_str())); + + nIndex++; + p = ++pTemp; + } + return StrArray; +} + +int CJS_PublicMethods::ParseStringInteger(const WideString& str, + size_t nStart, + size_t* pSkip, + size_t nMaxStep) { + int nRet = 0; + size_t nSkip = 0; + for (size_t i = nStart; i < str.GetLength(); ++i) { + if (i - nStart > 10) + break; + + wchar_t c = str[i]; + if (!std::iswdigit(c)) + break; + + nRet = nRet * 10 + FXSYS_DecimalCharToInt(c); + ++nSkip; + if (nSkip >= nMaxStep) + break; + } + + *pSkip = nSkip; + return nRet; +} + +WideString CJS_PublicMethods::ParseStringString(const WideString& str, + size_t nStart, + size_t* pSkip) { + WideString swRet; + swRet.Reserve(str.GetLength()); + for (size_t i = nStart; i < str.GetLength(); ++i) { + wchar_t c = str[i]; + if (!std::iswdigit(c)) + break; + + swRet += c; + } + + *pSkip = swRet.GetLength(); + return swRet; +} + +double CJS_PublicMethods::ParseNormalDate(const WideString& value, + bool* bWrongFormat) { + double dt = JS_GetDateTime(); + + int nYear = JS_GetYearFromTime(dt); + int nMonth = JS_GetMonthFromTime(dt) + 1; + int nDay = JS_GetDayFromTime(dt); + int nHour = JS_GetHourFromTime(dt); + int nMin = JS_GetMinFromTime(dt); + int nSec = JS_GetSecFromTime(dt); + + int number[3]; + + size_t nSkip = 0; + size_t nLen = value.GetLength(); + size_t nIndex = 0; + size_t i = 0; + while (i < nLen) { + if (nIndex > 2) + break; + + wchar_t c = value[i]; + if (std::iswdigit(c)) { + number[nIndex++] = ParseStringInteger(value, i, &nSkip, 4); + i += nSkip; + } else { + i++; + } + } + + if (nIndex == 2) { + // TODO(thestig): Should the else case set |bWrongFormat| to true? + // case2: month/day + // case3: day/month + if (IsValidMonth(number[0]) && IsValidDay(number[1])) { + nMonth = number[0]; + nDay = number[1]; + } else if (IsValidDay(number[0]) && IsValidMonth(number[1])) { + nDay = number[0]; + nMonth = number[1]; + } + + if (bWrongFormat) + *bWrongFormat = false; + } else if (nIndex == 3) { + // TODO(thestig): Should the else case set |bWrongFormat| to true? + // case1: year/month/day + // case2: month/day/year + // case3: day/month/year + if (number[0] > 12 && IsValidMonth(number[1]) && IsValidDay(number[2])) { + nYear = number[0]; + nMonth = number[1]; + nDay = number[2]; + } else if (IsValidMonth(number[0]) && IsValidDay(number[1]) && + number[2] > 31) { + nMonth = number[0]; + nDay = number[1]; + nYear = number[2]; + } else if (IsValidDay(number[0]) && IsValidMonth(number[1]) && + number[2] > 31) { + nDay = number[0]; + nMonth = number[1]; + nYear = number[2]; + } + + if (bWrongFormat) + *bWrongFormat = false; + } else { + if (bWrongFormat) + *bWrongFormat = true; + return dt; + } + + // TODO(thestig): Should we set |bWrongFormat| to false here too? + return JS_DateParse(WideString::Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, + nYear, nHour, nMin, nSec)); +} + +double CJS_PublicMethods::MakeRegularDate(const WideString& value, + const WideString& format, + bool* bWrongFormat) { + double dt = JS_GetDateTime(); + + if (format.IsEmpty() || value.IsEmpty()) + return dt; + + int nYear = JS_GetYearFromTime(dt); + int nMonth = JS_GetMonthFromTime(dt) + 1; + int nDay = JS_GetDayFromTime(dt); + int nHour = JS_GetHourFromTime(dt); + int nMin = JS_GetMinFromTime(dt); + int nSec = JS_GetSecFromTime(dt); + + int nYearSub = 99; // nYear - 2000; + + bool bPm = false; + bool bExit = false; + bool bBadFormat = false; + + size_t i = 0; + size_t j = 0; + + while (i < format.GetLength()) { + if (bExit) + break; + + wchar_t c = format[i]; + switch (c) { + case ':': + case '.': + case '-': + case '\\': + case '/': + i++; + j++; + break; + + case 'y': + case 'm': + case 'd': + case 'H': + case 'h': + case 'M': + case 's': + case 't': { + size_t oldj = j; + size_t nSkip = 0; + size_t remaining = format.GetLength() - i - 1; + + if (remaining == 0 || format[i + 1] != c) { + switch (c) { + case 'y': + i++; + j++; + break; + case 'm': + nMonth = ParseStringInteger(value, j, &nSkip, 2); + i++; + j += nSkip; + break; + case 'd': + nDay = ParseStringInteger(value, j, &nSkip, 2); + i++; + j += nSkip; + break; + case 'H': + nHour = ParseStringInteger(value, j, &nSkip, 2); + i++; + j += nSkip; + break; + case 'h': + nHour = ParseStringInteger(value, j, &nSkip, 2); + i++; + j += nSkip; + break; + case 'M': + nMin = ParseStringInteger(value, j, &nSkip, 2); + i++; + j += nSkip; + break; + case 's': + nSec = ParseStringInteger(value, j, &nSkip, 2); + i++; + j += nSkip; + break; + case 't': + bPm = (j < value.GetLength() && value[j] == 'p'); + i++; + j++; + break; + } + } else if (remaining == 1 || format[i + 2] != c) { + switch (c) { + case 'y': + nYear = ParseStringInteger(value, j, &nSkip, 4); + i += 2; + j += nSkip; + break; + case 'm': + nMonth = ParseStringInteger(value, j, &nSkip, 2); + i += 2; + j += nSkip; + break; + case 'd': + nDay = ParseStringInteger(value, j, &nSkip, 2); + i += 2; + j += nSkip; + break; + case 'H': + nHour = ParseStringInteger(value, j, &nSkip, 2); + i += 2; + j += nSkip; + break; + case 'h': + nHour = ParseStringInteger(value, j, &nSkip, 2); + i += 2; + j += nSkip; + break; + case 'M': + nMin = ParseStringInteger(value, j, &nSkip, 2); + i += 2; + j += nSkip; + break; + case 's': + nSec = ParseStringInteger(value, j, &nSkip, 2); + i += 2; + j += nSkip; + break; + case 't': + bPm = (j + 1 < value.GetLength() && value[j] == 'p' && + value[j + 1] == 'm'); + i += 2; + j += 2; + break; + } + } else if (remaining == 2 || format[i + 3] != c) { + switch (c) { + case 'm': { + WideString sMonth = ParseStringString(value, j, &nSkip); + bool bFind = false; + for (int m = 0; m < 12; m++) { + if (sMonth.CompareNoCase(kMonths[m]) == 0) { + nMonth = m + 1; + i += 3; + j += nSkip; + bFind = true; + break; + } + } + + if (!bFind) { + nMonth = ParseStringInteger(value, j, &nSkip, 3); + i += 3; + j += nSkip; + } + } break; + case 'y': + break; + default: + i += 3; + j += 3; + break; + } + } else if (remaining == 3 || format[i + 4] != c) { + switch (c) { + case 'y': + nYear = ParseStringInteger(value, j, &nSkip, 4); + j += nSkip; + i += 4; + break; + case 'm': { + bool bFind = false; + + WideString sMonth = ParseStringString(value, j, &nSkip); + sMonth.MakeLower(); + + for (int m = 0; m < 12; m++) { + WideString sFullMonths = kFullMonths[m]; + sFullMonths.MakeLower(); + + if (sFullMonths.Contains(sMonth.c_str())) { + nMonth = m + 1; + i += 4; + j += nSkip; + bFind = true; + break; + } + } + + if (!bFind) { + nMonth = ParseStringInteger(value, j, &nSkip, 4); + i += 4; + j += nSkip; + } + } break; + default: + i += 4; + j += 4; + break; + } + } else { + if (j >= value.GetLength() || format[i] != value[j]) { + bBadFormat = true; + bExit = true; + } + i++; + j++; + } + + if (oldj == j) { + bBadFormat = true; + bExit = true; + } + break; + } + + default: + if (value.GetLength() <= j) { + bExit = true; + } else if (format[i] != value[j]) { + bBadFormat = true; + bExit = true; + } + + i++; + j++; + break; + } + } + + if (bPm) + nHour += 12; + + if (nYear >= 0 && nYear <= nYearSub) + nYear += 2000; + + if (!bBadFormat) { + bBadFormat = !IsValidMonth(nMonth) || !IsValidDay(nDay) || + !IsValid24Hour(nHour) || !IsValidMinute(nMin) || + !IsValidSecond(nSec); + } + + double dRet; + if (bBadFormat) { + dRet = ParseNormalDate(value, &bBadFormat); + } else { + dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay), + JS_MakeTime(nHour, nMin, nSec, 0)); + if (std::isnan(dRet)) + dRet = JS_DateParse(value); + } + + if (std::isnan(dRet)) + dRet = ParseNormalDate(value, &bBadFormat); + + if (bWrongFormat) + *bWrongFormat = bBadFormat; + + return dRet; +} + +WideString CJS_PublicMethods::MakeFormatDate(double dDate, + const WideString& format) { + WideString sRet; + WideString sPart; + + int nYear = JS_GetYearFromTime(dDate); + int nMonth = JS_GetMonthFromTime(dDate) + 1; + int nDay = JS_GetDayFromTime(dDate); + int nHour = JS_GetHourFromTime(dDate); + int nMin = JS_GetMinFromTime(dDate); + int nSec = JS_GetSecFromTime(dDate); + + size_t i = 0; + while (i < format.GetLength()) { + wchar_t c = format[i]; + size_t remaining = format.GetLength() - i - 1; + sPart.clear(); + switch (c) { + case 'y': + case 'm': + case 'd': + case 'H': + case 'h': + case 'M': + case 's': + case 't': + if (remaining == 0 || format[i + 1] != c) { + switch (c) { + case 'y': + sPart += c; + break; + case 'm': + sPart = WideString::Format(L"%d", nMonth); + break; + case 'd': + sPart = WideString::Format(L"%d", nDay); + break; + case 'H': + sPart = WideString::Format(L"%d", nHour); + break; + case 'h': + sPart = + WideString::Format(L"%d", nHour > 12 ? nHour - 12 : nHour); + break; + case 'M': + sPart = WideString::Format(L"%d", nMin); + break; + case 's': + sPart = WideString::Format(L"%d", nSec); + break; + case 't': + sPart += nHour > 12 ? 'p' : 'a'; + break; + } + i++; + } else if (remaining == 1 || format[i + 2] != c) { + switch (c) { + case 'y': + sPart = WideString::Format(L"%02d", nYear - (nYear / 100) * 100); + break; + case 'm': + sPart = WideString::Format(L"%02d", nMonth); + break; + case 'd': + sPart = WideString::Format(L"%02d", nDay); + break; + case 'H': + sPart = WideString::Format(L"%02d", nHour); + break; + case 'h': + sPart = + WideString::Format(L"%02d", nHour > 12 ? nHour - 12 : nHour); + break; + case 'M': + sPart = WideString::Format(L"%02d", nMin); + break; + case 's': + sPart = WideString::Format(L"%02d", nSec); + break; + case 't': + sPart = nHour > 12 ? L"pm" : L"am"; + break; + } + i += 2; + } else if (remaining == 2 || format[i + 3] != c) { + switch (c) { + case 'm': + i += 3; + if (IsValidMonth(nMonth)) + sPart += kMonths[nMonth - 1]; + break; + default: + i += 3; + sPart += c; + sPart += c; + sPart += c; + break; + } + } else if (remaining == 3 || format[i + 4] != c) { + switch (c) { + case 'y': + sPart = WideString::Format(L"%04d", nYear); + i += 4; + break; + case 'm': + i += 4; + if (IsValidMonth(nMonth)) + sPart += kFullMonths[nMonth - 1]; + break; + default: + i += 4; + sPart += c; + sPart += c; + sPart += c; + sPart += c; + break; + } + } else { + i++; + sPart += c; + } + break; + default: + i++; + sPart += c; + break; + } + + sRet += sPart; + } + + return sRet; +} + +// function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency, +// bCurrencyPrepend) +CJS_Return CJS_PublicMethods::AFNumber_Format( + CJS_Runtime* pRuntime, + const std::vector>& params) { +#if _FX_OS_ != _FX_OS_ANDROID_ + if (params.size() != 6) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + WideString& Value = pEvent->Value(); + ByteString strValue = StrTrim(ByteString::FromUnicode(Value)); + if (strValue.IsEmpty()) + return CJS_Return(true); + + int iDec = abs(pRuntime->ToInt32(params[0])); + int iSepStyle = ValidStyleOrZero(pRuntime->ToInt32(params[1])); + int iNegStyle = ValidStyleOrZero(pRuntime->ToInt32(params[2])); + // params[3] is iCurrStyle, it's not used. + WideString wstrCurrency = pRuntime->ToWideString(params[4]); + bool bCurrencyPrepend = pRuntime->ToBoolean(params[5]); + + // Processing decimal places + NormalizeDecimalMark(&strValue); + double dValue = atof(strValue.c_str()); + if (iDec > 0) + dValue += kDoubleCorrect; + + // Calculating number string + bool bNegative; + int iDec2; + strValue = CalculateString(dValue, iDec, &iDec2, &bNegative); + if (strValue.IsEmpty()) { + dValue = 0; + strValue = CalculateString(dValue, iDec, &iDec2, &bNegative); + if (strValue.IsEmpty()) { + strValue = "0"; + iDec2 = 1; + } + } + ASSERT(iDec2 >= 0); + + // Processing separator style + if (static_cast(iDec2) < strValue.GetLength()) { + if (IsStyleWithCommaDecimalMark(iSepStyle)) + strValue.Replace(".", ","); + + if (iDec2 == 0) + strValue.Insert(iDec2, '0'); + } + if (IsStyleWithDigitSeparator(iSepStyle)) { + char cSeparator = DigitSeparatorForStyle(iSepStyle); + for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) + strValue.Insert(iDecPositive, cSeparator); + } + + // Processing currency string + Value = WideString::FromLocal(strValue.AsStringView()); + if (bCurrencyPrepend) + Value = wstrCurrency + Value; + else + Value = Value + wstrCurrency; + + // Processing negative style + if (bNegative) { + if (iNegStyle == 0) { + Value.InsertAtFront(L'-'); + } else if (iNegStyle == 2 || iNegStyle == 3) { + Value.InsertAtFront(L'('); + Value += L')'; + } + if (iNegStyle == 1 || iNegStyle == 3) { + if (Field* fTarget = pEvent->Target_Field()) { + v8::Local arColor = pRuntime->NewArray(); + pRuntime->PutArrayElement(arColor, 0, pRuntime->NewString(L"RGB")); + pRuntime->PutArrayElement(arColor, 1, pRuntime->NewNumber(1)); + pRuntime->PutArrayElement(arColor, 2, pRuntime->NewNumber(0)); + pRuntime->PutArrayElement(arColor, 3, pRuntime->NewNumber(0)); + fTarget->set_text_color(pRuntime, arColor); + } + } + } else { + if (iNegStyle == 1 || iNegStyle == 3) { + if (Field* fTarget = pEvent->Target_Field()) { + v8::Local arColor = pRuntime->NewArray(); + pRuntime->PutArrayElement(arColor, 0, pRuntime->NewString(L"RGB")); + pRuntime->PutArrayElement(arColor, 1, pRuntime->NewNumber(0)); + pRuntime->PutArrayElement(arColor, 2, pRuntime->NewNumber(0)); + pRuntime->PutArrayElement(arColor, 3, pRuntime->NewNumber(0)); + + CJS_Return result = fTarget->get_text_color(pRuntime); + CFX_Color crProp = color::ConvertArrayToPWLColor( + pRuntime, pRuntime->ToArray(result.Return())); + CFX_Color crColor = color::ConvertArrayToPWLColor(pRuntime, arColor); + if (crColor != crProp) + fTarget->set_text_color(pRuntime, arColor); + } + } + } +#endif + return CJS_Return(true); +} + +// function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency, +// bCurrencyPrepend) +CJS_Return CJS_PublicMethods::AFNumber_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 2) + return CJS_Return(false); + + CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); + CJS_EventHandler* pEvent = pContext->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + WideString& val = pEvent->Value(); + WideString& wstrChange = pEvent->Change(); + WideString wstrValue = val; + + if (pEvent->WillCommit()) { + WideString swTemp = StrTrim(wstrValue); + if (swTemp.IsEmpty()) + return CJS_Return(true); + + NormalizeDecimalMarkW(&swTemp); + if (!IsNumber(swTemp.c_str())) { + pEvent->Rc() = false; + WideString sError = JSGetStringFromID(JSMessage::kInvalidInputError); + AlertIfPossible(pContext, sError.c_str()); + return CJS_Return(sError); + } + // It happens after the last keystroke and before validating, + return CJS_Return(true); + } + + WideString wstrSelected; + if (pEvent->SelStart() != -1) { + wstrSelected = wstrValue.Mid(pEvent->SelStart(), + pEvent->SelEnd() - pEvent->SelStart()); + } + + bool bHasSign = wstrValue.Contains(L'-') && !wstrSelected.Contains(L'-'); + if (bHasSign) { + // can't insert "change" in front to sign postion. + if (pEvent->SelStart() == 0) { + pEvent->Rc() = false; + return CJS_Return(true); + } + } + + int iSepStyle = ValidStyleOrZero(pRuntime->ToInt32(params[1])); + const wchar_t cSep = DecimalMarkForStyle(iSepStyle); + + bool bHasSep = wstrValue.Contains(cSep); + for (size_t i = 0; i < wstrChange.GetLength(); ++i) { + if (wstrChange[i] == cSep) { + if (bHasSep) { + pEvent->Rc() = false; + return CJS_Return(true); + } + bHasSep = true; + continue; + } + if (wstrChange[i] == L'-') { + if (bHasSign) { + pEvent->Rc() = false; + return CJS_Return(true); + } + // sign's position is not correct + if (i != 0) { + pEvent->Rc() = false; + return CJS_Return(true); + } + if (pEvent->SelStart() != 0) { + pEvent->Rc() = false; + return CJS_Return(true); + } + bHasSign = true; + continue; + } + + if (!std::iswdigit(wstrChange[i])) { + pEvent->Rc() = false; + return CJS_Return(true); + } + } + + val = CalcMergedString(pEvent, wstrValue, wstrChange); + return CJS_Return(true); +} + +// function AFPercent_Format(nDec, sepStyle) +CJS_Return CJS_PublicMethods::AFPercent_Format( + CJS_Runtime* pRuntime, + const std::vector>& params) { +#if _FX_OS_ != _FX_OS_ANDROID_ + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + WideString& Value = pEvent->Value(); + ByteString strValue = StrTrim(ByteString::FromUnicode(Value)); + if (strValue.IsEmpty()) + return CJS_Return(true); + + int iDec = abs(pRuntime->ToInt32(params[0])); + int iSepStyle = ValidStyleOrZero(pRuntime->ToInt32(params[1])); + + // for processing decimal places + double dValue = atof(strValue.c_str()); + dValue *= 100; + if (iDec > 0) + dValue += kDoubleCorrect; + + int iDec2; + int iNegative = 0; + strValue = fcvt(dValue, iDec, &iDec2, &iNegative); + if (strValue.IsEmpty()) { + dValue = 0; + strValue = fcvt(dValue, iDec, &iDec2, &iNegative); + } + + if (iDec2 < 0) { + ByteString zeros; + char* zeros_ptr = zeros.GetBuffer(abs(iDec2)); + memset(zeros_ptr, '0', abs(iDec2)); + strValue = zeros + strValue; + + iDec2 = 0; + } + int iMax = strValue.GetLength(); + if (iDec2 > iMax) { + for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) + strValue += '0'; + + iMax = iDec2 + 1; + } + + // for processing seperator style + if (iDec2 < iMax) { + char mark = DecimalMarkForStyle(iSepStyle); + strValue.Insert(iDec2, mark); + iMax++; + + if (iDec2 == 0) + strValue.Insert(iDec2, '0'); + } + if (IsStyleWithDigitSeparator(iSepStyle)) { + char cSeparator = DigitSeparatorForStyle(iSepStyle); + for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) { + strValue.Insert(iDecPositive, cSeparator); + iMax++; + } + } + + // negative mark + if (iNegative) + strValue.InsertAtFront('-'); + + strValue += '%'; + Value = WideString::FromLocal(strValue.AsStringView()); +#endif + return CJS_Return(true); +} + +// AFPercent_Keystroke(nDec, sepStyle) +CJS_Return CJS_PublicMethods::AFPercent_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return AFNumber_Keystroke(pRuntime, params); +} + +// function AFDate_FormatEx(cFormat) +CJS_Return CJS_PublicMethods::AFDate_FormatEx( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); + CJS_EventHandler* pEvent = pContext->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + WideString& val = pEvent->Value(); + WideString strValue = val; + if (strValue.IsEmpty()) + return CJS_Return(true); + + WideString sFormat = pRuntime->ToWideString(params[0]); + double dDate; + if (strValue.Contains(L"GMT")) { + // for GMT format time + // such as "Tue Aug 11 14:24:16 GMT+08002009" + dDate = MakeInterDate(strValue); + } else { + dDate = MakeRegularDate(strValue, sFormat, nullptr); + } + + if (std::isnan(dDate)) { + WideString swMsg = WideString::Format( + JSGetStringFromID(JSMessage::kParseDateError).c_str(), sFormat.c_str()); + AlertIfPossible(pContext, swMsg.c_str()); + return CJS_Return(false); + } + + val = MakeFormatDate(dDate, sFormat); + return CJS_Return(true); +} + +double CJS_PublicMethods::MakeInterDate(const WideString& strValue) { + std::vector wsArray; + WideString sTemp; + for (const auto& c : strValue) { + if (c == L' ' || c == L':') { + wsArray.push_back(sTemp); + sTemp.clear(); + continue; + } + sTemp += c; + } + wsArray.push_back(sTemp); + if (wsArray.size() != 8) + return 0; + + int nMonth = 1; + sTemp = wsArray[1]; + for (size_t i = 0; i < FX_ArraySize(kMonths); ++i) { + if (sTemp.Compare(kMonths[i]) == 0) { + nMonth = i + 1; + break; + } + } + + int nDay = FX_atof(wsArray[2].AsStringView()); + int nHour = FX_atof(wsArray[3].AsStringView()); + int nMin = FX_atof(wsArray[4].AsStringView()); + int nSec = FX_atof(wsArray[5].AsStringView()); + int nYear = FX_atof(wsArray[7].AsStringView()); + double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay), + JS_MakeTime(nHour, nMin, nSec, 0)); + if (std::isnan(dRet)) + dRet = JS_DateParse(strValue); + + return dRet; +} + +// AFDate_KeystrokeEx(cFormat) +CJS_Return CJS_PublicMethods::AFDate_KeystrokeEx( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) { + return CJS_Return( + WideString(L"AFDate_KeystrokeEx's parameters' size r not correct")); + } + + CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); + CJS_EventHandler* pEvent = pContext->GetEventHandler(); + if (pEvent->WillCommit()) { + if (!pEvent->m_pValue) + return CJS_Return(false); + + const WideString& strValue = pEvent->Value(); + if (strValue.IsEmpty()) + return CJS_Return(true); + + WideString sFormat = pRuntime->ToWideString(params[0]); + bool bWrongFormat = false; + double dRet = MakeRegularDate(strValue, sFormat, &bWrongFormat); + if (bWrongFormat || std::isnan(dRet)) { + WideString swMsg = WideString::Format( + JSGetStringFromID(JSMessage::kParseDateError).c_str(), + sFormat.c_str()); + AlertIfPossible(pContext, swMsg.c_str()); + pEvent->Rc() = false; + return CJS_Return(true); + } + } + return CJS_Return(true); +} + +CJS_Return CJS_PublicMethods::AFDate_Format( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + static constexpr const wchar_t* cFormats[] = {L"m/d", + L"m/d/yy", + L"mm/dd/yy", + L"mm/yy", + L"d-mmm", + L"d-mmm-yy", + L"dd-mmm-yy", + L"yy-mm-dd", + L"mmm-yy", + L"mmmm-yy", + L"mmm d, yyyy", + L"mmmm d, yyyy", + L"m/d/yy h:MM tt", + L"m/d/yy HH:MM"}; + + int iIndex = + WithinBoundsOrZero(pRuntime->ToInt32(params[0]), FX_ArraySize(cFormats)); + std::vector> newParams; + newParams.push_back(pRuntime->NewString(cFormats[iIndex])); + return AFDate_FormatEx(pRuntime, newParams); +} + +// AFDate_KeystrokeEx(cFormat) +CJS_Return CJS_PublicMethods::AFDate_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + static constexpr const wchar_t* cFormats[] = {L"m/d", + L"m/d/yy", + L"mm/dd/yy", + L"mm/yy", + L"d-mmm", + L"d-mmm-yy", + L"dd-mmm-yy", + L"yy-mm-dd", + L"mmm-yy", + L"mmmm-yy", + L"mmm d, yyyy", + L"mmmm d, yyyy", + L"m/d/yy h:MM tt", + L"m/d/yy HH:MM"}; + + int iIndex = + WithinBoundsOrZero(pRuntime->ToInt32(params[0]), FX_ArraySize(cFormats)); + std::vector> newParams; + newParams.push_back(pRuntime->NewString(cFormats[iIndex])); + return AFDate_KeystrokeEx(pRuntime, newParams); +} + +// function AFTime_Format(ptf) +CJS_Return CJS_PublicMethods::AFTime_Format( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + static constexpr const wchar_t* cFormats[] = {L"HH:MM", L"h:MM tt", + L"HH:MM:ss", L"h:MM:ss tt"}; + + int iIndex = + WithinBoundsOrZero(pRuntime->ToInt32(params[0]), FX_ArraySize(cFormats)); + std::vector> newParams; + newParams.push_back(pRuntime->NewString(cFormats[iIndex])); + return AFDate_FormatEx(pRuntime, newParams); +} + +CJS_Return CJS_PublicMethods::AFTime_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + static constexpr const wchar_t* cFormats[] = {L"HH:MM", L"h:MM tt", + L"HH:MM:ss", L"h:MM:ss tt"}; + + int iIndex = + WithinBoundsOrZero(pRuntime->ToInt32(params[0]), FX_ArraySize(cFormats)); + std::vector> newParams; + newParams.push_back(pRuntime->NewString(cFormats[iIndex])); + return AFDate_KeystrokeEx(pRuntime, newParams); +} + +CJS_Return CJS_PublicMethods::AFTime_FormatEx( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return AFDate_FormatEx(pRuntime, params); +} + +CJS_Return CJS_PublicMethods::AFTime_KeystrokeEx( + CJS_Runtime* pRuntime, + const std::vector>& params) { + return AFDate_KeystrokeEx(pRuntime, params); +} + +// function AFSpecial_Format(psf) +CJS_Return CJS_PublicMethods::AFSpecial_Format( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + const WideString& wsSource = pEvent->Value(); + WideString wsFormat; + switch (pRuntime->ToInt32(params[0])) { + case 0: + wsFormat = L"99999"; + break; + case 1: + wsFormat = L"99999-9999"; + break; + case 2: + if (util::printx(L"9999999999", wsSource).GetLength() >= 10) + wsFormat = L"(999) 999-9999"; + else + wsFormat = L"999-9999"; + break; + case 3: + wsFormat = L"999-99-9999"; + break; + } + + pEvent->Value() = util::printx(wsFormat, wsSource); + return CJS_Return(true); +} + +// function AFSpecial_KeystrokeEx(mask) +CJS_Return CJS_PublicMethods::AFSpecial_KeystrokeEx( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); + CJS_EventHandler* pEvent = pContext->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + const WideString& valEvent = pEvent->Value(); + WideString wstrMask = pRuntime->ToWideString(params[0]); + if (wstrMask.IsEmpty()) + return CJS_Return(true); + + if (pEvent->WillCommit()) { + if (valEvent.IsEmpty()) + return CJS_Return(true); + + size_t iIndexMask = 0; + for (; iIndexMask < valEvent.GetLength(); ++iIndexMask) { + if (!MaskSatisfied(valEvent[iIndexMask], wstrMask[iIndexMask])) + break; + } + + if (iIndexMask != wstrMask.GetLength() || + (iIndexMask != valEvent.GetLength() && wstrMask.GetLength() != 0)) { + AlertIfPossible(pContext, + JSGetStringFromID(JSMessage::kInvalidInputError).c_str()); + pEvent->Rc() = false; + } + return CJS_Return(true); + } + + WideString& wideChange = pEvent->Change(); + if (wideChange.IsEmpty()) + return CJS_Return(true); + + WideString wChange = wideChange; + size_t iIndexMask = pEvent->SelStart(); + size_t combined_len = valEvent.GetLength() + wChange.GetLength() + + pEvent->SelStart() - pEvent->SelEnd(); + if (combined_len > wstrMask.GetLength()) { + AlertIfPossible(pContext, + JSGetStringFromID(JSMessage::kParamTooLongError).c_str()); + pEvent->Rc() = false; + return CJS_Return(true); + } + + if (iIndexMask >= wstrMask.GetLength() && !wChange.IsEmpty()) { + AlertIfPossible(pContext, + JSGetStringFromID(JSMessage::kParamTooLongError).c_str()); + pEvent->Rc() = false; + return CJS_Return(true); + } + + for (size_t i = 0; i < wChange.GetLength(); ++i) { + if (iIndexMask >= wstrMask.GetLength()) { + AlertIfPossible(pContext, + JSGetStringFromID(JSMessage::kParamTooLongError).c_str()); + pEvent->Rc() = false; + return CJS_Return(true); + } + wchar_t wMask = wstrMask[iIndexMask]; + if (!IsReservedMaskChar(wMask)) + wChange.SetAt(i, wMask); + + if (!MaskSatisfied(wChange[i], wMask)) { + pEvent->Rc() = false; + return CJS_Return(true); + } + iIndexMask++; + } + wideChange = wChange; + return CJS_Return(true); +} + +// function AFSpecial_Keystroke(psf) +CJS_Return CJS_PublicMethods::AFSpecial_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventHandler* pEvent = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + const char* cFormat = ""; + switch (pRuntime->ToInt32(params[0])) { + case 0: + cFormat = "99999"; + break; + case 1: + cFormat = "999999999"; + break; + case 2: + if (pEvent->Value().GetLength() + pEvent->Change().GetLength() > 7) + cFormat = "9999999999"; + else + cFormat = "9999999"; + break; + case 3: + cFormat = "999999999"; + break; + } + + std::vector> params2; + params2.push_back(pRuntime->NewString(cFormat)); + return AFSpecial_KeystrokeEx(pRuntime, params2); +} + +CJS_Return CJS_PublicMethods::AFMergeChange( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventHandler* pEventHandler = + pRuntime->GetCurrentEventContext()->GetEventHandler(); + + WideString swValue; + if (pEventHandler->m_pValue) + swValue = pEventHandler->Value(); + + if (pEventHandler->WillCommit()) + return CJS_Return(pRuntime->NewString(swValue.c_str())); + + WideString merged = + CalcMergedString(pEventHandler, swValue, pEventHandler->Change()); + return CJS_Return(pRuntime->NewString(merged.c_str())); +} + +CJS_Return CJS_PublicMethods::AFParseDateEx( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString sValue = pRuntime->ToWideString(params[0]); + WideString sFormat = pRuntime->ToWideString(params[1]); + double dDate = MakeRegularDate(sValue, sFormat, nullptr); + if (std::isnan(dDate)) { + WideString swMsg = WideString::Format( + JSGetStringFromID(JSMessage::kParseDateError).c_str(), sFormat.c_str()); + AlertIfPossible(pRuntime->GetCurrentEventContext(), swMsg.c_str()); + return CJS_Return(false); + } + return CJS_Return(pRuntime->NewNumber(dDate)); +} + +CJS_Return CJS_PublicMethods::AFSimple( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + return CJS_Return(pRuntime->NewNumber(static_cast(AF_Simple( + pRuntime->ToWideString(params[0]).c_str(), pRuntime->ToDouble(params[1]), + pRuntime->ToDouble(params[2]))))); +} + +CJS_Return CJS_PublicMethods::AFMakeNumber( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString ws = pRuntime->ToWideString(params[0]); + NormalizeDecimalMarkW(&ws); + + v8::Local val = + pRuntime->MaybeCoerceToNumber(pRuntime->NewString(ws.c_str())); + if (!val->IsNumber()) + return CJS_Return(pRuntime->NewNumber(0)); + return CJS_Return(val); +} + +CJS_Return CJS_PublicMethods::AFSimple_Calculate( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + if ((params[1].IsEmpty() || !params[1]->IsArray()) && !params[1]->IsString()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CPDFSDK_InterForm* pReaderInterForm = + pRuntime->GetFormFillEnv()->GetInterForm(); + CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm(); + + WideString sFunction = pRuntime->ToWideString(params[0]); + double dValue = wcscmp(sFunction.c_str(), L"PRD") == 0 ? 1.0 : 0.0; + + v8::Local FieldNameArray = + AF_MakeArrayFromList(pRuntime, params[0]); + int nFieldsCount = 0; + for (size_t i = 0; i < pRuntime->GetArrayLength(FieldNameArray); ++i) { + WideString wsFieldName = + pRuntime->ToWideString(pRuntime->GetArrayElement(FieldNameArray, i)); + + for (size_t j = 0; j < pInterForm->CountFields(wsFieldName); ++j) { + CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName); + if (!pFormField) + continue; + + double dTemp = 0.0; + switch (pFormField->GetFieldType()) { + case FormFieldType::kTextField: + case FormFieldType::kComboBox: { + WideString trimmed = pFormField->GetValue(); + trimmed.TrimRight(); + trimmed.TrimLeft(); + dTemp = FX_atof(trimmed.AsStringView()); + break; + } + case FormFieldType::kPushButton: + break; + case FormFieldType::kCheckBox: + case FormFieldType::kRadioButton: + for (int c = 0; c < pFormField->CountControls(); ++c) { + CPDF_FormControl* pFormCtrl = pFormField->GetControl(c); + if (!pFormField || !pFormCtrl->IsChecked()) + continue; + + WideString trimmed = pFormCtrl->GetExportValue(); + trimmed.TrimRight(); + trimmed.TrimLeft(); + dTemp = FX_atof(trimmed.AsStringView()); + break; + } + break; + case FormFieldType::kListBox: + if (pFormField->CountSelectedItems() <= 1) { + WideString trimmed = pFormField->GetValue(); + trimmed.TrimRight(); + trimmed.TrimLeft(); + dTemp = FX_atof(trimmed.AsStringView()); + } + break; + default: + break; + } + + if (i == 0 && j == 0 && + (wcscmp(sFunction.c_str(), L"MIN") == 0 || + wcscmp(sFunction.c_str(), L"MAX") == 0)) { + dValue = dTemp; + } + dValue = AF_Simple(sFunction.c_str(), dValue, dTemp); + + nFieldsCount++; + } + } + + if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0) + dValue /= nFieldsCount; + + dValue = floor(dValue * FXSYS_pow(10, 6) + 0.49) / FXSYS_pow(10, 6); + + CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); + if (pContext->GetEventHandler()->m_pValue) { + pContext->GetEventHandler()->Value() = + pRuntime->ToWideString(pRuntime->NewNumber(dValue)); + } + + return CJS_Return(true); +} + +/* This function validates the current event to ensure that its value is +** within the specified range. */ +CJS_Return CJS_PublicMethods::AFRange_Validate( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 4) + CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CJS_EventContext* pContext = pRuntime->GetCurrentEventContext(); + CJS_EventHandler* pEvent = pContext->GetEventHandler(); + if (!pEvent->m_pValue) + return CJS_Return(false); + + if (pEvent->Value().IsEmpty()) + return CJS_Return(true); + + double dEentValue = atof(ByteString::FromUnicode(pEvent->Value()).c_str()); + bool bGreaterThan = pRuntime->ToBoolean(params[0]); + double dGreaterThan = pRuntime->ToDouble(params[1]); + bool bLessThan = pRuntime->ToBoolean(params[2]); + double dLessThan = pRuntime->ToDouble(params[3]); + WideString swMsg; + + if (bGreaterThan && bLessThan) { + if (dEentValue < dGreaterThan || dEentValue > dLessThan) + swMsg = WideString::Format( + JSGetStringFromID(JSMessage::kRangeBetweenError).c_str(), + pRuntime->ToWideString(params[1]).c_str(), + pRuntime->ToWideString(params[3]).c_str()); + } else if (bGreaterThan) { + if (dEentValue < dGreaterThan) + swMsg = WideString::Format( + JSGetStringFromID(JSMessage::kRangeGreaterError).c_str(), + pRuntime->ToWideString(params[1]).c_str()); + } else if (bLessThan) { + if (dEentValue > dLessThan) + swMsg = WideString::Format( + JSGetStringFromID(JSMessage::kRangeLessError).c_str(), + pRuntime->ToWideString(params[3]).c_str()); + } + + if (!swMsg.IsEmpty()) { + AlertIfPossible(pContext, swMsg.c_str()); + pEvent->Rc() = false; + } + return CJS_Return(true); +} + +CJS_Return CJS_PublicMethods::AFExtractNums( + CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString str = pRuntime->ToWideString(params[0]); + if (str.GetLength() > 0 && IsDigitSeparatorOrDecimalMark(str[0])) + str.InsertAtFront(L'0'); + + WideString sPart; + v8::Local nums = pRuntime->NewArray(); + int nIndex = 0; + for (const auto& wc : str) { + if (std::iswdigit(wc)) { + sPart += wc; + } else if (sPart.GetLength() > 0) { + pRuntime->PutArrayElement(nums, nIndex, + pRuntime->NewString(sPart.c_str())); + sPart.clear(); + nIndex++; + } + } + if (sPart.GetLength() > 0) + pRuntime->PutArrayElement(nums, nIndex, pRuntime->NewString(sPart.c_str())); + + if (pRuntime->GetArrayLength(nums) > 0) + return CJS_Return(nums); + return CJS_Return(pRuntime->NewUndefined()); +} diff --git a/fxjs/cjs_publicmethods.h b/fxjs/cjs_publicmethods.h new file mode 100644 index 0000000000000000000000000000000000000000..87269969f8d94ee6b674fc8379ae835c8e0e6d99 --- /dev/null +++ b/fxjs/cjs_publicmethods.h @@ -0,0 +1,160 @@ +// 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 FXJS_CJS_PUBLICMETHODS_H_ +#define FXJS_CJS_PUBLICMETHODS_H_ + +#include +#include + +#include "fxjs/JS_Define.h" + +class CJS_PublicMethods : public CJS_Object { + public: + explicit CJS_PublicMethods(v8::Local pObject); + ~CJS_PublicMethods() override; + + static void DefineJSObjects(CFXJS_Engine* pEngine); + static double MakeRegularDate(const WideString& value, + const WideString& format, + bool* bWrongFormat); + + // Exposed for testing. + static WideString MakeFormatDate(double dDate, const WideString& format); + static bool IsNumber(const WideString& str); + + static CJS_Return AFNumber_Format( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFNumber_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFPercent_Format( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFPercent_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFDate_FormatEx( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFDate_KeystrokeEx( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFDate_Format( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFDate_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFTime_FormatEx( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFTime_KeystrokeEx( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFTime_Format( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFTime_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFSpecial_Format( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFSpecial_Keystroke( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFSpecial_KeystrokeEx( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFSimple(CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFMakeNumber( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFSimple_Calculate( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFRange_Validate( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFMergeChange( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFParseDateEx( + CJS_Runtime* pRuntime, + const std::vector>& params); + static CJS_Return AFExtractNums( + CJS_Runtime* pRuntime, + const std::vector>& params); + + static void AFNumber_Format_static( + const v8::FunctionCallbackInfo& info); + static void AFNumber_Keystroke_static( + const v8::FunctionCallbackInfo& info); + static void AFPercent_Format_static( + const v8::FunctionCallbackInfo& info); + static void AFPercent_Keystroke_static( + const v8::FunctionCallbackInfo& info); + static void AFDate_FormatEx_static( + const v8::FunctionCallbackInfo& info); + static void AFDate_KeystrokeEx_static( + const v8::FunctionCallbackInfo& info); + static void AFDate_Format_static( + const v8::FunctionCallbackInfo& info); + static void AFDate_Keystroke_static( + const v8::FunctionCallbackInfo& info); + static void AFTime_FormatEx_static( + const v8::FunctionCallbackInfo& info); + static void AFTime_KeystrokeEx_static( + const v8::FunctionCallbackInfo& info); + static void AFTime_Format_static( + const v8::FunctionCallbackInfo& info); + static void AFTime_Keystroke_static( + const v8::FunctionCallbackInfo& info); + static void AFSpecial_Format_static( + const v8::FunctionCallbackInfo& info); + static void AFSpecial_Keystroke_static( + const v8::FunctionCallbackInfo& info); + static void AFSpecial_KeystrokeEx_static( + const v8::FunctionCallbackInfo& info); + static void AFSimple_static(const v8::FunctionCallbackInfo& info); + static void AFMakeNumber_static( + const v8::FunctionCallbackInfo& info); + static void AFSimple_Calculate_static( + const v8::FunctionCallbackInfo& info); + static void AFRange_Validate_static( + const v8::FunctionCallbackInfo& info); + static void AFMergeChange_static( + const v8::FunctionCallbackInfo& info); + static void AFParseDateEx_static( + const v8::FunctionCallbackInfo& info); + static void AFExtractNums_static( + const v8::FunctionCallbackInfo& info); + + static const JSMethodSpec GlobalFunctionSpecs[]; + static int ParseStringInteger(const WideString& string, + size_t nStart, + size_t* pSkip, + size_t nMaxStep); + static WideString ParseStringString(const WideString& string, + size_t nStart, + size_t* pSkip); + static double ParseNormalDate(const WideString& value, bool* bWrongFormat); + static double MakeInterDate(const WideString& value); + + static bool MaskSatisfied(wchar_t c_Change, wchar_t c_Mask); + static bool IsReservedMaskChar(wchar_t ch); + + static double AF_Simple(const wchar_t* sFuction, + double dValue1, + double dValue2); + static v8::Local AF_MakeArrayFromList(CJS_Runtime* pRuntime, + v8::Local val); +}; + +#endif // FXJS_CJS_PUBLICMETHODS_H_ diff --git a/fxjs/cjs_publicmethods_embeddertest.cpp b/fxjs/cjs_publicmethods_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbab0817cec47424006a2a7274e517f19b39a64f --- /dev/null +++ b/fxjs/cjs_publicmethods_embeddertest.cpp @@ -0,0 +1,162 @@ +// Copyright 2015 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. + +#include + +#include "core/fxcrt/fx_string.h" +#include "fxjs/cjs_publicmethods.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/js_embedder_test.h" + +namespace { + +double RoundDownDate(double date) { + return date - fmod(date, 86400000); +} + +} // namespace + +class CJS_PublicMethodsEmbedderTest : public JSEmbedderTest {}; + +TEST_F(CJS_PublicMethodsEmbedderTest, MakeRegularDate) { + v8::Isolate::Scope isolate_scope(isolate()); + v8::HandleScope handle_scope(isolate()); + v8::Context::Scope context_scope(GetV8Context()); + bool bWrongFormat; + double date; + + // 1968 + bWrongFormat = false; + date = CJS_PublicMethods::MakeRegularDate(L"06/25/1968", L"mm/dd/yyyy", + &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(-47865600000, date); + EXPECT_FALSE(bWrongFormat); + + // 1968 + bWrongFormat = false; + date = CJS_PublicMethods::MakeRegularDate(L"25061968", L"ddmmyyyy", + &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(-47865600000, date); + EXPECT_FALSE(bWrongFormat); + + // 1968 + bWrongFormat = false; + date = CJS_PublicMethods::MakeRegularDate(L"19680625", L"yyyymmdd", + &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(-47865600000, date); + EXPECT_FALSE(bWrongFormat); + + // 1985 + bWrongFormat = false; + date = CJS_PublicMethods::MakeRegularDate(L"31121985", L"ddmmyyyy", + &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(504835200000.0, date); + EXPECT_FALSE(bWrongFormat); + + // 2085, the other '85. + bWrongFormat = false; + date = + CJS_PublicMethods::MakeRegularDate(L"311285", L"ddmmyy", &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(3660595200000.0, date); + EXPECT_FALSE(bWrongFormat); + + // 1995 + bWrongFormat = false; + date = CJS_PublicMethods::MakeRegularDate(L"01021995", L"ddmmyyyy", + &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(791596800000.0, date); + EXPECT_FALSE(bWrongFormat); + + // 2095, the other '95. + bWrongFormat = false; + date = + CJS_PublicMethods::MakeRegularDate(L"010295", L"ddmmyy", &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(3947356800000.0, date); + EXPECT_FALSE(bWrongFormat); + + // 2005 + bWrongFormat = false; + date = CJS_PublicMethods::MakeRegularDate(L"01022005", L"ddmmyyyy", + &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(1107216000000.0, date); + EXPECT_FALSE(bWrongFormat); + + // 2005 + bWrongFormat = false; + date = + CJS_PublicMethods::MakeRegularDate(L"010205", L"ddmmyy", &bWrongFormat); + date = RoundDownDate(date); + EXPECT_DOUBLE_EQ(1107216000000.0, date); + EXPECT_FALSE(bWrongFormat); +} + +TEST_F(CJS_PublicMethodsEmbedderTest, MakeFormatDate) { + v8::Isolate::Scope isolate_scope(isolate()); + v8::HandleScope handle_scope(isolate()); + v8::Context::Scope context_scope(GetV8Context()); + WideString formatted_date; + + // 1968-06-25 + formatted_date = CJS_PublicMethods::MakeFormatDate(-47952000000, L"ddmmyy"); + EXPECT_STREQ(L"250668", formatted_date.c_str()); + formatted_date = CJS_PublicMethods::MakeFormatDate(-47952000000, L"yy/mm/dd"); + EXPECT_STREQ(L"68/06/25", formatted_date.c_str()); + + // 1969-12-31 + formatted_date = CJS_PublicMethods::MakeFormatDate(-0.0001, L"ddmmyy"); + EXPECT_STREQ(L"311269", formatted_date.c_str()); + formatted_date = CJS_PublicMethods::MakeFormatDate(-0.0001, L"yy!mmdd"); + EXPECT_STREQ(L"69!1231", formatted_date.c_str()); + + // 1970-01-01 + formatted_date = CJS_PublicMethods::MakeFormatDate(0, L"ddmmyy"); + EXPECT_STREQ(L"010170", formatted_date.c_str()); + formatted_date = CJS_PublicMethods::MakeFormatDate(0, L"mm-yyyy-dd"); + EXPECT_STREQ(L"01-1970-01", formatted_date.c_str()); + + // 1985-12-31 + formatted_date = CJS_PublicMethods::MakeFormatDate(504835200000.0, L"ddmmyy"); + EXPECT_STREQ(L"311285", formatted_date.c_str()); + formatted_date = CJS_PublicMethods::MakeFormatDate(504835200000.0, L"yymmdd"); + EXPECT_STREQ(L"851231", formatted_date.c_str()); + + // 1995-02-01 + formatted_date = CJS_PublicMethods::MakeFormatDate(791596800000.0, L"ddmmyy"); + EXPECT_STREQ(L"010295", formatted_date.c_str()); + formatted_date = + CJS_PublicMethods::MakeFormatDate(791596800000.0, L"yyyymmdd"); + EXPECT_STREQ(L"19950201", formatted_date.c_str()); + + // 2005-02-01 + formatted_date = + CJS_PublicMethods::MakeFormatDate(1107216000000.0, L"ddmmyy"); + EXPECT_STREQ(L"010205", formatted_date.c_str()); + formatted_date = + CJS_PublicMethods::MakeFormatDate(1107216000000.0, L"yyyyddmm"); + EXPECT_STREQ(L"20050102", formatted_date.c_str()); + + // 2085-12-31 + formatted_date = + CJS_PublicMethods::MakeFormatDate(3660595200000.0, L"ddmmyy"); + EXPECT_STREQ(L"311285", formatted_date.c_str()); + formatted_date = + CJS_PublicMethods::MakeFormatDate(3660595200000.0, L"yyyydd"); + EXPECT_STREQ(L"208531", formatted_date.c_str()); + + // 2095-02-01 + formatted_date = + CJS_PublicMethods::MakeFormatDate(3947356800000.0, L"ddmmyy"); + EXPECT_STREQ(L"010295", formatted_date.c_str()); + formatted_date = + CJS_PublicMethods::MakeFormatDate(3947356800000.0, L"mmddyyyy"); + EXPECT_STREQ(L"02012095", formatted_date.c_str()); +} diff --git a/fxjs/cjs_publicmethods_unittest.cpp b/fxjs/cjs_publicmethods_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37bf93ba43e196a3ccab6cc994aef588ccd92b24 --- /dev/null +++ b/fxjs/cjs_publicmethods_unittest.cpp @@ -0,0 +1,51 @@ +// Copyright 2016 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. + +#include "fxjs/cjs_publicmethods.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CJS_PublicMethods, IsNumber) { + // TODO(weili): Check whether results from case 0, 1, 10, 15 are intended. + struct { + const wchar_t* input; + bool expected; + } test_data[] = { + // Empty string. + {L"", true}, + // Only whitespaces. + {L" ", true}, + // Content with invalid characters. + {L"xyz00", false}, + {L"1%", false}, + // Hex string. + {L"0x234", false}, + // Signed numbers. + {L"+123", true}, + {L"-98765", true}, + // Numbers with whitespaces. + {L" 345 ", true}, + // Float numbers. + {L"-1e5", false}, + {L"-2e", false}, + {L"e-5", true}, + {L"0.023", true}, + {L".356089", true}, + {L"1e-9", true}, + {L"-1.23e+23", true}, + // Numbers with commas. + {L"1,000,000", false}, + {L"560,024", true}, + // Regular numbers. + {L"0", true}, + {L"0123", true}, + {L"9876123", true}, + }; + for (size_t i = 0; i < FX_ArraySize(test_data); ++i) { + EXPECT_EQ(test_data[i].expected, + CJS_PublicMethods::IsNumber(test_data[i].input)) + << "for case " << i; + } +} diff --git a/fxjs/cjs_report.cpp b/fxjs/cjs_report.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0788a90a4cb8bbfa9d0cf52202ad5f0dd343ae71 --- /dev/null +++ b/fxjs/cjs_report.cpp @@ -0,0 +1,42 @@ +// 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 "fxjs/cjs_report.h" + +#include + +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_object.h" + +const JSMethodSpec CJS_Report::MethodSpecs[] = { + {"save", save_static}, + {"writeText", writeText_static}}; + +int CJS_Report::ObjDefnID = -1; + +// static +void CJS_Report::DefineJSObjects(CFXJS_Engine* pEngine, FXJSOBJTYPE eObjType) { + ObjDefnID = + pEngine->DefineObj("Report", eObjType, JSConstructor, + JSDestructor); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +Report::Report(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} + +Report::~Report() {} + +CJS_Return Report::writeText(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} + +CJS_Return Report::save(CJS_Runtime* pRuntime, + const std::vector>& params) { + // Unsafe, not supported. + return CJS_Return(true); +} diff --git a/fxjs/cjs_report.h b/fxjs/cjs_report.h new file mode 100644 index 0000000000000000000000000000000000000000..50259ef56f04867a216d9ab65489f63418feb45e --- /dev/null +++ b/fxjs/cjs_report.h @@ -0,0 +1,41 @@ +// 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 FXJS_CJS_REPORT_H_ +#define FXJS_CJS_REPORT_H_ + +#include + +#include "fxjs/JS_Define.h" + +class Report : public CJS_EmbedObj { + public: + explicit Report(CJS_Object* pJSObject); + ~Report() override; + + public: + CJS_Return save(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return writeText(CJS_Runtime* pRuntime, + const std::vector>& params); +}; + +class CJS_Report : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine, FXJSOBJTYPE eObjType); + + explicit CJS_Report(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Report() override {} + + JS_STATIC_METHOD(save, Report) + JS_STATIC_METHOD(writeText, Report); + + private: + static int ObjDefnID; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_REPORT_H_ diff --git a/fxjs/cjs_return.cpp b/fxjs/cjs_return.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adfd1c5c9f6059e0f1179fce750d1787f1c4a53e --- /dev/null +++ b/fxjs/cjs_return.cpp @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_return.h" + +CJS_Return::CJS_Return(bool result) : is_error_(!result) {} + +CJS_Return::CJS_Return(const WideString& err) : is_error_(true), error_(err) {} + +CJS_Return::CJS_Return(v8::Local ret) + : is_error_(false), return_(ret) {} + +CJS_Return::CJS_Return(const CJS_Return&) = default; + +CJS_Return::~CJS_Return() = default; diff --git a/fxjs/cjs_return.h b/fxjs/cjs_return.h new file mode 100644 index 0000000000000000000000000000000000000000..61c5778cdaa7aeb874c248e1d3e673824232e31e --- /dev/null +++ b/fxjs/cjs_return.h @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_RETURN_H_ +#define FXJS_CJS_RETURN_H_ + +#include "fxjs/fxjs_v8.h" + +class CJS_Return { + public: + explicit CJS_Return(bool); + explicit CJS_Return(const WideString&); + explicit CJS_Return(v8::Local); + CJS_Return(const CJS_Return&); + ~CJS_Return(); + + bool HasError() const { return is_error_; } + WideString Error() const { return error_; } + + bool HasReturn() const { return !return_.IsEmpty(); } + v8::Local Return() const { return return_; } + + private: + CJS_Return() = delete; + + bool is_error_ = false; + WideString error_; + v8::Local return_; +}; + +#endif // FXJS_CJS_RETURN_H_ diff --git a/fxjs/cjs_runtime.cpp b/fxjs/cjs_runtime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8e95e16e5d4ace1f7398bacd6d65f02bab948ae --- /dev/null +++ b/fxjs/cjs_runtime.cpp @@ -0,0 +1,292 @@ +// 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 "fxjs/cjs_runtime.h" + +#include + +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_annot.h" +#include "fxjs/cjs_app.h" +#include "fxjs/cjs_border.h" +#include "fxjs/cjs_color.h" +#include "fxjs/cjs_console.h" +#include "fxjs/cjs_display.h" +#include "fxjs/cjs_document.h" +#include "fxjs/cjs_event.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_field.h" +#include "fxjs/cjs_font.h" +#include "fxjs/cjs_global.h" +#include "fxjs/cjs_globalarrays.h" +#include "fxjs/cjs_globalconsts.h" +#include "fxjs/cjs_globaldata.h" +#include "fxjs/cjs_highlight.h" +#include "fxjs/cjs_icon.h" +#include "fxjs/cjs_object.h" +#include "fxjs/cjs_position.h" +#include "fxjs/cjs_printparamsobj.h" +#include "fxjs/cjs_publicmethods.h" +#include "fxjs/cjs_report.h" +#include "fxjs/cjs_scalehow.h" +#include "fxjs/cjs_scalewhen.h" +#include "fxjs/cjs_style.h" +#include "fxjs/cjs_timerobj.h" +#include "fxjs/cjs_util.h" +#include "fxjs/cjs_zoomtype.h" +#include "public/fpdf_formfill.h" +#include "third_party/base/stl_util.h" + +#ifdef PDF_ENABLE_XFA +#include "fxjs/cfxjse_value.h" +#endif // PDF_ENABLE_XFA + +// static +void IJS_Runtime::Initialize(unsigned int slot, void* isolate) { + FXJS_Initialize(slot, reinterpret_cast(isolate)); +} + +// static +void IJS_Runtime::Destroy() { + FXJS_Release(); +} + +// static +IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) { + return new CJS_Runtime(pFormFillEnv); +} + +// static +CJS_Runtime* CJS_Runtime::CurrentRuntimeFromIsolate(v8::Isolate* pIsolate) { + return static_cast( + CFXJS_Engine::CurrentEngineFromIsolate(pIsolate)); +} + +CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv) + : m_pFormFillEnv(pFormFillEnv), + m_bBlocking(false), + m_isolateManaged(false) { + v8::Isolate* pIsolate = nullptr; + + IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform; + if (pPlatform->version <= 2) { + unsigned int embedderDataSlot = 0; + v8::Isolate* pExternalIsolate = nullptr; + if (pPlatform->version == 2) { + pExternalIsolate = reinterpret_cast(pPlatform->m_isolate); + embedderDataSlot = pPlatform->m_v8EmbedderSlot; + } + FXJS_Initialize(embedderDataSlot, pExternalIsolate); + } + m_isolateManaged = FXJS_GetIsolate(&pIsolate); + SetIsolate(pIsolate); + +#ifdef PDF_ENABLE_XFA + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope handle_scope(pIsolate); +#endif + + if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0) + DefineJSObjects(); + + IJS_EventContext* pContext = NewEventContext(); + InitializeEngine(); + ReleaseEventContext(pContext); + SetFormFillEnvToDocument(); +} + +CJS_Runtime::~CJS_Runtime() { + NotifyObservedPtrs(); + ReleaseEngine(); + if (m_isolateManaged) { + GetIsolate()->Dispose(); + SetIsolate(nullptr); + } +} + +void CJS_Runtime::DefineJSObjects() { + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); + v8::Local context = v8::Context::New(GetIsolate()); + v8::Context::Scope context_scope(context); + + // The call order determines the "ObjDefID" assigned to each class. + // ObjDefIDs 0 - 2 + CJS_Border::DefineJSObjects(this); + CJS_Display::DefineJSObjects(this); + CJS_Font::DefineJSObjects(this); + + // ObjDefIDs 3 - 5 + CJS_Highlight::DefineJSObjects(this); + CJS_Position::DefineJSObjects(this); + CJS_ScaleHow::DefineJSObjects(this); + + // ObjDefIDs 6 - 8 + CJS_ScaleWhen::DefineJSObjects(this); + CJS_Style::DefineJSObjects(this); + CJS_Zoomtype::DefineJSObjects(this); + + // ObjDefIDs 9 - 11 + CJS_App::DefineJSObjects(this); + CJS_Color::DefineJSObjects(this); + CJS_Console::DefineJSObjects(this); + + // ObjDefIDs 12 - 14 + CJS_Document::DefineJSObjects(this); + CJS_Event::DefineJSObjects(this); + CJS_Field::DefineJSObjects(this); + + // ObjDefIDs 15 - 17 + CJS_Global::DefineJSObjects(this); + CJS_Icon::DefineJSObjects(this); + CJS_Util::DefineJSObjects(this); + + // ObjDefIDs 18 - 20 (these can't fail, return void). + CJS_PublicMethods::DefineJSObjects(this); + CJS_GlobalConsts::DefineJSObjects(this); + CJS_GlobalArrays::DefineJSObjects(this); + + // ObjDefIDs 21 - 23. + CJS_TimerObj::DefineJSObjects(this); + CJS_PrintParamsObj::DefineJSObjects(this); + CJS_Annot::DefineJSObjects(this); +} + +IJS_EventContext* CJS_Runtime::NewEventContext() { + m_EventContextArray.push_back(pdfium::MakeUnique(this)); + return m_EventContextArray.back().get(); +} + +void CJS_Runtime::ReleaseEventContext(IJS_EventContext* pContext) { + auto it = std::find(m_EventContextArray.begin(), m_EventContextArray.end(), + pdfium::FakeUniquePtr( + static_cast(pContext))); + if (it != m_EventContextArray.end()) + m_EventContextArray.erase(it); +} + +CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const { + return m_EventContextArray.empty() ? nullptr + : m_EventContextArray.back().get(); +} + +void CJS_Runtime::SetFormFillEnvToDocument() { + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); + v8::Local context = NewLocalContext(); + v8::Context::Scope context_scope(context); + + v8::Local pThis = GetThisObj(); + if (pThis.IsEmpty()) + return; + + if (CFXJS_Engine::GetObjDefnID(pThis) != CJS_Document::GetObjDefnID()) + return; + + CJS_Document* pJSDocument = + static_cast(GetObjectPrivate(pThis)); + if (!pJSDocument) + return; + + Document* pDocument = static_cast(pJSDocument->GetEmbedObject()); + if (!pDocument) + return; + + pDocument->SetFormFillEnv(m_pFormFillEnv.Get()); +} + +CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const { + return m_pFormFillEnv.Get(); +} + +int CJS_Runtime::ExecuteScript(const WideString& script, WideString* info) { + FXJSErr error = {}; + int nRet = Execute(script, &error); + if (nRet < 0) { + *info = WideString::Format(L"[ Line: %05d { %ls } ] : %s", error.linnum - 1, + error.srcline, error.message); + } + return nRet; +} + +bool CJS_Runtime::AddEventToSet(const FieldEvent& event) { + return m_FieldEventSet.insert(event).second; +} + +void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) { + m_FieldEventSet.erase(event); +} + +#ifdef PDF_ENABLE_XFA +WideString ChangeObjName(const WideString& str) { + WideString sRet = str; + sRet.Replace(L"_", L"."); + return sRet; +} + +bool CJS_Runtime::GetValueByName(const ByteStringView& utf8Name, + CFXJSE_Value* pValue) { + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); + v8::Local context = NewLocalContext(); + v8::Context::Scope context_scope(context); + v8::Local propvalue = context->Global()->Get( + v8::String::NewFromUtf8(GetIsolate(), utf8Name.unterminated_c_str(), + v8::String::kNormalString, utf8Name.GetLength())); + if (propvalue.IsEmpty()) { + pValue->SetUndefined(); + return false; + } + pValue->ForceSetValue(propvalue); + return true; +} + +bool CJS_Runtime::SetValueByName(const ByteStringView& utf8Name, + CFXJSE_Value* pValue) { + if (utf8Name.IsEmpty() || !pValue) + return false; + + v8::Isolate* pIsolate = GetIsolate(); + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope handle_scope(pIsolate); + v8::Local context = NewLocalContext(); + v8::Context::Scope context_scope(context); + v8::Local propvalue = + v8::Local::New(GetIsolate(), pValue->DirectGetValue()); + context->Global()->Set( + v8::String::NewFromUtf8(pIsolate, utf8Name.unterminated_c_str(), + v8::String::kNormalString, utf8Name.GetLength()), + propvalue); + return true; +} +#endif + +v8::Local CJS_Runtime::MaybeCoerceToNumber( + v8::Local value) { + bool bAllowNaN = false; + if (value->IsString()) { + ByteString bstr = ByteString::FromUnicode(ToWideString(value)); + if (bstr.GetLength() == 0) + return value; + if (bstr == "NaN") + bAllowNaN = true; + } + + v8::Isolate* pIsolate = GetIsolate(); + v8::TryCatch try_catch(pIsolate); + v8::MaybeLocal maybeNum = + value->ToNumber(pIsolate->GetCurrentContext()); + if (maybeNum.IsEmpty()) + return value; + + v8::Local num = maybeNum.ToLocalChecked(); + if (std::isnan(num->Value()) && !bAllowNaN) + return value; + + return num; +} diff --git a/fxjs/cjs_runtime.h b/fxjs/cjs_runtime.h new file mode 100644 index 0000000000000000000000000000000000000000..7ecc0d5ce42975da057c27eb2acd649d912daea3 --- /dev/null +++ b/fxjs/cjs_runtime.h @@ -0,0 +1,73 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_RUNTIME_H_ +#define FXJS_CJS_RUNTIME_H_ + +#include +#include +#include +#include +#include + +#include "core/fxcrt/observable.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/fxjs_v8.h" +#include "fxjs/ijs_runtime.h" + +class CJS_EventContext; + +class CJS_Runtime : public IJS_Runtime, + public CFXJS_Engine, + public Observable { + public: + using FieldEvent = std::pair; + + static CJS_Runtime* CurrentRuntimeFromIsolate(v8::Isolate* pIsolate); + + explicit CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv); + ~CJS_Runtime() override; + + // IJS_Runtime + IJS_EventContext* NewEventContext() override; + void ReleaseEventContext(IJS_EventContext* pContext) override; + CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override; + int ExecuteScript(const WideString& script, WideString* info) override; + + CJS_EventContext* GetCurrentEventContext() const; + + // Returns true if the event isn't already found in the set. + bool AddEventToSet(const FieldEvent& event); + void RemoveEventFromSet(const FieldEvent& event); + + void BeginBlock() { m_bBlocking = true; } + void EndBlock() { m_bBlocking = false; } + bool IsBlocking() const { return m_bBlocking; } + + // Attempt to convert the |value| into a number. If successful the number + // value will be returned, otherwise |value| is returned. + v8::Local MaybeCoerceToNumber(v8::Local value); + +#ifdef PDF_ENABLE_XFA + bool GetValueByName(const ByteStringView& utf8Name, + CFXJSE_Value* pValue) override; + bool SetValueByName(const ByteStringView& utf8Name, + CFXJSE_Value* pValue) override; +#endif // PDF_ENABLE_XFA + + private: + void DefineJSObjects(); + void SetFormFillEnvToDocument(); + + std::vector> m_EventContextArray; + CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; + bool m_bBlocking; + bool m_isolateManaged; + std::set m_FieldEventSet; +}; + +#endif // FXJS_CJS_RUNTIME_H_ diff --git a/fxjs/cjs_runtimestub.cpp b/fxjs/cjs_runtimestub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..919672832dac4e94c1e7d32da5a831a5203b95bf --- /dev/null +++ b/fxjs/cjs_runtimestub.cpp @@ -0,0 +1,60 @@ +// Copyright 2015 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 + +#include "core/fxcrt/unowned_ptr.h" +#include "fxjs/cjs_event_context_stub.h" +#include "fxjs/ijs_runtime.h" +#include "third_party/base/ptr_util.h" + +class CJS_RuntimeStub final : public IJS_Runtime { + public: + explicit CJS_RuntimeStub(CPDFSDK_FormFillEnvironment* pFormFillEnv) + : m_pFormFillEnv(pFormFillEnv) {} + ~CJS_RuntimeStub() override {} + + IJS_EventContext* NewEventContext() override { + if (!m_pContext) + m_pContext = pdfium::MakeUnique(); + return m_pContext.get(); + } + + void ReleaseEventContext(IJS_EventContext* pContext) override {} + + CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override { + return m_pFormFillEnv.Get(); + } + +#ifdef PDF_ENABLE_XFA + bool GetValueByName(const ByteStringView&, CFXJSE_Value*) override { + return false; + } + + bool SetValueByName(const ByteStringView&, CFXJSE_Value*) override { + return false; + } +#endif // PDF_ENABLE_XFA + + int ExecuteScript(const WideString& script, WideString* info) override { + return 0; + } + + protected: + UnownedPtr const m_pFormFillEnv; + std::unique_ptr m_pContext; +}; + +// static +void IJS_Runtime::Initialize(unsigned int slot, void* isolate) {} + +// static +void IJS_Runtime::Destroy() {} + +// static +IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) { + return new CJS_RuntimeStub(pFormFillEnv); +} diff --git a/fxjs/cjs_scalehow.cpp b/fxjs/cjs_scalehow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..762863b6867404dbb959182cfc0e7fabfe222a47 --- /dev/null +++ b/fxjs/cjs_scalehow.cpp @@ -0,0 +1,20 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_scalehow.h" + +const JSConstSpec CJS_ScaleHow::ConstSpecs[] = { + {"proportional", JSConstSpec::Number, 0, 0}, + {"anamorphic", JSConstSpec::Number, 1, 0}}; + +int CJS_ScaleHow::ObjDefnID = -1; + +// static +void CJS_ScaleHow::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("scaleHow", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_scalehow.h b/fxjs/cjs_scalehow.h new file mode 100644 index 0000000000000000000000000000000000000000..8177a3eabbcef06e57b2fe4d321cdb73e19c61b8 --- /dev/null +++ b/fxjs/cjs_scalehow.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_SCALEHOW_H_ +#define FXJS_CJS_SCALEHOW_H_ + +#include "fxjs/JS_Define.h" + +class CJS_ScaleHow : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_ScaleHow(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_ScaleHow() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_SCALEHOW_H_ diff --git a/fxjs/cjs_scalewhen.cpp b/fxjs/cjs_scalewhen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59f04870caff757e31af33075520d131ed10801f --- /dev/null +++ b/fxjs/cjs_scalewhen.cpp @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_scalewhen.h" + +const JSConstSpec CJS_ScaleWhen::ConstSpecs[] = { + {"always", JSConstSpec::Number, 0, 0}, + {"never", JSConstSpec::Number, 1, 0}, + {"tooBig", JSConstSpec::Number, 2, 0}, + {"tooSmall", JSConstSpec::Number, 3, 0}}; + +int CJS_ScaleWhen::ObjDefnID = -1; + +// static +void CJS_ScaleWhen::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("scaleWhen", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_scalewhen.h b/fxjs/cjs_scalewhen.h new file mode 100644 index 0000000000000000000000000000000000000000..e97a2851192b0a09d41682ea0d46ca09ae7150ba --- /dev/null +++ b/fxjs/cjs_scalewhen.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_SCALEWHEN_H_ +#define FXJS_CJS_SCALEWHEN_H_ + +#include "fxjs/JS_Define.h" + +class CJS_ScaleWhen : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_ScaleWhen(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_ScaleWhen() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_SCALEWHEN_H_ diff --git a/fxjs/cjs_style.cpp b/fxjs/cjs_style.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be95e9a5011147f29545ce1b396a2c27cb6c02c7 --- /dev/null +++ b/fxjs/cjs_style.cpp @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_style.h" + +const JSConstSpec CJS_Style::ConstSpecs[] = { + {"ch", JSConstSpec::String, 0, "check"}, + {"cr", JSConstSpec::String, 0, "cross"}, + {"di", JSConstSpec::String, 0, "diamond"}, + {"ci", JSConstSpec::String, 0, "circle"}, + {"st", JSConstSpec::String, 0, "star"}, + {"sq", JSConstSpec::String, 0, "square"}}; + +int CJS_Style::ObjDefnID = -1; + +// static +void CJS_Style::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("style", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_style.h b/fxjs/cjs_style.h new file mode 100644 index 0000000000000000000000000000000000000000..46ab66b617d8e5002dc1083067392af83144ad42 --- /dev/null +++ b/fxjs/cjs_style.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_STYLE_H_ +#define FXJS_CJS_STYLE_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Style : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Style(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Style() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_STYLE_H_ diff --git a/fxjs/cjs_timerobj.cpp b/fxjs/cjs_timerobj.cpp new file mode 100644 index 0000000000000000000000000000000000000000..410ad0846e007e136aa9eb18178440f4b2252557 --- /dev/null +++ b/fxjs/cjs_timerobj.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_timerobj.h" + +#include "fxjs/global_timer.h" + +int CJS_TimerObj::ObjDefnID = -1; + +// static +int CJS_TimerObj::GetObjDefnID() { + return ObjDefnID; +} + +// static +void CJS_TimerObj::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = pEngine->DefineObj("TimerObj", FXJSOBJTYPE_DYNAMIC, + JSConstructor, + JSDestructor); +} + +TimerObj::TimerObj(CJS_Object* pJSObject) + : CJS_EmbedObj(pJSObject), m_nTimerID(0) {} + +TimerObj::~TimerObj() {} + +void TimerObj::SetTimer(GlobalTimer* pTimer) { + m_nTimerID = pTimer->GetTimerID(); +} diff --git a/fxjs/cjs_timerobj.h b/fxjs/cjs_timerobj.h new file mode 100644 index 0000000000000000000000000000000000000000..be095558e231dd52def8da2945965e809026af43 --- /dev/null +++ b/fxjs/cjs_timerobj.h @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_TIMEROBJ_H_ +#define FXJS_CJS_TIMEROBJ_H_ + +#include "fxjs/JS_Define.h" + +class GlobalTimer; + +class TimerObj : public CJS_EmbedObj { + public: + explicit TimerObj(CJS_Object* pJSObject); + ~TimerObj() override; + + void SetTimer(GlobalTimer* pTimer); + int GetTimerID() const { return m_nTimerID; } + + private: + int m_nTimerID; // Weak reference to GlobalTimer through global map. +}; + +class CJS_TimerObj : public CJS_Object { + public: + static int GetObjDefnID(); + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_TimerObj(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_TimerObj() override {} + + private: + static int ObjDefnID; +}; + +#endif // FXJS_CJS_TIMEROBJ_H_ diff --git a/fxjs/cjs_util.cpp b/fxjs/cjs_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57267ad4188466e08023ff124a2fb27c974e4696 --- /dev/null +++ b/fxjs/cjs_util.cpp @@ -0,0 +1,471 @@ +// 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 "fxjs/cjs_util.h" + +#include + +#include +#include +#include +#include +#include + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/JS_Define.h" +#include "fxjs/cjs_event_context.h" +#include "fxjs/cjs_eventhandler.h" +#include "fxjs/cjs_object.h" +#include "fxjs/cjs_publicmethods.h" +#include "fxjs/cjs_runtime.h" +#include "fxjs/js_resources.h" + +#if _FX_OS_ == _FX_OS_ANDROID_ +#include +#endif + +namespace { + +// Map PDF-style directives to equivalent wcsftime directives. Not +// all have direct equivalents, though. +struct TbConvert { + const wchar_t* lpszJSMark; + const wchar_t* lpszCppMark; +}; + +// Map PDF-style directives lacking direct wcsftime directives to +// the value with which they will be replaced. +struct TbConvertAdditional { + const wchar_t* lpszJSMark; + int iValue; +}; + +const TbConvert TbConvertTable[] = { + {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"}, + {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"}, + {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"}, + {L"TT", L"%p"}, +#if defined(_WIN32) + {L"tt", L"%p"}, {L"h", L"%#I"}, +#else + {L"tt", L"%P"}, {L"h", L"%l"}, +#endif +}; + +} // namespace + +const JSMethodSpec CJS_Util::MethodSpecs[] = { + {"printd", printd_static}, + {"printf", printf_static}, + {"printx", printx_static}, + {"scand", scand_static}, + {"byteToChar", byteToChar_static}}; + +int CJS_Util::ObjDefnID = -1; + +// static +void CJS_Util::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("util", FXJSOBJTYPE_STATIC, + JSConstructor, JSDestructor); + DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {} + +util::~util() {} + +CJS_Return util::printf(CJS_Runtime* pRuntime, + const std::vector>& params) { + const size_t iSize = params.size(); + if (iSize < 1) + return CJS_Return(false); + + std::wstring unsafe_fmt_string(pRuntime->ToWideString(params[0]).c_str()); + std::vector unsafe_conversion_specifiers; + int iOffset = 0; + int iOffend = 0; + unsafe_fmt_string.insert(unsafe_fmt_string.begin(), L'S'); + while (iOffset != -1) { + iOffend = unsafe_fmt_string.find(L"%", iOffset + 1); + std::wstring strSub; + if (iOffend == -1) + strSub = unsafe_fmt_string.substr(iOffset); + else + strSub = unsafe_fmt_string.substr(iOffset, iOffend - iOffset); + unsafe_conversion_specifiers.push_back(strSub); + iOffset = iOffend; + } + + std::wstring c_strResult; + for (size_t iIndex = 0; iIndex < unsafe_conversion_specifiers.size(); + ++iIndex) { + std::wstring c_strFormat = unsafe_conversion_specifiers[iIndex]; + if (iIndex == 0) { + c_strResult = c_strFormat; + continue; + } + + if (iIndex >= iSize) { + c_strResult += c_strFormat; + continue; + } + + WideString strSegment; + switch (ParseDataType(&c_strFormat)) { + case UTIL_INT: + strSegment = WideString::Format(c_strFormat.c_str(), + pRuntime->ToInt32(params[iIndex])); + break; + case UTIL_DOUBLE: + strSegment = WideString::Format(c_strFormat.c_str(), + pRuntime->ToDouble(params[iIndex])); + break; + case UTIL_STRING: + strSegment = + WideString::Format(c_strFormat.c_str(), + pRuntime->ToWideString(params[iIndex]).c_str()); + break; + default: + strSegment = WideString::Format(L"%ls", c_strFormat.c_str()); + break; + } + c_strResult += strSegment.c_str(); + } + + c_strResult.erase(c_strResult.begin()); + return CJS_Return(pRuntime->NewString(c_strResult.c_str())); +} + +CJS_Return util::printd(CJS_Runtime* pRuntime, + const std::vector>& params) { + const size_t iSize = params.size(); + if (iSize < 2) + return CJS_Return(false); + + if (params[1].IsEmpty() || !params[1]->IsDate()) + return CJS_Return(JSGetStringFromID(JSMessage::kSecondParamNotDateError)); + + v8::Local v8_date = params[1].As(); + if (v8_date.IsEmpty() || std::isnan(pRuntime->ToDouble(v8_date))) { + return CJS_Return( + JSGetStringFromID(JSMessage::kSecondParamInvalidDateError)); + } + + double date = JS_LocalTime(pRuntime->ToDouble(v8_date)); + int year = JS_GetYearFromTime(date); + int month = JS_GetMonthFromTime(date) + 1; // One-based. + int day = JS_GetDayFromTime(date); + int hour = JS_GetHourFromTime(date); + int min = JS_GetMinFromTime(date); + int sec = JS_GetSecFromTime(date); + + if (params[0]->IsNumber()) { + WideString swResult; + switch (pRuntime->ToInt32(params[0])) { + case 0: + swResult = WideString::Format(L"D:%04d%02d%02d%02d%02d%02d", year, + month, day, hour, min, sec); + break; + case 1: + swResult = WideString::Format(L"%04d.%02d.%02d %02d:%02d:%02d", year, + month, day, hour, min, sec); + break; + case 2: + swResult = WideString::Format(L"%04d/%02d/%02d %02d:%02d:%02d", year, + month, day, hour, min, sec); + break; + default: + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + } + + return CJS_Return(pRuntime->NewString(swResult.c_str())); + } + + if (params[0]->IsString()) { + // We don't support XFAPicture at the moment. + if (iSize > 2 && pRuntime->ToBoolean(params[2])) + return CJS_Return(JSGetStringFromID(JSMessage::kNotSupportedError)); + + // Convert PDF-style format specifiers to wcsftime specifiers. Remove any + // pre-existing %-directives before inserting our own. + std::basic_string cFormat = + pRuntime->ToWideString(params[0]).c_str(); + cFormat.erase(std::remove(cFormat.begin(), cFormat.end(), '%'), + cFormat.end()); + + for (size_t i = 0; i < FX_ArraySize(TbConvertTable); ++i) { + int iStart = 0; + int iEnd; + while ((iEnd = cFormat.find(TbConvertTable[i].lpszJSMark, iStart)) != + -1) { + cFormat.replace(iEnd, wcslen(TbConvertTable[i].lpszJSMark), + TbConvertTable[i].lpszCppMark); + iStart = iEnd; + } + } + + if (year < 0) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + static const TbConvertAdditional cTableAd[] = { + {L"m", month}, {L"d", day}, + {L"H", hour}, {L"h", hour > 12 ? hour - 12 : hour}, + {L"M", min}, {L"s", sec}, + }; + + for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) { + int iStart = 0; + int iEnd; + while ((iEnd = cFormat.find(cTableAd[i].lpszJSMark, iStart)) != -1) { + if (iEnd > 0) { + if (cFormat[iEnd - 1] == L'%') { + iStart = iEnd + 1; + continue; + } + } + cFormat.replace(iEnd, wcslen(cTableAd[i].lpszJSMark), + WideString::Format(L"%d", cTableAd[i].iValue).c_str()); + iStart = iEnd; + } + } + + struct tm time = {}; + time.tm_year = year - 1900; + time.tm_mon = month - 1; + time.tm_mday = day; + time.tm_hour = hour; + time.tm_min = min; + time.tm_sec = sec; + + wchar_t buf[64] = {}; + FXSYS_wcsftime(buf, 64, cFormat.c_str(), &time); + cFormat = buf; + return CJS_Return(pRuntime->NewString(cFormat.c_str())); + } + + return CJS_Return(JSGetStringFromID(JSMessage::kTypeError)); +} + +CJS_Return util::printx(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + return CJS_Return( + pRuntime->NewString(printx(pRuntime->ToWideString(params[0]), + pRuntime->ToWideString(params[1])) + .c_str())); +} + +enum CaseMode { kPreserveCase, kUpperCase, kLowerCase }; + +static wchar_t TranslateCase(wchar_t input, CaseMode eMode) { + if (eMode == kLowerCase && FXSYS_isupper(input)) + return input | 0x20; + if (eMode == kUpperCase && FXSYS_islower(input)) + return input & ~0x20; + return input; +} + +WideString util::printx(const WideString& wsFormat, + const WideString& wsSource) { + WideString wsResult; + size_t iSourceIdx = 0; + size_t iFormatIdx = 0; + CaseMode eCaseMode = kPreserveCase; + bool bEscaped = false; + while (iFormatIdx < wsFormat.GetLength()) { + if (bEscaped) { + bEscaped = false; + wsResult += wsFormat[iFormatIdx]; + ++iFormatIdx; + continue; + } + switch (wsFormat[iFormatIdx]) { + case '\\': { + bEscaped = true; + ++iFormatIdx; + } break; + case '<': { + eCaseMode = kLowerCase; + ++iFormatIdx; + } break; + case '>': { + eCaseMode = kUpperCase; + ++iFormatIdx; + } break; + case '=': { + eCaseMode = kPreserveCase; + ++iFormatIdx; + } break; + case '?': { + if (iSourceIdx < wsSource.GetLength()) { + wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); + ++iSourceIdx; + } + ++iFormatIdx; + } break; + case 'X': { + if (iSourceIdx < wsSource.GetLength()) { + if (FXSYS_iswalnum(wsSource[iSourceIdx])) { + wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); + ++iFormatIdx; + } + ++iSourceIdx; + } else { + ++iFormatIdx; + } + } break; + case 'A': { + if (iSourceIdx < wsSource.GetLength()) { + if (FXSYS_iswalpha(wsSource[iSourceIdx])) { + wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); + ++iFormatIdx; + } + ++iSourceIdx; + } else { + ++iFormatIdx; + } + } break; + case '9': { + if (iSourceIdx < wsSource.GetLength()) { + if (std::iswdigit(wsSource[iSourceIdx])) { + wsResult += wsSource[iSourceIdx]; + ++iFormatIdx; + } + ++iSourceIdx; + } else { + ++iFormatIdx; + } + } break; + case '*': { + if (iSourceIdx < wsSource.GetLength()) { + wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode); + ++iSourceIdx; + } else { + ++iFormatIdx; + } + } break; + default: { + wsResult += wsFormat[iFormatIdx]; + ++iFormatIdx; + } break; + } + } + return wsResult; +} + +CJS_Return util::scand(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 2) + return CJS_Return(false); + + WideString sFormat = pRuntime->ToWideString(params[0]); + WideString sDate = pRuntime->ToWideString(params[1]); + double dDate = JS_GetDateTime(); + if (sDate.GetLength() > 0) + dDate = CJS_PublicMethods::MakeRegularDate(sDate, sFormat, nullptr); + + if (std::isnan(dDate)) + return CJS_Return(pRuntime->NewUndefined()); + return CJS_Return(pRuntime->NewDate(dDate)); +} + +CJS_Return util::byteToChar(CJS_Runtime* pRuntime, + const std::vector>& params) { + if (params.size() < 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int arg = pRuntime->ToInt32(params[0]); + if (arg < 0 || arg > 255) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + WideString wStr(static_cast(arg)); + return CJS_Return(pRuntime->NewString(wStr.c_str())); +} + +// Ensure that sFormat contains at most one well-understood printf formatting +// directive which is safe to use with a single argument, and return the type +// of argument expected, or -1 otherwise. If -1 is returned, it is NOT safe +// to use sFormat with printf() and it must be copied byte-by-byte. +int util::ParseDataType(std::wstring* sFormat) { + enum State { BEFORE, FLAGS, WIDTH, PRECISION, SPECIFIER, AFTER }; + + int result = -1; + State state = BEFORE; + size_t precision_digits = 0; + size_t i = 0; + while (i < sFormat->length()) { + wchar_t c = (*sFormat)[i]; + switch (state) { + case BEFORE: + if (c == L'%') + state = FLAGS; + break; + case FLAGS: + if (c == L'+' || c == L'-' || c == L'#' || c == L' ') { + // Stay in same state. + } else { + state = WIDTH; + continue; // Re-process same character. + } + break; + case WIDTH: + if (c == L'*') + return -1; + if (std::iswdigit(c)) { + // Stay in same state. + } else if (c == L'.') { + state = PRECISION; + } else { + state = SPECIFIER; + continue; // Re-process same character. + } + break; + case PRECISION: + if (c == L'*') + return -1; + if (std::iswdigit(c)) { + // Stay in same state. + ++precision_digits; + } else { + state = SPECIFIER; + continue; // Re-process same character. + } + break; + case SPECIFIER: + if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' || + c == L'u' || c == L'x' || c == L'X') { + result = UTIL_INT; + } else if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || + c == L'G') { + result = UTIL_DOUBLE; + } else if (c == L's' || c == L'S') { + // Map s to S since we always deal internally with wchar_t strings. + // TODO(tsepez): Probably 100% borked. %S is not a standard + // conversion. + (*sFormat)[i] = L'S'; + result = UTIL_STRING; + } else { + return -1; + } + state = AFTER; + break; + case AFTER: + if (c == L'%') + return -1; + // Stay in same state until string exhausted. + break; + } + ++i; + } + // See https://crbug.com/740166 + if (result == UTIL_INT && precision_digits > 2) + return -1; + + return result; +} diff --git a/fxjs/cjs_util.h b/fxjs/cjs_util.h new file mode 100644 index 0000000000000000000000000000000000000000..cc2026dfc71fec707883c381ece7c8242c7f0f81 --- /dev/null +++ b/fxjs/cjs_util.h @@ -0,0 +1,63 @@ +// 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 FXJS_CJS_UTIL_H_ +#define FXJS_CJS_UTIL_H_ + +#include +#include + +#include "fxjs/JS_Define.h" + +// Return values for ParseDataType() below. +#define UTIL_INT 0 +#define UTIL_DOUBLE 1 +#define UTIL_STRING 2 + +class util : public CJS_EmbedObj { + public: + explicit util(CJS_Object* pJSObject); + ~util() override; + + CJS_Return printd(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return printf(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return printx(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return scand(CJS_Runtime* pRuntime, + const std::vector>& params); + CJS_Return byteToChar(CJS_Runtime* pRuntime, + const std::vector>& params); + + static WideString printx(const WideString& cFormat, + const WideString& cSource); + + private: + friend class CJS_Util_ParseDataType_Test; + + static int ParseDataType(std::wstring* sFormat); +}; + +class CJS_Util : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Util(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Util() override {} + + JS_STATIC_METHOD(printd, util); + JS_STATIC_METHOD(printf, util); + JS_STATIC_METHOD(printx, util); + JS_STATIC_METHOD(scand, util); + JS_STATIC_METHOD(byteToChar, util); + + private: + static int ObjDefnID; + static const JSMethodSpec MethodSpecs[]; +}; + +#endif // FXJS_CJS_UTIL_H_ diff --git a/fxjs/cjs_util_unittest.cpp b/fxjs/cjs_util_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f43f0fcb6097e7b9c1ae01fdab2c033afd75eda --- /dev/null +++ b/fxjs/cjs_util_unittest.cpp @@ -0,0 +1,113 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fxjs/cjs_util.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CJS_Util, ParseDataType) { + struct ParseDataTypeCase { + const wchar_t* const input_string; + const int expected; + }; + + // Commented out tests follow the spec but are not passing. + const ParseDataTypeCase cases[] = { + // Not conversions + {L"", -1}, + {L"d", -1}, + + // Simple cases + {L"%d", UTIL_INT}, + {L"%x", UTIL_INT}, + {L"%f", UTIL_DOUBLE}, + {L"%s", UTIL_STRING}, + + // nDecSep Not implemented + // {L"%,0d", UTIL_INT}, + // {L"%,1d", UTIL_INT}, + // {L"%,2d", UTIL_INT}, + // {L"%,3d", UTIL_INT}, + // {L"%,4d", -1}, + // {L"%,d", -1}, + + // cFlags("+ 0#"") are only valid for numeric conversions. + {L"%+d", UTIL_INT}, + {L"%+x", UTIL_INT}, + {L"%+f", UTIL_DOUBLE}, + // {L"%+s", -1}, + {L"% d", UTIL_INT}, + {L"% x", UTIL_INT}, + {L"% f", UTIL_DOUBLE}, + // {L"% s", -1}, + {L"%0d", UTIL_INT}, + {L"%0x", UTIL_INT}, + {L"%0f", UTIL_DOUBLE}, + // {L"%0s", -1}, + {L"%#d", UTIL_INT}, + {L"%#x", UTIL_INT}, + {L"%#f", UTIL_DOUBLE}, + // {L"%#s", -1}, + + // nWidth should work. for all conversions, can be combined with cFlags=0 + // for numbers. + {L"%5d", UTIL_INT}, + {L"%05d", UTIL_INT}, + {L"%5x", UTIL_INT}, + {L"%05x", UTIL_INT}, + {L"%5f", UTIL_DOUBLE}, + {L"%05f", UTIL_DOUBLE}, + {L"%5s", UTIL_STRING}, + // {L"%05s", -1}, + + // nPrecision should only work for float + // {L"%.5d", -1}, + // {L"%.5x", -1}, + {L"%.5f", UTIL_DOUBLE}, + // {L"%.5s", -1}, + // {L"%.14d", -1}, + // {L"%.14x", -1}, + {L"%.14f", UTIL_DOUBLE}, + // {L"%.14s", -1}, + // {L"%.f", -1}, + + // See https://crbug.com/740166 + // nPrecision too large (> 260) causes crashes in Windows. + // Avoid this by limiting to two digits + {L"%.1d", UTIL_INT}, + {L"%.10d", UTIL_INT}, + {L"%.100d", -1}, + + // Unexpected characters + {L"%ad", -1}, + {L"%bx", -1}, + // {L"%cf", -1}, + // {L"%es", -1}, + // {L"%gd", -1}, + {L"%hx", -1}, + // {L"%if", -1}, + {L"%js", -1}, + {L"%@d", -1}, + {L"%~x", -1}, + {L"%[f", -1}, + {L"%\0s", -1}, + {L"%\nd", -1}, + {L"%\rx", -1}, + // {L"%%f", -1}, + // {L"% s", -1}, + + // Combine multiple valid components + {L"%+6d", UTIL_INT}, + {L"% 7x", UTIL_INT}, + {L"%#9.3f", UTIL_DOUBLE}, + {L"%10s", UTIL_STRING}, + }; + + for (size_t i = 0; i < FX_ArraySize(cases); i++) { + std::wstring input(cases[i].input_string); + EXPECT_EQ(cases[i].expected, util::ParseDataType(&input)) + << cases[i].input_string; + } +} diff --git a/fxjs/cjs_v8.cpp b/fxjs/cjs_v8.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f77ec6a88a02a364895d88b37c537105bc4ba30 --- /dev/null +++ b/fxjs/cjs_v8.cpp @@ -0,0 +1,241 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_v8.h" + +#ifdef PDF_ENABLE_XFA +#include "fxjs/cfxjse_context.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#endif // PDF_ENABLE_XFA + +CJS_V8::CJS_V8(v8::Isolate* isolate) : m_isolate(isolate) {} + +CJS_V8::~CJS_V8() { + m_V8PersistentContext.Reset(); +} + +v8::Local CJS_V8::GetObjectProperty( + v8::Local pObj, + const WideString& wsPropertyName) { + if (pObj.IsEmpty()) + return v8::Local(); + v8::Local val; + if (!pObj->Get(m_isolate->GetCurrentContext(), + NewString(wsPropertyName.AsStringView())) + .ToLocal(&val)) + return v8::Local(); + return val; +} + +std::vector CJS_V8::GetObjectPropertyNames( + v8::Local pObj) { + if (pObj.IsEmpty()) + return std::vector(); + + v8::Local val; + v8::Local context = m_isolate->GetCurrentContext(); + if (!pObj->GetPropertyNames(context).ToLocal(&val)) + return std::vector(); + + std::vector result; + for (uint32_t i = 0; i < val->Length(); ++i) { + result.push_back(ToWideString(val->Get(context, i).ToLocalChecked())); + } + + return result; +} + +void CJS_V8::PutObjectProperty(v8::Local pObj, + const WideString& wsPropertyName, + v8::Local pPut) { + if (pObj.IsEmpty()) + return; + pObj->Set(m_isolate->GetCurrentContext(), + NewString(wsPropertyName.AsStringView()), pPut) + .FromJust(); +} + +v8::Local CJS_V8::NewArray() { + return v8::Array::New(m_isolate); +} + +unsigned CJS_V8::PutArrayElement(v8::Local pArray, + unsigned index, + v8::Local pValue) { + if (pArray.IsEmpty()) + return 0; + if (pArray->Set(m_isolate->GetCurrentContext(), index, pValue).IsNothing()) + return 0; + return 1; +} + +v8::Local CJS_V8::GetArrayElement(v8::Local pArray, + unsigned index) { + if (pArray.IsEmpty()) + return v8::Local(); + v8::Local val; + if (!pArray->Get(m_isolate->GetCurrentContext(), index).ToLocal(&val)) + return v8::Local(); + return val; +} + +unsigned CJS_V8::GetArrayLength(v8::Local pArray) { + if (pArray.IsEmpty()) + return 0; + return pArray->Length(); +} + +v8::Local CJS_V8::NewLocalContext() { + return v8::Local::New(m_isolate, m_V8PersistentContext); +} + +v8::Local CJS_V8::GetPersistentContext() { + return m_V8PersistentContext.Get(m_isolate); +} + +v8::Local CJS_V8::NewNumber(int number) { + return v8::Int32::New(m_isolate, number); +} + +v8::Local CJS_V8::NewNumber(double number) { + return v8::Number::New(m_isolate, number); +} + +v8::Local CJS_V8::NewNumber(float number) { + return v8::Number::New(m_isolate, (float)number); +} + +v8::Local CJS_V8::NewBoolean(bool b) { + return v8::Boolean::New(m_isolate, b); +} + +v8::Local CJS_V8::NewString(const ByteStringView& str) { + v8::Isolate* pIsolate = m_isolate ? m_isolate : v8::Isolate::GetCurrent(); + return v8::String::NewFromUtf8(pIsolate, str.unterminated_c_str(), + v8::NewStringType::kNormal, str.GetLength()) + .ToLocalChecked(); +} + +v8::Local CJS_V8::NewString(const WideStringView& str) { + // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t + // wide-strings isn't handled by v8, so use UTF8 as a common + // intermediate format. + return NewString(FX_UTF8Encode(str).AsStringView()); +} + +v8::Local CJS_V8::NewNull() { + return v8::Null(m_isolate); +} + +v8::Local CJS_V8::NewUndefined() { + return v8::Undefined(m_isolate); +} + +v8::Local CJS_V8::NewDate(double d) { + return v8::Date::New(m_isolate->GetCurrentContext(), d) + .ToLocalChecked() + .As(); +} + +int CJS_V8::ToInt32(v8::Local pValue) { + if (pValue.IsEmpty()) + return 0; + v8::Local context = m_isolate->GetCurrentContext(); + v8::MaybeLocal maybe_int32 = pValue->ToInt32(context); + if (maybe_int32.IsEmpty()) + return 0; + return maybe_int32.ToLocalChecked()->Value(); +} + +bool CJS_V8::ToBoolean(v8::Local pValue) { + if (pValue.IsEmpty()) + return false; + v8::Local context = m_isolate->GetCurrentContext(); + v8::MaybeLocal maybe_boolean = pValue->ToBoolean(context); + if (maybe_boolean.IsEmpty()) + return false; + return maybe_boolean.ToLocalChecked()->Value(); +} + +double CJS_V8::ToDouble(v8::Local pValue) { + if (pValue.IsEmpty()) + return 0.0; + v8::Local context = m_isolate->GetCurrentContext(); + v8::MaybeLocal maybe_number = pValue->ToNumber(context); + if (maybe_number.IsEmpty()) + return 0.0; + return maybe_number.ToLocalChecked()->Value(); +} + +WideString CJS_V8::ToWideString(v8::Local pValue) { + if (pValue.IsEmpty()) + return WideString(); + v8::Local context = m_isolate->GetCurrentContext(); + v8::MaybeLocal maybe_string = pValue->ToString(context); + if (maybe_string.IsEmpty()) + return WideString(); + v8::String::Utf8Value s(m_isolate, maybe_string.ToLocalChecked()); + return WideString::FromUTF8(ByteStringView(*s, s.length())); +} + +ByteString CJS_V8::ToByteString(v8::Local pValue) { + if (pValue.IsEmpty()) + return ByteString(); + v8::Local context = m_isolate->GetCurrentContext(); + v8::MaybeLocal maybe_string = pValue->ToString(context); + if (maybe_string.IsEmpty()) + return ByteString(); + v8::String::Utf8Value s(m_isolate, maybe_string.ToLocalChecked()); + return ByteString(*s); +} + +v8::Local CJS_V8::ToObject(v8::Local pValue) { + if (pValue.IsEmpty() || !pValue->IsObject()) + return v8::Local(); + v8::Local context = m_isolate->GetCurrentContext(); + return pValue->ToObject(context).ToLocalChecked(); +} + +v8::Local CJS_V8::ToArray(v8::Local pValue) { + if (pValue.IsEmpty() || !pValue->IsArray()) + return v8::Local(); + v8::Local context = m_isolate->GetCurrentContext(); + return v8::Local::Cast(pValue->ToObject(context).ToLocalChecked()); +} + +void CJS_V8::SetConstArray(const WideString& name, v8::Local array) { + m_ConstArrays[name] = v8::Global(GetIsolate(), array); +} + +v8::Local CJS_V8::GetConstArray(const WideString& name) { + return v8::Local::New(GetIsolate(), m_ConstArrays[name]); +} + +#ifdef PDF_ENABLE_XFA +CXFA_Object* CJS_V8::ToXFAObject(v8::Local obj) { + ASSERT(!obj.IsEmpty()); + + if (!obj->IsObject()) + return nullptr; + + CFXJSE_HostObject* hostObj = + FXJSE_RetrieveObjectBinding(obj.As(), nullptr); + if (!hostObj || hostObj->type() != CFXJSE_HostObject::kXFA) + return nullptr; + return static_cast(hostObj); +} + +v8::Local CJS_V8::NewXFAObject( + CXFA_Object* obj, + v8::Global& tmpl) { + v8::EscapableHandleScope scope(m_isolate); + v8::Local klass = + v8::Local::New(m_isolate, tmpl); + v8::Local object = klass->InstanceTemplate()->NewInstance(); + FXJSE_UpdateObjectBinding(object, obj); + return scope.Escape(object); +} +#endif // PDF_ENABLE_XFA diff --git a/fxjs/cjs_v8.h b/fxjs/cjs_v8.h new file mode 100644 index 0000000000000000000000000000000000000000..b79d236670e9e5f1629c34e53a758a6e577a4502 --- /dev/null +++ b/fxjs/cjs_v8.h @@ -0,0 +1,93 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_V8_H_ +#define FXJS_CJS_V8_H_ + +#include +#include + +#include +#include + +#include "core/fxcrt/bytestring.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/widestring.h" + +#ifdef PDF_ENABLE_XFA +class CXFA_Object; +#endif // PDF_ENABLE_XFA + +class CJS_V8 { + public: + explicit CJS_V8(v8::Isolate* pIsolate); + virtual ~CJS_V8(); + + v8::Isolate* GetIsolate() const { return m_isolate; } + + v8::Local NewLocalContext(); + v8::Local GetPersistentContext(); + + v8::Local NewNull(); + v8::Local NewUndefined(); + v8::Local NewArray(); + v8::Local NewNumber(int number); + v8::Local NewNumber(double number); + v8::Local NewNumber(float number); + v8::Local NewBoolean(bool b); + v8::Local NewString(const ByteStringView& str); + v8::Local NewString(const WideStringView& str); + v8::Local NewDate(double d); + + int ToInt32(v8::Local pValue); + bool ToBoolean(v8::Local pValue); + double ToDouble(v8::Local pValue); + WideString ToWideString(v8::Local pValue); + ByteString ToByteString(v8::Local pValue); + v8::Local ToObject(v8::Local pValue); + v8::Local ToArray(v8::Local pValue); + +#ifdef PDF_ENABLE_XFA + CXFA_Object* ToXFAObject(v8::Local obj); + v8::Local NewXFAObject(CXFA_Object* obj, + v8::Global& tmpl); +#endif // PDF_ENABLE_XFA + + // Arrays. + unsigned GetArrayLength(v8::Local pArray); + v8::Local GetArrayElement(v8::Local pArray, + unsigned index); + unsigned PutArrayElement(v8::Local pArray, + unsigned index, + v8::Local pValue); + + void SetConstArray(const WideString& name, v8::Local array); + v8::Local GetConstArray(const WideString& name); + + // Objects. + std::vector GetObjectPropertyNames(v8::Local pObj); + v8::Local GetObjectProperty(v8::Local pObj, + const WideString& PropertyName); + void PutObjectProperty(v8::Local pObj, + const WideString& PropertyName, + v8::Local pValue); + + protected: + void SetIsolate(v8::Isolate* pIsolate) { m_isolate = pIsolate; } + void ClearConstArray() { m_ConstArrays.clear(); } + + void ResetPersistentContext(v8::Local context) { + m_V8PersistentContext.Reset(m_isolate, context); + } + void ReleasePersistentContext() { m_V8PersistentContext.Reset(); } + + private: + v8::Isolate* m_isolate; + std::map> m_ConstArrays; + v8::Global m_V8PersistentContext; +}; + +#endif // FXJS_CJS_V8_H_ diff --git a/fxjs/cjs_zoomtype.cpp b/fxjs/cjs_zoomtype.cpp new file mode 100644 index 0000000000000000000000000000000000000000..528bba0a8d475580287c62d4cae80f5393fbc855 --- /dev/null +++ b/fxjs/cjs_zoomtype.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/cjs_zoomtype.h" + +const JSConstSpec CJS_Zoomtype::ConstSpecs[] = { + {"none", JSConstSpec::String, 0, "NoVary"}, + {"fitP", JSConstSpec::String, 0, "FitPage"}, + {"fitW", JSConstSpec::String, 0, "FitWidth"}, + {"fitH", JSConstSpec::String, 0, "FitHeight"}, + {"fitV", JSConstSpec::String, 0, "FitVisibleWidth"}, + {"pref", JSConstSpec::String, 0, "Preferred"}, + {"refW", JSConstSpec::String, 0, "ReflowWidth"}}; + +int CJS_Zoomtype::ObjDefnID = -1; + +// static +void CJS_Zoomtype::DefineJSObjects(CFXJS_Engine* pEngine) { + ObjDefnID = + pEngine->DefineObj("zoomtype", FXJSOBJTYPE_STATIC, nullptr, nullptr); + DefineConsts(pEngine, ObjDefnID, ConstSpecs, FX_ArraySize(ConstSpecs)); +} diff --git a/fxjs/cjs_zoomtype.h b/fxjs/cjs_zoomtype.h new file mode 100644 index 0000000000000000000000000000000000000000..14db0a4c96d72394f66ef22a62022784f3ed8e02 --- /dev/null +++ b/fxjs/cjs_zoomtype.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_CJS_ZOOMTYPE_H_ +#define FXJS_CJS_ZOOMTYPE_H_ + +#include "fxjs/JS_Define.h" + +class CJS_Zoomtype : public CJS_Object { + public: + static void DefineJSObjects(CFXJS_Engine* pEngine); + + explicit CJS_Zoomtype(v8::Local pObject) : CJS_Object(pObject) {} + ~CJS_Zoomtype() override {} + + private: + static int ObjDefnID; + static const JSConstSpec ConstSpecs[]; +}; + +#endif // FXJS_CJS_ZOOMTYPE_H_ diff --git a/fxjs/fxjs_v8.cpp b/fxjs/fxjs_v8.cpp index b0e1a1b260bc1312548c48470cba1001ea2176c0..50345cfcd17749a2f3d0f5a8064e32e7a8bfa6f3 100644 --- a/fxjs/fxjs_v8.cpp +++ b/fxjs/fxjs_v8.cpp @@ -8,7 +8,7 @@ #include -#include "core/fxcrt/fx_basic.h" +#include "third_party/base/allocator/partition_allocator/partition_alloc.h" // Keep this consistent with the values defined in gin/public/context_holder.h // (without actually requiring a dependency on gin itself for the standalone @@ -144,15 +144,24 @@ static v8::Local GetGlobalObjectTemplate( } void* FXJS_ArrayBufferAllocator::Allocate(size_t length) { - return calloc(1, length); + if (length > kMaxAllowedBytes) + return nullptr; + void* p = AllocateUninitialized(length); + if (p) + memset(p, 0, length); + return p; } void* FXJS_ArrayBufferAllocator::AllocateUninitialized(size_t length) { - return malloc(length); + if (length > kMaxAllowedBytes) + return nullptr; + return pdfium::base::PartitionAllocGeneric( + gArrayBufferPartitionAllocator.root(), length, "FXJS_ArrayBuffer"); } void FXJS_ArrayBufferAllocator::Free(void* data, size_t length) { - free(data); + pdfium::base::PartitionFreeGeneric(gArrayBufferPartitionAllocator.root(), + data); } void V8TemplateMapTraits::Dispose(v8::Isolate* isolate, @@ -161,15 +170,16 @@ void V8TemplateMapTraits::Dispose(v8::Isolate* isolate, v8::Local obj = value.Get(isolate); if (obj.IsEmpty()) return; - CFXJS_Engine* pEngine = CFXJS_Engine::CurrentEngineFromIsolate(isolate); - int id = pEngine->GetObjDefnID(obj); + int id = CFXJS_Engine::GetObjDefnID(obj); if (id == -1) return; CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(isolate, id); if (!pObjDef) return; - if (pObjDef->m_pDestructor) - pObjDef->m_pDestructor(pEngine, obj); + if (pObjDef->m_pDestructor) { + pObjDef->m_pDestructor(CFXJS_Engine::CurrentEngineFromIsolate(isolate), + obj); + } CFXJS_Engine::FreeObjectPrivate(obj); } @@ -244,13 +254,11 @@ FXJS_PerIsolateData* FXJS_PerIsolateData::Get(v8::Isolate* pIsolate) { FXJS_PerIsolateData::FXJS_PerIsolateData(v8::Isolate* pIsolate) : m_pDynamicObjsMap(new V8TemplateMap(pIsolate)) {} -CFXJS_Engine::CFXJS_Engine() : m_isolate(nullptr) {} +CFXJS_Engine::CFXJS_Engine() : CJS_V8(nullptr) {} -CFXJS_Engine::CFXJS_Engine(v8::Isolate* pIsolate) : m_isolate(pIsolate) {} +CFXJS_Engine::CFXJS_Engine(v8::Isolate* pIsolate) : CJS_V8(pIsolate) {} -CFXJS_Engine::~CFXJS_Engine() { - m_V8PersistentContext.Reset(); -} +CFXJS_Engine::~CFXJS_Engine() = default; // static CFXJS_Engine* CFXJS_Engine::CurrentEngineFromIsolate(v8::Isolate* pIsolate) { @@ -282,43 +290,39 @@ int CFXJS_Engine::DefineObj(const char* sObjName, FXJSOBJTYPE eObjType, CFXJS_Engine::Constructor pConstructor, CFXJS_Engine::Destructor pDestructor) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); - FXJS_PerIsolateData::SetUp(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); + FXJS_PerIsolateData::SetUp(GetIsolate()); CFXJS_ObjDefinition* pObjDef = new CFXJS_ObjDefinition( - m_isolate, sObjName, eObjType, pConstructor, pDestructor); + GetIsolate(), sObjName, eObjType, pConstructor, pDestructor); return pObjDef->AssignID(); } void CFXJS_Engine::DefineObjMethod(int nObjDefnID, const char* sMethodName, v8::FunctionCallback pMethodCall) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); CFXJS_ObjDefinition* pObjDef = - CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID); + CFXJS_ObjDefinition::ForID(GetIsolate(), nObjDefnID); v8::Local fun = v8::FunctionTemplate::New( - m_isolate, pMethodCall, v8::Local(), pObjDef->GetSignature()); + GetIsolate(), pMethodCall, v8::Local(), + pObjDef->GetSignature()); fun->RemovePrototype(); - pObjDef->GetInstanceTemplate()->Set( - v8::String::NewFromUtf8(m_isolate, sMethodName, - v8::NewStringType::kNormal) - .ToLocalChecked(), - fun, v8::ReadOnly); + pObjDef->GetInstanceTemplate()->Set(NewString(sMethodName), fun, + v8::ReadOnly); } void CFXJS_Engine::DefineObjProperty(int nObjDefnID, const char* sPropName, v8::AccessorGetterCallback pPropGet, v8::AccessorSetterCallback pPropPut) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); CFXJS_ObjDefinition* pObjDef = - CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID); - pObjDef->GetInstanceTemplate()->SetAccessor( - v8::String::NewFromUtf8(m_isolate, sPropName, v8::NewStringType::kNormal) - .ToLocalChecked(), - pPropGet, pPropPut); + CFXJS_ObjDefinition::ForID(GetIsolate(), nObjDefnID); + pObjDef->GetInstanceTemplate()->SetAccessor(NewString(sPropName), pPropGet, + pPropPut); } void CFXJS_Engine::DefineObjAllProperties( @@ -327,10 +331,10 @@ void CFXJS_Engine::DefineObjAllProperties( v8::NamedPropertyGetterCallback pPropGet, v8::NamedPropertySetterCallback pPropPut, v8::NamedPropertyDeleterCallback pPropDel) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); CFXJS_ObjDefinition* pObjDef = - CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID); + CFXJS_ObjDefinition::ForID(GetIsolate(), nObjDefnID); pObjDef->GetInstanceTemplate()->SetNamedPropertyHandler(pPropGet, pPropPut, pPropQurey, pPropDel); } @@ -338,63 +342,56 @@ void CFXJS_Engine::DefineObjAllProperties( void CFXJS_Engine::DefineObjConst(int nObjDefnID, const char* sConstName, v8::Local pDefault) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); CFXJS_ObjDefinition* pObjDef = - CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID); - pObjDef->GetInstanceTemplate()->Set(m_isolate, sConstName, pDefault); + CFXJS_ObjDefinition::ForID(GetIsolate(), nObjDefnID); + pObjDef->GetInstanceTemplate()->Set(GetIsolate(), sConstName, pDefault); } void CFXJS_Engine::DefineGlobalMethod(const char* sMethodName, v8::FunctionCallback pMethodCall) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); v8::Local fun = - v8::FunctionTemplate::New(m_isolate, pMethodCall); + v8::FunctionTemplate::New(GetIsolate(), pMethodCall); fun->RemovePrototype(); - GetGlobalObjectTemplate(m_isolate)->Set( - v8::String::NewFromUtf8(m_isolate, sMethodName, - v8::NewStringType::kNormal) - .ToLocalChecked(), - fun, v8::ReadOnly); + GetGlobalObjectTemplate(GetIsolate()) + ->Set(NewString(sMethodName), fun, v8::ReadOnly); } void CFXJS_Engine::DefineGlobalConst(const wchar_t* sConstName, v8::FunctionCallback pConstGetter) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); - CFX_ByteString bsConst = FX_UTF8Encode(CFX_WideStringC(sConstName)); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); v8::Local fun = - v8::FunctionTemplate::New(m_isolate, pConstGetter); + v8::FunctionTemplate::New(GetIsolate(), pConstGetter); fun->RemovePrototype(); - GetGlobalObjectTemplate(m_isolate)->SetAccessorProperty( - v8::String::NewFromUtf8(m_isolate, bsConst.c_str(), - v8::NewStringType::kNormal) - .ToLocalChecked(), - fun); + GetGlobalObjectTemplate(GetIsolate()) + ->SetAccessorProperty(NewString(sConstName), fun); } void CFXJS_Engine::InitializeEngine() { - if (m_isolate == g_isolate) + if (GetIsolate() == g_isolate) ++g_isolate_ref_count; - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); // This has to happen before we call GetGlobalObjectTemplate because that - // method gets the PerIsolateData from m_isolate. - FXJS_PerIsolateData::SetUp(m_isolate); + // method gets the PerIsolateData from GetIsolate(). + FXJS_PerIsolateData::SetUp(GetIsolate()); - v8::Local v8Context = - v8::Context::New(m_isolate, nullptr, GetGlobalObjectTemplate(m_isolate)); + v8::Local v8Context = v8::Context::New( + GetIsolate(), nullptr, GetGlobalObjectTemplate(GetIsolate())); v8::Context::Scope context_scope(v8Context); v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, this); - int maxID = CFXJS_ObjDefinition::MaxID(m_isolate); + int maxID = CFXJS_ObjDefinition::MaxID(GetIsolate()); m_StaticObjects.resize(maxID + 1); for (int i = 0; i < maxID; ++i) { - CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(m_isolate, i); + CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(GetIsolate(), i); if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) { CFXJS_PerObjectData::SetInObject(new CFXJS_PerObjectData(i), v8Context->Global() @@ -408,42 +405,39 @@ void CFXJS_Engine::InitializeEngine() { .ToLocalChecked()); } } else if (pObjDef->m_ObjType == FXJSOBJTYPE_STATIC) { - v8::Local pObjName = - v8::String::NewFromUtf8(m_isolate, pObjDef->m_ObjName, - v8::NewStringType::kNormal, - strlen(pObjDef->m_ObjName)) - .ToLocalChecked(); - + v8::Local pObjName = NewString(pObjDef->m_ObjName); v8::Local obj = NewFxDynamicObj(i, true); - v8Context->Global()->Set(v8Context, pObjName, obj).FromJust(); - m_StaticObjects[i] = new v8::Global(m_isolate, obj); + if (!obj.IsEmpty()) { + v8Context->Global()->Set(v8Context, pObjName, obj).FromJust(); + m_StaticObjects[i] = new v8::Global(GetIsolate(), obj); + } else { + m_StaticObjects[i] = nullptr; + } } } - m_V8PersistentContext.Reset(m_isolate, v8Context); + ResetPersistentContext(v8Context); } void CFXJS_Engine::ReleaseEngine() { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::HandleScope handle_scope(m_isolate); - v8::Local context = - v8::Local::New(m_isolate, m_V8PersistentContext); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); + v8::Local context = NewLocalContext(); v8::Context::Scope context_scope(context); - - FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_isolate); + FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(GetIsolate()); if (!pData) return; - m_ConstArrays.clear(); + ClearConstArray(); - int maxID = CFXJS_ObjDefinition::MaxID(m_isolate); + int maxID = CFXJS_ObjDefinition::MaxID(GetIsolate()); for (int i = 0; i < maxID; ++i) { - CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(m_isolate, i); + CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(GetIsolate(), i); v8::Local pObj; if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) { pObj = context->Global()->GetPrototype()->ToObject(context).ToLocalChecked(); } else if (m_StaticObjects[i] && !m_StaticObjects[i]->IsEmpty()) { - pObj = v8::Local::New(m_isolate, *m_StaticObjects[i]); + pObj = v8::Local::New(GetIsolate(), *m_StaticObjects[i]); delete m_StaticObjects[i]; m_StaticObjects[i] = nullptr; } @@ -455,35 +449,30 @@ void CFXJS_Engine::ReleaseEngine() { } } - m_V8PersistentContext.Reset(); + ReleasePersistentContext(); - if (m_isolate == g_isolate && --g_isolate_ref_count > 0) + if (GetIsolate() == g_isolate && --g_isolate_ref_count > 0) return; delete pData; - m_isolate->SetData(g_embedderDataSlot, nullptr); + GetIsolate()->SetData(g_embedderDataSlot, nullptr); } -int CFXJS_Engine::Execute(const CFX_WideString& script, FXJSErr* pError) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::TryCatch try_catch(m_isolate); - CFX_ByteString bsScript = script.UTF8Encode(); - v8::Local context = m_isolate->GetCurrentContext(); +int CFXJS_Engine::Execute(const WideString& script, FXJSErr* pError) { + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::TryCatch try_catch(GetIsolate()); + v8::Local context = GetIsolate()->GetCurrentContext(); v8::Local compiled_script; - if (!v8::Script::Compile(context, - v8::String::NewFromUtf8(m_isolate, bsScript.c_str(), - v8::NewStringType::kNormal, - bsScript.GetLength()) - .ToLocalChecked()) + if (!v8::Script::Compile(context, NewString(script.AsStringView())) .ToLocal(&compiled_script)) { - v8::String::Utf8Value error(try_catch.Exception()); + v8::String::Utf8Value error(GetIsolate(), try_catch.Exception()); // TODO(tsepez): return error via pError->message. return -1; } v8::Local result; if (!compiled_script->Run(context).ToLocal(&result)) { - v8::String::Utf8Value error(try_catch.Exception()); + v8::String::Utf8Value error(GetIsolate(), try_catch.Exception()); // TODO(tsepez): return error via pError->message. return -1; } @@ -492,25 +481,26 @@ int CFXJS_Engine::Execute(const CFX_WideString& script, FXJSErr* pError) { v8::Local CFXJS_Engine::NewFxDynamicObj(int nObjDefnID, bool bStatic) { - v8::Isolate::Scope isolate_scope(m_isolate); - v8::Local context = m_isolate->GetCurrentContext(); + v8::Isolate::Scope isolate_scope(GetIsolate()); + v8::Local context = GetIsolate()->GetCurrentContext(); if (nObjDefnID == -1) { - v8::Local objTempl = v8::ObjectTemplate::New(m_isolate); + v8::Local objTempl = + v8::ObjectTemplate::New(GetIsolate()); v8::Local obj; if (!objTempl->NewInstance(context).ToLocal(&obj)) return v8::Local(); return obj; } - FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_isolate); + FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(GetIsolate()); if (!pData) return v8::Local(); - if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(m_isolate)) + if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(GetIsolate())) return v8::Local(); CFXJS_ObjDefinition* pObjDef = - CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID); + CFXJS_ObjDefinition::ForID(GetIsolate(), nObjDefnID); v8::Local obj; if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj)) return v8::Local(); @@ -520,31 +510,25 @@ v8::Local CFXJS_Engine::NewFxDynamicObj(int nObjDefnID, if (pObjDef->m_pConstructor) pObjDef->m_pConstructor(this, obj); - if (!bStatic && FXJS_PerIsolateData::Get(m_isolate)->m_pDynamicObjsMap) - FXJS_PerIsolateData::Get(m_isolate)->m_pDynamicObjsMap->set(pObjData, obj); + if (!bStatic && FXJS_PerIsolateData::Get(GetIsolate())->m_pDynamicObjsMap) + FXJS_PerIsolateData::Get(GetIsolate()) + ->m_pDynamicObjsMap->set(pObjData, obj); return obj; } v8::Local CFXJS_Engine::GetThisObj() { - v8::Isolate::Scope isolate_scope(m_isolate); - if (!FXJS_PerIsolateData::Get(m_isolate)) + v8::Isolate::Scope isolate_scope(GetIsolate()); + if (!FXJS_PerIsolateData::Get(GetIsolate())) return v8::Local(); // Return the global object. - v8::Local context = m_isolate->GetCurrentContext(); + v8::Local context = GetIsolate()->GetCurrentContext(); return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked(); } -void CFXJS_Engine::Error(const CFX_WideString& message) { - // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t - // wide-strings isn't handled by v8, so use UTF8 as a common - // intermediate format. - CFX_ByteString utf8_message = message.UTF8Encode(); - m_isolate->ThrowException(v8::String::NewFromUtf8(m_isolate, - utf8_message.c_str(), - v8::NewStringType::kNormal) - .ToLocalChecked()); +void CFXJS_Engine::Error(const WideString& message) { + GetIsolate()->ThrowException(NewString(message.AsStringView())); } void CFXJS_Engine::SetObjectPrivate(v8::Local pObj, void* p) { @@ -560,7 +544,7 @@ void* CFXJS_Engine::GetObjectPrivate(v8::Local pObj) { if (!pData && !pObj.IsEmpty()) { // It could be a global proxy object. v8::Local v = pObj->GetPrototype(); - v8::Local context = m_isolate->GetCurrentContext(); + v8::Local context = GetIsolate()->GetCurrentContext(); if (v->IsObject()) { pData = CFXJS_PerObjectData::GetFromObject( v->ToObject(context).ToLocalChecked()); @@ -568,172 +552,3 @@ void* CFXJS_Engine::GetObjectPrivate(v8::Local pObj) { } return pData ? pData->m_pPrivate : nullptr; } - -v8::Local CFXJS_Engine::GetObjectProperty( - v8::Local pObj, - const CFX_WideString& wsPropertyName) { - if (pObj.IsEmpty()) - return v8::Local(); - v8::Local val; - if (!pObj->Get(m_isolate->GetCurrentContext(), - NewString(wsPropertyName.AsStringC())) - .ToLocal(&val)) - return v8::Local(); - return val; -} - -std::vector CFXJS_Engine::GetObjectPropertyNames( - v8::Local pObj) { - if (pObj.IsEmpty()) - return std::vector(); - - v8::Local val; - v8::Local context = m_isolate->GetCurrentContext(); - if (!pObj->GetPropertyNames(context).ToLocal(&val)) - return std::vector(); - - std::vector result; - for (uint32_t i = 0; i < val->Length(); ++i) { - result.push_back(ToWideString(val->Get(context, i).ToLocalChecked())); - } - - return result; -} - -void CFXJS_Engine::PutObjectProperty(v8::Local pObj, - const CFX_WideString& wsPropertyName, - v8::Local pPut) { - if (pObj.IsEmpty()) - return; - pObj->Set(m_isolate->GetCurrentContext(), - NewString(wsPropertyName.AsStringC()), pPut) - .FromJust(); -} - - -v8::Local CFXJS_Engine::NewArray() { - return v8::Array::New(m_isolate); -} - -unsigned CFXJS_Engine::PutArrayElement(v8::Local pArray, - unsigned index, - v8::Local pValue) { - if (pArray.IsEmpty()) - return 0; - if (pArray->Set(m_isolate->GetCurrentContext(), index, pValue).IsNothing()) - return 0; - return 1; -} - -v8::Local CFXJS_Engine::GetArrayElement(v8::Local pArray, - unsigned index) { - if (pArray.IsEmpty()) - return v8::Local(); - v8::Local val; - if (!pArray->Get(m_isolate->GetCurrentContext(), index).ToLocal(&val)) - return v8::Local(); - return val; -} - -unsigned CFXJS_Engine::GetArrayLength(v8::Local pArray) { - if (pArray.IsEmpty()) - return 0; - return pArray->Length(); -} - -v8::Local CFXJS_Engine::NewLocalContext() { - return v8::Local::New(m_isolate, m_V8PersistentContext); -} - -v8::Local CFXJS_Engine::GetPersistentContext() { - return m_V8PersistentContext.Get(m_isolate); -} - -v8::Local CFXJS_Engine::NewNumber(int number) { - return v8::Int32::New(m_isolate, number); -} - -v8::Local CFXJS_Engine::NewNumber(double number) { - return v8::Number::New(m_isolate, number); -} - -v8::Local CFXJS_Engine::NewNumber(float number) { - return v8::Number::New(m_isolate, (float)number); -} - -v8::Local CFXJS_Engine::NewBoolean(bool b) { - return v8::Boolean::New(m_isolate, b); -} - -v8::Local CFXJS_Engine::NewString(const CFX_ByteStringC& str) { - v8::Isolate* pIsolate = m_isolate ? m_isolate : v8::Isolate::GetCurrent(); - return v8::String::NewFromUtf8(pIsolate, str.c_str(), - v8::NewStringType::kNormal, str.GetLength()) - .ToLocalChecked(); -} - -v8::Local CFXJS_Engine::NewString(const CFX_WideStringC& str) { - return NewString(FX_UTF8Encode(str).AsStringC()); -} - -v8::Local CFXJS_Engine::NewNull() { - return v8::Local(); -} - -v8::Local CFXJS_Engine::NewDate(double d) { - return v8::Date::New(m_isolate->GetCurrentContext(), d) - .ToLocalChecked() - .As(); -} - -int CFXJS_Engine::ToInt32(v8::Local pValue) { - if (pValue.IsEmpty()) - return 0; - v8::Local context = m_isolate->GetCurrentContext(); - return pValue->ToInt32(context).ToLocalChecked()->Value(); -} - -bool CFXJS_Engine::ToBoolean(v8::Local pValue) { - if (pValue.IsEmpty()) - return false; - v8::Local context = m_isolate->GetCurrentContext(); - return pValue->ToBoolean(context).ToLocalChecked()->Value(); -} - -double CFXJS_Engine::ToDouble(v8::Local pValue) { - if (pValue.IsEmpty()) - return 0.0; - v8::Local context = m_isolate->GetCurrentContext(); - return pValue->ToNumber(context).ToLocalChecked()->Value(); -} - -CFX_WideString CFXJS_Engine::ToWideString(v8::Local pValue) { - if (pValue.IsEmpty()) - return CFX_WideString(); - v8::Local context = m_isolate->GetCurrentContext(); - v8::String::Utf8Value s(pValue->ToString(context).ToLocalChecked()); - return CFX_WideString::FromUTF8(CFX_ByteStringC(*s, s.length())); -} - -v8::Local CFXJS_Engine::ToObject(v8::Local pValue) { - if (pValue.IsEmpty() || !pValue->IsObject()) - return v8::Local(); - v8::Local context = m_isolate->GetCurrentContext(); - return pValue->ToObject(context).ToLocalChecked(); -} - -v8::Local CFXJS_Engine::ToArray(v8::Local pValue) { - if (pValue.IsEmpty() || !pValue->IsArray()) - return v8::Local(); - v8::Local context = m_isolate->GetCurrentContext(); - return v8::Local::Cast(pValue->ToObject(context).ToLocalChecked()); -} - -void CFXJS_Engine::SetConstArray(const CFX_WideString& name, - v8::Local array) { - m_ConstArrays[name] = v8::Global(GetIsolate(), array); -} - -v8::Local CFXJS_Engine::GetConstArray(const CFX_WideString& name) { - return v8::Local::New(GetIsolate(), m_ConstArrays[name]); -} diff --git a/fxjs/fxjs_v8.h b/fxjs/fxjs_v8.h index 50b0b2c6d0b10d44bbb610b80ac0c3575298ae83..457523575541ebd1d75f7b6b7a098b1481327141 100644 --- a/fxjs/fxjs_v8.h +++ b/fxjs/fxjs_v8.h @@ -22,6 +22,8 @@ #include #include "core/fxcrt/fx_string.h" +#include "fxjs/cjs_v8.h" + #ifdef PDF_ENABLE_XFA // Header for CFXJSE_RuntimeData. FXJS_V8 doesn't interpret this class, // it is just passed along to XFA. @@ -53,10 +55,8 @@ class V8TemplateMapTraits : public v8::StdMapTraits { typedef v8::GlobalValueMap MapType; typedef void WeakCallbackDataType; - static WeakCallbackDataType* WeakCallbackParameter( - MapType* map, - void* key, - const v8::Local& value) { + static WeakCallbackDataType* + WeakCallbackParameter(MapType* map, void* key, v8::Local value) { return key; } static MapType* MapFromWeakCallbackInfo( @@ -111,6 +111,7 @@ class FXJS_PerIsolateData { }; class FXJS_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { + static const size_t kMaxAllowedBytes = 0x10000000; void* Allocate(size_t length) override; void* AllocateUninitialized(size_t length) override; void Free(void* data, size_t length) override; @@ -127,10 +128,10 @@ bool FXJS_GetIsolate(v8::Isolate** pResultIsolate); // Get the global isolate's ref count. size_t FXJS_GlobalIsolateRefCount(); -class CFXJS_Engine { +class CFXJS_Engine : public CJS_V8 { public: explicit CFXJS_Engine(v8::Isolate* pIsolate); - ~CFXJS_Engine(); + ~CFXJS_Engine() override; using Constructor = void (*)(CFXJS_Engine* pEngine, v8::Local obj); @@ -139,8 +140,6 @@ class CFXJS_Engine { static CFXJS_Engine* CurrentEngineFromIsolate(v8::Isolate* pIsolate); static int GetObjDefnID(v8::Local pObj); - v8::Isolate* GetIsolate() const { return m_isolate; } - // Always returns a valid, newly-created objDefnID. int DefineObj(const char* sObjName, FXJSOBJTYPE eObjType, @@ -172,68 +171,25 @@ class CFXJS_Engine { void ReleaseEngine(); // Called after FXJS_InitializeEngine call made. - int Execute(const CFX_WideString& script, FXJSErr* perror); + int Execute(const WideString& script, FXJSErr* perror); - v8::Local NewLocalContext(); - v8::Local GetPersistentContext(); v8::Local GetThisObj(); - v8::Local NewNull(); - v8::Local NewArray(); - v8::Local NewNumber(int number); - v8::Local NewNumber(double number); - v8::Local NewNumber(float number); - v8::Local NewBoolean(bool b); - v8::Local NewString(const CFX_ByteStringC& str); - v8::Local NewString(const CFX_WideStringC& str); - v8::Local NewDate(double d); v8::Local NewFxDynamicObj(int nObjDefnID, bool bStatic = false); - int ToInt32(v8::Local pValue); - bool ToBoolean(v8::Local pValue); - double ToDouble(v8::Local pValue); - CFX_WideString ToWideString(v8::Local pValue); - v8::Local ToObject(v8::Local pValue); - v8::Local ToArray(v8::Local pValue); - - // Arrays. - unsigned GetArrayLength(v8::Local pArray); - v8::Local GetArrayElement(v8::Local pArray, - unsigned index); - unsigned PutArrayElement(v8::Local pArray, - unsigned index, - v8::Local pValue); - - // Objects. - std::vector GetObjectPropertyNames( - v8::Local pObj); - v8::Local GetObjectProperty(v8::Local pObj, - const CFX_WideString& PropertyName); - void PutObjectProperty(v8::Local pObj, - const CFX_WideString& PropertyName, - v8::Local pValue); - // Native object binding. void SetObjectPrivate(v8::Local pObj, void* p); void* GetObjectPrivate(v8::Local pObj); static void FreeObjectPrivate(void* p); static void FreeObjectPrivate(v8::Local pObj); - void SetConstArray(const CFX_WideString& name, v8::Local array); - v8::Local GetConstArray(const CFX_WideString& name); - - void Error(const CFX_WideString& message); + void Error(const WideString& message); protected: CFXJS_Engine(); - void SetIsolate(v8::Isolate* pIsolate) { m_isolate = pIsolate; } - private: - v8::Isolate* m_isolate; - v8::Global m_V8PersistentContext; std::vector*> m_StaticObjects; - std::map> m_ConstArrays; }; #endif // FXJS_FXJS_V8_H_ diff --git a/fxjs/fxjs_v8_embeddertest.cpp b/fxjs/fxjs_v8_embeddertest.cpp index 4d05a20bf98939b31b2977ed11480aee93bd31f1..d975264d1d730746398a381e37ed840375dac213 100644 --- a/fxjs/fxjs_v8_embeddertest.cpp +++ b/fxjs/fxjs_v8_embeddertest.cpp @@ -19,7 +19,7 @@ const wchar_t kScript2[] = L"fred = 8"; class FXJSV8EmbedderTest : public JSEmbedderTest { public: - void ExecuteInCurrentContext(const CFX_WideString& script) { + void ExecuteInCurrentContext(const WideString& script) { FXJSErr error; int sts = engine()->Execute(script, &error); EXPECT_EQ(0, sts); @@ -37,7 +37,7 @@ TEST_F(FXJSV8EmbedderTest, Getters) { v8::HandleScope handle_scope(isolate()); v8::Context::Scope context_scope(GetV8Context()); - ExecuteInCurrentContext(CFX_WideString(kScript1)); + ExecuteInCurrentContext(WideString(kScript1)); CheckAssignmentInCurrentContext(kExpected1); } @@ -52,13 +52,13 @@ TEST_F(FXJSV8EmbedderTest, MultipleEngines) { engine2.InitializeEngine(); v8::Context::Scope context_scope(GetV8Context()); - ExecuteInCurrentContext(CFX_WideString(kScript0)); + ExecuteInCurrentContext(WideString(kScript0)); CheckAssignmentInCurrentContext(kExpected0); { v8::Local context1 = engine1.NewLocalContext(); v8::Context::Scope context_scope1(context1); - ExecuteInCurrentContext(CFX_WideString(kScript1)); + ExecuteInCurrentContext(WideString(kScript1)); CheckAssignmentInCurrentContext(kExpected1); } @@ -67,7 +67,7 @@ TEST_F(FXJSV8EmbedderTest, MultipleEngines) { { v8::Local context2 = engine2.NewLocalContext(); v8::Context::Scope context_scope2(context2); - ExecuteInCurrentContext(CFX_WideString(kScript2)); + ExecuteInCurrentContext(WideString(kScript2)); CheckAssignmentInCurrentContext(kExpected2); } @@ -98,11 +98,25 @@ TEST_F(FXJSV8EmbedderTest, NewNull) { EXPECT_FALSE(engine()->ToBoolean(nullz)); EXPECT_EQ(0, engine()->ToInt32(nullz)); EXPECT_EQ(0.0, engine()->ToDouble(nullz)); - EXPECT_EQ(L"", engine()->ToWideString(nullz)); + EXPECT_EQ(L"null", engine()->ToWideString(nullz)); EXPECT_TRUE(engine()->ToObject(nullz).IsEmpty()); EXPECT_TRUE(engine()->ToArray(nullz).IsEmpty()); } +TEST_F(FXJSV8EmbedderTest, NewUndefined) { + v8::Isolate::Scope isolate_scope(isolate()); + v8::HandleScope handle_scope(isolate()); + v8::Context::Scope context_scope(GetV8Context()); + + auto undef = engine()->NewUndefined(); + EXPECT_FALSE(engine()->ToBoolean(undef)); + EXPECT_EQ(0, engine()->ToInt32(undef)); + EXPECT_TRUE(std::isnan(engine()->ToDouble(undef))); + EXPECT_EQ(L"undefined", engine()->ToWideString(undef)); + EXPECT_TRUE(engine()->ToObject(undef).IsEmpty()); + EXPECT_TRUE(engine()->ToArray(undef).IsEmpty()); +} + TEST_F(FXJSV8EmbedderTest, NewBoolean) { v8::Isolate::Scope isolate_scope(isolate()); v8::HandleScope handle_scope(isolate()); @@ -192,6 +206,7 @@ TEST_F(FXJSV8EmbedderTest, NewObject) { v8::Context::Scope context_scope(GetV8Context()); auto object = engine()->NewFxDynamicObj(-1); + ASSERT_FALSE(object.IsEmpty()); EXPECT_EQ(0u, engine()->GetObjectPropertyNames(object).size()); EXPECT_FALSE(engine()->GetObjectProperty(object, L"clams").IsEmpty()); EXPECT_TRUE(engine()->GetObjectProperty(object, L"clams")->IsUndefined()); diff --git a/fxjs/fxjse.h b/fxjs/fxjse.h index 069a3b29a3d5dc08e931bb1f58096d67f2917957..873fcf50d2193a82732c8d23cadb3f2081763649 100644 --- a/fxjs/fxjse.h +++ b/fxjs/fxjse.h @@ -13,24 +13,36 @@ class CFXJSE_Arguments; class CFXJSE_Value; +class CJS_Return; -// C++ object which can be wrapped by CFXJSE_value. +// C++ object which is retrieved from v8 object's slot. class CFXJSE_HostObject { public: virtual ~CFXJSE_HostObject() {} + + // Small layering violation here, but we need to distinguish between the + // two kinds of subclasses. + enum Type { kXFA, kFM2JS }; + Type type() const { return type_; } + + protected: + explicit CFXJSE_HostObject(Type type) { type_ = type; } + + Type type_; }; +typedef CJS_Return (*FXJSE_MethodCallback)( + const v8::FunctionCallbackInfo& info, + const WideString& functionName); typedef void (*FXJSE_FuncCallback)(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, + const ByteStringView& szFuncName, CFXJSE_Arguments& args); typedef void (*FXJSE_PropAccessor)(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue); typedef int32_t (*FXJSE_PropTypeGetter)(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, bool bQueryIn); -typedef bool (*FXJSE_PropDeleter)(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName); enum FXJSE_ClassPropTypes { FXJSE_ClassPropType_None, @@ -39,36 +51,20 @@ enum FXJSE_ClassPropTypes { }; struct FXJSE_FUNCTION_DESCRIPTOR { - const FX_CHAR* name; + const char* name; FXJSE_FuncCallback callbackProc; }; -struct FXJSE_PROPERTY_DESCRIPTOR { - const FX_CHAR* name; - FXJSE_PropAccessor getProc; - FXJSE_PropAccessor setProc; -}; - struct FXJSE_CLASS_DESCRIPTOR { - const FX_CHAR* name; - FXJSE_FuncCallback constructor; - const FXJSE_PROPERTY_DESCRIPTOR* properties; + const char* name; const FXJSE_FUNCTION_DESCRIPTOR* methods; - int32_t propNum; int32_t methNum; FXJSE_PropTypeGetter dynPropTypeGetter; FXJSE_PropAccessor dynPropGetter; FXJSE_PropAccessor dynPropSetter; - FXJSE_PropDeleter dynPropDeleter; - FXJSE_FuncCallback dynMethodCall; + FXJSE_MethodCallback dynMethodCall; }; -void FXJSE_Initialize(); -void FXJSE_Finalize(); - -v8::Isolate* FXJSE_Runtime_Create_Own(); -void FXJSE_Runtime_Release(v8::Isolate* pIsolate); - -void FXJSE_ThrowMessage(const CFX_ByteStringC& utf8Message); +void FXJSE_ThrowMessage(const ByteStringView& utf8Message); #endif // FXJS_FXJSE_H_ diff --git a/fxjs/global_timer.cpp b/fxjs/global_timer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f7f09c6737eeb142a51e6e9add877da96da860c --- /dev/null +++ b/fxjs/global_timer.cpp @@ -0,0 +1,80 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/global_timer.h" + +GlobalTimer::GlobalTimer(app* pObj, + CPDFSDK_FormFillEnvironment* pFormFillEnv, + CJS_Runtime* pRuntime, + int nType, + const WideString& script, + uint32_t dwElapse, + uint32_t dwTimeOut) + : m_nTimerID(0), + m_pEmbedObj(pObj), + m_bProcessing(false), + m_nType(nType), + m_dwTimeOut(dwTimeOut), + m_swJScript(script), + m_pRuntime(pRuntime), + m_pFormFillEnv(pFormFillEnv) { + CFX_SystemHandler* pHandler = m_pFormFillEnv->GetSysHandler(); + m_nTimerID = pHandler->SetTimer(dwElapse, Trigger); + if (m_nTimerID) + (*GetGlobalTimerMap())[m_nTimerID] = this; +} + +GlobalTimer::~GlobalTimer() { + if (!m_nTimerID) + return; + + if (GetRuntime()) + m_pFormFillEnv->GetSysHandler()->KillTimer(m_nTimerID); + + GetGlobalTimerMap()->erase(m_nTimerID); +} + +// static +void GlobalTimer::Trigger(int nTimerID) { + auto it = GetGlobalTimerMap()->find(nTimerID); + if (it == GetGlobalTimerMap()->end()) + return; + + GlobalTimer* pTimer = it->second; + if (pTimer->m_bProcessing) + return; + + pTimer->m_bProcessing = true; + if (pTimer->m_pEmbedObj) + pTimer->m_pEmbedObj->TimerProc(pTimer); + + // Timer proc may have destroyed timer, find it again. + it = GetGlobalTimerMap()->find(nTimerID); + if (it == GetGlobalTimerMap()->end()) + return; + + pTimer = it->second; + pTimer->m_bProcessing = false; + if (pTimer->IsOneShot()) + pTimer->m_pEmbedObj->CancelProc(pTimer); +} + +// static +void GlobalTimer::Cancel(int nTimerID) { + auto it = GetGlobalTimerMap()->find(nTimerID); + if (it == GetGlobalTimerMap()->end()) + return; + + GlobalTimer* pTimer = it->second; + pTimer->m_pEmbedObj->CancelProc(pTimer); +} + +// static +GlobalTimer::TimerMap* GlobalTimer::GetGlobalTimerMap() { + // Leak the timer array at shutdown. + static auto* s_TimerMap = new TimerMap; + return s_TimerMap; +} diff --git a/fxjs/global_timer.h b/fxjs/global_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..ec8806b9a113dbba8af1658990a93c2398ba6e66 --- /dev/null +++ b/fxjs/global_timer.h @@ -0,0 +1,50 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_GLOBAL_TIMER_H_ +#define FXJS_GLOBAL_TIMER_H_ + +#include + +#include "fxjs/cjs_app.h" + +class GlobalTimer { + public: + GlobalTimer(app* pObj, + CPDFSDK_FormFillEnvironment* pFormFillEnv, + CJS_Runtime* pRuntime, + int nType, + const WideString& script, + uint32_t dwElapse, + uint32_t dwTimeOut); + ~GlobalTimer(); + + static void Trigger(int nTimerID); + static void Cancel(int nTimerID); + + bool IsOneShot() const { return m_nType == 1; } + uint32_t GetTimeOut() const { return m_dwTimeOut; } + int GetTimerID() const { return m_nTimerID; } + CJS_Runtime* GetRuntime() const { return m_pRuntime.Get(); } + WideString GetJScript() const { return m_swJScript; } + + private: + using TimerMap = std::map; + static TimerMap* GetGlobalTimerMap(); + + uint32_t m_nTimerID; + app* const m_pEmbedObj; + bool m_bProcessing; + + // data + const int m_nType; // 0:Interval; 1:TimeOut + const uint32_t m_dwTimeOut; + const WideString m_swJScript; + CJS_Runtime::ObservedPtr m_pRuntime; + CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv; +}; + +#endif // FXJS_GLOBAL_TIMER_H_ diff --git a/fpdfsdk/javascript/ijs_event_context.h b/fxjs/ijs_event_context.h similarity index 84% rename from fpdfsdk/javascript/ijs_event_context.h rename to fxjs/ijs_event_context.h index 8428072cdd72277e11dfda7eb449975930dd2b03..9b8dd8eabe4bbfb8c12645deaf72f47928297e21 100644 --- a/fpdfsdk/javascript/ijs_event_context.h +++ b/fxjs/ijs_event_context.h @@ -4,8 +4,8 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#ifndef FPDFSDK_JAVASCRIPT_IJS_EVENT_CONTEXT_H_ -#define FPDFSDK_JAVASCRIPT_IJS_EVENT_CONTEXT_H_ +#ifndef FXJS_IJS_EVENT_CONTEXT_H_ +#define FXJS_IJS_EVENT_CONTEXT_H_ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" @@ -20,13 +20,12 @@ class CPDFSDK_FormFillEnvironment; // may trigger new events on top of one another. class IJS_EventContext { public: - virtual bool RunScript(const CFX_WideString& script, - CFX_WideString* info) = 0; + virtual bool RunScript(const WideString& script, WideString* info) = 0; virtual void OnApp_Init() = 0; virtual void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString& strTargetName) = 0; + const WideString& strTargetName) = 0; virtual void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0; virtual void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0; virtual void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0; @@ -53,38 +52,38 @@ class IJS_EventContext { virtual void OnField_Focus(bool bModifier, bool bShift, CPDF_FormField* pTarget, - const CFX_WideString& Value) = 0; + const WideString& Value) = 0; virtual void OnField_Blur(bool bModifier, bool bShift, CPDF_FormField* pTarget, - const CFX_WideString& Value) = 0; + const WideString& Value) = 0; virtual void OnField_Calculate(CPDF_FormField* pSource, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool& bRc) = 0; virtual void OnField_Format(CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool bWillCommit) = 0; - virtual void OnField_Keystroke(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, + virtual void OnField_Keystroke(WideString& strChange, + const WideString& strChangeEx, bool KeyDown, bool bModifier, int& nSelEnd, int& nSelStart, bool bShift, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool bWillCommit, bool bFieldFull, bool& bRc) = 0; - virtual void OnField_Validate(CFX_WideString& strChange, - const CFX_WideString& strChangeEx, + virtual void OnField_Validate(WideString& strChange, + const WideString& strChangeEx, bool bKeyDown, bool bModifier, bool bShift, CPDF_FormField* pTarget, - CFX_WideString& Value, + WideString& Value, bool& bRc) = 0; virtual void OnScreen_Focus(bool bModifier, @@ -122,7 +121,7 @@ class IJS_EventContext { virtual void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0; virtual void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv, - const CFX_WideString&) = 0; + const WideString&) = 0; virtual void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0; virtual void OnConsole_Exec() = 0; virtual void OnExternal_Exec() = 0; @@ -131,4 +130,4 @@ class IJS_EventContext { virtual ~IJS_EventContext() {} }; -#endif // FPDFSDK_JAVASCRIPT_IJS_EVENT_CONTEXT_H_ +#endif // FXJS_IJS_EVENT_CONTEXT_H_ diff --git a/fxjs/ijs_runtime.h b/fxjs/ijs_runtime.h new file mode 100644 index 0000000000000000000000000000000000000000..e649aada0ceff4db2e0a07c4b51d577b4f6983c7 --- /dev/null +++ b/fxjs/ijs_runtime.h @@ -0,0 +1,44 @@ +// Copyright 2016 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 FXJS_IJS_RUNTIME_H_ +#define FXJS_IJS_RUNTIME_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" + +#ifdef PDF_ENABLE_XFA +#include "fxjs/fxjse.h" +#endif // PDF_ENABLE_XFA + +class CPDFSDK_FormFillEnvironment; +class IJS_EventContext; + +// Owns the FJXS objects needed to actually execute JS. +class IJS_Runtime { + public: + static void Initialize(unsigned int slot, void* isolate); + static void Destroy(); + static IJS_Runtime* Create(CPDFSDK_FormFillEnvironment* pFormFillEnv); + virtual ~IJS_Runtime() {} + + virtual IJS_EventContext* NewEventContext() = 0; + virtual void ReleaseEventContext(IJS_EventContext* pContext) = 0; + virtual CPDFSDK_FormFillEnvironment* GetFormFillEnv() const = 0; + virtual int ExecuteScript(const WideString& script, WideString* info) = 0; + +#ifdef PDF_ENABLE_XFA + virtual bool GetValueByName(const ByteStringView& utf8Name, + CFXJSE_Value* pValue) = 0; + virtual bool SetValueByName(const ByteStringView& utf8Name, + CFXJSE_Value* pValue) = 0; +#endif // PDF_ENABLE_XFA + + protected: + IJS_Runtime() {} +}; + +#endif // FXJS_IJS_RUNTIME_H_ diff --git a/fxjs/js_resources.cpp b/fxjs/js_resources.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bfffbc3714b7f4933bc12756c730502febce013b --- /dev/null +++ b/fxjs/js_resources.cpp @@ -0,0 +1,70 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/js_resources.h" + +WideString JSGetStringFromID(JSMessage msg) { + switch (msg) { + case JSMessage::kAlert: + return L"Alert"; + case JSMessage::kParamError: + return L"Incorrect number of parameters passed to function."; + case JSMessage::kInvalidInputError: + return L"The input value is invalid."; + case JSMessage::kParamTooLongError: + return L"The input value is too long."; + case JSMessage::kParseDateError: + return L"The input value can't be parsed as a valid date/time (%s)."; + case JSMessage::kRangeBetweenError: + return L"The input value must be greater than or equal to %s" + L" and less than or equal to %s."; + case JSMessage::kRangeGreaterError: + return L"The input value must be greater than or equal to %s."; + case JSMessage::kRangeLessError: + return L"The input value must be less than or equal to %s."; + case JSMessage::kNotSupportedError: + return L"Operation not supported."; + case JSMessage::kBusyError: + return L"System is busy."; + case JSMessage::kDuplicateEventError: + return L"Duplicate formfield event found."; + case JSMessage::kRunSuccess: + return L"Script ran successfully."; + case JSMessage::kSecondParamNotDateError: + return L"The second parameter can't be converted to a Date."; + case JSMessage::kSecondParamInvalidDateError: + return L"The second parameter is an invalid Date!"; + case JSMessage::kGlobalNotFoundError: + return L"Global value not found."; + case JSMessage::kReadOnlyError: + return L"Cannot assign to readonly property."; + case JSMessage::kTypeError: + return L"Incorrect parameter type."; + case JSMessage::kValueError: + return L"Incorrect parameter value."; + case JSMessage::kPermissionError: + return L"Permission denied."; + case JSMessage::kBadObjectError: + return L"Object no longer exists."; + case JSMessage::kTooManyOccurances: + return L"Too many occurances"; + } + NOTREACHED(); + return L""; +} + +WideString JSFormatErrorString(const char* class_name, + const char* property_name, + const WideString& details) { + WideString result = WideString::FromLocal(class_name); + if (property_name) { + result += L"."; + result += WideString::FromLocal(property_name); + } + result += L": "; + result += details; + return result; +} diff --git a/fxjs/js_resources.h b/fxjs/js_resources.h new file mode 100644 index 0000000000000000000000000000000000000000..0b664c997ccfa2496432b6d467d7a5340fa7b462 --- /dev/null +++ b/fxjs/js_resources.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_JS_RESOURCES_H_ +#define FXJS_JS_RESOURCES_H_ + +#include "core/fxcrt/widestring.h" + +enum class JSMessage { + kRunSuccess = 0, + kAlert, + kParamError, + kInvalidInputError, + kParamTooLongError, + kParseDateError, + kRangeBetweenError, + kRangeGreaterError, + kRangeLessError, + kNotSupportedError, + kBusyError, + kDuplicateEventError, + kSecondParamNotDateError, + kSecondParamInvalidDateError, + kGlobalNotFoundError, + kReadOnlyError, + kTypeError, + kValueError, + kPermissionError, + kBadObjectError, + kTooManyOccurances +}; + +WideString JSGetStringFromID(JSMessage msg); +WideString JSFormatErrorString(const char* class_name, + const char* property_name, + const WideString& details); + +#endif // FXJS_JS_RESOURCES_H_ diff --git a/fxjs/xfa/cjx_arc.cpp b/fxjs/xfa/cjx_arc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92b626dff7b1178813e23f44d94fbfac0263ee51 --- /dev/null +++ b/fxjs/xfa/cjx_arc.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_arc.h" + +#include "xfa/fxfa/parser/cxfa_arc.h" + +CJX_Arc::CJX_Arc(CXFA_Arc* node) : CJX_Node(node) {} + +CJX_Arc::~CJX_Arc() = default; + +void CJX_Arc::circular(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Arc::hand(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Arc::startAngle(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Arc::sweepAngle(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Arc::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Arc::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_arc.h b/fxjs/xfa/cjx_arc.h new file mode 100644 index 0000000000000000000000000000000000000000..a9a6bb6733598611c58d7ef1e9f6b246a909327c --- /dev/null +++ b/fxjs/xfa/cjx_arc.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ARC_H_ +#define FXJS_XFA_CJX_ARC_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Arc; + +class CJX_Arc : public CJX_Node { + public: + explicit CJX_Arc(CXFA_Arc* node); + ~CJX_Arc() override; + + JS_PROP(circular); + JS_PROP(hand); + JS_PROP(startAngle); + JS_PROP(sweepAngle); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ARC_H_ diff --git a/fxjs/xfa/cjx_area.cpp b/fxjs/xfa/cjx_area.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee621943b6e50ddee2c12886a961aba64ef11a73 --- /dev/null +++ b/fxjs/xfa/cjx_area.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_area.h" + +#include "xfa/fxfa/parser/cxfa_area.h" + +CJX_Area::CJX_Area(CXFA_Area* node) : CJX_Container(node) {} + +CJX_Area::~CJX_Area() = default; + +void CJX_Area::colSpan(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Area::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Area::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Area::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Area::x(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Area::y(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_area.h b/fxjs/xfa/cjx_area.h new file mode 100644 index 0000000000000000000000000000000000000000..94083b351a76cc05f7a1a6dd88c106c421f3e1dd --- /dev/null +++ b/fxjs/xfa/cjx_area.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_AREA_H_ +#define FXJS_XFA_CJX_AREA_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_Area; + +class CJX_Area : public CJX_Container { + public: + explicit CJX_Area(CXFA_Area* node); + ~CJX_Area() override; + + JS_PROP(colSpan); + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(x); + JS_PROP(y); +}; + +#endif // FXJS_XFA_CJX_AREA_H_ diff --git a/fxjs/xfa/cjx_assist.cpp b/fxjs/xfa/cjx_assist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcd7f37d083865bf755b2544fd370a4c1841a895 --- /dev/null +++ b/fxjs/xfa/cjx_assist.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_assist.h" + +#include "xfa/fxfa/parser/cxfa_assist.h" + +CJX_Assist::CJX_Assist(CXFA_Assist* node) : CJX_Node(node) {} + +CJX_Assist::~CJX_Assist() = default; + +void CJX_Assist::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Assist::role(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Assist::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_assist.h b/fxjs/xfa/cjx_assist.h new file mode 100644 index 0000000000000000000000000000000000000000..9e7c9c55e3a4768e98abd859886785ecd054b22e --- /dev/null +++ b/fxjs/xfa/cjx_assist.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ASSIST_H_ +#define FXJS_XFA_CJX_ASSIST_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Assist; + +class CJX_Assist : public CJX_Node { + public: + explicit CJX_Assist(CXFA_Assist* node); + ~CJX_Assist() override; + + JS_PROP(role); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ASSIST_H_ diff --git a/fxjs/xfa/cjx_barcode.cpp b/fxjs/xfa/cjx_barcode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7520cc35714f0e20a1b44634c7499b0ef5a37f98 --- /dev/null +++ b/fxjs/xfa/cjx_barcode.cpp @@ -0,0 +1,133 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_barcode.h" + +#include "xfa/fxfa/parser/cxfa_barcode.h" + +CJX_Barcode::CJX_Barcode(CXFA_Barcode* node) : CJX_Node(node) {} + +CJX_Barcode::~CJX_Barcode() = default; + +void CJX_Barcode::charEncoding(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::checksum(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::dataColumnCount(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::dataLength(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::dataPrep(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::dataRowCount(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::endChar(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::errorCorrectionLevel(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::moduleHeight(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::moduleWidth(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::printCheckDigit(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::rowColumnRatio(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::startChar(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::textLocation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::truncate(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::upsMode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Barcode::wideNarrowRatio(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_barcode.h b/fxjs/xfa/cjx_barcode.h new file mode 100644 index 0000000000000000000000000000000000000000..f5d88816bdd4e57a4e6d6fc2bb029d3af7deb132 --- /dev/null +++ b/fxjs/xfa/cjx_barcode.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BARCODE_H_ +#define FXJS_XFA_CJX_BARCODE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Barcode; + +class CJX_Barcode : public CJX_Node { + public: + explicit CJX_Barcode(CXFA_Barcode* arc); + ~CJX_Barcode() override; + + JS_PROP(charEncoding); + JS_PROP(checksum); + JS_PROP(dataColumnCount); + JS_PROP(dataLength); + JS_PROP(dataPrep); + JS_PROP(dataRowCount); + JS_PROP(endChar); + JS_PROP(errorCorrectionLevel); + JS_PROP(moduleHeight); + JS_PROP(moduleWidth); + JS_PROP(printCheckDigit); + JS_PROP(rowColumnRatio); + JS_PROP(startChar); + JS_PROP(textLocation); + JS_PROP(truncate); + JS_PROP(type); + JS_PROP(upsMode); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(wideNarrowRatio); +}; + +#endif // FXJS_XFA_CJX_BARCODE_H_ diff --git a/fxjs/xfa/cjx_bind.cpp b/fxjs/xfa/cjx_bind.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a73312dfd1cf687cab0c52d890933fc9eae43ff3 --- /dev/null +++ b/fxjs/xfa/cjx_bind.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_bind.h" + +#include "xfa/fxfa/parser/cxfa_bind.h" + +CJX_Bind::CJX_Bind(CXFA_Bind* node) : CJX_Node(node) {} + +CJX_Bind::~CJX_Bind() = default; + +void CJX_Bind::contentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bind::match(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bind::ref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bind::transferEncoding(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bind::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bind::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_bind.h b/fxjs/xfa/cjx_bind.h new file mode 100644 index 0000000000000000000000000000000000000000..9fc8ab8071c90011a1ebec5124d45ea4fc2c09a9 --- /dev/null +++ b/fxjs/xfa/cjx_bind.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BIND_H_ +#define FXJS_XFA_CJX_BIND_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Bind; + +class CJX_Bind : public CJX_Node { + public: + explicit CJX_Bind(CXFA_Bind* node); + ~CJX_Bind() override; + + JS_PROP(contentType); + JS_PROP(match); + JS_PROP(ref); + JS_PROP(transferEncoding); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BIND_H_ diff --git a/fxjs/xfa/cjx_binditems.cpp b/fxjs/xfa/cjx_binditems.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd1f30d814803e250ef60007ac9e3ccd9e44d086 --- /dev/null +++ b/fxjs/xfa/cjx_binditems.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_binditems.h" + +#include "xfa/fxfa/parser/cxfa_binditems.h" + +CJX_BindItems::CJX_BindItems(CXFA_BindItems* node) : CJX_Node(node) {} + +CJX_BindItems::~CJX_BindItems() = default; + +void CJX_BindItems::connection(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BindItems::labelRef(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BindItems::valueRef(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_binditems.h b/fxjs/xfa/cjx_binditems.h new file mode 100644 index 0000000000000000000000000000000000000000..e47b3faea5508604aaf34f1574b9ed36641933d7 --- /dev/null +++ b/fxjs/xfa/cjx_binditems.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BINDITEMS_H_ +#define FXJS_XFA_CJX_BINDITEMS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_BindItems; + +class CJX_BindItems : public CJX_Node { + public: + explicit CJX_BindItems(CXFA_BindItems* node); + ~CJX_BindItems() override; + + JS_PROP(connection); + JS_PROP(labelRef); + JS_PROP(valueRef); +}; + +#endif // FXJS_XFA_CJX_BINDITEMS_H_ diff --git a/fxjs/xfa/cjx_bookend.cpp b/fxjs/xfa/cjx_bookend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2399e26f58ab1e875806200c5fb23fe88393a09d --- /dev/null +++ b/fxjs/xfa/cjx_bookend.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_bookend.h" + +#include "xfa/fxfa/parser/cxfa_bookend.h" + +CJX_Bookend::CJX_Bookend(CXFA_Bookend* node) : CJX_Node(node) {} + +CJX_Bookend::~CJX_Bookend() = default; + +void CJX_Bookend::leader(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bookend::trailer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bookend::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Bookend::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_bookend.h b/fxjs/xfa/cjx_bookend.h new file mode 100644 index 0000000000000000000000000000000000000000..0165091f066946579b08c6ad7fd028ef1dad78a6 --- /dev/null +++ b/fxjs/xfa/cjx_bookend.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BOOKEND_H_ +#define FXJS_XFA_CJX_BOOKEND_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Bookend; + +class CJX_Bookend : public CJX_Node { + public: + explicit CJX_Bookend(CXFA_Bookend* node); + ~CJX_Bookend() override; + + JS_PROP(leader); + JS_PROP(trailer); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BOOKEND_H_ diff --git a/fxjs/xfa/cjx_boolean.cpp b/fxjs/xfa/cjx_boolean.cpp new file mode 100644 index 0000000000000000000000000000000000000000..761d0a2be9620aea89658b40651c71a7a404729a --- /dev/null +++ b/fxjs/xfa/cjx_boolean.cpp @@ -0,0 +1,57 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_boolean.h" + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_boolean.h" + +CJX_Boolean::CJX_Boolean(CXFA_Boolean* node) : CJX_Content(node) {} + +CJX_Boolean::~CJX_Boolean() = default; + +void CJX_Boolean::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Boolean::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (!bSetting) { + WideString wsValue = GetContent(true); + pValue->SetBoolean(wsValue == L"1"); + return; + } + + ByteString newValue; + if (pValue && !(pValue->IsNull() || pValue->IsUndefined())) + newValue = pValue->ToString(); + + int32_t iValue = FXSYS_atoi(newValue.c_str()); + WideString wsNewValue(iValue == 0 ? L"0" : L"1"); + WideString wsFormatValue(wsNewValue); + CXFA_WidgetAcc* pContainerWidgetAcc = + ToNode(GetXFAObject())->GetContainerWidgetAcc(); + if (pContainerWidgetAcc) + wsFormatValue = pContainerWidgetAcc->GetFormatDataValue(wsNewValue); + + SetContent(wsNewValue, wsFormatValue, true, true, true); +} + +void CJX_Boolean::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Boolean::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_boolean.h b/fxjs/xfa/cjx_boolean.h new file mode 100644 index 0000000000000000000000000000000000000000..c90291aa8a14ff76f305004672dd55feaf3d0c46 --- /dev/null +++ b/fxjs/xfa/cjx_boolean.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BOOLEAN_H_ +#define FXJS_XFA_CJX_BOOLEAN_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Boolean; + +class CJX_Boolean : public CJX_Content { + public: + explicit CJX_Boolean(CXFA_Boolean* node); + ~CJX_Boolean() override; + + JS_PROP(use); + JS_PROP(defaultValue); /* {default} */ + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_BOOLEAN_H_ diff --git a/fxjs/xfa/cjx_border.cpp b/fxjs/xfa/cjx_border.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92355a85c16b756226d5f0f7acea4a8b2f722eed --- /dev/null +++ b/fxjs/xfa/cjx_border.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_border.h" + +#include "xfa/fxfa/parser/cxfa_border.h" + +CJX_Border::CJX_Border(CXFA_Border* node) : CJX_Node(node) {} + +CJX_Border::~CJX_Border() = default; + +void CJX_Border::breakValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Border::hand(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Border::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Border::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Border::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Border::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_border.h b/fxjs/xfa/cjx_border.h new file mode 100644 index 0000000000000000000000000000000000000000..b95ca4c311681ce10a09ee3188da3b45c3642cef --- /dev/null +++ b/fxjs/xfa/cjx_border.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BORDER_H_ +#define FXJS_XFA_CJX_BORDER_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Border; + +class CJX_Border : public CJX_Node { + public: + explicit CJX_Border(CXFA_Border* node); + ~CJX_Border() override; + + JS_PROP(breakValue); /* break */ + JS_PROP(hand); + JS_PROP(presence); + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BORDER_H_ diff --git a/fxjs/xfa/cjx_break.cpp b/fxjs/xfa/cjx_break.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d04a05f1899d16a739f416581308f52284ef51d7 --- /dev/null +++ b/fxjs/xfa/cjx_break.cpp @@ -0,0 +1,85 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_break.h" + +#include "xfa/fxfa/parser/cxfa_break.h" + +CJX_Break::CJX_Break(CXFA_Break* node) : CJX_Node(node) {} + +CJX_Break::~CJX_Break() = default; + +void CJX_Break::after(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::afterTarget(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::before(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::beforeTarget(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::bookendLeader(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::bookendTrailer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::overflowLeader(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::overflowTarget(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::overflowTrailer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::startNew(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Break::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_break.h b/fxjs/xfa/cjx_break.h new file mode 100644 index 0000000000000000000000000000000000000000..86cb249bf7264786b41e82693daed460f4470691 --- /dev/null +++ b/fxjs/xfa/cjx_break.h @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BREAK_H_ +#define FXJS_XFA_CJX_BREAK_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Break; + +class CJX_Break : public CJX_Node { + public: + explicit CJX_Break(CXFA_Break* node); + ~CJX_Break() override; + + JS_PROP(after); + JS_PROP(afterTarget); + JS_PROP(before); + JS_PROP(beforeTarget); + JS_PROP(bookendLeader); + JS_PROP(bookendTrailer); + JS_PROP(overflowLeader); + JS_PROP(overflowTarget); + JS_PROP(overflowTrailer); + JS_PROP(startNew); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BREAK_H_ diff --git a/fxjs/xfa/cjx_breakafter.cpp b/fxjs/xfa/cjx_breakafter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76a5a3bc45b20d91830261ea8300fabe5aca39e7 --- /dev/null +++ b/fxjs/xfa/cjx_breakafter.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_breakafter.h" + +#include "xfa/fxfa/parser/cxfa_breakafter.h" + +CJX_BreakAfter::CJX_BreakAfter(CXFA_BreakAfter* node) : CJX_Node(node) {} + +CJX_BreakAfter::~CJX_BreakAfter() = default; + +void CJX_BreakAfter::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakAfter::startNew(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakAfter::trailer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakAfter::targetType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakAfter::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakAfter::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakAfter::leader(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_breakafter.h b/fxjs/xfa/cjx_breakafter.h new file mode 100644 index 0000000000000000000000000000000000000000..aa1eccc084e372388c8b588fe7e9491a7ad9d911 --- /dev/null +++ b/fxjs/xfa/cjx_breakafter.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BREAKAFTER_H_ +#define FXJS_XFA_CJX_BREAKAFTER_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_BreakAfter; + +class CJX_BreakAfter : public CJX_Node { + public: + explicit CJX_BreakAfter(CXFA_BreakAfter* node); + ~CJX_BreakAfter() override; + + JS_PROP(leader); + JS_PROP(startNew); + JS_PROP(target); + JS_PROP(targetType); + JS_PROP(trailer); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BREAKAFTER_H_ diff --git a/fxjs/xfa/cjx_breakbefore.cpp b/fxjs/xfa/cjx_breakbefore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83fa01e7cb265c1975250ad25a13ba4b95e9ccff --- /dev/null +++ b/fxjs/xfa/cjx_breakbefore.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_breakbefore.h" + +#include "xfa/fxfa/parser/cxfa_breakbefore.h" + +CJX_BreakBefore::CJX_BreakBefore(CXFA_BreakBefore* node) : CJX_Node(node) {} + +CJX_BreakBefore::~CJX_BreakBefore() = default; + +void CJX_BreakBefore::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakBefore::startNew(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakBefore::trailer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakBefore::targetType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakBefore::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakBefore::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_BreakBefore::leader(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_breakbefore.h b/fxjs/xfa/cjx_breakbefore.h new file mode 100644 index 0000000000000000000000000000000000000000..3f8dbbb3c61417d1f15764539677f798189215f9 --- /dev/null +++ b/fxjs/xfa/cjx_breakbefore.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BREAKBEFORE_H_ +#define FXJS_XFA_CJX_BREAKBEFORE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_BreakBefore; + +class CJX_BreakBefore : public CJX_Node { + public: + explicit CJX_BreakBefore(CXFA_BreakBefore* node); + ~CJX_BreakBefore() override; + + JS_PROP(leader); + JS_PROP(startNew); + JS_PROP(target); + JS_PROP(targetType); + JS_PROP(trailer); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BREAKBEFORE_H_ diff --git a/fxjs/xfa/cjx_button.cpp b/fxjs/xfa/cjx_button.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5bd6eb01e52387191750efdb60462f114c88756 --- /dev/null +++ b/fxjs/xfa/cjx_button.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_button.h" + +#include "xfa/fxfa/parser/cxfa_button.h" + +CJX_Button::CJX_Button(CXFA_Button* node) : CJX_Node(node) {} + +CJX_Button::~CJX_Button() = default; + +void CJX_Button::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Button::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Button::highlight(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_button.h b/fxjs/xfa/cjx_button.h new file mode 100644 index 0000000000000000000000000000000000000000..3732aae6746f70d1bde2e91bbffb95f5a4155e3b --- /dev/null +++ b/fxjs/xfa/cjx_button.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_BUTTON_H_ +#define FXJS_XFA_CJX_BUTTON_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Button; + +class CJX_Button : public CJX_Node { + public: + explicit CJX_Button(CXFA_Button* node); + ~CJX_Button() override; + + JS_PROP(highlight); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_BUTTON_H_ diff --git a/fxjs/xfa/cjx_calculate.cpp b/fxjs/xfa/cjx_calculate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5db4dffad11fd1107e84850ee251d8f37099f23 --- /dev/null +++ b/fxjs/xfa/cjx_calculate.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_calculate.h" + +#include "xfa/fxfa/parser/cxfa_calculate.h" + +CJX_Calculate::CJX_Calculate(CXFA_Calculate* node) : CJX_Node(node) {} + +CJX_Calculate::~CJX_Calculate() = default; + +void CJX_Calculate::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Calculate::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Calculate::override(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_calculate.h b/fxjs/xfa/cjx_calculate.h new file mode 100644 index 0000000000000000000000000000000000000000..2410f1bf4520b949906603a8111c55dee9637e6b --- /dev/null +++ b/fxjs/xfa/cjx_calculate.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CALCULATE_H_ +#define FXJS_XFA_CJX_CALCULATE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Calculate; + +class CJX_Calculate : public CJX_Node { + public: + explicit CJX_Calculate(CXFA_Calculate* node); + ~CJX_Calculate() override; + + JS_PROP(override); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CALCULATE_H_ diff --git a/fxjs/xfa/cjx_caption.cpp b/fxjs/xfa/cjx_caption.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c7f6a8d04627121faae07da8ca36cb6089825d1 --- /dev/null +++ b/fxjs/xfa/cjx_caption.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_caption.h" + +#include "xfa/fxfa/parser/cxfa_caption.h" + +CJX_Caption::CJX_Caption(CXFA_Caption* node) : CJX_Node(node) {} + +CJX_Caption::~CJX_Caption() = default; + +void CJX_Caption::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Caption::reserve(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Caption::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Caption::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Caption::placement(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_caption.h b/fxjs/xfa/cjx_caption.h new file mode 100644 index 0000000000000000000000000000000000000000..9af6915f353a58b182727d64871c23b0f58cb6cc --- /dev/null +++ b/fxjs/xfa/cjx_caption.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CAPTION_H_ +#define FXJS_XFA_CJX_CAPTION_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Caption; + +class CJX_Caption : public CJX_Node { + public: + explicit CJX_Caption(CXFA_Caption* node); + ~CJX_Caption() override; + + JS_PROP(placement); + JS_PROP(presence); + JS_PROP(reserve); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CAPTION_H_ diff --git a/fxjs/xfa/cjx_certificate.cpp b/fxjs/xfa/cjx_certificate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d105651350df5c1062fae02a8c0dbbc8db3114c --- /dev/null +++ b/fxjs/xfa/cjx_certificate.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_certificate.h" + +#include "xfa/fxfa/parser/cxfa_certificate.h" + +CJX_Certificate::CJX_Certificate(CXFA_Certificate* node) : CJX_TextNode(node) {} + +CJX_Certificate::~CJX_Certificate() = default; + +void CJX_Certificate::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Certificate::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_certificate.h b/fxjs/xfa/cjx_certificate.h new file mode 100644 index 0000000000000000000000000000000000000000..af62b9135fe71caac4582269c3e2966b867d594c --- /dev/null +++ b/fxjs/xfa/cjx_certificate.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CERTIFICATE_H_ +#define FXJS_XFA_CJX_CERTIFICATE_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Certificate; + +class CJX_Certificate : public CJX_TextNode { + public: + explicit CJX_Certificate(CXFA_Certificate* node); + ~CJX_Certificate() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CERTIFICATE_H_ diff --git a/fxjs/xfa/cjx_certificates.cpp b/fxjs/xfa/cjx_certificates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68286307b35206d396c0ca7e6b83614b36e8f40e --- /dev/null +++ b/fxjs/xfa/cjx_certificates.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_certificates.h" + +#include "xfa/fxfa/parser/cxfa_certificates.h" + +CJX_Certificates::CJX_Certificates(CXFA_Certificates* node) : CJX_Node(node) {} + +CJX_Certificates::~CJX_Certificates() = default; + +void CJX_Certificates::url(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Certificates::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Certificates::credentialServerPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Certificates::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Certificates::urlPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_certificates.h b/fxjs/xfa/cjx_certificates.h new file mode 100644 index 0000000000000000000000000000000000000000..160d88d9a8e8ec154c3582864298eb509a59f60e --- /dev/null +++ b/fxjs/xfa/cjx_certificates.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CERTIFICATES_H_ +#define FXJS_XFA_CJX_CERTIFICATES_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Certificates; + +class CJX_Certificates : public CJX_Node { + public: + explicit CJX_Certificates(CXFA_Certificates* node); + ~CJX_Certificates() override; + + JS_PROP(credentialServerPolicy); + JS_PROP(url); + JS_PROP(urlPolicy); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CERTIFICATES_H_ diff --git a/fxjs/xfa/cjx_checkbutton.cpp b/fxjs/xfa/cjx_checkbutton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c5b1e61865f3149ab4999bfba436034244cc34a --- /dev/null +++ b/fxjs/xfa/cjx_checkbutton.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_checkbutton.h" + +#include "xfa/fxfa/parser/cxfa_checkbutton.h" + +CJX_CheckButton::CJX_CheckButton(CXFA_CheckButton* node) : CJX_Node(node) {} + +CJX_CheckButton::~CJX_CheckButton() = default; + +void CJX_CheckButton::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_CheckButton::allowNeutral(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_CheckButton::mark(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_CheckButton::shape(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_CheckButton::size(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_CheckButton::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_checkbutton.h b/fxjs/xfa/cjx_checkbutton.h new file mode 100644 index 0000000000000000000000000000000000000000..18cca68d23b8763ced8542d483dec389d132c5f1 --- /dev/null +++ b/fxjs/xfa/cjx_checkbutton.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CHECKBUTTON_H_ +#define FXJS_XFA_CJX_CHECKBUTTON_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_CheckButton; + +class CJX_CheckButton : public CJX_Node { + public: + explicit CJX_CheckButton(CXFA_CheckButton* node); + ~CJX_CheckButton() override; + + JS_PROP(allowNeutral); + JS_PROP(mark); + JS_PROP(shape); + JS_PROP(size); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CHECKBUTTON_H_ diff --git a/fxjs/xfa/cjx_choicelist.cpp b/fxjs/xfa/cjx_choicelist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c85a03706100b02ff8838c1a612bd8d5de3bd44 --- /dev/null +++ b/fxjs/xfa/cjx_choicelist.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_choicelist.h" + +#include "xfa/fxfa/parser/cxfa_choicelist.h" + +CJX_ChoiceList::CJX_ChoiceList(CXFA_ChoiceList* node) : CJX_Node(node) {} + +CJX_ChoiceList::~CJX_ChoiceList() = default; + +void CJX_ChoiceList::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ChoiceList::open(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ChoiceList::commitOn(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ChoiceList::textEntry(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ChoiceList::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_choicelist.h b/fxjs/xfa/cjx_choicelist.h new file mode 100644 index 0000000000000000000000000000000000000000..40336f2aac50b0c381eb0656535f7fa6fdc1d06c --- /dev/null +++ b/fxjs/xfa/cjx_choicelist.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CHOICELIST_H_ +#define FXJS_XFA_CJX_CHOICELIST_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_ChoiceList; + +class CJX_ChoiceList : public CJX_Node { + public: + explicit CJX_ChoiceList(CXFA_ChoiceList* node); + ~CJX_ChoiceList() override; + + JS_PROP(commitOn); + JS_PROP(open); + JS_PROP(textEntry); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CHOICELIST_H_ diff --git a/fxjs/xfa/cjx_color.cpp b/fxjs/xfa/cjx_color.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe7da0590c4e089a6754503821184a9a0eef6e21 --- /dev/null +++ b/fxjs/xfa/cjx_color.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_color.h" + +#include "xfa/fxfa/parser/cxfa_color.h" + +CJX_Color::CJX_Color(CXFA_Color* node) : CJX_Node(node) {} + +CJX_Color::~CJX_Color() = default; + +void CJX_Color::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Color::cSpace(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Color::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Color::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_color.h b/fxjs/xfa/cjx_color.h new file mode 100644 index 0000000000000000000000000000000000000000..c6257535568ce912aaf1b121aa09d40f51cbe3a1 --- /dev/null +++ b/fxjs/xfa/cjx_color.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_COLOR_H_ +#define FXJS_XFA_CJX_COLOR_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Color; + +class CJX_Color : public CJX_Node { + public: + explicit CJX_Color(CXFA_Color* node); + ~CJX_Color() override; + + JS_PROP(cSpace); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_COLOR_H_ diff --git a/fxjs/xfa/cjx_comb.cpp b/fxjs/xfa/cjx_comb.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77144af33c5fa2c80568b810b9ce4dd0e18031b9 --- /dev/null +++ b/fxjs/xfa/cjx_comb.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_comb.h" + +#include "xfa/fxfa/parser/cxfa_comb.h" + +CJX_Comb::CJX_Comb(CXFA_Comb* node) : CJX_Node(node) {} + +CJX_Comb::~CJX_Comb() = default; + +void CJX_Comb::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Comb::numberOfCells(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_Integer(pValue, bSetting, eAttribute); +} + +void CJX_Comb::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_comb.h b/fxjs/xfa/cjx_comb.h new file mode 100644 index 0000000000000000000000000000000000000000..1c8d631f1d62c0e833dbd552cddd18e4b402e628 --- /dev/null +++ b/fxjs/xfa/cjx_comb.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_COMB_H_ +#define FXJS_XFA_CJX_COMB_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Comb; + +class CJX_Comb : public CJX_Node { + public: + explicit CJX_Comb(CXFA_Comb* node); + ~CJX_Comb() override; + + JS_PROP(numberOfCells); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_COMB_H_ diff --git a/fxjs/xfa/cjx_command.cpp b/fxjs/xfa/cjx_command.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30e654b8bdee185b78157c3a95b10d6ae5bd517b --- /dev/null +++ b/fxjs/xfa/cjx_command.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_command.h" + +#include "xfa/fxfa/parser/cxfa_command.h" + +CJX_Command::CJX_Command(CXFA_Command* node) : CJX_Node(node) {} + +CJX_Command::~CJX_Command() = default; + +void CJX_Command::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Command::timeout(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Command::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_command.h b/fxjs/xfa/cjx_command.h new file mode 100644 index 0000000000000000000000000000000000000000..c4605a31efbcf82254b34e615aa8861dd6229ca0 --- /dev/null +++ b/fxjs/xfa/cjx_command.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_COMMAND_H_ +#define FXJS_XFA_CJX_COMMAND_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Command; + +class CJX_Command : public CJX_Node { + public: + explicit CJX_Command(CXFA_Command* node); + ~CJX_Command() override; + + JS_PROP(timeout); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_COMMAND_H_ diff --git a/fxjs/xfa/cjx_connect.cpp b/fxjs/xfa/cjx_connect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d58420d1dfc0380a7c020cdb205050937868a662 --- /dev/null +++ b/fxjs/xfa/cjx_connect.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_connect.h" + +#include "xfa/fxfa/parser/cxfa_connect.h" + +CJX_Connect::CJX_Connect(CXFA_Connect* node) : CJX_Node(node) {} + +CJX_Connect::~CJX_Connect() = default; + +void CJX_Connect::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Connect::timeout(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Connect::connection(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Connect::usage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Connect::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Connect::delayedOpen(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Connect::ref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_connect.h b/fxjs/xfa/cjx_connect.h new file mode 100644 index 0000000000000000000000000000000000000000..2c279175c76734ea7f4603d560aefb180ae06117 --- /dev/null +++ b/fxjs/xfa/cjx_connect.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CONNECT_H_ +#define FXJS_XFA_CJX_CONNECT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Connect; + +class CJX_Connect : public CJX_Node { + public: + explicit CJX_Connect(CXFA_Connect* node); + ~CJX_Connect() override; + + JS_PROP(connection); + JS_PROP(delayedOpen); + JS_PROP(ref); + JS_PROP(timeout); + JS_PROP(usage); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CONNECT_H_ diff --git a/fxjs/xfa/cjx_connectstring.cpp b/fxjs/xfa/cjx_connectstring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75c6359f8482669a692965555b8311b53aca6e7e --- /dev/null +++ b/fxjs/xfa/cjx_connectstring.cpp @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_connectstring.h" + +#include "xfa/fxfa/parser/cxfa_connectstring.h" + +CJX_ConnectString::CJX_ConnectString(CXFA_ConnectString* node) + : CJX_TextNode(node) {} + +CJX_ConnectString::~CJX_ConnectString() = default; + +void CJX_ConnectString::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ConnectString::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_connectstring.h b/fxjs/xfa/cjx_connectstring.h new file mode 100644 index 0000000000000000000000000000000000000000..969c92b6d8362678c0676e959b82deb26e5758e4 --- /dev/null +++ b/fxjs/xfa/cjx_connectstring.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CONNECTSTRING_H_ +#define FXJS_XFA_CJX_CONNECTSTRING_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_ConnectString; + +class CJX_ConnectString : public CJX_TextNode { + public: + explicit CJX_ConnectString(CXFA_ConnectString* node); + ~CJX_ConnectString() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_CONNECTSTRING_H_ diff --git a/fxjs/xfa/cjx_container.cpp b/fxjs/xfa/cjx_container.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf0aca0cbb86c8cff855be8f9d385474492eff9f --- /dev/null +++ b/fxjs/xfa/cjx_container.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_container.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_field.h" + +const CJX_MethodSpec CJX_Container::MethodSpecs[] = { + {"getDelta", getDelta_static}, + {"getDeltas", getDeltas_static}}; + +CJX_Container::CJX_Container(CXFA_Node* node) : CJX_Node(node) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Container::~CJX_Container() {} + +CJS_Return CJX_Container::getDelta( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_Container::getDeltas( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument()); + return CJS_Return(runtime->NewXFAObject( + pFormNodes, + GetDocument()->GetScriptContext()->GetJseNormalClass()->GetTemplate())); +} diff --git a/fxjs/xfa/cjx_container.h b/fxjs/xfa/cjx_container.h new file mode 100644 index 0000000000000000000000000000000000000000..0e2170fa2aa95f6304f5e092b307239a40fcfbb6 --- /dev/null +++ b/fxjs/xfa/cjx_container.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CONTAINER_H_ +#define FXJS_XFA_CJX_CONTAINER_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Node; + +class CJX_Container : public CJX_Node { + public: + explicit CJX_Container(CXFA_Node* node); + ~CJX_Container() override; + + JS_METHOD(getDelta, CJX_Container); + JS_METHOD(getDeltas, CJX_Container); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_CONTAINER_H_ diff --git a/fxjs/xfa/cjx_content.cpp b/fxjs/xfa/cjx_content.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd25829a67528c9a5278f56acc471e48a18a340e --- /dev/null +++ b/fxjs/xfa/cjx_content.cpp @@ -0,0 +1,14 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_content.h" + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cxfa_object.h" + +CJX_Content::CJX_Content(CXFA_Object* obj) : CJX_Object(obj) {} + +CJX_Content::~CJX_Content() {} diff --git a/fxjs/xfa/cjx_content.h b/fxjs/xfa/cjx_content.h new file mode 100644 index 0000000000000000000000000000000000000000..983a75005dca52aa030eabf92284131cc7968164 --- /dev/null +++ b/fxjs/xfa/cjx_content.h @@ -0,0 +1,21 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CONTENT_H_ +#define FXJS_XFA_CJX_CONTENT_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CXFA_Content; + +class CJX_Content : public CJX_Object { + public: + explicit CJX_Content(CXFA_Object* obj); + ~CJX_Content() override; +}; + +#endif // FXJS_XFA_CJX_CONTENT_H_ diff --git a/fxjs/xfa/cjx_contentarea.cpp b/fxjs/xfa/cjx_contentarea.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1e74e7c993dabf75a85f10cb62fffbd2c0c1335 --- /dev/null +++ b/fxjs/xfa/cjx_contentarea.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_contentarea.h" + +#include "xfa/fxfa/parser/cxfa_contentarea.h" + +CJX_ContentArea::CJX_ContentArea(CXFA_ContentArea* node) + : CJX_Container(node) {} + +CJX_ContentArea::~CJX_ContentArea() = default; + +void CJX_ContentArea::x(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ContentArea::y(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ContentArea::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ContentArea::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ContentArea::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_contentarea.h b/fxjs/xfa/cjx_contentarea.h new file mode 100644 index 0000000000000000000000000000000000000000..d97e1085663d8e5aefe4e337de44f0751b6cd73b --- /dev/null +++ b/fxjs/xfa/cjx_contentarea.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CONTENTAREA_H_ +#define FXJS_XFA_CJX_CONTENTAREA_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_ContentArea; + +class CJX_ContentArea : public CJX_Container { + public: + explicit CJX_ContentArea(CXFA_ContentArea* node); + ~CJX_ContentArea() override; + + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(x); + JS_PROP(y); +}; + +#endif // FXJS_XFA_CJX_CONTENTAREA_H_ diff --git a/fxjs/xfa/cjx_corner.cpp b/fxjs/xfa/cjx_corner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ed1922dd9f915bd6dde3a16e15a454ce547ca80 --- /dev/null +++ b/fxjs/xfa/cjx_corner.cpp @@ -0,0 +1,61 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_corner.h" + +#include "xfa/fxfa/parser/cxfa_corner.h" + +CJX_Corner::CJX_Corner(CXFA_Corner* node) : CJX_Node(node) {} + +CJX_Corner::~CJX_Corner() = default; + +void CJX_Corner::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::stroke(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::inverted(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::thickness(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::join(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Corner::radius(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_corner.h b/fxjs/xfa/cjx_corner.h new file mode 100644 index 0000000000000000000000000000000000000000..83251a5ba984a70b728c032d4b8c22e4d7072e50 --- /dev/null +++ b/fxjs/xfa/cjx_corner.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_CORNER_H_ +#define FXJS_XFA_CJX_CORNER_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Corner; + +class CJX_Corner : public CJX_Node { + public: + explicit CJX_Corner(CXFA_Corner* node); + ~CJX_Corner() override; + + JS_PROP(inverted); + JS_PROP(join); + JS_PROP(presence); + JS_PROP(radius); + JS_PROP(stroke); + JS_PROP(thickness); + JS_PROP(usehref); + JS_PROP(use); +}; + +#endif // FXJS_XFA_CJX_CORNER_H_ diff --git a/fxjs/xfa/cjx_datavalue.cpp b/fxjs/xfa/cjx_datavalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b90ed45e666eb63c22315b0d33b25506771a5768 --- /dev/null +++ b/fxjs/xfa/cjx_datavalue.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_datavalue.h" + +#include "xfa/fxfa/parser/cxfa_datavalue.h" + +CJX_DataValue::CJX_DataValue(CXFA_DataValue* node) : CJX_Node(node) {} + +CJX_DataValue::~CJX_DataValue() = default; + +void CJX_DataValue::contentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DataValue::contains(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DataValue::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_DataValue::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} + +void CJX_DataValue::isNull(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_BOOL(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_datavalue.h b/fxjs/xfa/cjx_datavalue.h new file mode 100644 index 0000000000000000000000000000000000000000..16e8ed41fb2c2b166500d4be355607f889a81aa7 --- /dev/null +++ b/fxjs/xfa/cjx_datavalue.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DATAVALUE_H_ +#define FXJS_XFA_CJX_DATAVALUE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_DataValue; + +class CJX_DataValue : public CJX_Node { + public: + explicit CJX_DataValue(CXFA_DataValue* node); + ~CJX_DataValue() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(contains); + JS_PROP(contentType); + JS_PROP(isNull); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_DATAVALUE_H_ diff --git a/fxjs/xfa/cjx_datawindow.cpp b/fxjs/xfa/cjx_datawindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5209cb47e61b7b8b4b1ad05c69de4e977d0f50a3 --- /dev/null +++ b/fxjs/xfa/cjx_datawindow.cpp @@ -0,0 +1,65 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_datawindow.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cscript_datawindow.h" + +const CJX_MethodSpec CJX_DataWindow::MethodSpecs[] = { + {"gotoRecord", gotoRecord_static}, + {"isRecordGroup", isRecordGroup_static}, + {"moveCurrentRecord", moveCurrentRecord_static}, + {"record", record_static}}; + +CJX_DataWindow::CJX_DataWindow(CScript_DataWindow* window) + : CJX_Object(window) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_DataWindow::~CJX_DataWindow() {} + +CJS_Return CJX_DataWindow::moveCurrentRecord( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_DataWindow::record( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_DataWindow::gotoRecord( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_DataWindow::isRecordGroup( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +void CJX_DataWindow::recordsBefore(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_DataWindow::currentRecordNumber(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_DataWindow::recordsAfter(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_DataWindow::isDefined(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} diff --git a/fxjs/xfa/cjx_datawindow.h b/fxjs/xfa/cjx_datawindow.h new file mode 100644 index 0000000000000000000000000000000000000000..dfaa6a44baeeb60fa461cc176cbc9c7d65fcc7cc --- /dev/null +++ b/fxjs/xfa/cjx_datawindow.h @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DATAWINDOW_H_ +#define FXJS_XFA_CJX_DATAWINDOW_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CFXJSE_Value; +class CScript_DataWindow; + +class CJX_DataWindow : public CJX_Object { + public: + explicit CJX_DataWindow(CScript_DataWindow* window); + ~CJX_DataWindow() override; + + JS_METHOD(gotoRecord, CJX_DataWindow); + JS_METHOD(isRecordGroup, CJX_DataWindow); + JS_METHOD(moveCurrentRecord, CJX_DataWindow); + JS_METHOD(record, CJX_DataWindow); + + JS_PROP(currentRecordNumber); + JS_PROP(isDefined); + JS_PROP(recordsAfter); + JS_PROP(recordsBefore); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_DATAWINDOW_H_ diff --git a/fxjs/xfa/cjx_date.cpp b/fxjs/xfa/cjx_date.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ade95a915bf978f29f12b71b150b2d2eb5c2f002 --- /dev/null +++ b/fxjs/xfa/cjx_date.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_date.h" + +#include "xfa/fxfa/parser/cxfa_date.h" + +CJX_Date::CJX_Date(CXFA_Date* node) : CJX_Content(node) {} + +CJX_Date::~CJX_Date() = default; + +void CJX_Date::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Date::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Date::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Date::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_date.h b/fxjs/xfa/cjx_date.h new file mode 100644 index 0000000000000000000000000000000000000000..96dfd0e2c762cab273d69b76c667600a587ae9f5 --- /dev/null +++ b/fxjs/xfa/cjx_date.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DATE_H_ +#define FXJS_XFA_CJX_DATE_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Date; + +class CJX_Date : public CJX_Content { + public: + explicit CJX_Date(CXFA_Date* node); + ~CJX_Date() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_DATE_H_ diff --git a/fxjs/xfa/cjx_datetime.cpp b/fxjs/xfa/cjx_datetime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35ffd05f8ed415cd1ab1876830fb58684fbf8223 --- /dev/null +++ b/fxjs/xfa/cjx_datetime.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_datetime.h" + +#include "xfa/fxfa/parser/cxfa_datetime.h" + +CJX_DateTime::CJX_DateTime(CXFA_DateTime* node) : CJX_Node(node) {} + +CJX_DateTime::~CJX_DateTime() = default; + +void CJX_DateTime::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DateTime::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_DateTime::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DateTime::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_datetime.h b/fxjs/xfa/cjx_datetime.h new file mode 100644 index 0000000000000000000000000000000000000000..9cf7d2fb18d1cf991dcce26bad7e85986e33e48d --- /dev/null +++ b/fxjs/xfa/cjx_datetime.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DATETIME_H_ +#define FXJS_XFA_CJX_DATETIME_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_DateTime; + +class CJX_DateTime : public CJX_Node { + public: + explicit CJX_DateTime(CXFA_DateTime* node); + ~CJX_DateTime() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_DATETIME_H_ diff --git a/fxjs/xfa/cjx_datetimeedit.cpp b/fxjs/xfa/cjx_datetimeedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..284dbf03c1cc8b0b5022fdf4ed4aff77759956d1 --- /dev/null +++ b/fxjs/xfa/cjx_datetimeedit.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_datetimeedit.h" + +#include "xfa/fxfa/parser/cxfa_datetimeedit.h" + +CJX_DateTimeEdit::CJX_DateTimeEdit(CXFA_DateTimeEdit* node) : CJX_Node(node) {} + +CJX_DateTimeEdit::~CJX_DateTimeEdit() = default; + +void CJX_DateTimeEdit::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DateTimeEdit::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DateTimeEdit::hScrollPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_datetimeedit.h b/fxjs/xfa/cjx_datetimeedit.h new file mode 100644 index 0000000000000000000000000000000000000000..067c6bba81d4d18d7d8236880178801c5bf5495a --- /dev/null +++ b/fxjs/xfa/cjx_datetimeedit.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DATETIMEEDIT_H_ +#define FXJS_XFA_CJX_DATETIMEEDIT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_DateTimeEdit; + +class CJX_DateTimeEdit : public CJX_Node { + public: + explicit CJX_DateTimeEdit(CXFA_DateTimeEdit* node); + ~CJX_DateTimeEdit() override; + + JS_PROP(hScrollPolicy); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_DATETIMEEDIT_H_ diff --git a/fxjs/xfa/cjx_decimal.cpp b/fxjs/xfa/cjx_decimal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66763baf947bba2aac26bbacef1b44bc3609e4fe --- /dev/null +++ b/fxjs/xfa/cjx_decimal.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_decimal.h" + +#include "xfa/fxfa/parser/cxfa_decimal.h" + +CJX_Decimal::CJX_Decimal(CXFA_Decimal* node) : CJX_Content(node) {} + +CJX_Decimal::~CJX_Decimal() = default; + +void CJX_Decimal::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Decimal::fracDigits(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Decimal::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Decimal::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Decimal::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Decimal::leadDigits(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_decimal.h b/fxjs/xfa/cjx_decimal.h new file mode 100644 index 0000000000000000000000000000000000000000..5753112d04bcef4c8af88e80a366b6350a8bb984 --- /dev/null +++ b/fxjs/xfa/cjx_decimal.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DECIMAL_H_ +#define FXJS_XFA_CJX_DECIMAL_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Decimal; + +class CJX_Decimal : public CJX_Content { + public: + explicit CJX_Decimal(CXFA_Decimal* node); + ~CJX_Decimal() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(fracDigits); + JS_PROP(leadDigits); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_DECIMAL_H_ diff --git a/fxjs/xfa/cjx_defaultui.cpp b/fxjs/xfa/cjx_defaultui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63995cd2ac8fd571cefb73191bc1ca0a034476dd --- /dev/null +++ b/fxjs/xfa/cjx_defaultui.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_defaultui.h" + +#include "xfa/fxfa/parser/cxfa_defaultui.h" + +CJX_DefaultUi::CJX_DefaultUi(CXFA_DefaultUi* node) : CJX_Node(node) {} + +CJX_DefaultUi::~CJX_DefaultUi() = default; + +void CJX_DefaultUi::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DefaultUi::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_defaultui.h b/fxjs/xfa/cjx_defaultui.h new file mode 100644 index 0000000000000000000000000000000000000000..8b8983b8b430bc552f491e9c64d692306887eb29 --- /dev/null +++ b/fxjs/xfa/cjx_defaultui.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DEFAULTUI_H_ +#define FXJS_XFA_CJX_DEFAULTUI_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_DefaultUi; + +class CJX_DefaultUi : public CJX_Node { + public: + explicit CJX_DefaultUi(CXFA_DefaultUi* node); + ~CJX_DefaultUi() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_DEFAULTUI_H_ diff --git a/fxjs/xfa/cjx_delete.cpp b/fxjs/xfa/cjx_delete.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35fe991f6060c6576c790f71ae738c6ea4a780fe --- /dev/null +++ b/fxjs/xfa/cjx_delete.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_delete.h" + +#include "xfa/fxfa/parser/cxfa_delete.h" + +CJX_Delete::CJX_Delete(CXFA_Delete* node) : CJX_TextNode(node) {} + +CJX_Delete::~CJX_Delete() = default; + +void CJX_Delete::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Delete::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_delete.h b/fxjs/xfa/cjx_delete.h new file mode 100644 index 0000000000000000000000000000000000000000..413a140f4487953bc2bdc669a46b66c7652cf14b --- /dev/null +++ b/fxjs/xfa/cjx_delete.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DELETE_H_ +#define FXJS_XFA_CJX_DELETE_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Delete; + +class CJX_Delete : public CJX_TextNode { + public: + explicit CJX_Delete(CXFA_Delete* node); + ~CJX_Delete() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_DELETE_H_ diff --git a/fxjs/xfa/cjx_delta.cpp b/fxjs/xfa/cjx_delta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d8cbd52f3f2b0d46d75014edc67a1acc15feba2 --- /dev/null +++ b/fxjs/xfa/cjx_delta.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_delta.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_delta.h" + +const CJX_MethodSpec CJX_Delta::MethodSpecs[] = {{"restore", restore_static}}; + +CJX_Delta::CJX_Delta(CXFA_Delta* delta) : CJX_Object(delta) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Delta::~CJX_Delta() {} + +CJS_Return CJX_Delta::restore(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +void CJX_Delta::currentValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Delta::savedValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Delta::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} diff --git a/fxjs/xfa/cjx_delta.h b/fxjs/xfa/cjx_delta.h new file mode 100644 index 0000000000000000000000000000000000000000..2b981cd56bbfa960bd3f0837f36b2e294851710e --- /dev/null +++ b/fxjs/xfa/cjx_delta.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DELTA_H_ +#define FXJS_XFA_CJX_DELTA_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CXFA_Delta; + +class CJX_Delta : public CJX_Object { + public: + explicit CJX_Delta(CXFA_Delta* delta); + ~CJX_Delta() override; + + JS_METHOD(restore, CJX_Delta); + + JS_PROP(currentValue); + JS_PROP(savedValue); + JS_PROP(target); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_DELTA_H_ diff --git a/fxjs/xfa/cjx_deltas.cpp b/fxjs/xfa/cjx_deltas.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8969fb03c939832957adda8bf0b227a285a63df --- /dev/null +++ b/fxjs/xfa/cjx_deltas.cpp @@ -0,0 +1,13 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_deltas.h" + +#include "xfa/fxfa/parser/cxfa_deltas.h" + +CJX_Deltas::CJX_Deltas(CXFA_Deltas* src) : CJX_List(src) {} + +CJX_Deltas::~CJX_Deltas() {} diff --git a/fxjs/xfa/cjx_deltas.h b/fxjs/xfa/cjx_deltas.h new file mode 100644 index 0000000000000000000000000000000000000000..c94753f17b80da1f0a11876777c7fff663bc112f --- /dev/null +++ b/fxjs/xfa/cjx_deltas.h @@ -0,0 +1,20 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DELTAS_H_ +#define FXJS_XFA_CJX_DELTAS_H_ + +#include "fxjs/xfa/cjx_list.h" + +class CXFA_Deltas; + +class CJX_Deltas : public CJX_List { + public: + explicit CJX_Deltas(CXFA_Deltas* node); + ~CJX_Deltas() override; +}; + +#endif // FXJS_XFA_CJX_DELTAS_H_ diff --git a/fxjs/xfa/cjx_desc.cpp b/fxjs/xfa/cjx_desc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a49ae63323acec2f8c268393b98d271624142539 --- /dev/null +++ b/fxjs/xfa/cjx_desc.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_desc.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_desc.h" + +const CJX_MethodSpec CJX_Desc::MethodSpecs[] = {{"metadata", metadata_static}}; + +CJX_Desc::CJX_Desc(CXFA_Desc* desc) : CJX_Node(desc) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Desc::~CJX_Desc() {} + +CJS_Return CJX_Desc::metadata(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 0 && params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewString("")); +} + +void CJX_Desc::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Desc::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_desc.h b/fxjs/xfa/cjx_desc.h new file mode 100644 index 0000000000000000000000000000000000000000..4d21c7ba3273651954d4b7b340b70d679ba58935 --- /dev/null +++ b/fxjs/xfa/cjx_desc.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DESC_H_ +#define FXJS_XFA_CJX_DESC_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Desc; + +class CJX_Desc : public CJX_Node { + public: + explicit CJX_Desc(CXFA_Desc* desc); + ~CJX_Desc() override; + + JS_METHOD(metadata, CJX_Desc); + + JS_PROP(use); + JS_PROP(usehref); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_DESC_H_ diff --git a/fxjs/xfa/cjx_digestmethod.cpp b/fxjs/xfa/cjx_digestmethod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b85fc0082e106c5c8b32203f6a6b16be3bf7351f --- /dev/null +++ b/fxjs/xfa/cjx_digestmethod.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_digestmethod.h" + +#include "xfa/fxfa/parser/cxfa_digestmethod.h" + +CJX_DigestMethod::CJX_DigestMethod(CXFA_DigestMethod* node) : CJX_Node(node) {} + +CJX_DigestMethod::~CJX_DigestMethod() = default; + +void CJX_DigestMethod::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DigestMethod::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_digestmethod.h b/fxjs/xfa/cjx_digestmethod.h new file mode 100644 index 0000000000000000000000000000000000000000..d14e6f17ad12b3104593e017ee03f2f33c58a33a --- /dev/null +++ b/fxjs/xfa/cjx_digestmethod.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DIGESTMETHOD_H_ +#define FXJS_XFA_CJX_DIGESTMETHOD_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_DigestMethod; + +class CJX_DigestMethod : public CJX_Node { + public: + explicit CJX_DigestMethod(CXFA_DigestMethod* node); + ~CJX_DigestMethod() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_DIGESTMETHOD_H_ diff --git a/fxjs/xfa/cjx_digestmethods.cpp b/fxjs/xfa/cjx_digestmethods.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae7cbcd3e1ed61c8dad1efe776b6d0f15287846b --- /dev/null +++ b/fxjs/xfa/cjx_digestmethods.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_digestmethods.h" + +#include "xfa/fxfa/parser/cxfa_digestmethods.h" + +CJX_DigestMethods::CJX_DigestMethods(CXFA_DigestMethods* node) + : CJX_Node(node) {} + +CJX_DigestMethods::~CJX_DigestMethods() = default; + +void CJX_DigestMethods::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DigestMethods::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_DigestMethods::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_digestmethods.h b/fxjs/xfa/cjx_digestmethods.h new file mode 100644 index 0000000000000000000000000000000000000000..b3addc367ebd878811c764dcd534abd56794278f --- /dev/null +++ b/fxjs/xfa/cjx_digestmethods.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DIGESTMETHODS_H_ +#define FXJS_XFA_CJX_DIGESTMETHODS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_DigestMethods; + +class CJX_DigestMethods : public CJX_Node { + public: + explicit CJX_DigestMethods(CXFA_DigestMethods* node); + ~CJX_DigestMethods() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_DIGESTMETHODS_H_ diff --git a/fxjs/xfa/cjx_draw.cpp b/fxjs/xfa/cjx_draw.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1baabfd2c0a5d9233f866759775463b89824d2f --- /dev/null +++ b/fxjs/xfa/cjx_draw.cpp @@ -0,0 +1,153 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_draw.h" + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_draw.h" + +CJX_Draw::CJX_Draw(CXFA_Draw* node) : CJX_Container(node) {} + +CJX_Draw::~CJX_Draw() = default; + +void CJX_Draw::h(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::w(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::x(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::y(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::hAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::rotate(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::vAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::maxH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::maxW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::minH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::minW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::rawValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Draw::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (!bSetting) { + WideString content = GetContent(true); + if (content.IsEmpty()) + pValue->SetNull(); + else + pValue->SetString(content.UTF8Encode().AsStringView()); + + return; + } + + if (!pValue || !pValue->IsString()) + return; + + XFA_Element uiType = GetXFANode()->GetWidgetAcc()->GetUIType(); + if (uiType != XFA_Element::Text) + return; + + WideString wsNewValue = pValue->ToWideString(); + SetContent(wsNewValue, wsNewValue, true, true, true); +} + +void CJX_Draw::colSpan(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::locale(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Draw::anchorType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_draw.h b/fxjs/xfa/cjx_draw.h new file mode 100644 index 0000000000000000000000000000000000000000..1d5603aefeab711667a79c6ef73a3755cc1ecfd9 --- /dev/null +++ b/fxjs/xfa/cjx_draw.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_DRAW_H_ +#define FXJS_XFA_CJX_DRAW_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_Draw; + +class CJX_Draw : public CJX_Container { + public: + explicit CJX_Draw(CXFA_Draw* node); + ~CJX_Draw() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(anchorType); + JS_PROP(colSpan); + JS_PROP(h); + JS_PROP(hAlign); + JS_PROP(locale); + JS_PROP(maxH); + JS_PROP(maxW); + JS_PROP(minH); + JS_PROP(minW); + JS_PROP(presence); + JS_PROP(rawValue); + JS_PROP(relevant); + JS_PROP(rotate); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(vAlign); + JS_PROP(w); + JS_PROP(x); + JS_PROP(y); +}; + +#endif // FXJS_XFA_CJX_DRAW_H_ diff --git a/fxjs/xfa/cjx_edge.cpp b/fxjs/xfa/cjx_edge.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea1fa35c4901e8cf108a3ff678f4a6b31de49b6f --- /dev/null +++ b/fxjs/xfa/cjx_edge.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_edge.h" + +#include "xfa/fxfa/parser/cxfa_edge.h" + +CJX_Edge::CJX_Edge(CXFA_Edge* node) : CJX_Node(node) {} + +CJX_Edge::~CJX_Edge() = default; + +void CJX_Edge::cap(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Edge::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Edge::stroke(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Edge::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Edge::thickness(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Edge::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_edge.h b/fxjs/xfa/cjx_edge.h new file mode 100644 index 0000000000000000000000000000000000000000..ef4ddeb27554d0335b2c537be83124bdc078ced4 --- /dev/null +++ b/fxjs/xfa/cjx_edge.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EDGE_H_ +#define FXJS_XFA_CJX_EDGE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Edge; + +class CJX_Edge : public CJX_Node { + public: + explicit CJX_Edge(CXFA_Edge* node); + ~CJX_Edge() override; + + JS_PROP(cap); + JS_PROP(presence); + JS_PROP(stroke); + JS_PROP(thickness); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_EDGE_H_ diff --git a/fxjs/xfa/cjx_encoding.cpp b/fxjs/xfa/cjx_encoding.cpp new file mode 100644 index 0000000000000000000000000000000000000000..debfe4042af211277464fa6248cb1733b380a75d --- /dev/null +++ b/fxjs/xfa/cjx_encoding.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_encoding.h" + +#include "xfa/fxfa/parser/cxfa_encoding.h" + +CJX_Encoding::CJX_Encoding(CXFA_Encoding* node) : CJX_Node(node) {} + +CJX_Encoding::~CJX_Encoding() = default; + +void CJX_Encoding::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Encoding::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_encoding.h b/fxjs/xfa/cjx_encoding.h new file mode 100644 index 0000000000000000000000000000000000000000..ea82333d4464f4df93b86e57f1d946dbeb112d50 --- /dev/null +++ b/fxjs/xfa/cjx_encoding.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ENCODING_H_ +#define FXJS_XFA_CJX_ENCODING_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Encoding; + +class CJX_Encoding : public CJX_Node { + public: + explicit CJX_Encoding(CXFA_Encoding* node); + ~CJX_Encoding() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ENCODING_H_ diff --git a/fxjs/xfa/cjx_encodings.cpp b/fxjs/xfa/cjx_encodings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..667929f194120148a139b7b657edf8ad88acf907 --- /dev/null +++ b/fxjs/xfa/cjx_encodings.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_encodings.h" + +#include "xfa/fxfa/parser/cxfa_encodings.h" + +CJX_Encodings::CJX_Encodings(CXFA_Encodings* node) : CJX_Node(node) {} + +CJX_Encodings::~CJX_Encodings() = default; + +void CJX_Encodings::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Encodings::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Encodings::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_encodings.h b/fxjs/xfa/cjx_encodings.h new file mode 100644 index 0000000000000000000000000000000000000000..da4f617c18e20fa9d6e55ab1fec846bf75595afa --- /dev/null +++ b/fxjs/xfa/cjx_encodings.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ENCODINGS_H_ +#define FXJS_XFA_CJX_ENCODINGS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Encodings; + +class CJX_Encodings : public CJX_Node { + public: + explicit CJX_Encodings(CXFA_Encodings* node); + ~CJX_Encodings() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ENCODINGS_H_ diff --git a/fxjs/xfa/cjx_encrypt.cpp b/fxjs/xfa/cjx_encrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbed1f243ad2bec2528943cadfed2c8dbf67e55b --- /dev/null +++ b/fxjs/xfa/cjx_encrypt.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_encrypt.h" + +#include "xfa/fxfa/parser/cxfa_encrypt.h" + +CJX_Encrypt::CJX_Encrypt(CXFA_Encrypt* node) : CJX_Node(node) {} + +CJX_Encrypt::~CJX_Encrypt() = default; + +void CJX_Encrypt::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Encrypt::format(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Encrypt::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_encrypt.h b/fxjs/xfa/cjx_encrypt.h new file mode 100644 index 0000000000000000000000000000000000000000..85fac152527ae5cd8fe12bccf95fec0a6590d4f9 --- /dev/null +++ b/fxjs/xfa/cjx_encrypt.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ENCRYPT_H_ +#define FXJS_XFA_CJX_ENCRYPT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Encrypt; + +class CJX_Encrypt : public CJX_Node { + public: + explicit CJX_Encrypt(CXFA_Encrypt* node); + ~CJX_Encrypt() override; + + JS_PROP(format); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ENCRYPT_H_ diff --git a/fxjs/xfa/cjx_event.cpp b/fxjs/xfa/cjx_event.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8cb2bce36de435df0981a376b7f83de17accf6b0 --- /dev/null +++ b/fxjs/xfa/cjx_event.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_event.h" + +#include "xfa/fxfa/parser/cxfa_event.h" + +CJX_Event::CJX_Event(CXFA_Event* node) : CJX_Node(node) {} + +CJX_Event::~CJX_Event() = default; + +void CJX_Event::ref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Event::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Event::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Event::activity(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_event.h b/fxjs/xfa/cjx_event.h new file mode 100644 index 0000000000000000000000000000000000000000..6c6d92064d3620308b683cae549d49a41b9605da --- /dev/null +++ b/fxjs/xfa/cjx_event.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EVENT_H_ +#define FXJS_XFA_CJX_EVENT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Event; + +class CJX_Event : public CJX_Node { + public: + explicit CJX_Event(CXFA_Event* node); + ~CJX_Event() override; + + JS_PROP(activity); + JS_PROP(ref); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_EVENT_H_ diff --git a/fxjs/xfa/cjx_eventpseudomodel.cpp b/fxjs/xfa/cjx_eventpseudomodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b2d9777d0fae7ec3d38b9c5774fab4ac714bfba --- /dev/null +++ b/fxjs/xfa/cjx_eventpseudomodel.cpp @@ -0,0 +1,256 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_eventpseudomodel.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/parser/cscript_eventpseudomodel.h" + +namespace { + +void StringProperty(CFXJSE_Value* pValue, WideString& wsValue, bool bSetting) { + if (bSetting) { + wsValue = pValue->ToWideString(); + return; + } + pValue->SetString(wsValue.UTF8Encode().AsStringView()); +} + +void InterProperty(CFXJSE_Value* pValue, int32_t& iValue, bool bSetting) { + if (bSetting) { + iValue = pValue->ToInteger(); + return; + } + pValue->SetInteger(iValue); +} + +void BooleanProperty(CFXJSE_Value* pValue, bool& bValue, bool bSetting) { + if (bSetting) { + bValue = pValue->ToBoolean(); + return; + } + pValue->SetBoolean(bValue); +} + +} // namespace + +const CJX_MethodSpec CJX_EventPseudoModel::MethodSpecs[] = { + {"emit", emit_static}, + {"reset", reset_static}}; + +CJX_EventPseudoModel::CJX_EventPseudoModel(CScript_EventPseudoModel* model) + : CJX_Object(model) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_EventPseudoModel::~CJX_EventPseudoModel() {} + +void CJX_EventPseudoModel::change(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::Change, bSetting); +} + +void CJX_EventPseudoModel::commitKey(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::CommitKey, bSetting); +} + +void CJX_EventPseudoModel::fullText(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::FullText, bSetting); +} + +void CJX_EventPseudoModel::keyDown(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::Keydown, bSetting); +} + +void CJX_EventPseudoModel::modifier(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::Modifier, bSetting); +} + +void CJX_EventPseudoModel::newContentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::NewContentType, bSetting); +} + +void CJX_EventPseudoModel::newText(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::NewText, bSetting); +} + +void CJX_EventPseudoModel::prevContentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::PreviousContentType, bSetting); +} + +void CJX_EventPseudoModel::prevText(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::PreviousText, bSetting); +} + +void CJX_EventPseudoModel::reenter(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::Reenter, bSetting); +} + +void CJX_EventPseudoModel::selEnd(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::SelectionEnd, bSetting); +} + +void CJX_EventPseudoModel::selStart(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::SelectionStart, bSetting); +} + +void CJX_EventPseudoModel::shift(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::Shift, bSetting); +} + +void CJX_EventPseudoModel::soapFaultCode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::SoapFaultCode, bSetting); +} + +void CJX_EventPseudoModel::soapFaultString(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::SoapFaultString, bSetting); +} + +void CJX_EventPseudoModel::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Property(pValue, XFA_Event::Target, bSetting); +} + +CJS_Return CJX_EventPseudoModel::emit( + CJS_V8* runtime, + const std::vector>& params) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + CXFA_EventParam* pEventParam = pScriptContext->GetEventParam(); + if (!pEventParam) + return CJS_Return(true); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_FFWidgetHandler* pWidgetHandler = pNotify->GetWidgetHandler(); + if (!pWidgetHandler) + return CJS_Return(true); + + pWidgetHandler->ProcessEvent(pEventParam->m_pTarget, pEventParam); + return CJS_Return(true); +} + +CJS_Return CJX_EventPseudoModel::reset( + CJS_V8* runtime, + const std::vector>& params) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + CXFA_EventParam* pEventParam = pScriptContext->GetEventParam(); + if (!pEventParam) + return CJS_Return(true); + + pEventParam->Reset(); + return CJS_Return(true); +} + +void CJX_EventPseudoModel::Property(CFXJSE_Value* pValue, + XFA_Event dwFlag, + bool bSetting) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return; + + CXFA_EventParam* pEventParam = pScriptContext->GetEventParam(); + if (!pEventParam) + return; + + switch (dwFlag) { + case XFA_Event::CancelAction: + BooleanProperty(pValue, pEventParam->m_bCancelAction, bSetting); + break; + case XFA_Event::Change: + StringProperty(pValue, pEventParam->m_wsChange, bSetting); + break; + case XFA_Event::CommitKey: + InterProperty(pValue, pEventParam->m_iCommitKey, bSetting); + break; + case XFA_Event::FullText: + StringProperty(pValue, pEventParam->m_wsFullText, bSetting); + break; + case XFA_Event::Keydown: + BooleanProperty(pValue, pEventParam->m_bKeyDown, bSetting); + break; + case XFA_Event::Modifier: + BooleanProperty(pValue, pEventParam->m_bModifier, bSetting); + break; + case XFA_Event::NewContentType: + StringProperty(pValue, pEventParam->m_wsNewContentType, bSetting); + break; + case XFA_Event::NewText: + StringProperty(pValue, pEventParam->m_wsNewText, bSetting); + break; + case XFA_Event::PreviousContentType: + StringProperty(pValue, pEventParam->m_wsPrevContentType, bSetting); + break; + case XFA_Event::PreviousText: + StringProperty(pValue, pEventParam->m_wsPrevText, bSetting); + break; + case XFA_Event::Reenter: + BooleanProperty(pValue, pEventParam->m_bReenter, bSetting); + break; + case XFA_Event::SelectionEnd: + InterProperty(pValue, pEventParam->m_iSelEnd, bSetting); + break; + case XFA_Event::SelectionStart: + InterProperty(pValue, pEventParam->m_iSelStart, bSetting); + break; + case XFA_Event::Shift: + BooleanProperty(pValue, pEventParam->m_bShift, bSetting); + break; + case XFA_Event::SoapFaultCode: + StringProperty(pValue, pEventParam->m_wsSoapFaultCode, bSetting); + break; + case XFA_Event::SoapFaultString: + StringProperty(pValue, pEventParam->m_wsSoapFaultString, bSetting); + break; + case XFA_Event::Target: + break; + default: + break; + } +} diff --git a/fxjs/xfa/cjx_eventpseudomodel.h b/fxjs/xfa/cjx_eventpseudomodel.h new file mode 100644 index 0000000000000000000000000000000000000000..92d731c28969c7179de5e9881f5de3fa49c138f5 --- /dev/null +++ b/fxjs/xfa/cjx_eventpseudomodel.h @@ -0,0 +1,67 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EVENTPSEUDOMODEL_H_ +#define FXJS_XFA_CJX_EVENTPSEUDOMODEL_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CFXJSE_Value; +class CScript_EventPseudoModel; + +enum class XFA_Event { + Change = 0, + CommitKey, + FullText, + Keydown, + Modifier, + NewContentType, + NewText, + PreviousContentType, + PreviousText, + Reenter, + SelectionEnd, + SelectionStart, + Shift, + SoapFaultCode, + SoapFaultString, + Target, + CancelAction +}; + +class CJX_EventPseudoModel : public CJX_Object { + public: + explicit CJX_EventPseudoModel(CScript_EventPseudoModel* model); + ~CJX_EventPseudoModel() override; + + JS_METHOD(emit, CJX_EventPseudoModel); + JS_METHOD(reset, CJX_EventPseudoModel); + + JS_PROP(change); + JS_PROP(commitKey); + JS_PROP(fullText); + JS_PROP(keyDown); + JS_PROP(modifier); + JS_PROP(newContentType); + JS_PROP(newText); + JS_PROP(prevContentType); + JS_PROP(prevText); + JS_PROP(reenter); + JS_PROP(selEnd); + JS_PROP(selStart); + JS_PROP(shift); + JS_PROP(soapFaultCode); + JS_PROP(soapFaultString); + JS_PROP(target); + + private: + void Property(CFXJSE_Value* pValue, XFA_Event dwFlag, bool bSetting); + + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_EVENTPSEUDOMODEL_H_ diff --git a/fxjs/xfa/cjx_exclgroup.cpp b/fxjs/xfa/cjx_exclgroup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d814dc125f33b1cda2d8e9b6926ff6a8e954a02 --- /dev/null +++ b/fxjs/xfa/cjx_exclgroup.cpp @@ -0,0 +1,290 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_exclgroup.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/fxfa.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_exclgroup.h" + +const CJX_MethodSpec CJX_ExclGroup::MethodSpecs[] = { + {"execCalculate", execCalculate_static}, + {"execEvent", execEvent_static}, + {"execInitialize", execInitialize_static}, + {"execValidate", execValidate_static}, + {"selectedMember", selectedMember_static}}; + +CJX_ExclGroup::CJX_ExclGroup(CXFA_ExclGroup* group) : CJX_Node(group) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_ExclGroup::~CJX_ExclGroup() {} + +CJS_Return CJX_ExclGroup::execEvent( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + execSingleEventByName(runtime->ToWideString(params[0]).AsStringView(), + XFA_Element::ExclGroup); + return CJS_Return(true); +} + +CJS_Return CJX_ExclGroup::execInitialize( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize); + return CJS_Return(true); +} + +CJS_Return CJX_ExclGroup::execCalculate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate); + return CJS_Return(true); +} + +CJS_Return CJX_ExclGroup::execValidate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* notify = GetDocument()->GetNotify(); + if (!notify) + return CJS_Return(runtime->NewBoolean(false)); + + int32_t iRet = notify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate); + return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); +} + +CJS_Return CJX_ExclGroup::selectedMember( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(runtime->NewNull()); + + CXFA_Node* pReturnNode = nullptr; + if (params.empty()) { + pReturnNode = pWidgetAcc->GetSelectedMember(); + } else { + pReturnNode = pWidgetAcc->SetSelectedMember( + runtime->ToWideString(params[0]).AsStringView(), true); + } + if (!pReturnNode) + return CJS_Return(runtime->NewNull()); + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pReturnNode); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +void CJX_ExclGroup::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + if (bSetting) { + pWidgetAcc->SetSelectedMemberByValue(pValue->ToWideString().AsStringView(), + true, true, true); + return; + } + + WideString wsValue = GetContent(true); + XFA_VERSION curVersion = GetDocument()->GetCurVersionMode(); + if (wsValue.IsEmpty() && curVersion >= XFA_VERSION_300) { + pValue->SetNull(); + return; + } + pValue->SetString(wsValue.UTF8Encode().AsStringView()); +} + +void CJX_ExclGroup::rawValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::transient(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_ExclGroup::access(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::accessKey(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::anchorType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::borderColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_BorderColor(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::borderWidth(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_BorderWidth(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::colSpan(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::fillColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_FillColor(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::h(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::hAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::layout(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::mandatory(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_Mandatory(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::mandatoryMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_MandatoryMessage(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::maxH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::maxW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::minH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::minW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::validationMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_ValidationMessage(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::vAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::w(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::x(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExclGroup::y(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_exclgroup.h b/fxjs/xfa/cjx_exclgroup.h new file mode 100644 index 0000000000000000000000000000000000000000..a972fba5ff94281b09fe138d9ed8f7a2153f38f3 --- /dev/null +++ b/fxjs/xfa/cjx_exclgroup.h @@ -0,0 +1,59 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EXCLGROUP_H_ +#define FXJS_XFA_CJX_EXCLGROUP_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_ExclGroup; + +class CJX_ExclGroup : public CJX_Node { + public: + explicit CJX_ExclGroup(CXFA_ExclGroup* group); + ~CJX_ExclGroup() override; + + JS_METHOD(execCalculate, CJX_ExclGroup); + JS_METHOD(execEvent, CJX_ExclGroup); + JS_METHOD(execInitialize, CJX_ExclGroup); + JS_METHOD(execValidate, CJX_ExclGroup); + JS_METHOD(selectedMember, CJX_ExclGroup); + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(access); + JS_PROP(accessKey); + JS_PROP(anchorType); + JS_PROP(borderColor); + JS_PROP(borderWidth); + JS_PROP(colSpan); + JS_PROP(fillColor); + JS_PROP(h); + JS_PROP(hAlign); + JS_PROP(layout); + JS_PROP(mandatory); + JS_PROP(mandatoryMessage); + JS_PROP(maxH); + JS_PROP(maxW); + JS_PROP(minH); + JS_PROP(minW); + JS_PROP(presence); + JS_PROP(rawValue); + JS_PROP(relevant); + JS_PROP(transient); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(validationMessage); + JS_PROP(vAlign); + JS_PROP(w); + JS_PROP(x); + JS_PROP(y); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_EXCLGROUP_H_ diff --git a/fxjs/xfa/cjx_exdata.cpp b/fxjs/xfa/cjx_exdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ce72c4943837c12d5fe4c551ff1cadbb79f9c22 --- /dev/null +++ b/fxjs/xfa/cjx_exdata.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_exdata.h" + +#include "xfa/fxfa/parser/cxfa_exdata.h" + +CJX_ExData::CJX_ExData(CXFA_ExData* node) : CJX_Content(node) {} + +CJX_ExData::~CJX_ExData() = default; + +void CJX_ExData::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExData::contentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExData::transferEncoding(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExData::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_ExData::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExData::maxLength(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExData::href(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_exdata.h b/fxjs/xfa/cjx_exdata.h new file mode 100644 index 0000000000000000000000000000000000000000..e059da8b9d8617471f6d04d9f4fee093bbf9c184 --- /dev/null +++ b/fxjs/xfa/cjx_exdata.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EXDATA_H_ +#define FXJS_XFA_CJX_EXDATA_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_ExData; + +class CJX_ExData : public CJX_Content { + public: + explicit CJX_ExData(CXFA_ExData* node); + ~CJX_ExData() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(contentType); + JS_PROP(href); + JS_PROP(maxLength); + JS_PROP(transferEncoding); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_EXDATA_H_ diff --git a/fxjs/xfa/cjx_execute.cpp b/fxjs/xfa/cjx_execute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5fc4a77859bcfe7159d7be5820a336c0a7ebd6f2 --- /dev/null +++ b/fxjs/xfa/cjx_execute.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_execute.h" + +#include "xfa/fxfa/parser/cxfa_execute.h" + +CJX_Execute::CJX_Execute(CXFA_Execute* node) : CJX_Node(node) {} + +CJX_Execute::~CJX_Execute() = default; + +void CJX_Execute::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Execute::connection(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Execute::runAt(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Execute::executeType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Execute::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_execute.h b/fxjs/xfa/cjx_execute.h new file mode 100644 index 0000000000000000000000000000000000000000..ef7f629e36b326c8cfc754089afc7406b2b7896e --- /dev/null +++ b/fxjs/xfa/cjx_execute.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EXECUTE_H_ +#define FXJS_XFA_CJX_EXECUTE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Execute; + +class CJX_Execute : public CJX_Node { + public: + explicit CJX_Execute(CXFA_Execute* node); + ~CJX_Execute() override; + + JS_PROP(connection); + JS_PROP(executeType); + JS_PROP(runAt); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_EXECUTE_H_ diff --git a/fxjs/xfa/cjx_exobject.cpp b/fxjs/xfa/cjx_exobject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2252d53d061d59ca2dddd47c1f90927295ff7381 --- /dev/null +++ b/fxjs/xfa/cjx_exobject.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_exobject.h" + +#include "xfa/fxfa/parser/cxfa_exobject.h" + +CJX_ExObject::CJX_ExObject(CXFA_ExObject* node) : CJX_Node(node) {} + +CJX_ExObject::~CJX_ExObject() = default; + +void CJX_ExObject::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExObject::codeType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExObject::archive(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExObject::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExObject::codeBase(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ExObject::classId(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_exobject.h b/fxjs/xfa/cjx_exobject.h new file mode 100644 index 0000000000000000000000000000000000000000..2fec24a6fb91256fa1c0e55b07af5273351d5d06 --- /dev/null +++ b/fxjs/xfa/cjx_exobject.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EXOBJECT_H_ +#define FXJS_XFA_CJX_EXOBJECT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_ExObject; + +class CJX_ExObject : public CJX_Node { + public: + explicit CJX_ExObject(CXFA_ExObject* node); + ~CJX_ExObject() override; + + JS_PROP(archive); + JS_PROP(classId); + JS_PROP(codeBase); + JS_PROP(codeType); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_EXOBJECT_H_ diff --git a/fxjs/xfa/cjx_extras.cpp b/fxjs/xfa/cjx_extras.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73ea8ea5ba674f934ca14ddbc412c911098ea5ab --- /dev/null +++ b/fxjs/xfa/cjx_extras.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_extras.h" + +#include "xfa/fxfa/parser/cxfa_extras.h" + +CJX_Extras::CJX_Extras(CXFA_Extras* node) : CJX_Node(node) {} + +CJX_Extras::~CJX_Extras() = default; + +void CJX_Extras::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Extras::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Extras::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_extras.h b/fxjs/xfa/cjx_extras.h new file mode 100644 index 0000000000000000000000000000000000000000..9f5790369e5d513ec938e12731a66f691a9ddedc --- /dev/null +++ b/fxjs/xfa/cjx_extras.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_EXTRAS_H_ +#define FXJS_XFA_CJX_EXTRAS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Extras; + +class CJX_Extras : public CJX_Node { + public: + explicit CJX_Extras(CXFA_Extras* node); + ~CJX_Extras() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_EXTRAS_H_ diff --git a/fxjs/xfa/cjx_field.cpp b/fxjs/xfa/cjx_field.cpp new file mode 100644 index 0000000000000000000000000000000000000000..299c6ef3a485bf09ae825e0fe12b8e31300834c9 --- /dev/null +++ b/fxjs/xfa/cjx_field.cpp @@ -0,0 +1,531 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_field.h" + +#include + +#include "core/fxcrt/cfx_decimal.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/fxfa.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_field.h" +#include "xfa/fxfa/parser/cxfa_value.h" + +const CJX_MethodSpec CJX_Field::MethodSpecs[] = { + {"addItem", addItem_static}, + {"boundItem", boundItem_static}, + {"clearItems", clearItems_static}, + {"deleteItem", deleteItem_static}, + {"execCalculate", execCalculate_static}, + {"execEvent", execEvent_static}, + {"execInitialize", execInitialize_static}, + {"execValidate", execValidate_static}, + {"getDisplayItem", getDisplayItem_static}, + {"getItemState", getItemState_static}, + {"getSaveItem", getSaveItem_static}, + {"setItemState", setItemState_static}}; + +CJX_Field::CJX_Field(CXFA_Field* field) : CJX_Container(field) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Field::~CJX_Field() {} + +CJS_Return CJX_Field::clearItems( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (pWidgetAcc) + pWidgetAcc->DeleteItem(-1, true, false); + return CJS_Return(true); +} + +CJS_Return CJX_Field::execEvent( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString eventString = runtime->ToWideString(params[0]); + int32_t iRet = + execSingleEventByName(eventString.AsStringView(), XFA_Element::Field); + if (eventString != L"validate") + return CJS_Return(true); + + return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); +} + +CJS_Return CJX_Field::execInitialize( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) { + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize, false, + false); + } + return CJS_Return(true); +} + +CJS_Return CJX_Field::deleteItem( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(true); + + bool bValue = pWidgetAcc->DeleteItem(runtime->ToInt32(params[0]), true, true); + return CJS_Return(runtime->NewBoolean(bValue)); +} + +CJS_Return CJX_Field::getSaveItem( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t iIndex = runtime->ToInt32(params[0]); + if (iIndex < 0) + return CJS_Return(runtime->NewNull()); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(runtime->NewNull()); + + Optional value = pWidgetAcc->GetChoiceListItem(iIndex, true); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(runtime->NewString(value->UTF8Encode().AsStringView())); +} + +CJS_Return CJX_Field::boundItem( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(true); + + WideString value = runtime->ToWideString(params[0]); + WideString boundValue = pWidgetAcc->GetItemValue(value.AsStringView()); + return CJS_Return(runtime->NewString(boundValue.UTF8Encode().AsStringView())); +} + +CJS_Return CJX_Field::getItemState( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(true); + + int32_t state = pWidgetAcc->GetItemState(runtime->ToInt32(params[0])); + return CJS_Return(runtime->NewBoolean(state != 0)); +} + +CJS_Return CJX_Field::execCalculate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) { + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate, false, + false); + } + return CJS_Return(true); +} + +CJS_Return CJX_Field::getDisplayItem( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t iIndex = runtime->ToInt32(params[0]); + if (iIndex < 0) + return CJS_Return(runtime->NewNull()); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(runtime->NewNull()); + + Optional value = pWidgetAcc->GetChoiceListItem(iIndex, false); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(runtime->NewString(value->UTF8Encode().AsStringView())); +} + +CJS_Return CJX_Field::setItemState( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(true); + + int32_t iIndex = runtime->ToInt32(params[0]); + if (runtime->ToInt32(params[1]) != 0) { + pWidgetAcc->SetItemState(iIndex, true, true, true, true); + return CJS_Return(true); + } + if (pWidgetAcc->GetItemState(iIndex)) + pWidgetAcc->SetItemState(iIndex, false, true, true, true); + + return CJS_Return(true); +} + +CJS_Return CJX_Field::addItem(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1 && params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); + if (!pWidgetAcc) + return CJS_Return(true); + + WideString label; + if (params.size() >= 1) + label = runtime->ToWideString(params[0]); + + WideString value; + if (params.size() >= 2) + value = runtime->ToWideString(params[1]); + + pWidgetAcc->InsertItem(label, value, true); + return CJS_Return(true); +} + +CJS_Return CJX_Field::execValidate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(runtime->NewBoolean(false)); + + int32_t iRet = pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate, + false, false); + return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); +} + +void CJX_Field::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Node* xfaNode = GetXFANode(); + CXFA_WidgetAcc* pWidgetAcc = xfaNode->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + if (bSetting) { + if (pValue) { + pWidgetAcc->SetPreNull(pWidgetAcc->IsNull()); + pWidgetAcc->SetIsNull(pValue->IsNull()); + } + + WideString wsNewText; + if (pValue && !(pValue->IsNull() || pValue->IsUndefined())) + wsNewText = pValue->ToWideString(); + + CXFA_Node* pUIChild = pWidgetAcc->GetUIChild(); + if (pUIChild->GetElementType() == XFA_Element::NumericEdit) { + wsNewText = pWidgetAcc->NumericLimit( + wsNewText, pWidgetAcc->GetLeadDigits(), pWidgetAcc->GetFracDigits()); + } + + CXFA_WidgetAcc* pContainerWidgetAcc = xfaNode->GetContainerWidgetAcc(); + WideString wsFormatText(wsNewText); + if (pContainerWidgetAcc) + wsFormatText = pContainerWidgetAcc->GetFormatDataValue(wsNewText); + + SetContent(wsNewText, wsFormatText, true, true, true); + return; + } + + WideString content = GetContent(true); + if (content.IsEmpty()) { + pValue->SetNull(); + return; + } + + CXFA_Node* pUIChild = pWidgetAcc->GetUIChild(); + CXFA_Node* formValue = xfaNode->GetFormValueIfExists(); + CXFA_Node* pNode = formValue ? formValue->GetFirstChild() : nullptr; + if (pNode && pNode->GetElementType() == XFA_Element::Decimal) { + if (pUIChild->GetElementType() == XFA_Element::NumericEdit && + (pNode->JSObject()->GetInteger(XFA_Attribute::FracDigits) == -1)) { + pValue->SetString(content.UTF8Encode().AsStringView()); + } else { + CFX_Decimal decimal(content.AsStringView()); + pValue->SetFloat((float)(double)decimal); + } + } else if (pNode && pNode->GetElementType() == XFA_Element::Integer) { + pValue->SetInteger(FXSYS_wtoi(content.c_str())); + } else if (pNode && pNode->GetElementType() == XFA_Element::Boolean) { + pValue->SetBoolean(FXSYS_wtoi(content.c_str()) == 0 ? false : true); + } else if (pNode && pNode->GetElementType() == XFA_Element::Float) { + CFX_Decimal decimal(content.AsStringView()); + pValue->SetFloat((float)(double)decimal); + } else { + pValue->SetString(content.UTF8Encode().AsStringView()); + } +} + +void CJX_Field::editValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + if (bSetting) { + pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pValue->ToWideString()); + return; + } + pValue->SetString( + pWidgetAcc->GetValue(XFA_VALUEPICTURE_Edit).UTF8Encode().AsStringView()); +} + +void CJX_Field::formatMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_Message(pValue, bSetting, XFA_SOM_FormatMessage); +} + +void CJX_Field::formattedValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + if (bSetting) { + pWidgetAcc->SetValue(XFA_VALUEPICTURE_Display, pValue->ToWideString()); + return; + } + pValue->SetString(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display) + .UTF8Encode() + .AsStringView()); +} + +void CJX_Field::parentSubform(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetNull(); +} + +void CJX_Field::selectedIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + if (!bSetting) { + pValue->SetInteger(pWidgetAcc->GetSelectedItem(0)); + return; + } + + int32_t iIndex = pValue->ToInteger(); + if (iIndex == -1) { + pWidgetAcc->ClearAllSelections(); + return; + } + + pWidgetAcc->SetItemState(iIndex, true, true, true, true); +} + +void CJX_Field::access(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::accessKey(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::anchorType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::borderColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_BorderColor(pValue, bSetting, eAttribute); +} + +void CJX_Field::borderWidth(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_BorderWidth(pValue, bSetting, eAttribute); +} + +void CJX_Field::colSpan(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::fillColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_FillColor(pValue, bSetting, eAttribute); +} + +void CJX_Field::fontColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_FontColor(pValue, bSetting, eAttribute); +} + +void CJX_Field::h(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::hAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::locale(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::mandatory(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_Mandatory(pValue, bSetting, eAttribute); +} + +void CJX_Field::mandatoryMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_MandatoryMessage(pValue, bSetting, eAttribute); +} + +void CJX_Field::maxH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::maxW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::minH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::minW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::rawValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Field::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::rotate(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::validationMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_ValidationMessage(pValue, bSetting, eAttribute); +} + +void CJX_Field::vAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::w(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::x(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Field::y(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_field.h b/fxjs/xfa/cjx_field.h new file mode 100644 index 0000000000000000000000000000000000000000..4f7238fc198be2e999ca9adc99105ca8c33c8deb --- /dev/null +++ b/fxjs/xfa/cjx_field.h @@ -0,0 +1,72 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FIELD_H_ +#define FXJS_XFA_CJX_FIELD_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_container.h" + +class CXFA_Field; + +class CJX_Field : public CJX_Container { + public: + explicit CJX_Field(CXFA_Field* field); + ~CJX_Field() override; + + JS_METHOD(addItem, CJX_Field); + JS_METHOD(boundItem, CJX_Field); + JS_METHOD(clearItems, CJX_Field); + JS_METHOD(deleteItem, CJX_Field); + JS_METHOD(execCalculate, CJX_Field); + JS_METHOD(execEvent, CJX_Field); + JS_METHOD(execInitialize, CJX_Field); + JS_METHOD(execValidate, CJX_Field); + JS_METHOD(getDisplayItem, CJX_Field); + JS_METHOD(getItemState, CJX_Field); + JS_METHOD(getSaveItem, CJX_Field); + JS_METHOD(setItemState, CJX_Field); + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(access); + JS_PROP(accessKey); + JS_PROP(anchorType); + JS_PROP(borderColor); + JS_PROP(borderWidth); + JS_PROP(colSpan); + JS_PROP(editValue); + JS_PROP(fillColor); + JS_PROP(fontColor); + JS_PROP(formatMessage); + JS_PROP(formattedValue); + JS_PROP(h); + JS_PROP(hAlign); + JS_PROP(locale); + JS_PROP(mandatory); + JS_PROP(mandatoryMessage); + JS_PROP(maxH); + JS_PROP(maxW); + JS_PROP(minH); + JS_PROP(minW); + JS_PROP(parentSubform); + JS_PROP(presence); + JS_PROP(rawValue); + JS_PROP(relevant); + JS_PROP(rotate); + JS_PROP(selectedIndex); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(validationMessage); + JS_PROP(vAlign); + JS_PROP(w); + JS_PROP(x); + JS_PROP(y); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_FIELD_H_ diff --git a/fxjs/xfa/cjx_fill.cpp b/fxjs/xfa/cjx_fill.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c6aa957c8722eaf15a597f3637ad16d06937c16 --- /dev/null +++ b/fxjs/xfa/cjx_fill.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_fill.h" + +#include "xfa/fxfa/parser/cxfa_fill.h" + +CJX_Fill::CJX_Fill(CXFA_Fill* node) : CJX_Node(node) {} + +CJX_Fill::~CJX_Fill() = default; + +void CJX_Fill::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Fill::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Fill::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_fill.h b/fxjs/xfa/cjx_fill.h new file mode 100644 index 0000000000000000000000000000000000000000..869e3cc2b5d28eacbf3edb28bbb8b5674aa8cd53 --- /dev/null +++ b/fxjs/xfa/cjx_fill.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FILL_H_ +#define FXJS_XFA_CJX_FILL_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Fill; + +class CJX_Fill : public CJX_Node { + public: + explicit CJX_Fill(CXFA_Fill* node); + ~CJX_Fill() override; + + JS_PROP(presence); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_FILL_H_ diff --git a/fxjs/xfa/cjx_filter.cpp b/fxjs/xfa/cjx_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e43dfa8aedae35451ff77ce39f5220c611a80a41 --- /dev/null +++ b/fxjs/xfa/cjx_filter.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_filter.h" + +#include "xfa/fxfa/parser/cxfa_filter.h" + +CJX_Filter::CJX_Filter(CXFA_Filter* node) : CJX_Node(node) {} + +CJX_Filter::~CJX_Filter() = default; + +void CJX_Filter::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Filter::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Filter::addRevocationInfo(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_filter.h b/fxjs/xfa/cjx_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..275d509bbc062fe9c3c7bd03ec3302dc2ba49688 --- /dev/null +++ b/fxjs/xfa/cjx_filter.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FILTER_H_ +#define FXJS_XFA_CJX_FILTER_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Filter; + +class CJX_Filter : public CJX_Node { + public: + explicit CJX_Filter(CXFA_Filter* node); + ~CJX_Filter() override; + + JS_PROP(addRevocationInfo); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_FILTER_H_ diff --git a/fxjs/xfa/cjx_float.cpp b/fxjs/xfa/cjx_float.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04808129377445ec745ba4584b13605931ec4871 --- /dev/null +++ b/fxjs/xfa/cjx_float.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_float.h" + +#include "xfa/fxfa/parser/cxfa_float.h" + +CJX_Float::CJX_Float(CXFA_Float* node) : CJX_Content(node) {} + +CJX_Float::~CJX_Float() = default; + +void CJX_Float::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Float::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Float::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Float::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_float.h b/fxjs/xfa/cjx_float.h new file mode 100644 index 0000000000000000000000000000000000000000..1c9489b35fc3710765cde39f19455684e01a81ad --- /dev/null +++ b/fxjs/xfa/cjx_float.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FLOAT_H_ +#define FXJS_XFA_CJX_FLOAT_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Float; + +class CJX_Float : public CJX_Content { + public: + explicit CJX_Float(CXFA_Float* node); + ~CJX_Float() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_FLOAT_H_ diff --git a/fxjs/xfa/cjx_font.cpp b/fxjs/xfa/cjx_font.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0c62374d8e9f01bd37da072538bb9a845dece60 --- /dev/null +++ b/fxjs/xfa/cjx_font.cpp @@ -0,0 +1,115 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_font.h" + +#include "xfa/fxfa/parser/cxfa_font.h" + +CJX_Font::CJX_Font(CXFA_Font* node) : CJX_Node(node) {} + +CJX_Font::~CJX_Font() = default; + +void CJX_Font::lineThrough(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::typeface(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::fontHorizontalScale(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::kerningMode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::underline(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::baselineShift(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::overlinePeriod(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::letterSpacing(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::lineThroughPeriod(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::fontVerticalScale(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::size(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::posture(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::weight(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::underlinePeriod(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Font::overline(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_font.h b/fxjs/xfa/cjx_font.h new file mode 100644 index 0000000000000000000000000000000000000000..65b40e45081fecf9dc900d388e5c4822faddab9a --- /dev/null +++ b/fxjs/xfa/cjx_font.h @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FONT_H_ +#define FXJS_XFA_CJX_FONT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Font; + +class CJX_Font : public CJX_Node { + public: + explicit CJX_Font(CXFA_Font* node); + ~CJX_Font() override; + + JS_PROP(baselineShift); + JS_PROP(fontHorizontalScale); + JS_PROP(fontVerticalScale); + JS_PROP(kerningMode); + JS_PROP(letterSpacing); + JS_PROP(lineThrough); + JS_PROP(lineThroughPeriod); + JS_PROP(overline); + JS_PROP(overlinePeriod); + JS_PROP(posture); + JS_PROP(size); + JS_PROP(typeface); + JS_PROP(underline); + JS_PROP(underlinePeriod); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(weight); +}; + +#endif // FXJS_XFA_CJX_FONT_H_ diff --git a/fxjs/xfa/cjx_form.cpp b/fxjs/xfa/cjx_form.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54f06fe96646e941d885d6e14c297d102908ab4f --- /dev/null +++ b/fxjs/xfa/cjx_form.cpp @@ -0,0 +1,123 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_form.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_form.h" + +const CJX_MethodSpec CJX_Form::MethodSpecs[] = { + {"execCalculate", execCalculate_static}, + {"execInitialize", execInitialize_static}, + {"execValidate", execValidate_static}, + {"formNodes", formNodes_static}, + {"recalculate", recalculate_static}, + {"remerge", remerge_static}}; + +CJX_Form::CJX_Form(CXFA_Form* form) : CJX_Model(form) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Form::~CJX_Form() {} + +CJS_Return CJX_Form::formNodes( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Node* pDataNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pDataNode) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + std::vector formItems; + CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument()); + pFormNodes->SetArrayNodeList(formItems); + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pFormNodes); + if (!value) + return CJS_Return(runtime->NewNull()); + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_Form::remerge(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + GetDocument()->DoDataRemerge(true); + return CJS_Return(true); +} + +CJS_Return CJX_Form::execInitialize( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize); + return CJS_Return(true); +} + +CJS_Return CJX_Form::recalculate( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_EventParam* pEventParam = + GetDocument()->GetScriptContext()->GetEventParam(); + if (pEventParam->m_eType == XFA_EVENT_Calculate || + pEventParam->m_eType == XFA_EVENT_InitCalculate) { + return CJS_Return(true); + } + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify || runtime->ToInt32(params[0]) != 0) + return CJS_Return(true); + + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate); + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate); + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Ready, true); + return CJS_Return(true); +} + +CJS_Return CJX_Form::execCalculate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate); + return CJS_Return(true); +} + +CJS_Return CJX_Form::execValidate( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 0) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(runtime->NewBoolean(false)); + + int32_t iRet = + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate); + return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); +} diff --git a/fxjs/xfa/cjx_form.h b/fxjs/xfa/cjx_form.h new file mode 100644 index 0000000000000000000000000000000000000000..e4d64daca086aef2e7198f1b7e6cca59515a4b37 --- /dev/null +++ b/fxjs/xfa/cjx_form.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FORM_H_ +#define FXJS_XFA_CJX_FORM_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_model.h" + +class CXFA_Form; + +class CJX_Form : public CJX_Model { + public: + explicit CJX_Form(CXFA_Form* form); + ~CJX_Form() override; + + JS_METHOD(execCalculate, CJX_Form); + JS_METHOD(execInitialize, CJX_Form); + JS_METHOD(execValidate, CJX_Form); + JS_METHOD(formNodes, CJX_Form); + JS_METHOD(recalculate, CJX_Form); + JS_METHOD(remerge, CJX_Form); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_FORM_H_ diff --git a/fxjs/xfa/cjx_format.cpp b/fxjs/xfa/cjx_format.cpp new file mode 100644 index 0000000000000000000000000000000000000000..978650290160ef166155cfea2f9e0d789c0b73e7 --- /dev/null +++ b/fxjs/xfa/cjx_format.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_format.h" + +#include "xfa/fxfa/parser/cxfa_format.h" + +CJX_Format::CJX_Format(CXFA_Format* node) : CJX_Node(node) {} + +CJX_Format::~CJX_Format() = default; + +void CJX_Format::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Format::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_format.h b/fxjs/xfa/cjx_format.h new file mode 100644 index 0000000000000000000000000000000000000000..5e8c971b96f466ec2d95dbd73349ab1bb0c0f2d3 --- /dev/null +++ b/fxjs/xfa/cjx_format.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_FORMAT_H_ +#define FXJS_XFA_CJX_FORMAT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Format; + +class CJX_Format : public CJX_Node { + public: + explicit CJX_Format(CXFA_Format* node); + ~CJX_Format() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_FORMAT_H_ diff --git a/fxjs/xfa/cjx_handler.cpp b/fxjs/xfa/cjx_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e09a7550da2cf51c061b203c9e538d69a26989e --- /dev/null +++ b/fxjs/xfa/cjx_handler.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_handler.h" + +#include "xfa/fxfa/parser/cxfa_handler.h" + +CJX_Handler::CJX_Handler(CXFA_Handler* node) : CJX_TextNode(node) {} + +CJX_Handler::~CJX_Handler() = default; + +void CJX_Handler::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Handler::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Handler::version(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Handler::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_handler.h b/fxjs/xfa/cjx_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..373328b85fba16ad0649829177d75549b78eebbb --- /dev/null +++ b/fxjs/xfa/cjx_handler.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_HANDLER_H_ +#define FXJS_XFA_CJX_HANDLER_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Handler; + +class CJX_Handler : public CJX_TextNode { + public: + explicit CJX_Handler(CXFA_Handler* node); + ~CJX_Handler() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(version); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_HANDLER_H_ diff --git a/fxjs/xfa/cjx_hostpseudomodel.cpp b/fxjs/xfa/cjx_hostpseudomodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..12aa2bdb2bf199b6ab84882487608400c8b5f214 --- /dev/null +++ b/fxjs/xfa/cjx_hostpseudomodel.cpp @@ -0,0 +1,638 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_hostpseudomodel.h" + +#include +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cscript_hostpseudomodel.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +namespace { + +int32_t FilterName(const WideStringView& wsExpression, + int32_t nStart, + WideString& wsFilter) { + ASSERT(nStart > -1); + int32_t iLength = wsExpression.GetLength(); + if (nStart >= iLength) + return iLength; + + wchar_t* pBuf = wsFilter.GetBuffer(iLength - nStart); + int32_t nCount = 0; + const wchar_t* pSrc = wsExpression.unterminated_c_str(); + wchar_t wCur; + while (nStart < iLength) { + wCur = pSrc[nStart++]; + if (wCur == ',') + break; + + pBuf[nCount++] = wCur; + } + wsFilter.ReleaseBuffer(nCount); + wsFilter.Trim(); + return nStart; +} + +} // namespace + +const CJX_MethodSpec CJX_HostPseudoModel::MethodSpecs[] = { + {"beep", beep_static}, + {"documentCountInBatch", documentCountInBatch_static}, + {"documentInBatch", documentInBatch_static}, + {"exportData", exportData_static}, + {"getFocus", getFocus_static}, + {"gotoURL", gotoURL_static}, + {"importData", importData_static}, + {"messageBox", messageBox_static}, + {"openList", openList_static}, + {"pageDown", pageDown_static}, + {"pageUp", pageUp_static}, + {"print", print_static}, + {"resetData", resetData_static}, + {"response", response_static}, + {"setFocus", setFocus_static}}; + +CJX_HostPseudoModel::CJX_HostPseudoModel(CScript_HostPseudoModel* model) + : CJX_Object(model) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_HostPseudoModel::~CJX_HostPseudoModel() {} + +void CJX_HostPseudoModel::appType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetString("Exchange"); +} + +void CJX_HostPseudoModel::calculationsEnabled(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + if (bSetting) { + pNotify->GetDocEnvironment()->SetCalculationsEnabled(hDoc, + pValue->ToBoolean()); + return; + } + pValue->SetBoolean(pNotify->GetDocEnvironment()->IsCalculationsEnabled(hDoc)); +} + +void CJX_HostPseudoModel::currentPage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + if (bSetting) { + pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, pValue->ToInteger()); + return; + } + pValue->SetInteger(pNotify->GetDocEnvironment()->GetCurrentPage(hDoc)); +} + +void CJX_HostPseudoModel::language(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + if (bSetting) { + ThrowException(L"Unable to set language value."); + return; + } + pValue->SetString( + pNotify->GetAppProvider()->GetLanguage().UTF8Encode().AsStringView()); +} + +void CJX_HostPseudoModel::numPages(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + if (bSetting) { + ThrowException(L"Unable to set numPages value."); + return; + } + pValue->SetInteger(pNotify->GetDocEnvironment()->CountPages(hDoc)); +} + +void CJX_HostPseudoModel::platform(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + if (bSetting) { + ThrowException(L"Unable to set platform value."); + return; + } + pValue->SetString( + pNotify->GetAppProvider()->GetPlatform().UTF8Encode().AsStringView()); +} + +void CJX_HostPseudoModel::title(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return; + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + if (bSetting) { + pNotify->GetDocEnvironment()->SetTitle(hDoc, pValue->ToWideString()); + return; + } + + WideString wsTitle; + pNotify->GetDocEnvironment()->GetTitle(hDoc, wsTitle); + pValue->SetString(wsTitle.UTF8Encode().AsStringView()); +} + +void CJX_HostPseudoModel::validationsEnabled(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + if (bSetting) { + pNotify->GetDocEnvironment()->SetValidationsEnabled(hDoc, + pValue->ToBoolean()); + return; + } + + bool bEnabled = pNotify->GetDocEnvironment()->IsValidationsEnabled(hDoc); + pValue->SetBoolean(bEnabled); +} + +void CJX_HostPseudoModel::variation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return; + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + if (bSetting) { + ThrowException(L"Unable to set variation value."); + return; + } + pValue->SetString("Full"); +} + +void CJX_HostPseudoModel::version(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + if (bSetting) { + ThrowException(L"Unable to set version value."); + return; + } + pValue->SetString("11"); +} + +void CJX_HostPseudoModel::name(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetString( + pNotify->GetAppProvider()->GetAppName().UTF8Encode().AsStringView()); +} + +CJS_Return CJX_HostPseudoModel::gotoURL( + CJS_V8* runtime, + const std::vector>& params) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return CJS_Return(true); + + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + WideString URL = runtime->ToWideString(params[0]); + pNotify->GetDocEnvironment()->GotoURL(hDoc, URL); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::openList( + CJS_V8* runtime, + const std::vector>& params) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return CJS_Return(true); + + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_Node* pNode = nullptr; + if (params[0]->IsObject()) { + pNode = ToNode(runtime->ToXFAObject(params[0])); + } else if (params[0]->IsString()) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + CXFA_Object* pObject = pScriptContext->GetThisObject(); + if (!pObject) + return CJS_Return(true); + + uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings; + XFA_RESOLVENODE_RS resolveNodeRS; + bool iRet = pScriptContext->ResolveObjects( + pObject, runtime->ToWideString(params[0]).AsStringView(), + &resolveNodeRS, dwFlag, nullptr); + if (!iRet || !resolveNodeRS.objects.front()->IsNode()) + return CJS_Return(true); + + pNode = resolveNodeRS.objects.front()->AsNode(); + } + + CXFA_LayoutProcessor* pDocLayout = GetDocument()->GetDocLayout(); + if (!pDocLayout) + return CJS_Return(true); + + CXFA_FFWidget* hWidget = + pNotify->GetHWidget(pDocLayout->GetLayoutItem(pNode)); + if (!hWidget) + return CJS_Return(true); + + pNotify->GetDocEnvironment()->SetFocusWidget(pNotify->GetHDOC(), hWidget); + pNotify->OpenDropDownList(hWidget); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::response( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 4) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + WideString question; + if (params.size() >= 1) + question = runtime->ToWideString(params[0]); + + WideString title; + if (params.size() >= 2) + title = runtime->ToWideString(params[1]); + + WideString defaultAnswer; + if (params.size() >= 3) + defaultAnswer = runtime->ToWideString(params[2]); + + bool mark = false; + if (params.size() >= 4) + mark = runtime->ToInt32(params[3]) != 0; + + WideString answer = + pNotify->GetAppProvider()->Response(question, title, defaultAnswer, mark); + return CJS_Return(runtime->NewString(answer.UTF8Encode().AsStringView())); +} + +CJS_Return CJX_HostPseudoModel::documentInBatch( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_HostPseudoModel::resetData( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() > 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + WideString expression; + if (params.size() >= 1) + expression = runtime->ToWideString(params[0]); + + if (expression.IsEmpty()) { + pNotify->ResetData(); + return CJS_Return(true); + } + + int32_t iStart = 0; + WideString wsName; + CXFA_Node* pNode = nullptr; + int32_t iExpLength = expression.GetLength(); + while (iStart < iExpLength) { + iStart = FilterName(expression.AsStringView(), iStart, wsName); + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + CXFA_Object* pObject = pScriptContext->GetThisObject(); + if (!pObject) + return CJS_Return(true); + + uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings; + XFA_RESOLVENODE_RS resolveNodeRS; + bool iRet = pScriptContext->ResolveObjects(pObject, wsName.AsStringView(), + &resolveNodeRS, dwFlag, nullptr); + if (!iRet || !resolveNodeRS.objects.front()->IsNode()) + continue; + + pNode = resolveNodeRS.objects.front()->AsNode(); + pNotify->ResetData(pNode->GetWidgetAcc()); + } + if (!pNode) + pNotify->ResetData(); + + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::beep( + CJS_V8* runtime, + const std::vector>& params) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return CJS_Return(true); + + if (params.size() > 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + uint32_t dwType = 4; + if (params.size() >= 1) + dwType = runtime->ToInt32(params[0]); + + pNotify->GetAppProvider()->Beep(dwType); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::setFocus( + CJS_V8* runtime, + const std::vector>& params) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return CJS_Return(true); + + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_Node* pNode = nullptr; + if (params.size() >= 1) { + if (params[0]->IsObject()) { + pNode = ToNode(runtime->ToXFAObject(params[0])); + } else if (params[0]->IsString()) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + CXFA_Object* pObject = pScriptContext->GetThisObject(); + if (!pObject) + return CJS_Return(true); + + uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings; + XFA_RESOLVENODE_RS resolveNodeRS; + bool iRet = pScriptContext->ResolveObjects( + pObject, runtime->ToWideString(params[0]).AsStringView(), + &resolveNodeRS, dwFlag, nullptr); + if (!iRet || !resolveNodeRS.objects.front()->IsNode()) + return CJS_Return(true); + + pNode = resolveNodeRS.objects.front()->AsNode(); + } + } + pNotify->SetFocusWidgetNode(pNode); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::getFocus( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_Node* pNode = pNotify->GetFocusWidgetNode(); + if (!pNode) + return CJS_Return(true); + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_HostPseudoModel::messageBox( + CJS_V8* runtime, + const std::vector>& params) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return CJS_Return(true); + + if (params.empty() || params.size() > 4) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + WideString message; + if (params.size() >= 1) + message = runtime->ToWideString(params[0]); + + WideString title; + if (params.size() >= 2) + title = runtime->ToWideString(params[1]); + + uint32_t messageType = XFA_MBICON_Error; + if (params.size() >= 3) { + messageType = runtime->ToInt32(params[2]); + if (messageType > XFA_MBICON_Status) + messageType = XFA_MBICON_Error; + } + + uint32_t buttonType = XFA_MB_OK; + if (params.size() >= 4) { + buttonType = runtime->ToInt32(params[3]); + if (buttonType > XFA_MB_YesNoCancel) + buttonType = XFA_MB_OK; + } + + int32_t iValue = pNotify->GetAppProvider()->MsgBox(message, title, + messageType, buttonType); + return CJS_Return(runtime->NewNumber(iValue)); +} + +CJS_Return CJX_HostPseudoModel::documentCountInBatch( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_HostPseudoModel::print( + CJS_V8* runtime, + const std::vector>& params) { + if (!GetDocument()->GetScriptContext()->IsRunAtClient()) + return CJS_Return(true); + + if (params.size() != 8) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + uint32_t dwOptions = 0; + if (runtime->ToBoolean(params[0])) + dwOptions |= XFA_PRINTOPT_ShowDialog; + if (runtime->ToBoolean(params[3])) + dwOptions |= XFA_PRINTOPT_CanCancel; + if (runtime->ToBoolean(params[4])) + dwOptions |= XFA_PRINTOPT_ShrinkPage; + if (runtime->ToBoolean(params[5])) + dwOptions |= XFA_PRINTOPT_AsImage; + if (runtime->ToBoolean(params[6])) + dwOptions |= XFA_PRINTOPT_ReverseOrder; + if (runtime->ToBoolean(params[7])) + dwOptions |= XFA_PRINTOPT_PrintAnnot; + + int32_t nStartPage = runtime->ToInt32(params[1]); + int32_t nEndPage = runtime->ToInt32(params[2]); + + pNotify->GetDocEnvironment()->Print(pNotify->GetHDOC(), nStartPage, nEndPage, + dwOptions); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::importData( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::exportData( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + WideString filePath; + if (params.size() >= 1) + filePath = runtime->ToWideString(params[0]); + + bool XDP = true; + if (params.size() >= 2) + XDP = runtime->ToBoolean(params[1]); + + pNotify->GetDocEnvironment()->ExportData(pNotify->GetHDOC(), filePath, XDP); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::pageUp( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + int32_t nCurPage = pNotify->GetDocEnvironment()->GetCurrentPage(hDoc); + int32_t nNewPage = 0; + if (nCurPage <= 1) + return CJS_Return(true); + + nNewPage = nCurPage - 1; + pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage); + return CJS_Return(true); +} + +CJS_Return CJX_HostPseudoModel::pageDown( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_FFDoc* hDoc = pNotify->GetHDOC(); + int32_t nCurPage = pNotify->GetDocEnvironment()->GetCurrentPage(hDoc); + int32_t nPageCount = pNotify->GetDocEnvironment()->CountPages(hDoc); + if (!nPageCount || nCurPage == nPageCount) + return CJS_Return(true); + + int32_t nNewPage = 0; + if (nCurPage >= nPageCount) + nNewPage = nPageCount - 1; + else + nNewPage = nCurPage + 1; + + pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage); + return CJS_Return(true); +} diff --git a/fxjs/xfa/cjx_hostpseudomodel.h b/fxjs/xfa/cjx_hostpseudomodel.h new file mode 100644 index 0000000000000000000000000000000000000000..b4d6fe66e265563b24a8517da8381e61b8172f7f --- /dev/null +++ b/fxjs/xfa/cjx_hostpseudomodel.h @@ -0,0 +1,57 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_HOSTPSEUDOMODEL_H_ +#define FXJS_XFA_CJX_HOSTPSEUDOMODEL_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CFXJSE_Value; +class CScript_HostPseudoModel; + +class CJX_HostPseudoModel : public CJX_Object { + public: + explicit CJX_HostPseudoModel(CScript_HostPseudoModel* model); + ~CJX_HostPseudoModel() override; + + JS_METHOD(beep, CJX_HostPseudoModel); + JS_METHOD(documentCountInBatch, CJX_HostPseudoModel); + JS_METHOD(documentInBatch, CJX_HostPseudoModel); + JS_METHOD(exportData, CJX_HostPseudoModel); + JS_METHOD(getFocus, CJX_HostPseudoModel); + JS_METHOD(gotoURL, CJX_HostPseudoModel); + JS_METHOD(importData, CJX_HostPseudoModel); + JS_METHOD(messageBox, CJX_HostPseudoModel); + JS_METHOD(openList, CJX_HostPseudoModel); + JS_METHOD(pageDown, CJX_HostPseudoModel); + JS_METHOD(pageUp, CJX_HostPseudoModel); + JS_METHOD(print, CJX_HostPseudoModel); + JS_METHOD(resetData, CJX_HostPseudoModel); + JS_METHOD(response, CJX_HostPseudoModel); + JS_METHOD(setFocus, CJX_HostPseudoModel); + + JS_PROP(appType); + JS_PROP(calculationsEnabled); + JS_PROP(currentPage); + JS_PROP(language); + JS_PROP(numPages); + JS_PROP(platform); + JS_PROP(title); + JS_PROP(validationsEnabled); + JS_PROP(variation); + JS_PROP(version); + + // TODO(dsinclair): Remove when xfa_basic_data_element_script is removed. + // Doesn't exist in spec + JS_PROP(name); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_HOSTPSEUDOMODEL_H_ diff --git a/fxjs/xfa/cjx_image.cpp b/fxjs/xfa/cjx_image.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ea2131c8f8aa2fa12796d93daf3eb2ed748986b --- /dev/null +++ b/fxjs/xfa/cjx_image.cpp @@ -0,0 +1,61 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_image.h" + +#include "xfa/fxfa/parser/cxfa_image.h" + +CJX_Image::CJX_Image(CXFA_Image* node) : CJX_Node(node) {} + +CJX_Image::~CJX_Image() = default; + +void CJX_Image::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Image::contentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Image::transferEncoding(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Image::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue_Read(pValue, bSetting, eAttribute); +} + +void CJX_Image::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Image::aspect(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Image::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue_Read(pValue, bSetting, eAttribute); +} + +void CJX_Image::href(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_image.h b/fxjs/xfa/cjx_image.h new file mode 100644 index 0000000000000000000000000000000000000000..5cd120a674b6cc4e981f2e6ca52d5b1a6f3a0300 --- /dev/null +++ b/fxjs/xfa/cjx_image.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_IMAGE_H_ +#define FXJS_XFA_CJX_IMAGE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Image; + +class CJX_Image : public CJX_Node { + public: + explicit CJX_Image(CXFA_Image* node); + ~CJX_Image() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(aspect); + JS_PROP(contentType); + JS_PROP(href); + JS_PROP(transferEncoding); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_IMAGE_H_ diff --git a/fxjs/xfa/cjx_imageedit.cpp b/fxjs/xfa/cjx_imageedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a325eca6dc21c8dfd995f92c66c119cbad080228 --- /dev/null +++ b/fxjs/xfa/cjx_imageedit.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_imageedit.h" + +#include "xfa/fxfa/parser/cxfa_imageedit.h" + +CJX_ImageEdit::CJX_ImageEdit(CXFA_ImageEdit* node) : CJX_Node(node) {} + +CJX_ImageEdit::~CJX_ImageEdit() = default; + +void CJX_ImageEdit::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ImageEdit::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ImageEdit::data(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_imageedit.h b/fxjs/xfa/cjx_imageedit.h new file mode 100644 index 0000000000000000000000000000000000000000..ebf4fa3e8ca32919dc957d892d5403c28e41028f --- /dev/null +++ b/fxjs/xfa/cjx_imageedit.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_IMAGEEDIT_H_ +#define FXJS_XFA_CJX_IMAGEEDIT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_ImageEdit; + +class CJX_ImageEdit : public CJX_Node { + public: + explicit CJX_ImageEdit(CXFA_ImageEdit* node); + ~CJX_ImageEdit() override; + + JS_PROP(data); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_IMAGEEDIT_H_ diff --git a/fxjs/xfa/cjx_insert.cpp b/fxjs/xfa/cjx_insert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf2ae32489f861f77d43044580120f6757a045f9 --- /dev/null +++ b/fxjs/xfa/cjx_insert.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_insert.h" + +#include "xfa/fxfa/parser/cxfa_insert.h" + +CJX_Insert::CJX_Insert(CXFA_Insert* node) : CJX_TextNode(node) {} + +CJX_Insert::~CJX_Insert() = default; + +void CJX_Insert::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Insert::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_insert.h b/fxjs/xfa/cjx_insert.h new file mode 100644 index 0000000000000000000000000000000000000000..3b73df8f7d6bfd415f64cd1973a06d5f53de7190 --- /dev/null +++ b/fxjs/xfa/cjx_insert.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_INSERT_H_ +#define FXJS_XFA_CJX_INSERT_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Insert; + +class CJX_Insert : public CJX_TextNode { + public: + explicit CJX_Insert(CXFA_Insert* node); + ~CJX_Insert() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_INSERT_H_ diff --git a/fxjs/xfa/cjx_instancemanager.cpp b/fxjs/xfa/cjx_instancemanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..830541ed7c8b0f45bdf15d0d58e561049f64fdbb --- /dev/null +++ b/fxjs/xfa/cjx_instancemanager.cpp @@ -0,0 +1,327 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_instancemanager.h" + +#include +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_instancemanager.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_occur.h" + +const CJX_MethodSpec CJX_InstanceManager::MethodSpecs[] = { + {"addInstance", addInstance_static}, + {"insertInstance", insertInstance_static}, + {"moveInstance", moveInstance_static}, + {"removeInstance", removeInstance_static}, + {"setInstances", setInstances_static}}; + +CJX_InstanceManager::CJX_InstanceManager(CXFA_InstanceManager* mgr) + : CJX_Node(mgr) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_InstanceManager::~CJX_InstanceManager() {} + +int32_t CJX_InstanceManager::SetInstances(int32_t iDesired) { + CXFA_Occur* occur = GetXFANode()->GetOccurIfExists(); + int32_t iMin = occur ? occur->GetMin() : CXFA_Occur::kDefaultMin; + if (iDesired < iMin) { + ThrowTooManyOccurancesException(L"min"); + return 1; + } + + int32_t iMax = occur ? occur->GetMax() : CXFA_Occur::kDefaultMax; + if (iMax >= 0 && iDesired > iMax) { + ThrowTooManyOccurancesException(L"max"); + return 2; + } + + int32_t iCount = GetXFANode()->GetCount(); + if (iDesired == iCount) + return 0; + + if (iDesired < iCount) { + WideString wsInstManagerName = GetCData(XFA_Attribute::Name); + WideString wsInstanceName = WideString( + wsInstManagerName.IsEmpty() + ? wsInstManagerName + : wsInstManagerName.Right(wsInstManagerName.GetLength() - 1)); + uint32_t dInstanceNameHash = + FX_HashCode_GetW(wsInstanceName.AsStringView(), false); + CXFA_Node* pPrevSibling = iDesired == 0 + ? GetXFANode() + : GetXFANode()->GetItemIfExists(iDesired - 1); + if (!pPrevSibling) { + // TODO(dsinclair): Better error? + ThrowIndexOutOfBoundsException(); + return 0; + } + + while (iCount > iDesired) { + CXFA_Node* pRemoveInstance = pPrevSibling->GetNextSibling(); + if (pRemoveInstance->GetElementType() != XFA_Element::Subform && + pRemoveInstance->GetElementType() != XFA_Element::SubformSet) { + continue; + } + if (pRemoveInstance->GetElementType() == XFA_Element::InstanceManager) { + NOTREACHED(); + break; + } + if (pRemoveInstance->GetNameHash() == dInstanceNameHash) { + GetXFANode()->RemoveItem(pRemoveInstance, true); + iCount--; + } + } + } else { + while (iCount < iDesired) { + CXFA_Node* pNewInstance = GetXFANode()->CreateInstanceIfPossible(true); + if (!pNewInstance) + return 0; + + GetXFANode()->InsertItem(pNewInstance, iCount, iCount, false); + ++iCount; + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return 0; + + pNotify->RunNodeInitialize(pNewInstance); + } + } + + CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); + if (pLayoutPro) { + pLayoutPro->AddChangedContainer( + ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form))); + } + return 0; +} + +int32_t CJX_InstanceManager::MoveInstance(int32_t iTo, int32_t iFrom) { + int32_t iCount = GetXFANode()->GetCount(); + if (iFrom > iCount || iTo > iCount - 1) { + ThrowIndexOutOfBoundsException(); + return 1; + } + if (iFrom < 0 || iTo < 0 || iFrom == iTo) + return 0; + + CXFA_Node* pMoveInstance = GetXFANode()->GetItemIfExists(iFrom); + if (!pMoveInstance) { + ThrowIndexOutOfBoundsException(); + return 1; + } + + GetXFANode()->RemoveItem(pMoveInstance, false); + GetXFANode()->InsertItem(pMoveInstance, iTo, iCount - 1, true); + CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); + if (pLayoutPro) { + pLayoutPro->AddChangedContainer( + ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form))); + } + return 0; +} + +CJS_Return CJX_InstanceManager::moveInstance( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t iFrom = runtime->ToInt32(params[0]); + int32_t iTo = runtime->ToInt32(params[1]); + MoveInstance(iTo, iFrom); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_Node* pToInstance = GetXFANode()->GetItemIfExists(iTo); + if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform) + pNotify->RunSubformIndexChange(pToInstance); + + CXFA_Node* pFromInstance = GetXFANode()->GetItemIfExists(iFrom); + if (pFromInstance && + pFromInstance->GetElementType() == XFA_Element::Subform) { + pNotify->RunSubformIndexChange(pFromInstance); + } + + return CJS_Return(true); +} + +CJS_Return CJX_InstanceManager::removeInstance( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t iIndex = runtime->ToInt32(params[0]); + int32_t iCount = GetXFANode()->GetCount(); + if (iIndex < 0 || iIndex >= iCount) + return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError)); + + CXFA_Occur* occur = GetXFANode()->GetOccurIfExists(); + int32_t iMin = occur ? occur->GetMin() : CXFA_Occur::kDefaultMin; + if (iCount - 1 < iMin) + return CJS_Return(JSGetStringFromID(JSMessage::kTooManyOccurances)); + + CXFA_Node* pRemoveInstance = GetXFANode()->GetItemIfExists(iIndex); + if (!pRemoveInstance) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + GetXFANode()->RemoveItem(pRemoveInstance, true); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) { + for (int32_t i = iIndex; i < iCount - 1; i++) { + CXFA_Node* pSubformInstance = GetXFANode()->GetItemIfExists(i); + if (pSubformInstance && + pSubformInstance->GetElementType() == XFA_Element::Subform) { + pNotify->RunSubformIndexChange(pSubformInstance); + } + } + } + CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); + if (pLayoutPro) { + pLayoutPro->AddChangedContainer( + ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form))); + } + return CJS_Return(true); +} + +CJS_Return CJX_InstanceManager::setInstances( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + SetInstances(runtime->ToInt32(params[0])); + return CJS_Return(true); +} + +CJS_Return CJX_InstanceManager::addInstance( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty() && params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + bool fFlags = true; + if (params.size() == 1) + fFlags = runtime->ToBoolean(params[0]); + + int32_t iCount = GetXFANode()->GetCount(); + CXFA_Occur* occur = GetXFANode()->GetOccurIfExists(); + int32_t iMax = occur ? occur->GetMax() : CXFA_Occur::kDefaultMax; + if (iMax >= 0 && iCount >= iMax) + return CJS_Return(JSGetStringFromID(JSMessage::kTooManyOccurances)); + + CXFA_Node* pNewInstance = GetXFANode()->CreateInstanceIfPossible(fFlags); + if (!pNewInstance) + return CJS_Return(runtime->NewNull()); + + GetXFANode()->InsertItem(pNewInstance, iCount, iCount, false); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) { + pNotify->RunNodeInitialize(pNewInstance); + + CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); + if (pLayoutPro) { + pLayoutPro->AddChangedContainer( + ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form))); + } + } + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_InstanceManager::insertInstance( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1 && params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t iIndex = runtime->ToInt32(params[0]); + bool bBind = false; + if (params.size() == 2) + bBind = runtime->ToBoolean(params[1]); + + int32_t iCount = GetXFANode()->GetCount(); + if (iIndex < 0 || iIndex > iCount) + return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError)); + + CXFA_Occur* occur = GetXFANode()->GetOccurIfExists(); + int32_t iMax = occur ? occur->GetMax() : CXFA_Occur::kDefaultMax; + if (iMax >= 0 && iCount >= iMax) + return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError)); + + CXFA_Node* pNewInstance = GetXFANode()->CreateInstanceIfPossible(bBind); + if (!pNewInstance) + return CJS_Return(runtime->NewNull()); + + GetXFANode()->InsertItem(pNewInstance, iIndex, iCount, true); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) { + pNotify->RunNodeInitialize(pNewInstance); + CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); + if (pLayoutPro) { + pLayoutPro->AddChangedContainer( + ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form))); + } + } + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +void CJX_InstanceManager::max(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + CXFA_Occur* occur = GetXFANode()->GetOccurIfExists(); + pValue->SetInteger(occur ? occur->GetMax() : CXFA_Occur::kDefaultMax); +} + +void CJX_InstanceManager::min(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + CXFA_Occur* occur = GetXFANode()->GetOccurIfExists(); + pValue->SetInteger(occur ? occur->GetMin() : CXFA_Occur::kDefaultMin); +} + +void CJX_InstanceManager::count(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + pValue->SetInteger(GetXFANode()->GetCount()); + return; + } + SetInstances(pValue->ToInteger()); +} diff --git a/fxjs/xfa/cjx_instancemanager.h b/fxjs/xfa/cjx_instancemanager.h new file mode 100644 index 0000000000000000000000000000000000000000..74efad5ba9014ca3639cfb7da34faa7ba24ea2b1 --- /dev/null +++ b/fxjs/xfa/cjx_instancemanager.h @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_INSTANCEMANAGER_H_ +#define FXJS_XFA_CJX_INSTANCEMANAGER_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_InstanceManager; + +class CJX_InstanceManager : public CJX_Node { + public: + explicit CJX_InstanceManager(CXFA_InstanceManager* mgr); + ~CJX_InstanceManager() override; + + JS_METHOD(addInstance, CJX_InstanceManager); + JS_METHOD(insertInstance, CJX_InstanceManager); + JS_METHOD(moveInstance, CJX_InstanceManager); + JS_METHOD(removeInstance, CJX_InstanceManager); + JS_METHOD(setInstances, CJX_InstanceManager); + + JS_PROP(count); + JS_PROP(max); + JS_PROP(min); + + int32_t MoveInstance(int32_t iTo, int32_t iFrom); + + private: + int32_t SetInstances(int32_t iDesired); + + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_INSTANCEMANAGER_H_ diff --git a/fxjs/xfa/cjx_integer.cpp b/fxjs/xfa/cjx_integer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1840dd36ab712955a67ca115461007faef94a54 --- /dev/null +++ b/fxjs/xfa/cjx_integer.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_integer.h" + +#include "xfa/fxfa/parser/cxfa_integer.h" + +CJX_Integer::CJX_Integer(CXFA_Integer* node) : CJX_Content(node) {} + +CJX_Integer::~CJX_Integer() = default; + +void CJX_Integer::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Integer::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Integer::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Integer::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_integer.h b/fxjs/xfa/cjx_integer.h new file mode 100644 index 0000000000000000000000000000000000000000..90daabfc6f417cff8e5c4b45b21470461b8a1819 --- /dev/null +++ b/fxjs/xfa/cjx_integer.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_INTEGER_H_ +#define FXJS_XFA_CJX_INTEGER_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Integer; + +class CJX_Integer : public CJX_Content { + public: + explicit CJX_Integer(CXFA_Integer* node); + ~CJX_Integer() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_INTEGER_H_ diff --git a/fxjs/xfa/cjx_issuers.cpp b/fxjs/xfa/cjx_issuers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5cd381d6405ad3205190f5cc1b274d1ebeb90d50 --- /dev/null +++ b/fxjs/xfa/cjx_issuers.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_issuers.h" + +#include "xfa/fxfa/parser/cxfa_issuers.h" + +CJX_Issuers::CJX_Issuers(CXFA_Issuers* node) : CJX_Node(node) {} + +CJX_Issuers::~CJX_Issuers() = default; + +void CJX_Issuers::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Issuers::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Issuers::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_issuers.h b/fxjs/xfa/cjx_issuers.h new file mode 100644 index 0000000000000000000000000000000000000000..5d76e72b93fd46805f0882658d946f44856b04aa --- /dev/null +++ b/fxjs/xfa/cjx_issuers.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ISSUERS_H_ +#define FXJS_XFA_CJX_ISSUERS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Issuers; + +class CJX_Issuers : public CJX_Node { + public: + explicit CJX_Issuers(CXFA_Issuers* node); + ~CJX_Issuers() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ISSUERS_H_ diff --git a/fxjs/xfa/cjx_items.cpp b/fxjs/xfa/cjx_items.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4afdd04f47538e05211d206646de0bd717942b7 --- /dev/null +++ b/fxjs/xfa/cjx_items.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_items.h" + +#include "xfa/fxfa/parser/cxfa_items.h" + +CJX_Items::CJX_Items(CXFA_Items* node) : CJX_Node(node) {} + +CJX_Items::~CJX_Items() = default; + +void CJX_Items::ref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Items::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Items::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Items::save(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Items::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_items.h b/fxjs/xfa/cjx_items.h new file mode 100644 index 0000000000000000000000000000000000000000..94f2b4374d7d940b6905eeb48dc373608fecd3fb --- /dev/null +++ b/fxjs/xfa/cjx_items.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ITEMS_H_ +#define FXJS_XFA_CJX_ITEMS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Items; + +class CJX_Items : public CJX_Node { + public: + explicit CJX_Items(CXFA_Items* node); + ~CJX_Items() override; + + JS_PROP(presence); + JS_PROP(ref); + JS_PROP(save); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ITEMS_H_ diff --git a/fxjs/xfa/cjx_keep.cpp b/fxjs/xfa/cjx_keep.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25238e3c5898841f694b17185a977253a0ae39bb --- /dev/null +++ b/fxjs/xfa/cjx_keep.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_keep.h" + +#include "xfa/fxfa/parser/cxfa_keep.h" + +CJX_Keep::CJX_Keep(CXFA_Keep* node) : CJX_Node(node) {} + +CJX_Keep::~CJX_Keep() = default; + +void CJX_Keep::next(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Keep::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Keep::previous(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Keep::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Keep::intact(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_keep.h b/fxjs/xfa/cjx_keep.h new file mode 100644 index 0000000000000000000000000000000000000000..fa8a1119f282d6c85a70ea28849045825d468194 --- /dev/null +++ b/fxjs/xfa/cjx_keep.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_KEEP_H_ +#define FXJS_XFA_CJX_KEEP_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Keep; + +class CJX_Keep : public CJX_Node { + public: + explicit CJX_Keep(CXFA_Keep* node); + ~CJX_Keep() override; + + JS_PROP(intact); + JS_PROP(next); + JS_PROP(previous); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_KEEP_H_ diff --git a/fxjs/xfa/cjx_keyusage.cpp b/fxjs/xfa/cjx_keyusage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99947e9e7d7976e63792e0c279107d77a006e5c7 --- /dev/null +++ b/fxjs/xfa/cjx_keyusage.cpp @@ -0,0 +1,85 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_keyusage.h" + +#include "xfa/fxfa/parser/cxfa_keyusage.h" + +CJX_KeyUsage::CJX_KeyUsage(CXFA_KeyUsage* node) : CJX_Node(node) {} + +CJX_KeyUsage::~CJX_KeyUsage() = default; + +void CJX_KeyUsage::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::nonRepudiation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::encipherOnly(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::digitalSignature(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::crlSign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::keyAgreement(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::keyEncipherment(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::dataEncipherment(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::keyCertSign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_KeyUsage::decipherOnly(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_keyusage.h b/fxjs/xfa/cjx_keyusage.h new file mode 100644 index 0000000000000000000000000000000000000000..3ff546de181cbd79eacc4a5f5f6ad9858768fc1c --- /dev/null +++ b/fxjs/xfa/cjx_keyusage.h @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_KEYUSAGE_H_ +#define FXJS_XFA_CJX_KEYUSAGE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_KeyUsage; + +class CJX_KeyUsage : public CJX_Node { + public: + explicit CJX_KeyUsage(CXFA_KeyUsage* node); + ~CJX_KeyUsage() override; + + JS_PROP(crlSign); + JS_PROP(dataEncipherment); + JS_PROP(decipherOnly); + JS_PROP(digitalSignature); + JS_PROP(encipherOnly); + JS_PROP(keyAgreement); + JS_PROP(keyCertSign); + JS_PROP(keyEncipherment); + JS_PROP(nonRepudiation); + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_KEYUSAGE_H_ diff --git a/fxjs/xfa/cjx_layoutpseudomodel.cpp b/fxjs/xfa/cjx_layoutpseudomodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..384bd09d63f1843ade579d7dba2f55e4d7c5d125 --- /dev/null +++ b/fxjs/xfa/cjx_layoutpseudomodel.cpp @@ -0,0 +1,482 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_layoutpseudomodel.h" + +#include + +#include "core/fxcrt/fx_coordinates.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cscript_layoutpseudomodel.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" +#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_form.h" +#include "xfa/fxfa/parser/cxfa_layoutitem.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_contentlayoutitem.h" + +const CJX_MethodSpec CJX_LayoutPseudoModel::MethodSpecs[] = { + {"absPage", absPage_static}, + {"absPageCount", absPageCount_static}, + {"absPageCountInBatch", absPageCountInBatch_static}, + {"absPageInBatch", absPageInBatch_static}, + {"absPageSpan", absPageSpan_static}, + {"h", h_static}, + {"page", page_static}, + {"pageContent", pageContent_static}, + {"pageCount", pageCount_static}, + {"pageSpan", pageSpan_static}, + {"relayout", relayout_static}, + {"relayoutPageArea", relayoutPageArea_static}, + {"sheet", sheet_static}, + {"sheetCount", sheetCount_static}, + {"sheetCountInBatch", sheetCountInBatch_static}, + {"sheetInBatch", sheetInBatch_static}, + {"w", w_static}, + {"x", x_static}, + {"y", y_static}}; + +CJX_LayoutPseudoModel::CJX_LayoutPseudoModel(CScript_LayoutPseudoModel* model) + : CJX_Object(model) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_LayoutPseudoModel::~CJX_LayoutPseudoModel() {} + +void CJX_LayoutPseudoModel::ready(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + if (bSetting) { + ThrowException(L"Unable to set ready value."); + return; + } + + int32_t iStatus = pNotify->GetLayoutStatus(); + pValue->SetBoolean(iStatus >= 2); +} + +CJS_Return CJX_LayoutPseudoModel::HWXY( + CJS_V8* runtime, + const std::vector>& params, + XFA_LAYOUTMODEL_HWXY layoutModel) { + if (params.empty() || params.size() > 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Node* pNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pNode) + return CJS_Return(true); + + WideString unit(L"pt"); + if (params.size() >= 2) { + WideString tmp_unit = runtime->ToWideString(params[1]); + if (!tmp_unit.IsEmpty()) + unit = tmp_unit; + } + int32_t iIndex = params.size() >= 3 ? runtime->ToInt32(params[2]) : 0; + + CXFA_LayoutProcessor* pDocLayout = GetDocument()->GetDocLayout(); + if (!pDocLayout) + return CJS_Return(true); + + CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); + if (!pLayoutItem) + return CJS_Return(true); + + while (iIndex > 0 && pLayoutItem) { + pLayoutItem = pLayoutItem->GetNext(); + --iIndex; + } + + if (!pLayoutItem) + return CJS_Return(runtime->NewNumber(0.0)); + + CXFA_Measurement measure; + CFX_RectF rtRect = pLayoutItem->GetRect(true); + switch (layoutModel) { + case XFA_LAYOUTMODEL_H: + measure.Set(rtRect.height, XFA_Unit::Pt); + break; + case XFA_LAYOUTMODEL_W: + measure.Set(rtRect.width, XFA_Unit::Pt); + break; + case XFA_LAYOUTMODEL_X: + measure.Set(rtRect.left, XFA_Unit::Pt); + break; + case XFA_LAYOUTMODEL_Y: + measure.Set(rtRect.top, XFA_Unit::Pt); + break; + } + + float fValue = + measure.ToUnit(CXFA_Measurement::GetUnitFromString(unit.AsStringView())); + return CJS_Return(runtime->NewNumber(FXSYS_round(fValue * 1000) / 1000.0f)); +} + +CJS_Return CJX_LayoutPseudoModel::h( + CJS_V8* runtime, + const std::vector>& params) { + return HWXY(runtime, params, XFA_LAYOUTMODEL_H); +} + +CJS_Return CJX_LayoutPseudoModel::w( + CJS_V8* runtime, + const std::vector>& params) { + return HWXY(runtime, params, XFA_LAYOUTMODEL_W); +} + +CJS_Return CJX_LayoutPseudoModel::x( + CJS_V8* runtime, + const std::vector>& params) { + return HWXY(runtime, params, XFA_LAYOUTMODEL_X); +} + +CJS_Return CJX_LayoutPseudoModel::y( + CJS_V8* runtime, + const std::vector>& params) { + return HWXY(runtime, params, XFA_LAYOUTMODEL_Y); +} + +CJS_Return CJX_LayoutPseudoModel::NumberedPageCount(CJS_V8* runtime, + bool bNumbered) { + CXFA_LayoutProcessor* pDocLayout = GetDocument()->GetDocLayout(); + if (!pDocLayout) + return CJS_Return(true); + + int32_t iPageCount = 0; + int32_t iPageNum = pDocLayout->CountPages(); + if (bNumbered) { + for (int32_t i = 0; i < iPageNum; i++) { + CXFA_ContainerLayoutItem* pLayoutPage = pDocLayout->GetPage(i); + if (!pLayoutPage) + continue; + + CXFA_Node* pMasterPage = pLayoutPage->GetMasterPage(); + if (pMasterPage->JSObject()->GetInteger(XFA_Attribute::Numbered)) + iPageCount++; + } + } else { + iPageCount = iPageNum; + } + return CJS_Return(runtime->NewNumber(iPageCount)); +} + +CJS_Return CJX_LayoutPseudoModel::pageCount( + CJS_V8* runtime, + const std::vector>& params) { + return NumberedPageCount(runtime, true); +} + +CJS_Return CJX_LayoutPseudoModel::pageSpan( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Node* pNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pNode) + return CJS_Return(true); + + CXFA_LayoutProcessor* pDocLayout = GetDocument()->GetDocLayout(); + if (!pDocLayout) + return CJS_Return(true); + + CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); + if (!pLayoutItem) + return CJS_Return(runtime->NewNumber(-1)); + + int32_t iLast = pLayoutItem->GetLast()->GetPage()->GetPageIndex(); + int32_t iFirst = pLayoutItem->GetFirst()->GetPage()->GetPageIndex(); + int32_t iPageSpan = iLast - iFirst + 1; + return CJS_Return(runtime->NewNumber(iPageSpan)); +} + +CJS_Return CJX_LayoutPseudoModel::page( + CJS_V8* runtime, + const std::vector>& params) { + return PageInternals(runtime, params, false); +} + +std::vector CJX_LayoutPseudoModel::GetObjArray( + CXFA_LayoutProcessor* pDocLayout, + int32_t iPageNo, + const WideString& wsType, + bool bOnPageArea) { + CXFA_ContainerLayoutItem* pLayoutPage = pDocLayout->GetPage(iPageNo); + if (!pLayoutPage) + return std::vector(); + + std::vector retArray; + if (wsType == L"pageArea") { + if (pLayoutPage->m_pFormNode) + retArray.push_back(pLayoutPage->m_pFormNode); + return retArray; + } + if (wsType == L"contentArea") { + for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; + pItem = pItem->m_pNextSibling) { + if (pItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) + retArray.push_back(pItem->m_pFormNode); + } + return retArray; + } + std::set formItems; + if (wsType.IsEmpty()) { + if (pLayoutPage->m_pFormNode) + retArray.push_back(pLayoutPage->m_pFormNode); + + for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; + pItem = pItem->m_pNextSibling) { + if (pItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { + retArray.push_back(pItem->m_pFormNode); + if (!bOnPageArea) { + CXFA_NodeIteratorTemplate + iterator(static_cast(pItem->m_pFirstChild)); + for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); + pItemChild; pItemChild = iterator.MoveToNext()) { + if (!pItemChild->IsContentLayoutItem()) { + continue; + } + XFA_Element eType = pItemChild->m_pFormNode->GetElementType(); + if (eType != XFA_Element::Field && eType != XFA_Element::Draw && + eType != XFA_Element::Subform && eType != XFA_Element::Area) { + continue; + } + if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) + continue; + + formItems.insert(pItemChild->m_pFormNode); + retArray.push_back(pItemChild->m_pFormNode); + } + } + } else { + if (bOnPageArea) { + CXFA_NodeIteratorTemplate + iterator(static_cast(pItem)); + for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); + pItemChild; pItemChild = iterator.MoveToNext()) { + if (!pItemChild->IsContentLayoutItem()) { + continue; + } + XFA_Element eType = pItemChild->m_pFormNode->GetElementType(); + if (eType != XFA_Element::Field && eType != XFA_Element::Draw && + eType != XFA_Element::Subform && eType != XFA_Element::Area) { + continue; + } + if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) + continue; + formItems.insert(pItemChild->m_pFormNode); + retArray.push_back(pItemChild->m_pFormNode); + } + } + } + } + return retArray; + } + + XFA_Element eType = XFA_Element::Unknown; + if (wsType == L"field") + eType = XFA_Element::Field; + else if (wsType == L"draw") + eType = XFA_Element::Draw; + else if (wsType == L"subform") + eType = XFA_Element::Subform; + else if (wsType == L"area") + eType = XFA_Element::Area; + + if (eType != XFA_Element::Unknown) { + for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; + pItem = pItem->m_pNextSibling) { + if (pItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { + if (!bOnPageArea) { + CXFA_NodeIteratorTemplate + iterator(static_cast(pItem->m_pFirstChild)); + for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); + pItemChild; pItemChild = iterator.MoveToNext()) { + if (!pItemChild->IsContentLayoutItem()) + continue; + if (pItemChild->m_pFormNode->GetElementType() != eType) + continue; + if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) + continue; + + formItems.insert(pItemChild->m_pFormNode); + retArray.push_back(pItemChild->m_pFormNode); + } + } + } else { + if (bOnPageArea) { + CXFA_NodeIteratorTemplate + iterator(static_cast(pItem)); + for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); + pItemChild; pItemChild = iterator.MoveToNext()) { + if (!pItemChild->IsContentLayoutItem()) + continue; + if (pItemChild->m_pFormNode->GetElementType() != eType) + continue; + if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) + continue; + + formItems.insert(pItemChild->m_pFormNode); + retArray.push_back(pItemChild->m_pFormNode); + } + } + } + } + } + return retArray; +} + +CJS_Return CJX_LayoutPseudoModel::pageContent( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t iIndex = 0; + if (params.size() >= 1) + iIndex = runtime->ToInt32(params[0]); + + WideString wsType; + if (params.size() >= 2) + wsType = runtime->ToWideString(params[1]); + + bool bOnPageArea = false; + if (params.size() >= 3) + bOnPageArea = runtime->ToBoolean(params[2]); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(true); + + CXFA_LayoutProcessor* pDocLayout = GetDocument()->GetDocLayout(); + if (!pDocLayout) + return CJS_Return(true); + + auto pArrayNodeList = pdfium::MakeUnique(GetDocument()); + pArrayNodeList->SetArrayNodeList( + GetObjArray(pDocLayout, iIndex, wsType, bOnPageArea)); + + // TODO(dsinclair): Who owns the array once we release it? Won't this leak? + return CJS_Return(runtime->NewXFAObject( + pArrayNodeList.release(), + GetDocument()->GetScriptContext()->GetJseNormalClass()->GetTemplate())); +} + +CJS_Return CJX_LayoutPseudoModel::absPageCount( + CJS_V8* runtime, + const std::vector>& params) { + return NumberedPageCount(runtime, false); +} + +CJS_Return CJX_LayoutPseudoModel::absPageCountInBatch( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_LayoutPseudoModel::sheetCountInBatch( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_LayoutPseudoModel::relayout( + CJS_V8* runtime, + const std::vector>& params) { + CXFA_Node* pRootNode = GetDocument()->GetRoot(); + CXFA_Form* pFormRoot = + pRootNode->GetFirstChildByClass(XFA_Element::Form); + CXFA_Node* pContentRootNode = pFormRoot->GetFirstChild(); + CXFA_LayoutProcessor* pLayoutProcessor = GetDocument()->GetLayoutProcessor(); + if (pContentRootNode) + pLayoutProcessor->AddChangedContainer(pContentRootNode); + + pLayoutProcessor->SetForceReLayout(true); + return CJS_Return(true); +} + +CJS_Return CJX_LayoutPseudoModel::absPageSpan( + CJS_V8* runtime, + const std::vector>& params) { + return pageSpan(runtime, params); +} + +CJS_Return CJX_LayoutPseudoModel::absPageInBatch( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_LayoutPseudoModel::sheetInBatch( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_LayoutPseudoModel::sheet( + CJS_V8* runtime, + const std::vector>& params) { + return PageInternals(runtime, params, true); +} + +CJS_Return CJX_LayoutPseudoModel::relayoutPageArea( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_LayoutPseudoModel::sheetCount( + CJS_V8* runtime, + const std::vector>& params) { + return NumberedPageCount(runtime, false); +} + +CJS_Return CJX_LayoutPseudoModel::absPage( + CJS_V8* runtime, + const std::vector>& params) { + return PageInternals(runtime, params, true); +} + +CJS_Return CJX_LayoutPseudoModel::PageInternals( + CJS_V8* runtime, + const std::vector>& params, + bool bAbsPage) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Node* pNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pNode) + return CJS_Return(runtime->NewNumber(0)); + + CXFA_LayoutProcessor* pDocLayout = GetDocument()->GetDocLayout(); + if (!pDocLayout) + return CJS_Return(true); + + CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); + if (!pLayoutItem) + return CJS_Return(runtime->NewNumber(-1)); + + int32_t iPage = pLayoutItem->GetFirst()->GetPage()->GetPageIndex(); + return CJS_Return(runtime->NewNumber(bAbsPage ? iPage : iPage + 1)); +} diff --git a/fxjs/xfa/cjx_layoutpseudomodel.h b/fxjs/xfa/cjx_layoutpseudomodel.h new file mode 100644 index 0000000000000000000000000000000000000000..6dbef6038a53fe996add884ac213329e2d2a9d7c --- /dev/null +++ b/fxjs/xfa/cjx_layoutpseudomodel.h @@ -0,0 +1,70 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_LAYOUTPSEUDOMODEL_H_ +#define FXJS_XFA_CJX_LAYOUTPSEUDOMODEL_H_ + +#include + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +enum XFA_LAYOUTMODEL_HWXY { + XFA_LAYOUTMODEL_H, + XFA_LAYOUTMODEL_W, + XFA_LAYOUTMODEL_X, + XFA_LAYOUTMODEL_Y +}; + +class CFXJSE_Value; +class CScript_LayoutPseudoModel; +class CXFA_LayoutProcessor; +class CXFA_Node; + +class CJX_LayoutPseudoModel : public CJX_Object { + public: + explicit CJX_LayoutPseudoModel(CScript_LayoutPseudoModel* model); + ~CJX_LayoutPseudoModel() override; + + JS_METHOD(absPage, CJX_LayoutPseudoModel); + JS_METHOD(absPageCount, CJX_LayoutPseudoModel); + JS_METHOD(absPageCountInBatch, CJX_LayoutPseudoModel); + JS_METHOD(absPageInBatch, CJX_LayoutPseudoModel); + JS_METHOD(absPageSpan, CJX_LayoutPseudoModel); + JS_METHOD(h, CJX_LayoutPseudoModel); + JS_METHOD(page, CJX_LayoutPseudoModel); + JS_METHOD(pageContent, CJX_LayoutPseudoModel); + JS_METHOD(pageCount, CJX_LayoutPseudoModel); + JS_METHOD(pageSpan, CJX_LayoutPseudoModel); + JS_METHOD(relayout, CJX_LayoutPseudoModel); + JS_METHOD(relayoutPageArea, CJX_LayoutPseudoModel); + JS_METHOD(sheet, CJX_LayoutPseudoModel); + JS_METHOD(sheetCount, CJX_LayoutPseudoModel); + JS_METHOD(sheetCountInBatch, CJX_LayoutPseudoModel); + JS_METHOD(sheetInBatch, CJX_LayoutPseudoModel); + JS_METHOD(w, CJX_LayoutPseudoModel); + JS_METHOD(x, CJX_LayoutPseudoModel); + JS_METHOD(y, CJX_LayoutPseudoModel); + + JS_PROP(ready); + + private: + CJS_Return NumberedPageCount(CJS_V8* runtime, bool bNumbered); + CJS_Return HWXY(CJS_V8* runtime, + const std::vector>& params, + XFA_LAYOUTMODEL_HWXY layoutModel); + std::vector GetObjArray(CXFA_LayoutProcessor* pDocLayout, + int32_t iPageNo, + const WideString& wsType, + bool bOnPageArea); + CJS_Return PageInternals(CJS_V8* runtime, + const std::vector>& params, + bool bAbsPage); + + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_LAYOUTPSEUDOMODEL_H_ diff --git a/fxjs/xfa/cjx_line.cpp b/fxjs/xfa/cjx_line.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48569390a48ae2e97f77452d63aa692ac9a81851 --- /dev/null +++ b/fxjs/xfa/cjx_line.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_line.h" + +#include "xfa/fxfa/parser/cxfa_line.h" + +CJX_Line::CJX_Line(CXFA_Line* node) : CJX_Node(node) {} + +CJX_Line::~CJX_Line() = default; + +void CJX_Line::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Line::slope(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Line::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Line::hand(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_line.h b/fxjs/xfa/cjx_line.h new file mode 100644 index 0000000000000000000000000000000000000000..7041c1259cbd6330ea1cd16f5837e3cbfa6779b2 --- /dev/null +++ b/fxjs/xfa/cjx_line.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_LINE_H_ +#define FXJS_XFA_CJX_LINE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Line; + +class CJX_Line : public CJX_Node { + public: + explicit CJX_Line(CXFA_Line* node); + ~CJX_Line() override; + + JS_PROP(hand); + JS_PROP(slope); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_LINE_H_ diff --git a/fxjs/xfa/cjx_linear.cpp b/fxjs/xfa/cjx_linear.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c226990540d98ac6566e7b1536a4c2c2ae8dac1 --- /dev/null +++ b/fxjs/xfa/cjx_linear.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_linear.h" + +#include "xfa/fxfa/parser/cxfa_linear.h" + +CJX_Linear::CJX_Linear(CXFA_Linear* node) : CJX_Node(node) {} + +CJX_Linear::~CJX_Linear() = default; + +void CJX_Linear::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Linear::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Linear::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_linear.h b/fxjs/xfa/cjx_linear.h new file mode 100644 index 0000000000000000000000000000000000000000..30a54bff47c697739a459a78c0a1df8d5d2938d6 --- /dev/null +++ b/fxjs/xfa/cjx_linear.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_LINEAR_H_ +#define FXJS_XFA_CJX_LINEAR_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Linear; + +class CJX_Linear : public CJX_Node { + public: + explicit CJX_Linear(CXFA_Linear* node); + ~CJX_Linear() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_LINEAR_H_ diff --git a/fxjs/xfa/cjx_list.cpp b/fxjs/xfa/cjx_list.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cbd32d35264d5b830c159939101ba758ca4bace --- /dev/null +++ b/fxjs/xfa/cjx_list.cpp @@ -0,0 +1,98 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_list.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "third_party/base/numerics/safe_conversions.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_list.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +const CJX_MethodSpec CJX_List::MethodSpecs[] = {{"append", append_static}, + {"insert", insert_static}, + {"item", item_static}, + {"remove", remove_static}}; + +CJX_List::CJX_List(CXFA_List* list) : CJX_Object(list) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_List::~CJX_List() {} + +CXFA_List* CJX_List::GetXFAList() { + return static_cast(GetXFAObject()); +} + +CJS_Return CJX_List::append(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + auto* pNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pNode) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + GetXFAList()->Append(pNode); + return CJS_Return(true); +} + +CJS_Return CJX_List::insert(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + auto* pNewNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pNewNode) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + auto* pBeforeNode = ToNode(runtime->ToXFAObject(params[1])); + GetXFAList()->Insert(pNewNode, pBeforeNode); + return CJS_Return(true); +} + +CJS_Return CJX_List::remove(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + auto* pNode = ToNode(runtime->ToXFAObject(params[0])); + if (!pNode) + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + GetXFAList()->Remove(pNode); + return CJS_Return(true); +} + +CJS_Return CJX_List::item(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + int32_t index = runtime->ToInt32(params[0]); + size_t cast_index = static_cast(index); + if (index < 0 || cast_index >= GetXFAList()->GetLength()) + return CJS_Return(JSGetStringFromID(JSMessage::kInvalidInputError)); + + return CJS_Return(runtime->NewXFAObject( + GetXFAList()->Item(cast_index), + GetDocument()->GetScriptContext()->GetJseNormalClass()->GetTemplate())); +} + +void CJX_List::length(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetInteger( + pdfium::base::checked_cast(GetXFAList()->GetLength())); +} diff --git a/fxjs/xfa/cjx_list.h b/fxjs/xfa/cjx_list.h new file mode 100644 index 0000000000000000000000000000000000000000..83801b7e088dc9bb567446c000ec0d53043d777f --- /dev/null +++ b/fxjs/xfa/cjx_list.h @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_LIST_H_ +#define FXJS_XFA_CJX_LIST_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CXFA_List; + +class CJX_List : public CJX_Object { + public: + explicit CJX_List(CXFA_List* list); + ~CJX_List() override; + + JS_METHOD(append, CJX_List); + JS_METHOD(insert, CJX_List); + JS_METHOD(item, CJX_List); + JS_METHOD(remove, CJX_List); + + JS_PROP(length); + + private: + CXFA_List* GetXFAList(); + + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_LIST_H_ diff --git a/fxjs/xfa/cjx_logpseudomodel.cpp b/fxjs/xfa/cjx_logpseudomodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..810ddfa008655b0f7489534663121473204cc567 --- /dev/null +++ b/fxjs/xfa/cjx_logpseudomodel.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_logpseudomodel.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cscript_logpseudomodel.h" + +const CJX_MethodSpec CJX_LogPseudoModel::MethodSpecs[] = { + {"message", message_static}, + {"traceEnabled", traceEnabled_static}, + {"traceActivate", traceActivate_static}, + {"traceDeactivate", traceDeactivate_static}, + {"trace", trace_static}}; + +CJX_LogPseudoModel::CJX_LogPseudoModel(CScript_LogPseudoModel* model) + : CJX_Object(model) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_LogPseudoModel::~CJX_LogPseudoModel() {} + +CJS_Return CJX_LogPseudoModel::message( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_LogPseudoModel::traceEnabled( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_LogPseudoModel::traceActivate( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_LogPseudoModel::traceDeactivate( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_LogPseudoModel::trace( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} diff --git a/fxjs/xfa/cjx_logpseudomodel.h b/fxjs/xfa/cjx_logpseudomodel.h new file mode 100644 index 0000000000000000000000000000000000000000..772bf305403ec4dbefe5bcac847ff2251358880c --- /dev/null +++ b/fxjs/xfa/cjx_logpseudomodel.h @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_LOGPSEUDOMODEL_H_ +#define FXJS_XFA_CJX_LOGPSEUDOMODEL_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CScript_LogPseudoModel; + +// TODO(dsinclair): This doesn't exist in the spec. Remove after +// xfa_basic_data_element_script is removed. +class CJX_LogPseudoModel : public CJX_Object { + public: + explicit CJX_LogPseudoModel(CScript_LogPseudoModel* model); + ~CJX_LogPseudoModel() override; + + JS_METHOD(message, CJX_LogPseudoModel); + JS_METHOD(traceEnabled, CJX_LogPseudoModel); + JS_METHOD(traceActivate, CJX_LogPseudoModel); + JS_METHOD(traceDeactivate, CJX_LogPseudoModel); + JS_METHOD(trace, CJX_LogPseudoModel); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_LOGPSEUDOMODEL_H_ diff --git a/fxjs/xfa/cjx_manifest.cpp b/fxjs/xfa/cjx_manifest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0882238aba2fc08461ddc085e5d765f84929e457 --- /dev/null +++ b/fxjs/xfa/cjx_manifest.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_manifest.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_manifest.h" + +const CJX_MethodSpec CJX_Manifest::MethodSpecs[] = { + {"evaluate", evaluate_static}}; + +CJX_Manifest::CJX_Manifest(CXFA_Manifest* manifest) : CJX_Node(manifest) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Manifest::~CJX_Manifest() {} + +CJS_Return CJX_Manifest::evaluate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + return CJS_Return( + runtime->NewBoolean(!!ToNode(GetXFAObject())->GetWidgetAcc())); +} + +void CJX_Manifest::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Manifest::action(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Manifest::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Manifest::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_manifest.h b/fxjs/xfa/cjx_manifest.h new file mode 100644 index 0000000000000000000000000000000000000000..75fcacdfb1ca62c0fb9e43528b4967924a4d072c --- /dev/null +++ b/fxjs/xfa/cjx_manifest.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MANIFEST_H_ +#define FXJS_XFA_CJX_MANIFEST_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Manifest; + +class CJX_Manifest : public CJX_Node { + public: + explicit CJX_Manifest(CXFA_Manifest* manifest); + ~CJX_Manifest() override; + + JS_METHOD(evaluate, CJX_Manifest); + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(action); + JS_PROP(use); + JS_PROP(usehref); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_MANIFEST_H_ diff --git a/fxjs/xfa/cjx_map.cpp b/fxjs/xfa/cjx_map.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a1fa14264c3dd96ef8fdb4fdc76a945cbd6a2fd --- /dev/null +++ b/fxjs/xfa/cjx_map.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_map.h" + +#include "xfa/fxfa/parser/cxfa_map.h" + +CJX_Map::CJX_Map(CXFA_Map* node) : CJX_Node(node) {} + +CJX_Map::~CJX_Map() = default; + +void CJX_Map::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Map::bind(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Map::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Map::from(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_map.h b/fxjs/xfa/cjx_map.h new file mode 100644 index 0000000000000000000000000000000000000000..dba7eb63e20eef36ab78a2ebda5c7326e9e1468c --- /dev/null +++ b/fxjs/xfa/cjx_map.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MAP_H_ +#define FXJS_XFA_CJX_MAP_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Map; + +class CJX_Map : public CJX_Node { + public: + explicit CJX_Map(CXFA_Map* node); + ~CJX_Map() override; + + JS_PROP(bind); + JS_PROP(from); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_MAP_H_ diff --git a/fxjs/xfa/cjx_margin.cpp b/fxjs/xfa/cjx_margin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62a180b324465e9c4c6eeff4b0fd0cf8def5e151 --- /dev/null +++ b/fxjs/xfa/cjx_margin.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_margin.h" + +#include "xfa/fxfa/parser/cxfa_margin.h" + +CJX_Margin::CJX_Margin(CXFA_Margin* node) : CJX_Node(node) {} + +CJX_Margin::~CJX_Margin() = default; + +void CJX_Margin::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Margin::leftInset(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Margin::bottomInset(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Margin::topInset(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Margin::rightInset(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Margin::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_margin.h b/fxjs/xfa/cjx_margin.h new file mode 100644 index 0000000000000000000000000000000000000000..0ca884f70814762a8f2598196b63452c8f2bd74a --- /dev/null +++ b/fxjs/xfa/cjx_margin.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MARGIN_H_ +#define FXJS_XFA_CJX_MARGIN_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Margin; + +class CJX_Margin : public CJX_Node { + public: + explicit CJX_Margin(CXFA_Margin* node); + ~CJX_Margin() override; + + JS_PROP(bottomInset); + JS_PROP(leftInset); + JS_PROP(rightInset); + JS_PROP(topInset); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_MARGIN_H_ diff --git a/fxjs/xfa/cjx_mdp.cpp b/fxjs/xfa/cjx_mdp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59730f68e6a0ba24c92de73cae449d7fe49b4dd3 --- /dev/null +++ b/fxjs/xfa/cjx_mdp.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_mdp.h" + +#include "xfa/fxfa/parser/cxfa_mdp.h" + +CJX_Mdp::CJX_Mdp(CXFA_Mdp* node) : CJX_Node(node) {} + +CJX_Mdp::~CJX_Mdp() = default; + +void CJX_Mdp::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Mdp::signatureType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Mdp::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Mdp::permissions(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_mdp.h b/fxjs/xfa/cjx_mdp.h new file mode 100644 index 0000000000000000000000000000000000000000..bdce2b83fd31b6d6ff9c9e1036bc9921dea252d1 --- /dev/null +++ b/fxjs/xfa/cjx_mdp.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MDP_H_ +#define FXJS_XFA_CJX_MDP_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Mdp; + +class CJX_Mdp : public CJX_Node { + public: + explicit CJX_Mdp(CXFA_Mdp* node); + ~CJX_Mdp() override; + + JS_PROP(permissions); + JS_PROP(signatureType); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_MDP_H_ diff --git a/fxjs/xfa/cjx_medium.cpp b/fxjs/xfa/cjx_medium.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8986d9bbb70680ff21d6bd21db01a23872dd5f4 --- /dev/null +++ b/fxjs/xfa/cjx_medium.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_medium.h" + +#include "xfa/fxfa/parser/cxfa_medium.h" + +CJX_Medium::CJX_Medium(CXFA_Medium* node) : CJX_Node(node) {} + +CJX_Medium::~CJX_Medium() = default; + +void CJX_Medium::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Medium::orientation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Medium::imagingBBox(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Medium::shortValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Medium::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Medium::stock(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Medium::longValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_medium.h b/fxjs/xfa/cjx_medium.h new file mode 100644 index 0000000000000000000000000000000000000000..99023dc4abf5331c006278061ccc1dca9d1fe4da --- /dev/null +++ b/fxjs/xfa/cjx_medium.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MEDIUM_H_ +#define FXJS_XFA_CJX_MEDIUM_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Medium; + +class CJX_Medium : public CJX_Node { + public: + explicit CJX_Medium(CXFA_Medium* node); + ~CJX_Medium() override; + + JS_PROP(imagingBBox); + JS_PROP(longValue); /* long */ + JS_PROP(orientation); + JS_PROP(shortValue); /* short */ + JS_PROP(stock); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_MEDIUM_H_ diff --git a/fxjs/xfa/cjx_message.cpp b/fxjs/xfa/cjx_message.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9f3f6afdc269fba01f3c7aee07afabb95700d33 --- /dev/null +++ b/fxjs/xfa/cjx_message.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_message.h" + +#include "xfa/fxfa/parser/cxfa_message.h" + +CJX_Message::CJX_Message(CXFA_Message* node) : CJX_Node(node) {} + +CJX_Message::~CJX_Message() = default; + +void CJX_Message::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Message::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_message.h b/fxjs/xfa/cjx_message.h new file mode 100644 index 0000000000000000000000000000000000000000..a2a461ebad0105cb8c38e0353d092ee46b956511 --- /dev/null +++ b/fxjs/xfa/cjx_message.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MESSAGE_H_ +#define FXJS_XFA_CJX_MESSAGE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Message; + +class CJX_Message : public CJX_Node { + public: + explicit CJX_Message(CXFA_Message* node); + ~CJX_Message() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_MESSAGE_H_ diff --git a/fxjs/xfa/cjx_model.cpp b/fxjs/xfa/cjx_model.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa5d6b21fa2f845f41e1583bfb3a4de3430d5e44 --- /dev/null +++ b/fxjs/xfa/cjx_model.cpp @@ -0,0 +1,92 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_model.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_delta.h" +#include "xfa/fxfa/parser/cxfa_document.h" + +const CJX_MethodSpec CJX_Model::MethodSpecs[] = { + {"clearErrorList", clearErrorList_static}, + {"createNode", createNode_static}, + {"isCompatibleNS", isCompatibleNS_static}}; + +CJX_Model::CJX_Model(CXFA_Node* node) : CJX_Node(node) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Model::~CJX_Model() {} + +CJS_Return CJX_Model::clearErrorList( + CJS_V8* runtime, + const std::vector>& params) { + return CJS_Return(true); +} + +CJS_Return CJX_Model::createNode( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString name; + if (params.size() > 1) + name = runtime->ToWideString(params[1]); + + WideString nameSpace; + if (params.size() == 3) + nameSpace = runtime->ToWideString(params[2]); + + WideString tagName = runtime->ToWideString(params[0]); + XFA_Element eType = CXFA_Node::NameToElement(tagName); + CXFA_Node* pNewNode = GetXFANode()->CreateSamePacketNode(eType); + if (!pNewNode) + return CJS_Return(runtime->NewNull()); + + if (!name.IsEmpty()) { + if (!pNewNode->HasAttribute(XFA_Attribute::Name)) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + pNewNode->JSObject()->SetAttribute(XFA_Attribute::Name, name.AsStringView(), + true); + if (pNewNode->GetPacketType() == XFA_PacketType::Datasets) + pNewNode->CreateXMLMappingNode(); + } + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewNode); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_Model::isCompatibleNS( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString nameSpace; + if (params.size() >= 1) + nameSpace = runtime->ToWideString(params[0]); + + return CJS_Return( + runtime->NewBoolean(TryNamespace().value_or(WideString()) == nameSpace)); +} + +void CJX_Model::context(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Model::aliasNode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} diff --git a/fxjs/xfa/cjx_model.h b/fxjs/xfa/cjx_model.h new file mode 100644 index 0000000000000000000000000000000000000000..fae1cc7cfdc6ed315c47f1dcae5756be0020e530 --- /dev/null +++ b/fxjs/xfa/cjx_model.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_MODEL_H_ +#define FXJS_XFA_CJX_MODEL_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Node; + +class CJX_Model : public CJX_Node { + public: + explicit CJX_Model(CXFA_Node* obj); + ~CJX_Model() override; + + JS_METHOD(clearErrorList, CJX_Model); + JS_METHOD(createNode, CJX_Model); + JS_METHOD(isCompatibleNS, CJX_Model); + + JS_PROP(aliasNode); + JS_PROP(context); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_MODEL_H_ diff --git a/fxjs/xfa/cjx_node.cpp b/fxjs/xfa/cjx_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf2642c8ad47ed420d903bb8bcef54bb12a8a047 --- /dev/null +++ b/fxjs/xfa/cjx_node.cpp @@ -0,0 +1,532 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_node.h" + +#include +#include + +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_codepage.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/js_resources.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_simple_parser.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +enum class EventAppliesToo { + kNone = 0, + kAll = 1, + kAllNonRecursive = 2, + kSubform = 3, + kFieldOrExclusion = 4, + kField = 5, + kSignature = 6, + kChoiceList = 7 +}; + +struct XFA_ExecEventParaInfo { + public: + uint32_t m_uHash; + const wchar_t* m_lpcEventName; + XFA_EVENTTYPE m_eventType; + EventAppliesToo m_validFlags; +}; + +const XFA_ExecEventParaInfo gs_eventParaInfos[] = { + {0x109d7ce7, L"mouseEnter", XFA_EVENT_MouseEnter, EventAppliesToo::kField}, + {0x1bfc72d9, L"preOpen", XFA_EVENT_PreOpen, EventAppliesToo::kChoiceList}, + {0x2196a452, L"initialize", XFA_EVENT_Initialize, EventAppliesToo::kAll}, + {0x27410f03, L"mouseExit", XFA_EVENT_MouseExit, EventAppliesToo::kField}, + {0x36f1c6d8, L"preSign", XFA_EVENT_PreSign, EventAppliesToo::kSignature}, + {0x4731d6ba, L"exit", XFA_EVENT_Exit, EventAppliesToo::kAllNonRecursive}, + {0x7233018a, L"validate", XFA_EVENT_Validate, EventAppliesToo::kAll}, + {0x8808385e, L"indexChange", XFA_EVENT_IndexChange, + EventAppliesToo::kSubform}, + {0x891f4606, L"change", XFA_EVENT_Change, + EventAppliesToo::kFieldOrExclusion}, + {0x9f693b21, L"mouseDown", XFA_EVENT_MouseDown, EventAppliesToo::kField}, + {0xcdce56b3, L"full", XFA_EVENT_Full, EventAppliesToo::kFieldOrExclusion}, + {0xd576d08e, L"mouseUp", XFA_EVENT_MouseUp, EventAppliesToo::kField}, + {0xd95657a6, L"click", XFA_EVENT_Click, EventAppliesToo::kFieldOrExclusion}, + {0xdbfbe02e, L"calculate", XFA_EVENT_Calculate, EventAppliesToo::kAll}, + {0xe25fa7b8, L"postOpen", XFA_EVENT_PostOpen, EventAppliesToo::kChoiceList}, + {0xe28dce7e, L"enter", XFA_EVENT_Enter, EventAppliesToo::kAllNonRecursive}, + {0xfd54fbb7, L"postSign", XFA_EVENT_PostSign, EventAppliesToo::kSignature}, +}; + +const XFA_ExecEventParaInfo* GetEventParaInfoByName( + const WideStringView& wsEventName) { + uint32_t uHash = FX_HashCode_GetW(wsEventName, false); + int32_t iStart = 0; + int32_t iEnd = (sizeof(gs_eventParaInfos) / sizeof(gs_eventParaInfos[0])) - 1; + do { + int32_t iMid = (iStart + iEnd) / 2; + const XFA_ExecEventParaInfo* eventParaInfo = &gs_eventParaInfos[iMid]; + if (uHash == eventParaInfo->m_uHash) + return eventParaInfo; + if (uHash < eventParaInfo->m_uHash) + iEnd = iMid - 1; + else + iStart = iMid + 1; + } while (iStart <= iEnd); + return nullptr; +} + +} // namespace + +const CJX_MethodSpec CJX_Node::MethodSpecs[] = { + {"applyXSL", applyXSL_static}, + {"assignNode", assignNode_static}, + {"clone", clone_static}, + {"getAttribute", getAttribute_static}, + {"getElement", getElement_static}, + {"isPropertySpecified", isPropertySpecified_static}, + {"loadXML", loadXML_static}, + {"saveFilteredXML", saveFilteredXML_static}, + {"saveXML", saveXML_static}, + {"setAttribute", setAttribute_static}, + {"setElement", setElement_static}}; + +CJX_Node::CJX_Node(CXFA_Node* node) : CJX_Tree(node) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Node::~CJX_Node() = default; + +CXFA_Node* CJX_Node::GetXFANode() { + return static_cast(GetXFAObject()); +} + +const CXFA_Node* CJX_Node::GetXFANode() const { + return static_cast(GetXFAObject()); +} + +CJS_Return CJX_Node::applyXSL(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + // TODO(weili): check whether we need to implement this, pdfium:501. + return CJS_Return(true); +} + +CJS_Return CJX_Node::assignNode( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + // TODO(weili): check whether we need to implement this, pdfium:501. + return CJS_Return(true); +} + +CJS_Return CJX_Node::clone(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Node* pCloneNode = GetXFANode()->Clone(runtime->ToBoolean(params[0])); + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pCloneNode); + if (!value) + return CJS_Return(runtime->NewNull()); + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_Node::getAttribute( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString expression = runtime->ToWideString(params[0]); + return CJS_Return(runtime->NewString( + GetAttribute(expression.AsStringView()).UTF8Encode().AsStringView())); +} + +CJS_Return CJX_Node::getElement( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString expression = runtime->ToWideString(params[0]); + int32_t iValue = params.size() >= 2 ? runtime->ToInt32(params[1]) : 0; + + CXFA_Node* pNode = GetOrCreateProperty( + iValue, CXFA_Node::NameToElement(expression)); + if (!pNode) + return CJS_Return(runtime->NewNull()); + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode); + if (!value) + return CJS_Return(runtime->NewNull()); + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_Node::isPropertySpecified( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString expression = runtime->ToWideString(params[0]); + XFA_Attribute attr = CXFA_Node::NameToAttribute(expression.AsStringView()); + if (attr != XFA_Attribute::Unknown && HasAttribute(attr)) + return CJS_Return(runtime->NewBoolean(true)); + + bool bParent = params.size() < 2 || runtime->ToBoolean(params[1]); + int32_t iIndex = params.size() == 3 ? runtime->ToInt32(params[2]) : 0; + XFA_Element eType = CXFA_Node::NameToElement(expression); + bool bHas = !!GetOrCreateProperty(iIndex, eType); + if (!bHas && bParent && GetXFANode()->GetParent()) { + // Also check on the parent. + auto* jsnode = GetXFANode()->GetParent()->JSObject(); + bHas = jsnode->HasAttribute(attr) || + !!jsnode->GetOrCreateProperty(iIndex, eType); + } + return CJS_Return(runtime->NewBoolean(bHas)); +} + +CJS_Return CJX_Node::loadXML(CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 3) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + ByteString expression = runtime->ToByteString(params[0]); + if (expression.IsEmpty()) + return CJS_Return(true); + + bool bIgnoreRoot = true; + if (params.size() >= 2) + bIgnoreRoot = runtime->ToBoolean(params[1]); + + bool bOverwrite = 0; + if (params.size() >= 3) + bOverwrite = runtime->ToBoolean(params[2]); + + auto pParser = pdfium::MakeUnique(GetDocument()); + if (!pParser) + return CJS_Return(true); + + CFX_XMLNode* pXMLNode = pParser->ParseXMLData(expression); + if (!pXMLNode) + return CJS_Return(true); + + if (bIgnoreRoot && + (pXMLNode->GetType() != FX_XMLNODE_Element || + XFA_RecognizeRichText(static_cast(pXMLNode)))) { + bIgnoreRoot = false; + } + + CXFA_Node* pFakeRoot = GetXFANode()->Clone(false); + WideString wsContentType = GetCData(XFA_Attribute::ContentType); + if (!wsContentType.IsEmpty()) { + pFakeRoot->JSObject()->SetCData(XFA_Attribute::ContentType, + WideString(wsContentType), false, false); + } + + std::unique_ptr pFakeXMLRoot(pFakeRoot->GetXMLMappingNode()); + if (!pFakeXMLRoot) { + CFX_XMLNode* pThisXMLRoot = GetXFANode()->GetXMLMappingNode(); + pFakeXMLRoot = pThisXMLRoot ? pThisXMLRoot->Clone() : nullptr; + } + if (!pFakeXMLRoot) { + pFakeXMLRoot = pdfium::MakeUnique( + WideString(GetXFANode()->GetClassName())); + } + + if (bIgnoreRoot) { + CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); + while (pXMLChild) { + CFX_XMLNode* pXMLSibling = + pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling); + pXMLNode->RemoveChildNode(pXMLChild); + pFakeXMLRoot->InsertChildNode(pXMLChild); + pXMLChild = pXMLSibling; + } + } else { + CFX_XMLNode* pXMLParent = pXMLNode->GetNodeItem(CFX_XMLNode::Parent); + if (pXMLParent) + pXMLParent->RemoveChildNode(pXMLNode); + + pFakeXMLRoot->InsertChildNode(pXMLNode); + } + + pParser->ConstructXFANode(pFakeRoot, pFakeXMLRoot.get()); + pFakeRoot = pParser->GetRootNode(); + if (!pFakeRoot) + return CJS_Return(true); + + if (bOverwrite) { + CXFA_Node* pChild = GetXFANode()->GetFirstChild(); + CXFA_Node* pNewChild = pFakeRoot->GetFirstChild(); + int32_t index = 0; + while (pNewChild) { + CXFA_Node* pItem = pNewChild->GetNextSibling(); + pFakeRoot->RemoveChild(pNewChild, true); + GetXFANode()->InsertChild(index++, pNewChild); + pNewChild->SetFlag(XFA_NodeFlag_Initialized, true); + pNewChild = pItem; + } + + while (pChild) { + CXFA_Node* pItem = pChild->GetNextSibling(); + GetXFANode()->RemoveChild(pChild, true); + pFakeRoot->InsertChild(pChild, nullptr); + pChild = pItem; + } + + if (GetXFANode()->GetPacketType() == XFA_PacketType::Form && + GetXFANode()->GetElementType() == XFA_Element::ExData) { + CFX_XMLNode* pTempXMLNode = GetXFANode()->GetXMLMappingNode(); + GetXFANode()->SetXMLMappingNode(pFakeXMLRoot.release()); + GetXFANode()->SetFlag(XFA_NodeFlag_OwnXMLNode, false); + if (pTempXMLNode && !pTempXMLNode->GetNodeItem(CFX_XMLNode::Parent)) + pFakeXMLRoot.reset(pTempXMLNode); + else + pFakeXMLRoot = nullptr; + } + MoveBufferMapData(pFakeRoot, GetXFANode()); + } else { + CXFA_Node* pChild = pFakeRoot->GetFirstChild(); + while (pChild) { + CXFA_Node* pItem = pChild->GetNextSibling(); + pFakeRoot->RemoveChild(pChild, true); + GetXFANode()->InsertChild(pChild, nullptr); + pChild->SetFlag(XFA_NodeFlag_Initialized, true); + pChild = pItem; + } + } + + if (pFakeXMLRoot) { + pFakeRoot->SetXMLMappingNode(pFakeXMLRoot.release()); + pFakeRoot->SetFlag(XFA_NodeFlag_OwnXMLNode, false); + } + pFakeRoot->SetFlag(XFA_NodeFlag_HasRemovedChildren, false); + + return CJS_Return(true); +} + +CJS_Return CJX_Node::saveFilteredXML( + CJS_V8* runtime, + const std::vector>& params) { + // TODO(weili): Check whether we need to implement this, pdfium:501. + return CJS_Return(true); +} + +CJS_Return CJX_Node::saveXML(CJS_V8* runtime, + const std::vector>& params) { + if (params.size() > 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + if (params.size() == 1 && runtime->ToWideString(params[0]) != L"pretty") + return CJS_Return(JSGetStringFromID(JSMessage::kValueError)); + + // TODO(weili): Check whether we need to save pretty print XML, pdfium:501. + + WideString bsXMLHeader = L"\n"; + if (GetXFANode()->GetPacketType() != XFA_PacketType::Form && + GetXFANode()->GetPacketType() != XFA_PacketType::Datasets) { + return CJS_Return(runtime->NewString("")); + } + + CFX_XMLNode* pElement = nullptr; + if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) { + pElement = GetXFANode()->GetXMLMappingNode(); + if (!pElement || pElement->GetType() != FX_XMLNODE_Element) { + return CJS_Return( + runtime->NewString(bsXMLHeader.UTF8Encode().AsStringView())); + } + + XFA_DataExporter_DealWithDataGroupNode(GetXFANode()); + } + + auto pMemoryStream = pdfium::MakeRetain(true); + auto pStream = + pdfium::MakeRetain(pMemoryStream, true); + pStream->SetCodePage(FX_CODEPAGE_UTF8); + pStream->WriteString(bsXMLHeader.AsStringView()); + + if (GetXFANode()->GetPacketType() == XFA_PacketType::Form) + XFA_DataExporter_RegenerateFormFile(GetXFANode(), pStream, nullptr, true); + else + pElement->SaveXMLNode(pStream); + + return CJS_Return(runtime->NewString( + ByteStringView(pMemoryStream->GetBuffer(), pMemoryStream->GetSize()))); +} + +CJS_Return CJX_Node::setAttribute( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString attributeValue = runtime->ToWideString(params[0]); + WideString attribute = runtime->ToWideString(params[1]); + SetAttribute(attribute.AsStringView(), attributeValue.AsStringView(), true); + return CJS_Return(true); +} + +CJS_Return CJX_Node::setElement( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1 && params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + // TODO(weili): check whether we need to implement this, pdfium:501. + return CJS_Return(true); +} + +void CJX_Node::id(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Node::ns(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetString( + TryNamespace().value_or(WideString()).UTF8Encode().AsStringView()); +} + +void CJX_Node::model(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap( + GetXFANode()->GetModelNode())); +} + +void CJX_Node::isContainer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetBoolean(GetXFANode()->IsContainerNode()); +} + +void CJX_Node::isNull(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + if (GetXFANode()->GetElementType() == XFA_Element::Subform) { + pValue->SetBoolean(false); + return; + } + pValue->SetBoolean(GetContent(false).IsEmpty()); +} + +void CJX_Node::oneOfChild(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + std::vector properties = GetXFANode()->GetNodeList( + XFA_NODEFILTER_OneOfProperty, XFA_Element::Unknown); + if (!properties.empty()) { + pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap( + properties.front())); + } +} + +int32_t CJX_Node::execSingleEventByName(const WideStringView& wsEventName, + XFA_Element eType) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return XFA_EVENTERROR_NotExist; + + const XFA_ExecEventParaInfo* eventParaInfo = + GetEventParaInfoByName(wsEventName); + if (!eventParaInfo) + return XFA_EVENTERROR_NotExist; + + switch (eventParaInfo->m_validFlags) { + case EventAppliesToo::kNone: + return XFA_EVENTERROR_NotExist; + case EventAppliesToo::kAll: + case EventAppliesToo::kAllNonRecursive: + return pNotify->ExecEventByDeepFirst( + GetXFANode(), eventParaInfo->m_eventType, false, + eventParaInfo->m_validFlags == EventAppliesToo::kAll); + case EventAppliesToo::kSubform: + if (eType != XFA_Element::Subform) + return XFA_EVENTERROR_NotExist; + + return pNotify->ExecEventByDeepFirst( + GetXFANode(), eventParaInfo->m_eventType, false, false); + case EventAppliesToo::kFieldOrExclusion: { + if (eType != XFA_Element::ExclGroup && eType != XFA_Element::Field) + return XFA_EVENTERROR_NotExist; + + CXFA_Node* pParentNode = GetXFANode()->GetParent(); + if (pParentNode && + pParentNode->GetElementType() == XFA_Element::ExclGroup) { + // TODO(dsinclair): This seems like a bug, we do the same work twice? + pNotify->ExecEventByDeepFirst(GetXFANode(), eventParaInfo->m_eventType, + false, false); + } + return pNotify->ExecEventByDeepFirst( + GetXFANode(), eventParaInfo->m_eventType, false, false); + } + case EventAppliesToo::kField: + if (eType != XFA_Element::Field) + return XFA_EVENTERROR_NotExist; + + return pNotify->ExecEventByDeepFirst( + GetXFANode(), eventParaInfo->m_eventType, false, false); + case EventAppliesToo::kSignature: { + CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); + if (!pWidgetAcc) + return XFA_EVENTERROR_NotExist; + + CXFA_Node* pUINode = pWidgetAcc->GetUIChild(); + if (pUINode->GetElementType() != XFA_Element::Signature) + return XFA_EVENTERROR_NotExist; + + return pNotify->ExecEventByDeepFirst( + GetXFANode(), eventParaInfo->m_eventType, false, false); + } + case EventAppliesToo::kChoiceList: { + CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); + if (!pWidgetAcc) + return XFA_EVENTERROR_NotExist; + + CXFA_Node* pUINode = pWidgetAcc->GetUIChild(); + if (pUINode->GetElementType() != XFA_Element::ChoiceList || + pWidgetAcc->IsListBox()) { + return XFA_EVENTERROR_NotExist; + } + return pNotify->ExecEventByDeepFirst( + GetXFANode(), eventParaInfo->m_eventType, false, false); + } + } + return XFA_EVENTERROR_NotExist; +} diff --git a/fxjs/xfa/cjx_node.h b/fxjs/xfa/cjx_node.h new file mode 100644 index 0000000000000000000000000000000000000000..f7cbce855b046433229951d3f0eec0b6f0c12d41 --- /dev/null +++ b/fxjs/xfa/cjx_node.h @@ -0,0 +1,52 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_NODE_H_ +#define FXJS_XFA_CJX_NODE_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" +#include "fxjs/xfa/cjx_tree.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CXFA_Node; + +class CJX_Node : public CJX_Tree { + public: + explicit CJX_Node(CXFA_Node* node); + ~CJX_Node() override; + + JS_METHOD(applyXSL, CJX_Node); + JS_METHOD(assignNode, CJX_Node); + JS_METHOD(clone, CJX_Node); + JS_METHOD(getAttribute, CJX_Node); + JS_METHOD(getElement, CJX_Node); + JS_METHOD(isPropertySpecified, CJX_Node); + JS_METHOD(loadXML, CJX_Node); + JS_METHOD(saveFilteredXML, CJX_Node); + JS_METHOD(saveXML, CJX_Node); + JS_METHOD(setAttribute, CJX_Node); + JS_METHOD(setElement, CJX_Node); + + JS_PROP(id); + JS_PROP(isContainer); + JS_PROP(isNull); + JS_PROP(model); + JS_PROP(ns); + JS_PROP(oneOfChild); + + CXFA_Node* GetXFANode(); + const CXFA_Node* GetXFANode() const; + + protected: + int32_t execSingleEventByName(const WideStringView& wsEventName, + XFA_Element eType); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_NODE_H_ diff --git a/fxjs/xfa/cjx_numericedit.cpp b/fxjs/xfa/cjx_numericedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c76cc66bf8ce36845e47f016b4ad3c2e08af7789 --- /dev/null +++ b/fxjs/xfa/cjx_numericedit.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_numericedit.h" + +#include "xfa/fxfa/parser/cxfa_numericedit.h" + +CJX_NumericEdit::CJX_NumericEdit(CXFA_NumericEdit* node) : CJX_Node(node) {} + +CJX_NumericEdit::~CJX_NumericEdit() = default; + +void CJX_NumericEdit::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_NumericEdit::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_NumericEdit::hScrollPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_numericedit.h b/fxjs/xfa/cjx_numericedit.h new file mode 100644 index 0000000000000000000000000000000000000000..43f9d001dc298a259e3df0d05b39a2a8a8eef591 --- /dev/null +++ b/fxjs/xfa/cjx_numericedit.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_NUMERICEDIT_H_ +#define FXJS_XFA_CJX_NUMERICEDIT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_NumericEdit; + +class CJX_NumericEdit : public CJX_Node { + public: + explicit CJX_NumericEdit(CXFA_NumericEdit* node); + ~CJX_NumericEdit() override; + + JS_PROP(hScrollPolicy); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_NUMERICEDIT_H_ diff --git a/fxjs/xfa/cjx_object.cpp b/fxjs/xfa/cjx_object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6408cf3eb970257d8e38e438c296999f96f3d95d --- /dev/null +++ b/fxjs/xfa/cjx_object.cpp @@ -0,0 +1,1704 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_object.h" + +#include + +#include "core/fxcrt/cfx_decimal.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/cjs_return.h" +#include "fxjs/xfa/cjx_boolean.h" +#include "fxjs/xfa/cjx_draw.h" +#include "fxjs/xfa/cjx_field.h" +#include "fxjs/xfa/cjx_instancemanager.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_datavalue.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxfa/parser/cxfa_fill.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#include "xfa/fxfa/parser/cxfa_occur.h" +#include "xfa/fxfa/parser/cxfa_proto.h" +#include "xfa/fxfa/parser/cxfa_subform.h" +#include "xfa/fxfa/parser/cxfa_validate.h" +#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +void XFA_DeleteWideString(void* pData) { + delete static_cast(pData); +} + +void XFA_CopyWideString(void*& pData) { + if (!pData) + return; + pData = new WideString(*reinterpret_cast(pData)); +} + +XFA_MAPDATABLOCKCALLBACKINFO deleteWideStringCallBack = {XFA_DeleteWideString, + XFA_CopyWideString}; + +enum XFA_KEYTYPE { + XFA_KEYTYPE_Custom, + XFA_KEYTYPE_Element, +}; + +void* GetMapKey_Custom(const WideStringView& wsKey) { + uint32_t dwKey = FX_HashCode_GetW(wsKey, false); + return (void*)(uintptr_t)((dwKey << 1) | XFA_KEYTYPE_Custom); +} + +void* GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) { + return (void*)(uintptr_t)((static_cast(eType) << 16) | + (static_cast(eAttribute) << 8) | + XFA_KEYTYPE_Element); +} + +void XFA_DefaultFreeData(void* pData) {} + +XFA_MAPDATABLOCKCALLBACKINFO gs_XFADefaultFreeData = {XFA_DefaultFreeData, + nullptr}; + +std::tuple StrToRGB(const WideString& strRGB) { + int32_t r = 0; + int32_t g = 0; + int32_t b = 0; + + size_t iIndex = 0; + for (size_t i = 0; i < strRGB.GetLength(); ++i) { + wchar_t ch = strRGB[i]; + if (ch == L',') + ++iIndex; + if (iIndex > 2) + break; + + int32_t iValue = ch - L'0'; + if (iValue >= 0 && iValue <= 9) { + switch (iIndex) { + case 0: + r = r * 10 + iValue; + break; + case 1: + g = g * 10 + iValue; + break; + default: + b = b * 10 + iValue; + break; + } + } + } + return {r, g, b}; +} + +} // namespace + +struct XFA_MAPDATABLOCK { + uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); } + + XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo; + int32_t iBytes; +}; + +struct XFA_MAPMODULEDATA { + XFA_MAPMODULEDATA() {} + ~XFA_MAPMODULEDATA() {} + + std::map m_ValueMap; + std::map m_BufferMap; +}; + +CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {} + +CJX_Object::~CJX_Object() { + ClearMapModuleBuffer(); +} + +void CJX_Object::DefineMethods(const CJX_MethodSpec method_specs[], + size_t count) { + for (size_t i = 0; i < count; ++i) + method_specs_[method_specs[i].pName] = method_specs[i].pMethodCall; +} + +CXFA_Document* CJX_Object::GetDocument() const { + return object_->GetDocument(); +} + +void CJX_Object::className(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetString( + FX_UTF8Encode(GetXFAObject()->GetClassName()).AsStringView()); +} + +int32_t CJX_Object::Subform_and_SubformSet_InstanceIndex() { + int32_t index = 0; + for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetPrevSibling(); pNode; + pNode = pNode->GetPrevSibling()) { + if ((pNode->GetElementType() != XFA_Element::Subform) && + (pNode->GetElementType() != XFA_Element::SubformSet)) { + break; + } + index++; + } + return index; +} + +bool CJX_Object::HasMethod(const WideString& func) const { + return pdfium::ContainsKey(method_specs_, func.UTF8Encode()); +} + +CJS_Return CJX_Object::RunMethod( + const WideString& func, + const std::vector>& params) { + auto it = method_specs_.find(func.UTF8Encode()); + if (it == method_specs_.end()) + return CJS_Return(false); + return it->second(this, GetXFAObject()->GetDocument()->GetScriptContext(), + params); +} + +void CJX_Object::ThrowTooManyOccurancesException(const WideString& obj) const { + ThrowException( + L"The element [%ls] has violated its allowable number of occurrences.", + obj.c_str()); +} + +void CJX_Object::ThrowInvalidPropertyException() const { + ThrowException(L"Invalid property set operation."); +} + +void CJX_Object::ThrowIndexOutOfBoundsException() const { + ThrowException(L"Index value is out of bounds."); +} + +void CJX_Object::ThrowParamCountMismatchException( + const WideString& method) const { + ThrowException(L"Incorrect number of parameters calling method '%.16s'.", + method.c_str()); +} + +void CJX_Object::ThrowArgumentMismatchException() const { + ThrowException(L"Argument mismatch in property or function argument."); +} + +void CJX_Object::ThrowException(const wchar_t* str, ...) const { + va_list arg_ptr; + va_start(arg_ptr, str); + WideString wsMessage = WideString::FormatV(str, arg_ptr); + va_end(arg_ptr); + + ASSERT(!wsMessage.IsEmpty()); + FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView()); +} + +bool CJX_Object::HasAttribute(XFA_Attribute eAttr) { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + return HasMapModuleKey(pKey); +} + +bool CJX_Object::SetAttribute(XFA_Attribute eAttr, + const WideStringView& wsValue, + bool bNotify) { + switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) { + case XFA_AttributeType::Enum: { + Optional item = + CXFA_Node::NameToAttributeEnum(wsValue); + return SetEnum( + eAttr, + item ? *item : *(ToNode(GetXFAObject())->GetDefaultEnum(eAttr)), + bNotify); + } + case XFA_AttributeType::CData: + return SetCData(eAttr, WideString(wsValue), bNotify, false); + case XFA_AttributeType::Boolean: + return SetBoolean(eAttr, wsValue != L"0", bNotify); + case XFA_AttributeType::Integer: + return SetInteger(eAttr, + FXSYS_round(FXSYS_wcstof(wsValue.unterminated_c_str(), + wsValue.GetLength(), nullptr)), + bNotify); + case XFA_AttributeType::Measure: + return SetMeasure(eAttr, CXFA_Measurement(wsValue), bNotify); + default: + break; + } + return false; +} + +void CJX_Object::SetMapModuleString(void* pKey, const WideStringView& wsValue) { + SetMapModuleBuffer(pKey, (void*)wsValue.unterminated_c_str(), + wsValue.GetLength() * sizeof(wchar_t), nullptr); +} + +bool CJX_Object::SetAttribute(const WideStringView& wsAttr, + const WideStringView& wsValue, + bool bNotify) { + XFA_Attribute attr = CXFA_Node::NameToAttribute(wsValue); + if (attr != XFA_Attribute::Unknown) + return SetAttribute(attr, wsValue, bNotify); + + void* pKey = GetMapKey_Custom(wsAttr); + SetMapModuleString(pKey, wsValue); + return true; +} + +WideString CJX_Object::GetAttribute(const WideStringView& attr) { + return TryAttribute(attr, true).value_or(WideString()); +} + +WideString CJX_Object::GetAttribute(XFA_Attribute attr) { + return TryAttribute(attr, true).value_or(WideString()); +} + +Optional CJX_Object::TryAttribute(XFA_Attribute eAttr, + bool bUseDefault) { + switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) { + case XFA_AttributeType::Enum: { + Optional value = TryEnum(eAttr, bUseDefault); + if (!value) + return {}; + + return {CXFA_Node::AttributeEnumToName(*value)}; + } + case XFA_AttributeType::CData: + return TryCData(eAttr, bUseDefault); + + case XFA_AttributeType::Boolean: { + Optional value = TryBoolean(eAttr, bUseDefault); + if (!value) + return {}; + return {*value ? L"1" : L"0"}; + } + case XFA_AttributeType::Integer: { + Optional iValue = TryInteger(eAttr, bUseDefault); + if (!iValue) + return {}; + return {WideString::Format(L"%d", *iValue)}; + } + case XFA_AttributeType::Measure: { + Optional value = TryMeasure(eAttr, bUseDefault); + if (!value) + return {}; + + return {value->ToString()}; + } + default: + break; + } + return {}; +} + +Optional CJX_Object::TryAttribute(const WideStringView& wsAttr, + bool bUseDefault) { + XFA_Attribute attr = CXFA_Node::NameToAttribute(wsAttr); + if (attr != XFA_Attribute::Unknown) + return TryAttribute(attr, bUseDefault); + + void* pKey = GetMapKey_Custom(wsAttr); + WideStringView wsValueC; + if (!GetMapModuleString(pKey, wsValueC)) + return {}; + + return {WideString(wsValueC)}; +} + +void CJX_Object::RemoveAttribute(const WideStringView& wsAttr) { + void* pKey = GetMapKey_Custom(wsAttr); + if (pKey) + RemoveMapModuleKey(pKey); +} + +Optional CJX_Object::TryBoolean(XFA_Attribute eAttr, bool bUseDefault) { + void* pValue = nullptr; + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + if (GetMapModuleValue(pKey, pValue)) + return {!!pValue}; + if (!bUseDefault) + return {}; + + return ToNode(GetXFAObject())->GetDefaultBoolean(eAttr); +} + +bool CJX_Object::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) { + CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Boolean, + (void*)(uintptr_t)bValue, bNotify); + if (elem) + elem->SetString(CXFA_Node::AttributeToName(eAttr), bValue ? L"1" : L"0"); + return true; +} + +bool CJX_Object::GetBoolean(XFA_Attribute eAttr) { + return TryBoolean(eAttr, true).value_or(false); +} + +bool CJX_Object::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) { + CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Integer, + (void*)(uintptr_t)iValue, bNotify); + if (elem) { + elem->SetString(CXFA_Node::AttributeToName(eAttr), + WideString::Format(L"%d", iValue)); + } + return true; +} + +int32_t CJX_Object::GetInteger(XFA_Attribute eAttr) { + return TryInteger(eAttr, true).value_or(0); +} + +Optional CJX_Object::TryInteger(XFA_Attribute eAttr, + bool bUseDefault) { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + void* pValue = nullptr; + if (GetMapModuleValue(pKey, pValue)) + return {static_cast(reinterpret_cast(pValue))}; + if (!bUseDefault) + return {}; + + return ToNode(GetXFAObject())->GetDefaultInteger(eAttr); +} + +Optional CJX_Object::TryEnum(XFA_Attribute eAttr, + bool bUseDefault) { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + void* pValue = nullptr; + if (GetMapModuleValue(pKey, pValue)) { + return { + static_cast(reinterpret_cast(pValue))}; + } + if (!bUseDefault) + return {}; + + return ToNode(GetXFAObject())->GetDefaultEnum(eAttr); +} + +bool CJX_Object::SetEnum(XFA_Attribute eAttr, + XFA_AttributeEnum eValue, + bool bNotify) { + CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Enum, + (void*)(uintptr_t)eValue, bNotify); + if (elem) { + elem->SetString(CXFA_Node::AttributeToName(eAttr), + CXFA_Node::AttributeEnumToName(eValue)); + } + return true; +} + +XFA_AttributeEnum CJX_Object::GetEnum(XFA_Attribute eAttr) { + return TryEnum(eAttr, true).value_or(XFA_AttributeEnum::Unknown); +} + +bool CJX_Object::SetMeasure(XFA_Attribute eAttr, + CXFA_Measurement mValue, + bool bNotify) { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + OnChanging(eAttr, bNotify); + SetMapModuleBuffer(pKey, &mValue, sizeof(CXFA_Measurement), nullptr); + OnChanged(eAttr, bNotify, false); + return true; +} + +Optional CJX_Object::TryMeasure(XFA_Attribute eAttr, + bool bUseDefault) const { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + void* pValue; + int32_t iBytes; + if (GetMapModuleBuffer(pKey, pValue, iBytes, true) && + iBytes == sizeof(CXFA_Measurement)) { + return {*reinterpret_cast(pValue)}; + } + if (!bUseDefault) + return {}; + + return ToNode(GetXFAObject())->GetDefaultMeasurement(eAttr); +} + +Optional CJX_Object::TryMeasureAsFloat(XFA_Attribute attr) const { + Optional measure = TryMeasure(attr, false); + if (measure) + return {measure->ToUnit(XFA_Unit::Pt)}; + return {}; +} + +CXFA_Measurement CJX_Object::GetMeasure(XFA_Attribute eAttr) const { + return TryMeasure(eAttr, true).value_or(CXFA_Measurement()); +} + +WideString CJX_Object::GetCData(XFA_Attribute eAttr) { + return TryCData(eAttr, true).value_or(WideString()); +} + +bool CJX_Object::SetCData(XFA_Attribute eAttr, + const WideString& wsValue, + bool bNotify, + bool bScriptModify) { + CXFA_Node* xfaObj = ToNode(GetXFAObject()); + void* pKey = GetMapKey_Element(xfaObj->GetElementType(), eAttr); + OnChanging(eAttr, bNotify); + if (eAttr == XFA_Attribute::Value) { + WideString* pClone = new WideString(wsValue); + SetUserData(pKey, pClone, &deleteWideStringCallBack); + } else { + SetMapModuleString(pKey, wsValue.AsStringView()); + if (eAttr == XFA_Attribute::Name) + xfaObj->UpdateNameHash(); + } + OnChanged(eAttr, bNotify, bScriptModify); + + if (!xfaObj->IsNeedSavingXMLNode() || eAttr == XFA_Attribute::QualifiedName || + eAttr == XFA_Attribute::BindingNode) { + return true; + } + + if (eAttr == XFA_Attribute::Name && + (xfaObj->GetElementType() == XFA_Element::DataValue || + xfaObj->GetElementType() == XFA_Element::DataGroup)) { + return true; + } + + auto* elem = static_cast(xfaObj->GetXMLMappingNode()); + if (eAttr == XFA_Attribute::Value) { + FX_XMLNODETYPE eXMLType = elem->GetType(); + switch (eXMLType) { + case FX_XMLNODE_Element: + if (xfaObj->IsAttributeInXML()) { + elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)), + wsValue); + } else { + bool bDeleteChildren = true; + if (xfaObj->GetPacketType() == XFA_PacketType::Datasets) { + for (CXFA_Node* pChildDataNode = xfaObj->GetFirstChild(); + pChildDataNode; + pChildDataNode = pChildDataNode->GetNextSibling()) { + if (!pChildDataNode->GetBindItems()->empty()) { + bDeleteChildren = false; + break; + } + } + } + if (bDeleteChildren) + elem->DeleteChildren(); + + elem->SetTextData(wsValue); + } + break; + case FX_XMLNODE_Text: + static_cast(xfaObj->GetXMLMappingNode()) + ->SetText(wsValue); + break; + default: + NOTREACHED(); + } + return true; + } + ASSERT(elem->GetType() == FX_XMLNODE_Element); + + WideString wsAttrName = CXFA_Node::AttributeToName(eAttr); + if (eAttr == XFA_Attribute::ContentType) + wsAttrName = L"xfa:" + wsAttrName; + + elem->SetString(wsAttrName, wsValue); + return true; +} + +void CJX_Object::SetAttributeValue(const WideString& wsValue, + const WideString& wsXMLValue, + bool bNotify, + bool bScriptModify) { + auto* xfaObj = ToNode(GetXFAObject()); + + void* pKey = + GetMapKey_Element(xfaObj->GetElementType(), XFA_Attribute::Value); + OnChanging(XFA_Attribute::Value, bNotify); + WideString* pClone = new WideString(wsValue); + SetUserData(pKey, pClone, &deleteWideStringCallBack); + OnChanged(XFA_Attribute::Value, bNotify, bScriptModify); + if (!xfaObj->IsNeedSavingXMLNode()) + return; + + auto* elem = static_cast(xfaObj->GetXMLMappingNode()); + FX_XMLNODETYPE eXMLType = elem->GetType(); + switch (eXMLType) { + case FX_XMLNODE_Element: + if (xfaObj->IsAttributeInXML()) { + elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)), + wsXMLValue); + } else { + bool bDeleteChildren = true; + if (xfaObj->GetPacketType() == XFA_PacketType::Datasets) { + for (CXFA_Node* pChildDataNode = xfaObj->GetFirstChild(); + pChildDataNode; + pChildDataNode = pChildDataNode->GetNextSibling()) { + if (!pChildDataNode->GetBindItems()->empty()) { + bDeleteChildren = false; + break; + } + } + } + if (bDeleteChildren) + elem->DeleteChildren(); + + elem->SetTextData(wsXMLValue); + } + break; + case FX_XMLNODE_Text: + static_cast(xfaObj->GetXMLMappingNode()) + ->SetText(wsXMLValue); + break; + default: + ASSERT(0); + } +} + +Optional CJX_Object::TryCData(XFA_Attribute eAttr, + bool bUseDefault) { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + if (eAttr == XFA_Attribute::Value) { + void* pData; + int32_t iBytes = 0; + WideString* pStr = nullptr; + if (GetMapModuleBuffer(pKey, pData, iBytes, true) && + iBytes == sizeof(void*)) { + memcpy(&pData, pData, iBytes); + pStr = reinterpret_cast(pData); + } + if (pStr) + return {*pStr}; + } else { + WideStringView wsValueC; + if (GetMapModuleString(pKey, wsValueC)) + return {WideString(wsValueC)}; + } + if (!bUseDefault) + return {}; + + return ToNode(GetXFAObject())->GetDefaultCData(eAttr); +} + +CFX_XMLElement* CJX_Object::SetValue(XFA_Attribute eAttr, + XFA_AttributeType eType, + void* pValue, + bool bNotify) { + void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr); + OnChanging(eAttr, bNotify); + SetMapModuleValue(pKey, pValue); + OnChanged(eAttr, bNotify, false); + if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode()) + return nullptr; + + auto* elem = + static_cast(ToNode(GetXFAObject())->GetXMLMappingNode()); + ASSERT(elem->GetType() == FX_XMLNODE_Element); + + return elem; +} + +bool CJX_Object::SetContent(const WideString& wsContent, + const WideString& wsXMLValue, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + CXFA_Node* pNode = nullptr; + CXFA_Node* pBindNode = nullptr; + switch (ToNode(GetXFAObject())->GetObjectType()) { + case XFA_ObjectType::ContainerNode: { + if (XFA_FieldIsMultiListBox(ToNode(GetXFAObject()))) { + CXFA_Value* pValue = + GetOrCreateProperty(0, XFA_Element::Value); + if (!pValue) + break; + + CXFA_Node* pChildValue = pValue->GetFirstChild(); + ASSERT(pChildValue); + pChildValue->JSObject()->SetCData(XFA_Attribute::ContentType, + L"text/xml", false, false); + pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify, + bScriptModify, false); + CXFA_Node* pBind = ToNode(GetXFAObject())->GetBindData(); + if (bSyncData && pBind) { + std::vector wsSaveTextArray; + size_t iSize = 0; + if (!wsContent.IsEmpty()) { + size_t iStart = 0; + size_t iLength = wsContent.GetLength(); + auto iEnd = wsContent.Find(L'\n', iStart); + iEnd = !iEnd.has_value() ? iLength : iEnd; + while (iEnd.value() >= iStart) { + wsSaveTextArray.push_back( + wsContent.Mid(iStart, iEnd.value() - iStart)); + iStart = iEnd.value() + 1; + if (iStart >= iLength) + break; + + iEnd = wsContent.Find(L'\n', iStart); + if (!iEnd.has_value()) { + wsSaveTextArray.push_back( + wsContent.Mid(iStart, iLength - iStart)); + } + } + iSize = wsSaveTextArray.size(); + } + if (iSize == 0) { + while (CXFA_Node* pChildNode = pBind->GetFirstChild()) { + pBind->RemoveChild(pChildNode, true); + } + } else { + std::vector valueNodes = pBind->GetNodeList( + XFA_NODEFILTER_Children, XFA_Element::DataValue); + size_t iDatas = valueNodes.size(); + if (iDatas < iSize) { + size_t iAddNodes = iSize - iDatas; + CXFA_Node* pValueNodes = nullptr; + while (iAddNodes-- > 0) { + pValueNodes = + pBind->CreateSamePacketNode(XFA_Element::DataValue); + pValueNodes->JSObject()->SetCData(XFA_Attribute::Name, L"value", + false, false); + pValueNodes->CreateXMLMappingNode(); + pBind->InsertChild(pValueNodes, nullptr); + } + pValueNodes = nullptr; + } else if (iDatas > iSize) { + size_t iDelNodes = iDatas - iSize; + while (iDelNodes-- > 0) { + pBind->RemoveChild(pBind->GetFirstChild(), true); + } + } + int32_t i = 0; + for (CXFA_Node* pValueNode = pBind->GetFirstChild(); pValueNode; + pValueNode = pValueNode->GetNextSibling()) { + pValueNode->JSObject()->SetAttributeValue( + wsSaveTextArray[i], wsSaveTextArray[i], false, false); + i++; + } + } + for (const auto& pArrayNode : *(pBind->GetBindItems())) { + if (pArrayNode.Get() != ToNode(GetXFAObject())) { + pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify, + bScriptModify, false); + } + } + } + break; + } + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExclGroup) { + pNode = ToNode(GetXFAObject()); + } else { + CXFA_Value* pValue = + GetOrCreateProperty(0, XFA_Element::Value); + if (!pValue) + break; + + CXFA_Node* pChildValue = pValue->GetFirstChild(); + ASSERT(pChildValue); + pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify, + bScriptModify, false); + } + pBindNode = ToNode(GetXFAObject())->GetBindData(); + if (pBindNode && bSyncData) { + pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify, + bScriptModify, false); + for (const auto& pArrayNode : *(pBindNode->GetBindItems())) { + if (pArrayNode.Get() != ToNode(GetXFAObject())) { + pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify, + true, false); + } + } + } + pBindNode = nullptr; + break; + } + case XFA_ObjectType::ContentNode: { + WideString wsContentType; + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExData) { + Optional ret = + TryAttribute(XFA_Attribute::ContentType, false); + if (ret) + wsContentType = *ret; + if (wsContentType == L"text/html") { + wsContentType = L""; + SetAttribute(XFA_Attribute::ContentType, wsContentType.AsStringView(), + false); + } + } + + CXFA_Node* pContentRawDataNode = ToNode(GetXFAObject())->GetFirstChild(); + if (!pContentRawDataNode) { + pContentRawDataNode = + ToNode(GetXFAObject()) + ->CreateSamePacketNode((wsContentType == L"text/xml") + ? XFA_Element::Sharpxml + : XFA_Element::Sharptext); + ToNode(GetXFAObject())->InsertChild(pContentRawDataNode, nullptr); + } + return pContentRawDataNode->JSObject()->SetContent( + wsContent, wsXMLValue, bNotify, bScriptModify, bSyncData); + } + case XFA_ObjectType::NodeC: + case XFA_ObjectType::TextNode: + pNode = ToNode(GetXFAObject()); + break; + case XFA_ObjectType::NodeV: + pNode = ToNode(GetXFAObject()); + if (bSyncData && + ToNode(GetXFAObject())->GetPacketType() == XFA_PacketType::Form) { + CXFA_Node* pParent = ToNode(GetXFAObject())->GetParent(); + if (pParent) { + pParent = pParent->GetParent(); + } + if (pParent && pParent->GetElementType() == XFA_Element::Value) { + pParent = pParent->GetParent(); + if (pParent && pParent->IsContainerNode()) { + pBindNode = pParent->GetBindData(); + if (pBindNode) { + pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify, + bScriptModify, false); + } + } + } + } + break; + default: + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue) { + pNode = ToNode(GetXFAObject()); + pBindNode = ToNode(GetXFAObject()); + } + break; + } + if (!pNode) + return false; + + SetAttributeValue(wsContent, wsXMLValue, bNotify, bScriptModify); + if (pBindNode && bSyncData) { + for (const auto& pArrayNode : *(pBindNode->GetBindItems())) { + pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify, + bScriptModify, false); + } + } + return true; +} + +WideString CJX_Object::GetContent(bool bScriptModify) { + return TryContent(bScriptModify, true).value_or(WideString()); +} + +Optional CJX_Object::TryContent(bool bScriptModify, bool bProto) { + CXFA_Node* pNode = nullptr; + switch (ToNode(GetXFAObject())->GetObjectType()) { + case XFA_ObjectType::ContainerNode: + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExclGroup) { + pNode = ToNode(GetXFAObject()); + } else { + CXFA_Value* pValue = + ToNode(GetXFAObject()) + ->GetChild(0, XFA_Element::Value, false); + if (!pValue) + return {}; + + CXFA_Node* pChildValue = pValue->GetFirstChild(); + if (pChildValue && XFA_FieldIsMultiListBox(ToNode(GetXFAObject()))) { + pChildValue->JSObject()->SetAttribute(XFA_Attribute::ContentType, + L"text/xml", false); + } + if (pChildValue) + return pChildValue->JSObject()->TryContent(bScriptModify, bProto); + return {}; + } + break; + case XFA_ObjectType::ContentNode: { + CXFA_Node* pContentRawDataNode = ToNode(GetXFAObject())->GetFirstChild(); + if (!pContentRawDataNode) { + XFA_Element element = XFA_Element::Sharptext; + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExData) { + Optional contentType = + TryAttribute(XFA_Attribute::ContentType, false); + if (contentType) { + if (*contentType == L"text/html") + element = XFA_Element::SharpxHTML; + else if (*contentType == L"text/xml") + element = XFA_Element::Sharpxml; + } + } + pContentRawDataNode = + ToNode(GetXFAObject())->CreateSamePacketNode(element); + ToNode(GetXFAObject())->InsertChild(pContentRawDataNode, nullptr); + } + return pContentRawDataNode->JSObject()->TryContent(bScriptModify, true); + } + case XFA_ObjectType::NodeC: + case XFA_ObjectType::NodeV: + case XFA_ObjectType::TextNode: + pNode = ToNode(GetXFAObject()); + default: + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue) + pNode = ToNode(GetXFAObject()); + break; + } + if (pNode) { + if (bScriptModify) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (pScriptContext) + GetDocument()->GetScriptContext()->AddNodesOfRunScript( + ToNode(GetXFAObject())); + } + return TryCData(XFA_Attribute::Value, false); + } + return {}; +} + +Optional CJX_Object::TryNamespace() { + if (ToNode(GetXFAObject())->IsModelNode() || + ToNode(GetXFAObject())->GetElementType() == XFA_Element::Packet) { + CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode(); + if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element) + return {}; + + return {static_cast(pXMLNode)->GetNamespaceURI()}; + } + + if (ToNode(GetXFAObject())->GetPacketType() != XFA_PacketType::Datasets) + return ToNode(GetXFAObject())->GetModelNode()->JSObject()->TryNamespace(); + + CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode(); + if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element) + return {}; + + if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue && + GetEnum(XFA_Attribute::Contains) == XFA_AttributeEnum::MetaData) { + WideString wsNamespace; + bool ret = XFA_FDEExtension_ResolveNamespaceQualifier( + static_cast(pXMLNode), + GetCData(XFA_Attribute::QualifiedName), &wsNamespace); + if (!ret) + return {}; + return {wsNamespace}; + } + return {static_cast(pXMLNode)->GetNamespaceURI()}; +} + +std::pair CJX_Object::GetPropertyInternal( + int32_t index, + XFA_Element eProperty) const { + const CXFA_Node* xfaNode = ToNode(GetXFAObject()); + if (index < 0 || index >= xfaNode->PropertyOccuranceCount(eProperty)) + return {nullptr, 0}; + + int32_t iCount = 0; + for (CXFA_Node* pNode = xfaNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() == eProperty) { + iCount++; + if (iCount > index) + return {pNode, iCount}; + } + } + return {nullptr, iCount}; +} + +CXFA_Node* CJX_Object::GetOrCreatePropertyInternal(int32_t index, + XFA_Element eProperty) { + CXFA_Node* xfaNode = ToNode(GetXFAObject()); + if (index < 0 || index >= xfaNode->PropertyOccuranceCount(eProperty)) + return nullptr; + + int32_t iCount = 0; + CXFA_Node* node; + std::tie(node, iCount) = GetPropertyInternal(index, eProperty); + if (node) + return node; + + if (xfaNode->HasPropertyFlags(eProperty, XFA_PROPERTYFLAG_OneOf)) { + for (CXFA_Node* pNode = xfaNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (xfaNode->HasPropertyFlags(pNode->GetElementType(), + XFA_PROPERTYFLAG_OneOf)) { + return nullptr; + } + } + } + + CXFA_Node* pNewNode = nullptr; + for (; iCount <= index; ++iCount) { + pNewNode = GetDocument()->CreateNode(xfaNode->GetPacketType(), eProperty); + if (!pNewNode) + return nullptr; + + xfaNode->InsertChild(pNewNode, nullptr); + pNewNode->SetFlag(XFA_NodeFlag_Initialized, true); + } + return pNewNode; +} + +bool CJX_Object::SetUserData(void* pKey, + void* pData, + XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) { + SetMapModuleBuffer(pKey, &pData, sizeof(void*), + pCallbackInfo ? pCallbackInfo : &gs_XFADefaultFreeData); + return true; +} + +XFA_MAPMODULEDATA* CJX_Object::CreateMapModuleData() { + if (!map_module_data_) + map_module_data_ = pdfium::MakeUnique(); + return map_module_data_.get(); +} + +XFA_MAPMODULEDATA* CJX_Object::GetMapModuleData() const { + return map_module_data_.get(); +} + +void CJX_Object::SetMapModuleValue(void* pKey, void* pValue) { + CreateMapModuleData()->m_ValueMap[pKey] = pValue; +} + +bool CJX_Object::GetMapModuleValue(void* pKey, void*& pValue) { + for (CXFA_Node* pNode = ToNode(GetXFAObject()); pNode; + pNode = pNode->GetTemplateNodeIfExists()) { + XFA_MAPMODULEDATA* pModule = pNode->JSObject()->GetMapModuleData(); + if (pModule) { + auto it = pModule->m_ValueMap.find(pKey); + if (it != pModule->m_ValueMap.end()) { + pValue = it->second; + return true; + } + } + if (pNode->GetPacketType() == XFA_PacketType::Datasets) + break; + } + return false; +} + +bool CJX_Object::GetMapModuleString(void* pKey, WideStringView& wsValue) { + void* pValue; + int32_t iBytes; + if (!GetMapModuleBuffer(pKey, pValue, iBytes, true)) + return false; + + // Defensive measure: no out-of-bounds pointers even if zero length. + int32_t iChars = iBytes / sizeof(wchar_t); + wsValue = WideStringView(iChars ? (const wchar_t*)pValue : nullptr, iChars); + return true; +} + +void CJX_Object::SetMapModuleBuffer( + void* pKey, + void* pValue, + int32_t iBytes, + XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) { + XFA_MAPDATABLOCK*& pBuffer = CreateMapModuleData()->m_BufferMap[pKey]; + if (!pBuffer) { + pBuffer = reinterpret_cast( + FX_Alloc(uint8_t, sizeof(XFA_MAPDATABLOCK) + iBytes)); + } else if (pBuffer->iBytes != iBytes) { + if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) + pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); + + pBuffer = reinterpret_cast( + FX_Realloc(uint8_t, pBuffer, sizeof(XFA_MAPDATABLOCK) + iBytes)); + } else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) { + pBuffer->pCallbackInfo->pFree( + *reinterpret_cast(pBuffer->GetData())); + } + if (!pBuffer) + return; + + pBuffer->pCallbackInfo = pCallbackInfo; + pBuffer->iBytes = iBytes; + memcpy(pBuffer->GetData(), pValue, iBytes); +} + +bool CJX_Object::GetMapModuleBuffer(void* pKey, + void*& pValue, + int32_t& iBytes, + bool bProtoAlso) const { + XFA_MAPDATABLOCK* pBuffer = nullptr; + for (const CXFA_Node* pNode = ToNode(GetXFAObject()); pNode; + pNode = pNode->GetTemplateNodeIfExists()) { + XFA_MAPMODULEDATA* pModule = pNode->JSObject()->GetMapModuleData(); + if (pModule) { + auto it = pModule->m_BufferMap.find(pKey); + if (it != pModule->m_BufferMap.end()) { + pBuffer = it->second; + break; + } + } + if (!bProtoAlso || pNode->GetPacketType() == XFA_PacketType::Datasets) + break; + } + if (!pBuffer) + return false; + + pValue = pBuffer->GetData(); + iBytes = pBuffer->iBytes; + return true; +} + +bool CJX_Object::HasMapModuleKey(void* pKey) { + XFA_MAPMODULEDATA* pModule = GetMapModuleData(); + return pModule && (pdfium::ContainsKey(pModule->m_ValueMap, pKey) || + pdfium::ContainsKey(pModule->m_BufferMap, pKey)); +} + +void CJX_Object::ClearMapModuleBuffer() { + XFA_MAPMODULEDATA* pModule = GetMapModuleData(); + if (!pModule) + return; + + for (auto& pair : pModule->m_BufferMap) { + XFA_MAPDATABLOCK* pBuffer = pair.second; + if (pBuffer) { + if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) + pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); + + FX_Free(pBuffer); + } + } + pModule->m_BufferMap.clear(); + pModule->m_ValueMap.clear(); +} + +void CJX_Object::RemoveMapModuleKey(void* pKey) { + ASSERT(pKey); + + XFA_MAPMODULEDATA* pModule = GetMapModuleData(); + if (!pModule) + return; + + auto it = pModule->m_BufferMap.find(pKey); + if (it != pModule->m_BufferMap.end()) { + XFA_MAPDATABLOCK* pBuffer = it->second; + if (pBuffer) { + if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) + pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); + + FX_Free(pBuffer); + } + pModule->m_BufferMap.erase(it); + } + pModule->m_ValueMap.erase(pKey); + return; +} + +void CJX_Object::MergeAllData(CXFA_Object* pDstModule) { + XFA_MAPMODULEDATA* pDstModuleData = + ToNode(pDstModule)->JSObject()->CreateMapModuleData(); + XFA_MAPMODULEDATA* pSrcModuleData = GetMapModuleData(); + if (!pSrcModuleData) + return; + + for (const auto& pair : pSrcModuleData->m_ValueMap) + pDstModuleData->m_ValueMap[pair.first] = pair.second; + + for (const auto& pair : pSrcModuleData->m_BufferMap) { + XFA_MAPDATABLOCK* pSrcBuffer = pair.second; + XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first]; + if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree && + !pSrcBuffer->pCallbackInfo->pCopy) { + if (pDstBuffer) { + pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); + pDstModuleData->m_BufferMap.erase(pair.first); + } + continue; + } + if (!pDstBuffer) { + pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc( + uint8_t, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes); + } else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) { + if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) { + pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); + } + pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc( + uint8_t, pDstBuffer, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes); + } else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) { + pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); + } + if (!pDstBuffer) + continue; + + pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo; + pDstBuffer->iBytes = pSrcBuffer->iBytes; + memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes); + if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) { + pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData()); + } + } +} + +void CJX_Object::MoveBufferMapData(CXFA_Object* pDstModule) { + if (!pDstModule) + return; + + bool bNeedMove = true; + if (pDstModule->GetElementType() != GetXFAObject()->GetElementType()) + bNeedMove = false; + + if (bNeedMove) + ToNode(pDstModule)->JSObject()->SetCalcData(ReleaseCalcData()); + if (!pDstModule->IsNodeV()) + return; + + WideString wsValue = ToNode(pDstModule)->JSObject()->GetContent(false); + WideString wsFormatValue(wsValue); + CXFA_WidgetAcc* pWidgetAcc = ToNode(pDstModule)->GetContainerWidgetAcc(); + if (pWidgetAcc) + wsFormatValue = pWidgetAcc->GetFormatDataValue(wsValue); + + ToNode(pDstModule) + ->JSObject() + ->SetContent(wsValue, wsFormatValue, true, true, true); +} + +void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcModule, + CXFA_Object* pDstModule) { + if (!pSrcModule || !pDstModule) + return; + + CXFA_Node* pSrcChild = ToNode(pSrcModule)->GetFirstChild(); + CXFA_Node* pDstChild = ToNode(pDstModule)->GetFirstChild(); + while (pSrcChild && pDstChild) { + MoveBufferMapData(pSrcChild, pDstChild); + + pSrcChild = pSrcChild->GetNextSibling(); + pDstChild = pDstChild->GetNextSibling(); + } + ToNode(pSrcModule)->JSObject()->MoveBufferMapData(pDstModule); +} + +void CJX_Object::OnChanging(XFA_Attribute eAttr, bool bNotify) { + if (!bNotify || !ToNode(GetXFAObject())->IsInitialized()) + return; + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->OnValueChanging(ToNode(GetXFAObject()), eAttr); +} + +void CJX_Object::OnChanged(XFA_Attribute eAttr, + bool bNotify, + bool bScriptModify) { + if (bNotify && ToNode(GetXFAObject())->IsInitialized()) + ToNode(GetXFAObject())->SendAttributeChangeMessage(eAttr, bScriptModify); +} + +void CJX_Object::SetCalcData(std::unique_ptr data) { + calc_data_ = std::move(data); +} + +std::unique_ptr CJX_Object::ReleaseCalcData() { + return std::move(calc_data_); +} + +void CJX_Object::Script_Attribute_String(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (!bSetting) { + pValue->SetString(GetAttribute(eAttribute).UTF8Encode().AsStringView()); + return; + } + + WideString wsValue = pValue->ToWideString(); + SetAttribute(eAttribute, wsValue.AsStringView(), true); + if (eAttribute != XFA_Attribute::Use || + GetXFAObject()->GetElementType() != XFA_Element::Desc) { + return; + } + + CXFA_Node* pTemplateNode = + ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Template)); + CXFA_Proto* pProtoRoot = + pTemplateNode->GetFirstChildByClass(XFA_Element::Subform) + ->GetFirstChildByClass(XFA_Element::Proto); + + WideString wsID; + WideString wsSOM; + if (!wsValue.IsEmpty()) { + if (wsValue[0] == '#') + wsID = WideString(wsValue.c_str() + 1, wsValue.GetLength() - 1); + else + wsSOM = wsValue; + } + + CXFA_Node* pProtoNode = nullptr; + if (!wsSOM.IsEmpty()) { + XFA_RESOLVENODE_RS resolveNodeRS; + bool iRet = GetDocument()->GetScriptContext()->ResolveObjects( + pProtoRoot, wsSOM.AsStringView(), &resolveNodeRS, + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | + XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings, + nullptr); + if (iRet && resolveNodeRS.objects.front()->IsNode()) + pProtoNode = resolveNodeRS.objects.front()->AsNode(); + + } else if (!wsID.IsEmpty()) { + pProtoNode = GetDocument()->GetNodeByID(pProtoRoot, wsID.AsStringView()); + } + if (!pProtoNode) + return; + + CXFA_Node* pHeadChild = ToNode(GetXFAObject())->GetFirstChild(); + while (pHeadChild) { + CXFA_Node* pSibling = pHeadChild->GetNextSibling(); + ToNode(GetXFAObject())->RemoveChild(pHeadChild, true); + pHeadChild = pSibling; + } + + std::unique_ptr pProtoForm(pProtoNode->CloneTemplateToForm(true)); + pHeadChild = pProtoForm->GetFirstChild(); + while (pHeadChild) { + CXFA_Node* pSibling = pHeadChild->GetNextSibling(); + pProtoForm->RemoveChild(pHeadChild, true); + ToNode(GetXFAObject())->InsertChild(pHeadChild, nullptr); + pHeadChild = pSibling; + } + + GetDocument()->RemovePurgeNode(pProtoForm.get()); +} + +void CJX_Object::Script_Attribute_BOOL(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + SetBoolean(eAttribute, pValue->ToBoolean(), true); + return; + } + pValue->SetString(GetBoolean(eAttribute) ? "1" : "0"); +} + +void CJX_Object::Script_Attribute_Integer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + SetInteger(eAttribute, pValue->ToInteger(), true); + return; + } + pValue->SetInteger(GetInteger(eAttribute)); +} + +void CJX_Object::Script_Som_FontColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Font* font = ToNode(object_.Get())->GetOrCreateFontIfPossible(); + if (!font) + return; + + if (bSetting) { + int32_t r; + int32_t g; + int32_t b; + std::tie(r, g, b) = StrToRGB(pValue->ToWideString()); + FX_ARGB color = ArgbEncode(0xff, r, g, b); + font->SetColor(color); + return; + } + + int32_t a; + int32_t r; + int32_t g; + int32_t b; + std::tie(a, r, g, b) = ArgbDecode(font->GetColor()); + pValue->SetString(ByteString::Format("%d,%d,%d", r, g, b).AsStringView()); +} + +void CJX_Object::Script_Som_FillColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible(); + CXFA_Fill* borderfill = border->GetOrCreateFillIfPossible(); + if (!borderfill) + return; + + if (bSetting) { + int32_t r; + int32_t g; + int32_t b; + std::tie(r, g, b) = StrToRGB(pValue->ToWideString()); + FX_ARGB color = ArgbEncode(0xff, r, g, b); + borderfill->SetColor(color); + return; + } + + FX_ARGB color = borderfill->GetColor(false); + int32_t a; + int32_t r; + int32_t g; + int32_t b; + std::tie(a, r, g, b) = ArgbDecode(color); + pValue->SetString( + WideString::Format(L"%d,%d,%d", r, g, b).UTF8Encode().AsStringView()); +} + +void CJX_Object::Script_Som_BorderColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible(); + int32_t iSize = border->CountEdges(); + if (bSetting) { + int32_t r = 0; + int32_t g = 0; + int32_t b = 0; + std::tie(r, g, b) = StrToRGB(pValue->ToWideString()); + FX_ARGB rgb = ArgbEncode(100, r, g, b); + for (int32_t i = 0; i < iSize; ++i) { + CXFA_Edge* edge = border->GetEdgeIfExists(i); + if (edge) + edge->SetColor(rgb); + } + + return; + } + + CXFA_Edge* edge = border->GetEdgeIfExists(0); + FX_ARGB color = edge ? edge->GetColor() : CXFA_Edge::kDefaultColor; + int32_t a; + int32_t r; + int32_t g; + int32_t b; + std::tie(a, r, g, b) = ArgbDecode(color); + pValue->SetString( + WideString::Format(L"%d,%d,%d", r, g, b).UTF8Encode().AsStringView()); +} + +void CJX_Object::Script_Som_BorderWidth(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible(); + if (bSetting) { + CXFA_Edge* edge = border->GetEdgeIfExists(0); + CXFA_Measurement thickness = + edge ? edge->GetMSThickness() : CXFA_Measurement(0.5, XFA_Unit::Pt); + pValue->SetString(thickness.ToString().UTF8Encode().AsStringView()); + return; + } + + WideString wsThickness = pValue->ToWideString(); + for (int32_t i = 0; i < border->CountEdges(); ++i) { + CXFA_Edge* edge = border->GetEdgeIfExists(i); + if (edge) + edge->SetMSThickness(CXFA_Measurement(wsThickness.AsStringView())); + } +} + +void CJX_Object::Script_Som_Message(CFXJSE_Value* pValue, + bool bSetting, + XFA_SOM_MESSAGETYPE iMessageType) { + bool bNew = false; + CXFA_Validate* validate = ToNode(object_.Get())->GetValidateIfExists(); + if (!validate) { + validate = ToNode(object_.Get())->GetOrCreateValidateIfPossible(); + bNew = true; + } + + if (bSetting) { + if (validate) { + switch (iMessageType) { + case XFA_SOM_ValidationMessage: + validate->SetScriptMessageText(pValue->ToWideString()); + break; + case XFA_SOM_FormatMessage: + validate->SetFormatMessageText(pValue->ToWideString()); + break; + case XFA_SOM_MandatoryMessage: + validate->SetNullMessageText(pValue->ToWideString()); + break; + default: + break; + } + } + + if (!bNew) { + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + pNotify->AddCalcValidate(ToNode(GetXFAObject())); + } + return; + } + + if (!validate) { + // TODO(dsinclair): Better error message? + ThrowInvalidPropertyException(); + return; + } + + WideString wsMessage; + switch (iMessageType) { + case XFA_SOM_ValidationMessage: + wsMessage = validate->GetScriptMessageText(); + break; + case XFA_SOM_FormatMessage: + wsMessage = validate->GetFormatMessageText(); + break; + case XFA_SOM_MandatoryMessage: + wsMessage = validate->GetNullMessageText(); + break; + default: + break; + } + pValue->SetString(wsMessage.UTF8Encode().AsStringView()); +} + +void CJX_Object::Script_Som_ValidationMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_Message(pValue, bSetting, XFA_SOM_ValidationMessage); +} + +void CJX_Object::Script_Som_MandatoryMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_Message(pValue, bSetting, XFA_SOM_MandatoryMessage); +} + +void CJX_Object::Script_Field_Length(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + if (!ToNode(object_.Get())->GetWidgetAcc()) { + pValue->SetInteger(0); + return; + } + pValue->SetInteger( + ToNode(object_.Get())->GetWidgetAcc()->CountChoiceListItems(true)); +} + +void CJX_Object::Script_Som_DefaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute /* unused */) { + XFA_Element eType = ToNode(GetXFAObject())->GetElementType(); + + // TODO(dsinclair): This should look through the properties on the node to see + // if defaultValue is defined and, if so, call that one. Just have to make + // sure that those defaultValue calls don't call back to this one .... + if (eType == XFA_Element::Field) { + static_cast(this)->defaultValue(pValue, bSetting, + XFA_Attribute::Unknown); + return; + } + if (eType == XFA_Element::Draw) { + static_cast(this)->defaultValue(pValue, bSetting, + XFA_Attribute::Unknown); + return; + } + if (eType == XFA_Element::Boolean) { + static_cast(this)->defaultValue(pValue, bSetting, + XFA_Attribute::Unknown); + return; + } + + if (bSetting) { + WideString wsNewValue; + if (pValue && !(pValue->IsNull() || pValue->IsUndefined())) + wsNewValue = pValue->ToWideString(); + + WideString wsFormatValue(wsNewValue); + CXFA_WidgetAcc* pContainerWidgetAcc = nullptr; + if (ToNode(GetXFAObject())->GetPacketType() == XFA_PacketType::Datasets) { + WideString wsPicture; + for (const auto& pFormNode : *(ToNode(GetXFAObject())->GetBindItems())) { + if (!pFormNode || pFormNode->HasRemovedChildren()) + continue; + + pContainerWidgetAcc = pFormNode->GetContainerWidgetAcc(); + if (pContainerWidgetAcc) { + wsPicture = + pContainerWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind); + } + if (!wsPicture.IsEmpty()) + break; + + pContainerWidgetAcc = nullptr; + } + } else if (ToNode(GetXFAObject())->GetPacketType() == + XFA_PacketType::Form) { + pContainerWidgetAcc = ToNode(GetXFAObject())->GetContainerWidgetAcc(); + } + + if (pContainerWidgetAcc) + wsFormatValue = pContainerWidgetAcc->GetFormatDataValue(wsNewValue); + + SetContent(wsNewValue, wsFormatValue, true, true, true); + return; + } + + WideString content = GetContent(true); + if (content.IsEmpty() && eType != XFA_Element::Text && + eType != XFA_Element::SubmitUrl) { + pValue->SetNull(); + } else if (eType == XFA_Element::Integer) { + pValue->SetInteger(FXSYS_wtoi(content.c_str())); + } else if (eType == XFA_Element::Float || eType == XFA_Element::Decimal) { + CFX_Decimal decimal(content.AsStringView()); + pValue->SetFloat((float)(double)decimal); + } else { + pValue->SetString(content.UTF8Encode().AsStringView()); + } +} + +void CJX_Object::Script_Som_DefaultValue_Read(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + WideString content = GetContent(true); + if (content.IsEmpty()) { + pValue->SetNull(); + return; + } + pValue->SetString(content.UTF8Encode().AsStringView()); +} + +void CJX_Object::Script_Som_DataNode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + CXFA_Node* pDataNode = ToNode(GetXFAObject())->GetBindData(); + if (!pDataNode) { + pValue->SetNull(); + return; + } + + pValue->Assign( + GetDocument()->GetScriptContext()->GetJSValueFromMap(pDataNode)); +} + +void CJX_Object::Script_Som_Mandatory(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Validate* validate = + ToNode(object_.Get())->GetOrCreateValidateIfPossible(); + if (!validate) + return; + + if (bSetting) { + validate->SetNullTest(pValue->ToWideString()); + return; + } + + WideString str = CXFA_Node::AttributeEnumToName(validate->GetNullTest()); + pValue->SetString(str.UTF8Encode().AsStringView()); +} + +void CJX_Object::Script_Som_InstanceIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (!bSetting) { + pValue->SetInteger(Subform_and_SubformSet_InstanceIndex()); + return; + } + + int32_t iTo = pValue->ToInteger(); + int32_t iFrom = Subform_and_SubformSet_InstanceIndex(); + CXFA_Node* pManagerNode = nullptr; + for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetPrevSibling(); pNode; + pNode = pNode->GetPrevSibling()) { + if (pNode->GetElementType() == XFA_Element::InstanceManager) { + pManagerNode = pNode; + break; + } + } + if (!pManagerNode) + return; + + auto* mgr = static_cast(pManagerNode->JSObject()); + mgr->MoveInstance(iTo, iFrom); + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return; + + CXFA_Node* pToInstance = pManagerNode->GetItemIfExists(iTo); + if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform) { + pNotify->RunSubformIndexChange(pToInstance); + } + + CXFA_Node* pFromInstance = pManagerNode->GetItemIfExists(iFrom); + if (pFromInstance && + pFromInstance->GetElementType() == XFA_Element::Subform) { + pNotify->RunSubformIndexChange(pFromInstance); + } +} + +void CJX_Object::Script_Subform_InstanceManager(CFXJSE_Value* pValue, + bool bSetting, + XFA_AttributeEnum eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + WideString wsName = GetCData(XFA_Attribute::Name); + CXFA_Node* pInstanceMgr = nullptr; + for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetPrevSibling(); pNode; + pNode = pNode->GetPrevSibling()) { + if (pNode->GetElementType() == XFA_Element::InstanceManager) { + WideString wsInstMgrName = + pNode->JSObject()->GetCData(XFA_Attribute::Name); + if (wsInstMgrName.GetLength() >= 1 && wsInstMgrName[0] == '_' && + wsInstMgrName.Right(wsInstMgrName.GetLength() - 1) == wsName) { + pInstanceMgr = pNode; + } + break; + } + } + if (!pInstanceMgr) { + pValue->SetNull(); + return; + } + + pValue->Assign( + GetDocument()->GetScriptContext()->GetJSValueFromMap(pInstanceMgr)); +} + +void CJX_Object::Script_SubmitFormat_Mode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Object::Script_Form_Checksum(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + SetAttribute(XFA_Attribute::Checksum, pValue->ToWideString().AsStringView(), + false); + return; + } + + Optional checksum = TryAttribute(XFA_Attribute::Checksum, false); + pValue->SetString(checksum ? checksum->UTF8Encode().AsStringView() : ""); +} + +void CJX_Object::Script_ExclGroup_ErrorText(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) + ThrowInvalidPropertyException(); +} diff --git a/fxjs/xfa/cjx_object.h b/fxjs/xfa/cjx_object.h new file mode 100644 index 0000000000000000000000000000000000000000..c252b450364e17c2720a611ac3f39575b6e10e71 --- /dev/null +++ b/fxjs/xfa/cjx_object.h @@ -0,0 +1,281 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_OBJECT_H_ +#define FXJS_XFA_CJX_OBJECT_H_ + +#include +#include +#include +#include + +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxcrt/widestring.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "fxjs/CJX_Define.h" +#include "third_party/base/optional.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CFXJSE_Value; +class CJS_V8; +class CXFA_CalcData; +class CXFA_Document; +class CXFA_LayoutItem; +class CXFA_Node; +class CXFA_Object; +struct XFA_MAPMODULEDATA; + +typedef CJS_Return (*CJX_MethodCall)( + CJX_Object* obj, + CJS_V8* runtime, + const std::vector>& params); +struct CJX_MethodSpec { + const char* pName; + CJX_MethodCall pMethodCall; +}; + +typedef void (*PD_CALLBACK_FREEDATA)(void* pData); +typedef void (*PD_CALLBACK_DUPLICATEDATA)(void*& pData); + +struct XFA_MAPDATABLOCKCALLBACKINFO { + PD_CALLBACK_FREEDATA pFree; + PD_CALLBACK_DUPLICATEDATA pCopy; +}; + +enum XFA_SOM_MESSAGETYPE { + XFA_SOM_ValidationMessage, + XFA_SOM_FormatMessage, + XFA_SOM_MandatoryMessage +}; + +class CJX_Object { + public: + explicit CJX_Object(CXFA_Object* obj); + virtual ~CJX_Object(); + + JS_PROP(className); + + CXFA_Object* GetXFAObject() { return object_.Get(); } + const CXFA_Object* GetXFAObject() const { return object_.Get(); } + + CXFA_Document* GetDocument() const; + + void SetCalcRecursionCount(size_t count) { calc_recursion_count_ = count; } + size_t GetCalcRecursionCount() const { return calc_recursion_count_; } + + void SetLayoutItem(CXFA_LayoutItem* item) { layout_item_ = item; } + CXFA_LayoutItem* GetLayoutItem() const { return layout_item_.Get(); } + + bool HasMethod(const WideString& func) const; + CJS_Return RunMethod(const WideString& func, + const std::vector>& params); + + bool HasAttribute(XFA_Attribute eAttr); + bool SetAttribute(XFA_Attribute eAttr, + const WideStringView& wsValue, + bool bNotify); + bool SetAttribute(const WideStringView& wsAttr, + const WideStringView& wsValue, + bool bNotify); + void RemoveAttribute(const WideStringView& wsAttr); + WideString GetAttribute(const WideStringView& attr); + WideString GetAttribute(XFA_Attribute attr); + Optional TryAttribute(const WideStringView& wsAttr, + bool bUseDefault); + Optional TryAttribute(XFA_Attribute eAttr, bool bUseDefault); + + Optional TryContent(bool bScriptModify, bool bProto); + bool SetContent(const WideString& wsContent, + const WideString& wsXMLValue, + bool bNotify, + bool bScriptModify, + bool bSyncData); + WideString GetContent(bool bScriptModify); + + template + T* GetProperty(int32_t index, XFA_Element eType) const { + CXFA_Node* node; + int32_t count; + std::tie(node, count) = GetPropertyInternal(index, eType); + return static_cast(node); + } + template + T* GetOrCreateProperty(int32_t index, XFA_Element eType) { + return static_cast(GetOrCreatePropertyInternal(index, eType)); + } + + void SetAttributeValue(const WideString& wsValue, + const WideString& wsXMLValue, + bool bNotify, + bool bScriptModify); + + void Script_Attribute_String(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Attribute_BOOL(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Attribute_Integer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + + void Script_Som_FontColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_FillColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_BorderColor(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_BorderWidth(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_ValidationMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_MandatoryMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Field_Length(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_DefaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_DefaultValue_Read(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_DataNode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_Mandatory(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_InstanceIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Som_Message(CFXJSE_Value* pValue, + bool bSetting, + XFA_SOM_MESSAGETYPE iMessageType); + void Script_Subform_InstanceManager(CFXJSE_Value* pValue, + bool bSetting, + XFA_AttributeEnum eAttribute); + void Script_SubmitFormat_Mode(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Form_Checksum(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_ExclGroup_ErrorText(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + + Optional TryNamespace(); + + Optional TryInteger(XFA_Attribute eAttr, bool bUseDefault); + bool SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify); + int32_t GetInteger(XFA_Attribute eAttr); + + Optional TryCData(XFA_Attribute eAttr, bool bUseDefault); + bool SetCData(XFA_Attribute eAttr, + const WideString& wsValue, + bool bNotify, + bool bScriptModify); + WideString GetCData(XFA_Attribute eAttr); + + Optional TryEnum(XFA_Attribute eAttr, bool bUseDefault); + bool SetEnum(XFA_Attribute eAttr, XFA_AttributeEnum eValue, bool bNotify); + XFA_AttributeEnum GetEnum(XFA_Attribute eAttr); + + Optional TryBoolean(XFA_Attribute eAttr, bool bUseDefault); + bool SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify); + bool GetBoolean(XFA_Attribute eAttr); + + Optional TryMeasure(XFA_Attribute eAttr, + bool bUseDefault) const; + Optional TryMeasureAsFloat(XFA_Attribute attr) const; + bool SetMeasure(XFA_Attribute eAttr, CXFA_Measurement mValue, bool bNotify); + CXFA_Measurement GetMeasure(XFA_Attribute eAttr) const; + + void MergeAllData(CXFA_Object* pDstModule); + + void SetCalcData(std::unique_ptr data); + CXFA_CalcData* GetCalcData() const { return calc_data_.get(); } + std::unique_ptr ReleaseCalcData(); + + int32_t InstanceManager_SetInstances(int32_t iDesired); + int32_t InstanceManager_MoveInstance(int32_t iTo, int32_t iFrom); + + void ThrowInvalidPropertyException() const; + void ThrowArgumentMismatchException() const; + void ThrowIndexOutOfBoundsException() const; + void ThrowParamCountMismatchException(const WideString& method) const; + void ThrowTooManyOccurancesException(const WideString& obj) const; + + protected: + void DefineMethods(const CJX_MethodSpec method_specs[], size_t count); + + void MoveBufferMapData(CXFA_Object* pSrcModule, CXFA_Object* pDstModule); + void SetMapModuleString(void* pKey, const WideStringView& wsValue); + void ThrowException(const wchar_t* str, ...) const; + + private: + void Script_Boolean_DefaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Draw_DefaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + void Script_Field_DefaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); + + std::pair GetPropertyInternal(int32_t index, + XFA_Element eType) const; + CXFA_Node* GetOrCreatePropertyInternal(int32_t index, XFA_Element eType); + + void OnChanged(XFA_Attribute eAttr, bool bNotify, bool bScriptModify); + void OnChanging(XFA_Attribute eAttr, bool bNotify); + bool SetUserData(void* pKey, + void* pData, + XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo); + + // Returns a pointer to the XML node that needs to be updated with the new + // attribute value. |nullptr| if no update is needed. + CFX_XMLElement* SetValue(XFA_Attribute eAttr, + XFA_AttributeType eType, + void* pValue, + bool bNotify); + int32_t Subform_and_SubformSet_InstanceIndex(); + + XFA_MAPMODULEDATA* CreateMapModuleData(); + XFA_MAPMODULEDATA* GetMapModuleData() const; + void SetMapModuleValue(void* pKey, void* pValue); + bool GetMapModuleValue(void* pKey, void*& pValue); + bool GetMapModuleString(void* pKey, WideStringView& wsValue); + void SetMapModuleBuffer(void* pKey, + void* pValue, + int32_t iBytes, + XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo); + bool GetMapModuleBuffer(void* pKey, + void*& pValue, + int32_t& iBytes, + bool bProtoAlso) const; + bool HasMapModuleKey(void* pKey); + void ClearMapModuleBuffer(); + void RemoveMapModuleKey(void* pKey); + void MoveBufferMapData(CXFA_Object* pDstModule); + + UnownedPtr object_; + UnownedPtr layout_item_; + std::unique_ptr map_module_data_; + std::unique_ptr calc_data_; + std::map method_specs_; + size_t calc_recursion_count_ = 0; +}; + +#endif // FXJS_XFA_CJX_OBJECT_H_ diff --git a/fxjs/xfa/cjx_occur.cpp b/fxjs/xfa/cjx_occur.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f57cd96cb508c3abe389a6f87a1bc14693f158a1 --- /dev/null +++ b/fxjs/xfa/cjx_occur.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_occur.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cxfa_occur.h" + +CJX_Occur::CJX_Occur(CXFA_Occur* node) : CJX_Node(node) {} + +CJX_Occur::~CJX_Occur() = default; + +void CJX_Occur::max(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Occur* occur = static_cast(GetXFANode()); + if (!bSetting) { + pValue->SetInteger(occur->GetMax()); + return; + } + occur->SetMax(pValue->ToInteger()); +} + +void CJX_Occur::min(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CXFA_Occur* occur = static_cast(GetXFANode()); + if (!bSetting) { + pValue->SetInteger(occur->GetMin()); + return; + } + occur->SetMin(pValue->ToInteger()); +} + +void CJX_Occur::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Occur::initial(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Occur::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_occur.h b/fxjs/xfa/cjx_occur.h new file mode 100644 index 0000000000000000000000000000000000000000..fe174238ec1d81888305df806259de7644e55b98 --- /dev/null +++ b/fxjs/xfa/cjx_occur.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_OCCUR_H_ +#define FXJS_XFA_CJX_OCCUR_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Occur; + +class CJX_Occur : public CJX_Node { + public: + explicit CJX_Occur(CXFA_Occur* node); + ~CJX_Occur() override; + + JS_PROP(initial); + JS_PROP(max); + JS_PROP(min); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_OCCUR_H_ diff --git a/fxjs/xfa/cjx_oid.cpp b/fxjs/xfa/cjx_oid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1320f8df7eef053ebaea0ec08fc656debf73b49f --- /dev/null +++ b/fxjs/xfa/cjx_oid.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_oid.h" + +#include "xfa/fxfa/parser/cxfa_oid.h" + +CJX_Oid::CJX_Oid(CXFA_Oid* node) : CJX_TextNode(node) {} + +CJX_Oid::~CJX_Oid() = default; + +void CJX_Oid::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Oid::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_oid.h b/fxjs/xfa/cjx_oid.h new file mode 100644 index 0000000000000000000000000000000000000000..2578388c2f4679a61041e6385edc3f721deeecca --- /dev/null +++ b/fxjs/xfa/cjx_oid.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_OID_H_ +#define FXJS_XFA_CJX_OID_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Oid; + +class CJX_Oid : public CJX_TextNode { + public: + explicit CJX_Oid(CXFA_Oid* node); + ~CJX_Oid() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_OID_H_ diff --git a/fxjs/xfa/cjx_oids.cpp b/fxjs/xfa/cjx_oids.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a00697479bbcf0ba29606d58389cf218fd212656 --- /dev/null +++ b/fxjs/xfa/cjx_oids.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_oids.h" + +#include "xfa/fxfa/parser/cxfa_oids.h" + +CJX_Oids::CJX_Oids(CXFA_Oids* node) : CJX_Node(node) {} + +CJX_Oids::~CJX_Oids() = default; + +void CJX_Oids::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Oids::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Oids::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_oids.h b/fxjs/xfa/cjx_oids.h new file mode 100644 index 0000000000000000000000000000000000000000..9951206420016f9969303d003b9cb1f72a25458a --- /dev/null +++ b/fxjs/xfa/cjx_oids.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_OIDS_H_ +#define FXJS_XFA_CJX_OIDS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Oids; + +class CJX_Oids : public CJX_Node { + public: + explicit CJX_Oids(CXFA_Oids* node); + ~CJX_Oids() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_OIDS_H_ diff --git a/fxjs/xfa/cjx_operation.cpp b/fxjs/xfa/cjx_operation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb412bd71f63d0f4052da767557e1e83bf788e0b --- /dev/null +++ b/fxjs/xfa/cjx_operation.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_operation.h" + +#include "xfa/fxfa/parser/cxfa_operation.h" + +CJX_Operation::CJX_Operation(CXFA_Operation* node) : CJX_TextNode(node) {} + +CJX_Operation::~CJX_Operation() = default; + +void CJX_Operation::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Operation::output(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Operation::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Operation::input(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_operation.h b/fxjs/xfa/cjx_operation.h new file mode 100644 index 0000000000000000000000000000000000000000..b32ea6259429d818cd7316eb887feac66b6a6834 --- /dev/null +++ b/fxjs/xfa/cjx_operation.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_OPERATION_H_ +#define FXJS_XFA_CJX_OPERATION_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Operation; + +class CJX_Operation : public CJX_TextNode { + public: + explicit CJX_Operation(CXFA_Operation* node); + ~CJX_Operation() override; + + JS_PROP(input); + JS_PROP(output); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_OPERATION_H_ diff --git a/fxjs/xfa/cjx_overflow.cpp b/fxjs/xfa/cjx_overflow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6572d4e7c99dda9525fe438980ccdea11f369f5 --- /dev/null +++ b/fxjs/xfa/cjx_overflow.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_overflow.h" + +#include "xfa/fxfa/parser/cxfa_overflow.h" + +CJX_Overflow::CJX_Overflow(CXFA_Overflow* node) : CJX_Node(node) {} + +CJX_Overflow::~CJX_Overflow() = default; + +void CJX_Overflow::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Overflow::trailer(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Overflow::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Overflow::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Overflow::leader(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_overflow.h b/fxjs/xfa/cjx_overflow.h new file mode 100644 index 0000000000000000000000000000000000000000..c4f94b85991e6e4a7b68318958185474152ed660 --- /dev/null +++ b/fxjs/xfa/cjx_overflow.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_OVERFLOW_H_ +#define FXJS_XFA_CJX_OVERFLOW_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Overflow; + +class CJX_Overflow : public CJX_Node { + public: + explicit CJX_Overflow(CXFA_Overflow* node); + ~CJX_Overflow() override; + + JS_PROP(leader); + JS_PROP(target); + JS_PROP(trailer); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_OVERFLOW_H_ diff --git a/fxjs/xfa/cjx_packet.cpp b/fxjs/xfa/cjx_packet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fdebe626ab19cca610b6d4ed4005412654bed948 --- /dev/null +++ b/fxjs/xfa/cjx_packet.cpp @@ -0,0 +1,91 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_packet.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_packet.h" + +const CJX_MethodSpec CJX_Packet::MethodSpecs[] = { + {"getAttribute", getAttribute_static}, + {"removeAttribute", removeAttribute_static}, + {"setAttribute", setAttribute_static}}; + +CJX_Packet::CJX_Packet(CXFA_Packet* packet) : CJX_Node(packet) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Packet::~CJX_Packet() {} + +CJS_Return CJX_Packet::getAttribute( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString attributeValue; + CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode(); + if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) { + attributeValue = static_cast(pXMLNode)->GetString( + runtime->ToWideString(params[0]).c_str()); + } + return CJS_Return( + runtime->NewString(attributeValue.UTF8Encode().AsStringView())); +} + +CJS_Return CJX_Packet::setAttribute( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode(); + if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) { + static_cast(pXMLNode)->SetString( + runtime->ToWideString(params[1]), runtime->ToWideString(params[0])); + } + return CJS_Return(runtime->NewNull()); +} + +CJS_Return CJX_Packet::removeAttribute( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode(); + if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) { + WideString name = runtime->ToWideString(params[0]); + CFX_XMLElement* pXMLElement = static_cast(pXMLNode); + if (pXMLElement->HasAttribute(name.c_str())) + pXMLElement->RemoveAttribute(name.c_str()); + } + return CJS_Return(runtime->NewNull()); +} + +void CJX_Packet::content(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode(); + if (bSetting) { + if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = static_cast(pXMLNode); + pXMLElement->SetTextData(pValue->ToWideString()); + } + return; + } + + WideString wsTextData; + if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = static_cast(pXMLNode); + wsTextData = pXMLElement->GetTextData(); + } + + pValue->SetString(wsTextData.UTF8Encode().AsStringView()); +} diff --git a/fxjs/xfa/cjx_packet.h b/fxjs/xfa/cjx_packet.h new file mode 100644 index 0000000000000000000000000000000000000000..ac1c170fdd76780b982b0f0218b5575249573b94 --- /dev/null +++ b/fxjs/xfa/cjx_packet.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PACKET_H_ +#define FXJS_XFA_CJX_PACKET_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Packet; + +class CJX_Packet : public CJX_Node { + public: + explicit CJX_Packet(CXFA_Packet* packet); + ~CJX_Packet() override; + + JS_METHOD(getAttribute, CJX_Packet); + JS_METHOD(removeAttribute, CJX_Packet); + JS_METHOD(setAttribute, CJX_Packet); + + JS_PROP(content); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_PACKET_H_ diff --git a/fxjs/xfa/cjx_pagearea.cpp b/fxjs/xfa/cjx_pagearea.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4085d38798cb5644ce9aad47b93abadc975b4122 --- /dev/null +++ b/fxjs/xfa/cjx_pagearea.cpp @@ -0,0 +1,61 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_pagearea.h" + +#include "xfa/fxfa/parser/cxfa_pagearea.h" + +CJX_PageArea::CJX_PageArea(CXFA_PageArea* node) : CJX_Container(node) {} + +CJX_PageArea::~CJX_PageArea() = default; + +void CJX_PageArea::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::pagePosition(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::oddOrEven(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::initialNumber(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::numbered(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageArea::blankOrNotBlank(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_pagearea.h b/fxjs/xfa/cjx_pagearea.h new file mode 100644 index 0000000000000000000000000000000000000000..8935fa63624c892661b3d2476233e70afcef0f88 --- /dev/null +++ b/fxjs/xfa/cjx_pagearea.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PAGEAREA_H_ +#define FXJS_XFA_CJX_PAGEAREA_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_PageArea; + +class CJX_PageArea : public CJX_Container { + public: + explicit CJX_PageArea(CXFA_PageArea* node); + ~CJX_PageArea() override; + + JS_PROP(blankOrNotBlank); + JS_PROP(initialNumber); + JS_PROP(numbered); + JS_PROP(oddOrEven); + JS_PROP(pagePosition); + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_PAGEAREA_H_ diff --git a/fxjs/xfa/cjx_pageset.cpp b/fxjs/xfa/cjx_pageset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfab7904edae3f337caa4225db36e6ffe42c367c --- /dev/null +++ b/fxjs/xfa/cjx_pageset.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_pageset.h" + +#include "xfa/fxfa/parser/cxfa_pageset.h" + +CJX_PageSet::CJX_PageSet(CXFA_PageSet* node) : CJX_Container(node) {} + +CJX_PageSet::~CJX_PageSet() = default; + +void CJX_PageSet::relation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageSet::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageSet::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PageSet::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_pageset.h b/fxjs/xfa/cjx_pageset.h new file mode 100644 index 0000000000000000000000000000000000000000..7e0ab17443a7bc64cd766ae4383f61e8f095ae13 --- /dev/null +++ b/fxjs/xfa/cjx_pageset.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PAGESET_H_ +#define FXJS_XFA_CJX_PAGESET_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_PageSet; + +class CJX_PageSet : public CJX_Container { + public: + explicit CJX_PageSet(CXFA_PageSet* node); + ~CJX_PageSet() override; + + JS_PROP(relation); + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_PAGESET_H_ diff --git a/fxjs/xfa/cjx_para.cpp b/fxjs/xfa/cjx_para.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a12e4736ffcc3735e15b62aab7f45e9eb1a3d23 --- /dev/null +++ b/fxjs/xfa/cjx_para.cpp @@ -0,0 +1,97 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_para.h" + +#include "xfa/fxfa/parser/cxfa_para.h" + +CJX_Para::CJX_Para(CXFA_Para* node) : CJX_Node(node) {} + +CJX_Para::~CJX_Para() = default; + +void CJX_Para::hAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::textIndent(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::marginRight(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::marginLeft(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::radixOffset(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::preserve(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::spaceBelow(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::vAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::tabDefault(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::tabStops(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::lineHeight(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Para::spaceAbove(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_para.h b/fxjs/xfa/cjx_para.h new file mode 100644 index 0000000000000000000000000000000000000000..6bf2841cf9948f10ab06acfd3f1b66590e8a2379 --- /dev/null +++ b/fxjs/xfa/cjx_para.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PARA_H_ +#define FXJS_XFA_CJX_PARA_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Para; + +class CJX_Para : public CJX_Node { + public: + explicit CJX_Para(CXFA_Para* node); + ~CJX_Para() override; + + JS_PROP(hAlign); + JS_PROP(lineHeight); + JS_PROP(marginLeft); + JS_PROP(marginRight); + JS_PROP(preserve); + JS_PROP(radixOffset); + JS_PROP(spaceAbove); + JS_PROP(spaceBelow); + JS_PROP(tabDefault); + JS_PROP(tabStops); + JS_PROP(textIndent); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(vAlign); +}; + +#endif // FXJS_XFA_CJX_PARA_H_ diff --git a/fxjs/xfa/cjx_password.cpp b/fxjs/xfa/cjx_password.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a44354beecf56b708530371b078c11ed4d66551d --- /dev/null +++ b/fxjs/xfa/cjx_password.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_password.h" + +#include "xfa/fxfa/parser/cxfa_password.h" + +CJX_Password::CJX_Password(CXFA_Password* node) : CJX_TextNode(node) {} + +CJX_Password::~CJX_Password() = default; + +void CJX_Password::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Password::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_password.h b/fxjs/xfa/cjx_password.h new file mode 100644 index 0000000000000000000000000000000000000000..ede93cc5ab57511ad0ef9aba53ba30d205fd37c4 --- /dev/null +++ b/fxjs/xfa/cjx_password.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PASSWORD_H_ +#define FXJS_XFA_CJX_PASSWORD_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Password; + +class CJX_Password : public CJX_TextNode { + public: + explicit CJX_Password(CXFA_Password* node); + ~CJX_Password() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_PASSWORD_H_ diff --git a/fxjs/xfa/cjx_passwordedit.cpp b/fxjs/xfa/cjx_passwordedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b1c591a7a5e0d599d4e98924c83f07adf3a8b88 --- /dev/null +++ b/fxjs/xfa/cjx_passwordedit.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_passwordedit.h" + +#include "xfa/fxfa/parser/cxfa_passwordedit.h" + +CJX_PasswordEdit::CJX_PasswordEdit(CXFA_PasswordEdit* node) : CJX_Node(node) {} + +CJX_PasswordEdit::~CJX_PasswordEdit() = default; + +void CJX_PasswordEdit::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PasswordEdit::passwordChar(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PasswordEdit::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_PasswordEdit::hScrollPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_passwordedit.h b/fxjs/xfa/cjx_passwordedit.h new file mode 100644 index 0000000000000000000000000000000000000000..e4a5fcb9e5d911775c8277c74a88faac1ae00f6b --- /dev/null +++ b/fxjs/xfa/cjx_passwordedit.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PASSWORDEDIT_H_ +#define FXJS_XFA_CJX_PASSWORDEDIT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_PasswordEdit; + +class CJX_PasswordEdit : public CJX_Node { + public: + explicit CJX_PasswordEdit(CXFA_PasswordEdit* node); + ~CJX_PasswordEdit() override; + + JS_PROP(hScrollPolicy); + JS_PROP(passwordChar); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_PASSWORDEDIT_H_ diff --git a/fxjs/xfa/cjx_pattern.cpp b/fxjs/xfa/cjx_pattern.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5acaa84f1435bc81720d239b78e1ad2dd77df819 --- /dev/null +++ b/fxjs/xfa/cjx_pattern.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_pattern.h" + +#include "xfa/fxfa/parser/cxfa_pattern.h" + +CJX_Pattern::CJX_Pattern(CXFA_Pattern* node) : CJX_Node(node) {} + +CJX_Pattern::~CJX_Pattern() = default; + +void CJX_Pattern::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Pattern::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Pattern::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_pattern.h b/fxjs/xfa/cjx_pattern.h new file mode 100644 index 0000000000000000000000000000000000000000..81754b8ebc84a2ddf1d3c3c6fdc53742f444f42e --- /dev/null +++ b/fxjs/xfa/cjx_pattern.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PATTERN_H_ +#define FXJS_XFA_CJX_PATTERN_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Pattern; + +class CJX_Pattern : public CJX_Node { + public: + explicit CJX_Pattern(CXFA_Pattern* node); + ~CJX_Pattern() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_PATTERN_H_ diff --git a/fxjs/xfa/cjx_picture.cpp b/fxjs/xfa/cjx_picture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81f5ec41f74c50fec26ce3ac0fc6e19e0907e1b0 --- /dev/null +++ b/fxjs/xfa/cjx_picture.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_picture.h" + +#include "xfa/fxfa/parser/cxfa_picture.h" + +CJX_Picture::CJX_Picture(CXFA_Picture* node) : CJX_Node(node) {} + +CJX_Picture::~CJX_Picture() = default; + +void CJX_Picture::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Picture::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Picture::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Picture::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_picture.h b/fxjs/xfa/cjx_picture.h new file mode 100644 index 0000000000000000000000000000000000000000..25497c3313e93cb364e91dc28fe5fdd18df3271c --- /dev/null +++ b/fxjs/xfa/cjx_picture.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_PICTURE_H_ +#define FXJS_XFA_CJX_PICTURE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Picture; + +class CJX_Picture : public CJX_Node { + public: + explicit CJX_Picture(CXFA_Picture* node); + ~CJX_Picture() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_PICTURE_H_ diff --git a/fxjs/xfa/cjx_query.cpp b/fxjs/xfa/cjx_query.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6f255fd129cb441891d2207c47f51d267679018 --- /dev/null +++ b/fxjs/xfa/cjx_query.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_query.h" + +#include "xfa/fxfa/parser/cxfa_query.h" + +CJX_Query::CJX_Query(CXFA_Query* node) : CJX_Node(node) {} + +CJX_Query::~CJX_Query() = default; + +void CJX_Query::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Query::commandType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Query::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_query.h b/fxjs/xfa/cjx_query.h new file mode 100644 index 0000000000000000000000000000000000000000..1057fa20403b0c2b7977ee144eb1dc53427c3cb3 --- /dev/null +++ b/fxjs/xfa/cjx_query.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_QUERY_H_ +#define FXJS_XFA_CJX_QUERY_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Query; + +class CJX_Query : public CJX_Node { + public: + explicit CJX_Query(CXFA_Query* node); + ~CJX_Query() override; + + JS_PROP(commandType); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_QUERY_H_ diff --git a/fxjs/xfa/cjx_radial.cpp b/fxjs/xfa/cjx_radial.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd8b1a207b72e974c14e8c1f3a16df1cfd122d80 --- /dev/null +++ b/fxjs/xfa/cjx_radial.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_radial.h" + +#include "xfa/fxfa/parser/cxfa_radial.h" + +CJX_Radial::CJX_Radial(CXFA_Radial* node) : CJX_Node(node) {} + +CJX_Radial::~CJX_Radial() = default; + +void CJX_Radial::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Radial::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Radial::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_radial.h b/fxjs/xfa/cjx_radial.h new file mode 100644 index 0000000000000000000000000000000000000000..30737976e5ec7e91b58c5ae0bcd24cdf6a4af085 --- /dev/null +++ b/fxjs/xfa/cjx_radial.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_RADIAL_H_ +#define FXJS_XFA_CJX_RADIAL_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Radial; + +class CJX_Radial : public CJX_Node { + public: + explicit CJX_Radial(CXFA_Radial* node); + ~CJX_Radial() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_RADIAL_H_ diff --git a/fxjs/xfa/cjx_reason.cpp b/fxjs/xfa/cjx_reason.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9bb6c3d5d1b1664133ec39733047886ec548a14 --- /dev/null +++ b/fxjs/xfa/cjx_reason.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_reason.h" + +#include "xfa/fxfa/parser/cxfa_reason.h" + +CJX_Reason::CJX_Reason(CXFA_Reason* node) : CJX_TextNode(node) {} + +CJX_Reason::~CJX_Reason() = default; + +void CJX_Reason::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Reason::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_reason.h b/fxjs/xfa/cjx_reason.h new file mode 100644 index 0000000000000000000000000000000000000000..465cedecbc523b6b7c5adaf5bd574cb516f930e2 --- /dev/null +++ b/fxjs/xfa/cjx_reason.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_REASON_H_ +#define FXJS_XFA_CJX_REASON_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Reason; + +class CJX_Reason : public CJX_TextNode { + public: + explicit CJX_Reason(CXFA_Reason* node); + ~CJX_Reason() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_REASON_H_ diff --git a/fxjs/xfa/cjx_reasons.cpp b/fxjs/xfa/cjx_reasons.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11a986812a7ad7a043d55f731b967e1511261729 --- /dev/null +++ b/fxjs/xfa/cjx_reasons.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_reasons.h" + +#include "xfa/fxfa/parser/cxfa_reasons.h" + +CJX_Reasons::CJX_Reasons(CXFA_Reasons* node) : CJX_Node(node) {} + +CJX_Reasons::~CJX_Reasons() = default; + +void CJX_Reasons::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Reasons::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Reasons::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_reasons.h b/fxjs/xfa/cjx_reasons.h new file mode 100644 index 0000000000000000000000000000000000000000..a5da62ab3ebe97ddf432d5739d92663b61b075ea --- /dev/null +++ b/fxjs/xfa/cjx_reasons.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_REASONS_H_ +#define FXJS_XFA_CJX_REASONS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Reasons; + +class CJX_Reasons : public CJX_Node { + public: + explicit CJX_Reasons(CXFA_Reasons* node); + ~CJX_Reasons() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_REASONS_H_ diff --git a/fxjs/xfa/cjx_recordset.cpp b/fxjs/xfa/cjx_recordset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4fe21f60cb32ee3cab34d3d1a83d0099cdcaf48 --- /dev/null +++ b/fxjs/xfa/cjx_recordset.cpp @@ -0,0 +1,63 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_recordset.h" + +#include + +#include "xfa/fxfa/parser/cxfa_recordset.h" + +CJX_RecordSet::CJX_RecordSet(CXFA_RecordSet* node) : CJX_Node(node) {} + +CJX_RecordSet::~CJX_RecordSet() = default; + +void CJX_RecordSet::max(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::eofAction(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::cursorType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::lockType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::bofAction(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RecordSet::cursorLocation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_recordset.h b/fxjs/xfa/cjx_recordset.h new file mode 100644 index 0000000000000000000000000000000000000000..7c34f6e4725540a82f5798b4a1154032f9f5782d --- /dev/null +++ b/fxjs/xfa/cjx_recordset.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_RECORDSET_H_ +#define FXJS_XFA_CJX_RECORDSET_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_RecordSet; + +class CJX_RecordSet : public CJX_Node { + public: + explicit CJX_RecordSet(CXFA_RecordSet* node); + ~CJX_RecordSet() override; + + JS_PROP(bofAction); + JS_PROP(cursorLocation); + JS_PROP(cursorType); + JS_PROP(eofAction); + JS_PROP(lockType); + JS_PROP(max); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_RECORDSET_H_ diff --git a/fxjs/xfa/cjx_rectangle.cpp b/fxjs/xfa/cjx_rectangle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..155a29f935c9980555fdd34b7dcba50632a434e5 --- /dev/null +++ b/fxjs/xfa/cjx_rectangle.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_rectangle.h" + +#include "xfa/fxfa/parser/cxfa_rectangle.h" + +CJX_Rectangle::CJX_Rectangle(CXFA_Rectangle* node) : CJX_Node(node) {} + +CJX_Rectangle::~CJX_Rectangle() = default; + +void CJX_Rectangle::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Rectangle::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Rectangle::hand(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_rectangle.h b/fxjs/xfa/cjx_rectangle.h new file mode 100644 index 0000000000000000000000000000000000000000..c08f7a9eb150cb85fd969040e8caa8e34bb914c8 --- /dev/null +++ b/fxjs/xfa/cjx_rectangle.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_RECTANGLE_H_ +#define FXJS_XFA_CJX_RECTANGLE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Rectangle; + +class CJX_Rectangle : public CJX_Node { + public: + explicit CJX_Rectangle(CXFA_Rectangle* node); + ~CJX_Rectangle() override; + + JS_PROP(hand); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_RECTANGLE_H_ diff --git a/fxjs/xfa/cjx_ref.cpp b/fxjs/xfa/cjx_ref.cpp new file mode 100644 index 0000000000000000000000000000000000000000..593081533434eee4f00c977e272aadf912b21c4b --- /dev/null +++ b/fxjs/xfa/cjx_ref.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_ref.h" + +#include "xfa/fxfa/parser/cxfa_ref.h" + +CJX_Ref::CJX_Ref(CXFA_Ref* node) : CJX_TextNode(node) {} + +CJX_Ref::~CJX_Ref() = default; + +void CJX_Ref::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Ref::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_ref.h b/fxjs/xfa/cjx_ref.h new file mode 100644 index 0000000000000000000000000000000000000000..4366282eede905f893fcf2cf8b8fe1feedc40cf6 --- /dev/null +++ b/fxjs/xfa/cjx_ref.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_REF_H_ +#define FXJS_XFA_CJX_REF_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Ref; + +class CJX_Ref : public CJX_TextNode { + public: + explicit CJX_Ref(CXFA_Ref* node); + ~CJX_Ref() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_REF_H_ diff --git a/fxjs/xfa/cjx_rootelement.cpp b/fxjs/xfa/cjx_rootelement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31fbb006b62fbcf8ce88e36e9d31c71ec0b29b4f --- /dev/null +++ b/fxjs/xfa/cjx_rootelement.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_rootelement.h" + +#include "xfa/fxfa/parser/cxfa_rootelement.h" + +CJX_RootElement::CJX_RootElement(CXFA_RootElement* node) : CJX_TextNode(node) {} + +CJX_RootElement::~CJX_RootElement() = default; + +void CJX_RootElement::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_RootElement::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_rootelement.h b/fxjs/xfa/cjx_rootelement.h new file mode 100644 index 0000000000000000000000000000000000000000..40790df64ec729ae189b0e161b51ed6b3cbb8bfc --- /dev/null +++ b/fxjs/xfa/cjx_rootelement.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_ROOTELEMENT_H_ +#define FXJS_XFA_CJX_ROOTELEMENT_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_RootElement; + +class CJX_RootElement : public CJX_TextNode { + public: + explicit CJX_RootElement(CXFA_RootElement* node); + ~CJX_RootElement() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_ROOTELEMENT_H_ diff --git a/fxjs/xfa/cjx_script.cpp b/fxjs/xfa/cjx_script.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4016c137aff267b1e2115fdf08108a6cca1e6e72 --- /dev/null +++ b/fxjs/xfa/cjx_script.cpp @@ -0,0 +1,66 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_script.h" + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cxfa_script.h" + +CJX_Script::CJX_Script(CXFA_Script* node) : CJX_Node(node) {} + +CJX_Script::~CJX_Script() = default; + +void CJX_Script::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Script::contentType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Script::runAt(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Script::stateless(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetString(FX_UTF8Encode(WideStringView(L"0", 1)).AsStringView()); +} + +void CJX_Script::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Script::binding(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Script::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Script::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + defaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_script.h b/fxjs/xfa/cjx_script.h new file mode 100644 index 0000000000000000000000000000000000000000..ad5f99418db9dff53bab1bd567f751303ec9720d --- /dev/null +++ b/fxjs/xfa/cjx_script.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SCRIPT_H_ +#define FXJS_XFA_CJX_SCRIPT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Script; + +class CJX_Script : public CJX_Node { + public: + explicit CJX_Script(CXFA_Script* node); + ~CJX_Script() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(binding); + JS_PROP(contentType); + JS_PROP(runAt); + JS_PROP(stateless); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_SCRIPT_H_ diff --git a/fxjs/xfa/cjx_select.cpp b/fxjs/xfa/cjx_select.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1cb25992eda6a63acafb2f6c7a2332d1ad48b4e --- /dev/null +++ b/fxjs/xfa/cjx_select.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_select.h" + +#include "xfa/fxfa/parser/cxfa_select.h" + +CJX_Select::CJX_Select(CXFA_Select* node) : CJX_TextNode(node) {} + +CJX_Select::~CJX_Select() = default; + +void CJX_Select::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Select::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_select.h b/fxjs/xfa/cjx_select.h new file mode 100644 index 0000000000000000000000000000000000000000..334c003f2dd49be348bd31566a0d47598280c154 --- /dev/null +++ b/fxjs/xfa/cjx_select.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SELECT_H_ +#define FXJS_XFA_CJX_SELECT_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Select; + +class CJX_Select : public CJX_TextNode { + public: + explicit CJX_Select(CXFA_Select* node); + ~CJX_Select() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SELECT_H_ diff --git a/fxjs/xfa/cjx_setproperty.cpp b/fxjs/xfa/cjx_setproperty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..871fc4decea39a6d2db487d2e5cec2bf6a05eb06 --- /dev/null +++ b/fxjs/xfa/cjx_setproperty.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_setproperty.h" + +#include "xfa/fxfa/parser/cxfa_setproperty.h" + +CJX_SetProperty::CJX_SetProperty(CXFA_SetProperty* node) : CJX_Node(node) {} + +CJX_SetProperty::~CJX_SetProperty() = default; + +void CJX_SetProperty::connection(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SetProperty::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_setproperty.h b/fxjs/xfa/cjx_setproperty.h new file mode 100644 index 0000000000000000000000000000000000000000..9929fefeb70c55a4bbd7b32f170a594a93a17825 --- /dev/null +++ b/fxjs/xfa/cjx_setproperty.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SETPROPERTY_H_ +#define FXJS_XFA_CJX_SETPROPERTY_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_SetProperty; + +class CJX_SetProperty : public CJX_Node { + public: + explicit CJX_SetProperty(CXFA_SetProperty* node); + ~CJX_SetProperty() override; + + JS_PROP(connection); + JS_PROP(target); +}; + +#endif // FXJS_XFA_CJX_SETPROPERTY_H_ diff --git a/fxjs/xfa/cjx_signature.cpp b/fxjs/xfa/cjx_signature.cpp new file mode 100644 index 0000000000000000000000000000000000000000..912d9d871c7cbb214c7160f99f5d945bd3d407b2 --- /dev/null +++ b/fxjs/xfa/cjx_signature.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_signature.h" + +#include "xfa/fxfa/parser/cxfa_signature.h" + +CJX_Signature::CJX_Signature(CXFA_Signature* node) : CJX_Node(node) {} + +CJX_Signature::~CJX_Signature() = default; + +void CJX_Signature::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Signature::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_signature.h b/fxjs/xfa/cjx_signature.h new file mode 100644 index 0000000000000000000000000000000000000000..bed0b1a2b416247a215c1800bd6fa2db0f611802 --- /dev/null +++ b/fxjs/xfa/cjx_signature.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SIGNATURE_H_ +#define FXJS_XFA_CJX_SIGNATURE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Signature; + +class CJX_Signature : public CJX_Node { + public: + explicit CJX_Signature(CXFA_Signature* node); + ~CJX_Signature() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SIGNATURE_H_ diff --git a/fxjs/xfa/cjx_signatureproperties.cpp b/fxjs/xfa/cjx_signatureproperties.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f2e7a7fd0fa4da4ee5fecbbd930e32013302730 --- /dev/null +++ b/fxjs/xfa/cjx_signatureproperties.cpp @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_signatureproperties.h" + +#include "xfa/fxfa/parser/cxfa_signatureproperties.h" + +CJX_SignatureProperties::CJX_SignatureProperties(CXFA_SignatureProperties* node) + : CJX_Node(node) {} + +CJX_SignatureProperties::~CJX_SignatureProperties() = default; + +void CJX_SignatureProperties::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SignatureProperties::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_signatureproperties.h b/fxjs/xfa/cjx_signatureproperties.h new file mode 100644 index 0000000000000000000000000000000000000000..ffd47a3dc6ad5bd9cfd33558d3b12106b06a75ef --- /dev/null +++ b/fxjs/xfa/cjx_signatureproperties.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SIGNATUREPROPERTIES_H_ +#define FXJS_XFA_CJX_SIGNATUREPROPERTIES_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_SignatureProperties; + +/* Deprecated */ +class CJX_SignatureProperties : public CJX_Node { + public: + explicit CJX_SignatureProperties(CXFA_SignatureProperties* node); + ~CJX_SignatureProperties() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SIGNATUREPROPERTIES_H_ diff --git a/fxjs/xfa/cjx_signaturepseudomodel.cpp b/fxjs/xfa/cjx_signaturepseudomodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..202532c6ca76a07a3ce0f30489b1daf074b4dbf3 --- /dev/null +++ b/fxjs/xfa/cjx_signaturepseudomodel.cpp @@ -0,0 +1,59 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_signaturepseudomodel.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cscript_signaturepseudomodel.h" + +const CJX_MethodSpec CJX_SignaturePseudoModel::MethodSpecs[] = { + {"verify", verifySignature_static}, + {"sign", sign_static}, + {"enumerate", enumerate_static}, + {"clear", clear_static}}; + +CJX_SignaturePseudoModel::CJX_SignaturePseudoModel( + CScript_SignaturePseudoModel* model) + : CJX_Object(model) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_SignaturePseudoModel::~CJX_SignaturePseudoModel() {} + +CJS_Return CJX_SignaturePseudoModel::verifySignature( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 4) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewNumber(0)); +} + +CJS_Return CJX_SignaturePseudoModel::sign( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() < 3 || params.size() > 7) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewBoolean(false)); +} + +CJS_Return CJX_SignaturePseudoModel::enumerate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_SignaturePseudoModel::clear( + CJS_V8* runtime, + const std::vector>& params) { + if (params.empty() || params.size() > 2) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewBoolean(false)); +} diff --git a/fxjs/xfa/cjx_signaturepseudomodel.h b/fxjs/xfa/cjx_signaturepseudomodel.h new file mode 100644 index 0000000000000000000000000000000000000000..88f90fb33a19aa20231e519dab3bb0c734f5afa9 --- /dev/null +++ b/fxjs/xfa/cjx_signaturepseudomodel.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SIGNATUREPSEUDOMODEL_H_ +#define FXJS_XFA_CJX_SIGNATUREPSEUDOMODEL_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CScript_SignaturePseudoModel; + +class CJX_SignaturePseudoModel : public CJX_Object { + public: + explicit CJX_SignaturePseudoModel(CScript_SignaturePseudoModel* model); + ~CJX_SignaturePseudoModel() override; + + JS_METHOD(verifySignature /*verify*/, CJX_SignaturePseudoModel); + JS_METHOD(sign, CJX_SignaturePseudoModel); + JS_METHOD(enumerate, CJX_SignaturePseudoModel); + JS_METHOD(clear, CJX_SignaturePseudoModel); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_SIGNATUREPSEUDOMODEL_H_ diff --git a/fxjs/xfa/cjx_signdata.cpp b/fxjs/xfa/cjx_signdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eca7430d171d7d37a45533368eeaaaaf8c401bcd --- /dev/null +++ b/fxjs/xfa/cjx_signdata.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_signdata.h" + +#include "xfa/fxfa/parser/cxfa_signdata.h" + +CJX_SignData::CJX_SignData(CXFA_SignData* node) : CJX_Node(node) {} + +CJX_SignData::~CJX_SignData() = default; + +void CJX_SignData::ref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SignData::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SignData::operation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SignData::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SignData::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_signdata.h b/fxjs/xfa/cjx_signdata.h new file mode 100644 index 0000000000000000000000000000000000000000..7d9b1755ffa60cd12d9959a3a07cefa9f529e2fd --- /dev/null +++ b/fxjs/xfa/cjx_signdata.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SIGNDATA_H_ +#define FXJS_XFA_CJX_SIGNDATA_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_SignData; + +class CJX_SignData : public CJX_Node { + public: + explicit CJX_SignData(CXFA_SignData* node); + ~CJX_SignData() override; + + JS_PROP(operation); + JS_PROP(ref); + JS_PROP(target); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SIGNDATA_H_ diff --git a/fxjs/xfa/cjx_signing.cpp b/fxjs/xfa/cjx_signing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..378f7253305bb75e4cd389557d4db76ec6ca0e4d --- /dev/null +++ b/fxjs/xfa/cjx_signing.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_signing.h" + +#include "xfa/fxfa/parser/cxfa_signing.h" + +CJX_Signing::CJX_Signing(CXFA_Signing* node) : CJX_Node(node) {} + +CJX_Signing::~CJX_Signing() = default; + +void CJX_Signing::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Signing::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Signing::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_signing.h b/fxjs/xfa/cjx_signing.h new file mode 100644 index 0000000000000000000000000000000000000000..8b355097c7b57bc69478ff7a2329beece335e6c2 --- /dev/null +++ b/fxjs/xfa/cjx_signing.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SIGNING_H_ +#define FXJS_XFA_CJX_SIGNING_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Signing; + +class CJX_Signing : public CJX_Node { + public: + explicit CJX_Signing(CXFA_Signing* node); + ~CJX_Signing() override; + + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SIGNING_H_ diff --git a/fxjs/xfa/cjx_soapaction.cpp b/fxjs/xfa/cjx_soapaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..854d2d78a725174e8ea8432812b9c2470d20960f --- /dev/null +++ b/fxjs/xfa/cjx_soapaction.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_soapaction.h" + +#include "xfa/fxfa/parser/cxfa_soapaction.h" + +CJX_SoapAction::CJX_SoapAction(CXFA_SoapAction* node) : CJX_TextNode(node) {} + +CJX_SoapAction::~CJX_SoapAction() = default; + +void CJX_SoapAction::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SoapAction::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_soapaction.h b/fxjs/xfa/cjx_soapaction.h new file mode 100644 index 0000000000000000000000000000000000000000..efc90e4f6bd8a28307d6093ece5e0d4ccef3cd95 --- /dev/null +++ b/fxjs/xfa/cjx_soapaction.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SOAPACTION_H_ +#define FXJS_XFA_CJX_SOAPACTION_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_SoapAction; + +class CJX_SoapAction : public CJX_TextNode { + public: + explicit CJX_SoapAction(CXFA_SoapAction* node); + ~CJX_SoapAction() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SOAPACTION_H_ diff --git a/fxjs/xfa/cjx_soapaddress.cpp b/fxjs/xfa/cjx_soapaddress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be7e84cb4ca738b4b9fadcbc1e3b3ec40baf1d93 --- /dev/null +++ b/fxjs/xfa/cjx_soapaddress.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_soapaddress.h" + +#include "xfa/fxfa/parser/cxfa_soapaddress.h" + +CJX_SoapAddress::CJX_SoapAddress(CXFA_SoapAddress* node) : CJX_TextNode(node) {} + +CJX_SoapAddress::~CJX_SoapAddress() = default; + +void CJX_SoapAddress::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SoapAddress::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_soapaddress.h b/fxjs/xfa/cjx_soapaddress.h new file mode 100644 index 0000000000000000000000000000000000000000..3e6e0047157fb9a65760a0bc122adf1b7850c4db --- /dev/null +++ b/fxjs/xfa/cjx_soapaddress.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SOAPADDRESS_H_ +#define FXJS_XFA_CJX_SOAPADDRESS_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_SoapAddress; + +class CJX_SoapAddress : public CJX_TextNode { + public: + explicit CJX_SoapAddress(CXFA_SoapAddress* node); + ~CJX_SoapAddress() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SOAPADDRESS_H_ diff --git a/fxjs/xfa/cjx_solid.cpp b/fxjs/xfa/cjx_solid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e692153ec6b9245b7eee28a896cb985c2879142d --- /dev/null +++ b/fxjs/xfa/cjx_solid.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_solid.h" + +#include "xfa/fxfa/parser/cxfa_solid.h" + +CJX_Solid::CJX_Solid(CXFA_Solid* node) : CJX_Node(node) {} + +CJX_Solid::~CJX_Solid() = default; + +void CJX_Solid::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Solid::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_solid.h b/fxjs/xfa/cjx_solid.h new file mode 100644 index 0000000000000000000000000000000000000000..3b8dd5eb631dd768f3bf1b18c42e640ff8a6cef0 --- /dev/null +++ b/fxjs/xfa/cjx_solid.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SOLID_H_ +#define FXJS_XFA_CJX_SOLID_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Solid; + +class CJX_Solid : public CJX_Node { + public: + explicit CJX_Solid(CXFA_Solid* node); + ~CJX_Solid() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SOLID_H_ diff --git a/fxjs/xfa/cjx_source.cpp b/fxjs/xfa/cjx_source.cpp new file mode 100644 index 0000000000000000000000000000000000000000..399a6c3664ae49510cb395b668fe256a7ec79380 --- /dev/null +++ b/fxjs/xfa/cjx_source.cpp @@ -0,0 +1,179 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_source.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_source.h" + +const CJX_MethodSpec CJX_Source::MethodSpecs[] = { + {"addNew", addNew_static}, + {"cancel", cancel_static}, + {"cancelBatch", cancelBatch_static}, + {"close", close_static}, + {"delete", deleteItem_static}, + {"first", first_static}, + {"hasDataChanged", hasDataChanged_static}, + {"isBOF", isBOF_static}, + {"isEOF", isEOF_static}, + {"last", last_static}, + {"next", next_static}, + {"open", open_static}, + {"previous", previous_static}, + {"requery", requery_static}, + {"resync", resync_static}, + {"update", update_static}, + {"updateBatch", updateBatch_static}}; + +CJX_Source::CJX_Source(CXFA_Source* src) : CJX_Node(src) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Source::~CJX_Source() {} + +CJS_Return CJX_Source::next(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::cancelBatch( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::first(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::updateBatch( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::previous( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::isBOF(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::isEOF(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::cancel(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::update(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::open(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::deleteItem( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::addNew(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::requery( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::resync(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::close(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::last(CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +CJS_Return CJX_Source::hasDataChanged( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(true); +} + +void CJX_Source::db(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) {} + +void CJX_Source::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Source::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_source.h b/fxjs/xfa/cjx_source.h new file mode 100644 index 0000000000000000000000000000000000000000..de84912910b8ab92cc3765501971d118e079dd18 --- /dev/null +++ b/fxjs/xfa/cjx_source.h @@ -0,0 +1,46 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SOURCE_H_ +#define FXJS_XFA_CJX_SOURCE_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Source; + +class CJX_Source : public CJX_Node { + public: + explicit CJX_Source(CXFA_Source* src); + ~CJX_Source() override; + + JS_METHOD(addNew, CJX_Source); + JS_METHOD(cancel, CJX_Source); + JS_METHOD(cancelBatch, CJX_Source); + JS_METHOD(close, CJX_Source); + JS_METHOD(deleteItem /*delete*/, CJX_Source); + JS_METHOD(first, CJX_Source); + JS_METHOD(hasDataChanged, CJX_Source); + JS_METHOD(isBOF, CJX_Source); + JS_METHOD(isEOF, CJX_Source); + JS_METHOD(last, CJX_Source); + JS_METHOD(next, CJX_Source); + JS_METHOD(open, CJX_Source); + JS_METHOD(previous, CJX_Source); + JS_METHOD(requery, CJX_Source); + JS_METHOD(resync, CJX_Source); + JS_METHOD(update, CJX_Source); + JS_METHOD(updateBatch, CJX_Source); + + JS_PROP(db); + JS_PROP(use); + JS_PROP(usehref); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_SOURCE_H_ diff --git a/fxjs/xfa/cjx_sourceset.cpp b/fxjs/xfa/cjx_sourceset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5bfabdea628d6f11634d6e5d407cf51b57b23b28 --- /dev/null +++ b/fxjs/xfa/cjx_sourceset.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_sourceset.h" + +#include "xfa/fxfa/parser/cxfa_sourceset.h" + +CJX_SourceSet::CJX_SourceSet(CXFA_SourceSet* node) : CJX_Model(node) {} + +CJX_SourceSet::~CJX_SourceSet() = default; + +void CJX_SourceSet::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SourceSet::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_sourceset.h b/fxjs/xfa/cjx_sourceset.h new file mode 100644 index 0000000000000000000000000000000000000000..de4ac68bed851418ddf4ba5beb1258d9b46bffbc --- /dev/null +++ b/fxjs/xfa/cjx_sourceset.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SOURCESET_H_ +#define FXJS_XFA_CJX_SOURCESET_H_ + +#include "fxjs/xfa/cjx_model.h" + +class CXFA_SourceSet; + +class CJX_SourceSet : public CJX_Model { + public: + explicit CJX_SourceSet(CXFA_SourceSet* node); + ~CJX_SourceSet() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SOURCESET_H_ diff --git a/fxjs/xfa/cjx_speak.cpp b/fxjs/xfa/cjx_speak.cpp new file mode 100644 index 0000000000000000000000000000000000000000..161b245439a5db7d3aaa29e3d404dba785d2d8e1 --- /dev/null +++ b/fxjs/xfa/cjx_speak.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_speak.h" + +#include "xfa/fxfa/parser/cxfa_speak.h" + +CJX_Speak::CJX_Speak(CXFA_Speak* node) : CJX_TextNode(node) {} + +CJX_Speak::~CJX_Speak() = default; + +void CJX_Speak::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Speak::priority(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Speak::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Speak::disable(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_speak.h b/fxjs/xfa/cjx_speak.h new file mode 100644 index 0000000000000000000000000000000000000000..56981054bc11db9a5548f31ce6fd04cd031c519c --- /dev/null +++ b/fxjs/xfa/cjx_speak.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SPEAK_H_ +#define FXJS_XFA_CJX_SPEAK_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Speak; + +class CJX_Speak : public CJX_TextNode { + public: + explicit CJX_Speak(CXFA_Speak* node); + ~CJX_Speak() override; + + JS_PROP(disable); + JS_PROP(priority); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SPEAK_H_ diff --git a/fxjs/xfa/cjx_stipple.cpp b/fxjs/xfa/cjx_stipple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae520c9ad990283f4fcd3a864d8fa99dcde2c089 --- /dev/null +++ b/fxjs/xfa/cjx_stipple.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_stipple.h" + +#include "xfa/fxfa/parser/cxfa_stipple.h" + +CJX_Stipple::CJX_Stipple(CXFA_Stipple* node) : CJX_Node(node) {} + +CJX_Stipple::~CJX_Stipple() = default; + +void CJX_Stipple::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Stipple::rate(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Stipple::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_stipple.h b/fxjs/xfa/cjx_stipple.h new file mode 100644 index 0000000000000000000000000000000000000000..68ddd83589b2d06f6cd1bd6f2de69d43dda8d6df --- /dev/null +++ b/fxjs/xfa/cjx_stipple.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_STIPPLE_H_ +#define FXJS_XFA_CJX_STIPPLE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Stipple; + +class CJX_Stipple : public CJX_Node { + public: + explicit CJX_Stipple(CXFA_Stipple* node); + ~CJX_Stipple() override; + + JS_PROP(rate); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_STIPPLE_H_ diff --git a/fxjs/xfa/cjx_subform.cpp b/fxjs/xfa/cjx_subform.cpp new file mode 100644 index 0000000000000000000000000000000000000000..947d66db1d648aebdbe9c586d89ce83d96768021 --- /dev/null +++ b/fxjs/xfa/cjx_subform.cpp @@ -0,0 +1,229 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_subform.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/fxfa.h" +#include "xfa/fxfa/parser/cxfa_delta.h" +#include "xfa/fxfa/parser/cxfa_document.h" + +const CJX_MethodSpec CJX_Subform::MethodSpecs[] = { + {"execCalculate", execCalculate_static}, + {"execEvent", execEvent_static}, + {"execInitialize", execInitialize_static}, + {"execValidate", execValidate_static}}; + +CJX_Subform::CJX_Subform(CXFA_Node* node) : CJX_Container(node) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Subform::~CJX_Subform() {} + +CJS_Return CJX_Subform::execEvent( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + execSingleEventByName(runtime->ToWideString(params[0]).AsStringView(), + XFA_Element::Subform); + return CJS_Return(true); +} + +CJS_Return CJX_Subform::execInitialize( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize); + return CJS_Return(true); +} + +CJS_Return CJX_Subform::execCalculate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (pNotify) + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate); + return CJS_Return(true); +} + +CJS_Return CJX_Subform::execValidate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); + if (!pNotify) + return CJS_Return(runtime->NewBoolean(false)); + + int32_t iRet = + pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate); + return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); +} + +void CJX_Subform::locale(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + SetCData(XFA_Attribute::Locale, pValue->ToWideString(), true, true); + return; + } + + WideString wsLocaleName = GetXFANode()->GetLocaleName().value_or(L""); + pValue->SetString(wsLocaleName.UTF8Encode().AsStringView()); +} + +void CJX_Subform::instanceIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_InstanceIndex(pValue, bSetting, eAttribute); +} + +void CJX_Subform::allowMacro(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::anchorType(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::colSpan(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::columnWidths(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::h(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::hAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::layout(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::maxH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::maxW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::minH(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::minW(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::presence(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::restoreState(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::scope(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::validationMessage(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_ValidationMessage(pValue, bSetting, eAttribute); +} + +void CJX_Subform::vAlign(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::w(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::x(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Subform::y(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_subform.h b/fxjs/xfa/cjx_subform.h new file mode 100644 index 0000000000000000000000000000000000000000..a1c535b6435e7698aaebee88e40aa890e91e5123 --- /dev/null +++ b/fxjs/xfa/cjx_subform.h @@ -0,0 +1,54 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SUBFORM_H_ +#define FXJS_XFA_CJX_SUBFORM_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_container.h" + +class CXFA_Delta; + +class CJX_Subform : public CJX_Container { + public: + explicit CJX_Subform(CXFA_Node* container); + ~CJX_Subform() override; + + JS_METHOD(execCalculate, CJX_Subform); + JS_METHOD(execEvent, CJX_Subform); + JS_METHOD(execInitialize, CJX_Subform); + JS_METHOD(execValidate, CJX_Subform); + + JS_PROP(allowMacro); + JS_PROP(anchorType); + JS_PROP(colSpan); + JS_PROP(columnWidths); + JS_PROP(h); + JS_PROP(hAlign); + JS_PROP(instanceIndex); + JS_PROP(layout); + JS_PROP(locale); + JS_PROP(maxH); + JS_PROP(maxW); + JS_PROP(minH); + JS_PROP(minW); + JS_PROP(presence); + JS_PROP(relevant); + JS_PROP(restoreState); + JS_PROP(scope); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(validationMessage); + JS_PROP(vAlign); + JS_PROP(w); + JS_PROP(x); + JS_PROP(y); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_SUBFORM_H_ diff --git a/fxjs/xfa/cjx_subformset.cpp b/fxjs/xfa/cjx_subformset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd36abb3df5e34db4dba5bcd9eca9d6b0107f0f4 --- /dev/null +++ b/fxjs/xfa/cjx_subformset.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_subformset.h" + +#include "xfa/fxfa/parser/cxfa_subformset.h" + +CJX_SubformSet::CJX_SubformSet(CXFA_SubformSet* node) : CJX_Container(node) {} + +CJX_SubformSet::~CJX_SubformSet() = default; + +void CJX_SubformSet::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SubformSet::relation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SubformSet::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SubformSet::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_SubformSet::instanceIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_InstanceIndex(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_subformset.h b/fxjs/xfa/cjx_subformset.h new file mode 100644 index 0000000000000000000000000000000000000000..589b44d460ee4e458fc00030c5b18dcb39dab7e1 --- /dev/null +++ b/fxjs/xfa/cjx_subformset.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SUBFORMSET_H_ +#define FXJS_XFA_CJX_SUBFORMSET_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_SubformSet; + +class CJX_SubformSet : public CJX_Container { + public: + explicit CJX_SubformSet(CXFA_SubformSet* node); + ~CJX_SubformSet() override; + + JS_PROP(instanceIndex); + JS_PROP(relation); + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_SUBFORMSET_H_ diff --git a/fxjs/xfa/cjx_subjectdn.cpp b/fxjs/xfa/cjx_subjectdn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a5b4ab58d9fce8178e87db1b8407250cbd86408 --- /dev/null +++ b/fxjs/xfa/cjx_subjectdn.cpp @@ -0,0 +1,19 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_subjectdn.h" + +#include "xfa/fxfa/parser/cxfa_subjectdn.h" + +CJX_SubjectDN::CJX_SubjectDN(CXFA_SubjectDN* node) : CJX_Node(node) {} + +CJX_SubjectDN::~CJX_SubjectDN() = default; + +void CJX_SubjectDN::delimiter(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_subjectdn.h b/fxjs/xfa/cjx_subjectdn.h new file mode 100644 index 0000000000000000000000000000000000000000..d13218b225851928442c723a4f9f2789d6a350b3 --- /dev/null +++ b/fxjs/xfa/cjx_subjectdn.h @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SUBJECTDN_H_ +#define FXJS_XFA_CJX_SUBJECTDN_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_SubjectDN; + +class CJX_SubjectDN : public CJX_Node { + public: + explicit CJX_SubjectDN(CXFA_SubjectDN* node); + ~CJX_SubjectDN() override; + + JS_PROP(delimiter); +}; + +#endif // FXJS_XFA_CJX_SUBJECTDN_H_ diff --git a/fxjs/xfa/cjx_subjectdns.cpp b/fxjs/xfa/cjx_subjectdns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7d9db5622d8bad212d7b047a9a59d041ead0400 --- /dev/null +++ b/fxjs/xfa/cjx_subjectdns.cpp @@ -0,0 +1,19 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_subjectdns.h" + +#include "xfa/fxfa/parser/cxfa_subjectdns.h" + +CJX_SubjectDNs::CJX_SubjectDNs(CXFA_SubjectDNs* node) : CJX_Node(node) {} + +CJX_SubjectDNs::~CJX_SubjectDNs() = default; + +void CJX_SubjectDNs::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_subjectdns.h b/fxjs/xfa/cjx_subjectdns.h new file mode 100644 index 0000000000000000000000000000000000000000..104d826285a4221756cba79267a2d30b2a7951ed --- /dev/null +++ b/fxjs/xfa/cjx_subjectdns.h @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SUBJECTDNS_H_ +#define FXJS_XFA_CJX_SUBJECTDNS_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_SubjectDNs; + +class CJX_SubjectDNs : public CJX_Node { + public: + explicit CJX_SubjectDNs(CXFA_SubjectDNs* node); + ~CJX_SubjectDNs() override; + + JS_PROP(type); +}; + +#endif // FXJS_XFA_CJX_SUBJECTDNS_H_ diff --git a/fxjs/xfa/cjx_submit.cpp b/fxjs/xfa/cjx_submit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..292e4320c8a67326907bdb10b871553c09751b57 --- /dev/null +++ b/fxjs/xfa/cjx_submit.cpp @@ -0,0 +1,55 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_submit.h" + +#include "xfa/fxfa/parser/cxfa_submit.h" + +CJX_Submit::CJX_Submit(CXFA_Submit* node) : CJX_Node(node) {} + +CJX_Submit::~CJX_Submit() = default; + +void CJX_Submit::format(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Submit::embedPDF(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Submit::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Submit::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Submit::target(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Submit::textEncoding(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Submit::xdpContent(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_submit.h b/fxjs/xfa/cjx_submit.h new file mode 100644 index 0000000000000000000000000000000000000000..aefec32b8e8e640ace5619afdb561fb79c0242c8 --- /dev/null +++ b/fxjs/xfa/cjx_submit.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_SUBMIT_H_ +#define FXJS_XFA_CJX_SUBMIT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Submit; + +class CJX_Submit : public CJX_Node { + public: + explicit CJX_Submit(CXFA_Submit* node); + ~CJX_Submit() override; + + JS_PROP(embedPDF); + JS_PROP(format); + JS_PROP(target); + JS_PROP(textEncoding); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(xdpContent); +}; + +#endif // FXJS_XFA_CJX_SUBMIT_H_ diff --git a/fxjs/xfa/cjx_template.cpp b/fxjs/xfa/cjx_template.cpp new file mode 100644 index 0000000000000000000000000000000000000000..816c9d487b5c69501923b4e37a8428f1eedd501d --- /dev/null +++ b/fxjs/xfa/cjx_template.cpp @@ -0,0 +1,81 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_template.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_template.h" + +const CJX_MethodSpec CJX_Template::MethodSpecs[] = { + {"execCalculate", execCalculate_static}, + {"execInitialize", execInitialize_static}, + {"execValidate", execValidate_static}, + {"formNodes", formNodes_static}, + {"recalculate", recalculate_static}, + {"remerge", remerge_static}}; + +CJX_Template::CJX_Template(CXFA_Template* tmpl) : CJX_Model(tmpl) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Template::~CJX_Template() {} + +CJS_Return CJX_Template::formNodes( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewBoolean(true)); +} + +CJS_Return CJX_Template::remerge( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + GetDocument()->DoDataRemerge(true); + return CJS_Return(true); +} + +CJS_Return CJX_Template::execInitialize( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return( + runtime->NewBoolean(!!ToNode(GetXFAObject())->GetWidgetAcc())); +} + +CJS_Return CJX_Template::recalculate( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewBoolean(true)); +} + +CJS_Return CJX_Template::execCalculate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return( + runtime->NewBoolean(!!ToNode(GetXFAObject())->GetWidgetAcc())); +} + +CJS_Return CJX_Template::execValidate( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty()) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return( + runtime->NewBoolean(!!ToNode(GetXFAObject())->GetWidgetAcc())); +} diff --git a/fxjs/xfa/cjx_template.h b/fxjs/xfa/cjx_template.h new file mode 100644 index 0000000000000000000000000000000000000000..2c8278815365fd085b241fb86e8d53bbc794f093 --- /dev/null +++ b/fxjs/xfa/cjx_template.h @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TEMPLATE_H_ +#define FXJS_XFA_CJX_TEMPLATE_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_model.h" + +class CXFA_Template; + +class CJX_Template : public CJX_Model { + public: + explicit CJX_Template(CXFA_Template* tmpl); + ~CJX_Template() override; + + /* The docs list a |createNode| method on Template but that method already + * exists on Model, also the |createNode| docs say it exists on Model not + * on Template so I'm leaving |createNode| out of the template methods. */ + JS_METHOD(execCalculate, CJX_Template); + JS_METHOD(execInitialize, CJX_Template); + JS_METHOD(execValidate, CJX_Template); + JS_METHOD(formNodes, CJX_Template); + JS_METHOD(recalculate, CJX_Template); + JS_METHOD(remerge, CJX_Template); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_TEMPLATE_H_ diff --git a/fxjs/xfa/cjx_text.cpp b/fxjs/xfa/cjx_text.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eda2ff8b22f10ffdbd2ac0cd46f329f43c63c953 --- /dev/null +++ b/fxjs/xfa/cjx_text.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_text.h" + +#include "xfa/fxfa/parser/cxfa_text.h" + +CJX_Text::CJX_Text(CXFA_Text* node) : CJX_Content(node) {} + +CJX_Text::~CJX_Text() = default; + +void CJX_Text::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Text::maxChars(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Text::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Text::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Text::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_text.h b/fxjs/xfa/cjx_text.h new file mode 100644 index 0000000000000000000000000000000000000000..386a7a9679d1aa0d3118e04b7948a5b3a456bd04 --- /dev/null +++ b/fxjs/xfa/cjx_text.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TEXT_H_ +#define FXJS_XFA_CJX_TEXT_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Text; + +class CJX_Text : public CJX_Content { + public: + explicit CJX_Text(CXFA_Text* node); + ~CJX_Text() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(maxChars); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_TEXT_H_ diff --git a/fxjs/xfa/cjx_textedit.cpp b/fxjs/xfa/cjx_textedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1a6faa13bbad787488fd09ac657cf2e052b9166 --- /dev/null +++ b/fxjs/xfa/cjx_textedit.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_textedit.h" + +#include "xfa/fxfa/parser/cxfa_textedit.h" + +CJX_TextEdit::CJX_TextEdit(CXFA_TextEdit* node) : CJX_Node(node) {} + +CJX_TextEdit::~CJX_TextEdit() = default; + +void CJX_TextEdit::vScrollPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TextEdit::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TextEdit::allowRichText(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TextEdit::multiLine(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TextEdit::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TextEdit::hScrollPolicy(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_textedit.h b/fxjs/xfa/cjx_textedit.h new file mode 100644 index 0000000000000000000000000000000000000000..c7f42c963be8e514d2fa8a39098bbab3800e8a46 --- /dev/null +++ b/fxjs/xfa/cjx_textedit.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TEXTEDIT_H_ +#define FXJS_XFA_CJX_TEXTEDIT_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_TextEdit; + +class CJX_TextEdit : public CJX_Node { + public: + explicit CJX_TextEdit(CXFA_TextEdit* node); + ~CJX_TextEdit() override; + + JS_PROP(allowRichText); + JS_PROP(hScrollPolicy); + JS_PROP(multiLine); + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(vScrollPolicy); +}; + +#endif // FXJS_XFA_CJX_TEXTEDIT_H_ diff --git a/fxjs/xfa/cjx_textnode.cpp b/fxjs/xfa/cjx_textnode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..133510c30e8762bcf0682f827d7cacddd57be86b --- /dev/null +++ b/fxjs/xfa/cjx_textnode.cpp @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_textnode.h" + +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +CJX_TextNode::CJX_TextNode(CXFA_Node* node) : CJX_Node(node) {} + +CJX_TextNode::~CJX_TextNode() {} + +void CJX_TextNode::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute attr) { + Script_Som_DefaultValue(pValue, bSetting, attr); +} + +void CJX_TextNode::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute attr) { + Script_Som_DefaultValue(pValue, bSetting, attr); +} diff --git a/fxjs/xfa/cjx_textnode.h b/fxjs/xfa/cjx_textnode.h new file mode 100644 index 0000000000000000000000000000000000000000..12d44d7814df59d7a610961bafdb9ef9c25ab550 --- /dev/null +++ b/fxjs/xfa/cjx_textnode.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TEXTNODE_H_ +#define FXJS_XFA_CJX_TEXTNODE_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Node; + +class CJX_TextNode : public CJX_Node { + public: + explicit CJX_TextNode(CXFA_Node* node); + ~CJX_TextNode() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_TEXTNODE_H_ diff --git a/fxjs/xfa/cjx_time.cpp b/fxjs/xfa/cjx_time.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74855fd3d7a659a69de09662db5f8b72c4463155 --- /dev/null +++ b/fxjs/xfa/cjx_time.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_time.h" + +#include "xfa/fxfa/parser/cxfa_time.h" + +CJX_Time::CJX_Time(CXFA_Time* node) : CJX_Content(node) {} + +CJX_Time::~CJX_Time() = default; + +void CJX_Time::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Time::defaultValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} + +void CJX_Time::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Time::value(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Som_DefaultValue(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_time.h b/fxjs/xfa/cjx_time.h new file mode 100644 index 0000000000000000000000000000000000000000..95b05cc107133c2ae640e08249a778d143e904d8 --- /dev/null +++ b/fxjs/xfa/cjx_time.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TIME_H_ +#define FXJS_XFA_CJX_TIME_H_ + +#include "fxjs/xfa/cjx_content.h" + +class CXFA_Time; + +class CJX_Time : public CJX_Content { + public: + explicit CJX_Time(CXFA_Time* node); + ~CJX_Time() override; + + JS_PROP(defaultValue); /* {default} */ + JS_PROP(use); + JS_PROP(usehref); + JS_PROP(value); +}; + +#endif // FXJS_XFA_CJX_TIME_H_ diff --git a/fxjs/xfa/cjx_timestamp.cpp b/fxjs/xfa/cjx_timestamp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..011d696cc1b97f2a0e863d4f2236c37dce66fb5f --- /dev/null +++ b/fxjs/xfa/cjx_timestamp.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_timestamp.h" + +#include "xfa/fxfa/parser/cxfa_timestamp.h" + +CJX_TimeStamp::CJX_TimeStamp(CXFA_TimeStamp* node) : CJX_Node(node) {} + +CJX_TimeStamp::~CJX_TimeStamp() = default; + +void CJX_TimeStamp::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TimeStamp::type(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TimeStamp::server(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_TimeStamp::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_timestamp.h b/fxjs/xfa/cjx_timestamp.h new file mode 100644 index 0000000000000000000000000000000000000000..ad7ab02a2994d7614383fe4668b46d623c5bcb8a --- /dev/null +++ b/fxjs/xfa/cjx_timestamp.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TIMESTAMP_H_ +#define FXJS_XFA_CJX_TIMESTAMP_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_TimeStamp; + +class CJX_TimeStamp : public CJX_Node { + public: + explicit CJX_TimeStamp(CXFA_TimeStamp* node); + ~CJX_TimeStamp() override; + + JS_PROP(server); + JS_PROP(type); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_TIMESTAMP_H_ diff --git a/fxjs/xfa/cjx_tooltip.cpp b/fxjs/xfa/cjx_tooltip.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d6e2427c81613e1b61a4d7d531d54ad96ecf6b2 --- /dev/null +++ b/fxjs/xfa/cjx_tooltip.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_tooltip.h" + +#include "xfa/fxfa/parser/cxfa_tooltip.h" + +CJX_ToolTip::CJX_ToolTip(CXFA_ToolTip* node) : CJX_TextNode(node) {} + +CJX_ToolTip::~CJX_ToolTip() = default; + +void CJX_ToolTip::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_ToolTip::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_tooltip.h b/fxjs/xfa/cjx_tooltip.h new file mode 100644 index 0000000000000000000000000000000000000000..178d11b0e9c81aee1445647e25ef93e5e4685fde --- /dev/null +++ b/fxjs/xfa/cjx_tooltip.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TOOLTIP_H_ +#define FXJS_XFA_CJX_TOOLTIP_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_ToolTip; + +class CJX_ToolTip : public CJX_TextNode { + public: + explicit CJX_ToolTip(CXFA_ToolTip* node); + ~CJX_ToolTip() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_TOOLTIP_H_ diff --git a/fxjs/xfa/cjx_traversal.cpp b/fxjs/xfa/cjx_traversal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffdcd3527253b22f6a76940dea1c2d17c65df142 --- /dev/null +++ b/fxjs/xfa/cjx_traversal.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_traversal.h" + +#include "xfa/fxfa/parser/cxfa_traversal.h" + +CJX_Traversal::CJX_Traversal(CXFA_Traversal* node) : CJX_Node(node) {} + +CJX_Traversal::~CJX_Traversal() = default; + +void CJX_Traversal::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Traversal::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_traversal.h b/fxjs/xfa/cjx_traversal.h new file mode 100644 index 0000000000000000000000000000000000000000..d9072f3456c9252209e57745ef5939fcdb7d0f89 --- /dev/null +++ b/fxjs/xfa/cjx_traversal.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TRAVERSAL_H_ +#define FXJS_XFA_CJX_TRAVERSAL_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Traversal; + +class CJX_Traversal : public CJX_Node { + public: + explicit CJX_Traversal(CXFA_Traversal* node); + ~CJX_Traversal() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_TRAVERSAL_H_ diff --git a/fxjs/xfa/cjx_traverse.cpp b/fxjs/xfa/cjx_traverse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0d5345ea4a524b20b27e27327f359a3dd41775a --- /dev/null +++ b/fxjs/xfa/cjx_traverse.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_traverse.h" + +#include "xfa/fxfa/parser/cxfa_traverse.h" + +CJX_Traverse::CJX_Traverse(CXFA_Traverse* node) : CJX_Node(node) {} + +CJX_Traverse::~CJX_Traverse() = default; + +void CJX_Traverse::ref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Traverse::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Traverse::operation(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Traverse::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_traverse.h b/fxjs/xfa/cjx_traverse.h new file mode 100644 index 0000000000000000000000000000000000000000..2eef88eb6fc5f9a33220c33db6eda40b9f4bd462 --- /dev/null +++ b/fxjs/xfa/cjx_traverse.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TRAVERSE_H_ +#define FXJS_XFA_CJX_TRAVERSE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Traverse; + +class CJX_Traverse : public CJX_Node { + public: + explicit CJX_Traverse(CXFA_Traverse* node); + ~CJX_Traverse() override; + + JS_PROP(operation); + JS_PROP(ref); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_TRAVERSE_H_ diff --git a/fxjs/xfa/cjx_tree.cpp b/fxjs/xfa/cjx_tree.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e20115b9bcd00817bb66f52c682f3fd1b50a3e8c --- /dev/null +++ b/fxjs/xfa/cjx_tree.cpp @@ -0,0 +1,239 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_tree.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" +#include "xfa/fxfa/parser/cxfa_attachnodelist.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +const CJX_MethodSpec CJX_Tree::MethodSpecs[] = { + {"resolveNode", resolveNode_static}, + {"resolveNodes", resolveNodes_static}}; + +CJX_Tree::CJX_Tree(CXFA_Object* obj) : CJX_Object(obj) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_Tree::~CJX_Tree() {} + +CJS_Return CJX_Tree::resolveNode( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + WideString expression = runtime->ToWideString(params[0]); + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + CXFA_Object* refNode = GetXFAObject(); + if (refNode->GetElementType() == XFA_Element::Xfa) + refNode = pScriptContext->GetThisObject(); + + uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | + XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings; + XFA_RESOLVENODE_RS resolveNodeRS; + if (!pScriptContext->ResolveObjects(ToNode(refNode), + expression.AsStringView(), &resolveNodeRS, + dwFlag, nullptr)) { + return CJS_Return(runtime->NewNull()); + } + + if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + CXFA_Object* pObject = resolveNodeRS.objects.front(); + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pObject); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); + } + + const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = + resolveNodeRS.pScriptAttribute; + if (!lpAttributeInfo || + lpAttributeInfo->eValueType != XFA_ScriptType::Object) { + return CJS_Return(runtime->NewNull()); + } + + auto pValue = pdfium::MakeUnique(pScriptContext->GetIsolate()); + CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject(); + (jsObject->*(lpAttributeInfo->callback))(pValue.get(), false, + lpAttributeInfo->attribute); + return CJS_Return(pValue->DirectGetValue().Get(runtime->GetIsolate())); +} + +CJS_Return CJX_Tree::resolveNodes( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Object* refNode = GetXFAObject(); + if (refNode->GetElementType() == XFA_Element::Xfa) + refNode = GetDocument()->GetScriptContext()->GetThisObject(); + + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return CJS_Return(true); + + auto pValue = pdfium::MakeUnique(pScriptContext->GetIsolate()); + ResolveNodeList(pValue.get(), runtime->ToWideString(params[0]), + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | + XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings, + ToNode(refNode)); + return CJS_Return(pValue->DirectGetValue().Get(runtime->GetIsolate())); +} + +void CJX_Tree::all(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + uint32_t dwFlag = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL; + WideString wsExpression = GetAttribute(XFA_Attribute::Name) + L"[*]"; + ResolveNodeList(pValue, wsExpression, dwFlag, nullptr); +} + +void CJX_Tree::classAll(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + WideString wsExpression = L"#" + GetXFAObject()->GetClassName() + L"[*]"; + ResolveNodeList(pValue, wsExpression, + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL, nullptr); +} + +void CJX_Tree::name(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Tree::nodes(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return; + + if (bSetting) { + WideString wsMessage = L"Unable to set "; + FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView()); + return; + } + + CXFA_AttachNodeList* pNodeList = + new CXFA_AttachNodeList(GetDocument(), ToNode(GetXFAObject())); + pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass()); +} + +void CJX_Tree::parent(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + CXFA_Node* pParent = ToNode(GetXFAObject())->GetParent(); + if (!pParent) { + pValue->SetNull(); + return; + } + + pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pParent)); +} + +void CJX_Tree::index(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameNameIndex()); +} + +void CJX_Tree::classIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameClassIndex()); +} + +void CJX_Tree::somExpression(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + WideString wsSOMExpression = GetXFAObject()->GetSOMExpression(); + pValue->SetString(wsSOMExpression.UTF8Encode().AsStringView()); +} + +void CJX_Tree::ResolveNodeList(CFXJSE_Value* pValue, + WideString wsExpression, + uint32_t dwFlag, + CXFA_Node* refNode) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return; + if (!refNode) + refNode = ToNode(GetXFAObject()); + + XFA_RESOLVENODE_RS resolveNodeRS; + pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(), + &resolveNodeRS, dwFlag, nullptr); + CXFA_ArrayNodeList* pNodeList = new CXFA_ArrayNodeList(GetDocument()); + if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + for (CXFA_Object* pObject : resolveNodeRS.objects) { + if (pObject->IsNode()) + pNodeList->Append(pObject->AsNode()); + } + } else { + if (resolveNodeRS.pScriptAttribute && + resolveNodeRS.pScriptAttribute->eValueType == XFA_ScriptType::Object) { + for (CXFA_Object* pObject : resolveNodeRS.objects) { + auto pValue = + pdfium::MakeUnique(pScriptContext->GetIsolate()); + CJX_Object* jsObject = pObject->JSObject(); + (jsObject->*(resolveNodeRS.pScriptAttribute->callback))( + pValue.get(), false, resolveNodeRS.pScriptAttribute->attribute); + + CXFA_Object* obj = CFXJSE_Engine::ToObject(pValue.get(), nullptr); + if (obj->IsNode()) + pNodeList->Append(obj->AsNode()); + } + } + } + pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass()); +} diff --git a/fxjs/xfa/cjx_tree.h b/fxjs/xfa/cjx_tree.h new file mode 100644 index 0000000000000000000000000000000000000000..9389d2ec4f5f612dbb1ec2dd6b71209c01978cf8 --- /dev/null +++ b/fxjs/xfa/cjx_tree.h @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TREE_H_ +#define FXJS_XFA_CJX_TREE_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_object.h" + +class CXFA_Object; +class CXFA_Node; + +class CJX_Tree : public CJX_Object { + public: + explicit CJX_Tree(CXFA_Object* obj); + ~CJX_Tree() override; + + JS_METHOD(resolveNode, CJX_Tree); + JS_METHOD(resolveNodes, CJX_Tree); + + JS_PROP(all); + JS_PROP(classAll); + JS_PROP(classIndex); + JS_PROP(index); + JS_PROP(name); + JS_PROP(nodes); + JS_PROP(parent); + JS_PROP(somExpression); + + private: + void ResolveNodeList(CFXJSE_Value* pValue, + WideString wsExpression, + uint32_t dwFlag, + CXFA_Node* refNode); + + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_TREE_H_ diff --git a/fxjs/xfa/cjx_treelist.cpp b/fxjs/xfa/cjx_treelist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b91a0b7541e1c60c010bbf14e49d77e5cbcaec8e --- /dev/null +++ b/fxjs/xfa/cjx_treelist.cpp @@ -0,0 +1,48 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_treelist.h" + +#include + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_treelist.h" + +const CJX_MethodSpec CJX_TreeList::MethodSpecs[] = { + {"namedItem", namedItem_static}}; + +CJX_TreeList::CJX_TreeList(CXFA_TreeList* list) : CJX_List(list) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_TreeList::~CJX_TreeList() {} + +CXFA_TreeList* CJX_TreeList::GetXFATreeList() { + return static_cast(GetXFAObject()); +} + +CJS_Return CJX_TreeList::namedItem( + CJS_V8* runtime, + const std::vector>& params) { + if (params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + + CXFA_Node* pNode = GetXFATreeList()->NamedItem( + runtime->ToWideString(params[0]).AsStringView()); + if (!pNode) + return CJS_Return(true); + + CFXJSE_Value* value = + GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode); + if (!value) + return CJS_Return(runtime->NewNull()); + + return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate())); +} diff --git a/fxjs/xfa/cjx_treelist.h b/fxjs/xfa/cjx_treelist.h new file mode 100644 index 0000000000000000000000000000000000000000..29a95e6d74a12c0627cdffda3503c85b4f2e95b0 --- /dev/null +++ b/fxjs/xfa/cjx_treelist.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_TREELIST_H_ +#define FXJS_XFA_CJX_TREELIST_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_list.h" + +class CXFA_TreeList; + +class CJX_TreeList : public CJX_List { + public: + explicit CJX_TreeList(CXFA_TreeList* list); + ~CJX_TreeList() override; + + JS_METHOD(namedItem, CJX_TreeList); + + private: + CXFA_TreeList* GetXFATreeList(); + + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_TREELIST_H_ diff --git a/fxjs/xfa/cjx_ui.cpp b/fxjs/xfa/cjx_ui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90db789dd79e15fdcf6185a3758a3421752b5087 --- /dev/null +++ b/fxjs/xfa/cjx_ui.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_ui.h" + +#include "xfa/fxfa/parser/cxfa_ui.h" + +CJX_Ui::CJX_Ui(CXFA_Ui* node) : CJX_Node(node) {} + +CJX_Ui::~CJX_Ui() = default; + +void CJX_Ui::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Ui::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_ui.h b/fxjs/xfa/cjx_ui.h new file mode 100644 index 0000000000000000000000000000000000000000..e82b1deacbb9e6c1d8cd64038c678d90172546e6 --- /dev/null +++ b/fxjs/xfa/cjx_ui.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_UI_H_ +#define FXJS_XFA_CJX_UI_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Ui; + +class CJX_Ui : public CJX_Node { + public: + explicit CJX_Ui(CXFA_Ui* node); + ~CJX_Ui() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_UI_H_ diff --git a/fxjs/xfa/cjx_update.cpp b/fxjs/xfa/cjx_update.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5d1ef27c940e39edac186b3233240a68845e45d --- /dev/null +++ b/fxjs/xfa/cjx_update.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_update.h" + +#include "xfa/fxfa/parser/cxfa_update.h" + +CJX_Update::CJX_Update(CXFA_Update* node) : CJX_TextNode(node) {} + +CJX_Update::~CJX_Update() = default; + +void CJX_Update::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Update::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_update.h b/fxjs/xfa/cjx_update.h new file mode 100644 index 0000000000000000000000000000000000000000..c1acb4bd9065d18015ea5c9196f578ee9162a6dc --- /dev/null +++ b/fxjs/xfa/cjx_update.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_UPDATE_H_ +#define FXJS_XFA_CJX_UPDATE_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Update; + +class CJX_Update : public CJX_TextNode { + public: + explicit CJX_Update(CXFA_Update* node); + ~CJX_Update() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_UPDATE_H_ diff --git a/fxjs/xfa/cjx_uri.cpp b/fxjs/xfa/cjx_uri.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ffbb68e8f816ffff518db9e13991f8bf38cdf6f --- /dev/null +++ b/fxjs/xfa/cjx_uri.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_uri.h" + +#include "xfa/fxfa/parser/cxfa_uri.h" + +CJX_Uri::CJX_Uri(CXFA_Uri* node) : CJX_TextNode(node) {} + +CJX_Uri::~CJX_Uri() = default; + +void CJX_Uri::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Uri::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_uri.h b/fxjs/xfa/cjx_uri.h new file mode 100644 index 0000000000000000000000000000000000000000..805bc5c1ab0b0f7c18bc8dc418e54f9424bfe878 --- /dev/null +++ b/fxjs/xfa/cjx_uri.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_URI_H_ +#define FXJS_XFA_CJX_URI_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_Uri; + +class CJX_Uri : public CJX_TextNode { + public: + explicit CJX_Uri(CXFA_Uri* node); + ~CJX_Uri() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_URI_H_ diff --git a/fxjs/xfa/cjx_user.cpp b/fxjs/xfa/cjx_user.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a42f927d47251d1340ed4c0fc11d8f84c5a04a30 --- /dev/null +++ b/fxjs/xfa/cjx_user.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_user.h" + +#include "xfa/fxfa/parser/cxfa_user.h" + +CJX_User::CJX_User(CXFA_User* node) : CJX_TextNode(node) {} + +CJX_User::~CJX_User() = default; + +void CJX_User::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_User::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_user.h b/fxjs/xfa/cjx_user.h new file mode 100644 index 0000000000000000000000000000000000000000..6111df8535f55bbbf8775a134ce7386e0c33e978 --- /dev/null +++ b/fxjs/xfa/cjx_user.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_USER_H_ +#define FXJS_XFA_CJX_USER_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_User; + +class CJX_User : public CJX_TextNode { + public: + explicit CJX_User(CXFA_User* node); + ~CJX_User() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_USER_H_ diff --git a/fxjs/xfa/cjx_validate.cpp b/fxjs/xfa/cjx_validate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16c264e23e8fb6284df670be08cfb003a1988793 --- /dev/null +++ b/fxjs/xfa/cjx_validate.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_validate.h" + +#include "xfa/fxfa/parser/cxfa_validate.h" + +CJX_Validate::CJX_Validate(CXFA_Validate* node) : CJX_Node(node) {} + +CJX_Validate::~CJX_Validate() = default; + +void CJX_Validate::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Validate::scriptTest(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Validate::nullTest(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Validate::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Validate::formatTest(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_validate.h b/fxjs/xfa/cjx_validate.h new file mode 100644 index 0000000000000000000000000000000000000000..c54923d5b075fce9d575c9e1be0945bf80e63c0f --- /dev/null +++ b/fxjs/xfa/cjx_validate.h @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_VALIDATE_H_ +#define FXJS_XFA_CJX_VALIDATE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Validate; + +class CJX_Validate : public CJX_Node { + public: + explicit CJX_Validate(CXFA_Validate* node); + ~CJX_Validate() override; + + JS_PROP(formatTest); + JS_PROP(nullTest); + JS_PROP(scriptTest); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_VALIDATE_H_ diff --git a/fxjs/xfa/cjx_value.cpp b/fxjs/xfa/cjx_value.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8fe3b239f5a5659f982aaabb26b3a6aeb2c47cc6 --- /dev/null +++ b/fxjs/xfa/cjx_value.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_value.h" + +#include "xfa/fxfa/parser/cxfa_value.h" + +CJX_Value::CJX_Value(CXFA_Value* node) : CJX_Node(node) {} + +CJX_Value::~CJX_Value() = default; + +void CJX_Value::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Value::relevant(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Value::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Value::override(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_BOOL(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_value.h b/fxjs/xfa/cjx_value.h new file mode 100644 index 0000000000000000000000000000000000000000..f9c2a2ceb980f50151a3560525d91a68f96a483d --- /dev/null +++ b/fxjs/xfa/cjx_value.h @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_VALUE_H_ +#define FXJS_XFA_CJX_VALUE_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_Value; + +class CJX_Value : public CJX_Node { + public: + explicit CJX_Value(CXFA_Value* node); + ~CJX_Value() override; + + JS_PROP(override); + JS_PROP(relevant); + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_VALUE_H_ diff --git a/fxjs/xfa/cjx_variables.cpp b/fxjs/xfa/cjx_variables.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0904c9f3fe5979e2e14b8f0b5417eaf98fd639f0 --- /dev/null +++ b/fxjs/xfa/cjx_variables.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_variables.h" + +#include "xfa/fxfa/parser/cxfa_variables.h" + +CJX_Variables::CJX_Variables(CXFA_Variables* node) : CJX_Container(node) {} + +CJX_Variables::~CJX_Variables() = default; + +void CJX_Variables::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Variables::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_variables.h b/fxjs/xfa/cjx_variables.h new file mode 100644 index 0000000000000000000000000000000000000000..8ed373e5cd86a218b01e4bc2a88979b61357cbfc --- /dev/null +++ b/fxjs/xfa/cjx_variables.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_VARIABLES_H_ +#define FXJS_XFA_CJX_VARIABLES_H_ + +#include "fxjs/xfa/cjx_container.h" + +class CXFA_Variables; + +class CJX_Variables : public CJX_Container { + public: + explicit CJX_Variables(CXFA_Variables* node); + ~CJX_Variables() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_VARIABLES_H_ diff --git a/fxjs/xfa/cjx_wsdladdress.cpp b/fxjs/xfa/cjx_wsdladdress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc6a77c2e47143e9e98f3314cb80046c752bfaff --- /dev/null +++ b/fxjs/xfa/cjx_wsdladdress.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_wsdladdress.h" + +#include "xfa/fxfa/parser/cxfa_wsdladdress.h" + +CJX_WsdlAddress::CJX_WsdlAddress(CXFA_WsdlAddress* node) : CJX_TextNode(node) {} + +CJX_WsdlAddress::~CJX_WsdlAddress() = default; + +void CJX_WsdlAddress::use(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_WsdlAddress::usehref(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_wsdladdress.h b/fxjs/xfa/cjx_wsdladdress.h new file mode 100644 index 0000000000000000000000000000000000000000..a742d1a97317a7e63b9b0b8e0c3bead6b873b9eb --- /dev/null +++ b/fxjs/xfa/cjx_wsdladdress.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_WSDLADDRESS_H_ +#define FXJS_XFA_CJX_WSDLADDRESS_H_ + +#include "fxjs/xfa/cjx_textnode.h" + +class CXFA_WsdlAddress; + +class CJX_WsdlAddress : public CJX_TextNode { + public: + explicit CJX_WsdlAddress(CXFA_WsdlAddress* node); + ~CJX_WsdlAddress() override; + + JS_PROP(use); + JS_PROP(usehref); +}; + +#endif // FXJS_XFA_CJX_WSDLADDRESS_H_ diff --git a/fxjs/xfa/cjx_wsdlconnection.cpp b/fxjs/xfa/cjx_wsdlconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c6ca46dd9db6a8a25e667b08818815442afc582 --- /dev/null +++ b/fxjs/xfa/cjx_wsdlconnection.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_wsdlconnection.h" + +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/js_resources.h" +#include "xfa/fxfa/parser/cxfa_wsdlconnection.h" + +const CJX_MethodSpec CJX_WsdlConnection::MethodSpecs[] = { + {"execute", execute_static}}; + +CJX_WsdlConnection::CJX_WsdlConnection(CXFA_WsdlConnection* connection) + : CJX_Node(connection) { + DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); +} + +CJX_WsdlConnection::~CJX_WsdlConnection() {} + +CJS_Return CJX_WsdlConnection::execute( + CJS_V8* runtime, + const std::vector>& params) { + if (!params.empty() && params.size() != 1) + return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); + return CJS_Return(runtime->NewBoolean(false)); +} + +void CJX_WsdlConnection::dataDescription(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_WsdlConnection::execute(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_wsdlconnection.h b/fxjs/xfa/cjx_wsdlconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..d755b5d075a42f9efc74209225b079ebe278f7e5 --- /dev/null +++ b/fxjs/xfa/cjx_wsdlconnection.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_WSDLCONNECTION_H_ +#define FXJS_XFA_CJX_WSDLCONNECTION_H_ + +#include "fxjs/CJX_Define.h" +#include "fxjs/xfa/cjx_node.h" + +class CXFA_WsdlConnection; + +class CJX_WsdlConnection : public CJX_Node { + public: + explicit CJX_WsdlConnection(CXFA_WsdlConnection* connection); + ~CJX_WsdlConnection() override; + + JS_METHOD(execute, CJX_WsdlConnection); + + JS_PROP(dataDescription); + JS_PROP(execute); + + private: + static const CJX_MethodSpec MethodSpecs[]; +}; + +#endif // FXJS_XFA_CJX_WSDLCONNECTION_H_ diff --git a/fxjs/xfa/cjx_xfa.cpp b/fxjs/xfa/cjx_xfa.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc0d7f118ee0bda2cf42f68549276fae4115e2f9 --- /dev/null +++ b/fxjs/xfa/cjx_xfa.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_xfa.h" + +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_xfa.h" + +CJX_Xfa::CJX_Xfa(CXFA_Xfa* node) : CJX_Model(node) {} + +CJX_Xfa::~CJX_Xfa() = default; + +void CJX_Xfa::thisValue(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) + return; + + CXFA_Object* pThis = GetDocument()->GetScriptContext()->GetThisObject(); + ASSERT(pThis); + pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pThis)); +} + +void CJX_Xfa::timeStamp(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} + +void CJX_Xfa::uuid(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_xfa.h b/fxjs/xfa/cjx_xfa.h new file mode 100644 index 0000000000000000000000000000000000000000..0c8ed7efff3d4981cfdf9ef8262cbe5176add58a --- /dev/null +++ b/fxjs/xfa/cjx_xfa.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_XFA_H_ +#define FXJS_XFA_CJX_XFA_H_ + +#include "fxjs/xfa/cjx_model.h" + +class CXFA_Xfa; + +class CJX_Xfa : public CJX_Model { + public: + explicit CJX_Xfa(CXFA_Xfa* node); + ~CJX_Xfa() override; + + JS_PROP(thisValue); /* this */ + JS_PROP(timeStamp); + JS_PROP(uuid); +}; + +#endif // FXJS_XFA_CJX_XFA_H_ diff --git a/fxjs/xfa/cjx_xmlconnection.cpp b/fxjs/xfa/cjx_xmlconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6622aab12e6b7c1c544883d3f5c043d9f90d274f --- /dev/null +++ b/fxjs/xfa/cjx_xmlconnection.cpp @@ -0,0 +1,20 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_xmlconnection.h" + +#include "xfa/fxfa/parser/cxfa_xmlconnection.h" + +CJX_XmlConnection::CJX_XmlConnection(CXFA_XmlConnection* node) + : CJX_Node(node) {} + +CJX_XmlConnection::~CJX_XmlConnection() = default; + +void CJX_XmlConnection::dataDescription(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_xmlconnection.h b/fxjs/xfa/cjx_xmlconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..03c5c37320ea279e4acc9cb164788eb8aad23b75 --- /dev/null +++ b/fxjs/xfa/cjx_xmlconnection.h @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_XMLCONNECTION_H_ +#define FXJS_XFA_CJX_XMLCONNECTION_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_XmlConnection; + +class CJX_XmlConnection : public CJX_Node { + public: + explicit CJX_XmlConnection(CXFA_XmlConnection* node); + ~CJX_XmlConnection() override; + + JS_PROP(dataDescription); +}; + +#endif // FXJS_XFA_CJX_XMLCONNECTION_H_ diff --git a/fxjs/xfa/cjx_xsdconnection.cpp b/fxjs/xfa/cjx_xsdconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa7d42ae1354caedc7fbe678507c5db239ce12e4 --- /dev/null +++ b/fxjs/xfa/cjx_xsdconnection.cpp @@ -0,0 +1,20 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fxjs/xfa/cjx_xsdconnection.h" + +#include "xfa/fxfa/parser/cxfa_xsdconnection.h" + +CJX_XsdConnection::CJX_XsdConnection(CXFA_XsdConnection* node) + : CJX_Node(node) {} + +CJX_XsdConnection::~CJX_XsdConnection() = default; + +void CJX_XsdConnection::dataDescription(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + Script_Attribute_String(pValue, bSetting, eAttribute); +} diff --git a/fxjs/xfa/cjx_xsdconnection.h b/fxjs/xfa/cjx_xsdconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..66c79a14fa6452cc38bddda14da398dde7800d5b --- /dev/null +++ b/fxjs/xfa/cjx_xsdconnection.h @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FXJS_XFA_CJX_XSDCONNECTION_H_ +#define FXJS_XFA_CJX_XSDCONNECTION_H_ + +#include "fxjs/xfa/cjx_node.h" + +class CXFA_XsdConnection; + +class CJX_XsdConnection : public CJX_Node { + public: + explicit CJX_XsdConnection(CXFA_XsdConnection* node); + ~CJX_XsdConnection() override; + + JS_PROP(dataDescription); +}; + +#endif // FXJS_XFA_CJX_XSDCONNECTION_H_ diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 7062e43a494e2653aebea929d90e7438fa467565..6d2a69977aaa6edfbbd0bba841e53cd229964d6d 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg @@ -7,15 +7,8 @@ git_repo_url: "https://pdfium.googlesource.com/pdfium.git" cq_status_url: "https://chromium-cq-status.appspot.com" gerrit {} -rietveld { - url: "https://codereview.chromium.org" -} verifiers { - reviewer_lgtm { - committer_list: "project-pdfium-committers" - dry_run_access_list: "project-pdfium-tryjob-access" - } gerrit_cq_ability { committer_list: "project-pdfium-committers" dry_run_access_list: "project-pdfium-tryjob-access" @@ -41,6 +34,9 @@ verifiers { builders { name: "linux_asan_lsan" } + builders { + name: "linux_msan" + } builders { name: "linux_no_v8" } @@ -53,6 +49,9 @@ verifiers { builders { name: "linux_xfa_asan_lsan" } + builders { + name: "linux_xfa_msan" + } builders { name: "linux_xfa_rel" } @@ -74,6 +73,9 @@ verifiers { builders { name: "win" } + builders { + name: "win_asan" + } builders { name: "win_no_v8" } @@ -87,10 +89,13 @@ verifiers { name: "win_xfa_32" } builders { - name: "win_xfa_clang" + name: "win_xfa_asan" + } + builders { + name: "win_xfa_msvc" } builders { - name: "win_xfa_clang_32" + name: "win_xfa_msvc_32" } builders { name: "win_xfa_rel" diff --git a/navbar.md b/navbar.md index a7f9307ae71b10a9bf78f2bd90d4f4c2ac0109e0..c12cf110891fd3a830567edb139f8f654c74258c 100644 --- a/navbar.md +++ b/navbar.md @@ -9,5 +9,6 @@ found in the LICENSE file. * [Home](/README.md) * [Getting Started](/docs/getting-started.md) * [V8 Getting Started](/docs/v8-getting-started.md) +* [SafetyNet](/docs/safetynet.md) [home]: /README.md diff --git a/pdfium.bp b/pdfium.bp index d1a4f16c5b065580248286a0a8ab72db04d112c7..e188280f038d41f78a021d1a425c6a5aaa979e58 100644 --- a/pdfium.bp +++ b/pdfium.bp @@ -1,41 +1,31 @@ cc_library_shared { name: "libpdfium", - defaults: ["pdfium-defaults"], - - cflags: [ - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], + defaults: ["pdfium-core"], static_libs: [ + "libpdfiumfdrm", "libpdfiumformfiller", - "libpdfiumpdfwindow", - "libpdfiumjavascript", "libpdfiumfpdfapi", - "libpdfiumfxge", - "libpdfiumfxedit", + "libpdfiumfpdfdoc", "libpdfiumfpdftext", - "libpdfiumfxcrt", "libpdfiumfxcodec", - "libpdfiumfpdfdoc", - "libpdfiumfdrm", - "libpdfiumagg23", + "libpdfiumfxcrt", + "libpdfiumfxge", + "libpdfiumfxjs", + "libpdfiumpwl", + "libpdfiumfx_agg", "libpdfiumbigint", - "libpdfiumlcms", - "libpdfiumjpeg", - "libpdfiumopenjpeg", - "libpdfiumzlib", + "libpdfiumpdfiumbase", + "libpdfiumlcms2", + "libpdfiumfx_libopenjpeg", ], // TODO: figure out why turning on exceptions requires manually linking libdl shared_libs: [ "libdl", "libft2", + "libz", + "libjpeg", ], srcs: [ @@ -60,6 +50,9 @@ cc_library_shared { "fpdfsdk/fpdf_structtree.cpp", "fpdfsdk/fpdf_sysfontinfo.cpp", "fpdfsdk/fpdf_transformpage.cpp", + "fpdfsdk/fpdfannot.cpp", + "fpdfsdk/fpdfattachment.cpp", + "fpdfsdk/fpdfcatalog.cpp", "fpdfsdk/fpdfdoc.cpp", "fpdfsdk/fpdfeditimg.cpp", "fpdfsdk/fpdfeditpage.cpp", @@ -71,9 +64,15 @@ cc_library_shared { "fpdfsdk/fpdftext.cpp", "fpdfsdk/fpdfview.cpp", "fpdfsdk/fsdk_actionhandler.cpp", + "fpdfsdk/fsdk_filewriteadapter.cpp", "fpdfsdk/fsdk_pauseadapter.cpp", "fpdfsdk/pdfsdk_fieldaction.cpp", ], export_include_dirs: ["public"], + + include_dirs: [ + "external/freetype/include", + "external/freetype/include/freetype", + ], } diff --git a/pdfium.gni b/pdfium.gni index 8ce09f968d75a96abb6f9b3639b08d781958cd4f..e48750e5f06f315210668cd919e0e09513b56c2f 100644 --- a/pdfium.gni +++ b/pdfium.gni @@ -7,9 +7,13 @@ import("//build_overrides/pdfium.gni") # This file contains PDFium-related build flags. declare_args() { - # On Android there's no system FreeType. On Windows and Mac, only a few - # methods are used from it. - pdfium_bundle_freetype = !is_linux + # Build PDFium either: + # 1) When set to true, with a bundled FreeType, built from FreeType source + # code in //third_party/freetype and PDFium's FreeType configs in + # third_party/freetype/include. + # 2) When set to false, use whatever FreeType target is defined in + # //build/config/freetype. + pdf_bundle_freetype = pdf_bundle_freetype_override # Build PDFium either with or without v8 support. pdf_enable_v8 = pdf_enable_v8_override @@ -29,10 +33,12 @@ declare_args() { # If XFA, also support png codec. Ignored if not XFA. pdf_enable_xfa_tiff = true - # Build PDFium against skia (experimental) rather than agg. Use Skia to draw everything. + # Build PDFium against Skia (experimental) rather than AGG. Use Skia to draw + # everything. pdf_use_skia = pdf_use_skia_override - # Build PDFium against skia (experimental) rather than agg. Use Skia to draw paths. + # Build PDFium against Skia (experimental) rather than AGG. Use Skia to draw + # paths. pdf_use_skia_paths = pdf_use_skia_paths_override # Build PDFium with or without experimental win32 GDI APIs. @@ -41,6 +47,25 @@ declare_args() { # Build PDFium standalone pdf_is_standalone = false + # Build a complete static library + pdf_is_complete_lib = false + + # Enable callgrind for performance profiling + enable_callgrind = false + # Enable coverage information use_coverage = false + + # Don't build against bundled zlib. + use_system_zlib = false + + # Don't build against bundled lcms2. + use_system_lcms2 = false + + # Don't build against bundled libpng. + use_system_libpng = false +} + +if (pdf_use_skia && pdf_use_skia_paths) { + assert(false, "Enable at most ONE of pdf_use_skia and pdf_use_skia_paths") } diff --git a/pdfiumfdrm.bp b/pdfiumfdrm.bp index f28c79ee79bb1c90758f5ad6a2630b9a5b0b785f..b59898fc2a35cd07983f2df6e28a766457dac26c 100644 --- a/pdfiumfdrm.bp +++ b/pdfiumfdrm.bp @@ -1,16 +1,9 @@ cc_library_static { name: "libpdfiumfdrm", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", + static_libs: [ + "libpdfiumfxcrt", ], srcs: [ diff --git a/pdfiumformfiller.bp b/pdfiumformfiller.bp index 8206f667a1880828ece0787ddcda7d2f1d0ed581..a6619df6d90d2dff58d7f6a6c4f74e74dbf9bb85 100644 --- a/pdfiumformfiller.bp +++ b/pdfiumformfiller.bp @@ -1,20 +1,14 @@ cc_library_static { name: "libpdfiumformfiller", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", + static_libs: [ + "libpdfiumfxcrt", ], srcs: [ "fpdfsdk/formfiller/cba_fontmap.cpp", + "fpdfsdk/formfiller/cffl_button.cpp", "fpdfsdk/formfiller/cffl_checkbox.cpp", "fpdfsdk/formfiller/cffl_combobox.cpp", "fpdfsdk/formfiller/cffl_formfiller.cpp", @@ -23,6 +17,7 @@ cc_library_static { "fpdfsdk/formfiller/cffl_pushbutton.cpp", "fpdfsdk/formfiller/cffl_radiobutton.cpp", "fpdfsdk/formfiller/cffl_textfield.cpp", + "fpdfsdk/formfiller/cffl_textobject.cpp", ], include_dirs: [ diff --git a/pdfiumfpdfapi.bp b/pdfiumfpdfapi.bp index e2f4e51ab5b2746e9b40ba3d459b4d80d9dae6be..2beb9c63a0576035fdbe33cb25235646a8701379 100644 --- a/pdfiumfpdfapi.bp +++ b/pdfiumfpdfapi.bp @@ -1,17 +1,11 @@ cc_library_static { name: "libpdfiumfpdfapi", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", + static_libs: [ + "libpdfiumfxcrt", + "libpdfiumlcms2", + "libpdfiumfdrm", ], srcs: [ @@ -79,19 +73,26 @@ cc_library_static { "core/fpdfapi/cmaps/fpdf_cmaps.cpp", "core/fpdfapi/cpdf_modulemgr.cpp", "core/fpdfapi/cpdf_pagerendercontext.cpp", + "core/fpdfapi/edit/cpdf_creator.cpp", + "core/fpdfapi/edit/cpdf_encryptor.cpp", + "core/fpdfapi/edit/cpdf_flateencoder.cpp", "core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp", - "core/fpdfapi/edit/fpdf_edit_create.cpp", + "core/fpdfapi/font/cfx_cttgsubtable.cpp", + "core/fpdfapi/font/cfx_stockfontarray.cpp", + "core/fpdfapi/font/cpdf_cid2unicodemap.cpp", "core/fpdfapi/font/cpdf_cidfont.cpp", + "core/fpdfapi/font/cpdf_cmap.cpp", + "core/fpdfapi/font/cpdf_cmapmanager.cpp", + "core/fpdfapi/font/cpdf_cmapparser.cpp", "core/fpdfapi/font/cpdf_font.cpp", "core/fpdfapi/font/cpdf_fontencoding.cpp", + "core/fpdfapi/font/cpdf_fontglobals.cpp", "core/fpdfapi/font/cpdf_simplefont.cpp", + "core/fpdfapi/font/cpdf_tounicodemap.cpp", "core/fpdfapi/font/cpdf_truetypefont.cpp", "core/fpdfapi/font/cpdf_type1font.cpp", "core/fpdfapi/font/cpdf_type3char.cpp", "core/fpdfapi/font/cpdf_type3font.cpp", - "core/fpdfapi/font/fpdf_font.cpp", - "core/fpdfapi/font/fpdf_font_cid.cpp", - "core/fpdfapi/font/ttgsubtable.cpp", "core/fpdfapi/page/cpdf_allstates.cpp", "core/fpdfapi/page/cpdf_clippath.cpp", "core/fpdfapi/page/cpdf_color.cpp", @@ -100,11 +101,15 @@ cc_library_static { "core/fpdfapi/page/cpdf_contentmark.cpp", "core/fpdfapi/page/cpdf_contentmarkitem.cpp", "core/fpdfapi/page/cpdf_contentparser.cpp", + "core/fpdfapi/page/cpdf_devicecs.cpp", "core/fpdfapi/page/cpdf_docpagedata.cpp", + "core/fpdfapi/page/cpdf_expintfunc.cpp", "core/fpdfapi/page/cpdf_form.cpp", "core/fpdfapi/page/cpdf_formobject.cpp", + "core/fpdfapi/page/cpdf_function.cpp", "core/fpdfapi/page/cpdf_generalstate.cpp", "core/fpdfapi/page/cpdf_graphicstates.cpp", + "core/fpdfapi/page/cpdf_iccprofile.cpp", "core/fpdfapi/page/cpdf_image.cpp", "core/fpdfapi/page/cpdf_imageobject.cpp", "core/fpdfapi/page/cpdf_meshstream.cpp", @@ -116,18 +121,22 @@ cc_library_static { "core/fpdfapi/page/cpdf_path.cpp", "core/fpdfapi/page/cpdf_pathobject.cpp", "core/fpdfapi/page/cpdf_pattern.cpp", + "core/fpdfapi/page/cpdf_patterncs.cpp", + "core/fpdfapi/page/cpdf_psengine.cpp", + "core/fpdfapi/page/cpdf_psfunc.cpp", + "core/fpdfapi/page/cpdf_sampledfunc.cpp", "core/fpdfapi/page/cpdf_shadingobject.cpp", "core/fpdfapi/page/cpdf_shadingpattern.cpp", + "core/fpdfapi/page/cpdf_stitchfunc.cpp", "core/fpdfapi/page/cpdf_streamcontentparser.cpp", "core/fpdfapi/page/cpdf_streamparser.cpp", "core/fpdfapi/page/cpdf_textobject.cpp", "core/fpdfapi/page/cpdf_textstate.cpp", "core/fpdfapi/page/cpdf_tilingpattern.cpp", - "core/fpdfapi/page/fpdf_page_colors.cpp", - "core/fpdfapi/page/fpdf_page_func.cpp", "core/fpdfapi/parser/cfdf_document.cpp", "core/fpdfapi/parser/cpdf_array.cpp", "core/fpdfapi/parser/cpdf_boolean.cpp", + "core/fpdfapi/parser/cpdf_cross_ref_avail.cpp", "core/fpdfapi/parser/cpdf_crypto_handler.cpp", "core/fpdfapi/parser/cpdf_data_avail.cpp", "core/fpdfapi/parser/cpdf_dictionary.cpp", @@ -139,7 +148,11 @@ cc_library_static { "core/fpdfapi/parser/cpdf_null.cpp", "core/fpdfapi/parser/cpdf_number.cpp", "core/fpdfapi/parser/cpdf_object.cpp", + "core/fpdfapi/parser/cpdf_object_avail.cpp", + "core/fpdfapi/parser/cpdf_object_walker.cpp", + "core/fpdfapi/parser/cpdf_page_object_avail.cpp", "core/fpdfapi/parser/cpdf_parser.cpp", + "core/fpdfapi/parser/cpdf_read_validator.cpp", "core/fpdfapi/parser/cpdf_reference.cpp", "core/fpdfapi/parser/cpdf_security_handler.cpp", "core/fpdfapi/parser/cpdf_simple_parser.cpp", diff --git a/pdfiumfpdfdoc.bp b/pdfiumfpdfdoc.bp index 1d974f6fa4d6811adaaa85630639f6580187f67d..c3493a8ccfdd2eec1dbd7522a39be82b3ac07f4a 100644 --- a/pdfiumfpdfdoc.bp +++ b/pdfiumfpdfdoc.bp @@ -1,21 +1,13 @@ cc_library_static { name: "libpdfiumfpdfdoc", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", + static_libs: [ + "libpdfiumfxcrt", ], srcs: [ "core/fpdfdoc/cline.cpp", - "core/fpdfdoc/clines.cpp", "core/fpdfdoc/cpdf_aaction.cpp", "core/fpdfdoc/cpdf_action.cpp", "core/fpdfdoc/cpdf_actionfields.cpp", @@ -39,16 +31,15 @@ cc_library_static { "core/fpdfdoc/cpdf_numbertree.cpp", "core/fpdfdoc/cpdf_occontext.cpp", "core/fpdfdoc/cpdf_pagelabel.cpp", + "core/fpdfdoc/cpdf_structelement.cpp", + "core/fpdfdoc/cpdf_structtree.cpp", "core/fpdfdoc/cpdf_variabletext.cpp", "core/fpdfdoc/cpdf_viewerpreferences.cpp", - "core/fpdfdoc/cpvt_color.cpp", "core/fpdfdoc/cpvt_fontmap.cpp", "core/fpdfdoc/cpvt_generateap.cpp", - "core/fpdfdoc/cpvt_sectioninfo.cpp", "core/fpdfdoc/cpvt_wordinfo.cpp", "core/fpdfdoc/csection.cpp", "core/fpdfdoc/ctypeset.cpp", - "core/fpdfdoc/doc_tagged.cpp", ], include_dirs: [ diff --git a/pdfiumfpdftext.bp b/pdfiumfpdftext.bp index eff60c3b9822a4cb2a020f01762451f589a296fb..7ae75d79fb7fbbf2f478c391621e7d50861bcde2 100644 --- a/pdfiumfpdftext.bp +++ b/pdfiumfpdftext.bp @@ -1,16 +1,9 @@ cc_library_static { name: "libpdfiumfpdftext", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", + static_libs: [ + "libpdfiumfxcrt", ], srcs: [ diff --git a/pdfiumfxcodec.bp b/pdfiumfxcodec.bp index f1ccfb532188fb7705ba66e00562e9d8ae48ccfe..f8b5fb74cffa1f1b064e409ca0c2c7346a11f32a 100644 --- a/pdfiumfxcodec.bp +++ b/pdfiumfxcodec.bp @@ -1,22 +1,26 @@ cc_library_static { name: "libpdfiumfxcodec", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", "-Wno-pointer-to-int-cast", - "-Wno-unused-parameter", + "-DUSE_SYSTEM_ZLIB", + "-DUSE_SYSTEM_LIBJPEG", + ], + + static_libs: [ + "libpdfiumfxcrt", + "libpdfiumlcms2", + "libpdfiumfx_libopenjpeg", ], - shared_libs: ["libz"], + shared_libs: [ + "libz", + "libjpeg", + ], srcs: [ + "core/fxcodec/codec/ccodec_scanlinedecoder.cpp", "core/fxcodec/codec/fx_codec.cpp", "core/fxcodec/codec/fx_codec_fax.cpp", "core/fxcodec/codec/fx_codec_flate.cpp", @@ -30,7 +34,6 @@ cc_library_static { "core/fxcodec/jbig2/JBig2_Context.cpp", "core/fxcodec/jbig2/JBig2_GrdProc.cpp", "core/fxcodec/jbig2/JBig2_GrrdProc.cpp", - "core/fxcodec/jbig2/JBig2_GsidProc.cpp", "core/fxcodec/jbig2/JBig2_HtrdProc.cpp", "core/fxcodec/jbig2/JBig2_HuffmanDecoder.cpp", "core/fxcodec/jbig2/JBig2_HuffmanTable.cpp", diff --git a/pdfiumfxcrt.bp b/pdfiumfxcrt.bp index 60e70f83234bcbc86bd1c654891455779491bd2a..5acbc28927bd15dac5f8038b68ac7c4214baf075 100644 --- a/pdfiumfxcrt.bp +++ b/pdfiumfxcrt.bp @@ -1,45 +1,42 @@ cc_library_static { name: "libpdfiumfxcrt", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], - arch: { - arm64: { - cflags: [ - "-D_FX_CPU_=_FX_X64_", - "-fPIC", - ], - }, - }, - - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", + static_libs: [ + "libpdfiumpdfiumbase" + ], - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", + shared_libs: [ + "libft2", ], srcs: [ - "core/fxcrt/fx_basic_array.cpp", - "core/fxcrt/fx_basic_bstring.cpp", - "core/fxcrt/fx_basic_buffer.cpp", - "core/fxcrt/fx_basic_coords.cpp", - "core/fxcrt/fx_basic_gcc.cpp", - "core/fxcrt/fx_basic_memmgr.cpp", - "core/fxcrt/fx_basic_utf.cpp", - "core/fxcrt/fx_basic_util.cpp", - "core/fxcrt/fx_basic_wstring.cpp", + "core/fxcrt/bytestring.cpp", + "core/fxcrt/cfx_binarybuf.cpp", + "core/fxcrt/cfx_bitstream.cpp", + "core/fxcrt/cfx_datetime.cpp", + "core/fxcrt/cfx_fileaccess_posix.cpp", + "core/fxcrt/cfx_fileaccess_windows.cpp", + "core/fxcrt/cfx_memorystream.cpp", + "core/fxcrt/cfx_seekablemultistream.cpp", + "core/fxcrt/cfx_utf8decoder.cpp", + "core/fxcrt/cfx_widetextbuf.cpp", "core/fxcrt/fx_bidi.cpp", + "core/fxcrt/fx_coordinates.cpp", "core/fxcrt/fx_extension.cpp", + "core/fxcrt/fx_memory.cpp", + "core/fxcrt/fx_random.cpp", + "core/fxcrt/fx_stream.cpp", + "core/fxcrt/fx_string.cpp", + "core/fxcrt/fx_system.cpp", "core/fxcrt/fx_ucddata.cpp", "core/fxcrt/fx_unicode.cpp", - "core/fxcrt/fx_xml_composer.cpp", - "core/fxcrt/fx_xml_parser.cpp", - "core/fxcrt/fxcrt_posix.cpp", - "core/fxcrt/fxcrt_stream.cpp", - "core/fxcrt/fxcrt_windows.cpp", + "core/fxcrt/widestring.cpp", + "core/fxcrt/xml/cxml_attritem.cpp", + "core/fxcrt/xml/cxml_content.cpp", + "core/fxcrt/xml/cxml_databufacc.cpp", + "core/fxcrt/xml/cxml_element.cpp", + "core/fxcrt/xml/cxml_object.cpp", + "core/fxcrt/xml/cxml_parser.cpp", ], } diff --git a/pdfiumfxedit.bp b/pdfiumfxedit.bp deleted file mode 100644 index 1d1622ef7fec51102b5f17e7aedc82f1150e5226..0000000000000000000000000000000000000000 --- a/pdfiumfxedit.bp +++ /dev/null @@ -1,26 +0,0 @@ -cc_library_static { - name: "libpdfiumfxedit", - defaults: ["pdfium-defaults"], - - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], - - srcs: [ - "fpdfsdk/fxedit/fxet_ap.cpp", - "fpdfsdk/fxedit/fxet_edit.cpp", - "fpdfsdk/fxedit/fxet_list.cpp", - ], - - include_dirs: [ - "external/freetype/include", - "external/freetype/include/freetype", - ], -} diff --git a/pdfiumfxge.bp b/pdfiumfxge.bp index 5350a9c37c019e6a738f477b95ccd3e14a0672e4..9c72701f2dd5de256c9b59089130c30d9726c2c8 100644 --- a/pdfiumfxge.bp +++ b/pdfiumfxge.bp @@ -1,31 +1,55 @@ cc_library_static { name: "libpdfiumfxge", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-core"], cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", + "-DDEFINE_PS_TABLES", + "-DEFINE_PS_TABLES_DATA", ], - clang_cflags: ["-Wno-switch"], + static_libs: [ + "libpdfiumfxcrt", + "libpdfiumfx_agg", + ], srcs: [ + "core/fxge/android/cfpf_skiabufferfont.cpp", "core/fxge/android/cfpf_skiadevicemodule.cpp", + "core/fxge/android/cfpf_skiafilefont.cpp", "core/fxge/android/cfpf_skiafont.cpp", + "core/fxge/android/cfpf_skiafontdescriptor.cpp", "core/fxge/android/cfpf_skiafontmgr.cpp", + "core/fxge/android/cfpf_skiapathfont.cpp", "core/fxge/android/cfx_androidfontinfo.cpp", "core/fxge/android/fx_android_imp.cpp", - "core/fxge/dib/fx_dib_composite.cpp", - "core/fxge/dib/fx_dib_convert.cpp", - "core/fxge/dib/fx_dib_engine.cpp", + "core/fxge/cfx_cliprgn.cpp", + "core/fxge/cfx_color.cpp", + "core/fxge/cfx_facecache.cpp", + "core/fxge/cfx_folderfontinfo.cpp", + "core/fxge/cfx_font.cpp", + "core/fxge/cfx_fontcache.cpp", + "core/fxge/cfx_fontmapper.cpp", + "core/fxge/cfx_fontmgr.cpp", + "core/fxge/cfx_gemodule.cpp", + "core/fxge/cfx_graphstate.cpp", + "core/fxge/cfx_graphstatedata.cpp", + "core/fxge/cfx_pathdata.cpp", + "core/fxge/cfx_renderdevice.cpp", + "core/fxge/cfx_substfont.cpp", + "core/fxge/cfx_unicodeencoding.cpp", + "core/fxge/cttfontdesc.cpp", + "core/fxge/dib/cfx_bitmapcomposer.cpp", + "core/fxge/dib/cfx_bitmapstorer.cpp", + "core/fxge/dib/cfx_dibextractor.cpp", + "core/fxge/dib/cfx_dibitmap.cpp", + "core/fxge/dib/cfx_dibsource.cpp", + "core/fxge/dib/cfx_filtereddib.cpp", + "core/fxge/dib/cfx_imagerenderer.cpp", + "core/fxge/dib/cfx_imagestretcher.cpp", + "core/fxge/dib/cfx_imagetransformer.cpp", + "core/fxge/dib/cfx_scanlinecompositor.cpp", + "core/fxge/dib/cstretchengine.cpp", "core/fxge/dib/fx_dib_main.cpp", - "core/fxge/dib/fx_dib_transform.cpp", "core/fxge/fontdata/chromefontdata/FoxitDingbats.cpp", "core/fxge/fontdata/chromefontdata/FoxitFixed.cpp", "core/fxge/fontdata/chromefontdata/FoxitFixedBold.cpp", @@ -43,25 +67,11 @@ cc_library_static { "core/fxge/fontdata/chromefontdata/FoxitSerifMM.cpp", "core/fxge/fontdata/chromefontdata/FoxitSymbol.cpp", "core/fxge/freetype/fx_freetype.cpp", - "core/fxge/ge/cfx_cliprgn.cpp", - "core/fxge/ge/cfx_facecache.cpp", - "core/fxge/ge/cfx_folderfontinfo.cpp", - "core/fxge/ge/cfx_font.cpp", - "core/fxge/ge/cfx_fontcache.cpp", - "core/fxge/ge/cfx_fontmapper.cpp", - "core/fxge/ge/cfx_fontmgr.cpp", - "core/fxge/ge/cfx_gemodule.cpp", - "core/fxge/ge/cfx_graphstate.cpp", - "core/fxge/ge/cfx_graphstatedata.cpp", - "core/fxge/ge/cfx_pathdata.cpp", - "core/fxge/ge/cfx_renderdevice.cpp", - "core/fxge/ge/cfx_substfont.cpp", - "core/fxge/ge/cfx_unicodeencoding.cpp", - "core/fxge/ge/cttfontdesc.cpp", - "core/fxge/ge/fx_ge_fontmap.cpp", - "core/fxge/ge/fx_ge_linux.cpp", - "core/fxge/ge/fx_ge_text.cpp", + "core/fxge/fx_ge_fontmap.cpp", + "core/fxge/fx_ge_linux.cpp", + "core/fxge/fx_ge_text.cpp", "core/fxge/ifx_renderdevicedriver.cpp", + "core/fxge/agg/fx_agg_driver.cpp", ], diff --git a/pdfiumfxjs.bp b/pdfiumfxjs.bp new file mode 100644 index 0000000000000000000000000000000000000000..572c95b38bf71eb09fd920613595b8e2aeb8ba05 --- /dev/null +++ b/pdfiumfxjs.bp @@ -0,0 +1,13 @@ +cc_library_static { + name: "libpdfiumfxjs", + defaults: ["pdfium-core"], + + static_libs: [ + "libpdfiumfxcrt" + ], + + srcs: [ + "fxjs/cjs_event_context_stub.cpp", + "fxjs/cjs_runtimestub.cpp", + ], +} diff --git a/pdfiumjavascript.bp b/pdfiumjavascript.bp deleted file mode 100644 index b2ae23d90858911cf25b780a9b9a8e41fc941734..0000000000000000000000000000000000000000 --- a/pdfiumjavascript.bp +++ /dev/null @@ -1,17 +0,0 @@ -cc_library_static { - name: "libpdfiumjavascript", - defaults: ["pdfium-defaults"], - - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], - - srcs: ["fpdfsdk/javascript/JS_Runtime_Stub.cpp"], -} diff --git a/pdfiumpdfwindow.bp b/pdfiumpdfwindow.bp deleted file mode 100644 index fe63c6fca3207fb9584b523b416e471aeafa058b..0000000000000000000000000000000000000000 --- a/pdfiumpdfwindow.bp +++ /dev/null @@ -1,36 +0,0 @@ -cc_library_static { - name: "libpdfiumpdfwindow", - defaults: ["pdfium-defaults"], - - cflags: [ - "-DOPJ_STATIC", - "-DV8_DEPRECATION_WARNINGS", - "-D_CRT_SECURE_NO_WARNINGS", - - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], - - srcs: [ - "fpdfsdk/pdfwindow/PWL_Button.cpp", - "fpdfsdk/pdfwindow/PWL_Caret.cpp", - "fpdfsdk/pdfwindow/PWL_ComboBox.cpp", - "fpdfsdk/pdfwindow/PWL_Edit.cpp", - "fpdfsdk/pdfwindow/PWL_EditCtrl.cpp", - "fpdfsdk/pdfwindow/PWL_FontMap.cpp", - "fpdfsdk/pdfwindow/PWL_Icon.cpp", - "fpdfsdk/pdfwindow/PWL_ListBox.cpp", - "fpdfsdk/pdfwindow/PWL_ScrollBar.cpp", - "fpdfsdk/pdfwindow/PWL_SpecialButton.cpp", - "fpdfsdk/pdfwindow/PWL_Utils.cpp", - "fpdfsdk/pdfwindow/PWL_Wnd.cpp", - "fpdfsdk/pdfwindow/cpwl_color.cpp", - ], - - include_dirs: [ - "external/freetype/include", - "external/freetype/include/freetype", - ], -} diff --git a/pdfiumpwl.bp b/pdfiumpwl.bp new file mode 100644 index 0000000000000000000000000000000000000000..78bd562810f2019692eaa61ec3661e5a9d0bd8e0 --- /dev/null +++ b/pdfiumpwl.bp @@ -0,0 +1,32 @@ +cc_library_static { + name: "libpdfiumpwl", + defaults: ["pdfium-core"], + + static_libs: [ + "libpdfiumfxcrt", + ], + + srcs: [ + "fpdfsdk/pwl/cpwl_appstream.cpp", + "fpdfsdk/pwl/cpwl_button.cpp", + "fpdfsdk/pwl/cpwl_caret.cpp", + "fpdfsdk/pwl/cpwl_combo_box.cpp", + "fpdfsdk/pwl/cpwl_edit.cpp", + "fpdfsdk/pwl/cpwl_edit_ctrl.cpp", + "fpdfsdk/pwl/cpwl_edit_impl.cpp", + "fpdfsdk/pwl/cpwl_font_map.cpp", + "fpdfsdk/pwl/cpwl_icon.cpp", + "fpdfsdk/pwl/cpwl_list_box.cpp", + "fpdfsdk/pwl/cpwl_list_impl.cpp", + "fpdfsdk/pwl/cpwl_scroll_bar.cpp", + "fpdfsdk/pwl/cpwl_special_button.cpp", + "fpdfsdk/pwl/cpwl_timer.cpp", + "fpdfsdk/pwl/cpwl_timer_handler.cpp", + "fpdfsdk/pwl/cpwl_wnd.cpp", + ], + + include_dirs: [ + "external/freetype/include", + "external/freetype/include/freetype", + ], +} diff --git a/public/PRESUBMIT.py b/public/PRESUBMIT.py new file mode 100644 index 0000000000000000000000000000000000000000..35bd873fbc924978de07bb722e5f422b8c867be8 --- /dev/null +++ b/public/PRESUBMIT.py @@ -0,0 +1,33 @@ +# Copyright 2017 The 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. + +"""Presubmit script for pdfium. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def _CheckPublicHeaders(input_api, output_api): + """Checks that the public headers match the API tests.""" + src_path = input_api.os_path.dirname(input_api.PresubmitLocalPath()) + check_script = input_api.os_path.join( + src_path, 'testing' , 'tools' , 'api_check.py') + try: + input_api.subprocess.check_output(check_script) + return [] + except input_api.subprocess.CalledProcessError as error: + return [output_api.PresubmitError('api_check.py failed:', + long_text=error.output)] + + +def CheckChangeOnUpload(input_api, output_api): + results = [] + results += _CheckPublicHeaders(input_api, output_api) + return results + + +def CheckChangeOnCommit(input_api, output_api): + results = [] + results += _CheckPublicHeaders(input_api, output_api) + return results diff --git a/public/cpp/fpdf_deleters.h b/public/cpp/fpdf_deleters.h new file mode 100644 index 0000000000000000000000000000000000000000..238ef30e62289132f9b20fb3dcc6a53922a58da3 --- /dev/null +++ b/public/cpp/fpdf_deleters.h @@ -0,0 +1,51 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PUBLIC_CPP_FPDF_DELETERS_H_ +#define PUBLIC_CPP_FPDF_DELETERS_H_ + +#include "public/fpdf_dataavail.h" +#include "public/fpdf_edit.h" +#include "public/fpdf_formfill.h" +#include "public/fpdf_structtree.h" +#include "public/fpdf_text.h" +#include "public/fpdfview.h" + +// Custom deleters for using FPDF_* types with std::unique_ptr<>. + +struct FPDFAvailDeleter { + inline void operator()(FPDF_AVAIL avail) { FPDFAvail_Destroy(avail); } +}; + +struct FPDFBitmapDeleter { + inline void operator()(FPDF_BITMAP bitmap) { FPDFBitmap_Destroy(bitmap); } +}; + +struct FPDFDocumentDeleter { + inline void operator()(FPDF_DOCUMENT doc) { FPDF_CloseDocument(doc); } +}; + +struct FPDFFormHandleDeleter { + inline void operator()(FPDF_FORMHANDLE form) { + FPDFDOC_ExitFormFillEnvironment(form); + } +}; + +struct FPDFTextPageDeleter { + inline void operator()(FPDF_TEXTPAGE text) { FPDFText_ClosePage(text); } +}; + +struct FPDFPageDeleter { + inline void operator()(FPDF_PAGE page) { FPDF_ClosePage(page); } +}; + +struct FPDFStructTreeDeleter { + inline void operator()(FPDF_STRUCTTREE tree) { FPDF_StructTree_Close(tree); } +}; + +struct FPDFFontDeleter { + inline void operator()(FPDF_FONT font) { FPDFFont_Close(font); } +}; + +#endif // PUBLIC_CPP_FPDF_DELETERS_H_ diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h new file mode 100644 index 0000000000000000000000000000000000000000..d5ef54cf3bc43d7211f18397c155fb9f5c366ba8 --- /dev/null +++ b/public/fpdf_annot.h @@ -0,0 +1,509 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PUBLIC_FPDF_ANNOT_H_ +#define PUBLIC_FPDF_ANNOT_H_ + +// NOLINTNEXTLINE(build/include) +#include "fpdfview.h" + +// NOLINTNEXTLINE(build/include) +#include "fpdf_doc.h" +// NOLINTNEXTLINE(build/include) +#include "fpdf_formfill.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#define FPDF_ANNOT_UNKNOWN 0 +#define FPDF_ANNOT_TEXT 1 +#define FPDF_ANNOT_LINK 2 +#define FPDF_ANNOT_FREETEXT 3 +#define FPDF_ANNOT_LINE 4 +#define FPDF_ANNOT_SQUARE 5 +#define FPDF_ANNOT_CIRCLE 6 +#define FPDF_ANNOT_POLYGON 7 +#define FPDF_ANNOT_POLYLINE 8 +#define FPDF_ANNOT_HIGHLIGHT 9 +#define FPDF_ANNOT_UNDERLINE 10 +#define FPDF_ANNOT_SQUIGGLY 11 +#define FPDF_ANNOT_STRIKEOUT 12 +#define FPDF_ANNOT_STAMP 13 +#define FPDF_ANNOT_CARET 14 +#define FPDF_ANNOT_INK 15 +#define FPDF_ANNOT_POPUP 16 +#define FPDF_ANNOT_FILEATTACHMENT 17 +#define FPDF_ANNOT_SOUND 18 +#define FPDF_ANNOT_MOVIE 19 +#define FPDF_ANNOT_WIDGET 20 +#define FPDF_ANNOT_SCREEN 21 +#define FPDF_ANNOT_PRINTERMARK 22 +#define FPDF_ANNOT_TRAPNET 23 +#define FPDF_ANNOT_WATERMARK 24 +#define FPDF_ANNOT_THREED 25 +#define FPDF_ANNOT_RICHMEDIA 26 +#define FPDF_ANNOT_XFAWIDGET 27 + +// Refer to PDF Reference (6th edition) table 8.16 for all annotation flags. +#define FPDF_ANNOT_FLAG_NONE 0 +#define FPDF_ANNOT_FLAG_INVISIBLE (1 << 0) +#define FPDF_ANNOT_FLAG_HIDDEN (1 << 1) +#define FPDF_ANNOT_FLAG_PRINT (1 << 2) +#define FPDF_ANNOT_FLAG_NOZOOM (1 << 3) +#define FPDF_ANNOT_FLAG_NOROTATE (1 << 4) +#define FPDF_ANNOT_FLAG_NOVIEW (1 << 5) +#define FPDF_ANNOT_FLAG_READONLY (1 << 6) +#define FPDF_ANNOT_FLAG_LOCKED (1 << 7) +#define FPDF_ANNOT_FLAG_TOGGLENOVIEW (1 << 8) + +#define FPDF_ANNOT_APPEARANCEMODE_NORMAL 0 +#define FPDF_ANNOT_APPEARANCEMODE_ROLLOVER 1 +#define FPDF_ANNOT_APPEARANCEMODE_DOWN 2 +#define FPDF_ANNOT_APPEARANCEMODE_COUNT 3 + +#define FPDF_OBJECT_UNKNOWN 0 +#define FPDF_OBJECT_BOOLEAN 1 +#define FPDF_OBJECT_NUMBER 2 +#define FPDF_OBJECT_STRING 3 +#define FPDF_OBJECT_NAME 4 +#define FPDF_OBJECT_ARRAY 5 +#define FPDF_OBJECT_DICTIONARY 6 +#define FPDF_OBJECT_STREAM 7 +#define FPDF_OBJECT_NULLOBJ 8 +#define FPDF_OBJECT_REFERENCE 9 + +// Refer to PDF Reference version 1.7 table 8.70 for field flags common to all +// interactive form field types. +#define FPDF_FORMFLAG_NONE 0 +#define FPDF_FORMFLAG_READONLY (1 << 0) +#define FPDF_FORMFLAG_REQUIRED (1 << 1) +#define FPDF_FORMFLAG_NOEXPORT (1 << 2) + +// Refer to PDF Reference version 1.7 table 8.77 for field flags specific to +// interactive form text fields. +#define FPDF_FORMFLAG_TEXT_MULTILINE (1 << 12) + +// Refer to PDF Reference version 1.7 table 8.79 for field flags specific to +// interactive form choice fields. +#define FPDF_FORMFLAG_CHOICE_COMBO (1 << 17) +#define FPDF_FORMFLAG_CHOICE_EDIT (1 << 18) + +typedef enum FPDFANNOT_COLORTYPE { + FPDFANNOT_COLORTYPE_Color = 0, + FPDFANNOT_COLORTYPE_InteriorColor +} FPDFANNOT_COLORTYPE; + +// Experimental API. +// Check if an annotation subtype is currently supported for creation. +// Currently supported subtypes: circle, highlight, ink, popup, square, +// squiggly, stamp, strikeout, text, and underline. +// +// subtype - the subtype to be checked. +// +// Returns true if this subtype supported. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype); + +// Experimental API. +// Create an annotation in |page| of the subtype |subtype|. If the specified +// subtype is illegal or unsupported, then a new annotation will not be created. +// Must call FPDFPage_CloseAnnot() when the annotation returned by this +// function is no longer needed. +// +// page - handle to a page. +// subtype - the subtype of the new annotation. +// +// Returns a handle to the new annotation object, or NULL on failure. +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV +FPDFPage_CreateAnnot(FPDF_PAGE page, FPDF_ANNOTATION_SUBTYPE subtype); + +// Experimental API. +// Get the number of annotations in |page|. +// +// page - handle to a page. +// +// Returns the number of annotations in |page|. +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotCount(FPDF_PAGE page); + +// Experimental API. +// Get annotation in |page| at |index|. Must call FPDFPage_CloseAnnot() when the +// annotation returned by this function is no longer needed. +// +// page - handle to a page. +// index - the index of the annotation. +// +// Returns a handle to the annotation object, or NULL on failure. +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV FPDFPage_GetAnnot(FPDF_PAGE page, + int index); + +// Experimental API. +// Get the index of |annot| in |page|. This is the opposite of +// FPDFPage_GetAnnot(). +// +// page - handle to the page that the annotation is on. +// annot - handle to an annotation. +// +// Returns the index of |annot|, or -1 on failure. +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotIndex(FPDF_PAGE page, + FPDF_ANNOTATION annot); + +// Experimental API. +// Close an annotation. Must be called when the annotation returned by +// FPDFPage_CreateAnnot() or FPDFPage_GetAnnot() is no longer needed. This +// function does not remove the annotation from the document. +// +// annot - handle to an annotation. +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_CloseAnnot(FPDF_ANNOTATION annot); + +// Experimental API. +// Remove the annotation in |page| at |index|. +// +// page - handle to a page. +// index - the index of the annotation. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_RemoveAnnot(FPDF_PAGE page, + int index); + +// Experimental API. +// Get the subtype of an annotation. +// +// annot - handle to an annotation. +// +// Returns the annotation subtype. +FPDF_EXPORT FPDF_ANNOTATION_SUBTYPE FPDF_CALLCONV +FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot); + +// Experimental API. +// Check if an annotation subtype is currently supported for object extraction, +// update, and removal. +// Currently supported subtypes: ink and stamp. +// +// subtype - the subtype to be checked. +// +// Returns true if this subtype supported. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_IsObjectSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype); + +// Experimental API. +// Update |obj| in |annot|. |obj| must be in |annot| already and must have +// been retrieved by FPDFAnnot_GetObject(). Currently, only ink and stamp +// annotations are supported by this API. Also note that only path, image, and +// text objects have APIs for modification; see FPDFPath_*(), FPDFText_*(), and +// FPDFImageObj_*(). +// +// annot - handle to an annotation. +// obj - handle to the object that |annot| needs to update. +// +// Return true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_UpdateObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj); + +// Experimental API. +// Add |obj| to |annot|. |obj| must have been created by +// FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj(), and +// will be owned by |annot|. Note that an |obj| cannot belong to more than one +// |annot|. Currently, only ink and stamp annotations are supported by this API. +// Also note that only path, image, and text objects have APIs for creation. +// +// annot - handle to an annotation. +// obj - handle to the object that is to be added to |annot|. +// +// Return true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_AppendObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj); + +// Experimental API. +// Get the total number of objects in |annot|, including path objects, text +// objects, external objects, image objects, and shading objects. +// +// annot - handle to an annotation. +// +// Returns the number of objects in |annot|. +FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetObjectCount(FPDF_ANNOTATION annot); + +// Experimental API. +// Get the object in |annot| at |index|. +// +// annot - handle to an annotation. +// index - the index of the object. +// +// Return a handle to the object, or NULL on failure. +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFAnnot_GetObject(FPDF_ANNOTATION annot, int index); + +// Experimental API. +// Remove the object in |annot| at |index|. +// +// annot - handle to an annotation. +// index - the index of the object to be removed. +// +// Return true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_RemoveObject(FPDF_ANNOTATION annot, int index); + +// Experimental API. +// Set the color of an annotation. Fails when called on annotations with +// appearance streams already defined; instead use +// FPDFPath_Set{Stroke|Fill}Color(). +// +// annot - handle to an annotation. +// type - type of the color to be set. +// R, G, B - buffer to hold the RGB value of the color. Ranges from 0 to 255. +// A - buffer to hold the opacity. Ranges from 0 to 255. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetColor(FPDF_ANNOTATION annot, + FPDFANNOT_COLORTYPE type, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); + +// Experimental API. +// Get the color of an annotation. If no color is specified, default to yellow +// for highlight annotation, black for all else. Fails when called on +// annotations with appearance streams already defined; instead use +// FPDFPath_Get{Stroke|Fill}Color(). +// +// annot - handle to an annotation. +// type - type of the color requested. +// R, G, B - buffer to hold the RGB value of the color. Ranges from 0 to 255. +// A - buffer to hold the opacity. Ranges from 0 to 255. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetColor(FPDF_ANNOTATION annot, + FPDFANNOT_COLORTYPE type, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A); + +// Experimental API. +// Check if the annotation is of a type that has attachment points +// (i.e. quadpoints). Quadpoints are the vertices of the rectange that +// encompasses the texts affected by the annotation. They provide the +// coordinates in the page where the annotation is attached. Only text markup +// annotations (i.e. highlight, strikeout, squiggly, and underline) and link +// annotations have quadpoints. +// +// annot - handle to an annotation. +// +// Returns true if the annotation is of a type that has quadpoints, false +// otherwise. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot); + +// Experimental API. +// Set the attachment points (i.e. quadpoints) of an annotation. If the +// annotation's appearance stream is defined and this annotation is of a type +// with quadpoints, then update the bounding box too if the new quadpoints +// define a bigger one. +// +// annot - handle to an annotation. +// quadPoints - the quadpoints to be set. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot, + const FS_QUADPOINTSF* quadPoints); + +// Experimental API. +// Get the attachment points (i.e. quadpoints) of an annotation. +// +// annot - handle to an annotation. +// quadPoints - receives the quadpoints; must not be NULL. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot, + FS_QUADPOINTSF* quadPoints); + +// Experimental API. +// Set the annotation rectangle defining the location of the annotation. If the +// annotation's appearance stream is defined and this annotation is of a type +// without quadpoints, then update the bounding box too if the new rectangle +// defines a bigger one. +// +// annot - handle to an annotation. +// rect - the annotation rectangle to be set. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetRect(FPDF_ANNOTATION annot, + const FS_RECTF* rect); + +// Experimental API. +// Get the annotation rectangle defining the location of the annotation. +// +// annot - handle to an annotation. +// rect - receives the rectangle; must not be NULL. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot, + FS_RECTF* rect); + +// Experimental API. +// Check if |annot|'s dictionary has |key| as a key. +// +// annot - handle to an annotation. +// key - the key to look for, encoded in UTF-8. +// +// Returns true if |key| exists. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot, + FPDF_BYTESTRING key); + +// Experimental API. +// Get the type of the value corresponding to |key| in |annot|'s dictionary. +// +// annot - handle to an annotation. +// key - the key to look for, encoded in UTF-8. +// +// Returns the type of the dictionary value. +FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV +FPDFAnnot_GetValueType(FPDF_ANNOTATION annot, FPDF_BYTESTRING key); + +// Experimental API. +// Set the string value corresponding to |key| in |annot|'s dictionary, +// overwriting the existing value if any. The value type would be +// FPDF_OBJECT_STRING after this function call succeeds. +// +// annot - handle to an annotation. +// key - the key to the dictionary entry to be set, encoded in UTF-8. +// value - the string value to be set, encoded in UTF16-LE. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_SetStringValue(FPDF_ANNOTATION annot, + FPDF_BYTESTRING key, + FPDF_WIDESTRING value); + +// Experimental API. +// Get the string value corresponding to |key| in |annot|'s dictionary. |buffer| +// is only modified if |buflen| is longer than the length of contents. Note that +// if |key| does not exist in the dictionary or if |key|'s corresponding value +// in the dictionary is not a string (i.e. the value is not of type +// FPDF_OBJECT_STRING or FPDF_OBJECT_NAME), then an empty string would be copied +// to |buffer| and the return value would be 2. On other errors, nothing would +// be added to |buffer| and the return value would be 0. +// +// annot - handle to an annotation. +// key - the key to the requested dictionary entry, encoded in UTF-8. +// buffer - buffer for holding the value string, encoded in UTF16-LE. +// buflen - length of the buffer. +// +// Returns the length of the string value. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAnnot_GetStringValue(FPDF_ANNOTATION annot, + FPDF_BYTESTRING key, + void* buffer, + unsigned long buflen); + +// Experimental API. +// Set the AP (appearance string) in |annot|'s dictionary for a given +// |appearanceMode|. +// +// annot - handle to an annotation. +// appearanceMode - the appearance mode (normal, rollover or down) for which +// to get the AP. +// value - the string value to be set, encoded in UTF16-LE. If +// nullptr is passed, the AP is cleared for that mode. If the +// mode is Normal, APs for all modes are cleared. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAnnot_SetAP(FPDF_ANNOTATION annot, + FPDF_ANNOT_APPEARANCEMODE appearanceMode, + FPDF_WIDESTRING value); + +// Experimental API. +// Get the AP (appearance string) from |annot|'s dictionary for a given +// |appearanceMode|. +// |buffer| is only modified if |buflen| is large enough to hold the whole AP +// string. If |buflen| is smaller, the total size of the AP is still returned, +// but nothing is copied. +// If there is no appearance stream for |annot| in |appearanceMode|, an empty +// string is written to |buf| and 2 is returned. +// On other errors, nothing is written to |buffer| and 0 is returned. +// +// annot - handle to an annotation. +// appearanceMode - the appearance mode (normal, rollover or down) for which +// to get the AP. +// buffer - buffer for holding the value string, encoded in UTF16-LE. +// buflen - length of the buffer. +// +// Returns the length of the string value. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAnnot_GetAP(FPDF_ANNOTATION annot, + FPDF_ANNOT_APPEARANCEMODE appearanceMode, + void* buffer, + unsigned long buflen); + +// Experimental API. +// Get the annotation corresponding to |key| in |annot|'s dictionary. Common +// keys for linking annotations include "IRT" and "Popup". Must call +// FPDFPage_CloseAnnot() when the annotation returned by this function is no +// longer needed. +// +// annot - handle to an annotation. +// key - the key to the requested dictionary entry, encoded in UTF-8. +// +// Returns a handle to the linked annotation object, or NULL on failure. +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV +FPDFAnnot_GetLinkedAnnot(FPDF_ANNOTATION annot, FPDF_BYTESTRING key); + +// Experimental API. +// Get the annotation flags of |annot|. +// +// annot - handle to an annotation. +// +// Returns the annotation flags. +FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetFlags(FPDF_ANNOTATION annot); + +// Experimental API. +// Set the |annot|'s flags to be of the value |flags|. +// +// annot - handle to an annotation. +// flags - the flag values to be set. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetFlags(FPDF_ANNOTATION annot, + int flags); + +// Experimental API. +// Get the annotation flags of |annot|, which is an interactive form +// annotation in |page|. +// +// page - handle to a page. +// annot - handle to an interactive form annotation. +// +// Returns the annotation flags specific to interactive forms. +FPDF_EXPORT int FPDF_CALLCONV +FPDFAnnot_GetFormFieldFlags(FPDF_PAGE page, FPDF_ANNOTATION annot); + +// Experimental API. +// Retrieves an interactive form annotation whose rectangle contains a given +// point on a page. Must call FPDFPage_CloseAnnot() when the annotation returned +// is no longer needed. +// +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// page - handle to the page, returned by FPDF_LoadPage function. +// page_x - X position in PDF "user space". +// page_y - Y position in PDF "user space". +// +// Returns the interactive form annotation whose rectangle contains the given +// coordinates on the page. If there is no such annotation, return NULL. +FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV +FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // PUBLIC_FPDF_ANNOT_H_ diff --git a/public/fpdf_attachment.h b/public/fpdf_attachment.h new file mode 100644 index 0000000000000000000000000000000000000000..7b5597480079c2d8e55d5fae884b8fb2059b0971 --- /dev/null +++ b/public/fpdf_attachment.h @@ -0,0 +1,170 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PUBLIC_FPDF_ATTACHMENT_H_ +#define PUBLIC_FPDF_ATTACHMENT_H_ + +// NOLINTNEXTLINE(build/include) +#include "fpdfview.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Experimental API. +// Get the number of embedded files in |document|. +// +// document - handle to a document. +// +// Returns the number of embedded files in |document|. +FPDF_EXPORT int FPDF_CALLCONV +FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document); + +// Experimental API. +// Add an embedded file with |name| in |document|. If |name| is empty, or if +// |name| is the name of a existing embedded file in |document|, or if +// |document|'s embedded file name tree is too deep (i.e. |document| has too +// many embedded files already), then a new attachment will not be added. +// +// document - handle to a document. +// name - name of the new attachment. +// +// Returns a handle to the new attachment object, or NULL on failure. +FPDF_EXPORT FPDF_ATTACHMENT FPDF_CALLCONV +FPDFDoc_AddAttachment(FPDF_DOCUMENT document, FPDF_WIDESTRING name); + +// Experimental API. +// Get the embedded attachment at |index| in |document|. Note that the returned +// attachment handle is only valid while |document| is open. +// +// document - handle to a document. +// index - the index of the requested embedded file. +// +// Returns the handle to the attachment object, or NULL on failure. +FPDF_EXPORT FPDF_ATTACHMENT FPDF_CALLCONV +FPDFDoc_GetAttachment(FPDF_DOCUMENT document, int index); + +// Experimental API. +// Delete the embedded attachment at |index| in |document|. Note that this does +// not remove the attachment data from the PDF file; it simply removes the +// file's entry in the embedded files name tree so that it does not appear in +// the attachment list. This behavior may change in the future. +// +// document - handle to a document. +// index - the index of the embedded file to be deleted. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFDoc_DeleteAttachment(FPDF_DOCUMENT document, int index); + +// Experimental API. +// Get the name of the |attachment| file. |buffer| is only modified if |buflen| +// is longer than the length of the file name. On errors, |buffer| is unmodified +// and the returned length is 0. +// +// attachment - handle to an attachment. +// buffer - buffer for holding the file name, encoded in UTF16-LE. +// buflen - length of the buffer. +// +// Returns the length of the file name. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAttachment_GetName(FPDF_ATTACHMENT attachment, + void* buffer, + unsigned long buflen); + +// Experimental API. +// Check if the params dictionary of |attachment| has |key| as a key. +// +// attachment - handle to an attachment. +// key - the key to look for, encoded in UTF-8. +// +// Returns true if |key| exists. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAttachment_HasKey(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key); + +// Experimental API. +// Get the type of the value corresponding to |key| in the params dictionary of +// the embedded |attachment|. +// +// attachment - handle to an attachment. +// key - the key to look for, encoded in UTF-8. +// +// Returns the type of the dictionary value. +FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV +FPDFAttachment_GetValueType(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key); + +// Experimental API. +// Set the string value corresponding to |key| in the params dictionary of the +// embedded file |attachment|, overwriting the existing value if any. The value +// type should be FPDF_OBJECT_STRING after this function call succeeds. +// +// attachment - handle to an attachment. +// key - the key to the dictionary entry, encoded in UTF-8. +// value - the string value to be set, encoded in UTF16-LE. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAttachment_SetStringValue(FPDF_ATTACHMENT attachment, + FPDF_BYTESTRING key, + FPDF_WIDESTRING value); + +// Experimental API. +// Get the string value corresponding to |key| in the params dictionary of the +// embedded file |attachment|. |buffer| is only modified if |buflen| is longer +// than the length of the string value. Note that if |key| does not exist in the +// dictionary or if |key|'s corresponding value in the dictionary is not a +// string (i.e. the value is not of type FPDF_OBJECT_STRING or +// FPDF_OBJECT_NAME), then an empty string would be copied to |buffer| and the +// return value would be 2. On other errors, nothing would be added to |buffer| +// and the return value would be 0. +// +// attachment - handle to an attachment. +// key - the key to the requested string value, encoded in UTF-8. +// buffer - buffer for holding the string value encoded in UTF16-LE. +// buflen - length of the buffer. +// +// Returns the length of the dictionary value string. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment, + FPDF_BYTESTRING key, + void* buffer, + unsigned long buflen); + +// Experimental API. +// Set the file data of |attachment|, overwriting the existing file data if any. +// The creation date and checksum will be updated, while all other dictionary +// entries will be deleted. Note that only contents with |len| smaller than +// INT_MAX is supported. +// +// attachment - handle to an attachment. +// contents - buffer holding the file data to be written in raw bytes. +// len - length of file data. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFAttachment_SetFile(FPDF_ATTACHMENT attachment, + FPDF_DOCUMENT document, + const void* contents, + const unsigned long len); + +// Experimental API. +// Get the file data of |attachment|. |buffer| is only modified if |buflen| is +// longer than the length of the file. On errors, |buffer| is unmodified and the +// returned length is 0. +// +// attachment - handle to an attachment. +// buffer - buffer for holding the file data in raw bytes. +// buflen - length of the buffer. +// +// Returns the length of the file. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAttachment_GetFile(FPDF_ATTACHMENT attachment, + void* buffer, + unsigned long buflen); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // PUBLIC_FPDF_ATTACHMENT_H_ diff --git a/public/fpdf_catalog.h b/public/fpdf_catalog.h new file mode 100644 index 0000000000000000000000000000000000000000..48d27756f3534879796449a7e38b2cf2429363ef --- /dev/null +++ b/public/fpdf_catalog.h @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PUBLIC_FPDF_CATALOG_H_ +#define PUBLIC_FPDF_CATALOG_H_ + +// NOLINTNEXTLINE(build/include) +#include "fpdfview.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Experimental API. + * + * Determine if |document| represents a tagged PDF. + * + * For the definition of tagged PDF, See (see 10.7 "Tagged PDF" in PDF + * Reference 1.7). + * + * document - handle to a document. + * + * Returns |true| iff |document| is a tagged PDF. + */ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFCatalog_IsTagged(FPDF_DOCUMENT document); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // PUBLIC_FPDF_CATALOG_H_ diff --git a/public/fpdf_dataavail.h b/public/fpdf_dataavail.h index 2413e2be7a7d2a35ee9491230807790940ee405f..3ce92110acc3bf8a7053db599cfb21704d4c571a 100644 --- a/public/fpdf_dataavail.h +++ b/public/fpdf_dataavail.h @@ -60,13 +60,13 @@ typedef void* FPDF_AVAIL; // Returns a handle to the document availability provider, or NULL on error. // // |FPDFAvail_Destroy| must be called when done with the availability provider. -DLLEXPORT FPDF_AVAIL STDCALL FPDFAvail_Create(FX_FILEAVAIL* file_avail, - FPDF_FILEACCESS* file); +FPDF_EXPORT FPDF_AVAIL FPDF_CALLCONV FPDFAvail_Create(FX_FILEAVAIL* file_avail, + FPDF_FILEACCESS* file); // Destroy the |avail| document availability provider. // // avail - handle to document availability provider to be destroyed. -DLLEXPORT void STDCALL FPDFAvail_Destroy(FPDF_AVAIL avail); +FPDF_EXPORT void FPDF_CALLCONV FPDFAvail_Destroy(FPDF_AVAIL avail); // Download hints interface. Used to receive hints for further downloading. typedef struct _FX_DOWNLOADHINTS { @@ -103,11 +103,12 @@ typedef struct _FX_DOWNLOADHINTS { // Applications should call this function whenever new data arrives, and process // all the generated download hints, if any, until the function returns // |PDF_DATA_ERROR| or |PDF_DATA_AVAIL|. +// if hints is nullptr, the function just check current document availability. // // Once all data is available, call |FPDFAvail_GetDocument| to get a document // handle. -DLLEXPORT int STDCALL -FPDFAvail_IsDocAvail(FPDF_AVAIL avail, FX_DOWNLOADHINTS* hints); +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsDocAvail(FPDF_AVAIL avail, + FX_DOWNLOADHINTS* hints); // Get document from the availability provider. // @@ -118,8 +119,8 @@ FPDFAvail_IsDocAvail(FPDF_AVAIL avail, FX_DOWNLOADHINTS* hints); // // When |FPDFAvail_IsDocAvail| returns TRUE, call |FPDFAvail_GetDocument| to // retrieve the document handle. -DLLEXPORT FPDF_DOCUMENT STDCALL FPDFAvail_GetDocument(FPDF_AVAIL avail, - FPDF_BYTESTRING password); +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV +FPDFAvail_GetDocument(FPDF_AVAIL avail, FPDF_BYTESTRING password); // Get the page number for the first available page in a linearized PDF. // @@ -130,7 +131,7 @@ DLLEXPORT FPDF_DOCUMENT STDCALL FPDFAvail_GetDocument(FPDF_AVAIL avail, // For most linearized PDFs, the first available page will be the first page, // however, some PDFs might make another page the first available page. // For non-linearized PDFs, this function will always return zero. -DLLEXPORT int STDCALL FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc); +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc); // Check if |page_index| is ready for loading, if not, get the // |FX_DOWNLOADHINTS|. @@ -150,9 +151,11 @@ DLLEXPORT int STDCALL FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc); // all the generated download |hints|, if any, until this function returns // |PDF_DATA_ERROR| or |PDF_DATA_AVAIL|. Applications can then perform page // loading. -DLLEXPORT int STDCALL FPDFAvail_IsPageAvail(FPDF_AVAIL avail, - int page_index, - FX_DOWNLOADHINTS* hints); +// if hints is nullptr, the function just check current availability of +// specified page. +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsPageAvail(FPDF_AVAIL avail, + int page_index, + FX_DOWNLOADHINTS* hints); // Check if form data is ready for initialization, if not, get the // |FX_DOWNLOADHINTS|. @@ -171,10 +174,12 @@ DLLEXPORT int STDCALL FPDFAvail_IsPageAvail(FPDF_AVAIL avail, // The application should call this function whenever new data arrives and // process all the generated download |hints|, if any, until the function // |PDF_FORM_ERROR|, |PDF_FORM_AVAIL| or |PDF_FORM_NOTEXIST|. +// if hints is nullptr, the function just check current form availability. +// // Applications can then perform page loading. It is recommend to call // |FPDFDOC_InitFormFillEnvironment| when |PDF_FORM_AVAIL| is returned. -DLLEXPORT int STDCALL FPDFAvail_IsFormAvail(FPDF_AVAIL avail, - FX_DOWNLOADHINTS* hints); +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsFormAvail(FPDF_AVAIL avail, + FX_DOWNLOADHINTS* hints); // Check whether a document is a linearized PDF. // @@ -189,7 +194,7 @@ DLLEXPORT int STDCALL FPDFAvail_IsFormAvail(FPDF_AVAIL avail, // when we have 1k of data. If the files size less than 1k, it returns // |PDF_LINEARIZATION_UNKNOWN| as there is insufficient information to determine // if the PDF is linearlized. -DLLEXPORT int STDCALL FPDFAvail_IsLinearized(FPDF_AVAIL avail); +FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsLinearized(FPDF_AVAIL avail); #ifdef __cplusplus } // extern "C" diff --git a/public/fpdf_doc.h b/public/fpdf_doc.h index 9d55a2e826d72aff31559c522e77e2cb34caaa7b..b523575967fc896d7f31e2a7d8cbdd0648e72bec 100644 --- a/public/fpdf_doc.h +++ b/public/fpdf_doc.h @@ -25,6 +25,17 @@ extern "C" { // Launch an application or open a file. #define PDFACTION_LAUNCH 4 +// View destination fit types. See pdfmark reference v9, page 48. +#define PDFDEST_VIEW_UNKNOWN_MODE 0 +#define PDFDEST_VIEW_XYZ 1 +#define PDFDEST_VIEW_FIT 2 +#define PDFDEST_VIEW_FITH 3 +#define PDFDEST_VIEW_FITV 4 +#define PDFDEST_VIEW_FITR 5 +#define PDFDEST_VIEW_FITB 6 +#define PDFDEST_VIEW_FITBH 7 +#define PDFDEST_VIEW_FITBV 8 + typedef struct _FS_QUADPOINTSF { FS_FLOAT x1; FS_FLOAT y1; @@ -44,7 +55,7 @@ typedef struct _FS_QUADPOINTSF { // // Returns a handle to the first child of |bookmark| or the first top-level // bookmark item. NULL if no child or top-level bookmark found. -DLLEXPORT FPDF_BOOKMARK STDCALL +FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark); // Get the next sibling of |bookmark|. @@ -54,7 +65,7 @@ FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark); // // Returns a handle to the next sibling of |bookmark|, or NULL if this is the // last bookmark at this level. -DLLEXPORT FPDF_BOOKMARK STDCALL +FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark); // Get the title of |bookmark|. @@ -70,9 +81,10 @@ FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark); // Regardless of the platform, the |buffer| is always in UTF-16LE encoding. The // string is terminated by a UTF16 NUL character. If |buflen| is less than the // required length, or |buffer| is NULL, |buffer| will not be modified. -DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark, - void* buffer, - unsigned long buflen); +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark, + void* buffer, + unsigned long buflen); // Find the bookmark with |title| in |document|. // @@ -83,8 +95,8 @@ DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark, // // |FPDFBookmark_Find| will always return the first bookmark found even if // multiple bookmarks have the same |title|. -DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, - FPDF_WIDESTRING title); +FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV +FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title); // Get the destination associated with |bookmark|. // @@ -93,8 +105,8 @@ DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, // // Returns the handle to the destination data, NULL if no destination is // associated with |bookmark|. -DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, - FPDF_BOOKMARK bookmark); +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV +FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark); // Get the action associated with |bookmark|. // @@ -103,7 +115,8 @@ DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, // Returns the handle to the action data, or NULL if no action is associated // with |bookmark|. When NULL is returned, |FPDFBookmark_GetDest| should be // called to get the |bookmark| destination data. -DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark); +FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV +FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark); // Get the type of |action|. // @@ -115,7 +128,7 @@ DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark); // PDFACTION_REMOTEGOTO // PDFACTION_URI // PDFACTION_LAUNCH -DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION action); +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION action); // Get the destination of |action|. // @@ -128,8 +141,8 @@ DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION action); // In the case of |PDFACTION_REMOTEGOTO|, you should first call // |FPDFAction_GetFilePath| then load that document, the document handle from // that document should pass as |document| to |FPDFAction_GetDest|. -DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, - FPDF_ACTION action); +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFAction_GetDest(FPDF_DOCUMENT document, + FPDF_ACTION action); // Get file path of a |PDFACTION_REMOTEGOTO| |action|. // @@ -138,13 +151,13 @@ DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, // buffer - a buffer for output the path string. May be NULL. // buflen - the length of the buffer, in bytes. May be 0. // -// Returns the number of bytes in the file path, including the trailing UTF16 -// NUL character. +// Returns the number of bytes in the file path, including the trailing NUL +// character. // -// Regardless of the platform, the |buffer| is always in UTF-16LE encoding. +// Regardless of the platform, the |buffer| is always in UTF-8 encoding. // If |buflen| is less than the returned length, or |buffer| is NULL, |buffer| // will not be modified. -DLLEXPORT unsigned long STDCALL +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetFilePath(FPDF_ACTION action, void* buffer, unsigned long buflen); // Get the URI path of a |PDFACTION_URI| |action|. @@ -158,10 +171,11 @@ FPDFAction_GetFilePath(FPDF_ACTION action, void* buffer, unsigned long buflen); // // The |buffer| is always encoded in 7-bit ASCII. If |buflen| is less than the // returned length, or |buffer| is NULL, |buffer| will not be modified. -DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, - FPDF_ACTION action, - void* buffer, - unsigned long buflen); +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFAction_GetURIPath(FPDF_DOCUMENT document, + FPDF_ACTION action, + void* buffer, + unsigned long buflen); // Get the page index of |dest|. // @@ -169,8 +183,20 @@ DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, // dest - handle to the destination. // // Returns the page index containing |dest|. Page indices start from 0. -DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, - FPDF_DEST dest); +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST dest); + +// Get the view (fit type) specified by |dest|. +// Experimental API. Subject to change. +// +// dest - handle to the destination. +// pNumParams - receives the number of view parameters, which is at most 4. +// pParams - buffer to write the view parameters. Must be at least 4 +// FS_FLOATs long. +// Returns one of the PDFDEST_VIEW_* constants, PDFDEST_VIEW_UNKNOWN_MODE if +// |dest| does not specify a view. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFDest_GetView(FPDF_DEST dest, unsigned long* pNumParams, FS_FLOAT* pParams); // Get the (x, y, zoom) location of |dest| in the destination page, if the // destination is in [page /XYZ x y zoom] syntax. @@ -186,13 +212,14 @@ DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, // // Note the [x, y, zoom] values are only set if the corresponding hasXVal, // hasYVal or hasZoomVal flags are true. -DLLEXPORT FPDF_BOOL STDCALL FPDFDest_GetLocationInPage(FPDF_DEST dest, - FPDF_BOOL* hasXCoord, - FPDF_BOOL* hasYCoord, - FPDF_BOOL* hasZoom, - FS_FLOAT* x, - FS_FLOAT* y, - FS_FLOAT* zoom); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFDest_GetLocationInPage(FPDF_DEST dest, + FPDF_BOOL* hasXCoord, + FPDF_BOOL* hasYCoord, + FPDF_BOOL* hasZoom, + FS_FLOAT* x, + FS_FLOAT* y, + FS_FLOAT* zoom); // Find a link at point (|x|,|y|) on |page|. // @@ -204,9 +231,9 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFDest_GetLocationInPage(FPDF_DEST dest, // // You can convert coordinates from screen coordinates to page coordinates using // |FPDF_DeviceToPage|. -DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, - double x, - double y); +FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFLink_GetLinkAtPoint(FPDF_PAGE page, + double x, + double y); // Find the Z-order of link at point (|x|,|y|) on |page|. // @@ -219,8 +246,9 @@ DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, // // You can convert coordinates from screen coordinates to page coordinates using // |FPDF_DeviceToPage|. -DLLEXPORT int STDCALL -FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, double x, double y); +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, + double x, + double y); // Get destination info for |link|. // @@ -230,15 +258,15 @@ FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page, double x, double y); // Returns a handle to the destination, or NULL if there is no destination // associated with the link. In this case, you should call |FPDFLink_GetAction| // to retrieve the action associated with |link|. -DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, - FPDF_LINK link); +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFLink_GetDest(FPDF_DOCUMENT document, + FPDF_LINK link); // Get action info for |link|. // // link - handle to the link. // // Returns a handle to the action associated to |link|, or NULL if no action. -DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK link); +FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDFLink_GetAction(FPDF_LINK link); // Enumerates all the link annotations in |page|. // @@ -248,9 +276,9 @@ DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK link); // linkAnnot - the link handle for |startPos|. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, - int* startPos, - FPDF_LINK* linkAnnot); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page, + int* startPos, + FPDF_LINK* linkAnnot); // Get the rectangle for |linkAnnot|. // @@ -258,15 +286,15 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, // rect - the annotation rectangle. // // Returns true on success. -DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, - FS_RECTF* rect); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, + FS_RECTF* rect); // Get the count of quadrilateral points to the |linkAnnot|. // // linkAnnot - handle to the link annotation. // // Returns the count of quadrilateral points. -DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot); +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot); // Get the quadrilateral points for the specified |quadIndex| in |linkAnnot|. // @@ -275,9 +303,10 @@ DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot); // quadPoints - receives the quadrilateral points. // // Returns true on success. -DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, - int quadIndex, - FS_QUADPOINTSF* quadPoints); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, + int quadIndex, + FS_QUADPOINTSF* quadPoints); // Get meta-data |tag| content from |document|. // @@ -296,10 +325,14 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, // The |buffer| is always encoded in UTF-16LE. The |buffer| is followed by two // bytes of zeros indicating the end of the string. If |buflen| is less than // the returned length, or |buffer| is NULL, |buffer| will not be modified. -DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT document, - FPDF_BYTESTRING tag, - void* buffer, - unsigned long buflen); +// +// For linearized files, FPDFAvail_IsFormAvail must be called before this, and +// it must have returned PDF_FORM_AVAIL or PDF_FORM_NOTEXIST. Before that, there +// is no guarantee the metadata has been loaded. +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetMetaText(FPDF_DOCUMENT document, + FPDF_BYTESTRING tag, + void* buffer, + unsigned long buflen); // Get the page label for |page_index| from |document|. // @@ -313,10 +346,11 @@ DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT document, // The |buffer| is always encoded in UTF-16LE. The |buffer| is followed by two // bytes of zeros indicating the end of the string. If |buflen| is less than // the returned length, or |buffer| is NULL, |buffer| will not be modified. -DLLEXPORT unsigned long STDCALL FPDF_GetPageLabel(FPDF_DOCUMENT document, - int page_index, - void* buffer, - unsigned long buflen); +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_GetPageLabel(FPDF_DOCUMENT document, + int page_index, + void* buffer, + unsigned long buflen); #ifdef __cplusplus } // extern "C" diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h index 3350b5c6a7aae6052cda1f38dc79424e25a415b1..685fbdd029592f39b52356f6e55eeada50e44e47 100644 --- a/public/fpdf_edit.h +++ b/public/fpdf_edit.h @@ -20,16 +20,71 @@ #define FPDF_GetRValue(argb) ((uint8_t)((argb) >> 16)) #define FPDF_GetAValue(argb) ((uint8_t)((argb) >> 24)) +// Refer to PDF Reference version 1.7 table 4.12 for all color space families. +#define FPDF_COLORSPACE_UNKNOWN 0 +#define FPDF_COLORSPACE_DEVICEGRAY 1 +#define FPDF_COLORSPACE_DEVICERGB 2 +#define FPDF_COLORSPACE_DEVICECMYK 3 +#define FPDF_COLORSPACE_CALGRAY 4 +#define FPDF_COLORSPACE_CALRGB 5 +#define FPDF_COLORSPACE_LAB 6 +#define FPDF_COLORSPACE_ICCBASED 7 +#define FPDF_COLORSPACE_SEPARATION 8 +#define FPDF_COLORSPACE_DEVICEN 9 +#define FPDF_COLORSPACE_INDEXED 10 +#define FPDF_COLORSPACE_PATTERN 11 + // The page object constants. +#define FPDF_PAGEOBJ_UNKNOWN 0 #define FPDF_PAGEOBJ_TEXT 1 #define FPDF_PAGEOBJ_PATH 2 #define FPDF_PAGEOBJ_IMAGE 3 #define FPDF_PAGEOBJ_SHADING 4 #define FPDF_PAGEOBJ_FORM 5 +// The path segment constants. +#define FPDF_SEGMENT_UNKNOWN -1 +#define FPDF_SEGMENT_LINETO 0 +#define FPDF_SEGMENT_BEZIERTO 1 +#define FPDF_SEGMENT_MOVETO 2 + #define FPDF_FILLMODE_ALTERNATE 1 #define FPDF_FILLMODE_WINDING 2 +#define FPDF_FONT_TYPE1 1 +#define FPDF_FONT_TRUETYPE 2 + +#define FPDF_LINECAP_BUTT 0 +#define FPDF_LINECAP_ROUND 1 +#define FPDF_LINECAP_PROJECTING_SQUARE 2 + +#define FPDF_LINEJOIN_MITER 0 +#define FPDF_LINEJOIN_ROUND 1 +#define FPDF_LINEJOIN_BEVEL 2 + +#define FPDF_PRINTMODE_EMF 0 +#define FPDF_PRINTMODE_TEXTONLY 1 +#define FPDF_PRINTMODE_POSTSCRIPT2 2 +#define FPDF_PRINTMODE_POSTSCRIPT3 3 + +typedef struct FPDF_IMAGEOBJ_METADATA { + // The image width in pixels. + unsigned int width; + // The image height in pixels. + unsigned int height; + // The image's horizontal pixel-per-inch. + float horizontal_dpi; + // The image's vertical pixel-per-inch. + float vertical_dpi; + // The number of bits used to represent each pixel. + unsigned int bits_per_pixel; + // The image's colorspace. See above for the list of FPDF_COLORSPACE_*. + int colorspace; + // The image's marked content ID. Useful for pairing with associated alt-text. + // A value of -1 indicates no ID. + int marked_content_id; +} FPDF_IMAGEOBJ_METADATA; + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -37,7 +92,7 @@ extern "C" { // Create a new PDF document. // // Returns a handle to a new document, or NULL on failure. -DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument(); +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument(); // Create a new PDF page. // @@ -52,16 +107,17 @@ DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument(); // // The page should be closed with CPDF_ClosePage() when finished as // with any other page in the document. -DLLEXPORT FPDF_PAGE STDCALL FPDFPage_New(FPDF_DOCUMENT document, - int page_index, - double width, - double height); +FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDFPage_New(FPDF_DOCUMENT document, + int page_index, + double width, + double height); // Delete the page at |page_index|. // // document - handle to document. // page_index - the index of the page to delete. -DLLEXPORT void STDCALL FPDFPage_Delete(FPDF_DOCUMENT document, int page_index); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_Delete(FPDF_DOCUMENT document, + int page_index); // Get the rotation of |page|. // @@ -72,7 +128,7 @@ DLLEXPORT void STDCALL FPDFPage_Delete(FPDF_DOCUMENT document, int page_index); // 1 - Rotated 90 degrees clockwise. // 2 - Rotated 180 degrees clockwise. // 3 - Rotated 270 degrees clockwise. -DLLEXPORT int STDCALL FPDFPage_GetRotation(FPDF_PAGE page); +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetRotation(FPDF_PAGE page); // Set rotation for |page|. // @@ -82,22 +138,31 @@ DLLEXPORT int STDCALL FPDFPage_GetRotation(FPDF_PAGE page); // 1 - Rotated 90 degrees clockwise. // 2 - Rotated 180 degrees clockwise. // 3 - Rotated 270 degrees clockwise. -DLLEXPORT void STDCALL FPDFPage_SetRotation(FPDF_PAGE page, int rotate); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetRotation(FPDF_PAGE page, int rotate); // Insert |page_obj| into |page|. // // page - handle to a page // page_obj - handle to a page object. The |page_obj| will be automatically // freed. -DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page, - FPDF_PAGEOBJECT page_obj); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertObject(FPDF_PAGE page, + FPDF_PAGEOBJECT page_obj); + +// Get number of page objects inside |page|. +// +// page - handle to a page. +// +// Returns the number of objects in |page|. +// +// DEPRECATED. Please use FPDFPage_CountObjects. +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObject(FPDF_PAGE page); // Get number of page objects inside |page|. // // page - handle to a page. // // Returns the number of objects in |page|. -DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page); +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObjects(FPDF_PAGE page); // Get object in |page| at |index|. // @@ -105,14 +170,15 @@ DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page); // index - the index of a page object. // // Returns the handle to the page object, or NULL on failed. -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPage_GetObject(FPDF_PAGE page, int index); +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPage_GetObject(FPDF_PAGE page, + int index); // Checks if |page| contains transparency. // // page - handle to a page. // // Returns TRUE if |page| contains transparency. -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_HasTransparency(FPDF_PAGE page); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_HasTransparency(FPDF_PAGE page); // Generate the content of |page|. // @@ -122,17 +188,34 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_HasTransparency(FPDF_PAGE page); // // Before you save the page to a file, or reload the page, you must call // |FPDFPage_GenerateContent| or any changes to |page| will be lost. -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GenerateContent(FPDF_PAGE page); + +// Destroy |page_obj| by releasing its resources. |page_obj| must have been +// created by FPDFPageObj_CreateNew{Path|Rect}() or +// FPDFPageObj_New{Text|Image}Obj(). This function must be called on +// newly-created objects if they are not added to a page through +// FPDFPage_InsertObject() or to an annotation through FPDFAnnot_AppendObject(). +// +// page_obj - handle to a page object. +FPDF_EXPORT void FPDF_CALLCONV FPDFPageObj_Destroy(FPDF_PAGEOBJECT page_obj); -// Checks if |pageObject| contains transparency. +// Checks if |page_object| contains transparency. // -// pageObject - handle to a page object. +// page_object - handle to a page object. // // Returns TRUE if |pageObject| contains transparency. -DLLEXPORT FPDF_BOOL STDCALL -FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT page_object); + +// Get type of |page_object|. +// +// page_object - handle to a page object. +// +// Returns one of the FPDF_PAGEOBJ_* values on success, FPDF_PAGEOBJ_UNKNOWN on +// error. +FPDF_EXPORT int FPDF_CALLCONV FPDFPageObj_GetType(FPDF_PAGEOBJECT page_object); -// Transform |pageObject| by the given matrix. +// Transform |page_object| by the given matrix. // // page_object - handle to a page object. // a - matrix value. @@ -146,13 +229,14 @@ FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject); // |a c e| // |b d f| // and can be used to scale, rotate, shear and translate the |page_object|. -DLLEXPORT void STDCALL FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object, - double a, - double b, - double c, - double d, - double e, - double f); +FPDF_EXPORT void FPDF_CALLCONV +FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object, + double a, + double b, + double c, + double d, + double e, + double f); // Transform all annotations in |page|. // @@ -168,21 +252,21 @@ DLLEXPORT void STDCALL FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object, // |a c e| // |b d f| // and can be used to scale, rotate, shear and translate the |page| annotations. -DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page, - double a, - double b, - double c, - double d, - double e, - double f); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_TransformAnnots(FPDF_PAGE page, + double a, + double b, + double c, + double d, + double e, + double f); // Create a new image object. // // document - handle to a document. // // Returns a handle to a new image object. -DLLEXPORT FPDF_PAGEOBJECT STDCALL -FPDFPageObj_NewImgeObj(FPDF_DOCUMENT document); +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFPageObj_NewImageObj(FPDF_DOCUMENT document); // Load an image from a JPEG image file and then set it into |image_object|. // @@ -198,7 +282,7 @@ FPDFPageObj_NewImgeObj(FPDF_DOCUMENT document); // for all the loaded pages. Pass |pages| and page count (|nCount|) to this API // to clear the image cache. If the image is not previously shared, or NULL is a // valid |pages| value. -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages, int nCount, FPDF_PAGEOBJECT image_object, @@ -220,7 +304,7 @@ FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages, // valid |pages| value. This function loads the JPEG image inline, so the image // content is copied to the file. This allows |fileAccess| and its associated // data to be deleted after this function returns. -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages, int nCount, FPDF_PAGEOBJECT image_object, @@ -242,13 +326,14 @@ FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages, // and can be used to scale, rotate, shear and translate the |page| annotations. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object, - double a, - double b, - double c, - double d, - double e, - double f); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object, + double a, + double b, + double c, + double d, + double e, + double f); // Set |bitmap| to |image_object|. // @@ -258,10 +343,91 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object, // bitmap - handle of the bitmap. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetBitmap(FPDF_PAGE* pages, - int nCount, - FPDF_PAGEOBJECT image_object, - FPDF_BITMAP bitmap); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFImageObj_SetBitmap(FPDF_PAGE* pages, + int nCount, + FPDF_PAGEOBJECT image_object, + FPDF_BITMAP bitmap); + +// Get a bitmap rasterisation of |image_object|. The returned bitmap will be +// owned by the caller, and FPDFBitmap_Destroy() must be called on the returned +// bitmap when it is no longer needed. +// +// image_object - handle to an image object. +// +// Returns the bitmap. +FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV +FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object); + +// Get the decoded image data of |image_object|. The decoded data is the +// uncompressed image data, i.e. the raw image data after having all filters +// applied. |buffer| is only modified if |buflen| is longer than the length of +// the decoded image data. +// +// image_object - handle to an image object. +// buffer - buffer for holding the decoded image data in raw bytes. +// buflen - length of the buffer. +// +// Returns the length of the decoded image data. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object, + void* buffer, + unsigned long buflen); + +// Get the raw image data of |image_object|. The raw data is the image data as +// stored in the PDF without applying any filters. |buffer| is only modified if +// |buflen| is longer than the length of the raw image data. +// +// image_object - handle to an image object. +// buffer - buffer for holding the raw image data in raw bytes. +// buflen - length of the buffer. +// +// Returns the length of the raw image data. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object, + void* buffer, + unsigned long buflen); + +// Get the number of filters (i.e. decoders) of the image in |image_object|. +// +// image_object - handle to an image object. +// +// Returns the number of |image_object|'s filters. +FPDF_EXPORT int FPDF_CALLCONV +FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object); + +// Get the filter at |index| of |image_object|'s list of filters. Note that the +// filters need to be applied in order, i.e. the first filter should be applied +// first, then the second, etc. |buffer| is only modified if |buflen| is longer +// than the length of the filter string. +// +// image_object - handle to an image object. +// index - the index of the filter requested. +// buffer - buffer for holding filter string, encoded in UTF-8. +// buflen - length of the buffer. +// +// Returns the length of the filter string. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object, + int index, + void* buffer, + unsigned long buflen); + +// Get the image metadata of |image_object|, including dimension, DPI, bits per +// pixel, and colorspace. If the |image_object| is not an image object or if it +// does not have an image, then the return value will be false. Otherwise, +// failure to retrieve any specific parameter would result in its value being 0. +// +// image_object - handle to an image object. +// page - handle to the page that |image_object| is on. Required for +// retrieving the image's bits per pixel and colorspace. +// metadata - receives the image metadata; must not be NULL. +// +// Returns true if successful. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object, + FPDF_PAGE page, + FPDF_IMAGEOBJ_METADATA* metadata); // Create a new path object at an initial position. // @@ -269,7 +435,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetBitmap(FPDF_PAGE* pages, // y - initial vertical position. // // Returns a handle to a new path object. -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewPath(float x, float y); +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPageObj_CreateNewPath(float x, + float y); // Create a closed path consisting of a rectangle. // @@ -279,10 +446,38 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewPath(float x, float y); // h - height of the rectangle. // // Returns a handle to the new path object. -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewRect(float x, - float y, - float w, - float h); +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPageObj_CreateNewRect(float x, + float y, + float w, + float h); + +// Get the bounding box of |page_object|. +// +// page_object - handle to a page object. +// left - pointer where the left coordinate will be stored +// bottom - pointer where the bottom coordinate will be stored +// right - pointer where the right coordinate will be stored +// top - pointer where the top coordinate will be stored +// +// Returns TRUE on success. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPageObj_GetBounds(FPDF_PAGEOBJECT page_object, + float* left, + float* bottom, + float* right, + float* top); + +// Set the blend mode of |page_object|. +// +// page_object - handle to a page object. +// blend_mode - string containing the blend mode. +// +// Blend mode can be one of following: Color, ColorBurn, ColorDodge, Darken, +// Difference, Exclusion, HardLight, Hue, Lighten, Luminosity, Multiply, Normal, +// Overlay, Saturation, Screen, SoftLight +FPDF_EXPORT void FPDF_CALLCONV +FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page_object, + FPDF_BYTESTRING blend_mode); // Set the stroke RGBA of a path. Range of values: 0 - 255. // @@ -293,11 +488,28 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewRect(float x, // A - the stroke alpha for the path. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, - unsigned int R, - unsigned int G, - unsigned int B, - unsigned int A); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); + +// Get the stroke RGBA of a path. Range of values: 0 - 255. +// +// path - the handle to the path object. +// R - the red component of the path stroke color. +// G - the green component of the path stroke color. +// B - the blue component of the path stroke color. +// A - the stroke alpha of the path. +// +// Returns TRUE on success. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPath_GetStrokeColor(FPDF_PAGEOBJECT path, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A); // Set the stroke width of a path. // @@ -305,7 +517,28 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, // width - the width of the stroke. // // Returns TRUE on success -DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width); + +// Set the line join of |page_object|. +// +// page_object - handle to a page object. +// line_join - line join +// +// Line join can be one of following: FPDF_LINEJOIN_MITER, FPDF_LINEJOIN_ROUND, +// FPDF_LINEJOIN_BEVEL +FPDF_EXPORT void FPDF_CALLCONV FPDFPath_SetLineJoin(FPDF_PAGEOBJECT page_object, + int line_join); + +// Set the line cap of |page_object|. +// +// page_object - handle to a page object. +// line_cap - line cap +// +// Line cap can be one of following: FPDF_LINECAP_BUTT, FPDF_LINECAP_ROUND, +// FPDF_LINECAP_PROJECTING_SQUARE +FPDF_EXPORT void FPDF_CALLCONV FPDFPath_SetLineCap(FPDF_PAGEOBJECT page_object, + int line_cap); // Set the fill RGBA of a path. Range of values: 0 - 255. // @@ -316,11 +549,76 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width); // A - the fill alpha for the path. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL FPDFPath_SetFillColor(FPDF_PAGEOBJECT path, - unsigned int R, - unsigned int G, - unsigned int B, - unsigned int A); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetFillColor(FPDF_PAGEOBJECT path, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); + +// Get the fill RGBA of a path. Range of values: 0 - 255. +// +// path - the handle to the path object. +// R - the red component of the path fill color. +// G - the green component of the path fill color. +// B - the blue component of the path fill color. +// A - the fill alpha of the path. +// +// Returns TRUE on success. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_GetFillColor(FPDF_PAGEOBJECT path, + unsigned int* R, + unsigned int* G, + unsigned int* B, + unsigned int* A); + +// Experimental API. +// Get number of segments inside |path|. +// +// path - handle to a path. +// +// A segment is a command, created by e.g. FPDFPath_MoveTo(), +// FPDFPath_LineTo() or FPDFPath_BezierTo(). +// +// Returns the number of objects in |path| or -1 on failure. +FPDF_EXPORT int FPDF_CALLCONV FPDFPath_CountSegments(FPDF_PAGEOBJECT path); + +// Experimental API. +// Get segment in |path| at |index|. +// +// path - handle to a path. +// index - the index of a segment. +// +// Returns the handle to the segment, or NULL on faiure. +FPDF_EXPORT FPDF_PATHSEGMENT FPDF_CALLCONV +FPDFPath_GetPathSegment(FPDF_PAGEOBJECT path, int index); + +// Experimental API. +// Get coordinates of |segment|. +// +// segment - handle to a segment. +// x - the horizontal position of the segment. +// y - the vertical position of the segment. +// +// Returns TRUE on success, otherwise |x| and |y| is not set. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPathSegment_GetPoint(FPDF_PATHSEGMENT segment, float* x, float* y); + +// Experimental API. +// Get type of |segment|. +// +// segment - handle to a segment. +// +// Returns one of the FPDF_SEGMENT_* values on success, +// FPDF_SEGMENT_UNKNOWN on error. +FPDF_EXPORT int FPDF_CALLCONV FPDFPathSegment_GetType(FPDF_PATHSEGMENT segment); + +// Experimental API. +// Gets if the |segment| closes the current subpath of a given path. +// +// segment - handle to a segment. +// +// Returns close flag for non-NULL segment, FALSE otherwise. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPathSegment_GetClose(FPDF_PATHSEGMENT segment); // Move a path's current point. // @@ -332,7 +630,9 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetFillColor(FPDF_PAGEOBJECT path, // new one. // // Returns TRUE on success -DLLEXPORT FPDF_BOOL FPDFPath_MoveTo(FPDF_PAGEOBJECT path, float x, float y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_MoveTo(FPDF_PAGEOBJECT path, + float x, + float y); // Add a line between the current point and a new point in the path. // @@ -343,7 +643,9 @@ DLLEXPORT FPDF_BOOL FPDFPath_MoveTo(FPDF_PAGEOBJECT path, float x, float y); // The path's current point is changed to (x, y). // // Returns TRUE on success -DLLEXPORT FPDF_BOOL FPDFPath_LineTo(FPDF_PAGEOBJECT path, float x, float y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_LineTo(FPDF_PAGEOBJECT path, + float x, + float y); // Add a cubic Bezier curve to the given path, starting at the current point. // @@ -356,13 +658,13 @@ DLLEXPORT FPDF_BOOL FPDFPath_LineTo(FPDF_PAGEOBJECT path, float x, float y); // y3 - the vertical position of the ending point of the Bezier curve. // // Returns TRUE on success -DLLEXPORT FPDF_BOOL FPDFPath_BezierTo(FPDF_PAGEOBJECT path, - float x1, - float y1, - float x2, - float y2, - float x3, - float y3); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_BezierTo(FPDF_PAGEOBJECT path, + float x1, + float y1, + float x2, + float y2, + float x3, + float y3); // Close the current subpath of a given path. // @@ -372,7 +674,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_BezierTo(FPDF_PAGEOBJECT path, // subpath, thus terminating the current subpath. // // Returns TRUE on success -DLLEXPORT FPDF_BOOL FPDFPath_Close(FPDF_PAGEOBJECT path); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_Close(FPDF_PAGEOBJECT path); // Set the drawing mode of a path. // @@ -382,9 +684,9 @@ DLLEXPORT FPDF_BOOL FPDFPath_Close(FPDF_PAGEOBJECT path); // stroke - a boolean specifying if the path should be stroked or not. // // Returns TRUE on success -DLLEXPORT FPDF_BOOL FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, - int fillmode, - FPDF_BOOL stroke); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, + int fillmode, + FPDF_BOOL stroke); // Create a new text object using one of the standard PDF fonts. // @@ -393,30 +695,71 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path, // font_size - the font size for the new text object. // // Returns a handle to a new text object, or NULL on failure -DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_NewTextObj(FPDF_DOCUMENT document, - FPDF_BYTESTRING font, - float font_size); +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFPageObj_NewTextObj(FPDF_DOCUMENT document, + FPDF_BYTESTRING font, + float font_size); // Set the text for a textobject. If it had text, it will be replaced. // // text_object - handle to the text object. -// text - string containing the text to be added. +// text - the UTF-16LE encoded string containing the text to be added. // // Returns TRUE on success -DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object, - FPDF_BYTESTRING text); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_SetText(FPDF_PAGEOBJECT text_object, FPDF_WIDESTRING text); -// Returns a type 1 font object loaded from a stream of data. The font is loaded -// into the document. The caller does not need to free the returned object. +// Returns a font object loaded from a stream of data. The font is loaded +// into the document. +// +// document - handle to the document. +// data - the stream of data, which will be copied by the font object. +// size - size of the stream, in bytes. +// font_type - FPDF_FONT_TYPE1 or FPDF_FONT_TRUETYPE depending on the font +// type. +// cid - a boolean specifying if the font is a CID font or not. // -// document - handle to the document. -// data - the stream of data, which will be copied by the font object. -// size - size of the stream, in bytes. +// The loaded font can be closed using FPDF_Font_Close. // // Returns NULL on failure -DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadType1Font(FPDF_DOCUMENT document, - const uint8_t* data, - uint32_t size); +FPDF_EXPORT FPDF_FONT FPDF_CALLCONV FPDFText_LoadFont(FPDF_DOCUMENT document, + const uint8_t* data, + uint32_t size, + int font_type, + FPDF_BOOL cid); + +// Set the fill RGBA of a text object. Range of values: 0 - 255. +// +// text_object - handle to the text object. +// R - the red component for the path fill color. +// G - the green component for the path fill color. +// B - the blue component for the path fill color. +// A - the fill alpha for the path. +// +// Returns TRUE on success. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_SetFillColor(FPDF_PAGEOBJECT text_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); + +// Close a loaded PDF font. +// +// font - Handle to the loaded font. +FPDF_EXPORT void FPDF_CALLCONV FPDFFont_Close(FPDF_FONT font); + +// Create a new text object using a loaded font. +// +// document - handle to the document. +// font - handle to the font object. +// font_size - the font size for the new text object. +// +// Returns a handle to a new text object, or NULL on failure +FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV +FPDFPageObj_CreateTextObj(FPDF_DOCUMENT document, + FPDF_FONT font, + float font_size); #ifdef __cplusplus } // extern "C" diff --git a/public/fpdf_ext.h b/public/fpdf_ext.h index 3465878990180d12ac488a2ddf3222957da18c4f..e488c5283bb4b293cf5763ddd639e6147e84d9ec 100644 --- a/public/fpdf_ext.h +++ b/public/fpdf_ext.h @@ -64,7 +64,7 @@ typedef struct _UNSUPPORT_INFO { // unsp_info - Pointer to an UNSUPPORT_INFO structure. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info); // Unknown page mode. @@ -89,7 +89,7 @@ FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info); // Returns one of the |PAGEMODE_*| flags defined above. // // The page mode defines how the document should be initially displayed. -DLLEXPORT int STDCALL FPDFDoc_GetPageMode(FPDF_DOCUMENT document); +FPDF_EXPORT int FPDF_CALLCONV FPDFDoc_GetPageMode(FPDF_DOCUMENT document); #ifdef __cplusplus } // extern "C" diff --git a/public/fpdf_flatten.h b/public/fpdf_flatten.h index c1e354e906757d9a018d617d7a54645c71d8635f..614540e1563bc2d3076ff0289ea2d66da2803637 100644 --- a/public/fpdf_flatten.h +++ b/public/fpdf_flatten.h @@ -35,7 +35,7 @@ extern "C" { // // Currently, all failures return |FLATTEN_FAIL| with no indication of the // cause. -DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag); +FPDF_EXPORT int FPDF_CALLCONV FPDFPage_Flatten(FPDF_PAGE page, int nFlag); #ifdef __cplusplus } // extern "C" diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h index 09b80eaf90b7734e4dcaeb90efe222b2e7dd0922..c2e2bd515ac23fe51af745956c2c976dcf1527a2 100644 --- a/public/fpdf_formfill.h +++ b/public/fpdf_formfill.h @@ -12,11 +12,14 @@ typedef void* FPDF_FORMHANDLE; -#ifdef PDF_ENABLE_XFA -#define DOCTYPE_PDF 0 // Normal pdf Document -#define DOCTYPE_DYNAMIC_XFA 1 // Dynamic xfa Document Type -#define DOCTYPE_STATIC_XFA 2 // Static xfa Document Type -#endif // PDF_ENABLE_XFA +// These values are return values for a public API, so should not be changed +// other than the count when adding new values. +#define FORMTYPE_NONE 0 // Document contains no forms +#define FORMTYPE_ACRO_FORM 1 // Forms are specified using AcroForm spec +#define FORMTYPE_XFA_FULL 2 // Forms are specified using the entire XFA spec +#define FORMTYPE_XFA_FOREGROUND \ + 3 // Forms are specified using the XFAF subset of XFA spec +#define FORMTYPE_COUNT 4 // The number of form types // Exported Functions #ifdef __cplusplus @@ -1081,7 +1084,7 @@ typedef struct _FPDF_FORMFILLINFO { * Return Value: * Return handler to the form fill module. NULL means fails. **/ -DLLEXPORT FPDF_FORMHANDLE STDCALL +FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, FPDF_FORMFILLINFO* formInfo); @@ -1094,7 +1097,8 @@ FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, * Return Value: * NULL. **/ -DLLEXPORT void STDCALL FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle); +FPDF_EXPORT void FPDF_CALLCONV +FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle); /** * Function: FORM_OnAfterLoadPage @@ -1108,8 +1112,8 @@ DLLEXPORT void STDCALL FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle); * Return Value: * NONE. **/ -DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page, - FPDF_FORMHANDLE hHandle); +FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle); /** * Function: FORM_OnBeforeClosePage @@ -1124,8 +1128,8 @@ DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page, * Return Value: * NONE. **/ -DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page, - FPDF_FORMHANDLE hHandle); +FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle); /** * Function: FORM_DoDocumentJSAction @@ -1142,7 +1146,7 @@ DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page, *document, this method will execute the javascript action; * otherwise, the method will do nothing. **/ -DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle); +FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle); /** * Function: FORM_DoDocumentOpenAction @@ -1157,7 +1161,8 @@ DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle); * This method will do nothing if there is no open-actions embedded in *the document. **/ -DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle); +FPDF_EXPORT void FPDF_CALLCONV +FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle); // additional actions type of document. #define FPDFDOC_AACTION_WC \ @@ -1187,8 +1192,8 @@ DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle); *additional-action corresponding to the specified aaType. **/ -DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, - int aaType); +FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, + int aaType); // Additional-action types of page object #define FPDFPAGE_AACTION_OPEN \ @@ -1213,9 +1218,9 @@ DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, * This method will do nothing if no additional-action corresponding to *the specified aaType exists. **/ -DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page, - FPDF_FORMHANDLE hHandle, - int aaType); +FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle, + int aaType); /** * Function: FORM_OnMouseMove @@ -1233,11 +1238,34 @@ DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y); + +/** + * Function: FORM_OnFocus + * This function focuses the form annotation at a given point. If the + * annotation at the point already has focus, nothing happens. If there + * is no annotation at the point, remove form focus. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage. + * modifier - Indicates whether various virtual keys are down. + * page_x - Specifies the x-coordinate of the cursor in PDF user + * space. + * page_y - Specifies the y-coordinate of the cursor in PDF user + * space. + * Return Value: + * TRUE if there is an annotation at the given point and it has focus. + **/ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y); /** * Function: FORM_OnLButtonDown @@ -1256,11 +1284,11 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y); /** * Function: FORM_OnLButtonUp @@ -1277,23 +1305,23 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y); #ifdef PDF_ENABLE_XFA -DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y); -DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int modifier, - double page_x, - double page_y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y); #endif // PDF_ENABLE_XFA /** @@ -1310,10 +1338,10 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int nKeyCode, - int modifier); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nKeyCode, + int modifier); /** * Function: FORM_OnKeyUp @@ -1329,10 +1357,10 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int nKeyCode, - int modifier); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nKeyCode, + int modifier); /** * Function: FORM_OnChar @@ -1349,10 +1377,54 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_OnChar(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - int nChar, - int modifier); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nChar, + int modifier); + +/** + * Function: FORM_GetSelectedText + * You can call this function to obtain selected text within + * a form text field or form combobox text field. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage + * function. + * buffer - Buffer for holding the selected text, encoded + * in UTF16-LE. If NULL, |buffer| is not modified. + * buflen - Length of |buffer| in bytes. If |buflen| + is less than the length of the selected text + string, |buffer| is not modified. + * Return Value: + * Length in bytes of selected text in form text field or form combobox + * text field. + **/ +FPDF_EXPORT unsigned long FPDF_CALLCONV +FORM_GetSelectedText(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + void* buffer, + unsigned long buflen); + +/** + * Function: FORM_ReplaceSelection + * You can call this function to replace the selected text in a form + * text field or user-editable form combobox text field with another + * text string (which can be empty or non-empty). If there is no + * selected text, this function will append the replacement text after + * the current caret position. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage + * function. + * wsText - The text to be inserted, in UTF-16LE format. + * Return Value: + * None. + **/ +FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + FPDF_WIDESTRING wsText); /** * Function: FORM_ForceToKillFocus. @@ -1366,9 +1438,12 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_OnChar(FPDF_FORMHANDLE hHandle, * Return Value: * TRUE indicates success; otherwise false. **/ -DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle); -// Field Types +// Form Field Types +// The names of the defines are stable, but the specific values associated with +// them are not, so do not hardcode their values. #define FPDF_FORMFIELD_UNKNOWN 0 // Unknown. #define FPDF_FORMFIELD_PUSHBUTTON 1 // push button type. #define FPDF_FORMFIELD_CHECKBOX 2 // check box type. @@ -1376,8 +1451,33 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle); #define FPDF_FORMFIELD_COMBOBOX 4 // combo box type. #define FPDF_FORMFIELD_LISTBOX 5 // list box type. #define FPDF_FORMFIELD_TEXTFIELD 6 // text field type. +#define FPDF_FORMFIELD_SIGNATURE 7 // text field type. #ifdef PDF_ENABLE_XFA -#define FPDF_FORMFIELD_XFA 7 // text field type. +#define FPDF_FORMFIELD_XFA 8 // Generic XFA type. +#define FPDF_FORMFIELD_XFA_CHECKBOX 9 // XFA check box type. +#define FPDF_FORMFIELD_XFA_COMBOBOX 10 // XFA combo box type. +#define FPDF_FORMFIELD_XFA_IMAGEFIELD 11 // XFA image field type. +#define FPDF_FORMFIELD_XFA_LISTBOX 12 // XFA list box type. +#define FPDF_FORMFIELD_XFA_PUSHBUTTON 13 // XFA push button type. +#define FPDF_FORMFIELD_XFA_SIGNATURE 14 // XFA signture field type. +#define FPDF_FORMFIELD_XFA_TEXTFIELD 15 // XFA text field type. +#endif // PDF_ENABLE_XFA + +#ifndef PDF_ENABLE_XFA +#define FPDF_FORMFIELD_COUNT 8 +#else +#define FPDF_FORMFIELD_COUNT 16 +#endif // PDF_ENABLE_XFA + +#ifdef PDF_ENABLE_XFA +#define IS_XFA_FORMFIELD(type) \ + ((type == FPDF_FORMFIELD_XFA) || (type == FPDF_FORMFIELD_XFA_CHECKBOX) || \ + (type == FPDF_FORMFIELD_XFA_COMBOBOX) || \ + (type == FPDF_FORMFIELD_XFA_IMAGEFIELD) || \ + (type == FPDF_FORMFIELD_XFA_LISTBOX) || \ + (type == FPDF_FORMFIELD_XFA_PUSHBUTTON) || \ + (type == FPDF_FORMFIELD_XFA_SIGNATURE) || \ + (type == FPDF_FORMFIELD_XFA_TEXTFIELD)) #endif // PDF_ENABLE_XFA /** @@ -1393,19 +1493,11 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle); * Return the type of the form field; -1 indicates no field. * See field types above. **/ -DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y); - -/** - * Function: FPDPage_HasFormFieldAtPoint - * DEPRECATED. Please use FPDFPage_HasFormFieldAtPoint. - **/ -DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y); +FPDF_EXPORT int FPDF_CALLCONV +FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y); /** * Function: FPDFPage_FormFieldZOrderAtPoint @@ -1420,10 +1512,11 @@ DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, * Return the z-order of the form field; -1 indicates no field. * Higher numbers are closer to the front. **/ -DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page, - double page_x, - double page_y); +FPDF_EXPORT int FPDF_CALLCONV +FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y); /** * Function: FPDF_SetFormFieldHighlightColor @@ -1441,15 +1534,16 @@ DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, * Return Value: * NONE. * Comments: - * When the parameter fieldType is set to zero, the highlight color - *will be applied to all the form fields in the + * When the parameter fieldType is set to FPDF_FORMFIELD_UNKNOWN, the + * highlight color will be applied to all the form fields in the * document. * Please refresh the client window to show the highlight immediately - *if necessary. + * if necessary. **/ -DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, - int fieldType, - unsigned long color); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, + int fieldType, + unsigned long color); /** * Function: FPDF_SetFormFieldHighlightAlpha @@ -1465,8 +1559,8 @@ DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, * Return Value: * NONE. **/ -DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, - unsigned char alpha); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha); /** * Function: FPDF_RemoveFormFieldHighlight @@ -1480,7 +1574,8 @@ DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, * Please refresh the client window to remove the highlight immediately *if necessary. **/ -DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle); /** * Function: FPDF_FFLDraw @@ -1520,45 +1615,44 @@ DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle); *call this function after rendering functions, such as FPDF_RenderPageBitmap or *FPDF_RenderPageBitmap_Start, finish rendering the page contents. **/ -DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, - FPDF_BITMAP bitmap, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags); +FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, + FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags); #ifdef _SKIA_SUPPORT_ -DLLEXPORT void STDCALL FPDF_FFLRecord(FPDF_FORMHANDLE hHandle, - FPDF_RECORDER recorder, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags); +FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLRecord(FPDF_FORMHANDLE hHandle, + FPDF_RECORDER recorder, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags); #endif -#ifdef PDF_ENABLE_XFA /** - * Function: FPDF_HasXFAField - * This method is designed to check whether a pdf document - *has XFA fields. + * Experimental API + * Function: FPDF_GetFormType + * Returns the type of form contained in the PDF document. * Parameters: * document - Handle to document. *Returned by FPDF_LoadDocument function. * docType - Document type defined as - *DOCTYPE_xxx. + *FORMTYPE_xxx. * Return Value: - * TRUE indicates that the input document has XFA fields, - *otherwise FALSE. + * Integer value representing one of the FORMTYPE_xxx + *values. **/ -DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document, - int* docType); +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document); +#ifdef PDF_ENABLE_XFA /** * Function: FPDF_LoadXFA * If the document consists of XFA fields, there should call this @@ -1569,7 +1663,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document, * Return Value: * TRUE indicates success,otherwise FALSE. **/ -DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document); /** * Function: FPDF_Widget_Undo @@ -1582,8 +1676,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document); * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget); +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Undo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget); /** * Function: FPDF_Widget_Redo * This method will implement the redo feature for the specified xfa @@ -1595,8 +1689,8 @@ DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_Widget_Redo(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget); +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Redo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget); /** * Function: FPDF_Widget_SelectAll * This method will implement the select all feature for the specified @@ -1608,8 +1702,8 @@ DLLEXPORT void STDCALL FPDF_Widget_Redo(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_Widget_SelectAll(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget); +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_SelectAll(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget); /** * Function: FPDF_Widget_Copy * This method will implement the copy feature for the specified xfa @@ -1624,10 +1718,10 @@ DLLEXPORT void STDCALL FPDF_Widget_SelectAll(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget, - FPDF_WIDESTRING wsText, - FPDF_DWORD* size); +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Copy(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size); /** * Function: FPDF_Widget_Cut * This method will implement the cut feature for the specified xfa @@ -1642,10 +1736,10 @@ DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget, - FPDF_WIDESTRING wsText, - FPDF_DWORD* size); +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Cut(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size); /** * Function: FPDF_Widget_Paste * This method will implement the paste feature for the specified xfa @@ -1659,10 +1753,10 @@ DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_Widget_Paste(FPDF_DOCUMENT document, - FPDF_WIDGET hWidget, - FPDF_WIDESTRING wsText, - FPDF_DWORD size); +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Paste(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD size); /** * Function: FPDF_Widget_ReplaceSpellCheckWord * This method will implement the spell check feature for the specified @@ -1678,7 +1772,7 @@ DLLEXPORT void STDCALL FPDF_Widget_Paste(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document, FPDF_WIDGET hWidget, float x, @@ -1687,19 +1781,20 @@ FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document, /** * Function: FPDF_Widget_GetSpellCheckWords * This method will implement the spell check feature for the specified - *xfa field. + * xfa field. * Parameters: - * document - Handle to document. Returned by - *FPDF_LoadDocument function. + * document - Handle to document as returned by + * FPDF_LoadDocument function. * hWidget - Handle to the xfa field. * x - The x value of the specified point. * y - The y value of the specified point. * stringHandle - Pointer to FPDF_STRINGHANDLE to receive the - *speck check text buffer, in UTF-16LE format. + * speck check text buffer, in UTF-16LE format. + * Caller must free using FPDF_StringHandleRelease. * Return Value: * None. **/ -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document, FPDF_WIDGET hWidget, float x, @@ -1713,7 +1808,8 @@ FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document, * Return Value: * None. **/ -DLLEXPORT int STDCALL FPDF_StringHandleCounts(FPDF_STRINGHANDLE stringHandle); +FPDF_EXPORT int FPDF_CALLCONV +FPDF_StringHandleCounts(FPDF_STRINGHANDLE stringHandle); /** * Function: FPDF_StringHandleGetStringByIndex * This method will get the specified index of the text buffer. @@ -1726,7 +1822,7 @@ DLLEXPORT int STDCALL FPDF_StringHandleCounts(FPDF_STRINGHANDLE stringHandle); * Return Value: * TRUE indicates success, otherwise FALSE. **/ -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE stringHandle, int index, FPDF_BYTESTRING bsText, @@ -1739,7 +1835,8 @@ FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE stringHandle, * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle); /** * Function: FPDF_StringHandleAddString * This method will add the specified text buffer. @@ -1751,7 +1848,7 @@ DLLEXPORT void STDCALL FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle); * Return Value: * TRUE indicates success, otherwise FALSE. **/ -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle, FPDF_BYTESTRING bsText, FPDF_DWORD size); diff --git a/public/fpdf_ppo.h b/public/fpdf_ppo.h index d9c83002b58f263bb1bf01e87abf0cd97a2fdbb5..88c3162ecbc8d53d44dd99466f0047d0dd1313be 100644 --- a/public/fpdf_ppo.h +++ b/public/fpdf_ppo.h @@ -23,10 +23,10 @@ extern "C" { // index - The page index to insert at. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, - FPDF_DOCUMENT src_doc, - FPDF_BYTESTRING pagerange, - int index); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc, + FPDF_DOCUMENT src_doc, + FPDF_BYTESTRING pagerange, + int index); // Copy the viewer preferences from |src_doc| into |dest_doc|. // @@ -34,8 +34,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc, // src_doc - Document to read the viewer preferences from. // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, - FPDF_DOCUMENT src_doc); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc); #ifdef __cplusplus } // extern "C" diff --git a/public/fpdf_progressive.h b/public/fpdf_progressive.h index 0c3d501317b4755dd778a57b3b358e29ca4b04a9..3f0ae293a85c1f0c8480a69c79f92732bc9da088 100644 --- a/public/fpdf_progressive.h +++ b/public/fpdf_progressive.h @@ -11,8 +11,10 @@ #include "fpdfview.h" // Flags for progressive process status. -#define FPDF_RENDER_READER 0 -#define FPDF_RENDER_TOBECOUNTINUED 1 +#define FPDF_RENDER_READY 0 +#define FPDF_RENDER_READER 0 // Deprecated +#define FPDF_RENDER_TOBECONTINUED 1 +#define FPDF_RENDER_TOBECOUNTINUED 1 // Deprecated. #define FPDF_RENDER_DONE 2 #define FPDF_RENDER_FAILED 3 @@ -77,15 +79,15 @@ typedef struct _IFSDK_PAUSE { // Rendering Status. See flags for progressive process status for the // details. // -DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags, - IFSDK_PAUSE* pause); +FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags, + IFSDK_PAUSE* pause); // Function: FPDF_RenderPage_Continue // Continue rendering a PDF page. @@ -99,8 +101,8 @@ DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap, // Return value: // The rendering status. See flags for progressive process status for // the details. -DLLEXPORT int STDCALL FPDF_RenderPage_Continue(FPDF_PAGE page, - IFSDK_PAUSE* pause); +FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPage_Continue(FPDF_PAGE page, + IFSDK_PAUSE* pause); // Function: FPDF_RenderPage_Close // Release the resource allocate during page rendering. Need to be @@ -111,7 +113,7 @@ DLLEXPORT int STDCALL FPDF_RenderPage_Continue(FPDF_PAGE page, // function. // Return value: // NULL -DLLEXPORT void STDCALL FPDF_RenderPage_Close(FPDF_PAGE page); +FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage_Close(FPDF_PAGE page); #ifdef __cplusplus } diff --git a/public/fpdf_save.h b/public/fpdf_save.h index c34e2bc6c7173996ac7f5768ca5893a741cc8d58..6ffca52ee38916ab91df6b4dbd186dae91b0f36c 100644 --- a/public/fpdf_save.h +++ b/public/fpdf_save.h @@ -59,9 +59,9 @@ typedef struct FPDF_FILEWRITE_ { // Return value: // TRUE for succeed, FALSE for failed. // -DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveAsCopy(FPDF_DOCUMENT document, - FPDF_FILEWRITE* pFileWrite, - FPDF_DWORD flags); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document, + FPDF_FILEWRITE* pFileWrite, + FPDF_DWORD flags); // Function: FPDF_SaveWithVersion // Same as function ::FPDF_SaveAsCopy, except the file version of the @@ -75,10 +75,11 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveAsCopy(FPDF_DOCUMENT document, // Return value: // TRUE if succeed, FALSE if failed. // -DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveWithVersion(FPDF_DOCUMENT document, - FPDF_FILEWRITE* pFileWrite, - FPDF_DWORD flags, - int fileVersion); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_SaveWithVersion(FPDF_DOCUMENT document, + FPDF_FILEWRITE* pFileWrite, + FPDF_DWORD flags, + int fileVersion); #ifdef __cplusplus } diff --git a/public/fpdf_searchex.h b/public/fpdf_searchex.h index 7c1b31848e7ea7da7bf85627ed6879ff8177bd8f..207c1046c1d6f6f51ca06e1667923cbef1bf9def 100644 --- a/public/fpdf_searchex.h +++ b/public/fpdf_searchex.h @@ -20,9 +20,18 @@ extern "C" { // nTextIndex - index of the text returned from |FPDFText_GetText|. // // Returns the index of the character in internal character list. -1 for error. -DLLEXPORT int STDCALL +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetCharIndexFromTextIndex(FPDF_TEXTPAGE text_page, int nTextIndex); +// Get the text index in |text_page| internal character list. +// +// text_page - a text page information structure. +// nCharIndex - index of the character in internal character list. +// +// Returns the index of the text returned from |FPDFText_GetText|. -1 for error. +FPDF_EXPORT int FPDF_CALLCONV +FPDFText_GetTextIndexFromCharIndex(FPDF_TEXTPAGE text_page, int nCharIndex); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/public/fpdf_structtree.h b/public/fpdf_structtree.h index 3d4da402aa53c07a36e4af904c46f9cbf376b4a3..2e86ae65b30aade62e1f033c45688a668ef96a99 100644 --- a/public/fpdf_structtree.h +++ b/public/fpdf_structtree.h @@ -21,7 +21,8 @@ extern "C" { // function. // Return value: // A handle to the structure tree or NULL on error. -DLLEXPORT FPDF_STRUCTTREE STDCALL FPDF_StructTree_GetForPage(FPDF_PAGE page); +FPDF_EXPORT FPDF_STRUCTTREE FPDF_CALLCONV +FPDF_StructTree_GetForPage(FPDF_PAGE page); // Function: FPDF_StructTree_Close // Release the resource allocate by FPDF_StructTree_GetForPage. @@ -30,7 +31,8 @@ DLLEXPORT FPDF_STRUCTTREE STDCALL FPDF_StructTree_GetForPage(FPDF_PAGE page); // FPDF_StructTree_LoadPage function. // Return value: // NULL -DLLEXPORT void STDCALL FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree); // Function: FPDF_StructTree_CountChildren // Count the number of children for the structure tree. @@ -39,7 +41,7 @@ DLLEXPORT void STDCALL FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree); // FPDF_StructTree_LoadPage function. // Return value: // The number of children, or -1 on error. -DLLEXPORT int STDCALL +FPDF_EXPORT int FPDF_CALLCONV FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree); // Function: FPDF_StructTree_GetChildAtIndex @@ -50,7 +52,7 @@ FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree); // index - The index for the child, 0-based. // Return value: // The child at the n-th index or NULL on error. -DLLEXPORT FPDF_STRUCTELEMENT STDCALL +FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index); // Function: FPDF_StructElement_GetAltText @@ -68,18 +70,68 @@ FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index); // encoding. The string is terminated by a UTF16 NUL character. If // |buflen| is less than the required length, or |buffer| is NULL, // |buffer| will not be modified. -DLLEXPORT unsigned long STDCALL +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element, void* buffer, unsigned long buflen); +// Function: FPDF_StructElement_GetMarkedContentID +// Get the marked content ID for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// Return value: +// The marked content ID of the element. If no ID exists, returns +// -1. +FPDF_EXPORT int FPDF_CALLCONV +FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element); + +// Function: FPDF_StructElement_GetType +// Get the type (/S) for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the type, including the terminating NUL +// character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element, + void* buffer, + unsigned long buflen); + +// Function: FPDF_StructElement_GetTitle +// Get the title (/T) for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the title, including the terminating NUL +// character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element, + void* buffer, + unsigned long buflen); + // Function: FPDF_StructElement_CountChildren // Count the number of children for the structure element. // Parameters: // struct_element - Handle to the struct element. // Return value: // The number of children, or -1 on error. -DLLEXPORT int STDCALL +FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element); // Function: FPDF_StructElement_GetChildAtIndex @@ -92,12 +144,12 @@ FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element); // Comments: // If the child exists but is not an element, then this function will // return NULL. This will also return NULL for out of bounds indices. -DLLEXPORT FPDF_STRUCTELEMENT STDCALL +FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element, int index); #ifdef __cplusplus -} +} // extern "C" #endif #endif // PUBLIC_FPDF_STRUCTTREE_H_ diff --git a/public/fpdf_sysfontinfo.h b/public/fpdf_sysfontinfo.h index a0edffffa27ee5fbe563f8b14f56e98d35cf2cf1..49302c892f103034d73fb409993d14e815ce36d7 100644 --- a/public/fpdf_sysfontinfo.h +++ b/public/fpdf_sysfontinfo.h @@ -20,7 +20,7 @@ #define FXFONT_CHINESEBIG5_CHARSET 136 /* Font pitch and family flags */ -#define FXFONT_FF_FIXEDPITCH 1 +#define FXFONT_FF_FIXEDPITCH (1 << 0) #define FXFONT_FF_ROMAN (1 << 4) #define FXFONT_FF_SCRIPT (4 << 4) @@ -106,10 +106,7 @@ typedef struct _FPDF_SYSFONTINFO { *constants. * face - Typeface name. Currently use system local encoding *only. - * bExact - Pointer to a boolean value receiving the indicator - *whether mapper found the exact match. - * If mapper is not sure whether it's exact match, - *ignore this paramter. + * bExact - Obsolete: this parameter is now ignored. * Return Value: * An opaque pointer for font handle, or NULL if system mapping is *not supported. @@ -244,7 +241,7 @@ typedef struct FPDF_CharsetFontMap_ { * Return Value: * Pointer to the Charset Font Map. **/ -DLLEXPORT const FPDF_CharsetFontMap* STDCALL FPDF_GetDefaultTTFMap(); +FPDF_EXPORT const FPDF_CharsetFontMap* FPDF_CALLCONV FPDF_GetDefaultTTFMap(); /** * Function: FPDF_AddInstalledFont @@ -259,9 +256,9 @@ DLLEXPORT const FPDF_CharsetFontMap* STDCALL FPDF_GetDefaultTTFMap(); * Return Value: * None. **/ -DLLEXPORT void STDCALL FPDF_AddInstalledFont(void* mapper, - const char* face, - int charset); +FPDF_EXPORT void FPDF_CALLCONV FPDF_AddInstalledFont(void* mapper, + const char* face, + int charset); /** * Function: FPDF_SetSystemFontInfo @@ -275,7 +272,8 @@ DLLEXPORT void STDCALL FPDF_AddInstalledFont(void* mapper, * Return Value: * None **/ -DLLEXPORT void STDCALL FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfo); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfo); /** * Function: FPDF_GetDefaultSystemFontInfo @@ -294,7 +292,7 @@ DLLEXPORT void STDCALL FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfo); * Application should call FPDF_FreeDefaultSystemFontInfo to free the *returned pointer. **/ -DLLEXPORT FPDF_SYSFONTINFO* STDCALL FPDF_GetDefaultSystemFontInfo(); +FPDF_EXPORT FPDF_SYSFONTINFO* FPDF_CALLCONV FPDF_GetDefaultSystemFontInfo(); /** * Function: FPDF_FreeDefaultSystemFontInfo @@ -307,7 +305,8 @@ DLLEXPORT FPDF_SYSFONTINFO* STDCALL FPDF_GetDefaultSystemFontInfo(); * Return Value: * None **/ -DLLEXPORT void FPDF_FreeDefaultSystemFontInfo(FPDF_SYSFONTINFO* pFontInfo); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_FreeDefaultSystemFontInfo(FPDF_SYSFONTINFO* pFontInfo); #ifdef __cplusplus } diff --git a/public/fpdf_text.h b/public/fpdf_text.h index 5c241527ebd4018c6c4bb1d79476297bd8790998..043dc169c99f70d56c0dfffadd29fa2b0018e614 100644 --- a/public/fpdf_text.h +++ b/public/fpdf_text.h @@ -27,7 +27,7 @@ extern "C" { // Application must call FPDFText_ClosePage to release the text page // information. // -DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page); +FPDF_EXPORT FPDF_TEXTPAGE FPDF_CALLCONV FPDFText_LoadPage(FPDF_PAGE page); // Function: FPDFText_ClosePage // Release all resources allocated for a text page information @@ -38,7 +38,7 @@ DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page); // Return Value: // None. // -DLLEXPORT void STDCALL FPDFText_ClosePage(FPDF_TEXTPAGE text_page); +FPDF_EXPORT void FPDF_CALLCONV FPDFText_ClosePage(FPDF_TEXTPAGE text_page); // Function: FPDFText_CountChars // Get number of characters in a page. @@ -56,7 +56,7 @@ DLLEXPORT void STDCALL FPDFText_ClosePage(FPDF_TEXTPAGE text_page); // first character in the page // has an index value of zero. // -DLLEXPORT int STDCALL FPDFText_CountChars(FPDF_TEXTPAGE text_page); +FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountChars(FPDF_TEXTPAGE text_page); // Function: FPDFText_GetUnicode // Get Unicode of a character in a page. @@ -70,8 +70,8 @@ DLLEXPORT int STDCALL FPDFText_CountChars(FPDF_TEXTPAGE text_page); // convert to Unicode, // the return value will be zero. // -DLLEXPORT unsigned int STDCALL FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, - int index); +FPDF_EXPORT unsigned int FPDF_CALLCONV +FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, int index); // Function: FPDFText_GetFontSize // Get the font size of a particular character. @@ -84,8 +84,8 @@ DLLEXPORT unsigned int STDCALL FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, // 1/72 inch). // This is the typographic size of the font (so called "em size"). // -DLLEXPORT double STDCALL FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, - int index); +FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, + int index); // Function: FPDFText_GetCharBox // Get bounding box of a particular character. @@ -102,16 +102,39 @@ DLLEXPORT double STDCALL FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, // top - Pointer to a double number receiving top position of // the character box. // Return Value: -// None. +// On success, return TRUE and fill in |left|, |right|, |bottom|, and +// |top|. If |text_page| is invalid, or if |index| is out of bounds, +// then return FALSE, and the out parameters remain unmodified. // Comments: // All positions are measured in PDF "user space". // -DLLEXPORT void STDCALL FPDFText_GetCharBox(FPDF_TEXTPAGE text_page, - int index, - double* left, - double* right, - double* bottom, - double* top); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetCharBox(FPDF_TEXTPAGE text_page, + int index, + double* left, + double* right, + double* bottom, + double* top); + +// Function: FPDFText_GetCharOrigin +// Get origin of a particular character. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// x - Pointer to a double number receiving x coordinate of +// the character origin. +// y - Pointer to a double number receiving y coordinate of +// the character origin. +// Return Value: +// Whether the call succeeded. If false, x and y are unchanged. +// Comments: +// All positions are measured in PDF "user space". +// +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFText_GetCharOrigin(FPDF_TEXTPAGE text_page, + int index, + double* x, + double* y); // Function: FPDFText_GetCharIndexAtPos // Get the index of a character at or nearby a certain position on the @@ -131,11 +154,12 @@ DLLEXPORT void STDCALL FPDFText_GetCharBox(FPDF_TEXTPAGE text_page, // be -1. // If an error occurs, -3 will be returned. // -DLLEXPORT int STDCALL FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page, - double x, - double y, - double xTolerance, - double yTolerance); +FPDF_EXPORT int FPDF_CALLCONV +FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page, + double x, + double y, + double xTolerance, + double yTolerance); // Function: FPDFText_GetText // Extract unicode text string from the page. @@ -154,10 +178,10 @@ DLLEXPORT int STDCALL FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page, // Comments: // This function ignores characters without unicode information. // -DLLEXPORT int STDCALL FPDFText_GetText(FPDF_TEXTPAGE text_page, - int start_index, - int count, - unsigned short* result); +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetText(FPDF_TEXTPAGE text_page, + int start_index, + int count, + unsigned short* result); // Function: FPDFText_CountRects // Count number of rectangular areas occupied by a segment of texts. @@ -177,9 +201,9 @@ DLLEXPORT int STDCALL FPDFText_GetText(FPDF_TEXTPAGE text_page, // one if those characters // are on the same line and use same font settings. // -DLLEXPORT int STDCALL FPDFText_CountRects(FPDF_TEXTPAGE text_page, - int start_index, - int count); +FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountRects(FPDF_TEXTPAGE text_page, + int start_index, + int count); // Function: FPDFText_GetRect // Get a rectangular area from the result generated by @@ -197,14 +221,18 @@ DLLEXPORT int STDCALL FPDFText_CountRects(FPDF_TEXTPAGE text_page, // bottom - Pointer to a double value receiving the rectangle // bottom boundary. // Return Value: -// None. +// On success, return TRUE and fill in |left|, |top|, |right|, and +// |bottom|. If |link_page| is invalid then return FALSE, and the out +// parameters remain unmodified. If |link_page| is valid but +// |link_index| is out of bounds, then return FALSE and set the out +// parameters to 0. // -DLLEXPORT void STDCALL FPDFText_GetRect(FPDF_TEXTPAGE text_page, - int rect_index, - double* left, - double* top, - double* right, - double* bottom); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetRect(FPDF_TEXTPAGE text_page, + int rect_index, + double* left, + double* top, + double* right, + double* bottom); // Function: FPDFText_GetBoundedText // Extract unicode text within a rectangular boundary on the page. @@ -232,13 +260,13 @@ DLLEXPORT void STDCALL FPDFText_GetRect(FPDF_TEXTPAGE text_page, // If the buffer is too small, as much text as will fit is copied into // it. // -DLLEXPORT int STDCALL FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, - double left, - double top, - double right, - double bottom, - unsigned short* buffer, - int buflen); +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, + double left, + double top, + double right, + double bottom, + unsigned short* buffer, + int buflen); // Flags used by FPDFText_FindStart function. #define FPDF_MATCHCASE \ @@ -258,10 +286,11 @@ DLLEXPORT int STDCALL FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, // A handle for the search context. FPDFText_FindClose must be called // to release this handle. // -DLLEXPORT FPDF_SCHHANDLE STDCALL FPDFText_FindStart(FPDF_TEXTPAGE text_page, - FPDF_WIDESTRING findwhat, - unsigned long flags, - int start_index); +FPDF_EXPORT FPDF_SCHHANDLE FPDF_CALLCONV +FPDFText_FindStart(FPDF_TEXTPAGE text_page, + FPDF_WIDESTRING findwhat, + unsigned long flags, + int start_index); // Function: FPDFText_FindNext // Search in the direction from page start to end. @@ -271,7 +300,7 @@ DLLEXPORT FPDF_SCHHANDLE STDCALL FPDFText_FindStart(FPDF_TEXTPAGE text_page, // Return Value: // Whether a match is found. // -DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindNext(FPDF_SCHHANDLE handle); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindNext(FPDF_SCHHANDLE handle); // Function: FPDFText_FindPrev // Search in the direction from page end to start. @@ -281,7 +310,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindNext(FPDF_SCHHANDLE handle); // Return Value: // Whether a match is found. // -DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindPrev(FPDF_SCHHANDLE handle); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindPrev(FPDF_SCHHANDLE handle); // Function: FPDFText_GetSchResultIndex // Get the starting character index of the search result. @@ -291,7 +320,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindPrev(FPDF_SCHHANDLE handle); // Return Value: // Index for the starting character. // -DLLEXPORT int STDCALL FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle); +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle); // Function: FPDFText_GetSchCount // Get the number of matched characters in the search result. @@ -301,7 +330,7 @@ DLLEXPORT int STDCALL FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle); // Return Value: // Number of matched characters. // -DLLEXPORT int STDCALL FPDFText_GetSchCount(FPDF_SCHHANDLE handle); +FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetSchCount(FPDF_SCHHANDLE handle); // Function: FPDFText_FindClose // Release a search context. @@ -311,7 +340,7 @@ DLLEXPORT int STDCALL FPDFText_GetSchCount(FPDF_SCHHANDLE handle); // Return Value: // None. // -DLLEXPORT void STDCALL FPDFText_FindClose(FPDF_SCHHANDLE handle); +FPDF_EXPORT void FPDF_CALLCONV FPDFText_FindClose(FPDF_SCHHANDLE handle); // Function: FPDFLink_LoadWebLinks // Prepare information about weblinks in a page. @@ -336,7 +365,8 @@ DLLEXPORT void STDCALL FPDFText_FindClose(FPDF_SCHHANDLE handle); // // FPDFLink_CloseWebLinks must be called to release resources. // -DLLEXPORT FPDF_PAGELINK STDCALL FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page); +FPDF_EXPORT FPDF_PAGELINK FPDF_CALLCONV +FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page); // Function: FPDFLink_CountWebLinks // Count number of detected web links. @@ -345,7 +375,7 @@ DLLEXPORT FPDF_PAGELINK STDCALL FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page); // Return Value: // Number of detected web links. // -DLLEXPORT int STDCALL FPDFLink_CountWebLinks(FPDF_PAGELINK link_page); +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountWebLinks(FPDF_PAGELINK link_page); // Function: FPDFLink_GetURL // Fetch the URL information for a detected web link. @@ -366,10 +396,10 @@ DLLEXPORT int STDCALL FPDFLink_CountWebLinks(FPDF_PAGELINK link_page); // If |link_index| does not correspond to a valid link, then the result // is an empty string. // -DLLEXPORT int STDCALL FPDFLink_GetURL(FPDF_PAGELINK link_page, - int link_index, - unsigned short* buffer, - int buflen); +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetURL(FPDF_PAGELINK link_page, + int link_index, + unsigned short* buffer, + int buflen); // Function: FPDFLink_CountRects // Count number of rectangular areas for the link. @@ -380,8 +410,8 @@ DLLEXPORT int STDCALL FPDFLink_GetURL(FPDF_PAGELINK link_page, // Number of rectangular areas for the link. If |link_index| does // not correspond to a valid link, then 0 is returned. // -DLLEXPORT int STDCALL FPDFLink_CountRects(FPDF_PAGELINK link_page, - int link_index); +FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountRects(FPDF_PAGELINK link_page, + int link_index); // Function: FPDFLink_GetRect // Fetch the boundaries of a rectangle for a link. @@ -398,16 +428,18 @@ DLLEXPORT int STDCALL FPDFLink_CountRects(FPDF_PAGELINK link_page, // bottom - Pointer to a double value receiving the rectangle // bottom boundary. // Return Value: -// None. If |link_index| does not correspond to a valid link, then -// |left|, |top|, |right|, and |bottom| remain unmodified. +// On success, return TRUE and fill in |left|, |top|, |right|, and +// |bottom|. If |link_page| is invalid or if |link_index| does not +// correspond to a valid link, then return FALSE, and the out +// parameters remain unmodified. // -DLLEXPORT void STDCALL FPDFLink_GetRect(FPDF_PAGELINK link_page, - int link_index, - int rect_index, - double* left, - double* top, - double* right, - double* bottom); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetRect(FPDF_PAGELINK link_page, + int link_index, + int rect_index, + double* left, + double* top, + double* right, + double* bottom); // Function: FPDFLink_CloseWebLinks // Release resources used by weblink feature. @@ -416,7 +448,7 @@ DLLEXPORT void STDCALL FPDFLink_GetRect(FPDF_PAGELINK link_page, // Return Value: // None. // -DLLEXPORT void STDCALL FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page); +FPDF_EXPORT void FPDF_CALLCONV FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page); #ifdef __cplusplus } diff --git a/public/fpdf_transformpage.h b/public/fpdf_transformpage.h index 66271fcda8a16359a0aa8493f861f6f737d8320b..a6ed04a51110fbaa1b61603cd9e2f2abb9d9ff3c 100644 --- a/public/fpdf_transformpage.h +++ b/public/fpdf_transformpage.h @@ -26,11 +26,11 @@ typedef void* FPDF_PAGEARCLOADER; * @param[in] top - The top of the rectangle. * @retval None. */ -DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page, - float left, - float bottom, - float right, - float top); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetMediaBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top); /** * Set "CropBox" entry to the page dictionary. @@ -41,11 +41,11 @@ DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page, * @param[in] top - The top of the rectangle. * @retval None. */ -DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page, - float left, - float bottom, - float right, - float top); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetCropBox(FPDF_PAGE page, + float left, + float bottom, + float right, + float top); /** Get "MediaBox" entry from the page dictionary. * @param[in] page - Handle to a page. @@ -59,11 +59,11 @@ DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page, * rectangle. * @retval True if success,else fail. */ -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page, - float* left, - float* bottom, - float* right, - float* top); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetMediaBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top); /** Get "CropBox" entry from the page dictionary. * @param[in] page - Handle to a page. @@ -77,25 +77,30 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page, * rectangle. * @retval True if success,else fail. */ -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetCropBox(FPDF_PAGE page, - float* left, - float* bottom, - float* right, - float* top); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetCropBox(FPDF_PAGE page, + float* left, + float* bottom, + float* right, + float* top); /** -* Transform the whole page with a specified matrix, then clip the page content -* region. -* -* @param[in] page - A page handle. -* @param[in] matrix - The transform matrix. -* @param[in] clipRect - A rectangle page area to be clipped. -* @Note. This function will transform the whole page, and would take effect to -* all the objects in the page. -*/ -DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, - FS_MATRIX* matrix, - FS_RECTF* clipRect); + * Apply transforms to |page|. + * + * If |matrix| is provided it will be applied to transform the page. + * If |clipRect| is provided it will be used to clip the resulting page. + * If neither |matrix| or |clipRect| are provided this method returns |false|. + * Returns |true| if transforms are applied. + * + * @param[in] page - Page handle. + * @param[in] matrix - Transform matrix. + * @param[in] clipRect - Clipping rectangle. + * @Note. This function will transform the whole page, and would take effect to + * all the objects in the page. + */ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDFPage_TransFormWithClip(FPDF_PAGE page, + FS_MATRIX* matrix, + FS_RECTF* clipRect); /** * Transform (scale, rotate, shear, move) the clip path of page object. @@ -109,7 +114,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, * @param[in] f - The coefficient "f" of the matrix. * @retval None. */ -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object, double a, double b, @@ -127,10 +132,10 @@ FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object, * @param[in] top - The top of the clip box. * @retval a handle to the clip path. */ -DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left, - float bottom, - float right, - float top); +FPDF_EXPORT FPDF_CLIPPATH FPDF_CALLCONV FPDF_CreateClipPath(float left, + float bottom, + float right, + float top); /** * Destroy the clip path. @@ -139,7 +144,7 @@ DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left, * Destroy the clip path. * @retval None. */ -DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath); +FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath); /** * Clip the page content, the page content that outside the clipping region @@ -151,8 +156,8 @@ DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath); * array. In this way, the page content will be clipped * by this clip path. */ -DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page, - FPDF_CLIPPATH clipPath); +FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertClipPath(FPDF_PAGE page, + FPDF_CLIPPATH clipPath); #ifdef __cplusplus } diff --git a/public/fpdfview.h b/public/fpdfview.h index 1c47a366bd0016b6603090026fab66b860cfc838..ffa46783476435c37b382c19ef03bdd3ff05b19b 100644 --- a/public/fpdfview.h +++ b/public/fpdfview.h @@ -20,28 +20,39 @@ #define PDF_USE_XFA #endif // PDF_ENABLE_XFA +// PDF object types +#define FPDF_OBJECT_UNKNOWN 0 +#define FPDF_OBJECT_BOOLEAN 1 +#define FPDF_OBJECT_NUMBER 2 +#define FPDF_OBJECT_STRING 3 +#define FPDF_OBJECT_NAME 4 +#define FPDF_OBJECT_ARRAY 5 +#define FPDF_OBJECT_DICTIONARY 6 +#define FPDF_OBJECT_STREAM 7 +#define FPDF_OBJECT_NULLOBJ 8 +#define FPDF_OBJECT_REFERENCE 9 + // PDF types typedef void* FPDF_ACTION; +typedef void* FPDF_ANNOTATION; +typedef void* FPDF_ATTACHMENT; typedef void* FPDF_BITMAP; typedef void* FPDF_BOOKMARK; typedef void* FPDF_CLIPPATH; typedef void* FPDF_DEST; -typedef void* FPDF_DOCSCHHANDLE; typedef void* FPDF_DOCUMENT; typedef void* FPDF_FONT; -typedef void* FPDF_HMODULE; typedef void* FPDF_LINK; -typedef void* FPDF_MODULEMGR; typedef void* FPDF_PAGE; typedef void* FPDF_PAGELINK; typedef void* FPDF_PAGEOBJECT; // Page object(text, path, etc) typedef void* FPDF_PAGERANGE; -typedef void* FPDF_PATH; typedef void* FPDF_RECORDER; typedef void* FPDF_SCHHANDLE; typedef void* FPDF_STRUCTELEMENT; typedef void* FPDF_STRUCTTREE; typedef void* FPDF_TEXTPAGE; +typedef void const* FPDF_PATHSEGMENT; #ifdef PDF_ENABLE_XFA typedef void* FPDF_STRINGHANDLE; @@ -101,7 +112,14 @@ typedef struct _FPDF_BSTR { // system wide string by yourself. typedef const char* FPDF_STRING; -// Matrix for transformation. +// Matrix for transformation, in the form [a b c d e f], equivalent to: +// | a b 0 | +// | c d 0 | +// | e f 1 | +// +// Translation is performed with [1 0 0 1 tx ty]. +// Scaling is performed with [sx 0 0 sy 0 0]. +// See PDF Reference 1.7, 4.2.2 Common Transformations for more. typedef struct _FS_MATRIX_ { float a; float b; @@ -126,13 +144,20 @@ typedef struct _FS_RECTF_ { // Const Pointer to FS_RECTF structure. typedef const FS_RECTF* FS_LPCRECTF; +// Annotation enums. +typedef int FPDF_ANNOTATION_SUBTYPE; +typedef int FPDF_ANNOT_APPEARANCEMODE; + +// Dictionary value types. +typedef int FPDF_OBJECT_TYPE; + #if defined(_WIN32) && defined(FPDFSDK_EXPORTS) // On Windows system, functions are exported in a DLL -#define DLLEXPORT __declspec(dllexport) -#define STDCALL __stdcall +#define FPDF_EXPORT __declspec(dllexport) +#define FPDF_CALLCONV __stdcall #else -#define DLLEXPORT -#define STDCALL +#define FPDF_EXPORT +#define FPDF_CALLCONV #endif // Exported Functions @@ -149,7 +174,7 @@ extern "C" { // Comments: // Convenience function to call FPDF_InitLibraryWithConfig() for // backwards comatibility purposes. -DLLEXPORT void STDCALL FPDF_InitLibrary(); +FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary(); // Process-wide options for initializing the library. typedef struct FPDF_LIBRARY_CONFIG_ { @@ -183,8 +208,8 @@ typedef struct FPDF_LIBRARY_CONFIG_ { // Comments: // You have to call this function before you can call any PDF // processing functions. -DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig( - const FPDF_LIBRARY_CONFIG* config); +FPDF_EXPORT void FPDF_CALLCONV +FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* config); // Function: FPDF_DestroyLibary // Release all resources allocated by the FPDFSDK library. @@ -197,7 +222,7 @@ DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig( // the library. // After this function is called, you should not call any PDF // processing functions. -DLLEXPORT void STDCALL FPDF_DestroyLibrary(); +FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary(); // Policy for accessing the local machine time. #define FPDF_POLICY_MACHINETIME_ACCESS 0 @@ -210,8 +235,8 @@ DLLEXPORT void STDCALL FPDF_DestroyLibrary(); // enable - True to enable, false to disable the policy. // Return value: // None. -DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy, - FPDF_BOOL enable); +FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy, + FPDF_BOOL enable); #if defined(_WIN32) #if defined(PDFIUM_PRINT_TEXT_WITH_GDI) @@ -229,7 +254,7 @@ typedef void (*PDFiumEnsureTypefaceCharactersAccessible)(const LOGFONT* font, // func - A function pointer. See description above. // Return value: // None. -DLLEXPORT void STDCALL +FPDF_EXPORT void FPDF_CALLCONV FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func); // Function: FPDF_SetPrintTextWithGDI @@ -239,21 +264,34 @@ FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func); // use_gdi - Set to true to enable printing text with GDI. // Return value: // None. -DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi); +FPDF_EXPORT void FPDF_CALLCONV FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi); #endif // PDFIUM_PRINT_TEXT_WITH_GDI // Function: FPDF_SetPrintPostscriptLevel // Set postscript printing level when printing on Windows. // Experimental API. // Parameters: -// postscript_level - 0 to disable postscript printing, -// 2 to print with postscript level 2, -// 3 to print with postscript level 3. -// All other values are invalid. +// postscript_level- 0 to disable postscript printing, +// 2 to print with postscript level 2, +// 3 to print with postscript level 3. +// All other values are invalid. // Return value: -// True if successful, false if unsucessful (typically invalid input). -DLLEXPORT FPDF_BOOL STDCALL -FPDF_SetPrintPostscriptLevel(FPDF_BOOL postscript_level); +// True if successful, false if unsuccessful (typically invalid input). +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_SetPrintPostscriptLevel(int postscript_level); + +// Function: FPDF_SetPrintMode +// Set printing mode when printing on Windows. +// Experimental API. +// Parameters: +// mode - FPDF_PRINTMODE_EMF to output EMF (default) +// FPDF_PRINTMODE_TEXTONLY to output text only (for charstream +// devices) +// FPDF_PRINTMODE_POSTSCRIPT2 to output level 2 postscript +// FPDF_PRINTMODE_POSTSCRIPT3 to output level 3 postscript +// Return value: +// True if successful, false if unsuccessful (typically invalid input). +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode); #endif // defined(_WIN32) // Function: FPDF_LoadDocument @@ -268,8 +306,8 @@ FPDF_SetPrintPostscriptLevel(FPDF_BOOL postscript_level); // Loaded document can be closed by FPDF_CloseDocument(). // If this function fails, you can use FPDF_GetLastError() to retrieve // the reason why it failed. -DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, - FPDF_BYTESTRING password); +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV +FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password); // Function: FPDF_LoadMemDocument // Open and load a PDF document from memory. @@ -289,9 +327,8 @@ DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, // If PDFium is built with the XFA module, the application should call // FPDF_LoadXFA() function after the PDF document loaded to support XFA // fields defined in the fpdfformfill.h file. -DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf, - int size, - FPDF_BYTESTRING password); +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV +FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password); // Structure for custom file access. typedef struct { @@ -416,7 +453,7 @@ typedef struct _FPDF_FILEHANDLER { // If PDFium is built with the XFA module, the application should call // FPDF_LoadXFA() function after the PDF document loaded to support XFA // fields defined in the fpdfformfill.h file. -DLLEXPORT FPDF_DOCUMENT STDCALL +FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess, FPDF_BYTESTRING password); // Function: FPDF_GetFileVersion @@ -430,8 +467,8 @@ FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess, FPDF_BYTESTRING password); // Comments: // If the document was created by FPDF_CreateNewDocument, // then this function will always fail. -DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, - int* fileVersion); +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc, + int* fileVersion); #define FPDF_ERR_SUCCESS 0 // No error. #define FPDF_ERR_UNKNOWN 1 // Unknown error. @@ -454,7 +491,7 @@ DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, // Comments: // If the previous SDK call succeeded, the return value of this // function is not defined. -DLLEXPORT unsigned long STDCALL FPDF_GetLastError(); +FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError(); // Function: FPDF_GetDocPermission // Get file permission flags of the document. @@ -464,7 +501,8 @@ DLLEXPORT unsigned long STDCALL FPDF_GetLastError(); // A 32-bit integer indicating permission flags. Please refer to the // PDF Reference for detailed descriptions. If the document is not // protected, 0xffffffff will be returned. -DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document); +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_GetDocPermissions(FPDF_DOCUMENT document); // Function: FPDF_GetSecurityHandlerRevision // Get the revision for the security handler. @@ -474,7 +512,8 @@ DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document); // The security handler revision number. Please refer to the PDF // Reference for a detailed description. If the document is not // protected, -1 will be returned. -DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document); +FPDF_EXPORT int FPDF_CALLCONV +FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document); // Function: FPDF_GetPageCount // Get total number of pages in the document. @@ -482,7 +521,7 @@ DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document); // document - Handle to document. Returned by FPDF_LoadDocument. // Return value: // Total number of pages in the document. -DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document); +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document); // Function: FPDF_LoadPage // Load a page inside the document. @@ -494,8 +533,8 @@ DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document); // Comments: // The loaded page can be rendered to devices using FPDF_RenderPage. // The loaded page can be closed using FPDF_ClosePage. -DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, - int page_index); +FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document, + int page_index); // Function: FPDF_GetPageWidth // Get page width. @@ -504,7 +543,7 @@ DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, // Return value: // Page width (excluding non-displayable area) measured in points. // One point is 1/72 inch (around 0.3528 mm). -DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page); +FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page); // Function: FPDF_GetPageHeight // Get page height. @@ -513,7 +552,20 @@ DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page); // Return value: // Page height (excluding non-displayable area) measured in points. // One point is 1/72 inch (around 0.3528 mm) -DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page); +FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page); + +// Experimental API. +// Function: FPDF_GetPageBoundingBox +// Get the bounding box of the page. This is the intersection between +// its media box and its crop box. +// Parameters: +// page - Handle to the page. Returned by FPDF_LoadPage. +// rect - Pointer to a rect to receive the page bounding box. +// On an error, |rect| won't be filled. +// Return value: +// True for success. +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page, + FS_RECTF* rect); // Function: FPDF_GetPageSizeByIndex // Get the size of the page at the given index. @@ -526,10 +578,10 @@ DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page); // (in points). // Return value: // Non-zero for success. 0 for error (document or page not found). -DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, - int page_index, - double* width, - double* height); +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, + int page_index, + double* width, + double* height); // Page rendering flags. They can be combined with bit-wise OR. // @@ -583,14 +635,14 @@ DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, // defined above. // Return value: // None. -DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags); +FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags); #endif // Function: FPDF_RenderPageBitmap @@ -598,7 +650,8 @@ DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, // Parameters: // bitmap - Handle to the device independent bitmap (as the // output buffer). The bitmap handle can be created -// by FPDFBitmap_Create. +// by FPDFBitmap_Create or retrieved from an image +// object by FPDFImageObj_GetBitmap. // page - Handle to the page. Returned by FPDF_LoadPage // start_x - Left pixel position of the display area in // bitmap coordinates. @@ -618,41 +671,44 @@ DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, // widget and popup annotations. // Return value: // None. -DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, - FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int flags); +FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags); // Function: FPDF_RenderPageBitmapWithMatrix // Render contents of a page to a device independent bitmap. // Parameters: // bitmap - Handle to the device independent bitmap (as the // output buffer). The bitmap handle can be created -// by FPDFBitmap_Create. -// page - Handle to the page. Returned by FPDF_LoadPage -// matrix - The transform matrix. -// clipping - The rect to clip to. +// by FPDFBitmap_Create or retrieved by +// FPDFImageObj_GetBitmap. +// page - Handle to the page. Returned by FPDF_LoadPage. +// matrix - The transform matrix, which must be invertible. +// See PDF Reference 1.7, 4.2.2 Common Transformations. +// clipping - The rect to clip to in device coords. // flags - 0 for normal display, or combination of the Page // Rendering flags defined above. With the FPDF_ANNOT // flag, it renders all annotations that do not require // user-interaction, which are all annotations except // widget and popup annotations. // Return value: -// None. -DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap, - FPDF_PAGE page, - const FS_MATRIX* matrix, - const FS_RECTF* clipping, - int flags); +// None. Note that behavior is undefined if det of |matrix| is 0. +FPDF_EXPORT void FPDF_CALLCONV +FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap, + FPDF_PAGE page, + const FS_MATRIX* matrix, + const FS_RECTF* clipping, + int flags); #ifdef _SKIA_SUPPORT_ -DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page, - int size_x, - int size_y); +FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page, + int size_x, + int size_y); #endif // Function: FPDF_ClosePage @@ -661,7 +717,7 @@ DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page, // page - Handle to the loaded page. // Return value: // None. -DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page); +FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page); // Function: FPDF_CloseDocument // Close a loaded PDF document. @@ -669,7 +725,7 @@ DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page); // document - Handle to the loaded document. // Return value: // None. -DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document); +FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document); // Function: FPDF_DeviceToPage // Convert the screen coordinates of a point to page coordinates. @@ -711,16 +767,16 @@ DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document); // You must make sure the start_x, start_y, size_x, size_y // and rotate parameters have exactly same values as you used in // the FPDF_RenderPage() function call. -DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - int device_x, - int device_y, - double* page_x, - double* page_y); +FPDF_EXPORT void FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int device_x, + int device_y, + double* page_x, + double* page_y); // Function: FPDF_PageToDevice // Convert the page coordinates of a point to screen coordinates. @@ -747,16 +803,16 @@ DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, // None. // Comments: // See comments for FPDF_DeviceToPage(). -DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, - int start_x, - int start_y, - int size_x, - int size_y, - int rotate, - double page_x, - double page_y, - int* device_x, - int* device_y); +FPDF_EXPORT void FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + double page_x, + double page_y, + int* device_x, + int* device_y); // Function: FPDFBitmap_Create // Create a device independent bitmap (FXDIB). @@ -787,11 +843,13 @@ DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, // This function allocates enough memory for holding all pixels in the // bitmap, but it doesn't initialize the buffer. Applications can use // FPDFBitmap_FillRect to fill the bitmap using any color. -DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, - int height, - int alpha); +FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width, + int height, + int alpha); // More DIB formats +// Unknown or unsupported format. +#define FPDFBitmap_Unknown 0 // Gray scale bitmap, one byte per pixel. #define FPDFBitmap_Gray 1 // 3 bytes per pixel, byte order: blue, green, red. @@ -826,11 +884,23 @@ DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, // If an external buffer is used, then the application should destroy // the buffer by itself. FPDFBitmap_Destroy function will not destroy // the buffer. -DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, - int height, - int format, - void* first_scan, - int stride); +FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width, + int height, + int format, + void* first_scan, + int stride); + +// Function: FPDFBitmap_GetFormat +// Get the format of the bitmap. +// Parameters: +// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create +// or FPDFImageObj_GetBitmap. +// Return value: +// The format of the bitmap. +// Comments: +// Only formats supported by FPDFBitmap_CreateEx are supported by this +// function; see the list of such formats above. +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap); // Function: FPDFBitmap_FillRect // Fill a rectangle in a bitmap. @@ -856,17 +926,18 @@ DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, // background will be replaced by the source color and the alpha. // // If the alpha channel is not used, the alpha parameter is ignored. -DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, - int left, - int top, - int width, - int height, - FPDF_DWORD color); +FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap, + int left, + int top, + int width, + int height, + FPDF_DWORD color); // Function: FPDFBitmap_GetBuffer // Get data buffer of a bitmap. // Parameters: -// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create. +// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create +// or FPDFImageObj_GetBitmap. // Return value: // The pointer to the first byte of the bitmap buffer. // Comments: @@ -878,44 +949,48 @@ DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, // // The data is in BGRA format. Where the A maybe unused if alpha was // not specified. -DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap); +FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap); // Function: FPDFBitmap_GetWidth // Get width of a bitmap. // Parameters: -// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create. +// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create +// or FPDFImageObj_GetBitmap. // Return value: // The width of the bitmap in pixels. -DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap); +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap); // Function: FPDFBitmap_GetHeight // Get height of a bitmap. // Parameters: -// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create. +// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create +// or FPDFImageObj_GetBitmap. // Return value: // The height of the bitmap in pixels. -DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap); +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap); // Function: FPDFBitmap_GetStride // Get number of bytes for each line in the bitmap buffer. // Parameters: -// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create. +// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create +// or FPDFImageObj_GetBitmap. // Return value: // The number of bytes for each line in the bitmap buffer. // Comments: // The stride may be more than width * number of bytes per pixel. -DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap); +FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap); // Function: FPDFBitmap_Destroy // Destroy a bitmap and release all related buffers. // Parameters: -// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create. +// bitmap - Handle to the bitmap. Returned by FPDFBitmap_Create +// or FPDFImageObj_GetBitmap. // Return value: // None. // Comments: // This function will not destroy any external buffers provided when // the bitmap was created. -DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap); +FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap); // Function: FPDF_VIEWERREF_GetPrintScaling // Whether the PDF document prefers to be scaled or not. @@ -923,7 +998,7 @@ DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap); // document - Handle to the loaded document. // Return value: // None. -DLLEXPORT FPDF_BOOL STDCALL +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document); // Function: FPDF_VIEWERREF_GetNumCopies @@ -932,7 +1007,8 @@ FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document); // document - Handle to the loaded document. // Return value: // The number of copies to be printed. -DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document); +FPDF_EXPORT int FPDF_CALLCONV +FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document); // Function: FPDF_VIEWERREF_GetPrintPageRange // Page numbers to initialize print dialog box when file is printed. @@ -940,7 +1016,7 @@ DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document); // document - Handle to the loaded document. // Return value: // The print page range to be used for printing. -DLLEXPORT FPDF_PAGERANGE STDCALL +FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document); // Function: FPDF_VIEWERREF_GetDuplex @@ -950,7 +1026,7 @@ FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document); // document - Handle to the loaded document. // Return value: // The paper handling option to be used when printing. -DLLEXPORT FPDF_DUPLEXTYPE STDCALL +FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document); // Function: FPDF_VIEWERREF_GetName @@ -958,7 +1034,8 @@ FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document); // be of type "name". // Parameters: // document - Handle to the loaded document. -// key - Name of the key in the viewer pref dictionary. +// key - Name of the key in the viewer pref dictionary, +// encoded in UTF-8. // buffer - A string to write the contents of the key to. // length - Length of the buffer. // Return value: @@ -967,10 +1044,11 @@ FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document); // as when |document| is invalid or |buffer| is NULL. If |length| is // less than the returned length, or |buffer| is NULL, |buffer| will // not be modified. -DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, - FPDF_BYTESTRING key, - char* buffer, - unsigned long length); +FPDF_EXPORT unsigned long FPDF_CALLCONV +FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, + FPDF_BYTESTRING key, + char* buffer, + unsigned long length); // Function: FPDF_CountNamedDests // Get the count of named destinations in the PDF document. @@ -978,7 +1056,8 @@ DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document, // document - Handle to a document // Return value: // The count of named destinations. -DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document); +FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV +FPDF_CountNamedDests(FPDF_DOCUMENT document); // Function: FPDF_GetNamedDestByName // Get a the destination handle for the given name. @@ -987,8 +1066,8 @@ DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document); // name - The name of a destination. // Return value: // The handle to the destination. -DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document, - FPDF_BYTESTRING name); +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV +FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name); // Function: FPDF_GetNamedDest // Get the named destination by index. @@ -1011,25 +1090,25 @@ DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document, // // If buflen is not sufficiently large, it will be set to -1 upon // return. -DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document, - int index, - void* buffer, - long* buflen); +FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document, + int index, + void* buffer, + long* buflen); #ifdef PDF_ENABLE_XFA // Function: FPDF_BStr_Init // Helper function to initialize a byte string. -DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str); +FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* str); // Function: FPDF_BStr_Set // Helper function to set string data. -DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str, - FPDF_LPCSTR bstr, - int length); +FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* str, + FPDF_LPCSTR bstr, + int length); // Function: FPDF_BStr_Clear // Helper function to clear a byte string. -DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str); +FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* str); #endif // PDF_ENABLE_XFA #ifdef __cplusplus diff --git a/samples/BUILD.gn b/samples/BUILD.gn index 23f4d0ca56aff1154cb0720ade310c7cd0dca747..66b02f652836e54765e0f946ea0cbf35899175ec 100644 --- a/samples/BUILD.gn +++ b/samples/BUILD.gn @@ -8,7 +8,6 @@ import("../pdfium.gni") group("samples") { testonly = true deps = [ - ":pdfium_diff", ":pdfium_test", ] } @@ -33,6 +32,11 @@ config("pdfium_samples_config") { if (is_asan) { defines += [ "PDF_ENABLE_ASAN" ] } + + if (enable_callgrind) { + defines += [ "ENABLE_CALLGRIND" ] + } + if (use_coverage && is_clang) { cflags += [ "--coverage", @@ -46,24 +50,17 @@ config("pdfium_samples_config") { executable("pdfium_test") { testonly = true sources = [ - "image_diff_png.cc", - "image_diff_png.h", "pdfium_test.cc", ] deps = [ + "../:image_diff", "../:pdfium", "../:test_support", - "//build/config/sanitizers:deps", + "//build/config:exe_and_shlib_deps", "//build/win:default_exe_manifest", - - # Regardless of whether the library ships against system freetype, - # always link this binary against the bundled one for consistency - # of results across platforms. - "../third_party:fx_freetype", ] - if (!pdf_enable_xfa) { - deps += [ "../third_party:fx_lpng" ] - } + configs += [ ":pdfium_samples_config" ] + if (pdf_enable_v8) { deps += [ "//v8:v8_libplatform" ] include_dirs = [ @@ -75,27 +72,4 @@ executable("pdfium_test") { if (pdf_use_skia || pdf_use_skia_paths) { deps += [ "//skia" ] } - configs += [ ":pdfium_samples_config" ] -} - -executable("pdfium_diff") { - testonly = true - sources = [ - "image_diff.cc", - "image_diff_png.cc", - "image_diff_png.h", - ] - deps = [ - "../:pdfium", - "//build/config/sanitizers:deps", - "//build/win:default_exe_manifest", - ] - if (!pdf_enable_xfa) { - deps += [ "../third_party:fx_lpng" ] - } - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ - ":pdfium_samples_config", - "//build/config/compiler:no_chromium_code", - ] } diff --git a/samples/DEPS b/samples/DEPS index 4a926a7cf228ae314527dc1d3acc407003a641dd..26f9ee22ebd1d8ded2ce8bae4c7ea435aae94c39 100644 --- a/samples/DEPS +++ b/samples/DEPS @@ -1,8 +1,5 @@ include_rules = [ '+public', - '+third_party/libpng16', '+third_party/skia/include', - '+third_party/zlib_v128', '+v8', - '+core/fdrm/crypto/fx_crypt.h', ] diff --git a/samples/image_diff.cc b/samples/image_diff.cc deleted file mode 100644 index 3aa626be65bfc771fde52b0c972a76a671513cf6..0000000000000000000000000000000000000000 --- a/samples/image_diff.cc +++ /dev/null @@ -1,352 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file input format is based loosely on -// Tools/DumpRenderTree/ImageDiff.m - -// The exact format of this tool's output to stdout is important, to match -// what the run-webkit-tests script expects. - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "samples/image_diff_png.h" -#include "third_party/base/logging.h" -#include "third_party/base/numerics/safe_conversions.h" - -#if defined(OS_WIN) -#include -#endif - -// Return codes used by this utility. -static const int kStatusSame = 0; -static const int kStatusDifferent = 1; -static const int kStatusError = 2; - -// Color codes. -static const uint32_t RGBA_RED = 0x000000ff; -static const uint32_t RGBA_ALPHA = 0xff000000; - -class Image { - public: - Image() : w_(0), h_(0) { - } - - Image(const Image& image) - : w_(image.w_), - h_(image.h_), - data_(image.data_) { - } - - bool has_image() const { - return w_ > 0 && h_ > 0; - } - - int w() const { - return w_; - } - - int h() const { - return h_; - } - - const unsigned char* data() const { - return &data_.front(); - } - - // Creates the image from the given filename on disk, and returns true on - // success. - bool CreateFromFilename(const std::string& path) { - FILE* f = fopen(path.c_str(), "rb"); - if (!f) - return false; - - std::vector compressed; - const size_t kBufSize = 1024; - unsigned char buf[kBufSize]; - size_t num_read = 0; - while ((num_read = fread(buf, 1, kBufSize, f)) > 0) { - compressed.insert(compressed.end(), buf, buf + num_read); - } - - fclose(f); - - if (!image_diff_png::DecodePNG(compressed.data(), compressed.size(), &data_, - &w_, &h_)) { - Clear(); - return false; - } - return true; - } - - void Clear() { - w_ = h_ = 0; - data_.clear(); - } - - // Returns the RGBA value of the pixel at the given location - uint32_t pixel_at(int x, int y) const { - if (!pixel_in_bounds(x, y)) - return 0; - return *reinterpret_cast(&(data_[pixel_address(x, y)])); - } - - void set_pixel_at(int x, int y, uint32_t color) { - if (!pixel_in_bounds(x, y)) - return; - - void* addr = &data_[pixel_address(x, y)]; - *reinterpret_cast(addr) = color; - } - - private: - bool pixel_in_bounds(int x, int y) const { - return x >= 0 && x < w_ && y >= 0 && y < h_; - } - - size_t pixel_address(int x, int y) const { return (y * w_ + x) * 4; } - - // Pixel dimensions of the image. - int w_; - int h_; - - std::vector data_; -}; - -float CalculateDifferencePercentage(const Image& actual, int pixels_different) { - // Like the WebKit ImageDiff tool, we define percentage different in terms - // of the size of the 'actual' bitmap. - float total_pixels = - static_cast(actual.w()) * static_cast(actual.h()); - if (total_pixels == 0) { - // When the bitmap is empty, they are 100% different. - return 100.0f; - } - return 100.0f * pixels_different / total_pixels; -} - -void CountImageSizeMismatchAsPixelDifference(const Image& baseline, - const Image& actual, - int* pixels_different) { - int w = std::min(baseline.w(), actual.w()); - int h = std::min(baseline.h(), actual.h()); - - // Count pixels that are a difference in size as also being different. - int max_w = std::max(baseline.w(), actual.w()); - int max_h = std::max(baseline.h(), actual.h()); - // These pixels are off the right side, not including the lower right corner. - *pixels_different += (max_w - w) * h; - // These pixels are along the bottom, including the lower right corner. - *pixels_different += (max_h - h) * max_w; -} - -float PercentageDifferent(const Image& baseline, const Image& actual) { - int w = std::min(baseline.w(), actual.w()); - int h = std::min(baseline.h(), actual.h()); - - // Compute pixels different in the overlap. - int pixels_different = 0; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - if (baseline.pixel_at(x, y) != actual.pixel_at(x, y)) - ++pixels_different; - } - } - - CountImageSizeMismatchAsPixelDifference(baseline, actual, &pixels_different); - return CalculateDifferencePercentage(actual, pixels_different); -} - -// FIXME: Replace with unordered_map when available. -typedef std::map RgbaToCountMap; - -float HistogramPercentageDifferent(const Image& baseline, const Image& actual) { - // TODO(johnme): Consider using a joint histogram instead, as described in - // "Comparing Images Using Joint Histograms" by Pass & Zabih - // http://www.cs.cornell.edu/~rdz/papers/pz-jms99.pdf - - int w = std::min(baseline.w(), actual.w()); - int h = std::min(baseline.h(), actual.h()); - - // Count occurences of each RGBA pixel value of baseline in the overlap. - RgbaToCountMap baseline_histogram; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - // hash_map operator[] inserts a 0 (default constructor) if key not found. - ++baseline_histogram[baseline.pixel_at(x, y)]; - } - } - - // Compute pixels different in the histogram of the overlap. - int pixels_different = 0; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - uint32_t actual_rgba = actual.pixel_at(x, y); - RgbaToCountMap::iterator it = baseline_histogram.find(actual_rgba); - if (it != baseline_histogram.end() && it->second > 0) - --it->second; - else - ++pixels_different; - } - } - - CountImageSizeMismatchAsPixelDifference(baseline, actual, &pixels_different); - return CalculateDifferencePercentage(actual, pixels_different); -} - -void PrintHelp() { - fprintf(stderr, - "Usage:\n" - " image_diff [--histogram] \n" - " Compares two files on disk, returning 0 when they are the same;\n" - " passing \"--histogram\" additionally calculates a diff of the\n" - " RGBA value histograms (which is resistant to shifts in layout)\n" - " image_diff --diff \n" - " Compares two files on disk, outputs an image that visualizes the\n" - " difference to \n"); -} - -int CompareImages(const std::string& file1, - const std::string& file2, - bool compare_histograms) { - Image actual_image; - Image baseline_image; - - if (!actual_image.CreateFromFilename(file1)) { - fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file1.c_str()); - return kStatusError; - } - if (!baseline_image.CreateFromFilename(file2)) { - fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file2.c_str()); - return kStatusError; - } - - if (compare_histograms) { - float percent = HistogramPercentageDifferent(actual_image, baseline_image); - const char* passed = percent > 0.0 ? "failed" : "passed"; - printf("histogram diff: %01.2f%% %s\n", percent, passed); - } - - const char* const diff_name = compare_histograms ? "exact diff" : "diff"; - float percent = PercentageDifferent(actual_image, baseline_image); - const char* const passed = percent > 0.0 ? "failed" : "passed"; - printf("%s: %01.2f%% %s\n", diff_name, percent, passed); - - if (percent > 0.0) { - // failure: The WebKit version also writes the difference image to - // stdout, which seems excessive for our needs. - return kStatusDifferent; - } - // success - return kStatusSame; -} - -bool CreateImageDiff(const Image& image1, const Image& image2, Image* out) { - int w = std::min(image1.w(), image2.w()); - int h = std::min(image1.h(), image2.h()); - *out = Image(image1); - bool same = (image1.w() == image2.w()) && (image1.h() == image2.h()); - - // TODO(estade): do something with the extra pixels if the image sizes - // are different. - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - uint32_t base_pixel = image1.pixel_at(x, y); - if (base_pixel != image2.pixel_at(x, y)) { - // Set differing pixels red. - out->set_pixel_at(x, y, RGBA_RED | RGBA_ALPHA); - same = false; - } else { - // Set same pixels as faded. - uint32_t alpha = base_pixel & RGBA_ALPHA; - uint32_t new_pixel = base_pixel - ((alpha / 2) & RGBA_ALPHA); - out->set_pixel_at(x, y, new_pixel); - } - } - } - - return same; -} - -int DiffImages(const std::string& file1, - const std::string& file2, - const std::string& out_file) { - Image actual_image; - Image baseline_image; - - if (!actual_image.CreateFromFilename(file1)) { - fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file1.c_str()); - return kStatusError; - } - if (!baseline_image.CreateFromFilename(file2)) { - fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file2.c_str()); - return kStatusError; - } - - Image diff_image; - bool same = CreateImageDiff(baseline_image, actual_image, &diff_image); - if (same) - return kStatusSame; - - std::vector png_encoding; - image_diff_png::EncodeRGBAPNG( - diff_image.data(), diff_image.w(), diff_image.h(), - diff_image.w() * 4, &png_encoding); - - FILE* f = fopen(out_file.c_str(), "wb"); - if (!f) - return kStatusError; - - size_t size = png_encoding.size(); - char* ptr = reinterpret_cast(&png_encoding.front()); - if (fwrite(ptr, 1, size, f) != size) - return kStatusError; - - return kStatusDifferent; -} - -int main(int argc, const char* argv[]) { - bool histograms = false; - bool produce_diff_image = false; - std::string filename1; - std::string filename2; - std::string diff_filename; - - int i; - for (i = 1; i < argc; ++i) { - const char* arg = argv[i]; - if (strstr(arg, "--") != arg) - break; - if (strcmp(arg, "--histogram") == 0) { - histograms = true; - } else if (strcmp(arg, "--diff") == 0) { - produce_diff_image = true; - } - } - if (i < argc) - filename1 = argv[i++]; - if (i < argc) - filename2 = argv[i++]; - if (i < argc) - diff_filename = argv[i++]; - - if (produce_diff_image) { - if (!diff_filename.empty()) { - return DiffImages(filename1, filename2, diff_filename); - } - } else if (!filename2.empty()) { - return CompareImages(filename1, filename2, histograms); - } - - PrintHelp(); - return kStatusError; -} diff --git a/samples/image_diff_png.cc b/samples/image_diff_png.cc deleted file mode 100644 index 18753e25804a516bd454ab71f3d9aafdaf5b0607..0000000000000000000000000000000000000000 --- a/samples/image_diff_png.cc +++ /dev/null @@ -1,644 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a duplicate of chromium's src/tools/imagediff/image_diff_png.cc -// that has been modified to build in a pdfium environment, which itself -// was duplicated as follows: - -// This is a duplicate of ui/gfx/codec/png_codec.cc, after removing code related -// to Skia, that we can use when running layout tests with minimal dependencies. - -#include "samples/image_diff_png.h" - -#include -#include - -#include - -#include "third_party/base/logging.h" -#include "third_party/libpng16/png.h" -#include "third_party/zlib_v128/zlib.h" - -namespace image_diff_png { - -namespace { - -enum ColorFormat { - // 3 bytes per pixel (packed), in RGB order regardless of endianness. - // This is the native JPEG format. - FORMAT_RGB, - - // 4 bytes per pixel, in RGBA order in memory regardless of endianness. - FORMAT_RGBA, - - // 4 bytes per pixel, in BGRA order in memory regardless of endianness. - // This is the default Windows DIB order. - FORMAT_BGRA, -}; - -// Represents a comment in the tEXt ancillary chunk of the png. -struct Comment { - std::string key; - std::string text; -}; - -// Converts BGRA->RGBA and RGBA->BGRA. -void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width, - unsigned char* output, bool* is_opaque) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &input[x * 4]; - unsigned char* pixel_out = &output[x * 4]; - pixel_out[0] = pixel_in[2]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[0]; - pixel_out[3] = pixel_in[3]; - } -} - -void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width, - unsigned char* rgb, bool* is_opaque) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &rgba[x * 4]; - unsigned char* pixel_out = &rgb[x * 3]; - pixel_out[0] = pixel_in[0]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[2]; - } -} - -} // namespace - -// Decoder -// -// This code is based on WebKit libpng interface (PNGImageDecoder), which is -// in turn based on the Mozilla png decoder. - -namespace { - -// Gamma constants: We assume we're on Windows which uses a gamma of 2.2. -const double kMaxGamma = 21474.83; // Maximum gamma accepted by png library. -const double kDefaultGamma = 2.2; -const double kInverseGamma = 1.0 / kDefaultGamma; - -class PngDecoderState { - public: - // Output is a vector. - PngDecoderState(ColorFormat ofmt, std::vector* o) - : output_format(ofmt), - output_channels(0), - is_opaque(true), - output(o), - row_converter(NULL), - width(0), - height(0), - done(false) { - } - - ColorFormat output_format; - int output_channels; - - // Used during the reading of an SkBitmap. Defaults to true until we see a - // pixel with anything other than an alpha of 255. - bool is_opaque; - - // An intermediary buffer for decode output. - std::vector* output; - - // Called to convert a row from the library to the correct output format. - // When NULL, no conversion is necessary. - void (*row_converter)(const unsigned char* in, int w, unsigned char* out, - bool* is_opaque); - - // Size of the image, set in the info callback. - int width; - int height; - - // Set to true when we've found the end of the data. - bool done; -}; - -void ConvertRGBtoRGBA(const unsigned char* rgb, int pixel_width, - unsigned char* rgba, bool* is_opaque) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &rgb[x * 3]; - unsigned char* pixel_out = &rgba[x * 4]; - pixel_out[0] = pixel_in[0]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[2]; - pixel_out[3] = 0xff; - } -} - -void ConvertRGBtoBGRA(const unsigned char* rgb, int pixel_width, - unsigned char* bgra, bool* is_opaque) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &rgb[x * 3]; - unsigned char* pixel_out = &bgra[x * 4]; - pixel_out[0] = pixel_in[2]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[0]; - pixel_out[3] = 0xff; - } -} - -// Called when the png header has been read. This code is based on the WebKit -// PNGImageDecoder -void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) { - PngDecoderState* state = static_cast( - png_get_progressive_ptr(png_ptr)); - - int bit_depth, color_type, interlace_type, compression_type; - int filter_type, channels; - png_uint_32 w, h; - png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, - &interlace_type, &compression_type, &filter_type); - - // Bounds check. When the image is unreasonably big, we'll error out and - // end up back at the setjmp call when we set up decoding. "Unreasonably big" - // means "big enough that w * h * 32bpp might overflow an int"; we choose this - // threshold to match WebKit and because a number of places in code assume - // that an image's size (in bytes) fits in a (signed) int. - unsigned long long total_size = - static_cast(w) * static_cast(h); - if (total_size > ((1 << 29) - 1)) - longjmp(png_jmpbuf(png_ptr), 1); - state->width = static_cast(w); - state->height = static_cast(h); - - // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. - if (color_type == PNG_COLOR_TYPE_PALETTE || - (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)) - png_set_expand(png_ptr); - - // Transparency for paletted images. - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand(png_ptr); - - // Convert 16-bit to 8-bit. - if (bit_depth == 16) - png_set_strip_16(png_ptr); - - // Expand grayscale to RGB. - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - - // Deal with gamma and keep it under our control. - double gamma; - if (png_get_gAMA(png_ptr, info_ptr, &gamma)) { - if (gamma <= 0.0 || gamma > kMaxGamma) { - gamma = kInverseGamma; - png_set_gAMA(png_ptr, info_ptr, gamma); - } - png_set_gamma(png_ptr, kDefaultGamma, gamma); - } else { - png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma); - } - - // Tell libpng to send us rows for interlaced pngs. - if (interlace_type == PNG_INTERLACE_ADAM7) - png_set_interlace_handling(png_ptr); - - // Update our info now - png_read_update_info(png_ptr, info_ptr); - channels = png_get_channels(png_ptr, info_ptr); - - // Pick our row format converter necessary for this data. - if (channels == 3) { - switch (state->output_format) { - case FORMAT_RGB: - state->row_converter = NULL; // no conversion necessary - state->output_channels = 3; - break; - case FORMAT_RGBA: - state->row_converter = &ConvertRGBtoRGBA; - state->output_channels = 4; - break; - case FORMAT_BGRA: - state->row_converter = &ConvertRGBtoBGRA; - state->output_channels = 4; - break; - default: - NOTREACHED(); - break; - } - } else if (channels == 4) { - switch (state->output_format) { - case FORMAT_RGB: - state->row_converter = &ConvertRGBAtoRGB; - state->output_channels = 3; - break; - case FORMAT_RGBA: - state->row_converter = NULL; // no conversion necessary - state->output_channels = 4; - break; - case FORMAT_BGRA: - state->row_converter = &ConvertBetweenBGRAandRGBA; - state->output_channels = 4; - break; - default: - NOTREACHED(); - break; - } - } else { - NOTREACHED(); - longjmp(png_jmpbuf(png_ptr), 1); - } - - state->output->resize( - state->width * state->output_channels * state->height); -} - -void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row, - png_uint_32 row_num, int pass) { - PngDecoderState* state = static_cast( - png_get_progressive_ptr(png_ptr)); - - if (static_cast(row_num) > state->height) { - NOTREACHED(); - return; - } - - unsigned char* base = NULL; - base = &state->output->front(); - - unsigned char* dest = &base[state->width * state->output_channels * row_num]; - if (state->row_converter) - state->row_converter(new_row, state->width, dest, &state->is_opaque); - else - memcpy(dest, new_row, state->width * state->output_channels); -} - -void DecodeEndCallback(png_struct* png_ptr, png_info* info) { - PngDecoderState* state = static_cast( - png_get_progressive_ptr(png_ptr)); - - // Mark the image as complete, this will tell the Decode function that we - // have successfully found the end of the data. - state->done = true; -} - -// Automatically destroys the given read structs on destruction to make -// cleanup and error handling code cleaner. -class PngReadStructDestroyer { - public: - PngReadStructDestroyer(png_struct** ps, png_info** pi) : ps_(ps), pi_(pi) { - } - ~PngReadStructDestroyer() { - png_destroy_read_struct(ps_, pi_, NULL); - } - private: - png_struct** ps_; - png_info** pi_; -}; - -bool BuildPNGStruct(const unsigned char* input, size_t input_size, - png_struct** png_ptr, png_info** info_ptr) { - if (input_size < 8) - return false; // Input data too small to be a png - - // Have libpng check the signature, it likes the first 8 bytes. - if (png_sig_cmp(const_cast(input), 0, 8) != 0) - return false; - - *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!*png_ptr) - return false; - - *info_ptr = png_create_info_struct(*png_ptr); - if (!*info_ptr) { - png_destroy_read_struct(png_ptr, NULL, NULL); - return false; - } - - return true; -} - -} // namespace - -// static -bool Decode(const unsigned char* input, size_t input_size, - ColorFormat format, std::vector* output, - int* w, int* h) { - png_struct* png_ptr = NULL; - png_info* info_ptr = NULL; - if (!BuildPNGStruct(input, input_size, &png_ptr, &info_ptr)) - return false; - - PngReadStructDestroyer destroyer(&png_ptr, &info_ptr); - if (setjmp(png_jmpbuf(png_ptr))) { - // The destroyer will ensure that the structures are cleaned up in this - // case, even though we may get here as a jump from random parts of the - // PNG library called below. - return false; - } - - PngDecoderState state(format, output); - - png_set_progressive_read_fn(png_ptr, &state, &DecodeInfoCallback, - &DecodeRowCallback, &DecodeEndCallback); - png_process_data(png_ptr, - info_ptr, - const_cast(input), - input_size); - - if (!state.done) { - // Fed it all the data but the library didn't think we got all the data, so - // this file must be truncated. - output->clear(); - return false; - } - - *w = state.width; - *h = state.height; - return true; -} - -// Encoder -// -// This section of the code is based on nsPNGEncoder.cpp in Mozilla -// (Copyright 2005 Google Inc.) - -namespace { - -// Passed around as the io_ptr in the png structs so our callbacks know where -// to write data. -struct PngEncoderState { - explicit PngEncoderState(std::vector* o) : out(o) {} - std::vector* out; -}; - -// Called by libpng to flush its internal buffer to ours. -void EncoderWriteCallback(png_structp png, png_bytep data, png_size_t size) { - PngEncoderState* state = static_cast(png_get_io_ptr(png)); - size_t old_size = state->out->size(); - state->out->resize(old_size + size); - memcpy(&(*state->out)[old_size], data, size); -} - -void FakeFlushCallback(png_structp png) { - // We don't need to perform any flushing since we aren't doing real IO, but - // we're required to provide this function by libpng. -} - -void ConvertBGRAtoRGB(const unsigned char* bgra, int pixel_width, - unsigned char* rgb, bool* is_opaque) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &bgra[x * 4]; - unsigned char* pixel_out = &rgb[x * 3]; - pixel_out[0] = pixel_in[2]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[0]; - } -} - -#ifdef PNG_TEXT_SUPPORTED - -inline char* strdup(const char* str) { -#if defined(OS_WIN) - return _strdup(str); -#else - return ::strdup(str); -#endif -} - -class CommentWriter { - public: - explicit CommentWriter(const std::vector& comments) - : comments_(comments), - png_text_(new png_text[comments.size()]) { - for (size_t i = 0; i < comments.size(); ++i) - AddComment(i, comments[i]); - } - - ~CommentWriter() { - for (size_t i = 0; i < comments_.size(); ++i) { - free(png_text_[i].key); - free(png_text_[i].text); - } - delete [] png_text_; - } - - bool HasComments() { - return !comments_.empty(); - } - - png_text* get_png_text() { - return png_text_; - } - - int size() { - return static_cast(comments_.size()); - } - - private: - void AddComment(size_t pos, const Comment& comment) { - png_text_[pos].compression = PNG_TEXT_COMPRESSION_NONE; - // A PNG comment's key can only be 79 characters long. - if (comment.key.length() > 79) - return; - png_text_[pos].key = strdup(comment.key.substr(0, 78).c_str()); - png_text_[pos].text = strdup(comment.text.c_str()); - png_text_[pos].text_length = comment.text.length(); -#ifdef PNG_iTXt_SUPPORTED - png_text_[pos].itxt_length = 0; - png_text_[pos].lang = 0; - png_text_[pos].lang_key = 0; -#endif - } - - const std::vector comments_; - png_text* png_text_; -}; -#endif // PNG_TEXT_SUPPORTED - -// The type of functions usable for converting between pixel formats. -typedef void (*FormatConverter)(const unsigned char* in, int w, - unsigned char* out, bool* is_opaque); - -// libpng uses a wacky setjmp-based API, which makes the compiler nervous. -// We constrain all of the calls we make to libpng where the setjmp() is in -// place to this function. -// Returns true on success. -bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr, - PngEncoderState* state, - int width, int height, int row_byte_width, - const unsigned char* input, int compression_level, - int png_output_color_type, int output_color_components, - FormatConverter converter, - const std::vector& comments) { -#ifdef PNG_TEXT_SUPPORTED - CommentWriter comment_writer(comments); -#endif - unsigned char* row_buffer = NULL; - - // Make sure to not declare any locals here -- locals in the presence - // of setjmp() in C++ code makes gcc complain. - - if (setjmp(png_jmpbuf(png_ptr))) { - delete[] row_buffer; - return false; - } - - png_set_compression_level(png_ptr, compression_level); - - // Set our callback for libpng to give us the data. - png_set_write_fn(png_ptr, state, EncoderWriteCallback, FakeFlushCallback); - - png_set_IHDR(png_ptr, info_ptr, width, height, 8, png_output_color_type, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - -#ifdef PNG_TEXT_SUPPORTED - if (comment_writer.HasComments()) { - png_set_text(png_ptr, info_ptr, comment_writer.get_png_text(), - comment_writer.size()); - } -#endif - - png_write_info(png_ptr, info_ptr); - - if (!converter) { - // No conversion needed, give the data directly to libpng. - for (int y = 0; y < height; y ++) { - png_write_row(png_ptr, - const_cast(&input[y * row_byte_width])); - } - } else { - // Needs conversion using a separate buffer. - row_buffer = new unsigned char[width * output_color_components]; - for (int y = 0; y < height; y ++) { - converter(&input[y * row_byte_width], width, row_buffer, NULL); - png_write_row(png_ptr, row_buffer); - } - delete[] row_buffer; - } - - png_write_end(png_ptr, info_ptr); - return true; -} - -} // namespace - -// static -bool EncodeWithCompressionLevel(const unsigned char* input, ColorFormat format, - const int width, const int height, - int row_byte_width, - bool discard_transparency, - const std::vector& comments, - int compression_level, - std::vector* output) { - // Run to convert an input row into the output row format, NULL means no - // conversion is necessary. - FormatConverter converter = NULL; - - int input_color_components, output_color_components; - int png_output_color_type; - switch (format) { - case FORMAT_RGB: - input_color_components = 3; - output_color_components = 3; - png_output_color_type = PNG_COLOR_TYPE_RGB; - discard_transparency = false; - break; - - case FORMAT_RGBA: - input_color_components = 4; - if (discard_transparency) { - output_color_components = 3; - png_output_color_type = PNG_COLOR_TYPE_RGB; - converter = ConvertRGBAtoRGB; - } else { - output_color_components = 4; - png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; - converter = NULL; - } - break; - - case FORMAT_BGRA: - input_color_components = 4; - if (discard_transparency) { - output_color_components = 3; - png_output_color_type = PNG_COLOR_TYPE_RGB; - converter = ConvertBGRAtoRGB; - } else { - output_color_components = 4; - png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; - converter = ConvertBetweenBGRAandRGBA; - } - break; - - default: - NOTREACHED(); - return false; - } - - // Row stride should be at least as long as the length of the data. - if (input_color_components * width < row_byte_width) - return false; - - png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); - if (!png_ptr) - return false; - png_info* info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, NULL); - return false; - } - - PngEncoderState state(output); - bool success = DoLibpngWrite(png_ptr, info_ptr, &state, - width, height, row_byte_width, - input, compression_level, png_output_color_type, - output_color_components, converter, comments); - png_destroy_write_struct(&png_ptr, &info_ptr); - - return success; -} - -// static -bool Encode(const unsigned char* input, ColorFormat format, - const int width, const int height, int row_byte_width, - bool discard_transparency, - const std::vector& comments, - std::vector* output) { - return EncodeWithCompressionLevel(input, format, width, height, - row_byte_width, - discard_transparency, - comments, Z_DEFAULT_COMPRESSION, - output); -} - -// Decode a PNG into an RGBA pixel array. -bool DecodePNG(const unsigned char* input, size_t input_size, - std::vector* output, - int* width, int* height) { - return Decode(input, input_size, FORMAT_RGBA, output, width, height); -} - -// Encode an RGBA pixel array into a PNG. -bool EncodeRGBAPNG(const unsigned char* input, - int width, - int height, - int row_byte_width, - std::vector* output) { - return Encode(input, FORMAT_RGBA, - width, height, row_byte_width, false, - std::vector(), output); -} - -// Encode an BGRA pixel array into a PNG. -bool EncodeBGRAPNG(const unsigned char* input, - int width, - int height, - int row_byte_width, - bool discard_transparency, - std::vector* output) { - return Encode(input, FORMAT_BGRA, - width, height, row_byte_width, discard_transparency, - std::vector(), output); -} - -} // namespace image_diff_png diff --git a/samples/image_diff_png.h b/samples/image_diff_png.h deleted file mode 100644 index 7bb395a4a545ca06c198ebbd79c1cb09a16d0fa6..0000000000000000000000000000000000000000 --- a/samples/image_diff_png.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SAMPLES_IMAGE_DIFF_PNG_H_ -#define SAMPLES_IMAGE_DIFF_PNG_H_ - -#include // for size_t. - -#include - -namespace image_diff_png { - -// Decode a PNG into an RGBA pixel array. -bool DecodePNG(const unsigned char* input, - size_t input_size, - std::vector* output, - int* width, - int* height); - -// Encode an RGBA pixel array into a PNG. -bool EncodeRGBAPNG(const unsigned char* input, - int width, - int height, - int row_byte_width, - std::vector* output); - -// Encode an BGRA pixel array into a PNG. -bool EncodeBGRAPNG(const unsigned char* input, - int width, - int height, - int row_byte_width, - bool discard_transparency, - std::vector* output); - -} // namespace image_diff_png - -#endif // SAMPLES_IMAGE_DIFF_PNG_H_ diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index a0afd4d09c339a1dd29972ba920de251cbfe4f1e..1549bd7ed46d520f264fbeb4c43625e3161d66e0 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc @@ -7,7 +7,10 @@ #include #include +#include +#include #include +#include #include #include #include @@ -17,15 +20,20 @@ #define _SKIA_SUPPORT_ #endif -#include "core/fdrm/crypto/fx_crypt.h" +#include "public/cpp/fpdf_deleters.h" +#include "public/fpdf_annot.h" +#include "public/fpdf_attachment.h" #include "public/fpdf_dataavail.h" #include "public/fpdf_edit.h" #include "public/fpdf_ext.h" #include "public/fpdf_formfill.h" +#include "public/fpdf_progressive.h" +#include "public/fpdf_structtree.h" #include "public/fpdf_text.h" #include "public/fpdfview.h" -#include "samples/image_diff_png.h" +#include "testing/image_diff/image_diff_png.h" #include "testing/test_support.h" +#include "third_party/base/logging.h" #ifdef _WIN32 #include @@ -33,6 +41,10 @@ #include #endif +#ifdef ENABLE_CALLGRIND +#include +#endif // ENABLE_CALLGRIND + #ifdef PDF_ENABLE_V8 #include "v8/include/libplatform/libplatform.h" #include "v8/include/v8.h" @@ -51,28 +63,49 @@ enum OutputFormat { OUTPUT_NONE, + OUTPUT_STRUCTURE, OUTPUT_TEXT, OUTPUT_PPM, OUTPUT_PNG, + OUTPUT_ANNOT, #ifdef _WIN32 OUTPUT_BMP, OUTPUT_EMF, + OUTPUT_PS2, + OUTPUT_PS3, #endif #ifdef PDF_ENABLE_SKIA OUTPUT_SKP, #endif }; +namespace { + struct Options { Options() : show_config(false), + show_metadata(false), send_events(false), + render_oneshot(false), + save_attachments(false), + save_images(false), +#ifdef ENABLE_CALLGRIND + callgrind_delimiters(false), +#endif // ENABLE_CALLGRIND pages(false), md5(false), - output_format(OUTPUT_NONE) {} + output_format(OUTPUT_NONE) { + } bool show_config; + bool show_metadata; bool send_events; + bool render_oneshot; + bool save_attachments; + bool save_images; +#ifdef ENABLE_CALLGRIND + bool callgrind_delimiters; +#endif // ENABLE_CALLGRIND bool pages; bool md5; OutputFormat output_format; @@ -88,23 +121,19 @@ struct Options { struct FPDF_FORMFILLINFO_PDFiumTest : public FPDF_FORMFILLINFO { // Hold a map of the currently loaded pages in order to avoid them // to get loaded twice. - std::map loaded_pages; + std::map> loaded_pages; // Hold a pointer of FPDF_FORMHANDLE so that PDFium app hooks can // make use of it. FPDF_FORMHANDLE form_handle; }; -struct AvailDeleter { - inline void operator()(FPDF_AVAIL avail) const { FPDFAvail_Destroy(avail); } -}; - -static FPDF_FORMFILLINFO_PDFiumTest* ToPDFiumTestFormFillInfo( +FPDF_FORMFILLINFO_PDFiumTest* ToPDFiumTestFormFillInfo( FPDF_FORMFILLINFO* form_fill_info) { return static_cast(form_fill_info); } -static bool CheckDimensions(int stride, int width, int height) { +bool CheckDimensions(int stride, int width, int height) { if (stride < 0 || width < 0 || height < 0) return false; if (height > 0 && width > INT_MAX / height) @@ -112,23 +141,20 @@ static bool CheckDimensions(int stride, int width, int height) { return true; } -static void OutputMD5Hash(const char* file_name, const char* buffer, int len) { +void OutputMD5Hash(const char* file_name, const char* buffer, int len) { // Get the MD5 hash and write it to stdout. - uint8_t digest[16]; - CRYPT_MD5Generate(reinterpret_cast(buffer), len, digest); - printf("MD5:%s:", file_name); - for (int i = 0; i < 16; i++) - printf("%02x", digest[i]); - printf("\n"); + std::string hash = + GenerateMD5Base16(reinterpret_cast(buffer), len); + printf("MD5:%s:%s\n", file_name, hash.c_str()); } -static std::string WritePpm(const char* pdf_name, - int num, - const void* buffer_void, - int stride, - int width, - int height) { - const char* buffer = reinterpret_cast(buffer_void); +std::string WritePpm(const char* pdf_name, + int num, + const void* buffer_void, + int stride, + int width, + int height) { + const auto* buffer = reinterpret_cast(buffer_void); if (!CheckDimensions(stride, width, height)) return ""; @@ -159,7 +185,8 @@ static std::string WritePpm(const char* pdf_name, dest_line[(w * 3) + 2] = src_line[w * 4]; } } - fwrite(result.data(), out_len, 1, fp); + if (fwrite(result.data(), out_len, 1, fp) != 1) + fprintf(stderr, "Failed to write to %s\n", filename); fclose(fp); return std::string(filename); } @@ -182,30 +209,249 @@ void WriteText(FPDF_PAGE page, const char* pdf_name, int num) { // Output in UTF32-LE. uint32_t bom = 0x0000FEFF; - fwrite(&bom, sizeof(bom), 1, fp); + if (fwrite(&bom, sizeof(bom), 1, fp) != 1) { + fprintf(stderr, "Failed to write to %s\n", filename); + (void)fclose(fp); + return; + } - FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); - for (int i = 0; i < FPDFText_CountChars(textpage); i++) { - uint32_t c = FPDFText_GetUnicode(textpage, i); - fwrite(&c, sizeof(c), 1, fp); + std::unique_ptr textpage(FPDFText_LoadPage(page)); + for (int i = 0; i < FPDFText_CountChars(textpage.get()); i++) { + uint32_t c = FPDFText_GetUnicode(textpage.get(), i); + if (fwrite(&c, sizeof(c), 1, fp) != 1) { + fprintf(stderr, "Failed to write to %s\n", filename); + break; + } } + (void)fclose(fp); +} - FPDFText_ClosePage(textpage); +const char* AnnotSubtypeToCString(FPDF_ANNOTATION_SUBTYPE subtype) { + if (subtype == FPDF_ANNOT_TEXT) + return "Text"; + if (subtype == FPDF_ANNOT_LINK) + return "Link"; + if (subtype == FPDF_ANNOT_FREETEXT) + return "FreeText"; + if (subtype == FPDF_ANNOT_LINE) + return "Line"; + if (subtype == FPDF_ANNOT_SQUARE) + return "Square"; + if (subtype == FPDF_ANNOT_CIRCLE) + return "Circle"; + if (subtype == FPDF_ANNOT_POLYGON) + return "Polygon"; + if (subtype == FPDF_ANNOT_POLYLINE) + return "PolyLine"; + if (subtype == FPDF_ANNOT_HIGHLIGHT) + return "Highlight"; + if (subtype == FPDF_ANNOT_UNDERLINE) + return "Underline"; + if (subtype == FPDF_ANNOT_SQUIGGLY) + return "Squiggly"; + if (subtype == FPDF_ANNOT_STRIKEOUT) + return "StrikeOut"; + if (subtype == FPDF_ANNOT_STAMP) + return "Stamp"; + if (subtype == FPDF_ANNOT_CARET) + return "Caret"; + if (subtype == FPDF_ANNOT_INK) + return "Ink"; + if (subtype == FPDF_ANNOT_POPUP) + return "Popup"; + if (subtype == FPDF_ANNOT_FILEATTACHMENT) + return "FileAttachment"; + if (subtype == FPDF_ANNOT_SOUND) + return "Sound"; + if (subtype == FPDF_ANNOT_MOVIE) + return "Movie"; + if (subtype == FPDF_ANNOT_WIDGET) + return "Widget"; + if (subtype == FPDF_ANNOT_SCREEN) + return "Screen"; + if (subtype == FPDF_ANNOT_PRINTERMARK) + return "PrinterMark"; + if (subtype == FPDF_ANNOT_TRAPNET) + return "TrapNet"; + if (subtype == FPDF_ANNOT_WATERMARK) + return "Watermark"; + if (subtype == FPDF_ANNOT_THREED) + return "3D"; + if (subtype == FPDF_ANNOT_RICHMEDIA) + return "RichMedia"; + if (subtype == FPDF_ANNOT_XFAWIDGET) + return "XFAWidget"; + NOTREACHED(); + return ""; +} + +void AppendFlagString(const char* flag, std::string* output) { + if (!output->empty()) + *output += ", "; + *output += flag; +} + +std::string AnnotFlagsToString(int flags) { + std::string str; + if (flags & FPDF_ANNOT_FLAG_INVISIBLE) + AppendFlagString("Invisible", &str); + if (flags & FPDF_ANNOT_FLAG_HIDDEN) + AppendFlagString("Hidden", &str); + if (flags & FPDF_ANNOT_FLAG_PRINT) + AppendFlagString("Print", &str); + if (flags & FPDF_ANNOT_FLAG_NOZOOM) + AppendFlagString("NoZoom", &str); + if (flags & FPDF_ANNOT_FLAG_NOROTATE) + AppendFlagString("NoRotate", &str); + if (flags & FPDF_ANNOT_FLAG_NOVIEW) + AppendFlagString("NoView", &str); + if (flags & FPDF_ANNOT_FLAG_READONLY) + AppendFlagString("ReadOnly", &str); + if (flags & FPDF_ANNOT_FLAG_LOCKED) + AppendFlagString("Locked", &str); + if (flags & FPDF_ANNOT_FLAG_TOGGLENOVIEW) + AppendFlagString("ToggleNoView", &str); + return str; +} + +const char* PageObjectTypeToCString(int type) { + if (type == FPDF_PAGEOBJ_TEXT) + return "Text"; + if (type == FPDF_PAGEOBJ_PATH) + return "Path"; + if (type == FPDF_PAGEOBJ_IMAGE) + return "Image"; + if (type == FPDF_PAGEOBJ_SHADING) + return "Shading"; + if (type == FPDF_PAGEOBJ_FORM) + return "Form"; + NOTREACHED(); + return ""; +} + +void WriteAnnot(FPDF_PAGE page, const char* pdf_name, int num) { + // Open the output text file. + char filename[256]; + int chars_formatted = + snprintf(filename, sizeof(filename), "%s.%d.annot.txt", pdf_name, num); + if (chars_formatted < 0 || + static_cast(chars_formatted) >= sizeof(filename)) { + fprintf(stderr, "Filename %s is too long\n", filename); + return; + } + FILE* fp = fopen(filename, "w"); + if (!fp) { + fprintf(stderr, "Failed to open %s for output\n", filename); + return; + } + + int annot_count = FPDFPage_GetAnnotCount(page); + fprintf(fp, "Number of annotations: %d\n\n", annot_count); + + // Iterate through all annotations on this page. + for (int i = 0; i < annot_count; ++i) { + // Retrieve the annotation object and its subtype. + fprintf(fp, "Annotation #%d:\n", i + 1); + FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, i); + if (!annot) { + fprintf(fp, "Failed to retrieve annotation!\n\n"); + continue; + } + FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot); + fprintf(fp, "Subtype: %s\n", AnnotSubtypeToCString(subtype)); + + // Retrieve the annotation flags. + fprintf(fp, "Flags set: %s\n", + AnnotFlagsToString(FPDFAnnot_GetFlags(annot)).c_str()); + + // Retrieve the annotation's object count and object types. + const int obj_count = FPDFAnnot_GetObjectCount(annot); + fprintf(fp, "Number of objects: %d\n", obj_count); + if (obj_count > 0) { + fprintf(fp, "Object types: "); + for (int j = 0; j < obj_count; ++j) { + const char* type = PageObjectTypeToCString( + FPDFPageObj_GetType(FPDFAnnot_GetObject(annot, j))); + fprintf(fp, "%s ", type); + } + fprintf(fp, "\n"); + } + + // Retrieve the annotation's color and interior color. + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + if (!FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A)) { + fprintf(fp, "Failed to retrieve color.\n"); + } else { + fprintf(fp, "Color in RGBA: %d %d %d %d\n", R, G, B, A); + } + if (!FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_InteriorColor, &R, &G, + &B, &A)) { + fprintf(fp, "Failed to retrieve interior color.\n"); + } else { + fprintf(fp, "Interior color in RGBA: %d %d %d %d\n", R, G, B, A); + } + + // Retrieve the annotation's contents and author. + static constexpr char kContentsKey[] = "Contents"; + static constexpr char kAuthorKey[] = "T"; + unsigned long len = + FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0); + std::vector buf(len); + FPDFAnnot_GetStringValue(annot, kContentsKey, buf.data(), len); + fprintf(fp, "Content: %ls\n", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + len = FPDFAnnot_GetStringValue(annot, kAuthorKey, nullptr, 0); + buf.clear(); + buf.resize(len); + FPDFAnnot_GetStringValue(annot, kAuthorKey, buf.data(), len); + fprintf(fp, "Author: %ls\n", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Retrieve the annotation's quadpoints if it is a markup annotation. + if (FPDFAnnot_HasAttachmentPoints(annot)) { + FS_QUADPOINTSF quadpoints; + if (FPDFAnnot_GetAttachmentPoints(annot, &quadpoints)) { + fprintf(fp, + "Quadpoints: (%.3f, %.3f), (%.3f, %.3f), (%.3f, %.3f), (%.3f, " + "%.3f)\n", + quadpoints.x1, quadpoints.y1, quadpoints.x2, quadpoints.y2, + quadpoints.x3, quadpoints.y3, quadpoints.x4, quadpoints.y4); + } else { + fprintf(fp, "Failed to retrieve quadpoints.\n"); + } + } + + // Retrieve the annotation's rectangle coordinates. + FS_RECTF rect; + if (FPDFAnnot_GetRect(annot, &rect)) { + fprintf(fp, "Rectangle: l - %.3f, b - %.3f, r - %.3f, t - %.3f\n\n", + rect.left, rect.bottom, rect.right, rect.top); + } else { + fprintf(fp, "Failed to retrieve annotation rectangle.\n"); + } + + FPDFPage_CloseAnnot(annot); + } (void)fclose(fp); } -static std::string WritePng(const char* pdf_name, - int num, - const void* buffer_void, - int stride, - int width, - int height) { +std::string WritePng(const char* pdf_name, + int num, + const void* buffer_void, + int stride, + int width, + int height) { if (!CheckDimensions(stride, width, height)) return ""; std::vector png_encoding; - const unsigned char* buffer = static_cast(buffer_void); + const auto* buffer = static_cast(buffer_void); if (!image_diff_png::EncodeBGRAPNG( buffer, width, height, stride, false, &png_encoding)) { fprintf(stderr, "Failed to convert bitmap to PNG\n"); @@ -230,19 +476,19 @@ static std::string WritePng(const char* pdf_name, size_t bytes_written = fwrite( &png_encoding.front(), 1, png_encoding.size(), fp); if (bytes_written != png_encoding.size()) - fprintf(stderr, "Failed to write to %s\n", filename); + fprintf(stderr, "Failed to write to %s\n", filename); (void)fclose(fp); return std::string(filename); } #ifdef _WIN32 -static std::string WriteBmp(const char* pdf_name, - int num, - const void* buffer, - int stride, - int width, - int height) { +std::string WriteBmp(const char* pdf_name, + int num, + const void* buffer, + int stride, + int width, + int height) { if (!CheckDimensions(stride, width, height)) return ""; @@ -270,22 +516,23 @@ static std::string WriteBmp(const char* pdf_name, file_header.bfSize = sizeof(file_header) + bmi.bmiHeader.biSize + out_len; file_header.bfOffBits = file_header.bfSize - out_len; - fwrite(&file_header, sizeof(file_header), 1, fp); - fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp); - fwrite(buffer, out_len, 1, fp); + if (fwrite(&file_header, sizeof(file_header), 1, fp) != 1 || + fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp) != 1 || + fwrite(buffer, out_len, 1, fp) != 1) { + fprintf(stderr, "Failed to write to %s\n", filename); + } fclose(fp); return std::string(filename); } void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) { - int width = static_cast(FPDF_GetPageWidth(page)); - int height = static_cast(FPDF_GetPageHeight(page)); - char filename[256]; snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num); HDC dc = CreateEnhMetaFileA(nullptr, filename, nullptr, nullptr); + int width = static_cast(FPDF_GetPageWidth(page)); + int height = static_cast(FPDF_GetPageHeight(page)); HRGN rgn = CreateRectRgn(0, 0, width, height); SelectClipRgn(dc, rgn); DeleteObject(rgn); @@ -300,12 +547,56 @@ void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) { DeleteEnhMetaFile(CloseEnhMetaFile(dc)); } -#endif + +int CALLBACK EnhMetaFileProc(HDC hdc, + HANDLETABLE* handle_table, + const ENHMETARECORD* record, + int objects_count, + LPARAM param) { + std::vector& items = + *reinterpret_cast*>(param); + items.push_back(record); + return 1; +} + +void WritePS(FPDF_PAGE page, const char* pdf_name, int num) { + char filename[256]; + snprintf(filename, sizeof(filename), "%s.%d.ps", pdf_name, num); + FILE* fp = fopen(filename, "wb"); + if (!fp) + return; + + HDC dc = CreateEnhMetaFileA(nullptr, nullptr, nullptr, nullptr); + + int width = static_cast(FPDF_GetPageWidth(page)); + int height = static_cast(FPDF_GetPageHeight(page)); + FPDF_RenderPage(dc, page, 0, 0, width, height, 0, + FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH); + + HENHMETAFILE emf = CloseEnhMetaFile(dc); + std::vector items; + EnumEnhMetaFile(nullptr, emf, &EnhMetaFileProc, &items, nullptr); + for (const ENHMETARECORD* record : items) { + if (record->iType != EMR_GDICOMMENT) + continue; + + const auto* comment = reinterpret_cast(record); + const char* data = reinterpret_cast(comment->Data); + uint16_t size = *reinterpret_cast(data); + if (fwrite(data + sizeof(uint16_t), size, 1, fp) != 1) { + fprintf(stderr, "Failed to write to %s\n", filename); + break; + } + } + fclose(fp); + DeleteEnhMetaFile(emf); +} +#endif // _WIN32 #ifdef PDF_ENABLE_SKIA -static std::string WriteSkp(const char* pdf_name, - int num, - SkPictureRecorder* recorder) { +std::string WriteSkp(const char* pdf_name, + int num, + SkPictureRecorder* recorder) { char filename[256]; int chars_formatted = snprintf(filename, sizeof(filename), "%s.%d.skp", pdf_name, num); @@ -353,7 +644,7 @@ int ExampleAppResponse(IPDF_JSPLATFORM*, GetPlatformWString(label).c_str(), is_password, length); // UTF-16, always LE regardless of platform. - uint8_t* ptr = static_cast(response); + auto* ptr = static_cast(response); ptr[0] = 'N'; ptr[1] = 0; ptr[2] = 'o'; @@ -436,8 +727,20 @@ bool ParseCommandLine(const std::vector& args, const std::string& cur_arg = args[cur_idx]; if (cur_arg == "--show-config") { options->show_config = true; + } else if (cur_arg == "--show-metadata") { + options->show_metadata = true; } else if (cur_arg == "--send-events") { options->send_events = true; + } else if (cur_arg == "--render-oneshot") { + options->render_oneshot = true; + } else if (cur_arg == "--save-attachments") { + options->save_attachments = true; + } else if (cur_arg == "--save-images") { + options->save_images = true; +#ifdef ENABLE_CALLGRIND + } else if (cur_arg == "--callgrind-delim") { + options->callgrind_delimiters = true; +#endif // ENABLE_CALLGRIND } else if (cur_arg == "--ppm") { if (options->output_format != OUTPUT_NONE) { fprintf(stderr, "Duplicate or conflicting --ppm argument\n"); @@ -456,6 +759,12 @@ bool ParseCommandLine(const std::vector& args, return false; } options->output_format = OUTPUT_TEXT; + } else if (cur_arg == "--annot") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --annot argument\n"); + return false; + } + options->output_format = OUTPUT_ANNOT; #ifdef PDF_ENABLE_SKIA } else if (cur_arg == "--skp") { if (options->output_format != OUTPUT_NONE) { @@ -478,6 +787,18 @@ bool ParseCommandLine(const std::vector& args, return false; } options->output_format = OUTPUT_EMF; + } else if (cur_arg == "--ps2") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --ps2 argument\n"); + return false; + } + options->output_format = OUTPUT_PS2; + } else if (cur_arg == "--ps3") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --ps3 argument\n"); + return false; + } + options->output_format = OUTPUT_PS3; } else if (cur_arg == "--bmp") { if (options->output_format != OUTPUT_NONE) { fprintf(stderr, "Duplicate or conflicting --bmp argument\n"); @@ -504,6 +825,12 @@ bool ParseCommandLine(const std::vector& args, return false; } options->scale_factor_as_string = cur_arg.substr(8); + } else if (cur_arg == "--show-structure") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --show-structure argument\n"); + return false; + } + options->output_format = OUTPUT_STRUCTURE; } else if (cur_arg.size() > 8 && cur_arg.compare(0, 8, "--pages=") == 0) { if (options->pages) { fprintf(stderr, "Duplicate --pages argument\n"); @@ -536,14 +863,46 @@ bool ParseCommandLine(const std::vector& args, return true; } +void PrintLastError() { + unsigned long err = FPDF_GetLastError(); + fprintf(stderr, "Load pdf docs unsuccessful: "); + switch (err) { + case FPDF_ERR_SUCCESS: + fprintf(stderr, "Success"); + break; + case FPDF_ERR_UNKNOWN: + fprintf(stderr, "Unknown error"); + break; + case FPDF_ERR_FILE: + fprintf(stderr, "File not found or could not be opened"); + break; + case FPDF_ERR_FORMAT: + fprintf(stderr, "File not in PDF format or corrupted"); + break; + case FPDF_ERR_PASSWORD: + fprintf(stderr, "Password required or incorrect password"); + break; + case FPDF_ERR_SECURITY: + fprintf(stderr, "Unsupported security scheme"); + break; + case FPDF_ERR_PAGE: + fprintf(stderr, "Page not found or content error"); + break; + default: + fprintf(stderr, "Unknown error %ld", err); + } + fprintf(stderr, ".\n"); + return; +} + FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* avail, size_t offset, size_t size) { return true; } void Add_Segment(FX_DOWNLOADHINTS* hints, size_t offset, size_t size) {} -void SendPageEvents(const FPDF_FORMHANDLE& form, - const FPDF_PAGE& page, +void SendPageEvents(FPDF_FORMHANDLE form, + FPDF_PAGE page, const std::string& events) { auto lines = StringSplit(events, '\n'); for (auto line : lines) { @@ -551,7 +910,14 @@ void SendPageEvents(const FPDF_FORMHANDLE& form, if (command[0].empty()) continue; auto tokens = StringSplit(command[0], ','); - if (tokens[0] == "keycode") { + if (tokens[0] == "charcode") { + if (tokens.size() == 2) { + int keycode = atoi(tokens[1].c_str()); + FORM_OnChar(form, page, keycode, 0); + } else { + fprintf(stderr, "charcode: bad args\n"); + } + } else if (tokens[0] == "keycode") { if (tokens.size() == 2) { int keycode = atoi(tokens[1].c_str()); FORM_OnKeyDown(form, page, keycode, 0); @@ -597,6 +963,14 @@ void SendPageEvents(const FPDF_FORMHANDLE& form, } else { fprintf(stderr, "mousemove: bad args\n"); } + } else if (tokens[0] == "focus") { + if (tokens.size() == 3) { + int x = atoi(tokens[1].c_str()); + int y = atoi(tokens[2].c_str()); + FORM_OnFocus(form, page, 0, x, y); + } else { + fprintf(stderr, "focus: bad args\n"); + } } else { fprintf(stderr, "Unrecognized event: %s\n", tokens[0].c_str()); } @@ -609,59 +983,309 @@ FPDF_PAGE GetPageForIndex(FPDF_FORMFILLINFO* param, FPDF_FORMFILLINFO_PDFiumTest* form_fill_info = ToPDFiumTestFormFillInfo(param); auto& loaded_pages = form_fill_info->loaded_pages; - auto iter = loaded_pages.find(index); if (iter != loaded_pages.end()) - return iter->second; + return iter->second.get(); FPDF_PAGE page = FPDF_LoadPage(doc, index); if (!page) return nullptr; FPDF_FORMHANDLE& form_handle = form_fill_info->form_handle; - FORM_OnAfterLoadPage(page, form_handle); FORM_DoPageAAction(page, form_handle, FPDFPAGE_AACTION_OPEN); - - loaded_pages[index] = page; + loaded_pages[index].reset(page); return page; } +std::wstring ConvertToWString(const unsigned short* buf, + unsigned long buf_size) { + std::wstring result; + result.reserve(buf_size); + std::copy(buf, buf + buf_size, std::back_inserter(result)); + return result; +} + +void DumpChildStructure(FPDF_STRUCTELEMENT child, int indent) { + static const size_t kBufSize = 1024; + unsigned short buf[kBufSize]; + unsigned long len = FPDF_StructElement_GetType(child, buf, kBufSize); + printf("%*s%ls", indent * 2, "", ConvertToWString(buf, len).c_str()); + + memset(buf, 0, sizeof(buf)); + len = FPDF_StructElement_GetTitle(child, buf, kBufSize); + if (len > 0) + printf(": '%ls'", ConvertToWString(buf, len).c_str()); + + memset(buf, 0, sizeof(buf)); + len = FPDF_StructElement_GetAltText(child, buf, kBufSize); + if (len > 0) + printf(" (%ls)", ConvertToWString(buf, len).c_str()); + printf("\n"); + + for (int i = 0; i < FPDF_StructElement_CountChildren(child); ++i) { + FPDF_STRUCTELEMENT sub_child = FPDF_StructElement_GetChildAtIndex(child, i); + // If the child is not an Element then this will return null. This can + // happen if the element is things like an object reference or a stream. + if (!sub_child) + continue; + + DumpChildStructure(sub_child, indent + 1); + } +} + +void DumpPageStructure(FPDF_PAGE page, const int page_idx) { + std::unique_ptr tree( + FPDF_StructTree_GetForPage(page)); + if (!tree) { + fprintf(stderr, "Failed to load struct tree for page %d\n", page_idx); + return; + } + + printf("Structure Tree for Page %d\n", page_idx); + for (int i = 0; i < FPDF_StructTree_CountChildren(tree.get()); ++i) { + FPDF_STRUCTELEMENT child = FPDF_StructTree_GetChildAtIndex(tree.get(), i); + if (!child) { + fprintf(stderr, "Failed to load child %d for page %d\n", i, page_idx); + continue; + } + DumpChildStructure(child, 0); + } + printf("\n\n"); +} + +void DumpMetaData(FPDF_DOCUMENT doc) { + constexpr const char* meta_tags[] = {"Title", "Author", "Subject", + "Keywords", "Creator", "Producer", + "CreationDate", "ModDate"}; + for (const char* meta_tag : meta_tags) { + char meta_buffer[4096]; + unsigned long len = + FPDF_GetMetaText(doc, meta_tag, meta_buffer, sizeof(meta_buffer)); + if (!len) + continue; + + auto* meta_string = reinterpret_cast(meta_buffer); + printf("%-12s = %ls (%lu bytes)\n", meta_tag, + GetPlatformWString(meta_string).c_str(), len); + } +} + +void SaveAttachments(FPDF_DOCUMENT doc, const std::string& name) { + for (int i = 0; i < FPDFDoc_GetAttachmentCount(doc); ++i) { + FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(doc, i); + + // Retrieve the attachment file name. + std::string attachment_name; + unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0); + if (len) { + std::vector buf(len); + unsigned long actual_len = + FPDFAttachment_GetName(attachment, buf.data(), len); + if (actual_len == len) { + attachment_name = + GetPlatformString(reinterpret_cast(buf.data())); + } + } + if (attachment_name.empty()) { + fprintf(stderr, "Attachment #%d has an empty file name.\n", i + 1); + continue; + } + + // Calculate the full attachment file name. + char save_name[256]; + int chars_formatted = + snprintf(save_name, sizeof(save_name), "%s.attachment.%s", name.c_str(), + attachment_name.c_str()); + if (chars_formatted < 0 || + static_cast(chars_formatted) >= sizeof(save_name)) { + fprintf(stderr, "Filename %s is too long\n", save_name); + continue; + } + + // Retrieve the attachment. + len = FPDFAttachment_GetFile(attachment, nullptr, 0); + std::vector data_buf(len); + if (len) { + unsigned long actual_len = + FPDFAttachment_GetFile(attachment, data_buf.data(), len); + if (actual_len != len) + data_buf.clear(); + } + if (data_buf.empty()) { + fprintf(stderr, "Attachment \"%s\" is empty.\n", attachment_name.c_str()); + continue; + } + + // Write the attachment file. + FILE* fp = fopen(save_name, "wb"); + if (!fp) { + fprintf(stderr, "Failed to open %s for saving attachment.\n", save_name); + continue; + } + + size_t written_len = fwrite(data_buf.data(), 1, len, fp); + if (written_len == len) { + fprintf(stderr, "Saved attachment \"%s\" as: %s.\n", + attachment_name.c_str(), save_name); + } else { + fprintf(stderr, "Failed to write to %s\n", save_name); + } + fclose(fp); + } +} + +void SaveImages(FPDF_PAGE page, const char* pdf_name, int page_num) { + for (int i = 0; i < FPDFPage_CountObjects(page); ++i) { + FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i); + if (FPDFPageObj_GetType(obj) != FPDF_PAGEOBJ_IMAGE) + continue; + + std::unique_ptr bitmap( + FPDFImageObj_GetBitmap(obj)); + if (!bitmap) { + fprintf(stderr, "Image object #%d on page #%d has an empty bitmap.\n", + i + 1, page_num + 1); + continue; + } + + int format = FPDFBitmap_GetFormat(bitmap.get()); + if (format == FPDFBitmap_Unknown) { + fprintf(stderr, + "Image object #%d on page #%d has a bitmap of unknown format.\n", + i + 1, page_num + 1); + continue; + } + + std::vector png_encoding; + const unsigned char* buffer = + static_cast(FPDFBitmap_GetBuffer(bitmap.get())); + int width = FPDFBitmap_GetWidth(bitmap.get()); + int height = FPDFBitmap_GetHeight(bitmap.get()); + int stride = FPDFBitmap_GetStride(bitmap.get()); + bool ret = false; + switch (format) { + case FPDFBitmap_Gray: + ret = image_diff_png::EncodeGrayPNG(buffer, width, height, stride, + &png_encoding); + break; + case FPDFBitmap_BGR: + ret = image_diff_png::EncodeBGRPNG(buffer, width, height, stride, + &png_encoding); + break; + case FPDFBitmap_BGRx: + ret = image_diff_png::EncodeBGRAPNG(buffer, width, height, stride, true, + &png_encoding); + break; + case FPDFBitmap_BGRA: + ret = image_diff_png::EncodeBGRAPNG(buffer, width, height, stride, + false, &png_encoding); + break; + default: + NOTREACHED(); + } + if (!ret) { + fprintf(stderr, + "Failed to convert image object #%d on page #%d to png.\n", i + 1, + page_num + 1); + continue; + } + + char filename[256]; + int chars_formatted = snprintf(filename, sizeof(filename), "%s.%d.%d.png", + pdf_name, page_num, i); + if (chars_formatted < 0 || + static_cast(chars_formatted) >= sizeof(filename)) { + fprintf(stderr, "Filename %s for saving image is too long\n", filename); + continue; + } + + FILE* fp = fopen(filename, "wb"); + if (!fp) { + fprintf(stderr, "Failed to open %s for saving image.\n", filename); + continue; + } + + size_t bytes_written = + fwrite(&png_encoding.front(), 1, png_encoding.size(), fp); + if (bytes_written != png_encoding.size()) + fprintf(stderr, "Failed to write to %s.\n", filename); + else + fprintf(stderr, "Successfully wrote embedded image %s.\n", filename); + + (void)fclose(fp); + } +} + +// Note, for a client using progressive rendering you'd want to determine if you +// need the rendering to pause instead of always saying |true|. This is for +// testing to force the renderer to break whenever possible. +FPDF_BOOL NeedToPauseNow(IFSDK_PAUSE* p) { + return true; +} + bool RenderPage(const std::string& name, FPDF_DOCUMENT doc, - FPDF_FORMHANDLE& form, - FPDF_FORMFILLINFO_PDFiumTest& form_fill_info, + FPDF_FORMHANDLE form, + FPDF_FORMFILLINFO_PDFiumTest* form_fill_info, const int page_index, const Options& options, const std::string& events) { - FPDF_PAGE page = GetPageForIndex(&form_fill_info, doc, page_index); + FPDF_PAGE page = GetPageForIndex(form_fill_info, doc, page_index); if (!page) return false; - - FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page); - if (options.send_events) SendPageEvents(form, page, events); + if (options.save_images) + SaveImages(page, name.c_str(), page_index); + if (options.output_format == OUTPUT_STRUCTURE) { + DumpPageStructure(page, page_index); + return true; + } + + std::unique_ptr text_page(FPDFText_LoadPage(page)); double scale = 1.0; if (!options.scale_factor_as_string.empty()) std::stringstream(options.scale_factor_as_string) >> scale; - int width = static_cast(FPDF_GetPageWidth(page) * scale); - int height = static_cast(FPDF_GetPageHeight(page) * scale); + auto width = static_cast(FPDF_GetPageWidth(page) * scale); + auto height = static_cast(FPDF_GetPageHeight(page) * scale); int alpha = FPDFPage_HasTransparency(page) ? 1 : 0; - FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, alpha); + std::unique_ptr bitmap( + FPDFBitmap_Create(width, height, alpha)); + if (bitmap) { FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF; - FPDFBitmap_FillRect(bitmap, 0, 0, width, height, fill_color); - FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, FPDF_ANNOT); + FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, fill_color); + + if (options.render_oneshot) { + // Note, client programs probably want to use this method instead of the + // progressive calls. The progressive calls are if you need to pause the + // rendering to update the UI, the PDF renderer will break when possible. + FPDF_RenderPageBitmap(bitmap.get(), page, 0, 0, width, height, 0, + FPDF_ANNOT); + } else { + IFSDK_PAUSE pause; + pause.version = 1; + pause.NeedToPauseNow = &NeedToPauseNow; + + int rv = FPDF_RenderPageBitmap_Start(bitmap.get(), page, 0, 0, width, + height, 0, FPDF_ANNOT, &pause); + while (rv == FPDF_RENDER_TOBECOUNTINUED) + rv = FPDF_RenderPage_Continue(page, &pause); + } - FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, FPDF_ANNOT); - int stride = FPDFBitmap_GetStride(bitmap); + FPDF_FFLDraw(form, bitmap.get(), page, 0, 0, width, height, 0, FPDF_ANNOT); + + if (!options.render_oneshot) + FPDF_RenderPage_Close(page); + + int stride = FPDFBitmap_GetStride(bitmap.get()); const char* buffer = - reinterpret_cast(FPDFBitmap_GetBuffer(bitmap)); + reinterpret_cast(FPDFBitmap_GetBuffer(bitmap.get())); - std::string&& image_file_name = ""; + std::string image_file_name; switch (options.output_format) { #ifdef _WIN32 case OUTPUT_BMP: @@ -672,11 +1296,20 @@ bool RenderPage(const std::string& name, case OUTPUT_EMF: WriteEmf(page, name.c_str(), page_index); break; + + case OUTPUT_PS2: + case OUTPUT_PS3: + WritePS(page, name.c_str(), page_index); + break; #endif case OUTPUT_TEXT: WriteText(page, name.c_str(), page_index); break; + case OUTPUT_ANNOT: + WriteAnnot(page, name.c_str(), page_index); + break; + case OUTPUT_PNG: image_file_name = WritePng(name.c_str(), page_index, buffer, stride, width, height); @@ -702,20 +1335,14 @@ bool RenderPage(const std::string& name, // Write the filename and the MD5 of the buffer to stdout if we wrote a // file. - if (options.md5 && image_file_name != "") + if (options.md5 && !image_file_name.empty()) OutputMD5Hash(image_file_name.c_str(), buffer, stride * height); - - FPDFBitmap_Destroy(bitmap); } else { fprintf(stderr, "Page was too large to be rendered.\n"); } - form_fill_info.loaded_pages.erase(page_index); - FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE); FORM_OnBeforeClosePage(page, form); - FPDFText_ClosePage(text_page); - FPDF_ClosePage(page); return !!bitmap; } @@ -724,14 +1351,17 @@ void RenderPdf(const std::string& name, size_t len, const Options& options, const std::string& events) { - IPDF_JSPLATFORM platform_callbacks; - memset(&platform_callbacks, '\0', sizeof(platform_callbacks)); + IPDF_JSPLATFORM platform_callbacks = {}; platform_callbacks.version = 3; platform_callbacks.app_alert = ExampleAppAlert; platform_callbacks.app_response = ExampleAppResponse; platform_callbacks.Doc_gotoPage = ExampleDocGotoPage; platform_callbacks.Doc_mail = ExampleDocMail; + // The pdf_avail must outlive doc. + std::unique_ptr pdf_avail; + // The document must outlive |form_callbacks.loaded_pages|. + std::unique_ptr doc; FPDF_FORMFILLINFO_PDFiumTest form_callbacks = {}; #ifdef PDF_ENABLE_XFA form_callbacks.version = 2; @@ -742,105 +1372,84 @@ void RenderPdf(const std::string& name, form_callbacks.m_pJsPlatform = &platform_callbacks; TestLoader loader(pBuf, len); - FPDF_FILEACCESS file_access; - memset(&file_access, '\0', sizeof(file_access)); + FPDF_FILEACCESS file_access = {}; file_access.m_FileLen = static_cast(len); file_access.m_GetBlock = TestLoader::GetBlock; file_access.m_Param = &loader; - FX_FILEAVAIL file_avail; - memset(&file_avail, '\0', sizeof(file_avail)); + FX_FILEAVAIL file_avail = {}; file_avail.version = 1; file_avail.IsDataAvail = Is_Data_Avail; - FX_DOWNLOADHINTS hints; - memset(&hints, '\0', sizeof(hints)); + FX_DOWNLOADHINTS hints = {}; hints.version = 1; hints.AddSegment = Add_Segment; - FPDF_DOCUMENT doc; int nRet = PDF_DATA_NOTAVAIL; bool bIsLinearized = false; - FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access); - std::unique_ptr scoped_pdf_avail_deleter(pdf_avail); + pdf_avail.reset(FPDFAvail_Create(&file_avail, &file_access)); - if (FPDFAvail_IsLinearized(pdf_avail) == PDF_LINEARIZED) { - doc = FPDFAvail_GetDocument(pdf_avail, nullptr); + if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) { + doc.reset(FPDFAvail_GetDocument(pdf_avail.get(), nullptr)); if (doc) { while (nRet == PDF_DATA_NOTAVAIL) - nRet = FPDFAvail_IsDocAvail(pdf_avail, &hints); + nRet = FPDFAvail_IsDocAvail(pdf_avail.get(), &hints); if (nRet == PDF_DATA_ERROR) { fprintf(stderr, "Unknown error in checking if doc was available.\n"); - FPDF_CloseDocument(doc); return; } - nRet = FPDFAvail_IsFormAvail(pdf_avail, &hints); + nRet = FPDFAvail_IsFormAvail(pdf_avail.get(), &hints); if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL) { fprintf(stderr, "Error %d was returned in checking if form was available.\n", nRet); - FPDF_CloseDocument(doc); return; } bIsLinearized = true; } } else { - doc = FPDF_LoadCustomDocument(&file_access, nullptr); + doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr)); } if (!doc) { - unsigned long err = FPDF_GetLastError(); - fprintf(stderr, "Load pdf docs unsuccessful: "); - switch (err) { - case FPDF_ERR_SUCCESS: - fprintf(stderr, "Success"); - break; - case FPDF_ERR_UNKNOWN: - fprintf(stderr, "Unknown error"); - break; - case FPDF_ERR_FILE: - fprintf(stderr, "File not found or could not be opened"); - break; - case FPDF_ERR_FORMAT: - fprintf(stderr, "File not in PDF format or corrupted"); - break; - case FPDF_ERR_PASSWORD: - fprintf(stderr, "Password required or incorrect password"); - break; - case FPDF_ERR_SECURITY: - fprintf(stderr, "Unsupported security scheme"); - break; - case FPDF_ERR_PAGE: - fprintf(stderr, "Page not found or content error"); - break; - default: - fprintf(stderr, "Unknown error %ld", err); - } - fprintf(stderr, ".\n"); - + PrintLastError(); return; } - (void)FPDF_GetDocPermissions(doc); + (void)FPDF_GetDocPermissions(doc.get()); + + if (options.show_metadata) + DumpMetaData(doc.get()); - FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnvironment(doc, &form_callbacks); - form_callbacks.form_handle = form; + if (options.save_attachments) + SaveAttachments(doc.get(), name); + + std::unique_ptr form( + FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks)); + form_callbacks.form_handle = form.get(); #ifdef PDF_ENABLE_XFA - int doc_type = DOCTYPE_PDF; - if (FPDF_HasXFAField(doc, &doc_type) && doc_type != DOCTYPE_PDF && - !FPDF_LoadXFA(doc)) { - fprintf(stderr, "LoadXFA unsuccessful, continuing anyway.\n"); + int doc_type = FPDF_GetFormType(doc.get()); + if (doc_type == FORMTYPE_XFA_FULL || doc_type == FORMTYPE_XFA_FOREGROUND) { + if (!FPDF_LoadXFA(doc.get())) + fprintf(stderr, "LoadXFA unsuccessful, continuing anyway.\n"); } #endif // PDF_ENABLE_XFA - FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD); - FPDF_SetFormFieldHighlightAlpha(form, 100); - FORM_DoDocumentJSAction(form); - FORM_DoDocumentOpenAction(form); + FPDF_SetFormFieldHighlightColor(form.get(), FPDF_FORMFIELD_UNKNOWN, 0xFFE4DD); + FPDF_SetFormFieldHighlightAlpha(form.get(), 100); + FORM_DoDocumentJSAction(form.get()); + FORM_DoDocumentOpenAction(form.get()); - int page_count = FPDF_GetPageCount(doc); +#if _WIN32 + if (options.output_format == OUTPUT_PS2) + FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT2); + else if (options.output_format == OUTPUT_PS3) + FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3); +#endif + + int page_count = FPDF_GetPageCount(doc.get()); int rendered_pages = 0; int bad_pages = 0; int first_page = options.pages ? options.first_page : 0; @@ -849,33 +1458,29 @@ void RenderPdf(const std::string& name, if (bIsLinearized) { nRet = PDF_DATA_NOTAVAIL; while (nRet == PDF_DATA_NOTAVAIL) - nRet = FPDFAvail_IsPageAvail(pdf_avail, i, &hints); + nRet = FPDFAvail_IsPageAvail(pdf_avail.get(), i, &hints); if (nRet == PDF_DATA_ERROR) { fprintf(stderr, "Unknown error in checking if page %d is available.\n", i); - FPDFDOC_ExitFormFillEnvironment(form); - FPDF_CloseDocument(doc); return; } } - if (RenderPage(name, doc, form, form_callbacks, i, options, events)) + if (RenderPage(name, doc.get(), form.get(), &form_callbacks, i, options, + events)) { ++rendered_pages; - else + } else { ++bad_pages; + } } - FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC); - - FPDFDOC_ExitFormFillEnvironment(form); - FPDF_CloseDocument(doc); - + FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC); fprintf(stderr, "Rendered %d pages.\n", rendered_pages); if (bad_pages) fprintf(stderr, "Skipped %d bad pages.\n", bad_pages); } -static void ShowConfig() { +void ShowConfig() { std::string config; std::string maybe_comma; #if PDF_ENABLE_V8 @@ -901,27 +1506,44 @@ static void ShowConfig() { printf("%s\n", config.c_str()); } -static const char kUsageString[] = +constexpr char kUsageString[] = "Usage: pdfium_test [OPTION] [FILE]...\n" - " --show-config - print build options and exit\n" - " --send-events - send input described by .evt file\n" - " --bin-dir= - override path to v8 external data\n" - " --font-dir= - override path to external fonts\n" - " --scale= - scale output size by number (e.g. 0.5)\n" + " --show-config - print build options and exit\n" + " --show-metadata - print the file metadata\n" + " --show-structure - print the structure elements from the document\n" + " --send-events - send input described by .evt file\n" + " --render-oneshot - render image without using progressive renderer\n" + " --save-attachments - write embedded attachments " + ".attachment.\n" + " --save-images - write embedded images " + "...png\n" +#ifdef ENABLE_CALLGRIND + " --callgrind-delim - delimit interesting section when using callgrind\n" +#endif // ENABLE_CALLGRIND + " --bin-dir= - override path to v8 external data\n" + " --font-dir= - override path to external fonts\n" + " --scale= - scale output size by number (e.g. 0.5)\n" " --pages=(-) - only render the given 0-based page(s)\n" #ifdef _WIN32 - " --bmp - write page images ..bmp\n" - " --emf - write page meta files ..emf\n" + " --bmp - write page images ..bmp\n" + " --emf - write page meta files ..emf\n" + " --ps2 - write page raw PostScript (Lvl 2) " + "..ps\n" + " --ps3 - write page raw PostScript (Lvl 3) " + "..ps\n" #endif // _WIN32 - " --txt - write page text in UTF32-LE ..txt\n" - " --png - write page images ..png\n" - " --ppm - write page images ..ppm\n" + " --txt - write page text in UTF32-LE ..txt\n" + " --png - write page images ..png\n" + " --ppm - write page images ..ppm\n" + " --annot - write annotation info ..annot.txt\n" #ifdef PDF_ENABLE_SKIA - " --skp - write page images ..skp\n" + " --skp - write page images ..skp\n" #endif - " --md5 - write output image paths and their md5 hashes to stdout.\n" + " --md5 - write output image paths and their md5 hashes to stdout.\n" ""; +} // namespace + int main(int argc, const char* argv[]) { std::vector args(argv, argv + argc); Options options; @@ -967,8 +1589,7 @@ int main(int argc, const char* argv[]) { } FPDF_InitLibraryWithConfig(&config); - UNSUPPORT_INFO unsupported_info; - memset(&unsupported_info, '\0', sizeof(unsupported_info)); + UNSUPPORT_INFO unsupported_info = {}; unsupported_info.version = 1; unsupported_info.FSDK_UnSupport_Handler = ExampleUnsupportedHandler; @@ -981,6 +1602,12 @@ int main(int argc, const char* argv[]) { if (!file_contents) continue; fprintf(stderr, "Rendering PDF file %s.\n", filename.c_str()); + +#ifdef ENABLE_CALLGRIND + if (options.callgrind_delimiters) + CALLGRIND_START_INSTRUMENTATION; +#endif // ENABLE_CALLGRIND + std::string events; if (options.send_events) { std::string event_filename = filename; @@ -1001,6 +1628,11 @@ int main(int argc, const char* argv[]) { } } RenderPdf(filename, file_contents.get(), file_length, options, events); + +#ifdef ENABLE_CALLGRIND + if (options.callgrind_delimiters) + CALLGRIND_STOP_INSTRUMENTATION; +#endif // ENABLE_CALLGRIND } FPDF_DestroyLibrary(); diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 723e872b0dcb7439dc028067d4f5707d00c7df59..7ca7c1912612802493e87f84385dbc1270a9638c 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn @@ -23,9 +23,11 @@ config("skia_config") { "config", "ext", "//third_party/skia/include/c", + "//third_party/skia/include/codec", "//third_party/skia/include/config", "//third_party/skia/include/core", "//third_party/skia/include/effects", + "//third_party/skia/include/encode", "//third_party/skia/include/images", "//third_party/skia/include/lazy", "//third_party/skia/include/pathops", @@ -33,13 +35,22 @@ config("skia_config") { "//third_party/skia/include/pipe", "//third_party/skia/include/ports", "//third_party/skia/include/utils", - - # TODO(dsinclair): Right way to use //third_party/freetype? - "//third_party/freetype/include", + "//third_party/skia/third_party/vulkan", ] defines = [] + if (is_win) { + defines += [ "SK_FREETYPE_MINIMUM_RUNTIME_VERSION=(((FREETYPE_MAJOR) * 0x01000000) | ((FREETYPE_MINOR) * 0x00010000) | ((FREETYPE_PATCH) * 0x00000100))" ] + } + + if (is_component_build) { + defines += [ + "SKIA_DLL", + "GR_GL_IGNORE_ES3_MSAA=0", + ] + } + if (skia_support_gpu) { include_dirs += [ "//third_party/skia/include/gpu", @@ -80,6 +91,7 @@ config("skia_library_config") { "//third_party/skia/src/pdf", "//third_party/skia/src/ports", "//third_party/skia/src/sfnt", + "//third_party/skia/src/shaders", "//third_party/skia/src/sksl", "//third_party/skia/src/utils", "//third_party/skia/src/lazy", @@ -93,6 +105,10 @@ config("skia_library_config") { defines = [] + if (is_component_build) { + defines += [ "SKIA_IMPLEMENTATION=1" ] + } + if (current_cpu == "arm") { if (arm_use_neon) { defines += [ "SK_ARM_HAS_NEON" ] @@ -171,7 +187,7 @@ component("skia") { "ext/google_logging.cc", ] - # The skia gypi values are relative to the skia_dir, so we need to rebase. + # The skia sources values are relative to the skia_dir, so we need to rebase. sources += skia_core_sources sources += skia_effects_sources sources += skia_sksl_sources @@ -179,6 +195,7 @@ component("skia") { sources += [ "//third_party/skia/src/fonts/SkFontMgr_indirect.cpp", "//third_party/skia/src/fonts/SkRemotableFontMgr.cpp", + "//third_party/skia/src/images/SkImageEncoder.cpp", "//third_party/skia/src/ports/SkFontHost_FreeType.cpp", "//third_party/skia/src/ports/SkFontHost_FreeType_common.cpp", "//third_party/skia/src/ports/SkFontHost_win.cpp", @@ -186,7 +203,6 @@ component("skia") { "//third_party/skia/src/ports/SkFontMgr_android_factory.cpp", "//third_party/skia/src/ports/SkFontMgr_android_parser.cpp", "//third_party/skia/src/ports/SkGlobalInitialization_default.cpp", - "//third_party/skia/src/ports/SkImageEncoder_none.cpp", "//third_party/skia/src/ports/SkImageGenerator_none.cpp", "//third_party/skia/src/ports/SkOSFile_posix.cpp", "//third_party/skia/src/ports/SkOSFile_stdio.cpp", @@ -223,14 +239,12 @@ component("skia") { sources += skia_null_gpu_sources } - # Remove unused util files include in utils.gypi + # Remove unused util files include in utils.gni sources -= [ - "//third_party/skia/src/utils/SkBoundaryPatch.cpp", "//third_party/skia/src/utils/SkCamera.cpp", "//third_party/skia/src/utils/SkDumpCanvas.cpp", "//third_party/skia/src/utils/SkFrontBufferedStream.cpp", "//third_party/skia/src/utils/SkInterpolator.cpp", - "//third_party/skia/src/utils/SkMeshUtils.cpp", "//third_party/skia/src/utils/SkParsePath.cpp", ] @@ -306,7 +320,8 @@ component("skia") { deps = [ ":skia_opts", - "../third_party:fx_zlib", + "../third_party:zlib", + "//:freetype_common", ] if (is_linux) { @@ -486,7 +501,7 @@ source_set("skia_opts") { cflags += [ "-fomit-frame-pointer" ] sources = skia_opts.none_sources } else { - assert(false, "Need to port cpu specific stuff from skia_library_opts.gyp") + assert(false, "Need to port cpu specific stuff from gn/BUILDCONFIG.gn") } if (is_android && !is_debug) { diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index e09a2351b3bd68b6bcf0a38c1aab42737b979c69..bb9862b5640a1d97e66a94746d4de2fe1ffbd70b 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h @@ -235,7 +235,7 @@ SK_API void SkDebugf_FileLine(const char* file, #define SK_SUPPORT_LEGACY_EVAL_CUBIC #endif -///////////////////////// Imported from BUILD.gn and skia_common.gypi +///////////////////////// Imported from BUILD.gn /* In some places Skia can use static initializers for global initialization, * or fall back to lazy runtime initialization. Chrome always wants the latter. diff --git a/testing/DEPS b/testing/DEPS index 5adeb4141be0accfe0c73c120cf4b94f1f716193..d0dc17242b6a965bcd8060a91f7b77db5d62d31e 100644 --- a/testing/DEPS +++ b/testing/DEPS @@ -1,6 +1,8 @@ include_rules = [ '+core', + '+fpdfsdk', '+fxjs', '+public', '+v8', + '+xfa' ] diff --git a/testing/SUPPRESSIONS b/testing/SUPPRESSIONS index 447c9fa529bd4dc45743e94f299a835704486263..1edc158161ca61eb2f390da395468242c49085db 100644 --- a/testing/SUPPRESSIONS +++ b/testing/SUPPRESSIONS @@ -18,11 +18,6 @@ # # Try to keep the file alphabetized within each category of test. -# -# Pixel tests -# -font_size.in mac * * - # # Corpus tests # @@ -50,219 +45,28 @@ font_size.in mac * * 8.2_name_dest_f_dest.pdf mac * * 8.2_outline.pdf mac * * 8.3_presentation.pdf mac * * -FRC_10_8.2.2_Prev_remove_all.pdf mac * * FRC_10_8.2.2__T8.3_original_file.pdf * * * -FRC_10_8.2.4_View_C.pdf mac * * -FRC_10_8.2.4__remove_ModDate_value.pdf mac * * -FRC_11_8.2.2_Prev_remove_obj.pdf mac * * FRC_11_8.2.2__T8.3_first_last_exchange.pdf * * * -FRC_11_8.2.4_View_edit.pdf mac * * -FRC_11_8.2.4__remove_ModDate_all.pdf mac * * -FRC_12_8.2.2__Next_remove_value.pdf mac * * FRC_12_8.2.2__T8.3_first_outline_obj_ID.pdf * * * -FRC_12_8.2.4_View_remove_all.pdf mac * * -FRC_12_8.2.4__remove_ModDate_obj_.pdf mac * * -FRC_13_8.2.2__Next_remove_all.pdf mac * * FRC_13_8.2.2__T8.3_Count_edit300.pdf * * * -FRC_13_8.2.4_View_remove_value.pdf mac * * -FRC_13_8.2.4_remove_Size_value.pdf mac * * -FRC_14_8.2.2__Next_remove_obj.pdf mac * * FRC_14_8.2.2__T8.3_Count_edit0.pdf * * * -FRC_14_8.2.4_Sort_remove_all.pdf mac * * -FRC_14_8.2.4_remove_Size_all.pdf mac * * -FRC_15_8.2.2__Next_exchange.pdf mac * * FRC_15_8.2.2__T8.3_Count_edit1.pdf * * * -FRC_15_8.2.4_Sort_remove_value.pdf mac * * -FRC_15_8.2.4_remove_Size_obj.pdf mac * * -FRC_16_8.2.2__Next_add.pdf mac * * FRC_16_8.2.2__T8.3_Count_edit_1.pdf * * * -FRC_16_8.2.4__remove_CompressedSize__value.pdf mac * * -FRC_17_8.2.2__T8.4_First_remove_value.pdf mac * * -FRC_17_8.2.4__remove_CompressedSize__all.pdf mac * * -FRC_18_8.2.2__T8.4_First_remove_all.pdf mac * * -FRC_18_8.2.4__remove_CompressedSize__obj.pdf mac * * -FRC_19_8.2.2__T8.4_First_remove_obj.pdf mac * * -FRC_19_8.2.4__remove_CreationDate_value.pdf mac * * FRC_1_8.2.2__T8.3_First_empty.pdf * * * -FRC_1_8.2.2__Title_edit.pdf mac * * -FRC_1_8.2.4_Type_8.6_.pdf mac * * -FRC_1_8.2.4__original.pdf mac * * -FRC_20_8.2.2__T8.4_First_remove_value2.pdf mac * * -FRC_20_8.2.4__remove_CreationDate_all.pdf mac * * -FRC_21_8.2.2__T8.4_First_remove_all2.pdf mac * * -FRC_21_8.2.4__remove_CreationDate_obj.pdf mac * * -FRC_22_8.2.2__T8.4_First_remove_obj2.pdf mac * * -FRC_22_8.2.4__remove_Order_value.pdf mac * * -FRC_23_8.2.2__T8.4_Last_remove_value.pdf mac * * -FRC_23_8.2.4__remove_Order_all.pdf mac * * -FRC_24_8.2.2__T8.4_Last_remove_all.pdf mac * * -FRC_24_8.2.4__remove_Order_obj.pdf mac * * -FRC_25_8.2.2__T8.4_Last_remove_obj.pdf mac * * -FRC_26_8.2.2__T8.4_Last_remove_value2.pdf mac * * -FRC_27_8.2.2__T8.4_Last_remove_all2.pdf mac * * -FRC_28_8.2.2__T8.4_Last_remove_obj2.pdf mac * * -FRC_29_8.2.2__T8.4_First_Last_exchange.pdf mac * * FRC_2_8.2.2__T8.3_Last_empty.pdf * * * -FRC_2_8.2.2__Title_remove_value.pdf mac * * -FRC_2_8.2.4_Type_8.6__remove_value.pdf mac * * -FRC_2_8.2.4__add_type_.pdf mac * * -FRC_3.5_AuthEvent_EFOpen.pdf mac * * -FRC_3.5_CFM_AESV2__EncryptMetadata_F.pdf mac * * -FRC_3.5_CF_EFF_StdCF_Strf_Stmf_Identity.pdf mac * * -FRC_3.5_CF_Strf_stmf_StdCF.pdf mac * * -FRC_3.5_EncryptMetadata_None.pdf mac * * -FRC_3.5_P_4_Password_1.pdf mac * * -FRC_3.5_P__1852_Password_1.pdf mac * * -FRC_3.5_P__2584_Password_1.pdf mac * * -FRC_3.5_P__2616_Password_1.pdf mac * * -FRC_3.5_P__2880_Password_1.pdf mac * * -FRC_3.5_P__3376_Password_1.pdf mac * * -FRC_3.5_P__3392_Password_1.pdf mac * * -FRC_3.5_P__3608_Password_1.pdf mac * * -FRC_3.5_P__3616_Password_1.pdf mac,win * * -FRC_3.5_P__3648_Password_1.pdf mac * * -FRC_3.5_P__3900_Password_1.pdf mac * * -FRC_3.5_V_4_CFM_V2_.pdf mac * * -FRC_3.5_V_5_CFM_AESV3.pdf mac * * -FRC_3.5_v_1_length_40_Filter_standard.pdf mac * * -FRC_3.5_v_2_length_128_AuthEvent_DocOpen_.pdf mac * * -FRC_31_8.2.2_add_dest_entry.pdf mac * * -FRC_32_8.2.2_A_Support_action.pdf mac * * -FRC_33_8.2.2_A_empty.pdf mac * * -FRC_34_8.2.2_A_remove.pdf mac * * -FRC_35_8.2.2_A_remove_A_item.pdf mac * * -FRC_36_8.2.2_Dest.pdf mac * * -FRC_37_8.2.2_Dest_empty.pdf mac * * -FRC_38_8.2.2_Dest_remove.pdf mac * * -FRC_39_8.2.2_C_edit.pdf mac * * +FRC_3.5_P__3616_Password_1.pdf * * * FRC_3_8.2.2_Type_empty.pdf * * * -FRC_3_8.2.2__Title_remove_all.pdf mac * * -FRC_3_8.2.4_Type_8.6__edit_.pdf mac * * -FRC_3_8.2.4__add_type_value.pdf mac * * -FRC_4.5.3_DeviceCMYK_k.pdf mac * * -FRC_4.5.3_DeviceGray_g.pdf mac * * -FRC_4.5.3_DeviceRGB_rg.pdf mac * * -FRC_4.5.4_CalGray_gamma.pdf mac * * -FRC_4.5.4_CalGray_whitepoint.pdf mac * * -FRC_4.5.4_CalRGB_gamma.pdf mac * * -FRC_4.5.4_CalRGB_matrix.pdf mac * * -FRC_4.5.4_CalRGB_whitepoint.pdf mac * * -FRC_4.5.4_ICCBased.pdf mac * * -FRC_4.5.4_Lab.pdf mac * * -FRC_4.5.4_RI_Absolute.pdf mac * * -FRC_4.5.4_RI_Perceptual.pdf mac * * -FRC_4.5.4_RI_Relative.pdf mac * * -FRC_4.5.4_RI_Saturation.pdf mac * * -FRC_4.5.4_Separation.pdf mac * * -FRC_4.5.5_DeviceN.pdf mac * * -FRC_4.5.5_Indexed.pdf mac * * -FRC_4.5.5_Pattern_tiling.pdf mac * * -FRC_40_8.2.2_C_empty1.pdf mac * * -FRC_41_8.2.2_C_empty2.pdf mac * * -FRC_42_8.2.2_C_empty3.pdf mac * * -FRC_43_8.2.2_C_empty.pdf mac * * -FRC_44_8.2.2_C_remove.pdf mac * * -FRC_45_8.2.2_F_edit_F_1_2_3.pdf mac * * -FRC_46_8.2.2_F_edit_F__1__2__3.pdf mac * * -FRC_47_8.2.2_F_edit_F_32__32.pdf mac * * -FRC_48_8.2.2_F_edit_F_100__100.pdf mac * * -FRC_49_8.2.2_F_empty.pdf mac * * -FRC_4_8.2.2_Parent_edit2.pdf mac * * FRC_4_8.2.2__T8.3_Count_empty.pdf * * * -FRC_4_8.2.4_Schema_8.6__remove_all.pdf mac * * -FRC_4_8.2.4__remove_FileName_value.pdf mac * * -FRC_50_8.2.2_F_remove.pdf mac * * -FRC_51_8.2.2_T_8.4__Count_edit_count_100.pdf mac * * -FRC_52_8.2.2_T_8.4__Count_edit_count_0.pdf mac * * -FRC_53_8.2.2_T_8.4__Count_empty.pdf mac * * -FRC_54_8.2.2_T_8.4__Count_empty1.pdf mac * * -FRC_55_8.2.2_T_8.4__Count_remove.pdf mac * * -FRC_56_8.2.2_C_edit_C__1.pdf mac * * -FRC_57_8.2.2_C_edit_C_2.pdf mac * * -FRC_58_8.2.2_Count_edit_count__2.pdf mac * * -FRC_5_8.2.2_Parent_remove_value.pdf mac * * FRC_5_8.2.2__T8.3_First_remove.pdf * * * -FRC_5_8.2.4_Schema_8.6__remove_value.pdf mac * * -FRC_5_8.2.4__remove_FileName_all.pdf mac * * -FRC_6_8.2.2_Parent_remove_all.pdf mac * * FRC_6_8.2.2__T8.3_Last_remove.pdf * * * -FRC_6_8.2.4_Schema_8.6__remove_obj.pdf mac * * -FRC_6_8.2.4__remove_FileName_obj.pdf mac * * -FRC_7_8.2.2_Parent_remove_obj.pdf mac * * FRC_7_8.2.2_Type_remove.pdf * * * -FRC_7_8.2.4_View_H.pdf mac * * -FRC_7_8.2.4__remove_Description_value.pdf mac * * -FRC_8.4.1_Annotations_AP_N_.pdf mac * * -FRC_8.4.1_Annotations_AP_N_R.D_.pdf mac * * -FRC_8.4.1_Annotations_AP_N_R_.pdf mac * * -FRC_8.4.1_Annotations_AS_Off_.pdf mac * * -FRC_8.4.1_Annotations_AS_Yes_.pdf mac * * -FRC_8.4.1_Annotations_Border.pdf mac * * -FRC_8.4.1_Annotations_C.pdf mac * * FRC_8.4.1_Annotations_M.pdf * * * -FRC_8.4.1_Annotations_M_text_string_.pdf mac * * FRC_8.4.1_Annotations_NM.pdf * * * -FRC_8.4.1_Annotations_P.pdf mac * * -FRC_8.4.1_Annotations_Rect.pdf mac * * -FRC_8.4.1_Annotations_Type.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_Hidden.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_Invisible.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_Locked.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_LockedContents.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_NoRotate.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_NoView.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_NoZoom.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_Print.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_ReadOnly.pdf mac * * -FRC_8.4.2_Annotation_Flags_F_ToggleNoView.pdf mac * * -FRC_8.4.3_Border_Stypes_D_different_values.pdf mac * * -FRC_8.4.3_Border_Stypes_D_remove.pdf mac * * -FRC_8.4.3_Border_Stypes_I_different_values.pdf mac * * -FRC_8.4.3_Border_Stypes_I_remove.pdf mac * * -FRC_8.4.3_Border_Stypes_S_different_values_BE_.pdf mac * * -FRC_8.4.3_Border_Stypes_S_different_values_BS_.pdf mac * * -FRC_8.4.3_Border_Stypes_S_not_exist_BS_.pdf mac * * -FRC_8.4.3_Border_Stypes_S_remove_BE_.pdf mac * * -FRC_8.4.3_Border_Stypes_S_remove_BS_.pdf mac * * -FRC_8.4.3_Border_Stypes_Type_add.pdf mac * * -FRC_8.4.3_Border_Stypes_Type_not_exist_default_.pdf mac * * -FRC_8.4.3_Border_Stypes_W_different_values.pdf mac * * -FRC_8.4.3_Border_Stypes_W_remove.pdf mac * * -FRC_8.5_Bl_Hide.pdf mac * * -FRC_8.5_Catalog_OpenAction.pdf mac * * -FRC_8.5_Catalog_WC.pdf mac * * -FRC_8.5_DP.pdf mac * * -FRC_8.5_DS.pdf mac * * -FRC_8.5_E_GoTo_D.pdf mac * * -FRC_8.5_Fo_URI_Base.pdf mac * * -FRC_8.5_Link_URL.pdf mac * * -FRC_8.5_Outline_A.pdf mac * * FRC_8.5_Page_C_SubmitForm.pdf * * * -FRC_8.5_Page_O_URI.pdf mac * * FRC_8.5_Page_PI_ResetForm_Phantom.pdf * * * -FRC_8.5_Page_PV_Named_Phantom.pdf mac * * -FRC_8.5_Screen_Fo_JavaScript.pdf mac * * -FRC_8.5_Screen_Img_D_Launch.pdf mac * * -FRC_8.5_Screen_Rendition.pdf mac * * -FRC_8.5_URI_IsMap.pdf mac * * -FRC_8.5_U_GoToR_NewWindow.pdf mac * * -FRC_8.5_U_GoToR_NewWindow_2.pdf mac * * -FRC_8.5_WP.pdf mac * * -FRC_8.5_WS.pdf mac * * -FRC_8.5_Widget_C.pdf mac * * -FRC_8.5_Widget_F.pdf mac * * FRC_8.5_Widget_F.pdf * nov8 * -FRC_8.5_Widget_K.pdf mac * * -FRC_8.5_Widget_V.pdf mac * * -FRC_8.5_X_GoToR_D.pdf mac * * -FRC_8_8.2.2_Parent_edit.pdf mac * * FRC_8_8.2.2__T8.3_Count_remove.pdf * * * -FRC_8_8.2.4_View_D.pdf mac * * -FRC_8_8.2.4__remove__Description_all.pdf mac * * -FRC_9_8.2.2_Prev_remove_value.pdf mac * * FRC_9_8.2.2__T8.3_remove_first_item.pdf * * * -FRC_9_8.2.4_View_T.pdf mac * * -FRC_9_8.2.4__remove__Description_obj.pdf mac * * action.pdf * * * action_execute_a_menu_item.pdf mac * * action_hide_show_form.pdf mac * * @@ -288,8 +92,6 @@ bookmark.pdf * * * bookmarkgetcolor.pdf mac * * bug_0_length_line.pdf mac * * bug_0_width_line.pdf mac * * -bug_434.pdf * * noxfa -bug_434.pdf win * xfa bug_440132.pdf mac * * bug_white_space.pdf mac * * calcorderindex_test.pdf * * * @@ -330,12 +132,12 @@ example_006.pdf mac,win * * example_007.pdf mac * * example_008.pdf mac * * example_009.pdf mac * * -example_010.pdf mac,win * * +example_010.pdf mac * * example_011.pdf mac * * example_012.pdf mac * * example_013.pdf mac * * example_014.pdf mac * * -example_015.pdf mac,win * * +example_015.pdf mac * * example_016.pdf mac * * example_017.pdf mac * * example_018.pdf mac * * @@ -343,7 +145,7 @@ example_019.pdf mac * * example_020.pdf mac * * example_021.pdf mac * * example_022.pdf mac * * -example_023.pdf mac,win * * +example_023.pdf mac * * example_024.pdf mac * * example_025.pdf mac * * example_026.pdf mac * * @@ -373,7 +175,7 @@ example_049.pdf mac * * example_050.pdf mac * * example_051.pdf mac * * example_052.pdf mac * * -example_053.pdf mac,win * * +example_053.pdf mac * * example_054.pdf mac * * example_055.pdf mac,win * * example_056.pdf mac * * @@ -484,29 +286,38 @@ zh_file1.pdf mac * * zh_function_list.pdf mac * * zh_shared_document.pdf mac * * -bug_679643.in * * noxfa -bug_679642.in * * noxfa +# TODO(hnakashima): These might never have been run. Go over them and fix. -### TODO(dsinclair): These need to be fixed .... -Test_DateField_locale_en_CA.pdf asan * * -Test_DateField_locale_en_GB.pdf asan * * -Test_DateField_locale_en_US.pdf asan * * -Test_DateField_locale_fr_CA.pdf asan * * -Test_DateField_locale_fr_FR.pdf asan * * -Test_DateField_locale_nl_NL.pdf asan * * -Test_DateField_locale_zh_CN.pdf asan * * -Test_DateField_locale_zh_HK.pdf asan * * -Test_PasswordField.pdf asan * * -format_custom_format.pdf asan * * +FRC_8.5_E&X.pdf * * * +FRC_8.5_O&PO_GoToE.pdf * * * +FRC_8.5_OpenAction&O_URI.pdf * * * +FRC_8.5_PC&C_GoToE_T_T.pdf * * * +FRC_8.5_PC_GoToE_T_R&P&A.pdf * * * +FRC_8.5_PO_GoToE_T_R&N.pdf * * * -# # xfa_specific -# + Choose.pdf * * * data_binding.pdf * * * Date_FormCale.pdf * * * +# TODO(npm): Add proper evt for MouseEvents. +MouseEvents_enter.pdf * * * +MouseEvents_exit.pdf * * * +Oneof3.pdf * * * Sum.pdf * * * TimeField.pdf win,linux * * Test_CheckBox.pdf * * * Test_DateField_locale_zh_HK.pdf mac,win * * +# +# JavaScript tests +# +bug_679642.in * * noxfa +bug_679643.in * * noxfa +bug_735912.in * * noxfa + +# +# Pixel tests +# +bug_492.in * nov8 * + diff --git a/testing/SUPPRESSIONS_IMAGE_DIFF b/testing/SUPPRESSIONS_IMAGE_DIFF new file mode 100644 index 0000000000000000000000000000000000000000..cdb2d66f932e0a7742c9503f6428f9ae73201645 --- /dev/null +++ b/testing/SUPPRESSIONS_IMAGE_DIFF @@ -0,0 +1,32 @@ +# Copyright 2017 The 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. +# +# List of tests to have image diff tests skipped, one per line. +# There are four space-separated columns per line +# Each column (except column 0) can contain a comma-separated list of values. +# +# Column 0: test file name +# Column 1: platform: *, win, mac, linux +# Column 2: v8 support: *, nov8, v8 +# Column 3: xfa support: *, noxfa, xfa +# +# All columns on a line on a line must match, but filenames may be repeated +# on subsequent lines to suppress more cases. Within each column, any one of +# the comma-separated values must match in order for the colum to "match". +# The filenames and keywords are case-sensitive. +# +# Try to keep the file alphabetized within each category of test. + +# +# Corpus tests +# +FRC_3.5_CF_Strf_stmf_DefaultCryptFilter.pdf * * * +FRC_3.5_EncryptMetadata_T.pdf * * * +FRC_3.5_Encrypt_is_damage.pdf * * * +FRC_3.5_Filter_PubSec_SubFilter_s5.pdf * * * +FRC_3.5_Filter_PubSec_Sub_SubFilter_s4.pdf * * * +MouseEvents.pdf * * * +Oneof.pdf * * * +bug_651304.pdf * * * +outline.pdf * * * diff --git a/testing/__init__.py b/testing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp index 79074153fbb36ad1792e9800d6afe787af908d4d..b434353bd9f9b14047a7575e061ad5dd18523cb1 100644 --- a/testing/embedder_test.cpp +++ b/testing/embedder_test.cpp @@ -6,6 +6,7 @@ #include +#include #include #include #include @@ -17,8 +18,10 @@ #include "public/fpdf_text.h" #include "public/fpdfview.h" #include "testing/gmock/include/gmock/gmock.h" +#include "testing/image_diff/image_diff_png.h" #include "testing/test_support.h" #include "testing/utils/path_service.h" +#include "third_party/base/ptr_util.h" #ifdef PDF_ENABLE_V8 #include "v8/include/v8-platform.h" @@ -27,31 +30,20 @@ namespace { -const char* g_exe_path = nullptr; - -#ifdef PDF_ENABLE_V8 -#ifdef V8_USE_EXTERNAL_STARTUP_DATA -v8::StartupData* g_v8_natives = nullptr; -v8::StartupData* g_v8_snapshot = nullptr; -#endif // V8_USE_EXTERNAL_STARTUP_DATA -#endif // PDF_ENABLE_V8 - -FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) { - return true; -} - -void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {} - -std::string CRYPT_ToBase16(const uint8_t* digest) { - static char const zEncode[] = "0123456789abcdef"; - std::string ret; - ret.resize(32); - for (int i = 0, j = 0; i < 16; i++, j += 2) { - uint8_t a = digest[i]; - ret[j] = zEncode[(a >> 4) & 0xf]; - ret[j + 1] = zEncode[a & 0xf]; +int GetBitmapBytesPerPixel(FPDF_BITMAP bitmap) { + const int format = FPDFBitmap_GetFormat(bitmap); + switch (format) { + case FPDFBitmap_Gray: + return 1; + case FPDFBitmap_BGR: + return 3; + case FPDFBitmap_BGRx: + case FPDFBitmap_BGRA: + return 4; + default: + ASSERT(false); + return 0; } - return ret; } } // namespace @@ -65,34 +57,14 @@ EmbedderTest::EmbedderTest() loader_(nullptr), file_length_(0), file_contents_(nullptr) { - memset(&hints_, 0, sizeof(hints_)); memset(&file_access_, 0, sizeof(file_access_)); - memset(&file_avail_, 0, sizeof(file_avail_)); delegate_ = default_delegate_.get(); -#ifdef PDF_ENABLE_V8 -#ifdef V8_USE_EXTERNAL_STARTUP_DATA - if (g_v8_natives && g_v8_snapshot) { - InitializeV8ForPDFium(g_exe_path, std::string(), nullptr, nullptr, - &platform_); - } else { - g_v8_natives = new v8::StartupData; - g_v8_snapshot = new v8::StartupData; - InitializeV8ForPDFium(g_exe_path, std::string(), g_v8_natives, - g_v8_snapshot, &platform_); - } -#else - InitializeV8ForPDFium(g_exe_path, &platform_); -#endif // V8_USE_EXTERNAL_STARTUP_DATA -#endif // FPDF_ENABLE_V8 + FPDF_FILEWRITE::version = 1; + FPDF_FILEWRITE::WriteBlock = WriteBlockCallback; } -EmbedderTest::~EmbedderTest() { -#ifdef PDF_ENABLE_V8 - v8::V8::ShutdownPlatform(); - delete platform_; -#endif // PDF_ENABLE_V8 -} +EmbedderTest::~EmbedderTest() {} void EmbedderTest::SetUp() { FPDF_LIBRARY_CONFIG config; @@ -107,6 +79,8 @@ void EmbedderTest::SetUp() { info->version = 1; info->FSDK_UnSupport_Handler = UnsupportedHandlerTrampoline; FSDK_SetUnSpObjProcessHandler(info); + + m_SavedDocument = nullptr; } void EmbedderTest::TearDown() { @@ -118,7 +92,6 @@ void EmbedderTest::TearDown() { FPDFAvail_Destroy(avail_); FPDF_DestroyLibrary(); - delete loader_; } @@ -127,13 +100,26 @@ bool EmbedderTest::CreateEmptyDocument() { if (!document_) return false; - SetupFormFillEnvironment(); + form_handle_ = SetupFormFillEnvironment(document_); return true; } -bool EmbedderTest::OpenDocument(const std::string& filename, - const char* password, - bool must_linearize) { +bool EmbedderTest::OpenDocument(const std::string& filename) { + return OpenDocumentWithOptions(filename, nullptr, false); +} + +bool EmbedderTest::OpenDocumentLinearized(const std::string& filename) { + return OpenDocumentWithOptions(filename, nullptr, true); +} + +bool EmbedderTest::OpenDocumentWithPassword(const std::string& filename, + const char* password) { + return OpenDocumentWithOptions(filename, password, false); +} + +bool EmbedderTest::OpenDocumentWithOptions(const std::string& filename, + const char* password, + bool must_linearize) { std::string file_path; if (!PathService::GetTestFilePath(filename, &file_path)) return false; @@ -146,69 +132,81 @@ bool EmbedderTest::OpenDocument(const std::string& filename, file_access_.m_FileLen = static_cast(file_length_); file_access_.m_GetBlock = TestLoader::GetBlock; file_access_.m_Param = loader_; + fake_file_access_ = pdfium::MakeUnique(&file_access_); + return OpenDocumentHelper(password, must_linearize, fake_file_access_.get(), + &document_, &avail_, &form_handle_); +} - file_avail_.version = 1; - file_avail_.IsDataAvail = Is_Data_Avail; - - hints_.version = 1; - hints_.AddSegment = Add_Segment; - - avail_ = FPDFAvail_Create(&file_avail_, &file_access_); - - if (FPDFAvail_IsLinearized(avail_) == PDF_LINEARIZED) { - document_ = FPDFAvail_GetDocument(avail_, password); - if (!document_) { - return false; - } +bool EmbedderTest::OpenDocumentHelper(const char* password, + bool must_linearize, + FakeFileAccess* network_simulator, + FPDF_DOCUMENT* document, + FPDF_AVAIL* avail, + FPDF_FORMHANDLE* form_handle) { + network_simulator->AddSegment(0, 1024); + network_simulator->SetRequestedDataAvailable(); + *avail = FPDFAvail_Create(network_simulator->GetFileAvail(), + network_simulator->GetFileAccess()); + if (FPDFAvail_IsLinearized(*avail) == PDF_LINEARIZED) { int32_t nRet = PDF_DATA_NOTAVAIL; while (nRet == PDF_DATA_NOTAVAIL) { - nRet = FPDFAvail_IsDocAvail(avail_, &hints_); + network_simulator->SetRequestedDataAvailable(); + nRet = + FPDFAvail_IsDocAvail(*avail, network_simulator->GetDownloadHints()); } - if (nRet == PDF_DATA_ERROR) { + if (nRet == PDF_DATA_ERROR) return false; - } - nRet = FPDFAvail_IsFormAvail(avail_, &hints_); - if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL) { + + *document = FPDFAvail_GetDocument(*avail, password); + if (!*document) return false; + + nRet = PDF_DATA_NOTAVAIL; + while (nRet == PDF_DATA_NOTAVAIL) { + network_simulator->SetRequestedDataAvailable(); + nRet = + FPDFAvail_IsFormAvail(*avail, network_simulator->GetDownloadHints()); } - int page_count = FPDF_GetPageCount(document_); + if (nRet == PDF_FORM_ERROR) + return false; + + int page_count = FPDF_GetPageCount(*document); for (int i = 0; i < page_count; ++i) { nRet = PDF_DATA_NOTAVAIL; while (nRet == PDF_DATA_NOTAVAIL) { - nRet = FPDFAvail_IsPageAvail(avail_, i, &hints_); + network_simulator->SetRequestedDataAvailable(); + nRet = FPDFAvail_IsPageAvail(*avail, i, + network_simulator->GetDownloadHints()); } - if (nRet == PDF_DATA_ERROR) { + + if (nRet == PDF_DATA_ERROR) return false; - } } } else { - if (must_linearize) { + if (must_linearize) return false; - } - document_ = FPDF_LoadCustomDocument(&file_access_, password); - if (!document_) { + network_simulator->SetWholeFileAvailable(); + *document = + FPDF_LoadCustomDocument(network_simulator->GetFileAccess(), password); + if (!*document) return false; - } } - + *form_handle = SetupFormFillEnvironment(*document); #ifdef PDF_ENABLE_XFA - int docType = DOCTYPE_PDF; - if (FPDF_HasXFAField(document_, &docType)) { - if (docType != DOCTYPE_PDF) - (void)FPDF_LoadXFA(document_); - } + int doc_type = FPDF_GetFormType(*document); + if (doc_type == FORMTYPE_XFA_FULL || doc_type == FORMTYPE_XFA_FOREGROUND) + FPDF_LoadXFA(*document); #endif // PDF_ENABLE_XFA - - (void)FPDF_GetDocPermissions(document_); - SetupFormFillEnvironment(); + (void)FPDF_GetDocPermissions(*document); return true; } -void EmbedderTest::SetupFormFillEnvironment() { +FPDF_FORMHANDLE EmbedderTest::SetupFormFillEnvironment(FPDF_DOCUMENT doc) { IPDF_JSPLATFORM* platform = static_cast(this); - memset(platform, 0, sizeof(IPDF_JSPLATFORM)); + memset(platform, '\0', sizeof(IPDF_JSPLATFORM)); platform->version = 2; platform->app_alert = AlertTrampoline; + platform->m_isolate = external_isolate_; FPDF_FORMFILLINFO* formfillinfo = static_cast(this); memset(formfillinfo, 0, sizeof(FPDF_FORMFILLINFO)); @@ -221,41 +219,46 @@ void EmbedderTest::SetupFormFillEnvironment() { formfillinfo->FFI_KillTimer = KillTimerTrampoline; formfillinfo->FFI_GetPage = GetPageTrampoline; formfillinfo->m_pJsPlatform = platform; - - form_handle_ = FPDFDOC_InitFormFillEnvironment(document_, formfillinfo); - FPDF_SetFormFieldHighlightColor(form_handle_, 0, 0xFFE4DD); - FPDF_SetFormFieldHighlightAlpha(form_handle_, 100); + FPDF_FORMHANDLE form_handle = + FPDFDOC_InitFormFillEnvironment(doc, formfillinfo); + FPDF_SetFormFieldHighlightColor(form_handle, FPDF_FORMFIELD_UNKNOWN, + 0xFFE4DD); + FPDF_SetFormFieldHighlightAlpha(form_handle, 100); + return form_handle; } void EmbedderTest::DoOpenActions() { + ASSERT(form_handle_); FORM_DoDocumentJSAction(form_handle_); FORM_DoDocumentOpenAction(form_handle_); } int EmbedderTest::GetFirstPageNum() { int first_page = FPDFAvail_GetFirstPageNum(document_); - (void)FPDFAvail_IsPageAvail(avail_, first_page, &hints_); + (void)FPDFAvail_IsPageAvail(avail_, first_page, + fake_file_access_->GetDownloadHints()); return first_page; } int EmbedderTest::GetPageCount() { int page_count = FPDF_GetPageCount(document_); - for (int i = 0; i < page_count; ++i) { - (void)FPDFAvail_IsPageAvail(avail_, i, &hints_); - } + for (int i = 0; i < page_count; ++i) + (void)FPDFAvail_IsPageAvail(avail_, i, + fake_file_access_->GetDownloadHints()); return page_count; } FPDF_PAGE EmbedderTest::LoadPage(int page_number) { + ASSERT(form_handle_); // First check whether it is loaded already. auto it = page_map_.find(page_number); if (it != page_map_.end()) return it->second; FPDF_PAGE page = FPDF_LoadPage(document_, page_number); - if (!page) { + if (!page) return nullptr; - } + FORM_OnAfterLoadPage(page, form_handle_); FORM_DoPageAAction(page, form_handle_, FPDFPAGE_AACTION_OPEN); // Cache the page. @@ -265,18 +268,25 @@ FPDF_PAGE EmbedderTest::LoadPage(int page_number) { } FPDF_BITMAP EmbedderTest::RenderPage(FPDF_PAGE page) { + return RenderPageWithFlags(page, form_handle_, 0); +} + +FPDF_BITMAP EmbedderTest::RenderPageWithFlags(FPDF_PAGE page, + FPDF_FORMHANDLE handle, + int flags) { int width = static_cast(FPDF_GetPageWidth(page)); int height = static_cast(FPDF_GetPageHeight(page)); int alpha = FPDFPage_HasTransparency(page) ? 1 : 0; FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, alpha); FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF; FPDFBitmap_FillRect(bitmap, 0, 0, width, height, fill_color); - FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0); - FPDF_FFLDraw(form_handle_, bitmap, page, 0, 0, width, height, 0, 0); + FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, flags); + FPDF_FFLDraw(handle, bitmap, page, 0, 0, width, height, 0, flags); return bitmap; } void EmbedderTest::UnloadPage(FPDF_PAGE page) { + ASSERT(form_handle_); FORM_DoPageAAction(page, form_handle_, FPDFPAGE_AACTION_CLOSE); FORM_OnBeforeClosePage(page, form_handle_); FPDF_ClosePage(page); @@ -289,6 +299,77 @@ void EmbedderTest::UnloadPage(FPDF_PAGE page) { page_reverse_map_.erase(it); } +FPDF_DOCUMENT EmbedderTest::OpenSavedDocument(const char* password) { + memset(&saved_file_access_, 0, sizeof(saved_file_access_)); + saved_file_access_.m_FileLen = m_String.size(); + saved_file_access_.m_GetBlock = GetBlockFromString; + saved_file_access_.m_Param = &m_String; + + saved_fake_file_access_ = + pdfium::MakeUnique(&saved_file_access_); + + EXPECT_TRUE(OpenDocumentHelper(password, false, saved_fake_file_access_.get(), + &m_SavedDocument, &m_SavedAvail, + &m_SavedForm)); + return m_SavedDocument; +} + +void EmbedderTest::CloseSavedDocument() { + ASSERT(m_SavedDocument); + + FPDFDOC_ExitFormFillEnvironment(m_SavedForm); + FPDF_CloseDocument(m_SavedDocument); + FPDFAvail_Destroy(m_SavedAvail); + + m_SavedForm = nullptr; + m_SavedDocument = nullptr; + m_SavedAvail = nullptr; +} + +FPDF_PAGE EmbedderTest::LoadSavedPage(int page_number) { + ASSERT(m_SavedDocument); + + EXPECT_LT(page_number, FPDF_GetPageCount(m_SavedDocument)); + FPDF_PAGE page = FPDF_LoadPage(m_SavedDocument, page_number); + + ASSERT(page); + return page; +} + +FPDF_BITMAP EmbedderTest::RenderSavedPage(FPDF_PAGE page) { + return RenderPageWithFlags(page, m_SavedForm, 0); +} + +void EmbedderTest::CloseSavedPage(FPDF_PAGE page) { + ASSERT(page); + FPDF_ClosePage(page); +} + +void EmbedderTest::VerifySavedRendering(FPDF_PAGE page, + int width, + int height, + const char* md5) { + ASSERT(m_SavedDocument); + ASSERT(page); + + FPDF_BITMAP new_bitmap = RenderPageWithFlags(page, m_SavedForm, FPDF_ANNOT); + CompareBitmap(new_bitmap, width, height, md5); + FPDFBitmap_Destroy(new_bitmap); +} + +void EmbedderTest::VerifySavedDocument(int width, int height, const char* md5) { + OpenSavedDocument(); + FPDF_PAGE page = LoadSavedPage(0); + VerifySavedRendering(page, width, height, md5); + CloseSavedPage(page); + CloseSavedDocument(); +} + +void EmbedderTest::SetWholeFileAvailable() { + ASSERT(fake_file_access_); + fake_file_access_->SetWholeFileAvailable(); +} + FPDF_PAGE EmbedderTest::Delegate::GetPage(FPDF_FORMFILLINFO* info, FPDF_DOCUMENT document, int page_index) { @@ -336,6 +417,43 @@ FPDF_PAGE EmbedderTest::GetPageTrampoline(FPDF_FORMFILLINFO* info, page_index); } +// static +std::string EmbedderTest::HashBitmap(FPDF_BITMAP bitmap) { + uint8_t digest[16]; + CRYPT_MD5Generate(static_cast(FPDFBitmap_GetBuffer(bitmap)), + FPDFBitmap_GetWidth(bitmap) * + GetBitmapBytesPerPixel(bitmap) * + FPDFBitmap_GetHeight(bitmap), + digest); + return CryptToBase16(digest); +} + +#ifndef NDEBUG +// static +void EmbedderTest::WriteBitmapToPng(FPDF_BITMAP bitmap, + const std::string& filename) { + const int stride = FPDFBitmap_GetStride(bitmap); + const int width = FPDFBitmap_GetWidth(bitmap); + const int height = FPDFBitmap_GetHeight(bitmap); + const auto* buffer = + static_cast(FPDFBitmap_GetBuffer(bitmap)); + + std::vector png_encoding; + bool encoded = image_diff_png::EncodeBGRAPNG(buffer, width, height, stride, + false, &png_encoding); + + ASSERT_TRUE(encoded); + ASSERT_LT(filename.size(), 256u); + + std::ofstream png_file; + png_file.open(filename, std::ios_base::out | std::ios_base::binary); + png_file.write(reinterpret_cast(&png_encoding.front()), + png_encoding.size()); + ASSERT_TRUE(png_file.good()); + png_file.close(); +} +#endif + // static void EmbedderTest::CompareBitmap(FPDF_BITMAP bitmap, int expected_width, @@ -343,34 +461,41 @@ void EmbedderTest::CompareBitmap(FPDF_BITMAP bitmap, const char* expected_md5sum) { ASSERT_EQ(expected_width, FPDFBitmap_GetWidth(bitmap)); ASSERT_EQ(expected_height, FPDFBitmap_GetHeight(bitmap)); - const int expected_stride = expected_width * 4; + + // The expected stride is calculated using the same formula as in + // CFX_DIBitmap::CalculatePitchAndSize(), which sets the bitmap stride. + const int expected_stride = + (expected_width * GetBitmapBytesPerPixel(bitmap) * 8 + 31) / 32 * 4; ASSERT_EQ(expected_stride, FPDFBitmap_GetStride(bitmap)); if (!expected_md5sum) return; - uint8_t digest[16]; - CRYPT_MD5Generate(static_cast(FPDFBitmap_GetBuffer(bitmap)), - expected_stride * expected_height, digest); - EXPECT_EQ(expected_md5sum, CRYPT_ToBase16(digest)); + EXPECT_EQ(expected_md5sum, HashBitmap(bitmap)); } -// Can't use gtest-provided main since we need to stash the path to the -// executable in order to find the external V8 binary data files. -int main(int argc, char** argv) { - g_exe_path = argv[0]; - testing::InitGoogleTest(&argc, argv); - testing::InitGoogleMock(&argc, argv); - int ret_val = RUN_ALL_TESTS(); - -#ifdef PDF_ENABLE_V8 -#ifdef V8_USE_EXTERNAL_STARTUP_DATA - if (g_v8_natives) - free(const_cast(g_v8_natives->data)); - if (g_v8_snapshot) - free(const_cast(g_v8_snapshot->data)); -#endif // V8_USE_EXTERNAL_STARTUP_DATA -#endif // PDF_ENABLE_V8 +// static +int EmbedderTest::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite, + const void* data, + unsigned long size) { + EmbedderTest* pThis = static_cast(pFileWrite); + pThis->m_String.append(static_cast(data), size); + return 1; +} - return ret_val; +// static +int EmbedderTest::GetBlockFromString(void* param, + unsigned long pos, + unsigned char* buf, + unsigned long size) { + std::string* new_file = static_cast(param); + if (!new_file || pos + size < pos) + return 0; + + unsigned long file_size = new_file->size(); + if (pos + size > file_size) + return 0; + + memcpy(buf, new_file->data() + pos, size); + return 1; } diff --git a/testing/embedder_test.h b/testing/embedder_test.h index cc0caec8f63b32c4b968a52abba61c4ada1068c5..98432e3e542d521c2296cb6642eb91ff51649268 100644 --- a/testing/embedder_test.h +++ b/testing/embedder_test.h @@ -12,7 +12,9 @@ #include "public/fpdf_dataavail.h" #include "public/fpdf_ext.h" #include "public/fpdf_formfill.h" +#include "public/fpdf_save.h" #include "public/fpdfview.h" +#include "testing/fake_file_access.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" @@ -27,7 +29,8 @@ class TestLoader; class EmbedderTest : public ::testing::Test, public UNSUPPORT_INFO, public IPDF_JSPLATFORM, - public FPDF_FORMFILLINFO { + public FPDF_FORMFILLINFO, + public FPDF_FILEWRITE { public: class Delegate { public: @@ -78,32 +81,64 @@ class EmbedderTest : public ::testing::Test, // Create an empty document, and its form fill environment. Returns true // on success or false on failure. - virtual bool CreateEmptyDocument(); + bool CreateEmptyDocument(); // Open the document specified by |filename|, and create its form fill // environment, or return false on failure. // The filename is relative to the test data directory where we store all the // test files. - virtual bool OpenDocument(const std::string& filename, - const char* password = nullptr, - bool must_linearize = false); + // |password| can be nullptr if there is none. + virtual bool OpenDocumentWithOptions(const std::string& filename, + const char* password, + bool must_linearize); + + // Variants provided for convenience. + bool OpenDocument(const std::string& filename); + bool OpenDocumentLinearized(const std::string& filename); + bool OpenDocumentWithPassword(const std::string& filename, + const char* password); // Perform JavaScript actions that are to run at document open time. - virtual void DoOpenActions(); + void DoOpenActions(); // Determine the page numbers present in the document. - virtual int GetFirstPageNum(); - virtual int GetPageCount(); + int GetFirstPageNum(); + int GetPageCount(); // Load a specific page of the open document. - virtual FPDF_PAGE LoadPage(int page_number); + FPDF_PAGE LoadPage(int page_number); // Convert a loaded page into a bitmap. - virtual FPDF_BITMAP RenderPage(FPDF_PAGE page); + FPDF_BITMAP RenderPage(FPDF_PAGE page); + + // Convert a loaded page into a bitmap with page rendering flags specified. + // See public/fpdfview.h for a list of page rendering flags. + FPDF_BITMAP RenderPageWithFlags(FPDF_PAGE page, + FPDF_FORMHANDLE handle, + int flags); // Relese the resources obtained from LoadPage(). Further use of |page| // is prohibited after this call is made. - virtual void UnloadPage(FPDF_PAGE page); + void UnloadPage(FPDF_PAGE page); + + protected: + bool OpenDocumentHelper(const char* password, + bool must_linearize, + FakeFileAccess* network_simulator, + FPDF_DOCUMENT* document, + FPDF_AVAIL* avail, + FPDF_FORMHANDLE* form_handle); + + FPDF_FORMHANDLE SetupFormFillEnvironment(FPDF_DOCUMENT doc); + + // Return the hash of |bitmap|. + static std::string HashBitmap(FPDF_BITMAP bitmap); + +#ifndef NDEBUG + // For debugging purposes. + // Write |bitmap| to a png file. + static void WriteBitmapToPng(FPDF_BITMAP bitmap, const std::string& filename); +#endif // Check |bitmap| to make sure it has the right dimensions and content. static void CompareBitmap(FPDF_BITMAP bitmap, @@ -111,26 +146,46 @@ class EmbedderTest : public ::testing::Test, int expected_height, const char* expected_md5sum); - protected: - void SetupFormFillEnvironment(); + void ClearString() { m_String.clear(); } + const std::string& GetString() const { return m_String; } + + static int GetBlockFromString(void* param, + unsigned long pos, + unsigned char* buf, + unsigned long size); + + FPDF_DOCUMENT OpenSavedDocument(const char* password = nullptr); + void CloseSavedDocument(); + FPDF_PAGE LoadSavedPage(int page_number); + FPDF_BITMAP RenderSavedPage(FPDF_PAGE page); + void CloseSavedPage(FPDF_PAGE page); + void VerifySavedRendering(FPDF_PAGE page, + int width, + int height, + const char* md5); + void VerifySavedDocument(int width, int height, const char* md5); + + void SetWholeFileAvailable(); Delegate* delegate_; std::unique_ptr default_delegate_; FPDF_DOCUMENT document_; FPDF_FORMHANDLE form_handle_; FPDF_AVAIL avail_; - FX_DOWNLOADHINTS hints_; - FPDF_FILEACCESS file_access_; - FX_FILEAVAIL file_avail_; -#ifdef PDF_ENABLE_V8 - v8::Platform* platform_; -#endif // PDF_ENABLE_V8 + FPDF_FILEACCESS file_access_; // must outlive avail_. void* external_isolate_; TestLoader* loader_; size_t file_length_; std::unique_ptr file_contents_; std::map page_map_; std::map page_reverse_map_; + FPDF_DOCUMENT m_SavedDocument; + FPDF_FORMHANDLE m_SavedForm; + FPDF_AVAIL m_SavedAvail; + FPDF_FILEACCESS saved_file_access_; // must outlive m_SavedAvail. + std::unique_ptr fake_file_access_; // must outlive avail_. + std::unique_ptr + saved_fake_file_access_; // must outlive m_SavedAvail. private: static void UnsupportedHandlerTrampoline(UNSUPPORT_INFO*, int type); @@ -146,6 +201,11 @@ class EmbedderTest : public ::testing::Test, static FPDF_PAGE GetPageTrampoline(FPDF_FORMFILLINFO* info, FPDF_DOCUMENT document, int page_index); + static int WriteBlockCallback(FPDF_FILEWRITE* pFileWrite, + const void* data, + unsigned long size); + + std::string m_String; }; #endif // TESTING_EMBEDDER_TEST_H_ diff --git a/testing/embedder_test_main.cpp b/testing/embedder_test_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ade6118e64fc8376258b50790929d22c7d6d1158 --- /dev/null +++ b/testing/embedder_test_main.cpp @@ -0,0 +1,94 @@ +// Copyright 2018 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. + +#include + +#include "core/fxcrt/fx_memory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +#ifdef PDF_ENABLE_V8 +#include "v8/include/v8-platform.h" +#include "v8/include/v8.h" +#endif // PDF_ENABLE_v8 + +namespace { + +const char* g_exe_path = nullptr; + +#ifdef PDF_ENABLE_V8 +#ifdef V8_USE_EXTERNAL_STARTUP_DATA +v8::StartupData* g_v8_natives = nullptr; +v8::StartupData* g_v8_snapshot = nullptr; +#endif // V8_USE_EXTERNAL_STARTUP_DATA +#endif // PDF_ENABLE_V8 + +// The loading time of the CFGAS_FontMgr is linear in the number of times it is +// loaded. So, if a test suite has a lot of tests that need a font manager they +// can end up executing very, very slowly. +class Environment : public testing::Environment { + public: + void SetUp() override { +#ifdef PDF_ENABLE_V8 +#ifdef V8_USE_EXTERNAL_STARTUP_DATA + if (g_v8_natives && g_v8_snapshot) { + InitializeV8ForPDFium(g_exe_path, std::string(), nullptr, nullptr, + &platform_); + } else { + g_v8_natives = new v8::StartupData; + g_v8_snapshot = new v8::StartupData; + InitializeV8ForPDFium(g_exe_path, std::string(), g_v8_natives, + g_v8_snapshot, &platform_); + } +#else + InitializeV8ForPDFium(g_exe_path, &platform_); +#endif // V8_USE_EXTERNAL_STARTUP_DATA +#endif // FPDF_ENABLE_V8 + } + + void TearDown() override { +#ifdef PDF_ENABLE_V8 + v8::V8::ShutdownPlatform(); + delete platform_; +#endif // PDF_ENABLE_V8 + } + + private: +#ifdef PDF_ENABLE_V8 + v8::Platform* platform_; +#endif // PDF_ENABLE_V8 +}; + +Environment* env_ = nullptr; + +} // namespace + +// Can't use gtest-provided main since we need to stash the path to the +// executable in order to find the external V8 binary data files. +int main(int argc, char** argv) { + g_exe_path = argv[0]; + + FXMEM_InitializePartitionAlloc(); + + env_ = new Environment(); + // The env will be deleted by gtest. + AddGlobalTestEnvironment(env_); + + testing::InitGoogleTest(&argc, argv); + testing::InitGoogleMock(&argc, argv); + + int ret_val = RUN_ALL_TESTS(); + +#ifdef PDF_ENABLE_V8 +#ifdef V8_USE_EXTERNAL_STARTUP_DATA + if (g_v8_natives) + free(const_cast(g_v8_natives->data)); + if (g_v8_snapshot) + free(const_cast(g_v8_snapshot->data)); +#endif // V8_USE_EXTERNAL_STARTUP_DATA +#endif // PDF_ENABLE_V8 + + return ret_val; +} diff --git a/testing/fake_file_access.cpp b/testing/fake_file_access.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c69f278102d905c16e96dfcb28a3b34c0e3e9268 --- /dev/null +++ b/testing/fake_file_access.cpp @@ -0,0 +1,115 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/fake_file_access.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_system.h" +#include "third_party/base/ptr_util.h" + +namespace { + +class FileAccessWrapper : public FPDF_FILEACCESS { + public: + explicit FileAccessWrapper(FakeFileAccess* simulator) + : simulator_(simulator) { + m_FileLen = simulator_->GetFileSize(); + m_GetBlock = &GetBlockImpl; + m_Param = this; + } + + static int GetBlockImpl(void* param, + unsigned long position, + unsigned char* pBuf, + unsigned long size) { + return static_cast(param)->simulator_->GetBlock( + position, pBuf, size); + } + + private: + fxcrt::UnownedPtr simulator_; +}; + +class FileAvailImpl : public FX_FILEAVAIL { + public: + explicit FileAvailImpl(FakeFileAccess* simulator) : simulator_(simulator) { + version = 1; + IsDataAvail = &IsDataAvailImpl; + } + + static FPDF_BOOL IsDataAvailImpl(FX_FILEAVAIL* pThis, + size_t offset, + size_t size) { + return static_cast(pThis)->simulator_->IsDataAvail(offset, + size); + } + + private: + fxcrt::UnownedPtr simulator_; +}; + +class DownloadHintsImpl : public FX_DOWNLOADHINTS { + public: + explicit DownloadHintsImpl(FakeFileAccess* simulator) + : simulator_(simulator) { + version = 1; + AddSegment = &AddSegmentImpl; + } + + static void AddSegmentImpl(FX_DOWNLOADHINTS* pThis, + size_t offset, + size_t size) { + return static_cast(pThis)->simulator_->AddSegment( + offset, size); + } + + private: + fxcrt::UnownedPtr simulator_; +}; + +} // namespace + +FakeFileAccess::FakeFileAccess(FPDF_FILEACCESS* file_access) + : file_access_(file_access), + file_access_wrapper_(pdfium::MakeUnique(this)), + file_avail_(pdfium::MakeUnique(this)), + download_hints_(pdfium::MakeUnique(this)) { + ASSERT(file_access_); +} + +FakeFileAccess::~FakeFileAccess() {} + +FPDF_BOOL FakeFileAccess::IsDataAvail(size_t offset, size_t size) const { + return available_data_.Contains(RangeSet::Range(offset, offset + size)); +} + +void FakeFileAccess::AddSegment(size_t offset, size_t size) { + requested_data_.Union(RangeSet::Range(offset, offset + size)); +} + +unsigned long FakeFileAccess::GetFileSize() { + return file_access_->m_FileLen; +} + +int FakeFileAccess::GetBlock(unsigned long position, + unsigned char* pBuf, + unsigned long size) { + if (!IsDataAvail(static_cast(position), static_cast(size))) + return false; + return file_access_->m_GetBlock(file_access_->m_Param, position, pBuf, size); +} + +void FakeFileAccess::SetRequestedDataAvailable() { + available_data_.Union(requested_data_); + requested_data_.Clear(); +} + +void FakeFileAccess::SetWholeFileAvailable() { + available_data_.Union(RangeSet::Range(0, static_cast(GetFileSize()))); + requested_data_.Clear(); +} diff --git a/testing/fake_file_access.h b/testing/fake_file_access.h new file mode 100644 index 0000000000000000000000000000000000000000..1328b16392082c65556983081c9a063c0993d1ee --- /dev/null +++ b/testing/fake_file_access.h @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TESTING_FAKE_FILE_ACCESS_H_ +#define TESTING_FAKE_FILE_ACCESS_H_ + +#include + +#include "core/fxcrt/unowned_ptr.h" +#include "public/fpdf_dataavail.h" +#include "public/fpdfview.h" +#include "testing/range_set.h" + +class FakeFileAccess { + public: + explicit FakeFileAccess(FPDF_FILEACCESS* file_access); + ~FakeFileAccess(); + + FPDF_FILEACCESS* GetFileAccess() const { return file_access_wrapper_.get(); } + FX_FILEAVAIL* GetFileAvail() const { return file_avail_.get(); } + FX_DOWNLOADHINTS* GetDownloadHints() const { return download_hints_.get(); } + + FPDF_BOOL IsDataAvail(size_t offset, size_t size) const; + void AddSegment(size_t offset, size_t size); + + unsigned long GetFileSize(); + + int GetBlock(unsigned long position, unsigned char* pBuf, unsigned long size); + void SetRequestedDataAvailable(); + void SetWholeFileAvailable(); + + private: + fxcrt::UnownedPtr file_access_; + std::unique_ptr file_access_wrapper_; + std::unique_ptr file_avail_; + std::unique_ptr download_hints_; + RangeSet available_data_; + RangeSet requested_data_; +}; + +#endif // TESTING_FAKE_FILE_ACCESS_H_ diff --git a/testing/fx_string_testhelpers.cpp b/testing/fx_string_testhelpers.cpp index 934dd680e40f751edefc8012484fca3476bf032b..443cc89ed17b9003f776046fc7ccf23ad7d4f692 100644 --- a/testing/fx_string_testhelpers.cpp +++ b/testing/fx_string_testhelpers.cpp @@ -6,43 +6,13 @@ #include #include - -namespace { - -template -std::ostream& output_string(std::ostream& out, const T& str) { - out << std::hex << std::setfill('0') << '"'; - // This function is used for FX strings whose length is defined as int. - for (int i = 0; i < str.GetLength(); ++i) { - unsigned int c = str.GetAt(i); - if (c >= 0x20 && c < 0x7F) { - out << static_cast(c); - } else if (sizeof(typename T::CharType) == 1) { - out << "\\x" << std::setw(2) << c << std::setw(0); - } else if (c < 0x10000) { - out << "\\u" << std::setw(4) << c << std::setw(0); - } else { - out << ""; - } - } - out << '"' << std::dec << std::setfill(' '); - return out; -} - -} // namespace - -std::ostream& operator<<(std::ostream& out, const CFX_ByteStringC& str) { - return output_string(out, str); -} - -std::ostream& operator<<(std::ostream& out, const CFX_ByteString& str) { - return output_string(out, str); -} - -std::ostream& operator<<(std::ostream& out, const CFX_WideStringC& str) { - return output_string(out, str); -} - -std::ostream& operator<<(std::ostream& out, const CFX_WideString& str) { - return output_string(out, str); +#include + +std::ostream& operator<<(std::ostream& os, const CFX_DateTime& dt) { + os << dt.GetYear() << "-" << std::to_string(dt.GetMonth()) << "-" + << std::to_string(dt.GetDay()) << " " << std::to_string(dt.GetHour()) + << ":" << std::to_string(dt.GetMinute()) << ":" + << std::to_string(dt.GetSecond()) << "." + << std::to_string(dt.GetMillisecond()); + return os; } diff --git a/testing/fx_string_testhelpers.h b/testing/fx_string_testhelpers.h index 82552d7227418b6d3e1ecd377c6c604ed94e4d2c..5a269a3cf65f50a568ee0db57af7145741756327 100644 --- a/testing/fx_string_testhelpers.h +++ b/testing/fx_string_testhelpers.h @@ -7,12 +7,59 @@ #include -#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/cfx_datetime.h" +#include "core/fxcrt/fx_stream.h" -// Output stream operator so GTEST macros work with FX strings. -std::ostream& operator<<(std::ostream& out, const CFX_ByteStringC& str); -std::ostream& operator<<(std::ostream& out, const CFX_ByteString& str); -std::ostream& operator<<(std::ostream& out, const CFX_WideStringC& str); -std::ostream& operator<<(std::ostream& out, const CFX_WideString& str); +// Output stream operator so GTEST macros work with CFX_DateTime objects. +std::ostream& operator<<(std::ostream& os, const CFX_DateTime& dt); + +class CFX_InvalidSeekableReadStream : public IFX_SeekableReadStream { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + // IFX_SeekableReadStream overrides: + bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { + return false; + } + FX_FILESIZE GetSize() override { return data_size_; } + + private: + explicit CFX_InvalidSeekableReadStream(FX_FILESIZE data_size) + : data_size_(data_size) {} + + FX_FILESIZE data_size_; +}; + +class CFX_BufferSeekableReadStream : public IFX_SeekableReadStream { + public: + template + friend RetainPtr pdfium::MakeRetain(Args&&... args); + + // IFX_SeekableReadStream: + bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { + if (offset < 0 || static_cast(offset) >= data_size_) + return false; + + if (static_cast(offset) + size > data_size_) + size = data_size_ - static_cast(offset); + if (size == 0) + return false; + + memcpy(buffer, data_ + offset, size); + return true; + } + + FX_FILESIZE GetSize() override { + return static_cast(data_size_); + } + + private: + CFX_BufferSeekableReadStream(const unsigned char* src, size_t src_size) + : data_(src), data_size_(src_size) {} + + const unsigned char* data_; + size_t data_size_; +}; #endif // TESTING_FX_STRING_TESTHELPERS_H_ diff --git a/testing/image_diff/DEPS b/testing/image_diff/DEPS new file mode 100644 index 0000000000000000000000000000000000000000..4bd2335cd7e0948f3d31c60b90828c7c7dc3a3a1 --- /dev/null +++ b/testing/image_diff/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + '+third_party/libpng16', + '+third_party/zlib', +] + diff --git a/testing/image_diff/image_diff.cpp b/testing/image_diff/image_diff.cpp new file mode 100644 index 0000000000000000000000000000000000000000..806e0c84d510eeb8dc8ed18cba35a0721b2ac802 --- /dev/null +++ b/testing/image_diff/image_diff.cpp @@ -0,0 +1,336 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file input format is based loosely on +// Tools/DumpRenderTree/ImageDiff.m + +// The exact format of this tool's output to stdout is important, to match +// what the run-webkit-tests script expects. + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "core/fxcrt/fx_memory.h" +#include "testing/image_diff/image_diff_png.h" +#include "third_party/base/logging.h" +#include "third_party/base/numerics/safe_conversions.h" + +#if defined(OS_WIN) +#include +#endif + +// Return codes used by this utility. +static const int kStatusSame = 0; +static const int kStatusDifferent = 1; +static const int kStatusError = 2; + +// Color codes. +static const uint32_t RGBA_RED = 0x000000ff; +static const uint32_t RGBA_ALPHA = 0xff000000; + +class Image { + public: + Image() : w_(0), h_(0) {} + Image(const Image& image) : w_(image.w_), h_(image.h_), data_(image.data_) {} + + bool has_image() const { return w_ > 0 && h_ > 0; } + int w() const { return w_; } + int h() const { return h_; } + const unsigned char* data() const { return &data_.front(); } + + // Creates the image from the given filename on disk, and returns true on + // success. + bool CreateFromFilename(const std::string& path) { + FILE* f = fopen(path.c_str(), "rb"); + if (!f) + return false; + + std::vector compressed; + const size_t kBufSize = 1024; + unsigned char buf[kBufSize]; + size_t num_read = 0; + while ((num_read = fread(buf, 1, kBufSize, f)) > 0) { + compressed.insert(compressed.end(), buf, buf + num_read); + } + + fclose(f); + + if (!image_diff_png::DecodePNG(compressed.data(), compressed.size(), &data_, + &w_, &h_)) { + Clear(); + return false; + } + return true; + } + + void Clear() { + w_ = h_ = 0; + data_.clear(); + } + + // Returns the RGBA value of the pixel at the given location + uint32_t pixel_at(int x, int y) const { + if (!pixel_in_bounds(x, y)) + return 0; + return *reinterpret_cast(&(data_[pixel_address(x, y)])); + } + + void set_pixel_at(int x, int y, uint32_t color) { + if (!pixel_in_bounds(x, y)) + return; + + void* addr = &data_[pixel_address(x, y)]; + *reinterpret_cast(addr) = color; + } + + private: + bool pixel_in_bounds(int x, int y) const { + return x >= 0 && x < w_ && y >= 0 && y < h_; + } + + size_t pixel_address(int x, int y) const { return (y * w_ + x) * 4; } + + // Pixel dimensions of the image. + int w_; + int h_; + + std::vector data_; +}; + +float CalculateDifferencePercentage(const Image& actual, int pixels_different) { + // Like the WebKit ImageDiff tool, we define percentage different in terms + // of the size of the 'actual' bitmap. + float total_pixels = + static_cast(actual.w()) * static_cast(actual.h()); + if (total_pixels == 0) { + // When the bitmap is empty, they are 100% different. + return 100.0f; + } + return 100.0f * pixels_different / total_pixels; +} + +void CountImageSizeMismatchAsPixelDifference(const Image& baseline, + const Image& actual, + int* pixels_different) { + int w = std::min(baseline.w(), actual.w()); + int h = std::min(baseline.h(), actual.h()); + + // Count pixels that are a difference in size as also being different. + int max_w = std::max(baseline.w(), actual.w()); + int max_h = std::max(baseline.h(), actual.h()); + // These pixels are off the right side, not including the lower right corner. + *pixels_different += (max_w - w) * h; + // These pixels are along the bottom, including the lower right corner. + *pixels_different += (max_h - h) * max_w; +} + +float PercentageDifferent(const Image& baseline, const Image& actual) { + int w = std::min(baseline.w(), actual.w()); + int h = std::min(baseline.h(), actual.h()); + + // Compute pixels different in the overlap. + int pixels_different = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + if (baseline.pixel_at(x, y) != actual.pixel_at(x, y)) + ++pixels_different; + } + } + + CountImageSizeMismatchAsPixelDifference(baseline, actual, &pixels_different); + return CalculateDifferencePercentage(actual, pixels_different); +} + +float HistogramPercentageDifferent(const Image& baseline, const Image& actual) { + // TODO(johnme): Consider using a joint histogram instead, as described in + // "Comparing Images Using Joint Histograms" by Pass & Zabih + // http://www.cs.cornell.edu/~rdz/papers/pz-jms99.pdf + + int w = std::min(baseline.w(), actual.w()); + int h = std::min(baseline.h(), actual.h()); + + // Count occurences of each RGBA pixel value of baseline in the overlap. + std::map baseline_histogram; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + // hash_map operator[] inserts a 0 (default constructor) if key not found. + ++baseline_histogram[baseline.pixel_at(x, y)]; + } + } + + // Compute pixels different in the histogram of the overlap. + int pixels_different = 0; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + uint32_t actual_rgba = actual.pixel_at(x, y); + auto it = baseline_histogram.find(actual_rgba); + if (it != baseline_histogram.end() && it->second > 0) + --it->second; + else + ++pixels_different; + } + } + + CountImageSizeMismatchAsPixelDifference(baseline, actual, &pixels_different); + return CalculateDifferencePercentage(actual, pixels_different); +} + +void PrintHelp() { + fprintf( + stderr, + "Usage:\n" + " image_diff [--histogram] \n" + " Compares two files on disk, returning 0 when they are the same;\n" + " passing \"--histogram\" additionally calculates a diff of the\n" + " RGBA value histograms (which is resistant to shifts in layout)\n" + " image_diff --diff \n" + " Compares two files on disk, outputs an image that visualizes the\n" + " difference to \n"); +} + +int CompareImages(const std::string& file1, + const std::string& file2, + bool compare_histograms) { + Image actual_image; + Image baseline_image; + + if (!actual_image.CreateFromFilename(file1)) { + fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file1.c_str()); + return kStatusError; + } + if (!baseline_image.CreateFromFilename(file2)) { + fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file2.c_str()); + return kStatusError; + } + + if (compare_histograms) { + float percent = HistogramPercentageDifferent(actual_image, baseline_image); + const char* passed = percent > 0.0 ? "failed" : "passed"; + printf("histogram diff: %01.2f%% %s\n", percent, passed); + } + + const char* const diff_name = compare_histograms ? "exact diff" : "diff"; + float percent = PercentageDifferent(actual_image, baseline_image); + const char* const passed = percent > 0.0 ? "failed" : "passed"; + printf("%s: %01.2f%% %s\n", diff_name, percent, passed); + + if (percent > 0.0) { + // failure: The WebKit version also writes the difference image to + // stdout, which seems excessive for our needs. + return kStatusDifferent; + } + // success + return kStatusSame; +} + +bool CreateImageDiff(const Image& image1, const Image& image2, Image* out) { + int w = std::min(image1.w(), image2.w()); + int h = std::min(image1.h(), image2.h()); + *out = Image(image1); + bool same = (image1.w() == image2.w()) && (image1.h() == image2.h()); + + // TODO(estade): do something with the extra pixels if the image sizes + // are different. + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + uint32_t base_pixel = image1.pixel_at(x, y); + if (base_pixel != image2.pixel_at(x, y)) { + // Set differing pixels red. + out->set_pixel_at(x, y, RGBA_RED | RGBA_ALPHA); + same = false; + } else { + // Set same pixels as faded. + uint32_t alpha = base_pixel & RGBA_ALPHA; + uint32_t new_pixel = base_pixel - ((alpha / 2) & RGBA_ALPHA); + out->set_pixel_at(x, y, new_pixel); + } + } + } + + return same; +} + +int DiffImages(const std::string& file1, + const std::string& file2, + const std::string& out_file) { + Image actual_image; + Image baseline_image; + + if (!actual_image.CreateFromFilename(file1)) { + fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file1.c_str()); + return kStatusError; + } + if (!baseline_image.CreateFromFilename(file2)) { + fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file2.c_str()); + return kStatusError; + } + + Image diff_image; + bool same = CreateImageDiff(baseline_image, actual_image, &diff_image); + if (same) + return kStatusSame; + + std::vector png_encoding; + image_diff_png::EncodeRGBAPNG(diff_image.data(), diff_image.w(), + diff_image.h(), diff_image.w() * 4, + &png_encoding); + + FILE* f = fopen(out_file.c_str(), "wb"); + if (!f) + return kStatusError; + + size_t size = png_encoding.size(); + char* ptr = reinterpret_cast(&png_encoding.front()); + if (fwrite(ptr, 1, size, f) != size) + return kStatusError; + + return kStatusDifferent; +} + +int main(int argc, const char* argv[]) { + FXMEM_InitializePartitionAlloc(); + + bool histograms = false; + bool produce_diff_image = false; + std::string filename1; + std::string filename2; + std::string diff_filename; + + int i; + for (i = 1; i < argc; ++i) { + const char* arg = argv[i]; + if (strstr(arg, "--") != arg) + break; + if (strcmp(arg, "--histogram") == 0) { + histograms = true; + } else if (strcmp(arg, "--diff") == 0) { + produce_diff_image = true; + } + } + if (i < argc) + filename1 = argv[i++]; + if (i < argc) + filename2 = argv[i++]; + if (i < argc) + diff_filename = argv[i++]; + + if (produce_diff_image) { + if (!diff_filename.empty()) { + return DiffImages(filename1, filename2, diff_filename); + } + } else if (!filename2.empty()) { + return CompareImages(filename1, filename2, histograms); + } + + PrintHelp(); + return kStatusError; +} diff --git a/testing/image_diff/image_diff_png.cpp b/testing/image_diff/image_diff_png.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48b5ae17b4282d8aaeff30952c6d080ea2e4be8a --- /dev/null +++ b/testing/image_diff/image_diff_png.cpp @@ -0,0 +1,718 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a duplicate of chromium's src/tools/imagediff/image_diff_png.cc +// that has been modified to build in a pdfium environment, which itself +// was duplicated as follows: + +// This is a duplicate of ui/gfx/codec/png_codec.cc, after removing code related +// to Skia, that we can use when running layout tests with minimal dependencies. + +#include "testing/image_diff/image_diff_png.h" + +#include +#include + +#include + +#include "third_party/base/logging.h" +#include "third_party/zlib/zlib.h" + +#ifdef USE_SYSTEM_LIBPNG +#include +#else +#include "third_party/libpng16/png.h" +#endif + +namespace image_diff_png { + +namespace { + +enum ColorFormat { + // 3 bytes per pixel (packed), in RGB order regardless of endianness. + // This is the native JPEG format. + FORMAT_RGB, + + // 3 bytes per pixel, in BGR order regardless of endianness. + FORMAT_BGR, + + // 4 bytes per pixel, in RGBA order in memory regardless of endianness. + FORMAT_RGBA, + + // 4 bytes per pixel, in BGRA order in memory regardless of endianness. + // This is the default Windows DIB order. + FORMAT_BGRA, + + // 1 byte per pixel. + FORMAT_GRAY, +}; + +// Represents a comment in the tEXt ancillary chunk of the png. +struct Comment { + std::string key; + std::string text; +}; + +// Converts BGRA->RGBA and RGBA->BGRA. +void ConvertBetweenBGRAandRGBA(const unsigned char* input, + int pixel_width, + unsigned char* output, + bool* is_opaque) { + for (int x = 0; x < pixel_width; x++) { + const unsigned char* pixel_in = &input[x * 4]; + unsigned char* pixel_out = &output[x * 4]; + pixel_out[0] = pixel_in[2]; + pixel_out[1] = pixel_in[1]; + pixel_out[2] = pixel_in[0]; + pixel_out[3] = pixel_in[3]; + } +} + +void ConvertBGRtoRGB(const unsigned char* bgr, + int pixel_width, + unsigned char* rgb, + bool* is_opaque) { + for (int x = 0; x < pixel_width; x++) { + const unsigned char* pixel_in = &bgr[x * 3]; + unsigned char* pixel_out = &rgb[x * 3]; + pixel_out[0] = pixel_in[2]; + pixel_out[1] = pixel_in[1]; + pixel_out[2] = pixel_in[0]; + } +} + +void ConvertRGBAtoRGB(const unsigned char* rgba, + int pixel_width, + unsigned char* rgb, + bool* is_opaque) { + for (int x = 0; x < pixel_width; x++) { + const unsigned char* pixel_in = &rgba[x * 4]; + unsigned char* pixel_out = &rgb[x * 3]; + pixel_out[0] = pixel_in[0]; + pixel_out[1] = pixel_in[1]; + pixel_out[2] = pixel_in[2]; + } +} + +} // namespace + +// Decoder +// +// This code is based on WebKit libpng interface (PNGImageDecoder), which is +// in turn based on the Mozilla png decoder. + +namespace { + +// Gamma constants: We assume we're on Windows which uses a gamma of 2.2. +const double kMaxGamma = 21474.83; // Maximum gamma accepted by png library. +const double kDefaultGamma = 2.2; +const double kInverseGamma = 1.0 / kDefaultGamma; + +class PngDecoderState { + public: + // Output is a vector. + PngDecoderState(ColorFormat ofmt, std::vector* o) + : output_format(ofmt), + output_channels(0), + is_opaque(true), + output(o), + row_converter(nullptr), + width(0), + height(0), + done(false) {} + + ColorFormat output_format; + int output_channels; + + // Used during the reading of an SkBitmap. Defaults to true until we see a + // pixel with anything other than an alpha of 255. + bool is_opaque; + + // An intermediary buffer for decode output. + std::vector* output; + + // Called to convert a row from the library to the correct output format. + // When NULL, no conversion is necessary. + void (*row_converter)(const unsigned char* in, + int w, + unsigned char* out, + bool* is_opaque); + + // Size of the image, set in the info callback. + int width; + int height; + + // Set to true when we've found the end of the data. + bool done; +}; + +void ConvertRGBtoRGBA(const unsigned char* rgb, + int pixel_width, + unsigned char* rgba, + bool* is_opaque) { + for (int x = 0; x < pixel_width; x++) { + const unsigned char* pixel_in = &rgb[x * 3]; + unsigned char* pixel_out = &rgba[x * 4]; + pixel_out[0] = pixel_in[0]; + pixel_out[1] = pixel_in[1]; + pixel_out[2] = pixel_in[2]; + pixel_out[3] = 0xff; + } +} + +void ConvertRGBtoBGRA(const unsigned char* rgb, + int pixel_width, + unsigned char* bgra, + bool* is_opaque) { + for (int x = 0; x < pixel_width; x++) { + const unsigned char* pixel_in = &rgb[x * 3]; + unsigned char* pixel_out = &bgra[x * 4]; + pixel_out[0] = pixel_in[2]; + pixel_out[1] = pixel_in[1]; + pixel_out[2] = pixel_in[0]; + pixel_out[3] = 0xff; + } +} + +// Called when the png header has been read. This code is based on the WebKit +// PNGImageDecoder +void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) { + PngDecoderState* state = + static_cast(png_get_progressive_ptr(png_ptr)); + + int bit_depth, color_type, interlace_type, compression_type; + int filter_type, channels; + png_uint_32 w, h; + png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, + &interlace_type, &compression_type, &filter_type); + + // Bounds check. When the image is unreasonably big, we'll error out and + // end up back at the setjmp call when we set up decoding. "Unreasonably big" + // means "big enough that w * h * 32bpp might overflow an int"; we choose this + // threshold to match WebKit and because a number of places in code assume + // that an image's size (in bytes) fits in a (signed) int. + unsigned long long total_size = + static_cast(w) * static_cast(h); + if (total_size > ((1 << 29) - 1)) + longjmp(png_jmpbuf(png_ptr), 1); + state->width = static_cast(w); + state->height = static_cast(h); + + // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. + if (color_type == PNG_COLOR_TYPE_PALETTE || + (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)) + png_set_expand(png_ptr); + + // Transparency for paletted images. + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + + // Convert 16-bit to 8-bit. + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + // Expand grayscale to RGB. + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + // Deal with gamma and keep it under our control. + double gamma; + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) { + if (gamma <= 0.0 || gamma > kMaxGamma) { + gamma = kInverseGamma; + png_set_gAMA(png_ptr, info_ptr, gamma); + } + png_set_gamma(png_ptr, kDefaultGamma, gamma); + } else { + png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma); + } + + // Tell libpng to send us rows for interlaced pngs. + if (interlace_type == PNG_INTERLACE_ADAM7) + png_set_interlace_handling(png_ptr); + + // Update our info now + png_read_update_info(png_ptr, info_ptr); + channels = png_get_channels(png_ptr, info_ptr); + + // Pick our row format converter necessary for this data. + if (channels == 3) { + switch (state->output_format) { + case FORMAT_RGB: + state->row_converter = nullptr; // no conversion necessary + state->output_channels = 3; + break; + case FORMAT_RGBA: + state->row_converter = &ConvertRGBtoRGBA; + state->output_channels = 4; + break; + case FORMAT_BGRA: + state->row_converter = &ConvertRGBtoBGRA; + state->output_channels = 4; + break; + case FORMAT_GRAY: + state->row_converter = nullptr; + state->output_channels = 1; + break; + default: + NOTREACHED(); + break; + } + } else if (channels == 4) { + switch (state->output_format) { + case FORMAT_RGB: + state->row_converter = &ConvertRGBAtoRGB; + state->output_channels = 3; + break; + case FORMAT_RGBA: + state->row_converter = nullptr; // no conversion necessary + state->output_channels = 4; + break; + case FORMAT_BGRA: + state->row_converter = &ConvertBetweenBGRAandRGBA; + state->output_channels = 4; + break; + default: + NOTREACHED(); + break; + } + } else { + NOTREACHED(); + longjmp(png_jmpbuf(png_ptr), 1); + } + + state->output->resize(state->width * state->output_channels * state->height); +} + +void DecodeRowCallback(png_struct* png_ptr, + png_byte* new_row, + png_uint_32 row_num, + int pass) { + PngDecoderState* state = + static_cast(png_get_progressive_ptr(png_ptr)); + + if (static_cast(row_num) > state->height) { + NOTREACHED(); + return; + } + + unsigned char* base = NULL; + base = &state->output->front(); + + unsigned char* dest = &base[state->width * state->output_channels * row_num]; + if (state->row_converter) + state->row_converter(new_row, state->width, dest, &state->is_opaque); + else + memcpy(dest, new_row, state->width * state->output_channels); +} + +void DecodeEndCallback(png_struct* png_ptr, png_info* info) { + PngDecoderState* state = + static_cast(png_get_progressive_ptr(png_ptr)); + + // Mark the image as complete, this will tell the Decode function that we + // have successfully found the end of the data. + state->done = true; +} + +// Automatically destroys the given read structs on destruction to make +// cleanup and error handling code cleaner. +class PngReadStructDestroyer { + public: + PngReadStructDestroyer(png_struct** ps, png_info** pi) : ps_(ps), pi_(pi) {} + ~PngReadStructDestroyer() { png_destroy_read_struct(ps_, pi_, NULL); } + + private: + png_struct** ps_; + png_info** pi_; +}; + +bool BuildPNGStruct(const unsigned char* input, + size_t input_size, + png_struct** png_ptr, + png_info** info_ptr) { + if (input_size < 8) + return false; // Input data too small to be a png + + // Have libpng check the signature, it likes the first 8 bytes. + if (png_sig_cmp(const_cast(input), 0, 8) != 0) + return false; + + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!*png_ptr) + return false; + + *info_ptr = png_create_info_struct(*png_ptr); + if (!*info_ptr) { + png_destroy_read_struct(png_ptr, NULL, NULL); + return false; + } + + return true; +} + +} // namespace + +// static +bool Decode(const unsigned char* input, + size_t input_size, + ColorFormat format, + std::vector* output, + int* w, + int* h) { + png_struct* png_ptr = NULL; + png_info* info_ptr = NULL; + if (!BuildPNGStruct(input, input_size, &png_ptr, &info_ptr)) + return false; + + PngReadStructDestroyer destroyer(&png_ptr, &info_ptr); + if (setjmp(png_jmpbuf(png_ptr))) { + // The destroyer will ensure that the structures are cleaned up in this + // case, even though we may get here as a jump from random parts of the + // PNG library called below. + return false; + } + + PngDecoderState state(format, output); + + png_set_progressive_read_fn(png_ptr, &state, &DecodeInfoCallback, + &DecodeRowCallback, &DecodeEndCallback); + png_process_data(png_ptr, info_ptr, const_cast(input), + input_size); + + if (!state.done) { + // Fed it all the data but the library didn't think we got all the data, so + // this file must be truncated. + output->clear(); + return false; + } + + *w = state.width; + *h = state.height; + return true; +} + +// Encoder +// +// This section of the code is based on nsPNGEncoder.cpp in Mozilla +// (Copyright 2005 Google Inc.) + +namespace { + +// Passed around as the io_ptr in the png structs so our callbacks know where +// to write data. +struct PngEncoderState { + explicit PngEncoderState(std::vector* o) : out(o) {} + std::vector* out; +}; + +// Called by libpng to flush its internal buffer to ours. +void EncoderWriteCallback(png_structp png, png_bytep data, png_size_t size) { + PngEncoderState* state = static_cast(png_get_io_ptr(png)); + size_t old_size = state->out->size(); + state->out->resize(old_size + size); + memcpy(&(*state->out)[old_size], data, size); +} + +void FakeFlushCallback(png_structp png) { + // We don't need to perform any flushing since we aren't doing real IO, but + // we're required to provide this function by libpng. +} + +void ConvertBGRAtoRGB(const unsigned char* bgra, + int pixel_width, + unsigned char* rgb, + bool* is_opaque) { + for (int x = 0; x < pixel_width; x++) { + const unsigned char* pixel_in = &bgra[x * 4]; + unsigned char* pixel_out = &rgb[x * 3]; + pixel_out[0] = pixel_in[2]; + pixel_out[1] = pixel_in[1]; + pixel_out[2] = pixel_in[0]; + } +} + +#ifdef PNG_TEXT_SUPPORTED + +inline char* strdup(const char* str) { +#if defined(OS_WIN) + return _strdup(str); +#else + return ::strdup(str); +#endif +} + +class CommentWriter { + public: + explicit CommentWriter(const std::vector& comments) + : comments_(comments), png_text_(new png_text[comments.size()]) { + for (size_t i = 0; i < comments.size(); ++i) + AddComment(i, comments[i]); + } + + ~CommentWriter() { + for (size_t i = 0; i < comments_.size(); ++i) { + free(png_text_[i].key); + free(png_text_[i].text); + } + delete[] png_text_; + } + + bool HasComments() { return !comments_.empty(); } + + png_text* get_png_text() { return png_text_; } + + int size() { return static_cast(comments_.size()); } + + private: + void AddComment(size_t pos, const Comment& comment) { + png_text_[pos].compression = PNG_TEXT_COMPRESSION_NONE; + // A PNG comment's key can only be 79 characters long. + if (comment.key.length() > 79) + return; + png_text_[pos].key = strdup(comment.key.substr(0, 78).c_str()); + png_text_[pos].text = strdup(comment.text.c_str()); + png_text_[pos].text_length = comment.text.length(); +#ifdef PNG_iTXt_SUPPORTED + png_text_[pos].itxt_length = 0; + png_text_[pos].lang = 0; + png_text_[pos].lang_key = 0; +#endif + } + + const std::vector comments_; + png_text* png_text_; +}; +#endif // PNG_TEXT_SUPPORTED + +// The type of functions usable for converting between pixel formats. +typedef void (*FormatConverter)(const unsigned char* in, + int w, + unsigned char* out, + bool* is_opaque); + +// libpng uses a wacky setjmp-based API, which makes the compiler nervous. +// We constrain all of the calls we make to libpng where the setjmp() is in +// place to this function. +// Returns true on success. +bool DoLibpngWrite(png_struct* png_ptr, + png_info* info_ptr, + PngEncoderState* state, + int width, + int height, + int row_byte_width, + const unsigned char* input, + int compression_level, + int png_output_color_type, + int output_color_components, + FormatConverter converter, + const std::vector& comments) { +#ifdef PNG_TEXT_SUPPORTED + CommentWriter comment_writer(comments); +#endif + unsigned char* row_buffer = NULL; + + // Make sure to not declare any locals here -- locals in the presence + // of setjmp() in C++ code makes gcc complain. + + if (setjmp(png_jmpbuf(png_ptr))) { + delete[] row_buffer; + return false; + } + + png_set_compression_level(png_ptr, compression_level); + + // Set our callback for libpng to give us the data. + png_set_write_fn(png_ptr, state, EncoderWriteCallback, FakeFlushCallback); + + png_set_IHDR(png_ptr, info_ptr, width, height, 8, png_output_color_type, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + +#ifdef PNG_TEXT_SUPPORTED + if (comment_writer.HasComments()) { + png_set_text(png_ptr, info_ptr, comment_writer.get_png_text(), + comment_writer.size()); + } +#endif + + png_write_info(png_ptr, info_ptr); + + if (!converter) { + // No conversion needed, give the data directly to libpng. + for (int y = 0; y < height; y++) { + png_write_row(png_ptr, + const_cast(&input[y * row_byte_width])); + } + } else { + // Needs conversion using a separate buffer. + row_buffer = new unsigned char[width * output_color_components]; + for (int y = 0; y < height; y++) { + converter(&input[y * row_byte_width], width, row_buffer, NULL); + png_write_row(png_ptr, row_buffer); + } + delete[] row_buffer; + } + + png_write_end(png_ptr, info_ptr); + return true; +} + +} // namespace + +// static +bool EncodeWithCompressionLevel(const unsigned char* input, + ColorFormat format, + const int width, + const int height, + int row_byte_width, + bool discard_transparency, + const std::vector& comments, + int compression_level, + std::vector* output) { + // Run to convert an input row into the output row format, NULL means no + // conversion is necessary. + FormatConverter converter = nullptr; + + int input_color_components, output_color_components; + int png_output_color_type; + switch (format) { + case FORMAT_BGR: + converter = ConvertBGRtoRGB; + + case FORMAT_RGB: + input_color_components = 3; + output_color_components = 3; + png_output_color_type = PNG_COLOR_TYPE_RGB; + discard_transparency = false; + break; + + case FORMAT_RGBA: + input_color_components = 4; + if (discard_transparency) { + output_color_components = 3; + png_output_color_type = PNG_COLOR_TYPE_RGB; + converter = ConvertRGBAtoRGB; + } else { + output_color_components = 4; + png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; + converter = nullptr; + } + break; + + case FORMAT_BGRA: + input_color_components = 4; + if (discard_transparency) { + output_color_components = 3; + png_output_color_type = PNG_COLOR_TYPE_RGB; + converter = ConvertBGRAtoRGB; + } else { + output_color_components = 4; + png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; + converter = ConvertBetweenBGRAandRGBA; + } + break; + + case FORMAT_GRAY: + input_color_components = 1; + output_color_components = 1; + png_output_color_type = PNG_COLOR_TYPE_GRAY; + discard_transparency = false; + break; + + default: + NOTREACHED(); + return false; + } + + // Row stride should be at least as long as the length of the data. + if (row_byte_width < input_color_components * width) + return false; + + png_struct* png_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + return false; + png_info* info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, NULL); + return false; + } + + PngEncoderState state(output); + bool success = + DoLibpngWrite(png_ptr, info_ptr, &state, width, height, row_byte_width, + input, compression_level, png_output_color_type, + output_color_components, converter, comments); + png_destroy_write_struct(&png_ptr, &info_ptr); + + return success; +} + +// static +bool Encode(const unsigned char* input, + ColorFormat format, + const int width, + const int height, + int row_byte_width, + bool discard_transparency, + const std::vector& comments, + std::vector* output) { + return EncodeWithCompressionLevel(input, format, width, height, + row_byte_width, discard_transparency, + comments, Z_DEFAULT_COMPRESSION, output); +} + +// Decode a PNG into an RGBA pixel array. +bool DecodePNG(const unsigned char* input, + size_t input_size, + std::vector* output, + int* width, + int* height) { + return Decode(input, input_size, FORMAT_RGBA, output, width, height); +} + +// Encode a BGR pixel array into a PNG. +bool EncodeBGRPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + std::vector* output) { + return Encode(input, FORMAT_BGR, width, height, row_byte_width, false, + std::vector(), output); +} + +// Encode an RGBA pixel array into a PNG. +bool EncodeRGBAPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + std::vector* output) { + return Encode(input, FORMAT_RGBA, width, height, row_byte_width, false, + std::vector(), output); +} + +// Encode an BGRA pixel array into a PNG. +bool EncodeBGRAPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + bool discard_transparency, + std::vector* output) { + return Encode(input, FORMAT_BGRA, width, height, row_byte_width, + discard_transparency, std::vector(), output); +} + +// Encode a grayscale pixel array into a PNG. +bool EncodeGrayPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + std::vector* output) { + return Encode(input, FORMAT_GRAY, width, height, row_byte_width, false, + std::vector(), output); +} + +} // namespace image_diff_png diff --git a/testing/image_diff/image_diff_png.h b/testing/image_diff/image_diff_png.h new file mode 100644 index 0000000000000000000000000000000000000000..b334b20453add2686ffe9fd30decbd4c2c05e1cd --- /dev/null +++ b/testing/image_diff/image_diff_png.h @@ -0,0 +1,52 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TESTING_IMAGE_DIFF_IMAGE_DIFF_PNG_H_ +#define TESTING_IMAGE_DIFF_IMAGE_DIFF_PNG_H_ + +#include // for size_t. + +#include + +namespace image_diff_png { + +// Decode a PNG into an RGBA pixel array. +bool DecodePNG(const unsigned char* input, + size_t input_size, + std::vector* output, + int* width, + int* height); + +// Encode a BGR pixel array into a PNG. +bool EncodeBGRPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + std::vector* output); + +// Encode an RGBA pixel array into a PNG. +bool EncodeRGBAPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + std::vector* output); + +// Encode an BGRA pixel array into a PNG. +bool EncodeBGRAPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + bool discard_transparency, + std::vector* output); + +// Encode a grayscale pixel array into a PNG. +bool EncodeGrayPNG(const unsigned char* input, + int width, + int height, + int row_byte_width, + std::vector* output); + +} // namespace image_diff_png + +#endif // TESTING_IMAGE_DIFF_IMAGE_DIFF_PNG_H_ diff --git a/testing/js_embedder_test.cpp b/testing/js_embedder_test.cpp index 064a96104917496a6eeb840d8eeb8c7bdd70ae5a..e9eb70d1ec36bb90d8ab1737565162c3e167a622 100644 --- a/testing/js_embedder_test.cpp +++ b/testing/js_embedder_test.cpp @@ -3,11 +3,12 @@ // found in the LICENSE file. #include "testing/js_embedder_test.h" + #include "third_party/base/ptr_util.h" JSEmbedderTest::JSEmbedderTest() - : m_pArrayBufferAllocator(new FXJS_ArrayBufferAllocator), - m_pIsolate(nullptr) {} + : m_pArrayBufferAllocator(pdfium::MakeUnique()) { +} JSEmbedderTest::~JSEmbedderTest() {} diff --git a/testing/js_embedder_test.h b/testing/js_embedder_test.h index fbec0ea5c91eca5cab7bf6b94f4c647f93e994ee..1f27dbeae66ad8151364d3637338853de0b9ca75 100644 --- a/testing/js_embedder_test.h +++ b/testing/js_embedder_test.h @@ -6,7 +6,6 @@ #define TESTING_JS_EMBEDDER_TEST_H_ #include -#include #include "fxjs/fxjs_v8.h" #include "testing/embedder_test.h" @@ -25,7 +24,7 @@ class JSEmbedderTest : public EmbedderTest { private: std::unique_ptr m_pArrayBufferAllocator; - v8::Isolate* m_pIsolate; + v8::Isolate* m_pIsolate = nullptr; std::unique_ptr m_Engine; }; diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn index 9ba8e32ba6f1e7a82a48a2bd09e4f624ebeeaf3a..20c64d9835466b7f796b57bde7ad762903efd3d8 100644 --- a/testing/libfuzzer/BUILD.gn +++ b/testing/libfuzzer/BUILD.gn @@ -21,14 +21,47 @@ config("libfuzzer_config") { } group("libfuzzer") { + testonly = true + deps = [ + ":pdf_cmap_fuzzer", + ":pdf_codec_a85_fuzzer", + ":pdf_codec_fax_fuzzer", + ":pdf_codec_icc_fuzzer", + ":pdf_codec_jbig2_fuzzer", + ":pdf_codec_rle_fuzzer", + ":pdf_font_fuzzer", + ":pdf_hint_table_fuzzer", + ":pdf_jpx_fuzzer", + ":pdf_psengine_fuzzer", + ":pdf_streamparser_fuzzer", + ] + if (pdf_enable_xfa) { + deps += [ + ":pdf_cfx_barcode_fuzzer", + ":pdf_cfx_saxreader_fuzzer", + ":pdf_codec_bmp_fuzzer", + ":pdf_codec_gif_fuzzer", + ":pdf_codec_jpeg_fuzzer", + ":pdf_codec_png_fuzzer", + ":pdf_codec_tiff_fuzzer", + ":pdf_css_fuzzer", + ":pdf_fm2js_fuzzer", + ":pdf_formcalc_fuzzer", + ":pdf_lzw_fuzzer", + ":pdf_xml_fuzzer", + ] + } } template("pdfium_fuzzer") { source_set(target_name) { - sources = invoker.sources + sources = invoker.sources + [ "pdf_fuzzer_init.cc" ] deps = [ "../..:pdfium", ] + if (defined(invoker.deps)) { + deps += invoker.deps + } testonly = true configs -= [ "//build/config/compiler:chromium_code" ] configs += [ @@ -39,6 +72,12 @@ template("pdfium_fuzzer") { } if (pdf_enable_xfa) { + pdfium_fuzzer("pdf_cfx_barcode_fuzzer") { + sources = [ + "pdf_cfx_barcode_fuzzer.cc", + ] + } + pdfium_fuzzer("pdf_cfx_saxreader_fuzzer") { sources = [ "pdf_cfx_saxreader_fuzzer.cc", @@ -92,6 +131,18 @@ if (pdf_enable_xfa) { ] } + pdfium_fuzzer("pdf_formcalc_fuzzer") { + sources = [ + "pdf_formcalc_fuzzer.cc", + ] + } + + pdfium_fuzzer("pdf_lzw_fuzzer") { + sources = [ + "pdf_lzw_fuzzer.cc", + ] + } + pdfium_fuzzer("pdf_xml_fuzzer") { sources = [ "pdf_xml_fuzzer.cc", @@ -118,6 +169,9 @@ pdfium_fuzzer("pdf_codec_fax_fuzzer") { } pdfium_fuzzer("pdf_codec_icc_fuzzer") { + deps = [ + "../../third_party/:lcms2", + ] sources = [ "pdf_codec_icc_fuzzer.cc", ] @@ -135,6 +189,12 @@ pdfium_fuzzer("pdf_codec_rle_fuzzer") { ] } +pdfium_fuzzer("pdf_font_fuzzer") { + sources = [ + "pdf_font_fuzzer.cc", + ] +} + pdfium_fuzzer("pdf_hint_table_fuzzer") { sources = [ "pdf_hint_table_fuzzer.cc", diff --git a/testing/libfuzzer/pdf_cfx_barcode_fuzzer.cc b/testing/libfuzzer/pdf_cfx_barcode_fuzzer.cc new file mode 100644 index 0000000000000000000000000000000000000000..3334e86bfce427c24685c7f877b6fbcaa6f6f8ce --- /dev/null +++ b/testing/libfuzzer/pdf_cfx_barcode_fuzzer.cc @@ -0,0 +1,38 @@ +// Copyright 2017 The 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. + +#include + +#include "core/fxcrt/fx_string.h" +#include "xfa/fwl/cfx_barcode.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 2 * sizeof(wchar_t)) + return 0; + + BC_TYPE type = static_cast(data[0] % (BC_DATAMATRIX + 1)); + + // Only used one byte, but align with wchar_t for string below. + data += sizeof(wchar_t); + size -= sizeof(wchar_t); + + CFX_Barcode barcode; + if (!barcode.Create(type)) + return 0; + + // TODO(tsepez): Setup more options from |data|. + barcode.SetModuleHeight(300); + barcode.SetModuleWidth(420); + barcode.SetHeight(298); + barcode.SetWidth(418); + + WideStringView content(reinterpret_cast(data), + size / sizeof(wchar_t)); + + if (!barcode.Encode(content)) + return 0; + + // TODO(tsepez): Output to device. + return 0; +} diff --git a/testing/libfuzzer/pdf_cfx_saxreader_fuzzer.cc b/testing/libfuzzer/pdf_cfx_saxreader_fuzzer.cc index d99457d360f948e2d3238a851e6127103f786822..a811a8e96c5c355950b57f7fb09a2471b8bf2146 100644 --- a/testing/libfuzzer/pdf_cfx_saxreader_fuzzer.cc +++ b/testing/libfuzzer/pdf_cfx_saxreader_fuzzer.cc @@ -4,29 +4,21 @@ #include -#include "core/fxcrt/cfx_retain_ptr.h" -#include "xfa/fde/xml/cfx_saxreader.h" -#include "xfa/fgas/crt/fgas_stream.h" -#include "xfa/fxfa/parser/cxfa_widetextread.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/xml/cfx_saxreader.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - CFX_WideString input = CFX_WideString::FromUTF8( - CFX_ByteStringC(data, static_cast(size))); - auto stream = pdfium::MakeRetain(input); - if (!stream) - return 0; - - CFX_RetainPtr fileRead = - stream->MakeSeekableReadStream(); - if (!fileRead) - return 0; - CFX_SAXReader reader; - if (reader.StartParse(fileRead, 0, -1, CFX_SaxParseMode_NotSkipSpace) < 0) + if (reader.StartParse(pdfium::MakeRetain( + const_cast(data), size, false), + 0, -1, CFX_SaxParseMode_NotSkipSpace) < 0) { return 0; + } while (1) { - int32_t ret = reader.ContinueParse(nullptr); + int32_t ret = reader.ContinueParse(); if (ret < 0 || ret > 99) break; } diff --git a/testing/libfuzzer/pdf_cmap_fuzzer.cc b/testing/libfuzzer/pdf_cmap_fuzzer.cc index 1e1ade7e1925e07959464db8a6ba8972d558869c..b0e41d511c6900438859c98eefefa00d94956d91 100644 --- a/testing/libfuzzer/pdf_cmap_fuzzer.cc +++ b/testing/libfuzzer/pdf_cmap_fuzzer.cc @@ -4,10 +4,11 @@ #include -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "third_party/base/ptr_util.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - CPDF_CMap cmap; - cmap.LoadEmbedded(data, size); + auto cmap = pdfium::MakeRetain(); + cmap->LoadEmbedded(data, size); return 0; } diff --git a/testing/libfuzzer/pdf_codec_icc_fuzzer.cc b/testing/libfuzzer/pdf_codec_icc_fuzzer.cc index d7bfdba0cfaeec7096acdf8938e5be386e4af579..7021017953cdb6271fda375e29807c5e98419c47 100644 --- a/testing/libfuzzer/pdf_codec_icc_fuzzer.cc +++ b/testing/libfuzzer/pdf_codec_icc_fuzzer.cc @@ -9,16 +9,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { CCodec_IccModule icc_module; uint32_t nComponent = 0; - void* transform = icc_module.CreateTransform_sRGB(data, size, nComponent); + std::unique_ptr transform = + icc_module.CreateTransform_sRGB(data, size, &nComponent); if (transform) { - FX_FLOAT src[4]; - FX_FLOAT dst[4]; + float src[4]; + float dst[4]; for (int i = 0; i < 4; i++) src[i] = 0.5f; icc_module.SetComponents(nComponent); - icc_module.Translate(transform, src, dst); - icc_module.DestroyTransform(transform); + icc_module.Translate(transform.get(), src, dst); } return 0; diff --git a/testing/libfuzzer/pdf_codec_jbig2_fuzzer.cc b/testing/libfuzzer/pdf_codec_jbig2_fuzzer.cc index 1db39751db0380083d7d0dc99bbaf7b8c81f25a0..7b8e2aac33d16ea465489806f519c0ee93179d57 100644 --- a/testing/libfuzzer/pdf_codec_jbig2_fuzzer.cc +++ b/testing/libfuzzer/pdf_codec_jbig2_fuzzer.cc @@ -9,7 +9,10 @@ #include "core/fxcodec/JBig2_DocumentContext.h" #include "core/fxcodec/codec/ccodec_jbig2module.h" #include "core/fxcodec/jbig2/JBig2_Context.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" +#include "third_party/base/ptr_util.h" static uint32_t GetInteger(const uint8_t* data) { return data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; @@ -25,20 +28,29 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { size -= kParameterSize; data += kParameterSize; - std::unique_ptr bitmap(new CFX_DIBitmap); + static constexpr uint32_t kMemLimit = 512000000; // 512 MB + static constexpr uint32_t k1bppRgbComponents = 4; // From CFX_DIBitmap impl. + FX_SAFE_UINT32 mem = width; + mem *= height; + mem *= k1bppRgbComponents; + if (!mem.IsValid() || mem.ValueOrDie() > kMemLimit) + return 0; + + auto bitmap = pdfium::MakeRetain(); if (!bitmap->Create(width, height, FXDIB_1bppRgb)) return 0; - std::unique_ptr stream(new CPDF_Stream); + auto stream = pdfium::MakeUnique(); stream->AsStream()->SetData(data, size); - CPDF_StreamAcc src_stream; - src_stream.LoadAllData(stream->AsStream(), true); + + auto src_stream = pdfium::MakeRetain(stream->AsStream()); + src_stream->LoadAllDataRaw(); CCodec_Jbig2Module module; CCodec_Jbig2Context jbig2_context; std::unique_ptr document_context; FXCODEC_STATUS status = module.StartDecode( - &jbig2_context, &document_context, width, height, &src_stream, nullptr, + &jbig2_context, &document_context, width, height, src_stream, nullptr, bitmap->GetBuffer(), bitmap->GetPitch(), nullptr); while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) diff --git a/testing/libfuzzer/pdf_css_fuzzer.cc b/testing/libfuzzer/pdf_css_fuzzer.cc index f02f006ea038c9cac447db34d946c7d49768c6c0..7cd924e70ff2d3ec6665d2edf3ee8b0acc32a780 100644 --- a/testing/libfuzzer/pdf_css_fuzzer.cc +++ b/testing/libfuzzer/pdf_css_fuzzer.cc @@ -4,28 +4,25 @@ #include -#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_csssyntaxparser.h" #include "core/fxcrt/fx_string.h" -#include "xfa/fde/css/cfde_csssyntaxparser.h" -#include "xfa/fde/css/fde_css.h" -#include "xfa/fgas/crt/fgas_stream.h" -#include "xfa/fxfa/parser/cxfa_widetextread.h" +#include "core/fxcrt/retain_ptr.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - CFX_WideString input = CFX_WideString::FromUTF8( - CFX_ByteStringC(data, static_cast(size))); + WideString input = + WideString::FromUTF8(ByteStringView(data, static_cast(size))); // If we convert the input into an empty string bail out. if (input.GetLength() == 0) return 0; - CFDE_CSSSyntaxParser parser; - parser.Init(input.c_str(), input.GetLength()); - - FDE_CSSSyntaxStatus status; + CFX_CSSSyntaxParser parser(input.c_str(), input.GetLength()); + CFX_CSSSyntaxStatus status; do { status = parser.DoSyntaxParse(); - } while (status != FDE_CSSSyntaxStatus::Error && - status != FDE_CSSSyntaxStatus::EOS); + } while (status != CFX_CSSSyntaxStatus::Error && + status != CFX_CSSSyntaxStatus::EOS); return 0; } diff --git a/testing/libfuzzer/pdf_fm2js_fuzzer.cc b/testing/libfuzzer/pdf_fm2js_fuzzer.cc index 9afaa915ecd9a49c39546eccc7b9c3a89a83fc70..2541dfbcc8b074a8f1c233050527a5ab9d9c33a3 100644 --- a/testing/libfuzzer/pdf_fm2js_fuzzer.cc +++ b/testing/libfuzzer/pdf_fm2js_fuzzer.cc @@ -5,23 +5,19 @@ #include #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/cfx_widetextbuf.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/fm2js/xfa_program.h" +#include "fxjs/cfxjse_formcalc_context.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FX_SAFE_STRSIZE safe_size = size; + FX_SAFE_SIZE_T safe_size = size; if (!safe_size.IsValid()) return 0; - CFX_WideString input = - CFX_WideString::FromUTF8(CFX_ByteStringC(data, safe_size.ValueOrDie())); - CXFA_FMProgram program(input.AsStringC()); - if (program.ParseProgram()) - return 0; - CFX_WideTextBuf js; - program.TranslateProgram(js); + WideString input = + WideString::FromUTF8(ByteStringView(data, safe_size.ValueOrDie())); + CFXJSE_FormCalcContext::Translate(input.AsStringView(), &js); return 0; } diff --git a/testing/libfuzzer/pdf_font_fuzzer.cc b/testing/libfuzzer/pdf_font_fuzzer.cc new file mode 100644 index 0000000000000000000000000000000000000000..aed66613fa1531c6330d4755dadbfa2d2f5a1880 --- /dev/null +++ b/testing/libfuzzer/pdf_font_fuzzer.cc @@ -0,0 +1,33 @@ +// Copyright 2017 The 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. + +#include +#include + +#include "public/cpp/fpdf_deleters.h" +#include "public/fpdf_edit.h" +#include "public/fpdfview.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 2) + return 0; + + std::unique_ptr doc(FPDF_CreateNewDocument()); + std::unique_ptr page( + FPDFPage_New(doc.get(), 0, 612, 792)); + int font_type = data[0]; + FPDF_BOOL cid = data[1]; + data += 2; + size -= 2; + std::unique_ptr font( + FPDFText_LoadFont(doc.get(), data, size, font_type, cid)); + if (!font) + return 0; + + FPDF_PAGEOBJECT text_object = + FPDFPageObj_CreateTextObj(doc.get(), font.get(), 12.0f); + FPDFPage_InsertObject(page.get(), text_object); + FPDFPage_GenerateContent(page.get()); + return 0; +} diff --git a/testing/libfuzzer/pdf_formcalc_fuzzer.cc b/testing/libfuzzer/pdf_formcalc_fuzzer.cc new file mode 100644 index 0000000000000000000000000000000000000000..08e22bb24722fc26192d55ab2dc25ea949d6ff62 --- /dev/null +++ b/testing/libfuzzer/pdf_formcalc_fuzzer.cc @@ -0,0 +1,16 @@ +// Copyright 2017 The 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. + +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_string.h" +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + WideString input = WideString::FromUTF8(ByteStringView(data, size)); + + CXFA_FMParser parser(input.AsStringView()); + parser.Parse(); + + return 0; +} diff --git a/testing/libfuzzer/pdf_fuzzer_init.cc b/testing/libfuzzer/pdf_fuzzer_init.cc new file mode 100644 index 0000000000000000000000000000000000000000..4b9790c3f89f808e00e2fbc8bd5b333da79014b6 --- /dev/null +++ b/testing/libfuzzer/pdf_fuzzer_init.cc @@ -0,0 +1,21 @@ +// Copyright 2017 The 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. + +#include + +#include "public/fpdfview.h" + +// Initialize the library once for all runs of the fuzzer. +struct TestCase { + TestCase() { + memset(&config, '\0', sizeof(config)); + config.version = 2; + config.m_pUserFontPaths = nullptr; + config.m_pIsolate = nullptr; + config.m_v8EmbedderSlot = 0; + FPDF_InitLibraryWithConfig(&config); + } + FPDF_LIBRARY_CONFIG config; +}; +static TestCase* testCase = new TestCase(); diff --git a/testing/libfuzzer/pdf_hint_table_fuzzer.cc b/testing/libfuzzer/pdf_hint_table_fuzzer.cc index b31d56eb8fb9c8f4d6edb7a2a2b4d38e12c5426e..ee51e25f24b03f781a362b241bc984dc87b65579 100644 --- a/testing/libfuzzer/pdf_hint_table_fuzzer.cc +++ b/testing/libfuzzer/pdf_hint_table_fuzzer.cc @@ -10,6 +10,7 @@ #include "core/fpdfapi/parser/cpdf_hint_tables.h" #include "core/fpdfapi/parser/cpdf_linearized_header.h" #include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fxcrt/cfx_bitstream.h" #include "third_party/base/ptr_util.h" int32_t GetData(const int32_t** data32, const uint8_t** data, size_t* size) { @@ -35,8 +36,7 @@ class HintTableForFuzzing : public CPDF_HintTables { if (size < static_cast(shared_hint_table_offset_)) return; - CFX_BitStream bs; - bs.Init(data, size); + CFX_BitStream bs(data, size); if (!ReadPageHintTable(&bs)) return; ReadSharedObjHintTable(&bs, shared_hint_table_offset_); @@ -49,7 +49,7 @@ class HintTableForFuzzing : public CPDF_HintTables { class FakeLinearized : public CPDF_LinearizedHeader { public: explicit FakeLinearized(CPDF_Dictionary* linearized_dict) - : CPDF_LinearizedHeader(linearized_dict) {} + : CPDF_LinearizedHeader(linearized_dict, 0) {} }; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { diff --git a/testing/libfuzzer/pdf_jpx_fuzzer.cc b/testing/libfuzzer/pdf_jpx_fuzzer.cc index bea7ba2dbefa87622510e21136495bfb7c8a8b4c..da65bc2d9ad1b98b71a749de50d48e67ef6d369c 100644 --- a/testing/libfuzzer/pdf_jpx_fuzzer.cc +++ b/testing/libfuzzer/pdf_jpx_fuzzer.cc @@ -6,18 +6,17 @@ #include #include -#include "core/fxcodec/codec/codec_int.h" +#include "core/fxcodec/codec/ccodec_jpxmodule.h" +#include "core/fxcodec/codec/cjpx_decoder.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" CCodec_JpxModule g_module; -struct DecoderDeleter { - void operator()(CJPX_Decoder* decoder) { g_module.DestroyDecoder(decoder); } -}; - extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - std::unique_ptr decoder( - g_module.CreateDecoder(data, size, nullptr)); + std::unique_ptr decoder = + g_module.CreateDecoder(data, size, nullptr); if (!decoder) return 0; @@ -26,6 +25,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { uint32_t components; g_module.GetImageInfo(decoder.get(), &width, &height, &components); + static constexpr uint32_t kMemLimit = 1024 * 1024 * 1024; // 1 GB. + FX_SAFE_UINT32 mem = width; + mem *= height; + mem *= components; + if (!mem.IsValid() || mem.ValueOrDie() > kMemLimit) + return 0; + FXDIB_Format format; if (components == 1) { format = FXDIB_8bppRgb; @@ -37,8 +43,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { width = (width * components + 2) / 3; format = FXDIB_Rgb; } - - std::unique_ptr bitmap(new CFX_DIBitmap); + auto bitmap = pdfium::MakeRetain(); if (!bitmap->Create(width, height, format)) return 0; diff --git a/testing/libfuzzer/pdf_lzw_fuzzer.cc b/testing/libfuzzer/pdf_lzw_fuzzer.cc new file mode 100644 index 0000000000000000000000000000000000000000..71c258969d49bbee76e04330c23fc788a5fd3bd5 --- /dev/null +++ b/testing/libfuzzer/pdf_lzw_fuzzer.cc @@ -0,0 +1,58 @@ +// Copyright 2017 The 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. + +#include + +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" +#include "third_party/base/numerics/safe_conversions.h" + +// Between 2x and 5x is a standard range for LZW according to a quick +// search of papers. Running up to 10x to catch any niche cases. +constexpr uint32_t kMinCompressionRatio = 2; +constexpr uint32_t kMaxCompressionRatio = 10; + +void LZWFuzz(const uint8_t* src_buf, + size_t src_size, + uint8_t color_exp, + uint8_t code_exp) { + std::unique_ptr decompressor = + CFX_LZWDecompressor::Create(color_exp, code_exp); + if (!decompressor) + return; + + for (uint32_t compressions_ratio = kMinCompressionRatio; + compressions_ratio <= kMaxCompressionRatio; compressions_ratio++) { + std::vector des_buf(compressions_ratio * src_size); + // This cast should be safe since the caller is checking for overflow on + // the initial data. + uint32_t des_size = static_cast(des_buf.size()); + if (CFX_GifDecodeStatus::InsufficientDestSize != + decompressor->Decode(const_cast(src_buf), src_size, + des_buf.data(), &des_size)) + return; + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Need at least 3 bytes to do anything. + if (size < 3) + return 0; + + // Normally the GIF would provide the code and color sizes, instead, going + // to assume they are the first two bytes of data provided. + uint8_t color_exp = data[0]; + uint8_t code_exp = data[1]; + const uint8_t* lzw_data = data + 2; + uint32_t lzw_data_size = static_cast(size - 2); + // Check that there isn't going to be an overflow in the destination buffer + // size. + if (lzw_data_size > + std::numeric_limits::max() / kMaxCompressionRatio) { + return 0; + } + + LZWFuzz(lzw_data, lzw_data_size, color_exp, code_exp); + + return 0; +} diff --git a/testing/libfuzzer/pdf_xml_fuzzer.cc b/testing/libfuzzer/pdf_xml_fuzzer.cc index e3cd2543449cdb28432ff0fbb031d688295355b8..d8010f90f8ab7f9b29761aff14431dc3b0b1f1ef 100644 --- a/testing/libfuzzer/pdf_xml_fuzzer.cc +++ b/testing/libfuzzer/pdf_xml_fuzzer.cc @@ -6,33 +6,33 @@ #include #include -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/xml/cfx_xmldoc.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmlparser.h" #include "third_party/base/ptr_util.h" -#include "xfa/fde/xml/fde_xml_imp.h" -#include "xfa/fxfa/parser/cxfa_xml_parser.h" -#include "xfa/fxfa/parser/cxfa_widetextread.h" namespace { -CFDE_XMLNode* XFA_FDEExtension_GetDocumentNode( - CFDE_XMLDoc* pXMLDoc, +CFX_XMLNode* XFA_FDEExtension_GetDocumentNode( + CFX_XMLDoc* pXMLDoc, bool bVerifyWellFormness = false) { if (!pXMLDoc) { return nullptr; } - CFDE_XMLNode* pXMLFakeRoot = pXMLDoc->GetRoot(); - for (CFDE_XMLNode* pXMLNode = - pXMLFakeRoot->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pXMLNode->GetType() == FDE_XMLNODE_Element) { + CFX_XMLNode* pXMLFakeRoot = pXMLDoc->GetRoot(); + for (CFX_XMLNode* pXMLNode = + pXMLFakeRoot->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pXMLNode->GetType() == FX_XMLNODE_Element) { if (bVerifyWellFormness) { - for (CFDE_XMLNode* pNextNode = - pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling); + for (CFX_XMLNode* pNextNode = + pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling); pNextNode; - pNextNode = pNextNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pNextNode->GetType() == FDE_XMLNODE_Element) { + pNextNode = pNextNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pNextNode->GetType() == FX_XMLNODE_Element) { return nullptr; } } @@ -46,21 +46,18 @@ CFDE_XMLNode* XFA_FDEExtension_GetDocumentNode( } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FX_SAFE_STRSIZE safe_size = size; + FX_SAFE_SIZE_T safe_size = size; if (!safe_size.IsValid()) return 0; - CFX_WideString input = - CFX_WideString::FromUTF8(CFX_ByteStringC(data, safe_size.ValueOrDie())); - auto stream = pdfium::MakeRetain(input); - if (!stream) + RetainPtr stream = + pdfium::MakeRetain(const_cast(data), + size); + auto doc = pdfium::MakeUnique(); + if (!doc->LoadXML(pdfium::MakeUnique(doc->GetRoot(), stream))) return 0; - auto doc = pdfium::MakeUnique(); - if (!doc->LoadXML(pdfium::MakeUnique(doc->GetRoot(), stream))) - return 0; - - if (doc->DoLoad(nullptr) < 100) + if (doc->DoLoad() < 100) return 0; (void)XFA_FDEExtension_GetDocumentNode(doc.get()); diff --git a/testing/libfuzzer/xfa_codec_fuzzer.h b/testing/libfuzzer/xfa_codec_fuzzer.h index 9a8b23e36837d4fbf5ceb23baba7bd16bdda14ba..b1d888f3807f03c3ab5788eb1e53c116fea2cef4 100644 --- a/testing/libfuzzer/xfa_codec_fuzzer.h +++ b/testing/libfuzzer/xfa_codec_fuzzer.h @@ -13,9 +13,14 @@ #include "core/fxcodec/codec/ccodec_progressivedecoder.h" #include "core/fxcodec/codec/ccodec_tiffmodule.h" #include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_stream.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "testing/fx_string_testhelpers.h" #include "third_party/base/ptr_util.h" +// Support up to 64 MB. This prevents trivial OOM when MSAN is on and +// time outs. +const int kXFACodecFuzzerPixelLimit = 64000000; + class XFACodecFuzzer { public: static int Fuzz(const uint8_t* data, size_t size, FXCODEC_IMAGE_TYPE type) { @@ -27,51 +32,36 @@ class XFACodecFuzzer { std::unique_ptr decoder = mgr->CreateProgressiveDecoder(); - CFX_RetainPtr source(new Reader(data, size)); + auto source = pdfium::MakeRetain(data, size); FXCODEC_STATUS status = decoder->LoadImageInfo(source, type, nullptr, true); if (status != FXCODEC_STATUS_FRAME_READY) return 0; - std::unique_ptr bitmap(new CFX_DIBitmap); + // Skipping very large images, since they will take a long time and may lead + // to OOM. + FX_SAFE_UINT32 bitmap_size = decoder->GetHeight(); + bitmap_size *= decoder->GetWidth(); + bitmap_size *= 4; // From CFX_DIBitmap impl. + if (!bitmap_size.IsValid() || + bitmap_size.ValueOrDie() > kXFACodecFuzzerPixelLimit) { + return 0; + } + + auto bitmap = pdfium::MakeRetain(); bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), FXDIB_Argb); - int32_t frames; - if (decoder->GetFrames(frames) != FXCODEC_STATUS_DECODE_READY || - frames == 0) + size_t frames; + std::tie(status, frames) = decoder->GetFrames(); + if (status != FXCODEC_STATUS_DECODE_READY || frames == 0) return 0; - status = decoder->StartDecode(bitmap.get(), 0, 0, bitmap->GetWidth(), + status = decoder->StartDecode(bitmap, 0, 0, bitmap->GetWidth(), bitmap->GetHeight()); while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) status = decoder->ContinueDecode(); return 0; } - - private: - class Reader : public IFX_SeekableReadStream { - public: - Reader(const uint8_t* data, size_t size) : m_data(data), m_size(size) {} - ~Reader() {} - - bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { - if (offset < 0 || static_cast(offset) >= m_size) - return false; - if (offset + size > m_size) - size = m_size - offset; - if (size == 0) - return false; - - memcpy(buffer, m_data + offset, size); - return true; - } - - FX_FILESIZE GetSize() override { return static_cast(m_size); } - - private: - const uint8_t* const m_data; - size_t m_size; - }; }; #endif // TESTING_LIBFUZZER_XFA_CODEC_FUZZER_H_ diff --git a/testing/range_set.cpp b/testing/range_set.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fc540f17c932f666d71a7c442fa4d723f1a8abb --- /dev/null +++ b/testing/range_set.cpp @@ -0,0 +1,74 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/range_set.h" + +#include + +#include "core/fxcrt/fx_system.h" + +RangeSet::RangeSet() {} +RangeSet::~RangeSet() {} + +bool RangeSet::Contains(const Range& range) const { + if (IsEmptyRange(range)) + return false; + + const Range fixed_range = FixDirection(range); + auto it = ranges().upper_bound(fixed_range); + + if (it == ranges().begin()) + return false; // No ranges includes range.first. + + --it; // Now it starts equal or before range.first. + return it->second >= fixed_range.second; +} + +void RangeSet::Union(const Range& range) { + if (IsEmptyRange(range)) + return; + + Range fixed_range = FixDirection(range); + if (IsEmpty()) { + ranges_.insert(fixed_range); + return; + } + + auto start = ranges_.upper_bound(fixed_range); + if (start != ranges_.begin()) + --start; // start now points to the key equal or lower than offset. + + if (start->second < fixed_range.first) + ++start; // start element is entirely before current range, skip it. + + auto end = ranges_.upper_bound(Range(fixed_range.second, fixed_range.second)); + + if (start == end) { // No ranges to merge. + ranges_.insert(fixed_range); + return; + } + + --end; + + const int new_start = std::min(start->first, fixed_range.first); + const int new_end = std::max(end->second, fixed_range.second); + + ranges_.erase(start, ++end); + ranges_.insert(Range(new_start, new_end)); +} + +void RangeSet::Union(const RangeSet& range_set) { + ASSERT(&range_set != this); + for (const auto& it : range_set.ranges()) + Union(it); +} + +RangeSet::Range RangeSet::FixDirection(const Range& range) const { + return range.first <= range.second ? range + : Range(range.second + 1, range.first + 1); +} + +bool RangeSet::IsEmptyRange(const Range& range) const { + return range.first == range.second; +} diff --git a/testing/range_set.h b/testing/range_set.h new file mode 100644 index 0000000000000000000000000000000000000000..6ed24bd83c63c053cc4834614d90cd919a18e8f2 --- /dev/null +++ b/testing/range_set.h @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TESTING_RANGE_SET_H_ +#define TESTING_RANGE_SET_H_ + +#include + +#include +#include + +class RangeSet { + public: + using Range = std::pair; + + RangeSet(); + ~RangeSet(); + + bool Contains(const Range& range) const; + + void Union(const Range& range); + + void Union(const RangeSet& range_set); + + bool IsEmpty() const { return ranges().empty(); } + + void Clear() { ranges_.clear(); } + + struct range_compare { + bool operator()(const Range& lval, const Range& rval) const { + return lval.first < rval.first; + } + }; + + using RangesContainer = std::set; + const RangesContainer& ranges() const { return ranges_; } + + private: + Range FixDirection(const Range& range) const; + + bool IsEmptyRange(const Range& range) const; + + RangesContainer ranges_; +}; + +#endif // TESTING_RANGE_SET_H_ diff --git a/testing/resources/annotation_highlight_long_content.pdf b/testing/resources/annotation_highlight_long_content.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7fd9103c41898f1b741c999ed9499077efe0eec4 Binary files /dev/null and b/testing/resources/annotation_highlight_long_content.pdf differ diff --git a/testing/resources/annotation_highlight_rollover_ap.in b/testing/resources/annotation_highlight_rollover_ap.in new file mode 100644 index 0000000000000000000000000000000000000000..426ed88b1d9abfabddcf9bc0d3511a77dc5a98ff --- /dev/null +++ b/testing/resources/annotation_highlight_rollover_ap.in @@ -0,0 +1,86 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OpenAction 20 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Annots [ + 4 0 R + ] + /Tabs /R +>> +endobj + +{{object 4 0}} << + /Type /Annot + /Subtype /Highlight + /Rect [ 75 681 512 690 ] + /NM (Annot-1) + /F 4 + /QuadPoints [ 75 688 512 688 75 679 512 679 ] + /C [ 0.0001108646 0.001760244 0.9982184 ] + /Contents () + /AP << + /R 5 0 R + >> +>> +endobj + +{{object 5 0}} << + /BBox [ + 67.7299 + 704.296 + 136.325 + 721.292 + ] + /FormType 1 + /Matrix [ + 1.0 + 0.0 + 0.0 + 1.0 + -67.7299 + -704.296 + ] + /Resources << + /ProcSet [ + /PDF + ] + >> + /Subtype /Form + /Type /XObject + /Length 165 +>> +stream +1 0.819611 0 rg +0.9997 w +72 704.7961 m +68.2298 708.5663 68.2298 717.0216 72 720.7918 c +132.0551 720.7918 l +135.8253 717.0216 135.8253 708.5663 132.0551 704.7961 c +f +endstream +>> +endobj + +{{xref}} +trailer << + /Root 1 0 R + /Size 6 +>> +{{startxref}} +%%EOF diff --git a/testing/resources/annotation_highlight_rollover_ap.pdf b/testing/resources/annotation_highlight_rollover_ap.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1763b2cc3cbb2ac9226acd52fbfa7900ff33e683 --- /dev/null +++ b/testing/resources/annotation_highlight_rollover_ap.pdf @@ -0,0 +1,95 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R + /OpenAction 20 0 R +>> +endobj +2 0 obj << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +3 0 obj << + /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Annots [ + 4 0 R + ] + /Tabs /R +>> +endobj + +4 0 obj << + /Type /Annot + /Subtype /Highlight + /Rect [ 75 681 512 690 ] + /NM (Annot-1) + /F 4 + /QuadPoints [ 75 688 512 688 75 679 512 679 ] + /C [ 0.0001108646 0.001760244 0.9982184 ] + /Contents () + /AP << + /R 5 0 R + >> +>> +endobj + +5 0 obj << + /BBox [ + 67.7299 + 704.296 + 136.325 + 721.292 + ] + /FormType 1 + /Matrix [ + 1.0 + 0.0 + 0.0 + 1.0 + -67.7299 + -704.296 + ] + /Resources << + /ProcSet [ + /PDF + ] + >> + /Subtype /Form + /Type /XObject + /Length 165 +>> +stream +1 0.819611 0 rg +0.9997 w +72 704.7961 m +68.2298 708.5663 68.2298 717.0216 72 720.7918 c +132.0551 720.7918 l +135.8253 717.0216 135.8253 708.5663 132.0551 704.7961 c +f +endstream +>> +endobj + +xref +0 6 +0000000000 65535 f +0000000015 00000 n +0000000089 00000 n +0000000177 00000 n +0000000292 00000 n +0000000535 00000 n +trailer << + /Root 1 0 R + /Size 6 +>> +startxref +993 +%%EOF diff --git a/testing/resources/annotation_highlight_square_with_ap.pdf b/testing/resources/annotation_highlight_square_with_ap.pdf new file mode 100644 index 0000000000000000000000000000000000000000..64d5c40d75ce3f42a77c92ce3ff2f884c9720197 Binary files /dev/null and b/testing/resources/annotation_highlight_square_with_ap.pdf differ diff --git a/testing/resources/annotation_ink_multiple.pdf b/testing/resources/annotation_ink_multiple.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5c3d4a0f6397654b99357b28781d82c4ce84c6dd Binary files /dev/null and b/testing/resources/annotation_ink_multiple.pdf differ diff --git a/testing/resources/annotation_stamp_with_ap.pdf b/testing/resources/annotation_stamp_with_ap.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9181c96af580194adf6e414a444b079549da7170 Binary files /dev/null and b/testing/resources/annotation_stamp_with_ap.pdf differ diff --git a/testing/resources/annotiter.in b/testing/resources/annotiter.in index 4dc2a4ee2e23ac93c49b7af4a0365c7d8848fa76..21e7b45e173b8b0457e429dee27e8f0baedabf1a 100644 --- a/testing/resources/annotiter.in +++ b/testing/resources/annotiter.in @@ -122,8 +122,6 @@ endobj >> endobj {{xref}} -trailer << - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/annotiter.pdf b/testing/resources/annotiter.pdf index 2cb6d395d0088b1f8868c01ad83c87fdc5cade9f..feb7909768706d5731064844028e74d48631092e 100644 --- a/testing/resources/annotiter.pdf +++ b/testing/resources/annotiter.pdf @@ -150,9 +150,7 @@ xref 0000001160 00000 n 0000001288 00000 n 0000001415 00000 n -trailer << - /Root 1 0 R ->> +trailer<< /Root 1 0 R /Size 26 >> startxref 1546 %%EOF diff --git a/testing/resources/bookmarks.in b/testing/resources/bookmarks.in index dfa6e1426f6f4ceb6b9a40b5b6665ba22524fc37..793f6ae542fb34d2761a2abab903c6206f80aeb1 100644 --- a/testing/resources/bookmarks.in +++ b/testing/resources/bookmarks.in @@ -90,9 +90,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/bookmarks.pdf b/testing/resources/bookmarks.pdf index 824ce78db7c7a0787af5538547c82f40fbb8ce41..8c2eb5ac7beccad52355fb21fbe37441356e3c99 100644 --- a/testing/resources/bookmarks.pdf +++ b/testing/resources/bookmarks.pdf @@ -115,10 +115,7 @@ xref 0000000000 65535 f 0000000924 00000 n 0000001034 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +trailer<< /Root 1 0 R /Size 23 >> startxref 1122 %%EOF diff --git a/testing/resources/bookmarks_circular.in b/testing/resources/bookmarks_circular.in index 48a5695e17d2fc203bfe66d8f34702bfbe4cb549..1b05f36a1eff00f174ebfa5c76906d17ad495118 100644 --- a/testing/resources/bookmarks_circular.in +++ b/testing/resources/bookmarks_circular.in @@ -90,9 +90,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/bookmarks_circular.pdf b/testing/resources/bookmarks_circular.pdf index e7eb624781081082d4437ee37f4d1f4aca71b1a4..0e4ef86e695ffd4c9c81713af04fd44755757f71 100644 --- a/testing/resources/bookmarks_circular.pdf +++ b/testing/resources/bookmarks_circular.pdf @@ -115,10 +115,7 @@ xref 0000000000 65535 f 0000000924 00000 n 0000001034 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +trailer<< /Root 1 0 R /Size 23 >> startxref 1122 %%EOF diff --git a/testing/resources/bug_650.pdf b/testing/resources/bug_650.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5e46032f6ca24b64cc30b11791dd9d6d4a810e8c Binary files /dev/null and b/testing/resources/bug_650.pdf differ diff --git a/testing/resources/bug_707673.pdf b/testing/resources/bug_707673.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4f412bc73599a28b116e6dacd260d84206fc7e44 Binary files /dev/null and b/testing/resources/bug_707673.pdf differ diff --git a/testing/resources/bug_709793.in b/testing/resources/bug_709793.in new file mode 100644 index 0000000000000000000000000000000000000000..c9fe0882a740071969a46c0d83238817d101cd6c --- /dev/null +++ b/testing/resources/bug_709793.in @@ -0,0 +1,22 @@ +{{header}} +{{object 1 0}} << + /Pages 3 0 R + /AcroForm << + /XFA 7 0 R + >> +>> +endobj +{{object 3 0}} << +>> +endobj +{{object 7 0}} << +>>stream +
+endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/bug_709793.pdf b/testing/resources/bug_709793.pdf new file mode 100644 index 0000000000000000000000000000000000000000..003c7cf76980664dc8735c469b0995ca3c3d0b4a --- /dev/null +++ b/testing/resources/bug_709793.pdf @@ -0,0 +1,33 @@ +%PDF-1.7 +% +1 0 obj << + /Pages 3 0 R + /AcroForm << + /XFA 7 0 R + >> +>> +endobj +3 0 obj << +>> +endobj +7 0 obj << +>>stream + +endstream +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000000 65535 f +0000000086 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000107 00000 n +trailer << + /Root 1 0 R +>> +startxref +212 +%%EOF diff --git a/testing/resources/bug_713197.in b/testing/resources/bug_713197.in new file mode 100644 index 0000000000000000000000000000000000000000..49eaee2d93c21e9b3828a90cf1939d0c594aaca5 --- /dev/null +++ b/testing/resources/bug_713197.in @@ -0,0 +1,27 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}}<< + /Type /Pages + /MediaBox [0 0 600 800] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}}<< + /Type /Page + /Parent 2 0 R + /Resources <<>> + /Rotate -90 +>> +endobj +{{xref}} +trailer << + /Size 4 + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/bug_713197.pdf b/testing/resources/bug_713197.pdf new file mode 100644 index 0000000000000000000000000000000000000000..571cde9d7f136ac6aa7318bd6579321e9ec7cd3c --- /dev/null +++ b/testing/resources/bug_713197.pdf @@ -0,0 +1,34 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj<< + /Type /Pages + /MediaBox [0 0 600 800] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj<< + /Type /Page + /Parent 2 0 R + /Resources <<>> + /Rotate -90 +>> +endobj +xref +0 4 +0000000000 65535 f +0000000016 00000 n +0000000074 00000 n +0000000171 00000 n +trailer << + /Size 4 + /Root 1 0 R +>> +startxref +260 +%%EOF diff --git a/testing/resources/bug_717.pdf b/testing/resources/bug_717.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e3abd00e9e1127aeada78251231c0ae88df3e552 Binary files /dev/null and b/testing/resources/bug_717.pdf differ diff --git a/testing/resources/bug_750568.in b/testing/resources/bug_750568.in new file mode 100644 index 0000000000000000000000000000000000000000..9d7209382784e9eb9a82514415b2062460ee4659 --- /dev/null +++ b/testing/resources/bug_750568.in @@ -0,0 +1,77 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 4 + /Kids [ 3 0 R 4 0 R 5 0 R 6 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Contents 7 0 R +>> +endobj +{{object 4 0}} << + /Type /Page + /Parent 2 0 R + /Contents 8 0 R +>> +endobj +{{object 5 0}} << + /Type /Page + /Parent 2 0 R + /Contents 9 0 R +>> +endobj +{{object 6 0}} << + /Type /Page + /Parent 2 0 R + /Contents 10 0 R +>> +endobj +{{object 7 0}} << +>> +stream +q +0 0 0 rg +10 80 50 30 re B* +Q +endstream +endobj +{{object 8 0}} << +>> +stream +q +0 0 1 rg +70 135 50 30 re B* +Q +endstream +endobj +{{object 9 0}} << +>> +stream +q +0 1 0 rg +130 80 50 30 re B* +Q +endstream +endobj +{{object 10 0}} << +>> +stream +q +1 0 0 rg +70 25 50 30 re B* +Q +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/bug_750568.pdf b/testing/resources/bug_750568.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5fb60142bd92aa66258cf93556b7f8ff62c0b93e --- /dev/null +++ b/testing/resources/bug_750568.pdf @@ -0,0 +1,91 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 4 + /Kids [ 3 0 R 4 0 R 5 0 R 6 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 7 0 R +>> +endobj +4 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 8 0 R +>> +endobj +5 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 9 0 R +>> +endobj +6 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 10 0 R +>> +endobj +7 0 obj << +>> +stream +q +0 0 0 rg +10 80 50 30 re B* +Q +endstream +endobj +8 0 obj << +>> +stream +q +0 0 1 rg +70 135 50 30 re B* +Q +endstream +endobj +9 0 obj << +>> +stream +q +0 1 0 rg +130 80 50 30 re B* +Q +endstream +endobj +10 0 obj << +>> +stream +q +1 0 0 rg +70 25 50 30 re B* +Q +endstream +endobj +xref +0 11 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000179 00000 n +0000000248 00000 n +0000000317 00000 n +0000000386 00000 n +0000000456 00000 n +0000000525 00000 n +0000000595 00000 n +0000000665 00000 n +trailer<< /Root 1 0 R /Size 11 >> +startxref +735 +%%EOF diff --git a/testing/resources/bug_757705.pdf b/testing/resources/bug_757705.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ef7d96e678a06c831a6d90c032207071d5b7828b Binary files /dev/null and b/testing/resources/bug_757705.pdf differ diff --git a/testing/resources/bug_765384.in b/testing/resources/bug_765384.in new file mode 100644 index 0000000000000000000000000000000000000000..e7e46c797e4e5dd201ccf23258b899be3743e74c --- /dev/null +++ b/testing/resources/bug_765384.in @@ -0,0 +1,98 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm 4 0 R + /OpenAction 10 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Annots [ + 8 0 R + 9 0 R + ] +>> +endobj +% Forms +{{object 4 0}} << + /XFA [ + (xdp:xdp) 43 0 R + (form) 49 0 R + () 50 0 R + ] + /Fields [ + 8 0 R + 9 0 R + ] +>> +endobj +% Fields +{{object 8 0}} << + /FT /Ch + /Ff 0 + /T (MyField) + /Type /Annot + /Subtype /Widget + /Rect [0 0 800 800] + /Opt [(test 1) (test 2)] + /AA << /K 20 0 R >> +>> +endobj +% Fields +{{object 9 0}} << + /FT /Tx + /T (MyField2) + /Type /Annot + /Subtype /Widget + /V (myfield_2) + /Rect [0 0 1 1] +>> +endobj +% JS Action +{{object 20 0}} << + /Type /Action + /S /JavaScript + /JS 21 0 R +>> +endobj +% JS program to exexute +{{object 21 0}} << +>> +stream +this.getField("MyField2").setFocus(); +this.getField("MyField").borderStyle="dashed"; +this.getField("MyField").setFocus(); +endstream +endobj +{{object 43 0}} << +>>stream + + +endstream +endobj +{{object 49 0}} << +>>stream + + +endstream +endobj +{{object 50 0}} << +>>stream + +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/bug_765384.pdf b/testing/resources/bug_765384.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e820fcc736885111c39d9dc7485ae41712bd42da --- /dev/null +++ b/testing/resources/bug_765384.pdf @@ -0,0 +1,152 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R + /AcroForm 4 0 R + /OpenAction 10 0 R +>> +endobj +2 0 obj << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +3 0 obj << + /Type /Page + /Parent 2 0 R + /Annots [ + 8 0 R + 9 0 R + ] +>> +endobj +% Forms +4 0 obj << + /XFA [ + (xdp:xdp) 43 0 R + (form) 49 0 R + () 50 0 R + ] + /Fields [ + 8 0 R + 9 0 R + ] +>> +endobj +% Fields +8 0 obj << + /FT /Ch + /Ff 0 + /T (MyField) + /Type /Annot + /Subtype /Widget + /Rect [0 0 800 800] + /Opt [(test 1) (test 2)] + /AA << /K 20 0 R >> +>> +endobj +% Fields +9 0 obj << + /FT /Tx + /T (MyField2) + /Type /Annot + /Subtype /Widget + /V (myfield_2) + /Rect [0 0 1 1] +>> +endobj +% JS Action +20 0 obj << + /Type /Action + /S /JavaScript + /JS 21 0 R +>> +endobj +% JS program to exexute +21 0 obj << +>> +stream +this.getField("MyField2").setFocus(); +this.getField("MyField").borderStyle="dashed"; +this.getField("MyField").setFocus(); +endstream +endobj +43 0 obj << +>>stream + + +endstream +endobj +49 0 obj << +>>stream + + +endstream +endobj +50 0 obj << +>>stream + +endstream +endobj +xref +0 51 +0000000000 65535 f +0000000015 00000 n +0000000107 00000 n +0000000195 00000 n +0000000292 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000436 00000 n +0000000604 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000732 00000 n +0000000824 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000985 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000001109 00000 n +0000001187 00000 n +trailer<< /Root 1 0 R /Size 51 >> +startxref +1236 +%%EOF diff --git a/testing/resources/bug_779.in b/testing/resources/bug_779.in new file mode 100644 index 0000000000000000000000000000000000000000..f8e21a0aad45a42b536f42b262c341fc2e5f9483 --- /dev/null +++ b/testing/resources/bug_779.in @@ -0,0 +1,50 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 612 792 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /Resources 5 0 R +>> +endobj +{{object 4 0}} << +>> +stream +1 0 0 -1 0 792 cm +0 0 255 RG +255 0 0 rg +5 w +/GS1 gs +q +100 100 m +200 200 l +200 300 l +b* +endstream +endobj +{{object 5 0}} << + /ExtGState << + /GS1 6 0 R + >> +>> +endobj +{{object 6 0}} << + /Type /ExtGState + /CA 0.3 + /ca 0.3 +>> +{{xref}} +{{trailer}} +{{startxref}} +%%EOF \ No newline at end of file diff --git a/testing/resources/bug_779.pdf b/testing/resources/bug_779.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2d609045cc3a69bfeb5c369911268dc4e04ca24e --- /dev/null +++ b/testing/resources/bug_779.pdf @@ -0,0 +1,60 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 612 792 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /Resources 5 0 R +>> +endobj +4 0 obj << +>> +stream +1 0 0 -1 0 792 cm +0 0 255 RG +255 0 0 rg +5 w +/GS1 gs +q +100 100 m +200 200 l +200 300 l +b* +endstream +endobj +5 0 obj << + /ExtGState << + /GS1 6 0 R + >> +>> +endobj +6 0 obj << + /Type /ExtGState + /CA 0.3 + /ca 0.3 +>> +xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000249 00000 n +0000000374 00000 n +0000000431 00000 n +trailer<< /Root 1 0 R /Size 7 >> +startxref +484 +%%EOF \ No newline at end of file diff --git a/testing/resources/bug_781804.pdf b/testing/resources/bug_781804.pdf new file mode 100644 index 0000000000000000000000000000000000000000..29304f157e6008b1d9dc3c01299cdec42c1c4494 Binary files /dev/null and b/testing/resources/bug_781804.pdf differ diff --git a/testing/resources/bug_782596.pdf b/testing/resources/bug_782596.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e28d897ada11d4fbe9304a4ea97723e12f9a4c34 Binary files /dev/null and b/testing/resources/bug_782596.pdf differ diff --git a/testing/resources/bug_921.in b/testing/resources/bug_921.in new file mode 100644 index 0000000000000000000000000000000000000000..9c48b2004e7f53e53094578f2d72818b50cc0c57 --- /dev/null +++ b/testing/resources/bug_921.in @@ -0,0 +1,64 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 612 792 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F0 4 0 R + >> + >> + /Contents 6 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type0 + /BaseFont /FooFont + /Encoding /Identity-H + /DescendantFonts [5 0 R] +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /CIDFontType2 + /DW 500 + /BaseFont /FooFont + /CIDSystemInfo << + /Ordering (Identity) + /Registry (Adobe) + /Supplement 0 + >> +>> +endobj +{{object 6 0}} << +/Length 2784 +>> +stream +BT +3 Tr +/F0 8 Tf +1.00 -0.00 0.00 1.00 258.2 99.6 Tm 198.0 Tz [ <0418> ] TJ 11.3 0.0 Td 121.2 Tz [ <0440><0430><0437><0432><0435> ] TJ 27.8 0.0 Td 126.0 Tz [ <043D><0435> ] TJ 14.2 0.0 Td 129.0 Tz [ <0432><044B><0440><0430><0436><0430><0435><0442> ] TJ 45.1 0.0 Td 118.0 Tz [ <0433><043B><0443><0431><043E><043A><043E><0433><043E> ] TJ 46.3 0.0 Td 119.0 Tz [ <0447><0435><043B><043E><0432><0435> ] TJ /F0 9 Tf +-161.8 -10.3 Td 102.1 Tz [ <0447><0435><0441><043A><043E><0433><043E> ] TJ 36.7 0.0 Td 104.3 Tz [ <0441><0442><0440><0430><0434><0430><043D><0438><044F> ] TJ 46.8 0.0 Td 118.7 Tz [ <043B><0438><0446><043E> ] TJ 25.4 0.0 Td 116.4 Tz [ <041E><0442><0435><043B><043B><043E> ] TJ 34.8 0.0 Td 250.7 Tz [ <2014> ] TJ 15.4 0.0 Td 113.8 Tz [ <041F><043E><043B><044F><043A><043E> ] TJ /F0 8 Tf +-157.7 -10.3 Td 102.0 Tz [ <0432><0430><002C> ] TJ 18.0 0.0 Td 122.4 Tz [ <043A><043E><0433><0434><0430> ] TJ 30.0 0.0 Td 129.0 Tz [ <043E><043D> ] TJ 16.6 0.0 Td 114.8 Tz [ <0433><043E><0432><043E><0440><0438><0442><003A> ] TJ 41.0 0.0 Td 129.4 Tz [ <00AB><0421><0435><0440><0434><0446><0435> ] TJ 40.8 0.0 Td 138.0 Tz [ <043C><043E><0435> ] TJ 22.3 0.0 Td 120.0 Tz [ <043E><0431><0440><0430> ] TJ /F0 9 Tf +-168.2 -10.8 Td 104.9 Tz [ <0442><0438><043B><043E><0441><044C> ] TJ 31.9 0.0 Td 128.0 Tz [ <0432> ] TJ 10.8 0.0 Td 102.9 Tz [ <043A><0430><043C><0435><043D><044C><0021> ] TJ 36.0 0.0 Td 119.1 Tz [ <0423><0434><0430><0440><0438><0432> ] TJ 37.0 0.0 Td 125.3 Tz [ <043F><043E> ] TJ 15.8 0.0 Td 101.3 Tz [ <043D><0435><043C><002C> ] TJ 22.1 0.0 Td 117.3 Tz [ <044F> ] TJ 8.9 0.0 Td 124.8 Tz [ <0443><0448><0438><0431><0443> ] TJ /F0 8 Tf +-162.5 -10.6 Td 115.5 Tz [ <0441><0435><0431><0435> ] TJ 21.6 0.0 Td 120.0 Tz [ <0440><0443><043A><0443><002E> ] TJ 29.0 0.0 Td 156.0 Tz [ <041D><043E> ] TJ 17.0 0.0 Td 107.2 Tz [ <0432><0441><0435><002D><0442><0430><043A><0438> ] TJ 40.6 0.0 Td 136.0 Tz [ <043C><0438><0440> ] TJ 20.9 0.0 Td 132.0 Tz [ <043D><0435> ] TJ 15.1 0.0 Td 120.0 Tz [ <0432><0438><0434><0430><043B> ] TJ 29.8 0.0 Td 112.0 Tz [ <0441><043E><0437> ] TJ -175.4 -10.6 Td 120.0 Tz [ <0434><0430><043D><044C><044F> ] TJ 30.7 0.0 Td 104.1 Tz [ <043F><0440><0435><043B><0435><0441><0442><043D><0435><0439><0021><002E><002E><00BB> ] TJ 64.1 0.0 Td 204.0 Tz [ <0418> ] TJ 16.6 0.0 Td 122.4 Tz [ <0432><043D><043E><0432><044C> ] TJ 33.1 0.0 Td 156.0 Tz [ <043C><044B> ] TJ 21.8 0.0 Td 126.0 Tz [ <0432><0438><0434><0438><043C> ] TJ /F0 9 Tf +-164.9 -11.0 Td 106.7 Tz [ <0433><043B><0443><0431><043E><043A><043E><0435> ] TJ 43.9 0.0 Td 104.9 Tz [ <0447><0435><043B><043E><0432><0435><0447><0435><0441><043A><043E><0435> ] TJ 62.4 0.0 Td 99.2 Tz [ <0441><0442><0440><0430><0434><0430><043D><0438><0435><002E> ] TJ 50.9 0.0 Td 112.0 Tz [ <041F><043E><0440><0443><0433><0430> ] TJ +ET +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/bug_921.pdf b/testing/resources/bug_921.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fb3950e54a37edc98c06a5a1fd2cb4c4fd265bb6 --- /dev/null +++ b/testing/resources/bug_921.pdf @@ -0,0 +1,74 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 612 792 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F0 4 0 R + >> + >> + /Contents 6 0 R +>> +endobj +4 0 obj << + /Type /Font + /Subtype /Type0 + /BaseFont /FooFont + /Encoding /Identity-H + /DescendantFonts [5 0 R] +>> +endobj +5 0 obj << + /Type /Font + /Subtype /CIDFontType2 + /DW 500 + /BaseFont /FooFont + /CIDSystemInfo << + /Ordering (Identity) + /Registry (Adobe) + /Supplement 0 + >> +>> +endobj +6 0 obj << +/Length 2784 +>> +stream +BT +3 Tr +/F0 8 Tf +1.00 -0.00 0.00 1.00 258.2 99.6 Tm 198.0 Tz [ <0418> ] TJ 11.3 0.0 Td 121.2 Tz [ <0440><0430><0437><0432><0435> ] TJ 27.8 0.0 Td 126.0 Tz [ <043D><0435> ] TJ 14.2 0.0 Td 129.0 Tz [ <0432><044B><0440><0430><0436><0430><0435><0442> ] TJ 45.1 0.0 Td 118.0 Tz [ <0433><043B><0443><0431><043E><043A><043E><0433><043E> ] TJ 46.3 0.0 Td 119.0 Tz [ <0447><0435><043B><043E><0432><0435> ] TJ /F0 9 Tf +-161.8 -10.3 Td 102.1 Tz [ <0447><0435><0441><043A><043E><0433><043E> ] TJ 36.7 0.0 Td 104.3 Tz [ <0441><0442><0440><0430><0434><0430><043D><0438><044F> ] TJ 46.8 0.0 Td 118.7 Tz [ <043B><0438><0446><043E> ] TJ 25.4 0.0 Td 116.4 Tz [ <041E><0442><0435><043B><043B><043E> ] TJ 34.8 0.0 Td 250.7 Tz [ <2014> ] TJ 15.4 0.0 Td 113.8 Tz [ <041F><043E><043B><044F><043A><043E> ] TJ /F0 8 Tf +-157.7 -10.3 Td 102.0 Tz [ <0432><0430><002C> ] TJ 18.0 0.0 Td 122.4 Tz [ <043A><043E><0433><0434><0430> ] TJ 30.0 0.0 Td 129.0 Tz [ <043E><043D> ] TJ 16.6 0.0 Td 114.8 Tz [ <0433><043E><0432><043E><0440><0438><0442><003A> ] TJ 41.0 0.0 Td 129.4 Tz [ <00AB><0421><0435><0440><0434><0446><0435> ] TJ 40.8 0.0 Td 138.0 Tz [ <043C><043E><0435> ] TJ 22.3 0.0 Td 120.0 Tz [ <043E><0431><0440><0430> ] TJ /F0 9 Tf +-168.2 -10.8 Td 104.9 Tz [ <0442><0438><043B><043E><0441><044C> ] TJ 31.9 0.0 Td 128.0 Tz [ <0432> ] TJ 10.8 0.0 Td 102.9 Tz [ <043A><0430><043C><0435><043D><044C><0021> ] TJ 36.0 0.0 Td 119.1 Tz [ <0423><0434><0430><0440><0438><0432> ] TJ 37.0 0.0 Td 125.3 Tz [ <043F><043E> ] TJ 15.8 0.0 Td 101.3 Tz [ <043D><0435><043C><002C> ] TJ 22.1 0.0 Td 117.3 Tz [ <044F> ] TJ 8.9 0.0 Td 124.8 Tz [ <0443><0448><0438><0431><0443> ] TJ /F0 8 Tf +-162.5 -10.6 Td 115.5 Tz [ <0441><0435><0431><0435> ] TJ 21.6 0.0 Td 120.0 Tz [ <0440><0443><043A><0443><002E> ] TJ 29.0 0.0 Td 156.0 Tz [ <041D><043E> ] TJ 17.0 0.0 Td 107.2 Tz [ <0432><0441><0435><002D><0442><0430><043A><0438> ] TJ 40.6 0.0 Td 136.0 Tz [ <043C><0438><0440> ] TJ 20.9 0.0 Td 132.0 Tz [ <043D><0435> ] TJ 15.1 0.0 Td 120.0 Tz [ <0432><0438><0434><0430><043B> ] TJ 29.8 0.0 Td 112.0 Tz [ <0441><043E><0437> ] TJ -175.4 -10.6 Td 120.0 Tz [ <0434><0430><043D><044C><044F> ] TJ 30.7 0.0 Td 104.1 Tz [ <043F><0440><0435><043B><0435><0441><0442><043D><0435><0439><0021><002E><002E><00BB> ] TJ 64.1 0.0 Td 204.0 Tz [ <0418> ] TJ 16.6 0.0 Td 122.4 Tz [ <0432><043D><043E><0432><044C> ] TJ 33.1 0.0 Td 156.0 Tz [ <043C><044B> ] TJ 21.8 0.0 Td 126.0 Tz [ <0432><0438><0434><0438><043C> ] TJ /F0 9 Tf +-164.9 -11.0 Td 106.7 Tz [ <0433><043B><0443><0431><043E><043A><043E><0435> ] TJ 43.9 0.0 Td 104.9 Tz [ <0447><0435><043B><043E><0432><0435><0447><0435><0441><043A><043E><0435> ] TJ 62.4 0.0 Td 99.2 Tz [ <0441><0442><0440><0430><0434><0430><043D><0438><0435><002E> ] TJ 50.9 0.0 Td 112.0 Tz [ <041F><043E><0440><0443><0433><0430> ] TJ +ET +endstream +endobj +xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000287 00000 n +0000000412 00000 n +0000000593 00000 n +trailer<< /Root 1 0 R /Size 7 >> +startxref +3428 +%%EOF diff --git a/testing/resources/circular_viewer_ref.in b/testing/resources/circular_viewer_ref.in new file mode 100644 index 0000000000000000000000000000000000000000..0ce7808154296c65b3a72afb76df571891655012 --- /dev/null +++ b/testing/resources/circular_viewer_ref.in @@ -0,0 +1,24 @@ +{{header}} +{{object 1 0}} +<> + >>>> +>> +endobj + +{{object 2 0}} +<> +endobj + +{{object 7 0}} +<> +endobj + +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/circular_viewer_ref.pdf b/testing/resources/circular_viewer_ref.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f97d068a068516c2e49172028609c662a9d8d869 --- /dev/null +++ b/testing/resources/circular_viewer_ref.pdf @@ -0,0 +1,35 @@ +%PDF-1.7 +% +1 0 obj +<> + >>>> +>> +endobj + +2 0 obj +<> +endobj + +7 0 obj +<> +endobj + +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000157 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000195 00000 n +trailer<< /Root 1 0 R /Size 8 >> +startxref +291 +%%EOF diff --git a/testing/resources/combobox_form.in b/testing/resources/combobox_form.in new file mode 100644 index 0000000000000000000000000000000000000000..6c9f914023d827e73954e06ee1235e2fcd3dfe5b --- /dev/null +++ b/testing/resources/combobox_form.in @@ -0,0 +1,86 @@ +{{header}} +{{object 1 0}} +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 8 0 R 9 0 R 10 0 R ] /DR 4 0 R >> +>> +endobj +{{object 2 0}} +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +{{object 3 0}} +<< + /Type /Page + /Parent 2 0 R + /Resources 4 0 R + /MediaBox [ 0 0 300 300 ] + /Contents 7 0 R + /Annots [ 8 0 R 9 0 R 10 0 R ] +>> +endobj +{{object 4 0}} +<< /Font 5 0 R >> +endobj +{{object 5 0}} +<< /F1 6 0 R >> +endobj +{{object 6 0}} +<< + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 7 0}} +<< /Length 51 >> +stream +BT +0 0 0 rg +/F1 12 Tf +100 150 Td +(Test Form) Tj +ET +endstream +endobj +{{object 8 0}} +<< + /Type /Annot + /FT /Ch + /Ff 393216 + /T (Combo_Editable) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 50 200 80 ] + /Subtype /Widget + /Opt [[(foo) (Foo)] [(bar) (Bar)] [(qux) (Qux)]] +>> +endobj +{{object 9 0}} +<< + /Type /Annot + /FT /Ch + /Ff 131072 + /T (Combo1) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget + /Opt [(Apple) (Banana) (Cherry)] + /V (Banana) +>> +endobj +{{object 10 0}} +<< + /Type /Annot + /FT /Ch + /Ff 131073 + /T (Combo_ReadOnly) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 200 200 230 ] + /Subtype /Widget + /Opt [(Dog) (Elephant) (Frog)] +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/combobox_form.pdf b/testing/resources/combobox_form.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5249276b629991ac0baae1d46663e5264eda196d --- /dev/null +++ b/testing/resources/combobox_form.pdf @@ -0,0 +1,100 @@ +%PDF-1.7 +% +1 0 obj +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 8 0 R 9 0 R 10 0 R ] /DR 4 0 R >> +>> +endobj +2 0 obj +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +3 0 obj +<< + /Type /Page + /Parent 2 0 R + /Resources 4 0 R + /MediaBox [ 0 0 300 300 ] + /Contents 7 0 R + /Annots [ 8 0 R 9 0 R 10 0 R ] +>> +endobj +4 0 obj +<< /Font 5 0 R >> +endobj +5 0 obj +<< /F1 6 0 R >> +endobj +6 0 obj +<< + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +7 0 obj +<< /Length 51 >> +stream +BT +0 0 0 rg +/F1 12 Tf +100 150 Td +(Test Form) Tj +ET +endstream +endobj +8 0 obj +<< + /Type /Annot + /FT /Ch + /Ff 393216 + /T (Combo_Editable) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 50 200 80 ] + /Subtype /Widget + /Opt [[(foo) (Foo)] [(bar) (Bar)] [(qux) (Qux)]] +>> +endobj +9 0 obj +<< + /Type /Annot + /FT /Ch + /Ff 131072 + /T (Combo1) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget + /Opt [(Apple) (Banana) (Cherry)] + /V (Banana) +>> +endobj +10 0 obj +<< + /Type /Annot + /FT /Ch + /Ff 131073 + /T (Combo_ReadOnly) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 200 200 230 ] + /Subtype /Widget + /Opt [(Dog) (Elephant) (Frog)] +>> +endobj +xref +0 11 +0000000000 65535 f +0000000015 00000 n +0000000127 00000 n +0000000186 00000 n +0000000335 00000 n +0000000368 00000 n +0000000399 00000 n +0000000475 00000 n +0000000575 00000 n +0000000779 00000 n +0000000975 00000 n +trailer<< /Root 1 0 R /Size 11 >> +startxref +1164 +%%EOF diff --git a/testing/resources/control_characters.in b/testing/resources/control_characters.in new file mode 100644 index 0000000000000000000000000000000000000000..ca7827fe114ef4f72c1da5b93548ee0e58252a39 --- /dev/null +++ b/testing/resources/control_characters.in @@ -0,0 +1,54 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + >> + /Contents 6 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 6 0}} << +>> +stream +BT +20 50 Td +/F1 12 Tf +(Hello\2\3, world!) Tj +0 50 Td +/F2 16 Tf +(Goodbye, world!) Tj +ET +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/control_characters.pdf b/testing/resources/control_characters.pdf new file mode 100644 index 0000000000000000000000000000000000000000..535009733f587b6b9d52104f1e95f06b19d34c34 --- /dev/null +++ b/testing/resources/control_characters.pdf @@ -0,0 +1,64 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + >> + /Contents 6 0 R +>> +endobj +4 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +5 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +6 0 obj << +>> +stream +BT +20 50 Td +/F1 12 Tf +(Hello\2\3, world!) Tj +0 50 Td +/F2 16 Tf +(Goodbye, world!) Tj +ET +endstream +endobj +xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000303 00000 n +0000000381 00000 n +0000000457 00000 n +trailer<< /Root 1 0 R /Size 7 >> +startxref +582 +%%EOF diff --git a/testing/resources/embedded_attachments.pdf b/testing/resources/embedded_attachments.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1e8fecd3dcb6a2c4ba2636d7e892a9b083b462c6 Binary files /dev/null and b/testing/resources/embedded_attachments.pdf differ diff --git a/testing/resources/embedded_images.pdf b/testing/resources/embedded_images.pdf new file mode 100644 index 0000000000000000000000000000000000000000..82adbeaa4c21d84b1013fe7ce4b140ba266ba438 Binary files /dev/null and b/testing/resources/embedded_images.pdf differ diff --git a/testing/resources/hello_world.in b/testing/resources/hello_world.in index 19fce0ce335de77ea31e295a87025eb52f65110e..d3cf265c353341ea0740fc35ed8e795c905ee561 100644 --- a/testing/resources/hello_world.in +++ b/testing/resources/hello_world.in @@ -3,6 +3,7 @@ /Type /Catalog /Pages 2 0 R >> +endobj {{object 2 0}} << /Type /Pages /MediaBox [ 0 0 200 200 ] @@ -48,9 +49,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/hello_world.pdf b/testing/resources/hello_world.pdf index bb4f0a88e7aedbbdbe4bdc6b22ff0696bed0282b..dcde8f7655a15f23b4499fc8543ecb1d3da5432a 100644 --- a/testing/resources/hello_world.pdf +++ b/testing/resources/hello_world.pdf @@ -4,6 +4,7 @@ /Type /Catalog /Pages 2 0 R >> +endobj 2 0 obj << /Type /Pages /MediaBox [ 0 0 200 200 ] @@ -52,15 +53,12 @@ xref 0 7 0000000000 65535 f 0000000015 00000 n -0000000061 00000 n -0000000154 00000 n -0000000296 00000 n -0000000374 00000 n -0000000450 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +0000000068 00000 n +0000000161 00000 n +0000000303 00000 n +0000000381 00000 n +0000000457 00000 n +trailer<< /Root 1 0 R /Size 7 >> startxref -571 +578 %%EOF diff --git a/testing/resources/javascript/array_buffer.in b/testing/resources/javascript/array_buffer.in new file mode 100644 index 0000000000000000000000000000000000000000..1f3e32d60d7a6b5b1695adf26e840fd3c421fc08 --- /dev/null +++ b/testing/resources/javascript/array_buffer.in @@ -0,0 +1,68 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OpenAction 10 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <> + >> + /Contents [21 0 R] + /MediaBox [0 0 612 792] +>> +% OpenAction action +{{object 10 0}} << + /Type /Action + /S /JavaScript + /JS 11 0 R +>> +endobj +% JS program to exexute +{{object 11 0}} << +>> +stream +app.alert("This test attempts to make array buffers until exhausted"); + +function test(size) { + var i, ab, ia; + app.alert("Trying size " + size); + ab = new ArrayBuffer(size); + ia = new Int32Array(ab); + for (i = 0; i < size / 4; ++i) { + ia[i] = i; + } + for (i = 0; i < size / 4; ++i) { + if (ia[i] != i) { + throw('aaaaaaah'); + } + } +} + +try { + test(1000); + test(2000000); + test(4000000000); +} catch (e) { + app.alert("Caught error " + e); +} +endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/javascript/array_buffer_expected.txt b/testing/resources/javascript/array_buffer_expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..f8f3bf227c35bc2039497031b2c2e94ccbcad413 --- /dev/null +++ b/testing/resources/javascript/array_buffer_expected.txt @@ -0,0 +1,5 @@ +Alert: This test attempts to make array buffers until exhausted +Alert: Trying size 1000 +Alert: Trying size 2000000 +Alert: Trying size 4000000000 +Alert: Caught error RangeError: Array buffer allocation failed diff --git a/testing/resources/javascript/bug_735912.in b/testing/resources/javascript/bug_735912.in new file mode 100644 index 0000000000000000000000000000000000000000..7f42d1b7c2283bc13d3a603c1525c95806c37637 --- /dev/null +++ b/testing/resources/javascript/bug_735912.in @@ -0,0 +1,115 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm 4 0 R + /OpenAction 30 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Annots [ + 8 0 R + ] + /AA << /C 36 0 R >> +>> +endobj +% Forms +{{object 4 0}} << + /XFA [ + (xdp:xdp) 43 0 R + (form) 49 0 R + () 50 0 R + ] + /Fields [ + 8 0 R + ] +>> +endobj +% Fields +{{object 8 0}} << + /FT /Tx + /T (MyField) + /Type /Annot + /Subtype /Widget + /Rect [100 300 500 400] + /AA << /Bl 34 0 R >> +>> +endobj +% JS Action +{{object 30 0}} << + /Type /Action + /S /JavaScript + /JS 31 0 R +>> +endobj +% JS program to exexute +{{object 31 0}} << +>> +stream +this.getField("MyField").setFocus(); +app.alert("focused"); +endstream +endobj +% Lost Focus AAction MyField +{{object 34 0}} << + /Type /Action + /S /JavaScript + /JS 35 0 R +>> +endobj +% JS program to exexute +{{object 35 0}} << +>> +stream +this.removeField("MyField"); +app.alert("removed"); +endstream +endobj +% Closing Page 0 +{{object 36 0}} << + /Type /Action + /S /JavaScript + /JS 37 0 R +>> +endobj +% JS program to exexute +{{object 37 0}} << +>> +stream +this.removeField("MyField"); +endstream +endobj +{{object 43 0}} << +>>stream + + +endstream +endobj +{{object 49 0}} << +>>stream + + +endstream +endobj +{{object 50 0}} << +>>stream + +endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/javascript/bug_735912_expected.txt b/testing/resources/javascript/bug_735912_expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7d0f42f51739a26fc5b1da3fef21a6289a54d6ef --- /dev/null +++ b/testing/resources/javascript/bug_735912_expected.txt @@ -0,0 +1,2 @@ +Alert: removed +Alert: focused diff --git a/testing/resources/javascript/bug_740166.in b/testing/resources/javascript/bug_740166.in new file mode 100644 index 0000000000000000000000000000000000000000..1e2eb910ff9f9a671f2345805049170d9b393bbd --- /dev/null +++ b/testing/resources/javascript/bug_740166.in @@ -0,0 +1,61 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm 4 0 R + /OpenAction 10 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <> + >> + /Contents [21 0 R] + /MediaBox [0 0 612 792] +>> +% Forms +{{object 4 0}} << + /Fields [5 0 R] +>> +% Field +{{object 5 0}} << + /FT /Tx + /T (MyField) + /Type /Annot + /Subtype /Widget + /Rect [100 200 150 250] +>> +% OpenAction action +{{object 10 0}} << + /Type /Action + /S /JavaScript + /JS 11 0 R +>> +endobj +% JS program to exexute +{{object 11 0}} << +>> +stream +app.alert(util.printf("Values = %0.1x .9999 %x", 1, 2)); +app.alert(util.printf("Values = %0.10x .9999 %x", 1, 2)); +app.alert(util.printf("Values = %0.100x .9999 %x", 1, 2)); +app.alert(util.printf("Values = %0.1000x .9999 %x", 1, 2)); +endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/javascript/bug_740166_expected.txt b/testing/resources/javascript/bug_740166_expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1cece3bff8954b07b9fcab7b1ef0b4e2bf970c4c --- /dev/null +++ b/testing/resources/javascript/bug_740166_expected.txt @@ -0,0 +1,4 @@ +Alert: Values = 1 .9999 2 +Alert: Values = 0000000001 .9999 2 +Alert: Values = %0.100x .9999 2 +Alert: Values = %0.1000x .9999 2 diff --git a/testing/resources/javascript/mouse_events.evt b/testing/resources/javascript/mouse_events.evt new file mode 100644 index 0000000000000000000000000000000000000000..57105063e47e7bc429f5f7542b64da3b848a0af3 --- /dev/null +++ b/testing/resources/javascript/mouse_events.evt @@ -0,0 +1,19 @@ +# Mouse in, mouse out. +mousemove,125,225 +mousemove,125,100 +# Mouse in, click in field. +mousemove,125,225 +mousedown,left,125,225 +mouseup,left,125,225 +# Mouse out, click elsewhere. +# This should trigger an On Blur event. (Bug 881) +mousemove,125,100 +mousedown,left,125,100 +mouseup,left,125,100 +# Mouse in, focus. +mousemove,125,225 +focus,125,225 +# Mouse out, unfocus. +# This should trigger an On Blur event. (Bug 881) +mousemove,125,100 +focus,125,100 diff --git a/testing/resources/javascript/mouse_events.in b/testing/resources/javascript/mouse_events.in new file mode 100644 index 0000000000000000000000000000000000000000..a72162add3fa1ae4b509419b4bd4dde2e0172973 --- /dev/null +++ b/testing/resources/javascript/mouse_events.in @@ -0,0 +1,92 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm 4 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <> + >> + /Annots [ 5 0 R ] + /Contents [21 0 R] + /MediaBox [0 0 612 792] +>> +% Forms +{{object 4 0}} << + /Fields [5 0 R] +>> +% Field with actions: +% Cursor enter: E +% Cursor exit: X +% Mouse down: D +% Mouse up: U +% Focus: Fo +% Blur: Bl +{{object 5 0}} << + /FT /Tx + /T (MyField) + /Type /Annot + /Subtype /Widget + /Rect [100 200 150 250] + /AA << + /E 10 0 R + /X 11 0 R + /D 12 0 R + /U 13 0 R + /Fo 14 0 R + /Bl 15 0 R + >> +>> +{{object 10 0}} << + /Type /Action + /S /JavaScript + /JS (app.alert\("enter"\);) +>> +endobj +{{object 11 0}} << + /Type /Action + /S /JavaScript + /JS (app.alert\("exit"\);) +>> +endobj +{{object 12 0}} << + /Type /Action + /S /JavaScript + /JS (app.alert\("down"\);) +>> +endobj +{{object 13 0}} << + /Type /Action + /S /JavaScript + /JS (app.alert\("up"\);) +>> +endobj +{{object 14 0}} << + /Type /Action + /S /JavaScript + /JS (app.alert\("focus"\);) +>> +endobj +{{object 15 0}} << + /Type /Action + /S /JavaScript + /JS (app.alert\("blur"\);) +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/javascript/mouse_events_expected.txt b/testing/resources/javascript/mouse_events_expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..3d9b8b6071bc4025e84fd060355a74b311905d75 --- /dev/null +++ b/testing/resources/javascript/mouse_events_expected.txt @@ -0,0 +1,10 @@ +Alert: enter +Alert: exit +Alert: enter +Alert: down +Alert: focus +Alert: up +Alert: exit +Alert: enter +Alert: focus +Alert: exit diff --git a/testing/resources/javascript/util_printd.in b/testing/resources/javascript/util_printd.in index f098187cf07ffbe840dc3b0f997b7f300a1e78bf..4d8610d429e5cd8230ed9fc9b5c653f5927c42d0 100644 --- a/testing/resources/javascript/util_printd.in +++ b/testing/resources/javascript/util_printd.in @@ -94,6 +94,38 @@ TestOneFormat({"clams": 3}, d1); TestOneFormat(["clams", 3], d1); TestOneXFAFormat("mm", d1, false); TestOneXFAFormat("mm", d1, true); + +// Date with year 0. +// TODO(thestig): Why is the output different from Acrobat? +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(0, 06, 04, 15, 59, 58)); +// Date with month 20. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 20, 04, 15, 59, 58)); +// Date with day 100. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 20, 100, 15, 59, 58)); +// Date with hour 50 +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, 04, 50, 59, 58)); +// Date with minute 1234. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, 04, 15, 1234, 58)); +// Date with second 65. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, 04, 15, 59, 65)); +// Date with April 31th. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 03, 31, 15, 59, 58)); +// Date with February 30th. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 01, 30, 15, 59, 58)); +// Date with negative year. +// Acrobat prints out "07/04/-001 15:59:58" but handling this rarely used case +// outside of FXSYS_wcsftime() is a lot of work. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(-1, 06, 04, 15, 59, 58)); +// Date with negative month. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, -1, 30, 15, 59, 58)); +// Date with negative day. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, -1, 15, 59, 58)); +// Date with negative hour. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, 04, -1, 59, 58)); +// Date with negative minute. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, 04, 15, -1, 58)); +// Date with negative second. +TestOneFormat("mm/dd/yyyy HH:MM:ss", new Date(2014, 06, 04, 15, 59, -1)); endstream endobj {{xref}} diff --git a/testing/resources/javascript/util_printd_expected.txt b/testing/resources/javascript/util_printd_expected.txt index 47abb2fd4236161c88b38d6207152c569403a8d7..76ede71ee5934e60021022ae464adea5ef28f1f4 100644 --- a/testing/resources/javascript/util_printd_expected.txt +++ b/testing/resources/javascript/util_printd_expected.txt @@ -38,3 +38,17 @@ Alert: [object Object]: Caught error: util.printd: Incorrect parameter type. Alert: clams,3: Caught error: util.printd: Incorrect parameter type. Alert: mm: 07 Alert: mm: Caught error: util.printd: Operation not supported. +Alert: mm/dd/yyyy HH:MM:ss: 07/03/1900 14:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 09/04/2015 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 12/09/2015 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/06/2014 02:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/05/2014 11:34:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 16:00:05 +Alert: mm/dd/yyyy HH:MM:ss: 05/01/2014 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 03/02/2014 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: Caught error: util.printd: Incorrect parameter value. +Alert: mm/dd/yyyy HH:MM:ss: 12/30/2013 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 06/29/2014 15:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/03/2014 23:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 14:59:58 +Alert: mm/dd/yyyy HH:MM:ss: 07/04/2014 15:58:59 diff --git a/testing/resources/launch_action.in b/testing/resources/launch_action.in index c98539f5eaf8d30ddfdbefb683963eb3c99d9b58..00569e4489d2456a69d36da0b65df5cba74171af 100644 --- a/testing/resources/launch_action.in +++ b/testing/resources/launch_action.in @@ -3,6 +3,7 @@ /Type /Catalog /Pages 2 0 R >> +endobj {{object 2 0}} << /Type /Pages /MediaBox [ 0 0 200 200 ] @@ -40,15 +41,13 @@ endobj /F 6 0 R /S /Launch >> +endobj {{object 6 0}} << /F (test.pdf) /Type / Filespec >> endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/launch_action.pdf b/testing/resources/launch_action.pdf index 99a42923deead8813fdc98d454e88200e1f72d91..327c863c7acb07274ed7cc583ed3ba26ed7b7755 100644 --- a/testing/resources/launch_action.pdf +++ b/testing/resources/launch_action.pdf @@ -4,6 +4,7 @@ /Type /Catalog /Pages 2 0 R >> +endobj 2 0 obj << /Type /Pages /MediaBox [ 0 0 200 200 ] @@ -41,6 +42,7 @@ endobj /F 6 0 R /S /Launch >> +endobj 6 0 obj << /F (test.pdf) /Type / Filespec @@ -50,15 +52,12 @@ xref 0 7 0000000000 65535 f 0000000015 00000 n -0000000061 00000 n -0000000154 00000 n -0000000223 00000 n -0000000489 00000 n -0000000527 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +0000000068 00000 n +0000000161 00000 n +0000000230 00000 n +0000000496 00000 n +0000000541 00000 n +trailer<< /Root 1 0 R /Size 7 >> startxref -583 +597 %%EOF diff --git a/testing/resources/linearized.pdf b/testing/resources/linearized.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3c2d3a25a22f6599263283c76d30340fb1aa4db0 Binary files /dev/null and b/testing/resources/linearized.pdf differ diff --git a/testing/resources/marked_content_id.pdf b/testing/resources/marked_content_id.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ddbf11f3193615fc3a50091e6afab927a5c46b6c Binary files /dev/null and b/testing/resources/marked_content_id.pdf differ diff --git a/testing/resources/named_dests.in b/testing/resources/named_dests.in index 5309ee23aabddf4ef057fecfc07d9aa5bea429ca..a97aebe8bf6fc8fe00db2f06187439a8a3abc8bd 100644 --- a/testing/resources/named_dests.in +++ b/testing/resources/named_dests.in @@ -101,9 +101,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/named_dests.pdf b/testing/resources/named_dests.pdf index 2e0e5ce71d69eda4c77fdf79185dd8ab806b6c14..b99cead4ce289c02c4c81bb8a323f2b39f6286c2 100644 --- a/testing/resources/named_dests.pdf +++ b/testing/resources/named_dests.pdf @@ -126,10 +126,7 @@ xref 0000000000 65535 f 0000001283 00000 n 0000001393 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +trailer<< /Root 1 0 R /Size 23 >> startxref 1481 %%EOF diff --git a/testing/resources/pixel/bug_113910.evt b/testing/resources/pixel/bug_113910.evt new file mode 100644 index 0000000000000000000000000000000000000000..ca8821f0062bf3456e362c8880708edc447e3cde --- /dev/null +++ b/testing/resources/pixel/bug_113910.evt @@ -0,0 +1,8 @@ +mousemove,150,120 +mousedown,left,150,120 +mouseup,left,150,120 +charcode,49 +charcode,50 +charcode,51 +charcode,52 +charcode,13 diff --git a/testing/resources/pixel/bug_113910.in b/testing/resources/pixel/bug_113910.in new file mode 100644 index 0000000000000000000000000000000000000000..fdfcc54364544685a789963dfeeb69eb7b71cf9b --- /dev/null +++ b/testing/resources/pixel/bug_113910.in @@ -0,0 +1,66 @@ +{{header}} +{{object 1 0}} +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 4 0 R 10 0 R ] /DR 5 0 R >> +>> +endobj +{{object 2 0}} +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +{{object 3 0}} +<< + /Type /Page + /Parent 2 0 R + /Resources 5 0 R + /MediaBox [ 0 0 300 200 ] + /Contents 8 0 R + /Annots [ 4 0 R 10 0 R ] +>> +endobj +{{object 4 0}} +<< + /Type /Annot + /FT /Tx + /T (Text Box) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget + /AA << /F 9 0 R >> +>> +endobj +{{object 5 0}} +<< /Font 6 0 R >> +endobj +{{object 6 0}} +<< /F1 7 0 R >> +endobj +{{object 7 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 8 0}}<< +>> +stream +endstream +endobj +{{object 9 0}} +<< /JS (AFNumber_Format\(0, 1, 0, 0, "", false\);) /S /JavaScript >> +endobj +{{object 10 0}} +<< + /Type /Annot + /FT /Tx + /T (Text2) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 40 200 70 ] + /Subtype /Widget +>> +endobj +{{xref}} +trailer<< /Root 1 0 R >> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_113910_expected.pdf.0.png b/testing/resources/pixel/bug_113910_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..57c6f087f17f24271a9dbde67715191f644ba8ff Binary files /dev/null and b/testing/resources/pixel/bug_113910_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_113910_expected_mac.pdf.0.png b/testing/resources/pixel/bug_113910_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..5b21f5ab789ece23f44dd32a7d9266fc175322f0 Binary files /dev/null and b/testing/resources/pixel/bug_113910_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_491_invisible.in b/testing/resources/pixel/bug_491_invisible.in new file mode 100644 index 0000000000000000000000000000000000000000..75b7e58c5f322880013311e8b5dbba6ea647280c --- /dev/null +++ b/testing/resources/pixel/bug_491_invisible.in @@ -0,0 +1,75 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OCProperties << + /OCGs [ + 8 0 R + ] + /D << + /BaseState /OFF + >> + >> +>> +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + /Properties << + /OC0 7 0 R + >> + >> + /Contents 6 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 6 0}} << +>> +stream +16 96 32 32 re B +/OC /OC0 BDC +64 96 32 32 re B +EMC +endstream +endobj +{{object 7 0}} << + /OCGs [ + 8 0 R + ] + /Type /OCMD +>> +endobj +{{object 8 0}} << + /Type /OCG + /Name (Show Text) +>> +endobj +{{xref}} +trailer << + /Size 9 + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_491_invisible_expected.pdf.0.png b/testing/resources/pixel/bug_491_invisible_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..067ca22f15907728fd09dfbf595557a39eede67a Binary files /dev/null and b/testing/resources/pixel/bug_491_invisible_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_491_unspecified.in b/testing/resources/pixel/bug_491_unspecified.in new file mode 100644 index 0000000000000000000000000000000000000000..b1e7312935cde5c1e0888d5254fe4ea13427fdee --- /dev/null +++ b/testing/resources/pixel/bug_491_unspecified.in @@ -0,0 +1,74 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OCProperties << + /OCGs [ + 8 0 R + ] + /D << + /BaseState /OFF + >> + >> +>> +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + /Properties << + /OC0 7 0 R + >> + >> + /Contents 6 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 6 0}} << +>> +stream +16 96 32 32 re B +/OC /OC0 BDC +64 96 32 32 re B +EMC +endstream +endobj +{{object 7 0}} << + /OCGs [ + ] + /Type /OCMD +>> +endobj +{{object 8 0}} << + /Type /OCG + /Name (Show Text) +>> +endobj +{{xref}} +trailer << + /Size 9 + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_491_unspecified_expected.pdf.0.png b/testing/resources/pixel/bug_491_unspecified_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..fa1b37c8826a05165f485d2d7b590aeeceaf8c32 Binary files /dev/null and b/testing/resources/pixel/bug_491_unspecified_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_491_visible.in b/testing/resources/pixel/bug_491_visible.in new file mode 100644 index 0000000000000000000000000000000000000000..8e21b6c09bda2b82bbdcef5167d9fb49f904640c --- /dev/null +++ b/testing/resources/pixel/bug_491_visible.in @@ -0,0 +1,75 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OCProperties << + /OCGs [ + 8 0 R + ] + /D << + /BaseState /ON + >> + >> +>> +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + /Properties << + /OC0 7 0 R + >> + >> + /Contents 6 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 6 0}} << +>> +stream +16 96 32 32 re B +/OC /OC0 BDC +64 96 32 32 re B +EMC +endstream +endobj +{{object 7 0}} << + /OCGs [ + 8 0 R + ] + /Type /OCMD +>> +endobj +{{object 8 0}} << + /Type /OCG + /Name (Show Text) +>> +endobj +{{xref}} +trailer << + /Size 9 + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_491_visible_expected.pdf.0.png b/testing/resources/pixel/bug_491_visible_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..fa1b37c8826a05165f485d2d7b590aeeceaf8c32 Binary files /dev/null and b/testing/resources/pixel/bug_491_visible_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_492.pdf.0.png b/testing/resources/pixel/bug_492.pdf.0.png deleted file mode 100644 index adc4b53e0ee3d41c5785375c7c67d3c0e08d4048..0000000000000000000000000000000000000000 Binary files a/testing/resources/pixel/bug_492.pdf.0.png and /dev/null differ diff --git a/testing/resources/pixel/bug_492_expected.pdf.0.png b/testing/resources/pixel/bug_492_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..46b6c9b1f3125a11454bced857822ac01aae09c7 Binary files /dev/null and b/testing/resources/pixel/bug_492_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_1_expected.pdf.0.png b/testing/resources/pixel/bug_524043_1_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_524043_1_expected.pdf.0.png and b/testing/resources/pixel/bug_524043_1_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_1_expected_mac.pdf.0.png b/testing/resources/pixel/bug_524043_1_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_524043_1_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_524043_1_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_2_expected.pdf.0.png b/testing/resources/pixel/bug_524043_2_expected.pdf.0.png index 19de52a360accb8bc96951c1489a79197d3818f3..04304fe59b0daa657ddb08ffc59e53e0060f2d14 100644 Binary files a/testing/resources/pixel/bug_524043_2_expected.pdf.0.png and b/testing/resources/pixel/bug_524043_2_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_2_expected_mac.pdf.0.png b/testing/resources/pixel/bug_524043_2_expected_mac.pdf.0.png index 1136013d885afe9713ea2950e389c0b7ce9f1c4f..ecede7d82c0ad030b6924fefd676e006b888c8cb 100644 Binary files a/testing/resources/pixel/bug_524043_2_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_524043_2_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_3_expected.pdf.0.png b/testing/resources/pixel/bug_524043_3_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_524043_3_expected.pdf.0.png and b/testing/resources/pixel/bug_524043_3_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_3_expected_mac.pdf.0.png b/testing/resources/pixel/bug_524043_3_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_524043_3_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_524043_3_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_4_expected.pdf.0.png b/testing/resources/pixel/bug_524043_4_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_524043_4_expected.pdf.0.png and b/testing/resources/pixel/bug_524043_4_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_4_expected_mac.pdf.0.png b/testing/resources/pixel/bug_524043_4_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_524043_4_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_524043_4_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_5_expected.pdf.0.png b/testing/resources/pixel/bug_524043_5_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_524043_5_expected.pdf.0.png and b/testing/resources/pixel/bug_524043_5_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_5_expected_mac.pdf.0.png b/testing/resources/pixel/bug_524043_5_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_524043_5_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_524043_5_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_7_expected.pdf.0.png b/testing/resources/pixel/bug_524043_7_expected.pdf.0.png index 19de52a360accb8bc96951c1489a79197d3818f3..04304fe59b0daa657ddb08ffc59e53e0060f2d14 100644 Binary files a/testing/resources/pixel/bug_524043_7_expected.pdf.0.png and b/testing/resources/pixel/bug_524043_7_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_524043_7_expected_mac.pdf.0.png b/testing/resources/pixel/bug_524043_7_expected_mac.pdf.0.png index 1136013d885afe9713ea2950e389c0b7ce9f1c4f..ecede7d82c0ad030b6924fefd676e006b888c8cb 100644 Binary files a/testing/resources/pixel/bug_524043_7_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_524043_7_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_528103.in b/testing/resources/pixel/bug_528103.in new file mode 100644 index 0000000000000000000000000000000000000000..9223b0b77a6e24ae94873e7e3e37b148fc23f67d --- /dev/null +++ b/testing/resources/pixel/bug_528103.in @@ -0,0 +1,47 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 500 100 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + >> + >> + /Contents 5 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Arial +>> +endobj +{{object 5 0}} << +>> +stream +BT +150 Tz +100 50 TD /F1 12 Tf [(Intentionally)] TJ +10 0 TD [-5000(Nonoverlapping)] TJ +10 0 TD [-12000(Text)] TJ +ET +endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_528103_expected.pdf.0.png b/testing/resources/pixel/bug_528103_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..5c0c25443b20f546f0649c7de0967cc5531fd030 Binary files /dev/null and b/testing/resources/pixel/bug_528103_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_528103_expected_mac.pdf.0.png b/testing/resources/pixel/bug_528103_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..cb028f9e13982acffa75979c05caed6bcf0b2455 Binary files /dev/null and b/testing/resources/pixel/bug_528103_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_528103_expected_win.pdf.0.png b/testing/resources/pixel/bug_528103_expected_win.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..aca0606af61e58d7d9f5ca88bad601d599f62fa9 Binary files /dev/null and b/testing/resources/pixel/bug_528103_expected_win.pdf.0.png differ diff --git a/testing/resources/pixel/bug_543018_1_expected.pdf.0.png b/testing/resources/pixel/bug_543018_1_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_543018_1_expected.pdf.0.png and b/testing/resources/pixel/bug_543018_1_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_543018_1_expected_mac.pdf.0.png b/testing/resources/pixel/bug_543018_1_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_543018_1_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_543018_1_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_543018_2_expected.pdf.0.png b/testing/resources/pixel/bug_543018_2_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_543018_2_expected.pdf.0.png and b/testing/resources/pixel/bug_543018_2_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_543018_2_expected_mac.pdf.0.png b/testing/resources/pixel/bug_543018_2_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_543018_2_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_543018_2_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_551258_1_expected.pdf.0.png b/testing/resources/pixel/bug_551258_1_expected.pdf.0.png index a044bb0c37a110f6fedd55c188196d9e1e41718d..eabf95737502da5cdff7060ea4cfa2c500a82cf1 100644 Binary files a/testing/resources/pixel/bug_551258_1_expected.pdf.0.png and b/testing/resources/pixel/bug_551258_1_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_551258_1_expected_mac.pdf.0.png b/testing/resources/pixel/bug_551258_1_expected_mac.pdf.0.png index e4d57103ef10d20c329b5163d072c15d8e2dcf31..b85b9d0f9675209b9f2bfa13af1d981c47abab7d 100644 Binary files a/testing/resources/pixel/bug_551258_1_expected_mac.pdf.0.png and b/testing/resources/pixel/bug_551258_1_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_665467.in b/testing/resources/pixel/bug_665467.in new file mode 100644 index 0000000000000000000000000000000000000000..6ef2c1cb822138ac2b1090bd736d29f32726649f --- /dev/null +++ b/testing/resources/pixel/bug_665467.in @@ -0,0 +1,99 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj + +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 100 100 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj + +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources + << + /Font << /F1 4 0 R >> + >> + /Contents 8 0 R +>> +endobj + +{{object 4 0}} << + /Type /Font + /Subtype /TrueType + /BaseFont /ChromeSansMM + /Encoding 5 0 R + /FirstChar 32 + /LastChar 255 + /Name /F1 + /ToUnicode 6 0 R + /FontDescriptor 7 0 R +>> +endobj + +{{object 5 0}} << + /Differences [ 161 /someunknownname ] + /Type /Encoding +>> +endobj + +{{object 6 0}} << +>> +stream +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<> def +/CMapName /Adobe-Identity-H def +CMapType 2 def +1 begincodespacerange +<00> +endcodespacerange +1 beginbfchar + <043B> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +endstream +endobj + +{{object 7 0}} << + << /Ascent 1000 + /CapHeight 0 + /Descent -200 + /Flags 32 + /FontBBox [ -599 -207 1338 1034 ] + /FontName /ChromeSansMM + /ItalicAngle 0 + /StemV 0 + /Type /FontDescriptor +>> +endobj + +{{object 8 0}} << +>> +stream +BT +50 50 Td /F1 15 Tf Tj +ET +endstream +endobj + +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_665467_expected.pdf.0.png b/testing/resources/pixel/bug_665467_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..e3b37b47d241e58a83d4ec3cb647ec0250b1e487 Binary files /dev/null and b/testing/resources/pixel/bug_665467_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_665467_expected_mac.pdf.0.png b/testing/resources/pixel/bug_665467_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..9f51dcb8554aae7df8b89d581474f2b74fdc4551 Binary files /dev/null and b/testing/resources/pixel/bug_665467_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_714187.in b/testing/resources/pixel/bug_714187.in new file mode 100644 index 0000000000000000000000000000000000000000..4ec2395b02cae52a26fecc6d966d5a07999c9ba9 --- /dev/null +++ b/testing/resources/pixel/bug_714187.in @@ -0,0 +1,68 @@ +{{header}} + +{{object 2 0}} << + /Type /Pages + /Rotate 90 + /Kids [ 3 0 R ] + /Count 1 +>> +endobj + +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj + +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /Resources << + /XObject << + /S5 5 0 R + >> + >> +>> +endobj + +{{object 4 0}} << + /Length 187 +>> +stream +q +0 1 -1 0 0 0 cm +1 0 0 -1 0 0 cm +0.072 0 0 0.072 0 0 cm +1 0 0 0.9598603839 0 275 cm +1.0 0 0 1.0 250 850 cm +1.0 0 0 1.0 2283.515625 845.525 cm +0.0005208333 0 0 -0.0005426136 0 0 cm +/S5 Do +Q + +endstream +endobj + +{{object 5 0}} << + /Type /XObject + /Subtype /Form + /FormType 1 + /BBox [ 24320 -704128 524224 -121856 ] + /Length 68 +>> +stream +524213 -411346 m +109719 -121914 24382 -263727 24382 -416322 c +h +f + +endstream +endobj + +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_714187_expected.pdf.0.png b/testing/resources/pixel/bug_714187_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..195dad2d71db2d60aa790445a5e9ca3ff7b7908b Binary files /dev/null and b/testing/resources/pixel/bug_714187_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_718762.in b/testing/resources/pixel/bug_718762.in new file mode 100644 index 0000000000000000000000000000000000000000..3459dc0a1c65c0a523bcbdfdbf7d1b568475ca8f --- /dev/null +++ b/testing/resources/pixel/bug_718762.in @@ -0,0 +1,67 @@ +{{header}} +{{object 1 0}} << + /Type /Pages + /Count 1 + /Kids[ 3 0 R ] +>> +endobj +{{object 2 0}} << + /Type /Catalog + /Pages 1 0 R +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 1 0 R + /Resources 6 0 R + /MediaBox[ 0 0 64 64] + /Contents[ 5 0 R ] +>> +endobj +{{object 4 0}} << + /Type /XObject + /Subtype /Image + /Name /I1 + /Width 5000 + /Height 5000 + /BitsPerComponent 8 + /ColorSpace /DeviceCMYK + /Filter [/ASCIIHexDecode /FlateDecode /DCTDecode] + /Decode [1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0] + /Length 734 +>> +stream +789cedcd3d4ec2001806e00f680529d4165a643671f112c6901095b09838b01983899bd7e02c9ec +2c143f8b37802af50cba81770799eef9ddebcc9d7bc355f515c2faf96d1e974e2b2bd68be23bfd8 +3edd3fc436f69acf5844afdbdda795b44907699a24e9b0df3f188c86a35136ccb2713e29c679996 +759312bca6955d7f5e8e8783eabe693aaae9a97a806d3dd74972c4e625dc6a68c5519cd6bd4ede3 +f8edb0adabe26f1bcd47e4c922d6b18955c4793cdf9ddedc9e3dfe9d01000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000fc835ef +3fe03ce2e1eba +endstream +endobj +{{object 5 0}} << +/Length 28 +>> +stream +q +64 0 0 64 0 0 cm +/I1 Do +Q +endstream +endobj +{{object 6 0}} << + /ProcSet [/PDF /ImageC] + /XObject<> +>> +endobj +{{xref}} +trailer << + /Size 7 + /Root 2 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_718762_expected.pdf.0.png b/testing/resources/pixel/bug_718762_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..73069f23aa28ebb988feb34b84ae212640de9fba Binary files /dev/null and b/testing/resources/pixel/bug_718762_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_733528.in b/testing/resources/pixel/bug_733528.in new file mode 100644 index 0000000000000000000000000000000000000000..3602c3f2b5737956d38c54959f0e45c0a340b514 --- /dev/null +++ b/testing/resources/pixel/bug_733528.in @@ -0,0 +1,72 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /AcroForm << + /Fields [ 4 0 R 9 0 R ] + /DR 5 0 R + /NeedAppearances true + >> +>> +endobj +{{object 2 0}} << + /Count 1 + /Kids [ 3 0 R ] + /Type /Pages +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources 5 0 R + /MediaBox [ 0 0 300 200 ] + /Contents 8 0 R + /Annots [ 4 0 R 9 0 R ] +>> +endobj +{{object 4 0}} << + /Type /Annot + /FT /Tx + /T (SharedField) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget + /V (Hello, world) +>> +endobj +{{object 5 0}} << + /Font 6 0 R +>> +endobj +{{object 6 0}} << + /F1 7 0 R +>> +endobj +{{object 7 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 8 0}} << +>> +stream +endstream +endobj +{{object 9 0}} << + /Type /Annot + /FT /Tx + /T (SharedField) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 40 200 70 ] + /Subtype /Widget + /V () +>> +endobj +{{xref}} +trailer << + /Root 1 0 R + /Size 10 +>> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_733528_expected.pdf.0.png b/testing/resources/pixel/bug_733528_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..eaf48b5d5fedfa0b207c184fb0f846b4a1d1a1a9 Binary files /dev/null and b/testing/resources/pixel/bug_733528_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_733528_expected_mac.pdf.0.png b/testing/resources/pixel/bug_733528_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c8302b1e0a408e7608fd1b604c44877842ef6b Binary files /dev/null and b/testing/resources/pixel/bug_733528_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_736695_1.in b/testing/resources/pixel/bug_736695_1.in new file mode 100644 index 0000000000000000000000000000000000000000..85a6d74c7257e1874b4e627b54dc12fdd315fb6d --- /dev/null +++ b/testing/resources/pixel/bug_736695_1.in @@ -0,0 +1,60 @@ +{{header}} + +{{object 1 0}} +<< + /AcroForm << /Fields [ 9 0 R ] >> + /Pages 22 0 R + /Type /Catalog +>> +endobj + +{{object 9 0}} +<< + /F 4 + /FT /Ch + /Ff 393216 + /Opt [ ] + /P 21 0 R + /Rect [ 165.7 315.9 315.7 330.1 ] + /Subtype /Widget + /T (Country Box) + /Type /Annot +>> +endobj + +{{object 21 0}} +<< + /Annots [ 9 0 R ] + /Contents 49 0 R + /MediaBox [ 0 0 595 342 ] + /Parent 22 0 R + /Type /Page +>> +endobj + +{{object 22 0}} +<< + /Count 1 + /Kids [ 21 0 R ] + /MediaBox [ 0 0 595 842 ] + /Type /Pages +>> +endobj + +{{object 49 0}} +<< /Length 88 >> +stream +0.1 w +0 0 0 RG +1 1 1 rg +q 0 0.1 595.2 841.8 re +W* n +163.1 313.1 155.3 19.9 re B* +Q +endstream +endobj + +{{xref}} +trailer<< /Root 1 0 R >> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_736695_1_expected.pdf.0.png b/testing/resources/pixel/bug_736695_1_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..99d7bd74431776cdc966d19c1aaabb1f0f29867c Binary files /dev/null and b/testing/resources/pixel/bug_736695_1_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_736695_2.evt b/testing/resources/pixel/bug_736695_2.evt new file mode 100644 index 0000000000000000000000000000000000000000..794dbf29aacf526090e67a16d384fde381c40932 --- /dev/null +++ b/testing/resources/pixel/bug_736695_2.evt @@ -0,0 +1,4 @@ +# Open the dropdown to make sure it displays correctly. +mousemove,312,324 +mousedown,left,312,324 +mouseup,left,312,324 diff --git a/testing/resources/pixel/bug_736695_2.in b/testing/resources/pixel/bug_736695_2.in new file mode 100644 index 0000000000000000000000000000000000000000..85a6d74c7257e1874b4e627b54dc12fdd315fb6d --- /dev/null +++ b/testing/resources/pixel/bug_736695_2.in @@ -0,0 +1,60 @@ +{{header}} + +{{object 1 0}} +<< + /AcroForm << /Fields [ 9 0 R ] >> + /Pages 22 0 R + /Type /Catalog +>> +endobj + +{{object 9 0}} +<< + /F 4 + /FT /Ch + /Ff 393216 + /Opt [ ] + /P 21 0 R + /Rect [ 165.7 315.9 315.7 330.1 ] + /Subtype /Widget + /T (Country Box) + /Type /Annot +>> +endobj + +{{object 21 0}} +<< + /Annots [ 9 0 R ] + /Contents 49 0 R + /MediaBox [ 0 0 595 342 ] + /Parent 22 0 R + /Type /Page +>> +endobj + +{{object 22 0}} +<< + /Count 1 + /Kids [ 21 0 R ] + /MediaBox [ 0 0 595 842 ] + /Type /Pages +>> +endobj + +{{object 49 0}} +<< /Length 88 >> +stream +0.1 w +0 0 0 RG +1 1 1 rg +q 0 0.1 595.2 841.8 re +W* n +163.1 313.1 155.3 19.9 re B* +Q +endstream +endobj + +{{xref}} +trailer<< /Root 1 0 R >> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_736695_2_expected.pdf.0.png b/testing/resources/pixel/bug_736695_2_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..33ea077362e6cf56f41e08861f4a6b42564fcb59 Binary files /dev/null and b/testing/resources/pixel/bug_736695_2_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_736695_2_expected_mac.pdf.0.png b/testing/resources/pixel/bug_736695_2_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..46c70854d492d3bc365dd1a02059213c527ae942 Binary files /dev/null and b/testing/resources/pixel/bug_736695_2_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_736695_3.evt b/testing/resources/pixel/bug_736695_3.evt new file mode 100644 index 0000000000000000000000000000000000000000..d64d59102286cedf9b081d040ab0cb13b2f7bbeb --- /dev/null +++ b/testing/resources/pixel/bug_736695_3.evt @@ -0,0 +1,9 @@ +# Open dropdown +mousemove,312,324 +mousedown,left,312,324 +mouseup,left,312,324 + +# Select item +mousemove,312,310 +mousedown,left,312,310 +mouseup,left,312,310 diff --git a/testing/resources/pixel/bug_736695_3.in b/testing/resources/pixel/bug_736695_3.in new file mode 100644 index 0000000000000000000000000000000000000000..85a6d74c7257e1874b4e627b54dc12fdd315fb6d --- /dev/null +++ b/testing/resources/pixel/bug_736695_3.in @@ -0,0 +1,60 @@ +{{header}} + +{{object 1 0}} +<< + /AcroForm << /Fields [ 9 0 R ] >> + /Pages 22 0 R + /Type /Catalog +>> +endobj + +{{object 9 0}} +<< + /F 4 + /FT /Ch + /Ff 393216 + /Opt [ ] + /P 21 0 R + /Rect [ 165.7 315.9 315.7 330.1 ] + /Subtype /Widget + /T (Country Box) + /Type /Annot +>> +endobj + +{{object 21 0}} +<< + /Annots [ 9 0 R ] + /Contents 49 0 R + /MediaBox [ 0 0 595 342 ] + /Parent 22 0 R + /Type /Page +>> +endobj + +{{object 22 0}} +<< + /Count 1 + /Kids [ 21 0 R ] + /MediaBox [ 0 0 595 842 ] + /Type /Pages +>> +endobj + +{{object 49 0}} +<< /Length 88 >> +stream +0.1 w +0 0 0 RG +1 1 1 rg +q 0 0.1 595.2 841.8 re +W* n +163.1 313.1 155.3 19.9 re B* +Q +endstream +endobj + +{{xref}} +trailer<< /Root 1 0 R >> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_736695_3_expected.pdf.0.png b/testing/resources/pixel/bug_736695_3_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..cbffe0a6f6a3cddf9ccbb8b78e6b93b3af7b3582 Binary files /dev/null and b/testing/resources/pixel/bug_736695_3_expected.pdf.0.png differ diff --git a/testing/resources/pixel/bug_736695_3_expected_mac.pdf.0.png b/testing/resources/pixel/bug_736695_3_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..1abcd184f23e0f149361afc28a40c1a3c243214e Binary files /dev/null and b/testing/resources/pixel/bug_736695_3_expected_mac.pdf.0.png differ diff --git a/testing/resources/pixel/bug_736695_4.evt b/testing/resources/pixel/bug_736695_4.evt new file mode 100644 index 0000000000000000000000000000000000000000..af591cb373e170ea71c62ad5c4e5e1c078f0772b --- /dev/null +++ b/testing/resources/pixel/bug_736695_4.evt @@ -0,0 +1,12 @@ +# Open dropdown +mousemove,312,324 +mousedown,left,312,324 +mouseup,left,312,324 + +# Hover item +mousemove,312,310 + +# Select off +mousemove,6,6 +mousedown,left,6,6 +mouseup,left,6,6 diff --git a/testing/resources/pixel/bug_736695_4.in b/testing/resources/pixel/bug_736695_4.in new file mode 100644 index 0000000000000000000000000000000000000000..85a6d74c7257e1874b4e627b54dc12fdd315fb6d --- /dev/null +++ b/testing/resources/pixel/bug_736695_4.in @@ -0,0 +1,60 @@ +{{header}} + +{{object 1 0}} +<< + /AcroForm << /Fields [ 9 0 R ] >> + /Pages 22 0 R + /Type /Catalog +>> +endobj + +{{object 9 0}} +<< + /F 4 + /FT /Ch + /Ff 393216 + /Opt [ ] + /P 21 0 R + /Rect [ 165.7 315.9 315.7 330.1 ] + /Subtype /Widget + /T (Country Box) + /Type /Annot +>> +endobj + +{{object 21 0}} +<< + /Annots [ 9 0 R ] + /Contents 49 0 R + /MediaBox [ 0 0 595 342 ] + /Parent 22 0 R + /Type /Page +>> +endobj + +{{object 22 0}} +<< + /Count 1 + /Kids [ 21 0 R ] + /MediaBox [ 0 0 595 842 ] + /Type /Pages +>> +endobj + +{{object 49 0}} +<< /Length 88 >> +stream +0.1 w +0 0 0 RG +1 1 1 rg +q 0 0.1 595.2 841.8 re +W* n +163.1 313.1 155.3 19.9 re B* +Q +endstream +endobj + +{{xref}} +trailer<< /Root 1 0 R >> +{{startxref}} +%%EOF diff --git a/testing/resources/pixel/bug_736695_4_expected.pdf.0.png b/testing/resources/pixel/bug_736695_4_expected.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..99d7bd74431776cdc966d19c1aaabb1f0f29867c Binary files /dev/null and b/testing/resources/pixel/bug_736695_4_expected.pdf.0.png differ diff --git a/testing/resources/pixel/font_size_expected.pdf.0.png b/testing/resources/pixel/font_size_expected.pdf.0.png index a14df36afe04aad2d9195a544765bbf3e22068a6..b4506e0d2c33523257ea703d62834340969670be 100644 Binary files a/testing/resources/pixel/font_size_expected.pdf.0.png and b/testing/resources/pixel/font_size_expected.pdf.0.png differ diff --git a/testing/resources/pixel/font_size_expected_mac.pdf.0.png b/testing/resources/pixel/font_size_expected_mac.pdf.0.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd06901a4b526c4cb132b921271d7bb34f9c06a Binary files /dev/null and b/testing/resources/pixel/font_size_expected_mac.pdf.0.png differ diff --git a/testing/resources/rectangles.in b/testing/resources/rectangles.in new file mode 100644 index 0000000000000000000000000000000000000000..49932fff2aa842d17ce2d41a50b22fd87235e194 --- /dev/null +++ b/testing/resources/rectangles.in @@ -0,0 +1,42 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 300 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R +>> +endobj +{{object 4 0}} << +>> +stream +q +0 0 0 rg +0 290 10 10 re B* +10 150 50 30 re B* +0 0 1 rg +190 290 10 10 re B* +70 232 50 30 re B* +0 1 0 rg +190 0 10 10 re B* +130 150 50 30 re B* +1 0 0 rg +0 0 10 10 re B* +70 67 50 30 re B* +Q +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/rectangles.pdf b/testing/resources/rectangles.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7bad251ba7e08efc9c383d88518367a6f204cdd6 --- /dev/null +++ b/testing/resources/rectangles.pdf @@ -0,0 +1,50 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 200 300 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R +>> +endobj +4 0 obj << +>> +stream +q +0 0 0 rg +0 290 10 10 re B* +10 150 50 30 re B* +0 0 1 rg +190 290 10 10 re B* +70 232 50 30 re B* +0 1 0 rg +190 0 10 10 re B* +130 150 50 30 re B* +1 0 0 rg +0 0 10 10 re B* +70 67 50 30 re B* +Q +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000230 00000 n +trailer<< /Root 1 0 R /Size 5 >> +startxref +456 +%%EOF diff --git a/testing/resources/repeat_viewer_ref.in b/testing/resources/repeat_viewer_ref.in new file mode 100644 index 0000000000000000000000000000000000000000..09a17f522dfa6604c2288cde8bb7cf18483feac5 --- /dev/null +++ b/testing/resources/repeat_viewer_ref.in @@ -0,0 +1,19 @@ +{{header}} +{{object 1 0}} +<>/ViewerPreferences<< +<>/ViewerPreferences<< +<>/ViewerPreferences<<>> +endobj + +{{object 2 0}} +<> +endobj + +{{object 7 0}} +<> +endobj + +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/repeat_viewer_ref.pdf b/testing/resources/repeat_viewer_ref.pdf new file mode 100644 index 0000000000000000000000000000000000000000..72bd7e484761c4565c79b8831079d1f15c68879e --- /dev/null +++ b/testing/resources/repeat_viewer_ref.pdf @@ -0,0 +1,30 @@ +%PDF-1.7 +% +1 0 obj +<>/ViewerPreferences<< +<>/ViewerPreferences<< +<>/ViewerPreferences<<>> +endobj + +2 0 obj +<> +endobj + +7 0 obj +<> +endobj + +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000183 00000 n +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000000 65535 f +0000000221 00000 n +trailer<< /Root 1 0 R /Size 8 >> +startxref +317 +%%EOF diff --git a/test/xfa_node_caption.pdf b/testing/resources/simple_xfa.pdf similarity index 100% rename from test/xfa_node_caption.pdf rename to testing/resources/simple_xfa.pdf diff --git a/testing/resources/text_form.in b/testing/resources/text_form.in new file mode 100644 index 0000000000000000000000000000000000000000..c30f0bac4ed9042e8cb41abe1f840b960ed48336 --- /dev/null +++ b/testing/resources/text_form.in @@ -0,0 +1,58 @@ +{{header}} +{{object 1 0}} +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 4 0 R ] /DR 5 0 R >> +>> +endobj +{{object 2 0}} +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +{{object 3 0}} +<< + /Type /Page + /Parent 2 0 R + /Resources 5 0 R + /MediaBox [ 0 0 300 300 ] + /Contents 8 0 R + /Annots [ 4 0 R ] +>> +endobj +{{object 4 0}} +<< + /Type /Annot + /FT /Tx + /T (Text Box) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget +>> +endobj +{{object 5 0}} +<< /Font 6 0 R >> +endobj +{{object 6 0}} +<< /F1 7 0 R >> +endobj +{{object 7 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 8 0}} +<< /Length 51 >> +stream +BT +0 0 0 rg +/F1 12 Tf +100 150 Td +(Test Form) Tj +ET +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/text_form.pdf b/testing/resources/text_form.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1f3ab8571c992a1244bd7738b9d190139d4efd9c --- /dev/null +++ b/testing/resources/text_form.pdf @@ -0,0 +1,70 @@ +%PDF-1.7 +% +1 0 obj +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 4 0 R ] /DR 5 0 R >> +>> +endobj +2 0 obj +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +3 0 obj +<< + /Type /Page + /Parent 2 0 R + /Resources 5 0 R + /MediaBox [ 0 0 300 300 ] + /Contents 8 0 R + /Annots [ 4 0 R ] +>> +endobj +4 0 obj +<< + /Type /Annot + /FT /Tx + /T (Text Box) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget +>> +endobj +5 0 obj +<< /Font 6 0 R >> +endobj +6 0 obj +<< /F1 7 0 R >> +endobj +7 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +8 0 obj +<< /Length 51 >> +stream +BT +0 0 0 rg +/F1 12 Tf +100 150 Td +(Test Form) Tj +ET +endstream +endobj +xref +0 9 +0000000000 65535 f +0000000015 00000 n +0000000114 00000 n +0000000173 00000 n +0000000309 00000 n +0000000445 00000 n +0000000478 00000 n +0000000509 00000 n +0000000585 00000 n +trailer<< /Root 1 0 R /Size 9 >> +startxref +685 +%%EOF diff --git a/testing/resources/text_form_multiple.in b/testing/resources/text_form_multiple.in new file mode 100644 index 0000000000000000000000000000000000000000..576e15597cf6a1004b17996cbd20b78e6c97c9d7 --- /dev/null +++ b/testing/resources/text_form_multiple.in @@ -0,0 +1,81 @@ +{{header}} +{{object 1 0}} +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 4 0 R 9 0 R 10 0 R ] /DR 5 0 R >> +>> +endobj +{{object 2 0}} +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +{{object 3 0}} +<< + /Type /Page + /Parent 2 0 R + /Resources 5 0 R + /MediaBox [ 0 0 300 300 ] + /Contents 8 0 R + /Annots [ 4 0 R 9 0 R 10 0 R ] +>> +endobj +{{object 4 0}} +<< + /Type /Annot + /FT /Tx + /T (Text Box) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget +>> +endobj +{{object 5 0}} +<< /Font 6 0 R >> +endobj +{{object 6 0}} +<< /F1 7 0 R >> +endobj +{{object 7 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 8 0}} +<< /Length 51 >> +stream +BT +0 0 0 rg +/F1 12 Tf +100 150 Td +(Test Form) Tj +ET +endstream +endobj +{{object 9 0}} +<< + /Type /Annot + /FT /Tx + /Ff 1 + /T (ReadOnly) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 200 200 230 ] + /Subtype /Widget +>> +endobj +{{object 10 0}} +<< + /Type /Annot + /FT /Tx + /T (CharLimit) + /MaxLen 10 + /DA (0 0 0 rg /F1 12 Tf) + /V (Elephant) + /Rect [ 100 50 200 75 ] + /Subtype /Widget +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/text_form_multiple.pdf b/testing/resources/text_form_multiple.pdf new file mode 100644 index 0000000000000000000000000000000000000000..172ab5e8645c2cd6fa9575a812338dbef9ab9c87 --- /dev/null +++ b/testing/resources/text_form_multiple.pdf @@ -0,0 +1,95 @@ +%PDF-1.7 +% +1 0 obj +<< + /Type /Catalog + /Pages 2 0 R + /AcroForm << /Fields [ 4 0 R 9 0 R 10 0 R ] /DR 5 0 R >> +>> +endobj +2 0 obj +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +3 0 obj +<< + /Type /Page + /Parent 2 0 R + /Resources 5 0 R + /MediaBox [ 0 0 300 300 ] + /Contents 8 0 R + /Annots [ 4 0 R 9 0 R 10 0 R ] +>> +endobj +4 0 obj +<< + /Type /Annot + /FT /Tx + /T (Text Box) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 100 200 130 ] + /Subtype /Widget +>> +endobj +5 0 obj +<< /Font 6 0 R >> +endobj +6 0 obj +<< /F1 7 0 R >> +endobj +7 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +8 0 obj +<< /Length 51 >> +stream +BT +0 0 0 rg +/F1 12 Tf +100 150 Td +(Test Form) Tj +ET +endstream +endobj +9 0 obj +<< + /Type /Annot + /FT /Tx + /Ff 1 + /T (ReadOnly) + /DA (0 0 0 rg /F1 12 Tf) + /Rect [ 100 200 200 230 ] + /Subtype /Widget +>> +endobj +10 0 obj +<< + /Type /Annot + /FT /Tx + /T (CharLimit) + /MaxLen 10 + /DA (0 0 0 rg /F1 12 Tf) + /V (Elephant) + /Rect [ 100 50 200 75 ] + /Subtype /Widget +>> +endobj +xref +0 11 +0000000000 65535 f +0000000015 00000 n +0000000127 00000 n +0000000186 00000 n +0000000335 00000 n +0000000471 00000 n +0000000504 00000 n +0000000535 00000 n +0000000611 00000 n +0000000711 00000 n +0000000855 00000 n +trailer<< /Root 1 0 R /Size 11 >> +startxref +1020 +%%EOF diff --git a/testing/resources/unsupported_feature.in b/testing/resources/unsupported_feature.in new file mode 100644 index 0000000000000000000000000000000000000000..d3080519bfd37c37f7d1329d20d735941638634c --- /dev/null +++ b/testing/resources/unsupported_feature.in @@ -0,0 +1,30 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /Collection /Test +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 3 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <> + >> + /MediaBox [0 0 612 792] + /Tabs /R +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/unsupported_feature.pdf b/testing/resources/unsupported_feature.pdf new file mode 100644 index 0000000000000000000000000000000000000000..eb7ee08fa4eca9e27b2f9b17fa97883feea599e2 --- /dev/null +++ b/testing/resources/unsupported_feature.pdf @@ -0,0 +1,37 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R + /Collection /Test +>> +endobj +2 0 obj << + /Type /Pages + /Count 3 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +3 0 obj << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <> + >> + /MediaBox [0 0 612 792] + /Tabs /R +>> +endobj +xref +0 4 +0000000000 65535 f +0000000015 00000 n +0000000088 00000 n +0000000176 00000 n +trailer<< /Root 1 0 R /Size 4 >> +startxref +310 +%%EOF diff --git a/testing/resources/use_outlines.in b/testing/resources/use_outlines.in index b344143f64ebea1ef974aa5b07216b746adb2784..7b09ff9547373326ad4a82ce36b58b3f27deeaae 100644 --- a/testing/resources/use_outlines.in +++ b/testing/resources/use_outlines.in @@ -4,6 +4,7 @@ /Pages 2 0 R /PageMode /UseOutlines >> +endobj {{object 2 0}} << /Type /Pages /MediaBox [ 0 0 200 200 ] @@ -49,9 +50,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/use_outlines.pdf b/testing/resources/use_outlines.pdf index 371ff4083c9f3a4d818039b68624ad56f59630e0..81b01cabf69b3dc3867cf874e9dad6b1a7893c2e 100644 --- a/testing/resources/use_outlines.pdf +++ b/testing/resources/use_outlines.pdf @@ -5,6 +5,7 @@ /Pages 2 0 R /PageMode /UseOutlines >> +endobj 2 0 obj << /Type /Pages /MediaBox [ 0 0 200 200 ] @@ -53,15 +54,12 @@ xref 0 7 0000000000 65535 f 0000000015 00000 n -0000000086 00000 n -0000000179 00000 n -0000000321 00000 n -0000000399 00000 n -0000000475 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +0000000093 00000 n +0000000186 00000 n +0000000328 00000 n +0000000406 00000 n +0000000482 00000 n +trailer<< /Root 1 0 R /Size 7 >> startxref -596 +603 %%EOF diff --git a/testing/resources/viewer_ref.in b/testing/resources/viewer_ref.in index 62ae372dfe905cc54ddd47d81e1968347894991c..704e9d3a46dddd5358ee09b5097e05b262ad585a 100644 --- a/testing/resources/viewer_ref.in +++ b/testing/resources/viewer_ref.in @@ -49,9 +49,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/viewer_ref.pdf b/testing/resources/viewer_ref.pdf index fb72107b5bf3ee50ec8ffe76a83a43ac1f007785..851ea273e76bbb06ad19834e0112d2115276be7d 100644 --- a/testing/resources/viewer_ref.pdf +++ b/testing/resources/viewer_ref.pdf @@ -73,10 +73,7 @@ xref 0000000000 65535 f 0000000000 65535 f 0000000537 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +trailer<< /Root 1 0 R /Size 22 >> startxref 625 %%EOF diff --git a/testing/resources/weblinks.in b/testing/resources/weblinks.in index ed20b2e6427922dfed89b445bac9211db11f3fe3..818e676e90f1928c24cfa8474b7d6e92dab269a6 100644 --- a/testing/resources/weblinks.in +++ b/testing/resources/weblinks.in @@ -3,6 +3,7 @@ /Type /Catalog /Pages 2 0 R >> +endobj {{object 2 0}} << /Type /Pages /MediaBox [ 0 0 600 600 ] @@ -58,9 +59,6 @@ ET endstream endobj {{xref}} -trailer << - /Size 6 - /Root 1 0 R ->> +{{trailer}} {{startxref}} %%EOF diff --git a/testing/resources/weblinks.pdf b/testing/resources/weblinks.pdf index 0d201a45aa79527648aefc7322cd928249789ad0..2639be85dc22eaae1c9bddc171f705a45609ef79 100644 --- a/testing/resources/weblinks.pdf +++ b/testing/resources/weblinks.pdf @@ -4,6 +4,7 @@ /Type /Catalog /Pages 2 0 R >> +endobj 2 0 obj << /Type /Pages /MediaBox [ 0 0 600 600 ] @@ -62,15 +63,12 @@ xref 0 7 0000000000 65535 f 0000000015 00000 n -0000000061 00000 n -0000000154 00000 n -0000000374 00000 n +0000000068 00000 n +0000000161 00000 n +0000000381 00000 n 0000000000 65535 f -0000000450 00000 n -trailer << - /Size 6 - /Root 1 0 R ->> +0000000457 00000 n +trailer<< /Root 1 0 R /Size 7 >> startxref -963 +970 %%EOF diff --git a/testing/resources/weblinks_across_lines.in b/testing/resources/weblinks_across_lines.in new file mode 100644 index 0000000000000000000000000000000000000000..5771534913a0c31321d4818848709c0247e0ded2 --- /dev/null +++ b/testing/resources/weblinks_across_lines.in @@ -0,0 +1,72 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 600 600 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + >> + /Contents 6 0 R +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 6 0}} << +>> +stream +BT +/F1 12 Tf +50 50 Td +(Hello, world! This is not a link.) Tj +0 50 Td +(Is this http://example.com?) Tj +0 50 Td +(foo a link?) Tj +/F2 14 Tf +0 50 Td +(How about this http://example.com/) Tj +0 50 Td +(foo a link?) Tj +0 50 Td +(Is this http://example.com/test-) Tj +0 50 Td +(foo a link?) Tj +(Is this http://abc.com/test-) Tj +0 50 Td +0 50 Td +(foo a link?) Tj +0 50 Td +(And this http://example.com/) Tj +0 50 Td +(http://www.abc.com a link?) Tj +ET +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/weblinks_across_lines.pdf b/testing/resources/weblinks_across_lines.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b70910d62989329dc83bde8ddd2fceb381a0a6ca --- /dev/null +++ b/testing/resources/weblinks_across_lines.pdf @@ -0,0 +1,82 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 600 600 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + >> + /Contents 6 0 R +>> +endobj +4 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +5 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +6 0 obj << +>> +stream +BT +/F1 12 Tf +50 50 Td +(Hello, world! This is not a link.) Tj +0 50 Td +(Is this http://example.com?) Tj +0 50 Td +(foo a link?) Tj +/F2 14 Tf +0 50 Td +(How about this http://example.com/) Tj +0 50 Td +(foo a link?) Tj +0 50 Td +(Is this http://example.com/test-) Tj +0 50 Td +(foo a link?) Tj +(Is this http://abc.com/test-) Tj +0 50 Td +0 50 Td +(foo a link?) Tj +0 50 Td +(And this http://example.com/) Tj +0 50 Td +(http://www.abc.com a link?) Tj +ET +endstream +endobj +xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000161 00000 n +0000000303 00000 n +0000000381 00000 n +0000000457 00000 n +trailer<< /Root 1 0 R /Size 7 >> +startxref +928 +%%EOF diff --git a/test/barcode_test.pdf b/testing/resources/xfa/barcode_test.pdf similarity index 100% rename from test/barcode_test.pdf rename to testing/resources/xfa/barcode_test.pdf diff --git a/test/dynamic_list_box_allow_multiple_selection.pdf b/testing/resources/xfa/dynamic_list_box_allow_multiple_selection.pdf similarity index 100% rename from test/dynamic_list_box_allow_multiple_selection.pdf rename to testing/resources/xfa/dynamic_list_box_allow_multiple_selection.pdf diff --git a/test/dynamic_password_field_background_fill.pdf b/testing/resources/xfa/dynamic_password_field_background_fill.pdf similarity index 100% rename from test/dynamic_password_field_background_fill.pdf rename to testing/resources/xfa/dynamic_password_field_background_fill.pdf diff --git a/test/dynamic_table_color_and_width.pdf b/testing/resources/xfa/dynamic_table_color_and_width.pdf similarity index 100% rename from test/dynamic_table_color_and_width.pdf rename to testing/resources/xfa/dynamic_table_color_and_width.pdf diff --git a/test/email_recommended.pdf b/testing/resources/xfa/email_recommended.pdf similarity index 100% rename from test/email_recommended.pdf rename to testing/resources/xfa/email_recommended.pdf diff --git a/test/resolve_nodes.pdf b/testing/resources/xfa/resolve_nodes.pdf similarity index 100% rename from test/resolve_nodes.pdf rename to testing/resources/xfa/resolve_nodes.pdf diff --git a/test/standard_symbols.pdf b/testing/resources/xfa/standard_symbols.pdf similarity index 100% rename from test/standard_symbols.pdf rename to testing/resources/xfa/standard_symbols.pdf diff --git a/test/static_list_box_caption.pdf b/testing/resources/xfa/static_list_box_caption.pdf similarity index 100% rename from test/static_list_box_caption.pdf rename to testing/resources/xfa/static_list_box_caption.pdf diff --git a/test/static_password_field_rotate.pdf b/testing/resources/xfa/static_password_field_rotate.pdf similarity index 100% rename from test/static_password_field_rotate.pdf rename to testing/resources/xfa/static_password_field_rotate.pdf diff --git a/testing/resources/xfa/xfa_node_caption.pdf b/testing/resources/xfa/xfa_node_caption.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ef8eb7dcc9767fbf58f21e52edc77d9839924e51 Binary files /dev/null and b/testing/resources/xfa/xfa_node_caption.pdf differ diff --git a/testing/resources/zero_length_stream.in b/testing/resources/zero_length_stream.in new file mode 100644 index 0000000000000000000000000000000000000000..e7203437cc044d25bc0b784c56e8e079eaade91e --- /dev/null +++ b/testing/resources/zero_length_stream.in @@ -0,0 +1,60 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +{{object 2 0}} << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + >> + /Contents [6 0 R 7 0 R] +>> +endobj +{{object 4 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +{{object 5 0}} << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +{{object 6 0}} << + /Filter /FlateDecode + /Length 0 +>> +stream +endstream +endobj +{{object 7 0}} << +>> +stream +BT +20 50 Td +/F1 12 Tf +(Hello, world!) Tj +0 50 Td +/F2 16 Tf +(Goodbye, world!) Tj +ET +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF diff --git a/testing/resources/zero_length_stream.pdf b/testing/resources/zero_length_stream.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1317c3f98a1c06af8783f58eb44493db39b27727 --- /dev/null +++ b/testing/resources/zero_length_stream.pdf @@ -0,0 +1,71 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +2 0 obj << + /Type /Pages + /MediaBox [ 0 0 200 200 ] + /Count 1 + /Kids [ 3 0 R ] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Resources << + /Font << + /F1 4 0 R + /F2 5 0 R + >> + >> + /Contents [6 0 R 7 0 R] +>> +endobj +4 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Times-Roman +>> +endobj +5 0 obj << + /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj +6 0 obj << + /Filter /FlateDecode + /Length 0 +>> +stream +endstream +endobj +7 0 obj << +>> +stream +BT +20 50 Td +/F1 12 Tf +(Hello, world!) Tj +0 50 Td +/F2 16 Tf +(Goodbye, world!) Tj +ET +endstream +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000061 00000 n +0000000154 00000 n +0000000304 00000 n +0000000382 00000 n +0000000458 00000 n +0000000531 00000 n +trailer<< /Root 1 0 R /Size 8 >> +startxref +652 +%%EOF diff --git a/testing/test.gni b/testing/test.gni index b6677d45fc46d62ab61b6e78be6b66f5ddab9a5f..3b9eddc4ee906350349f9a7cc85141385c545c93 100644 --- a/testing/test.gni +++ b/testing/test.gni @@ -15,7 +15,6 @@ template("test") { if (is_android) { import("//build/config/android/config.gni") import("//build/config/android/rules.gni") - import("//build/config/sanitizers/sanitizers.gni") _use_raw_android_executable = defined(invoker.use_raw_android_executable) && invoker.use_raw_android_executable @@ -54,9 +53,12 @@ template("test") { # the default shared_library configs rather than executable configs. configs -= [ "//build/config:shared_library_config", - "//build/config/android:hide_native_jni_exports", + "//build/config/android:hide_all_but_jni_onload", + ] + configs += [ + "//build/config:executable_config", + "//build/config/android:hide_all_but_jni", ] - configs += [ "//build/config:executable_config" ] # Don't output to the root or else conflict with the group() below. output_name = rebase_path(_exec_output, root_out_dir) @@ -185,15 +187,6 @@ template("test") { deps += [ ":$_apk_target" ] } } - - # TODO(GYP_GONE): Delete this after we've converted everything to GN. - # The _run targets exist only for compatibility w/ GYP. - group("${target_name}_apk_run") { - testonly = true - deps = [ - ":${invoker.target_name}", - ] - } } else if (is_ios) { import("//build/config/ios/rules.gni") @@ -237,11 +230,7 @@ template("test") { if (!defined(deps)) { deps = [] } - deps += [ - # All shared libraries must have the sanitizer deps to properly link in - # asan mode (this target will be empty in other cases). - "//build/config/sanitizers:deps", - ] + deps += [ "//build/config:exe_and_shlib_deps" ] if (!defined(bundle_deps)) { bundle_deps = [] } @@ -254,24 +243,13 @@ template("test") { testonly = true deps += [ - # All shared libraries must have the sanitizer deps to properly link in - # asan mode (this target will be empty in other cases). - "//build/config/sanitizers:deps", + "//build/config:exe_and_shlib_deps", # Give tests the default manifest on Windows (a no-op elsewhere). "//build/win:default_exe_manifest", ] } - # TODO(GYP_GONE): Delete this after we've converted everything to GN. - # The _run targets exist only for compatibility with GYP. - group("${target_name}_run") { - testonly = true - deps = [ - ":${invoker.target_name}", - ] - } - if (defined(invoker.output_name) && target_name != invoker.output_name) { group("${invoker.output_name}_run") { testonly = true diff --git a/testing/test_support.cpp b/testing/test_support.cpp index a530b3ea4c401724389943c4256979f2afc8a050..b32ec7de965398621f8e9350296b2c55b0fccc44 100644 --- a/testing/test_support.cpp +++ b/testing/test_support.cpp @@ -7,12 +7,14 @@ #include #include -#include - +#include "core/fdrm/crypto/fx_crypt.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_string.h" #include "testing/utils/path_service.h" #ifdef PDF_ENABLE_V8 #include "v8/include/libplatform/libplatform.h" +#include "v8/include/v8.h" #endif namespace { @@ -102,6 +104,12 @@ std::unique_ptr GetFileContents(const char* filename, return buffer; } +std::string GetPlatformString(FPDF_WIDESTRING wstr) { + WideString wide_string = + WideString::FromUTF16LE(wstr, WideString::WStringLength(wstr)); + return std::string(wide_string.UTF8Encode().c_str()); +} + std::wstring GetPlatformWString(FPDF_WIDESTRING wstr) { if (!wstr) return nullptr; @@ -149,6 +157,24 @@ std::unique_ptr GetFPDFWideString( return result; } +std::string CryptToBase16(const uint8_t* digest) { + static char const zEncode[] = "0123456789abcdef"; + std::string ret; + ret.resize(32); + for (int i = 0, j = 0; i < 16; i++, j += 2) { + uint8_t a = digest[i]; + ret[j] = zEncode[(a >> 4) & 0xf]; + ret[j + 1] = zEncode[a & 0xf]; + } + return ret; +} + +std::string GenerateMD5Base16(const uint8_t* data, uint32_t size) { + uint8_t digest[16]; + CRYPT_MD5Generate(data, size, digest); + return CryptToBase16(digest); +} + #ifdef PDF_ENABLE_V8 #ifdef V8_USE_EXTERNAL_STARTUP_DATA bool InitializeV8ForPDFium(const std::string& exe_path, @@ -192,21 +218,3 @@ int TestLoader::GetBlock(void* param, memcpy(pBuf, pLoader->m_pBuf + pos, size); return 1; } - -TestSaver::TestSaver() { - FPDF_FILEWRITE::version = 1; - FPDF_FILEWRITE::WriteBlock = WriteBlockCallback; -} - -void TestSaver::ClearString() { - m_String.clear(); -} - -// static -int TestSaver::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite, - const void* data, - unsigned long size) { - TestSaver* pThis = static_cast(pFileWrite); - pThis->m_String.append(static_cast(data), size); - return 1; -} diff --git a/testing/test_support.h b/testing/test_support.h index 4111ca61ed625d37a061a698a0e7b2e34474fcff..ec4b4aeacb703c75709d0d1d17739f0357fde0ff 100644 --- a/testing/test_support.h +++ b/testing/test_support.h @@ -6,46 +6,47 @@ #define TESTING_TEST_SUPPORT_H_ #include + #include #include #include -#include "public/fpdf_save.h" #include "public/fpdfview.h" -#ifdef PDF_ENABLE_V8 -#include "v8/include/v8.h" -#endif // PDF_ENABLE_V8 +#if PDF_ENABLE_XFA +#include "xfa/fgas/font/cfgas_fontmgr.h" +#endif // PDF_ENABLE_XFA namespace pdfium { -#define STR_IN_TEST_CASE(input_literal, ...) \ - { \ - (const unsigned char*) input_literal, sizeof(input_literal) - 1, \ - __VA_ARGS__ \ +#define STR_IN_TEST_CASE(input_literal, ...) \ + { \ + reinterpret_cast(input_literal), \ + sizeof(input_literal) - 1, __VA_ARGS__ \ } -#define STR_IN_OUT_CASE(input_literal, expected_literal, ...) \ - { \ - (const unsigned char*) input_literal, sizeof(input_literal) - 1, \ - (const unsigned char*)expected_literal, sizeof(expected_literal) - 1, \ - __VA_ARGS__ \ +#define STR_IN_OUT_CASE(input_literal, expected_literal, ...) \ + { \ + reinterpret_cast(input_literal), \ + sizeof(input_literal) - 1, \ + reinterpret_cast(expected_literal), \ + sizeof(expected_literal) - 1, __VA_ARGS__ \ } struct StrFuncTestData { const unsigned char* input; - unsigned int input_size; + uint32_t input_size; const unsigned char* expected; - unsigned int expected_size; + uint32_t expected_size; }; struct DecodeTestData { const unsigned char* input; - unsigned int input_size; + uint32_t input_size; const unsigned char* expected; - unsigned int expected_size; + uint32_t expected_size; // The size of input string being processed. - unsigned int processed_size; + uint32_t processed_size; }; struct NullTermWstrFuncTestData { @@ -66,17 +67,30 @@ std::unique_ptr GetFileContents(const char* filename, std::vector StringSplit(const std::string& str, char delimiter); +// Converts a FPDF_WIDESTRING to a std::string. +// Deals with differences between UTF16LE and UTF8. +std::string GetPlatformString(FPDF_WIDESTRING wstr); + // Converts a FPDF_WIDESTRING to a std::wstring. // Deals with differences between UTF16LE and wchar_t. -std::wstring GetPlatformWString(const FPDF_WIDESTRING wstr); +std::wstring GetPlatformWString(FPDF_WIDESTRING wstr); // Returns a newly allocated FPDF_WIDESTRING. // Deals with differences between UTF16LE and wchar_t. std::unique_ptr GetFPDFWideString( const std::wstring& wstr); +std::string CryptToBase16(const uint8_t* digest); +std::string GenerateMD5Base16(const uint8_t* data, uint32_t size); + #ifdef PDF_ENABLE_V8 +namespace v8 { +class Platform; +} #ifdef V8_USE_EXTERNAL_STARTUP_DATA +namespace v8 { +class StartupData; +} bool InitializeV8ForPDFium(const std::string& exe_path, const std::string& bin_dir, v8::StartupData* natives_blob, @@ -101,19 +115,8 @@ class TestLoader { const size_t m_Len; }; -class TestSaver : public FPDF_FILEWRITE { - public: - TestSaver(); - - void ClearString(); - const std::string& GetString() const { return m_String; } - - private: - static int WriteBlockCallback(FPDF_FILEWRITE* pFileWrite, - const void* data, - unsigned long size); - - std::string m_String; -}; +#if PDF_ENABLE_XFA +CFGAS_FontMgr* GetGlobalFontManager(); +#endif // PDF_ENABLE_XFA #endif // TESTING_TEST_SUPPORT_H_ diff --git a/testing/tools/__init__.py b/testing/tools/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/testing/tools/api_check.py b/testing/tools/api_check.py new file mode 100755 index 0000000000000000000000000000000000000000..ee769bcda5b61cc34ec51fc1fb6d065bfaf8d72a --- /dev/null +++ b/testing/tools/api_check.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# Copyright 2017 The 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. + +"""Verifies exported functions in public/*.h are in fpdfview_c_api_test.c. + +This script gathers a list of functions from public/*.h that contain +FPDF_EXPORT. It then gathers a list of functions from +fpdfsdk/fpdfview_c_api_test.c. It then verifies both lists do not contain +duplicates, and they match each other. + +""" + +import os +import re +import sys + +def _IsValidFunctionName(function, filename): + if function.startswith('FPDF'): + return True + if function == 'FSDK_SetUnSpObjProcessHandler' and filename == 'fpdf_ext.h': + return True + if function.startswith('FORM_') and filename == 'fpdf_formfill.h': + return True + return False + + +def _FindFunction(function_snippet, filename): + function_split = function_snippet.split('(') + assert len(function_split) == 2 + function = function_split[0] + assert _IsValidFunctionName(function, filename) + return function + + +def _GetExportsFromHeader(dirname, filename): + with open(os.path.join(dirname, filename)) as f: + contents = f.readlines() + look_for_function_name = False + functions = [] + for line in contents: + if look_for_function_name: + look_for_function_name = False + split_line = line.rstrip().split(' ') + functions.append(_FindFunction(split_line[0], filename)) + continue + + if not line.startswith('FPDF_EXPORT '): + continue + + # Format should be: FPDF_EXPORT return_type FPDF_CALLCONV + split_line = line.rstrip().split(' ') + callconv_index = split_line.index('FPDF_CALLCONV') + assert callconv_index >= 2 + if callconv_index + 1 == len(split_line): + look_for_function_name = True + continue + + functions.append(_FindFunction(split_line[callconv_index + 1], filename)) + return functions + + +def _GetFunctionsFromPublicHeaders(src_path): + public_path = os.path.join(src_path, 'public') + functions = [] + for filename in os.listdir(public_path): + if filename.endswith('.h'): + functions.extend(_GetExportsFromHeader(public_path, filename)) + return functions + + +def _GetFunctionsFromTest(api_test_path): + chk_regex = re.compile('^ CHK\((.*)\);\n$') + with open(api_test_path) as f: + contents = f.readlines() + functions = [] + for line in contents: + match = chk_regex.match(line) + if match: + functions.append(match.groups()[0]) + return functions + + +def _FindDuplicates(functions): + return set([f for f in functions if functions.count(f) > 1]) + + +def _CheckAndPrintFailures(failure_list, failure_message): + if not failure_list: + return True + + print '%s:' % failure_message + for f in sorted(failure_list): + print f + return False + + +def main(): + script_abspath = os.path.abspath(__file__) + src_path = os.path.dirname(os.path.dirname(os.path.dirname(script_abspath))) + public_functions = _GetFunctionsFromPublicHeaders(src_path) + + api_test_relative_path = os.path.join('fpdfsdk', 'fpdfview_c_api_test.c') + api_test_path = os.path.join(src_path, api_test_relative_path) + test_functions = _GetFunctionsFromTest(api_test_path) + + result = True + duplicate_public_functions = _FindDuplicates(public_functions) + check = _CheckAndPrintFailures(duplicate_public_functions, + 'Found duplicate functions in public headers') + result = result and check + + duplicate_test_functions = _FindDuplicates(test_functions) + check = _CheckAndPrintFailures(duplicate_test_functions, + 'Found duplicate functions in API test') + result = result and check + + public_functions_set = set(public_functions) + test_functions_set = set(test_functions) + not_tested = public_functions_set.difference(test_functions_set) + check = _CheckAndPrintFailures(not_tested, 'Functions not tested') + result = result and check + non_existent = test_functions_set.difference(public_functions_set) + check = _CheckAndPrintFailures(non_existent, 'Tested functions do not exist') + result = result and check + + if not result: + print ('Some checks failed. Make sure %s is in sync with the public API ' + 'headers.' + % api_test_relative_path); + return 1 + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/testing/tools/common.py b/testing/tools/common.py index b6e4a7d62e896d08c29ad028c5f47c41be03641b..fc1600421059ad44ea594fdeee02c997222d72ef 100755 --- a/testing/tools/common.py +++ b/testing/tools/common.py @@ -3,8 +3,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import datetime import glob import os +import re import subprocess import sys @@ -25,6 +27,38 @@ def RunCommand(cmd): except subprocess.CalledProcessError as e: return e + +def RunCommandPropagateErr(cmd, stdout_has_errors=False, + exit_status_on_error=None): + """Run a command as a subprocess. + + Errors in that subprocess are printed out if it returns an error exit code. + + Args: + cmd: Command to run as a list of strings. + stdout_has_errors: Whether to print stdout instead of stderr on an error + exit. + exit_status_on_error: If specified, upon an error in the subprocess the + caller script exits immediately with the given status. + """ + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, err = p.communicate() + + if p.returncode: + PrintErr('\nError when invoking "%s"' % ' '.join(cmd)) + if stdout_has_errors: + PrintErr(output) + + PrintErr(err) + + if exit_status_on_error is not None: + sys.exit(exit_status_on_error) + + return None + + return output + + # RunCommandExtractHashedFiles returns a tuple: (raised_exception, hashed_files) # It runs the given command. If it fails it will return an exception and None. # If it succeeds it will return None and the list of processed files extracted @@ -96,3 +130,27 @@ class DirectoryFinder: if other_components: result = os.path.join(result, other_components) return result + + +def GetBooleanGnArg(arg_name, build_dir, verbose=False): + '''Extract the value of a boolean flag in args.gn''' + cwd = os.getcwd() + os.chdir(build_dir) + gn_args_output = subprocess.check_output( + ['gn', 'args', '.', '--list=%s' % arg_name, '--short']) + os.chdir(cwd) + arg_match_output = re.search('%s = (.*)' % arg_name, gn_args_output).group(1) + if verbose: + print >> sys.stderr, "Found '%s' for value of %s" % (arg_match_output, arg) + return arg_match_output == 'true' + + +def PrintWithTime(s): + """Prints s prepended by a timestamp.""" + print '[%s] %s' % (datetime.datetime.now().strftime("%Y%m%d %H:%M:%S"), + s) + + +def PrintErr(s): + """Prints s to stderr.""" + print >> sys.stderr, s diff --git a/testing/tools/coverage/coverage_report.py b/testing/tools/coverage/coverage_report.py new file mode 100755 index 0000000000000000000000000000000000000000..95c88bf61273edefc9b463b86dab3a15a747bd4e --- /dev/null +++ b/testing/tools/coverage/coverage_report.py @@ -0,0 +1,393 @@ +#!/usr/bin/env python +# Copyright 2017 The 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. + +"""Generates a coverage report for given binaries using llvm-gcov & lcov. + +Requires llvm-cov 3.5 or later. +Requires lcov 1.11 or later. +Requires that 'use_coverage = true' is set in args.gn. +""" + +import argparse +from collections import namedtuple +import os +import pprint +import re +import subprocess +import sys + + +# Add src dir to path to avoid having to set PYTHONPATH. +sys.path.append( + os.path.abspath( + os.path.join( + os.path.dirname(__file__), + os.path.pardir, + os.path.pardir, + os.path.pardir))) + +from testing.tools.common import GetBooleanGnArg + + +# 'binary' is the file that is to be run for the test. +# 'use_test_runner' indicates if 'binary' depends on test_runner.py and thus +# requires special handling. +TestSpec = namedtuple('TestSpec', 'binary, use_test_runner') + +# All of the coverage tests that the script knows how to run. +COVERAGE_TESTS = { + 'pdfium_unittests': TestSpec('pdfium_unittests', False), + 'pdfium_embeddertests': TestSpec('pdfium_embeddertests', False), + 'corpus_tests': TestSpec('run_corpus_tests.py', True), + 'javascript_tests': TestSpec('run_javascript_tests.py', True), + 'pixel_tests': TestSpec('run_pixel_tests.py', True), +} + +# Coverage tests that are known to take a long time to run, so are not in the +# default set. The user must either explicitly invoke these tests or pass in +# --slow. +SLOW_TESTS = ['corpus_tests', 'javascript_tests', 'pixel_tests'] + +class CoverageExecutor(object): + + def __init__(self, parser, args): + """Initialize executor based on the current script environment + + Args: + parser: argparse.ArgumentParser for handling improper inputs. + args: Dictionary of arguments passed into the calling script. + """ + self.dry_run = args['dry_run'] + self.verbose = args['verbose'] + + llvm_cov = self.determine_proper_llvm_cov() + if not llvm_cov: + print 'Unable to find appropriate llvm-cov to use' + sys.exit(1) + self.lcov_env = os.environ + self.lcov_env['LLVM_COV_BIN'] = llvm_cov + + self.lcov = self.determine_proper_lcov() + if not self.lcov: + print 'Unable to find appropriate lcov to use' + sys.exit(1) + + self.coverage_files = set() + self.source_directory = args['source_directory'] + if not os.path.isdir(self.source_directory): + parser.error("'%s' needs to be a directory" % self.source_directory) + + self.build_directory = args['build_directory'] + if not os.path.isdir(self.build_directory): + parser.error("'%s' needs to be a directory" % self.build_directory) + + self.coverage_tests = self.calculate_coverage_tests(args) + if not self.coverage_tests: + parser.error( + 'No valid tests in set to be run. This is likely due to bad command ' + 'line arguments') + + if not GetBooleanGnArg('use_coverage', self.build_directory, self.verbose): + parser.error( + 'use_coverage does not appear to be set to true for build, but is ' + 'needed') + + self.use_goma = GetBooleanGnArg('use_goma', self.build_directory, + self.verbose) + + self.output_directory = args['output_directory'] + if not os.path.exists(self.output_directory): + if not self.dry_run: + os.makedirs(self.output_directory) + elif not os.path.isdir(self.output_directory): + parser.error('%s exists, but is not a directory' % self.output_directory) + self.coverage_totals_path = os.path.join(self.output_directory, + 'pdfium_totals.info') + + def check_output(self, args, dry_run=False, env=None): + """Dry run aware wrapper of subprocess.check_output()""" + if dry_run: + print "Would have run '%s'" % ' '.join(args) + return '' + + output = subprocess.check_output(args, env=env) + + if self.verbose: + print "check_output(%s) returned '%s'" % (args, output) + return output + + def call(self, args, dry_run=False, env=None): + """Dry run aware wrapper of subprocess.call()""" + if dry_run: + print "Would have run '%s'" % ' '.join(args) + return 0 + + output = subprocess.call(args, env=env) + + if self.verbose: + print 'call(%s) returned %s' % (args, output) + return output + + def call_lcov(self, args, dry_run=False, needs_directory=True): + """Wrapper to call lcov that adds appropriate arguments as needed.""" + lcov_args = [ + self.lcov, '--config-file', + os.path.join(self.source_directory, 'testing', 'tools', 'coverage', + 'lcovrc'), + '--gcov-tool', + os.path.join(self.source_directory, 'testing', 'tools', 'coverage', + 'llvm-gcov') + ] + if needs_directory: + lcov_args.extend(['--directory', self.source_directory]) + if not self.verbose: + lcov_args.append('--quiet') + lcov_args.extend(args) + return self.call(lcov_args, dry_run=dry_run, env=self.lcov_env) + + def calculate_coverage_tests(self, args): + """Determine which tests should be run.""" + testing_tools_directory = os.path.join(self.source_directory, 'testing', + 'tools') + coverage_tests = {} + for name in COVERAGE_TESTS.keys(): + test_spec = COVERAGE_TESTS[name] + if test_spec.use_test_runner: + binary_path = os.path.join(testing_tools_directory, test_spec.binary) + else: + binary_path = os.path.join(self.build_directory, test_spec.binary) + coverage_tests[name] = TestSpec(binary_path, test_spec.use_test_runner) + + if args['tests']: + return {name: spec + for name, spec in coverage_tests.iteritems() if name in args['tests']} + elif not args['slow']: + return {name: spec + for name, spec in coverage_tests.iteritems() if name not in SLOW_TESTS} + else: + return coverage_tests + + def find_acceptable_binary(self, binary_name, version_regex, + min_major_version, min_minor_version): + """Find the newest version of binary that meets the min version.""" + min_version = (min_major_version, min_minor_version) + parsed_versions = {} + # When calling Bash builtins like this the command and arguments must be + # passed in as a single string instead of as separate list members. + potential_binaries = self.check_output( + ['bash', '-c', 'compgen -abck %s' % binary_name]).splitlines() + for binary in potential_binaries: + if self.verbose: + print 'Testing llvm-cov binary, %s' % binary + # Assuming that scripts that don't respond to --version correctly are not + # valid binaries and just happened to get globbed in. This is true for + # lcov and llvm-cov + try: + version_output = self.check_output([binary, '--version']).splitlines() + except subprocess.CalledProcessError: + if self.verbose: + print '--version returned failure status 1, so ignoring' + continue + + for line in version_output: + matcher = re.match(version_regex, line) + if matcher: + parsed_version = (int(matcher.group(1)), int(matcher.group(2))) + if parsed_version >= min_version: + parsed_versions[parsed_version] = binary + break + + if not parsed_versions: + return None + return parsed_versions[max(parsed_versions)] + + def determine_proper_llvm_cov(self): + """Find a version of llvm_cov that will work with the script.""" + version_regex = re.compile('.*LLVM version ([\d]+)\.([\d]+).*') + return self.find_acceptable_binary('llvm-cov', version_regex, 3, 5) + + def determine_proper_lcov(self): + """Find a version of lcov that will work with the script.""" + version_regex = re.compile('.*LCOV version ([\d]+)\.([\d]+).*') + return self.find_acceptable_binary('lcov', version_regex, 1, 11) + + def build_binaries(self): + """Build all the binaries that are going to be needed for coverage + generation.""" + call_args = ['ninja'] + if self.use_goma: + call_args.extend(['-j', '250']) + call_args.extend(['-C', self.build_directory]) + return self.call(call_args, dry_run=self.dry_run) == 0 + + def generate_coverage(self, name, spec): + """Generate the coverage data for a test + + Args: + name: Name associated with the test to be run. This is used as a label + in the coverage data, so should be unique across all of the tests + being run. + spec: Tuple containing the path to the binary to run, and if this test + uses test_runner.py. + """ + if self.verbose: + print "Generating coverage for test '%s', using data '%s'" % (name, spec) + if not os.path.exists(spec.binary): + print('Unable to generate coverage for %s, since it appears to not exist' + ' @ %s') % (name, spec.binary) + return False + + if self.call_lcov(['--zerocounters'], dry_run=self.dry_run): + print 'Unable to clear counters for %s' % name + return False + + binary_args = [spec.binary] + if spec.use_test_runner: + # Test runner performs multi-threading in the wrapper script, not the test + # binary, so need -j 1, otherwise multiple processes will be writing to + # the code coverage files, invalidating results. + # TODO(pdfium:811): Rewrite how test runner tests work, so that they can + # be run in multi-threaded mode. + binary_args.extend(['-j', '1', '--build-dir', self.build_directory]) + if self.call(binary_args, dry_run=self.dry_run) and self.verbose: + print('Running %s appears to have failed, which might affect ' + 'results') % spec.binary + + output_raw_path = os.path.join(self.output_directory, '%s_raw.info' % name) + if self.call_lcov( + ['--capture', '--test-name', name, '--output-file', output_raw_path], + dry_run=self.dry_run): + print 'Unable to capture coverage data for %s' % name + return False + + output_filtered_path = os.path.join(self.output_directory, + '%s_filtered.info' % name) + output_filters = [ + '/usr/include/*', '*third_party*', '*testing*', '*_unittest.cpp', + '*_embeddertest.cpp' + ] + if self.call_lcov( + ['--remove', output_raw_path] + output_filters + + ['--output-file', output_filtered_path], + dry_run=self.dry_run, + needs_directory=False): + print 'Unable to filter coverage data for %s' % name + return False + + self.coverage_files.add(output_filtered_path) + return True + + def merge_coverage(self): + """Merge all of the coverage data sets into one for report generation.""" + merge_args = [] + for coverage_file in self.coverage_files: + merge_args.extend(['--add-tracefile', coverage_file]) + + merge_args.extend(['--output-file', self.coverage_totals_path]) + return self.call_lcov( + merge_args, dry_run=self.dry_run, needs_directory=False) == 0 + + def generate_report(self): + """Produce HTML coverage report based on combined coverage data set.""" + config_file = os.path.join( + self.source_directory, 'testing', 'tools', 'coverage', 'lcovrc') + + lcov_args = ['genhtml', + '--config-file', config_file, + '--legend', + '--demangle-cpp', + '--show-details', + '--prefix', self.source_directory, + '--ignore-errors', + 'source', self.coverage_totals_path, + '--output-directory', self.output_directory] + return self.call(lcov_args, dry_run=self.dry_run) == 0 + + def run(self): + """Setup environment, execute the tests and generate coverage report""" + if not self.build_binaries(): + print 'Failed to successfully build binaries' + return False + + for name in self.coverage_tests.keys(): + if not self.generate_coverage(name, self.coverage_tests[name]): + print 'Failed to successfully generate coverage data' + return False + + if not self.merge_coverage(): + print 'Failed to successfully merge generated coverage data' + return False + + if not self.generate_report(): + print 'Failed to successfully generated coverage report' + return False + + return True + + +def main(): + parser = argparse.ArgumentParser() + parser.formatter_class = argparse.RawDescriptionHelpFormatter + parser.description = ('Generates a coverage report for given binaries using ' + 'llvm-cov & lcov.\n\n' + 'Requires llvm-cov 3.5 or later.\n' + 'Requires lcov 1.11 or later.\n\n' + 'By default runs pdfium_unittests and ' + 'pdfium_embeddertests. If --slow is passed in then all ' + 'tests will be run. If any of the tests are specified ' + 'on the command line, then only those will be run.') + parser.add_argument( + '-s', + '--source_directory', + help='Location of PDFium source directory, defaults to CWD', + default=os.getcwd()) + build_default = os.path.join('out', 'Coverage') + parser.add_argument( + '-b', + '--build_directory', + help= + 'Location of PDFium build directory with coverage enabled, defaults to ' + '%s under CWD' % build_default, + default=os.path.join(os.getcwd(), build_default)) + output_default = 'coverage_report' + parser.add_argument( + '-o', + '--output_directory', + help='Location to write out coverage report to, defaults to %s under CWD ' + % output_default, + default=os.path.join(os.getcwd(), output_default)) + parser.add_argument( + '-n', + '--dry-run', + help='Output commands instead of executing them', + action='store_true') + parser.add_argument( + '-v', + '--verbose', + help='Output additional diagnostic information', + action='store_true') + parser.add_argument( + '--slow', + help='Run all tests, even those known to take a long time. Ignored if ' + 'specific tests are passed in.', + action='store_true') + parser.add_argument( + 'tests', + help='Tests to be run, defaults to all. Valid entries are %s' % + COVERAGE_TESTS.keys(), + nargs='*') + + args = vars(parser.parse_args()) + if args['verbose']: + pprint.pprint(args) + + executor = CoverageExecutor(parser, args) + if executor.run(): + return 0 + return 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/testing/tools/coverage/lcovrc b/testing/tools/coverage/lcovrc new file mode 100644 index 0000000000000000000000000000000000000000..d2d39d75da0037639eeb368684e18b10806dcd45 --- /dev/null +++ b/testing/tools/coverage/lcovrc @@ -0,0 +1,156 @@ +# Specify an external style sheet file (same as --css-file option of genhtml) +#genhtml_css_file = gcov.css + +# Specify coverage rate limits (in %) for classifying file entries +# HI: hi_limit <= rate <= 100 graph color: green +# MED: med_limit <= rate < hi_limit graph color: orange +# LO: 0 <= rate < med_limit graph color: red +genhtml_hi_limit = 80 +genhtml_med_limit = 50 + +# Width of line coverage field in source code view +genhtml_line_field_width = 12 + +# Width of branch coverage field in source code view +genhtml_branch_field_width = 16 + +# Width of overview image (used by --frames option of genhtml) +genhtml_overview_width = 80 + +# Resolution of overview navigation: this number specifies the maximum +# difference in lines between the position a user selected from the overview +# and the position the source code window is scrolled to (used by --frames +# option of genhtml) +genhtml_nav_resolution = 4 + +# Clicking a line in the overview image should show the source code view at +# a position a bit further up so that the requested line is not the first +# line in the window. This number specifies that offset in lines (used by +# --frames option of genhtml) +genhtml_nav_offset = 10 + +# Do not remove unused test descriptions if non-zero (same as +# --keep-descriptions option of genhtml) +genhtml_keep_descriptions = 0 + +# Do not remove prefix from directory names if non-zero (same as --no-prefix +# option of genhtml) +genhtml_no_prefix = 0 + +# Do not create source code view if non-zero (same as --no-source option of +# genhtml) +genhtml_no_source = 0 + +# Replace tabs with number of spaces in source view (same as --num-spaces +# option of genhtml) +genhtml_num_spaces = 8 + +# Highlight lines with converted-only data if non-zero (same as --highlight +# option of genhtml) +genhtml_highlight = 0 + +# Include color legend in HTML output if non-zero (same as --legend option of +# genhtml) +genhtml_legend = 0 + +# Use FILE as HTML prolog for generated pages (same as --html-prolog option of +# genhtml) +#genhtml_html_prolog = FILE + +# Use FILE as HTML epilog for generated pages (same as --html-epilog option of +# genhtml) +#genhtml_html_epilog = FILE + +# Use custom filename extension for pages (same as --html-extension option of +# genhtml) +#genhtml_html_extension = html + +# Compress all generated html files with gzip. +#genhtml_html_gzip = 1 + +# Include sorted overview pages (can be disabled by the --no-sort option of +# genhtml) +genhtml_sort = 1 + +# Include function coverage data display (can be disabled by the +# --no-func-coverage option of genhtml) +genhtml_function_coverage = 1 + +# Include branch coverage data display (can be disabled by the +# --no-branch-coverage option of genhtml) +genhtml_branch_coverage = 1 + +# Specify the character set of all generated HTML pages +genhtml_charset=UTF-8 + +# Allow HTML markup in test case description text if non-zero +genhtml_desc_html=0 + +# Specify the precision for coverage rates +#genhtml_precision=1 + +# Location of the gcov tool (same as --gcov-info option of geninfo) +#geninfo_gcov_tool = llvm-gcov + +# Adjust test names to include operating system information if non-zero +#geninfo_adjust_testname = 0 + +# Calculate checksum for each source code line if non-zero (same as --checksum +# option of geninfo if non-zero, same as --no-checksum if zero) +#geninfo_checksum = 1 + +# Specify whether to capture coverage data for external source files (can +# be overridden by the --external and --no-external options of geninfo/lcov) +geninfo_external = 1 + +# Enable libtool compatibility mode if non-zero (same as --compat-libtool option +# of geninfo if non-zero, same as --no-compat-libtool if zero) +#geninfo_compat_libtool = 0 + +# Use gcov's --all-blocks option if non-zero +#geninfo_gcov_all_blocks = 1 + +# Specify compatiblity modes (same as --compat option of geninfo). +#geninfo_compat = libtool=on, hammer=auto, split_crc=auto + +# Adjust path to source files by removing or changing path components that +# match the specified pattern (Perl regular expression format) +#geninfo_adjust_src_path = /tmp/build => /usr/src + +# Specify if geninfo should try to automatically determine the base-directory +# when collecting coverage data. +geninfo_auto_base = 1 + +# Directory containing gcov kernel files +# lcov_gcov_dir = /proc/gcov + +# Location of the insmod tool +lcov_insmod_tool = /sbin/insmod + +# Location of the modprobe tool +lcov_modprobe_tool = /sbin/modprobe + +# Location of the rmmod tool +lcov_rmmod_tool = /sbin/rmmod + +# Location for temporary directories +lcov_tmp_dir = /tmp + +# Show full paths during list operation if non-zero (same as --list-full-path +# option of lcov) +lcov_list_full_path = 0 + +# Specify the maximum width for list output. This value is ignored when +# lcov_list_full_path is non-zero. +lcov_list_width = 80 + +# Specify the maximum percentage of file names which may be truncated when +# choosing a directory prefix in list output. This value is ignored when +# lcov_list_full_path is non-zero. +lcov_list_truncate_max = 20 + +# Specify if function coverage data should be collected and processed. +lcov_function_coverage = 1 + +# Specify if branch coverage data should be collected and processed. +lcov_branch_coverage = 1 diff --git a/testing/tools/coverage/llvm-gcov b/testing/tools/coverage/llvm-gcov new file mode 100755 index 0000000000000000000000000000000000000000..8141e7ef270ecc88890b234195541ffb5211752f --- /dev/null +++ b/testing/tools/coverage/llvm-gcov @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 2017 The 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. + +# Wrapper script to make llvm-cov behave like gcov, so it can be passed in as the --gcov-tool +# parameter when using lcov. Specifically adds the keyword 'gcov' to the arguments being passed in, +# to tell llvm-cov to operate in gcov compatibility mode. +# +# LLVM_COV_BIN needs to be set by caller and should the path to +# a llvm-cov binary with a version of 3.5 or greater. + +set -e + +exec ${LLVM_COV_BIN} gcov $* diff --git a/testing/tools/fixup_pdf_template.py b/testing/tools/fixup_pdf_template.py index 80a712f6e89d6903d372a36935f70057b09c538e..10ca241242f9fdffb2e205876b8ee7ceb430d7af 100755 --- a/testing/tools/fixup_pdf_template.py +++ b/testing/tools/fixup_pdf_template.py @@ -10,8 +10,10 @@ script replaces {{name}}-style variables in the input with calculated results {{header}} - expands to the header comment required for PDF files. {{xref}} - expands to a generated xref table, noting the offset. + {{trailer}} - expands to a standard trailer with "1 0 R" as the /Root. {{startxref} - expands to a startxref directive followed by correct offset. - {{object x y}} - expands to |x y obj| declaration, noting the offset.""" + {{object x y}} - expands to |x y obj| declaration, noting the offset. +""" import optparse import os @@ -19,15 +21,19 @@ import re import sys class TemplateProcessor: - HEADER_TOKEN = '{{header}}' + HEADER_TOKEN = '{{header}}' HEADER_REPLACEMENT = '%PDF-1.7\n%\xa0\xf2\xa4\xf4' XREF_TOKEN = '{{xref}}' XREF_REPLACEMENT = 'xref\n%d %d\n' - # XREF rows must be exactly 20 bytes - space required. XREF_REPLACEMENT_N = '%010d %05d n \n' XREF_REPLACEMENT_F = '0000000000 65535 f \n' + # XREF rows must be exactly 20 bytes - space required. + assert(len(XREF_REPLACEMENT_F) == 20) + + TRAILER_TOKEN = '{{trailer}}' + TRAILER_REPLACEMENT = 'trailer<< /Root 1 0 R /Size %d >>' STARTXREF_TOKEN= '{{startxref}}' STARTXREF_REPLACEMENT = 'startxref\n%d' @@ -60,6 +66,9 @@ class TemplateProcessor: if self.XREF_TOKEN in line: self.xref_offset = self.offset line = self.generate_xref_table() + if self.TRAILER_TOKEN in line: + replacement = self.TRAILER_REPLACEMENT % (self.max_object_number + 1) + line = line.replace(self.TRAILER_TOKEN, replacement) if self.STARTXREF_TOKEN in line: replacement = self.STARTXREF_REPLACEMENT % self.xref_offset line = line.replace(self.STARTXREF_TOKEN, replacement) diff --git a/testing/tools/githelper.py b/testing/tools/githelper.py new file mode 100644 index 0000000000000000000000000000000000000000..2e94196e858276fefbbe26237a9cf8dfb38b826d --- /dev/null +++ b/testing/tools/githelper.py @@ -0,0 +1,66 @@ +# Copyright 2017 The 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. + +"""Classes for dealing with git.""" + +import subprocess + +from common import RunCommandPropagateErr + + +class GitHelper(object): + """Issues git commands. Stateful.""" + + def __init__(self): + self.stashed = 0 + + def Checkout(self, branch): + """Checks out a branch.""" + RunCommandPropagateErr(['git', 'checkout', branch], exit_status_on_error=1) + + def FetchOriginMaster(self): + """Fetches new changes on origin/master.""" + RunCommandPropagateErr(['git', 'fetch', 'origin', 'master'], + exit_status_on_error=1) + + def StashPush(self): + """Stashes uncommitted changes.""" + output = RunCommandPropagateErr(['git', 'stash', '--include-untracked'], + exit_status_on_error=1) + if 'No local changes to save' in output: + return False + + self.stashed += 1 + return True + + def StashPopAll(self): + """Pops as many changes as this instance stashed.""" + while self.stashed > 0: + RunCommandPropagateErr(['git', 'stash', 'pop'], exit_status_on_error=1) + self.stashed -= 1 + + def GetCurrentBranchName(self): + """Returns a string with the current branch name.""" + return RunCommandPropagateErr( + ['git', 'rev-parse', '--abbrev-ref', 'HEAD'], + exit_status_on_error=1).strip() + + def GetCurrentBranchHash(self): + return RunCommandPropagateErr( + ['git', 'rev-parse', 'HEAD'], exit_status_on_error=1).strip() + + def IsCurrentBranchClean(self): + output = RunCommandPropagateErr(['git', 'status', '--porcelain'], + exit_status_on_error=1) + return not output + + def BranchExists(self, branch_name): + """Return whether a branch with the given name exists.""" + output = RunCommandPropagateErr(['git', 'rev-parse', '--verify', + branch_name]) + return output is not None + + def CloneLocal(self, source_repo, new_repo): + RunCommandPropagateErr(['git', 'clone', source_repo, new_repo], + exit_status_on_error=1) diff --git a/testing/tools/gold.py b/testing/tools/gold.py index db3bf81b739fd4bfe654cf806457096fb1671057..a8222378e80f7b0189f815cb9f2736b0f60c9b47 100644 --- a/testing/tools/gold.py +++ b/testing/tools/gold.py @@ -7,6 +7,132 @@ import json import os import shlex import shutil +import urllib2 + + +def _ParseKeyValuePairs(kv_str): + """ + Parses a string of the type 'key1 value1 key2 value2' into a dict. + """ + kv_pairs = shlex.split(kv_str) + if len(kv_pairs) % 2: + raise ValueError('Uneven number of key/value pairs. Got %s' % kv_str) + return { kv_pairs[i]:kv_pairs[i + 1] for i in xrange(0, len(kv_pairs), 2) } + + +# This module downloads a json provided by Skia Gold with the expected baselines +# for each test file. +# +# The expected format for the json is: +# { +# "commit": { +# "author": "John Doe (jdoe@chromium.org)", +# "commit_time": 1510598123, +# "hash": "cee39e6e90c219cc91f2c94a912a06977f4461a0" +# }, +# "master": { +# "abc.pdf.1": { +# "0ec3d86f545052acd7c9a16fde8ca9d4": 1, +# "80455b71673becc9fbc100d6da56ca65": 1, +# "b68e2ecb80090b4502ec89ad1be2322c": 1 +# }, +# "defgh.pdf.0": { +# "01e020cd4cd05c6738e479a46a506044": 1, +# "b68e2ecb80090b4502ec89ad1be2322c": 1 +# } +# }, +# "changeLists": { +# "18499" : { +# "abc.pdf.1": { +# "d5dd649124cf1779152253dc8fb239c5": 1, +# "42a270581930579cdb0f28674972fb1a": 1, +# } +# } +# } +# } +class GoldBaseline(object): + + def __init__(self, properties_str): + """ + properties_str is a string with space separated key/value pairs that + is used to find the cl number for which to baseline + """ + self._properties = _ParseKeyValuePairs(properties_str) + self._baselines = self._LoadSkiaGoldBaselines() + + def _LoadSkiaGoldBaselines(self): + """ + Download the baseline json and return a list of the two baselines that + should be used to match hashes (master and cl#). + """ + GOLD_BASELINE_URL = ('https://storage.googleapis.com/skia-infra-gm/' + 'hash_files/gold-pdfium-baseline.json') + try: + response = urllib2.urlopen(GOLD_BASELINE_URL) + json_data = response.read() + except (urllib2.HTTPError, urllib2.URLError) as e: + print ('Error: Unable to read skia gold json from %s: %s' + % (GOLD_BASELINE_URL, e)) + return None + + try: + data = json.loads(json_data) + except ValueError: + print 'Error: Malformed json read from %s: %s' % (GOLD_BASELINE_URL, e) + return None + + try: + master_baseline = data['master'] + except (KeyError, TypeError): + print ('Error: "master" key not in json read from %s: %s' + % (GOLD_BASELINE_URL, e)) + return None + + cl_number_str = self._properties.get('issue') + if cl_number_str is None: + return [master_baseline] + + try: + cl_baseline = data['changeLists'][cl_number_str] + except KeyError: + return [master_baseline] + + return [cl_baseline, master_baseline] + + # Return values for MatchLocalResult(). + MATCH = 'match' + MISMATCH = 'mismatch' + NO_BASELINE = 'no_baseline' + BASELINE_DOWNLOAD_FAILED = 'baseline_download_failed' + + def MatchLocalResult(self, test_name, md5_hash): + """ + Match a locally generated hash of a test cases rendered image with the + expected hashes downloaded in the baselines json. + + Each baseline is a dict mapping the test case name to a dict with the + expected hashes as keys. Therefore, this list of baselines should be + searched until the test case name is found, then the hash should be matched + with the options in that dict. If the hashes don't match, it should be + considered a failure and we should not continue searching the baseline list. + + Returns MATCH if the md5 provided matches the ones in the baseline json, + MISMATCH if it does not, NO_BASELINE if the test case has no baseline, or + BASELINE_DOWNLOAD_FAILED if the baseline could not be downloaded and parsed. + """ + if self._baselines is None: + return GoldBaseline.BASELINE_DOWNLOAD_FAILED + + found_test_case = False + for baseline in self._baselines: + if test_name in baseline: + found_test_case = True + if md5_hash in baseline[test_name]: + return GoldBaseline.MATCH + + return (GoldBaseline.MISMATCH if found_test_case + else GoldBaseline.NO_BASELINE) + # This module collects and writes output in a format expected by the # Gold baseline tool. Based on meta data provided explicitly and by @@ -56,7 +182,8 @@ class GoldResults(object): """ source_type is the source_type (=corpus) field used for all results. output_dir is the directory where the resulting images are copied and - the dm.json file is written. + the dm.json file is written. If the directory exists it will + be removed and recreated. propertiesStr is a string with space separated key/value pairs that is used to set the top level fields in the output JSON file. keyStr is a string with space separated key/value pairs that @@ -65,14 +192,15 @@ class GoldResults(object): that should be ignored. """ self._source_type = source_type - self._properties = self._parseKeyValuePairs(propertiesStr) - self._properties["key"] = self._parseKeyValuePairs(keyStr) + self._properties = _ParseKeyValuePairs(propertiesStr) + self._properties["key"] = _ParseKeyValuePairs(keyStr) self._results = [] self._outputDir = outputDir - # make sure the output directory exists. - if not os.path.exists(outputDir): - os.makedirs(outputDir) + # make sure the output directory exists and is empty. + if os.path.exists(outputDir): + shutil.rmtree(outputDir, ignore_errors=True) + os.makedirs(outputDir) self._ignore_hashes = set() if ignore_hashes_file: @@ -104,12 +232,6 @@ class GoldResults(object): } }) - def _parseKeyValuePairs(self, kvStr): - kvPairs = shlex.split(kvStr) - if len(kvPairs) % 2: - raise ValueError("Uneven number of key/value pairs. Got %s" % kvStr) - return { kvPairs[i]:kvPairs[i+1] for i in range(0, len(kvPairs), 2) } - def WriteResults(self): self._properties.update({ "results": self._results diff --git a/testing/tools/pngdiffer.py b/testing/tools/pngdiffer.py index a1533b8329f4a440e5cee836ed3f0fee000d673c..a9bc9d6529516815058a9ef0159f24402d403ea3 100755 --- a/testing/tools/pngdiffer.py +++ b/testing/tools/pngdiffer.py @@ -4,32 +4,26 @@ # found in the LICENSE file. import os +import shutil import sys import common class PNGDiffer(): - ACTUAL_TEMPLATE = '.pdf.%d.png' - EXPECTED_TEMPLATE = '_expected' + ACTUAL_TEMPLATE - PLATFORM_EXPECTED_TEMPLATE = '_expected_%s' + ACTUAL_TEMPLATE - def __init__(self, finder): self.pdfium_diff_path = finder.ExecutablePath('pdfium_diff') self.os_name = finder.os_name def GetActualFiles(self, input_filename, source_dir, working_dir): actual_paths = [] - template_paths = self._GetTemplatePaths( - input_filename, source_dir, working_dir) - actual_path_template = template_paths[0]; - expected_path_template = template_paths[1] - platform_expected_path_template = template_paths[2] + path_templates = PathTemplates(input_filename, source_dir, working_dir) + i = 0 while True: - actual_path = actual_path_template % i - expected_path = expected_path_template % i - platform_expected_path = ( - platform_expected_path_template % (self.os_name, i)) + actual_path = path_templates.GetActualPath(i) + expected_path = path_templates.GetExpectedPath(i) + platform_expected_path = path_templates.GetPlatformExpectedPath( + self.os_name, i) if os.path.exists(platform_expected_path): expected_path = platform_expected_path elif not os.path.exists(expected_path): @@ -39,19 +33,16 @@ class PNGDiffer(): return actual_paths def HasDifferences(self, input_filename, source_dir, working_dir): - template_paths = self._GetTemplatePaths( - input_filename, source_dir, working_dir) - actual_path_template = template_paths[0]; - expected_path_template = template_paths[1] - platform_expected_path_template = template_paths[2] + path_templates = PathTemplates(input_filename, source_dir, working_dir) + i = 0 while True: - actual_path = actual_path_template % i - expected_path = expected_path_template % i + actual_path = path_templates.GetActualPath(i) + expected_path = path_templates.GetExpectedPath(i) # PDFium tests should be platform independent. Platform based results are # used to capture platform dependent implementations. - platform_expected_path = ( - platform_expected_path_template % (self.os_name, i)) + platform_expected_path = path_templates.GetPlatformExpectedPath( + self.os_name, i) if (not os.path.exists(expected_path) and not os.path.exists(platform_expected_path)): if i == 0: @@ -75,11 +66,57 @@ class PNGDiffer(): i += 1 return False - def _GetTemplatePaths(self, input_filename, source_dir, working_dir): + def Regenerate(self, input_filename, source_dir, working_dir, platform_only): + path_templates = PathTemplates(input_filename, source_dir, working_dir) + + page = 0 + while True: + # Loop through the generated page images. Stop when there is a page + # missing a png, which means the document ended. + actual_path = path_templates.GetActualPath(page) + if not os.path.isfile(actual_path): + break + + platform_expected_path = path_templates.GetPlatformExpectedPath( + self.os_name, page) + + # If there is a platform expected png, we will overwrite it. Otherwise, + # overwrite the generic png in "all" mode, or do nothing in "platform" + # mode. + if os.path.exists(platform_expected_path): + expected_path = platform_expected_path + elif not platform_only: + expected_path = path_templates.GetExpectedPath(page) + else: + expected_path = None + + if expected_path is not None and os.path.exists(expected_path): + shutil.copyfile(actual_path, expected_path) + + page += 1 + + +ACTUAL_TEMPLATE = '.pdf.%d.png' +EXPECTED_TEMPLATE = '_expected' + ACTUAL_TEMPLATE +PLATFORM_EXPECTED_TEMPLATE = '_expected_%s' + ACTUAL_TEMPLATE + + +class PathTemplates(object): + + def __init__(self, input_filename, source_dir, working_dir): input_root, _ = os.path.splitext(input_filename) - actual_path = os.path.join(working_dir, input_root + self.ACTUAL_TEMPLATE) - expected_path = os.path.join( - source_dir, input_root + self.EXPECTED_TEMPLATE) - platform_expected_path = os.path.join( - source_dir, input_root + self.PLATFORM_EXPECTED_TEMPLATE) - return (actual_path, expected_path, platform_expected_path) + self.actual_path_template = os.path.join(working_dir, + input_root + ACTUAL_TEMPLATE) + self.expected_path = os.path.join( + source_dir, input_root + EXPECTED_TEMPLATE) + self.platform_expected_path = os.path.join( + source_dir, input_root + PLATFORM_EXPECTED_TEMPLATE) + + def GetActualPath(self, page): + return self.actual_path_template % page + + def GetExpectedPath(self, page): + return self.expected_path % page + + def GetPlatformExpectedPath(self, platform, page): + return self.platform_expected_path % (platform, page) diff --git a/testing/tools/run_corpus_tests.py b/testing/tools/run_corpus_tests.py index 494240657965fe02739a240d6a78a5a85bbaffea..1175de497c5f239c8a8a9da2186a01be7c281c11 100755 --- a/testing/tools/run_corpus_tests.py +++ b/testing/tools/run_corpus_tests.py @@ -9,6 +9,8 @@ import test_runner def main(): runner = test_runner.TestRunner('corpus') + runner.SetEnforceExpectedImages(True) + runner.SetOneShotRenderer(True) return runner.Run() if __name__ == '__main__': diff --git a/testing/tools/run_pixel_tests.py b/testing/tools/run_pixel_tests.py index aad39c56002eccda0a834f78156f5d9ef0cabe91..1d61966c2effb5aefaf9dcb345bd0d99ddcf8049 100755 --- a/testing/tools/run_pixel_tests.py +++ b/testing/tools/run_pixel_tests.py @@ -9,6 +9,7 @@ import test_runner def main(): runner = test_runner.TestRunner('pixel') + runner.SetEnforceExpectedImages(True) return runner.Run() if __name__ == '__main__': diff --git a/testing/tools/safetynet_compare.py b/testing/tools/safetynet_compare.py new file mode 100755 index 0000000000000000000000000000000000000000..0cf1aec036e9076d9538d007f36081ed8143289f --- /dev/null +++ b/testing/tools/safetynet_compare.py @@ -0,0 +1,680 @@ +#!/usr/bin/env python +# Copyright 2017 The 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. + +"""Compares the performance of two versions of the pdfium code.""" + +import argparse +import functools +import json +import multiprocessing +import os +import re +import shutil +import subprocess +import sys +import tempfile + +from common import GetBooleanGnArg +from common import PrintErr +from common import RunCommandPropagateErr +from githelper import GitHelper +from safetynet_conclusions import ComparisonConclusions +from safetynet_conclusions import PrintConclusionsDictHumanReadable +from safetynet_conclusions import RATING_IMPROVEMENT +from safetynet_conclusions import RATING_REGRESSION + + +def RunSingleTestCaseParallel(this, run_label, build_dir, test_case): + result = this.RunSingleTestCase(run_label, build_dir, test_case) + return (test_case, result) + + +class CompareRun(object): + """A comparison between two branches of pdfium.""" + + def __init__(self, args): + self.git = GitHelper() + self.args = args + self._InitPaths() + + def _InitPaths(self): + if self.args.this_repo: + self.safe_script_dir = self.args.build_dir + else: + self.safe_script_dir = os.path.join('testing', 'tools') + + self.safe_measure_script_path = os.path.abspath( + os.path.join(self.safe_script_dir, + 'safetynet_measure.py')) + + input_file_re = re.compile('^.+[.]pdf$') + self.test_cases = [] + for input_path in self.args.input_paths: + if os.path.isfile(input_path): + self.test_cases.append(input_path) + elif os.path.isdir(input_path): + for file_dir, _, filename_list in os.walk(input_path): + for input_filename in filename_list: + if input_file_re.match(input_filename): + file_path = os.path.join(file_dir, input_filename) + if os.path.isfile(file_path): + self.test_cases.append(file_path) + + self.after_build_dir = self.args.build_dir + if self.args.build_dir_before: + self.before_build_dir = self.args.build_dir_before + else: + self.before_build_dir = self.after_build_dir + + def Run(self): + """Runs comparison by checking out branches, building and measuring them. + + Returns: + Exit code for the script. + """ + if self.args.this_repo: + self._FreezeMeasureScript() + + if self.args.branch_after: + if self.args.this_repo: + before, after = self._ProfileTwoOtherBranchesInThisRepo( + self.args.branch_before, + self.args.branch_after) + else: + before, after = self._ProfileTwoOtherBranches( + self.args.branch_before, + self.args.branch_after) + elif self.args.branch_before: + if self.args.this_repo: + before, after = self._ProfileCurrentAndOtherBranchInThisRepo( + self.args.branch_before) + else: + before, after = self._ProfileCurrentAndOtherBranch( + self.args.branch_before) + else: + if self.args.this_repo: + before, after = self._ProfileLocalChangesAndCurrentBranchInThisRepo() + else: + before, after = self._ProfileLocalChangesAndCurrentBranch() + + conclusions = self._DrawConclusions(before, after) + conclusions_dict = conclusions.GetOutputDict() + conclusions_dict.setdefault('metadata', {})['profiler'] = self.args.profiler + + self._PrintConclusions(conclusions_dict) + + self._CleanUp(conclusions) + + return 0 + + def _FreezeMeasureScript(self): + """Freezes a version of the measuring script. + + This is needed to make sure we are comparing the pdfium library changes and + not script changes that may happen between the two branches. + """ + self.__FreezeFile(os.path.join('testing', 'tools', 'safetynet_measure.py')) + self.__FreezeFile(os.path.join('testing', 'tools', 'common.py')) + + def __FreezeFile(self, file): + RunCommandPropagateErr(['cp', file, self.safe_script_dir], + exit_status_on_error=1) + + def _ProfileTwoOtherBranchesInThisRepo(self, before_branch, after_branch): + """Profiles two branches that are not the current branch. + + This is done in the local repository and changes may not be restored if the + script fails or is interrupted. + + after_branch does not need to descend from before_branch, they will be + measured the same way + + Args: + before_branch: One branch to profile. + after_branch: Other branch to profile. + + Returns: + A tuple (before, after), where each of before and after is a dict + mapping a test case name to the profiling values for that test case + in the given branch. + """ + branch_to_restore = self.git.GetCurrentBranchName() + + self._StashLocalChanges() + + self._CheckoutBranch(after_branch) + self._BuildCurrentBranch(self.after_build_dir) + after = self._MeasureCurrentBranch('after', self.after_build_dir) + + self._CheckoutBranch(before_branch) + self._BuildCurrentBranch(self.before_build_dir) + before = self._MeasureCurrentBranch('before', self.before_build_dir) + + self._CheckoutBranch(branch_to_restore) + self._RestoreLocalChanges() + + return before, after + + def _ProfileTwoOtherBranches(self, before_branch, after_branch): + """Profiles two branches that are not the current branch. + + This is done in new, cloned repositories, therefore it is safer but slower + and requires downloads. + + after_branch does not need to descend from before_branch, they will be + measured the same way + + Args: + before_branch: One branch to profile. + after_branch: Other branch to profile. + + Returns: + A tuple (before, after), where each of before and after is a dict + mapping a test case name to the profiling values for that test case + in the given branch. + """ + after = self._ProfileSeparateRepo('after', + self.after_build_dir, + after_branch) + before = self._ProfileSeparateRepo('before', + self.before_build_dir, + before_branch) + return before, after + + def _ProfileCurrentAndOtherBranchInThisRepo(self, other_branch): + """Profiles the current branch (with uncommitted changes) and another one. + + This is done in the local repository and changes may not be restored if the + script fails or is interrupted. + + The current branch does not need to descend from other_branch. + + Args: + other_branch: Other branch to profile that is not the current. + + Returns: + A tuple (before, after), where each of before and after is a dict + mapping a test case name to the profiling values for that test case + in the given branch. The current branch is considered to be "after" and + the other branch is considered to be "before". + """ + branch_to_restore = self.git.GetCurrentBranchName() + + self._BuildCurrentBranch(self.after_build_dir) + after = self._MeasureCurrentBranch('after', self.after_build_dir) + + self._StashLocalChanges() + + self._CheckoutBranch(other_branch) + self._BuildCurrentBranch(self.before_build_dir) + before = self._MeasureCurrentBranch('before', self.before_build_dir) + + self._CheckoutBranch(branch_to_restore) + self._RestoreLocalChanges() + + return before, after + + def _ProfileCurrentAndOtherBranch(self, other_branch): + """Profiles the current branch (with uncommitted changes) and another one. + + This is done in new, cloned repositories, therefore it is safer but slower + and requires downloads. + + The current branch does not need to descend from other_branch. + + Args: + other_branch: Other branch to profile that is not the current. None will + compare to the same branch. + + Returns: + A tuple (before, after), where each of before and after is a dict + mapping a test case name to the profiling values for that test case + in the given branch. The current branch is considered to be "after" and + the other branch is considered to be "before". + """ + self._BuildCurrentBranch(self.after_build_dir) + after = self._MeasureCurrentBranch('after', self.after_build_dir) + + before = self._ProfileSeparateRepo('before', + self.before_build_dir, + other_branch) + + return before, after + + def _ProfileLocalChangesAndCurrentBranchInThisRepo(self): + """Profiles the current branch with and without uncommitted changes. + + This is done in the local repository and changes may not be restored if the + script fails or is interrupted. + + Returns: + A tuple (before, after), where each of before and after is a dict + mapping a test case name to the profiling values for that test case + using the given version. The current branch without uncommitted changes is + considered to be "before" and with uncommitted changes is considered to be + "after". + """ + self._BuildCurrentBranch(self.after_build_dir) + after = self._MeasureCurrentBranch('after', self.after_build_dir) + + pushed = self._StashLocalChanges() + if not pushed and not self.args.build_dir_before: + PrintErr('Warning: No local changes to compare') + + before_build_dir = self.before_build_dir + + self._BuildCurrentBranch(before_build_dir) + before = self._MeasureCurrentBranch('before', before_build_dir) + + self._RestoreLocalChanges() + + return before, after + + def _ProfileLocalChangesAndCurrentBranch(self): + """Profiles the current branch with and without uncommitted changes. + + This is done in new, cloned repositories, therefore it is safer but slower + and requires downloads. + + Returns: + A tuple (before, after), where each of before and after is a dict + mapping a test case name to the profiling values for that test case + using the given version. The current branch without uncommitted changes is + considered to be "before" and with uncommitted changes is considered to be + "after". + """ + return self._ProfileCurrentAndOtherBranch(other_branch=None) + + def _ProfileSeparateRepo(self, run_label, relative_build_dir, branch): + """Profiles a branch in a a temporary git repository. + + Args: + run_label: String to differentiate this version of the code in output + files from other versions. + relative_build_dir: Path to the build dir in the current working dir to + clone build args from. + branch: Branch to checkout in the new repository. None will + profile the same branch checked out in the original repo. + Returns: + A dict mapping each test case name to the profiling values for that + test case. + """ + build_dir = self._CreateTempRepo('repo_%s' % run_label, + relative_build_dir, + branch) + + self._BuildCurrentBranch(build_dir) + return self._MeasureCurrentBranch(run_label, build_dir) + + def _CreateTempRepo(self, dir_name, relative_build_dir, branch): + """Clones a temporary git repository out of the current working dir. + + Args: + dir_name: Name for the temporary repository directory + relative_build_dir: Path to the build dir in the current working dir to + clone build args from. + branch: Branch to checkout in the new repository. None will keep checked + out the same branch as the local repo. + Returns: + Path to the build directory of the new repository. + """ + cwd = os.getcwd() + + repo_dir = tempfile.mkdtemp(suffix='-%s' % dir_name) + src_dir = os.path.join(repo_dir, 'pdfium') + + self.git.CloneLocal(os.getcwd(), src_dir) + + if branch is not None: + os.chdir(src_dir) + self.git.Checkout(branch) + + os.chdir(repo_dir) + PrintErr('Syncing...') + + cmd = ['gclient', 'config', '--unmanaged', + 'https://pdfium.googlesource.com/pdfium.git'] + if self.args.cache_dir: + cmd.append('--cache-dir=%s' % self.args.cache_dir) + RunCommandPropagateErr(cmd, exit_status_on_error=1) + + RunCommandPropagateErr(['gclient', 'sync'], exit_status_on_error=1) + + PrintErr('Done.') + + build_dir = os.path.join(src_dir, relative_build_dir) + os.makedirs(build_dir) + os.chdir(src_dir) + + source_gn_args = os.path.join(cwd, relative_build_dir, 'args.gn') + dest_gn_args = os.path.join(build_dir, 'args.gn') + shutil.copy(source_gn_args, dest_gn_args) + + RunCommandPropagateErr(['gn', 'gen', relative_build_dir], + exit_status_on_error=1) + + os.chdir(cwd) + + return build_dir + + + def _CheckoutBranch(self, branch): + PrintErr("Checking out branch '%s'" % branch) + self.git.Checkout(branch) + + def _StashLocalChanges(self): + PrintErr('Stashing local changes') + return self.git.StashPush() + + def _RestoreLocalChanges(self): + PrintErr('Restoring local changes') + self.git.StashPopAll() + + def _BuildCurrentBranch(self, build_dir): + """Synchronizes and builds the current version of pdfium. + + Args: + build_dir: String with path to build directory + """ + PrintErr('Syncing...') + RunCommandPropagateErr(['gclient', 'sync'], exit_status_on_error=1) + PrintErr('Done.') + + PrintErr('Building...') + cmd = ['ninja', '-C', build_dir, 'pdfium_test'] + if GetBooleanGnArg('use_goma', build_dir): + cmd.extend(['-j', '250']) + RunCommandPropagateErr(cmd, stdout_has_errors=True, exit_status_on_error=1) + PrintErr('Done.') + + def _MeasureCurrentBranch(self, run_label, build_dir): + PrintErr('Measuring...') + if self.args.num_workers > 1 and len(self.test_cases) > 1: + results = self._RunAsync(run_label, build_dir) + else: + results = self._RunSync(run_label, build_dir) + PrintErr('Done.') + + return results + + def _RunSync(self, run_label, build_dir): + """Profiles the test cases synchronously. + + Args: + run_label: String to differentiate this version of the code in output + files from other versions. + build_dir: String with path to build directory + + Returns: + A dict mapping each test case name to the profiling values for that + test case. + """ + results = {} + + for test_case in self.test_cases: + result = self.RunSingleTestCase(run_label, build_dir, test_case) + if result is not None: + results[test_case] = result + + return results + + def _RunAsync(self, run_label, build_dir): + """Profiles the test cases asynchronously. + + Uses as many workers as configured by --num-workers. + + Args: + run_label: String to differentiate this version of the code in output + files from other versions. + build_dir: String with path to build directory + + Returns: + A dict mapping each test case name to the profiling values for that + test case. + """ + results = {} + pool = multiprocessing.Pool(self.args.num_workers) + worker_func = functools.partial( + RunSingleTestCaseParallel, self, run_label, build_dir) + + try: + # The timeout is a workaround for http://bugs.python.org/issue8296 + # which prevents KeyboardInterrupt from working. + one_year_in_seconds = 3600 * 24 * 365 + worker_results = (pool.map_async(worker_func, self.test_cases) + .get(one_year_in_seconds)) + for worker_result in worker_results: + test_case, result = worker_result + if result is not None: + results[test_case] = result + except KeyboardInterrupt: + pool.terminate() + sys.exit(1) + else: + pool.close() + + pool.join() + + return results + + def RunSingleTestCase(self, run_label, build_dir, test_case): + """Profiles a single test case. + + Args: + run_label: String to differentiate this version of the code in output + files from other versions. + build_dir: String with path to build directory + test_case: Path to the test case. + + Returns: + The measured profiling value for that test case. + """ + command = [self.safe_measure_script_path, test_case, + '--build-dir=%s' % build_dir] + + if self.args.interesting_section: + command.append('--interesting-section') + + if self.args.profiler: + command.append('--profiler=%s' % self.args.profiler) + + profile_file_path = self._GetProfileFilePath(run_label, test_case) + if profile_file_path: + command.append('--output-path=%s' % profile_file_path) + + output = RunCommandPropagateErr(command) + + if output is None: + return None + + # Get the time number as output, making sure it's just a number + output = output.strip() + if re.match('^[0-9]+$', output): + return int(output) + + return None + + def _GetProfileFilePath(self, run_label, test_case): + if self.args.output_dir: + output_filename = ('callgrind.out.%s.%s' + % (test_case.replace('/', '_'), + run_label)) + return os.path.join(self.args.output_dir, output_filename) + else: + return None + + def _DrawConclusions(self, times_before_branch, times_after_branch): + """Draws conclusions comparing results of test runs in two branches. + + Args: + times_before_branch: A dict mapping each test case name to the + profiling values for that test case in the branch to be considered + as the baseline. + times_after_branch: A dict mapping each test case name to the + profiling values for that test case in the branch to be considered + as the new version. + + Returns: + ComparisonConclusions with all test cases processed. + """ + conclusions = ComparisonConclusions(self.args.threshold_significant) + + for test_case in sorted(self.test_cases): + before = times_before_branch.get(test_case) + after = times_after_branch.get(test_case) + conclusions.ProcessCase(test_case, before, after) + + return conclusions + + def _PrintConclusions(self, conclusions_dict): + """Prints the conclusions as the script output. + + Depending on the script args, this can output a human or a machine-readable + version of the conclusions. + + Args: + conclusions_dict: Dict to print returned from + ComparisonConclusions.GetOutputDict(). + """ + if self.args.machine_readable: + print json.dumps(conclusions_dict) + else: + PrintConclusionsDictHumanReadable( + conclusions_dict, colored=True, key=self.args.case_order) + + def _CleanUp(self, conclusions): + """Removes profile output files for uninteresting cases. + + Cases without significant regressions or improvements and considered + uninteresting. + + Args: + conclusions: A ComparisonConclusions. + """ + if not self.args.output_dir: + return + + if self.args.profiler != 'callgrind': + return + + for case_result in conclusions.GetCaseResults().values(): + if case_result.rating not in [RATING_REGRESSION, RATING_IMPROVEMENT]: + self._CleanUpOutputFile('before', case_result.case_name) + self._CleanUpOutputFile('after', case_result.case_name) + + def _CleanUpOutputFile(self, run_label, case_name): + """Removes one profile output file. + + If the output file does not exist, fails silently. + + Args: + run_label: String to differentiate a version of the code in output + files from other versions. + case_name: String identifying test case for which to remove the output + file. + """ + try: + os.remove(self._GetProfileFilePath(run_label, case_name)) + except OSError: + pass + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('input_paths', nargs='+', + help='pdf files or directories to search for pdf files ' + 'to run as test cases') + parser.add_argument('--branch-before', + help='git branch to use as "before" for comparison. ' + 'Omitting this will use the current branch ' + 'without uncommitted changes as the baseline.') + parser.add_argument('--branch-after', + help='git branch to use as "after" for comparison. ' + 'Omitting this will use the current branch ' + 'with uncommitted changes.') + parser.add_argument('--build-dir', default=os.path.join('out', 'Release'), + help='relative path from the base source directory ' + 'to the build directory') + parser.add_argument('--build-dir-before', + help='relative path from the base source directory ' + 'to the build directory for the "before" branch, if ' + 'different from the build directory for the ' + '"after" branch') + parser.add_argument('--cache-dir', default=None, + help='directory with a new or preexisting cache for ' + 'downloads. Default is to not use a cache.') + parser.add_argument('--this-repo', action='store_true', + help='use the repository where the script is instead of ' + 'checking out a temporary one. This is faster and ' + 'does not require downloads, but although it ' + 'restores the state of the local repo, if the ' + 'script is killed or crashes the changes can remain ' + 'stashed and you may be on another branch.') + parser.add_argument('--profiler', default='callgrind', + help='which profiler to use. Supports callgrind and ' + 'perfstat for now. Default is callgrind.') + parser.add_argument('--interesting-section', action='store_true', + help='whether to measure just the interesting section or ' + 'the whole test harness. Limiting to only the ' + 'interesting section does not work on Release since ' + 'the delimiters are optimized out') + parser.add_argument('--num-workers', default=multiprocessing.cpu_count(), + type=int, help='run NUM_WORKERS jobs in parallel') + parser.add_argument('--output-dir', + help='directory to write the profile data output files') + parser.add_argument('--threshold-significant', default=0.02, type=float, + help='variations in performance above this factor are ' + 'considered significant') + parser.add_argument('--machine-readable', action='store_true', + help='whether to get output for machines. If enabled the ' + 'output will be a json with the format specified in ' + 'ComparisonConclusions.GetOutputDict(). Default is ' + 'human-readable.') + parser.add_argument('--case-order', default=None, + help='what key to use when sorting test cases in the ' + 'output. Accepted values are "after", "before", ' + '"ratio" and "rating". Default is sorting by test ' + 'case path.') + + args = parser.parse_args() + + # Always start at the pdfium src dir, which is assumed to be two level above + # this script. + pdfium_src_dir = os.path.join( + os.path.dirname(__file__), + os.path.pardir, + os.path.pardir) + os.chdir(pdfium_src_dir) + + git = GitHelper() + + if args.branch_after and not args.branch_before: + PrintErr('--branch-after requires --branch-before to be specified.') + return 1 + + if args.branch_after and not git.BranchExists(args.branch_after): + PrintErr('Branch "%s" does not exist' % args.branch_after) + return 1 + + if args.branch_before and not git.BranchExists(args.branch_before): + PrintErr('Branch "%s" does not exist' % args.branch_before) + return 1 + + if args.output_dir: + args.output_dir = os.path.expanduser(args.output_dir) + if not os.path.isdir(args.output_dir): + PrintErr('"%s" is not a directory' % args.output_dir) + return 1 + + if args.threshold_significant <= 0.0: + PrintErr('--threshold-significant should receive a positive float') + return 1 + + run = CompareRun(args) + return run.Run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/testing/tools/safetynet_conclusions.py b/testing/tools/safetynet_conclusions.py new file mode 100644 index 0000000000000000000000000000000000000000..fdbc10df14be7aeac28523f0b7eae045d0d16f17 --- /dev/null +++ b/testing/tools/safetynet_conclusions.py @@ -0,0 +1,300 @@ +# Copyright 2017 The 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. + +"""Classes that draw conclusions out of a comparison and represent them.""" + +from collections import Counter + + +FORMAT_RED = '\033[01;31m{0}\033[00m' +FORMAT_GREEN = '\033[01;32m{0}\033[00m' +FORMAT_MAGENTA = '\033[01;35m{0}\033[00m' +FORMAT_CYAN = '\033[01;36m{0}\033[00m' +FORMAT_NORMAL = '{0}' + +RATING_FAILURE = 'failure' +RATING_REGRESSION = 'regression' +RATING_IMPROVEMENT = 'improvement' +RATING_NO_CHANGE = 'no_change' +RATING_SMALL_CHANGE = 'small_change' + +RATINGS = [ + RATING_FAILURE, + RATING_REGRESSION, + RATING_IMPROVEMENT, + RATING_NO_CHANGE, + RATING_SMALL_CHANGE +] + +RATING_TO_COLOR = { + RATING_FAILURE: FORMAT_MAGENTA, + RATING_REGRESSION: FORMAT_RED, + RATING_IMPROVEMENT: FORMAT_CYAN, + RATING_NO_CHANGE: FORMAT_GREEN, + RATING_SMALL_CHANGE: FORMAT_NORMAL, +} + + +class ComparisonConclusions(object): + """All conclusions drawn from a comparison. + + This is initialized empty and then processes pairs of results for each test + case, determining the rating for that case, which can be: + "failure" if either or both runs for the case failed. + "regression" if there is a significant increase in time for the test case. + "improvement" if there is a significant decrease in time for the test case. + "no_change" if the time for the test case did not change at all. + "small_change" if the time for the test case changed but within the threshold. + """ + + def __init__(self, threshold_significant): + """Initializes an empty ComparisonConclusions. + + Args: + threshold_significant: Float with the tolerance beyond which changes in + measurements are considered significant. + + The change is considered as a multiplication rather than an addition + of a fraction of the previous measurement, that is, a + threshold_significant of 1.0 will flag test cases that became over + 100% slower (> 200% of the previous time measured) or over 100% faster + (< 50% of the previous time measured). + + threshold_significant 0.02 -> 98.04% to 102% is not significant + threshold_significant 0.1 -> 90.9% to 110% is not significant + threshold_significant 0.25 -> 80% to 125% is not significant + threshold_significant 1 -> 50% to 200% is not significant + threshold_significant 4 -> 20% to 500% is not significant + + """ + self.threshold_significant = threshold_significant + self.threshold_significant_negative = (1 / (1 + threshold_significant)) - 1 + + self.params = {'threshold': threshold_significant} + self.summary = ComparisonSummary() + self.case_results = {} + + def ProcessCase(self, case_name, before, after): + """Feeds a test case results to the ComparisonConclusions. + + Args: + case_name: String identifying the case. + before: Measurement for the "before" version of the code. + after: Measurement for the "after" version of the code. + """ + + # Switch 0 to None to simplify the json dict output. All zeros are + # considered failed runs, so they will be represented by "null". + if not before: + before = None + if not after: + after = None + + if not before or not after: + ratio = None + rating = RATING_FAILURE + else: + ratio = (float(after) / before) - 1.0 + if ratio > self.threshold_significant: + rating = RATING_REGRESSION + elif ratio < self.threshold_significant_negative: + rating = RATING_IMPROVEMENT + elif ratio == 0: + rating = RATING_NO_CHANGE + else: + rating = RATING_SMALL_CHANGE + + case_result = CaseResult(case_name, before, after, ratio, rating) + + self.summary.ProcessCaseResult(case_result) + self.case_results[case_name] = case_result + + def GetSummary(self): + """Gets the ComparisonSummary with consolidated totals.""" + return self.summary + + def GetCaseResults(self): + """Gets a dict mapping each test case identifier to its CaseResult.""" + return self.case_results + + def GetOutputDict(self): + """Returns a conclusions dict with all the conclusions drawn. + + Returns: + A serializable dict with the format illustrated below: + { + "version": 1, + "params": { + "threshold": 0.02 + }, + "summary": { + "total": 123, + "failure": 1, + "regression": 2, + "improvement": 1, + "no_change": 100, + "small_change": 19 + }, + "comparison_by_case": { + "testing/resources/new_test.pdf": { + "before": None, + "after": 1000, + "ratio": None, + "rating": "failure" + }, + "testing/resources/test1.pdf": { + "before": 100, + "after": 120, + "ratio": 0.2, + "rating": "regression" + }, + "testing/resources/test2.pdf": { + "before": 100, + "after": 2000, + "ratio": 19.0, + "rating": "regression" + }, + "testing/resources/test3.pdf": { + "before": 1000, + "after": 1005, + "ratio": 0.005, + "rating": "small_change" + }, + "testing/resources/test4.pdf": { + "before": 1000, + "after": 1000, + "ratio": 0.0, + "rating": "no_change" + }, + "testing/resources/test5.pdf": { + "before": 1000, + "after": 600, + "ratio": -0.4, + "rating": "improvement" + } + } + } + """ + output_dict = {} + output_dict['version'] = 1 + output_dict['params'] = {'threshold': self.threshold_significant} + output_dict['summary'] = self.summary.GetOutputDict() + output_dict['comparison_by_case'] = { + cr.case_name.decode('utf-8'): cr.GetOutputDict() + for cr in self.GetCaseResults().values() + } + return output_dict + + +class ComparisonSummary(object): + """Totals computed for a comparison.""" + + def __init__(self): + self.rating_counter = Counter() + + def ProcessCaseResult(self, case_result): + self.rating_counter[case_result.rating] += 1 + + def GetTotal(self): + """Gets the number of test cases processed.""" + return sum(self.rating_counter.values()) + + def GetCount(self, rating): + """Gets the number of test cases processed with a given rating.""" + return self.rating_counter[rating] + + def GetOutputDict(self): + """Returns a dict that can be serialized with all the totals.""" + result = {'total': self.GetTotal()} + for rating in RATINGS: + result[rating] = self.GetCount(rating) + return result + + +class CaseResult(object): + """The conclusion for the comparison of a single test case.""" + + def __init__(self, case_name, before, after, ratio, rating): + """Initializes an empty ComparisonConclusions. + + Args: + case_name: String identifying the case. + before: Measurement for the "before" version of the code. + after: Measurement for the "after" version of the code. + ratio: Difference between |after| and |before| as a fraction of |before|. + rating: Rating for this test case. + """ + self.case_name = case_name + self.before = before + self.after = after + self.ratio = ratio + self.rating = rating + + def GetOutputDict(self): + """Returns a dict with the test case's conclusions.""" + return {'before': self.before, + 'after': self.after, + 'ratio': self.ratio, + 'rating': self.rating} + + +def PrintConclusionsDictHumanReadable(conclusions_dict, colored, key=None): + """Prints a conclusions dict in a human-readable way. + + Args: + conclusions_dict: Dict to print. + colored: Whether to color the output to highlight significant changes. + key: String with the CaseResult dictionary key to sort the cases. + """ + # Print header + print '=' * 80 + print '{0:>11s} {1:>15s} {2}' .format( + '% Change', + 'Time after', + 'Test case') + print '-' * 80 + + color = FORMAT_NORMAL + + # Print cases + if key is not None: + case_pairs = sorted(conclusions_dict['comparison_by_case'].iteritems(), + key=lambda kv: kv[1][key]) + else: + case_pairs = sorted(conclusions_dict['comparison_by_case'].iteritems()) + + for case_name, case_dict in case_pairs: + if colored: + color = RATING_TO_COLOR[case_dict['rating']] + + if case_dict['rating'] == RATING_FAILURE: + print u'{} to measure time for {}'.format( + color.format('Failed'), + case_name).encode('utf-8') + continue + + print u'{0} {1:15,d} {2}' .format( + color.format('{:+11.4%}'.format(case_dict['ratio'])), + case_dict['after'], + case_name).encode('utf-8') + + # Print totals + totals = conclusions_dict['summary'] + print '=' * 80 + print 'Test cases run: %d' % totals['total'] + + if colored: + color = FORMAT_MAGENTA if totals[RATING_FAILURE] else FORMAT_GREEN + print ('Failed to measure: %s' + % color.format(totals[RATING_FAILURE])) + + if colored: + color = FORMAT_RED if totals[RATING_REGRESSION] else FORMAT_GREEN + print ('Regressions: %s' + % color.format(totals[RATING_REGRESSION])) + + if colored: + color = FORMAT_CYAN if totals[RATING_IMPROVEMENT] else FORMAT_GREEN + print ('Improvements: %s' + % color.format(totals[RATING_IMPROVEMENT])) diff --git a/testing/tools/safetynet_job.py b/testing/tools/safetynet_job.py new file mode 100755 index 0000000000000000000000000000000000000000..7416533222336b32c8182145148f7d4fd4e0d35f --- /dev/null +++ b/testing/tools/safetynet_job.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# Copyright 2017 The 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. + +"""Looks for performance regressions on all pushes since the last run. + +Run this nightly to have a periodical check for performance regressions. + +Stores the results for each run and last checkpoint in a results directory. +""" + +import argparse +import datetime +import json +import os +import sys + +from common import PrintWithTime +from common import RunCommandPropagateErr +from githelper import GitHelper +from safetynet_conclusions import PrintConclusionsDictHumanReadable + + +class JobContext(object): + """Context for a single run, including name and directory paths.""" + + def __init__(self, args): + self.datetime = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + self.results_dir = args.results_dir + self.last_revision_covered_file = os.path.join(self.results_dir, + 'last_revision_covered') + self.run_output_dir = os.path.join(self.results_dir, + 'profiles_%s' % self.datetime) + self.run_output_log_file = os.path.join(self.results_dir, + '%s.log' % self.datetime) + + +class JobRun(object): + """A single run looking for regressions since the last one.""" + + def __init__(self, args, context): + """Constructor. + + Args: + args: Namespace with arguments passed to the script. + context: JobContext for this run. + """ + self.git = GitHelper() + self.args = args + self.context = context + + def Run(self): + """Searches for regressions. + + Will only write a checkpoint when first run, and on all subsequent runs + a comparison is done against the last checkpoint. + + Returns: + Exit code for the script: 0 if no significant changes are found; 1 if + there was an error in the comparison; 3 if there was a regression; 4 if + there was an improvement and no regression. + """ + pdfium_src_dir = os.path.join( + os.path.dirname(__file__), + os.path.pardir, + os.path.pardir) + os.chdir(pdfium_src_dir) + + if not self.git.IsCurrentBranchClean() and not self.args.no_checkout: + PrintWithTime('Current branch is not clean, aborting') + return 1 + + branch_to_restore = self.git.GetCurrentBranchName() + + if not self.args.no_checkout: + self.git.FetchOriginMaster() + self.git.Checkout('origin/master') + + # Make sure results dir exists + if not os.path.exists(self.context.results_dir): + os.makedirs(self.context.results_dir) + + if not os.path.exists(self.context.last_revision_covered_file): + result = self._InitialRun() + else: + with open(self.context.last_revision_covered_file) as f: + last_revision_covered = f.read().strip() + result = self._IncrementalRun(last_revision_covered) + + self.git.Checkout(branch_to_restore) + return result + + def _InitialRun(self): + """Initial run, just write a checkpoint. + + Returns: + Exit code for the script. + """ + current = self.git.GetCurrentBranchHash() + + PrintWithTime('Initial run, current is %s' % current) + + self._WriteCheckpoint(current) + + PrintWithTime('All set up, next runs will be incremental and perform ' + 'comparisons') + return 0 + + def _IncrementalRun(self, last_revision_covered): + """Incremental run, compare against last checkpoint and update it. + + Args: + last_revision_covered: String with hash for last checkpoint. + + Returns: + Exit code for the script. + """ + current = self.git.GetCurrentBranchHash() + + PrintWithTime('Incremental run, current is %s, last is %s' + % (current, last_revision_covered)) + + if not os.path.exists(self.context.run_output_dir): + os.makedirs(self.context.run_output_dir) + + if current == last_revision_covered: + PrintWithTime('No changes seen, finishing job') + output_info = { + 'metadata': self._BuildRunMetadata(last_revision_covered, + current, + False)} + self._WriteRawJson(output_info) + return 0 + + # Run compare + cmd = ['testing/tools/safetynet_compare.py', + '--this-repo', + '--machine-readable', + '--branch-before=%s' % last_revision_covered, + '--output-dir=%s' % self.context.run_output_dir] + cmd.extend(self.args.input_paths) + + json_output = RunCommandPropagateErr(cmd) + + if json_output is None: + return 1 + + output_info = json.loads(json_output) + + run_metadata = self._BuildRunMetadata(last_revision_covered, + current, + True) + output_info.setdefault('metadata', {}).update(run_metadata) + self._WriteRawJson(output_info) + + PrintConclusionsDictHumanReadable(output_info, + colored=(not self.args.output_to_log + and not self.args.no_color), + key='after') + + status = 0 + + if output_info['summary']['improvement']: + PrintWithTime('Improvement detected.') + status = 4 + + if output_info['summary']['regression']: + PrintWithTime('Regression detected.') + status = 3 + + if status == 0: + PrintWithTime('Nothing detected.') + + self._WriteCheckpoint(current) + + return status + + def _WriteRawJson(self, output_info): + json_output_file = os.path.join(self.context.run_output_dir, 'raw.json') + with open(json_output_file, 'w') as f: + json.dump(output_info, f) + + def _BuildRunMetadata(self, revision_before, revision_after, + comparison_performed): + return { + 'datetime': self.context.datetime, + 'revision_before': revision_before, + 'revision_after': revision_after, + 'comparison_performed': comparison_performed, + } + + def _WriteCheckpoint(self, checkpoint): + if not self.args.no_checkpoint: + with open(self.context.last_revision_covered_file, 'w') as f: + f.write(checkpoint + '\n') + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('results_dir', + help='where to write the job results') + parser.add_argument('input_paths', nargs='+', + help='pdf files or directories to search for pdf files ' + 'to run as test cases') + parser.add_argument('--no-checkout', action='store_true', + help='whether to skip checking out origin/master. Use ' + 'for script debugging.') + parser.add_argument('--no-checkpoint', action='store_true', + help='whether to skip writing the new checkpoint. Use ' + 'for script debugging.') + parser.add_argument('--no-color', action='store_true', + help='whether to write output without color escape ' + 'codes.') + parser.add_argument('--output-to-log', action='store_true', + help='whether to write output to a log file') + args = parser.parse_args() + + job_context = JobContext(args) + + if args.output_to_log: + log_file = open(job_context.run_output_log_file, 'w') + sys.stdout = log_file + sys.stderr = log_file + + run = JobRun(args, job_context) + result = run.Run() + + if args.output_to_log: + log_file.close() + + return result + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/testing/tools/safetynet_measure.py b/testing/tools/safetynet_measure.py new file mode 100755 index 0000000000000000000000000000000000000000..7b5bd5fe9d7df86657bd1e871713029746cf6457 --- /dev/null +++ b/testing/tools/safetynet_measure.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# Copyright 2017 The 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. + +"""Measures performance for rendering a single test case with pdfium. + +The output is a number that is a metric which depends on the profiler specified. +""" + +import argparse +import os +import re +import subprocess +import sys + +from common import PrintErr + + +CALLGRIND_PROFILER = 'callgrind' +PERFSTAT_PROFILER = 'perfstat' + +PDFIUM_TEST = 'pdfium_test' + +class PerformanceRun(object): + """A single measurement of a test case.""" + + def __init__(self, args): + self.args = args + self.pdfium_test_path = os.path.join(self.args.build_dir, PDFIUM_TEST) + + def _CheckTools(self): + """Returns whether the tool file paths are sane.""" + if not os.path.exists(self.pdfium_test_path): + PrintErr("FAILURE: Can't find test executable '%s'" + % self.pdfium_test_path) + PrintErr('Use --build-dir to specify its location.') + return False + if not os.access(self.pdfium_test_path, os.X_OK): + PrintErr("FAILURE: Test executable '%s' lacks execution permissions" + % self.pdfium_test_path) + return False + return True + + def Run(self): + """Runs test harness and measures performance with the given profiler. + + Returns: + Exit code for the script. + """ + if not self._CheckTools(): + return 1 + + if self.args.profiler == CALLGRIND_PROFILER: + time = self._RunCallgrind() + elif self.args.profiler == PERFSTAT_PROFILER: + time = self._RunPerfStat() + else: + PrintErr('profiler=%s not supported, aborting' % self.args.profiler) + return 1 + + if time is None: + return 1 + + print time + return 0 + + def _RunCallgrind(self): + """Runs test harness and measures performance with callgrind. + + Returns: + int with the result of the measurement, in instructions or time. + """ + # Whether to turn instrument the whole run or to use the callgrind macro + # delimiters in pdfium_test. + instrument_at_start = 'no' if self.args.interesting_section else 'yes' + output_path = self.args.output_path or '/dev/null' + + valgrind_cmd = (['valgrind', '--tool=callgrind', + '--instr-atstart=%s' % instrument_at_start, + '--callgrind-out-file=%s' % output_path] + + self._BuildTestHarnessCommand()) + output = subprocess.check_output(valgrind_cmd, stderr=subprocess.STDOUT) + + # Match the line with the instruction count, eg. + # '==98765== Collected : 12345' + return self._ExtractIrCount(r'\bCollected\b *: *\b(\d+)', output) + + def _RunPerfStat(self): + """Runs test harness and measures performance with perf stat. + + Returns: + int with the result of the measurement, in instructions or time. + """ + # --no-big-num: do not add thousands separators + # -einstructions: print only instruction count + cmd_to_run = (['perf', 'stat', '--no-big-num', '-einstructions'] + + self._BuildTestHarnessCommand()) + output = subprocess.check_output(cmd_to_run, stderr=subprocess.STDOUT) + + # Match the line with the instruction count, eg. + # ' 12345 instructions' + return self._ExtractIrCount(r'\b(\d+)\b.*\binstructions\b', output) + + def _BuildTestHarnessCommand(self): + """Builds command to run the test harness.""" + cmd = [self.pdfium_test_path, '--send-events'] + if self.args.interesting_section: + cmd.append('--callgrind-delim') + cmd.append(self.args.pdf_path) + return cmd + + def _ExtractIrCount(self, regex, output): + """Extracts a number from the output with a regex.""" + matched = re.search(regex, output) + + if not matched: + return None + + # Group 1 is the instruction number, eg. 12345 + return int(matched.group(1)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('pdf_path', + help='test case to measure load and rendering time') + parser.add_argument('--build-dir', default=os.path.join('out', 'Release'), + help='relative path to the build directory with ' + '%s' % PDFIUM_TEST) + parser.add_argument('--profiler', default=CALLGRIND_PROFILER, + help='which profiler to use. Supports callgrind and ' + 'perfstat for now.') + parser.add_argument('--interesting-section', action='store_true', + help='whether to measure just the interesting section or ' + 'the whole test harness. The interesting section is ' + 'pdfium reading a pdf from memory and rendering ' + 'it, which omits loading the time to load the file, ' + 'initialize the library, terminate it, etc. ' + 'Limiting to only the interesting section does not ' + 'work on Release since the delimiters are optimized ' + 'out. Callgrind only.') + parser.add_argument('--output-path', + help='where to write the profile data output file') + args = parser.parse_args() + + if args.interesting_section and args.profiler != CALLGRIND_PROFILER: + PrintErr('--interesting-section requires profiler to be callgrind.') + return 1 + + run = PerformanceRun(args) + return run.Run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/testing/tools/suppressor.py b/testing/tools/suppressor.py index 86d2668adbda433c332f1b274214f235d5017fc9..2b4b5d3f08ab29f885db9a6b09ef05ccdb2986d3 100755 --- a/testing/tools/suppressor.py +++ b/testing/tools/suppressor.py @@ -12,12 +12,16 @@ class Suppressor: feature_vector = feature_string.strip().split(",") self.has_v8 = "V8" in feature_vector self.has_xfa = "XFA" in feature_vector - self.is_asan = "ASAN" in feature_vector + self.suppression_set = self._LoadSuppressedSet('SUPPRESSIONS', finder) + self.image_suppression_set = self._LoadSuppressedSet( + 'SUPPRESSIONS_IMAGE_DIFF', + finder) + + def _LoadSuppressedSet(self, suppressions_filename, finder): v8_option = "v8" if self.has_v8 else "nov8" xfa_option = "xfa" if self.has_xfa else "noxfa" - - with open(os.path.join(finder.TestingDir(), 'SUPPRESSIONS')) as f: - self.suppression_set = set(self._FilterSuppressions( + with open(os.path.join(finder.TestingDir(), suppressions_filename)) as f: + return set(self._FilterSuppressions( common.os_name(), v8_option, xfa_option, self._ExtractSuppressions(f))) def _ExtractSuppressions(self, f): @@ -33,8 +37,6 @@ class Suppressor: os_column = item[1].split(","); js_column = item[2].split(","); xfa_column = item[3].split(","); - if self.is_asan and 'asan' in os_column: - return True return (('*' in os_column or os in os_column) and ('*' in js_column or js in js_column) and ('*' in xfa_column or xfa in xfa_column)) @@ -50,3 +52,9 @@ class Suppressor: print "%s execution is suppressed" % input_filepath return True return False + + def IsImageDiffSuppressed(self, input_filename): + if input_filename in self.image_suppression_set: + print "%s image diff comparison is suppressed" % input_filename + return True + return False diff --git a/testing/tools/test_runner.py b/testing/tools/test_runner.py index 6cd3a6c05abd7f569939ef7a8f8bf5b1cc551d36..e895552bc86799be20ef2a673ad5bcc4a33e12ee 100644 --- a/testing/tools/test_runner.py +++ b/testing/tools/test_runner.py @@ -39,6 +39,8 @@ def TestOneFileParallel(this, test_case): class TestRunner: def __init__(self, dirname): self.test_dir = dirname + self.enforce_expected_images = False + self.oneshot_renderer = False # GenerateAndTest returns a tuple where # success is a boolean indicating whether the tests passed comparison @@ -62,8 +64,8 @@ class TestRunner: raised_exception = self.Generate(source_dir, input_filename, input_root, pdf_path) - if raised_exception != None: - print "FAILURE: " + input_filename + "; " + str(raised_exception) + if raised_exception is not None: + print 'FAILURE: %s; %s' % (input_filename, raised_exception) return False, [] results = [] @@ -72,23 +74,35 @@ class TestRunner: else: raised_exception, results = self.TestPixel(input_root, pdf_path) - if raised_exception != None: - print "FAILURE: " + input_filename + "; " + str(raised_exception) + if raised_exception is not None: + print 'FAILURE: %s; %s' % (input_filename, raised_exception) return False, results - if len(actual_images): + if actual_images: if self.image_differ.HasDifferences(input_filename, source_dir, self.working_dir): + if (self.options.regenerate_expected + and not self.test_suppressor.IsResultSuppressed(input_filename) + and not self.test_suppressor.IsImageDiffSuppressed(input_filename)): + platform_only = (self.options.regenerate_expected == 'platform') + self.image_differ.Regenerate(input_filename, source_dir, + self.working_dir, platform_only) return False, results + else: + if (self.enforce_expected_images + and not self.test_suppressor.IsImageDiffSuppressed(input_filename)): + print 'FAILURE: %s; Missing expected images' % input_filename + return False, results + return True, results def Generate(self, source_dir, input_filename, input_root, pdf_path): original_path = os.path.join(source_dir, input_filename) input_path = os.path.join(source_dir, input_root + '.in') - input_event_path = os.path.join(source_dir, input_root + ".evt") + input_event_path = os.path.join(source_dir, input_root + '.evt') if os.path.exists(input_event_path): - output_event_path = os.path.splitext(pdf_path)[0] + ".evt" + output_event_path = os.path.splitext(pdf_path)[0] + '.evt' shutil.copyfile(input_event_path, output_event_path) if not os.path.exists(input_path): @@ -102,42 +116,51 @@ class TestRunner: [sys.executable, self.fixup_path, '--output-dir=' + self.working_dir, input_path]) - def TestText(self, input_root, expected_txt_path, pdf_path): txt_path = os.path.join(self.working_dir, input_root + '.txt') with open(txt_path, 'w') as outfile: - cmd_to_run = [self.pdfium_test_path, pdf_path] + cmd_to_run = [self.pdfium_test_path, '--send-events', pdf_path] subprocess.check_call(cmd_to_run, stdout=outfile) cmd = [sys.executable, self.text_diff_path, expected_txt_path, txt_path] return common.RunCommand(cmd) - def TestPixel(self, input_root, pdf_path): - cmd_to_run = [self.pdfium_test_path, '--send-events', '--png'] - if self.gold_results: - cmd_to_run.append('--md5') + cmd_to_run = [self.pdfium_test_path, '--send-events', '--png', '--md5'] + if self.oneshot_renderer: + cmd_to_run.append('--render-oneshot') cmd_to_run.append(pdf_path) return common.RunCommandExtractHashedFiles(cmd_to_run) def HandleResult(self, input_filename, input_path, result): success, image_paths = result - if self.gold_results: - if image_paths: - for img_path, md5_hash in image_paths: - # the output filename (without extension becomes the test name) - test_name = os.path.splitext(os.path.split(img_path)[1])[0] + + if image_paths: + for img_path, md5_hash in image_paths: + # The output filename without image extension becomes the test name. + # For example, "/path/to/.../testing/corpus/example_005.pdf.0.png" + # becomes "example_005.pdf.0". + test_name = os.path.splitext(os.path.split(img_path)[1])[0] + + if not self.test_suppressor.IsResultSuppressed(input_filename): + matched = self.gold_baseline.MatchLocalResult(test_name, md5_hash) + if matched == gold.GoldBaseline.MISMATCH: + print 'Skia Gold hash mismatch for test case: %s' % test_name + elif matched == gold.GoldBaseline.NO_BASELINE: + print 'No Skia Gold baseline found for test case: %s' % test_name + + if self.gold_results: self.gold_results.AddTestResult(test_name, md5_hash, img_path) if self.test_suppressor.IsResultSuppressed(input_filename): + self.result_suppressed_cases.append(input_filename) if success: self.surprises.append(input_path) else: if not success: self.failures.append(input_path) - def Run(self): parser = optparse.OptionParser() @@ -149,23 +172,41 @@ class TestRunner: help='run NUM_WORKERS jobs in parallel') parser.add_option('--gold_properties', default='', dest="gold_properties", - help='Key value pairs that are written to the top level of the JSON file that is ingested by Gold.') + help='Key value pairs that are written to the top level ' + 'of the JSON file that is ingested by Gold.') parser.add_option('--gold_key', default='', dest="gold_key", - help='Key value pairs that are added to the "key" field of the JSON file that is ingested by Gold.') + help='Key value pairs that are added to the "key" field ' + 'of the JSON file that is ingested by Gold.') parser.add_option('--gold_output_dir', default='', dest="gold_output_dir", - help='Path of where to write the JSON output to be uploaded to Gold.') + help='Path of where to write the JSON output to be ' + 'uploaded to Gold.') - parser.add_option('--gold_ignore_hashes', default='', dest="gold_ignore_hashes", + parser.add_option('--gold_ignore_hashes', default='', + dest="gold_ignore_hashes", help='Path to a file with MD5 hashes we wish to ignore.') - parser.add_option('--ignore_errors', action="store_true", dest="ignore_errors", - help='Prevents the return value from being non-zero when image comparison fails.') + parser.add_option('--regenerate_expected', default='', + dest="regenerate_expected", + help='Regenerates expected images. Valid values are ' + '"all" to regenerate all expected pngs, and ' + '"platform" to regenerate only platform-specific ' + 'expected pngs.') - options, args = parser.parse_args() + parser.add_option('--ignore_errors', action="store_true", + dest="ignore_errors", + help='Prevents the return value from being non-zero ' + 'when image comparison fails.') - finder = common.DirectoryFinder(options.build_dir) + self.options, self.args = parser.parse_args() + + if (self.options.regenerate_expected + and self.options.regenerate_expected not in ['all', 'platform']) : + print 'FAILURE: --regenerate_expected must be "all" or "platform"' + return 1 + + finder = common.DirectoryFinder(self.options.build_dir) self.fixup_path = finder.ScriptPath('fixup_pdf_template.py') self.text_diff_path = finder.ScriptPath('text_diff.py') @@ -178,7 +219,7 @@ class TestRunner: self.pdfium_test_path = finder.ExecutablePath('pdfium_test') if not os.path.exists(self.pdfium_test_path): print "FAILURE: Can't find test executable '%s'" % self.pdfium_test_path - print "Use --build-dir to specify its location." + print 'Use --build-dir to specify its location.' return 1 self.working_dir = finder.WorkingDir(os.path.join('testing', self.test_dir)) @@ -190,47 +231,53 @@ class TestRunner: self.test_suppressor = suppressor.Suppressor(finder, self.feature_string) self.image_differ = pngdiffer.PNGDiffer(finder) + self.gold_baseline = gold.GoldBaseline(self.options.gold_properties) + walk_from_dir = finder.TestingDir(test_dir); - test_cases = [] - input_file_re = re.compile('^[a-zA-Z0-9_.]+[.](in|pdf)$') - if len(args): - for file_name in args: - file_name.replace(".pdf", ".in") + self.test_cases = [] + self.execution_suppressed_cases = [] + input_file_re = re.compile('^.+[.](in|pdf)$') + if self.args: + for file_name in self.args: + file_name.replace('.pdf', '.in') input_path = os.path.join(walk_from_dir, file_name) if not os.path.isfile(input_path): print "Can't find test file '%s'" % file_name return 1 - test_cases.append((os.path.basename(input_path), + self.test_cases.append((os.path.basename(input_path), os.path.dirname(input_path))) else: for file_dir, _, filename_list in os.walk(walk_from_dir): for input_filename in filename_list: if input_file_re.match(input_filename): input_path = os.path.join(file_dir, input_filename) - if not self.test_suppressor.IsExecutionSuppressed(input_path): + if self.test_suppressor.IsExecutionSuppressed(input_path): + self.execution_suppressed_cases.append(input_path) + else: if os.path.isfile(input_path): - test_cases.append((input_filename, file_dir)) + self.test_cases.append((input_filename, file_dir)) self.failures = [] self.surprises = [] + self.result_suppressed_cases = [] # Collect Gold results if an output directory was named. self.gold_results = None - if options.gold_output_dir: - self.gold_results = gold.GoldResults("pdfium", - options.gold_output_dir, - options.gold_properties, - options.gold_key, - options.gold_ignore_hashes) - - if options.num_workers > 1 and len(test_cases) > 1: + if self.options.gold_output_dir: + self.gold_results = gold.GoldResults('pdfium', + self.options.gold_output_dir, + self.options.gold_properties, + self.options.gold_key, + self.options.gold_ignore_hashes) + + if self.options.num_workers > 1 and len(self.test_cases) > 1: try: - pool = multiprocessing.Pool(options.num_workers) + pool = multiprocessing.Pool(self.options.num_workers) worker_func = functools.partial(TestOneFileParallel, self) - worker_results = pool.imap(worker_func, test_cases) + worker_results = pool.imap(worker_func, self.test_cases) for worker_result in worker_results: result, input_filename, source_dir = worker_result input_path = os.path.join(source_dir, input_filename) @@ -243,7 +290,7 @@ class TestRunner: pool.close() pool.join() else: - for test_case in test_cases: + for test_case in self.test_cases: input_filename, input_file_dir = test_case result = self.GenerateAndTest(input_filename, input_file_dir) self.HandleResult(input_filename, @@ -256,7 +303,7 @@ class TestRunner: self.surprises.sort() print '\n\nUnexpected Successes:' for surprise in self.surprises: - print surprise; + print surprise if self.failures: self.failures.sort() @@ -264,6 +311,33 @@ class TestRunner: for failure in self.failures: print failure - if not options.ignore_errors: + self._PrintSummary() + + if self.failures: + if not self.options.ignore_errors: return 1 + return 0 + + def _PrintSummary(self): + number_test_cases = len(self.test_cases) + number_failures = len(self.failures) + number_suppressed = len(self.result_suppressed_cases) + number_successes = number_test_cases - number_failures - number_suppressed + number_surprises = len(self.surprises) + print + print 'Test cases executed: %d' % number_test_cases + print ' Successes: %d' % number_successes + print ' Suppressed: %d' % number_suppressed + print ' Surprises: %d' % number_surprises + print ' Failures: %d' % number_failures + print + print 'Test cases not executed: %d' % len(self.execution_suppressed_cases) + + def SetEnforceExpectedImages(self, new_value): + """Set whether to enforce that each test case provide an expected image.""" + self.enforce_expected_images = new_value + + def SetOneShotRenderer(self, new_value): + """Set whether to use the oneshot renderer. """ + self.oneshot_renderer = new_value diff --git a/testing/unit_test_main.cpp b/testing/unit_test_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64b12993a9f6e5414c4ee516aaf2f2a33a1db4e1 --- /dev/null +++ b/testing/unit_test_main.cpp @@ -0,0 +1,67 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "core/fxcrt/fx_memory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if PDF_ENABLE_XFA +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +namespace { + +// The loading time of the CFGAS_FontMgr is linear in the number of times it is +// loaded. So, if a test suite has a lot of tests that need a font manager they +// can end up executing very, very slowly. +class Environment : public testing::Environment { + public: + void SetUp() override { + // TODO(dsinclair): This font loading is slow. We should make a test font + // loader which loads up a single font we use in all tests. + CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo( + IFX_SystemFontInfo::CreateDefault(nullptr)); + + font_mgr_ = pdfium::MakeUnique(); + if (!font_mgr_->EnumFonts()) + font_mgr_ = nullptr; + } + + void TearDown() override { + font_mgr_.reset(); + } + CFGAS_FontMgr* FontManager() const { return font_mgr_.get(); } + + private: + std::unique_ptr font_mgr_; +}; + +Environment* env_ = nullptr; + +} // namespace + +CFGAS_FontMgr* GetGlobalFontManager() { + return env_->FontManager(); +} +#endif // PDF_ENABLE_XFA + +// Can't use gtest-provided main since we need to initialize partition +// alloc before invoking any test. +int main(int argc, char** argv) { + FXMEM_InitializePartitionAlloc(); + +#if PDF_ENABLE_XFA + env_ = new Environment(); + // The env will be deleted by gtest. + AddGlobalTestEnvironment(env_); +#endif // PDF_ENABLE_XFA + + testing::InitGoogleTest(&argc, argv); + testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/testing/xfa_js_embedder_test.cpp b/testing/xfa_js_embedder_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d007c87f65f69cef4e57fae22b9ba908bee4b06f --- /dev/null +++ b/testing/xfa_js_embedder_test.cpp @@ -0,0 +1,81 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/xfa_js_embedder_test.h" + +#include + +#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" +#include "fpdfsdk/fsdk_define.h" +#include "fxjs/cfxjse_engine.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +XFAJSEmbedderTest::XFAJSEmbedderTest() + : array_buffer_allocator_(pdfium::MakeUnique()) { +} + +XFAJSEmbedderTest::~XFAJSEmbedderTest() {} + +void XFAJSEmbedderTest::SetUp() { + v8::Isolate::CreateParams params; + params.array_buffer_allocator = array_buffer_allocator_.get(); + isolate_ = v8::Isolate::New(params); + ASSERT_TRUE(isolate_); + + EmbedderTest::SetExternalIsolate(isolate_); + EmbedderTest::SetUp(); +} + +void XFAJSEmbedderTest::TearDown() { + value_.reset(); + script_context_ = nullptr; + + EmbedderTest::TearDown(); + + isolate_->Dispose(); + isolate_ = nullptr; +} + +CXFA_Document* XFAJSEmbedderTest::GetXFADocument() { + return UnderlyingFromFPDFDocument(document())->GetXFADoc()->GetXFADoc(); +} + +bool XFAJSEmbedderTest::OpenDocumentWithOptions(const std::string& filename, + const char* password, + bool must_linearize) { + if (!EmbedderTest::OpenDocumentWithOptions(filename, password, + must_linearize)) + return false; + + script_context_ = GetXFADocument()->GetScriptContext(); + return true; +} + +bool XFAJSEmbedderTest::Execute(const ByteStringView& input) { + if (ExecuteHelper(input)) { + return true; + } + + CFXJSE_Value msg(GetIsolate()); + value_->GetObjectPropertyByIdx(1, &msg); + fprintf(stderr, "JS: %.*s\n", static_cast(input.GetLength()), + input.unterminated_c_str()); + // If the parsing of the input fails, then v8 will not run, so there will be + // no value here to print. + if (msg.IsString() && !msg.ToWideString().IsEmpty()) + fprintf(stderr, "JS ERROR: %ls\n", msg.ToWideString().c_str()); + return false; +} + +bool XFAJSEmbedderTest::ExecuteSilenceFailure(const ByteStringView& input) { + return ExecuteHelper(input); +} + +bool XFAJSEmbedderTest::ExecuteHelper(const ByteStringView& input) { + value_ = pdfium::MakeUnique(GetIsolate()); + return script_context_->RunScript(CXFA_Script::Type::Formcalc, + WideString::FromUTF8(input).AsStringView(), + value_.get(), GetXFADocument()->GetRoot()); +} diff --git a/testing/xfa_js_embedder_test.h b/testing/xfa_js_embedder_test.h new file mode 100644 index 0000000000000000000000000000000000000000..5f4549601c242f484d8c93f3309919dc91c0e955 --- /dev/null +++ b/testing/xfa_js_embedder_test.h @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TESTING_XFA_JS_EMBEDDER_TEST_H_ +#define TESTING_XFA_JS_EMBEDDER_TEST_H_ + +#include +#include + +#include "fxjs/cfxjse_value.h" +#include "fxjs/fxjs_v8.h" +#include "testing/embedder_test.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_object.h" + +class CFXJSE_Engine; + +class XFAJSEmbedderTest : public EmbedderTest { + public: + XFAJSEmbedderTest(); + ~XFAJSEmbedderTest() override; + + // EmbedderTest: + void SetUp() override; + void TearDown() override; + bool OpenDocumentWithOptions(const std::string& filename, + const char* password, + bool must_linearize) override; + + v8::Isolate* GetIsolate() const { return isolate_; } + CXFA_Document* GetXFADocument(); + + bool Execute(const ByteStringView& input); + bool ExecuteSilenceFailure(const ByteStringView& input); + + CFXJSE_Value* GetValue() const { return value_.get(); } + + private: + std::unique_ptr array_buffer_allocator_; + std::unique_ptr value_; + v8::Isolate* isolate_ = nullptr; + CFXJSE_Engine* script_context_ = nullptr; + + bool ExecuteHelper(const ByteStringView& input); +}; + +#endif // TESTING_XFA_JS_EMBEDDER_TEST_H_ diff --git a/third_party/Android.bp b/third_party/Android.bp index fe99487e8c2ae1ed6af6163a1e57b1aef2b20d89..2d294e0d2642b7ba4bc275cb81743e1f383c1cd3 100644 --- a/third_party/Android.bp +++ b/third_party/Android.bp @@ -1,8 +1,14 @@ +cc_defaults { + name: "pdfium-third-party", + defaults: [ + "pdfium-common" + ], +} + build = [ - "pdfiumagg23.bp", + "pdfiumfx_agg.bp", "pdfiumbigint.bp", - "pdfiumlcms.bp", - "pdfiumjpeg.bp", - "pdfiumopenjpeg.bp", - "pdfiumzlib.bp", + "pdfiumlcms2.bp", + "pdfiumpdfiumbase.bp", + "pdfiumfx_libopenjpeg.bp", ] diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn index 50ab7070588609cbd14c00d8a67e33df63b11478..1cfee77c60e8bffdf092f0991c0d87f3b6c3487d 100644 --- a/third_party/BUILD.gn +++ b/third_party/BUILD.gn @@ -3,15 +3,19 @@ # found in the LICENSE file. import("//build/config/arm.gni") +import("//build/config/jumbo.gni") +import("//build/config/linux/pkg_config.gni") import("//build_overrides/build.gni") import("../pdfium.gni") group("third_party") { deps = [ ":bigint", - ":fx_freetype", ":pdfium_base", ] + if (pdf_bundle_freetype) { + deps += [ ":fx_freetype" ] + } } config("pdfium_third_party_config") { @@ -38,64 +42,152 @@ static_library("bigint") { ] } -config("fx_freetype_warnings") { - visibility = [ ":*" ] - if (is_clang) { - # open_face_PS_from_sfnt_stream() and open_face_from_buffer() in - # ftbase.h are unused. - cflags = [ "-Wno-unused-function" ] +if (pdf_bundle_freetype) { + config("fx_freetype_warnings") { + visibility = [ ":*" ] + if (is_clang) { + # open_face_PS_from_sfnt_stream() and open_face_from_buffer() in + # ftbase.h are unused. + # + # ttgload.c casts from unsigned int to unsigned long to void*. + cflags = [ + "-Wno-unused-function", + "-Wno-int-to-void-pointer-cast", + ] + } } -} -# Tests may link against this even if the production library doesn't, -# so it needs to be separate from it. -static_library("fx_freetype") { - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ - "//build/config/compiler:no_chromium_code", - ":pdfium_third_party_config", + config("freetype_public_includes_config") { + # The relative freetype/include path points to PDFium's custom config. + # The absolute path points to whatever copy of FreeType is in + # //third_party/freetype. + include_dirs = [ + "freetype/include", + "//third_party/freetype/src/include", + ] + defines = [ + # GN currently does not escape '<' and '>' when generating xml based + # Visual Studio project files. As a result, use quotes instead of pointy + # brackets in these defines. + "FT_CONFIG_MODULES_H=\"freetype-custom-config/ftmodule.h\"", + "FT_CONFIG_OPTIONS_H=\"freetype-custom-config/ftoption.h\"", + ] + } - # Must be after no_chromium_code for warning flags to be ordered correctly. - ":fx_freetype_warnings", - ] - defines = [ "FT2_BUILD_LIBRARY" ] - sources = [ - "freetype/include/freetype/freetype.h", - "freetype/include/freetype/ftmm.h", - "freetype/include/freetype/ftotval.h", - "freetype/include/freetype/ftoutln.h", - "freetype/include/freetype/internal/ftobjs.h", - "freetype/include/freetype/internal/ftstream.h", - "freetype/include/freetype/internal/tttypes.h", - "freetype/include/freetype/tttables.h", - "freetype/include/ft2build.h", - "freetype/src/base/ftbase.c", - "freetype/src/base/ftbase.h", - "freetype/src/base/ftbitmap.c", - "freetype/src/base/ftglyph.c", - "freetype/src/base/ftinit.c", - "freetype/src/base/ftlcdfil.c", - "freetype/src/base/ftmm.c", - "freetype/src/base/ftsystem.c", - "freetype/src/cff/cff.c", - "freetype/src/cff/cffobjs.h", - "freetype/src/cff/cfftypes.h", - "freetype/src/cid/type1cid.c", - "freetype/src/psaux/psaux.c", - "freetype/src/pshinter/pshinter.c", - "freetype/src/psnames/psmodule.c", - "freetype/src/raster/raster.c", - "freetype/src/sfnt/sfnt.c", - "freetype/src/smooth/smooth.c", - "freetype/src/truetype/truetype.c", - "freetype/src/type1/type1.c", - ] - if (pdf_use_skia || pdf_use_skia_paths) { - sources += [ - "freetype/src/base/ftfntfmt.c", - "freetype/src/base/ftfstype.c", - "freetype/src/base/fttype1.c", + # Tests may link against this even if the production library doesn't, + # so it needs to be separate from it. + jumbo_static_library("fx_freetype") { + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + ":pdfium_third_party_config", + + # Must be after no_chromium_code for warning flags to be ordered correctly. + ":fx_freetype_warnings", ] + + public_configs = [ ":freetype_public_includes_config" ] + + defines = [ "FT2_BUILD_LIBRARY" ] + sources = [ + "//third_party/freetype/include/pstables.h", + "//third_party/freetype/src/include/freetype/config/ftconfig.h", + "//third_party/freetype/src/include/freetype/config/ftheader.h", + "//third_party/freetype/src/include/freetype/config/ftstdlib.h", + "//third_party/freetype/src/include/freetype/freetype.h", + "//third_party/freetype/src/include/freetype/ftadvanc.h", + "//third_party/freetype/src/include/freetype/ftbitmap.h", + "//third_party/freetype/src/include/freetype/ftcffdrv.h", + "//third_party/freetype/src/include/freetype/fterrdef.h", + "//third_party/freetype/src/include/freetype/fterrors.h", + "//third_party/freetype/src/include/freetype/ftfntfmt.h", + "//third_party/freetype/src/include/freetype/ftglyph.h", + "//third_party/freetype/src/include/freetype/ftgzip.h", + "//third_party/freetype/src/include/freetype/ftimage.h", + "//third_party/freetype/src/include/freetype/ftincrem.h", + "//third_party/freetype/src/include/freetype/ftlcdfil.h", + "//third_party/freetype/src/include/freetype/ftlist.h", + "//third_party/freetype/src/include/freetype/ftmm.h", + "//third_party/freetype/src/include/freetype/ftmodapi.h", + "//third_party/freetype/src/include/freetype/ftmoderror.h", + "//third_party/freetype/src/include/freetype/ftobjs.h", + "//third_party/freetype/src/include/freetype/ftotval.h", + "//third_party/freetype/src/include/freetype/ftoutln.h", + "//third_party/freetype/src/include/freetype/ftrender.h", + "//third_party/freetype/src/include/freetype/ftsizes.h", + "//third_party/freetype/src/include/freetype/ftsnames.h", + "//third_party/freetype/src/include/freetype/ftstream.h", + "//third_party/freetype/src/include/freetype/ftsystem.h", + "//third_party/freetype/src/include/freetype/fttrigon.h", + "//third_party/freetype/src/include/freetype/ftttdrv.h", + "//third_party/freetype/src/include/freetype/fttypes.h", + "//third_party/freetype/src/include/freetype/internal/autohint.h", + "//third_party/freetype/src/include/freetype/internal/ftcalc.h", + "//third_party/freetype/src/include/freetype/internal/ftdebug.h", + "//third_party/freetype/src/include/freetype/internal/ftdriver.h", + "//third_party/freetype/src/include/freetype/internal/ftgloadr.h", + "//third_party/freetype/src/include/freetype/internal/fthash.h", + "//third_party/freetype/src/include/freetype/internal/ftmemory.h", + "//third_party/freetype/src/include/freetype/internal/ftobjs.h", + "//third_party/freetype/src/include/freetype/internal/ftpic.h", + "//third_party/freetype/src/include/freetype/internal/ftrfork.h", + "//third_party/freetype/src/include/freetype/internal/ftserv.h", + "//third_party/freetype/src/include/freetype/internal/ftstream.h", + "//third_party/freetype/src/include/freetype/internal/ftvalid.h", + "//third_party/freetype/src/include/freetype/internal/internal.h", + "//third_party/freetype/src/include/freetype/internal/psaux.h", + "//third_party/freetype/src/include/freetype/internal/pshints.h", + "//third_party/freetype/src/include/freetype/internal/services/svcid.h", + "//third_party/freetype/src/include/freetype/internal/services/svfntfmt.h", + "//third_party/freetype/src/include/freetype/internal/services/svgldict.h", + "//third_party/freetype/src/include/freetype/internal/services/svkern.h", + "//third_party/freetype/src/include/freetype/internal/services/svmetric.h", + "//third_party/freetype/src/include/freetype/internal/services/svmm.h", + "//third_party/freetype/src/include/freetype/internal/services/svpostnm.h", + "//third_party/freetype/src/include/freetype/internal/services/svprop.h", + "//third_party/freetype/src/include/freetype/internal/services/svpscmap.h", + "//third_party/freetype/src/include/freetype/internal/services/svpsinfo.h", + "//third_party/freetype/src/include/freetype/internal/services/svsfnt.h", + "//third_party/freetype/src/include/freetype/internal/services/svttcmap.h", + "//third_party/freetype/src/include/freetype/internal/services/svtteng.h", + "//third_party/freetype/src/include/freetype/internal/services/svttglyf.h", + "//third_party/freetype/src/include/freetype/internal/sfnt.h", + "//third_party/freetype/src/include/freetype/internal/t1types.h", + "//third_party/freetype/src/include/freetype/internal/tttypes.h", + "//third_party/freetype/src/include/freetype/t1tables.h", + "//third_party/freetype/src/include/freetype/ttnameid.h", + "//third_party/freetype/src/include/freetype/tttables.h", + "//third_party/freetype/src/include/freetype/tttags.h", + "//third_party/freetype/src/include/ft2build.h", + "//third_party/freetype/src/src/base/ftbase.c", + "//third_party/freetype/src/src/base/ftbase.h", + "//third_party/freetype/src/src/base/ftbitmap.c", + "//third_party/freetype/src/src/base/ftfntfmt.c", + "//third_party/freetype/src/src/base/ftglyph.c", + "//third_party/freetype/src/src/base/ftinit.c", + "//third_party/freetype/src/src/base/ftlcdfil.c", + "//third_party/freetype/src/src/base/ftmm.c", + "//third_party/freetype/src/src/base/ftsystem.c", + "//third_party/freetype/src/src/cff/cff.c", + "//third_party/freetype/src/src/cff/cffobjs.h", + "//third_party/freetype/src/src/cff/cfftypes.h", + "//third_party/freetype/src/src/cid/type1cid.c", + "//third_party/freetype/src/src/psaux/psaux.c", + "//third_party/freetype/src/src/pshinter/pshinter.c", + "//third_party/freetype/src/src/psnames/psmodule.c", + "//third_party/freetype/src/src/raster/raster.c", + "//third_party/freetype/src/src/sfnt/sfnt.c", + "//third_party/freetype/src/src/smooth/smooth.c", + "//third_party/freetype/src/src/truetype/truetype.c", + "//third_party/freetype/src/src/type1/type1.c", + ] + if (pdf_use_skia || pdf_use_skia_paths) { + sources += [ + "//third_party/freetype/src/include/freetype/ftsynth.h", + "//third_party/freetype/src/src/base/ftfstype.c", + "//third_party/freetype/src/src/base/fttype1.c", + ] + } } } @@ -108,7 +200,7 @@ if (!pdf_use_skia && !pdf_use_skia_paths) { } } - static_library("fx_agg") { + jumbo_static_library("fx_agg") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code", @@ -158,119 +250,111 @@ static_library("fx_lcms2") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code", + "//build/config/sanitizers:cfi_icall_generalize_pointers", ":pdfium_third_party_config", # Must be after no_chromium_code for warning flags to be ordered correctly. ":fx_lcms2_warnings", ] sources = [ - "lcms2-2.6/include/lcms2.h", - "lcms2-2.6/include/lcms2_plugin.h", - "lcms2-2.6/src/cmscam02.c", - "lcms2-2.6/src/cmscgats.c", - "lcms2-2.6/src/cmscnvrt.c", - "lcms2-2.6/src/cmserr.c", - "lcms2-2.6/src/cmsgamma.c", - "lcms2-2.6/src/cmsgmt.c", - "lcms2-2.6/src/cmshalf.c", - "lcms2-2.6/src/cmsintrp.c", - "lcms2-2.6/src/cmsio0.c", - "lcms2-2.6/src/cmsio1.c", - "lcms2-2.6/src/cmslut.c", - "lcms2-2.6/src/cmsmd5.c", - "lcms2-2.6/src/cmsmtrx.c", - "lcms2-2.6/src/cmsnamed.c", - "lcms2-2.6/src/cmsopt.c", - "lcms2-2.6/src/cmspack.c", - "lcms2-2.6/src/cmspcs.c", - "lcms2-2.6/src/cmsplugin.c", - "lcms2-2.6/src/cmsps2.c", - "lcms2-2.6/src/cmssamp.c", - "lcms2-2.6/src/cmssm.c", - "lcms2-2.6/src/cmstypes.c", - "lcms2-2.6/src/cmsvirt.c", - "lcms2-2.6/src/cmswtpnt.c", - "lcms2-2.6/src/cmsxform.c", + "lcms/include/lcms2.h", + "lcms/include/lcms2_plugin.h", + "lcms/src/cmsalpha.c", + "lcms/src/cmscam02.c", + "lcms/src/cmscgats.c", + "lcms/src/cmscnvrt.c", + "lcms/src/cmserr.c", + "lcms/src/cmsgamma.c", + "lcms/src/cmsgmt.c", + "lcms/src/cmshalf.c", + "lcms/src/cmsintrp.c", + "lcms/src/cmsio0.c", + "lcms/src/cmsio1.c", + "lcms/src/cmslut.c", + "lcms/src/cmsmd5.c", + "lcms/src/cmsmtrx.c", + "lcms/src/cmsnamed.c", + "lcms/src/cmsopt.c", + "lcms/src/cmspack.c", + "lcms/src/cmspcs.c", + "lcms/src/cmsplugin.c", + "lcms/src/cmsps2.c", + "lcms/src/cmssamp.c", + "lcms/src/cmssm.c", + "lcms/src/cmstypes.c", + "lcms/src/cmsvirt.c", + "lcms/src/cmswtpnt.c", + "lcms/src/cmsxform.c", ] } -# This is only used for standalone builds. -config("jpeg_warnings") { - visibility = [ ":*" ] - if (is_clang) { - cflags = [ "-Wno-shift-negative-value" ] +if (!build_with_chromium) { + declare_args() { + # Uses system libjpeg. If true, overrides use_libjpeg_turbo. + use_system_libjpeg = false + + # Uses libjpeg_turbo as the jpeg implementation. Has no effect if + # use_system_libjpeg is set. + use_libjpeg_turbo = true + } + + config("system_libjpeg_config") { + libs = [ "jpeg" ] + defines = [ "USE_SYSTEM_LIBJPEG" ] + } + + config("libjpeg_turbo_config") { + defines = [ "USE_LIBJPEG_TURBO=1" ] + } + + # This is a meta target that forwards to the system's libjpeg, + # third_party/libjpeg, or third_party/libjpeg_turbo depending on the build args + # declared in this file. + group("jpeg") { + if (use_system_libjpeg) { + public_configs = [ ":system_libjpeg_config" ] + } else if (use_libjpeg_turbo) { + public_deps = [ + "//third_party/libjpeg_turbo:libjpeg", + ] + public_configs = [ ":libjpeg_turbo_config" ] + } else { + public_deps = [ + "//third_party/libjpeg:libjpeg", + ] + } } } -static_library("jpeg") { - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ - "//build/config/compiler:no_chromium_code", - ":pdfium_third_party_config", +config("system_zlib_config") { + libs = [ "z" ] + defines = [ "USE_SYSTEM_ZLIB" ] +} - # Must be after no_chromium_code for warning flags to be ordered correctly. - ":jpeg_warnings", - ] - sources = [ - "libjpeg/cderror.h", - "libjpeg/cdjpeg.h", - "libjpeg/fpdfapi_jcapimin.c", - "libjpeg/fpdfapi_jcapistd.c", - "libjpeg/fpdfapi_jccoefct.c", - "libjpeg/fpdfapi_jccolor.c", - "libjpeg/fpdfapi_jcdctmgr.c", - "libjpeg/fpdfapi_jchuff.c", - "libjpeg/fpdfapi_jcinit.c", - "libjpeg/fpdfapi_jcmainct.c", - "libjpeg/fpdfapi_jcmarker.c", - "libjpeg/fpdfapi_jcmaster.c", - "libjpeg/fpdfapi_jcomapi.c", - "libjpeg/fpdfapi_jcparam.c", - "libjpeg/fpdfapi_jcphuff.c", - "libjpeg/fpdfapi_jcprepct.c", - "libjpeg/fpdfapi_jcsample.c", - "libjpeg/fpdfapi_jctrans.c", - "libjpeg/fpdfapi_jdapimin.c", - "libjpeg/fpdfapi_jdapistd.c", - "libjpeg/fpdfapi_jdcoefct.c", - "libjpeg/fpdfapi_jdcolor.c", - "libjpeg/fpdfapi_jddctmgr.c", - "libjpeg/fpdfapi_jdhuff.c", - "libjpeg/fpdfapi_jdinput.c", - "libjpeg/fpdfapi_jdmainct.c", - "libjpeg/fpdfapi_jdmarker.c", - "libjpeg/fpdfapi_jdmaster.c", - "libjpeg/fpdfapi_jdmerge.c", - "libjpeg/fpdfapi_jdphuff.c", - "libjpeg/fpdfapi_jdpostct.c", - "libjpeg/fpdfapi_jdsample.c", - "libjpeg/fpdfapi_jdtrans.c", - "libjpeg/fpdfapi_jerror.c", - "libjpeg/fpdfapi_jfdctfst.c", - "libjpeg/fpdfapi_jfdctint.c", - "libjpeg/fpdfapi_jidctfst.c", - "libjpeg/fpdfapi_jidctint.c", - "libjpeg/fpdfapi_jidctred.c", - "libjpeg/fpdfapi_jmemmgr.c", - "libjpeg/fpdfapi_jmemnobs.c", - "libjpeg/fpdfapi_jutils.c", - "libjpeg/jchuff.h", - "libjpeg/jconfig.h", - "libjpeg/jdct.h", - "libjpeg/jdhuff.h", - "libjpeg/jerror.h", - "libjpeg/jinclude.h", - "libjpeg/jmemsys.h", - "libjpeg/jmorecfg.h", - "libjpeg/jpegint.h", - "libjpeg/jpeglib.h", - "libjpeg/jversion.h", - "libjpeg/makefile", - "libjpeg/transupp.h", - ] - deps = [ - "..:fxcrt", - ] +group("zlib") { + if (use_system_zlib) { + public_configs = [ ":system_zlib_config" ] + } else { + public_deps = [ + "//third_party/zlib", + ] + } +} + +if (use_system_lcms2) { + pkg_config("lcms2_from_pkgconfig") { + defines = [ "USE_SYSTEM_LCMS2" ] + packages = [ "lcms2" ] + } +} +group("lcms2") { + if (use_system_lcms2) { + public_configs = [ ":lcms2_from_pkgconfig" ] + } else { + public_deps = [ + ":fx_lcms2", + ] + } } config("fx_libopenjpeg_warnings") { @@ -307,15 +391,32 @@ static_library("fx_libopenjpeg") { "libopenjpeg20/openjpeg.c", "libopenjpeg20/opj_clock.c", "libopenjpeg20/pi.c", - "libopenjpeg20/raw.c", + "libopenjpeg20/sparse_array.c", + "libopenjpeg20/sparse_array.h", "libopenjpeg20/t1.c", "libopenjpeg20/t2.c", "libopenjpeg20/tcd.c", "libopenjpeg20/tgt.c", + "libopenjpeg20/thread.c", ] } -static_library("fx_lpng") { +config("system_libpng_config") { + libs = [ "png" ] + defines = [ "USE_SYSTEM_LIBPNG" ] +} + +group("png") { + if (use_system_libpng) { + public_configs = [ ":system_libpng_config" ] + } else { + public_deps = [ + ":fx_lpng", + ] + } +} + +jumbo_static_library("fx_lpng") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code", @@ -349,6 +450,9 @@ static_library("fx_lpng") { defines = [] cflags = [] + deps = [ + ":zlib", + ] if (current_cpu == "x86" || current_cpu == "x64") { sources += [ @@ -386,6 +490,7 @@ if (pdf_enable_xfa) { configs -= [ "//build/config/win:lean_and_mean" ] } deps = [ + ":zlib", "//third_party:jpeg", ] sources = [ @@ -430,57 +535,36 @@ if (pdf_enable_xfa) { } } -# TODO(dsinclair): Remove if fixed upstream. https://crbug.com/507712 -config("fx_zlib_warnings") { - visibility = [ ":*" ] - if (is_clang) { - cflags = [ "-Wno-shift-negative-value" ] - } -} - -static_library("fx_zlib") { - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ - "//build/config/compiler:no_chromium_code", - ":pdfium_third_party_config", - - # Must be after no_chromium_code for warning flags to be ordered correctly. - ":fx_zlib_warnings", - ] - sources = [ - "zlib_v128/adler32.c", - "zlib_v128/compress.c", - "zlib_v128/crc32.c", - "zlib_v128/deflate.c", - "zlib_v128/gzclose.c", - "zlib_v128/gzlib.c", - "zlib_v128/gzread.c", - "zlib_v128/gzwrite.c", - "zlib_v128/infback.c", - "zlib_v128/inffast.c", - "zlib_v128/inflate.c", - "zlib_v128/inftrees.c", - "zlib_v128/trees.c", - "zlib_v128/uncompr.c", - "zlib_v128/zutil.c", - ] -} - -# Can not be a static library due to lack of .cc files. -source_set("pdfium_base") { +jumbo_source_set("pdfium_base") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code", ":pdfium_third_party_config", ] sources = [ + "base/allocator/partition_allocator/address_space_randomization.cc", + "base/allocator/partition_allocator/address_space_randomization.h", + "base/allocator/partition_allocator/oom.h", + "base/allocator/partition_allocator/page_allocator.cc", + "base/allocator/partition_allocator/page_allocator.h", + "base/allocator/partition_allocator/partition_alloc.cc", + "base/allocator/partition_allocator/partition_alloc.h", + "base/allocator/partition_allocator/spin_lock.cc", + "base/allocator/partition_allocator/spin_lock.h", + "base/base_export.h", + "base/bits.h", + "base/compiler_specific.h", "base/logging.h", "base/macros.h", "base/numerics/safe_conversions.h", "base/numerics/safe_conversions_impl.h", "base/numerics/safe_math.h", "base/numerics/safe_math_impl.h", + "base/optional.h", "base/ptr_util.h", "base/stl_util.h", + "base/sys_byteorder.h", + "base/template_util.h", + "build/build_config.h", ] } diff --git a/third_party/DEPS b/third_party/DEPS index c2a3adde7b81a22ef790ace27e774ea111cd1167..93ca1a0bd49032fe4feb755df54e9e19f2c56d00 100644 --- a/third_party/DEPS +++ b/third_party/DEPS @@ -1,7 +1,7 @@ include_rules = [ # A lot of third_party code has been modified to use fxcrt. - '+core/fxcrt/fx_basic.h', '+core/fxcrt/fx_coordinates.h', '+core/fxcrt/fx_memory.h', '+core/fxcrt/fx_system.h', + '+build', ] diff --git a/third_party/agg23/0000-bug-466.patch b/third_party/agg23/0000-bug-466.patch index 3217b3838a9fdd07d96dc7840d4fd9de4b329381..e761198a48b16d0f081602fe895d019ae1ccea77 100644 --- a/third_party/agg23/0000-bug-466.patch +++ b/third_party/agg23/0000-bug-466.patch @@ -4,7 +4,7 @@ index 6d7ba8a..2b06b1b 100644 +++ b/third_party/agg23/agg_math_stroke.h @@ -60,28 +60,30 @@ void stroke_calc_arc(VertexConsumer& out_vertices, } - da = FXSYS_acos(width / (width + ((1.0f / 8) / approximation_scale))) * 2; + da = acos(width / (width + ((1.0f / 8) / approximation_scale))) * 2; out_vertices.add(coord_type(x + dx1, y + dy1)); - if(!ccw) { - if(a1 > a2) { @@ -18,8 +18,8 @@ index 6d7ba8a..2b06b1b 100644 a1 += da; - while(a1 < a2) { + while (a1 < a2) { - out_vertices.add(coord_type(x + (width * FXSYS_cos(a1)), - y + (width * FXSYS_sin(a1)))); + out_vertices.add(coord_type(x + (width * cos(a1)), + y + (width * sin(a1)))); - a1 += da; + a1 += da; } @@ -34,8 +34,8 @@ index 6d7ba8a..2b06b1b 100644 a1 -= da; - while(a1 > a2) { + while (a1 > a2) { - out_vertices.add(coord_type(x + (width * FXSYS_cos(a1)), - y + (width * FXSYS_sin(a1)))); + out_vertices.add(coord_type(x + (width * cos(a1)), + y + (width * sin(a1)))); - a1 -= da; + a1 -= da; } diff --git a/third_party/agg23/0001-gcc-warning.patch b/third_party/agg23/0001-gcc-warning.patch index 759696ef03490badd5aab5393e63891a42644385..3bdce6578e167ba554be680fac90b4b03d8847a7 100644 --- a/third_party/agg23/0001-gcc-warning.patch +++ b/third_party/agg23/0001-gcc-warning.patch @@ -4,7 +4,7 @@ index dc13851..7f21bac 100644 +++ b/third_party/agg23/agg_path_storage.h @@ -38,9 +38,9 @@ public: } - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y) + unsigned vertex(float* x, float* y) { - return (m_vertex_idx < m_path->total_vertices()) ? - m_path->vertex(m_vertex_idx++, x, y) : diff --git a/third_party/agg23/0002-ubsan-error-fixes.patch b/third_party/agg23/0002-ubsan-error-fixes.patch index 00ced0071cdcca03192a5f866ac925970350b7e9..58b17dc19cbe747c12a5827c11af530fd4ed5e7b 100644 --- a/third_party/agg23/0002-ubsan-error-fixes.patch +++ b/third_party/agg23/0002-ubsan-error-fixes.patch @@ -13,21 +13,21 @@ index db6ca97..5b1261f 100644 @@ -36,8 +37,18 @@ inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, T* x, T* y) { - const FX_FLOAT nearzero = 1e-30f; -- FX_FLOAT deltax = (FX_FLOAT)(x2 - x1); -- FX_FLOAT deltay = (FX_FLOAT)(y2 - y1); + const float nearzero = 1e-30f; +- float deltax = (float)(x2 - x1); +- float deltay = (float)(y2 - y1); + -+ pdfium::base::CheckedNumeric width = x2; ++ pdfium::base::CheckedNumeric width = x2; + width -= x1; + if (!width.IsValid()) + return 0; -+ pdfium::base::CheckedNumeric height = y2; ++ pdfium::base::CheckedNumeric height = y2; + height -= y1; + if (!height.IsValid()) + return 0; + -+ FX_FLOAT deltax = width.ValueOrDefault(0); -+ FX_FLOAT deltay = height.ValueOrDefault(0); ++ float deltax = width.ValueOrDefault(0); ++ float deltay = height.ValueOrDefault(0); unsigned np = 0; if(deltax == 0) { deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; diff --git a/third_party/agg23/agg_array.h b/third_party/agg23/agg_array.h index 204ae2e7a2178f0314789012b809a506cd1ee554..d521b046068a2a9b7fa5f49ec2ca696a733fdfa3 100644 --- a/third_party/agg23/agg_array.h +++ b/third_party/agg23/agg_array.h @@ -40,10 +40,7 @@ public: } void allocate(unsigned size, unsigned extra_tail = 0); void resize(unsigned new_size); - void zero() - { - FXSYS_memset(m_array, 0, sizeof(T) * m_size); - } + void zero() { memset(m_array, 0, sizeof(T) * m_size); } void add(const T& v) { m_array[m_size++] = v; @@ -130,7 +127,7 @@ void pod_array::resize(unsigned new_size) if(new_size > m_size) { if(new_size > m_capacity) { T* data = FX_Alloc(T, new_size); - FXSYS_memcpy(data, m_array, m_size * sizeof(T)); + memcpy(data, m_array, m_size * sizeof(T)); FX_Free(m_array); m_array = data; } @@ -145,14 +142,14 @@ template pod_array::pod_array(const pod_array& v) : m_capacity(v.m_capacity), m_array(v.m_capacity ? FX_Alloc(T, v.m_capacity) : 0) { - FXSYS_memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + memcpy(m_array, v.m_array, sizeof(T) * v.m_size); } template const pod_array& pod_array::operator = (const pod_array&v) { allocate(v.m_size); if(v.m_size) { - FXSYS_memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + memcpy(m_array, v.m_array, sizeof(T) * v.m_size); } return *this; } @@ -322,7 +319,7 @@ pod_deque::pod_deque(const pod_deque& v) : unsigned i; for(i = 0; i < v.m_num_blocks; ++i) { m_blocks[i] = FX_Alloc(T, block_size); - FXSYS_memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); } } template @@ -333,7 +330,7 @@ const pod_deque& pod_deque::operator = (const pod_deque& v) allocate_block(i); } for(i = 0; i < v.m_num_blocks; ++i) { - FXSYS_memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); } m_size = v.m_size; return *this; @@ -344,10 +341,8 @@ void pod_deque::allocate_block(unsigned nb) if(nb >= m_max_blocks) { T** new_blocks = FX_Alloc(T*, m_max_blocks + m_block_ptr_inc); if(m_blocks) { - FXSYS_memcpy(new_blocks, - m_blocks, - m_num_blocks * sizeof(T*)); - FX_Free(m_blocks); + memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(T*)); + FX_Free(m_blocks); } m_blocks = new_blocks; m_max_blocks += m_block_ptr_inc; @@ -476,10 +471,8 @@ private: if(m_num_blocks >= m_max_blocks) { int8u** new_blocks = FX_Alloc(int8u*, m_max_blocks + m_block_ptr_inc); if(m_blocks) { - FXSYS_memcpy(new_blocks, - m_blocks, - m_num_blocks * sizeof(int8u*)); - FX_Free(m_blocks); + memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(int8u*)); + FX_Free(m_blocks); } m_blocks = new_blocks; m_max_blocks += m_block_ptr_inc; diff --git a/third_party/agg23/agg_basics.h b/third_party/agg23/agg_basics.h index 52a658ec96ffe74743e34a13374aed339f25e181..fc155561e017d4f14b21f3f8ab7290e5a0ab6fc4 100644 --- a/third_party/agg23/agg_basics.h +++ b/third_party/agg23/agg_basics.h @@ -41,7 +41,7 @@ #endif #define AGG_INLINE inline -#include "core/fxcrt/fx_system.h" // For FX_FLOAT +#include "core/fxcrt/fx_system.h" namespace agg { @@ -143,7 +143,7 @@ inline Rect unite_rectangles(const Rect& r1, const Rect& r2) return r; } typedef rect_base rect; -typedef rect_base rect_d; +typedef rect_base rect_d; enum path_commands_e { path_cmd_stop = 0, path_cmd_move_to = 1, @@ -261,10 +261,10 @@ inline unsigned set_orientation(unsigned c, unsigned o) return clear_orientation(c) | o; } struct point_type { - FX_FLOAT x, y; + float x, y; unsigned flag; point_type() {} - point_type(FX_FLOAT x_, FX_FLOAT y_, unsigned flag_ = 0) : x(x_), y(y_), flag(flag_) {} + point_type(float x_, float y_, unsigned flag_ = 0) : x(x_), y(y_), flag(flag_) {} }; struct point_type_flag : public point_type { unsigned flag; @@ -272,13 +272,13 @@ struct point_type_flag : public point_type { { flag = 0; } - point_type_flag(FX_FLOAT x_, FX_FLOAT y_, unsigned flag_ = 0) : point_type(x_, y_), flag(flag_) {} + point_type_flag(float x_, float y_, unsigned flag_ = 0) : point_type(x_, y_), flag(flag_) {} }; struct vertex_type { - FX_FLOAT x, y; + float x, y; unsigned cmd; vertex_type() {} - vertex_type(FX_FLOAT x_, FX_FLOAT y_, unsigned cmd_) : + vertex_type(float x_, float y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {} }; } diff --git a/third_party/agg23/agg_clip_liang_barsky.h b/third_party/agg23/agg_clip_liang_barsky.h index 5b1261f004041c99538b94bcdd5237bec7850922..31b35fe96eb4eb58afd039a3d382b821640044da 100644 --- a/third_party/agg23/agg_clip_liang_barsky.h +++ b/third_party/agg23/agg_clip_liang_barsky.h @@ -36,45 +36,45 @@ inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, const rect_base& clip_box, T* x, T* y) { - const FX_FLOAT nearzero = 1e-30f; + const float nearzero = 1e-30f; - pdfium::base::CheckedNumeric width = x2; + pdfium::base::CheckedNumeric width = x2; width -= x1; if (!width.IsValid()) return 0; - pdfium::base::CheckedNumeric height = y2; + pdfium::base::CheckedNumeric height = y2; height -= y1; if (!height.IsValid()) return 0; - FX_FLOAT deltax = width.ValueOrDefault(0); - FX_FLOAT deltay = height.ValueOrDefault(0); + float deltax = width.ValueOrDefault(0); + float deltay = height.ValueOrDefault(0); unsigned np = 0; if(deltax == 0) { deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; } - FX_FLOAT xin, xout; + float xin, xout; if(deltax > 0) { - xin = (FX_FLOAT)clip_box.x1; - xout = (FX_FLOAT)clip_box.x2; + xin = (float)clip_box.x1; + xout = (float)clip_box.x2; } else { - xin = (FX_FLOAT)clip_box.x2; - xout = (FX_FLOAT)clip_box.x1; + xin = (float)clip_box.x2; + xout = (float)clip_box.x1; } - FX_FLOAT tinx = (xin - x1) / deltax; + float tinx = (xin - x1) / deltax; if(deltay == 0) { deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; } - FX_FLOAT yin, yout; + float yin, yout; if(deltay > 0) { - yin = (FX_FLOAT)clip_box.y1; - yout = (FX_FLOAT)clip_box.y2; + yin = (float)clip_box.y1; + yout = (float)clip_box.y2; } else { - yin = (FX_FLOAT)clip_box.y2; - yout = (FX_FLOAT)clip_box.y1; + yin = (float)clip_box.y2; + yout = (float)clip_box.y1; } - FX_FLOAT tiny = (yin - y1) / deltay; - FX_FLOAT tin1, tin2; + float tiny = (yin - y1) / deltay; + float tin1, tin2; if (tinx < tiny) { tin1 = tinx; tin2 = tiny; @@ -89,9 +89,9 @@ inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, ++np; } if(tin2 <= 1.0f) { - FX_FLOAT toutx = (xout - x1) / deltax; - FX_FLOAT touty = (yout - y1) / deltay; - FX_FLOAT tout1 = (toutx < touty) ? toutx : touty; + float toutx = (xout - x1) / deltax; + float touty = (yout - y1) / deltay; + float tout1 = (toutx < touty) ? toutx : touty; if (tin2 > 0 || tout1 > 0) { if(tin2 <= tout1) { if(tin2 > 0) { diff --git a/third_party/agg23/agg_conv_adaptor_vcgen.h b/third_party/agg23/agg_conv_adaptor_vcgen.h index 0d8d6ff99e044b5fd0163ccb3c4ca99ea27a4b91..be4dc2d609596e5706e6fd9504ece0482ebae53c 100644 --- a/third_party/agg23/agg_conv_adaptor_vcgen.h +++ b/third_party/agg23/agg_conv_adaptor_vcgen.h @@ -20,10 +20,10 @@ namespace agg { struct null_markers { void remove_all() {} - void add_vertex(FX_FLOAT, FX_FLOAT, unsigned) {} + void add_vertex(float, float, unsigned) {} void prepare_src() {} void rewind(unsigned) {} - unsigned vertex(FX_FLOAT*, FX_FLOAT*) + unsigned vertex(float*, float*) { return path_cmd_stop; } @@ -67,7 +67,7 @@ public: m_source->rewind(path_id); m_status = initial; } - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y); + unsigned vertex(float* x, float* y); private: conv_adaptor_vcgen(const conv_adaptor_vcgen&); const conv_adaptor_vcgen& @@ -77,11 +77,11 @@ private: Markers m_markers; status m_status; unsigned m_last_cmd; - FX_FLOAT m_start_x; - FX_FLOAT m_start_y; + float m_start_x; + float m_start_y; }; template -unsigned conv_adaptor_vcgen::vertex(FX_FLOAT* x, FX_FLOAT* y) +unsigned conv_adaptor_vcgen::vertex(float* x, float* y) { unsigned cmd = path_cmd_stop; bool done = false; diff --git a/third_party/agg23/agg_conv_dash.h b/third_party/agg23/agg_conv_dash.h index 63b2019dde949c5b6f9224951439f81dc6a1257b..f87eccc3b12d0dfd0188d113d2ab6cd70b1b0841 100644 --- a/third_party/agg23/agg_conv_dash.h +++ b/third_party/agg23/agg_conv_dash.h @@ -36,15 +36,15 @@ struct conv_dash : public conv_adaptor_vcgen { base_type::generator().remove_all_dashes(); } - void add_dash(FX_FLOAT dash_len, FX_FLOAT gap_len) + void add_dash(float dash_len, float gap_len) { base_type::generator().add_dash(dash_len, gap_len); } - void dash_start(FX_FLOAT ds) + void dash_start(float ds) { base_type::generator().dash_start(ds); } - void shorten(FX_FLOAT s) + void shorten(float s) { base_type::generator().shorten(s); } diff --git a/third_party/agg23/agg_conv_stroke.h b/third_party/agg23/agg_conv_stroke.h index 5a36bd73bb8be8c94efe800b1a92344021e8222e..82268ddec66e7fcdfe624ed51c273067029d3107 100644 --- a/third_party/agg23/agg_conv_stroke.h +++ b/third_party/agg23/agg_conv_stroke.h @@ -57,47 +57,47 @@ struct conv_stroke : { return base_type::generator().inner_join(); } - void width(FX_FLOAT w) + void width(float w) { base_type::generator().width(w); } - void miter_limit(FX_FLOAT ml) + void miter_limit(float ml) { base_type::generator().miter_limit(ml); } - void miter_limit_theta(FX_FLOAT t) + void miter_limit_theta(float t) { base_type::generator().miter_limit_theta(t); } - void inner_miter_limit(FX_FLOAT ml) + void inner_miter_limit(float ml) { base_type::generator().inner_miter_limit(ml); } - void approximation_scale(FX_FLOAT as) + void approximation_scale(float as) { base_type::generator().approximation_scale(as); } - FX_FLOAT width() const + float width() const { return base_type::generator().width(); } - FX_FLOAT miter_limit() const + float miter_limit() const { return base_type::generator().miter_limit(); } - FX_FLOAT inner_miter_limit() const + float inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } - FX_FLOAT approximation_scale() const + float approximation_scale() const { return base_type::generator().approximation_scale(); } - void shorten(FX_FLOAT s) + void shorten(float s) { base_type::generator().shorten(s); } - FX_FLOAT shorten() const + float shorten() const { return base_type::generator().shorten(); } diff --git a/third_party/agg23/agg_curves.cpp b/third_party/agg23/agg_curves.cpp index b86cf630c3988f016e7d6f557ba1f55dc063fa39..41900c81fb9cf7ca75178f41087f252c9ce718cf 100644 --- a/third_party/agg23/agg_curves.cpp +++ b/third_party/agg23/agg_curves.cpp @@ -21,16 +21,15 @@ #include "agg_curves.h" #include "agg_math.h" -#include "core/fxcrt/fx_basic.h" namespace agg { -const FX_FLOAT curve_collinearity_epsilon = 1e-30f; +const float curve_collinearity_epsilon = 1e-30f; enum curve_recursion_limit_e { curve_recursion_limit = 16 }; -void curve4_div::init(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) +void curve4_div::init(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) { m_points.remove_all(); m_distance_tolerance_square = 1.0f / 4; @@ -38,40 +37,39 @@ void curve4_div::init(FX_FLOAT x1, FX_FLOAT y1, bezier(x1, y1, x2, y2, x3, y3, x4, y4); m_count = 0; } -void curve4_div::recursive_bezier(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4, +void curve4_div::recursive_bezier(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4, unsigned level) { if(level > curve_recursion_limit) { return; } - FX_FLOAT x12 = (x1 + x2) / 2; - FX_FLOAT y12 = (y1 + y2) / 2; - FX_FLOAT x23 = (x2 + x3) / 2; - FX_FLOAT y23 = (y2 + y3) / 2; - FX_FLOAT x34 = (x3 + x4) / 2; - FX_FLOAT y34 = (y3 + y4) / 2; - FX_FLOAT x123 = (x12 + x23) / 2; - FX_FLOAT y123 = (y12 + y23) / 2; - FX_FLOAT x234 = (x23 + x34) / 2; - FX_FLOAT y234 = (y23 + y34) / 2; - FX_FLOAT x1234 = (x123 + x234) / 2; - FX_FLOAT y1234 = (y123 + y234) / 2; - FX_FLOAT dx = x4 - x1; - FX_FLOAT dy = y4 - y1; - FX_FLOAT d2 = FXSYS_fabs(((x2 - x4) * dy) - ((y2 - y4) * dx)); - FX_FLOAT d3 = FXSYS_fabs(((x3 - x4) * dy) - ((y3 - y4) * dx)); + float x12 = (x1 + x2) / 2; + float y12 = (y1 + y2) / 2; + float x23 = (x2 + x3) / 2; + float y23 = (y2 + y3) / 2; + float x34 = (x3 + x4) / 2; + float y34 = (y3 + y4) / 2; + float x123 = (x12 + x23) / 2; + float y123 = (y12 + y23) / 2; + float x234 = (x23 + x34) / 2; + float y234 = (y23 + y34) / 2; + float x1234 = (x123 + x234) / 2; + float y1234 = (y123 + y234) / 2; + float dx = x4 - x1; + float dy = y4 - y1; + float d2 = fabs(((x2 - x4) * dy) - ((y2 - y4) * dx)); + float d3 = fabs(((x3 - x4) * dy) - ((y3 - y4) * dx)); switch((int(d2 > curve_collinearity_epsilon) << 1) + int(d3 > curve_collinearity_epsilon)) { case 0: - if(FXSYS_fabs(x1 + x3 - x2 - x2) + - FXSYS_fabs(y1 + y3 - y2 - y2) + - FXSYS_fabs(x2 + x4 - x3 - x3) + - FXSYS_fabs(y2 + y4 - y3 - y3) <= m_distance_tolerance_manhattan) { - m_points.add(point_type(x1234, y1234, path_flags_jr)); - return; + if (fabs(x1 + x3 - x2 - x2) + fabs(y1 + y3 - y2 - y2) + + fabs(x2 + x4 - x3 - x3) + fabs(y2 + y4 - y3 - y3) <= + m_distance_tolerance_manhattan) { + m_points.add(point_type(x1234, y1234, path_flags_jr)); + return; } break; case 1: @@ -99,10 +97,10 @@ void curve4_div::recursive_bezier(FX_FLOAT x1, FX_FLOAT y1, recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); } -void curve4_div::bezier(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) +void curve4_div::bezier(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) { m_points.add(point_type(x1, y1)); recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); diff --git a/third_party/agg23/agg_curves.h b/third_party/agg23/agg_curves.h index 495f7a6a8f40b0df24b2b26545a8cba655f256a3..488db4a1ffaba5d0264dcf604349cd92b1919f32 100644 --- a/third_party/agg23/agg_curves.h +++ b/third_party/agg23/agg_curves.h @@ -20,12 +20,12 @@ namespace agg { struct curve4_points { - FX_FLOAT cp[8]; + float cp[8]; curve4_points() {} - curve4_points(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) + curve4_points(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) { cp[0] = x1; cp[1] = y1; @@ -36,10 +36,10 @@ struct curve4_points { cp[6] = x4; cp[7] = y4; } - void init(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) + void init(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) { cp[0] = x1; cp[1] = y1; @@ -50,11 +50,11 @@ struct curve4_points { cp[6] = x4; cp[7] = y4; } - FX_FLOAT operator [] (unsigned i) const + float operator [] (unsigned i) const { return cp[i]; } - FX_FLOAT& operator [] (unsigned i) + float& operator [] (unsigned i) { return cp[i]; } @@ -65,10 +65,10 @@ public: curve4_div() : m_count(0) {} - curve4_div(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) : + curve4_div(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) : m_count(0) { init(x1, y1, x2, y2, x3, y3, x4, y4); @@ -83,10 +83,10 @@ public: m_points.remove_all(); m_count = 0; } - void init(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4); + void init(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4); void init(const curve4_points& cp) { init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); @@ -95,7 +95,7 @@ public: { m_count = 0; } - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y) + unsigned vertex(float* x, float* y) { if(m_count >= m_points.size()) { return path_cmd_stop; @@ -105,7 +105,7 @@ public: *y = p.y; return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; } - unsigned vertex_flag(FX_FLOAT* x, FX_FLOAT* y, int& flag) + unsigned vertex_flag(float* x, float* y, int& flag) { if(m_count >= m_points.size()) { return path_cmd_stop; @@ -121,17 +121,17 @@ public: return m_points.size(); } private: - void bezier(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4); - void recursive_bezier(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4, + void bezier(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4); + void recursive_bezier(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4, unsigned level); - FX_FLOAT m_distance_tolerance_square; - FX_FLOAT m_distance_tolerance_manhattan; + float m_distance_tolerance_square; + float m_distance_tolerance_manhattan; unsigned m_count; pod_deque m_points; }; @@ -139,10 +139,10 @@ class curve4 { public: curve4() {} - curve4(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) + curve4(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) { init(x1, y1, x2, y2, x3, y3, x4, y4); } @@ -154,10 +154,10 @@ public: { m_curve_div.reset(); } - void init(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x3, FX_FLOAT y3, - FX_FLOAT x4, FX_FLOAT y4) + void init(float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) { m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); } @@ -169,11 +169,11 @@ public: { m_curve_div.rewind(path_id); } - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y) + unsigned vertex(float* x, float* y) { return m_curve_div.vertex(x, y); } - unsigned vertex_curve_flag(FX_FLOAT* x, FX_FLOAT* y, int& flag) + unsigned vertex_curve_flag(float* x, float* y, int& flag) { return m_curve_div.vertex_flag(x, y, flag); } diff --git a/third_party/agg23/agg_math.h b/third_party/agg23/agg_math.h index e003297dfffb4a579e17bd7554cd33d7a4dfbad2..6d5e39ac3e4afd0dc91049b6d42664996350ec78 100644 --- a/third_party/agg23/agg_math.h +++ b/third_party/agg23/agg_math.h @@ -21,39 +21,39 @@ #include "agg_basics.h" namespace agg { -const FX_FLOAT intersection_epsilon = 1.0e-30f; -AGG_INLINE FX_FLOAT calc_point_location(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x, FX_FLOAT y) +const float intersection_epsilon = 1.0e-30f; +AGG_INLINE float calc_point_location(float x1, float y1, + float x2, float y2, + float x, float y) { return ((x - x2) * (y2 - y1)) - ((y - y2) * (x2 - x1)); } -AGG_INLINE FX_FLOAT calc_distance(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2) +AGG_INLINE float calc_distance(float x1, float y1, float x2, float y2) { - FX_FLOAT dx = x2 - x1; - FX_FLOAT dy = y2 - y1; + float dx = x2 - x1; + float dy = y2 - y1; return FXSYS_sqrt2(dx, dy); } -AGG_INLINE FX_FLOAT calc_line_point_distance(FX_FLOAT x1, FX_FLOAT y1, - FX_FLOAT x2, FX_FLOAT y2, - FX_FLOAT x, FX_FLOAT y) +AGG_INLINE float calc_line_point_distance(float x1, float y1, + float x2, float y2, + float x, float y) { - FX_FLOAT dx = x2 - x1; - FX_FLOAT dy = y2 - y1; - FX_FLOAT d = FXSYS_sqrt2(dx, dy); + float dx = x2 - x1; + float dy = y2 - y1; + float d = FXSYS_sqrt2(dx, dy); if(d < intersection_epsilon) { return calc_distance(x1, y1, x, y); } return ((x - x2) * dy / d) - ((y - y2) * dx / d); } -AGG_INLINE bool calc_intersection(FX_FLOAT ax, FX_FLOAT ay, FX_FLOAT bx, FX_FLOAT by, - FX_FLOAT cx, FX_FLOAT cy, FX_FLOAT dx, FX_FLOAT dy, - FX_FLOAT* x, FX_FLOAT* y) +AGG_INLINE bool calc_intersection(float ax, float ay, float bx, float by, + float cx, float cy, float dx, float dy, + float* x, float* y) { - FX_FLOAT num = ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); - FX_FLOAT den = ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); - if (FXSYS_fabs(den) < intersection_epsilon) { - return false; + float num = ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); + float den = ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); + if (fabs(den) < intersection_epsilon) { + return false; } *x = ax + ((bx - ax) * num / den); *y = ay + ((by - ay) * num / den); diff --git a/third_party/agg23/agg_math_stroke.h b/third_party/agg23/agg_math_stroke.h index 2b06b1bfda76ef76b00909878252a41a165e4b4e..82df8080cf228a015b641ad207b813687ad0b3a0 100644 --- a/third_party/agg23/agg_math_stroke.h +++ b/third_party/agg23/agg_math_stroke.h @@ -41,24 +41,24 @@ enum inner_join_e { inner_jag, inner_round }; -const FX_FLOAT stroke_theta = 1.0f / 1000.0f; +const float stroke_theta = 1.0f / 1000.0f; template void stroke_calc_arc(VertexConsumer& out_vertices, - FX_FLOAT x, FX_FLOAT y, - FX_FLOAT dx1, FX_FLOAT dy1, - FX_FLOAT dx2, FX_FLOAT dy2, - FX_FLOAT width, - FX_FLOAT approximation_scale) + float x, float y, + float dx1, float dy1, + float dx2, float dy2, + float width, + float approximation_scale) { typedef typename VertexConsumer::value_type coord_type; - FX_FLOAT a1 = FXSYS_atan2(dy1, dx1); - FX_FLOAT a2 = FXSYS_atan2(dy2, dx2); - FX_FLOAT da = a1 - a2; + float a1 = atan2(dy1, dx1); + float a2 = atan2(dy2, dx2); + float da = a1 - a2; bool ccw = da > 0 && da < FX_PI; if(width < 0) { width = -width; } - da = FXSYS_acos(width / (width + ((1.0f / 8) / approximation_scale))) * 2; + da = acos(width / (width + ((1.0f / 8) / approximation_scale))) * 2; out_vertices.add(coord_type(x + dx1, y + dy1)); if (da > 0) { if (!ccw) { @@ -68,8 +68,8 @@ void stroke_calc_arc(VertexConsumer& out_vertices, a2 -= da / 4; a1 += da; while (a1 < a2) { - out_vertices.add(coord_type(x + (width * FXSYS_cos(a1)), - y + (width * FXSYS_sin(a1)))); + out_vertices.add( + coord_type(x + (width * cos(a1)), y + (width * sin(a1)))); a1 += da; } } else { @@ -79,8 +79,8 @@ void stroke_calc_arc(VertexConsumer& out_vertices, a2 += da / 4; a1 -= da; while (a1 > a2) { - out_vertices.add(coord_type(x + (width * FXSYS_cos(a1)), - y + (width * FXSYS_sin(a1)))); + out_vertices.add( + coord_type(x + (width * cos(a1)), y + (width * sin(a1)))); a1 -= da; } } @@ -92,31 +92,31 @@ void stroke_calc_miter(VertexConsumer& out_vertices, const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, - FX_FLOAT dx1, FX_FLOAT dy1, - FX_FLOAT dx2, FX_FLOAT dy2, - FX_FLOAT width, + float dx1, float dy1, + float dx2, float dy2, + float width, line_join_e line_join, - FX_FLOAT miter_limit, - FX_FLOAT approximation_scale) + float miter_limit, + float approximation_scale) { typedef typename VertexConsumer::value_type coord_type; - FX_FLOAT xi = v1.x; - FX_FLOAT yi = v1.y; + float xi = v1.x; + float yi = v1.y; bool miter_limit_exceeded = true; if(calc_intersection(v0.x + dx1, v0.y - dy1, v1.x + dx1, v1.y - dy1, v1.x + dx2, v1.y - dy2, v2.x + dx2, v2.y - dy2, &xi, &yi)) { - FX_FLOAT d1 = calc_distance(v1.x, v1.y, xi, yi); - FX_FLOAT lim = width * miter_limit; + float d1 = calc_distance(v1.x, v1.y, xi, yi); + float lim = width * miter_limit; if(d1 <= lim) { out_vertices.add(coord_type(xi, yi)); miter_limit_exceeded = false; } } else { - FX_FLOAT x2 = v1.x + dx1; - FX_FLOAT y2 = v1.y - dy1; + float x2 = v1.x + dx1; + float y2 = v1.y - dy1; if ((((x2 - v0.x) * dy1) - ((v0.y - y2) * dx1) < 0) != (((x2 - v2.x) * dy1) - ((v2.y - y2) * dx1) < 0)) { out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); @@ -147,17 +147,17 @@ template void stroke_calc_cap(VertexConsumer& out_vertices, const vertex_dist& v0, const vertex_dist& v1, - FX_FLOAT len, + float len, line_cap_e line_cap, - FX_FLOAT width, - FX_FLOAT approximation_scale) + float width, + float approximation_scale) { typedef typename VertexConsumer::value_type coord_type; out_vertices.remove_all(); - FX_FLOAT dx1 = (v1.y - v0.y) / len; - FX_FLOAT dy1 = (v1.x - v0.x) / len; - FX_FLOAT dx2 = 0; - FX_FLOAT dy2 = 0; + float dx1 = (v1.y - v0.y) / len; + float dy1 = (v1.x - v0.x) / len; + float dx2 = 0; + float dy2 = 0; dx1 = dx1 * width; dy1 = dy1 * width; if(line_cap != round_cap) { @@ -168,18 +168,16 @@ void stroke_calc_cap(VertexConsumer& out_vertices, out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2)); out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2)); } else { - FX_FLOAT a1 = FXSYS_atan2(dy1, -dx1); - FX_FLOAT a2 = a1 + FX_PI; - FX_FLOAT da = - FXSYS_acos(width / (width + ((1.0f / 8) / approximation_scale))) * - 2; - out_vertices.add(coord_type(v0.x - dx1, v0.y + dy1)); + float a1 = atan2(dy1, -dx1); + float a2 = a1 + FX_PI; + float da = acos(width / (width + ((1.0f / 8) / approximation_scale))) * 2; + out_vertices.add(coord_type(v0.x - dx1, v0.y + dy1)); + a1 += da; + a2 -= da / 4; + while (a1 < a2) { + out_vertices.add( + coord_type(v0.x + (width * cos(a1)), v0.y + (width * sin(a1)))); a1 += da; - a2 -= da / 4; - while(a1 < a2) { - out_vertices.add(coord_type(v0.x + (width * FXSYS_cos(a1)), - v0.y + (width * FXSYS_sin(a1)))); - a1 += da; } out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1)); } @@ -189,17 +187,17 @@ void stroke_calc_join(VertexConsumer& out_vertices, const vertex_dist& v0, const vertex_dist& v1, const vertex_dist& v2, - FX_FLOAT len1, - FX_FLOAT len2, - FX_FLOAT width, + float len1, + float len2, + float width, line_join_e line_join, inner_join_e inner_join, - FX_FLOAT miter_limit, - FX_FLOAT inner_miter_limit, - FX_FLOAT approximation_scale) + float miter_limit, + float inner_miter_limit, + float approximation_scale) { typedef typename VertexConsumer::value_type coord_type; - FX_FLOAT dx1, dy1, dx2, dy2; + float dx1, dy1, dx2, dy2; dx1 = width * (v1.y - v0.y) / len1; dy1 = width * (v1.x - v0.x) / len1; dx2 = width * (v2.y - v1.y) / len2; @@ -221,7 +219,7 @@ void stroke_calc_join(VertexConsumer& out_vertices, break; case inner_jag: case inner_round: { - FX_FLOAT d = (dx1 - dx2) * (dx1 - dx2) + (dy1 - dy2) * (dy1 - dy2); + float d = (dx1 - dx2) * (dx1 - dx2) + (dy1 - dy2) * (dy1 - dy2); if(d < len1 * len1 && d < len2 * len2) { stroke_calc_miter(out_vertices, v0, v1, v2, dx1, dy1, dx2, dy2, diff --git a/third_party/agg23/agg_path_storage.cpp b/third_party/agg23/agg_path_storage.cpp index 968746738a646b8f90d5277b5e5e327b77efd81e..063ece5424dfe9e4a4ba55f2b1480ee4f81c9f2b 100644 --- a/third_party/agg23/agg_path_storage.cpp +++ b/third_party/agg23/agg_path_storage.cpp @@ -23,16 +23,17 @@ // //---------------------------------------------------------------------------- -#include "agg_math.h" #include "agg_path_storage.h" -#include "core/fxcrt/fx_basic.h" + +#include "agg_math.h" +#include "core/fxcrt/fx_memory.h" namespace agg { path_storage::~path_storage() { if(m_total_blocks) { - FX_FLOAT** coord_blk = m_coord_blocks + m_total_blocks - 1; + float** coord_blk = m_coord_blocks + m_total_blocks - 1; while(m_total_blocks--) { FX_Free(*coord_blk); --coord_blk; @@ -52,27 +53,23 @@ path_storage::path_storage() : void path_storage::allocate_block(unsigned nb) { if(nb >= m_max_blocks) { - FX_FLOAT** new_coords = - FX_Alloc2D(FX_FLOAT*, m_max_blocks + block_pool, 2); + float** new_coords = + FX_Alloc2D(float*, m_max_blocks + block_pool, 2); unsigned char** new_cmds = (unsigned char**)(new_coords + m_max_blocks + block_pool); if(m_coord_blocks) { - FXSYS_memcpy(new_coords, - m_coord_blocks, - m_max_blocks * sizeof(FX_FLOAT*)); - FXSYS_memcpy(new_cmds, - m_cmd_blocks, - m_max_blocks * sizeof(unsigned char*)); - FX_Free(m_coord_blocks); + memcpy(new_coords, m_coord_blocks, m_max_blocks * sizeof(float*)); + memcpy(new_cmds, m_cmd_blocks, m_max_blocks * sizeof(unsigned char*)); + FX_Free(m_coord_blocks); } m_coord_blocks = new_coords; m_cmd_blocks = new_cmds; m_max_blocks += block_pool; } m_coord_blocks[nb] = - FX_Alloc( FX_FLOAT, block_size * 2 + + FX_Alloc( float, block_size * 2 + block_size / - (sizeof(FX_FLOAT) / sizeof(unsigned char))); + (sizeof(float) / sizeof(unsigned char))); m_cmd_blocks[nb] = (unsigned char*)(m_coord_blocks[nb] + block_size * 2); m_total_blocks++; @@ -81,9 +78,9 @@ void path_storage::rewind(unsigned path_id) { m_iterator = path_id; } -void path_storage::curve4(FX_FLOAT x_ctrl1, FX_FLOAT y_ctrl1, - FX_FLOAT x_ctrl2, FX_FLOAT y_ctrl2, - FX_FLOAT x_to, FX_FLOAT y_to) +void path_storage::curve4(float x_ctrl1, float y_ctrl1, + float x_ctrl2, float y_ctrl2, + float x_to, float y_to) { add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); diff --git a/third_party/agg23/agg_path_storage.h b/third_party/agg23/agg_path_storage.h index 7f21bacd09c4a79763d73863ea5d9cb5b7e5f358..17e82d73e4c4820140729ea57d7f51d0093773c6 100644 --- a/third_party/agg23/agg_path_storage.h +++ b/third_party/agg23/agg_path_storage.h @@ -36,7 +36,7 @@ public: { m_vertex_idx = path_id; } - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y) + unsigned vertex(float* x, float* y) { return (m_vertex_idx < m_path->total_vertices()) ? m_path->vertex(m_vertex_idx++, x, y) @@ -48,19 +48,19 @@ public: }; ~path_storage(); path_storage(); - unsigned last_vertex(FX_FLOAT* x, FX_FLOAT* y) const; - unsigned prev_vertex(FX_FLOAT* x, FX_FLOAT* y) const; - void move_to(FX_FLOAT x, FX_FLOAT y); - void line_to(FX_FLOAT x, FX_FLOAT y); - void curve4(FX_FLOAT x_ctrl1, FX_FLOAT y_ctrl1, - FX_FLOAT x_ctrl2, FX_FLOAT y_ctrl2, - FX_FLOAT x_to, FX_FLOAT y_to); + unsigned last_vertex(float* x, float* y) const; + unsigned prev_vertex(float* x, float* y) const; + void move_to(float x, float y); + void line_to(float x, float y); + void curve4(float x_ctrl1, float y_ctrl1, + float x_ctrl2, float y_ctrl2, + float x_to, float y_to); template void add_path(VertexSource& vs, unsigned path_id = 0, bool solid_path = true) { - FX_FLOAT x, y; + float x, y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { @@ -75,7 +75,7 @@ public: unsigned path_id = 0, bool solid_path = true) { - FX_FLOAT x, y; + float x, y; unsigned cmd; int flag; vs.rewind(path_id); @@ -90,10 +90,10 @@ public: { return m_total_vertices; } - unsigned vertex(unsigned idx, FX_FLOAT* x, FX_FLOAT* y) const + unsigned vertex(unsigned idx, float* x, float* y) const { unsigned nb = idx >> block_shift; - const FX_FLOAT* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); + const float* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); *x = *pv++; *y = *pv; return m_cmd_blocks[nb][idx & block_mask]; @@ -107,42 +107,42 @@ public: return m_cmd_blocks[idx >> block_shift][idx & block_mask] & path_flags_jr; } void rewind(unsigned path_id); - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y); - void add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd); + unsigned vertex(float* x, float* y); + void add_vertex(float x, float y, unsigned cmd); void end_poly(); private: void allocate_block(unsigned nb); - unsigned char* storage_ptrs(FX_FLOAT** xy_ptr); + unsigned char* storage_ptrs(float** xy_ptr); private: unsigned m_total_vertices; unsigned m_total_blocks; unsigned m_max_blocks; - FX_FLOAT** m_coord_blocks; + float** m_coord_blocks; unsigned char** m_cmd_blocks; unsigned m_iterator; }; -inline unsigned path_storage::vertex(FX_FLOAT* x, FX_FLOAT* y) +inline unsigned path_storage::vertex(float* x, float* y) { if(m_iterator >= m_total_vertices) { return path_cmd_stop; } return vertex(m_iterator++, x, y); } -inline unsigned path_storage::prev_vertex(FX_FLOAT* x, FX_FLOAT* y) const +inline unsigned path_storage::prev_vertex(float* x, float* y) const { if(m_total_vertices > 1) { return vertex(m_total_vertices - 2, x, y); } return path_cmd_stop; } -inline unsigned path_storage::last_vertex(FX_FLOAT* x, FX_FLOAT* y) const +inline unsigned path_storage::last_vertex(float* x, float* y) const { if(m_total_vertices) { return vertex(m_total_vertices - 1, x, y); } return path_cmd_stop; } -inline unsigned char* path_storage::storage_ptrs(FX_FLOAT** xy_ptr) +inline unsigned char* path_storage::storage_ptrs(float** xy_ptr) { unsigned nb = m_total_vertices >> block_shift; if(nb >= m_total_blocks) { @@ -151,20 +151,20 @@ inline unsigned char* path_storage::storage_ptrs(FX_FLOAT** xy_ptr) *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); return m_cmd_blocks[nb] + (m_total_vertices & block_mask); } -inline void path_storage::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) +inline void path_storage::add_vertex(float x, float y, unsigned cmd) { - FX_FLOAT* coord_ptr = 0; + float* coord_ptr = 0; unsigned char* cmd_ptr = storage_ptrs(&coord_ptr); *cmd_ptr = (unsigned char)cmd; *coord_ptr++ = x; *coord_ptr = y; m_total_vertices++; } -inline void path_storage::move_to(FX_FLOAT x, FX_FLOAT y) +inline void path_storage::move_to(float x, float y) { add_vertex(x, y, path_cmd_move_to); } -inline void path_storage::line_to(FX_FLOAT x, FX_FLOAT y) +inline void path_storage::line_to(float x, float y) { add_vertex(x, y, path_cmd_line_to); } diff --git a/third_party/agg23/agg_rasterizer_scanline_aa.cpp b/third_party/agg23/agg_rasterizer_scanline_aa.cpp index af6dd58fe30432a36f4eb18c8049d05074f75e05..c90bdafdd07044c70df4a9022df2934b80c1c140 100644 --- a/third_party/agg23/agg_rasterizer_scanline_aa.cpp +++ b/third_party/agg23/agg_rasterizer_scanline_aa.cpp @@ -118,8 +118,8 @@ void outline_aa::allocate_block() if(m_num_blocks >= m_max_blocks) { cell_aa** new_cells = FX_Alloc( cell_aa*, m_max_blocks + cell_block_pool); if(m_cells) { - FXSYS_memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_aa*)); - FX_Free(m_cells); + memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_aa*)); + FX_Free(m_cells); } m_cells = new_cells; m_max_blocks += cell_block_pool; diff --git a/third_party/agg23/agg_rasterizer_scanline_aa.h b/third_party/agg23/agg_rasterizer_scanline_aa.h index fc28290f549e07cf4c6ffc3e69a63167346dca5e..c747ee379e941af9f0d7b75f4c5280ff51bf4986 100644 --- a/third_party/agg23/agg_rasterizer_scanline_aa.h +++ b/third_party/agg23/agg_rasterizer_scanline_aa.h @@ -45,7 +45,7 @@ enum poly_base_scale_e { poly_base_size = 1 << poly_base_shift, poly_base_mask = poly_base_size - 1 }; -inline int poly_coord(FX_FLOAT c) +inline int poly_coord(float c) { return int(c * poly_base_size); } @@ -219,14 +219,14 @@ public: m_outline.reset(); m_status = status_initial; } - void clip_box(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2) + void clip_box(float x1, float y1, float x2, float y2) { m_clip_box = rect(poly_coord(x1), poly_coord(y1), poly_coord(x2), poly_coord(y2)); m_clip_box.normalize(); m_clipping = true; } - void add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) + void add_vertex(float x, float y, unsigned cmd) { if(is_close(cmd)) { close_polygon(); @@ -374,8 +374,8 @@ public: template void add_path(VertexSource& vs, unsigned path_id = 0) { - FX_FLOAT x; - FX_FLOAT y; + float x; + float y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { @@ -385,8 +385,8 @@ public: template void add_path_transformed(VertexSource& vs, const CFX_Matrix* pMatrix, unsigned path_id = 0) { - FX_FLOAT x; - FX_FLOAT y; + float x; + float y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { diff --git a/third_party/agg23/agg_scanline_u.h b/third_party/agg23/agg_scanline_u.h index 210011532903115698d5085cb586bb6a2f893e31..844dc9aad3599c0f78a55d7d580df531971ea78d 100644 --- a/third_party/agg23/agg_scanline_u.h +++ b/third_party/agg23/agg_scanline_u.h @@ -83,7 +83,7 @@ public: void add_cells(int x, unsigned len, const CoverT* covers) { x -= m_min_x; - FXSYS_memcpy(m_covers + x, covers, len * sizeof(CoverT)); + memcpy(m_covers + x, covers, len * sizeof(CoverT)); if(x == m_last_x + 1) { m_cur_span->len += (coord_type)len; } else { @@ -97,7 +97,7 @@ public: void add_span(int x, unsigned len, unsigned cover) { x -= m_min_x; - FXSYS_memset(m_covers + x, cover, len); + memset(m_covers + x, cover, len); if(x == m_last_x + 1) { m_cur_span->len += (coord_type)len; } else { diff --git a/third_party/agg23/agg_shorten_path.h b/third_party/agg23/agg_shorten_path.h index d7eb4be018ca52a16e45191b224567c2de76b28d..2f62ec52d2f1ee46bd411d71a3b110be4150dc3d 100644 --- a/third_party/agg23/agg_shorten_path.h +++ b/third_party/agg23/agg_shorten_path.h @@ -20,11 +20,11 @@ namespace agg { template -void shorten_path(VertexSequence& vs, FX_FLOAT s, unsigned closed = 0) +void shorten_path(VertexSequence& vs, float s, unsigned closed = 0) { typedef typename VertexSequence::value_type vertex_type; if(s > 0 && vs.size() > 1) { - FX_FLOAT d; + float d; int n = int(vs.size() - 2); while(n) { d = vs[n].dist; @@ -42,8 +42,8 @@ void shorten_path(VertexSequence& vs, FX_FLOAT s, unsigned closed = 0) vertex_type& prev = vs[n - 1]; vertex_type& last = vs[n]; d = (prev.dist - s) / prev.dist; - FX_FLOAT x = prev.x + (last.x - prev.x) * d; - FX_FLOAT y = prev.y + (last.y - prev.y) * d; + float x = prev.x + (last.x - prev.x) * d; + float y = prev.y + (last.y - prev.y) * d; last.x = x; last.y = y; if(!prev(last)) { diff --git a/third_party/agg23/agg_vcgen_dash.cpp b/third_party/agg23/agg_vcgen_dash.cpp index bd5a2122a229ac812a15a412bf3898c5021a1335..fdbd2aa7fe0eb907708e1e7b88f6a74d90886c0a 100644 --- a/third_party/agg23/agg_vcgen_dash.cpp +++ b/third_party/agg23/agg_vcgen_dash.cpp @@ -20,7 +20,6 @@ #include "agg_shorten_path.h" #include "agg_vcgen_dash.h" -#include "core/fxcrt/fx_basic.h" namespace agg { @@ -44,7 +43,7 @@ void vcgen_dash::remove_all_dashes() m_curr_dash_start = 0; m_curr_dash = 0; } -void vcgen_dash::add_dash(FX_FLOAT dash_len, FX_FLOAT gap_len) +void vcgen_dash::add_dash(float dash_len, float gap_len) { if(m_num_dashes < max_dashes) { m_total_dash_len += dash_len + gap_len; @@ -52,12 +51,12 @@ void vcgen_dash::add_dash(FX_FLOAT dash_len, FX_FLOAT gap_len) m_dashes[m_num_dashes++] = gap_len; } } -void vcgen_dash::dash_start(FX_FLOAT ds) +void vcgen_dash::dash_start(float ds) { m_dash_start = ds; - calc_dash_start(FXSYS_fabs(ds)); + calc_dash_start(fabs(ds)); } -void vcgen_dash::calc_dash_start(FX_FLOAT ds) +void vcgen_dash::calc_dash_start(float ds) { m_curr_dash = 0; m_curr_dash_start = 0; @@ -81,7 +80,7 @@ void vcgen_dash::remove_all() m_src_vertices.remove_all(); m_closed = 0; } -void vcgen_dash::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) +void vcgen_dash::add_vertex(float x, float y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { @@ -103,7 +102,7 @@ void vcgen_dash::rewind(unsigned) m_status = ready; m_src_vertex = 0; } -unsigned vcgen_dash::vertex(FX_FLOAT* x, FX_FLOAT* y) +unsigned vcgen_dash::vertex(float* x, float* y) { unsigned cmd = path_cmd_move_to; while(!is_stop(cmd)) { @@ -127,7 +126,7 @@ unsigned vcgen_dash::vertex(FX_FLOAT* x, FX_FLOAT* y) } return path_cmd_move_to; case polyline: { - FX_FLOAT dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; + float dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; unsigned cmd = (m_curr_dash & 1) ? path_cmd_move_to : path_cmd_line_to; diff --git a/third_party/agg23/agg_vcgen_dash.h b/third_party/agg23/agg_vcgen_dash.h index 9c3aa630c207156ab925c5953fe76d1f6758d74e..7702fa7adcfd7ee05cf78ff3fc1a7a9639ecd269 100644 --- a/third_party/agg23/agg_vcgen_dash.h +++ b/third_party/agg23/agg_vcgen_dash.h @@ -38,9 +38,9 @@ public: typedef vertex_sequence vertex_storage; vcgen_dash(); void remove_all_dashes(); - void add_dash(FX_FLOAT dash_len, FX_FLOAT gap_len); - void dash_start(FX_FLOAT ds); - void shorten(FX_FLOAT s) + void add_dash(float dash_len, float gap_len); + void dash_start(float ds); + void shorten(float s) { m_shorten = s; } @@ -49,21 +49,21 @@ public: return m_shorten; } void remove_all(); - void add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd); + void add_vertex(float x, float y, unsigned cmd); void rewind(unsigned path_id); - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y); + unsigned vertex(float* x, float* y); private: vcgen_dash(const vcgen_dash&); const vcgen_dash& operator = (const vcgen_dash&); - void calc_dash_start(FX_FLOAT ds); - FX_FLOAT m_dashes[max_dashes]; - FX_FLOAT m_total_dash_len; + void calc_dash_start(float ds); + float m_dashes[max_dashes]; + float m_total_dash_len; unsigned m_num_dashes; - FX_FLOAT m_dash_start; - FX_FLOAT m_shorten; - FX_FLOAT m_curr_dash_start; + float m_dash_start; + float m_shorten; + float m_curr_dash_start; unsigned m_curr_dash; - FX_FLOAT m_curr_rest; + float m_curr_rest; const vertex_dist* m_v1; const vertex_dist* m_v2; vertex_storage m_src_vertices; diff --git a/third_party/agg23/agg_vcgen_stroke.cpp b/third_party/agg23/agg_vcgen_stroke.cpp index 03225b1649346cebb702ab47e57d5ef42aa54d0b..3e97a31473bdca852cd29becac8b95a04b69e3b0 100644 --- a/third_party/agg23/agg_vcgen_stroke.cpp +++ b/third_party/agg23/agg_vcgen_stroke.cpp @@ -24,7 +24,6 @@ //---------------------------------------------------------------------------- #include "agg_vcgen_stroke.h" -#include "core/fxcrt/fx_basic.h" namespace agg { @@ -51,7 +50,7 @@ void vcgen_stroke::remove_all() m_closed = 0; m_status = initial; } -void vcgen_stroke::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) +void vcgen_stroke::add_vertex(float x, float y, unsigned cmd) { m_status = initial; if(is_move_to(cmd)) { @@ -64,13 +63,13 @@ void vcgen_stroke::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd) } } } -static inline void calc_butt_cap(FX_FLOAT* cap, +static inline void calc_butt_cap(float* cap, const vertex_dist& v0, const vertex_dist& v1, - FX_FLOAT len, - FX_FLOAT width) { - FX_FLOAT dx = (v1.y - v0.y) * width / len; - FX_FLOAT dy = (v1.x - v0.x) * width / len; + float len, + float width) { + float dx = (v1.y - v0.y) * width / len; + float dy = (v1.x - v0.x) * width / len; cap[0] = v0.x - dx; cap[1] = v0.y + dy; cap[2] = v0.x + dx; @@ -88,7 +87,7 @@ void vcgen_stroke::rewind(unsigned) m_src_vertex = 0; m_out_vertex = 0; } -unsigned vcgen_stroke::vertex(FX_FLOAT* x, FX_FLOAT* y) +unsigned vcgen_stroke::vertex(float* x, float* y) { unsigned cmd = path_cmd_line_to; line_join_e curj; diff --git a/third_party/agg23/agg_vcgen_stroke.h b/third_party/agg23/agg_vcgen_stroke.h index 84fadd6ed8b1e6e108e6304294a9f98a8559151f..23142d37f6460adf2cfd07ed28e135c3da9eb936 100644 --- a/third_party/agg23/agg_vcgen_stroke.h +++ b/third_party/agg23/agg_vcgen_stroke.h @@ -61,52 +61,52 @@ public: { return m_inner_join; } - void width(FX_FLOAT w) + void width(float w) { m_width = w / 2; } - void miter_limit(FX_FLOAT ml) + void miter_limit(float ml) { m_miter_limit = ml; } - void miter_limit_theta(FX_FLOAT t); - void inner_miter_limit(FX_FLOAT ml) + void miter_limit_theta(float t); + void inner_miter_limit(float ml) { m_inner_miter_limit = ml; } - void approximation_scale(FX_FLOAT as) + void approximation_scale(float as) { m_approx_scale = as; } - FX_FLOAT width() const + float width() const { return m_width * 2; } - FX_FLOAT miter_limit() const + float miter_limit() const { return m_miter_limit; } - FX_FLOAT inner_miter_limit() const + float inner_miter_limit() const { return m_inner_miter_limit; } - FX_FLOAT approximation_scale() const + float approximation_scale() const { return m_approx_scale; } void remove_all(); - void add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd); + void add_vertex(float x, float y, unsigned cmd); void rewind(unsigned path_id); - unsigned vertex(FX_FLOAT* x, FX_FLOAT* y); + unsigned vertex(float* x, float* y); private: vcgen_stroke(const vcgen_stroke&); const vcgen_stroke& operator = (const vcgen_stroke&); vertex_storage m_src_vertices; coord_storage m_out_vertices; - FX_FLOAT m_width; - FX_FLOAT m_miter_limit; - FX_FLOAT m_inner_miter_limit; - FX_FLOAT m_approx_scale; + float m_width; + float m_miter_limit; + float m_inner_miter_limit; + float m_approx_scale; line_cap_e m_line_cap; line_join_e m_line_join; inner_join_e m_inner_join; diff --git a/third_party/agg23/agg_vertex_sequence.h b/third_party/agg23/agg_vertex_sequence.h index 6600bf2085f0f5a8e63507b2fdc001cb66296f37..448e57b04de901e57d6555eb03698abea8771d7a 100644 --- a/third_party/agg23/agg_vertex_sequence.h +++ b/third_party/agg23/agg_vertex_sequence.h @@ -69,13 +69,13 @@ void vertex_sequence::close(bool closed) } } } -const FX_FLOAT vertex_dist_epsilon = 1e-14f; +const float vertex_dist_epsilon = 1e-14f; struct vertex_dist { - FX_FLOAT x; - FX_FLOAT y; - FX_FLOAT dist; + float x; + float y; + float dist; vertex_dist() {} - vertex_dist(FX_FLOAT x_, FX_FLOAT y_) : + vertex_dist(float x_, float y_) : x(x_), y(y_), dist(0) @@ -90,7 +90,7 @@ struct vertex_dist { struct vertex_dist_cmd : public vertex_dist { unsigned cmd; vertex_dist_cmd() {} - vertex_dist_cmd(FX_FLOAT x_, FX_FLOAT y_, unsigned cmd_) : + vertex_dist_cmd(float x_, float y_, unsigned cmd_) : vertex_dist(x_, y_), cmd(cmd_) { diff --git a/third_party/base/allocator/partition_allocator/address_space_randomization.cc b/third_party/base/allocator/partition_allocator/address_space_randomization.cc new file mode 100644 index 0000000000000000000000000000000000000000..08f22be80ab0064a1eea11900c16d367f06fd873 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/address_space_randomization.cc @@ -0,0 +1,143 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/base/allocator/partition_allocator/address_space_randomization.h" + +#include "third_party/base/allocator/partition_allocator/page_allocator.h" +#include "third_party/base/allocator/partition_allocator/spin_lock.h" +#include "third_party/build/build_config.h" + +#if defined(OS_WIN) +#include +#else +#include +#include +#endif + +// VersionHelpers.h must be included after windows.h. +#if defined(OS_WIN) +#include +#endif + +namespace pdfium { +namespace base { + +namespace { + +// This is the same PRNG as used by tcmalloc for mapping address randomness; +// see http://burtleburtle.net/bob/rand/smallprng.html +struct ranctx { + subtle::SpinLock lock; + bool initialized; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; +}; + +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + +uint32_t ranvalInternal(ranctx* x) { + uint32_t e = x->a - rot(x->b, 27); + x->a = x->b ^ rot(x->c, 17); + x->b = x->c + x->d; + x->c = x->d + e; + x->d = e + x->a; + return x->d; +} + +#undef rot + +uint32_t ranval(ranctx* x) { + subtle::SpinLock::Guard guard(x->lock); + if (UNLIKELY(!x->initialized)) { + x->initialized = true; + char c; + uint32_t seed = static_cast(reinterpret_cast(&c)); + uint32_t pid; + uint32_t usec; +#if defined(OS_WIN) + pid = GetCurrentProcessId(); + SYSTEMTIME st; + GetSystemTime(&st); + usec = static_cast(st.wMilliseconds * 1000); +#else + pid = static_cast(getpid()); + struct timeval tv; + gettimeofday(&tv, 0); + usec = static_cast(tv.tv_usec); +#endif + seed ^= pid; + seed ^= usec; + x->a = 0xf1ea5eed; + x->b = x->c = x->d = seed; + for (int i = 0; i < 20; ++i) { + (void)ranvalInternal(x); + } + } + uint32_t ret = ranvalInternal(x); + return ret; +} + +static struct ranctx s_ranctx; + +} // namespace + +// Calculates a random preferred mapping address. In calculating an address, we +// balance good ASLR against not fragmenting the address space too badly. +void* GetRandomPageBase() { + uintptr_t random; + random = static_cast(ranval(&s_ranctx)); +#if defined(ARCH_CPU_X86_64) + random <<= 32UL; + random |= static_cast(ranval(&s_ranctx)); +// This address mask gives a low likelihood of address space collisions. We +// handle the situation gracefully if there is a collision. +#if defined(OS_WIN) + random &= 0x3ffffffffffUL; + // Windows >= 8.1 has the full 47 bits. Use them where available. + static bool windows_81 = false; + static bool windows_81_initialized = false; + if (!windows_81_initialized) { + windows_81 = IsWindows8Point1OrGreater(); + windows_81_initialized = true; + } + if (!windows_81) { + random += 0x10000000000UL; + } +#elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + // This range is copied from the TSan source, but works for all tools. + random &= 0x007fffffffffUL; + random += 0x7e8000000000UL; +#else + // Linux and OS X support the full 47-bit user space of x64 processors. + random &= 0x3fffffffffffUL; +#endif +#elif defined(ARCH_CPU_ARM64) + // ARM64 on Linux has 39-bit user space. + random &= 0x3fffffffffUL; + random += 0x1000000000UL; +#else // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_ARM64) +#if defined(OS_WIN) + // On win32 host systems the randomization plus huge alignment causes + // excessive fragmentation. Plus most of these systems lack ASLR, so the + // randomization isn't buying anything. In that case we just skip it. + // TODO(jschuh): Just dump the randomization when HE-ASLR is present. + static BOOL isWow64 = -1; + if (isWow64 == -1 && !IsWow64Process(GetCurrentProcess(), &isWow64)) + isWow64 = FALSE; + if (!isWow64) + return nullptr; +#endif // defined(OS_WIN) + // This is a good range on Windows, Linux and Mac. + // Allocates in the 0.5-1.5GB region. + random &= 0x3fffffff; + random += 0x20000000; +#endif // defined(ARCH_CPU_X86_64) + random &= kPageAllocationGranularityBaseMask; + return reinterpret_cast(random); +} + +} // namespace base +} // namespace pdfium diff --git a/third_party/base/allocator/partition_allocator/address_space_randomization.h b/third_party/base/allocator/partition_allocator/address_space_randomization.h new file mode 100644 index 0000000000000000000000000000000000000000..97c5f606dda5fe00fb79e5d15d8c19aff19d05f9 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/address_space_randomization.h @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION + +namespace pdfium { +namespace base { + +// Calculates a random preferred mapping address. In calculating an address, we +// balance good ASLR against not fragmenting the address space too badly. +void* GetRandomPageBase(); + +} // namespace base +} // namespace pdfium + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION diff --git a/third_party/base/allocator/partition_allocator/oom.h b/third_party/base/allocator/partition_allocator/oom.h new file mode 100644 index 0000000000000000000000000000000000000000..41f29b5642bbe176f6b2f139f20326e1c45f7fe7 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/oom.h @@ -0,0 +1,37 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_OOM_H +#define BASE_ALLOCATOR_OOM_H + +#include "third_party/base/logging.h" + +#if defined(OS_WIN) +#include +#endif + +// Do not want trivial entry points just calling OOM_CRASH() to be +// commoned up by linker icf/comdat folding. +#define OOM_CRASH_PREVENT_ICF() \ + volatile int oom_crash_inhibit_icf = __LINE__; \ + ALLOW_UNUSED_LOCAL(oom_crash_inhibit_icf) + +// OOM_CRASH() - Specialization of IMMEDIATE_CRASH which will raise a custom +// exception on Windows to signal this is OOM and not a normal assert. +#if defined(OS_WIN) +#define OOM_CRASH() \ + do { \ + OOM_CRASH_PREVENT_ICF(); \ + ::RaiseException(0xE0000008, EXCEPTION_NONCONTINUABLE, 0, nullptr); \ + IMMEDIATE_CRASH(); \ + } while (0) +#else +#define OOM_CRASH() \ + do { \ + OOM_CRASH_PREVENT_ICF(); \ + IMMEDIATE_CRASH(); \ + } while (0) +#endif + +#endif // BASE_ALLOCATOR_OOM_H diff --git a/third_party/base/allocator/partition_allocator/page_allocator.cc b/third_party/base/allocator/partition_allocator/page_allocator.cc new file mode 100644 index 0000000000000000000000000000000000000000..abe159b727789510e4554af947c95b0371d072ed --- /dev/null +++ b/third_party/base/allocator/partition_allocator/page_allocator.cc @@ -0,0 +1,281 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/base/allocator/partition_allocator/page_allocator.h" + +#include + +#include + +#include "third_party/base/allocator/partition_allocator/address_space_randomization.h" +#include "third_party/base/base_export.h" +#include "third_party/base/logging.h" +#include "third_party/build/build_config.h" + +#if defined(OS_POSIX) + +#include +#include + +#ifndef MADV_FREE +#define MADV_FREE MADV_DONTNEED +#endif + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +// On POSIX |mmap| uses a nearby address if the hint address is blocked. +static const bool kHintIsAdvisory = true; +static std::atomic s_allocPageErrorCode{0}; + +#elif defined(OS_WIN) + +#include + +// |VirtualAlloc| will fail if allocation at the hint address is blocked. +static const bool kHintIsAdvisory = false; +static std::atomic s_allocPageErrorCode{ERROR_SUCCESS}; + +#else +#error Unknown OS +#endif // defined(OS_POSIX) + +namespace pdfium { +namespace base { + +// This internal function wraps the OS-specific page allocation call: +// |VirtualAlloc| on Windows, and |mmap| on POSIX. +static void* SystemAllocPages( + void* hint, + size_t length, + PageAccessibilityConfiguration page_accessibility) { + DCHECK(!(length & kPageAllocationGranularityOffsetMask)); + DCHECK(!(reinterpret_cast(hint) & + kPageAllocationGranularityOffsetMask)); + void* ret; +#if defined(OS_WIN) + DWORD access_flag = + page_accessibility == PageAccessible ? PAGE_READWRITE : PAGE_NOACCESS; + ret = VirtualAlloc(hint, length, MEM_RESERVE | MEM_COMMIT, access_flag); + if (!ret) + s_allocPageErrorCode = GetLastError(); +#else + int access_flag = page_accessibility == PageAccessible + ? (PROT_READ | PROT_WRITE) + : PROT_NONE; + ret = mmap(hint, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (ret == MAP_FAILED) { + s_allocPageErrorCode = errno; + ret = 0; + } +#endif + return ret; +} + +// Trims base to given length and alignment. Windows returns null on failure and +// frees base. +static void* TrimMapping(void* base, + size_t base_length, + size_t trim_length, + uintptr_t align, + PageAccessibilityConfiguration page_accessibility) { + size_t pre_slack = reinterpret_cast(base) & (align - 1); + if (pre_slack) + pre_slack = align - pre_slack; + size_t post_slack = base_length - pre_slack - trim_length; + DCHECK(base_length >= trim_length || pre_slack || post_slack); + DCHECK(pre_slack < base_length); + DCHECK(post_slack < base_length); + void* ret = base; + +#if defined(OS_POSIX) // On POSIX we can resize the allocation run. + (void)page_accessibility; + if (pre_slack) { + int res = munmap(base, pre_slack); + CHECK(!res); + ret = reinterpret_cast(base) + pre_slack; + } + if (post_slack) { + int res = munmap(reinterpret_cast(ret) + trim_length, post_slack); + CHECK(!res); + } +#else // On Windows we can't resize the allocation run. + if (pre_slack || post_slack) { + ret = reinterpret_cast(base) + pre_slack; + FreePages(base, base_length); + ret = SystemAllocPages(ret, trim_length, page_accessibility); + } +#endif + + return ret; +} + +void* AllocPages(void* address, + size_t length, + size_t align, + PageAccessibilityConfiguration page_accessibility) { + DCHECK(length >= kPageAllocationGranularity); + DCHECK(!(length & kPageAllocationGranularityOffsetMask)); + DCHECK(align >= kPageAllocationGranularity); + DCHECK(!(align & kPageAllocationGranularityOffsetMask)); + DCHECK(!(reinterpret_cast(address) & + kPageAllocationGranularityOffsetMask)); + uintptr_t align_offset_mask = align - 1; + uintptr_t align_base_mask = ~align_offset_mask; + DCHECK(!(reinterpret_cast(address) & align_offset_mask)); + + // If the client passed null as the address, choose a good one. + if (!address) { + address = GetRandomPageBase(); + address = reinterpret_cast(reinterpret_cast(address) & + align_base_mask); + } + + // First try to force an exact-size, aligned allocation from our random base. + for (int count = 0; count < 3; ++count) { + void* ret = SystemAllocPages(address, length, page_accessibility); + if (kHintIsAdvisory || ret) { + // If the alignment is to our liking, we're done. + if (!(reinterpret_cast(ret) & align_offset_mask)) + return ret; + FreePages(ret, length); +#if defined(ARCH_CPU_32_BITS) + address = reinterpret_cast( + (reinterpret_cast(ret) + align) & align_base_mask); +#endif + } else if (!address) { // We know we're OOM when an unhinted allocation + // fails. + return nullptr; + } else { +#if defined(ARCH_CPU_32_BITS) + address = reinterpret_cast(address) + align; +#endif + } + +#if !defined(ARCH_CPU_32_BITS) + // Keep trying random addresses on systems that have a large address space. + address = GetRandomPageBase(); + address = reinterpret_cast(reinterpret_cast(address) & + align_base_mask); +#endif + } + + // Map a larger allocation so we can force alignment, but continue randomizing + // only on 64-bit POSIX. + size_t try_length = length + (align - kPageAllocationGranularity); + CHECK(try_length >= length); + void* ret; + + do { + // Don't continue to burn cycles on mandatory hints (Windows). + address = kHintIsAdvisory ? GetRandomPageBase() : nullptr; + ret = SystemAllocPages(address, try_length, page_accessibility); + // The retries are for Windows, where a race can steal our mapping on + // resize. + } while (ret && + (ret = TrimMapping(ret, try_length, length, align, + page_accessibility)) == nullptr); + + return ret; +} + +void FreePages(void* address, size_t length) { + DCHECK(!(reinterpret_cast(address) & + kPageAllocationGranularityOffsetMask)); + DCHECK(!(length & kPageAllocationGranularityOffsetMask)); +#if defined(OS_POSIX) + int ret = munmap(address, length); + CHECK(!ret); +#else + BOOL ret = VirtualFree(address, 0, MEM_RELEASE); + CHECK(ret); +#endif +} + +void SetSystemPagesInaccessible(void* address, size_t length) { + DCHECK(!(length & kSystemPageOffsetMask)); +#if defined(OS_POSIX) + int ret = mprotect(address, length, PROT_NONE); + CHECK(!ret); +#else + BOOL ret = VirtualFree(address, length, MEM_DECOMMIT); + CHECK(ret); +#endif +} + +bool SetSystemPagesAccessible(void* address, size_t length) { + DCHECK(!(length & kSystemPageOffsetMask)); +#if defined(OS_POSIX) + return !mprotect(address, length, PROT_READ | PROT_WRITE); +#else + return !!VirtualAlloc(address, length, MEM_COMMIT, PAGE_READWRITE); +#endif +} + +void DecommitSystemPages(void* address, size_t length) { + DCHECK(!(length & kSystemPageOffsetMask)); +#if defined(OS_POSIX) + int ret = madvise(address, length, MADV_FREE); + if (ret != 0 && errno == EINVAL) { + // MADV_FREE only works on Linux 4.5+ . If request failed, + // retry with older MADV_DONTNEED . Note that MADV_FREE + // being defined at compile time doesn't imply runtime support. + ret = madvise(address, length, MADV_DONTNEED); + } + CHECK(!ret); +#else + SetSystemPagesInaccessible(address, length); +#endif +} + +void RecommitSystemPages(void* address, size_t length) { + DCHECK(!(length & kSystemPageOffsetMask)); +#if defined(OS_POSIX) + (void)address; +#else + CHECK(SetSystemPagesAccessible(address, length)); +#endif +} + +void DiscardSystemPages(void* address, size_t length) { + DCHECK(!(length & kSystemPageOffsetMask)); +#if defined(OS_POSIX) + // On POSIX, the implementation detail is that discard and decommit are the + // same, and lead to pages that are returned to the system immediately and + // get replaced with zeroed pages when touched. So we just call + // DecommitSystemPages() here to avoid code duplication. + DecommitSystemPages(address, length); +#else + // On Windows discarded pages are not returned to the system immediately and + // not guaranteed to be zeroed when returned to the application. + using DiscardVirtualMemoryFunction = + DWORD(WINAPI*)(PVOID virtualAddress, SIZE_T size); + static DiscardVirtualMemoryFunction discard_virtual_memory = + reinterpret_cast(-1); + if (discard_virtual_memory == + reinterpret_cast(-1)) + discard_virtual_memory = + reinterpret_cast(GetProcAddress( + GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory")); + // Use DiscardVirtualMemory when available because it releases faster than + // MEM_RESET. + DWORD ret = 1; + if (discard_virtual_memory) + ret = discard_virtual_memory(address, length); + // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on + // failure. + if (ret) { + void* ret = VirtualAlloc(address, length, MEM_RESET, PAGE_READWRITE); + CHECK(ret); + } +#endif +} + +uint32_t GetAllocPageErrorCode() { + return s_allocPageErrorCode; +} + +} // namespace base +} // namespace pdfium diff --git a/third_party/base/allocator/partition_allocator/page_allocator.h b/third_party/base/allocator/partition_allocator/page_allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..aee2532485b9e14cbf1ea86c176c1dda4c283085 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/page_allocator.h @@ -0,0 +1,133 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H + +#include + +#include + +#include "third_party/base/base_export.h" +#include "third_party/base/compiler_specific.h" +#include "third_party/build/build_config.h" + +namespace pdfium { +namespace base { + +#if defined(OS_WIN) +static const size_t kPageAllocationGranularityShift = 16; // 64KB +#elif defined(_MIPS_ARCH_LOONGSON) +static const size_t kPageAllocationGranularityShift = 14; // 16KB +#else +static const size_t kPageAllocationGranularityShift = 12; // 4KB +#endif +static const size_t kPageAllocationGranularity = + 1 << kPageAllocationGranularityShift; +static const size_t kPageAllocationGranularityOffsetMask = + kPageAllocationGranularity - 1; +static const size_t kPageAllocationGranularityBaseMask = + ~kPageAllocationGranularityOffsetMask; + +// All Blink-supported systems have 4096 sized system pages and can handle +// permissions and commit / decommit at this granularity. +// Loongson have 16384 sized system pages. +#if defined(_MIPS_ARCH_LOONGSON) +static const size_t kSystemPageSize = 16384; +#else +static const size_t kSystemPageSize = 4096; +#endif +static const size_t kSystemPageOffsetMask = kSystemPageSize - 1; +static const size_t kSystemPageBaseMask = ~kSystemPageOffsetMask; + +enum PageAccessibilityConfiguration { + PageAccessible, + PageInaccessible, +}; + +// Allocate one or more pages. +// The requested address is just a hint; the actual address returned may +// differ. The returned address will be aligned at least to align bytes. +// len is in bytes, and must be a multiple of kPageAllocationGranularity. +// align is in bytes, and must be a power-of-two multiple of +// kPageAllocationGranularity. +// If addr is null, then a suitable and randomized address will be chosen +// automatically. +// PageAccessibilityConfiguration controls the permission of the +// allocated pages. +// This call will return null if the allocation cannot be satisfied. +BASE_EXPORT void* AllocPages(void* address, + size_t len, + size_t align, + PageAccessibilityConfiguration); + +// Free one or more pages. +// addr and len must match a previous call to allocPages(). +BASE_EXPORT void FreePages(void* address, size_t length); + +// Mark one or more system pages as being inaccessible. +// Subsequently accessing any address in the range will fault, and the +// addresses will not be re-used by future allocations. +// len must be a multiple of kSystemPageSize bytes. +BASE_EXPORT void SetSystemPagesInaccessible(void* address, size_t length); + +// Mark one or more system pages as being accessible. +// The pages will be readable and writeable. +// len must be a multiple of kSystemPageSize bytes. +// The result bool value indicates whether the permission +// change succeeded or not. You must check the result +// (in most cases you need to CHECK that it is true). +BASE_EXPORT WARN_UNUSED_RESULT bool SetSystemPagesAccessible(void* address, + size_t length); + +// Decommit one or more system pages. Decommitted means that the physical memory +// is released to the system, but the virtual address space remains reserved. +// System pages are re-committed by calling recommitSystemPages(). Touching +// a decommitted page _may_ fault. +// Clients should not make any assumptions about the contents of decommitted +// system pages, before or after they write to the page. The only guarantee +// provided is that the contents of the system page will be deterministic again +// after recommitting and writing to it. In particlar note that system pages are +// not guaranteed to be zero-filled upon re-commit. len must be a multiple of +// kSystemPageSize bytes. +BASE_EXPORT void DecommitSystemPages(void* address, size_t length); + +// Recommit one or more system pages. Decommitted system pages must be +// recommitted before they are read are written again. +// Note that this operation may be a no-op on some platforms. +// len must be a multiple of kSystemPageSize bytes. +BASE_EXPORT void RecommitSystemPages(void* address, size_t length); + +// Discard one or more system pages. Discarding is a hint to the system that +// the page is no longer required. The hint may: +// - Do nothing. +// - Discard the page immediately, freeing up physical pages. +// - Discard the page at some time in the future in response to memory pressure. +// Only committed pages should be discarded. Discarding a page does not +// decommit it, and it is valid to discard an already-discarded page. +// A read or write to a discarded page will not fault. +// Reading from a discarded page may return the original page content, or a +// page full of zeroes. +// Writing to a discarded page is the only guaranteed way to tell the system +// that the page is required again. Once written to, the content of the page is +// guaranteed stable once more. After being written to, the page content may be +// based on the original page content, or a page of zeroes. +// len must be a multiple of kSystemPageSize bytes. +BASE_EXPORT void DiscardSystemPages(void* address, size_t length); + +ALWAYS_INLINE uintptr_t RoundUpToSystemPage(uintptr_t address) { + return (address + kSystemPageOffsetMask) & kSystemPageBaseMask; +} + +ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) { + return address & kSystemPageBaseMask; +} + +// Returns errno (or GetLastError code) when mmap (or VirtualAlloc) fails. +BASE_EXPORT uint32_t GetAllocPageErrorCode(); + +} // namespace base +} // namespace pdfium + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H diff --git a/third_party/base/allocator/partition_allocator/partition_alloc.cc b/third_party/base/allocator/partition_allocator/partition_alloc.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff366b861f81fb06e2fb26e53861489ec50c4126 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/partition_alloc.cc @@ -0,0 +1,1444 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/base/allocator/partition_allocator/partition_alloc.h" + +#include + +#include "third_party/base/allocator/partition_allocator/oom.h" +#include "third_party/base/allocator/partition_allocator/spin_lock.h" +#include "third_party/base/compiler_specific.h" + +// Two partition pages are used as guard / metadata page so make sure the super +// page size is bigger. +static_assert(pdfium::base::kPartitionPageSize * 4 <= + pdfium::base::kSuperPageSize, + "ok super page size"); +static_assert(!(pdfium::base::kSuperPageSize % + pdfium::base::kPartitionPageSize), + "ok super page multiple"); +// Four system pages gives us room to hack out a still-guard-paged piece +// of metadata in the middle of a guard partition page. +static_assert(pdfium::base::kSystemPageSize * 4 <= + pdfium::base::kPartitionPageSize, + "ok partition page size"); +static_assert(!(pdfium::base::kPartitionPageSize % + pdfium::base::kSystemPageSize), + "ok partition page multiple"); +static_assert(sizeof(pdfium::base::PartitionPage) <= + pdfium::base::kPageMetadataSize, + "PartitionPage should not be too big"); +static_assert(sizeof(pdfium::base::PartitionBucket) <= + pdfium::base::kPageMetadataSize, + "PartitionBucket should not be too big"); +static_assert(sizeof(pdfium::base::PartitionSuperPageExtentEntry) <= + pdfium::base::kPageMetadataSize, + "PartitionSuperPageExtentEntry should not be too big"); +static_assert(pdfium::base::kPageMetadataSize * + pdfium::base::kNumPartitionPagesPerSuperPage <= + pdfium::base::kSystemPageSize, + "page metadata fits in hole"); +// Check that some of our zanier calculations worked out as expected. +static_assert(pdfium::base::kGenericSmallestBucket == 8, + "generic smallest bucket"); +static_assert(pdfium::base::kGenericMaxBucketed == 983040, + "generic max bucketed"); +static_assert(pdfium::base::kMaxSystemPagesPerSlotSpan < (1 << 8), + "System pages per slot span must be less than 128."); + +namespace pdfium { +namespace base { + +subtle::SpinLock PartitionRootBase::gInitializedLock; +bool PartitionRootBase::gInitialized = false; +PartitionPage PartitionRootBase::gSeedPage; +PartitionBucket PartitionRootBase::gPagedBucket; +void (*PartitionRootBase::gOomHandlingFunction)() = nullptr; +PartitionAllocHooks::AllocationHook* PartitionAllocHooks::allocation_hook_ = + nullptr; +PartitionAllocHooks::FreeHook* PartitionAllocHooks::free_hook_ = nullptr; + +static uint8_t PartitionBucketNumSystemPages(size_t size) { + // This works out reasonably for the current bucket sizes of the generic + // allocator, and the current values of partition page size and constants. + // Specifically, we have enough room to always pack the slots perfectly into + // some number of system pages. The only waste is the waste associated with + // unfaulted pages (i.e. wasted address space). + // TODO: we end up using a lot of system pages for very small sizes. For + // example, we'll use 12 system pages for slot size 24. The slot size is + // so small that the waste would be tiny with just 4, or 1, system pages. + // Later, we can investigate whether there are anti-fragmentation benefits + // to using fewer system pages. + double best_waste_ratio = 1.0f; + uint16_t best_pages = 0; + if (size > kMaxSystemPagesPerSlotSpan * kSystemPageSize) { + DCHECK(!(size % kSystemPageSize)); + best_pages = static_cast(size / kSystemPageSize); + CHECK(best_pages < (1 << 8)); + return static_cast(best_pages); + } + DCHECK(size <= kMaxSystemPagesPerSlotSpan * kSystemPageSize); + for (uint16_t i = kNumSystemPagesPerPartitionPage - 1; + i <= kMaxSystemPagesPerSlotSpan; ++i) { + size_t page_size = kSystemPageSize * i; + size_t num_slots = page_size / size; + size_t waste = page_size - (num_slots * size); + // Leaving a page unfaulted is not free; the page will occupy an empty page + // table entry. Make a simple attempt to account for that. + size_t num_remainder_pages = i & (kNumSystemPagesPerPartitionPage - 1); + size_t num_unfaulted_pages = + num_remainder_pages + ? (kNumSystemPagesPerPartitionPage - num_remainder_pages) + : 0; + waste += sizeof(void*) * num_unfaulted_pages; + double waste_ratio = (double)waste / (double)page_size; + if (waste_ratio < best_waste_ratio) { + best_waste_ratio = waste_ratio; + best_pages = i; + } + } + DCHECK(best_pages > 0); + CHECK(best_pages <= kMaxSystemPagesPerSlotSpan); + return static_cast(best_pages); +} + +static void PartitionAllocBaseInit(PartitionRootBase* root) { + DCHECK(!root->initialized); + { + subtle::SpinLock::Guard guard(PartitionRootBase::gInitializedLock); + if (!PartitionRootBase::gInitialized) { + PartitionRootBase::gInitialized = true; + // We mark the seed page as free to make sure it is skipped by our + // logic to find a new active page. + PartitionRootBase::gPagedBucket.active_pages_head = + &PartitionRootGeneric::gSeedPage; + } + } + + root->initialized = true; + root->total_size_of_committed_pages = 0; + root->total_size_of_super_pages = 0; + root->total_size_of_direct_mapped_pages = 0; + root->next_super_page = 0; + root->next_partition_page = 0; + root->next_partition_page_end = 0; + root->first_extent = 0; + root->current_extent = 0; + root->direct_map_list = 0; + + memset(&root->global_empty_page_ring, '\0', + sizeof(root->global_empty_page_ring)); + root->global_empty_page_ring_index = 0; + + // This is a "magic" value so we can test if a root pointer is valid. + root->inverted_self = ~reinterpret_cast(root); +} + +static void PartitionBucketInitBase(PartitionBucket* bucket, + PartitionRootBase* root) { + bucket->active_pages_head = &PartitionRootGeneric::gSeedPage; + bucket->empty_pages_head = 0; + bucket->decommitted_pages_head = 0; + bucket->num_full_pages = 0; + bucket->num_system_pages_per_slot_span = + PartitionBucketNumSystemPages(bucket->slot_size); +} + +void PartitionAllocGlobalInit(void (*oom_handling_function)()) { + DCHECK(oom_handling_function); + PartitionRootBase::gOomHandlingFunction = oom_handling_function; +} + +void PartitionAllocInit(PartitionRoot* root, + size_t num_buckets, + size_t max_allocation) { + PartitionAllocBaseInit(root); + + root->num_buckets = num_buckets; + root->max_allocation = max_allocation; + size_t i; + for (i = 0; i < root->num_buckets; ++i) { + PartitionBucket* bucket = &root->buckets()[i]; + if (!i) + bucket->slot_size = kAllocationGranularity; + else + bucket->slot_size = i << kBucketShift; + PartitionBucketInitBase(bucket, root); + } +} + +void PartitionAllocGenericInit(PartitionRootGeneric* root) { + subtle::SpinLock::Guard guard(root->lock); + + PartitionAllocBaseInit(root); + + // Precalculate some shift and mask constants used in the hot path. + // Example: malloc(41) == 101001 binary. + // Order is 6 (1 << 6-1) == 32 is highest bit set. + // order_index is the next three MSB == 010 == 2. + // sub_order_index_mask is a mask for the remaining bits == 11 (masking to 01 + // for + // the sub_order_index). + size_t order; + for (order = 0; order <= kBitsPerSizeT; ++order) { + size_t order_index_shift; + if (order < kGenericNumBucketsPerOrderBits + 1) + order_index_shift = 0; + else + order_index_shift = order - (kGenericNumBucketsPerOrderBits + 1); + root->order_index_shifts[order] = order_index_shift; + size_t sub_order_index_mask; + if (order == kBitsPerSizeT) { + // This avoids invoking undefined behavior for an excessive shift. + sub_order_index_mask = + static_cast(-1) >> (kGenericNumBucketsPerOrderBits + 1); + } else { + sub_order_index_mask = ((static_cast(1) << order) - 1) >> + (kGenericNumBucketsPerOrderBits + 1); + } + root->order_sub_index_masks[order] = sub_order_index_mask; + } + + // Set up the actual usable buckets first. + // Note that typical values (i.e. min allocation size of 8) will result in + // pseudo buckets (size==9 etc. or more generally, size is not a multiple + // of the smallest allocation granularity). + // We avoid them in the bucket lookup map, but we tolerate them to keep the + // code simpler and the structures more generic. + size_t i, j; + size_t current_size = kGenericSmallestBucket; + size_t currentIncrement = + kGenericSmallestBucket >> kGenericNumBucketsPerOrderBits; + PartitionBucket* bucket = &root->buckets[0]; + for (i = 0; i < kGenericNumBucketedOrders; ++i) { + for (j = 0; j < kGenericNumBucketsPerOrder; ++j) { + bucket->slot_size = current_size; + PartitionBucketInitBase(bucket, root); + // Disable psuedo buckets so that touching them faults. + if (current_size % kGenericSmallestBucket) + bucket->active_pages_head = 0; + current_size += currentIncrement; + ++bucket; + } + currentIncrement <<= 1; + } + DCHECK(current_size == 1 << kGenericMaxBucketedOrder); + DCHECK(bucket == &root->buckets[0] + kGenericNumBuckets); + + // Then set up the fast size -> bucket lookup table. + bucket = &root->buckets[0]; + PartitionBucket** bucketPtr = &root->bucket_lookups[0]; + for (order = 0; order <= kBitsPerSizeT; ++order) { + for (j = 0; j < kGenericNumBucketsPerOrder; ++j) { + if (order < kGenericMinBucketedOrder) { + // Use the bucket of the finest granularity for malloc(0) etc. + *bucketPtr++ = &root->buckets[0]; + } else if (order > kGenericMaxBucketedOrder) { + *bucketPtr++ = &PartitionRootGeneric::gPagedBucket; + } else { + PartitionBucket* validBucket = bucket; + // Skip over invalid buckets. + while (validBucket->slot_size % kGenericSmallestBucket) + validBucket++; + *bucketPtr++ = validBucket; + bucket++; + } + } + } + DCHECK(bucket == &root->buckets[0] + kGenericNumBuckets); + DCHECK(bucketPtr == + &root->bucket_lookups[0] + + ((kBitsPerSizeT + 1) * kGenericNumBucketsPerOrder)); + // And there's one last bucket lookup that will be hit for e.g. malloc(-1), + // which tries to overflow to a non-existant order. + *bucketPtr = &PartitionRootGeneric::gPagedBucket; +} + +#if !defined(ARCH_CPU_64_BITS) +static NOINLINE void PartitionOutOfMemoryWithLotsOfUncommitedPages() { + OOM_CRASH(); +} +#endif + +static NOINLINE void PartitionOutOfMemory(const PartitionRootBase* root) { +#if !defined(ARCH_CPU_64_BITS) + // Check whether this OOM is due to a lot of super pages that are allocated + // but not committed, probably due to http://crbug.com/421387. + if (root->total_size_of_super_pages + + root->total_size_of_direct_mapped_pages - + root->total_size_of_committed_pages > + kReasonableSizeOfUnusedPages) { + PartitionOutOfMemoryWithLotsOfUncommitedPages(); + } +#endif + if (PartitionRootBase::gOomHandlingFunction) + (*PartitionRootBase::gOomHandlingFunction)(); + OOM_CRASH(); +} + +static NOINLINE void PartitionExcessiveAllocationSize() { + OOM_CRASH(); +} + +static NOINLINE void PartitionBucketFull() { + OOM_CRASH(); +} + +// partitionPageStateIs* +// Note that it's only valid to call these functions on pages found on one of +// the page lists. Specifically, you can't call these functions on full pages +// that were detached from the active list. +static bool ALWAYS_INLINE +PartitionPageStateIsActive(const PartitionPage* page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + DCHECK(!page->page_offset); + return (page->num_allocated_slots > 0 && + (page->freelist_head || page->num_unprovisioned_slots)); +} + +static bool ALWAYS_INLINE PartitionPageStateIsFull(const PartitionPage* page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + DCHECK(!page->page_offset); + bool ret = (page->num_allocated_slots == PartitionBucketSlots(page->bucket)); + if (ret) { + DCHECK(!page->freelist_head); + DCHECK(!page->num_unprovisioned_slots); + } + return ret; +} + +static bool ALWAYS_INLINE PartitionPageStateIsEmpty(const PartitionPage* page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + DCHECK(!page->page_offset); + return (!page->num_allocated_slots && page->freelist_head); +} + +static bool ALWAYS_INLINE +PartitionPageStateIsDecommitted(const PartitionPage* page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + DCHECK(!page->page_offset); + bool ret = (!page->num_allocated_slots && !page->freelist_head); + if (ret) { + DCHECK(!page->num_unprovisioned_slots); + DCHECK(page->empty_cache_index == -1); + } + return ret; +} + +static void PartitionIncreaseCommittedPages(PartitionRootBase* root, + size_t len) { + root->total_size_of_committed_pages += len; + DCHECK(root->total_size_of_committed_pages <= + root->total_size_of_super_pages + + root->total_size_of_direct_mapped_pages); +} + +static void PartitionDecreaseCommittedPages(PartitionRootBase* root, + size_t len) { + root->total_size_of_committed_pages -= len; + DCHECK(root->total_size_of_committed_pages <= + root->total_size_of_super_pages + + root->total_size_of_direct_mapped_pages); +} + +static ALWAYS_INLINE void PartitionDecommitSystemPages(PartitionRootBase* root, + void* address, + size_t length) { + DecommitSystemPages(address, length); + PartitionDecreaseCommittedPages(root, length); +} + +static ALWAYS_INLINE void PartitionRecommitSystemPages(PartitionRootBase* root, + void* address, + size_t length) { + RecommitSystemPages(address, length); + PartitionIncreaseCommittedPages(root, length); +} + +static ALWAYS_INLINE void* PartitionAllocPartitionPages( + PartitionRootBase* root, + int flags, + uint16_t num_partition_pages) { + DCHECK(!(reinterpret_cast(root->next_partition_page) % + kPartitionPageSize)); + DCHECK(!(reinterpret_cast(root->next_partition_page_end) % + kPartitionPageSize)); + DCHECK(num_partition_pages <= kNumPartitionPagesPerSuperPage); + size_t total_size = kPartitionPageSize * num_partition_pages; + size_t num_partition_pages_left = + (root->next_partition_page_end - root->next_partition_page) >> + kPartitionPageShift; + if (LIKELY(num_partition_pages_left >= num_partition_pages)) { + // In this case, we can still hand out pages from the current super page + // allocation. + char* ret = root->next_partition_page; + root->next_partition_page += total_size; + PartitionIncreaseCommittedPages(root, total_size); + return ret; + } + + // Need a new super page. We want to allocate super pages in a continguous + // address region as much as possible. This is important for not causing + // page table bloat and not fragmenting address spaces in 32 bit + // architectures. + char* requestedAddress = root->next_super_page; + char* super_page = reinterpret_cast(AllocPages( + requestedAddress, kSuperPageSize, kSuperPageSize, PageAccessible)); + if (UNLIKELY(!super_page)) + return 0; + + root->total_size_of_super_pages += kSuperPageSize; + PartitionIncreaseCommittedPages(root, total_size); + + root->next_super_page = super_page + kSuperPageSize; + char* ret = super_page + kPartitionPageSize; + root->next_partition_page = ret + total_size; + root->next_partition_page_end = root->next_super_page - kPartitionPageSize; + // Make the first partition page in the super page a guard page, but leave a + // hole in the middle. + // This is where we put page metadata and also a tiny amount of extent + // metadata. + SetSystemPagesInaccessible(super_page, kSystemPageSize); + SetSystemPagesInaccessible(super_page + (kSystemPageSize * 2), + kPartitionPageSize - (kSystemPageSize * 2)); + // Also make the last partition page a guard page. + SetSystemPagesInaccessible(super_page + (kSuperPageSize - kPartitionPageSize), + kPartitionPageSize); + + // If we were after a specific address, but didn't get it, assume that + // the system chose a lousy address. Here most OS'es have a default + // algorithm that isn't randomized. For example, most Linux + // distributions will allocate the mapping directly before the last + // successful mapping, which is far from random. So we just get fresh + // randomness for the next mapping attempt. + if (requestedAddress && requestedAddress != super_page) + root->next_super_page = 0; + + // We allocated a new super page so update super page metadata. + // First check if this is a new extent or not. + PartitionSuperPageExtentEntry* latest_extent = + reinterpret_cast( + PartitionSuperPageToMetadataArea(super_page)); + // By storing the root in every extent metadata object, we have a fast way + // to go from a pointer within the partition to the root object. + latest_extent->root = root; + // Most new extents will be part of a larger extent, and these three fields + // are unused, but we initialize them to 0 so that we get a clear signal + // in case they are accidentally used. + latest_extent->super_page_base = 0; + latest_extent->super_pages_end = 0; + latest_extent->next = 0; + + PartitionSuperPageExtentEntry* current_extent = root->current_extent; + bool isNewExtent = (super_page != requestedAddress); + if (UNLIKELY(isNewExtent)) { + if (UNLIKELY(!current_extent)) { + DCHECK(!root->first_extent); + root->first_extent = latest_extent; + } else { + DCHECK(current_extent->super_page_base); + current_extent->next = latest_extent; + } + root->current_extent = latest_extent; + latest_extent->super_page_base = super_page; + latest_extent->super_pages_end = super_page + kSuperPageSize; + } else { + // We allocated next to an existing extent so just nudge the size up a + // little. + DCHECK(current_extent->super_pages_end); + current_extent->super_pages_end += kSuperPageSize; + DCHECK(ret >= current_extent->super_page_base && + ret < current_extent->super_pages_end); + } + return ret; +} + +static ALWAYS_INLINE uint16_t +PartitionBucketPartitionPages(const PartitionBucket* bucket) { + return (bucket->num_system_pages_per_slot_span + + (kNumSystemPagesPerPartitionPage - 1)) / + kNumSystemPagesPerPartitionPage; +} + +static ALWAYS_INLINE void PartitionPageReset(PartitionPage* page) { + DCHECK(PartitionPageStateIsDecommitted(page)); + + page->num_unprovisioned_slots = PartitionBucketSlots(page->bucket); + DCHECK(page->num_unprovisioned_slots); + + page->next_page = nullptr; +} + +static ALWAYS_INLINE void PartitionPageSetup(PartitionPage* page, + PartitionBucket* bucket) { + // The bucket never changes. We set it up once. + page->bucket = bucket; + page->empty_cache_index = -1; + + PartitionPageReset(page); + + // If this page has just a single slot, do not set up page offsets for any + // page metadata other than the first one. This ensures that attempts to + // touch invalid page metadata fail. + if (page->num_unprovisioned_slots == 1) + return; + + uint16_t num_partition_pages = PartitionBucketPartitionPages(bucket); + char* page_char_ptr = reinterpret_cast(page); + for (uint16_t i = 1; i < num_partition_pages; ++i) { + page_char_ptr += kPageMetadataSize; + PartitionPage* secondary_page = + reinterpret_cast(page_char_ptr); + secondary_page->page_offset = i; + } +} + +static ALWAYS_INLINE char* PartitionPageAllocAndFillFreelist( + PartitionPage* page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + uint16_t num_slots = page->num_unprovisioned_slots; + DCHECK(num_slots); + PartitionBucket* bucket = page->bucket; + // We should only get here when _every_ slot is either used or unprovisioned. + // (The third state is "on the freelist". If we have a non-empty freelist, we + // should not get here.) + DCHECK(num_slots + page->num_allocated_slots == PartitionBucketSlots(bucket)); + // Similarly, make explicitly sure that the freelist is empty. + DCHECK(!page->freelist_head); + DCHECK(page->num_allocated_slots >= 0); + + size_t size = bucket->slot_size; + char* base = reinterpret_cast(PartitionPageToPointer(page)); + char* return_object = base + (size * page->num_allocated_slots); + char* firstFreelistPointer = return_object + size; + char* firstFreelistPointerExtent = + firstFreelistPointer + sizeof(PartitionFreelistEntry*); + // Our goal is to fault as few system pages as possible. We calculate the + // page containing the "end" of the returned slot, and then allow freelist + // pointers to be written up to the end of that page. + char* sub_page_limit = reinterpret_cast( + RoundUpToSystemPage(reinterpret_cast(firstFreelistPointer))); + char* slots_limit = return_object + (size * num_slots); + char* freelist_limit = sub_page_limit; + if (UNLIKELY(slots_limit < freelist_limit)) + freelist_limit = slots_limit; + + uint16_t num_new_freelist_entries = 0; + if (LIKELY(firstFreelistPointerExtent <= freelist_limit)) { + // Only consider used space in the slot span. If we consider wasted + // space, we may get an off-by-one when a freelist pointer fits in the + // wasted space, but a slot does not. + // We know we can fit at least one freelist pointer. + num_new_freelist_entries = 1; + // Any further entries require space for the whole slot span. + num_new_freelist_entries += static_cast( + (freelist_limit - firstFreelistPointerExtent) / size); + } + + // We always return an object slot -- that's the +1 below. + // We do not neccessarily create any new freelist entries, because we cross + // sub page boundaries frequently for large bucket sizes. + DCHECK(num_new_freelist_entries + 1 <= num_slots); + num_slots -= (num_new_freelist_entries + 1); + page->num_unprovisioned_slots = num_slots; + page->num_allocated_slots++; + + if (LIKELY(num_new_freelist_entries)) { + char* freelist_pointer = firstFreelistPointer; + PartitionFreelistEntry* entry = + reinterpret_cast(freelist_pointer); + page->freelist_head = entry; + while (--num_new_freelist_entries) { + freelist_pointer += size; + PartitionFreelistEntry* next_entry = + reinterpret_cast(freelist_pointer); + entry->next = PartitionFreelistMask(next_entry); + entry = next_entry; + } + entry->next = PartitionFreelistMask(0); + } else { + page->freelist_head = 0; + } + return return_object; +} + +// This helper function scans a bucket's active page list for a suitable new +// active page. +// When it finds a suitable new active page (one that has free slots and is not +// empty), it is set as the new active page. If there is no suitable new +// active page, the current active page is set to the seed page. +// As potential pages are scanned, they are tidied up according to their state. +// Empty pages are swept on to the empty page list, decommitted pages on to the +// decommitted page list and full pages are unlinked from any list. +static bool PartitionSetNewActivePage(PartitionBucket* bucket) { + PartitionPage* page = bucket->active_pages_head; + if (page == &PartitionRootBase::gSeedPage) + return false; + + PartitionPage* next_page; + + for (; page; page = next_page) { + next_page = page->next_page; + DCHECK(page->bucket == bucket); + DCHECK(page != bucket->empty_pages_head); + DCHECK(page != bucket->decommitted_pages_head); + + // Deal with empty and decommitted pages. + if (LIKELY(PartitionPageStateIsActive(page))) { + // This page is usable because it has freelist entries, or has + // unprovisioned slots we can create freelist entries from. + bucket->active_pages_head = page; + return true; + } + if (LIKELY(PartitionPageStateIsEmpty(page))) { + page->next_page = bucket->empty_pages_head; + bucket->empty_pages_head = page; + } else if (LIKELY(PartitionPageStateIsDecommitted(page))) { + page->next_page = bucket->decommitted_pages_head; + bucket->decommitted_pages_head = page; + } else { + DCHECK(PartitionPageStateIsFull(page)); + // If we get here, we found a full page. Skip over it too, and also + // tag it as full (via a negative value). We need it tagged so that + // free'ing can tell, and move it back into the active page list. + page->num_allocated_slots = -page->num_allocated_slots; + ++bucket->num_full_pages; + // num_full_pages is a uint16_t for efficient packing so guard against + // overflow to be safe. + if (UNLIKELY(!bucket->num_full_pages)) + PartitionBucketFull(); + // Not necessary but might help stop accidents. + page->next_page = 0; + } + } + + bucket->active_pages_head = &PartitionRootGeneric::gSeedPage; + return false; +} + +static ALWAYS_INLINE PartitionDirectMapExtent* partitionPageToDirectMapExtent( + PartitionPage* page) { + DCHECK(PartitionBucketIsDirectMapped(page->bucket)); + return reinterpret_cast( + reinterpret_cast(page) + 3 * kPageMetadataSize); +} + +static ALWAYS_INLINE void PartitionPageSetRawSize(PartitionPage* page, + size_t size) { + size_t* raw_size_ptr = PartitionPageGetRawSizePtr(page); + if (UNLIKELY(raw_size_ptr != nullptr)) + *raw_size_ptr = size; +} + +static ALWAYS_INLINE PartitionPage* PartitionDirectMap(PartitionRootBase* root, + int flags, + size_t raw_size) { + size_t size = PartitionDirectMapSize(raw_size); + + // Because we need to fake looking like a super page, we need to allocate + // a bunch of system pages more than "size": + // - The first few system pages are the partition page in which the super + // page metadata is stored. We fault just one system page out of a partition + // page sized clump. + // - We add a trailing guard page on 32-bit (on 64-bit we rely on the + // massive address space plus randomization instead). + size_t map_size = size + kPartitionPageSize; +#if !defined(ARCH_CPU_64_BITS) + map_size += kSystemPageSize; +#endif + // Round up to the allocation granularity. + map_size += kPageAllocationGranularityOffsetMask; + map_size &= kPageAllocationGranularityBaseMask; + + // TODO: these pages will be zero-filled. Consider internalizing an + // allocZeroed() API so we can avoid a memset() entirely in this case. + char* ptr = reinterpret_cast( + AllocPages(0, map_size, kSuperPageSize, PageAccessible)); + if (UNLIKELY(!ptr)) + return nullptr; + + size_t committed_page_size = size + kSystemPageSize; + root->total_size_of_direct_mapped_pages += committed_page_size; + PartitionIncreaseCommittedPages(root, committed_page_size); + + char* slot = ptr + kPartitionPageSize; + SetSystemPagesInaccessible(ptr + (kSystemPageSize * 2), + kPartitionPageSize - (kSystemPageSize * 2)); +#if !defined(ARCH_CPU_64_BITS) + SetSystemPagesInaccessible(ptr, kSystemPageSize); + SetSystemPagesInaccessible(slot + size, kSystemPageSize); +#endif + + PartitionSuperPageExtentEntry* extent = + reinterpret_cast( + PartitionSuperPageToMetadataArea(ptr)); + extent->root = root; + // The new structures are all located inside a fresh system page so they + // will all be zeroed out. These DCHECKs are for documentation. + DCHECK(!extent->super_page_base); + DCHECK(!extent->super_pages_end); + DCHECK(!extent->next); + PartitionPage* page = PartitionPointerToPageNoAlignmentCheck(slot); + PartitionBucket* bucket = reinterpret_cast( + reinterpret_cast(page) + (kPageMetadataSize * 2)); + DCHECK(!page->next_page); + DCHECK(!page->num_allocated_slots); + DCHECK(!page->num_unprovisioned_slots); + DCHECK(!page->page_offset); + DCHECK(!page->empty_cache_index); + page->bucket = bucket; + page->freelist_head = reinterpret_cast(slot); + PartitionFreelistEntry* next_entry = + reinterpret_cast(slot); + next_entry->next = PartitionFreelistMask(0); + + DCHECK(!bucket->active_pages_head); + DCHECK(!bucket->empty_pages_head); + DCHECK(!bucket->decommitted_pages_head); + DCHECK(!bucket->num_system_pages_per_slot_span); + DCHECK(!bucket->num_full_pages); + bucket->slot_size = size; + + PartitionDirectMapExtent* map_extent = partitionPageToDirectMapExtent(page); + map_extent->map_size = map_size - kPartitionPageSize - kSystemPageSize; + map_extent->bucket = bucket; + + // Maintain the doubly-linked list of all direct mappings. + map_extent->next_extent = root->direct_map_list; + if (map_extent->next_extent) + map_extent->next_extent->prev_extent = map_extent; + map_extent->prev_extent = nullptr; + root->direct_map_list = map_extent; + + return page; +} + +static ALWAYS_INLINE void PartitionDirectUnmap(PartitionPage* page) { + PartitionRootBase* root = PartitionPageToRoot(page); + const PartitionDirectMapExtent* extent = partitionPageToDirectMapExtent(page); + size_t unmap_size = extent->map_size; + + // Maintain the doubly-linked list of all direct mappings. + if (extent->prev_extent) { + DCHECK(extent->prev_extent->next_extent == extent); + extent->prev_extent->next_extent = extent->next_extent; + } else { + root->direct_map_list = extent->next_extent; + } + if (extent->next_extent) { + DCHECK(extent->next_extent->prev_extent == extent); + extent->next_extent->prev_extent = extent->prev_extent; + } + + // Add on the size of the trailing guard page and preceeding partition + // page. + unmap_size += kPartitionPageSize + kSystemPageSize; + + size_t uncommitted_page_size = page->bucket->slot_size + kSystemPageSize; + PartitionDecreaseCommittedPages(root, uncommitted_page_size); + DCHECK(root->total_size_of_direct_mapped_pages >= uncommitted_page_size); + root->total_size_of_direct_mapped_pages -= uncommitted_page_size; + + DCHECK(!(unmap_size & kPageAllocationGranularityOffsetMask)); + + char* ptr = reinterpret_cast(PartitionPageToPointer(page)); + // Account for the mapping starting a partition page before the actual + // allocation address. + ptr -= kPartitionPageSize; + + FreePages(ptr, unmap_size); +} + +void* PartitionAllocSlowPath(PartitionRootBase* root, + int flags, + size_t size, + PartitionBucket* bucket) { + // The slow path is called when the freelist is empty. + DCHECK(!bucket->active_pages_head->freelist_head); + + PartitionPage* new_page = nullptr; + + // For the PartitionAllocGeneric API, we have a bunch of buckets marked + // as special cases. We bounce them through to the slow path so that we + // can still have a blazing fast hot path due to lack of corner-case + // branches. + bool returnNull = flags & PartitionAllocReturnNull; + if (UNLIKELY(PartitionBucketIsDirectMapped(bucket))) { + DCHECK(size > kGenericMaxBucketed); + DCHECK(bucket == &PartitionRootBase::gPagedBucket); + DCHECK(bucket->active_pages_head == &PartitionRootGeneric::gSeedPage); + if (size > kGenericMaxDirectMapped) { + if (returnNull) + return nullptr; + PartitionExcessiveAllocationSize(); + } + new_page = PartitionDirectMap(root, flags, size); + } else if (LIKELY(PartitionSetNewActivePage(bucket))) { + // First, did we find an active page in the active pages list? + new_page = bucket->active_pages_head; + DCHECK(PartitionPageStateIsActive(new_page)); + } else if (LIKELY(bucket->empty_pages_head != nullptr) || + LIKELY(bucket->decommitted_pages_head != nullptr)) { + // Second, look in our lists of empty and decommitted pages. + // Check empty pages first, which are preferred, but beware that an + // empty page might have been decommitted. + while (LIKELY((new_page = bucket->empty_pages_head) != nullptr)) { + DCHECK(new_page->bucket == bucket); + DCHECK(PartitionPageStateIsEmpty(new_page) || + PartitionPageStateIsDecommitted(new_page)); + bucket->empty_pages_head = new_page->next_page; + // Accept the empty page unless it got decommitted. + if (new_page->freelist_head) { + new_page->next_page = nullptr; + break; + } + DCHECK(PartitionPageStateIsDecommitted(new_page)); + new_page->next_page = bucket->decommitted_pages_head; + bucket->decommitted_pages_head = new_page; + } + if (UNLIKELY(!new_page) && + LIKELY(bucket->decommitted_pages_head != nullptr)) { + new_page = bucket->decommitted_pages_head; + DCHECK(new_page->bucket == bucket); + DCHECK(PartitionPageStateIsDecommitted(new_page)); + bucket->decommitted_pages_head = new_page->next_page; + void* addr = PartitionPageToPointer(new_page); + PartitionRecommitSystemPages(root, addr, + PartitionBucketBytes(new_page->bucket)); + PartitionPageReset(new_page); + } + DCHECK(new_page); + } else { + // Third. If we get here, we need a brand new page. + uint16_t num_partition_pages = PartitionBucketPartitionPages(bucket); + void* rawPages = + PartitionAllocPartitionPages(root, flags, num_partition_pages); + if (LIKELY(rawPages != nullptr)) { + new_page = PartitionPointerToPageNoAlignmentCheck(rawPages); + PartitionPageSetup(new_page, bucket); + } + } + + // Bail if we had a memory allocation failure. + if (UNLIKELY(!new_page)) { + DCHECK(bucket->active_pages_head == &PartitionRootGeneric::gSeedPage); + if (returnNull) + return nullptr; + PartitionOutOfMemory(root); + } + + bucket = new_page->bucket; + DCHECK(bucket != &PartitionRootBase::gPagedBucket); + bucket->active_pages_head = new_page; + PartitionPageSetRawSize(new_page, size); + + // If we found an active page with free slots, or an empty page, we have a + // usable freelist head. + if (LIKELY(new_page->freelist_head != nullptr)) { + PartitionFreelistEntry* entry = new_page->freelist_head; + PartitionFreelistEntry* new_head = PartitionFreelistMask(entry->next); + new_page->freelist_head = new_head; + new_page->num_allocated_slots++; + return entry; + } + // Otherwise, we need to build the freelist. + DCHECK(new_page->num_unprovisioned_slots); + return PartitionPageAllocAndFillFreelist(new_page); +} + +static ALWAYS_INLINE void PartitionDecommitPage(PartitionRootBase* root, + PartitionPage* page) { + DCHECK(PartitionPageStateIsEmpty(page)); + DCHECK(!PartitionBucketIsDirectMapped(page->bucket)); + void* addr = PartitionPageToPointer(page); + PartitionDecommitSystemPages(root, addr, PartitionBucketBytes(page->bucket)); + + // We actually leave the decommitted page in the active list. We'll sweep + // it on to the decommitted page list when we next walk the active page + // list. + // Pulling this trick enables us to use a singly-linked page list for all + // cases, which is critical in keeping the page metadata structure down to + // 32 bytes in size. + page->freelist_head = 0; + page->num_unprovisioned_slots = 0; + DCHECK(PartitionPageStateIsDecommitted(page)); +} + +static void PartitionDecommitPageIfPossible(PartitionRootBase* root, + PartitionPage* page) { + DCHECK(page->empty_cache_index >= 0); + DCHECK(static_cast(page->empty_cache_index) < kMaxFreeableSpans); + DCHECK(page == root->global_empty_page_ring[page->empty_cache_index]); + page->empty_cache_index = -1; + if (PartitionPageStateIsEmpty(page)) + PartitionDecommitPage(root, page); +} + +static ALWAYS_INLINE void PartitionRegisterEmptyPage(PartitionPage* page) { + DCHECK(PartitionPageStateIsEmpty(page)); + PartitionRootBase* root = PartitionPageToRoot(page); + + // If the page is already registered as empty, give it another life. + if (page->empty_cache_index != -1) { + DCHECK(page->empty_cache_index >= 0); + DCHECK(static_cast(page->empty_cache_index) < kMaxFreeableSpans); + DCHECK(root->global_empty_page_ring[page->empty_cache_index] == page); + root->global_empty_page_ring[page->empty_cache_index] = 0; + } + + int16_t current_index = root->global_empty_page_ring_index; + PartitionPage* pageToDecommit = root->global_empty_page_ring[current_index]; + // The page might well have been re-activated, filled up, etc. before we get + // around to looking at it here. + if (pageToDecommit) + PartitionDecommitPageIfPossible(root, pageToDecommit); + + // We put the empty slot span on our global list of "pages that were once + // empty". thus providing it a bit of breathing room to get re-used before + // we really free it. This improves performance, particularly on Mac OS X + // which has subpar memory management performance. + root->global_empty_page_ring[current_index] = page; + page->empty_cache_index = current_index; + ++current_index; + if (current_index == kMaxFreeableSpans) + current_index = 0; + root->global_empty_page_ring_index = current_index; +} + +static void PartitionDecommitEmptyPages(PartitionRootBase* root) { + for (size_t i = 0; i < kMaxFreeableSpans; ++i) { + PartitionPage* page = root->global_empty_page_ring[i]; + if (page) + PartitionDecommitPageIfPossible(root, page); + root->global_empty_page_ring[i] = nullptr; + } +} + +void PartitionFreeSlowPath(PartitionPage* page) { + PartitionBucket* bucket = page->bucket; + DCHECK(page != &PartitionRootGeneric::gSeedPage); + if (LIKELY(page->num_allocated_slots == 0)) { + // Page became fully unused. + if (UNLIKELY(PartitionBucketIsDirectMapped(bucket))) { + PartitionDirectUnmap(page); + return; + } + // If it's the current active page, change it. We bounce the page to + // the empty list as a force towards defragmentation. + if (LIKELY(page == bucket->active_pages_head)) + (void)PartitionSetNewActivePage(bucket); + DCHECK(bucket->active_pages_head != page); + + PartitionPageSetRawSize(page, 0); + DCHECK(!PartitionPageGetRawSize(page)); + + PartitionRegisterEmptyPage(page); + } else { + DCHECK(!PartitionBucketIsDirectMapped(bucket)); + // Ensure that the page is full. That's the only valid case if we + // arrive here. + DCHECK(page->num_allocated_slots < 0); + // A transition of num_allocated_slots from 0 to -1 is not legal, and + // likely indicates a double-free. + CHECK(page->num_allocated_slots != -1); + page->num_allocated_slots = -page->num_allocated_slots - 2; + DCHECK(page->num_allocated_slots == PartitionBucketSlots(bucket) - 1); + // Fully used page became partially used. It must be put back on the + // non-full page list. Also make it the current page to increase the + // chances of it being filled up again. The old current page will be + // the next page. + DCHECK(!page->next_page); + if (LIKELY(bucket->active_pages_head != &PartitionRootGeneric::gSeedPage)) + page->next_page = bucket->active_pages_head; + bucket->active_pages_head = page; + --bucket->num_full_pages; + // Special case: for a partition page with just a single slot, it may + // now be empty and we want to run it through the empty logic. + if (UNLIKELY(page->num_allocated_slots == 0)) + PartitionFreeSlowPath(page); + } +} + +bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, + PartitionPage* page, + size_t raw_size) { + DCHECK(PartitionBucketIsDirectMapped(page->bucket)); + + raw_size = PartitionCookieSizeAdjustAdd(raw_size); + + // Note that the new size might be a bucketed size; this function is called + // whenever we're reallocating a direct mapped allocation. + size_t new_size = PartitionDirectMapSize(raw_size); + if (new_size < kGenericMinDirectMappedDownsize) + return false; + + // bucket->slot_size is the current size of the allocation. + size_t current_size = page->bucket->slot_size; + if (new_size == current_size) + return true; + + char* char_ptr = static_cast(PartitionPageToPointer(page)); + + if (new_size < current_size) { + size_t map_size = partitionPageToDirectMapExtent(page)->map_size; + + // Don't reallocate in-place if new size is less than 80 % of the full + // map size, to avoid holding on to too much unused address space. + if ((new_size / kSystemPageSize) * 5 < (map_size / kSystemPageSize) * 4) + return false; + + // Shrink by decommitting unneeded pages and making them inaccessible. + size_t decommitSize = current_size - new_size; + PartitionDecommitSystemPages(root, char_ptr + new_size, decommitSize); + SetSystemPagesInaccessible(char_ptr + new_size, decommitSize); + } else if (new_size <= partitionPageToDirectMapExtent(page)->map_size) { + // Grow within the actually allocated memory. Just need to make the + // pages accessible again. + size_t recommit_size = new_size - current_size; + bool ret = SetSystemPagesAccessible(char_ptr + current_size, recommit_size); + CHECK(ret); + PartitionRecommitSystemPages(root, char_ptr + current_size, recommit_size); + +#if DCHECK_IS_ON() + memset(char_ptr + current_size, kUninitializedByte, recommit_size); +#endif + } else { + // We can't perform the realloc in-place. + // TODO: support this too when possible. + return false; + } + +#if DCHECK_IS_ON() + // Write a new trailing cookie. + PartitionCookieWriteValue(char_ptr + raw_size - kCookieSize); +#endif + + PartitionPageSetRawSize(page, raw_size); + DCHECK(PartitionPageGetRawSize(page) == raw_size); + + page->bucket->slot_size = new_size; + return true; +} + +void* PartitionReallocGeneric(PartitionRootGeneric* root, + void* ptr, + size_t new_size, + const char* type_name) { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + return realloc(ptr, new_size); +#else + if (UNLIKELY(!ptr)) + return PartitionAllocGeneric(root, new_size, type_name); + if (UNLIKELY(!new_size)) { + PartitionFreeGeneric(root, ptr); + return 0; + } + + if (new_size > kGenericMaxDirectMapped) + PartitionExcessiveAllocationSize(); + + DCHECK(PartitionPointerIsValid(PartitionCookieFreePointerAdjust(ptr))); + + PartitionPage* page = + PartitionPointerToPage(PartitionCookieFreePointerAdjust(ptr)); + + if (UNLIKELY(PartitionBucketIsDirectMapped(page->bucket))) { + // We may be able to perform the realloc in place by changing the + // accessibility of memory pages and, if reducing the size, decommitting + // them. + if (partitionReallocDirectMappedInPlace(root, page, new_size)) { + PartitionAllocHooks::ReallocHookIfEnabled(ptr, ptr, new_size, type_name); + return ptr; + } + } + + size_t actual_new_size = PartitionAllocActualSize(root, new_size); + size_t actual_old_size = PartitionAllocGetSize(ptr); + + // TODO: note that tcmalloc will "ignore" a downsizing realloc() unless the + // new size is a significant percentage smaller. We could do the same if we + // determine it is a win. + if (actual_new_size == actual_old_size) { + // Trying to allocate a block of size new_size would give us a block of + // the same size as the one we've already got, so re-use the allocation + // after updating statistics (and cookies, if present). + PartitionPageSetRawSize(page, PartitionCookieSizeAdjustAdd(new_size)); +#if DCHECK_IS_ON() + // Write a new trailing cookie when it is possible to keep track of + // |new_size| via the raw size pointer. + if (PartitionPageGetRawSizePtr(page)) + PartitionCookieWriteValue(static_cast(ptr) + new_size); +#endif + return ptr; + } + + // This realloc cannot be resized in-place. Sadness. + void* ret = PartitionAllocGeneric(root, new_size, type_name); + size_t copy_size = actual_old_size; + if (new_size < copy_size) + copy_size = new_size; + + memcpy(ret, ptr, copy_size); + PartitionFreeGeneric(root, ptr); + return ret; +#endif +} + +static size_t PartitionPurgePage(PartitionPage* page, bool discard) { + const PartitionBucket* bucket = page->bucket; + size_t slot_size = bucket->slot_size; + if (slot_size < kSystemPageSize || !page->num_allocated_slots) + return 0; + + size_t bucket_num_slots = PartitionBucketSlots(bucket); + size_t discardable_bytes = 0; + + size_t raw_size = PartitionPageGetRawSize(const_cast(page)); + if (raw_size) { + uint32_t usedBytes = static_cast(RoundUpToSystemPage(raw_size)); + discardable_bytes = bucket->slot_size - usedBytes; + if (discardable_bytes && discard) { + char* ptr = reinterpret_cast(PartitionPageToPointer(page)); + ptr += usedBytes; + DiscardSystemPages(ptr, discardable_bytes); + } + return discardable_bytes; + } + + const size_t max_slot_count = + (kPartitionPageSize * kMaxPartitionPagesPerSlotSpan) / kSystemPageSize; + DCHECK(bucket_num_slots <= max_slot_count); + DCHECK(page->num_unprovisioned_slots < bucket_num_slots); + size_t num_slots = bucket_num_slots - page->num_unprovisioned_slots; + char slot_usage[max_slot_count]; + size_t last_slot = static_cast(-1); + memset(slot_usage, 1, num_slots); + char* ptr = reinterpret_cast(PartitionPageToPointer(page)); + PartitionFreelistEntry* entry = page->freelist_head; + // First, walk the freelist for this page and make a bitmap of which slots + // are not in use. + while (entry) { + size_t slotIndex = (reinterpret_cast(entry) - ptr) / slot_size; + DCHECK(slotIndex < num_slots); + slot_usage[slotIndex] = 0; + entry = PartitionFreelistMask(entry->next); + // If we have a slot where the masked freelist entry is 0, we can + // actually discard that freelist entry because touching a discarded + // page is guaranteed to return original content or 0. + // (Note that this optimization won't fire on big endian machines + // because the masking function is negation.) + if (!PartitionFreelistMask(entry)) + last_slot = slotIndex; + } + + // If the slot(s) at the end of the slot span are not in used, we can + // truncate them entirely and rewrite the freelist. + size_t truncated_slots = 0; + while (!slot_usage[num_slots - 1]) { + truncated_slots++; + num_slots--; + DCHECK(num_slots); + } + // First, do the work of calculating the discardable bytes. Don't actually + // discard anything unless the discard flag was passed in. + char* begin_ptr = nullptr; + char* end_ptr = nullptr; + size_t unprovisioned_bytes = 0; + if (truncated_slots) { + begin_ptr = ptr + (num_slots * slot_size); + end_ptr = begin_ptr + (slot_size * truncated_slots); + begin_ptr = reinterpret_cast( + RoundUpToSystemPage(reinterpret_cast(begin_ptr))); + // We round the end pointer here up and not down because we're at the + // end of a slot span, so we "own" all the way up the page boundary. + end_ptr = reinterpret_cast( + RoundUpToSystemPage(reinterpret_cast(end_ptr))); + DCHECK(end_ptr <= ptr + PartitionBucketBytes(bucket)); + if (begin_ptr < end_ptr) { + unprovisioned_bytes = end_ptr - begin_ptr; + discardable_bytes += unprovisioned_bytes; + } + } + if (unprovisioned_bytes && discard) { + DCHECK(truncated_slots > 0); + size_t num_new_entries = 0; + page->num_unprovisioned_slots += static_cast(truncated_slots); + // Rewrite the freelist. + PartitionFreelistEntry** entry_ptr = &page->freelist_head; + for (size_t slotIndex = 0; slotIndex < num_slots; ++slotIndex) { + if (slot_usage[slotIndex]) + continue; + PartitionFreelistEntry* entry = reinterpret_cast( + ptr + (slot_size * slotIndex)); + *entry_ptr = PartitionFreelistMask(entry); + entry_ptr = reinterpret_cast(entry); + num_new_entries++; + } + // Terminate the freelist chain. + *entry_ptr = nullptr; + // The freelist head is stored unmasked. + page->freelist_head = PartitionFreelistMask(page->freelist_head); + DCHECK(num_new_entries == num_slots - page->num_allocated_slots); + // Discard the memory. + DiscardSystemPages(begin_ptr, unprovisioned_bytes); + } + + // Next, walk the slots and for any not in use, consider where the system + // page boundaries occur. We can release any system pages back to the + // system as long as we don't interfere with a freelist pointer or an + // adjacent slot. + for (size_t i = 0; i < num_slots; ++i) { + if (slot_usage[i]) + continue; + // The first address we can safely discard is just after the freelist + // pointer. There's one quirk: if the freelist pointer is actually a + // null, we can discard that pointer value too. + char* begin_ptr = ptr + (i * slot_size); + char* end_ptr = begin_ptr + slot_size; + if (i != last_slot) + begin_ptr += sizeof(PartitionFreelistEntry); + begin_ptr = reinterpret_cast( + RoundUpToSystemPage(reinterpret_cast(begin_ptr))); + end_ptr = reinterpret_cast( + RoundDownToSystemPage(reinterpret_cast(end_ptr))); + if (begin_ptr < end_ptr) { + size_t partial_slot_bytes = end_ptr - begin_ptr; + discardable_bytes += partial_slot_bytes; + if (discard) + DiscardSystemPages(begin_ptr, partial_slot_bytes); + } + } + return discardable_bytes; +} + +static void PartitionPurgeBucket(PartitionBucket* bucket) { + if (bucket->active_pages_head != &PartitionRootGeneric::gSeedPage) { + for (PartitionPage* page = bucket->active_pages_head; page; + page = page->next_page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + (void)PartitionPurgePage(page, true); + } + } +} + +void PartitionPurgeMemory(PartitionRoot* root, int flags) { + if (flags & PartitionPurgeDecommitEmptyPages) + PartitionDecommitEmptyPages(root); + // We don't currently do anything for PartitionPurgeDiscardUnusedSystemPages + // here because that flag is only useful for allocations >= system page + // size. We only have allocations that large inside generic partitions + // at the moment. +} + +void PartitionPurgeMemoryGeneric(PartitionRootGeneric* root, int flags) { + subtle::SpinLock::Guard guard(root->lock); + if (flags & PartitionPurgeDecommitEmptyPages) + PartitionDecommitEmptyPages(root); + if (flags & PartitionPurgeDiscardUnusedSystemPages) { + for (size_t i = 0; i < kGenericNumBuckets; ++i) { + PartitionBucket* bucket = &root->buckets[i]; + if (bucket->slot_size >= kSystemPageSize) + PartitionPurgeBucket(bucket); + } + } +} + +static void PartitionDumpPageStats(PartitionBucketMemoryStats* stats_out, + const PartitionPage* page) { + uint16_t bucket_num_slots = PartitionBucketSlots(page->bucket); + + if (PartitionPageStateIsDecommitted(page)) { + ++stats_out->num_decommitted_pages; + return; + } + + stats_out->discardable_bytes += + PartitionPurgePage(const_cast(page), false); + + size_t raw_size = PartitionPageGetRawSize(const_cast(page)); + if (raw_size) + stats_out->active_bytes += static_cast(raw_size); + else + stats_out->active_bytes += + (page->num_allocated_slots * stats_out->bucket_slot_size); + + size_t page_bytes_resident = + RoundUpToSystemPage((bucket_num_slots - page->num_unprovisioned_slots) * + stats_out->bucket_slot_size); + stats_out->resident_bytes += page_bytes_resident; + if (PartitionPageStateIsEmpty(page)) { + stats_out->decommittable_bytes += page_bytes_resident; + ++stats_out->num_empty_pages; + } else if (PartitionPageStateIsFull(page)) { + ++stats_out->num_full_pages; + } else { + DCHECK(PartitionPageStateIsActive(page)); + ++stats_out->num_active_pages; + } +} + +static void PartitionDumpBucketStats(PartitionBucketMemoryStats* stats_out, + const PartitionBucket* bucket) { + DCHECK(!PartitionBucketIsDirectMapped(bucket)); + stats_out->is_valid = false; + // If the active page list is empty (== &PartitionRootGeneric::gSeedPage), + // the bucket might still need to be reported if it has a list of empty, + // decommitted or full pages. + if (bucket->active_pages_head == &PartitionRootGeneric::gSeedPage && + !bucket->empty_pages_head && !bucket->decommitted_pages_head && + !bucket->num_full_pages) + return; + + memset(stats_out, '\0', sizeof(*stats_out)); + stats_out->is_valid = true; + stats_out->is_direct_map = false; + stats_out->num_full_pages = static_cast(bucket->num_full_pages); + stats_out->bucket_slot_size = bucket->slot_size; + uint16_t bucket_num_slots = PartitionBucketSlots(bucket); + size_t bucket_useful_storage = stats_out->bucket_slot_size * bucket_num_slots; + stats_out->allocated_page_size = PartitionBucketBytes(bucket); + stats_out->active_bytes = bucket->num_full_pages * bucket_useful_storage; + stats_out->resident_bytes = + bucket->num_full_pages * stats_out->allocated_page_size; + + for (const PartitionPage* page = bucket->empty_pages_head; page; + page = page->next_page) { + DCHECK(PartitionPageStateIsEmpty(page) || + PartitionPageStateIsDecommitted(page)); + PartitionDumpPageStats(stats_out, page); + } + for (const PartitionPage* page = bucket->decommitted_pages_head; page; + page = page->next_page) { + DCHECK(PartitionPageStateIsDecommitted(page)); + PartitionDumpPageStats(stats_out, page); + } + + if (bucket->active_pages_head != &PartitionRootGeneric::gSeedPage) { + for (const PartitionPage* page = bucket->active_pages_head; page; + page = page->next_page) { + DCHECK(page != &PartitionRootGeneric::gSeedPage); + PartitionDumpPageStats(stats_out, page); + } + } +} + +void PartitionDumpStatsGeneric(PartitionRootGeneric* partition, + const char* partition_name, + bool is_light_dump, + PartitionStatsDumper* dumper) { + PartitionMemoryStats stats = {0}; + stats.total_mmapped_bytes = partition->total_size_of_super_pages + + partition->total_size_of_direct_mapped_pages; + stats.total_committed_bytes = partition->total_size_of_committed_pages; + + size_t direct_mapped_allocations_total_size = 0; + + static const size_t kMaxReportableDirectMaps = 4096; + + // Allocate on the heap rather than on the stack to avoid stack overflow + // skirmishes (on Windows, in particular). + std::unique_ptr direct_map_lengths = nullptr; + if (!is_light_dump) { + direct_map_lengths = + std::unique_ptr(new uint32_t[kMaxReportableDirectMaps]); + } + + PartitionBucketMemoryStats bucket_stats[kGenericNumBuckets]; + size_t num_direct_mapped_allocations = 0; + { + subtle::SpinLock::Guard guard(partition->lock); + + for (size_t i = 0; i < kGenericNumBuckets; ++i) { + const PartitionBucket* bucket = &partition->buckets[i]; + // Don't report the pseudo buckets that the generic allocator sets up in + // order to preserve a fast size->bucket map (see + // PartitionAllocGenericInit for details). + if (!bucket->active_pages_head) + bucket_stats[i].is_valid = false; + else + PartitionDumpBucketStats(&bucket_stats[i], bucket); + if (bucket_stats[i].is_valid) { + stats.total_resident_bytes += bucket_stats[i].resident_bytes; + stats.total_active_bytes += bucket_stats[i].active_bytes; + stats.total_decommittable_bytes += bucket_stats[i].decommittable_bytes; + stats.total_discardable_bytes += bucket_stats[i].discardable_bytes; + } + } + + for (PartitionDirectMapExtent *extent = partition->direct_map_list; + extent && num_direct_mapped_allocations < kMaxReportableDirectMaps; + extent = extent->next_extent, ++num_direct_mapped_allocations) { + DCHECK(!extent->next_extent || + extent->next_extent->prev_extent == extent); + size_t slot_size = extent->bucket->slot_size; + direct_mapped_allocations_total_size += slot_size; + if (is_light_dump) + continue; + direct_map_lengths[num_direct_mapped_allocations] = slot_size; + } + } + + if (!is_light_dump) { + // Call |PartitionsDumpBucketStats| after collecting stats because it can + // try to allocate using |PartitionAllocGeneric| and it can't obtain the + // lock. + for (size_t i = 0; i < kGenericNumBuckets; ++i) { + if (bucket_stats[i].is_valid) + dumper->PartitionsDumpBucketStats(partition_name, &bucket_stats[i]); + } + + for (size_t i = 0; i < num_direct_mapped_allocations; ++i) { + uint32_t size = direct_map_lengths[i]; + + PartitionBucketMemoryStats stats; + memset(&stats, '\0', sizeof(stats)); + stats.is_valid = true; + stats.is_direct_map = true; + stats.num_full_pages = 1; + stats.allocated_page_size = size; + stats.bucket_slot_size = size; + stats.active_bytes = size; + stats.resident_bytes = size; + dumper->PartitionsDumpBucketStats(partition_name, &stats); + } + } + + stats.total_resident_bytes += direct_mapped_allocations_total_size; + stats.total_active_bytes += direct_mapped_allocations_total_size; + dumper->PartitionDumpTotals(partition_name, &stats); +} + +void PartitionDumpStats(PartitionRoot* partition, + const char* partition_name, + bool is_light_dump, + PartitionStatsDumper* dumper) { + static const size_t kMaxReportableBuckets = 4096 / sizeof(void*); + PartitionBucketMemoryStats memory_stats[kMaxReportableBuckets]; + const size_t partitionNumBuckets = partition->num_buckets; + DCHECK(partitionNumBuckets <= kMaxReportableBuckets); + + for (size_t i = 0; i < partitionNumBuckets; ++i) + PartitionDumpBucketStats(&memory_stats[i], &partition->buckets()[i]); + + // PartitionsDumpBucketStats is called after collecting stats because it + // can use PartitionAlloc to allocate and this can affect the statistics. + PartitionMemoryStats stats = {0}; + stats.total_mmapped_bytes = partition->total_size_of_super_pages; + stats.total_committed_bytes = partition->total_size_of_committed_pages; + DCHECK(!partition->total_size_of_direct_mapped_pages); + for (size_t i = 0; i < partitionNumBuckets; ++i) { + if (memory_stats[i].is_valid) { + stats.total_resident_bytes += memory_stats[i].resident_bytes; + stats.total_active_bytes += memory_stats[i].active_bytes; + stats.total_decommittable_bytes += memory_stats[i].decommittable_bytes; + stats.total_discardable_bytes += memory_stats[i].discardable_bytes; + if (!is_light_dump) + dumper->PartitionsDumpBucketStats(partition_name, &memory_stats[i]); + } + } + dumper->PartitionDumpTotals(partition_name, &stats); +} + +} // namespace base +} // namespace pdfium diff --git a/third_party/base/allocator/partition_allocator/partition_alloc.h b/third_party/base/allocator/partition_allocator/partition_alloc.h new file mode 100644 index 0000000000000000000000000000000000000000..7e8415c7601192530b092a610edeee16bc0ebf39 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/partition_alloc.h @@ -0,0 +1,911 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H + +// DESCRIPTION +// partitionAlloc() / PartitionAllocGeneric() and PartitionFree() / +// PartitionFreeGeneric() are approximately analagous to malloc() and free(). +// +// The main difference is that a PartitionRoot / PartitionRootGeneric object +// must be supplied to these functions, representing a specific "heap partition" +// that will be used to satisfy the allocation. Different partitions are +// guaranteed to exist in separate address spaces, including being separate from +// the main system heap. If the contained objects are all freed, physical memory +// is returned to the system but the address space remains reserved. +// See PartitionAlloc.md for other security properties PartitionAlloc provides. +// +// THE ONLY LEGITIMATE WAY TO OBTAIN A PartitionRoot IS THROUGH THE +// SizeSpecificPartitionAllocator / PartitionAllocatorGeneric classes. To +// minimize the instruction count to the fullest extent possible, the +// PartitionRoot is really just a header adjacent to other data areas provided +// by the allocator class. +// +// The partitionAlloc() variant of the API has the following caveats: +// - Allocations and frees against a single partition must be single threaded. +// - Allocations must not exceed a max size, chosen at compile-time via a +// templated parameter to PartitionAllocator. +// - Allocation sizes must be aligned to the system pointer size. +// - Allocations are bucketed exactly according to size. +// +// And for PartitionAllocGeneric(): +// - Multi-threaded use against a single partition is ok; locking is handled. +// - Allocations of any arbitrary size can be handled (subject to a limit of +// INT_MAX bytes for security reasons). +// - Bucketing is by approximate size, for example an allocation of 4000 bytes +// might be placed into a 4096-byte bucket. Bucket sizes are chosen to try and +// keep worst-case waste to ~10%. +// +// The allocators are designed to be extremely fast, thanks to the following +// properties and design: +// - Just two single (reasonably predicatable) branches in the hot / fast path +// for both allocating and (significantly) freeing. +// - A minimal number of operations in the hot / fast path, with the slow paths +// in separate functions, leading to the possibility of inlining. +// - Each partition page (which is usually multiple physical pages) has a +// metadata structure which allows fast mapping of free() address to an +// underlying bucket. +// - Supports a lock-free API for fast performance in single-threaded cases. +// - The freelist for a given bucket is split across a number of partition +// pages, enabling various simple tricks to try and minimize fragmentation. +// - Fine-grained bucket sizes leading to less waste and better packing. +// +// The following security properties could be investigated in the future: +// - Per-object bucketing (instead of per-size) is mostly available at the API, +// but not used yet. +// - No randomness of freelist entries or bucket position. +// - Better checking for wild pointers in free(). +// - Better freelist masking function to guarantee fault on 32-bit. + +#include +#include + +#include "third_party/base/allocator/partition_allocator/page_allocator.h" +#include "third_party/base/allocator/partition_allocator/spin_lock.h" +#include "third_party/base/bits.h" +#include "third_party/base/compiler_specific.h" +#include "third_party/base/logging.h" +#include "third_party/base/sys_byteorder.h" +#include "third_party/build/build_config.h" + +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) +#include +#endif + +namespace pdfium { +namespace base { + +// Allocation granularity of sizeof(void*) bytes. +static const size_t kAllocationGranularity = sizeof(void*); +static const size_t kAllocationGranularityMask = kAllocationGranularity - 1; +static const size_t kBucketShift = (kAllocationGranularity == 8) ? 3 : 2; + +// Underlying partition storage pages are a power-of-two size. It is typical +// for a partition page to be based on multiple system pages. Most references to +// "page" refer to partition pages. +// We also have the concept of "super pages" -- these are the underlying system +// allocations we make. Super pages contain multiple partition pages inside them +// and include space for a small amount of metadata per partition page. +// Inside super pages, we store "slot spans". A slot span is a continguous range +// of one or more partition pages that stores allocations of the same size. +// Slot span sizes are adjusted depending on the allocation size, to make sure +// the packing does not lead to unused (wasted) space at the end of the last +// system page of the span. For our current max slot span size of 64k and other +// constant values, we pack _all_ PartitionAllocGeneric() sizes perfectly up +// against the end of a system page. +#if defined(_MIPS_ARCH_LOONGSON) +static const size_t kPartitionPageShift = 16; // 64KB +#else +static const size_t kPartitionPageShift = 14; // 16KB +#endif +static const size_t kPartitionPageSize = 1 << kPartitionPageShift; +static const size_t kPartitionPageOffsetMask = kPartitionPageSize - 1; +static const size_t kPartitionPageBaseMask = ~kPartitionPageOffsetMask; +static const size_t kMaxPartitionPagesPerSlotSpan = 4; + +// To avoid fragmentation via never-used freelist entries, we hand out partition +// freelist sections gradually, in units of the dominant system page size. +// What we're actually doing is avoiding filling the full partition page (16 KB) +// with freelist pointers right away. Writing freelist pointers will fault and +// dirty a private page, which is very wasteful if we never actually store +// objects there. +static const size_t kNumSystemPagesPerPartitionPage = + kPartitionPageSize / kSystemPageSize; +static const size_t kMaxSystemPagesPerSlotSpan = + kNumSystemPagesPerPartitionPage * kMaxPartitionPagesPerSlotSpan; + +// We reserve virtual address space in 2MB chunks (aligned to 2MB as well). +// These chunks are called "super pages". We do this so that we can store +// metadata in the first few pages of each 2MB aligned section. This leads to +// a very fast free(). We specifically choose 2MB because this virtual address +// block represents a full but single PTE allocation on ARM, ia32 and x64. +// +// The layout of the super page is as follows. The sizes below are the same +// for 32 bit and 64 bit. +// +// | Guard page (4KB) | +// | Metadata page (4KB) | +// | Guard pages (8KB) | +// | Slot span | +// | Slot span | +// | ... | +// | Slot span | +// | Guard page (4KB) | +// +// - Each slot span is a contiguous range of one or more PartitionPages. +// - The metadata page has the following format. Note that the PartitionPage +// that is not at the head of a slot span is "unused". In other words, +// the metadata for the slot span is stored only in the first PartitionPage +// of the slot span. Metadata accesses to other PartitionPages are +// redirected to the first PartitionPage. +// +// | SuperPageExtentEntry (32B) | +// | PartitionPage of slot span 1 (32B, used) | +// | PartitionPage of slot span 1 (32B, unused) | +// | PartitionPage of slot span 1 (32B, unused) | +// | PartitionPage of slot span 2 (32B, used) | +// | PartitionPage of slot span 3 (32B, used) | +// | ... | +// | PartitionPage of slot span N (32B, unused) | +// +// A direct mapped page has a similar layout to fake it looking like a super +// page: +// +// | Guard page (4KB) | +// | Metadata page (4KB) | +// | Guard pages (8KB) | +// | Direct mapped object | +// | Guard page (4KB) | +// +// - The metadata page has the following layout: +// +// | SuperPageExtentEntry (32B) | +// | PartitionPage (32B) | +// | PartitionBucket (32B) | +// | PartitionDirectMapExtent (8B) | +static const size_t kSuperPageShift = 21; // 2MB +static const size_t kSuperPageSize = 1 << kSuperPageShift; +static const size_t kSuperPageOffsetMask = kSuperPageSize - 1; +static const size_t kSuperPageBaseMask = ~kSuperPageOffsetMask; +static const size_t kNumPartitionPagesPerSuperPage = + kSuperPageSize / kPartitionPageSize; + +static const size_t kPageMetadataShift = 5; // 32 bytes per partition page. +static const size_t kPageMetadataSize = 1 << kPageMetadataShift; + +// The following kGeneric* constants apply to the generic variants of the API. +// The "order" of an allocation is closely related to the power-of-two size of +// the allocation. More precisely, the order is the bit index of the +// most-significant-bit in the allocation size, where the bit numbers starts +// at index 1 for the least-significant-bit. +// In terms of allocation sizes, order 0 covers 0, order 1 covers 1, order 2 +// covers 2->3, order 3 covers 4->7, order 4 covers 8->15. +static const size_t kGenericMinBucketedOrder = 4; // 8 bytes. +static const size_t kGenericMaxBucketedOrder = + 20; // Largest bucketed order is 1<<(20-1) (storing 512KB -> almost 1MB) +static const size_t kGenericNumBucketedOrders = + (kGenericMaxBucketedOrder - kGenericMinBucketedOrder) + 1; +// Eight buckets per order (for the higher orders), e.g. order 8 is 128, 144, +// 160, ..., 240: +static const size_t kGenericNumBucketsPerOrderBits = 3; +static const size_t kGenericNumBucketsPerOrder = + 1 << kGenericNumBucketsPerOrderBits; +static const size_t kGenericNumBuckets = + kGenericNumBucketedOrders * kGenericNumBucketsPerOrder; +static const size_t kGenericSmallestBucket = 1 + << (kGenericMinBucketedOrder - 1); +static const size_t kGenericMaxBucketSpacing = + 1 << ((kGenericMaxBucketedOrder - 1) - kGenericNumBucketsPerOrderBits); +static const size_t kGenericMaxBucketed = + (1 << (kGenericMaxBucketedOrder - 1)) + + ((kGenericNumBucketsPerOrder - 1) * kGenericMaxBucketSpacing); +static const size_t kGenericMinDirectMappedDownsize = + kGenericMaxBucketed + + 1; // Limit when downsizing a direct mapping using realloc(). +static const size_t kGenericMaxDirectMapped = INT_MAX - kSystemPageSize; +static const size_t kBitsPerSizeT = sizeof(void*) * CHAR_BIT; + +// Constants for the memory reclaim logic. +static const size_t kMaxFreeableSpans = 16; + +// If the total size in bytes of allocated but not committed pages exceeds this +// value (probably it is a "out of virtual address space" crash), +// a special crash stack trace is generated at |partitionOutOfMemory|. +// This is to distinguish "out of virtual address space" from +// "out of physical memory" in crash reports. +static const size_t kReasonableSizeOfUnusedPages = 1024 * 1024 * 1024; // 1GiB + +#if DCHECK_IS_ON() +// These two byte values match tcmalloc. +static const unsigned char kUninitializedByte = 0xAB; +static const unsigned char kFreedByte = 0xCD; +static const size_t kCookieSize = + 16; // Handles alignment up to XMM instructions on Intel. +static const unsigned char kCookieValue[kCookieSize] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xD0, 0x0D, + 0x13, 0x37, 0xF0, 0x05, 0xBA, 0x11, 0xAB, 0x1E}; +#endif + +struct PartitionBucket; +struct PartitionRootBase; + +struct PartitionFreelistEntry { + PartitionFreelistEntry* next; +}; + +// Some notes on page states. A page can be in one of four major states: +// 1) Active. +// 2) Full. +// 3) Empty. +// 4) Decommitted. +// An active page has available free slots. A full page has no free slots. An +// empty page has no free slots, and a decommitted page is an empty page that +// had its backing memory released back to the system. +// There are two linked lists tracking the pages. The "active page" list is an +// approximation of a list of active pages. It is an approximation because +// full, empty and decommitted pages may briefly be present in the list until +// we next do a scan over it. +// The "empty page" list is an accurate list of pages which are either empty +// or decommitted. +// +// The significant page transitions are: +// - free() will detect when a full page has a slot free()'d and immediately +// return the page to the head of the active list. +// - free() will detect when a page is fully emptied. It _may_ add it to the +// empty list or it _may_ leave it on the active list until a future list scan. +// - malloc() _may_ scan the active page list in order to fulfil the request. +// If it does this, full, empty and decommitted pages encountered will be +// booted out of the active list. If there are no suitable active pages found, +// an empty or decommitted page (if one exists) will be pulled from the empty +// list on to the active list. +struct PartitionPage { + PartitionFreelistEntry* freelist_head; + PartitionPage* next_page; + PartitionBucket* bucket; + // Deliberately signed, 0 for empty or decommitted page, -n for full pages: + int16_t num_allocated_slots; + uint16_t num_unprovisioned_slots; + uint16_t page_offset; + int16_t empty_cache_index; // -1 if not in the empty cache. +}; + +struct PartitionBucket { + PartitionPage* active_pages_head; // Accessed most in hot path => goes first. + PartitionPage* empty_pages_head; + PartitionPage* decommitted_pages_head; + uint32_t slot_size; + unsigned num_system_pages_per_slot_span : 8; + unsigned num_full_pages : 24; +}; + +// An "extent" is a span of consecutive superpages. We link to the partition's +// next extent (if there is one) at the very start of a superpage's metadata +// area. +struct PartitionSuperPageExtentEntry { + PartitionRootBase* root; + char* super_page_base; + char* super_pages_end; + PartitionSuperPageExtentEntry* next; +}; + +struct PartitionDirectMapExtent { + PartitionDirectMapExtent* next_extent; + PartitionDirectMapExtent* prev_extent; + PartitionBucket* bucket; + size_t map_size; // Mapped size, not including guard pages and meta-data. +}; + +struct BASE_EXPORT PartitionRootBase { + size_t total_size_of_committed_pages; + size_t total_size_of_super_pages; + size_t total_size_of_direct_mapped_pages; + // Invariant: total_size_of_committed_pages <= + // total_size_of_super_pages + + // total_size_of_direct_mapped_pages. + unsigned num_buckets; + unsigned max_allocation; + bool initialized; + char* next_super_page; + char* next_partition_page; + char* next_partition_page_end; + PartitionSuperPageExtentEntry* current_extent; + PartitionSuperPageExtentEntry* first_extent; + PartitionDirectMapExtent* direct_map_list; + PartitionPage* global_empty_page_ring[kMaxFreeableSpans]; + int16_t global_empty_page_ring_index; + uintptr_t inverted_self; + + static subtle::SpinLock gInitializedLock; + static bool gInitialized; + // gSeedPage is used as a sentinel to indicate that there is no page + // in the active page list. We can use nullptr, but in that case we need + // to add a null-check branch to the hot allocation path. We want to avoid + // that. + static PartitionPage gSeedPage; + static PartitionBucket gPagedBucket; + // gOomHandlingFunction is invoked when ParitionAlloc hits OutOfMemory. + static void (*gOomHandlingFunction)(); +}; + +// Never instantiate a PartitionRoot directly, instead use PartitionAlloc. +struct PartitionRoot : public PartitionRootBase { + // The PartitionAlloc templated class ensures the following is correct. + ALWAYS_INLINE PartitionBucket* buckets() { + return reinterpret_cast(this + 1); + } + ALWAYS_INLINE const PartitionBucket* buckets() const { + return reinterpret_cast(this + 1); + } +}; + +// Never instantiate a PartitionRootGeneric directly, instead use +// PartitionAllocatorGeneric. +struct PartitionRootGeneric : public PartitionRootBase { + subtle::SpinLock lock; + // Some pre-computed constants. + size_t order_index_shifts[kBitsPerSizeT + 1]; + size_t order_sub_index_masks[kBitsPerSizeT + 1]; + // The bucket lookup table lets us map a size_t to a bucket quickly. + // The trailing +1 caters for the overflow case for very large allocation + // sizes. It is one flat array instead of a 2D array because in the 2D + // world, we'd need to index array[blah][max+1] which risks undefined + // behavior. + PartitionBucket* + bucket_lookups[((kBitsPerSizeT + 1) * kGenericNumBucketsPerOrder) + 1]; + PartitionBucket buckets[kGenericNumBuckets]; +}; + +// Flags for PartitionAllocGenericFlags. +enum PartitionAllocFlags { + PartitionAllocReturnNull = 1 << 0, +}; + +// Struct used to retrieve total memory usage of a partition. Used by +// PartitionStatsDumper implementation. +struct PartitionMemoryStats { + size_t total_mmapped_bytes; // Total bytes mmaped from the system. + size_t total_committed_bytes; // Total size of commmitted pages. + size_t total_resident_bytes; // Total bytes provisioned by the partition. + size_t total_active_bytes; // Total active bytes in the partition. + size_t total_decommittable_bytes; // Total bytes that could be decommitted. + size_t total_discardable_bytes; // Total bytes that could be discarded. +}; + +// Struct used to retrieve memory statistics about a partition bucket. Used by +// PartitionStatsDumper implementation. +struct PartitionBucketMemoryStats { + bool is_valid; // Used to check if the stats is valid. + bool is_direct_map; // True if this is a direct mapping; size will not be + // unique. + uint32_t bucket_slot_size; // The size of the slot in bytes. + uint32_t allocated_page_size; // Total size the partition page allocated from + // the system. + uint32_t active_bytes; // Total active bytes used in the bucket. + uint32_t resident_bytes; // Total bytes provisioned in the bucket. + uint32_t decommittable_bytes; // Total bytes that could be decommitted. + uint32_t discardable_bytes; // Total bytes that could be discarded. + uint32_t num_full_pages; // Number of pages with all slots allocated. + uint32_t num_active_pages; // Number of pages that have at least one + // provisioned slot. + uint32_t num_empty_pages; // Number of pages that are empty + // but not decommitted. + uint32_t num_decommitted_pages; // Number of pages that are empty + // and decommitted. +}; + +// Interface that is passed to PartitionDumpStats and +// PartitionDumpStatsGeneric for using the memory statistics. +class BASE_EXPORT PartitionStatsDumper { + public: + // Called to dump total memory used by partition, once per partition. + virtual void PartitionDumpTotals(const char* partition_name, + const PartitionMemoryStats*) = 0; + + // Called to dump stats about buckets, for each bucket. + virtual void PartitionsDumpBucketStats(const char* partition_name, + const PartitionBucketMemoryStats*) = 0; +}; + +BASE_EXPORT void PartitionAllocGlobalInit(void (*oom_handling_function)()); +BASE_EXPORT void PartitionAllocInit(PartitionRoot*, + size_t num_buckets, + size_t max_allocation); +BASE_EXPORT void PartitionAllocGenericInit(PartitionRootGeneric*); + +enum PartitionPurgeFlags { + // Decommitting the ring list of empty pages is reasonably fast. + PartitionPurgeDecommitEmptyPages = 1 << 0, + // Discarding unused system pages is slower, because it involves walking all + // freelists in all active partition pages of all buckets >= system page + // size. It often frees a similar amount of memory to decommitting the empty + // pages, though. + PartitionPurgeDiscardUnusedSystemPages = 1 << 1, +}; + +BASE_EXPORT void PartitionPurgeMemory(PartitionRoot*, int); +BASE_EXPORT void PartitionPurgeMemoryGeneric(PartitionRootGeneric*, int); + +BASE_EXPORT NOINLINE void* PartitionAllocSlowPath(PartitionRootBase*, + int, + size_t, + PartitionBucket*); +BASE_EXPORT NOINLINE void PartitionFreeSlowPath(PartitionPage*); +BASE_EXPORT NOINLINE void* PartitionReallocGeneric(PartitionRootGeneric*, + void*, + size_t, + const char* type_name); + +BASE_EXPORT void PartitionDumpStats(PartitionRoot*, + const char* partition_name, + bool is_light_dump, + PartitionStatsDumper*); +BASE_EXPORT void PartitionDumpStatsGeneric(PartitionRootGeneric*, + const char* partition_name, + bool is_light_dump, + PartitionStatsDumper*); + +class BASE_EXPORT PartitionAllocHooks { + public: + typedef void AllocationHook(void* address, size_t, const char* type_name); + typedef void FreeHook(void* address); + + static void SetAllocationHook(AllocationHook* hook) { + allocation_hook_ = hook; + } + static void SetFreeHook(FreeHook* hook) { free_hook_ = hook; } + + static void AllocationHookIfEnabled(void* address, + size_t size, + const char* type_name) { + AllocationHook* hook = allocation_hook_; + if (UNLIKELY(hook != nullptr)) + hook(address, size, type_name); + } + + static void FreeHookIfEnabled(void* address) { + FreeHook* hook = free_hook_; + if (UNLIKELY(hook != nullptr)) + hook(address); + } + + static void ReallocHookIfEnabled(void* old_address, + void* new_address, + size_t size, + const char* type_name) { + // Report a reallocation as a free followed by an allocation. + AllocationHook* allocation_hook = allocation_hook_; + FreeHook* free_hook = free_hook_; + if (UNLIKELY(allocation_hook && free_hook)) { + free_hook(old_address); + allocation_hook(new_address, size, type_name); + } + } + + private: + // Pointers to hook functions that PartitionAlloc will call on allocation and + // free if the pointers are non-null. + static AllocationHook* allocation_hook_; + static FreeHook* free_hook_; +}; + +ALWAYS_INLINE PartitionFreelistEntry* PartitionFreelistMask( + PartitionFreelistEntry* ptr) { +// We use bswap on little endian as a fast mask for two reasons: +// 1) If an object is freed and its vtable used where the attacker doesn't +// get the chance to run allocations between the free and use, the vtable +// dereference is likely to fault. +// 2) If the attacker has a linear buffer overflow and elects to try and +// corrupt a freelist pointer, partial pointer overwrite attacks are +// thwarted. +// For big endian, similar guarantees are arrived at with a negation. +#if defined(ARCH_CPU_BIG_ENDIAN) + uintptr_t masked = ~reinterpret_cast(ptr); +#else + uintptr_t masked = ByteSwapUintPtrT(reinterpret_cast(ptr)); +#endif + return reinterpret_cast(masked); +} + +ALWAYS_INLINE size_t PartitionCookieSizeAdjustAdd(size_t size) { +#if DCHECK_IS_ON() + // Add space for cookies, checking for integer overflow. TODO(palmer): + // Investigate the performance and code size implications of using + // CheckedNumeric throughout PA. + DCHECK(size + (2 * kCookieSize) > size); + size += 2 * kCookieSize; +#endif + return size; +} + +ALWAYS_INLINE size_t PartitionCookieSizeAdjustSubtract(size_t size) { +#if DCHECK_IS_ON() + // Remove space for cookies. + DCHECK(size >= 2 * kCookieSize); + size -= 2 * kCookieSize; +#endif + return size; +} + +ALWAYS_INLINE void* PartitionCookieFreePointerAdjust(void* ptr) { +#if DCHECK_IS_ON() + // The value given to the application is actually just after the cookie. + ptr = static_cast(ptr) - kCookieSize; +#endif + return ptr; +} + +ALWAYS_INLINE void PartitionCookieWriteValue(void* ptr) { +#if DCHECK_IS_ON() + auto* cookie_ptr = reinterpret_cast(ptr); + for (size_t i = 0; i < kCookieSize; ++i, ++cookie_ptr) + *cookie_ptr = kCookieValue[i]; +#endif +} + +ALWAYS_INLINE void PartitionCookieCheckValue(void* ptr) { +#if DCHECK_IS_ON() + auto* cookie_ptr = reinterpret_cast(ptr); + for (size_t i = 0; i < kCookieSize; ++i, ++cookie_ptr) + DCHECK(*cookie_ptr == kCookieValue[i]); +#endif +} + +ALWAYS_INLINE char* PartitionSuperPageToMetadataArea(char* ptr) { + auto pointer_as_uint = reinterpret_cast(ptr); + DCHECK(!(pointer_as_uint & kSuperPageOffsetMask)); + // The metadata area is exactly one system page (the guard page) into the + // super page. + return reinterpret_cast(pointer_as_uint + kSystemPageSize); +} + +ALWAYS_INLINE PartitionPage* PartitionPointerToPageNoAlignmentCheck(void* ptr) { + auto pointer_as_uint = reinterpret_cast(ptr); + auto* super_page_ptr = + reinterpret_cast(pointer_as_uint & kSuperPageBaseMask); + uintptr_t partition_page_index = + (pointer_as_uint & kSuperPageOffsetMask) >> kPartitionPageShift; + // Index 0 is invalid because it is the metadata and guard area and + // the last index is invalid because it is a guard page. + DCHECK(partition_page_index); + DCHECK(partition_page_index < kNumPartitionPagesPerSuperPage - 1); + auto* page = reinterpret_cast( + PartitionSuperPageToMetadataArea(super_page_ptr) + + (partition_page_index << kPageMetadataShift)); + // Partition pages in the same slot span can share the same page object. + // Adjust for that. + size_t delta = page->page_offset << kPageMetadataShift; + page = + reinterpret_cast(reinterpret_cast(page) - delta); + return page; +} + +ALWAYS_INLINE void* PartitionPageToPointer(const PartitionPage* page) { + auto pointer_as_uint = reinterpret_cast(page); + uintptr_t super_page_offset = (pointer_as_uint & kSuperPageOffsetMask); + DCHECK(super_page_offset > kSystemPageSize); + DCHECK(super_page_offset < kSystemPageSize + (kNumPartitionPagesPerSuperPage * + kPageMetadataSize)); + uintptr_t partition_page_index = + (super_page_offset - kSystemPageSize) >> kPageMetadataShift; + // Index 0 is invalid because it is the metadata area and the last index is + // invalid because it is a guard page. + DCHECK(partition_page_index); + DCHECK(partition_page_index < kNumPartitionPagesPerSuperPage - 1); + uintptr_t super_page_base = (pointer_as_uint & kSuperPageBaseMask); + auto* ret = reinterpret_cast( + super_page_base + (partition_page_index << kPartitionPageShift)); + return ret; +} + +ALWAYS_INLINE PartitionPage* PartitionPointerToPage(void* ptr) { + PartitionPage* page = PartitionPointerToPageNoAlignmentCheck(ptr); + // Checks that the pointer is a multiple of bucket size. + DCHECK(!((reinterpret_cast(ptr) - + reinterpret_cast(PartitionPageToPointer(page))) % + page->bucket->slot_size)); + return page; +} + +ALWAYS_INLINE bool PartitionBucketIsDirectMapped( + const PartitionBucket* bucket) { + return !bucket->num_system_pages_per_slot_span; +} + +ALWAYS_INLINE size_t PartitionBucketBytes(const PartitionBucket* bucket) { + return bucket->num_system_pages_per_slot_span * kSystemPageSize; +} + +ALWAYS_INLINE uint16_t PartitionBucketSlots(const PartitionBucket* bucket) { + return static_cast(PartitionBucketBytes(bucket) / + bucket->slot_size); +} + +ALWAYS_INLINE size_t* PartitionPageGetRawSizePtr(PartitionPage* page) { + // For single-slot buckets which span more than one partition page, we + // have some spare metadata space to store the raw allocation size. We + // can use this to report better statistics. + PartitionBucket* bucket = page->bucket; + if (bucket->slot_size <= kMaxSystemPagesPerSlotSpan * kSystemPageSize) + return nullptr; + + DCHECK((bucket->slot_size % kSystemPageSize) == 0); + DCHECK(PartitionBucketIsDirectMapped(bucket) || + PartitionBucketSlots(bucket) == 1); + page++; + return reinterpret_cast(&page->freelist_head); +} + +ALWAYS_INLINE size_t PartitionPageGetRawSize(PartitionPage* page) { + size_t* raw_size_ptr = PartitionPageGetRawSizePtr(page); + if (UNLIKELY(raw_size_ptr != nullptr)) + return *raw_size_ptr; + return 0; +} + +ALWAYS_INLINE PartitionRootBase* PartitionPageToRoot(PartitionPage* page) { + auto* extent_entry = reinterpret_cast( + reinterpret_cast(page) & kSystemPageBaseMask); + return extent_entry->root; +} + +ALWAYS_INLINE bool PartitionPointerIsValid(void* ptr) { + PartitionPage* page = PartitionPointerToPage(ptr); + PartitionRootBase* root = PartitionPageToRoot(page); + return root->inverted_self == ~reinterpret_cast(root); +} + +ALWAYS_INLINE void* PartitionBucketAlloc(PartitionRootBase* root, + int flags, + size_t size, + PartitionBucket* bucket) { + PartitionPage* page = bucket->active_pages_head; + // Check that this page is neither full nor freed. + DCHECK(page->num_allocated_slots >= 0); + void* ret = page->freelist_head; + if (LIKELY(ret)) { + // If these asserts fire, you probably corrupted memory. + DCHECK(PartitionPointerIsValid(ret)); + // All large allocations must go through the slow path to correctly + // update the size metadata. + DCHECK(PartitionPageGetRawSize(page) == 0); + PartitionFreelistEntry* new_head = + PartitionFreelistMask(static_cast(ret)->next); + page->freelist_head = new_head; + page->num_allocated_slots++; + } else { + ret = PartitionAllocSlowPath(root, flags, size, bucket); + DCHECK(!ret || PartitionPointerIsValid(ret)); + } +#if DCHECK_IS_ON() + if (!ret) + return nullptr; + // Fill the uninitialized pattern, and write the cookies. + page = PartitionPointerToPage(ret); + size_t slot_size = page->bucket->slot_size; + size_t raw_size = PartitionPageGetRawSize(page); + if (raw_size) { + DCHECK(raw_size == size); + slot_size = raw_size; + } + size_t no_cookie_size = PartitionCookieSizeAdjustSubtract(slot_size); + auto* char_ret = static_cast(ret); + // The value given to the application is actually just after the cookie. + ret = char_ret + kCookieSize; + memset(ret, kUninitializedByte, no_cookie_size); + PartitionCookieWriteValue(char_ret); + PartitionCookieWriteValue(char_ret + kCookieSize + no_cookie_size); +#endif + return ret; +} + +ALWAYS_INLINE void* PartitionAlloc(PartitionRoot* root, + size_t size, + const char* type_name) { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + void* result = malloc(size); + CHECK(result); + return result; +#else + size_t requested_size = size; + size = PartitionCookieSizeAdjustAdd(size); + DCHECK(root->initialized); + size_t index = size >> kBucketShift; + DCHECK(index < root->num_buckets); + DCHECK(size == index << kBucketShift); + PartitionBucket* bucket = &root->buckets()[index]; + void* result = PartitionBucketAlloc(root, 0, size, bucket); + PartitionAllocHooks::AllocationHookIfEnabled(result, requested_size, + type_name); + return result; +#endif // defined(MEMORY_TOOL_REPLACES_ALLOCATOR) +} + +ALWAYS_INLINE void PartitionFreeWithPage(void* ptr, PartitionPage* page) { +// If these asserts fire, you probably corrupted memory. +#if DCHECK_IS_ON() + size_t slot_size = page->bucket->slot_size; + size_t raw_size = PartitionPageGetRawSize(page); + if (raw_size) + slot_size = raw_size; + PartitionCookieCheckValue(ptr); + PartitionCookieCheckValue(reinterpret_cast(ptr) + slot_size - + kCookieSize); + memset(ptr, kFreedByte, slot_size); +#endif + DCHECK(page->num_allocated_slots); + PartitionFreelistEntry* freelist_head = page->freelist_head; + DCHECK(!freelist_head || PartitionPointerIsValid(freelist_head)); + CHECK(ptr != freelist_head); // Catches an immediate double free. + // Look for double free one level deeper in debug. + DCHECK(!freelist_head || ptr != PartitionFreelistMask(freelist_head->next)); + auto* entry = static_cast(ptr); + entry->next = PartitionFreelistMask(freelist_head); + page->freelist_head = entry; + --page->num_allocated_slots; + if (UNLIKELY(page->num_allocated_slots <= 0)) { + PartitionFreeSlowPath(page); + } else { + // All single-slot allocations must go through the slow path to + // correctly update the size metadata. + DCHECK(PartitionPageGetRawSize(page) == 0); + } +} + +ALWAYS_INLINE void PartitionFree(void* ptr) { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + free(ptr); +#else + PartitionAllocHooks::FreeHookIfEnabled(ptr); + ptr = PartitionCookieFreePointerAdjust(ptr); + DCHECK(PartitionPointerIsValid(ptr)); + PartitionPage* page = PartitionPointerToPage(ptr); + PartitionFreeWithPage(ptr, page); +#endif +} + +ALWAYS_INLINE PartitionBucket* PartitionGenericSizeToBucket( + PartitionRootGeneric* root, + size_t size) { + size_t order = kBitsPerSizeT - bits::CountLeadingZeroBitsSizeT(size); + // The order index is simply the next few bits after the most significant bit. + size_t order_index = (size >> root->order_index_shifts[order]) & + (kGenericNumBucketsPerOrder - 1); + // And if the remaining bits are non-zero we must bump the bucket up. + size_t sub_order_index = size & root->order_sub_index_masks[order]; + PartitionBucket* bucket = + root->bucket_lookups[(order << kGenericNumBucketsPerOrderBits) + + order_index + !!sub_order_index]; + DCHECK(!bucket->slot_size || bucket->slot_size >= size); + DCHECK(!(bucket->slot_size % kGenericSmallestBucket)); + return bucket; +} + +ALWAYS_INLINE void* PartitionAllocGenericFlags(PartitionRootGeneric* root, + int flags, + size_t size, + const char* type_name) { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + void* result = malloc(size); + CHECK(result || flags & PartitionAllocReturnNull); + return result; +#else + DCHECK(root->initialized); + size_t requested_size = size; + size = PartitionCookieSizeAdjustAdd(size); + PartitionBucket* bucket = PartitionGenericSizeToBucket(root, size); + void* ret = nullptr; + { + subtle::SpinLock::Guard guard(root->lock); + ret = PartitionBucketAlloc(root, flags, size, bucket); + } + PartitionAllocHooks::AllocationHookIfEnabled(ret, requested_size, type_name); + return ret; +#endif +} + +ALWAYS_INLINE void* PartitionAllocGeneric(PartitionRootGeneric* root, + size_t size, + const char* type_name) { + return PartitionAllocGenericFlags(root, 0, size, type_name); +} + +ALWAYS_INLINE void PartitionFreeGeneric(PartitionRootGeneric* root, void* ptr) { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + free(ptr); +#else + DCHECK(root->initialized); + + if (UNLIKELY(!ptr)) + return; + + PartitionAllocHooks::FreeHookIfEnabled(ptr); + ptr = PartitionCookieFreePointerAdjust(ptr); + DCHECK(PartitionPointerIsValid(ptr)); + PartitionPage* page = PartitionPointerToPage(ptr); + { + subtle::SpinLock::Guard guard(root->lock); + PartitionFreeWithPage(ptr, page); + } +#endif +} + +ALWAYS_INLINE size_t PartitionDirectMapSize(size_t size) { + // Caller must check that the size is not above the kGenericMaxDirectMapped + // limit before calling. This also guards against integer overflow in the + // calculation here. + DCHECK(size <= kGenericMaxDirectMapped); + return (size + kSystemPageOffsetMask) & kSystemPageBaseMask; +} + +ALWAYS_INLINE size_t PartitionAllocActualSize(PartitionRootGeneric* root, + size_t size) { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + return size; +#else + DCHECK(root->initialized); + size = PartitionCookieSizeAdjustAdd(size); + PartitionBucket* bucket = PartitionGenericSizeToBucket(root, size); + if (LIKELY(!PartitionBucketIsDirectMapped(bucket))) { + size = bucket->slot_size; + } else if (size > kGenericMaxDirectMapped) { + // Too large to allocate => return the size unchanged. + } else { + DCHECK(bucket == &PartitionRootBase::gPagedBucket); + size = PartitionDirectMapSize(size); + } + return PartitionCookieSizeAdjustSubtract(size); +#endif +} + +ALWAYS_INLINE bool PartitionAllocSupportsGetSize() { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + return false; +#else + return true; +#endif +} + +ALWAYS_INLINE size_t PartitionAllocGetSize(void* ptr) { + // No need to lock here. Only |ptr| being freed by another thread could + // cause trouble, and the caller is responsible for that not happening. + DCHECK(PartitionAllocSupportsGetSize()); + ptr = PartitionCookieFreePointerAdjust(ptr); + DCHECK(PartitionPointerIsValid(ptr)); + PartitionPage* page = PartitionPointerToPage(ptr); + size_t size = page->bucket->slot_size; + return PartitionCookieSizeAdjustSubtract(size); +} + +// N (or more accurately, N - sizeof(void*)) represents the largest size in +// bytes that will be handled by a SizeSpecificPartitionAllocator. +// Attempts to partitionAlloc() more than this amount will fail. +template +class SizeSpecificPartitionAllocator { + public: + static const size_t kMaxAllocation = N - kAllocationGranularity; + static const size_t kNumBuckets = N / kAllocationGranularity; + void init() { + PartitionAllocInit(&partition_root_, kNumBuckets, kMaxAllocation); + } + ALWAYS_INLINE PartitionRoot* root() { return &partition_root_; } + + private: + PartitionRoot partition_root_; + PartitionBucket actual_buckets_[kNumBuckets]; +}; + +class PartitionAllocatorGeneric { + public: + void init() { PartitionAllocGenericInit(&partition_root_); } + ALWAYS_INLINE PartitionRootGeneric* root() { return &partition_root_; } + + private: + PartitionRootGeneric partition_root_; +}; + +} // namespace base +} // namespace pdfium + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H diff --git a/third_party/base/allocator/partition_allocator/spin_lock.cc b/third_party/base/allocator/partition_allocator/spin_lock.cc new file mode 100644 index 0000000000000000000000000000000000000000..8d7151a8b7d416ce8bfd63e260a6d91d6d9effc4 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/spin_lock.cc @@ -0,0 +1,84 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/base/allocator/partition_allocator/spin_lock.h" + +#if defined(OS_WIN) +#include +#elif defined(OS_POSIX) +#include +#endif + +// The YIELD_PROCESSOR macro wraps an architecture specific-instruction that +// informs the processor we're in a busy wait, so it can handle the branch more +// intelligently and e.g. reduce power to our core or give more resources to the +// other hyper-thread on this core. See the following for context: +// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops +// +// The YIELD_THREAD macro tells the OS to relinquish our quantum. This is +// basically a worst-case fallback, and if you're hitting it with any frequency +// you really should be using a proper lock (such as |base::Lock|)rather than +// these spinlocks. +#if defined(OS_WIN) +#define YIELD_PROCESSOR YieldProcessor() +#define YIELD_THREAD SwitchToThread() +#elif defined(COMPILER_GCC) || defined(__clang__) +#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_X86) +#define YIELD_PROCESSOR __asm__ __volatile__("pause") +#elif (defined(ARCH_CPU_ARMEL) && __ARM_ARCH >= 6) || defined(ARCH_CPU_ARM64) +#define YIELD_PROCESSOR __asm__ __volatile__("yield") +#elif defined(ARCH_CPU_MIPSEL) +// The MIPS32 docs state that the PAUSE instruction is a no-op on older +// architectures (first added in MIPS32r2). To avoid assembler errors when +// targeting pre-r2, we must encode the instruction manually. +#define YIELD_PROCESSOR __asm__ __volatile__(".word 0x00000140") +#elif defined(ARCH_CPU_MIPS64EL) && __mips_isa_rev >= 2 +// Don't bother doing using .word here since r2 is the lowest supported mips64 +// that Chromium supports. +#define YIELD_PROCESSOR __asm__ __volatile__("pause") +#endif +#endif + +#ifndef YIELD_PROCESSOR +#warning "Processor yield not supported on this architecture." +#define YIELD_PROCESSOR ((void)0) +#endif + +#ifndef YIELD_THREAD +#if defined(OS_POSIX) +#define YIELD_THREAD sched_yield() +#else +#warning "Thread yield not supported on this OS." +#define YIELD_THREAD ((void)0) +#endif +#endif + +namespace pdfium { +namespace base { +namespace subtle { + +void SpinLock::LockSlow() { + // The value of |kYieldProcessorTries| is cargo culted from TCMalloc, Windows + // critical section defaults, and various other recommendations. + // TODO(jschuh): Further tuning may be warranted. + static const int kYieldProcessorTries = 1000; + do { + do { + for (int count = 0; count < kYieldProcessorTries; ++count) { + // Let the processor know we're spinning. + YIELD_PROCESSOR; + if (!lock_.load(std::memory_order_relaxed) && + LIKELY(!lock_.exchange(true, std::memory_order_acquire))) + return; + } + + // Give the OS a chance to schedule something on this core. + YIELD_THREAD; + } while (lock_.load(std::memory_order_relaxed)); + } while (UNLIKELY(lock_.exchange(true, std::memory_order_acquire))); +} + +} // namespace subtle +} // namespace base +} // namespace pdfium diff --git a/third_party/base/allocator/partition_allocator/spin_lock.h b/third_party/base/allocator/partition_allocator/spin_lock.h new file mode 100644 index 0000000000000000000000000000000000000000..7a42a29c4ed0d1fa215325289fb998af64042c23 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/spin_lock.h @@ -0,0 +1,54 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SPIN_LOCK_H +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SPIN_LOCK_H + +#include +#include +#include + +#include "third_party/base/base_export.h" +#include "third_party/base/compiler_specific.h" + +// Spinlock is a simple spinlock class based on the standard CPU primitive of +// atomic increment and decrement of an int at a given memory address. These are +// intended only for very short duration locks and assume a system with multiple +// cores. For any potentially longer wait you should use a real lock, such as +// |base::Lock|. +// +// |SpinLock|s MUST be globals. Using them as (e.g.) struct/class members will +// result in an uninitialized lock, which is dangerously incorrect. + +namespace pdfium { +namespace base { +namespace subtle { + +class SpinLock { + public: + using Guard = std::lock_guard; + + ALWAYS_INLINE void lock() { + static_assert(sizeof(lock_) == sizeof(int), + "int and lock_ are different sizes"); + if (LIKELY(!lock_.exchange(true, std::memory_order_acquire))) + return; + LockSlow(); + } + + ALWAYS_INLINE void unlock() { lock_.store(false, std::memory_order_release); } + + private: + // This is called if the initial attempt to acquire the lock fails. It's + // slower, but has a much better scheduling and power consumption behavior. + BASE_EXPORT void LockSlow(); + + std::atomic_int lock_; +}; + +} // namespace subtle +} // namespace base +} // namespace pdfium + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SPIN_LOCK_H diff --git a/third_party/base/base_export.h b/third_party/base/base_export.h new file mode 100644 index 0000000000000000000000000000000000000000..a0d6d9bb72e1c5b07e3124675f5241849a68dd47 --- /dev/null +++ b/third_party/base/base_export.h @@ -0,0 +1,3 @@ +#ifndef BASE_EXPORT +#define BASE_EXPORT +#endif diff --git a/third_party/base/bits.h b/third_party/base/bits.h new file mode 100644 index 0000000000000000000000000000000000000000..220be4b73c4d14b9a98ea60cf4ca37fa97fcc4c5 --- /dev/null +++ b/third_party/base/bits.h @@ -0,0 +1,114 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file defines some bit utilities. + +#ifndef BASE_BITS_H_ +#define BASE_BITS_H_ + +#include +#include + +#include "third_party/base/compiler_specific.h" +#include "third_party/base/logging.h" + +#if defined(COMPILER_MSVC) +#include +#endif + +namespace pdfium { +namespace base { +namespace bits { + +// Returns the integer i such as 2^i <= n < 2^(i+1) +inline int Log2Floor(uint32_t n) { + if (n == 0) + return -1; + int log = 0; + uint32_t value = n; + for (int i = 4; i >= 0; --i) { + int shift = (1 << i); + uint32_t x = value >> shift; + if (x != 0) { + value = x; + log += shift; + } + } + DCHECK_EQ(value, 1u); + return log; +} + +// Returns the integer i such as 2^(i-1) < n <= 2^i +inline int Log2Ceiling(uint32_t n) { + if (n == 0) { + return -1; + } else { + // Log2Floor returns -1 for 0, so the following works correctly for n=1. + return 1 + Log2Floor(n - 1); + } +} + +// Round up |size| to a multiple of alignment, which must be a power of two. +inline size_t Align(size_t size, size_t alignment) { + DCHECK_EQ(alignment & (alignment - 1), 0u); + return (size + alignment - 1) & ~(alignment - 1); +} + +// These functions count the number of leading zeros in a binary value, starting +// with the most significant bit. C does not have an operator to do this, but +// fortunately the various compilers have built-ins that map to fast underlying +// processor instructions. +#if defined(COMPILER_MSVC) + +ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) { + unsigned long index; + return LIKELY(_BitScanReverse(&index, x)) ? (31 - index) : 32; +} + +#if defined(ARCH_CPU_64_BITS) + +// MSVC only supplies _BitScanForward64 when building for a 64-bit target. +ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) { + unsigned long index; + return LIKELY(_BitScanReverse64(&index, x)) ? (63 - index) : 64; +} + +#endif + +#elif defined(COMPILER_GCC) + +// This is very annoying. __builtin_clz has undefined behaviour for an input of +// 0, even though there's clearly a return value that makes sense, and even +// though some processor clz instructions have defined behaviour for 0. We could +// drop to raw __asm__ to do better, but we'll avoid doing that unless we see +// proof that we need to. +ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) { + return LIKELY(x) ? __builtin_clz(x) : 32; +} + +ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) { + return LIKELY(x) ? __builtin_clzll(x) : 64; +} + +#endif + +#if defined(ARCH_CPU_64_BITS) + +ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) { + return CountLeadingZeroBits64(x); +} + +#else + +ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) { + return CountLeadingZeroBits32(x); +} + +#endif + +} // namespace bits +} // namespace base +} // namespace pdfium + +#endif // BASE_BITS_H_ diff --git a/third_party/base/compiler_specific.h b/third_party/base/compiler_specific.h new file mode 100644 index 0000000000000000000000000000000000000000..3dbd1abb33d4a01a0529ae249a029d6f775b8c68 --- /dev/null +++ b/third_party/base/compiler_specific.h @@ -0,0 +1,233 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_COMPILER_SPECIFIC_H_ +#define BASE_COMPILER_SPECIFIC_H_ + +#include "build/build_config.h" + +#if defined(COMPILER_MSVC) + +// For _Printf_format_string_. +#include + +// Macros for suppressing and disabling warnings on MSVC. +// +// Warning numbers are enumerated at: +// http://msdn.microsoft.com/en-us/library/8x5x43k7(VS.80).aspx +// +// The warning pragma: +// http://msdn.microsoft.com/en-us/library/2c8f766e(VS.80).aspx +// +// Using __pragma instead of #pragma inside macros: +// http://msdn.microsoft.com/en-us/library/d9x1s805.aspx + +// MSVC_SUPPRESS_WARNING disables warning |n| for the remainder of the line and +// for the next line of the source file. +#define MSVC_SUPPRESS_WARNING(n) __pragma(warning(suppress : n)) + +// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled. +// The warning remains disabled until popped by MSVC_POP_WARNING. +#define MSVC_PUSH_DISABLE_WARNING(n) \ + __pragma(warning(push)) __pragma(warning(disable : n)) + +// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level +// remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all +// warnings. +#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n)) + +// Pop effects of innermost MSVC_PUSH_* macro. +#define MSVC_POP_WARNING() __pragma(warning(pop)) + +#define MSVC_DISABLE_OPTIMIZE() __pragma(optimize("", off)) +#define MSVC_ENABLE_OPTIMIZE() __pragma(optimize("", on)) + +// Allows exporting a class that inherits from a non-exported base class. +// This uses suppress instead of push/pop because the delimiter after the +// declaration (either "," or "{") has to be placed before the pop macro. +// +// Example usage: +// class EXPORT_API Foo : NON_EXPORTED_BASE(public Bar) { +// +// MSVC Compiler warning C4275: +// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'. +// Note that this is intended to be used only when no access to the base class' +// static data is done through derived classes or inline methods. For more info, +// see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx +#define NON_EXPORTED_BASE(code) \ + MSVC_SUPPRESS_WARNING(4275) \ + code + +#else // Not MSVC + +#define _Printf_format_string_ +#define MSVC_SUPPRESS_WARNING(n) +#define MSVC_PUSH_DISABLE_WARNING(n) +#define MSVC_PUSH_WARNING_LEVEL(n) +#define MSVC_POP_WARNING() +#define MSVC_DISABLE_OPTIMIZE() +#define MSVC_ENABLE_OPTIMIZE() +#define NON_EXPORTED_BASE(code) code + +#endif // COMPILER_MSVC + +// Annotate a variable indicating it's ok if the variable is not used. +// (Typically used to silence a compiler warning when the assignment +// is important for some other reason.) +// Use like: +// int x = ...; +// ALLOW_UNUSED_LOCAL(x); +#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0 + +// Annotate a typedef or function indicating it's ok if it's not used. +// Use like: +// typedef Foo Bar ALLOW_UNUSED_TYPE; +#if defined(COMPILER_GCC) || defined(__clang__) +#define ALLOW_UNUSED_TYPE __attribute__((unused)) +#else +#define ALLOW_UNUSED_TYPE +#endif + +// Annotate a function indicating it should not be inlined. +// Use like: +// NOINLINE void DoStuff() { ... } +#if defined(COMPILER_GCC) +#define NOINLINE __attribute__((noinline)) +#elif defined(COMPILER_MSVC) +#define NOINLINE __declspec(noinline) +#else +#define NOINLINE +#endif + +#if COMPILER_GCC && defined(NDEBUG) +#define ALWAYS_INLINE inline __attribute__((__always_inline__)) +#elif COMPILER_MSVC && defined(NDEBUG) +#define ALWAYS_INLINE __forceinline +#else +#define ALWAYS_INLINE inline +#endif + +// Specify memory alignment for structs, classes, etc. +// Use like: +// class ALIGNAS(16) MyClass { ... } +// ALIGNAS(16) int array[4]; +#if defined(COMPILER_MSVC) +#define ALIGNAS(byte_alignment) __declspec(align(byte_alignment)) +#elif defined(COMPILER_GCC) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#endif + +// Return the byte alignment of the given type (available at compile time). +// Use like: +// ALIGNOF(int32_t) // this would be 4 +#if defined(COMPILER_MSVC) +#define ALIGNOF(type) __alignof(type) +#elif defined(COMPILER_GCC) +#define ALIGNOF(type) __alignof__(type) +#endif + +// Annotate a function indicating the caller must examine the return value. +// Use like: +// int foo() WARN_UNUSED_RESULT; +// To explicitly ignore a result, see |ignore_result()| in base/macros.h. +#undef WARN_UNUSED_RESULT +#if defined(COMPILER_GCC) || defined(__clang__) +#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define WARN_UNUSED_RESULT +#endif + +// Tell the compiler a function is using a printf-style format string. +// |format_param| is the one-based index of the format string parameter; +// |dots_param| is the one-based index of the "..." parameter. +// For v*printf functions (which take a va_list), pass 0 for dots_param. +// (This is undocumented but matches what the system C headers do.) +#if defined(COMPILER_GCC) || defined(__clang__) +#define PRINTF_FORMAT(format_param, dots_param) \ + __attribute__((format(printf, format_param, dots_param))) +#else +#define PRINTF_FORMAT(format_param, dots_param) +#endif + +// WPRINTF_FORMAT is the same, but for wide format strings. +// This doesn't appear to yet be implemented in any compiler. +// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 . +#define WPRINTF_FORMAT(format_param, dots_param) +// If available, it would look like: +// __attribute__((format(wprintf, format_param, dots_param))) + +// Sanitizers annotations. +#if defined(__has_attribute) +#if __has_attribute(no_sanitize) +#define NO_SANITIZE(what) __attribute__((no_sanitize(what))) +#endif +#endif +#if !defined(NO_SANITIZE) +#define NO_SANITIZE(what) +#endif + +// MemorySanitizer annotations. +#if defined(MEMORY_SANITIZER) && !defined(OS_NACL) +#include + +// Mark a memory region fully initialized. +// Use this to annotate code that deliberately reads uninitialized data, for +// example a GC scavenging root set pointers from the stack. +#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size) + +// Check a memory region for initializedness, as if it was being used here. +// If any bits are uninitialized, crash with an MSan report. +// Use this to sanitize data which MSan won't be able to track, e.g. before +// passing data to another process via shared memory. +#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \ + __msan_check_mem_is_initialized(p, size) +#else // MEMORY_SANITIZER +#define MSAN_UNPOISON(p, size) +#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) +#endif // MEMORY_SANITIZER + +// DISABLE_CFI_PERF -- Disable Control Flow Integrity for perf reasons. +#if !defined(DISABLE_CFI_PERF) +#if defined(__clang__) && defined(OFFICIAL_BUILD) +#define DISABLE_CFI_PERF __attribute__((no_sanitize("cfi"))) +#else +#define DISABLE_CFI_PERF +#endif +#endif + +// Macro useful for writing cross-platform function pointers. +#if !defined(CDECL) +#if defined(OS_WIN) +#define CDECL __cdecl +#else // defined(OS_WIN) +#define CDECL +#endif // defined(OS_WIN) +#endif // !defined(CDECL) + +// Macro for hinting that an expression is likely to be false. +#if !defined(UNLIKELY) +#if defined(COMPILER_GCC) +#define UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define UNLIKELY(x) (x) +#endif // defined(COMPILER_GCC) +#endif // !defined(UNLIKELY) + +#if !defined(LIKELY) +#if defined(COMPILER_GCC) +#define LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define LIKELY(x) (x) +#endif // defined(COMPILER_GCC) +#endif // !defined(LIKELY) + +// Compiler feature-detection. +// clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension +#if defined(__has_feature) +#define HAS_FEATURE(FEATURE) __has_feature(FEATURE) +#else +#define HAS_FEATURE(FEATURE) 0 +#endif + +#endif // BASE_COMPILER_SPECIFIC_H_ diff --git a/third_party/base/logging.h b/third_party/base/logging.h index bf4faea57e08fd9ca75e1b7933327e8cee5612c1..38b0dd9a17b296459277c466374a4a9c64e787b8 100644 --- a/third_party/base/logging.h +++ b/third_party/base/logging.h @@ -21,6 +21,19 @@ NULL_DEREF_IF_POSSIBLE \ } +// TODO(palmer): These are quick hacks to import PartitionAlloc with minimum +// hassle. Look into pulling in the real DCHECK definition. It might be more +// than we need, or have more dependencies than we want. In the meantime, this +// is safe, at the cost of some performance. +#define DCHECK CHECK +#define DCHECK_EQ(x, y) CHECK((x) == (y)) +#define DCHECK_IS_ON() true + +// TODO(palmer): Also a quick hack. IMMEDIATE_CRASH used to be simple in +// Chromium base/, but it got way more complicated and has lots of base/ +// dependencies now. Sad! +#define IMMEDIATE_CRASH() abort(); + #define NOTREACHED() assert(false) #endif // PDFIUM_THIRD_PARTY_BASE_LOGGING_H_ diff --git a/third_party/base/macros.h b/third_party/base/macros.h index 05c3132e4693861ae6b4cf9dd44b8a5d29b9104c..b6ec16120417ff3830966cac3c294e3b3cf3e076 100644 --- a/third_party/base/macros.h +++ b/third_party/base/macros.h @@ -28,4 +28,10 @@ #undef COMPILE_ASSERT #define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) +// A macro to disallow the copy constructor and operator= functions. +// This should be used in the private: declarations for a class. +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete + #endif // PDFIUM_THIRD_PARTY_BASE_MACROS_H_ diff --git a/third_party/base/numerics/safe_conversions_impl.h b/third_party/base/numerics/safe_conversions_impl.h index 2a7ce146e3c2b5b5fd4324cbb07e27839723f8ef..4077b28200c3fc4be1fe7f16db906ef6face7d89 100644 --- a/third_party/base/numerics/safe_conversions_impl.h +++ b/third_party/base/numerics/safe_conversions_impl.h @@ -143,7 +143,7 @@ class RangeCheck { public: constexpr RangeCheck(bool is_in_lower_bound, bool is_in_upper_bound) : is_underflow_(!is_in_lower_bound), is_overflow_(!is_in_upper_bound) {} - constexpr RangeCheck() : is_underflow_(0), is_overflow_(0) {} + constexpr RangeCheck() : is_underflow_(false), is_overflow_(false) {} constexpr bool IsValid() const { return !is_overflow_ && !is_underflow_; } constexpr bool IsInvalid() const { return is_overflow_ && is_underflow_; } constexpr bool IsOverflow() const { return is_overflow_ && !is_underflow_; } @@ -725,7 +725,7 @@ constexpr bool SafeCompare(const L lhs, const R rhs) { static_cast(static_cast(rhs))) // Let the template functions figure it out for mixed types. : C::Test(lhs, rhs); -}; +} } // namespace internal } // namespace base diff --git a/third_party/base/numerics/safe_math.h b/third_party/base/numerics/safe_math.h index a0c41a467b904fb742bfc7f0fe0a098112a3378f..f24ba024ebb40cc4d37a1c3f295c53d1f3045246 100644 --- a/third_party/base/numerics/safe_math.h +++ b/third_party/base/numerics/safe_math.h @@ -100,7 +100,7 @@ class CheckedNumeric { public: using type = T; - constexpr CheckedNumeric() {} + constexpr CheckedNumeric() = default; // Copy constructor. template @@ -419,7 +419,7 @@ ChkMathOp(const L lhs, const R rhs, const Args... args) { auto tmp = ChkMathOp(lhs, rhs); return tmp.IsValid() ? ChkMathOp(tmp, args...) : decltype(ChkMathOp(tmp, args...))(tmp); -}; +} // The following macros are just boilerplate for the standard arithmetic // operator overloads and variadic function templates. A macro isn't the nicest diff --git a/third_party/base/numerics/safe_math_impl.h b/third_party/base/numerics/safe_math_impl.h index 5ad79ce1923dadb69971e407298baab3717dc060..4bcc67188c6a45e53229c5e03c25fd4e9d3440e2 100644 --- a/third_party/base/numerics/safe_math_impl.h +++ b/third_party/base/numerics/safe_math_impl.h @@ -59,9 +59,9 @@ bool CheckedAddImpl(T x, T y, T* result) { // it using the unsigned type of the same size. using UnsignedDst = typename std::make_unsigned::type; using SignedDst = typename std::make_signed::type; - UnsignedDst ux = static_cast(x); - UnsignedDst uy = static_cast(y); - UnsignedDst uresult = static_cast(ux + uy); + auto ux = static_cast(x); + auto uy = static_cast(y); + auto uresult = static_cast(ux + uy); *result = static_cast(uresult); // Addition is valid if the sign of (x + y) is equal to either that of x or // that of y. @@ -110,9 +110,9 @@ bool CheckedSubImpl(T x, T y, T* result) { // it using the unsigned type of the same size. using UnsignedDst = typename std::make_unsigned::type; using SignedDst = typename std::make_signed::type; - UnsignedDst ux = static_cast(x); - UnsignedDst uy = static_cast(y); - UnsignedDst uresult = static_cast(ux - uy); + auto ux = static_cast(x); + auto uy = static_cast(y); + auto uresult = static_cast(ux - uy); *result = static_cast(uresult); // Subtraction is valid if either x and y have same sign, or (x-y) and x have // the same sign. @@ -163,7 +163,7 @@ bool CheckedMulImpl(T x, T y, T* result) { using SignedDst = typename std::make_signed::type; const UnsignedDst ux = SafeUnsignedAbs(x); const UnsignedDst uy = SafeUnsignedAbs(y); - UnsignedDst uresult = static_cast(ux * uy); + auto uresult = static_cast(ux * uy); const bool is_negative = std::is_signed::value && static_cast(x ^ y) < 0; *result = is_negative ? 0 - uresult : uresult; @@ -308,7 +308,7 @@ struct CheckedLshOp::type; static const ShiftType kBitWidth = IntegerBitsPlusSign::value; - const ShiftType real_shift = static_cast(shift); + const auto real_shift = static_cast(shift); // Signed shift is not legal on negative values. if (!IsValueNegative(x) && real_shift < kBitWidth) { // Just use a multiplication because it's easy. diff --git a/third_party/base/optional.h b/third_party/base/optional.h new file mode 100644 index 0000000000000000000000000000000000000000..f92101c19b0a20c4c6cc4dd6d884446d671638fe --- /dev/null +++ b/third_party/base/optional.h @@ -0,0 +1,509 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDFIUM_THIRD_PARTY_BASE_OPTIONAL_H_ +#define PDFIUM_THIRD_PARTY_BASE_OPTIONAL_H_ + +#include + +#include "third_party/base/logging.h" + +namespace pdfium { + +// Specification: +// http://en.cppreference.com/w/cpp/utility/optional/in_place_t +struct in_place_t {}; + +// Specification: +// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t +struct nullopt_t { + constexpr explicit nullopt_t(int) {} +}; + +// Specification: +// http://en.cppreference.com/w/cpp/utility/optional/in_place +constexpr in_place_t in_place = {}; + +// Specification: +// http://en.cppreference.com/w/cpp/utility/optional/nullopt +constexpr nullopt_t nullopt(0); + +namespace internal { + +template ::value> +struct OptionalStorage { + // Initializing |empty_| here instead of using default member initializing + // to avoid errors in g++ 4.8. + constexpr OptionalStorage() : empty_('\0') {} + + constexpr explicit OptionalStorage(const T& value) + : is_null_(false), value_(value) {} + + // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. + explicit OptionalStorage(T&& value) + : is_null_(false), value_(std::move(value)) {} + + // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. + template + explicit OptionalStorage(in_place_t, Args&&... args) + : is_null_(false), value_(std::forward(args)...) {} + + // When T is not trivially destructible we must call its + // destructor before deallocating its memory. + ~OptionalStorage() { + if (!is_null_) + value_.~T(); + } + + bool is_null_ = true; + union { + // |empty_| exists so that the union will always be initialized, even when + // it doesn't contain a value. Union members must be initialized for the + // constructor to be 'constexpr'. + char empty_; + T value_; + }; +}; + +template +struct OptionalStorage { + // Initializing |empty_| here instead of using default member initializing + // to avoid errors in g++ 4.8. + constexpr OptionalStorage() : empty_('\0') {} + + constexpr explicit OptionalStorage(const T& value) + : is_null_(false), value_(value) {} + + // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. + explicit OptionalStorage(T&& value) + : is_null_(false), value_(std::move(value)) {} + + // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. + template + explicit OptionalStorage(in_place_t, Args&&... args) + : is_null_(false), value_(std::forward(args)...) {} + + // When T is trivially destructible (i.e. its destructor does nothing) there + // is no need to call it. Explicitly defaulting the destructor means it's not + // user-provided. Those two together make this destructor trivial. + ~OptionalStorage() = default; + + bool is_null_ = true; + union { + // |empty_| exists so that the union will always be initialized, even when + // it doesn't contain a value. Union members must be initialized for the + // constructor to be 'constexpr'. + char empty_; + T value_; + }; +}; + +} // namespace internal + +// pdfium::Optional is a PDFium version of the C++17 optional class, +// based on the Chromium version: +// std::optional documentation: +// http://en.cppreference.com/w/cpp/utility/optional +// Chromium documentation: +// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md +// +// These are the differences between the specification and the implementation: +// - The constructor and emplace method using initializer_list are not +// implemented because 'initializer_list' is banned from Chromium. +// - Constructors do not use 'constexpr' as it is a C++14 extension. +// - 'constexpr' might be missing in some places for reasons specified locally. +// - No exceptions are thrown, because they are banned from Chromium. +// - All the non-members are in the 'pdifum' namespace instead of 'std'. +template +class Optional { + public: + using value_type = T; + + constexpr Optional() = default; + + constexpr Optional(nullopt_t) {} + + Optional(const Optional& other) { + if (!other.storage_.is_null_) + Init(other.value()); + } + + Optional(Optional&& other) { + if (!other.storage_.is_null_) + Init(std::move(other.value())); + } + + constexpr Optional(const T& value) : storage_(value) {} + + // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. + Optional(T&& value) : storage_(std::move(value)) {} + + // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. + template + explicit Optional(in_place_t, Args&&... args) + : storage_(in_place, std::forward(args)...) {} + + ~Optional() = default; + + Optional& operator=(nullopt_t) { + FreeIfNeeded(); + return *this; + } + + Optional& operator=(const Optional& other) { + if (other.storage_.is_null_) { + FreeIfNeeded(); + return *this; + } + + InitOrAssign(other.value()); + return *this; + } + + Optional& operator=(Optional&& other) { + if (other.storage_.is_null_) { + FreeIfNeeded(); + return *this; + } + + InitOrAssign(std::move(other.value())); + return *this; + } + + template + typename std::enable_if, T>::value, + Optional&>::type + operator=(U&& value) { + InitOrAssign(std::forward(value)); + return *this; + } + + // TODO(mlamouri): can't use 'constexpr' with DCHECK. + const T* operator->() const { + DCHECK(!storage_.is_null_); + return &value(); + } + + // TODO(mlamouri): using 'constexpr' here breaks compiler that assume it was + // meant to be 'constexpr const'. + T* operator->() { + DCHECK(!storage_.is_null_); + return &value(); + } + + constexpr const T& operator*() const& { return value(); } + + // TODO(mlamouri): using 'constexpr' here breaks compiler that assume it was + // meant to be 'constexpr const'. + T& operator*() & { return value(); } + + constexpr const T&& operator*() const&& { return std::move(value()); } + + // TODO(mlamouri): using 'constexpr' here breaks compiler that assume it was + // meant to be 'constexpr const'. + T&& operator*() && { return std::move(value()); } + + constexpr explicit operator bool() const { return !storage_.is_null_; } + + constexpr bool has_value() const { return !storage_.is_null_; } + + // TODO(mlamouri): using 'constexpr' here breaks compiler that assume it was + // meant to be 'constexpr const'. + T& value() & { + DCHECK(!storage_.is_null_); + return storage_.value_; + } + + // TODO(mlamouri): can't use 'constexpr' with DCHECK. + const T& value() const& { + DCHECK(!storage_.is_null_); + return storage_.value_; + } + + // TODO(mlamouri): using 'constexpr' here breaks compiler that assume it was + // meant to be 'constexpr const'. + T&& value() && { + DCHECK(!storage_.is_null_); + return std::move(storage_.value_); + } + + // TODO(mlamouri): can't use 'constexpr' with DCHECK. + const T&& value() const&& { + DCHECK(!storage_.is_null_); + return std::move(storage_.value_); + } + + template + constexpr T value_or(U&& default_value) const& { + // TODO(mlamouri): add the following assert when possible: + // static_assert(std::is_copy_constructible::value, + // "T must be copy constructible"); + static_assert(std::is_convertible::value, + "U must be convertible to T"); + return storage_.is_null_ ? static_cast(std::forward(default_value)) + : value(); + } + + template + T value_or(U&& default_value) && { + // TODO(mlamouri): add the following assert when possible: + // static_assert(std::is_move_constructible::value, + // "T must be move constructible"); + static_assert(std::is_convertible::value, + "U must be convertible to T"); + return storage_.is_null_ ? static_cast(std::forward(default_value)) + : std::move(value()); + } + + void swap(Optional& other) { + if (storage_.is_null_ && other.storage_.is_null_) + return; + + if (storage_.is_null_ != other.storage_.is_null_) { + if (storage_.is_null_) { + Init(std::move(other.storage_.value_)); + other.FreeIfNeeded(); + } else { + other.Init(std::move(storage_.value_)); + FreeIfNeeded(); + } + return; + } + + DCHECK(!storage_.is_null_ && !other.storage_.is_null_); + using std::swap; + swap(**this, *other); + } + + void reset() { + FreeIfNeeded(); + } + + template + void emplace(Args&&... args) { + FreeIfNeeded(); + Init(std::forward(args)...); + } + + private: + void Init(const T& value) { + DCHECK(storage_.is_null_); + new (&storage_.value_) T(value); + storage_.is_null_ = false; + } + + void Init(T&& value) { + DCHECK(storage_.is_null_); + new (&storage_.value_) T(std::move(value)); + storage_.is_null_ = false; + } + + template + void Init(Args&&... args) { + DCHECK(storage_.is_null_); + new (&storage_.value_) T(std::forward(args)...); + storage_.is_null_ = false; + } + + void InitOrAssign(const T& value) { + if (storage_.is_null_) + Init(value); + else + storage_.value_ = value; + } + + void InitOrAssign(T&& value) { + if (storage_.is_null_) + Init(std::move(value)); + else + storage_.value_ = std::move(value); + } + + void FreeIfNeeded() { + if (storage_.is_null_) + return; + storage_.value_.~T(); + storage_.is_null_ = true; + } + + internal::OptionalStorage storage_; +}; + +template +constexpr bool operator==(const Optional& lhs, const Optional& rhs) { + return !!lhs != !!rhs ? false : lhs == nullopt || (*lhs == *rhs); +} + +template +constexpr bool operator!=(const Optional& lhs, const Optional& rhs) { + return !(lhs == rhs); +} + +template +constexpr bool operator<(const Optional& lhs, const Optional& rhs) { + return rhs == nullopt ? false : (lhs == nullopt ? true : *lhs < *rhs); +} + +template +constexpr bool operator<=(const Optional& lhs, const Optional& rhs) { + return !(rhs < lhs); +} + +template +constexpr bool operator>(const Optional& lhs, const Optional& rhs) { + return rhs < lhs; +} + +template +constexpr bool operator>=(const Optional& lhs, const Optional& rhs) { + return !(lhs < rhs); +} + +template +constexpr bool operator==(const Optional& opt, nullopt_t) { + return !opt; +} + +template +constexpr bool operator==(nullopt_t, const Optional& opt) { + return !opt; +} + +template +constexpr bool operator!=(const Optional& opt, nullopt_t) { + return !!opt; +} + +template +constexpr bool operator!=(nullopt_t, const Optional& opt) { + return !!opt; +} + +template +constexpr bool operator<(const Optional& opt, nullopt_t) { + return false; +} + +template +constexpr bool operator<(nullopt_t, const Optional& opt) { + return !!opt; +} + +template +constexpr bool operator<=(const Optional& opt, nullopt_t) { + return !opt; +} + +template +constexpr bool operator<=(nullopt_t, const Optional& opt) { + return true; +} + +template +constexpr bool operator>(const Optional& opt, nullopt_t) { + return !!opt; +} + +template +constexpr bool operator>(nullopt_t, const Optional& opt) { + return false; +} + +template +constexpr bool operator>=(const Optional& opt, nullopt_t) { + return true; +} + +template +constexpr bool operator>=(nullopt_t, const Optional& opt) { + return !opt; +} + +template +constexpr bool operator==(const Optional& opt, const T& value) { + return opt != nullopt ? *opt == value : false; +} + +template +constexpr bool operator==(const T& value, const Optional& opt) { + return opt == value; +} + +template +constexpr bool operator!=(const Optional& opt, const T& value) { + return !(opt == value); +} + +template +constexpr bool operator!=(const T& value, const Optional& opt) { + return !(opt == value); +} + +template +constexpr bool operator<(const Optional& opt, const T& value) { + return opt != nullopt ? *opt < value : true; +} + +template +constexpr bool operator<(const T& value, const Optional& opt) { + return opt != nullopt ? value < *opt : false; +} + +template +constexpr bool operator<=(const Optional& opt, const T& value) { + return !(opt > value); +} + +template +constexpr bool operator<=(const T& value, const Optional& opt) { + return !(value > opt); +} + +template +constexpr bool operator>(const Optional& opt, const T& value) { + return value < opt; +} + +template +constexpr bool operator>(const T& value, const Optional& opt) { + return opt < value; +} + +template +constexpr bool operator>=(const Optional& opt, const T& value) { + return !(opt < value); +} + +template +constexpr bool operator>=(const T& value, const Optional& opt) { + return !(value < opt); +} + +template +constexpr Optional::type> make_optional(T&& value) { + return Optional::type>(std::forward(value)); +} + +template +void swap(Optional& lhs, Optional& rhs) { + lhs.swap(rhs); +} + +} // namespace pdfium + +namespace std { + +template +struct hash> { + size_t operator()(const pdfium::Optional& opt) const { + return opt == pdfium::nullopt ? 0 : std::hash()(*opt); + } +}; + +} // namespace std + +template +using Optional = pdfium::Optional; + +#endif // PDFIUM_THIRD_PARTY_BASE_OPTIONAL_H_ diff --git a/third_party/base/stl_util.h b/third_party/base/stl_util.h index 795414b59f021543e904394efcd693985bf3b392..6c36ddcda1b88940c096f778762f058b7fbc292c 100644 --- a/third_party/base/stl_util.h +++ b/third_party/base/stl_util.h @@ -6,6 +6,7 @@ #define PDFIUM_THIRD_PARTY_BASE_STL_UTIL_H_ #include +#include #include #include @@ -24,8 +25,8 @@ bool ContainsKey(const Collection& collection, const Key& key) { // Returns true if the value is in the collection. template bool ContainsValue(const Collection& collection, const Value& value) { - return std::find(collection.begin(), collection.end(), value) != - collection.end(); + return std::find(std::begin(collection), std::end(collection), value) != + std::end(collection); } // Means of generating a key for searching STL collections of std::unique_ptr @@ -44,6 +45,13 @@ ResultType CollectionSize(const Collection& collection) { return pdfium::base::checked_cast(collection.size()); } +// Convenience routine for "int-fected" code, to handle signed indicies. The +// compiler can deduce the type, making this more convenient than the above. +template +bool IndexInBounds(const Collection& collection, IndexType index) { + return index >= 0 && index < CollectionSize(collection); +} + // Track the addition of an object to a set, removing it automatically when // the ScopedSetInsertion goes out of scope. template @@ -60,6 +68,12 @@ class ScopedSetInsertion { const T m_Entry; }; +// std::clamp(), some day. +template +constexpr const T& clamp(const T& v, const T& lo, const T& hi) { + return std::min(std::max(v, lo), hi); +} + } // namespace pdfium #endif // PDFIUM_THIRD_PARTY_BASE_STL_UTIL_H_ diff --git a/third_party/base/sys_byteorder.h b/third_party/base/sys_byteorder.h new file mode 100644 index 0000000000000000000000000000000000000000..593abe17d432fa1b38abe851a79a6643bf597595 --- /dev/null +++ b/third_party/base/sys_byteorder.h @@ -0,0 +1,141 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This header defines cross-platform ByteSwap() implementations for 16, 32 and +// 64-bit values, and NetToHostXX() / HostToNextXX() functions equivalent to +// the traditional ntohX() and htonX() functions. +// Use the functions defined here rather than using the platform-specific +// functions directly. + +#ifndef BASE_SYS_BYTEORDER_H_ +#define BASE_SYS_BYTEORDER_H_ + +#include + +#include "third_party/base/logging.h" +#include "third_party/build/build_config.h" + +#if defined(COMPILER_MSVC) +#include +#endif + +namespace pdfium { +namespace base { + +// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. +inline uint16_t ByteSwap(uint16_t x) { +#if defined(COMPILER_MSVC) + return _byteswap_ushort(x); +#else + return __builtin_bswap16(x); +#endif +} + +inline uint32_t ByteSwap(uint32_t x) { +#if defined(COMPILER_MSVC) + return _byteswap_ulong(x); +#else + return __builtin_bswap32(x); +#endif +} + +inline uint64_t ByteSwap(uint64_t x) { +#if defined(COMPILER_MSVC) + return _byteswap_uint64(x); +#else + return __builtin_bswap64(x); +#endif +} + +inline uintptr_t ByteSwapUintPtrT(uintptr_t x) { + // We do it this way because some build configurations are ILP32 even when + // defined(ARCH_CPU_64_BITS). Unfortunately, we can't use sizeof in #ifs. But, + // because these conditionals are constexprs, the irrelevant branches will + // likely be optimized away, so this construction should not result in code + // bloat. + if (sizeof(uintptr_t) == 4) { + return ByteSwap(static_cast(x)); + } else if (sizeof(uintptr_t) == 8) { + return ByteSwap(static_cast(x)); + } else { + NOTREACHED(); + } +} + +// Converts the bytes in |x| from host order (endianness) to little endian, and +// returns the result. +inline uint16_t ByteSwapToLE16(uint16_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return x; +#else + return ByteSwap(x); +#endif +} +inline uint32_t ByteSwapToLE32(uint32_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return x; +#else + return ByteSwap(x); +#endif +} +inline uint64_t ByteSwapToLE64(uint64_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return x; +#else + return ByteSwap(x); +#endif +} + +// Converts the bytes in |x| from network to host order (endianness), and +// returns the result. +inline uint16_t NetToHost16(uint16_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return ByteSwap(x); +#else + return x; +#endif +} +inline uint32_t NetToHost32(uint32_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return ByteSwap(x); +#else + return x; +#endif +} +inline uint64_t NetToHost64(uint64_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return ByteSwap(x); +#else + return x; +#endif +} + +// Converts the bytes in |x| from host to network order (endianness), and +// returns the result. +inline uint16_t HostToNet16(uint16_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return ByteSwap(x); +#else + return x; +#endif +} +inline uint32_t HostToNet32(uint32_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return ByteSwap(x); +#else + return x; +#endif +} +inline uint64_t HostToNet64(uint64_t x) { +#if defined(ARCH_CPU_LITTLE_ENDIAN) + return ByteSwap(x); +#else + return x; +#endif +} + +} // namespace base +} // namespace pdfium + +#endif // BASE_SYS_BYTEORDER_H_ diff --git a/third_party/base/template_util.h b/third_party/base/template_util.h new file mode 100644 index 0000000000000000000000000000000000000000..b2463225f8ed63663c4041101299549db1e5748e --- /dev/null +++ b/third_party/base/template_util.h @@ -0,0 +1,203 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TEMPLATE_UTIL_H_ +#define BASE_TEMPLATE_UTIL_H_ + +#include +#include +#include +#include + +#include "third_party/build/build_config.h" + +// This hacks around libstdc++ 4.6 missing stuff in type_traits, while we need +// to support it. +#define CR_GLIBCXX_4_7_0 20120322 +#define CR_GLIBCXX_4_5_4 20120702 +#define CR_GLIBCXX_4_6_4 20121127 +#if defined(__GLIBCXX__) && \ + (__GLIBCXX__ < CR_GLIBCXX_4_7_0 || __GLIBCXX__ == CR_GLIBCXX_4_5_4 || \ + __GLIBCXX__ == CR_GLIBCXX_4_6_4) +#define CR_USE_FALLBACKS_FOR_OLD_GLIBCXX +#endif + +// Some versions of libstdc++ have partial support for type_traits, but misses +// a smaller subset while removing some of the older non-standard stuff. Assume +// that all versions below 5.0 fall in this category, along with one 5.0 +// experimental release. Test for this by consulting compiler major version, +// the only reliable option available, so theoretically this could fail should +// you attempt to mix an earlier version of libstdc++ with >= GCC5. But +// that's unlikely to work out, especially as GCC5 changed ABI. +#define CR_GLIBCXX_5_0_0 20150123 +#if (defined(__GNUC__) && __GNUC__ < 5) || \ + (defined(__GLIBCXX__) && __GLIBCXX__ == CR_GLIBCXX_5_0_0) +#define CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX +#endif + +// This hacks around using gcc with libc++ which has some incompatibilies. +// - is_trivially_* doesn't work: https://llvm.org/bugs/show_bug.cgi?id=27538 +// TODO(danakj): Remove this when android builders are all using a newer version +// of gcc, or the android ndk is updated to a newer libc++ that works with older +// gcc versions. +#if !defined(__clang__) && defined(_LIBCPP_VERSION) +#define CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX +#endif + +namespace base { + +template +struct is_non_const_reference : std::false_type {}; +template +struct is_non_const_reference : std::true_type {}; +template +struct is_non_const_reference : std::false_type {}; + +// is_assignable + +namespace internal { + +template +struct SelectSecond { + using type = Second; +}; + +struct Any { + Any(...); +}; + +// True case: If |Lvalue| can be assigned to from |Rvalue|, then the return +// value is a true_type. +template +typename internal::SelectSecond< + decltype((std::declval() = std::declval())), + std::true_type>::type +IsAssignableTest(Lvalue&&, Rvalue&&); + +// False case: Otherwise the return value is a false_type. +template +std::false_type IsAssignableTest(internal::Any, Rvalue&&); + +// Default case: Neither Lvalue nor Rvalue is void. Uses IsAssignableTest to +// determine the type of IsAssignableImpl. +template ::value || std::is_void::value> +struct IsAssignableImpl + : public std::common_type(), + std::declval()))>::type {}; + +// Void case: Either Lvalue or Rvalue is void. Then the type of IsAssignableTest +// is false_type. +template +struct IsAssignableImpl : public std::false_type {}; + +// Uses expression SFINAE to detect whether using operator<< would work. +template +struct SupportsOstreamOperator : std::false_type {}; +template +struct SupportsOstreamOperator() + << std::declval()))> + : std::true_type {}; + +} // namespace internal + +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +template +struct is_assignable : public internal::IsAssignableImpl {}; + +// is_copy_assignable is true if a T const& is assignable to a T&. +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +template +struct is_copy_assignable + : public is_assignable::type, + typename std::add_lvalue_reference< + typename std::add_const::type>::type> {}; + +// is_move_assignable is true if a T&& is assignable to a T&. +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +template +struct is_move_assignable + : public is_assignable::type, + const typename std::add_rvalue_reference::type> { +}; + +// underlying_type produces the integer type backing an enum type. +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +#if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) +template +struct underlying_type { + using type = __underlying_type(T); +}; +#else +template +using underlying_type = std::underlying_type; +#endif + +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +#if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) +template +using is_trivially_destructible = std::has_trivial_destructor; +#else +template +using is_trivially_destructible = std::is_trivially_destructible; +#endif + +// is_trivially_copyable is especially hard to get right. +// - Older versions of libstdc++ will fail to have it like they do for other +// type traits. In this case we should provide it based on compiler +// intrinsics. This is covered by the CR_USE_FALLBACKS_FOR_OLD_GLIBCXX define. +// - An experimental release of gcc includes most of type_traits but misses +// is_trivially_copyable, so we still have to avoid using libstdc++ in this +// case, which is covered by CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX. +// - When compiling libc++ from before r239653, with a gcc compiler, the +// std::is_trivially_copyable can fail. So we need to work around that by not +// using the one in libc++ in this case. This is covered by the +// CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX define, and is discussed in +// https://llvm.org/bugs/show_bug.cgi?id=27538#c1 where they point out that +// in libc++'s commit r239653 this is fixed by libc++ checking for gcc 5.1. +// - In both of the above cases we are using the gcc compiler. When defining +// this ourselves on compiler intrinsics, the __is_trivially_copyable() +// intrinsic is not available on gcc before version 5.1 (see the discussion in +// https://llvm.org/bugs/show_bug.cgi?id=27538#c1 again), so we must check for +// that version. +// - When __is_trivially_copyable() is not available because we are on gcc older +// than 5.1, we need to fall back to something, so we use __has_trivial_copy() +// instead based on what was done one-off in bit_cast() previously. + +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace and it works with gcc as needed. +#if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) || \ + defined(CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX) || \ + defined(CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX) +template +struct is_trivially_copyable { +// TODO(danakj): Remove this when android builders are all using a newer version +// of gcc, or the android ndk is updated to a newer libc++ that does this for +// us. +#if _GNUC_VER >= 501 + static constexpr bool value = __is_trivially_copyable(T); +#else + static constexpr bool value = __has_trivial_copy(T); +#endif +}; +#else +template +using is_trivially_copyable = std::is_trivially_copyable; +#endif + +} // namespace base + +#undef CR_USE_FALLBACKS_FOR_OLD_GLIBCXX +#undef CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX +#undef CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX + +#endif // BASE_TEMPLATE_UTIL_H_ diff --git a/third_party/build/build_config.h b/third_party/build/build_config.h new file mode 100644 index 0000000000000000000000000000000000000000..d4c66e046d57fbbc255d0af309b8e3bbe3343689 --- /dev/null +++ b/third_party/build/build_config.h @@ -0,0 +1,194 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file adds defines about the platform we're currently building on. +// Operating System: +// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) / +// OS_NACL (NACL_SFI or NACL_NONSFI) / OS_NACL_SFI / OS_NACL_NONSFI +// OS_CHROMEOS is set by the build system +// Compiler: +// COMPILER_MSVC / COMPILER_GCC +// Processor: +// ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64) +// ARCH_CPU_32_BITS / ARCH_CPU_64_BITS + +#ifndef BUILD_BUILD_CONFIG_H_ +#define BUILD_BUILD_CONFIG_H_ + +// A set of macros to use for platform detection. +#if defined(__native_client__) +// __native_client__ must be first, so that other OS_ defines are not set. +#define OS_NACL 1 +// OS_NACL comes in two sandboxing technology flavors, SFI or Non-SFI. +// PNaCl toolchain defines __native_client_nonsfi__ macro in Non-SFI build +// mode, while it does not in SFI build mode. +#if defined(__native_client_nonsfi__) +#define OS_NACL_NONSFI +#else +#define OS_NACL_SFI +#endif +#elif defined(ANDROID) +#define OS_ANDROID 1 +#elif defined(__APPLE__) +// only include TargetConditions after testing ANDROID as some android builds +// on mac don't have this header available and it's not needed unless the target +// is really mac/ios. +#include +#define OS_MACOSX 1 +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#define OS_IOS 1 +#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#elif defined(__linux__) +#define OS_LINUX 1 +// include a system header to pull in features.h for glibc/uclibc macros. +#include +#if defined(__GLIBC__) && !defined(__UCLIBC__) +// we really are using glibc, not uClibc pretending to be glibc +#define LIBC_GLIBC 1 +#endif +#elif defined(_WIN32) +#define OS_WIN 1 +#elif defined(__FreeBSD__) +#define OS_FREEBSD 1 +#elif defined(__NetBSD__) +#define OS_NETBSD 1 +#elif defined(__OpenBSD__) +#define OS_OPENBSD 1 +#elif defined(__sun) +#define OS_SOLARIS 1 +#elif defined(__QNXNTO__) +#define OS_QNX 1 +#else +#error Please add support for your platform in build/build_config.h +#endif + +#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS) +#error Cannot use both OpenSSL and NSS for certificates +#endif + +// For access to standard BSD features, use OS_BSD instead of a +// more specific macro. +#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) +#define OS_BSD 1 +#endif + +// For access to standard POSIXish features, use OS_POSIX instead of a +// more specific macro. +#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \ + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_SOLARIS) || \ + defined(OS_ANDROID) || defined(OS_OPENBSD) || defined(OS_SOLARIS) || \ + defined(OS_ANDROID) || defined(OS_NACL) || defined(OS_QNX) +#define OS_POSIX 1 +#endif + +// Use tcmalloc +#if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \ + !defined(NO_TCMALLOC) +#define USE_TCMALLOC 1 +#endif + +// Compiler detection. +#if defined(__GNUC__) +#define COMPILER_GCC 1 +#elif defined(_MSC_VER) +#define COMPILER_MSVC 1 +#else +#error Please add support for your compiler in build/build_config.h +#endif + +// Processor architecture detection. For more info on what's defined, see: +// http://msdn.microsoft.com/en-us/library/b0084kay.aspx +// http://www.agner.org/optimize/calling_conventions.pdf +// or with gcc, run: "echo | gcc -E -dM -" +#if defined(_M_X64) || defined(__x86_64__) +#define ARCH_CPU_X86_FAMILY 1 +#define ARCH_CPU_X86_64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(_M_IX86) || defined(__i386__) +#define ARCH_CPU_X86_FAMILY 1 +#define ARCH_CPU_X86 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__s390x__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390X 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__s390__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390 1 +#define ARCH_CPU_31_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__PPC64__) && defined(__BIG_ENDIAN__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__PPC64__) && defined(__LITTLE_ENDIAN__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__PPC__) +#define ARCH_CPU_PPC_FAMILY 1 +#define ARCH_CPU_PPC 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__ARMEL__) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARMEL 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__aarch64__) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARM64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__pnacl__) +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__MIPSEL__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64EL 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#else +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPSEL 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#endif +#else +#error Please add support for your architecture in build/build_config.h +#endif + +// Type detection for wchar_t. +#if defined(OS_WIN) +#define WCHAR_T_IS_UTF16 +#elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \ + (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) +#define WCHAR_T_IS_UTF32 +#elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \ + (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) +// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to +// compile in this mode (in particular, Chrome doesn't). This is intended for +// other projects using base who manage their own dependencies and make sure +// short wchar works for them. +#define WCHAR_T_IS_UTF16 +#else +#error Please add support for your compiler in build/build_config.h +#endif + +#if defined(OS_ANDROID) +// The compiler thinks std::string::const_iterator and "const char*" are +// equivalent types. +#define STD_STRING_ITERATOR_IS_CHAR_POINTER +// The compiler thinks base::string16::const_iterator and "char16*" are +// equivalent types. +#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER +#endif + +#endif // BUILD_BUILD_CONFIG_H_ diff --git a/third_party/eu-strip/README.pdfium b/third_party/eu-strip/README.pdfium new file mode 100644 index 0000000000000000000000000000000000000000..e84974d92b9cec9abd45c2dbaab1dd74a0a6d7dc --- /dev/null +++ b/third_party/eu-strip/README.pdfium @@ -0,0 +1,24 @@ +Name: eu-strip +URL: https://sourceware.org/elfutils/ +Version: 0.158 +Security Critical: no +License: LGPL 3 +License File: NOT_SHIPPED + +Description: + +Patched eu-strip from elfutils. + +Build instructions (on Trusty; note that this will build the +Ubuntu-patched version of elfutils): +$ mkdir elfutils +$ cd elfutils +$ apt-get source elfutils +$ cd elfutils-0.158 +[ Edit libelf/elf_end.c and remove the free() on line 164. ] +$ ./configure +$ make +$ gcc -std=gnu99 -Wall -Wshadow -Wunused -Wextra -fgnu89-inline + -Wformat=2 -Werror -g -O2 -Wl,-rpath-link,libelf:libdw -o eu-strip + src/strip.o libebl/libebl.a libelf/libelf.a lib/libeu.a -ldl +$ eu-strip ./eu-strip # Keep the binary small, please. diff --git a/third_party/eu-strip/bin/eu-strip b/third_party/eu-strip/bin/eu-strip new file mode 100755 index 0000000000000000000000000000000000000000..994e2263b9185f77169c6c8545869d3c84cf0a8a Binary files /dev/null and b/third_party/eu-strip/bin/eu-strip differ diff --git a/third_party/freetype/0000-include.patch b/third_party/freetype/0000-include.patch index d7478e78112c3d3b361b4c9c7fe5f52b54a53572..d6c837471c57549b840c3bedf645f68f68e2a507 100644 --- a/third_party/freetype/0000-include.patch +++ b/third_party/freetype/0000-include.patch @@ -1,28 +1,6 @@ -diff -ru freetype-2.6.1/include/freetype/config/ftmodule.h include/freetype/config/ftmodule.h ---- freetype-2.6.1/include/freetype/config/ftmodule.h 2015-11-05 13:52:36.734733186 -0800 -+++ include/freetype/config/ftmodule.h 2015-11-05 13:44:54.445479822 -0800 -@@ -1,3 +1,20 @@ -+/***************************************************************************/ -+/* */ -+/* ftmodule.h */ -+/* */ -+/* FreeType modules public interface (specification). */ -+/* */ -+/* Copyright 1996-2001, 2002, 2003 by */ -+/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -+/* */ -+/* This file is part of the FreeType project, and may only be used, */ -+/* modified, and distributed under the terms of the FreeType project */ -+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -+/* this file you indicate that you have read the license and */ -+/* understand and accept it fully. */ -+/* */ -+/***************************************************************************/ -+ - /* - * This file registers the FreeType modules compiled into the library. - * -@@ -10,15 +27,15 @@ +--- third_party/freetype/include/freetype/config/ftmodule.h 2017-03-07 20:15:52.781636524 -0800 ++++ third_party/freetype/include/freetype/config/ftmodule.h 2017-03-22 22:57:58.536233071 -0700 +@@ -10,15 +10,15 @@ * */ @@ -43,7 +21,7 @@ diff -ru freetype-2.6.1/include/freetype/config/ftmodule.h include/freetype/conf FT_USE_MODULE( FT_Module_Class, psaux_module_class ) FT_USE_MODULE( FT_Module_Class, psnames_module_class ) FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) -@@ -27,6 +44,6 @@ +@@ -27,6 +27,6 @@ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) @@ -51,10 +29,9 @@ diff -ru freetype-2.6.1/include/freetype/config/ftmodule.h include/freetype/conf +//FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) /* EOF */ -diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/config/ftoption.h ---- freetype-2.6.1/include/freetype/config/ftoption.h 2015-11-05 13:52:36.734733186 -0800 -+++ include/freetype/config/ftoption.h 2015-11-05 13:44:54.445479822 -0800 -@@ -92,7 +92,7 @@ +--- third_party/freetype/include/freetype/config/ftoption.h 2017-03-07 20:15:52.781636524 -0800 ++++ third_party/freetype/include/freetype/config/ftoption.h 2017-03-22 22:57:58.532233095 -0700 +@@ -122,7 +122,7 @@ /* This is done to allow FreeType clients to run unmodified, forcing */ /* them to display normal gray-level anti-aliased glyphs. */ /* */ @@ -63,16 +40,16 @@ diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/conf /*************************************************************************/ -@@ -163,7 +163,7 @@ +@@ -193,7 +193,7 @@ /* Define this macro if you want to enable this `feature'. See also */ /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ /* */ -#define FT_CONFIG_OPTION_USE_ZLIB -+//#define FT_CONFIG_OPTION_USE_ZLIB ++#undef FT_CONFIG_OPTION_USE_ZLIB /*************************************************************************/ -@@ -336,7 +336,7 @@ +@@ -366,7 +366,7 @@ /* */ /* Note that the `FOND' resource isn't checked. */ /* */ @@ -81,7 +58,7 @@ diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/conf /*************************************************************************/ -@@ -512,7 +512,7 @@ +@@ -556,7 +556,7 @@ /* embedded bitmaps in all formats using the SFNT module (namely */ /* TrueType & OpenType). */ /* */ @@ -90,7 +67,7 @@ diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/conf /*************************************************************************/ -@@ -681,7 +681,7 @@ +@@ -705,7 +705,7 @@ /* and avar tables). This has many similarities to Type 1 Multiple */ /* Masters support. */ /* */ @@ -99,7 +76,7 @@ diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/conf /*************************************************************************/ -@@ -689,7 +689,7 @@ +@@ -713,7 +713,7 @@ /* Define TT_CONFIG_OPTION_BDF if you want to include support for */ /* an embedded `BDF ' table within SFNT-based bitmap formats. */ /* */ @@ -108,7 +85,7 @@ diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/conf /*************************************************************************/ -@@ -725,7 +725,7 @@ +@@ -767,7 +767,7 @@ /* */ /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */ /* */ @@ -117,4 +94,3 @@ diff -ru freetype-2.6.1/include/freetype/config/ftoption.h include/freetype/conf /*************************************************************************/ -Only in freetype-2.6.1/include/freetype: ftchapters.h diff --git a/third_party/freetype/README.pdfium b/third_party/freetype/README.pdfium index f8fad6f3b46e865b1ce2b2ecbcfea37703a0fb77..3e9aa69980aec7a35426ce45759ea2b17fa24987 100644 --- a/third_party/freetype/README.pdfium +++ b/third_party/freetype/README.pdfium @@ -1,6 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: 2.6.1 +Version: VER-2-8-1-145 +Revision: 2c048a8a622e9f44f255aa3316026f124ac9ecbc Security Critical: yes License: FreeType License (FTL) License File: FTL.TXT @@ -10,25 +11,10 @@ FreeType library. Local Modifications: -0000-include.patch: Modifications to configuration header files. - -include/freetype/ftchapers.h is not included. +include/pstables.h: A copy of freetype/src/psnames/pstables.h. This file is not +part of the public Freetype API, but pdfium needs it. Since it won't be +avilable when building with the system Freetype, we provide it as a convenience. -The following directories in src/ are not included from -upstream FreeType as they are never used: - -autofit -bdf -bzip2 -cache -gxvalid -gzip -Jamfile -lzw -otvalid -pcf -pfr -tools -type42 -winfonts +0000-include.patch: Modifications to configuration header files. +Most of the updating can be automated will roll-freetype.sh. diff --git a/third_party/freetype/include/freetype-custom-config/ftmodule.h b/third_party/freetype/include/freetype-custom-config/ftmodule.h new file mode 100644 index 0000000000000000000000000000000000000000..0d31ce6932c47e6120d34fae72cb9414f4e01d47 --- /dev/null +++ b/third_party/freetype/include/freetype-custom-config/ftmodule.h @@ -0,0 +1,32 @@ +/* + * This file registers the FreeType modules compiled into the library. + * + * If you use GNU make, this file IS NOT USED! Instead, it is created in + * the objects directory (normally `/objs/') based on information + * from `/modules.cfg'. + * + * Please read `docs/INSTALL.ANY' and `docs/CUSTOMIZE' how to compile + * FreeType without GNU make. + * + */ + +//FT_USE_MODULE( FT_Module_Class, autofit_module_class ) +FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) +//FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) +//FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) +//FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) +//FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) +FT_USE_MODULE( FT_Module_Class, psaux_module_class ) +FT_USE_MODULE( FT_Module_Class, psnames_module_class ) +FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) +FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) +FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) +//FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) + +/* EOF */ diff --git a/third_party/freetype/include/freetype/config/ftoption.h b/third_party/freetype/include/freetype-custom-config/ftoption.h similarity index 83% rename from third_party/freetype/include/freetype/config/ftoption.h rename to third_party/freetype/include/freetype-custom-config/ftoption.h index 886e64e9bfadcf9a9fa79fec54bd792d308fcf17..b986473fdcfc6eaa58377bd9e17e00341a4bef6f 100644 --- a/third_party/freetype/include/freetype/config/ftoption.h +++ b/third_party/freetype/include/freetype-custom-config/ftoption.h @@ -4,7 +4,7 @@ /* */ /* User-selectable configuration macros (specification only). */ /* */ -/* Copyright 1996-2015 by */ +/* Copyright 1996-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -16,8 +16,8 @@ /***************************************************************************/ -#ifndef __FTOPTION_H__ -#define __FTOPTION_H__ +#ifndef FTOPTION_H_ +#define FTOPTION_H_ #include @@ -75,6 +75,36 @@ FT_BEGIN_HEADER /*************************************************************************/ + /*************************************************************************/ + /* */ + /* If you enable this configuration option, FreeType recognizes an */ + /* environment variable called `FREETYPE_PROPERTIES', which can be used */ + /* to control the various font drivers and modules. The controllable */ + /* properties are listed in the section `Controlling FreeType Modules' */ + /* in the reference's table of contents; currently there are properties */ + /* for the auto-hinter (file `ftautoh.h'), CFF (file `ftcffdrv.h'), */ + /* TrueType (file `ftttdrv.h'), and PCF (file `ftpcfdrv.h'). */ + /* */ + /* `FREETYPE_PROPERTIES' has the following syntax form (broken here into */ + /* multiple lines for better readability). */ + /* */ + /* */ + /* ':' */ + /* '=' */ + /* */ + /* ':' */ + /* '=' */ + /* ... */ + /* */ + /* Example: */ + /* */ + /* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ */ + /* cff:no-stem-darkening=1 \ */ + /* autofitter:warping=1 */ + /* */ +#define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + + /*************************************************************************/ /* */ /* Uncomment the line below if you want to activate sub-pixel rendering */ @@ -163,7 +193,7 @@ FT_BEGIN_HEADER /* Define this macro if you want to enable this `feature'. See also */ /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ /* */ -//#define FT_CONFIG_OPTION_USE_ZLIB +#undef FT_CONFIG_OPTION_USE_ZLIB /*************************************************************************/ @@ -492,7 +522,21 @@ FT_BEGIN_HEADER /* code will be used. */ /* */ /* Setting this macro is needed for systems that prohibit address */ - /* fixups, such as BREW. */ + /* fixups, such as BREW. [Note that standard compilers like gcc or */ + /* clang handle PIC generation automatically; you don't have to set */ + /* FT_CONFIG_OPTION_PIC, which is only necessary for very special */ + /* compilers.] */ + /* */ + /* Note that FT_CONFIG_OPTION_PIC support is not available for all */ + /* modules (see `modules.cfg' for a complete list). For building with */ + /* FT_CONFIG_OPTION_PIC support, do the following. */ + /* */ + /* 0. Clone the repository. */ + /* 1. Define FT_CONFIG_OPTION_PIC. */ + /* 2. Remove all subdirectories in `src' that don't have */ + /* FT_CONFIG_OPTION_PIC support. */ + /* 3. Comment out the corresponding modules in `modules.cfg'. */ + /* 4. Compile. */ /* */ /* #define FT_CONFIG_OPTION_PIC */ @@ -586,73 +630,53 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile */ - /* EXPERIMENTAL subpixel hinting support into the TrueType driver. This */ - /* replaces the native TrueType hinting mechanism when anything but */ - /* FT_RENDER_MODE_MONO is requested. */ - /* */ - /* Enabling this causes the TrueType driver to ignore instructions under */ - /* certain conditions. This is done in accordance with the guide here, */ - /* with some minor differences: */ - /* */ - /* http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ - /* */ - /* By undefining this, you only compile the code necessary to hint */ - /* TrueType glyphs with native TT hinting. */ - /* */ - /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ - /* defined. */ - /* */ -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - - /*************************************************************************/ - /* */ - /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */ - /* of the TrueType bytecode interpreter is used that doesn't implement */ - /* any of the patented opcodes and algorithms. The patents related to */ - /* TrueType hinting have expired worldwide since May 2010; this option */ - /* is now deprecated. */ + /* subpixel hinting support into the TrueType driver. This modifies the */ + /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is */ + /* requested. */ /* */ - /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* */ - /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, */ - /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */ - /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */ + /* In particular, it modifies the bytecode interpreter to interpret (or */ + /* not) instructions in a certain way so that all TrueType fonts look */ + /* like they do in a Windows ClearType (DirectWrite) environment. See */ + /* [1] for a technical overview on what this means. See `ttinterp.h' */ + /* for more details on the LEAN option. */ /* */ - /* This macro is only useful for a small number of font files (mostly */ - /* for Asian scripts) that require bytecode interpretation to properly */ - /* load glyphs. For all other fonts, this produces unpleasant results, */ - /* thus the unpatented interpreter is never used to load glyphs from */ - /* TrueType fonts unless one of the following two options is used. */ + /* There are three options. */ /* */ - /* - The unpatented interpreter is explicitly activated by the user */ - /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */ - /* when opening the FT_Face. */ + /* 1. This option is associated with the `Infinality' moniker. */ + /* Contributed by an individual nicknamed Infinality with the goal of */ + /* making TrueType fonts render better than on Windows. A high */ + /* amount of configurability and flexibility, down to rules for */ + /* single glyphs in fonts, but also very slow. Its experimental and */ + /* slow nature and the original developer losing interest meant that */ + /* this option was never enabled in default builds. */ /* */ - /* - FreeType detects that the FT_Face corresponds to one of the */ - /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */ - /* contains a hard-coded list of font names and other matching */ - /* parameters (see function `tt_face_init' in file */ - /* `src/truetype/ttobjs.c'). */ + /* 2. The new default mode for the TrueType driver. The Infinality code */ + /* base was stripped to the bare minimum and all configurability */ + /* removed in the name of speed and simplicity. The configurability */ + /* was mainly aimed at legacy fonts like Arial, Times New Roman, or */ + /* Courier. Legacy fonts are fonts that modify vertical stems to */ + /* achieve clean black-and-white bitmaps. The new mode focuses on */ + /* applying a minimal set of rules to all fonts indiscriminately so */ + /* that modern and web fonts render well while legacy fonts render */ + /* okay. */ /* */ - /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */ + /* 3. Compile both. */ /* */ - /* { */ - /* FT_Parameter parameter; */ - /* FT_Open_Args open_args; */ + /* By undefining these, you get rendering behavior like on Windows */ + /* without ClearType, i.e., Windows XP without ClearType enabled and */ + /* Win9x (interpreter version v35). Or not, depending on how much */ + /* hinting blood and testing tears the font designer put into a given */ + /* font. If you define one or both subpixel hinting options, you can */ + /* switch between between v35 and the ones you define. */ /* */ + /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */ + /* defined. */ /* */ - /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */ + /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ /* */ - /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */ - /* open_args.pathname = my_font_pathname; */ - /* open_args.num_params = 1; */ - /* open_args.params = ¶meter; */ - /* */ - /* error = FT_Open_Face( library, &open_args, index, &face ); */ - /* ... */ - /* } */ - /* */ -/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */ +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ /*************************************************************************/ @@ -692,6 +716,24 @@ FT_BEGIN_HEADER #undef TT_CONFIG_OPTION_BDF + /*************************************************************************/ + /* */ + /* Option TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES controls the maximum */ + /* number of bytecode instructions executed for a single run of the */ + /* bytecode interpreter, needed to prevent infinite loops. You don't */ + /* want to change this except for very special situations (e.g., making */ + /* a library fuzzer spend less time to handle broken fonts). */ + /* */ + /* It is not expected that this value is ever modified by a configuring */ + /* script; instead, it gets surrounded with #ifndef ... #endif so that */ + /* the value can be set as a preprocessor option on the compiler's */ + /* command line. */ + /* */ +#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES +#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L +#endif + + /*************************************************************************/ /*************************************************************************/ /**** ****/ @@ -790,6 +832,33 @@ FT_BEGIN_HEADER /* #define CFF_CONFIG_OPTION_OLD_ENGINE */ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** P C F D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* There are many PCF fonts just called `Fixed' which look completely */ + /* different, and which have nothing to do with each other. When */ + /* selecting `Fixed' in KDE or Gnome one gets results that appear rather */ + /* random, the style changes often if one changes the size and one */ + /* cannot select some fonts at all. This option makes the PCF module */ + /* prepend the foundry name (plus a space) to the family name. */ + /* */ + /* We also check whether we have `wide' characters; all put together, we */ + /* get family names like `Sony Fixed' or `Misc Fixed Wide'. */ + /* */ + /* If this option is activated, it can be controlled with the */ + /* `no-long-family-names' property of the pcf driver module. */ + /* */ +/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + /*************************************************************************/ /*************************************************************************/ /**** ****/ @@ -808,7 +877,9 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ - /* Compile autofit module with Indic script support. */ + /* Compile autofit module with fallback Indic script support, covering */ + /* some scripts that the `latin' submodule of the autofit module doesn't */ + /* (yet) handle. */ /* */ #define AF_CONFIG_OPTION_INDIC @@ -827,6 +898,26 @@ FT_BEGIN_HEADER /* */ #define AF_CONFIG_OPTION_USE_WARPER + /*************************************************************************/ + /* */ + /* Use TrueType-like size metrics for `light' auto-hinting. */ + /* */ + /* It is strongly recommended to avoid this option, which exists only to */ + /* help some legacy applications retain its appearance and behaviour */ + /* with respect to auto-hinted TrueType fonts. */ + /* */ + /* The very reason this option exists at all are GNU/Linux distributions */ + /* like Fedora that did not un-patch the following change (which was */ + /* present in FreeType between versions 2.4.6 and 2.7.1, inclusive). */ + /* */ + /* 2011-07-16 Steven Chu */ + /* */ + /* [truetype] Fix metrics on size request for scalable fonts. */ + /* */ + /* This problematic commit is now reverted (more or less). */ + /* */ +/* #define AF_CONFIG_OPTION_TT_SIZE_METRICS */ + /* */ @@ -838,14 +929,19 @@ FT_BEGIN_HEADER /* - * This macro is defined if either unpatented or native TrueType - * hinting is requested by the definitions above. + * This macro is defined if native TrueType hinting is requested by the + * definitions above. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER -#undef TT_CONFIG_OPTION_UNPATENTED_HINTING -#elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING -#define TT_USE_BYTECODE_INTERPRETER + +#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 +#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY +#endif + +#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 +#define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL +#endif #endif @@ -880,7 +976,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* __FTOPTION_H__ */ +#endif /* FTOPTION_H_ */ /* END */ diff --git a/third_party/freetype/include/freetype/config/ftconfig.h b/third_party/freetype/include/freetype/config/ftconfig.h deleted file mode 100644 index d4d79936df1653891c953a1337394678583719ed..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/config/ftconfig.h +++ /dev/null @@ -1,467 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftconfig.h */ -/* */ -/* ANSI-specific configuration file (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This header file contains a number of macro definitions that are used */ - /* by the rest of the engine. Most of the macros here are automatically */ - /* determined at compile time, and you should not need to change it to */ - /* port FreeType, except to compile the library with a non-ANSI */ - /* compiler. */ - /* */ - /* Note however that if some specific modifications are needed, we */ - /* advise you to place a modified copy in your build directory. */ - /* */ - /* The build directory is usually `builds/', and contains */ - /* system-specific files that are always included first when building */ - /* the library. */ - /* */ - /* This ANSI version should stay in `include/config/'. */ - /* */ - /*************************************************************************/ - -#ifndef __FTCONFIG_H__ -#define __FTCONFIG_H__ - -#include -#include FT_CONFIG_OPTIONS_H -#include FT_CONFIG_STANDARD_LIBRARY_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ - /* */ - /* These macros can be toggled to suit a specific system. The current */ - /* ones are defaults used to compile FreeType in an ANSI C environment */ - /* (16bit compilers are also supported). Copy this file to your own */ - /* `builds/' directory, and edit it to port the engine. */ - /* */ - /*************************************************************************/ - - - /* There are systems (like the Texas Instruments 'C54x) where a `char' */ - /* has 16 bits. ANSI C says that sizeof(char) is always 1. Since an */ - /* `int' has 16 bits also for this system, sizeof(int) gives 1 which */ - /* is probably unexpected. */ - /* */ - /* `CHAR_BIT' (defined in limits.h) gives the number of bits in a */ - /* `char' type. */ - -#ifndef FT_CHAR_BIT -#define FT_CHAR_BIT CHAR_BIT -#endif - - - /* The size of an `int' type. */ -#if FT_UINT_MAX == 0xFFFFUL -#define FT_SIZEOF_INT (16 / FT_CHAR_BIT) -#elif FT_UINT_MAX == 0xFFFFFFFFUL -#define FT_SIZEOF_INT (32 / FT_CHAR_BIT) -#elif FT_UINT_MAX > 0xFFFFFFFFUL && FT_UINT_MAX == 0xFFFFFFFFFFFFFFFFUL -#define FT_SIZEOF_INT (64 / FT_CHAR_BIT) -#else -#error "Unsupported size of `int' type!" -#endif - - /* The size of a `long' type. A five-byte `long' (as used e.g. on the */ - /* DM642) is recognized but avoided. */ -#if FT_ULONG_MAX == 0xFFFFFFFFUL -#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT) -#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFUL -#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT) -#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL -#define FT_SIZEOF_LONG (64 / FT_CHAR_BIT) -#else -#error "Unsupported size of `long' type!" -#endif - - - /* FT_UNUSED is a macro used to indicate that a given parameter is not */ - /* used -- this is only used to get rid of unpleasant compiler warnings */ -#ifndef FT_UNUSED -#define FT_UNUSED( arg ) ( (arg) = (arg) ) -#endif - - - /*************************************************************************/ - /* */ - /* AUTOMATIC CONFIGURATION MACROS */ - /* */ - /* These macros are computed from the ones defined above. Don't touch */ - /* their definition, unless you know precisely what you are doing. No */ - /* porter should need to mess with them. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* Mac support */ - /* */ - /* This is the only necessary change, so it is defined here instead */ - /* providing a new configuration file. */ - /* */ -#if defined( __APPLE__ ) || ( defined( __MWERKS__ ) && defined( macintosh ) ) - /* no Carbon frameworks for 64bit 10.4.x */ - /* AvailabilityMacros.h is available since Mac OS X 10.2, */ - /* so guess the system version by maximum errno before inclusion */ -#include -#ifdef ECANCELED /* defined since 10.2 */ -#include "AvailabilityMacros.h" -#endif -#if defined( __LP64__ ) && \ - ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 ) -#undef FT_MACINTOSH -#endif - -#elif defined( __SC__ ) || defined( __MRC__ ) - /* Classic MacOS compilers */ -#include "ConditionalMacros.h" -#if TARGET_OS_MAC -#define FT_MACINTOSH 1 -#endif - -#endif - - - /*************************************************************************/ - /* */ - /*
*/ - /* basic_types */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Int16 */ - /* */ - /* */ - /* A typedef for a 16bit signed integer type. */ - /* */ - typedef signed short FT_Int16; - - - /*************************************************************************/ - /* */ - /* */ - /* FT_UInt16 */ - /* */ - /* */ - /* A typedef for a 16bit unsigned integer type. */ - /* */ - typedef unsigned short FT_UInt16; - - /* */ - - - /* this #if 0 ... #endif clause is for documentation purposes */ -#if 0 - - /*************************************************************************/ - /* */ - /* */ - /* FT_Int32 */ - /* */ - /* */ - /* A typedef for a 32bit signed integer type. The size depends on */ - /* the configuration. */ - /* */ - typedef signed XXX FT_Int32; - - - /*************************************************************************/ - /* */ - /* */ - /* FT_UInt32 */ - /* */ - /* A typedef for a 32bit unsigned integer type. The size depends on */ - /* the configuration. */ - /* */ - typedef unsigned XXX FT_UInt32; - - - /*************************************************************************/ - /* */ - /* */ - /* FT_Int64 */ - /* */ - /* A typedef for a 64bit signed integer type. The size depends on */ - /* the configuration. Only defined if there is real 64bit support; */ - /* otherwise, it gets emulated with a structure (if necessary). */ - /* */ - typedef signed XXX FT_Int64; - - - /*************************************************************************/ - /* */ - /* */ - /* FT_UInt64 */ - /* */ - /* A typedef for a 64bit unsigned integer type. The size depends on */ - /* the configuration. Only defined if there is real 64bit support; */ - /* otherwise, it gets emulated with a structure (if necessary). */ - /* */ - typedef unsigned XXX FT_UInt64; - - /* */ - -#endif - -#if FT_SIZEOF_INT == (32 / FT_CHAR_BIT) - - typedef signed int FT_Int32; - typedef unsigned int FT_UInt32; - -#elif FT_SIZEOF_LONG == (32 / FT_CHAR_BIT) - - typedef signed long FT_Int32; - typedef unsigned long FT_UInt32; - -#else -#error "no 32bit type found -- please check your configuration files" -#endif - - - /* look up an integer type that is at least 32 bits */ -#if FT_SIZEOF_INT >= (32 / FT_CHAR_BIT) - - typedef int FT_Fast; - typedef unsigned int FT_UFast; - -#elif FT_SIZEOF_LONG >= (32 / FT_CHAR_BIT) - - typedef long FT_Fast; - typedef unsigned long FT_UFast; - -#endif - - - /* determine whether we have a 64-bit int type for platforms without */ - /* Autoconf */ -#if FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) - - /* FT_LONG64 must be defined if a 64-bit type is available */ -#define FT_LONG64 -#define FT_INT64 long -#define FT_UINT64 unsigned long - - /*************************************************************************/ - /* */ - /* A 64-bit data type may create compilation problems if you compile */ - /* in strict ANSI mode. To avoid them, we disable other 64-bit data */ - /* types if __STDC__ is defined. You can however ignore this rule */ - /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ - /* */ -#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 ) - -#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ - - /* this compiler provides the __int64 type */ -#define FT_LONG64 -#define FT_INT64 __int64 -#define FT_UINT64 unsigned __int64 - -#elif defined( __BORLANDC__ ) /* Borland C++ */ - - /* XXXX: We should probably check the value of __BORLANDC__ in order */ - /* to test the compiler version. */ - - /* this compiler provides the __int64 type */ -#define FT_LONG64 -#define FT_INT64 __int64 -#define FT_UINT64 unsigned __int64 - -#elif defined( __WATCOMC__ ) /* Watcom C++ */ - - /* Watcom doesn't provide 64-bit data types */ - -#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */ - -#define FT_LONG64 -#define FT_INT64 long long int -#define FT_UINT64 unsigned long long int - -#elif defined( __GNUC__ ) - - /* GCC provides the `long long' type */ -#define FT_LONG64 -#define FT_INT64 long long int -#define FT_UINT64 unsigned long long int - -#endif /* _MSC_VER */ - -#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ - -#ifdef FT_LONG64 - typedef FT_INT64 FT_Int64; - typedef FT_UINT64 FT_UInt64; -#endif - - - /*************************************************************************/ - /* */ - /* miscellaneous */ - /* */ - /*************************************************************************/ - - -#define FT_BEGIN_STMNT do { -#define FT_END_STMNT } while ( 0 ) -#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT - - - /* typeof condition taken from gnulib's `intprops.h' header file */ -#if ( __GNUC__ >= 2 || \ - defined( __IBM__TYPEOF__ ) || \ - ( __SUNPRO_C >= 0x5110 && !__STDC__ ) ) -#define FT_TYPEOF( type ) (__typeof__ (type)) -#else -#define FT_TYPEOF( type ) /* empty */ -#endif - - -#ifdef FT_MAKE_OPTION_SINGLE_OBJECT - -#define FT_LOCAL( x ) static x -#define FT_LOCAL_DEF( x ) static x - -#else - -#ifdef __cplusplus -#define FT_LOCAL( x ) extern "C" x -#define FT_LOCAL_DEF( x ) extern "C" x -#else -#define FT_LOCAL( x ) extern x -#define FT_LOCAL_DEF( x ) x -#endif - -#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */ - -#define FT_LOCAL_ARRAY( x ) extern const x -#define FT_LOCAL_ARRAY_DEF( x ) const x - - -#ifndef FT_BASE - -#ifdef __cplusplus -#define FT_BASE( x ) extern "C" x -#else -#define FT_BASE( x ) extern x -#endif - -#endif /* !FT_BASE */ - - -#ifndef FT_BASE_DEF - -#ifdef __cplusplus -#define FT_BASE_DEF( x ) x -#else -#define FT_BASE_DEF( x ) x -#endif - -#endif /* !FT_BASE_DEF */ - - -#ifndef FT_EXPORT - -#ifdef __cplusplus -#define FT_EXPORT( x ) extern "C" x -#else -#define FT_EXPORT( x ) extern x -#endif - -#endif /* !FT_EXPORT */ - - -#ifndef FT_EXPORT_DEF - -#ifdef __cplusplus -#define FT_EXPORT_DEF( x ) extern "C" x -#else -#define FT_EXPORT_DEF( x ) extern x -#endif - -#endif /* !FT_EXPORT_DEF */ - - -#ifndef FT_EXPORT_VAR - -#ifdef __cplusplus -#define FT_EXPORT_VAR( x ) extern "C" x -#else -#define FT_EXPORT_VAR( x ) extern x -#endif - -#endif /* !FT_EXPORT_VAR */ - - /* The following macros are needed to compile the library with a */ - /* C++ compiler and with 16bit compilers. */ - /* */ - - /* This is special. Within C++, you must specify `extern "C"' for */ - /* functions which are used via function pointers, and you also */ - /* must do that for structures which contain function pointers to */ - /* assure C linkage -- it's not possible to have (local) anonymous */ - /* functions which are accessed by (global) function pointers. */ - /* */ - /* */ - /* FT_CALLBACK_DEF is used to _define_ a callback function. */ - /* */ - /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */ - /* contains pointers to callback functions. */ - /* */ - /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */ - /* that contains pointers to callback functions. */ - /* */ - /* */ - /* Some 16bit compilers have to redefine these macros to insert */ - /* the infamous `_cdecl' or `__fastcall' declarations. */ - /* */ -#ifndef FT_CALLBACK_DEF -#ifdef __cplusplus -#define FT_CALLBACK_DEF( x ) extern "C" x -#else -#define FT_CALLBACK_DEF( x ) static x -#endif -#endif /* FT_CALLBACK_DEF */ - -#ifndef FT_CALLBACK_TABLE -#ifdef __cplusplus -#define FT_CALLBACK_TABLE extern "C" -#define FT_CALLBACK_TABLE_DEF extern "C" -#else -#define FT_CALLBACK_TABLE extern -#define FT_CALLBACK_TABLE_DEF /* nothing */ -#endif -#endif /* FT_CALLBACK_TABLE */ - - -FT_END_HEADER - - -#endif /* __FTCONFIG_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/config/ftheader.h b/third_party/freetype/include/freetype/config/ftheader.h deleted file mode 100644 index 55f833db0fb52bee8ee9df8c498f16c05f98397c..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/config/ftheader.h +++ /dev/null @@ -1,834 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftheader.h */ -/* */ -/* Build macros of the FreeType 2 library. */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#ifndef __FT_HEADER_H__ -#define __FT_HEADER_H__ - - - /*@***********************************************************************/ - /* */ - /* */ - /* FT_BEGIN_HEADER */ - /* */ - /* */ - /* This macro is used in association with @FT_END_HEADER in header */ - /* files to ensure that the declarations within are properly */ - /* encapsulated in an `extern "C" { .. }' block when included from a */ - /* C++ compiler. */ - /* */ -#ifdef __cplusplus -#define FT_BEGIN_HEADER extern "C" { -#else -#define FT_BEGIN_HEADER /* nothing */ -#endif - - - /*@***********************************************************************/ - /* */ - /* */ - /* FT_END_HEADER */ - /* */ - /* */ - /* This macro is used in association with @FT_BEGIN_HEADER in header */ - /* files to ensure that the declarations within are properly */ - /* encapsulated in an `extern "C" { .. }' block when included from a */ - /* C++ compiler. */ - /* */ -#ifdef __cplusplus -#define FT_END_HEADER } -#else -#define FT_END_HEADER /* nothing */ -#endif - - - /*************************************************************************/ - /* */ - /* Aliases for the FreeType 2 public and configuration files. */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /*
*/ - /* header_file_macros */ - /* */ - /* */ - /* Header File Macros */ - /* */ - /* <Abstract> */ - /* Macro definitions used to #include specific header files. */ - /* */ - /* <Description> */ - /* The following macros are defined to the name of specific */ - /* FreeType~2 header files. They can be used directly in #include */ - /* statements as in: */ - /* */ - /* { */ - /* #include FT_FREETYPE_H */ - /* #include FT_MULTIPLE_MASTERS_H */ - /* #include FT_GLYPH_H */ - /* } */ - /* */ - /* There are several reasons why we are now using macros to name */ - /* public header files. The first one is that such macros are not */ - /* limited to the infamous 8.3~naming rule required by DOS (and */ - /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */ - /* */ - /* The second reason is that it allows for more flexibility in the */ - /* way FreeType~2 is installed on a given system. */ - /* */ - /*************************************************************************/ - - - /* configuration files */ - - /************************************************************************* - * - * @macro: - * FT_CONFIG_CONFIG_H - * - * @description: - * A macro used in #include statements to name the file containing - * FreeType~2 configuration data. - * - */ -#ifndef FT_CONFIG_CONFIG_H -#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h> -#endif - - - /************************************************************************* - * - * @macro: - * FT_CONFIG_STANDARD_LIBRARY_H - * - * @description: - * A macro used in #include statements to name the file containing - * FreeType~2 interface to the standard C library functions. - * - */ -#ifndef FT_CONFIG_STANDARD_LIBRARY_H -#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h> -#endif - - - /************************************************************************* - * - * @macro: - * FT_CONFIG_OPTIONS_H - * - * @description: - * A macro used in #include statements to name the file containing - * FreeType~2 project-specific configuration options. - * - */ -#ifndef FT_CONFIG_OPTIONS_H -#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h> -#endif - - - /************************************************************************* - * - * @macro: - * FT_CONFIG_MODULES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * list of FreeType~2 modules that are statically linked to new library - * instances in @FT_Init_FreeType. - * - */ -#ifndef FT_CONFIG_MODULES_H -#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h> -#endif - - /* */ - - /* public headers */ - - /************************************************************************* - * - * @macro: - * FT_FREETYPE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * base FreeType~2 API. - * - */ -#define FT_FREETYPE_H <freetype/freetype.h> - - - /************************************************************************* - * - * @macro: - * FT_ERRORS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * list of FreeType~2 error codes (and messages). - * - * It is included by @FT_FREETYPE_H. - * - */ -#define FT_ERRORS_H <freetype/fterrors.h> - - - /************************************************************************* - * - * @macro: - * FT_MODULE_ERRORS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * list of FreeType~2 module error offsets (and messages). - * - */ -#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h> - - - /************************************************************************* - * - * @macro: - * FT_SYSTEM_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 interface to low-level operations (i.e., memory management - * and stream i/o). - * - * It is included by @FT_FREETYPE_H. - * - */ -#define FT_SYSTEM_H <freetype/ftsystem.h> - - - /************************************************************************* - * - * @macro: - * FT_IMAGE_H - * - * @description: - * A macro used in #include statements to name the file containing type - * definitions related to glyph images (i.e., bitmaps, outlines, - * scan-converter parameters). - * - * It is included by @FT_FREETYPE_H. - * - */ -#define FT_IMAGE_H <freetype/ftimage.h> - - - /************************************************************************* - * - * @macro: - * FT_TYPES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * basic data types defined by FreeType~2. - * - * It is included by @FT_FREETYPE_H. - * - */ -#define FT_TYPES_H <freetype/fttypes.h> - - - /************************************************************************* - * - * @macro: - * FT_LIST_H - * - * @description: - * A macro used in #include statements to name the file containing the - * list management API of FreeType~2. - * - * (Most applications will never need to include this file.) - * - */ -#define FT_LIST_H <freetype/ftlist.h> - - - /************************************************************************* - * - * @macro: - * FT_OUTLINE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * scalable outline management API of FreeType~2. - * - */ -#define FT_OUTLINE_H <freetype/ftoutln.h> - - - /************************************************************************* - * - * @macro: - * FT_SIZES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * API which manages multiple @FT_Size objects per face. - * - */ -#define FT_SIZES_H <freetype/ftsizes.h> - - - /************************************************************************* - * - * @macro: - * FT_MODULE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * module management API of FreeType~2. - * - */ -#define FT_MODULE_H <freetype/ftmodapi.h> - - - /************************************************************************* - * - * @macro: - * FT_RENDER_H - * - * @description: - * A macro used in #include statements to name the file containing the - * renderer module management API of FreeType~2. - * - */ -#define FT_RENDER_H <freetype/ftrender.h> - - - /************************************************************************* - * - * @macro: - * FT_AUTOHINTER_H - * - * @description: - * A macro used in #include statements to name the file containing - * structures and macros related to the auto-hinting module. - * - */ -#define FT_AUTOHINTER_H <freetype/ftautoh.h> - - - /************************************************************************* - * - * @macro: - * FT_CFF_DRIVER_H - * - * @description: - * A macro used in #include statements to name the file containing - * structures and macros related to the CFF driver module. - * - */ -#define FT_CFF_DRIVER_H <freetype/ftcffdrv.h> - - - /************************************************************************* - * - * @macro: - * FT_TRUETYPE_DRIVER_H - * - * @description: - * A macro used in #include statements to name the file containing - * structures and macros related to the TrueType driver module. - * - */ -#define FT_TRUETYPE_DRIVER_H <freetype/ftttdrv.h> - - - /************************************************************************* - * - * @macro: - * FT_TYPE1_TABLES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * types and API specific to the Type~1 format. - * - */ -#define FT_TYPE1_TABLES_H <freetype/t1tables.h> - - - /************************************************************************* - * - * @macro: - * FT_TRUETYPE_IDS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * enumeration values which identify name strings, languages, encodings, - * etc. This file really contains a _large_ set of constant macro - * definitions, taken from the TrueType and OpenType specifications. - * - */ -#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h> - - - /************************************************************************* - * - * @macro: - * FT_TRUETYPE_TABLES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * types and API specific to the TrueType (as well as OpenType) format. - * - */ -#define FT_TRUETYPE_TABLES_H <freetype/tttables.h> - - - /************************************************************************* - * - * @macro: - * FT_TRUETYPE_TAGS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of TrueType four-byte `tags' which identify blocks in - * SFNT-based font formats (i.e., TrueType and OpenType). - * - */ -#define FT_TRUETYPE_TAGS_H <freetype/tttags.h> - - - /************************************************************************* - * - * @macro: - * FT_BDF_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of an API which accesses BDF-specific strings from a - * face. - * - */ -#define FT_BDF_H <freetype/ftbdf.h> - - - /************************************************************************* - * - * @macro: - * FT_CID_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of an API which access CID font information from a - * face. - * - */ -#define FT_CID_H <freetype/ftcid.h> - - - /************************************************************************* - * - * @macro: - * FT_GZIP_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of an API which supports gzip-compressed files. - * - */ -#define FT_GZIP_H <freetype/ftgzip.h> - - - /************************************************************************* - * - * @macro: - * FT_LZW_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of an API which supports LZW-compressed files. - * - */ -#define FT_LZW_H <freetype/ftlzw.h> - - - /************************************************************************* - * - * @macro: - * FT_BZIP2_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of an API which supports bzip2-compressed files. - * - */ -#define FT_BZIP2_H <freetype/ftbzip2.h> - - - /************************************************************************* - * - * @macro: - * FT_WINFONTS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * definitions of an API which supports Windows FNT files. - * - */ -#define FT_WINFONTS_H <freetype/ftwinfnt.h> - - - /************************************************************************* - * - * @macro: - * FT_GLYPH_H - * - * @description: - * A macro used in #include statements to name the file containing the - * API of the optional glyph management component. - * - */ -#define FT_GLYPH_H <freetype/ftglyph.h> - - - /************************************************************************* - * - * @macro: - * FT_BITMAP_H - * - * @description: - * A macro used in #include statements to name the file containing the - * API of the optional bitmap conversion component. - * - */ -#define FT_BITMAP_H <freetype/ftbitmap.h> - - - /************************************************************************* - * - * @macro: - * FT_BBOX_H - * - * @description: - * A macro used in #include statements to name the file containing the - * API of the optional exact bounding box computation routines. - * - */ -#define FT_BBOX_H <freetype/ftbbox.h> - - - /************************************************************************* - * - * @macro: - * FT_CACHE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * API of the optional FreeType~2 cache sub-system. - * - */ -#define FT_CACHE_H <freetype/ftcache.h> - - - /************************************************************************* - * - * @macro: - * FT_CACHE_IMAGE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * `glyph image' API of the FreeType~2 cache sub-system. - * - * It is used to define a cache for @FT_Glyph elements. You can also - * use the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need to - * store small glyph bitmaps, as it will use less memory. - * - * This macro is deprecated. Simply include @FT_CACHE_H to have all - * glyph image-related cache declarations. - * - */ -#define FT_CACHE_IMAGE_H FT_CACHE_H - - - /************************************************************************* - * - * @macro: - * FT_CACHE_SMALL_BITMAPS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * `small bitmaps' API of the FreeType~2 cache sub-system. - * - * It is used to define a cache for small glyph bitmaps in a relatively - * memory-efficient way. You can also use the API defined in - * @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images, - * including scalable outlines. - * - * This macro is deprecated. Simply include @FT_CACHE_H to have all - * small bitmaps-related cache declarations. - * - */ -#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H - - - /************************************************************************* - * - * @macro: - * FT_CACHE_CHARMAP_H - * - * @description: - * A macro used in #include statements to name the file containing the - * `charmap' API of the FreeType~2 cache sub-system. - * - * This macro is deprecated. Simply include @FT_CACHE_H to have all - * charmap-based cache declarations. - * - */ -#define FT_CACHE_CHARMAP_H FT_CACHE_H - - - /************************************************************************* - * - * @macro: - * FT_MAC_H - * - * @description: - * A macro used in #include statements to name the file containing the - * Macintosh-specific FreeType~2 API. The latter is used to access - * fonts embedded in resource forks. - * - * This header file must be explicitly included by client applications - * compiled on the Mac (note that the base API still works though). - * - */ -#define FT_MAC_H <freetype/ftmac.h> - - - /************************************************************************* - * - * @macro: - * FT_MULTIPLE_MASTERS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * optional multiple-masters management API of FreeType~2. - * - */ -#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h> - - - /************************************************************************* - * - * @macro: - * FT_SFNT_NAMES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * optional FreeType~2 API which accesses embedded `name' strings in - * SFNT-based font formats (i.e., TrueType and OpenType). - * - */ -#define FT_SFNT_NAMES_H <freetype/ftsnames.h> - - - /************************************************************************* - * - * @macro: - * FT_OPENTYPE_VALIDATE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * optional FreeType~2 API which validates OpenType tables (BASE, GDEF, - * GPOS, GSUB, JSTF). - * - */ -#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h> - - - /************************************************************************* - * - * @macro: - * FT_GX_VALIDATE_H - * - * @description: - * A macro used in #include statements to name the file containing the - * optional FreeType~2 API which validates TrueTypeGX/AAT tables (feat, - * mort, morx, bsln, just, kern, opbd, trak, prop). - * - */ -#define FT_GX_VALIDATE_H <freetype/ftgxval.h> - - - /************************************************************************* - * - * @macro: - * FT_PFR_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which accesses PFR-specific data. - * - */ -#define FT_PFR_H <freetype/ftpfr.h> - - - /************************************************************************* - * - * @macro: - * FT_STROKER_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which provides functions to stroke outline paths. - */ -#define FT_STROKER_H <freetype/ftstroke.h> - - - /************************************************************************* - * - * @macro: - * FT_SYNTHESIS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which performs artificial obliquing and emboldening. - */ -#define FT_SYNTHESIS_H <freetype/ftsynth.h> - - - /************************************************************************* - * - * @macro: - * FT_FONT_FORMATS_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which provides functions specific to font formats. - */ -#define FT_FONT_FORMATS_H <freetype/ftfntfmt.h> - - /* deprecated */ -#define FT_XFREE86_H FT_FONT_FORMATS_H - - - /************************************************************************* - * - * @macro: - * FT_TRIGONOMETRY_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which performs trigonometric computations (e.g., - * cosines and arc tangents). - */ -#define FT_TRIGONOMETRY_H <freetype/fttrigon.h> - - - /************************************************************************* - * - * @macro: - * FT_LCD_FILTER_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which performs color filtering for subpixel rendering. - */ -#define FT_LCD_FILTER_H <freetype/ftlcdfil.h> - - - /************************************************************************* - * - * @macro: - * FT_UNPATENTED_HINTING_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which performs color filtering for subpixel rendering. - */ -#define FT_UNPATENTED_HINTING_H <freetype/ttunpat.h> - - - /************************************************************************* - * - * @macro: - * FT_INCREMENTAL_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which performs color filtering for subpixel rendering. - */ -#define FT_INCREMENTAL_H <freetype/ftincrem.h> - - - /************************************************************************* - * - * @macro: - * FT_GASP_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which returns entries from the TrueType GASP table. - */ -#define FT_GASP_H <freetype/ftgasp.h> - - - /************************************************************************* - * - * @macro: - * FT_ADVANCES_H - * - * @description: - * A macro used in #include statements to name the file containing the - * FreeType~2 API which returns individual and ranged glyph advances. - */ -#define FT_ADVANCES_H <freetype/ftadvanc.h> - - - /* */ - -#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h> - - - /* The internals of the cache sub-system are no longer exposed. We */ - /* default to FT_CACHE_H at the moment just in case, but we know of */ - /* no rogue client that uses them. */ - /* */ -#define FT_CACHE_MANAGER_H <freetype/ftcache.h> -#define FT_CACHE_INTERNAL_MRU_H <freetype/ftcache.h> -#define FT_CACHE_INTERNAL_MANAGER_H <freetype/ftcache.h> -#define FT_CACHE_INTERNAL_CACHE_H <freetype/ftcache.h> -#define FT_CACHE_INTERNAL_GLYPH_H <freetype/ftcache.h> -#define FT_CACHE_INTERNAL_IMAGE_H <freetype/ftcache.h> -#define FT_CACHE_INTERNAL_SBITS_H <freetype/ftcache.h> - - -#define FT_INCREMENTAL_H <freetype/ftincrem.h> - -#define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h> - - - /* - * Include internal headers definitions from <internal/...> - * only when building the library. - */ -#ifdef FT2_BUILD_LIBRARY -#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h> -#include FT_INTERNAL_INTERNAL_H -#endif /* FT2_BUILD_LIBRARY */ - - -#endif /* __FT2_BUILD_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/config/ftmodule.h b/third_party/freetype/include/freetype/config/ftmodule.h deleted file mode 100644 index fb255743a7d7f2a1061b28887bfe1793d943f2f4..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/config/ftmodule.h +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmodule.h */ -/* */ -/* FreeType modules public interface (specification). */ -/* */ -/* Copyright 1996-2001, 2002, 2003 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/* - * This file registers the FreeType modules compiled into the library. - * - * If you use GNU make, this file IS NOT USED! Instead, it is created in - * the objects directory (normally `<topdir>/objs/') based on information - * from `<topdir>/modules.cfg'. - * - * Please read `docs/INSTALL.ANY' and `docs/CUSTOMIZE' how to compile - * FreeType without GNU make. - * - */ - -//FT_USE_MODULE( FT_Module_Class, autofit_module_class ) -FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) -//FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) -//FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) -//FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) -//FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) -FT_USE_MODULE( FT_Module_Class, psaux_module_class ) -FT_USE_MODULE( FT_Module_Class, psnames_module_class ) -FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) -FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) -//FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) - -/* EOF */ diff --git a/third_party/freetype/include/freetype/config/ftstdlib.h b/third_party/freetype/include/freetype/config/ftstdlib.h deleted file mode 100644 index 4b471d4d15d2b8c8a5247e5918e37500aca9e4d1..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/config/ftstdlib.h +++ /dev/null @@ -1,174 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftstdlib.h */ -/* */ -/* ANSI-specific library and header configuration file (specification */ -/* only). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to group all #includes to the ANSI C library that */ - /* FreeType normally requires. It also defines macros to rename the */ - /* standard functions within the FreeType source code. */ - /* */ - /* Load a file which defines __FTSTDLIB_H__ before this one to override */ - /* it. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTSTDLIB_H__ -#define __FTSTDLIB_H__ - - -#include <stddef.h> - -#define ft_ptrdiff_t ptrdiff_t - - - /**********************************************************************/ - /* */ - /* integer limits */ - /* */ - /* UINT_MAX and ULONG_MAX are used to automatically compute the size */ - /* of `int' and `long' in bytes at compile-time. So far, this works */ - /* for all platforms the library has been tested on. */ - /* */ - /* Note that on the extremely rare platforms that do not provide */ - /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */ - /* old Crays where `int' is 36 bits), we do not make any guarantee */ - /* about the correct behaviour of FT2 with all fonts. */ - /* */ - /* In these case, `ftconfig.h' will refuse to compile anyway with a */ - /* message like `couldn't find 32-bit type' or something similar. */ - /* */ - /**********************************************************************/ - - -#include <limits.h> - -#define FT_CHAR_BIT CHAR_BIT -#define FT_USHORT_MAX USHRT_MAX -#define FT_INT_MAX INT_MAX -#define FT_INT_MIN INT_MIN -#define FT_UINT_MAX UINT_MAX -#define FT_LONG_MAX LONG_MAX -#define FT_ULONG_MAX ULONG_MAX - - - /**********************************************************************/ - /* */ - /* character and string processing */ - /* */ - /**********************************************************************/ - - -#include <string.h> - -#define ft_memchr memchr -#define ft_memcmp memcmp -#define ft_memcpy memcpy -#define ft_memmove memmove -#define ft_memset memset -#define ft_strcat strcat -#define ft_strcmp strcmp -#define ft_strcpy strcpy -#define ft_strlen strlen -#define ft_strncmp strncmp -#define ft_strncpy strncpy -#define ft_strrchr strrchr -#define ft_strstr strstr - - - /**********************************************************************/ - /* */ - /* file handling */ - /* */ - /**********************************************************************/ - - -#include <stdio.h> - -#define FT_FILE FILE -#define ft_fclose fclose -#define ft_fopen fopen -#define ft_fread fread -#define ft_fseek fseek -#define ft_ftell ftell -#define ft_sprintf sprintf - - - /**********************************************************************/ - /* */ - /* sorting */ - /* */ - /**********************************************************************/ - - -#include <stdlib.h> - -#define ft_qsort qsort - - - /**********************************************************************/ - /* */ - /* memory allocation */ - /* */ - /**********************************************************************/ - - -#define ft_scalloc calloc -#define ft_sfree free -#define ft_smalloc malloc -#define ft_srealloc realloc - - - /**********************************************************************/ - /* */ - /* miscellaneous */ - /* */ - /**********************************************************************/ - - -#define ft_atol atol - - - /**********************************************************************/ - /* */ - /* execution control */ - /* */ - /**********************************************************************/ - - -#include <setjmp.h> - -#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */ - /* jmp_buf is defined as a macro */ - /* on certain platforms */ - -#define ft_longjmp longjmp -#define ft_setjmp( b ) setjmp( *(ft_jmp_buf*) &(b) ) /* same thing here */ - - - /* the following is only used for debugging purposes, i.e., if */ - /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */ - -#include <stdarg.h> - - -#endif /* __FTSTDLIB_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/freetype.h b/third_party/freetype/include/freetype/freetype.h deleted file mode 100644 index b6247f510f030306b62a81f5ebb039354d8e68bd..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/freetype.h +++ /dev/null @@ -1,4204 +0,0 @@ -/***************************************************************************/ -/* */ -/* freetype.h */ -/* */ -/* FreeType high-level API and common types (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FREETYPE_H__ -#define __FREETYPE_H__ - - -#ifndef FT_FREETYPE_H -#error "`ft2build.h' hasn't been included yet!" -#error "Please always use macros to include FreeType header files." -#error "Example:" -#error " #include <ft2build.h>" -#error " #include FT_FREETYPE_H" -#endif - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_TYPES_H -#include FT_ERRORS_H - - -FT_BEGIN_HEADER - - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* header_inclusion */ - /* */ - /* <Title> */ - /* FreeType's header inclusion scheme */ - /* */ - /* <Abstract> */ - /* How client applications should include FreeType header files. */ - /* */ - /* <Description> */ - /* To be as flexible as possible (and for historical reasons), */ - /* FreeType uses a very special inclusion scheme to load header */ - /* files, for example */ - /* */ - /* { */ - /* #include <ft2build.h> */ - /* */ - /* #include FT_FREETYPE_H */ - /* #include FT_OUTLINE_H */ - /* } */ - /* */ - /* A compiler and its preprocessor only needs an include path to find */ - /* the file `ft2build.h'; the exact locations and names of the other */ - /* FreeType header files are hidden by preprocessor macro names, */ - /* loaded by `ft2build.h'. The API documentation always gives the */ - /* header macro name needed for a particular function. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* user_allocation */ - /* */ - /* <Title> */ - /* User allocation */ - /* */ - /* <Abstract> */ - /* How client applications should allocate FreeType data structures. */ - /* */ - /* <Description> */ - /* FreeType assumes that structures allocated by the user and passed */ - /* as arguments are zeroed out except for the actual data. In other */ - /* words, it is recommended to use `calloc' (or variants of it) */ - /* instead of `malloc' for allocation. */ - /* */ - /*************************************************************************/ - - - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* B A S I C T Y P E S */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* base_interface */ - /* */ - /* <Title> */ - /* Base Interface */ - /* */ - /* <Abstract> */ - /* The FreeType~2 base font interface. */ - /* */ - /* <Description> */ - /* This section describes the most important public high-level API */ - /* functions of FreeType~2. */ - /* */ - /* <Order> */ - /* FT_Library */ - /* FT_Face */ - /* FT_Size */ - /* FT_GlyphSlot */ - /* FT_CharMap */ - /* FT_Encoding */ - /* FT_ENC_TAG */ - /* */ - /* FT_FaceRec */ - /* */ - /* FT_FACE_FLAG_SCALABLE */ - /* FT_FACE_FLAG_FIXED_SIZES */ - /* FT_FACE_FLAG_FIXED_WIDTH */ - /* FT_FACE_FLAG_HORIZONTAL */ - /* FT_FACE_FLAG_VERTICAL */ - /* FT_FACE_FLAG_COLOR */ - /* FT_FACE_FLAG_SFNT */ - /* FT_FACE_FLAG_CID_KEYED */ - /* FT_FACE_FLAG_TRICKY */ - /* FT_FACE_FLAG_KERNING */ - /* FT_FACE_FLAG_MULTIPLE_MASTERS */ - /* FT_FACE_FLAG_GLYPH_NAMES */ - /* FT_FACE_FLAG_EXTERNAL_STREAM */ - /* FT_FACE_FLAG_HINTER */ - /* FT_FACE_FLAG_TRICKY */ - /* */ - /* FT_HAS_HORIZONTAL */ - /* FT_HAS_VERTICAL */ - /* FT_HAS_KERNING */ - /* FT_HAS_FIXED_SIZES */ - /* FT_HAS_GLYPH_NAMES */ - /* FT_HAS_MULTIPLE_MASTERS */ - /* FT_HAS_COLOR */ - /* */ - /* FT_IS_SFNT */ - /* FT_IS_SCALABLE */ - /* FT_IS_FIXED_WIDTH */ - /* FT_IS_CID_KEYED */ - /* FT_IS_TRICKY */ - /* */ - /* FT_STYLE_FLAG_BOLD */ - /* FT_STYLE_FLAG_ITALIC */ - /* */ - /* FT_SizeRec */ - /* FT_Size_Metrics */ - /* */ - /* FT_GlyphSlotRec */ - /* FT_Glyph_Metrics */ - /* FT_SubGlyph */ - /* */ - /* FT_Bitmap_Size */ - /* */ - /* FT_Init_FreeType */ - /* FT_Done_FreeType */ - /* */ - /* FT_New_Face */ - /* FT_Done_Face */ - /* FT_Reference_Face */ - /* FT_New_Memory_Face */ - /* FT_Open_Face */ - /* FT_Open_Args */ - /* FT_Parameter */ - /* FT_Attach_File */ - /* FT_Attach_Stream */ - /* */ - /* FT_Set_Char_Size */ - /* FT_Set_Pixel_Sizes */ - /* FT_Request_Size */ - /* FT_Select_Size */ - /* FT_Size_Request_Type */ - /* FT_Size_RequestRec */ - /* FT_Size_Request */ - /* FT_Set_Transform */ - /* FT_Load_Glyph */ - /* FT_Get_Char_Index */ - /* FT_Get_First_Char */ - /* FT_Get_Next_Char */ - /* FT_Get_Name_Index */ - /* FT_Load_Char */ - /* */ - /* FT_OPEN_MEMORY */ - /* FT_OPEN_STREAM */ - /* FT_OPEN_PATHNAME */ - /* FT_OPEN_DRIVER */ - /* FT_OPEN_PARAMS */ - /* */ - /* FT_LOAD_DEFAULT */ - /* FT_LOAD_RENDER */ - /* FT_LOAD_MONOCHROME */ - /* FT_LOAD_LINEAR_DESIGN */ - /* FT_LOAD_NO_SCALE */ - /* FT_LOAD_NO_HINTING */ - /* FT_LOAD_NO_BITMAP */ - /* FT_LOAD_NO_AUTOHINT */ - /* FT_LOAD_COLOR */ - /* */ - /* FT_LOAD_VERTICAL_LAYOUT */ - /* FT_LOAD_IGNORE_TRANSFORM */ - /* FT_LOAD_FORCE_AUTOHINT */ - /* FT_LOAD_NO_RECURSE */ - /* FT_LOAD_PEDANTIC */ - /* */ - /* FT_LOAD_TARGET_NORMAL */ - /* FT_LOAD_TARGET_LIGHT */ - /* FT_LOAD_TARGET_MONO */ - /* FT_LOAD_TARGET_LCD */ - /* FT_LOAD_TARGET_LCD_V */ - /* */ - /* FT_LOAD_TARGET_MODE */ - /* */ - /* FT_Render_Glyph */ - /* FT_Render_Mode */ - /* FT_Get_Kerning */ - /* FT_Kerning_Mode */ - /* FT_Get_Track_Kerning */ - /* FT_Get_Glyph_Name */ - /* FT_Get_Postscript_Name */ - /* */ - /* FT_CharMapRec */ - /* FT_Select_Charmap */ - /* FT_Set_Charmap */ - /* FT_Get_Charmap_Index */ - /* */ - /* FT_Get_FSType_Flags */ - /* FT_Get_SubGlyph_Info */ - /* */ - /* FT_Face_Internal */ - /* FT_Size_Internal */ - /* FT_Slot_Internal */ - /* */ - /* FT_FACE_FLAG_XXX */ - /* FT_STYLE_FLAG_XXX */ - /* FT_OPEN_XXX */ - /* FT_LOAD_XXX */ - /* FT_LOAD_TARGET_XXX */ - /* FT_SUBGLYPH_FLAG_XXX */ - /* FT_FSTYPE_XXX */ - /* */ - /* FT_HAS_FAST_GLYPHS */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Glyph_Metrics */ - /* */ - /* <Description> */ - /* A structure used to model the metrics of a single glyph. The */ - /* values are expressed in 26.6 fractional pixel format; if the flag */ - /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */ - /* are expressed in font units instead. */ - /* */ - /* <Fields> */ - /* width :: */ - /* The glyph's width. */ - /* */ - /* height :: */ - /* The glyph's height. */ - /* */ - /* horiBearingX :: */ - /* Left side bearing for horizontal layout. */ - /* */ - /* horiBearingY :: */ - /* Top side bearing for horizontal layout. */ - /* */ - /* horiAdvance :: */ - /* Advance width for horizontal layout. */ - /* */ - /* vertBearingX :: */ - /* Left side bearing for vertical layout. */ - /* */ - /* vertBearingY :: */ - /* Top side bearing for vertical layout. Larger positive values */ - /* mean further below the vertical glyph origin. */ - /* */ - /* vertAdvance :: */ - /* Advance height for vertical layout. Positive values mean the */ - /* glyph has a positive advance downward. */ - /* */ - /* <Note> */ - /* If not disabled with @FT_LOAD_NO_HINTING, the values represent */ - /* dimensions of the hinted glyph (in case hinting is applicable). */ - /* */ - /* Stroking a glyph with an outside border does not increase */ - /* `horiAdvance' or `vertAdvance'; you have to manually adjust these */ - /* values to account for the added width and height. */ - /* */ - typedef struct FT_Glyph_Metrics_ - { - FT_Pos width; - FT_Pos height; - - FT_Pos horiBearingX; - FT_Pos horiBearingY; - FT_Pos horiAdvance; - - FT_Pos vertBearingX; - FT_Pos vertBearingY; - FT_Pos vertAdvance; - - } FT_Glyph_Metrics; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Bitmap_Size */ - /* */ - /* <Description> */ - /* This structure models the metrics of a bitmap strike (i.e., a set */ - /* of glyphs for a given point size and resolution) in a bitmap font. */ - /* It is used for the `available_sizes' field of @FT_Face. */ - /* */ - /* <Fields> */ - /* height :: The vertical distance, in pixels, between two */ - /* consecutive baselines. It is always positive. */ - /* */ - /* width :: The average width, in pixels, of all glyphs in the */ - /* strike. */ - /* */ - /* size :: The nominal size of the strike in 26.6 fractional */ - /* points. This field is not very useful. */ - /* */ - /* x_ppem :: The horizontal ppem (nominal width) in 26.6 fractional */ - /* pixels. */ - /* */ - /* y_ppem :: The vertical ppem (nominal height) in 26.6 fractional */ - /* pixels. */ - /* */ - /* <Note> */ - /* Windows FNT: */ - /* The nominal size given in a FNT font is not reliable. Thus when */ - /* the driver finds it incorrect, it sets `size' to some calculated */ - /* values and sets `x_ppem' and `y_ppem' to the pixel width and */ - /* height given in the font, respectively. */ - /* */ - /* TrueType embedded bitmaps: */ - /* `size', `width', and `height' values are not contained in the */ - /* bitmap strike itself. They are computed from the global font */ - /* parameters. */ - /* */ - typedef struct FT_Bitmap_Size_ - { - FT_Short height; - FT_Short width; - - FT_Pos size; - - FT_Pos x_ppem; - FT_Pos y_ppem; - - } FT_Bitmap_Size; - - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* O B J E C T C L A S S E S */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Library */ - /* */ - /* <Description> */ - /* A handle to a FreeType library instance. Each `library' is */ - /* completely independent from the others; it is the `root' of a set */ - /* of objects like fonts, faces, sizes, etc. */ - /* */ - /* It also embeds a memory manager (see @FT_Memory), as well as a */ - /* scan-line converter object (see @FT_Raster). */ - /* */ - /* In multi-threaded applications it is easiest to use one */ - /* `FT_Library' object per thread. In case this is too cumbersome, */ - /* a single `FT_Library' object across threads is possible also */ - /* (since FreeType version 2.5.6), as long as a mutex lock is used */ - /* around @FT_New_Face and @FT_Done_Face. */ - /* */ - /* <Note> */ - /* Library objects are normally created by @FT_Init_FreeType, and */ - /* destroyed with @FT_Done_FreeType. If you need reference-counting */ - /* (cf. @FT_Reference_Library), use @FT_New_Library and */ - /* @FT_Done_Library. */ - /* */ - typedef struct FT_LibraryRec_ *FT_Library; - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* module_management */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Module */ - /* */ - /* <Description> */ - /* A handle to a given FreeType module object. Each module can be a */ - /* font driver, a renderer, or anything else that provides services */ - /* to the formers. */ - /* */ - typedef struct FT_ModuleRec_* FT_Module; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Driver */ - /* */ - /* <Description> */ - /* A handle to a given FreeType font driver object. Each font driver */ - /* is a special module capable of creating faces from font files. */ - /* */ - typedef struct FT_DriverRec_* FT_Driver; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Renderer */ - /* */ - /* <Description> */ - /* A handle to a given FreeType renderer. A renderer is a special */ - /* module in charge of converting a glyph image to a bitmap, when */ - /* necessary. Each renderer supports a given glyph image format, and */ - /* one or more target surface depths. */ - /* */ - typedef struct FT_RendererRec_* FT_Renderer; - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* base_interface */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Face */ - /* */ - /* <Description> */ - /* A handle to a given typographic face object. A face object models */ - /* a given typeface, in a given style. */ - /* */ - /* <Note> */ - /* Each face object also owns a single @FT_GlyphSlot object, as well */ - /* as one or more @FT_Size objects. */ - /* */ - /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */ - /* a given filepathname or a custom input stream. */ - /* */ - /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */ - /* */ - /* An `FT_Face' object can only be safely used from one thread at a */ - /* time. Similarly, creation and destruction of `FT_Face' with the */ - /* same @FT_Library object can only be done from one thread at a */ - /* time. On the other hand, functions like @FT_Load_Glyph and its */ - /* siblings are thread-safe and do not need the lock to be held as */ - /* long as the same `FT_Face' object is not used from multiple */ - /* threads at the same time. */ - /* */ - /* <Also> */ - /* See @FT_FaceRec for the publicly accessible fields of a given face */ - /* object. */ - /* */ - typedef struct FT_FaceRec_* FT_Face; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Size */ - /* */ - /* <Description> */ - /* A handle to an object used to model a face scaled to a given */ - /* character size. */ - /* */ - /* <Note> */ - /* Each @FT_Face has an _active_ @FT_Size object that is used by */ - /* functions like @FT_Load_Glyph to determine the scaling */ - /* transformation that in turn is used to load and hint glyphs and */ - /* metrics. */ - /* */ - /* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */ - /* @FT_Request_Size or even @FT_Select_Size to change the content */ - /* (i.e., the scaling values) of the active @FT_Size. */ - /* */ - /* You can use @FT_New_Size to create additional size objects for a */ - /* given @FT_Face, but they won't be used by other functions until */ - /* you activate it through @FT_Activate_Size. Only one size can be */ - /* activated at any given time per face. */ - /* */ - /* <Also> */ - /* See @FT_SizeRec for the publicly accessible fields of a given size */ - /* object. */ - /* */ - typedef struct FT_SizeRec_* FT_Size; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_GlyphSlot */ - /* */ - /* <Description> */ - /* A handle to a given `glyph slot'. A slot is a container where it */ - /* is possible to load any of the glyphs contained in its parent */ - /* face. */ - /* */ - /* In other words, each time you call @FT_Load_Glyph or */ - /* @FT_Load_Char, the slot's content is erased by the new glyph data, */ - /* i.e., the glyph's metrics, its image (bitmap or outline), and */ - /* other control information. */ - /* */ - /* <Also> */ - /* See @FT_GlyphSlotRec for the publicly accessible glyph fields. */ - /* */ - typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_CharMap */ - /* */ - /* <Description> */ - /* A handle to a given character map. A charmap is used to translate */ - /* character codes in a given encoding into glyph indexes for its */ - /* parent's face. Some font formats may provide several charmaps per */ - /* font. */ - /* */ - /* Each face object owns zero or more charmaps, but only one of them */ - /* can be `active' and used by @FT_Get_Char_Index or @FT_Load_Char. */ - /* */ - /* The list of available charmaps in a face is available through the */ - /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */ - /* */ - /* The currently active charmap is available as `face->charmap'. */ - /* You should call @FT_Set_Charmap to change it. */ - /* */ - /* <Note> */ - /* When a new face is created (either through @FT_New_Face or */ - /* @FT_Open_Face), the library looks for a Unicode charmap within */ - /* the list and automatically activates it. */ - /* */ - /* <Also> */ - /* See @FT_CharMapRec for the publicly accessible fields of a given */ - /* character map. */ - /* */ - typedef struct FT_CharMapRec_* FT_CharMap; - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_ENC_TAG */ - /* */ - /* <Description> */ - /* This macro converts four-letter tags into an unsigned long. It is */ - /* used to define `encoding' identifiers (see @FT_Encoding). */ - /* */ - /* <Note> */ - /* Since many 16-bit compilers don't like 32-bit enumerations, you */ - /* should redefine this macro in case of problems to something like */ - /* this: */ - /* */ - /* { */ - /* #define FT_ENC_TAG( value, a, b, c, d ) value */ - /* } */ - /* */ - /* to get a simple enumeration without assigning special numbers. */ - /* */ - -#ifndef FT_ENC_TAG -#define FT_ENC_TAG( value, a, b, c, d ) \ - value = ( ( (FT_UInt32)(a) << 24 ) | \ - ( (FT_UInt32)(b) << 16 ) | \ - ( (FT_UInt32)(c) << 8 ) | \ - (FT_UInt32)(d) ) - -#endif /* FT_ENC_TAG */ - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Encoding */ - /* */ - /* <Description> */ - /* An enumeration used to specify character sets supported by */ - /* charmaps. Used in the @FT_Select_Charmap API function. */ - /* */ - /* <Note> */ - /* Despite the name, this enumeration lists specific character */ - /* repertories (i.e., charsets), and not text encoding methods (e.g., */ - /* UTF-8, UTF-16, etc.). */ - /* */ - /* Other encodings might be defined in the future. */ - /* */ - /* <Values> */ - /* FT_ENCODING_NONE :: */ - /* The encoding value~0 is reserved. */ - /* */ - /* FT_ENCODING_UNICODE :: */ - /* Corresponds to the Unicode character set. This value covers */ - /* all versions of the Unicode repertoire, including ASCII and */ - /* Latin-1. Most fonts include a Unicode charmap, but not all */ - /* of them. */ - /* */ - /* For example, if you want to access Unicode value U+1F028 (and */ - /* the font contains it), use value 0x1F028 as the input value for */ - /* @FT_Get_Char_Index. */ - /* */ - /* FT_ENCODING_MS_SYMBOL :: */ - /* Corresponds to the Microsoft Symbol encoding, used to encode */ - /* mathematical symbols and wingdings. For more information, see */ - /* `http://www.microsoft.com/typography/otspec/recom.htm', */ - /* `http://www.kostis.net/charsets/symbol.htm', and */ - /* `http://www.kostis.net/charsets/wingding.htm'. */ - /* */ - /* This encoding uses character codes from the PUA (Private Unicode */ - /* Area) in the range U+F020-U+F0FF. */ - /* */ - /* FT_ENCODING_SJIS :: */ - /* Corresponds to Japanese SJIS encoding. More info at */ - /* at `http://en.wikipedia.org/wiki/Shift_JIS'. */ - /* See note on multi-byte encodings below. */ - /* */ - /* FT_ENCODING_GB2312 :: */ - /* Corresponds to an encoding system for Simplified Chinese as used */ - /* used in mainland China. */ - /* */ - /* FT_ENCODING_BIG5 :: */ - /* Corresponds to an encoding system for Traditional Chinese as */ - /* used in Taiwan and Hong Kong. */ - /* */ - /* FT_ENCODING_WANSUNG :: */ - /* Corresponds to the Korean encoding system known as Wansung. */ - /* For more information see */ - /* `https://msdn.microsoft.com/en-US/goglobal/cc305154'. */ - /* */ - /* FT_ENCODING_JOHAB :: */ - /* The Korean standard character set (KS~C 5601-1992), which */ - /* corresponds to MS Windows code page 1361. This character set */ - /* includes all possible Hangeul character combinations. */ - /* */ - /* FT_ENCODING_ADOBE_LATIN_1 :: */ - /* Corresponds to a Latin-1 encoding as defined in a Type~1 */ - /* PostScript font. It is limited to 256 character codes. */ - /* */ - /* FT_ENCODING_ADOBE_STANDARD :: */ - /* Corresponds to the Adobe Standard encoding, as found in Type~1, */ - /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ - /* codes. */ - /* */ - /* FT_ENCODING_ADOBE_EXPERT :: */ - /* Corresponds to the Adobe Expert encoding, as found in Type~1, */ - /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ - /* codes. */ - /* */ - /* FT_ENCODING_ADOBE_CUSTOM :: */ - /* Corresponds to a custom encoding, as found in Type~1, CFF, and */ - /* OpenType/CFF fonts. It is limited to 256 character codes. */ - /* */ - /* FT_ENCODING_APPLE_ROMAN :: */ - /* Corresponds to the 8-bit Apple roman encoding. Many TrueType */ - /* and OpenType fonts contain a charmap for this encoding, since */ - /* older versions of Mac OS are able to use it. */ - /* */ - /* FT_ENCODING_OLD_LATIN_2 :: */ - /* This value is deprecated and was never used nor reported by */ - /* FreeType. Don't use or test for it. */ - /* */ - /* FT_ENCODING_MS_SJIS :: */ - /* Same as FT_ENCODING_SJIS. Deprecated. */ - /* */ - /* FT_ENCODING_MS_GB2312 :: */ - /* Same as FT_ENCODING_GB2312. Deprecated. */ - /* */ - /* FT_ENCODING_MS_BIG5 :: */ - /* Same as FT_ENCODING_BIG5. Deprecated. */ - /* */ - /* FT_ENCODING_MS_WANSUNG :: */ - /* Same as FT_ENCODING_WANSUNG. Deprecated. */ - /* */ - /* FT_ENCODING_MS_JOHAB :: */ - /* Same as FT_ENCODING_JOHAB. Deprecated. */ - /* */ - /* <Note> */ - /* By default, FreeType automatically synthesizes a Unicode charmap */ - /* for PostScript fonts, using their glyph names dictionaries. */ - /* However, it also reports the encodings defined explicitly in the */ - /* font file, for the cases when they are needed, with the Adobe */ - /* values as well. */ - /* */ - /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */ - /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */ - /* FT_ENCODING_UNICODE). Use @FT_Get_BDF_Charset_ID to find out */ - /* which encoding is really present. If, for example, the */ - /* `cs_registry' field is `KOI8' and the `cs_encoding' field is `R', */ - /* the font is encoded in KOI8-R. */ - /* */ - /* FT_ENCODING_NONE is always set (with a single exception) by the */ - /* winfonts driver. Use @FT_Get_WinFNT_Header and examine the */ - /* `charset' field of the @FT_WinFNT_HeaderRec structure to find out */ - /* which encoding is really present. For example, */ - /* @FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for */ - /* Russian). */ - /* */ - /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */ - /* and `encoding_id' is not @TT_MAC_ID_ROMAN (otherwise it is set to */ - /* FT_ENCODING_APPLE_ROMAN). */ - /* */ - /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */ - /* @FT_Get_CMap_Language_ID to query the Mac language ID that may */ - /* be needed to be able to distinguish Apple encoding variants. See */ - /* */ - /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt */ - /* */ - /* to get an idea how to do that. Basically, if the language ID */ - /* is~0, don't use it, otherwise subtract 1 from the language ID. */ - /* Then examine `encoding_id'. If, for example, `encoding_id' is */ - /* @TT_MAC_ID_ROMAN and the language ID (minus~1) is */ - /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */ - /* @TT_MAC_ID_ARABIC with `TT_MAC_LANGID_FARSI' means the Farsi */ - /* variant the Arabic encoding. */ - /* */ - typedef enum FT_Encoding_ - { - FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ), - - FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ), - FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), - - FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ), - FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ), - FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ), - FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ), - FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ), - - /* for backwards compatibility */ - FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, - FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, - FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, - FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, - FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, - - FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ), - FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ), - FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ), - FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ), - - FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ), - - FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' ) - - } FT_Encoding; - - - /* these constants are deprecated; use the corresponding `FT_Encoding' */ - /* values instead */ -#define ft_encoding_none FT_ENCODING_NONE -#define ft_encoding_unicode FT_ENCODING_UNICODE -#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL -#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 -#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 -#define ft_encoding_sjis FT_ENCODING_SJIS -#define ft_encoding_gb2312 FT_ENCODING_GB2312 -#define ft_encoding_big5 FT_ENCODING_BIG5 -#define ft_encoding_wansung FT_ENCODING_WANSUNG -#define ft_encoding_johab FT_ENCODING_JOHAB - -#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD -#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT -#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM -#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_CharMapRec */ - /* */ - /* <Description> */ - /* The base charmap structure. */ - /* */ - /* <Fields> */ - /* face :: A handle to the parent face object. */ - /* */ - /* encoding :: An @FT_Encoding tag identifying the charmap. Use */ - /* this with @FT_Select_Charmap. */ - /* */ - /* platform_id :: An ID number describing the platform for the */ - /* following encoding ID. This comes directly from */ - /* the TrueType specification and should be emulated */ - /* for other formats. */ - /* */ - /* encoding_id :: A platform specific encoding number. This also */ - /* comes from the TrueType specification and should be */ - /* emulated similarly. */ - /* */ - typedef struct FT_CharMapRec_ - { - FT_Face face; - FT_Encoding encoding; - FT_UShort platform_id; - FT_UShort encoding_id; - - } FT_CharMapRec; - - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* B A S E O B J E C T C L A S S E S */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Face_Internal */ - /* */ - /* <Description> */ - /* An opaque handle to an `FT_Face_InternalRec' structure, used to */ - /* model private data of a given @FT_Face object. */ - /* */ - /* This structure might change between releases of FreeType~2 and is */ - /* not generally available to client applications. */ - /* */ - typedef struct FT_Face_InternalRec_* FT_Face_Internal; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_FaceRec */ - /* */ - /* <Description> */ - /* FreeType root face class structure. A face object models a */ - /* typeface in a font file. */ - /* */ - /* <Fields> */ - /* num_faces :: The number of faces in the font file. Some */ - /* font formats can have multiple faces in */ - /* a font file. */ - /* */ - /* face_index :: This field holds two different values. */ - /* Bits 0-15 are the index of the face in the */ - /* font file (starting with value~0). They */ - /* are set to~0 if there is only one face in */ - /* the font file. */ - /* */ - /* Bits 16-30 are relevant to GX variation */ - /* fonts only, holding the named instance */ - /* index for the current face index (starting */ - /* with value~1; value~0 indicates font access */ - /* without GX variation data). For non-GX */ - /* fonts, bits 16-30 are ignored. If we have */ - /* the third named instance of face~4, say, */ - /* `face_index' is set to 0x00030004. */ - /* */ - /* Bit 31 is always zero (this is, */ - /* `face_index' is always a positive value). */ - /* */ - /* face_flags :: A set of bit flags that give important */ - /* information about the face; see */ - /* @FT_FACE_FLAG_XXX for the details. */ - /* */ - /* style_flags :: The lower 16~bits contain a set of bit */ - /* flags indicating the style of the face; see */ - /* @FT_STYLE_FLAG_XXX for the details. Bits */ - /* 16-30 hold the number of named instances */ - /* available for the current face if we have a */ - /* GX variation (sub)font. Bit 31 is always */ - /* zero (this is, `style_flags' is always a */ - /* positive value). */ - /* */ - /* num_glyphs :: The number of glyphs in the face. If the */ - /* face is scalable and has sbits (see */ - /* `num_fixed_sizes'), it is set to the number */ - /* of outline glyphs. */ - /* */ - /* For CID-keyed fonts, this value gives the */ - /* highest CID used in the font. */ - /* */ - /* family_name :: The face's family name. This is an ASCII */ - /* string, usually in English, that describes */ - /* the typeface's family (like `Times New */ - /* Roman', `Bodoni', `Garamond', etc). This */ - /* is a least common denominator used to list */ - /* fonts. Some formats (TrueType & OpenType) */ - /* provide localized and Unicode versions of */ - /* this string. Applications should use the */ - /* format specific interface to access them. */ - /* Can be NULL (e.g., in fonts embedded in a */ - /* PDF file). */ - /* */ - /* In case the font doesn't provide a specific */ - /* family name entry, FreeType tries to */ - /* synthesize one, deriving it from other name */ - /* entries. */ - /* */ - /* style_name :: The face's style name. This is an ASCII */ - /* string, usually in English, that describes */ - /* the typeface's style (like `Italic', */ - /* `Bold', `Condensed', etc). Not all font */ - /* formats provide a style name, so this field */ - /* is optional, and can be set to NULL. As */ - /* for `family_name', some formats provide */ - /* localized and Unicode versions of this */ - /* string. Applications should use the format */ - /* specific interface to access them. */ - /* */ - /* num_fixed_sizes :: The number of bitmap strikes in the face. */ - /* Even if the face is scalable, there might */ - /* still be bitmap strikes, which are called */ - /* `sbits' in that case. */ - /* */ - /* available_sizes :: An array of @FT_Bitmap_Size for all bitmap */ - /* strikes in the face. It is set to NULL if */ - /* there is no bitmap strike. */ - /* */ - /* num_charmaps :: The number of charmaps in the face. */ - /* */ - /* charmaps :: An array of the charmaps of the face. */ - /* */ - /* generic :: A field reserved for client uses. See the */ - /* @FT_Generic type description. */ - /* */ - /* bbox :: The font bounding box. Coordinates are */ - /* expressed in font units (see */ - /* `units_per_EM'). The box is large enough */ - /* to contain any glyph from the font. Thus, */ - /* `bbox.yMax' can be seen as the `maximum */ - /* ascender', and `bbox.yMin' as the `minimum */ - /* descender'. Only relevant for scalable */ - /* formats. */ - /* */ - /* Note that the bounding box might be off by */ - /* (at least) one pixel for hinted fonts. See */ - /* @FT_Size_Metrics for further discussion. */ - /* */ - /* units_per_EM :: The number of font units per EM square for */ - /* this face. This is typically 2048 for */ - /* TrueType fonts, and 1000 for Type~1 fonts. */ - /* Only relevant for scalable formats. */ - /* */ - /* ascender :: The typographic ascender of the face, */ - /* expressed in font units. For font formats */ - /* not having this information, it is set to */ - /* `bbox.yMax'. Only relevant for scalable */ - /* formats. */ - /* */ - /* descender :: The typographic descender of the face, */ - /* expressed in font units. For font formats */ - /* not having this information, it is set to */ - /* `bbox.yMin'. Note that this field is */ - /* usually negative. Only relevant for */ - /* scalable formats. */ - /* */ - /* height :: This value is the vertical distance */ - /* between two consecutive baselines, */ - /* expressed in font units. It is always */ - /* positive. Only relevant for scalable */ - /* formats. */ - /* */ - /* If you want the global glyph height, use */ - /* `ascender - descender'. */ - /* */ - /* max_advance_width :: The maximum advance width, in font units, */ - /* for all glyphs in this face. This can be */ - /* used to make word wrapping computations */ - /* faster. Only relevant for scalable */ - /* formats. */ - /* */ - /* max_advance_height :: The maximum advance height, in font units, */ - /* for all glyphs in this face. This is only */ - /* relevant for vertical layouts, and is set */ - /* to `height' for fonts that do not provide */ - /* vertical metrics. Only relevant for */ - /* scalable formats. */ - /* */ - /* underline_position :: The position, in font units, of the */ - /* underline line for this face. It is the */ - /* center of the underlining stem. Only */ - /* relevant for scalable formats. */ - /* */ - /* underline_thickness :: The thickness, in font units, of the */ - /* underline for this face. Only relevant for */ - /* scalable formats. */ - /* */ - /* glyph :: The face's associated glyph slot(s). */ - /* */ - /* size :: The current active size for this face. */ - /* */ - /* charmap :: The current active charmap for this face. */ - /* */ - /* <Note> */ - /* Fields may be changed after a call to @FT_Attach_File or */ - /* @FT_Attach_Stream. */ - /* */ - typedef struct FT_FaceRec_ - { - FT_Long num_faces; - FT_Long face_index; - - FT_Long face_flags; - FT_Long style_flags; - - FT_Long num_glyphs; - - FT_String* family_name; - FT_String* style_name; - - FT_Int num_fixed_sizes; - FT_Bitmap_Size* available_sizes; - - FT_Int num_charmaps; - FT_CharMap* charmaps; - - FT_Generic generic; - - /*# The following member variables (down to `underline_thickness') */ - /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ - /*# for bitmap fonts. */ - FT_BBox bbox; - - FT_UShort units_per_EM; - FT_Short ascender; - FT_Short descender; - FT_Short height; - - FT_Short max_advance_width; - FT_Short max_advance_height; - - FT_Short underline_position; - FT_Short underline_thickness; - - FT_GlyphSlot glyph; - FT_Size size; - FT_CharMap charmap; - - /*@private begin */ - - FT_Driver driver; - FT_Memory memory; - FT_Stream stream; - - FT_ListRec sizes_list; - - FT_Generic autohint; /* face-specific auto-hinter data */ - void* extensions; /* unused */ - - FT_Face_Internal internal; - - /*@private end */ - - } FT_FaceRec; - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_FACE_FLAG_XXX */ - /* */ - /* <Description> */ - /* A list of bit flags used in the `face_flags' field of the */ - /* @FT_FaceRec structure. They inform client applications of */ - /* properties of the corresponding face. */ - /* */ - /* <Values> */ - /* FT_FACE_FLAG_SCALABLE :: */ - /* Indicates that the face contains outline glyphs. This doesn't */ - /* prevent bitmap strikes, i.e., a face can have both this and */ - /* and @FT_FACE_FLAG_FIXED_SIZES set. */ - /* */ - /* FT_FACE_FLAG_FIXED_SIZES :: */ - /* Indicates that the face contains bitmap strikes. See also the */ - /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */ - /* */ - /* FT_FACE_FLAG_FIXED_WIDTH :: */ - /* Indicates that the face contains fixed-width characters (like */ - /* Courier, Lucido, MonoType, etc.). */ - /* */ - /* FT_FACE_FLAG_SFNT :: */ - /* Indicates that the face uses the `sfnt' storage scheme. For */ - /* now, this means TrueType and OpenType. */ - /* */ - /* FT_FACE_FLAG_HORIZONTAL :: */ - /* Indicates that the face contains horizontal glyph metrics. This */ - /* should be set for all common formats. */ - /* */ - /* FT_FACE_FLAG_VERTICAL :: */ - /* Indicates that the face contains vertical glyph metrics. This */ - /* is only available in some formats, not all of them. */ - /* */ - /* FT_FACE_FLAG_KERNING :: */ - /* Indicates that the face contains kerning information. If set, */ - /* the kerning distance can be retrieved through the function */ - /* @FT_Get_Kerning. Otherwise the function always return the */ - /* vector (0,0). Note that FreeType doesn't handle kerning data */ - /* from the `GPOS' table (as present in some OpenType fonts). */ - /* */ - /* FT_FACE_FLAG_FAST_GLYPHS :: */ - /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */ - /* */ - /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */ - /* Indicates that the font contains multiple masters and is capable */ - /* of interpolating between them. See the multiple-masters */ - /* specific API for details. */ - /* */ - /* FT_FACE_FLAG_GLYPH_NAMES :: */ - /* Indicates that the font contains glyph names that can be */ - /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */ - /* fonts contain broken glyph name tables. Use the function */ - /* @FT_Has_PS_Glyph_Names when needed. */ - /* */ - /* FT_FACE_FLAG_EXTERNAL_STREAM :: */ - /* Used internally by FreeType to indicate that a face's stream was */ - /* provided by the client application and should not be destroyed */ - /* when @FT_Done_Face is called. Don't read or test this flag. */ - /* */ - /* FT_FACE_FLAG_HINTER :: */ - /* Set if the font driver has a hinting machine of its own. For */ - /* example, with TrueType fonts, it makes sense to use data from */ - /* the SFNT `gasp' table only if the native TrueType hinting engine */ - /* (with the bytecode interpreter) is available and active. */ - /* */ - /* FT_FACE_FLAG_CID_KEYED :: */ - /* Set if the font is CID-keyed. In that case, the font is not */ - /* accessed by glyph indices but by CID values. For subsetted */ - /* CID-keyed fonts this has the consequence that not all index */ - /* values are a valid argument to FT_Load_Glyph. Only the CID */ - /* values for which corresponding glyphs in the subsetted font */ - /* exist make FT_Load_Glyph return successfully; in all other cases */ - /* you get an `FT_Err_Invalid_Argument' error. */ - /* */ - /* Note that CID-keyed fonts that are in an SFNT wrapper don't */ - /* have this flag set since the glyphs are accessed in the normal */ - /* way (using contiguous indices); the `CID-ness' isn't visible to */ - /* the application. */ - /* */ - /* FT_FACE_FLAG_TRICKY :: */ - /* Set if the font is `tricky', this is, it always needs the */ - /* font format's native hinting engine to get a reasonable result. */ - /* A typical example is the Chinese font `mingli.ttf' that uses */ - /* TrueType bytecode instructions to move and scale all of its */ - /* subglyphs. */ - /* */ - /* It is not possible to auto-hint such fonts using */ - /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */ - /* @FT_LOAD_NO_HINTING. You have to set both @FT_LOAD_NO_HINTING */ - /* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */ - /* probably never want this except for demonstration purposes. */ - /* */ - /* Currently, there are about a dozen TrueType fonts in the list of */ - /* tricky fonts; they are hard-coded in file `ttobjs.c'. */ - /* */ - /* FT_FACE_FLAG_COLOR :: */ - /* Set if the font has color glyph tables. To access color glyphs */ - /* use @FT_LOAD_COLOR. */ - /* */ -#define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) -#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) -#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 ) -#define FT_FACE_FLAG_SFNT ( 1L << 3 ) -#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 ) -#define FT_FACE_FLAG_VERTICAL ( 1L << 5 ) -#define FT_FACE_FLAG_KERNING ( 1L << 6 ) -#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 ) -#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 ) -#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 ) -#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 ) -#define FT_FACE_FLAG_HINTER ( 1L << 11 ) -#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 ) -#define FT_FACE_FLAG_TRICKY ( 1L << 13 ) -#define FT_FACE_FLAG_COLOR ( 1L << 14 ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_HORIZONTAL( face ) - * - * @description: - * A macro that returns true whenever a face object contains - * horizontal metrics (this is true for all font formats though). - * - * @also: - * @FT_HAS_VERTICAL can be used to check for vertical metrics. - * - */ -#define FT_HAS_HORIZONTAL( face ) \ - ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_VERTICAL( face ) - * - * @description: - * A macro that returns true whenever a face object contains real - * vertical metrics (and not only synthesized ones). - * - */ -#define FT_HAS_VERTICAL( face ) \ - ( face->face_flags & FT_FACE_FLAG_VERTICAL ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_KERNING( face ) - * - * @description: - * A macro that returns true whenever a face object contains kerning - * data that can be accessed with @FT_Get_Kerning. - * - */ -#define FT_HAS_KERNING( face ) \ - ( face->face_flags & FT_FACE_FLAG_KERNING ) - - - /************************************************************************* - * - * @macro: - * FT_IS_SCALABLE( face ) - * - * @description: - * A macro that returns true whenever a face object contains a scalable - * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF, - * and PFR font formats. - * - */ -#define FT_IS_SCALABLE( face ) \ - ( face->face_flags & FT_FACE_FLAG_SCALABLE ) - - - /************************************************************************* - * - * @macro: - * FT_IS_SFNT( face ) - * - * @description: - * A macro that returns true whenever a face object contains a font - * whose format is based on the SFNT storage scheme. This usually - * means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded - * bitmap fonts. - * - * If this macro is true, all functions defined in @FT_SFNT_NAMES_H and - * @FT_TRUETYPE_TABLES_H are available. - * - */ -#define FT_IS_SFNT( face ) \ - ( face->face_flags & FT_FACE_FLAG_SFNT ) - - - /************************************************************************* - * - * @macro: - * FT_IS_FIXED_WIDTH( face ) - * - * @description: - * A macro that returns true whenever a face object contains a font face - * that contains fixed-width (or `monospace', `fixed-pitch', etc.) - * glyphs. - * - */ -#define FT_IS_FIXED_WIDTH( face ) \ - ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_FIXED_SIZES( face ) - * - * @description: - * A macro that returns true whenever a face object contains some - * embedded bitmaps. See the `available_sizes' field of the - * @FT_FaceRec structure. - * - */ -#define FT_HAS_FIXED_SIZES( face ) \ - ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_FAST_GLYPHS( face ) - * - * @description: - * Deprecated. - * - */ -#define FT_HAS_FAST_GLYPHS( face ) 0 - - - /************************************************************************* - * - * @macro: - * FT_HAS_GLYPH_NAMES( face ) - * - * @description: - * A macro that returns true whenever a face object contains some glyph - * names that can be accessed through @FT_Get_Glyph_Name. - * - */ -#define FT_HAS_GLYPH_NAMES( face ) \ - ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_MULTIPLE_MASTERS( face ) - * - * @description: - * A macro that returns true whenever a face object contains some - * multiple masters. The functions provided by @FT_MULTIPLE_MASTERS_H - * are then available to choose the exact design you want. - * - */ -#define FT_HAS_MULTIPLE_MASTERS( face ) \ - ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) - - - /************************************************************************* - * - * @macro: - * FT_IS_CID_KEYED( face ) - * - * @description: - * A macro that returns true whenever a face object contains a CID-keyed - * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more - * details. - * - * If this macro is true, all functions defined in @FT_CID_H are - * available. - * - */ -#define FT_IS_CID_KEYED( face ) \ - ( face->face_flags & FT_FACE_FLAG_CID_KEYED ) - - - /************************************************************************* - * - * @macro: - * FT_IS_TRICKY( face ) - * - * @description: - * A macro that returns true whenever a face represents a `tricky' font. - * See the discussion of @FT_FACE_FLAG_TRICKY for more details. - * - */ -#define FT_IS_TRICKY( face ) \ - ( face->face_flags & FT_FACE_FLAG_TRICKY ) - - - /************************************************************************* - * - * @macro: - * FT_HAS_COLOR( face ) - * - * @description: - * A macro that returns true whenever a face object contains - * tables for color glyphs. - * - */ -#define FT_HAS_COLOR( face ) \ - ( face->face_flags & FT_FACE_FLAG_COLOR ) - - - /*************************************************************************/ - /* */ - /* <Const> */ - /* FT_STYLE_FLAG_XXX */ - /* */ - /* <Description> */ - /* A list of bit flags used to indicate the style of a given face. */ - /* These are used in the `style_flags' field of @FT_FaceRec. */ - /* */ - /* <Values> */ - /* FT_STYLE_FLAG_ITALIC :: */ - /* Indicates that a given face style is italic or oblique. */ - /* */ - /* FT_STYLE_FLAG_BOLD :: */ - /* Indicates that a given face is bold. */ - /* */ - /* <Note> */ - /* The style information as provided by FreeType is very basic. More */ - /* details are beyond the scope and should be done on a higher level */ - /* (for example, by analyzing various fields of the `OS/2' table in */ - /* SFNT based fonts). */ - /* */ -#define FT_STYLE_FLAG_ITALIC ( 1 << 0 ) -#define FT_STYLE_FLAG_BOLD ( 1 << 1 ) - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Size_Internal */ - /* */ - /* <Description> */ - /* An opaque handle to an `FT_Size_InternalRec' structure, used to */ - /* model private data of a given @FT_Size object. */ - /* */ - typedef struct FT_Size_InternalRec_* FT_Size_Internal; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Size_Metrics */ - /* */ - /* <Description> */ - /* The size metrics structure gives the metrics of a size object. */ - /* */ - /* <Fields> */ - /* x_ppem :: The width of the scaled EM square in pixels, hence */ - /* the term `ppem' (pixels per EM). It is also */ - /* referred to as `nominal width'. */ - /* */ - /* y_ppem :: The height of the scaled EM square in pixels, */ - /* hence the term `ppem' (pixels per EM). It is also */ - /* referred to as `nominal height'. */ - /* */ - /* x_scale :: A 16.16 fractional scaling value used to convert */ - /* horizontal metrics from font units to 26.6 */ - /* fractional pixels. Only relevant for scalable */ - /* font formats. */ - /* */ - /* y_scale :: A 16.16 fractional scaling value used to convert */ - /* vertical metrics from font units to 26.6 */ - /* fractional pixels. Only relevant for scalable */ - /* font formats. */ - /* */ - /* ascender :: The ascender in 26.6 fractional pixels. See */ - /* @FT_FaceRec for the details. */ - /* */ - /* descender :: The descender in 26.6 fractional pixels. See */ - /* @FT_FaceRec for the details. */ - /* */ - /* height :: The height in 26.6 fractional pixels. See */ - /* @FT_FaceRec for the details. */ - /* */ - /* max_advance :: The maximum advance width in 26.6 fractional */ - /* pixels. See @FT_FaceRec for the details. */ - /* */ - /* <Note> */ - /* The scaling values, if relevant, are determined first during a */ - /* size changing operation. The remaining fields are then set by the */ - /* driver. For scalable formats, they are usually set to scaled */ - /* values of the corresponding fields in @FT_FaceRec. */ - /* */ - /* Note that due to glyph hinting, these values might not be exact */ - /* for certain fonts. Thus they must be treated as unreliable */ - /* with an error margin of at least one pixel! */ - /* */ - /* Indeed, the only way to get the exact metrics is to render _all_ */ - /* glyphs. As this would be a definite performance hit, it is up to */ - /* client applications to perform such computations. */ - /* */ - /* The FT_Size_Metrics structure is valid for bitmap fonts also. */ - /* */ - typedef struct FT_Size_Metrics_ - { - FT_UShort x_ppem; /* horizontal pixels per EM */ - FT_UShort y_ppem; /* vertical pixels per EM */ - - FT_Fixed x_scale; /* scaling values used to convert font */ - FT_Fixed y_scale; /* units to 26.6 fractional pixels */ - - FT_Pos ascender; /* ascender in 26.6 frac. pixels */ - FT_Pos descender; /* descender in 26.6 frac. pixels */ - FT_Pos height; /* text height in 26.6 frac. pixels */ - FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ - - } FT_Size_Metrics; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_SizeRec */ - /* */ - /* <Description> */ - /* FreeType root size class structure. A size object models a face */ - /* object at a given size. */ - /* */ - /* <Fields> */ - /* face :: Handle to the parent face object. */ - /* */ - /* generic :: A typeless pointer, unused by the FreeType library or */ - /* any of its drivers. It can be used by client */ - /* applications to link their own data to each size */ - /* object. */ - /* */ - /* metrics :: Metrics for this size object. This field is read-only. */ - /* */ - typedef struct FT_SizeRec_ - { - FT_Face face; /* parent face object */ - FT_Generic generic; /* generic pointer for client uses */ - FT_Size_Metrics metrics; /* size metrics */ - FT_Size_Internal internal; - - } FT_SizeRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_SubGlyph */ - /* */ - /* <Description> */ - /* The subglyph structure is an internal object used to describe */ - /* subglyphs (for example, in the case of composites). */ - /* */ - /* <Note> */ - /* The subglyph implementation is not part of the high-level API, */ - /* hence the forward structure declaration. */ - /* */ - /* You can however retrieve subglyph information with */ - /* @FT_Get_SubGlyph_Info. */ - /* */ - typedef struct FT_SubGlyphRec_* FT_SubGlyph; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Slot_Internal */ - /* */ - /* <Description> */ - /* An opaque handle to an `FT_Slot_InternalRec' structure, used to */ - /* model private data of a given @FT_GlyphSlot object. */ - /* */ - typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_GlyphSlotRec */ - /* */ - /* <Description> */ - /* FreeType root glyph slot class structure. A glyph slot is a */ - /* container where individual glyphs can be loaded, be they in */ - /* outline or bitmap format. */ - /* */ - /* <Fields> */ - /* library :: A handle to the FreeType library instance */ - /* this slot belongs to. */ - /* */ - /* face :: A handle to the parent face object. */ - /* */ - /* next :: In some cases (like some font tools), several */ - /* glyph slots per face object can be a good */ - /* thing. As this is rare, the glyph slots are */ - /* listed through a direct, single-linked list */ - /* using its `next' field. */ - /* */ - /* generic :: A typeless pointer unused by the FreeType */ - /* library or any of its drivers. It can be */ - /* used by client applications to link their own */ - /* data to each glyph slot object. */ - /* */ - /* metrics :: The metrics of the last loaded glyph in the */ - /* slot. The returned values depend on the last */ - /* load flags (see the @FT_Load_Glyph API */ - /* function) and can be expressed either in 26.6 */ - /* fractional pixels or font units. */ - /* */ - /* Note that even when the glyph image is */ - /* transformed, the metrics are not. */ - /* */ - /* linearHoriAdvance :: The advance width of the unhinted glyph. */ - /* Its value is expressed in 16.16 fractional */ - /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */ - /* when loading the glyph. This field can be */ - /* important to perform correct WYSIWYG layout. */ - /* Only relevant for outline glyphs. */ - /* */ - /* linearVertAdvance :: The advance height of the unhinted glyph. */ - /* Its value is expressed in 16.16 fractional */ - /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */ - /* when loading the glyph. This field can be */ - /* important to perform correct WYSIWYG layout. */ - /* Only relevant for outline glyphs. */ - /* */ - /* advance :: This shorthand is, depending on */ - /* @FT_LOAD_IGNORE_TRANSFORM, the transformed */ - /* (hinted) advance width for the glyph, in 26.6 */ - /* fractional pixel format. As specified with */ - /* @FT_LOAD_VERTICAL_LAYOUT, it uses either the */ - /* `horiAdvance' or the `vertAdvance' value of */ - /* `metrics' field. */ - /* */ - /* format :: This field indicates the format of the image */ - /* contained in the glyph slot. Typically */ - /* @FT_GLYPH_FORMAT_BITMAP, */ - /* @FT_GLYPH_FORMAT_OUTLINE, or */ - /* @FT_GLYPH_FORMAT_COMPOSITE, but others are */ - /* possible. */ - /* */ - /* bitmap :: This field is used as a bitmap descriptor */ - /* when the slot format is */ - /* @FT_GLYPH_FORMAT_BITMAP. Note that the */ - /* address and content of the bitmap buffer can */ - /* change between calls of @FT_Load_Glyph and a */ - /* few other functions. */ - /* */ - /* bitmap_left :: The bitmap's left bearing expressed in */ - /* integer pixels. Only valid if the format is */ - /* @FT_GLYPH_FORMAT_BITMAP, this is, if the */ - /* glyph slot contains a bitmap. */ - /* */ - /* bitmap_top :: The bitmap's top bearing expressed in integer */ - /* pixels. Remember that this is the distance */ - /* from the baseline to the top-most glyph */ - /* scanline, upwards y~coordinates being */ - /* *positive*. */ - /* */ - /* outline :: The outline descriptor for the current glyph */ - /* image if its format is */ - /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */ - /* loaded, `outline' can be transformed, */ - /* distorted, embolded, etc. However, it must */ - /* not be freed. */ - /* */ - /* num_subglyphs :: The number of subglyphs in a composite glyph. */ - /* This field is only valid for the composite */ - /* glyph format that should normally only be */ - /* loaded with the @FT_LOAD_NO_RECURSE flag. */ - /* */ - /* subglyphs :: An array of subglyph descriptors for */ - /* composite glyphs. There are `num_subglyphs' */ - /* elements in there. Currently internal to */ - /* FreeType. */ - /* */ - /* control_data :: Certain font drivers can also return the */ - /* control data for a given glyph image (e.g. */ - /* TrueType bytecode, Type~1 charstrings, etc.). */ - /* This field is a pointer to such data. */ - /* */ - /* control_len :: This is the length in bytes of the control */ - /* data. */ - /* */ - /* other :: Really wicked formats can use this pointer to */ - /* present their own glyph image to client */ - /* applications. Note that the application */ - /* needs to know about the image format. */ - /* */ - /* lsb_delta :: The difference between hinted and unhinted */ - /* left side bearing while auto-hinting is */ - /* active. Zero otherwise. */ - /* */ - /* rsb_delta :: The difference between hinted and unhinted */ - /* right side bearing while auto-hinting is */ - /* active. Zero otherwise. */ - /* */ - /* <Note> */ - /* If @FT_Load_Glyph is called with default flags (see */ - /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */ - /* its native format (e.g., an outline glyph for TrueType and Type~1 */ - /* formats). */ - /* */ - /* This image can later be converted into a bitmap by calling */ - /* @FT_Render_Glyph. This function finds the current renderer for */ - /* the native image's format, then invokes it. */ - /* */ - /* The renderer is in charge of transforming the native image through */ - /* the slot's face transformation fields, then converting it into a */ - /* bitmap that is returned in `slot->bitmap'. */ - /* */ - /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */ - /* to specify the position of the bitmap relative to the current pen */ - /* position (e.g., coordinates (0,0) on the baseline). Of course, */ - /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */ - /* */ - /* <Note> */ - /* Here is a small pseudo code fragment that shows how to use */ - /* `lsb_delta' and `rsb_delta': */ - /* */ - /* { */ - /* FT_Pos origin_x = 0; */ - /* FT_Pos prev_rsb_delta = 0; */ - /* */ - /* */ - /* for all glyphs do */ - /* <compute kern between current and previous glyph and add it to */ - /* `origin_x'> */ - /* */ - /* <load glyph with `FT_Load_Glyph'> */ - /* */ - /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */ - /* origin_x -= 64; */ - /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */ - /* origin_x += 64; */ - /* */ - /* prev_rsb_delta = face->glyph->rsb_delta; */ - /* */ - /* <save glyph image, or render glyph, or ...> */ - /* */ - /* origin_x += face->glyph->advance.x; */ - /* endfor */ - /* } */ - /* */ - typedef struct FT_GlyphSlotRec_ - { - FT_Library library; - FT_Face face; - FT_GlyphSlot next; - FT_UInt reserved; /* retained for binary compatibility */ - FT_Generic generic; - - FT_Glyph_Metrics metrics; - FT_Fixed linearHoriAdvance; - FT_Fixed linearVertAdvance; - FT_Vector advance; - - FT_Glyph_Format format; - - FT_Bitmap bitmap; - FT_Int bitmap_left; - FT_Int bitmap_top; - - FT_Outline outline; - - FT_UInt num_subglyphs; - FT_SubGlyph subglyphs; - - void* control_data; - long control_len; - - FT_Pos lsb_delta; - FT_Pos rsb_delta; - - void* other; - - FT_Slot_Internal internal; - - } FT_GlyphSlotRec; - - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* F U N C T I O N S */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Init_FreeType */ - /* */ - /* <Description> */ - /* Initialize a new FreeType library object. The set of modules */ - /* that are registered by this function is determined at build time. */ - /* */ - /* <Output> */ - /* alibrary :: A handle to a new library object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* In case you want to provide your own memory allocating routines, */ - /* use @FT_New_Library instead, followed by a call to */ - /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module). */ - /* */ - /* See the documentation of @FT_Library and @FT_Face for */ - /* multi-threading issues. */ - /* */ - /* If you need reference-counting (cf. @FT_Reference_Library), use */ - /* @FT_New_Library and @FT_Done_Library. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Init_FreeType( FT_Library *alibrary ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_FreeType */ - /* */ - /* <Description> */ - /* Destroy a given FreeType library object and all of its children, */ - /* including resources, drivers, faces, sizes, etc. */ - /* */ - /* <Input> */ - /* library :: A handle to the target library object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Done_FreeType( FT_Library library ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_OPEN_XXX */ - /* */ - /* <Description> */ - /* A list of bit field constants used within the `flags' field of the */ - /* @FT_Open_Args structure. */ - /* */ - /* <Values> */ - /* FT_OPEN_MEMORY :: This is a memory-based stream. */ - /* */ - /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */ - /* */ - /* FT_OPEN_PATHNAME :: Create a new input stream from a C~path */ - /* name. */ - /* */ - /* FT_OPEN_DRIVER :: Use the `driver' field. */ - /* */ - /* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */ - /* */ - /* <Note> */ - /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */ - /* flags are mutually exclusive. */ - /* */ -#define FT_OPEN_MEMORY 0x1 -#define FT_OPEN_STREAM 0x2 -#define FT_OPEN_PATHNAME 0x4 -#define FT_OPEN_DRIVER 0x8 -#define FT_OPEN_PARAMS 0x10 - - - /* these constants are deprecated; use the corresponding `FT_OPEN_XXX' */ - /* values instead */ -#define ft_open_memory FT_OPEN_MEMORY -#define ft_open_stream FT_OPEN_STREAM -#define ft_open_pathname FT_OPEN_PATHNAME -#define ft_open_driver FT_OPEN_DRIVER -#define ft_open_params FT_OPEN_PARAMS - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Parameter */ - /* */ - /* <Description> */ - /* A simple structure used to pass more or less generic parameters to */ - /* @FT_Open_Face. */ - /* */ - /* <Fields> */ - /* tag :: A four-byte identification tag. */ - /* */ - /* data :: A pointer to the parameter data. */ - /* */ - /* <Note> */ - /* The ID and function of parameters are driver-specific. See the */ - /* various FT_PARAM_TAG_XXX flags for more information. */ - /* */ - typedef struct FT_Parameter_ - { - FT_ULong tag; - FT_Pointer data; - - } FT_Parameter; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Open_Args */ - /* */ - /* <Description> */ - /* A structure used to indicate how to open a new font file or */ - /* stream. A pointer to such a structure can be used as a parameter */ - /* for the functions @FT_Open_Face and @FT_Attach_Stream. */ - /* */ - /* <Fields> */ - /* flags :: A set of bit flags indicating how to use the */ - /* structure. */ - /* */ - /* memory_base :: The first byte of the file in memory. */ - /* */ - /* memory_size :: The size in bytes of the file in memory. */ - /* */ - /* pathname :: A pointer to an 8-bit file pathname. */ - /* */ - /* stream :: A handle to a source stream object. */ - /* */ - /* driver :: This field is exclusively used by @FT_Open_Face; */ - /* it simply specifies the font driver to use to open */ - /* the face. If set to~0, FreeType tries to load the */ - /* face with each one of the drivers in its list. */ - /* */ - /* num_params :: The number of extra parameters. */ - /* */ - /* params :: Extra parameters passed to the font driver when */ - /* opening a new face. */ - /* */ - /* <Note> */ - /* The stream type is determined by the contents of `flags' that */ - /* are tested in the following order by @FT_Open_Face: */ - /* */ - /* If the @FT_OPEN_MEMORY bit is set, assume that this is a */ - /* memory file of `memory_size' bytes, located at `memory_address'. */ - /* The data are are not copied, and the client is responsible for */ - /* releasing and destroying them _after_ the corresponding call to */ - /* @FT_Done_Face. */ - /* */ - /* Otherwise, if the @FT_OPEN_STREAM bit is set, assume that a */ - /* custom input stream `stream' is used. */ - /* */ - /* Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this */ - /* is a normal file and use `pathname' to open it. */ - /* */ - /* If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to */ - /* open the file with the driver whose handler is in `driver'. */ - /* */ - /* If the @FT_OPEN_PARAMS bit is set, the parameters given by */ - /* `num_params' and `params' is used. They are ignored otherwise. */ - /* */ - /* Ideally, both the `pathname' and `params' fields should be tagged */ - /* as `const'; this is missing for API backwards compatibility. In */ - /* other words, applications should treat them as read-only. */ - /* */ - typedef struct FT_Open_Args_ - { - FT_UInt flags; - const FT_Byte* memory_base; - FT_Long memory_size; - FT_String* pathname; - FT_Stream stream; - FT_Module driver; - FT_Int num_params; - FT_Parameter* params; - - } FT_Open_Args; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face */ - /* */ - /* <Description> */ - /* This function calls @FT_Open_Face to open a font by its pathname. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library resource. */ - /* */ - /* <Input> */ - /* pathname :: A path to the font file. */ - /* */ - /* face_index :: See @FT_Open_Face for a detailed description of this */ - /* parameter. */ - /* */ - /* <Output> */ - /* aface :: A handle to a new face object. If `face_index' is */ - /* greater than or equal to zero, it must be non-NULL. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* Use @FT_Done_Face to destroy the created @FT_Face object (along */ - /* with its slot and sizes). */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Face( FT_Library library, - const char* filepathname, - FT_Long face_index, - FT_Face *aface ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Memory_Face */ - /* */ - /* <Description> */ - /* This function calls @FT_Open_Face to open a font that has been */ - /* loaded into memory. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library resource. */ - /* */ - /* <Input> */ - /* file_base :: A pointer to the beginning of the font data. */ - /* */ - /* file_size :: The size of the memory chunk used by the font data. */ - /* */ - /* face_index :: See @FT_Open_Face for a detailed description of this */ - /* parameter. */ - /* */ - /* <Output> */ - /* aface :: A handle to a new face object. If `face_index' is */ - /* greater than or equal to zero, it must be non-NULL. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* You must not deallocate the memory before calling @FT_Done_Face. */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Memory_Face( FT_Library library, - const FT_Byte* file_base, - FT_Long file_size, - FT_Long face_index, - FT_Face *aface ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Open_Face */ - /* */ - /* <Description> */ - /* Create a face object from a given resource described by */ - /* @FT_Open_Args. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library resource. */ - /* */ - /* <Input> */ - /* args :: A pointer to an `FT_Open_Args' structure that must */ - /* be filled by the caller. */ - /* */ - /* face_index :: This field holds two different values. Bits 0-15 */ - /* are the index of the face in the font file (starting */ - /* with value~0). Set it to~0 if there is only one */ - /* face in the font file. */ - /* */ - /* Bits 16-30 are relevant to GX variation fonts only, */ - /* specifying the named instance index for the current */ - /* face index (starting with value~1; value~0 makes */ - /* FreeType ignore named instances). For non-GX fonts, */ - /* bits 16-30 are ignored. Assuming that you want to */ - /* access the third named instance in face~4, */ - /* `face_index' should be set to 0x00030004. If you */ - /* want to access face~4 without GX variation handling, */ - /* simply set `face_index' to value~4. */ - /* */ - /* FT_Open_Face and its siblings can be used to quickly */ - /* check whether the font format of a given font */ - /* resource is supported by FreeType. In general, if */ - /* the `face_index' argument is negative, the */ - /* function's return value is~0 if the font format is */ - /* recognized, or non-zero otherwise. The function */ - /* allocates a more or less empty face handle in */ - /* `*aface' (if `aface' isn't NULL); the only two */ - /* useful fields in this special case are */ - /* `face->num_faces' and `face->style_flags'. For any */ - /* negative value of `face_index', `face->num_faces' */ - /* gives the number of faces within the font file. For */ - /* the negative value `-(N+1)' (with `N' a 16-bit */ - /* value), bits 16-30 in `face->style_flags' give the */ - /* number of named instances in face `N' if we have a */ - /* GX variation font (or zero otherwise). After */ - /* examination, the returned @FT_Face structure should */ - /* be deallocated with a call to @FT_Done_Face. */ - /* */ - /* <Output> */ - /* aface :: A handle to a new face object. If `face_index' is */ - /* greater than or equal to zero, it must be non-NULL. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* Unlike FreeType 1.x, this function automatically creates a glyph */ - /* slot for the face object that can be accessed directly through */ - /* `face->glyph'. */ - /* */ - /* Each new face object created with this function also owns a */ - /* default @FT_Size object, accessible as `face->size'. */ - /* */ - /* One @FT_Library instance can have multiple face objects, this is, */ - /* @FT_Open_Face and its siblings can be called multiple times using */ - /* the same `library' argument. */ - /* */ - /* See the discussion of reference counters in the description of */ - /* @FT_Reference_Face. */ - /* */ - /* To loop over all faces, use code similar to the following snippet */ - /* (omitting the error handling). */ - /* */ - /* { */ - /* ... */ - /* FT_Face face; */ - /* FT_Long i, num_faces; */ - /* */ - /* */ - /* error = FT_Open_Face( library, args, -1, &face ); */ - /* if ( error ) { ... } */ - /* */ - /* num_faces = face->num_faces; */ - /* FT_Done_Face( face ); */ - /* */ - /* for ( i = 0; i < num_faces; i++ ) */ - /* { */ - /* ... */ - /* error = FT_Open_Face( library, args, i, &face ); */ - /* ... */ - /* FT_Done_Face( face ); */ - /* ... */ - /* } */ - /* } */ - /* */ - /* To loop over all valid values for `face_index', use something */ - /* similar to the following snippet, again without error handling. */ - /* The code accesses all faces immediately (thus only a single call */ - /* of `FT_Open_Face' within the do-loop), with and without named */ - /* instances. */ - /* */ - /* { */ - /* ... */ - /* FT_Face face; */ - /* */ - /* FT_Long num_faces = 0; */ - /* FT_Long num_instances = 0; */ - /* */ - /* FT_Long face_idx = 0; */ - /* FT_Long instance_idx = 0; */ - /* */ - /* */ - /* do */ - /* { */ - /* FT_Long id = ( instance_idx << 16 ) + face_idx; */ - /* */ - /* */ - /* error = FT_Open_Face( library, args, id, &face ); */ - /* if ( error ) { ... } */ - /* */ - /* num_faces = face->num_faces; */ - /* num_instances = face->style_flags >> 16; */ - /* */ - /* ... */ - /* */ - /* FT_Done_Face( face ); */ - /* */ - /* if ( instance_idx < num_instances ) */ - /* instance_idx++; */ - /* else */ - /* { */ - /* face_idx++; */ - /* instance_idx = 0; */ - /* } */ - /* */ - /* } while ( face_idx < num_faces ) */ - /* } */ - /* */ - FT_EXPORT( FT_Error ) - FT_Open_Face( FT_Library library, - const FT_Open_Args* args, - FT_Long face_index, - FT_Face *aface ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Attach_File */ - /* */ - /* <Description> */ - /* This function calls @FT_Attach_Stream to attach a file. */ - /* */ - /* <InOut> */ - /* face :: The target face object. */ - /* */ - /* <Input> */ - /* filepathname :: The pathname. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Attach_File( FT_Face face, - const char* filepathname ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Attach_Stream */ - /* */ - /* <Description> */ - /* `Attach' data to a face object. Normally, this is used to read */ - /* additional information for the face object. For example, you can */ - /* attach an AFM file that comes with a Type~1 font to get the */ - /* kerning values and other metrics. */ - /* */ - /* <InOut> */ - /* face :: The target face object. */ - /* */ - /* <Input> */ - /* parameters :: A pointer to @FT_Open_Args that must be filled by */ - /* the caller. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The meaning of the `attach' (i.e., what really happens when the */ - /* new file is read) is not fixed by FreeType itself. It really */ - /* depends on the font format (and thus the font driver). */ - /* */ - /* Client applications are expected to know what they are doing */ - /* when invoking this function. Most drivers simply do not implement */ - /* file attachments. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Attach_Stream( FT_Face face, - FT_Open_Args* parameters ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Reference_Face */ - /* */ - /* <Description> */ - /* A counter gets initialized to~1 at the time an @FT_Face structure */ - /* is created. This function increments the counter. @FT_Done_Face */ - /* then only destroys a face if the counter is~1, otherwise it simply */ - /* decrements the counter. */ - /* */ - /* This function helps in managing life-cycles of structures that */ - /* reference @FT_Face objects. */ - /* */ - /* <Input> */ - /* face :: A handle to a target face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Since> */ - /* 2.4.2 */ - /* */ - FT_EXPORT( FT_Error ) - FT_Reference_Face( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_Face */ - /* */ - /* <Description> */ - /* Discard a given face object, as well as all of its child slots and */ - /* sizes. */ - /* */ - /* <Input> */ - /* face :: A handle to a target face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* See the discussion of reference counters in the description of */ - /* @FT_Reference_Face. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Done_Face( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Select_Size */ - /* */ - /* <Description> */ - /* Select a bitmap strike. */ - /* */ - /* <InOut> */ - /* face :: A handle to a target face object. */ - /* */ - /* <Input> */ - /* strike_index :: The index of the bitmap strike in the */ - /* `available_sizes' field of @FT_FaceRec structure. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Select_Size( FT_Face face, - FT_Int strike_index ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Size_Request_Type */ - /* */ - /* <Description> */ - /* An enumeration type that lists the supported size request types. */ - /* */ - /* <Values> */ - /* FT_SIZE_REQUEST_TYPE_NOMINAL :: */ - /* The nominal size. The `units_per_EM' field of @FT_FaceRec is */ - /* used to determine both scaling values. */ - /* */ - /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */ - /* The real dimension. The sum of the the `ascender' and (minus */ - /* of) the `descender' fields of @FT_FaceRec are used to determine */ - /* both scaling values. */ - /* */ - /* FT_SIZE_REQUEST_TYPE_BBOX :: */ - /* The font bounding box. The width and height of the `bbox' field */ - /* of @FT_FaceRec are used to determine the horizontal and vertical */ - /* scaling value, respectively. */ - /* */ - /* FT_SIZE_REQUEST_TYPE_CELL :: */ - /* The `max_advance_width' field of @FT_FaceRec is used to */ - /* determine the horizontal scaling value; the vertical scaling */ - /* value is determined the same way as */ - /* @FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling */ - /* values are set to the smaller one. This type is useful if you */ - /* want to specify the font size for, say, a window of a given */ - /* dimension and 80x24 cells. */ - /* */ - /* FT_SIZE_REQUEST_TYPE_SCALES :: */ - /* Specify the scaling values directly. */ - /* */ - /* <Note> */ - /* The above descriptions only apply to scalable formats. For bitmap */ - /* formats, the behaviour is up to the driver. */ - /* */ - /* See the note section of @FT_Size_Metrics if you wonder how size */ - /* requesting relates to scaling values. */ - /* */ - typedef enum FT_Size_Request_Type_ - { - FT_SIZE_REQUEST_TYPE_NOMINAL, - FT_SIZE_REQUEST_TYPE_REAL_DIM, - FT_SIZE_REQUEST_TYPE_BBOX, - FT_SIZE_REQUEST_TYPE_CELL, - FT_SIZE_REQUEST_TYPE_SCALES, - - FT_SIZE_REQUEST_TYPE_MAX - - } FT_Size_Request_Type; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Size_RequestRec */ - /* */ - /* <Description> */ - /* A structure used to model a size request. */ - /* */ - /* <Fields> */ - /* type :: See @FT_Size_Request_Type. */ - /* */ - /* width :: The desired width. */ - /* */ - /* height :: The desired height. */ - /* */ - /* horiResolution :: The horizontal resolution. If set to zero, */ - /* `width' is treated as a 26.6 fractional pixel */ - /* value. */ - /* */ - /* vertResolution :: The vertical resolution. If set to zero, */ - /* `height' is treated as a 26.6 fractional pixel */ - /* value. */ - /* */ - /* <Note> */ - /* If `width' is zero, then the horizontal scaling value is set equal */ - /* to the vertical scaling value, and vice versa. */ - /* */ - typedef struct FT_Size_RequestRec_ - { - FT_Size_Request_Type type; - FT_Long width; - FT_Long height; - FT_UInt horiResolution; - FT_UInt vertResolution; - - } FT_Size_RequestRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Size_Request */ - /* */ - /* <Description> */ - /* A handle to a size request structure. */ - /* */ - typedef struct FT_Size_RequestRec_ *FT_Size_Request; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Request_Size */ - /* */ - /* <Description> */ - /* Resize the scale of the active @FT_Size object in a face. */ - /* */ - /* <InOut> */ - /* face :: A handle to a target face object. */ - /* */ - /* <Input> */ - /* req :: A pointer to a @FT_Size_RequestRec. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* Although drivers may select the bitmap strike matching the */ - /* request, you should not rely on this if you intend to select a */ - /* particular bitmap strike. Use @FT_Select_Size instead in that */ - /* case. */ - /* */ - /* The relation between the requested size and the resulting glyph */ - /* size is dependent entirely on how the size is defined in the */ - /* source face. The font designer chooses the final size of each */ - /* glyph relative to this size. For more information refer to */ - /* `http://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html' */ - /* */ - /* Don't use this function if you are using the FreeType cache API. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Request_Size( FT_Face face, - FT_Size_Request req ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Char_Size */ - /* */ - /* <Description> */ - /* This function calls @FT_Request_Size to request the nominal size */ - /* (in points). */ - /* */ - /* <InOut> */ - /* face :: A handle to a target face object. */ - /* */ - /* <Input> */ - /* char_width :: The nominal width, in 26.6 fractional points. */ - /* */ - /* char_height :: The nominal height, in 26.6 fractional points. */ - /* */ - /* horz_resolution :: The horizontal resolution in dpi. */ - /* */ - /* vert_resolution :: The vertical resolution in dpi. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* If either the character width or height is zero, it is set equal */ - /* to the other value. */ - /* */ - /* If either the horizontal or vertical resolution is zero, it is set */ - /* equal to the other value. */ - /* */ - /* A character width or height smaller than 1pt is set to 1pt; if */ - /* both resolution values are zero, they are set to 72dpi. */ - /* */ - /* Don't use this function if you are using the FreeType cache API. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_Char_Size( FT_Face face, - FT_F26Dot6 char_width, - FT_F26Dot6 char_height, - FT_UInt horz_resolution, - FT_UInt vert_resolution ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Pixel_Sizes */ - /* */ - /* <Description> */ - /* This function calls @FT_Request_Size to request the nominal size */ - /* (in pixels). */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Input> */ - /* pixel_width :: The nominal width, in pixels. */ - /* */ - /* pixel_height :: The nominal height, in pixels. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* You should not rely on the resulting glyphs matching, or being */ - /* constrained, to this pixel size. Refer to @FT_Request_Size to */ - /* understand how requested sizes relate to actual sizes. */ - /* */ - /* Don't use this function if you are using the FreeType cache API. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_Pixel_Sizes( FT_Face face, - FT_UInt pixel_width, - FT_UInt pixel_height ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Load_Glyph */ - /* */ - /* <Description> */ - /* A function used to load a single glyph into the glyph slot of a */ - /* face object. */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object where the glyph */ - /* is loaded. */ - /* */ - /* <Input> */ - /* glyph_index :: The index of the glyph in the font file. For */ - /* CID-keyed fonts (either in PS or in CFF format) */ - /* this argument specifies the CID value. */ - /* */ - /* load_flags :: A flag indicating what to load for this glyph. The */ - /* @FT_LOAD_XXX constants can be used to control the */ - /* glyph loading process (e.g., whether the outline */ - /* should be scaled, whether to load bitmaps or not, */ - /* whether to hint the outline, etc). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The loaded glyph may be transformed. See @FT_Set_Transform for */ - /* the details. */ - /* */ - /* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is */ - /* returned for invalid CID values (this is, for CID values that */ - /* don't have a corresponding glyph in the font). See the discussion */ - /* of the @FT_FACE_FLAG_CID_KEYED flag for more details. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Load_Glyph( FT_Face face, - FT_UInt glyph_index, - FT_Int32 load_flags ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Load_Char */ - /* */ - /* <Description> */ - /* A function used to load a single glyph into the glyph slot of a */ - /* face object, according to its character code. */ - /* */ - /* <InOut> */ - /* face :: A handle to a target face object where the glyph */ - /* is loaded. */ - /* */ - /* <Input> */ - /* char_code :: The glyph's character code, according to the */ - /* current charmap used in the face. */ - /* */ - /* load_flags :: A flag indicating what to load for this glyph. The */ - /* @FT_LOAD_XXX constants can be used to control the */ - /* glyph loading process (e.g., whether the outline */ - /* should be scaled, whether to load bitmaps or not, */ - /* whether to hint the outline, etc). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Load_Char( FT_Face face, - FT_ULong char_code, - FT_Int32 load_flags ); - - - /************************************************************************* - * - * @enum: - * FT_LOAD_XXX - * - * @description: - * A list of bit field constants used with @FT_Load_Glyph to indicate - * what kind of operations to perform during glyph loading. - * - * @values: - * FT_LOAD_DEFAULT :: - * Corresponding to~0, this value is used as the default glyph load - * operation. In this case, the following happens: - * - * 1. FreeType looks for a bitmap for the glyph corresponding to the - * face's current size. If one is found, the function returns. - * The bitmap data can be accessed from the glyph slot (see note - * below). - * - * 2. If no embedded bitmap is searched or found, FreeType looks for a - * scalable outline. If one is found, it is loaded from the font - * file, scaled to device pixels, then `hinted' to the pixel grid - * in order to optimize it. The outline data can be accessed from - * the glyph slot (see note below). - * - * Note that by default, the glyph loader doesn't render outlines into - * bitmaps. The following flags are used to modify this default - * behaviour to more specific and useful cases. - * - * FT_LOAD_NO_SCALE :: - * Don't scale the loaded outline glyph but keep it in font units. - * - * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and - * unsets @FT_LOAD_RENDER. - * - * If the font is `tricky' (see @FT_FACE_FLAG_TRICKY for more), using - * FT_LOAD_NO_SCALE usually yields meaningless outlines because the - * subglyphs must be scaled and positioned with hinting instructions. - * This can be solved by loading the font without FT_LOAD_NO_SCALE and - * setting the character size to `font->units_per_EM'. - * - * FT_LOAD_NO_HINTING :: - * Disable hinting. This generally generates `blurrier' bitmap glyphs - * when the glyph are rendered in any of the anti-aliased modes. See - * also the note below. - * - * This flag is implied by @FT_LOAD_NO_SCALE. - * - * FT_LOAD_RENDER :: - * Call @FT_Render_Glyph after the glyph is loaded. By default, the - * glyph is rendered in @FT_RENDER_MODE_NORMAL mode. This can be - * overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME. - * - * This flag is unset by @FT_LOAD_NO_SCALE. - * - * FT_LOAD_NO_BITMAP :: - * Ignore bitmap strikes when loading. Bitmap-only fonts ignore this - * flag. - * - * @FT_LOAD_NO_SCALE always sets this flag. - * - * FT_LOAD_VERTICAL_LAYOUT :: - * Load the glyph for vertical text layout. In particular, the - * `advance' value in the @FT_GlyphSlotRec structure is set to the - * `vertAdvance' value of the `metrics' field. - * - * In case @FT_HAS_VERTICAL doesn't return true, you shouldn't use - * this flag currently. Reason is that in this case vertical metrics - * get synthesized, and those values are not always consistent across - * various font formats. - * - * FT_LOAD_FORCE_AUTOHINT :: - * Indicates that the auto-hinter is preferred over the font's native - * hinter. See also the note below. - * - * FT_LOAD_PEDANTIC :: - * Indicates that the font driver should perform pedantic verifications - * during glyph loading. This is mostly used to detect broken glyphs - * in fonts. By default, FreeType tries to handle broken fonts also. - * - * In particular, errors from the TrueType bytecode engine are not - * passed to the application if this flag is not set; this might - * result in partially hinted or distorted glyphs in case a glyph's - * bytecode is buggy. - * - * FT_LOAD_NO_RECURSE :: - * Indicate that the font driver should not load composite glyphs - * recursively. Instead, it should set the `num_subglyph' and - * `subglyphs' values of the glyph slot accordingly, and set - * `glyph->format' to @FT_GLYPH_FORMAT_COMPOSITE. The description of - * subglyphs can then be accessed with @FT_Get_SubGlyph_Info. - * - * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM. - * - * FT_LOAD_IGNORE_TRANSFORM :: - * Indicates that the transform matrix set by @FT_Set_Transform should - * be ignored. - * - * FT_LOAD_MONOCHROME :: - * This flag is used with @FT_LOAD_RENDER to indicate that you want to - * render an outline glyph to a 1-bit monochrome bitmap glyph, with - * 8~pixels packed into each byte of the bitmap data. - * - * Note that this has no effect on the hinting algorithm used. You - * should rather use @FT_LOAD_TARGET_MONO so that the - * monochrome-optimized hinting algorithm is used. - * - * FT_LOAD_LINEAR_DESIGN :: - * Indicates that the `linearHoriAdvance' and `linearVertAdvance' - * fields of @FT_GlyphSlotRec should be kept in font units. See - * @FT_GlyphSlotRec for details. - * - * FT_LOAD_NO_AUTOHINT :: - * Disable auto-hinter. See also the note below. - * - * FT_LOAD_COLOR :: - * This flag is used to request loading of color embedded-bitmap - * images. The resulting color bitmaps, if available, will have the - * @FT_PIXEL_MODE_BGRA format. When the flag is not used and color - * bitmaps are found, they will be converted to 256-level gray - * bitmaps transparently. Those bitmaps will be in the - * @FT_PIXEL_MODE_GRAY format. - * - * FT_LOAD_COMPUTE_METRICS :: - * This flag sets computing glyph metrics without the use of bundled - * metrics tables (for example, the `hdmx' table in TrueType fonts). - * Well-behaving fonts have optimized bundled metrics and these should - * be used. This flag is mainly used by font validating or font - * editing applications, which need to ignore, verify, or edit those - * tables. - * - * Currently, this flag is only implemented for TrueType fonts. - * - * FT_LOAD_CROP_BITMAP :: - * Ignored. Deprecated. - * - * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH :: - * Ignored. Deprecated. - * - * @note: - * By default, hinting is enabled and the font's native hinter (see - * @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can - * disable hinting by setting @FT_LOAD_NO_HINTING or change the - * precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set - * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be - * used at all. - * - * See the description of @FT_FACE_FLAG_TRICKY for a special exception - * (affecting only a handful of Asian fonts). - * - * Besides deciding which hinter to use, you can also decide which - * hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details. - * - * Note that the auto-hinter needs a valid Unicode cmap (either a native - * one or synthesized by FreeType) for producing correct results. If a - * font provides an incorrect mapping (for example, assigning the - * character code U+005A, LATIN CAPITAL LETTER Z, to a glyph depicting a - * mathematical integral sign), the auto-hinter might produce useless - * results. - * - */ -#define FT_LOAD_DEFAULT 0x0 -#define FT_LOAD_NO_SCALE ( 1L << 0 ) -#define FT_LOAD_NO_HINTING ( 1L << 1 ) -#define FT_LOAD_RENDER ( 1L << 2 ) -#define FT_LOAD_NO_BITMAP ( 1L << 3 ) -#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) -#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) -#define FT_LOAD_CROP_BITMAP ( 1L << 6 ) -#define FT_LOAD_PEDANTIC ( 1L << 7 ) -#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) -#define FT_LOAD_NO_RECURSE ( 1L << 10 ) -#define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 ) -#define FT_LOAD_MONOCHROME ( 1L << 12 ) -#define FT_LOAD_LINEAR_DESIGN ( 1L << 13 ) -#define FT_LOAD_NO_AUTOHINT ( 1L << 15 ) - /* Bits 16..19 are used by `FT_LOAD_TARGET_' */ -#define FT_LOAD_COLOR ( 1L << 20 ) -#define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) - - /* */ - - /* used internally only by certain font drivers! */ -#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 ) -#define FT_LOAD_SBITS_ONLY ( 1L << 14 ) - - - /************************************************************************** - * - * @enum: - * FT_LOAD_TARGET_XXX - * - * @description: - * A list of values that are used to select a specific hinting algorithm - * to use by the hinter. You should OR one of these values to your - * `load_flags' when calling @FT_Load_Glyph. - * - * Note that font's native hinters may ignore the hinting algorithm you - * have specified (e.g., the TrueType bytecode interpreter). You can set - * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. - * - * Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it - * always implies @FT_LOAD_FORCE_AUTOHINT. - * - * @values: - * FT_LOAD_TARGET_NORMAL :: - * This corresponds to the default hinting algorithm, optimized for - * standard gray-level rendering. For monochrome output, use - * @FT_LOAD_TARGET_MONO instead. - * - * FT_LOAD_TARGET_LIGHT :: - * A lighter hinting algorithm for non-monochrome modes. Many - * generated glyphs are more fuzzy but better resemble its original - * shape. A bit like rendering on Mac OS~X. - * - * As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT. - * - * FT_LOAD_TARGET_MONO :: - * Strong hinting algorithm that should only be used for monochrome - * output. The result is probably unpleasant if the glyph is rendered - * in non-monochrome modes. - * - * FT_LOAD_TARGET_LCD :: - * A variant of @FT_LOAD_TARGET_NORMAL optimized for horizontally - * decimated LCD displays. - * - * FT_LOAD_TARGET_LCD_V :: - * A variant of @FT_LOAD_TARGET_NORMAL optimized for vertically - * decimated LCD displays. - * - * @note: - * You should use only _one_ of the FT_LOAD_TARGET_XXX values in your - * `load_flags'. They can't be ORed. - * - * If @FT_LOAD_RENDER is also set, the glyph is rendered in the - * corresponding mode (i.e., the mode that matches the used algorithm - * best). An exeption is FT_LOAD_TARGET_MONO since it implies - * @FT_LOAD_MONOCHROME. - * - * You can use a hinting algorithm that doesn't correspond to the same - * rendering mode. As an example, it is possible to use the `light' - * hinting algorithm and have the results rendered in horizontal LCD - * pixel mode, with code like - * - * { - * FT_Load_Glyph( face, glyph_index, - * load_flags | FT_LOAD_TARGET_LIGHT ); - * - * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); - * } - * - */ -#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 ) - -#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) -#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) -#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO ) -#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD ) -#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V ) - - - /************************************************************************** - * - * @macro: - * FT_LOAD_TARGET_MODE - * - * @description: - * Return the @FT_Render_Mode corresponding to a given - * @FT_LOAD_TARGET_XXX value. - * - */ -#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) ) - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Transform */ - /* */ - /* <Description> */ - /* A function used to set the transformation that is applied to glyph */ - /* images when they are loaded into a glyph slot through */ - /* @FT_Load_Glyph. */ - /* */ - /* <InOut> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Input> */ - /* matrix :: A pointer to the transformation's 2x2 matrix. Use~0 for */ - /* the identity matrix. */ - /* delta :: A pointer to the translation vector. Use~0 for the null */ - /* vector. */ - /* */ - /* <Note> */ - /* The transformation is only applied to scalable image formats after */ - /* the glyph has been loaded. It means that hinting is unaltered by */ - /* the transformation and is performed on the character size given in */ - /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */ - /* */ - /* Note that this also transforms the `face.glyph.advance' field, but */ - /* *not* the values in `face.glyph.metrics'. */ - /* */ - FT_EXPORT( void ) - FT_Set_Transform( FT_Face face, - FT_Matrix* matrix, - FT_Vector* delta ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Render_Mode */ - /* */ - /* <Description> */ - /* An enumeration type that lists the render modes supported by */ - /* FreeType~2. Each mode corresponds to a specific type of scanline */ - /* conversion performed on the outline. */ - /* */ - /* For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode' */ - /* field in the @FT_GlyphSlotRec structure gives the format of the */ - /* returned bitmap. */ - /* */ - /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity. */ - /* */ - /* <Values> */ - /* FT_RENDER_MODE_NORMAL :: */ - /* This is the default render mode; it corresponds to 8-bit */ - /* anti-aliased bitmaps. */ - /* */ - /* FT_RENDER_MODE_LIGHT :: */ - /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */ - /* defined as a separate value because render modes are also used */ - /* indirectly to define hinting algorithm selectors. See */ - /* @FT_LOAD_TARGET_XXX for details. */ - /* */ - /* FT_RENDER_MODE_MONO :: */ - /* This mode corresponds to 1-bit bitmaps (with 2~levels of */ - /* opacity). */ - /* */ - /* FT_RENDER_MODE_LCD :: */ - /* This mode corresponds to horizontal RGB and BGR sub-pixel */ - /* displays like LCD screens. It produces 8-bit bitmaps that are */ - /* 3~times the width of the original glyph outline in pixels, and */ - /* which use the @FT_PIXEL_MODE_LCD mode. */ - /* */ - /* FT_RENDER_MODE_LCD_V :: */ - /* This mode corresponds to vertical RGB and BGR sub-pixel displays */ - /* (like PDA screens, rotated LCD displays, etc.). It produces */ - /* 8-bit bitmaps that are 3~times the height of the original */ - /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */ - /* */ - /* <Note> */ - /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph can be */ - /* filtered to reduce color-fringes by using @FT_Library_SetLcdFilter */ - /* (not active in the default builds). It is up to the caller to */ - /* either call @FT_Library_SetLcdFilter (if available) or do the */ - /* filtering itself. */ - /* */ - /* The selected render mode only affects vector glyphs of a font. */ - /* Embedded bitmaps often have a different pixel mode like */ - /* @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform */ - /* them into 8-bit pixmaps. */ - /* */ - typedef enum FT_Render_Mode_ - { - FT_RENDER_MODE_NORMAL = 0, - FT_RENDER_MODE_LIGHT, - FT_RENDER_MODE_MONO, - FT_RENDER_MODE_LCD, - FT_RENDER_MODE_LCD_V, - - FT_RENDER_MODE_MAX - - } FT_Render_Mode; - - - /* these constants are deprecated; use the corresponding */ - /* `FT_Render_Mode' values instead */ -#define ft_render_mode_normal FT_RENDER_MODE_NORMAL -#define ft_render_mode_mono FT_RENDER_MODE_MONO - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Render_Glyph */ - /* */ - /* <Description> */ - /* Convert a given glyph image to a bitmap. It does so by inspecting */ - /* the glyph image format, finding the relevant renderer, and */ - /* invoking it. */ - /* */ - /* <InOut> */ - /* slot :: A handle to the glyph slot containing the image to */ - /* convert. */ - /* */ - /* <Input> */ - /* render_mode :: This is the render mode used to render the glyph */ - /* image into a bitmap. See @FT_Render_Mode for a */ - /* list of possible values. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* To get meaningful results, font scaling values must be set with */ - /* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Render_Glyph( FT_GlyphSlot slot, - FT_Render_Mode render_mode ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Kerning_Mode */ - /* */ - /* <Description> */ - /* An enumeration used to specify which kerning values to return in */ - /* @FT_Get_Kerning. */ - /* */ - /* <Values> */ - /* FT_KERNING_DEFAULT :: Return grid-fitted kerning distances in */ - /* pixels (value is~0). Whether they are */ - /* scaled depends on @FT_LOAD_NO_SCALE. */ - /* */ - /* FT_KERNING_UNFITTED :: Return un-grid-fitted kerning distances in */ - /* 26.6 fractional pixels. Whether they are */ - /* scaled depends on @FT_LOAD_NO_SCALE. */ - /* */ - /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */ - /* units. */ - /* */ - /* <Note> */ - /* FT_KERNING_DEFAULT returns full pixel values; it also makes */ - /* FreeType heuristically scale down kerning distances at small ppem */ - /* values so that they don't become too big. */ - /* */ - typedef enum FT_Kerning_Mode_ - { - FT_KERNING_DEFAULT = 0, - FT_KERNING_UNFITTED, - FT_KERNING_UNSCALED - - } FT_Kerning_Mode; - - - /* these constants are deprecated; use the corresponding */ - /* `FT_Kerning_Mode' values instead */ -#define ft_kerning_default FT_KERNING_DEFAULT -#define ft_kerning_unfitted FT_KERNING_UNFITTED -#define ft_kerning_unscaled FT_KERNING_UNSCALED - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Kerning */ - /* */ - /* <Description> */ - /* Return the kerning vector between two glyphs of a same face. */ - /* */ - /* <Input> */ - /* face :: A handle to a source face object. */ - /* */ - /* left_glyph :: The index of the left glyph in the kern pair. */ - /* */ - /* right_glyph :: The index of the right glyph in the kern pair. */ - /* */ - /* kern_mode :: See @FT_Kerning_Mode for more information. */ - /* Determines the scale and dimension of the returned */ - /* kerning vector. */ - /* */ - /* <Output> */ - /* akerning :: The kerning vector. This is either in font units, */ - /* fractional pixels (26.6 format), or pixels for */ - /* scalable formats, and in pixels for fixed-sizes */ - /* formats. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* Only horizontal layouts (left-to-right & right-to-left) are */ - /* supported by this method. Other layouts, or more sophisticated */ - /* kernings, are out of the scope of this API function -- they can be */ - /* implemented through format-specific interfaces. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Kerning( FT_Face face, - FT_UInt left_glyph, - FT_UInt right_glyph, - FT_UInt kern_mode, - FT_Vector *akerning ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Track_Kerning */ - /* */ - /* <Description> */ - /* Return the track kerning for a given face object at a given size. */ - /* */ - /* <Input> */ - /* face :: A handle to a source face object. */ - /* */ - /* point_size :: The point size in 16.16 fractional points. */ - /* */ - /* degree :: The degree of tightness. Increasingly negative */ - /* values represent tighter track kerning, while */ - /* increasingly positive values represent looser track */ - /* kerning. Value zero means no track kerning. */ - /* */ - /* <Output> */ - /* akerning :: The kerning in 16.16 fractional points, to be */ - /* uniformly applied between all glyphs. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* Currently, only the Type~1 font driver supports track kerning, */ - /* using data from AFM files (if attached with @FT_Attach_File or */ - /* @FT_Attach_Stream). */ - /* */ - /* Only very few AFM files come with track kerning data; please refer */ - /* to the Adobe's AFM specification for more details. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Track_Kerning( FT_Face face, - FT_Fixed point_size, - FT_Int degree, - FT_Fixed* akerning ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Glyph_Name */ - /* */ - /* <Description> */ - /* Retrieve the ASCII name of a given glyph in a face. This only */ - /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1. */ - /* */ - /* <Input> */ - /* face :: A handle to a source face object. */ - /* */ - /* glyph_index :: The glyph index. */ - /* */ - /* buffer_max :: The maximum number of bytes available in the */ - /* buffer. */ - /* */ - /* <Output> */ - /* buffer :: A pointer to a target buffer where the name is */ - /* copied to. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* An error is returned if the face doesn't provide glyph names or if */ - /* the glyph index is invalid. In all cases of failure, the first */ - /* byte of `buffer' is set to~0 to indicate an empty name. */ - /* */ - /* The glyph name is truncated to fit within the buffer if it is too */ - /* long. The returned string is always zero-terminated. */ - /* */ - /* Be aware that FreeType reorders glyph indices internally so that */ - /* glyph index~0 always corresponds to the `missing glyph' (called */ - /* `.notdef'). */ - /* */ - /* This function always returns an error if the config macro */ - /* `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoptions.h'. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Glyph_Name( FT_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Postscript_Name */ - /* */ - /* <Description> */ - /* Retrieve the ASCII PostScript name of a given face, if available. */ - /* This only works with PostScript and TrueType fonts. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Return> */ - /* A pointer to the face's PostScript name. NULL if unavailable. */ - /* */ - /* <Note> */ - /* The returned pointer is owned by the face and is destroyed with */ - /* it. */ - /* */ - FT_EXPORT( const char* ) - FT_Get_Postscript_Name( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Select_Charmap */ - /* */ - /* <Description> */ - /* Select a given charmap by its encoding tag (as listed in */ - /* `freetype.h'). */ - /* */ - /* <InOut> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Input> */ - /* encoding :: A handle to the selected encoding. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* This function returns an error if no charmap in the face */ - /* corresponds to the encoding queried here. */ - /* */ - /* Because many fonts contain more than a single cmap for Unicode */ - /* encoding, this function has some special code to select the one */ - /* that covers Unicode best (`best' in the sense that a UCS-4 cmap is */ - /* preferred to a UCS-2 cmap). It is thus preferable to */ - /* @FT_Set_Charmap in this case. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Select_Charmap( FT_Face face, - FT_Encoding encoding ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Charmap */ - /* */ - /* <Description> */ - /* Select a given charmap for character code to glyph index mapping. */ - /* */ - /* <InOut> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Input> */ - /* charmap :: A handle to the selected charmap. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* This function returns an error if the charmap is not part of */ - /* the face (i.e., if it is not listed in the `face->charmaps' */ - /* table). */ - /* */ - /* It also fails if a type~14 charmap is selected. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_Charmap( FT_Face face, - FT_CharMap charmap ); - - - /************************************************************************* - * - * @function: - * FT_Get_Charmap_Index - * - * @description: - * Retrieve index of a given charmap. - * - * @input: - * charmap :: - * A handle to a charmap. - * - * @return: - * The index into the array of character maps within the face to which - * `charmap' belongs. If an error occurs, -1 is returned. - * - */ - FT_EXPORT( FT_Int ) - FT_Get_Charmap_Index( FT_CharMap charmap ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Char_Index */ - /* */ - /* <Description> */ - /* Return the glyph index of a given character code. This function */ - /* uses a charmap object to do the mapping. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* charcode :: The character code. */ - /* */ - /* <Return> */ - /* The glyph index. 0~means `undefined character code'. */ - /* */ - /* <Note> */ - /* If you use FreeType to manipulate the contents of font files */ - /* directly, be aware that the glyph index returned by this function */ - /* doesn't always correspond to the internal indices used within the */ - /* file. This is done to ensure that value~0 always corresponds to */ - /* the `missing glyph'. If the first glyph is not named `.notdef', */ - /* then for Type~1 and Type~42 fonts, `.notdef' will be moved into */ - /* the glyph ID~0 position, and whatever was there will be moved to */ - /* the position `.notdef' had. For Type~1 fonts, if there is no */ - /* `.notdef' glyph at all, then one will be created at index~0 and */ - /* whatever was there will be moved to the last index -- Type~42 */ - /* fonts are considered invalid under this condition. */ - /* */ - FT_EXPORT( FT_UInt ) - FT_Get_Char_Index( FT_Face face, - FT_ULong charcode ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_First_Char */ - /* */ - /* <Description> */ - /* This function is used to return the first character code in the */ - /* current charmap of a given face. It also returns the */ - /* corresponding glyph index. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Output> */ - /* agindex :: Glyph index of first character code. 0~if charmap is */ - /* empty. */ - /* */ - /* <Return> */ - /* The charmap's first character code. */ - /* */ - /* <Note> */ - /* You should use this function with @FT_Get_Next_Char to be able to */ - /* parse all character codes available in a given charmap. The code */ - /* should look like this: */ - /* */ - /* { */ - /* FT_ULong charcode; */ - /* FT_UInt gindex; */ - /* */ - /* */ - /* charcode = FT_Get_First_Char( face, &gindex ); */ - /* while ( gindex != 0 ) */ - /* { */ - /* ... do something with (charcode,gindex) pair ... */ - /* */ - /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */ - /* } */ - /* } */ - /* */ - /* Be aware that character codes can have values up to 0xFFFFFFFF; */ - /* this might happen for non-Unicode or malformed cmaps. However, */ - /* even with regular Unicode encoding, so-called `last resort fonts' */ - /* (using SFNT cmap format 13, see function @FT_Get_CMap_Format) */ - /* normally have entries for all Unicode characters up to 0x1FFFFF, */ - /* which can cause *a lot* of iterations. */ - /* */ - /* Note that `*agindex' is set to~0 if the charmap is empty. The */ - /* result itself can be~0 in two cases: if the charmap is empty or */ - /* if the value~0 is the first valid character code. */ - /* */ - FT_EXPORT( FT_ULong ) - FT_Get_First_Char( FT_Face face, - FT_UInt *agindex ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Next_Char */ - /* */ - /* <Description> */ - /* This function is used to return the next character code in the */ - /* current charmap of a given face following the value `char_code', */ - /* as well as the corresponding glyph index. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* char_code :: The starting character code. */ - /* */ - /* <Output> */ - /* agindex :: Glyph index of next character code. 0~if charmap */ - /* is empty. */ - /* */ - /* <Return> */ - /* The charmap's next character code. */ - /* */ - /* <Note> */ - /* You should use this function with @FT_Get_First_Char to walk */ - /* over all character codes available in a given charmap. See the */ - /* note for this function for a simple code example. */ - /* */ - /* Note that `*agindex' is set to~0 when there are no more codes in */ - /* the charmap. */ - /* */ - FT_EXPORT( FT_ULong ) - FT_Get_Next_Char( FT_Face face, - FT_ULong char_code, - FT_UInt *agindex ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Name_Index */ - /* */ - /* <Description> */ - /* Return the glyph index of a given glyph name. This function uses */ - /* driver specific objects to do the translation. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* glyph_name :: The glyph name. */ - /* */ - /* <Return> */ - /* The glyph index. 0~means `undefined character code'. */ - /* */ - FT_EXPORT( FT_UInt ) - FT_Get_Name_Index( FT_Face face, - FT_String* glyph_name ); - - - /************************************************************************* - * - * @macro: - * FT_SUBGLYPH_FLAG_XXX - * - * @description: - * A list of constants used to describe subglyphs. Please refer to the - * TrueType specification for the meaning of the various flags. - * - * @values: - * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS :: - * FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES :: - * FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID :: - * FT_SUBGLYPH_FLAG_SCALE :: - * FT_SUBGLYPH_FLAG_XY_SCALE :: - * FT_SUBGLYPH_FLAG_2X2 :: - * FT_SUBGLYPH_FLAG_USE_MY_METRICS :: - * - */ -#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 -#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 -#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 -#define FT_SUBGLYPH_FLAG_SCALE 8 -#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 -#define FT_SUBGLYPH_FLAG_2X2 0x80 -#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 - - - /************************************************************************* - * - * @func: - * FT_Get_SubGlyph_Info - * - * @description: - * Retrieve a description of a given subglyph. Only use it if - * `glyph->format' is @FT_GLYPH_FORMAT_COMPOSITE; an error is - * returned otherwise. - * - * @input: - * glyph :: - * The source glyph slot. - * - * sub_index :: - * The index of the subglyph. Must be less than - * `glyph->num_subglyphs'. - * - * @output: - * p_index :: - * The glyph index of the subglyph. - * - * p_flags :: - * The subglyph flags, see @FT_SUBGLYPH_FLAG_XXX. - * - * p_arg1 :: - * The subglyph's first argument (if any). - * - * p_arg2 :: - * The subglyph's second argument (if any). - * - * p_transform :: - * The subglyph transformation (if any). - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be - * interpreted depending on the flags returned in `*p_flags'. See the - * TrueType specification for details. - * - */ - FT_EXPORT( FT_Error ) - FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, - FT_UInt sub_index, - FT_Int *p_index, - FT_UInt *p_flags, - FT_Int *p_arg1, - FT_Int *p_arg2, - FT_Matrix *p_transform ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_FSTYPE_XXX */ - /* */ - /* <Description> */ - /* A list of bit flags used in the `fsType' field of the OS/2 table */ - /* in a TrueType or OpenType font and the `FSType' entry in a */ - /* PostScript font. These bit flags are returned by */ - /* @FT_Get_FSType_Flags; they inform client applications of embedding */ - /* and subsetting restrictions associated with a font. */ - /* */ - /* See */ - /* http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf */ - /* for more details. */ - /* */ - /* <Values> */ - /* FT_FSTYPE_INSTALLABLE_EMBEDDING :: */ - /* Fonts with no fsType bit set may be embedded and permanently */ - /* installed on the remote system by an application. */ - /* */ - /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING :: */ - /* Fonts that have only this bit set must not be modified, embedded */ - /* or exchanged in any manner without first obtaining permission of */ - /* the font software copyright owner. */ - /* */ - /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING :: */ - /* If this bit is set, the font may be embedded and temporarily */ - /* loaded on the remote system. Documents containing Preview & */ - /* Print fonts must be opened `read-only'; no edits can be applied */ - /* to the document. */ - /* */ - /* FT_FSTYPE_EDITABLE_EMBEDDING :: */ - /* If this bit is set, the font may be embedded but must only be */ - /* installed temporarily on other systems. In contrast to Preview */ - /* & Print fonts, documents containing editable fonts may be opened */ - /* for reading, editing is permitted, and changes may be saved. */ - /* */ - /* FT_FSTYPE_NO_SUBSETTING :: */ - /* If this bit is set, the font may not be subsetted prior to */ - /* embedding. */ - /* */ - /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY :: */ - /* If this bit is set, only bitmaps contained in the font may be */ - /* embedded; no outline data may be embedded. If there are no */ - /* bitmaps available in the font, then the font is unembeddable. */ - /* */ - /* <Note> */ - /* The flags are ORed together, thus more than a single value can be */ - /* returned. */ - /* */ - /* While the fsType flags can indicate that a font may be embedded, a */ - /* license with the font vendor may be separately required to use the */ - /* font in this way. */ - /* */ -#define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000 -#define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002 -#define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004 -#define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008 -#define FT_FSTYPE_NO_SUBSETTING 0x0100 -#define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200 - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_FSType_Flags */ - /* */ - /* <Description> */ - /* Return the fsType flags for a font. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Return> */ - /* The fsType flags, @FT_FSTYPE_XXX. */ - /* */ - /* <Note> */ - /* Use this function rather than directly reading the `fs_type' field */ - /* in the @PS_FontInfoRec structure, which is only guaranteed to */ - /* return the correct results for Type~1 fonts. */ - /* */ - /* <Since> */ - /* 2.3.8 */ - /* */ - FT_EXPORT( FT_UShort ) - FT_Get_FSType_Flags( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* glyph_variants */ - /* */ - /* <Title> */ - /* Glyph Variants */ - /* */ - /* <Abstract> */ - /* The FreeType~2 interface to Unicode Ideographic Variation */ - /* Sequences (IVS), using the SFNT cmap format~14. */ - /* */ - /* <Description> */ - /* Many CJK characters have variant forms. They are a sort of grey */ - /* area somewhere between being totally irrelevant and semantically */ - /* distinct; for this reason, the Unicode consortium decided to */ - /* introduce Ideographic Variation Sequences (IVS), consisting of a */ - /* Unicode base character and one of 240 variant selectors */ - /* (U+E0100-U+E01EF), instead of further extending the already huge */ - /* code range for CJK characters. */ - /* */ - /* An IVS is registered and unique; for further details please refer */ - /* to Unicode Technical Standard #37, the Ideographic Variation */ - /* Database: */ - /* */ - /* http://www.unicode.org/reports/tr37/ */ - /* */ - /* To date (November 2014), the character with the most variants is */ - /* U+9089, having 32 such IVS. */ - /* */ - /* Adobe and MS decided to support IVS with a new cmap subtable */ - /* (format~14). It is an odd subtable because it is not a mapping of */ - /* input code points to glyphs, but contains lists of all variants */ - /* supported by the font. */ - /* */ - /* A variant may be either `default' or `non-default'. A default */ - /* variant is the one you will get for that code point if you look it */ - /* up in the standard Unicode cmap. A non-default variant is a */ - /* different glyph. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_GetCharVariantIndex */ - /* */ - /* <Description> */ - /* Return the glyph index of a given character code as modified by */ - /* the variation selector. */ - /* */ - /* <Input> */ - /* face :: */ - /* A handle to the source face object. */ - /* */ - /* charcode :: */ - /* The character code point in Unicode. */ - /* */ - /* variantSelector :: */ - /* The Unicode code point of the variation selector. */ - /* */ - /* <Return> */ - /* The glyph index. 0~means either `undefined character code', or */ - /* `undefined selector code', or `no variation selector cmap */ - /* subtable', or `current CharMap is not Unicode'. */ - /* */ - /* <Note> */ - /* If you use FreeType to manipulate the contents of font files */ - /* directly, be aware that the glyph index returned by this function */ - /* doesn't always correspond to the internal indices used within */ - /* the file. This is done to ensure that value~0 always corresponds */ - /* to the `missing glyph'. */ - /* */ - /* This function is only meaningful if */ - /* a) the font has a variation selector cmap sub table, */ - /* and */ - /* b) the current charmap has a Unicode encoding. */ - /* */ - /* <Since> */ - /* 2.3.6 */ - /* */ - FT_EXPORT( FT_UInt ) - FT_Face_GetCharVariantIndex( FT_Face face, - FT_ULong charcode, - FT_ULong variantSelector ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_GetCharVariantIsDefault */ - /* */ - /* <Description> */ - /* Check whether this variant of this Unicode character is the one to */ - /* be found in the `cmap'. */ - /* */ - /* <Input> */ - /* face :: */ - /* A handle to the source face object. */ - /* */ - /* charcode :: */ - /* The character codepoint in Unicode. */ - /* */ - /* variantSelector :: */ - /* The Unicode codepoint of the variation selector. */ - /* */ - /* <Return> */ - /* 1~if found in the standard (Unicode) cmap, 0~if found in the */ - /* variation selector cmap, or -1 if it is not a variant. */ - /* */ - /* <Note> */ - /* This function is only meaningful if the font has a variation */ - /* selector cmap subtable. */ - /* */ - /* <Since> */ - /* 2.3.6 */ - /* */ - FT_EXPORT( FT_Int ) - FT_Face_GetCharVariantIsDefault( FT_Face face, - FT_ULong charcode, - FT_ULong variantSelector ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_GetVariantSelectors */ - /* */ - /* <Description> */ - /* Return a zero-terminated list of Unicode variant selectors found */ - /* in the font. */ - /* */ - /* <Input> */ - /* face :: */ - /* A handle to the source face object. */ - /* */ - /* <Return> */ - /* A pointer to an array of selector code points, or NULL if there is */ - /* no valid variant selector cmap subtable. */ - /* */ - /* <Note> */ - /* The last item in the array is~0; the array is owned by the */ - /* @FT_Face object but can be overwritten or released on the next */ - /* call to a FreeType function. */ - /* */ - /* <Since> */ - /* 2.3.6 */ - /* */ - FT_EXPORT( FT_UInt32* ) - FT_Face_GetVariantSelectors( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_GetVariantsOfChar */ - /* */ - /* <Description> */ - /* Return a zero-terminated list of Unicode variant selectors found */ - /* for the specified character code. */ - /* */ - /* <Input> */ - /* face :: */ - /* A handle to the source face object. */ - /* */ - /* charcode :: */ - /* The character codepoint in Unicode. */ - /* */ - /* <Return> */ - /* A pointer to an array of variant selector code points that are */ - /* active for the given character, or NULL if the corresponding list */ - /* is empty. */ - /* */ - /* <Note> */ - /* The last item in the array is~0; the array is owned by the */ - /* @FT_Face object but can be overwritten or released on the next */ - /* call to a FreeType function. */ - /* */ - /* <Since> */ - /* 2.3.6 */ - /* */ - FT_EXPORT( FT_UInt32* ) - FT_Face_GetVariantsOfChar( FT_Face face, - FT_ULong charcode ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_GetCharsOfVariant */ - /* */ - /* <Description> */ - /* Return a zero-terminated list of Unicode character codes found for */ - /* the specified variant selector. */ - /* */ - /* <Input> */ - /* face :: */ - /* A handle to the source face object. */ - /* */ - /* variantSelector :: */ - /* The variant selector code point in Unicode. */ - /* */ - /* <Return> */ - /* A list of all the code points that are specified by this selector */ - /* (both default and non-default codes are returned) or NULL if there */ - /* is no valid cmap or the variant selector is invalid. */ - /* */ - /* <Note> */ - /* The last item in the array is~0; the array is owned by the */ - /* @FT_Face object but can be overwritten or released on the next */ - /* call to a FreeType function. */ - /* */ - /* <Since> */ - /* 2.3.6 */ - /* */ - FT_EXPORT( FT_UInt32* ) - FT_Face_GetCharsOfVariant( FT_Face face, - FT_ULong variantSelector ); - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* computations */ - /* */ - /* <Title> */ - /* Computations */ - /* */ - /* <Abstract> */ - /* Crunching fixed numbers and vectors. */ - /* */ - /* <Description> */ - /* This section contains various functions used to perform */ - /* computations on 16.16 fixed-float numbers or 2d vectors. */ - /* */ - /* <Order> */ - /* FT_MulDiv */ - /* FT_MulFix */ - /* FT_DivFix */ - /* FT_RoundFix */ - /* FT_CeilFix */ - /* FT_FloorFix */ - /* FT_Vector_Transform */ - /* FT_Matrix_Multiply */ - /* FT_Matrix_Invert */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_MulDiv */ - /* */ - /* <Description> */ - /* A very simple function used to perform the computation `(a*b)/c' */ - /* with maximum accuracy (it uses a 64-bit intermediate integer */ - /* whenever necessary). */ - /* */ - /* This function isn't necessarily as fast as some processor specific */ - /* operations, but is at least completely portable. */ - /* */ - /* <Input> */ - /* a :: The first multiplier. */ - /* b :: The second multiplier. */ - /* c :: The divisor. */ - /* */ - /* <Return> */ - /* The result of `(a*b)/c'. This function never traps when trying to */ - /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ - /* on the signs of `a' and `b'. */ - /* */ - FT_EXPORT( FT_Long ) - FT_MulDiv( FT_Long a, - FT_Long b, - FT_Long c ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_MulFix */ - /* */ - /* <Description> */ - /* A very simple function used to perform the computation */ - /* `(a*b)/0x10000' with maximum accuracy. Most of the time this is */ - /* used to multiply a given value by a 16.16 fixed-point factor. */ - /* */ - /* <Input> */ - /* a :: The first multiplier. */ - /* b :: The second multiplier. Use a 16.16 factor here whenever */ - /* possible (see note below). */ - /* */ - /* <Return> */ - /* The result of `(a*b)/0x10000'. */ - /* */ - /* <Note> */ - /* This function has been optimized for the case where the absolute */ - /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ - /* As this happens mainly when scaling from notional units to */ - /* fractional pixels in FreeType, it resulted in noticeable speed */ - /* improvements between versions 2.x and 1.x. */ - /* */ - /* As a conclusion, always try to place a 16.16 factor as the */ - /* _second_ argument of this function; this can make a great */ - /* difference. */ - /* */ - FT_EXPORT( FT_Long ) - FT_MulFix( FT_Long a, - FT_Long b ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_DivFix */ - /* */ - /* <Description> */ - /* A very simple function used to perform the computation */ - /* `(a*0x10000)/b' with maximum accuracy. Most of the time, this is */ - /* used to divide a given value by a 16.16 fixed-point factor. */ - /* */ - /* <Input> */ - /* a :: The numerator. */ - /* b :: The denominator. Use a 16.16 factor here. */ - /* */ - /* <Return> */ - /* The result of `(a*0x10000)/b'. */ - /* */ - FT_EXPORT( FT_Long ) - FT_DivFix( FT_Long a, - FT_Long b ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_RoundFix */ - /* */ - /* <Description> */ - /* A very simple function used to round a 16.16 fixed number. */ - /* */ - /* <Input> */ - /* a :: The number to be rounded. */ - /* */ - /* <Return> */ - /* `a' rounded to nearest 16.16 fixed integer, halfway cases away */ - /* from zero. */ - /* */ - FT_EXPORT( FT_Fixed ) - FT_RoundFix( FT_Fixed a ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_CeilFix */ - /* */ - /* <Description> */ - /* A very simple function used to compute the ceiling function of a */ - /* 16.16 fixed number. */ - /* */ - /* <Input> */ - /* a :: The number for which the ceiling function is to be computed. */ - /* */ - /* <Return> */ - /* `a' rounded towards plus infinity. */ - /* */ - FT_EXPORT( FT_Fixed ) - FT_CeilFix( FT_Fixed a ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_FloorFix */ - /* */ - /* <Description> */ - /* A very simple function used to compute the floor function of a */ - /* 16.16 fixed number. */ - /* */ - /* <Input> */ - /* a :: The number for which the floor function is to be computed. */ - /* */ - /* <Return> */ - /* `a' rounded towards minus infinity. */ - /* */ - FT_EXPORT( FT_Fixed ) - FT_FloorFix( FT_Fixed a ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Vector_Transform */ - /* */ - /* <Description> */ - /* Transform a single vector through a 2x2 matrix. */ - /* */ - /* <InOut> */ - /* vector :: The target vector to transform. */ - /* */ - /* <Input> */ - /* matrix :: A pointer to the source 2x2 matrix. */ - /* */ - /* <Note> */ - /* The result is undefined if either `vector' or `matrix' is invalid. */ - /* */ - FT_EXPORT( void ) - FT_Vector_Transform( FT_Vector* vec, - const FT_Matrix* matrix ); - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* version */ - /* */ - /* <Title> */ - /* FreeType Version */ - /* */ - /* <Abstract> */ - /* Functions and macros related to FreeType versions. */ - /* */ - /* <Description> */ - /* Note that those functions and macros are of limited use because */ - /* even a new release of FreeType with only documentation changes */ - /* increases the version number. */ - /* */ - /* <Order> */ - /* FT_Library_Version */ - /* */ - /* FREETYPE_MAJOR */ - /* FREETYPE_MINOR */ - /* FREETYPE_PATCH */ - /* */ - /* FT_Face_CheckTrueTypePatents */ - /* FT_Face_SetUnpatentedHinting */ - /* */ - /* FREETYPE_XXX */ - /* */ - /*************************************************************************/ - - - /************************************************************************* - * - * @enum: - * FREETYPE_XXX - * - * @description: - * These three macros identify the FreeType source code version. - * Use @FT_Library_Version to access them at runtime. - * - * @values: - * FREETYPE_MAJOR :: The major version number. - * FREETYPE_MINOR :: The minor version number. - * FREETYPE_PATCH :: The patch level. - * - * @note: - * The version number of FreeType if built as a dynamic link library - * with the `libtool' package is _not_ controlled by these three - * macros. - * - */ -#define FREETYPE_MAJOR 2 -#define FREETYPE_MINOR 6 -#define FREETYPE_PATCH 1 - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Library_Version */ - /* */ - /* <Description> */ - /* Return the version of the FreeType library being used. This is */ - /* useful when dynamically linking to the library, since one cannot */ - /* use the macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and */ - /* @FREETYPE_PATCH. */ - /* */ - /* <Input> */ - /* library :: A source library handle. */ - /* */ - /* <Output> */ - /* amajor :: The major version number. */ - /* */ - /* aminor :: The minor version number. */ - /* */ - /* apatch :: The patch version number. */ - /* */ - /* <Note> */ - /* The reason why this function takes a `library' argument is because */ - /* certain programs implement library initialization in a custom way */ - /* that doesn't use @FT_Init_FreeType. */ - /* */ - /* In such cases, the library version might not be available before */ - /* the library object has been created. */ - /* */ - FT_EXPORT( void ) - FT_Library_Version( FT_Library library, - FT_Int *amajor, - FT_Int *aminor, - FT_Int *apatch ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_CheckTrueTypePatents */ - /* */ - /* <Description> */ - /* Parse all bytecode instructions of a TrueType font file to check */ - /* whether any of the patented opcodes are used. This is only useful */ - /* if you want to be able to use the unpatented hinter with */ - /* fonts that do *not* use these opcodes. */ - /* */ - /* Note that this function parses *all* glyph instructions in the */ - /* font file, which may be slow. */ - /* */ - /* <Input> */ - /* face :: A face handle. */ - /* */ - /* <Return> */ - /* 1~if this is a TrueType font that uses one of the patented */ - /* opcodes, 0~otherwise. */ - /* */ - /* <Note> */ - /* Since May 2010, TrueType hinting is no longer patented. */ - /* */ - /* <Since> */ - /* 2.3.5 */ - /* */ - FT_EXPORT( FT_Bool ) - FT_Face_CheckTrueTypePatents( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Face_SetUnpatentedHinting */ - /* */ - /* <Description> */ - /* Enable or disable the unpatented hinter for a given face. */ - /* Only enable it if you have determined that the face doesn't */ - /* use any patented opcodes (see @FT_Face_CheckTrueTypePatents). */ - /* */ - /* <Input> */ - /* face :: A face handle. */ - /* */ - /* value :: New boolean setting. */ - /* */ - /* <Return> */ - /* The old setting value. This will always be false if this is not */ - /* an SFNT font, or if the unpatented hinter is not compiled in this */ - /* instance of the library. */ - /* */ - /* <Note> */ - /* Since May 2010, TrueType hinting is no longer patented. */ - /* */ - /* <Since> */ - /* 2.3.5 */ - /* */ - FT_EXPORT( FT_Bool ) - FT_Face_SetUnpatentedHinting( FT_Face face, - FT_Bool value ); - - /* */ - - -FT_END_HEADER - -#endif /* __FREETYPE_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftadvanc.h b/third_party/freetype/include/freetype/ftadvanc.h deleted file mode 100644 index b4d2aed567730a8b103ca7ad593bedc5b26bc5a3..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftadvanc.h +++ /dev/null @@ -1,187 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftadvanc.h */ -/* */ -/* Quick computation of advance widths (specification only). */ -/* */ -/* Copyright 2008-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTADVANC_H__ -#define __FTADVANC_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /************************************************************************** - * - * @section: - * quick_advance - * - * @title: - * Quick retrieval of advance values - * - * @abstract: - * Retrieve horizontal and vertical advance values without processing - * glyph outlines, if possible. - * - * @description: - * This section contains functions to quickly extract advance values - * without handling glyph outlines, if possible. - * - * @order: - * FT_Get_Advance - * FT_Get_Advances - * - */ - - - /*************************************************************************/ - /* */ - /* <Const> */ - /* FT_ADVANCE_FLAG_FAST_ONLY */ - /* */ - /* <Description> */ - /* A bit-flag to be OR-ed with the `flags' parameter of the */ - /* @FT_Get_Advance and @FT_Get_Advances functions. */ - /* */ - /* If set, it indicates that you want these functions to fail if the */ - /* corresponding hinting mode or font driver doesn't allow for very */ - /* quick advance computation. */ - /* */ - /* Typically, glyphs that are either unscaled, unhinted, bitmapped, */ - /* or light-hinted can have their advance width computed very */ - /* quickly. */ - /* */ - /* Normal and bytecode hinted modes that require loading, scaling, */ - /* and hinting of the glyph outline, are extremely slow by */ - /* comparison. */ - /* */ -#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000L - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Advance */ - /* */ - /* <Description> */ - /* Retrieve the advance value of a given glyph outline in an */ - /* @FT_Face. */ - /* */ - /* <Input> */ - /* face :: The source @FT_Face handle. */ - /* */ - /* gindex :: The glyph index. */ - /* */ - /* load_flags :: A set of bit flags similar to those used when */ - /* calling @FT_Load_Glyph, used to determine what kind */ - /* of advances you need. */ - /* <Output> */ - /* padvance :: The advance value. If scaling is performed (based on */ - /* the value of `load_flags'), the advance value is in */ - /* 16.16 format. Otherwise, it is in font units. */ - /* */ - /* If @FT_LOAD_VERTICAL_LAYOUT is set, this is the */ - /* vertical advance corresponding to a vertical layout. */ - /* Otherwise, it is the horizontal advance in a */ - /* horizontal layout. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */ - /* if the corresponding font backend doesn't have a quick way to */ - /* retrieve the advances. */ - /* */ - /* A scaled advance is returned in 16.16 format but isn't transformed */ - /* by the affine transformation specified by @FT_Set_Transform. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Advance( FT_Face face, - FT_UInt gindex, - FT_Int32 load_flags, - FT_Fixed *padvance ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Advances */ - /* */ - /* <Description> */ - /* Retrieve the advance values of several glyph outlines in an */ - /* @FT_Face. */ - /* */ - /* <Input> */ - /* face :: The source @FT_Face handle. */ - /* */ - /* start :: The first glyph index. */ - /* */ - /* count :: The number of advance values you want to retrieve. */ - /* */ - /* load_flags :: A set of bit flags similar to those used when */ - /* calling @FT_Load_Glyph. */ - /* */ - /* <Output> */ - /* padvance :: The advance values. This array, to be provided by the */ - /* caller, must contain at least `count' elements. */ - /* */ - /* If scaling is performed (based on the value of */ - /* `load_flags'), the advance values are in 16.16 format. */ - /* Otherwise, they are in font units. */ - /* */ - /* If @FT_LOAD_VERTICAL_LAYOUT is set, these are the */ - /* vertical advances corresponding to a vertical layout. */ - /* Otherwise, they are the horizontal advances in a */ - /* horizontal layout. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */ - /* if the corresponding font backend doesn't have a quick way to */ - /* retrieve the advances. */ - /* */ - /* Scaled advances are returned in 16.16 format but aren't */ - /* transformed by the affine transformation specified by */ - /* @FT_Set_Transform. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Advances( FT_Face face, - FT_UInt start, - FT_UInt count, - FT_Int32 load_flags, - FT_Fixed *padvances ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTADVANC_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftautoh.h b/third_party/freetype/include/freetype/ftautoh.h deleted file mode 100644 index ab39c2199524d546e743faf261d60397563c2245..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftautoh.h +++ /dev/null @@ -1,450 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftautoh.h */ -/* */ -/* FreeType API for controlling the auto-hinter (specification only). */ -/* */ -/* Copyright 2012-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTAUTOH_H__ -#define __FTAUTOH_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /************************************************************************** - * - * @section: - * auto_hinter - * - * @title: - * The auto-hinter - * - * @abstract: - * Controlling the auto-hinting module. - * - * @description: - * While FreeType's auto-hinter doesn't expose API functions by itself, - * it is possible to control its behaviour with @FT_Property_Set and - * @FT_Property_Get. The following lists the available properties - * together with the necessary macros and structures. - * - * Note that the auto-hinter's module name is `autofitter' for - * historical reasons. - * - */ - - - /************************************************************************** - * - * @property: - * glyph-to-script-map - * - * @description: - * *Experimental* *only* - * - * The auto-hinter provides various script modules to hint glyphs. - * Examples of supported scripts are Latin or CJK. Before a glyph is - * auto-hinted, the Unicode character map of the font gets examined, and - * the script is then determined based on Unicode character ranges, see - * below. - * - * OpenType fonts, however, often provide much more glyphs than - * character codes (small caps, superscripts, ligatures, swashes, etc.), - * to be controlled by so-called `features'. Handling OpenType features - * can be quite complicated and thus needs a separate library on top of - * FreeType. - * - * The mapping between glyph indices and scripts (in the auto-hinter - * sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an - * array with `num_glyphs' elements, as found in the font's @FT_Face - * structure. The `glyph-to-script-map' property returns a pointer to - * this array, which can be modified as needed. Note that the - * modification should happen before the first glyph gets processed by - * the auto-hinter so that the global analysis of the font shapes - * actually uses the modified mapping. - * - * The following example code demonstrates how to access it (omitting - * the error handling). - * - * { - * FT_Library library; - * FT_Face face; - * FT_Prop_GlyphToScriptMap prop; - * - * - * FT_Init_FreeType( &library ); - * FT_New_Face( library, "foo.ttf", 0, &face ); - * - * prop.face = face; - * - * FT_Property_Get( library, "autofitter", - * "glyph-to-script-map", &prop ); - * - * // adjust `prop.map' as needed right here - * - * FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT ); - * } - * - */ - - - /************************************************************************** - * - * @enum: - * FT_AUTOHINTER_SCRIPT_XXX - * - * @description: - * *Experimental* *only* - * - * A list of constants used for the @glyph-to-script-map property to - * specify the script submodule the auto-hinter should use for hinting a - * particular glyph. - * - * @values: - * FT_AUTOHINTER_SCRIPT_NONE :: - * Don't auto-hint this glyph. - * - * FT_AUTOHINTER_SCRIPT_LATIN :: - * Apply the latin auto-hinter. For the auto-hinter, `latin' is a - * very broad term, including Cyrillic and Greek also since characters - * from those scripts share the same design constraints. - * - * By default, characters from the following Unicode ranges are - * assigned to this submodule. - * - * { - * U+0020 - U+007F // Basic Latin (no control characters) - * U+00A0 - U+00FF // Latin-1 Supplement (no control characters) - * U+0100 - U+017F // Latin Extended-A - * U+0180 - U+024F // Latin Extended-B - * U+0250 - U+02AF // IPA Extensions - * U+02B0 - U+02FF // Spacing Modifier Letters - * U+0300 - U+036F // Combining Diacritical Marks - * U+0370 - U+03FF // Greek and Coptic - * U+0400 - U+04FF // Cyrillic - * U+0500 - U+052F // Cyrillic Supplement - * U+1D00 - U+1D7F // Phonetic Extensions - * U+1D80 - U+1DBF // Phonetic Extensions Supplement - * U+1DC0 - U+1DFF // Combining Diacritical Marks Supplement - * U+1E00 - U+1EFF // Latin Extended Additional - * U+1F00 - U+1FFF // Greek Extended - * U+2000 - U+206F // General Punctuation - * U+2070 - U+209F // Superscripts and Subscripts - * U+20A0 - U+20CF // Currency Symbols - * U+2150 - U+218F // Number Forms - * U+2460 - U+24FF // Enclosed Alphanumerics - * U+2C60 - U+2C7F // Latin Extended-C - * U+2DE0 - U+2DFF // Cyrillic Extended-A - * U+2E00 - U+2E7F // Supplemental Punctuation - * U+A640 - U+A69F // Cyrillic Extended-B - * U+A720 - U+A7FF // Latin Extended-D - * U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures) - * U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols - * U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement - * } - * - * FT_AUTOHINTER_SCRIPT_CJK :: - * Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old - * Vietnamese, and some other scripts. - * - * By default, characters from the following Unicode ranges are - * assigned to this submodule. - * - * { - * U+1100 - U+11FF // Hangul Jamo - * U+2E80 - U+2EFF // CJK Radicals Supplement - * U+2F00 - U+2FDF // Kangxi Radicals - * U+2FF0 - U+2FFF // Ideographic Description Characters - * U+3000 - U+303F // CJK Symbols and Punctuation - * U+3040 - U+309F // Hiragana - * U+30A0 - U+30FF // Katakana - * U+3100 - U+312F // Bopomofo - * U+3130 - U+318F // Hangul Compatibility Jamo - * U+3190 - U+319F // Kanbun - * U+31A0 - U+31BF // Bopomofo Extended - * U+31C0 - U+31EF // CJK Strokes - * U+31F0 - U+31FF // Katakana Phonetic Extensions - * U+3200 - U+32FF // Enclosed CJK Letters and Months - * U+3300 - U+33FF // CJK Compatibility - * U+3400 - U+4DBF // CJK Unified Ideographs Extension A - * U+4DC0 - U+4DFF // Yijing Hexagram Symbols - * U+4E00 - U+9FFF // CJK Unified Ideographs - * U+A960 - U+A97F // Hangul Jamo Extended-A - * U+AC00 - U+D7AF // Hangul Syllables - * U+D7B0 - U+D7FF // Hangul Jamo Extended-B - * U+F900 - U+FAFF // CJK Compatibility Ideographs - * U+FE10 - U+FE1F // Vertical forms - * U+FE30 - U+FE4F // CJK Compatibility Forms - * U+FF00 - U+FFEF // Halfwidth and Fullwidth Forms - * U+1B000 - U+1B0FF // Kana Supplement - * U+1D300 - U+1D35F // Tai Xuan Hing Symbols - * U+1F200 - U+1F2FF // Enclosed Ideographic Supplement - * U+20000 - U+2A6DF // CJK Unified Ideographs Extension B - * U+2A700 - U+2B73F // CJK Unified Ideographs Extension C - * U+2B740 - U+2B81F // CJK Unified Ideographs Extension D - * U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement - * } - * - * FT_AUTOHINTER_SCRIPT_INDIC :: - * Apply the indic auto-hinter, covering all major scripts from the - * Indian sub-continent and some other related scripts like Thai, Lao, - * or Tibetan. - * - * By default, characters from the following Unicode ranges are - * assigned to this submodule. - * - * { - * U+0900 - U+0DFF // Indic Range - * U+0F00 - U+0FFF // Tibetan - * U+1900 - U+194F // Limbu - * U+1B80 - U+1BBF // Sundanese - * U+1C80 - U+1CDF // Meetei Mayak - * U+A800 - U+A82F // Syloti Nagri - * U+11800 - U+118DF // Sharada - * } - * - * Note that currently Indic support is rudimentary only, missing blue - * zone support. - * - */ -#define FT_AUTOHINTER_SCRIPT_NONE 0 -#define FT_AUTOHINTER_SCRIPT_LATIN 1 -#define FT_AUTOHINTER_SCRIPT_CJK 2 -#define FT_AUTOHINTER_SCRIPT_INDIC 3 - - - /************************************************************************** - * - * @struct: - * FT_Prop_GlyphToScriptMap - * - * @description: - * *Experimental* *only* - * - * The data exchange structure for the @glyph-to-script-map property. - * - */ - typedef struct FT_Prop_GlyphToScriptMap_ - { - FT_Face face; - FT_UShort* map; - - } FT_Prop_GlyphToScriptMap; - - - /************************************************************************** - * - * @property: - * fallback-script - * - * @description: - * *Experimental* *only* - * - * If no auto-hinter script module can be assigned to a glyph, a - * fallback script gets assigned to it (see also the - * @glyph-to-script-map property). By default, this is - * @FT_AUTOHINTER_SCRIPT_CJK. Using the `fallback-script' property, - * this fallback value can be changed. - * - * { - * FT_Library library; - * FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "autofitter", - * "fallback-script", &fallback_script ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - * It's important to use the right timing for changing this value: The - * creation of the glyph-to-script map that eventually uses the - * fallback script value gets triggered either by setting or reading a - * face-specific property like @glyph-to-script-map, or by auto-hinting - * any glyph from that face. In particular, if you have already created - * an @FT_Face structure but not loaded any glyph (using the - * auto-hinter), a change of the fallback script will affect this face. - * - */ - - - /************************************************************************** - * - * @property: - * default-script - * - * @description: - * *Experimental* *only* - * - * If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make - * the HarfBuzz library access OpenType features for getting better - * glyph coverages, this property sets the (auto-fitter) script to be - * used for the default (OpenType) script data of a font's GSUB table. - * Features for the default script are intended for all scripts not - * explicitly handled in GSUB; an example is a `dlig' feature, - * containing the combination of the characters `T', `E', and `L' to - * form a `TEL' ligature. - * - * By default, this is @FT_AUTOHINTER_SCRIPT_LATIN. Using the - * `default-script' property, this default value can be changed. - * - * { - * FT_Library library; - * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "autofitter", - * "default-script", &default_script ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - * It's important to use the right timing for changing this value: The - * creation of the glyph-to-script map that eventually uses the - * default script value gets triggered either by setting or reading a - * face-specific property like @glyph-to-script-map, or by auto-hinting - * any glyph from that face. In particular, if you have already created - * an @FT_Face structure but not loaded any glyph (using the - * auto-hinter), a change of the default script will affect this face. - * - */ - - - /************************************************************************** - * - * @property: - * increase-x-height - * - * @description: - * For ppem values in the range 6~<= ppem <= `increase-x-height', round - * up the font's x~height much more often than normally. If the value - * is set to~0, which is the default, this feature is switched off. Use - * this property to improve the legibility of small font sizes if - * necessary. - * - * { - * FT_Library library; - * FT_Face face; - * FT_Prop_IncreaseXHeight prop; - * - * - * FT_Init_FreeType( &library ); - * FT_New_Face( library, "foo.ttf", 0, &face ); - * FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 ); - * - * prop.face = face; - * prop.limit = 14; - * - * FT_Property_Set( library, "autofitter", - * "increase-x-height", &prop ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - * Set this value right after calling @FT_Set_Char_Size, but before - * loading any glyph (using the auto-hinter). - * - */ - - - /************************************************************************** - * - * @struct: - * FT_Prop_IncreaseXHeight - * - * @description: - * The data exchange structure for the @increase-x-height property. - * - */ - typedef struct FT_Prop_IncreaseXHeight_ - { - FT_Face face; - FT_UInt limit; - - } FT_Prop_IncreaseXHeight; - - - /************************************************************************** - * - * @property: - * warping - * - * @description: - * *Experimental* *only* - * - * If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to - * activate the warp hinting code in the auto-hinter, this property - * switches warping on and off. - * - * Warping only works in `light' auto-hinting mode. The idea of the - * code is to slightly scale and shift a glyph along the non-hinted - * dimension (which is usually the horizontal axis) so that as much of - * its segments are aligned (more or less) to the grid. To find out a - * glyph's optimal scaling and shifting value, various parameter - * combinations are tried and scored. - * - * By default, warping is off. The example below shows how to switch on - * warping (omitting the error handling). - * - * { - * FT_Library library; - * FT_Bool warping = 1; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "autofitter", - * "warping", &warping ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - * The warping code can also change advance widths. Have a look at the - * `lsb_delta' and `rsb_delta' fields in the @FT_GlyphSlotRec structure - * for details on improving inter-glyph distances while rendering. - * - * Since warping is a global property of the auto-hinter it is best to - * change its value before rendering any face. Otherwise, you should - * reload all faces that get auto-hinted in `light' hinting mode. - * - */ - - - /* */ - - -FT_END_HEADER - -#endif /* __FTAUTOH_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftbbox.h b/third_party/freetype/include/freetype/ftbbox.h deleted file mode 100644 index 9d9d04076764970bd818e265820a8fd9376a4431..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftbbox.h +++ /dev/null @@ -1,101 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbbox.h */ -/* */ -/* FreeType exact bbox computation (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This component has a _single_ role: to compute exact outline bounding */ - /* boxes. */ - /* */ - /* It is separated from the rest of the engine for various technical */ - /* reasons. It may well be integrated in `ftoutln' later. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTBBOX_H__ -#define __FTBBOX_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* outline_processing */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Get_BBox */ - /* */ - /* <Description> */ - /* Compute the exact bounding box of an outline. This is slower */ - /* than computing the control box. However, it uses an advanced */ - /* algorithm that returns _very_ quickly when the two boxes */ - /* coincide. Otherwise, the outline Bézier arcs are traversed to */ - /* extract their extrema. */ - /* */ - /* <Input> */ - /* outline :: A pointer to the source outline. */ - /* */ - /* <Output> */ - /* abbox :: The outline's exact bounding box. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* If the font is tricky and the glyph has been loaded with */ - /* @FT_LOAD_NO_SCALE, the resulting BBox is meaningless. To get */ - /* reasonable values for the BBox it is necessary to load the glyph */ - /* at a large ppem value (so that the hinting instructions can */ - /* properly shift and scale the subglyphs), then extracting the BBox, */ - /* which can be eventually converted back to font units. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Get_BBox( FT_Outline* outline, - FT_BBox *abbox ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTBBOX_H__ */ - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/include/freetype/ftbdf.h b/third_party/freetype/include/freetype/ftbdf.h deleted file mode 100644 index 0bdabf481cb3252cd289c72a8aab66435d231378..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftbdf.h +++ /dev/null @@ -1,210 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbdf.h */ -/* */ -/* FreeType API for accessing BDF-specific strings (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTBDF_H__ -#define __FTBDF_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* bdf_fonts */ - /* */ - /* <Title> */ - /* BDF and PCF Files */ - /* */ - /* <Abstract> */ - /* BDF and PCF specific API. */ - /* */ - /* <Description> */ - /* This section contains the declaration of functions specific to BDF */ - /* and PCF fonts. */ - /* */ - /*************************************************************************/ - - - /********************************************************************** - * - * @enum: - * BDF_PropertyType - * - * @description: - * A list of BDF property types. - * - * @values: - * BDF_PROPERTY_TYPE_NONE :: - * Value~0 is used to indicate a missing property. - * - * BDF_PROPERTY_TYPE_ATOM :: - * Property is a string atom. - * - * BDF_PROPERTY_TYPE_INTEGER :: - * Property is a 32-bit signed integer. - * - * BDF_PROPERTY_TYPE_CARDINAL :: - * Property is a 32-bit unsigned integer. - */ - typedef enum BDF_PropertyType_ - { - BDF_PROPERTY_TYPE_NONE = 0, - BDF_PROPERTY_TYPE_ATOM = 1, - BDF_PROPERTY_TYPE_INTEGER = 2, - BDF_PROPERTY_TYPE_CARDINAL = 3 - - } BDF_PropertyType; - - - /********************************************************************** - * - * @type: - * BDF_Property - * - * @description: - * A handle to a @BDF_PropertyRec structure to model a given - * BDF/PCF property. - */ - typedef struct BDF_PropertyRec_* BDF_Property; - - - /********************************************************************** - * - * @struct: - * BDF_PropertyRec - * - * @description: - * This structure models a given BDF/PCF property. - * - * @fields: - * type :: - * The property type. - * - * u.atom :: - * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. May be - * NULL, indicating an empty string. - * - * u.integer :: - * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER. - * - * u.cardinal :: - * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL. - */ - typedef struct BDF_PropertyRec_ - { - BDF_PropertyType type; - union { - const char* atom; - FT_Int32 integer; - FT_UInt32 cardinal; - - } u; - - } BDF_PropertyRec; - - - /********************************************************************** - * - * @function: - * FT_Get_BDF_Charset_ID - * - * @description: - * Retrieve a BDF font character set identity, according to - * the BDF specification. - * - * @input: - * face :: - * A handle to the input face. - * - * @output: - * acharset_encoding :: - * Charset encoding, as a C~string, owned by the face. - * - * acharset_registry :: - * Charset registry, as a C~string, owned by the face. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with BDF faces, returning an error otherwise. - */ - FT_EXPORT( FT_Error ) - FT_Get_BDF_Charset_ID( FT_Face face, - const char* *acharset_encoding, - const char* *acharset_registry ); - - - /********************************************************************** - * - * @function: - * FT_Get_BDF_Property - * - * @description: - * Retrieve a BDF property from a BDF or PCF font file. - * - * @input: - * face :: A handle to the input face. - * - * name :: The property name. - * - * @output: - * aproperty :: The property. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function works with BDF _and_ PCF fonts. It returns an error - * otherwise. It also returns an error if the property is not in the - * font. - * - * A `property' is a either key-value pair within the STARTPROPERTIES - * ... ENDPROPERTIES block of a BDF font or a key-value pair from the - * `info->props' array within a `FontRec' structure of a PCF font. - * - * Integer properties are always stored as `signed' within PCF fonts; - * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value - * for BDF fonts only. - * - * In case of error, `aproperty->type' is always set to - * @BDF_PROPERTY_TYPE_NONE. - */ - FT_EXPORT( FT_Error ) - FT_Get_BDF_Property( FT_Face face, - const char* prop_name, - BDF_PropertyRec *aproperty ); - - /* */ - -FT_END_HEADER - -#endif /* __FTBDF_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftbitmap.h b/third_party/freetype/include/freetype/ftbitmap.h deleted file mode 100644 index 46cc47b7d1ed9f9ea6522def7fa2bae81a66db30..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftbitmap.h +++ /dev/null @@ -1,240 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbitmap.h */ -/* */ -/* FreeType utility functions for bitmaps (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTBITMAP_H__ -#define __FTBITMAP_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* bitmap_handling */ - /* */ - /* <Title> */ - /* Bitmap Handling */ - /* */ - /* <Abstract> */ - /* Handling FT_Bitmap objects. */ - /* */ - /* <Description> */ - /* This section contains functions for handling @FT_Bitmap objects. */ - /* Note that none of the functions changes the bitmap's `flow' (as */ - /* indicated by the sign of the `pitch' field in `FT_Bitmap'). */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Bitmap_Init */ - /* */ - /* <Description> */ - /* Initialize a pointer to an @FT_Bitmap structure. */ - /* */ - /* <InOut> */ - /* abitmap :: A pointer to the bitmap structure. */ - /* */ - /* <Note> */ - /* A deprecated name for the same function is `FT_Bitmap_New'. */ - /* */ - FT_EXPORT( void ) - FT_Bitmap_Init( FT_Bitmap *abitmap ); - - - /* deprecated */ - FT_EXPORT( void ) - FT_Bitmap_New( FT_Bitmap *abitmap ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Bitmap_Copy */ - /* */ - /* <Description> */ - /* Copy a bitmap into another one. */ - /* */ - /* <Input> */ - /* library :: A handle to a library object. */ - /* */ - /* source :: A handle to the source bitmap. */ - /* */ - /* <Output> */ - /* target :: A handle to the target bitmap. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Bitmap_Copy( FT_Library library, - const FT_Bitmap *source, - FT_Bitmap *target); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Bitmap_Embolden */ - /* */ - /* <Description> */ - /* Embolden a bitmap. The new bitmap will be about `xStrength' */ - /* pixels wider and `yStrength' pixels higher. The left and bottom */ - /* borders are kept unchanged. */ - /* */ - /* <Input> */ - /* library :: A handle to a library object. */ - /* */ - /* xStrength :: How strong the glyph is emboldened horizontally. */ - /* Expressed in 26.6 pixel format. */ - /* */ - /* yStrength :: How strong the glyph is emboldened vertically. */ - /* Expressed in 26.6 pixel format. */ - /* */ - /* <InOut> */ - /* bitmap :: A handle to the target bitmap. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The current implementation restricts `xStrength' to be less than */ - /* or equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO. */ - /* */ - /* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */ - /* you should call @FT_GlyphSlot_Own_Bitmap on the slot first. */ - /* */ - /* Bitmaps in @FT_PIXEL_MODE_GRAY2 and @FT_PIXEL_MODE_GRAY@ format */ - /* are converted to @FT_PIXEL_MODE_GRAY format (i.e., 8bpp). */ - /* */ - FT_EXPORT( FT_Error ) - FT_Bitmap_Embolden( FT_Library library, - FT_Bitmap* bitmap, - FT_Pos xStrength, - FT_Pos yStrength ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Bitmap_Convert */ - /* */ - /* <Description> */ - /* Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp */ - /* to a bitmap object with depth 8bpp, making the number of used */ - /* bytes line (a.k.a. the `pitch') a multiple of `alignment'. */ - /* */ - /* <Input> */ - /* library :: A handle to a library object. */ - /* */ - /* source :: The source bitmap. */ - /* */ - /* alignment :: The pitch of the bitmap is a multiple of this */ - /* parameter. Common values are 1, 2, or 4. */ - /* */ - /* <Output> */ - /* target :: The target bitmap. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* It is possible to call @FT_Bitmap_Convert multiple times without */ - /* calling @FT_Bitmap_Done (the memory is simply reallocated). */ - /* */ - /* Use @FT_Bitmap_Done to finally remove the bitmap object. */ - /* */ - /* The `library' argument is taken to have access to FreeType's */ - /* memory handling functions. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Bitmap_Convert( FT_Library library, - const FT_Bitmap *source, - FT_Bitmap *target, - FT_Int alignment ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_GlyphSlot_Own_Bitmap */ - /* */ - /* <Description> */ - /* Make sure that a glyph slot owns `slot->bitmap'. */ - /* */ - /* <Input> */ - /* slot :: The glyph slot. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* This function is to be used in combination with */ - /* @FT_Bitmap_Embolden. */ - /* */ - FT_EXPORT( FT_Error ) - FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Bitmap_Done */ - /* */ - /* <Description> */ - /* Destroy a bitmap object initialized with @FT_Bitmap_Init. */ - /* */ - /* <Input> */ - /* library :: A handle to a library object. */ - /* */ - /* bitmap :: The bitmap object to be freed. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The `library' argument is taken to have access to FreeType's */ - /* memory handling functions. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Bitmap_Done( FT_Library library, - FT_Bitmap *bitmap ); - - - /* */ - - -FT_END_HEADER - -#endif /* __FTBITMAP_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftbzip2.h b/third_party/freetype/include/freetype/ftbzip2.h deleted file mode 100644 index c25f9469dff3c78a23e18862d295d55555cd9aa6..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftbzip2.h +++ /dev/null @@ -1,102 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbzip2.h */ -/* */ -/* Bzip2-compressed stream support. */ -/* */ -/* Copyright 2010-2015 by */ -/* Joel Klinghed. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTBZIP2_H__ -#define __FTBZIP2_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /*************************************************************************/ - /* */ - /* <Section> */ - /* bzip2 */ - /* */ - /* <Title> */ - /* BZIP2 Streams */ - /* */ - /* <Abstract> */ - /* Using bzip2-compressed font files. */ - /* */ - /* <Description> */ - /* This section contains the declaration of Bzip2-specific functions. */ - /* */ - /*************************************************************************/ - - - /************************************************************************ - * - * @function: - * FT_Stream_OpenBzip2 - * - * @description: - * Open a new stream to parse bzip2-compressed font files. This is - * mainly used to support the compressed `*.pcf.bz2' fonts that come - * with XFree86. - * - * @input: - * stream :: - * The target embedding stream. - * - * source :: - * The source stream. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The source stream must be opened _before_ calling this function. - * - * Calling the internal function `FT_Stream_Close' on the new stream will - * *not* call `FT_Stream_Close' on the source stream. None of the stream - * objects will be released to the heap. - * - * The stream implementation is very basic and resets the decompression - * process each time seeking backwards is needed within the stream. - * - * In certain builds of the library, bzip2 compression recognition is - * automatically handled when calling @FT_New_Face or @FT_Open_Face. - * This means that if no font driver is capable of handling the raw - * compressed file, the library will try to open a bzip2 compressed stream - * from it and re-open the face with it. - * - * This function may return `FT_Err_Unimplemented_Feature' if your build - * of FreeType was not compiled with bzip2 support. - */ - FT_EXPORT( FT_Error ) - FT_Stream_OpenBzip2( FT_Stream stream, - FT_Stream source ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTBZIP2_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftcache.h b/third_party/freetype/include/freetype/ftcache.h deleted file mode 100644 index 68525bb8294baf1f4ebd55ec6067fb19c4530622..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftcache.h +++ /dev/null @@ -1,1057 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftcache.h */ -/* */ -/* FreeType Cache subsystem (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTCACHE_H__ -#define __FTCACHE_H__ - - -#include <ft2build.h> -#include FT_GLYPH_H - - -FT_BEGIN_HEADER - - - /************************************************************************* - * - * <Section> - * cache_subsystem - * - * <Title> - * Cache Sub-System - * - * <Abstract> - * How to cache face, size, and glyph data with FreeType~2. - * - * <Description> - * This section describes the FreeType~2 cache sub-system, which is used - * to limit the number of concurrently opened @FT_Face and @FT_Size - * objects, as well as caching information like character maps and glyph - * images while limiting their maximum memory usage. - * - * Note that all types and functions begin with the `FTC_' prefix. - * - * The cache is highly portable and thus doesn't know anything about the - * fonts installed on your system, or how to access them. This implies - * the following scheme: - * - * First, available or installed font faces are uniquely identified by - * @FTC_FaceID values, provided to the cache by the client. Note that - * the cache only stores and compares these values, and doesn't try to - * interpret them in any way. - * - * Second, the cache calls, only when needed, a client-provided function - * to convert an @FTC_FaceID into a new @FT_Face object. The latter is - * then completely managed by the cache, including its termination - * through @FT_Done_Face. To monitor termination of face objects, the - * finalizer callback in the `generic' field of the @FT_Face object can - * be used, which might also be used to store the @FTC_FaceID of the - * face. - * - * Clients are free to map face IDs to anything else. The most simple - * usage is to associate them to a (pathname,face_index) pair that is - * used to call @FT_New_Face. However, more complex schemes are also - * possible. - * - * Note that for the cache to work correctly, the face ID values must be - * *persistent*, which means that the contents they point to should not - * change at runtime, or that their value should not become invalid. - * - * If this is unavoidable (e.g., when a font is uninstalled at runtime), - * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let - * the cache get rid of any references to the old @FTC_FaceID it may - * keep internally. Failure to do so will lead to incorrect behaviour - * or even crashes. - * - * To use the cache, start with calling @FTC_Manager_New to create a new - * @FTC_Manager object, which models a single cache instance. You can - * then look up @FT_Face and @FT_Size objects with - * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. - * - * If you want to use the charmap caching, call @FTC_CMapCache_New, then - * later use @FTC_CMapCache_Lookup to perform the equivalent of - * @FT_Get_Char_Index, only much faster. - * - * If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then - * later use @FTC_ImageCache_Lookup to retrieve the corresponding - * @FT_Glyph objects from the cache. - * - * If you need lots of small bitmaps, it is much more memory efficient - * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This - * returns @FTC_SBitRec structures, which are used to store small - * bitmaps directly. (A small bitmap is one whose metrics and - * dimensions all fit into 8-bit integers). - * - * We hope to also provide a kerning cache in the near future. - * - * - * <Order> - * FTC_Manager - * FTC_FaceID - * FTC_Face_Requester - * - * FTC_Manager_New - * FTC_Manager_Reset - * FTC_Manager_Done - * FTC_Manager_LookupFace - * FTC_Manager_LookupSize - * FTC_Manager_RemoveFaceID - * - * FTC_Node - * FTC_Node_Unref - * - * FTC_ImageCache - * FTC_ImageCache_New - * FTC_ImageCache_Lookup - * - * FTC_SBit - * FTC_SBitCache - * FTC_SBitCache_New - * FTC_SBitCache_Lookup - * - * FTC_CMapCache - * FTC_CMapCache_New - * FTC_CMapCache_Lookup - * - *************************************************************************/ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** BASIC TYPE DEFINITIONS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /************************************************************************* - * - * @type: FTC_FaceID - * - * @description: - * An opaque pointer type that is used to identity face objects. The - * contents of such objects is application-dependent. - * - * These pointers are typically used to point to a user-defined - * structure containing a font file path, and face index. - * - * @note: - * Never use NULL as a valid @FTC_FaceID. - * - * Face IDs are passed by the client to the cache manager that calls, - * when needed, the @FTC_Face_Requester to translate them into new - * @FT_Face objects. - * - * If the content of a given face ID changes at runtime, or if the value - * becomes invalid (e.g., when uninstalling a font), you should - * immediately call @FTC_Manager_RemoveFaceID before any other cache - * function. - * - * Failure to do so will result in incorrect behaviour or even - * memory leaks and crashes. - */ - typedef FT_Pointer FTC_FaceID; - - - /************************************************************************ - * - * @functype: - * FTC_Face_Requester - * - * @description: - * A callback function provided by client applications. It is used by - * the cache manager to translate a given @FTC_FaceID into a new valid - * @FT_Face object, on demand. - * - * <Input> - * face_id :: - * The face ID to resolve. - * - * library :: - * A handle to a FreeType library object. - * - * req_data :: - * Application-provided request data (see note below). - * - * <Output> - * aface :: - * A new @FT_Face handle. - * - * <Return> - * FreeType error code. 0~means success. - * - * <Note> - * The third parameter `req_data' is the same as the one passed by the - * client when @FTC_Manager_New is called. - * - * The face requester should not perform funny things on the returned - * face object, like creating a new @FT_Size for it, or setting a - * transformation through @FT_Set_Transform! - */ - typedef FT_Error - (*FTC_Face_Requester)( FTC_FaceID face_id, - FT_Library library, - FT_Pointer req_data, - FT_Face* aface ); - - /* */ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** CACHE MANAGER OBJECT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FTC_Manager */ - /* */ - /* <Description> */ - /* This object corresponds to one instance of the cache-subsystem. */ - /* It is used to cache one or more @FT_Face objects, along with */ - /* corresponding @FT_Size objects. */ - /* */ - /* The manager intentionally limits the total number of opened */ - /* @FT_Face and @FT_Size objects to control memory usage. See the */ - /* `max_faces' and `max_sizes' parameters of @FTC_Manager_New. */ - /* */ - /* The manager is also used to cache `nodes' of various types while */ - /* limiting their total memory usage. */ - /* */ - /* All limitations are enforced by keeping lists of managed objects */ - /* in most-recently-used order, and flushing old nodes to make room */ - /* for new ones. */ - /* */ - typedef struct FTC_ManagerRec_* FTC_Manager; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FTC_Node */ - /* */ - /* <Description> */ - /* An opaque handle to a cache node object. Each cache node is */ - /* reference-counted. A node with a count of~0 might be flushed */ - /* out of a full cache whenever a lookup request is performed. */ - /* */ - /* If you look up nodes, you have the ability to `acquire' them, */ - /* i.e., to increment their reference count. This will prevent the */ - /* node from being flushed out of the cache until you explicitly */ - /* `release' it (see @FTC_Node_Unref). */ - /* */ - /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */ - /* */ - typedef struct FTC_NodeRec_* FTC_Node; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_Manager_New */ - /* */ - /* <Description> */ - /* Create a new cache manager. */ - /* */ - /* <Input> */ - /* library :: The parent FreeType library handle to use. */ - /* */ - /* max_faces :: Maximum number of opened @FT_Face objects managed by */ - /* this cache instance. Use~0 for defaults. */ - /* */ - /* max_sizes :: Maximum number of opened @FT_Size objects managed by */ - /* this cache instance. Use~0 for defaults. */ - /* */ - /* max_bytes :: Maximum number of bytes to use for cached data nodes. */ - /* Use~0 for defaults. Note that this value does not */ - /* account for managed @FT_Face and @FT_Size objects. */ - /* */ - /* requester :: An application-provided callback used to translate */ - /* face IDs into real @FT_Face objects. */ - /* */ - /* req_data :: A generic pointer that is passed to the requester */ - /* each time it is called (see @FTC_Face_Requester). */ - /* */ - /* <Output> */ - /* amanager :: A handle to a new manager object. 0~in case of */ - /* failure. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FTC_Manager_New( FT_Library library, - FT_UInt max_faces, - FT_UInt max_sizes, - FT_ULong max_bytes, - FTC_Face_Requester requester, - FT_Pointer req_data, - FTC_Manager *amanager ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_Manager_Reset */ - /* */ - /* <Description> */ - /* Empty a given cache manager. This simply gets rid of all the */ - /* currently cached @FT_Face and @FT_Size objects within the manager. */ - /* */ - /* <InOut> */ - /* manager :: A handle to the manager. */ - /* */ - FT_EXPORT( void ) - FTC_Manager_Reset( FTC_Manager manager ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_Manager_Done */ - /* */ - /* <Description> */ - /* Destroy a given manager after emptying it. */ - /* */ - /* <Input> */ - /* manager :: A handle to the target cache manager object. */ - /* */ - FT_EXPORT( void ) - FTC_Manager_Done( FTC_Manager manager ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_Manager_LookupFace */ - /* */ - /* <Description> */ - /* Retrieve the @FT_Face object that corresponds to a given face ID */ - /* through a cache manager. */ - /* */ - /* <Input> */ - /* manager :: A handle to the cache manager. */ - /* */ - /* face_id :: The ID of the face object. */ - /* */ - /* <Output> */ - /* aface :: A handle to the face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The returned @FT_Face object is always owned by the manager. You */ - /* should never try to discard it yourself. */ - /* */ - /* The @FT_Face object doesn't necessarily have a current size object */ - /* (i.e., face->size can be~0). If you need a specific `font size', */ - /* use @FTC_Manager_LookupSize instead. */ - /* */ - /* Never change the face's transformation matrix (i.e., never call */ - /* the @FT_Set_Transform function) on a returned face! If you need */ - /* to transform glyphs, do it yourself after glyph loading. */ - /* */ - /* When you perform a lookup, out-of-memory errors are detected */ - /* _within_ the lookup and force incremental flushes of the cache */ - /* until enough memory is released for the lookup to succeed. */ - /* */ - /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */ - /* already been completely flushed, and still no memory was available */ - /* for the operation. */ - /* */ - FT_EXPORT( FT_Error ) - FTC_Manager_LookupFace( FTC_Manager manager, - FTC_FaceID face_id, - FT_Face *aface ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FTC_ScalerRec */ - /* */ - /* <Description> */ - /* A structure used to describe a given character size in either */ - /* pixels or points to the cache manager. See */ - /* @FTC_Manager_LookupSize. */ - /* */ - /* <Fields> */ - /* face_id :: The source face ID. */ - /* */ - /* width :: The character width. */ - /* */ - /* height :: The character height. */ - /* */ - /* pixel :: A Boolean. If 1, the `width' and `height' fields are */ - /* interpreted as integer pixel character sizes. */ - /* Otherwise, they are expressed as 1/64th of points. */ - /* */ - /* x_res :: Only used when `pixel' is value~0 to indicate the */ - /* horizontal resolution in dpi. */ - /* */ - /* y_res :: Only used when `pixel' is value~0 to indicate the */ - /* vertical resolution in dpi. */ - /* */ - /* <Note> */ - /* This type is mainly used to retrieve @FT_Size objects through the */ - /* cache manager. */ - /* */ - typedef struct FTC_ScalerRec_ - { - FTC_FaceID face_id; - FT_UInt width; - FT_UInt height; - FT_Int pixel; - FT_UInt x_res; - FT_UInt y_res; - - } FTC_ScalerRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FTC_Scaler */ - /* */ - /* <Description> */ - /* A handle to an @FTC_ScalerRec structure. */ - /* */ - typedef struct FTC_ScalerRec_* FTC_Scaler; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_Manager_LookupSize */ - /* */ - /* <Description> */ - /* Retrieve the @FT_Size object that corresponds to a given */ - /* @FTC_ScalerRec pointer through a cache manager. */ - /* */ - /* <Input> */ - /* manager :: A handle to the cache manager. */ - /* */ - /* scaler :: A scaler handle. */ - /* */ - /* <Output> */ - /* asize :: A handle to the size object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The returned @FT_Size object is always owned by the manager. You */ - /* should never try to discard it by yourself. */ - /* */ - /* You can access the parent @FT_Face object simply as `size->face' */ - /* if you need it. Note that this object is also owned by the */ - /* manager. */ - /* */ - /* <Note> */ - /* When you perform a lookup, out-of-memory errors are detected */ - /* _within_ the lookup and force incremental flushes of the cache */ - /* until enough memory is released for the lookup to succeed. */ - /* */ - /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */ - /* already been completely flushed, and still no memory is available */ - /* for the operation. */ - /* */ - FT_EXPORT( FT_Error ) - FTC_Manager_LookupSize( FTC_Manager manager, - FTC_Scaler scaler, - FT_Size *asize ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_Node_Unref */ - /* */ - /* <Description> */ - /* Decrement a cache node's internal reference count. When the count */ - /* reaches 0, it is not destroyed but becomes eligible for subsequent */ - /* cache flushes. */ - /* */ - /* <Input> */ - /* node :: The cache node handle. */ - /* */ - /* manager :: The cache manager handle. */ - /* */ - FT_EXPORT( void ) - FTC_Node_Unref( FTC_Node node, - FTC_Manager manager ); - - - /************************************************************************* - * - * @function: - * FTC_Manager_RemoveFaceID - * - * @description: - * A special function used to indicate to the cache manager that - * a given @FTC_FaceID is no longer valid, either because its - * content changed, or because it was deallocated or uninstalled. - * - * @input: - * manager :: - * The cache manager handle. - * - * face_id :: - * The @FTC_FaceID to be removed. - * - * @note: - * This function flushes all nodes from the cache corresponding to this - * `face_id', with the exception of nodes with a non-null reference - * count. - * - * Such nodes are however modified internally so as to never appear - * in later lookups with the same `face_id' value, and to be immediately - * destroyed when released by all their users. - * - */ - FT_EXPORT( void ) - FTC_Manager_RemoveFaceID( FTC_Manager manager, - FTC_FaceID face_id ); - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* cache_subsystem */ - /* */ - /*************************************************************************/ - - /************************************************************************* - * - * @type: - * FTC_CMapCache - * - * @description: - * An opaque handle used to model a charmap cache. This cache is to - * hold character codes -> glyph indices mappings. - * - */ - typedef struct FTC_CMapCacheRec_* FTC_CMapCache; - - - /************************************************************************* - * - * @function: - * FTC_CMapCache_New - * - * @description: - * Create a new charmap cache. - * - * @input: - * manager :: - * A handle to the cache manager. - * - * @output: - * acache :: - * A new cache handle. NULL in case of error. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * Like all other caches, this one will be destroyed with the cache - * manager. - * - */ - FT_EXPORT( FT_Error ) - FTC_CMapCache_New( FTC_Manager manager, - FTC_CMapCache *acache ); - - - /************************************************************************ - * - * @function: - * FTC_CMapCache_Lookup - * - * @description: - * Translate a character code into a glyph index, using the charmap - * cache. - * - * @input: - * cache :: - * A charmap cache handle. - * - * face_id :: - * The source face ID. - * - * cmap_index :: - * The index of the charmap in the source face. Any negative value - * means to use the cache @FT_Face's default charmap. - * - * char_code :: - * The character code (in the corresponding charmap). - * - * @return: - * Glyph index. 0~means `no glyph'. - * - */ - FT_EXPORT( FT_UInt ) - FTC_CMapCache_Lookup( FTC_CMapCache cache, - FTC_FaceID face_id, - FT_Int cmap_index, - FT_UInt32 char_code ); - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* cache_subsystem */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** IMAGE CACHE OBJECT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /************************************************************************* - * - * @struct: - * FTC_ImageTypeRec - * - * @description: - * A structure used to model the type of images in a glyph cache. - * - * @fields: - * face_id :: - * The face ID. - * - * width :: - * The width in pixels. - * - * height :: - * The height in pixels. - * - * flags :: - * The load flags, as in @FT_Load_Glyph. - * - */ - typedef struct FTC_ImageTypeRec_ - { - FTC_FaceID face_id; - FT_UInt width; - FT_UInt height; - FT_Int32 flags; - - } FTC_ImageTypeRec; - - - /************************************************************************* - * - * @type: - * FTC_ImageType - * - * @description: - * A handle to an @FTC_ImageTypeRec structure. - * - */ - typedef struct FTC_ImageTypeRec_* FTC_ImageType; - - - /* */ - - -#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \ - ( (d1)->face_id == (d2)->face_id && \ - (d1)->width == (d2)->width && \ - (d1)->flags == (d2)->flags ) - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FTC_ImageCache */ - /* */ - /* <Description> */ - /* A handle to a glyph image cache object. They are designed to */ - /* hold many distinct glyph images while not exceeding a certain */ - /* memory threshold. */ - /* */ - typedef struct FTC_ImageCacheRec_* FTC_ImageCache; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_ImageCache_New */ - /* */ - /* <Description> */ - /* Create a new glyph image cache. */ - /* */ - /* <Input> */ - /* manager :: The parent manager for the image cache. */ - /* */ - /* <Output> */ - /* acache :: A handle to the new glyph image cache object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FTC_ImageCache_New( FTC_Manager manager, - FTC_ImageCache *acache ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_ImageCache_Lookup */ - /* */ - /* <Description> */ - /* Retrieve a given glyph image from a glyph image cache. */ - /* */ - /* <Input> */ - /* cache :: A handle to the source glyph image cache. */ - /* */ - /* type :: A pointer to a glyph image type descriptor. */ - /* */ - /* gindex :: The glyph index to retrieve. */ - /* */ - /* <Output> */ - /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */ - /* failure. */ - /* */ - /* anode :: Used to return the address of of the corresponding cache */ - /* node after incrementing its reference count (see note */ - /* below). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The returned glyph is owned and managed by the glyph image cache. */ - /* Never try to transform or discard it manually! You can however */ - /* create a copy with @FT_Glyph_Copy and modify the new one. */ - /* */ - /* If `anode' is _not_ NULL, it receives the address of the cache */ - /* node containing the glyph image, after increasing its reference */ - /* count. This ensures that the node (as well as the @FT_Glyph) will */ - /* always be kept in the cache until you call @FTC_Node_Unref to */ - /* `release' it. */ - /* */ - /* If `anode' is NULL, the cache node is left unchanged, which means */ - /* that the @FT_Glyph could be flushed out of the cache on the next */ - /* call to one of the caching sub-system APIs. Don't assume that it */ - /* is persistent! */ - /* */ - FT_EXPORT( FT_Error ) - FTC_ImageCache_Lookup( FTC_ImageCache cache, - FTC_ImageType type, - FT_UInt gindex, - FT_Glyph *aglyph, - FTC_Node *anode ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_ImageCache_LookupScaler */ - /* */ - /* <Description> */ - /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */ - /* to specify the face ID and its size. */ - /* */ - /* <Input> */ - /* cache :: A handle to the source glyph image cache. */ - /* */ - /* scaler :: A pointer to a scaler descriptor. */ - /* */ - /* load_flags :: The corresponding load flags. */ - /* */ - /* gindex :: The glyph index to retrieve. */ - /* */ - /* <Output> */ - /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */ - /* failure. */ - /* */ - /* anode :: Used to return the address of of the corresponding */ - /* cache node after incrementing its reference count */ - /* (see note below). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The returned glyph is owned and managed by the glyph image cache. */ - /* Never try to transform or discard it manually! You can however */ - /* create a copy with @FT_Glyph_Copy and modify the new one. */ - /* */ - /* If `anode' is _not_ NULL, it receives the address of the cache */ - /* node containing the glyph image, after increasing its reference */ - /* count. This ensures that the node (as well as the @FT_Glyph) will */ - /* always be kept in the cache until you call @FTC_Node_Unref to */ - /* `release' it. */ - /* */ - /* If `anode' is NULL, the cache node is left unchanged, which means */ - /* that the @FT_Glyph could be flushed out of the cache on the next */ - /* call to one of the caching sub-system APIs. Don't assume that it */ - /* is persistent! */ - /* */ - /* Calls to @FT_Set_Char_Size and friends have no effect on cached */ - /* glyphs; you should always use the FreeType cache API instead. */ - /* */ - FT_EXPORT( FT_Error ) - FTC_ImageCache_LookupScaler( FTC_ImageCache cache, - FTC_Scaler scaler, - FT_ULong load_flags, - FT_UInt gindex, - FT_Glyph *aglyph, - FTC_Node *anode ); - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FTC_SBit */ - /* */ - /* <Description> */ - /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */ - /* structure for details. */ - /* */ - typedef struct FTC_SBitRec_* FTC_SBit; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FTC_SBitRec */ - /* */ - /* <Description> */ - /* A very compact structure used to describe a small glyph bitmap. */ - /* */ - /* <Fields> */ - /* width :: The bitmap width in pixels. */ - /* */ - /* height :: The bitmap height in pixels. */ - /* */ - /* left :: The horizontal distance from the pen position to the */ - /* left bitmap border (a.k.a. `left side bearing', or */ - /* `lsb'). */ - /* */ - /* top :: The vertical distance from the pen position (on the */ - /* baseline) to the upper bitmap border (a.k.a. `top */ - /* side bearing'). The distance is positive for upwards */ - /* y~coordinates. */ - /* */ - /* format :: The format of the glyph bitmap (monochrome or gray). */ - /* */ - /* max_grays :: Maximum gray level value (in the range 1 to~255). */ - /* */ - /* pitch :: The number of bytes per bitmap line. May be positive */ - /* or negative. */ - /* */ - /* xadvance :: The horizontal advance width in pixels. */ - /* */ - /* yadvance :: The vertical advance height in pixels. */ - /* */ - /* buffer :: A pointer to the bitmap pixels. */ - /* */ - typedef struct FTC_SBitRec_ - { - FT_Byte width; - FT_Byte height; - FT_Char left; - FT_Char top; - - FT_Byte format; - FT_Byte max_grays; - FT_Short pitch; - FT_Char xadvance; - FT_Char yadvance; - - FT_Byte* buffer; - - } FTC_SBitRec; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FTC_SBitCache */ - /* */ - /* <Description> */ - /* A handle to a small bitmap cache. These are special cache objects */ - /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */ - /* much more efficient way than the traditional glyph image cache */ - /* implemented by @FTC_ImageCache. */ - /* */ - typedef struct FTC_SBitCacheRec_* FTC_SBitCache; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_SBitCache_New */ - /* */ - /* <Description> */ - /* Create a new cache to store small glyph bitmaps. */ - /* */ - /* <Input> */ - /* manager :: A handle to the source cache manager. */ - /* */ - /* <Output> */ - /* acache :: A handle to the new sbit cache. NULL in case of error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FTC_SBitCache_New( FTC_Manager manager, - FTC_SBitCache *acache ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_SBitCache_Lookup */ - /* */ - /* <Description> */ - /* Look up a given small glyph bitmap in a given sbit cache and */ - /* `lock' it to prevent its flushing from the cache until needed. */ - /* */ - /* <Input> */ - /* cache :: A handle to the source sbit cache. */ - /* */ - /* type :: A pointer to the glyph image type descriptor. */ - /* */ - /* gindex :: The glyph index. */ - /* */ - /* <Output> */ - /* sbit :: A handle to a small bitmap descriptor. */ - /* */ - /* anode :: Used to return the address of of the corresponding cache */ - /* node after incrementing its reference count (see note */ - /* below). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The small bitmap descriptor and its bit buffer are owned by the */ - /* cache and should never be freed by the application. They might */ - /* as well disappear from memory on the next cache lookup, so don't */ - /* treat them as persistent data. */ - /* */ - /* The descriptor's `buffer' field is set to~0 to indicate a missing */ - /* glyph bitmap. */ - /* */ - /* If `anode' is _not_ NULL, it receives the address of the cache */ - /* node containing the bitmap, after increasing its reference count. */ - /* This ensures that the node (as well as the image) will always be */ - /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ - /* */ - /* If `anode' is NULL, the cache node is left unchanged, which means */ - /* that the bitmap could be flushed out of the cache on the next */ - /* call to one of the caching sub-system APIs. Don't assume that it */ - /* is persistent! */ - /* */ - FT_EXPORT( FT_Error ) - FTC_SBitCache_Lookup( FTC_SBitCache cache, - FTC_ImageType type, - FT_UInt gindex, - FTC_SBit *sbit, - FTC_Node *anode ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FTC_SBitCache_LookupScaler */ - /* */ - /* <Description> */ - /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */ - /* to specify the face ID and its size. */ - /* */ - /* <Input> */ - /* cache :: A handle to the source sbit cache. */ - /* */ - /* scaler :: A pointer to the scaler descriptor. */ - /* */ - /* load_flags :: The corresponding load flags. */ - /* */ - /* gindex :: The glyph index. */ - /* */ - /* <Output> */ - /* sbit :: A handle to a small bitmap descriptor. */ - /* */ - /* anode :: Used to return the address of of the corresponding */ - /* cache node after incrementing its reference count */ - /* (see note below). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The small bitmap descriptor and its bit buffer are owned by the */ - /* cache and should never be freed by the application. They might */ - /* as well disappear from memory on the next cache lookup, so don't */ - /* treat them as persistent data. */ - /* */ - /* The descriptor's `buffer' field is set to~0 to indicate a missing */ - /* glyph bitmap. */ - /* */ - /* If `anode' is _not_ NULL, it receives the address of the cache */ - /* node containing the bitmap, after increasing its reference count. */ - /* This ensures that the node (as well as the image) will always be */ - /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ - /* */ - /* If `anode' is NULL, the cache node is left unchanged, which means */ - /* that the bitmap could be flushed out of the cache on the next */ - /* call to one of the caching sub-system APIs. Don't assume that it */ - /* is persistent! */ - /* */ - FT_EXPORT( FT_Error ) - FTC_SBitCache_LookupScaler( FTC_SBitCache cache, - FTC_Scaler scaler, - FT_ULong load_flags, - FT_UInt gindex, - FTC_SBit *sbit, - FTC_Node *anode ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTCACHE_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftcffdrv.h b/third_party/freetype/include/freetype/ftcffdrv.h deleted file mode 100644 index 6c8e416cee332dcff8f405c665b5c7ecee217bad..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftcffdrv.h +++ /dev/null @@ -1,262 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftcffdrv.h */ -/* */ -/* FreeType API for controlling the CFF driver (specification only). */ -/* */ -/* Copyright 2013-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTCFFDRV_H__ -#define __FTCFFDRV_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /************************************************************************** - * - * @section: - * cff_driver - * - * @title: - * The CFF driver - * - * @abstract: - * Controlling the CFF driver module. - * - * @description: - * While FreeType's CFF driver doesn't expose API functions by itself, - * it is possible to control its behaviour with @FT_Property_Set and - * @FT_Property_Get. The list below gives the available properties - * together with the necessary macros and structures. - * - * The CFF driver's module name is `cff'. - * - * *Hinting* *and* *antialiasing* *principles* *of* *the* *new* *engine* - * - * The rasterizer is positioning horizontal features (e.g., ascender - * height & x-height, or crossbars) on the pixel grid and minimizing the - * amount of antialiasing applied to them, while placing vertical - * features (vertical stems) on the pixel grid without hinting, thus - * representing the stem position and weight accurately. Sometimes the - * vertical stems may be only partially black. In this context, - * `antialiasing' means that stems are not positioned exactly on pixel - * borders, causing a fuzzy appearance. - * - * There are two principles behind this approach. - * - * 1) No hinting in the horizontal direction: Unlike `superhinted' - * TrueType, which changes glyph widths to accommodate regular - * inter-glyph spacing, Adobe's approach is `faithful to the design' in - * representing both the glyph width and the inter-glyph spacing - * designed for the font. This makes the screen display as close as it - * can be to the result one would get with infinite resolution, while - * preserving what is considered the key characteristics of each glyph. - * Note that the distances between unhinted and grid-fitted positions at - * small sizes are comparable to kerning values and thus would be - * noticeable (and distracting) while reading if hinting were applied. - * - * One of the reasons to not hint horizontally is antialiasing for LCD - * screens: The pixel geometry of modern displays supplies three - * vertical sub-pixels as the eye moves horizontally across each visible - * pixel. On devices where we can be certain this characteristic is - * present a rasterizer can take advantage of the sub-pixels to add - * increments of weight. In Western writing systems this turns out to - * be the more critical direction anyway; the weights and spacing of - * vertical stems (see above) are central to Armenian, Cyrillic, Greek, - * and Latin type designs. Even when the rasterizer uses greyscale - * antialiasing instead of color (a necessary compromise when one - * doesn't know the screen characteristics), the unhinted vertical - * features preserve the design's weight and spacing much better than - * aliased type would. - * - * 2) Aligment in the vertical direction: Weights and spacing along the - * y~axis are less critical; what is much more important is the visual - * alignment of related features (like cap-height and x-height). The - * sense of alignment for these is enhanced by the sharpness of grid-fit - * edges, while the cruder vertical resolution (full pixels instead of - * 1/3 pixels) is less of a problem. - * - * On the technical side, horizontal alignment zones for ascender, - * x-height, and other important height values (traditionally called - * `blue zones') as defined in the font are positioned independently, - * each being rounded to the nearest pixel edge, taking care of - * overshoot suppression at small sizes, stem darkening, and scaling. - * - * Hstems (this is, hint values defined in the font to help align - * horizontal features) that fall within a blue zone are said to be - * `captured' and are aligned to that zone. Uncaptured stems are moved - * in one of four ways, top edge up or down, bottom edge up or down. - * Unless there are conflicting hstems, the smallest movement is taken - * to minimize distortion. - * - * @order: - * hinting-engine - * no-stem-darkening - * darkening-parameters - * - */ - - - /************************************************************************** - * - * @property: - * hinting-engine - * - * @description: - * Thanks to Adobe, which contributed a new hinting (and parsing) - * engine, an application can select between `freetype' and `adobe' if - * compiled with CFF_CONFIG_OPTION_OLD_ENGINE. If this configuration - * macro isn't defined, `hinting-engine' does nothing. - * - * The default engine is `freetype' if CFF_CONFIG_OPTION_OLD_ENGINE is - * defined, and `adobe' otherwise. - * - * The following example code demonstrates how to select Adobe's hinting - * engine (omitting the error handling). - * - * { - * FT_Library library; - * FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "cff", - * "hinting-engine", &hinting_engine ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - */ - - - /************************************************************************** - * - * @enum: - * FT_CFF_HINTING_XXX - * - * @description: - * A list of constants used for the @hinting-engine property to select - * the hinting engine for CFF fonts. - * - * @values: - * FT_CFF_HINTING_FREETYPE :: - * Use the old FreeType hinting engine. - * - * FT_CFF_HINTING_ADOBE :: - * Use the hinting engine contributed by Adobe. - * - */ -#define FT_CFF_HINTING_FREETYPE 0 -#define FT_CFF_HINTING_ADOBE 1 - - - /************************************************************************** - * - * @property: - * no-stem-darkening - * - * @description: - * By default, the Adobe CFF engine darkens stems at smaller sizes, - * regardless of hinting, to enhance contrast. This feature requires - * a rendering system with proper gamma correction. Setting this - * property, stem darkening gets switched off. - * - * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set. - * - * { - * FT_Library library; - * FT_Bool no_stem_darkening = TRUE; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "cff", - * "no-stem-darkening", &no_stem_darkening ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - */ - - - /************************************************************************** - * - * @property: - * darkening-parameters - * - * @description: - * By default, the Adobe CFF engine darkens stems as follows (if the - * `no-stem-darkening' property isn't set): - * - * { - * stem width <= 0.5px: darkening amount = 0.4px - * stem width = 1px: darkening amount = 0.275px - * stem width = 1.667px: darkening amount = 0.275px - * stem width >= 2.333px: darkening amount = 0px - * } - * - * and piecewise linear in-between. At configuration time, these four - * control points can be set with the macro - * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS'. At runtime, the control - * points can be changed using the `darkening-parameters' property, as - * the following example demonstrates. - * - * { - * FT_Library library; - * FT_Int darken_params[8] = { 500, 300, // x1, y1 - * 1000, 200, // x2, y2 - * 1500, 100, // x3, y3 - * 2000, 0 }; // x4, y4 - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "cff", - * "darkening-parameters", darken_params ); - * } - * - * The x~values give the stem width, and the y~values the darkening - * amount. The unit is 1000th of pixels. All coordinate values must be - * positive; the x~values must be monotonically increasing; the - * y~values must be monotonically decreasing and smaller than or - * equal to 500 (corresponding to half a pixel); the slope of each - * linear piece must be shallower than -1 (e.g., -.4). - * - * @note: - * This property can be used with @FT_Property_Get also. - * - */ - - /* */ - - -FT_END_HEADER - - -#endif /* __FTCFFDRV_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftcid.h b/third_party/freetype/include/freetype/ftcid.h deleted file mode 100644 index 05741c85b7ac633b206967dd3145df79c2ccaea9..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftcid.h +++ /dev/null @@ -1,168 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftcid.h */ -/* */ -/* FreeType API for accessing CID font information (specification). */ -/* */ -/* Copyright 2007-2015 by */ -/* Dereg Clegg and Michael Toftdal. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTCID_H__ -#define __FTCID_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* cid_fonts */ - /* */ - /* <Title> */ - /* CID Fonts */ - /* */ - /* <Abstract> */ - /* CID-keyed font specific API. */ - /* */ - /* <Description> */ - /* This section contains the declaration of CID-keyed font specific */ - /* functions. */ - /* */ - /*************************************************************************/ - - - /********************************************************************** - * - * @function: - * FT_Get_CID_Registry_Ordering_Supplement - * - * @description: - * Retrieve the Registry/Ordering/Supplement triple (also known as the - * "R/O/S") from a CID-keyed font. - * - * @input: - * face :: - * A handle to the input face. - * - * @output: - * registry :: - * The registry, as a C~string, owned by the face. - * - * ordering :: - * The ordering, as a C~string, owned by the face. - * - * supplement :: - * The supplement. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with CID faces, returning an error - * otherwise. - * - * @since: - * 2.3.6 - */ - FT_EXPORT( FT_Error ) - FT_Get_CID_Registry_Ordering_Supplement( FT_Face face, - const char* *registry, - const char* *ordering, - FT_Int *supplement); - - - /********************************************************************** - * - * @function: - * FT_Get_CID_Is_Internally_CID_Keyed - * - * @description: - * Retrieve the type of the input face, CID keyed or not. In - * constrast to the @FT_IS_CID_KEYED macro this function returns - * successfully also for CID-keyed fonts in an SNFT wrapper. - * - * @input: - * face :: - * A handle to the input face. - * - * @output: - * is_cid :: - * The type of the face as an @FT_Bool. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with CID faces and OpenType fonts, - * returning an error otherwise. - * - * @since: - * 2.3.9 - */ - FT_EXPORT( FT_Error ) - FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face, - FT_Bool *is_cid ); - - - /********************************************************************** - * - * @function: - * FT_Get_CID_From_Glyph_Index - * - * @description: - * Retrieve the CID of the input glyph index. - * - * @input: - * face :: - * A handle to the input face. - * - * glyph_index :: - * The input glyph index. - * - * @output: - * cid :: - * The CID as an @FT_UInt. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with CID faces and OpenType fonts, - * returning an error otherwise. - * - * @since: - * 2.3.9 - */ - FT_EXPORT( FT_Error ) - FT_Get_CID_From_Glyph_Index( FT_Face face, - FT_UInt glyph_index, - FT_UInt *cid ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTCID_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/fterrdef.h b/third_party/freetype/include/freetype/fterrdef.h deleted file mode 100644 index d865da7127c25068f4935ffe6e5fbad5b31f6dea..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/fterrdef.h +++ /dev/null @@ -1,276 +0,0 @@ -/***************************************************************************/ -/* */ -/* fterrdef.h */ -/* */ -/* FreeType error codes (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* error_code_values */ - /* */ - /* <Title> */ - /* Error Code Values */ - /* */ - /* <Abstract> */ - /* All possible error codes returned by FreeType functions. */ - /* */ - /* <Description> */ - /* The list below is taken verbatim from the file `fterrdef.h' */ - /* (loaded automatically by including `FT_FREETYPE_H'). The first */ - /* argument of the `FT_ERROR_DEF_' macro is the error label; by */ - /* default, the prefix `FT_Err_' gets added so that you get error */ - /* names like `FT_Err_Cannot_Open_Resource'. The second argument is */ - /* the error code, and the last argument an error string, which is not */ - /* used by FreeType. */ - /* */ - /* Within your application you should *only* use error names and */ - /* *never* its numeric values! The latter might (and actually do) */ - /* change in forthcoming FreeType versions. */ - /* */ - /* Macro `FT_NOERRORDEF_' defines `FT_Err_Ok', which is always zero. */ - /* See the `Error Enumerations' subsection how to automatically */ - /* generate a list of error strings. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Err_XXX */ - /* */ - /*************************************************************************/ - - /* generic errors */ - - FT_NOERRORDEF_( Ok, 0x00, - "no error" ) - - FT_ERRORDEF_( Cannot_Open_Resource, 0x01, - "cannot open resource" ) - FT_ERRORDEF_( Unknown_File_Format, 0x02, - "unknown file format" ) - FT_ERRORDEF_( Invalid_File_Format, 0x03, - "broken file" ) - FT_ERRORDEF_( Invalid_Version, 0x04, - "invalid FreeType version" ) - FT_ERRORDEF_( Lower_Module_Version, 0x05, - "module version is too low" ) - FT_ERRORDEF_( Invalid_Argument, 0x06, - "invalid argument" ) - FT_ERRORDEF_( Unimplemented_Feature, 0x07, - "unimplemented feature" ) - FT_ERRORDEF_( Invalid_Table, 0x08, - "broken table" ) - FT_ERRORDEF_( Invalid_Offset, 0x09, - "broken offset within table" ) - FT_ERRORDEF_( Array_Too_Large, 0x0A, - "array allocation size too large" ) - FT_ERRORDEF_( Missing_Module, 0x0B, - "missing module" ) - FT_ERRORDEF_( Missing_Property, 0x0C, - "missing property" ) - - /* glyph/character errors */ - - FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, - "invalid glyph index" ) - FT_ERRORDEF_( Invalid_Character_Code, 0x11, - "invalid character code" ) - FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, - "unsupported glyph image format" ) - FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, - "cannot render this glyph format" ) - FT_ERRORDEF_( Invalid_Outline, 0x14, - "invalid outline" ) - FT_ERRORDEF_( Invalid_Composite, 0x15, - "invalid composite glyph" ) - FT_ERRORDEF_( Too_Many_Hints, 0x16, - "too many hints" ) - FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, - "invalid pixel size" ) - - /* handle errors */ - - FT_ERRORDEF_( Invalid_Handle, 0x20, - "invalid object handle" ) - FT_ERRORDEF_( Invalid_Library_Handle, 0x21, - "invalid library handle" ) - FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, - "invalid module handle" ) - FT_ERRORDEF_( Invalid_Face_Handle, 0x23, - "invalid face handle" ) - FT_ERRORDEF_( Invalid_Size_Handle, 0x24, - "invalid size handle" ) - FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, - "invalid glyph slot handle" ) - FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, - "invalid charmap handle" ) - FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, - "invalid cache manager handle" ) - FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, - "invalid stream handle" ) - - /* driver errors */ - - FT_ERRORDEF_( Too_Many_Drivers, 0x30, - "too many modules" ) - FT_ERRORDEF_( Too_Many_Extensions, 0x31, - "too many extensions" ) - - /* memory errors */ - - FT_ERRORDEF_( Out_Of_Memory, 0x40, - "out of memory" ) - FT_ERRORDEF_( Unlisted_Object, 0x41, - "unlisted object" ) - - /* stream errors */ - - FT_ERRORDEF_( Cannot_Open_Stream, 0x51, - "cannot open stream" ) - FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, - "invalid stream seek" ) - FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, - "invalid stream skip" ) - FT_ERRORDEF_( Invalid_Stream_Read, 0x54, - "invalid stream read" ) - FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, - "invalid stream operation" ) - FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, - "invalid frame operation" ) - FT_ERRORDEF_( Nested_Frame_Access, 0x57, - "nested frame access" ) - FT_ERRORDEF_( Invalid_Frame_Read, 0x58, - "invalid frame read" ) - - /* raster errors */ - - FT_ERRORDEF_( Raster_Uninitialized, 0x60, - "raster uninitialized" ) - FT_ERRORDEF_( Raster_Corrupted, 0x61, - "raster corrupted" ) - FT_ERRORDEF_( Raster_Overflow, 0x62, - "raster overflow" ) - FT_ERRORDEF_( Raster_Negative_Height, 0x63, - "negative height while rastering" ) - - /* cache errors */ - - FT_ERRORDEF_( Too_Many_Caches, 0x70, - "too many registered caches" ) - - /* TrueType and SFNT errors */ - - FT_ERRORDEF_( Invalid_Opcode, 0x80, - "invalid opcode" ) - FT_ERRORDEF_( Too_Few_Arguments, 0x81, - "too few arguments" ) - FT_ERRORDEF_( Stack_Overflow, 0x82, - "stack overflow" ) - FT_ERRORDEF_( Code_Overflow, 0x83, - "code overflow" ) - FT_ERRORDEF_( Bad_Argument, 0x84, - "bad argument" ) - FT_ERRORDEF_( Divide_By_Zero, 0x85, - "division by zero" ) - FT_ERRORDEF_( Invalid_Reference, 0x86, - "invalid reference" ) - FT_ERRORDEF_( Debug_OpCode, 0x87, - "found debug opcode" ) - FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, - "found ENDF opcode in execution stream" ) - FT_ERRORDEF_( Nested_DEFS, 0x89, - "nested DEFS" ) - FT_ERRORDEF_( Invalid_CodeRange, 0x8A, - "invalid code range" ) - FT_ERRORDEF_( Execution_Too_Long, 0x8B, - "execution context too long" ) - FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, - "too many function definitions" ) - FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, - "too many instruction definitions" ) - FT_ERRORDEF_( Table_Missing, 0x8E, - "SFNT font table missing" ) - FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, - "horizontal header (hhea) table missing" ) - FT_ERRORDEF_( Locations_Missing, 0x90, - "locations (loca) table missing" ) - FT_ERRORDEF_( Name_Table_Missing, 0x91, - "name table missing" ) - FT_ERRORDEF_( CMap_Table_Missing, 0x92, - "character map (cmap) table missing" ) - FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, - "horizontal metrics (hmtx) table missing" ) - FT_ERRORDEF_( Post_Table_Missing, 0x94, - "PostScript (post) table missing" ) - FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, - "invalid horizontal metrics" ) - FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, - "invalid character map (cmap) format" ) - FT_ERRORDEF_( Invalid_PPem, 0x97, - "invalid ppem value" ) - FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, - "invalid vertical metrics" ) - FT_ERRORDEF_( Could_Not_Find_Context, 0x99, - "could not find context" ) - FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, - "invalid PostScript (post) table format" ) - FT_ERRORDEF_( Invalid_Post_Table, 0x9B, - "invalid PostScript (post) table" ) - - /* CFF, CID, and Type 1 errors */ - - FT_ERRORDEF_( Syntax_Error, 0xA0, - "opcode syntax error" ) - FT_ERRORDEF_( Stack_Underflow, 0xA1, - "argument stack underflow" ) - FT_ERRORDEF_( Ignore, 0xA2, - "ignore" ) - FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, - "no Unicode glyph name found" ) - FT_ERRORDEF_( Glyph_Too_Big, 0xA4, - "glyph to big for hinting" ) - - /* BDF errors */ - - FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, - "`STARTFONT' field missing" ) - FT_ERRORDEF_( Missing_Font_Field, 0xB1, - "`FONT' field missing" ) - FT_ERRORDEF_( Missing_Size_Field, 0xB2, - "`SIZE' field missing" ) - FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, - "`FONTBOUNDINGBOX' field missing" ) - FT_ERRORDEF_( Missing_Chars_Field, 0xB4, - "`CHARS' field missing" ) - FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, - "`STARTCHAR' field missing" ) - FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, - "`ENCODING' field missing" ) - FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, - "`BBX' field missing" ) - FT_ERRORDEF_( Bbx_Too_Big, 0xB8, - "`BBX' too big" ) - FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, - "Font header corrupted or missing fields" ) - FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, - "Font glyphs corrupted or missing fields" ) - - /* */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/fterrors.h b/third_party/freetype/include/freetype/fterrors.h deleted file mode 100644 index 0507b9ad7dcf318a7ecc3bdc3a179db1b4b31cdb..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/fterrors.h +++ /dev/null @@ -1,216 +0,0 @@ -/***************************************************************************/ -/* */ -/* fterrors.h */ -/* */ -/* FreeType error code handling (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* error_enumerations */ - /* */ - /* <Title> */ - /* Error Enumerations */ - /* */ - /* <Abstract> */ - /* How to handle errors and error strings. */ - /* */ - /* <Description> */ - /* The header file `fterrors.h' (which is automatically included by */ - /* `freetype.h' defines the handling of FreeType's enumeration */ - /* constants. It can also be used to generate error message strings */ - /* with a small macro trick explained below. */ - /* */ - /* *Error* *Formats* */ - /* */ - /* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */ - /* defined in `ftoption.h' in order to make the higher byte indicate */ - /* the module where the error has happened (this is not compatible */ - /* with standard builds of FreeType 2, however). See the file */ - /* `ftmoderr.h' for more details. */ - /* */ - /* *Error* *Message* *Strings* */ - /* */ - /* Error definitions are set up with special macros that allow client */ - /* applications to build a table of error message strings. The */ - /* strings are not included in a normal build of FreeType 2 to */ - /* save space (most client applications do not use them). */ - /* */ - /* To do so, you have to define the following macros before including */ - /* this file. */ - /* */ - /* { */ - /* FT_ERROR_START_LIST */ - /* } */ - /* */ - /* This macro is called before anything else to define the start of */ - /* the error list. It is followed by several FT_ERROR_DEF calls. */ - /* */ - /* { */ - /* FT_ERROR_DEF( e, v, s ) */ - /* } */ - /* */ - /* This macro is called to define one single error. `e' is the error */ - /* code identifier (e.g., `Invalid_Argument'), `v' is the error's */ - /* numerical value, and `s' is the corresponding error string. */ - /* */ - /* { */ - /* FT_ERROR_END_LIST */ - /* } */ - /* */ - /* This macro ends the list. */ - /* */ - /* Additionally, you have to undefine `__FTERRORS_H__' before */ - /* #including this file. */ - /* */ - /* Here is a simple example. */ - /* */ - /* { */ - /* #undef __FTERRORS_H__ */ - /* #define FT_ERRORDEF( e, v, s ) { e, s }, */ - /* #define FT_ERROR_START_LIST { */ - /* #define FT_ERROR_END_LIST { 0, NULL } }; */ - /* */ - /* const struct */ - /* { */ - /* int err_code; */ - /* const char* err_msg; */ - /* } ft_errors[] = */ - /* */ - /* #include FT_ERRORS_H */ - /* } */ - /* */ - /* Note that `FT_Err_Ok' is _not_ defined with `FT_ERRORDEF' but with */ - /* `FT_NOERRORDEF'; it is always zero. */ - /* */ - /*************************************************************************/ - - /* */ - -#ifndef __FTERRORS_H__ -#define __FTERRORS_H__ - - - /* include module base error codes */ -#include FT_MODULE_ERRORS_H - - - /*******************************************************************/ - /*******************************************************************/ - /***** *****/ - /***** SETUP MACROS *****/ - /***** *****/ - /*******************************************************************/ - /*******************************************************************/ - - -#undef FT_NEED_EXTERN_C - - - /* FT_ERR_PREFIX is used as a prefix for error identifiers. */ - /* By default, we use `FT_Err_'. */ - /* */ -#ifndef FT_ERR_PREFIX -#define FT_ERR_PREFIX FT_Err_ -#endif - - - /* FT_ERR_BASE is used as the base for module-specific errors. */ - /* */ -#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS - -#ifndef FT_ERR_BASE -#define FT_ERR_BASE FT_Mod_Err_Base -#endif - -#else - -#undef FT_ERR_BASE -#define FT_ERR_BASE 0 - -#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */ - - - /* If FT_ERRORDEF is not defined, we need to define a simple */ - /* enumeration type. */ - /* */ -#ifndef FT_ERRORDEF - -#define FT_ERRORDEF( e, v, s ) e = v, -#define FT_ERROR_START_LIST enum { -#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) }; - -#ifdef __cplusplus -#define FT_NEED_EXTERN_C - extern "C" { -#endif - -#endif /* !FT_ERRORDEF */ - - - /* this macro is used to define an error */ -#define FT_ERRORDEF_( e, v, s ) \ - FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s ) - - /* this is only used for <module>_Err_Ok, which must be 0! */ -#define FT_NOERRORDEF_( e, v, s ) \ - FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s ) - - -#ifdef FT_ERROR_START_LIST - FT_ERROR_START_LIST -#endif - - - /* now include the error codes */ -#include FT_ERROR_DEFINITIONS_H - - -#ifdef FT_ERROR_END_LIST - FT_ERROR_END_LIST -#endif - - - /*******************************************************************/ - /*******************************************************************/ - /***** *****/ - /***** SIMPLE CLEANUP *****/ - /***** *****/ - /*******************************************************************/ - /*******************************************************************/ - -#ifdef FT_NEED_EXTERN_C - } -#endif - -#undef FT_ERROR_START_LIST -#undef FT_ERROR_END_LIST - -#undef FT_ERRORDEF -#undef FT_ERRORDEF_ -#undef FT_NOERRORDEF_ - -#undef FT_NEED_EXTERN_C -#undef FT_ERR_BASE - - /* FT_ERR_PREFIX is needed internally */ -#ifndef FT2_BUILD_LIBRARY -#undef FT_ERR_PREFIX -#endif - -#endif /* __FTERRORS_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftfntfmt.h b/third_party/freetype/include/freetype/ftfntfmt.h deleted file mode 100644 index 1f8ff28f104ddf13013a68f6d75d4c9b0f5cea16..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftfntfmt.h +++ /dev/null @@ -1,92 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftfntfmt.h */ -/* */ -/* Support functions for font formats. */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTFNTFMT_H__ -#define __FTFNTFMT_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* font_formats */ - /* */ - /* <Title> */ - /* Font Formats */ - /* */ - /* <Abstract> */ - /* Getting the font format. */ - /* */ - /* <Description> */ - /* The single function in this section can be used to get the font */ - /* format. Note that this information is not needed normally; */ - /* however, there are special cases (like in PDF devices) where it is */ - /* important to differentiate, in spite of FreeType's uniform API. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Font_Format */ - /* */ - /* <Description> */ - /* Return a string describing the format of a given face. Possible */ - /* values are `TrueType', `Type~1', `BDF', `PCF', `Type~42', */ - /* `CID~Type~1', `CFF', `PFR', and `Windows~FNT'. */ - /* */ - /* The return value is suitable to be used as an X11 FONT_PROPERTY. */ - /* */ - /* <Input> */ - /* face :: */ - /* Input face handle. */ - /* */ - /* <Return> */ - /* Font format string. NULL in case of error. */ - /* */ - /* <Note> */ - /* A deprecated name for the same function is */ - /* `FT_Get_X11_Font_Format'. */ - /* */ - FT_EXPORT( const char* ) - FT_Get_Font_Format( FT_Face face ); - - - /* deprecated */ - FT_EXPORT( const char* ) - FT_Get_X11_Font_Format( FT_Face face ); - - - /* */ - - -FT_END_HEADER - -#endif /* __FTFNTFMT_H__ */ diff --git a/third_party/freetype/include/freetype/ftgasp.h b/third_party/freetype/include/freetype/ftgasp.h deleted file mode 100644 index 9a9b6321b32e72dc627c631c1cb97b730831c109..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftgasp.h +++ /dev/null @@ -1,129 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgasp.h */ -/* */ -/* Access of TrueType's `gasp' table (specification). */ -/* */ -/* Copyright 2007-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef _FT_GASP_H_ -#define _FT_GASP_H_ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - - /*************************************************************************** - * - * @section: - * gasp_table - * - * @title: - * Gasp Table - * - * @abstract: - * Retrieving TrueType `gasp' table entries. - * - * @description: - * The function @FT_Get_Gasp can be used to query a TrueType or OpenType - * font for specific entries in its `gasp' table, if any. This is - * mainly useful when implementing native TrueType hinting with the - * bytecode interpreter to duplicate the Windows text rendering results. - */ - - /************************************************************************* - * - * @enum: - * FT_GASP_XXX - * - * @description: - * A list of values and/or bit-flags returned by the @FT_Get_Gasp - * function. - * - * @values: - * FT_GASP_NO_TABLE :: - * This special value means that there is no GASP table in this face. - * It is up to the client to decide what to do. - * - * FT_GASP_DO_GRIDFIT :: - * Grid-fitting and hinting should be performed at the specified ppem. - * This *really* means TrueType bytecode interpretation. If this bit - * is not set, no hinting gets applied. - * - * FT_GASP_DO_GRAY :: - * Anti-aliased rendering should be performed at the specified ppem. - * If not set, do monochrome rendering. - * - * FT_GASP_SYMMETRIC_SMOOTHING :: - * If set, smoothing along multiple axes must be used with ClearType. - * - * FT_GASP_SYMMETRIC_GRIDFIT :: - * Grid-fitting must be used with ClearType's symmetric smoothing. - * - * @note: - * The bit-flags `FT_GASP_DO_GRIDFIT' and `FT_GASP_DO_GRAY' are to be - * used for standard font rasterization only. Independently of that, - * `FT_GASP_SYMMETRIC_SMOOTHING' and `FT_GASP_SYMMETRIC_GRIDFIT' are to - * be used if ClearType is enabled (and `FT_GASP_DO_GRIDFIT' and - * `FT_GASP_DO_GRAY' are consequently ignored). - * - * `ClearType' is Microsoft's implementation of LCD rendering, partly - * protected by patents. - * - * @since: - * 2.3.0 - */ -#define FT_GASP_NO_TABLE -1 -#define FT_GASP_DO_GRIDFIT 0x01 -#define FT_GASP_DO_GRAY 0x02 -#define FT_GASP_SYMMETRIC_SMOOTHING 0x08 -#define FT_GASP_SYMMETRIC_GRIDFIT 0x10 - - - /************************************************************************* - * - * @func: - * FT_Get_Gasp - * - * @description: - * Read the `gasp' table from a TrueType or OpenType font file and - * return the entry corresponding to a given character pixel size. - * - * @input: - * face :: The source face handle. - * ppem :: The vertical character pixel size. - * - * @return: - * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no - * `gasp' table in the face. - * - * @since: - * 2.3.0 - */ - FT_EXPORT( FT_Int ) - FT_Get_Gasp( FT_Face face, - FT_UInt ppem ); - - /* */ - - -#endif /* _FT_GASP_H_ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftglyph.h b/third_party/freetype/include/freetype/ftglyph.h deleted file mode 100644 index 803ad396219f138806cdc296a04bce7dd3d65cae..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftglyph.h +++ /dev/null @@ -1,605 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftglyph.h */ -/* */ -/* FreeType convenience functions to handle glyphs (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file contains the definition of several convenience functions */ - /* that can be used by client applications to easily retrieve glyph */ - /* bitmaps and outlines from a given face. */ - /* */ - /* These functions should be optional if you are writing a font server */ - /* or text layout engine on top of FreeType. However, they are pretty */ - /* handy for many other simple uses of the library. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTGLYPH_H__ -#define __FTGLYPH_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* glyph_management */ - /* */ - /* <Title> */ - /* Glyph Management */ - /* */ - /* <Abstract> */ - /* Generic interface to manage individual glyph data. */ - /* */ - /* <Description> */ - /* This section contains definitions used to manage glyph data */ - /* through generic FT_Glyph objects. Each of them can contain a */ - /* bitmap, a vector outline, or even images in other formats. */ - /* */ - /*************************************************************************/ - - - /* forward declaration to a private type */ - typedef struct FT_Glyph_Class_ FT_Glyph_Class; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Glyph */ - /* */ - /* <Description> */ - /* Handle to an object used to model generic glyph images. It is a */ - /* pointer to the @FT_GlyphRec structure and can contain a glyph */ - /* bitmap or pointer. */ - /* */ - /* <Note> */ - /* Glyph objects are not owned by the library. You must thus release */ - /* them manually (through @FT_Done_Glyph) _before_ calling */ - /* @FT_Done_FreeType. */ - /* */ - typedef struct FT_GlyphRec_* FT_Glyph; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_GlyphRec */ - /* */ - /* <Description> */ - /* The root glyph structure contains a given glyph image plus its */ - /* advance width in 16.16 fixed-point format. */ - /* */ - /* <Fields> */ - /* library :: A handle to the FreeType library object. */ - /* */ - /* clazz :: A pointer to the glyph's class. Private. */ - /* */ - /* format :: The format of the glyph's image. */ - /* */ - /* advance :: A 16.16 vector that gives the glyph's advance width. */ - /* */ - typedef struct FT_GlyphRec_ - { - FT_Library library; - const FT_Glyph_Class* clazz; - FT_Glyph_Format format; - FT_Vector advance; - - } FT_GlyphRec; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_BitmapGlyph */ - /* */ - /* <Description> */ - /* A handle to an object used to model a bitmap glyph image. This is */ - /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */ - /* */ - typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_BitmapGlyphRec */ - /* */ - /* <Description> */ - /* A structure used for bitmap glyph images. This really is a */ - /* `sub-class' of @FT_GlyphRec. */ - /* */ - /* <Fields> */ - /* root :: The root @FT_Glyph fields. */ - /* */ - /* left :: The left-side bearing, i.e., the horizontal distance */ - /* from the current pen position to the left border of the */ - /* glyph bitmap. */ - /* */ - /* top :: The top-side bearing, i.e., the vertical distance from */ - /* the current pen position to the top border of the glyph */ - /* bitmap. This distance is positive for upwards~y! */ - /* */ - /* bitmap :: A descriptor for the bitmap. */ - /* */ - /* <Note> */ - /* You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have */ - /* `glyph->format == FT_GLYPH_FORMAT_BITMAP'. This lets you access */ - /* the bitmap's contents easily. */ - /* */ - /* The corresponding pixel buffer is always owned by @FT_BitmapGlyph */ - /* and is thus created and destroyed with it. */ - /* */ - typedef struct FT_BitmapGlyphRec_ - { - FT_GlyphRec root; - FT_Int left; - FT_Int top; - FT_Bitmap bitmap; - - } FT_BitmapGlyphRec; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_OutlineGlyph */ - /* */ - /* <Description> */ - /* A handle to an object used to model an outline glyph image. This */ - /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */ - /* */ - typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_OutlineGlyphRec */ - /* */ - /* <Description> */ - /* A structure used for outline (vectorial) glyph images. This */ - /* really is a `sub-class' of @FT_GlyphRec. */ - /* */ - /* <Fields> */ - /* root :: The root @FT_Glyph fields. */ - /* */ - /* outline :: A descriptor for the outline. */ - /* */ - /* <Note> */ - /* You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have */ - /* `glyph->format == FT_GLYPH_FORMAT_OUTLINE'. This lets you access */ - /* the outline's content easily. */ - /* */ - /* As the outline is extracted from a glyph slot, its coordinates are */ - /* expressed normally in 26.6 pixels, unless the flag */ - /* @FT_LOAD_NO_SCALE was used in @FT_Load_Glyph() or @FT_Load_Char(). */ - /* */ - /* The outline's tables are always owned by the object and are */ - /* destroyed with it. */ - /* */ - typedef struct FT_OutlineGlyphRec_ - { - FT_GlyphRec root; - FT_Outline outline; - - } FT_OutlineGlyphRec; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Glyph */ - /* */ - /* <Description> */ - /* A function used to extract a glyph image from a slot. Note that */ - /* the created @FT_Glyph object must be released with @FT_Done_Glyph. */ - /* */ - /* <Input> */ - /* slot :: A handle to the source glyph slot. */ - /* */ - /* <Output> */ - /* aglyph :: A handle to the glyph object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Glyph( FT_GlyphSlot slot, - FT_Glyph *aglyph ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_Copy */ - /* */ - /* <Description> */ - /* A function used to copy a glyph image. Note that the created */ - /* @FT_Glyph object must be released with @FT_Done_Glyph. */ - /* */ - /* <Input> */ - /* source :: A handle to the source glyph object. */ - /* */ - /* <Output> */ - /* target :: A handle to the target glyph object. 0~in case of */ - /* error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Glyph_Copy( FT_Glyph source, - FT_Glyph *target ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_Transform */ - /* */ - /* <Description> */ - /* Transform a glyph image if its format is scalable. */ - /* */ - /* <InOut> */ - /* glyph :: A handle to the target glyph object. */ - /* */ - /* <Input> */ - /* matrix :: A pointer to a 2x2 matrix to apply. */ - /* */ - /* delta :: A pointer to a 2d vector to apply. Coordinates are */ - /* expressed in 1/64th of a pixel. */ - /* */ - /* <Return> */ - /* FreeType error code (if not 0, the glyph format is not scalable). */ - /* */ - /* <Note> */ - /* The 2x2 transformation matrix is also applied to the glyph's */ - /* advance vector. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Glyph_Transform( FT_Glyph glyph, - FT_Matrix* matrix, - FT_Vector* delta ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Glyph_BBox_Mode */ - /* */ - /* <Description> */ - /* The mode how the values of @FT_Glyph_Get_CBox are returned. */ - /* */ - /* <Values> */ - /* FT_GLYPH_BBOX_UNSCALED :: */ - /* Return unscaled font units. */ - /* */ - /* FT_GLYPH_BBOX_SUBPIXELS :: */ - /* Return unfitted 26.6 coordinates. */ - /* */ - /* FT_GLYPH_BBOX_GRIDFIT :: */ - /* Return grid-fitted 26.6 coordinates. */ - /* */ - /* FT_GLYPH_BBOX_TRUNCATE :: */ - /* Return coordinates in integer pixels. */ - /* */ - /* FT_GLYPH_BBOX_PIXELS :: */ - /* Return grid-fitted pixel coordinates. */ - /* */ - typedef enum FT_Glyph_BBox_Mode_ - { - FT_GLYPH_BBOX_UNSCALED = 0, - FT_GLYPH_BBOX_SUBPIXELS = 0, - FT_GLYPH_BBOX_GRIDFIT = 1, - FT_GLYPH_BBOX_TRUNCATE = 2, - FT_GLYPH_BBOX_PIXELS = 3 - - } FT_Glyph_BBox_Mode; - - - /* these constants are deprecated; use the corresponding */ - /* `FT_Glyph_BBox_Mode' values instead */ -#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED -#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS -#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT -#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE -#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_Get_CBox */ - /* */ - /* <Description> */ - /* Return a glyph's `control box'. The control box encloses all the */ - /* outline's points, including Bézier control points. Though it */ - /* coincides with the exact bounding box for most glyphs, it can be */ - /* slightly larger in some situations (like when rotating an outline */ - /* that contains Bézier outside arcs). */ - /* */ - /* Computing the control box is very fast, while getting the bounding */ - /* box can take much more time as it needs to walk over all segments */ - /* and arcs in the outline. To get the latter, you can use the */ - /* `ftbbox' component, which is dedicated to this single task. */ - /* */ - /* <Input> */ - /* glyph :: A handle to the source glyph object. */ - /* */ - /* mode :: The mode that indicates how to interpret the returned */ - /* bounding box values. */ - /* */ - /* <Output> */ - /* acbox :: The glyph coordinate bounding box. Coordinates are */ - /* expressed in 1/64th of pixels if it is grid-fitted. */ - /* */ - /* <Note> */ - /* Coordinates are relative to the glyph origin, using the y~upwards */ - /* convention. */ - /* */ - /* If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode' */ - /* must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font */ - /* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */ - /* is another name for this constant. */ - /* */ - /* If the font is tricky and the glyph has been loaded with */ - /* @FT_LOAD_NO_SCALE, the resulting CBox is meaningless. To get */ - /* reasonable values for the CBox it is necessary to load the glyph */ - /* at a large ppem value (so that the hinting instructions can */ - /* properly shift and scale the subglyphs), then extracting the CBox, */ - /* which can be eventually converted back to font units. */ - /* */ - /* Note that the maximum coordinates are exclusive, which means that */ - /* one can compute the width and height of the glyph image (be it in */ - /* integer or 26.6 pixels) as: */ - /* */ - /* { */ - /* width = bbox.xMax - bbox.xMin; */ - /* height = bbox.yMax - bbox.yMin; */ - /* } */ - /* */ - /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */ - /* @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, */ - /* which corresponds to: */ - /* */ - /* { */ - /* bbox.xMin = FLOOR(bbox.xMin); */ - /* bbox.yMin = FLOOR(bbox.yMin); */ - /* bbox.xMax = CEILING(bbox.xMax); */ - /* bbox.yMax = CEILING(bbox.yMax); */ - /* } */ - /* */ - /* To get the bbox in pixel coordinates, set `bbox_mode' to */ - /* @FT_GLYPH_BBOX_TRUNCATE. */ - /* */ - /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */ - /* to @FT_GLYPH_BBOX_PIXELS. */ - /* */ - FT_EXPORT( void ) - FT_Glyph_Get_CBox( FT_Glyph glyph, - FT_UInt bbox_mode, - FT_BBox *acbox ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Glyph_To_Bitmap */ - /* */ - /* <Description> */ - /* Convert a given glyph object to a bitmap glyph object. */ - /* */ - /* <InOut> */ - /* the_glyph :: A pointer to a handle to the target glyph. */ - /* */ - /* <Input> */ - /* render_mode :: An enumeration that describes how the data is */ - /* rendered. */ - /* */ - /* origin :: A pointer to a vector used to translate the glyph */ - /* image before rendering. Can be~0 (if no */ - /* translation). The origin is expressed in */ - /* 26.6 pixels. */ - /* */ - /* destroy :: A boolean that indicates that the original glyph */ - /* image should be destroyed by this function. It is */ - /* never destroyed in case of error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* This function does nothing if the glyph format isn't scalable. */ - /* */ - /* The glyph image is translated with the `origin' vector before */ - /* rendering. */ - /* */ - /* The first parameter is a pointer to an @FT_Glyph handle, that will */ - /* be _replaced_ by this function (with newly allocated data). */ - /* Typically, you would use (omitting error handling): */ - /* */ - /* */ - /* { */ - /* FT_Glyph glyph; */ - /* FT_BitmapGlyph glyph_bitmap; */ - /* */ - /* */ - /* // load glyph */ - /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ - /* */ - /* // extract glyph image */ - /* error = FT_Get_Glyph( face->glyph, &glyph ); */ - /* */ - /* // convert to a bitmap (default render mode + destroying old) */ - /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */ - /* { */ - /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, */ - /* 0, 1 ); */ - /* if ( error ) // `glyph' unchanged */ - /* ... */ - /* } */ - /* */ - /* // access bitmap content by typecasting */ - /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ - /* */ - /* // do funny stuff with it, like blitting/drawing */ - /* ... */ - /* */ - /* // discard glyph image (bitmap or not) */ - /* FT_Done_Glyph( glyph ); */ - /* } */ - /* */ - /* */ - /* Here another example, again without error handling: */ - /* */ - /* */ - /* { */ - /* FT_Glyph glyphs[MAX_GLYPHS] */ - /* */ - /* */ - /* ... */ - /* */ - /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ - /* error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || */ - /* FT_Get_Glyph ( face->glyph, &glyph[idx] ); */ - /* */ - /* ... */ - /* */ - /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ - /* { */ - /* FT_Glyph bitmap = glyphs[idx]; */ - /* */ - /* */ - /* ... */ - /* */ - /* // after this call, `bitmap' no longer points into */ - /* // the `glyphs' array (and the old value isn't destroyed) */ - /* FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 ); */ - /* */ - /* ... */ - /* */ - /* FT_Done_Glyph( bitmap ); */ - /* } */ - /* */ - /* ... */ - /* */ - /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */ - /* FT_Done_Glyph( glyphs[idx] ); */ - /* } */ - /* */ - FT_EXPORT( FT_Error ) - FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, - FT_Render_Mode render_mode, - FT_Vector* origin, - FT_Bool destroy ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_Glyph */ - /* */ - /* <Description> */ - /* Destroy a given glyph. */ - /* */ - /* <Input> */ - /* glyph :: A handle to the target glyph object. */ - /* */ - FT_EXPORT( void ) - FT_Done_Glyph( FT_Glyph glyph ); - - /* */ - - - /* other helpful functions */ - - /*************************************************************************/ - /* */ - /* <Section> */ - /* computations */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Matrix_Multiply */ - /* */ - /* <Description> */ - /* Perform the matrix operation `b = a*b'. */ - /* */ - /* <Input> */ - /* a :: A pointer to matrix `a'. */ - /* */ - /* <InOut> */ - /* b :: A pointer to matrix `b'. */ - /* */ - /* <Note> */ - /* The result is undefined if either `a' or `b' is zero. */ - /* */ - FT_EXPORT( void ) - FT_Matrix_Multiply( const FT_Matrix* a, - FT_Matrix* b ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Matrix_Invert */ - /* */ - /* <Description> */ - /* Invert a 2x2 matrix. Return an error if it can't be inverted. */ - /* */ - /* <InOut> */ - /* matrix :: A pointer to the target matrix. Remains untouched in */ - /* case of error. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Matrix_Invert( FT_Matrix* matrix ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTGLYPH_H__ */ - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/include/freetype/ftgxval.h b/third_party/freetype/include/freetype/ftgxval.h deleted file mode 100644 index 0e9ac1dad31681fa7ce457372b772d0e68e39c77..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftgxval.h +++ /dev/null @@ -1,357 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgxval.h */ -/* */ -/* FreeType API for validating TrueTypeGX/AAT tables (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* Masatake YAMATO, Redhat K.K, */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/***************************************************************************/ -/* */ -/* gxvalid is derived from both gxlayout module and otvalid module. */ -/* Development of gxlayout is supported by the Information-technology */ -/* Promotion Agency(IPA), Japan. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTGXVAL_H__ -#define __FTGXVAL_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* gx_validation */ - /* */ - /* <Title> */ - /* TrueTypeGX/AAT Validation */ - /* */ - /* <Abstract> */ - /* An API to validate TrueTypeGX/AAT tables. */ - /* */ - /* <Description> */ - /* This section contains the declaration of functions to validate */ - /* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */ - /* trak, prop, lcar). */ - /* */ - /* <Order> */ - /* FT_TrueTypeGX_Validate */ - /* FT_TrueTypeGX_Free */ - /* */ - /* FT_ClassicKern_Validate */ - /* FT_ClassicKern_Free */ - /* */ - /* FT_VALIDATE_GX_LENGTH */ - /* FT_VALIDATE_GXXXX */ - /* FT_VALIDATE_CKERNXXX */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* */ - /* Warning: Use FT_VALIDATE_XXX to validate a table. */ - /* Following definitions are for gxvalid developers. */ - /* */ - /* */ - /*************************************************************************/ - -#define FT_VALIDATE_feat_INDEX 0 -#define FT_VALIDATE_mort_INDEX 1 -#define FT_VALIDATE_morx_INDEX 2 -#define FT_VALIDATE_bsln_INDEX 3 -#define FT_VALIDATE_just_INDEX 4 -#define FT_VALIDATE_kern_INDEX 5 -#define FT_VALIDATE_opbd_INDEX 6 -#define FT_VALIDATE_trak_INDEX 7 -#define FT_VALIDATE_prop_INDEX 8 -#define FT_VALIDATE_lcar_INDEX 9 -#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX - - - /************************************************************************* - * - * @macro: - * FT_VALIDATE_GX_LENGTH - * - * @description: - * The number of tables checked in this module. Use it as a parameter - * for the `table-length' argument of function @FT_TrueTypeGX_Validate. - */ -#define FT_VALIDATE_GX_LENGTH (FT_VALIDATE_GX_LAST_INDEX + 1) - - /* */ - - /* Up to 0x1000 is used by otvalid. - Ox2xxx is reserved for feature OT extension. */ -#define FT_VALIDATE_GX_START 0x4000 -#define FT_VALIDATE_GX_BITFIELD( tag ) \ - ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX ) - - - /********************************************************************** - * - * @enum: - * FT_VALIDATE_GXXXX - * - * @description: - * A list of bit-field constants used with @FT_TrueTypeGX_Validate to - * indicate which TrueTypeGX/AAT Type tables should be validated. - * - * @values: - * FT_VALIDATE_feat :: - * Validate `feat' table. - * - * FT_VALIDATE_mort :: - * Validate `mort' table. - * - * FT_VALIDATE_morx :: - * Validate `morx' table. - * - * FT_VALIDATE_bsln :: - * Validate `bsln' table. - * - * FT_VALIDATE_just :: - * Validate `just' table. - * - * FT_VALIDATE_kern :: - * Validate `kern' table. - * - * FT_VALIDATE_opbd :: - * Validate `opbd' table. - * - * FT_VALIDATE_trak :: - * Validate `trak' table. - * - * FT_VALIDATE_prop :: - * Validate `prop' table. - * - * FT_VALIDATE_lcar :: - * Validate `lcar' table. - * - * FT_VALIDATE_GX :: - * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern, - * opbd, trak, prop and lcar). - * - */ - -#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat ) -#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort ) -#define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx ) -#define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln ) -#define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just ) -#define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern ) -#define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd ) -#define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak ) -#define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop ) -#define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar ) - -#define FT_VALIDATE_GX ( FT_VALIDATE_feat | \ - FT_VALIDATE_mort | \ - FT_VALIDATE_morx | \ - FT_VALIDATE_bsln | \ - FT_VALIDATE_just | \ - FT_VALIDATE_kern | \ - FT_VALIDATE_opbd | \ - FT_VALIDATE_trak | \ - FT_VALIDATE_prop | \ - FT_VALIDATE_lcar ) - - - /********************************************************************** - * - * @function: - * FT_TrueTypeGX_Validate - * - * @description: - * Validate various TrueTypeGX tables to assure that all offsets and - * indices are valid. The idea is that a higher-level library that - * actually does the text layout can access those tables without - * error checking (which can be quite time consuming). - * - * @input: - * face :: - * A handle to the input face. - * - * validation_flags :: - * A bit field that specifies the tables to be validated. See - * @FT_VALIDATE_GXXXX for possible values. - * - * table_length :: - * The size of the `tables' array. Normally, @FT_VALIDATE_GX_LENGTH - * should be passed. - * - * @output: - * tables :: - * The array where all validated sfnt tables are stored. - * The array itself must be allocated by a client. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with TrueTypeGX fonts, returning an error - * otherwise. - * - * After use, the application should deallocate the buffers pointed to by - * each `tables' element, by calling @FT_TrueTypeGX_Free. A NULL value - * indicates that the table either doesn't exist in the font, the - * application hasn't asked for validation, or the validator doesn't have - * the ability to validate the sfnt table. - */ - FT_EXPORT( FT_Error ) - FT_TrueTypeGX_Validate( FT_Face face, - FT_UInt validation_flags, - FT_Bytes tables[FT_VALIDATE_GX_LENGTH], - FT_UInt table_length ); - - - /********************************************************************** - * - * @function: - * FT_TrueTypeGX_Free - * - * @description: - * Free the buffer allocated by TrueTypeGX validator. - * - * @input: - * face :: - * A handle to the input face. - * - * table :: - * The pointer to the buffer allocated by - * @FT_TrueTypeGX_Validate. - * - * @note: - * This function must be used to free the buffer allocated by - * @FT_TrueTypeGX_Validate only. - */ - FT_EXPORT( void ) - FT_TrueTypeGX_Free( FT_Face face, - FT_Bytes table ); - - - /********************************************************************** - * - * @enum: - * FT_VALIDATE_CKERNXXX - * - * @description: - * A list of bit-field constants used with @FT_ClassicKern_Validate - * to indicate the classic kern dialect or dialects. If the selected - * type doesn't fit, @FT_ClassicKern_Validate regards the table as - * invalid. - * - * @values: - * FT_VALIDATE_MS :: - * Handle the `kern' table as a classic Microsoft kern table. - * - * FT_VALIDATE_APPLE :: - * Handle the `kern' table as a classic Apple kern table. - * - * FT_VALIDATE_CKERN :: - * Handle the `kern' as either classic Apple or Microsoft kern table. - */ -#define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 ) -#define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 ) - -#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE ) - - - /********************************************************************** - * - * @function: - * FT_ClassicKern_Validate - * - * @description: - * Validate classic (16-bit format) kern table to assure that the offsets - * and indices are valid. The idea is that a higher-level library that - * actually does the text layout can access those tables without error - * checking (which can be quite time consuming). - * - * The `kern' table validator in @FT_TrueTypeGX_Validate deals with both - * the new 32-bit format and the classic 16-bit format, while - * FT_ClassicKern_Validate only supports the classic 16-bit format. - * - * @input: - * face :: - * A handle to the input face. - * - * validation_flags :: - * A bit field that specifies the dialect to be validated. See - * @FT_VALIDATE_CKERNXXX for possible values. - * - * @output: - * ckern_table :: - * A pointer to the kern table. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * After use, the application should deallocate the buffers pointed to by - * `ckern_table', by calling @FT_ClassicKern_Free. A NULL value - * indicates that the table doesn't exist in the font. - */ - FT_EXPORT( FT_Error ) - FT_ClassicKern_Validate( FT_Face face, - FT_UInt validation_flags, - FT_Bytes *ckern_table ); - - - /********************************************************************** - * - * @function: - * FT_ClassicKern_Free - * - * @description: - * Free the buffer allocated by classic Kern validator. - * - * @input: - * face :: - * A handle to the input face. - * - * table :: - * The pointer to the buffer that is allocated by - * @FT_ClassicKern_Validate. - * - * @note: - * This function must be used to free the buffer allocated by - * @FT_ClassicKern_Validate only. - */ - FT_EXPORT( void ) - FT_ClassicKern_Free( FT_Face face, - FT_Bytes table ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTGXVAL_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftgzip.h b/third_party/freetype/include/freetype/ftgzip.h deleted file mode 100644 index b3a532d5e15f3f60d523a58c2474740853ff6127..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftgzip.h +++ /dev/null @@ -1,148 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgzip.h */ -/* */ -/* Gzip-compressed stream support. */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTGZIP_H__ -#define __FTGZIP_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /*************************************************************************/ - /* */ - /* <Section> */ - /* gzip */ - /* */ - /* <Title> */ - /* GZIP Streams */ - /* */ - /* <Abstract> */ - /* Using gzip-compressed font files. */ - /* */ - /* <Description> */ - /* This section contains the declaration of Gzip-specific functions. */ - /* */ - /*************************************************************************/ - - - /************************************************************************ - * - * @function: - * FT_Stream_OpenGzip - * - * @description: - * Open a new stream to parse gzip-compressed font files. This is - * mainly used to support the compressed `*.pcf.gz' fonts that come - * with XFree86. - * - * @input: - * stream :: - * The target embedding stream. - * - * source :: - * The source stream. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The source stream must be opened _before_ calling this function. - * - * Calling the internal function `FT_Stream_Close' on the new stream will - * *not* call `FT_Stream_Close' on the source stream. None of the stream - * objects will be released to the heap. - * - * The stream implementation is very basic and resets the decompression - * process each time seeking backwards is needed within the stream. - * - * In certain builds of the library, gzip compression recognition is - * automatically handled when calling @FT_New_Face or @FT_Open_Face. - * This means that if no font driver is capable of handling the raw - * compressed file, the library will try to open a gzipped stream from - * it and re-open the face with it. - * - * This function may return `FT_Err_Unimplemented_Feature' if your build - * of FreeType was not compiled with zlib support. - */ - FT_EXPORT( FT_Error ) - FT_Stream_OpenGzip( FT_Stream stream, - FT_Stream source ); - - - /************************************************************************ - * - * @function: - * FT_Gzip_Uncompress - * - * @description: - * Decompress a zipped input buffer into an output buffer. This function - * is modeled after zlib's `uncompress' function. - * - * @input: - * memory :: - * A FreeType memory handle. - * - * input :: - * The input buffer. - * - * input_len :: - * The length of the input buffer. - * - * @output: - * output:: - * The output buffer. - * - * @inout: - * output_len :: - * Before calling the function, this is the the total size of the - * output buffer, which must be large enough to hold the entire - * uncompressed data (so the size of the uncompressed data must be - * known in advance). After calling the function, `output_len' is the - * size of the used data in `output'. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function may return `FT_Err_Unimplemented_Feature' if your build - * of FreeType was not compiled with zlib support. - */ - FT_EXPORT( FT_Error ) - FT_Gzip_Uncompress( FT_Memory memory, - FT_Byte* output, - FT_ULong* output_len, - const FT_Byte* input, - FT_ULong input_len ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTGZIP_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftimage.h b/third_party/freetype/include/freetype/ftimage.h deleted file mode 100644 index 82f284c4f9879fcaa06d93e7569ad35e63ee4e86..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftimage.h +++ /dev/null @@ -1,1214 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftimage.h */ -/* */ -/* FreeType glyph image formats and default raster interface */ -/* (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* Note: A `raster' is simply a scan-line converter, used to render */ - /* FT_Outlines into FT_Bitmaps. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTIMAGE_H__ -#define __FTIMAGE_H__ - - - /* _STANDALONE_ is from ftgrays.c */ -#ifndef _STANDALONE_ -#include <ft2build.h> -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* basic_types */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Pos */ - /* */ - /* <Description> */ - /* The type FT_Pos is used to store vectorial coordinates. Depending */ - /* on the context, these can represent distances in integer font */ - /* units, or 16.16, or 26.6 fixed-point pixel coordinates. */ - /* */ - typedef signed long FT_Pos; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Vector */ - /* */ - /* <Description> */ - /* A simple structure used to store a 2D vector; coordinates are of */ - /* the FT_Pos type. */ - /* */ - /* <Fields> */ - /* x :: The horizontal coordinate. */ - /* y :: The vertical coordinate. */ - /* */ - typedef struct FT_Vector_ - { - FT_Pos x; - FT_Pos y; - - } FT_Vector; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_BBox */ - /* */ - /* <Description> */ - /* A structure used to hold an outline's bounding box, i.e., the */ - /* coordinates of its extrema in the horizontal and vertical */ - /* directions. */ - /* */ - /* <Fields> */ - /* xMin :: The horizontal minimum (left-most). */ - /* */ - /* yMin :: The vertical minimum (bottom-most). */ - /* */ - /* xMax :: The horizontal maximum (right-most). */ - /* */ - /* yMax :: The vertical maximum (top-most). */ - /* */ - /* <Note> */ - /* The bounding box is specified with the coordinates of the lower */ - /* left and the upper right corner. In PostScript, those values are */ - /* often called (llx,lly) and (urx,ury), respectively. */ - /* */ - /* If `yMin' is negative, this value gives the glyph's descender. */ - /* Otherwise, the glyph doesn't descend below the baseline. */ - /* Similarly, if `ymax' is positive, this value gives the glyph's */ - /* ascender. */ - /* */ - /* `xMin' gives the horizontal distance from the glyph's origin to */ - /* the left edge of the glyph's bounding box. If `xMin' is negative, */ - /* the glyph extends to the left of the origin. */ - /* */ - typedef struct FT_BBox_ - { - FT_Pos xMin, yMin; - FT_Pos xMax, yMax; - - } FT_BBox; - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Pixel_Mode */ - /* */ - /* <Description> */ - /* An enumeration type used to describe the format of pixels in a */ - /* given bitmap. Note that additional formats may be added in the */ - /* future. */ - /* */ - /* <Values> */ - /* FT_PIXEL_MODE_NONE :: */ - /* Value~0 is reserved. */ - /* */ - /* FT_PIXEL_MODE_MONO :: */ - /* A monochrome bitmap, using 1~bit per pixel. Note that pixels */ - /* are stored in most-significant order (MSB), which means that */ - /* the left-most pixel in a byte has value 128. */ - /* */ - /* FT_PIXEL_MODE_GRAY :: */ - /* An 8-bit bitmap, generally used to represent anti-aliased glyph */ - /* images. Each pixel is stored in one byte. Note that the number */ - /* of `gray' levels is stored in the `num_grays' field of the */ - /* @FT_Bitmap structure (it generally is 256). */ - /* */ - /* FT_PIXEL_MODE_GRAY2 :: */ - /* A 2-bit per pixel bitmap, used to represent embedded */ - /* anti-aliased bitmaps in font files according to the OpenType */ - /* specification. We haven't found a single font using this */ - /* format, however. */ - /* */ - /* FT_PIXEL_MODE_GRAY4 :: */ - /* A 4-bit per pixel bitmap, representing embedded anti-aliased */ - /* bitmaps in font files according to the OpenType specification. */ - /* We haven't found a single font using this format, however. */ - /* */ - /* FT_PIXEL_MODE_LCD :: */ - /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */ - /* used for display on LCD displays; the bitmap is three times */ - /* wider than the original glyph image. See also */ - /* @FT_RENDER_MODE_LCD. */ - /* */ - /* FT_PIXEL_MODE_LCD_V :: */ - /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */ - /* used for display on rotated LCD displays; the bitmap is three */ - /* times taller than the original glyph image. See also */ - /* @FT_RENDER_MODE_LCD_V. */ - /* */ - /* FT_PIXEL_MODE_BGRA :: */ - /* An image with four 8-bit channels per pixel, representing a */ - /* color image (such as emoticons) with alpha channel. For each */ - /* pixel, the format is BGRA, which means, the blue channel comes */ - /* first in memory. The color channels are pre-multiplied and in */ - /* the sRGB colorspace. For example, full red at half-translucent */ - /* opacity will be represented as `00,00,80,80', not `00,00,FF,80'. */ - /* See also @FT_LOAD_COLOR. */ - /* */ - typedef enum FT_Pixel_Mode_ - { - FT_PIXEL_MODE_NONE = 0, - FT_PIXEL_MODE_MONO, - FT_PIXEL_MODE_GRAY, - FT_PIXEL_MODE_GRAY2, - FT_PIXEL_MODE_GRAY4, - FT_PIXEL_MODE_LCD, - FT_PIXEL_MODE_LCD_V, - FT_PIXEL_MODE_BGRA, - - FT_PIXEL_MODE_MAX /* do not remove */ - - } FT_Pixel_Mode; - - - /* these constants are deprecated; use the corresponding `FT_Pixel_Mode' */ - /* values instead. */ -#define ft_pixel_mode_none FT_PIXEL_MODE_NONE -#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO -#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY -#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 -#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Bitmap */ - /* */ - /* <Description> */ - /* A structure used to describe a bitmap or pixmap to the raster. */ - /* Note that we now manage pixmaps of various depths through the */ - /* `pixel_mode' field. */ - /* */ - /* <Fields> */ - /* rows :: The number of bitmap rows. */ - /* */ - /* width :: The number of pixels in bitmap row. */ - /* */ - /* pitch :: The pitch's absolute value is the number of bytes */ - /* taken by one bitmap row, including padding. */ - /* However, the pitch is positive when the bitmap has */ - /* a `down' flow, and negative when it has an `up' */ - /* flow. In all cases, the pitch is an offset to add */ - /* to a bitmap pointer in order to go down one row. */ - /* */ - /* Note that `padding' means the alignment of a */ - /* bitmap to a byte border, and FreeType functions */ - /* normally align to the smallest possible integer */ - /* value. */ - /* */ - /* For the B/W rasterizer, `pitch' is always an even */ - /* number. */ - /* */ - /* To change the pitch of a bitmap (say, to make it a */ - /* multiple of 4), use @FT_Bitmap_Convert. */ - /* Alternatively, you might use callback functions to */ - /* directly render to the application's surface; see */ - /* the file `example2.cpp' in the tutorial for a */ - /* demonstration. */ - /* */ - /* buffer :: A typeless pointer to the bitmap buffer. This */ - /* value should be aligned on 32-bit boundaries in */ - /* most cases. */ - /* */ - /* num_grays :: This field is only used with */ - /* @FT_PIXEL_MODE_GRAY; it gives the number of gray */ - /* levels used in the bitmap. */ - /* */ - /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */ - /* See @FT_Pixel_Mode for possible values. */ - /* */ - /* palette_mode :: This field is intended for paletted pixel modes; */ - /* it indicates how the palette is stored. Not */ - /* used currently. */ - /* */ - /* palette :: A typeless pointer to the bitmap palette; this */ - /* field is intended for paletted pixel modes. Not */ - /* used currently. */ - /* */ - typedef struct FT_Bitmap_ - { - unsigned int rows; - unsigned int width; - int pitch; - unsigned char* buffer; - unsigned short num_grays; - unsigned char pixel_mode; - unsigned char palette_mode; - void* palette; - - } FT_Bitmap; - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* outline_processing */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Outline */ - /* */ - /* <Description> */ - /* This structure is used to describe an outline to the scan-line */ - /* converter. */ - /* */ - /* <Fields> */ - /* n_contours :: The number of contours in the outline. */ - /* */ - /* n_points :: The number of points in the outline. */ - /* */ - /* points :: A pointer to an array of `n_points' @FT_Vector */ - /* elements, giving the outline's point coordinates. */ - /* */ - /* tags :: A pointer to an array of `n_points' chars, giving */ - /* each outline point's type. */ - /* */ - /* If bit~0 is unset, the point is `off' the curve, */ - /* i.e., a Bézier control point, while it is `on' if */ - /* set. */ - /* */ - /* Bit~1 is meaningful for `off' points only. If set, */ - /* it indicates a third-order Bézier arc control point; */ - /* and a second-order control point if unset. */ - /* */ - /* If bit~2 is set, bits 5-7 contain the drop-out mode */ - /* (as defined in the OpenType specification; the value */ - /* is the same as the argument to the SCANMODE */ - /* instruction). */ - /* */ - /* Bits 3 and~4 are reserved for internal purposes. */ - /* */ - /* contours :: An array of `n_contours' shorts, giving the end */ - /* point of each contour within the outline. For */ - /* example, the first contour is defined by the points */ - /* `0' to `contours[0]', the second one is defined by */ - /* the points `contours[0]+1' to `contours[1]', etc. */ - /* */ - /* flags :: A set of bit flags used to characterize the outline */ - /* and give hints to the scan-converter and hinter on */ - /* how to convert/grid-fit it. See @FT_OUTLINE_XXX. */ - /* */ - /* <Note> */ - /* The B/W rasterizer only checks bit~2 in the `tags' array for the */ - /* first point of each contour. The drop-out mode as given with */ - /* @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and */ - /* @FT_OUTLINE_INCLUDE_STUBS in `flags' is then overridden. */ - /* */ - typedef struct FT_Outline_ - { - short n_contours; /* number of contours in glyph */ - short n_points; /* number of points in the glyph */ - - FT_Vector* points; /* the outline's points */ - char* tags; /* the points flags */ - short* contours; /* the contour end points */ - - int flags; /* outline masks */ - - } FT_Outline; - - /* */ - - /* Following limits must be consistent with */ - /* FT_Outline.{n_contours,n_points} */ -#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX -#define FT_OUTLINE_POINTS_MAX SHRT_MAX - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_OUTLINE_XXX */ - /* */ - /* <Description> */ - /* A list of bit-field constants use for the flags in an outline's */ - /* `flags' field. */ - /* */ - /* <Values> */ - /* FT_OUTLINE_NONE :: */ - /* Value~0 is reserved. */ - /* */ - /* FT_OUTLINE_OWNER :: */ - /* If set, this flag indicates that the outline's field arrays */ - /* (i.e., `points', `flags', and `contours') are `owned' by the */ - /* outline object, and should thus be freed when it is destroyed. */ - /* */ - /* FT_OUTLINE_EVEN_ODD_FILL :: */ - /* By default, outlines are filled using the non-zero winding rule. */ - /* If set to 1, the outline will be filled using the even-odd fill */ - /* rule (only works with the smooth rasterizer). */ - /* */ - /* FT_OUTLINE_REVERSE_FILL :: */ - /* By default, outside contours of an outline are oriented in */ - /* clock-wise direction, as defined in the TrueType specification. */ - /* This flag is set if the outline uses the opposite direction */ - /* (typically for Type~1 fonts). This flag is ignored by the scan */ - /* converter. */ - /* */ - /* FT_OUTLINE_IGNORE_DROPOUTS :: */ - /* By default, the scan converter will try to detect drop-outs in */ - /* an outline and correct the glyph bitmap to ensure consistent */ - /* shape continuity. If set, this flag hints the scan-line */ - /* converter to ignore such cases. See below for more information. */ - /* */ - /* FT_OUTLINE_SMART_DROPOUTS :: */ - /* Select smart dropout control. If unset, use simple dropout */ - /* control. Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See */ - /* below for more information. */ - /* */ - /* FT_OUTLINE_INCLUDE_STUBS :: */ - /* If set, turn pixels on for `stubs', otherwise exclude them. */ - /* Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for */ - /* more information. */ - /* */ - /* FT_OUTLINE_HIGH_PRECISION :: */ - /* This flag indicates that the scan-line converter should try to */ - /* convert this outline to bitmaps with the highest possible */ - /* quality. It is typically set for small character sizes. Note */ - /* that this is only a hint that might be completely ignored by a */ - /* given scan-converter. */ - /* */ - /* FT_OUTLINE_SINGLE_PASS :: */ - /* This flag is set to force a given scan-converter to only use a */ - /* single pass over the outline to render a bitmap glyph image. */ - /* Normally, it is set for very large character sizes. It is only */ - /* a hint that might be completely ignored by a given */ - /* scan-converter. */ - /* */ - /* <Note> */ - /* The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, */ - /* and @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth */ - /* rasterizer. */ - /* */ - /* There exists a second mechanism to pass the drop-out mode to the */ - /* B/W rasterizer; see the `tags' field in @FT_Outline. */ - /* */ - /* Please refer to the description of the `SCANTYPE' instruction in */ - /* the OpenType specification (in file `ttinst1.doc') how simple */ - /* drop-outs, smart drop-outs, and stubs are defined. */ - /* */ -#define FT_OUTLINE_NONE 0x0 -#define FT_OUTLINE_OWNER 0x1 -#define FT_OUTLINE_EVEN_ODD_FILL 0x2 -#define FT_OUTLINE_REVERSE_FILL 0x4 -#define FT_OUTLINE_IGNORE_DROPOUTS 0x8 -#define FT_OUTLINE_SMART_DROPOUTS 0x10 -#define FT_OUTLINE_INCLUDE_STUBS 0x20 - -#define FT_OUTLINE_HIGH_PRECISION 0x100 -#define FT_OUTLINE_SINGLE_PASS 0x200 - - - /* these constants are deprecated; use the corresponding */ - /* `FT_OUTLINE_XXX' values instead */ -#define ft_outline_none FT_OUTLINE_NONE -#define ft_outline_owner FT_OUTLINE_OWNER -#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL -#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL -#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS -#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION -#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS - - /* */ - -#define FT_CURVE_TAG( flag ) ( flag & 3 ) - -#define FT_CURVE_TAG_ON 1 -#define FT_CURVE_TAG_CONIC 0 -#define FT_CURVE_TAG_CUBIC 2 - -#define FT_CURVE_TAG_HAS_SCANMODE 4 - -#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */ -#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */ - -#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \ - FT_CURVE_TAG_TOUCH_Y ) - -#define FT_Curve_Tag_On FT_CURVE_TAG_ON -#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC -#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC -#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X -#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Outline_MoveToFunc */ - /* */ - /* <Description> */ - /* A function pointer type used to describe the signature of a `move */ - /* to' function during outline walking/decomposition. */ - /* */ - /* A `move to' is emitted to start a new contour in an outline. */ - /* */ - /* <Input> */ - /* to :: A pointer to the target point of the `move to'. */ - /* */ - /* user :: A typeless pointer, which is passed from the caller of the */ - /* decomposition function. */ - /* */ - /* <Return> */ - /* Error code. 0~means success. */ - /* */ - typedef int - (*FT_Outline_MoveToFunc)( const FT_Vector* to, - void* user ); - -#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Outline_LineToFunc */ - /* */ - /* <Description> */ - /* A function pointer type used to describe the signature of a `line */ - /* to' function during outline walking/decomposition. */ - /* */ - /* A `line to' is emitted to indicate a segment in the outline. */ - /* */ - /* <Input> */ - /* to :: A pointer to the target point of the `line to'. */ - /* */ - /* user :: A typeless pointer, which is passed from the caller of the */ - /* decomposition function. */ - /* */ - /* <Return> */ - /* Error code. 0~means success. */ - /* */ - typedef int - (*FT_Outline_LineToFunc)( const FT_Vector* to, - void* user ); - -#define FT_Outline_LineTo_Func FT_Outline_LineToFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Outline_ConicToFunc */ - /* */ - /* <Description> */ - /* A function pointer type used to describe the signature of a `conic */ - /* to' function during outline walking or decomposition. */ - /* */ - /* A `conic to' is emitted to indicate a second-order Bézier arc in */ - /* the outline. */ - /* */ - /* <Input> */ - /* control :: An intermediate control point between the last position */ - /* and the new target in `to'. */ - /* */ - /* to :: A pointer to the target end point of the conic arc. */ - /* */ - /* user :: A typeless pointer, which is passed from the caller of */ - /* the decomposition function. */ - /* */ - /* <Return> */ - /* Error code. 0~means success. */ - /* */ - typedef int - (*FT_Outline_ConicToFunc)( const FT_Vector* control, - const FT_Vector* to, - void* user ); - -#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Outline_CubicToFunc */ - /* */ - /* <Description> */ - /* A function pointer type used to describe the signature of a `cubic */ - /* to' function during outline walking or decomposition. */ - /* */ - /* A `cubic to' is emitted to indicate a third-order Bézier arc. */ - /* */ - /* <Input> */ - /* control1 :: A pointer to the first Bézier control point. */ - /* */ - /* control2 :: A pointer to the second Bézier control point. */ - /* */ - /* to :: A pointer to the target end point. */ - /* */ - /* user :: A typeless pointer, which is passed from the caller of */ - /* the decomposition function. */ - /* */ - /* <Return> */ - /* Error code. 0~means success. */ - /* */ - typedef int - (*FT_Outline_CubicToFunc)( const FT_Vector* control1, - const FT_Vector* control2, - const FT_Vector* to, - void* user ); - -#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Outline_Funcs */ - /* */ - /* <Description> */ - /* A structure to hold various function pointers used during outline */ - /* decomposition in order to emit segments, conic, and cubic Béziers. */ - /* */ - /* <Fields> */ - /* move_to :: The `move to' emitter. */ - /* */ - /* line_to :: The segment emitter. */ - /* */ - /* conic_to :: The second-order Bézier arc emitter. */ - /* */ - /* cubic_to :: The third-order Bézier arc emitter. */ - /* */ - /* shift :: The shift that is applied to coordinates before they */ - /* are sent to the emitter. */ - /* */ - /* delta :: The delta that is applied to coordinates before they */ - /* are sent to the emitter, but after the shift. */ - /* */ - /* <Note> */ - /* The point coordinates sent to the emitters are the transformed */ - /* version of the original coordinates (this is important for high */ - /* accuracy during scan-conversion). The transformation is simple: */ - /* */ - /* { */ - /* x' = (x << shift) - delta */ - /* y' = (x << shift) - delta */ - /* } */ - /* */ - /* Set the values of `shift' and `delta' to~0 to get the original */ - /* point coordinates. */ - /* */ - typedef struct FT_Outline_Funcs_ - { - FT_Outline_MoveToFunc move_to; - FT_Outline_LineToFunc line_to; - FT_Outline_ConicToFunc conic_to; - FT_Outline_CubicToFunc cubic_to; - - int shift; - FT_Pos delta; - - } FT_Outline_Funcs; - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* basic_types */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_IMAGE_TAG */ - /* */ - /* <Description> */ - /* This macro converts four-letter tags to an unsigned long type. */ - /* */ - /* <Note> */ - /* Since many 16-bit compilers don't like 32-bit enumerations, you */ - /* should redefine this macro in case of problems to something like */ - /* this: */ - /* */ - /* { */ - /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */ - /* } */ - /* */ - /* to get a simple enumeration without assigning special numbers. */ - /* */ -#ifndef FT_IMAGE_TAG -#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \ - value = ( ( (unsigned long)_x1 << 24 ) | \ - ( (unsigned long)_x2 << 16 ) | \ - ( (unsigned long)_x3 << 8 ) | \ - (unsigned long)_x4 ) -#endif /* FT_IMAGE_TAG */ - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Glyph_Format */ - /* */ - /* <Description> */ - /* An enumeration type used to describe the format of a given glyph */ - /* image. Note that this version of FreeType only supports two image */ - /* formats, even though future font drivers will be able to register */ - /* their own format. */ - /* */ - /* <Values> */ - /* FT_GLYPH_FORMAT_NONE :: */ - /* The value~0 is reserved. */ - /* */ - /* FT_GLYPH_FORMAT_COMPOSITE :: */ - /* The glyph image is a composite of several other images. This */ - /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */ - /* report compound glyphs (like accented characters). */ - /* */ - /* FT_GLYPH_FORMAT_BITMAP :: */ - /* The glyph image is a bitmap, and can be described as an */ - /* @FT_Bitmap. You generally need to access the `bitmap' field of */ - /* the @FT_GlyphSlotRec structure to read it. */ - /* */ - /* FT_GLYPH_FORMAT_OUTLINE :: */ - /* The glyph image is a vectorial outline made of line segments */ - /* and Bézier arcs; it can be described as an @FT_Outline; you */ - /* generally want to access the `outline' field of the */ - /* @FT_GlyphSlotRec structure to read it. */ - /* */ - /* FT_GLYPH_FORMAT_PLOTTER :: */ - /* The glyph image is a vectorial path with no inside and outside */ - /* contours. Some Type~1 fonts, like those in the Hershey family, */ - /* contain glyphs in this format. These are described as */ - /* @FT_Outline, but FreeType isn't currently capable of rendering */ - /* them correctly. */ - /* */ - typedef enum FT_Glyph_Format_ - { - FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ), - - FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ), - FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ), - FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ), - FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ) - - } FT_Glyph_Format; - - - /* these constants are deprecated; use the corresponding */ - /* `FT_Glyph_Format' values instead. */ -#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE -#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE -#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP -#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE -#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** R A S T E R D E F I N I T I O N S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* A raster is a scan converter, in charge of rendering an outline into */ - /* a a bitmap. This section contains the public API for rasters. */ - /* */ - /* Note that in FreeType 2, all rasters are now encapsulated within */ - /* specific modules called `renderers'. See `ftrender.h' for more */ - /* details on renderers. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* raster */ - /* */ - /* <Title> */ - /* Scanline Converter */ - /* */ - /* <Abstract> */ - /* How vectorial outlines are converted into bitmaps and pixmaps. */ - /* */ - /* <Description> */ - /* This section contains technical definitions. */ - /* */ - /* <Order> */ - /* FT_Raster */ - /* FT_Span */ - /* FT_SpanFunc */ - /* */ - /* FT_Raster_Params */ - /* FT_RASTER_FLAG_XXX */ - /* */ - /* FT_Raster_NewFunc */ - /* FT_Raster_DoneFunc */ - /* FT_Raster_ResetFunc */ - /* FT_Raster_SetModeFunc */ - /* FT_Raster_RenderFunc */ - /* FT_Raster_Funcs */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Raster */ - /* */ - /* <Description> */ - /* An opaque handle (pointer) to a raster object. Each object can be */ - /* used independently to convert an outline into a bitmap or pixmap. */ - /* */ - typedef struct FT_RasterRec_* FT_Raster; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Span */ - /* */ - /* <Description> */ - /* A structure used to model a single span of gray pixels when */ - /* rendering an anti-aliased bitmap. */ - /* */ - /* <Fields> */ - /* x :: The span's horizontal start position. */ - /* */ - /* len :: The span's length in pixels. */ - /* */ - /* coverage :: The span color/coverage, ranging from 0 (background) */ - /* to 255 (foreground). */ - /* */ - /* <Note> */ - /* This structure is used by the span drawing callback type named */ - /* @FT_SpanFunc that takes the y~coordinate of the span as a */ - /* parameter. */ - /* */ - /* The coverage value is always between 0 and 255. If you want less */ - /* gray values, the callback function has to reduce them. */ - /* */ - typedef struct FT_Span_ - { - short x; - unsigned short len; - unsigned char coverage; - - } FT_Span; - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_SpanFunc */ - /* */ - /* <Description> */ - /* A function used as a call-back by the anti-aliased renderer in */ - /* order to let client applications draw themselves the gray pixel */ - /* spans on each scan line. */ - /* */ - /* <Input> */ - /* y :: The scanline's y~coordinate. */ - /* */ - /* count :: The number of spans to draw on this scanline. */ - /* */ - /* spans :: A table of `count' spans to draw on the scanline. */ - /* */ - /* user :: User-supplied data that is passed to the callback. */ - /* */ - /* <Note> */ - /* This callback allows client applications to directly render the */ - /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ - /* */ - /* This can be used to write anti-aliased outlines directly to a */ - /* given background bitmap, and even perform translucency. */ - /* */ - /* Note that the `count' field cannot be greater than a fixed value */ - /* defined by the `FT_MAX_GRAY_SPANS' configuration macro in */ - /* `ftoption.h'. By default, this value is set to~32, which means */ - /* that if there are more than 32~spans on a given scanline, the */ - /* callback is called several times with the same `y' parameter in */ - /* order to draw all callbacks. */ - /* */ - /* Otherwise, the callback is only called once per scan-line, and */ - /* only for those scanlines that do have `gray' pixels on them. */ - /* */ - typedef void - (*FT_SpanFunc)( int y, - int count, - const FT_Span* spans, - void* user ); - -#define FT_Raster_Span_Func FT_SpanFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_BitTest_Func */ - /* */ - /* <Description> */ - /* Deprecated, unimplemented. */ - /* */ - typedef int - (*FT_Raster_BitTest_Func)( int y, - int x, - void* user ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_BitSet_Func */ - /* */ - /* <Description> */ - /* Deprecated, unimplemented. */ - /* */ - typedef void - (*FT_Raster_BitSet_Func)( int y, - int x, - void* user ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_RASTER_FLAG_XXX */ - /* */ - /* <Description> */ - /* A list of bit flag constants as used in the `flags' field of a */ - /* @FT_Raster_Params structure. */ - /* */ - /* <Values> */ - /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */ - /* */ - /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */ - /* anti-aliased glyph image should be */ - /* generated. Otherwise, it will be */ - /* monochrome (1-bit). */ - /* */ - /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */ - /* rendering. In this mode, client */ - /* applications must provide their own span */ - /* callback. This lets them directly */ - /* draw or compose over an existing bitmap. */ - /* If this bit is not set, the target */ - /* pixmap's buffer _must_ be zeroed before */ - /* rendering. */ - /* */ - /* Direct rendering is only possible with */ - /* anti-aliased glyphs. */ - /* */ - /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */ - /* rendering mode. If set, the output will */ - /* be clipped to a box specified in the */ - /* `clip_box' field of the */ - /* @FT_Raster_Params structure. */ - /* */ - /* Note that by default, the glyph bitmap */ - /* is clipped to the target pixmap, except */ - /* in direct rendering mode where all spans */ - /* are generated if no clipping box is set. */ - /* */ -#define FT_RASTER_FLAG_DEFAULT 0x0 -#define FT_RASTER_FLAG_AA 0x1 -#define FT_RASTER_FLAG_DIRECT 0x2 -#define FT_RASTER_FLAG_CLIP 0x4 - - /* these constants are deprecated; use the corresponding */ - /* `FT_RASTER_FLAG_XXX' values instead */ -#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT -#define ft_raster_flag_aa FT_RASTER_FLAG_AA -#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT -#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Raster_Params */ - /* */ - /* <Description> */ - /* A structure to hold the arguments used by a raster's render */ - /* function. */ - /* */ - /* <Fields> */ - /* target :: The target bitmap. */ - /* */ - /* source :: A pointer to the source glyph image (e.g., an */ - /* @FT_Outline). */ - /* */ - /* flags :: The rendering flags. */ - /* */ - /* gray_spans :: The gray span drawing callback. */ - /* */ - /* black_spans :: Unused. */ - /* */ - /* bit_test :: Unused. */ - /* */ - /* bit_set :: Unused. */ - /* */ - /* user :: User-supplied data that is passed to each drawing */ - /* callback. */ - /* */ - /* clip_box :: An optional clipping box. It is only used in */ - /* direct rendering mode. Note that coordinates here */ - /* should be expressed in _integer_ pixels (and not in */ - /* 26.6 fixed-point units). */ - /* */ - /* <Note> */ - /* An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA */ - /* bit flag is set in the `flags' field, otherwise a monochrome */ - /* bitmap is generated. */ - /* */ - /* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */ - /* raster will call the `gray_spans' callback to draw gray pixel */ - /* spans. This allows direct composition over a pre-existing bitmap */ - /* through user-provided callbacks to perform the span drawing and */ - /* composition. Not supported by the monochrome rasterizer. */ - /* */ - typedef struct FT_Raster_Params_ - { - const FT_Bitmap* target; - const void* source; - int flags; - FT_SpanFunc gray_spans; - FT_SpanFunc black_spans; /* unused */ - FT_Raster_BitTest_Func bit_test; /* unused */ - FT_Raster_BitSet_Func bit_set; /* unused */ - void* user; - FT_BBox clip_box; - - } FT_Raster_Params; - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_NewFunc */ - /* */ - /* <Description> */ - /* A function used to create a new raster object. */ - /* */ - /* <Input> */ - /* memory :: A handle to the memory allocator. */ - /* */ - /* <Output> */ - /* raster :: A handle to the new raster object. */ - /* */ - /* <Return> */ - /* Error code. 0~means success. */ - /* */ - /* <Note> */ - /* The `memory' parameter is a typeless pointer in order to avoid */ - /* un-wanted dependencies on the rest of the FreeType code. In */ - /* practice, it is an @FT_Memory object, i.e., a handle to the */ - /* standard FreeType memory allocator. However, this field can be */ - /* completely ignored by a given raster implementation. */ - /* */ - typedef int - (*FT_Raster_NewFunc)( void* memory, - FT_Raster* raster ); - -#define FT_Raster_New_Func FT_Raster_NewFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_DoneFunc */ - /* */ - /* <Description> */ - /* A function used to destroy a given raster object. */ - /* */ - /* <Input> */ - /* raster :: A handle to the raster object. */ - /* */ - typedef void - (*FT_Raster_DoneFunc)( FT_Raster raster ); - -#define FT_Raster_Done_Func FT_Raster_DoneFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_ResetFunc */ - /* */ - /* <Description> */ - /* FreeType used to provide an area of memory called the `render */ - /* pool' available to all registered rasters. This was not thread */ - /* safe however and now FreeType never allocates this pool. NULL */ - /* is always passed in as pool_base. */ - /* */ - /* This function is called each time the render pool changes, or just */ - /* after a new raster object is created. */ - /* */ - /* <Input> */ - /* raster :: A handle to the new raster object. */ - /* */ - /* pool_base :: The address in memory of the render pool. */ - /* */ - /* pool_size :: The size in bytes of the render pool. */ - /* */ - /* <Note> */ - /* Rasters should ignore the render pool and rely on dynamic or stack */ - /* allocation if they want to (a handle to the memory allocator is */ - /* passed to the raster constructor). */ - /* */ - typedef void - (*FT_Raster_ResetFunc)( FT_Raster raster, - unsigned char* pool_base, - unsigned long pool_size ); - -#define FT_Raster_Reset_Func FT_Raster_ResetFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_SetModeFunc */ - /* */ - /* <Description> */ - /* This function is a generic facility to change modes or attributes */ - /* in a given raster. This can be used for debugging purposes, or */ - /* simply to allow implementation-specific `features' in a given */ - /* raster module. */ - /* */ - /* <Input> */ - /* raster :: A handle to the new raster object. */ - /* */ - /* mode :: A 4-byte tag used to name the mode or property. */ - /* */ - /* args :: A pointer to the new mode/property to use. */ - /* */ - typedef int - (*FT_Raster_SetModeFunc)( FT_Raster raster, - unsigned long mode, - void* args ); - -#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Raster_RenderFunc */ - /* */ - /* <Description> */ - /* Invoke a given raster to scan-convert a given glyph image into a */ - /* target bitmap. */ - /* */ - /* <Input> */ - /* raster :: A handle to the raster object. */ - /* */ - /* params :: A pointer to an @FT_Raster_Params structure used to */ - /* store the rendering parameters. */ - /* */ - /* <Return> */ - /* Error code. 0~means success. */ - /* */ - /* <Note> */ - /* The exact format of the source image depends on the raster's glyph */ - /* format defined in its @FT_Raster_Funcs structure. It can be an */ - /* @FT_Outline or anything else in order to support a large array of */ - /* glyph formats. */ - /* */ - /* Note also that the render function can fail and return a */ - /* `FT_Err_Unimplemented_Feature' error code if the raster used does */ - /* not support direct composition. */ - /* */ - /* XXX: For now, the standard raster doesn't support direct */ - /* composition but this should change for the final release (see */ - /* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */ - /* for examples of distinct implementations that support direct */ - /* composition). */ - /* */ - typedef int - (*FT_Raster_RenderFunc)( FT_Raster raster, - const FT_Raster_Params* params ); - -#define FT_Raster_Render_Func FT_Raster_RenderFunc - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Raster_Funcs */ - /* */ - /* <Description> */ - /* A structure used to describe a given raster class to the library. */ - /* */ - /* <Fields> */ - /* glyph_format :: The supported glyph format for this raster. */ - /* */ - /* raster_new :: The raster constructor. */ - /* */ - /* raster_reset :: Used to reset the render pool within the raster. */ - /* */ - /* raster_render :: A function to render a glyph into a given bitmap. */ - /* */ - /* raster_done :: The raster destructor. */ - /* */ - typedef struct FT_Raster_Funcs_ - { - FT_Glyph_Format glyph_format; - FT_Raster_NewFunc raster_new; - FT_Raster_ResetFunc raster_reset; - FT_Raster_SetModeFunc raster_set_mode; - FT_Raster_RenderFunc raster_render; - FT_Raster_DoneFunc raster_done; - - } FT_Raster_Funcs; - - /* */ - - -FT_END_HEADER - -#endif /* __FTIMAGE_H__ */ - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/include/freetype/ftincrem.h b/third_party/freetype/include/freetype/ftincrem.h deleted file mode 100644 index 840af25b05981b90a6c9f3d40c58f094a34c7a9a..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftincrem.h +++ /dev/null @@ -1,354 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftincrem.h */ -/* */ -/* FreeType incremental loading (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTINCREM_H__ -#define __FTINCREM_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /*************************************************************************** - * - * @section: - * incremental - * - * @title: - * Incremental Loading - * - * @abstract: - * Custom Glyph Loading. - * - * @description: - * This section contains various functions used to perform so-called - * `incremental' glyph loading. This is a mode where all glyphs loaded - * from a given @FT_Face are provided by the client application. - * - * Apart from that, all other tables are loaded normally from the font - * file. This mode is useful when FreeType is used within another - * engine, e.g., a PostScript Imaging Processor. - * - * To enable this mode, you must use @FT_Open_Face, passing an - * @FT_Parameter with the @FT_PARAM_TAG_INCREMENTAL tag and an - * @FT_Incremental_Interface value. See the comments for - * @FT_Incremental_InterfaceRec for an example. - * - */ - - - /*************************************************************************** - * - * @type: - * FT_Incremental - * - * @description: - * An opaque type describing a user-provided object used to implement - * `incremental' glyph loading within FreeType. This is used to support - * embedded fonts in certain environments (e.g., PostScript interpreters), - * where the glyph data isn't in the font file, or must be overridden by - * different values. - * - * @note: - * It is up to client applications to create and implement @FT_Incremental - * objects, as long as they provide implementations for the methods - * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc - * and @FT_Incremental_GetGlyphMetricsFunc. - * - * See the description of @FT_Incremental_InterfaceRec to understand how - * to use incremental objects with FreeType. - * - */ - typedef struct FT_IncrementalRec_* FT_Incremental; - - - /*************************************************************************** - * - * @struct: - * FT_Incremental_MetricsRec - * - * @description: - * A small structure used to contain the basic glyph metrics returned - * by the @FT_Incremental_GetGlyphMetricsFunc method. - * - * @fields: - * bearing_x :: - * Left bearing, in font units. - * - * bearing_y :: - * Top bearing, in font units. - * - * advance :: - * Horizontal component of glyph advance, in font units. - * - * advance_v :: - * Vertical component of glyph advance, in font units. - * - * @note: - * These correspond to horizontal or vertical metrics depending on the - * value of the `vertical' argument to the function - * @FT_Incremental_GetGlyphMetricsFunc. - * - */ - typedef struct FT_Incremental_MetricsRec_ - { - FT_Long bearing_x; - FT_Long bearing_y; - FT_Long advance; - FT_Long advance_v; /* since 2.3.12 */ - - } FT_Incremental_MetricsRec; - - - /*************************************************************************** - * - * @struct: - * FT_Incremental_Metrics - * - * @description: - * A handle to an @FT_Incremental_MetricsRec structure. - * - */ - typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics; - - - /*************************************************************************** - * - * @type: - * FT_Incremental_GetGlyphDataFunc - * - * @description: - * A function called by FreeType to access a given glyph's data bytes - * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is - * enabled. - * - * Note that the format of the glyph's data bytes depends on the font - * file format. For TrueType, it must correspond to the raw bytes within - * the `glyf' table. For PostScript formats, it must correspond to the - * *unencrypted* charstring bytes, without any `lenIV' header. It is - * undefined for any other format. - * - * @input: - * incremental :: - * Handle to an opaque @FT_Incremental handle provided by the client - * application. - * - * glyph_index :: - * Index of relevant glyph. - * - * @output: - * adata :: - * A structure describing the returned glyph data bytes (which will be - * accessed as a read-only byte block). - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If this function returns successfully the method - * @FT_Incremental_FreeGlyphDataFunc will be called later to release - * the data bytes. - * - * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for - * compound glyphs. - * - */ - typedef FT_Error - (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental, - FT_UInt glyph_index, - FT_Data* adata ); - - - /*************************************************************************** - * - * @type: - * FT_Incremental_FreeGlyphDataFunc - * - * @description: - * A function used to release the glyph data bytes returned by a - * successful call to @FT_Incremental_GetGlyphDataFunc. - * - * @input: - * incremental :: - * A handle to an opaque @FT_Incremental handle provided by the client - * application. - * - * data :: - * A structure describing the glyph data bytes (which will be accessed - * as a read-only byte block). - * - */ - typedef void - (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental, - FT_Data* data ); - - - /*************************************************************************** - * - * @type: - * FT_Incremental_GetGlyphMetricsFunc - * - * @description: - * A function used to retrieve the basic metrics of a given glyph index - * before accessing its data. This is necessary because, in certain - * formats like TrueType, the metrics are stored in a different place from - * the glyph images proper. - * - * @input: - * incremental :: - * A handle to an opaque @FT_Incremental handle provided by the client - * application. - * - * glyph_index :: - * Index of relevant glyph. - * - * vertical :: - * If true, return vertical metrics. - * - * ametrics :: - * This parameter is used for both input and output. - * The original glyph metrics, if any, in font units. If metrics are - * not available all the values must be set to zero. - * - * @output: - * ametrics :: - * The replacement glyph metrics in font units. - * - */ - typedef FT_Error - (*FT_Incremental_GetGlyphMetricsFunc) - ( FT_Incremental incremental, - FT_UInt glyph_index, - FT_Bool vertical, - FT_Incremental_MetricsRec *ametrics ); - - - /************************************************************************** - * - * @struct: - * FT_Incremental_FuncsRec - * - * @description: - * A table of functions for accessing fonts that load data - * incrementally. Used in @FT_Incremental_InterfaceRec. - * - * @fields: - * get_glyph_data :: - * The function to get glyph data. Must not be null. - * - * free_glyph_data :: - * The function to release glyph data. Must not be null. - * - * get_glyph_metrics :: - * The function to get glyph metrics. May be null if the font does - * not provide overriding glyph metrics. - * - */ - typedef struct FT_Incremental_FuncsRec_ - { - FT_Incremental_GetGlyphDataFunc get_glyph_data; - FT_Incremental_FreeGlyphDataFunc free_glyph_data; - FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; - - } FT_Incremental_FuncsRec; - - - /*************************************************************************** - * - * @struct: - * FT_Incremental_InterfaceRec - * - * @description: - * A structure to be used with @FT_Open_Face to indicate that the user - * wants to support incremental glyph loading. You should use it with - * @FT_PARAM_TAG_INCREMENTAL as in the following example: - * - * { - * FT_Incremental_InterfaceRec inc_int; - * FT_Parameter parameter; - * FT_Open_Args open_args; - * - * - * // set up incremental descriptor - * inc_int.funcs = my_funcs; - * inc_int.object = my_object; - * - * // set up optional parameter - * parameter.tag = FT_PARAM_TAG_INCREMENTAL; - * parameter.data = &inc_int; - * - * // set up FT_Open_Args structure - * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; - * open_args.pathname = my_font_pathname; - * open_args.num_params = 1; - * open_args.params = ¶meter; // we use one optional argument - * - * // open the font - * error = FT_Open_Face( library, &open_args, index, &face ); - * ... - * } - * - */ - typedef struct FT_Incremental_InterfaceRec_ - { - const FT_Incremental_FuncsRec* funcs; - FT_Incremental object; - - } FT_Incremental_InterfaceRec; - - - /*************************************************************************** - * - * @type: - * FT_Incremental_Interface - * - * @description: - * A pointer to an @FT_Incremental_InterfaceRec structure. - * - */ - typedef FT_Incremental_InterfaceRec* FT_Incremental_Interface; - - - /*************************************************************************** - * - * @constant: - * FT_PARAM_TAG_INCREMENTAL - * - * @description: - * A constant used as the tag of @FT_Parameter structures to indicate - * an incremental loading object to be used by FreeType. - * - */ -#define FT_PARAM_TAG_INCREMENTAL FT_MAKE_TAG( 'i', 'n', 'c', 'r' ) - - /* */ - - -FT_END_HEADER - -#endif /* __FTINCREM_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftlcdfil.h b/third_party/freetype/include/freetype/ftlcdfil.h deleted file mode 100644 index 4cd999a4b34146cde345db9edfc51fcf44252f17..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftlcdfil.h +++ /dev/null @@ -1,251 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftlcdfil.h */ -/* */ -/* FreeType API for color filtering of subpixel bitmap glyphs */ -/* (specification). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FT_LCD_FILTER_H__ -#define __FT_LCD_FILTER_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /*************************************************************************** - * - * @section: - * lcd_filtering - * - * @title: - * LCD Filtering - * - * @abstract: - * Reduce color fringes of LCD-optimized bitmaps. - * - * @description: - * The @FT_Library_SetLcdFilter API can be used to specify a low-pass - * filter, which is then applied to LCD-optimized bitmaps generated - * through @FT_Render_Glyph. This is useful to reduce color fringes - * that would occur with unfiltered rendering. - * - * Note that no filter is active by default, and that this function is - * *not* implemented in default builds of the library. You need to - * #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file - * in order to activate it. - * - * FreeType generates alpha coverage maps, which are linear by nature. - * For instance, the value 0x80 in bitmap representation means that - * (within numerical precision) 0x80/0xFF fraction of that pixel is - * covered by the glyph's outline. The blending function for placing - * text over a background is - * - * { - * dst = alpha * src + (1 - alpha) * dst , - * } - * - * which is known as OVER. However, when calculating the output of the - * OVER operator, the source colors should first be transformed to a - * linear color space, then alpha blended in that space, and transformed - * back to the output color space. - * - * When linear light blending is used, the default FIR5 filtering - * weights (as given by FT_LCD_FILTER_DEFAULT) are no longer optimal, as - * they have been designed for black on white rendering while lacking - * gamma correction. To preserve color neutrality, weights for a FIR5 - * filter should be chosen according to two free parameters `a' and `c', - * and the FIR weights should be - * - * { - * [a - c, a + c, 2 * a, a + c, a - c] . - * } - * - * This formula generates equal weights for all the color primaries - * across the filter kernel, which makes it colorless. One suggested - * set of weights is - * - * { - * [0x10, 0x50, 0x60, 0x50, 0x10] , - * } - * - * where `a' has value 0x30 and `b' value 0x20. The weights in filter - * may have a sum larger than 0x100, which increases coloration slightly - * but also improves contrast. - */ - - - /**************************************************************************** - * - * @enum: - * FT_LcdFilter - * - * @description: - * A list of values to identify various types of LCD filters. - * - * @values: - * FT_LCD_FILTER_NONE :: - * Do not perform filtering. When used with subpixel rendering, this - * results in sometimes severe color fringes. - * - * FT_LCD_FILTER_DEFAULT :: - * The default filter reduces color fringes considerably, at the cost - * of a slight blurriness in the output. - * - * FT_LCD_FILTER_LIGHT :: - * The light filter is a variant that produces less blurriness at the - * cost of slightly more color fringes than the default one. It might - * be better, depending on taste, your monitor, or your personal vision. - * - * FT_LCD_FILTER_LEGACY :: - * This filter corresponds to the original libXft color filter. It - * provides high contrast output but can exhibit really bad color - * fringes if glyphs are not extremely well hinted to the pixel grid. - * In other words, it only works well if the TrueType bytecode - * interpreter is enabled *and* high-quality hinted fonts are used. - * - * This filter is only provided for comparison purposes, and might be - * disabled or stay unsupported in the future. - * - * @since: - * 2.3.0 - */ - typedef enum FT_LcdFilter_ - { - FT_LCD_FILTER_NONE = 0, - FT_LCD_FILTER_DEFAULT = 1, - FT_LCD_FILTER_LIGHT = 2, - FT_LCD_FILTER_LEGACY = 16, - - FT_LCD_FILTER_MAX /* do not remove */ - - } FT_LcdFilter; - - - /************************************************************************** - * - * @func: - * FT_Library_SetLcdFilter - * - * @description: - * This function is used to apply color filtering to LCD decimated - * bitmaps, like the ones used when calling @FT_Render_Glyph with - * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V. - * - * @input: - * library :: - * A handle to the target library instance. - * - * filter :: - * The filter type. - * - * You can use @FT_LCD_FILTER_NONE here to disable this feature, or - * @FT_LCD_FILTER_DEFAULT to use a default filter that should work - * well on most LCD screens. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This feature is always disabled by default. Clients must make an - * explicit call to this function with a `filter' value other than - * @FT_LCD_FILTER_NONE in order to enable it. - * - * Due to *PATENTS* covering subpixel rendering, this function doesn't - * do anything except returning `FT_Err_Unimplemented_Feature' if the - * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not - * defined in your build of the library, which should correspond to all - * default builds of FreeType. - * - * The filter affects glyph bitmaps rendered through @FT_Render_Glyph, - * @FT_Outline_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char. - * - * It does _not_ affect the output of @FT_Outline_Render and - * @FT_Outline_Get_Bitmap. - * - * If this feature is activated, the dimensions of LCD glyph bitmaps are - * either larger or taller than the dimensions of the corresponding - * outline with regards to the pixel grid. For example, for - * @FT_RENDER_MODE_LCD, the filter adds up to 3~pixels to the left, and - * up to 3~pixels to the right. - * - * The bitmap offset values are adjusted correctly, so clients shouldn't - * need to modify their layout and glyph positioning code when enabling - * the filter. - * - * @since: - * 2.3.0 - */ - FT_EXPORT( FT_Error ) - FT_Library_SetLcdFilter( FT_Library library, - FT_LcdFilter filter ); - - - /************************************************************************** - * - * @func: - * FT_Library_SetLcdFilterWeights - * - * @description: - * Use this function to override the filter weights selected by - * @FT_Library_SetLcdFilter. By default, FreeType uses the quintuple - * (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x10, - * 0x40, 0x70, 0x40, 0x10) for FT_LCD_FILTER_DEFAULT and - * FT_LCD_FILTER_LEGACY. - * - * @input: - * library :: - * A handle to the target library instance. - * - * weights :: - * A pointer to an array; the function copies the first five bytes and - * uses them to specify the filter weights. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * Due to *PATENTS* covering subpixel rendering, this function doesn't - * do anything except returning `FT_Err_Unimplemented_Feature' if the - * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not - * defined in your build of the library, which should correspond to all - * default builds of FreeType. - * - * This function must be called after @FT_Library_SetLcdFilter to have - * any effect. - * - * @since: - * 2.4.0 - */ - FT_EXPORT( FT_Error ) - FT_Library_SetLcdFilterWeights( FT_Library library, - unsigned char *weights ); - - /* */ - - -FT_END_HEADER - -#endif /* __FT_LCD_FILTER_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftlist.h b/third_party/freetype/include/freetype/ftlist.h deleted file mode 100644 index 12b48c78f7059b500d097b4426e22232aaead5e1..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftlist.h +++ /dev/null @@ -1,276 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftlist.h */ -/* */ -/* Generic list support for FreeType (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file implements functions relative to list processing. Its */ - /* data structures are defined in `freetype.h'. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTLIST_H__ -#define __FTLIST_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* list_processing */ - /* */ - /* <Title> */ - /* List Processing */ - /* */ - /* <Abstract> */ - /* Simple management of lists. */ - /* */ - /* <Description> */ - /* This section contains various definitions related to list */ - /* processing using doubly-linked nodes. */ - /* */ - /* <Order> */ - /* FT_List */ - /* FT_ListNode */ - /* FT_ListRec */ - /* FT_ListNodeRec */ - /* */ - /* FT_List_Add */ - /* FT_List_Insert */ - /* FT_List_Find */ - /* FT_List_Remove */ - /* FT_List_Up */ - /* FT_List_Iterate */ - /* FT_List_Iterator */ - /* FT_List_Finalize */ - /* FT_List_Destructor */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Find */ - /* */ - /* <Description> */ - /* Find the list node for a given listed object. */ - /* */ - /* <Input> */ - /* list :: A pointer to the parent list. */ - /* data :: The address of the listed object. */ - /* */ - /* <Return> */ - /* List node. NULL if it wasn't found. */ - /* */ - FT_EXPORT( FT_ListNode ) - FT_List_Find( FT_List list, - void* data ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Add */ - /* */ - /* <Description> */ - /* Append an element to the end of a list. */ - /* */ - /* <InOut> */ - /* list :: A pointer to the parent list. */ - /* node :: The node to append. */ - /* */ - FT_EXPORT( void ) - FT_List_Add( FT_List list, - FT_ListNode node ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Insert */ - /* */ - /* <Description> */ - /* Insert an element at the head of a list. */ - /* */ - /* <InOut> */ - /* list :: A pointer to parent list. */ - /* node :: The node to insert. */ - /* */ - FT_EXPORT( void ) - FT_List_Insert( FT_List list, - FT_ListNode node ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Remove */ - /* */ - /* <Description> */ - /* Remove a node from a list. This function doesn't check whether */ - /* the node is in the list! */ - /* */ - /* <Input> */ - /* node :: The node to remove. */ - /* */ - /* <InOut> */ - /* list :: A pointer to the parent list. */ - /* */ - FT_EXPORT( void ) - FT_List_Remove( FT_List list, - FT_ListNode node ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Up */ - /* */ - /* <Description> */ - /* Move a node to the head/top of a list. Used to maintain LRU */ - /* lists. */ - /* */ - /* <InOut> */ - /* list :: A pointer to the parent list. */ - /* node :: The node to move. */ - /* */ - FT_EXPORT( void ) - FT_List_Up( FT_List list, - FT_ListNode node ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_List_Iterator */ - /* */ - /* <Description> */ - /* An FT_List iterator function that is called during a list parse */ - /* by @FT_List_Iterate. */ - /* */ - /* <Input> */ - /* node :: The current iteration list node. */ - /* */ - /* user :: A typeless pointer passed to @FT_List_Iterate. */ - /* Can be used to point to the iteration's state. */ - /* */ - typedef FT_Error - (*FT_List_Iterator)( FT_ListNode node, - void* user ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Iterate */ - /* */ - /* <Description> */ - /* Parse a list and calls a given iterator function on each element. */ - /* Note that parsing is stopped as soon as one of the iterator calls */ - /* returns a non-zero value. */ - /* */ - /* <Input> */ - /* list :: A handle to the list. */ - /* iterator :: An iterator function, called on each node of the list. */ - /* user :: A user-supplied field that is passed as the second */ - /* argument to the iterator. */ - /* */ - /* <Return> */ - /* The result (a FreeType error code) of the last iterator call. */ - /* */ - FT_EXPORT( FT_Error ) - FT_List_Iterate( FT_List list, - FT_List_Iterator iterator, - void* user ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_List_Destructor */ - /* */ - /* <Description> */ - /* An @FT_List iterator function that is called during a list */ - /* finalization by @FT_List_Finalize to destroy all elements in a */ - /* given list. */ - /* */ - /* <Input> */ - /* system :: The current system object. */ - /* */ - /* data :: The current object to destroy. */ - /* */ - /* user :: A typeless pointer passed to @FT_List_Iterate. It can */ - /* be used to point to the iteration's state. */ - /* */ - typedef void - (*FT_List_Destructor)( FT_Memory memory, - void* data, - void* user ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_List_Finalize */ - /* */ - /* <Description> */ - /* Destroy all elements in the list as well as the list itself. */ - /* */ - /* <Input> */ - /* list :: A handle to the list. */ - /* */ - /* destroy :: A list destructor that will be applied to each element */ - /* of the list. Set this to NULL if not needed. */ - /* */ - /* memory :: The current memory object that handles deallocation. */ - /* */ - /* user :: A user-supplied field that is passed as the last */ - /* argument to the destructor. */ - /* */ - /* <Note> */ - /* This function expects that all nodes added by @FT_List_Add or */ - /* @FT_List_Insert have been dynamically allocated. */ - /* */ - FT_EXPORT( void ) - FT_List_Finalize( FT_List list, - FT_List_Destructor destroy, - FT_Memory memory, - void* user ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTLIST_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftlzw.h b/third_party/freetype/include/freetype/ftlzw.h deleted file mode 100644 index d3ec28e554f9c8864726734d3b8bc6288a5d2d43..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftlzw.h +++ /dev/null @@ -1,99 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftlzw.h */ -/* */ -/* LZW-compressed stream support. */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTLZW_H__ -#define __FTLZW_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /*************************************************************************/ - /* */ - /* <Section> */ - /* lzw */ - /* */ - /* <Title> */ - /* LZW Streams */ - /* */ - /* <Abstract> */ - /* Using LZW-compressed font files. */ - /* */ - /* <Description> */ - /* This section contains the declaration of LZW-specific functions. */ - /* */ - /*************************************************************************/ - - /************************************************************************ - * - * @function: - * FT_Stream_OpenLZW - * - * @description: - * Open a new stream to parse LZW-compressed font files. This is - * mainly used to support the compressed `*.pcf.Z' fonts that come - * with XFree86. - * - * @input: - * stream :: The target embedding stream. - * - * source :: The source stream. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The source stream must be opened _before_ calling this function. - * - * Calling the internal function `FT_Stream_Close' on the new stream will - * *not* call `FT_Stream_Close' on the source stream. None of the stream - * objects will be released to the heap. - * - * The stream implementation is very basic and resets the decompression - * process each time seeking backwards is needed within the stream - * - * In certain builds of the library, LZW compression recognition is - * automatically handled when calling @FT_New_Face or @FT_Open_Face. - * This means that if no font driver is capable of handling the raw - * compressed file, the library will try to open a LZW stream from it - * and re-open the face with it. - * - * This function may return `FT_Err_Unimplemented_Feature' if your build - * of FreeType was not compiled with LZW support. - */ - FT_EXPORT( FT_Error ) - FT_Stream_OpenLZW( FT_Stream stream, - FT_Stream source ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTLZW_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftmac.h b/third_party/freetype/include/freetype/ftmac.h deleted file mode 100644 index 14c55cfe2b7b14703f12ef39087597b2d075767c..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftmac.h +++ /dev/null @@ -1,274 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmac.h */ -/* */ -/* Additional Mac-specific API. */ -/* */ -/* Copyright 1996-2015 by */ -/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -/***************************************************************************/ -/* */ -/* NOTE: Include this file after FT_FREETYPE_H and after any */ -/* Mac-specific headers (because this header uses Mac types such as */ -/* Handle, FSSpec, FSRef, etc.) */ -/* */ -/***************************************************************************/ - - -#ifndef __FTMAC_H__ -#define __FTMAC_H__ - - -#include <ft2build.h> - - -FT_BEGIN_HEADER - - -/* gcc-3.4.1 and later can warn about functions tagged as deprecated */ -#ifndef FT_DEPRECATED_ATTRIBUTE -#if defined(__GNUC__) && \ - ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) -#define FT_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) -#else -#define FT_DEPRECATED_ATTRIBUTE -#endif -#endif - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* mac_specific */ - /* */ - /* <Title> */ - /* Mac Specific Interface */ - /* */ - /* <Abstract> */ - /* Only available on the Macintosh. */ - /* */ - /* <Description> */ - /* The following definitions are only available if FreeType is */ - /* compiled on a Macintosh. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face_From_FOND */ - /* */ - /* <Description> */ - /* Create a new face object from a FOND resource. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library resource. */ - /* */ - /* <Input> */ - /* fond :: A FOND resource. */ - /* */ - /* face_index :: Only supported for the -1 `sanity check' special */ - /* case. */ - /* */ - /* <Output> */ - /* aface :: A handle to a new face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Notes> */ - /* This function can be used to create @FT_Face objects from fonts */ - /* that are installed in the system as follows. */ - /* */ - /* { */ - /* fond = GetResource( 'FOND', fontName ); */ - /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */ - /* } */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Face_From_FOND( FT_Library library, - Handle fond, - FT_Long face_index, - FT_Face *aface ) - FT_DEPRECATED_ATTRIBUTE; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_GetFile_From_Mac_Name */ - /* */ - /* <Description> */ - /* Return an FSSpec for the disk file containing the named font. */ - /* */ - /* <Input> */ - /* fontName :: Mac OS name of the font (e.g., Times New Roman */ - /* Bold). */ - /* */ - /* <Output> */ - /* pathSpec :: FSSpec to the file. For passing to */ - /* @FT_New_Face_From_FSSpec. */ - /* */ - /* face_index :: Index of the face. For passing to */ - /* @FT_New_Face_From_FSSpec. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_GetFile_From_Mac_Name( const char* fontName, - FSSpec* pathSpec, - FT_Long* face_index ) - FT_DEPRECATED_ATTRIBUTE; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_GetFile_From_Mac_ATS_Name */ - /* */ - /* <Description> */ - /* Return an FSSpec for the disk file containing the named font. */ - /* */ - /* <Input> */ - /* fontName :: Mac OS name of the font in ATS framework. */ - /* */ - /* <Output> */ - /* pathSpec :: FSSpec to the file. For passing to */ - /* @FT_New_Face_From_FSSpec. */ - /* */ - /* face_index :: Index of the face. For passing to */ - /* @FT_New_Face_From_FSSpec. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_GetFile_From_Mac_ATS_Name( const char* fontName, - FSSpec* pathSpec, - FT_Long* face_index ) - FT_DEPRECATED_ATTRIBUTE; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_GetFilePath_From_Mac_ATS_Name */ - /* */ - /* <Description> */ - /* Return a pathname of the disk file and face index for given font */ - /* name that is handled by ATS framework. */ - /* */ - /* <Input> */ - /* fontName :: Mac OS name of the font in ATS framework. */ - /* */ - /* <Output> */ - /* path :: Buffer to store pathname of the file. For passing */ - /* to @FT_New_Face. The client must allocate this */ - /* buffer before calling this function. */ - /* */ - /* maxPathSize :: Lengths of the buffer `path' that client allocated. */ - /* */ - /* face_index :: Index of the face. For passing to @FT_New_Face. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_GetFilePath_From_Mac_ATS_Name( const char* fontName, - UInt8* path, - UInt32 maxPathSize, - FT_Long* face_index ) - FT_DEPRECATED_ATTRIBUTE; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face_From_FSSpec */ - /* */ - /* <Description> */ - /* Create a new face object from a given resource and typeface index */ - /* using an FSSpec to the font file. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library resource. */ - /* */ - /* <Input> */ - /* spec :: FSSpec to the font file. */ - /* */ - /* face_index :: The index of the face within the resource. The */ - /* first face has index~0. */ - /* <Output> */ - /* aface :: A handle to a new face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */ - /* it accepts an FSSpec instead of a path. */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Face_From_FSSpec( FT_Library library, - const FSSpec *spec, - FT_Long face_index, - FT_Face *aface ) - FT_DEPRECATED_ATTRIBUTE; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face_From_FSRef */ - /* */ - /* <Description> */ - /* Create a new face object from a given resource and typeface index */ - /* using an FSRef to the font file. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library resource. */ - /* */ - /* <Input> */ - /* spec :: FSRef to the font file. */ - /* */ - /* face_index :: The index of the face within the resource. The */ - /* first face has index~0. */ - /* <Output> */ - /* aface :: A handle to a new face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* @FT_New_Face_From_FSRef is identical to @FT_New_Face except */ - /* it accepts an FSRef instead of a path. */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Face_From_FSRef( FT_Library library, - const FSRef *ref, - FT_Long face_index, - FT_Face *aface ) - FT_DEPRECATED_ATTRIBUTE; - - /* */ - - -FT_END_HEADER - - -#endif /* __FTMAC_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftmm.h b/third_party/freetype/include/freetype/ftmm.h deleted file mode 100644 index 6ef47987e6d00da218ec8e88ae0f7bc56a038c3a..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftmm.h +++ /dev/null @@ -1,379 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmm.h */ -/* */ -/* FreeType Multiple Master font interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTMM_H__ -#define __FTMM_H__ - - -#include <ft2build.h> -#include FT_TYPE1_TABLES_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* multiple_masters */ - /* */ - /* <Title> */ - /* Multiple Masters */ - /* */ - /* <Abstract> */ - /* How to manage Multiple Masters fonts. */ - /* */ - /* <Description> */ - /* The following types and functions are used to manage Multiple */ - /* Master fonts, i.e., the selection of specific design instances by */ - /* setting design axis coordinates. */ - /* */ - /* George Williams has extended this interface to make it work with */ - /* both Type~1 Multiple Masters fonts and GX distortable (var) */ - /* fonts. Some of these routines only work with MM fonts, others */ - /* will work with both types. They are similar enough that a */ - /* consistent interface makes sense. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_MM_Axis */ - /* */ - /* <Description> */ - /* A simple structure used to model a given axis in design space for */ - /* Multiple Masters fonts. */ - /* */ - /* This structure can't be used for GX var fonts. */ - /* */ - /* <Fields> */ - /* name :: The axis's name. */ - /* */ - /* minimum :: The axis's minimum design coordinate. */ - /* */ - /* maximum :: The axis's maximum design coordinate. */ - /* */ - typedef struct FT_MM_Axis_ - { - FT_String* name; - FT_Long minimum; - FT_Long maximum; - - } FT_MM_Axis; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Multi_Master */ - /* */ - /* <Description> */ - /* A structure used to model the axes and space of a Multiple Masters */ - /* font. */ - /* */ - /* This structure can't be used for GX var fonts. */ - /* */ - /* <Fields> */ - /* num_axis :: Number of axes. Cannot exceed~4. */ - /* */ - /* num_designs :: Number of designs; should be normally 2^num_axis */ - /* even though the Type~1 specification strangely */ - /* allows for intermediate designs to be present. */ - /* This number cannot exceed~16. */ - /* */ - /* axis :: A table of axis descriptors. */ - /* */ - typedef struct FT_Multi_Master_ - { - FT_UInt num_axis; - FT_UInt num_designs; - FT_MM_Axis axis[T1_MAX_MM_AXIS]; - - } FT_Multi_Master; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Var_Axis */ - /* */ - /* <Description> */ - /* A simple structure used to model a given axis in design space for */ - /* Multiple Masters and GX var fonts. */ - /* */ - /* <Fields> */ - /* name :: The axis's name. */ - /* Not always meaningful for GX. */ - /* */ - /* minimum :: The axis's minimum design coordinate. */ - /* */ - /* def :: The axis's default design coordinate. */ - /* FreeType computes meaningful default values for MM; it */ - /* is then an integer value, not in 16.16 format. */ - /* */ - /* maximum :: The axis's maximum design coordinate. */ - /* */ - /* tag :: The axis's tag (the GX equivalent to `name'). */ - /* FreeType provides default values for MM if possible. */ - /* */ - /* strid :: The entry in `name' table (another GX version of */ - /* `name'). */ - /* Not meaningful for MM. */ - /* */ - typedef struct FT_Var_Axis_ - { - FT_String* name; - - FT_Fixed minimum; - FT_Fixed def; - FT_Fixed maximum; - - FT_ULong tag; - FT_UInt strid; - - } FT_Var_Axis; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Var_Named_Style */ - /* */ - /* <Description> */ - /* A simple structure used to model a named style in a GX var font. */ - /* */ - /* This structure can't be used for MM fonts. */ - /* */ - /* <Fields> */ - /* coords :: The design coordinates for this style. */ - /* This is an array with one entry for each axis. */ - /* */ - /* strid :: The entry in `name' table identifying this style. */ - /* */ - typedef struct FT_Var_Named_Style_ - { - FT_Fixed* coords; - FT_UInt strid; - - } FT_Var_Named_Style; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_MM_Var */ - /* */ - /* <Description> */ - /* A structure used to model the axes and space of a Multiple Masters */ - /* or GX var distortable font. */ - /* */ - /* Some fields are specific to one format and not to the other. */ - /* */ - /* <Fields> */ - /* num_axis :: The number of axes. The maximum value is~4 for */ - /* MM; no limit in GX. */ - /* */ - /* num_designs :: The number of designs; should be normally */ - /* 2^num_axis for MM fonts. Not meaningful for GX */ - /* (where every glyph could have a different */ - /* number of designs). */ - /* */ - /* num_namedstyles :: The number of named styles; only meaningful for */ - /* GX that allows certain design coordinates to */ - /* have a string ID (in the `name' table) */ - /* associated with them. The font can tell the */ - /* user that, for example, Weight=1.5 is `Bold'. */ - /* */ - /* axis :: An axis descriptor table. */ - /* GX fonts contain slightly more data than MM. */ - /* */ - /* namedstyle :: A named style table. */ - /* Only meaningful with GX. */ - /* */ - typedef struct FT_MM_Var_ - { - FT_UInt num_axis; - FT_UInt num_designs; - FT_UInt num_namedstyles; - FT_Var_Axis* axis; - FT_Var_Named_Style* namedstyle; - - } FT_MM_Var; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Multi_Master */ - /* */ - /* <Description> */ - /* Retrieve the Multiple Master descriptor of a given font. */ - /* */ - /* This function can't be used with GX fonts. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face. */ - /* */ - /* <Output> */ - /* amaster :: The Multiple Masters descriptor. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Multi_Master( FT_Face face, - FT_Multi_Master *amaster ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_MM_Var */ - /* */ - /* <Description> */ - /* Retrieve the Multiple Master/GX var descriptor of a given font. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face. */ - /* */ - /* <Output> */ - /* amaster :: The Multiple Masters/GX var descriptor. */ - /* Allocates a data structure, which the user must free. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_MM_Var( FT_Face face, - FT_MM_Var* *amaster ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_MM_Design_Coordinates */ - /* */ - /* <Description> */ - /* For Multiple Masters fonts, choose an interpolated font design */ - /* through design coordinates. */ - /* */ - /* This function can't be used with GX fonts. */ - /* */ - /* <InOut> */ - /* face :: A handle to the source face. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available design coordinates. If it */ - /* is larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use default values for the remaining axes. */ - /* */ - /* coords :: An array of design coordinates. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_MM_Design_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Var_Design_Coordinates */ - /* */ - /* <Description> */ - /* For Multiple Master or GX Var fonts, choose an interpolated font */ - /* design through design coordinates. */ - /* */ - /* <InOut> */ - /* face :: A handle to the source face. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available design coordinates. If it */ - /* is larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use default values for the remaining axes. */ - /* */ - /* coords :: An array of design coordinates. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_Var_Design_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_MM_Blend_Coordinates */ - /* */ - /* <Description> */ - /* For Multiple Masters and GX var fonts, choose an interpolated font */ - /* design through normalized blend coordinates. */ - /* */ - /* <InOut> */ - /* face :: A handle to the source face. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available design coordinates. If it */ - /* is larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use default values for the remaining axes. */ - /* */ - /* coords :: The design coordinates array (each element must be */ - /* between 0 and 1.0). */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_MM_Blend_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Var_Blend_Coordinates */ - /* */ - /* <Description> */ - /* This is another name of @FT_Set_MM_Blend_Coordinates. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_Var_Blend_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTMM_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftmodapi.h b/third_party/freetype/include/freetype/ftmodapi.h deleted file mode 100644 index 544279a68afc2d0d120d75015db59baa95853e4c..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftmodapi.h +++ /dev/null @@ -1,669 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmodapi.h */ -/* */ -/* FreeType modules public interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTMODAPI_H__ -#define __FTMODAPI_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* module_management */ - /* */ - /* <Title> */ - /* Module Management */ - /* */ - /* <Abstract> */ - /* How to add, upgrade, remove, and control modules from FreeType. */ - /* */ - /* <Description> */ - /* The definitions below are used to manage modules within FreeType. */ - /* Modules can be added, upgraded, and removed at runtime. */ - /* Additionally, some module properties can be controlled also. */ - /* */ - /* Here is a list of possible values of the `module_name' field in */ - /* the @FT_Module_Class structure. */ - /* */ - /* { */ - /* autofitter */ - /* bdf */ - /* cff */ - /* gxvalid */ - /* otvalid */ - /* pcf */ - /* pfr */ - /* psaux */ - /* pshinter */ - /* psnames */ - /* raster1 */ - /* sfnt */ - /* smooth, smooth-lcd, smooth-lcdv */ - /* truetype */ - /* type1 */ - /* type42 */ - /* t1cid */ - /* winfonts */ - /* } */ - /* */ - /* Note that the FreeType Cache sub-system is not a FreeType module. */ - /* */ - /* <Order> */ - /* FT_Module */ - /* FT_Module_Constructor */ - /* FT_Module_Destructor */ - /* FT_Module_Requester */ - /* FT_Module_Class */ - /* */ - /* FT_Add_Module */ - /* FT_Get_Module */ - /* FT_Remove_Module */ - /* FT_Add_Default_Modules */ - /* */ - /* FT_Property_Set */ - /* FT_Property_Get */ - /* */ - /* FT_New_Library */ - /* FT_Done_Library */ - /* FT_Reference_Library */ - /* */ - /* FT_Renderer */ - /* FT_Renderer_Class */ - /* */ - /* FT_Get_Renderer */ - /* FT_Set_Renderer */ - /* */ - /* FT_Set_Debug_Hook */ - /* */ - /*************************************************************************/ - - - /* module bit flags */ -#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */ -#define FT_MODULE_RENDERER 2 /* this module is a renderer */ -#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */ -#define FT_MODULE_STYLER 8 /* this module is a styler */ - -#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */ - /* scalable fonts */ -#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */ - /* support vector outlines */ -#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */ - /* own hinter */ - - - /* deprecated values */ -#define ft_module_font_driver FT_MODULE_FONT_DRIVER -#define ft_module_renderer FT_MODULE_RENDERER -#define ft_module_hinter FT_MODULE_HINTER -#define ft_module_styler FT_MODULE_STYLER - -#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE -#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES -#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER - - - typedef FT_Pointer FT_Module_Interface; - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Module_Constructor */ - /* */ - /* <Description> */ - /* A function used to initialize (not create) a new module object. */ - /* */ - /* <Input> */ - /* module :: The module to initialize. */ - /* */ - typedef FT_Error - (*FT_Module_Constructor)( FT_Module module ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Module_Destructor */ - /* */ - /* <Description> */ - /* A function used to finalize (not destroy) a given module object. */ - /* */ - /* <Input> */ - /* module :: The module to finalize. */ - /* */ - typedef void - (*FT_Module_Destructor)( FT_Module module ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Module_Requester */ - /* */ - /* <Description> */ - /* A function used to query a given module for a specific interface. */ - /* */ - /* <Input> */ - /* module :: The module to be searched. */ - /* */ - /* name :: The name of the interface in the module. */ - /* */ - typedef FT_Module_Interface - (*FT_Module_Requester)( FT_Module module, - const char* name ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Module_Class */ - /* */ - /* <Description> */ - /* The module class descriptor. */ - /* */ - /* <Fields> */ - /* module_flags :: Bit flags describing the module. */ - /* */ - /* module_size :: The size of one module object/instance in */ - /* bytes. */ - /* */ - /* module_name :: The name of the module. */ - /* */ - /* module_version :: The version, as a 16.16 fixed number */ - /* (major.minor). */ - /* */ - /* module_requires :: The version of FreeType this module requires, */ - /* as a 16.16 fixed number (major.minor). Starts */ - /* at version 2.0, i.e., 0x20000. */ - /* */ - /* module_init :: The initializing function. */ - /* */ - /* module_done :: The finalizing function. */ - /* */ - /* get_interface :: The interface requesting function. */ - /* */ - typedef struct FT_Module_Class_ - { - FT_ULong module_flags; - FT_Long module_size; - const FT_String* module_name; - FT_Fixed module_version; - FT_Fixed module_requires; - - const void* module_interface; - - FT_Module_Constructor module_init; - FT_Module_Destructor module_done; - FT_Module_Requester get_interface; - - } FT_Module_Class; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Add_Module */ - /* */ - /* <Description> */ - /* Add a new module to a given library instance. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library object. */ - /* */ - /* <Input> */ - /* clazz :: A pointer to class descriptor for the module. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* An error will be returned if a module already exists by that name, */ - /* or if the module requires a version of FreeType that is too great. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Add_Module( FT_Library library, - const FT_Module_Class* clazz ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Module */ - /* */ - /* <Description> */ - /* Find a module by its name. */ - /* */ - /* <Input> */ - /* library :: A handle to the library object. */ - /* */ - /* module_name :: The module's name (as an ASCII string). */ - /* */ - /* <Return> */ - /* A module handle. 0~if none was found. */ - /* */ - /* <Note> */ - /* FreeType's internal modules aren't documented very well, and you */ - /* should look up the source code for details. */ - /* */ - FT_EXPORT( FT_Module ) - FT_Get_Module( FT_Library library, - const char* module_name ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Remove_Module */ - /* */ - /* <Description> */ - /* Remove a given module from a library instance. */ - /* */ - /* <InOut> */ - /* library :: A handle to a library object. */ - /* */ - /* <Input> */ - /* module :: A handle to a module object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The module object is destroyed by the function in case of success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Remove_Module( FT_Library library, - FT_Module module ); - - - /********************************************************************** - * - * @function: - * FT_Property_Set - * - * @description: - * Set a property for a given module. - * - * @input: - * library :: - * A handle to the library the module is part of. - * - * module_name :: - * The module name. - * - * property_name :: - * The property name. Properties are described in the `Synopsis' - * subsection of the module's documentation. - * - * Note that only a few modules have properties. - * - * value :: - * A generic pointer to a variable or structure that gives the new - * value of the property. The exact definition of `value' is - * dependent on the property; see the `Synopsis' subsection of the - * module's documentation. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If `module_name' isn't a valid module name, or `property_name' - * doesn't specify a valid property, or if `value' doesn't represent a - * valid value for the given property, an error is returned. - * - * The following example sets property `bar' (a simple integer) in - * module `foo' to value~1. - * - * { - * FT_UInt bar; - * - * - * bar = 1; - * FT_Property_Set( library, "foo", "bar", &bar ); - * } - * - * Note that the FreeType Cache sub-system doesn't recognize module - * property changes. To avoid glyph lookup confusion within the cache - * you should call @FTC_Manager_Reset to completely flush the cache if - * a module property gets changed after @FTC_Manager_New has been - * called. - * - * It is not possible to set properties of the FreeType Cache - * sub-system itself with FT_Property_Set; use @FTC_Property_Set - * instead. - * - * @since: - * 2.4.11 - * - */ - FT_EXPORT( FT_Error ) - FT_Property_Set( FT_Library library, - const FT_String* module_name, - const FT_String* property_name, - const void* value ); - - - /********************************************************************** - * - * @function: - * FT_Property_Get - * - * @description: - * Get a module's property value. - * - * @input: - * library :: - * A handle to the library the module is part of. - * - * module_name :: - * The module name. - * - * property_name :: - * The property name. Properties are described in the `Synopsis' - * subsection of the module's documentation. - * - * @inout: - * value :: - * A generic pointer to a variable or structure that gives the - * value of the property. The exact definition of `value' is - * dependent on the property; see the `Synopsis' subsection of the - * module's documentation. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If `module_name' isn't a valid module name, or `property_name' - * doesn't specify a valid property, or if `value' doesn't represent a - * valid value for the given property, an error is returned. - * - * The following example gets property `baz' (a range) in module `foo'. - * - * { - * typedef range_ - * { - * FT_Int32 min; - * FT_Int32 max; - * - * } range; - * - * range baz; - * - * - * FT_Property_Get( library, "foo", "baz", &baz ); - * } - * - * It is not possible to retrieve properties of the FreeType Cache - * sub-system with FT_Property_Get; use @FTC_Property_Get instead. - * - * @since: - * 2.4.11 - * - */ - FT_EXPORT( FT_Error ) - FT_Property_Get( FT_Library library, - const FT_String* module_name, - const FT_String* property_name, - void* value ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Reference_Library */ - /* */ - /* <Description> */ - /* A counter gets initialized to~1 at the time an @FT_Library */ - /* structure is created. This function increments the counter. */ - /* @FT_Done_Library then only destroys a library if the counter is~1, */ - /* otherwise it simply decrements the counter. */ - /* */ - /* This function helps in managing life-cycles of structures that */ - /* reference @FT_Library objects. */ - /* */ - /* <Input> */ - /* library :: A handle to a target library object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Since> */ - /* 2.4.2 */ - /* */ - FT_EXPORT( FT_Error ) - FT_Reference_Library( FT_Library library ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Library */ - /* */ - /* <Description> */ - /* This function is used to create a new FreeType library instance */ - /* from a given memory object. It is thus possible to use libraries */ - /* with distinct memory allocators within the same program. Note, */ - /* however, that the used @FT_Memory structure is expected to remain */ - /* valid for the life of the @FT_Library object. */ - /* */ - /* Normally, you would call this function (followed by a call to */ - /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module) */ - /* instead of @FT_Init_FreeType to initialize the FreeType library. */ - /* */ - /* Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a */ - /* library instance. */ - /* */ - /* <Input> */ - /* memory :: A handle to the original memory object. */ - /* */ - /* <Output> */ - /* alibrary :: A pointer to handle of a new library object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* See the discussion of reference counters in the description of */ - /* @FT_Reference_Library. */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Library( FT_Memory memory, - FT_Library *alibrary ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_Library */ - /* */ - /* <Description> */ - /* Discard a given library object. This closes all drivers and */ - /* discards all resource objects. */ - /* */ - /* <Input> */ - /* library :: A handle to the target library. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* See the discussion of reference counters in the description of */ - /* @FT_Reference_Library. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Done_Library( FT_Library library ); - - /* */ - - typedef void - (*FT_DebugHook_Func)( void* arg ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Debug_Hook */ - /* */ - /* <Description> */ - /* Set a debug hook function for debugging the interpreter of a font */ - /* format. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library object. */ - /* */ - /* <Input> */ - /* hook_index :: The index of the debug hook. You should use the */ - /* values defined in `ftobjs.h', e.g., */ - /* `FT_DEBUG_HOOK_TRUETYPE'. */ - /* */ - /* debug_hook :: The function used to debug the interpreter. */ - /* */ - /* <Note> */ - /* Currently, four debug hook slots are available, but only two (for */ - /* the TrueType and the Type~1 interpreter) are defined. */ - /* */ - /* Since the internal headers of FreeType are no longer installed, */ - /* the symbol `FT_DEBUG_HOOK_TRUETYPE' isn't available publicly. */ - /* This is a bug and will be fixed in a forthcoming release. */ - /* */ - FT_EXPORT( void ) - FT_Set_Debug_Hook( FT_Library library, - FT_UInt hook_index, - FT_DebugHook_Func debug_hook ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Add_Default_Modules */ - /* */ - /* <Description> */ - /* Add the set of default drivers to a given library object. */ - /* This is only useful when you create a library object with */ - /* @FT_New_Library (usually to plug a custom memory manager). */ - /* */ - /* <InOut> */ - /* library :: A handle to a new library object. */ - /* */ - FT_EXPORT( void ) - FT_Add_Default_Modules( FT_Library library ); - - - - /************************************************************************** - * - * @section: - * truetype_engine - * - * @title: - * The TrueType Engine - * - * @abstract: - * TrueType bytecode support. - * - * @description: - * This section contains a function used to query the level of TrueType - * bytecode support compiled in this version of the library. - * - */ - - - /************************************************************************** - * - * @enum: - * FT_TrueTypeEngineType - * - * @description: - * A list of values describing which kind of TrueType bytecode - * engine is implemented in a given FT_Library instance. It is used - * by the @FT_Get_TrueType_Engine_Type function. - * - * @values: - * FT_TRUETYPE_ENGINE_TYPE_NONE :: - * The library doesn't implement any kind of bytecode interpreter. - * - * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED :: - * The library implements a bytecode interpreter that doesn't - * support the patented operations of the TrueType virtual machine. - * - * Its main use is to load certain Asian fonts that position and - * scale glyph components with bytecode instructions. It produces - * bad output for most other fonts. - * - * FT_TRUETYPE_ENGINE_TYPE_PATENTED :: - * The library implements a bytecode interpreter that covers - * the full instruction set of the TrueType virtual machine (this - * was governed by patents until May 2010, hence the name). - * - * @since: - * 2.2 - * - */ - typedef enum FT_TrueTypeEngineType_ - { - FT_TRUETYPE_ENGINE_TYPE_NONE = 0, - FT_TRUETYPE_ENGINE_TYPE_UNPATENTED, - FT_TRUETYPE_ENGINE_TYPE_PATENTED - - } FT_TrueTypeEngineType; - - - /************************************************************************** - * - * @func: - * FT_Get_TrueType_Engine_Type - * - * @description: - * Return an @FT_TrueTypeEngineType value to indicate which level of - * the TrueType virtual machine a given library instance supports. - * - * @input: - * library :: - * A library instance. - * - * @return: - * A value indicating which level is supported. - * - * @since: - * 2.2 - * - */ - FT_EXPORT( FT_TrueTypeEngineType ) - FT_Get_TrueType_Engine_Type( FT_Library library ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTMODAPI_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftmoderr.h b/third_party/freetype/include/freetype/ftmoderr.h deleted file mode 100644 index 9d7f9814091faecb7dfff470c04cc7af98b512ca..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftmoderr.h +++ /dev/null @@ -1,194 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmoderr.h */ -/* */ -/* FreeType module error offsets (specification). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the FreeType module error codes. */ - /* */ - /* If the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in `ftoption.h' is */ - /* set, the lower byte of an error value identifies the error code as */ - /* usual. In addition, the higher byte identifies the module. For */ - /* example, the error `FT_Err_Invalid_File_Format' has value 0x0003, the */ - /* error `TT_Err_Invalid_File_Format' has value 0x1303, the error */ - /* `T1_Err_Invalid_File_Format' has value 0x1403, etc. */ - /* */ - /* Note that `FT_Err_Ok', `TT_Err_Ok', etc. are always equal to zero, */ - /* including the high byte. */ - /* */ - /* If FT_CONFIG_OPTION_USE_MODULE_ERRORS isn't set, the higher byte of */ - /* an error value is set to zero. */ - /* */ - /* To hide the various `XXX_Err_' prefixes in the source code, FreeType */ - /* provides some macros in `fttypes.h'. */ - /* */ - /* FT_ERR( err ) */ - /* Add current error module prefix (as defined with the */ - /* `FT_ERR_PREFIX' macro) to `err'. For example, in the BDF module */ - /* the line */ - /* */ - /* error = FT_ERR( Invalid_Outline ); */ - /* */ - /* expands to */ - /* */ - /* error = BDF_Err_Invalid_Outline; */ - /* */ - /* For simplicity, you can always use `FT_Err_Ok' directly instead */ - /* of `FT_ERR( Ok )'. */ - /* */ - /* FT_ERR_EQ( errcode, err ) */ - /* FT_ERR_NEQ( errcode, err ) */ - /* Compare error code `errcode' with the error `err' for equality */ - /* and inequality, respectively. Example: */ - /* */ - /* if ( FT_ERR_EQ( error, Invalid_Outline ) ) */ - /* ... */ - /* */ - /* Using this macro you don't have to think about error prefixes. */ - /* Of course, if module errors are not active, the above example is */ - /* the same as */ - /* */ - /* if ( error == FT_Err_Invalid_Outline ) */ - /* ... */ - /* */ - /* FT_ERROR_BASE( errcode ) */ - /* FT_ERROR_MODULE( errcode ) */ - /* Get base error and module error code, respectively. */ - /* */ - /* */ - /* It can also be used to create a module error message table easily */ - /* with something like */ - /* */ - /* { */ - /* #undef __FTMODERR_H__ */ - /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */ - /* #define FT_MODERR_START_LIST { */ - /* #define FT_MODERR_END_LIST { 0, 0 } }; */ - /* */ - /* const struct */ - /* { */ - /* int mod_err_offset; */ - /* const char* mod_err_msg */ - /* } ft_mod_errors[] = */ - /* */ - /* #include FT_MODULE_ERRORS_H */ - /* } */ - /* */ - /*************************************************************************/ - - -#ifndef __FTMODERR_H__ -#define __FTMODERR_H__ - - - /*******************************************************************/ - /*******************************************************************/ - /***** *****/ - /***** SETUP MACROS *****/ - /***** *****/ - /*******************************************************************/ - /*******************************************************************/ - - -#undef FT_NEED_EXTERN_C - -#ifndef FT_MODERRDEF - -#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS -#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v, -#else -#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0, -#endif - -#define FT_MODERR_START_LIST enum { -#define FT_MODERR_END_LIST FT_Mod_Err_Max }; - -#ifdef __cplusplus -#define FT_NEED_EXTERN_C - extern "C" { -#endif - -#endif /* !FT_MODERRDEF */ - - - /*******************************************************************/ - /*******************************************************************/ - /***** *****/ - /***** LIST MODULE ERROR BASES *****/ - /***** *****/ - /*******************************************************************/ - /*******************************************************************/ - - -#ifdef FT_MODERR_START_LIST - FT_MODERR_START_LIST -#endif - - - FT_MODERRDEF( Base, 0x000, "base module" ) - FT_MODERRDEF( Autofit, 0x100, "autofitter module" ) - FT_MODERRDEF( BDF, 0x200, "BDF module" ) - FT_MODERRDEF( Bzip2, 0x300, "Bzip2 module" ) - FT_MODERRDEF( Cache, 0x400, "cache module" ) - FT_MODERRDEF( CFF, 0x500, "CFF module" ) - FT_MODERRDEF( CID, 0x600, "CID module" ) - FT_MODERRDEF( Gzip, 0x700, "Gzip module" ) - FT_MODERRDEF( LZW, 0x800, "LZW module" ) - FT_MODERRDEF( OTvalid, 0x900, "OpenType validation module" ) - FT_MODERRDEF( PCF, 0xA00, "PCF module" ) - FT_MODERRDEF( PFR, 0xB00, "PFR module" ) - FT_MODERRDEF( PSaux, 0xC00, "PS auxiliary module" ) - FT_MODERRDEF( PShinter, 0xD00, "PS hinter module" ) - FT_MODERRDEF( PSnames, 0xE00, "PS names module" ) - FT_MODERRDEF( Raster, 0xF00, "raster module" ) - FT_MODERRDEF( SFNT, 0x1000, "SFNT module" ) - FT_MODERRDEF( Smooth, 0x1100, "smooth raster module" ) - FT_MODERRDEF( TrueType, 0x1200, "TrueType module" ) - FT_MODERRDEF( Type1, 0x1300, "Type 1 module" ) - FT_MODERRDEF( Type42, 0x1400, "Type 42 module" ) - FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" ) - FT_MODERRDEF( GXvalid, 0x1600, "GX validation module" ) - - -#ifdef FT_MODERR_END_LIST - FT_MODERR_END_LIST -#endif - - - /*******************************************************************/ - /*******************************************************************/ - /***** *****/ - /***** CLEANUP *****/ - /***** *****/ - /*******************************************************************/ - /*******************************************************************/ - - -#ifdef FT_NEED_EXTERN_C - } -#endif - -#undef FT_MODERR_START_LIST -#undef FT_MODERR_END_LIST -#undef FT_MODERRDEF -#undef FT_NEED_EXTERN_C - - -#endif /* __FTMODERR_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftotval.h b/third_party/freetype/include/freetype/ftotval.h deleted file mode 100644 index e744b713fbec06c2e461071c406d6f292d990eb2..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftotval.h +++ /dev/null @@ -1,204 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftotval.h */ -/* */ -/* FreeType API for validating OpenType tables (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -/***************************************************************************/ -/* */ -/* */ -/* Warning: This module might be moved to a different library in the */ -/* future to avoid a tight dependency between FreeType and the */ -/* OpenType specification. */ -/* */ -/* */ -/***************************************************************************/ - - -#ifndef __FTOTVAL_H__ -#define __FTOTVAL_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* ot_validation */ - /* */ - /* <Title> */ - /* OpenType Validation */ - /* */ - /* <Abstract> */ - /* An API to validate OpenType tables. */ - /* */ - /* <Description> */ - /* This section contains the declaration of functions to validate */ - /* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). */ - /* */ - /* <Order> */ - /* FT_OpenType_Validate */ - /* FT_OpenType_Free */ - /* */ - /* FT_VALIDATE_OTXXX */ - /* */ - /*************************************************************************/ - - - /********************************************************************** - * - * @enum: - * FT_VALIDATE_OTXXX - * - * @description: - * A list of bit-field constants used with @FT_OpenType_Validate to - * indicate which OpenType tables should be validated. - * - * @values: - * FT_VALIDATE_BASE :: - * Validate BASE table. - * - * FT_VALIDATE_GDEF :: - * Validate GDEF table. - * - * FT_VALIDATE_GPOS :: - * Validate GPOS table. - * - * FT_VALIDATE_GSUB :: - * Validate GSUB table. - * - * FT_VALIDATE_JSTF :: - * Validate JSTF table. - * - * FT_VALIDATE_MATH :: - * Validate MATH table. - * - * FT_VALIDATE_OT :: - * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). - * - */ -#define FT_VALIDATE_BASE 0x0100 -#define FT_VALIDATE_GDEF 0x0200 -#define FT_VALIDATE_GPOS 0x0400 -#define FT_VALIDATE_GSUB 0x0800 -#define FT_VALIDATE_JSTF 0x1000 -#define FT_VALIDATE_MATH 0x2000 - -#define FT_VALIDATE_OT FT_VALIDATE_BASE | \ - FT_VALIDATE_GDEF | \ - FT_VALIDATE_GPOS | \ - FT_VALIDATE_GSUB | \ - FT_VALIDATE_JSTF | \ - FT_VALIDATE_MATH - - /********************************************************************** - * - * @function: - * FT_OpenType_Validate - * - * @description: - * Validate various OpenType tables to assure that all offsets and - * indices are valid. The idea is that a higher-level library that - * actually does the text layout can access those tables without - * error checking (which can be quite time consuming). - * - * @input: - * face :: - * A handle to the input face. - * - * validation_flags :: - * A bit field that specifies the tables to be validated. See - * @FT_VALIDATE_OTXXX for possible values. - * - * @output: - * BASE_table :: - * A pointer to the BASE table. - * - * GDEF_table :: - * A pointer to the GDEF table. - * - * GPOS_table :: - * A pointer to the GPOS table. - * - * GSUB_table :: - * A pointer to the GSUB table. - * - * JSTF_table :: - * A pointer to the JSTF table. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with OpenType fonts, returning an error - * otherwise. - * - * After use, the application should deallocate the five tables with - * @FT_OpenType_Free. A NULL value indicates that the table either - * doesn't exist in the font, or the application hasn't asked for - * validation. - */ - FT_EXPORT( FT_Error ) - FT_OpenType_Validate( FT_Face face, - FT_UInt validation_flags, - FT_Bytes *BASE_table, - FT_Bytes *GDEF_table, - FT_Bytes *GPOS_table, - FT_Bytes *GSUB_table, - FT_Bytes *JSTF_table ); - - /********************************************************************** - * - * @function: - * FT_OpenType_Free - * - * @description: - * Free the buffer allocated by OpenType validator. - * - * @input: - * face :: - * A handle to the input face. - * - * table :: - * The pointer to the buffer that is allocated by - * @FT_OpenType_Validate. - * - * @note: - * This function must be used to free the buffer allocated by - * @FT_OpenType_Validate only. - */ - FT_EXPORT( void ) - FT_OpenType_Free( FT_Face face, - FT_Bytes table ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTOTVAL_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftoutln.h b/third_party/freetype/include/freetype/ftoutln.h deleted file mode 100644 index b6ec70de8cf95cae3b31146b5c1b17c881d46292..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftoutln.h +++ /dev/null @@ -1,574 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftoutln.h */ -/* */ -/* Support for the FT_Outline type used to store glyph shapes of */ -/* most scalable font formats (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTOUTLN_H__ -#define __FTOUTLN_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* outline_processing */ - /* */ - /* <Title> */ - /* Outline Processing */ - /* */ - /* <Abstract> */ - /* Functions to create, transform, and render vectorial glyph images. */ - /* */ - /* <Description> */ - /* This section contains routines used to create and destroy scalable */ - /* glyph images known as `outlines'. These can also be measured, */ - /* transformed, and converted into bitmaps and pixmaps. */ - /* */ - /* <Order> */ - /* FT_Outline */ - /* FT_Outline_New */ - /* FT_Outline_Done */ - /* FT_Outline_Copy */ - /* FT_Outline_Translate */ - /* FT_Outline_Transform */ - /* FT_Outline_Embolden */ - /* FT_Outline_EmboldenXY */ - /* FT_Outline_Reverse */ - /* FT_Outline_Check */ - /* */ - /* FT_Outline_Get_CBox */ - /* FT_Outline_Get_BBox */ - /* */ - /* FT_Outline_Get_Bitmap */ - /* FT_Outline_Render */ - /* FT_Outline_Decompose */ - /* FT_Outline_Funcs */ - /* FT_Outline_MoveToFunc */ - /* FT_Outline_LineToFunc */ - /* FT_Outline_ConicToFunc */ - /* FT_Outline_CubicToFunc */ - /* */ - /* FT_Orientation */ - /* FT_Outline_Get_Orientation */ - /* */ - /* FT_OUTLINE_XXX */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Decompose */ - /* */ - /* <Description> */ - /* Walk over an outline's structure to decompose it into individual */ - /* segments and Bézier arcs. This function also emits `move to' */ - /* operations to indicate the start of new contours in the outline. */ - /* */ - /* <Input> */ - /* outline :: A pointer to the source target. */ - /* */ - /* func_interface :: A table of `emitters', i.e., function pointers */ - /* called during decomposition to indicate path */ - /* operations. */ - /* */ - /* <InOut> */ - /* user :: A typeless pointer that is passed to each */ - /* emitter during the decomposition. It can be */ - /* used to store the state during the */ - /* decomposition. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* A contour that contains a single point only is represented by a */ - /* `move to' operation followed by `line to' to the same point. In */ - /* most cases, it is best to filter this out before using the */ - /* outline for stroking purposes (otherwise it would result in a */ - /* visible dot when round caps are used). */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Decompose( FT_Outline* outline, - const FT_Outline_Funcs* func_interface, - void* user ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_New */ - /* */ - /* <Description> */ - /* Create a new outline of a given size. */ - /* */ - /* <Input> */ - /* library :: A handle to the library object from where the */ - /* outline is allocated. Note however that the new */ - /* outline will *not* necessarily be *freed*, when */ - /* destroying the library, by @FT_Done_FreeType. */ - /* */ - /* numPoints :: The maximum number of points within the outline. */ - /* Must be smaller than or equal to 0xFFFF (65535). */ - /* */ - /* numContours :: The maximum number of contours within the outline. */ - /* This value must be in the range 0 to `numPoints'. */ - /* */ - /* <Output> */ - /* anoutline :: A handle to the new outline. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The reason why this function takes a `library' parameter is simply */ - /* to use the library's memory allocator. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_New( FT_Library library, - FT_UInt numPoints, - FT_Int numContours, - FT_Outline *anoutline ); - - - FT_EXPORT( FT_Error ) - FT_Outline_New_Internal( FT_Memory memory, - FT_UInt numPoints, - FT_Int numContours, - FT_Outline *anoutline ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Done */ - /* */ - /* <Description> */ - /* Destroy an outline created with @FT_Outline_New. */ - /* */ - /* <Input> */ - /* library :: A handle of the library object used to allocate the */ - /* outline. */ - /* */ - /* outline :: A pointer to the outline object to be discarded. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* If the outline's `owner' field is not set, only the outline */ - /* descriptor will be released. */ - /* */ - /* The reason why this function takes an `library' parameter is */ - /* simply to use ft_mem_free(). */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Done( FT_Library library, - FT_Outline* outline ); - - - FT_EXPORT( FT_Error ) - FT_Outline_Done_Internal( FT_Memory memory, - FT_Outline* outline ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Check */ - /* */ - /* <Description> */ - /* Check the contents of an outline descriptor. */ - /* */ - /* <Input> */ - /* outline :: A handle to a source outline. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Check( FT_Outline* outline ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Get_CBox */ - /* */ - /* <Description> */ - /* Return an outline's `control box'. The control box encloses all */ - /* the outline's points, including Bézier control points. Though it */ - /* coincides with the exact bounding box for most glyphs, it can be */ - /* slightly larger in some situations (like when rotating an outline */ - /* that contains Bézier outside arcs). */ - /* */ - /* Computing the control box is very fast, while getting the bounding */ - /* box can take much more time as it needs to walk over all segments */ - /* and arcs in the outline. To get the latter, you can use the */ - /* `ftbbox' component, which is dedicated to this single task. */ - /* */ - /* <Input> */ - /* outline :: A pointer to the source outline descriptor. */ - /* */ - /* <Output> */ - /* acbox :: The outline's control box. */ - /* */ - /* <Note> */ - /* See @FT_Glyph_Get_CBox for a discussion of tricky fonts. */ - /* */ - FT_EXPORT( void ) - FT_Outline_Get_CBox( const FT_Outline* outline, - FT_BBox *acbox ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Translate */ - /* */ - /* <Description> */ - /* Apply a simple translation to the points of an outline. */ - /* */ - /* <InOut> */ - /* outline :: A pointer to the target outline descriptor. */ - /* */ - /* <Input> */ - /* xOffset :: The horizontal offset. */ - /* */ - /* yOffset :: The vertical offset. */ - /* */ - FT_EXPORT( void ) - FT_Outline_Translate( const FT_Outline* outline, - FT_Pos xOffset, - FT_Pos yOffset ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Copy */ - /* */ - /* <Description> */ - /* Copy an outline into another one. Both objects must have the */ - /* same sizes (number of points & number of contours) when this */ - /* function is called. */ - /* */ - /* <Input> */ - /* source :: A handle to the source outline. */ - /* */ - /* <Output> */ - /* target :: A handle to the target outline. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Copy( const FT_Outline* source, - FT_Outline *target ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Transform */ - /* */ - /* <Description> */ - /* Apply a simple 2x2 matrix to all of an outline's points. Useful */ - /* for applying rotations, slanting, flipping, etc. */ - /* */ - /* <InOut> */ - /* outline :: A pointer to the target outline descriptor. */ - /* */ - /* <Input> */ - /* matrix :: A pointer to the transformation matrix. */ - /* */ - /* <Note> */ - /* You can use @FT_Outline_Translate if you need to translate the */ - /* outline's points. */ - /* */ - FT_EXPORT( void ) - FT_Outline_Transform( const FT_Outline* outline, - const FT_Matrix* matrix ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Embolden */ - /* */ - /* <Description> */ - /* Embolden an outline. The new outline will be at most 4~times */ - /* `strength' pixels wider and higher. You may think of the left and */ - /* bottom borders as unchanged. */ - /* */ - /* Negative `strength' values to reduce the outline thickness are */ - /* possible also. */ - /* */ - /* <InOut> */ - /* outline :: A handle to the target outline. */ - /* */ - /* <Input> */ - /* strength :: How strong the glyph is emboldened. Expressed in */ - /* 26.6 pixel format. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The used algorithm to increase or decrease the thickness of the */ - /* glyph doesn't change the number of points; this means that certain */ - /* situations like acute angles or intersections are sometimes */ - /* handled incorrectly. */ - /* */ - /* If you need `better' metrics values you should call */ - /* @FT_Outline_Get_CBox or @FT_Outline_Get_BBox. */ - /* */ - /* Example call: */ - /* */ - /* { */ - /* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */ - /* if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) */ - /* FT_Outline_Embolden( &face->glyph->outline, strength ); */ - /* } */ - /* */ - /* To get meaningful results, font scaling values must be set with */ - /* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Embolden( FT_Outline* outline, - FT_Pos strength ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_EmboldenXY */ - /* */ - /* <Description> */ - /* Embolden an outline. The new outline will be `xstrength' pixels */ - /* wider and `ystrength' pixels higher. Otherwise, it is similar to */ - /* @FT_Outline_Embolden, which uses the same strength in both */ - /* directions. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_EmboldenXY( FT_Outline* outline, - FT_Pos xstrength, - FT_Pos ystrength ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Reverse */ - /* */ - /* <Description> */ - /* Reverse the drawing direction of an outline. This is used to */ - /* ensure consistent fill conventions for mirrored glyphs. */ - /* */ - /* <InOut> */ - /* outline :: A pointer to the target outline descriptor. */ - /* */ - /* <Note> */ - /* This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in */ - /* the outline's `flags' field. */ - /* */ - /* It shouldn't be used by a normal client application, unless it */ - /* knows what it is doing. */ - /* */ - FT_EXPORT( void ) - FT_Outline_Reverse( FT_Outline* outline ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Get_Bitmap */ - /* */ - /* <Description> */ - /* Render an outline within a bitmap. The outline's image is simply */ - /* OR-ed to the target bitmap. */ - /* */ - /* <Input> */ - /* library :: A handle to a FreeType library object. */ - /* */ - /* outline :: A pointer to the source outline descriptor. */ - /* */ - /* <InOut> */ - /* abitmap :: A pointer to the target bitmap descriptor. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* This function does NOT CREATE the bitmap, it only renders an */ - /* outline image within the one you pass to it! Consequently, the */ - /* various fields in `abitmap' should be set accordingly. */ - /* */ - /* It will use the raster corresponding to the default glyph format. */ - /* */ - /* The value of the `num_grays' field in `abitmap' is ignored. If */ - /* you select the gray-level rasterizer, and you want less than 256 */ - /* gray levels, you have to use @FT_Outline_Render directly. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Get_Bitmap( FT_Library library, - FT_Outline* outline, - const FT_Bitmap *abitmap ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Render */ - /* */ - /* <Description> */ - /* Render an outline within a bitmap using the current scan-convert. */ - /* This function uses an @FT_Raster_Params structure as an argument, */ - /* allowing advanced features like direct composition, translucency, */ - /* etc. */ - /* */ - /* <Input> */ - /* library :: A handle to a FreeType library object. */ - /* */ - /* outline :: A pointer to the source outline descriptor. */ - /* */ - /* <InOut> */ - /* params :: A pointer to an @FT_Raster_Params structure used to */ - /* describe the rendering operation. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* You should know what you are doing and how @FT_Raster_Params works */ - /* to use this function. */ - /* */ - /* The field `params.source' will be set to `outline' before the scan */ - /* converter is called, which means that the value you give to it is */ - /* actually ignored. */ - /* */ - /* The gray-level rasterizer always uses 256 gray levels. If you */ - /* want less gray levels, you have to provide your own span callback. */ - /* See the @FT_RASTER_FLAG_DIRECT value of the `flags' field in the */ - /* @FT_Raster_Params structure for more details. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Outline_Render( FT_Library library, - FT_Outline* outline, - FT_Raster_Params* params ); - - - /************************************************************************** - * - * @enum: - * FT_Orientation - * - * @description: - * A list of values used to describe an outline's contour orientation. - * - * The TrueType and PostScript specifications use different conventions - * to determine whether outline contours should be filled or unfilled. - * - * @values: - * FT_ORIENTATION_TRUETYPE :: - * According to the TrueType specification, clockwise contours must - * be filled, and counter-clockwise ones must be unfilled. - * - * FT_ORIENTATION_POSTSCRIPT :: - * According to the PostScript specification, counter-clockwise contours - * must be filled, and clockwise ones must be unfilled. - * - * FT_ORIENTATION_FILL_RIGHT :: - * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to - * remember that in TrueType, everything that is to the right of - * the drawing direction of a contour must be filled. - * - * FT_ORIENTATION_FILL_LEFT :: - * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to - * remember that in PostScript, everything that is to the left of - * the drawing direction of a contour must be filled. - * - * FT_ORIENTATION_NONE :: - * The orientation cannot be determined. That is, different parts of - * the glyph have different orientation. - * - */ - typedef enum FT_Orientation_ - { - FT_ORIENTATION_TRUETYPE = 0, - FT_ORIENTATION_POSTSCRIPT = 1, - FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE, - FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT, - FT_ORIENTATION_NONE - - } FT_Orientation; - - - /************************************************************************** - * - * @function: - * FT_Outline_Get_Orientation - * - * @description: - * This function analyzes a glyph outline and tries to compute its - * fill orientation (see @FT_Orientation). This is done by integrating - * the total area covered by the outline. The positive integral - * corresponds to the clockwise orientation and @FT_ORIENTATION_POSTSCRIPT - * is returned. The negative integral corresponds to the counter-clockwise - * orientation and @FT_ORIENTATION_TRUETYPE is returned. - * - * Note that this will return @FT_ORIENTATION_TRUETYPE for empty - * outlines. - * - * @input: - * outline :: - * A handle to the source outline. - * - * @return: - * The orientation. - * - */ - FT_EXPORT( FT_Orientation ) - FT_Outline_Get_Orientation( FT_Outline* outline ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTOUTLN_H__ */ - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/include/freetype/ftpfr.h b/third_party/freetype/include/freetype/ftpfr.h deleted file mode 100644 index a1c02a2f5ee03681c7ac390b6cfb68528019b2f7..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftpfr.h +++ /dev/null @@ -1,172 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftpfr.h */ -/* */ -/* FreeType API for accessing PFR-specific data (specification only). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTPFR_H__ -#define __FTPFR_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* pfr_fonts */ - /* */ - /* <Title> */ - /* PFR Fonts */ - /* */ - /* <Abstract> */ - /* PFR/TrueDoc specific API. */ - /* */ - /* <Description> */ - /* This section contains the declaration of PFR-specific functions. */ - /* */ - /*************************************************************************/ - - - /********************************************************************** - * - * @function: - * FT_Get_PFR_Metrics - * - * @description: - * Return the outline and metrics resolutions of a given PFR face. - * - * @input: - * face :: Handle to the input face. It can be a non-PFR face. - * - * @output: - * aoutline_resolution :: - * Outline resolution. This is equivalent to `face->units_per_EM' - * for non-PFR fonts. Optional (parameter can be NULL). - * - * ametrics_resolution :: - * Metrics resolution. This is equivalent to `outline_resolution' - * for non-PFR fonts. Optional (parameter can be NULL). - * - * ametrics_x_scale :: - * A 16.16 fixed-point number used to scale distance expressed - * in metrics units to device sub-pixels. This is equivalent to - * `face->size->x_scale', but for metrics only. Optional (parameter - * can be NULL). - * - * ametrics_y_scale :: - * Same as `ametrics_x_scale' but for the vertical direction. - * optional (parameter can be NULL). - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If the input face is not a PFR, this function will return an error. - * However, in all cases, it will return valid values. - */ - FT_EXPORT( FT_Error ) - FT_Get_PFR_Metrics( FT_Face face, - FT_UInt *aoutline_resolution, - FT_UInt *ametrics_resolution, - FT_Fixed *ametrics_x_scale, - FT_Fixed *ametrics_y_scale ); - - - /********************************************************************** - * - * @function: - * FT_Get_PFR_Kerning - * - * @description: - * Return the kerning pair corresponding to two glyphs in a PFR face. - * The distance is expressed in metrics units, unlike the result of - * @FT_Get_Kerning. - * - * @input: - * face :: A handle to the input face. - * - * left :: Index of the left glyph. - * - * right :: Index of the right glyph. - * - * @output: - * avector :: A kerning vector. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function always return distances in original PFR metrics - * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED - * mode, which always returns distances converted to outline units. - * - * You can use the value of the `x_scale' and `y_scale' parameters - * returned by @FT_Get_PFR_Metrics to scale these to device sub-pixels. - */ - FT_EXPORT( FT_Error ) - FT_Get_PFR_Kerning( FT_Face face, - FT_UInt left, - FT_UInt right, - FT_Vector *avector ); - - - /********************************************************************** - * - * @function: - * FT_Get_PFR_Advance - * - * @description: - * Return a given glyph advance, expressed in original metrics units, - * from a PFR font. - * - * @input: - * face :: A handle to the input face. - * - * gindex :: The glyph index. - * - * @output: - * aadvance :: The glyph advance in metrics units. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics - * to convert the advance to device sub-pixels (i.e., 1/64th of pixels). - */ - FT_EXPORT( FT_Error ) - FT_Get_PFR_Advance( FT_Face face, - FT_UInt gindex, - FT_Pos *aadvance ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTPFR_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftrender.h b/third_party/freetype/include/freetype/ftrender.h deleted file mode 100644 index ec8da700b144ed413c84d5f740b99164aea3a6d2..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftrender.h +++ /dev/null @@ -1,232 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftrender.h */ -/* */ -/* FreeType renderer modules public interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTRENDER_H__ -#define __FTRENDER_H__ - - -#include <ft2build.h> -#include FT_MODULE_H -#include FT_GLYPH_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* module_management */ - /* */ - /*************************************************************************/ - - - /* create a new glyph object */ - typedef FT_Error - (*FT_Glyph_InitFunc)( FT_Glyph glyph, - FT_GlyphSlot slot ); - - /* destroys a given glyph object */ - typedef void - (*FT_Glyph_DoneFunc)( FT_Glyph glyph ); - - typedef void - (*FT_Glyph_TransformFunc)( FT_Glyph glyph, - const FT_Matrix* matrix, - const FT_Vector* delta ); - - typedef void - (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph, - FT_BBox* abbox ); - - typedef FT_Error - (*FT_Glyph_CopyFunc)( FT_Glyph source, - FT_Glyph target ); - - typedef FT_Error - (*FT_Glyph_PrepareFunc)( FT_Glyph glyph, - FT_GlyphSlot slot ); - -/* deprecated */ -#define FT_Glyph_Init_Func FT_Glyph_InitFunc -#define FT_Glyph_Done_Func FT_Glyph_DoneFunc -#define FT_Glyph_Transform_Func FT_Glyph_TransformFunc -#define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc -#define FT_Glyph_Copy_Func FT_Glyph_CopyFunc -#define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc - - - struct FT_Glyph_Class_ - { - FT_Long glyph_size; - FT_Glyph_Format glyph_format; - FT_Glyph_InitFunc glyph_init; - FT_Glyph_DoneFunc glyph_done; - FT_Glyph_CopyFunc glyph_copy; - FT_Glyph_TransformFunc glyph_transform; - FT_Glyph_GetBBoxFunc glyph_bbox; - FT_Glyph_PrepareFunc glyph_prepare; - }; - - - typedef FT_Error - (*FT_Renderer_RenderFunc)( FT_Renderer renderer, - FT_GlyphSlot slot, - FT_UInt mode, - const FT_Vector* origin ); - - typedef FT_Error - (*FT_Renderer_TransformFunc)( FT_Renderer renderer, - FT_GlyphSlot slot, - const FT_Matrix* matrix, - const FT_Vector* delta ); - - - typedef void - (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer, - FT_GlyphSlot slot, - FT_BBox* cbox ); - - - typedef FT_Error - (*FT_Renderer_SetModeFunc)( FT_Renderer renderer, - FT_ULong mode_tag, - FT_Pointer mode_ptr ); - -/* deprecated identifiers */ -#define FTRenderer_render FT_Renderer_RenderFunc -#define FTRenderer_transform FT_Renderer_TransformFunc -#define FTRenderer_getCBox FT_Renderer_GetCBoxFunc -#define FTRenderer_setMode FT_Renderer_SetModeFunc - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Renderer_Class */ - /* */ - /* <Description> */ - /* The renderer module class descriptor. */ - /* */ - /* <Fields> */ - /* root :: The root @FT_Module_Class fields. */ - /* */ - /* glyph_format :: The glyph image format this renderer handles. */ - /* */ - /* render_glyph :: A method used to render the image that is in a */ - /* given glyph slot into a bitmap. */ - /* */ - /* transform_glyph :: A method used to transform the image that is in */ - /* a given glyph slot. */ - /* */ - /* get_glyph_cbox :: A method used to access the glyph's cbox. */ - /* */ - /* set_mode :: A method used to pass additional parameters. */ - /* */ - /* raster_class :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. */ - /* This is a pointer to its raster's class. */ - /* */ - typedef struct FT_Renderer_Class_ - { - FT_Module_Class root; - - FT_Glyph_Format glyph_format; - - FT_Renderer_RenderFunc render_glyph; - FT_Renderer_TransformFunc transform_glyph; - FT_Renderer_GetCBoxFunc get_glyph_cbox; - FT_Renderer_SetModeFunc set_mode; - - FT_Raster_Funcs* raster_class; - - } FT_Renderer_Class; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Renderer */ - /* */ - /* <Description> */ - /* Retrieve the current renderer for a given glyph format. */ - /* */ - /* <Input> */ - /* library :: A handle to the library object. */ - /* */ - /* format :: The glyph format. */ - /* */ - /* <Return> */ - /* A renderer handle. 0~if none found. */ - /* */ - /* <Note> */ - /* An error will be returned if a module already exists by that name, */ - /* or if the module requires a version of FreeType that is too great. */ - /* */ - /* To add a new renderer, simply use @FT_Add_Module. To retrieve a */ - /* renderer by its name, use @FT_Get_Module. */ - /* */ - FT_EXPORT( FT_Renderer ) - FT_Get_Renderer( FT_Library library, - FT_Glyph_Format format ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Set_Renderer */ - /* */ - /* <Description> */ - /* Set the current renderer to use, and set additional mode. */ - /* */ - /* <InOut> */ - /* library :: A handle to the library object. */ - /* */ - /* <Input> */ - /* renderer :: A handle to the renderer object. */ - /* */ - /* num_params :: The number of additional parameters. */ - /* */ - /* parameters :: Additional parameters. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* In case of success, the renderer will be used to convert glyph */ - /* images in the renderer's known format into bitmaps. */ - /* */ - /* This doesn't change the current renderer for other formats. */ - /* */ - /* Currently, no FreeType renderer module uses `parameters'; you */ - /* should thus always pass NULL as the value. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Set_Renderer( FT_Library library, - FT_Renderer renderer, - FT_UInt num_params, - FT_Parameter* parameters ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTRENDER_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftsizes.h b/third_party/freetype/include/freetype/ftsizes.h deleted file mode 100644 index bef8424715f1960eb11b4c5ffa0d974c1d276e50..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftsizes.h +++ /dev/null @@ -1,159 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsizes.h */ -/* */ -/* FreeType size objects management (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* Typical application would normally not need to use these functions. */ - /* However, they have been placed in a public API for the rare cases */ - /* where they are needed. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTSIZES_H__ -#define __FTSIZES_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* sizes_management */ - /* */ - /* <Title> */ - /* Size Management */ - /* */ - /* <Abstract> */ - /* Managing multiple sizes per face. */ - /* */ - /* <Description> */ - /* When creating a new face object (e.g., with @FT_New_Face), an */ - /* @FT_Size object is automatically created and used to store all */ - /* pixel-size dependent information, available in the `face->size' */ - /* field. */ - /* */ - /* It is however possible to create more sizes for a given face, */ - /* mostly in order to manage several character pixel sizes of the */ - /* same font family and style. See @FT_New_Size and @FT_Done_Size. */ - /* */ - /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */ - /* modify the contents of the current `active' size; you thus need */ - /* to use @FT_Activate_Size to change it. */ - /* */ - /* 99% of applications won't need the functions provided here, */ - /* especially if they use the caching sub-system, so be cautious */ - /* when using these. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Size */ - /* */ - /* <Description> */ - /* Create a new size object from a given face object. */ - /* */ - /* <Input> */ - /* face :: A handle to a parent face object. */ - /* */ - /* <Output> */ - /* asize :: A handle to a new size object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* You need to call @FT_Activate_Size in order to select the new size */ - /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */ - /* @FT_Load_Glyph, @FT_Load_Char, etc. */ - /* */ - FT_EXPORT( FT_Error ) - FT_New_Size( FT_Face face, - FT_Size* size ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_Size */ - /* */ - /* <Description> */ - /* Discard a given size object. Note that @FT_Done_Face */ - /* automatically discards all size objects allocated with */ - /* @FT_New_Size. */ - /* */ - /* <Input> */ - /* size :: A handle to a target size object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Done_Size( FT_Size size ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Activate_Size */ - /* */ - /* <Description> */ - /* Even though it is possible to create several size objects for a */ - /* given face (see @FT_New_Size for details), functions like */ - /* @FT_Load_Glyph or @FT_Load_Char only use the one that has been */ - /* activated last to determine the `current character pixel size'. */ - /* */ - /* This function can be used to `activate' a previously created size */ - /* object. */ - /* */ - /* <Input> */ - /* size :: A handle to a target size object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* If `face' is the size's parent face object, this function changes */ - /* the value of `face->size' to the input size handle. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Activate_Size( FT_Size size ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTSIZES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftsnames.h b/third_party/freetype/include/freetype/ftsnames.h deleted file mode 100644 index 0f7fbe1744536991ea6edcb0eea72dade53b2285..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftsnames.h +++ /dev/null @@ -1,200 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsnames.h */ -/* */ -/* Simple interface to access SFNT name tables (which are used */ -/* to hold font names, copyright info, notices, etc.) (specification). */ -/* */ -/* This is _not_ used to retrieve glyph names! */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FT_SFNT_NAMES_H__ -#define __FT_SFNT_NAMES_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* sfnt_names */ - /* */ - /* <Title> */ - /* SFNT Names */ - /* */ - /* <Abstract> */ - /* Access the names embedded in TrueType and OpenType files. */ - /* */ - /* <Description> */ - /* The TrueType and OpenType specifications allow the inclusion of */ - /* a special `names table' in font files. This table contains */ - /* textual (and internationalized) information regarding the font, */ - /* like family name, copyright, version, etc. */ - /* */ - /* The definitions below are used to access them if available. */ - /* */ - /* Note that this has nothing to do with glyph names! */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_SfntName */ - /* */ - /* <Description> */ - /* A structure used to model an SFNT `name' table entry. */ - /* */ - /* <Fields> */ - /* platform_id :: The platform ID for `string'. */ - /* */ - /* encoding_id :: The encoding ID for `string'. */ - /* */ - /* language_id :: The language ID for `string'. */ - /* */ - /* name_id :: An identifier for `string'. */ - /* */ - /* string :: The `name' string. Note that its format differs */ - /* depending on the (platform,encoding) pair. It can */ - /* be a Pascal String, a UTF-16 one, etc. */ - /* */ - /* Generally speaking, the string is not */ - /* zero-terminated. Please refer to the TrueType */ - /* specification for details. */ - /* */ - /* string_len :: The length of `string' in bytes. */ - /* */ - /* <Note> */ - /* Possible values for `platform_id', `encoding_id', `language_id', */ - /* and `name_id' are given in the file `ttnameid.h'. For details */ - /* please refer to the TrueType or OpenType specification. */ - /* */ - /* See also @TT_PLATFORM_XXX, @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */ - /* @TT_ISO_ID_XXX, and @TT_MS_ID_XXX. */ - /* */ - typedef struct FT_SfntName_ - { - FT_UShort platform_id; - FT_UShort encoding_id; - FT_UShort language_id; - FT_UShort name_id; - - FT_Byte* string; /* this string is *not* null-terminated! */ - FT_UInt string_len; /* in bytes */ - - } FT_SfntName; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Sfnt_Name_Count */ - /* */ - /* <Description> */ - /* Retrieve the number of name strings in the SFNT `name' table. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face. */ - /* */ - /* <Return> */ - /* The number of strings in the `name' table. */ - /* */ - FT_EXPORT( FT_UInt ) - FT_Get_Sfnt_Name_Count( FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Sfnt_Name */ - /* */ - /* <Description> */ - /* Retrieve a string of the SFNT `name' table for a given index. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face. */ - /* */ - /* idx :: The index of the `name' string. */ - /* */ - /* <Output> */ - /* aname :: The indexed @FT_SfntName structure. */ - /* */ - /* <Return> */ - /* FreeType error code. 0~means success. */ - /* */ - /* <Note> */ - /* The `string' array returned in the `aname' structure is not */ - /* null-terminated. The application should deallocate it if it is no */ - /* longer in use. */ - /* */ - /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */ - /* `name' table entries, then do a loop until you get the right */ - /* platform, encoding, and name ID. */ - /* */ - FT_EXPORT( FT_Error ) - FT_Get_Sfnt_Name( FT_Face face, - FT_UInt idx, - FT_SfntName *aname ); - - - /*************************************************************************** - * - * @constant: - * FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY - * - * @description: - * A constant used as the tag of @FT_Parameter structures to make - * FT_Open_Face() ignore preferred family subfamily names in `name' - * table since OpenType version 1.4. For backwards compatibility with - * legacy systems that have a 4-face-per-family restriction. - * - */ -#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY FT_MAKE_TAG( 'i', 'g', 'p', 'f' ) - - - /*************************************************************************** - * - * @constant: - * FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY - * - * @description: - * A constant used as the tag of @FT_Parameter structures to make - * FT_Open_Face() ignore preferred subfamily names in `name' table since - * OpenType version 1.4. For backwards compatibility with legacy - * systems that have a 4-face-per-family restriction. - * - */ -#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY FT_MAKE_TAG( 'i', 'g', 'p', 's' ) - - /* */ - - -FT_END_HEADER - -#endif /* __FT_SFNT_NAMES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftstroke.h b/third_party/freetype/include/freetype/ftstroke.h deleted file mode 100644 index 7ebb1e7404e94519fc1b65f6c25e54b22b08eef8..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftstroke.h +++ /dev/null @@ -1,785 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftstroke.h */ -/* */ -/* FreeType path stroker (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FT_STROKE_H__ -#define __FT_STROKE_H__ - -#include <ft2build.h> -#include FT_OUTLINE_H -#include FT_GLYPH_H - - -FT_BEGIN_HEADER - - - /************************************************************************ - * - * @section: - * glyph_stroker - * - * @title: - * Glyph Stroker - * - * @abstract: - * Generating bordered and stroked glyphs. - * - * @description: - * This component generates stroked outlines of a given vectorial - * glyph. It also allows you to retrieve the `outside' and/or the - * `inside' borders of the stroke. - * - * This can be useful to generate `bordered' glyph, i.e., glyphs - * displayed with a coloured (and anti-aliased) border around their - * shape. - * - * @order: - * FT_Stroker - * - * FT_Stroker_LineJoin - * FT_Stroker_LineCap - * FT_StrokerBorder - * - * FT_Outline_GetInsideBorder - * FT_Outline_GetOutsideBorder - * - * FT_Glyph_Stroke - * FT_Glyph_StrokeBorder - * - * FT_Stroker_New - * FT_Stroker_Set - * FT_Stroker_Rewind - * FT_Stroker_ParseOutline - * FT_Stroker_Done - * - * FT_Stroker_BeginSubPath - * FT_Stroker_EndSubPath - * - * FT_Stroker_LineTo - * FT_Stroker_ConicTo - * FT_Stroker_CubicTo - * - * FT_Stroker_GetBorderCounts - * FT_Stroker_ExportBorder - * FT_Stroker_GetCounts - * FT_Stroker_Export - * - */ - - - /************************************************************** - * - * @type: - * FT_Stroker - * - * @description: - * Opaque handle to a path stroker object. - */ - typedef struct FT_StrokerRec_* FT_Stroker; - - - /************************************************************** - * - * @enum: - * FT_Stroker_LineJoin - * - * @description: - * These values determine how two joining lines are rendered - * in a stroker. - * - * @values: - * FT_STROKER_LINEJOIN_ROUND :: - * Used to render rounded line joins. Circular arcs are used - * to join two lines smoothly. - * - * FT_STROKER_LINEJOIN_BEVEL :: - * Used to render beveled line joins. The outer corner of - * the joined lines is filled by enclosing the triangular - * region of the corner with a straight line between the - * outer corners of each stroke. - * - * FT_STROKER_LINEJOIN_MITER_FIXED :: - * Used to render mitered line joins, with fixed bevels if the - * miter limit is exceeded. The outer edges of the strokes - * for the two segments are extended until they meet at an - * angle. If the segments meet at too sharp an angle (such - * that the miter would extend from the intersection of the - * segments a distance greater than the product of the miter - * limit value and the border radius), then a bevel join (see - * above) is used instead. This prevents long spikes being - * created. FT_STROKER_LINEJOIN_MITER_FIXED generates a miter - * line join as used in PostScript and PDF. - * - * FT_STROKER_LINEJOIN_MITER_VARIABLE :: - * FT_STROKER_LINEJOIN_MITER :: - * Used to render mitered line joins, with variable bevels if - * the miter limit is exceeded. The intersection of the - * strokes is clipped at a line perpendicular to the bisector - * of the angle between the strokes, at the distance from the - * intersection of the segments equal to the product of the - * miter limit value and the border radius. This prevents - * long spikes being created. - * FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line - * join as used in XPS. FT_STROKER_LINEJOIN_MITER is an alias - * for FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for - * backwards compatibility. - */ - typedef enum FT_Stroker_LineJoin_ - { - FT_STROKER_LINEJOIN_ROUND = 0, - FT_STROKER_LINEJOIN_BEVEL = 1, - FT_STROKER_LINEJOIN_MITER_VARIABLE = 2, - FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE, - FT_STROKER_LINEJOIN_MITER_FIXED = 3 - - } FT_Stroker_LineJoin; - - - /************************************************************** - * - * @enum: - * FT_Stroker_LineCap - * - * @description: - * These values determine how the end of opened sub-paths are - * rendered in a stroke. - * - * @values: - * FT_STROKER_LINECAP_BUTT :: - * The end of lines is rendered as a full stop on the last - * point itself. - * - * FT_STROKER_LINECAP_ROUND :: - * The end of lines is rendered as a half-circle around the - * last point. - * - * FT_STROKER_LINECAP_SQUARE :: - * The end of lines is rendered as a square around the - * last point. - */ - typedef enum FT_Stroker_LineCap_ - { - FT_STROKER_LINECAP_BUTT = 0, - FT_STROKER_LINECAP_ROUND, - FT_STROKER_LINECAP_SQUARE - - } FT_Stroker_LineCap; - - - /************************************************************** - * - * @enum: - * FT_StrokerBorder - * - * @description: - * These values are used to select a given stroke border - * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder. - * - * @values: - * FT_STROKER_BORDER_LEFT :: - * Select the left border, relative to the drawing direction. - * - * FT_STROKER_BORDER_RIGHT :: - * Select the right border, relative to the drawing direction. - * - * @note: - * Applications are generally interested in the `inside' and `outside' - * borders. However, there is no direct mapping between these and the - * `left' and `right' ones, since this really depends on the glyph's - * drawing orientation, which varies between font formats. - * - * You can however use @FT_Outline_GetInsideBorder and - * @FT_Outline_GetOutsideBorder to get these. - */ - typedef enum FT_StrokerBorder_ - { - FT_STROKER_BORDER_LEFT = 0, - FT_STROKER_BORDER_RIGHT - - } FT_StrokerBorder; - - - /************************************************************** - * - * @function: - * FT_Outline_GetInsideBorder - * - * @description: - * Retrieve the @FT_StrokerBorder value corresponding to the - * `inside' borders of a given outline. - * - * @input: - * outline :: - * The source outline handle. - * - * @return: - * The border index. @FT_STROKER_BORDER_RIGHT for empty or invalid - * outlines. - */ - FT_EXPORT( FT_StrokerBorder ) - FT_Outline_GetInsideBorder( FT_Outline* outline ); - - - /************************************************************** - * - * @function: - * FT_Outline_GetOutsideBorder - * - * @description: - * Retrieve the @FT_StrokerBorder value corresponding to the - * `outside' borders of a given outline. - * - * @input: - * outline :: - * The source outline handle. - * - * @return: - * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid - * outlines. - */ - FT_EXPORT( FT_StrokerBorder ) - FT_Outline_GetOutsideBorder( FT_Outline* outline ); - - - /************************************************************** - * - * @function: - * FT_Stroker_New - * - * @description: - * Create a new stroker object. - * - * @input: - * library :: - * FreeType library handle. - * - * @output: - * astroker :: - * A new stroker object handle. NULL in case of error. - * - * @return: - * FreeType error code. 0~means success. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_New( FT_Library library, - FT_Stroker *astroker ); - - - /************************************************************** - * - * @function: - * FT_Stroker_Set - * - * @description: - * Reset a stroker object's attributes. - * - * @input: - * stroker :: - * The target stroker handle. - * - * radius :: - * The border radius. - * - * line_cap :: - * The line cap style. - * - * line_join :: - * The line join style. - * - * miter_limit :: - * The miter limit for the FT_STROKER_LINEJOIN_MITER_FIXED and - * FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles, - * expressed as 16.16 fixed-point value. - * - * @note: - * The radius is expressed in the same units as the outline - * coordinates. - * - * This function calls @FT_Stroker_Rewind automatically. - */ - FT_EXPORT( void ) - FT_Stroker_Set( FT_Stroker stroker, - FT_Fixed radius, - FT_Stroker_LineCap line_cap, - FT_Stroker_LineJoin line_join, - FT_Fixed miter_limit ); - - - /************************************************************** - * - * @function: - * FT_Stroker_Rewind - * - * @description: - * Reset a stroker object without changing its attributes. - * You should call this function before beginning a new - * series of calls to @FT_Stroker_BeginSubPath or - * @FT_Stroker_EndSubPath. - * - * @input: - * stroker :: - * The target stroker handle. - */ - FT_EXPORT( void ) - FT_Stroker_Rewind( FT_Stroker stroker ); - - - /************************************************************** - * - * @function: - * FT_Stroker_ParseOutline - * - * @description: - * A convenience function used to parse a whole outline with - * the stroker. The resulting outline(s) can be retrieved - * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export. - * - * @input: - * stroker :: - * The target stroker handle. - * - * outline :: - * The source outline. - * - * opened :: - * A boolean. If~1, the outline is treated as an open path instead - * of a closed one. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If `opened' is~0 (the default), the outline is treated as a closed - * path, and the stroker generates two distinct `border' outlines. - * - * If `opened' is~1, the outline is processed as an open path, and the - * stroker generates a single `stroke' outline. - * - * This function calls @FT_Stroker_Rewind automatically. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_ParseOutline( FT_Stroker stroker, - FT_Outline* outline, - FT_Bool opened ); - - - /************************************************************** - * - * @function: - * FT_Stroker_BeginSubPath - * - * @description: - * Start a new sub-path in the stroker. - * - * @input: - * stroker :: - * The target stroker handle. - * - * to :: - * A pointer to the start vector. - * - * open :: - * A boolean. If~1, the sub-path is treated as an open one. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function is useful when you need to stroke a path that is - * not stored as an @FT_Outline object. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_BeginSubPath( FT_Stroker stroker, - FT_Vector* to, - FT_Bool open ); - - - /************************************************************** - * - * @function: - * FT_Stroker_EndSubPath - * - * @description: - * Close the current sub-path in the stroker. - * - * @input: - * stroker :: - * The target stroker handle. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * You should call this function after @FT_Stroker_BeginSubPath. - * If the subpath was not `opened', this function `draws' a - * single line segment to the start position when needed. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_EndSubPath( FT_Stroker stroker ); - - - /************************************************************** - * - * @function: - * FT_Stroker_LineTo - * - * @description: - * `Draw' a single line segment in the stroker's current sub-path, - * from the last position. - * - * @input: - * stroker :: - * The target stroker handle. - * - * to :: - * A pointer to the destination point. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * You should call this function between @FT_Stroker_BeginSubPath and - * @FT_Stroker_EndSubPath. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_LineTo( FT_Stroker stroker, - FT_Vector* to ); - - - /************************************************************** - * - * @function: - * FT_Stroker_ConicTo - * - * @description: - * `Draw' a single quadratic Bézier in the stroker's current sub-path, - * from the last position. - * - * @input: - * stroker :: - * The target stroker handle. - * - * control :: - * A pointer to a Bézier control point. - * - * to :: - * A pointer to the destination point. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * You should call this function between @FT_Stroker_BeginSubPath and - * @FT_Stroker_EndSubPath. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_ConicTo( FT_Stroker stroker, - FT_Vector* control, - FT_Vector* to ); - - - /************************************************************** - * - * @function: - * FT_Stroker_CubicTo - * - * @description: - * `Draw' a single cubic Bézier in the stroker's current sub-path, - * from the last position. - * - * @input: - * stroker :: - * The target stroker handle. - * - * control1 :: - * A pointer to the first Bézier control point. - * - * control2 :: - * A pointer to second Bézier control point. - * - * to :: - * A pointer to the destination point. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * You should call this function between @FT_Stroker_BeginSubPath and - * @FT_Stroker_EndSubPath. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_CubicTo( FT_Stroker stroker, - FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to ); - - - /************************************************************** - * - * @function: - * FT_Stroker_GetBorderCounts - * - * @description: - * Call this function once you have finished parsing your paths - * with the stroker. It returns the number of points and - * contours necessary to export one of the `border' or `stroke' - * outlines generated by the stroker. - * - * @input: - * stroker :: - * The target stroker handle. - * - * border :: - * The border index. - * - * @output: - * anum_points :: - * The number of points. - * - * anum_contours :: - * The number of contours. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * When an outline, or a sub-path, is `closed', the stroker generates - * two independent `border' outlines, named `left' and `right'. - * - * When the outline, or a sub-path, is `opened', the stroker merges - * the `border' outlines with caps. The `left' border receives all - * points, while the `right' border becomes empty. - * - * Use the function @FT_Stroker_GetCounts instead if you want to - * retrieve the counts associated to both borders. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_GetBorderCounts( FT_Stroker stroker, - FT_StrokerBorder border, - FT_UInt *anum_points, - FT_UInt *anum_contours ); - - - /************************************************************** - * - * @function: - * FT_Stroker_ExportBorder - * - * @description: - * Call this function after @FT_Stroker_GetBorderCounts to - * export the corresponding border to your own @FT_Outline - * structure. - * - * Note that this function appends the border points and - * contours to your outline, but does not try to resize its - * arrays. - * - * @input: - * stroker :: - * The target stroker handle. - * - * border :: - * The border index. - * - * outline :: - * The target outline handle. - * - * @note: - * Always call this function after @FT_Stroker_GetBorderCounts to - * get sure that there is enough room in your @FT_Outline object to - * receive all new data. - * - * When an outline, or a sub-path, is `closed', the stroker generates - * two independent `border' outlines, named `left' and `right'. - * - * When the outline, or a sub-path, is `opened', the stroker merges - * the `border' outlines with caps. The `left' border receives all - * points, while the `right' border becomes empty. - * - * Use the function @FT_Stroker_Export instead if you want to - * retrieve all borders at once. - */ - FT_EXPORT( void ) - FT_Stroker_ExportBorder( FT_Stroker stroker, - FT_StrokerBorder border, - FT_Outline* outline ); - - - /************************************************************** - * - * @function: - * FT_Stroker_GetCounts - * - * @description: - * Call this function once you have finished parsing your paths - * with the stroker. It returns the number of points and - * contours necessary to export all points/borders from the stroked - * outline/path. - * - * @input: - * stroker :: - * The target stroker handle. - * - * @output: - * anum_points :: - * The number of points. - * - * anum_contours :: - * The number of contours. - * - * @return: - * FreeType error code. 0~means success. - */ - FT_EXPORT( FT_Error ) - FT_Stroker_GetCounts( FT_Stroker stroker, - FT_UInt *anum_points, - FT_UInt *anum_contours ); - - - /************************************************************** - * - * @function: - * FT_Stroker_Export - * - * @description: - * Call this function after @FT_Stroker_GetBorderCounts to - * export all borders to your own @FT_Outline structure. - * - * Note that this function appends the border points and - * contours to your outline, but does not try to resize its - * arrays. - * - * @input: - * stroker :: - * The target stroker handle. - * - * outline :: - * The target outline handle. - */ - FT_EXPORT( void ) - FT_Stroker_Export( FT_Stroker stroker, - FT_Outline* outline ); - - - /************************************************************** - * - * @function: - * FT_Stroker_Done - * - * @description: - * Destroy a stroker object. - * - * @input: - * stroker :: - * A stroker handle. Can be NULL. - */ - FT_EXPORT( void ) - FT_Stroker_Done( FT_Stroker stroker ); - - - /************************************************************** - * - * @function: - * FT_Glyph_Stroke - * - * @description: - * Stroke a given outline glyph object with a given stroker. - * - * @inout: - * pglyph :: - * Source glyph handle on input, new glyph handle on output. - * - * @input: - * stroker :: - * A stroker handle. - * - * destroy :: - * A Boolean. If~1, the source glyph object is destroyed - * on success. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The source glyph is untouched in case of error. - * - * Adding stroke may yield a significantly wider and taller glyph - * depending on how large of a radius was used to stroke the glyph. You - * may need to manually adjust horizontal and vertical advance amounts - * to account for this added size. - */ - FT_EXPORT( FT_Error ) - FT_Glyph_Stroke( FT_Glyph *pglyph, - FT_Stroker stroker, - FT_Bool destroy ); - - - /************************************************************** - * - * @function: - * FT_Glyph_StrokeBorder - * - * @description: - * Stroke a given outline glyph object with a given stroker, but - * only return either its inside or outside border. - * - * @inout: - * pglyph :: - * Source glyph handle on input, new glyph handle on output. - * - * @input: - * stroker :: - * A stroker handle. - * - * inside :: - * A Boolean. If~1, return the inside border, otherwise - * the outside border. - * - * destroy :: - * A Boolean. If~1, the source glyph object is destroyed - * on success. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The source glyph is untouched in case of error. - * - * Adding stroke may yield a significantly wider and taller glyph - * depending on how large of a radius was used to stroke the glyph. You - * may need to manually adjust horizontal and vertical advance amounts - * to account for this added size. - */ - FT_EXPORT( FT_Error ) - FT_Glyph_StrokeBorder( FT_Glyph *pglyph, - FT_Stroker stroker, - FT_Bool inside, - FT_Bool destroy ); - - /* */ - -FT_END_HEADER - -#endif /* __FT_STROKE_H__ */ - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/include/freetype/ftsynth.h b/third_party/freetype/include/freetype/ftsynth.h deleted file mode 100644 index fbcbad871a92496f520fb8e0927eac9d3e329118..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftsynth.h +++ /dev/null @@ -1,84 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsynth.h */ -/* */ -/* FreeType synthesizing code for emboldening and slanting */ -/* (specification). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********* *********/ - /********* WARNING, THIS IS ALPHA CODE! THIS API *********/ - /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/ - /********* FREETYPE DEVELOPMENT TEAM *********/ - /********* *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* Main reason for not lifting the functions in this module to a */ - /* `standard' API is that the used parameters for emboldening and */ - /* slanting are not configurable. Consider the functions as a */ - /* code resource that should be copied into the application and */ - /* adapted to the particular needs. */ - - -#ifndef __FTSYNTH_H__ -#define __FTSYNTH_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /* Embolden a glyph by a `reasonable' value (which is highly a matter of */ - /* taste). This function is actually a convenience function, providing */ - /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */ - /* */ - /* For emboldened outlines the height, width, and advance metrics are */ - /* increased by the strength of the emboldening -- this even affects */ - /* mono-width fonts! */ - /* */ - /* You can also call @FT_Outline_Get_CBox to get precise values. */ - FT_EXPORT( void ) - FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); - - /* Slant an outline glyph to the right by about 12 degrees. */ - FT_EXPORT( void ) - FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTSYNTH_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftsystem.h b/third_party/freetype/include/freetype/ftsystem.h deleted file mode 100644 index 2bc999910b47c473c7422c944dc2bcdb62094c5c..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftsystem.h +++ /dev/null @@ -1,355 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsystem.h */ -/* */ -/* FreeType low-level system interface definition (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTSYSTEM_H__ -#define __FTSYSTEM_H__ - - -#include <ft2build.h> - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* system_interface */ - /* */ - /* <Title> */ - /* System Interface */ - /* */ - /* <Abstract> */ - /* How FreeType manages memory and i/o. */ - /* */ - /* <Description> */ - /* This section contains various definitions related to memory */ - /* management and i/o access. You need to understand this */ - /* information if you want to use a custom memory manager or you own */ - /* i/o streams. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* M E M O R Y M A N A G E M E N T */ - /* */ - /*************************************************************************/ - - - /************************************************************************* - * - * @type: - * FT_Memory - * - * @description: - * A handle to a given memory manager object, defined with an - * @FT_MemoryRec structure. - * - */ - typedef struct FT_MemoryRec_* FT_Memory; - - - /************************************************************************* - * - * @functype: - * FT_Alloc_Func - * - * @description: - * A function used to allocate `size' bytes from `memory'. - * - * @input: - * memory :: - * A handle to the source memory manager. - * - * size :: - * The size in bytes to allocate. - * - * @return: - * Address of new memory block. 0~in case of failure. - * - */ - typedef void* - (*FT_Alloc_Func)( FT_Memory memory, - long size ); - - - /************************************************************************* - * - * @functype: - * FT_Free_Func - * - * @description: - * A function used to release a given block of memory. - * - * @input: - * memory :: - * A handle to the source memory manager. - * - * block :: - * The address of the target memory block. - * - */ - typedef void - (*FT_Free_Func)( FT_Memory memory, - void* block ); - - - /************************************************************************* - * - * @functype: - * FT_Realloc_Func - * - * @description: - * A function used to re-allocate a given block of memory. - * - * @input: - * memory :: - * A handle to the source memory manager. - * - * cur_size :: - * The block's current size in bytes. - * - * new_size :: - * The block's requested new size. - * - * block :: - * The block's current address. - * - * @return: - * New block address. 0~in case of memory shortage. - * - * @note: - * In case of error, the old block must still be available. - * - */ - typedef void* - (*FT_Realloc_Func)( FT_Memory memory, - long cur_size, - long new_size, - void* block ); - - - /************************************************************************* - * - * @struct: - * FT_MemoryRec - * - * @description: - * A structure used to describe a given memory manager to FreeType~2. - * - * @fields: - * user :: - * A generic typeless pointer for user data. - * - * alloc :: - * A pointer type to an allocation function. - * - * free :: - * A pointer type to an memory freeing function. - * - * realloc :: - * A pointer type to a reallocation function. - * - */ - struct FT_MemoryRec_ - { - void* user; - FT_Alloc_Func alloc; - FT_Free_Func free; - FT_Realloc_Func realloc; - }; - - - /*************************************************************************/ - /* */ - /* I / O M A N A G E M E N T */ - /* */ - /*************************************************************************/ - - - /************************************************************************* - * - * @type: - * FT_Stream - * - * @description: - * A handle to an input stream. - * - * @also: - * See @FT_StreamRec for the publicly accessible fields of a given - * stream object. - * - */ - typedef struct FT_StreamRec_* FT_Stream; - - - /************************************************************************* - * - * @struct: - * FT_StreamDesc - * - * @description: - * A union type used to store either a long or a pointer. This is used - * to store a file descriptor or a `FILE*' in an input stream. - * - */ - typedef union FT_StreamDesc_ - { - long value; - void* pointer; - - } FT_StreamDesc; - - - /************************************************************************* - * - * @functype: - * FT_Stream_IoFunc - * - * @description: - * A function used to seek and read data from a given input stream. - * - * @input: - * stream :: - * A handle to the source stream. - * - * offset :: - * The offset of read in stream (always from start). - * - * buffer :: - * The address of the read buffer. - * - * count :: - * The number of bytes to read from the stream. - * - * @return: - * The number of bytes effectively read by the stream. - * - * @note: - * This function might be called to perform a seek or skip operation - * with a `count' of~0. A non-zero return value then indicates an - * error. - * - */ - typedef unsigned long - (*FT_Stream_IoFunc)( FT_Stream stream, - unsigned long offset, - unsigned char* buffer, - unsigned long count ); - - - /************************************************************************* - * - * @functype: - * FT_Stream_CloseFunc - * - * @description: - * A function used to close a given input stream. - * - * @input: - * stream :: - * A handle to the target stream. - * - */ - typedef void - (*FT_Stream_CloseFunc)( FT_Stream stream ); - - - /************************************************************************* - * - * @struct: - * FT_StreamRec - * - * @description: - * A structure used to describe an input stream. - * - * @input: - * base :: - * For memory-based streams, this is the address of the first stream - * byte in memory. This field should always be set to NULL for - * disk-based streams. - * - * size :: - * The stream size in bytes. - * - * In case of compressed streams where the size is unknown before - * actually doing the decompression, the value is set to 0x7FFFFFFF. - * (Note that this size value can occur for normal streams also; it is - * thus just a hint.) - * - * pos :: - * The current position within the stream. - * - * descriptor :: - * This field is a union that can hold an integer or a pointer. It is - * used by stream implementations to store file descriptors or `FILE*' - * pointers. - * - * pathname :: - * This field is completely ignored by FreeType. However, it is often - * useful during debugging to use it to store the stream's filename - * (where available). - * - * read :: - * The stream's input function. - * - * close :: - * The stream's close function. - * - * memory :: - * The memory manager to use to preload frames. This is set - * internally by FreeType and shouldn't be touched by stream - * implementations. - * - * cursor :: - * This field is set and used internally by FreeType when parsing - * frames. - * - * limit :: - * This field is set and used internally by FreeType when parsing - * frames. - * - */ - typedef struct FT_StreamRec_ - { - unsigned char* base; - unsigned long size; - unsigned long pos; - - FT_StreamDesc descriptor; - FT_StreamDesc pathname; - FT_Stream_IoFunc read; - FT_Stream_CloseFunc close; - - FT_Memory memory; - unsigned char* cursor; - unsigned char* limit; - - } FT_StreamRec; - - /* */ - - -FT_END_HEADER - -#endif /* __FTSYSTEM_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/fttrigon.h b/third_party/freetype/include/freetype/fttrigon.h deleted file mode 100644 index 485ec5158744d449b05a9b21ca4b5fe7efcf47f5..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/fttrigon.h +++ /dev/null @@ -1,350 +0,0 @@ -/***************************************************************************/ -/* */ -/* fttrigon.h */ -/* */ -/* FreeType trigonometric functions (specification). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTTRIGON_H__ -#define __FTTRIGON_H__ - -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* computations */ - /* */ - /*************************************************************************/ - - - /************************************************************************* - * - * @type: - * FT_Angle - * - * @description: - * This type is used to model angle values in FreeType. Note that the - * angle is a 16.16 fixed-point value expressed in degrees. - * - */ - typedef FT_Fixed FT_Angle; - - - /************************************************************************* - * - * @macro: - * FT_ANGLE_PI - * - * @description: - * The angle pi expressed in @FT_Angle units. - * - */ -#define FT_ANGLE_PI ( 180L << 16 ) - - - /************************************************************************* - * - * @macro: - * FT_ANGLE_2PI - * - * @description: - * The angle 2*pi expressed in @FT_Angle units. - * - */ -#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 ) - - - /************************************************************************* - * - * @macro: - * FT_ANGLE_PI2 - * - * @description: - * The angle pi/2 expressed in @FT_Angle units. - * - */ -#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 ) - - - /************************************************************************* - * - * @macro: - * FT_ANGLE_PI4 - * - * @description: - * The angle pi/4 expressed in @FT_Angle units. - * - */ -#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 ) - - - /************************************************************************* - * - * @function: - * FT_Sin - * - * @description: - * Return the sinus of a given angle in fixed-point format. - * - * @input: - * angle :: - * The input angle. - * - * @return: - * The sinus value. - * - * @note: - * If you need both the sinus and cosinus for a given angle, use the - * function @FT_Vector_Unit. - * - */ - FT_EXPORT( FT_Fixed ) - FT_Sin( FT_Angle angle ); - - - /************************************************************************* - * - * @function: - * FT_Cos - * - * @description: - * Return the cosinus of a given angle in fixed-point format. - * - * @input: - * angle :: - * The input angle. - * - * @return: - * The cosinus value. - * - * @note: - * If you need both the sinus and cosinus for a given angle, use the - * function @FT_Vector_Unit. - * - */ - FT_EXPORT( FT_Fixed ) - FT_Cos( FT_Angle angle ); - - - /************************************************************************* - * - * @function: - * FT_Tan - * - * @description: - * Return the tangent of a given angle in fixed-point format. - * - * @input: - * angle :: - * The input angle. - * - * @return: - * The tangent value. - * - */ - FT_EXPORT( FT_Fixed ) - FT_Tan( FT_Angle angle ); - - - /************************************************************************* - * - * @function: - * FT_Atan2 - * - * @description: - * Return the arc-tangent corresponding to a given vector (x,y) in - * the 2d plane. - * - * @input: - * x :: - * The horizontal vector coordinate. - * - * y :: - * The vertical vector coordinate. - * - * @return: - * The arc-tangent value (i.e. angle). - * - */ - FT_EXPORT( FT_Angle ) - FT_Atan2( FT_Fixed x, - FT_Fixed y ); - - - /************************************************************************* - * - * @function: - * FT_Angle_Diff - * - * @description: - * Return the difference between two angles. The result is always - * constrained to the ]-PI..PI] interval. - * - * @input: - * angle1 :: - * First angle. - * - * angle2 :: - * Second angle. - * - * @return: - * Constrained value of `value2-value1'. - * - */ - FT_EXPORT( FT_Angle ) - FT_Angle_Diff( FT_Angle angle1, - FT_Angle angle2 ); - - - /************************************************************************* - * - * @function: - * FT_Vector_Unit - * - * @description: - * Return the unit vector corresponding to a given angle. After the - * call, the value of `vec.x' will be `cos(angle)', and the value of - * `vec.y' will be `sin(angle)'. - * - * This function is useful to retrieve both the sinus and cosinus of a - * given angle quickly. - * - * @output: - * vec :: - * The address of target vector. - * - * @input: - * angle :: - * The input angle. - * - */ - FT_EXPORT( void ) - FT_Vector_Unit( FT_Vector* vec, - FT_Angle angle ); - - - /************************************************************************* - * - * @function: - * FT_Vector_Rotate - * - * @description: - * Rotate a vector by a given angle. - * - * @inout: - * vec :: - * The address of target vector. - * - * @input: - * angle :: - * The input angle. - * - */ - FT_EXPORT( void ) - FT_Vector_Rotate( FT_Vector* vec, - FT_Angle angle ); - - - /************************************************************************* - * - * @function: - * FT_Vector_Length - * - * @description: - * Return the length of a given vector. - * - * @input: - * vec :: - * The address of target vector. - * - * @return: - * The vector length, expressed in the same units that the original - * vector coordinates. - * - */ - FT_EXPORT( FT_Fixed ) - FT_Vector_Length( FT_Vector* vec ); - - - /************************************************************************* - * - * @function: - * FT_Vector_Polarize - * - * @description: - * Compute both the length and angle of a given vector. - * - * @input: - * vec :: - * The address of source vector. - * - * @output: - * length :: - * The vector length. - * - * angle :: - * The vector angle. - * - */ - FT_EXPORT( void ) - FT_Vector_Polarize( FT_Vector* vec, - FT_Fixed *length, - FT_Angle *angle ); - - - /************************************************************************* - * - * @function: - * FT_Vector_From_Polar - * - * @description: - * Compute vector coordinates from a length and angle. - * - * @output: - * vec :: - * The address of source vector. - * - * @input: - * length :: - * The vector length. - * - * angle :: - * The vector angle. - * - */ - FT_EXPORT( void ) - FT_Vector_From_Polar( FT_Vector* vec, - FT_Fixed length, - FT_Angle angle ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTTRIGON_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftttdrv.h b/third_party/freetype/include/freetype/ftttdrv.h deleted file mode 100644 index dc0081a0b9620c84e2cb6252b48daa07f668a21b..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftttdrv.h +++ /dev/null @@ -1,310 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftttdrv.h */ -/* */ -/* FreeType API for controlling the TrueType driver */ -/* (specification only). */ -/* */ -/* Copyright 2013-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTTTDRV_H__ -#define __FTTTDRV_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /************************************************************************** - * - * @section: - * tt_driver - * - * @title: - * The TrueType driver - * - * @abstract: - * Controlling the TrueType driver module. - * - * @description: - * While FreeType's TrueType driver doesn't expose API functions by - * itself, it is possible to control its behaviour with @FT_Property_Set - * and @FT_Property_Get. The following lists the available properties - * together with the necessary macros and structures. - * - * The TrueType driver's module name is `truetype'. - * - * We start with a list of definitions, kindly provided by Greg - * Hitchcock. - * - * _Bi-Level_ _Rendering_ - * - * Monochromatic rendering, exclusively used in the early days of - * TrueType by both Apple and Microsoft. Microsoft's GDI interface - * supported hinting of the right-side bearing point, such that the - * advance width could be non-linear. Most often this was done to - * achieve some level of glyph symmetry. To enable reasonable - * performance (e.g., not having to run hinting on all glyphs just to - * get the widths) there was a bit in the head table indicating if the - * side bearing was hinted, and additional tables, `hdmx' and `LTSH', to - * cache hinting widths across multiple sizes and device aspect ratios. - * - * _Font_ _Smoothing_ - * - * Microsoft's GDI implementation of anti-aliasing. Not traditional - * anti-aliasing as the outlines were hinted before the sampling. The - * widths matched the bi-level rendering. - * - * _ClearType_ _Rendering_ - * - * Technique that uses physical subpixels to improve rendering on LCD - * (and other) displays. Because of the higher resolution, many methods - * of improving symmetry in glyphs through hinting the right-side - * bearing were no longer necessary. This lead to what GDI calls - * `natural widths' ClearType, see - * http://www.beatstamm.com/typography/RTRCh4.htm#Sec21. Since hinting - * has extra resolution, most non-linearity went away, but it is still - * possible for hints to change the advance widths in this mode. - * - * _ClearType_ _Compatible_ _Widths_ - * - * One of the earliest challenges with ClearType was allowing the - * implementation in GDI to be selected without requiring all UI and - * documents to reflow. To address this, a compatible method of - * rendering ClearType was added where the font hints are executed once - * to determine the width in bi-level rendering, and then re-run in - * ClearType, with the difference in widths being absorbed in the font - * hints for ClearType (mostly in the white space of hints); see - * http://www.beatstamm.com/typography/RTRCh4.htm#Sec20. Somewhat by - * definition, compatible width ClearType allows for non-linear widths, - * but only when the bi-level version has non-linear widths. - * - * _ClearType_ _Subpixel_ _Positioning_ - * - * One of the nice benefits of ClearType is the ability to more crisply - * display fractional widths; unfortunately, the GDI model of integer - * bitmaps did not support this. However, the WPF and Direct Write - * frameworks do support fractional widths. DWrite calls this `natural - * mode', not to be confused with GDI's `natural widths'. Subpixel - * positioning, in the current implementation of Direct Write, - * unfortunately does not support hinted advance widths, see - * http://www.beatstamm.com/typography/RTRCh4.htm#Sec22. Note that the - * TrueType interpreter fully allows the advance width to be adjusted in - * this mode, just the DWrite client will ignore those changes. - * - * _ClearType_ _Backwards_ _Compatibility_ - * - * This is a set of exceptions made in the TrueType interpreter to - * minimize hinting techniques that were problematic with the extra - * resolution of ClearType; see - * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and - * http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx. - * This technique is not to be confused with ClearType compatible - * widths. ClearType backwards compatibility has no direct impact on - * changing advance widths, but there might be an indirect impact on - * disabling some deltas. This could be worked around in backwards - * compatibility mode. - * - * _Native_ _ClearType_ _Mode_ - * - * (Not to be confused with `natural widths'.) This mode removes all - * the exceptions in the TrueType interpreter when running with - * ClearType. Any issues on widths would still apply, though. - * - */ - - - /************************************************************************** - * - * @property: - * interpreter-version - * - * @description: - * Currently, two versions are available, representing the bytecode - * interpreter with and without subpixel hinting support, - * respectively. The default is subpixel support if - * TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel - * support otherwise (since it isn't available then). - * - * If subpixel hinting is on, many TrueType bytecode instructions behave - * differently compared to B/W or grayscale rendering (except if `native - * ClearType' is selected by the font). The main idea is to render at a - * much increased horizontal resolution, then sampling down the created - * output to subpixel precision. However, many older fonts are not - * suited to this and must be specially taken care of by applying - * (hardcoded) font-specific tweaks. - * - * Details on subpixel hinting and some of the necessary tweaks can be - * found in Greg Hitchcock's whitepaper at - * `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'. - * - * The following example code demonstrates how to activate subpixel - * hinting (omitting the error handling). - * - * { - * FT_Library library; - * FT_Face face; - * FT_UInt interpreter_version = TT_INTERPRETER_VERSION_38; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "truetype", - * "interpreter-version", - * &interpreter_version ); - * } - * - * @note: - * This property can be used with @FT_Property_Get also. - * - */ - - - /************************************************************************** - * - * @enum: - * TT_INTERPRETER_VERSION_XXX - * - * @description: - * A list of constants used for the @interpreter-version property to - * select the hinting engine for Truetype fonts. - * - * The numeric value in the constant names represents the version - * number as returned by the `GETINFO' bytecode instruction. - * - * @values: - * TT_INTERPRETER_VERSION_35 :: - * Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in - * Windows~98; only grayscale and B/W rasterizing is supported. - * - * TT_INTERPRETER_VERSION_38 :: - * Version~38 corresponds to MS rasterizer v.1.9; it is roughly - * equivalent to the hinting provided by DirectWrite ClearType (as - * can be found, for example, in the Internet Explorer~9 running on - * Windows~7). - * - * @note: - * This property controls the behaviour of the bytecode interpreter - * and thus how outlines get hinted. It does *not* control how glyph - * get rasterized! In particular, it does not control subpixel color - * filtering. - * - * If FreeType has not been compiled with configuration option - * FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an - * `FT_Err_Unimplemented_Feature' error. - * - * Depending on the graphics framework, Microsoft uses different - * bytecode and rendering engines. As a consequence, the version - * numbers returned by a call to the `GETINFO' bytecode instruction are - * more convoluted than desired. - * - * Here are two tables that try to shed some light on the possible - * values for the MS rasterizer engine, together with the additional - * features introduced by it. - * - * { - * GETINFO framework version feature - * ------------------------------------------------------------------- - * 3 GDI (Win 3.1), v1.0 16-bit, first version - * TrueImage - * 33 GDI (Win NT 3.1), v1.5 32-bit - * HP Laserjet - * 34 GDI (Win 95) v1.6 font smoothing, - * new SCANTYPE opcode - * 35 GDI (Win 98/2000) v1.7 (UN)SCALED_COMPONENT_OFFSET - * bits in composite glyphs - * 36 MGDI (Win CE 2) v1.6+ classic ClearType - * 37 GDI (XP and later), v1.8 ClearType - * GDI+ old (before Vista) - * 38 GDI+ old (Vista, Win 7), v1.9 subpixel ClearType, - * WPF Y-direction ClearType, - * additional error checking - * 39 DWrite (before Win 8) v2.0 subpixel ClearType flags - * in GETINFO opcode, - * bug fixes - * 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag - * DWrite (Win 8) in GETINFO opcode, - * Gray ClearType - * } - * - * The `version' field gives a rough orientation only, since some - * applications provided certain features much earlier (as an example, - * Microsoft Reader used subpixel and Y-direction ClearType already in - * Windows 2000). Similarly, updates to a given framework might include - * improved hinting support. - * - * { - * version sampling rendering comment - * x y x y - * -------------------------------------------------------------- - * v1.0 normal normal B/W B/W bi-level - * v1.6 high high gray gray grayscale - * v1.8 high normal color-filter B/W (GDI) ClearType - * v1.9 high high color-filter gray Color ClearType - * v2.1 high normal gray B/W Gray ClearType - * v2.1 high high gray gray Gray ClearType - * } - * - * Color and Gray ClearType are the two available variants of - * `Y-direction ClearType', meaning grayscale rasterization along the - * Y-direction; the name used in the TrueType specification for this - * feature is `symmetric smoothing'. `Classic ClearType' is the - * original algorithm used before introducing a modified version in - * Win~XP. Another name for v1.6's grayscale rendering is `font - * smoothing', and `Color ClearType' is sometimes also called `DWrite - * ClearType'. To differentiate between today's Color ClearType and the - * earlier ClearType variant with B/W rendering along the vertical axis, - * the latter is sometimes called `GDI ClearType'. - * - * `Normal' and `high' sampling describe the (virtual) resolution to - * access the rasterized outline after the hinting process. `Normal' - * means 1 sample per grid line (i.e., B/W). In the current Microsoft - * implementation, `high' means an extra virtual resolution of 16x16 (or - * 16x1) grid lines per pixel for bytecode instructions like `MIRP'. - * After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid - * lines for color filtering if Color ClearType is activated. - * - * Note that `Gray ClearType' is essentially the same as v1.6's - * grayscale rendering. However, the GETINFO instruction handles it - * differently: v1.6 returns bit~12 (hinting for grayscale), while v2.1 - * returns bits~13 (hinting for ClearType), 18 (symmetrical smoothing), - * and~19 (Gray ClearType). Also, this mode respects bits 2 and~3 for - * the version~1 gasp table exclusively (like Color ClearType), while - * v1.6 only respects the values of version~0 (bits 0 and~1). - * - * FreeType doesn't provide all capabilities of the most recent - * ClearType incarnation, thus we identify our subpixel support as - * version~38. - * - */ -#define TT_INTERPRETER_VERSION_35 35 -#define TT_INTERPRETER_VERSION_38 38 - - /* */ - - -FT_END_HEADER - - -#endif /* __FTTTDRV_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/fttypes.h b/third_party/freetype/include/freetype/fttypes.h deleted file mode 100644 index 706a1be4ef9fdbd0a494e987cdedefb0dd626c9d..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/fttypes.h +++ /dev/null @@ -1,602 +0,0 @@ -/***************************************************************************/ -/* */ -/* fttypes.h */ -/* */ -/* FreeType simple types definitions (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTTYPES_H__ -#define __FTTYPES_H__ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_SYSTEM_H -#include FT_IMAGE_H - -#include <stddef.h> - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* basic_types */ - /* */ - /* <Title> */ - /* Basic Data Types */ - /* */ - /* <Abstract> */ - /* The basic data types defined by the library. */ - /* */ - /* <Description> */ - /* This section contains the basic data types defined by FreeType~2, */ - /* ranging from simple scalar types to bitmap descriptors. More */ - /* font-specific structures are defined in a different section. */ - /* */ - /* <Order> */ - /* FT_Byte */ - /* FT_Bytes */ - /* FT_Char */ - /* FT_Int */ - /* FT_UInt */ - /* FT_Int16 */ - /* FT_UInt16 */ - /* FT_Int32 */ - /* FT_UInt32 */ - /* FT_Int64 */ - /* FT_UInt64 */ - /* FT_Short */ - /* FT_UShort */ - /* FT_Long */ - /* FT_ULong */ - /* FT_Bool */ - /* FT_Offset */ - /* FT_PtrDist */ - /* FT_String */ - /* FT_Tag */ - /* FT_Error */ - /* FT_Fixed */ - /* FT_Pointer */ - /* FT_Pos */ - /* FT_Vector */ - /* FT_BBox */ - /* FT_Matrix */ - /* FT_FWord */ - /* FT_UFWord */ - /* FT_F2Dot14 */ - /* FT_UnitVector */ - /* FT_F26Dot6 */ - /* FT_Data */ - /* */ - /* FT_MAKE_TAG */ - /* */ - /* FT_Generic */ - /* FT_Generic_Finalizer */ - /* */ - /* FT_Bitmap */ - /* FT_Pixel_Mode */ - /* FT_Palette_Mode */ - /* FT_Glyph_Format */ - /* FT_IMAGE_TAG */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Bool */ - /* */ - /* <Description> */ - /* A typedef of unsigned char, used for simple booleans. As usual, */ - /* values 1 and~0 represent true and false, respectively. */ - /* */ - typedef unsigned char FT_Bool; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_FWord */ - /* */ - /* <Description> */ - /* A signed 16-bit integer used to store a distance in original font */ - /* units. */ - /* */ - typedef signed short FT_FWord; /* distance in FUnits */ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_UFWord */ - /* */ - /* <Description> */ - /* An unsigned 16-bit integer used to store a distance in original */ - /* font units. */ - /* */ - typedef unsigned short FT_UFWord; /* unsigned distance */ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Char */ - /* */ - /* <Description> */ - /* A simple typedef for the _signed_ char type. */ - /* */ - typedef signed char FT_Char; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Byte */ - /* */ - /* <Description> */ - /* A simple typedef for the _unsigned_ char type. */ - /* */ - typedef unsigned char FT_Byte; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Bytes */ - /* */ - /* <Description> */ - /* A typedef for constant memory areas. */ - /* */ - typedef const FT_Byte* FT_Bytes; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Tag */ - /* */ - /* <Description> */ - /* A typedef for 32-bit tags (as used in the SFNT format). */ - /* */ - typedef FT_UInt32 FT_Tag; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_String */ - /* */ - /* <Description> */ - /* A simple typedef for the char type, usually used for strings. */ - /* */ - typedef char FT_String; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Short */ - /* */ - /* <Description> */ - /* A typedef for signed short. */ - /* */ - typedef signed short FT_Short; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_UShort */ - /* */ - /* <Description> */ - /* A typedef for unsigned short. */ - /* */ - typedef unsigned short FT_UShort; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Int */ - /* */ - /* <Description> */ - /* A typedef for the int type. */ - /* */ - typedef signed int FT_Int; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_UInt */ - /* */ - /* <Description> */ - /* A typedef for the unsigned int type. */ - /* */ - typedef unsigned int FT_UInt; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Long */ - /* */ - /* <Description> */ - /* A typedef for signed long. */ - /* */ - typedef signed long FT_Long; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_ULong */ - /* */ - /* <Description> */ - /* A typedef for unsigned long. */ - /* */ - typedef unsigned long FT_ULong; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_F2Dot14 */ - /* */ - /* <Description> */ - /* A signed 2.14 fixed-point type used for unit vectors. */ - /* */ - typedef signed short FT_F2Dot14; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_F26Dot6 */ - /* */ - /* <Description> */ - /* A signed 26.6 fixed-point type used for vectorial pixel */ - /* coordinates. */ - /* */ - typedef signed long FT_F26Dot6; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Fixed */ - /* */ - /* <Description> */ - /* This type is used to store 16.16 fixed-point values, like scaling */ - /* values or matrix coefficients. */ - /* */ - typedef signed long FT_Fixed; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Error */ - /* */ - /* <Description> */ - /* The FreeType error code type. A value of~0 is always interpreted */ - /* as a successful operation. */ - /* */ - typedef int FT_Error; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Pointer */ - /* */ - /* <Description> */ - /* A simple typedef for a typeless pointer. */ - /* */ - typedef void* FT_Pointer; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_Offset */ - /* */ - /* <Description> */ - /* This is equivalent to the ANSI~C `size_t' type, i.e., the largest */ - /* _unsigned_ integer type used to express a file size or position, */ - /* or a memory block size. */ - /* */ - typedef size_t FT_Offset; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_PtrDist */ - /* */ - /* <Description> */ - /* This is equivalent to the ANSI~C `ptrdiff_t' type, i.e., the */ - /* largest _signed_ integer type used to express the distance */ - /* between two pointers. */ - /* */ - typedef ft_ptrdiff_t FT_PtrDist; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_UnitVector */ - /* */ - /* <Description> */ - /* A simple structure used to store a 2D vector unit vector. Uses */ - /* FT_F2Dot14 types. */ - /* */ - /* <Fields> */ - /* x :: Horizontal coordinate. */ - /* */ - /* y :: Vertical coordinate. */ - /* */ - typedef struct FT_UnitVector_ - { - FT_F2Dot14 x; - FT_F2Dot14 y; - - } FT_UnitVector; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Matrix */ - /* */ - /* <Description> */ - /* A simple structure used to store a 2x2 matrix. Coefficients are */ - /* in 16.16 fixed-point format. The computation performed is: */ - /* */ - /* { */ - /* x' = x*xx + y*xy */ - /* y' = x*yx + y*yy */ - /* } */ - /* */ - /* <Fields> */ - /* xx :: Matrix coefficient. */ - /* */ - /* xy :: Matrix coefficient. */ - /* */ - /* yx :: Matrix coefficient. */ - /* */ - /* yy :: Matrix coefficient. */ - /* */ - typedef struct FT_Matrix_ - { - FT_Fixed xx, xy; - FT_Fixed yx, yy; - - } FT_Matrix; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Data */ - /* */ - /* <Description> */ - /* Read-only binary data represented as a pointer and a length. */ - /* */ - /* <Fields> */ - /* pointer :: The data. */ - /* */ - /* length :: The length of the data in bytes. */ - /* */ - typedef struct FT_Data_ - { - const FT_Byte* pointer; - FT_Int length; - - } FT_Data; - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Generic_Finalizer */ - /* */ - /* <Description> */ - /* Describe a function used to destroy the `client' data of any */ - /* FreeType object. See the description of the @FT_Generic type for */ - /* details of usage. */ - /* */ - /* <Input> */ - /* The address of the FreeType object that is under finalization. */ - /* Its client data is accessed through its `generic' field. */ - /* */ - typedef void (*FT_Generic_Finalizer)(void* object); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Generic */ - /* */ - /* <Description> */ - /* Client applications often need to associate their own data to a */ - /* variety of FreeType core objects. For example, a text layout API */ - /* might want to associate a glyph cache to a given size object. */ - /* */ - /* Some FreeType object contains a `generic' field, of type */ - /* FT_Generic, which usage is left to client applications and font */ - /* servers. */ - /* */ - /* It can be used to store a pointer to client-specific data, as well */ - /* as the address of a `finalizer' function, which will be called by */ - /* FreeType when the object is destroyed (for example, the previous */ - /* client example would put the address of the glyph cache destructor */ - /* in the `finalizer' field). */ - /* */ - /* <Fields> */ - /* data :: A typeless pointer to any client-specified data. This */ - /* field is completely ignored by the FreeType library. */ - /* */ - /* finalizer :: A pointer to a `generic finalizer' function, which */ - /* will be called when the object is destroyed. If this */ - /* field is set to NULL, no code will be called. */ - /* */ - typedef struct FT_Generic_ - { - void* data; - FT_Generic_Finalizer finalizer; - - } FT_Generic; - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_MAKE_TAG */ - /* */ - /* <Description> */ - /* This macro converts four-letter tags that are used to label */ - /* TrueType tables into an unsigned long, to be used within FreeType. */ - /* */ - /* <Note> */ - /* The produced values *must* be 32-bit integers. Don't redefine */ - /* this macro. */ - /* */ -#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ - (FT_Tag) \ - ( ( (FT_ULong)_x1 << 24 ) | \ - ( (FT_ULong)_x2 << 16 ) | \ - ( (FT_ULong)_x3 << 8 ) | \ - (FT_ULong)_x4 ) - - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* L I S T M A N A G E M E N T */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* list_processing */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_ListNode */ - /* */ - /* <Description> */ - /* Many elements and objects in FreeType are listed through an */ - /* @FT_List record (see @FT_ListRec). As its name suggests, an */ - /* FT_ListNode is a handle to a single list element. */ - /* */ - typedef struct FT_ListNodeRec_* FT_ListNode; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* FT_List */ - /* */ - /* <Description> */ - /* A handle to a list record (see @FT_ListRec). */ - /* */ - typedef struct FT_ListRec_* FT_List; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_ListNodeRec */ - /* */ - /* <Description> */ - /* A structure used to hold a single list element. */ - /* */ - /* <Fields> */ - /* prev :: The previous element in the list. NULL if first. */ - /* */ - /* next :: The next element in the list. NULL if last. */ - /* */ - /* data :: A typeless pointer to the listed object. */ - /* */ - typedef struct FT_ListNodeRec_ - { - FT_ListNode prev; - FT_ListNode next; - void* data; - - } FT_ListNodeRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_ListRec */ - /* */ - /* <Description> */ - /* A structure used to hold a simple doubly-linked list. These are */ - /* used in many parts of FreeType. */ - /* */ - /* <Fields> */ - /* head :: The head (first element) of doubly-linked list. */ - /* */ - /* tail :: The tail (last element) of doubly-linked list. */ - /* */ - typedef struct FT_ListRec_ - { - FT_ListNode head; - FT_ListNode tail; - - } FT_ListRec; - - /* */ - - -#define FT_IS_EMPTY( list ) ( (list).head == 0 ) -#define FT_BOOL( x ) ( (FT_Bool)( x ) ) - - /* concatenate C tokens */ -#define FT_ERR_XCAT( x, y ) x ## y -#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) - - /* see `ftmoderr.h' for descriptions of the following macros */ - -#define FT_ERR( e ) FT_ERR_CAT( FT_ERR_PREFIX, e ) - -#define FT_ERROR_BASE( x ) ( (x) & 0xFF ) -#define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U ) - -#define FT_ERR_EQ( x, e ) \ - ( FT_ERROR_BASE( x ) == FT_ERROR_BASE( FT_ERR( e ) ) ) -#define FT_ERR_NEQ( x, e ) \ - ( FT_ERROR_BASE( x ) != FT_ERROR_BASE( FT_ERR( e ) ) ) - - -FT_END_HEADER - -#endif /* __FTTYPES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ftwinfnt.h b/third_party/freetype/include/freetype/ftwinfnt.h deleted file mode 100644 index caedaa1cc76649486d8bca7144df2571d0fbd9b4..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ftwinfnt.h +++ /dev/null @@ -1,275 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftwinfnt.h */ -/* */ -/* FreeType API for accessing Windows fnt-specific data. */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTWINFNT_H__ -#define __FTWINFNT_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* winfnt_fonts */ - /* */ - /* <Title> */ - /* Window FNT Files */ - /* */ - /* <Abstract> */ - /* Windows FNT specific API. */ - /* */ - /* <Description> */ - /* This section contains the declaration of Windows FNT specific */ - /* functions. */ - /* */ - /*************************************************************************/ - - - /************************************************************************* - * - * @enum: - * FT_WinFNT_ID_XXX - * - * @description: - * A list of valid values for the `charset' byte in - * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX - * encodings (except for cp1361) can be found at - * ftp://ftp.unicode.org/Public in the MAPPINGS/VENDORS/MICSFT/WINDOWS - * subdirectory. cp1361 is roughly a superset of - * MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT. - * - * @values: - * FT_WinFNT_ID_DEFAULT :: - * This is used for font enumeration and font creation as a - * `don't care' value. Valid font files don't contain this value. - * When querying for information about the character set of the font - * that is currently selected into a specified device context, this - * return value (of the related Windows API) simply denotes failure. - * - * FT_WinFNT_ID_SYMBOL :: - * There is no known mapping table available. - * - * FT_WinFNT_ID_MAC :: - * Mac Roman encoding. - * - * FT_WinFNT_ID_OEM :: - * From Michael Pöttgen <michael@poettgen.de>: - * - * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM - * is used for the charset of vector fonts, like `modern.fon', - * `roman.fon', and `script.fon' on Windows. - * - * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value - * specifies a character set that is operating-system dependent. - * - * The `IFIMETRICS' documentation from the `Windows Driver - * Development Kit' says: This font supports an OEM-specific - * character set. The OEM character set is system dependent. - * - * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the - * second default codepage that most international versions of - * Windows have. It is one of the OEM codepages from - * - * https://msdn.microsoft.com/en-us/goglobal/bb964655, - * - * and is used for the `DOS boxes', to support legacy applications. - * A German Windows version for example usually uses ANSI codepage - * 1252 and OEM codepage 850. - * - * FT_WinFNT_ID_CP874 :: - * A superset of Thai TIS 620 and ISO 8859-11. - * - * FT_WinFNT_ID_CP932 :: - * A superset of Japanese Shift-JIS (with minor deviations). - * - * FT_WinFNT_ID_CP936 :: - * A superset of simplified Chinese GB 2312-1980 (with different - * ordering and minor deviations). - * - * FT_WinFNT_ID_CP949 :: - * A superset of Korean Hangul KS~C 5601-1987 (with different - * ordering and minor deviations). - * - * FT_WinFNT_ID_CP950 :: - * A superset of traditional Chinese Big~5 ETen (with different - * ordering and minor deviations). - * - * FT_WinFNT_ID_CP1250 :: - * A superset of East European ISO 8859-2 (with slightly different - * ordering). - * - * FT_WinFNT_ID_CP1251 :: - * A superset of Russian ISO 8859-5 (with different ordering). - * - * FT_WinFNT_ID_CP1252 :: - * ANSI encoding. A superset of ISO 8859-1. - * - * FT_WinFNT_ID_CP1253 :: - * A superset of Greek ISO 8859-7 (with minor modifications). - * - * FT_WinFNT_ID_CP1254 :: - * A superset of Turkish ISO 8859-9. - * - * FT_WinFNT_ID_CP1255 :: - * A superset of Hebrew ISO 8859-8 (with some modifications). - * - * FT_WinFNT_ID_CP1256 :: - * A superset of Arabic ISO 8859-6 (with different ordering). - * - * FT_WinFNT_ID_CP1257 :: - * A superset of Baltic ISO 8859-13 (with some deviations). - * - * FT_WinFNT_ID_CP1258 :: - * For Vietnamese. This encoding doesn't cover all necessary - * characters. - * - * FT_WinFNT_ID_CP1361 :: - * Korean (Johab). - */ - -#define FT_WinFNT_ID_CP1252 0 -#define FT_WinFNT_ID_DEFAULT 1 -#define FT_WinFNT_ID_SYMBOL 2 -#define FT_WinFNT_ID_MAC 77 -#define FT_WinFNT_ID_CP932 128 -#define FT_WinFNT_ID_CP949 129 -#define FT_WinFNT_ID_CP1361 130 -#define FT_WinFNT_ID_CP936 134 -#define FT_WinFNT_ID_CP950 136 -#define FT_WinFNT_ID_CP1253 161 -#define FT_WinFNT_ID_CP1254 162 -#define FT_WinFNT_ID_CP1258 163 -#define FT_WinFNT_ID_CP1255 177 -#define FT_WinFNT_ID_CP1256 178 -#define FT_WinFNT_ID_CP1257 186 -#define FT_WinFNT_ID_CP1251 204 -#define FT_WinFNT_ID_CP874 222 -#define FT_WinFNT_ID_CP1250 238 -#define FT_WinFNT_ID_OEM 255 - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_WinFNT_HeaderRec */ - /* */ - /* <Description> */ - /* Windows FNT Header info. */ - /* */ - typedef struct FT_WinFNT_HeaderRec_ - { - FT_UShort version; - FT_ULong file_size; - FT_Byte copyright[60]; - FT_UShort file_type; - FT_UShort nominal_point_size; - FT_UShort vertical_resolution; - FT_UShort horizontal_resolution; - FT_UShort ascent; - FT_UShort internal_leading; - FT_UShort external_leading; - FT_Byte italic; - FT_Byte underline; - FT_Byte strike_out; - FT_UShort weight; - FT_Byte charset; - FT_UShort pixel_width; - FT_UShort pixel_height; - FT_Byte pitch_and_family; - FT_UShort avg_width; - FT_UShort max_width; - FT_Byte first_char; - FT_Byte last_char; - FT_Byte default_char; - FT_Byte break_char; - FT_UShort bytes_per_row; - FT_ULong device_offset; - FT_ULong face_name_offset; - FT_ULong bits_pointer; - FT_ULong bits_offset; - FT_Byte reserved; - FT_ULong flags; - FT_UShort A_space; - FT_UShort B_space; - FT_UShort C_space; - FT_UShort color_table_offset; - FT_ULong reserved1[4]; - - } FT_WinFNT_HeaderRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_WinFNT_Header */ - /* */ - /* <Description> */ - /* A handle to an @FT_WinFNT_HeaderRec structure. */ - /* */ - typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header; - - - /********************************************************************** - * - * @function: - * FT_Get_WinFNT_Header - * - * @description: - * Retrieve a Windows FNT font info header. - * - * @input: - * face :: A handle to the input face. - * - * @output: - * aheader :: The WinFNT header. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * This function only works with Windows FNT faces, returning an error - * otherwise. - */ - FT_EXPORT( FT_Error ) - FT_Get_WinFNT_Header( FT_Face face, - FT_WinFNT_HeaderRec *aheader ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTWINFNT_H__ */ - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/include/freetype/internal/autohint.h b/third_party/freetype/include/freetype/internal/autohint.h deleted file mode 100644 index 8d5a9773cb54a49bb96089b52e17a4aa58575815..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/autohint.h +++ /dev/null @@ -1,244 +0,0 @@ -/***************************************************************************/ -/* */ -/* autohint.h */ -/* */ -/* High-level `autohint' module-specific interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* The auto-hinter is used to load and automatically hint glyphs if a */ - /* format-specific hinter isn't available. */ - /* */ - /*************************************************************************/ - - -#ifndef __AUTOHINT_H__ -#define __AUTOHINT_H__ - - - /*************************************************************************/ - /* */ - /* A small technical note regarding automatic hinting in order to */ - /* clarify this module interface. */ - /* */ - /* An automatic hinter might compute two kinds of data for a given face: */ - /* */ - /* - global hints: Usually some metrics that describe global properties */ - /* of the face. It is computed by scanning more or less */ - /* aggressively the glyphs in the face, and thus can be */ - /* very slow to compute (even if the size of global */ - /* hints is really small). */ - /* */ - /* - glyph hints: These describe some important features of the glyph */ - /* outline, as well as how to align them. They are */ - /* generally much faster to compute than global hints. */ - /* */ - /* The current FreeType auto-hinter does a pretty good job while */ - /* performing fast computations for both global and glyph hints. */ - /* However, we might be interested in introducing more complex and */ - /* powerful algorithms in the future, like the one described in the John */ - /* D. Hobby paper, which unfortunately requires a lot more horsepower. */ - /* */ - /* Because a sufficiently sophisticated font management system would */ - /* typically implement an LRU cache of opened face objects to reduce */ - /* memory usage, it is a good idea to be able to avoid recomputing */ - /* global hints every time the same face is re-opened. */ - /* */ - /* We thus provide the ability to cache global hints outside of the face */ - /* object, in order to speed up font re-opening time. Of course, this */ - /* feature is purely optional, so most client programs won't even notice */ - /* it. */ - /* */ - /* I initially thought that it would be a good idea to cache the glyph */ - /* hints too. However, my general idea now is that if you really need */ - /* to cache these too, you are simply in need of a new font format, */ - /* where all this information could be stored within the font file and */ - /* decoded on the fly. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H - - -FT_BEGIN_HEADER - - - typedef struct FT_AutoHinterRec_ *FT_AutoHinter; - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_AutoHinter_GlobalGetFunc */ - /* */ - /* <Description> */ - /* Retrieve the global hints computed for a given face object. The */ - /* resulting data is dissociated from the face and will survive a */ - /* call to FT_Done_Face(). It must be discarded through the API */ - /* FT_AutoHinter_GlobalDoneFunc(). */ - /* */ - /* <Input> */ - /* hinter :: A handle to the source auto-hinter. */ - /* */ - /* face :: A handle to the source face object. */ - /* */ - /* <Output> */ - /* global_hints :: A typeless pointer to the global hints. */ - /* */ - /* global_len :: The size in bytes of the global hints. */ - /* */ - typedef void - (*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter hinter, - FT_Face face, - void** global_hints, - long* global_len ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_AutoHinter_GlobalDoneFunc */ - /* */ - /* <Description> */ - /* Discard the global hints retrieved through */ - /* FT_AutoHinter_GlobalGetFunc(). This is the only way these hints */ - /* are freed from memory. */ - /* */ - /* <Input> */ - /* hinter :: A handle to the auto-hinter module. */ - /* */ - /* global :: A pointer to retrieved global hints to discard. */ - /* */ - typedef void - (*FT_AutoHinter_GlobalDoneFunc)( FT_AutoHinter hinter, - void* global ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_AutoHinter_GlobalResetFunc */ - /* */ - /* <Description> */ - /* This function is used to recompute the global metrics in a given */ - /* font. This is useful when global font data changes (e.g. Multiple */ - /* Masters fonts where blend coordinates change). */ - /* */ - /* <Input> */ - /* hinter :: A handle to the source auto-hinter. */ - /* */ - /* face :: A handle to the face. */ - /* */ - typedef void - (*FT_AutoHinter_GlobalResetFunc)( FT_AutoHinter hinter, - FT_Face face ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_AutoHinter_GlyphLoadFunc */ - /* */ - /* <Description> */ - /* This function is used to load, scale, and automatically hint a */ - /* glyph from a given face. */ - /* */ - /* <Input> */ - /* face :: A handle to the face. */ - /* */ - /* glyph_index :: The glyph index. */ - /* */ - /* load_flags :: The load flags. */ - /* */ - /* <Note> */ - /* This function is capable of loading composite glyphs by hinting */ - /* each sub-glyph independently (which improves quality). */ - /* */ - /* It will call the font driver with @FT_Load_Glyph, with */ - /* @FT_LOAD_NO_SCALE set. */ - /* */ - typedef FT_Error - (*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter hinter, - FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_AutoHinter_InterfaceRec */ - /* */ - /* <Description> */ - /* The auto-hinter module's interface. */ - /* */ - typedef struct FT_AutoHinter_InterfaceRec_ - { - FT_AutoHinter_GlobalResetFunc reset_face; - FT_AutoHinter_GlobalGetFunc get_global_hints; - FT_AutoHinter_GlobalDoneFunc done_global_hints; - FT_AutoHinter_GlyphLoadFunc load_glyph; - - } FT_AutoHinter_InterfaceRec, *FT_AutoHinter_Interface; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_AUTOHINTER_INTERFACE( \ - class_, \ - reset_face_, \ - get_global_hints_, \ - done_global_hints_, \ - load_glyph_ ) \ - FT_CALLBACK_TABLE_DEF \ - const FT_AutoHinter_InterfaceRec class_ = \ - { \ - reset_face_, \ - get_global_hints_, \ - done_global_hints_, \ - load_glyph_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_AUTOHINTER_INTERFACE( \ - class_, \ - reset_face_, \ - get_global_hints_, \ - done_global_hints_, \ - load_glyph_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_AutoHinter_InterfaceRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->reset_face = reset_face_; \ - clazz->get_global_hints = get_global_hints_; \ - clazz->done_global_hints = done_global_hints_; \ - clazz->load_glyph = load_glyph_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - -FT_END_HEADER - -#endif /* __AUTOHINT_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftcalc.h b/third_party/freetype/include/freetype/internal/ftcalc.h deleted file mode 100644 index 67ade7e5f947c986315eb2b8c3ccbd3bbb00c4be..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftcalc.h +++ /dev/null @@ -1,418 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftcalc.h */ -/* */ -/* Arithmetic computations (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTCALC_H__ -#define __FTCALC_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ - /* */ - /*************************************************************************/ - -#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER - /* Provide assembler fragments for performance-critical functions. */ - /* These must be defined `static __inline__' with GCC. */ - -#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ - -#define FT_MULFIX_ASSEMBLER FT_MulFix_arm - - /* documentation is in freetype.h */ - - static __inline FT_Int32 - FT_MulFix_arm( FT_Int32 a, - FT_Int32 b ) - { - register FT_Int32 t, t2; - - - __asm - { - smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ - mov a, t, asr #31 /* a = (hi >> 31) */ - add a, a, #0x8000 /* a += 0x8000 */ - adds t2, t2, a /* t2 += a */ - adc t, t, #0 /* t += carry */ - mov a, t2, lsr #16 /* a = t2 >> 16 */ - orr a, a, t, lsl #16 /* a |= t << 16 */ - } - return a; - } - -#endif /* __CC_ARM || __ARMCC__ */ - - -#ifdef __GNUC__ - -#if defined( __arm__ ) && \ - ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ - !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) - -#define FT_MULFIX_ASSEMBLER FT_MulFix_arm - - /* documentation is in freetype.h */ - - static __inline__ FT_Int32 - FT_MulFix_arm( FT_Int32 a, - FT_Int32 b ) - { - register FT_Int32 t, t2; - - - __asm__ __volatile__ ( - "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ - "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ -#if defined( __clang__ ) && defined( __thumb2__ ) - "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ -#else - "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ -#endif - "adds %1, %1, %0\n\t" /* %1 += %0 */ - "adc %2, %2, #0\n\t" /* %2 += carry */ - "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ - "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ - : "=r"(a), "=&r"(t2), "=&r"(t) - : "r"(a), "r"(b) - : "cc" ); - return a; - } - -#endif /* __arm__ && */ - /* ( __thumb2__ || !__thumb__ ) && */ - /* !( __CC_ARM || __ARMCC__ ) */ - - -#if defined( __i386__ ) - -#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 - - /* documentation is in freetype.h */ - - static __inline__ FT_Int32 - FT_MulFix_i386( FT_Int32 a, - FT_Int32 b ) - { - register FT_Int32 result; - - - __asm__ __volatile__ ( - "imul %%edx\n" - "movl %%edx, %%ecx\n" - "sarl $31, %%ecx\n" - "addl $0x8000, %%ecx\n" - "addl %%ecx, %%eax\n" - "adcl $0, %%edx\n" - "shrl $16, %%eax\n" - "shll $16, %%edx\n" - "addl %%edx, %%eax\n" - : "=a"(result), "=d"(b) - : "a"(a), "d"(b) - : "%ecx", "cc" ); - return result; - } - -#endif /* i386 */ - -#endif /* __GNUC__ */ - - -#ifdef _MSC_VER /* Visual C++ */ - -#ifdef _M_IX86 - -#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 - - /* documentation is in freetype.h */ - - static __inline FT_Int32 - FT_MulFix_i386( FT_Int32 a, - FT_Int32 b ) - { - register FT_Int32 result; - - __asm - { - mov eax, a - mov edx, b - imul edx - mov ecx, edx - sar ecx, 31 - add ecx, 8000h - add eax, ecx - adc edx, 0 - shr eax, 16 - shl edx, 16 - add eax, edx - mov result, eax - } - return result; - } - -#endif /* _M_IX86 */ - -#endif /* _MSC_VER */ - - -#if defined( __GNUC__ ) && defined( __x86_64__ ) - -#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 - - static __inline__ FT_Int32 - FT_MulFix_x86_64( FT_Int32 a, - FT_Int32 b ) - { - /* Temporarily disable the warning that C90 doesn't support */ - /* `long long'. */ -#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlong-long" -#endif - -#if 1 - /* Technically not an assembly fragment, but GCC does a really good */ - /* job at inlining it and generating good machine code for it. */ - long long ret, tmp; - - - ret = (long long)a * b; - tmp = ret >> 63; - ret += 0x8000 + tmp; - - return (FT_Int32)( ret >> 16 ); -#else - - /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ - /* code from the lines below. The main issue is that `wide_a' is not */ - /* properly initialized by sign-extending `a'. Instead, the generated */ - /* machine code assumes that the register that contains `a' on input */ - /* can be used directly as a 64-bit value, which is wrong most of the */ - /* time. */ - long long wide_a = (long long)a; - long long wide_b = (long long)b; - long long result; - - - __asm__ __volatile__ ( - "imul %2, %1\n" - "mov %1, %0\n" - "sar $63, %0\n" - "lea 0x8000(%1, %0), %0\n" - "sar $16, %0\n" - : "=&r"(result), "=&r"(wide_a) - : "r"(wide_b) - : "cc" ); - - return (FT_Int32)result; -#endif - -#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 ) -#pragma GCC diagnostic pop -#endif - } - -#endif /* __GNUC__ && __x86_64__ */ - -#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ - - -#ifdef FT_CONFIG_OPTION_INLINE_MULFIX -#ifdef FT_MULFIX_ASSEMBLER -#define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) ) -#endif -#endif - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_MulDiv_No_Round */ - /* */ - /* <Description> */ - /* A very simple function used to perform the computation `(a*b)/c' */ - /* (without rounding) with maximum accuracy (it uses a 64-bit */ - /* intermediate integer whenever necessary). */ - /* */ - /* This function isn't necessarily as fast as some processor specific */ - /* operations, but is at least completely portable. */ - /* */ - /* <Input> */ - /* a :: The first multiplier. */ - /* b :: The second multiplier. */ - /* c :: The divisor. */ - /* */ - /* <Return> */ - /* The result of `(a*b)/c'. This function never traps when trying to */ - /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ - /* on the signs of `a' and `b'. */ - /* */ - FT_BASE( FT_Long ) - FT_MulDiv_No_Round( FT_Long a, - FT_Long b, - FT_Long c ); - - - /* - * A variant of FT_Matrix_Multiply which scales its result afterwards. - * The idea is that both `a' and `b' are scaled by factors of 10 so that - * the values are as precise as possible to get a correct result during - * the 64bit multiplication. Let `sa' and `sb' be the scaling factors of - * `a' and `b', respectively, then the scaling factor of the result is - * `sa*sb'. - */ - FT_BASE( void ) - FT_Matrix_Multiply_Scaled( const FT_Matrix* a, - FT_Matrix *b, - FT_Long scaling ); - - - /* - * A variant of FT_Vector_Transform. See comments for - * FT_Matrix_Multiply_Scaled. - */ - FT_BASE( void ) - FT_Vector_Transform_Scaled( FT_Vector* vector, - const FT_Matrix* matrix, - FT_Long scaling ); - - - /* - * This function normalizes a vector and returns its original length. - * The normalized vector is a 16.16 fixed-point unit vector with length - * close to 0x10000. The accuracy of the returned length is limited to - * 16 bits also. The function utilizes quick inverse square root - * approximation without divisions and square roots relying on Newton's - * iterations instead. - */ - FT_BASE( FT_UInt32 ) - FT_Vector_NormLen( FT_Vector* vector ); - - - /* - * Return -1, 0, or +1, depending on the orientation of a given corner. - * We use the Cartesian coordinate system, with positive vertical values - * going upwards. The function returns +1 if the corner turns to the - * left, -1 to the right, and 0 for undecidable cases. - */ - FT_BASE( FT_Int ) - ft_corner_orientation( FT_Pos in_x, - FT_Pos in_y, - FT_Pos out_x, - FT_Pos out_y ); - - - /* - * Return TRUE if a corner is flat or nearly flat. This is equivalent to - * saying that the corner point is close to its neighbors, or inside an - * ellipse defined by the neighbor focal points to be more precise. - */ - FT_BASE( FT_Int ) - ft_corner_is_flat( FT_Pos in_x, - FT_Pos in_y, - FT_Pos out_x, - FT_Pos out_y ); - - - /* - * Return the most significant bit index. - */ - -#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER -#if defined( __GNUC__ ) && \ - ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) ) - -#if FT_SIZEOF_INT == 4 - -#define FT_MSB( x ) ( 31 - __builtin_clz( x ) ) - -#elif FT_SIZEOF_LONG == 4 - -#define FT_MSB( x ) ( 31 - __builtin_clzl( x ) ) - -#endif - -#endif /* __GNUC__ */ -#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ - -#ifndef FT_MSB - - FT_BASE( FT_Int ) - FT_MSB( FT_UInt32 z ); - -#endif - - - /* - * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses - * two fixed-point arguments instead. - */ - FT_BASE( FT_Fixed ) - FT_Hypot( FT_Fixed x, - FT_Fixed y ); - - -#if 0 - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_SqrtFixed */ - /* */ - /* <Description> */ - /* Computes the square root of a 16.16 fixed-point value. */ - /* */ - /* <Input> */ - /* x :: The value to compute the root for. */ - /* */ - /* <Return> */ - /* The result of `sqrt(x)'. */ - /* */ - /* <Note> */ - /* This function is not very fast. */ - /* */ - FT_BASE( FT_Int32 ) - FT_SqrtFixed( FT_Int32 x ); - -#endif /* 0 */ - - -#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) -#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) -#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) -#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) -#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) -#define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 ) - -#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ - : ( -( ( 32 - (x) ) & -64 ) ) ) - - -FT_END_HEADER - -#endif /* __FTCALC_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftdebug.h b/third_party/freetype/include/freetype/internal/ftdebug.h deleted file mode 100644 index 216c73031ebf0896174cc46a6049f06acfd73e66..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftdebug.h +++ /dev/null @@ -1,255 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftdebug.h */ -/* */ -/* Debugging and logging component (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/* */ -/* IMPORTANT: A description of FreeType's debugging support can be */ -/* found in `docs/DEBUG.TXT'. Read it if you need to use or */ -/* understand this code. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTDEBUG_H__ -#define __FTDEBUG_H__ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_FREETYPE_H - - -FT_BEGIN_HEADER - - - /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */ - /* is already defined; this simplifies the following #ifdefs */ - /* */ -#ifdef FT_DEBUG_LEVEL_TRACE -#undef FT_DEBUG_LEVEL_ERROR -#define FT_DEBUG_LEVEL_ERROR -#endif - - - /*************************************************************************/ - /* */ - /* Define the trace enums as well as the trace levels array when they */ - /* are needed. */ - /* */ - /*************************************************************************/ - -#ifdef FT_DEBUG_LEVEL_TRACE - -#define FT_TRACE_DEF( x ) trace_ ## x , - - /* defining the enumeration */ - typedef enum FT_Trace_ - { -#include FT_INTERNAL_TRACE_H - trace_count - - } FT_Trace; - - - /* defining the array of trace levels, provided by `src/base/ftdebug.c' */ - extern int ft_trace_levels[trace_count]; - -#undef FT_TRACE_DEF - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - - /*************************************************************************/ - /* */ - /* Define the FT_TRACE macro */ - /* */ - /* IMPORTANT! */ - /* */ - /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */ - /* value before using any TRACE macro. */ - /* */ - /*************************************************************************/ - -#ifdef FT_DEBUG_LEVEL_TRACE - -#define FT_TRACE( level, varformat ) \ - do \ - { \ - if ( ft_trace_levels[FT_COMPONENT] >= level ) \ - FT_Message varformat; \ - } while ( 0 ) - -#else /* !FT_DEBUG_LEVEL_TRACE */ - -#define FT_TRACE( level, varformat ) do { } while ( 0 ) /* nothing */ - -#endif /* !FT_DEBUG_LEVEL_TRACE */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Trace_Get_Count */ - /* */ - /* <Description> */ - /* Return the number of available trace components. */ - /* */ - /* <Return> */ - /* The number of trace components. 0 if FreeType 2 is not built with */ - /* FT_DEBUG_LEVEL_TRACE definition. */ - /* */ - /* <Note> */ - /* This function may be useful if you want to access elements of */ - /* the internal `ft_trace_levels' array by an index. */ - /* */ - FT_BASE( FT_Int ) - FT_Trace_Get_Count( void ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Trace_Get_Name */ - /* */ - /* <Description> */ - /* Return the name of a trace component. */ - /* */ - /* <Input> */ - /* The index of the trace component. */ - /* */ - /* <Return> */ - /* The name of the trace component. This is a statically allocated */ - /* C string, so do not free it after use. NULL if FreeType 2 is not */ - /* built with FT_DEBUG_LEVEL_TRACE definition. */ - /* */ - /* <Note> */ - /* Use @FT_Trace_Get_Count to get the number of available trace */ - /* components. */ - /* */ - /* This function may be useful if you want to control FreeType 2's */ - /* debug level in your application. */ - /* */ - FT_BASE( const char* ) - FT_Trace_Get_Name( FT_Int idx ); - - - /*************************************************************************/ - /* */ - /* You need two opening and closing parentheses! */ - /* */ - /* Example: FT_TRACE0(( "Value is %i", foo )) */ - /* */ - /* Output of the FT_TRACEX macros is sent to stderr. */ - /* */ - /*************************************************************************/ - -#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat ) -#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat ) -#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat ) -#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat ) -#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat ) -#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat ) -#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat ) -#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat ) - - - /*************************************************************************/ - /* */ - /* Define the FT_ERROR macro. */ - /* */ - /* Output of this macro is sent to stderr. */ - /* */ - /*************************************************************************/ - -#ifdef FT_DEBUG_LEVEL_ERROR - -#define FT_ERROR( varformat ) FT_Message varformat - -#else /* !FT_DEBUG_LEVEL_ERROR */ - -#define FT_ERROR( varformat ) do { } while ( 0 ) /* nothing */ - -#endif /* !FT_DEBUG_LEVEL_ERROR */ - - - /*************************************************************************/ - /* */ - /* Define the FT_ASSERT and FT_THROW macros. The call to `FT_Throw' */ - /* makes it possible to easily set a breakpoint at this function. */ - /* */ - /*************************************************************************/ - -#ifdef FT_DEBUG_LEVEL_ERROR - -#define FT_ASSERT( condition ) \ - do \ - { \ - if ( !( condition ) ) \ - FT_Panic( "assertion failed on line %d of file %s\n", \ - __LINE__, __FILE__ ); \ - } while ( 0 ) - -#define FT_THROW( e ) \ - ( FT_Throw( FT_ERR_CAT( FT_ERR_PREFIX, e ), \ - __LINE__, \ - __FILE__ ) | \ - FT_ERR_CAT( FT_ERR_PREFIX, e ) ) - -#else /* !FT_DEBUG_LEVEL_ERROR */ - -#define FT_ASSERT( condition ) do { } while ( 0 ) - -#define FT_THROW( e ) FT_ERR_CAT( FT_ERR_PREFIX, e ) - -#endif /* !FT_DEBUG_LEVEL_ERROR */ - - - /*************************************************************************/ - /* */ - /* Define `FT_Message' and `FT_Panic' when needed. */ - /* */ - /*************************************************************************/ - -#ifdef FT_DEBUG_LEVEL_ERROR - -#include "stdio.h" /* for vfprintf() */ - - /* print a message */ - FT_BASE( void ) - FT_Message( const char* fmt, - ... ); - - /* print a message and exit */ - FT_BASE( void ) - FT_Panic( const char* fmt, - ... ); - - /* report file name and line number of an error */ - FT_BASE( int ) - FT_Throw( FT_Error error, - int line, - const char* file ); - -#endif /* FT_DEBUG_LEVEL_ERROR */ - - - FT_BASE( void ) - ft_debug_init( void ); - -FT_END_HEADER - -#endif /* __FTDEBUG_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftdriver.h b/third_party/freetype/include/freetype/internal/ftdriver.h deleted file mode 100644 index 16856d3df831f0623a7690d3f163999383027c94..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftdriver.h +++ /dev/null @@ -1,409 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftdriver.h */ -/* */ -/* FreeType font driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTDRIVER_H__ -#define __FTDRIVER_H__ - - -#include <ft2build.h> -#include FT_MODULE_H - - -FT_BEGIN_HEADER - - - typedef FT_Error - (*FT_Face_InitFunc)( FT_Stream stream, - FT_Face face, - FT_Int typeface_index, - FT_Int num_params, - FT_Parameter* parameters ); - - typedef void - (*FT_Face_DoneFunc)( FT_Face face ); - - - typedef FT_Error - (*FT_Size_InitFunc)( FT_Size size ); - - typedef void - (*FT_Size_DoneFunc)( FT_Size size ); - - - typedef FT_Error - (*FT_Slot_InitFunc)( FT_GlyphSlot slot ); - - typedef void - (*FT_Slot_DoneFunc)( FT_GlyphSlot slot ); - - - typedef FT_Error - (*FT_Size_RequestFunc)( FT_Size size, - FT_Size_Request req ); - - typedef FT_Error - (*FT_Size_SelectFunc)( FT_Size size, - FT_ULong size_index ); - - typedef FT_Error - (*FT_Slot_LoadFunc)( FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ); - - - typedef FT_UInt - (*FT_CharMap_CharIndexFunc)( FT_CharMap charmap, - FT_Long charcode ); - - typedef FT_Long - (*FT_CharMap_CharNextFunc)( FT_CharMap charmap, - FT_Long charcode ); - - - typedef FT_Error - (*FT_Face_GetKerningFunc)( FT_Face face, - FT_UInt left_glyph, - FT_UInt right_glyph, - FT_Vector* kerning ); - - - typedef FT_Error - (*FT_Face_AttachFunc)( FT_Face face, - FT_Stream stream ); - - - typedef FT_Error - (*FT_Face_GetAdvancesFunc)( FT_Face face, - FT_UInt first, - FT_UInt count, - FT_Int32 flags, - FT_Fixed* advances ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Driver_ClassRec */ - /* */ - /* <Description> */ - /* The font driver class. This structure mostly contains pointers to */ - /* driver methods. */ - /* */ - /* <Fields> */ - /* root :: The parent module. */ - /* */ - /* face_object_size :: The size of a face object in bytes. */ - /* */ - /* size_object_size :: The size of a size object in bytes. */ - /* */ - /* slot_object_size :: The size of a glyph object in bytes. */ - /* */ - /* init_face :: The format-specific face constructor. */ - /* */ - /* done_face :: The format-specific face destructor. */ - /* */ - /* init_size :: The format-specific size constructor. */ - /* */ - /* done_size :: The format-specific size destructor. */ - /* */ - /* init_slot :: The format-specific slot constructor. */ - /* */ - /* done_slot :: The format-specific slot destructor. */ - /* */ - /* */ - /* load_glyph :: A function handle to load a glyph to a slot. */ - /* This field is mandatory! */ - /* */ - /* get_kerning :: A function handle to return the unscaled */ - /* kerning for a given pair of glyphs. Can be */ - /* set to 0 if the format doesn't support */ - /* kerning. */ - /* */ - /* attach_file :: This function handle is used to read */ - /* additional data for a face from another */ - /* file/stream. For example, this can be used to */ - /* add data from AFM or PFM files on a Type 1 */ - /* face, or a CIDMap on a CID-keyed face. */ - /* */ - /* get_advances :: A function handle used to return advance */ - /* widths of `count' glyphs (in font units), */ - /* starting at `first'. The `vertical' flag must */ - /* be set to get vertical advance heights. The */ - /* `advances' buffer is caller-allocated. */ - /* The idea of this function is to be able to */ - /* perform device-independent text layout without */ - /* loading a single glyph image. */ - /* */ - /* request_size :: A handle to a function used to request the new */ - /* character size. Can be set to 0 if the */ - /* scaling done in the base layer suffices. */ - /* */ - /* select_size :: A handle to a function used to select a new */ - /* fixed size. It is used only if */ - /* @FT_FACE_FLAG_FIXED_SIZES is set. Can be set */ - /* to 0 if the scaling done in the base layer */ - /* suffices. */ - /* <Note> */ - /* Most function pointers, with the exception of `load_glyph', can be */ - /* set to 0 to indicate a default behaviour. */ - /* */ - typedef struct FT_Driver_ClassRec_ - { - FT_Module_Class root; - - FT_Long face_object_size; - FT_Long size_object_size; - FT_Long slot_object_size; - - FT_Face_InitFunc init_face; - FT_Face_DoneFunc done_face; - - FT_Size_InitFunc init_size; - FT_Size_DoneFunc done_size; - - FT_Slot_InitFunc init_slot; - FT_Slot_DoneFunc done_slot; - - FT_Slot_LoadFunc load_glyph; - - FT_Face_GetKerningFunc get_kerning; - FT_Face_AttachFunc attach_file; - FT_Face_GetAdvancesFunc get_advances; - - /* since version 2.2 */ - FT_Size_RequestFunc request_size; - FT_Size_SelectFunc select_size; - - } FT_Driver_ClassRec, *FT_Driver_Class; - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DECLARE_DRIVER */ - /* */ - /* <Description> */ - /* Used to create a forward declaration of an FT_Driver_ClassRec */ - /* struct instance. */ - /* */ - /* <Macro> */ - /* FT_DEFINE_DRIVER */ - /* */ - /* <Description> */ - /* Used to initialize an instance of FT_Driver_ClassRec struct. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is defined a `create' function has to be */ - /* called with a pointer where the allocated structure is returned. */ - /* And when it is no longer needed a `destroy' function needs to be */ - /* called to release that allocation. */ - /* */ - /* `fcinit.c' (ft_create_default_module_classes) already contains a */ - /* mechanism to call these functions for the default modules */ - /* described in `ftmodule.h'. */ - /* */ - /* Notice that the created `create' and `destroy' functions call */ - /* `pic_init' and `pic_free' to allow you to manually allocate and */ - /* initialize any additional global data, like a module specific */ - /* interface, and put them in the global pic container defined in */ - /* `ftpic.h'. If you don't need them just implement the functions as */ - /* empty to resolve the link error. Also the `pic_init' and */ - /* `pic_free' functions should be declared in `pic.h', to be referred */ - /* by driver definition calling `FT_DEFINE_DRIVER' in following. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */ - /* allocated in the global scope (or the scope where the macro is */ - /* used). */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DECLARE_DRIVER( class_ ) \ - FT_CALLBACK_TABLE \ - const FT_Driver_ClassRec class_; - -#define FT_DEFINE_DRIVER( \ - class_, \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_, \ - face_object_size_, \ - size_object_size_, \ - slot_object_size_, \ - init_face_, \ - done_face_, \ - init_size_, \ - done_size_, \ - init_slot_, \ - done_slot_, \ - load_glyph_, \ - get_kerning_, \ - attach_file_, \ - get_advances_, \ - request_size_, \ - select_size_ ) \ - FT_CALLBACK_TABLE_DEF \ - const FT_Driver_ClassRec class_ = \ - { \ - FT_DEFINE_ROOT_MODULE( flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - \ - face_object_size_, \ - size_object_size_, \ - slot_object_size_, \ - \ - init_face_, \ - done_face_, \ - \ - init_size_, \ - done_size_, \ - \ - init_slot_, \ - done_slot_, \ - \ - load_glyph_, \ - \ - get_kerning_, \ - attach_file_, \ - get_advances_, \ - \ - request_size_, \ - select_size_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DECLARE_DRIVER( class_ ) FT_DECLARE_MODULE( class_ ) - -#define FT_DEFINE_DRIVER( \ - class_, \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_, \ - face_object_size_, \ - size_object_size_, \ - slot_object_size_, \ - init_face_, \ - done_face_, \ - init_size_, \ - done_size_, \ - init_slot_, \ - done_slot_, \ - load_glyph_, \ - get_kerning_, \ - attach_file_, \ - get_advances_, \ - request_size_, \ - select_size_ ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_Module_Class* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - FT_Driver_Class dclazz = (FT_Driver_Class)clazz; \ - \ - \ - class_ ## _pic_free( library ); \ - if ( dclazz ) \ - FT_FREE( dclazz ); \ - } \ - \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_Module_Class** output_class ) \ - { \ - FT_Driver_Class clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \ - return error; \ - \ - error = class_ ## _pic_init( library ); \ - if ( error ) \ - { \ - FT_FREE( clazz ); \ - return error; \ - } \ - \ - FT_DEFINE_ROOT_MODULE( flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - \ - clazz->face_object_size = face_object_size_; \ - clazz->size_object_size = size_object_size_; \ - clazz->slot_object_size = slot_object_size_; \ - \ - clazz->init_face = init_face_; \ - clazz->done_face = done_face_; \ - \ - clazz->init_size = init_size_; \ - clazz->done_size = done_size_; \ - \ - clazz->init_slot = init_slot_; \ - clazz->done_slot = done_slot_; \ - \ - clazz->load_glyph = load_glyph_; \ - \ - clazz->get_kerning = get_kerning_; \ - clazz->attach_file = attach_file_; \ - clazz->get_advances = get_advances_; \ - \ - clazz->request_size = request_size_; \ - clazz->select_size = select_size_; \ - \ - *output_class = (FT_Module_Class*)clazz; \ - \ - return FT_Err_Ok; \ - } - - -#endif /* FT_CONFIG_OPTION_PIC */ - -FT_END_HEADER - -#endif /* __FTDRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftgloadr.h b/third_party/freetype/include/freetype/internal/ftgloadr.h deleted file mode 100644 index 970dd70cc3ec9d6ccf1c74cf41361f6d6aa6556b..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftgloadr.h +++ /dev/null @@ -1,172 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgloadr.h */ -/* */ -/* The FreeType glyph loader (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTGLOADR_H__ -#define __FTGLOADR_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_GlyphLoader */ - /* */ - /* <Description> */ - /* The glyph loader is an internal object used to load several glyphs */ - /* together (for example, in the case of composites). */ - /* */ - /* <Note> */ - /* The glyph loader implementation is not part of the high-level API, */ - /* hence the forward structure declaration. */ - /* */ - typedef struct FT_GlyphLoaderRec_* FT_GlyphLoader ; - - -#if 0 /* moved to freetype.h in version 2.2 */ -#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 -#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 -#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 -#define FT_SUBGLYPH_FLAG_SCALE 8 -#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 -#define FT_SUBGLYPH_FLAG_2X2 0x80 -#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 -#endif - - - typedef struct FT_SubGlyphRec_ - { - FT_Int index; - FT_UShort flags; - FT_Int arg1; - FT_Int arg2; - FT_Matrix transform; - - } FT_SubGlyphRec; - - - typedef struct FT_GlyphLoadRec_ - { - FT_Outline outline; /* outline */ - FT_Vector* extra_points; /* extra points table */ - FT_Vector* extra_points2; /* second extra points table */ - FT_UInt num_subglyphs; /* number of subglyphs */ - FT_SubGlyph subglyphs; /* subglyphs */ - - } FT_GlyphLoadRec, *FT_GlyphLoad; - - - typedef struct FT_GlyphLoaderRec_ - { - FT_Memory memory; - FT_UInt max_points; - FT_UInt max_contours; - FT_UInt max_subglyphs; - FT_Bool use_extra; - - FT_GlyphLoadRec base; - FT_GlyphLoadRec current; - - void* other; /* for possible future extension? */ - - } FT_GlyphLoaderRec; - - - /* create new empty glyph loader */ - FT_BASE( FT_Error ) - FT_GlyphLoader_New( FT_Memory memory, - FT_GlyphLoader *aloader ); - - /* add an extra points table to a glyph loader */ - FT_BASE( FT_Error ) - FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ); - - /* destroy a glyph loader */ - FT_BASE( void ) - FT_GlyphLoader_Done( FT_GlyphLoader loader ); - - /* reset a glyph loader (frees everything int it) */ - FT_BASE( void ) - FT_GlyphLoader_Reset( FT_GlyphLoader loader ); - - /* rewind a glyph loader */ - FT_BASE( void ) - FT_GlyphLoader_Rewind( FT_GlyphLoader loader ); - - /* check that there is enough space to add `n_points' and `n_contours' */ - /* to the glyph loader */ - FT_BASE( FT_Error ) - FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, - FT_UInt n_points, - FT_UInt n_contours ); - - -#define FT_GLYPHLOADER_CHECK_P( _loader, _count ) \ - ( (_count) == 0 || \ - ( (FT_UInt)(_loader)->base.outline.n_points + \ - (FT_UInt)(_loader)->current.outline.n_points + \ - (FT_UInt)(_count) ) <= (_loader)->max_points ) - -#define FT_GLYPHLOADER_CHECK_C( _loader, _count ) \ - ( (_count) == 0 || \ - ( (FT_UInt)(_loader)->base.outline.n_contours + \ - (FT_UInt)(_loader)->current.outline.n_contours + \ - (FT_UInt)(_count) ) <= (_loader)->max_contours ) - -#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points, _contours ) \ - ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points ) && \ - FT_GLYPHLOADER_CHECK_C( _loader, _contours ) ) \ - ? 0 \ - : FT_GlyphLoader_CheckPoints( (_loader), \ - (FT_UInt)(_points), \ - (FT_UInt)(_contours) ) ) - - - /* check that there is enough space to add `n_subs' sub-glyphs to */ - /* a glyph loader */ - FT_BASE( FT_Error ) - FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, - FT_UInt n_subs ); - - /* prepare a glyph loader, i.e. empty the current glyph */ - FT_BASE( void ) - FT_GlyphLoader_Prepare( FT_GlyphLoader loader ); - - /* add the current glyph to the base glyph */ - FT_BASE( void ) - FT_GlyphLoader_Add( FT_GlyphLoader loader ); - - /* copy points from one glyph loader to another */ - FT_BASE( FT_Error ) - FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, - FT_GlyphLoader source ); - - /* */ - - -FT_END_HEADER - -#endif /* __FTGLOADR_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftmemory.h b/third_party/freetype/include/freetype/internal/ftmemory.h deleted file mode 100644 index c0c553b4fc92a99c4e7c3ecc22dabc4db5c8cd6f..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftmemory.h +++ /dev/null @@ -1,386 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmemory.h */ -/* */ -/* The FreeType memory management macros (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTMEMORY_H__ -#define __FTMEMORY_H__ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_TYPES_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_SET_ERROR */ - /* */ - /* <Description> */ - /* This macro is used to set an implicit `error' variable to a given */ - /* expression's value (usually a function call), and convert it to a */ - /* boolean which is set whenever the value is != 0. */ - /* */ -#undef FT_SET_ERROR -#define FT_SET_ERROR( expression ) \ - ( ( error = (expression) ) != 0 ) - - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** M E M O R Y ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* - * C++ refuses to handle statements like p = (void*)anything, with `p' a - * typed pointer. Since we don't have a `typeof' operator in standard - * C++, we have to use a template to emulate it. - */ - -#ifdef __cplusplus - - extern "C++" - template <typename T> inline T* - cplusplus_typeof( T*, - void *v ) - { - return static_cast <T*> ( v ); - } - -#define FT_ASSIGNP( p, val ) (p) = cplusplus_typeof( (p), (val) ) - -#else - -#define FT_ASSIGNP( p, val ) (p) = (val) - -#endif - - - -#ifdef FT_DEBUG_MEMORY - - FT_BASE( const char* ) _ft_debug_file; - FT_BASE( long ) _ft_debug_lineno; - -#define FT_DEBUG_INNER( exp ) ( _ft_debug_file = __FILE__, \ - _ft_debug_lineno = __LINE__, \ - (exp) ) - -#define FT_ASSIGNP_INNER( p, exp ) ( _ft_debug_file = __FILE__, \ - _ft_debug_lineno = __LINE__, \ - FT_ASSIGNP( p, exp ) ) - -#else /* !FT_DEBUG_MEMORY */ - -#define FT_DEBUG_INNER( exp ) (exp) -#define FT_ASSIGNP_INNER( p, exp ) FT_ASSIGNP( p, exp ) - -#endif /* !FT_DEBUG_MEMORY */ - - - /* - * The allocation functions return a pointer, and the error code - * is written to through the `p_error' parameter. See below for - * for documentation. - */ - - FT_BASE( FT_Pointer ) - ft_mem_alloc( FT_Memory memory, - FT_Long size, - FT_Error *p_error ); - - FT_BASE( FT_Pointer ) - ft_mem_qalloc( FT_Memory memory, - FT_Long size, - FT_Error *p_error ); - - FT_BASE( FT_Pointer ) - ft_mem_realloc( FT_Memory memory, - FT_Long item_size, - FT_Long cur_count, - FT_Long new_count, - void* block, - FT_Error *p_error ); - - FT_BASE( FT_Pointer ) - ft_mem_qrealloc( FT_Memory memory, - FT_Long item_size, - FT_Long cur_count, - FT_Long new_count, - void* block, - FT_Error *p_error ); - - FT_BASE( void ) - ft_mem_free( FT_Memory memory, - const void* P ); - - -#define FT_MEM_ALLOC( ptr, size ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory, \ - (FT_Long)(size), \ - &error ) ) - -#define FT_MEM_FREE( ptr ) \ - FT_BEGIN_STMNT \ - ft_mem_free( memory, (ptr) ); \ - (ptr) = NULL; \ - FT_END_STMNT - -#define FT_MEM_NEW( ptr ) \ - FT_MEM_ALLOC( ptr, sizeof ( *(ptr) ) ) - -#define FT_MEM_REALLOC( ptr, cursz, newsz ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, \ - 1, \ - (FT_Long)(cursz), \ - (FT_Long)(newsz), \ - (ptr), \ - &error ) ) - -#define FT_MEM_QALLOC( ptr, size ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_qalloc( memory, \ - (FT_Long)(size), \ - &error ) ) - -#define FT_MEM_QNEW( ptr ) \ - FT_MEM_QALLOC( ptr, sizeof ( *(ptr) ) ) - -#define FT_MEM_QREALLOC( ptr, cursz, newsz ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, \ - 1, \ - (FT_Long)(cursz), \ - (FT_Long)(newsz), \ - (ptr), \ - &error ) ) - -#define FT_MEM_ALLOC_MULT( ptr, count, item_size ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, \ - (FT_Long)(item_size), \ - 0, \ - (FT_Long)(count), \ - NULL, \ - &error ) ) - -#define FT_MEM_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, \ - (FT_Long)(itmsz), \ - (FT_Long)(oldcnt), \ - (FT_Long)(newcnt), \ - (ptr), \ - &error ) ) - -#define FT_MEM_QALLOC_MULT( ptr, count, item_size ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, \ - (FT_Long)(item_size), \ - 0, \ - (FT_Long)(count), \ - NULL, \ - &error ) ) - -#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz) \ - FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, \ - (FT_Long)(itmsz), \ - (FT_Long)(oldcnt), \ - (FT_Long)(newcnt), \ - (ptr), \ - &error ) ) - - -#define FT_MEM_SET_ERROR( cond ) ( (cond), error != 0 ) - - -#define FT_MEM_SET( dest, byte, count ) \ - ft_memset( dest, byte, (FT_Offset)(count) ) - -#define FT_MEM_COPY( dest, source, count ) \ - ft_memcpy( dest, source, (FT_Offset)(count) ) - -#define FT_MEM_MOVE( dest, source, count ) \ - ft_memmove( dest, source, (FT_Offset)(count) ) - - -#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count ) - -#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) ) - - -#define FT_ARRAY_ZERO( dest, count ) \ - FT_MEM_ZERO( dest, \ - (FT_Offset)(count) * sizeof ( *(dest) ) ) - -#define FT_ARRAY_COPY( dest, source, count ) \ - FT_MEM_COPY( dest, \ - source, \ - (FT_Offset)(count) * sizeof ( *(dest) ) ) - -#define FT_ARRAY_MOVE( dest, source, count ) \ - FT_MEM_MOVE( dest, \ - source, \ - (FT_Offset)(count) * sizeof ( *(dest) ) ) - - - /* - * Return the maximum number of addressable elements in an array. - * We limit ourselves to INT_MAX, rather than UINT_MAX, to avoid - * any problems. - */ -#define FT_ARRAY_MAX( ptr ) ( FT_INT_MAX / sizeof ( *(ptr) ) ) - -#define FT_ARRAY_CHECK( ptr, count ) ( (count) <= FT_ARRAY_MAX( ptr ) ) - - - /*************************************************************************/ - /* */ - /* The following functions macros expect that their pointer argument is */ - /* _typed_ in order to automatically compute array element sizes. */ - /* */ - -#define FT_MEM_NEW_ARRAY( ptr, count ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, \ - sizeof ( *(ptr) ), \ - 0, \ - (FT_Long)(count), \ - NULL, \ - &error ) ) - -#define FT_MEM_RENEW_ARRAY( ptr, cursz, newsz ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, \ - sizeof ( *(ptr) ), \ - (FT_Long)(cursz), \ - (FT_Long)(newsz), \ - (ptr), \ - &error ) ) - -#define FT_MEM_QNEW_ARRAY( ptr, count ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, \ - sizeof ( *(ptr) ), \ - 0, \ - (FT_Long)(count), \ - NULL, \ - &error ) ) - -#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz ) \ - FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, \ - sizeof ( *(ptr) ), \ - (FT_Long)(cursz), \ - (FT_Long)(newsz), \ - (ptr), \ - &error ) ) - -#define FT_ALLOC( ptr, size ) \ - FT_MEM_SET_ERROR( FT_MEM_ALLOC( ptr, size ) ) - -#define FT_REALLOC( ptr, cursz, newsz ) \ - FT_MEM_SET_ERROR( FT_MEM_REALLOC( ptr, cursz, newsz ) ) - -#define FT_ALLOC_MULT( ptr, count, item_size ) \ - FT_MEM_SET_ERROR( FT_MEM_ALLOC_MULT( ptr, count, item_size ) ) - -#define FT_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \ - FT_MEM_SET_ERROR( FT_MEM_REALLOC_MULT( ptr, oldcnt, \ - newcnt, itmsz ) ) - -#define FT_QALLOC( ptr, size ) \ - FT_MEM_SET_ERROR( FT_MEM_QALLOC( ptr, size ) ) - -#define FT_QREALLOC( ptr, cursz, newsz ) \ - FT_MEM_SET_ERROR( FT_MEM_QREALLOC( ptr, cursz, newsz ) ) - -#define FT_QALLOC_MULT( ptr, count, item_size ) \ - FT_MEM_SET_ERROR( FT_MEM_QALLOC_MULT( ptr, count, item_size ) ) - -#define FT_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \ - FT_MEM_SET_ERROR( FT_MEM_QREALLOC_MULT( ptr, oldcnt, \ - newcnt, itmsz ) ) - -#define FT_FREE( ptr ) FT_MEM_FREE( ptr ) - -#define FT_NEW( ptr ) FT_MEM_SET_ERROR( FT_MEM_NEW( ptr ) ) - -#define FT_NEW_ARRAY( ptr, count ) \ - FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) ) - -#define FT_RENEW_ARRAY( ptr, curcnt, newcnt ) \ - FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) ) - -#define FT_QNEW( ptr ) \ - FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) ) - -#define FT_QNEW_ARRAY( ptr, count ) \ - FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) ) - -#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt ) \ - FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) ) - - - FT_BASE( FT_Pointer ) - ft_mem_strdup( FT_Memory memory, - const char* str, - FT_Error *p_error ); - - FT_BASE( FT_Pointer ) - ft_mem_dup( FT_Memory memory, - const void* address, - FT_ULong size, - FT_Error *p_error ); - - -#define FT_MEM_STRDUP( dst, str ) \ - (dst) = (char*)ft_mem_strdup( memory, (const char*)(str), &error ) - -#define FT_STRDUP( dst, str ) \ - FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) ) - -#define FT_MEM_DUP( dst, address, size ) \ - (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error ) - -#define FT_DUP( dst, address, size ) \ - FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) ) - - - /* Return >= 1 if a truncation occurs. */ - /* Return 0 if the source string fits the buffer. */ - /* This is *not* the same as strlcpy(). */ - FT_BASE( FT_Int ) - ft_mem_strcpyn( char* dst, - const char* src, - FT_ULong size ); - -#define FT_STRCPYN( dst, src, size ) \ - ft_mem_strcpyn( (char*)dst, (const char*)(src), (FT_ULong)(size) ) - - /* */ - - -FT_END_HEADER - -#endif /* __FTMEMORY_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftobjs.h b/third_party/freetype/include/freetype/internal/ftobjs.h deleted file mode 100644 index da5582dc3fcc34493d1c4a936aad7237c3739124..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftobjs.h +++ /dev/null @@ -1,1571 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftobjs.h */ -/* */ -/* The FreeType private base classes (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file contains the definition of all internal FreeType classes. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTOBJS_H__ -#define __FTOBJS_H__ - -#include <ft2build.h> -#include FT_RENDER_H -#include FT_SIZES_H -#include FT_LCD_FILTER_H -#include FT_INTERNAL_MEMORY_H -#include FT_INTERNAL_GLYPH_LOADER_H -#include FT_INTERNAL_DRIVER_H -#include FT_INTERNAL_AUTOHINT_H -#include FT_INTERNAL_SERVICE_H -#include FT_INTERNAL_PIC_H - -#ifdef FT_CONFIG_OPTION_INCREMENTAL -#include FT_INCREMENTAL_H -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* Some generic definitions. */ - /* */ -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef NULL -#define NULL (void*)0 -#endif - - - /*************************************************************************/ - /* */ - /* The min and max functions missing in C. As usual, be careful not to */ - /* write things like FT_MIN( a++, b++ ) to avoid side effects. */ - /* */ -#define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) ) -#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) ) - -#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) ) - - /* - * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min' - * algorithm. We use alpha = 1, beta = 3/8, giving us results with a - * largest error less than 7% compared to the exact value. - */ -#define FT_HYPOT( x, y ) \ - ( x = FT_ABS( x ), \ - y = FT_ABS( y ), \ - x > y ? x + ( 3 * y >> 3 ) \ - : y + ( 3 * x >> 3 ) ) - - /* we use FT_TYPEOF to suppress signedness compilation warnings */ -#define FT_PAD_FLOOR( x, n ) ( (x) & ~FT_TYPEOF( x )( (n)-1 ) ) -#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n ) -#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n ) - -#define FT_PIX_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 ) -#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 ) -#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 ) - - - /* - * character classification functions -- since these are used to parse - * font files, we must not use those in <ctypes.h> which are - * locale-dependent - */ -#define ft_isdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U ) - -#define ft_isxdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U || \ - ( (unsigned)(x) - 'a' ) < 6U || \ - ( (unsigned)(x) - 'A' ) < 6U ) - - /* the next two macros assume ASCII representation */ -#define ft_isupper( x ) ( ( (unsigned)(x) - 'A' ) < 26U ) -#define ft_islower( x ) ( ( (unsigned)(x) - 'a' ) < 26U ) - -#define ft_isalpha( x ) ( ft_isupper( x ) || ft_islower( x ) ) -#define ft_isalnum( x ) ( ft_isdigit( x ) || ft_isalpha( x ) ) - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** C H A R M A P S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /* handle to internal charmap object */ - typedef struct FT_CMapRec_* FT_CMap; - - /* handle to charmap class structure */ - typedef const struct FT_CMap_ClassRec_* FT_CMap_Class; - - /* internal charmap object structure */ - typedef struct FT_CMapRec_ - { - FT_CharMapRec charmap; - FT_CMap_Class clazz; - - } FT_CMapRec; - - /* typecase any pointer to a charmap handle */ -#define FT_CMAP( x ) ((FT_CMap)( x )) - - /* obvious macros */ -#define FT_CMAP_PLATFORM_ID( x ) FT_CMAP( x )->charmap.platform_id -#define FT_CMAP_ENCODING_ID( x ) FT_CMAP( x )->charmap.encoding_id -#define FT_CMAP_ENCODING( x ) FT_CMAP( x )->charmap.encoding -#define FT_CMAP_FACE( x ) FT_CMAP( x )->charmap.face - - - /* class method definitions */ - typedef FT_Error - (*FT_CMap_InitFunc)( FT_CMap cmap, - FT_Pointer init_data ); - - typedef void - (*FT_CMap_DoneFunc)( FT_CMap cmap ); - - typedef FT_UInt - (*FT_CMap_CharIndexFunc)( FT_CMap cmap, - FT_UInt32 char_code ); - - typedef FT_UInt - (*FT_CMap_CharNextFunc)( FT_CMap cmap, - FT_UInt32 *achar_code ); - - typedef FT_UInt - (*FT_CMap_CharVarIndexFunc)( FT_CMap cmap, - FT_CMap unicode_cmap, - FT_UInt32 char_code, - FT_UInt32 variant_selector ); - - typedef FT_Bool - (*FT_CMap_CharVarIsDefaultFunc)( FT_CMap cmap, - FT_UInt32 char_code, - FT_UInt32 variant_selector ); - - typedef FT_UInt32 * - (*FT_CMap_VariantListFunc)( FT_CMap cmap, - FT_Memory mem ); - - typedef FT_UInt32 * - (*FT_CMap_CharVariantListFunc)( FT_CMap cmap, - FT_Memory mem, - FT_UInt32 char_code ); - - typedef FT_UInt32 * - (*FT_CMap_VariantCharListFunc)( FT_CMap cmap, - FT_Memory mem, - FT_UInt32 variant_selector ); - - - typedef struct FT_CMap_ClassRec_ - { - FT_ULong size; - FT_CMap_InitFunc init; - FT_CMap_DoneFunc done; - FT_CMap_CharIndexFunc char_index; - FT_CMap_CharNextFunc char_next; - - /* Subsequent entries are special ones for format 14 -- the variant */ - /* selector subtable which behaves like no other */ - - FT_CMap_CharVarIndexFunc char_var_index; - FT_CMap_CharVarIsDefaultFunc char_var_default; - FT_CMap_VariantListFunc variant_list; - FT_CMap_CharVariantListFunc charvariant_list; - FT_CMap_VariantCharListFunc variantchar_list; - - } FT_CMap_ClassRec; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DECLARE_CMAP_CLASS( class_ ) \ - FT_CALLBACK_TABLE const FT_CMap_ClassRec class_; - -#define FT_DEFINE_CMAP_CLASS( \ - class_, \ - size_, \ - init_, \ - done_, \ - char_index_, \ - char_next_, \ - char_var_index_, \ - char_var_default_, \ - variant_list_, \ - charvariant_list_, \ - variantchar_list_ ) \ - FT_CALLBACK_TABLE_DEF \ - const FT_CMap_ClassRec class_ = \ - { \ - size_, \ - init_, \ - done_, \ - char_index_, \ - char_next_, \ - char_var_index_, \ - char_var_default_, \ - variant_list_, \ - charvariant_list_, \ - variantchar_list_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DECLARE_CMAP_CLASS( class_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_CMap_ClassRec* clazz ); - -#define FT_DEFINE_CMAP_CLASS( \ - class_, \ - size_, \ - init_, \ - done_, \ - char_index_, \ - char_next_, \ - char_var_index_, \ - char_var_default_, \ - variant_list_, \ - charvariant_list_, \ - variantchar_list_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_CMap_ClassRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->size = size_; \ - clazz->init = init_; \ - clazz->done = done_; \ - clazz->char_index = char_index_; \ - clazz->char_next = char_next_; \ - clazz->char_var_index = char_var_index_; \ - clazz->char_var_default = char_var_default_; \ - clazz->variant_list = variant_list_; \ - clazz->charvariant_list = charvariant_list_; \ - clazz->variantchar_list = variantchar_list_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /* create a new charmap and add it to charmap->face */ - FT_BASE( FT_Error ) - FT_CMap_New( FT_CMap_Class clazz, - FT_Pointer init_data, - FT_CharMap charmap, - FT_CMap *acmap ); - - /* destroy a charmap and remove it from face's list */ - FT_BASE( void ) - FT_CMap_Done( FT_CMap cmap ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Face_InternalRec */ - /* */ - /* <Description> */ - /* This structure contains the internal fields of each FT_Face */ - /* object. These fields may change between different releases of */ - /* FreeType. */ - /* */ - /* <Fields> */ - /* max_points :: */ - /* The maximum number of points used to store the vectorial outline */ - /* of any glyph in this face. If this value cannot be known in */ - /* advance, or if the face isn't scalable, this should be set to 0. */ - /* Only relevant for scalable formats. */ - /* */ - /* max_contours :: */ - /* The maximum number of contours used to store the vectorial */ - /* outline of any glyph in this face. If this value cannot be */ - /* known in advance, or if the face isn't scalable, this should be */ - /* set to 0. Only relevant for scalable formats. */ - /* */ - /* transform_matrix :: */ - /* A 2x2 matrix of 16.16 coefficients used to transform glyph */ - /* outlines after they are loaded from the font. Only used by the */ - /* convenience functions. */ - /* */ - /* transform_delta :: */ - /* A translation vector used to transform glyph outlines after they */ - /* are loaded from the font. Only used by the convenience */ - /* functions. */ - /* */ - /* transform_flags :: */ - /* Some flags used to classify the transform. Only used by the */ - /* convenience functions. */ - /* */ - /* services :: */ - /* A cache for frequently used services. It should be only */ - /* accessed with the macro `FT_FACE_LOOKUP_SERVICE'. */ - /* */ - /* incremental_interface :: */ - /* If non-null, the interface through which glyph data and metrics */ - /* are loaded incrementally for faces that do not provide all of */ - /* this data when first opened. This field exists only if */ - /* @FT_CONFIG_OPTION_INCREMENTAL is defined. */ - /* */ - /* ignore_unpatented_hinter :: */ - /* This boolean flag instructs the glyph loader to ignore the */ - /* native font hinter, if one is found. This is exclusively used */ - /* in the case when the unpatented hinter is compiled within the */ - /* library. */ - /* */ - /* refcount :: */ - /* A counter initialized to~1 at the time an @FT_Face structure is */ - /* created. @FT_Reference_Face increments this counter, and */ - /* @FT_Done_Face only destroys a face if the counter is~1, */ - /* otherwise it simply decrements it. */ - /* */ - typedef struct FT_Face_InternalRec_ - { - FT_Matrix transform_matrix; - FT_Vector transform_delta; - FT_Int transform_flags; - - FT_ServiceCacheRec services; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - FT_Incremental_InterfaceRec* incremental_interface; -#endif - - FT_Bool ignore_unpatented_hinter; - FT_Int refcount; - - } FT_Face_InternalRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Slot_InternalRec */ - /* */ - /* <Description> */ - /* This structure contains the internal fields of each FT_GlyphSlot */ - /* object. These fields may change between different releases of */ - /* FreeType. */ - /* */ - /* <Fields> */ - /* loader :: The glyph loader object used to load outlines */ - /* into the glyph slot. */ - /* */ - /* flags :: Possible values are zero or */ - /* FT_GLYPH_OWN_BITMAP. The latter indicates */ - /* that the FT_GlyphSlot structure owns the */ - /* bitmap buffer. */ - /* */ - /* glyph_transformed :: Boolean. Set to TRUE when the loaded glyph */ - /* must be transformed through a specific */ - /* font transformation. This is _not_ the same */ - /* as the face transform set through */ - /* FT_Set_Transform(). */ - /* */ - /* glyph_matrix :: The 2x2 matrix corresponding to the glyph */ - /* transformation, if necessary. */ - /* */ - /* glyph_delta :: The 2d translation vector corresponding to */ - /* the glyph transformation, if necessary. */ - /* */ - /* glyph_hints :: Format-specific glyph hints management. */ - /* */ - -#define FT_GLYPH_OWN_BITMAP 0x1U - - typedef struct FT_Slot_InternalRec_ - { - FT_GlyphLoader loader; - FT_UInt flags; - FT_Bool glyph_transformed; - FT_Matrix glyph_matrix; - FT_Vector glyph_delta; - void* glyph_hints; - - } FT_GlyphSlot_InternalRec; - - -#if 0 - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_Size_InternalRec */ - /* */ - /* <Description> */ - /* This structure contains the internal fields of each FT_Size */ - /* object. Currently, it's empty. */ - /* */ - /*************************************************************************/ - - typedef struct FT_Size_InternalRec_ - { - /* empty */ - - } FT_Size_InternalRec; - -#endif - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** M O D U L E S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_ModuleRec */ - /* */ - /* <Description> */ - /* A module object instance. */ - /* */ - /* <Fields> */ - /* clazz :: A pointer to the module's class. */ - /* */ - /* library :: A handle to the parent library object. */ - /* */ - /* memory :: A handle to the memory manager. */ - /* */ - typedef struct FT_ModuleRec_ - { - FT_Module_Class* clazz; - FT_Library library; - FT_Memory memory; - - } FT_ModuleRec; - - - /* typecast an object to an FT_Module */ -#define FT_MODULE( x ) ((FT_Module)( x )) -#define FT_MODULE_CLASS( x ) FT_MODULE( x )->clazz -#define FT_MODULE_LIBRARY( x ) FT_MODULE( x )->library -#define FT_MODULE_MEMORY( x ) FT_MODULE( x )->memory - - -#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_FONT_DRIVER ) - -#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_RENDERER ) - -#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_HINTER ) - -#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_STYLER ) - -#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_DRIVER_SCALABLE ) - -#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_DRIVER_NO_OUTLINES ) - -#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ - FT_MODULE_DRIVER_HAS_HINTER ) - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Module_Interface */ - /* */ - /* <Description> */ - /* Finds a module and returns its specific interface as a typeless */ - /* pointer. */ - /* */ - /* <Input> */ - /* library :: A handle to the library object. */ - /* */ - /* module_name :: The module's name (as an ASCII string). */ - /* */ - /* <Return> */ - /* A module-specific interface if available, 0 otherwise. */ - /* */ - /* <Note> */ - /* You should better be familiar with FreeType internals to know */ - /* which module to look for, and what its interface is :-) */ - /* */ - FT_BASE( const void* ) - FT_Get_Module_Interface( FT_Library library, - const char* mod_name ); - - FT_BASE( FT_Pointer ) - ft_module_get_service( FT_Module module, - const char* service_id ); - - /* */ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** F A C E, S I Z E & G L Y P H S L O T O B J E C T S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /* a few macros used to perform easy typecasts with minimal brain damage */ - -#define FT_FACE( x ) ((FT_Face)(x)) -#define FT_SIZE( x ) ((FT_Size)(x)) -#define FT_SLOT( x ) ((FT_GlyphSlot)(x)) - -#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver -#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library -#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory -#define FT_FACE_STREAM( x ) FT_FACE( x )->stream - -#define FT_SIZE_FACE( x ) FT_SIZE( x )->face -#define FT_SLOT_FACE( x ) FT_SLOT( x )->face - -#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph -#define FT_FACE_SIZE( x ) FT_FACE( x )->size - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_GlyphSlot */ - /* */ - /* <Description> */ - /* It is sometimes useful to have more than one glyph slot for a */ - /* given face object. This function is used to create additional */ - /* slots. All of them are automatically discarded when the face is */ - /* destroyed. */ - /* */ - /* <Input> */ - /* face :: A handle to a parent face object. */ - /* */ - /* <Output> */ - /* aslot :: A handle to a new glyph slot object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_BASE( FT_Error ) - FT_New_GlyphSlot( FT_Face face, - FT_GlyphSlot *aslot ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_GlyphSlot */ - /* */ - /* <Description> */ - /* Destroys a given glyph slot. Remember however that all slots are */ - /* automatically destroyed with its parent. Using this function is */ - /* not always mandatory. */ - /* */ - /* <Input> */ - /* slot :: A handle to a target glyph slot. */ - /* */ - FT_BASE( void ) - FT_Done_GlyphSlot( FT_GlyphSlot slot ); - - /* */ - -#define FT_REQUEST_WIDTH( req ) \ - ( (req)->horiResolution \ - ? ( (req)->width * (FT_Pos)(req)->horiResolution + 36 ) / 72 \ - : (req)->width ) - -#define FT_REQUEST_HEIGHT( req ) \ - ( (req)->vertResolution \ - ? ( (req)->height * (FT_Pos)(req)->vertResolution + 36 ) / 72 \ - : (req)->height ) - - - /* Set the metrics according to a bitmap strike. */ - FT_BASE( void ) - FT_Select_Metrics( FT_Face face, - FT_ULong strike_index ); - - - /* Set the metrics according to a size request. */ - FT_BASE( void ) - FT_Request_Metrics( FT_Face face, - FT_Size_Request req ); - - - /* Match a size request against `available_sizes'. */ - FT_BASE( FT_Error ) - FT_Match_Size( FT_Face face, - FT_Size_Request req, - FT_Bool ignore_width, - FT_ULong* size_index ); - - - /* Use the horizontal metrics to synthesize the vertical metrics. */ - /* If `advance' is zero, it is also synthesized. */ - FT_BASE( void ) - ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics, - FT_Pos advance ); - - - /* Free the bitmap of a given glyphslot when needed (i.e., only when it */ - /* was allocated with ft_glyphslot_alloc_bitmap). */ - FT_BASE( void ) - ft_glyphslot_free_bitmap( FT_GlyphSlot slot ); - - - /* Allocate a new bitmap buffer in a glyph slot. */ - FT_BASE( FT_Error ) - ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, - FT_ULong size ); - - - /* Set the bitmap buffer in a glyph slot to a given pointer. The buffer */ - /* will not be freed by a later call to ft_glyphslot_free_bitmap. */ - FT_BASE( void ) - ft_glyphslot_set_bitmap( FT_GlyphSlot slot, - FT_Byte* buffer ); - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** R E N D E R E R S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - -#define FT_RENDERER( x ) ((FT_Renderer)( x )) -#define FT_GLYPH( x ) ((FT_Glyph)( x )) -#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x )) -#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x )) - - - typedef struct FT_RendererRec_ - { - FT_ModuleRec root; - FT_Renderer_Class* clazz; - FT_Glyph_Format glyph_format; - FT_Glyph_Class glyph_class; - - FT_Raster raster; - FT_Raster_Render_Func raster_render; - FT_Renderer_RenderFunc render; - - } FT_RendererRec; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** F O N T D R I V E R S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* typecast a module into a driver easily */ -#define FT_DRIVER( x ) ((FT_Driver)(x)) - - /* typecast a module as a driver, and get its driver class */ -#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_DriverRec */ - /* */ - /* <Description> */ - /* The root font driver class. A font driver is responsible for */ - /* managing and loading font files of a given format. */ - /* */ - /* <Fields> */ - /* root :: Contains the fields of the root module class. */ - /* */ - /* clazz :: A pointer to the font driver's class. Note that */ - /* this is NOT root.clazz. `class' wasn't used */ - /* as it is a reserved word in C++. */ - /* */ - /* faces_list :: The list of faces currently opened by this */ - /* driver. */ - /* */ - /* glyph_loader :: Unused. Used to be glyph loader for all faces */ - /* managed by this driver. */ - /* */ - typedef struct FT_DriverRec_ - { - FT_ModuleRec root; - FT_Driver_Class clazz; - FT_ListRec faces_list; - FT_GlyphLoader glyph_loader; - - } FT_DriverRec; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** L I B R A R I E S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* This hook is used by the TrueType debugger. It must be set to an */ - /* alternate truetype bytecode interpreter function. */ -#define FT_DEBUG_HOOK_TRUETYPE 0 - - - /* Set this debug hook to a non-null pointer to force unpatented hinting */ - /* for all faces when both TT_USE_BYTECODE_INTERPRETER and */ - /* TT_CONFIG_OPTION_UNPATENTED_HINTING are defined. This is only used */ - /* during debugging. */ -#define FT_DEBUG_HOOK_UNPATENTED_HINTING 1 - - - typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap, - FT_Render_Mode render_mode, - FT_Library library ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* FT_LibraryRec */ - /* */ - /* <Description> */ - /* The FreeType library class. This is the root of all FreeType */ - /* data. Use FT_New_Library() to create a library object, and */ - /* FT_Done_Library() to discard it and all child objects. */ - /* */ - /* <Fields> */ - /* memory :: The library's memory object. Manages memory */ - /* allocation. */ - /* */ - /* version_major :: The major version number of the library. */ - /* */ - /* version_minor :: The minor version number of the library. */ - /* */ - /* version_patch :: The current patch level of the library. */ - /* */ - /* num_modules :: The number of modules currently registered */ - /* within this library. This is set to 0 for new */ - /* libraries. New modules are added through the */ - /* FT_Add_Module() API function. */ - /* */ - /* modules :: A table used to store handles to the currently */ - /* registered modules. Note that each font driver */ - /* contains a list of its opened faces. */ - /* */ - /* renderers :: The list of renderers currently registered */ - /* within the library. */ - /* */ - /* cur_renderer :: The current outline renderer. This is a */ - /* shortcut used to avoid parsing the list on */ - /* each call to FT_Outline_Render(). It is a */ - /* handle to the current renderer for the */ - /* FT_GLYPH_FORMAT_OUTLINE format. */ - /* */ - /* auto_hinter :: XXX */ - /* */ - /* raster_pool :: The raster object's render pool. This can */ - /* ideally be changed dynamically at run-time. */ - /* */ - /* raster_pool_size :: The size of the render pool in bytes. */ - /* */ - /* debug_hooks :: XXX */ - /* */ - /* lcd_filter :: If subpixel rendering is activated, the */ - /* selected LCD filter mode. */ - /* */ - /* lcd_extra :: If subpixel rendering is activated, the number */ - /* of extra pixels needed for the LCD filter. */ - /* */ - /* lcd_weights :: If subpixel rendering is activated, the LCD */ - /* filter weights, if any. */ - /* */ - /* lcd_filter_func :: If subpixel rendering is activated, the LCD */ - /* filtering callback function. */ - /* */ - /* pic_container :: Contains global structs and tables, instead */ - /* of defining them globallly. */ - /* */ - /* refcount :: A counter initialized to~1 at the time an */ - /* @FT_Library structure is created. */ - /* @FT_Reference_Library increments this counter, */ - /* and @FT_Done_Library only destroys a library */ - /* if the counter is~1, otherwise it simply */ - /* decrements it. */ - /* */ - typedef struct FT_LibraryRec_ - { - FT_Memory memory; /* library's memory manager */ - - FT_Int version_major; - FT_Int version_minor; - FT_Int version_patch; - - FT_UInt num_modules; - FT_Module modules[FT_MAX_MODULES]; /* module objects */ - - FT_ListRec renderers; /* list of renderers */ - FT_Renderer cur_renderer; /* current outline renderer */ - FT_Module auto_hinter; - - FT_Byte* raster_pool; /* scan-line conversion */ - /* render pool */ - FT_ULong raster_pool_size; /* size of render pool in bytes */ - - FT_DebugHook_Func debug_hooks[4]; - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - FT_LcdFilter lcd_filter; - FT_Int lcd_extra; /* number of extra pixels */ - FT_Byte lcd_weights[7]; /* filter weights, if any */ - FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ -#endif - -#ifdef FT_CONFIG_OPTION_PIC - FT_PIC_Container pic_container; -#endif - - FT_Int refcount; - - } FT_LibraryRec; - - - FT_BASE( FT_Renderer ) - FT_Lookup_Renderer( FT_Library library, - FT_Glyph_Format format, - FT_ListNode* node ); - - FT_BASE( FT_Error ) - FT_Render_Glyph_Internal( FT_Library library, - FT_GlyphSlot slot, - FT_Render_Mode render_mode ); - - typedef const char* - (*FT_Face_GetPostscriptNameFunc)( FT_Face face ); - - typedef FT_Error - (*FT_Face_GetGlyphNameFunc)( FT_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ); - - typedef FT_UInt - (*FT_Face_GetGlyphNameIndexFunc)( FT_Face face, - FT_String* glyph_name ); - - -#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Memory */ - /* */ - /* <Description> */ - /* Creates a new memory object. */ - /* */ - /* <Return> */ - /* A pointer to the new memory object. 0 in case of error. */ - /* */ - FT_BASE( FT_Memory ) - FT_New_Memory( void ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Done_Memory */ - /* */ - /* <Description> */ - /* Discards memory manager. */ - /* */ - /* <Input> */ - /* memory :: A handle to the memory manager. */ - /* */ - FT_BASE( void ) - FT_Done_Memory( FT_Memory memory ); - -#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ - - - /* Define default raster's interface. The default raster is located in */ - /* `src/base/ftraster.c'. */ - /* */ - /* Client applications can register new rasters through the */ - /* FT_Set_Raster() API. */ - -#ifndef FT_NO_DEFAULT_RASTER - FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster; -#endif - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** P I C S U P P O R T ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* PIC support macros for ftimage.h */ - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DEFINE_OUTLINE_FUNCS */ - /* */ - /* <Description> */ - /* Used to initialize an instance of FT_Outline_Funcs struct. */ - /* When FT_CONFIG_OPTION_PIC is defined an init funtion will need to */ - /* be called with a pre-allocated structure to be filled. */ - /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */ - /* allocated in the global scope (or the scope where the macro */ - /* is used). */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_OUTLINE_FUNCS( \ - class_, \ - move_to_, \ - line_to_, \ - conic_to_, \ - cubic_to_, \ - shift_, \ - delta_ ) \ - static const FT_Outline_Funcs class_ = \ - { \ - move_to_, \ - line_to_, \ - conic_to_, \ - cubic_to_, \ - shift_, \ - delta_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_OUTLINE_FUNCS( \ - class_, \ - move_to_, \ - line_to_, \ - conic_to_, \ - cubic_to_, \ - shift_, \ - delta_ ) \ - static FT_Error \ - Init_Class_ ## class_( FT_Outline_Funcs* clazz ) \ - { \ - clazz->move_to = move_to_; \ - clazz->line_to = line_to_; \ - clazz->conic_to = conic_to_; \ - clazz->cubic_to = cubic_to_; \ - clazz->shift = shift_; \ - clazz->delta = delta_; \ - \ - return FT_Err_Ok; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DEFINE_RASTER_FUNCS */ - /* */ - /* <Description> */ - /* Used to initialize an instance of FT_Raster_Funcs struct. */ - /* When FT_CONFIG_OPTION_PIC is defined an init funtion will need to */ - /* be called with a pre-allocated structure to be filled. */ - /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */ - /* allocated in the global scope (or the scope where the macro */ - /* is used). */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_RASTER_FUNCS( \ - class_, \ - glyph_format_, \ - raster_new_, \ - raster_reset_, \ - raster_set_mode_, \ - raster_render_, \ - raster_done_ ) \ - const FT_Raster_Funcs class_ = \ - { \ - glyph_format_, \ - raster_new_, \ - raster_reset_, \ - raster_set_mode_, \ - raster_render_, \ - raster_done_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_RASTER_FUNCS( \ - class_, \ - glyph_format_, \ - raster_new_, \ - raster_reset_, \ - raster_set_mode_, \ - raster_render_, \ - raster_done_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Raster_Funcs* clazz ) \ - { \ - clazz->glyph_format = glyph_format_; \ - clazz->raster_new = raster_new_; \ - clazz->raster_reset = raster_reset_; \ - clazz->raster_set_mode = raster_set_mode_; \ - clazz->raster_render = raster_render_; \ - clazz->raster_done = raster_done_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /* PIC support macros for ftrender.h */ - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DEFINE_GLYPH */ - /* */ - /* <Description> */ - /* Used to initialize an instance of FT_Glyph_Class struct. */ - /* When FT_CONFIG_OPTION_PIC is defined an init funtion will need to */ - /* be called with a pre-allocated stcture to be filled. */ - /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */ - /* allocated in the global scope (or the scope where the macro */ - /* is used). */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_GLYPH( \ - class_, \ - size_, \ - format_, \ - init_, \ - done_, \ - copy_, \ - transform_, \ - bbox_, \ - prepare_ ) \ - FT_CALLBACK_TABLE_DEF \ - const FT_Glyph_Class class_ = \ - { \ - size_, \ - format_, \ - init_, \ - done_, \ - copy_, \ - transform_, \ - bbox_, \ - prepare_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_GLYPH( \ - class_, \ - size_, \ - format_, \ - init_, \ - done_, \ - copy_, \ - transform_, \ - bbox_, \ - prepare_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Glyph_Class* clazz ) \ - { \ - clazz->glyph_size = size_; \ - clazz->glyph_format = format_; \ - clazz->glyph_init = init_; \ - clazz->glyph_done = done_; \ - clazz->glyph_copy = copy_; \ - clazz->glyph_transform = transform_; \ - clazz->glyph_bbox = bbox_; \ - clazz->glyph_prepare = prepare_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DECLARE_RENDERER */ - /* */ - /* <Description> */ - /* Used to create a forward declaration of a */ - /* FT_Renderer_Class struct instance. */ - /* */ - /* <Macro> */ - /* FT_DEFINE_RENDERER */ - /* */ - /* <Description> */ - /* Used to initialize an instance of FT_Renderer_Class struct. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is defined a `create' funtion will need */ - /* to be called with a pointer where the allocated structure is */ - /* returned. And when it is no longer needed a `destroy' function */ - /* needs to be called to release that allocation. */ - /* `fcinit.c' (ft_create_default_module_classes) already contains */ - /* a mechanism to call these functions for the default modules */ - /* described in `ftmodule.h'. */ - /* */ - /* Notice that the created `create' and `destroy' functions call */ - /* `pic_init' and `pic_free' to allow you to manually allocate and */ - /* initialize any additional global data, like a module specific */ - /* interface, and put them in the global pic container defined in */ - /* `ftpic.h'. If you don't need them just implement the functions as */ - /* empty to resolve the link error. Also the `pic_init' and */ - /* `pic_free' functions should be declared in `pic.h', to be referred */ - /* by the renderer definition calling `FT_DEFINE_RENDERER' in the */ - /* following. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */ - /* allocated in the global scope (or the scope where the macro */ - /* is used). */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DECLARE_RENDERER( class_ ) \ - FT_EXPORT_VAR( const FT_Renderer_Class ) class_; - -#define FT_DEFINE_RENDERER( \ - class_, \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_, \ - glyph_format_, \ - render_glyph_, \ - transform_glyph_, \ - get_glyph_cbox_, \ - set_mode_, \ - raster_class_ ) \ - FT_CALLBACK_TABLE_DEF \ - const FT_Renderer_Class class_ = \ - { \ - FT_DEFINE_ROOT_MODULE( flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - glyph_format_, \ - \ - render_glyph_, \ - transform_glyph_, \ - get_glyph_cbox_, \ - set_mode_, \ - \ - raster_class_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DECLARE_RENDERER( class_ ) FT_DECLARE_MODULE( class_ ) - -#define FT_DEFINE_RENDERER( \ - class_, \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_, \ - glyph_format_, \ - render_glyph_, \ - transform_glyph_, \ - get_glyph_cbox_, \ - set_mode_, \ - raster_class_ ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_Module_Class* clazz ) \ - { \ - FT_Renderer_Class* rclazz = (FT_Renderer_Class*)clazz; \ - FT_Memory memory = library->memory; \ - \ - \ - class_ ## _pic_free( library ); \ - if ( rclazz ) \ - FT_FREE( rclazz ); \ - } \ - \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_Module_Class** output_class ) \ - { \ - FT_Renderer_Class* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \ - return error; \ - \ - error = class_ ## _pic_init( library ); \ - if ( error ) \ - { \ - FT_FREE( clazz ); \ - return error; \ - } \ - \ - FT_DEFINE_ROOT_MODULE( flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - \ - clazz->glyph_format = glyph_format_; \ - \ - clazz->render_glyph = render_glyph_; \ - clazz->transform_glyph = transform_glyph_; \ - clazz->get_glyph_cbox = get_glyph_cbox_; \ - clazz->set_mode = set_mode_; \ - \ - clazz->raster_class = raster_class_; \ - \ - *output_class = (FT_Module_Class*)clazz; \ - \ - return FT_Err_Ok; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /* PIC support macros for ftmodapi.h **/ - - -#ifdef FT_CONFIG_OPTION_PIC - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Module_Creator */ - /* */ - /* <Description> */ - /* A function used to create (allocate) a new module class object. */ - /* The object's members are initialized, but the module itself is */ - /* not. */ - /* */ - /* <Input> */ - /* memory :: A handle to the memory manager. */ - /* output_class :: Initialized with the newly allocated class. */ - /* */ - typedef FT_Error - (*FT_Module_Creator)( FT_Memory memory, - FT_Module_Class** output_class ); - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* FT_Module_Destroyer */ - /* */ - /* <Description> */ - /* A function used to destroy (deallocate) a module class object. */ - /* */ - /* <Input> */ - /* memory :: A handle to the memory manager. */ - /* clazz :: Module class to destroy. */ - /* */ - typedef void - (*FT_Module_Destroyer)( FT_Memory memory, - FT_Module_Class* clazz ); - -#endif - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DECLARE_MODULE */ - /* */ - /* <Description> */ - /* Used to create a forward declaration of a */ - /* FT_Module_Class struct instance. */ - /* */ - /* <Macro> */ - /* FT_DEFINE_MODULE */ - /* */ - /* <Description> */ - /* Used to initialize an instance of an FT_Module_Class struct. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is defined a `create' funtion needs to */ - /* be called with a pointer where the allocated structure is */ - /* returned. And when it is no longer needed a `destroy' function */ - /* needs to be called to release that allocation. */ - /* `fcinit.c' (ft_create_default_module_classes) already contains */ - /* a mechanism to call these functions for the default modules */ - /* described in `ftmodule.h'. */ - /* */ - /* Notice that the created `create' and `destroy' functions call */ - /* `pic_init' and `pic_free' to allow you to manually allocate and */ - /* initialize any additional global data, like a module specific */ - /* interface, and put them in the global pic container defined in */ - /* `ftpic.h'. If you don't need them just implement the functions as */ - /* empty to resolve the link error. Also the `pic_init' and */ - /* `pic_free' functions should be declared in `pic.h', to be referred */ - /* by the module definition calling `FT_DEFINE_MODULE' in the */ - /* following. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */ - /* allocated in the global scope (or the scope where the macro */ - /* is used). */ - /* */ - /* <Macro> */ - /* FT_DEFINE_ROOT_MODULE */ - /* */ - /* <Description> */ - /* Used to initialize an instance of an FT_Module_Class struct inside */ - /* another struct that contains it or in a function that initializes */ - /* that containing struct. */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DECLARE_MODULE( class_ ) \ - FT_CALLBACK_TABLE \ - const FT_Module_Class class_; - -#define FT_DEFINE_ROOT_MODULE( \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - { \ - flags_, \ - size_, \ - \ - name_, \ - version_, \ - requires_, \ - \ - interface_, \ - \ - init_, \ - done_, \ - get_interface_, \ - }, - -#define FT_DEFINE_MODULE( \ - class_, \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - FT_CALLBACK_TABLE_DEF \ - const FT_Module_Class class_ = \ - { \ - flags_, \ - size_, \ - \ - name_, \ - version_, \ - requires_, \ - \ - interface_, \ - \ - init_, \ - done_, \ - get_interface_, \ - }; - - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DECLARE_MODULE( class_ ) \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_Module_Class** output_class ); \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_Module_Class* clazz ); - -#define FT_DEFINE_ROOT_MODULE( \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - clazz->root.module_flags = flags_; \ - clazz->root.module_size = size_; \ - clazz->root.module_name = name_; \ - clazz->root.module_version = version_; \ - clazz->root.module_requires = requires_; \ - \ - clazz->root.module_interface = interface_; \ - \ - clazz->root.module_init = init_; \ - clazz->root.module_done = done_; \ - clazz->root.get_interface = get_interface_; - -#define FT_DEFINE_MODULE( \ - class_, \ - flags_, \ - size_, \ - name_, \ - version_, \ - requires_, \ - interface_, \ - init_, \ - done_, \ - get_interface_ ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_Module_Class* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - class_ ## _pic_free( library ); \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_Module_Class** output_class ) \ - { \ - FT_Memory memory = library->memory; \ - FT_Module_Class* clazz = NULL; \ - FT_Error error; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) ) \ - return error; \ - error = class_ ## _pic_init( library ); \ - if ( error ) \ - { \ - FT_FREE( clazz ); \ - return error; \ - } \ - \ - clazz->module_flags = flags_; \ - clazz->module_size = size_; \ - clazz->module_name = name_; \ - clazz->module_version = version_; \ - clazz->module_requires = requires_; \ - \ - clazz->module_interface = interface_; \ - \ - clazz->module_init = init_; \ - clazz->module_done = done_; \ - clazz->get_interface = get_interface_; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -FT_END_HEADER - -#endif /* __FTOBJS_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftpic.h b/third_party/freetype/include/freetype/internal/ftpic.h deleted file mode 100644 index 7f9154f419ea03f164755a225058eb3e2fa1d4e3..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftpic.h +++ /dev/null @@ -1,71 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftpic.h */ -/* */ -/* The FreeType position independent code services (declaration). */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* Modules that ordinarily have const global data that need address */ - /* can instead define pointers here. */ - /* */ - /*************************************************************************/ - - -#ifndef __FTPIC_H__ -#define __FTPIC_H__ - - -FT_BEGIN_HEADER - -#ifdef FT_CONFIG_OPTION_PIC - - typedef struct FT_PIC_Container_ - { - /* pic containers for base */ - void* base; - - /* pic containers for modules */ - void* autofit; - void* cff; - void* pshinter; - void* psnames; - void* raster; - void* sfnt; - void* smooth; - void* truetype; - - } FT_PIC_Container; - - - /* Initialize the various function tables, structs, etc. */ - /* stored in the container. */ - FT_BASE( FT_Error ) - ft_pic_container_init( FT_Library library ); - - - /* Destroy the contents of the container. */ - FT_BASE( void ) - ft_pic_container_destroy( FT_Library library ); - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -FT_END_HEADER - -#endif /* __FTPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftrfork.h b/third_party/freetype/include/freetype/internal/ftrfork.h deleted file mode 100644 index da61ca75b53339d849accd97bcc35d6196026c1c..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftrfork.h +++ /dev/null @@ -1,266 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftrfork.h */ -/* */ -/* Embedded resource forks accessor (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* Masatake YAMATO and Redhat K.K. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/***************************************************************************/ -/* Development of the code in this file is support of */ -/* Information-technology Promotion Agency, Japan. */ -/***************************************************************************/ - - -#ifndef __FTRFORK_H__ -#define __FTRFORK_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H - - -FT_BEGIN_HEADER - - - /* Number of guessing rules supported in `FT_Raccess_Guess'. */ - /* Don't forget to increment the number if you add a new guessing rule. */ -#define FT_RACCESS_N_RULES 9 - - - /* A structure to describe a reference in a resource by its resource ID */ - /* and internal offset. The `POST' resource expects to be concatenated */ - /* by the order of resource IDs instead of its appearance in the file. */ - - typedef struct FT_RFork_Ref_ - { - FT_UShort res_id; - FT_Long offset; - - } FT_RFork_Ref; - -#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK - typedef FT_Error - (*ft_raccess_guess_func)( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - typedef enum FT_RFork_Rule_ { - FT_RFork_Rule_invalid = -2, - FT_RFork_Rule_uknown, /* -1 */ - FT_RFork_Rule_apple_double, - FT_RFork_Rule_apple_single, - FT_RFork_Rule_darwin_ufs_export, - FT_RFork_Rule_darwin_newvfs, - FT_RFork_Rule_darwin_hfsplus, - FT_RFork_Rule_vfat, - FT_RFork_Rule_linux_cap, - FT_RFork_Rule_linux_double, - FT_RFork_Rule_linux_netatalk - } FT_RFork_Rule; - - /* For fast translation between rule index and rule type, - * the macros FT_RFORK_xxx should be kept consistent with - * the raccess_guess_funcs table - */ - typedef struct ft_raccess_guess_rec_ { - ft_raccess_guess_func func; - FT_RFork_Rule type; - } ft_raccess_guess_rec; - -#ifndef FT_CONFIG_OPTION_PIC - - /* this array is a storage in non-PIC mode, so ; is needed in END */ -#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \ - static const type name[] = { -#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \ - { raccess_guess_ ## func_suffix, \ - FT_RFork_Rule_ ## type_suffix }, -#define CONST_FT_RFORK_RULE_ARRAY_END }; - -#else /* FT_CONFIG_OPTION_PIC */ - - /* this array is a function in PIC mode, so no ; is needed in END */ -#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \ - void \ - FT_Init_Table_ ## name( type* storage ) \ - { \ - type* local = storage; \ - \ - \ - int i = 0; -#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \ - local[i].func = raccess_guess_ ## func_suffix; \ - local[i].type = FT_RFork_Rule_ ## type_suffix; \ - i++; -#define CONST_FT_RFORK_RULE_ARRAY_END } - -#endif /* FT_CONFIG_OPTION_PIC */ - -#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Raccess_Guess */ - /* */ - /* <Description> */ - /* Guess a file name and offset where the actual resource fork is */ - /* stored. The macro FT_RACCESS_N_RULES holds the number of */ - /* guessing rules; the guessed result for the Nth rule is */ - /* represented as a triplet: a new file name (new_names[N]), a file */ - /* offset (offsets[N]), and an error code (errors[N]). */ - /* */ - /* <Input> */ - /* library :: */ - /* A FreeType library instance. */ - /* */ - /* stream :: */ - /* A file stream containing the resource fork. */ - /* */ - /* base_name :: */ - /* The (base) file name of the resource fork used for some */ - /* guessing rules. */ - /* */ - /* <Output> */ - /* new_names :: */ - /* An array of guessed file names in which the resource forks may */ - /* exist. If `new_names[N]' is NULL, the guessed file name is */ - /* equal to `base_name'. */ - /* */ - /* offsets :: */ - /* An array of guessed file offsets. `offsets[N]' holds the file */ - /* offset of the possible start of the resource fork in file */ - /* `new_names[N]'. */ - /* */ - /* errors :: */ - /* An array of FreeType error codes. `errors[N]' is the error */ - /* code of Nth guessing rule function. If `errors[N]' is not */ - /* FT_Err_Ok, `new_names[N]' and `offsets[N]' are meaningless. */ - /* */ - FT_BASE( void ) - FT_Raccess_Guess( FT_Library library, - FT_Stream stream, - char* base_name, - char** new_names, - FT_Long* offsets, - FT_Error* errors ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Raccess_Get_HeaderInfo */ - /* */ - /* <Description> */ - /* Get the information from the header of resource fork. The */ - /* information includes the file offset where the resource map */ - /* starts, and the file offset where the resource data starts. */ - /* `FT_Raccess_Get_DataOffsets' requires these two data. */ - /* */ - /* <Input> */ - /* library :: */ - /* A FreeType library instance. */ - /* */ - /* stream :: */ - /* A file stream containing the resource fork. */ - /* */ - /* rfork_offset :: */ - /* The file offset where the resource fork starts. */ - /* */ - /* <Output> */ - /* map_offset :: */ - /* The file offset where the resource map starts. */ - /* */ - /* rdata_pos :: */ - /* The file offset where the resource data starts. */ - /* */ - /* <Return> */ - /* FreeType error code. FT_Err_Ok means success. */ - /* */ - FT_BASE( FT_Error ) - FT_Raccess_Get_HeaderInfo( FT_Library library, - FT_Stream stream, - FT_Long rfork_offset, - FT_Long *map_offset, - FT_Long *rdata_pos ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Raccess_Get_DataOffsets */ - /* */ - /* <Description> */ - /* Get the data offsets for a tag in a resource fork. Offsets are */ - /* stored in an array because, in some cases, resources in a resource */ - /* fork have the same tag. */ - /* */ - /* <Input> */ - /* library :: */ - /* A FreeType library instance. */ - /* */ - /* stream :: */ - /* A file stream containing the resource fork. */ - /* */ - /* map_offset :: */ - /* The file offset where the resource map starts. */ - /* */ - /* rdata_pos :: */ - /* The file offset where the resource data starts. */ - /* */ - /* tag :: */ - /* The resource tag. */ - /* */ - /* sort_by_res_id :: */ - /* A Boolean to sort the fragmented resource by their ids. */ - /* The fragmented resources for `POST' resource should be sorted */ - /* to restore Type1 font properly. For `snft' resources, sorting */ - /* may induce a different order of the faces in comparison to that */ - /* by QuickDraw API. */ - /* */ - /* <Output> */ - /* offsets :: */ - /* The stream offsets for the resource data specified by `tag'. */ - /* This array is allocated by the function, so you have to call */ - /* @ft_mem_free after use. */ - /* */ - /* count :: */ - /* The length of offsets array. */ - /* */ - /* <Return> */ - /* FreeType error code. FT_Err_Ok means success. */ - /* */ - /* <Note> */ - /* Normally you should use `FT_Raccess_Get_HeaderInfo' to get the */ - /* value for `map_offset' and `rdata_pos'. */ - /* */ - FT_BASE( FT_Error ) - FT_Raccess_Get_DataOffsets( FT_Library library, - FT_Stream stream, - FT_Long map_offset, - FT_Long rdata_pos, - FT_Long tag, - FT_Bool sort_by_res_id, - FT_Long **offsets, - FT_Long *count ); - - -FT_END_HEADER - -#endif /* __FTRFORK_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftserv.h b/third_party/freetype/include/freetype/internal/ftserv.h deleted file mode 100644 index 11a0c7f3de52e47c04da659f5553ccec2fcbaf80..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftserv.h +++ /dev/null @@ -1,763 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftserv.h */ -/* */ -/* The FreeType services (specification only). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* Each module can export one or more `services'. Each service is */ - /* identified by a constant string and modeled by a pointer; the latter */ - /* generally corresponds to a structure containing function pointers. */ - /* */ - /* Note that a service's data cannot be a mere function pointer because */ - /* in C it is possible that function pointers might be implemented */ - /* differently than data pointers (e.g. 48 bits instead of 32). */ - /* */ - /*************************************************************************/ - - -#ifndef __FTSERV_H__ -#define __FTSERV_H__ - - -FT_BEGIN_HEADER - - /* - * @macro: - * FT_FACE_FIND_SERVICE - * - * @description: - * This macro is used to look up a service from a face's driver module. - * - * @input: - * face :: - * The source face handle. - * - * id :: - * A string describing the service as defined in the service's - * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to - * `multi-masters'). It is automatically prefixed with - * `FT_SERVICE_ID_'. - * - * @output: - * ptr :: - * A variable that receives the service pointer. Will be NULL - * if not found. - */ -#ifdef __cplusplus - -#define FT_FACE_FIND_SERVICE( face, ptr, id ) \ - FT_BEGIN_STMNT \ - FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ - FT_Pointer _tmp_ = NULL; \ - FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \ - \ - \ - if ( module->clazz->get_interface ) \ - _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \ - *_pptr_ = _tmp_; \ - FT_END_STMNT - -#else /* !C++ */ - -#define FT_FACE_FIND_SERVICE( face, ptr, id ) \ - FT_BEGIN_STMNT \ - FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ - FT_Pointer _tmp_ = NULL; \ - \ - if ( module->clazz->get_interface ) \ - _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \ - ptr = _tmp_; \ - FT_END_STMNT - -#endif /* !C++ */ - - - /* - * @macro: - * FT_FACE_FIND_GLOBAL_SERVICE - * - * @description: - * This macro is used to look up a service from all modules. - * - * @input: - * face :: - * The source face handle. - * - * id :: - * A string describing the service as defined in the service's - * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to - * `multi-masters'). It is automatically prefixed with - * `FT_SERVICE_ID_'. - * - * @output: - * ptr :: - * A variable that receives the service pointer. Will be NULL - * if not found. - */ -#ifdef __cplusplus - -#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \ - FT_BEGIN_STMNT \ - FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ - FT_Pointer _tmp_; \ - FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \ - \ - \ - _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \ - *_pptr_ = _tmp_; \ - FT_END_STMNT - -#else /* !C++ */ - -#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \ - FT_BEGIN_STMNT \ - FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \ - FT_Pointer _tmp_; \ - \ - \ - _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \ - ptr = _tmp_; \ - FT_END_STMNT - -#endif /* !C++ */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** S E R V I C E D E S C R I P T O R S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* - * The following structure is used to _describe_ a given service - * to the library. This is useful to build simple static service lists. - */ - typedef struct FT_ServiceDescRec_ - { - const char* serv_id; /* service name */ - const void* serv_data; /* service pointer/data */ - - } FT_ServiceDescRec; - - typedef const FT_ServiceDescRec* FT_ServiceDesc; - - - /*************************************************************************/ - /* */ - /* <Macro> */ - /* FT_DEFINE_SERVICEDESCREC1 */ - /* FT_DEFINE_SERVICEDESCREC2 */ - /* FT_DEFINE_SERVICEDESCREC3 */ - /* FT_DEFINE_SERVICEDESCREC4 */ - /* FT_DEFINE_SERVICEDESCREC5 */ - /* FT_DEFINE_SERVICEDESCREC6 */ - /* FT_DEFINE_SERVICEDESCREC7 */ - /* */ - /* <Description> */ - /* Used to initialize an array of FT_ServiceDescRec structures. */ - /* */ - /* When FT_CONFIG_OPTION_PIC is defined a `create' function needs to */ - /* be called with a pointer to return an allocated array. As soon as */ - /* it is no longer needed, a `destroy' function needs to be called to */ - /* release that allocation. */ - /* */ - /* These functions should be manually called from the `pic_init' and */ - /* `pic_free' functions of your module (see FT_DEFINE_MODULE). */ - /* */ - /* When FT_CONFIG_OPTION_PIC is not defined the array will be */ - /* allocated in the global scope (or the scope where the macro is */ - /* used). */ - /* */ -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICEDESCREC1( class_, \ - serv_id_1, serv_data_1 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { NULL, NULL } \ - }; - -#define FT_DEFINE_SERVICEDESCREC2( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { serv_id_2, serv_data_2 }, \ - { NULL, NULL } \ - }; - -#define FT_DEFINE_SERVICEDESCREC3( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { serv_id_2, serv_data_2 }, \ - { serv_id_3, serv_data_3 }, \ - { NULL, NULL } \ - }; - -#define FT_DEFINE_SERVICEDESCREC4( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { serv_id_2, serv_data_2 }, \ - { serv_id_3, serv_data_3 }, \ - { serv_id_4, serv_data_4 }, \ - { NULL, NULL } \ - }; - -#define FT_DEFINE_SERVICEDESCREC5( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4, \ - serv_id_5, serv_data_5 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { serv_id_2, serv_data_2 }, \ - { serv_id_3, serv_data_3 }, \ - { serv_id_4, serv_data_4 }, \ - { serv_id_5, serv_data_5 }, \ - { NULL, NULL } \ - }; - -#define FT_DEFINE_SERVICEDESCREC6( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4, \ - serv_id_5, serv_data_5, \ - serv_id_6, serv_data_6 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { serv_id_2, serv_data_2 }, \ - { serv_id_3, serv_data_3 }, \ - { serv_id_4, serv_data_4 }, \ - { serv_id_5, serv_data_5 }, \ - { serv_id_6, serv_data_6 }, \ - { NULL, NULL } \ - }; - -#define FT_DEFINE_SERVICEDESCREC7( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4, \ - serv_id_5, serv_data_5, \ - serv_id_6, serv_data_6, \ - serv_id_7, serv_data_7 ) \ - static const FT_ServiceDescRec class_[] = \ - { \ - { serv_id_1, serv_data_1 }, \ - { serv_id_2, serv_data_2 }, \ - { serv_id_3, serv_data_3 }, \ - { serv_id_4, serv_data_4 }, \ - { serv_id_5, serv_data_5 }, \ - { serv_id_6, serv_data_6 }, \ - { serv_id_7, serv_data_7 }, \ - { NULL, NULL } \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICEDESCREC1( class_, \ - serv_id_1, serv_data_1 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class ) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 2 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = NULL; \ - clazz[1].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#define FT_DEFINE_SERVICEDESCREC2( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class ) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 3 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = serv_id_2; \ - clazz[1].serv_data = serv_data_2; \ - clazz[2].serv_id = NULL; \ - clazz[2].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#define FT_DEFINE_SERVICEDESCREC3( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class ) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 4 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = serv_id_2; \ - clazz[1].serv_data = serv_data_2; \ - clazz[2].serv_id = serv_id_3; \ - clazz[2].serv_data = serv_data_3; \ - clazz[3].serv_id = NULL; \ - clazz[3].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#define FT_DEFINE_SERVICEDESCREC4( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class ) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 5 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = serv_id_2; \ - clazz[1].serv_data = serv_data_2; \ - clazz[2].serv_id = serv_id_3; \ - clazz[2].serv_data = serv_data_3; \ - clazz[3].serv_id = serv_id_4; \ - clazz[3].serv_data = serv_data_4; \ - clazz[4].serv_id = NULL; \ - clazz[4].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#define FT_DEFINE_SERVICEDESCREC5( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4, \ - serv_id_5, serv_data_5 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class ) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 6 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = serv_id_2; \ - clazz[1].serv_data = serv_data_2; \ - clazz[2].serv_id = serv_id_3; \ - clazz[2].serv_data = serv_data_3; \ - clazz[3].serv_id = serv_id_4; \ - clazz[3].serv_data = serv_data_4; \ - clazz[4].serv_id = serv_id_5; \ - clazz[4].serv_data = serv_data_5; \ - clazz[5].serv_id = NULL; \ - clazz[5].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#define FT_DEFINE_SERVICEDESCREC6( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4, \ - serv_id_5, serv_data_5, \ - serv_id_6, serv_data_6 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 7 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = serv_id_2; \ - clazz[1].serv_data = serv_data_2; \ - clazz[2].serv_id = serv_id_3; \ - clazz[2].serv_data = serv_data_3; \ - clazz[3].serv_id = serv_id_4; \ - clazz[3].serv_data = serv_data_4; \ - clazz[4].serv_id = serv_id_5; \ - clazz[4].serv_data = serv_data_5; \ - clazz[5].serv_id = serv_id_6; \ - clazz[5].serv_data = serv_data_6; \ - clazz[6].serv_id = NULL; \ - clazz[6].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#define FT_DEFINE_SERVICEDESCREC7( class_, \ - serv_id_1, serv_data_1, \ - serv_id_2, serv_data_2, \ - serv_id_3, serv_data_3, \ - serv_id_4, serv_data_4, \ - serv_id_5, serv_data_5, \ - serv_id_6, serv_data_6, \ - serv_id_7, serv_data_7 ) \ - void \ - FT_Destroy_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec* clazz ) \ - { \ - FT_Memory memory = library->memory; \ - \ - \ - if ( clazz ) \ - FT_FREE( clazz ); \ - } \ - \ - FT_Error \ - FT_Create_Class_ ## class_( FT_Library library, \ - FT_ServiceDescRec** output_class) \ - { \ - FT_ServiceDescRec* clazz = NULL; \ - FT_Error error; \ - FT_Memory memory = library->memory; \ - \ - \ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) ) \ - return error; \ - \ - clazz[0].serv_id = serv_id_1; \ - clazz[0].serv_data = serv_data_1; \ - clazz[1].serv_id = serv_id_2; \ - clazz[1].serv_data = serv_data_2; \ - clazz[2].serv_id = serv_id_3; \ - clazz[2].serv_data = serv_data_3; \ - clazz[3].serv_id = serv_id_4; \ - clazz[3].serv_data = serv_data_4; \ - clazz[4].serv_id = serv_id_5; \ - clazz[4].serv_data = serv_data_5; \ - clazz[5].serv_id = serv_id_6; \ - clazz[5].serv_data = serv_data_6; \ - clazz[6].serv_id = serv_id_7; \ - clazz[6].serv_data = serv_data_7; \ - clazz[7].serv_id = NULL; \ - clazz[7].serv_data = NULL; \ - \ - *output_class = clazz; \ - \ - return FT_Err_Ok; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /* - * Parse a list of FT_ServiceDescRec descriptors and look for - * a specific service by ID. Note that the last element in the - * array must be { NULL, NULL }, and that the function should - * return NULL if the service isn't available. - * - * This function can be used by modules to implement their - * `get_service' method. - */ - FT_BASE( FT_Pointer ) - ft_service_list_lookup( FT_ServiceDesc service_descriptors, - const char* service_id ); - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** S E R V I C E S C A C H E *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* - * This structure is used to store a cache for several frequently used - * services. It is the type of `face->internal->services'. You - * should only use FT_FACE_LOOKUP_SERVICE to access it. - * - * All fields should have the type FT_Pointer to relax compilation - * dependencies. We assume the developer isn't completely stupid. - * - * Each field must be named `service_XXXX' where `XXX' corresponds to - * the correct FT_SERVICE_ID_XXXX macro. See the definition of - * FT_FACE_LOOKUP_SERVICE below how this is implemented. - * - */ - typedef struct FT_ServiceCacheRec_ - { - FT_Pointer service_POSTSCRIPT_FONT_NAME; - FT_Pointer service_MULTI_MASTERS; - FT_Pointer service_GLYPH_DICT; - FT_Pointer service_PFR_METRICS; - FT_Pointer service_WINFNT; - - } FT_ServiceCacheRec, *FT_ServiceCache; - - - /* - * A magic number used within the services cache. - */ - - /* ensure that value `1' has the same width as a pointer */ -#define FT_SERVICE_UNAVAILABLE ((FT_Pointer)~(FT_PtrDist)1) - - - /* - * @macro: - * FT_FACE_LOOKUP_SERVICE - * - * @description: - * This macro is used to lookup a service from a face's driver module - * using its cache. - * - * @input: - * face:: - * The source face handle containing the cache. - * - * field :: - * The field name in the cache. - * - * id :: - * The service ID. - * - * @output: - * ptr :: - * A variable receiving the service data. NULL if not available. - */ -#ifdef __cplusplus - -#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ - FT_BEGIN_STMNT \ - FT_Pointer svc; \ - FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \ - \ - \ - svc = FT_FACE( face )->internal->services. service_ ## id; \ - if ( svc == FT_SERVICE_UNAVAILABLE ) \ - svc = NULL; \ - else if ( svc == NULL ) \ - { \ - FT_FACE_FIND_SERVICE( face, svc, id ); \ - \ - FT_FACE( face )->internal->services. service_ ## id = \ - (FT_Pointer)( svc != NULL ? svc \ - : FT_SERVICE_UNAVAILABLE ); \ - } \ - *Pptr = svc; \ - FT_END_STMNT - -#else /* !C++ */ - -#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ - FT_BEGIN_STMNT \ - FT_Pointer svc; \ - \ - \ - svc = FT_FACE( face )->internal->services. service_ ## id; \ - if ( svc == FT_SERVICE_UNAVAILABLE ) \ - svc = NULL; \ - else if ( svc == NULL ) \ - { \ - FT_FACE_FIND_SERVICE( face, svc, id ); \ - \ - FT_FACE( face )->internal->services. service_ ## id = \ - (FT_Pointer)( svc != NULL ? svc \ - : FT_SERVICE_UNAVAILABLE ); \ - } \ - ptr = svc; \ - FT_END_STMNT - -#endif /* !C++ */ - - /* - * A macro used to define new service structure types. - */ - -#define FT_DEFINE_SERVICE( name ) \ - typedef struct FT_Service_ ## name ## Rec_ \ - FT_Service_ ## name ## Rec ; \ - typedef struct FT_Service_ ## name ## Rec_ \ - const * FT_Service_ ## name ; \ - struct FT_Service_ ## name ## Rec_ - - /* */ - - /* - * The header files containing the services. - */ - -#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h> -#define FT_SERVICE_CID_H <freetype/internal/services/svcid.h> -#define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h> -#define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h> -#define FT_SERVICE_KERNING_H <freetype/internal/services/svkern.h> -#define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h> -#define FT_SERVICE_OPENTYPE_VALIDATE_H <freetype/internal/services/svotval.h> -#define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h> -#define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h> -#define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h> -#define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h> -#define FT_SERVICE_PROPERTIES_H <freetype/internal/services/svprop.h> -#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h> -#define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h> -#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h> -#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h> -#define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h> -#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h> - - /* */ - -FT_END_HEADER - -#endif /* __FTSERV_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftstream.h b/third_party/freetype/include/freetype/internal/ftstream.h deleted file mode 100644 index 384e5df305cdacb59e3cf0d19cc735fffc3df502..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftstream.h +++ /dev/null @@ -1,536 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftstream.h */ -/* */ -/* Stream handling (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTSTREAM_H__ -#define __FTSTREAM_H__ - - -#include <ft2build.h> -#include FT_SYSTEM_H -#include FT_INTERNAL_OBJECTS_H - - -FT_BEGIN_HEADER - - - /* format of an 8-bit frame_op value: */ - /* */ - /* bit 76543210 */ - /* xxxxxxes */ - /* */ - /* s is set to 1 if the value is signed. */ - /* e is set to 1 if the value is little-endian. */ - /* xxx is a command. */ - -#define FT_FRAME_OP_SHIFT 2 -#define FT_FRAME_OP_SIGNED 1 -#define FT_FRAME_OP_LITTLE 2 -#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT ) - -#define FT_MAKE_FRAME_OP( command, little, sign ) \ - ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign ) - -#define FT_FRAME_OP_END 0 -#define FT_FRAME_OP_START 1 /* start a new frame */ -#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */ -#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */ -#define FT_FRAME_OP_LONG 4 /* read 4-byte value */ -#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */ -#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */ - - - typedef enum FT_Frame_Op_ - { - ft_frame_end = 0, - ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ), - - ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ), - ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ), - - ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ), - ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ), - ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ), - ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ), - - ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ), - ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ), - ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ), - ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ), - - ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ), - ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ), - ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ), - ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ), - - ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ), - ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 ) - - } FT_Frame_Op; - - - typedef struct FT_Frame_Field_ - { - FT_Byte value; - FT_Byte size; - FT_UShort offset; - - } FT_Frame_Field; - - - /* Construct an FT_Frame_Field out of a structure type and a field name. */ - /* The structure type must be set in the FT_STRUCTURE macro before */ - /* calling the FT_FRAME_START() macro. */ - /* */ -#define FT_FIELD_SIZE( f ) \ - (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f ) - -#define FT_FIELD_SIZE_DELTA( f ) \ - (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f[0] ) - -#define FT_FIELD_OFFSET( f ) \ - (FT_UShort)( offsetof( FT_STRUCTURE, f ) ) - -#define FT_FRAME_FIELD( frame_op, field ) \ - { \ - frame_op, \ - FT_FIELD_SIZE( field ), \ - FT_FIELD_OFFSET( field ) \ - } - -#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 } - -#define FT_FRAME_START( size ) { ft_frame_start, 0, size } -#define FT_FRAME_END { ft_frame_end, 0, 0 } - -#define FT_FRAME_LONG( f ) FT_FRAME_FIELD( ft_frame_long_be, f ) -#define FT_FRAME_ULONG( f ) FT_FRAME_FIELD( ft_frame_ulong_be, f ) -#define FT_FRAME_SHORT( f ) FT_FRAME_FIELD( ft_frame_short_be, f ) -#define FT_FRAME_USHORT( f ) FT_FRAME_FIELD( ft_frame_ushort_be, f ) -#define FT_FRAME_OFF3( f ) FT_FRAME_FIELD( ft_frame_off3_be, f ) -#define FT_FRAME_UOFF3( f ) FT_FRAME_FIELD( ft_frame_uoff3_be, f ) -#define FT_FRAME_BYTE( f ) FT_FRAME_FIELD( ft_frame_byte, f ) -#define FT_FRAME_CHAR( f ) FT_FRAME_FIELD( ft_frame_schar, f ) - -#define FT_FRAME_LONG_LE( f ) FT_FRAME_FIELD( ft_frame_long_le, f ) -#define FT_FRAME_ULONG_LE( f ) FT_FRAME_FIELD( ft_frame_ulong_le, f ) -#define FT_FRAME_SHORT_LE( f ) FT_FRAME_FIELD( ft_frame_short_le, f ) -#define FT_FRAME_USHORT_LE( f ) FT_FRAME_FIELD( ft_frame_ushort_le, f ) -#define FT_FRAME_OFF3_LE( f ) FT_FRAME_FIELD( ft_frame_off3_le, f ) -#define FT_FRAME_UOFF3_LE( f ) FT_FRAME_FIELD( ft_frame_uoff3_le, f ) - -#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 } -#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 } -#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 } - -#define FT_FRAME_BYTES( field, count ) \ - { \ - ft_frame_bytes, \ - count, \ - FT_FIELD_OFFSET( field ) \ - } - -#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 } - - - /*************************************************************************/ - /* */ - /* Integer extraction macros -- the `buffer' parameter must ALWAYS be of */ - /* type `char*' or equivalent (1-byte elements). */ - /* */ - -#define FT_BYTE_( p, i ) ( ((const FT_Byte*)(p))[(i)] ) - -#define FT_INT16( x ) ( (FT_Int16)(x) ) -#define FT_UINT16( x ) ( (FT_UInt16)(x) ) -#define FT_INT32( x ) ( (FT_Int32)(x) ) -#define FT_UINT32( x ) ( (FT_UInt32)(x) ) - - -#define FT_BYTE_U16( p, i, s ) ( FT_UINT16( FT_BYTE_( p, i ) ) << (s) ) -#define FT_BYTE_U32( p, i, s ) ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) ) - - -#define FT_PEEK_SHORT( p ) FT_INT16( FT_BYTE_U16( p, 0, 8) | \ - FT_BYTE_U16( p, 1, 0) ) - -#define FT_PEEK_USHORT( p ) FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \ - FT_BYTE_U16( p, 1, 0 ) ) - -#define FT_PEEK_LONG( p ) FT_INT32( FT_BYTE_U32( p, 0, 24 ) | \ - FT_BYTE_U32( p, 1, 16 ) | \ - FT_BYTE_U32( p, 2, 8 ) | \ - FT_BYTE_U32( p, 3, 0 ) ) - -#define FT_PEEK_ULONG( p ) FT_UINT32( FT_BYTE_U32( p, 0, 24 ) | \ - FT_BYTE_U32( p, 1, 16 ) | \ - FT_BYTE_U32( p, 2, 8 ) | \ - FT_BYTE_U32( p, 3, 0 ) ) - -#define FT_PEEK_OFF3( p ) FT_INT32( FT_BYTE_U32( p, 0, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 2, 0 ) ) - -#define FT_PEEK_UOFF3( p ) FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 2, 0 ) ) - -#define FT_PEEK_SHORT_LE( p ) FT_INT16( FT_BYTE_U16( p, 1, 8 ) | \ - FT_BYTE_U16( p, 0, 0 ) ) - -#define FT_PEEK_USHORT_LE( p ) FT_UINT16( FT_BYTE_U16( p, 1, 8 ) | \ - FT_BYTE_U16( p, 0, 0 ) ) - -#define FT_PEEK_LONG_LE( p ) FT_INT32( FT_BYTE_U32( p, 3, 24 ) | \ - FT_BYTE_U32( p, 2, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 0, 0 ) ) - -#define FT_PEEK_ULONG_LE( p ) FT_UINT32( FT_BYTE_U32( p, 3, 24 ) | \ - FT_BYTE_U32( p, 2, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 0, 0 ) ) - -#define FT_PEEK_OFF3_LE( p ) FT_INT32( FT_BYTE_U32( p, 2, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 0, 0 ) ) - -#define FT_PEEK_UOFF3_LE( p ) FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 0, 0 ) ) - - -#define FT_NEXT_CHAR( buffer ) \ - ( (signed char)*buffer++ ) - -#define FT_NEXT_BYTE( buffer ) \ - ( (unsigned char)*buffer++ ) - -#define FT_NEXT_SHORT( buffer ) \ - ( (short)( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) ) - -#define FT_NEXT_USHORT( buffer ) \ - ( (unsigned short)( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) ) - -#define FT_NEXT_OFF3( buffer ) \ - ( (long)( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) ) - -#define FT_NEXT_UOFF3( buffer ) \ - ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) ) - -#define FT_NEXT_LONG( buffer ) \ - ( (long)( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) ) - -#define FT_NEXT_ULONG( buffer ) \ - ( (unsigned long)( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) ) - - -#define FT_NEXT_SHORT_LE( buffer ) \ - ( (short)( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) ) - -#define FT_NEXT_USHORT_LE( buffer ) \ - ( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) ) - -#define FT_NEXT_OFF3_LE( buffer ) \ - ( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) ) - -#define FT_NEXT_UOFF3_LE( buffer ) \ - ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) ) - -#define FT_NEXT_LONG_LE( buffer ) \ - ( (long)( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) ) - -#define FT_NEXT_ULONG_LE( buffer ) \ - ( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) ) - - - /*************************************************************************/ - /* */ - /* Each GET_xxxx() macro uses an implicit `stream' variable. */ - /* */ -#if 0 -#define FT_GET_MACRO( type ) FT_NEXT_ ## type ( stream->cursor ) - -#define FT_GET_CHAR() FT_GET_MACRO( CHAR ) -#define FT_GET_BYTE() FT_GET_MACRO( BYTE ) -#define FT_GET_SHORT() FT_GET_MACRO( SHORT ) -#define FT_GET_USHORT() FT_GET_MACRO( USHORT ) -#define FT_GET_OFF3() FT_GET_MACRO( OFF3 ) -#define FT_GET_UOFF3() FT_GET_MACRO( UOFF3 ) -#define FT_GET_LONG() FT_GET_MACRO( LONG ) -#define FT_GET_ULONG() FT_GET_MACRO( ULONG ) -#define FT_GET_TAG4() FT_GET_MACRO( ULONG ) - -#define FT_GET_SHORT_LE() FT_GET_MACRO( SHORT_LE ) -#define FT_GET_USHORT_LE() FT_GET_MACRO( USHORT_LE ) -#define FT_GET_LONG_LE() FT_GET_MACRO( LONG_LE ) -#define FT_GET_ULONG_LE() FT_GET_MACRO( ULONG_LE ) - -#else -#define FT_GET_MACRO( func, type ) ( (type)func( stream ) ) - -#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetChar, FT_Char ) -#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte ) -#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_Short ) -#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort ) -#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_Long ) -#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong ) -#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetULong, FT_Long ) -#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong ) -#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong ) - -#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Short ) -#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UShort ) -#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_Long ) -#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong ) -#endif - -#define FT_READ_MACRO( func, type, var ) \ - ( var = (type)func( stream, &error ), \ - error != FT_Err_Ok ) - -#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var ) -#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var ) -#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var ) -#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_UShort, var ) -#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_Long, var ) -#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_ULong, var ) -#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_Long, var ) -#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_ULong, var ) - -#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Short, var ) -#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UShort, var ) -#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Long, var ) -#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_ULong, var ) - - -#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM - - /* initialize a stream for reading a regular system stream */ - FT_BASE( FT_Error ) - FT_Stream_Open( FT_Stream stream, - const char* filepathname ); - -#endif /* FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ - - - /* create a new (input) stream from an FT_Open_Args structure */ - FT_BASE( FT_Error ) - FT_Stream_New( FT_Library library, - const FT_Open_Args* args, - FT_Stream *astream ); - - /* free a stream */ - FT_BASE( void ) - FT_Stream_Free( FT_Stream stream, - FT_Int external ); - - /* initialize a stream for reading in-memory data */ - FT_BASE( void ) - FT_Stream_OpenMemory( FT_Stream stream, - const FT_Byte* base, - FT_ULong size ); - - /* close a stream (does not destroy the stream structure) */ - FT_BASE( void ) - FT_Stream_Close( FT_Stream stream ); - - - /* seek within a stream. position is relative to start of stream */ - FT_BASE( FT_Error ) - FT_Stream_Seek( FT_Stream stream, - FT_ULong pos ); - - /* skip bytes in a stream */ - FT_BASE( FT_Error ) - FT_Stream_Skip( FT_Stream stream, - FT_Long distance ); - - /* return current stream position */ - FT_BASE( FT_ULong ) - FT_Stream_Pos( FT_Stream stream ); - - /* read bytes from a stream into a user-allocated buffer, returns an */ - /* error if not all bytes could be read. */ - FT_BASE( FT_Error ) - FT_Stream_Read( FT_Stream stream, - FT_Byte* buffer, - FT_ULong count ); - - /* read bytes from a stream at a given position */ - FT_BASE( FT_Error ) - FT_Stream_ReadAt( FT_Stream stream, - FT_ULong pos, - FT_Byte* buffer, - FT_ULong count ); - - /* try to read bytes at the end of a stream; return number of bytes */ - /* really available */ - FT_BASE( FT_ULong ) - FT_Stream_TryRead( FT_Stream stream, - FT_Byte* buffer, - FT_ULong count ); - - /* Enter a frame of `count' consecutive bytes in a stream. Returns an */ - /* error if the frame could not be read/accessed. The caller can use */ - /* the FT_Stream_Get_XXX functions to retrieve frame data without */ - /* error checks. */ - /* */ - /* You must _always_ call FT_Stream_ExitFrame() once you have entered */ - /* a stream frame! */ - /* */ - FT_BASE( FT_Error ) - FT_Stream_EnterFrame( FT_Stream stream, - FT_ULong count ); - - /* exit a stream frame */ - FT_BASE( void ) - FT_Stream_ExitFrame( FT_Stream stream ); - - /* Extract a stream frame. If the stream is disk-based, a heap block */ - /* is allocated and the frame bytes are read into it. If the stream */ - /* is memory-based, this function simply set a pointer to the data. */ - /* */ - /* Useful to optimize access to memory-based streams transparently. */ - /* */ - /* All extracted frames must be `freed' with a call to the function */ - /* FT_Stream_ReleaseFrame(). */ - /* */ - FT_BASE( FT_Error ) - FT_Stream_ExtractFrame( FT_Stream stream, - FT_ULong count, - FT_Byte** pbytes ); - - /* release an extract frame (see FT_Stream_ExtractFrame) */ - FT_BASE( void ) - FT_Stream_ReleaseFrame( FT_Stream stream, - FT_Byte** pbytes ); - - /* read a byte from an entered frame */ - FT_BASE( FT_Char ) - FT_Stream_GetChar( FT_Stream stream ); - - /* read a 16-bit big-endian unsigned integer from an entered frame */ - FT_BASE( FT_UShort ) - FT_Stream_GetUShort( FT_Stream stream ); - - /* read a 24-bit big-endian unsigned integer from an entered frame */ - FT_BASE( FT_ULong ) - FT_Stream_GetUOffset( FT_Stream stream ); - - /* read a 32-bit big-endian unsigned integer from an entered frame */ - FT_BASE( FT_ULong ) - FT_Stream_GetULong( FT_Stream stream ); - - /* read a 16-bit little-endian unsigned integer from an entered frame */ - FT_BASE( FT_UShort ) - FT_Stream_GetUShortLE( FT_Stream stream ); - - /* read a 32-bit little-endian unsigned integer from an entered frame */ - FT_BASE( FT_ULong ) - FT_Stream_GetULongLE( FT_Stream stream ); - - - /* read a byte from a stream */ - FT_BASE( FT_Char ) - FT_Stream_ReadChar( FT_Stream stream, - FT_Error* error ); - - /* read a 16-bit big-endian unsigned integer from a stream */ - FT_BASE( FT_UShort ) - FT_Stream_ReadUShort( FT_Stream stream, - FT_Error* error ); - - /* read a 24-bit big-endian unsigned integer from a stream */ - FT_BASE( FT_ULong ) - FT_Stream_ReadUOffset( FT_Stream stream, - FT_Error* error ); - - /* read a 32-bit big-endian integer from a stream */ - FT_BASE( FT_ULong ) - FT_Stream_ReadULong( FT_Stream stream, - FT_Error* error ); - - /* read a 16-bit little-endian unsigned integer from a stream */ - FT_BASE( FT_UShort ) - FT_Stream_ReadUShortLE( FT_Stream stream, - FT_Error* error ); - - /* read a 32-bit little-endian unsigned integer from a stream */ - FT_BASE( FT_ULong ) - FT_Stream_ReadULongLE( FT_Stream stream, - FT_Error* error ); - - /* Read a structure from a stream. The structure must be described */ - /* by an array of FT_Frame_Field records. */ - FT_BASE( FT_Error ) - FT_Stream_ReadFields( FT_Stream stream, - const FT_Frame_Field* fields, - void* structure ); - - -#define FT_STREAM_POS() \ - FT_Stream_Pos( stream ) - -#define FT_STREAM_SEEK( position ) \ - FT_SET_ERROR( FT_Stream_Seek( stream, \ - (FT_ULong)(position) ) ) - -#define FT_STREAM_SKIP( distance ) \ - FT_SET_ERROR( FT_Stream_Skip( stream, \ - (FT_Long)(distance) ) ) - -#define FT_STREAM_READ( buffer, count ) \ - FT_SET_ERROR( FT_Stream_Read( stream, \ - (FT_Byte*)(buffer), \ - (FT_ULong)(count) ) ) - -#define FT_STREAM_READ_AT( position, buffer, count ) \ - FT_SET_ERROR( FT_Stream_ReadAt( stream, \ - (FT_ULong)(position), \ - (FT_Byte*)buffer, \ - (FT_ULong)(count) ) ) - -#define FT_STREAM_READ_FIELDS( fields, object ) \ - FT_SET_ERROR( FT_Stream_ReadFields( stream, fields, object ) ) - - -#define FT_FRAME_ENTER( size ) \ - FT_SET_ERROR( \ - FT_DEBUG_INNER( FT_Stream_EnterFrame( stream, \ - (FT_ULong)(size) ) ) ) - -#define FT_FRAME_EXIT() \ - FT_DEBUG_INNER( FT_Stream_ExitFrame( stream ) ) - -#define FT_FRAME_EXTRACT( size, bytes ) \ - FT_SET_ERROR( \ - FT_DEBUG_INNER( FT_Stream_ExtractFrame( stream, \ - (FT_ULong)(size), \ - (FT_Byte**)&(bytes) ) ) ) - -#define FT_FRAME_RELEASE( bytes ) \ - FT_DEBUG_INNER( FT_Stream_ReleaseFrame( stream, \ - (FT_Byte**)&(bytes) ) ) - - -FT_END_HEADER - -#endif /* __FTSTREAM_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/fttrace.h b/third_party/freetype/include/freetype/internal/fttrace.h deleted file mode 100644 index 9d28d214d62e312be15e437629da1f76719bd0a7..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/fttrace.h +++ /dev/null @@ -1,154 +0,0 @@ -/***************************************************************************/ -/* */ -/* fttrace.h */ -/* */ -/* Tracing handling (specification only). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /* definitions of trace levels for FreeType 2 */ - - /* the first level must always be `trace_any' */ -FT_TRACE_DEF( any ) - - /* base components */ -FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */ -FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */ -FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */ -FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */ -FT_TRACE_DEF( list ) /* list management (ftlist.c) */ -FT_TRACE_DEF( init ) /* initialization (ftinit.c) */ -FT_TRACE_DEF( objs ) /* base objects (ftobjs.c) */ -FT_TRACE_DEF( outline ) /* outline management (ftoutln.c) */ -FT_TRACE_DEF( glyph ) /* glyph management (ftglyph.c) */ -FT_TRACE_DEF( gloader ) /* glyph loader (ftgloadr.c) */ - -FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */ -FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */ -FT_TRACE_DEF( mm ) /* MM interface (ftmm.c) */ -FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */ -FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */ -FT_TRACE_DEF( bitmap ) /* bitmap checksum (ftobjs.c) */ - - /* Cache sub-system */ -FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */ - - /* SFNT driver components */ -FT_TRACE_DEF( sfdriver ) /* SFNT font driver (sfdriver.c) */ -FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */ -FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ -FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */ -FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */ -FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */ -FT_TRACE_DEF( ttpost ) /* PS table processing (ttpost.c) */ -FT_TRACE_DEF( ttsbit ) /* TrueType sbit handling (ttsbit.c) */ -FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */ - - /* TrueType driver components */ -FT_TRACE_DEF( ttdriver ) /* TT font driver (ttdriver.c) */ -FT_TRACE_DEF( ttgload ) /* TT glyph loader (ttgload.c) */ -FT_TRACE_DEF( ttinterp ) /* bytecode interpreter (ttinterp.c) */ -FT_TRACE_DEF( ttobjs ) /* TT objects manager (ttobjs.c) */ -FT_TRACE_DEF( ttpload ) /* TT data/program loader (ttpload.c) */ -FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */ - - /* Type 1 driver components */ -FT_TRACE_DEF( t1afm ) -FT_TRACE_DEF( t1driver ) -FT_TRACE_DEF( t1gload ) -FT_TRACE_DEF( t1hint ) -FT_TRACE_DEF( t1load ) -FT_TRACE_DEF( t1objs ) -FT_TRACE_DEF( t1parse ) - - /* PostScript helper module `psaux' */ -FT_TRACE_DEF( t1decode ) -FT_TRACE_DEF( psobjs ) -FT_TRACE_DEF( psconv ) - - /* PostScript hinting module `pshinter' */ -FT_TRACE_DEF( pshrec ) -FT_TRACE_DEF( pshalgo1 ) -FT_TRACE_DEF( pshalgo2 ) - - /* Type 2 driver components */ -FT_TRACE_DEF( cffdriver ) -FT_TRACE_DEF( cffgload ) -FT_TRACE_DEF( cffload ) -FT_TRACE_DEF( cffobjs ) -FT_TRACE_DEF( cffparse ) - -FT_TRACE_DEF( cf2blues ) -FT_TRACE_DEF( cf2hints ) -FT_TRACE_DEF( cf2interp ) - - /* Type 42 driver component */ -FT_TRACE_DEF( t42 ) - - /* CID driver components */ -FT_TRACE_DEF( cidafm ) -FT_TRACE_DEF( ciddriver ) -FT_TRACE_DEF( cidgload ) -FT_TRACE_DEF( cidload ) -FT_TRACE_DEF( cidobjs ) -FT_TRACE_DEF( cidparse ) - - /* Windows font component */ -FT_TRACE_DEF( winfnt ) - - /* PCF font components */ -FT_TRACE_DEF( pcfdriver ) -FT_TRACE_DEF( pcfread ) - - /* BDF font components */ -FT_TRACE_DEF( bdfdriver ) -FT_TRACE_DEF( bdflib ) - - /* PFR font component */ -FT_TRACE_DEF( pfr ) - - /* OpenType validation components */ -FT_TRACE_DEF( otvmodule ) -FT_TRACE_DEF( otvcommon ) -FT_TRACE_DEF( otvbase ) -FT_TRACE_DEF( otvgdef ) -FT_TRACE_DEF( otvgpos ) -FT_TRACE_DEF( otvgsub ) -FT_TRACE_DEF( otvjstf ) -FT_TRACE_DEF( otvmath ) - - /* TrueTypeGX/AAT validation components */ -FT_TRACE_DEF( gxvmodule ) -FT_TRACE_DEF( gxvcommon ) -FT_TRACE_DEF( gxvfeat ) -FT_TRACE_DEF( gxvmort ) -FT_TRACE_DEF( gxvmorx ) -FT_TRACE_DEF( gxvbsln ) -FT_TRACE_DEF( gxvjust ) -FT_TRACE_DEF( gxvkern ) -FT_TRACE_DEF( gxvopbd ) -FT_TRACE_DEF( gxvtrak ) -FT_TRACE_DEF( gxvprop ) -FT_TRACE_DEF( gxvlcar ) - - /* autofit components */ -FT_TRACE_DEF( afmodule ) -FT_TRACE_DEF( afhints ) -FT_TRACE_DEF( afcjk ) -FT_TRACE_DEF( aflatin ) -FT_TRACE_DEF( aflatin2 ) -FT_TRACE_DEF( afwarp ) -FT_TRACE_DEF( afharfbuzz ) -FT_TRACE_DEF( afglobal ) - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/ftvalid.h b/third_party/freetype/include/freetype/internal/ftvalid.h deleted file mode 100644 index 9cda6eef5f6747e2b31b101ba2fc0b1df947d188..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/ftvalid.h +++ /dev/null @@ -1,159 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftvalid.h */ -/* */ -/* FreeType validation support (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTVALID_H__ -#define __FTVALID_H__ - -#include <ft2build.h> -#include FT_CONFIG_STANDARD_LIBRARY_H /* for ft_setjmp and ft_longjmp */ - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** V A L I D A T I O N ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /* handle to a validation object */ - typedef struct FT_ValidatorRec_ volatile* FT_Validator; - - - /*************************************************************************/ - /* */ - /* There are three distinct validation levels defined here: */ - /* */ - /* FT_VALIDATE_DEFAULT :: */ - /* A table that passes this validation level can be used reliably by */ - /* FreeType. It generally means that all offsets have been checked to */ - /* prevent out-of-bound reads, that array counts are correct, etc. */ - /* */ - /* FT_VALIDATE_TIGHT :: */ - /* A table that passes this validation level can be used reliably and */ - /* doesn't contain invalid data. For example, a charmap table that */ - /* returns invalid glyph indices will not pass, even though it can */ - /* be used with FreeType in default mode (the library will simply */ - /* return an error later when trying to load the glyph). */ - /* */ - /* It also checks that fields which must be a multiple of 2, 4, or 8, */ - /* don't have incorrect values, etc. */ - /* */ - /* FT_VALIDATE_PARANOID :: */ - /* Only for font debugging. Checks that a table follows the */ - /* specification by 100%. Very few fonts will be able to pass this */ - /* level anyway but it can be useful for certain tools like font */ - /* editors/converters. */ - /* */ - typedef enum FT_ValidationLevel_ - { - FT_VALIDATE_DEFAULT = 0, - FT_VALIDATE_TIGHT, - FT_VALIDATE_PARANOID - - } FT_ValidationLevel; - - -#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ - /* We disable the warning `structure was padded due to */ - /* __declspec(align())' in order to compile cleanly with */ - /* the maximum level of warnings. */ -#pragma warning( push ) -#pragma warning( disable : 4324 ) -#endif /* _MSC_VER */ - - /* validator structure */ - typedef struct FT_ValidatorRec_ - { - ft_jmp_buf jump_buffer; /* used for exception handling */ - - const FT_Byte* base; /* address of table in memory */ - const FT_Byte* limit; /* `base' + sizeof(table) in memory */ - FT_ValidationLevel level; /* validation level */ - FT_Error error; /* error returned. 0 means success */ - - } FT_ValidatorRec; - -#if defined( _MSC_VER ) -#pragma warning( pop ) -#endif - -#define FT_VALIDATOR( x ) ( (FT_Validator)( x ) ) - - - FT_BASE( void ) - ft_validator_init( FT_Validator valid, - const FT_Byte* base, - const FT_Byte* limit, - FT_ValidationLevel level ); - - /* Do not use this. It's broken and will cause your validator to crash */ - /* if you run it on an invalid font. */ - FT_BASE( FT_Int ) - ft_validator_run( FT_Validator valid ); - - /* Sets the error field in a validator, then calls `longjmp' to return */ - /* to high-level caller. Using `setjmp/longjmp' avoids many stupid */ - /* error checks within the validation routines. */ - /* */ - FT_BASE( void ) - ft_validator_error( FT_Validator valid, - FT_Error error ); - - - /* Calls ft_validate_error. Assumes that the `valid' local variable */ - /* holds a pointer to the current validator object. */ - /* */ -#define FT_INVALID( _error ) FT_INVALID_( _error ) -#define FT_INVALID_( _error ) \ - ft_validator_error( valid, FT_THROW( _error ) ) - - /* called when a broken table is detected */ -#define FT_INVALID_TOO_SHORT \ - FT_INVALID( Invalid_Table ) - - /* called when an invalid offset is detected */ -#define FT_INVALID_OFFSET \ - FT_INVALID( Invalid_Offset ) - - /* called when an invalid format/value is detected */ -#define FT_INVALID_FORMAT \ - FT_INVALID( Invalid_Table ) - - /* called when an invalid glyph index is detected */ -#define FT_INVALID_GLYPH_ID \ - FT_INVALID( Invalid_Glyph_Index ) - - /* called when an invalid field value is detected */ -#define FT_INVALID_DATA \ - FT_INVALID( Invalid_Table ) - - -FT_END_HEADER - -#endif /* __FTVALID_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/internal.h b/third_party/freetype/include/freetype/internal/internal.h deleted file mode 100644 index 809ce59c92fb3cbe8e82e88f72cdd168c7ca4f11..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/internal.h +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************/ -/* */ -/* internal.h */ -/* */ -/* Internal header files (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is automatically included by `ft2build.h'. */ - /* Do not include it manually! */ - /* */ - /*************************************************************************/ - - -#define FT_INTERNAL_OBJECTS_H <freetype/internal/ftobjs.h> -#define FT_INTERNAL_PIC_H <freetype/internal/ftpic.h> -#define FT_INTERNAL_STREAM_H <freetype/internal/ftstream.h> -#define FT_INTERNAL_MEMORY_H <freetype/internal/ftmemory.h> -#define FT_INTERNAL_DEBUG_H <freetype/internal/ftdebug.h> -#define FT_INTERNAL_CALC_H <freetype/internal/ftcalc.h> -#define FT_INTERNAL_DRIVER_H <freetype/internal/ftdriver.h> -#define FT_INTERNAL_TRACE_H <freetype/internal/fttrace.h> -#define FT_INTERNAL_GLYPH_LOADER_H <freetype/internal/ftgloadr.h> -#define FT_INTERNAL_SFNT_H <freetype/internal/sfnt.h> -#define FT_INTERNAL_SERVICE_H <freetype/internal/ftserv.h> -#define FT_INTERNAL_RFORK_H <freetype/internal/ftrfork.h> -#define FT_INTERNAL_VALIDATE_H <freetype/internal/ftvalid.h> - -#define FT_INTERNAL_TRUETYPE_TYPES_H <freetype/internal/tttypes.h> -#define FT_INTERNAL_TYPE1_TYPES_H <freetype/internal/t1types.h> - -#define FT_INTERNAL_POSTSCRIPT_AUX_H <freetype/internal/psaux.h> -#define FT_INTERNAL_POSTSCRIPT_HINTS_H <freetype/internal/pshints.h> -#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H <freetype/internal/psglobal.h> - -#define FT_INTERNAL_AUTOHINT_H <freetype/internal/autohint.h> - - -#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ - - /* We disable the warning `conditional expression is constant' here */ - /* in order to compile cleanly with the maximum level of warnings. */ - /* In particular, the warning complains about stuff like `while(0)' */ - /* which is very useful in macro definitions. There is no benefit */ - /* in having it enabled. */ -#pragma warning( disable : 4127 ) - -#endif /* _MSC_VER */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/psaux.h b/third_party/freetype/include/freetype/internal/psaux.h deleted file mode 100644 index 1c5f784f52c1725bbf6edf91ee0e5fbea9022f25..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/psaux.h +++ /dev/null @@ -1,877 +0,0 @@ -/***************************************************************************/ -/* */ -/* psaux.h */ -/* */ -/* Auxiliary functions and data structures related to PostScript fonts */ -/* (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSAUX_H__ -#define __PSAUX_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_TYPE1_TYPES_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1_TABLE *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - typedef struct PS_TableRec_* PS_Table; - typedef const struct PS_Table_FuncsRec_* PS_Table_Funcs; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_Table_FuncsRec */ - /* */ - /* <Description> */ - /* A set of function pointers to manage PS_Table objects. */ - /* */ - /* <Fields> */ - /* table_init :: Used to initialize a table. */ - /* */ - /* table_done :: Finalizes resp. destroy a given table. */ - /* */ - /* table_add :: Adds a new object to a table. */ - /* */ - /* table_release :: Releases table data, then finalizes it. */ - /* */ - typedef struct PS_Table_FuncsRec_ - { - FT_Error - (*init)( PS_Table table, - FT_Int count, - FT_Memory memory ); - - void - (*done)( PS_Table table ); - - FT_Error - (*add)( PS_Table table, - FT_Int idx, - void* object, - FT_UInt length ); - - void - (*release)( PS_Table table ); - - } PS_Table_FuncsRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_TableRec */ - /* */ - /* <Description> */ - /* A PS_Table is a simple object used to store an array of objects in */ - /* a single memory block. */ - /* */ - /* <Fields> */ - /* block :: The address in memory of the growheap's block. This */ - /* can change between two object adds, due to */ - /* reallocation. */ - /* */ - /* cursor :: The current top of the grow heap within its block. */ - /* */ - /* capacity :: The current size of the heap block. Increments by */ - /* 1kByte chunks. */ - /* */ - /* init :: Set to 0xDEADBEEF if `elements' and `lengths' have */ - /* been allocated. */ - /* */ - /* max_elems :: The maximum number of elements in table. */ - /* */ - /* num_elems :: The current number of elements in table. */ - /* */ - /* elements :: A table of element addresses within the block. */ - /* */ - /* lengths :: A table of element sizes within the block. */ - /* */ - /* memory :: The object used for memory operations */ - /* (alloc/realloc). */ - /* */ - /* funcs :: A table of method pointers for this object. */ - /* */ - typedef struct PS_TableRec_ - { - FT_Byte* block; /* current memory block */ - FT_Offset cursor; /* current cursor in memory block */ - FT_Offset capacity; /* current size of memory block */ - FT_ULong init; - - FT_Int max_elems; - FT_Int num_elems; - FT_Byte** elements; /* addresses of table elements */ - FT_UInt* lengths; /* lengths of table elements */ - - FT_Memory memory; - PS_Table_FuncsRec funcs; - - } PS_TableRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 FIELDS & TOKENS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef struct PS_ParserRec_* PS_Parser; - - typedef struct T1_TokenRec_* T1_Token; - - typedef struct T1_FieldRec_* T1_Field; - - - /* simple enumeration type used to identify token types */ - typedef enum T1_TokenType_ - { - T1_TOKEN_TYPE_NONE = 0, - T1_TOKEN_TYPE_ANY, - T1_TOKEN_TYPE_STRING, - T1_TOKEN_TYPE_ARRAY, - T1_TOKEN_TYPE_KEY, /* aka `name' */ - - /* do not remove */ - T1_TOKEN_TYPE_MAX - - } T1_TokenType; - - - /* a simple structure used to identify tokens */ - typedef struct T1_TokenRec_ - { - FT_Byte* start; /* first character of token in input stream */ - FT_Byte* limit; /* first character after the token */ - T1_TokenType type; /* type of token */ - - } T1_TokenRec; - - - /* enumeration type used to identify object fields */ - typedef enum T1_FieldType_ - { - T1_FIELD_TYPE_NONE = 0, - T1_FIELD_TYPE_BOOL, - T1_FIELD_TYPE_INTEGER, - T1_FIELD_TYPE_FIXED, - T1_FIELD_TYPE_FIXED_1000, - T1_FIELD_TYPE_STRING, - T1_FIELD_TYPE_KEY, - T1_FIELD_TYPE_BBOX, - T1_FIELD_TYPE_MM_BBOX, - T1_FIELD_TYPE_INTEGER_ARRAY, - T1_FIELD_TYPE_FIXED_ARRAY, - T1_FIELD_TYPE_CALLBACK, - - /* do not remove */ - T1_FIELD_TYPE_MAX - - } T1_FieldType; - - - typedef enum T1_FieldLocation_ - { - T1_FIELD_LOCATION_CID_INFO, - T1_FIELD_LOCATION_FONT_DICT, - T1_FIELD_LOCATION_FONT_EXTRA, - T1_FIELD_LOCATION_FONT_INFO, - T1_FIELD_LOCATION_PRIVATE, - T1_FIELD_LOCATION_BBOX, - T1_FIELD_LOCATION_LOADER, - T1_FIELD_LOCATION_FACE, - T1_FIELD_LOCATION_BLEND, - - /* do not remove */ - T1_FIELD_LOCATION_MAX - - } T1_FieldLocation; - - - typedef void - (*T1_Field_ParseFunc)( FT_Face face, - FT_Pointer parser ); - - - /* structure type used to model object fields */ - typedef struct T1_FieldRec_ - { - const char* ident; /* field identifier */ - T1_FieldLocation location; - T1_FieldType type; /* type of field */ - T1_Field_ParseFunc reader; - FT_UInt offset; /* offset of field in object */ - FT_Byte size; /* size of field in bytes */ - FT_UInt array_max; /* maximum number of elements for */ - /* array */ - FT_UInt count_offset; /* offset of element count for */ - /* arrays; must not be zero if in */ - /* use -- in other words, a */ - /* `num_FOO' element must not */ - /* start the used structure if we */ - /* parse a `FOO' array */ - FT_UInt dict; /* where we expect it */ - } T1_FieldRec; - -#define T1_FIELD_DICT_FONTDICT ( 1 << 0 ) /* also FontInfo and FDArray */ -#define T1_FIELD_DICT_PRIVATE ( 1 << 1 ) - - - -#define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \ - { \ - _ident, T1CODE, _type, \ - 0, \ - FT_FIELD_OFFSET( _fname ), \ - FT_FIELD_SIZE( _fname ), \ - 0, 0, \ - _dict \ - }, - -#define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \ - { \ - _ident, T1CODE, T1_FIELD_TYPE_CALLBACK, \ - (T1_Field_ParseFunc)_reader, \ - 0, 0, \ - 0, 0, \ - _dict \ - }, - -#define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \ - { \ - _ident, T1CODE, _type, \ - 0, \ - FT_FIELD_OFFSET( _fname ), \ - FT_FIELD_SIZE_DELTA( _fname ), \ - _max, \ - FT_FIELD_OFFSET( num_ ## _fname ), \ - _dict \ - }, - -#define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \ - { \ - _ident, T1CODE, _type, \ - 0, \ - FT_FIELD_OFFSET( _fname ), \ - FT_FIELD_SIZE_DELTA( _fname ), \ - _max, 0, \ - _dict \ - }, - - -#define T1_FIELD_BOOL( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BOOL, _fname, _dict ) - -#define T1_FIELD_NUM( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER, _fname, _dict ) - -#define T1_FIELD_FIXED( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED, _fname, _dict ) - -#define T1_FIELD_FIXED_1000( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_1000, _fname, \ - _dict ) - -#define T1_FIELD_STRING( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_STRING, _fname, _dict ) - -#define T1_FIELD_KEY( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_KEY, _fname, _dict ) - -#define T1_FIELD_BBOX( _ident, _fname, _dict ) \ - T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BBOX, _fname, _dict ) - - -#define T1_FIELD_NUM_TABLE( _ident, _fname, _fmax, _dict ) \ - T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \ - _fname, _fmax, _dict ) - -#define T1_FIELD_FIXED_TABLE( _ident, _fname, _fmax, _dict ) \ - T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \ - _fname, _fmax, _dict ) - -#define T1_FIELD_NUM_TABLE2( _ident, _fname, _fmax, _dict ) \ - T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \ - _fname, _fmax, _dict ) - -#define T1_FIELD_FIXED_TABLE2( _ident, _fname, _fmax, _dict ) \ - T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \ - _fname, _fmax, _dict ) - -#define T1_FIELD_CALLBACK( _ident, _name, _dict ) \ - T1_NEW_CALLBACK_FIELD( _ident, _name, _dict ) - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 PARSER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef const struct PS_Parser_FuncsRec_* PS_Parser_Funcs; - - typedef struct PS_Parser_FuncsRec_ - { - void - (*init)( PS_Parser parser, - FT_Byte* base, - FT_Byte* limit, - FT_Memory memory ); - - void - (*done)( PS_Parser parser ); - - void - (*skip_spaces)( PS_Parser parser ); - void - (*skip_PS_token)( PS_Parser parser ); - - FT_Long - (*to_int)( PS_Parser parser ); - FT_Fixed - (*to_fixed)( PS_Parser parser, - FT_Int power_ten ); - - FT_Error - (*to_bytes)( PS_Parser parser, - FT_Byte* bytes, - FT_Offset max_bytes, - FT_ULong* pnum_bytes, - FT_Bool delimiters ); - - FT_Int - (*to_coord_array)( PS_Parser parser, - FT_Int max_coords, - FT_Short* coords ); - FT_Int - (*to_fixed_array)( PS_Parser parser, - FT_Int max_values, - FT_Fixed* values, - FT_Int power_ten ); - - void - (*to_token)( PS_Parser parser, - T1_Token token ); - void - (*to_token_array)( PS_Parser parser, - T1_Token tokens, - FT_UInt max_tokens, - FT_Int* pnum_tokens ); - - FT_Error - (*load_field)( PS_Parser parser, - const T1_Field field, - void** objects, - FT_UInt max_objects, - FT_ULong* pflags ); - - FT_Error - (*load_field_table)( PS_Parser parser, - const T1_Field field, - void** objects, - FT_UInt max_objects, - FT_ULong* pflags ); - - } PS_Parser_FuncsRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_ParserRec */ - /* */ - /* <Description> */ - /* A PS_Parser is an object used to parse a Type 1 font very quickly. */ - /* */ - /* <Fields> */ - /* cursor :: The current position in the text. */ - /* */ - /* base :: Start of the processed text. */ - /* */ - /* limit :: End of the processed text. */ - /* */ - /* error :: The last error returned. */ - /* */ - /* memory :: The object used for memory operations (alloc/realloc). */ - /* */ - /* funcs :: A table of functions for the parser. */ - /* */ - typedef struct PS_ParserRec_ - { - FT_Byte* cursor; - FT_Byte* base; - FT_Byte* limit; - FT_Error error; - FT_Memory memory; - - PS_Parser_FuncsRec funcs; - - } PS_ParserRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 BUILDER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - typedef struct T1_BuilderRec_* T1_Builder; - - - typedef FT_Error - (*T1_Builder_Check_Points_Func)( T1_Builder builder, - FT_Int count ); - - typedef void - (*T1_Builder_Add_Point_Func)( T1_Builder builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ); - - typedef FT_Error - (*T1_Builder_Add_Point1_Func)( T1_Builder builder, - FT_Pos x, - FT_Pos y ); - - typedef FT_Error - (*T1_Builder_Add_Contour_Func)( T1_Builder builder ); - - typedef FT_Error - (*T1_Builder_Start_Point_Func)( T1_Builder builder, - FT_Pos x, - FT_Pos y ); - - typedef void - (*T1_Builder_Close_Contour_Func)( T1_Builder builder ); - - - typedef const struct T1_Builder_FuncsRec_* T1_Builder_Funcs; - - typedef struct T1_Builder_FuncsRec_ - { - void - (*init)( T1_Builder builder, - FT_Face face, - FT_Size size, - FT_GlyphSlot slot, - FT_Bool hinting ); - - void - (*done)( T1_Builder builder ); - - T1_Builder_Check_Points_Func check_points; - T1_Builder_Add_Point_Func add_point; - T1_Builder_Add_Point1_Func add_point1; - T1_Builder_Add_Contour_Func add_contour; - T1_Builder_Start_Point_Func start_point; - T1_Builder_Close_Contour_Func close_contour; - - } T1_Builder_FuncsRec; - - - /* an enumeration type to handle charstring parsing states */ - typedef enum T1_ParseState_ - { - T1_Parse_Start, - T1_Parse_Have_Width, - T1_Parse_Have_Moveto, - T1_Parse_Have_Path - - } T1_ParseState; - - - /*************************************************************************/ - /* */ - /* <Structure> */ - /* T1_BuilderRec */ - /* */ - /* <Description> */ - /* A structure used during glyph loading to store its outline. */ - /* */ - /* <Fields> */ - /* memory :: The current memory object. */ - /* */ - /* face :: The current face object. */ - /* */ - /* glyph :: The current glyph slot. */ - /* */ - /* loader :: XXX */ - /* */ - /* base :: The base glyph outline. */ - /* */ - /* current :: The current glyph outline. */ - /* */ - /* max_points :: maximum points in builder outline */ - /* */ - /* max_contours :: Maximum number of contours in builder outline. */ - /* */ - /* pos_x :: The horizontal translation (if composite glyph). */ - /* */ - /* pos_y :: The vertical translation (if composite glyph). */ - /* */ - /* left_bearing :: The left side bearing point. */ - /* */ - /* advance :: The horizontal advance vector. */ - /* */ - /* bbox :: Unused. */ - /* */ - /* parse_state :: An enumeration which controls the charstring */ - /* parsing state. */ - /* */ - /* load_points :: If this flag is not set, no points are loaded. */ - /* */ - /* no_recurse :: Set but not used. */ - /* */ - /* metrics_only :: A boolean indicating that we only want to compute */ - /* the metrics of a given glyph, not load all of its */ - /* points. */ - /* */ - /* funcs :: An array of function pointers for the builder. */ - /* */ - typedef struct T1_BuilderRec_ - { - FT_Memory memory; - FT_Face face; - FT_GlyphSlot glyph; - FT_GlyphLoader loader; - FT_Outline* base; - FT_Outline* current; - - FT_Pos pos_x; - FT_Pos pos_y; - - FT_Vector left_bearing; - FT_Vector advance; - - FT_BBox bbox; /* bounding box */ - T1_ParseState parse_state; - FT_Bool load_points; - FT_Bool no_recurse; - - FT_Bool metrics_only; - - void* hints_funcs; /* hinter-specific */ - void* hints_globals; /* hinter-specific */ - - T1_Builder_FuncsRec funcs; - - } T1_BuilderRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 DECODER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#if 0 - - /*************************************************************************/ - /* */ - /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ - /* calls during glyph loading. */ - /* */ -#define T1_MAX_SUBRS_CALLS 8 - - - /*************************************************************************/ - /* */ - /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ - /* minimum of 16 is required. */ - /* */ -#define T1_MAX_CHARSTRINGS_OPERANDS 32 - -#endif /* 0 */ - - - typedef struct T1_Decoder_ZoneRec_ - { - FT_Byte* cursor; - FT_Byte* base; - FT_Byte* limit; - - } T1_Decoder_ZoneRec, *T1_Decoder_Zone; - - - typedef struct T1_DecoderRec_* T1_Decoder; - typedef const struct T1_Decoder_FuncsRec_* T1_Decoder_Funcs; - - - typedef FT_Error - (*T1_Decoder_Callback)( T1_Decoder decoder, - FT_UInt glyph_index ); - - - typedef struct T1_Decoder_FuncsRec_ - { - FT_Error - (*init)( T1_Decoder decoder, - FT_Face face, - FT_Size size, - FT_GlyphSlot slot, - FT_Byte** glyph_names, - PS_Blend blend, - FT_Bool hinting, - FT_Render_Mode hint_mode, - T1_Decoder_Callback callback ); - - void - (*done)( T1_Decoder decoder ); - - FT_Error - (*parse_charstrings)( T1_Decoder decoder, - FT_Byte* base, - FT_UInt len ); - - } T1_Decoder_FuncsRec; - - - typedef struct T1_DecoderRec_ - { - T1_BuilderRec builder; - - FT_Long stack[T1_MAX_CHARSTRINGS_OPERANDS]; - FT_Long* top; - - T1_Decoder_ZoneRec zones[T1_MAX_SUBRS_CALLS + 1]; - T1_Decoder_Zone zone; - - FT_Service_PsCMaps psnames; /* for seac */ - FT_UInt num_glyphs; - FT_Byte** glyph_names; - - FT_Int lenIV; /* internal for sub routine calls */ - FT_Int num_subrs; - FT_Byte** subrs; - FT_UInt* subrs_len; /* array of subrs length (optional) */ - - FT_Matrix font_matrix; - FT_Vector font_offset; - - FT_Int flex_state; - FT_Int num_flex_vectors; - FT_Vector flex_vectors[7]; - - PS_Blend blend; /* for multiple master support */ - - FT_Render_Mode hint_mode; - - T1_Decoder_Callback parse_callback; - T1_Decoder_FuncsRec funcs; - - FT_Long* buildchar; - FT_UInt len_buildchar; - - FT_Bool seac; - - } T1_DecoderRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** AFM PARSER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef struct AFM_ParserRec_* AFM_Parser; - - typedef struct AFM_Parser_FuncsRec_ - { - FT_Error - (*init)( AFM_Parser parser, - FT_Memory memory, - FT_Byte* base, - FT_Byte* limit ); - - void - (*done)( AFM_Parser parser ); - - FT_Error - (*parse)( AFM_Parser parser ); - - } AFM_Parser_FuncsRec; - - - typedef struct AFM_StreamRec_* AFM_Stream; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* AFM_ParserRec */ - /* */ - /* <Description> */ - /* An AFM_Parser is a parser for the AFM files. */ - /* */ - /* <Fields> */ - /* memory :: The object used for memory operations (alloc and */ - /* realloc). */ - /* */ - /* stream :: This is an opaque object. */ - /* */ - /* FontInfo :: The result will be stored here. */ - /* */ - /* get_index :: A user provided function to get a glyph index by its */ - /* name. */ - /* */ - typedef struct AFM_ParserRec_ - { - FT_Memory memory; - AFM_Stream stream; - - AFM_FontInfo FontInfo; - - FT_Int - (*get_index)( const char* name, - FT_Offset len, - void* user_data ); - - void* user_data; - - } AFM_ParserRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 CHARMAPS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef const struct T1_CMap_ClassesRec_* T1_CMap_Classes; - - typedef struct T1_CMap_ClassesRec_ - { - FT_CMap_Class standard; - FT_CMap_Class expert; - FT_CMap_Class custom; - FT_CMap_Class unicode; - - } T1_CMap_ClassesRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PSAux Module Interface *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef struct PSAux_ServiceRec_ - { - /* don't use `PS_Table_Funcs' and friends to avoid compiler warnings */ - const PS_Table_FuncsRec* ps_table_funcs; - const PS_Parser_FuncsRec* ps_parser_funcs; - const T1_Builder_FuncsRec* t1_builder_funcs; - const T1_Decoder_FuncsRec* t1_decoder_funcs; - - void - (*t1_decrypt)( FT_Byte* buffer, - FT_Offset length, - FT_UShort seed ); - - T1_CMap_Classes t1_cmap_classes; - - /* fields after this comment line were added after version 2.1.10 */ - const AFM_Parser_FuncsRec* afm_parser_funcs; - - } PSAux_ServiceRec, *PSAux_Service; - - /* backwards-compatible type definition */ - typedef PSAux_ServiceRec PSAux_Interface; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** Some convenience functions *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define IS_PS_NEWLINE( ch ) \ - ( (ch) == '\r' || \ - (ch) == '\n' ) - -#define IS_PS_SPACE( ch ) \ - ( (ch) == ' ' || \ - IS_PS_NEWLINE( ch ) || \ - (ch) == '\t' || \ - (ch) == '\f' || \ - (ch) == '\0' ) - -#define IS_PS_SPECIAL( ch ) \ - ( (ch) == '/' || \ - (ch) == '(' || (ch) == ')' || \ - (ch) == '<' || (ch) == '>' || \ - (ch) == '[' || (ch) == ']' || \ - (ch) == '{' || (ch) == '}' || \ - (ch) == '%' ) - -#define IS_PS_DELIM( ch ) \ - ( IS_PS_SPACE( ch ) || \ - IS_PS_SPECIAL( ch ) ) - -#define IS_PS_DIGIT( ch ) \ - ( (ch) >= '0' && (ch) <= '9' ) - -#define IS_PS_XDIGIT( ch ) \ - ( IS_PS_DIGIT( ch ) || \ - ( (ch) >= 'A' && (ch) <= 'F' ) || \ - ( (ch) >= 'a' && (ch) <= 'f' ) ) - -#define IS_PS_BASE85( ch ) \ - ( (ch) >= '!' && (ch) <= 'u' ) - -#define IS_PS_TOKEN( cur, limit, token ) \ - ( (char)(cur)[0] == (token)[0] && \ - ( (cur) + sizeof ( (token) ) == (limit) || \ - ( (cur) + sizeof( (token) ) < (limit) && \ - IS_PS_DELIM( (cur)[sizeof ( (token) ) - 1] ) ) ) && \ - ft_strncmp( (char*)(cur), (token), sizeof ( (token) ) - 1 ) == 0 ) - - -FT_END_HEADER - -#endif /* __PSAUX_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/pshints.h b/third_party/freetype/include/freetype/internal/pshints.h deleted file mode 100644 index 12aaabacd4363cb95081c66cd712b7e520a9f69a..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/pshints.h +++ /dev/null @@ -1,722 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshints.h */ -/* */ -/* Interface to Postscript-specific (Type 1 and Type 2) hints */ -/* recorders (specification only). These are used to support native */ -/* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSHINTS_H__ -#define __PSHINTS_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TYPE1_TABLES_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** INTERNAL REPRESENTATION OF GLOBALS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef struct PSH_GlobalsRec_* PSH_Globals; - - typedef FT_Error - (*PSH_Globals_NewFunc)( FT_Memory memory, - T1_Private* private_dict, - PSH_Globals* aglobals ); - - typedef void - (*PSH_Globals_SetScaleFunc)( PSH_Globals globals, - FT_Fixed x_scale, - FT_Fixed y_scale, - FT_Fixed x_delta, - FT_Fixed y_delta ); - - typedef void - (*PSH_Globals_DestroyFunc)( PSH_Globals globals ); - - - typedef struct PSH_Globals_FuncsRec_ - { - PSH_Globals_NewFunc create; - PSH_Globals_SetScaleFunc set_scale; - PSH_Globals_DestroyFunc destroy; - - } PSH_Globals_FuncsRec, *PSH_Globals_Funcs; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PUBLIC TYPE 1 HINTS RECORDER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /************************************************************************* - * - * @type: - * T1_Hints - * - * @description: - * This is a handle to an opaque structure used to record glyph hints - * from a Type 1 character glyph character string. - * - * The methods used to operate on this object are defined by the - * @T1_Hints_FuncsRec structure. Recording glyph hints is normally - * achieved through the following scheme: - * - * - Open a new hint recording session by calling the `open' method. - * This rewinds the recorder and prepare it for new input. - * - * - For each hint found in the glyph charstring, call the corresponding - * method (`stem', `stem3', or `reset'). Note that these functions do - * not return an error code. - * - * - Close the recording session by calling the `close' method. It - * returns an error code if the hints were invalid or something - * strange happened (e.g., memory shortage). - * - * The hints accumulated in the object can later be used by the - * PostScript hinter. - * - */ - typedef struct T1_HintsRec_* T1_Hints; - - - /************************************************************************* - * - * @type: - * T1_Hints_Funcs - * - * @description: - * A pointer to the @T1_Hints_FuncsRec structure that defines the API of - * a given @T1_Hints object. - * - */ - typedef const struct T1_Hints_FuncsRec_* T1_Hints_Funcs; - - - /************************************************************************* - * - * @functype: - * T1_Hints_OpenFunc - * - * @description: - * A method of the @T1_Hints class used to prepare it for a new Type 1 - * hints recording session. - * - * @input: - * hints :: - * A handle to the Type 1 hints recorder. - * - * @note: - * You should always call the @T1_Hints_CloseFunc method in order to - * close an opened recording session. - * - */ - typedef void - (*T1_Hints_OpenFunc)( T1_Hints hints ); - - - /************************************************************************* - * - * @functype: - * T1_Hints_SetStemFunc - * - * @description: - * A method of the @T1_Hints class used to record a new horizontal or - * vertical stem. This corresponds to the Type 1 `hstem' and `vstem' - * operators. - * - * @input: - * hints :: - * A handle to the Type 1 hints recorder. - * - * dimension :: - * 0 for horizontal stems (hstem), 1 for vertical ones (vstem). - * - * coords :: - * Array of 2 coordinates in 16.16 format, used as (position,length) - * stem descriptor. - * - * @note: - * Use vertical coordinates (y) for horizontal stems (dim=0). Use - * horizontal coordinates (x) for vertical stems (dim=1). - * - * `coords[0]' is the absolute stem position (lowest coordinate); - * `coords[1]' is the length. - * - * The length can be negative, in which case it must be either -20 or - * -21. It is interpreted as a `ghost' stem, according to the Type 1 - * specification. - * - * If the length is -21 (corresponding to a bottom ghost stem), then - * the real stem position is `coords[0]+coords[1]'. - * - */ - typedef void - (*T1_Hints_SetStemFunc)( T1_Hints hints, - FT_UInt dimension, - FT_Fixed* coords ); - - - /************************************************************************* - * - * @functype: - * T1_Hints_SetStem3Func - * - * @description: - * A method of the @T1_Hints class used to record three - * counter-controlled horizontal or vertical stems at once. - * - * @input: - * hints :: - * A handle to the Type 1 hints recorder. - * - * dimension :: - * 0 for horizontal stems, 1 for vertical ones. - * - * coords :: - * An array of 6 values in 16.16 format, holding 3 (position,length) - * pairs for the counter-controlled stems. - * - * @note: - * Use vertical coordinates (y) for horizontal stems (dim=0). Use - * horizontal coordinates (x) for vertical stems (dim=1). - * - * The lengths cannot be negative (ghost stems are never - * counter-controlled). - * - */ - typedef void - (*T1_Hints_SetStem3Func)( T1_Hints hints, - FT_UInt dimension, - FT_Fixed* coords ); - - - /************************************************************************* - * - * @functype: - * T1_Hints_ResetFunc - * - * @description: - * A method of the @T1_Hints class used to reset the stems hints in a - * recording session. - * - * @input: - * hints :: - * A handle to the Type 1 hints recorder. - * - * end_point :: - * The index of the last point in the input glyph in which the - * previously defined hints apply. - * - */ - typedef void - (*T1_Hints_ResetFunc)( T1_Hints hints, - FT_UInt end_point ); - - - /************************************************************************* - * - * @functype: - * T1_Hints_CloseFunc - * - * @description: - * A method of the @T1_Hints class used to close a hint recording - * session. - * - * @input: - * hints :: - * A handle to the Type 1 hints recorder. - * - * end_point :: - * The index of the last point in the input glyph. - * - * @return: - * FreeType error code. 0 means success. - * - * @note: - * The error code is set to indicate that an error occurred during the - * recording session. - * - */ - typedef FT_Error - (*T1_Hints_CloseFunc)( T1_Hints hints, - FT_UInt end_point ); - - - /************************************************************************* - * - * @functype: - * T1_Hints_ApplyFunc - * - * @description: - * A method of the @T1_Hints class used to apply hints to the - * corresponding glyph outline. Must be called once all hints have been - * recorded. - * - * @input: - * hints :: - * A handle to the Type 1 hints recorder. - * - * outline :: - * A pointer to the target outline descriptor. - * - * globals :: - * The hinter globals for this font. - * - * hint_mode :: - * Hinting information. - * - * @return: - * FreeType error code. 0 means success. - * - * @note: - * On input, all points within the outline are in font coordinates. On - * output, they are in 1/64th of pixels. - * - * The scaling transformation is taken from the `globals' object which - * must correspond to the same font as the glyph. - * - */ - typedef FT_Error - (*T1_Hints_ApplyFunc)( T1_Hints hints, - FT_Outline* outline, - PSH_Globals globals, - FT_Render_Mode hint_mode ); - - - /************************************************************************* - * - * @struct: - * T1_Hints_FuncsRec - * - * @description: - * The structure used to provide the API to @T1_Hints objects. - * - * @fields: - * hints :: - * A handle to the T1 Hints recorder. - * - * open :: - * The function to open a recording session. - * - * close :: - * The function to close a recording session. - * - * stem :: - * The function to set a simple stem. - * - * stem3 :: - * The function to set counter-controlled stems. - * - * reset :: - * The function to reset stem hints. - * - * apply :: - * The function to apply the hints to the corresponding glyph outline. - * - */ - typedef struct T1_Hints_FuncsRec_ - { - T1_Hints hints; - T1_Hints_OpenFunc open; - T1_Hints_CloseFunc close; - T1_Hints_SetStemFunc stem; - T1_Hints_SetStem3Func stem3; - T1_Hints_ResetFunc reset; - T1_Hints_ApplyFunc apply; - - } T1_Hints_FuncsRec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PUBLIC TYPE 2 HINTS RECORDER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /************************************************************************* - * - * @type: - * T2_Hints - * - * @description: - * This is a handle to an opaque structure used to record glyph hints - * from a Type 2 character glyph character string. - * - * The methods used to operate on this object are defined by the - * @T2_Hints_FuncsRec structure. Recording glyph hints is normally - * achieved through the following scheme: - * - * - Open a new hint recording session by calling the `open' method. - * This rewinds the recorder and prepare it for new input. - * - * - For each hint found in the glyph charstring, call the corresponding - * method (`stems', `hintmask', `counters'). Note that these - * functions do not return an error code. - * - * - Close the recording session by calling the `close' method. It - * returns an error code if the hints were invalid or something - * strange happened (e.g., memory shortage). - * - * The hints accumulated in the object can later be used by the - * Postscript hinter. - * - */ - typedef struct T2_HintsRec_* T2_Hints; - - - /************************************************************************* - * - * @type: - * T2_Hints_Funcs - * - * @description: - * A pointer to the @T2_Hints_FuncsRec structure that defines the API of - * a given @T2_Hints object. - * - */ - typedef const struct T2_Hints_FuncsRec_* T2_Hints_Funcs; - - - /************************************************************************* - * - * @functype: - * T2_Hints_OpenFunc - * - * @description: - * A method of the @T2_Hints class used to prepare it for a new Type 2 - * hints recording session. - * - * @input: - * hints :: - * A handle to the Type 2 hints recorder. - * - * @note: - * You should always call the @T2_Hints_CloseFunc method in order to - * close an opened recording session. - * - */ - typedef void - (*T2_Hints_OpenFunc)( T2_Hints hints ); - - - /************************************************************************* - * - * @functype: - * T2_Hints_StemsFunc - * - * @description: - * A method of the @T2_Hints class used to set the table of stems in - * either the vertical or horizontal dimension. Equivalent to the - * `hstem', `vstem', `hstemhm', and `vstemhm' Type 2 operators. - * - * @input: - * hints :: - * A handle to the Type 2 hints recorder. - * - * dimension :: - * 0 for horizontal stems (hstem), 1 for vertical ones (vstem). - * - * count :: - * The number of stems. - * - * coords :: - * An array of `count' (position,length) pairs in 16.16 format. - * - * @note: - * Use vertical coordinates (y) for horizontal stems (dim=0). Use - * horizontal coordinates (x) for vertical stems (dim=1). - * - * There are `2*count' elements in the `coords' array. Each even - * element is an absolute position in font units, each odd element is a - * length in font units. - * - * A length can be negative, in which case it must be either -20 or - * -21. It is interpreted as a `ghost' stem, according to the Type 1 - * specification. - * - */ - typedef void - (*T2_Hints_StemsFunc)( T2_Hints hints, - FT_UInt dimension, - FT_Int count, - FT_Fixed* coordinates ); - - - /************************************************************************* - * - * @functype: - * T2_Hints_MaskFunc - * - * @description: - * A method of the @T2_Hints class used to set a given hintmask (this - * corresponds to the `hintmask' Type 2 operator). - * - * @input: - * hints :: - * A handle to the Type 2 hints recorder. - * - * end_point :: - * The glyph index of the last point to which the previously defined - * or activated hints apply. - * - * bit_count :: - * The number of bits in the hint mask. - * - * bytes :: - * An array of bytes modelling the hint mask. - * - * @note: - * If the hintmask starts the charstring (before any glyph point - * definition), the value of `end_point' should be 0. - * - * `bit_count' is the number of meaningful bits in the `bytes' array; it - * must be equal to the total number of hints defined so far (i.e., - * horizontal+verticals). - * - * The `bytes' array can come directly from the Type 2 charstring and - * respects the same format. - * - */ - typedef void - (*T2_Hints_MaskFunc)( T2_Hints hints, - FT_UInt end_point, - FT_UInt bit_count, - const FT_Byte* bytes ); - - - /************************************************************************* - * - * @functype: - * T2_Hints_CounterFunc - * - * @description: - * A method of the @T2_Hints class used to set a given counter mask - * (this corresponds to the `hintmask' Type 2 operator). - * - * @input: - * hints :: - * A handle to the Type 2 hints recorder. - * - * end_point :: - * A glyph index of the last point to which the previously defined or - * active hints apply. - * - * bit_count :: - * The number of bits in the hint mask. - * - * bytes :: - * An array of bytes modelling the hint mask. - * - * @note: - * If the hintmask starts the charstring (before any glyph point - * definition), the value of `end_point' should be 0. - * - * `bit_count' is the number of meaningful bits in the `bytes' array; it - * must be equal to the total number of hints defined so far (i.e., - * horizontal+verticals). - * - * The `bytes' array can come directly from the Type 2 charstring and - * respects the same format. - * - */ - typedef void - (*T2_Hints_CounterFunc)( T2_Hints hints, - FT_UInt bit_count, - const FT_Byte* bytes ); - - - /************************************************************************* - * - * @functype: - * T2_Hints_CloseFunc - * - * @description: - * A method of the @T2_Hints class used to close a hint recording - * session. - * - * @input: - * hints :: - * A handle to the Type 2 hints recorder. - * - * end_point :: - * The index of the last point in the input glyph. - * - * @return: - * FreeType error code. 0 means success. - * - * @note: - * The error code is set to indicate that an error occurred during the - * recording session. - * - */ - typedef FT_Error - (*T2_Hints_CloseFunc)( T2_Hints hints, - FT_UInt end_point ); - - - /************************************************************************* - * - * @functype: - * T2_Hints_ApplyFunc - * - * @description: - * A method of the @T2_Hints class used to apply hints to the - * corresponding glyph outline. Must be called after the `close' - * method. - * - * @input: - * hints :: - * A handle to the Type 2 hints recorder. - * - * outline :: - * A pointer to the target outline descriptor. - * - * globals :: - * The hinter globals for this font. - * - * hint_mode :: - * Hinting information. - * - * @return: - * FreeType error code. 0 means success. - * - * @note: - * On input, all points within the outline are in font coordinates. On - * output, they are in 1/64th of pixels. - * - * The scaling transformation is taken from the `globals' object which - * must correspond to the same font than the glyph. - * - */ - typedef FT_Error - (*T2_Hints_ApplyFunc)( T2_Hints hints, - FT_Outline* outline, - PSH_Globals globals, - FT_Render_Mode hint_mode ); - - - /************************************************************************* - * - * @struct: - * T2_Hints_FuncsRec - * - * @description: - * The structure used to provide the API to @T2_Hints objects. - * - * @fields: - * hints :: - * A handle to the T2 hints recorder object. - * - * open :: - * The function to open a recording session. - * - * close :: - * The function to close a recording session. - * - * stems :: - * The function to set the dimension's stems table. - * - * hintmask :: - * The function to set hint masks. - * - * counter :: - * The function to set counter masks. - * - * apply :: - * The function to apply the hints on the corresponding glyph outline. - * - */ - typedef struct T2_Hints_FuncsRec_ - { - T2_Hints hints; - T2_Hints_OpenFunc open; - T2_Hints_CloseFunc close; - T2_Hints_StemsFunc stems; - T2_Hints_MaskFunc hintmask; - T2_Hints_CounterFunc counter; - T2_Hints_ApplyFunc apply; - - } T2_Hints_FuncsRec; - - - /* */ - - - typedef struct PSHinter_Interface_ - { - PSH_Globals_Funcs (*get_globals_funcs)( FT_Module module ); - T1_Hints_Funcs (*get_t1_funcs) ( FT_Module module ); - T2_Hints_Funcs (*get_t2_funcs) ( FT_Module module ); - - } PSHinter_Interface; - - typedef PSHinter_Interface* PSHinter_Service; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_PSHINTER_INTERFACE( \ - class_, \ - get_globals_funcs_, \ - get_t1_funcs_, \ - get_t2_funcs_ ) \ - static const PSHinter_Interface class_ = \ - { \ - get_globals_funcs_, \ - get_t1_funcs_, \ - get_t2_funcs_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_PSHINTER_INTERFACE( \ - class_, \ - get_globals_funcs_, \ - get_t1_funcs_, \ - get_t2_funcs_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - PSHinter_Interface* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->get_globals_funcs = get_globals_funcs_; \ - clazz->get_t1_funcs = get_t1_funcs_; \ - clazz->get_t2_funcs = get_t2_funcs_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - -FT_END_HEADER - -#endif /* __PSHINTS_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svbdf.h b/third_party/freetype/include/freetype/internal/services/svbdf.h deleted file mode 100644 index 865b53687d034c6260911f0e859fcec734cf4487..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svbdf.h +++ /dev/null @@ -1,82 +0,0 @@ -/***************************************************************************/ -/* */ -/* svbdf.h */ -/* */ -/* The FreeType BDF services (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVBDF_H__ -#define __SVBDF_H__ - -#include FT_BDF_H -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_BDF "bdf" - - typedef FT_Error - (*FT_BDF_GetCharsetIdFunc)( FT_Face face, - const char* *acharset_encoding, - const char* *acharset_registry ); - - typedef FT_Error - (*FT_BDF_GetPropertyFunc)( FT_Face face, - const char* prop_name, - BDF_PropertyRec *aproperty ); - - - FT_DEFINE_SERVICE( BDF ) - { - FT_BDF_GetCharsetIdFunc get_charset_id; - FT_BDF_GetPropertyFunc get_property; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_BDFRec( class_, \ - get_charset_id_, \ - get_property_ ) \ - static const FT_Service_BDFRec class_ = \ - { \ - get_charset_id_, get_property_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_BDFRec( class_, \ - get_charset_id_, \ - get_property_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Service_BDFRec* clazz ) \ - { \ - clazz->get_charset_id = get_charset_id_; \ - clazz->get_property = get_property_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVBDF_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svcid.h b/third_party/freetype/include/freetype/internal/services/svcid.h deleted file mode 100644 index 4a535a6f424d6ba80d419015b27ad502edbb16e1..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svcid.h +++ /dev/null @@ -1,90 +0,0 @@ -/***************************************************************************/ -/* */ -/* svcid.h */ -/* */ -/* The FreeType CID font services (specification). */ -/* */ -/* Copyright 2007-2015 by */ -/* Derek Clegg and Michael Toftdal. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVCID_H__ -#define __SVCID_H__ - -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_CID "CID" - - typedef FT_Error - (*FT_CID_GetRegistryOrderingSupplementFunc)( FT_Face face, - const char* *registry, - const char* *ordering, - FT_Int *supplement ); - typedef FT_Error - (*FT_CID_GetIsInternallyCIDKeyedFunc)( FT_Face face, - FT_Bool *is_cid ); - typedef FT_Error - (*FT_CID_GetCIDFromGlyphIndexFunc)( FT_Face face, - FT_UInt glyph_index, - FT_UInt *cid ); - - FT_DEFINE_SERVICE( CID ) - { - FT_CID_GetRegistryOrderingSupplementFunc get_ros; - FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid; - FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_CIDREC( class_, \ - get_ros_, \ - get_is_cid_, \ - get_cid_from_glyph_index_ ) \ - static const FT_Service_CIDRec class_ = \ - { \ - get_ros_, get_is_cid_, get_cid_from_glyph_index_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_CIDREC( class_, \ - get_ros_, \ - get_is_cid_, \ - get_cid_from_glyph_index_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_Service_CIDRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->get_ros = get_ros_; \ - clazz->get_is_cid = get_is_cid_; \ - clazz->get_cid_from_glyph_index = get_cid_from_glyph_index_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVCID_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svfntfmt.h b/third_party/freetype/include/freetype/internal/services/svfntfmt.h deleted file mode 100644 index f8b3617364cbb718e9f097522210c53d9e2c3f26..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svfntfmt.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************/ -/* */ -/* svfntfmt.h */ -/* */ -/* The FreeType font format service (specification only). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVFNTFMT_H__ -#define __SVFNTFMT_H__ - -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - - /* - * A trivial service used to return the name of a face's font driver, - * according to the XFree86 nomenclature. Note that the service data - * is a simple constant string pointer. - */ - -#define FT_SERVICE_ID_FONT_FORMAT "font-format" - -#define FT_FONT_FORMAT_TRUETYPE "TrueType" -#define FT_FONT_FORMAT_TYPE_1 "Type 1" -#define FT_FONT_FORMAT_BDF "BDF" -#define FT_FONT_FORMAT_PCF "PCF" -#define FT_FONT_FORMAT_TYPE_42 "Type 42" -#define FT_FONT_FORMAT_CID "CID Type 1" -#define FT_FONT_FORMAT_CFF "CFF" -#define FT_FONT_FORMAT_PFR "PFR" -#define FT_FONT_FORMAT_WINFNT "Windows FNT" - - /* */ - - -FT_END_HEADER - - -#endif /* __SVFNTFMT_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svgldict.h b/third_party/freetype/include/freetype/internal/services/svgldict.h deleted file mode 100644 index f78bca5d77614bedb6657fece18df68e7536fc9f..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svgldict.h +++ /dev/null @@ -1,88 +0,0 @@ -/***************************************************************************/ -/* */ -/* svgldict.h */ -/* */ -/* The FreeType glyph dictionary services (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVGLDICT_H__ -#define __SVGLDICT_H__ - -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - - /* - * A service used to retrieve glyph names, as well as to find the - * index of a given glyph name in a font. - * - */ - -#define FT_SERVICE_ID_GLYPH_DICT "glyph-dict" - - - typedef FT_Error - (*FT_GlyphDict_GetNameFunc)( FT_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ); - - typedef FT_UInt - (*FT_GlyphDict_NameIndexFunc)( FT_Face face, - FT_String* glyph_name ); - - - FT_DEFINE_SERVICE( GlyphDict ) - { - FT_GlyphDict_GetNameFunc get_name; - FT_GlyphDict_NameIndexFunc name_index; /* optional */ - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_GLYPHDICTREC( class_, \ - get_name_, \ - name_index_) \ - static const FT_Service_GlyphDictRec class_ = \ - { \ - get_name_, name_index_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_GLYPHDICTREC( class_, \ - get_name_, \ - name_index_) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_Service_GlyphDictRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->get_name = get_name_; \ - clazz->name_index = name_index_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVGLDICT_H__ */ diff --git a/third_party/freetype/include/freetype/internal/services/svgxval.h b/third_party/freetype/include/freetype/internal/services/svgxval.h deleted file mode 100644 index 59cc3b7048949291684186365a7f900d31012470..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svgxval.h +++ /dev/null @@ -1,72 +0,0 @@ -/***************************************************************************/ -/* */ -/* svgxval.h */ -/* */ -/* FreeType API for validating TrueTypeGX/AAT tables (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* Masatake YAMATO, Red Hat K.K., */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/***************************************************************************/ -/* */ -/* gxvalid is derived from both gxlayout module and otvalid module. */ -/* Development of gxlayout is supported by the Information-technology */ -/* Promotion Agency(IPA), Japan. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVGXVAL_H__ -#define __SVGXVAL_H__ - -#include FT_GX_VALIDATE_H -#include FT_INTERNAL_VALIDATE_H - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_GX_VALIDATE "truetypegx-validate" -#define FT_SERVICE_ID_CLASSICKERN_VALIDATE "classickern-validate" - - typedef FT_Error - (*gxv_validate_func)( FT_Face face, - FT_UInt gx_flags, - FT_Bytes tables[FT_VALIDATE_GX_LENGTH], - FT_UInt table_length ); - - - typedef FT_Error - (*ckern_validate_func)( FT_Face face, - FT_UInt ckern_flags, - FT_Bytes *ckern_table ); - - - FT_DEFINE_SERVICE( GXvalidate ) - { - gxv_validate_func validate; - }; - - FT_DEFINE_SERVICE( CKERNvalidate ) - { - ckern_validate_func validate; - }; - - /* */ - - -FT_END_HEADER - - -#endif /* __SVGXVAL_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svkern.h b/third_party/freetype/include/freetype/internal/services/svkern.h deleted file mode 100644 index bc26f15941c2fa0138e3334732857a4431ebbd8e..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svkern.h +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************/ -/* */ -/* svkern.h */ -/* */ -/* The FreeType Kerning service (specification). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVKERN_H__ -#define __SVKERN_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_TRUETYPE_TABLES_H - - -FT_BEGIN_HEADER - -#define FT_SERVICE_ID_KERNING "kerning" - - - typedef FT_Error - (*FT_Kerning_TrackGetFunc)( FT_Face face, - FT_Fixed point_size, - FT_Int degree, - FT_Fixed* akerning ); - - FT_DEFINE_SERVICE( Kerning ) - { - FT_Kerning_TrackGetFunc get_track; - }; - - /* */ - - -FT_END_HEADER - - -#endif /* __SVKERN_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svmm.h b/third_party/freetype/include/freetype/internal/services/svmm.h deleted file mode 100644 index f2cecfbb3bc6e837af68e9f9896e4fffec1406bc..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svmm.h +++ /dev/null @@ -1,113 +0,0 @@ -/***************************************************************************/ -/* */ -/* svmm.h */ -/* */ -/* The FreeType Multiple Masters and GX var services (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVMM_H__ -#define __SVMM_H__ - -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - - /* - * A service used to manage multiple-masters data in a given face. - * - * See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H). - * - */ - -#define FT_SERVICE_ID_MULTI_MASTERS "multi-masters" - - - typedef FT_Error - (*FT_Get_MM_Func)( FT_Face face, - FT_Multi_Master* master ); - - typedef FT_Error - (*FT_Get_MM_Var_Func)( FT_Face face, - FT_MM_Var* *master ); - - typedef FT_Error - (*FT_Set_MM_Design_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); - - typedef FT_Error - (*FT_Set_Var_Design_Func)( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - typedef FT_Error - (*FT_Set_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); - - - FT_DEFINE_SERVICE( MultiMasters ) - { - FT_Get_MM_Func get_mm; - FT_Set_MM_Design_Func set_mm_design; - FT_Set_MM_Blend_Func set_mm_blend; - FT_Get_MM_Var_Func get_mm_var; - FT_Set_Var_Design_Func set_var_design; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_var_, \ - set_var_design_ ) \ - static const FT_Service_MultiMastersRec class_ = \ - { \ - get_mm_, set_mm_design_, set_mm_blend_, get_mm_var_, set_var_design_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_var_, \ - set_var_design_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Service_MultiMastersRec* clazz ) \ - { \ - clazz->get_mm = get_mm_; \ - clazz->set_mm_design = set_mm_design_; \ - clazz->set_mm_blend = set_mm_blend_; \ - clazz->get_mm_var = get_mm_var_; \ - clazz->set_var_design = set_var_design_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - -#endif /* __SVMM_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svotval.h b/third_party/freetype/include/freetype/internal/services/svotval.h deleted file mode 100644 index a82a6420fd7faa57647c6ec806323582ae01b9be..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svotval.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************/ -/* */ -/* svotval.h */ -/* */ -/* The FreeType OpenType validation service (specification). */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVOTVAL_H__ -#define __SVOTVAL_H__ - -#include FT_OPENTYPE_VALIDATE_H -#include FT_INTERNAL_VALIDATE_H - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_OPENTYPE_VALIDATE "opentype-validate" - - - typedef FT_Error - (*otv_validate_func)( FT_Face volatile face, - FT_UInt ot_flags, - FT_Bytes *base, - FT_Bytes *gdef, - FT_Bytes *gpos, - FT_Bytes *gsub, - FT_Bytes *jstf ); - - - FT_DEFINE_SERVICE( OTvalidate ) - { - otv_validate_func validate; - }; - - /* */ - - -FT_END_HEADER - - -#endif /* __SVOTVAL_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svpfr.h b/third_party/freetype/include/freetype/internal/services/svpfr.h deleted file mode 100644 index d4eb1693d0c1f9d3d2c9e112d7a8227edbfcf026..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svpfr.h +++ /dev/null @@ -1,66 +0,0 @@ -/***************************************************************************/ -/* */ -/* svpfr.h */ -/* */ -/* Internal PFR service functions (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVPFR_H__ -#define __SVPFR_H__ - -#include FT_PFR_H -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_PFR_METRICS "pfr-metrics" - - - typedef FT_Error - (*FT_PFR_GetMetricsFunc)( FT_Face face, - FT_UInt *aoutline, - FT_UInt *ametrics, - FT_Fixed *ax_scale, - FT_Fixed *ay_scale ); - - typedef FT_Error - (*FT_PFR_GetKerningFunc)( FT_Face face, - FT_UInt left, - FT_UInt right, - FT_Vector *avector ); - - typedef FT_Error - (*FT_PFR_GetAdvanceFunc)( FT_Face face, - FT_UInt gindex, - FT_Pos *aadvance ); - - - FT_DEFINE_SERVICE( PfrMetrics ) - { - FT_PFR_GetMetricsFunc get_metrics; - FT_PFR_GetKerningFunc get_kerning; - FT_PFR_GetAdvanceFunc get_advance; - - }; - - /* */ - -FT_END_HEADER - -#endif /* __SVPFR_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svpostnm.h b/third_party/freetype/include/freetype/internal/services/svpostnm.h deleted file mode 100644 index a89f79e4796bd8695fbc3b2ef18d4d877a024cef..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svpostnm.h +++ /dev/null @@ -1,81 +0,0 @@ -/***************************************************************************/ -/* */ -/* svpostnm.h */ -/* */ -/* The FreeType PostScript name services (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVPOSTNM_H__ -#define __SVPOSTNM_H__ - -#include FT_INTERNAL_SERVICE_H - - -FT_BEGIN_HEADER - - /* - * A trivial service used to retrieve the PostScript name of a given - * font when available. The `get_name' field should never be NULL. - * - * The corresponding function can return NULL to indicate that the - * PostScript name is not available. - * - * The name is owned by the face and will be destroyed with it. - */ - -#define FT_SERVICE_ID_POSTSCRIPT_FONT_NAME "postscript-font-name" - - - typedef const char* - (*FT_PsName_GetFunc)( FT_Face face ); - - - FT_DEFINE_SERVICE( PsFontName ) - { - FT_PsName_GetFunc get_ps_font_name; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_PSFONTNAMEREC( class_, get_ps_font_name_ ) \ - static const FT_Service_PsFontNameRec class_ = \ - { \ - get_ps_font_name_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_PSFONTNAMEREC( class_, get_ps_font_name_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_Service_PsFontNameRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->get_ps_font_name = get_ps_font_name_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVPOSTNM_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svprop.h b/third_party/freetype/include/freetype/internal/services/svprop.h deleted file mode 100644 index c9f07ce33ace9f63439d608afb528b6c075011c0..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svprop.h +++ /dev/null @@ -1,81 +0,0 @@ -/***************************************************************************/ -/* */ -/* svprop.h */ -/* */ -/* The FreeType property service (specification). */ -/* */ -/* Copyright 2012-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVPROP_H__ -#define __SVPROP_H__ - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_PROPERTIES "properties" - - - typedef FT_Error - (*FT_Properties_SetFunc)( FT_Module module, - const char* property_name, - const void* value ); - - typedef FT_Error - (*FT_Properties_GetFunc)( FT_Module module, - const char* property_name, - void* value ); - - - FT_DEFINE_SERVICE( Properties ) - { - FT_Properties_SetFunc set_property; - FT_Properties_GetFunc get_property; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_PROPERTIESREC( class_, \ - set_property_, \ - get_property_ ) \ - static const FT_Service_PropertiesRec class_ = \ - { \ - set_property_, \ - get_property_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_PROPERTIESREC( class_, \ - set_property_, \ - get_property_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Service_PropertiesRec* clazz ) \ - { \ - clazz->set_property = set_property_; \ - clazz->get_property = get_property_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVPROP_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svpscmap.h b/third_party/freetype/include/freetype/internal/services/svpscmap.h deleted file mode 100644 index 66da6e10438219bf572ffe704d05a2e4cd4670b5..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svpscmap.h +++ /dev/null @@ -1,177 +0,0 @@ -/***************************************************************************/ -/* */ -/* svpscmap.h */ -/* */ -/* The FreeType PostScript charmap service (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVPSCMAP_H__ -#define __SVPSCMAP_H__ - -#include FT_INTERNAL_OBJECTS_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_POSTSCRIPT_CMAPS "postscript-cmaps" - - - /* - * Adobe glyph name to unicode value. - */ - typedef FT_UInt32 - (*PS_Unicode_ValueFunc)( const char* glyph_name ); - - /* - * Macintosh name id to glyph name. NULL if invalid index. - */ - typedef const char* - (*PS_Macintosh_NameFunc)( FT_UInt name_index ); - - /* - * Adobe standard string ID to glyph name. NULL if invalid index. - */ - typedef const char* - (*PS_Adobe_Std_StringsFunc)( FT_UInt string_index ); - - - /* - * Simple unicode -> glyph index charmap built from font glyph names - * table. - */ - typedef struct PS_UniMap_ - { - FT_UInt32 unicode; /* bit 31 set: is glyph variant */ - FT_UInt glyph_index; - - } PS_UniMap; - - - typedef struct PS_UnicodesRec_* PS_Unicodes; - - typedef struct PS_UnicodesRec_ - { - FT_CMapRec cmap; - FT_UInt num_maps; - PS_UniMap* maps; - - } PS_UnicodesRec; - - - /* - * A function which returns a glyph name for a given index. Returns - * NULL if invalid index. - */ - typedef const char* - (*PS_GetGlyphNameFunc)( FT_Pointer data, - FT_UInt string_index ); - - /* - * A function used to release the glyph name returned by - * PS_GetGlyphNameFunc, when needed - */ - typedef void - (*PS_FreeGlyphNameFunc)( FT_Pointer data, - const char* name ); - - typedef FT_Error - (*PS_Unicodes_InitFunc)( FT_Memory memory, - PS_Unicodes unicodes, - FT_UInt num_glyphs, - PS_GetGlyphNameFunc get_glyph_name, - PS_FreeGlyphNameFunc free_glyph_name, - FT_Pointer glyph_data ); - - typedef FT_UInt - (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes, - FT_UInt32 unicode ); - - typedef FT_UInt32 - (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes, - FT_UInt32 *unicode ); - - - FT_DEFINE_SERVICE( PsCMaps ) - { - PS_Unicode_ValueFunc unicode_value; - - PS_Unicodes_InitFunc unicodes_init; - PS_Unicodes_CharIndexFunc unicodes_char_index; - PS_Unicodes_CharNextFunc unicodes_char_next; - - PS_Macintosh_NameFunc macintosh_name; - PS_Adobe_Std_StringsFunc adobe_std_strings; - const unsigned short* adobe_std_encoding; - const unsigned short* adobe_expert_encoding; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_PSCMAPSREC( class_, \ - unicode_value_, \ - unicodes_init_, \ - unicodes_char_index_, \ - unicodes_char_next_, \ - macintosh_name_, \ - adobe_std_strings_, \ - adobe_std_encoding_, \ - adobe_expert_encoding_ ) \ - static const FT_Service_PsCMapsRec class_ = \ - { \ - unicode_value_, unicodes_init_, \ - unicodes_char_index_, unicodes_char_next_, macintosh_name_, \ - adobe_std_strings_, adobe_std_encoding_, adobe_expert_encoding_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_PSCMAPSREC( class_, \ - unicode_value_, \ - unicodes_init_, \ - unicodes_char_index_, \ - unicodes_char_next_, \ - macintosh_name_, \ - adobe_std_strings_, \ - adobe_std_encoding_, \ - adobe_expert_encoding_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_Service_PsCMapsRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->unicode_value = unicode_value_; \ - clazz->unicodes_init = unicodes_init_; \ - clazz->unicodes_char_index = unicodes_char_index_; \ - clazz->unicodes_char_next = unicodes_char_next_; \ - clazz->macintosh_name = macintosh_name_; \ - clazz->adobe_std_strings = adobe_std_strings_; \ - clazz->adobe_std_encoding = adobe_std_encoding_; \ - clazz->adobe_expert_encoding = adobe_expert_encoding_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVPSCMAP_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svpsinfo.h b/third_party/freetype/include/freetype/internal/services/svpsinfo.h deleted file mode 100644 index 752a2660258c7342345b29d7aa9e7c6c07770211..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svpsinfo.h +++ /dev/null @@ -1,111 +0,0 @@ -/***************************************************************************/ -/* */ -/* svpsinfo.h */ -/* */ -/* The FreeType PostScript info service (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVPSINFO_H__ -#define __SVPSINFO_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_INTERNAL_TYPE1_TYPES_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_POSTSCRIPT_INFO "postscript-info" - - - typedef FT_Error - (*PS_GetFontInfoFunc)( FT_Face face, - PS_FontInfoRec* afont_info ); - - typedef FT_Error - (*PS_GetFontExtraFunc)( FT_Face face, - PS_FontExtraRec* afont_extra ); - - typedef FT_Int - (*PS_HasGlyphNamesFunc)( FT_Face face ); - - typedef FT_Error - (*PS_GetFontPrivateFunc)( FT_Face face, - PS_PrivateRec* afont_private ); - - typedef FT_Long - (*PS_GetFontValueFunc)( FT_Face face, - PS_Dict_Keys key, - FT_UInt idx, - void *value, - FT_Long value_len ); - - - FT_DEFINE_SERVICE( PsInfo ) - { - PS_GetFontInfoFunc ps_get_font_info; - PS_GetFontExtraFunc ps_get_font_extra; - PS_HasGlyphNamesFunc ps_has_glyph_names; - PS_GetFontPrivateFunc ps_get_font_private; - PS_GetFontValueFunc ps_get_font_value; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_PSINFOREC( class_, \ - get_font_info_, \ - ps_get_font_extra_, \ - has_glyph_names_, \ - get_font_private_, \ - get_font_value_ ) \ - static const FT_Service_PsInfoRec class_ = \ - { \ - get_font_info_, ps_get_font_extra_, has_glyph_names_, \ - get_font_private_, get_font_value_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_PSINFOREC( class_, \ - get_font_info_, \ - ps_get_font_extra_, \ - has_glyph_names_, \ - get_font_private_, \ - get_font_value_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_Service_PsInfoRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->ps_get_font_info = get_font_info_; \ - clazz->ps_get_font_extra = ps_get_font_extra_; \ - clazz->ps_has_glyph_names = has_glyph_names_; \ - clazz->ps_get_font_private = get_font_private_; \ - clazz->ps_get_font_value = get_font_value_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVPSINFO_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svsfnt.h b/third_party/freetype/include/freetype/internal/services/svsfnt.h deleted file mode 100644 index 252ae1cf5eb096e83e4a0ff93ed338124060bfd9..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svsfnt.h +++ /dev/null @@ -1,103 +0,0 @@ -/***************************************************************************/ -/* */ -/* svsfnt.h */ -/* */ -/* The FreeType SFNT table loading service (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVSFNT_H__ -#define __SVSFNT_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_TRUETYPE_TABLES_H - - -FT_BEGIN_HEADER - - - /* - * SFNT table loading service. - */ - -#define FT_SERVICE_ID_SFNT_TABLE "sfnt-table" - - - /* - * Used to implement FT_Load_Sfnt_Table(). - */ - typedef FT_Error - (*FT_SFNT_TableLoadFunc)( FT_Face face, - FT_ULong tag, - FT_Long offset, - FT_Byte* buffer, - FT_ULong* length ); - - /* - * Used to implement FT_Get_Sfnt_Table(). - */ - typedef void* - (*FT_SFNT_TableGetFunc)( FT_Face face, - FT_Sfnt_Tag tag ); - - - /* - * Used to implement FT_Sfnt_Table_Info(). - */ - typedef FT_Error - (*FT_SFNT_TableInfoFunc)( FT_Face face, - FT_UInt idx, - FT_ULong *tag, - FT_ULong *offset, - FT_ULong *length ); - - - FT_DEFINE_SERVICE( SFNT_Table ) - { - FT_SFNT_TableLoadFunc load_table; - FT_SFNT_TableGetFunc get_table; - FT_SFNT_TableInfoFunc table_info; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_SFNT_TABLEREC( class_, load_, get_, info_ ) \ - static const FT_Service_SFNT_TableRec class_ = \ - { \ - load_, get_, info_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_SFNT_TABLEREC( class_, load_, get_, info_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Service_SFNT_TableRec* clazz ) \ - { \ - clazz->load_table = load_; \ - clazz->get_table = get_; \ - clazz->table_info = info_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - - -#endif /* __SVSFNT_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svttcmap.h b/third_party/freetype/include/freetype/internal/services/svttcmap.h deleted file mode 100644 index cd95b9ab81f6e43fa53c6e6223141b8b72497995..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svttcmap.h +++ /dev/null @@ -1,106 +0,0 @@ -/***************************************************************************/ -/* */ -/* svttcmap.h */ -/* */ -/* The FreeType TrueType/sfnt cmap extra information service. */ -/* */ -/* Copyright 2003-2015 by */ -/* Masatake YAMATO, Redhat K.K., */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/* Development of this service is support of - Information-technology Promotion Agency, Japan. */ - -#ifndef __SVTTCMAP_H__ -#define __SVTTCMAP_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_TRUETYPE_TABLES_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_TT_CMAP "tt-cmaps" - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_CMapInfo */ - /* */ - /* <Description> */ - /* A structure used to store TrueType/sfnt specific cmap information */ - /* which is not covered by the generic @FT_CharMap structure. This */ - /* structure can be accessed with the @FT_Get_TT_CMap_Info function. */ - /* */ - /* <Fields> */ - /* language :: */ - /* The language ID used in Mac fonts. Definitions of values are in */ - /* `ttnameid.h'. */ - /* */ - /* format :: */ - /* The cmap format. OpenType 1.6 defines the formats 0 (byte */ - /* encoding table), 2~(high-byte mapping through table), 4~(segment */ - /* mapping to delta values), 6~(trimmed table mapping), 8~(mixed */ - /* 16-bit and 32-bit coverage), 10~(trimmed array), 12~(segmented */ - /* coverage), 13~(last resort font), and 14 (Unicode Variation */ - /* Sequences). */ - /* */ - typedef struct TT_CMapInfo_ - { - FT_ULong language; - FT_Long format; - - } TT_CMapInfo; - - - typedef FT_Error - (*TT_CMap_Info_GetFunc)( FT_CharMap charmap, - TT_CMapInfo *cmap_info ); - - - FT_DEFINE_SERVICE( TTCMaps ) - { - TT_CMap_Info_GetFunc get_cmap_info; - }; - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_TTCMAPSREC( class_, get_cmap_info_ ) \ - static const FT_Service_TTCMapsRec class_ = \ - { \ - get_cmap_info_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_TTCMAPSREC( class_, get_cmap_info_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - FT_Service_TTCMapsRec* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->get_cmap_info = get_cmap_info_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - -#endif /* __SVTTCMAP_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svtteng.h b/third_party/freetype/include/freetype/internal/services/svtteng.h deleted file mode 100644 index 272ee8c055301e6ef489dfdcf06671ca8b1d85a2..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svtteng.h +++ /dev/null @@ -1,53 +0,0 @@ -/***************************************************************************/ -/* */ -/* svtteng.h */ -/* */ -/* The FreeType TrueType engine query service (specification). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVTTENG_H__ -#define __SVTTENG_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_MODULE_H - - -FT_BEGIN_HEADER - - - /* - * SFNT table loading service. - */ - -#define FT_SERVICE_ID_TRUETYPE_ENGINE "truetype-engine" - - /* - * Used to implement FT_Get_TrueType_Engine_Type - */ - - FT_DEFINE_SERVICE( TrueTypeEngine ) - { - FT_TrueTypeEngineType engine_type; - }; - - /* */ - - -FT_END_HEADER - - -#endif /* __SVTTENG_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svttglyf.h b/third_party/freetype/include/freetype/internal/services/svttglyf.h deleted file mode 100644 index f5cb76a9f85c7d80d3ef205220f8cd9cb8258797..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svttglyf.h +++ /dev/null @@ -1,69 +0,0 @@ -/***************************************************************************/ -/* */ -/* svttglyf.h */ -/* */ -/* The FreeType TrueType glyph service. */ -/* */ -/* Copyright 2007-2015 by */ -/* David Turner. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#ifndef __SVTTGLYF_H__ -#define __SVTTGLYF_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_TRUETYPE_TABLES_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_TT_GLYF "tt-glyf" - - - typedef FT_ULong - (*TT_Glyf_GetLocationFunc)( FT_Face face, - FT_UInt gindex, - FT_ULong *psize ); - - FT_DEFINE_SERVICE( TTGlyf ) - { - TT_Glyf_GetLocationFunc get_location; - }; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SERVICE_TTGLYFREC( class_, get_location_ ) \ - static const FT_Service_TTGlyfRec class_ = \ - { \ - get_location_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_SERVICE_TTGLYFREC( class_, get_location_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Service_TTGlyfRec* clazz ) \ - { \ - clazz->get_location = get_location_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - - -FT_END_HEADER - -#endif /* __SVTTGLYF_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/services/svwinfnt.h b/third_party/freetype/include/freetype/internal/services/svwinfnt.h deleted file mode 100644 index 0036929b2f80504b36e220e4d5b05d4995ca4ecf..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/services/svwinfnt.h +++ /dev/null @@ -1,50 +0,0 @@ -/***************************************************************************/ -/* */ -/* svwinfnt.h */ -/* */ -/* The FreeType Windows FNT/FONT service (specification). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SVWINFNT_H__ -#define __SVWINFNT_H__ - -#include FT_INTERNAL_SERVICE_H -#include FT_WINFONTS_H - - -FT_BEGIN_HEADER - - -#define FT_SERVICE_ID_WINFNT "winfonts" - - typedef FT_Error - (*FT_WinFnt_GetHeaderFunc)( FT_Face face, - FT_WinFNT_HeaderRec *aheader ); - - - FT_DEFINE_SERVICE( WinFnt ) - { - FT_WinFnt_GetHeaderFunc get_header; - }; - - /* */ - - -FT_END_HEADER - - -#endif /* __SVWINFNT_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/sfnt.h b/third_party/freetype/include/freetype/internal/sfnt.h deleted file mode 100644 index 30f53bf09ce0a838eb45ddad6492c65f9f5eb719..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/sfnt.h +++ /dev/null @@ -1,748 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfnt.h */ -/* */ -/* High-level `sfnt' driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SFNT_H__ -#define __SFNT_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_DRIVER_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Init_Face_Func */ - /* */ - /* <Description> */ - /* First part of the SFNT face object initialization. This finds */ - /* the face in a SFNT file or collection, and load its format tag in */ - /* face->format_tag. */ - /* */ - /* <Input> */ - /* stream :: The input stream. */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* face_index :: The index of the TrueType font, if we are opening a */ - /* collection, in bits 0-15. The numbered instance */ - /* index~+~1 of a GX (sub)font, if applicable, in bits */ - /* 16-30. */ - /* */ - /* num_params :: The number of additional parameters. */ - /* */ - /* params :: Optional additional parameters. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* The stream cursor must be at the font file's origin. */ - /* */ - /* This function recognizes fonts embedded in a `TrueType */ - /* collection'. */ - /* */ - /* Once the format tag has been validated by the font driver, it */ - /* should then call the TT_Load_Face_Func() callback to read the rest */ - /* of the SFNT tables in the object. */ - /* */ - typedef FT_Error - (*TT_Init_Face_Func)( FT_Stream stream, - TT_Face face, - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_Face_Func */ - /* */ - /* <Description> */ - /* Second part of the SFNT face object initialization. This loads */ - /* the common SFNT tables (head, OS/2, maxp, metrics, etc.) in the */ - /* face object. */ - /* */ - /* <Input> */ - /* stream :: The input stream. */ - /* */ - /* face :: A handle to the target face object. */ - /* */ - /* face_index :: The index of the TrueType font, if we are opening a */ - /* collection, in bits 0-15. The numbered instance */ - /* index~+~1 of a GX (sub)font, if applicable, in bits */ - /* 16-30. */ - /* */ - /* num_params :: The number of additional parameters. */ - /* */ - /* params :: Optional additional parameters. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* This function must be called after TT_Init_Face_Func(). */ - /* */ - typedef FT_Error - (*TT_Load_Face_Func)( FT_Stream stream, - TT_Face face, - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Done_Face_Func */ - /* */ - /* <Description> */ - /* A callback used to delete the common SFNT data from a face. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Note> */ - /* This function does NOT destroy the face object. */ - /* */ - typedef void - (*TT_Done_Face_Func)( TT_Face face ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_Any_Func */ - /* */ - /* <Description> */ - /* Load any font table into client memory. */ - /* */ - /* <Input> */ - /* face :: The face object to look for. */ - /* */ - /* tag :: The tag of table to load. Use the value 0 if you want */ - /* to access the whole font file, else set this parameter */ - /* to a valid TrueType table tag that you can forge with */ - /* the MAKE_TT_TAG macro. */ - /* */ - /* offset :: The starting offset in the table (or the file if */ - /* tag == 0). */ - /* */ - /* length :: The address of the decision variable: */ - /* */ - /* If length == NULL: */ - /* Loads the whole table. Returns an error if */ - /* `offset' == 0! */ - /* */ - /* If *length == 0: */ - /* Exits immediately; returning the length of the given */ - /* table or of the font file, depending on the value of */ - /* `tag'. */ - /* */ - /* If *length != 0: */ - /* Loads the next `length' bytes of table or font, */ - /* starting at offset `offset' (in table or font too). */ - /* */ - /* <Output> */ - /* buffer :: The address of target buffer. */ - /* */ - /* <Return> */ - /* TrueType error code. 0 means success. */ - /* */ - typedef FT_Error - (*TT_Load_Any_Func)( TT_Face face, - FT_ULong tag, - FT_Long offset, - FT_Byte *buffer, - FT_ULong* length ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Find_SBit_Image_Func */ - /* */ - /* <Description> */ - /* Check whether an embedded bitmap (an `sbit') exists for a given */ - /* glyph, at a given strike. */ - /* */ - /* <Input> */ - /* face :: The target face object. */ - /* */ - /* glyph_index :: The glyph index. */ - /* */ - /* strike_index :: The current strike index. */ - /* */ - /* <Output> */ - /* arange :: The SBit range containing the glyph index. */ - /* */ - /* astrike :: The SBit strike containing the glyph index. */ - /* */ - /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. Returns */ - /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ - /* glyph. */ - /* */ - typedef FT_Error - (*TT_Find_SBit_Image_Func)( TT_Face face, - FT_UInt glyph_index, - FT_ULong strike_index, - TT_SBit_Range *arange, - TT_SBit_Strike *astrike, - FT_ULong *aglyph_offset ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_SBit_Metrics_Func */ - /* */ - /* <Description> */ - /* Get the big metrics for a given embedded bitmap. */ - /* */ - /* <Input> */ - /* stream :: The input stream. */ - /* */ - /* range :: The SBit range containing the glyph. */ - /* */ - /* <Output> */ - /* big_metrics :: A big SBit metrics structure for the glyph. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* The stream cursor must be positioned at the glyph's offset within */ - /* the `EBDT' table before the call. */ - /* */ - /* If the image format uses variable metrics, the stream cursor is */ - /* positioned just after the metrics header in the `EBDT' table on */ - /* function exit. */ - /* */ - typedef FT_Error - (*TT_Load_SBit_Metrics_Func)( FT_Stream stream, - TT_SBit_Range range, - TT_SBit_Metrics metrics ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_SBit_Image_Func */ - /* */ - /* <Description> */ - /* Load a given glyph sbit image from the font resource. This also */ - /* returns its metrics. */ - /* */ - /* <Input> */ - /* face :: */ - /* The target face object. */ - /* */ - /* strike_index :: */ - /* The strike index. */ - /* */ - /* glyph_index :: */ - /* The current glyph index. */ - /* */ - /* load_flags :: */ - /* The current load flags. */ - /* */ - /* stream :: */ - /* The input stream. */ - /* */ - /* <Output> */ - /* amap :: */ - /* The target pixmap. */ - /* */ - /* ametrics :: */ - /* A big sbit metrics structure for the glyph image. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. Returns an error if no */ - /* glyph sbit exists for the index. */ - /* */ - /* <Note> */ - /* The `map.buffer' field is always freed before the glyph is loaded. */ - /* */ - typedef FT_Error - (*TT_Load_SBit_Image_Func)( TT_Face face, - FT_ULong strike_index, - FT_UInt glyph_index, - FT_UInt load_flags, - FT_Stream stream, - FT_Bitmap *amap, - TT_SBit_MetricsRec *ametrics ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Set_SBit_Strike_Func */ - /* */ - /* <Description> */ - /* Select an sbit strike for a given size request. */ - /* */ - /* <Input> */ - /* face :: The target face object. */ - /* */ - /* req :: The size request. */ - /* */ - /* <Output> */ - /* astrike_index :: The index of the sbit strike. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. Returns an error if no */ - /* sbit strike exists for the selected ppem values. */ - /* */ - typedef FT_Error - (*TT_Set_SBit_Strike_Func)( TT_Face face, - FT_Size_Request req, - FT_ULong* astrike_index ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_Strike_Metrics_Func */ - /* */ - /* <Description> */ - /* Load the metrics of a given strike. */ - /* */ - /* <Input> */ - /* face :: The target face object. */ - /* */ - /* strike_index :: The strike index. */ - /* */ - /* <Output> */ - /* metrics :: the metrics of the strike. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. Returns an error if no */ - /* such sbit strike exists. */ - /* */ - typedef FT_Error - (*TT_Load_Strike_Metrics_Func)( TT_Face face, - FT_ULong strike_index, - FT_Size_Metrics* metrics ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Get_PS_Name_Func */ - /* */ - /* <Description> */ - /* Get the PostScript glyph name of a glyph. */ - /* */ - /* <Input> */ - /* idx :: The glyph index. */ - /* */ - /* PSname :: The address of a string pointer. Will be NULL in case */ - /* of error, otherwise it is a pointer to the glyph name. */ - /* */ - /* You must not modify the returned string! */ - /* */ - /* <Output> */ - /* FreeType error code. 0 means success. */ - /* */ - typedef FT_Error - (*TT_Get_PS_Name_Func)( TT_Face face, - FT_UInt idx, - FT_String** PSname ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_Metrics_Func */ - /* */ - /* <Description> */ - /* Load a metrics table, which is a table with a horizontal and a */ - /* vertical version. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* vertical :: A boolean flag. If set, load the vertical one. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - typedef FT_Error - (*TT_Load_Metrics_Func)( TT_Face face, - FT_Stream stream, - FT_Bool vertical ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Get_Metrics_Func */ - /* */ - /* <Description> */ - /* Load the horizontal or vertical header in a face object. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* vertical :: A boolean flag. If set, load vertical metrics. */ - /* */ - /* gindex :: The glyph index. */ - /* */ - /* <Output> */ - /* abearing :: The horizontal (or vertical) bearing. Set to zero in */ - /* case of error. */ - /* */ - /* aadvance :: The horizontal (or vertical) advance. Set to zero in */ - /* case of error. */ - /* */ - typedef void - (*TT_Get_Metrics_Func)( TT_Face face, - FT_Bool vertical, - FT_UInt gindex, - FT_Short* abearing, - FT_UShort* aadvance ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Get_Name_Func */ - /* */ - /* <Description> */ - /* From the `name' table, return a given ENGLISH name record in */ - /* ASCII. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* nameid :: The name id of the name record to return. */ - /* */ - /* <InOut> */ - /* name :: The address of an allocated string pointer. NULL if */ - /* no name is present. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - typedef FT_Error - (*TT_Get_Name_Func)( TT_Face face, - FT_UShort nameid, - FT_String** name ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Load_Table_Func */ - /* */ - /* <Description> */ - /* Load a given TrueType table. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* The function uses `face->goto_table' to seek the stream to the */ - /* start of the table, except while loading the font directory. */ - /* */ - typedef FT_Error - (*TT_Load_Table_Func)( TT_Face face, - FT_Stream stream ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Free_Table_Func */ - /* */ - /* <Description> */ - /* Free a given TrueType table. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - typedef void - (*TT_Free_Table_Func)( TT_Face face ); - - - /* - * @functype: - * TT_Face_GetKerningFunc - * - * @description: - * Return the horizontal kerning value between two glyphs. - * - * @input: - * face :: A handle to the source face object. - * left_glyph :: The left glyph index. - * right_glyph :: The right glyph index. - * - * @return: - * The kerning value in font units. - */ - typedef FT_Int - (*TT_Face_GetKerningFunc)( TT_Face face, - FT_UInt left_glyph, - FT_UInt right_glyph ); - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* SFNT_Interface */ - /* */ - /* <Description> */ - /* This structure holds pointers to the functions used to load and */ - /* free the basic tables that are required in a `sfnt' font file. */ - /* */ - /* <Fields> */ - /* Check the various xxx_Func() descriptions for details. */ - /* */ - typedef struct SFNT_Interface_ - { - TT_Loader_GotoTableFunc goto_table; - - TT_Init_Face_Func init_face; - TT_Load_Face_Func load_face; - TT_Done_Face_Func done_face; - FT_Module_Requester get_interface; - - TT_Load_Any_Func load_any; - - /* these functions are called by `load_face' but they can also */ - /* be called from external modules, if there is a need to do so */ - TT_Load_Table_Func load_head; - TT_Load_Metrics_Func load_hhea; - TT_Load_Table_Func load_cmap; - TT_Load_Table_Func load_maxp; - TT_Load_Table_Func load_os2; - TT_Load_Table_Func load_post; - - TT_Load_Table_Func load_name; - TT_Free_Table_Func free_name; - - /* this field was called `load_kerning' up to version 2.1.10 */ - TT_Load_Table_Func load_kern; - - TT_Load_Table_Func load_gasp; - TT_Load_Table_Func load_pclt; - - /* see `ttload.h'; this field was called `load_bitmap_header' up to */ - /* version 2.1.10 */ - TT_Load_Table_Func load_bhed; - - TT_Load_SBit_Image_Func load_sbit_image; - - /* see `ttpost.h' */ - TT_Get_PS_Name_Func get_psname; - TT_Free_Table_Func free_psnames; - - /* starting here, the structure differs from version 2.1.7 */ - - /* this field was introduced in version 2.1.8, named `get_psname' */ - TT_Face_GetKerningFunc get_kerning; - - /* new elements introduced after version 2.1.10 */ - - /* load the font directory, i.e., the offset table and */ - /* the table directory */ - TT_Load_Table_Func load_font_dir; - TT_Load_Metrics_Func load_hmtx; - - TT_Load_Table_Func load_eblc; - TT_Free_Table_Func free_eblc; - - TT_Set_SBit_Strike_Func set_sbit_strike; - TT_Load_Strike_Metrics_Func load_strike_metrics; - - TT_Get_Metrics_Func get_metrics; - - TT_Get_Name_Func get_name; - - } SFNT_Interface; - - - /* transitional */ - typedef SFNT_Interface* SFNT_Service; - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_SFNT_INTERFACE( \ - class_, \ - goto_table_, \ - init_face_, \ - load_face_, \ - done_face_, \ - get_interface_, \ - load_any_, \ - load_head_, \ - load_hhea_, \ - load_cmap_, \ - load_maxp_, \ - load_os2_, \ - load_post_, \ - load_name_, \ - free_name_, \ - load_kern_, \ - load_gasp_, \ - load_pclt_, \ - load_bhed_, \ - load_sbit_image_, \ - get_psname_, \ - free_psnames_, \ - get_kerning_, \ - load_font_dir_, \ - load_hmtx_, \ - load_eblc_, \ - free_eblc_, \ - set_sbit_strike_, \ - load_strike_metrics_, \ - get_metrics_, \ - get_name_ ) \ - static const SFNT_Interface class_ = \ - { \ - goto_table_, \ - init_face_, \ - load_face_, \ - done_face_, \ - get_interface_, \ - load_any_, \ - load_head_, \ - load_hhea_, \ - load_cmap_, \ - load_maxp_, \ - load_os2_, \ - load_post_, \ - load_name_, \ - free_name_, \ - load_kern_, \ - load_gasp_, \ - load_pclt_, \ - load_bhed_, \ - load_sbit_image_, \ - get_psname_, \ - free_psnames_, \ - get_kerning_, \ - load_font_dir_, \ - load_hmtx_, \ - load_eblc_, \ - free_eblc_, \ - set_sbit_strike_, \ - load_strike_metrics_, \ - get_metrics_, \ - get_name_, \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_INTERNAL( a, a_ ) \ - clazz->a = a_; - -#define FT_DEFINE_SFNT_INTERFACE( \ - class_, \ - goto_table_, \ - init_face_, \ - load_face_, \ - done_face_, \ - get_interface_, \ - load_any_, \ - load_head_, \ - load_hhea_, \ - load_cmap_, \ - load_maxp_, \ - load_os2_, \ - load_post_, \ - load_name_, \ - free_name_, \ - load_kern_, \ - load_gasp_, \ - load_pclt_, \ - load_bhed_, \ - load_sbit_image_, \ - get_psname_, \ - free_psnames_, \ - get_kerning_, \ - load_font_dir_, \ - load_hmtx_, \ - load_eblc_, \ - free_eblc_, \ - set_sbit_strike_, \ - load_strike_metrics_, \ - get_metrics_, \ - get_name_ ) \ - void \ - FT_Init_Class_ ## class_( FT_Library library, \ - SFNT_Interface* clazz ) \ - { \ - FT_UNUSED( library ); \ - \ - clazz->goto_table = goto_table_; \ - clazz->init_face = init_face_; \ - clazz->load_face = load_face_; \ - clazz->done_face = done_face_; \ - clazz->get_interface = get_interface_; \ - clazz->load_any = load_any_; \ - clazz->load_head = load_head_; \ - clazz->load_hhea = load_hhea_; \ - clazz->load_cmap = load_cmap_; \ - clazz->load_maxp = load_maxp_; \ - clazz->load_os2 = load_os2_; \ - clazz->load_post = load_post_; \ - clazz->load_name = load_name_; \ - clazz->free_name = free_name_; \ - clazz->load_kern = load_kern_; \ - clazz->load_gasp = load_gasp_; \ - clazz->load_pclt = load_pclt_; \ - clazz->load_bhed = load_bhed_; \ - clazz->load_sbit_image = load_sbit_image_; \ - clazz->get_psname = get_psname_; \ - clazz->free_psnames = free_psnames_; \ - clazz->get_kerning = get_kerning_; \ - clazz->load_font_dir = load_font_dir_; \ - clazz->load_hmtx = load_hmtx_; \ - clazz->load_eblc = load_eblc_; \ - clazz->free_eblc = free_eblc_; \ - clazz->set_sbit_strike = set_sbit_strike_; \ - clazz->load_strike_metrics = load_strike_metrics_; \ - clazz->get_metrics = get_metrics_; \ - clazz->get_name = get_name_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - -FT_END_HEADER - -#endif /* __SFNT_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/t1types.h b/third_party/freetype/include/freetype/internal/t1types.h deleted file mode 100644 index 029acc400934f0effc5c9617aaa0ed5814769c72..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/t1types.h +++ /dev/null @@ -1,255 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1types.h */ -/* */ -/* Basic Type1/Type2 type definitions and interface (specification */ -/* only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1TYPES_H__ -#define __T1TYPES_H__ - - -#include <ft2build.h> -#include FT_TYPE1_TABLES_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H -#include FT_INTERNAL_SERVICE_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* T1_EncodingRec */ - /* */ - /* <Description> */ - /* A structure modeling a custom encoding. */ - /* */ - /* <Fields> */ - /* num_chars :: The number of character codes in the encoding. */ - /* Usually 256. */ - /* */ - /* code_first :: The lowest valid character code in the encoding. */ - /* */ - /* code_last :: The highest valid character code in the encoding */ - /* + 1. When equal to code_first there are no valid */ - /* character codes. */ - /* */ - /* char_index :: An array of corresponding glyph indices. */ - /* */ - /* char_name :: An array of corresponding glyph names. */ - /* */ - typedef struct T1_EncodingRecRec_ - { - FT_Int num_chars; - FT_Int code_first; - FT_Int code_last; - - FT_UShort* char_index; - FT_String** char_name; - - } T1_EncodingRec, *T1_Encoding; - - - /* used to hold extra data of PS_FontInfoRec that - * cannot be stored in the publicly defined structure. - * - * Note these can't be blended with multiple-masters. - */ - typedef struct PS_FontExtraRec_ - { - FT_UShort fs_type; - - } PS_FontExtraRec; - - - typedef struct T1_FontRec_ - { - PS_FontInfoRec font_info; /* font info dictionary */ - PS_FontExtraRec font_extra; /* font info extra fields */ - PS_PrivateRec private_dict; /* private dictionary */ - FT_String* font_name; /* top-level dictionary */ - - T1_EncodingType encoding_type; - T1_EncodingRec encoding; - - FT_Byte* subrs_block; - FT_Byte* charstrings_block; - FT_Byte* glyph_names_block; - - FT_Int num_subrs; - FT_Byte** subrs; - FT_UInt* subrs_len; - - FT_Int num_glyphs; - FT_String** glyph_names; /* array of glyph names */ - FT_Byte** charstrings; /* array of glyph charstrings */ - FT_UInt* charstrings_len; - - FT_Byte paint_type; - FT_Byte font_type; - FT_Matrix font_matrix; - FT_Vector font_offset; - FT_BBox font_bbox; - FT_Long font_id; - - FT_Fixed stroke_width; - - } T1_FontRec, *T1_Font; - - - typedef struct CID_SubrsRec_ - { - FT_Int num_subrs; - FT_Byte** code; - - } CID_SubrsRec, *CID_Subrs; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** AFM FONT INFORMATION STRUCTURES ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - typedef struct AFM_TrackKernRec_ - { - FT_Int degree; - FT_Fixed min_ptsize; - FT_Fixed min_kern; - FT_Fixed max_ptsize; - FT_Fixed max_kern; - - } AFM_TrackKernRec, *AFM_TrackKern; - - typedef struct AFM_KernPairRec_ - { - FT_UInt index1; - FT_UInt index2; - FT_Int x; - FT_Int y; - - } AFM_KernPairRec, *AFM_KernPair; - - typedef struct AFM_FontInfoRec_ - { - FT_Bool IsCIDFont; - FT_BBox FontBBox; - FT_Fixed Ascender; - FT_Fixed Descender; - AFM_TrackKern TrackKerns; /* free if non-NULL */ - FT_UInt NumTrackKern; - AFM_KernPair KernPairs; /* free if non-NULL */ - FT_UInt NumKernPair; - - } AFM_FontInfoRec, *AFM_FontInfo; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** ORIGINAL T1_FACE CLASS DEFINITION ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - typedef struct T1_FaceRec_* T1_Face; - typedef struct CID_FaceRec_* CID_Face; - - - typedef struct T1_FaceRec_ - { - FT_FaceRec root; - T1_FontRec type1; - const void* psnames; - const void* psaux; - const void* afm_data; - FT_CharMapRec charmaprecs[2]; - FT_CharMap charmaps[2]; - - /* support for Multiple Masters fonts */ - PS_Blend blend; - - /* undocumented, optional: indices of subroutines that express */ - /* the NormalizeDesignVector and the ConvertDesignVector procedure, */ - /* respectively, as Type 2 charstrings; -1 if keywords not present */ - FT_Int ndv_idx; - FT_Int cdv_idx; - - /* undocumented, optional: has the same meaning as len_buildchar */ - /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */ - FT_UInt len_buildchar; - FT_Long* buildchar; - - /* since version 2.1 - interface to PostScript hinter */ - const void* pshinter; - - } T1_FaceRec; - - - typedef struct CID_FaceRec_ - { - FT_FaceRec root; - void* psnames; - void* psaux; - CID_FaceInfoRec cid; - PS_FontExtraRec font_extra; -#if 0 - void* afm_data; -#endif - CID_Subrs subrs; - - /* since version 2.1 - interface to PostScript hinter */ - void* pshinter; - - /* since version 2.1.8, but was originally positioned after `afm_data' */ - FT_Byte* binary_data; /* used if hex data has been converted */ - FT_Stream cid_stream; - - } CID_FaceRec; - - -FT_END_HEADER - -#endif /* __T1TYPES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/internal/tttypes.h b/third_party/freetype/include/freetype/internal/tttypes.h deleted file mode 100644 index 1507a7c57a0f57941008f6a04145dc0eae99d89d..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/internal/tttypes.h +++ /dev/null @@ -1,1526 +0,0 @@ -/***************************************************************************/ -/* */ -/* tttypes.h */ -/* */ -/* Basic SFNT/TrueType type definitions and interface (specification */ -/* only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTTYPES_H__ -#define __TTTYPES_H__ - - -#include <ft2build.h> -#include FT_TRUETYPE_TABLES_H -#include FT_INTERNAL_OBJECTS_H - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include FT_MULTIPLE_MASTERS_H -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TTC_HeaderRec */ - /* */ - /* <Description> */ - /* TrueType collection header. This table contains the offsets of */ - /* the font headers of each distinct TrueType face in the file. */ - /* */ - /* <Fields> */ - /* tag :: Must be `ttc ' to indicate a TrueType collection. */ - /* */ - /* version :: The version number. */ - /* */ - /* count :: The number of faces in the collection. The */ - /* specification says this should be an unsigned long, but */ - /* we use a signed long since we need the value -1 for */ - /* specific purposes. */ - /* */ - /* offsets :: The offsets of the font headers, one per face. */ - /* */ - typedef struct TTC_HeaderRec_ - { - FT_ULong tag; - FT_Fixed version; - FT_Long count; - FT_ULong* offsets; - - } TTC_HeaderRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* SFNT_HeaderRec */ - /* */ - /* <Description> */ - /* SFNT file format header. */ - /* */ - /* <Fields> */ - /* format_tag :: The font format tag. */ - /* */ - /* num_tables :: The number of tables in file. */ - /* */ - /* search_range :: Must be `16 * (max power of 2 <= num_tables)'. */ - /* */ - /* entry_selector :: Must be log2 of `search_range / 16'. */ - /* */ - /* range_shift :: Must be `num_tables * 16 - search_range'. */ - /* */ - typedef struct SFNT_HeaderRec_ - { - FT_ULong format_tag; - FT_UShort num_tables; - FT_UShort search_range; - FT_UShort entry_selector; - FT_UShort range_shift; - - FT_ULong offset; /* not in file */ - - } SFNT_HeaderRec, *SFNT_Header; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_TableRec */ - /* */ - /* <Description> */ - /* This structure describes a given table of a TrueType font. */ - /* */ - /* <Fields> */ - /* Tag :: A four-bytes tag describing the table. */ - /* */ - /* CheckSum :: The table checksum. This value can be ignored. */ - /* */ - /* Offset :: The offset of the table from the start of the TrueType */ - /* font in its resource. */ - /* */ - /* Length :: The table length (in bytes). */ - /* */ - typedef struct TT_TableRec_ - { - FT_ULong Tag; /* table type */ - FT_ULong CheckSum; /* table checksum */ - FT_ULong Offset; /* table file offset */ - FT_ULong Length; /* table length */ - - } TT_TableRec, *TT_Table; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* WOFF_HeaderRec */ - /* */ - /* <Description> */ - /* WOFF file format header. */ - /* */ - /* <Fields> */ - /* See */ - /* */ - /* http://www.w3.org/TR/WOFF/#WOFFHeader */ - /* */ - typedef struct WOFF_HeaderRec_ - { - FT_ULong signature; - FT_ULong flavor; - FT_ULong length; - FT_UShort num_tables; - FT_UShort reserved; - FT_ULong totalSfntSize; - FT_UShort majorVersion; - FT_UShort minorVersion; - FT_ULong metaOffset; - FT_ULong metaLength; - FT_ULong metaOrigLength; - FT_ULong privOffset; - FT_ULong privLength; - - } WOFF_HeaderRec, *WOFF_Header; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* WOFF_TableRec */ - /* */ - /* <Description> */ - /* This structure describes a given table of a WOFF font. */ - /* */ - /* <Fields> */ - /* Tag :: A four-bytes tag describing the table. */ - /* */ - /* Offset :: The offset of the table from the start of the WOFF */ - /* font in its resource. */ - /* */ - /* CompLength :: Compressed table length (in bytes). */ - /* */ - /* OrigLength :: Unompressed table length (in bytes). */ - /* */ - /* CheckSum :: The table checksum. This value can be ignored. */ - /* */ - /* OrigOffset :: The uncompressed table file offset. This value gets */ - /* computed while constructing the (uncompressed) SFNT */ - /* header. It is not contained in the WOFF file. */ - /* */ - typedef struct WOFF_TableRec_ - { - FT_ULong Tag; /* table ID */ - FT_ULong Offset; /* table file offset */ - FT_ULong CompLength; /* compressed table length */ - FT_ULong OrigLength; /* uncompressed table length */ - FT_ULong CheckSum; /* uncompressed checksum */ - - FT_ULong OrigOffset; /* uncompressed table file offset */ - /* (not in the WOFF file) */ - } WOFF_TableRec, *WOFF_Table; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_LongMetricsRec */ - /* */ - /* <Description> */ - /* A structure modeling the long metrics of the `hmtx' and `vmtx' */ - /* TrueType tables. The values are expressed in font units. */ - /* */ - /* <Fields> */ - /* advance :: The advance width or height for the glyph. */ - /* */ - /* bearing :: The left-side or top-side bearing for the glyph. */ - /* */ - typedef struct TT_LongMetricsRec_ - { - FT_UShort advance; - FT_Short bearing; - - } TT_LongMetricsRec, *TT_LongMetrics; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* TT_ShortMetrics */ - /* */ - /* <Description> */ - /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ - /* tables. */ - /* */ - typedef FT_Short TT_ShortMetrics; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_NameEntryRec */ - /* */ - /* <Description> */ - /* A structure modeling TrueType name records. Name records are used */ - /* to store important strings like family name, style name, */ - /* copyright, etc. in _localized_ versions (i.e., language, encoding, */ - /* etc). */ - /* */ - /* <Fields> */ - /* platformID :: The ID of the name's encoding platform. */ - /* */ - /* encodingID :: The platform-specific ID for the name's encoding. */ - /* */ - /* languageID :: The platform-specific ID for the name's language. */ - /* */ - /* nameID :: The ID specifying what kind of name this is. */ - /* */ - /* stringLength :: The length of the string in bytes. */ - /* */ - /* stringOffset :: The offset to the string in the `name' table. */ - /* */ - /* string :: A pointer to the string's bytes. Note that these */ - /* are usually UTF-16 encoded characters. */ - /* */ - typedef struct TT_NameEntryRec_ - { - FT_UShort platformID; - FT_UShort encodingID; - FT_UShort languageID; - FT_UShort nameID; - FT_UShort stringLength; - FT_ULong stringOffset; - - /* this last field is not defined in the spec */ - /* but used by the FreeType engine */ - - FT_Byte* string; - - } TT_NameEntryRec, *TT_NameEntry; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_NameTableRec */ - /* */ - /* <Description> */ - /* A structure modeling the TrueType name table. */ - /* */ - /* <Fields> */ - /* format :: The format of the name table. */ - /* */ - /* numNameRecords :: The number of names in table. */ - /* */ - /* storageOffset :: The offset of the name table in the `name' */ - /* TrueType table. */ - /* */ - /* names :: An array of name records. */ - /* */ - /* stream :: the file's input stream. */ - /* */ - typedef struct TT_NameTableRec_ - { - FT_UShort format; - FT_UInt numNameRecords; - FT_UInt storageOffset; - TT_NameEntryRec* names; - FT_Stream stream; - - } TT_NameTableRec, *TT_NameTable; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_GaspRangeRec */ - /* */ - /* <Description> */ - /* A tiny structure used to model a gasp range according to the */ - /* TrueType specification. */ - /* */ - /* <Fields> */ - /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */ - /* */ - /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */ - /* modes to be used. */ - /* */ - typedef struct TT_GaspRangeRec_ - { - FT_UShort maxPPEM; - FT_UShort gaspFlag; - - } TT_GaspRangeRec, *TT_GaspRange; - - -#define TT_GASP_GRIDFIT 0x01 -#define TT_GASP_DOGRAY 0x02 - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_GaspRec */ - /* */ - /* <Description> */ - /* A structure modeling the TrueType `gasp' table used to specify */ - /* grid-fitting and anti-aliasing behaviour. */ - /* */ - /* <Fields> */ - /* version :: The version number. */ - /* */ - /* numRanges :: The number of gasp ranges in table. */ - /* */ - /* gaspRanges :: An array of gasp ranges. */ - /* */ - typedef struct TT_Gasp_ - { - FT_UShort version; - FT_UShort numRanges; - TT_GaspRange gaspRanges; - - } TT_GaspRec; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** EMBEDDED BITMAPS SUPPORT ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_MetricsRec */ - /* */ - /* <Description> */ - /* A structure used to hold the big metrics of a given glyph bitmap */ - /* in a TrueType or OpenType font. These are usually found in the */ - /* `EBDT' (Microsoft) or `bloc' (Apple) table. */ - /* */ - /* <Fields> */ - /* height :: The glyph height in pixels. */ - /* */ - /* width :: The glyph width in pixels. */ - /* */ - /* horiBearingX :: The horizontal left bearing. */ - /* */ - /* horiBearingY :: The horizontal top bearing. */ - /* */ - /* horiAdvance :: The horizontal advance. */ - /* */ - /* vertBearingX :: The vertical left bearing. */ - /* */ - /* vertBearingY :: The vertical top bearing. */ - /* */ - /* vertAdvance :: The vertical advance. */ - /* */ - typedef struct TT_SBit_MetricsRec_ - { - FT_UShort height; - FT_UShort width; - - FT_Short horiBearingX; - FT_Short horiBearingY; - FT_UShort horiAdvance; - - FT_Short vertBearingX; - FT_Short vertBearingY; - FT_UShort vertAdvance; - - } TT_SBit_MetricsRec, *TT_SBit_Metrics; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_SmallMetricsRec */ - /* */ - /* <Description> */ - /* A structure used to hold the small metrics of a given glyph bitmap */ - /* in a TrueType or OpenType font. These are usually found in the */ - /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */ - /* */ - /* <Fields> */ - /* height :: The glyph height in pixels. */ - /* */ - /* width :: The glyph width in pixels. */ - /* */ - /* bearingX :: The left-side bearing. */ - /* */ - /* bearingY :: The top-side bearing. */ - /* */ - /* advance :: The advance width or height. */ - /* */ - typedef struct TT_SBit_Small_Metrics_ - { - FT_Byte height; - FT_Byte width; - - FT_Char bearingX; - FT_Char bearingY; - FT_Byte advance; - - } TT_SBit_SmallMetricsRec, *TT_SBit_SmallMetrics; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_LineMetricsRec */ - /* */ - /* <Description> */ - /* A structure used to describe the text line metrics of a given */ - /* bitmap strike, for either a horizontal or vertical layout. */ - /* */ - /* <Fields> */ - /* ascender :: The ascender in pixels. */ - /* */ - /* descender :: The descender in pixels. */ - /* */ - /* max_width :: The maximum glyph width in pixels. */ - /* */ - /* caret_slope_enumerator :: Rise of the caret slope, typically set */ - /* to 1 for non-italic fonts. */ - /* */ - /* caret_slope_denominator :: Rise of the caret slope, typically set */ - /* to 0 for non-italic fonts. */ - /* */ - /* caret_offset :: Offset in pixels to move the caret for */ - /* proper positioning. */ - /* */ - /* min_origin_SB :: Minimum of horiBearingX (resp. */ - /* vertBearingY). */ - /* min_advance_SB :: Minimum of */ - /* */ - /* horizontal advance - */ - /* ( horiBearingX + width ) */ - /* */ - /* resp. */ - /* */ - /* vertical advance - */ - /* ( vertBearingY + height ) */ - /* */ - /* max_before_BL :: Maximum of horiBearingY (resp. */ - /* vertBearingY). */ - /* */ - /* min_after_BL :: Minimum of */ - /* */ - /* horiBearingY - height */ - /* */ - /* resp. */ - /* */ - /* vertBearingX - width */ - /* */ - /* pads :: Unused (to make the size of the record */ - /* a multiple of 32 bits. */ - /* */ - typedef struct TT_SBit_LineMetricsRec_ - { - FT_Char ascender; - FT_Char descender; - FT_Byte max_width; - FT_Char caret_slope_numerator; - FT_Char caret_slope_denominator; - FT_Char caret_offset; - FT_Char min_origin_SB; - FT_Char min_advance_SB; - FT_Char max_before_BL; - FT_Char min_after_BL; - FT_Char pads[2]; - - } TT_SBit_LineMetricsRec, *TT_SBit_LineMetrics; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_RangeRec */ - /* */ - /* <Description> */ - /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */ - /* (Microsoft) or `bloc' (Apple) tables. */ - /* */ - /* <Fields> */ - /* first_glyph :: The first glyph index in the range. */ - /* */ - /* last_glyph :: The last glyph index in the range. */ - /* */ - /* index_format :: The format of index table. Valid values are 1 */ - /* to 5. */ - /* */ - /* image_format :: The format of `EBDT' image data. */ - /* */ - /* image_offset :: The offset to image data in `EBDT'. */ - /* */ - /* image_size :: For index formats 2 and 5. This is the size in */ - /* bytes of each glyph bitmap. */ - /* */ - /* big_metrics :: For index formats 2 and 5. This is the big */ - /* metrics for each glyph bitmap. */ - /* */ - /* num_glyphs :: For index formats 4 and 5. This is the number of */ - /* glyphs in the code array. */ - /* */ - /* glyph_offsets :: For index formats 1 and 3. */ - /* */ - /* glyph_codes :: For index formats 4 and 5. */ - /* */ - /* table_offset :: The offset of the index table in the `EBLC' */ - /* table. Only used during strike loading. */ - /* */ - typedef struct TT_SBit_RangeRec_ - { - FT_UShort first_glyph; - FT_UShort last_glyph; - - FT_UShort index_format; - FT_UShort image_format; - FT_ULong image_offset; - - FT_ULong image_size; - TT_SBit_MetricsRec metrics; - FT_ULong num_glyphs; - - FT_ULong* glyph_offsets; - FT_UShort* glyph_codes; - - FT_ULong table_offset; - - } TT_SBit_RangeRec, *TT_SBit_Range; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_StrikeRec */ - /* */ - /* <Description> */ - /* A structure used describe a given bitmap strike in the `EBLC' */ - /* (Microsoft) or `bloc' (Apple) tables. */ - /* */ - /* <Fields> */ - /* num_index_ranges :: The number of index ranges. */ - /* */ - /* index_ranges :: An array of glyph index ranges. */ - /* */ - /* color_ref :: Unused. `color_ref' is put in for future */ - /* enhancements, but these fields are already */ - /* in use by other platforms (e.g. Newton). */ - /* For details, please see */ - /* */ - /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */ - /* */ - /* hori :: The line metrics for horizontal layouts. */ - /* */ - /* vert :: The line metrics for vertical layouts. */ - /* */ - /* start_glyph :: The lowest glyph index for this strike. */ - /* */ - /* end_glyph :: The highest glyph index for this strike. */ - /* */ - /* x_ppem :: The number of horizontal pixels per EM. */ - /* */ - /* y_ppem :: The number of vertical pixels per EM. */ - /* */ - /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */ - /* and 8. */ - /* */ - /* flags :: Is this a vertical or horizontal strike? For */ - /* details, please see */ - /* */ - /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */ - /* */ - typedef struct TT_SBit_StrikeRec_ - { - FT_Int num_ranges; - TT_SBit_Range sbit_ranges; - FT_ULong ranges_offset; - - FT_ULong color_ref; - - TT_SBit_LineMetricsRec hori; - TT_SBit_LineMetricsRec vert; - - FT_UShort start_glyph; - FT_UShort end_glyph; - - FT_Byte x_ppem; - FT_Byte y_ppem; - - FT_Byte bit_depth; - FT_Char flags; - - } TT_SBit_StrikeRec, *TT_SBit_Strike; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_ComponentRec */ - /* */ - /* <Description> */ - /* A simple structure to describe a compound sbit element. */ - /* */ - /* <Fields> */ - /* glyph_code :: The element's glyph index. */ - /* */ - /* x_offset :: The element's left bearing. */ - /* */ - /* y_offset :: The element's top bearing. */ - /* */ - typedef struct TT_SBit_ComponentRec_ - { - FT_UShort glyph_code; - FT_Char x_offset; - FT_Char y_offset; - - } TT_SBit_ComponentRec, *TT_SBit_Component; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_SBit_ScaleRec */ - /* */ - /* <Description> */ - /* A structure used describe a given bitmap scaling table, as defined */ - /* in the `EBSC' table. */ - /* */ - /* <Fields> */ - /* hori :: The horizontal line metrics. */ - /* */ - /* vert :: The vertical line metrics. */ - /* */ - /* x_ppem :: The number of horizontal pixels per EM. */ - /* */ - /* y_ppem :: The number of vertical pixels per EM. */ - /* */ - /* x_ppem_substitute :: Substitution x_ppem value. */ - /* */ - /* y_ppem_substitute :: Substitution y_ppem value. */ - /* */ - typedef struct TT_SBit_ScaleRec_ - { - TT_SBit_LineMetricsRec hori; - TT_SBit_LineMetricsRec vert; - - FT_Byte x_ppem; - FT_Byte y_ppem; - - FT_Byte x_ppem_substitute; - FT_Byte y_ppem_substitute; - - } TT_SBit_ScaleRec, *TT_SBit_Scale; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_Post_20Rec */ - /* */ - /* <Description> */ - /* Postscript names sub-table, format 2.0. Stores the PS name of */ - /* each glyph in the font face. */ - /* */ - /* <Fields> */ - /* num_glyphs :: The number of named glyphs in the table. */ - /* */ - /* num_names :: The number of PS names stored in the table. */ - /* */ - /* glyph_indices :: The indices of the glyphs in the names arrays. */ - /* */ - /* glyph_names :: The PS names not in Mac Encoding. */ - /* */ - typedef struct TT_Post_20Rec_ - { - FT_UShort num_glyphs; - FT_UShort num_names; - FT_UShort* glyph_indices; - FT_Char** glyph_names; - - } TT_Post_20Rec, *TT_Post_20; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_Post_25Rec */ - /* */ - /* <Description> */ - /* Postscript names sub-table, format 2.5. Stores the PS name of */ - /* each glyph in the font face. */ - /* */ - /* <Fields> */ - /* num_glyphs :: The number of glyphs in the table. */ - /* */ - /* offsets :: An array of signed offsets in a normal Mac */ - /* Postscript name encoding. */ - /* */ - typedef struct TT_Post_25_ - { - FT_UShort num_glyphs; - FT_Char* offsets; - - } TT_Post_25Rec, *TT_Post_25; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_Post_NamesRec */ - /* */ - /* <Description> */ - /* Postscript names table, either format 2.0 or 2.5. */ - /* */ - /* <Fields> */ - /* loaded :: A flag to indicate whether the PS names are loaded. */ - /* */ - /* format_20 :: The sub-table used for format 2.0. */ - /* */ - /* format_25 :: The sub-table used for format 2.5. */ - /* */ - typedef struct TT_Post_NamesRec_ - { - FT_Bool loaded; - - union - { - TT_Post_20Rec format_20; - TT_Post_25Rec format_25; - - } names; - - } TT_Post_NamesRec, *TT_Post_Names; - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** GX VARIATION TABLE SUPPORT ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - typedef struct GX_BlendRec_ *GX_Blend; -#endif - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** EMBEDDED BDF PROPERTIES TABLE SUPPORT ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /* - * These types are used to support a `BDF ' table that isn't part of the - * official TrueType specification. It is mainly used in SFNT-based - * bitmap fonts that were generated from a set of BDF fonts. - * - * The format of the table is as follows. - * - * USHORT version `BDF ' table version number, should be 0x0001. - * USHORT strikeCount Number of strikes (bitmap sizes) in this table. - * ULONG stringTable Offset (from start of BDF table) to string - * table. - * - * This is followed by an array of `strikeCount' descriptors, having the - * following format. - * - * USHORT ppem Vertical pixels per EM for this strike. - * USHORT numItems Number of items for this strike (properties and - * atoms). Maximum is 255. - * - * This array in turn is followed by `strikeCount' value sets. Each - * `value set' is an array of `numItems' items with the following format. - * - * ULONG item_name Offset in string table to item name. - * USHORT item_type The item type. Possible values are - * 0 => string (e.g., COMMENT) - * 1 => atom (e.g., FONT or even SIZE) - * 2 => int32 - * 3 => uint32 - * 0x10 => A flag to indicate a properties. This - * is ORed with the above values. - * ULONG item_value For strings => Offset into string table without - * the corresponding double quotes. - * For atoms => Offset into string table. - * For integers => Direct value. - * - * All strings in the string table consist of bytes and are - * zero-terminated. - * - */ - -#ifdef TT_CONFIG_OPTION_BDF - - typedef struct TT_BDFRec_ - { - FT_Byte* table; - FT_Byte* table_end; - FT_Byte* strings; - FT_ULong strings_size; - FT_UInt num_strikes; - FT_Bool loaded; - - } TT_BDFRec, *TT_BDF; - -#endif /* TT_CONFIG_OPTION_BDF */ - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** ***/ - /*** ORIGINAL TT_FACE CLASS DEFINITION ***/ - /*** ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This structure/class is defined here because it is common to the */ - /* following formats: TTF, OpenType-TT, and OpenType-CFF. */ - /* */ - /* Note, however, that the classes TT_Size and TT_GlyphSlot are not */ - /* shared between font drivers, and are thus defined in `ttobjs.h'. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* TT_Face */ - /* */ - /* <Description> */ - /* A handle to a TrueType face/font object. A TT_Face encapsulates */ - /* the resolution and scaling independent parts of a TrueType font */ - /* resource. */ - /* */ - /* <Note> */ - /* The TT_Face structure is also used as a `parent class' for the */ - /* OpenType-CFF class (T2_Face). */ - /* */ - typedef struct TT_FaceRec_* TT_Face; - - - /* a function type used for the truetype bytecode interpreter hooks */ - typedef FT_Error - (*TT_Interpreter)( void* exec_context ); - - /* forward declaration */ - typedef struct TT_LoaderRec_* TT_Loader; - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Loader_GotoTableFunc */ - /* */ - /* <Description> */ - /* Seeks a stream to the start of a given TrueType table. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* tag :: A 4-byte tag used to name the table. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Output> */ - /* length :: The length of the table in bytes. Set to 0 if not */ - /* needed. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* The stream cursor must be at the font file's origin. */ - /* */ - typedef FT_Error - (*TT_Loader_GotoTableFunc)( TT_Face face, - FT_ULong tag, - FT_Stream stream, - FT_ULong* length ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Loader_StartGlyphFunc */ - /* */ - /* <Description> */ - /* Seeks a stream to the start of a given glyph element, and opens a */ - /* frame for it. */ - /* */ - /* <Input> */ - /* loader :: The current TrueType glyph loader object. */ - /* */ - /* glyph index :: The index of the glyph to access. */ - /* */ - /* offset :: The offset of the glyph according to the */ - /* `locations' table. */ - /* */ - /* byte_count :: The size of the frame in bytes. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* This function is normally equivalent to FT_STREAM_SEEK(offset) */ - /* followed by FT_FRAME_ENTER(byte_count) with the loader's stream, */ - /* but alternative formats (e.g. compressed ones) might use something */ - /* different. */ - /* */ - typedef FT_Error - (*TT_Loader_StartGlyphFunc)( TT_Loader loader, - FT_UInt glyph_index, - FT_ULong offset, - FT_UInt byte_count ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Loader_ReadGlyphFunc */ - /* */ - /* <Description> */ - /* Reads one glyph element (its header, a simple glyph, or a */ - /* composite) from the loader's current stream frame. */ - /* */ - /* <Input> */ - /* loader :: The current TrueType glyph loader object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - typedef FT_Error - (*TT_Loader_ReadGlyphFunc)( TT_Loader loader ); - - - /*************************************************************************/ - /* */ - /* <FuncType> */ - /* TT_Loader_EndGlyphFunc */ - /* */ - /* <Description> */ - /* Closes the current loader stream frame for the glyph. */ - /* */ - /* <Input> */ - /* loader :: The current TrueType glyph loader object. */ - /* */ - typedef void - (*TT_Loader_EndGlyphFunc)( TT_Loader loader ); - - - typedef enum TT_SbitTableType_ - { - TT_SBIT_TABLE_TYPE_NONE = 0, - TT_SBIT_TABLE_TYPE_EBLC, /* `EBLC' (Microsoft), */ - /* `bloc' (Apple) */ - TT_SBIT_TABLE_TYPE_CBLC, /* `CBLC' (Google) */ - TT_SBIT_TABLE_TYPE_SBIX, /* `sbix' (Apple) */ - - /* do not remove */ - TT_SBIT_TABLE_TYPE_MAX - - } TT_SbitTableType; - - - /*************************************************************************/ - /* */ - /* TrueType Face Type */ - /* */ - /* <Struct> */ - /* TT_Face */ - /* */ - /* <Description> */ - /* The TrueType face class. These objects model the resolution and */ - /* point-size independent data found in a TrueType font file. */ - /* */ - /* <Fields> */ - /* root :: The base FT_Face structure, managed by the */ - /* base layer. */ - /* */ - /* ttc_header :: The TrueType collection header, used when */ - /* the file is a `ttc' rather than a `ttf'. */ - /* For ordinary font files, the field */ - /* `ttc_header.count' is set to 0. */ - /* */ - /* format_tag :: The font format tag. */ - /* */ - /* num_tables :: The number of TrueType tables in this font */ - /* file. */ - /* */ - /* dir_tables :: The directory of TrueType tables for this */ - /* font file. */ - /* */ - /* header :: The font's font header (`head' table). */ - /* Read on font opening. */ - /* */ - /* horizontal :: The font's horizontal header (`hhea' */ - /* table). This field also contains the */ - /* associated horizontal metrics table */ - /* (`hmtx'). */ - /* */ - /* max_profile :: The font's maximum profile table. Read on */ - /* font opening. Note that some maximum */ - /* values cannot be taken directly from this */ - /* table. We thus define additional fields */ - /* below to hold the computed maxima. */ - /* */ - /* vertical_info :: A boolean which is set when the font file */ - /* contains vertical metrics. If not, the */ - /* value of the `vertical' field is */ - /* undefined. */ - /* */ - /* vertical :: The font's vertical header (`vhea' table). */ - /* This field also contains the associated */ - /* vertical metrics table (`vmtx'), if found. */ - /* IMPORTANT: The contents of this field is */ - /* undefined if the `vertical_info' field is */ - /* unset. */ - /* */ - /* num_names :: The number of name records within this */ - /* TrueType font. */ - /* */ - /* name_table :: The table of name records (`name'). */ - /* */ - /* os2 :: The font's OS/2 table (`OS/2'). */ - /* */ - /* postscript :: The font's PostScript table (`post' */ - /* table). The PostScript glyph names are */ - /* not loaded by the driver on face opening. */ - /* See the `ttpost' module for more details. */ - /* */ - /* cmap_table :: Address of the face's `cmap' SFNT table */ - /* in memory (it's an extracted frame). */ - /* */ - /* cmap_size :: The size in bytes of the `cmap_table' */ - /* described above. */ - /* */ - /* goto_table :: A function called by each TrueType table */ - /* loader to position a stream's cursor to */ - /* the start of a given table according to */ - /* its tag. It defaults to TT_Goto_Face but */ - /* can be different for strange formats (e.g. */ - /* Type 42). */ - /* */ - /* access_glyph_frame :: A function used to access the frame of a */ - /* given glyph within the face's font file. */ - /* */ - /* forget_glyph_frame :: A function used to forget the frame of a */ - /* given glyph when all data has been loaded. */ - /* */ - /* read_glyph_header :: A function used to read a glyph header. */ - /* It must be called between an `access' and */ - /* `forget'. */ - /* */ - /* read_simple_glyph :: A function used to read a simple glyph. */ - /* It must be called after the header was */ - /* read, and before the `forget'. */ - /* */ - /* read_composite_glyph :: A function used to read a composite glyph. */ - /* It must be called after the header was */ - /* read, and before the `forget'. */ - /* */ - /* sfnt :: A pointer to the SFNT service. */ - /* */ - /* psnames :: A pointer to the PostScript names service. */ - /* */ - /* hdmx :: The face's horizontal device metrics */ - /* (`hdmx' table). This table is optional in */ - /* TrueType/OpenType fonts. */ - /* */ - /* gasp :: The grid-fitting and scaling properties */ - /* table (`gasp'). This table is optional in */ - /* TrueType/OpenType fonts. */ - /* */ - /* pclt :: The `pclt' SFNT table. */ - /* */ - /* num_sbit_scales :: The number of sbit scales for this font. */ - /* */ - /* sbit_scales :: Array of sbit scales embedded in this */ - /* font. This table is optional in a */ - /* TrueType/OpenType font. */ - /* */ - /* postscript_names :: A table used to store the Postscript names */ - /* of the glyphs for this font. See the */ - /* file `ttconfig.h' for comments on the */ - /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */ - /* */ - /* num_locations :: The number of glyph locations in this */ - /* TrueType file. This should be */ - /* identical to the number of glyphs. */ - /* Ignored for Type 2 fonts. */ - /* */ - /* glyph_locations :: An array of longs. These are offsets to */ - /* glyph data within the `glyf' table. */ - /* Ignored for Type 2 font faces. */ - /* */ - /* glyf_len :: The length of the `glyf' table. Needed */ - /* for malformed `loca' tables. */ - /* */ - /* font_program_size :: Size in bytecodes of the face's font */ - /* program. 0 if none defined. Ignored for */ - /* Type 2 fonts. */ - /* */ - /* font_program :: The face's font program (bytecode stream) */ - /* executed at load time, also used during */ - /* glyph rendering. Comes from the `fpgm' */ - /* table. Ignored for Type 2 font fonts. */ - /* */ - /* cvt_program_size :: The size in bytecodes of the face's cvt */ - /* program. Ignored for Type 2 fonts. */ - /* */ - /* cvt_program :: The face's cvt program (bytecode stream) */ - /* executed each time an instance/size is */ - /* changed/reset. Comes from the `prep' */ - /* table. Ignored for Type 2 fonts. */ - /* */ - /* cvt_size :: Size of the control value table (in */ - /* entries). Ignored for Type 2 fonts. */ - /* */ - /* cvt :: The face's original control value table. */ - /* Coordinates are expressed in unscaled font */ - /* units. Comes from the `cvt ' table. */ - /* Ignored for Type 2 fonts. */ - /* */ - /* num_kern_pairs :: The number of kerning pairs present in the */ - /* font file. The engine only loads the */ - /* first horizontal format 0 kern table it */ - /* finds in the font file. Ignored for */ - /* Type 2 fonts. */ - /* */ - /* kern_table_index :: The index of the kerning table in the font */ - /* kerning directory. Ignored for Type 2 */ - /* fonts. */ - /* */ - /* interpreter :: A pointer to the TrueType bytecode */ - /* interpreters field is also used to hook */ - /* the debugger in `ttdebug'. */ - /* */ - /* unpatented_hinting :: If true, use only unpatented methods in */ - /* the bytecode interpreter. */ - /* */ - /* doblend :: A boolean which is set if the font should */ - /* be blended (this is for GX var). */ - /* */ - /* blend :: Contains the data needed to control GX */ - /* variation tables (rather like Multiple */ - /* Master data). */ - /* */ - /* extra :: Reserved for third-party font drivers. */ - /* */ - /* postscript_name :: The PS name of the font. Used by the */ - /* postscript name service. */ - /* */ - typedef struct TT_FaceRec_ - { - FT_FaceRec root; - - TTC_HeaderRec ttc_header; - - FT_ULong format_tag; - FT_UShort num_tables; - TT_Table dir_tables; - - TT_Header header; /* TrueType header table */ - TT_HoriHeader horizontal; /* TrueType horizontal header */ - - TT_MaxProfile max_profile; - - FT_Bool vertical_info; - TT_VertHeader vertical; /* TT Vertical header, if present */ - - FT_UShort num_names; /* number of name records */ - TT_NameTableRec name_table; /* name table */ - - TT_OS2 os2; /* TrueType OS/2 table */ - TT_Postscript postscript; /* TrueType Postscript table */ - - FT_Byte* cmap_table; /* extracted `cmap' table */ - FT_ULong cmap_size; - - TT_Loader_GotoTableFunc goto_table; - - TT_Loader_StartGlyphFunc access_glyph_frame; - TT_Loader_EndGlyphFunc forget_glyph_frame; - TT_Loader_ReadGlyphFunc read_glyph_header; - TT_Loader_ReadGlyphFunc read_simple_glyph; - TT_Loader_ReadGlyphFunc read_composite_glyph; - - /* a typeless pointer to the SFNT_Interface table used to load */ - /* the basic TrueType tables in the face object */ - void* sfnt; - - /* a typeless pointer to the FT_Service_PsCMapsRec table used to */ - /* handle glyph names <-> unicode & Mac values */ - void* psnames; - - - /***********************************************************************/ - /* */ - /* Optional TrueType/OpenType tables */ - /* */ - /***********************************************************************/ - - /* grid-fitting and scaling table */ - TT_GaspRec gasp; /* the `gasp' table */ - - /* PCL 5 table */ - TT_PCLT pclt; - - /* embedded bitmaps support */ - FT_ULong num_sbit_scales; - TT_SBit_Scale sbit_scales; - - /* postscript names table */ - TT_Post_NamesRec postscript_names; - - - /***********************************************************************/ - /* */ - /* TrueType-specific fields (ignored by the OTF-Type2 driver) */ - /* */ - /***********************************************************************/ - - /* the font program, if any */ - FT_ULong font_program_size; - FT_Byte* font_program; - - /* the cvt program, if any */ - FT_ULong cvt_program_size; - FT_Byte* cvt_program; - - /* the original, unscaled, control value table */ - FT_ULong cvt_size; - FT_Short* cvt; - - /* A pointer to the bytecode interpreter to use. This is also */ - /* used to hook the debugger for the `ttdebug' utility. */ - TT_Interpreter interpreter; - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - /* Use unpatented hinting only. */ - FT_Bool unpatented_hinting; -#endif - - /***********************************************************************/ - /* */ - /* Other tables or fields. This is used by derivative formats like */ - /* OpenType. */ - /* */ - /***********************************************************************/ - - FT_Generic extra; - - const char* postscript_name; - - FT_ULong glyf_len; - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_Bool doblend; - GX_Blend blend; -#endif - - /* since version 2.2 */ - - FT_Byte* horz_metrics; - FT_ULong horz_metrics_size; - - FT_Byte* vert_metrics; - FT_ULong vert_metrics_size; - - FT_ULong num_locations; /* in broken TTF, gid > 0xFFFF */ - FT_Byte* glyph_locations; - - FT_Byte* hdmx_table; - FT_ULong hdmx_table_size; - FT_UInt hdmx_record_count; - FT_ULong hdmx_record_size; - FT_Byte* hdmx_record_sizes; - - FT_Byte* sbit_table; - FT_ULong sbit_table_size; - TT_SbitTableType sbit_table_type; - FT_UInt sbit_num_strikes; - - FT_Byte* kern_table; - FT_ULong kern_table_size; - FT_UInt num_kern_tables; - FT_UInt32 kern_avail_bits; - FT_UInt32 kern_order_bits; - -#ifdef TT_CONFIG_OPTION_BDF - TT_BDFRec bdf; -#endif /* TT_CONFIG_OPTION_BDF */ - - /* since 2.3.0 */ - FT_ULong horz_metrics_offset; - FT_ULong vert_metrics_offset; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* since 2.4.12 */ - FT_ULong sph_found_func_flags; /* special functions found */ - /* for this face */ - FT_Bool sph_compatibility_mode; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - } TT_FaceRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_GlyphZoneRec */ - /* */ - /* <Description> */ - /* A glyph zone is used to load, scale and hint glyph outline */ - /* coordinates. */ - /* */ - /* <Fields> */ - /* memory :: A handle to the memory manager. */ - /* */ - /* max_points :: The maximum size in points of the zone. */ - /* */ - /* max_contours :: Max size in links contours of the zone. */ - /* */ - /* n_points :: The current number of points in the zone. */ - /* */ - /* n_contours :: The current number of contours in the zone. */ - /* */ - /* org :: The original glyph coordinates (font */ - /* units/scaled). */ - /* */ - /* cur :: The current glyph coordinates (scaled/hinted). */ - /* */ - /* tags :: The point control tags. */ - /* */ - /* contours :: The contours end points. */ - /* */ - /* first_point :: Offset of the current subglyph's first point. */ - /* */ - typedef struct TT_GlyphZoneRec_ - { - FT_Memory memory; - FT_UShort max_points; - FT_Short max_contours; - FT_UShort n_points; /* number of points in zone */ - FT_Short n_contours; /* number of contours */ - - FT_Vector* org; /* original point coordinates */ - FT_Vector* cur; /* current point coordinates */ - FT_Vector* orus; /* original (unscaled) point coordinates */ - - FT_Byte* tags; /* current touch flags */ - FT_UShort* contours; /* contour end points */ - - FT_UShort first_point; /* offset of first (#0) point */ - - } TT_GlyphZoneRec, *TT_GlyphZone; - - - /* handle to execution context */ - typedef struct TT_ExecContextRec_* TT_ExecContext; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* TT_Size */ - /* */ - /* <Description> */ - /* A handle to a TrueType size object. */ - /* */ - typedef struct TT_SizeRec_* TT_Size; - - - /* glyph loader structure */ - typedef struct TT_LoaderRec_ - { - TT_Face face; - TT_Size size; - FT_GlyphSlot glyph; - FT_GlyphLoader gloader; - - FT_ULong load_flags; - FT_UInt glyph_index; - - FT_Stream stream; - FT_Int byte_len; - - FT_Short n_contours; - FT_BBox bbox; - FT_Int left_bearing; - FT_Int advance; - FT_Int linear; - FT_Bool linear_def; - FT_Vector pp1; - FT_Vector pp2; - - FT_ULong glyf_offset; - - /* the zone where we load our glyphs */ - TT_GlyphZoneRec base; - TT_GlyphZoneRec zone; - - TT_ExecContext exec; - FT_Byte* instructions; - FT_ULong ins_pos; - - /* for possible extensibility in other formats */ - void* other; - - /* since version 2.1.8 */ - FT_Int top_bearing; - FT_Int vadvance; - FT_Vector pp3; - FT_Vector pp4; - - /* since version 2.2.1 */ - FT_Byte* cursor; - FT_Byte* limit; - - } TT_LoaderRec; - - -FT_END_HEADER - -#endif /* __TTTYPES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/t1tables.h b/third_party/freetype/include/freetype/t1tables.h deleted file mode 100644 index a6ea415af58590d63a6cfd096b01bf7734e68e88..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/t1tables.h +++ /dev/null @@ -1,761 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1tables.h */ -/* */ -/* Basic Type 1/Type 2 tables definitions and interface (specification */ -/* only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1TABLES_H__ -#define __T1TABLES_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* type1_tables */ - /* */ - /* <Title> */ - /* Type 1 Tables */ - /* */ - /* <Abstract> */ - /* Type~1 (PostScript) specific font tables. */ - /* */ - /* <Description> */ - /* This section contains the definition of Type 1-specific tables, */ - /* including structures related to other PostScript font formats. */ - /* */ - /* <Order> */ - /* PS_FontInfoRec */ - /* PS_FontInfo */ - /* PS_PrivateRec */ - /* PS_Private */ - /* */ - /* CID_FaceDictRec */ - /* CID_FaceDict */ - /* CID_FaceInfoRec */ - /* CID_FaceInfo */ - /* */ - /* FT_Has_PS_Glyph_Names */ - /* FT_Get_PS_Font_Info */ - /* FT_Get_PS_Font_Private */ - /* FT_Get_PS_Font_Value */ - /* */ - /* T1_Blend_Flags */ - /* T1_EncodingType */ - /* PS_Dict_Keys */ - /* */ - /*************************************************************************/ - - - /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */ - /* structures in order to support Multiple Master fonts. */ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_FontInfoRec */ - /* */ - /* <Description> */ - /* A structure used to model a Type~1 or Type~2 FontInfo dictionary. */ - /* Note that for Multiple Master fonts, each instance has its own */ - /* FontInfo dictionary. */ - /* */ - typedef struct PS_FontInfoRec_ - { - FT_String* version; - FT_String* notice; - FT_String* full_name; - FT_String* family_name; - FT_String* weight; - FT_Long italic_angle; - FT_Bool is_fixed_pitch; - FT_Short underline_position; - FT_UShort underline_thickness; - - } PS_FontInfoRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_FontInfo */ - /* */ - /* <Description> */ - /* A handle to a @PS_FontInfoRec structure. */ - /* */ - typedef struct PS_FontInfoRec_* PS_FontInfo; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* T1_FontInfo */ - /* */ - /* <Description> */ - /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */ - /* kept to maintain source compatibility between various versions of */ - /* FreeType. */ - /* */ - typedef PS_FontInfoRec T1_FontInfo; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_PrivateRec */ - /* */ - /* <Description> */ - /* A structure used to model a Type~1 or Type~2 private dictionary. */ - /* Note that for Multiple Master fonts, each instance has its own */ - /* Private dictionary. */ - /* */ - typedef struct PS_PrivateRec_ - { - FT_Int unique_id; - FT_Int lenIV; - - FT_Byte num_blue_values; - FT_Byte num_other_blues; - FT_Byte num_family_blues; - FT_Byte num_family_other_blues; - - FT_Short blue_values[14]; - FT_Short other_blues[10]; - - FT_Short family_blues [14]; - FT_Short family_other_blues[10]; - - FT_Fixed blue_scale; - FT_Int blue_shift; - FT_Int blue_fuzz; - - FT_UShort standard_width[1]; - FT_UShort standard_height[1]; - - FT_Byte num_snap_widths; - FT_Byte num_snap_heights; - FT_Bool force_bold; - FT_Bool round_stem_up; - - FT_Short snap_widths [13]; /* including std width */ - FT_Short snap_heights[13]; /* including std height */ - - FT_Fixed expansion_factor; - - FT_Long language_group; - FT_Long password; - - FT_Short min_feature[2]; - - } PS_PrivateRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* PS_Private */ - /* */ - /* <Description> */ - /* A handle to a @PS_PrivateRec structure. */ - /* */ - typedef struct PS_PrivateRec_* PS_Private; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* T1_Private */ - /* */ - /* <Description> */ - /* This type is equivalent to @PS_PrivateRec. It is deprecated but */ - /* kept to maintain source compatibility between various versions of */ - /* FreeType. */ - /* */ - typedef PS_PrivateRec T1_Private; - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* T1_Blend_Flags */ - /* */ - /* <Description> */ - /* A set of flags used to indicate which fields are present in a */ - /* given blend dictionary (font info or private). Used to support */ - /* Multiple Masters fonts. */ - /* */ - /* <Values> */ - /* T1_BLEND_UNDERLINE_POSITION :: */ - /* T1_BLEND_UNDERLINE_THICKNESS :: */ - /* T1_BLEND_ITALIC_ANGLE :: */ - /* T1_BLEND_BLUE_VALUES :: */ - /* T1_BLEND_OTHER_BLUES :: */ - /* T1_BLEND_STANDARD_WIDTH :: */ - /* T1_BLEND_STANDARD_HEIGHT :: */ - /* T1_BLEND_STEM_SNAP_WIDTHS :: */ - /* T1_BLEND_STEM_SNAP_HEIGHTS :: */ - /* T1_BLEND_BLUE_SCALE :: */ - /* T1_BLEND_BLUE_SHIFT :: */ - /* T1_BLEND_FAMILY_BLUES :: */ - /* T1_BLEND_FAMILY_OTHER_BLUES :: */ - /* T1_BLEND_FORCE_BOLD :: */ - /* */ - typedef enum T1_Blend_Flags_ - { - /* required fields in a FontInfo blend dictionary */ - T1_BLEND_UNDERLINE_POSITION = 0, - T1_BLEND_UNDERLINE_THICKNESS, - T1_BLEND_ITALIC_ANGLE, - - /* required fields in a Private blend dictionary */ - T1_BLEND_BLUE_VALUES, - T1_BLEND_OTHER_BLUES, - T1_BLEND_STANDARD_WIDTH, - T1_BLEND_STANDARD_HEIGHT, - T1_BLEND_STEM_SNAP_WIDTHS, - T1_BLEND_STEM_SNAP_HEIGHTS, - T1_BLEND_BLUE_SCALE, - T1_BLEND_BLUE_SHIFT, - T1_BLEND_FAMILY_BLUES, - T1_BLEND_FAMILY_OTHER_BLUES, - T1_BLEND_FORCE_BOLD, - - T1_BLEND_MAX /* do not remove */ - - } T1_Blend_Flags; - - - /* these constants are deprecated; use the corresponding */ - /* `T1_Blend_Flags' values instead */ -#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION -#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS -#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE -#define t1_blend_blue_values T1_BLEND_BLUE_VALUES -#define t1_blend_other_blues T1_BLEND_OTHER_BLUES -#define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH -#define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT -#define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS -#define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS -#define t1_blend_blue_scale T1_BLEND_BLUE_SCALE -#define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT -#define t1_blend_family_blues T1_BLEND_FAMILY_BLUES -#define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES -#define t1_blend_force_bold T1_BLEND_FORCE_BOLD -#define t1_blend_max T1_BLEND_MAX - - /* */ - - - /* maximum number of Multiple Masters designs, as defined in the spec */ -#define T1_MAX_MM_DESIGNS 16 - - /* maximum number of Multiple Masters axes, as defined in the spec */ -#define T1_MAX_MM_AXIS 4 - - /* maximum number of elements in a design map */ -#define T1_MAX_MM_MAP_POINTS 20 - - - /* this structure is used to store the BlendDesignMap entry for an axis */ - typedef struct PS_DesignMap_ - { - FT_Byte num_points; - FT_Long* design_points; - FT_Fixed* blend_points; - - } PS_DesignMapRec, *PS_DesignMap; - - /* backwards-compatible definition */ - typedef PS_DesignMapRec T1_DesignMap; - - - typedef struct PS_BlendRec_ - { - FT_UInt num_designs; - FT_UInt num_axis; - - FT_String* axis_names[T1_MAX_MM_AXIS]; - FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; - PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; - - FT_Fixed* weight_vector; - FT_Fixed* default_weight_vector; - - PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; - PS_Private privates [T1_MAX_MM_DESIGNS + 1]; - - FT_ULong blend_bitflags; - - FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; - - /* since 2.3.0 */ - - /* undocumented, optional: the default design instance; */ - /* corresponds to default_weight_vector -- */ - /* num_default_design_vector == 0 means it is not present */ - /* in the font and associated metrics files */ - FT_UInt default_design_vector[T1_MAX_MM_DESIGNS]; - FT_UInt num_default_design_vector; - - } PS_BlendRec, *PS_Blend; - - - /* backwards-compatible definition */ - typedef PS_BlendRec T1_Blend; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_FaceDictRec */ - /* */ - /* <Description> */ - /* A structure used to represent data in a CID top-level dictionary. */ - /* */ - typedef struct CID_FaceDictRec_ - { - PS_PrivateRec private_dict; - - FT_UInt len_buildchar; - FT_Fixed forcebold_threshold; - FT_Pos stroke_width; - FT_Fixed expansion_factor; - - FT_Byte paint_type; - FT_Byte font_type; - FT_Matrix font_matrix; - FT_Vector font_offset; - - FT_UInt num_subrs; - FT_ULong subrmap_offset; - FT_Int sd_bytes; - - } CID_FaceDictRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_FaceDict */ - /* */ - /* <Description> */ - /* A handle to a @CID_FaceDictRec structure. */ - /* */ - typedef struct CID_FaceDictRec_* CID_FaceDict; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_FontDict */ - /* */ - /* <Description> */ - /* This type is equivalent to @CID_FaceDictRec. It is deprecated but */ - /* kept to maintain source compatibility between various versions of */ - /* FreeType. */ - /* */ - typedef CID_FaceDictRec CID_FontDict; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_FaceInfoRec */ - /* */ - /* <Description> */ - /* A structure used to represent CID Face information. */ - /* */ - typedef struct CID_FaceInfoRec_ - { - FT_String* cid_font_name; - FT_Fixed cid_version; - FT_Int cid_font_type; - - FT_String* registry; - FT_String* ordering; - FT_Int supplement; - - PS_FontInfoRec font_info; - FT_BBox font_bbox; - FT_ULong uid_base; - - FT_Int num_xuid; - FT_ULong xuid[16]; - - FT_ULong cidmap_offset; - FT_Int fd_bytes; - FT_Int gd_bytes; - FT_ULong cid_count; - - FT_Int num_dicts; - CID_FaceDict font_dicts; - - FT_ULong data_offset; - - } CID_FaceInfoRec; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_FaceInfo */ - /* */ - /* <Description> */ - /* A handle to a @CID_FaceInfoRec structure. */ - /* */ - typedef struct CID_FaceInfoRec_* CID_FaceInfo; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_Info */ - /* */ - /* <Description> */ - /* This type is equivalent to @CID_FaceInfoRec. It is deprecated but */ - /* kept to maintain source compatibility between various versions of */ - /* FreeType. */ - /* */ - typedef CID_FaceInfoRec CID_Info; - - - /************************************************************************ - * - * @function: - * FT_Has_PS_Glyph_Names - * - * @description: - * Return true if a given face provides reliable PostScript glyph - * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro, - * except that certain fonts (mostly TrueType) contain incorrect - * glyph name tables. - * - * When this function returns true, the caller is sure that the glyph - * names returned by @FT_Get_Glyph_Name are reliable. - * - * @input: - * face :: - * face handle - * - * @return: - * Boolean. True if glyph names are reliable. - * - */ - FT_EXPORT( FT_Int ) - FT_Has_PS_Glyph_Names( FT_Face face ); - - - /************************************************************************ - * - * @function: - * FT_Get_PS_Font_Info - * - * @description: - * Retrieve the @PS_FontInfoRec structure corresponding to a given - * PostScript font. - * - * @input: - * face :: - * PostScript face handle. - * - * @output: - * afont_info :: - * Output font info structure pointer. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * String pointers within the @PS_FontInfoRec structure are owned by - * the face and don't need to be freed by the caller. Missing entries - * in the font's FontInfo dictionary are represented by NULL pointers. - * - * If the font's format is not PostScript-based, this function will - * return the `FT_Err_Invalid_Argument' error code. - * - */ - FT_EXPORT( FT_Error ) - FT_Get_PS_Font_Info( FT_Face face, - PS_FontInfo afont_info ); - - - /************************************************************************ - * - * @function: - * FT_Get_PS_Font_Private - * - * @description: - * Retrieve the @PS_PrivateRec structure corresponding to a given - * PostScript font. - * - * @input: - * face :: - * PostScript face handle. - * - * @output: - * afont_private :: - * Output private dictionary structure pointer. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * The string pointers within the @PS_PrivateRec structure are owned by - * the face and don't need to be freed by the caller. - * - * If the font's format is not PostScript-based, this function returns - * the `FT_Err_Invalid_Argument' error code. - * - */ - FT_EXPORT( FT_Error ) - FT_Get_PS_Font_Private( FT_Face face, - PS_Private afont_private ); - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* T1_EncodingType */ - /* */ - /* <Description> */ - /* An enumeration describing the `Encoding' entry in a Type 1 */ - /* dictionary. */ - /* */ - /* <Values> */ - /* T1_ENCODING_TYPE_NONE :: */ - /* T1_ENCODING_TYPE_ARRAY :: */ - /* T1_ENCODING_TYPE_STANDARD :: */ - /* T1_ENCODING_TYPE_ISOLATIN1 :: */ - /* T1_ENCODING_TYPE_EXPERT :: */ - /* */ - typedef enum T1_EncodingType_ - { - T1_ENCODING_TYPE_NONE = 0, - T1_ENCODING_TYPE_ARRAY, - T1_ENCODING_TYPE_STANDARD, - T1_ENCODING_TYPE_ISOLATIN1, - T1_ENCODING_TYPE_EXPERT - - } T1_EncodingType; - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* PS_Dict_Keys */ - /* */ - /* <Description> */ - /* An enumeration used in calls to @FT_Get_PS_Font_Value to identify */ - /* the Type~1 dictionary entry to retrieve. */ - /* */ - /* <Values> */ - /* PS_DICT_FONT_TYPE :: */ - /* PS_DICT_FONT_MATRIX :: */ - /* PS_DICT_FONT_BBOX :: */ - /* PS_DICT_PAINT_TYPE :: */ - /* PS_DICT_FONT_NAME :: */ - /* PS_DICT_UNIQUE_ID :: */ - /* PS_DICT_NUM_CHAR_STRINGS :: */ - /* PS_DICT_CHAR_STRING_KEY :: */ - /* PS_DICT_CHAR_STRING :: */ - /* PS_DICT_ENCODING_TYPE :: */ - /* PS_DICT_ENCODING_ENTRY :: */ - /* PS_DICT_NUM_SUBRS :: */ - /* PS_DICT_SUBR :: */ - /* PS_DICT_STD_HW :: */ - /* PS_DICT_STD_VW :: */ - /* PS_DICT_NUM_BLUE_VALUES :: */ - /* PS_DICT_BLUE_VALUE :: */ - /* PS_DICT_BLUE_FUZZ :: */ - /* PS_DICT_NUM_OTHER_BLUES :: */ - /* PS_DICT_OTHER_BLUE :: */ - /* PS_DICT_NUM_FAMILY_BLUES :: */ - /* PS_DICT_FAMILY_BLUE :: */ - /* PS_DICT_NUM_FAMILY_OTHER_BLUES :: */ - /* PS_DICT_FAMILY_OTHER_BLUE :: */ - /* PS_DICT_BLUE_SCALE :: */ - /* PS_DICT_BLUE_SHIFT :: */ - /* PS_DICT_NUM_STEM_SNAP_H :: */ - /* PS_DICT_STEM_SNAP_H :: */ - /* PS_DICT_NUM_STEM_SNAP_V :: */ - /* PS_DICT_STEM_SNAP_V :: */ - /* PS_DICT_FORCE_BOLD :: */ - /* PS_DICT_RND_STEM_UP :: */ - /* PS_DICT_MIN_FEATURE :: */ - /* PS_DICT_LEN_IV :: */ - /* PS_DICT_PASSWORD :: */ - /* PS_DICT_LANGUAGE_GROUP :: */ - /* PS_DICT_VERSION :: */ - /* PS_DICT_NOTICE :: */ - /* PS_DICT_FULL_NAME :: */ - /* PS_DICT_FAMILY_NAME :: */ - /* PS_DICT_WEIGHT :: */ - /* PS_DICT_IS_FIXED_PITCH :: */ - /* PS_DICT_UNDERLINE_POSITION :: */ - /* PS_DICT_UNDERLINE_THICKNESS :: */ - /* PS_DICT_FS_TYPE :: */ - /* PS_DICT_ITALIC_ANGLE :: */ - /* */ - typedef enum PS_Dict_Keys_ - { - /* conventionally in the font dictionary */ - PS_DICT_FONT_TYPE, /* FT_Byte */ - PS_DICT_FONT_MATRIX, /* FT_Fixed */ - PS_DICT_FONT_BBOX, /* FT_Fixed */ - PS_DICT_PAINT_TYPE, /* FT_Byte */ - PS_DICT_FONT_NAME, /* FT_String* */ - PS_DICT_UNIQUE_ID, /* FT_Int */ - PS_DICT_NUM_CHAR_STRINGS, /* FT_Int */ - PS_DICT_CHAR_STRING_KEY, /* FT_String* */ - PS_DICT_CHAR_STRING, /* FT_String* */ - PS_DICT_ENCODING_TYPE, /* T1_EncodingType */ - PS_DICT_ENCODING_ENTRY, /* FT_String* */ - - /* conventionally in the font Private dictionary */ - PS_DICT_NUM_SUBRS, /* FT_Int */ - PS_DICT_SUBR, /* FT_String* */ - PS_DICT_STD_HW, /* FT_UShort */ - PS_DICT_STD_VW, /* FT_UShort */ - PS_DICT_NUM_BLUE_VALUES, /* FT_Byte */ - PS_DICT_BLUE_VALUE, /* FT_Short */ - PS_DICT_BLUE_FUZZ, /* FT_Int */ - PS_DICT_NUM_OTHER_BLUES, /* FT_Byte */ - PS_DICT_OTHER_BLUE, /* FT_Short */ - PS_DICT_NUM_FAMILY_BLUES, /* FT_Byte */ - PS_DICT_FAMILY_BLUE, /* FT_Short */ - PS_DICT_NUM_FAMILY_OTHER_BLUES, /* FT_Byte */ - PS_DICT_FAMILY_OTHER_BLUE, /* FT_Short */ - PS_DICT_BLUE_SCALE, /* FT_Fixed */ - PS_DICT_BLUE_SHIFT, /* FT_Int */ - PS_DICT_NUM_STEM_SNAP_H, /* FT_Byte */ - PS_DICT_STEM_SNAP_H, /* FT_Short */ - PS_DICT_NUM_STEM_SNAP_V, /* FT_Byte */ - PS_DICT_STEM_SNAP_V, /* FT_Short */ - PS_DICT_FORCE_BOLD, /* FT_Bool */ - PS_DICT_RND_STEM_UP, /* FT_Bool */ - PS_DICT_MIN_FEATURE, /* FT_Short */ - PS_DICT_LEN_IV, /* FT_Int */ - PS_DICT_PASSWORD, /* FT_Long */ - PS_DICT_LANGUAGE_GROUP, /* FT_Long */ - - /* conventionally in the font FontInfo dictionary */ - PS_DICT_VERSION, /* FT_String* */ - PS_DICT_NOTICE, /* FT_String* */ - PS_DICT_FULL_NAME, /* FT_String* */ - PS_DICT_FAMILY_NAME, /* FT_String* */ - PS_DICT_WEIGHT, /* FT_String* */ - PS_DICT_IS_FIXED_PITCH, /* FT_Bool */ - PS_DICT_UNDERLINE_POSITION, /* FT_Short */ - PS_DICT_UNDERLINE_THICKNESS, /* FT_UShort */ - PS_DICT_FS_TYPE, /* FT_UShort */ - PS_DICT_ITALIC_ANGLE, /* FT_Long */ - - PS_DICT_MAX = PS_DICT_ITALIC_ANGLE - - } PS_Dict_Keys; - - - /************************************************************************ - * - * @function: - * FT_Get_PS_Font_Value - * - * @description: - * Retrieve the value for the supplied key from a PostScript font. - * - * @input: - * face :: - * PostScript face handle. - * - * key :: - * An enumeration value representing the dictionary key to retrieve. - * - * idx :: - * For array values, this specifies the index to be returned. - * - * value :: - * A pointer to memory into which to write the value. - * - * valen_len :: - * The size, in bytes, of the memory supplied for the value. - * - * @output: - * value :: - * The value matching the above key, if it exists. - * - * @return: - * The amount of memory (in bytes) required to hold the requested - * value (if it exists, -1 otherwise). - * - * @note: - * The values returned are not pointers into the internal structures of - * the face, but are `fresh' copies, so that the memory containing them - * belongs to the calling application. This also enforces the - * `read-only' nature of these values, i.e., this function cannot be - * used to manipulate the face. - * - * `value' is a void pointer because the values returned can be of - * various types. - * - * If either `value' is NULL or `value_len' is too small, just the - * required memory size for the requested entry is returned. - * - * The `idx' parameter is used, not only to retrieve elements of, for - * example, the FontMatrix or FontBBox, but also to retrieve name keys - * from the CharStrings dictionary, and the charstrings themselves. It - * is ignored for atomic values. - * - * PS_DICT_BLUE_SCALE returns a value that is scaled up by 1000. To - * get the value as in the font stream, you need to divide by - * 65536000.0 (to remove the FT_Fixed scale, and the x1000 scale). - * - * IMPORTANT: Only key/value pairs read by the FreeType interpreter can - * be retrieved. So, for example, PostScript procedures such as NP, - * ND, and RD are not available. Arbitrary keys are, obviously, not be - * available either. - * - * If the font's format is not PostScript-based, this function returns - * the `FT_Err_Invalid_Argument' error code. - * - */ - FT_EXPORT( FT_Long ) - FT_Get_PS_Font_Value( FT_Face face, - PS_Dict_Keys key, - FT_UInt idx, - void *value, - FT_Long value_len ); - - /* */ - -FT_END_HEADER - -#endif /* __T1TABLES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ttnameid.h b/third_party/freetype/include/freetype/ttnameid.h deleted file mode 100644 index c9585f2413788c590587a5f3ced22af44c2c4d62..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ttnameid.h +++ /dev/null @@ -1,1237 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttnameid.h */ -/* */ -/* TrueType name ID definitions (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTNAMEID_H__ -#define __TTNAMEID_H__ - - -#include <ft2build.h> - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Section> */ - /* truetype_tables */ - /* */ - - - /*************************************************************************/ - /* */ - /* Possible values for the `platform' identifier code in the name */ - /* records of the TTF `name' table. */ - /* */ - /*************************************************************************/ - - - /*********************************************************************** - * - * @enum: - * TT_PLATFORM_XXX - * - * @description: - * A list of valid values for the `platform_id' identifier code in - * @FT_CharMapRec and @FT_SfntName structures. - * - * @values: - * TT_PLATFORM_APPLE_UNICODE :: - * Used by Apple to indicate a Unicode character map and/or name entry. - * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note - * that name entries in this format are coded as big-endian UCS-2 - * character codes _only_. - * - * TT_PLATFORM_MACINTOSH :: - * Used by Apple to indicate a MacOS-specific charmap and/or name entry. - * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that - * most TrueType fonts contain an Apple roman charmap to be usable on - * MacOS systems (even if they contain a Microsoft charmap as well). - * - * TT_PLATFORM_ISO :: - * This value was used to specify ISO/IEC 10646 charmaps. It is however - * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding - * `encoding_id' values. - * - * TT_PLATFORM_MICROSOFT :: - * Used by Microsoft to indicate Windows-specific charmaps. See - * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values. - * Note that most fonts contain a Unicode charmap using - * (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS). - * - * TT_PLATFORM_CUSTOM :: - * Used to indicate application-specific charmaps. - * - * TT_PLATFORM_ADOBE :: - * This value isn't part of any font format specification, but is used - * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec - * structure. See @TT_ADOBE_ID_XXX. - */ - -#define TT_PLATFORM_APPLE_UNICODE 0 -#define TT_PLATFORM_MACINTOSH 1 -#define TT_PLATFORM_ISO 2 /* deprecated */ -#define TT_PLATFORM_MICROSOFT 3 -#define TT_PLATFORM_CUSTOM 4 -#define TT_PLATFORM_ADOBE 7 /* artificial */ - - - /*********************************************************************** - * - * @enum: - * TT_APPLE_ID_XXX - * - * @description: - * A list of valid values for the `encoding_id' for - * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries. - * - * @values: - * TT_APPLE_ID_DEFAULT :: - * Unicode version 1.0. - * - * TT_APPLE_ID_UNICODE_1_1 :: - * Unicode 1.1; specifies Hangul characters starting at U+34xx. - * - * TT_APPLE_ID_ISO_10646 :: - * Deprecated (identical to preceding). - * - * TT_APPLE_ID_UNICODE_2_0 :: - * Unicode 2.0 and beyond (UTF-16 BMP only). - * - * TT_APPLE_ID_UNICODE_32 :: - * Unicode 3.1 and beyond, using UTF-32. - * - * TT_APPLE_ID_VARIANT_SELECTOR :: - * From Adobe, not Apple. Not a normal cmap. Specifies variations - * on a real cmap. - */ - -#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ -#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ -#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ -#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ -#define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ -#define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ - - - /*********************************************************************** - * - * @enum: - * TT_MAC_ID_XXX - * - * @description: - * A list of valid values for the `encoding_id' for - * @TT_PLATFORM_MACINTOSH charmaps and name entries. - * - * @values: - * TT_MAC_ID_ROMAN :: - * TT_MAC_ID_JAPANESE :: - * TT_MAC_ID_TRADITIONAL_CHINESE :: - * TT_MAC_ID_KOREAN :: - * TT_MAC_ID_ARABIC :: - * TT_MAC_ID_HEBREW :: - * TT_MAC_ID_GREEK :: - * TT_MAC_ID_RUSSIAN :: - * TT_MAC_ID_RSYMBOL :: - * TT_MAC_ID_DEVANAGARI :: - * TT_MAC_ID_GURMUKHI :: - * TT_MAC_ID_GUJARATI :: - * TT_MAC_ID_ORIYA :: - * TT_MAC_ID_BENGALI :: - * TT_MAC_ID_TAMIL :: - * TT_MAC_ID_TELUGU :: - * TT_MAC_ID_KANNADA :: - * TT_MAC_ID_MALAYALAM :: - * TT_MAC_ID_SINHALESE :: - * TT_MAC_ID_BURMESE :: - * TT_MAC_ID_KHMER :: - * TT_MAC_ID_THAI :: - * TT_MAC_ID_LAOTIAN :: - * TT_MAC_ID_GEORGIAN :: - * TT_MAC_ID_ARMENIAN :: - * TT_MAC_ID_MALDIVIAN :: - * TT_MAC_ID_SIMPLIFIED_CHINESE :: - * TT_MAC_ID_TIBETAN :: - * TT_MAC_ID_MONGOLIAN :: - * TT_MAC_ID_GEEZ :: - * TT_MAC_ID_SLAVIC :: - * TT_MAC_ID_VIETNAMESE :: - * TT_MAC_ID_SINDHI :: - * TT_MAC_ID_UNINTERP :: - */ - -#define TT_MAC_ID_ROMAN 0 -#define TT_MAC_ID_JAPANESE 1 -#define TT_MAC_ID_TRADITIONAL_CHINESE 2 -#define TT_MAC_ID_KOREAN 3 -#define TT_MAC_ID_ARABIC 4 -#define TT_MAC_ID_HEBREW 5 -#define TT_MAC_ID_GREEK 6 -#define TT_MAC_ID_RUSSIAN 7 -#define TT_MAC_ID_RSYMBOL 8 -#define TT_MAC_ID_DEVANAGARI 9 -#define TT_MAC_ID_GURMUKHI 10 -#define TT_MAC_ID_GUJARATI 11 -#define TT_MAC_ID_ORIYA 12 -#define TT_MAC_ID_BENGALI 13 -#define TT_MAC_ID_TAMIL 14 -#define TT_MAC_ID_TELUGU 15 -#define TT_MAC_ID_KANNADA 16 -#define TT_MAC_ID_MALAYALAM 17 -#define TT_MAC_ID_SINHALESE 18 -#define TT_MAC_ID_BURMESE 19 -#define TT_MAC_ID_KHMER 20 -#define TT_MAC_ID_THAI 21 -#define TT_MAC_ID_LAOTIAN 22 -#define TT_MAC_ID_GEORGIAN 23 -#define TT_MAC_ID_ARMENIAN 24 -#define TT_MAC_ID_MALDIVIAN 25 -#define TT_MAC_ID_SIMPLIFIED_CHINESE 25 -#define TT_MAC_ID_TIBETAN 26 -#define TT_MAC_ID_MONGOLIAN 27 -#define TT_MAC_ID_GEEZ 28 -#define TT_MAC_ID_SLAVIC 29 -#define TT_MAC_ID_VIETNAMESE 30 -#define TT_MAC_ID_SINDHI 31 -#define TT_MAC_ID_UNINTERP 32 - - - /*********************************************************************** - * - * @enum: - * TT_ISO_ID_XXX - * - * @description: - * A list of valid values for the `encoding_id' for - * @TT_PLATFORM_ISO charmaps and name entries. - * - * Their use is now deprecated. - * - * @values: - * TT_ISO_ID_7BIT_ASCII :: - * ASCII. - * TT_ISO_ID_10646 :: - * ISO/10646. - * TT_ISO_ID_8859_1 :: - * Also known as Latin-1. - */ - -#define TT_ISO_ID_7BIT_ASCII 0 -#define TT_ISO_ID_10646 1 -#define TT_ISO_ID_8859_1 2 - - - /*********************************************************************** - * - * @enum: - * TT_MS_ID_XXX - * - * @description: - * A list of valid values for the `encoding_id' for - * @TT_PLATFORM_MICROSOFT charmaps and name entries. - * - * @values: - * TT_MS_ID_SYMBOL_CS :: - * Corresponds to Microsoft symbol encoding. See - * @FT_ENCODING_MS_SYMBOL. - * - * TT_MS_ID_UNICODE_CS :: - * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See - * @FT_ENCODING_UNICODE. - * - * TT_MS_ID_SJIS :: - * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS. - * - * TT_MS_ID_GB2312 :: - * Corresponds to Simplified Chinese as used in Mainland China. See - * @FT_ENCODING_GB2312. - * - * TT_MS_ID_BIG_5 :: - * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. - * See @FT_ENCODING_BIG5. - * - * TT_MS_ID_WANSUNG :: - * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG. - * - * TT_MS_ID_JOHAB :: - * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB. - * - * TT_MS_ID_UCS_4 :: - * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to - * the OpenType specification version 1.4 (mid-2001.) - */ - -#define TT_MS_ID_SYMBOL_CS 0 -#define TT_MS_ID_UNICODE_CS 1 -#define TT_MS_ID_SJIS 2 -#define TT_MS_ID_GB2312 3 -#define TT_MS_ID_BIG_5 4 -#define TT_MS_ID_WANSUNG 5 -#define TT_MS_ID_JOHAB 6 -#define TT_MS_ID_UCS_4 10 - - - /*********************************************************************** - * - * @enum: - * TT_ADOBE_ID_XXX - * - * @description: - * A list of valid values for the `encoding_id' for - * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! - * - * @values: - * TT_ADOBE_ID_STANDARD :: - * Adobe standard encoding. - * TT_ADOBE_ID_EXPERT :: - * Adobe expert encoding. - * TT_ADOBE_ID_CUSTOM :: - * Adobe custom encoding. - * TT_ADOBE_ID_LATIN_1 :: - * Adobe Latin~1 encoding. - */ - -#define TT_ADOBE_ID_STANDARD 0 -#define TT_ADOBE_ID_EXPERT 1 -#define TT_ADOBE_ID_CUSTOM 2 -#define TT_ADOBE_ID_LATIN_1 3 - - - /*************************************************************************/ - /* */ - /* Possible values of the language identifier field in the name records */ - /* of the TTF `name' table if the `platform' identifier code is */ - /* TT_PLATFORM_MACINTOSH. These values are also used as return values */ - /* for function @FT_Get_CMap_Language_ID. */ - /* */ - /* The canonical source for the Apple assigned Language ID's is at */ - /* */ - /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html */ - /* */ -#define TT_MAC_LANGID_ENGLISH 0 -#define TT_MAC_LANGID_FRENCH 1 -#define TT_MAC_LANGID_GERMAN 2 -#define TT_MAC_LANGID_ITALIAN 3 -#define TT_MAC_LANGID_DUTCH 4 -#define TT_MAC_LANGID_SWEDISH 5 -#define TT_MAC_LANGID_SPANISH 6 -#define TT_MAC_LANGID_DANISH 7 -#define TT_MAC_LANGID_PORTUGUESE 8 -#define TT_MAC_LANGID_NORWEGIAN 9 -#define TT_MAC_LANGID_HEBREW 10 -#define TT_MAC_LANGID_JAPANESE 11 -#define TT_MAC_LANGID_ARABIC 12 -#define TT_MAC_LANGID_FINNISH 13 -#define TT_MAC_LANGID_GREEK 14 -#define TT_MAC_LANGID_ICELANDIC 15 -#define TT_MAC_LANGID_MALTESE 16 -#define TT_MAC_LANGID_TURKISH 17 -#define TT_MAC_LANGID_CROATIAN 18 -#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 -#define TT_MAC_LANGID_URDU 20 -#define TT_MAC_LANGID_HINDI 21 -#define TT_MAC_LANGID_THAI 22 -#define TT_MAC_LANGID_KOREAN 23 -#define TT_MAC_LANGID_LITHUANIAN 24 -#define TT_MAC_LANGID_POLISH 25 -#define TT_MAC_LANGID_HUNGARIAN 26 -#define TT_MAC_LANGID_ESTONIAN 27 -#define TT_MAC_LANGID_LETTISH 28 -#define TT_MAC_LANGID_SAAMISK 29 -#define TT_MAC_LANGID_FAEROESE 30 -#define TT_MAC_LANGID_FARSI 31 -#define TT_MAC_LANGID_RUSSIAN 32 -#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 -#define TT_MAC_LANGID_FLEMISH 34 -#define TT_MAC_LANGID_IRISH 35 -#define TT_MAC_LANGID_ALBANIAN 36 -#define TT_MAC_LANGID_ROMANIAN 37 -#define TT_MAC_LANGID_CZECH 38 -#define TT_MAC_LANGID_SLOVAK 39 -#define TT_MAC_LANGID_SLOVENIAN 40 -#define TT_MAC_LANGID_YIDDISH 41 -#define TT_MAC_LANGID_SERBIAN 42 -#define TT_MAC_LANGID_MACEDONIAN 43 -#define TT_MAC_LANGID_BULGARIAN 44 -#define TT_MAC_LANGID_UKRAINIAN 45 -#define TT_MAC_LANGID_BYELORUSSIAN 46 -#define TT_MAC_LANGID_UZBEK 47 -#define TT_MAC_LANGID_KAZAKH 48 -#define TT_MAC_LANGID_AZERBAIJANI 49 -#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 -#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 -#define TT_MAC_LANGID_ARMENIAN 51 -#define TT_MAC_LANGID_GEORGIAN 52 -#define TT_MAC_LANGID_MOLDAVIAN 53 -#define TT_MAC_LANGID_KIRGHIZ 54 -#define TT_MAC_LANGID_TAJIKI 55 -#define TT_MAC_LANGID_TURKMEN 56 -#define TT_MAC_LANGID_MONGOLIAN 57 -#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 -#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 -#define TT_MAC_LANGID_PASHTO 59 -#define TT_MAC_LANGID_KURDISH 60 -#define TT_MAC_LANGID_KASHMIRI 61 -#define TT_MAC_LANGID_SINDHI 62 -#define TT_MAC_LANGID_TIBETAN 63 -#define TT_MAC_LANGID_NEPALI 64 -#define TT_MAC_LANGID_SANSKRIT 65 -#define TT_MAC_LANGID_MARATHI 66 -#define TT_MAC_LANGID_BENGALI 67 -#define TT_MAC_LANGID_ASSAMESE 68 -#define TT_MAC_LANGID_GUJARATI 69 -#define TT_MAC_LANGID_PUNJABI 70 -#define TT_MAC_LANGID_ORIYA 71 -#define TT_MAC_LANGID_MALAYALAM 72 -#define TT_MAC_LANGID_KANNADA 73 -#define TT_MAC_LANGID_TAMIL 74 -#define TT_MAC_LANGID_TELUGU 75 -#define TT_MAC_LANGID_SINHALESE 76 -#define TT_MAC_LANGID_BURMESE 77 -#define TT_MAC_LANGID_KHMER 78 -#define TT_MAC_LANGID_LAO 79 -#define TT_MAC_LANGID_VIETNAMESE 80 -#define TT_MAC_LANGID_INDONESIAN 81 -#define TT_MAC_LANGID_TAGALOG 82 -#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 -#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 -#define TT_MAC_LANGID_AMHARIC 85 -#define TT_MAC_LANGID_TIGRINYA 86 -#define TT_MAC_LANGID_GALLA 87 -#define TT_MAC_LANGID_SOMALI 88 -#define TT_MAC_LANGID_SWAHILI 89 -#define TT_MAC_LANGID_RUANDA 90 -#define TT_MAC_LANGID_RUNDI 91 -#define TT_MAC_LANGID_CHEWA 92 -#define TT_MAC_LANGID_MALAGASY 93 -#define TT_MAC_LANGID_ESPERANTO 94 -#define TT_MAC_LANGID_WELSH 128 -#define TT_MAC_LANGID_BASQUE 129 -#define TT_MAC_LANGID_CATALAN 130 -#define TT_MAC_LANGID_LATIN 131 -#define TT_MAC_LANGID_QUECHUA 132 -#define TT_MAC_LANGID_GUARANI 133 -#define TT_MAC_LANGID_AYMARA 134 -#define TT_MAC_LANGID_TATAR 135 -#define TT_MAC_LANGID_UIGHUR 136 -#define TT_MAC_LANGID_DZONGKHA 137 -#define TT_MAC_LANGID_JAVANESE 138 -#define TT_MAC_LANGID_SUNDANESE 139 - - -#if 0 /* these seem to be errors that have been dropped */ - -#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 -#define TT_MAC_LANGID_IRISH_GAELIC 141 - -#endif - - - /* The following codes are new as of 2000-03-10 */ -#define TT_MAC_LANGID_GALICIAN 140 -#define TT_MAC_LANGID_AFRIKAANS 141 -#define TT_MAC_LANGID_BRETON 142 -#define TT_MAC_LANGID_INUKTITUT 143 -#define TT_MAC_LANGID_SCOTTISH_GAELIC 144 -#define TT_MAC_LANGID_MANX_GAELIC 145 -#define TT_MAC_LANGID_IRISH_GAELIC 146 -#define TT_MAC_LANGID_TONGAN 147 -#define TT_MAC_LANGID_GREEK_POLYTONIC 148 -#define TT_MAC_LANGID_GREELANDIC 149 -#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 - - - /*************************************************************************/ - /* */ - /* Possible values of the language identifier field in the name records */ - /* of the TTF `name' table if the `platform' identifier code is */ - /* TT_PLATFORM_MICROSOFT. */ - /* */ - /* The canonical source for the MS assigned LCIDs is */ - /* */ - /* http://www.microsoft.com/globaldev/reference/lcid-all.mspx */ - /* */ - -#define TT_MS_LANGID_ARABIC_GENERAL 0x0001 -#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 -#define TT_MS_LANGID_ARABIC_IRAQ 0x0801 -#define TT_MS_LANGID_ARABIC_EGYPT 0x0C01 -#define TT_MS_LANGID_ARABIC_LIBYA 0x1001 -#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 -#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 -#define TT_MS_LANGID_ARABIC_TUNISIA 0x1C01 -#define TT_MS_LANGID_ARABIC_OMAN 0x2001 -#define TT_MS_LANGID_ARABIC_YEMEN 0x2401 -#define TT_MS_LANGID_ARABIC_SYRIA 0x2801 -#define TT_MS_LANGID_ARABIC_JORDAN 0x2C01 -#define TT_MS_LANGID_ARABIC_LEBANON 0x3001 -#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 -#define TT_MS_LANGID_ARABIC_UAE 0x3801 -#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3C01 -#define TT_MS_LANGID_ARABIC_QATAR 0x4001 -#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 -#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 -#define TT_MS_LANGID_CHINESE_GENERAL 0x0004 -#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 -#define TT_MS_LANGID_CHINESE_PRC 0x0804 -#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0C04 -#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 - -#if 1 /* this looks like the correct value */ -#define TT_MS_LANGID_CHINESE_MACAU 0x1404 -#else /* but beware, Microsoft may change its mind... - the most recent Word reference has the following: */ -#define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG -#endif - -#if 0 /* used only with .NET `cultures'; commented out */ -#define TT_MS_LANGID_CHINESE_TRADITIONAL 0x7C04 -#endif - -#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 -#define TT_MS_LANGID_DANISH_DENMARK 0x0406 -#define TT_MS_LANGID_GERMAN_GERMANY 0x0407 -#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 -#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0C07 -#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 -#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 -#define TT_MS_LANGID_GREEK_GREECE 0x0408 - - /* don't ask what this one means... It is commented out currently. */ -#if 0 -#define TT_MS_LANGID_GREEK_GREECE2 0x2008 -#endif - -#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009 -#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 -#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 -#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0C09 -#define TT_MS_LANGID_ENGLISH_CANADA 0x1009 -#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 -#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 -#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1C09 -#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 -#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 -#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 -#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2C09 -#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 -#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 -#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809 -#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3C09 -#define TT_MS_LANGID_ENGLISH_INDIA 0x4009 -#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 -#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 -#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040A -#define TT_MS_LANGID_SPANISH_MEXICO 0x080A -#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0C0A -#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100A -#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140A -#define TT_MS_LANGID_SPANISH_PANAMA 0x180A -#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1C0A -#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200A -#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240A -#define TT_MS_LANGID_SPANISH_PERU 0x280A -#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2C0A -#define TT_MS_LANGID_SPANISH_ECUADOR 0x300A -#define TT_MS_LANGID_SPANISH_CHILE 0x340A -#define TT_MS_LANGID_SPANISH_URUGUAY 0x380A -#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3C0A -#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400A -#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440A -#define TT_MS_LANGID_SPANISH_HONDURAS 0x480A -#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4C0A -#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500A -#define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540A - /* The following ID blatantly violate MS specs by using a */ - /* sublanguage > 0x1F. */ -#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40AU -#define TT_MS_LANGID_FINNISH_FINLAND 0x040B -#define TT_MS_LANGID_FRENCH_FRANCE 0x040C -#define TT_MS_LANGID_FRENCH_BELGIUM 0x080C -#define TT_MS_LANGID_FRENCH_CANADA 0x0C0C -#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100C -#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140C -#define TT_MS_LANGID_FRENCH_MONACO 0x180C -#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1C0C -#define TT_MS_LANGID_FRENCH_REUNION 0x200C -#define TT_MS_LANGID_FRENCH_CONGO 0x240C - /* which was formerly: */ -#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO -#define TT_MS_LANGID_FRENCH_SENEGAL 0x280C -#define TT_MS_LANGID_FRENCH_CAMEROON 0x2C0C -#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300C -#define TT_MS_LANGID_FRENCH_MALI 0x340C -#define TT_MS_LANGID_FRENCH_MOROCCO 0x380C -#define TT_MS_LANGID_FRENCH_HAITI 0x3C0C - /* and another violation of the spec (see 0xE40AU) */ -#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40CU -#define TT_MS_LANGID_HEBREW_ISRAEL 0x040D -#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040E -#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040F -#define TT_MS_LANGID_ITALIAN_ITALY 0x0410 -#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 -#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 -#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 -#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 -#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 -#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 -#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 -#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 -#define TT_MS_LANGID_POLISH_POLAND 0x0415 -#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 -#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 -#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 -#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 -#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 -#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 -#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 -#define TT_MS_LANGID_CROATIAN_CROATIA 0x041A -#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081A -#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0C1A - -#if 0 /* this used to be this value, but it looks like we were wrong */ -#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101A -#else /* current sources say */ -#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101A -#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141A - /* and XPsp2 Platform SDK added (2004-07-26) */ - /* Names are shortened to be significant within 40 chars. */ -#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181A -#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181A -#endif - -#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041B -#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041C -#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041D -#define TT_MS_LANGID_SWEDISH_FINLAND 0x081D -#define TT_MS_LANGID_THAI_THAILAND 0x041E -#define TT_MS_LANGID_TURKISH_TURKEY 0x041F -#define TT_MS_LANGID_URDU_PAKISTAN 0x0420 -#define TT_MS_LANGID_URDU_INDIA 0x0820 -#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 -#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 -#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 -#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 -#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 -#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 -#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 -#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 -#define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 -#define TT_MS_LANGID_FARSI_IRAN 0x0429 -#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042A -#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042B -#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042C -#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082C -#define TT_MS_LANGID_BASQUE_SPAIN 0x042D -#define TT_MS_LANGID_SORBIAN_GERMANY 0x042E -#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042F -#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 -#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 -#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 -#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 -#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 -#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 -#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 -#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 -#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 -#define TT_MS_LANGID_HINDI_INDIA 0x0439 -#define TT_MS_LANGID_MALTESE_MALTA 0x043A - /* Added by XPsp2 Platform SDK (2004-07-26) */ -#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043B -#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083B -#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3B -#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103B -#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143B -#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183B -#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3B -#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203B -#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243B - /* ... and we also keep our old identifier... */ -#define TT_MS_LANGID_SAAMI_LAPONIA 0x043B - -#if 0 /* this seems to be a previous inversion */ -#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C -#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C -#else -#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C -#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C -#endif - -#define TT_MS_LANGID_YIDDISH_GERMANY 0x043D -#define TT_MS_LANGID_MALAY_MALAYSIA 0x043E -#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083E -#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043F -#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440 - /* alias declared in Windows 2000 */ -#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \ - TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN - -#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 -#define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 -#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 -#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 -#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 -#define TT_MS_LANGID_BENGALI_INDIA 0x0445 -#define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 -#define TT_MS_LANGID_PUNJABI_INDIA 0x0446 -#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846 -#define TT_MS_LANGID_GUJARATI_INDIA 0x0447 -#define TT_MS_LANGID_ORIYA_INDIA 0x0448 -#define TT_MS_LANGID_TAMIL_INDIA 0x0449 -#define TT_MS_LANGID_TELUGU_INDIA 0x044A -#define TT_MS_LANGID_KANNADA_INDIA 0x044B -#define TT_MS_LANGID_MALAYALAM_INDIA 0x044C -#define TT_MS_LANGID_ASSAMESE_INDIA 0x044D -#define TT_MS_LANGID_MARATHI_INDIA 0x044E -#define TT_MS_LANGID_SANSKRIT_INDIA 0x044F -#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 -#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850 -#define TT_MS_LANGID_TIBETAN_CHINA 0x0451 - /* Don't use the next constant! It has */ - /* (1) the wrong spelling (Dzonghka) */ - /* (2) Microsoft doesn't officially define it -- */ - /* at least it is not in the List of Local */ - /* ID Values. */ - /* (3) Dzongkha is not the same language as */ - /* Tibetan, so merging it is wrong anyway. */ - /* */ - /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW. */ -#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851 - -#if 0 - /* the following used to be defined */ -#define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451 - /* ... but it was changed; */ -#else - /* So we will continue to #define it, but with the correct value */ -#define TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_DZONGHKA_BHUTAN -#endif - -#define TT_MS_LANGID_WELSH_WALES 0x0452 -#define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 -#define TT_MS_LANGID_LAO_LAOS 0x0454 -#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455 -#define TT_MS_LANGID_GALICIAN_SPAIN 0x0456 -#define TT_MS_LANGID_KONKANI_INDIA 0x0457 -#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458 -#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459 -#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859 - /* Missing a LCID for Sindhi in Devanagari script */ -#define TT_MS_LANGID_SYRIAC_SYRIA 0x045A -#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045B -#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045C -#define TT_MS_LANGID_INUKTITUT_CANADA 0x045D -#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045E -#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045F -#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085F - /* Missing a LCID for Tifinagh script */ -#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460 - /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */ - /* script is yet unclear... might be Arabic, Nagari or Sharada */ -#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860 - /* ... and aliased (by MS) for compatibility reasons. */ -#define TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_KASHMIRI_SASIA -#define TT_MS_LANGID_NEPALI_NEPAL 0x0461 -#define TT_MS_LANGID_NEPALI_INDIA 0x0861 -#define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 -#define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 -#define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 -#define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 - /* alias declared in Windows 2000 */ -#define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES -#define TT_MS_LANGID_EDO_NIGERIA 0x0466 -#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467 -#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 -#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469 -#define TT_MS_LANGID_YORUBA_NIGERIA 0x046A -#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046B -#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086B -#define TT_MS_LANGID_QUECHUA_PERU 0x0C6B -#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046C - /* Also spelled by XPsp2 Platform SDK (2004-07-26) */ -#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \ - TT_MS_LANGID_SEPEDI_SOUTH_AFRICA - /* language codes 0x046D, 0x046E and 0x046F are (still) unknown. */ -#define TT_MS_LANGID_IGBO_NIGERIA 0x0470 -#define TT_MS_LANGID_KANURI_NIGERIA 0x0471 -#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472 -#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473 -#define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873 - /* also spelled in the `Passport SDK' list as: */ -#define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA -#define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474 -#define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475 -#define TT_MS_LANGID_LATIN 0x0476 -#define TT_MS_LANGID_SOMALI_SOMALIA 0x0477 - /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */ - /* not written (but OTOH the peculiar writing system is worth */ - /* studying). */ -#define TT_MS_LANGID_YI_CHINA 0x0478 -#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479 - /* language codes from 0x047A to 0x047F are (still) unknown. */ -#define TT_MS_LANGID_UIGHUR_CHINA 0x0480 -#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 - -#if 0 /* not deemed useful for fonts */ -#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04FF -#endif - - - /*************************************************************************/ - /* */ - /* Possible values of the `name' identifier field in the name records of */ - /* the TTF `name' table. These values are platform independent. */ - /* */ -#define TT_NAME_ID_COPYRIGHT 0 -#define TT_NAME_ID_FONT_FAMILY 1 -#define TT_NAME_ID_FONT_SUBFAMILY 2 -#define TT_NAME_ID_UNIQUE_ID 3 -#define TT_NAME_ID_FULL_NAME 4 -#define TT_NAME_ID_VERSION_STRING 5 -#define TT_NAME_ID_PS_NAME 6 -#define TT_NAME_ID_TRADEMARK 7 - - /* the following values are from the OpenType spec */ -#define TT_NAME_ID_MANUFACTURER 8 -#define TT_NAME_ID_DESIGNER 9 -#define TT_NAME_ID_DESCRIPTION 10 -#define TT_NAME_ID_VENDOR_URL 11 -#define TT_NAME_ID_DESIGNER_URL 12 -#define TT_NAME_ID_LICENSE 13 -#define TT_NAME_ID_LICENSE_URL 14 - /* number 15 is reserved */ -#define TT_NAME_ID_PREFERRED_FAMILY 16 -#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 -#define TT_NAME_ID_MAC_FULL_NAME 18 - - /* The following code is new as of 2000-01-21 */ -#define TT_NAME_ID_SAMPLE_TEXT 19 - - /* This is new in OpenType 1.3 */ -#define TT_NAME_ID_CID_FINDFONT_NAME 20 - - /* This is new in OpenType 1.5 */ -#define TT_NAME_ID_WWS_FAMILY 21 -#define TT_NAME_ID_WWS_SUBFAMILY 22 - - - /*************************************************************************/ - /* */ - /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ - /* */ - /* Updated 08-Nov-2008. */ - /* */ - - /* Bit 0 Basic Latin */ -#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ - /* Bit 1 C1 Controls and Latin-1 Supplement */ -#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ - /* Bit 2 Latin Extended-A */ -#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ - /* Bit 3 Latin Extended-B */ -#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ - /* Bit 4 IPA Extensions */ - /* Phonetic Extensions */ - /* Phonetic Extensions Supplement */ -#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ - /* U+1D00-U+1D7F */ - /* U+1D80-U+1DBF */ - /* Bit 5 Spacing Modifier Letters */ - /* Modifier Tone Letters */ -#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ - /* U+A700-U+A71F */ - /* Bit 6 Combining Diacritical Marks */ - /* Combining Diacritical Marks Supplement */ -#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ - /* U+1DC0-U+1DFF */ - /* Bit 7 Greek and Coptic */ -#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ - /* Bit 8 Coptic */ -#define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */ - /* Bit 9 Cyrillic */ - /* Cyrillic Supplement */ - /* Cyrillic Extended-A */ - /* Cyrillic Extended-B */ -#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ - /* U+0500-U+052F */ - /* U+2DE0-U+2DFF */ - /* U+A640-U+A69F */ - /* Bit 10 Armenian */ -#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ - /* Bit 11 Hebrew */ -#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ - /* Bit 12 Vai */ -#define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */ - /* Bit 13 Arabic */ - /* Arabic Supplement */ -#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ - /* U+0750-U+077F */ - /* Bit 14 NKo */ -#define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */ - /* Bit 15 Devanagari */ -#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ - /* Bit 16 Bengali */ -#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ - /* Bit 17 Gurmukhi */ -#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ - /* Bit 18 Gujarati */ -#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ - /* Bit 19 Oriya */ -#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ - /* Bit 20 Tamil */ -#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ - /* Bit 21 Telugu */ -#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ - /* Bit 22 Kannada */ -#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ - /* Bit 23 Malayalam */ -#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ - /* Bit 24 Thai */ -#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ - /* Bit 25 Lao */ -#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ - /* Bit 26 Georgian */ - /* Georgian Supplement */ -#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ - /* U+2D00-U+2D2F */ - /* Bit 27 Balinese */ -#define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */ - /* Bit 28 Hangul Jamo */ -#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ - /* Bit 29 Latin Extended Additional */ - /* Latin Extended-C */ - /* Latin Extended-D */ -#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ - /* U+2C60-U+2C7F */ - /* U+A720-U+A7FF */ - /* Bit 30 Greek Extended */ -#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ - /* Bit 31 General Punctuation */ - /* Supplemental Punctuation */ -#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ - /* U+2E00-U+2E7F */ - /* Bit 32 Superscripts And Subscripts */ -#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ - /* Bit 33 Currency Symbols */ -#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ - /* Bit 34 Combining Diacritical Marks For Symbols */ -#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ - /* Bit 35 Letterlike Symbols */ -#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ - /* Bit 36 Number Forms */ -#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ - /* Bit 37 Arrows */ - /* Supplemental Arrows-A */ - /* Supplemental Arrows-B */ - /* Miscellaneous Symbols and Arrows */ -#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ - /* U+27F0-U+27FF */ - /* U+2900-U+297F */ - /* U+2B00-U+2BFF */ - /* Bit 38 Mathematical Operators */ - /* Supplemental Mathematical Operators */ - /* Miscellaneous Mathematical Symbols-A */ - /* Miscellaneous Mathematical Symbols-B */ -#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ - /* U+2A00-U+2AFF */ - /* U+27C0-U+27EF */ - /* U+2980-U+29FF */ - /* Bit 39 Miscellaneous Technical */ -#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ - /* Bit 40 Control Pictures */ -#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ - /* Bit 41 Optical Character Recognition */ -#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ - /* Bit 42 Enclosed Alphanumerics */ -#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ - /* Bit 43 Box Drawing */ -#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ - /* Bit 44 Block Elements */ -#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ - /* Bit 45 Geometric Shapes */ -#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ - /* Bit 46 Miscellaneous Symbols */ -#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ - /* Bit 47 Dingbats */ -#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ - /* Bit 48 CJK Symbols and Punctuation */ -#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ - /* Bit 49 Hiragana */ -#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ - /* Bit 50 Katakana */ - /* Katakana Phonetic Extensions */ -#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ - /* U+31F0-U+31FF */ - /* Bit 51 Bopomofo */ - /* Bopomofo Extended */ -#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ - /* U+31A0-U+31BF */ - /* Bit 52 Hangul Compatibility Jamo */ -#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ - /* Bit 53 Phags-Pa */ -#define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */ -#define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */ -#define TT_UCR_PHAGSPA - /* Bit 54 Enclosed CJK Letters and Months */ -#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ - /* Bit 55 CJK Compatibility */ -#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ - /* Bit 56 Hangul Syllables */ -#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ - /* Bit 57 High Surrogates */ - /* High Private Use Surrogates */ - /* Low Surrogates */ - /* */ - /* According to OpenType specs v.1.3+, */ - /* setting bit 57 implies that there is */ - /* at least one codepoint beyond the */ - /* Basic Multilingual Plane that is */ - /* supported by this font. So it really */ - /* means >= U+10000 */ -#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ - /* U+DB80-U+DBFF */ - /* U+DC00-U+DFFF */ -#define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES - /* Bit 58 Phoenician */ -#define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/ - /* Bit 59 CJK Unified Ideographs */ - /* CJK Radicals Supplement */ - /* Kangxi Radicals */ - /* Ideographic Description Characters */ - /* CJK Unified Ideographs Extension A */ - /* CJK Unified Ideographs Extension B */ - /* Kanbun */ -#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ - /* U+2E80-U+2EFF */ - /* U+2F00-U+2FDF */ - /* U+2FF0-U+2FFF */ - /* U+3400-U+4DB5 */ - /*U+20000-U+2A6DF*/ - /* U+3190-U+319F */ - /* Bit 60 Private Use */ -#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ - /* Bit 61 CJK Strokes */ - /* CJK Compatibility Ideographs */ - /* CJK Compatibility Ideographs Supplement */ -#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */ - /* U+F900-U+FAFF */ - /*U+2F800-U+2FA1F*/ - /* Bit 62 Alphabetic Presentation Forms */ -#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ - /* Bit 63 Arabic Presentation Forms-A */ -#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ - /* Bit 64 Combining Half Marks */ -#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ - /* Bit 65 Vertical forms */ - /* CJK Compatibility Forms */ -#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */ - /* U+FE30-U+FE4F */ - /* Bit 66 Small Form Variants */ -#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ - /* Bit 67 Arabic Presentation Forms-B */ -#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ - /* Bit 68 Halfwidth and Fullwidth Forms */ -#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ - /* Bit 69 Specials */ -#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ - /* Bit 70 Tibetan */ -#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ - /* Bit 71 Syriac */ -#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ - /* Bit 72 Thaana */ -#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ - /* Bit 73 Sinhala */ -#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ - /* Bit 74 Myanmar */ -#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ - /* Bit 75 Ethiopic */ - /* Ethiopic Supplement */ - /* Ethiopic Extended */ -#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ - /* U+1380-U+139F */ - /* U+2D80-U+2DDF */ - /* Bit 76 Cherokee */ -#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ - /* Bit 77 Unified Canadian Aboriginal Syllabics */ -#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ - /* Bit 78 Ogham */ -#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ - /* Bit 79 Runic */ -#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ - /* Bit 80 Khmer */ - /* Khmer Symbols */ -#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ - /* U+19E0-U+19FF */ - /* Bit 81 Mongolian */ -#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ - /* Bit 82 Braille Patterns */ -#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ - /* Bit 83 Yi Syllables */ - /* Yi Radicals */ -#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ - /* U+A490-U+A4CF */ - /* Bit 84 Tagalog */ - /* Hanunoo */ - /* Buhid */ - /* Tagbanwa */ -#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ - /* U+1720-U+173F */ - /* U+1740-U+175F */ - /* U+1760-U+177F */ - /* Bit 85 Old Italic */ -#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ - /* Bit 86 Gothic */ -#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ - /* Bit 87 Deseret */ -#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ - /* Bit 88 Byzantine Musical Symbols */ - /* Musical Symbols */ - /* Ancient Greek Musical Notation */ -#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ - /*U+1D100-U+1D1FF*/ - /*U+1D200-U+1D24F*/ - /* Bit 89 Mathematical Alphanumeric Symbols */ -#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ - /* Bit 90 Private Use (plane 15) */ - /* Private Use (plane 16) */ -#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ - /*U+100000-U+10FFFD*/ - /* Bit 91 Variation Selectors */ - /* Variation Selectors Supplement */ -#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ - /*U+E0100-U+E01EF*/ - /* Bit 92 Tags */ -#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ - /* Bit 93 Limbu */ -#define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */ - /* Bit 94 Tai Le */ -#define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ - /* Bit 95 New Tai Lue */ -#define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ - /* Bit 96 Buginese */ -#define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ - /* Bit 97 Glagolitic */ -#define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */ - /* Bit 98 Tifinagh */ -#define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */ - /* Bit 99 Yijing Hexagram Symbols */ -#define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */ - /* Bit 100 Syloti Nagri */ -#define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */ - /* Bit 101 Linear B Syllabary */ - /* Linear B Ideograms */ - /* Aegean Numbers */ -#define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/ - /*U+10080-U+100FF*/ - /*U+10100-U+1013F*/ - /* Bit 102 Ancient Greek Numbers */ -#define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/ - /* Bit 103 Ugaritic */ -#define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/ - /* Bit 104 Old Persian */ -#define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/ - /* Bit 105 Shavian */ -#define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/ - /* Bit 106 Osmanya */ -#define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/ - /* Bit 107 Cypriot Syllabary */ -#define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/ - /* Bit 108 Kharoshthi */ -#define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/ - /* Bit 109 Tai Xuan Jing Symbols */ -#define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/ - /* Bit 110 Cuneiform */ - /* Cuneiform Numbers and Punctuation */ -#define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/ - /*U+12400-U+1247F*/ - /* Bit 111 Counting Rod Numerals */ -#define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/ - /* Bit 112 Sundanese */ -#define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */ - /* Bit 113 Lepcha */ -#define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */ - /* Bit 114 Ol Chiki */ -#define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */ - /* Bit 115 Saurashtra */ -#define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */ - /* Bit 116 Kayah Li */ -#define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */ - /* Bit 117 Rejang */ -#define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */ - /* Bit 118 Cham */ -#define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */ - /* Bit 119 Ancient Symbols */ -#define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/ - /* Bit 120 Phaistos Disc */ -#define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/ - /* Bit 121 Carian */ - /* Lycian */ - /* Lydian */ -#define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/ - /*U+10280-U+1029F*/ - /*U+10920-U+1093F*/ - /* Bit 122 Domino Tiles */ - /* Mahjong Tiles */ -#define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/ - /*U+1F000-U+1F02F*/ - /* Bit 123-127 Reserved for process-internal usage */ - - - /*************************************************************************/ - /* */ - /* Some compilers have a very limited length of identifiers. */ - /* */ -#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) -#define HAVE_LIMIT_ON_IDENTS -#endif - - -#ifndef HAVE_LIMIT_ON_IDENTS - - - /*************************************************************************/ - /* */ - /* Here some alias #defines in order to be clearer. */ - /* */ - /* These are not always #defined to stay within the 31~character limit, */ - /* which some compilers have. */ - /* */ - /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */ - /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ - /* If you get a warning with such a compiler, use the -i40 switch. */ - /* */ -#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ - TT_UCR_ARABIC_PRESENTATIONS_A -#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ - TT_UCR_ARABIC_PRESENTATIONS_B - -#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ - TT_UCR_COMBINING_DIACRITICS -#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ - TT_UCR_COMBINING_DIACRITICS_SYMB - - -#endif /* !HAVE_LIMIT_ON_IDENTS */ - - -FT_END_HEADER - -#endif /* __TTNAMEID_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/tttables.h b/third_party/freetype/include/freetype/tttables.h deleted file mode 100644 index 1568f4036473e8815384d10fb0706b44069c42d7..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/tttables.h +++ /dev/null @@ -1,829 +0,0 @@ -/***************************************************************************/ -/* */ -/* tttables.h */ -/* */ -/* Basic SFNT/TrueType tables definitions and interface */ -/* (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTTABLES_H__ -#define __TTTABLES_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - /*************************************************************************/ - /* */ - /* <Section> */ - /* truetype_tables */ - /* */ - /* <Title> */ - /* TrueType Tables */ - /* */ - /* <Abstract> */ - /* TrueType specific table types and functions. */ - /* */ - /* <Description> */ - /* This section contains the definition of TrueType-specific tables */ - /* as well as some routines used to access and process them. */ - /* */ - /* <Order> */ - /* TT_Header */ - /* TT_HoriHeader */ - /* TT_VertHeader */ - /* TT_OS2 */ - /* TT_Postscript */ - /* TT_PCLT */ - /* TT_MaxProfile */ - /* */ - /* FT_Sfnt_Tag */ - /* FT_Get_Sfnt_Table */ - /* FT_Load_Sfnt_Table */ - /* FT_Sfnt_Table_Info */ - /* */ - /* FT_Get_CMap_Language_ID */ - /* FT_Get_CMap_Format */ - /* */ - /* FT_PARAM_TAG_UNPATENTED_HINTING */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_Header */ - /* */ - /* <Description> */ - /* A structure used to model a TrueType font header table. All */ - /* fields follow the TrueType specification. */ - /* */ - typedef struct TT_Header_ - { - FT_Fixed Table_Version; - FT_Fixed Font_Revision; - - FT_Long CheckSum_Adjust; - FT_Long Magic_Number; - - FT_UShort Flags; - FT_UShort Units_Per_EM; - - FT_Long Created [2]; - FT_Long Modified[2]; - - FT_Short xMin; - FT_Short yMin; - FT_Short xMax; - FT_Short yMax; - - FT_UShort Mac_Style; - FT_UShort Lowest_Rec_PPEM; - - FT_Short Font_Direction; - FT_Short Index_To_Loc_Format; - FT_Short Glyph_Data_Format; - - } TT_Header; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_HoriHeader */ - /* */ - /* <Description> */ - /* A structure used to model a TrueType horizontal header, the `hhea' */ - /* table, as well as the corresponding horizontal metrics table, */ - /* i.e., the `hmtx' table. */ - /* */ - /* <Fields> */ - /* Version :: The table version. */ - /* */ - /* Ascender :: The font's ascender, i.e., the distance */ - /* from the baseline to the top-most of all */ - /* glyph points found in the font. */ - /* */ - /* This value is invalid in many fonts, as */ - /* it is usually set by the font designer, */ - /* and often reflects only a portion of the */ - /* glyphs found in the font (maybe ASCII). */ - /* */ - /* You should use the `sTypoAscender' field */ - /* of the OS/2 table instead if you want */ - /* the correct one. */ - /* */ - /* Descender :: The font's descender, i.e., the distance */ - /* from the baseline to the bottom-most of */ - /* all glyph points found in the font. It */ - /* is negative. */ - /* */ - /* This value is invalid in many fonts, as */ - /* it is usually set by the font designer, */ - /* and often reflects only a portion of the */ - /* glyphs found in the font (maybe ASCII). */ - /* */ - /* You should use the `sTypoDescender' */ - /* field of the OS/2 table instead if you */ - /* want the correct one. */ - /* */ - /* Line_Gap :: The font's line gap, i.e., the distance */ - /* to add to the ascender and descender to */ - /* get the BTB, i.e., the */ - /* baseline-to-baseline distance for the */ - /* font. */ - /* */ - /* advance_Width_Max :: This field is the maximum of all advance */ - /* widths found in the font. It can be */ - /* used to compute the maximum width of an */ - /* arbitrary string of text. */ - /* */ - /* min_Left_Side_Bearing :: The minimum left side bearing of all */ - /* glyphs within the font. */ - /* */ - /* min_Right_Side_Bearing :: The minimum right side bearing of all */ - /* glyphs within the font. */ - /* */ - /* xMax_Extent :: The maximum horizontal extent (i.e., the */ - /* `width' of a glyph's bounding box) for */ - /* all glyphs in the font. */ - /* */ - /* caret_Slope_Rise :: The rise coefficient of the cursor's */ - /* slope of the cursor (slope=rise/run). */ - /* */ - /* caret_Slope_Run :: The run coefficient of the cursor's */ - /* slope. */ - /* */ - /* Reserved :: 8~reserved bytes. */ - /* */ - /* metric_Data_Format :: Always~0. */ - /* */ - /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */ - /* table -- this value can be smaller than */ - /* the total number of glyphs in the font. */ - /* */ - /* long_metrics :: A pointer into the `hmtx' table. */ - /* */ - /* short_metrics :: A pointer into the `hmtx' table. */ - /* */ - /* <Note> */ - /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ - /* be identical except for the names of their fields, */ - /* which are different. */ - /* */ - /* This ensures that a single function in the `ttload' */ - /* module is able to read both the horizontal and vertical */ - /* headers. */ - /* */ - typedef struct TT_HoriHeader_ - { - FT_Fixed Version; - FT_Short Ascender; - FT_Short Descender; - FT_Short Line_Gap; - - FT_UShort advance_Width_Max; /* advance width maximum */ - - FT_Short min_Left_Side_Bearing; /* minimum left-sb */ - FT_Short min_Right_Side_Bearing; /* minimum right-sb */ - FT_Short xMax_Extent; /* xmax extents */ - FT_Short caret_Slope_Rise; - FT_Short caret_Slope_Run; - FT_Short caret_Offset; - - FT_Short Reserved[4]; - - FT_Short metric_Data_Format; - FT_UShort number_Of_HMetrics; - - /* The following fields are not defined by the TrueType specification */ - /* but they are used to connect the metrics header to the relevant */ - /* `HMTX' table. */ - - void* long_metrics; - void* short_metrics; - - } TT_HoriHeader; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_VertHeader */ - /* */ - /* <Description> */ - /* A structure used to model a TrueType vertical header, the `vhea' */ - /* table, as well as the corresponding vertical metrics table, i.e., */ - /* the `vmtx' table. */ - /* */ - /* <Fields> */ - /* Version :: The table version. */ - /* */ - /* Ascender :: The font's ascender, i.e., the distance */ - /* from the baseline to the top-most of */ - /* all glyph points found in the font. */ - /* */ - /* This value is invalid in many fonts, as */ - /* it is usually set by the font designer, */ - /* and often reflects only a portion of */ - /* the glyphs found in the font (maybe */ - /* ASCII). */ - /* */ - /* You should use the `sTypoAscender' */ - /* field of the OS/2 table instead if you */ - /* want the correct one. */ - /* */ - /* Descender :: The font's descender, i.e., the */ - /* distance from the baseline to the */ - /* bottom-most of all glyph points found */ - /* in the font. It is negative. */ - /* */ - /* This value is invalid in many fonts, as */ - /* it is usually set by the font designer, */ - /* and often reflects only a portion of */ - /* the glyphs found in the font (maybe */ - /* ASCII). */ - /* */ - /* You should use the `sTypoDescender' */ - /* field of the OS/2 table instead if you */ - /* want the correct one. */ - /* */ - /* Line_Gap :: The font's line gap, i.e., the distance */ - /* to add to the ascender and descender to */ - /* get the BTB, i.e., the */ - /* baseline-to-baseline distance for the */ - /* font. */ - /* */ - /* advance_Height_Max :: This field is the maximum of all */ - /* advance heights found in the font. It */ - /* can be used to compute the maximum */ - /* height of an arbitrary string of text. */ - /* */ - /* min_Top_Side_Bearing :: The minimum top side bearing of all */ - /* glyphs within the font. */ - /* */ - /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */ - /* glyphs within the font. */ - /* */ - /* yMax_Extent :: The maximum vertical extent (i.e., the */ - /* `height' of a glyph's bounding box) for */ - /* all glyphs in the font. */ - /* */ - /* caret_Slope_Rise :: The rise coefficient of the cursor's */ - /* slope of the cursor (slope=rise/run). */ - /* */ - /* caret_Slope_Run :: The run coefficient of the cursor's */ - /* slope. */ - /* */ - /* caret_Offset :: The cursor's offset for slanted fonts. */ - /* This value is `reserved' in vmtx */ - /* version 1.0. */ - /* */ - /* Reserved :: 8~reserved bytes. */ - /* */ - /* metric_Data_Format :: Always~0. */ - /* */ - /* number_Of_HMetrics :: Number of VMetrics entries in the */ - /* `vmtx' table -- this value can be */ - /* smaller than the total number of glyphs */ - /* in the font. */ - /* */ - /* long_metrics :: A pointer into the `vmtx' table. */ - /* */ - /* short_metrics :: A pointer into the `vmtx' table. */ - /* */ - /* <Note> */ - /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ - /* be identical except for the names of their fields, */ - /* which are different. */ - /* */ - /* This ensures that a single function in the `ttload' */ - /* module is able to read both the horizontal and vertical */ - /* headers. */ - /* */ - typedef struct TT_VertHeader_ - { - FT_Fixed Version; - FT_Short Ascender; - FT_Short Descender; - FT_Short Line_Gap; - - FT_UShort advance_Height_Max; /* advance height maximum */ - - FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ - FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ - FT_Short yMax_Extent; /* xmax or ymax extents */ - FT_Short caret_Slope_Rise; - FT_Short caret_Slope_Run; - FT_Short caret_Offset; - - FT_Short Reserved[4]; - - FT_Short metric_Data_Format; - FT_UShort number_Of_VMetrics; - - /* The following fields are not defined by the TrueType specification */ - /* but they're used to connect the metrics header to the relevant */ - /* `HMTX' or `VMTX' table. */ - - void* long_metrics; - void* short_metrics; - - } TT_VertHeader; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_OS2 */ - /* */ - /* <Description> */ - /* A structure used to model a TrueType OS/2 table. All fields */ - /* comply to the OpenType specification. */ - /* */ - /* Note that we now support old Mac fonts that do not include an OS/2 */ - /* table. In this case, the `version' field is always set to 0xFFFF. */ - /* */ - typedef struct TT_OS2_ - { - FT_UShort version; /* 0x0001 - more or 0xFFFF */ - FT_Short xAvgCharWidth; - FT_UShort usWeightClass; - FT_UShort usWidthClass; - FT_UShort fsType; - FT_Short ySubscriptXSize; - FT_Short ySubscriptYSize; - FT_Short ySubscriptXOffset; - FT_Short ySubscriptYOffset; - FT_Short ySuperscriptXSize; - FT_Short ySuperscriptYSize; - FT_Short ySuperscriptXOffset; - FT_Short ySuperscriptYOffset; - FT_Short yStrikeoutSize; - FT_Short yStrikeoutPosition; - FT_Short sFamilyClass; - - FT_Byte panose[10]; - - FT_ULong ulUnicodeRange1; /* Bits 0-31 */ - FT_ULong ulUnicodeRange2; /* Bits 32-63 */ - FT_ULong ulUnicodeRange3; /* Bits 64-95 */ - FT_ULong ulUnicodeRange4; /* Bits 96-127 */ - - FT_Char achVendID[4]; - - FT_UShort fsSelection; - FT_UShort usFirstCharIndex; - FT_UShort usLastCharIndex; - FT_Short sTypoAscender; - FT_Short sTypoDescender; - FT_Short sTypoLineGap; - FT_UShort usWinAscent; - FT_UShort usWinDescent; - - /* only version 1 and higher: */ - - FT_ULong ulCodePageRange1; /* Bits 0-31 */ - FT_ULong ulCodePageRange2; /* Bits 32-63 */ - - /* only version 2 and higher: */ - - FT_Short sxHeight; - FT_Short sCapHeight; - FT_UShort usDefaultChar; - FT_UShort usBreakChar; - FT_UShort usMaxContext; - - /* only version 5 and higher: */ - - FT_UShort usLowerOpticalPointSize; /* in twips (1/20th points) */ - FT_UShort usUpperOpticalPointSize; /* in twips (1/20th points) */ - - } TT_OS2; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_Postscript */ - /* */ - /* <Description> */ - /* A structure used to model a TrueType PostScript table. All fields */ - /* comply to the TrueType specification. This structure does not */ - /* reference the PostScript glyph names, which can be nevertheless */ - /* accessed with the `ttpost' module. */ - /* */ - typedef struct TT_Postscript_ - { - FT_Fixed FormatType; - FT_Fixed italicAngle; - FT_Short underlinePosition; - FT_Short underlineThickness; - FT_ULong isFixedPitch; - FT_ULong minMemType42; - FT_ULong maxMemType42; - FT_ULong minMemType1; - FT_ULong maxMemType1; - - /* Glyph names follow in the file, but we don't */ - /* load them by default. See the ttpost.c file. */ - - } TT_Postscript; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_PCLT */ - /* */ - /* <Description> */ - /* A structure used to model a TrueType PCLT table. All fields */ - /* comply to the TrueType specification. */ - /* */ - typedef struct TT_PCLT_ - { - FT_Fixed Version; - FT_ULong FontNumber; - FT_UShort Pitch; - FT_UShort xHeight; - FT_UShort Style; - FT_UShort TypeFamily; - FT_UShort CapHeight; - FT_UShort SymbolSet; - FT_Char TypeFace[16]; - FT_Char CharacterComplement[8]; - FT_Char FileName[6]; - FT_Char StrokeWeight; - FT_Char WidthType; - FT_Byte SerifStyle; - FT_Byte Reserved; - - } TT_PCLT; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_MaxProfile */ - /* */ - /* <Description> */ - /* The maximum profile is a table containing many max values, which */ - /* can be used to pre-allocate arrays. This ensures that no memory */ - /* allocation occurs during a glyph load. */ - /* */ - /* <Fields> */ - /* version :: The version number. */ - /* */ - /* numGlyphs :: The number of glyphs in this TrueType */ - /* font. */ - /* */ - /* maxPoints :: The maximum number of points in a */ - /* non-composite TrueType glyph. See also */ - /* the structure element */ - /* `maxCompositePoints'. */ - /* */ - /* maxContours :: The maximum number of contours in a */ - /* non-composite TrueType glyph. See also */ - /* the structure element */ - /* `maxCompositeContours'. */ - /* */ - /* maxCompositePoints :: The maximum number of points in a */ - /* composite TrueType glyph. See also the */ - /* structure element `maxPoints'. */ - /* */ - /* maxCompositeContours :: The maximum number of contours in a */ - /* composite TrueType glyph. See also the */ - /* structure element `maxContours'. */ - /* */ - /* maxZones :: The maximum number of zones used for */ - /* glyph hinting. */ - /* */ - /* maxTwilightPoints :: The maximum number of points in the */ - /* twilight zone used for glyph hinting. */ - /* */ - /* maxStorage :: The maximum number of elements in the */ - /* storage area used for glyph hinting. */ - /* */ - /* maxFunctionDefs :: The maximum number of function */ - /* definitions in the TrueType bytecode for */ - /* this font. */ - /* */ - /* maxInstructionDefs :: The maximum number of instruction */ - /* definitions in the TrueType bytecode for */ - /* this font. */ - /* */ - /* maxStackElements :: The maximum number of stack elements used */ - /* during bytecode interpretation. */ - /* */ - /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */ - /* used for glyph hinting. */ - /* */ - /* maxComponentElements :: The maximum number of simple (i.e., non- */ - /* composite) glyphs in a composite glyph. */ - /* */ - /* maxComponentDepth :: The maximum nesting depth of composite */ - /* glyphs. */ - /* */ - /* <Note> */ - /* This structure is only used during font loading. */ - /* */ - typedef struct TT_MaxProfile_ - { - FT_Fixed version; - FT_UShort numGlyphs; - FT_UShort maxPoints; - FT_UShort maxContours; - FT_UShort maxCompositePoints; - FT_UShort maxCompositeContours; - FT_UShort maxZones; - FT_UShort maxTwilightPoints; - FT_UShort maxStorage; - FT_UShort maxFunctionDefs; - FT_UShort maxInstructionDefs; - FT_UShort maxStackElements; - FT_UShort maxSizeOfInstructions; - FT_UShort maxComponentElements; - FT_UShort maxComponentDepth; - - } TT_MaxProfile; - - - /*************************************************************************/ - /* */ - /* <Enum> */ - /* FT_Sfnt_Tag */ - /* */ - /* <Description> */ - /* An enumeration used to specify the index of an SFNT table. */ - /* Used in the @FT_Get_Sfnt_Table API function. */ - /* */ - /* <Values> */ - /* FT_SFNT_HEAD :: To access the font's @TT_Header structure. */ - /* */ - /* FT_SFNT_MAXP :: To access the font's @TT_MaxProfile structure. */ - /* */ - /* FT_SFNT_OS2 :: To access the font's @TT_OS2 structure. */ - /* */ - /* FT_SFNT_HHEA :: To access the font's @TT_HoriHeader structure. */ - /* */ - /* FT_SFNT_VHEA :: To access the font's @TT_VertHeader struture. */ - /* */ - /* FT_SFNT_POST :: To access the font's @TT_Postscript structure. */ - /* */ - /* FT_SFNT_PCLT :: To access the font's @TT_PCLT structure. */ - /* */ - typedef enum FT_Sfnt_Tag_ - { - FT_SFNT_HEAD, - FT_SFNT_MAXP, - FT_SFNT_OS2, - FT_SFNT_HHEA, - FT_SFNT_VHEA, - FT_SFNT_POST, - FT_SFNT_PCLT, - - FT_SFNT_MAX - - } FT_Sfnt_Tag; - - /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag' */ - /* values instead */ -#define ft_sfnt_head FT_SFNT_HEAD -#define ft_sfnt_maxp FT_SFNT_MAXP -#define ft_sfnt_os2 FT_SFNT_OS2 -#define ft_sfnt_hhea FT_SFNT_HHEA -#define ft_sfnt_vhea FT_SFNT_VHEA -#define ft_sfnt_post FT_SFNT_POST -#define ft_sfnt_pclt FT_SFNT_PCLT - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_Sfnt_Table */ - /* */ - /* <Description> */ - /* Return a pointer to a given SFNT table within a face. */ - /* */ - /* <Input> */ - /* face :: A handle to the source. */ - /* */ - /* tag :: The index of the SFNT table. */ - /* */ - /* <Return> */ - /* A type-less pointer to the table. This will be~0 in case of */ - /* error, or if the corresponding table was not found *OR* loaded */ - /* from the file. */ - /* */ - /* Use a typecast according to `tag' to access the structure */ - /* elements. */ - /* */ - /* <Note> */ - /* The table is owned by the face object and disappears with it. */ - /* */ - /* This function is only useful to access SFNT tables that are loaded */ - /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */ - /* a list. */ - /* */ - /* Here an example how to access the `vhea' table: */ - /* */ - /* { */ - /* TT_VertHeader* vert_header; */ - /* */ - /* */ - /* vert_header = */ - /* (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA ); */ - /* } */ - /* */ - FT_EXPORT( void* ) - FT_Get_Sfnt_Table( FT_Face face, - FT_Sfnt_Tag tag ); - - - /************************************************************************** - * - * @function: - * FT_Load_Sfnt_Table - * - * @description: - * Load any font table into client memory. - * - * @input: - * face :: - * A handle to the source face. - * - * tag :: - * The four-byte tag of the table to load. Use the value~0 if you want - * to access the whole font file. Otherwise, you can use one of the - * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new - * one with @FT_MAKE_TAG. - * - * offset :: - * The starting offset in the table (or file if tag == 0). - * - * @output: - * buffer :: - * The target buffer address. The client must ensure that the memory - * array is big enough to hold the data. - * - * @inout: - * length :: - * If the `length' parameter is NULL, then try to load the whole table. - * Return an error code if it fails. - * - * Else, if `*length' is~0, exit immediately while returning the - * table's (or file) full size in it. - * - * Else the number of bytes to read from the table or file, from the - * starting offset. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * If you need to determine the table's length you should first call this - * function with `*length' set to~0, as in the following example: - * - * { - * FT_ULong length = 0; - * - * - * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); - * if ( error ) { ... table does not exist ... } - * - * buffer = malloc( length ); - * if ( buffer == NULL ) { ... not enough memory ... } - * - * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); - * if ( error ) { ... could not load table ... } - * } - * - * Note that structures like @TT_Header or @TT_OS2 can't be used with - * this function; they are limited to @FT_Get_Sfnt_Table. Reason is that - * those structures depend on the processor architecture, with varying - * size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian). - * - */ - FT_EXPORT( FT_Error ) - FT_Load_Sfnt_Table( FT_Face face, - FT_ULong tag, - FT_Long offset, - FT_Byte* buffer, - FT_ULong* length ); - - - /************************************************************************** - * - * @function: - * FT_Sfnt_Table_Info - * - * @description: - * Return information on an SFNT table. - * - * @input: - * face :: - * A handle to the source face. - * - * table_index :: - * The index of an SFNT table. The function returns - * FT_Err_Table_Missing for an invalid value. - * - * @inout: - * tag :: - * The name tag of the SFNT table. If the value is NULL, `table_index' - * is ignored, and `length' returns the number of SFNT tables in the - * font. - * - * @output: - * length :: - * The length of the SFNT table (or the number of SFNT tables, depending - * on `tag'). - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * While parsing fonts, FreeType handles SFNT tables with length zero as - * missing. - * - */ - FT_EXPORT( FT_Error ) - FT_Sfnt_Table_Info( FT_Face face, - FT_UInt table_index, - FT_ULong *tag, - FT_ULong *length ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_CMap_Language_ID */ - /* */ - /* <Description> */ - /* Return TrueType/sfnt specific cmap language ID. Definitions of */ - /* language ID values are in `ttnameid.h'. */ - /* */ - /* <Input> */ - /* charmap :: */ - /* The target charmap. */ - /* */ - /* <Return> */ - /* The language ID of `charmap'. If `charmap' doesn't belong to a */ - /* TrueType/sfnt face, just return~0 as the default value. */ - /* */ - /* For a format~14 cmap (to access Unicode IVS), the return value is */ - /* 0xFFFFFFFF. */ - /* */ - FT_EXPORT( FT_ULong ) - FT_Get_CMap_Language_ID( FT_CharMap charmap ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Get_CMap_Format */ - /* */ - /* <Description> */ - /* Return TrueType/sfnt specific cmap format. */ - /* */ - /* <Input> */ - /* charmap :: */ - /* The target charmap. */ - /* */ - /* <Return> */ - /* The format of `charmap'. If `charmap' doesn't belong to a */ - /* TrueType/sfnt face, return -1. */ - /* */ - FT_EXPORT( FT_Long ) - FT_Get_CMap_Format( FT_CharMap charmap ); - - /* */ - - -FT_END_HEADER - -#endif /* __TTTABLES_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/tttags.h b/third_party/freetype/include/freetype/tttags.h deleted file mode 100644 index 3836c7bbfd5b9d1a86a917cc23aaa1fe696e46f1..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/tttags.h +++ /dev/null @@ -1,111 +0,0 @@ -/***************************************************************************/ -/* */ -/* tttags.h */ -/* */ -/* Tags for TrueType and OpenType tables (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTAGS_H__ -#define __TTAGS_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - -#define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' ) -#define TTAG_BASE FT_MAKE_TAG( 'B', 'A', 'S', 'E' ) -#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' ) -#define TTAG_BDF FT_MAKE_TAG( 'B', 'D', 'F', ' ' ) -#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' ) -#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' ) -#define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' ) -#define TTAG_CBDT FT_MAKE_TAG( 'C', 'B', 'D', 'T' ) -#define TTAG_CBLC FT_MAKE_TAG( 'C', 'B', 'L', 'C' ) -#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' ) -#define TTAG_CID FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) -#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' ) -#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' ) -#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' ) -#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' ) -#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' ) -#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' ) -#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' ) -#define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' ) -#define TTAG_FOND FT_MAKE_TAG( 'F', 'O', 'N', 'D' ) -#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' ) -#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' ) -#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' ) -#define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' ) -#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' ) -#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' ) -#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) -#define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' ) -#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' ) -#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' ) -#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' ) -#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' ) -#define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' ) -#define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' ) -#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' ) -#define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' ) -#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' ) -#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' ) -#define TTAG_LWFN FT_MAKE_TAG( 'L', 'W', 'F', 'N' ) -#define TTAG_MATH FT_MAKE_TAG( 'M', 'A', 'T', 'H' ) -#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' ) -#define TTAG_META FT_MAKE_TAG( 'M', 'E', 'T', 'A' ) -#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' ) -#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' ) -#define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' ) -#define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' ) -#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' ) -#define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' ) -#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' ) -#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) -#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' ) -#define TTAG_POST FT_MAKE_TAG( 'P', 'O', 'S', 'T' ) -#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' ) -#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' ) -#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' ) -#define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' ) -#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' ) -#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' ) -#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' ) -#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) -#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) -#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' ) -#define TTAG_TYP1 FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) -#define TTAG_typ1 FT_MAKE_TAG( 't', 'y', 'p', '1' ) -#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' ) -#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' ) -#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' ) -#define TTAG_wOFF FT_MAKE_TAG( 'w', 'O', 'F', 'F' ) - - -FT_END_HEADER - -#endif /* __TTAGS_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/freetype/ttunpat.h b/third_party/freetype/include/freetype/ttunpat.h deleted file mode 100644 index 8ea556895c1856904f87d69a3df016ddf0a2be5c..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/freetype/ttunpat.h +++ /dev/null @@ -1,60 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttunpat.h */ -/* */ -/* Definitions for the unpatented TrueType hinting system */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* Written by Graham Asher <graham.asher@btinternet.com> */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTUNPAT_H__ -#define __TTUNPAT_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H - -#ifdef FREETYPE_H -#error "freetype.h of FreeType 1 has been loaded!" -#error "Please fix the directory search order for header files" -#error "so that freetype.h of FreeType 2 is found first." -#endif - - -FT_BEGIN_HEADER - - - /*************************************************************************** - * - * @constant: - * FT_PARAM_TAG_UNPATENTED_HINTING - * - * @description: - * A constant used as the tag of an @FT_Parameter structure to indicate - * that unpatented methods only should be used by the TrueType bytecode - * interpreter for a typeface opened by @FT_Open_Face. - * - */ -#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' ) - - /* */ - - -FT_END_HEADER - - -#endif /* __TTUNPAT_H__ */ - - -/* END */ diff --git a/third_party/freetype/include/ft2build.h b/third_party/freetype/include/ft2build.h deleted file mode 100644 index 419b80ae44d20125fca2538840508b6f538af931..0000000000000000000000000000000000000000 --- a/third_party/freetype/include/ft2build.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* ft2build.h */ -/* */ -/* FreeType 2 build and setup macros. */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This is the `entry point' for FreeType header file inclusions. It is */ - /* the only header file which should be included directly; all other */ - /* FreeType header files should be accessed with macro names (after */ - /* including `ft2build.h'). */ - /* */ - /* A typical example is */ - /* */ - /* #include <ft2build.h> */ - /* #include FT_FREETYPE_H */ - /* */ - /*************************************************************************/ - - -#ifndef __FT2BUILD_H__ -#define __FT2BUILD_H__ - -#include <freetype/config/ftheader.h> - -#endif /* __FT2BUILD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psnames/pstables.h b/third_party/freetype/include/pstables.h similarity index 99% rename from third_party/freetype/src/psnames/pstables.h rename to third_party/freetype/include/pstables.h index 3f31c31b1892dfe0614b0820c119a7420d67629f..2a2b717d8f80aa4f7fa19164c2fb5754bc2352c0 100644 --- a/third_party/freetype/src/psnames/pstables.h +++ b/third_party/freetype/include/pstables.h @@ -4,7 +4,7 @@ /* */ /* PostScript glyph names. */ /* */ -/* Copyright 2005-2015 by */ +/* Copyright 2005-2017 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -19,7 +19,16 @@ /* This file has been generated automatically -- do not edit! */ - static const char ft_standard_glyph_names[3696] = +#ifndef DEFINE_PS_TABLES_DATA +#ifdef __cplusplus + extern "C" +#else + extern +#endif +#endif + const char ft_standard_glyph_names[3696] +#ifdef DEFINE_PS_TABLES_DATA + = { '.','n','u','l','l', 0, 'n','o','n','m','a','r','k','i','n','g','r','e','t','u','r','n', 0, @@ -441,14 +450,25 @@ 'R','e','g','u','l','a','r', 0, 'R','o','m','a','n', 0, 'S','e','m','i','b','o','l','d', 0, - }; + } +#endif /* DEFINE_PS_TABLES_DATA */ + ; #define FT_NUM_MAC_NAMES 258 /* Values are offsets into the `ft_standard_glyph_names' table */ - static const short ft_mac_names[FT_NUM_MAC_NAMES] = +#ifndef DEFINE_PS_TABLES_DATA +#ifdef __cplusplus + extern "C" +#else + extern +#endif +#endif + const short ft_mac_names[FT_NUM_MAC_NAMES] +#ifdef DEFINE_PS_TABLES_DATA + = { 253, 0, 6, 261, 267, 274, 283, 294, 301, 309, 758, 330, 340, 351, 360, 365, 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430, @@ -469,14 +489,25 @@ 1066,1073,1101,1143,1536,1783,1596,1843,1253,1207,1319,1579,1826,1229, 1270,1313,1323,1171,1290,1332,1211,1235,1276, 169, 175, 182, 189, 200, 209, 218, 225, 232, 239, 246 - }; + } +#endif /* DEFINE_PS_TABLES_DATA */ + ; #define FT_NUM_SID_NAMES 391 /* Values are offsets into the `ft_standard_glyph_names' table */ - static const short ft_sid_names[FT_NUM_SID_NAMES] = +#ifndef DEFINE_PS_TABLES_DATA +#ifdef __cplusplus + extern "C" +#else + extern +#endif +#endif + const short ft_sid_names[FT_NUM_SID_NAMES] +#ifdef DEFINE_PS_TABLES_DATA + = { 253, 261, 267, 274, 283, 294, 301, 309, 319, 330, 340, 351, 360, 365, 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430, 436, 441, @@ -506,11 +537,22 @@ 3237,3249,3264,3275,3283,3297,3309,3321,3338,3353,3365,3377,3394,3409, 3418,3430,3442,3454,3471,3483,3498,3506,3518,3530,3542,3559,3574,3586, 3597,3612,3620,3628,3636,3644,3650,3655,3660,3666,3673,3681,3687 - }; + } +#endif /* DEFINE_PS_TABLES_DATA */ + ; /* the following are indices into the SID name table */ - static const unsigned short t1_standard_encoding[256] = +#ifndef DEFINE_PS_TABLES_DATA +#ifdef __cplusplus + extern "C" +#else + extern +#endif +#endif + const unsigned short t1_standard_encoding[256] +#ifdef DEFINE_PS_TABLES_DATA + = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -528,11 +570,22 @@ 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,138, 0,139, 0, 0, 0, 0,140,141,142,143, 0, 0, 0, 0, 0,144, 0, 0, 0,145, 0, 0,146,147,148,149, 0, 0, 0, 0 - }; + } +#endif /* DEFINE_PS_TABLES_DATA */ + ; /* the following are indices into the SID name table */ - static const unsigned short t1_expert_encoding[256] = +#ifndef DEFINE_PS_TABLES_DATA +#ifdef __cplusplus + extern "C" +#else + extern +#endif +#endif + const unsigned short t1_expert_encoding[256] +#ifdef DEFINE_PS_TABLES_DATA + = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -550,7 +603,9 @@ 331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346, 347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362, 363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378 - }; + } +#endif /* DEFINE_PS_TABLES_DATA */ + ; /* @@ -564,7 +619,16 @@ #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST - static const unsigned char ft_adobe_glyph_list[55997L] = +#ifndef DEFINE_PS_TABLES_DATA +#ifdef __cplusplus + extern "C" +#else + extern +#endif +#endif + const unsigned char ft_adobe_glyph_list[55997L] +#ifdef DEFINE_PS_TABLES_DATA + = { 0, 52, 0,106, 2,167, 3, 63, 4,220, 6,125, 9,143, 10, 23, 11,137, 12,199, 14,246, 15, 87, 16,233, 17,219, 18,104, 19, 88, @@ -4066,9 +4130,12 @@ 248,232,239,239,107,128, 2,144,243,244,242,239,235,101,128, 1, 182,117, 2,218,167,218,178,232,233,242,225,231,225,238, 97,128, 48, 90,235,225,244,225,235,225,238, 97,128, 48,186 - }; + } +#endif /* DEFINE_PS_TABLES_DATA */ + ; +#ifdef DEFINE_PS_TABLES /* * This function searches the compressed table efficiently. */ @@ -4163,6 +4230,7 @@ NotFound: return 0; } +#endif /* DEFINE_PS_TABLES */ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ diff --git a/third_party/freetype/roll-freetype.sh b/third_party/freetype/roll-freetype.sh new file mode 100755 index 0000000000000000000000000000000000000000..0930a6484780d8a7e5e74aef72e54edc86a62122 --- /dev/null +++ b/third_party/freetype/roll-freetype.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# Copyright 2017 The 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. + +set -e +set -o pipefail +set -u + +REVIEWERS=`paste -s -d, third_party/freetype/OWNERS` +roll-dep -r "${REVIEWERS}" "$@" pdfium/third_party/freetype/src/ +FTVERSION=`git -C third_party/freetype/src/ describe --long` +FTCOMMIT=`git -C third_party/freetype/src/ rev-parse HEAD` + +# Make sure our copy of pstables.h matches the one in freetype/src. +cmp third_party/freetype/src/src/psnames/pstables.h \ + third_party/freetype/include/pstables.h + +sed -i "s/^Version: .*\$/Version: ${FTVERSION%-*}/" \ + third_party/freetype/README.pdfium +sed -i "s/^Revision: .*\$/Revision: ${FTCOMMIT}/" \ + third_party/freetype/README.pdfium + +git add third_party/freetype/README.pdfium +git commit --quiet --amend --no-edit diff --git a/third_party/freetype/src/base/Jamfile b/third_party/freetype/src/base/Jamfile deleted file mode 100644 index e39fb096b240ca3693f313115ff8879164b7c48a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/Jamfile +++ /dev/null @@ -1,87 +0,0 @@ -# FreeType 2 src/base Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) base ; - - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = basepic - ftadvanc - ftcalc - ftdbgmem - ftgloadr - ftobjs - ftoutln - ftpic - ftrfork - ftsnames - ftstream - fttrigon - ftutil - ; - } - else - { - _sources = ftbase ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# Add the optional/replaceable files. -# -{ - local _sources = ftapi - ftbbox - ftbdf - ftbitmap - ftcid - ftdebug - ftfntfmt - ftfstype - ftgasp - ftglyph - ftgxval - ftinit - ftlcdfil - ftmm - ftotval - ftpatent - ftpfr - ftstroke - ftsynth - ftsystem - fttype1 - ftwinfnt - ; - - Library $(FT2_LIB) : $(_sources).c ; -} - -# Add Macintosh-specific file to the library when necessary. -# -if $(MAC) -{ - Library $(FT2_LIB) : ftmac.c ; -} -else if $(OS) = MACOSX -{ - if $(FT2_MULTI) - { - Library $(FT2_LIB) : ftmac.c ; - } -} - -# end of src/base Jamfile diff --git a/third_party/freetype/src/base/basepic.c b/third_party/freetype/src/base/basepic.c deleted file mode 100644 index 9850ed96a4267c0a3bf4a1ae3d62cded95aa2107..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/basepic.c +++ /dev/null @@ -1,108 +0,0 @@ -/***************************************************************************/ -/* */ -/* basepic.c */ -/* */ -/* The FreeType position independent code services for base. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "basepic.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from ftglyph.c */ - void - FT_Init_Class_ft_outline_glyph_class( FT_Glyph_Class* clazz ); - - void - FT_Init_Class_ft_bitmap_glyph_class( FT_Glyph_Class* clazz ); - -#ifdef FT_CONFIG_OPTION_MAC_FONTS - /* forward declaration of PIC init function from ftrfork.c */ - /* (not modularized) */ - void - FT_Init_Table_ft_raccess_guess_table( ft_raccess_guess_rec* record ); -#endif - - /* forward declaration of PIC init functions from ftinit.c */ - FT_Error - ft_create_default_module_classes( FT_Library library ); - - void - ft_destroy_default_module_classes( FT_Library library ); - - - void - ft_base_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->base ) - { - /* destroy default module classes */ - /* (in case FT_Add_Default_Modules was used) */ - ft_destroy_default_module_classes( library ); - - FT_FREE( pic_container->base ); - pic_container->base = NULL; - } - } - - - FT_Error - ft_base_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - BasePIC* container = NULL; - FT_Memory memory = library->memory; - - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->base = container; - - /* initialize default modules list and pointers */ - error = ft_create_default_module_classes( library ); - if ( error ) - goto Exit; - - /* initialize pointer table - */ - /* this is how the module usually expects this data */ - FT_Init_Class_ft_outline_glyph_class( - &container->ft_outline_glyph_class ); - FT_Init_Class_ft_bitmap_glyph_class( - &container->ft_bitmap_glyph_class ); -#ifdef FT_CONFIG_OPTION_MAC_FONTS - FT_Init_Table_ft_raccess_guess_table( - (ft_raccess_guess_rec*)&container->ft_raccess_guess_table ); -#endif - - Exit: - if ( error ) - ft_base_pic_free( library ); - return error; - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/base/basepic.h b/third_party/freetype/src/base/basepic.h deleted file mode 100644 index c5d7cbf5ab77aa781d9d6bbe51ccd4dbb7ffc69d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/basepic.h +++ /dev/null @@ -1,91 +0,0 @@ -/***************************************************************************/ -/* */ -/* basepic.h */ -/* */ -/* The FreeType position independent code services for base. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __BASEPIC_H__ -#define __BASEPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class -#define FT_BITMAP_GLYPH_CLASS_GET &ft_bitmap_glyph_class -#define FT_DEFAULT_MODULES_GET ft_default_modules - -#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK -#define FT_RACCESS_GUESS_TABLE_GET ft_raccess_guess_table -#endif - -#else /* FT_CONFIG_OPTION_PIC */ - -#include FT_GLYPH_H - -#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK -#include FT_INTERNAL_RFORK_H -#endif - - -FT_BEGIN_HEADER - - typedef struct BasePIC_ - { - FT_Module_Class** default_module_classes; - FT_Glyph_Class ft_outline_glyph_class; - FT_Glyph_Class ft_bitmap_glyph_class; - -#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK - ft_raccess_guess_rec ft_raccess_guess_table[FT_RACCESS_N_RULES]; -#endif - - } BasePIC; - - -#define GET_PIC( lib ) ( (BasePIC*)( (lib)->pic_container.base ) ) - -#define FT_OUTLINE_GLYPH_CLASS_GET \ - ( &GET_PIC( library )->ft_outline_glyph_class ) -#define FT_BITMAP_GLYPH_CLASS_GET \ - ( &GET_PIC( library )->ft_bitmap_glyph_class ) -#define FT_DEFAULT_MODULES_GET \ - ( GET_PIC( library )->default_module_classes ) - -#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK -#define FT_RACCESS_GUESS_TABLE_GET \ - ( GET_PIC( library )->ft_raccess_guess_table ) -#endif - - - /* see basepic.c for the implementation */ - void - ft_base_pic_free( FT_Library library ); - - FT_Error - ft_base_pic_init( FT_Library library ); - -FT_END_HEADER - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -#endif /* __BASEPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftadvanc.c b/third_party/freetype/src/base/ftadvanc.c deleted file mode 100644 index f12908f5181e3f2451a33c5bb11f91ac283225b0..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftadvanc.c +++ /dev/null @@ -1,168 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftadvanc.c */ -/* */ -/* Quick computation of advance widths (body). */ -/* */ -/* Copyright 2008-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_ADVANCES_H -#include FT_INTERNAL_OBJECTS_H - - - static FT_Error - _ft_face_scale_advances( FT_Face face, - FT_Fixed* advances, - FT_UInt count, - FT_Int32 flags ) - { - FT_Fixed scale; - FT_UInt nn; - - - if ( flags & FT_LOAD_NO_SCALE ) - return FT_Err_Ok; - - if ( face->size == NULL ) - return FT_THROW( Invalid_Size_Handle ); - - if ( flags & FT_LOAD_VERTICAL_LAYOUT ) - scale = face->size->metrics.y_scale; - else - scale = face->size->metrics.x_scale; - - /* this must be the same scaling as to get linear{Hori,Vert}Advance */ - /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */ - - for ( nn = 0; nn < count; nn++ ) - advances[nn] = FT_MulDiv( advances[nn], scale, 64 ); - - return FT_Err_Ok; - } - - - /* at the moment, we can perform fast advance retrieval only in */ - /* the following cases: */ - /* */ - /* - unscaled load */ - /* - unhinted load */ - /* - light-hinted load */ - -#define LOAD_ADVANCE_FAST_CHECK( flags ) \ - ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \ - FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT ) - - - /* documentation is in ftadvanc.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Advance( FT_Face face, - FT_UInt gindex, - FT_Int32 flags, - FT_Fixed *padvance ) - { - FT_Face_GetAdvancesFunc func; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !padvance ) - return FT_THROW( Invalid_Argument ); - - if ( gindex >= (FT_UInt)face->num_glyphs ) - return FT_THROW( Invalid_Glyph_Index ); - - func = face->driver->clazz->get_advances; - if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) ) - { - FT_Error error; - - - error = func( face, gindex, 1, flags, padvance ); - if ( !error ) - return _ft_face_scale_advances( face, padvance, 1, flags ); - - if ( FT_ERR_NEQ( error, Unimplemented_Feature ) ) - return error; - } - - return FT_Get_Advances( face, gindex, 1, flags, padvance ); - } - - - /* documentation is in ftadvanc.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Advances( FT_Face face, - FT_UInt start, - FT_UInt count, - FT_Int32 flags, - FT_Fixed *padvances ) - { - FT_Face_GetAdvancesFunc func; - FT_UInt num, end, nn; - FT_Error error = FT_Err_Ok; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !padvances ) - return FT_THROW( Invalid_Argument ); - - num = (FT_UInt)face->num_glyphs; - end = start + count; - if ( start >= num || end < start || end > num ) - return FT_THROW( Invalid_Glyph_Index ); - - if ( count == 0 ) - return FT_Err_Ok; - - func = face->driver->clazz->get_advances; - if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) ) - { - error = func( face, start, count, flags, padvances ); - if ( !error ) - return _ft_face_scale_advances( face, padvances, count, flags ); - - if ( FT_ERR_NEQ( error, Unimplemented_Feature ) ) - return error; - } - - error = FT_Err_Ok; - - if ( flags & FT_ADVANCE_FLAG_FAST_ONLY ) - return FT_THROW( Unimplemented_Feature ); - - flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; - for ( nn = 0; nn < count; nn++ ) - { - error = FT_Load_Glyph( face, start + nn, flags ); - if ( error ) - break; - - /* scale from 26.6 to 16.16 */ - padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) - ? face->glyph->advance.y << 10 - : face->glyph->advance.x << 10; - } - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftapi.c b/third_party/freetype/src/base/ftapi.c deleted file mode 100644 index f22a181b59b1684f01dc4fbc8c6f5340d56b4544..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftapi.c +++ /dev/null @@ -1,121 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftapi.c */ -/* */ -/* The FreeType compatibility functions (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_LIST_H -#include FT_OUTLINE_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TABLES_H -#include FT_OUTLINE_H - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** C O M P A T I B I L I T Y ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /* backwards compatibility API */ - - FT_BASE_DEF( void ) - FT_New_Memory_Stream( FT_Library library, - FT_Byte* base, - FT_ULong size, - FT_Stream stream ) - { - FT_UNUSED( library ); - - FT_Stream_OpenMemory( stream, base, size ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Seek_Stream( FT_Stream stream, - FT_ULong pos ) - { - return FT_Stream_Seek( stream, pos ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Skip_Stream( FT_Stream stream, - FT_Long distance ) - { - return FT_Stream_Skip( stream, distance ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Read_Stream( FT_Stream stream, - FT_Byte* buffer, - FT_ULong count ) - { - return FT_Stream_Read( stream, buffer, count ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Read_Stream_At( FT_Stream stream, - FT_ULong pos, - FT_Byte* buffer, - FT_ULong count ) - { - return FT_Stream_ReadAt( stream, pos, buffer, count ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Extract_Frame( FT_Stream stream, - FT_ULong count, - FT_Byte** pbytes ) - { - return FT_Stream_ExtractFrame( stream, count, pbytes ); - } - - - FT_BASE_DEF( void ) - FT_Release_Frame( FT_Stream stream, - FT_Byte** pbytes ) - { - FT_Stream_ReleaseFrame( stream, pbytes ); - } - - FT_BASE_DEF( FT_Error ) - FT_Access_Frame( FT_Stream stream, - FT_ULong count ) - { - return FT_Stream_EnterFrame( stream, count ); - } - - - FT_BASE_DEF( void ) - FT_Forget_Frame( FT_Stream stream ) - { - FT_Stream_ExitFrame( stream ); - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftbase.c b/third_party/freetype/src/base/ftbase.c deleted file mode 100644 index 253dfb723690ec5ea36f86e57676ede22d770b1e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftbase.c +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbase.c */ -/* */ -/* Single object library component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include "ftpic.c" -#include "basepic.c" -#include "ftadvanc.c" -#include "ftcalc.c" -#include "ftdbgmem.c" -#include "ftgloadr.c" -#include "ftobjs.c" -#include "ftoutln.c" -#include "ftrfork.c" -#include "ftsnames.c" -#include "ftstream.c" -#include "fttrigon.c" -#include "ftutil.c" - -#ifdef FT_MACINTOSH -#include "ftmac.c" -#endif - -/* END */ diff --git a/third_party/freetype/src/base/ftbase.h b/third_party/freetype/src/base/ftbase.h deleted file mode 100644 index e37fefa411f9cbb8ef20de14790f1e07670f2202..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftbase.h +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbase.h */ -/* */ -/* The FreeType private functions used in base module (specification). */ -/* */ -/* Copyright 2008-2015 by */ -/* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTBASE_H__ -#define __FTBASE_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H - - -FT_BEGIN_HEADER - - - /* MacOS resource fork cannot exceed 16MB at least for Carbon code; */ - /* see https://support.microsoft.com/en-us/kb/130437 */ -#define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL - - - /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */ - /* font, and try to load a face specified by the face_index. */ - FT_LOCAL( FT_Error ) - open_face_PS_from_sfnt_stream( FT_Library library, - FT_Stream stream, - FT_Long face_index, - FT_Int num_params, - FT_Parameter *params, - FT_Face *aface ); - - - /* Create a new FT_Face given a buffer and a driver name. */ - /* From ftmac.c. */ - FT_LOCAL( FT_Error ) - open_face_from_buffer( FT_Library library, - FT_Byte* base, - FT_ULong size, - FT_Long face_index, - const char* driver_name, - FT_Face *aface ); - - -#if defined( FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK ) && \ - !defined( FT_MACINTOSH ) - /* Mac OS X/Darwin kernel often changes recommended method to access */ - /* the resource fork and older methods makes the kernel issue the */ - /* warning of deprecated method. To calm it down, the methods based */ - /* on Darwin VFS should be grouped and skip the rest methods after */ - /* the case the resource is opened but found to lack a font in it. */ - FT_LOCAL( FT_Bool ) - ft_raccess_rule_by_darwin_vfs( FT_Library library, FT_UInt rule_index ); -#endif - - -FT_END_HEADER - -#endif /* __FTBASE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftbbox.c b/third_party/freetype/src/base/ftbbox.c deleted file mode 100644 index 10df98de6ad27c3785a69c68a743dad322b2a684..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftbbox.c +++ /dev/null @@ -1,509 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbbox.c */ -/* */ -/* FreeType bbox computation (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used */ -/* modified and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This component has a _single_ role: to compute exact outline bounding */ - /* boxes. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_BBOX_H -#include FT_IMAGE_H -#include FT_OUTLINE_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_OBJECTS_H - - - typedef struct TBBox_Rec_ - { - FT_Vector last; - FT_BBox bbox; - - } TBBox_Rec; - - -#define FT_UPDATE_BBOX( p, bbox ) \ - FT_BEGIN_STMNT \ - if ( p->x < bbox.xMin ) \ - bbox.xMin = p->x; \ - if ( p->x > bbox.xMax ) \ - bbox.xMax = p->x; \ - if ( p->y < bbox.yMin ) \ - bbox.yMin = p->y; \ - if ( p->y > bbox.yMax ) \ - bbox.yMax = p->y; \ - FT_END_STMNT - -#define CHECK_X( p, bbox ) \ - ( p->x < bbox.xMin || p->x > bbox.xMax ) - -#define CHECK_Y( p, bbox ) \ - ( p->y < bbox.yMin || p->y > bbox.yMax ) - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* BBox_Move_To */ - /* */ - /* <Description> */ - /* This function is used as a `move_to' emitter during */ - /* FT_Outline_Decompose(). It simply records the destination point */ - /* in `user->last'. We also update bbox in case contour starts with */ - /* an implicit `on' point. */ - /* */ - /* <Input> */ - /* to :: A pointer to the destination vector. */ - /* */ - /* <InOut> */ - /* user :: A pointer to the current walk context. */ - /* */ - /* <Return> */ - /* Always 0. Needed for the interface only. */ - /* */ - static int - BBox_Move_To( FT_Vector* to, - TBBox_Rec* user ) - { - FT_UPDATE_BBOX( to, user->bbox ); - - user->last = *to; - - return 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* BBox_Line_To */ - /* */ - /* <Description> */ - /* This function is used as a `line_to' emitter during */ - /* FT_Outline_Decompose(). It simply records the destination point */ - /* in `user->last'; no further computations are necessary because */ - /* bbox already contains both explicit ends of the line segment. */ - /* */ - /* <Input> */ - /* to :: A pointer to the destination vector. */ - /* */ - /* <InOut> */ - /* user :: A pointer to the current walk context. */ - /* */ - /* <Return> */ - /* Always 0. Needed for the interface only. */ - /* */ - static int - BBox_Line_To( FT_Vector* to, - TBBox_Rec* user ) - { - user->last = *to; - - return 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* BBox_Conic_Check */ - /* */ - /* <Description> */ - /* Find the extrema of a 1-dimensional conic Bezier curve and update */ - /* a bounding range. This version uses direct computation, as it */ - /* doesn't need square roots. */ - /* */ - /* <Input> */ - /* y1 :: The start coordinate. */ - /* */ - /* y2 :: The coordinate of the control point. */ - /* */ - /* y3 :: The end coordinate. */ - /* */ - /* <InOut> */ - /* min :: The address of the current minimum. */ - /* */ - /* max :: The address of the current maximum. */ - /* */ - static void - BBox_Conic_Check( FT_Pos y1, - FT_Pos y2, - FT_Pos y3, - FT_Pos* min, - FT_Pos* max ) - { - /* This function is only called when a control off-point is outside */ - /* the bbox that contains all on-points. It finds a local extremum */ - /* within the segment, equal to (y1*y3 - y2*y2)/(y1 - 2*y2 + y3). */ - /* Or, offsetting from y2, we get */ - - y1 -= y2; - y3 -= y2; - y2 += FT_MulDiv( y1, y3, y1 + y3 ); - - if ( y2 < *min ) - *min = y2; - if ( y2 > *max ) - *max = y2; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* BBox_Conic_To */ - /* */ - /* <Description> */ - /* This function is used as a `conic_to' emitter during */ - /* FT_Outline_Decompose(). It checks a conic Bezier curve with the */ - /* current bounding box, and computes its extrema if necessary to */ - /* update it. */ - /* */ - /* <Input> */ - /* control :: A pointer to a control point. */ - /* */ - /* to :: A pointer to the destination vector. */ - /* */ - /* <InOut> */ - /* user :: The address of the current walk context. */ - /* */ - /* <Return> */ - /* Always 0. Needed for the interface only. */ - /* */ - /* <Note> */ - /* In the case of a non-monotonous arc, we compute directly the */ - /* extremum coordinates, as it is sufficiently fast. */ - /* */ - static int - BBox_Conic_To( FT_Vector* control, - FT_Vector* to, - TBBox_Rec* user ) - { - /* in case `to' is implicit and not included in bbox yet */ - FT_UPDATE_BBOX( to, user->bbox ); - - if ( CHECK_X( control, user->bbox ) ) - BBox_Conic_Check( user->last.x, - control->x, - to->x, - &user->bbox.xMin, - &user->bbox.xMax ); - - if ( CHECK_Y( control, user->bbox ) ) - BBox_Conic_Check( user->last.y, - control->y, - to->y, - &user->bbox.yMin, - &user->bbox.yMax ); - - user->last = *to; - - return 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* BBox_Cubic_Check */ - /* */ - /* <Description> */ - /* Find the extrema of a 1-dimensional cubic Bezier curve and */ - /* update a bounding range. This version uses iterative splitting */ - /* because it is faster than the exact solution with square roots. */ - /* */ - /* <Input> */ - /* p1 :: The start coordinate. */ - /* */ - /* p2 :: The coordinate of the first control point. */ - /* */ - /* p3 :: The coordinate of the second control point. */ - /* */ - /* p4 :: The end coordinate. */ - /* */ - /* <InOut> */ - /* min :: The address of the current minimum. */ - /* */ - /* max :: The address of the current maximum. */ - /* */ - static FT_Pos - cubic_peak( FT_Pos q1, - FT_Pos q2, - FT_Pos q3, - FT_Pos q4 ) - { - FT_Pos peak = 0; - FT_Int shift; - - - /* This function finds a peak of a cubic segment if it is above 0 */ - /* using iterative bisection of the segment, or returns 0. */ - /* The fixed-point arithmetic of bisection is inherently stable */ - /* but may loose accuracy in the two lowest bits. To compensate, */ - /* we upscale the segment if there is room. Large values may need */ - /* to be downscaled to avoid overflows during bisection. */ - /* It is called with either q2 or q3 positive, which is necessary */ - /* for the peak to exist and avoids undefined FT_MSB. */ - - shift = 27 - FT_MSB( (FT_UInt32)( FT_ABS( q1 ) | - FT_ABS( q2 ) | - FT_ABS( q3 ) | - FT_ABS( q4 ) ) ); - - if ( shift > 0 ) - { - /* upscaling too much just wastes time */ - if ( shift > 2 ) - shift = 2; - - q1 <<= shift; - q2 <<= shift; - q3 <<= shift; - q4 <<= shift; - } - else - { - q1 >>= -shift; - q2 >>= -shift; - q3 >>= -shift; - q4 >>= -shift; - } - - /* for a peak to exist above 0, the cubic segment must have */ - /* at least one of its control off-points above 0. */ - while ( q2 > 0 || q3 > 0 ) - { - /* determine which half contains the maximum and split */ - if ( q1 + q2 > q3 + q4 ) /* first half */ - { - q4 = q4 + q3; - q3 = q3 + q2; - q2 = q2 + q1; - q4 = q4 + q3; - q3 = q3 + q2; - q4 = ( q4 + q3 ) / 8; - q3 = q3 / 4; - q2 = q2 / 2; - } - else /* second half */ - { - q1 = q1 + q2; - q2 = q2 + q3; - q3 = q3 + q4; - q1 = q1 + q2; - q2 = q2 + q3; - q1 = ( q1 + q2 ) / 8; - q2 = q2 / 4; - q3 = q3 / 2; - } - - /* check whether either end reached the maximum */ - if ( q1 == q2 && q1 >= q3 ) - { - peak = q1; - break; - } - if ( q3 == q4 && q2 <= q4 ) - { - peak = q4; - break; - } - } - - if ( shift > 0 ) - peak >>= shift; - else - peak <<= -shift; - - return peak; - } - - - static void - BBox_Cubic_Check( FT_Pos p1, - FT_Pos p2, - FT_Pos p3, - FT_Pos p4, - FT_Pos* min, - FT_Pos* max ) - { - /* This function is only called when a control off-point is outside */ - /* the bbox that contains all on-points. So at least one of the */ - /* conditions below holds and cubic_peak is called with at least one */ - /* non-zero argument. */ - - if ( p2 > *max || p3 > *max ) - *max += cubic_peak( p1 - *max, p2 - *max, p3 - *max, p4 - *max ); - - /* now flip the signs to update the minimum */ - if ( p2 < *min || p3 < *min ) - *min -= cubic_peak( *min - p1, *min - p2, *min - p3, *min - p4 ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* BBox_Cubic_To */ - /* */ - /* <Description> */ - /* This function is used as a `cubic_to' emitter during */ - /* FT_Outline_Decompose(). It checks a cubic Bezier curve with the */ - /* current bounding box, and computes its extrema if necessary to */ - /* update it. */ - /* */ - /* <Input> */ - /* control1 :: A pointer to the first control point. */ - /* */ - /* control2 :: A pointer to the second control point. */ - /* */ - /* to :: A pointer to the destination vector. */ - /* */ - /* <InOut> */ - /* user :: The address of the current walk context. */ - /* */ - /* <Return> */ - /* Always 0. Needed for the interface only. */ - /* */ - /* <Note> */ - /* In the case of a non-monotonous arc, we don't compute directly */ - /* extremum coordinates, we subdivide instead. */ - /* */ - static int - BBox_Cubic_To( FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to, - TBBox_Rec* user ) - { - /* We don't need to check `to' since it is always an on-point, */ - /* thus within the bbox. Only segments with an off-point outside */ - /* the bbox can possibly reach new extreme values. */ - - if ( CHECK_X( control1, user->bbox ) || - CHECK_X( control2, user->bbox ) ) - BBox_Cubic_Check( user->last.x, - control1->x, - control2->x, - to->x, - &user->bbox.xMin, - &user->bbox.xMax ); - - if ( CHECK_Y( control1, user->bbox ) || - CHECK_Y( control2, user->bbox ) ) - BBox_Cubic_Check( user->last.y, - control1->y, - control2->y, - to->y, - &user->bbox.yMin, - &user->bbox.yMax ); - - user->last = *to; - - return 0; - } - - - FT_DEFINE_OUTLINE_FUNCS(bbox_interface, - (FT_Outline_MoveTo_Func) BBox_Move_To, - (FT_Outline_LineTo_Func) BBox_Line_To, - (FT_Outline_ConicTo_Func)BBox_Conic_To, - (FT_Outline_CubicTo_Func)BBox_Cubic_To, - 0, 0 - ) - - - /* documentation is in ftbbox.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Get_BBox( FT_Outline* outline, - FT_BBox *abbox ) - { - FT_BBox cbox = { 0x7FFFFFFFL, 0x7FFFFFFFL, - -0x7FFFFFFFL, -0x7FFFFFFFL }; - FT_BBox bbox = { 0x7FFFFFFFL, 0x7FFFFFFFL, - -0x7FFFFFFFL, -0x7FFFFFFFL }; - FT_Vector* vec; - FT_UShort n; - - - if ( !abbox ) - return FT_THROW( Invalid_Argument ); - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - /* if outline is empty, return (0,0,0,0) */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) - { - abbox->xMin = abbox->xMax = 0; - abbox->yMin = abbox->yMax = 0; - return 0; - } - - /* We compute the control box as well as the bounding box of */ - /* all `on' points in the outline. Then, if the two boxes */ - /* coincide, we exit immediately. */ - - vec = outline->points; - - for ( n = 0; n < outline->n_points; n++ ) - { - FT_UPDATE_BBOX( vec, cbox); - - if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON ) - FT_UPDATE_BBOX( vec, bbox); - - vec++; - } - - /* test two boxes for equality */ - if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax || - cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax ) - { - /* the two boxes are different, now walk over the outline to */ - /* get the Bezier arc extrema. */ - - FT_Error error; - TBBox_Rec user; - -#ifdef FT_CONFIG_OPTION_PIC - FT_Outline_Funcs bbox_interface; - Init_Class_bbox_interface(&bbox_interface); -#endif - - user.bbox = bbox; - - error = FT_Outline_Decompose( outline, &bbox_interface, &user ); - if ( error ) - return error; - - *abbox = user.bbox; - } - else - *abbox = bbox; - - return FT_Err_Ok; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftbdf.c b/third_party/freetype/src/base/ftbdf.c deleted file mode 100644 index aa72ddcdf9ddc964fe6168cb213e90923e8b8b15..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftbdf.c +++ /dev/null @@ -1,91 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbdf.c */ -/* */ -/* FreeType API for accessing BDF-specific strings (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_BDF_H - - - /* documentation is in ftbdf.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_BDF_Charset_ID( FT_Face face, - const char* *acharset_encoding, - const char* *acharset_registry ) - { - FT_Error error; - const char* encoding = NULL; - const char* registry = NULL; - - FT_Service_BDF service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - FT_FACE_FIND_SERVICE( face, service, BDF ); - - if ( service && service->get_charset_id ) - error = service->get_charset_id( face, &encoding, ®istry ); - else - error = FT_THROW( Invalid_Argument ); - - if ( acharset_encoding ) - *acharset_encoding = encoding; - - if ( acharset_registry ) - *acharset_registry = registry; - - return error; - } - - - /* documentation is in ftbdf.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_BDF_Property( FT_Face face, - const char* prop_name, - BDF_PropertyRec *aproperty ) - { - FT_Error error; - - FT_Service_BDF service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !aproperty ) - return FT_THROW( Invalid_Argument ); - - aproperty->type = BDF_PROPERTY_TYPE_NONE; - - FT_FACE_FIND_SERVICE( face, service, BDF ); - - if ( service && service->get_property ) - error = service->get_property( face, prop_name, aproperty ); - else - error = FT_THROW( Invalid_Argument ); - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftbitmap.c b/third_party/freetype/src/base/ftbitmap.c deleted file mode 100644 index a54572aaa2aefde360d5ef6c938992a52a27e130..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftbitmap.c +++ /dev/null @@ -1,809 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftbitmap.c */ -/* */ -/* FreeType utility functions for bitmaps (body). */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_BITMAP_H -#include FT_IMAGE_H -#include FT_INTERNAL_OBJECTS_H - - - static - const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - - /* documentation is in ftbitmap.h */ - - FT_EXPORT_DEF( void ) - FT_Bitmap_Init( FT_Bitmap *abitmap ) - { - if ( abitmap ) - *abitmap = null_bitmap; - } - - - /* deprecated function name; retained for ABI compatibility */ - - FT_EXPORT_DEF( void ) - FT_Bitmap_New( FT_Bitmap *abitmap ) - { - if ( abitmap ) - *abitmap = null_bitmap; - } - - - /* documentation is in ftbitmap.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Bitmap_Copy( FT_Library library, - const FT_Bitmap *source, - FT_Bitmap *target) - { - FT_Memory memory; - FT_Error error = FT_Err_Ok; - - FT_Int pitch; - FT_ULong size; - - FT_Int source_pitch_sign, target_pitch_sign; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !source || !target ) - return FT_THROW( Invalid_Argument ); - - if ( source == target ) - return FT_Err_Ok; - - source_pitch_sign = source->pitch < 0 ? -1 : 1; - target_pitch_sign = target->pitch < 0 ? -1 : 1; - - if ( source->buffer == NULL ) - { - *target = *source; - if ( source_pitch_sign != target_pitch_sign ) - target->pitch = -target->pitch; - - return FT_Err_Ok; - } - - memory = library->memory; - pitch = source->pitch; - - if ( pitch < 0 ) - pitch = -pitch; - size = (FT_ULong)pitch * source->rows; - - if ( target->buffer ) - { - FT_Int target_pitch = target->pitch; - FT_ULong target_size; - - - if ( target_pitch < 0 ) - target_pitch = -target_pitch; - target_size = (FT_ULong)target_pitch * target->rows; - - if ( target_size != size ) - (void)FT_QREALLOC( target->buffer, target_size, size ); - } - else - (void)FT_QALLOC( target->buffer, size ); - - if ( !error ) - { - unsigned char *p; - - - p = target->buffer; - *target = *source; - target->buffer = p; - - if ( source_pitch_sign == target_pitch_sign ) - FT_MEM_COPY( target->buffer, source->buffer, size ); - else - { - /* take care of bitmap flow */ - FT_UInt i; - FT_Byte* s = source->buffer; - FT_Byte* t = target->buffer; - - - t += (FT_ULong)pitch * ( target->rows - 1 ); - - for ( i = target->rows; i > 0; i-- ) - { - FT_ARRAY_COPY( t, s, pitch ); - - s += pitch; - t -= pitch; - } - } - } - - return error; - } - - - /* Enlarge `bitmap' horizontally and vertically by `xpixels' */ - /* and `ypixels', respectively. */ - - static FT_Error - ft_bitmap_assure_buffer( FT_Memory memory, - FT_Bitmap* bitmap, - FT_UInt xpixels, - FT_UInt ypixels ) - { - FT_Error error; - int pitch; - int new_pitch; - FT_UInt bpp; - FT_UInt i, width, height; - unsigned char* buffer = NULL; - - - width = bitmap->width; - height = bitmap->rows; - pitch = bitmap->pitch; - if ( pitch < 0 ) - pitch = -pitch; - - switch ( bitmap->pixel_mode ) - { - case FT_PIXEL_MODE_MONO: - bpp = 1; - new_pitch = (int)( ( width + xpixels + 7 ) >> 3 ); - break; - case FT_PIXEL_MODE_GRAY2: - bpp = 2; - new_pitch = (int)( ( width + xpixels + 3 ) >> 2 ); - break; - case FT_PIXEL_MODE_GRAY4: - bpp = 4; - new_pitch = (int)( ( width + xpixels + 1 ) >> 1 ); - break; - case FT_PIXEL_MODE_GRAY: - case FT_PIXEL_MODE_LCD: - case FT_PIXEL_MODE_LCD_V: - bpp = 8; - new_pitch = (int)( width + xpixels ); - break; - default: - return FT_THROW( Invalid_Glyph_Format ); - } - - /* if no need to allocate memory */ - if ( ypixels == 0 && new_pitch <= pitch ) - { - /* zero the padding */ - FT_UInt bit_width = (FT_UInt)pitch * 8; - FT_UInt bit_last = ( width + xpixels ) * bpp; - - - if ( bit_last < bit_width ) - { - FT_Byte* line = bitmap->buffer + ( bit_last >> 3 ); - FT_Byte* end = bitmap->buffer + pitch; - FT_UInt shift = bit_last & 7; - FT_UInt mask = 0xFF00U >> shift; - FT_UInt count = height; - - - for ( ; count > 0; count--, line += pitch, end += pitch ) - { - FT_Byte* write = line; - - - if ( shift > 0 ) - { - write[0] = (FT_Byte)( write[0] & mask ); - write++; - } - if ( write < end ) - FT_MEM_ZERO( write, end - write ); - } - } - - return FT_Err_Ok; - } - - /* otherwise allocate new buffer */ - if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) ) - return error; - - /* new rows get added at the top of the bitmap, */ - /* thus take care of the flow direction */ - if ( bitmap->pitch > 0 ) - { - FT_UInt len = ( width * bpp + 7 ) >> 3; - - - for ( i = 0; i < bitmap->rows; i++ ) - FT_MEM_COPY( buffer + (FT_UInt)new_pitch * ( ypixels + i ), - bitmap->buffer + (FT_UInt)pitch * i, - len ); - } - else - { - FT_UInt len = ( width * bpp + 7 ) >> 3; - - - for ( i = 0; i < bitmap->rows; i++ ) - FT_MEM_COPY( buffer + (FT_UInt)new_pitch * i, - bitmap->buffer + (FT_UInt)pitch * i, - len ); - } - - FT_FREE( bitmap->buffer ); - bitmap->buffer = buffer; - - if ( bitmap->pitch < 0 ) - new_pitch = -new_pitch; - - /* set pitch only, width and height are left untouched */ - bitmap->pitch = new_pitch; - - return FT_Err_Ok; - } - - - /* documentation is in ftbitmap.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Bitmap_Embolden( FT_Library library, - FT_Bitmap* bitmap, - FT_Pos xStrength, - FT_Pos yStrength ) - { - FT_Error error; - unsigned char* p; - FT_Int i, x, pitch; - FT_UInt y; - FT_Int xstr, ystr; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !bitmap || !bitmap->buffer ) - return FT_THROW( Invalid_Argument ); - - if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) || - ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) ) - return FT_THROW( Invalid_Argument ); - - xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6; - ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6; - - if ( xstr == 0 && ystr == 0 ) - return FT_Err_Ok; - else if ( xstr < 0 || ystr < 0 ) - return FT_THROW( Invalid_Argument ); - - switch ( bitmap->pixel_mode ) - { - case FT_PIXEL_MODE_GRAY2: - case FT_PIXEL_MODE_GRAY4: - { - FT_Bitmap tmp; - - - /* convert to 8bpp */ - FT_Bitmap_Init( &tmp ); - error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 ); - if ( error ) - return error; - - FT_Bitmap_Done( library, bitmap ); - *bitmap = tmp; - } - break; - - case FT_PIXEL_MODE_MONO: - if ( xstr > 8 ) - xstr = 8; - break; - - case FT_PIXEL_MODE_LCD: - xstr *= 3; - break; - - case FT_PIXEL_MODE_LCD_V: - ystr *= 3; - break; - - case FT_PIXEL_MODE_BGRA: - /* We don't embolden color glyphs. */ - return FT_Err_Ok; - } - - error = ft_bitmap_assure_buffer( library->memory, bitmap, - (FT_UInt)xstr, (FT_UInt)ystr ); - if ( error ) - return error; - - /* take care of bitmap flow */ - pitch = bitmap->pitch; - if ( pitch > 0 ) - p = bitmap->buffer + pitch * ystr; - else - { - pitch = -pitch; - p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 ); - } - - /* for each row */ - for ( y = 0; y < bitmap->rows ; y++ ) - { - /* - * Horizontally: - * - * From the last pixel on, make each pixel or'ed with the - * `xstr' pixels before it. - */ - for ( x = pitch - 1; x >= 0; x-- ) - { - unsigned char tmp; - - - tmp = p[x]; - for ( i = 1; i <= xstr; i++ ) - { - if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO ) - { - p[x] |= tmp >> i; - - /* the maximum value of 8 for `xstr' comes from here */ - if ( x > 0 ) - p[x] |= p[x - 1] << ( 8 - i ); - -#if 0 - if ( p[x] == 0xFF ) - break; -#endif - } - else - { - if ( x - i >= 0 ) - { - if ( p[x] + p[x - i] > bitmap->num_grays - 1 ) - { - p[x] = (unsigned char)( bitmap->num_grays - 1 ); - break; - } - else - { - p[x] = (unsigned char)( p[x] + p[x - i] ); - if ( p[x] == bitmap->num_grays - 1 ) - break; - } - } - else - break; - } - } - } - - /* - * Vertically: - * - * Make the above `ystr' rows or'ed with it. - */ - for ( x = 1; x <= ystr; x++ ) - { - unsigned char* q; - - - q = p - bitmap->pitch * x; - for ( i = 0; i < pitch; i++ ) - q[i] |= p[i]; - } - - p += bitmap->pitch; - } - - bitmap->width += (FT_UInt)xstr; - bitmap->rows += (FT_UInt)ystr; - - return FT_Err_Ok; - } - - - static FT_Byte - ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra ) - { - FT_UInt a = bgra[3]; - FT_UInt l; - - - /* Short-circuit transparent color to avoid division by zero. */ - if ( !a ) - return 0; - - /* - * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722 - * coefficients for RGB channels *on the linear colors*. - * A gamma of 2.2 is fair to assume. And then, we need to - * undo the premultiplication too. - * - * http://accessibility.kde.org/hsl-adjusted.php - * - * We do the computation with integers only, applying a gamma of 2.0. - * We guarantee 32-bit arithmetic to avoid overflow but the resulting - * luminosity fits into 16 bits. - * - */ - - l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + - 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + - 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; - - /* - * Final transparency can be determined as follows. - * - * - If alpha is zero, we want 0. - * - If alpha is zero and luminosity is zero, we want 255. - * - If alpha is zero and luminosity is one, we want 0. - * - * So the formula is a * (1 - l) = a - l * a. - * - * We still need to undo premultiplication by dividing l by a*a. - * - */ - - return (FT_Byte)( a - l / a ); - } - - - /* documentation is in ftbitmap.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Bitmap_Convert( FT_Library library, - const FT_Bitmap *source, - FT_Bitmap *target, - FT_Int alignment ) - { - FT_Error error = FT_Err_Ok; - FT_Memory memory; - - FT_Byte* s; - FT_Byte* t; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !source || !target ) - return FT_THROW( Invalid_Argument ); - - memory = library->memory; - - switch ( source->pixel_mode ) - { - case FT_PIXEL_MODE_MONO: - case FT_PIXEL_MODE_GRAY: - case FT_PIXEL_MODE_GRAY2: - case FT_PIXEL_MODE_GRAY4: - case FT_PIXEL_MODE_LCD: - case FT_PIXEL_MODE_LCD_V: - case FT_PIXEL_MODE_BGRA: - { - FT_Int pad, old_target_pitch, target_pitch; - FT_ULong old_size; - - - old_target_pitch = target->pitch; - if ( old_target_pitch < 0 ) - old_target_pitch = -old_target_pitch; - - old_size = target->rows * (FT_UInt)old_target_pitch; - - target->pixel_mode = FT_PIXEL_MODE_GRAY; - target->rows = source->rows; - target->width = source->width; - - pad = 0; - if ( alignment > 0 ) - { - pad = (FT_Int)source->width % alignment; - if ( pad != 0 ) - pad = alignment - pad; - } - - target_pitch = (FT_Int)source->width + pad; - - if ( target_pitch > 0 && - (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch ) - return FT_THROW( Invalid_Argument ); - - if ( target->rows * (FT_ULong)target_pitch > old_size && - FT_QREALLOC( target->buffer, - old_size, target->rows * (FT_UInt)target_pitch ) ) - return error; - - target->pitch = target->pitch < 0 ? -target_pitch : target_pitch; - } - break; - - default: - error = FT_THROW( Invalid_Argument ); - } - - s = source->buffer; - t = target->buffer; - - /* take care of bitmap flow */ - if ( source->pitch < 0 ) - s -= source->pitch * (FT_Int)( source->rows - 1 ); - if ( target->pitch < 0 ) - t -= target->pitch * (FT_Int)( target->rows - 1 ); - - switch ( source->pixel_mode ) - { - case FT_PIXEL_MODE_MONO: - { - FT_UInt i; - - - target->num_grays = 2; - - for ( i = source->rows; i > 0; i-- ) - { - FT_Byte* ss = s; - FT_Byte* tt = t; - FT_UInt j; - - - /* get the full bytes */ - for ( j = source->width >> 3; j > 0; j-- ) - { - FT_Int val = ss[0]; /* avoid a byte->int cast on each line */ - - - tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 ); - tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 ); - tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 ); - tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 ); - tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 ); - tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 ); - tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 ); - tt[7] = (FT_Byte)( val & 0x01 ); - - tt += 8; - ss += 1; - } - - /* get remaining pixels (if any) */ - j = source->width & 7; - if ( j > 0 ) - { - FT_Int val = *ss; - - - for ( ; j > 0; j-- ) - { - tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7); - val <<= 1; - tt += 1; - } - } - - s += source->pitch; - t += target->pitch; - } - } - break; - - - case FT_PIXEL_MODE_GRAY: - case FT_PIXEL_MODE_LCD: - case FT_PIXEL_MODE_LCD_V: - { - FT_UInt width = source->width; - FT_UInt i; - - - target->num_grays = 256; - - for ( i = source->rows; i > 0; i-- ) - { - FT_ARRAY_COPY( t, s, width ); - - s += source->pitch; - t += target->pitch; - } - } - break; - - - case FT_PIXEL_MODE_GRAY2: - { - FT_UInt i; - - - target->num_grays = 4; - - for ( i = source->rows; i > 0; i-- ) - { - FT_Byte* ss = s; - FT_Byte* tt = t; - FT_UInt j; - - - /* get the full bytes */ - for ( j = source->width >> 2; j > 0; j-- ) - { - FT_Int val = ss[0]; - - - tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); - tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 ); - tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 ); - tt[3] = (FT_Byte)( ( val & 0x03 ) ); - - ss += 1; - tt += 4; - } - - j = source->width & 3; - if ( j > 0 ) - { - FT_Int val = ss[0]; - - - for ( ; j > 0; j-- ) - { - tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); - val <<= 2; - tt += 1; - } - } - - s += source->pitch; - t += target->pitch; - } - } - break; - - - case FT_PIXEL_MODE_GRAY4: - { - FT_UInt i; - - - target->num_grays = 16; - - for ( i = source->rows; i > 0; i-- ) - { - FT_Byte* ss = s; - FT_Byte* tt = t; - FT_UInt j; - - - /* get the full bytes */ - for ( j = source->width >> 1; j > 0; j-- ) - { - FT_Int val = ss[0]; - - - tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 ); - tt[1] = (FT_Byte)( ( val & 0x0F ) ); - - ss += 1; - tt += 2; - } - - if ( source->width & 1 ) - tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 ); - - s += source->pitch; - t += target->pitch; - } - } - break; - - - case FT_PIXEL_MODE_BGRA: - { - FT_UInt i; - - - target->num_grays = 256; - - for ( i = source->rows; i > 0; i-- ) - { - FT_Byte* ss = s; - FT_Byte* tt = t; - FT_UInt j; - - - for ( j = source->width; j > 0; j-- ) - { - tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss ); - - ss += 4; - tt += 1; - } - - s += source->pitch; - t += target->pitch; - } - } - break; - - default: - ; - } - - return error; - } - - - /* documentation is in ftbitmap.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ) - { - if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP && - !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) - { - FT_Bitmap bitmap; - FT_Error error; - - - FT_Bitmap_Init( &bitmap ); - error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap ); - if ( error ) - return error; - - slot->bitmap = bitmap; - slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - } - - return FT_Err_Ok; - } - - - /* documentation is in ftbitmap.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Bitmap_Done( FT_Library library, - FT_Bitmap *bitmap ) - { - FT_Memory memory; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !bitmap ) - return FT_THROW( Invalid_Argument ); - - memory = library->memory; - - FT_FREE( bitmap->buffer ); - *bitmap = null_bitmap; - - return FT_Err_Ok; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftcalc.c b/third_party/freetype/src/base/ftcalc.c deleted file mode 100644 index 619a08b3a0c3e2a2a60399b4579605b46ef37388..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftcalc.c +++ /dev/null @@ -1,1003 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftcalc.c */ -/* */ -/* Arithmetic computations (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* Support for 1-complement arithmetic has been totally dropped in this */ - /* release. You can still write your own code if you need it. */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* Implementing basic computation routines. */ - /* */ - /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */ - /* and FT_FloorFix() are declared in freetype.h. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_GLYPH_H -#include FT_TRIGONOMETRY_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H - - -#ifdef FT_MULFIX_ASSEMBLER -#undef FT_MulFix -#endif - -/* we need to emulate a 64-bit data type if a real one isn't available */ - -#ifndef FT_LONG64 - - typedef struct FT_Int64_ - { - FT_UInt32 lo; - FT_UInt32 hi; - - } FT_Int64; - -#endif /* !FT_LONG64 */ - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_calc - - - /* transfer sign leaving a positive number */ -#define FT_MOVE_SIGN( x, s ) \ - FT_BEGIN_STMNT \ - if ( x < 0 ) \ - { \ - x = -x; \ - s = -s; \ - } \ - FT_END_STMNT - - /* The following three functions are available regardless of whether */ - /* FT_LONG64 is defined. */ - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_RoundFix( FT_Fixed a ) - { - return ( a + 0x8000L - ( a < 0 ) ) & ~0xFFFFL; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_CeilFix( FT_Fixed a ) - { - return ( a + 0xFFFFL ) & ~0xFFFFL; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_FloorFix( FT_Fixed a ) - { - return a & ~0xFFFFL; - } - -#ifndef FT_MSB - - FT_BASE_DEF ( FT_Int ) - FT_MSB( FT_UInt32 z ) - { - FT_Int shift = 0; - - - /* determine msb bit index in `shift' */ - if ( z & 0xFFFF0000UL ) - { - z >>= 16; - shift += 16; - } - if ( z & 0x0000FF00UL ) - { - z >>= 8; - shift += 8; - } - if ( z & 0x000000F0UL ) - { - z >>= 4; - shift += 4; - } - if ( z & 0x0000000CUL ) - { - z >>= 2; - shift += 2; - } - if ( z & 0x00000002UL ) - { - /* z >>= 1; */ - shift += 1; - } - - return shift; - } - -#endif /* !FT_MSB */ - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( FT_Fixed ) - FT_Hypot( FT_Fixed x, - FT_Fixed y ) - { - FT_Vector v; - - - v.x = x; - v.y = y; - - return FT_Vector_Length( &v ); - } - - -#ifdef FT_LONG64 - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_MulDiv( FT_Long a_, - FT_Long b_, - FT_Long c_ ) - { - FT_Int s = 1; - FT_UInt64 a, b, c, d; - FT_Long d_; - - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - - a = (FT_UInt64)a_; - b = (FT_UInt64)b_; - c = (FT_UInt64)c_; - - d = c > 0 ? ( a * b + ( c >> 1 ) ) / c - : 0x7FFFFFFFUL; - - d_ = (FT_Long)d; - - return s < 0 ? -d_ : d_; - } - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( FT_Long ) - FT_MulDiv_No_Round( FT_Long a_, - FT_Long b_, - FT_Long c_ ) - { - FT_Int s = 1; - FT_UInt64 a, b, c, d; - FT_Long d_; - - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - - a = (FT_UInt64)a_; - b = (FT_UInt64)b_; - c = (FT_UInt64)c_; - - d = c > 0 ? a * b / c - : 0x7FFFFFFFUL; - - d_ = (FT_Long)d; - - return s < 0 ? -d_ : d_; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_MulFix( FT_Long a_, - FT_Long b_ ) - { -#ifdef FT_MULFIX_ASSEMBLER - - return FT_MULFIX_ASSEMBLER( a_, b_ ); - -#else - - FT_Int64 ab = (FT_Int64)a_ * (FT_Int64)b_; - - /* this requires arithmetic right shift of signed numbers */ - return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 ); - -#endif /* FT_MULFIX_ASSEMBLER */ - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_DivFix( FT_Long a_, - FT_Long b_ ) - { - FT_Int s = 1; - FT_UInt64 a, b, q; - FT_Long q_; - - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - - a = (FT_UInt64)a_; - b = (FT_UInt64)b_; - - q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b - : 0x7FFFFFFFUL; - - q_ = (FT_Long)q; - - return s < 0 ? -q_ : q_; - } - - -#else /* !FT_LONG64 */ - - - static void - ft_multo64( FT_UInt32 x, - FT_UInt32 y, - FT_Int64 *z ) - { - FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; - - - lo1 = x & 0x0000FFFFU; hi1 = x >> 16; - lo2 = y & 0x0000FFFFU; hi2 = y >> 16; - - lo = lo1 * lo2; - i1 = lo1 * hi2; - i2 = lo2 * hi1; - hi = hi1 * hi2; - - /* Check carry overflow of i1 + i2 */ - i1 += i2; - hi += (FT_UInt32)( i1 < i2 ) << 16; - - hi += i1 >> 16; - i1 = i1 << 16; - - /* Check carry overflow of i1 + lo */ - lo += i1; - hi += ( lo < i1 ); - - z->lo = lo; - z->hi = hi; - } - - - static FT_UInt32 - ft_div64by32( FT_UInt32 hi, - FT_UInt32 lo, - FT_UInt32 y ) - { - FT_UInt32 r, q; - FT_Int i; - - - if ( hi >= y ) - return (FT_UInt32)0x7FFFFFFFL; - - /* We shift as many bits as we can into the high register, perform */ - /* 32-bit division with modulo there, then work through the remaining */ - /* bits with long division. This optimization is especially noticeable */ - /* for smaller dividends that barely use the high register. */ - - i = 31 - FT_MSB( hi ); - r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */ - q = r / y; - r -= q * y; /* remainder */ - - i = 32 - i; /* bits remaining in low register */ - do - { - q <<= 1; - r = ( r << 1 ) | ( lo >> 31 ); lo <<= 1; - - if ( r >= y ) - { - r -= y; - q |= 1; - } - } while ( --i ); - - return q; - } - - - static void - FT_Add64( FT_Int64* x, - FT_Int64* y, - FT_Int64 *z ) - { - FT_UInt32 lo, hi; - - - lo = x->lo + y->lo; - hi = x->hi + y->hi + ( lo < x->lo ); - - z->lo = lo; - z->hi = hi; - } - - - /* The FT_MulDiv function has been optimized thanks to ideas from */ - /* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */ - /* a rather common case when everything fits within 32-bits. */ - /* */ - /* We compute 'a*b+c/2', then divide it by 'c' (all positive values). */ - /* */ - /* The product of two positive numbers never exceeds the square of */ - /* its mean values. Therefore, we always avoid the overflow by */ - /* imposing */ - /* */ - /* (a + b) / 2 <= sqrt(X - c/2) , */ - /* */ - /* where X = 2^32 - 1, the maximum unsigned 32-bit value, and using */ - /* unsigned arithmetic. Now we replace `sqrt' with a linear function */ - /* that is smaller or equal for all values of c in the interval */ - /* [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the */ - /* endpoints. Substituting the linear solution and explicit numbers */ - /* we get */ - /* */ - /* a + b <= 131071.99 - c / 122291.84 . */ - /* */ - /* In practice, we should use a faster and even stronger inequality */ - /* */ - /* a + b <= 131071 - (c >> 16) */ - /* */ - /* or, alternatively, */ - /* */ - /* a + b <= 129894 - (c >> 17) . */ - /* */ - /* FT_MulFix, on the other hand, is optimized for a small value of */ - /* the first argument, when the second argument can be much larger. */ - /* This can be achieved by scaling the second argument and the limit */ - /* in the above inequalities. For example, */ - /* */ - /* a + (b >> 8) <= (131071 >> 4) */ - /* */ - /* covers the practical range of use. The actual test below is a bit */ - /* tighter to avoid the border case overflows. */ - /* */ - /* In the case of FT_DivFix, the exact overflow check */ - /* */ - /* a << 16 <= X - c/2 */ - /* */ - /* is scaled down by 2^16 and we use */ - /* */ - /* a <= 65535 - (c >> 17) . */ - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_MulDiv( FT_Long a_, - FT_Long b_, - FT_Long c_ ) - { - FT_Int s = 1; - FT_UInt32 a, b, c; - - - /* XXX: this function does not allow 64-bit arguments */ - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - c = (FT_UInt32)c_; - - if ( c == 0 ) - a = 0x7FFFFFFFUL; - - else if ( a + b <= 129894UL - ( c >> 17 ) ) - a = ( a * b + ( c >> 1 ) ) / c; - - else - { - FT_Int64 temp, temp2; - - - ft_multo64( a, b, &temp ); - - temp2.hi = 0; - temp2.lo = c >> 1; - - FT_Add64( &temp, &temp2, &temp ); - - /* last attempt to ditch long division */ - a = temp.hi == 0 ? temp.lo / c - : ft_div64by32( temp.hi, temp.lo, c ); - } - - a_ = (FT_Long)a; - - return s < 0 ? -a_ : a_; - } - - - FT_BASE_DEF( FT_Long ) - FT_MulDiv_No_Round( FT_Long a_, - FT_Long b_, - FT_Long c_ ) - { - FT_Int s = 1; - FT_UInt32 a, b, c; - - - /* XXX: this function does not allow 64-bit arguments */ - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - c = (FT_UInt32)c_; - - if ( c == 0 ) - a = 0x7FFFFFFFUL; - - else if ( a + b <= 131071UL ) - a = a * b / c; - - else - { - FT_Int64 temp; - - - ft_multo64( a, b, &temp ); - - /* last attempt to ditch long division */ - a = temp.hi == 0 ? temp.lo / c - : ft_div64by32( temp.hi, temp.lo, c ); - } - - a_ = (FT_Long)a; - - return s < 0 ? -a_ : a_; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_MulFix( FT_Long a_, - FT_Long b_ ) - { -#ifdef FT_MULFIX_ASSEMBLER - - return FT_MULFIX_ASSEMBLER( a_, b_ ); - -#elif 0 - - /* - * This code is nonportable. See comment below. - * - * However, on a platform where right-shift of a signed quantity fills - * the leftmost bits by copying the sign bit, it might be faster. - */ - - FT_Long sa, sb; - FT_UInt32 a, b; - - - /* - * This is a clever way of converting a signed number `a' into its - * absolute value (stored back into `a') and its sign. The sign is - * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a' - * was negative. (Similarly for `b' and `sb'). - * - * Unfortunately, it doesn't work (at least not portably). - * - * It makes the assumption that right-shift on a negative signed value - * fills the leftmost bits by copying the sign bit. This is wrong. - * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206, - * the result of right-shift of a negative signed value is - * implementation-defined. At least one implementation fills the - * leftmost bits with 0s (i.e., it is exactly the same as an unsigned - * right shift). This means that when `a' is negative, `sa' ends up - * with the value 1 rather than -1. After that, everything else goes - * wrong. - */ - sa = ( a_ >> ( sizeof ( a_ ) * 8 - 1 ) ); - a = ( a_ ^ sa ) - sa; - sb = ( b_ >> ( sizeof ( b_ ) * 8 - 1 ) ); - b = ( b_ ^ sb ) - sb; - - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - - if ( a + ( b >> 8 ) <= 8190UL ) - a = ( a * b + 0x8000U ) >> 16; - else - { - FT_UInt32 al = a & 0xFFFFUL; - - - a = ( a >> 16 ) * b + al * ( b >> 16 ) + - ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 ); - } - - sa ^= sb; - a = ( a ^ sa ) - sa; - - return (FT_Long)a; - -#else /* 0 */ - - FT_Int s = 1; - FT_UInt32 a, b; - - - /* XXX: this function does not allow 64-bit arguments */ - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - - if ( a + ( b >> 8 ) <= 8190UL ) - a = ( a * b + 0x8000UL ) >> 16; - else - { - FT_UInt32 al = a & 0xFFFFUL; - - - a = ( a >> 16 ) * b + al * ( b >> 16 ) + - ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 ); - } - - a_ = (FT_Long)a; - - return s < 0 ? -a_ : a_; - -#endif /* 0 */ - - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_DivFix( FT_Long a_, - FT_Long b_ ) - { - FT_Int s = 1; - FT_UInt32 a, b, q; - FT_Long q_; - - - /* XXX: this function does not allow 64-bit arguments */ - - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - - a = (FT_UInt32)a_; - b = (FT_UInt32)b_; - - if ( b == 0 ) - { - /* check for division by 0 */ - q = 0x7FFFFFFFUL; - } - else if ( a <= 65535UL - ( b >> 17 ) ) - { - /* compute result directly */ - q = ( ( a << 16 ) + ( b >> 1 ) ) / b; - } - else - { - /* we need more bits; we have to do it by hand */ - FT_Int64 temp, temp2; - - - temp.hi = a >> 16; - temp.lo = a << 16; - temp2.hi = 0; - temp2.lo = b >> 1; - - FT_Add64( &temp, &temp2, &temp ); - q = ft_div64by32( temp.hi, temp.lo, b ); - } - - q_ = (FT_Long)q; - - return s < 0 ? -q_ : q_; - } - - -#endif /* !FT_LONG64 */ - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( void ) - FT_Matrix_Multiply( const FT_Matrix* a, - FT_Matrix *b ) - { - FT_Fixed xx, xy, yx, yy; - - - if ( !a || !b ) - return; - - xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx ); - xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy ); - yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx ); - yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy ); - - b->xx = xx; b->xy = xy; - b->yx = yx; b->yy = yy; - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Matrix_Invert( FT_Matrix* matrix ) - { - FT_Pos delta, xx, yy; - - - if ( !matrix ) - return FT_THROW( Invalid_Argument ); - - /* compute discriminant */ - delta = FT_MulFix( matrix->xx, matrix->yy ) - - FT_MulFix( matrix->xy, matrix->yx ); - - if ( !delta ) - return FT_THROW( Invalid_Argument ); /* matrix can't be inverted */ - - matrix->xy = - FT_DivFix( matrix->xy, delta ); - matrix->yx = - FT_DivFix( matrix->yx, delta ); - - xx = matrix->xx; - yy = matrix->yy; - - matrix->xx = FT_DivFix( yy, delta ); - matrix->yy = FT_DivFix( xx, delta ); - - return FT_Err_Ok; - } - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( void ) - FT_Matrix_Multiply_Scaled( const FT_Matrix* a, - FT_Matrix *b, - FT_Long scaling ) - { - FT_Fixed xx, xy, yx, yy; - - FT_Long val = 0x10000L * scaling; - - - if ( !a || !b ) - return; - - xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val ); - xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val ); - yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val ); - yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val ); - - b->xx = xx; b->xy = xy; - b->yx = yx; b->yy = yy; - } - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( void ) - FT_Vector_Transform_Scaled( FT_Vector* vector, - const FT_Matrix* matrix, - FT_Long scaling ) - { - FT_Pos xz, yz; - - FT_Long val = 0x10000L * scaling; - - - if ( !vector || !matrix ) - return; - - xz = FT_MulDiv( vector->x, matrix->xx, val ) + - FT_MulDiv( vector->y, matrix->xy, val ); - - yz = FT_MulDiv( vector->x, matrix->yx, val ) + - FT_MulDiv( vector->y, matrix->yy, val ); - - vector->x = xz; - vector->y = yz; - } - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( FT_UInt32 ) - FT_Vector_NormLen( FT_Vector* vector ) - { - FT_Int32 x_ = vector->x; - FT_Int32 y_ = vector->y; - FT_Int32 b, z; - FT_UInt32 x, y, u, v, l; - FT_Int sx = 1, sy = 1, shift; - - - FT_MOVE_SIGN( x_, sx ); - FT_MOVE_SIGN( y_, sy ); - - x = (FT_UInt32)x_; - y = (FT_UInt32)y_; - - /* trivial cases */ - if ( x == 0 ) - { - if ( y > 0 ) - vector->y = sy * 0x10000; - return y; - } - else if ( y == 0 ) - { - if ( x > 0 ) - vector->x = sx * 0x10000; - return x; - } - - /* Estimate length and prenormalize by shifting so that */ - /* the new approximate length is between 2/3 and 4/3. */ - /* The magic constant 0xAAAAAAAAUL (2/3 of 2^32) helps */ - /* achieve this in 16.16 fixed-point representation. */ - l = x > y ? x + ( y >> 1 ) - : y + ( x >> 1 ); - - shift = 31 - FT_MSB( l ); - shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) ); - - if ( shift > 0 ) - { - x <<= shift; - y <<= shift; - - /* re-estimate length for tiny vectors */ - l = x > y ? x + ( y >> 1 ) - : y + ( x >> 1 ); - } - else - { - x >>= -shift; - y >>= -shift; - l >>= -shift; - } - - /* lower linear approximation for reciprocal length minus one */ - b = 0x10000 - (FT_Int32)l; - - x_ = (FT_Int32)x; - y_ = (FT_Int32)y; - - /* Newton's iterations */ - do - { - u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) ); - v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) ); - - /* Normalized squared length in the parentheses approaches 2^32. */ - /* On two's complement systems, converting to signed gives the */ - /* difference with 2^32 even if the expression wraps around. */ - z = -(FT_Int32)( u * u + v * v ) / 0x200; - z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000; - - b += z; - - } while ( z > 0 ); - - vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u; - vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v; - - /* Conversion to signed helps to recover from likely wrap around */ - /* in calculating the prenormalized length, because it gives the */ - /* correct difference with 2^32 on two's complement systems. */ - l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 ); - if ( shift > 0 ) - l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift; - else - l <<= -shift; - - return l; - } - - -#if 0 - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( FT_Int32 ) - FT_SqrtFixed( FT_Int32 x ) - { - FT_UInt32 root, rem_hi, rem_lo, test_div; - FT_Int count; - - - root = 0; - - if ( x > 0 ) - { - rem_hi = 0; - rem_lo = (FT_UInt32)x; - count = 24; - do - { - rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 ); - rem_lo <<= 2; - root <<= 1; - test_div = ( root << 1 ) + 1; - - if ( rem_hi >= test_div ) - { - rem_hi -= test_div; - root += 1; - } - } while ( --count ); - } - - return (FT_Int32)root; - } - -#endif /* 0 */ - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( FT_Int ) - ft_corner_orientation( FT_Pos in_x, - FT_Pos in_y, - FT_Pos out_x, - FT_Pos out_y ) - { -#ifdef FT_LONG64 - - FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x; - - - return ( delta > 0 ) - ( delta < 0 ); - -#else - - FT_Int result; - - - if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 131071UL && - (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 131071UL ) - { - FT_Long z1 = in_x * out_y; - FT_Long z2 = in_y * out_x; - - - if ( z1 > z2 ) - result = +1; - else if ( z1 < z2 ) - result = -1; - else - result = 0; - } - else /* products might overflow 32 bits */ - { - FT_Int64 z1, z2; - - - /* XXX: this function does not allow 64-bit arguments */ - ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 ); - ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 ); - - if ( z1.hi > z2.hi ) - result = +1; - else if ( z1.hi < z2.hi ) - result = -1; - else if ( z1.lo > z2.lo ) - result = +1; - else if ( z1.lo < z2.lo ) - result = -1; - else - result = 0; - } - - /* XXX: only the sign of return value, +1/0/-1 must be used */ - return result; - -#endif - } - - - /* documentation is in ftcalc.h */ - - FT_BASE_DEF( FT_Int ) - ft_corner_is_flat( FT_Pos in_x, - FT_Pos in_y, - FT_Pos out_x, - FT_Pos out_y ) - { - FT_Pos ax = in_x + out_x; - FT_Pos ay = in_y + out_y; - - FT_Pos d_in, d_out, d_hypot; - - - /* The idea of this function is to compare the length of the */ - /* hypotenuse with the `in' and `out' length. The `corner' */ - /* represented by `in' and `out' is flat if the hypotenuse's */ - /* length isn't too large. */ - /* */ - /* This approach has the advantage that the angle between */ - /* `in' and `out' is not checked. In case one of the two */ - /* vectors is `dominant', this is, much larger than the */ - /* other vector, we thus always have a flat corner. */ - /* */ - /* hypotenuse */ - /* x---------------------------x */ - /* \ / */ - /* \ / */ - /* in \ / out */ - /* \ / */ - /* o */ - /* Point */ - - d_in = FT_HYPOT( in_x, in_y ); - d_out = FT_HYPOT( out_x, out_y ); - d_hypot = FT_HYPOT( ax, ay ); - - /* now do a simple length comparison: */ - /* */ - /* d_in + d_out < 17/16 d_hypot */ - - return ( d_in + d_out - d_hypot ) < ( d_hypot >> 4 ); - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftcid.c b/third_party/freetype/src/base/ftcid.c deleted file mode 100644 index 0734881b7190b1d8b2a8259fc554d5177604ff85..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftcid.c +++ /dev/null @@ -1,118 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftcid.c */ -/* */ -/* FreeType API for accessing CID font information. */ -/* */ -/* Copyright 2007-2015 by */ -/* Derek Clegg and Michael Toftdal. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_CID_H -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_CID_H - - - /* documentation is in ftcid.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_CID_Registry_Ordering_Supplement( FT_Face face, - const char* *registry, - const char* *ordering, - FT_Int *supplement) - { - FT_Error error; - const char* r = NULL; - const char* o = NULL; - FT_Int s = 0; - - - error = FT_ERR( Invalid_Argument ); - - if ( face ) - { - FT_Service_CID service; - - - FT_FACE_FIND_SERVICE( face, service, CID ); - - if ( service && service->get_ros ) - error = service->get_ros( face, &r, &o, &s ); - } - - if ( registry ) - *registry = r; - - if ( ordering ) - *ordering = o; - - if ( supplement ) - *supplement = s; - - return error; - } - - - FT_EXPORT_DEF( FT_Error ) - FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face, - FT_Bool *is_cid ) - { - FT_Error error = FT_ERR( Invalid_Argument ); - FT_Bool ic = 0; - - - if ( face ) - { - FT_Service_CID service; - - - FT_FACE_FIND_SERVICE( face, service, CID ); - - if ( service && service->get_is_cid ) - error = service->get_is_cid( face, &ic); - } - - if ( is_cid ) - *is_cid = ic; - - return error; - } - - - FT_EXPORT_DEF( FT_Error ) - FT_Get_CID_From_Glyph_Index( FT_Face face, - FT_UInt glyph_index, - FT_UInt *cid ) - { - FT_Error error = FT_ERR( Invalid_Argument ); - FT_UInt c = 0; - - - if ( face ) - { - FT_Service_CID service; - - - FT_FACE_FIND_SERVICE( face, service, CID ); - - if ( service && service->get_cid_from_glyph_index ) - error = service->get_cid_from_glyph_index( face, glyph_index, &c); - } - - if ( cid ) - *cid = c; - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftdbgmem.c b/third_party/freetype/src/base/ftdbgmem.c deleted file mode 100644 index 6f20313b345c89ad6fff6c6e851709b2dccae707..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftdbgmem.c +++ /dev/null @@ -1,998 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftdbgmem.c */ -/* */ -/* Memory debugger (body). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_MEMORY_H -#include FT_SYSTEM_H -#include FT_ERRORS_H -#include FT_TYPES_H - - -#ifdef FT_DEBUG_MEMORY - -#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released - * to the heap. This is useful to detect double-frees - * or weird heap corruption, but it uses large amounts of - * memory, however. - */ - -#include FT_CONFIG_STANDARD_LIBRARY_H - - FT_BASE_DEF( const char* ) _ft_debug_file = NULL; - FT_BASE_DEF( long ) _ft_debug_lineno = 0; - - extern void - FT_DumpMemory( FT_Memory memory ); - - - typedef struct FT_MemSourceRec_* FT_MemSource; - typedef struct FT_MemNodeRec_* FT_MemNode; - typedef struct FT_MemTableRec_* FT_MemTable; - - -#define FT_MEM_VAL( addr ) ( (FT_PtrDist)(FT_Pointer)( addr ) ) - - /* - * This structure holds statistics for a single allocation/release - * site. This is useful to know where memory operations happen the - * most. - */ - typedef struct FT_MemSourceRec_ - { - const char* file_name; - long line_no; - - FT_Long cur_blocks; /* current number of allocated blocks */ - FT_Long max_blocks; /* max. number of allocated blocks */ - FT_Long all_blocks; /* total number of blocks allocated */ - - FT_Long cur_size; /* current cumulative allocated size */ - FT_Long max_size; /* maximum cumulative allocated size */ - FT_Long all_size; /* total cumulative allocated size */ - - FT_Long cur_max; /* current maximum allocated size */ - - FT_UInt32 hash; - FT_MemSource link; - - } FT_MemSourceRec; - - - /* - * We don't need a resizable array for the memory sources because - * their number is pretty limited within FreeType. - */ -#define FT_MEM_SOURCE_BUCKETS 128 - - /* - * This structure holds information related to a single allocated - * memory block. If KEEPALIVE is defined, blocks that are freed by - * FreeType are never released to the system. Instead, their `size' - * field is set to `-size'. This is mainly useful to detect double - * frees, at the price of a large memory footprint during execution. - */ - typedef struct FT_MemNodeRec_ - { - FT_Byte* address; - FT_Long size; /* < 0 if the block was freed */ - - FT_MemSource source; - -#ifdef KEEPALIVE - const char* free_file_name; - FT_Long free_line_no; -#endif - - FT_MemNode link; - - } FT_MemNodeRec; - - - /* - * The global structure, containing compound statistics and all hash - * tables. - */ - typedef struct FT_MemTableRec_ - { - FT_Long size; - FT_Long nodes; - FT_MemNode* buckets; - - FT_Long alloc_total; - FT_Long alloc_current; - FT_Long alloc_max; - FT_Long alloc_count; - - FT_Bool bound_total; - FT_Long alloc_total_max; - - FT_Bool bound_count; - FT_Long alloc_count_max; - - FT_MemSource sources[FT_MEM_SOURCE_BUCKETS]; - - FT_Bool keep_alive; - - FT_Memory memory; - FT_Pointer memory_user; - FT_Alloc_Func alloc; - FT_Free_Func free; - FT_Realloc_Func realloc; - - } FT_MemTableRec; - - -#define FT_MEM_SIZE_MIN 7 -#define FT_MEM_SIZE_MAX 13845163 - -#define FT_FILENAME( x ) ( (x) ? (x) : "unknown file" ) - - - /* - * Prime numbers are ugly to handle. It would be better to implement - * L-Hashing, which is 10% faster and doesn't require divisions. - */ - static const FT_Int ft_mem_primes[] = - { - 7, - 11, - 19, - 37, - 73, - 109, - 163, - 251, - 367, - 557, - 823, - 1237, - 1861, - 2777, - 4177, - 6247, - 9371, - 14057, - 21089, - 31627, - 47431, - 71143, - 106721, - 160073, - 240101, - 360163, - 540217, - 810343, - 1215497, - 1823231, - 2734867, - 4102283, - 6153409, - 9230113, - 13845163, - }; - - - static FT_Long - ft_mem_closest_prime( FT_Long num ) - { - size_t i; - - - for ( i = 0; - i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ ) - if ( ft_mem_primes[i] > num ) - return ft_mem_primes[i]; - - return FT_MEM_SIZE_MAX; - } - - - static void - ft_mem_debug_panic( const char* fmt, - ... ) - { - va_list ap; - - - printf( "FreeType.Debug: " ); - - va_start( ap, fmt ); - vprintf( fmt, ap ); - va_end( ap ); - - printf( "\n" ); - exit( EXIT_FAILURE ); - } - - - static FT_Pointer - ft_mem_table_alloc( FT_MemTable table, - FT_Long size ) - { - FT_Memory memory = table->memory; - FT_Pointer block; - - - memory->user = table->memory_user; - block = table->alloc( memory, size ); - memory->user = table; - - return block; - } - - - static void - ft_mem_table_free( FT_MemTable table, - FT_Pointer block ) - { - FT_Memory memory = table->memory; - - - memory->user = table->memory_user; - table->free( memory, block ); - memory->user = table; - } - - - static void - ft_mem_table_resize( FT_MemTable table ) - { - FT_Long new_size; - - - new_size = ft_mem_closest_prime( table->nodes ); - if ( new_size != table->size ) - { - FT_MemNode* new_buckets; - FT_Long i; - - - new_buckets = (FT_MemNode *) - ft_mem_table_alloc( - table, - new_size * (FT_Long)sizeof ( FT_MemNode ) ); - if ( new_buckets == NULL ) - return; - - FT_ARRAY_ZERO( new_buckets, new_size ); - - for ( i = 0; i < table->size; i++ ) - { - FT_MemNode node, next, *pnode; - FT_PtrDist hash; - - - node = table->buckets[i]; - while ( node ) - { - next = node->link; - hash = FT_MEM_VAL( node->address ) % (FT_PtrDist)new_size; - pnode = new_buckets + hash; - - node->link = pnode[0]; - pnode[0] = node; - - node = next; - } - } - - if ( table->buckets ) - ft_mem_table_free( table, table->buckets ); - - table->buckets = new_buckets; - table->size = new_size; - } - } - - - static FT_MemTable - ft_mem_table_new( FT_Memory memory ) - { - FT_MemTable table; - - - table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) ); - if ( table == NULL ) - goto Exit; - - FT_ZERO( table ); - - table->size = FT_MEM_SIZE_MIN; - table->nodes = 0; - - table->memory = memory; - - table->memory_user = memory->user; - - table->alloc = memory->alloc; - table->realloc = memory->realloc; - table->free = memory->free; - - table->buckets = (FT_MemNode *) - memory->alloc( - memory, - table->size * (FT_Long)sizeof ( FT_MemNode ) ); - if ( table->buckets ) - FT_ARRAY_ZERO( table->buckets, table->size ); - else - { - memory->free( memory, table ); - table = NULL; - } - - Exit: - return table; - } - - - static void - ft_mem_table_destroy( FT_MemTable table ) - { - FT_Long i; - FT_Long leak_count = 0; - FT_Long leaks = 0; - - - FT_DumpMemory( table->memory ); - - /* remove all blocks from the table, revealing leaked ones */ - for ( i = 0; i < table->size; i++ ) - { - FT_MemNode *pnode = table->buckets + i, next, node = *pnode; - - - while ( node ) - { - next = node->link; - node->link = NULL; - - if ( node->size > 0 ) - { - printf( - "leaked memory block at address %p, size %8ld in (%s:%ld)\n", - node->address, node->size, - FT_FILENAME( node->source->file_name ), - node->source->line_no ); - - leak_count++; - leaks += node->size; - - ft_mem_table_free( table, node->address ); - } - - node->address = NULL; - node->size = 0; - - ft_mem_table_free( table, node ); - node = next; - } - table->buckets[i] = NULL; - } - - ft_mem_table_free( table, table->buckets ); - table->buckets = NULL; - - table->size = 0; - table->nodes = 0; - - /* remove all sources */ - for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ ) - { - FT_MemSource source, next; - - - for ( source = table->sources[i]; source != NULL; source = next ) - { - next = source->link; - ft_mem_table_free( table, source ); - } - - table->sources[i] = NULL; - } - - printf( "FreeType: total memory allocations = %ld\n", - table->alloc_total ); - printf( "FreeType: maximum memory footprint = %ld\n", - table->alloc_max ); - - ft_mem_table_free( table, table ); - - if ( leak_count > 0 ) - ft_mem_debug_panic( - "FreeType: %ld bytes of memory leaked in %ld blocks\n", - leaks, leak_count ); - - printf( "FreeType: no memory leaks detected\n" ); - } - - - static FT_MemNode* - ft_mem_table_get_nodep( FT_MemTable table, - FT_Byte* address ) - { - FT_PtrDist hash; - FT_MemNode *pnode, node; - - - hash = FT_MEM_VAL( address ); - pnode = table->buckets + ( hash % (FT_PtrDist)table->size ); - - for (;;) - { - node = pnode[0]; - if ( !node ) - break; - - if ( node->address == address ) - break; - - pnode = &node->link; - } - return pnode; - } - - - static FT_MemSource - ft_mem_table_get_source( FT_MemTable table ) - { - FT_UInt32 hash; - FT_MemSource node, *pnode; - - - /* cast to FT_PtrDist first since void* can be larger */ - /* than FT_UInt32 and GCC 4.1.1 emits a warning */ - hash = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file + - (FT_UInt32)( 5 * _ft_debug_lineno ); - pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS]; - - for ( ;; ) - { - node = *pnode; - if ( node == NULL ) - break; - - if ( node->file_name == _ft_debug_file && - node->line_no == _ft_debug_lineno ) - goto Exit; - - pnode = &node->link; - } - - node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) ); - if ( node == NULL ) - ft_mem_debug_panic( - "not enough memory to perform memory debugging\n" ); - - node->file_name = _ft_debug_file; - node->line_no = _ft_debug_lineno; - - node->cur_blocks = 0; - node->max_blocks = 0; - node->all_blocks = 0; - - node->cur_size = 0; - node->max_size = 0; - node->all_size = 0; - - node->cur_max = 0; - - node->link = NULL; - node->hash = hash; - *pnode = node; - - Exit: - return node; - } - - - static void - ft_mem_table_set( FT_MemTable table, - FT_Byte* address, - FT_Long size, - FT_Long delta ) - { - FT_MemNode *pnode, node; - - - if ( table ) - { - FT_MemSource source; - - - pnode = ft_mem_table_get_nodep( table, address ); - node = *pnode; - if ( node ) - { - if ( node->size < 0 ) - { - /* This block was already freed. Our memory is now completely */ - /* corrupted! */ - /* This can only happen in keep-alive mode. */ - ft_mem_debug_panic( - "memory heap corrupted (allocating freed block)" ); - } - else - { - /* This block was already allocated. This means that our memory */ - /* is also corrupted! */ - ft_mem_debug_panic( - "memory heap corrupted (re-allocating allocated block at" - " %p, of size %ld)\n" - "org=%s:%d new=%s:%d\n", - node->address, node->size, - FT_FILENAME( node->source->file_name ), node->source->line_no, - FT_FILENAME( _ft_debug_file ), _ft_debug_lineno ); - } - } - - /* we need to create a new node in this table */ - node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) ); - if ( node == NULL ) - ft_mem_debug_panic( "not enough memory to run memory tests" ); - - node->address = address; - node->size = size; - node->source = source = ft_mem_table_get_source( table ); - - if ( delta == 0 ) - { - /* this is an allocation */ - source->all_blocks++; - source->cur_blocks++; - if ( source->cur_blocks > source->max_blocks ) - source->max_blocks = source->cur_blocks; - } - - if ( size > source->cur_max ) - source->cur_max = size; - - if ( delta != 0 ) - { - /* we are growing or shrinking a reallocated block */ - source->cur_size += delta; - table->alloc_current += delta; - } - else - { - /* we are allocating a new block */ - source->cur_size += size; - table->alloc_current += size; - } - - source->all_size += size; - - if ( source->cur_size > source->max_size ) - source->max_size = source->cur_size; - - node->free_file_name = NULL; - node->free_line_no = 0; - - node->link = pnode[0]; - - pnode[0] = node; - table->nodes++; - - table->alloc_total += size; - - if ( table->alloc_current > table->alloc_max ) - table->alloc_max = table->alloc_current; - - if ( table->nodes * 3 < table->size || - table->size * 3 < table->nodes ) - ft_mem_table_resize( table ); - } - } - - - static void - ft_mem_table_remove( FT_MemTable table, - FT_Byte* address, - FT_Long delta ) - { - if ( table ) - { - FT_MemNode *pnode, node; - - - pnode = ft_mem_table_get_nodep( table, address ); - node = *pnode; - if ( node ) - { - FT_MemSource source; - - - if ( node->size < 0 ) - ft_mem_debug_panic( - "freeing memory block at %p more than once at (%s:%ld)\n" - "block allocated at (%s:%ld) and released at (%s:%ld)", - address, - FT_FILENAME( _ft_debug_file ), _ft_debug_lineno, - FT_FILENAME( node->source->file_name ), node->source->line_no, - FT_FILENAME( node->free_file_name ), node->free_line_no ); - - /* scramble the node's content for additional safety */ - FT_MEM_SET( address, 0xF3, node->size ); - - if ( delta == 0 ) - { - source = node->source; - - source->cur_blocks--; - source->cur_size -= node->size; - - table->alloc_current -= node->size; - } - - if ( table->keep_alive ) - { - /* we simply invert the node's size to indicate that the node */ - /* was freed. */ - node->size = -node->size; - node->free_file_name = _ft_debug_file; - node->free_line_no = _ft_debug_lineno; - } - else - { - table->nodes--; - - *pnode = node->link; - - node->size = 0; - node->source = NULL; - - ft_mem_table_free( table, node ); - - if ( table->nodes * 3 < table->size || - table->size * 3 < table->nodes ) - ft_mem_table_resize( table ); - } - } - else - ft_mem_debug_panic( - "trying to free unknown block at %p in (%s:%ld)\n", - address, - FT_FILENAME( _ft_debug_file ), _ft_debug_lineno ); - } - } - - - static FT_Pointer - ft_mem_debug_alloc( FT_Memory memory, - FT_Long size ) - { - FT_MemTable table = (FT_MemTable)memory->user; - FT_Byte* block; - - - if ( size <= 0 ) - ft_mem_debug_panic( "negative block size allocation (%ld)", size ); - - /* return NULL if the maximum number of allocations was reached */ - if ( table->bound_count && - table->alloc_count >= table->alloc_count_max ) - return NULL; - - /* return NULL if this allocation would overflow the maximum heap size */ - if ( table->bound_total && - table->alloc_total_max - table->alloc_current > size ) - return NULL; - - block = (FT_Byte *)ft_mem_table_alloc( table, size ); - if ( block ) - { - ft_mem_table_set( table, block, size, 0 ); - - table->alloc_count++; - } - - _ft_debug_file = "<unknown>"; - _ft_debug_lineno = 0; - - return (FT_Pointer)block; - } - - - static void - ft_mem_debug_free( FT_Memory memory, - FT_Pointer block ) - { - FT_MemTable table = (FT_MemTable)memory->user; - - - if ( block == NULL ) - ft_mem_debug_panic( "trying to free NULL in (%s:%ld)", - FT_FILENAME( _ft_debug_file ), - _ft_debug_lineno ); - - ft_mem_table_remove( table, (FT_Byte*)block, 0 ); - - if ( !table->keep_alive ) - ft_mem_table_free( table, block ); - - table->alloc_count--; - - _ft_debug_file = "<unknown>"; - _ft_debug_lineno = 0; - } - - - static FT_Pointer - ft_mem_debug_realloc( FT_Memory memory, - FT_Long cur_size, - FT_Long new_size, - FT_Pointer block ) - { - FT_MemTable table = (FT_MemTable)memory->user; - FT_MemNode node, *pnode; - FT_Pointer new_block; - FT_Long delta; - - const char* file_name = FT_FILENAME( _ft_debug_file ); - FT_Long line_no = _ft_debug_lineno; - - - /* unlikely, but possible */ - if ( new_size == cur_size ) - return block; - - /* the following is valid according to ANSI C */ -#if 0 - if ( block == NULL || cur_size == 0 ) - ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)", - file_name, line_no ); -#endif - - /* while the following is allowed in ANSI C also, we abort since */ - /* such case should be handled by FreeType. */ - if ( new_size <= 0 ) - ft_mem_debug_panic( - "trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)", - block, cur_size, file_name, line_no ); - - /* check `cur_size' value */ - pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block ); - node = *pnode; - if ( !node ) - ft_mem_debug_panic( - "trying to reallocate unknown block at %p in (%s:%ld)", - block, file_name, line_no ); - - if ( node->size <= 0 ) - ft_mem_debug_panic( - "trying to reallocate freed block at %p in (%s:%ld)", - block, file_name, line_no ); - - if ( node->size != cur_size ) - ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is " - "%ld instead of %ld in (%s:%ld)", - block, cur_size, node->size, file_name, line_no ); - - /* return NULL if the maximum number of allocations was reached */ - if ( table->bound_count && - table->alloc_count >= table->alloc_count_max ) - return NULL; - - delta = new_size - cur_size; - - /* return NULL if this allocation would overflow the maximum heap size */ - if ( delta > 0 && - table->bound_total && - table->alloc_current + delta > table->alloc_total_max ) - return NULL; - - new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size ); - if ( new_block == NULL ) - return NULL; - - ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta ); - - ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size - : (size_t)new_size ); - - ft_mem_table_remove( table, (FT_Byte*)block, delta ); - - _ft_debug_file = "<unknown>"; - _ft_debug_lineno = 0; - - if ( !table->keep_alive ) - ft_mem_table_free( table, block ); - - return new_block; - } - - - extern FT_Int - ft_mem_debug_init( FT_Memory memory ) - { - FT_MemTable table; - FT_Int result = 0; - - - if ( getenv( "FT2_DEBUG_MEMORY" ) ) - { - table = ft_mem_table_new( memory ); - if ( table ) - { - const char* p; - - - memory->user = table; - memory->alloc = ft_mem_debug_alloc; - memory->realloc = ft_mem_debug_realloc; - memory->free = ft_mem_debug_free; - - p = getenv( "FT2_ALLOC_TOTAL_MAX" ); - if ( p != NULL ) - { - FT_Long total_max = ft_atol( p ); - - - if ( total_max > 0 ) - { - table->bound_total = 1; - table->alloc_total_max = total_max; - } - } - - p = getenv( "FT2_ALLOC_COUNT_MAX" ); - if ( p != NULL ) - { - FT_Long total_count = ft_atol( p ); - - - if ( total_count > 0 ) - { - table->bound_count = 1; - table->alloc_count_max = total_count; - } - } - - p = getenv( "FT2_KEEP_ALIVE" ); - if ( p != NULL ) - { - FT_Long keep_alive = ft_atol( p ); - - - if ( keep_alive > 0 ) - table->keep_alive = 1; - } - - result = 1; - } - } - return result; - } - - - extern void - ft_mem_debug_done( FT_Memory memory ) - { - FT_MemTable table = (FT_MemTable)memory->user; - - - if ( table ) - { - memory->free = table->free; - memory->realloc = table->realloc; - memory->alloc = table->alloc; - - ft_mem_table_destroy( table ); - memory->user = NULL; - } - } - - - static int - ft_mem_source_compare( const void* p1, - const void* p2 ) - { - FT_MemSource s1 = *(FT_MemSource*)p1; - FT_MemSource s2 = *(FT_MemSource*)p2; - - - if ( s2->max_size > s1->max_size ) - return 1; - else if ( s2->max_size < s1->max_size ) - return -1; - else - return 0; - } - - - extern void - FT_DumpMemory( FT_Memory memory ) - { - FT_MemTable table = (FT_MemTable)memory->user; - - - if ( table ) - { - FT_MemSource* bucket = table->sources; - FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS; - FT_MemSource* sources; - FT_Int nn, count; - const char* fmt; - - - count = 0; - for ( ; bucket < limit; bucket++ ) - { - FT_MemSource source = *bucket; - - - for ( ; source; source = source->link ) - count++; - } - - sources = (FT_MemSource*) - ft_mem_table_alloc( - table, count * (FT_Long)sizeof ( *sources ) ); - - count = 0; - for ( bucket = table->sources; bucket < limit; bucket++ ) - { - FT_MemSource source = *bucket; - - - for ( ; source; source = source->link ) - sources[count++] = source; - } - - ft_qsort( sources, - (size_t)count, - sizeof ( *sources ), - ft_mem_source_compare ); - - printf( "FreeType Memory Dump: " - "current=%ld max=%ld total=%ld count=%ld\n", - table->alloc_current, table->alloc_max, - table->alloc_total, table->alloc_count ); - printf( " block block sizes sizes sizes source\n" ); - printf( " count high sum highsum max location\n" ); - printf( "-------------------------------------------------\n" ); - - fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n"; - - for ( nn = 0; nn < count; nn++ ) - { - FT_MemSource source = sources[nn]; - - - printf( fmt, - source->cur_blocks, source->max_blocks, - source->cur_size, source->max_size, source->cur_max, - FT_FILENAME( source->file_name ), - source->line_no ); - } - printf( "------------------------------------------------\n" ); - - ft_mem_table_free( table, sources ); - } - } - -#else /* !FT_DEBUG_MEMORY */ - - /* ANSI C doesn't like empty source files */ - typedef int _debug_mem_dummy; - -#endif /* !FT_DEBUG_MEMORY */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftdebug.c b/third_party/freetype/src/base/ftdebug.c deleted file mode 100644 index 03e18a86999c8034bc3a880fc1ae55c5fdd7af56..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftdebug.c +++ /dev/null @@ -1,266 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftdebug.c */ -/* */ -/* Debugging and logging component (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This component contains various macros and functions used to ease the */ - /* debugging of the FreeType engine. Its main purpose is in assertion */ - /* checking, tracing, and error detection. */ - /* */ - /* There are now three debugging modes: */ - /* */ - /* - trace mode */ - /* */ - /* Error and trace messages are sent to the log file (which can be the */ - /* standard error output). */ - /* */ - /* - error mode */ - /* */ - /* Only error messages are generated. */ - /* */ - /* - release mode: */ - /* */ - /* No error message is sent or generated. The code is free from any */ - /* debugging parts. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_DEBUG_H - - -#ifdef FT_DEBUG_LEVEL_ERROR - - /* documentation is in ftdebug.h */ - - FT_BASE_DEF( void ) - FT_Message( const char* fmt, - ... ) - { - va_list ap; - - - va_start( ap, fmt ); - vfprintf( stderr, fmt, ap ); - va_end( ap ); - } - - - /* documentation is in ftdebug.h */ - - FT_BASE_DEF( void ) - FT_Panic( const char* fmt, - ... ) - { - va_list ap; - - - va_start( ap, fmt ); - vfprintf( stderr, fmt, ap ); - va_end( ap ); - - exit( EXIT_FAILURE ); - } - - - /* documentation is in ftdebug.h */ - - FT_BASE_DEF( int ) - FT_Throw( FT_Error error, - int line, - const char* file ) - { - FT_UNUSED( error ); - FT_UNUSED( line ); - FT_UNUSED( file ); - - return 0; - } - -#endif /* FT_DEBUG_LEVEL_ERROR */ - - - -#ifdef FT_DEBUG_LEVEL_TRACE - - /* array of trace levels, initialized to 0 */ - int ft_trace_levels[trace_count]; - - - /* define array of trace toggle names */ -#define FT_TRACE_DEF( x ) #x , - - static const char* ft_trace_toggles[trace_count + 1] = - { -#include FT_INTERNAL_TRACE_H - NULL - }; - -#undef FT_TRACE_DEF - - - /* documentation is in ftdebug.h */ - - FT_BASE_DEF( FT_Int ) - FT_Trace_Get_Count( void ) - { - return trace_count; - } - - - /* documentation is in ftdebug.h */ - - FT_BASE_DEF( const char * ) - FT_Trace_Get_Name( FT_Int idx ) - { - int max = FT_Trace_Get_Count(); - - - if ( idx < max ) - return ft_trace_toggles[idx]; - else - return NULL; - } - - - /*************************************************************************/ - /* */ - /* Initialize the tracing sub-system. This is done by retrieving the */ - /* value of the `FT2_DEBUG' environment variable. It must be a list of */ - /* toggles, separated by spaces, `;', or `,'. Example: */ - /* */ - /* export FT2_DEBUG="any:3 memory:7 stream:5" */ - /* */ - /* This requests that all levels be set to 3, except the trace level for */ - /* the memory and stream components which are set to 7 and 5, */ - /* respectively. */ - /* */ - /* See the file `include/freetype/internal/fttrace.h' for details of */ - /* the available toggle names. */ - /* */ - /* The level must be between 0 and 7; 0 means quiet (except for serious */ - /* runtime errors), and 7 means _very_ verbose. */ - /* */ - FT_BASE_DEF( void ) - ft_debug_init( void ) - { - const char* ft2_debug = getenv( "FT2_DEBUG" ); - - - if ( ft2_debug ) - { - const char* p = ft2_debug; - const char* q; - - - for ( ; *p; p++ ) - { - /* skip leading whitespace and separators */ - if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' ) - continue; - - /* read toggle name, followed by ':' */ - q = p; - while ( *p && *p != ':' ) - p++; - - if ( !*p ) - break; - - if ( *p == ':' && p > q ) - { - FT_Int n, i, len = (FT_Int)( p - q ); - FT_Int level = -1, found = -1; - - - for ( n = 0; n < trace_count; n++ ) - { - const char* toggle = ft_trace_toggles[n]; - - - for ( i = 0; i < len; i++ ) - { - if ( toggle[i] != q[i] ) - break; - } - - if ( i == len && toggle[i] == 0 ) - { - found = n; - break; - } - } - - /* read level */ - p++; - if ( *p ) - { - level = *p - '0'; - if ( level < 0 || level > 7 ) - level = -1; - } - - if ( found >= 0 && level >= 0 ) - { - if ( found == trace_any ) - { - /* special case for `any' */ - for ( n = 0; n < trace_count; n++ ) - ft_trace_levels[n] = level; - } - else - ft_trace_levels[found] = level; - } - } - } - } - } - - -#else /* !FT_DEBUG_LEVEL_TRACE */ - - - FT_BASE_DEF( void ) - ft_debug_init( void ) - { - /* nothing */ - } - - - FT_BASE_DEF( FT_Int ) - FT_Trace_Get_Count( void ) - { - return 0; - } - - - FT_BASE_DEF( const char * ) - FT_Trace_Get_Name( FT_Int idx ) - { - FT_UNUSED( idx ); - - return NULL; - } - - -#endif /* !FT_DEBUG_LEVEL_TRACE */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftfntfmt.c b/third_party/freetype/src/base/ftfntfmt.c deleted file mode 100644 index 98e7431a2b94648b13ddb5edb9e92c97a326b669..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftfntfmt.c +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftfntfmt.c */ -/* */ -/* FreeType utility file for font formats (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FONT_FORMATS_H -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_FONT_FORMAT_H - - - /* documentation is in ftfntfmt.h */ - - FT_EXPORT_DEF( const char* ) - FT_Get_Font_Format( FT_Face face ) - { - const char* result = NULL; - - - if ( face ) - FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT ); - - return result; - } - - - /* deprecated function name; retained for ABI compatibility */ - - FT_EXPORT_DEF( const char* ) - FT_Get_X11_Font_Format( FT_Face face ) - { - const char* result = NULL; - - - if ( face ) - FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT ); - - return result; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftfstype.c b/third_party/freetype/src/base/ftfstype.c deleted file mode 100644 index cd3458f73e1640cccfc15a3f5b8b747b26baaba2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftfstype.c +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftfstype.c */ -/* */ -/* FreeType utility file to access FSType data (body). */ -/* */ -/* Copyright 2008-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#include <ft2build.h> -#include FT_TYPE1_TABLES_H -#include FT_TRUETYPE_TABLES_H -#include FT_INTERNAL_SERVICE_H -#include FT_SERVICE_POSTSCRIPT_INFO_H - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UShort ) - FT_Get_FSType_Flags( FT_Face face ) - { - TT_OS2* os2; - - - /* first, try to get the fs_type directly from the font */ - if ( face ) - { - FT_Service_PsInfo service = NULL; - - - FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); - - if ( service && service->ps_get_font_extra ) - { - PS_FontExtraRec extra; - - - if ( !service->ps_get_font_extra( face, &extra ) && - extra.fs_type != 0 ) - return extra.fs_type; - } - } - - /* look at FSType before fsType for Type42 */ - - if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, FT_SFNT_OS2 ) ) != NULL && - os2->version != 0xFFFFU ) - return os2->fsType; - - return 0; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftgasp.c b/third_party/freetype/src/base/ftgasp.c deleted file mode 100644 index bbd257c47954084f05920fc0947519d7cc4ab51c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftgasp.c +++ /dev/null @@ -1,61 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgasp.c */ -/* */ -/* Access of TrueType's `gasp' table (body). */ -/* */ -/* Copyright 2007-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_GASP_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - - FT_EXPORT_DEF( FT_Int ) - FT_Get_Gasp( FT_Face face, - FT_UInt ppem ) - { - FT_Int result = FT_GASP_NO_TABLE; - - - if ( face && FT_IS_SFNT( face ) ) - { - TT_Face ttface = (TT_Face)face; - - - if ( ttface->gasp.numRanges > 0 ) - { - TT_GaspRange range = ttface->gasp.gaspRanges; - TT_GaspRange range_end = range + ttface->gasp.numRanges; - - - while ( ppem > range->maxPPEM ) - { - range++; - if ( range >= range_end ) - goto Exit; - } - - result = range->gaspFlag; - - /* ensure that we don't have spurious bits */ - if ( ttface->gasp.version == 0 ) - result &= 3; - } - } - Exit: - return result; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftgloadr.c b/third_party/freetype/src/base/ftgloadr.c deleted file mode 100644 index 7e28638b27fe1ca0c51cb2f6e6df0ef6dae7603a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftgloadr.c +++ /dev/null @@ -1,406 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgloadr.c */ -/* */ -/* The FreeType glyph loader (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_GLYPH_LOADER_H -#include FT_INTERNAL_MEMORY_H -#include FT_INTERNAL_OBJECTS_H - -#undef FT_COMPONENT -#define FT_COMPONENT trace_gloader - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** *****/ - /***** G L Y P H L O A D E R *****/ - /***** *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* The glyph loader is a simple object which is used to load a set of */ - /* glyphs easily. It is critical for the correct loading of composites. */ - /* */ - /* Ideally, one can see it as a stack of abstract `glyph' objects. */ - /* */ - /* loader.base Is really the bottom of the stack. It describes a */ - /* single glyph image made of the juxtaposition of */ - /* several glyphs (those `in the stack'). */ - /* */ - /* loader.current Describes the top of the stack, on which a new */ - /* glyph can be loaded. */ - /* */ - /* Rewind Clears the stack. */ - /* Prepare Set up `loader.current' for addition of a new glyph */ - /* image. */ - /* Add Add the `current' glyph image to the `base' one, */ - /* and prepare for another one. */ - /* */ - /* The glyph loader is now a base object. Each driver used to */ - /* re-implement it in one way or the other, which wasted code and */ - /* energy. */ - /* */ - /*************************************************************************/ - - - /* create a new glyph loader */ - FT_BASE_DEF( FT_Error ) - FT_GlyphLoader_New( FT_Memory memory, - FT_GlyphLoader *aloader ) - { - FT_GlyphLoader loader = NULL; - FT_Error error; - - - if ( !FT_NEW( loader ) ) - { - loader->memory = memory; - *aloader = loader; - } - return error; - } - - - /* rewind the glyph loader - reset counters to 0 */ - FT_BASE_DEF( void ) - FT_GlyphLoader_Rewind( FT_GlyphLoader loader ) - { - FT_GlyphLoad base = &loader->base; - FT_GlyphLoad current = &loader->current; - - - base->outline.n_points = 0; - base->outline.n_contours = 0; - base->num_subglyphs = 0; - - *current = *base; - } - - - /* reset the glyph loader, frees all allocated tables */ - /* and starts from zero */ - FT_BASE_DEF( void ) - FT_GlyphLoader_Reset( FT_GlyphLoader loader ) - { - FT_Memory memory = loader->memory; - - - FT_FREE( loader->base.outline.points ); - FT_FREE( loader->base.outline.tags ); - FT_FREE( loader->base.outline.contours ); - FT_FREE( loader->base.extra_points ); - FT_FREE( loader->base.subglyphs ); - - loader->base.extra_points2 = NULL; - - loader->max_points = 0; - loader->max_contours = 0; - loader->max_subglyphs = 0; - - FT_GlyphLoader_Rewind( loader ); - } - - - /* delete a glyph loader */ - FT_BASE_DEF( void ) - FT_GlyphLoader_Done( FT_GlyphLoader loader ) - { - if ( loader ) - { - FT_Memory memory = loader->memory; - - - FT_GlyphLoader_Reset( loader ); - FT_FREE( loader ); - } - } - - - /* re-adjust the `current' outline fields */ - static void - FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader ) - { - FT_Outline* base = &loader->base.outline; - FT_Outline* current = &loader->current.outline; - - - current->points = base->points + base->n_points; - current->tags = base->tags + base->n_points; - current->contours = base->contours + base->n_contours; - - /* handle extra points table - if any */ - if ( loader->use_extra ) - { - loader->current.extra_points = loader->base.extra_points + - base->n_points; - - loader->current.extra_points2 = loader->base.extra_points2 + - base->n_points; - } - } - - - FT_BASE_DEF( FT_Error ) - FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ) - { - FT_Error error; - FT_Memory memory = loader->memory; - - - if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) ) - { - loader->use_extra = 1; - loader->base.extra_points2 = loader->base.extra_points + - loader->max_points; - - FT_GlyphLoader_Adjust_Points( loader ); - } - return error; - } - - - /* re-adjust the `current' subglyphs field */ - static void - FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader ) - { - FT_GlyphLoad base = &loader->base; - FT_GlyphLoad current = &loader->current; - - - current->subglyphs = base->subglyphs + base->num_subglyphs; - } - - - /* Ensure that we can add `n_points' and `n_contours' to our glyph. */ - /* This function reallocates its outline tables if necessary. Note that */ - /* it DOESN'T change the number of points within the loader! */ - /* */ - FT_BASE_DEF( FT_Error ) - FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, - FT_UInt n_points, - FT_UInt n_contours ) - { - FT_Memory memory = loader->memory; - FT_Error error = FT_Err_Ok; - FT_Outline* base = &loader->base.outline; - FT_Outline* current = &loader->current.outline; - FT_Bool adjust = 0; - - FT_UInt new_max, old_max; - - - /* check points & tags */ - new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points + - n_points; - old_max = loader->max_points; - - if ( new_max > old_max ) - { - new_max = FT_PAD_CEIL( new_max, 8 ); - - if ( new_max > FT_OUTLINE_POINTS_MAX ) - return FT_THROW( Array_Too_Large ); - - if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || - FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) - goto Exit; - - if ( loader->use_extra ) - { - if ( FT_RENEW_ARRAY( loader->base.extra_points, - old_max * 2, new_max * 2 ) ) - goto Exit; - - FT_ARRAY_MOVE( loader->base.extra_points + new_max, - loader->base.extra_points + old_max, - old_max ); - - loader->base.extra_points2 = loader->base.extra_points + new_max; - } - - adjust = 1; - loader->max_points = new_max; - } - - /* check contours */ - old_max = loader->max_contours; - new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours + - n_contours; - if ( new_max > old_max ) - { - new_max = FT_PAD_CEIL( new_max, 4 ); - - if ( new_max > FT_OUTLINE_CONTOURS_MAX ) - return FT_THROW( Array_Too_Large ); - - if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) - goto Exit; - - adjust = 1; - loader->max_contours = new_max; - } - - if ( adjust ) - FT_GlyphLoader_Adjust_Points( loader ); - - Exit: - if ( error ) - FT_GlyphLoader_Reset( loader ); - - return error; - } - - - /* Ensure that we can add `n_subglyphs' to our glyph. this function */ - /* reallocates its subglyphs table if necessary. Note that it DOES */ - /* NOT change the number of subglyphs within the loader! */ - /* */ - FT_BASE_DEF( FT_Error ) - FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, - FT_UInt n_subs ) - { - FT_Memory memory = loader->memory; - FT_Error error = FT_Err_Ok; - FT_UInt new_max, old_max; - - FT_GlyphLoad base = &loader->base; - FT_GlyphLoad current = &loader->current; - - - new_max = base->num_subglyphs + current->num_subglyphs + n_subs; - old_max = loader->max_subglyphs; - if ( new_max > old_max ) - { - new_max = FT_PAD_CEIL( new_max, 2 ); - if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) ) - goto Exit; - - loader->max_subglyphs = new_max; - - FT_GlyphLoader_Adjust_Subglyphs( loader ); - } - - Exit: - return error; - } - - - /* prepare loader for the addition of a new glyph on top of the base one */ - FT_BASE_DEF( void ) - FT_GlyphLoader_Prepare( FT_GlyphLoader loader ) - { - FT_GlyphLoad current = &loader->current; - - - current->outline.n_points = 0; - current->outline.n_contours = 0; - current->num_subglyphs = 0; - - FT_GlyphLoader_Adjust_Points ( loader ); - FT_GlyphLoader_Adjust_Subglyphs( loader ); - } - - - /* add current glyph to the base image -- and prepare for another */ - FT_BASE_DEF( void ) - FT_GlyphLoader_Add( FT_GlyphLoader loader ) - { - FT_GlyphLoad base; - FT_GlyphLoad current; - - FT_Int n_curr_contours; - FT_Int n_base_points; - FT_Int n; - - - if ( !loader ) - return; - - base = &loader->base; - current = &loader->current; - - n_curr_contours = current->outline.n_contours; - n_base_points = base->outline.n_points; - - base->outline.n_points = - (short)( base->outline.n_points + current->outline.n_points ); - base->outline.n_contours = - (short)( base->outline.n_contours + current->outline.n_contours ); - - base->num_subglyphs += current->num_subglyphs; - - /* adjust contours count in newest outline */ - for ( n = 0; n < n_curr_contours; n++ ) - current->outline.contours[n] = - (short)( current->outline.contours[n] + n_base_points ); - - /* prepare for another new glyph image */ - FT_GlyphLoader_Prepare( loader ); - } - - - FT_BASE_DEF( FT_Error ) - FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, - FT_GlyphLoader source ) - { - FT_Error error; - FT_UInt num_points = (FT_UInt)source->base.outline.n_points; - FT_UInt num_contours = (FT_UInt)source->base.outline.n_contours; - - - error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours ); - if ( !error ) - { - FT_Outline* out = &target->base.outline; - FT_Outline* in = &source->base.outline; - - - FT_ARRAY_COPY( out->points, in->points, - num_points ); - FT_ARRAY_COPY( out->tags, in->tags, - num_points ); - FT_ARRAY_COPY( out->contours, in->contours, - num_contours ); - - /* do we need to copy the extra points? */ - if ( target->use_extra && source->use_extra ) - { - FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points, - num_points ); - FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2, - num_points ); - } - - out->n_points = (short)num_points; - out->n_contours = (short)num_contours; - - FT_GlyphLoader_Adjust_Points( target ); - } - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftglyph.c b/third_party/freetype/src/base/ftglyph.c deleted file mode 100644 index cb7fc37787ea97720bcdff6c9d7dcecc2b0901dc..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftglyph.c +++ /dev/null @@ -1,629 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftglyph.c */ -/* */ -/* FreeType convenience functions to handle glyphs (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* This file contains the definition of several convenience functions */ - /* that can be used by client applications to easily retrieve glyph */ - /* bitmaps and outlines from a given face. */ - /* */ - /* These functions should be optional if you are writing a font server */ - /* or text layout engine on top of FreeType. However, they are pretty */ - /* handy for many other simple uses of the library. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_GLYPH_H -#include FT_OUTLINE_H -#include FT_BITMAP_H -#include FT_INTERNAL_OBJECTS_H - -#include "basepic.h" - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_glyph - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** FT_BitmapGlyph support ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_CALLBACK_DEF( FT_Error ) - ft_bitmap_glyph_init( FT_Glyph bitmap_glyph, - FT_GlyphSlot slot ) - { - FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; - FT_Error error = FT_Err_Ok; - FT_Library library = FT_GLYPH( glyph )->library; - - - if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) - { - error = FT_THROW( Invalid_Glyph_Format ); - goto Exit; - } - - glyph->left = slot->bitmap_left; - glyph->top = slot->bitmap_top; - - /* do lazy copying whenever possible */ - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { - glyph->bitmap = slot->bitmap; - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - else - { - FT_Bitmap_Init( &glyph->bitmap ); - error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap ); - } - - Exit: - return error; - } - - - FT_CALLBACK_DEF( FT_Error ) - ft_bitmap_glyph_copy( FT_Glyph bitmap_source, - FT_Glyph bitmap_target ) - { - FT_Library library = bitmap_source->library; - FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source; - FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target; - - - target->left = source->left; - target->top = source->top; - - return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap ); - } - - - FT_CALLBACK_DEF( void ) - ft_bitmap_glyph_done( FT_Glyph bitmap_glyph ) - { - FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; - FT_Library library = FT_GLYPH( glyph )->library; - - - FT_Bitmap_Done( library, &glyph->bitmap ); - } - - - FT_CALLBACK_DEF( void ) - ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph, - FT_BBox* cbox ) - { - FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; - - - cbox->xMin = glyph->left << 6; - cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width << 6 ); - cbox->yMax = glyph->top << 6; - cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows << 6 ); - } - - - FT_DEFINE_GLYPH(ft_bitmap_glyph_class, - sizeof ( FT_BitmapGlyphRec ), - FT_GLYPH_FORMAT_BITMAP, - - ft_bitmap_glyph_init, - ft_bitmap_glyph_done, - ft_bitmap_glyph_copy, - 0, /* FT_Glyph_TransformFunc */ - ft_bitmap_glyph_bbox, - 0 /* FT_Glyph_PrepareFunc */ - ) - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** FT_OutlineGlyph support ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_CALLBACK_DEF( FT_Error ) - ft_outline_glyph_init( FT_Glyph outline_glyph, - FT_GlyphSlot slot ) - { - FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; - FT_Error error = FT_Err_Ok; - FT_Library library = FT_GLYPH( glyph )->library; - FT_Outline* source = &slot->outline; - FT_Outline* target = &glyph->outline; - - - /* check format in glyph slot */ - if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) - { - error = FT_THROW( Invalid_Glyph_Format ); - goto Exit; - } - - /* allocate new outline */ - error = FT_Outline_New( library, - (FT_UInt)source->n_points, - source->n_contours, - &glyph->outline ); - if ( error ) - goto Exit; - - FT_Outline_Copy( source, target ); - - Exit: - return error; - } - - - FT_CALLBACK_DEF( void ) - ft_outline_glyph_done( FT_Glyph outline_glyph ) - { - FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; - - - FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); - } - - - FT_CALLBACK_DEF( FT_Error ) - ft_outline_glyph_copy( FT_Glyph outline_source, - FT_Glyph outline_target ) - { - FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source; - FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target; - FT_Error error; - FT_Library library = FT_GLYPH( source )->library; - - - error = FT_Outline_New( library, - (FT_UInt)source->outline.n_points, - source->outline.n_contours, - &target->outline ); - if ( !error ) - FT_Outline_Copy( &source->outline, &target->outline ); - - return error; - } - - - FT_CALLBACK_DEF( void ) - ft_outline_glyph_transform( FT_Glyph outline_glyph, - const FT_Matrix* matrix, - const FT_Vector* delta ) - { - FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; - - - if ( matrix ) - FT_Outline_Transform( &glyph->outline, matrix ); - - if ( delta ) - FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); - } - - - FT_CALLBACK_DEF( void ) - ft_outline_glyph_bbox( FT_Glyph outline_glyph, - FT_BBox* bbox ) - { - FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; - - - FT_Outline_Get_CBox( &glyph->outline, bbox ); - } - - - FT_CALLBACK_DEF( FT_Error ) - ft_outline_glyph_prepare( FT_Glyph outline_glyph, - FT_GlyphSlot slot ) - { - FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; - - - slot->format = FT_GLYPH_FORMAT_OUTLINE; - slot->outline = glyph->outline; - slot->outline.flags &= ~FT_OUTLINE_OWNER; - - return FT_Err_Ok; - } - - - FT_DEFINE_GLYPH( ft_outline_glyph_class, - sizeof ( FT_OutlineGlyphRec ), - FT_GLYPH_FORMAT_OUTLINE, - - ft_outline_glyph_init, - ft_outline_glyph_done, - ft_outline_glyph_copy, - ft_outline_glyph_transform, - ft_outline_glyph_bbox, - ft_outline_glyph_prepare - ) - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** FT_Glyph class and API ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - static FT_Error - ft_new_glyph( FT_Library library, - const FT_Glyph_Class* clazz, - FT_Glyph* aglyph ) - { - FT_Memory memory = library->memory; - FT_Error error; - FT_Glyph glyph = NULL; - - - *aglyph = NULL; - - if ( !FT_ALLOC( glyph, clazz->glyph_size ) ) - { - glyph->library = library; - glyph->clazz = clazz; - glyph->format = clazz->glyph_format; - - *aglyph = glyph; - } - - return error; - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Glyph_Copy( FT_Glyph source, - FT_Glyph *target ) - { - FT_Glyph copy; - FT_Error error; - const FT_Glyph_Class* clazz; - - - /* check arguments */ - if ( !target || !source || !source->clazz ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - *target = NULL; - - if ( !source || !source->clazz ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - clazz = source->clazz; - error = ft_new_glyph( source->library, clazz, © ); - if ( error ) - goto Exit; - - copy->advance = source->advance; - copy->format = source->format; - - if ( clazz->glyph_copy ) - error = clazz->glyph_copy( source, copy ); - - if ( error ) - FT_Done_Glyph( copy ); - else - *target = copy; - - Exit: - return error; - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Glyph( FT_GlyphSlot slot, - FT_Glyph *aglyph ) - { - FT_Library library; - FT_Error error; - FT_Glyph glyph; - - const FT_Glyph_Class* clazz = NULL; - - - if ( !slot ) - return FT_THROW( Invalid_Slot_Handle ); - - library = slot->library; - - if ( !aglyph ) - return FT_THROW( Invalid_Argument ); - - /* if it is a bitmap, that's easy :-) */ - if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) - clazz = FT_BITMAP_GLYPH_CLASS_GET; - - /* if it is an outline */ - else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - clazz = FT_OUTLINE_GLYPH_CLASS_GET; - - else - { - /* try to find a renderer that supports the glyph image format */ - FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 ); - - - if ( render ) - clazz = &render->glyph_class; - } - - if ( !clazz ) - { - error = FT_THROW( Invalid_Glyph_Format ); - goto Exit; - } - - /* create FT_Glyph object */ - error = ft_new_glyph( library, clazz, &glyph ); - if ( error ) - goto Exit; - - /* copy advance while converting it to 16.16 format */ - glyph->advance.x = slot->advance.x << 10; - glyph->advance.y = slot->advance.y << 10; - - /* now import the image from the glyph slot */ - error = clazz->glyph_init( glyph, slot ); - - /* if an error occurred, destroy the glyph */ - if ( error ) - FT_Done_Glyph( glyph ); - else - *aglyph = glyph; - - Exit: - return error; - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Glyph_Transform( FT_Glyph glyph, - FT_Matrix* matrix, - FT_Vector* delta ) - { - FT_Error error = FT_Err_Ok; - - - if ( !glyph || !glyph->clazz ) - error = FT_THROW( Invalid_Argument ); - else - { - const FT_Glyph_Class* clazz = glyph->clazz; - - - if ( clazz->glyph_transform ) - { - /* transform glyph image */ - clazz->glyph_transform( glyph, matrix, delta ); - - /* transform advance vector */ - if ( matrix ) - FT_Vector_Transform( &glyph->advance, matrix ); - } - else - error = FT_THROW( Invalid_Glyph_Format ); - } - return error; - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( void ) - FT_Glyph_Get_CBox( FT_Glyph glyph, - FT_UInt bbox_mode, - FT_BBox *acbox ) - { - const FT_Glyph_Class* clazz; - - - if ( !acbox ) - return; - - acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0; - - if ( !glyph || !glyph->clazz ) - return; - - clazz = glyph->clazz; - if ( !clazz->glyph_bbox ) - return; - - /* retrieve bbox in 26.6 coordinates */ - clazz->glyph_bbox( glyph, acbox ); - - /* perform grid fitting if needed */ - if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT || - bbox_mode == FT_GLYPH_BBOX_PIXELS ) - { - acbox->xMin = FT_PIX_FLOOR( acbox->xMin ); - acbox->yMin = FT_PIX_FLOOR( acbox->yMin ); - acbox->xMax = FT_PIX_CEIL( acbox->xMax ); - acbox->yMax = FT_PIX_CEIL( acbox->yMax ); - } - - /* convert to integer pixels if needed */ - if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE || - bbox_mode == FT_GLYPH_BBOX_PIXELS ) - { - acbox->xMin >>= 6; - acbox->yMin >>= 6; - acbox->xMax >>= 6; - acbox->yMax >>= 6; - } - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, - FT_Render_Mode render_mode, - FT_Vector* origin, - FT_Bool destroy ) - { - FT_GlyphSlotRec dummy; - FT_GlyphSlot_InternalRec dummy_internal; - FT_Error error = FT_Err_Ok; - FT_Glyph b, glyph; - FT_BitmapGlyph bitmap = NULL; - const FT_Glyph_Class* clazz; - - /* FT_BITMAP_GLYPH_CLASS_GET dereferences `library' in PIC mode */ - FT_Library library; - - - /* check argument */ - if ( !the_glyph ) - goto Bad; - glyph = *the_glyph; - if ( !glyph ) - goto Bad; - - clazz = glyph->clazz; - library = glyph->library; - if ( !library || !clazz ) - goto Bad; - - /* when called with a bitmap glyph, do nothing and return successfully */ - if ( clazz == FT_BITMAP_GLYPH_CLASS_GET ) - goto Exit; - - if ( !clazz->glyph_prepare ) - goto Bad; - - /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ - /* then calling FT_Render_Glyph_Internal() */ - - FT_MEM_ZERO( &dummy, sizeof ( dummy ) ); - FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) ); - dummy.internal = &dummy_internal; - dummy.library = library; - dummy.format = clazz->glyph_format; - - /* create result bitmap glyph */ - error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, &b ); - if ( error ) - goto Exit; - bitmap = (FT_BitmapGlyph)b; - -#if 1 - /* if `origin' is set, translate the glyph image */ - if ( origin ) - FT_Glyph_Transform( glyph, 0, origin ); -#else - FT_UNUSED( origin ); -#endif - - /* prepare dummy slot for rendering */ - error = clazz->glyph_prepare( glyph, &dummy ); - if ( !error ) - error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); - -#if 1 - if ( !destroy && origin ) - { - FT_Vector v; - - - v.x = -origin->x; - v.y = -origin->y; - FT_Glyph_Transform( glyph, 0, &v ); - } -#endif - - if ( error ) - goto Exit; - - /* in case of success, copy the bitmap to the glyph bitmap */ - error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy ); - if ( error ) - goto Exit; - - /* copy advance */ - bitmap->root.advance = glyph->advance; - - if ( destroy ) - FT_Done_Glyph( glyph ); - - *the_glyph = FT_GLYPH( bitmap ); - - Exit: - if ( error && bitmap ) - FT_Done_Glyph( FT_GLYPH( bitmap ) ); - - return error; - - Bad: - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - - /* documentation is in ftglyph.h */ - - FT_EXPORT_DEF( void ) - FT_Done_Glyph( FT_Glyph glyph ) - { - if ( glyph ) - { - FT_Memory memory = glyph->library->memory; - const FT_Glyph_Class* clazz = glyph->clazz; - - - if ( clazz->glyph_done ) - clazz->glyph_done( glyph ); - - FT_FREE( glyph ); - } - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftgxval.c b/third_party/freetype/src/base/ftgxval.c deleted file mode 100644 index 58868f2e86bc0bfc3c2021055bda0f3493897029..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftgxval.c +++ /dev/null @@ -1,142 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgxval.c */ -/* */ -/* FreeType API for validating TrueTyepGX/AAT tables (body). */ -/* */ -/* Copyright 2004-2015 by */ -/* Masatake YAMATO, Redhat K.K, */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/***************************************************************************/ -/* */ -/* gxvalid is derived from both gxlayout module and otvalid module. */ -/* Development of gxlayout is supported by the Information-technology */ -/* Promotion Agency(IPA), Japan. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_GX_VALIDATE_H - - - /* documentation is in ftgxval.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_TrueTypeGX_Validate( FT_Face face, - FT_UInt validation_flags, - FT_Bytes tables[FT_VALIDATE_GX_LENGTH], - FT_UInt table_length ) - { - FT_Service_GXvalidate service; - FT_Error error; - - - if ( !face ) - { - error = FT_THROW( Invalid_Face_Handle ); - goto Exit; - } - - if ( !tables ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE ); - - if ( service ) - error = service->validate( face, - validation_flags, - tables, - table_length ); - else - error = FT_THROW( Unimplemented_Feature ); - - Exit: - return error; - } - - - FT_EXPORT_DEF( void ) - FT_TrueTypeGX_Free( FT_Face face, - FT_Bytes table ) - { - FT_Memory memory; - - - if ( !face ) - return; - - memory = FT_FACE_MEMORY( face ); - - FT_FREE( table ); - } - - - FT_EXPORT_DEF( FT_Error ) - FT_ClassicKern_Validate( FT_Face face, - FT_UInt validation_flags, - FT_Bytes *ckern_table ) - { - FT_Service_CKERNvalidate service; - FT_Error error; - - - if ( !face ) - { - error = FT_THROW( Invalid_Face_Handle ); - goto Exit; - } - - if ( !ckern_table ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE ); - - if ( service ) - error = service->validate( face, - validation_flags, - ckern_table ); - else - error = FT_THROW( Unimplemented_Feature ); - - Exit: - return error; - } - - - FT_EXPORT_DEF( void ) - FT_ClassicKern_Free( FT_Face face, - FT_Bytes table ) - { - FT_Memory memory; - - - if ( !face ) - return; - - memory = FT_FACE_MEMORY( face ); - - - FT_FREE( table ); - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftinit.c b/third_party/freetype/src/base/ftinit.c deleted file mode 100644 index b65a91d06c6819217e54689d6fba1a5c075c1ad1..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftinit.c +++ /dev/null @@ -1,286 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftinit.c */ -/* */ -/* FreeType initialization layer (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* The purpose of this file is to implement the following two */ - /* functions: */ - /* */ - /* FT_Add_Default_Modules(): */ - /* This function is used to add the set of default modules to a */ - /* fresh new library object. The set is taken from the header file */ - /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */ - /* Build System' for more information. */ - /* */ - /* FT_Init_FreeType(): */ - /* This function creates a system object for the current platform, */ - /* builds a library out of it, then calls FT_Default_Drivers(). */ - /* */ - /* Note that even if FT_Init_FreeType() uses the implementation of the */ - /* system object defined at build time, client applications are still */ - /* able to provide their own `ftsystem.c'. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H -#include FT_MODULE_H -#include "basepic.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_init - - -#ifndef FT_CONFIG_OPTION_PIC - - -#undef FT_USE_MODULE -#ifdef __cplusplus -#define FT_USE_MODULE( type, x ) extern "C" const type x; -#else -#define FT_USE_MODULE( type, x ) extern const type x; -#endif - -#include FT_CONFIG_MODULES_H - -#undef FT_USE_MODULE -#define FT_USE_MODULE( type, x ) (const FT_Module_Class*)&(x), - - static - const FT_Module_Class* const ft_default_modules[] = - { -#include FT_CONFIG_MODULES_H - 0 - }; - - -#else /* FT_CONFIG_OPTION_PIC */ - - -#ifdef __cplusplus -#define FT_EXTERNC extern "C" -#else -#define FT_EXTERNC extern -#endif - - /* declare the module's class creation/destruction functions */ -#undef FT_USE_MODULE -#define FT_USE_MODULE( type, x ) \ - FT_EXTERNC FT_Error \ - FT_Create_Class_ ## x( FT_Library library, \ - FT_Module_Class* *output_class ); \ - FT_EXTERNC void \ - FT_Destroy_Class_ ## x( FT_Library library, \ - FT_Module_Class* clazz ); - -#include FT_CONFIG_MODULES_H - - /* count all module classes */ -#undef FT_USE_MODULE -#define FT_USE_MODULE( type, x ) MODULE_CLASS_ ## x, - - enum - { -#include FT_CONFIG_MODULES_H - FT_NUM_MODULE_CLASSES - }; - - /* destroy all module classes */ -#undef FT_USE_MODULE -#define FT_USE_MODULE( type, x ) \ - if ( classes[i] ) \ - { \ - FT_Destroy_Class_ ## x( library, classes[i] ); \ - } \ - i++; - - - FT_BASE_DEF( void ) - ft_destroy_default_module_classes( FT_Library library ) - { - FT_Module_Class* *classes; - FT_Memory memory; - FT_UInt i; - BasePIC* pic_container = (BasePIC*)library->pic_container.base; - - - if ( !pic_container->default_module_classes ) - return; - - memory = library->memory; - classes = pic_container->default_module_classes; - i = 0; - -#include FT_CONFIG_MODULES_H - - FT_FREE( classes ); - pic_container->default_module_classes = NULL; - } - - - /* initialize all module classes and the pointer table */ -#undef FT_USE_MODULE -#define FT_USE_MODULE( type, x ) \ - error = FT_Create_Class_ ## x( library, &clazz ); \ - if ( error ) \ - goto Exit; \ - classes[i++] = clazz; - - - FT_BASE_DEF( FT_Error ) - ft_create_default_module_classes( FT_Library library ) - { - FT_Error error; - FT_Memory memory; - FT_Module_Class* *classes = NULL; - FT_Module_Class* clazz; - FT_UInt i; - BasePIC* pic_container = (BasePIC*)library->pic_container.base; - - - memory = library->memory; - - pic_container->default_module_classes = NULL; - - if ( FT_ALLOC( classes, sizeof ( FT_Module_Class* ) * - ( FT_NUM_MODULE_CLASSES + 1 ) ) ) - return error; - - /* initialize all pointers to 0, especially the last one */ - for ( i = 0; i < FT_NUM_MODULE_CLASSES; i++ ) - classes[i] = NULL; - classes[FT_NUM_MODULE_CLASSES] = NULL; - - i = 0; - -#include FT_CONFIG_MODULES_H - - Exit: - if ( error ) - ft_destroy_default_module_classes( library ); - else - pic_container->default_module_classes = classes; - - return error; - } - - -#endif /* FT_CONFIG_OPTION_PIC */ - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( void ) - FT_Add_Default_Modules( FT_Library library ) - { - FT_Error error; - const FT_Module_Class* const* cur; - - - /* FT_DEFAULT_MODULES_GET dereferences `library' in PIC mode */ -#ifdef FT_CONFIG_OPTION_PIC - if ( !library ) - return; -#endif - - /* GCC 4.6 warns the type difference: - * FT_Module_Class** != const FT_Module_Class* const* - */ - cur = (const FT_Module_Class* const*)FT_DEFAULT_MODULES_GET; - - /* test for valid `library' delayed to FT_Add_Module() */ - while ( *cur ) - { - error = FT_Add_Module( library, *cur ); - /* notify errors, but don't stop */ - if ( error ) - FT_TRACE0(( "FT_Add_Default_Module:" - " Cannot install `%s', error = 0x%x\n", - (*cur)->module_name, error )); - cur++; - } - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Init_FreeType( FT_Library *alibrary ) - { - FT_Error error; - FT_Memory memory; - - - /* check of `alibrary' delayed to `FT_New_Library' */ - - /* First of all, allocate a new system object -- this function is part */ - /* of the system-specific component, i.e. `ftsystem.c'. */ - - memory = FT_New_Memory(); - if ( !memory ) - { - FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" )); - return FT_THROW( Unimplemented_Feature ); - } - - /* build a library out of it, then fill it with the set of */ - /* default drivers. */ - - error = FT_New_Library( memory, alibrary ); - if ( error ) - FT_Done_Memory( memory ); - else - FT_Add_Default_Modules( *alibrary ); - - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Done_FreeType( FT_Library library ) - { - FT_Memory memory; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - memory = library->memory; - - /* Discard the library object */ - FT_Done_Library( library ); - - /* discard memory manager */ - FT_Done_Memory( memory ); - - return FT_Err_Ok; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftlcdfil.c b/third_party/freetype/src/base/ftlcdfil.c deleted file mode 100644 index ff6f7e98ceb5398ce491c2bc112f160f9ea77bdc..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftlcdfil.c +++ /dev/null @@ -1,398 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftlcdfil.c */ -/* */ -/* FreeType API for color filtering of subpixel bitmap glyphs (body). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_LCD_FILTER_H -#include FT_IMAGE_H -#include FT_INTERNAL_OBJECTS_H - - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - -/* define USE_LEGACY to implement the legacy filter */ -#define USE_LEGACY - - /* FIR filter used by the default and light filters */ - static void - _ft_lcd_filter_fir( FT_Bitmap* bitmap, - FT_Render_Mode mode, - FT_Library library ) - { - FT_Byte* weights = library->lcd_weights; - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - - - /* horizontal in-place FIR filter */ - if ( mode == FT_RENDER_MODE_LCD && width >= 4 ) - { - FT_Byte* line = bitmap->buffer; - - - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - - /* `fir' and `pix' must be at least 32 bit wide, since the sum of */ - /* the values in `weights' can exceed 0xFF */ - - for ( ; height > 0; height--, line += bitmap->pitch ) - { - FT_UInt fir[4]; /* below, `pix' is used as the 5th element */ - FT_UInt val1, xx; - - - val1 = line[0]; - fir[0] = weights[2] * val1; - fir[1] = weights[3] * val1; - fir[2] = weights[4] * val1; - fir[3] = 0; - - val1 = line[1]; - fir[0] += weights[1] * val1; - fir[1] += weights[2] * val1; - fir[2] += weights[3] * val1; - fir[3] += weights[4] * val1; - - for ( xx = 2; xx < width; xx++ ) - { - FT_UInt val, pix; - - - val = line[xx]; - pix = fir[0] + weights[0] * val; - fir[0] = fir[1] + weights[1] * val; - fir[1] = fir[2] + weights[2] * val; - fir[2] = fir[3] + weights[3] * val; - fir[3] = weights[4] * val; - - pix >>= 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - line[xx - 2] = (FT_Byte)pix; - } - - { - FT_UInt pix; - - - pix = fir[0] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - line[xx - 2] = (FT_Byte)pix; - - pix = fir[1] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - line[xx - 1] = (FT_Byte)pix; - } - } - } - - /* vertical in-place FIR filter */ - else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 ) - { - FT_Byte* column = bitmap->buffer; - FT_Int pitch = bitmap->pitch; - - - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - - for ( ; width > 0; width--, column++ ) - { - FT_Byte* col = column; - FT_UInt fir[4]; /* below, `pix' is used as the 5th element */ - FT_UInt val1, yy; - - - val1 = col[0]; - fir[0] = weights[2] * val1; - fir[1] = weights[3] * val1; - fir[2] = weights[4] * val1; - fir[3] = 0; - col += pitch; - - val1 = col[0]; - fir[0] += weights[1] * val1; - fir[1] += weights[2] * val1; - fir[2] += weights[3] * val1; - fir[3] += weights[4] * val1; - col += pitch; - - for ( yy = 2; yy < height; yy++ ) - { - FT_UInt val, pix; - - - val = col[0]; - pix = fir[0] + weights[0] * val; - fir[0] = fir[1] + weights[1] * val; - fir[1] = fir[2] + weights[2] * val; - fir[2] = fir[3] + weights[3] * val; - fir[3] = weights[4] * val; - - pix >>= 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - col[-2 * pitch] = (FT_Byte)pix; - col += pitch; - } - - { - FT_UInt pix; - - - pix = fir[0] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - col[-2 * pitch] = (FT_Byte)pix; - - pix = fir[1] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - col[-pitch] = (FT_Byte)pix; - } - } - } - } - - -#ifdef USE_LEGACY - - /* intra-pixel filter used by the legacy filter */ - static void - _ft_lcd_filter_legacy( FT_Bitmap* bitmap, - FT_Render_Mode mode, - FT_Library library ) - { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; - - static const unsigned int filters[3][3] = - { - { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 }, - { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 }, - { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } - }; - - FT_UNUSED( library ); - - - /* horizontal in-place intra-pixel filter */ - if ( mode == FT_RENDER_MODE_LCD && width >= 3 ) - { - FT_Byte* line = bitmap->buffer; - - - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - - for ( ; height > 0; height--, line += pitch ) - { - FT_UInt xx; - - - for ( xx = 0; xx < width; xx += 3 ) - { - FT_UInt r = 0; - FT_UInt g = 0; - FT_UInt b = 0; - FT_UInt p; - - - p = line[xx]; - r += filters[0][0] * p; - g += filters[0][1] * p; - b += filters[0][2] * p; - - p = line[xx + 1]; - r += filters[1][0] * p; - g += filters[1][1] * p; - b += filters[1][2] * p; - - p = line[xx + 2]; - r += filters[2][0] * p; - g += filters[2][1] * p; - b += filters[2][2] * p; - - line[xx] = (FT_Byte)( r / 65536 ); - line[xx + 1] = (FT_Byte)( g / 65536 ); - line[xx + 2] = (FT_Byte)( b / 65536 ); - } - } - } - else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 ) - { - FT_Byte* column = bitmap->buffer; - - - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - - for ( ; width > 0; width--, column++ ) - { - FT_Byte* col = column; - FT_Byte* col_end = col + (FT_Int)height * pitch; - - - for ( ; col < col_end; col += 3 * pitch ) - { - FT_UInt r = 0; - FT_UInt g = 0; - FT_UInt b = 0; - FT_UInt p; - - - p = col[0]; - r += filters[0][0] * p; - g += filters[0][1] * p; - b += filters[0][2] * p; - - p = col[pitch]; - r += filters[1][0] * p; - g += filters[1][1] * p; - b += filters[1][2] * p; - - p = col[pitch * 2]; - r += filters[2][0] * p; - g += filters[2][1] * p; - b += filters[2][2] * p; - - col[0] = (FT_Byte)( r / 65536 ); - col[pitch] = (FT_Byte)( g / 65536 ); - col[2 * pitch] = (FT_Byte)( b / 65536 ); - } - } - } - } - -#endif /* USE_LEGACY */ - - - FT_EXPORT_DEF( FT_Error ) - FT_Library_SetLcdFilterWeights( FT_Library library, - unsigned char *weights ) - { - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !weights ) - return FT_THROW( Invalid_Argument ); - - ft_memcpy( library->lcd_weights, weights, 5 ); - - return FT_Err_Ok; - } - - - FT_EXPORT_DEF( FT_Error ) - FT_Library_SetLcdFilter( FT_Library library, - FT_LcdFilter filter ) - { - static const FT_Byte light_filter[5] = - { 0x00, 0x55, 0x56, 0x55, 0x00 }; - /* the values here sum up to a value larger than 256, */ - /* providing a cheap gamma correction */ - static const FT_Byte default_filter[5] = - { 0x10, 0x40, 0x70, 0x40, 0x10 }; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - switch ( filter ) - { - case FT_LCD_FILTER_NONE: - library->lcd_filter_func = NULL; - library->lcd_extra = 0; - break; - - case FT_LCD_FILTER_DEFAULT: -#if defined( FT_FORCE_LEGACY_LCD_FILTER ) - - library->lcd_filter_func = _ft_lcd_filter_legacy; - library->lcd_extra = 0; - -#elif defined( FT_FORCE_LIGHT_LCD_FILTER ) - - ft_memcpy( library->lcd_weights, light_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; - -#else - - ft_memcpy( library->lcd_weights, default_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; - -#endif - - break; - - case FT_LCD_FILTER_LIGHT: - ft_memcpy( library->lcd_weights, light_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; - break; - -#ifdef USE_LEGACY - - case FT_LCD_FILTER_LEGACY: - library->lcd_filter_func = _ft_lcd_filter_legacy; - library->lcd_extra = 0; - break; - -#endif - - default: - return FT_THROW( Invalid_Argument ); - } - - library->lcd_filter = filter; - - return FT_Err_Ok; - } - -#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - - FT_EXPORT_DEF( FT_Error ) - FT_Library_SetLcdFilterWeights( FT_Library library, - unsigned char *weights ) - { - FT_UNUSED( library ); - FT_UNUSED( weights ); - - return FT_THROW( Unimplemented_Feature ); - } - - - FT_EXPORT_DEF( FT_Error ) - FT_Library_SetLcdFilter( FT_Library library, - FT_LcdFilter filter ) - { - FT_UNUSED( library ); - FT_UNUSED( filter ); - - return FT_THROW( Unimplemented_Feature ); - } - -#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftmac.c b/third_party/freetype/src/base/ftmac.c deleted file mode 100644 index 114bbb63919c4217afd05c2b5e81c2827cfae3be..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftmac.c +++ /dev/null @@ -1,1080 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmac.c */ -/* */ -/* Mac FOND support. Written by just@letterror.com. */ -/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */ -/* */ -/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */ -/* classic platforms built by MPW. */ -/* */ -/* Copyright 1996-2015 by */ -/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /* - Notes - - Mac suitcase files can (and often do!) contain multiple fonts. To - support this I use the face_index argument of FT_(Open|New)_Face() - functions, and pretend the suitcase file is a collection. - - Warning: fbit and NFNT bitmap resources are not supported yet. In old - sfnt fonts, bitmap glyph data for each size is stored in each `NFNT' - resources instead of the `bdat' table in the sfnt resource. Therefore, - face->num_fixed_sizes is set to 0, because bitmap data in `NFNT' - resource is unavailable at present. - - The Mac FOND support works roughly like this: - - - Check whether the offered stream points to a Mac suitcase file. This - is done by checking the file type: it has to be 'FFIL' or 'tfil'. The - stream that gets passed to our init_face() routine is a stdio stream, - which isn't usable for us, since the FOND resources live in the - resource fork. So we just grab the stream->pathname field. - - - Read the FOND resource into memory, then check whether there is a - TrueType font and/or(!) a Type 1 font available. - - - If there is a Type 1 font available (as a separate `LWFN' file), read - its data into memory, massage it slightly so it becomes PFB data, wrap - it into a memory stream, load the Type 1 driver and delegate the rest - of the work to it by calling FT_Open_Face(). (XXX TODO: after this - has been done, the kerning data from the FOND resource should be - appended to the face: On the Mac there are usually no AFM files - available. However, this is tricky since we need to map Mac char - codes to ps glyph names to glyph ID's...) - - - If there is a TrueType font (an `sfnt' resource), read it into memory, - wrap it into a memory stream, load the TrueType driver and delegate - the rest of the work to it, by calling FT_Open_Face(). - - - Some suitcase fonts (notably Onyx) might point the `LWFN' file to - itself, even though it doesn't contains `POST' resources. To handle - this special case without opening the file an extra time, we just - ignore errors from the `LWFN' and fallback to the `sfnt' if both are - available. - */ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TRUETYPE_TAGS_H -#include FT_INTERNAL_STREAM_H -#include "ftbase.h" - - /* This is for Mac OS X. Without redefinition, OS_INLINE */ - /* expands to `static inline' which doesn't survive the */ - /* -ansi compilation flag of GCC. */ -#if !HAVE_ANSI_OS_INLINE -#undef OS_INLINE -#define OS_INLINE static __inline__ -#endif - - /* `configure' checks the availability of `ResourceIndex' strictly */ - /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */ - /* not set (e.g., a build without `configure'), the availability */ - /* is guessed from the SDK version. */ -#ifndef HAVE_TYPE_RESOURCE_INDEX -#if !defined( MAC_OS_X_VERSION_10_5 ) || \ - ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 ) -#define HAVE_TYPE_RESOURCE_INDEX 0 -#else -#define HAVE_TYPE_RESOURCE_INDEX 1 -#endif -#endif /* !HAVE_TYPE_RESOURCE_INDEX */ - -#if ( HAVE_TYPE_RESOURCE_INDEX == 0 ) - typedef short ResourceIndex; -#endif - -#include <CoreServices/CoreServices.h> -#include <ApplicationServices/ApplicationServices.h> -#include <sys/syslimits.h> /* PATH_MAX */ - - /* Don't want warnings about our own use of deprecated functions. */ -#define FT_DEPRECATED_ATTRIBUTE - -#include FT_MAC_H - -#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */ -#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault -#endif - - - /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over - TrueType in case *both* are available (this is not common, - but it *is* possible). */ -#ifndef PREFER_LWFN -#define PREFER_LWFN 1 -#endif - - -#ifdef FT_MACINTOSH - - /* This function is deprecated because FSSpec is deprecated in Mac OS X */ - FT_EXPORT_DEF( FT_Error ) - FT_GetFile_From_Mac_Name( const char* fontName, - FSSpec* pathSpec, - FT_Long* face_index ) - { - FT_UNUSED( fontName ); - FT_UNUSED( pathSpec ); - FT_UNUSED( face_index ); - - return FT_THROW( Unimplemented_Feature ); - } - - - /* Private function. */ - /* The FSSpec type has been discouraged for a long time, */ - /* unfortunately an FSRef replacement API for */ - /* ATSFontGetFileSpecification() is only available in */ - /* Mac OS X 10.5 and later. */ - static OSStatus - FT_ATSFontGetFileReference( ATSFontRef ats_font_id, - FSRef* ats_font_ref ) - { -#if defined( MAC_OS_X_VERSION_10_5 ) && \ - ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - - OSStatus err; - - err = ATSFontGetFileReference( ats_font_id, ats_font_ref ); - - return err; -#elif __LP64__ /* No 64bit Carbon API on legacy platforms */ - FT_UNUSED( ats_font_id ); - FT_UNUSED( ats_font_ref ); - - - return fnfErr; -#else /* 32bit Carbon API on legacy platforms */ - OSStatus err; - FSSpec spec; - - - err = ATSFontGetFileSpecification( ats_font_id, &spec ); - if ( noErr == err ) - err = FSpMakeFSRef( &spec, ats_font_ref ); - - return err; -#endif - } - - - static FT_Error - FT_GetFileRef_From_Mac_ATS_Name( const char* fontName, - FSRef* ats_font_ref, - FT_Long* face_index ) - { - CFStringRef cf_fontName; - ATSFontRef ats_font_id; - - - *face_index = 0; - - cf_fontName = CFStringCreateWithCString( NULL, fontName, - kCFStringEncodingMacRoman ); - ats_font_id = ATSFontFindFromName( cf_fontName, - kATSOptionFlagsUnRestrictedScope ); - CFRelease( cf_fontName ); - - if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) - return FT_THROW( Unknown_File_Format ); - - if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) ) - return FT_THROW( Unknown_File_Format ); - - /* face_index calculation by searching preceding fontIDs */ - /* with same FSRef */ - { - ATSFontRef id2 = ats_font_id - 1; - FSRef ref2; - - - while ( id2 > 0 ) - { - if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) ) - break; - if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) ) - break; - - id2 --; - } - *face_index = ats_font_id - ( id2 + 1 ); - } - - return FT_Err_Ok; - } - - - FT_EXPORT_DEF( FT_Error ) - FT_GetFilePath_From_Mac_ATS_Name( const char* fontName, - UInt8* path, - UInt32 maxPathSize, - FT_Long* face_index ) - { - FSRef ref; - FT_Error err; - - - if ( !fontName || !face_index ) - return FT_THROW( Invalid_Argument) ; - - err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index ); - if ( err ) - return err; - - if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) ) - return FT_THROW( Unknown_File_Format ); - - return FT_Err_Ok; - } - - - /* This function is deprecated because FSSpec is deprecated in Mac OS X */ - FT_EXPORT_DEF( FT_Error ) - FT_GetFile_From_Mac_ATS_Name( const char* fontName, - FSSpec* pathSpec, - FT_Long* face_index ) - { -#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \ - ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) ) - FT_UNUSED( fontName ); - FT_UNUSED( pathSpec ); - FT_UNUSED( face_index ); - - return FT_THROW( Unimplemented_Feature ); -#else - FSRef ref; - FT_Error err; - - - if ( !fontName || !face_index ) - return FT_THROW( Invalid_Argument ); - - err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index ); - if ( err ) - return err; - - if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, - pathSpec, NULL ) ) - return FT_THROW( Unknown_File_Format ); - - return FT_Err_Ok; -#endif - } - - - static OSErr - FT_FSPathMakeRes( const UInt8* pathname, - ResFileRefNum* res ) - { - OSErr err; - FSRef ref; - - - if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) ) - return FT_THROW( Cannot_Open_Resource ); - - /* at present, no support for dfont format */ - err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res ); - if ( noErr == err ) - return err; - - /* fallback to original resource-fork font */ - *res = FSOpenResFile( &ref, fsRdPerm ); - err = ResError(); - - return err; - } - - - /* Return the file type for given pathname */ - static OSType - get_file_type_from_path( const UInt8* pathname ) - { - FSRef ref; - FSCatalogInfo info; - - - if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) ) - return ( OSType ) 0; - - if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info, - NULL, NULL, NULL ) ) - return ( OSType ) 0; - - return ((FInfo *)(info.finderInfo))->fdType; - } - - - /* Given a PostScript font name, create the Macintosh LWFN file name. */ - static void - create_lwfn_name( char* ps_name, - Str255 lwfn_file_name ) - { - int max = 5, count = 0; - FT_Byte* p = lwfn_file_name; - FT_Byte* q = (FT_Byte*)ps_name; - - - lwfn_file_name[0] = 0; - - while ( *q ) - { - if ( ft_isupper( *q ) ) - { - if ( count ) - max = 3; - count = 0; - } - if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) ) - { - *++p = *q; - lwfn_file_name[0]++; - count++; - } - q++; - } - } - - - static short - count_faces_sfnt( char* fond_data ) - { - /* The count is 1 greater than the value in the FOND. */ - /* Isn't that cute? :-) */ - - return EndianS16_BtoN( *( (short*)( fond_data + - sizeof ( FamRec ) ) ) ) + 1; - } - - - static short - count_faces_scalable( char* fond_data ) - { - AsscEntry* assoc; - short i, face, face_all; - - - face_all = EndianS16_BtoN( *( (short *)( fond_data + - sizeof ( FamRec ) ) ) ) + 1; - assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); - face = 0; - - for ( i = 0; i < face_all; i++ ) - { - if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) ) - face++; - } - return face; - } - - - /* Look inside the FOND data, answer whether there should be an SFNT - resource, and answer the name of a possible LWFN Type 1 file. - - Thanks to Paul Miller (paulm@profoundeffects.com) for the fix - to load a face OTHER than the first one in the FOND! - */ - - - static void - parse_fond( char* fond_data, - short* have_sfnt, - ResID* sfnt_id, - Str255 lwfn_file_name, - short face_index ) - { - AsscEntry* assoc; - AsscEntry* base_assoc; - FamRec* fond; - - - *sfnt_id = 0; - *have_sfnt = 0; - lwfn_file_name[0] = 0; - - fond = (FamRec*)fond_data; - assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); - base_assoc = assoc; - - /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */ - if ( 47 < face_index ) - return; - - /* Let's do a little range checking before we get too excited here */ - if ( face_index < count_faces_sfnt( fond_data ) ) - { - assoc += face_index; /* add on the face_index! */ - - /* if the face at this index is not scalable, - fall back to the first one (old behavior) */ - if ( EndianS16_BtoN( assoc->fontSize ) == 0 ) - { - *have_sfnt = 1; - *sfnt_id = EndianS16_BtoN( assoc->fontID ); - } - else if ( base_assoc->fontSize == 0 ) - { - *have_sfnt = 1; - *sfnt_id = EndianS16_BtoN( base_assoc->fontID ); - } - } - - if ( EndianS32_BtoN( fond->ffStylOff ) ) - { - unsigned char* p = (unsigned char*)fond_data; - StyleTable* style; - unsigned short string_count; - char ps_name[256]; - unsigned char* names[64]; - int i; - - - p += EndianS32_BtoN( fond->ffStylOff ); - style = (StyleTable*)p; - p += sizeof ( StyleTable ); - string_count = EndianS16_BtoN( *(short*)(p) ); - string_count = FT_MIN( 64, string_count ); - p += sizeof ( short ); - - for ( i = 0; i < string_count; i++ ) - { - names[i] = p; - p += names[i][0]; - p++; - } - - { - size_t ps_name_len = (size_t)names[0][0]; - - - if ( ps_name_len != 0 ) - { - ft_memcpy(ps_name, names[0] + 1, ps_name_len); - ps_name[ps_name_len] = 0; - } - if ( style->indexes[face_index] > 1 && - style->indexes[face_index] <= string_count ) - { - unsigned char* suffixes = names[style->indexes[face_index] - 1]; - - - for ( i = 1; i <= suffixes[0]; i++ ) - { - unsigned char* s; - size_t j = suffixes[i] - 1; - - - if ( j < string_count && ( s = names[j] ) != NULL ) - { - size_t s_len = (size_t)s[0]; - - - if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) ) - { - ft_memcpy( ps_name + ps_name_len, s + 1, s_len ); - ps_name_len += s_len; - ps_name[ps_name_len] = 0; - } - } - } - } - } - - create_lwfn_name( ps_name, lwfn_file_name ); - } - } - - - static FT_Error - lookup_lwfn_by_fond( const UInt8* path_fond, - ConstStr255Param base_lwfn, - UInt8* path_lwfn, - size_t path_size ) - { - FSRef ref, par_ref; - size_t dirname_len; - - - /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */ - /* We should not extract parent directory by string manipulation. */ - - if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) ) - return FT_THROW( Invalid_Argument ); - - if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, - NULL, NULL, NULL, &par_ref ) ) - return FT_THROW( Invalid_Argument ); - - if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) ) - return FT_THROW( Invalid_Argument ); - - if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size ) - return FT_THROW( Invalid_Argument ); - - /* now we have absolute dirname in path_lwfn */ - ft_strcat( (char *)path_lwfn, "/" ); - dirname_len = ft_strlen( (char *)path_lwfn ); - ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 ); - path_lwfn[dirname_len + base_lwfn[0]] = '\0'; - - if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) ) - return FT_THROW( Cannot_Open_Resource ); - - if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, - NULL, NULL, NULL, NULL ) ) - return FT_THROW( Cannot_Open_Resource ); - - return FT_Err_Ok; - } - - - static short - count_faces( Handle fond, - const UInt8* pathname ) - { - ResID sfnt_id; - short have_sfnt, have_lwfn; - Str255 lwfn_file_name; - UInt8 buff[PATH_MAX]; - FT_Error err; - short num_faces; - - - have_sfnt = have_lwfn = 0; - - parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 ); - - if ( lwfn_file_name[0] ) - { - err = lookup_lwfn_by_fond( pathname, lwfn_file_name, - buff, sizeof ( buff ) ); - if ( !err ) - have_lwfn = 1; - } - - if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) ) - num_faces = 1; - else - num_faces = count_faces_scalable( *fond ); - - return num_faces; - } - - - /* Read Type 1 data from the POST resources inside the LWFN file, - return a PFB buffer. This is somewhat convoluted because the FT2 - PFB parser wants the ASCII header as one chunk, and the LWFN - chunks are often not organized that way, so we glue chunks - of the same type together. */ - static FT_Error - read_lwfn( FT_Memory memory, - ResFileRefNum res, - FT_Byte** pfb_data, - FT_ULong* size ) - { - FT_Error error = FT_Err_Ok; - ResID res_id; - unsigned char *buffer, *p, *size_p = NULL; - FT_ULong total_size = 0; - FT_ULong old_total_size = 0; - FT_ULong post_size, pfb_chunk_size; - Handle post_data; - char code, last_code; - - - UseResFile( res ); - - /* First pass: load all POST resources, and determine the size of */ - /* the output buffer. */ - res_id = 501; - last_code = -1; - - for (;;) - { - post_data = Get1Resource( TTAG_POST, res_id++ ); - if ( post_data == NULL ) - break; /* we are done */ - - code = (*post_data)[0]; - - if ( code != last_code ) - { - if ( code == 5 ) - total_size += 2; /* just the end code */ - else - total_size += 6; /* code + 4 bytes chunk length */ - } - - total_size += (FT_ULong)GetHandleSize( post_data ) - 2; - last_code = code; - - /* detect resource fork overflow */ - if ( FT_MAC_RFORK_MAX_LEN < total_size ) - { - error = FT_THROW( Array_Too_Large ); - goto Error; - } - - old_total_size = total_size; - } - - if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) - goto Error; - - /* Second pass: append all POST data to the buffer, add PFB fields. */ - /* Glue all consecutive chunks of the same type together. */ - p = buffer; - res_id = 501; - last_code = -1; - pfb_chunk_size = 0; - - for (;;) - { - post_data = Get1Resource( TTAG_POST, res_id++ ); - if ( post_data == NULL ) - break; /* we are done */ - - post_size = (FT_ULong)GetHandleSize( post_data ) - 2; - code = (*post_data)[0]; - - if ( code != last_code ) - { - if ( last_code != -1 ) - { - /* we are done adding a chunk, fill in the size field */ - if ( size_p != NULL ) - { - *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF ); - *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF ); - *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF ); - *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF ); - } - pfb_chunk_size = 0; - } - - *p++ = 0x80; - if ( code == 5 ) - *p++ = 0x03; /* the end */ - else if ( code == 2 ) - *p++ = 0x02; /* binary segment */ - else - *p++ = 0x01; /* ASCII segment */ - - if ( code != 5 ) - { - size_p = p; /* save for later */ - p += 4; /* make space for size field */ - } - } - - ft_memcpy( p, *post_data + 2, post_size ); - pfb_chunk_size += post_size; - p += post_size; - last_code = code; - } - - *pfb_data = buffer; - *size = total_size; - - Error: - CloseResFile( res ); - return error; - } - - - /* Create a new FT_Face from a file path to an LWFN file. */ - static FT_Error - FT_New_Face_From_LWFN( FT_Library library, - const UInt8* pathname, - FT_Long face_index, - FT_Face* aface ) - { - FT_Byte* pfb_data; - FT_ULong pfb_size; - FT_Error error; - ResFileRefNum res; - - - if ( noErr != FT_FSPathMakeRes( pathname, &res ) ) - return FT_THROW( Cannot_Open_Resource ); - - pfb_data = NULL; - pfb_size = 0; - error = read_lwfn( library->memory, res, &pfb_data, &pfb_size ); - CloseResFile( res ); /* PFB is already loaded, useless anymore */ - if ( error ) - return error; - - return open_face_from_buffer( library, - pfb_data, - pfb_size, - face_index, - "type1", - aface ); - } - - - /* Create a new FT_Face from an SFNT resource, specified by res ID. */ - static FT_Error - FT_New_Face_From_SFNT( FT_Library library, - ResID sfnt_id, - FT_Long face_index, - FT_Face* aface ) - { - Handle sfnt = NULL; - FT_Byte* sfnt_data; - size_t sfnt_size; - FT_Error error = FT_Err_Ok; - FT_Memory memory = library->memory; - int is_cff, is_sfnt_ps; - - - sfnt = GetResource( TTAG_sfnt, sfnt_id ); - if ( sfnt == NULL ) - return FT_THROW( Invalid_Handle ); - - sfnt_size = (FT_ULong)GetHandleSize( sfnt ); - - /* detect resource fork overflow */ - if ( FT_MAC_RFORK_MAX_LEN < sfnt_size ) - return FT_THROW( Array_Too_Large ); - - if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) - { - ReleaseResource( sfnt ); - return error; - } - - ft_memcpy( sfnt_data, *sfnt, sfnt_size ); - ReleaseResource( sfnt ); - - is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); - is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 ); - - if ( is_sfnt_ps ) - { - FT_Stream stream; - - - if ( FT_NEW( stream ) ) - goto Try_OpenType; - - FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size ); - if ( !open_face_PS_from_sfnt_stream( library, - stream, - face_index, - 0, NULL, - aface ) ) - { - FT_Stream_Close( stream ); - FT_FREE( stream ); - FT_FREE( sfnt_data ); - goto Exit; - } - - FT_FREE( stream ); - } - Try_OpenType: - error = open_face_from_buffer( library, - sfnt_data, - sfnt_size, - face_index, - is_cff ? "cff" : "truetype", - aface ); - Exit: - return error; - } - - - /* Create a new FT_Face from a file path to a suitcase file. */ - static FT_Error - FT_New_Face_From_Suitcase( FT_Library library, - const UInt8* pathname, - FT_Long face_index, - FT_Face* aface ) - { - FT_Error error = FT_ERR( Cannot_Open_Resource ); - ResFileRefNum res_ref; - ResourceIndex res_index; - Handle fond; - short num_faces_in_res; - - - if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) ) - return FT_THROW( Cannot_Open_Resource ); - - UseResFile( res_ref ); - if ( ResError() ) - return FT_THROW( Cannot_Open_Resource ); - - num_faces_in_res = 0; - for ( res_index = 1; ; ++res_index ) - { - short num_faces_in_fond; - - - fond = Get1IndResource( TTAG_FOND, res_index ); - if ( ResError() ) - break; - - num_faces_in_fond = count_faces( fond, pathname ); - num_faces_in_res += num_faces_in_fond; - - if ( 0 <= face_index && face_index < num_faces_in_fond && error ) - error = FT_New_Face_From_FOND( library, fond, face_index, aface ); - - face_index -= num_faces_in_fond; - } - - CloseResFile( res_ref ); - if ( !error && aface && *aface ) - (*aface)->num_faces = num_faces_in_res; - return error; - } - - - /* documentation is in ftmac.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_New_Face_From_FOND( FT_Library library, - Handle fond, - FT_Long face_index, - FT_Face* aface ) - { - short have_sfnt, have_lwfn = 0; - ResID sfnt_id, fond_id; - OSType fond_type; - Str255 fond_name; - Str255 lwfn_file_name; - UInt8 path_lwfn[PATH_MAX]; - OSErr err; - FT_Error error = FT_Err_Ok; - - - /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */ - - GetResInfo( fond, &fond_id, &fond_type, fond_name ); - if ( ResError() != noErr || fond_type != TTAG_FOND ) - return FT_THROW( Invalid_File_Format ); - - parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index ); - - if ( lwfn_file_name[0] ) - { - ResFileRefNum res; - - - res = HomeResFile( fond ); - if ( noErr != ResError() ) - goto found_no_lwfn_file; - - { - UInt8 path_fond[PATH_MAX]; - FSRef ref; - - - err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum, - NULL, NULL, NULL, &ref, NULL ); - if ( noErr != err ) - goto found_no_lwfn_file; - - err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) ); - if ( noErr != err ) - goto found_no_lwfn_file; - - error = lookup_lwfn_by_fond( path_fond, lwfn_file_name, - path_lwfn, sizeof ( path_lwfn ) ); - if ( !error ) - have_lwfn = 1; - } - } - - if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) ) - error = FT_New_Face_From_LWFN( library, - path_lwfn, - face_index, - aface ); - else - error = FT_THROW( Unknown_File_Format ); - - found_no_lwfn_file: - if ( have_sfnt && error ) - error = FT_New_Face_From_SFNT( library, - sfnt_id, - face_index, - aface ); - - return error; - } - - - /* Common function to load a new FT_Face from a resource file. */ - static FT_Error - FT_New_Face_From_Resource( FT_Library library, - const UInt8* pathname, - FT_Long face_index, - FT_Face* aface ) - { - OSType file_type; - FT_Error error; - - - /* LWFN is a (very) specific file format, check for it explicitly */ - file_type = get_file_type_from_path( pathname ); - if ( file_type == TTAG_LWFN ) - return FT_New_Face_From_LWFN( library, pathname, face_index, aface ); - - /* Otherwise the file type doesn't matter (there are more than */ - /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */ - /* if it works, fine. */ - - error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface ); - if ( error == 0 ) - return error; - - /* let it fall through to normal loader (.ttf, .otf, etc.); */ - /* we signal this by returning no error and no FT_Face */ - *aface = NULL; - return 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face */ - /* */ - /* <Description> */ - /* This is the Mac-specific implementation of FT_New_Face. In */ - /* addition to the standard FT_New_Face() functionality, it also */ - /* accepts pathnames to Mac suitcase files. For further */ - /* documentation see the original FT_New_Face() in freetype.h. */ - /* */ - FT_EXPORT_DEF( FT_Error ) - FT_New_Face( FT_Library library, - const char* pathname, - FT_Long face_index, - FT_Face* aface ) - { - FT_Open_Args args; - FT_Error error; - - - /* test for valid `library' and `aface' delayed to FT_Open_Face() */ - if ( !pathname ) - return FT_THROW( Invalid_Argument ); - - *aface = NULL; - - /* try resourcefork based font: LWFN, FFIL */ - error = FT_New_Face_From_Resource( library, (UInt8 *)pathname, - face_index, aface ); - if ( error != 0 || *aface != NULL ) - return error; - - /* let it fall through to normal loader (.ttf, .otf, etc.) */ - args.flags = FT_OPEN_PATHNAME; - args.pathname = (char*)pathname; - return FT_Open_Face( library, &args, face_index, aface ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face_From_FSRef */ - /* */ - /* <Description> */ - /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */ - /* accepts an FSRef instead of a path. */ - /* */ - /* This function is deprecated because Carbon data types (FSRef) */ - /* are not cross-platform, and thus not suitable for the freetype API. */ - FT_EXPORT_DEF( FT_Error ) - FT_New_Face_From_FSRef( FT_Library library, - const FSRef* ref, - FT_Long face_index, - FT_Face* aface ) - { - FT_Error error; - FT_Open_Args args; - - OSErr err; - UInt8 pathname[PATH_MAX]; - - - /* check of `library' and `aface' delayed to */ - /* `FT_New_Face_From_Resource' */ - - if ( !ref ) - return FT_THROW( Invalid_Argument ); - - err = FSRefMakePath( ref, pathname, sizeof ( pathname ) ); - if ( err ) - error = FT_THROW( Cannot_Open_Resource ); - - error = FT_New_Face_From_Resource( library, pathname, face_index, aface ); - if ( error != 0 || *aface != NULL ) - return error; - - /* fallback to datafork font */ - args.flags = FT_OPEN_PATHNAME; - args.pathname = (char*)pathname; - return FT_Open_Face( library, &args, face_index, aface ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_New_Face_From_FSSpec */ - /* */ - /* <Description> */ - /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */ - /* accepts an FSSpec instead of a path. */ - /* */ - /* This function is deprecated because FSSpec is deprecated in Mac OS X */ - FT_EXPORT_DEF( FT_Error ) - FT_New_Face_From_FSSpec( FT_Library library, - const FSSpec* spec, - FT_Long face_index, - FT_Face* aface ) - { -#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \ - ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) ) - FT_UNUSED( library ); - FT_UNUSED( spec ); - FT_UNUSED( face_index ); - FT_UNUSED( aface ); - - return FT_THROW( Unimplemented_Feature ); -#else - FSRef ref; - - - /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */ - - if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr ) - return FT_THROW( Invalid_Argument ); - else - return FT_New_Face_From_FSRef( library, &ref, face_index, aface ); -#endif - } - -#endif /* FT_MACINTOSH */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftmm.c b/third_party/freetype/src/base/ftmm.c deleted file mode 100644 index 7c012aa4386b346976779ac23f43b6fef9969034..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftmm.c +++ /dev/null @@ -1,234 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmm.c */ -/* */ -/* Multiple Master font support (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_MULTIPLE_MASTERS_H -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_MULTIPLE_MASTERS_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_mm - - - static FT_Error - ft_face_get_mm_service( FT_Face face, - FT_Service_MultiMasters *aservice ) - { - FT_Error error; - - - *aservice = NULL; - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - error = FT_ERR( Invalid_Argument ); - - if ( FT_HAS_MULTIPLE_MASTERS( face ) ) - { - FT_FACE_LOOKUP_SERVICE( face, - *aservice, - MULTI_MASTERS ); - - if ( *aservice ) - error = FT_Err_Ok; - } - - return error; - } - - - /* documentation is in ftmm.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Multi_Master( FT_Face face, - FT_Multi_Master *amaster ) - { - FT_Error error; - FT_Service_MultiMasters service; - - - /* check of `face' delayed to `ft_face_get_mm_service' */ - - if ( !amaster ) - return FT_THROW( Invalid_Argument ); - - error = ft_face_get_mm_service( face, &service ); - if ( !error ) - { - error = FT_ERR( Invalid_Argument ); - if ( service->get_mm ) - error = service->get_mm( face, amaster ); - } - - return error; - } - - - /* documentation is in ftmm.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_MM_Var( FT_Face face, - FT_MM_Var* *amaster ) - { - FT_Error error; - FT_Service_MultiMasters service; - - - /* check of `face' delayed to `ft_face_get_mm_service' */ - - if ( !amaster ) - return FT_THROW( Invalid_Argument ); - - error = ft_face_get_mm_service( face, &service ); - if ( !error ) - { - error = FT_ERR( Invalid_Argument ); - if ( service->get_mm_var ) - error = service->get_mm_var( face, amaster ); - } - - return error; - } - - - /* documentation is in ftmm.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_MM_Design_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ) - { - FT_Error error; - FT_Service_MultiMasters service; - - - /* check of `face' delayed to `ft_face_get_mm_service' */ - - if ( !coords ) - return FT_THROW( Invalid_Argument ); - - error = ft_face_get_mm_service( face, &service ); - if ( !error ) - { - error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_design ) - error = service->set_mm_design( face, num_coords, coords ); - } - - return error; - } - - - /* documentation is in ftmm.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_Var_Design_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - FT_Error error; - FT_Service_MultiMasters service; - - - /* check of `face' delayed to `ft_face_get_mm_service' */ - - if ( !coords ) - return FT_THROW( Invalid_Argument ); - - error = ft_face_get_mm_service( face, &service ); - if ( !error ) - { - error = FT_ERR( Invalid_Argument ); - if ( service->set_var_design ) - error = service->set_var_design( face, num_coords, coords ); - } - - return error; - } - - - /* documentation is in ftmm.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_MM_Blend_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - FT_Error error; - FT_Service_MultiMasters service; - - - /* check of `face' delayed to `ft_face_get_mm_service' */ - - if ( !coords ) - return FT_THROW( Invalid_Argument ); - - error = ft_face_get_mm_service( face, &service ); - if ( !error ) - { - error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_blend ) - error = service->set_mm_blend( face, num_coords, coords ); - } - - return error; - } - - - /* documentation is in ftmm.h */ - - /* This is exactly the same as the previous function. It exists for */ - /* orthogonality. */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_Var_Blend_Coordinates( FT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - FT_Error error; - FT_Service_MultiMasters service; - - - /* check of `face' delayed to `ft_face_get_mm_service' */ - - if ( !coords ) - return FT_THROW( Invalid_Argument ); - - error = ft_face_get_mm_service( face, &service ); - if ( !error ) - { - error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_blend ) - error = service->set_mm_blend( face, num_coords, coords ); - } - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftobjs.c b/third_party/freetype/src/base/ftobjs.c deleted file mode 100644 index f0c2e77fccf5b3e3b31224bacfdae2e9252f751c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftobjs.c +++ /dev/null @@ -1,4933 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftobjs.c */ -/* */ -/* The FreeType private base classes (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_LIST_H -#include FT_OUTLINE_H -#include FT_INTERNAL_VALIDATE_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_RFORK_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ -#include FT_TRUETYPE_TABLES_H -#include FT_TRUETYPE_TAGS_H -#include FT_TRUETYPE_IDS_H - -#include FT_SERVICE_PROPERTIES_H -#include FT_SERVICE_SFNT_H -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_GLYPH_DICT_H -#include FT_SERVICE_TT_CMAP_H -#include FT_SERVICE_KERNING_H -#include FT_SERVICE_TRUETYPE_ENGINE_H - -#ifdef FT_CONFIG_OPTION_MAC_FONTS -#include "ftbase.h" -#endif - - -#ifdef FT_DEBUG_LEVEL_TRACE - -#include FT_BITMAP_H - -#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ - /* We disable the warning `conversion from XXX to YYY, */ - /* possible loss of data' in order to compile cleanly with */ - /* the maximum level of warnings: `md5.c' is non-FreeType */ - /* code, and it gets used during development builds only. */ -#pragma warning( push ) -#pragma warning( disable : 4244 ) -#endif /* _MSC_VER */ - - /* it's easiest to include `md5.c' directly */ -#include "md5.c" - -#if defined( _MSC_VER ) -#pragma warning( pop ) -#endif - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - -#define GRID_FIT_METRICS - - - FT_BASE_DEF( FT_Pointer ) - ft_service_list_lookup( FT_ServiceDesc service_descriptors, - const char* service_id ) - { - FT_Pointer result = NULL; - FT_ServiceDesc desc = service_descriptors; - - - if ( desc && service_id ) - { - for ( ; desc->serv_id != NULL; desc++ ) - { - if ( ft_strcmp( desc->serv_id, service_id ) == 0 ) - { - result = (FT_Pointer)desc->serv_data; - break; - } - } - } - - return result; - } - - - FT_BASE_DEF( void ) - ft_validator_init( FT_Validator valid, - const FT_Byte* base, - const FT_Byte* limit, - FT_ValidationLevel level ) - { - valid->base = base; - valid->limit = limit; - valid->level = level; - valid->error = FT_Err_Ok; - } - - - FT_BASE_DEF( FT_Int ) - ft_validator_run( FT_Validator valid ) - { - /* This function doesn't work! None should call it. */ - FT_UNUSED( valid ); - - return -1; - } - - - FT_BASE_DEF( void ) - ft_validator_error( FT_Validator valid, - FT_Error error ) - { - /* since the cast below also disables the compiler's */ - /* type check, we introduce a dummy variable, which */ - /* will be optimized away */ - volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer; - - - valid->error = error; - - /* throw away volatileness; use `jump_buffer' or the */ - /* compiler may warn about an unused local variable */ - ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** S T R E A M ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* create a new input stream from an FT_Open_Args structure */ - /* */ - FT_BASE_DEF( FT_Error ) - FT_Stream_New( FT_Library library, - const FT_Open_Args* args, - FT_Stream *astream ) - { - FT_Error error; - FT_Memory memory; - FT_Stream stream = NULL; - - - *astream = NULL; - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !args ) - return FT_THROW( Invalid_Argument ); - - memory = library->memory; - - if ( FT_NEW( stream ) ) - goto Exit; - - stream->memory = memory; - - if ( args->flags & FT_OPEN_MEMORY ) - { - /* create a memory-based stream */ - FT_Stream_OpenMemory( stream, - (const FT_Byte*)args->memory_base, - (FT_ULong)args->memory_size ); - } - -#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT - - else if ( args->flags & FT_OPEN_PATHNAME ) - { - /* create a normal system stream */ - error = FT_Stream_Open( stream, args->pathname ); - stream->pathname.pointer = args->pathname; - } - else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) - { - /* use an existing, user-provided stream */ - - /* in this case, we do not need to allocate a new stream object */ - /* since the caller is responsible for closing it himself */ - FT_FREE( stream ); - stream = args->stream; - } - -#endif - - else - error = FT_THROW( Invalid_Argument ); - - if ( error ) - FT_FREE( stream ); - else - stream->memory = memory; /* just to be certain */ - - *astream = stream; - - Exit: - return error; - } - - - FT_BASE_DEF( void ) - FT_Stream_Free( FT_Stream stream, - FT_Int external ) - { - if ( stream ) - { - FT_Memory memory = stream->memory; - - - FT_Stream_Close( stream ); - - if ( !external ) - FT_FREE( stream ); - } - } - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_objs - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - static FT_Error - ft_glyphslot_init( FT_GlyphSlot slot ) - { - FT_Driver driver = slot->face->driver; - FT_Driver_Class clazz = driver->clazz; - FT_Memory memory = driver->root.memory; - FT_Error error = FT_Err_Ok; - FT_Slot_Internal internal = NULL; - - - slot->library = driver->root.library; - - if ( FT_NEW( internal ) ) - goto Exit; - - slot->internal = internal; - - if ( FT_DRIVER_USES_OUTLINES( driver ) ) - error = FT_GlyphLoader_New( memory, &internal->loader ); - - if ( !error && clazz->init_slot ) - error = clazz->init_slot( slot ); - - Exit: - return error; - } - - - FT_BASE_DEF( void ) - ft_glyphslot_free_bitmap( FT_GlyphSlot slot ) - { - if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) - { - FT_Memory memory = FT_FACE_MEMORY( slot->face ); - - - FT_FREE( slot->bitmap.buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - else - { - /* assume that the bitmap buffer was stolen or not */ - /* allocated from the heap */ - slot->bitmap.buffer = NULL; - } - } - - - FT_BASE_DEF( void ) - ft_glyphslot_set_bitmap( FT_GlyphSlot slot, - FT_Byte* buffer ) - { - ft_glyphslot_free_bitmap( slot ); - - slot->bitmap.buffer = buffer; - - FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 ); - } - - - FT_BASE_DEF( FT_Error ) - ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, - FT_ULong size ) - { - FT_Memory memory = FT_FACE_MEMORY( slot->face ); - FT_Error error; - - - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - FT_FREE( slot->bitmap.buffer ); - else - slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - - (void)FT_ALLOC( slot->bitmap.buffer, size ); - return error; - } - - - static void - ft_glyphslot_clear( FT_GlyphSlot slot ) - { - /* free bitmap if needed */ - ft_glyphslot_free_bitmap( slot ); - - /* clear all public fields in the glyph slot */ - FT_ZERO( &slot->metrics ); - FT_ZERO( &slot->outline ); - - slot->bitmap.width = 0; - slot->bitmap.rows = 0; - slot->bitmap.pitch = 0; - slot->bitmap.pixel_mode = 0; - /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */ - - slot->bitmap_left = 0; - slot->bitmap_top = 0; - slot->num_subglyphs = 0; - slot->subglyphs = NULL; - slot->control_data = NULL; - slot->control_len = 0; - slot->other = NULL; - slot->format = FT_GLYPH_FORMAT_NONE; - - slot->linearHoriAdvance = 0; - slot->linearVertAdvance = 0; - slot->lsb_delta = 0; - slot->rsb_delta = 0; - } - - - static void - ft_glyphslot_done( FT_GlyphSlot slot ) - { - FT_Driver driver = slot->face->driver; - FT_Driver_Class clazz = driver->clazz; - FT_Memory memory = driver->root.memory; - - - if ( clazz->done_slot ) - clazz->done_slot( slot ); - - /* free bitmap buffer if needed */ - ft_glyphslot_free_bitmap( slot ); - - /* slot->internal might be NULL in out-of-memory situations */ - if ( slot->internal ) - { - /* free glyph loader */ - if ( FT_DRIVER_USES_OUTLINES( driver ) ) - { - FT_GlyphLoader_Done( slot->internal->loader ); - slot->internal->loader = NULL; - } - - FT_FREE( slot->internal ); - } - } - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( FT_Error ) - FT_New_GlyphSlot( FT_Face face, - FT_GlyphSlot *aslot ) - { - FT_Error error; - FT_Driver driver; - FT_Driver_Class clazz; - FT_Memory memory; - FT_GlyphSlot slot = NULL; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !face->driver ) - return FT_THROW( Invalid_Argument ); - - driver = face->driver; - clazz = driver->clazz; - memory = driver->root.memory; - - FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); - if ( !FT_ALLOC( slot, clazz->slot_object_size ) ) - { - slot->face = face; - - error = ft_glyphslot_init( slot ); - if ( error ) - { - ft_glyphslot_done( slot ); - FT_FREE( slot ); - goto Exit; - } - - slot->next = face->glyph; - face->glyph = slot; - - if ( aslot ) - *aslot = slot; - } - else if ( aslot ) - *aslot = NULL; - - - Exit: - FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); - return error; - } - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( void ) - FT_Done_GlyphSlot( FT_GlyphSlot slot ) - { - if ( slot ) - { - FT_Driver driver = slot->face->driver; - FT_Memory memory = driver->root.memory; - FT_GlyphSlot prev; - FT_GlyphSlot cur; - - - /* Remove slot from its parent face's list */ - prev = NULL; - cur = slot->face->glyph; - - while ( cur ) - { - if ( cur == slot ) - { - if ( !prev ) - slot->face->glyph = cur->next; - else - prev->next = cur->next; - - /* finalize client-specific data */ - if ( slot->generic.finalizer ) - slot->generic.finalizer( slot ); - - ft_glyphslot_done( slot ); - FT_FREE( slot ); - break; - } - prev = cur; - cur = cur->next; - } - } - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( void ) - FT_Set_Transform( FT_Face face, - FT_Matrix* matrix, - FT_Vector* delta ) - { - FT_Face_Internal internal; - - - if ( !face ) - return; - - internal = face->internal; - - internal->transform_flags = 0; - - if ( !matrix ) - { - internal->transform_matrix.xx = 0x10000L; - internal->transform_matrix.xy = 0; - internal->transform_matrix.yx = 0; - internal->transform_matrix.yy = 0x10000L; - - matrix = &internal->transform_matrix; - } - else - internal->transform_matrix = *matrix; - - /* set transform_flags bit flag 0 if `matrix' isn't the identity */ - if ( ( matrix->xy | matrix->yx ) || - matrix->xx != 0x10000L || - matrix->yy != 0x10000L ) - internal->transform_flags |= 1; - - if ( !delta ) - { - internal->transform_delta.x = 0; - internal->transform_delta.y = 0; - - delta = &internal->transform_delta; - } - else - internal->transform_delta = *delta; - - /* set transform_flags bit flag 1 if `delta' isn't the null vector */ - if ( delta->x | delta->y ) - internal->transform_flags |= 2; - } - - - static FT_Renderer - ft_lookup_glyph_renderer( FT_GlyphSlot slot ); - - -#ifdef GRID_FIT_METRICS - static void - ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot, - FT_Bool vertical ) - { - FT_Glyph_Metrics* metrics = &slot->metrics; - FT_Pos right, bottom; - - - if ( vertical ) - { - metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); - metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); - - right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width ); - bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height ); - - metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); - metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); - - metrics->width = right - metrics->vertBearingX; - metrics->height = bottom - metrics->vertBearingY; - } - else - { - metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); - metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); - - right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width ); - bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height ); - - metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); - metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); - - metrics->width = right - metrics->horiBearingX; - metrics->height = metrics->horiBearingY - bottom; - } - - metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); - metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); - } -#endif /* GRID_FIT_METRICS */ - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Load_Glyph( FT_Face face, - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - FT_Error error; - FT_Driver driver; - FT_GlyphSlot slot; - FT_Library library; - FT_Bool autohint = FALSE; - FT_Module hinter; - TT_Face ttface = (TT_Face)face; - - - if ( !face || !face->size || !face->glyph ) - return FT_THROW( Invalid_Face_Handle ); - - /* The validity test for `glyph_index' is performed by the */ - /* font drivers. */ - - slot = face->glyph; - ft_glyphslot_clear( slot ); - - driver = face->driver; - library = driver->root.library; - hinter = library->auto_hinter; - - /* resolve load flags dependencies */ - - if ( load_flags & FT_LOAD_NO_RECURSE ) - load_flags |= FT_LOAD_NO_SCALE | - FT_LOAD_IGNORE_TRANSFORM; - - if ( load_flags & FT_LOAD_NO_SCALE ) - { - load_flags |= FT_LOAD_NO_HINTING | - FT_LOAD_NO_BITMAP; - - load_flags &= ~FT_LOAD_RENDER; - } - - /* - * Determine whether we need to auto-hint or not. - * The general rules are: - * - * - Do only auto-hinting if we have a hinter module, a scalable font - * format dealing with outlines, and no transforms except simple - * slants and/or rotations by integer multiples of 90 degrees. - * - * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't - * have a native font hinter. - * - * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't - * any hinting bytecode in the TrueType/OpenType font. - * - * - Exception: The font is `tricky' and requires the native hinter to - * load properly. - */ - - if ( hinter && - !( load_flags & FT_LOAD_NO_HINTING ) && - !( load_flags & FT_LOAD_NO_AUTOHINT ) && - FT_DRIVER_IS_SCALABLE( driver ) && - FT_DRIVER_USES_OUTLINES( driver ) && - !FT_IS_TRICKY( face ) && - ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) || - ( face->internal->transform_matrix.yx == 0 && - face->internal->transform_matrix.xx != 0 ) || - ( face->internal->transform_matrix.xx == 0 && - face->internal->transform_matrix.yx != 0 ) ) ) - { - if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) || - !FT_DRIVER_HAS_HINTER( driver ) ) - autohint = TRUE; - else - { - FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); - - - /* the check for `num_locations' assures that we actually */ - /* test for instructions in a TTF and not in a CFF-based OTF */ - /* */ - /* since `maxSizeOfInstructions' might be unreliable, we */ - /* check the size of the `fpgm' and `prep' tables, too -- */ - /* the assumption is that there don't exist real TTFs where */ - /* both `fpgm' and `prep' tables are missing */ - if ( mode == FT_RENDER_MODE_LIGHT || - face->internal->ignore_unpatented_hinter || - ( FT_IS_SFNT( face ) && - ttface->num_locations && - ttface->max_profile.maxSizeOfInstructions == 0 && - ttface->font_program_size == 0 && - ttface->cvt_program_size == 0 ) ) - autohint = TRUE; - } - } - - if ( autohint ) - { - FT_AutoHinter_Interface hinting; - - - /* try to load embedded bitmaps first if available */ - /* */ - /* XXX: This is really a temporary hack that should disappear */ - /* promptly with FreeType 2.1! */ - /* */ - if ( FT_HAS_FIXED_SIZES( face ) && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) - { - error = driver->clazz->load_glyph( slot, face->size, - glyph_index, - load_flags | FT_LOAD_SBITS_ONLY ); - - if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP ) - goto Load_Ok; - } - - { - FT_Face_Internal internal = face->internal; - FT_Int transform_flags = internal->transform_flags; - - - /* since the auto-hinter calls FT_Load_Glyph by itself, */ - /* make sure that glyphs aren't transformed */ - internal->transform_flags = 0; - - /* load auto-hinted outline */ - hinting = (FT_AutoHinter_Interface)hinter->clazz->module_interface; - - error = hinting->load_glyph( (FT_AutoHinter)hinter, - slot, face->size, - glyph_index, load_flags ); - - internal->transform_flags = transform_flags; - } - } - else - { - error = driver->clazz->load_glyph( slot, - face->size, - glyph_index, - load_flags ); - if ( error ) - goto Exit; - - if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - { - /* check that the loaded outline is correct */ - error = FT_Outline_Check( &slot->outline ); - if ( error ) - goto Exit; - -#ifdef GRID_FIT_METRICS - if ( !( load_flags & FT_LOAD_NO_HINTING ) ) - ft_glyphslot_grid_fit_metrics( slot, - FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) ); -#endif - } - } - - Load_Ok: - /* compute the advance */ - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - slot->advance.x = 0; - slot->advance.y = slot->metrics.vertAdvance; - } - else - { - slot->advance.x = slot->metrics.horiAdvance; - slot->advance.y = 0; - } - - /* compute the linear advance in 16.16 pixels */ - if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && - ( FT_IS_SCALABLE( face ) ) ) - { - FT_Size_Metrics* metrics = &face->size->metrics; - - - /* it's tricky! */ - slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance, - metrics->x_scale, 64 ); - - slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance, - metrics->y_scale, 64 ); - } - - if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 ) - { - FT_Face_Internal internal = face->internal; - - - /* now, transform the glyph image if needed */ - if ( internal->transform_flags ) - { - /* get renderer */ - FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); - - - if ( renderer ) - error = renderer->clazz->transform_glyph( - renderer, slot, - &internal->transform_matrix, - &internal->transform_delta ); - else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - { - /* apply `standard' transformation if no renderer is available */ - if ( internal->transform_flags & 1 ) - FT_Outline_Transform( &slot->outline, - &internal->transform_matrix ); - - if ( internal->transform_flags & 2 ) - FT_Outline_Translate( &slot->outline, - internal->transform_delta.x, - internal->transform_delta.y ); - } - - /* transform advance */ - FT_Vector_Transform( &slot->advance, &internal->transform_matrix ); - } - } - - FT_TRACE5(( " x advance: %d\n" , slot->advance.x )); - FT_TRACE5(( " y advance: %d\n" , slot->advance.y )); - - FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance )); - FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance )); - - /* do we need to render the image now? */ - if ( !error && - slot->format != FT_GLYPH_FORMAT_BITMAP && - slot->format != FT_GLYPH_FORMAT_COMPOSITE && - load_flags & FT_LOAD_RENDER ) - { - FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); - - - if ( mode == FT_RENDER_MODE_NORMAL && - (load_flags & FT_LOAD_MONOCHROME ) ) - mode = FT_RENDER_MODE_MONO; - - error = FT_Render_Glyph( slot, mode ); - } - - Exit: - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Load_Char( FT_Face face, - FT_ULong char_code, - FT_Int32 load_flags ) - { - FT_UInt glyph_index; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - glyph_index = (FT_UInt)char_code; - if ( face->charmap ) - glyph_index = FT_Get_Char_Index( face, char_code ); - - return FT_Load_Glyph( face, glyph_index, load_flags ); - } - - - /* destructor for sizes list */ - static void - destroy_size( FT_Memory memory, - FT_Size size, - FT_Driver driver ) - { - /* finalize client-specific data */ - if ( size->generic.finalizer ) - size->generic.finalizer( size ); - - /* finalize format-specific stuff */ - if ( driver->clazz->done_size ) - driver->clazz->done_size( size ); - - FT_FREE( size->internal ); - FT_FREE( size ); - } - - - static void - ft_cmap_done_internal( FT_CMap cmap ); - - - static void - destroy_charmaps( FT_Face face, - FT_Memory memory ) - { - FT_Int n; - - - if ( !face ) - return; - - for ( n = 0; n < face->num_charmaps; n++ ) - { - FT_CMap cmap = FT_CMAP( face->charmaps[n] ); - - - ft_cmap_done_internal( cmap ); - - face->charmaps[n] = NULL; - } - - FT_FREE( face->charmaps ); - face->num_charmaps = 0; - } - - - /* destructor for faces list */ - static void - destroy_face( FT_Memory memory, - FT_Face face, - FT_Driver driver ) - { - FT_Driver_Class clazz = driver->clazz; - - - /* discard auto-hinting data */ - if ( face->autohint.finalizer ) - face->autohint.finalizer( face->autohint.data ); - - /* Discard glyph slots for this face. */ - /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */ - while ( face->glyph ) - FT_Done_GlyphSlot( face->glyph ); - - /* discard all sizes for this face */ - FT_List_Finalize( &face->sizes_list, - (FT_List_Destructor)destroy_size, - memory, - driver ); - face->size = NULL; - - /* now discard client data */ - if ( face->generic.finalizer ) - face->generic.finalizer( face ); - - /* discard charmaps */ - destroy_charmaps( face, memory ); - - /* finalize format-specific stuff */ - if ( clazz->done_face ) - clazz->done_face( face ); - - /* close the stream for this face if needed */ - FT_Stream_Free( - face->stream, - ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); - - face->stream = NULL; - - /* get rid of it */ - if ( face->internal ) - { - FT_FREE( face->internal ); - } - FT_FREE( face ); - } - - - static void - Destroy_Driver( FT_Driver driver ) - { - FT_List_Finalize( &driver->faces_list, - (FT_List_Destructor)destroy_face, - driver->root.memory, - driver ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* find_unicode_charmap */ - /* */ - /* <Description> */ - /* This function finds a Unicode charmap, if there is one. */ - /* And if there is more than one, it tries to favour the more */ - /* extensive one, i.e., one that supports UCS-4 against those which */ - /* are limited to the BMP (said UCS-2 encoding.) */ - /* */ - /* This function is called from open_face() (just below), and also */ - /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */ - /* */ - static FT_Error - find_unicode_charmap( FT_Face face ) - { - FT_CharMap* first; - FT_CharMap* cur; - - - /* caller should have already checked that `face' is valid */ - FT_ASSERT( face ); - - first = face->charmaps; - - if ( !first ) - return FT_THROW( Invalid_CharMap_Handle ); - - /* - * The original TrueType specification(s) only specified charmap - * formats that are capable of mapping 8 or 16 bit character codes to - * glyph indices. - * - * However, recent updates to the Apple and OpenType specifications - * introduced new formats that are capable of mapping 32-bit character - * codes as well. And these are already used on some fonts, mainly to - * map non-BMP Asian ideographs as defined in Unicode. - * - * For compatibility purposes, these fonts generally come with - * *several* Unicode charmaps: - * - * - One of them in the "old" 16-bit format, that cannot access - * all glyphs in the font. - * - * - Another one in the "new" 32-bit format, that can access all - * the glyphs. - * - * This function has been written to always favor a 32-bit charmap - * when found. Otherwise, a 16-bit one is returned when found. - */ - - /* Since the `interesting' table, with IDs (3,10), is normally the */ - /* last one, we loop backwards. This loses with type1 fonts with */ - /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */ - /* chars (.01% ?), and this is the same about 99.99% of the time! */ - - cur = first + face->num_charmaps; /* points after the last one */ - - for ( ; --cur >= first; ) - { - if ( cur[0]->encoding == FT_ENCODING_UNICODE ) - { - /* XXX If some new encodings to represent UCS-4 are added, */ - /* they should be added here. */ - if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT && - cur[0]->encoding_id == TT_MS_ID_UCS_4 ) || - ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && - cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) - { - face->charmap = cur[0]; - return FT_Err_Ok; - } - } - } - - /* We do not have any UCS-4 charmap. */ - /* Do the loop again and search for UCS-2 charmaps. */ - cur = first + face->num_charmaps; - - for ( ; --cur >= first; ) - { - if ( cur[0]->encoding == FT_ENCODING_UNICODE ) - { - face->charmap = cur[0]; - return FT_Err_Ok; - } - } - - return FT_THROW( Invalid_CharMap_Handle ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* find_variant_selector_charmap */ - /* */ - /* <Description> */ - /* This function finds the variant selector charmap, if there is one. */ - /* There can only be one (platform=0, specific=5, format=14). */ - /* */ - static FT_CharMap - find_variant_selector_charmap( FT_Face face ) - { - FT_CharMap* first; - FT_CharMap* end; - FT_CharMap* cur; - - - /* caller should have already checked that `face' is valid */ - FT_ASSERT( face ); - - first = face->charmaps; - - if ( !first ) - return NULL; - - end = first + face->num_charmaps; /* points after the last one */ - - for ( cur = first; cur < end; ++cur ) - { - if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && - cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR && - FT_Get_CMap_Format( cur[0] ) == 14 ) - return cur[0]; - } - - return NULL; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* open_face */ - /* */ - /* <Description> */ - /* This function does some work for FT_Open_Face(). */ - /* */ - static FT_Error - open_face( FT_Driver driver, - FT_Stream *astream, - FT_Bool external_stream, - FT_Long face_index, - FT_Int num_params, - FT_Parameter* params, - FT_Face *aface ) - { - FT_Memory memory; - FT_Driver_Class clazz; - FT_Face face = NULL; - FT_Face_Internal internal = NULL; - - FT_Error error, error2; - - - clazz = driver->clazz; - memory = driver->root.memory; - - /* allocate the face object and perform basic initialization */ - if ( FT_ALLOC( face, clazz->face_object_size ) ) - goto Fail; - - face->driver = driver; - face->memory = memory; - face->stream = *astream; - - /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ - if ( external_stream ) - face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; - - if ( FT_NEW( internal ) ) - goto Fail; - - face->internal = internal; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - { - int i; - - - face->internal->incremental_interface = NULL; - for ( i = 0; i < num_params && !face->internal->incremental_interface; - i++ ) - if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL ) - face->internal->incremental_interface = - (FT_Incremental_Interface)params[i].data; - } -#endif - - if ( clazz->init_face ) - error = clazz->init_face( *astream, - face, - (FT_Int)face_index, - num_params, - params ); - *astream = face->stream; /* Stream may have been changed. */ - if ( error ) - goto Fail; - - /* select Unicode charmap by default */ - error2 = find_unicode_charmap( face ); - - /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */ - /* is returned. */ - - /* no error should happen, but we want to play safe */ - if ( error2 && FT_ERR_NEQ( error2, Invalid_CharMap_Handle ) ) - { - error = error2; - goto Fail; - } - - *aface = face; - - Fail: - if ( error ) - { - destroy_charmaps( face, memory ); - if ( clazz->done_face ) - clazz->done_face( face ); - FT_FREE( internal ); - FT_FREE( face ); - *aface = NULL; - } - - return error; - } - - - /* there's a Mac-specific extended implementation of FT_New_Face() */ - /* in src/base/ftmac.c */ - -#ifndef FT_MACINTOSH - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_New_Face( FT_Library library, - const char* pathname, - FT_Long face_index, - FT_Face *aface ) - { - FT_Open_Args args; - - - /* test for valid `library' and `aface' delayed to `FT_Open_Face' */ - if ( !pathname ) - return FT_THROW( Invalid_Argument ); - - args.flags = FT_OPEN_PATHNAME; - args.pathname = (char*)pathname; - args.stream = NULL; - - return FT_Open_Face( library, &args, face_index, aface ); - } - -#endif - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_New_Memory_Face( FT_Library library, - const FT_Byte* file_base, - FT_Long file_size, - FT_Long face_index, - FT_Face *aface ) - { - FT_Open_Args args; - - - /* test for valid `library' and `face' delayed to `FT_Open_Face' */ - if ( !file_base ) - return FT_THROW( Invalid_Argument ); - - args.flags = FT_OPEN_MEMORY; - args.memory_base = file_base; - args.memory_size = file_size; - args.stream = NULL; - - return FT_Open_Face( library, &args, face_index, aface ); - } - - -#ifdef FT_CONFIG_OPTION_MAC_FONTS - - /* The behavior here is very similar to that in base/ftmac.c, but it */ - /* is designed to work on non-mac systems, so no mac specific calls. */ - /* */ - /* We look at the file and determine if it is a mac dfont file or a mac */ - /* resource file, or a macbinary file containing a mac resource file. */ - /* */ - /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */ - /* the point, especially since there may be multiple `FOND' resources. */ - /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */ - /* they occur in the file. */ - /* */ - /* Note that multiple `POST' resources do not mean multiple postscript */ - /* fonts; they all get jammed together to make what is essentially a */ - /* pfb file. */ - /* */ - /* We aren't interested in `NFNT' or `FONT' bitmap resources. */ - /* */ - /* As soon as we get an `sfnt' load it into memory and pass it off to */ - /* FT_Open_Face. */ - /* */ - /* If we have a (set of) `POST' resources, massage them into a (memory) */ - /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */ - /* going to try to save the kerning info. After all that lives in the */ - /* `FOND' which isn't in the file containing the `POST' resources so */ - /* we don't really have access to it. */ - - - /* Finalizer for a memory stream; gets called by FT_Done_Face(). */ - /* It frees the memory it uses. */ - /* From ftmac.c. */ - static void - memory_stream_close( FT_Stream stream ) - { - FT_Memory memory = stream->memory; - - - FT_FREE( stream->base ); - - stream->size = 0; - stream->base = NULL; - stream->close = NULL; - } - - - /* Create a new memory stream from a buffer and a size. */ - /* From ftmac.c. */ - static FT_Error - new_memory_stream( FT_Library library, - FT_Byte* base, - FT_ULong size, - FT_Stream_CloseFunc close, - FT_Stream *astream ) - { - FT_Error error; - FT_Memory memory; - FT_Stream stream = NULL; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !base ) - return FT_THROW( Invalid_Argument ); - - *astream = NULL; - memory = library->memory; - if ( FT_NEW( stream ) ) - goto Exit; - - FT_Stream_OpenMemory( stream, base, size ); - - stream->close = close; - - *astream = stream; - - Exit: - return error; - } - - - /* Create a new FT_Face given a buffer and a driver name. */ - /* from ftmac.c */ - FT_LOCAL_DEF( FT_Error ) - open_face_from_buffer( FT_Library library, - FT_Byte* base, - FT_ULong size, - FT_Long face_index, - const char* driver_name, - FT_Face *aface ) - { - FT_Open_Args args; - FT_Error error; - FT_Stream stream = NULL; - FT_Memory memory = library->memory; - - - error = new_memory_stream( library, - base, - size, - memory_stream_close, - &stream ); - if ( error ) - { - FT_FREE( base ); - return error; - } - - args.flags = FT_OPEN_STREAM; - args.stream = stream; - if ( driver_name ) - { - args.flags = args.flags | FT_OPEN_DRIVER; - args.driver = FT_Get_Module( library, driver_name ); - } - -#ifdef FT_MACINTOSH - /* At this point, the face index has served its purpose; */ - /* whoever calls this function has already used it to */ - /* locate the correct font data. We should not propagate */ - /* this index to FT_Open_Face() (unless it is negative). */ - - if ( face_index > 0 ) - face_index &= 0x7FFF0000L; /* retain GX data */ -#endif - - error = FT_Open_Face( library, &args, face_index, aface ); - - if ( error == FT_Err_Ok ) - (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; - else -#ifdef FT_MACINTOSH - FT_Stream_Free( stream, 0 ); -#else - { - FT_Stream_Close( stream ); - FT_FREE( stream ); - } -#endif - - return error; - } - - - /* Look up `TYP1' or `CID ' table from sfnt table directory. */ - /* `offset' and `length' must exclude the binary header in tables. */ - - /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */ - /* format too. Here, since we can't expect that the TrueType font */ - /* driver is loaded unconditially, we must parse the font by */ - /* ourselves. We are only interested in the name of the table and */ - /* the offset. */ - - static FT_Error - ft_lookup_PS_in_sfnt_stream( FT_Stream stream, - FT_Long face_index, - FT_ULong* offset, - FT_ULong* length, - FT_Bool* is_sfnt_cid ) - { - FT_Error error; - FT_UShort numTables; - FT_Long pstable_index; - FT_ULong tag; - int i; - - - *offset = 0; - *length = 0; - *is_sfnt_cid = FALSE; - - /* TODO: support for sfnt-wrapped PS/CID in TTC format */ - - /* version check for 'typ1' (should be ignored?) */ - if ( FT_READ_ULONG( tag ) ) - return error; - if ( tag != TTAG_typ1 ) - return FT_THROW( Unknown_File_Format ); - - if ( FT_READ_USHORT( numTables ) ) - return error; - if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */ - return error; - - pstable_index = -1; - *is_sfnt_cid = FALSE; - - for ( i = 0; i < numTables; i++ ) - { - if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) || - FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) ) - return error; - - if ( tag == TTAG_CID ) - { - pstable_index++; - *offset += 22; - *length -= 22; - *is_sfnt_cid = TRUE; - if ( face_index < 0 ) - return FT_Err_Ok; - } - else if ( tag == TTAG_TYP1 ) - { - pstable_index++; - *offset += 24; - *length -= 24; - *is_sfnt_cid = FALSE; - if ( face_index < 0 ) - return FT_Err_Ok; - } - if ( face_index >= 0 && pstable_index == face_index ) - return FT_Err_Ok; - } - return FT_THROW( Table_Missing ); - } - - - FT_LOCAL_DEF( FT_Error ) - open_face_PS_from_sfnt_stream( FT_Library library, - FT_Stream stream, - FT_Long face_index, - FT_Int num_params, - FT_Parameter *params, - FT_Face *aface ) - { - FT_Error error; - FT_Memory memory = library->memory; - FT_ULong offset, length; - FT_ULong pos; - FT_Bool is_sfnt_cid; - FT_Byte* sfnt_ps = NULL; - - FT_UNUSED( num_params ); - FT_UNUSED( params ); - - - /* ignore GX stuff */ - if ( face_index > 0 ) - face_index &= 0xFFFFL; - - pos = FT_STREAM_POS(); - - error = ft_lookup_PS_in_sfnt_stream( stream, - face_index, - &offset, - &length, - &is_sfnt_cid ); - if ( error ) - goto Exit; - - if ( FT_Stream_Seek( stream, pos + offset ) ) - goto Exit; - - if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) - goto Exit; - - error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); - if ( error ) { - FT_FREE( sfnt_ps ); - goto Exit; - } - - error = open_face_from_buffer( library, - sfnt_ps, - length, - FT_MIN( face_index, 0 ), - is_sfnt_cid ? "cid" : "type1", - aface ); - Exit: - { - FT_Error error1; - - - if ( FT_ERR_EQ( error, Unknown_File_Format ) ) - { - error1 = FT_Stream_Seek( stream, pos ); - if ( error1 ) - return error1; - } - - return error; - } - } - - -#ifndef FT_MACINTOSH - - /* The resource header says we've got resource_cnt `POST' (type1) */ - /* resources in this file. They all need to be coalesced into */ - /* one lump which gets passed on to the type1 driver. */ - /* Here can be only one PostScript font in a file so face_index */ - /* must be 0 (or -1). */ - /* */ - static FT_Error - Mac_Read_POST_Resource( FT_Library library, - FT_Stream stream, - FT_Long *offsets, - FT_Long resource_cnt, - FT_Long face_index, - FT_Face *aface ) - { - FT_Error error = FT_ERR( Cannot_Open_Resource ); - FT_Memory memory = library->memory; - FT_Byte* pfb_data = NULL; - int i, type, flags; - FT_ULong len; - FT_ULong pfb_len, pfb_pos, pfb_lenpos; - FT_ULong rlen, temp; - - - if ( face_index == -1 ) - face_index = 0; - if ( face_index != 0 ) - return error; - - /* Find the length of all the POST resources, concatenated. Assume */ - /* worst case (each resource in its own section). */ - pfb_len = 0; - for ( i = 0; i < resource_cnt; ++i ) - { - error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] ); - if ( error ) - goto Exit; - if ( FT_READ_ULONG( temp ) ) - goto Exit; - - /* FT2 allocator takes signed long buffer length, - * too large value causing overflow should be checked - */ - FT_TRACE4(( " POST fragment #%d: length=0x%08x" - " total pfb_len=0x%08x\n", - i, temp, pfb_len + temp + 6)); - if ( FT_MAC_RFORK_MAX_LEN < temp || - FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 ) - { - FT_TRACE2(( " MacOS resource length cannot exceed" - " 0x%08x\n", FT_MAC_RFORK_MAX_LEN )); - error = FT_THROW( Invalid_Offset ); - goto Exit; - } - - pfb_len += temp + 6; - } - - FT_TRACE2(( " total buffer size to concatenate %d" - " POST fragments: 0x%08x\n", - resource_cnt, pfb_len + 2)); - if ( pfb_len + 2 < 6 ) { - FT_TRACE2(( " too long fragment length makes" - " pfb_len confused: pfb_len=0x%08x\n", pfb_len )); - error = FT_THROW( Array_Too_Large ); - goto Exit; - } - if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) - goto Exit; - - pfb_data[0] = 0x80; - pfb_data[1] = 1; /* Ascii section */ - pfb_data[2] = 0; /* 4-byte length, fill in later */ - pfb_data[3] = 0; - pfb_data[4] = 0; - pfb_data[5] = 0; - pfb_pos = 6; - pfb_lenpos = 2; - - len = 0; - type = 1; - for ( i = 0; i < resource_cnt; ++i ) - { - error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] ); - if ( error ) - goto Exit2; - if ( FT_READ_ULONG( rlen ) ) - goto Exit2; - - /* FT2 allocator takes signed long buffer length, - * too large fragment length causing overflow should be checked - */ - if ( 0x7FFFFFFFUL < rlen ) - { - error = FT_THROW( Invalid_Offset ); - goto Exit2; - } - - if ( FT_READ_USHORT( flags ) ) - goto Exit2; - FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n", - i, offsets[i], rlen, flags )); - - error = FT_ERR( Array_Too_Large ); - /* postpone the check of rlen longer than buffer until FT_Stream_Read() */ - if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */ - { - FT_TRACE3(( " Skip POST fragment #%d because it is a comment\n", i )); - continue; - } - - /* the flags are part of the resource, so rlen >= 2. */ - /* but some fonts declare rlen = 0 for empty fragment */ - if ( rlen > 2 ) - rlen -= 2; - else - rlen = 0; - - if ( ( flags >> 8 ) == type ) - len += rlen; - else - { - FT_TRACE3(( " Write POST fragment #%d header (4-byte) to buffer" - " %p + 0x%08x\n", i, pfb_data, pfb_lenpos )); - if ( pfb_lenpos + 3 > pfb_len + 2 ) - goto Exit2; - pfb_data[pfb_lenpos ] = (FT_Byte)( len ); - pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); - pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); - pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); - - if ( ( flags >> 8 ) == 5 ) /* End of font mark */ - break; - - FT_TRACE3(( " Write POST fragment #%d header (6-byte) to buffer" - " %p + 0x%08x\n", i, pfb_data, pfb_pos )); - if ( pfb_pos + 6 > pfb_len + 2 ) - goto Exit2; - pfb_data[pfb_pos++] = 0x80; - - type = flags >> 8; - len = rlen; - - pfb_data[pfb_pos++] = (FT_Byte)type; - pfb_lenpos = pfb_pos; - pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */ - pfb_data[pfb_pos++] = 0; - pfb_data[pfb_pos++] = 0; - pfb_data[pfb_pos++] = 0; - } - - if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len ) - goto Exit2; - - FT_TRACE3(( " Load POST fragment #%d (%d byte) to buffer" - " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos )); - error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); - if ( error ) - goto Exit2; - pfb_pos += rlen; - } - - error = FT_ERR( Array_Too_Large ); - if ( pfb_pos + 2 > pfb_len + 2 ) - goto Exit2; - pfb_data[pfb_pos++] = 0x80; - pfb_data[pfb_pos++] = 3; - - if ( pfb_lenpos + 3 > pfb_len + 2 ) - goto Exit2; - pfb_data[pfb_lenpos ] = (FT_Byte)( len ); - pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); - pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); - pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); - - return open_face_from_buffer( library, - pfb_data, - pfb_pos, - face_index, - "type1", - aface ); - - Exit2: - if ( error == FT_ERR( Array_Too_Large ) ) - FT_TRACE2(( " Abort due to too-short buffer to store" - " all POST fragments\n" )); - else if ( error == FT_ERR( Invalid_Offset ) ) - FT_TRACE2(( " Abort due to invalid offset in a POST fragment\n" )); - if ( error ) - error = FT_ERR( Cannot_Open_Resource ); - FT_FREE( pfb_data ); - - Exit: - return error; - } - - - /* The resource header says we've got resource_cnt `sfnt' */ - /* (TrueType/OpenType) resources in this file. Look through */ - /* them for the one indicated by face_index, load it into mem, */ - /* pass it on to the truetype driver, and return it. */ - /* */ - static FT_Error - Mac_Read_sfnt_Resource( FT_Library library, - FT_Stream stream, - FT_Long *offsets, - FT_Long resource_cnt, - FT_Long face_index, - FT_Face *aface ) - { - FT_Memory memory = library->memory; - FT_Byte* sfnt_data = NULL; - FT_Error error; - FT_ULong flag_offset; - FT_Long rlen; - int is_cff; - FT_Long face_index_in_resource = 0; - - - if ( face_index == -1 ) - face_index = 0; - if ( face_index >= resource_cnt ) - return FT_THROW( Cannot_Open_Resource ); - - flag_offset = (FT_ULong)offsets[face_index]; - error = FT_Stream_Seek( stream, flag_offset ); - if ( error ) - goto Exit; - - if ( FT_READ_LONG( rlen ) ) - goto Exit; - if ( rlen == -1 ) - return FT_THROW( Cannot_Open_Resource ); - if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN ) - return FT_THROW( Invalid_Offset ); - - error = open_face_PS_from_sfnt_stream( library, - stream, - face_index, - 0, NULL, - aface ); - if ( !error ) - goto Exit; - - /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */ - if ( FT_Stream_Seek( stream, flag_offset + 4 ) ) - goto Exit; - - if ( FT_ALLOC( sfnt_data, rlen ) ) - return error; - error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen ); - if ( error ) { - FT_FREE( sfnt_data ); - goto Exit; - } - - is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); - error = open_face_from_buffer( library, - sfnt_data, - (FT_ULong)rlen, - face_index_in_resource, - is_cff ? "cff" : "truetype", - aface ); - - Exit: - return error; - } - - - /* Check for a valid resource fork header, or a valid dfont */ - /* header. In a resource fork the first 16 bytes are repeated */ - /* at the location specified by bytes 4-7. In a dfont bytes */ - /* 4-7 point to 16 bytes of zeroes instead. */ - /* */ - static FT_Error - IsMacResource( FT_Library library, - FT_Stream stream, - FT_Long resource_offset, - FT_Long face_index, - FT_Face *aface ) - { - FT_Memory memory = library->memory; - FT_Error error; - FT_Long map_offset, rdara_pos; - FT_Long *data_offsets; - FT_Long count; - - - error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset, - &map_offset, &rdara_pos ); - if ( error ) - return error; - - /* POST resources must be sorted to concatenate properly */ - error = FT_Raccess_Get_DataOffsets( library, stream, - map_offset, rdara_pos, - TTAG_POST, TRUE, - &data_offsets, &count ); - if ( !error ) - { - error = Mac_Read_POST_Resource( library, stream, data_offsets, count, - face_index, aface ); - FT_FREE( data_offsets ); - /* POST exists in an LWFN providing a single face */ - if ( !error ) - (*aface)->num_faces = 1; - return error; - } - - /* sfnt resources should not be sorted to preserve the face order by - QuickDraw API */ - error = FT_Raccess_Get_DataOffsets( library, stream, - map_offset, rdara_pos, - TTAG_sfnt, FALSE, - &data_offsets, &count ); - if ( !error ) - { - FT_Long face_index_internal = face_index % count; - - - error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count, - face_index_internal, aface ); - FT_FREE( data_offsets ); - if ( !error ) - (*aface)->num_faces = count; - } - - return error; - } - - - /* Check for a valid macbinary header, and if we find one */ - /* check that the (flattened) resource fork in it is valid. */ - /* */ - static FT_Error - IsMacBinary( FT_Library library, - FT_Stream stream, - FT_Long face_index, - FT_Face *aface ) - { - unsigned char header[128]; - FT_Error error; - FT_Long dlen, offset; - - - if ( NULL == stream ) - return FT_THROW( Invalid_Stream_Operation ); - - error = FT_Stream_Seek( stream, 0 ); - if ( error ) - goto Exit; - - error = FT_Stream_Read( stream, (FT_Byte*)header, 128 ); - if ( error ) - goto Exit; - - if ( header[ 0] != 0 || - header[74] != 0 || - header[82] != 0 || - header[ 1] == 0 || - header[ 1] > 33 || - header[63] != 0 || - header[2 + header[1]] != 0 || - header[0x53] > 0x7F ) - return FT_THROW( Unknown_File_Format ); - - dlen = ( header[0x53] << 24 ) | - ( header[0x54] << 16 ) | - ( header[0x55] << 8 ) | - header[0x56]; -#if 0 - rlen = ( header[0x57] << 24 ) | - ( header[0x58] << 16 ) | - ( header[0x59] << 8 ) | - header[0x5A]; -#endif /* 0 */ - offset = 128 + ( ( dlen + 127 ) & ~127 ); - - return IsMacResource( library, stream, offset, face_index, aface ); - - Exit: - return error; - } - - - static FT_Error - load_face_in_embedded_rfork( FT_Library library, - FT_Stream stream, - FT_Long face_index, - FT_Face *aface, - const FT_Open_Args *args ) - { - -#undef FT_COMPONENT -#define FT_COMPONENT trace_raccess - - FT_Memory memory = library->memory; - FT_Error error = FT_ERR( Unknown_File_Format ); - FT_UInt i; - - char * file_names[FT_RACCESS_N_RULES]; - FT_Long offsets[FT_RACCESS_N_RULES]; - FT_Error errors[FT_RACCESS_N_RULES]; - FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */ - - FT_Open_Args args2; - FT_Stream stream2 = NULL; - - - FT_Raccess_Guess( library, stream, - args->pathname, file_names, offsets, errors ); - - for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) - { - is_darwin_vfs = ft_raccess_rule_by_darwin_vfs( library, i ); - if ( is_darwin_vfs && vfs_rfork_has_no_font ) - { - FT_TRACE3(( "Skip rule %d: darwin vfs resource fork" - " is already checked and" - " no font is found\n", i )); - continue; - } - - if ( errors[i] ) - { - FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); - continue; - } - - args2.flags = FT_OPEN_PATHNAME; - args2.pathname = file_names[i] ? file_names[i] : args->pathname; - - FT_TRACE3(( "Try rule %d: %s (offset=%d) ...", - i, args2.pathname, offsets[i] )); - - error = FT_Stream_New( library, &args2, &stream2 ); - if ( is_darwin_vfs && FT_ERR_EQ( error, Cannot_Open_Stream ) ) - vfs_rfork_has_no_font = TRUE; - - if ( error ) - { - FT_TRACE3(( "failed\n" )); - continue; - } - - error = IsMacResource( library, stream2, offsets[i], - face_index, aface ); - FT_Stream_Free( stream2, 0 ); - - FT_TRACE3(( "%s\n", error ? "failed": "successful" )); - - if ( !error ) - break; - else if ( is_darwin_vfs ) - vfs_rfork_has_no_font = TRUE; - } - - for (i = 0; i < FT_RACCESS_N_RULES; i++) - { - if ( file_names[i] ) - FT_FREE( file_names[i] ); - } - - /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */ - if ( error ) - error = FT_ERR( Unknown_File_Format ); - - return error; - -#undef FT_COMPONENT -#define FT_COMPONENT trace_objs - - } - - - /* Check for some macintosh formats without Carbon framework. */ - /* Is this a macbinary file? If so look at the resource fork. */ - /* Is this a mac dfont file? */ - /* Is this an old style resource fork? (in data) */ - /* Else call load_face_in_embedded_rfork to try extra rules */ - /* (defined in `ftrfork.c'). */ - /* */ - static FT_Error - load_mac_face( FT_Library library, - FT_Stream stream, - FT_Long face_index, - FT_Face *aface, - const FT_Open_Args *args ) - { - FT_Error error; - FT_UNUSED( args ); - - - error = IsMacBinary( library, stream, face_index, aface ); - if ( FT_ERR_EQ( error, Unknown_File_Format ) ) - { - -#undef FT_COMPONENT -#define FT_COMPONENT trace_raccess - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE3(( "Try as dfont: " )); - if ( !( args->flags & FT_OPEN_MEMORY ) ) - FT_TRACE3(( "%s ...", args->pathname )); -#endif - - error = IsMacResource( library, stream, 0, face_index, aface ); - - FT_TRACE3(( "%s\n", error ? "failed" : "successful" )); - -#undef FT_COMPONENT -#define FT_COMPONENT trace_objs - - } - - if ( ( FT_ERR_EQ( error, Unknown_File_Format ) || - FT_ERR_EQ( error, Invalid_Stream_Operation ) ) && - ( args->flags & FT_OPEN_PATHNAME ) ) - error = load_face_in_embedded_rfork( library, stream, - face_index, aface, args ); - return error; - } -#endif - -#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Open_Face( FT_Library library, - const FT_Open_Args* args, - FT_Long face_index, - FT_Face *aface ) - { - FT_Error error; - FT_Driver driver = NULL; - FT_Memory memory = NULL; - FT_Stream stream = NULL; - FT_Face face = NULL; - FT_ListNode node = NULL; - FT_Bool external_stream; - FT_Module* cur; - FT_Module* limit; - - - /* test for valid `library' delayed to `FT_Stream_New' */ - - if ( ( !aface && face_index >= 0 ) || !args ) - return FT_THROW( Invalid_Argument ); - - external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && - args->stream ); - - /* create input stream */ - error = FT_Stream_New( library, args, &stream ); - if ( error ) - goto Fail3; - - memory = library->memory; - - /* If the font driver is specified in the `args' structure, use */ - /* it. Otherwise, we scan the list of registered drivers. */ - if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver ) - { - driver = FT_DRIVER( args->driver ); - - /* not all modules are drivers, so check... */ - if ( FT_MODULE_IS_DRIVER( driver ) ) - { - FT_Int num_params = 0; - FT_Parameter* params = NULL; - - - if ( args->flags & FT_OPEN_PARAMS ) - { - num_params = args->num_params; - params = args->params; - } - - error = open_face( driver, &stream, external_stream, face_index, - num_params, params, &face ); - if ( !error ) - goto Success; - } - else - error = FT_THROW( Invalid_Handle ); - - FT_Stream_Free( stream, external_stream ); - goto Fail; - } - else - { - error = FT_ERR( Missing_Module ); - - /* check each font driver for an appropriate format */ - cur = library->modules; - limit = cur + library->num_modules; - - for ( ; cur < limit; cur++ ) - { - /* not all modules are font drivers, so check... */ - if ( FT_MODULE_IS_DRIVER( cur[0] ) ) - { - FT_Int num_params = 0; - FT_Parameter* params = NULL; - - - driver = FT_DRIVER( cur[0] ); - - if ( args->flags & FT_OPEN_PARAMS ) - { - num_params = args->num_params; - params = args->params; - } - - error = open_face( driver, &stream, external_stream, face_index, - num_params, params, &face ); - if ( !error ) - goto Success; - -#ifdef FT_CONFIG_OPTION_MAC_FONTS - if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 && - FT_ERR_EQ( error, Table_Missing ) ) - { - /* TrueType but essential tables are missing */ - if ( FT_Stream_Seek( stream, 0 ) ) - break; - - error = open_face_PS_from_sfnt_stream( library, - stream, - face_index, - num_params, - params, - aface ); - if ( !error ) - { - FT_Stream_Free( stream, external_stream ); - return error; - } - } -#endif - - if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) - goto Fail3; - } - } - - Fail3: - /* If we are on the mac, and we get an */ - /* FT_Err_Invalid_Stream_Operation it may be because we have an */ - /* empty data fork, so we need to check the resource fork. */ - if ( FT_ERR_NEQ( error, Cannot_Open_Stream ) && - FT_ERR_NEQ( error, Unknown_File_Format ) && - FT_ERR_NEQ( error, Invalid_Stream_Operation ) ) - goto Fail2; - -#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) - error = load_mac_face( library, stream, face_index, aface, args ); - if ( !error ) - { - /* We don't want to go to Success here. We've already done that. */ - /* On the other hand, if we succeeded we still need to close this */ - /* stream (we opened a different stream which extracted the */ - /* interesting information out of this stream here. That stream */ - /* will still be open and the face will point to it). */ - FT_Stream_Free( stream, external_stream ); - return error; - } - - if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) - goto Fail2; -#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ - - /* no driver is able to handle this format */ - error = FT_THROW( Unknown_File_Format ); - - Fail2: - FT_Stream_Free( stream, external_stream ); - goto Fail; - } - - Success: - FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); - - /* add the face object to its driver's list */ - if ( FT_NEW( node ) ) - goto Fail; - - node->data = face; - /* don't assume driver is the same as face->driver, so use */ - /* face->driver instead. */ - FT_List_Add( &face->driver->faces_list, node ); - - /* now allocate a glyph slot object for the face */ - FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); - - if ( face_index >= 0 ) - { - error = FT_New_GlyphSlot( face, NULL ); - if ( error ) - goto Fail; - - /* finally, allocate a size object for the face */ - { - FT_Size size; - - - FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); - - error = FT_New_Size( face, &size ); - if ( error ) - goto Fail; - - face->size = size; - } - } - - /* some checks */ - - if ( FT_IS_SCALABLE( face ) ) - { - if ( face->height < 0 ) - face->height = (FT_Short)-face->height; - - if ( !FT_HAS_VERTICAL( face ) ) - face->max_advance_height = (FT_Short)face->height; - } - - if ( FT_HAS_FIXED_SIZES( face ) ) - { - FT_Int i; - - - for ( i = 0; i < face->num_fixed_sizes; i++ ) - { - FT_Bitmap_Size* bsize = face->available_sizes + i; - - - if ( bsize->height < 0 ) - bsize->height = (FT_Short)-bsize->height; - if ( bsize->x_ppem < 0 ) - bsize->x_ppem = (FT_Short)-bsize->x_ppem; - if ( bsize->y_ppem < 0 ) - bsize->y_ppem = -bsize->y_ppem; - } - } - - /* initialize internal face data */ - { - FT_Face_Internal internal = face->internal; - - - internal->transform_matrix.xx = 0x10000L; - internal->transform_matrix.xy = 0; - internal->transform_matrix.yx = 0; - internal->transform_matrix.yy = 0x10000L; - - internal->transform_delta.x = 0; - internal->transform_delta.y = 0; - - internal->refcount = 1; - } - - if ( aface ) - *aface = face; - else - FT_Done_Face( face ); - - goto Exit; - - Fail: - if ( node ) - FT_Done_Face( face ); /* face must be in the driver's list */ - else if ( face ) - destroy_face( memory, face, driver ); - - Exit: - FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); - - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Attach_File( FT_Face face, - const char* filepathname ) - { - FT_Open_Args open; - - - /* test for valid `face' delayed to `FT_Attach_Stream' */ - - if ( !filepathname ) - return FT_THROW( Invalid_Argument ); - - open.stream = NULL; - open.flags = FT_OPEN_PATHNAME; - open.pathname = (char*)filepathname; - - return FT_Attach_Stream( face, &open ); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Attach_Stream( FT_Face face, - FT_Open_Args* parameters ) - { - FT_Stream stream; - FT_Error error; - FT_Driver driver; - - FT_Driver_Class clazz; - - - /* test for valid `parameters' delayed to `FT_Stream_New' */ - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - driver = face->driver; - if ( !driver ) - return FT_THROW( Invalid_Driver_Handle ); - - error = FT_Stream_New( driver->root.library, parameters, &stream ); - if ( error ) - goto Exit; - - /* we implement FT_Attach_Stream in each driver through the */ - /* `attach_file' interface */ - - error = FT_ERR( Unimplemented_Feature ); - clazz = driver->clazz; - if ( clazz->attach_file ) - error = clazz->attach_file( face, stream ); - - /* close the attached stream */ - FT_Stream_Free( stream, - (FT_Bool)( parameters->stream && - ( parameters->flags & FT_OPEN_STREAM ) ) ); - - Exit: - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Reference_Face( FT_Face face ) - { - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - face->internal->refcount++; - - return FT_Err_Ok; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Done_Face( FT_Face face ) - { - FT_Error error; - FT_Driver driver; - FT_Memory memory; - FT_ListNode node; - - - error = FT_ERR( Invalid_Face_Handle ); - if ( face && face->driver ) - { - face->internal->refcount--; - if ( face->internal->refcount > 0 ) - error = FT_Err_Ok; - else - { - driver = face->driver; - memory = driver->root.memory; - - /* find face in driver's list */ - node = FT_List_Find( &driver->faces_list, face ); - if ( node ) - { - /* remove face object from the driver's list */ - FT_List_Remove( &driver->faces_list, node ); - FT_FREE( node ); - - /* now destroy the object proper */ - destroy_face( memory, face, driver ); - error = FT_Err_Ok; - } - } - } - - return error; - } - - - /* documentation is in ftobjs.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_New_Size( FT_Face face, - FT_Size *asize ) - { - FT_Error error; - FT_Memory memory; - FT_Driver driver; - FT_Driver_Class clazz; - - FT_Size size = NULL; - FT_ListNode node = NULL; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !asize ) - return FT_THROW( Invalid_Argument ); - - if ( !face->driver ) - return FT_THROW( Invalid_Driver_Handle ); - - *asize = NULL; - - driver = face->driver; - clazz = driver->clazz; - memory = face->memory; - - /* Allocate new size object and perform basic initialisation */ - if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) ) - goto Exit; - - size->face = face; - - /* for now, do not use any internal fields in size objects */ - size->internal = NULL; - - if ( clazz->init_size ) - error = clazz->init_size( size ); - - /* in case of success, add to the face's list */ - if ( !error ) - { - *asize = size; - node->data = size; - FT_List_Add( &face->sizes_list, node ); - } - - Exit: - if ( error ) - { - FT_FREE( node ); - FT_FREE( size ); - } - - return error; - } - - - /* documentation is in ftobjs.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Done_Size( FT_Size size ) - { - FT_Error error; - FT_Driver driver; - FT_Memory memory; - FT_Face face; - FT_ListNode node; - - - if ( !size ) - return FT_THROW( Invalid_Size_Handle ); - - face = size->face; - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - driver = face->driver; - if ( !driver ) - return FT_THROW( Invalid_Driver_Handle ); - - memory = driver->root.memory; - - error = FT_Err_Ok; - node = FT_List_Find( &face->sizes_list, size ); - if ( node ) - { - FT_List_Remove( &face->sizes_list, node ); - FT_FREE( node ); - - if ( face->size == size ) - { - face->size = NULL; - if ( face->sizes_list.head ) - face->size = (FT_Size)(face->sizes_list.head->data); - } - - destroy_size( memory, size, driver ); - } - else - error = FT_THROW( Invalid_Size_Handle ); - - return error; - } - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( FT_Error ) - FT_Match_Size( FT_Face face, - FT_Size_Request req, - FT_Bool ignore_width, - FT_ULong* size_index ) - { - FT_Int i; - FT_Long w, h; - - - if ( !FT_HAS_FIXED_SIZES( face ) ) - return FT_THROW( Invalid_Face_Handle ); - - /* FT_Bitmap_Size doesn't provide enough info... */ - if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) - return FT_THROW( Unimplemented_Feature ); - - w = FT_REQUEST_WIDTH ( req ); - h = FT_REQUEST_HEIGHT( req ); - - if ( req->width && !req->height ) - h = w; - else if ( !req->width && req->height ) - w = h; - - w = FT_PIX_ROUND( w ); - h = FT_PIX_ROUND( h ); - - for ( i = 0; i < face->num_fixed_sizes; i++ ) - { - FT_Bitmap_Size* bsize = face->available_sizes + i; - - - if ( h != FT_PIX_ROUND( bsize->y_ppem ) ) - continue; - - if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width ) - { - FT_TRACE3(( "FT_Match_Size: bitmap strike %d matches\n", i )); - - if ( size_index ) - *size_index = (FT_ULong)i; - - return FT_Err_Ok; - } - } - - return FT_THROW( Invalid_Pixel_Size ); - } - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( void ) - ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics, - FT_Pos advance ) - { - FT_Pos height = metrics->height; - - - /* compensate for glyph with bbox above/below the baseline */ - if ( metrics->horiBearingY < 0 ) - { - if ( height < metrics->horiBearingY ) - height = metrics->horiBearingY; - } - else if ( metrics->horiBearingY > 0 ) - height -= metrics->horiBearingY; - - /* the factor 1.2 is a heuristical value */ - if ( !advance ) - advance = height * 12 / 10; - - metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2; - metrics->vertBearingY = ( advance - height ) / 2; - metrics->vertAdvance = advance; - } - - - static void - ft_recompute_scaled_metrics( FT_Face face, - FT_Size_Metrics* metrics ) - { - /* Compute root ascender, descender, test height, and max_advance */ - -#ifdef GRID_FIT_METRICS - metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender, - metrics->y_scale ) ); - - metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender, - metrics->y_scale ) ); - - metrics->height = FT_PIX_ROUND( FT_MulFix( face->height, - metrics->y_scale ) ); - - metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width, - metrics->x_scale ) ); -#else /* !GRID_FIT_METRICS */ - metrics->ascender = FT_MulFix( face->ascender, - metrics->y_scale ); - - metrics->descender = FT_MulFix( face->descender, - metrics->y_scale ); - - metrics->height = FT_MulFix( face->height, - metrics->y_scale ); - - metrics->max_advance = FT_MulFix( face->max_advance_width, - metrics->x_scale ); -#endif /* !GRID_FIT_METRICS */ - } - - - FT_BASE_DEF( void ) - FT_Select_Metrics( FT_Face face, - FT_ULong strike_index ) - { - FT_Size_Metrics* metrics; - FT_Bitmap_Size* bsize; - - - metrics = &face->size->metrics; - bsize = face->available_sizes + strike_index; - - metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 ); - metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 ); - - if ( FT_IS_SCALABLE( face ) ) - { - metrics->x_scale = FT_DivFix( bsize->x_ppem, - face->units_per_EM ); - metrics->y_scale = FT_DivFix( bsize->y_ppem, - face->units_per_EM ); - - ft_recompute_scaled_metrics( face, metrics ); - } - else - { - metrics->x_scale = 1L << 16; - metrics->y_scale = 1L << 16; - metrics->ascender = bsize->y_ppem; - metrics->descender = 0; - metrics->height = bsize->height << 6; - metrics->max_advance = bsize->x_ppem; - } - - FT_TRACE5(( "FT_Select_Metrics:\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); - } - - - FT_BASE_DEF( void ) - FT_Request_Metrics( FT_Face face, - FT_Size_Request req ) - { - FT_Size_Metrics* metrics; - - - metrics = &face->size->metrics; - - if ( FT_IS_SCALABLE( face ) ) - { - FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0; - - - switch ( req->type ) - { - case FT_SIZE_REQUEST_TYPE_NOMINAL: - w = h = face->units_per_EM; - break; - - case FT_SIZE_REQUEST_TYPE_REAL_DIM: - w = h = face->ascender - face->descender; - break; - - case FT_SIZE_REQUEST_TYPE_BBOX: - w = face->bbox.xMax - face->bbox.xMin; - h = face->bbox.yMax - face->bbox.yMin; - break; - - case FT_SIZE_REQUEST_TYPE_CELL: - w = face->max_advance_width; - h = face->ascender - face->descender; - break; - - case FT_SIZE_REQUEST_TYPE_SCALES: - metrics->x_scale = (FT_Fixed)req->width; - metrics->y_scale = (FT_Fixed)req->height; - if ( !metrics->x_scale ) - metrics->x_scale = metrics->y_scale; - else if ( !metrics->y_scale ) - metrics->y_scale = metrics->x_scale; - goto Calculate_Ppem; - - case FT_SIZE_REQUEST_TYPE_MAX: - break; - } - - /* to be on the safe side */ - if ( w < 0 ) - w = -w; - - if ( h < 0 ) - h = -h; - - scaled_w = FT_REQUEST_WIDTH ( req ); - scaled_h = FT_REQUEST_HEIGHT( req ); - - /* determine scales */ - if ( req->width ) - { - metrics->x_scale = FT_DivFix( scaled_w, w ); - - if ( req->height ) - { - metrics->y_scale = FT_DivFix( scaled_h, h ); - - if ( req->type == FT_SIZE_REQUEST_TYPE_CELL ) - { - if ( metrics->y_scale > metrics->x_scale ) - metrics->y_scale = metrics->x_scale; - else - metrics->x_scale = metrics->y_scale; - } - } - else - { - metrics->y_scale = metrics->x_scale; - scaled_h = FT_MulDiv( scaled_w, h, w ); - } - } - else - { - metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h ); - scaled_w = FT_MulDiv( scaled_h, w, h ); - } - - Calculate_Ppem: - /* calculate the ppems */ - if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) - { - scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale ); - scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale ); - } - - metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 ); - metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 ); - - ft_recompute_scaled_metrics( face, metrics ); - } - else - { - FT_ZERO( metrics ); - metrics->x_scale = 1L << 16; - metrics->y_scale = 1L << 16; - } - - FT_TRACE5(( "FT_Request_Metrics:\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Select_Size( FT_Face face, - FT_Int strike_index ) - { - FT_Driver_Class clazz; - - - if ( !face || !FT_HAS_FIXED_SIZES( face ) ) - return FT_THROW( Invalid_Face_Handle ); - - if ( strike_index < 0 || strike_index >= face->num_fixed_sizes ) - return FT_THROW( Invalid_Argument ); - - clazz = face->driver->clazz; - - if ( clazz->select_size ) - { - FT_Error error; - - - error = clazz->select_size( face->size, (FT_ULong)strike_index ); - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_Size_Metrics* metrics = &face->size->metrics; - - - FT_TRACE5(( "FT_Select_Size (font driver's `select_size'):\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); - } -#endif - - return error; - } - - FT_Select_Metrics( face, (FT_ULong)strike_index ); - - return FT_Err_Ok; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Request_Size( FT_Face face, - FT_Size_Request req ) - { - FT_Driver_Class clazz; - FT_ULong strike_index; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !req || req->width < 0 || req->height < 0 || - req->type >= FT_SIZE_REQUEST_TYPE_MAX ) - return FT_THROW( Invalid_Argument ); - - clazz = face->driver->clazz; - - if ( clazz->request_size ) - { - FT_Error error; - - - error = clazz->request_size( face->size, req ); - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_Size_Metrics* metrics = &face->size->metrics; - - - FT_TRACE5(( "FT_Request_Size (font driver's `request_size'):\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); - } -#endif - - return error; - } - - /* - * The reason that a driver doesn't have `request_size' defined is - * either that the scaling here suffices or that the supported formats - * are bitmap-only and size matching is not implemented. - * - * In the latter case, a simple size matching is done. - */ - if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) ) - { - FT_Error error; - - - error = FT_Match_Size( face, req, 0, &strike_index ); - if ( error ) - return error; - - return FT_Select_Size( face, (FT_Int)strike_index ); - } - - FT_Request_Metrics( face, req ); - - return FT_Err_Ok; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_Char_Size( FT_Face face, - FT_F26Dot6 char_width, - FT_F26Dot6 char_height, - FT_UInt horz_resolution, - FT_UInt vert_resolution ) - { - FT_Size_RequestRec req; - - - /* check of `face' delayed to `FT_Request_Size' */ - - if ( !char_width ) - char_width = char_height; - else if ( !char_height ) - char_height = char_width; - - if ( !horz_resolution ) - horz_resolution = vert_resolution; - else if ( !vert_resolution ) - vert_resolution = horz_resolution; - - if ( char_width < 1 * 64 ) - char_width = 1 * 64; - if ( char_height < 1 * 64 ) - char_height = 1 * 64; - - if ( !horz_resolution ) - horz_resolution = vert_resolution = 72; - - req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; - req.width = char_width; - req.height = char_height; - req.horiResolution = horz_resolution; - req.vertResolution = vert_resolution; - - return FT_Request_Size( face, &req ); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_Pixel_Sizes( FT_Face face, - FT_UInt pixel_width, - FT_UInt pixel_height ) - { - FT_Size_RequestRec req; - - - /* check of `face' delayed to `FT_Request_Size' */ - - if ( pixel_width == 0 ) - pixel_width = pixel_height; - else if ( pixel_height == 0 ) - pixel_height = pixel_width; - - if ( pixel_width < 1 ) - pixel_width = 1; - if ( pixel_height < 1 ) - pixel_height = 1; - - /* use `>=' to avoid potential compiler warning on 16bit platforms */ - if ( pixel_width >= 0xFFFFU ) - pixel_width = 0xFFFFU; - if ( pixel_height >= 0xFFFFU ) - pixel_height = 0xFFFFU; - - req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; - req.width = (FT_Long)( pixel_width << 6 ); - req.height = (FT_Long)( pixel_height << 6 ); - req.horiResolution = 0; - req.vertResolution = 0; - - return FT_Request_Size( face, &req ); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Kerning( FT_Face face, - FT_UInt left_glyph, - FT_UInt right_glyph, - FT_UInt kern_mode, - FT_Vector *akerning ) - { - FT_Error error = FT_Err_Ok; - FT_Driver driver; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !akerning ) - return FT_THROW( Invalid_Argument ); - - driver = face->driver; - - akerning->x = 0; - akerning->y = 0; - - if ( driver->clazz->get_kerning ) - { - error = driver->clazz->get_kerning( face, - left_glyph, - right_glyph, - akerning ); - if ( !error ) - { - if ( kern_mode != FT_KERNING_UNSCALED ) - { - akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale ); - akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale ); - - if ( kern_mode != FT_KERNING_UNFITTED ) - { - FT_Pos orig_x = akerning->x; - FT_Pos orig_y = akerning->y; - - - /* we scale down kerning values for small ppem values */ - /* to avoid that rounding makes them too big. */ - /* `25' has been determined heuristically. */ - if ( face->size->metrics.x_ppem < 25 ) - akerning->x = FT_MulDiv( orig_x, - face->size->metrics.x_ppem, 25 ); - if ( face->size->metrics.y_ppem < 25 ) - akerning->y = FT_MulDiv( orig_y, - face->size->metrics.y_ppem, 25 ); - - akerning->x = FT_PIX_ROUND( akerning->x ); - akerning->y = FT_PIX_ROUND( akerning->y ); - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_Pos orig_x_rounded = FT_PIX_ROUND( orig_x ); - FT_Pos orig_y_rounded = FT_PIX_ROUND( orig_y ); - - - if ( akerning->x != orig_x_rounded || - akerning->y != orig_y_rounded ) - FT_TRACE5(( "FT_Get_Kerning: horizontal kerning" - " (%d, %d) scaled down to (%d, %d) pixels\n", - orig_x_rounded / 64, orig_y_rounded / 64, - akerning->x / 64, akerning->y / 64 )); - } -#endif - } - } - } - } - - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Track_Kerning( FT_Face face, - FT_Fixed point_size, - FT_Int degree, - FT_Fixed* akerning ) - { - FT_Service_Kerning service; - FT_Error error = FT_Err_Ok; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !akerning ) - return FT_THROW( Invalid_Argument ); - - FT_FACE_FIND_SERVICE( face, service, KERNING ); - if ( !service ) - return FT_THROW( Unimplemented_Feature ); - - error = service->get_track( face, - point_size, - degree, - akerning ); - - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Select_Charmap( FT_Face face, - FT_Encoding encoding ) - { - FT_CharMap* cur; - FT_CharMap* limit; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( encoding == FT_ENCODING_NONE ) - return FT_THROW( Invalid_Argument ); - - /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */ - /* charmap available, i.e., one with UCS-4 characters, if possible. */ - /* */ - /* This is done by find_unicode_charmap() above, to share code. */ - if ( encoding == FT_ENCODING_UNICODE ) - return find_unicode_charmap( face ); - - cur = face->charmaps; - if ( !cur ) - return FT_THROW( Invalid_CharMap_Handle ); - - limit = cur + face->num_charmaps; - - for ( ; cur < limit; cur++ ) - { - if ( cur[0]->encoding == encoding ) - { - face->charmap = cur[0]; - return 0; - } - } - - return FT_THROW( Invalid_Argument ); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_Charmap( FT_Face face, - FT_CharMap charmap ) - { - FT_CharMap* cur; - FT_CharMap* limit; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - cur = face->charmaps; - if ( !cur || !charmap ) - return FT_THROW( Invalid_CharMap_Handle ); - - if ( FT_Get_CMap_Format( charmap ) == 14 ) - return FT_THROW( Invalid_Argument ); - - limit = cur + face->num_charmaps; - - for ( ; cur < limit; cur++ ) - { - if ( cur[0] == charmap ) - { - face->charmap = cur[0]; - return FT_Err_Ok; - } - } - - return FT_THROW( Invalid_Argument ); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Int ) - FT_Get_Charmap_Index( FT_CharMap charmap ) - { - FT_Int i; - - - if ( !charmap || !charmap->face ) - return -1; - - for ( i = 0; i < charmap->face->num_charmaps; i++ ) - if ( charmap->face->charmaps[i] == charmap ) - break; - - FT_ASSERT( i < charmap->face->num_charmaps ); - - return i; - } - - - static void - ft_cmap_done_internal( FT_CMap cmap ) - { - FT_CMap_Class clazz = cmap->clazz; - FT_Face face = cmap->charmap.face; - FT_Memory memory = FT_FACE_MEMORY( face ); - - - if ( clazz->done ) - clazz->done( cmap ); - - FT_FREE( cmap ); - } - - - FT_BASE_DEF( void ) - FT_CMap_Done( FT_CMap cmap ) - { - if ( cmap ) - { - FT_Face face = cmap->charmap.face; - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Error error; - FT_Int i, j; - - - for ( i = 0; i < face->num_charmaps; i++ ) - { - if ( (FT_CMap)face->charmaps[i] == cmap ) - { - FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1]; - - - if ( FT_RENEW_ARRAY( face->charmaps, - face->num_charmaps, - face->num_charmaps - 1 ) ) - return; - - /* remove it from our list of charmaps */ - for ( j = i + 1; j < face->num_charmaps; j++ ) - { - if ( j == face->num_charmaps - 1 ) - face->charmaps[j - 1] = last_charmap; - else - face->charmaps[j - 1] = face->charmaps[j]; - } - - face->num_charmaps--; - - if ( (FT_CMap)face->charmap == cmap ) - face->charmap = NULL; - - ft_cmap_done_internal( cmap ); - - break; - } - } - } - } - - - FT_BASE_DEF( FT_Error ) - FT_CMap_New( FT_CMap_Class clazz, - FT_Pointer init_data, - FT_CharMap charmap, - FT_CMap *acmap ) - { - FT_Error error = FT_Err_Ok; - FT_Face face; - FT_Memory memory; - FT_CMap cmap = NULL; - - - if ( clazz == NULL || charmap == NULL || charmap->face == NULL ) - return FT_THROW( Invalid_Argument ); - - face = charmap->face; - memory = FT_FACE_MEMORY( face ); - - if ( !FT_ALLOC( cmap, clazz->size ) ) - { - cmap->charmap = *charmap; - cmap->clazz = clazz; - - if ( clazz->init ) - { - error = clazz->init( cmap, init_data ); - if ( error ) - goto Fail; - } - - /* add it to our list of charmaps */ - if ( FT_RENEW_ARRAY( face->charmaps, - face->num_charmaps, - face->num_charmaps + 1 ) ) - goto Fail; - - face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap; - } - - Exit: - if ( acmap ) - *acmap = cmap; - - return error; - - Fail: - ft_cmap_done_internal( cmap ); - cmap = NULL; - goto Exit; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UInt ) - FT_Get_Char_Index( FT_Face face, - FT_ULong charcode ) - { - FT_UInt result = 0; - - - if ( face && face->charmap ) - { - FT_CMap cmap = FT_CMAP( face->charmap ); - - - if ( charcode > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); - FT_TRACE1(( " 0x%x is truncated\n", charcode )); - } - - result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode ); - if ( result >= (FT_UInt)face->num_glyphs ) - result = 0; - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_ULong ) - FT_Get_First_Char( FT_Face face, - FT_UInt *agindex ) - { - FT_ULong result = 0; - FT_UInt gindex = 0; - - - /* only do something if we have a charmap, and we have glyphs at all */ - if ( face && face->charmap && face->num_glyphs ) - { - gindex = FT_Get_Char_Index( face, 0 ); - if ( gindex == 0 ) - result = FT_Get_Next_Char( face, 0, &gindex ); - } - - if ( agindex ) - *agindex = gindex; - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_ULong ) - FT_Get_Next_Char( FT_Face face, - FT_ULong charcode, - FT_UInt *agindex ) - { - FT_ULong result = 0; - FT_UInt gindex = 0; - - - if ( face && face->charmap && face->num_glyphs ) - { - FT_UInt32 code = (FT_UInt32)charcode; - FT_CMap cmap = FT_CMAP( face->charmap ); - - - do - { - gindex = cmap->clazz->char_next( cmap, &code ); - - } while ( gindex >= (FT_UInt)face->num_glyphs ); - - result = ( gindex == 0 ) ? 0 : code; - } - - if ( agindex ) - *agindex = gindex; - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UInt ) - FT_Face_GetCharVariantIndex( FT_Face face, - FT_ULong charcode, - FT_ULong variantSelector ) - { - FT_UInt result = 0; - - - if ( face && - face->charmap && - face->charmap->encoding == FT_ENCODING_UNICODE ) - { - FT_CharMap charmap = find_variant_selector_charmap( face ); - FT_CMap ucmap = FT_CMAP( face->charmap ); - - - if ( charmap != NULL ) - { - FT_CMap vcmap = FT_CMAP( charmap ); - - - if ( charcode > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); - FT_TRACE1(( " 0x%x is truncated\n", charcode )); - } - if ( variantSelector > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); - FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); - } - - result = vcmap->clazz->char_var_index( vcmap, ucmap, - (FT_UInt32)charcode, - (FT_UInt32)variantSelector ); - } - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Int ) - FT_Face_GetCharVariantIsDefault( FT_Face face, - FT_ULong charcode, - FT_ULong variantSelector ) - { - FT_Int result = -1; - - - if ( face ) - { - FT_CharMap charmap = find_variant_selector_charmap( face ); - - - if ( charmap != NULL ) - { - FT_CMap vcmap = FT_CMAP( charmap ); - - - if ( charcode > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); - FT_TRACE1(( " 0x%x is truncated\n", charcode )); - } - if ( variantSelector > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); - FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); - } - - result = vcmap->clazz->char_var_default( vcmap, - (FT_UInt32)charcode, - (FT_UInt32)variantSelector ); - } - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UInt32* ) - FT_Face_GetVariantSelectors( FT_Face face ) - { - FT_UInt32 *result = NULL; - - - if ( face ) - { - FT_CharMap charmap = find_variant_selector_charmap( face ); - - - if ( charmap != NULL ) - { - FT_CMap vcmap = FT_CMAP( charmap ); - FT_Memory memory = FT_FACE_MEMORY( face ); - - - result = vcmap->clazz->variant_list( vcmap, memory ); - } - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UInt32* ) - FT_Face_GetVariantsOfChar( FT_Face face, - FT_ULong charcode ) - { - FT_UInt32 *result = NULL; - - - if ( face ) - { - FT_CharMap charmap = find_variant_selector_charmap( face ); - - - if ( charmap != NULL ) - { - FT_CMap vcmap = FT_CMAP( charmap ); - FT_Memory memory = FT_FACE_MEMORY( face ); - - - if ( charcode > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); - FT_TRACE1(( " 0x%x is truncated\n", charcode )); - } - - result = vcmap->clazz->charvariant_list( vcmap, memory, - (FT_UInt32)charcode ); - } - } - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UInt32* ) - FT_Face_GetCharsOfVariant( FT_Face face, - FT_ULong variantSelector ) - { - FT_UInt32 *result = NULL; - - - if ( face ) - { - FT_CharMap charmap = find_variant_selector_charmap( face ); - - - if ( charmap != NULL ) - { - FT_CMap vcmap = FT_CMAP( charmap ); - FT_Memory memory = FT_FACE_MEMORY( face ); - - - if ( variantSelector > 0xFFFFFFFFUL ) - { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); - FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); - } - - result = vcmap->clazz->variantchar_list( vcmap, memory, - (FT_UInt32)variantSelector ); - } - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_UInt ) - FT_Get_Name_Index( FT_Face face, - FT_String* glyph_name ) - { - FT_UInt result = 0; - - - if ( face && - FT_HAS_GLYPH_NAMES( face ) && - glyph_name ) - { - FT_Service_GlyphDict service; - - - FT_FACE_LOOKUP_SERVICE( face, - service, - GLYPH_DICT ); - - if ( service && service->name_index ) - result = service->name_index( face, glyph_name ); - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Glyph_Name( FT_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ) - { - FT_Error error; - FT_Service_GlyphDict service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !buffer || buffer_max == 0 ) - return FT_THROW( Invalid_Argument ); - - /* clean up buffer */ - ((FT_Byte*)buffer)[0] = '\0'; - - if ( (FT_Long)glyph_index >= face->num_glyphs ) - return FT_THROW( Invalid_Glyph_Index ); - - if ( !FT_HAS_GLYPH_NAMES( face ) ) - return FT_THROW( Invalid_Argument ); - - FT_FACE_LOOKUP_SERVICE( face, service, GLYPH_DICT ); - if ( service && service->get_name ) - error = service->get_name( face, glyph_index, buffer, buffer_max ); - else - error = FT_THROW( Invalid_Argument ); - - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( const char* ) - FT_Get_Postscript_Name( FT_Face face ) - { - const char* result = NULL; - - - if ( !face ) - goto Exit; - - if ( !result ) - { - FT_Service_PsFontName service; - - - FT_FACE_LOOKUP_SERVICE( face, - service, - POSTSCRIPT_FONT_NAME ); - - if ( service && service->get_ps_font_name ) - result = service->get_ps_font_name( face ); - } - - Exit: - return result; - } - - - /* documentation is in tttables.h */ - - FT_EXPORT_DEF( void* ) - FT_Get_Sfnt_Table( FT_Face face, - FT_Sfnt_Tag tag ) - { - void* table = NULL; - FT_Service_SFNT_Table service; - - - if ( face && FT_IS_SFNT( face ) ) - { - FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); - if ( service != NULL ) - table = service->get_table( face, tag ); - } - - return table; - } - - - /* documentation is in tttables.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Load_Sfnt_Table( FT_Face face, - FT_ULong tag, - FT_Long offset, - FT_Byte* buffer, - FT_ULong* length ) - { - FT_Service_SFNT_Table service; - - - if ( !face || !FT_IS_SFNT( face ) ) - return FT_THROW( Invalid_Face_Handle ); - - FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); - if ( service == NULL ) - return FT_THROW( Unimplemented_Feature ); - - return service->load_table( face, tag, offset, buffer, length ); - } - - - /* documentation is in tttables.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Sfnt_Table_Info( FT_Face face, - FT_UInt table_index, - FT_ULong *tag, - FT_ULong *length ) - { - FT_Service_SFNT_Table service; - FT_ULong offset; - - - /* test for valid `length' delayed to `service->table_info' */ - - if ( !face || !FT_IS_SFNT( face ) ) - return FT_THROW( Invalid_Face_Handle ); - - FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); - if ( service == NULL ) - return FT_THROW( Unimplemented_Feature ); - - return service->table_info( face, table_index, tag, &offset, length ); - } - - - /* documentation is in tttables.h */ - - FT_EXPORT_DEF( FT_ULong ) - FT_Get_CMap_Language_ID( FT_CharMap charmap ) - { - FT_Service_TTCMaps service; - FT_Face face; - TT_CMapInfo cmap_info; - - - if ( !charmap || !charmap->face ) - return 0; - - face = charmap->face; - FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); - if ( service == NULL ) - return 0; - if ( service->get_cmap_info( charmap, &cmap_info )) - return 0; - - return cmap_info.language; - } - - - /* documentation is in tttables.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_Get_CMap_Format( FT_CharMap charmap ) - { - FT_Service_TTCMaps service; - FT_Face face; - TT_CMapInfo cmap_info; - - - if ( !charmap || !charmap->face ) - return -1; - - face = charmap->face; - FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); - if ( service == NULL ) - return -1; - if ( service->get_cmap_info( charmap, &cmap_info )) - return -1; - - return cmap_info.format; - } - - - /* documentation is in ftsizes.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Activate_Size( FT_Size size ) - { - FT_Face face; - - - if ( !size ) - return FT_THROW( Invalid_Size_Handle ); - - face = size->face; - if ( !face || !face->driver ) - return FT_THROW( Invalid_Face_Handle ); - - /* we don't need anything more complex than that; all size objects */ - /* are already listed by the face */ - face->size = size; - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** R E N D E R E R S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - /* lookup a renderer by glyph format in the library's list */ - FT_BASE_DEF( FT_Renderer ) - FT_Lookup_Renderer( FT_Library library, - FT_Glyph_Format format, - FT_ListNode* node ) - { - FT_ListNode cur; - FT_Renderer result = NULL; - - - if ( !library ) - goto Exit; - - cur = library->renderers.head; - - if ( node ) - { - if ( *node ) - cur = (*node)->next; - *node = NULL; - } - - while ( cur ) - { - FT_Renderer renderer = FT_RENDERER( cur->data ); - - - if ( renderer->glyph_format == format ) - { - if ( node ) - *node = cur; - - result = renderer; - break; - } - cur = cur->next; - } - - Exit: - return result; - } - - - static FT_Renderer - ft_lookup_glyph_renderer( FT_GlyphSlot slot ) - { - FT_Face face = slot->face; - FT_Library library = FT_FACE_LIBRARY( face ); - FT_Renderer result = library->cur_renderer; - - - if ( !result || result->glyph_format != slot->format ) - result = FT_Lookup_Renderer( library, slot->format, 0 ); - - return result; - } - - - static void - ft_set_current_renderer( FT_Library library ) - { - FT_Renderer renderer; - - - renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 ); - library->cur_renderer = renderer; - } - - - static FT_Error - ft_add_renderer( FT_Module module ) - { - FT_Library library = module->library; - FT_Memory memory = library->memory; - FT_Error error; - FT_ListNode node = NULL; - - - if ( FT_NEW( node ) ) - goto Exit; - - { - FT_Renderer render = FT_RENDERER( module ); - FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz; - - - render->clazz = clazz; - render->glyph_format = clazz->glyph_format; - - /* allocate raster object if needed */ - if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && - clazz->raster_class->raster_new ) - { - error = clazz->raster_class->raster_new( memory, &render->raster ); - if ( error ) - goto Fail; - - render->raster_render = clazz->raster_class->raster_render; - render->render = clazz->render_glyph; - } - - /* add to list */ - node->data = module; - FT_List_Add( &library->renderers, node ); - - ft_set_current_renderer( library ); - } - - Fail: - if ( error ) - FT_FREE( node ); - - Exit: - return error; - } - - - static void - ft_remove_renderer( FT_Module module ) - { - FT_Library library; - FT_Memory memory; - FT_ListNode node; - - - library = module->library; - if ( !library ) - return; - - memory = library->memory; - - node = FT_List_Find( &library->renderers, module ); - if ( node ) - { - FT_Renderer render = FT_RENDERER( module ); - - - /* release raster object, if any */ - if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && - render->raster ) - render->clazz->raster_class->raster_done( render->raster ); - - /* remove from list */ - FT_List_Remove( &library->renderers, node ); - FT_FREE( node ); - - ft_set_current_renderer( library ); - } - } - - - /* documentation is in ftrender.h */ - - FT_EXPORT_DEF( FT_Renderer ) - FT_Get_Renderer( FT_Library library, - FT_Glyph_Format format ) - { - /* test for valid `library' delayed to `FT_Lookup_Renderer' */ - - return FT_Lookup_Renderer( library, format, 0 ); - } - - - /* documentation is in ftrender.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Set_Renderer( FT_Library library, - FT_Renderer renderer, - FT_UInt num_params, - FT_Parameter* parameters ) - { - FT_ListNode node; - FT_Error error = FT_Err_Ok; - - FT_Renderer_SetModeFunc set_mode; - - - if ( !library ) - { - error = FT_THROW( Invalid_Library_Handle ); - goto Exit; - } - - if ( !renderer ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( num_params > 0 && !parameters ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - node = FT_List_Find( &library->renderers, renderer ); - if ( !node ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - FT_List_Up( &library->renderers, node ); - - if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE ) - library->cur_renderer = renderer; - - set_mode = renderer->clazz->set_mode; - - for ( ; num_params > 0; num_params-- ) - { - error = set_mode( renderer, parameters->tag, parameters->data ); - if ( error ) - break; - parameters++; - } - - Exit: - return error; - } - - - FT_BASE_DEF( FT_Error ) - FT_Render_Glyph_Internal( FT_Library library, - FT_GlyphSlot slot, - FT_Render_Mode render_mode ) - { - FT_Error error = FT_Err_Ok; - FT_Renderer renderer; - - - /* if it is already a bitmap, no need to do anything */ - switch ( slot->format ) - { - case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ - break; - - default: - { - FT_ListNode node = NULL; - - - /* small shortcut for the very common case */ - if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - { - renderer = library->cur_renderer; - node = library->renderers.head; - } - else - renderer = FT_Lookup_Renderer( library, slot->format, &node ); - - error = FT_ERR( Unimplemented_Feature ); - while ( renderer ) - { - error = renderer->render( renderer, slot, render_mode, NULL ); - if ( !error || - FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) - break; - - /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ - /* is unsupported by the current renderer for this glyph image */ - /* format. */ - - /* now, look for another renderer that supports the same */ - /* format. */ - renderer = FT_Lookup_Renderer( library, slot->format, &node ); - } - } - } - -#ifdef FT_DEBUG_LEVEL_TRACE - -#undef FT_COMPONENT -#define FT_COMPONENT trace_bitmap - - /* we convert to a single bitmap format for computing the checksum */ - if ( !error ) - { - FT_Bitmap bitmap; - FT_Error err; - - - FT_Bitmap_Init( &bitmap ); - - /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */ - err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 ); - if ( !err ) - { - MD5_CTX ctx; - unsigned char md5[16]; - int i; - unsigned int rows = bitmap.rows; - unsigned int pitch = (unsigned int)bitmap.pitch; - - - MD5_Init( &ctx ); - MD5_Update( &ctx, bitmap.buffer, rows * pitch ); - MD5_Final( md5, &ctx ); - - FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n" - " ", - rows, pitch )); - for ( i = 0; i < 16; i++ ) - FT_TRACE3(( "%02X", md5[i] )); - FT_TRACE3(( "\n" )); - } - - FT_Bitmap_Done( library, &bitmap ); - } - -#undef FT_COMPONENT -#define FT_COMPONENT trace_objs - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Render_Glyph( FT_GlyphSlot slot, - FT_Render_Mode render_mode ) - { - FT_Library library; - - - if ( !slot || !slot->face ) - return FT_THROW( Invalid_Argument ); - - library = FT_FACE_LIBRARY( slot->face ); - - return FT_Render_Glyph_Internal( library, slot, render_mode ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** M O D U L E S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Destroy_Module */ - /* */ - /* <Description> */ - /* Destroys a given module object. For drivers, this also destroys */ - /* all child faces. */ - /* */ - /* <InOut> */ - /* module :: A handle to the target driver object. */ - /* */ - /* <Note> */ - /* The driver _must_ be LOCKED! */ - /* */ - static void - Destroy_Module( FT_Module module ) - { - FT_Memory memory = module->memory; - FT_Module_Class* clazz = module->clazz; - FT_Library library = module->library; - - - if ( library && library->auto_hinter == module ) - library->auto_hinter = NULL; - - /* if the module is a renderer */ - if ( FT_MODULE_IS_RENDERER( module ) ) - ft_remove_renderer( module ); - - /* if the module is a font driver, add some steps */ - if ( FT_MODULE_IS_DRIVER( module ) ) - Destroy_Driver( FT_DRIVER( module ) ); - - /* finalize the module object */ - if ( clazz->module_done ) - clazz->module_done( module ); - - /* discard it */ - FT_FREE( module ); - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Add_Module( FT_Library library, - const FT_Module_Class* clazz ) - { - FT_Error error; - FT_Memory memory; - FT_Module module; - FT_UInt nn; - - -#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \ - FREETYPE_MINOR ) - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !clazz ) - return FT_THROW( Invalid_Argument ); - - /* check freetype version */ - if ( clazz->module_requires > FREETYPE_VER_FIXED ) - return FT_THROW( Invalid_Version ); - - /* look for a module with the same name in the library's table */ - for ( nn = 0; nn < library->num_modules; nn++ ) - { - module = library->modules[nn]; - if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 ) - { - /* this installed module has the same name, compare their versions */ - if ( clazz->module_version <= module->clazz->module_version ) - return FT_THROW( Lower_Module_Version ); - - /* remove the module from our list, then exit the loop to replace */ - /* it by our new version.. */ - FT_Remove_Module( library, module ); - break; - } - } - - memory = library->memory; - error = FT_Err_Ok; - - if ( library->num_modules >= FT_MAX_MODULES ) - { - error = FT_THROW( Too_Many_Drivers ); - goto Exit; - } - - /* allocate module object */ - if ( FT_ALLOC( module, clazz->module_size ) ) - goto Exit; - - /* base initialization */ - module->library = library; - module->memory = memory; - module->clazz = (FT_Module_Class*)clazz; - - /* check whether the module is a renderer - this must be performed */ - /* before the normal module initialization */ - if ( FT_MODULE_IS_RENDERER( module ) ) - { - /* add to the renderers list */ - error = ft_add_renderer( module ); - if ( error ) - goto Fail; - } - - /* is the module a auto-hinter? */ - if ( FT_MODULE_IS_HINTER( module ) ) - library->auto_hinter = module; - - /* if the module is a font driver */ - if ( FT_MODULE_IS_DRIVER( module ) ) - { - FT_Driver driver = FT_DRIVER( module ); - - - driver->clazz = (FT_Driver_Class)module->clazz; - } - - if ( clazz->module_init ) - { - error = clazz->module_init( module ); - if ( error ) - goto Fail; - } - - /* add module to the library's table */ - library->modules[library->num_modules++] = module; - - Exit: - return error; - - Fail: - if ( FT_MODULE_IS_RENDERER( module ) ) - { - FT_Renderer renderer = FT_RENDERER( module ); - - - if ( renderer->clazz && - renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && - renderer->raster ) - renderer->clazz->raster_class->raster_done( renderer->raster ); - } - - FT_FREE( module ); - goto Exit; - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Module ) - FT_Get_Module( FT_Library library, - const char* module_name ) - { - FT_Module result = NULL; - FT_Module* cur; - FT_Module* limit; - - - if ( !library || !module_name ) - return result; - - cur = library->modules; - limit = cur + library->num_modules; - - for ( ; cur < limit; cur++ ) - if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 ) - { - result = cur[0]; - break; - } - - return result; - } - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( const void* ) - FT_Get_Module_Interface( FT_Library library, - const char* mod_name ) - { - FT_Module module; - - - /* test for valid `library' delayed to FT_Get_Module() */ - - module = FT_Get_Module( library, mod_name ); - - return module ? module->clazz->module_interface : 0; - } - - - FT_BASE_DEF( FT_Pointer ) - ft_module_get_service( FT_Module module, - const char* service_id ) - { - FT_Pointer result = NULL; - - - if ( module ) - { - FT_ASSERT( module->clazz && module->clazz->get_interface ); - - /* first, look for the service in the module */ - if ( module->clazz->get_interface ) - result = module->clazz->get_interface( module, service_id ); - - if ( result == NULL ) - { - /* we didn't find it, look in all other modules then */ - FT_Library library = module->library; - FT_Module* cur = library->modules; - FT_Module* limit = cur + library->num_modules; - - - for ( ; cur < limit; cur++ ) - { - if ( cur[0] != module ) - { - FT_ASSERT( cur[0]->clazz ); - - if ( cur[0]->clazz->get_interface ) - { - result = cur[0]->clazz->get_interface( cur[0], service_id ); - if ( result != NULL ) - break; - } - } - } - } - } - - return result; - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Remove_Module( FT_Library library, - FT_Module module ) - { - /* try to find the module from the table, then remove it from there */ - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( module ) - { - FT_Module* cur = library->modules; - FT_Module* limit = cur + library->num_modules; - - - for ( ; cur < limit; cur++ ) - { - if ( cur[0] == module ) - { - /* remove it from the table */ - library->num_modules--; - limit--; - while ( cur < limit ) - { - cur[0] = cur[1]; - cur++; - } - limit[0] = NULL; - - /* destroy the module */ - Destroy_Module( module ); - - return FT_Err_Ok; - } - } - } - return FT_THROW( Invalid_Driver_Handle ); - } - - - static FT_Error - ft_property_do( FT_Library library, - const FT_String* module_name, - const FT_String* property_name, - void* value, - FT_Bool set ) - { - FT_Module* cur; - FT_Module* limit; - FT_Module_Interface interface; - - FT_Service_Properties service; - -#ifdef FT_DEBUG_LEVEL_ERROR - const FT_String* set_name = "FT_Property_Set"; - const FT_String* get_name = "FT_Property_Get"; - const FT_String* func_name = set ? set_name : get_name; -#endif - - FT_Bool missing_func; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !module_name || !property_name || !value ) - return FT_THROW( Invalid_Argument ); - - cur = library->modules; - limit = cur + library->num_modules; - - /* search module */ - for ( ; cur < limit; cur++ ) - if ( !ft_strcmp( cur[0]->clazz->module_name, module_name ) ) - break; - - if ( cur == limit ) - { - FT_ERROR(( "%s: can't find module `%s'\n", - func_name, module_name )); - return FT_THROW( Missing_Module ); - } - - /* check whether we have a service interface */ - if ( !cur[0]->clazz->get_interface ) - { - FT_ERROR(( "%s: module `%s' doesn't support properties\n", - func_name, module_name )); - return FT_THROW( Unimplemented_Feature ); - } - - /* search property service */ - interface = cur[0]->clazz->get_interface( cur[0], - FT_SERVICE_ID_PROPERTIES ); - if ( !interface ) - { - FT_ERROR(( "%s: module `%s' doesn't support properties\n", - func_name, module_name )); - return FT_THROW( Unimplemented_Feature ); - } - - service = (FT_Service_Properties)interface; - - if ( set ) - missing_func = (FT_Bool)( !service->set_property ); - else - missing_func = (FT_Bool)( !service->get_property ); - - if ( missing_func ) - { - FT_ERROR(( "%s: property service of module `%s' is broken\n", - func_name, module_name )); - return FT_THROW( Unimplemented_Feature ); - } - - return set ? service->set_property( cur[0], property_name, value ) - : service->get_property( cur[0], property_name, value ); - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Property_Set( FT_Library library, - const FT_String* module_name, - const FT_String* property_name, - const void* value ) - { - return ft_property_do( library, - module_name, - property_name, - (void*)value, - TRUE ); - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Property_Get( FT_Library library, - const FT_String* module_name, - const FT_String* property_name, - void* value ) - { - return ft_property_do( library, - module_name, - property_name, - value, - FALSE ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** L I B R A R Y ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Reference_Library( FT_Library library ) - { - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - library->refcount++; - - return FT_Err_Ok; - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_New_Library( FT_Memory memory, - FT_Library *alibrary ) - { - FT_Library library = NULL; - FT_Error error; - - - if ( !memory || !alibrary ) - return FT_THROW( Invalid_Argument ); - -#ifdef FT_DEBUG_LEVEL_ERROR - /* init debugging support */ - ft_debug_init(); -#endif - - /* first of all, allocate the library object */ - if ( FT_NEW( library ) ) - return error; - - library->memory = memory; - -#ifdef FT_CONFIG_OPTION_PIC - /* initialize position independent code containers */ - error = ft_pic_container_init( library ); - if ( error ) - goto Fail; -#endif - - /* we don't use raster_pool anymore. */ - library->raster_pool_size = 0; - library->raster_pool = NULL; - - library->version_major = FREETYPE_MAJOR; - library->version_minor = FREETYPE_MINOR; - library->version_patch = FREETYPE_PATCH; - - library->refcount = 1; - - /* That's ok now */ - *alibrary = library; - - return FT_Err_Ok; - -#ifdef FT_CONFIG_OPTION_PIC - Fail: - ft_pic_container_destroy( library ); -#endif - FT_FREE( library ); - return error; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( void ) - FT_Library_Version( FT_Library library, - FT_Int *amajor, - FT_Int *aminor, - FT_Int *apatch ) - { - FT_Int major = 0; - FT_Int minor = 0; - FT_Int patch = 0; - - - if ( library ) - { - major = library->version_major; - minor = library->version_minor; - patch = library->version_patch; - } - - if ( amajor ) - *amajor = major; - - if ( aminor ) - *aminor = minor; - - if ( apatch ) - *apatch = patch; - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Done_Library( FT_Library library ) - { - FT_Memory memory; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - library->refcount--; - if ( library->refcount > 0 ) - goto Exit; - - memory = library->memory; - - /* - * Close all faces in the library. If we don't do this, we can have - * some subtle memory leaks. - * - * Example: - * - * - the cff font driver uses the pshinter module in cff_size_done - * - if the pshinter module is destroyed before the cff font driver, - * opened FT_Face objects managed by the driver are not properly - * destroyed, resulting in a memory leak - * - * Some faces are dependent on other faces, like Type42 faces that - * depend on TrueType faces synthesized internally. - * - * The order of drivers should be specified in driver_name[]. - */ - { - FT_UInt m, n; - const char* driver_name[] = { "type42", NULL }; - - - for ( m = 0; - m < sizeof ( driver_name ) / sizeof ( driver_name[0] ); - m++ ) - { - for ( n = 0; n < library->num_modules; n++ ) - { - FT_Module module = library->modules[n]; - const char* module_name = module->clazz->module_name; - FT_List faces; - - - if ( driver_name[m] && - ft_strcmp( module_name, driver_name[m] ) != 0 ) - continue; - - if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 ) - continue; - - FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name )); - - faces = &FT_DRIVER( module )->faces_list; - while ( faces->head ) - { - FT_Done_Face( FT_FACE( faces->head->data ) ); - if ( faces->head ) - FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" )); - } - } - } - } - - /* Close all other modules in the library */ -#if 1 - /* XXX Modules are removed in the reversed order so that */ - /* type42 module is removed before truetype module. This */ - /* avoids double free in some occasions. It is a hack. */ - while ( library->num_modules > 0 ) - FT_Remove_Module( library, - library->modules[library->num_modules - 1] ); -#else - { - FT_UInt n; - - - for ( n = 0; n < library->num_modules; n++ ) - { - FT_Module module = library->modules[n]; - - - if ( module ) - { - Destroy_Module( module ); - library->modules[n] = NULL; - } - } - } -#endif - -#ifdef FT_CONFIG_OPTION_PIC - /* Destroy pic container contents */ - ft_pic_container_destroy( library ); -#endif - - FT_FREE( library ); - - Exit: - return FT_Err_Ok; - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( void ) - FT_Set_Debug_Hook( FT_Library library, - FT_UInt hook_index, - FT_DebugHook_Func debug_hook ) - { - if ( library && debug_hook && - hook_index < - ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) ) - library->debug_hooks[hook_index] = debug_hook; - } - - - /* documentation is in ftmodapi.h */ - - FT_EXPORT_DEF( FT_TrueTypeEngineType ) - FT_Get_TrueType_Engine_Type( FT_Library library ) - { - FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE; - - - if ( library ) - { - FT_Module module = FT_Get_Module( library, "truetype" ); - - - if ( module ) - { - FT_Service_TrueTypeEngine service; - - - service = (FT_Service_TrueTypeEngine) - ft_module_get_service( module, - FT_SERVICE_ID_TRUETYPE_ENGINE ); - if ( service ) - result = service->engine_type; - } - } - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, - FT_UInt sub_index, - FT_Int *p_index, - FT_UInt *p_flags, - FT_Int *p_arg1, - FT_Int *p_arg2, - FT_Matrix *p_transform ) - { - FT_Error error = FT_ERR( Invalid_Argument ); - - - if ( glyph && - glyph->subglyphs && - glyph->format == FT_GLYPH_FORMAT_COMPOSITE && - sub_index < glyph->num_subglyphs ) - { - FT_SubGlyph subg = glyph->subglyphs + sub_index; - - - *p_index = subg->index; - *p_flags = subg->flags; - *p_arg1 = subg->arg1; - *p_arg2 = subg->arg2; - *p_transform = subg->transform; - - error = FT_Err_Ok; - } - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftotval.c b/third_party/freetype/src/base/ftotval.c deleted file mode 100644 index 786457ba2afd9abf94746028bfd58a4757bee652..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftotval.c +++ /dev/null @@ -1,91 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftotval.c */ -/* */ -/* FreeType API for validating OpenType tables (body). */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_OPENTYPE_VALIDATE_H -#include FT_OPENTYPE_VALIDATE_H - - - /* documentation is in ftotval.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_OpenType_Validate( FT_Face face, - FT_UInt validation_flags, - FT_Bytes *BASE_table, - FT_Bytes *GDEF_table, - FT_Bytes *GPOS_table, - FT_Bytes *GSUB_table, - FT_Bytes *JSTF_table ) - { - FT_Service_OTvalidate service; - FT_Error error; - - - if ( !face ) - { - error = FT_THROW( Invalid_Face_Handle ); - goto Exit; - } - - if ( !( BASE_table && - GDEF_table && - GPOS_table && - GSUB_table && - JSTF_table ) ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - FT_FACE_FIND_GLOBAL_SERVICE( face, service, OPENTYPE_VALIDATE ); - - if ( service ) - error = service->validate( face, - validation_flags, - BASE_table, - GDEF_table, - GPOS_table, - GSUB_table, - JSTF_table ); - else - error = FT_THROW( Unimplemented_Feature ); - - Exit: - return error; - } - - - FT_EXPORT_DEF( void ) - FT_OpenType_Free( FT_Face face, - FT_Bytes table ) - { - FT_Memory memory; - - - if ( !face ) - return; - - memory = FT_FACE_MEMORY( face ); - - FT_FREE( table ); - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftoutln.c b/third_party/freetype/src/base/ftoutln.c deleted file mode 100644 index 35cc9f5569299b45c52e9523e9274a101fea94fe..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftoutln.c +++ /dev/null @@ -1,1099 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftoutln.c */ -/* */ -/* FreeType outline management (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* All functions are declared in freetype.h. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_OUTLINE_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_DEBUG_H -#include FT_TRIGONOMETRY_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_outline - - - static - const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Decompose( FT_Outline* outline, - const FT_Outline_Funcs* func_interface, - void* user ) - { -#undef SCALED -#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << shift ) \ - : ( (x) << shift ) ) - delta ) - - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_start; - - FT_Vector* point; - FT_Vector* limit; - char* tags; - - FT_Error error; - - FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ - FT_Int tag; /* current point's state */ - - FT_Int shift; - FT_Pos delta; - - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - if ( !func_interface ) - return FT_THROW( Invalid_Argument ); - - shift = func_interface->shift; - delta = func_interface->delta; - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - FT_Int last; /* index of last point in contour */ - - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); - - last = outline->contours[n]; - if ( last < 0 ) - goto Invalid_Outline; - limit = outline->points + last; - - v_start = outline->points[first]; - v_start.x = SCALED( v_start.x ); - v_start.y = SCALED( v_start.y ); - - v_last = outline->points[last]; - v_last.x = SCALED( v_last.x ); - v_last.y = SCALED( v_last.y ); - - v_control = v_start; - - point = outline->points + first; - tags = outline->tags + first; - tag = FT_CURVE_TAG( tags[0] ); - - /* A contour cannot start with a cubic control point! */ - if ( tag == FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - /* check first point to determine origin */ - if ( tag == FT_CURVE_TAG_CONIC ) - { - /* first point is conic control. Yes, this happens. */ - if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - limit--; - } - else - { - /* if both first and last points are conic, */ - /* start at their middle and record its position */ - /* for closure */ - v_start.x = ( v_start.x + v_last.x ) / 2; - v_start.y = ( v_start.y + v_last.y ) / 2; - - /* v_last = v_start; */ - } - point--; - tags--; - } - - FT_TRACE5(( " move to (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0 )); - error = func_interface->move_to( &v_start, user ); - if ( error ) - goto Exit; - - while ( point < limit ) - { - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - switch ( tag ) - { - case FT_CURVE_TAG_ON: /* emit a single line_to */ - { - FT_Vector vec; - - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); - - FT_TRACE5(( " line to (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0 )); - error = func_interface->line_to( &vec, user ); - if ( error ) - goto Exit; - continue; - } - - case FT_CURVE_TAG_CONIC: /* consume conic arcs */ - v_control.x = SCALED( point->x ); - v_control.y = SCALED( point->y ); - - Do_Conic: - if ( point < limit ) - { - FT_Vector vec; - FT_Vector v_middle; - - - point++; - tags++; - tag = FT_CURVE_TAG( tags[0] ); - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); - - if ( tag == FT_CURVE_TAG_ON ) - { - FT_TRACE5(( " conic to (%.2f, %.2f)" - " with control (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); - error = func_interface->conic_to( &v_control, &vec, user ); - if ( error ) - goto Exit; - continue; - } - - if ( tag != FT_CURVE_TAG_CONIC ) - goto Invalid_Outline; - - v_middle.x = ( v_control.x + vec.x ) / 2; - v_middle.y = ( v_control.y + vec.y ) / 2; - - FT_TRACE5(( " conic to (%.2f, %.2f)" - " with control (%.2f, %.2f)\n", - v_middle.x / 64.0, v_middle.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); - error = func_interface->conic_to( &v_control, &v_middle, user ); - if ( error ) - goto Exit; - - v_control = vec; - goto Do_Conic; - } - - FT_TRACE5(( " conic to (%.2f, %.2f)" - " with control (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); - error = func_interface->conic_to( &v_control, &v_start, user ); - goto Close; - - default: /* FT_CURVE_TAG_CUBIC */ - { - FT_Vector vec1, vec2; - - - if ( point + 1 > limit || - FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - point += 2; - tags += 2; - - vec1.x = SCALED( point[-2].x ); - vec1.y = SCALED( point[-2].y ); - - vec2.x = SCALED( point[-1].x ); - vec2.y = SCALED( point[-1].y ); - - if ( point <= limit ) - { - FT_Vector vec; - - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); - - FT_TRACE5(( " cubic to (%.2f, %.2f)" - " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0, - vec1.x / 64.0, vec1.y / 64.0, - vec2.x / 64.0, vec2.y / 64.0 )); - error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); - if ( error ) - goto Exit; - continue; - } - - FT_TRACE5(( " cubic to (%.2f, %.2f)" - " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0, - vec1.x / 64.0, vec1.y / 64.0, - vec2.x / 64.0, vec2.y / 64.0 )); - error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); - goto Close; - } - } - } - - /* close the contour with a line segment */ - FT_TRACE5(( " line to (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0 )); - error = func_interface->line_to( &v_start, user ); - - Close: - if ( error ) - goto Exit; - - first = (FT_UInt)last + 1; - } - - FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); - return FT_Err_Ok; - - Exit: - FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); - return error; - - Invalid_Outline: - return FT_THROW( Invalid_Outline ); - } - - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_New_Internal( FT_Memory memory, - FT_UInt numPoints, - FT_Int numContours, - FT_Outline *anoutline ) - { - FT_Error error; - - - if ( !anoutline || !memory ) - return FT_THROW( Invalid_Argument ); - - *anoutline = null_outline; - - if ( numContours < 0 || - (FT_UInt)numContours > numPoints ) - return FT_THROW( Invalid_Argument ); - - if ( numPoints > FT_OUTLINE_POINTS_MAX ) - return FT_THROW( Array_Too_Large ); - - if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || - FT_NEW_ARRAY( anoutline->tags, numPoints ) || - FT_NEW_ARRAY( anoutline->contours, numContours ) ) - goto Fail; - - anoutline->n_points = (FT_Short)numPoints; - anoutline->n_contours = (FT_Short)numContours; - anoutline->flags |= FT_OUTLINE_OWNER; - - return FT_Err_Ok; - - Fail: - anoutline->flags |= FT_OUTLINE_OWNER; - FT_Outline_Done_Internal( memory, anoutline ); - - return error; - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_New( FT_Library library, - FT_UInt numPoints, - FT_Int numContours, - FT_Outline *anoutline ) - { - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - return FT_Outline_New_Internal( library->memory, numPoints, - numContours, anoutline ); - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Check( FT_Outline* outline ) - { - if ( outline ) - { - FT_Int n_points = outline->n_points; - FT_Int n_contours = outline->n_contours; - FT_Int end0, end; - FT_Int n; - - - /* empty glyph? */ - if ( n_points == 0 && n_contours == 0 ) - return FT_Err_Ok; - - /* check point and contour counts */ - if ( n_points <= 0 || n_contours <= 0 ) - goto Bad; - - end0 = end = -1; - for ( n = 0; n < n_contours; n++ ) - { - end = outline->contours[n]; - - /* note that we don't accept empty contours */ - if ( end <= end0 || end >= n_points ) - goto Bad; - - end0 = end; - } - - if ( end != n_points - 1 ) - goto Bad; - - /* XXX: check the tags array */ - return FT_Err_Ok; - } - - Bad: - return FT_THROW( Invalid_Argument ); - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Copy( const FT_Outline* source, - FT_Outline *target ) - { - FT_Int is_owner; - - - if ( !source || !target ) - return FT_THROW( Invalid_Outline ); - - if ( source->n_points != target->n_points || - source->n_contours != target->n_contours ) - return FT_THROW( Invalid_Argument ); - - if ( source == target ) - return FT_Err_Ok; - - FT_ARRAY_COPY( target->points, source->points, source->n_points ); - - FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); - - FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); - - /* copy all flags, except the `FT_OUTLINE_OWNER' one */ - is_owner = target->flags & FT_OUTLINE_OWNER; - target->flags = source->flags; - - target->flags &= ~FT_OUTLINE_OWNER; - target->flags |= is_owner; - - return FT_Err_Ok; - } - - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Done_Internal( FT_Memory memory, - FT_Outline* outline ) - { - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - if ( !memory ) - return FT_THROW( Invalid_Argument ); - - if ( outline->flags & FT_OUTLINE_OWNER ) - { - FT_FREE( outline->points ); - FT_FREE( outline->tags ); - FT_FREE( outline->contours ); - } - *outline = null_outline; - - return FT_Err_Ok; - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Done( FT_Library library, - FT_Outline* outline ) - { - /* check for valid `outline' in FT_Outline_Done_Internal() */ - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - return FT_Outline_Done_Internal( library->memory, outline ); - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( void ) - FT_Outline_Get_CBox( const FT_Outline* outline, - FT_BBox *acbox ) - { - FT_Pos xMin, yMin, xMax, yMax; - - - if ( outline && acbox ) - { - if ( outline->n_points == 0 ) - { - xMin = 0; - yMin = 0; - xMax = 0; - yMax = 0; - } - else - { - FT_Vector* vec = outline->points; - FT_Vector* limit = vec + outline->n_points; - - - xMin = xMax = vec->x; - yMin = yMax = vec->y; - vec++; - - for ( ; vec < limit; vec++ ) - { - FT_Pos x, y; - - - x = vec->x; - if ( x < xMin ) xMin = x; - if ( x > xMax ) xMax = x; - - y = vec->y; - if ( y < yMin ) yMin = y; - if ( y > yMax ) yMax = y; - } - } - acbox->xMin = xMin; - acbox->xMax = xMax; - acbox->yMin = yMin; - acbox->yMax = yMax; - } - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( void ) - FT_Outline_Translate( const FT_Outline* outline, - FT_Pos xOffset, - FT_Pos yOffset ) - { - FT_UShort n; - FT_Vector* vec; - - - if ( !outline ) - return; - - vec = outline->points; - - for ( n = 0; n < outline->n_points; n++ ) - { - vec->x += xOffset; - vec->y += yOffset; - vec++; - } - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( void ) - FT_Outline_Reverse( FT_Outline* outline ) - { - FT_UShort n; - FT_Int first, last; - - - if ( !outline ) - return; - - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - last = outline->contours[n]; - - /* reverse point table */ - { - FT_Vector* p = outline->points + first; - FT_Vector* q = outline->points + last; - FT_Vector swap; - - - while ( p < q ) - { - swap = *p; - *p = *q; - *q = swap; - p++; - q--; - } - } - - /* reverse tags table */ - { - char* p = outline->tags + first; - char* q = outline->tags + last; - - - while ( p < q ) - { - char swap; - - - swap = *p; - *p = *q; - *q = swap; - p++; - q--; - } - } - - first = last + 1; - } - - outline->flags ^= FT_OUTLINE_REVERSE_FILL; - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Render( FT_Library library, - FT_Outline* outline, - FT_Raster_Params* params ) - { - FT_Error error; - FT_Renderer renderer; - FT_ListNode node; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - if ( !params ) - return FT_THROW( Invalid_Argument ); - - renderer = library->cur_renderer; - node = library->renderers.head; - - params->source = (void*)outline; - - error = FT_ERR( Cannot_Render_Glyph ); - while ( renderer ) - { - error = renderer->raster_render( renderer->raster, params ); - if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) - break; - - /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ - /* is unsupported by the current renderer for this glyph image */ - /* format */ - - /* now, look for another renderer that supports the same */ - /* format */ - renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, - &node ); - } - - return error; - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Get_Bitmap( FT_Library library, - FT_Outline* outline, - const FT_Bitmap *abitmap ) - { - FT_Raster_Params params; - - - if ( !abitmap ) - return FT_THROW( Invalid_Argument ); - - /* other checks are delayed to `FT_Outline_Render' */ - - params.target = abitmap; - params.flags = 0; - - if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || - abitmap->pixel_mode == FT_PIXEL_MODE_LCD || - abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) - params.flags |= FT_RASTER_FLAG_AA; - - return FT_Outline_Render( library, outline, ¶ms ); - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( void ) - FT_Vector_Transform( FT_Vector* vector, - const FT_Matrix* matrix ) - { - FT_Pos xz, yz; - - - if ( !vector || !matrix ) - return; - - xz = FT_MulFix( vector->x, matrix->xx ) + - FT_MulFix( vector->y, matrix->xy ); - - yz = FT_MulFix( vector->x, matrix->yx ) + - FT_MulFix( vector->y, matrix->yy ); - - vector->x = xz; - vector->y = yz; - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( void ) - FT_Outline_Transform( const FT_Outline* outline, - const FT_Matrix* matrix ) - { - FT_Vector* vec; - FT_Vector* limit; - - - if ( !outline || !matrix ) - return; - - vec = outline->points; - limit = vec + outline->n_points; - - for ( ; vec < limit; vec++ ) - FT_Vector_Transform( vec, matrix ); - } - - -#if 0 - -#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \ - do \ - { \ - (first) = ( c > 0 ) ? (outline)->points + \ - (outline)->contours[c - 1] + 1 \ - : (outline)->points; \ - (last) = (outline)->points + (outline)->contours[c]; \ - } while ( 0 ) - - - /* Is a point in some contour? */ - /* */ - /* We treat every point of the contour as if it */ - /* it were ON. That is, we allow false positives, */ - /* but disallow false negatives. (XXX really?) */ - static FT_Bool - ft_contour_has( FT_Outline* outline, - FT_Short c, - FT_Vector* point ) - { - FT_Vector* first; - FT_Vector* last; - FT_Vector* a; - FT_Vector* b; - FT_UInt n = 0; - - - FT_OUTLINE_GET_CONTOUR( outline, c, first, last ); - - for ( a = first; a <= last; a++ ) - { - FT_Pos x; - FT_Int intersect; - - - b = ( a == last ) ? first : a + 1; - - intersect = ( a->y - point->y ) ^ ( b->y - point->y ); - - /* a and b are on the same side */ - if ( intersect >= 0 ) - { - if ( intersect == 0 && a->y == point->y ) - { - if ( ( a->x <= point->x && b->x >= point->x ) || - ( a->x >= point->x && b->x <= point->x ) ) - return 1; - } - - continue; - } - - x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y ); - - if ( x < point->x ) - n++; - else if ( x == point->x ) - return 1; - } - - return n & 1; - } - - - static FT_Bool - ft_contour_enclosed( FT_Outline* outline, - FT_UShort c ) - { - FT_Vector* first; - FT_Vector* last; - FT_Short i; - - - FT_OUTLINE_GET_CONTOUR( outline, c, first, last ); - - for ( i = 0; i < outline->n_contours; i++ ) - { - if ( i != c && ft_contour_has( outline, i, first ) ) - { - FT_Vector* pt; - - - for ( pt = first + 1; pt <= last; pt++ ) - if ( !ft_contour_has( outline, i, pt ) ) - return 0; - - return 1; - } - } - - return 0; - } - - - /* This version differs from the public one in that each */ - /* part (contour not enclosed in another contour) of the */ - /* outline is checked for orientation. This is */ - /* necessary for some buggy CJK fonts. */ - static FT_Orientation - ft_outline_get_orientation( FT_Outline* outline ) - { - FT_Short i; - FT_Vector* first; - FT_Vector* last; - FT_Orientation orient = FT_ORIENTATION_NONE; - - - first = outline->points; - for ( i = 0; i < outline->n_contours; i++, first = last + 1 ) - { - FT_Vector* point; - FT_Vector* xmin_point; - FT_Pos xmin; - - - last = outline->points + outline->contours[i]; - - /* skip degenerate contours */ - if ( last < first + 2 ) - continue; - - if ( ft_contour_enclosed( outline, i ) ) - continue; - - xmin = first->x; - xmin_point = first; - - for ( point = first + 1; point <= last; point++ ) - { - if ( point->x < xmin ) - { - xmin = point->x; - xmin_point = point; - } - } - - /* check the orientation of the contour */ - { - FT_Vector* prev; - FT_Vector* next; - FT_Orientation o; - - - prev = ( xmin_point == first ) ? last : xmin_point - 1; - next = ( xmin_point == last ) ? first : xmin_point + 1; - - if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) > - FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) ) - o = FT_ORIENTATION_POSTSCRIPT; - else - o = FT_ORIENTATION_TRUETYPE; - - if ( orient == FT_ORIENTATION_NONE ) - orient = o; - else if ( orient != o ) - return FT_ORIENTATION_NONE; - } - } - - return orient; - } - -#endif /* 0 */ - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_Embolden( FT_Outline* outline, - FT_Pos strength ) - { - return FT_Outline_EmboldenXY( outline, strength, strength ); - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Outline_EmboldenXY( FT_Outline* outline, - FT_Pos xstrength, - FT_Pos ystrength ) - { - FT_Vector* points; - FT_Int c, first, last; - FT_Int orientation; - - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - xstrength /= 2; - ystrength /= 2; - if ( xstrength == 0 && ystrength == 0 ) - return FT_Err_Ok; - - orientation = FT_Outline_Get_Orientation( outline ); - if ( orientation == FT_ORIENTATION_NONE ) - { - if ( outline->n_contours ) - return FT_THROW( Invalid_Argument ); - else - return FT_Err_Ok; - } - - points = outline->points; - - first = 0; - for ( c = 0; c < outline->n_contours; c++ ) - { - FT_Vector in, out, anchor, shift; - FT_Fixed l_in, l_out, l_anchor = 0, l, q, d; - FT_Int i, j, k; - - - l_in = 0; - last = outline->contours[c]; - - /* Counter j cycles though the points; counter i advances only */ - /* when points are moved; anchor k marks the first moved point. */ - for ( i = last, j = first, k = -1; - j != i && i != k; - j = j < last ? j + 1 : first ) - { - if ( j != k ) - { - out.x = points[j].x - points[i].x; - out.y = points[j].y - points[i].y; - l_out = (FT_Fixed)FT_Vector_NormLen( &out ); - - if ( l_out == 0 ) - continue; - } - else - { - out = anchor; - l_out = l_anchor; - } - - if ( l_in != 0 ) - { - if ( k < 0 ) - { - k = i; - anchor = in; - l_anchor = l_in; - } - - d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); - - /* shift only if turn is less than ~160 degrees */ - if ( d > -0xF000L ) - { - d = d + 0x10000L; - - /* shift components along lateral bisector in proper orientation */ - shift.x = in.y + out.y; - shift.y = in.x + out.x; - - if ( orientation == FT_ORIENTATION_TRUETYPE ) - shift.x = -shift.x; - else - shift.y = -shift.y; - - /* restrict shift magnitude to better handle collapsing segments */ - q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); - if ( orientation == FT_ORIENTATION_TRUETYPE ) - q = -q; - - l = FT_MIN( l_in, l_out ); - - /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ - if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) ) - shift.x = FT_MulDiv( shift.x, xstrength, d ); - else - shift.x = FT_MulDiv( shift.x, l, q ); - - - if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) ) - shift.y = FT_MulDiv( shift.y, ystrength, d ); - else - shift.y = FT_MulDiv( shift.y, l, q ); - } - else - shift.x = shift.y = 0; - - for ( ; - i != j; - i = i < last ? i + 1 : first ) - { - points[i].x += xstrength + shift.x; - points[i].y += ystrength + shift.y; - } - } - else - i = j; - - in = out; - l_in = l_out; - } - - first = last + 1; - } - - return FT_Err_Ok; - } - - - /* documentation is in ftoutln.h */ - - FT_EXPORT_DEF( FT_Orientation ) - FT_Outline_Get_Orientation( FT_Outline* outline ) - { - FT_BBox cbox; - FT_Int xshift, yshift; - FT_Vector* points; - FT_Vector v_prev, v_cur; - FT_Int c, n, first; - FT_Pos area = 0; - - - if ( !outline || outline->n_points <= 0 ) - return FT_ORIENTATION_TRUETYPE; - - /* We use the nonzero winding rule to find the orientation. */ - /* Since glyph outlines behave much more `regular' than arbitrary */ - /* cubic or quadratic curves, this test deals with the polygon */ - /* only that is spanned up by the control points. */ - - FT_Outline_Get_CBox( outline, &cbox ); - - /* Handle collapsed outlines to avoid undefined FT_MSB. */ - if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax ) - return FT_ORIENTATION_NONE; - - xshift = FT_MSB( (FT_UInt32)( FT_ABS( cbox.xMax ) | - FT_ABS( cbox.xMin ) ) ) - 14; - xshift = FT_MAX( xshift, 0 ); - - yshift = FT_MSB( (FT_UInt32)( cbox.yMax - cbox.yMin ) ) - 14; - yshift = FT_MAX( yshift, 0 ); - - points = outline->points; - - first = 0; - for ( c = 0; c < outline->n_contours; c++ ) - { - FT_Int last = outline->contours[c]; - - - v_prev = points[last]; - - for ( n = first; n <= last; n++ ) - { - v_cur = points[n]; - area += ( ( v_cur.y - v_prev.y ) >> yshift ) * - ( ( v_cur.x + v_prev.x ) >> xshift ); - v_prev = v_cur; - } - - first = last + 1; - } - - if ( area > 0 ) - return FT_ORIENTATION_POSTSCRIPT; - else if ( area < 0 ) - return FT_ORIENTATION_TRUETYPE; - else - return FT_ORIENTATION_NONE; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftpatent.c b/third_party/freetype/src/base/ftpatent.c deleted file mode 100644 index bf2b0855c97725d6b5d29115d9d25e418c1fead5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftpatent.c +++ /dev/null @@ -1,287 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftpatent.c */ -/* */ -/* FreeType API for checking patented TrueType bytecode instructions */ -/* (body). */ -/* */ -/* Copyright 2007-2015 by */ -/* David Turner. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TRUETYPE_TAGS_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_STREAM_H -#include FT_SERVICE_SFNT_H -#include FT_SERVICE_TRUETYPE_GLYF_H - - - static FT_Bool - _tt_check_patents_in_range( FT_Stream stream, - FT_ULong size ) - { - FT_Bool result = FALSE; - FT_Error error; - FT_Bytes p, end; - - - if ( FT_FRAME_ENTER( size ) ) - return 0; - - p = stream->cursor; - end = p + size; - - while ( p < end ) - { - switch (p[0]) - { - case 0x06: /* SPvTL // */ - case 0x07: /* SPvTL + */ - case 0x08: /* SFvTL // */ - case 0x09: /* SFvTL + */ - case 0x0A: /* SPvFS */ - case 0x0B: /* SFvFS */ - result = TRUE; - goto Exit; - - case 0x40: - if ( p + 1 >= end ) - goto Exit; - - p += p[1] + 2; - break; - - case 0x41: - if ( p + 1 >= end ) - goto Exit; - - p += p[1] * 2 + 2; - break; - - case 0x71: /* DELTAP2 */ - case 0x72: /* DELTAP3 */ - case 0x73: /* DELTAC0 */ - case 0x74: /* DELTAC1 */ - case 0x75: /* DELTAC2 */ - result = TRUE; - goto Exit; - - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - p += ( p[0] - 0xB0 ) + 2; - break; - - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - p += ( p[0] - 0xB8 ) * 2 + 3; - break; - - default: - p += 1; - break; - } - } - - Exit: - FT_UNUSED( error ); - FT_FRAME_EXIT(); - return result; - } - - - static FT_Bool - _tt_check_patents_in_table( FT_Face face, - FT_ULong tag ) - { - FT_Stream stream = face->stream; - FT_Error error = FT_Err_Ok; - FT_Service_SFNT_Table service; - FT_Bool result = FALSE; - - - FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); - - if ( service ) - { - FT_UInt i = 0; - FT_ULong tag_i = 0, offset_i = 0, length_i = 0; - - - for ( i = 0; !error && tag_i != tag ; i++ ) - error = service->table_info( face, i, - &tag_i, &offset_i, &length_i ); - - if ( error || - FT_STREAM_SEEK( offset_i ) ) - goto Exit; - - result = _tt_check_patents_in_range( stream, length_i ); - } - - Exit: - return result; - } - - - static FT_Bool - _tt_face_check_patents( FT_Face face ) - { - FT_Stream stream = face->stream; - FT_UInt gindex; - FT_Error error; - FT_Bool result; - - FT_Service_TTGlyf service; - - - result = _tt_check_patents_in_table( face, TTAG_fpgm ); - if ( result ) - goto Exit; - - result = _tt_check_patents_in_table( face, TTAG_prep ); - if ( result ) - goto Exit; - - FT_FACE_FIND_SERVICE( face, service, TT_GLYF ); - if ( service == NULL ) - goto Exit; - - for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ ) - { - FT_ULong offset, num_ins, size; - FT_Int num_contours; - - - offset = service->get_location( face, gindex, &size ); - if ( size == 0 ) - continue; - - if ( FT_STREAM_SEEK( offset ) || - FT_READ_SHORT( num_contours ) ) - continue; - - if ( num_contours >= 0 ) /* simple glyph */ - { - if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) ) - continue; - } - else /* compound glyph */ - { - FT_Bool has_instr = 0; - - - if ( FT_STREAM_SKIP( 8 ) ) - continue; - - /* now read each component */ - for (;;) - { - FT_UInt flags, toskip; - - - if( FT_READ_USHORT( flags ) ) - break; - - toskip = 2 + 1 + 1; - - if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */ - toskip += 2; - - if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */ - toskip += 2; - else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */ - toskip += 4; - else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */ - toskip += 8; - - if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */ - has_instr = 1; - - if ( FT_STREAM_SKIP( toskip ) ) - goto NextGlyph; - - if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */ - break; - } - - if ( !has_instr ) - goto NextGlyph; - } - - if ( FT_READ_USHORT( num_ins ) ) - continue; - - result = _tt_check_patents_in_range( stream, num_ins ); - if ( result ) - goto Exit; - - NextGlyph: - ; - } - - Exit: - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Bool ) - FT_Face_CheckTrueTypePatents( FT_Face face ) - { - FT_Bool result = FALSE; - - - if ( face && FT_IS_SFNT( face ) ) - result = _tt_face_check_patents( face ); - - return result; - } - - - /* documentation is in freetype.h */ - - FT_EXPORT_DEF( FT_Bool ) - FT_Face_SetUnpatentedHinting( FT_Face face, - FT_Bool value ) - { - FT_Bool result = FALSE; - - -#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ - !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) - if ( face && FT_IS_SFNT( face ) ) - { - result = !face->internal->ignore_unpatented_hinter; - face->internal->ignore_unpatented_hinter = !value; - } -#else - FT_UNUSED( face ); - FT_UNUSED( value ); -#endif - - return result; - } - -/* END */ diff --git a/third_party/freetype/src/base/ftpfr.c b/third_party/freetype/src/base/ftpfr.c deleted file mode 100644 index 39f089e3e9dd4b0d76d118c52b334e6f54bb1db2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftpfr.c +++ /dev/null @@ -1,153 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftpfr.c */ -/* */ -/* FreeType API for accessing PFR-specific data (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_PFR_H - - - /* check the format */ - static FT_Service_PfrMetrics - ft_pfr_check( FT_Face face ) - { - FT_Service_PfrMetrics service = NULL; - - - if ( face ) - FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS ); - - return service; - } - - - /* documentation is in ftpfr.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_PFR_Metrics( FT_Face face, - FT_UInt *aoutline_resolution, - FT_UInt *ametrics_resolution, - FT_Fixed *ametrics_x_scale, - FT_Fixed *ametrics_y_scale ) - { - FT_Error error = FT_Err_Ok; - FT_Service_PfrMetrics service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - service = ft_pfr_check( face ); - if ( service ) - { - error = service->get_metrics( face, - aoutline_resolution, - ametrics_resolution, - ametrics_x_scale, - ametrics_y_scale ); - } - else - { - FT_Fixed x_scale, y_scale; - - - /* this is not a PFR font */ - if ( aoutline_resolution ) - *aoutline_resolution = face->units_per_EM; - - if ( ametrics_resolution ) - *ametrics_resolution = face->units_per_EM; - - x_scale = y_scale = 0x10000L; - if ( face->size ) - { - x_scale = face->size->metrics.x_scale; - y_scale = face->size->metrics.y_scale; - } - - if ( ametrics_x_scale ) - *ametrics_x_scale = x_scale; - - if ( ametrics_y_scale ) - *ametrics_y_scale = y_scale; - - error = FT_THROW( Unknown_File_Format ); - } - - return error; - } - - - /* documentation is in ftpfr.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_PFR_Kerning( FT_Face face, - FT_UInt left, - FT_UInt right, - FT_Vector *avector ) - { - FT_Error error; - FT_Service_PfrMetrics service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !avector ) - return FT_THROW( Invalid_Argument ); - - service = ft_pfr_check( face ); - if ( service ) - error = service->get_kerning( face, left, right, avector ); - else - error = FT_Get_Kerning( face, left, right, - FT_KERNING_UNSCALED, avector ); - - return error; - } - - - /* documentation is in ftpfr.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_PFR_Advance( FT_Face face, - FT_UInt gindex, - FT_Pos *aadvance ) - { - FT_Error error; - FT_Service_PfrMetrics service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !aadvance ) - return FT_THROW( Invalid_Argument ); - - service = ft_pfr_check( face ); - if ( service ) - error = service->get_advance( face, gindex, aadvance ); - else - /* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */ - error = FT_THROW( Invalid_Argument ); - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftpic.c b/third_party/freetype/src/base/ftpic.c deleted file mode 100644 index 6c4b1cd4e62d397638afad0b2f6598a2ceba463c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftpic.c +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftpic.c */ -/* */ -/* The FreeType position independent code services (body). */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "basepic.h" - -#ifdef FT_CONFIG_OPTION_PIC - - /* documentation is in ftpic.h */ - - FT_BASE_DEF( FT_Error ) - ft_pic_container_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error; - - - FT_MEM_SET( pic_container, 0, sizeof ( *pic_container ) ); - - error = ft_base_pic_init( library ); - if ( error ) - return error; - - return FT_Err_Ok; - } - - - /* Destroy the contents of the container. */ - FT_BASE_DEF( void ) - ft_pic_container_destroy( FT_Library library ) - { - ft_base_pic_free( library ); - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftrfork.c b/third_party/freetype/src/base/ftrfork.c deleted file mode 100644 index c30c76678e64fe7b89accb0070266bebb4d4a988..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftrfork.c +++ /dev/null @@ -1,880 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftrfork.c */ -/* */ -/* Embedded resource forks accessor (body). */ -/* */ -/* Copyright 2004-2015 by */ -/* Masatake YAMATO and Redhat K.K. */ -/* */ -/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */ -/* derived from ftobjs.c. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -/***************************************************************************/ -/* Development of the code in this file is support of */ -/* Information-technology Promotion Agency, Japan. */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_RFORK_H -#include "basepic.h" -#include "ftbase.h" - -#undef FT_COMPONENT -#define FT_COMPONENT trace_raccess - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** Resource fork directory access ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - FT_BASE_DEF( FT_Error ) - FT_Raccess_Get_HeaderInfo( FT_Library library, - FT_Stream stream, - FT_Long rfork_offset, - FT_Long *map_offset, - FT_Long *rdata_pos ) - { - FT_Error error; - unsigned char head[16], head2[16]; - FT_Long map_pos, rdata_len; - int allzeros, allmatch, i; - FT_Long type_list; - - FT_UNUSED( library ); - - - error = FT_Stream_Seek( stream, (FT_ULong)rfork_offset ); - if ( error ) - return error; - - error = FT_Stream_Read( stream, (FT_Byte *)head, 16 ); - if ( error ) - return error; - - /* ensure positive values */ - if ( head[0] >= 0x80 || head[4] >= 0x80 || head[8] >= 0x80 ) - return FT_THROW( Unknown_File_Format ); - - *rdata_pos = ( head[ 0] << 24 ) | - ( head[ 1] << 16 ) | - ( head[ 2] << 8 ) | - head[ 3]; - map_pos = ( head[ 4] << 24 ) | - ( head[ 5] << 16 ) | - ( head[ 6] << 8 ) | - head[ 7]; - rdata_len = ( head[ 8] << 24 ) | - ( head[ 9] << 16 ) | - ( head[10] << 8 ) | - head[11]; - - /* map_len = head[12] .. head[15] */ - - if ( *rdata_pos != map_pos - rdata_len || map_pos == 0 ) - return FT_THROW( Unknown_File_Format ); - - if ( FT_LONG_MAX - rfork_offset < *rdata_pos || - FT_LONG_MAX - rfork_offset < map_pos ) - return FT_THROW( Unknown_File_Format ); - - *rdata_pos += rfork_offset; - map_pos += rfork_offset; - - error = FT_Stream_Seek( stream, (FT_ULong)map_pos ); - if ( error ) - return error; - - head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */ - - error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 ); - if ( error ) - return error; - - allzeros = 1; - allmatch = 1; - for ( i = 0; i < 16; ++i ) - { - if ( head2[i] != 0 ) - allzeros = 0; - if ( head2[i] != head[i] ) - allmatch = 0; - } - if ( !allzeros && !allmatch ) - return FT_THROW( Unknown_File_Format ); - - /* If we have reached this point then it is probably a mac resource */ - /* file. Now, does it contain any interesting resources? */ - /* Skip handle to next resource map, the file resource number, and */ - /* attributes. */ - (void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */ - + 2 /* skip file resource number */ - + 2 ); /* skip attributes */ - - if ( FT_READ_USHORT( type_list ) ) - return error; - if ( type_list == -1 ) - return FT_THROW( Unknown_File_Format ); - - error = FT_Stream_Seek( stream, (FT_ULong)( map_pos + type_list ) ); - if ( error ) - return error; - - *map_offset = map_pos + type_list; - return FT_Err_Ok; - } - - - static int - ft_raccess_sort_ref_by_id( FT_RFork_Ref* a, - FT_RFork_Ref* b ) - { - if ( a->res_id < b->res_id ) - return -1; - else if ( a->res_id > b->res_id ) - return 1; - else - return 0; - } - - - FT_BASE_DEF( FT_Error ) - FT_Raccess_Get_DataOffsets( FT_Library library, - FT_Stream stream, - FT_Long map_offset, - FT_Long rdata_pos, - FT_Long tag, - FT_Bool sort_by_res_id, - FT_Long **offsets, - FT_Long *count ) - { - FT_Error error; - int i, j, cnt, subcnt; - FT_Long tag_internal, rpos; - FT_Memory memory = library->memory; - FT_Long temp; - FT_Long *offsets_internal = NULL; - FT_RFork_Ref *ref = NULL; - - - FT_TRACE3(( "\n" )); - error = FT_Stream_Seek( stream, (FT_ULong)map_offset ); - if ( error ) - return error; - - if ( FT_READ_USHORT( cnt ) ) - return error; - cnt++; - - for ( i = 0; i < cnt; ++i ) - { - if ( FT_READ_LONG( tag_internal ) || - FT_READ_USHORT( subcnt ) || - FT_READ_USHORT( rpos ) ) - return error; - - FT_TRACE2(( "Resource tags: %c%c%c%c\n", - (char)( 0xFF & ( tag_internal >> 24 ) ), - (char)( 0xFF & ( tag_internal >> 16 ) ), - (char)( 0xFF & ( tag_internal >> 8 ) ), - (char)( 0xFF & ( tag_internal >> 0 ) ) )); - FT_TRACE3(( " : subcount=%d, suboffset=0x%04x\n", - subcnt, rpos )); - - if ( tag_internal == tag ) - { - *count = subcnt + 1; - rpos += map_offset; - - error = FT_Stream_Seek( stream, (FT_ULong)rpos ); - if ( error ) - return error; - - if ( FT_NEW_ARRAY( ref, *count ) ) - return error; - - for ( j = 0; j < *count; ++j ) - { - if ( FT_READ_USHORT( ref[j].res_id ) ) - goto Exit; - if ( FT_STREAM_SKIP( 2 ) ) /* resource name */ - goto Exit; - if ( FT_READ_LONG( temp ) ) - goto Exit; - if ( FT_STREAM_SKIP( 4 ) ) /* mbz */ - goto Exit; - - ref[j].offset = temp & 0xFFFFFFL; - FT_TRACE3(( " [%d]:" - " resource_id=0x%04x, offset=0x%08x\n", - j, ref[j].res_id, ref[j].offset )); - } - - if (sort_by_res_id) - { - ft_qsort( ref, (size_t)*count, sizeof ( FT_RFork_Ref ), - ( int(*)(const void*, const void*) ) - ft_raccess_sort_ref_by_id ); - - FT_TRACE3(( " -- sort resources by their ids --\n" )); - for ( j = 0; j < *count; ++ j ) { - FT_TRACE3(( " [%d]:" - " resource_id=0x%04x, offset=0x%08x\n", - j, ref[j].res_id, ref[j].offset )); - } - } - - if ( FT_NEW_ARRAY( offsets_internal, *count ) ) - goto Exit; - - /* XXX: duplicated reference ID, - * gap between reference IDs are acceptable? - * further investigation on Apple implementation is needed. - */ - for ( j = 0; j < *count; ++j ) - offsets_internal[j] = rdata_pos + ref[j].offset; - - *offsets = offsets_internal; - error = FT_Err_Ok; - - Exit: - FT_FREE( ref ); - return error; - } - } - - return FT_THROW( Cannot_Open_Resource ); - } - - -#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** Guessing functions ****/ - /**** ****/ - /**** When you add a new guessing function, ****/ - /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - static FT_Error - raccess_guess_apple_double( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_apple_single( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_darwin_ufs_export( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_darwin_newvfs( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_darwin_hfsplus( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_vfat( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_linux_cap( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_linux_double( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_linux_netatalk( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ); - - - CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table, - ft_raccess_guess_rec) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk) - CONST_FT_RFORK_RULE_ARRAY_END - - - /*************************************************************************/ - /**** ****/ - /**** Helper functions ****/ - /**** ****/ - /*************************************************************************/ - - static FT_Error - raccess_guess_apple_generic( FT_Library library, - FT_Stream stream, - char *base_file_name, - FT_Int32 magic, - FT_Long *result_offset ); - - static FT_Error - raccess_guess_linux_double_from_file_name( FT_Library library, - char * file_name, - FT_Long *result_offset ); - - static char * - raccess_make_file_name( FT_Memory memory, - const char *original_name, - const char *insertion ); - - FT_BASE_DEF( void ) - FT_Raccess_Guess( FT_Library library, - FT_Stream stream, - char* base_name, - char **new_names, - FT_Long *offsets, - FT_Error *errors ) - { - FT_Int i; - - - for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) - { - new_names[i] = NULL; - if ( NULL != stream ) - errors[i] = FT_Stream_Seek( stream, 0 ); - else - errors[i] = FT_Err_Ok; - - if ( errors[i] ) - continue ; - - errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library, - stream, base_name, - &(new_names[i]), - &(offsets[i]) ); - } - - return; - } - - -#ifndef FT_MACINTOSH - static FT_RFork_Rule - raccess_get_rule_type_from_rule_index( FT_Library library, - FT_UInt rule_index ) - { - FT_UNUSED( library ); - - if ( rule_index >= FT_RACCESS_N_RULES ) - return FT_RFork_Rule_invalid; - - return FT_RACCESS_GUESS_TABLE_GET[rule_index].type; - } - - - /* - * For this function, refer ftbase.h. - */ - FT_LOCAL_DEF( FT_Bool ) - ft_raccess_rule_by_darwin_vfs( FT_Library library, - FT_UInt rule_index ) - { - switch( raccess_get_rule_type_from_rule_index( library, rule_index ) ) - { - case FT_RFork_Rule_darwin_newvfs: - case FT_RFork_Rule_darwin_hfsplus: - return TRUE; - - default: - return FALSE; - } - } -#endif - - - static FT_Error - raccess_guess_apple_double( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - FT_Int32 magic = ( 0x00 << 24 ) | - ( 0x05 << 16 ) | - ( 0x16 << 8 ) | - 0x07; - - - *result_file_name = NULL; - if ( NULL == stream ) - return FT_THROW( Cannot_Open_Stream ); - - return raccess_guess_apple_generic( library, stream, base_file_name, - magic, result_offset ); - } - - - static FT_Error - raccess_guess_apple_single( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - FT_Int32 magic = ( 0x00 << 24 ) | - ( 0x05 << 16 ) | - ( 0x16 << 8 ) | - 0x00; - - - *result_file_name = NULL; - if ( NULL == stream ) - return FT_THROW( Cannot_Open_Stream ); - - return raccess_guess_apple_generic( library, stream, base_file_name, - magic, result_offset ); - } - - - static FT_Error - raccess_guess_darwin_ufs_export( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - char* newpath; - FT_Error error; - FT_Memory memory; - - FT_UNUSED( stream ); - - - memory = library->memory; - newpath = raccess_make_file_name( memory, base_file_name, "._" ); - if ( !newpath ) - return FT_THROW( Out_Of_Memory ); - - error = raccess_guess_linux_double_from_file_name( library, newpath, - result_offset ); - if ( !error ) - *result_file_name = newpath; - else - FT_FREE( newpath ); - - return error; - } - - - static FT_Error - raccess_guess_darwin_hfsplus( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - /* - Only meaningful on systems with hfs+ drivers (or Macs). - */ - FT_Error error; - char* newpath = NULL; - FT_Memory memory; - FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name ); - - FT_UNUSED( stream ); - - - memory = library->memory; - - if ( base_file_len + 6 > FT_INT_MAX ) - return FT_THROW( Array_Too_Large ); - - if ( FT_ALLOC( newpath, base_file_len + 6 ) ) - return error; - - FT_MEM_COPY( newpath, base_file_name, base_file_len ); - FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 ); - - *result_file_name = newpath; - *result_offset = 0; - - return FT_Err_Ok; - } - - - static FT_Error - raccess_guess_darwin_newvfs( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - /* - Only meaningful on systems with Mac OS X (> 10.1). - */ - FT_Error error; - char* newpath = NULL; - FT_Memory memory; - FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name ); - - FT_UNUSED( stream ); - - - memory = library->memory; - - if ( base_file_len + 18 > FT_INT_MAX ) - return FT_THROW( Array_Too_Large ); - - if ( FT_ALLOC( newpath, base_file_len + 18 ) ) - return error; - - FT_MEM_COPY( newpath, base_file_name, base_file_len ); - FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 ); - - *result_file_name = newpath; - *result_offset = 0; - - return FT_Err_Ok; - } - - - static FT_Error - raccess_guess_vfat( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - char* newpath; - FT_Memory memory; - - FT_UNUSED( stream ); - - - memory = library->memory; - - newpath = raccess_make_file_name( memory, base_file_name, - "resource.frk/" ); - if ( !newpath ) - return FT_THROW( Out_Of_Memory ); - - *result_file_name = newpath; - *result_offset = 0; - - return FT_Err_Ok; - } - - - static FT_Error - raccess_guess_linux_cap( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - char* newpath; - FT_Memory memory; - - FT_UNUSED( stream ); - - - memory = library->memory; - - newpath = raccess_make_file_name( memory, base_file_name, ".resource/" ); - if ( !newpath ) - return FT_THROW( Out_Of_Memory ); - - *result_file_name = newpath; - *result_offset = 0; - - return FT_Err_Ok; - } - - - static FT_Error - raccess_guess_linux_double( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - char* newpath; - FT_Error error; - FT_Memory memory; - - FT_UNUSED( stream ); - - - memory = library->memory; - - newpath = raccess_make_file_name( memory, base_file_name, "%" ); - if ( !newpath ) - return FT_THROW( Out_Of_Memory ); - - error = raccess_guess_linux_double_from_file_name( library, newpath, - result_offset ); - if ( !error ) - *result_file_name = newpath; - else - FT_FREE( newpath ); - - return error; - } - - - static FT_Error - raccess_guess_linux_netatalk( FT_Library library, - FT_Stream stream, - char *base_file_name, - char **result_file_name, - FT_Long *result_offset ) - { - char* newpath; - FT_Error error; - FT_Memory memory; - - FT_UNUSED( stream ); - - - memory = library->memory; - - newpath = raccess_make_file_name( memory, base_file_name, - ".AppleDouble/" ); - if ( !newpath ) - return FT_THROW( Out_Of_Memory ); - - error = raccess_guess_linux_double_from_file_name( library, newpath, - result_offset ); - if ( !error ) - *result_file_name = newpath; - else - FT_FREE( newpath ); - - return error; - } - - - static FT_Error - raccess_guess_apple_generic( FT_Library library, - FT_Stream stream, - char *base_file_name, - FT_Int32 magic, - FT_Long *result_offset ) - { - FT_Int32 magic_from_stream; - FT_Error error; - FT_Int32 version_number = 0; - FT_UShort n_of_entries; - - int i; - FT_Int32 entry_id, entry_offset, entry_length = 0; - - const FT_Int32 resource_fork_entry_id = 0x2; - - FT_UNUSED( library ); - FT_UNUSED( base_file_name ); - FT_UNUSED( version_number ); - FT_UNUSED( entry_length ); - - - if ( FT_READ_LONG( magic_from_stream ) ) - return error; - if ( magic_from_stream != magic ) - return FT_THROW( Unknown_File_Format ); - - if ( FT_READ_LONG( version_number ) ) - return error; - - /* filler */ - error = FT_Stream_Skip( stream, 16 ); - if ( error ) - return error; - - if ( FT_READ_USHORT( n_of_entries ) ) - return error; - if ( n_of_entries == 0 ) - return FT_THROW( Unknown_File_Format ); - - for ( i = 0; i < n_of_entries; i++ ) - { - if ( FT_READ_LONG( entry_id ) ) - return error; - if ( entry_id == resource_fork_entry_id ) - { - if ( FT_READ_LONG( entry_offset ) || - FT_READ_LONG( entry_length ) ) - continue; - *result_offset = entry_offset; - - return FT_Err_Ok; - } - else - { - error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */ - if ( error ) - return error; - } - } - - return FT_THROW( Unknown_File_Format ); - } - - - static FT_Error - raccess_guess_linux_double_from_file_name( FT_Library library, - char *file_name, - FT_Long *result_offset ) - { - FT_Open_Args args2; - FT_Stream stream2; - char * nouse = NULL; - FT_Error error; - - - args2.flags = FT_OPEN_PATHNAME; - args2.pathname = file_name; - error = FT_Stream_New( library, &args2, &stream2 ); - if ( error ) - return error; - - error = raccess_guess_apple_double( library, stream2, file_name, - &nouse, result_offset ); - - FT_Stream_Free( stream2, 0 ); - - return error; - } - - - static char* - raccess_make_file_name( FT_Memory memory, - const char *original_name, - const char *insertion ) - { - char* new_name = NULL; - const char* tmp; - const char* slash; - size_t new_length; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); - - - new_length = ft_strlen( original_name ) + ft_strlen( insertion ); - if ( FT_ALLOC( new_name, new_length + 1 ) ) - return NULL; - - tmp = ft_strrchr( original_name, '/' ); - if ( tmp ) - { - ft_strncpy( new_name, - original_name, - (size_t)( tmp - original_name + 1 ) ); - new_name[tmp - original_name + 1] = '\0'; - slash = tmp + 1; - } - else - { - slash = original_name; - new_name[0] = '\0'; - } - - ft_strcat( new_name, insertion ); - ft_strcat( new_name, slash ); - - return new_name; - } - - -#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ - - - /*************************************************************************/ - /* Dummy function; just sets errors */ - /*************************************************************************/ - - FT_BASE_DEF( void ) - FT_Raccess_Guess( FT_Library library, - FT_Stream stream, - char *base_name, - char **new_names, - FT_Long *offsets, - FT_Error *errors ) - { - FT_Int i; - - FT_UNUSED( library ); - FT_UNUSED( stream ); - FT_UNUSED( base_name ); - - - for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) - { - new_names[i] = NULL; - offsets[i] = 0; - errors[i] = FT_ERR( Unimplemented_Feature ); - } - } - - -#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftsnames.c b/third_party/freetype/src/base/ftsnames.c deleted file mode 100644 index 80304e5c859b4b3c2290b2aacfce23c0a0fc9bcf..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftsnames.c +++ /dev/null @@ -1,94 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsnames.c */ -/* */ -/* Simple interface to access SFNT name tables (which are used */ -/* to hold font names, copyright info, notices, etc.) (body). */ -/* */ -/* This is _not_ used to retrieve glyph names! */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_SFNT_NAMES_H -#include FT_INTERNAL_TRUETYPE_TYPES_H -#include FT_INTERNAL_STREAM_H - - -#ifdef TT_CONFIG_OPTION_SFNT_NAMES - - - /* documentation is in ftsnames.h */ - - FT_EXPORT_DEF( FT_UInt ) - FT_Get_Sfnt_Name_Count( FT_Face face ) - { - return ( face && FT_IS_SFNT( face ) ) ? ((TT_Face)face)->num_names : 0; - } - - - /* documentation is in ftsnames.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_Sfnt_Name( FT_Face face, - FT_UInt idx, - FT_SfntName *aname ) - { - FT_Error error = FT_ERR( Invalid_Argument ); - - - if ( aname && face && FT_IS_SFNT( face ) ) - { - TT_Face ttface = (TT_Face)face; - - - if ( idx < (FT_UInt)ttface->num_names ) - { - TT_NameEntryRec* entry = ttface->name_table.names + idx; - - - /* load name on demand */ - if ( entry->stringLength > 0 && entry->string == NULL ) - { - FT_Memory memory = face->memory; - FT_Stream stream = face->stream; - - - if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || - FT_STREAM_SEEK( entry->stringOffset ) || - FT_STREAM_READ( entry->string, entry->stringLength ) ) - { - FT_FREE( entry->string ); - entry->stringLength = 0; - } - } - - aname->platform_id = entry->platformID; - aname->encoding_id = entry->encodingID; - aname->language_id = entry->languageID; - aname->name_id = entry->nameID; - aname->string = (FT_Byte*)entry->string; - aname->string_len = entry->stringLength; - - error = FT_Err_Ok; - } - } - - return error; - } - - -#endif /* TT_CONFIG_OPTION_SFNT_NAMES */ - - -/* END */ diff --git a/third_party/freetype/src/base/ftstream.c b/third_party/freetype/src/base/ftstream.c deleted file mode 100644 index b68f3f82d27cbbcc376dcf9beb9291dbac830268..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftstream.c +++ /dev/null @@ -1,860 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftstream.c */ -/* */ -/* I/O stream support (body). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_DEBUG_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_stream - - - FT_BASE_DEF( void ) - FT_Stream_OpenMemory( FT_Stream stream, - const FT_Byte* base, - FT_ULong size ) - { - stream->base = (FT_Byte*) base; - stream->size = size; - stream->pos = 0; - stream->cursor = NULL; - stream->read = NULL; - stream->close = NULL; - } - - - FT_BASE_DEF( void ) - FT_Stream_Close( FT_Stream stream ) - { - if ( stream && stream->close ) - stream->close( stream ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_Seek( FT_Stream stream, - FT_ULong pos ) - { - FT_Error error = FT_Err_Ok; - - - if ( stream->read ) - { - if ( stream->read( stream, pos, 0, 0 ) ) - { - FT_ERROR(( "FT_Stream_Seek:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - pos, stream->size )); - - error = FT_THROW( Invalid_Stream_Operation ); - } - } - /* note that seeking to the first position after the file is valid */ - else if ( pos > stream->size ) - { - FT_ERROR(( "FT_Stream_Seek:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - pos, stream->size )); - - error = FT_THROW( Invalid_Stream_Operation ); - } - - if ( !error ) - stream->pos = pos; - - return error; - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_Skip( FT_Stream stream, - FT_Long distance ) - { - if ( distance < 0 ) - return FT_THROW( Invalid_Stream_Operation ); - - return FT_Stream_Seek( stream, stream->pos + (FT_ULong)distance ); - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_Pos( FT_Stream stream ) - { - return stream->pos; - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_Read( FT_Stream stream, - FT_Byte* buffer, - FT_ULong count ) - { - return FT_Stream_ReadAt( stream, stream->pos, buffer, count ); - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_ReadAt( FT_Stream stream, - FT_ULong pos, - FT_Byte* buffer, - FT_ULong count ) - { - FT_Error error = FT_Err_Ok; - FT_ULong read_bytes; - - - if ( pos >= stream->size ) - { - FT_ERROR(( "FT_Stream_ReadAt:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - pos, stream->size )); - - return FT_THROW( Invalid_Stream_Operation ); - } - - if ( stream->read ) - read_bytes = stream->read( stream, pos, buffer, count ); - else - { - read_bytes = stream->size - pos; - if ( read_bytes > count ) - read_bytes = count; - - FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); - } - - stream->pos = pos + read_bytes; - - if ( read_bytes < count ) - { - FT_ERROR(( "FT_Stream_ReadAt:" - " invalid read; expected %lu bytes, got %lu\n", - count, read_bytes )); - - error = FT_THROW( Invalid_Stream_Operation ); - } - - return error; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_TryRead( FT_Stream stream, - FT_Byte* buffer, - FT_ULong count ) - { - FT_ULong read_bytes = 0; - - - if ( stream->pos >= stream->size ) - goto Exit; - - if ( stream->read ) - read_bytes = stream->read( stream, stream->pos, buffer, count ); - else - { - read_bytes = stream->size - stream->pos; - if ( read_bytes > count ) - read_bytes = count; - - FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes ); - } - - stream->pos += read_bytes; - - Exit: - return read_bytes; - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_ExtractFrame( FT_Stream stream, - FT_ULong count, - FT_Byte** pbytes ) - { - FT_Error error; - - - error = FT_Stream_EnterFrame( stream, count ); - if ( !error ) - { - *pbytes = (FT_Byte*)stream->cursor; - - /* equivalent to FT_Stream_ExitFrame(), with no memory block release */ - stream->cursor = NULL; - stream->limit = NULL; - } - - return error; - } - - - FT_BASE_DEF( void ) - FT_Stream_ReleaseFrame( FT_Stream stream, - FT_Byte** pbytes ) - { - if ( stream && stream->read ) - { - FT_Memory memory = stream->memory; - -#ifdef FT_DEBUG_MEMORY - ft_mem_free( memory, *pbytes ); - *pbytes = NULL; -#else - FT_FREE( *pbytes ); -#endif - } - *pbytes = NULL; - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_EnterFrame( FT_Stream stream, - FT_ULong count ) - { - FT_Error error = FT_Err_Ok; - FT_ULong read_bytes; - - - /* check for nested frame access */ - FT_ASSERT( stream && stream->cursor == 0 ); - - if ( stream->read ) - { - /* allocate the frame in memory */ - FT_Memory memory = stream->memory; - - - /* simple sanity check */ - if ( count > stream->size ) - { - FT_ERROR(( "FT_Stream_EnterFrame:" - " frame size (%lu) larger than stream size (%lu)\n", - count, stream->size )); - - error = FT_THROW( Invalid_Stream_Operation ); - goto Exit; - } - -#ifdef FT_DEBUG_MEMORY - /* assume _ft_debug_file and _ft_debug_lineno are already set */ - stream->base = (unsigned char*)ft_mem_qalloc( memory, - (FT_Long)count, - &error ); - if ( error ) - goto Exit; -#else - if ( FT_QALLOC( stream->base, count ) ) - goto Exit; -#endif - /* read it */ - read_bytes = stream->read( stream, stream->pos, - stream->base, count ); - if ( read_bytes < count ) - { - FT_ERROR(( "FT_Stream_EnterFrame:" - " invalid read; expected %lu bytes, got %lu\n", - count, read_bytes )); - - FT_FREE( stream->base ); - error = FT_THROW( Invalid_Stream_Operation ); - } - stream->cursor = stream->base; - stream->limit = stream->cursor + count; - stream->pos += read_bytes; - } - else - { - /* check current and new position */ - if ( stream->pos >= stream->size || - stream->size - stream->pos < count ) - { - FT_ERROR(( "FT_Stream_EnterFrame:" - " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n", - stream->pos, count, stream->size )); - - error = FT_THROW( Invalid_Stream_Operation ); - goto Exit; - } - - /* set cursor */ - stream->cursor = stream->base + stream->pos; - stream->limit = stream->cursor + count; - stream->pos += count; - } - - Exit: - return error; - } - - - FT_BASE_DEF( void ) - FT_Stream_ExitFrame( FT_Stream stream ) - { - /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */ - /* that it is possible to access a frame of length 0 in */ - /* some weird fonts (usually, when accessing an array of */ - /* 0 records, like in some strange kern tables). */ - /* */ - /* In this case, the loader code handles the 0-length table */ - /* gracefully; however, stream.cursor is really set to 0 by the */ - /* FT_Stream_EnterFrame() call, and this is not an error. */ - /* */ - FT_ASSERT( stream ); - - if ( stream->read ) - { - FT_Memory memory = stream->memory; - -#ifdef FT_DEBUG_MEMORY - ft_mem_free( memory, stream->base ); - stream->base = NULL; -#else - FT_FREE( stream->base ); -#endif - } - stream->cursor = NULL; - stream->limit = NULL; - } - - - FT_BASE_DEF( FT_Char ) - FT_Stream_GetChar( FT_Stream stream ) - { - FT_Char result; - - - FT_ASSERT( stream && stream->cursor ); - - result = 0; - if ( stream->cursor < stream->limit ) - result = (FT_Char)*stream->cursor++; - - return result; - } - - - FT_BASE_DEF( FT_UShort ) - FT_Stream_GetUShort( FT_Stream stream ) - { - FT_Byte* p; - FT_UShort result; - - - FT_ASSERT( stream && stream->cursor ); - - result = 0; - p = stream->cursor; - if ( p + 1 < stream->limit ) - result = FT_NEXT_USHORT( p ); - stream->cursor = p; - - return result; - } - - - FT_BASE_DEF( FT_UShort ) - FT_Stream_GetUShortLE( FT_Stream stream ) - { - FT_Byte* p; - FT_UShort result; - - - FT_ASSERT( stream && stream->cursor ); - - result = 0; - p = stream->cursor; - if ( p + 1 < stream->limit ) - result = FT_NEXT_USHORT_LE( p ); - stream->cursor = p; - - return result; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_GetUOffset( FT_Stream stream ) - { - FT_Byte* p; - FT_ULong result; - - - FT_ASSERT( stream && stream->cursor ); - - result = 0; - p = stream->cursor; - if ( p + 2 < stream->limit ) - result = FT_NEXT_UOFF3( p ); - stream->cursor = p; - return result; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_GetULong( FT_Stream stream ) - { - FT_Byte* p; - FT_ULong result; - - - FT_ASSERT( stream && stream->cursor ); - - result = 0; - p = stream->cursor; - if ( p + 3 < stream->limit ) - result = FT_NEXT_ULONG( p ); - stream->cursor = p; - return result; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_GetULongLE( FT_Stream stream ) - { - FT_Byte* p; - FT_ULong result; - - - FT_ASSERT( stream && stream->cursor ); - - result = 0; - p = stream->cursor; - if ( p + 3 < stream->limit ) - result = FT_NEXT_ULONG_LE( p ); - stream->cursor = p; - return result; - } - - - FT_BASE_DEF( FT_Char ) - FT_Stream_ReadChar( FT_Stream stream, - FT_Error* error ) - { - FT_Byte result = 0; - - - FT_ASSERT( stream ); - - *error = FT_Err_Ok; - - if ( stream->read ) - { - if ( stream->read( stream, stream->pos, &result, 1L ) != 1L ) - goto Fail; - } - else - { - if ( stream->pos < stream->size ) - result = stream->base[stream->pos]; - else - goto Fail; - } - stream->pos++; - - return (FT_Char)result; - - Fail: - *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadChar:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - stream->pos, stream->size )); - - return 0; - } - - - FT_BASE_DEF( FT_UShort ) - FT_Stream_ReadUShort( FT_Stream stream, - FT_Error* error ) - { - FT_Byte reads[2]; - FT_Byte* p = 0; - FT_UShort result = 0; - - - FT_ASSERT( stream ); - - *error = FT_Err_Ok; - - if ( stream->pos + 1 < stream->size ) - { - if ( stream->read ) - { - if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) - goto Fail; - - p = reads; - } - else - p = stream->base + stream->pos; - - if ( p ) - result = FT_NEXT_USHORT( p ); - } - else - goto Fail; - - stream->pos += 2; - - return result; - - Fail: - *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadUShort:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - stream->pos, stream->size )); - - return 0; - } - - - FT_BASE_DEF( FT_UShort ) - FT_Stream_ReadUShortLE( FT_Stream stream, - FT_Error* error ) - { - FT_Byte reads[2]; - FT_Byte* p = 0; - FT_UShort result = 0; - - - FT_ASSERT( stream ); - - *error = FT_Err_Ok; - - if ( stream->pos + 1 < stream->size ) - { - if ( stream->read ) - { - if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) - goto Fail; - - p = reads; - } - else - p = stream->base + stream->pos; - - if ( p ) - result = FT_NEXT_USHORT_LE( p ); - } - else - goto Fail; - - stream->pos += 2; - - return result; - - Fail: - *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadUShortLE:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - stream->pos, stream->size )); - - return 0; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_ReadUOffset( FT_Stream stream, - FT_Error* error ) - { - FT_Byte reads[3]; - FT_Byte* p = 0; - FT_ULong result = 0; - - - FT_ASSERT( stream ); - - *error = FT_Err_Ok; - - if ( stream->pos + 2 < stream->size ) - { - if ( stream->read ) - { - if (stream->read( stream, stream->pos, reads, 3L ) != 3L ) - goto Fail; - - p = reads; - } - else - p = stream->base + stream->pos; - - if ( p ) - result = FT_NEXT_UOFF3( p ); - } - else - goto Fail; - - stream->pos += 3; - - return result; - - Fail: - *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadUOffset:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - stream->pos, stream->size )); - - return 0; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_ReadULong( FT_Stream stream, - FT_Error* error ) - { - FT_Byte reads[4]; - FT_Byte* p = 0; - FT_ULong result = 0; - - - FT_ASSERT( stream ); - - *error = FT_Err_Ok; - - if ( stream->pos + 3 < stream->size ) - { - if ( stream->read ) - { - if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) - goto Fail; - - p = reads; - } - else - p = stream->base + stream->pos; - - if ( p ) - result = FT_NEXT_ULONG( p ); - } - else - goto Fail; - - stream->pos += 4; - - return result; - - Fail: - *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadULong:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - stream->pos, stream->size )); - - return 0; - } - - - FT_BASE_DEF( FT_ULong ) - FT_Stream_ReadULongLE( FT_Stream stream, - FT_Error* error ) - { - FT_Byte reads[4]; - FT_Byte* p = 0; - FT_ULong result = 0; - - - FT_ASSERT( stream ); - - *error = FT_Err_Ok; - - if ( stream->pos + 3 < stream->size ) - { - if ( stream->read ) - { - if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) - goto Fail; - - p = reads; - } - else - p = stream->base + stream->pos; - - if ( p ) - result = FT_NEXT_ULONG_LE( p ); - } - else - goto Fail; - - stream->pos += 4; - - return result; - - Fail: - *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadULongLE:" - " invalid i/o; pos = 0x%lx, size = 0x%lx\n", - stream->pos, stream->size )); - - return 0; - } - - - FT_BASE_DEF( FT_Error ) - FT_Stream_ReadFields( FT_Stream stream, - const FT_Frame_Field* fields, - void* structure ) - { - FT_Error error; - FT_Bool frame_accessed = 0; - FT_Byte* cursor; - - - if ( !fields ) - return FT_THROW( Invalid_Argument ); - - if ( !stream ) - return FT_THROW( Invalid_Stream_Handle ); - - cursor = stream->cursor; - - error = FT_Err_Ok; - do - { - FT_ULong value; - FT_Int sign_shift; - FT_Byte* p; - - - switch ( fields->value ) - { - case ft_frame_start: /* access a new frame */ - error = FT_Stream_EnterFrame( stream, fields->offset ); - if ( error ) - goto Exit; - - frame_accessed = 1; - cursor = stream->cursor; - fields++; - continue; /* loop! */ - - case ft_frame_bytes: /* read a byte sequence */ - case ft_frame_skip: /* skip some bytes */ - { - FT_UInt len = fields->size; - - - if ( cursor + len > stream->limit ) - { - error = FT_THROW( Invalid_Stream_Operation ); - goto Exit; - } - - if ( fields->value == ft_frame_bytes ) - { - p = (FT_Byte*)structure + fields->offset; - FT_MEM_COPY( p, cursor, len ); - } - cursor += len; - fields++; - continue; - } - - case ft_frame_byte: - case ft_frame_schar: /* read a single byte */ - value = FT_NEXT_BYTE( cursor ); - sign_shift = 24; - break; - - case ft_frame_short_be: - case ft_frame_ushort_be: /* read a 2-byte big-endian short */ - value = FT_NEXT_USHORT( cursor) ; - sign_shift = 16; - break; - - case ft_frame_short_le: - case ft_frame_ushort_le: /* read a 2-byte little-endian short */ - value = FT_NEXT_USHORT_LE( cursor ); - sign_shift = 16; - break; - - case ft_frame_long_be: - case ft_frame_ulong_be: /* read a 4-byte big-endian long */ - value = FT_NEXT_ULONG( cursor ); - sign_shift = 0; - break; - - case ft_frame_long_le: - case ft_frame_ulong_le: /* read a 4-byte little-endian long */ - value = FT_NEXT_ULONG_LE( cursor ); - sign_shift = 0; - break; - - case ft_frame_off3_be: - case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ - value = FT_NEXT_UOFF3( cursor ); - sign_shift = 8; - break; - - case ft_frame_off3_le: - case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ - value = FT_NEXT_UOFF3_LE( cursor ); - sign_shift = 8; - break; - - default: - /* otherwise, exit the loop */ - stream->cursor = cursor; - goto Exit; - } - - /* now, compute the signed value is necessary */ - if ( fields->value & FT_FRAME_OP_SIGNED ) - value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift ); - - /* finally, store the value in the object */ - - p = (FT_Byte*)structure + fields->offset; - switch ( fields->size ) - { - case ( 8 / FT_CHAR_BIT ): - *(FT_Byte*)p = (FT_Byte)value; - break; - - case ( 16 / FT_CHAR_BIT ): - *(FT_UShort*)p = (FT_UShort)value; - break; - - case ( 32 / FT_CHAR_BIT ): - *(FT_UInt32*)p = (FT_UInt32)value; - break; - - default: /* for 64-bit systems */ - *(FT_ULong*)p = (FT_ULong)value; - } - - /* go to next field */ - fields++; - } - while ( 1 ); - - Exit: - /* close the frame if it was opened by this read */ - if ( frame_accessed ) - FT_Stream_ExitFrame( stream ); - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftstroke.c b/third_party/freetype/src/base/ftstroke.c deleted file mode 100644 index fecb3cc25c0e14f25db68c41737aea47420a0f20..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftstroke.c +++ /dev/null @@ -1,2468 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftstroke.c */ -/* */ -/* FreeType path stroker (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_STROKER_H -#include FT_TRIGONOMETRY_H -#include FT_OUTLINE_H -#include FT_INTERNAL_MEMORY_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H - -#include "basepic.h" - - - /* declare an extern to access `ft_outline_glyph_class' globally */ - /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */ - /* macro to access it when FT_CONFIG_OPTION_PIC is defined */ -#ifndef FT_CONFIG_OPTION_PIC - FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class; -#endif - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_StrokerBorder ) - FT_Outline_GetInsideBorder( FT_Outline* outline ) - { - FT_Orientation o = FT_Outline_Get_Orientation( outline ); - - - return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT - : FT_STROKER_BORDER_LEFT; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_StrokerBorder ) - FT_Outline_GetOutsideBorder( FT_Outline* outline ) - { - FT_Orientation o = FT_Outline_Get_Orientation( outline ); - - - return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT - : FT_STROKER_BORDER_RIGHT; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** BEZIER COMPUTATIONS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 ) -#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 ) - -#define FT_EPSILON 2 - -#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON ) - - - static FT_Pos - ft_pos_abs( FT_Pos x ) - { - return x >= 0 ? x : -x; - } - - - static void - ft_conic_split( FT_Vector* base ) - { - FT_Pos a, b; - - - base[4].x = base[2].x; - b = base[1].x; - a = base[3].x = ( base[2].x + b ) / 2; - b = base[1].x = ( base[0].x + b ) / 2; - base[2].x = ( a + b ) / 2; - - base[4].y = base[2].y; - b = base[1].y; - a = base[3].y = ( base[2].y + b ) / 2; - b = base[1].y = ( base[0].y + b ) / 2; - base[2].y = ( a + b ) / 2; - } - - - static FT_Bool - ft_conic_is_small_enough( FT_Vector* base, - FT_Angle *angle_in, - FT_Angle *angle_out ) - { - FT_Vector d1, d2; - FT_Angle theta; - FT_Int close1, close2; - - - d1.x = base[1].x - base[2].x; - d1.y = base[1].y - base[2].y; - d2.x = base[0].x - base[1].x; - d2.y = base[0].y - base[1].y; - - close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); - close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); - - if ( close1 ) - { - if ( close2 ) - { - /* basically a point; */ - /* do nothing to retain original direction */ - } - else - { - *angle_in = - *angle_out = FT_Atan2( d2.x, d2.y ); - } - } - else /* !close1 */ - { - if ( close2 ) - { - *angle_in = - *angle_out = FT_Atan2( d1.x, d1.y ); - } - else - { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_out = FT_Atan2( d2.x, d2.y ); - } - } - - theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) ); - - return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD ); - } - - - static void - ft_cubic_split( FT_Vector* base ) - { - FT_Pos a, b, c, d; - - - base[6].x = base[3].x; - c = base[1].x; - d = base[2].x; - base[1].x = a = ( base[0].x + c ) / 2; - base[5].x = b = ( base[3].x + d ) / 2; - c = ( c + d ) / 2; - base[2].x = a = ( a + c ) / 2; - base[4].x = b = ( b + c ) / 2; - base[3].x = ( a + b ) / 2; - - base[6].y = base[3].y; - c = base[1].y; - d = base[2].y; - base[1].y = a = ( base[0].y + c ) / 2; - base[5].y = b = ( base[3].y + d ) / 2; - c = ( c + d ) / 2; - base[2].y = a = ( a + c ) / 2; - base[4].y = b = ( b + c ) / 2; - base[3].y = ( a + b ) / 2; - } - - - /* Return the average of `angle1' and `angle2'. */ - /* This gives correct result even if `angle1' and `angle2' */ - /* have opposite signs. */ - static FT_Angle - ft_angle_mean( FT_Angle angle1, - FT_Angle angle2 ) - { - return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2; - } - - - static FT_Bool - ft_cubic_is_small_enough( FT_Vector* base, - FT_Angle *angle_in, - FT_Angle *angle_mid, - FT_Angle *angle_out ) - { - FT_Vector d1, d2, d3; - FT_Angle theta1, theta2; - FT_Int close1, close2, close3; - - - d1.x = base[2].x - base[3].x; - d1.y = base[2].y - base[3].y; - d2.x = base[1].x - base[2].x; - d2.y = base[1].y - base[2].y; - d3.x = base[0].x - base[1].x; - d3.y = base[0].y - base[1].y; - - close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); - close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); - close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y ); - - if ( close1 ) - { - if ( close2 ) - { - if ( close3 ) - { - /* basically a point; */ - /* do nothing to retain original direction */ - } - else /* !close3 */ - { - *angle_in = - *angle_mid = - *angle_out = FT_Atan2( d3.x, d3.y ); - } - } - else /* !close2 */ - { - if ( close3 ) - { - *angle_in = - *angle_mid = - *angle_out = FT_Atan2( d2.x, d2.y ); - } - else /* !close3 */ - { - *angle_in = - *angle_mid = FT_Atan2( d2.x, d2.y ); - *angle_out = FT_Atan2( d3.x, d3.y ); - } - } - } - else /* !close1 */ - { - if ( close2 ) - { - if ( close3 ) - { - *angle_in = - *angle_mid = - *angle_out = FT_Atan2( d1.x, d1.y ); - } - else /* !close3 */ - { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_out = FT_Atan2( d3.x, d3.y ); - *angle_mid = ft_angle_mean( *angle_in, *angle_out ); - } - } - else /* !close2 */ - { - if ( close3 ) - { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_mid = - *angle_out = FT_Atan2( d2.x, d2.y ); - } - else /* !close3 */ - { - *angle_in = FT_Atan2( d1.x, d1.y ); - *angle_mid = FT_Atan2( d2.x, d2.y ); - *angle_out = FT_Atan2( d3.x, d3.y ); - } - } - } - - theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) ); - theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) ); - - return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD && - theta2 < FT_SMALL_CUBIC_THRESHOLD ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** STROKE BORDERS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef enum FT_StrokeTags_ - { - FT_STROKE_TAG_ON = 1, /* on-curve point */ - FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */ - FT_STROKE_TAG_BEGIN = 4, /* sub-path start */ - FT_STROKE_TAG_END = 8 /* sub-path end */ - - } FT_StrokeTags; - -#define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ) - - typedef struct FT_StrokeBorderRec_ - { - FT_UInt num_points; - FT_UInt max_points; - FT_Vector* points; - FT_Byte* tags; - FT_Bool movable; /* TRUE for ends of lineto borders */ - FT_Int start; /* index of current sub-path start point */ - FT_Memory memory; - FT_Bool valid; - - } FT_StrokeBorderRec, *FT_StrokeBorder; - - - static FT_Error - ft_stroke_border_grow( FT_StrokeBorder border, - FT_UInt new_points ) - { - FT_UInt old_max = border->max_points; - FT_UInt new_max = border->num_points + new_points; - FT_Error error = FT_Err_Ok; - - - if ( new_max > old_max ) - { - FT_UInt cur_max = old_max; - FT_Memory memory = border->memory; - - - while ( cur_max < new_max ) - cur_max += ( cur_max >> 1 ) + 16; - - if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) || - FT_RENEW_ARRAY( border->tags, old_max, cur_max ) ) - goto Exit; - - border->max_points = cur_max; - } - - Exit: - return error; - } - - - static void - ft_stroke_border_close( FT_StrokeBorder border, - FT_Bool reverse ) - { - FT_UInt start = (FT_UInt)border->start; - FT_UInt count = border->num_points; - - - FT_ASSERT( border->start >= 0 ); - - /* don't record empty paths! */ - if ( count <= start + 1U ) - border->num_points = start; - else - { - /* copy the last point to the start of this sub-path, since */ - /* it contains the `adjusted' starting coordinates */ - border->num_points = --count; - border->points[start] = border->points[count]; - - if ( reverse ) - { - /* reverse the points */ - { - FT_Vector* vec1 = border->points + start + 1; - FT_Vector* vec2 = border->points + count - 1; - - - for ( ; vec1 < vec2; vec1++, vec2-- ) - { - FT_Vector tmp; - - - tmp = *vec1; - *vec1 = *vec2; - *vec2 = tmp; - } - } - - /* then the tags */ - { - FT_Byte* tag1 = border->tags + start + 1; - FT_Byte* tag2 = border->tags + count - 1; - - - for ( ; tag1 < tag2; tag1++, tag2-- ) - { - FT_Byte tmp; - - - tmp = *tag1; - *tag1 = *tag2; - *tag2 = tmp; - } - } - } - - border->tags[start ] |= FT_STROKE_TAG_BEGIN; - border->tags[count - 1] |= FT_STROKE_TAG_END; - } - - border->start = -1; - border->movable = FALSE; - } - - - static FT_Error - ft_stroke_border_lineto( FT_StrokeBorder border, - FT_Vector* to, - FT_Bool movable ) - { - FT_Error error = FT_Err_Ok; - - - FT_ASSERT( border->start >= 0 ); - - if ( border->movable ) - { - /* move last point */ - border->points[border->num_points - 1] = *to; - } - else - { - /* don't add zero-length lineto */ - if ( border->num_points > 0 && - FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) && - FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) ) - return error; - - /* add one point */ - error = ft_stroke_border_grow( border, 1 ); - if ( !error ) - { - FT_Vector* vec = border->points + border->num_points; - FT_Byte* tag = border->tags + border->num_points; - - - vec[0] = *to; - tag[0] = FT_STROKE_TAG_ON; - - border->num_points += 1; - } - } - border->movable = movable; - return error; - } - - - static FT_Error - ft_stroke_border_conicto( FT_StrokeBorder border, - FT_Vector* control, - FT_Vector* to ) - { - FT_Error error; - - - FT_ASSERT( border->start >= 0 ); - - error = ft_stroke_border_grow( border, 2 ); - if ( !error ) - { - FT_Vector* vec = border->points + border->num_points; - FT_Byte* tag = border->tags + border->num_points; - - - vec[0] = *control; - vec[1] = *to; - - tag[0] = 0; - tag[1] = FT_STROKE_TAG_ON; - - border->num_points += 2; - } - - border->movable = FALSE; - - return error; - } - - - static FT_Error - ft_stroke_border_cubicto( FT_StrokeBorder border, - FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to ) - { - FT_Error error; - - - FT_ASSERT( border->start >= 0 ); - - error = ft_stroke_border_grow( border, 3 ); - if ( !error ) - { - FT_Vector* vec = border->points + border->num_points; - FT_Byte* tag = border->tags + border->num_points; - - - vec[0] = *control1; - vec[1] = *control2; - vec[2] = *to; - - tag[0] = FT_STROKE_TAG_CUBIC; - tag[1] = FT_STROKE_TAG_CUBIC; - tag[2] = FT_STROKE_TAG_ON; - - border->num_points += 3; - } - - border->movable = FALSE; - - return error; - } - - -#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 ) - - - static FT_Error - ft_stroke_border_arcto( FT_StrokeBorder border, - FT_Vector* center, - FT_Fixed radius, - FT_Angle angle_start, - FT_Angle angle_diff ) - { - FT_Angle total, angle, step, rotate, next, theta; - FT_Vector a, b, a2, b2; - FT_Fixed length; - FT_Error error = FT_Err_Ok; - - - /* compute start point */ - FT_Vector_From_Polar( &a, radius, angle_start ); - a.x += center->x; - a.y += center->y; - - total = angle_diff; - angle = angle_start; - rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2; - - while ( total != 0 ) - { - step = total; - if ( step > FT_ARC_CUBIC_ANGLE ) - step = FT_ARC_CUBIC_ANGLE; - - else if ( step < -FT_ARC_CUBIC_ANGLE ) - step = -FT_ARC_CUBIC_ANGLE; - - next = angle + step; - theta = step; - if ( theta < 0 ) - theta = -theta; - - theta >>= 1; - - /* compute end point */ - FT_Vector_From_Polar( &b, radius, next ); - b.x += center->x; - b.y += center->y; - - /* compute first and second control points */ - length = FT_MulDiv( radius, FT_Sin( theta ) * 4, - ( 0x10000L + FT_Cos( theta ) ) * 3 ); - - FT_Vector_From_Polar( &a2, length, angle + rotate ); - a2.x += a.x; - a2.y += a.y; - - FT_Vector_From_Polar( &b2, length, next - rotate ); - b2.x += b.x; - b2.y += b.y; - - /* add cubic arc */ - error = ft_stroke_border_cubicto( border, &a2, &b2, &b ); - if ( error ) - break; - - /* process the rest of the arc ?? */ - a = b; - total -= step; - angle = next; - } - - return error; - } - - - static FT_Error - ft_stroke_border_moveto( FT_StrokeBorder border, - FT_Vector* to ) - { - /* close current open path if any ? */ - if ( border->start >= 0 ) - ft_stroke_border_close( border, FALSE ); - - border->start = (FT_Int)border->num_points; - border->movable = FALSE; - - return ft_stroke_border_lineto( border, to, FALSE ); - } - - - static void - ft_stroke_border_init( FT_StrokeBorder border, - FT_Memory memory ) - { - border->memory = memory; - border->points = NULL; - border->tags = NULL; - - border->num_points = 0; - border->max_points = 0; - border->start = -1; - border->valid = FALSE; - } - - - static void - ft_stroke_border_reset( FT_StrokeBorder border ) - { - border->num_points = 0; - border->start = -1; - border->valid = FALSE; - } - - - static void - ft_stroke_border_done( FT_StrokeBorder border ) - { - FT_Memory memory = border->memory; - - - FT_FREE( border->points ); - FT_FREE( border->tags ); - - border->num_points = 0; - border->max_points = 0; - border->start = -1; - border->valid = FALSE; - } - - - static FT_Error - ft_stroke_border_get_counts( FT_StrokeBorder border, - FT_UInt *anum_points, - FT_UInt *anum_contours ) - { - FT_Error error = FT_Err_Ok; - FT_UInt num_points = 0; - FT_UInt num_contours = 0; - - FT_UInt count = border->num_points; - FT_Vector* point = border->points; - FT_Byte* tags = border->tags; - FT_Int in_contour = 0; - - - for ( ; count > 0; count--, num_points++, point++, tags++ ) - { - if ( tags[0] & FT_STROKE_TAG_BEGIN ) - { - if ( in_contour != 0 ) - goto Fail; - - in_contour = 1; - } - else if ( in_contour == 0 ) - goto Fail; - - if ( tags[0] & FT_STROKE_TAG_END ) - { - in_contour = 0; - num_contours++; - } - } - - if ( in_contour != 0 ) - goto Fail; - - border->valid = TRUE; - - Exit: - *anum_points = num_points; - *anum_contours = num_contours; - return error; - - Fail: - num_points = 0; - num_contours = 0; - goto Exit; - } - - - static void - ft_stroke_border_export( FT_StrokeBorder border, - FT_Outline* outline ) - { - /* copy point locations */ - FT_ARRAY_COPY( outline->points + outline->n_points, - border->points, - border->num_points ); - - /* copy tags */ - { - FT_UInt count = border->num_points; - FT_Byte* read = border->tags; - FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points; - - - for ( ; count > 0; count--, read++, write++ ) - { - if ( *read & FT_STROKE_TAG_ON ) - *write = FT_CURVE_TAG_ON; - else if ( *read & FT_STROKE_TAG_CUBIC ) - *write = FT_CURVE_TAG_CUBIC; - else - *write = FT_CURVE_TAG_CONIC; - } - } - - /* copy contours */ - { - FT_UInt count = border->num_points; - FT_Byte* tags = border->tags; - FT_Short* write = outline->contours + outline->n_contours; - FT_Short idx = (FT_Short)outline->n_points; - - - for ( ; count > 0; count--, tags++, idx++ ) - { - if ( *tags & FT_STROKE_TAG_END ) - { - *write++ = idx; - outline->n_contours++; - } - } - } - - outline->n_points += (short)border->num_points; - - FT_ASSERT( FT_Outline_Check( outline ) == 0 ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** STROKER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI ) - - typedef struct FT_StrokerRec_ - { - FT_Angle angle_in; /* direction into curr join */ - FT_Angle angle_out; /* direction out of join */ - FT_Vector center; /* current position */ - FT_Fixed line_length; /* length of last lineto */ - FT_Bool first_point; /* is this the start? */ - FT_Bool subpath_open; /* is the subpath open? */ - FT_Angle subpath_angle; /* subpath start direction */ - FT_Vector subpath_start; /* subpath start position */ - FT_Fixed subpath_line_length; /* subpath start lineto len */ - FT_Bool handle_wide_strokes; /* use wide strokes logic? */ - - FT_Stroker_LineCap line_cap; - FT_Stroker_LineJoin line_join; - FT_Stroker_LineJoin line_join_saved; - FT_Fixed miter_limit; - FT_Fixed radius; - - FT_StrokeBorderRec borders[2]; - FT_Library library; - - } FT_StrokerRec; - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_New( FT_Library library, - FT_Stroker *astroker ) - { - FT_Error error; /* assigned in FT_NEW */ - FT_Memory memory; - FT_Stroker stroker = NULL; - - - if ( !library ) - return FT_THROW( Invalid_Library_Handle ); - - if ( !astroker ) - return FT_THROW( Invalid_Argument ); - - memory = library->memory; - - if ( !FT_NEW( stroker ) ) - { - stroker->library = library; - - ft_stroke_border_init( &stroker->borders[0], memory ); - ft_stroke_border_init( &stroker->borders[1], memory ); - } - - *astroker = stroker; - - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( void ) - FT_Stroker_Set( FT_Stroker stroker, - FT_Fixed radius, - FT_Stroker_LineCap line_cap, - FT_Stroker_LineJoin line_join, - FT_Fixed miter_limit ) - { - if ( !stroker ) - return; - - stroker->radius = radius; - stroker->line_cap = line_cap; - stroker->line_join = line_join; - stroker->miter_limit = miter_limit; - - /* ensure miter limit has sensible value */ - if ( stroker->miter_limit < 0x10000L ) - stroker->miter_limit = 0x10000L; - - /* save line join style: */ - /* line join style can be temporarily changed when stroking curves */ - stroker->line_join_saved = line_join; - - FT_Stroker_Rewind( stroker ); - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( void ) - FT_Stroker_Rewind( FT_Stroker stroker ) - { - if ( stroker ) - { - ft_stroke_border_reset( &stroker->borders[0] ); - ft_stroke_border_reset( &stroker->borders[1] ); - } - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( void ) - FT_Stroker_Done( FT_Stroker stroker ) - { - if ( stroker ) - { - FT_Memory memory = stroker->library->memory; - - - ft_stroke_border_done( &stroker->borders[0] ); - ft_stroke_border_done( &stroker->borders[1] ); - - stroker->library = NULL; - FT_FREE( stroker ); - } - } - - - /* create a circular arc at a corner or cap */ - static FT_Error - ft_stroker_arcto( FT_Stroker stroker, - FT_Int side ) - { - FT_Angle total, rotate; - FT_Fixed radius = stroker->radius; - FT_Error error = FT_Err_Ok; - FT_StrokeBorder border = stroker->borders + side; - - - rotate = FT_SIDE_TO_ROTATE( side ); - - total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); - if ( total == FT_ANGLE_PI ) - total = -rotate * 2; - - error = ft_stroke_border_arcto( border, - &stroker->center, - radius, - stroker->angle_in + rotate, - total ); - border->movable = FALSE; - return error; - } - - - /* add a cap at the end of an opened path */ - static FT_Error - ft_stroker_cap( FT_Stroker stroker, - FT_Angle angle, - FT_Int side ) - { - FT_Error error = FT_Err_Ok; - - - if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND ) - { - /* add a round cap */ - stroker->angle_in = angle; - stroker->angle_out = angle + FT_ANGLE_PI; - - error = ft_stroker_arcto( stroker, side ); - } - else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE ) - { - /* add a square cap */ - FT_Vector delta, delta2; - FT_Angle rotate = FT_SIDE_TO_ROTATE( side ); - FT_Fixed radius = stroker->radius; - FT_StrokeBorder border = stroker->borders + side; - - - FT_Vector_From_Polar( &delta2, radius, angle + rotate ); - FT_Vector_From_Polar( &delta, radius, angle ); - - delta.x += stroker->center.x + delta2.x; - delta.y += stroker->center.y + delta2.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - FT_Vector_From_Polar( &delta2, radius, angle - rotate ); - FT_Vector_From_Polar( &delta, radius, angle ); - - delta.x += delta2.x + stroker->center.x; - delta.y += delta2.y + stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT ) - { - /* add a butt ending */ - FT_Vector delta; - FT_Angle rotate = FT_SIDE_TO_ROTATE( side ); - FT_Fixed radius = stroker->radius; - FT_StrokeBorder border = stroker->borders + side; - - - FT_Vector_From_Polar( &delta, radius, angle + rotate ); - - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - FT_Vector_From_Polar( &delta, radius, angle - rotate ); - - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - - Exit: - return error; - } - - - /* process an inside corner, i.e. compute intersection */ - static FT_Error - ft_stroker_inside( FT_Stroker stroker, - FT_Int side, - FT_Fixed line_length ) - { - FT_StrokeBorder border = stroker->borders + side; - FT_Angle phi, theta, rotate; - FT_Fixed length, thcos; - FT_Vector delta; - FT_Error error = FT_Err_Ok; - FT_Bool intersect; /* use intersection of lines? */ - - - rotate = FT_SIDE_TO_ROTATE( side ); - - theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2; - - /* Only intersect borders if between two lineto's and both */ - /* lines are long enough (line_length is zero for curves). */ - /* Also avoid U-turns of nearly 180 degree. */ - if ( !border->movable || line_length == 0 || - theta > 0x59C000 || theta < -0x59C000 ) - intersect = FALSE; - else - { - /* compute minimum required length of lines */ - FT_Fixed min_length = ft_pos_abs( FT_MulFix( stroker->radius, - FT_Tan( theta ) ) ); - - - intersect = FT_BOOL( min_length && - stroker->line_length >= min_length && - line_length >= min_length ); - } - - if ( !intersect ) - { - FT_Vector_From_Polar( &delta, stroker->radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - border->movable = FALSE; - } - else - { - /* compute median angle */ - phi = stroker->angle_in + theta; - - thcos = FT_Cos( theta ); - - length = FT_DivFix( stroker->radius, thcos ); - - FT_Vector_From_Polar( &delta, length, phi + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - } - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - - return error; - } - - - /* process an outside corner, i.e. compute bevel/miter/round */ - static FT_Error - ft_stroker_outside( FT_Stroker stroker, - FT_Int side, - FT_Fixed line_length ) - { - FT_StrokeBorder border = stroker->borders + side; - FT_Error error; - FT_Angle rotate; - - - if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND ) - error = ft_stroker_arcto( stroker, side ); - else - { - /* this is a mitered (pointed) or beveled (truncated) corner */ - FT_Fixed sigma = 0, radius = stroker->radius; - FT_Angle theta = 0, phi = 0; - FT_Fixed thcos = 0; - FT_Bool bevel, fixed_bevel; - - - rotate = FT_SIDE_TO_ROTATE( side ); - - bevel = - FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL ); - - fixed_bevel = - FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE ); - - if ( !bevel ) - { - theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); - - if ( theta == FT_ANGLE_PI ) - { - theta = rotate; - phi = stroker->angle_in; - } - else - { - theta /= 2; - phi = stroker->angle_in + theta + rotate; - } - - thcos = FT_Cos( theta ); - sigma = FT_MulFix( stroker->miter_limit, thcos ); - - /* is miter limit exceeded? */ - if ( sigma < 0x10000L ) - { - /* don't create variable bevels for very small deviations; */ - /* FT_Sin(x) = 0 for x <= 57 */ - if ( fixed_bevel || ft_pos_abs( theta ) > 57 ) - bevel = TRUE; - } - } - - if ( bevel ) /* this is a bevel (broken angle) */ - { - if ( fixed_bevel ) - { - /* the outer corners are simply joined together */ - FT_Vector delta; - - - /* add bevel */ - FT_Vector_From_Polar( &delta, - radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - border->movable = FALSE; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - else /* variable bevel */ - { - /* the miter is truncated */ - FT_Vector middle, delta; - FT_Fixed length; - - - /* compute middle point */ - FT_Vector_From_Polar( &middle, - FT_MulFix( radius, stroker->miter_limit ), - phi ); - middle.x += stroker->center.x; - middle.y += stroker->center.y; - - /* compute first angle point */ - length = FT_MulDiv( radius, 0x10000L - sigma, - ft_pos_abs( FT_Sin( theta ) ) ); - - FT_Vector_From_Polar( &delta, length, phi + rotate ); - delta.x += middle.x; - delta.y += middle.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - /* compute second angle point */ - FT_Vector_From_Polar( &delta, length, phi - rotate ); - delta.x += middle.x; - delta.y += middle.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - /* finally, add an end point; only needed if not lineto */ - /* (line_length is zero for curves) */ - if ( line_length == 0 ) - { - FT_Vector_From_Polar( &delta, - radius, - stroker->angle_out + rotate ); - - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - } - } - else /* this is a miter (intersection) */ - { - FT_Fixed length; - FT_Vector delta; - - - length = FT_DivFix( stroker->radius, thcos ); - - FT_Vector_From_Polar( &delta, length, phi ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - - /* now add an end point; only needed if not lineto */ - /* (line_length is zero for curves) */ - if ( line_length == 0 ) - { - FT_Vector_From_Polar( &delta, - stroker->radius, - stroker->angle_out + rotate ); - delta.x += stroker->center.x; - delta.y += stroker->center.y; - - error = ft_stroke_border_lineto( border, &delta, FALSE ); - } - } - } - - Exit: - return error; - } - - - static FT_Error - ft_stroker_process_corner( FT_Stroker stroker, - FT_Fixed line_length ) - { - FT_Error error = FT_Err_Ok; - FT_Angle turn; - FT_Int inside_side; - - - turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); - - /* no specific corner processing is required if the turn is 0 */ - if ( turn == 0 ) - goto Exit; - - /* when we turn to the right, the inside side is 0 */ - /* otherwise, the inside side is 1 */ - inside_side = ( turn < 0 ); - - /* process the inside side */ - error = ft_stroker_inside( stroker, inside_side, line_length ); - if ( error ) - goto Exit; - - /* process the outside side */ - error = ft_stroker_outside( stroker, !inside_side, line_length ); - - Exit: - return error; - } - - - /* add two points to the left and right borders corresponding to the */ - /* start of the subpath */ - static FT_Error - ft_stroker_subpath_start( FT_Stroker stroker, - FT_Angle start_angle, - FT_Fixed line_length ) - { - FT_Vector delta; - FT_Vector point; - FT_Error error; - FT_StrokeBorder border; - - - FT_Vector_From_Polar( &delta, stroker->radius, - start_angle + FT_ANGLE_PI2 ); - - point.x = stroker->center.x + delta.x; - point.y = stroker->center.y + delta.y; - - border = stroker->borders; - error = ft_stroke_border_moveto( border, &point ); - if ( error ) - goto Exit; - - point.x = stroker->center.x - delta.x; - point.y = stroker->center.y - delta.y; - - border++; - error = ft_stroke_border_moveto( border, &point ); - - /* save angle, position, and line length for last join */ - /* (line_length is zero for curves) */ - stroker->subpath_angle = start_angle; - stroker->first_point = FALSE; - stroker->subpath_line_length = line_length; - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_LineTo( FT_Stroker stroker, - FT_Vector* to ) - { - FT_Error error = FT_Err_Ok; - FT_StrokeBorder border; - FT_Vector delta; - FT_Angle angle; - FT_Int side; - FT_Fixed line_length; - - - if ( !stroker || !to ) - return FT_THROW( Invalid_Argument ); - - delta.x = to->x - stroker->center.x; - delta.y = to->y - stroker->center.y; - - /* a zero-length lineto is a no-op; avoid creating a spurious corner */ - if ( delta.x == 0 && delta.y == 0 ) - goto Exit; - - /* compute length of line */ - line_length = FT_Vector_Length( &delta ); - - angle = FT_Atan2( delta.x, delta.y ); - FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 ); - - /* process corner if necessary */ - if ( stroker->first_point ) - { - /* This is the first segment of a subpath. We need to */ - /* add a point to each border at their respective starting */ - /* point locations. */ - error = ft_stroker_subpath_start( stroker, angle, line_length ); - if ( error ) - goto Exit; - } - else - { - /* process the current corner */ - stroker->angle_out = angle; - error = ft_stroker_process_corner( stroker, line_length ); - if ( error ) - goto Exit; - } - - /* now add a line segment to both the `inside' and `outside' paths */ - for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) - { - FT_Vector point; - - - point.x = to->x + delta.x; - point.y = to->y + delta.y; - - /* the ends of lineto borders are movable */ - error = ft_stroke_border_lineto( border, &point, TRUE ); - if ( error ) - goto Exit; - - delta.x = -delta.x; - delta.y = -delta.y; - } - - stroker->angle_in = angle; - stroker->center = *to; - stroker->line_length = line_length; - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_ConicTo( FT_Stroker stroker, - FT_Vector* control, - FT_Vector* to ) - { - FT_Error error = FT_Err_Ok; - FT_Vector bez_stack[34]; - FT_Vector* arc; - FT_Vector* limit = bez_stack + 30; - FT_Bool first_arc = TRUE; - - - if ( !stroker || !control || !to ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - /* if all control points are coincident, this is a no-op; */ - /* avoid creating a spurious corner */ - if ( FT_IS_SMALL( stroker->center.x - control->x ) && - FT_IS_SMALL( stroker->center.y - control->y ) && - FT_IS_SMALL( control->x - to->x ) && - FT_IS_SMALL( control->y - to->y ) ) - { - stroker->center = *to; - goto Exit; - } - - arc = bez_stack; - arc[0] = *to; - arc[1] = *control; - arc[2] = stroker->center; - - while ( arc >= bez_stack ) - { - FT_Angle angle_in, angle_out; - - - /* initialize with current direction */ - angle_in = angle_out = stroker->angle_in; - - if ( arc < limit && - !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) ) - { - if ( stroker->first_point ) - stroker->angle_in = angle_in; - - ft_conic_split( arc ); - arc += 2; - continue; - } - - if ( first_arc ) - { - first_arc = FALSE; - - /* process corner if necessary */ - if ( stroker->first_point ) - error = ft_stroker_subpath_start( stroker, angle_in, 0 ); - else - { - stroker->angle_out = angle_in; - error = ft_stroker_process_corner( stroker, 0 ); - } - } - else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > - FT_SMALL_CONIC_THRESHOLD / 4 ) - { - /* if the deviation from one arc to the next is too great, */ - /* add a round corner */ - stroker->center = arc[2]; - stroker->angle_out = angle_in; - stroker->line_join = FT_STROKER_LINEJOIN_ROUND; - - error = ft_stroker_process_corner( stroker, 0 ); - - /* reinstate line join style */ - stroker->line_join = stroker->line_join_saved; - } - - if ( error ) - goto Exit; - - /* the arc's angle is small enough; we can add it directly to each */ - /* border */ - { - FT_Vector ctrl, end; - FT_Angle theta, phi, rotate, alpha0 = 0; - FT_Fixed length; - FT_StrokeBorder border; - FT_Int side; - - - theta = FT_Angle_Diff( angle_in, angle_out ) / 2; - phi = angle_in + theta; - length = FT_DivFix( stroker->radius, FT_Cos( theta ) ); - - /* compute direction of original arc */ - if ( stroker->handle_wide_strokes ) - alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y ); - - for ( border = stroker->borders, side = 0; - side <= 1; - side++, border++ ) - { - rotate = FT_SIDE_TO_ROTATE( side ); - - /* compute control point */ - FT_Vector_From_Polar( &ctrl, length, phi + rotate ); - ctrl.x += arc[1].x; - ctrl.y += arc[1].y; - - /* compute end point */ - FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); - end.x += arc[0].x; - end.y += arc[0].y; - - if ( stroker->handle_wide_strokes ) - { - FT_Vector start; - FT_Angle alpha1; - - - /* determine whether the border radius is greater than the */ - /* radius of curvature of the original arc */ - start = border->points[border->num_points - 1]; - - alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); - - /* is the direction of the border arc opposite to */ - /* that of the original arc? */ - if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > - FT_ANGLE_PI / 2 ) - { - FT_Angle beta, gamma; - FT_Vector bvec, delta; - FT_Fixed blen, sinA, sinB, alen; - - - /* use the sine rule to find the intersection point */ - beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y ); - gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); - - bvec.x = end.x - start.x; - bvec.y = end.y - start.y; - - blen = FT_Vector_Length( &bvec ); - - sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); - sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); - - alen = FT_MulDiv( blen, sinA, sinB ); - - FT_Vector_From_Polar( &delta, alen, beta ); - delta.x += start.x; - delta.y += start.y; - - /* circumnavigate the negative sector backwards */ - border->movable = FALSE; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_conicto( border, &ctrl, &start ); - if ( error ) - goto Exit; - /* and then move to the endpoint */ - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - - continue; - } - - /* else fall through */ - } - - /* simply add an arc */ - error = ft_stroke_border_conicto( border, &ctrl, &end ); - if ( error ) - goto Exit; - } - } - - arc -= 2; - - stroker->angle_in = angle_out; - } - - stroker->center = *to; - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_CubicTo( FT_Stroker stroker, - FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to ) - { - FT_Error error = FT_Err_Ok; - FT_Vector bez_stack[37]; - FT_Vector* arc; - FT_Vector* limit = bez_stack + 32; - FT_Bool first_arc = TRUE; - - - if ( !stroker || !control1 || !control2 || !to ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - /* if all control points are coincident, this is a no-op; */ - /* avoid creating a spurious corner */ - if ( FT_IS_SMALL( stroker->center.x - control1->x ) && - FT_IS_SMALL( stroker->center.y - control1->y ) && - FT_IS_SMALL( control1->x - control2->x ) && - FT_IS_SMALL( control1->y - control2->y ) && - FT_IS_SMALL( control2->x - to->x ) && - FT_IS_SMALL( control2->y - to->y ) ) - { - stroker->center = *to; - goto Exit; - } - - arc = bez_stack; - arc[0] = *to; - arc[1] = *control2; - arc[2] = *control1; - arc[3] = stroker->center; - - while ( arc >= bez_stack ) - { - FT_Angle angle_in, angle_mid, angle_out; - - - /* initialize with current direction */ - angle_in = angle_out = angle_mid = stroker->angle_in; - - if ( arc < limit && - !ft_cubic_is_small_enough( arc, &angle_in, - &angle_mid, &angle_out ) ) - { - if ( stroker->first_point ) - stroker->angle_in = angle_in; - - ft_cubic_split( arc ); - arc += 3; - continue; - } - - if ( first_arc ) - { - first_arc = FALSE; - - /* process corner if necessary */ - if ( stroker->first_point ) - error = ft_stroker_subpath_start( stroker, angle_in, 0 ); - else - { - stroker->angle_out = angle_in; - error = ft_stroker_process_corner( stroker, 0 ); - } - } - else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > - FT_SMALL_CUBIC_THRESHOLD / 4 ) - { - /* if the deviation from one arc to the next is too great, */ - /* add a round corner */ - stroker->center = arc[3]; - stroker->angle_out = angle_in; - stroker->line_join = FT_STROKER_LINEJOIN_ROUND; - - error = ft_stroker_process_corner( stroker, 0 ); - - /* reinstate line join style */ - stroker->line_join = stroker->line_join_saved; - } - - if ( error ) - goto Exit; - - /* the arc's angle is small enough; we can add it directly to each */ - /* border */ - { - FT_Vector ctrl1, ctrl2, end; - FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0; - FT_Fixed length1, length2; - FT_StrokeBorder border; - FT_Int side; - - - theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2; - theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2; - phi1 = ft_angle_mean( angle_in, angle_mid ); - phi2 = ft_angle_mean( angle_mid, angle_out ); - length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) ); - length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) ); - - /* compute direction of original arc */ - if ( stroker->handle_wide_strokes ) - alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y ); - - for ( border = stroker->borders, side = 0; - side <= 1; - side++, border++ ) - { - rotate = FT_SIDE_TO_ROTATE( side ); - - /* compute control points */ - FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate ); - ctrl1.x += arc[2].x; - ctrl1.y += arc[2].y; - - FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate ); - ctrl2.x += arc[1].x; - ctrl2.y += arc[1].y; - - /* compute end point */ - FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); - end.x += arc[0].x; - end.y += arc[0].y; - - if ( stroker->handle_wide_strokes ) - { - FT_Vector start; - FT_Angle alpha1; - - - /* determine whether the border radius is greater than the */ - /* radius of curvature of the original arc */ - start = border->points[border->num_points - 1]; - - alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); - - /* is the direction of the border arc opposite to */ - /* that of the original arc? */ - if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > - FT_ANGLE_PI / 2 ) - { - FT_Angle beta, gamma; - FT_Vector bvec, delta; - FT_Fixed blen, sinA, sinB, alen; - - - /* use the sine rule to find the intersection point */ - beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y ); - gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); - - bvec.x = end.x - start.x; - bvec.y = end.y - start.y; - - blen = FT_Vector_Length( &bvec ); - - sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); - sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); - - alen = FT_MulDiv( blen, sinA, sinB ); - - FT_Vector_From_Polar( &delta, alen, beta ); - delta.x += start.x; - delta.y += start.y; - - /* circumnavigate the negative sector backwards */ - border->movable = FALSE; - error = ft_stroke_border_lineto( border, &delta, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - error = ft_stroke_border_cubicto( border, - &ctrl2, - &ctrl1, - &start ); - if ( error ) - goto Exit; - /* and then move to the endpoint */ - error = ft_stroke_border_lineto( border, &end, FALSE ); - if ( error ) - goto Exit; - - continue; - } - - /* else fall through */ - } - - /* simply add an arc */ - error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end ); - if ( error ) - goto Exit; - } - } - - arc -= 3; - - stroker->angle_in = angle_out; - } - - stroker->center = *to; - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_BeginSubPath( FT_Stroker stroker, - FT_Vector* to, - FT_Bool open ) - { - if ( !stroker || !to ) - return FT_THROW( Invalid_Argument ); - - /* We cannot process the first point, because there is not enough */ - /* information regarding its corner/cap. The latter will be processed */ - /* in the `FT_Stroker_EndSubPath' routine. */ - /* */ - stroker->first_point = TRUE; - stroker->center = *to; - stroker->subpath_open = open; - - /* Determine if we need to check whether the border radius is greater */ - /* than the radius of curvature of a curve, to handle this case */ - /* specially. This is only required if bevel joins or butt caps may */ - /* be created, because round & miter joins and round & square caps */ - /* cover the negative sector created with wide strokes. */ - stroker->handle_wide_strokes = - FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND || - ( stroker->subpath_open && - stroker->line_cap == FT_STROKER_LINECAP_BUTT ) ); - - /* record the subpath start point for each border */ - stroker->subpath_start = *to; - - stroker->angle_in = 0; - - return FT_Err_Ok; - } - - - static FT_Error - ft_stroker_add_reverse_left( FT_Stroker stroker, - FT_Bool open ) - { - FT_StrokeBorder right = stroker->borders + 0; - FT_StrokeBorder left = stroker->borders + 1; - FT_Int new_points; - FT_Error error = FT_Err_Ok; - - - FT_ASSERT( left->start >= 0 ); - - new_points = (FT_Int)left->num_points - left->start; - if ( new_points > 0 ) - { - error = ft_stroke_border_grow( right, (FT_UInt)new_points ); - if ( error ) - goto Exit; - - { - FT_Vector* dst_point = right->points + right->num_points; - FT_Byte* dst_tag = right->tags + right->num_points; - FT_Vector* src_point = left->points + left->num_points - 1; - FT_Byte* src_tag = left->tags + left->num_points - 1; - - - while ( src_point >= left->points + left->start ) - { - *dst_point = *src_point; - *dst_tag = *src_tag; - - if ( open ) - dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END; - else - { - FT_Byte ttag = - (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END ); - - - /* switch begin/end tags if necessary */ - if ( ttag == FT_STROKE_TAG_BEGIN || - ttag == FT_STROKE_TAG_END ) - dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END; - } - - src_point--; - src_tag--; - dst_point++; - dst_tag++; - } - } - - left->num_points = (FT_UInt)left->start; - right->num_points += (FT_UInt)new_points; - - right->movable = FALSE; - left->movable = FALSE; - } - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - /* there's a lot of magic in this function! */ - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_EndSubPath( FT_Stroker stroker ) - { - FT_Error error = FT_Err_Ok; - - - if ( !stroker ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( stroker->subpath_open ) - { - FT_StrokeBorder right = stroker->borders; - - - /* All right, this is an opened path, we need to add a cap between */ - /* right & left, add the reverse of left, then add a final cap */ - /* between left & right. */ - error = ft_stroker_cap( stroker, stroker->angle_in, 0 ); - if ( error ) - goto Exit; - - /* add reversed points from `left' to `right' */ - error = ft_stroker_add_reverse_left( stroker, TRUE ); - if ( error ) - goto Exit; - - /* now add the final cap */ - stroker->center = stroker->subpath_start; - error = ft_stroker_cap( stroker, - stroker->subpath_angle + FT_ANGLE_PI, 0 ); - if ( error ) - goto Exit; - - /* Now end the right subpath accordingly. The left one is */ - /* rewind and doesn't need further processing. */ - ft_stroke_border_close( right, FALSE ); - } - else - { - FT_Angle turn; - FT_Int inside_side; - - - /* close the path if needed */ - if ( stroker->center.x != stroker->subpath_start.x || - stroker->center.y != stroker->subpath_start.y ) - { - error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); - if ( error ) - goto Exit; - } - - /* process the corner */ - stroker->angle_out = stroker->subpath_angle; - turn = FT_Angle_Diff( stroker->angle_in, - stroker->angle_out ); - - /* no specific corner processing is required if the turn is 0 */ - if ( turn != 0 ) - { - /* when we turn to the right, the inside side is 0 */ - /* otherwise, the inside side is 1 */ - inside_side = ( turn < 0 ); - - error = ft_stroker_inside( stroker, - inside_side, - stroker->subpath_line_length ); - if ( error ) - goto Exit; - - /* process the outside side */ - error = ft_stroker_outside( stroker, - !inside_side, - stroker->subpath_line_length ); - if ( error ) - goto Exit; - } - - /* then end our two subpaths */ - ft_stroke_border_close( stroker->borders + 0, FALSE ); - ft_stroke_border_close( stroker->borders + 1, TRUE ); - } - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_GetBorderCounts( FT_Stroker stroker, - FT_StrokerBorder border, - FT_UInt *anum_points, - FT_UInt *anum_contours ) - { - FT_UInt num_points = 0, num_contours = 0; - FT_Error error; - - - if ( !stroker || border > 1 ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - error = ft_stroke_border_get_counts( stroker->borders + border, - &num_points, &num_contours ); - Exit: - if ( anum_points ) - *anum_points = num_points; - - if ( anum_contours ) - *anum_contours = num_contours; - - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_GetCounts( FT_Stroker stroker, - FT_UInt *anum_points, - FT_UInt *anum_contours ) - { - FT_UInt count1, count2, num_points = 0; - FT_UInt count3, count4, num_contours = 0; - FT_Error error; - - - if ( !stroker ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - error = ft_stroke_border_get_counts( stroker->borders + 0, - &count1, &count2 ); - if ( error ) - goto Exit; - - error = ft_stroke_border_get_counts( stroker->borders + 1, - &count3, &count4 ); - if ( error ) - goto Exit; - - num_points = count1 + count3; - num_contours = count2 + count4; - - Exit: - if ( anum_points ) - *anum_points = num_points; - - if ( anum_contours ) - *anum_contours = num_contours; - - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( void ) - FT_Stroker_ExportBorder( FT_Stroker stroker, - FT_StrokerBorder border, - FT_Outline* outline ) - { - if ( !stroker || !outline ) - return; - - if ( border == FT_STROKER_BORDER_LEFT || - border == FT_STROKER_BORDER_RIGHT ) - { - FT_StrokeBorder sborder = & stroker->borders[border]; - - - if ( sborder->valid ) - ft_stroke_border_export( sborder, outline ); - } - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( void ) - FT_Stroker_Export( FT_Stroker stroker, - FT_Outline* outline ) - { - FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline ); - FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline ); - } - - - /* documentation is in ftstroke.h */ - - /* - * The following is very similar to FT_Outline_Decompose, except - * that we do support opened paths, and do not scale the outline. - */ - FT_EXPORT_DEF( FT_Error ) - FT_Stroker_ParseOutline( FT_Stroker stroker, - FT_Outline* outline, - FT_Bool opened ) - { - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_start; - - FT_Vector* point; - FT_Vector* limit; - char* tags; - - FT_Error error; - - FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ - FT_Int tag; /* current point's state */ - - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - if ( !stroker ) - return FT_THROW( Invalid_Argument ); - - FT_Stroker_Rewind( stroker ); - - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - FT_UInt last; /* index of last point in contour */ - - - last = (FT_UInt)outline->contours[n]; - limit = outline->points + last; - - /* skip empty points; we don't stroke these */ - if ( last <= first ) - { - first = last + 1; - continue; - } - - v_start = outline->points[first]; - v_last = outline->points[last]; - - v_control = v_start; - - point = outline->points + first; - tags = outline->tags + first; - tag = FT_CURVE_TAG( tags[0] ); - - /* A contour cannot start with a cubic control point! */ - if ( tag == FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - /* check first point to determine origin */ - if ( tag == FT_CURVE_TAG_CONIC ) - { - /* First point is conic control. Yes, this happens. */ - if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - limit--; - } - else - { - /* if both first and last points are conic, */ - /* start at their middle */ - v_start.x = ( v_start.x + v_last.x ) / 2; - v_start.y = ( v_start.y + v_last.y ) / 2; - } - point--; - tags--; - } - - error = FT_Stroker_BeginSubPath( stroker, &v_start, opened ); - if ( error ) - goto Exit; - - while ( point < limit ) - { - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - switch ( tag ) - { - case FT_CURVE_TAG_ON: /* emit a single line_to */ - { - FT_Vector vec; - - - vec.x = point->x; - vec.y = point->y; - - error = FT_Stroker_LineTo( stroker, &vec ); - if ( error ) - goto Exit; - continue; - } - - case FT_CURVE_TAG_CONIC: /* consume conic arcs */ - v_control.x = point->x; - v_control.y = point->y; - - Do_Conic: - if ( point < limit ) - { - FT_Vector vec; - FT_Vector v_middle; - - - point++; - tags++; - tag = FT_CURVE_TAG( tags[0] ); - - vec = point[0]; - - if ( tag == FT_CURVE_TAG_ON ) - { - error = FT_Stroker_ConicTo( stroker, &v_control, &vec ); - if ( error ) - goto Exit; - continue; - } - - if ( tag != FT_CURVE_TAG_CONIC ) - goto Invalid_Outline; - - v_middle.x = ( v_control.x + vec.x ) / 2; - v_middle.y = ( v_control.y + vec.y ) / 2; - - error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); - if ( error ) - goto Exit; - - v_control = vec; - goto Do_Conic; - } - - error = FT_Stroker_ConicTo( stroker, &v_control, &v_start ); - goto Close; - - default: /* FT_CURVE_TAG_CUBIC */ - { - FT_Vector vec1, vec2; - - - if ( point + 1 > limit || - FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - point += 2; - tags += 2; - - vec1 = point[-2]; - vec2 = point[-1]; - - if ( point <= limit ) - { - FT_Vector vec; - - - vec = point[0]; - - error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); - if ( error ) - goto Exit; - continue; - } - - error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); - goto Close; - } - } - } - - Close: - if ( error ) - goto Exit; - - /* don't try to end the path if no segments have been generated */ - if ( !stroker->first_point ) - { - error = FT_Stroker_EndSubPath( stroker ); - if ( error ) - goto Exit; - } - - first = last + 1; - } - - return FT_Err_Ok; - - Exit: - return error; - - Invalid_Outline: - return FT_THROW( Invalid_Outline ); - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Glyph_Stroke( FT_Glyph *pglyph, - FT_Stroker stroker, - FT_Bool destroy ) - { - FT_Error error = FT_ERR( Invalid_Argument ); - FT_Glyph glyph = NULL; - - /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */ - FT_Library library = stroker->library; - - FT_UNUSED( library ); - - - if ( !pglyph ) - goto Exit; - - glyph = *pglyph; - if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET ) - goto Exit; - - { - FT_Glyph copy; - - - error = FT_Glyph_Copy( glyph, © ); - if ( error ) - goto Exit; - - glyph = copy; - } - - { - FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; - FT_Outline* outline = &oglyph->outline; - FT_UInt num_points, num_contours; - - - error = FT_Stroker_ParseOutline( stroker, outline, FALSE ); - if ( error ) - goto Fail; - - FT_Stroker_GetCounts( stroker, &num_points, &num_contours ); - - FT_Outline_Done( glyph->library, outline ); - - error = FT_Outline_New( glyph->library, - num_points, - (FT_Int)num_contours, - outline ); - if ( error ) - goto Fail; - - outline->n_points = 0; - outline->n_contours = 0; - - FT_Stroker_Export( stroker, outline ); - } - - if ( destroy ) - FT_Done_Glyph( *pglyph ); - - *pglyph = glyph; - goto Exit; - - Fail: - FT_Done_Glyph( glyph ); - glyph = NULL; - - if ( !destroy ) - *pglyph = NULL; - - Exit: - return error; - } - - - /* documentation is in ftstroke.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Glyph_StrokeBorder( FT_Glyph *pglyph, - FT_Stroker stroker, - FT_Bool inside, - FT_Bool destroy ) - { - FT_Error error = FT_ERR( Invalid_Argument ); - FT_Glyph glyph = NULL; - - /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */ - FT_Library library = stroker->library; - - FT_UNUSED( library ); - - - if ( !pglyph ) - goto Exit; - - glyph = *pglyph; - if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET ) - goto Exit; - - { - FT_Glyph copy; - - - error = FT_Glyph_Copy( glyph, © ); - if ( error ) - goto Exit; - - glyph = copy; - } - - { - FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; - FT_StrokerBorder border; - FT_Outline* outline = &oglyph->outline; - FT_UInt num_points, num_contours; - - - border = FT_Outline_GetOutsideBorder( outline ); - if ( inside ) - { - if ( border == FT_STROKER_BORDER_LEFT ) - border = FT_STROKER_BORDER_RIGHT; - else - border = FT_STROKER_BORDER_LEFT; - } - - error = FT_Stroker_ParseOutline( stroker, outline, FALSE ); - if ( error ) - goto Fail; - - FT_Stroker_GetBorderCounts( stroker, border, - &num_points, &num_contours ); - - FT_Outline_Done( glyph->library, outline ); - - error = FT_Outline_New( glyph->library, - num_points, - (FT_Int)num_contours, - outline ); - if ( error ) - goto Fail; - - outline->n_points = 0; - outline->n_contours = 0; - - FT_Stroker_ExportBorder( stroker, border, outline ); - } - - if ( destroy ) - FT_Done_Glyph( *pglyph ); - - *pglyph = glyph; - goto Exit; - - Fail: - FT_Done_Glyph( glyph ); - glyph = NULL; - - if ( !destroy ) - *pglyph = NULL; - - Exit: - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftsynth.c b/third_party/freetype/src/base/ftsynth.c deleted file mode 100644 index cd685339573fbdce70b5884b003da91d06918421..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftsynth.c +++ /dev/null @@ -1,163 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsynth.c */ -/* */ -/* FreeType synthesizing code for emboldening and slanting (body). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_SYNTHESIS_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_OUTLINE_H -#include FT_BITMAP_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_synth - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** EXPERIMENTAL OBLIQUING SUPPORT ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - /* documentation is in ftsynth.h */ - - FT_EXPORT_DEF( void ) - FT_GlyphSlot_Oblique( FT_GlyphSlot slot ) - { - FT_Matrix transform; - FT_Outline* outline; - - - if ( !slot ) - return; - - outline = &slot->outline; - - /* only oblique outline glyphs */ - if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) - return; - - /* we don't touch the advance width */ - - /* For italic, simply apply a shear transform, with an angle */ - /* of about 12 degrees. */ - - transform.xx = 0x10000L; - transform.yx = 0x00000L; - - transform.xy = 0x0366AL; - transform.yy = 0x10000L; - - FT_Outline_Transform( outline, &transform ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** EXPERIMENTAL EMBOLDENING SUPPORT ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - - - /* documentation is in ftsynth.h */ - - FT_EXPORT_DEF( void ) - FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) - { - FT_Library library; - FT_Face face; - FT_Error error; - FT_Pos xstr, ystr; - - - if ( !slot ) - return; - - library = slot->library; - face = slot->face; - - if ( slot->format != FT_GLYPH_FORMAT_OUTLINE && - slot->format != FT_GLYPH_FORMAT_BITMAP ) - return; - - /* some reasonable strength */ - xstr = FT_MulFix( face->units_per_EM, - face->size->metrics.y_scale ) / 24; - ystr = xstr; - - if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) - FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); - - else /* slot->format == FT_GLYPH_FORMAT_BITMAP */ - { - /* round to full pixels */ - xstr &= ~63; - if ( xstr == 0 ) - xstr = 1 << 6; - ystr &= ~63; - - /* - * XXX: overflow check for 16-bit system, for compatibility - * with FT_GlyphSlot_Embolden() since freetype-2.1.10. - * unfortunately, this function return no informations - * about the cause of error. - */ - if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN ) - { - FT_TRACE1(( "FT_GlyphSlot_Embolden:" )); - FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr )); - return; - } - error = FT_GlyphSlot_Own_Bitmap( slot ); - if ( error ) - return; - - error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr ); - if ( error ) - return; - } - - if ( slot->advance.x ) - slot->advance.x += xstr; - - if ( slot->advance.y ) - slot->advance.y += ystr; - - slot->metrics.width += xstr; - slot->metrics.height += ystr; - slot->metrics.horiAdvance += xstr; - slot->metrics.vertAdvance += ystr; - slot->metrics.horiBearingY += ystr; - - /* XXX: 16-bit overflow case must be excluded before here */ - if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) - slot->bitmap_top += (FT_Int)( ystr >> 6 ); - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftsystem.c b/third_party/freetype/src/base/ftsystem.c deleted file mode 100644 index 1938fd8917c2e46f9a3d0b74d1b85a15760099e9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftsystem.c +++ /dev/null @@ -1,320 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsystem.c */ -/* */ -/* ANSI-specific FreeType low-level system interface (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* This file contains the default interface used by FreeType to access */ - /* low-level, i.e. memory management, i/o access as well as thread */ - /* synchronisation. It can be replaced by user-specific routines if */ - /* necessary. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_SYSTEM_H -#include FT_ERRORS_H -#include FT_TYPES_H - - - /*************************************************************************/ - /* */ - /* MEMORY MANAGEMENT INTERFACE */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* It is not necessary to do any error checking for the */ - /* allocation-related functions. This will be done by the higher level */ - /* routines like ft_mem_alloc() or ft_mem_realloc(). */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_alloc */ - /* */ - /* <Description> */ - /* The memory allocation function. */ - /* */ - /* <Input> */ - /* memory :: A pointer to the memory object. */ - /* */ - /* size :: The requested size in bytes. */ - /* */ - /* <Return> */ - /* The address of newly allocated block. */ - /* */ - FT_CALLBACK_DEF( void* ) - ft_alloc( FT_Memory memory, - long size ) - { - FT_UNUSED( memory ); - - return ft_smalloc( (size_t)size ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_realloc */ - /* */ - /* <Description> */ - /* The memory reallocation function. */ - /* */ - /* <Input> */ - /* memory :: A pointer to the memory object. */ - /* */ - /* cur_size :: The current size of the allocated memory block. */ - /* */ - /* new_size :: The newly requested size in bytes. */ - /* */ - /* block :: The current address of the block in memory. */ - /* */ - /* <Return> */ - /* The address of the reallocated memory block. */ - /* */ - FT_CALLBACK_DEF( void* ) - ft_realloc( FT_Memory memory, - long cur_size, - long new_size, - void* block ) - { - FT_UNUSED( memory ); - FT_UNUSED( cur_size ); - - return ft_srealloc( block, (size_t)new_size ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_free */ - /* */ - /* <Description> */ - /* The memory release function. */ - /* */ - /* <Input> */ - /* memory :: A pointer to the memory object. */ - /* */ - /* block :: The address of block in memory to be freed. */ - /* */ - FT_CALLBACK_DEF( void ) - ft_free( FT_Memory memory, - void* block ) - { - FT_UNUSED( memory ); - - ft_sfree( block ); - } - - - /*************************************************************************/ - /* */ - /* RESOURCE MANAGEMENT INTERFACE */ - /* */ - /*************************************************************************/ - -#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_io - - /* We use the macro STREAM_FILE for convenience to extract the */ - /* system-specific stream handle from a given FreeType stream object */ -#define STREAM_FILE( stream ) ( (FT_FILE*)stream->descriptor.pointer ) - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_ansi_stream_close */ - /* */ - /* <Description> */ - /* The function to close a stream. */ - /* */ - /* <Input> */ - /* stream :: A pointer to the stream object. */ - /* */ - FT_CALLBACK_DEF( void ) - ft_ansi_stream_close( FT_Stream stream ) - { - ft_fclose( STREAM_FILE( stream ) ); - - stream->descriptor.pointer = NULL; - stream->size = 0; - stream->base = NULL; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_ansi_stream_io */ - /* */ - /* <Description> */ - /* The function to open a stream. */ - /* */ - /* <Input> */ - /* stream :: A pointer to the stream object. */ - /* */ - /* offset :: The position in the data stream to start reading. */ - /* */ - /* buffer :: The address of buffer to store the read data. */ - /* */ - /* count :: The number of bytes to read from the stream. */ - /* */ - /* <Return> */ - /* The number of bytes actually read. If `count' is zero (this is, */ - /* the function is used for seeking), a non-zero return value */ - /* indicates an error. */ - /* */ - FT_CALLBACK_DEF( unsigned long ) - ft_ansi_stream_io( FT_Stream stream, - unsigned long offset, - unsigned char* buffer, - unsigned long count ) - { - FT_FILE* file; - - - if ( !count && offset > stream->size ) - return 1; - - file = STREAM_FILE( stream ); - - if ( stream->pos != offset ) - ft_fseek( file, (long)offset, SEEK_SET ); - - return (unsigned long)ft_fread( buffer, 1, count, file ); - } - - - /* documentation is in ftstream.h */ - - FT_BASE_DEF( FT_Error ) - FT_Stream_Open( FT_Stream stream, - const char* filepathname ) - { - FT_FILE* file; - - - if ( !stream ) - return FT_THROW( Invalid_Stream_Handle ); - - stream->descriptor.pointer = NULL; - stream->pathname.pointer = (char*)filepathname; - stream->base = NULL; - stream->pos = 0; - stream->read = NULL; - stream->close = NULL; - - file = ft_fopen( filepathname, "rb" ); - if ( !file ) - { - FT_ERROR(( "FT_Stream_Open:" - " could not open `%s'\n", filepathname )); - - return FT_THROW( Cannot_Open_Resource ); - } - - ft_fseek( file, 0, SEEK_END ); - stream->size = (unsigned long)ft_ftell( file ); - if ( !stream->size ) - { - FT_ERROR(( "FT_Stream_Open:" )); - FT_ERROR(( " opened `%s' but zero-sized\n", filepathname )); - ft_fclose( file ); - return FT_THROW( Cannot_Open_Stream ); - } - ft_fseek( file, 0, SEEK_SET ); - - stream->descriptor.pointer = file; - stream->read = ft_ansi_stream_io; - stream->close = ft_ansi_stream_close; - - FT_TRACE1(( "FT_Stream_Open:" )); - FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", - filepathname, stream->size )); - - return FT_Err_Ok; - } - -#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ - -#ifdef FT_DEBUG_MEMORY - - extern FT_Int - ft_mem_debug_init( FT_Memory memory ); - - extern void - ft_mem_debug_done( FT_Memory memory ); - -#endif - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( FT_Memory ) - FT_New_Memory( void ) - { - FT_Memory memory; - - - memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) ); - if ( memory ) - { - memory->user = NULL; - memory->alloc = ft_alloc; - memory->realloc = ft_realloc; - memory->free = ft_free; -#ifdef FT_DEBUG_MEMORY - ft_mem_debug_init( memory ); -#endif - } - - return memory; - } - - - /* documentation is in ftobjs.h */ - - FT_BASE_DEF( void ) - FT_Done_Memory( FT_Memory memory ) - { -#ifdef FT_DEBUG_MEMORY - ft_mem_debug_done( memory ); -#endif - ft_sfree( memory ); - } - - -/* END */ diff --git a/third_party/freetype/src/base/fttrigon.c b/third_party/freetype/src/base/fttrigon.c deleted file mode 100644 index 5b24304c2fc81c9a8b7edd8bc1a565d72c7d1752..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/fttrigon.c +++ /dev/null @@ -1,525 +0,0 @@ -/***************************************************************************/ -/* */ -/* fttrigon.c */ -/* */ -/* FreeType trigonometric functions (body). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* This is a fixed-point CORDIC implementation of trigonometric */ - /* functions as well as transformations between Cartesian and polar */ - /* coordinates. The angles are represented as 16.16 fixed-point values */ - /* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */ - /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */ - /* discrete Cartesian grid can have the same or better angular */ - /* resolution. Therefore, to maintain this precision, some functions */ - /* require an interim upscaling of the vectors, whereas others operate */ - /* with 24-bit long vectors directly. */ - /* */ - /*************************************************************************/ - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_CALC_H -#include FT_TRIGONOMETRY_H - - - /* the Cordic shrink factor 0.858785336480436 * 2^32 */ -#define FT_TRIG_SCALE 0xDBD95B16UL - - /* the highest bit in overflow-safe vector components, */ - /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ -#define FT_TRIG_SAFE_MSB 29 - - /* this table was generated for FT_PI = 180L << 16, i.e. degrees */ -#define FT_TRIG_MAX_ITERS 23 - - static const FT_Angle - ft_trig_arctan_table[] = - { - 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, - 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, - 57L, 29L, 14L, 7L, 4L, 2L, 1L - }; - - -#ifdef FT_LONG64 - - /* multiply a given value by the CORDIC shrink factor */ - static FT_Fixed - ft_trig_downscale( FT_Fixed val ) - { - FT_Int s = 1; - - - if ( val < 0 ) - { - val = -val; - s = -1; - } - - /* 0x40000000 comes from regression analysis between true */ - /* and CORDIC hypotenuse, so it minimizes the error */ - val = (FT_Fixed)( ( (FT_Int64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 ); - - return s < 0 ? -val : val; - } - -#else /* !FT_LONG64 */ - - /* multiply a given value by the CORDIC shrink factor */ - static FT_Fixed - ft_trig_downscale( FT_Fixed val ) - { - FT_Int s = 1; - FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; - - - if ( val < 0 ) - { - val = -val; - s = -1; - } - - lo1 = (FT_UInt32)val & 0x0000FFFFU; - hi1 = (FT_UInt32)val >> 16; - lo2 = FT_TRIG_SCALE & 0x0000FFFFU; - hi2 = FT_TRIG_SCALE >> 16; - - lo = lo1 * lo2; - i1 = lo1 * hi2; - i2 = lo2 * hi1; - hi = hi1 * hi2; - - /* Check carry overflow of i1 + i2 */ - i1 += i2; - hi += (FT_UInt32)( i1 < i2 ) << 16; - - hi += i1 >> 16; - i1 = i1 << 16; - - /* Check carry overflow of i1 + lo */ - lo += i1; - hi += ( lo < i1 ); - - /* 0x40000000 comes from regression analysis between true */ - /* and CORDIC hypotenuse, so it minimizes the error */ - - /* Check carry overflow of lo + 0x40000000 */ - lo += 0x40000000UL; - hi += ( lo < 0x40000000UL ); - - val = (FT_Fixed)hi; - - return s < 0 ? -val : val; - } - -#endif /* !FT_LONG64 */ - - - /* undefined and never called for zero vector */ - static FT_Int - ft_trig_prenorm( FT_Vector* vec ) - { - FT_Pos x, y; - FT_Int shift; - - - x = vec->x; - y = vec->y; - - shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) ); - - if ( shift <= FT_TRIG_SAFE_MSB ) - { - shift = FT_TRIG_SAFE_MSB - shift; - vec->x = (FT_Pos)( (FT_ULong)x << shift ); - vec->y = (FT_Pos)( (FT_ULong)y << shift ); - } - else - { - shift -= FT_TRIG_SAFE_MSB; - vec->x = x >> shift; - vec->y = y >> shift; - shift = -shift; - } - - return shift; - } - - - static void - ft_trig_pseudo_rotate( FT_Vector* vec, - FT_Angle theta ) - { - FT_Int i; - FT_Fixed x, y, xtemp, b; - const FT_Angle *arctanptr; - - - x = vec->x; - y = vec->y; - - /* Rotate inside [-PI/4,PI/4] sector */ - while ( theta < -FT_ANGLE_PI4 ) - { - xtemp = y; - y = -x; - x = xtemp; - theta += FT_ANGLE_PI2; - } - - while ( theta > FT_ANGLE_PI4 ) - { - xtemp = -y; - y = x; - x = xtemp; - theta -= FT_ANGLE_PI2; - } - - arctanptr = ft_trig_arctan_table; - - /* Pseudorotations, with right shifts */ - for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ ) - { - if ( theta < 0 ) - { - xtemp = x + ( ( y + b ) >> i ); - y = y - ( ( x + b ) >> i ); - x = xtemp; - theta += *arctanptr++; - } - else - { - xtemp = x - ( ( y + b ) >> i ); - y = y + ( ( x + b ) >> i ); - x = xtemp; - theta -= *arctanptr++; - } - } - - vec->x = x; - vec->y = y; - } - - - static void - ft_trig_pseudo_polarize( FT_Vector* vec ) - { - FT_Angle theta; - FT_Int i; - FT_Fixed x, y, xtemp, b; - const FT_Angle *arctanptr; - - - x = vec->x; - y = vec->y; - - /* Get the vector into [-PI/4,PI/4] sector */ - if ( y > x ) - { - if ( y > -x ) - { - theta = FT_ANGLE_PI2; - xtemp = y; - y = -x; - x = xtemp; - } - else - { - theta = y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI; - x = -x; - y = -y; - } - } - else - { - if ( y < -x ) - { - theta = -FT_ANGLE_PI2; - xtemp = -y; - y = x; - x = xtemp; - } - else - { - theta = 0; - } - } - - arctanptr = ft_trig_arctan_table; - - /* Pseudorotations, with right shifts */ - for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ ) - { - if ( y > 0 ) - { - xtemp = x + ( ( y + b ) >> i ); - y = y - ( ( x + b ) >> i ); - x = xtemp; - theta += *arctanptr++; - } - else - { - xtemp = x - ( ( y + b ) >> i ); - y = y + ( ( x + b ) >> i ); - x = xtemp; - theta -= *arctanptr++; - } - } - - /* round theta to acknowledge its error that mostly comes */ - /* from accumulated rounding errors in the arctan table */ - if ( theta >= 0 ) - theta = FT_PAD_ROUND( theta, 16 ); - else - theta = -FT_PAD_ROUND( -theta, 16 ); - - vec->x = x; - vec->y = theta; - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_Cos( FT_Angle angle ) - { - FT_Vector v; - - - FT_Vector_Unit( &v, angle ); - - return v.x; - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_Sin( FT_Angle angle ) - { - FT_Vector v; - - - FT_Vector_Unit( &v, angle ); - - return v.y; - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_Tan( FT_Angle angle ) - { - FT_Vector v; - - - FT_Vector_Unit( &v, angle ); - - return FT_DivFix( v.y, v.x ); - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( FT_Angle ) - FT_Atan2( FT_Fixed dx, - FT_Fixed dy ) - { - FT_Vector v; - - - if ( dx == 0 && dy == 0 ) - return 0; - - v.x = dx; - v.y = dy; - ft_trig_prenorm( &v ); - ft_trig_pseudo_polarize( &v ); - - return v.y; - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( void ) - FT_Vector_Unit( FT_Vector* vec, - FT_Angle angle ) - { - if ( !vec ) - return; - - vec->x = FT_TRIG_SCALE >> 8; - vec->y = 0; - ft_trig_pseudo_rotate( vec, angle ); - vec->x = ( vec->x + 0x80L ) >> 8; - vec->y = ( vec->y + 0x80L ) >> 8; - } - - - /* these macros return 0 for positive numbers, - and -1 for negative ones */ -#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) ) -#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) ) -#define FT_SIGN_INT32( x ) ( (x) >> 31 ) -#define FT_SIGN_INT16( x ) ( (x) >> 15 ) - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( void ) - FT_Vector_Rotate( FT_Vector* vec, - FT_Angle angle ) - { - FT_Int shift; - FT_Vector v; - - - if ( !vec || !angle ) - return; - - v = *vec; - - if ( v.x == 0 && v.y == 0 ) - return; - - shift = ft_trig_prenorm( &v ); - ft_trig_pseudo_rotate( &v, angle ); - v.x = ft_trig_downscale( v.x ); - v.y = ft_trig_downscale( v.y ); - - if ( shift > 0 ) - { - FT_Int32 half = (FT_Int32)1L << ( shift - 1 ); - - - vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; - vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; - } - else - { - shift = -shift; - vec->x = (FT_Pos)( (FT_ULong)v.x << shift ); - vec->y = (FT_Pos)( (FT_ULong)v.y << shift ); - } - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( FT_Fixed ) - FT_Vector_Length( FT_Vector* vec ) - { - FT_Int shift; - FT_Vector v; - - - if ( !vec ) - return 0; - - v = *vec; - - /* handle trivial cases */ - if ( v.x == 0 ) - { - return FT_ABS( v.y ); - } - else if ( v.y == 0 ) - { - return FT_ABS( v.x ); - } - - /* general case */ - shift = ft_trig_prenorm( &v ); - ft_trig_pseudo_polarize( &v ); - - v.x = ft_trig_downscale( v.x ); - - if ( shift > 0 ) - return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift; - - return (FT_Fixed)( (FT_UInt32)v.x << -shift ); - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( void ) - FT_Vector_Polarize( FT_Vector* vec, - FT_Fixed *length, - FT_Angle *angle ) - { - FT_Int shift; - FT_Vector v; - - - if ( !vec || !length || !angle ) - return; - - v = *vec; - - if ( v.x == 0 && v.y == 0 ) - return; - - shift = ft_trig_prenorm( &v ); - ft_trig_pseudo_polarize( &v ); - - v.x = ft_trig_downscale( v.x ); - - *length = shift >= 0 ? ( v.x >> shift ) - : (FT_Fixed)( (FT_UInt32)v.x << -shift ); - *angle = v.y; - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( void ) - FT_Vector_From_Polar( FT_Vector* vec, - FT_Fixed length, - FT_Angle angle ) - { - if ( !vec ) - return; - - vec->x = length; - vec->y = 0; - - FT_Vector_Rotate( vec, angle ); - } - - - /* documentation is in fttrigon.h */ - - FT_EXPORT_DEF( FT_Angle ) - FT_Angle_Diff( FT_Angle angle1, - FT_Angle angle2 ) - { - FT_Angle delta = angle2 - angle1; - - - while ( delta <= -FT_ANGLE_PI ) - delta += FT_ANGLE_2PI; - - while ( delta > FT_ANGLE_PI ) - delta -= FT_ANGLE_2PI; - - return delta; - } - - -/* END */ diff --git a/third_party/freetype/src/base/fttype1.c b/third_party/freetype/src/base/fttype1.c deleted file mode 100644 index c549382afdb919170021c1ac84b1a201dbf26dbb..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/fttype1.c +++ /dev/null @@ -1,127 +0,0 @@ -/***************************************************************************/ -/* */ -/* fttype1.c */ -/* */ -/* FreeType utility file for PS names support (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_SERVICE_H -#include FT_SERVICE_POSTSCRIPT_INFO_H - - - /* documentation is in t1tables.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_PS_Font_Info( FT_Face face, - PS_FontInfoRec* afont_info ) - { - FT_Error error; - FT_Service_PsInfo service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !afont_info ) - return FT_THROW( Invalid_Argument ); - - FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); - - if ( service && service->ps_get_font_info ) - error = service->ps_get_font_info( face, afont_info ); - else - error = FT_THROW( Invalid_Argument ); - - return error; - } - - - /* documentation is in t1tables.h */ - - FT_EXPORT_DEF( FT_Int ) - FT_Has_PS_Glyph_Names( FT_Face face ) - { - FT_Int result = 0; - FT_Service_PsInfo service; - - - if ( face ) - { - FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); - - if ( service && service->ps_has_glyph_names ) - result = service->ps_has_glyph_names( face ); - } - - return result; - } - - - /* documentation is in t1tables.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_PS_Font_Private( FT_Face face, - PS_PrivateRec* afont_private ) - { - FT_Error error; - FT_Service_PsInfo service; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !afont_private ) - return FT_THROW( Invalid_Argument ); - - FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); - - if ( service && service->ps_get_font_private ) - error = service->ps_get_font_private( face, afont_private ); - else - error = FT_THROW( Invalid_Argument ); - - return error; - } - - - /* documentation is in t1tables.h */ - - FT_EXPORT_DEF( FT_Long ) - FT_Get_PS_Font_Value( FT_Face face, - PS_Dict_Keys key, - FT_UInt idx, - void *value, - FT_Long value_len ) - { - FT_Int result = 0; - FT_Service_PsInfo service = NULL; - - - if ( face ) - { - FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); - - if ( service && service->ps_get_font_value ) - result = service->ps_get_font_value( face, key, idx, - value, value_len ); - } - - return result; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftutil.c b/third_party/freetype/src/base/ftutil.c deleted file mode 100644 index f5b72db70832faba095fc1af5de3b9e3232d238f..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftutil.c +++ /dev/null @@ -1,441 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftutil.c */ -/* */ -/* FreeType utility file for memory and list management (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_MEMORY_H -#include FT_INTERNAL_OBJECTS_H -#include FT_LIST_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_memory - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** *****/ - /***** M E M O R Y M A N A G E M E N T *****/ - /***** *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_BASE_DEF( FT_Pointer ) - ft_mem_alloc( FT_Memory memory, - FT_Long size, - FT_Error *p_error ) - { - FT_Error error; - FT_Pointer block = ft_mem_qalloc( memory, size, &error ); - - if ( !error && size > 0 ) - FT_MEM_ZERO( block, size ); - - *p_error = error; - return block; - } - - - FT_BASE_DEF( FT_Pointer ) - ft_mem_qalloc( FT_Memory memory, - FT_Long size, - FT_Error *p_error ) - { - FT_Error error = FT_Err_Ok; - FT_Pointer block = NULL; - - - if ( size > 0 ) - { - block = memory->alloc( memory, size ); - if ( block == NULL ) - error = FT_THROW( Out_Of_Memory ); - } - else if ( size < 0 ) - { - /* may help catch/prevent security issues */ - error = FT_THROW( Invalid_Argument ); - } - - *p_error = error; - return block; - } - - - FT_BASE_DEF( FT_Pointer ) - ft_mem_realloc( FT_Memory memory, - FT_Long item_size, - FT_Long cur_count, - FT_Long new_count, - void* block, - FT_Error *p_error ) - { - FT_Error error = FT_Err_Ok; - - - block = ft_mem_qrealloc( memory, item_size, - cur_count, new_count, block, &error ); - if ( !error && new_count > cur_count ) - FT_MEM_ZERO( (char*)block + cur_count * item_size, - ( new_count - cur_count ) * item_size ); - - *p_error = error; - return block; - } - - - FT_BASE_DEF( FT_Pointer ) - ft_mem_qrealloc( FT_Memory memory, - FT_Long item_size, - FT_Long cur_count, - FT_Long new_count, - void* block, - FT_Error *p_error ) - { - FT_Error error = FT_Err_Ok; - - - /* Note that we now accept `item_size == 0' as a valid parameter, in - * order to cover very weird cases where an ALLOC_MULT macro would be - * called. - */ - if ( cur_count < 0 || new_count < 0 || item_size < 0 ) - { - /* may help catch/prevent nasty security issues */ - error = FT_THROW( Invalid_Argument ); - } - else if ( new_count == 0 || item_size == 0 ) - { - ft_mem_free( memory, block ); - block = NULL; - } - else if ( new_count > FT_INT_MAX/item_size ) - { - error = FT_THROW( Array_Too_Large ); - } - else if ( cur_count == 0 ) - { - FT_ASSERT( block == NULL ); - - block = ft_mem_alloc( memory, new_count*item_size, &error ); - } - else - { - FT_Pointer block2; - FT_Long cur_size = cur_count*item_size; - FT_Long new_size = new_count*item_size; - - - block2 = memory->realloc( memory, cur_size, new_size, block ); - if ( block2 == NULL ) - error = FT_THROW( Out_Of_Memory ); - else - block = block2; - } - - *p_error = error; - return block; - } - - - FT_BASE_DEF( void ) - ft_mem_free( FT_Memory memory, - const void *P ) - { - if ( P ) - memory->free( memory, (void*)P ); - } - - - FT_BASE_DEF( FT_Pointer ) - ft_mem_dup( FT_Memory memory, - const void* address, - FT_ULong size, - FT_Error *p_error ) - { - FT_Error error; - FT_Pointer p = ft_mem_qalloc( memory, (FT_Long)size, &error ); - - - if ( !error && address ) - ft_memcpy( p, address, size ); - - *p_error = error; - return p; - } - - - FT_BASE_DEF( FT_Pointer ) - ft_mem_strdup( FT_Memory memory, - const char* str, - FT_Error *p_error ) - { - FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1 - : 0; - - - return ft_mem_dup( memory, str, len, p_error ); - } - - - FT_BASE_DEF( FT_Int ) - ft_mem_strcpyn( char* dst, - const char* src, - FT_ULong size ) - { - while ( size > 1 && *src != 0 ) - { - *dst++ = *src++; - size--; - } - - *dst = 0; /* always zero-terminate */ - - return *src != 0; - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** *****/ - /***** D O U B L Y L I N K E D L I S T S *****/ - /***** *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - -#undef FT_COMPONENT -#define FT_COMPONENT trace_list - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( FT_ListNode ) - FT_List_Find( FT_List list, - void* data ) - { - FT_ListNode cur; - - - if ( !list ) - return NULL; - - cur = list->head; - while ( cur ) - { - if ( cur->data == data ) - return cur; - - cur = cur->next; - } - - return NULL; - } - - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( void ) - FT_List_Add( FT_List list, - FT_ListNode node ) - { - FT_ListNode before; - - - if ( !list || !node ) - return; - - before = list->tail; - - node->next = NULL; - node->prev = before; - - if ( before ) - before->next = node; - else - list->head = node; - - list->tail = node; - } - - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( void ) - FT_List_Insert( FT_List list, - FT_ListNode node ) - { - FT_ListNode after; - - - if ( !list || !node ) - return; - - after = list->head; - - node->next = after; - node->prev = NULL; - - if ( !after ) - list->tail = node; - else - after->prev = node; - - list->head = node; - } - - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( void ) - FT_List_Remove( FT_List list, - FT_ListNode node ) - { - FT_ListNode before, after; - - - if ( !list || !node ) - return; - - before = node->prev; - after = node->next; - - if ( before ) - before->next = after; - else - list->head = after; - - if ( after ) - after->prev = before; - else - list->tail = before; - } - - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( void ) - FT_List_Up( FT_List list, - FT_ListNode node ) - { - FT_ListNode before, after; - - - if ( !list || !node ) - return; - - before = node->prev; - after = node->next; - - /* check whether we are already on top of the list */ - if ( !before ) - return; - - before->next = after; - - if ( after ) - after->prev = before; - else - list->tail = before; - - node->prev = NULL; - node->next = list->head; - list->head->prev = node; - list->head = node; - } - - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_List_Iterate( FT_List list, - FT_List_Iterator iterator, - void* user ) - { - FT_ListNode cur; - FT_Error error = FT_Err_Ok; - - - if ( !list || !iterator ) - return FT_THROW( Invalid_Argument ); - - cur = list->head; - - while ( cur ) - { - FT_ListNode next = cur->next; - - - error = iterator( cur, user ); - if ( error ) - break; - - cur = next; - } - - return error; - } - - - /* documentation is in ftlist.h */ - - FT_EXPORT_DEF( void ) - FT_List_Finalize( FT_List list, - FT_List_Destructor destroy, - FT_Memory memory, - void* user ) - { - FT_ListNode cur; - - - if ( !list || !memory ) - return; - - cur = list->head; - while ( cur ) - { - FT_ListNode next = cur->next; - void* data = cur->data; - - - if ( destroy ) - destroy( memory, data, user ); - - FT_FREE( cur ); - cur = next; - } - - list->head = NULL; - list->tail = NULL; - } - - -/* END */ diff --git a/third_party/freetype/src/base/ftwinfnt.c b/third_party/freetype/src/base/ftwinfnt.c deleted file mode 100644 index 76a19af983ad7ca3baccc25ff34697febbc65449..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/ftwinfnt.c +++ /dev/null @@ -1,53 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftwinfnt.c */ -/* */ -/* FreeType API for accessing Windows FNT specific info (body). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_WINFONTS_H -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_WINFNT_H - - - /* documentation is in ftwinfnt.h */ - - FT_EXPORT_DEF( FT_Error ) - FT_Get_WinFNT_Header( FT_Face face, - FT_WinFNT_HeaderRec *header ) - { - FT_Service_WinFnt service; - FT_Error error; - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( !header ) - return FT_THROW( Invalid_Argument ); - - FT_FACE_LOOKUP_SERVICE( face, service, WINFNT ); - - if ( service ) - error = service->get_header( face, header ); - else - error = FT_THROW( Invalid_Argument ); - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/base/md5.c b/third_party/freetype/src/base/md5.c deleted file mode 100644 index 52d96accd30ea6c9056de2f029d78b9a3bf1d572..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/md5.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. - * MD5 Message-Digest Algorithm (RFC 1321). - * - * Homepage: - * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - * - * Author: - * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> - * - * This software was written by Alexander Peslyak in 2001. No copyright is - * claimed, and the software is hereby placed in the public domain. - * In case this attempt to disclaim copyright and place the software in the - * public domain is deemed null and void, then the software is - * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * (This is a heavily cut-down "BSD license".) - * - * This differs from Colin Plumb's older public domain implementation in that - * no exactly 32-bit integer data type is required (any 32-bit or wider - * unsigned integer data type will do), there's no compile-time endianness - * configuration, and the function prototypes match OpenSSL's. No code from - * Colin Plumb's implementation has been reused; this comment merely compares - * the properties of the two independent implementations. - * - * The primary goals of this implementation are portability and ease of use. - * It is meant to be fast, but not as fast as possible. Some known - * optimizations are not included to reduce source code size and avoid - * compile-time configuration. - */ - -#ifndef HAVE_OPENSSL - -#include <string.h> - -#include "md5.h" - -/* - * The basic MD5 functions. - * - * F and G are optimized compared to their RFC 1321 definitions for - * architectures that lack an AND-NOT instruction, just like in Colin Plumb's - * implementation. - */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) -#define H(x, y, z) (((x) ^ (y)) ^ (z)) -#define H2(x, y, z) ((x) ^ ((y) ^ (z))) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) - -/* - * The MD5 transformation for all four rounds. - */ -#define STEP(f, a, b, c, d, x, t, s) \ - (a) += f((b), (c), (d)) + (x) + (t); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ - (a) += (b); - -/* - * SET reads 4 input bytes in little-endian byte order and stores them - * in a properly aligned word in host byte order. - * - * The check for little-endian architectures that tolerate unaligned - * memory accesses is just an optimization. Nothing will break if it - * doesn't work. - */ -#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) -#define SET(n) \ - (*(MD5_u32plus *)&ptr[(n) * 4]) -#define GET(n) \ - SET(n) -#else -#define SET(n) \ - (ctx->block[(n)] = \ - (MD5_u32plus)ptr[(n) * 4] | \ - ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) -#define GET(n) \ - (ctx->block[(n)]) -#endif - -/* - * This processes one or more 64-byte data blocks, but does NOT update - * the bit counters. There are no alignment requirements. - */ -static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) -{ - const unsigned char *ptr; - MD5_u32plus a, b, c, d; - MD5_u32plus saved_a, saved_b, saved_c, saved_d; - - ptr = (const unsigned char *)data; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - - do { - saved_a = a; - saved_b = b; - saved_c = c; - saved_d = d; - -/* Round 1 */ - STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) - STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) - STEP(F, c, d, a, b, SET(2), 0x242070db, 17) - STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) - STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) - STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) - STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) - STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) - STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) - STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) - STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) - STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) - STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) - STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) - STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) - STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) - -/* Round 2 */ - STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) - STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) - STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) - STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) - STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) - STEP(G, d, a, b, c, GET(10), 0x02441453, 9) - STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) - STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) - STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) - STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) - STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) - STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) - STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) - STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) - STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) - STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) - -/* Round 3 */ - STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) - STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) - STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) - STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) - STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) - STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) - STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) - STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) - STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) - STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) - STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) - STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) - STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) - STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) - STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) - STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) - -/* Round 4 */ - STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) - STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) - STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) - STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) - STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) - STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) - STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) - STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) - STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) - STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) - STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) - STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) - STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) - STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) - STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) - STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) - - a += saved_a; - b += saved_b; - c += saved_c; - d += saved_d; - - ptr += 64; - } while (size -= 64); - - ctx->a = a; - ctx->b = b; - ctx->c = c; - ctx->d = d; - - return ptr; -} - -void MD5_Init(MD5_CTX *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - - ctx->lo = 0; - ctx->hi = 0; -} - -void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) -{ - MD5_u32plus saved_lo; - unsigned long used, available; - - saved_lo = ctx->lo; - if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) - ctx->hi++; - ctx->hi += size >> 29; - - used = saved_lo & 0x3f; - - if (used) { - available = 64 - used; - - if (size < available) { - memcpy(&ctx->buffer[used], data, size); - return; - } - - memcpy(&ctx->buffer[used], data, available); - data = (const unsigned char *)data + available; - size -= available; - body(ctx, ctx->buffer, 64); - } - - if (size >= 64) { - data = body(ctx, data, size & ~(unsigned long)0x3f); - size &= 0x3f; - } - - memcpy(ctx->buffer, data, size); -} - -void MD5_Final(unsigned char *result, MD5_CTX *ctx) -{ - unsigned long used, available; - - used = ctx->lo & 0x3f; - - ctx->buffer[used++] = 0x80; - - available = 64 - used; - - if (available < 8) { - memset(&ctx->buffer[used], 0, available); - body(ctx, ctx->buffer, 64); - used = 0; - available = 64; - } - - memset(&ctx->buffer[used], 0, available - 8); - - ctx->lo <<= 3; - ctx->buffer[56] = ctx->lo; - ctx->buffer[57] = ctx->lo >> 8; - ctx->buffer[58] = ctx->lo >> 16; - ctx->buffer[59] = ctx->lo >> 24; - ctx->buffer[60] = ctx->hi; - ctx->buffer[61] = ctx->hi >> 8; - ctx->buffer[62] = ctx->hi >> 16; - ctx->buffer[63] = ctx->hi >> 24; - - body(ctx, ctx->buffer, 64); - - result[0] = ctx->a; - result[1] = ctx->a >> 8; - result[2] = ctx->a >> 16; - result[3] = ctx->a >> 24; - result[4] = ctx->b; - result[5] = ctx->b >> 8; - result[6] = ctx->b >> 16; - result[7] = ctx->b >> 24; - result[8] = ctx->c; - result[9] = ctx->c >> 8; - result[10] = ctx->c >> 16; - result[11] = ctx->c >> 24; - result[12] = ctx->d; - result[13] = ctx->d >> 8; - result[14] = ctx->d >> 16; - result[15] = ctx->d >> 24; - - memset(ctx, 0, sizeof(*ctx)); -} - -#endif diff --git a/third_party/freetype/src/base/md5.h b/third_party/freetype/src/base/md5.h deleted file mode 100644 index 2da44bf355a3a00b5abd283792e53efad339b1f3..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/base/md5.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. - * MD5 Message-Digest Algorithm (RFC 1321). - * - * Homepage: - * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - * - * Author: - * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> - * - * This software was written by Alexander Peslyak in 2001. No copyright is - * claimed, and the software is hereby placed in the public domain. - * In case this attempt to disclaim copyright and place the software in the - * public domain is deemed null and void, then the software is - * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See md5.c for more information. - */ - -#ifdef HAVE_OPENSSL -#include <openssl/md5.h> -#elif !defined(_MD5_H) -#define _MD5_H - -/* Any 32-bit or wider unsigned integer data type will do */ -typedef unsigned int MD5_u32plus; - -typedef struct { - MD5_u32plus lo, hi; - MD5_u32plus a, b, c, d; - unsigned char buffer[64]; - MD5_u32plus block[16]; -} MD5_CTX; - -extern void MD5_Init(MD5_CTX *ctx); -extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); -extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); - -#endif diff --git a/third_party/freetype/src/cff/Jamfile b/third_party/freetype/src/cff/Jamfile deleted file mode 100644 index deec0792ce4e5448646c59eaf61c69158ddef603..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/Jamfile +++ /dev/null @@ -1,45 +0,0 @@ -# FreeType 2 src/cff Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) cff ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = cffcmap - cffdrivr - cffgload - cffload - cffobjs - cffparse - cffpic - cf2arrst - cf2blues - cf2error - cf2font - cf2ft - cf2hints - cf2intrp - cf2read - cf2stack - ; - } - else - { - _sources = cff ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/cff Jamfile diff --git a/third_party/freetype/src/cff/cf2arrst.c b/third_party/freetype/src/cff/cf2arrst.c deleted file mode 100644 index 89f3e9f1d741964fc0711e22746cd11799781fe5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2arrst.c +++ /dev/null @@ -1,241 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2arrst.c */ -/* */ -/* Adobe's code for Array Stacks (body). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2glue.h" -#include "cf2arrst.h" - -#include "cf2error.h" - - - /* - * CF2_ArrStack uses an error pointer, to enable shared errors. - * Shared errors are necessary when multiple objects allow the program - * to continue after detecting errors. Only the first error should be - * recorded. - */ - - FT_LOCAL_DEF( void ) - cf2_arrstack_init( CF2_ArrStack arrstack, - FT_Memory memory, - FT_Error* error, - size_t sizeItem ) - { - FT_ASSERT( arrstack != NULL ); - - /* initialize the structure */ - arrstack->memory = memory; - arrstack->error = error; - arrstack->sizeItem = sizeItem; - arrstack->allocated = 0; - arrstack->chunk = 10; /* chunks of 10 items */ - arrstack->count = 0; - arrstack->totalSize = 0; - arrstack->ptr = NULL; - } - - - FT_LOCAL_DEF( void ) - cf2_arrstack_finalize( CF2_ArrStack arrstack ) - { - FT_Memory memory = arrstack->memory; /* for FT_FREE */ - - - FT_ASSERT( arrstack != NULL ); - - arrstack->allocated = 0; - arrstack->count = 0; - arrstack->totalSize = 0; - - /* free the data buffer */ - FT_FREE( arrstack->ptr ); - } - - - /* allocate or reallocate the buffer size; */ - /* return false on memory error */ - static FT_Bool - cf2_arrstack_setNumElements( CF2_ArrStack arrstack, - size_t numElements ) - { - FT_ASSERT( arrstack != NULL ); - - { - FT_Error error = FT_Err_Ok; /* for FT_REALLOC */ - FT_Memory memory = arrstack->memory; /* for FT_REALLOC */ - - size_t newSize = numElements * arrstack->sizeItem; - - - if ( numElements > FT_LONG_MAX / arrstack->sizeItem ) - goto exit; - - - FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */ - - if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) ) - { - arrstack->allocated = numElements; - arrstack->totalSize = newSize; - - if ( arrstack->count > numElements ) - { - /* we truncated the list! */ - CF2_SET_ERROR( arrstack->error, Stack_Overflow ); - arrstack->count = numElements; - return FALSE; - } - - return TRUE; /* success */ - } - } - - exit: - /* if there's not already an error, store this one */ - CF2_SET_ERROR( arrstack->error, Out_Of_Memory ); - - return FALSE; - } - - - /* set the count, ensuring allocation is sufficient */ - FT_LOCAL_DEF( void ) - cf2_arrstack_setCount( CF2_ArrStack arrstack, - size_t numElements ) - { - FT_ASSERT( arrstack != NULL ); - - if ( numElements > arrstack->allocated ) - { - /* expand the allocation first */ - if ( !cf2_arrstack_setNumElements( arrstack, numElements ) ) - return; - } - - arrstack->count = numElements; - } - - - /* clear the count */ - FT_LOCAL_DEF( void ) - cf2_arrstack_clear( CF2_ArrStack arrstack ) - { - FT_ASSERT( arrstack != NULL ); - - arrstack->count = 0; - } - - - /* current number of items */ - FT_LOCAL_DEF( size_t ) - cf2_arrstack_size( const CF2_ArrStack arrstack ) - { - FT_ASSERT( arrstack != NULL ); - - return arrstack->count; - } - - - FT_LOCAL_DEF( void* ) - cf2_arrstack_getBuffer( const CF2_ArrStack arrstack ) - { - FT_ASSERT( arrstack != NULL ); - - return arrstack->ptr; - } - - - /* return pointer to the given element */ - FT_LOCAL_DEF( void* ) - cf2_arrstack_getPointer( const CF2_ArrStack arrstack, - size_t idx ) - { - void* newPtr; - - - FT_ASSERT( arrstack != NULL ); - - if ( idx >= arrstack->count ) - { - /* overflow */ - CF2_SET_ERROR( arrstack->error, Stack_Overflow ); - idx = 0; /* choose safe default */ - } - - newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem; - - return newPtr; - } - - - /* push (append) an element at the end of the list; */ - /* return false on memory error */ - /* TODO: should there be a length param for extra checking? */ - FT_LOCAL_DEF( void ) - cf2_arrstack_push( CF2_ArrStack arrstack, - const void* ptr ) - { - FT_ASSERT( arrstack != NULL ); - - if ( arrstack->count == arrstack->allocated ) - { - /* grow the buffer by one chunk */ - if ( !cf2_arrstack_setNumElements( - arrstack, arrstack->allocated + arrstack->chunk ) ) - { - /* on error, ignore the push */ - return; - } - } - - FT_ASSERT( ptr != NULL ); - - { - size_t offset = arrstack->count * arrstack->sizeItem; - void* newPtr = (FT_Byte*)arrstack->ptr + offset; - - - FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem ); - arrstack->count += 1; - } - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2arrst.h b/third_party/freetype/src/cff/cf2arrst.h deleted file mode 100644 index ff5ad8b1268c00329da83382bb56f620d8adb854..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2arrst.h +++ /dev/null @@ -1,100 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2arrst.h */ -/* */ -/* Adobe's code for Array Stacks (specification). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2ARRST_H__ -#define __CF2ARRST_H__ - - -#include "cf2error.h" - - -FT_BEGIN_HEADER - - - /* need to define the struct here (not opaque) so it can be allocated by */ - /* clients */ - typedef struct CF2_ArrStackRec_ - { - FT_Memory memory; - FT_Error* error; - - size_t sizeItem; /* bytes per element */ - size_t allocated; /* items allocated */ - size_t chunk; /* allocation increment in items */ - size_t count; /* number of elements allocated */ - size_t totalSize; /* total bytes allocated */ - - void* ptr; /* ptr to data */ - - } CF2_ArrStackRec, *CF2_ArrStack; - - - FT_LOCAL( void ) - cf2_arrstack_init( CF2_ArrStack arrstack, - FT_Memory memory, - FT_Error* error, - size_t sizeItem ); - FT_LOCAL( void ) - cf2_arrstack_finalize( CF2_ArrStack arrstack ); - - FT_LOCAL( void ) - cf2_arrstack_setCount( CF2_ArrStack arrstack, - size_t numElements ); - FT_LOCAL( void ) - cf2_arrstack_clear( CF2_ArrStack arrstack ); - FT_LOCAL( size_t ) - cf2_arrstack_size( const CF2_ArrStack arrstack ); - - FT_LOCAL( void* ) - cf2_arrstack_getBuffer( const CF2_ArrStack arrstack ); - FT_LOCAL( void* ) - cf2_arrstack_getPointer( const CF2_ArrStack arrstack, - size_t idx ); - - FT_LOCAL( void ) - cf2_arrstack_push( CF2_ArrStack arrstack, - const void* ptr ); - - -FT_END_HEADER - - -#endif /* __CF2ARRST_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2blues.c b/third_party/freetype/src/cff/cf2blues.c deleted file mode 100644 index 250f89e0df46dc96d6b9fb1fecb1c6fe9d0f5bdd..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2blues.c +++ /dev/null @@ -1,579 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2blues.c */ -/* */ -/* Adobe's code for handling Blue Zones (body). */ -/* */ -/* Copyright 2009-2014 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2blues.h" -#include "cf2hints.h" -#include "cf2font.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cf2blues - - - /* - * For blue values, the FreeType parser produces an array of integers, - * while the Adobe CFF engine produces an array of fixed. - * Define a macro to convert FreeType to fixed. - */ -#define cf2_blueToFixed( x ) cf2_intToFixed( x ) - - - FT_LOCAL_DEF( void ) - cf2_blues_init( CF2_Blues blues, - CF2_Font font ) - { - /* pointer to parsed font object */ - CFF_Decoder* decoder = font->decoder; - - CF2_Fixed zoneHeight; - CF2_Fixed maxZoneHeight = 0; - CF2_Fixed csUnitsPerPixel; - - size_t numBlueValues; - size_t numOtherBlues; - size_t numFamilyBlues; - size_t numFamilyOtherBlues; - - FT_Pos* blueValues; - FT_Pos* otherBlues; - FT_Pos* familyBlues; - FT_Pos* familyOtherBlues; - - size_t i; - CF2_Fixed emBoxBottom, emBoxTop; - -#if 0 - CF2_Int unitsPerEm = font->unitsPerEm; - - - if ( unitsPerEm == 0 ) - unitsPerEm = 1000; -#endif - - FT_ZERO( blues ); - blues->scale = font->innerTransform.d; - - cf2_getBlueMetrics( decoder, - &blues->blueScale, - &blues->blueShift, - &blues->blueFuzz ); - - cf2_getBlueValues( decoder, &numBlueValues, &blueValues ); - cf2_getOtherBlues( decoder, &numOtherBlues, &otherBlues ); - cf2_getFamilyBlues( decoder, &numFamilyBlues, &familyBlues ); - cf2_getFamilyOtherBlues( decoder, &numFamilyOtherBlues, &familyOtherBlues ); - - /* - * synthetic em box hint heuristic - * - * Apply this when ideographic dictionary (LanguageGroup 1) has no - * real alignment zones. Adobe tools generate dummy zones at -250 and - * 1100 for a 1000 unit em. Fonts with ICF-based alignment zones - * should not enable the heuristic. When the heuristic is enabled, - * the font's blue zones are ignored. - * - */ - - /* get em box from OS/2 typoAscender/Descender */ - /* TODO: FreeType does not parse these metrics. Skip them for now. */ -#if 0 - FCM_getHorizontalLineMetrics( &e, - font->font, - &ascender, - &descender, - &linegap ); - if ( ascender - descender == unitsPerEm ) - { - emBoxBottom = cf2_intToFixed( descender ); - emBoxTop = cf2_intToFixed( ascender ); - } - else -#endif - { - emBoxBottom = CF2_ICF_Bottom; - emBoxTop = CF2_ICF_Top; - } - - if ( cf2_getLanguageGroup( decoder ) == 1 && - ( numBlueValues == 0 || - ( numBlueValues == 4 && - cf2_blueToFixed( blueValues[0] ) < emBoxBottom && - cf2_blueToFixed( blueValues[1] ) < emBoxBottom && - cf2_blueToFixed( blueValues[2] ) > emBoxTop && - cf2_blueToFixed( blueValues[3] ) > emBoxTop ) ) ) - { - /* - * Construct hint edges suitable for synthetic ghost hints at top - * and bottom of em box. +-CF2_MIN_COUNTER allows for unhinted - * features above or below the last hinted edge. This also gives a - * net 1 pixel boost to the height of ideographic glyphs. - * - * Note: Adjust synthetic hints outward by epsilon (0x.0001) to - * avoid interference. E.g., some fonts have real hints at - * 880 and -120. - */ - - blues->emBoxBottomEdge.csCoord = emBoxBottom - CF2_FIXED_EPSILON; - blues->emBoxBottomEdge.dsCoord = cf2_fixedRound( - FT_MulFix( - blues->emBoxBottomEdge.csCoord, - blues->scale ) ) - - CF2_MIN_COUNTER; - blues->emBoxBottomEdge.scale = blues->scale; - blues->emBoxBottomEdge.flags = CF2_GhostBottom | - CF2_Locked | - CF2_Synthetic; - - blues->emBoxTopEdge.csCoord = emBoxTop + CF2_FIXED_EPSILON + - 2 * font->darkenY; - blues->emBoxTopEdge.dsCoord = cf2_fixedRound( - FT_MulFix( - blues->emBoxTopEdge.csCoord, - blues->scale ) ) + - CF2_MIN_COUNTER; - blues->emBoxTopEdge.scale = blues->scale; - blues->emBoxTopEdge.flags = CF2_GhostTop | - CF2_Locked | - CF2_Synthetic; - - blues->doEmBoxHints = TRUE; /* enable the heuristic */ - - return; - } - - /* copy `BlueValues' and `OtherBlues' to a combined array of top and */ - /* bottom zones */ - for ( i = 0; i < numBlueValues; i += 2 ) - { - blues->zone[blues->count].csBottomEdge = - cf2_blueToFixed( blueValues[i] ); - blues->zone[blues->count].csTopEdge = - cf2_blueToFixed( blueValues[i + 1] ); - - zoneHeight = blues->zone[blues->count].csTopEdge - - blues->zone[blues->count].csBottomEdge; - - if ( zoneHeight < 0 ) - { - FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" )); - continue; /* reject this zone */ - } - - if ( zoneHeight > maxZoneHeight ) - { - /* take maximum before darkening adjustment */ - /* so overshoot suppression point doesn't change */ - maxZoneHeight = zoneHeight; - } - - /* adjust both edges of top zone upward by twice darkening amount */ - if ( i != 0 ) - { - blues->zone[blues->count].csTopEdge += 2 * font->darkenY; - blues->zone[blues->count].csBottomEdge += 2 * font->darkenY; - } - - /* first `BlueValue' is bottom zone; others are top */ - if ( i == 0 ) - { - blues->zone[blues->count].bottomZone = - TRUE; - blues->zone[blues->count].csFlatEdge = - blues->zone[blues->count].csTopEdge; - } - else - { - blues->zone[blues->count].bottomZone = - FALSE; - blues->zone[blues->count].csFlatEdge = - blues->zone[blues->count].csBottomEdge; - } - - blues->count += 1; - } - - for ( i = 0; i < numOtherBlues; i += 2 ) - { - blues->zone[blues->count].csBottomEdge = - cf2_blueToFixed( otherBlues[i] ); - blues->zone[blues->count].csTopEdge = - cf2_blueToFixed( otherBlues[i + 1] ); - - zoneHeight = blues->zone[blues->count].csTopEdge - - blues->zone[blues->count].csBottomEdge; - - if ( zoneHeight < 0 ) - { - FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" )); - continue; /* reject this zone */ - } - - if ( zoneHeight > maxZoneHeight ) - { - /* take maximum before darkening adjustment */ - /* so overshoot suppression point doesn't change */ - maxZoneHeight = zoneHeight; - } - - /* Note: bottom zones are not adjusted for darkening amount */ - - /* all OtherBlues are bottom zone */ - blues->zone[blues->count].bottomZone = - TRUE; - blues->zone[blues->count].csFlatEdge = - blues->zone[blues->count].csTopEdge; - - blues->count += 1; - } - - /* Adjust for FamilyBlues */ - - /* Search for the nearest flat edge in `FamilyBlues' or */ - /* `FamilyOtherBlues'. According to the Black Book, any matching edge */ - /* must be within one device pixel */ - - csUnitsPerPixel = FT_DivFix( cf2_intToFixed( 1 ), blues->scale ); - - /* loop on all zones in this font */ - for ( i = 0; i < blues->count; i++ ) - { - size_t j; - CF2_Fixed minDiff; - CF2_Fixed flatFamilyEdge, diff; - /* value for this font */ - CF2_Fixed flatEdge = blues->zone[i].csFlatEdge; - - - if ( blues->zone[i].bottomZone ) - { - /* In a bottom zone, the top edge is the flat edge. */ - /* Search `FamilyOtherBlues' for bottom zones; look for closest */ - /* Family edge that is within the one pixel threshold. */ - - minDiff = CF2_FIXED_MAX; - - for ( j = 0; j < numFamilyOtherBlues; j += 2 ) - { - /* top edge */ - flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] ); - - diff = cf2_fixedAbs( flatEdge - flatFamilyEdge ); - - if ( diff < minDiff && diff < csUnitsPerPixel ) - { - blues->zone[i].csFlatEdge = flatFamilyEdge; - minDiff = diff; - - if ( diff == 0 ) - break; - } - } - - /* check the first member of FamilyBlues, which is a bottom zone */ - if ( numFamilyBlues >= 2 ) - { - /* top edge */ - flatFamilyEdge = cf2_blueToFixed( familyBlues[1] ); - - diff = cf2_fixedAbs( flatEdge - flatFamilyEdge ); - - if ( diff < minDiff && diff < csUnitsPerPixel ) - blues->zone[i].csFlatEdge = flatFamilyEdge; - } - } - else - { - /* In a top zone, the bottom edge is the flat edge. */ - /* Search `FamilyBlues' for top zones; skip first zone, which is a */ - /* bottom zone; look for closest Family edge that is within the */ - /* one pixel threshold */ - - minDiff = CF2_FIXED_MAX; - - for ( j = 2; j < numFamilyBlues; j += 2 ) - { - /* bottom edge */ - flatFamilyEdge = cf2_blueToFixed( familyBlues[j] ); - - /* adjust edges of top zone upward by twice darkening amount */ - flatFamilyEdge += 2 * font->darkenY; /* bottom edge */ - - diff = cf2_fixedAbs( flatEdge - flatFamilyEdge ); - - if ( diff < minDiff && diff < csUnitsPerPixel ) - { - blues->zone[i].csFlatEdge = flatFamilyEdge; - minDiff = diff; - - if ( diff == 0 ) - break; - } - } - } - } - - /* TODO: enforce separation of zones, including BlueFuzz */ - - /* Adjust BlueScale; similar to AdjustBlueScale() in coretype */ - /* `bcsetup.c'. */ - - if ( maxZoneHeight > 0 ) - { - if ( blues->blueScale > FT_DivFix( cf2_intToFixed( 1 ), - maxZoneHeight ) ) - { - /* clamp at maximum scale */ - blues->blueScale = FT_DivFix( cf2_intToFixed( 1 ), - maxZoneHeight ); - } - - /* - * TODO: Revisit the bug fix for 613448. The minimum scale - * requirement catches a number of library fonts. For - * example, with default BlueScale (.039625) and 0.4 minimum, - * the test below catches any font with maxZoneHeight < 10.1. - * There are library fonts ranging from 2 to 10 that get - * caught, including e.g., Eurostile LT Std Medium with - * maxZoneHeight of 6. - * - */ -#if 0 - if ( blueScale < .4 / maxZoneHeight ) - { - tetraphilia_assert( 0 ); - /* clamp at minimum scale, per bug 0613448 fix */ - blueScale = .4 / maxZoneHeight; - } -#endif - - } - - /* - * Suppress overshoot and boost blue zones at small sizes. Boost - * amount varies linearly from 0.5 pixel near 0 to 0 pixel at - * blueScale cutoff. - * Note: This boost amount is different from the coretype heuristic. - * - */ - - if ( blues->scale < blues->blueScale ) - { - blues->suppressOvershoot = TRUE; - - /* Change rounding threshold for `dsFlatEdge'. */ - /* Note: constant changed from 0.5 to 0.6 to avoid a problem with */ - /* 10ppem Arial */ - - blues->boost = cf2_floatToFixed( .6 ) - - FT_MulDiv( cf2_floatToFixed ( .6 ), - blues->scale, - blues->blueScale ); - if ( blues->boost > 0x7FFF ) - { - /* boost must remain less than 0.5, or baseline could go negative */ - blues->boost = 0x7FFF; - } - } - - /* boost and darkening have similar effects; don't do both */ - if ( font->stemDarkened ) - blues->boost = 0; - - /* set device space alignment for each zone; */ - /* apply boost amount before rounding flat edge */ - - for ( i = 0; i < blues->count; i++ ) - { - if ( blues->zone[i].bottomZone ) - blues->zone[i].dsFlatEdge = cf2_fixedRound( - FT_MulFix( - blues->zone[i].csFlatEdge, - blues->scale ) - - blues->boost ); - else - blues->zone[i].dsFlatEdge = cf2_fixedRound( - FT_MulFix( - blues->zone[i].csFlatEdge, - blues->scale ) + - blues->boost ); - } - } - - - /* - * Check whether `stemHint' is captured by one of the blue zones. - * - * Zero, one or both edges may be valid; only valid edges can be - * captured. For compatibility with CoolType, search top and bottom - * zones in the same pass (see `BlueLock'). If a hint is captured, - * return true and position the edge(s) in one of 3 ways: - * - * 1) If `BlueScale' suppresses overshoot, position the captured edge - * at the flat edge of the zone. - * 2) If overshoot is not suppressed and `BlueShift' requires - * overshoot, position the captured edge a minimum of 1 device pixel - * from the flat edge. - * 3) If overshoot is not suppressed or required, position the captured - * edge at the nearest device pixel. - * - */ - FT_LOCAL_DEF( FT_Bool ) - cf2_blues_capture( const CF2_Blues blues, - CF2_Hint bottomHintEdge, - CF2_Hint topHintEdge ) - { - /* TODO: validate? */ - CF2_Fixed csFuzz = blues->blueFuzz; - - /* new position of captured edge */ - CF2_Fixed dsNew; - - /* amount that hint is moved when positioned */ - CF2_Fixed dsMove = 0; - - FT_Bool captured = FALSE; - CF2_UInt i; - - - /* assert edge flags are consistent */ - FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) && - !cf2_hint_isBottom( topHintEdge ) ); - - /* TODO: search once without blue fuzz for compatibility with coretype? */ - for ( i = 0; i < blues->count; i++ ) - { - if ( blues->zone[i].bottomZone && - cf2_hint_isBottom( bottomHintEdge ) ) - { - if ( ( blues->zone[i].csBottomEdge - csFuzz ) <= - bottomHintEdge->csCoord && - bottomHintEdge->csCoord <= - ( blues->zone[i].csTopEdge + csFuzz ) ) - { - /* bottom edge captured by bottom zone */ - - if ( blues->suppressOvershoot ) - dsNew = blues->zone[i].dsFlatEdge; - - else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >= - blues->blueShift ) - { - /* guarantee minimum of 1 pixel overshoot */ - dsNew = FT_MIN( - cf2_fixedRound( bottomHintEdge->dsCoord ), - blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) ); - } - - else - { - /* simply round captured edge */ - dsNew = cf2_fixedRound( bottomHintEdge->dsCoord ); - } - - dsMove = dsNew - bottomHintEdge->dsCoord; - captured = TRUE; - - break; - } - } - - if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) ) - { - if ( ( blues->zone[i].csBottomEdge - csFuzz ) <= - topHintEdge->csCoord && - topHintEdge->csCoord <= - ( blues->zone[i].csTopEdge + csFuzz ) ) - { - /* top edge captured by top zone */ - - if ( blues->suppressOvershoot ) - dsNew = blues->zone[i].dsFlatEdge; - - else if ( ( topHintEdge->csCoord - blues->zone[i].csBottomEdge ) >= - blues->blueShift ) - { - /* guarantee minimum of 1 pixel overshoot */ - dsNew = FT_MAX( - cf2_fixedRound( topHintEdge->dsCoord ), - blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) ); - } - - else - { - /* simply round captured edge */ - dsNew = cf2_fixedRound( topHintEdge->dsCoord ); - } - - dsMove = dsNew - topHintEdge->dsCoord; - captured = TRUE; - - break; - } - } - } - - if ( captured ) - { - /* move both edges and flag them `locked' */ - if ( cf2_hint_isValid( bottomHintEdge ) ) - { - bottomHintEdge->dsCoord += dsMove; - cf2_hint_lock( bottomHintEdge ); - } - - if ( cf2_hint_isValid( topHintEdge ) ) - { - topHintEdge->dsCoord += dsMove; - cf2_hint_lock( topHintEdge ); - } - } - - return captured; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2blues.h b/third_party/freetype/src/cff/cf2blues.h deleted file mode 100644 index 2f38fcad8f5ce932a6ecc07f05a9b97f4ce6c53a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2blues.h +++ /dev/null @@ -1,185 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2blues.h */ -/* */ -/* Adobe's code for handling Blue Zones (specification). */ -/* */ -/* Copyright 2009-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - - /* - * A `CF2_Blues' object stores the blue zones (horizontal alignment - * zones) of a font. These are specified in the CFF private dictionary - * by `BlueValues', `OtherBlues', `FamilyBlues', and `FamilyOtherBlues'. - * Each zone is defined by a top and bottom edge in character space. - * Further, each zone is either a top zone or a bottom zone, as recorded - * by `bottomZone'. - * - * The maximum number of `BlueValues' and `FamilyBlues' is 7 each. - * However, these are combined to produce a total of 7 zones. - * Similarly, the maximum number of `OtherBlues' and `FamilyOtherBlues' - * is 5 and these are combined to produce an additional 5 zones. - * - * Blue zones are used to `capture' hints and force them to a common - * alignment point. This alignment is recorded in device space in - * `dsFlatEdge'. Except for this value, a `CF2_Blues' object could be - * constructed independently of scaling. Construction may occur once - * the matrix is known. Other features implemented in the Capture - * method are overshoot suppression, overshoot enforcement, and Blue - * Boost. - * - * Capture is determined by `BlueValues' and `OtherBlues', but the - * alignment point may be adjusted to the scaled flat edge of - * `FamilyBlues' or `FamilyOtherBlues'. No alignment is done to the - * curved edge of a zone. - * - */ - - -#ifndef __CF2BLUES_H__ -#define __CF2BLUES_H__ - - -#include "cf2glue.h" - - -FT_BEGIN_HEADER - - - /* - * `CF2_Hint' is shared by `cf2hints.h' and - * `cf2blues.h', but `cf2blues.h' depends on - * `cf2hints.h', so define it here. Note: The typedef is in - * `cf2glue.h'. - * - */ - enum - { - CF2_GhostBottom = 0x1, /* a single bottom edge */ - CF2_GhostTop = 0x2, /* a single top edge */ - CF2_PairBottom = 0x4, /* the bottom edge of a stem hint */ - CF2_PairTop = 0x8, /* the top edge of a stem hint */ - CF2_Locked = 0x10, /* this edge has been aligned */ - /* by a blue zone */ - CF2_Synthetic = 0x20 /* this edge was synthesized */ - }; - - - /* - * Default value for OS/2 typoAscender/Descender when their difference - * is not equal to `unitsPerEm'. The default is based on -250 and 1100 - * in `CF2_Blues', assuming 1000 units per em here. - * - */ - enum - { - CF2_ICF_Top = cf2_intToFixed( 880 ), - CF2_ICF_Bottom = cf2_intToFixed( -120 ) - }; - - - /* - * Constant used for hint adjustment and for synthetic em box hint - * placement. - */ -#define CF2_MIN_COUNTER cf2_floatToFixed( 0.5 ) - - - /* shared typedef is in cf2glue.h */ - struct CF2_HintRec_ - { - CF2_UInt flags; /* attributes of the edge */ - size_t index; /* index in original stem hint array */ - /* (if not synthetic) */ - CF2_Fixed csCoord; - CF2_Fixed dsCoord; - CF2_Fixed scale; - }; - - - typedef struct CF2_BlueRec_ - { - CF2_Fixed csBottomEdge; - CF2_Fixed csTopEdge; - CF2_Fixed csFlatEdge; /* may be from either local or Family zones */ - CF2_Fixed dsFlatEdge; /* top edge of bottom zone or bottom edge */ - /* of top zone (rounded) */ - FT_Bool bottomZone; - - } CF2_BlueRec; - - - /* max total blue zones is 12 */ - enum - { - CF2_MAX_BLUES = 7, - CF2_MAX_OTHERBLUES = 5 - }; - - - typedef struct CF2_BluesRec_ - { - CF2_Fixed scale; - CF2_UInt count; - FT_Bool suppressOvershoot; - FT_Bool doEmBoxHints; - - CF2_Fixed blueScale; - CF2_Fixed blueShift; - CF2_Fixed blueFuzz; - - CF2_Fixed boost; - - CF2_HintRec emBoxTopEdge; - CF2_HintRec emBoxBottomEdge; - - CF2_BlueRec zone[CF2_MAX_BLUES + CF2_MAX_OTHERBLUES]; - - } CF2_BluesRec, *CF2_Blues; - - - FT_LOCAL( void ) - cf2_blues_init( CF2_Blues blues, - CF2_Font font ); - FT_LOCAL( FT_Bool ) - cf2_blues_capture( const CF2_Blues blues, - CF2_Hint bottomHintEdge, - CF2_Hint topHintEdge ); - - -FT_END_HEADER - - -#endif /* __CF2BLUES_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2error.c b/third_party/freetype/src/cff/cf2error.c deleted file mode 100644 index b5595a3d1f3eb02da19a1407743613b0b8c345f6..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2error.c +++ /dev/null @@ -1,52 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2error.c */ -/* */ -/* Adobe's code for error handling (body). */ -/* */ -/* Copyright 2006-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include "cf2error.h" - - - FT_LOCAL_DEF( void ) - cf2_setError( FT_Error* error, - FT_Error value ) - { - if ( error && *error == 0 ) - *error = value; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2error.h b/third_party/freetype/src/cff/cf2error.h deleted file mode 100644 index 6453ebcb7b85f3baae0cec275bb92665532d676d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2error.h +++ /dev/null @@ -1,119 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2error.h */ -/* */ -/* Adobe's code for error handling (specification). */ -/* */ -/* Copyright 2006-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2ERROR_H__ -#define __CF2ERROR_H__ - - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX CF2_Err_ -#define FT_ERR_BASE FT_Mod_Err_CF2 - - -#include FT_ERRORS_H -#include "cf2ft.h" - - -FT_BEGIN_HEADER - - - /* - * A poor-man error facility. - * - * This code being written in vanilla C, doesn't have the luxury of a - * language-supported exception mechanism such as the one available in - * Java. Instead, we are stuck with using error codes that must be - * carefully managed and preserved. However, it is convenient for us to - * model our error mechanism on a Java-like exception mechanism. - * When we assign an error code we are thus `throwing' an error. - * - * The perservation of an error code is done by coding convention. - * Upon a function call if the error code is anything other than - * `FT_Err_Ok', which is guaranteed to be zero, we - * will return without altering that error. This will allow the - * error to propogate and be handled at the appropriate location in - * the code. - * - * This allows a style of code where the error code is initialized - * up front and a block of calls are made with the error code only - * being checked after the block. If a new error occurs, the original - * error will be preserved and a functional no-op should result in any - * subsequent function that has an initial error code not equal to - * `FT_Err_Ok'. - * - * Errors are encoded by calling the `FT_THROW' macro. For example, - * - * { - * FT_Error e; - * - * - * ... - * e = FT_THROW( Out_Of_Memory ); - * } - * - */ - - - /* Set error code to a particular value. */ - FT_LOCAL( void ) - cf2_setError( FT_Error* error, - FT_Error value ); - - - /* - * A macro that conditionally sets an error code. - * - * This macro will first check whether `error' is set; - * if not, it will set it to `e'. - * - */ -#define CF2_SET_ERROR( error, e ) \ - cf2_setError( error, FT_THROW( e ) ) - - -FT_END_HEADER - - -#endif /* __CF2ERROR_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2fixed.h b/third_party/freetype/src/cff/cf2fixed.h deleted file mode 100644 index d6d9faf8e541f8f80c3a09daf2b4d14fdad21e63..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2fixed.h +++ /dev/null @@ -1,95 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2fixed.h */ -/* */ -/* Adobe's code for Fixed Point Mathematics (specification only). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2FIXED_H__ -#define __CF2FIXED_H__ - - -FT_BEGIN_HEADER - - - /* rasterizer integer and fixed point arithmetic must be 32-bit */ - -#define CF2_Fixed CF2_F16Dot16 - typedef FT_Int32 CF2_Frac; /* 2.30 fixed point */ - - -#define CF2_FIXED_MAX ( (CF2_Fixed)0x7FFFFFFFL ) -#define CF2_FIXED_MIN ( (CF2_Fixed)0x80000000L ) -#define CF2_FIXED_ONE 0x10000L -#define CF2_FIXED_EPSILON 0x0001 - - /* in C 89, left and right shift of negative numbers is */ - /* implementation specific behaviour in the general case */ - -#define cf2_intToFixed( i ) \ - ( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) ) -#define cf2_fixedToInt( x ) \ - ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) ) -#define cf2_fixedRound( x ) \ - ( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) ) -#define cf2_floatToFixed( f ) \ - ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) ) -#define cf2_fixedAbs( x ) \ - ( (x) < 0 ? -(x) : (x) ) -#define cf2_fixedFloor( x ) \ - ( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) ) -#define cf2_fixedFraction( x ) \ - ( (x) - cf2_fixedFloor( x ) ) -#define cf2_fracToFixed( x ) \ - ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 ) \ - : ( ( (x) + 0x2000 ) >> 14 ) ) - - - /* signed numeric types */ - typedef enum CF2_NumberType_ - { - CF2_NumberFixed, /* 16.16 */ - CF2_NumberFrac, /* 2.30 */ - CF2_NumberInt /* 32.0 */ - - } CF2_NumberType; - - -FT_END_HEADER - - -#endif /* __CF2FIXED_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2font.c b/third_party/freetype/src/cff/cf2font.c deleted file mode 100644 index 83fd348f2db6456cf861dff0b75075524eb84312..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2font.c +++ /dev/null @@ -1,512 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2font.c */ -/* */ -/* Adobe's code for font instances (body). */ -/* */ -/* Copyright 2007-2014 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_CALC_H - -#include "cf2ft.h" - -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2error.h" -#include "cf2intrp.h" - - - /* Compute a stem darkening amount in character space. */ - static void - cf2_computeDarkening( CF2_Fixed emRatio, - CF2_Fixed ppem, - CF2_Fixed stemWidth, - CF2_Fixed* darkenAmount, - CF2_Fixed boldenAmount, - FT_Bool stemDarkened, - FT_Int* darkenParams ) - { - /* - * Total darkening amount is computed in 1000 unit character space - * using the modified 5 part curve as Adobe's Avalon rasterizer. - * The darkening amount is smaller for thicker stems. - * It becomes zero when the stem is thicker than 2.333 pixels. - * - * By default, we use - * - * darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels, - * darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels, - * darkenAmount = 0 pixel if scaledStem >= 2.333 pixels, - * - * and piecewise linear in-between: - * - * - * darkening - * ^ - * | - * | (x1,y1) - * |--------+ - * | \ - * | \ - * | \ (x3,y3) - * | +----------+ - * | (x2,y2) \ - * | \ - * | \ - * | +----------------- - * | (x4,y4) - * +---------------------------------------------> stem - * thickness - * - * - * This corresponds to the following values for the - * `darkening-parameters' property: - * - * (x1, y1) = (500, 400) - * (x2, y2) = (1000, 275) - * (x3, y3) = (1667, 275) - * (x4, y4) = (2333, 0) - * - */ - - /* Internal calculations are done in units per thousand for */ - /* convenience. The x axis is scaled stem width in */ - /* thousandths of a pixel. That is, 1000 is 1 pixel. */ - /* The y axis is darkening amount in thousandths of a pixel.*/ - /* In the code, below, dividing by ppem and */ - /* adjusting for emRatio converts darkenAmount to character */ - /* space (font units). */ - CF2_Fixed stemWidthPer1000, scaledStem; - FT_Int logBase2; - - - *darkenAmount = 0; - - if ( boldenAmount == 0 && !stemDarkened ) - return; - - /* protect against range problems and divide by zero */ - if ( emRatio < cf2_floatToFixed( .01 ) ) - return; - - if ( stemDarkened ) - { - FT_Int x1 = darkenParams[0]; - FT_Int y1 = darkenParams[1]; - FT_Int x2 = darkenParams[2]; - FT_Int y2 = darkenParams[3]; - FT_Int x3 = darkenParams[4]; - FT_Int y3 = darkenParams[5]; - FT_Int x4 = darkenParams[6]; - FT_Int y4 = darkenParams[7]; - - - /* convert from true character space to 1000 unit character space; */ - /* add synthetic emboldening effect */ - - /* `stemWidthPer1000' will not overflow for a legitimate font */ - - stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio ); - - /* `scaledStem' can easily overflow, so we must clamp its maximum */ - /* value; the test doesn't need to be precise, but must be */ - /* conservative. The clamp value (default 2333) where */ - /* `darkenAmount' is zero is well below the overflow value of */ - /* 32767. */ - /* */ - /* FT_MSB computes the integer part of the base 2 logarithm. The */ - /* number of bits for the product is 1 or 2 more than the sum of */ - /* logarithms; remembering that the 16 lowest bits of the fraction */ - /* are dropped this is correct to within a factor of almost 4. */ - /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */ - /* is flagged as possible overflow because 0xFF.FFFF * 0xFF.FFFF = */ - /* 0xFFFF.FE00 is also 23+23. */ - - logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) + - FT_MSB( (FT_UInt32)ppem ); - - if ( logBase2 >= 46 ) - /* possible overflow */ - scaledStem = cf2_intToFixed( x4 ); - else - scaledStem = FT_MulFix( stemWidthPer1000, ppem ); - - /* now apply the darkening parameters */ - - if ( scaledStem < cf2_intToFixed( x1 ) ) - *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem ); - - else if ( scaledStem < cf2_intToFixed( x2 ) ) - { - FT_Int xdelta = x2 - x1; - FT_Int ydelta = y2 - y1; - FT_Int x = stemWidthPer1000 - - FT_DivFix( cf2_intToFixed( x1 ), ppem ); - - - if ( !xdelta ) - goto Try_x3; - - *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) + - FT_DivFix( cf2_intToFixed( y1 ), ppem ); - } - - else if ( scaledStem < cf2_intToFixed( x3 ) ) - { - Try_x3: - { - FT_Int xdelta = x3 - x2; - FT_Int ydelta = y3 - y2; - FT_Int x = stemWidthPer1000 - - FT_DivFix( cf2_intToFixed( x2 ), ppem ); - - - if ( !xdelta ) - goto Try_x4; - - *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) + - FT_DivFix( cf2_intToFixed( y2 ), ppem ); - } - } - - else if ( scaledStem < cf2_intToFixed( x4 ) ) - { - Try_x4: - { - FT_Int xdelta = x4 - x3; - FT_Int ydelta = y4 - y3; - FT_Int x = stemWidthPer1000 - - FT_DivFix( cf2_intToFixed( x3 ), ppem ); - - - if ( !xdelta ) - goto Use_y4; - - *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) + - FT_DivFix( cf2_intToFixed( y3 ), ppem ); - } - } - - else - { - Use_y4: - *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem ); - } - - /* use half the amount on each side and convert back to true */ - /* character space */ - *darkenAmount = FT_DivFix( *darkenAmount, 2 * emRatio ); - } - - /* add synthetic emboldening effect in character space */ - *darkenAmount += boldenAmount / 2; - } - - - /* set up values for the current FontDict and matrix */ - - /* caller's transform is adjusted for subpixel positioning */ - static void - cf2_font_setup( CF2_Font font, - const CF2_Matrix* transform ) - { - /* pointer to parsed font object */ - CFF_Decoder* decoder = font->decoder; - - FT_Bool needExtraSetup = FALSE; - - /* character space units */ - CF2_Fixed boldenX = font->syntheticEmboldeningAmountX; - CF2_Fixed boldenY = font->syntheticEmboldeningAmountY; - - CFF_SubFont subFont; - CF2_Fixed ppem; - - - /* clear previous error */ - font->error = FT_Err_Ok; - - /* if a CID fontDict has changed, we need to recompute some cached */ - /* data */ - subFont = cf2_getSubfont( decoder ); - if ( font->lastSubfont != subFont ) - { - font->lastSubfont = subFont; - needExtraSetup = TRUE; - } - - /* if ppem has changed, we need to recompute some cached data */ - /* note: because of CID font matrix concatenation, ppem and transform */ - /* do not necessarily track. */ - ppem = cf2_getPpemY( decoder ); - if ( font->ppem != ppem ) - { - font->ppem = ppem; - needExtraSetup = TRUE; - } - - /* copy hinted flag on each call */ - font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted ); - - /* determine if transform has changed; */ - /* include Fontmatrix but ignore translation */ - if ( ft_memcmp( transform, - &font->currentTransform, - 4 * sizeof ( CF2_Fixed ) ) != 0 ) - { - /* save `key' information for `cache of one' matrix data; */ - /* save client transform, without the translation */ - font->currentTransform = *transform; - font->currentTransform.tx = - font->currentTransform.ty = cf2_intToFixed( 0 ); - - /* TODO: FreeType transform is simple scalar; for now, use identity */ - /* for outer */ - font->innerTransform = *transform; - font->outerTransform.a = - font->outerTransform.d = cf2_intToFixed( 1 ); - font->outerTransform.b = - font->outerTransform.c = cf2_intToFixed( 0 ); - - needExtraSetup = TRUE; - } - - /* - * font->darkened is set to true if there is a stem darkening request or - * the font is synthetic emboldened. - * font->darkened controls whether to adjust blue zones, winding order, - * and hinting. - * - */ - if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) ) - { - font->stemDarkened = - (FT_Bool)( font->renderingFlags & CF2_FlagsDarkened ); - - /* blue zones depend on darkened flag */ - needExtraSetup = TRUE; - } - - /* recompute variables that are dependent on transform or FontDict or */ - /* darken flag */ - if ( needExtraSetup ) - { - /* StdVW is found in the private dictionary; */ - /* recompute darkening amounts whenever private dictionary or */ - /* transform change */ - /* Note: a rendering flag turns darkening on or off, so we want to */ - /* store the `on' amounts; */ - /* darkening amount is computed in character space */ - /* TODO: testing size-dependent darkening here; */ - /* what to do for rotations? */ - - CF2_Fixed emRatio; - CF2_Fixed stdHW; - CF2_Int unitsPerEm = font->unitsPerEm; - - - if ( unitsPerEm == 0 ) - unitsPerEm = 1000; - - ppem = FT_MAX( cf2_intToFixed( 4 ), - font->ppem ); /* use minimum ppem of 4 */ - -#if 0 - /* since vstem is measured in the x-direction, we use the `a' member */ - /* of the fontMatrix */ - emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->a ); -#endif - - /* Freetype does not preserve the fontMatrix when parsing; use */ - /* unitsPerEm instead. */ - /* TODO: check precision of this */ - emRatio = cf2_intToFixed( 1000 ) / unitsPerEm; - font->stdVW = cf2_getStdVW( decoder ); - - if ( font->stdVW <= 0 ) - font->stdVW = FT_DivFix( cf2_intToFixed( 75 ), emRatio ); - - if ( boldenX > 0 ) - { - /* Ensure that boldenX is at least 1 pixel for synthetic bold font */ - /* (similar to what Avalon does) */ - boldenX = FT_MAX( boldenX, - FT_DivFix( cf2_intToFixed( unitsPerEm ), ppem ) ); - - /* Synthetic emboldening adds at least 1 pixel to darkenX, while */ - /* stem darkening adds at most half pixel. Since the purpose of */ - /* stem darkening (readability at small sizes) is met with */ - /* synthetic emboldening, no need to add stem darkening for a */ - /* synthetic bold font. */ - cf2_computeDarkening( emRatio, - ppem, - font->stdVW, - &font->darkenX, - boldenX, - FALSE, - font->darkenParams ); - } - else - cf2_computeDarkening( emRatio, - ppem, - font->stdVW, - &font->darkenX, - 0, - font->stemDarkened, - font->darkenParams ); - -#if 0 - /* since hstem is measured in the y-direction, we use the `d' member */ - /* of the fontMatrix */ - /* TODO: use the same units per em as above; check this */ - emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->d ); -#endif - - /* set the default stem width, because it must be the same for all */ - /* family members; */ - /* choose a constant for StdHW that depends on font contrast */ - stdHW = cf2_getStdHW( decoder ); - - if ( stdHW > 0 && font->stdVW > 2 * stdHW ) - font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio ); - else - { - /* low contrast font gets less hstem darkening */ - font->stdHW = FT_DivFix( cf2_intToFixed( 110 ), emRatio ); - } - - cf2_computeDarkening( emRatio, - ppem, - font->stdHW, - &font->darkenY, - boldenY, - font->stemDarkened, - font->darkenParams ); - - if ( font->darkenX != 0 || font->darkenY != 0 ) - font->darkened = TRUE; - else - font->darkened = FALSE; - - font->reverseWinding = FALSE; /* initial expectation is CCW */ - - /* compute blue zones for this instance */ - cf2_blues_init( &font->blues, font ); - } - } - - - /* equivalent to AdobeGetOutline */ - FT_LOCAL_DEF( FT_Error ) - cf2_getGlyphOutline( CF2_Font font, - CF2_Buffer charstring, - const CF2_Matrix* transform, - CF2_F16Dot16* glyphWidth ) - { - FT_Error lastError = FT_Err_Ok; - - FT_Vector translation; - -#if 0 - FT_Vector advancePoint; -#endif - - CF2_Fixed advWidth = 0; - FT_Bool needWinding; - - - /* Note: use both integer and fraction for outlines. This allows bbox */ - /* to come out directly. */ - - translation.x = transform->tx; - translation.y = transform->ty; - - /* set up values based on transform */ - cf2_font_setup( font, transform ); - if ( font->error ) - goto exit; /* setup encountered an error */ - - /* reset darken direction */ - font->reverseWinding = FALSE; - - /* winding order only affects darkening */ - needWinding = font->darkened; - - while ( 1 ) - { - /* reset output buffer */ - cf2_outline_reset( &font->outline ); - - /* build the outline, passing the full translation */ - cf2_interpT2CharString( font, - charstring, - (CF2_OutlineCallbacks)&font->outline, - &translation, - FALSE, - 0, - 0, - &advWidth ); - - if ( font->error ) - goto exit; - - if ( !needWinding ) - break; - - /* check winding order */ - if ( font->outline.root.windingMomentum >= 0 ) /* CFF is CCW */ - break; - - /* invert darkening and render again */ - /* TODO: this should be a parameter to getOutline-computeOffset */ - font->reverseWinding = TRUE; - - needWinding = FALSE; /* exit after next iteration */ - } - - /* finish storing client outline */ - cf2_outline_close( &font->outline ); - - exit: - /* FreeType just wants the advance width; there is no translation */ - *glyphWidth = advWidth; - - /* free resources and collect errors from objects we've used */ - cf2_setError( &font->error, lastError ); - - return font->error; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2font.h b/third_party/freetype/src/cff/cf2font.h deleted file mode 100644 index 86cf02f49d1bca17bcd0330d2c997146dd2aac60..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2font.h +++ /dev/null @@ -1,121 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2font.h */ -/* */ -/* Adobe's code for font instances (specification). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2FONT_H__ -#define __CF2FONT_H__ - - -#include "cf2ft.h" -#include "cf2blues.h" - - -FT_BEGIN_HEADER - - -#define CF2_OPERAND_STACK_SIZE 48 -#define CF2_MAX_SUBR 16 /* maximum subroutine nesting; */ - /* only 10 are allowed but there exist */ - /* fonts like `HiraKakuProN-W3.ttf' */ - /* (Hiragino Kaku Gothic ProN W3; */ - /* 8.2d6e1; 2014-12-19) that exceed */ - /* this limit */ - - - /* typedef is in `cf2glue.h' */ - struct CF2_FontRec_ - { - FT_Memory memory; - FT_Error error; /* shared error for this instance */ - - CF2_RenderingFlags renderingFlags; - - /* variables that depend on Transform: */ - /* the following have zero translation; */ - /* inner * outer = font * original */ - - CF2_Matrix currentTransform; /* original client matrix */ - CF2_Matrix innerTransform; /* for hinting; erect, scaled */ - CF2_Matrix outerTransform; /* post hinting; includes rotations */ - CF2_Fixed ppem; /* transform-dependent */ - - CF2_Int unitsPerEm; - - CF2_Fixed syntheticEmboldeningAmountX; /* character space units */ - CF2_Fixed syntheticEmboldeningAmountY; /* character space units */ - - /* FreeType related members */ - CF2_OutlineRec outline; /* freetype glyph outline functions */ - CFF_Decoder* decoder; - CFF_SubFont lastSubfont; /* FreeType parsed data; */ - /* top font or subfont */ - - /* these flags can vary from one call to the next */ - FT_Bool hinted; - FT_Bool darkened; /* true if stemDarkened or synthetic bold */ - /* i.e. darkenX != 0 || darkenY != 0 */ - FT_Bool stemDarkened; - - FT_Int darkenParams[8]; /* 1000 unit character space */ - - /* variables that depend on both FontDict and Transform */ - CF2_Fixed stdVW; /* in character space; depends on dict entry */ - CF2_Fixed stdHW; /* in character space; depends on dict entry */ - CF2_Fixed darkenX; /* character space units */ - CF2_Fixed darkenY; /* depends on transform */ - /* and private dict (StdVW) */ - FT_Bool reverseWinding; /* darken assuming */ - /* counterclockwise winding */ - - CF2_BluesRec blues; /* computed zone data */ - }; - - - FT_LOCAL( FT_Error ) - cf2_getGlyphOutline( CF2_Font font, - CF2_Buffer charstring, - const CF2_Matrix* transform, - CF2_F16Dot16* glyphWidth ); - - -FT_END_HEADER - - -#endif /* __CF2FONT_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2ft.c b/third_party/freetype/src/cff/cf2ft.c deleted file mode 100644 index d2544a234516e6355f339dc2ed7cb99efd2defa5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2ft.c +++ /dev/null @@ -1,700 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2ft.c */ -/* */ -/* FreeType Glue Component to Adobe's Interpreter (body). */ -/* */ -/* Copyright 2013-2014 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2font.h" -#include "cf2error.h" - - -#define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */ - - - /* - * This check should avoid most internal overflow cases. Clients should - * generally respond to `Glyph_Too_Big' by getting a glyph outline - * at EM size, scaling it and filling it as a graphics operation. - * - */ - static FT_Error - cf2_checkTransform( const CF2_Matrix* transform, - CF2_Int unitsPerEm ) - { - CF2_Fixed maxScale; - - - FT_ASSERT( unitsPerEm > 0 ); - - if ( transform->a <= 0 || transform->d <= 0 ) - return FT_THROW( Invalid_Size_Handle ); - - FT_ASSERT( transform->b == 0 && transform->c == 0 ); - FT_ASSERT( transform->tx == 0 && transform->ty == 0 ); - - if ( unitsPerEm > 0x7FFF ) - return FT_THROW( Glyph_Too_Big ); - - maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) ); - - if ( transform->a > maxScale || transform->d > maxScale ) - return FT_THROW( Glyph_Too_Big ); - - return FT_Err_Ok; - } - - - static void - cf2_setGlyphWidth( CF2_Outline outline, - CF2_Fixed width ) - { - CFF_Decoder* decoder = outline->decoder; - - - FT_ASSERT( decoder ); - - decoder->glyph_width = cf2_fixedToInt( width ); - } - - - /* Clean up font instance. */ - static void - cf2_free_instance( void* ptr ) - { - CF2_Font font = (CF2_Font)ptr; - - - if ( font ) - { - FT_Memory memory = font->memory; - - - (void)memory; - } - } - - - /********************************************/ - /* */ - /* functions for handling client outline; */ - /* FreeType uses coordinates in 26.6 format */ - /* */ - /********************************************/ - - static void - cf2_builder_moveTo( CF2_OutlineCallbacks callbacks, - const CF2_CallbackParams params ) - { - /* downcast the object pointer */ - CF2_Outline outline = (CF2_Outline)callbacks; - CFF_Builder* builder; - - (void)params; /* only used in debug mode */ - - - FT_ASSERT( outline && outline->decoder ); - FT_ASSERT( params->op == CF2_PathOpMoveTo ); - - builder = &outline->decoder->builder; - - /* note: two successive moves simply close the contour twice */ - cff_builder_close_contour( builder ); - builder->path_begun = 0; - } - - - static void - cf2_builder_lineTo( CF2_OutlineCallbacks callbacks, - const CF2_CallbackParams params ) - { - FT_Error error; - - /* downcast the object pointer */ - CF2_Outline outline = (CF2_Outline)callbacks; - CFF_Builder* builder; - - - FT_ASSERT( outline && outline->decoder ); - FT_ASSERT( params->op == CF2_PathOpLineTo ); - - builder = &outline->decoder->builder; - - if ( !builder->path_begun ) - { - /* record the move before the line; also check points and set */ - /* `path_begun' */ - error = cff_builder_start_point( builder, - params->pt0.x, - params->pt0.y ); - if ( error ) - { - if ( !*callbacks->error ) - *callbacks->error = error; - return; - } - } - - /* `cff_builder_add_point1' includes a check_points call for one point */ - error = cff_builder_add_point1( builder, - params->pt1.x, - params->pt1.y ); - if ( error ) - { - if ( !*callbacks->error ) - *callbacks->error = error; - return; - } - } - - - static void - cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks, - const CF2_CallbackParams params ) - { - FT_Error error; - - /* downcast the object pointer */ - CF2_Outline outline = (CF2_Outline)callbacks; - CFF_Builder* builder; - - - FT_ASSERT( outline && outline->decoder ); - FT_ASSERT( params->op == CF2_PathOpCubeTo ); - - builder = &outline->decoder->builder; - - if ( !builder->path_begun ) - { - /* record the move before the line; also check points and set */ - /* `path_begun' */ - error = cff_builder_start_point( builder, - params->pt0.x, - params->pt0.y ); - if ( error ) - { - if ( !*callbacks->error ) - *callbacks->error = error; - return; - } - } - - /* prepare room for 3 points: 2 off-curve, 1 on-curve */ - error = cff_check_points( builder, 3 ); - if ( error ) - { - if ( !*callbacks->error ) - *callbacks->error = error; - return; - } - - cff_builder_add_point( builder, - params->pt1.x, - params->pt1.y, 0 ); - cff_builder_add_point( builder, - params->pt2.x, - params->pt2.y, 0 ); - cff_builder_add_point( builder, - params->pt3.x, - params->pt3.y, 1 ); - } - - - static void - cf2_outline_init( CF2_Outline outline, - FT_Memory memory, - FT_Error* error ) - { - FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) ); - - outline->root.memory = memory; - outline->root.error = error; - - outline->root.moveTo = cf2_builder_moveTo; - outline->root.lineTo = cf2_builder_lineTo; - outline->root.cubeTo = cf2_builder_cubeTo; - } - - - /* get scaling and hint flag from GlyphSlot */ - static void - cf2_getScaleAndHintFlag( CFF_Decoder* decoder, - CF2_Fixed* x_scale, - CF2_Fixed* y_scale, - FT_Bool* hinted, - FT_Bool* scaled ) - { - FT_ASSERT( decoder && decoder->builder.glyph ); - - /* note: FreeType scale includes a factor of 64 */ - *hinted = decoder->builder.glyph->hint; - *scaled = decoder->builder.glyph->scaled; - - if ( *hinted ) - { - *x_scale = ( decoder->builder.glyph->x_scale + 32 ) / 64; - *y_scale = ( decoder->builder.glyph->y_scale + 32 ) / 64; - } - else - { - /* for unhinted outlines, `cff_slot_load' does the scaling, */ - /* thus render at `unity' scale */ - - *x_scale = 0x0400; /* 1/64 as 16.16 */ - *y_scale = 0x0400; - } - } - - - /* get units per em from `FT_Face' */ - /* TODO: should handle font matrix concatenation? */ - static FT_UShort - cf2_getUnitsPerEm( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->builder.face ); - FT_ASSERT( decoder->builder.face->root.units_per_EM ); - - return decoder->builder.face->root.units_per_EM; - } - - - /* Main entry point: Render one glyph. */ - FT_LOCAL_DEF( FT_Error ) - cf2_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len ) - { - FT_Memory memory; - FT_Error error = FT_Err_Ok; - CF2_Font font; - - - FT_ASSERT( decoder && decoder->cff ); - - memory = decoder->builder.memory; - - /* CF2 data is saved here across glyphs */ - font = (CF2_Font)decoder->cff->cf2_instance.data; - - /* on first glyph, allocate instance structure */ - if ( decoder->cff->cf2_instance.data == NULL ) - { - decoder->cff->cf2_instance.finalizer = - (FT_Generic_Finalizer)cf2_free_instance; - - if ( FT_ALLOC( decoder->cff->cf2_instance.data, - sizeof ( CF2_FontRec ) ) ) - return FT_THROW( Out_Of_Memory ); - - font = (CF2_Font)decoder->cff->cf2_instance.data; - - font->memory = memory; - - /* initialize a client outline, to be shared by each glyph rendered */ - cf2_outline_init( &font->outline, font->memory, &font->error ); - } - - /* save decoder; it is a stack variable and will be different on each */ - /* call */ - font->decoder = decoder; - font->outline.decoder = decoder; - - { - /* build parameters for Adobe engine */ - - CFF_Builder* builder = &decoder->builder; - CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); - - /* local error */ - FT_Error error2 = FT_Err_Ok; - CF2_BufferRec buf; - CF2_Matrix transform; - CF2_F16Dot16 glyphWidth; - - FT_Bool hinted; - FT_Bool scaled; - - - /* FreeType has already looked up the GID; convert to */ - /* `RegionBuffer', assuming that the input has been validated */ - FT_ASSERT( charstring_base + charstring_len >= charstring_base ); - - FT_ZERO( &buf ); - buf.start = - buf.ptr = charstring_base; - buf.end = charstring_base + charstring_len; - - FT_ZERO( &transform ); - - cf2_getScaleAndHintFlag( decoder, - &transform.a, - &transform.d, - &hinted, - &scaled ); - - font->renderingFlags = 0; - if ( hinted ) - font->renderingFlags |= CF2_FlagsHinted; - if ( scaled && !driver->no_stem_darkening ) - font->renderingFlags |= CF2_FlagsDarkened; - - font->darkenParams[0] = driver->darken_params[0]; - font->darkenParams[1] = driver->darken_params[1]; - font->darkenParams[2] = driver->darken_params[2]; - font->darkenParams[3] = driver->darken_params[3]; - font->darkenParams[4] = driver->darken_params[4]; - font->darkenParams[5] = driver->darken_params[5]; - font->darkenParams[6] = driver->darken_params[6]; - font->darkenParams[7] = driver->darken_params[7]; - - /* now get an outline for this glyph; */ - /* also get units per em to validate scale */ - font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder ); - - if ( scaled ) - { - error2 = cf2_checkTransform( &transform, font->unitsPerEm ); - if ( error2 ) - return error2; - } - - error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth ); - if ( error2 ) - return FT_ERR( Invalid_File_Format ); - - cf2_setGlyphWidth( &font->outline, glyphWidth ); - - return FT_Err_Ok; - } - } - - - /* get pointer to current FreeType subfont (based on current glyphID) */ - FT_LOCAL_DEF( CFF_SubFont ) - cf2_getSubfont( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - return decoder->current_subfont; - } - - - /* get `y_ppem' from `CFF_Size' */ - FT_LOCAL_DEF( CF2_Fixed ) - cf2_getPpemY( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && - decoder->builder.face && - decoder->builder.face->root.size ); - - /* - * Note that `y_ppem' can be zero if there wasn't a call to - * `FT_Set_Char_Size' or something similar. However, this isn't a - * problem since we come to this place in the code only if - * FT_LOAD_NO_SCALE is set (the other case gets caught by - * `cf2_checkTransform'). The ppem value is needed to compute the stem - * darkening, which is disabled for getting the unscaled outline. - * - */ - return cf2_intToFixed( - decoder->builder.face->root.size->metrics.y_ppem ); - } - - - /* get standard stem widths for the current subfont; */ - /* FreeType stores these as integer font units */ - /* (note: variable names seem swapped) */ - FT_LOCAL_DEF( CF2_Fixed ) - cf2_getStdVW( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - return cf2_intToFixed( - decoder->current_subfont->private_dict.standard_height ); - } - - - FT_LOCAL_DEF( CF2_Fixed ) - cf2_getStdHW( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - return cf2_intToFixed( - decoder->current_subfont->private_dict.standard_width ); - } - - - /* note: FreeType stores 1000 times the actual value for `BlueScale' */ - FT_LOCAL_DEF( void ) - cf2_getBlueMetrics( CFF_Decoder* decoder, - CF2_Fixed* blueScale, - CF2_Fixed* blueShift, - CF2_Fixed* blueFuzz ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - *blueScale = FT_DivFix( - decoder->current_subfont->private_dict.blue_scale, - cf2_intToFixed( 1000 ) ); - *blueShift = cf2_intToFixed( - decoder->current_subfont->private_dict.blue_shift ); - *blueFuzz = cf2_intToFixed( - decoder->current_subfont->private_dict.blue_fuzz ); - } - - - /* get blue values counts and arrays; the FreeType parser has validated */ - /* the counts and verified that each is an even number */ - FT_LOCAL_DEF( void ) - cf2_getBlueValues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - *count = decoder->current_subfont->private_dict.num_blue_values; - *data = (FT_Pos*) - &decoder->current_subfont->private_dict.blue_values; - } - - - FT_LOCAL_DEF( void ) - cf2_getOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - *count = decoder->current_subfont->private_dict.num_other_blues; - *data = (FT_Pos*) - &decoder->current_subfont->private_dict.other_blues; - } - - - FT_LOCAL_DEF( void ) - cf2_getFamilyBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - *count = decoder->current_subfont->private_dict.num_family_blues; - *data = (FT_Pos*) - &decoder->current_subfont->private_dict.family_blues; - } - - - FT_LOCAL_DEF( void ) - cf2_getFamilyOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - *count = decoder->current_subfont->private_dict.num_family_other_blues; - *data = (FT_Pos*) - &decoder->current_subfont->private_dict.family_other_blues; - } - - - FT_LOCAL_DEF( CF2_Int ) - cf2_getLanguageGroup( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - return decoder->current_subfont->private_dict.language_group; - } - - - /* convert unbiased subroutine index to `CF2_Buffer' and */ - /* return 0 on success */ - FT_LOCAL_DEF( CF2_Int ) - cf2_initGlobalRegionBuffer( CFF_Decoder* decoder, - CF2_UInt idx, - CF2_Buffer buf ) - { - FT_ASSERT( decoder ); - - FT_ZERO( buf ); - - idx += (CF2_UInt)decoder->globals_bias; - if ( idx >= decoder->num_globals ) - return TRUE; /* error */ - - FT_ASSERT( decoder->globals ); - - buf->start = - buf->ptr = decoder->globals[idx]; - buf->end = decoder->globals[idx + 1]; - - return FALSE; /* success */ - } - - - /* convert AdobeStandardEncoding code to CF2_Buffer; */ - /* used for seac component */ - FT_LOCAL_DEF( FT_Error ) - cf2_getSeacComponent( CFF_Decoder* decoder, - CF2_Int code, - CF2_Buffer buf ) - { - CF2_Int gid; - FT_Byte* charstring; - FT_ULong len; - FT_Error error; - - - FT_ASSERT( decoder ); - - FT_ZERO( buf ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Incremental fonts don't necessarily have valid charsets. */ - /* They use the character code, not the glyph index, in this case. */ - if ( decoder->builder.face->root.internal->incremental_interface ) - gid = code; - else -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code ); - if ( gid < 0 ) - return FT_THROW( Invalid_Glyph_Format ); - } - - error = cff_get_glyph_data( decoder->builder.face, - (CF2_UInt)gid, - &charstring, - &len ); - /* TODO: for now, just pass the FreeType error through */ - if ( error ) - return error; - - /* assume input has been validated */ - FT_ASSERT( charstring + len >= charstring ); - - buf->start = charstring; - buf->end = charstring + len; - buf->ptr = buf->start; - - return FT_Err_Ok; - } - - - FT_LOCAL_DEF( void ) - cf2_freeSeacComponent( CFF_Decoder* decoder, - CF2_Buffer buf ) - { - FT_ASSERT( decoder ); - - cff_free_glyph_data( decoder->builder.face, - (FT_Byte**)&buf->start, - (FT_ULong)( buf->end - buf->start ) ); - } - - - FT_LOCAL_DEF( CF2_Int ) - cf2_initLocalRegionBuffer( CFF_Decoder* decoder, - CF2_UInt idx, - CF2_Buffer buf ) - { - FT_ASSERT( decoder ); - - FT_ZERO( buf ); - - idx += (CF2_UInt)decoder->locals_bias; - if ( idx >= decoder->num_locals ) - return TRUE; /* error */ - - FT_ASSERT( decoder->locals ); - - buf->start = - buf->ptr = decoder->locals[idx]; - buf->end = decoder->locals[idx + 1]; - - return FALSE; /* success */ - } - - - FT_LOCAL_DEF( CF2_Fixed ) - cf2_getDefaultWidthX( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - return cf2_intToFixed( - decoder->current_subfont->private_dict.default_width ); - } - - - FT_LOCAL_DEF( CF2_Fixed ) - cf2_getNominalWidthX( CFF_Decoder* decoder ) - { - FT_ASSERT( decoder && decoder->current_subfont ); - - return cf2_intToFixed( - decoder->current_subfont->private_dict.nominal_width ); - } - - - FT_LOCAL_DEF( void ) - cf2_outline_reset( CF2_Outline outline ) - { - CFF_Decoder* decoder = outline->decoder; - - - FT_ASSERT( decoder ); - - outline->root.windingMomentum = 0; - - FT_GlyphLoader_Rewind( decoder->builder.loader ); - } - - - FT_LOCAL_DEF( void ) - cf2_outline_close( CF2_Outline outline ) - { - CFF_Decoder* decoder = outline->decoder; - - - FT_ASSERT( decoder ); - - cff_builder_close_contour( &decoder->builder ); - - FT_GlyphLoader_Add( decoder->builder.loader ); - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2ft.h b/third_party/freetype/src/cff/cf2ft.h deleted file mode 100644 index 3073df382f7d10ff0144de91edc27479b9148584..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2ft.h +++ /dev/null @@ -1,147 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2ft.h */ -/* */ -/* FreeType Glue Component to Adobe's Interpreter (specification). */ -/* */ -/* Copyright 2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2FT_H__ -#define __CF2FT_H__ - - -#include "cf2types.h" - - - /* TODO: disable asserts for now */ -#define CF2_NDEBUG - - -#include FT_SYSTEM_H - -#include "cf2glue.h" -#include "cffgload.h" /* for CFF_Decoder */ - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - cf2_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len ); - - FT_LOCAL( CFF_SubFont ) - cf2_getSubfont( CFF_Decoder* decoder ); - - - FT_LOCAL( CF2_Fixed ) - cf2_getPpemY( CFF_Decoder* decoder ); - FT_LOCAL( CF2_Fixed ) - cf2_getStdVW( CFF_Decoder* decoder ); - FT_LOCAL( CF2_Fixed ) - cf2_getStdHW( CFF_Decoder* decoder ); - - FT_LOCAL( void ) - cf2_getBlueMetrics( CFF_Decoder* decoder, - CF2_Fixed* blueScale, - CF2_Fixed* blueShift, - CF2_Fixed* blueFuzz ); - FT_LOCAL( void ) - cf2_getBlueValues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); - FT_LOCAL( void ) - cf2_getOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); - FT_LOCAL( void ) - cf2_getFamilyBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); - FT_LOCAL( void ) - cf2_getFamilyOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); - - FT_LOCAL( CF2_Int ) - cf2_getLanguageGroup( CFF_Decoder* decoder ); - - FT_LOCAL( CF2_Int ) - cf2_initGlobalRegionBuffer( CFF_Decoder* decoder, - CF2_UInt idx, - CF2_Buffer buf ); - FT_LOCAL( FT_Error ) - cf2_getSeacComponent( CFF_Decoder* decoder, - CF2_Int code, - CF2_Buffer buf ); - FT_LOCAL( void ) - cf2_freeSeacComponent( CFF_Decoder* decoder, - CF2_Buffer buf ); - FT_LOCAL( CF2_Int ) - cf2_initLocalRegionBuffer( CFF_Decoder* decoder, - CF2_UInt idx, - CF2_Buffer buf ); - - FT_LOCAL( CF2_Fixed ) - cf2_getDefaultWidthX( CFF_Decoder* decoder ); - FT_LOCAL( CF2_Fixed ) - cf2_getNominalWidthX( CFF_Decoder* decoder ); - - - /* - * FreeType client outline - * - * process output from the charstring interpreter - */ - typedef struct CF2_OutlineRec_ - { - CF2_OutlineCallbacksRec root; /* base class must be first */ - CFF_Decoder* decoder; - - } CF2_OutlineRec, *CF2_Outline; - - - FT_LOCAL( void ) - cf2_outline_reset( CF2_Outline outline ); - FT_LOCAL( void ) - cf2_outline_close( CF2_Outline outline ); - - -FT_END_HEADER - - -#endif /* __CF2FT_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2glue.h b/third_party/freetype/src/cff/cf2glue.h deleted file mode 100644 index a24da39e93cad080f4ee5f9cccecf3ff5e950a07..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2glue.h +++ /dev/null @@ -1,144 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2glue.h */ -/* */ -/* Adobe's code for shared stuff (specification only). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2GLUE_H__ -#define __CF2GLUE_H__ - - -/* common includes for other modules */ -#include "cf2error.h" -#include "cf2fixed.h" -#include "cf2arrst.h" -#include "cf2read.h" - - -FT_BEGIN_HEADER - - - /* rendering parameters */ - - /* apply hints to rendered glyphs */ -#define CF2_FlagsHinted 1 - /* for testing */ -#define CF2_FlagsDarkened 2 - - /* type for holding the flags */ - typedef CF2_Int CF2_RenderingFlags; - - - /* elements of a glyph outline */ - typedef enum CF2_PathOp_ - { - CF2_PathOpMoveTo = 1, /* change the current point */ - CF2_PathOpLineTo = 2, /* line */ - CF2_PathOpQuadTo = 3, /* quadratic curve */ - CF2_PathOpCubeTo = 4 /* cubic curve */ - - } CF2_PathOp; - - - /* a matrix of fixed point values */ - typedef struct CF2_Matrix_ - { - CF2_F16Dot16 a; - CF2_F16Dot16 b; - CF2_F16Dot16 c; - CF2_F16Dot16 d; - CF2_F16Dot16 tx; - CF2_F16Dot16 ty; - - } CF2_Matrix; - - - /* these typedefs are needed by more than one header file */ - /* and gcc compiler doesn't allow redefinition */ - typedef struct CF2_FontRec_ CF2_FontRec, *CF2_Font; - typedef struct CF2_HintRec_ CF2_HintRec, *CF2_Hint; - - - /* A common structure for all callback parameters. */ - /* */ - /* Some members may be unused. For example, `pt0' is not used for */ - /* `moveTo' and `pt3' is not used for `quadTo'. The initial point `pt0' */ - /* is included for each path element for generality; curve conversions */ - /* need it. The `op' parameter allows one function to handle multiple */ - /* element types. */ - - typedef struct CF2_CallbackParamsRec_ - { - FT_Vector pt0; - FT_Vector pt1; - FT_Vector pt2; - FT_Vector pt3; - - CF2_Int op; - - } CF2_CallbackParamsRec, *CF2_CallbackParams; - - - /* forward reference */ - typedef struct CF2_OutlineCallbacksRec_ CF2_OutlineCallbacksRec, - *CF2_OutlineCallbacks; - - /* callback function pointers */ - typedef void - (*CF2_Callback_Type)( CF2_OutlineCallbacks callbacks, - const CF2_CallbackParams params ); - - - struct CF2_OutlineCallbacksRec_ - { - CF2_Callback_Type moveTo; - CF2_Callback_Type lineTo; - CF2_Callback_Type quadTo; - CF2_Callback_Type cubeTo; - - CF2_Int windingMomentum; /* for winding order detection */ - - FT_Memory memory; - FT_Error* error; - }; - - -FT_END_HEADER - - -#endif /* __CF2GLUE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2hints.c b/third_party/freetype/src/cff/cf2hints.c deleted file mode 100644 index 0e27000210d468953c4bc3127756d5f6059ce3cd..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2hints.c +++ /dev/null @@ -1,1847 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2hints.c */ -/* */ -/* Adobe's code for handling CFF hints (body). */ -/* */ -/* Copyright 2007-2014 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2hints.h" -#include "cf2intrp.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cf2hints - - - typedef struct CF2_HintMoveRec_ - { - size_t j; /* index of upper hint map edge */ - CF2_Fixed moveUp; /* adjustment to optimum position */ - - } CF2_HintMoveRec, *CF2_HintMove; - - - /* Compute angular momentum for winding order detection. It is called */ - /* for all lines and curves, but not necessarily in element order. */ - static CF2_Int - cf2_getWindingMomentum( CF2_Fixed x1, - CF2_Fixed y1, - CF2_Fixed x2, - CF2_Fixed y2 ) - { - /* cross product of pt1 position from origin with pt2 position from */ - /* pt1; we reduce the precision so that the result fits into 32 bits */ - - return ( x1 >> 16 ) * ( ( y2 - y1 ) >> 16 ) - - ( y1 >> 16 ) * ( ( x2 - x1 ) >> 16 ); - } - - - /* - * Construct from a StemHint; this is used as a parameter to - * `cf2_blues_capture'. - * `hintOrigin' is the character space displacement of a seac accent. - * Adjust stem hint for darkening here. - * - */ - static void - cf2_hint_init( CF2_Hint hint, - const CF2_ArrStack stemHintArray, - size_t indexStemHint, - const CF2_Font font, - CF2_Fixed hintOrigin, - CF2_Fixed scale, - FT_Bool bottom ) - { - CF2_Fixed width; - const CF2_StemHintRec* stemHint; - - - FT_ZERO( hint ); - - stemHint = (const CF2_StemHintRec*)cf2_arrstack_getPointer( - stemHintArray, - indexStemHint ); - - width = stemHint->max - stemHint->min; - - if ( width == cf2_intToFixed( -21 ) ) - { - /* ghost bottom */ - - if ( bottom ) - { - hint->csCoord = stemHint->max; - hint->flags = CF2_GhostBottom; - } - else - hint->flags = 0; - } - - else if ( width == cf2_intToFixed( -20 ) ) - { - /* ghost top */ - - if ( bottom ) - hint->flags = 0; - else - { - hint->csCoord = stemHint->min; - hint->flags = CF2_GhostTop; - } - } - - else if ( width < 0 ) - { - /* inverted pair */ - - /* - * Hints with negative widths were produced by an early version of a - * non-Adobe font tool. The Type 2 spec allows edge (ghost) hints - * with negative widths, but says - * - * All other negative widths have undefined meaning. - * - * CoolType has a silent workaround that negates the hint width; for - * permissive mode, we do the same here. - * - * Note: Such fonts cannot use ghost hints, but should otherwise work. - * Note: Some poor hints in our faux fonts can produce negative - * widths at some blends. For example, see a light weight of - * `u' in ASerifMM. - * - */ - if ( bottom ) - { - hint->csCoord = stemHint->max; - hint->flags = CF2_PairBottom; - } - else - { - hint->csCoord = stemHint->min; - hint->flags = CF2_PairTop; - } - } - - else - { - /* normal pair */ - - if ( bottom ) - { - hint->csCoord = stemHint->min; - hint->flags = CF2_PairBottom; - } - else - { - hint->csCoord = stemHint->max; - hint->flags = CF2_PairTop; - } - } - - /* Now that ghost hints have been detected, adjust this edge for */ - /* darkening. Bottoms are not changed; tops are incremented by twice */ - /* `darkenY'. */ - if ( cf2_hint_isTop( hint ) ) - hint->csCoord += 2 * font->darkenY; - - hint->csCoord += hintOrigin; - hint->scale = scale; - hint->index = indexStemHint; /* index in original stem hint array */ - - /* if original stem hint has been used, use the same position */ - if ( hint->flags != 0 && stemHint->used ) - { - if ( cf2_hint_isTop( hint ) ) - hint->dsCoord = stemHint->maxDS; - else - hint->dsCoord = stemHint->minDS; - - cf2_hint_lock( hint ); - } - else - hint->dsCoord = FT_MulFix( hint->csCoord, scale ); - } - - - /* initialize an invalid hint map element */ - static void - cf2_hint_initZero( CF2_Hint hint ) - { - FT_ZERO( hint ); - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hint_isValid( const CF2_Hint hint ) - { - return (FT_Bool)( hint->flags != 0 ); - } - - - static FT_Bool - cf2_hint_isPair( const CF2_Hint hint ) - { - return (FT_Bool)( ( hint->flags & - ( CF2_PairBottom | CF2_PairTop ) ) != 0 ); - } - - - static FT_Bool - cf2_hint_isPairTop( const CF2_Hint hint ) - { - return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 ); - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hint_isTop( const CF2_Hint hint ) - { - return (FT_Bool)( ( hint->flags & - ( CF2_PairTop | CF2_GhostTop ) ) != 0 ); - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hint_isBottom( const CF2_Hint hint ) - { - return (FT_Bool)( ( hint->flags & - ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 ); - } - - - static FT_Bool - cf2_hint_isLocked( const CF2_Hint hint ) - { - return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 ); - } - - - static FT_Bool - cf2_hint_isSynthetic( const CF2_Hint hint ) - { - return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 ); - } - - - FT_LOCAL_DEF( void ) - cf2_hint_lock( CF2_Hint hint ) - { - hint->flags |= CF2_Locked; - } - - - FT_LOCAL_DEF( void ) - cf2_hintmap_init( CF2_HintMap hintmap, - CF2_Font font, - CF2_HintMap initialMap, - CF2_ArrStack hintMoves, - CF2_Fixed scale ) - { - FT_ZERO( hintmap ); - - /* copy parameters from font instance */ - hintmap->hinted = font->hinted; - hintmap->scale = scale; - hintmap->font = font; - hintmap->initialHintMap = initialMap; - /* will clear in `cf2_hintmap_adjustHints' */ - hintmap->hintMoves = hintMoves; - } - - - static FT_Bool - cf2_hintmap_isValid( const CF2_HintMap hintmap ) - { - return hintmap->isValid; - } - - - /* transform character space coordinate to device space using hint map */ - static CF2_Fixed - cf2_hintmap_map( CF2_HintMap hintmap, - CF2_Fixed csCoord ) - { - if ( hintmap->count == 0 || ! hintmap->hinted ) - { - /* there are no hints; use uniform scale and zero offset */ - return FT_MulFix( csCoord, hintmap->scale ); - } - else - { - /* start linear search from last hit */ - CF2_UInt i = hintmap->lastIndex; - - FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES ); - - /* search up */ - while ( i < hintmap->count - 1 && - csCoord >= hintmap->edge[i + 1].csCoord ) - i += 1; - - /* search down */ - while ( i > 0 && csCoord < hintmap->edge[i].csCoord ) - i -= 1; - - hintmap->lastIndex = i; - - if ( i == 0 && csCoord < hintmap->edge[0].csCoord ) - { - /* special case for points below first edge: use uniform scale */ - return FT_MulFix( csCoord - hintmap->edge[0].csCoord, - hintmap->scale ) + - hintmap->edge[0].dsCoord; - } - else - { - /* - * Note: entries with duplicate csCoord are allowed. - * Use edge[i], the highest entry where csCoord >= entry[i].csCoord - */ - return FT_MulFix( csCoord - hintmap->edge[i].csCoord, - hintmap->edge[i].scale ) + - hintmap->edge[i].dsCoord; - } - } - } - - - /* - * This hinting policy moves a hint pair in device space so that one of - * its two edges is on a device pixel boundary (its fractional part is - * zero). `cf2_hintmap_insertHint' guarantees no overlap in CS - * space. Ensure here that there is no overlap in DS. - * - * In the first pass, edges are adjusted relative to adjacent hints. - * Those that are below have already been adjusted. Those that are - * above have not yet been adjusted. If a hint above blocks an - * adjustment to an optimal position, we will try again in a second - * pass. The second pass is top-down. - * - */ - - static void - cf2_hintmap_adjustHints( CF2_HintMap hintmap ) - { - size_t i, j; - - - cf2_arrstack_clear( hintmap->hintMoves ); /* working storage */ - - /* - * First pass is bottom-up (font hint order) without look-ahead. - * Locked edges are already adjusted. - * Unlocked edges begin with dsCoord from `initialHintMap'. - * Save edges that are not optimally adjusted in `hintMoves' array, - * and process them in second pass. - */ - - for ( i = 0; i < hintmap->count; i++ ) - { - FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] ); - - - /* index of upper edge (same value for ghost hint) */ - j = isPair ? i + 1 : i; - - FT_ASSERT( j < hintmap->count ); - FT_ASSERT( cf2_hint_isValid( &hintmap->edge[i] ) ); - FT_ASSERT( cf2_hint_isValid( &hintmap->edge[j] ) ); - FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) == - cf2_hint_isLocked( &hintmap->edge[j] ) ); - - if ( !cf2_hint_isLocked( &hintmap->edge[i] ) ) - { - /* hint edge is not locked, we can adjust it */ - CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord ); - CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord ); - - /* calculate all four possibilities; moves down are negative */ - CF2_Fixed downMoveDown = 0 - fracDown; - CF2_Fixed upMoveDown = 0 - fracUp; - CF2_Fixed downMoveUp = fracDown == 0 - ? 0 - : cf2_intToFixed( 1 ) - fracDown; - CF2_Fixed upMoveUp = fracUp == 0 - ? 0 - : cf2_intToFixed( 1 ) - fracUp; - - /* smallest move up */ - CF2_Fixed moveUp = FT_MIN( downMoveUp, upMoveUp ); - /* smallest move down */ - CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown ); - - /* final amount to move edge or edge pair */ - CF2_Fixed move; - - CF2_Fixed downMinCounter = CF2_MIN_COUNTER; - CF2_Fixed upMinCounter = CF2_MIN_COUNTER; - FT_Bool saveEdge = FALSE; - - - /* minimum counter constraint doesn't apply when adjacent edges */ - /* are synthetic */ - /* TODO: doesn't seem a big effect; for now, reduce the code */ -#if 0 - if ( i == 0 || - cf2_hint_isSynthetic( &hintmap->edge[i - 1] ) ) - downMinCounter = 0; - - if ( j >= hintmap->count - 1 || - cf2_hint_isSynthetic( &hintmap->edge[j + 1] ) ) - upMinCounter = 0; -#endif - - /* is there room to move up? */ - /* there is if we are at top of array or the next edge is at or */ - /* beyond proposed move up? */ - if ( j >= hintmap->count - 1 || - hintmap->edge[j + 1].dsCoord >= - hintmap->edge[j].dsCoord + moveUp + upMinCounter ) - { - /* there is room to move up; is there also room to move down? */ - if ( i == 0 || - hintmap->edge[i - 1].dsCoord <= - hintmap->edge[i].dsCoord + moveDown - downMinCounter ) - { - /* move smaller absolute amount */ - move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */ - } - else - move = moveUp; - } - else - { - /* is there room to move down? */ - if ( i == 0 || - hintmap->edge[i - 1].dsCoord <= - hintmap->edge[i].dsCoord + moveDown - downMinCounter ) - { - move = moveDown; - /* true if non-optimum move */ - saveEdge = (FT_Bool)( moveUp < -moveDown ); - } - else - { - /* no room to move either way without overlapping or reducing */ - /* the counter too much */ - move = 0; - saveEdge = TRUE; - } - } - - /* Identify non-moves and moves down that aren't optimal, and save */ - /* them for second pass. */ - /* Do this only if there is an unlocked edge above (which could */ - /* possibly move). */ - if ( saveEdge && - j < hintmap->count - 1 && - !cf2_hint_isLocked( &hintmap->edge[j + 1] ) ) - { - CF2_HintMoveRec savedMove; - - - savedMove.j = j; - /* desired adjustment in second pass */ - savedMove.moveUp = moveUp - move; - - cf2_arrstack_push( hintmap->hintMoves, &savedMove ); - } - - /* move the edge(s) */ - hintmap->edge[i].dsCoord += move; - if ( isPair ) - hintmap->edge[j].dsCoord += move; - } - - /* assert there are no overlaps in device space */ - FT_ASSERT( i == 0 || - hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord ); - FT_ASSERT( i < j || - hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord ); - - /* adjust the scales, avoiding divide by zero */ - if ( i > 0 ) - { - if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord ) - hintmap->edge[i - 1].scale = - FT_DivFix( - hintmap->edge[i].dsCoord - hintmap->edge[i - 1].dsCoord, - hintmap->edge[i].csCoord - hintmap->edge[i - 1].csCoord ); - } - - if ( isPair ) - { - if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord ) - hintmap->edge[j - 1].scale = - FT_DivFix( - hintmap->edge[j].dsCoord - hintmap->edge[j - 1].dsCoord, - hintmap->edge[j].csCoord - hintmap->edge[j - 1].csCoord ); - - i += 1; /* skip upper edge on next loop */ - } - } - - /* second pass tries to move non-optimal hints up, in case there is */ - /* room now */ - for ( i = cf2_arrstack_size( hintmap->hintMoves ); i > 0; i-- ) - { - CF2_HintMove hintMove = (CF2_HintMove) - cf2_arrstack_getPointer( hintmap->hintMoves, i - 1 ); - - - j = hintMove->j; - - /* this was tested before the push, above */ - FT_ASSERT( j < hintmap->count - 1 ); - - /* is there room to move up? */ - if ( hintmap->edge[j + 1].dsCoord >= - hintmap->edge[j].dsCoord + hintMove->moveUp + CF2_MIN_COUNTER ) - { - /* there is more room now, move edge up */ - hintmap->edge[j].dsCoord += hintMove->moveUp; - - if ( cf2_hint_isPair( &hintmap->edge[j] ) ) - { - FT_ASSERT( j > 0 ); - hintmap->edge[j - 1].dsCoord += hintMove->moveUp; - } - } - } - } - - - /* insert hint edges into map, sorted by csCoord */ - static void - cf2_hintmap_insertHint( CF2_HintMap hintmap, - CF2_Hint bottomHintEdge, - CF2_Hint topHintEdge ) - { - CF2_UInt indexInsert; - - /* set default values, then check for edge hints */ - FT_Bool isPair = TRUE; - CF2_Hint firstHintEdge = bottomHintEdge; - CF2_Hint secondHintEdge = topHintEdge; - - - /* one or none of the input params may be invalid when dealing with */ - /* edge hints; at least one edge must be valid */ - FT_ASSERT( cf2_hint_isValid( bottomHintEdge ) || - cf2_hint_isValid( topHintEdge ) ); - - /* determine how many and which edges to insert */ - if ( !cf2_hint_isValid( bottomHintEdge ) ) - { - /* insert only the top edge */ - firstHintEdge = topHintEdge; - isPair = FALSE; - } - else if ( !cf2_hint_isValid( topHintEdge ) ) - { - /* insert only the bottom edge */ - isPair = FALSE; - } - - /* paired edges must be in proper order */ - FT_ASSERT( !isPair || - topHintEdge->csCoord >= bottomHintEdge->csCoord ); - - /* linear search to find index value of insertion point */ - indexInsert = 0; - for ( ; indexInsert < hintmap->count; indexInsert++ ) - { - if ( hintmap->edge[indexInsert].csCoord >= firstHintEdge->csCoord ) - break; - } - - /* - * Discard any hints that overlap in character space. Most often, this - * is while building the initial map, where captured hints from all - * zones are combined. Define overlap to include hints that `touch' - * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that - * touch. Some fonts have non-ideographic glyphs that overlap our - * synthetic hints. - * - * Overlap also occurs when darkening stem hints that are close. - * - */ - if ( indexInsert < hintmap->count ) - { - /* we are inserting before an existing edge: */ - /* verify that an existing edge is not the same */ - if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord ) - return; /* ignore overlapping stem hint */ - - /* verify that a new pair does not straddle the next edge */ - if ( isPair && - hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord ) - return; /* ignore overlapping stem hint */ - - /* verify that we are not inserting between paired edges */ - if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) ) - return; /* ignore overlapping stem hint */ - } - - /* recompute device space locations using initial hint map */ - if ( cf2_hintmap_isValid( hintmap->initialHintMap ) && - !cf2_hint_isLocked( firstHintEdge ) ) - { - if ( isPair ) - { - /* Use hint map to position the center of stem, and nominal scale */ - /* to position the two edges. This preserves the stem width. */ - CF2_Fixed midpoint = cf2_hintmap_map( - hintmap->initialHintMap, - ( secondHintEdge->csCoord + - firstHintEdge->csCoord ) / 2 ); - CF2_Fixed halfWidth = FT_MulFix( - ( secondHintEdge->csCoord - - firstHintEdge->csCoord ) / 2, - hintmap->scale ); - - - firstHintEdge->dsCoord = midpoint - halfWidth; - secondHintEdge->dsCoord = midpoint + halfWidth; - } - else - firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap, - firstHintEdge->csCoord ); - } - - /* - * Discard any hints that overlap in device space; this can occur - * because locked hints have been moved to align with blue zones. - * - * TODO: Although we might correct this later during adjustment, we - * don't currently have a way to delete a conflicting hint once it has - * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened, - * initial hint map for second path, glyph 945 (the perispomeni (tilde) - * in U+1F6E, Greek omega with psili and perispomeni). Darkening is - * 25. Pair 667,747 initially conflicts in design space with top edge - * 660. This is because 667 maps to 7.87, and the top edge was - * captured by a zone at 8.0. The pair is later successfully inserted - * in a zone without the top edge. In this zone it is adjusted to 8.0, - * and no longer conflicts with the top edge in design space. This - * means it can be included in yet a later zone which does have the top - * edge hint. This produces a small mismatch between the first and - * last points of this path, even though the hint masks are the same. - * The density map difference is tiny (1/256). - * - */ - - if ( indexInsert > 0 ) - { - /* we are inserting after an existing edge */ - if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord ) - return; - } - - if ( indexInsert < hintmap->count ) - { - /* we are inserting before an existing edge */ - if ( isPair ) - { - if ( secondHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord ) - return; - } - else - { - if ( firstHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord ) - return; - } - } - - /* make room to insert */ - { - CF2_UInt iSrc = hintmap->count - 1; - CF2_UInt iDst = isPair ? hintmap->count + 1 : hintmap->count; - - CF2_UInt count = hintmap->count - indexInsert; - - - if ( iDst >= CF2_MAX_HINT_EDGES ) - { - FT_TRACE4(( "cf2_hintmap_insertHint: too many hintmaps\n" )); - return; - } - - while ( count-- ) - hintmap->edge[iDst--] = hintmap->edge[iSrc--]; - - /* insert first edge */ - hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */ - hintmap->count += 1; - - if ( isPair ) - { - /* insert second edge */ - hintmap->edge[indexInsert + 1] = *secondHintEdge; /* copy struct */ - hintmap->count += 1; - } - } - - return; - } - - - /* - * Build a map from hints and mask. - * - * This function may recur one level if `hintmap->initialHintMap' is not yet - * valid. - * If `initialMap' is true, simply build initial map. - * - * Synthetic hints are used in two ways. A hint at zero is inserted, if - * needed, in the initial hint map, to prevent translations from - * propagating across the origin. If synthetic em box hints are enabled - * for ideographic dictionaries, then they are inserted in all hint - * maps, including the initial one. - * - */ - FT_LOCAL_DEF( void ) - cf2_hintmap_build( CF2_HintMap hintmap, - CF2_ArrStack hStemHintArray, - CF2_ArrStack vStemHintArray, - CF2_HintMask hintMask, - CF2_Fixed hintOrigin, - FT_Bool initialMap ) - { - FT_Byte* maskPtr; - - CF2_Font font = hintmap->font; - CF2_HintMaskRec tempHintMask; - - size_t bitCount, i; - FT_Byte maskByte; - - - /* check whether initial map is constructed */ - if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) ) - { - /* make recursive call with initialHintMap and temporary mask; */ - /* temporary mask will get all bits set, below */ - cf2_hintmask_init( &tempHintMask, hintMask->error ); - cf2_hintmap_build( hintmap->initialHintMap, - hStemHintArray, - vStemHintArray, - &tempHintMask, - hintOrigin, - TRUE ); - } - - if ( !cf2_hintmask_isValid( hintMask ) ) - { - /* without a hint mask, assume all hints are active */ - cf2_hintmask_setAll( hintMask, - cf2_arrstack_size( hStemHintArray ) + - cf2_arrstack_size( vStemHintArray ) ); - if ( !cf2_hintmask_isValid( hintMask ) ) - return; /* too many stem hints */ - } - - /* begin by clearing the map */ - hintmap->count = 0; - hintmap->lastIndex = 0; - - /* make a copy of the hint mask so we can modify it */ - tempHintMask = *hintMask; - maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask ); - - /* use the hStem hints only, which are first in the mask */ - bitCount = cf2_arrstack_size( hStemHintArray ); - - /* Defense-in-depth. Should never return here. */ - if ( bitCount > hintMask->bitCount ) - return; - - /* synthetic embox hints get highest priority */ - if ( font->blues.doEmBoxHints ) - { - CF2_HintRec dummy; - - - cf2_hint_initZero( &dummy ); /* invalid hint map element */ - - /* ghost bottom */ - cf2_hintmap_insertHint( hintmap, - &font->blues.emBoxBottomEdge, - &dummy ); - /* ghost top */ - cf2_hintmap_insertHint( hintmap, - &dummy, - &font->blues.emBoxTopEdge ); - } - - /* insert hints captured by a blue zone or already locked (higher */ - /* priority) */ - for ( i = 0, maskByte = 0x80; i < bitCount; i++ ) - { - if ( maskByte & *maskPtr ) - { - /* expand StemHint into two `CF2_Hint' elements */ - CF2_HintRec bottomHintEdge, topHintEdge; - - - cf2_hint_init( &bottomHintEdge, - hStemHintArray, - i, - font, - hintOrigin, - hintmap->scale, - TRUE /* bottom */ ); - cf2_hint_init( &topHintEdge, - hStemHintArray, - i, - font, - hintOrigin, - hintmap->scale, - FALSE /* top */ ); - - if ( cf2_hint_isLocked( &bottomHintEdge ) || - cf2_hint_isLocked( &topHintEdge ) || - cf2_blues_capture( &font->blues, - &bottomHintEdge, - &topHintEdge ) ) - { - /* insert captured hint into map */ - cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge ); - - *maskPtr &= ~maskByte; /* turn off the bit for this hint */ - } - } - - if ( ( i & 7 ) == 7 ) - { - /* move to next mask byte */ - maskPtr++; - maskByte = 0x80; - } - else - maskByte >>= 1; - } - - /* initial hint map includes only captured hints plus maybe one at 0 */ - - /* - * TODO: There is a problem here because we are trying to build a - * single hint map containing all captured hints. It is - * possible for there to be conflicts between captured hints, - * either because of darkening or because the hints are in - * separate hint zones (we are ignoring hint zones for the - * initial map). An example of the latter is MinionPro-Regular - * v2.030 glyph 883 (Greek Capital Alpha with Psili) at 15ppem. - * A stem hint for the psili conflicts with the top edge hint - * for the base character. The stem hint gets priority because - * of its sort order. In glyph 884 (Greek Capital Alpha with - * Psili and Oxia), the top of the base character gets a stem - * hint, and the psili does not. This creates different initial - * maps for the two glyphs resulting in different renderings of - * the base character. Will probably defer this either as not - * worth the cost or as a font bug. I don't think there is any - * good reason for an accent to be captured by an alignment - * zone. -darnold 2/12/10 - */ - - if ( initialMap ) - { - /* Apply a heuristic that inserts a point for (0,0), unless it's */ - /* already covered by a mapping. This locks the baseline for glyphs */ - /* that have no baseline hints. */ - - if ( hintmap->count == 0 || - hintmap->edge[0].csCoord > 0 || - hintmap->edge[hintmap->count - 1].csCoord < 0 ) - { - /* all edges are above 0 or all edges are below 0; */ - /* construct a locked edge hint at 0 */ - - CF2_HintRec edge, invalid; - - - cf2_hint_initZero( &edge ); - - edge.flags = CF2_GhostBottom | - CF2_Locked | - CF2_Synthetic; - edge.scale = hintmap->scale; - - cf2_hint_initZero( &invalid ); - cf2_hintmap_insertHint( hintmap, &edge, &invalid ); - } - } - else - { - /* insert remaining hints */ - - maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask ); - - for ( i = 0, maskByte = 0x80; i < bitCount; i++ ) - { - if ( maskByte & *maskPtr ) - { - CF2_HintRec bottomHintEdge, topHintEdge; - - - cf2_hint_init( &bottomHintEdge, - hStemHintArray, - i, - font, - hintOrigin, - hintmap->scale, - TRUE /* bottom */ ); - cf2_hint_init( &topHintEdge, - hStemHintArray, - i, - font, - hintOrigin, - hintmap->scale, - FALSE /* top */ ); - - cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge ); - } - - if ( ( i & 7 ) == 7 ) - { - /* move to next mask byte */ - maskPtr++; - maskByte = 0x80; - } - else - maskByte >>= 1; - } - } - - /* - * Note: The following line is a convenient place to break when - * debugging hinting. Examine `hintmap->edge' for the list of - * enabled hints, then step over the call to see the effect of - * adjustment. We stop here first on the recursive call that - * creates the initial map, and then on each counter group and - * hint zone. - */ - - /* adjust positions of hint edges that are not locked to blue zones */ - cf2_hintmap_adjustHints( hintmap ); - - /* save the position of all hints that were used in this hint map; */ - /* if we use them again, we'll locate them in the same position */ - if ( !initialMap ) - { - for ( i = 0; i < hintmap->count; i++ ) - { - if ( !cf2_hint_isSynthetic( &hintmap->edge[i] ) ) - { - /* Note: include both valid and invalid edges */ - /* Note: top and bottom edges are copied back separately */ - CF2_StemHint stemhint = (CF2_StemHint) - cf2_arrstack_getPointer( hStemHintArray, - hintmap->edge[i].index ); - - - if ( cf2_hint_isTop( &hintmap->edge[i] ) ) - stemhint->maxDS = hintmap->edge[i].dsCoord; - else - stemhint->minDS = hintmap->edge[i].dsCoord; - - stemhint->used = TRUE; - } - } - } - - /* hint map is ready to use */ - hintmap->isValid = TRUE; - - /* remember this mask has been used */ - cf2_hintmask_setNew( hintMask, FALSE ); - } - - - FT_LOCAL_DEF( void ) - cf2_glyphpath_init( CF2_GlyphPath glyphpath, - CF2_Font font, - CF2_OutlineCallbacks callbacks, - CF2_Fixed scaleY, - /* CF2_Fixed hShift, */ - CF2_ArrStack hStemHintArray, - CF2_ArrStack vStemHintArray, - CF2_HintMask hintMask, - CF2_Fixed hintOriginY, - const CF2_Blues blues, - const FT_Vector* fractionalTranslation ) - { - FT_ZERO( glyphpath ); - - glyphpath->font = font; - glyphpath->callbacks = callbacks; - - cf2_arrstack_init( &glyphpath->hintMoves, - font->memory, - &font->error, - sizeof ( CF2_HintMoveRec ) ); - - cf2_hintmap_init( &glyphpath->initialHintMap, - font, - &glyphpath->initialHintMap, - &glyphpath->hintMoves, - scaleY ); - cf2_hintmap_init( &glyphpath->firstHintMap, - font, - &glyphpath->initialHintMap, - &glyphpath->hintMoves, - scaleY ); - cf2_hintmap_init( &glyphpath->hintMap, - font, - &glyphpath->initialHintMap, - &glyphpath->hintMoves, - scaleY ); - - glyphpath->scaleX = font->innerTransform.a; - glyphpath->scaleC = font->innerTransform.c; - glyphpath->scaleY = font->innerTransform.d; - - glyphpath->fractionalTranslation = *fractionalTranslation; - -#if 0 - glyphpath->hShift = hShift; /* for fauxing */ -#endif - - glyphpath->hStemHintArray = hStemHintArray; - glyphpath->vStemHintArray = vStemHintArray; - glyphpath->hintMask = hintMask; /* ptr to current mask */ - glyphpath->hintOriginY = hintOriginY; - glyphpath->blues = blues; - glyphpath->darken = font->darkened; /* TODO: should we make copies? */ - glyphpath->xOffset = font->darkenX; - glyphpath->yOffset = font->darkenY; - glyphpath->miterLimit = 2 * FT_MAX( - cf2_fixedAbs( glyphpath->xOffset ), - cf2_fixedAbs( glyphpath->yOffset ) ); - - /* .1 character space unit */ - glyphpath->snapThreshold = cf2_floatToFixed( 0.1f ); - - glyphpath->moveIsPending = TRUE; - glyphpath->pathIsOpen = FALSE; - glyphpath->pathIsClosing = FALSE; - glyphpath->elemIsQueued = FALSE; - } - - - FT_LOCAL_DEF( void ) - cf2_glyphpath_finalize( CF2_GlyphPath glyphpath ) - { - cf2_arrstack_finalize( &glyphpath->hintMoves ); - } - - - /* - * Hint point in y-direction and apply outerTransform. - * Input `current' hint map (which is actually delayed by one element). - * Input x,y point in Character Space. - * Output x,y point in Device Space, including translation. - */ - static void - cf2_glyphpath_hintPoint( CF2_GlyphPath glyphpath, - CF2_HintMap hintmap, - FT_Vector* ppt, - CF2_Fixed x, - CF2_Fixed y ) - { - FT_Vector pt; /* hinted point in upright DS */ - - - pt.x = FT_MulFix( glyphpath->scaleX, x ) + - FT_MulFix( glyphpath->scaleC, y ); - pt.y = cf2_hintmap_map( hintmap, y ); - - ppt->x = FT_MulFix( glyphpath->font->outerTransform.a, pt.x ) + - FT_MulFix( glyphpath->font->outerTransform.c, pt.y ) + - glyphpath->fractionalTranslation.x; - ppt->y = FT_MulFix( glyphpath->font->outerTransform.b, pt.x ) + - FT_MulFix( glyphpath->font->outerTransform.d, pt.y ) + - glyphpath->fractionalTranslation.y; - } - - - /* - * From two line segments, (u1,u2) and (v1,v2), compute a point of - * intersection on the corresponding lines. - * Return false if no intersection is found, or if the intersection is - * too far away from the ends of the line segments, u2 and v1. - * - */ - static FT_Bool - cf2_glyphpath_computeIntersection( CF2_GlyphPath glyphpath, - const FT_Vector* u1, - const FT_Vector* u2, - const FT_Vector* v1, - const FT_Vector* v2, - FT_Vector* intersection ) - { - /* - * Let `u' be a zero-based vector from the first segment, `v' from the - * second segment. - * Let `w 'be the zero-based vector from `u1' to `v1'. - * `perp' is the `perpendicular dot product'; see - * http://mathworld.wolfram.com/PerpDotProduct.html. - * `s' is the parameter for the parametric line for the first segment - * (`u'). - * - * See notation in - * http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm. - * Calculations are done in 16.16, but must handle the squaring of - * line lengths in character space. We scale all vectors by 1/32 to - * avoid overflow. This allows values up to 4095 to be squared. The - * scale factor cancels in the divide. - * - * TODO: the scale factor could be computed from UnitsPerEm. - * - */ - -#define cf2_perp( a, b ) \ - ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) ) - - /* round and divide by 32 */ -#define CF2_CS_SCALE( x ) \ - ( ( (x) + 0x10 ) >> 5 ) - - FT_Vector u, v, w; /* scaled vectors */ - CF2_Fixed denominator, s; - - - u.x = CF2_CS_SCALE( u2->x - u1->x ); - u.y = CF2_CS_SCALE( u2->y - u1->y ); - v.x = CF2_CS_SCALE( v2->x - v1->x ); - v.y = CF2_CS_SCALE( v2->y - v1->y ); - w.x = CF2_CS_SCALE( v1->x - u1->x ); - w.y = CF2_CS_SCALE( v1->y - u1->y ); - - denominator = cf2_perp( u, v ); - - if ( denominator == 0 ) - return FALSE; /* parallel or coincident lines */ - - s = FT_DivFix( cf2_perp( w, v ), denominator ); - - intersection->x = u1->x + FT_MulFix( s, u2->x - u1->x ); - intersection->y = u1->y + FT_MulFix( s, u2->y - u1->y ); - - /* - * Special case snapping for horizontal and vertical lines. - * This cleans up intersections and reduces problems with winding - * order detection. - * Sample case is sbc cd KozGoPr6N-Medium.otf 20 16685. - * Note: these calculations are in character space. - * - */ - - if ( u1->x == u2->x && - cf2_fixedAbs( intersection->x - u1->x ) < glyphpath->snapThreshold ) - intersection->x = u1->x; - if ( u1->y == u2->y && - cf2_fixedAbs( intersection->y - u1->y ) < glyphpath->snapThreshold ) - intersection->y = u1->y; - - if ( v1->x == v2->x && - cf2_fixedAbs( intersection->x - v1->x ) < glyphpath->snapThreshold ) - intersection->x = v1->x; - if ( v1->y == v2->y && - cf2_fixedAbs( intersection->y - v1->y ) < glyphpath->snapThreshold ) - intersection->y = v1->y; - - /* limit the intersection distance from midpoint of u2 and v1 */ - if ( cf2_fixedAbs( intersection->x - ( u2->x + v1->x ) / 2 ) > - glyphpath->miterLimit || - cf2_fixedAbs( intersection->y - ( u2->y + v1->y ) / 2 ) > - glyphpath->miterLimit ) - return FALSE; - - return TRUE; - } - - - /* - * Push the cached element (glyphpath->prevElem*) to the outline - * consumer. When a darkening offset is used, the end point of the - * cached element may be adjusted to an intersection point or we may - * synthesize a connecting line to the current element. If we are - * closing a subpath, we may also generate a connecting line to the start - * point. - * - * This is where Character Space (CS) is converted to Device Space (DS) - * using a hint map. This calculation must use a HintMap that was valid - * at the time the element was saved. For the first point in a subpath, - * that is a saved HintMap. For most elements, it just means the caller - * has delayed building a HintMap from the current HintMask. - * - * Transform each point with outerTransform and call the outline - * callbacks. This is a general 3x3 transform: - * - * x' = a*x + c*y + tx, y' = b*x + d*y + ty - * - * but it uses 4 elements from CF2_Font and the translation part - * from CF2_GlyphPath. - * - */ - static void - cf2_glyphpath_pushPrevElem( CF2_GlyphPath glyphpath, - CF2_HintMap hintmap, - FT_Vector* nextP0, - FT_Vector nextP1, - FT_Bool close ) - { - CF2_CallbackParamsRec params; - - FT_Vector* prevP0; - FT_Vector* prevP1; - - FT_Vector intersection = { 0, 0 }; - FT_Bool useIntersection = FALSE; - - - FT_ASSERT( glyphpath->prevElemOp == CF2_PathOpLineTo || - glyphpath->prevElemOp == CF2_PathOpCubeTo ); - - if ( glyphpath->prevElemOp == CF2_PathOpLineTo ) - { - prevP0 = &glyphpath->prevElemP0; - prevP1 = &glyphpath->prevElemP1; - } - else - { - prevP0 = &glyphpath->prevElemP2; - prevP1 = &glyphpath->prevElemP3; - } - - /* optimization: if previous and next elements are offset by the same */ - /* amount, then there will be no gap, and no need to compute an */ - /* intersection. */ - if ( prevP1->x != nextP0->x || prevP1->y != nextP0->y ) - { - /* previous element does not join next element: */ - /* adjust end point of previous element to the intersection */ - useIntersection = cf2_glyphpath_computeIntersection( glyphpath, - prevP0, - prevP1, - nextP0, - &nextP1, - &intersection ); - if ( useIntersection ) - { - /* modify the last point of the cached element (either line or */ - /* curve) */ - *prevP1 = intersection; - } - } - - params.pt0 = glyphpath->currentDS; - - switch( glyphpath->prevElemOp ) - { - case CF2_PathOpLineTo: - params.op = CF2_PathOpLineTo; - - /* note: pt2 and pt3 are unused */ - - if ( close ) - { - /* use first hint map if closing */ - cf2_glyphpath_hintPoint( glyphpath, - &glyphpath->firstHintMap, - ¶ms.pt1, - glyphpath->prevElemP1.x, - glyphpath->prevElemP1.y ); - } - else - { - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt1, - glyphpath->prevElemP1.x, - glyphpath->prevElemP1.y ); - } - - /* output only non-zero length lines */ - if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y ) - { - glyphpath->callbacks->lineTo( glyphpath->callbacks, ¶ms ); - - glyphpath->currentDS = params.pt1; - } - break; - - case CF2_PathOpCubeTo: - params.op = CF2_PathOpCubeTo; - - /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */ - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt1, - glyphpath->prevElemP1.x, - glyphpath->prevElemP1.y ); - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt2, - glyphpath->prevElemP2.x, - glyphpath->prevElemP2.y ); - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt3, - glyphpath->prevElemP3.x, - glyphpath->prevElemP3.y ); - - glyphpath->callbacks->cubeTo( glyphpath->callbacks, ¶ms ); - - glyphpath->currentDS = params.pt3; - - break; - } - - if ( !useIntersection || close ) - { - /* insert connecting line between end of previous element and start */ - /* of current one */ - /* note: at the end of a subpath, we might do both, so use `nextP0' */ - /* before we change it, below */ - - if ( close ) - { - /* if we are closing the subpath, then nextP0 is in the first */ - /* hint zone */ - cf2_glyphpath_hintPoint( glyphpath, - &glyphpath->firstHintMap, - ¶ms.pt1, - nextP0->x, - nextP0->y ); - } - else - { - cf2_glyphpath_hintPoint( glyphpath, - hintmap, - ¶ms.pt1, - nextP0->x, - nextP0->y ); - } - - if ( params.pt1.x != glyphpath->currentDS.x || - params.pt1.y != glyphpath->currentDS.y ) - { - /* length is nonzero */ - params.op = CF2_PathOpLineTo; - params.pt0 = glyphpath->currentDS; - - /* note: pt2 and pt3 are unused */ - glyphpath->callbacks->lineTo( glyphpath->callbacks, ¶ms ); - - glyphpath->currentDS = params.pt1; - } - } - - if ( useIntersection ) - { - /* return intersection point to caller */ - *nextP0 = intersection; - } - } - - - /* push a MoveTo element based on current point and offset of current */ - /* element */ - static void - cf2_glyphpath_pushMove( CF2_GlyphPath glyphpath, - FT_Vector start ) - { - CF2_CallbackParamsRec params; - - - params.op = CF2_PathOpMoveTo; - params.pt0 = glyphpath->currentDS; - - /* Test if move has really happened yet; it would have called */ - /* `cf2_hintmap_build' to set `isValid'. */ - if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ) - { - /* we are here iff first subpath is missing a moveto operator: */ - /* synthesize first moveTo to finish initialization of hintMap */ - cf2_glyphpath_moveTo( glyphpath, - glyphpath->start.x, - glyphpath->start.y ); - } - - cf2_glyphpath_hintPoint( glyphpath, - &glyphpath->hintMap, - ¶ms.pt1, - start.x, - start.y ); - - /* note: pt2 and pt3 are unused */ - glyphpath->callbacks->moveTo( glyphpath->callbacks, ¶ms ); - - glyphpath->currentDS = params.pt1; - glyphpath->offsetStart0 = start; - } - - - /* - * All coordinates are in character space. - * On input, (x1, y1) and (x2, y2) give line segment. - * On output, (x, y) give offset vector. - * We use a piecewise approximation to trig functions. - * - * TODO: Offset true perpendicular and proper length - * supply the y-translation for hinting here, too, - * that adds yOffset unconditionally to *y. - */ - static void - cf2_glyphpath_computeOffset( CF2_GlyphPath glyphpath, - CF2_Fixed x1, - CF2_Fixed y1, - CF2_Fixed x2, - CF2_Fixed y2, - CF2_Fixed* x, - CF2_Fixed* y ) - { - CF2_Fixed dx = x2 - x1; - CF2_Fixed dy = y2 - y1; - - - /* note: negative offsets don't work here; negate deltas to change */ - /* quadrants, below */ - if ( glyphpath->font->reverseWinding ) - { - dx = -dx; - dy = -dy; - } - - *x = *y = 0; - - if ( !glyphpath->darken ) - return; - - /* add momentum for this path element */ - glyphpath->callbacks->windingMomentum += - cf2_getWindingMomentum( x1, y1, x2, y2 ); - - /* note: allow mixed integer and fixed multiplication here */ - if ( dx >= 0 ) - { - if ( dy >= 0 ) - { - /* first quadrant, +x +y */ - - if ( dx > 2 * dy ) - { - /* +x */ - *x = 0; - *y = 0; - } - else if ( dy > 2 * dx ) - { - /* +y */ - *x = glyphpath->xOffset; - *y = glyphpath->yOffset; - } - else - { - /* +x +y */ - *x = FT_MulFix( cf2_floatToFixed( 0.7 ), - glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ), - glyphpath->yOffset ); - } - } - else - { - /* fourth quadrant, +x -y */ - - if ( dx > -2 * dy ) - { - /* +x */ - *x = 0; - *y = 0; - } - else if ( -dy > 2 * dx ) - { - /* -y */ - *x = -glyphpath->xOffset; - *y = glyphpath->yOffset; - } - else - { - /* +x -y */ - *x = FT_MulFix( cf2_floatToFixed( -0.7 ), - glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ), - glyphpath->yOffset ); - } - } - } - else - { - if ( dy >= 0 ) - { - /* second quadrant, -x +y */ - - if ( -dx > 2 * dy ) - { - /* -x */ - *x = 0; - *y = 2 * glyphpath->yOffset; - } - else if ( dy > -2 * dx ) - { - /* +y */ - *x = glyphpath->xOffset; - *y = glyphpath->yOffset; - } - else - { - /* -x +y */ - *x = FT_MulFix( cf2_floatToFixed( 0.7 ), - glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ), - glyphpath->yOffset ); - } - } - else - { - /* third quadrant, -x -y */ - - if ( -dx > -2 * dy ) - { - /* -x */ - *x = 0; - *y = 2 * glyphpath->yOffset; - } - else if ( -dy > -2 * dx ) - { - /* -y */ - *x = -glyphpath->xOffset; - *y = glyphpath->yOffset; - } - else - { - /* -x -y */ - *x = FT_MulFix( cf2_floatToFixed( -0.7 ), - glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ), - glyphpath->yOffset ); - } - } - } - } - - - /* - * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are - * called by the interpreter with Character Space (CS) coordinates. Each - * path element is placed into a queue of length one to await the - * calculation of the following element. At that time, the darkening - * offset of the following element is known and joins can be computed, - * including possible modification of this element, before mapping to - * Device Space (DS) and passing it on to the outline consumer. - * - */ - FT_LOCAL_DEF( void ) - cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath, - CF2_Fixed x, - CF2_Fixed y ) - { - cf2_glyphpath_closeOpenPath( glyphpath ); - - /* save the parameters of the move for later, when we'll know how to */ - /* offset it; */ - /* also save last move point */ - glyphpath->currentCS.x = glyphpath->start.x = x; - glyphpath->currentCS.y = glyphpath->start.y = y; - - glyphpath->moveIsPending = TRUE; - - /* ensure we have a valid map with current mask */ - if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) || - cf2_hintmask_isNew( glyphpath->hintMask ) ) - cf2_hintmap_build( &glyphpath->hintMap, - glyphpath->hStemHintArray, - glyphpath->vStemHintArray, - glyphpath->hintMask, - glyphpath->hintOriginY, - FALSE ); - - /* save a copy of current HintMap to use when drawing initial point */ - glyphpath->firstHintMap = glyphpath->hintMap; /* structure copy */ - } - - - FT_LOCAL_DEF( void ) - cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath, - CF2_Fixed x, - CF2_Fixed y ) - { - CF2_Fixed xOffset, yOffset; - FT_Vector P0, P1; - FT_Bool newHintMap; - - /* - * New hints will be applied after cf2_glyphpath_pushPrevElem has run. - * In case this is a synthesized closing line, any new hints should be - * delayed until this path is closed (`cf2_hintmask_isNew' will be - * called again before the next line or curve). - */ - - /* true if new hint map not on close */ - newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) && - !glyphpath->pathIsClosing; - - /* - * Zero-length lines may occur in the charstring. Because we cannot - * compute darkening offsets or intersections from zero-length lines, - * it is best to remove them and avoid artifacts. However, zero-length - * lines in CS at the start of a new hint map can generate non-zero - * lines in DS due to hint substitution. We detect a change in hint - * map here and pass those zero-length lines along. - */ - - /* - * Note: Find explicitly closed paths here with a conditional - * breakpoint using - * - * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y - * - */ - - if ( glyphpath->currentCS.x == x && - glyphpath->currentCS.y == y && - !newHintMap ) - /* - * Ignore zero-length lines in CS where the hint map is the same - * because the line in DS will also be zero length. - * - * Ignore zero-length lines when we synthesize a closing line because - * the close will be handled in cf2_glyphPath_pushPrevElem. - */ - return; - - cf2_glyphpath_computeOffset( glyphpath, - glyphpath->currentCS.x, - glyphpath->currentCS.y, - x, - y, - &xOffset, - &yOffset ); - - /* construct offset points */ - P0.x = glyphpath->currentCS.x + xOffset; - P0.y = glyphpath->currentCS.y + yOffset; - P1.x = x + xOffset; - P1.y = y + yOffset; - - if ( glyphpath->moveIsPending ) - { - /* emit offset 1st point as MoveTo */ - cf2_glyphpath_pushMove( glyphpath, P0 ); - - glyphpath->moveIsPending = FALSE; /* adjust state machine */ - glyphpath->pathIsOpen = TRUE; - - glyphpath->offsetStart1 = P1; /* record second point */ - } - - if ( glyphpath->elemIsQueued ) - { - FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) || - glyphpath->hintMap.count == 0 ); - - cf2_glyphpath_pushPrevElem( glyphpath, - &glyphpath->hintMap, - &P0, - P1, - FALSE ); - } - - /* queue the current element with offset points */ - glyphpath->elemIsQueued = TRUE; - glyphpath->prevElemOp = CF2_PathOpLineTo; - glyphpath->prevElemP0 = P0; - glyphpath->prevElemP1 = P1; - - /* update current map */ - if ( newHintMap ) - cf2_hintmap_build( &glyphpath->hintMap, - glyphpath->hStemHintArray, - glyphpath->vStemHintArray, - glyphpath->hintMask, - glyphpath->hintOriginY, - FALSE ); - - glyphpath->currentCS.x = x; /* pre-offset current point */ - glyphpath->currentCS.y = y; - } - - - FT_LOCAL_DEF( void ) - cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath, - CF2_Fixed x1, - CF2_Fixed y1, - CF2_Fixed x2, - CF2_Fixed y2, - CF2_Fixed x3, - CF2_Fixed y3 ) - { - CF2_Fixed xOffset1, yOffset1, xOffset3, yOffset3; - FT_Vector P0, P1, P2, P3; - - - /* TODO: ignore zero length portions of curve?? */ - cf2_glyphpath_computeOffset( glyphpath, - glyphpath->currentCS.x, - glyphpath->currentCS.y, - x1, - y1, - &xOffset1, - &yOffset1 ); - cf2_glyphpath_computeOffset( glyphpath, - x2, - y2, - x3, - y3, - &xOffset3, - &yOffset3 ); - - /* add momentum from the middle segment */ - glyphpath->callbacks->windingMomentum += - cf2_getWindingMomentum( x1, y1, x2, y2 ); - - /* construct offset points */ - P0.x = glyphpath->currentCS.x + xOffset1; - P0.y = glyphpath->currentCS.y + yOffset1; - P1.x = x1 + xOffset1; - P1.y = y1 + yOffset1; - /* note: preserve angle of final segment by using offset3 at both ends */ - P2.x = x2 + xOffset3; - P2.y = y2 + yOffset3; - P3.x = x3 + xOffset3; - P3.y = y3 + yOffset3; - - if ( glyphpath->moveIsPending ) - { - /* emit offset 1st point as MoveTo */ - cf2_glyphpath_pushMove( glyphpath, P0 ); - - glyphpath->moveIsPending = FALSE; - glyphpath->pathIsOpen = TRUE; - - glyphpath->offsetStart1 = P1; /* record second point */ - } - - if ( glyphpath->elemIsQueued ) - { - FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) || - glyphpath->hintMap.count == 0 ); - - cf2_glyphpath_pushPrevElem( glyphpath, - &glyphpath->hintMap, - &P0, - P1, - FALSE ); - } - - /* queue the current element with offset points */ - glyphpath->elemIsQueued = TRUE; - glyphpath->prevElemOp = CF2_PathOpCubeTo; - glyphpath->prevElemP0 = P0; - glyphpath->prevElemP1 = P1; - glyphpath->prevElemP2 = P2; - glyphpath->prevElemP3 = P3; - - /* update current map */ - if ( cf2_hintmask_isNew( glyphpath->hintMask ) ) - cf2_hintmap_build( &glyphpath->hintMap, - glyphpath->hStemHintArray, - glyphpath->vStemHintArray, - glyphpath->hintMask, - glyphpath->hintOriginY, - FALSE ); - - glyphpath->currentCS.x = x3; /* pre-offset current point */ - glyphpath->currentCS.y = y3; - } - - - FT_LOCAL_DEF( void ) - cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath ) - { - if ( glyphpath->pathIsOpen ) - { - /* - * A closing line in Character Space line is always generated below - * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns - * out to be zero length in Device Space. - */ - glyphpath->pathIsClosing = TRUE; - - cf2_glyphpath_lineTo( glyphpath, - glyphpath->start.x, - glyphpath->start.y ); - - /* empty the final element from the queue and close the path */ - if ( glyphpath->elemIsQueued ) - cf2_glyphpath_pushPrevElem( glyphpath, - &glyphpath->hintMap, - &glyphpath->offsetStart0, - glyphpath->offsetStart1, - TRUE ); - - /* reset state machine */ - glyphpath->moveIsPending = TRUE; - glyphpath->pathIsOpen = FALSE; - glyphpath->pathIsClosing = FALSE; - glyphpath->elemIsQueued = FALSE; - } - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2hints.h b/third_party/freetype/src/cff/cf2hints.h deleted file mode 100644 index f25d91bf89ffd895730a45faeffd9c6c74658741..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2hints.h +++ /dev/null @@ -1,289 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2hints.h */ -/* */ -/* Adobe's code for handling CFF hints (body). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2HINTS_H__ -#define __CF2HINTS_H__ - - -FT_BEGIN_HEADER - - - enum - { - CF2_MAX_HINTS = 96 /* maximum # of hints */ - }; - - - /* - * A HintMask object stores a bit mask that specifies which hints in the - * charstring are active at a given time. Hints in CFF must be declared - * at the start, before any drawing operators, with horizontal hints - * preceding vertical hints. The HintMask is ordered the same way, with - * horizontal hints immediately followed by vertical hints. Clients are - * responsible for knowing how many of each type are present. - * - * The maximum total number of hints is 96, as specified by the CFF - * specification. - * - * A HintMask is built 0 or more times while interpreting a charstring, by - * the HintMask operator. There is only one HintMask, but it is built or - * rebuilt each time there is a hint substitution (HintMask operator) in - * the charstring. A default HintMask with all bits set is built if there - * has been no HintMask operator prior to the first drawing operator. - * - */ - - typedef struct CF2_HintMaskRec_ - { - FT_Error* error; - - FT_Bool isValid; - FT_Bool isNew; - - size_t bitCount; - size_t byteCount; - - FT_Byte mask[( CF2_MAX_HINTS + 7 ) / 8]; - - } CF2_HintMaskRec, *CF2_HintMask; - - - typedef struct CF2_StemHintRec_ - { - FT_Bool used; /* DS positions are valid */ - - CF2_Fixed min; /* original character space value */ - CF2_Fixed max; - - CF2_Fixed minDS; /* DS position after first use */ - CF2_Fixed maxDS; - - } CF2_StemHintRec, *CF2_StemHint; - - - /* - * A HintMap object stores a piecewise linear function for mapping - * y-coordinates from character space to device space, providing - * appropriate pixel alignment to stem edges. - * - * The map is implemented as an array of `CF2_Hint' elements, each - * representing an edge. When edges are paired, as from stem hints, the - * bottom edge must immediately precede the top edge in the array. - * Element character space AND device space positions must both increase - * monotonically in the array. `CF2_Hint' elements are also used as - * parameters to `cf2_blues_capture'. - * - * The `cf2_hintmap_build' method must be called before any drawing - * operation (beginning with a Move operator) and at each hint - * substitution (HintMask operator). - * - * The `cf2_hintmap_map' method is called to transform y-coordinates at - * each drawing operation (move, line, curve). - * - */ - - /* TODO: make this a CF2_ArrStack and add a deep copy method */ - enum - { - CF2_MAX_HINT_EDGES = CF2_MAX_HINTS * 2 - }; - - - typedef struct CF2_HintMapRec_ - { - CF2_Font font; - - /* initial map based on blue zones */ - struct CF2_HintMapRec_* initialHintMap; - - /* working storage for 2nd pass adjustHints */ - CF2_ArrStack hintMoves; - - FT_Bool isValid; - FT_Bool hinted; - - CF2_Fixed scale; - CF2_UInt count; - - /* start search from this index */ - CF2_UInt lastIndex; - - CF2_HintRec edge[CF2_MAX_HINT_EDGES]; /* 192 */ - - } CF2_HintMapRec, *CF2_HintMap; - - - FT_LOCAL( FT_Bool ) - cf2_hint_isValid( const CF2_Hint hint ); - FT_LOCAL( FT_Bool ) - cf2_hint_isTop( const CF2_Hint hint ); - FT_LOCAL( FT_Bool ) - cf2_hint_isBottom( const CF2_Hint hint ); - FT_LOCAL( void ) - cf2_hint_lock( CF2_Hint hint ); - - - FT_LOCAL( void ) - cf2_hintmap_init( CF2_HintMap hintmap, - CF2_Font font, - CF2_HintMap initialMap, - CF2_ArrStack hintMoves, - CF2_Fixed scale ); - FT_LOCAL( void ) - cf2_hintmap_build( CF2_HintMap hintmap, - CF2_ArrStack hStemHintArray, - CF2_ArrStack vStemHintArray, - CF2_HintMask hintMask, - CF2_Fixed hintOrigin, - FT_Bool initialMap ); - - - /* - * GlyphPath is a wrapper for drawing operations that scales the - * coordinates according to the render matrix and HintMap. It also tracks - * open paths to control ClosePath and to insert MoveTo for broken fonts. - * - */ - typedef struct CF2_GlyphPathRec_ - { - /* TODO: gather some of these into a hinting context */ - - CF2_Font font; /* font instance */ - CF2_OutlineCallbacks callbacks; /* outline consumer */ - - - CF2_HintMapRec hintMap; /* current hint map */ - CF2_HintMapRec firstHintMap; /* saved copy */ - CF2_HintMapRec initialHintMap; /* based on all captured hints */ - - CF2_ArrStackRec hintMoves; /* list of hint moves for 2nd pass */ - - CF2_Fixed scaleX; /* matrix a */ - CF2_Fixed scaleC; /* matrix c */ - CF2_Fixed scaleY; /* matrix d */ - - FT_Vector fractionalTranslation; /* including deviceXScale */ -#if 0 - CF2_Fixed hShift; /* character space horizontal shift */ - /* (for fauxing) */ -#endif - - FT_Bool pathIsOpen; /* true after MoveTo */ - FT_Bool pathIsClosing; /* true when synthesizing closepath line */ - FT_Bool darken; /* true if stem darkening */ - FT_Bool moveIsPending; /* true between MoveTo and offset MoveTo */ - - /* references used to call `cf2_hintmap_build', if necessary */ - CF2_ArrStack hStemHintArray; - CF2_ArrStack vStemHintArray; - CF2_HintMask hintMask; /* ptr to the current mask */ - CF2_Fixed hintOriginY; /* copy of current origin */ - const CF2_BluesRec* blues; - - CF2_Fixed xOffset; /* character space offsets */ - CF2_Fixed yOffset; - - /* character space miter limit threshold */ - CF2_Fixed miterLimit; - /* vertical/horzizontal snap distance in character space */ - CF2_Fixed snapThreshold; - - FT_Vector offsetStart0; /* first and second points of first */ - FT_Vector offsetStart1; /* element with offset applied */ - - /* current point, character space, before offset */ - FT_Vector currentCS; - /* current point, device space */ - FT_Vector currentDS; - /* start point of subpath, character space */ - FT_Vector start; - - /* the following members constitute the `queue' of one element */ - FT_Bool elemIsQueued; - CF2_Int prevElemOp; - - FT_Vector prevElemP0; - FT_Vector prevElemP1; - FT_Vector prevElemP2; - FT_Vector prevElemP3; - - } CF2_GlyphPathRec, *CF2_GlyphPath; - - - FT_LOCAL( void ) - cf2_glyphpath_init( CF2_GlyphPath glyphpath, - CF2_Font font, - CF2_OutlineCallbacks callbacks, - CF2_Fixed scaleY, - /* CF2_Fixed hShift, */ - CF2_ArrStack hStemHintArray, - CF2_ArrStack vStemHintArray, - CF2_HintMask hintMask, - CF2_Fixed hintOrigin, - const CF2_Blues blues, - const FT_Vector* fractionalTranslation ); - FT_LOCAL( void ) - cf2_glyphpath_finalize( CF2_GlyphPath glyphpath ); - - FT_LOCAL( void ) - cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath, - CF2_Fixed x, - CF2_Fixed y ); - FT_LOCAL( void ) - cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath, - CF2_Fixed x, - CF2_Fixed y ); - FT_LOCAL( void ) - cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath, - CF2_Fixed x1, - CF2_Fixed y1, - CF2_Fixed x2, - CF2_Fixed y2, - CF2_Fixed x3, - CF2_Fixed y3 ); - FT_LOCAL( void ) - cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath ); - - -FT_END_HEADER - - -#endif /* __CF2HINTS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2intrp.c b/third_party/freetype/src/cff/cf2intrp.c deleted file mode 100644 index ff3fa9aaaabe33c32bb05428d049359651a0ee77..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2intrp.c +++ /dev/null @@ -1,1571 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2intrp.c */ -/* */ -/* Adobe's CFF Interpreter (body). */ -/* */ -/* Copyright 2007-2014 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2stack.h" -#include "cf2hints.h" -#include "cf2intrp.h" - -#include "cf2error.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cf2interp - - - /* some operators are not implemented yet */ -#define CF2_FIXME FT_TRACE4(( "cf2_interpT2CharString:" \ - " operator not implemented yet\n" )) - - - - FT_LOCAL_DEF( void ) - cf2_hintmask_init( CF2_HintMask hintmask, - FT_Error* error ) - { - FT_ZERO( hintmask ); - - hintmask->error = error; - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hintmask_isValid( const CF2_HintMask hintmask ) - { - return hintmask->isValid; - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hintmask_isNew( const CF2_HintMask hintmask ) - { - return hintmask->isNew; - } - - - FT_LOCAL_DEF( void ) - cf2_hintmask_setNew( CF2_HintMask hintmask, - FT_Bool val ) - { - hintmask->isNew = val; - } - - - /* clients call `getMaskPtr' in order to iterate */ - /* through hint mask */ - - FT_LOCAL_DEF( FT_Byte* ) - cf2_hintmask_getMaskPtr( CF2_HintMask hintmask ) - { - return hintmask->mask; - } - - - static size_t - cf2_hintmask_setCounts( CF2_HintMask hintmask, - size_t bitCount ) - { - if ( bitCount > CF2_MAX_HINTS ) - { - /* total of h and v stems must be <= 96 */ - CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format ); - return 0; - } - - hintmask->bitCount = bitCount; - hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8; - - hintmask->isValid = TRUE; - hintmask->isNew = TRUE; - - return bitCount; - } - - - /* consume the hintmask bytes from the charstring, advancing the src */ - /* pointer */ - static void - cf2_hintmask_read( CF2_HintMask hintmask, - CF2_Buffer charstring, - size_t bitCount ) - { - size_t i; - -#ifndef CF2_NDEBUG - /* these are the bits in the final mask byte that should be zero */ - /* Note: this variable is only used in an assert expression below */ - /* and then only if CF2_NDEBUG is not defined */ - CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; -#endif - - - /* initialize counts and isValid */ - if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) - return; - - FT_ASSERT( hintmask->byteCount > 0 ); - - FT_TRACE4(( " (maskbytes:" )); - - /* set mask and advance interpreter's charstring pointer */ - for ( i = 0; i < hintmask->byteCount; i++ ) - { - hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring ); - FT_TRACE4(( " 0x%02X", hintmask->mask[i] )); - } - - FT_TRACE4(( ")\n" )); - - /* assert any unused bits in last byte are zero unless there's a prior */ - /* error */ - /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ -#ifndef CF2_NDEBUG - FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 || - *hintmask->error ); -#endif - } - - - FT_LOCAL_DEF( void ) - cf2_hintmask_setAll( CF2_HintMask hintmask, - size_t bitCount ) - { - size_t i; - CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; - - - /* initialize counts and isValid */ - if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) - return; - - FT_ASSERT( hintmask->byteCount > 0 ); - FT_ASSERT( hintmask->byteCount < - sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) ); - - /* set mask to all ones */ - for ( i = 0; i < hintmask->byteCount; i++ ) - hintmask->mask[i] = 0xFF; - - /* clear unused bits */ - /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ - hintmask->mask[hintmask->byteCount - 1] &= ~mask; - } - - - /* Type2 charstring opcodes */ - enum - { - cf2_cmdRESERVED_0, /* 0 */ - cf2_cmdHSTEM, /* 1 */ - cf2_cmdRESERVED_2, /* 2 */ - cf2_cmdVSTEM, /* 3 */ - cf2_cmdVMOVETO, /* 4 */ - cf2_cmdRLINETO, /* 5 */ - cf2_cmdHLINETO, /* 6 */ - cf2_cmdVLINETO, /* 7 */ - cf2_cmdRRCURVETO, /* 8 */ - cf2_cmdRESERVED_9, /* 9 */ - cf2_cmdCALLSUBR, /* 10 */ - cf2_cmdRETURN, /* 11 */ - cf2_cmdESC, /* 12 */ - cf2_cmdRESERVED_13, /* 13 */ - cf2_cmdENDCHAR, /* 14 */ - cf2_cmdRESERVED_15, /* 15 */ - cf2_cmdRESERVED_16, /* 16 */ - cf2_cmdRESERVED_17, /* 17 */ - cf2_cmdHSTEMHM, /* 18 */ - cf2_cmdHINTMASK, /* 19 */ - cf2_cmdCNTRMASK, /* 20 */ - cf2_cmdRMOVETO, /* 21 */ - cf2_cmdHMOVETO, /* 22 */ - cf2_cmdVSTEMHM, /* 23 */ - cf2_cmdRCURVELINE, /* 24 */ - cf2_cmdRLINECURVE, /* 25 */ - cf2_cmdVVCURVETO, /* 26 */ - cf2_cmdHHCURVETO, /* 27 */ - cf2_cmdEXTENDEDNMBR, /* 28 */ - cf2_cmdCALLGSUBR, /* 29 */ - cf2_cmdVHCURVETO, /* 30 */ - cf2_cmdHVCURVETO /* 31 */ - }; - - enum - { - cf2_escDOTSECTION, /* 0 */ - cf2_escRESERVED_1, /* 1 */ - cf2_escRESERVED_2, /* 2 */ - cf2_escAND, /* 3 */ - cf2_escOR, /* 4 */ - cf2_escNOT, /* 5 */ - cf2_escRESERVED_6, /* 6 */ - cf2_escRESERVED_7, /* 7 */ - cf2_escRESERVED_8, /* 8 */ - cf2_escABS, /* 9 */ - cf2_escADD, /* 10 like otherADD */ - cf2_escSUB, /* 11 like otherSUB */ - cf2_escDIV, /* 12 */ - cf2_escRESERVED_13, /* 13 */ - cf2_escNEG, /* 14 */ - cf2_escEQ, /* 15 */ - cf2_escRESERVED_16, /* 16 */ - cf2_escRESERVED_17, /* 17 */ - cf2_escDROP, /* 18 */ - cf2_escRESERVED_19, /* 19 */ - cf2_escPUT, /* 20 like otherPUT */ - cf2_escGET, /* 21 like otherGET */ - cf2_escIFELSE, /* 22 like otherIFELSE */ - cf2_escRANDOM, /* 23 like otherRANDOM */ - cf2_escMUL, /* 24 like otherMUL */ - cf2_escRESERVED_25, /* 25 */ - cf2_escSQRT, /* 26 */ - cf2_escDUP, /* 27 like otherDUP */ - cf2_escEXCH, /* 28 like otherEXCH */ - cf2_escINDEX, /* 29 */ - cf2_escROLL, /* 30 */ - cf2_escRESERVED_31, /* 31 */ - cf2_escRESERVED_32, /* 32 */ - cf2_escRESERVED_33, /* 33 */ - cf2_escHFLEX, /* 34 */ - cf2_escFLEX, /* 35 */ - cf2_escHFLEX1, /* 36 */ - cf2_escFLEX1 /* 37 */ - }; - - - /* `stemHintArray' does not change once we start drawing the outline. */ - static void - cf2_doStems( const CF2_Font font, - CF2_Stack opStack, - CF2_ArrStack stemHintArray, - CF2_Fixed* width, - FT_Bool* haveWidth, - CF2_Fixed hintOffset ) - { - CF2_UInt i; - CF2_UInt count = cf2_stack_count( opStack ); - FT_Bool hasWidthArg = (FT_Bool)( count & 1 ); - - /* variable accumulates delta values from operand stack */ - CF2_Fixed position = hintOffset; - - if ( hasWidthArg && ! *haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + - cf2_getNominalWidthX( font->decoder ); - - if ( font->decoder->width_only ) - goto exit; - - for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 ) - { - /* construct a CF2_StemHint and push it onto the list */ - CF2_StemHintRec stemhint; - - - stemhint.min = - position += cf2_stack_getReal( opStack, i ); - stemhint.max = - position += cf2_stack_getReal( opStack, i + 1 ); - - stemhint.used = FALSE; - stemhint.maxDS = - stemhint.minDS = 0; - - cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */ - } - - cf2_stack_clear( opStack ); - - exit: - /* cf2_doStems must define a width (may be default) */ - *haveWidth = TRUE; - } - - - static void - cf2_doFlex( CF2_Stack opStack, - CF2_Fixed* curX, - CF2_Fixed* curY, - CF2_GlyphPath glyphPath, - const FT_Bool* readFromStack, - FT_Bool doConditionalLastRead ) - { - CF2_Fixed vals[14]; - CF2_UInt index; - FT_Bool isHFlex; - CF2_Int top, i, j; - - - vals[0] = *curX; - vals[1] = *curY; - index = 0; - isHFlex = readFromStack[9] == FALSE; - top = isHFlex ? 9 : 10; - - for ( i = 0; i < top; i++ ) - { - vals[i + 2] = vals[i]; - if ( readFromStack[i] ) - vals[i + 2] += cf2_stack_getReal( opStack, index++ ); - } - - if ( isHFlex ) - vals[9 + 2] = *curY; - - if ( doConditionalLastRead ) - { - FT_Bool lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) > - cf2_fixedAbs( vals[11] - *curY ) ); - CF2_Fixed lastVal = cf2_stack_getReal( opStack, index ); - - - if ( lastIsX ) - { - vals[12] = vals[10] + lastVal; - vals[13] = *curY; - } - else - { - vals[12] = *curX; - vals[13] = vals[11] + lastVal; - } - } - else - { - if ( readFromStack[10] ) - vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ ); - else - vals[12] = *curX; - - if ( readFromStack[11] ) - vals[13] = vals[11] + cf2_stack_getReal( opStack, index ); - else - vals[13] = *curY; - } - - for ( j = 0; j < 2; j++ ) - cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2], - vals[j * 6 + 3], - vals[j * 6 + 4], - vals[j * 6 + 5], - vals[j * 6 + 6], - vals[j * 6 + 7] ); - - cf2_stack_clear( opStack ); - - *curX = vals[12]; - *curY = vals[13]; - } - - - /* - * `error' is a shared error code used by many objects in this - * routine. Before the code continues from an error, it must check and - * record the error in `*error'. The idea is that this shared - * error code will record the first error encountered. If testing - * for an error anyway, the cost of `goto exit' is small, so we do it, - * even if continuing would be safe. In this case, `lastError' is - * set, so the testing and storing can be done in one place, at `exit'. - * - * Continuing after an error is intended for objects which do their own - * testing of `*error', e.g., array stack functions. This allows us to - * avoid an extra test after the call. - * - * Unimplemented opcodes are ignored. - * - */ - FT_LOCAL_DEF( void ) - cf2_interpT2CharString( CF2_Font font, - CF2_Buffer buf, - CF2_OutlineCallbacks callbacks, - const FT_Vector* translation, - FT_Bool doingSeac, - CF2_Fixed curX, - CF2_Fixed curY, - CF2_Fixed* width ) - { - /* lastError is used for errors that are immediately tested */ - FT_Error lastError = FT_Err_Ok; - - /* pointer to parsed font object */ - CFF_Decoder* decoder = font->decoder; - - FT_Error* error = &font->error; - FT_Memory memory = font->memory; - - CF2_Fixed scaleY = font->innerTransform.d; - CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder ); - - /* save this for hinting seac accents */ - CF2_Fixed hintOriginY = curY; - - CF2_Stack opStack = NULL; - FT_Byte op1; /* first opcode byte */ - - /* instruction limit; 20,000,000 matches Avalon */ - FT_UInt32 instructionLimit = 20000000UL; - - CF2_ArrStackRec subrStack; - - FT_Bool haveWidth; - CF2_Buffer charstring = NULL; - - CF2_Int charstringIndex = -1; /* initialize to empty */ - - /* TODO: placeholders for hint structures */ - - /* objects used for hinting */ - CF2_ArrStackRec hStemHintArray; - CF2_ArrStackRec vStemHintArray; - - CF2_HintMaskRec hintMask; - CF2_GlyphPathRec glyphPath; - - - /* initialize the remaining objects */ - cf2_arrstack_init( &subrStack, - memory, - error, - sizeof ( CF2_BufferRec ) ); - cf2_arrstack_init( &hStemHintArray, - memory, - error, - sizeof ( CF2_StemHintRec ) ); - cf2_arrstack_init( &vStemHintArray, - memory, - error, - sizeof ( CF2_StemHintRec ) ); - - /* initialize CF2_StemHint arrays */ - cf2_hintmask_init( &hintMask, error ); - - /* initialize path map to manage drawing operations */ - - /* Note: last 4 params are used to handle `MoveToPermissive', which */ - /* may need to call `hintMap.Build' */ - /* TODO: MoveToPermissive is gone; are these still needed? */ - cf2_glyphpath_init( &glyphPath, - font, - callbacks, - scaleY, - /* hShift, */ - &hStemHintArray, - &vStemHintArray, - &hintMask, - hintOriginY, - &font->blues, - translation ); - - /* - * Initialize state for width parsing. From the CFF Spec: - * - * The first stack-clearing operator, which must be one of hstem, - * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, - * rmoveto, or endchar, takes an additional argument - the width (as - * described earlier), which may be expressed as zero or one numeric - * argument. - * - * What we implement here uses the first validly specified width, but - * does not detect errors for specifying more than one width. - * - * If one of the above operators occurs without explicitly specifying - * a width, we assume the default width. - * - */ - haveWidth = FALSE; - *width = cf2_getDefaultWidthX( decoder ); - - /* - * Note: at this point, all pointers to resources must be NULL - * and all local objects must be initialized. - * There must be no branches to exit: above this point. - * - */ - - /* allocate an operand stack */ - opStack = cf2_stack_init( memory, error ); - if ( !opStack ) - { - lastError = FT_THROW( Out_Of_Memory ); - goto exit; - } - - /* initialize subroutine stack by placing top level charstring as */ - /* first element (max depth plus one for the charstring) */ - /* Note: Caller owns and must finalize the first charstring. */ - /* Our copy of it does not change that requirement. */ - cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 ); - - charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack ); - *charstring = *buf; /* structure copy */ - - charstringIndex = 0; /* entry is valid now */ - - /* catch errors so far */ - if ( *error ) - goto exit; - - /* main interpreter loop */ - while ( 1 ) - { - if ( cf2_buf_isEnd( charstring ) ) - { - /* If we've reached the end of the charstring, simulate a */ - /* cf2_cmdRETURN or cf2_cmdENDCHAR. */ - if ( charstringIndex ) - op1 = cf2_cmdRETURN; /* end of buffer for subroutine */ - else - op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */ - } - else - op1 = (FT_Byte)cf2_buf_readByte( charstring ); - - /* check for errors once per loop */ - if ( *error ) - goto exit; - - instructionLimit--; - if ( instructionLimit == 0 ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; - } - - switch( op1 ) - { - case cf2_cmdRESERVED_0: - case cf2_cmdRESERVED_2: - case cf2_cmdRESERVED_9: - case cf2_cmdRESERVED_13: - case cf2_cmdRESERVED_15: - case cf2_cmdRESERVED_16: - case cf2_cmdRESERVED_17: - /* we may get here if we have a prior error */ - FT_TRACE4(( " unknown op (%d)\n", op1 )); - break; - - case cf2_cmdHSTEMHM: - case cf2_cmdHSTEM: - FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" )); - - /* never add hints after the mask is computed */ - if ( cf2_hintmask_isValid( &hintMask ) ) - { - FT_TRACE4(( "cf2_interpT2CharString:" - " invalid horizontal hint mask\n" )); - break; - } - - cf2_doStems( font, - opStack, - &hStemHintArray, - width, - &haveWidth, - 0 ); - - if ( font->decoder->width_only ) - goto exit; - - break; - - case cf2_cmdVSTEMHM: - case cf2_cmdVSTEM: - FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" )); - - /* never add hints after the mask is computed */ - if ( cf2_hintmask_isValid( &hintMask ) ) - { - FT_TRACE4(( "cf2_interpT2CharString:" - " invalid vertical hint mask\n" )); - break; - } - - cf2_doStems( font, - opStack, - &vStemHintArray, - width, - &haveWidth, - 0 ); - - if ( font->decoder->width_only ) - goto exit; - - break; - - case cf2_cmdVMOVETO: - FT_TRACE4(( " vmoveto\n" )); - - if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - curY += cf2_stack_popFixed( opStack ); - - cf2_glyphpath_moveTo( &glyphPath, curX, curY ); - - break; - - case cf2_cmdRLINETO: - { - CF2_UInt index; - CF2_UInt count = cf2_stack_count( opStack ); - - - FT_TRACE4(( " rlineto\n" )); - - for ( index = 0; index < count; index += 2 ) - { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdHLINETO: - case cf2_cmdVLINETO: - { - CF2_UInt index; - CF2_UInt count = cf2_stack_count( opStack ); - - FT_Bool isX = op1 == cf2_cmdHLINETO; - - - FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); - - for ( index = 0; index < count; index++ ) - { - CF2_Fixed v = cf2_stack_getReal( opStack, index ); - - - if ( isX ) - curX += v; - else - curY += v; - - isX = !isX; - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - } - - cf2_stack_clear( opStack ); - } - continue; - - case cf2_cmdRCURVELINE: - case cf2_cmdRRCURVETO: - { - CF2_UInt count = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n" - : " rrcurveto\n" )); - - while ( index + 6 <= count ) - { - CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY; - CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1; - CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1; - CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2; - - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 6; - } - - if ( op1 == cf2_cmdRCURVELINE ) - { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdCALLGSUBR: - case cf2_cmdCALLSUBR: - { - CF2_UInt subrIndex; - - - FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr" - : " callsubr" )); - - if ( charstringIndex > CF2_MAX_SUBR ) - { - /* max subr plus one for charstring */ - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* overflow of stack */ - } - - /* push our current CFF charstring region on subrStack */ - charstring = (CF2_Buffer) - cf2_arrstack_getPointer( - &subrStack, - (size_t)charstringIndex + 1 ); - - /* set up the new CFF region and pointer */ - subrIndex = (CF2_UInt)cf2_stack_popInt( opStack ); - - switch ( op1 ) - { - case cf2_cmdCALLGSUBR: - FT_TRACE4(( " (idx %d, entering level %d)\n", - subrIndex + (CF2_UInt)decoder->globals_bias, - charstringIndex + 1 )); - - if ( cf2_initGlobalRegionBuffer( decoder, - subrIndex, - charstring ) ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* subroutine lookup or stream error */ - } - break; - - default: - /* cf2_cmdCALLSUBR */ - FT_TRACE4(( " (idx %d, entering level %d)\n", - subrIndex + (CF2_UInt)decoder->locals_bias, - charstringIndex + 1 )); - - if ( cf2_initLocalRegionBuffer( decoder, - subrIndex, - charstring ) ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* subroutine lookup or stream error */ - } - } - - charstringIndex += 1; /* entry is valid now */ - } - continue; /* do not clear the stack */ - - case cf2_cmdRETURN: - FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); - - if ( charstringIndex < 1 ) - { - /* Note: cannot return from top charstring */ - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* underflow of stack */ - } - - /* restore position in previous charstring */ - charstring = (CF2_Buffer) - cf2_arrstack_getPointer( - &subrStack, - (CF2_UInt)--charstringIndex ); - continue; /* do not clear the stack */ - - case cf2_cmdESC: - { - FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring ); - - - switch ( op2 ) - { - case cf2_escDOTSECTION: - /* something about `flip type of locking' -- ignore it */ - FT_TRACE4(( " dotsection\n" )); - - break; - - /* TODO: should these operators be supported? */ - case cf2_escAND: /* in spec */ - FT_TRACE4(( " and\n" )); - - CF2_FIXME; - break; - - case cf2_escOR: /* in spec */ - FT_TRACE4(( " or\n" )); - - CF2_FIXME; - break; - - case cf2_escNOT: /* in spec */ - FT_TRACE4(( " not\n" )); - - CF2_FIXME; - break; - - case cf2_escABS: /* in spec */ - FT_TRACE4(( " abs\n" )); - - CF2_FIXME; - break; - - case cf2_escADD: /* in spec */ - FT_TRACE4(( " add\n" )); - - CF2_FIXME; - break; - - case cf2_escSUB: /* in spec */ - FT_TRACE4(( " sub\n" )); - - CF2_FIXME; - break; - - case cf2_escDIV: /* in spec */ - FT_TRACE4(( " div\n" )); - - CF2_FIXME; - break; - - case cf2_escNEG: /* in spec */ - FT_TRACE4(( " neg\n" )); - - CF2_FIXME; - break; - - case cf2_escEQ: /* in spec */ - FT_TRACE4(( " eq\n" )); - - CF2_FIXME; - break; - - case cf2_escDROP: /* in spec */ - FT_TRACE4(( " drop\n" )); - - CF2_FIXME; - break; - - case cf2_escPUT: /* in spec */ - FT_TRACE4(( " put\n" )); - - CF2_FIXME; - break; - - case cf2_escGET: /* in spec */ - FT_TRACE4(( " get\n" )); - - CF2_FIXME; - break; - - case cf2_escIFELSE: /* in spec */ - FT_TRACE4(( " ifelse\n" )); - - CF2_FIXME; - break; - - case cf2_escRANDOM: /* in spec */ - FT_TRACE4(( " random\n" )); - - CF2_FIXME; - break; - - case cf2_escMUL: /* in spec */ - FT_TRACE4(( " mul\n" )); - - CF2_FIXME; - break; - - case cf2_escSQRT: /* in spec */ - FT_TRACE4(( " sqrt\n" )); - - CF2_FIXME; - break; - - case cf2_escDUP: /* in spec */ - FT_TRACE4(( " dup\n" )); - - CF2_FIXME; - break; - - case cf2_escEXCH: /* in spec */ - FT_TRACE4(( " exch\n" )); - - CF2_FIXME; - break; - - case cf2_escINDEX: /* in spec */ - FT_TRACE4(( " index\n" )); - - CF2_FIXME; - break; - - case cf2_escROLL: /* in spec */ - FT_TRACE4(( " roll\n" )); - - CF2_FIXME; - break; - - case cf2_escHFLEX: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, FALSE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, FALSE /* dy3 */, - TRUE /* dx4 */, FALSE /* dy4 */, - TRUE /* dx5 */, FALSE /* dy5 */, - TRUE /* dx6 */, FALSE /* dy6 */ - }; - - - FT_TRACE4(( " hflex\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - FALSE /* doConditionalLastRead */ ); - } - continue; - - case cf2_escFLEX: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, TRUE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, TRUE /* dy3 */, - TRUE /* dx4 */, TRUE /* dy4 */, - TRUE /* dx5 */, TRUE /* dy5 */, - TRUE /* dx6 */, TRUE /* dy6 */ - }; - - - FT_TRACE4(( " flex\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - FALSE /* doConditionalLastRead */ ); - } - break; /* TODO: why is this not a continue? */ - - case cf2_escHFLEX1: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, TRUE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, FALSE /* dy3 */, - TRUE /* dx4 */, FALSE /* dy4 */, - TRUE /* dx5 */, TRUE /* dy5 */, - TRUE /* dx6 */, FALSE /* dy6 */ - }; - - - FT_TRACE4(( " hflex1\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - FALSE /* doConditionalLastRead */ ); - } - continue; - - case cf2_escFLEX1: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, TRUE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, TRUE /* dy3 */, - TRUE /* dx4 */, TRUE /* dy4 */, - TRUE /* dx5 */, TRUE /* dy5 */, - FALSE /* dx6 */, FALSE /* dy6 */ - }; - - - FT_TRACE4(( " flex1\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - TRUE /* doConditionalLastRead */ ); - } - continue; - - case cf2_escRESERVED_1: - case cf2_escRESERVED_2: - case cf2_escRESERVED_6: - case cf2_escRESERVED_7: - case cf2_escRESERVED_8: - case cf2_escRESERVED_13: - case cf2_escRESERVED_16: - case cf2_escRESERVED_17: - case cf2_escRESERVED_19: - case cf2_escRESERVED_25: - case cf2_escRESERVED_31: - case cf2_escRESERVED_32: - case cf2_escRESERVED_33: - default: - FT_TRACE4(( " unknown op (12, %d)\n", op2 )); - - }; /* end of switch statement checking `op2' */ - - } /* case cf2_cmdESC */ - break; - - case cf2_cmdENDCHAR: - FT_TRACE4(( " endchar\n" )); - - if ( cf2_stack_count( opStack ) == 1 || - cf2_stack_count( opStack ) == 5 ) - { - if ( !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - } - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - /* close path if still open */ - cf2_glyphpath_closeOpenPath( &glyphPath ); - - if ( cf2_stack_count( opStack ) > 1 ) - { - /* must be either 4 or 5 -- */ - /* this is a (deprecated) implied `seac' operator */ - - CF2_Int achar; - CF2_Int bchar; - CF2_BufferRec component; - CF2_Fixed dummyWidth; /* ignore component width */ - FT_Error error2; - - - if ( doingSeac ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* nested seac */ - } - - achar = cf2_stack_popInt( opStack ); - bchar = cf2_stack_popInt( opStack ); - - curY = cf2_stack_popFixed( opStack ); - curX = cf2_stack_popFixed( opStack ); - - error2 = cf2_getSeacComponent( decoder, achar, &component ); - if ( error2 ) - { - lastError = error2; /* pass FreeType error through */ - goto exit; - } - cf2_interpT2CharString( font, - &component, - callbacks, - translation, - TRUE, - curX, - curY, - &dummyWidth ); - cf2_freeSeacComponent( decoder, &component ); - - error2 = cf2_getSeacComponent( decoder, bchar, &component ); - if ( error2 ) - { - lastError = error2; /* pass FreeType error through */ - goto exit; - } - cf2_interpT2CharString( font, - &component, - callbacks, - translation, - TRUE, - 0, - 0, - &dummyWidth ); - cf2_freeSeacComponent( decoder, &component ); - } - goto exit; - - case cf2_cmdCNTRMASK: - case cf2_cmdHINTMASK: - /* the final \n in the tracing message gets added in */ - /* `cf2_hintmask_read' (which also traces the mask bytes) */ - FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); - - /* never add hints after the mask is computed */ - if ( cf2_stack_count( opStack ) > 1 && - cf2_hintmask_isValid( &hintMask ) ) - { - FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" )); - break; - } - - /* if there are arguments on the stack, there this is an */ - /* implied cf2_cmdVSTEMHM */ - cf2_doStems( font, - opStack, - &vStemHintArray, - width, - &haveWidth, - 0 ); - - if ( font->decoder->width_only ) - goto exit; - - if ( op1 == cf2_cmdHINTMASK ) - { - /* consume the hint mask bytes which follow the operator */ - cf2_hintmask_read( &hintMask, - charstring, - cf2_arrstack_size( &hStemHintArray ) + - cf2_arrstack_size( &vStemHintArray ) ); - } - else - { - /* - * Consume the counter mask bytes which follow the operator: - * Build a temporary hint map, just to place and lock those - * stems participating in the counter mask. These are most - * likely the dominant hstems, and are grouped together in a - * few counter groups, not necessarily in correspondence - * with the hint groups. This reduces the chances of - * conflicts between hstems that are initially placed in - * separate hint groups and then brought together. The - * positions are copied back to `hStemHintArray', so we can - * discard `counterMask' and `counterHintMap'. - * - */ - CF2_HintMapRec counterHintMap; - CF2_HintMaskRec counterMask; - - - cf2_hintmap_init( &counterHintMap, - font, - &glyphPath.initialHintMap, - &glyphPath.hintMoves, - scaleY ); - cf2_hintmask_init( &counterMask, error ); - - cf2_hintmask_read( &counterMask, - charstring, - cf2_arrstack_size( &hStemHintArray ) + - cf2_arrstack_size( &vStemHintArray ) ); - cf2_hintmap_build( &counterHintMap, - &hStemHintArray, - &vStemHintArray, - &counterMask, - 0, - FALSE ); - } - break; - - case cf2_cmdRMOVETO: - FT_TRACE4(( " rmoveto\n" )); - - if ( cf2_stack_count( opStack ) > 2 && !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - curY += cf2_stack_popFixed( opStack ); - curX += cf2_stack_popFixed( opStack ); - - cf2_glyphpath_moveTo( &glyphPath, curX, curY ); - - break; - - case cf2_cmdHMOVETO: - FT_TRACE4(( " hmoveto\n" )); - - if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - curX += cf2_stack_popFixed( opStack ); - - cf2_glyphpath_moveTo( &glyphPath, curX, curY ); - - break; - - case cf2_cmdRLINECURVE: - { - CF2_UInt count = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - FT_TRACE4(( " rlinecurve\n" )); - - while ( index + 6 < count ) - { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - index += 2; - } - - while ( index < count ) - { - CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY; - CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1; - CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1; - CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2; - - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 6; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdVVCURVETO: - { - CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; - - FT_TRACE4(( " vvcurveto\n" )); - - while ( index < count ) - { - CF2_Fixed x1, y1, x2, y2, x3, y3; - - - if ( ( count - index ) & 1 ) - { - x1 = cf2_stack_getReal( opStack, index ) + curX; - - ++index; - } - else - x1 = curX; - - y1 = cf2_stack_getReal( opStack, index + 0 ) + curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = x2; - y3 = cf2_stack_getReal( opStack, index + 3 ) + y2; - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 4; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdHHCURVETO: - { - CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; - - FT_TRACE4(( " hhcurveto\n" )); - - while ( index < count ) - { - CF2_Fixed x1, y1, x2, y2, x3, y3; - - - if ( ( count - index ) & 1 ) - { - y1 = cf2_stack_getReal( opStack, index ) + curY; - - ++index; - } - else - y1 = curY; - - x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = cf2_stack_getReal( opStack, index + 3 ) + x2; - y3 = y2; - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 4; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdVHCURVETO: - case cf2_cmdHVCURVETO: - { - CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - FT_Bool alternate = op1 == cf2_cmdHVCURVETO; - - - /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ - /* 8n+4, or 8n+5, we enforce it by clearing the */ - /* second bit */ - /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; - - FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" )); - - while ( index < count ) - { - CF2_Fixed x1, x2, x3, y1, y2, y3; - - - if ( alternate ) - { - x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - y1 = curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - y3 = cf2_stack_getReal( opStack, index + 3 ) + y2; - - if ( count - index == 5 ) - { - x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - - ++index; - } - else - x3 = x2; - - alternate = FALSE; - } - else - { - x1 = curX; - y1 = cf2_stack_getReal( opStack, index + 0 ) + curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = cf2_stack_getReal( opStack, index + 3 ) + x2; - - if ( count - index == 5 ) - { - y3 = cf2_stack_getReal( opStack, index + 4 ) + y2; - - ++index; - } - else - y3 = y2; - - alternate = TRUE; - } - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 4; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdEXTENDEDNMBR: - { - CF2_Int v; - - - v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) | - cf2_buf_readByte( charstring ) ); - - FT_TRACE4(( " %d", v )); - - cf2_stack_pushInt( opStack, v ); - } - continue; - - default: - /* numbers */ - { - if ( /* op1 >= 32 && */ op1 <= 246 ) - { - CF2_Int v; - - - v = op1 - 139; - - FT_TRACE4(( " %d", v )); - - /* -107 .. 107 */ - cf2_stack_pushInt( opStack, v ); - } - - else if ( /* op1 >= 247 && */ op1 <= 250 ) - { - CF2_Int v; - - - v = op1; - v -= 247; - v *= 256; - v += cf2_buf_readByte( charstring ); - v += 108; - - FT_TRACE4(( " %d", v )); - - /* 108 .. 1131 */ - cf2_stack_pushInt( opStack, v ); - } - - else if ( /* op1 >= 251 && */ op1 <= 254 ) - { - CF2_Int v; - - - v = op1; - v -= 251; - v *= 256; - v += cf2_buf_readByte( charstring ); - v = -v - 108; - - FT_TRACE4(( " %d", v )); - - /* -1131 .. -108 */ - cf2_stack_pushInt( opStack, v ); - } - - else /* op1 == 255 */ - { - CF2_Fixed v; - - - v = (CF2_Fixed) - ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) | - ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) | - ( (FT_UInt32)cf2_buf_readByte( charstring ) << 8 ) | - (FT_UInt32)cf2_buf_readByte( charstring ) ); - - FT_TRACE4(( " %.2f", v / 65536.0 )); - - cf2_stack_pushFixed( opStack, v ); - } - } - continue; /* don't clear stack */ - - } /* end of switch statement checking `op1' */ - - cf2_stack_clear( opStack ); - - } /* end of main interpreter loop */ - - /* we get here if the charstring ends without cf2_cmdENDCHAR */ - FT_TRACE4(( "cf2_interpT2CharString:" - " charstring ends without ENDCHAR\n" )); - - exit: - /* check whether last error seen is also the first one */ - cf2_setError( error, lastError ); - - /* free resources from objects we've used */ - cf2_glyphpath_finalize( &glyphPath ); - cf2_arrstack_finalize( &vStemHintArray ); - cf2_arrstack_finalize( &hStemHintArray ); - cf2_arrstack_finalize( &subrStack ); - cf2_stack_free( opStack ); - - FT_TRACE4(( "\n" )); - - return; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2intrp.h b/third_party/freetype/src/cff/cf2intrp.h deleted file mode 100644 index b5d8947838e9fb610285cb86f6d9e2ec4e12f0c5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2intrp.h +++ /dev/null @@ -1,83 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2font.h */ -/* */ -/* Adobe's CFF Interpreter (specification). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2INTRP_H__ -#define __CF2INTRP_H__ - - -#include "cf2ft.h" -#include "cf2hints.h" - - -FT_BEGIN_HEADER - - - FT_LOCAL( void ) - cf2_hintmask_init( CF2_HintMask hintmask, - FT_Error* error ); - FT_LOCAL( FT_Bool ) - cf2_hintmask_isValid( const CF2_HintMask hintmask ); - FT_LOCAL( FT_Bool ) - cf2_hintmask_isNew( const CF2_HintMask hintmask ); - FT_LOCAL( void ) - cf2_hintmask_setNew( CF2_HintMask hintmask, - FT_Bool val ); - FT_LOCAL( FT_Byte* ) - cf2_hintmask_getMaskPtr( CF2_HintMask hintmask ); - FT_LOCAL( void ) - cf2_hintmask_setAll( CF2_HintMask hintmask, - size_t bitCount ); - - FT_LOCAL( void ) - cf2_interpT2CharString( CF2_Font font, - CF2_Buffer charstring, - CF2_OutlineCallbacks callbacks, - const FT_Vector* translation, - FT_Bool doingSeac, - CF2_Fixed curX, - CF2_Fixed curY, - CF2_Fixed* width ); - - -FT_END_HEADER - - -#endif /* __CF2INTRP_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2read.c b/third_party/freetype/src/cff/cf2read.c deleted file mode 100644 index 2b429e3eeb0ea3433dc33c0b9646fc46ee0d643e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2read.c +++ /dev/null @@ -1,112 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2read.c */ -/* */ -/* Adobe's code for stream handling (body). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2glue.h" - -#include "cf2error.h" - - - /* Define CF2_IO_FAIL as 1 to enable random errors and random */ - /* value errors in I/O. */ -#define CF2_IO_FAIL 0 - - -#if CF2_IO_FAIL - - /* set the .00 value to a nonzero probability */ - static int - randomError2( void ) - { - /* for region buffer ReadByte (interp) function */ - return (double)rand() / RAND_MAX < .00; - } - - /* set the .00 value to a nonzero probability */ - static CF2_Int - randomValue() - { - return (double)rand() / RAND_MAX < .00 ? rand() : 0; - } - -#endif /* CF2_IO_FAIL */ - - - /* Region Buffer */ - /* */ - /* Can be constructed from a copied buffer managed by */ - /* `FCM_getDatablock'. */ - /* Reads bytes with check for end of buffer. */ - - /* reading past the end of the buffer sets error and returns zero */ - FT_LOCAL_DEF( CF2_Int ) - cf2_buf_readByte( CF2_Buffer buf ) - { - if ( buf->ptr < buf->end ) - { -#if CF2_IO_FAIL - if ( randomError2() ) - { - CF2_SET_ERROR( buf->error, Invalid_Stream_Operation ); - return 0; - } - - return *(buf->ptr)++ + randomValue(); -#else - return *(buf->ptr)++; -#endif - } - else - { - CF2_SET_ERROR( buf->error, Invalid_Stream_Operation ); - return 0; - } - } - - - /* note: end condition can occur without error */ - FT_LOCAL_DEF( FT_Bool ) - cf2_buf_isEnd( CF2_Buffer buf ) - { - return (FT_Bool)( buf->ptr >= buf->end ); - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2read.h b/third_party/freetype/src/cff/cf2read.h deleted file mode 100644 index 7ef7c8c1493d520ecdfd67c3161c2b6968ab6ec2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2read.h +++ /dev/null @@ -1,68 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2read.h */ -/* */ -/* Adobe's code for stream handling (specification). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2READ_H__ -#define __CF2READ_H__ - - -FT_BEGIN_HEADER - - - typedef struct CF2_BufferRec_ - { - FT_Error* error; - const FT_Byte* start; - const FT_Byte* end; - const FT_Byte* ptr; - - } CF2_BufferRec, *CF2_Buffer; - - - FT_LOCAL( CF2_Int ) - cf2_buf_readByte( CF2_Buffer buf ); - FT_LOCAL( FT_Bool ) - cf2_buf_isEnd( CF2_Buffer buf ); - - -FT_END_HEADER - - -#endif /* __CF2READ_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2stack.c b/third_party/freetype/src/cff/cf2stack.c deleted file mode 100644 index 8332b5d91aaba6d364484e3a9a13534e24c978e3..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2stack.c +++ /dev/null @@ -1,205 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2stack.c */ -/* */ -/* Adobe's code for emulating a CFF stack (body). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2stack.h" - -#include "cf2error.h" - - - /* Allocate and initialize an instance of CF2_Stack. */ - /* Note: This function returns NULL on error (does not set */ - /* `error'). */ - FT_LOCAL_DEF( CF2_Stack ) - cf2_stack_init( FT_Memory memory, - FT_Error* e ) - { - FT_Error error = FT_Err_Ok; /* for FT_QNEW */ - - CF2_Stack stack = NULL; - - - if ( !FT_QNEW( stack ) ) - { - /* initialize the structure; FT_QNEW zeroes it */ - stack->memory = memory; - stack->error = e; - stack->top = &stack->buffer[0]; /* empty stack */ - } - - return stack; - } - - - FT_LOCAL_DEF( void ) - cf2_stack_free( CF2_Stack stack ) - { - if ( stack ) - { - FT_Memory memory = stack->memory; - - - /* free the main structure */ - FT_FREE( stack ); - } - } - - - FT_LOCAL_DEF( CF2_UInt ) - cf2_stack_count( CF2_Stack stack ) - { - return (CF2_UInt)( stack->top - &stack->buffer[0] ); - } - - - FT_LOCAL_DEF( void ) - cf2_stack_pushInt( CF2_Stack stack, - CF2_Int val ) - { - if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] ) - { - CF2_SET_ERROR( stack->error, Stack_Overflow ); - return; /* stack overflow */ - } - - stack->top->u.i = val; - stack->top->type = CF2_NumberInt; - ++stack->top; - } - - - FT_LOCAL_DEF( void ) - cf2_stack_pushFixed( CF2_Stack stack, - CF2_Fixed val ) - { - if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] ) - { - CF2_SET_ERROR( stack->error, Stack_Overflow ); - return; /* stack overflow */ - } - - stack->top->u.r = val; - stack->top->type = CF2_NumberFixed; - ++stack->top; - } - - - /* this function is only allowed to pop an integer type */ - FT_LOCAL_DEF( CF2_Int ) - cf2_stack_popInt( CF2_Stack stack ) - { - if ( stack->top == &stack->buffer[0] ) - { - CF2_SET_ERROR( stack->error, Stack_Underflow ); - return 0; /* underflow */ - } - if ( stack->top[-1].type != CF2_NumberInt ) - { - CF2_SET_ERROR( stack->error, Syntax_Error ); - return 0; /* type mismatch */ - } - - --stack->top; - - return stack->top->u.i; - } - - - /* Note: type mismatch is silently cast */ - /* TODO: check this */ - FT_LOCAL_DEF( CF2_Fixed ) - cf2_stack_popFixed( CF2_Stack stack ) - { - if ( stack->top == &stack->buffer[0] ) - { - CF2_SET_ERROR( stack->error, Stack_Underflow ); - return cf2_intToFixed( 0 ); /* underflow */ - } - - --stack->top; - - switch ( stack->top->type ) - { - case CF2_NumberInt: - return cf2_intToFixed( stack->top->u.i ); - case CF2_NumberFrac: - return cf2_fracToFixed( stack->top->u.f ); - default: - return stack->top->u.r; - } - } - - - /* Note: type mismatch is silently cast */ - /* TODO: check this */ - FT_LOCAL_DEF( CF2_Fixed ) - cf2_stack_getReal( CF2_Stack stack, - CF2_UInt idx ) - { - FT_ASSERT( cf2_stack_count( stack ) <= CF2_OPERAND_STACK_SIZE ); - - if ( idx >= cf2_stack_count( stack ) ) - { - CF2_SET_ERROR( stack->error, Stack_Overflow ); - return cf2_intToFixed( 0 ); /* bounds error */ - } - - switch ( stack->buffer[idx].type ) - { - case CF2_NumberInt: - return cf2_intToFixed( stack->buffer[idx].u.i ); - case CF2_NumberFrac: - return cf2_fracToFixed( stack->buffer[idx].u.f ); - default: - return stack->buffer[idx].u.r; - } - } - - - FT_LOCAL_DEF( void ) - cf2_stack_clear( CF2_Stack stack ) - { - stack->top = &stack->buffer[0]; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2stack.h b/third_party/freetype/src/cff/cf2stack.h deleted file mode 100644 index 7d6d1961fe9dfeb522d5aea0bf601d3cbf5da776..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2stack.h +++ /dev/null @@ -1,106 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2stack.h */ -/* */ -/* Adobe's code for emulating a CFF stack (specification). */ -/* */ -/* Copyright 2007-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2STACK_H__ -#define __CF2STACK_H__ - - -FT_BEGIN_HEADER - - - /* CFF operand stack; specified maximum of 48 or 192 values */ - typedef struct CF2_StackNumber_ - { - union - { - CF2_Fixed r; /* 16.16 fixed point */ - CF2_Frac f; /* 2.30 fixed point (for font matrix) */ - CF2_Int i; - } u; - - CF2_NumberType type; - - } CF2_StackNumber; - - - typedef struct CF2_StackRec_ - { - FT_Memory memory; - FT_Error* error; - CF2_StackNumber buffer[CF2_OPERAND_STACK_SIZE]; - CF2_StackNumber* top; - - } CF2_StackRec, *CF2_Stack; - - - FT_LOCAL( CF2_Stack ) - cf2_stack_init( FT_Memory memory, - FT_Error* error ); - FT_LOCAL( void ) - cf2_stack_free( CF2_Stack stack ); - - FT_LOCAL( CF2_UInt ) - cf2_stack_count( CF2_Stack stack ); - - FT_LOCAL( void ) - cf2_stack_pushInt( CF2_Stack stack, - CF2_Int val ); - FT_LOCAL( void ) - cf2_stack_pushFixed( CF2_Stack stack, - CF2_Fixed val ); - - FT_LOCAL( CF2_Int ) - cf2_stack_popInt( CF2_Stack stack ); - FT_LOCAL( CF2_Fixed ) - cf2_stack_popFixed( CF2_Stack stack ); - - FT_LOCAL( CF2_Fixed ) - cf2_stack_getReal( CF2_Stack stack, - CF2_UInt idx ); - - FT_LOCAL( void ) - cf2_stack_clear( CF2_Stack stack ); - - -FT_END_HEADER - - -#endif /* __CF2STACK_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cf2types.h b/third_party/freetype/src/cff/cf2types.h deleted file mode 100644 index ac6a02266e7c9a4751cab390edf1910dc55ec078..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cf2types.h +++ /dev/null @@ -1,78 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2types.h */ -/* */ -/* Adobe's code for defining data types (specification only). */ -/* */ -/* Copyright 2011-2013 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CF2TYPES_H__ -#define __CF2TYPES_H__ - -#include <ft2build.h> -#include FT_FREETYPE_H - - -FT_BEGIN_HEADER - - - /* - * The data models that we expect to support are as follows: - * - * name char short int long long-long pointer example - * ----------------------------------------------------- - * ILP32 8 16 32 32 64* 32 32-bit MacOS, x86 - * LLP64 8 16 32 32 64 64 x64 - * LP64 8 16 32 64 64 64 64-bit MacOS - * - * *) type may be supported by emulation on a 32-bit architecture - * - */ - - - /* integers at least 32 bits wide */ -#define CF2_UInt FT_UFast -#define CF2_Int FT_Fast - - - /* fixed-float numbers */ - typedef FT_Int32 CF2_F16Dot16; - - -FT_END_HEADER - - -#endif /* __CF2TYPES_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cff.c b/third_party/freetype/src/cff/cff.c deleted file mode 100644 index bb2cfb525315a743d6200009322f4de8a2c4a9a2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cff.c +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************/ -/* */ -/* cff.c */ -/* */ -/* FreeType OpenType driver component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> - -#include "cffpic.c" -#include "cffdrivr.c" -#include "cffparse.c" -#include "cffload.c" -#include "cffobjs.c" -#include "cffgload.c" -#include "cffcmap.c" - -#include "cf2arrst.c" -#include "cf2blues.c" -#include "cf2error.c" -#include "cf2font.c" -#include "cf2ft.c" -#include "cf2hints.c" -#include "cf2intrp.c" -#include "cf2read.c" -#include "cf2stack.c" - -/* END */ diff --git a/third_party/freetype/src/cff/cffcmap.c b/third_party/freetype/src/cff/cffcmap.c deleted file mode 100644 index e7538e9840587bea899e80652d22d8b0b5a1ef87..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffcmap.c +++ /dev/null @@ -1,216 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffcmap.c */ -/* */ -/* CFF character mapping table (cmap) support (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include "cffcmap.h" -#include "cffload.h" - -#include "cfferrs.h" - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_CALLBACK_DEF( FT_Error ) - cff_cmap_encoding_init( CFF_CMapStd cmap, - FT_Pointer pointer ) - { - TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Encoding encoding = &cff->encoding; - - FT_UNUSED( pointer ); - - - cmap->gids = encoding->codes; - - return 0; - } - - - FT_CALLBACK_DEF( void ) - cff_cmap_encoding_done( CFF_CMapStd cmap ) - { - cmap->gids = NULL; - } - - - FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_encoding_char_index( CFF_CMapStd cmap, - FT_UInt32 char_code ) - { - FT_UInt result = 0; - - - if ( char_code < 256 ) - result = cmap->gids[char_code]; - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_encoding_char_next( CFF_CMapStd cmap, - FT_UInt32 *pchar_code ) - { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; - - - *pchar_code = 0; - - if ( char_code < 255 ) - { - FT_UInt code = (FT_UInt)(char_code + 1); - - - for (;;) - { - if ( code >= 256 ) - break; - - result = cmap->gids[code]; - if ( result != 0 ) - { - *pchar_code = code; - break; - } - - code++; - } - } - return result; - } - - - FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec, - sizeof ( CFF_CMapStdRec ), - - (FT_CMap_InitFunc) cff_cmap_encoding_init, - (FT_CMap_DoneFunc) cff_cmap_encoding_done, - (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index, - (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next, - - NULL, NULL, NULL, NULL, NULL - ) - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_CALLBACK_DEF( const char* ) - cff_sid_to_glyph_name( TT_Face face, - FT_UInt idx ) - { - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Charset charset = &cff->charset; - FT_UInt sid = charset->sids[idx]; - - - return cff_index_get_sid_string( cff, sid ); - } - - - FT_CALLBACK_DEF( FT_Error ) - cff_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) - { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Charset charset = &cff->charset; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; - - FT_UNUSED( pointer ); - - - /* can't build Unicode map for CID-keyed font */ - /* because we don't know glyph names. */ - if ( !charset->sids ) - return FT_THROW( No_Unicode_Glyph_Name ); - - return psnames->unicodes_init( memory, - unicodes, - cff->num_glyphs, - (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name, - (PS_FreeGlyphNameFunc)NULL, - (FT_Pointer)face ); - } - - - FT_CALLBACK_DEF( void ) - cff_cmap_unicode_done( PS_Unicodes unicodes ) - { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - - - FT_FREE( unicodes->maps ); - unicodes->num_maps = 0; - } - - - FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) - { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; - - - return psnames->unicodes_char_index( unicodes, char_code ); - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) - { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; - - - return psnames->unicodes_char_next( unicodes, pchar_code ); - } - - - FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec, - sizeof ( PS_UnicodesRec ), - - (FT_CMap_InitFunc) cff_cmap_unicode_init, - (FT_CMap_DoneFunc) cff_cmap_unicode_done, - (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index, - (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next, - - NULL, NULL, NULL, NULL, NULL - ) - -/* END */ diff --git a/third_party/freetype/src/cff/cffcmap.h b/third_party/freetype/src/cff/cffcmap.h deleted file mode 100644 index 6eaed636ec0eb10f68b7b62a291801325fe81df4..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffcmap.h +++ /dev/null @@ -1,67 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffcmap.h */ -/* */ -/* CFF character mapping table (cmap) support (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFCMAP_H__ -#define __CFFCMAP_H__ - -#include "cffobjs.h" - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* standard (and expert) encoding cmaps */ - typedef struct CFF_CMapStdRec_* CFF_CMapStd; - - typedef struct CFF_CMapStdRec_ - { - FT_CMapRec cmap; - FT_UShort* gids; /* up to 256 elements */ - - } CFF_CMapStdRec; - - - FT_DECLARE_CMAP_CLASS(cff_cmap_encoding_class_rec) - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* unicode (synthetic) cmaps */ - - FT_DECLARE_CMAP_CLASS(cff_cmap_unicode_class_rec) - - -FT_END_HEADER - -#endif /* __CFFCMAP_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffdrivr.c b/third_party/freetype/src/cff/cffdrivr.c deleted file mode 100644 index a718b7a002484a300e571bcd49dfd5b041e015bc..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffdrivr.c +++ /dev/null @@ -1,907 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffdrivr.c */ -/* */ -/* OpenType font driver implementation (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_SERVICE_CID_H -#include FT_SERVICE_POSTSCRIPT_INFO_H -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_TT_CMAP_H - -#include "cffdrivr.h" -#include "cffgload.h" -#include "cffload.h" -#include "cffcmap.h" -#include "cffparse.h" - -#include "cfferrs.h" -#include "cffpic.h" - -#include FT_SERVICE_FONT_FORMAT_H -#include FT_SERVICE_GLYPH_DICT_H -#include FT_SERVICE_PROPERTIES_H -#include FT_CFF_DRIVER_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cffdriver - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** F A C E S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_get_kerning */ - /* */ - /* <Description> */ - /* A driver method used to return the kerning vector between two */ - /* glyphs of the same face. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* left_glyph :: The index of the left glyph in the kern pair. */ - /* */ - /* right_glyph :: The index of the right glyph in the kern pair. */ - /* */ - /* <Output> */ - /* kerning :: The kerning vector. This is in font units for */ - /* scalable formats, and in pixels for fixed-sizes */ - /* formats. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* Only horizontal layouts (left-to-right & right-to-left) are */ - /* supported by this function. Other layouts, or more sophisticated */ - /* kernings, are out of scope of this method (the basic driver */ - /* interface is meant to be simple). */ - /* */ - /* They can be implemented by format-specific interfaces. */ - /* */ - FT_CALLBACK_DEF( FT_Error ) - cff_get_kerning( FT_Face ttface, /* TT_Face */ - FT_UInt left_glyph, - FT_UInt right_glyph, - FT_Vector* kerning ) - { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; - - - kerning->x = 0; - kerning->y = 0; - - if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_glyph_load */ - /* */ - /* <Description> */ - /* A driver method used to load a glyph within a given glyph slot. */ - /* */ - /* <Input> */ - /* slot :: A handle to the target slot object where the glyph */ - /* will be loaded. */ - /* */ - /* size :: A handle to the source face size at which the glyph */ - /* must be scaled, loaded, etc. */ - /* */ - /* glyph_index :: The index of the glyph in the font file. */ - /* */ - /* load_flags :: A flag indicating what to load for this glyph. The */ - /* FT_LOAD_??? constants can be used to control the */ - /* glyph loading process (e.g., whether the outline */ - /* should be scaled, whether to load bitmaps or not, */ - /* whether to hint the outline, etc). */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_CALLBACK_DEF( FT_Error ) - cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ - FT_Size cffsize, /* CFF_Size */ - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - FT_Error error; - CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; - CFF_Size size = (CFF_Size)cffsize; - - - if ( !slot ) - return FT_THROW( Invalid_Slot_Handle ); - - FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); - - /* check whether we want a scaled outline or bitmap */ - if ( !size ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; - - /* reset the size object if necessary */ - if ( load_flags & FT_LOAD_NO_SCALE ) - size = NULL; - - if ( size ) - { - /* these two objects must have the same parent */ - if ( cffsize->face != cffslot->face ) - return FT_THROW( Invalid_Face_Handle ); - } - - /* now load the glyph outline if necessary */ - error = cff_slot_load( slot, size, glyph_index, load_flags ); - - /* force drop-out mode to 2 - irrelevant now */ - /* slot->outline.dropout_mode = 2; */ - - return error; - } - - - FT_CALLBACK_DEF( FT_Error ) - cff_get_advances( FT_Face face, - FT_UInt start, - FT_UInt count, - FT_Int32 flags, - FT_Fixed* advances ) - { - FT_UInt nn; - FT_Error error = FT_Err_Ok; - FT_GlyphSlot slot = face->glyph; - - - if ( FT_IS_SFNT( face ) ) - { - /* OpenType 1.7 mandates that the data from `hmtx' table be used; */ - /* it is no longer necessary that those values are identical to */ - /* the values in the `CFF' table */ - - TT_Face ttface = (TT_Face)face; - FT_Short dummy; - - - if ( flags & FT_LOAD_VERTICAL_LAYOUT ) - { - /* check whether we have data from the `vmtx' table at all; */ - /* otherwise we extract the info from the CFF glyphstrings */ - /* (instead of synthesizing a global value using the `OS/2' */ - /* table) */ - if ( !ttface->vertical_info ) - goto Missing_Table; - - for ( nn = 0; nn < count; nn++ ) - { - FT_UShort ah; - - - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 1, - start + nn, - &dummy, - &ah ); - - FT_TRACE5(( " idx %d: advance height %d font units\n", - start + nn, ah )); - advances[nn] = ah; - } - } - else - { - /* check whether we have data from the `hmtx' table at all */ - if ( !ttface->horizontal.number_Of_HMetrics ) - goto Missing_Table; - - for ( nn = 0; nn < count; nn++ ) - { - FT_UShort aw; - - - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 0, - start + nn, - &dummy, - &aw ); - - FT_TRACE5(( " idx %d: advance width %d font units\n", - start + nn, aw )); - advances[nn] = aw; - } - } - - return error; - } - - Missing_Table: - flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; - - for ( nn = 0; nn < count; nn++ ) - { - error = cff_glyph_load( slot, face->size, start + nn, flags ); - if ( error ) - break; - - advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) - ? slot->linearVertAdvance - : slot->linearHoriAdvance; - } - - return error; - } - - - /* - * GLYPH DICT SERVICE - * - */ - - static FT_Error - cff_get_glyph_name( CFF_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ) - { - CFF_Font font = (CFF_Font)face->extra.data; - FT_String* gname; - FT_UShort sid; - FT_Error error; - - - if ( !font->psnames ) - { - FT_ERROR(( "cff_get_glyph_name:" - " cannot get glyph name from CFF & CEF fonts\n" - " " - " without the `PSNames' module\n" )); - error = FT_THROW( Missing_Module ); - goto Exit; - } - - /* first, locate the sid in the charset table */ - sid = font->charset.sids[glyph_index]; - - /* now, lookup the name itself */ - gname = cff_index_get_sid_string( font, sid ); - - if ( gname ) - FT_STRCPYN( buffer, gname, buffer_max ); - - error = FT_Err_Ok; - - Exit: - return error; - } - - - static FT_UInt - cff_get_name_index( CFF_Face face, - FT_String* glyph_name ) - { - CFF_Font cff; - CFF_Charset charset; - FT_Service_PsCMaps psnames; - FT_String* name; - FT_UShort sid; - FT_UInt i; - - - cff = (CFF_FontRec *)face->extra.data; - charset = &cff->charset; - - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); - if ( !psnames ) - return 0; - - for ( i = 0; i < cff->num_glyphs; i++ ) - { - sid = charset->sids[i]; - - if ( sid > 390 ) - name = cff_index_get_string( cff, sid - 391 ); - else - name = (FT_String *)psnames->adobe_std_strings( sid ); - - if ( !name ) - continue; - - if ( !ft_strcmp( glyph_name, name ) ) - return i; - } - - return 0; - } - - - FT_DEFINE_SERVICE_GLYPHDICTREC( - cff_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, - (FT_GlyphDict_NameIndexFunc)cff_get_name_index - ) - - - /* - * POSTSCRIPT INFO SERVICE - * - */ - - static FT_Int - cff_ps_has_glyph_names( FT_Face face ) - { - return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; - } - - - static FT_Error - cff_ps_get_font_info( CFF_Face face, - PS_FontInfoRec* afont_info ) - { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; - - - if ( cff && cff->font_info == NULL ) - { - CFF_FontRecDict dict = &cff->top_font.font_dict; - PS_FontInfoRec *font_info = NULL; - FT_Memory memory = face->root.memory; - - - if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) - goto Fail; - - font_info->version = cff_index_get_sid_string( cff, - dict->version ); - font_info->notice = cff_index_get_sid_string( cff, - dict->notice ); - font_info->full_name = cff_index_get_sid_string( cff, - dict->full_name ); - font_info->family_name = cff_index_get_sid_string( cff, - dict->family_name ); - font_info->weight = cff_index_get_sid_string( cff, - dict->weight ); - font_info->italic_angle = dict->italic_angle; - font_info->is_fixed_pitch = dict->is_fixed_pitch; - font_info->underline_position = (FT_Short)dict->underline_position; - font_info->underline_thickness = (FT_UShort)dict->underline_thickness; - - cff->font_info = font_info; - } - - if ( cff ) - *afont_info = *cff->font_info; - - Fail: - return error; - } - - - FT_DEFINE_SERVICE_PSINFOREC( - cff_service_ps_info, - (PS_GetFontInfoFunc) cff_ps_get_font_info, - (PS_GetFontExtraFunc) NULL, - (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, - (PS_GetFontPrivateFunc)NULL, /* unsupported with CFF fonts */ - (PS_GetFontValueFunc) NULL /* not implemented */ - ) - - - /* - * POSTSCRIPT NAME SERVICE - * - */ - - static const char* - cff_get_ps_name( CFF_Face face ) - { - CFF_Font cff = (CFF_Font)face->extra.data; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; - - - /* following the OpenType specification 1.7, we return the name stored */ - /* in the `name' table for a CFF wrapped into an SFNT container */ - - if ( sfnt ) - { - FT_Library library = FT_FACE_LIBRARY( face ); - FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); - FT_Service_PsFontName service = - (FT_Service_PsFontName)ft_module_get_service( - sfnt_module, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME ); - - - if ( service && service->get_ps_font_name ) - return service->get_ps_font_name( FT_FACE( face ) ); - } - - return (const char*)cff->font_name; - } - - - FT_DEFINE_SERVICE_PSFONTNAMEREC( - cff_service_ps_name, - (FT_PsName_GetFunc)cff_get_ps_name - ) - - - /* - * TT CMAP INFO - * - * If the charmap is a synthetic Unicode encoding cmap or - * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO - * service defined in SFNT module. - * - * Otherwise call the service function in the sfnt module. - * - */ - static FT_Error - cff_get_cmap_info( FT_CharMap charmap, - TT_CMapInfo *cmap_info ) - { - FT_CMap cmap = FT_CMAP( charmap ); - FT_Error error = FT_Err_Ok; - - FT_Face face = FT_CMAP_FACE( cmap ); - FT_Library library = FT_FACE_LIBRARY( face ); - - - cmap_info->language = 0; - cmap_info->format = 0; - - if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET && - cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET ) - { - FT_Module sfnt = FT_Get_Module( library, "sfnt" ); - FT_Service_TTCMaps service = - (FT_Service_TTCMaps)ft_module_get_service( sfnt, - FT_SERVICE_ID_TT_CMAP ); - - - if ( service && service->get_cmap_info ) - error = service->get_cmap_info( charmap, cmap_info ); - } - - return error; - } - - - FT_DEFINE_SERVICE_TTCMAPSREC( - cff_service_get_cmap_info, - (TT_CMap_Info_GetFunc)cff_get_cmap_info - ) - - - /* - * CID INFO SERVICE - * - */ - static FT_Error - cff_get_ros( CFF_Face face, - const char* *registry, - const char* *ordering, - FT_Int *supplement ) - { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; - - - if ( cff ) - { - CFF_FontRecDict dict = &cff->top_font.font_dict; - - - if ( dict->cid_registry == 0xFFFFU ) - { - error = FT_THROW( Invalid_Argument ); - goto Fail; - } - - if ( registry ) - { - if ( cff->registry == NULL ) - cff->registry = cff_index_get_sid_string( cff, - dict->cid_registry ); - *registry = cff->registry; - } - - if ( ordering ) - { - if ( cff->ordering == NULL ) - cff->ordering = cff_index_get_sid_string( cff, - dict->cid_ordering ); - *ordering = cff->ordering; - } - - /* - * XXX: According to Adobe TechNote #5176, the supplement in CFF - * can be a real number. We truncate it to fit public API - * since freetype-2.3.6. - */ - if ( supplement ) - { - if ( dict->cid_supplement < FT_INT_MIN || - dict->cid_supplement > FT_INT_MAX ) - FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n", - dict->cid_supplement )); - *supplement = (FT_Int)dict->cid_supplement; - } - } - - Fail: - return error; - } - - - static FT_Error - cff_get_is_cid( CFF_Face face, - FT_Bool *is_cid ) - { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; - - - *is_cid = 0; - - if ( cff ) - { - CFF_FontRecDict dict = &cff->top_font.font_dict; - - - if ( dict->cid_registry != 0xFFFFU ) - *is_cid = 1; - } - - return error; - } - - - static FT_Error - cff_get_cid_from_glyph_index( CFF_Face face, - FT_UInt glyph_index, - FT_UInt *cid ) - { - FT_Error error = FT_Err_Ok; - CFF_Font cff; - - - cff = (CFF_Font)face->extra.data; - - if ( cff ) - { - FT_UInt c; - CFF_FontRecDict dict = &cff->top_font.font_dict; - - - if ( dict->cid_registry == 0xFFFFU ) - { - error = FT_THROW( Invalid_Argument ); - goto Fail; - } - - if ( glyph_index > cff->num_glyphs ) - { - error = FT_THROW( Invalid_Argument ); - goto Fail; - } - - c = cff->charset.sids[glyph_index]; - - if ( cid ) - *cid = c; - } - - Fail: - return error; - } - - - FT_DEFINE_SERVICE_CIDREC( - cff_service_cid_info, - (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros, - (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid, - (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index - ) - - - /* - * PROPERTY SERVICE - * - */ - static FT_Error - cff_property_set( FT_Module module, /* CFF_Driver */ - const char* property_name, - const void* value ) - { - FT_Error error = FT_Err_Ok; - CFF_Driver driver = (CFF_Driver)module; - - - if ( !ft_strcmp( property_name, "darkening-parameters" ) ) - { - FT_Int* darken_params = (FT_Int*)value; - - FT_Int x1 = darken_params[0]; - FT_Int y1 = darken_params[1]; - FT_Int x2 = darken_params[2]; - FT_Int y2 = darken_params[3]; - FT_Int x3 = darken_params[4]; - FT_Int y3 = darken_params[5]; - FT_Int x4 = darken_params[6]; - FT_Int y4 = darken_params[7]; - - - if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 || - y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 || - x1 > x2 || x2 > x3 || x3 > x4 || - y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 ) - return FT_THROW( Invalid_Argument ); - - driver->darken_params[0] = x1; - driver->darken_params[1] = y1; - driver->darken_params[2] = x2; - driver->darken_params[3] = y2; - driver->darken_params[4] = x3; - driver->darken_params[5] = y3; - driver->darken_params[6] = x4; - driver->darken_params[7] = y4; - - return error; - } - else if ( !ft_strcmp( property_name, "hinting-engine" ) ) - { - FT_UInt* hinting_engine = (FT_UInt*)value; - - -#ifndef CFF_CONFIG_OPTION_OLD_ENGINE - if ( *hinting_engine != FT_CFF_HINTING_ADOBE ) - error = FT_ERR( Unimplemented_Feature ); - else -#endif - driver->hinting_engine = *hinting_engine; - - return error; - } - else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) - { - FT_Bool* no_stem_darkening = (FT_Bool*)value; - - - driver->no_stem_darkening = *no_stem_darkening; - - return error; - } - - FT_TRACE0(( "cff_property_set: missing property `%s'\n", - property_name )); - return FT_THROW( Missing_Property ); - } - - - static FT_Error - cff_property_get( FT_Module module, /* CFF_Driver */ - const char* property_name, - const void* value ) - { - FT_Error error = FT_Err_Ok; - CFF_Driver driver = (CFF_Driver)module; - - - if ( !ft_strcmp( property_name, "darkening-parameters" ) ) - { - FT_Int* darken_params = driver->darken_params; - FT_Int* val = (FT_Int*)value; - - - val[0] = darken_params[0]; - val[1] = darken_params[1]; - val[2] = darken_params[2]; - val[3] = darken_params[3]; - val[4] = darken_params[4]; - val[5] = darken_params[5]; - val[6] = darken_params[6]; - val[7] = darken_params[7]; - - return error; - } - else if ( !ft_strcmp( property_name, "hinting-engine" ) ) - { - FT_UInt hinting_engine = driver->hinting_engine; - FT_UInt* val = (FT_UInt*)value; - - - *val = hinting_engine; - - return error; - } - else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) - { - FT_Bool no_stem_darkening = driver->no_stem_darkening; - FT_Bool* val = (FT_Bool*)value; - - - *val = no_stem_darkening; - - return error; - } - - FT_TRACE0(( "cff_property_get: missing property `%s'\n", - property_name )); - return FT_THROW( Missing_Property ); - } - - - FT_DEFINE_SERVICE_PROPERTIESREC( - cff_service_properties, - (FT_Properties_SetFunc)cff_property_set, - (FT_Properties_GetFunc)cff_property_get ) - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** D R I V E R I N T E R F A C E ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - -#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES - FT_DEFINE_SERVICEDESCREC7( - cff_services, - FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, - FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, - FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET, - FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, - FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET, - FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET - ) -#else - FT_DEFINE_SERVICEDESCREC6( - cff_services, - FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, - FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, - FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, - FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET, - FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET - ) -#endif - - - FT_CALLBACK_DEF( FT_Module_Interface ) - cff_get_interface( FT_Module driver, /* CFF_Driver */ - const char* module_interface ) - { - FT_Library library; - FT_Module sfnt; - FT_Module_Interface result; - - - /* CFF_SERVICES_GET dereferences `library' in PIC mode */ -#ifdef FT_CONFIG_OPTION_PIC - if ( !driver ) - return NULL; - library = driver->library; - if ( !library ) - return NULL; -#endif - - result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface ); - if ( result != NULL ) - return result; - - /* `driver' is not yet evaluated in non-PIC mode */ -#ifndef FT_CONFIG_OPTION_PIC - if ( !driver ) - return NULL; - library = driver->library; - if ( !library ) - return NULL; -#endif - - /* we pass our request to the `sfnt' module */ - sfnt = FT_Get_Module( library, "sfnt" ); - - return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; - } - - - /* The FT_DriverInterface structure is defined in ftdriver.h. */ - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#define CFF_SIZE_SELECT cff_size_select -#else -#define CFF_SIZE_SELECT 0 -#endif - - FT_DEFINE_DRIVER( - cff_driver_class, - - FT_MODULE_FONT_DRIVER | - FT_MODULE_DRIVER_SCALABLE | - FT_MODULE_DRIVER_HAS_HINTER, - - sizeof ( CFF_DriverRec ), - "cff", - 0x10000L, - 0x20000L, - - 0, /* module-specific interface */ - - cff_driver_init, - cff_driver_done, - cff_get_interface, - - /* now the specific driver fields */ - sizeof ( TT_FaceRec ), - sizeof ( CFF_SizeRec ), - sizeof ( CFF_GlyphSlotRec ), - - cff_face_init, - cff_face_done, - cff_size_init, - cff_size_done, - cff_slot_init, - cff_slot_done, - - cff_glyph_load, - - cff_get_kerning, - 0, /* FT_Face_AttachFunc */ - cff_get_advances, - - cff_size_request, - - CFF_SIZE_SELECT - ) - - -/* END */ diff --git a/third_party/freetype/src/cff/cffdrivr.h b/third_party/freetype/src/cff/cffdrivr.h deleted file mode 100644 index 9527f5e149588d745fe8cd8a399560796346b7b3..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffdrivr.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffdrivr.h */ -/* */ -/* High-level OpenType driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFDRIVER_H__ -#define __CFFDRIVER_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_DRIVER_H - - -FT_BEGIN_HEADER - - - FT_DECLARE_DRIVER( cff_driver_class ) - - -FT_END_HEADER - -#endif /* __CFFDRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cfferrs.h b/third_party/freetype/src/cff/cfferrs.h deleted file mode 100644 index 543bdb07c239448e79aad44fb6538992048c8e7a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cfferrs.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* cfferrs.h */ -/* */ -/* CFF error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the CFF error enumeration constants. */ - /* */ - /*************************************************************************/ - -#ifndef __CFFERRS_H__ -#define __CFFERRS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX CFF_Err_ -#define FT_ERR_BASE FT_Mod_Err_CFF - - -#include FT_ERRORS_H - -#endif /* __CFFERRS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffgload.c b/third_party/freetype/src/cff/cffgload.c deleted file mode 100644 index 5f57403e22a4e49c22fa2cab4c9b574e297ffa7e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffgload.c +++ /dev/null @@ -1,3086 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffgload.c */ -/* */ -/* OpenType Glyph Loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_OUTLINE_H -#include FT_CFF_DRIVER_H - -#include "cffobjs.h" -#include "cffload.h" -#include "cffgload.h" -#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */ - -#include "cfferrs.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cffgload - - -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - - typedef enum CFF_Operator_ - { - cff_op_unknown = 0, - - cff_op_rmoveto, - cff_op_hmoveto, - cff_op_vmoveto, - - cff_op_rlineto, - cff_op_hlineto, - cff_op_vlineto, - - cff_op_rrcurveto, - cff_op_hhcurveto, - cff_op_hvcurveto, - cff_op_rcurveline, - cff_op_rlinecurve, - cff_op_vhcurveto, - cff_op_vvcurveto, - - cff_op_flex, - cff_op_hflex, - cff_op_hflex1, - cff_op_flex1, - - cff_op_endchar, - - cff_op_hstem, - cff_op_vstem, - cff_op_hstemhm, - cff_op_vstemhm, - - cff_op_hintmask, - cff_op_cntrmask, - cff_op_dotsection, /* deprecated, acts as no-op */ - - cff_op_abs, - cff_op_add, - cff_op_sub, - cff_op_div, - cff_op_neg, - cff_op_random, - cff_op_mul, - cff_op_sqrt, - - cff_op_blend, - - cff_op_drop, - cff_op_exch, - cff_op_index, - cff_op_roll, - cff_op_dup, - - cff_op_put, - cff_op_get, - cff_op_store, - cff_op_load, - - cff_op_and, - cff_op_or, - cff_op_not, - cff_op_eq, - cff_op_ifelse, - - cff_op_callsubr, - cff_op_callgsubr, - cff_op_return, - - /* Type 1 opcodes: invalid but seen in real life */ - cff_op_hsbw, - cff_op_closepath, - cff_op_callothersubr, - cff_op_pop, - cff_op_seac, - cff_op_sbw, - cff_op_setcurrentpoint, - - /* do not remove */ - cff_op_max - - } CFF_Operator; - - -#define CFF_COUNT_CHECK_WIDTH 0x80 -#define CFF_COUNT_EXACT 0x40 -#define CFF_COUNT_CLEAR_STACK 0x20 - - /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ - /* used for checking the width and requested numbers of arguments */ - /* only; they are set to zero afterwards */ - - /* the other two flags are informative only and unused currently */ - - static const FT_Byte cff_argument_counts[] = - { - 0, /* unknown */ - - 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ - 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, - 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, - - 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - - 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - - 13, /* flex */ - 7, - 9, - 11, - - 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ - - 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ - 2 | CFF_COUNT_CHECK_WIDTH, - 2 | CFF_COUNT_CHECK_WIDTH, - 2 | CFF_COUNT_CHECK_WIDTH, - - 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ - 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ - 0, /* dotsection */ - - 1, /* abs */ - 2, - 2, - 2, - 1, - 0, - 2, - 1, - - 1, /* blend */ - - 1, /* drop */ - 2, - 1, - 2, - 1, - - 2, /* put */ - 1, - 4, - 3, - - 2, /* and */ - 2, - 1, - 2, - 4, - - 1, /* callsubr */ - 1, - 0, - - 2, /* hsbw */ - 0, - 0, - 0, - 5, /* seac */ - 4, /* sbw */ - 2 /* setcurrentpoint */ - }; - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** *********/ - /********** GENERIC CHARSTRING PARSING *********/ - /********** *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_builder_init */ - /* */ - /* <Description> */ - /* Initializes a given glyph builder. */ - /* */ - /* <InOut> */ - /* builder :: A pointer to the glyph builder to initialize. */ - /* */ - /* <Input> */ - /* face :: The current face object. */ - /* */ - /* size :: The current size object. */ - /* */ - /* glyph :: The current glyph object. */ - /* */ - /* hinting :: Whether hinting is active. */ - /* */ - static void - cff_builder_init( CFF_Builder* builder, - TT_Face face, - CFF_Size size, - CFF_GlyphSlot glyph, - FT_Bool hinting ) - { - builder->path_begun = 0; - builder->load_points = 1; - - builder->face = face; - builder->glyph = glyph; - builder->memory = face->root.memory; - - if ( glyph ) - { - FT_GlyphLoader loader = glyph->root.internal->loader; - - - builder->loader = loader; - builder->base = &loader->base.outline; - builder->current = &loader->current.outline; - FT_GlyphLoader_Rewind( loader ); - - builder->hints_globals = NULL; - builder->hints_funcs = NULL; - - if ( hinting && size ) - { - CFF_Internal internal = (CFF_Internal)size->root.internal; - - - builder->hints_globals = (void *)internal->topfont; - builder->hints_funcs = glyph->root.internal->glyph_hints; - } - } - - builder->pos_x = 0; - builder->pos_y = 0; - - builder->left_bearing.x = 0; - builder->left_bearing.y = 0; - builder->advance.x = 0; - builder->advance.y = 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_builder_done */ - /* */ - /* <Description> */ - /* Finalizes a given glyph builder. Its contents can still be used */ - /* after the call, but the function saves important information */ - /* within the corresponding glyph slot. */ - /* */ - /* <Input> */ - /* builder :: A pointer to the glyph builder to finalize. */ - /* */ - static void - cff_builder_done( CFF_Builder* builder ) - { - CFF_GlyphSlot glyph = builder->glyph; - - - if ( glyph ) - glyph->root.outline = *builder->base; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_compute_bias */ - /* */ - /* <Description> */ - /* Computes the bias value in dependence of the number of glyph */ - /* subroutines. */ - /* */ - /* <Input> */ - /* in_charstring_type :: The `CharstringType' value of the top DICT */ - /* dictionary. */ - /* */ - /* num_subrs :: The number of glyph subroutines. */ - /* */ - /* <Return> */ - /* The bias value. */ - static FT_Int - cff_compute_bias( FT_Int in_charstring_type, - FT_UInt num_subrs ) - { - FT_Int result; - - - if ( in_charstring_type == 1 ) - result = 0; - else if ( num_subrs < 1240 ) - result = 107; - else if ( num_subrs < 33900U ) - result = 1131; - else - result = 32768U; - - return result; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_decoder_init */ - /* */ - /* <Description> */ - /* Initializes a given glyph decoder. */ - /* */ - /* <InOut> */ - /* decoder :: A pointer to the glyph builder to initialize. */ - /* */ - /* <Input> */ - /* face :: The current face object. */ - /* */ - /* size :: The current size object. */ - /* */ - /* slot :: The current glyph object. */ - /* */ - /* hinting :: Whether hinting is active. */ - /* */ - /* hint_mode :: The hinting mode. */ - /* */ - FT_LOCAL_DEF( void ) - cff_decoder_init( CFF_Decoder* decoder, - TT_Face face, - CFF_Size size, - CFF_GlyphSlot slot, - FT_Bool hinting, - FT_Render_Mode hint_mode ) - { - CFF_Font cff = (CFF_Font)face->extra.data; - - - /* clear everything */ - FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); - - /* initialize builder */ - cff_builder_init( &decoder->builder, face, size, slot, hinting ); - - /* initialize Type2 decoder */ - decoder->cff = cff; - decoder->num_globals = cff->global_subrs_index.count; - decoder->globals = cff->global_subrs; - decoder->globals_bias = cff_compute_bias( - cff->top_font.font_dict.charstring_type, - decoder->num_globals ); - - decoder->hint_mode = hint_mode; - } - - - /* this function is used to select the subfont */ - /* and the locals subrs array */ - FT_LOCAL_DEF( FT_Error ) - cff_decoder_prepare( CFF_Decoder* decoder, - CFF_Size size, - FT_UInt glyph_index ) - { - CFF_Builder *builder = &decoder->builder; - CFF_Font cff = (CFF_Font)builder->face->extra.data; - CFF_SubFont sub = &cff->top_font; - FT_Error error = FT_Err_Ok; - - - /* manage CID fonts */ - if ( cff->num_subfonts ) - { - FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); - - - if ( fd_index >= cff->num_subfonts ) - { - FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - FT_TRACE3(( " in subfont %d:\n", fd_index )); - - sub = cff->subfonts[fd_index]; - - if ( builder->hints_funcs && size ) - { - CFF_Internal internal = (CFF_Internal)size->root.internal; - - - /* for CFFs without subfonts, this value has already been set */ - builder->hints_globals = (void *)internal->subfonts[fd_index]; - } - } - - decoder->num_locals = sub->local_subrs_index.count; - decoder->locals = sub->local_subrs; - decoder->locals_bias = cff_compute_bias( - decoder->cff->top_font.font_dict.charstring_type, - decoder->num_locals ); - - decoder->glyph_width = sub->private_dict.default_width; - decoder->nominal_width = sub->private_dict.nominal_width; - - decoder->current_subfont = sub; /* for Adobe's CFF handler */ - - Exit: - return error; - } - - - /* check that there is enough space for `count' more points */ - FT_LOCAL_DEF( FT_Error ) - cff_check_points( CFF_Builder* builder, - FT_Int count ) - { - return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); - } - - - /* add a new point, do not check space */ - FT_LOCAL_DEF( void ) - cff_builder_add_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ) - { - FT_Outline* outline = builder->current; - - - if ( builder->load_points ) - { - FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; - -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); - - - if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) - { - point->x = x >> 16; - point->y = y >> 16; - } - else -#endif - { - /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ - point->x = x >> 10; - point->y = y >> 10; - } - *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); - } - - outline->n_points++; - } - - - /* check space for a new on-curve point, then add it */ - FT_LOCAL_DEF( FT_Error ) - cff_builder_add_point1( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ) - { - FT_Error error; - - - error = cff_check_points( builder, 1 ); - if ( !error ) - cff_builder_add_point( builder, x, y, 1 ); - - return error; - } - - - /* check space for a new contour, then add it */ - static FT_Error - cff_builder_add_contour( CFF_Builder* builder ) - { - FT_Outline* outline = builder->current; - FT_Error error; - - - if ( !builder->load_points ) - { - outline->n_contours++; - return FT_Err_Ok; - } - - error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); - if ( !error ) - { - if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); - - outline->n_contours++; - } - - return error; - } - - - /* if a path was begun, add its first on-curve point */ - FT_LOCAL_DEF( FT_Error ) - cff_builder_start_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ) - { - FT_Error error = FT_Err_Ok; - - - /* test whether we are building a new contour */ - if ( !builder->path_begun ) - { - builder->path_begun = 1; - error = cff_builder_add_contour( builder ); - if ( !error ) - error = cff_builder_add_point1( builder, x, y ); - } - - return error; - } - - - /* close the current contour */ - FT_LOCAL_DEF( void ) - cff_builder_close_contour( CFF_Builder* builder ) - { - FT_Outline* outline = builder->current; - FT_Int first; - - - if ( !outline ) - return; - - first = outline->n_contours <= 1 - ? 0 : outline->contours[outline->n_contours - 2] + 1; - - /* We must not include the last point in the path if it */ - /* is located on the first point. */ - if ( outline->n_points > 1 ) - { - FT_Vector* p1 = outline->points + first; - FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; - - - /* `delete' last point only if it coincides with the first */ - /* point and if it is not a control point (which can happen). */ - if ( p1->x == p2->x && p1->y == p2->y ) - if ( *control == FT_CURVE_TAG_ON ) - outline->n_points--; - } - - if ( outline->n_contours > 0 ) - { - /* Don't add contours only consisting of one point, i.e., */ - /* check whether begin point and last point are the same. */ - if ( first == outline->n_points - 1 ) - { - outline->n_contours--; - outline->n_points--; - } - else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); - } - } - - - FT_LOCAL_DEF( FT_Int ) - cff_lookup_glyph_by_stdcharcode( CFF_Font cff, - FT_Int charcode ) - { - FT_UInt n; - FT_UShort glyph_sid; - - - /* CID-keyed fonts don't have glyph names */ - if ( !cff->charset.sids ) - return -1; - - /* check range of standard char code */ - if ( charcode < 0 || charcode > 255 ) - return -1; - - /* Get code to SID mapping from `cff_standard_encoding'. */ - glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); - - for ( n = 0; n < cff->num_glyphs; n++ ) - { - if ( cff->charset.sids[n] == glyph_sid ) - return (FT_Int)n; - } - - return -1; - } - - - FT_LOCAL_DEF( FT_Error ) - cff_get_glyph_data( TT_Face face, - FT_UInt glyph_index, - FT_Byte** pointer, - FT_ULong* length ) - { -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* For incremental fonts get the character data using the */ - /* callback function. */ - if ( face->root.internal->incremental_interface ) - { - FT_Data data; - FT_Error error = - face->root.internal->incremental_interface->funcs->get_glyph_data( - face->root.internal->incremental_interface->object, - glyph_index, &data ); - - - *pointer = (FT_Byte*)data.pointer; - *length = (FT_ULong)data.length; - - return error; - } - else -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - { - CFF_Font cff = (CFF_Font)(face->extra.data); - - - return cff_index_access_element( &cff->charstrings_index, glyph_index, - pointer, length ); - } - } - - - FT_LOCAL_DEF( void ) - cff_free_glyph_data( TT_Face face, - FT_Byte** pointer, - FT_ULong length ) - { -#ifndef FT_CONFIG_OPTION_INCREMENTAL - FT_UNUSED( length ); -#endif - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* For incremental fonts get the character data using the */ - /* callback function. */ - if ( face->root.internal->incremental_interface ) - { - FT_Data data; - - - data.pointer = *pointer; - data.length = (FT_Int)length; - - face->root.internal->incremental_interface->funcs->free_glyph_data( - face->root.internal->incremental_interface->object, &data ); - } - else -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - { - CFF_Font cff = (CFF_Font)(face->extra.data); - - - cff_index_forget_element( &cff->charstrings_index, pointer ); - } - } - - -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - - static FT_Error - cff_operator_seac( CFF_Decoder* decoder, - FT_Pos asb, - FT_Pos adx, - FT_Pos ady, - FT_Int bchar, - FT_Int achar ) - { - FT_Error error; - CFF_Builder* builder = &decoder->builder; - FT_Int bchar_index, achar_index; - TT_Face face = decoder->builder.face; - FT_Vector left_bearing, advance; - FT_Byte* charstring; - FT_ULong charstring_len; - FT_Pos glyph_width; - - - if ( decoder->seac ) - { - FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); - return FT_THROW( Syntax_Error ); - } - - adx += decoder->builder.left_bearing.x; - ady += decoder->builder.left_bearing.y; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Incremental fonts don't necessarily have valid charsets. */ - /* They use the character code, not the glyph index, in this case. */ - if ( face->root.internal->incremental_interface ) - { - bchar_index = bchar; - achar_index = achar; - } - else -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - CFF_Font cff = (CFF_Font)(face->extra.data); - - - bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); - achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); - } - - if ( bchar_index < 0 || achar_index < 0 ) - { - FT_ERROR(( "cff_operator_seac:" - " invalid seac character code arguments\n" )); - return FT_THROW( Syntax_Error ); - } - - /* If we are trying to load a composite glyph, do not load the */ - /* accent character and return the array of subglyphs. */ - if ( builder->no_recurse ) - { - FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; - FT_GlyphLoader loader = glyph->internal->loader; - FT_SubGlyph subg; - - - /* reallocate subglyph array if necessary */ - error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); - if ( error ) - goto Exit; - - subg = loader->current.subglyphs; - - /* subglyph 0 = base character */ - subg->index = bchar_index; - subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | - FT_SUBGLYPH_FLAG_USE_MY_METRICS; - subg->arg1 = 0; - subg->arg2 = 0; - subg++; - - /* subglyph 1 = accent character */ - subg->index = achar_index; - subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; - subg->arg1 = (FT_Int)( adx >> 16 ); - subg->arg2 = (FT_Int)( ady >> 16 ); - - /* set up remaining glyph fields */ - glyph->num_subglyphs = 2; - glyph->subglyphs = loader->base.subglyphs; - glyph->format = FT_GLYPH_FORMAT_COMPOSITE; - - loader->current.num_subglyphs = 2; - } - - FT_GlyphLoader_Prepare( builder->loader ); - - /* First load `bchar' in builder */ - error = cff_get_glyph_data( face, (FT_UInt)bchar_index, - &charstring, &charstring_len ); - if ( !error ) - { - /* the seac operator must not be nested */ - decoder->seac = TRUE; - error = cff_decoder_parse_charstrings( decoder, charstring, - charstring_len ); - decoder->seac = FALSE; - - cff_free_glyph_data( face, &charstring, charstring_len ); - - if ( error ) - goto Exit; - } - - /* Save the left bearing, advance and glyph width of the base */ - /* character as they will be erased by the next load. */ - - left_bearing = builder->left_bearing; - advance = builder->advance; - glyph_width = decoder->glyph_width; - - builder->left_bearing.x = 0; - builder->left_bearing.y = 0; - - builder->pos_x = adx - asb; - builder->pos_y = ady; - - /* Now load `achar' on top of the base outline. */ - error = cff_get_glyph_data( face, (FT_UInt)achar_index, - &charstring, &charstring_len ); - if ( !error ) - { - /* the seac operator must not be nested */ - decoder->seac = TRUE; - error = cff_decoder_parse_charstrings( decoder, charstring, - charstring_len ); - decoder->seac = FALSE; - - cff_free_glyph_data( face, &charstring, charstring_len ); - - if ( error ) - goto Exit; - } - - /* Restore the left side bearing, advance and glyph width */ - /* of the base character. */ - builder->left_bearing = left_bearing; - builder->advance = advance; - decoder->glyph_width = glyph_width; - - builder->pos_x = 0; - builder->pos_y = 0; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_decoder_parse_charstrings */ - /* */ - /* <Description> */ - /* Parses a given Type 2 charstrings program. */ - /* */ - /* <InOut> */ - /* decoder :: The current Type 1 decoder. */ - /* */ - /* <Input> */ - /* charstring_base :: The base of the charstring stream. */ - /* */ - /* charstring_len :: The length in bytes of the charstring stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - cff_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len ) - { - FT_Error error; - CFF_Decoder_Zone* zone; - FT_Byte* ip; - FT_Byte* limit; - CFF_Builder* builder = &decoder->builder; - FT_Pos x, y; - FT_Fixed seed; - FT_Fixed* stack; - FT_Int charstring_type = - decoder->cff->top_font.font_dict.charstring_type; - - T2_Hints_Funcs hinter; - - - /* set default width */ - decoder->num_hints = 0; - decoder->read_width = 1; - - /* compute random seed from stack address of parameter */ - seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^ - (FT_Offset)(char*)&decoder ^ - (FT_Offset)(char*)&charstring_base ) & - FT_ULONG_MAX ); - seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; - if ( seed == 0 ) - seed = 0x7384; - - /* initialize the decoder */ - decoder->top = decoder->stack; - decoder->zone = decoder->zones; - zone = decoder->zones; - stack = decoder->top; - - hinter = (T2_Hints_Funcs)builder->hints_funcs; - - builder->path_begun = 0; - - zone->base = charstring_base; - limit = zone->limit = charstring_base + charstring_len; - ip = zone->cursor = zone->base; - - error = FT_Err_Ok; - - x = builder->pos_x; - y = builder->pos_y; - - /* begin hints recording session, if any */ - if ( hinter ) - hinter->open( hinter->hints ); - - /* now execute loop */ - while ( ip < limit ) - { - CFF_Operator op; - FT_Byte v; - - - /********************************************************************/ - /* */ - /* Decode operator or operand */ - /* */ - v = *ip++; - if ( v >= 32 || v == 28 ) - { - FT_Int shift = 16; - FT_Int32 val; - - - /* this is an operand, push it on the stack */ - - /* if we use shifts, all computations are done with unsigned */ - /* values; the conversion to a signed value is the last step */ - if ( v == 28 ) - { - if ( ip + 1 >= limit ) - goto Syntax_Error; - val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] ); - ip += 2; - } - else if ( v < 247 ) - val = (FT_Int32)v - 139; - else if ( v < 251 ) - { - if ( ip >= limit ) - goto Syntax_Error; - val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; - } - else if ( v < 255 ) - { - if ( ip >= limit ) - goto Syntax_Error; - val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; - } - else - { - if ( ip + 3 >= limit ) - goto Syntax_Error; - val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | - ( (FT_UInt32)ip[1] << 16 ) | - ( (FT_UInt32)ip[2] << 8 ) | - (FT_UInt32)ip[3] ); - ip += 4; - if ( charstring_type == 2 ) - shift = 0; - } - if ( decoder->top - stack >= CFF_MAX_OPERANDS ) - goto Stack_Overflow; - - val = (FT_Int32)( (FT_UInt32)val << shift ); - *decoder->top++ = val; - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( !( val & 0xFFFFL ) ) - FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) )); - else - FT_TRACE4(( " %.2f", val / 65536.0 )); -#endif - - } - else - { - /* The specification says that normally arguments are to be taken */ - /* from the bottom of the stack. However, this seems not to be */ - /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ - /* arguments similar to a PS interpreter. */ - - FT_Fixed* args = decoder->top; - FT_Int num_args = (FT_Int)( args - decoder->stack ); - FT_Int req_args; - - - /* find operator */ - op = cff_op_unknown; - - switch ( v ) - { - case 1: - op = cff_op_hstem; - break; - case 3: - op = cff_op_vstem; - break; - case 4: - op = cff_op_vmoveto; - break; - case 5: - op = cff_op_rlineto; - break; - case 6: - op = cff_op_hlineto; - break; - case 7: - op = cff_op_vlineto; - break; - case 8: - op = cff_op_rrcurveto; - break; - case 9: - op = cff_op_closepath; - break; - case 10: - op = cff_op_callsubr; - break; - case 11: - op = cff_op_return; - break; - case 12: - { - if ( ip >= limit ) - goto Syntax_Error; - v = *ip++; - - switch ( v ) - { - case 0: - op = cff_op_dotsection; - break; - case 1: /* this is actually the Type1 vstem3 operator */ - op = cff_op_vstem; - break; - case 2: /* this is actually the Type1 hstem3 operator */ - op = cff_op_hstem; - break; - case 3: - op = cff_op_and; - break; - case 4: - op = cff_op_or; - break; - case 5: - op = cff_op_not; - break; - case 6: - op = cff_op_seac; - break; - case 7: - op = cff_op_sbw; - break; - case 8: - op = cff_op_store; - break; - case 9: - op = cff_op_abs; - break; - case 10: - op = cff_op_add; - break; - case 11: - op = cff_op_sub; - break; - case 12: - op = cff_op_div; - break; - case 13: - op = cff_op_load; - break; - case 14: - op = cff_op_neg; - break; - case 15: - op = cff_op_eq; - break; - case 16: - op = cff_op_callothersubr; - break; - case 17: - op = cff_op_pop; - break; - case 18: - op = cff_op_drop; - break; - case 20: - op = cff_op_put; - break; - case 21: - op = cff_op_get; - break; - case 22: - op = cff_op_ifelse; - break; - case 23: - op = cff_op_random; - break; - case 24: - op = cff_op_mul; - break; - case 26: - op = cff_op_sqrt; - break; - case 27: - op = cff_op_dup; - break; - case 28: - op = cff_op_exch; - break; - case 29: - op = cff_op_index; - break; - case 30: - op = cff_op_roll; - break; - case 33: - op = cff_op_setcurrentpoint; - break; - case 34: - op = cff_op_hflex; - break; - case 35: - op = cff_op_flex; - break; - case 36: - op = cff_op_hflex1; - break; - case 37: - op = cff_op_flex1; - break; - default: - FT_TRACE4(( " unknown op (12, %d)\n", v )); - break; - } - } - break; - case 13: - op = cff_op_hsbw; - break; - case 14: - op = cff_op_endchar; - break; - case 16: - op = cff_op_blend; - break; - case 18: - op = cff_op_hstemhm; - break; - case 19: - op = cff_op_hintmask; - break; - case 20: - op = cff_op_cntrmask; - break; - case 21: - op = cff_op_rmoveto; - break; - case 22: - op = cff_op_hmoveto; - break; - case 23: - op = cff_op_vstemhm; - break; - case 24: - op = cff_op_rcurveline; - break; - case 25: - op = cff_op_rlinecurve; - break; - case 26: - op = cff_op_vvcurveto; - break; - case 27: - op = cff_op_hhcurveto; - break; - case 29: - op = cff_op_callgsubr; - break; - case 30: - op = cff_op_vhcurveto; - break; - case 31: - op = cff_op_hvcurveto; - break; - default: - FT_TRACE4(( " unknown op (%d)\n", v )); - break; - } - - if ( op == cff_op_unknown ) - continue; - - /* check arguments */ - req_args = cff_argument_counts[op]; - if ( req_args & CFF_COUNT_CHECK_WIDTH ) - { - if ( num_args > 0 && decoder->read_width ) - { - /* If `nominal_width' is non-zero, the number is really a */ - /* difference against `nominal_width'. Else, the number here */ - /* is truly a width, not a difference against `nominal_width'. */ - /* If the font does not set `nominal_width', then */ - /* `nominal_width' defaults to zero, and so we can set */ - /* `glyph_width' to `nominal_width' plus number on the stack */ - /* -- for either case. */ - - FT_Int set_width_ok; - - - switch ( op ) - { - case cff_op_hmoveto: - case cff_op_vmoveto: - set_width_ok = num_args & 2; - break; - - case cff_op_hstem: - case cff_op_vstem: - case cff_op_hstemhm: - case cff_op_vstemhm: - case cff_op_rmoveto: - case cff_op_hintmask: - case cff_op_cntrmask: - set_width_ok = num_args & 1; - break; - - case cff_op_endchar: - /* If there is a width specified for endchar, we either have */ - /* 1 argument or 5 arguments. We like to argue. */ - set_width_ok = ( num_args == 5 ) || ( num_args == 1 ); - break; - - default: - set_width_ok = 0; - break; - } - - if ( set_width_ok ) - { - decoder->glyph_width = decoder->nominal_width + - ( stack[0] >> 16 ); - - if ( decoder->width_only ) - { - /* we only want the advance width; stop here */ - break; - } - - /* Consumed an argument. */ - num_args--; - } - } - - decoder->read_width = 0; - req_args = 0; - } - - req_args &= 0x000F; - if ( num_args < req_args ) - goto Stack_Underflow; - args -= req_args; - num_args -= req_args; - - /* At this point, `args' points to the first argument of the */ - /* operand in case `req_args' isn't zero. Otherwise, we have */ - /* to adjust `args' manually. */ - - /* Note that we only pop arguments from the stack which we */ - /* really need and can digest so that we can continue in case */ - /* of superfluous stack elements. */ - - switch ( op ) - { - case cff_op_hstem: - case cff_op_vstem: - case cff_op_hstemhm: - case cff_op_vstemhm: - /* the number of arguments is always even here */ - FT_TRACE4(( - op == cff_op_hstem ? " hstem\n" : - ( op == cff_op_vstem ? " vstem\n" : - ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); - - if ( hinter ) - hinter->stems( hinter->hints, - ( op == cff_op_hstem || op == cff_op_hstemhm ), - num_args / 2, - args - ( num_args & ~1 ) ); - - decoder->num_hints += num_args / 2; - args = stack; - break; - - case cff_op_hintmask: - case cff_op_cntrmask: - FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); - - /* implement vstem when needed -- */ - /* the specification doesn't say it, but this also works */ - /* with the 'cntrmask' operator */ - /* */ - if ( num_args > 0 ) - { - if ( hinter ) - hinter->stems( hinter->hints, - 0, - num_args / 2, - args - ( num_args & ~1 ) ); - - decoder->num_hints += num_args / 2; - } - - /* In a valid charstring there must be at least one byte */ - /* after `hintmask' or `cntrmask' (e.g., for a `return' */ - /* instruction). Additionally, there must be space for */ - /* `num_hints' bits. */ - - if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) - goto Syntax_Error; - - if ( hinter ) - { - if ( op == cff_op_hintmask ) - hinter->hintmask( hinter->hints, - (FT_UInt)builder->current->n_points, - (FT_UInt)decoder->num_hints, - ip ); - else - hinter->counter( hinter->hints, - (FT_UInt)decoder->num_hints, - ip ); - } - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_UInt maskbyte; - - - FT_TRACE4(( " (maskbytes:" )); - - for ( maskbyte = 0; - maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); - maskbyte++, ip++ ) - FT_TRACE4(( " 0x%02X", *ip )); - - FT_TRACE4(( ")\n" )); - } -#else - ip += ( decoder->num_hints + 7 ) >> 3; -#endif - args = stack; - break; - - case cff_op_rmoveto: - FT_TRACE4(( " rmoveto\n" )); - - cff_builder_close_contour( builder ); - builder->path_begun = 0; - x += args[-2]; - y += args[-1]; - args = stack; - break; - - case cff_op_vmoveto: - FT_TRACE4(( " vmoveto\n" )); - - cff_builder_close_contour( builder ); - builder->path_begun = 0; - y += args[-1]; - args = stack; - break; - - case cff_op_hmoveto: - FT_TRACE4(( " hmoveto\n" )); - - cff_builder_close_contour( builder ); - builder->path_begun = 0; - x += args[-1]; - args = stack; - break; - - case cff_op_rlineto: - FT_TRACE4(( " rlineto\n" )); - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_args / 2 ) ) - goto Fail; - - if ( num_args < 2 ) - goto Stack_Underflow; - - args -= num_args & ~1; - while ( args < decoder->top ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 1 ); - args += 2; - } - args = stack; - break; - - case cff_op_hlineto: - case cff_op_vlineto: - { - FT_Int phase = ( op == cff_op_hlineto ); - - - FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" - : " vlineto\n" )); - - if ( num_args < 0 ) - goto Stack_Underflow; - - /* there exist subsetted fonts (found in PDFs) */ - /* which call `hlineto' without arguments */ - if ( num_args == 0 ) - break; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_args ) ) - goto Fail; - - args = stack; - while ( args < decoder->top ) - { - if ( phase ) - x += args[0]; - else - y += args[0]; - - if ( cff_builder_add_point1( builder, x, y ) ) - goto Fail; - - args++; - phase ^= 1; - } - args = stack; - } - break; - - case cff_op_rrcurveto: - { - FT_Int nargs; - - - FT_TRACE4(( " rrcurveto\n" )); - - if ( num_args < 6 ) - goto Stack_Underflow; - - nargs = num_args - num_args % 6; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, nargs / 2 ) ) - goto Fail; - - args -= nargs; - while ( args < decoder->top ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args += 6; - } - args = stack; - } - break; - - case cff_op_vvcurveto: - { - FT_Int nargs; - - - FT_TRACE4(( " vvcurveto\n" )); - - if ( num_args < 4 ) - goto Stack_Underflow; - - /* if num_args isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - - nargs = num_args & ~2; - - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - - args -= nargs; - - if ( nargs & 1 ) - { - x += args[0]; - args++; - nargs--; - } - - if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) - goto Fail; - - while ( args < decoder->top ) - { - y += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - y += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - args += 4; - } - args = stack; - } - break; - - case cff_op_hhcurveto: - { - FT_Int nargs; - - - FT_TRACE4(( " hhcurveto\n" )); - - if ( num_args < 4 ) - goto Stack_Underflow; - - /* if num_args isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - - nargs = num_args & ~2; - - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - - args -= nargs; - if ( nargs & 1 ) - { - y += args[0]; - args++; - nargs--; - } - - if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) - goto Fail; - - while ( args < decoder->top ) - { - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - args += 4; - } - args = stack; - } - break; - - case cff_op_vhcurveto: - case cff_op_hvcurveto: - { - FT_Int phase; - FT_Int nargs; - - - FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" - : " hvcurveto\n" )); - - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - - if ( num_args < 4 ) - goto Stack_Underflow; - - /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ - /* we enforce it by clearing the second bit */ - - nargs = num_args & ~2; - - args -= nargs; - if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) ) - goto Stack_Underflow; - - phase = ( op == cff_op_hvcurveto ); - - while ( nargs >= 4 ) - { - nargs -= 4; - if ( phase ) - { - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - y += args[3]; - if ( nargs == 1 ) - x += args[4]; - cff_builder_add_point( builder, x, y, 1 ); - } - else - { - y += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[3]; - if ( nargs == 1 ) - y += args[4]; - cff_builder_add_point( builder, x, y, 1 ); - } - args += 4; - phase ^= 1; - } - args = stack; - } - break; - - case cff_op_rlinecurve: - { - FT_Int num_lines; - FT_Int nargs; - - - FT_TRACE4(( " rlinecurve\n" )); - - if ( num_args < 8 ) - goto Stack_Underflow; - - nargs = num_args & ~1; - num_lines = ( nargs - 6 ) / 2; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_lines + 3 ) ) - goto Fail; - - args -= nargs; - - /* first, add the line segments */ - while ( num_lines > 0 ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 1 ); - args += 2; - num_lines--; - } - - /* then the curve */ - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args = stack; - } - break; - - case cff_op_rcurveline: - { - FT_Int num_curves; - FT_Int nargs; - - - FT_TRACE4(( " rcurveline\n" )); - - if ( num_args < 8 ) - goto Stack_Underflow; - - nargs = num_args - 2; - nargs = nargs - nargs % 6 + 2; - num_curves = ( nargs - 2 ) / 6; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_curves * 3 + 2 ) ) - goto Fail; - - args -= nargs; - - /* first, add the curves */ - while ( num_curves > 0 ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args += 6; - num_curves--; - } - - /* then the final line */ - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 1 ); - args = stack; - } - break; - - case cff_op_hflex1: - { - FT_Pos start_y; - - - FT_TRACE4(( " hflex1\n" )); - - /* adding five more points: 4 control points, 1 on-curve point */ - /* -- make sure we have enough space for the start point if it */ - /* needs to be added */ - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - /* record the starting point's y position for later use */ - start_y = y; - - /* first control point */ - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - - /* second control point */ - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - - /* join point; on curve, with y-value the same as the last */ - /* control point's y-value */ - x += args[4]; - cff_builder_add_point( builder, x, y, 1 ); - - /* third control point, with y-value the same as the join */ - /* point's y-value */ - x += args[5]; - cff_builder_add_point( builder, x, y, 0 ); - - /* fourth control point */ - x += args[6]; - y += args[7]; - cff_builder_add_point( builder, x, y, 0 ); - - /* ending point, with y-value the same as the start */ - x += args[8]; - y = start_y; - cff_builder_add_point( builder, x, y, 1 ); - - args = stack; - break; - } - - case cff_op_hflex: - { - FT_Pos start_y; - - - FT_TRACE4(( " hflex\n" )); - - /* adding six more points; 4 control points, 2 on-curve points */ - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - /* record the starting point's y-position for later use */ - start_y = y; - - /* first control point */ - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - - /* second control point */ - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - - /* join point; on curve, with y-value the same as the last */ - /* control point's y-value */ - x += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - - /* third control point, with y-value the same as the join */ - /* point's y-value */ - x += args[4]; - cff_builder_add_point( builder, x, y, 0 ); - - /* fourth control point */ - x += args[5]; - y = start_y; - cff_builder_add_point( builder, x, y, 0 ); - - /* ending point, with y-value the same as the start point's */ - /* y-value -- we don't add this point, though */ - x += args[6]; - cff_builder_add_point( builder, x, y, 1 ); - - args = stack; - break; - } - - case cff_op_flex1: - { - FT_Pos start_x, start_y; /* record start x, y values for */ - /* alter use */ - FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ - /* algorithm below */ - FT_Int horizontal, count; - FT_Fixed* temp; - - - FT_TRACE4(( " flex1\n" )); - - /* adding six more points; 4 control points, 2 on-curve points */ - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - /* record the starting point's x, y position for later use */ - start_x = x; - start_y = y; - - /* XXX: figure out whether this is supposed to be a horizontal */ - /* or vertical flex; the Type 2 specification is vague... */ - - temp = args; - - /* grab up to the last argument */ - for ( count = 5; count > 0; count-- ) - { - dx += temp[0]; - dy += temp[1]; - temp += 2; - } - - if ( dx < 0 ) - dx = -dx; - if ( dy < 0 ) - dy = -dy; - - /* strange test, but here it is... */ - horizontal = ( dx > dy ); - - for ( count = 5; count > 0; count-- ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, - (FT_Bool)( count == 3 ) ); - args += 2; - } - - /* is last operand an x- or y-delta? */ - if ( horizontal ) - { - x += args[0]; - y = start_y; - } - else - { - x = start_x; - y += args[0]; - } - - cff_builder_add_point( builder, x, y, 1 ); - - args = stack; - break; - } - - case cff_op_flex: - { - FT_UInt count; - - - FT_TRACE4(( " flex\n" )); - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - for ( count = 6; count > 0; count-- ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, - (FT_Bool)( count == 4 || count == 1 ) ); - args += 2; - } - - args = stack; - } - break; - - case cff_op_seac: - FT_TRACE4(( " seac\n" )); - - error = cff_operator_seac( decoder, - args[0], args[1], args[2], - (FT_Int)( args[3] >> 16 ), - (FT_Int)( args[4] >> 16 ) ); - - /* add current outline to the glyph slot */ - FT_GlyphLoader_Add( builder->loader ); - - /* return now! */ - FT_TRACE4(( "\n" )); - return error; - - case cff_op_endchar: - FT_TRACE4(( " endchar\n" )); - - /* We are going to emulate the seac operator. */ - if ( num_args >= 4 ) - { - /* Save glyph width so that the subglyphs don't overwrite it. */ - FT_Pos glyph_width = decoder->glyph_width; - - - error = cff_operator_seac( decoder, - 0L, args[-4], args[-3], - (FT_Int)( args[-2] >> 16 ), - (FT_Int)( args[-1] >> 16 ) ); - - decoder->glyph_width = glyph_width; - } - else - { - cff_builder_close_contour( builder ); - - /* close hints recording session */ - if ( hinter ) - { - if ( hinter->close( hinter->hints, - (FT_UInt)builder->current->n_points ) ) - goto Syntax_Error; - - /* apply hints to the loaded glyph outline now */ - error = hinter->apply( hinter->hints, - builder->current, - (PSH_Globals)builder->hints_globals, - decoder->hint_mode ); - if ( error ) - goto Fail; - } - - /* add current outline to the glyph slot */ - FT_GlyphLoader_Add( builder->loader ); - } - - /* return now! */ - FT_TRACE4(( "\n" )); - return error; - - case cff_op_abs: - FT_TRACE4(( " abs\n" )); - - if ( args[0] < 0 ) - args[0] = -args[0]; - args++; - break; - - case cff_op_add: - FT_TRACE4(( " add\n" )); - - args[0] += args[1]; - args++; - break; - - case cff_op_sub: - FT_TRACE4(( " sub\n" )); - - args[0] -= args[1]; - args++; - break; - - case cff_op_div: - FT_TRACE4(( " div\n" )); - - args[0] = FT_DivFix( args[0], args[1] ); - args++; - break; - - case cff_op_neg: - FT_TRACE4(( " neg\n" )); - - args[0] = -args[0]; - args++; - break; - - case cff_op_random: - { - FT_Fixed Rand; - - - FT_TRACE4(( " rand\n" )); - - Rand = seed; - if ( Rand >= 0x8000L ) - Rand++; - - args[0] = Rand; - seed = FT_MulFix( seed, 0x10000L - seed ); - if ( seed == 0 ) - seed += 0x2873; - args++; - } - break; - - case cff_op_mul: - FT_TRACE4(( " mul\n" )); - - args[0] = FT_MulFix( args[0], args[1] ); - args++; - break; - - case cff_op_sqrt: - FT_TRACE4(( " sqrt\n" )); - - if ( args[0] > 0 ) - { - FT_Int count = 9; - FT_Fixed root = args[0]; - FT_Fixed new_root; - - - for (;;) - { - new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; - if ( new_root == root || count <= 0 ) - break; - root = new_root; - } - args[0] = new_root; - } - else - args[0] = 0; - args++; - break; - - case cff_op_drop: - /* nothing */ - FT_TRACE4(( " drop\n" )); - - break; - - case cff_op_exch: - { - FT_Fixed tmp; - - - FT_TRACE4(( " exch\n" )); - - tmp = args[0]; - args[0] = args[1]; - args[1] = tmp; - args += 2; - } - break; - - case cff_op_index: - { - FT_Int idx = (FT_Int)( args[0] >> 16 ); - - - FT_TRACE4(( " index\n" )); - - if ( idx < 0 ) - idx = 0; - else if ( idx > num_args - 2 ) - idx = num_args - 2; - args[0] = args[-( idx + 1 )]; - args++; - } - break; - - case cff_op_roll: - { - FT_Int count = (FT_Int)( args[0] >> 16 ); - FT_Int idx = (FT_Int)( args[1] >> 16 ); - - - FT_TRACE4(( " roll\n" )); - - if ( count <= 0 ) - count = 1; - - args -= count; - if ( args < stack ) - goto Stack_Underflow; - - if ( idx >= 0 ) - { - while ( idx > 0 ) - { - FT_Fixed tmp = args[count - 1]; - FT_Int i; - - - for ( i = count - 2; i >= 0; i-- ) - args[i + 1] = args[i]; - args[0] = tmp; - idx--; - } - } - else - { - while ( idx < 0 ) - { - FT_Fixed tmp = args[0]; - FT_Int i; - - - for ( i = 0; i < count - 1; i++ ) - args[i] = args[i + 1]; - args[count - 1] = tmp; - idx++; - } - } - args += count; - } - break; - - case cff_op_dup: - FT_TRACE4(( " dup\n" )); - - args[1] = args[0]; - args += 2; - break; - - case cff_op_put: - { - FT_Fixed val = args[0]; - FT_Int idx = (FT_Int)( args[1] >> 16 ); - - - FT_TRACE4(( " put\n" )); - - if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) - decoder->buildchar[idx] = val; - } - break; - - case cff_op_get: - { - FT_Int idx = (FT_Int)( args[0] >> 16 ); - FT_Fixed val = 0; - - - FT_TRACE4(( " get\n" )); - - if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) - val = decoder->buildchar[idx]; - - args[0] = val; - args++; - } - break; - - case cff_op_store: - FT_TRACE4(( " store\n")); - - goto Unimplemented; - - case cff_op_load: - FT_TRACE4(( " load\n" )); - - goto Unimplemented; - - case cff_op_dotsection: - /* this operator is deprecated and ignored by the parser */ - FT_TRACE4(( " dotsection\n" )); - break; - - case cff_op_closepath: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " closepath (invalid op)\n" )); - - args = stack; - break; - - case cff_op_hsbw: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " hsbw (invalid op)\n" )); - - decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 ); - - decoder->builder.left_bearing.x = args[0]; - decoder->builder.left_bearing.y = 0; - - x = decoder->builder.pos_x + args[0]; - y = decoder->builder.pos_y; - args = stack; - break; - - case cff_op_sbw: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " sbw (invalid op)\n" )); - - decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 ); - - decoder->builder.left_bearing.x = args[0]; - decoder->builder.left_bearing.y = args[1]; - - x = decoder->builder.pos_x + args[0]; - y = decoder->builder.pos_y + args[1]; - args = stack; - break; - - case cff_op_setcurrentpoint: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " setcurrentpoint (invalid op)\n" )); - - x = decoder->builder.pos_x + args[0]; - y = decoder->builder.pos_y + args[1]; - args = stack; - break; - - case cff_op_callothersubr: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " callothersubr (invalid op)\n" )); - - /* subsequent `pop' operands should add the arguments, */ - /* this is the implementation described for `unknown' other */ - /* subroutines in the Type1 spec. */ - /* */ - /* XXX Fix return arguments (see discussion below). */ - args -= 2 + ( args[-2] >> 16 ); - if ( args < stack ) - goto Stack_Underflow; - break; - - case cff_op_pop: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " pop (invalid op)\n" )); - - /* XXX Increasing `args' is wrong: After a certain number of */ - /* `pop's we get a stack overflow. Reason for doing it is */ - /* code like this (actually found in a CFF font): */ - /* */ - /* 17 1 3 callothersubr */ - /* pop */ - /* callsubr */ - /* */ - /* Since we handle `callothersubr' as a no-op, and */ - /* `callsubr' needs at least one argument, `pop' can't be a */ - /* no-op too as it basically should be. */ - /* */ - /* The right solution would be to provide real support for */ - /* `callothersubr' as done in `t1decode.c', however, given */ - /* the fact that CFF fonts with `pop' are invalid, it is */ - /* questionable whether it is worth the time. */ - args++; - break; - - case cff_op_and: - { - FT_Fixed cond = args[0] && args[1]; - - - FT_TRACE4(( " and\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_or: - { - FT_Fixed cond = args[0] || args[1]; - - - FT_TRACE4(( " or\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_eq: - { - FT_Fixed cond = !args[0]; - - - FT_TRACE4(( " eq\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_ifelse: - { - FT_Fixed cond = ( args[2] <= args[3] ); - - - FT_TRACE4(( " ifelse\n" )); - - if ( !cond ) - args[0] = args[1]; - args++; - } - break; - - case cff_op_callsubr: - { - FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + - decoder->locals_bias ); - - - FT_TRACE4(( " callsubr (idx %d, entering level %d)\n", - idx, - zone - decoder->zones + 1 )); - - if ( idx >= decoder->num_locals ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invalid local subr index\n" )); - goto Syntax_Error; - } - - if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " too many nested subrs\n" )); - goto Syntax_Error; - } - - zone->cursor = ip; /* save current instruction pointer */ - - zone++; - zone->base = decoder->locals[idx]; - zone->limit = decoder->locals[idx + 1]; - zone->cursor = zone->base; - - if ( !zone->base || zone->limit == zone->base ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invoking empty subrs\n" )); - goto Syntax_Error; - } - - decoder->zone = zone; - ip = zone->base; - limit = zone->limit; - } - break; - - case cff_op_callgsubr: - { - FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + - decoder->globals_bias ); - - - FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n", - idx, - zone - decoder->zones + 1 )); - - if ( idx >= decoder->num_globals ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invalid global subr index\n" )); - goto Syntax_Error; - } - - if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " too many nested subrs\n" )); - goto Syntax_Error; - } - - zone->cursor = ip; /* save current instruction pointer */ - - zone++; - zone->base = decoder->globals[idx]; - zone->limit = decoder->globals[idx + 1]; - zone->cursor = zone->base; - - if ( !zone->base || zone->limit == zone->base ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invoking empty subrs\n" )); - goto Syntax_Error; - } - - decoder->zone = zone; - ip = zone->base; - limit = zone->limit; - } - break; - - case cff_op_return: - FT_TRACE4(( " return (leaving level %d)\n", - decoder->zone - decoder->zones )); - - if ( decoder->zone <= decoder->zones ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " unexpected return\n" )); - goto Syntax_Error; - } - - decoder->zone--; - zone = decoder->zone; - ip = zone->cursor; - limit = zone->limit; - break; - - default: - Unimplemented: - FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); - - if ( ip[-1] == 12 ) - FT_ERROR(( " %d", ip[0] )); - FT_ERROR(( "\n" )); - - return FT_THROW( Unimplemented_Feature ); - } - - decoder->top = args; - - if ( decoder->top - stack >= CFF_MAX_OPERANDS ) - goto Stack_Overflow; - - } /* general operator processing */ - - } /* while ip < limit */ - - FT_TRACE4(( "..end..\n\n" )); - - Fail: - return error; - - Syntax_Error: - FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); - return FT_THROW( Invalid_File_Format ); - - Stack_Underflow: - FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); - return FT_THROW( Too_Few_Arguments ); - - Stack_Overflow: - FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); - return FT_THROW( Stack_Overflow ); - } - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** *********/ - /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ - /********** *********/ - /********** The following code is in charge of computing *********/ - /********** the maximum advance width of the font. It *********/ - /********** quickly processes each glyph charstring to *********/ - /********** extract the value from either a `sbw' or `seac' *********/ - /********** operator. *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - -#if 0 /* unused until we support pure CFF fonts */ - - - FT_LOCAL_DEF( FT_Error ) - cff_compute_max_advance( TT_Face face, - FT_Int* max_advance ) - { - FT_Error error = FT_Err_Ok; - CFF_Decoder decoder; - FT_Int glyph_index; - CFF_Font cff = (CFF_Font)face->other; - - - *max_advance = 0; - - /* Initialize load decoder */ - cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); - - decoder.builder.metrics_only = 1; - decoder.builder.load_points = 0; - - /* For each glyph, parse the glyph charstring and extract */ - /* the advance width. */ - for ( glyph_index = 0; glyph_index < face->root.num_glyphs; - glyph_index++ ) - { - FT_Byte* charstring; - FT_ULong charstring_len; - - - /* now get load the unscaled outline */ - error = cff_get_glyph_data( face, glyph_index, - &charstring, &charstring_len ); - if ( !error ) - { - error = cff_decoder_prepare( &decoder, size, glyph_index ); - if ( !error ) - error = cff_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); - - cff_free_glyph_data( face, &charstring, &charstring_len ); - } - - /* ignore the error if one has occurred -- skip to next glyph */ - error = FT_Err_Ok; - } - - *max_advance = decoder.builder.advance.x; - - return FT_Err_Ok; - } - - -#endif /* 0 */ - - - FT_LOCAL_DEF( FT_Error ) - cff_slot_load( CFF_GlyphSlot glyph, - CFF_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - FT_Error error; - CFF_Decoder decoder; - TT_Face face = (TT_Face)glyph->root.face; - FT_Bool hinting, scaled, force_scaling; - CFF_Font cff = (CFF_Font)face->extra.data; - - FT_Matrix font_matrix; - FT_Vector font_offset; - - - force_scaling = FALSE; - - /* in a CID-keyed font, consider `glyph_index' as a CID and map */ - /* it immediately to the real glyph_index -- if it isn't a */ - /* subsetted font, glyph_indices and CIDs are identical, though */ - if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && - cff->charset.cids ) - { - /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ - if ( glyph_index != 0 ) - { - glyph_index = cff_charset_cid_to_gindex( &cff->charset, - glyph_index ); - if ( glyph_index == 0 ) - return FT_THROW( Invalid_Argument ); - } - } - else if ( glyph_index >= cff->num_glyphs ) - return FT_THROW( Invalid_Argument ); - - if ( load_flags & FT_LOAD_NO_RECURSE ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; - - glyph->x_scale = 0x10000L; - glyph->y_scale = 0x10000L; - if ( size ) - { - glyph->x_scale = size->root.metrics.x_scale; - glyph->y_scale = size->root.metrics.y_scale; - } - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - /* try to load embedded bitmap if any */ - /* */ - /* XXX: The convention should be emphasized in */ - /* the documents because it can be confusing. */ - if ( size ) - { - CFF_Face cff_face = (CFF_Face)size->root.face; - SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; - FT_Stream stream = cff_face->root.stream; - - - if ( size->strike_index != 0xFFFFFFFFUL && - sfnt->load_eblc && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) - { - TT_SBit_MetricsRec metrics; - - - error = sfnt->load_sbit_image( face, - size->strike_index, - glyph_index, - (FT_UInt)load_flags, - stream, - &glyph->root.bitmap, - &metrics ); - - if ( !error ) - { - FT_Bool has_vertical_info; - FT_UShort advance; - FT_Short dummy; - - - glyph->root.outline.n_points = 0; - glyph->root.outline.n_contours = 0; - - glyph->root.metrics.width = (FT_Pos)metrics.width << 6; - glyph->root.metrics.height = (FT_Pos)metrics.height << 6; - - glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; - glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; - glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; - - glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; - glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; - glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; - - glyph->root.format = FT_GLYPH_FORMAT_BITMAP; - - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - glyph->root.bitmap_left = metrics.vertBearingX; - glyph->root.bitmap_top = metrics.vertBearingY; - } - else - { - glyph->root.bitmap_left = metrics.horiBearingX; - glyph->root.bitmap_top = metrics.horiBearingY; - } - - /* compute linear advance widths */ - - (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0, - glyph_index, - &dummy, - &advance ); - glyph->root.linearHoriAdvance = advance; - - has_vertical_info = FT_BOOL( - face->vertical_info && - face->vertical.number_Of_VMetrics > 0 ); - - /* get the vertical metrics from the vmtx table if we have one */ - if ( has_vertical_info ) - { - (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1, - glyph_index, - &dummy, - &advance ); - glyph->root.linearVertAdvance = advance; - } - else - { - /* make up vertical ones */ - if ( face->os2.version != 0xFFFFU ) - glyph->root.linearVertAdvance = (FT_Pos) - ( face->os2.sTypoAscender - face->os2.sTypoDescender ); - else - glyph->root.linearVertAdvance = (FT_Pos) - ( face->horizontal.Ascender - face->horizontal.Descender ); - } - - return error; - } - } - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - /* return immediately if we only want the embedded bitmaps */ - if ( load_flags & FT_LOAD_SBITS_ONLY ) - return FT_THROW( Invalid_Argument ); - - /* if we have a CID subfont, use its matrix (which has already */ - /* been multiplied with the root matrix) */ - - /* this scaling is only relevant if the PS hinter isn't active */ - if ( cff->num_subfonts ) - { - FT_Long top_upm, sub_upm; - FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, - glyph_index ); - - - if ( fd_index >= cff->num_subfonts ) - fd_index = (FT_Byte)( cff->num_subfonts - 1 ); - - top_upm = (FT_Long)cff->top_font.font_dict.units_per_em; - sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em; - - - font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; - font_offset = cff->subfonts[fd_index]->font_dict.font_offset; - - if ( top_upm != sub_upm ) - { - glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); - glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); - - force_scaling = TRUE; - } - } - else - { - font_matrix = cff->top_font.font_dict.font_matrix; - font_offset = cff->top_font.font_dict.font_offset; - } - - glyph->root.outline.n_points = 0; - glyph->root.outline.n_contours = 0; - - /* top-level code ensures that FT_LOAD_NO_HINTING is set */ - /* if FT_LOAD_NO_SCALE is active */ - hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); - scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); - - glyph->hint = hinting; - glyph->scaled = scaled; - glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ - - { -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); -#endif - - - FT_Byte* charstring; - FT_ULong charstring_len; - - - cff_decoder_init( &decoder, face, size, glyph, hinting, - FT_LOAD_TARGET_MODE( load_flags ) ); - - if ( load_flags & FT_LOAD_ADVANCE_ONLY ) - decoder.width_only = TRUE; - - decoder.builder.no_recurse = - (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); - - /* now load the unscaled outline */ - error = cff_get_glyph_data( face, glyph_index, - &charstring, &charstring_len ); - if ( error ) - goto Glyph_Build_Finished; - - error = cff_decoder_prepare( &decoder, size, glyph_index ); - if ( error ) - goto Glyph_Build_Finished; - -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - /* choose which CFF renderer to use */ - if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) - error = cff_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); - else -#endif - { - error = cf2_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); - - /* Adobe's engine uses 16.16 numbers everywhere; */ - /* as a consequence, glyphs larger than 2000ppem get rejected */ - if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) - { - /* this time, we retry unhinted and scale up the glyph later on */ - /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ - /* 0x400 for both `x_scale' and `y_scale' in this case) */ - hinting = FALSE; - force_scaling = TRUE; - glyph->hint = hinting; - - error = cf2_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); - } - } - - cff_free_glyph_data( face, &charstring, charstring_len ); - - if ( error ) - goto Glyph_Build_Finished; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Control data and length may not be available for incremental */ - /* fonts. */ - if ( face->root.internal->incremental_interface ) - { - glyph->root.control_data = NULL; - glyph->root.control_len = 0; - } - else -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - /* We set control_data and control_len if charstrings is loaded. */ - /* See how charstring loads at cff_index_access_element() in */ - /* cffload.c. */ - { - CFF_Index csindex = &cff->charstrings_index; - - - if ( csindex->offsets ) - { - glyph->root.control_data = csindex->bytes + - csindex->offsets[glyph_index] - 1; - glyph->root.control_len = (FT_Long)charstring_len; - } - } - - Glyph_Build_Finished: - /* save new glyph tables, if no error */ - if ( !error ) - cff_builder_done( &decoder.builder ); - /* XXX: anything to do for broken glyph entry? */ - } - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* Incremental fonts can optionally override the metrics. */ - if ( !error && - face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs->get_glyph_metrics ) - { - FT_Incremental_MetricsRec metrics; - - - metrics.bearing_x = decoder.builder.left_bearing.x; - metrics.bearing_y = 0; - metrics.advance = decoder.builder.advance.x; - metrics.advance_v = decoder.builder.advance.y; - - error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( - face->root.internal->incremental_interface->object, - glyph_index, FALSE, &metrics ); - - decoder.builder.left_bearing.x = metrics.bearing_x; - decoder.builder.advance.x = metrics.advance; - decoder.builder.advance.y = metrics.advance_v; - } - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - if ( !error ) - { - /* Now, set the metrics -- this is rather simple, as */ - /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax. */ - - /* For composite glyphs, return only left side bearing and */ - /* advance width. */ - if ( load_flags & FT_LOAD_NO_RECURSE ) - { - FT_Slot_Internal internal = glyph->root.internal; - - - glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; - glyph->root.metrics.horiAdvance = decoder.glyph_width; - internal->glyph_matrix = font_matrix; - internal->glyph_delta = font_offset; - internal->glyph_transformed = 1; - } - else - { - FT_BBox cbox; - FT_Glyph_Metrics* metrics = &glyph->root.metrics; - FT_Bool has_vertical_info; - - - if ( face->horizontal.number_Of_HMetrics ) - { - FT_Short horiBearingX = 0; - FT_UShort horiAdvance = 0; - - - ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, - glyph_index, - &horiBearingX, - &horiAdvance ); - metrics->horiAdvance = horiAdvance; - metrics->horiBearingX = horiBearingX; - glyph->root.linearHoriAdvance = horiAdvance; - } - else - { - /* copy the _unscaled_ advance width */ - metrics->horiAdvance = decoder.glyph_width; - glyph->root.linearHoriAdvance = decoder.glyph_width; - } - - glyph->root.internal->glyph_transformed = 0; - - has_vertical_info = FT_BOOL( face->vertical_info && - face->vertical.number_Of_VMetrics > 0 ); - - /* get the vertical metrics from the vmtx table if we have one */ - if ( has_vertical_info ) - { - FT_Short vertBearingY = 0; - FT_UShort vertAdvance = 0; - - - ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, - glyph_index, - &vertBearingY, - &vertAdvance ); - metrics->vertBearingY = vertBearingY; - metrics->vertAdvance = vertAdvance; - } - else - { - /* make up vertical ones */ - if ( face->os2.version != 0xFFFFU ) - metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - - face->os2.sTypoDescender ); - else - metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - - face->horizontal.Descender ); - } - - glyph->root.linearVertAdvance = metrics->vertAdvance; - - glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; - - glyph->root.outline.flags = 0; - if ( size && size->root.metrics.y_ppem < 24 ) - glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; - - glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; - - /* apply the font matrix, if any */ - if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || - font_matrix.xy != 0 || font_matrix.yx != 0 ) - { - FT_Outline_Transform( &glyph->root.outline, &font_matrix ); - - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, - font_matrix.xx ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, - font_matrix.yy ); - } - - if ( font_offset.x || font_offset.y ) - { - FT_Outline_Translate( &glyph->root.outline, - font_offset.x, - font_offset.y ); - - metrics->horiAdvance += font_offset.x; - metrics->vertAdvance += font_offset.y; - } - - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) - { - /* scale the outline and the metrics */ - FT_Int n; - FT_Outline* cur = &glyph->root.outline; - FT_Vector* vec = cur->points; - FT_Fixed x_scale = glyph->x_scale; - FT_Fixed y_scale = glyph->y_scale; - - - /* First of all, scale the points */ - if ( !hinting || !decoder.builder.hints_funcs ) - for ( n = cur->n_points; n > 0; n--, vec++ ) - { - vec->x = FT_MulFix( vec->x, x_scale ); - vec->y = FT_MulFix( vec->y, y_scale ); - } - - /* Then scale the metrics */ - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); - } - - /* compute the other metrics */ - FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); - - metrics->width = cbox.xMax - cbox.xMin; - metrics->height = cbox.yMax - cbox.yMin; - - metrics->horiBearingX = cbox.xMin; - metrics->horiBearingY = cbox.yMax; - - if ( has_vertical_info ) - metrics->vertBearingX = metrics->horiBearingX - - metrics->horiAdvance / 2; - else - { - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - ft_synthesize_vertical_metrics( metrics, - metrics->vertAdvance ); - } - } - } - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cffgload.h b/third_party/freetype/src/cff/cffgload.h deleted file mode 100644 index 5f2655f3d98424667f100975204f4595f2e447bb..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffgload.h +++ /dev/null @@ -1,245 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffgload.h */ -/* */ -/* OpenType Glyph Loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFGLOAD_H__ -#define __CFFGLOAD_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include "cffobjs.h" - - -FT_BEGIN_HEADER - - -#define CFF_MAX_OPERANDS 48 -#define CFF_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */ - /* only 10 are allowed but there exist */ - /* fonts like `HiraKakuProN-W3.ttf' */ - /* (Hiragino Kaku Gothic ProN W3; */ - /* 8.2d6e1; 2014-12-19) that exceed */ - /* this limit */ -#define CFF_MAX_TRANS_ELEMENTS 32 - - - /*************************************************************************/ - /* */ - /* <Structure> */ - /* CFF_Builder */ - /* */ - /* <Description> */ - /* A structure used during glyph loading to store its outline. */ - /* */ - /* <Fields> */ - /* memory :: The current memory object. */ - /* */ - /* face :: The current face object. */ - /* */ - /* glyph :: The current glyph slot. */ - /* */ - /* loader :: The current glyph loader. */ - /* */ - /* base :: The base glyph outline. */ - /* */ - /* current :: The current glyph outline. */ - /* */ - /* pos_x :: The horizontal translation (if composite glyph). */ - /* */ - /* pos_y :: The vertical translation (if composite glyph). */ - /* */ - /* left_bearing :: The left side bearing point. */ - /* */ - /* advance :: The horizontal advance vector. */ - /* */ - /* bbox :: Unused. */ - /* */ - /* path_begun :: A flag which indicates that a new path has begun. */ - /* */ - /* load_points :: If this flag is not set, no points are loaded. */ - /* */ - /* no_recurse :: Set but not used. */ - /* */ - /* metrics_only :: A boolean indicating that we only want to compute */ - /* the metrics of a given glyph, not load all of its */ - /* points. */ - /* */ - /* hints_funcs :: Auxiliary pointer for hinting. */ - /* */ - /* hints_globals :: Auxiliary pointer for hinting. */ - /* */ - typedef struct CFF_Builder_ - { - FT_Memory memory; - TT_Face face; - CFF_GlyphSlot glyph; - FT_GlyphLoader loader; - FT_Outline* base; - FT_Outline* current; - - FT_Pos pos_x; - FT_Pos pos_y; - - FT_Vector left_bearing; - FT_Vector advance; - - FT_BBox bbox; /* bounding box */ - FT_Bool path_begun; - FT_Bool load_points; - FT_Bool no_recurse; - - FT_Bool metrics_only; - - void* hints_funcs; /* hinter-specific */ - void* hints_globals; /* hinter-specific */ - - } CFF_Builder; - - - FT_LOCAL( FT_Error ) - cff_check_points( CFF_Builder* builder, - FT_Int count ); - - FT_LOCAL( void ) - cff_builder_add_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ); - FT_LOCAL( FT_Error ) - cff_builder_add_point1( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ); - FT_LOCAL( FT_Error ) - cff_builder_start_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ); - FT_LOCAL( void ) - cff_builder_close_contour( CFF_Builder* builder ); - - - FT_LOCAL( FT_Int ) - cff_lookup_glyph_by_stdcharcode( CFF_Font cff, - FT_Int charcode ); - FT_LOCAL( FT_Error ) - cff_get_glyph_data( TT_Face face, - FT_UInt glyph_index, - FT_Byte** pointer, - FT_ULong* length ); - FT_LOCAL( void ) - cff_free_glyph_data( TT_Face face, - FT_Byte** pointer, - FT_ULong length ); - - - /* execution context charstring zone */ - - typedef struct CFF_Decoder_Zone_ - { - FT_Byte* base; - FT_Byte* limit; - FT_Byte* cursor; - - } CFF_Decoder_Zone; - - - typedef struct CFF_Decoder_ - { - CFF_Builder builder; - CFF_Font cff; - - FT_Fixed stack[CFF_MAX_OPERANDS + 1]; - FT_Fixed* top; - - CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1]; - CFF_Decoder_Zone* zone; - - FT_Int flex_state; - FT_Int num_flex_vectors; - FT_Vector flex_vectors[7]; - - FT_Pos glyph_width; - FT_Pos nominal_width; - - FT_Bool read_width; - FT_Bool width_only; - FT_Int num_hints; - FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS]; - - FT_UInt num_locals; - FT_UInt num_globals; - - FT_Int locals_bias; - FT_Int globals_bias; - - FT_Byte** locals; - FT_Byte** globals; - - FT_Byte** glyph_names; /* for pure CFF fonts only */ - FT_UInt num_glyphs; /* number of glyphs in font */ - - FT_Render_Mode hint_mode; - - FT_Bool seac; - - CFF_SubFont current_subfont; /* for current glyph_index */ - - } CFF_Decoder; - - - FT_LOCAL( void ) - cff_decoder_init( CFF_Decoder* decoder, - TT_Face face, - CFF_Size size, - CFF_GlyphSlot slot, - FT_Bool hinting, - FT_Render_Mode hint_mode ); - - FT_LOCAL( FT_Error ) - cff_decoder_prepare( CFF_Decoder* decoder, - CFF_Size size, - FT_UInt glyph_index ); - -#if 0 /* unused until we support pure CFF fonts */ - - /* Compute the maximum advance width of a font through quick parsing */ - FT_LOCAL( FT_Error ) - cff_compute_max_advance( TT_Face face, - FT_Int* max_advance ); - -#endif /* 0 */ - -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - FT_LOCAL( FT_Error ) - cff_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len ); -#endif - - FT_LOCAL( FT_Error ) - cff_slot_load( CFF_GlyphSlot glyph, - CFF_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ); - - -FT_END_HEADER - -#endif /* __CFFGLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffload.c b/third_party/freetype/src/cff/cffload.c deleted file mode 100644 index c61222d6519fd94776d5e08f34ff4527b320741a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffload.c +++ /dev/null @@ -1,1703 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffload.c */ -/* */ -/* OpenType and CFF data/program tables loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include FT_TYPE1_TABLES_H - -#include "cffload.h" -#include "cffparse.h" - -#include "cfferrs.h" - - -#if 1 - - static const FT_UShort cff_isoadobe_charset[229] = - { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228 - }; - - static const FT_UShort cff_expert_charset[166] = - { - 0, 1, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 13, 14, 15, 99, - 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 27, 28, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 109, 110, - 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 158, 155, 163, 319, - 320, 321, 322, 323, 324, 325, 326, 150, - 164, 169, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378 - }; - - static const FT_UShort cff_expertsubset_charset[87] = - { - 0, 1, 231, 232, 235, 236, 237, 238, - 13, 14, 15, 99, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 27, 28, - 249, 250, 251, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, - 266, 109, 110, 267, 268, 269, 270, 272, - 300, 301, 302, 305, 314, 315, 158, 155, - 163, 320, 321, 322, 323, 324, 325, 326, - 150, 164, 169, 327, 328, 329, 330, 331, - 332, 333, 334, 335, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346 - }; - - static const FT_UShort cff_standard_encoding[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, - 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, - 0, 111, 112, 113, 114, 0, 115, 116, - 117, 118, 119, 120, 121, 122, 0, 123, - 0, 124, 125, 126, 127, 128, 129, 130, - 131, 0, 132, 133, 0, 134, 135, 136, - 137, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 138, 0, 139, 0, 0, 0, 0, - 140, 141, 142, 143, 0, 0, 0, 0, - 0, 144, 0, 0, 0, 145, 0, 0, - 146, 147, 148, 149, 0, 0, 0, 0 - }; - - static const FT_UShort cff_expert_encoding[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, - 1, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 237, 238, 13, 14, 15, 99, - 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 27, 28, 249, 250, 251, 252, - 0, 253, 254, 255, 256, 257, 0, 0, - 0, 258, 0, 0, 259, 260, 261, 262, - 0, 0, 263, 264, 265, 0, 266, 109, - 110, 267, 268, 269, 0, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 304, 305, 306, 0, 0, 307, 308, - 309, 310, 311, 0, 312, 0, 0, 312, - 0, 0, 314, 315, 0, 0, 316, 317, - 318, 0, 0, 0, 158, 155, 163, 319, - 320, 321, 322, 323, 324, 325, 0, 0, - 326, 150, 164, 169, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378 - }; - -#endif /* 1 */ - - - FT_LOCAL_DEF( FT_UShort ) - cff_get_standard_encoding( FT_UInt charcode ) - { - return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode] - : 0 ); - } - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cffload - - - /* read an offset from the index's stream current position */ - static FT_ULong - cff_index_read_offset( CFF_Index idx, - FT_Error *errorp ) - { - FT_Error error; - FT_Stream stream = idx->stream; - FT_Byte tmp[4]; - FT_ULong result = 0; - - - if ( !FT_STREAM_READ( tmp, idx->off_size ) ) - { - FT_Int nn; - - - for ( nn = 0; nn < idx->off_size; nn++ ) - result = ( result << 8 ) | tmp[nn]; - } - - *errorp = error; - return result; - } - - - static FT_Error - cff_index_init( CFF_Index idx, - FT_Stream stream, - FT_Bool load ) - { - FT_Error error; - FT_Memory memory = stream->memory; - FT_UShort count; - - - FT_MEM_ZERO( idx, sizeof ( *idx ) ); - - idx->stream = stream; - idx->start = FT_STREAM_POS(); - if ( !FT_READ_USHORT( count ) && - count > 0 ) - { - FT_Byte offsize; - FT_ULong size; - - - /* there is at least one element; read the offset size, */ - /* then access the offset table to compute the index's total size */ - if ( FT_READ_BYTE( offsize ) ) - goto Exit; - - if ( offsize < 1 || offsize > 4 ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - idx->count = count; - idx->off_size = offsize; - size = (FT_ULong)( count + 1 ) * offsize; - - idx->data_offset = idx->start + 3 + size; - - if ( FT_STREAM_SKIP( size - offsize ) ) - goto Exit; - - size = cff_index_read_offset( idx, &error ); - if ( error ) - goto Exit; - - if ( size == 0 ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - idx->data_size = --size; - - if ( load ) - { - /* load the data */ - if ( FT_FRAME_EXTRACT( size, idx->bytes ) ) - goto Exit; - } - else - { - /* skip the data */ - if ( FT_STREAM_SKIP( size ) ) - goto Exit; - } - } - - Exit: - if ( error ) - FT_FREE( idx->offsets ); - - return error; - } - - - static void - cff_index_done( CFF_Index idx ) - { - if ( idx->stream ) - { - FT_Stream stream = idx->stream; - FT_Memory memory = stream->memory; - - - if ( idx->bytes ) - FT_FRAME_RELEASE( idx->bytes ); - - FT_FREE( idx->offsets ); - FT_MEM_ZERO( idx, sizeof ( *idx ) ); - } - } - - - static FT_Error - cff_index_load_offsets( CFF_Index idx ) - { - FT_Error error = FT_Err_Ok; - FT_Stream stream = idx->stream; - FT_Memory memory = stream->memory; - - - if ( idx->count > 0 && idx->offsets == NULL ) - { - FT_Byte offsize = idx->off_size; - FT_ULong data_size; - FT_Byte* p; - FT_Byte* p_end; - FT_ULong* poff; - - - data_size = (FT_ULong)( idx->count + 1 ) * offsize; - - if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) || - FT_STREAM_SEEK( idx->start + 3 ) || - FT_FRAME_ENTER( data_size ) ) - goto Exit; - - poff = idx->offsets; - p = (FT_Byte*)stream->cursor; - p_end = p + data_size; - - switch ( offsize ) - { - case 1: - for ( ; p < p_end; p++, poff++ ) - poff[0] = p[0]; - break; - - case 2: - for ( ; p < p_end; p += 2, poff++ ) - poff[0] = FT_PEEK_USHORT( p ); - break; - - case 3: - for ( ; p < p_end; p += 3, poff++ ) - poff[0] = FT_PEEK_UOFF3( p ); - break; - - default: - for ( ; p < p_end; p += 4, poff++ ) - poff[0] = FT_PEEK_ULONG( p ); - } - - FT_FRAME_EXIT(); - } - - Exit: - if ( error ) - FT_FREE( idx->offsets ); - - return error; - } - - - /* Allocate a table containing pointers to an index's elements. */ - /* The `pool' argument makes this function convert the index */ - /* entries to C-style strings (this is, NULL-terminated). */ - static FT_Error - cff_index_get_pointers( CFF_Index idx, - FT_Byte*** table, - FT_Byte** pool ) - { - FT_Error error = FT_Err_Ok; - FT_Memory memory = idx->stream->memory; - - FT_Byte** t = NULL; - FT_Byte* new_bytes = NULL; - - - *table = NULL; - - if ( idx->offsets == NULL ) - { - error = cff_index_load_offsets( idx ); - if ( error ) - goto Exit; - } - - if ( idx->count > 0 && - !FT_NEW_ARRAY( t, idx->count + 1 ) && - ( !pool || !FT_ALLOC( new_bytes, - idx->data_size + idx->count ) ) ) - { - FT_ULong n, cur_offset; - FT_ULong extra = 0; - FT_Byte* org_bytes = idx->bytes; - - - /* at this point, `idx->offsets' can't be NULL */ - cur_offset = idx->offsets[0] - 1; - - /* sanity check */ - if ( cur_offset != 0 ) - { - FT_TRACE0(( "cff_index_get_pointers:" - " invalid first offset value %d set to zero\n", - cur_offset )); - cur_offset = 0; - } - - if ( !pool ) - t[0] = org_bytes + cur_offset; - else - t[0] = new_bytes + cur_offset; - - for ( n = 1; n <= idx->count; n++ ) - { - FT_ULong next_offset = idx->offsets[n] - 1; - - - /* two sanity checks for invalid offset tables */ - if ( next_offset < cur_offset ) - next_offset = cur_offset; - else if ( next_offset > idx->data_size ) - next_offset = idx->data_size; - - if ( !pool ) - t[n] = org_bytes + next_offset; - else - { - t[n] = new_bytes + next_offset + extra; - - if ( next_offset != cur_offset ) - { - FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] ); - t[n][0] = '\0'; - t[n] += 1; - extra++; - } - } - - cur_offset = next_offset; - } - *table = t; - - if ( pool ) - *pool = new_bytes; - } - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - cff_index_access_element( CFF_Index idx, - FT_UInt element, - FT_Byte** pbytes, - FT_ULong* pbyte_len ) - { - FT_Error error = FT_Err_Ok; - - - if ( idx && idx->count > element ) - { - /* compute start and end offsets */ - FT_Stream stream = idx->stream; - FT_ULong off1, off2 = 0; - - - /* load offsets from file or the offset table */ - if ( !idx->offsets ) - { - FT_ULong pos = element * idx->off_size; - - - if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) - goto Exit; - - off1 = cff_index_read_offset( idx, &error ); - if ( error ) - goto Exit; - - if ( off1 != 0 ) - { - do - { - element++; - off2 = cff_index_read_offset( idx, &error ); - } - while ( off2 == 0 && element < idx->count ); - } - } - else /* use offsets table */ - { - off1 = idx->offsets[element]; - if ( off1 ) - { - do - { - element++; - off2 = idx->offsets[element]; - - } while ( off2 == 0 && element < idx->count ); - } - } - - /* XXX: should check off2 does not exceed the end of this entry; */ - /* at present, only truncate off2 at the end of this stream */ - if ( off2 > stream->size + 1 || - idx->data_offset > stream->size - off2 + 1 ) - { - FT_ERROR(( "cff_index_access_element:" - " offset to next entry (%d)" - " exceeds the end of stream (%d)\n", - off2, stream->size - idx->data_offset + 1 )); - off2 = stream->size - idx->data_offset + 1; - } - - /* access element */ - if ( off1 && off2 > off1 ) - { - *pbyte_len = off2 - off1; - - if ( idx->bytes ) - { - /* this index was completely loaded in memory, that's easy */ - *pbytes = idx->bytes + off1 - 1; - } - else - { - /* this index is still on disk/file, access it through a frame */ - if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || - FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) - goto Exit; - } - } - else - { - /* empty index element */ - *pbytes = 0; - *pbyte_len = 0; - } - } - else - error = FT_THROW( Invalid_Argument ); - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - cff_index_forget_element( CFF_Index idx, - FT_Byte** pbytes ) - { - if ( idx->bytes == 0 ) - { - FT_Stream stream = idx->stream; - - - FT_FRAME_RELEASE( *pbytes ); - } - } - - - /* get an entry from Name INDEX */ - FT_LOCAL_DEF( FT_String* ) - cff_index_get_name( CFF_Font font, - FT_UInt element ) - { - CFF_Index idx = &font->name_index; - FT_Memory memory = idx->stream->memory; - FT_Byte* bytes; - FT_ULong byte_len; - FT_Error error; - FT_String* name = 0; - - - error = cff_index_access_element( idx, element, &bytes, &byte_len ); - if ( error ) - goto Exit; - - if ( !FT_ALLOC( name, byte_len + 1 ) ) - { - FT_MEM_COPY( name, bytes, byte_len ); - name[byte_len] = 0; - } - cff_index_forget_element( idx, &bytes ); - - Exit: - return name; - } - - - /* get an entry from String INDEX */ - FT_LOCAL_DEF( FT_String* ) - cff_index_get_string( CFF_Font font, - FT_UInt element ) - { - return ( element < font->num_strings ) - ? (FT_String*)font->strings[element] - : NULL; - } - - - FT_LOCAL_DEF( FT_String* ) - cff_index_get_sid_string( CFF_Font font, - FT_UInt sid ) - { - /* value 0xFFFFU indicates a missing dictionary entry */ - if ( sid == 0xFFFFU ) - return NULL; - - /* if it is not a standard string, return it */ - if ( sid > 390 ) - return cff_index_get_string( font, sid - 391 ); - - /* CID-keyed CFF fonts don't have glyph names */ - if ( !font->psnames ) - return NULL; - - /* this is a standard string */ - return (FT_String *)font->psnames->adobe_std_strings( sid ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** FD Select table support ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - - - static void - CFF_Done_FD_Select( CFF_FDSelect fdselect, - FT_Stream stream ) - { - if ( fdselect->data ) - FT_FRAME_RELEASE( fdselect->data ); - - fdselect->data_size = 0; - fdselect->format = 0; - fdselect->range_count = 0; - } - - - static FT_Error - CFF_Load_FD_Select( CFF_FDSelect fdselect, - FT_UInt num_glyphs, - FT_Stream stream, - FT_ULong offset ) - { - FT_Error error; - FT_Byte format; - FT_UInt num_ranges; - - - /* read format */ - if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) ) - goto Exit; - - fdselect->format = format; - fdselect->cache_count = 0; /* clear cache */ - - switch ( format ) - { - case 0: /* format 0, that's simple */ - fdselect->data_size = num_glyphs; - goto Load_Data; - - case 3: /* format 3, a tad more complex */ - if ( FT_READ_USHORT( num_ranges ) ) - goto Exit; - - if ( !num_ranges ) - { - FT_TRACE0(( "CFF_Load_FD_Select: empty FDSelect array\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - fdselect->data_size = num_ranges * 3 + 2; - - Load_Data: - if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) ) - goto Exit; - break; - - default: /* hmm... that's wrong */ - error = FT_THROW( Invalid_File_Format ); - } - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Byte ) - cff_fd_select_get( CFF_FDSelect fdselect, - FT_UInt glyph_index ) - { - FT_Byte fd = 0; - - - switch ( fdselect->format ) - { - case 0: - fd = fdselect->data[glyph_index]; - break; - - case 3: - /* first, compare to the cache */ - if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < - fdselect->cache_count ) - { - fd = fdselect->cache_fd; - break; - } - - /* then, look up the ranges array */ - { - FT_Byte* p = fdselect->data; - FT_Byte* p_limit = p + fdselect->data_size; - FT_Byte fd2; - FT_UInt first, limit; - - - first = FT_NEXT_USHORT( p ); - do - { - if ( glyph_index < first ) - break; - - fd2 = *p++; - limit = FT_NEXT_USHORT( p ); - - if ( glyph_index < limit ) - { - fd = fd2; - - /* update cache */ - fdselect->cache_first = first; - fdselect->cache_count = limit - first; - fdselect->cache_fd = fd2; - break; - } - first = limit; - - } while ( p < p_limit ); - } - break; - - default: - ; - } - - return fd; - } - - - /*************************************************************************/ - /*************************************************************************/ - /*** ***/ - /*** CFF font support ***/ - /*** ***/ - /*************************************************************************/ - /*************************************************************************/ - - static FT_Error - cff_charset_compute_cids( CFF_Charset charset, - FT_UInt num_glyphs, - FT_Memory memory ) - { - FT_Error error = FT_Err_Ok; - FT_UInt i; - FT_Long j; - FT_UShort max_cid = 0; - - - if ( charset->max_cid > 0 ) - goto Exit; - - for ( i = 0; i < num_glyphs; i++ ) - { - if ( charset->sids[i] > max_cid ) - max_cid = charset->sids[i]; - } - - if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) ) - goto Exit; - - /* When multiple GIDs map to the same CID, we choose the lowest */ - /* GID. This is not described in any spec, but it matches the */ - /* behaviour of recent Acroread versions. */ - for ( j = (FT_Long)num_glyphs - 1; j >= 0 ; j-- ) - charset->cids[charset->sids[j]] = (FT_UShort)j; - - charset->max_cid = max_cid; - charset->num_glyphs = num_glyphs; - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_UInt ) - cff_charset_cid_to_gindex( CFF_Charset charset, - FT_UInt cid ) - { - FT_UInt result = 0; - - - if ( cid <= charset->max_cid ) - result = charset->cids[cid]; - - return result; - } - - - static void - cff_charset_free_cids( CFF_Charset charset, - FT_Memory memory ) - { - FT_FREE( charset->cids ); - charset->max_cid = 0; - } - - - static void - cff_charset_done( CFF_Charset charset, - FT_Stream stream ) - { - FT_Memory memory = stream->memory; - - - cff_charset_free_cids( charset, memory ); - - FT_FREE( charset->sids ); - charset->format = 0; - charset->offset = 0; - } - - - static FT_Error - cff_charset_load( CFF_Charset charset, - FT_UInt num_glyphs, - FT_Stream stream, - FT_ULong base_offset, - FT_ULong offset, - FT_Bool invert ) - { - FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - FT_UShort glyph_sid; - - - /* If the the offset is greater than 2, we have to parse the */ - /* charset table. */ - if ( offset > 2 ) - { - FT_UInt j; - - - charset->offset = base_offset + offset; - - /* Get the format of the table. */ - if ( FT_STREAM_SEEK( charset->offset ) || - FT_READ_BYTE( charset->format ) ) - goto Exit; - - /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) - goto Exit; - - /* assign the .notdef glyph */ - charset->sids[0] = 0; - - switch ( charset->format ) - { - case 0: - if ( num_glyphs > 0 ) - { - if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) ) - goto Exit; - - for ( j = 1; j < num_glyphs; j++ ) - charset->sids[j] = FT_GET_USHORT(); - - FT_FRAME_EXIT(); - } - break; - - case 1: - case 2: - { - FT_UInt nleft; - FT_UInt i; - - - j = 1; - - while ( j < num_glyphs ) - { - /* Read the first glyph sid of the range. */ - if ( FT_READ_USHORT( glyph_sid ) ) - goto Exit; - - /* Read the number of glyphs in the range. */ - if ( charset->format == 2 ) - { - if ( FT_READ_USHORT( nleft ) ) - goto Exit; - } - else - { - if ( FT_READ_BYTE( nleft ) ) - goto Exit; - } - - /* try to rescue some of the SIDs if `nleft' is too large */ - if ( glyph_sid > 0xFFFFL - nleft ) - { - FT_ERROR(( "cff_charset_load: invalid SID range trimmed" - " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid )); - nleft = ( FT_UInt )( 0xFFFFL - glyph_sid ); - } - - /* Fill in the range of sids -- `nleft + 1' glyphs. */ - for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ ) - charset->sids[j] = glyph_sid; - } - } - break; - - default: - FT_ERROR(( "cff_charset_load: invalid table format\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - } - else - { - /* Parse default tables corresponding to offset == 0, 1, or 2. */ - /* CFF specification intimates the following: */ - /* */ - /* In order to use a predefined charset, the following must be */ - /* true: The charset constructed for the glyphs in the font's */ - /* charstrings dictionary must match the predefined charset in */ - /* the first num_glyphs. */ - - charset->offset = offset; /* record charset type */ - - switch ( (FT_UInt)offset ) - { - case 0: - if ( num_glyphs > 229 ) - { - FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe ISO-Latin)\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) - goto Exit; - - /* Copy the predefined charset into the allocated memory. */ - FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs ); - - break; - - case 1: - if ( num_glyphs > 166 ) - { - FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe Expert)\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) - goto Exit; - - /* Copy the predefined charset into the allocated memory. */ - FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs ); - - break; - - case 2: - if ( num_glyphs > 87 ) - { - FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe Expert Subset)\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) - goto Exit; - - /* Copy the predefined charset into the allocated memory. */ - FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs ); - - break; - - default: - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - } - - /* we have to invert the `sids' array for subsetted CID-keyed fonts */ - if ( invert ) - error = cff_charset_compute_cids( charset, num_glyphs, memory ); - - Exit: - /* Clean up if there was an error. */ - if ( error ) - { - FT_FREE( charset->sids ); - FT_FREE( charset->cids ); - charset->format = 0; - charset->offset = 0; - charset->sids = 0; - } - - return error; - } - - - static void - cff_encoding_done( CFF_Encoding encoding ) - { - encoding->format = 0; - encoding->offset = 0; - encoding->count = 0; - } - - - static FT_Error - cff_encoding_load( CFF_Encoding encoding, - CFF_Charset charset, - FT_UInt num_glyphs, - FT_Stream stream, - FT_ULong base_offset, - FT_ULong offset ) - { - FT_Error error = FT_Err_Ok; - FT_UInt count; - FT_UInt j; - FT_UShort glyph_sid; - FT_UInt glyph_code; - - - /* Check for charset->sids. If we do not have this, we fail. */ - if ( !charset->sids ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* Zero out the code to gid/sid mappings. */ - for ( j = 0; j < 256; j++ ) - { - encoding->sids [j] = 0; - encoding->codes[j] = 0; - } - - /* Note: The encoding table in a CFF font is indexed by glyph index; */ - /* the first encoded glyph index is 1. Hence, we read the character */ - /* code (`glyph_code') at index j and make the assignment: */ - /* */ - /* encoding->codes[glyph_code] = j + 1 */ - /* */ - /* We also make the assignment: */ - /* */ - /* encoding->sids[glyph_code] = charset->sids[j + 1] */ - /* */ - /* This gives us both a code to GID and a code to SID mapping. */ - - if ( offset > 1 ) - { - encoding->offset = base_offset + offset; - - /* we need to parse the table to determine its size */ - if ( FT_STREAM_SEEK( encoding->offset ) || - FT_READ_BYTE( encoding->format ) || - FT_READ_BYTE( count ) ) - goto Exit; - - switch ( encoding->format & 0x7F ) - { - case 0: - { - FT_Byte* p; - - - /* By convention, GID 0 is always ".notdef" and is never */ - /* coded in the font. Hence, the number of codes found */ - /* in the table is `count+1'. */ - /* */ - encoding->count = count + 1; - - if ( FT_FRAME_ENTER( count ) ) - goto Exit; - - p = (FT_Byte*)stream->cursor; - - for ( j = 1; j <= count; j++ ) - { - glyph_code = *p++; - - /* Make sure j is not too big. */ - if ( j < num_glyphs ) - { - /* Assign code to GID mapping. */ - encoding->codes[glyph_code] = (FT_UShort)j; - - /* Assign code to SID mapping. */ - encoding->sids[glyph_code] = charset->sids[j]; - } - } - - FT_FRAME_EXIT(); - } - break; - - case 1: - { - FT_UInt nleft; - FT_UInt i = 1; - FT_UInt k; - - - encoding->count = 0; - - /* Parse the Format1 ranges. */ - for ( j = 0; j < count; j++, i += nleft ) - { - /* Read the first glyph code of the range. */ - if ( FT_READ_BYTE( glyph_code ) ) - goto Exit; - - /* Read the number of codes in the range. */ - if ( FT_READ_BYTE( nleft ) ) - goto Exit; - - /* Increment nleft, so we read `nleft + 1' codes/sids. */ - nleft++; - - /* compute max number of character codes */ - if ( (FT_UInt)nleft > encoding->count ) - encoding->count = nleft; - - /* Fill in the range of codes/sids. */ - for ( k = i; k < nleft + i; k++, glyph_code++ ) - { - /* Make sure k is not too big. */ - if ( k < num_glyphs && glyph_code < 256 ) - { - /* Assign code to GID mapping. */ - encoding->codes[glyph_code] = (FT_UShort)k; - - /* Assign code to SID mapping. */ - encoding->sids[glyph_code] = charset->sids[k]; - } - } - } - - /* simple check; one never knows what can be found in a font */ - if ( encoding->count > 256 ) - encoding->count = 256; - } - break; - - default: - FT_ERROR(( "cff_encoding_load: invalid table format\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* Parse supplemental encodings, if any. */ - if ( encoding->format & 0x80 ) - { - FT_UInt gindex; - - - /* count supplements */ - if ( FT_READ_BYTE( count ) ) - goto Exit; - - for ( j = 0; j < count; j++ ) - { - /* Read supplemental glyph code. */ - if ( FT_READ_BYTE( glyph_code ) ) - goto Exit; - - /* Read the SID associated with this glyph code. */ - if ( FT_READ_USHORT( glyph_sid ) ) - goto Exit; - - /* Assign code to SID mapping. */ - encoding->sids[glyph_code] = glyph_sid; - - /* First, look up GID which has been assigned to */ - /* SID glyph_sid. */ - for ( gindex = 0; gindex < num_glyphs; gindex++ ) - { - if ( charset->sids[gindex] == glyph_sid ) - { - encoding->codes[glyph_code] = (FT_UShort)gindex; - break; - } - } - } - } - } - else - { - /* We take into account the fact a CFF font can use a predefined */ - /* encoding without containing all of the glyphs encoded by this */ - /* encoding (see the note at the end of section 12 in the CFF */ - /* specification). */ - - switch ( (FT_UInt)offset ) - { - case 0: - /* First, copy the code to SID mapping. */ - FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 ); - goto Populate; - - case 1: - /* First, copy the code to SID mapping. */ - FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 ); - - Populate: - /* Construct code to GID mapping from code to SID mapping */ - /* and charset. */ - - encoding->count = 0; - - error = cff_charset_compute_cids( charset, num_glyphs, - stream->memory ); - if ( error ) - goto Exit; - - for ( j = 0; j < 256; j++ ) - { - FT_UInt sid = encoding->sids[j]; - FT_UInt gid = 0; - - - if ( sid ) - gid = cff_charset_cid_to_gindex( charset, sid ); - - if ( gid != 0 ) - { - encoding->codes[j] = (FT_UShort)gid; - encoding->count = j + 1; - } - else - { - encoding->codes[j] = 0; - encoding->sids [j] = 0; - } - } - break; - - default: - FT_ERROR(( "cff_encoding_load: invalid table format\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - } - - Exit: - - /* Clean up if there was an error. */ - return error; - } - - - static FT_Error - cff_subfont_load( CFF_SubFont font, - CFF_Index idx, - FT_UInt font_index, - FT_Stream stream, - FT_ULong base_offset, - FT_Library library ) - { - FT_Error error; - CFF_ParserRec parser; - FT_Byte* dict = NULL; - FT_ULong dict_len; - CFF_FontRecDict top = &font->font_dict; - CFF_Private priv = &font->private_dict; - - - cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library ); - - /* set defaults */ - FT_MEM_ZERO( top, sizeof ( *top ) ); - - top->underline_position = -( 100L << 16 ); - top->underline_thickness = 50L << 16; - top->charstring_type = 2; - top->font_matrix.xx = 0x10000L; - top->font_matrix.yy = 0x10000L; - top->cid_count = 8720; - - /* we use the implementation specific SID value 0xFFFF to indicate */ - /* missing entries */ - top->version = 0xFFFFU; - top->notice = 0xFFFFU; - top->copyright = 0xFFFFU; - top->full_name = 0xFFFFU; - top->family_name = 0xFFFFU; - top->weight = 0xFFFFU; - top->embedded_postscript = 0xFFFFU; - - top->cid_registry = 0xFFFFU; - top->cid_ordering = 0xFFFFU; - top->cid_font_name = 0xFFFFU; - - error = cff_index_access_element( idx, font_index, &dict, &dict_len ); - if ( !error ) - { - FT_TRACE4(( " top dictionary:\n" )); - error = cff_parser_run( &parser, dict, dict + dict_len ); - } - - cff_index_forget_element( idx, &dict ); - - if ( error ) - goto Exit; - - /* if it is a CID font, we stop there */ - if ( top->cid_registry != 0xFFFFU ) - goto Exit; - - /* parse the private dictionary, if any */ - if ( top->private_offset && top->private_size ) - { - /* set defaults */ - FT_MEM_ZERO( priv, sizeof ( *priv ) ); - - priv->blue_shift = 7; - priv->blue_fuzz = 1; - priv->lenIV = -1; - priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); - priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); - - cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library ); - - if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || - FT_FRAME_ENTER( font->font_dict.private_size ) ) - goto Exit; - - FT_TRACE4(( " private dictionary:\n" )); - error = cff_parser_run( &parser, - (FT_Byte*)stream->cursor, - (FT_Byte*)stream->limit ); - FT_FRAME_EXIT(); - if ( error ) - goto Exit; - - /* ensure that `num_blue_values' is even */ - priv->num_blue_values &= ~1; - } - - /* read the local subrs, if any */ - if ( priv->local_subrs_offset ) - { - if ( FT_STREAM_SEEK( base_offset + top->private_offset + - priv->local_subrs_offset ) ) - goto Exit; - - error = cff_index_init( &font->local_subrs_index, stream, 1 ); - if ( error ) - goto Exit; - - error = cff_index_get_pointers( &font->local_subrs_index, - &font->local_subrs, NULL ); - if ( error ) - goto Exit; - } - - Exit: - return error; - } - - - static void - cff_subfont_done( FT_Memory memory, - CFF_SubFont subfont ) - { - if ( subfont ) - { - cff_index_done( &subfont->local_subrs_index ); - FT_FREE( subfont->local_subrs ); - } - } - - - FT_LOCAL_DEF( FT_Error ) - cff_font_load( FT_Library library, - FT_Stream stream, - FT_Int face_index, - CFF_Font font, - FT_Bool pure_cff ) - { - static const FT_Frame_Field cff_header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE CFF_FontRec - - FT_FRAME_START( 4 ), - FT_FRAME_BYTE( version_major ), - FT_FRAME_BYTE( version_minor ), - FT_FRAME_BYTE( header_size ), - FT_FRAME_BYTE( absolute_offsize ), - FT_FRAME_END - }; - - FT_Error error; - FT_Memory memory = stream->memory; - FT_ULong base_offset; - CFF_FontRecDict dict; - CFF_IndexRec string_index; - FT_UInt subfont_index; - - - FT_ZERO( font ); - FT_ZERO( &string_index ); - - font->stream = stream; - font->memory = memory; - dict = &font->top_font.font_dict; - base_offset = FT_STREAM_POS(); - - /* read CFF font header */ - if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) - goto Exit; - - /* check format */ - if ( font->version_major != 1 || - font->header_size < 4 || - font->absolute_offsize > 4 ) - { - FT_TRACE2(( " not a CFF font header\n" )); - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - /* skip the rest of the header */ - if ( FT_STREAM_SKIP( font->header_size - 4 ) ) - goto Exit; - - /* read the name, top dict, string and global subrs index */ - if ( FT_SET_ERROR( cff_index_init( &font->name_index, - stream, 0 ) ) || - FT_SET_ERROR( cff_index_init( &font->font_dict_index, - stream, 0 ) ) || - FT_SET_ERROR( cff_index_init( &string_index, - stream, 1 ) ) || - FT_SET_ERROR( cff_index_init( &font->global_subrs_index, - stream, 1 ) ) || - FT_SET_ERROR( cff_index_get_pointers( &string_index, - &font->strings, - &font->string_pool ) ) ) - goto Exit; - - font->num_strings = string_index.count; - - if ( pure_cff ) - { - /* well, we don't really forget the `disabled' fonts... */ - subfont_index = (FT_UInt)( face_index & 0xFFFF ); - - if ( face_index > 0 && subfont_index >= font->name_index.count ) - { - FT_ERROR(( "cff_font_load:" - " invalid subfont index for pure CFF font (%d)\n", - subfont_index )); - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - font->num_faces = font->name_index.count; - } - else - { - subfont_index = 0; - - if ( font->name_index.count > 1 ) - { - FT_ERROR(( "cff_font_load:" - " invalid CFF font with multiple subfonts\n" - " " - " in SFNT wrapper\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - } - - /* in case of a font format check, simply exit now */ - if ( face_index < 0 ) - goto Exit; - - /* now, parse the top-level font dictionary */ - FT_TRACE4(( "parsing top-level\n" )); - error = cff_subfont_load( &font->top_font, - &font->font_dict_index, - subfont_index, - stream, - base_offset, - library ); - if ( error ) - goto Exit; - - if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) - goto Exit; - - error = cff_index_init( &font->charstrings_index, stream, 0 ); - if ( error ) - goto Exit; - - /* now, check for a CID font */ - if ( dict->cid_registry != 0xFFFFU ) - { - CFF_IndexRec fd_index; - CFF_SubFont sub = NULL; - FT_UInt idx; - - - /* this is a CID-keyed font, we must now allocate a table of */ - /* sub-fonts, then load each of them separately */ - if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) - goto Exit; - - error = cff_index_init( &fd_index, stream, 0 ); - if ( error ) - goto Exit; - - if ( fd_index.count > CFF_MAX_CID_FONTS ) - { - FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" )); - goto Fail_CID; - } - - /* allocate & read each font dict independently */ - font->num_subfonts = fd_index.count; - if ( FT_NEW_ARRAY( sub, fd_index.count ) ) - goto Fail_CID; - - /* set up pointer table */ - for ( idx = 0; idx < fd_index.count; idx++ ) - font->subfonts[idx] = sub + idx; - - /* now load each subfont independently */ - for ( idx = 0; idx < fd_index.count; idx++ ) - { - sub = font->subfonts[idx]; - FT_TRACE4(( "parsing subfont %u\n", idx )); - error = cff_subfont_load( sub, &fd_index, idx, - stream, base_offset, library ); - if ( error ) - goto Fail_CID; - } - - /* now load the FD Select array */ - error = CFF_Load_FD_Select( &font->fd_select, - font->charstrings_index.count, - stream, - base_offset + dict->cid_fd_select_offset ); - - Fail_CID: - cff_index_done( &fd_index ); - - if ( error ) - goto Exit; - } - else - font->num_subfonts = 0; - - /* read the charstrings index now */ - if ( dict->charstrings_offset == 0 ) - { - FT_ERROR(( "cff_font_load: no charstrings offset\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - font->num_glyphs = font->charstrings_index.count; - - error = cff_index_get_pointers( &font->global_subrs_index, - &font->global_subrs, NULL ); - - if ( error ) - goto Exit; - - /* read the Charset and Encoding tables if available */ - if ( font->num_glyphs > 0 ) - { - FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); - - - error = cff_charset_load( &font->charset, font->num_glyphs, stream, - base_offset, dict->charset_offset, invert ); - if ( error ) - goto Exit; - - /* CID-keyed CFFs don't have an encoding */ - if ( dict->cid_registry == 0xFFFFU ) - { - error = cff_encoding_load( &font->encoding, - &font->charset, - font->num_glyphs, - stream, - base_offset, - dict->encoding_offset ); - if ( error ) - goto Exit; - } - } - - /* get the font name (/CIDFontName for CID-keyed fonts, */ - /* /FontName otherwise) */ - font->font_name = cff_index_get_name( font, subfont_index ); - - Exit: - cff_index_done( &string_index ); - - return error; - } - - - FT_LOCAL_DEF( void ) - cff_font_done( CFF_Font font ) - { - FT_Memory memory = font->memory; - FT_UInt idx; - - - cff_index_done( &font->global_subrs_index ); - cff_index_done( &font->font_dict_index ); - cff_index_done( &font->name_index ); - cff_index_done( &font->charstrings_index ); - - /* release font dictionaries, but only if working with */ - /* a CID keyed CFF font */ - if ( font->num_subfonts > 0 ) - { - for ( idx = 0; idx < font->num_subfonts; idx++ ) - cff_subfont_done( memory, font->subfonts[idx] ); - - /* the subfonts array has been allocated as a single block */ - FT_FREE( font->subfonts[0] ); - } - - cff_encoding_done( &font->encoding ); - cff_charset_done( &font->charset, font->stream ); - - cff_subfont_done( memory, &font->top_font ); - - CFF_Done_FD_Select( &font->fd_select, font->stream ); - - FT_FREE( font->font_info ); - - FT_FREE( font->font_name ); - FT_FREE( font->global_subrs ); - FT_FREE( font->strings ); - FT_FREE( font->string_pool ); - - if ( font->cf2_instance.finalizer ) - { - font->cf2_instance.finalizer( font->cf2_instance.data ); - FT_FREE( font->cf2_instance.data ); - } - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cffload.h b/third_party/freetype/src/cff/cffload.h deleted file mode 100644 index 459e7b04461c25dd58f11024ba9fc6687b24199d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffload.h +++ /dev/null @@ -1,83 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffload.h */ -/* */ -/* OpenType & CFF data/program tables loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFLOAD_H__ -#define __CFFLOAD_H__ - - -#include <ft2build.h> -#include "cfftypes.h" - - -FT_BEGIN_HEADER - - FT_LOCAL( FT_UShort ) - cff_get_standard_encoding( FT_UInt charcode ); - - - FT_LOCAL( FT_String* ) - cff_index_get_string( CFF_Font font, - FT_UInt element ); - - FT_LOCAL( FT_String* ) - cff_index_get_sid_string( CFF_Font font, - FT_UInt sid ); - - - FT_LOCAL( FT_Error ) - cff_index_access_element( CFF_Index idx, - FT_UInt element, - FT_Byte** pbytes, - FT_ULong* pbyte_len ); - - FT_LOCAL( void ) - cff_index_forget_element( CFF_Index idx, - FT_Byte** pbytes ); - - FT_LOCAL( FT_String* ) - cff_index_get_name( CFF_Font font, - FT_UInt element ); - - - FT_LOCAL( FT_UInt ) - cff_charset_cid_to_gindex( CFF_Charset charset, - FT_UInt cid ); - - - FT_LOCAL( FT_Error ) - cff_font_load( FT_Library library, - FT_Stream stream, - FT_Int face_index, - CFF_Font font, - FT_Bool pure_cff ); - - FT_LOCAL( void ) - cff_font_done( CFF_Font font ); - - - FT_LOCAL( FT_Byte ) - cff_fd_select_get( CFF_FDSelect fdselect, - FT_UInt glyph_index ); - - -FT_END_HEADER - -#endif /* __CFFLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffobjs.c b/third_party/freetype/src/cff/cffobjs.c deleted file mode 100644 index 0e0d5b034b6cc594aed1367584cb2c9f75cba494..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffobjs.c +++ /dev/null @@ -1,1077 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffobjs.c */ -/* */ -/* OpenType objects manager (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> - -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_STREAM_H -#include FT_ERRORS_H -#include FT_TRUETYPE_IDS_H -#include FT_TRUETYPE_TAGS_H -#include FT_INTERNAL_SFNT_H -#include FT_CFF_DRIVER_H - -#include "cffobjs.h" -#include "cffload.h" -#include "cffcmap.h" -#include "cffpic.h" - -#include "cfferrs.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cffobjs - - - /*************************************************************************/ - /* */ - /* SIZE FUNCTIONS */ - /* */ - /* Note that we store the global hints in the size's `internal' root */ - /* field. */ - /* */ - /*************************************************************************/ - - - static PSH_Globals_Funcs - cff_size_get_globals_funcs( CFF_Size size ) - { - CFF_Face face = (CFF_Face)size->root.face; - CFF_Font font = (CFF_Font)face->extra.data; - PSHinter_Service pshinter = font->pshinter; - FT_Module module; - - - module = FT_Get_Module( size->root.face->driver->root.library, - "pshinter" ); - return ( module && pshinter && pshinter->get_globals_funcs ) - ? pshinter->get_globals_funcs( module ) - : 0; - } - - - FT_LOCAL_DEF( void ) - cff_size_done( FT_Size cffsize ) /* CFF_Size */ - { - CFF_Size size = (CFF_Size)cffsize; - CFF_Face face = (CFF_Face)size->root.face; - CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = (CFF_Internal)cffsize->internal; - - - if ( internal ) - { - PSH_Globals_Funcs funcs; - - - funcs = cff_size_get_globals_funcs( size ); - if ( funcs ) - { - FT_UInt i; - - - funcs->destroy( internal->topfont ); - - for ( i = font->num_subfonts; i > 0; i-- ) - funcs->destroy( internal->subfonts[i - 1] ); - } - - /* `internal' is freed by destroy_size (in ftobjs.c) */ - } - } - - - /* CFF and Type 1 private dictionaries have slightly different */ - /* structures; we need to synthesize a Type 1 dictionary on the fly */ - - static void - cff_make_private_dict( CFF_SubFont subfont, - PS_Private priv ) - { - CFF_Private cpriv = &subfont->private_dict; - FT_UInt n, count; - - - FT_MEM_ZERO( priv, sizeof ( *priv ) ); - - count = priv->num_blue_values = cpriv->num_blue_values; - for ( n = 0; n < count; n++ ) - priv->blue_values[n] = (FT_Short)cpriv->blue_values[n]; - - count = priv->num_other_blues = cpriv->num_other_blues; - for ( n = 0; n < count; n++ ) - priv->other_blues[n] = (FT_Short)cpriv->other_blues[n]; - - count = priv->num_family_blues = cpriv->num_family_blues; - for ( n = 0; n < count; n++ ) - priv->family_blues[n] = (FT_Short)cpriv->family_blues[n]; - - count = priv->num_family_other_blues = cpriv->num_family_other_blues; - for ( n = 0; n < count; n++ ) - priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; - - priv->blue_scale = cpriv->blue_scale; - priv->blue_shift = (FT_Int)cpriv->blue_shift; - priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz; - - priv->standard_width[0] = (FT_UShort)cpriv->standard_width; - priv->standard_height[0] = (FT_UShort)cpriv->standard_height; - - count = priv->num_snap_widths = cpriv->num_snap_widths; - for ( n = 0; n < count; n++ ) - priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; - - count = priv->num_snap_heights = cpriv->num_snap_heights; - for ( n = 0; n < count; n++ ) - priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; - - priv->force_bold = cpriv->force_bold; - priv->language_group = cpriv->language_group; - priv->lenIV = cpriv->lenIV; - } - - - FT_LOCAL_DEF( FT_Error ) - cff_size_init( FT_Size cffsize ) /* CFF_Size */ - { - CFF_Size size = (CFF_Size)cffsize; - FT_Error error = FT_Err_Ok; - PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); - - - if ( funcs ) - { - CFF_Face face = (CFF_Face)cffsize->face; - CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = NULL; - - PS_PrivateRec priv; - FT_Memory memory = cffsize->face->memory; - - FT_UInt i; - - - if ( FT_NEW( internal ) ) - goto Exit; - - cff_make_private_dict( &font->top_font, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->topfont ); - if ( error ) - goto Exit; - - for ( i = font->num_subfonts; i > 0; i-- ) - { - CFF_SubFont sub = font->subfonts[i - 1]; - - - cff_make_private_dict( sub, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->subfonts[i - 1] ); - if ( error ) - goto Exit; - } - - cffsize->internal = (FT_Size_Internal)(void*)internal; - } - - size->strike_index = 0xFFFFFFFFUL; - - Exit: - return error; - } - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - FT_LOCAL_DEF( FT_Error ) - cff_size_select( FT_Size size, - FT_ULong strike_index ) - { - CFF_Size cffsize = (CFF_Size)size; - PSH_Globals_Funcs funcs; - - - cffsize->strike_index = strike_index; - - FT_Select_Metrics( size->face, strike_index ); - - funcs = cff_size_get_globals_funcs( cffsize ); - - if ( funcs ) - { - CFF_Face face = (CFF_Face)size->face; - CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = (CFF_Internal)size->internal; - - FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; - FT_UInt i; - - - funcs->set_scale( internal->topfont, - size->metrics.x_scale, size->metrics.y_scale, - 0, 0 ); - - for ( i = font->num_subfonts; i > 0; i-- ) - { - CFF_SubFont sub = font->subfonts[i - 1]; - FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em; - FT_Pos x_scale, y_scale; - - - if ( top_upm != sub_upm ) - { - x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); - y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); - } - else - { - x_scale = size->metrics.x_scale; - y_scale = size->metrics.y_scale; - } - - funcs->set_scale( internal->subfonts[i - 1], - x_scale, y_scale, 0, 0 ); - } - } - - return FT_Err_Ok; - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - - FT_LOCAL_DEF( FT_Error ) - cff_size_request( FT_Size size, - FT_Size_Request req ) - { - CFF_Size cffsize = (CFF_Size)size; - PSH_Globals_Funcs funcs; - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - if ( FT_HAS_FIXED_SIZES( size->face ) ) - { - CFF_Face cffface = (CFF_Face)size->face; - SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; - FT_ULong strike_index; - - - if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) ) - cffsize->strike_index = 0xFFFFFFFFUL; - else - return cff_size_select( size, strike_index ); - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - FT_Request_Metrics( size->face, req ); - - funcs = cff_size_get_globals_funcs( cffsize ); - - if ( funcs ) - { - CFF_Face cffface = (CFF_Face)size->face; - CFF_Font font = (CFF_Font)cffface->extra.data; - CFF_Internal internal = (CFF_Internal)size->internal; - - FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; - FT_UInt i; - - - funcs->set_scale( internal->topfont, - size->metrics.x_scale, size->metrics.y_scale, - 0, 0 ); - - for ( i = font->num_subfonts; i > 0; i-- ) - { - CFF_SubFont sub = font->subfonts[i - 1]; - FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em; - FT_Pos x_scale, y_scale; - - - if ( top_upm != sub_upm ) - { - x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); - y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); - } - else - { - x_scale = size->metrics.x_scale; - y_scale = size->metrics.y_scale; - } - - funcs->set_scale( internal->subfonts[i - 1], - x_scale, y_scale, 0, 0 ); - } - } - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* SLOT FUNCTIONS */ - /* */ - /*************************************************************************/ - - FT_LOCAL_DEF( void ) - cff_slot_done( FT_GlyphSlot slot ) - { - slot->internal->glyph_hints = NULL; - } - - - FT_LOCAL_DEF( FT_Error ) - cff_slot_init( FT_GlyphSlot slot ) - { - CFF_Face face = (CFF_Face)slot->face; - CFF_Font font = (CFF_Font)face->extra.data; - PSHinter_Service pshinter = font->pshinter; - - - if ( pshinter ) - { - FT_Module module; - - - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); - if ( module ) - { - T2_Hints_Funcs funcs; - - - funcs = pshinter->get_t2_funcs( module ); - slot->internal->glyph_hints = (void*)funcs; - } - } - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* FACE FUNCTIONS */ - /* */ - /*************************************************************************/ - - static FT_String* - cff_strcpy( FT_Memory memory, - const FT_String* source ) - { - FT_Error error; - FT_String* result; - - - (void)FT_STRDUP( result, source ); - - FT_UNUSED( error ); - - return result; - } - - - /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */ - /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */ - /* have been seen in the wild. */ - - static void - remove_subset_prefix( FT_String* name ) - { - FT_Int32 idx = 0; - FT_Int32 length = (FT_Int32)strlen( name ) + 1; - FT_Bool continue_search = 1; - - - while ( continue_search ) - { - if ( length >= 7 && name[6] == '+' ) - { - for ( idx = 0; idx < 6; idx++ ) - { - /* ASCII uppercase letters */ - if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) ) - continue_search = 0; - } - - if ( continue_search ) - { - for ( idx = 7; idx < length; idx++ ) - name[idx - 7] = name[idx]; - length -= 7; - } - } - else - continue_search = 0; - } - } - - - /* Remove the style part from the family name (if present). */ - - static void - remove_style( FT_String* family_name, - const FT_String* style_name ) - { - FT_Int32 family_name_length, style_name_length; - - - family_name_length = (FT_Int32)strlen( family_name ); - style_name_length = (FT_Int32)strlen( style_name ); - - if ( family_name_length > style_name_length ) - { - FT_Int idx; - - - for ( idx = 1; idx <= style_name_length; ++idx ) - { - if ( family_name[family_name_length - idx] != - style_name[style_name_length - idx] ) - break; - } - - if ( idx > style_name_length ) - { - /* family_name ends with style_name; remove it */ - idx = family_name_length - style_name_length - 1; - - /* also remove special characters */ - /* between real family name and style */ - while ( idx > 0 && - ( family_name[idx] == '-' || - family_name[idx] == ' ' || - family_name[idx] == '_' || - family_name[idx] == '+' ) ) - --idx; - - if ( idx > 0 ) - family_name[idx + 1] = '\0'; - } - } - } - - - FT_LOCAL_DEF( FT_Error ) - cff_face_init( FT_Stream stream, - FT_Face cffface, /* CFF_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ) - { - CFF_Face face = (CFF_Face)cffface; - FT_Error error; - SFNT_Service sfnt; - FT_Service_PsCMaps psnames; - PSHinter_Service pshinter; - FT_Bool pure_cff = 1; - FT_Bool sfnt_format = 0; - FT_Library library = cffface->driver->root.library; - - - sfnt = (SFNT_Service)FT_Get_Module_Interface( - library, "sfnt" ); - if ( !sfnt ) - { - FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" )); - error = FT_THROW( Missing_Module ); - goto Exit; - } - - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); - - pshinter = (PSHinter_Service)FT_Get_Module_Interface( - library, "pshinter" ); - - FT_TRACE2(( "CFF driver\n" )); - - /* create input stream from resource */ - if ( FT_STREAM_SEEK( 0 ) ) - goto Exit; - - /* check whether we have a valid OpenType file */ - error = sfnt->init_face( stream, face, face_index, num_params, params ); - if ( !error ) - { - if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ - { - FT_TRACE2(( " not an OpenType/CFF font\n" )); - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - /* if we are performing a simple font format check, exit immediately */ - if ( face_index < 0 ) - return FT_Err_Ok; - - sfnt_format = 1; - - /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ - /* font; in the latter case it doesn't have a `head' table */ - error = face->goto_table( face, TTAG_head, stream, 0 ); - if ( !error ) - { - pure_cff = 0; - - /* load font directory */ - error = sfnt->load_face( stream, face, face_index, - num_params, params ); - if ( error ) - goto Exit; - } - else - { - /* load the `cmap' table explicitly */ - error = sfnt->load_cmap( face, stream ); - if ( error ) - goto Exit; - } - - /* now load the CFF part of the file */ - error = face->goto_table( face, TTAG_CFF, stream, 0 ); - if ( error ) - goto Exit; - } - else - { - /* rewind to start of file; we are going to load a pure-CFF font */ - if ( FT_STREAM_SEEK( 0 ) ) - goto Exit; - error = FT_Err_Ok; - } - - /* now load and parse the CFF table in the file */ - { - CFF_Font cff = NULL; - CFF_FontRecDict dict; - FT_Memory memory = cffface->memory; - FT_Int32 flags; - FT_UInt i; - - - if ( FT_NEW( cff ) ) - goto Exit; - - face->extra.data = cff; - error = cff_font_load( library, stream, face_index, cff, pure_cff ); - if ( error ) - goto Exit; - - /* if we are performing a simple font format check, exit immediately */ - /* (this is here for pure CFF) */ - if ( face_index < 0 ) - return FT_Err_Ok; - - cff->pshinter = pshinter; - cff->psnames = psnames; - - cffface->face_index = face_index & 0xFFFF; - - /* Complement the root flags with some interesting information. */ - /* Note that this is only necessary for pure CFF and CEF fonts; */ - /* SFNT based fonts use the `name' table instead. */ - - cffface->num_glyphs = (FT_Long)cff->num_glyphs; - - dict = &cff->top_font.font_dict; - - /* we need the `PSNames' module for CFF and CEF formats */ - /* which aren't CID-keyed */ - if ( dict->cid_registry == 0xFFFFU && !psnames ) - { - FT_ERROR(( "cff_face_init:" - " cannot open CFF & CEF fonts\n" - " " - " without the `PSNames' module\n" )); - error = FT_THROW( Missing_Module ); - goto Exit; - } - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_UInt idx; - FT_String* s; - - - FT_TRACE4(( "SIDs\n" )); - - /* dump string index, including default strings for convenience */ - for ( idx = 0; idx < cff->num_strings + 390; idx++ ) - { - s = cff_index_get_sid_string( cff, idx ); - if ( s ) - FT_TRACE4((" %5d %s\n", idx, s )); - } - } -#endif /* FT_DEBUG_LEVEL_TRACE */ - - if ( !dict->has_font_matrix ) - dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; - - /* Normalize the font matrix so that `matrix->yy' is 1; the */ - /* scaling is done with `units_per_em' then (at this point, */ - /* it already contains the scaling factor, but without */ - /* normalization of the matrix). */ - /* */ - /* Note that the offsets must be expressed in integer font */ - /* units. */ - - { - FT_Matrix* matrix = &dict->font_matrix; - FT_Vector* offset = &dict->font_offset; - FT_ULong* upm = &dict->units_per_em; - FT_Fixed temp = FT_ABS( matrix->yy ); - - - if ( temp != 0x10000L ) - { - *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp ); - - matrix->xx = FT_DivFix( matrix->xx, temp ); - matrix->yx = FT_DivFix( matrix->yx, temp ); - matrix->xy = FT_DivFix( matrix->xy, temp ); - matrix->yy = FT_DivFix( matrix->yy, temp ); - offset->x = FT_DivFix( offset->x, temp ); - offset->y = FT_DivFix( offset->y, temp ); - } - - offset->x >>= 16; - offset->y >>= 16; - } - - for ( i = cff->num_subfonts; i > 0; i-- ) - { - CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; - CFF_FontRecDict top = &cff->top_font.font_dict; - - FT_Matrix* matrix; - FT_Vector* offset; - FT_ULong* upm; - FT_Fixed temp; - - - if ( sub->has_font_matrix ) - { - FT_Long scaling; - - - /* if we have a top-level matrix, */ - /* concatenate the subfont matrix */ - - if ( top->has_font_matrix ) - { - if ( top->units_per_em > 1 && sub->units_per_em > 1 ) - scaling = (FT_Long)FT_MIN( top->units_per_em, - sub->units_per_em ); - else - scaling = 1; - - FT_Matrix_Multiply_Scaled( &top->font_matrix, - &sub->font_matrix, - scaling ); - FT_Vector_Transform_Scaled( &sub->font_offset, - &top->font_matrix, - scaling ); - - sub->units_per_em = (FT_ULong) - FT_MulDiv( (FT_Long)sub->units_per_em, - (FT_Long)top->units_per_em, - scaling ); - } - } - else - { - sub->font_matrix = top->font_matrix; - sub->font_offset = top->font_offset; - - sub->units_per_em = top->units_per_em; - } - - matrix = &sub->font_matrix; - offset = &sub->font_offset; - upm = &sub->units_per_em; - temp = FT_ABS( matrix->yy ); - - if ( temp != 0x10000L ) - { - *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp ); - - matrix->xx = FT_DivFix( matrix->xx, temp ); - matrix->yx = FT_DivFix( matrix->yx, temp ); - matrix->xy = FT_DivFix( matrix->xy, temp ); - matrix->yy = FT_DivFix( matrix->yy, temp ); - offset->x = FT_DivFix( offset->x, temp ); - offset->y = FT_DivFix( offset->y, temp ); - } - - offset->x >>= 16; - offset->y >>= 16; - } - - if ( pure_cff ) - { - char* style_name = NULL; - - - /* set up num_faces */ - cffface->num_faces = (FT_Long)cff->num_faces; - - /* compute number of glyphs */ - if ( dict->cid_registry != 0xFFFFU ) - cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 ); - else - cffface->num_glyphs = (FT_Long)cff->charstrings_index.count; - - /* set global bbox, as well as EM size */ - cffface->bbox.xMin = dict->font_bbox.xMin >> 16; - cffface->bbox.yMin = dict->font_bbox.yMin >> 16; - /* no `U' suffix here to 0xFFFF! */ - cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16; - cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16; - - cffface->units_per_EM = (FT_UShort)( dict->units_per_em ); - - cffface->ascender = (FT_Short)( cffface->bbox.yMax ); - cffface->descender = (FT_Short)( cffface->bbox.yMin ); - - cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); - if ( cffface->height < cffface->ascender - cffface->descender ) - cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); - - cffface->underline_position = - (FT_Short)( dict->underline_position >> 16 ); - cffface->underline_thickness = - (FT_Short)( dict->underline_thickness >> 16 ); - - /* retrieve font family & style name */ - cffface->family_name = cff_index_get_name( - cff, - (FT_UInt)( face_index & 0xFFFF ) ); - if ( cffface->family_name ) - { - char* full = cff_index_get_sid_string( cff, - dict->full_name ); - char* fullp = full; - char* family = cffface->family_name; - char* family_name = NULL; - - - remove_subset_prefix( cffface->family_name ); - - if ( dict->family_name ) - { - family_name = cff_index_get_sid_string( cff, - dict->family_name ); - if ( family_name ) - family = family_name; - } - - /* We try to extract the style name from the full name. */ - /* We need to ignore spaces and dashes during the search. */ - if ( full && family ) - { - while ( *fullp ) - { - /* skip common characters at the start of both strings */ - if ( *fullp == *family ) - { - family++; - fullp++; - continue; - } - - /* ignore spaces and dashes in full name during comparison */ - if ( *fullp == ' ' || *fullp == '-' ) - { - fullp++; - continue; - } - - /* ignore spaces and dashes in family name during comparison */ - if ( *family == ' ' || *family == '-' ) - { - family++; - continue; - } - - if ( !*family && *fullp ) - { - /* The full name begins with the same characters as the */ - /* family name, with spaces and dashes removed. In this */ - /* case, the remaining string in `fullp' will be used as */ - /* the style name. */ - style_name = cff_strcpy( memory, fullp ); - - /* remove the style part from the family name (if present) */ - remove_style( cffface->family_name, style_name ); - } - break; - } - } - } - else - { - char *cid_font_name = - cff_index_get_sid_string( cff, - dict->cid_font_name ); - - - /* do we have a `/FontName' for a CID-keyed font? */ - if ( cid_font_name ) - cffface->family_name = cff_strcpy( memory, cid_font_name ); - } - - if ( style_name ) - cffface->style_name = style_name; - else - /* assume "Regular" style if we don't know better */ - cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); - - /*******************************************************************/ - /* */ - /* Compute face flags. */ - /* */ - flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ - FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ - FT_FACE_FLAG_HINTER; /* has native hinter */ - - if ( sfnt_format ) - flags |= FT_FACE_FLAG_SFNT; - - /* fixed width font? */ - if ( dict->is_fixed_pitch ) - flags |= FT_FACE_FLAG_FIXED_WIDTH; - - /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ -#if 0 - /* kerning available? */ - if ( face->kern_pairs ) - flags |= FT_FACE_FLAG_KERNING; -#endif - - cffface->face_flags |= flags; - - /*******************************************************************/ - /* */ - /* Compute style flags. */ - /* */ - flags = 0; - - if ( dict->italic_angle ) - flags |= FT_STYLE_FLAG_ITALIC; - - { - char *weight = cff_index_get_sid_string( cff, - dict->weight ); - - - if ( weight ) - if ( !ft_strcmp( weight, "Bold" ) || - !ft_strcmp( weight, "Black" ) ) - flags |= FT_STYLE_FLAG_BOLD; - } - - /* double check */ - if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) - if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || - !ft_strncmp( cffface->style_name, "Black", 5 ) ) - flags |= FT_STYLE_FLAG_BOLD; - - cffface->style_flags = flags; - } - - -#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES - /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ - /* has unset this flag because of the 3.0 `post' table. */ - if ( dict->cid_registry == 0xFFFFU ) - cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; -#endif - - if ( dict->cid_registry != 0xFFFFU && pure_cff ) - cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; - - - /*******************************************************************/ - /* */ - /* Compute char maps. */ - /* */ - - /* Try to synthesize a Unicode charmap if there is none available */ - /* already. If an OpenType font contains a Unicode "cmap", we */ - /* will use it, whatever be in the CFF part of the file. */ - { - FT_CharMapRec cmaprec; - FT_CharMap cmap; - FT_UInt nn; - CFF_Encoding encoding = &cff->encoding; - - - for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) - { - cmap = cffface->charmaps[nn]; - - /* Windows Unicode? */ - if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && - cmap->encoding_id == TT_MS_ID_UNICODE_CS ) - goto Skip_Unicode; - - /* Apple Unicode platform id? */ - if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) - goto Skip_Unicode; /* Apple Unicode */ - } - - /* since CID-keyed fonts don't contain glyph names, we can't */ - /* construct a cmap */ - if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) - goto Exit; - - /* we didn't find a Unicode charmap -- synthesize one */ - cmaprec.face = cffface; - cmaprec.platform_id = TT_PLATFORM_MICROSOFT; - cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; - cmaprec.encoding = FT_ENCODING_UNICODE; - - nn = (FT_UInt)cffface->num_charmaps; - - error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, - &cmaprec, NULL ); - if ( error && - FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) - goto Exit; - error = FT_Err_Ok; - - /* if no Unicode charmap was previously selected, select this one */ - if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) - cffface->charmap = cffface->charmaps[nn]; - - Skip_Unicode: - if ( encoding->count > 0 ) - { - FT_CMap_Class clazz; - - - cmaprec.face = cffface; - cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ - - if ( encoding->offset == 0 ) - { - cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; - cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; - clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; - } - else if ( encoding->offset == 1 ) - { - cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; - cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; - clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; - } - else - { - cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; - cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; - clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; - } - - error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); - } - } - } - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - cff_face_done( FT_Face cffface ) /* CFF_Face */ - { - CFF_Face face = (CFF_Face)cffface; - FT_Memory memory; - SFNT_Service sfnt; - - - if ( !face ) - return; - - memory = cffface->memory; - sfnt = (SFNT_Service)face->sfnt; - - if ( sfnt ) - sfnt->done_face( face ); - - { - CFF_Font cff = (CFF_Font)face->extra.data; - - - if ( cff ) - { - cff_font_done( cff ); - FT_FREE( face->extra.data ); - } - } - } - - - FT_LOCAL_DEF( FT_Error ) - cff_driver_init( FT_Module module ) /* CFF_Driver */ - { - CFF_Driver driver = (CFF_Driver)module; - - - /* set default property values, cf. `ftcffdrv.h' */ -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - driver->hinting_engine = FT_CFF_HINTING_FREETYPE; -#else - driver->hinting_engine = FT_CFF_HINTING_ADOBE; -#endif - - driver->no_stem_darkening = FALSE; - - driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; - driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; - driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; - driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; - driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; - driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; - driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; - driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; - - return FT_Err_Ok; - } - - - FT_LOCAL_DEF( void ) - cff_driver_done( FT_Module module ) /* CFF_Driver */ - { - FT_UNUSED( module ); - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cffobjs.h b/third_party/freetype/src/cff/cffobjs.h deleted file mode 100644 index 3cc953143b6b5b2a860c3ae6980693a722964657..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffobjs.h +++ /dev/null @@ -1,185 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffobjs.h */ -/* */ -/* OpenType objects manager (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFOBJS_H__ -#define __CFFOBJS_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include "cfftypes.h" -#include FT_INTERNAL_TRUETYPE_TYPES_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_Driver */ - /* */ - /* <Description> */ - /* A handle to an OpenType driver object. */ - /* */ - typedef struct CFF_DriverRec_* CFF_Driver; - - typedef TT_Face CFF_Face; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_Size */ - /* */ - /* <Description> */ - /* A handle to an OpenType size object. */ - /* */ - typedef struct CFF_SizeRec_ - { - FT_SizeRec root; - FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ - - } CFF_SizeRec, *CFF_Size; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_GlyphSlot */ - /* */ - /* <Description> */ - /* A handle to an OpenType glyph slot object. */ - /* */ - typedef struct CFF_GlyphSlotRec_ - { - FT_GlyphSlotRec root; - - FT_Bool hint; - FT_Bool scaled; - - FT_Fixed x_scale; - FT_Fixed y_scale; - - } CFF_GlyphSlotRec, *CFF_GlyphSlot; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_Internal */ - /* */ - /* <Description> */ - /* The interface to the `internal' field of `FT_Size'. */ - /* */ - typedef struct CFF_InternalRec_ - { - PSH_Globals topfont; - PSH_Globals subfonts[CFF_MAX_CID_FONTS]; - - } CFF_InternalRec, *CFF_Internal; - - - /*************************************************************************/ - /* */ - /* Subglyph transformation record. */ - /* */ - typedef struct CFF_Transform_ - { - FT_Fixed xx, xy; /* transformation matrix coefficients */ - FT_Fixed yx, yy; - FT_F26Dot6 ox, oy; /* offsets */ - - } CFF_Transform; - - - /***********************************************************************/ - /* */ - /* CFF driver class. */ - /* */ - typedef struct CFF_DriverRec_ - { - FT_DriverRec root; - - FT_UInt hinting_engine; - FT_Bool no_stem_darkening; - - FT_Int darken_params[8]; - - } CFF_DriverRec; - - - FT_LOCAL( FT_Error ) - cff_size_init( FT_Size size ); /* CFF_Size */ - - FT_LOCAL( void ) - cff_size_done( FT_Size size ); /* CFF_Size */ - - FT_LOCAL( FT_Error ) - cff_size_request( FT_Size size, - FT_Size_Request req ); - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - FT_LOCAL( FT_Error ) - cff_size_select( FT_Size size, - FT_ULong strike_index ); - -#endif - - FT_LOCAL( void ) - cff_slot_done( FT_GlyphSlot slot ); - - FT_LOCAL( FT_Error ) - cff_slot_init( FT_GlyphSlot slot ); - - - /*************************************************************************/ - /* */ - /* Face functions */ - /* */ - FT_LOCAL( FT_Error ) - cff_face_init( FT_Stream stream, - FT_Face face, /* CFF_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ); - - FT_LOCAL( void ) - cff_face_done( FT_Face face ); /* CFF_Face */ - - - /*************************************************************************/ - /* */ - /* Driver functions */ - /* */ - FT_LOCAL( FT_Error ) - cff_driver_init( FT_Module module ); /* CFF_Driver */ - - FT_LOCAL( void ) - cff_driver_done( FT_Module module ); /* CFF_Driver */ - - -FT_END_HEADER - -#endif /* __CFFOBJS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffparse.c b/third_party/freetype/src/cff/cffparse.c deleted file mode 100644 index 063b3517c534c4e0baf1d51bff3902936ff9f8ea..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffparse.c +++ /dev/null @@ -1,1193 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffparse.c */ -/* */ -/* CFF token stream parser (body) */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "cffparse.h" -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_DEBUG_H - -#include "cfferrs.h" -#include "cffpic.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cffparse - - - FT_LOCAL_DEF( void ) - cff_parser_init( CFF_Parser parser, - FT_UInt code, - void* object, - FT_Library library) - { - FT_MEM_ZERO( parser, sizeof ( *parser ) ); - - parser->top = parser->stack; - parser->object_code = code; - parser->object = object; - parser->library = library; - } - - - /* read an integer */ - static FT_Long - cff_parse_integer( FT_Byte* start, - FT_Byte* limit ) - { - FT_Byte* p = start; - FT_Int v = *p++; - FT_Long val = 0; - - - if ( v == 28 ) - { - if ( p + 2 > limit ) - goto Bad; - - val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] ); - } - else if ( v == 29 ) - { - if ( p + 4 > limit ) - goto Bad; - - val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) | - ( (FT_ULong)p[1] << 16 ) | - ( (FT_ULong)p[2] << 8 ) | - (FT_ULong)p[3] ); - } - else if ( v < 247 ) - { - val = v - 139; - } - else if ( v < 251 ) - { - if ( p + 1 > limit ) - goto Bad; - - val = ( v - 247 ) * 256 + p[0] + 108; - } - else - { - if ( p + 1 > limit ) - goto Bad; - - val = -( v - 251 ) * 256 - p[0] - 108; - } - - Exit: - return val; - - Bad: - val = 0; - FT_TRACE4(( "!!!END OF DATA:!!!" )); - goto Exit; - } - - - static const FT_Long power_tens[] = - { - 1L, - 10L, - 100L, - 1000L, - 10000L, - 100000L, - 1000000L, - 10000000L, - 100000000L, - 1000000000L - }; - - - /* read a real */ - static FT_Fixed - cff_parse_real( FT_Byte* start, - FT_Byte* limit, - FT_Long power_ten, - FT_Long* scaling ) - { - FT_Byte* p = start; - FT_Int nib; - FT_UInt phase; - - FT_Long result, number, exponent; - FT_Int sign = 0, exponent_sign = 0, have_overflow = 0; - FT_Long exponent_add, integer_length, fraction_length; - - - if ( scaling ) - *scaling = 0; - - result = 0; - - number = 0; - exponent = 0; - - exponent_add = 0; - integer_length = 0; - fraction_length = 0; - - /* First of all, read the integer part. */ - phase = 4; - - for (;;) - { - /* If we entered this iteration with phase == 4, we need to */ - /* read a new byte. This also skips past the initial 0x1E. */ - if ( phase ) - { - p++; - - /* Make sure we don't read past the end. */ - if ( p >= limit ) - goto Bad; - } - - /* Get the nibble. */ - nib = (FT_Int)( p[0] >> phase ) & 0xF; - phase = 4 - phase; - - if ( nib == 0xE ) - sign = 1; - else if ( nib > 9 ) - break; - else - { - /* Increase exponent if we can't add the digit. */ - if ( number >= 0xCCCCCCCL ) - exponent_add++; - /* Skip leading zeros. */ - else if ( nib || number ) - { - integer_length++; - number = number * 10 + nib; - } - } - } - - /* Read fraction part, if any. */ - if ( nib == 0xA ) - for (;;) - { - /* If we entered this iteration with phase == 4, we need */ - /* to read a new byte. */ - if ( phase ) - { - p++; - - /* Make sure we don't read past the end. */ - if ( p >= limit ) - goto Bad; - } - - /* Get the nibble. */ - nib = ( p[0] >> phase ) & 0xF; - phase = 4 - phase; - if ( nib >= 10 ) - break; - - /* Skip leading zeros if possible. */ - if ( !nib && !number ) - exponent_add--; - /* Only add digit if we don't overflow. */ - else if ( number < 0xCCCCCCCL && fraction_length < 9 ) - { - fraction_length++; - number = number * 10 + nib; - } - } - - /* Read exponent, if any. */ - if ( nib == 12 ) - { - exponent_sign = 1; - nib = 11; - } - - if ( nib == 11 ) - { - for (;;) - { - /* If we entered this iteration with phase == 4, */ - /* we need to read a new byte. */ - if ( phase ) - { - p++; - - /* Make sure we don't read past the end. */ - if ( p >= limit ) - goto Bad; - } - - /* Get the nibble. */ - nib = ( p[0] >> phase ) & 0xF; - phase = 4 - phase; - if ( nib >= 10 ) - break; - - /* Arbitrarily limit exponent. */ - if ( exponent > 1000 ) - have_overflow = 1; - else - exponent = exponent * 10 + nib; - } - - if ( exponent_sign ) - exponent = -exponent; - } - - if ( !number ) - goto Exit; - - if ( have_overflow ) - { - if ( exponent_sign ) - goto Underflow; - else - goto Overflow; - } - - /* We don't check `power_ten' and `exponent_add'. */ - exponent += power_ten + exponent_add; - - if ( scaling ) - { - /* Only use `fraction_length'. */ - fraction_length += integer_length; - exponent += integer_length; - - if ( fraction_length <= 5 ) - { - if ( number > 0x7FFFL ) - { - result = FT_DivFix( number, 10 ); - *scaling = exponent - fraction_length + 1; - } - else - { - if ( exponent > 0 ) - { - FT_Long new_fraction_length, shift; - - - /* Make `scaling' as small as possible. */ - new_fraction_length = FT_MIN( exponent, 5 ); - shift = new_fraction_length - fraction_length; - - if ( shift > 0 ) - { - exponent -= new_fraction_length; - number *= power_tens[shift]; - if ( number > 0x7FFFL ) - { - number /= 10; - exponent += 1; - } - } - else - exponent -= fraction_length; - } - else - exponent -= fraction_length; - - result = (FT_Long)( (FT_ULong)number << 16 ); - *scaling = exponent; - } - } - else - { - if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL ) - { - result = FT_DivFix( number, power_tens[fraction_length - 4] ); - *scaling = exponent - 4; - } - else - { - result = FT_DivFix( number, power_tens[fraction_length - 5] ); - *scaling = exponent - 5; - } - } - } - else - { - integer_length += exponent; - fraction_length -= exponent; - - if ( integer_length > 5 ) - goto Overflow; - if ( integer_length < -5 ) - goto Underflow; - - /* Remove non-significant digits. */ - if ( integer_length < 0 ) - { - number /= power_tens[-integer_length]; - fraction_length += integer_length; - } - - /* this can only happen if exponent was non-zero */ - if ( fraction_length == 10 ) - { - number /= 10; - fraction_length -= 1; - } - - /* Convert into 16.16 format. */ - if ( fraction_length > 0 ) - { - if ( ( number / power_tens[fraction_length] ) > 0x7FFFL ) - goto Exit; - - result = FT_DivFix( number, power_tens[fraction_length] ); - } - else - { - number *= power_tens[-fraction_length]; - - if ( number > 0x7FFFL ) - goto Overflow; - - result = (FT_Long)( (FT_ULong)number << 16 ); - } - } - - Exit: - if ( sign ) - result = -result; - - return result; - - Overflow: - result = 0x7FFFFFFFL; - FT_TRACE4(( "!!!OVERFLOW:!!!" )); - goto Exit; - - Underflow: - result = 0; - FT_TRACE4(( "!!!UNDERFLOW:!!!" )); - goto Exit; - - Bad: - result = 0; - FT_TRACE4(( "!!!END OF DATA:!!!" )); - goto Exit; - } - - - /* read a number, either integer or real */ - static FT_Long - cff_parse_num( FT_Byte** d ) - { - return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 ) - : cff_parse_integer( d[0], d[1] ); - } - - - /* read a floating point number, either integer or real */ - static FT_Fixed - do_fixed( FT_Byte** d, - FT_Long scaling ) - { - if ( **d == 30 ) - return cff_parse_real( d[0], d[1], scaling, NULL ); - else - { - FT_Long val = cff_parse_integer( d[0], d[1] ); - - - if ( scaling ) - val *= power_tens[scaling]; - - if ( val > 0x7FFF ) - { - val = 0x7FFFFFFFL; - goto Overflow; - } - else if ( val < -0x7FFF ) - { - val = -0x7FFFFFFFL; - goto Overflow; - } - - return (FT_Long)( (FT_ULong)val << 16 ); - - Overflow: - FT_TRACE4(( "!!!OVERFLOW:!!!" )); - return val; - } - } - - - /* read a floating point number, either integer or real */ - static FT_Fixed - cff_parse_fixed( FT_Byte** d ) - { - return do_fixed( d, 0 ); - } - - - /* read a floating point number, either integer or real, */ - /* but return `10^scaling' times the number read in */ - static FT_Fixed - cff_parse_fixed_scaled( FT_Byte** d, - FT_Long scaling ) - { - return do_fixed( d, scaling ); - } - - - /* read a floating point number, either integer or real, */ - /* and return it as precise as possible -- `scaling' returns */ - /* the scaling factor (as a power of 10) */ - static FT_Fixed - cff_parse_fixed_dynamic( FT_Byte** d, - FT_Long* scaling ) - { - FT_ASSERT( scaling ); - - if ( **d == 30 ) - return cff_parse_real( d[0], d[1], 0, scaling ); - else - { - FT_Long number; - FT_Int integer_length; - - - number = cff_parse_integer( d[0], d[1] ); - - if ( number > 0x7FFFL ) - { - for ( integer_length = 5; integer_length < 10; integer_length++ ) - if ( number < power_tens[integer_length] ) - break; - - if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL ) - { - *scaling = integer_length - 4; - return FT_DivFix( number, power_tens[integer_length - 4] ); - } - else - { - *scaling = integer_length - 5; - return FT_DivFix( number, power_tens[integer_length - 5] ); - } - } - else - { - *scaling = 0; - return (FT_Long)( (FT_ULong)number << 16 ); - } - } - } - - - static FT_Error - cff_parse_font_matrix( CFF_Parser parser ) - { - CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; - FT_Matrix* matrix = &dict->font_matrix; - FT_Vector* offset = &dict->font_offset; - FT_ULong* upm = &dict->units_per_em; - FT_Byte** data = parser->stack; - FT_Error error = FT_ERR( Stack_Underflow ); - - - if ( parser->top >= parser->stack + 6 ) - { - FT_Long scaling; - - - error = FT_Err_Ok; - - dict->has_font_matrix = TRUE; - - /* We expect a well-formed font matrix, this is, the matrix elements */ - /* `xx' and `yy' are of approximately the same magnitude. To avoid */ - /* loss of precision, we use the magnitude of element `xx' to scale */ - /* all other elements. The scaling factor is then contained in the */ - /* `units_per_em' value. */ - - matrix->xx = cff_parse_fixed_dynamic( data++, &scaling ); - - scaling = -scaling; - - if ( scaling < 0 || scaling > 9 ) - { - /* Return default matrix in case of unlikely values. */ - - FT_TRACE1(( "cff_parse_font_matrix:" - " strange scaling value for xx element (%d),\n" - " " - " using default matrix\n", scaling )); - - matrix->xx = 0x10000L; - matrix->yx = 0; - matrix->xy = 0; - matrix->yy = 0x10000L; - offset->x = 0; - offset->y = 0; - *upm = 1; - - goto Exit; - } - - matrix->yx = cff_parse_fixed_scaled( data++, scaling ); - matrix->xy = cff_parse_fixed_scaled( data++, scaling ); - matrix->yy = cff_parse_fixed_scaled( data++, scaling ); - offset->x = cff_parse_fixed_scaled( data++, scaling ); - offset->y = cff_parse_fixed_scaled( data, scaling ); - - *upm = (FT_ULong)power_tens[scaling]; - - FT_TRACE4(( " [%f %f %f %f %f %f]\n", - (double)matrix->xx / *upm / 65536, - (double)matrix->xy / *upm / 65536, - (double)matrix->yx / *upm / 65536, - (double)matrix->yy / *upm / 65536, - (double)offset->x / *upm / 65536, - (double)offset->y / *upm / 65536 )); - } - - Exit: - return error; - } - - - static FT_Error - cff_parse_font_bbox( CFF_Parser parser ) - { - CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; - FT_BBox* bbox = &dict->font_bbox; - FT_Byte** data = parser->stack; - FT_Error error; - - - error = FT_ERR( Stack_Underflow ); - - if ( parser->top >= parser->stack + 4 ) - { - bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) ); - bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) ); - bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) ); - bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) ); - error = FT_Err_Ok; - - FT_TRACE4(( " [%d %d %d %d]\n", - bbox->xMin / 65536, - bbox->yMin / 65536, - bbox->xMax / 65536, - bbox->yMax / 65536 )); - } - - return error; - } - - - static FT_Error - cff_parse_private_dict( CFF_Parser parser ) - { - CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; - FT_Byte** data = parser->stack; - FT_Error error; - - - error = FT_ERR( Stack_Underflow ); - - if ( parser->top >= parser->stack + 2 ) - { - FT_Long tmp; - - - tmp = cff_parse_num( data++ ); - if ( tmp < 0 ) - { - FT_ERROR(( "cff_parse_private_dict: Invalid dictionary size\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - dict->private_size = (FT_ULong)tmp; - - tmp = cff_parse_num( data ); - if ( tmp < 0 ) - { - FT_ERROR(( "cff_parse_private_dict: Invalid dictionary offset\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - dict->private_offset = (FT_ULong)tmp; - - FT_TRACE4(( " %lu %lu\n", - dict->private_size, dict->private_offset )); - - error = FT_Err_Ok; - } - - Fail: - return error; - } - - - static FT_Error - cff_parse_cid_ros( CFF_Parser parser ) - { - CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; - FT_Byte** data = parser->stack; - FT_Error error; - - - error = FT_ERR( Stack_Underflow ); - - if ( parser->top >= parser->stack + 3 ) - { - dict->cid_registry = (FT_UInt)cff_parse_num( data++ ); - dict->cid_ordering = (FT_UInt)cff_parse_num( data++ ); - if ( **data == 30 ) - FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" )); - dict->cid_supplement = cff_parse_num( data ); - if ( dict->cid_supplement < 0 ) - FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n", - dict->cid_supplement )); - error = FT_Err_Ok; - - FT_TRACE4(( " %d %d %d\n", - dict->cid_registry, - dict->cid_ordering, - dict->cid_supplement )); - } - - return error; - } - - -#define CFF_FIELD_NUM( code, name, id ) \ - CFF_FIELD( code, name, id, cff_kind_num ) -#define CFF_FIELD_FIXED( code, name, id ) \ - CFF_FIELD( code, name, id, cff_kind_fixed ) -#define CFF_FIELD_FIXED_1000( code, name, id ) \ - CFF_FIELD( code, name, id, cff_kind_fixed_thousand ) -#define CFF_FIELD_STRING( code, name, id ) \ - CFF_FIELD( code, name, id, cff_kind_string ) -#define CFF_FIELD_BOOL( code, name, id ) \ - CFF_FIELD( code, name, id, cff_kind_bool ) - -#define CFFCODE_TOPDICT 0x1000 -#define CFFCODE_PRIVATE 0x2000 - - -#ifndef FT_CONFIG_OPTION_PIC - - -#undef CFF_FIELD -#undef CFF_FIELD_DELTA - - -#ifndef FT_DEBUG_LEVEL_TRACE - - -#define CFF_FIELD_CALLBACK( code, name, id ) \ - { \ - cff_kind_callback, \ - code | CFFCODE, \ - 0, 0, \ - cff_parse_ ## name, \ - 0, 0 \ - }, - -#define CFF_FIELD( code, name, id, kind ) \ - { \ - kind, \ - code | CFFCODE, \ - FT_FIELD_OFFSET( name ), \ - FT_FIELD_SIZE( name ), \ - 0, 0, 0 \ - }, - -#define CFF_FIELD_DELTA( code, name, max, id ) \ - { \ - cff_kind_delta, \ - code | CFFCODE, \ - FT_FIELD_OFFSET( name ), \ - FT_FIELD_SIZE_DELTA( name ), \ - 0, \ - max, \ - FT_FIELD_OFFSET( num_ ## name ) \ - }, - - static const CFF_Field_Handler cff_field_handlers[] = - { - -#include "cfftoken.h" - - { 0, 0, 0, 0, 0, 0, 0 } - }; - - -#else /* FT_DEBUG_LEVEL_TRACE */ - - - -#define CFF_FIELD_CALLBACK( code, name, id ) \ - { \ - cff_kind_callback, \ - code | CFFCODE, \ - 0, 0, \ - cff_parse_ ## name, \ - 0, 0, \ - id \ - }, - -#define CFF_FIELD( code, name, id, kind ) \ - { \ - kind, \ - code | CFFCODE, \ - FT_FIELD_OFFSET( name ), \ - FT_FIELD_SIZE( name ), \ - 0, 0, 0, \ - id \ - }, - -#define CFF_FIELD_DELTA( code, name, max, id ) \ - { \ - cff_kind_delta, \ - code | CFFCODE, \ - FT_FIELD_OFFSET( name ), \ - FT_FIELD_SIZE_DELTA( name ), \ - 0, \ - max, \ - FT_FIELD_OFFSET( num_ ## name ), \ - id \ - }, - - static const CFF_Field_Handler cff_field_handlers[] = - { - -#include "cfftoken.h" - - { 0, 0, 0, 0, 0, 0, 0, 0 } - }; - - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - -#else /* FT_CONFIG_OPTION_PIC */ - - - void - FT_Destroy_Class_cff_field_handlers( FT_Library library, - CFF_Field_Handler* clazz ) - { - FT_Memory memory = library->memory; - - - if ( clazz ) - FT_FREE( clazz ); - } - - - FT_Error - FT_Create_Class_cff_field_handlers( FT_Library library, - CFF_Field_Handler** output_class ) - { - CFF_Field_Handler* clazz = NULL; - FT_Error error; - FT_Memory memory = library->memory; - - int i = 0; - - -#undef CFF_FIELD -#define CFF_FIELD( code, name, id, kind ) i++; -#undef CFF_FIELD_DELTA -#define CFF_FIELD_DELTA( code, name, max, id ) i++; -#undef CFF_FIELD_CALLBACK -#define CFF_FIELD_CALLBACK( code, name, id ) i++; - -#include "cfftoken.h" - - i++; /* { 0, 0, 0, 0, 0, 0, 0 } */ - - if ( FT_ALLOC( clazz, sizeof ( CFF_Field_Handler ) * i ) ) - return error; - - i = 0; - - -#ifndef FT_DEBUG_LEVEL_TRACE - - -#undef CFF_FIELD_CALLBACK -#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \ - clazz[i].kind = cff_kind_callback; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = 0; \ - clazz[i].size = 0; \ - clazz[i].reader = cff_parse_ ## name_; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - i++; - -#undef CFF_FIELD -#define CFF_FIELD( code_, name_, id_, kind_ ) \ - clazz[i].kind = kind_; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - i++; \ - -#undef CFF_FIELD_DELTA -#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \ - clazz[i].kind = cff_kind_delta; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = max_; \ - clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ - i++; - -#include "cfftoken.h" - - clazz[i].kind = 0; - clazz[i].code = 0; - clazz[i].offset = 0; - clazz[i].size = 0; - clazz[i].reader = 0; - clazz[i].array_max = 0; - clazz[i].count_offset = 0; - - -#else /* FT_DEBUG_LEVEL_TRACE */ - - -#undef CFF_FIELD_CALLBACK -#define CFF_FIELD_CALLBACK( code_, name_, id_ ) \ - clazz[i].kind = cff_kind_callback; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = 0; \ - clazz[i].size = 0; \ - clazz[i].reader = cff_parse_ ## name_; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - clazz[i].id = id_; \ - i++; - -#undef CFF_FIELD -#define CFF_FIELD( code_, name_, id_, kind_ ) \ - clazz[i].kind = kind_; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = 0; \ - clazz[i].count_offset = 0; \ - clazz[i].id = id_; \ - i++; \ - -#undef CFF_FIELD_DELTA -#define CFF_FIELD_DELTA( code_, name_, max_, id_ ) \ - clazz[i].kind = cff_kind_delta; \ - clazz[i].code = code_ | CFFCODE; \ - clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ - clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \ - clazz[i].reader = 0; \ - clazz[i].array_max = max_; \ - clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ - clazz[i].id = id_; \ - i++; - -#include "cfftoken.h" - - clazz[i].kind = 0; - clazz[i].code = 0; - clazz[i].offset = 0; - clazz[i].size = 0; - clazz[i].reader = 0; - clazz[i].array_max = 0; - clazz[i].count_offset = 0; - clazz[i].id = 0; - - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - - *output_class = clazz; - - return FT_Err_Ok; - } - - -#endif /* FT_CONFIG_OPTION_PIC */ - - - FT_LOCAL_DEF( FT_Error ) - cff_parser_run( CFF_Parser parser, - FT_Byte* start, - FT_Byte* limit ) - { - FT_Byte* p = start; - FT_Error error = FT_Err_Ok; - FT_Library library = parser->library; - FT_UNUSED( library ); - - - parser->top = parser->stack; - parser->start = start; - parser->limit = limit; - parser->cursor = start; - - while ( p < limit ) - { - FT_UInt v = *p; - - - if ( v >= 27 && v != 31 ) - { - /* it's a number; we will push its position on the stack */ - if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH ) - goto Stack_Overflow; - - *parser->top ++ = p; - - /* now, skip it */ - if ( v == 30 ) - { - /* skip real number */ - p++; - for (;;) - { - /* An unterminated floating point number at the */ - /* end of a dictionary is invalid but harmless. */ - if ( p >= limit ) - goto Exit; - v = p[0] >> 4; - if ( v == 15 ) - break; - v = p[0] & 0xF; - if ( v == 15 ) - break; - p++; - } - } - else if ( v == 28 ) - p += 2; - else if ( v == 29 ) - p += 4; - else if ( v > 246 ) - p += 1; - } - else - { - /* This is not a number, hence it's an operator. Compute its code */ - /* and look for it in our current list. */ - - FT_UInt code; - FT_UInt num_args = (FT_UInt) - ( parser->top - parser->stack ); - const CFF_Field_Handler* field; - - - *parser->top = p; - code = v; - if ( v == 12 ) - { - /* two byte operator */ - p++; - if ( p >= limit ) - goto Syntax_Error; - - code = 0x100 | p[0]; - } - code = code | parser->object_code; - - for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ ) - { - if ( field->code == (FT_Int)code ) - { - /* we found our field's handler; read it */ - FT_Long val; - FT_Byte* q = (FT_Byte*)parser->object + field->offset; - - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( " %s", field->id )); -#endif - - /* check that we have enough arguments -- except for */ - /* delta encoded arrays, which can be empty */ - if ( field->kind != cff_kind_delta && num_args < 1 ) - goto Stack_Underflow; - - switch ( field->kind ) - { - case cff_kind_bool: - case cff_kind_string: - case cff_kind_num: - val = cff_parse_num( parser->stack ); - goto Store_Number; - - case cff_kind_fixed: - val = cff_parse_fixed( parser->stack ); - goto Store_Number; - - case cff_kind_fixed_thousand: - val = cff_parse_fixed_scaled( parser->stack, 3 ); - - Store_Number: - switch ( field->size ) - { - case (8 / FT_CHAR_BIT): - *(FT_Byte*)q = (FT_Byte)val; - break; - - case (16 / FT_CHAR_BIT): - *(FT_Short*)q = (FT_Short)val; - break; - - case (32 / FT_CHAR_BIT): - *(FT_Int32*)q = (FT_Int)val; - break; - - default: /* for 64-bit systems */ - *(FT_Long*)q = val; - } - -#ifdef FT_DEBUG_LEVEL_TRACE - switch ( field->kind ) - { - case cff_kind_bool: - FT_TRACE4(( " %s\n", val ? "true" : "false" )); - break; - - case cff_kind_string: - FT_TRACE4(( " %ld (SID)\n", val )); - break; - - case cff_kind_num: - FT_TRACE4(( " %ld\n", val )); - break; - - case cff_kind_fixed: - FT_TRACE4(( " %f\n", (double)val / 65536 )); - break; - - case cff_kind_fixed_thousand: - FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 )); - - default: - ; /* never reached */ - } -#endif - - break; - - case cff_kind_delta: - { - FT_Byte* qcount = (FT_Byte*)parser->object + - field->count_offset; - - FT_Byte** data = parser->stack; - - - if ( num_args > field->array_max ) - num_args = field->array_max; - - FT_TRACE4(( " [" )); - - /* store count */ - *qcount = (FT_Byte)num_args; - - val = 0; - while ( num_args > 0 ) - { - val += cff_parse_num( data++ ); - switch ( field->size ) - { - case (8 / FT_CHAR_BIT): - *(FT_Byte*)q = (FT_Byte)val; - break; - - case (16 / FT_CHAR_BIT): - *(FT_Short*)q = (FT_Short)val; - break; - - case (32 / FT_CHAR_BIT): - *(FT_Int32*)q = (FT_Int)val; - break; - - default: /* for 64-bit systems */ - *(FT_Long*)q = val; - } - - FT_TRACE4(( " %ld", val )); - - q += field->size; - num_args--; - } - - FT_TRACE4(( "]\n" )); - } - break; - - default: /* callback */ - error = field->reader( parser ); - if ( error ) - goto Exit; - } - goto Found; - } - } - - /* this is an unknown operator, or it is unsupported; */ - /* we will ignore it for now. */ - - Found: - /* clear stack */ - parser->top = parser->stack; - } - p++; - } - - Exit: - return error; - - Stack_Overflow: - error = FT_THROW( Invalid_Argument ); - goto Exit; - - Stack_Underflow: - error = FT_THROW( Invalid_Argument ); - goto Exit; - - Syntax_Error: - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - -/* END */ diff --git a/third_party/freetype/src/cff/cffparse.h b/third_party/freetype/src/cff/cffparse.h deleted file mode 100644 index 8ad02ea1e25bda2ad21b279bd79fe9d6cc070b6f..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffparse.h +++ /dev/null @@ -1,106 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffparse.h */ -/* */ -/* CFF token stream parser (specification) */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFF_PARSE_H__ -#define __CFF_PARSE_H__ - - -#include <ft2build.h> -#include "cfftypes.h" -#include FT_INTERNAL_OBJECTS_H - - -FT_BEGIN_HEADER - - -#define CFF_MAX_STACK_DEPTH 96 - -#define CFF_CODE_TOPDICT 0x1000 -#define CFF_CODE_PRIVATE 0x2000 - - - typedef struct CFF_ParserRec_ - { - FT_Library library; - FT_Byte* start; - FT_Byte* limit; - FT_Byte* cursor; - - FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1]; - FT_Byte** top; - - FT_UInt object_code; - void* object; - - } CFF_ParserRec, *CFF_Parser; - - - FT_LOCAL( void ) - cff_parser_init( CFF_Parser parser, - FT_UInt code, - void* object, - FT_Library library); - - FT_LOCAL( FT_Error ) - cff_parser_run( CFF_Parser parser, - FT_Byte* start, - FT_Byte* limit ); - - - enum - { - cff_kind_none = 0, - cff_kind_num, - cff_kind_fixed, - cff_kind_fixed_thousand, - cff_kind_string, - cff_kind_bool, - cff_kind_delta, - cff_kind_callback, - - cff_kind_max /* do not remove */ - }; - - - /* now generate handlers for the most simple fields */ - typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser ); - - typedef struct CFF_Field_Handler_ - { - int kind; - int code; - FT_UInt offset; - FT_Byte size; - CFF_Field_Reader reader; - FT_UInt array_max; - FT_UInt count_offset; - -#ifdef FT_DEBUG_LEVEL_TRACE - const char* id; -#endif - - } CFF_Field_Handler; - - -FT_END_HEADER - - -#endif /* __CFF_PARSE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffpic.c b/third_party/freetype/src/cff/cffpic.c deleted file mode 100644 index d40dec50e9d1f7c79311708b3491464ef264e5ef..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffpic.c +++ /dev/null @@ -1,138 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffpic.c */ -/* */ -/* The FreeType position independent code services for cff module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "cffcmap.h" -#include "cffpic.h" -#include "cfferrs.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from cffdrivr.c */ - FT_Error - FT_Create_Class_cff_services( FT_Library library, - FT_ServiceDescRec** output_class ); - void - FT_Destroy_Class_cff_services( FT_Library library, - FT_ServiceDescRec* clazz ); - void - FT_Init_Class_cff_service_ps_info( FT_Library library, - FT_Service_PsInfoRec* clazz ); - void - FT_Init_Class_cff_service_glyph_dict( FT_Library library, - FT_Service_GlyphDictRec* clazz ); - void - FT_Init_Class_cff_service_ps_name( FT_Library library, - FT_Service_PsFontNameRec* clazz ); - void - FT_Init_Class_cff_service_get_cmap_info( FT_Library library, - FT_Service_TTCMapsRec* clazz ); - void - FT_Init_Class_cff_service_cid_info( FT_Library library, - FT_Service_CIDRec* clazz ); - - /* forward declaration of PIC init functions from cffparse.c */ - FT_Error - FT_Create_Class_cff_field_handlers( FT_Library library, - CFF_Field_Handler** output_class ); - void - FT_Destroy_Class_cff_field_handlers( FT_Library library, - CFF_Field_Handler* clazz ); - - - void - cff_driver_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->cff ) - { - CffModulePIC* container = (CffModulePIC*)pic_container->cff; - - - if ( container->cff_services ) - FT_Destroy_Class_cff_services( library, - container->cff_services ); - container->cff_services = NULL; - if ( container->cff_field_handlers ) - FT_Destroy_Class_cff_field_handlers( - library, container->cff_field_handlers ); - container->cff_field_handlers = NULL; - FT_FREE( container ); - pic_container->cff = NULL; - } - } - - - FT_Error - cff_driver_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - CffModulePIC* container = NULL; - FT_Memory memory = library->memory; - - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC ( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->cff = container; - - /* initialize pointer table - */ - /* this is how the module usually expects this data */ - error = FT_Create_Class_cff_services( library, - &container->cff_services ); - if ( error ) - goto Exit; - - error = FT_Create_Class_cff_field_handlers( - library, &container->cff_field_handlers ); - if ( error ) - goto Exit; - - FT_Init_Class_cff_service_ps_info( - library, &container->cff_service_ps_info ); - FT_Init_Class_cff_service_glyph_dict( - library, &container->cff_service_glyph_dict ); - FT_Init_Class_cff_service_ps_name( - library, &container->cff_service_ps_name ); - FT_Init_Class_cff_service_get_cmap_info( - library, &container->cff_service_get_cmap_info ); - FT_Init_Class_cff_service_cid_info( - library, &container->cff_service_cid_info ); - FT_Init_Class_cff_cmap_encoding_class_rec( - library, &container->cff_cmap_encoding_class_rec ); - FT_Init_Class_cff_cmap_unicode_class_rec( - library, &container->cff_cmap_unicode_class_rec ); - - Exit: - if ( error ) - cff_driver_class_pic_free( library ); - return error; - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cffpic.h b/third_party/freetype/src/cff/cffpic.h deleted file mode 100644 index 9a221a7b7eedc94bf673bdb600b8d158dc6f8838..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cffpic.h +++ /dev/null @@ -1,108 +0,0 @@ -/***************************************************************************/ -/* */ -/* cffpic.h */ -/* */ -/* The FreeType position independent code services for cff module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFPIC_H__ -#define __CFFPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -#ifndef FT_CONFIG_OPTION_PIC - -#define CFF_SERVICE_PS_INFO_GET cff_service_ps_info -#define CFF_SERVICE_GLYPH_DICT_GET cff_service_glyph_dict -#define CFF_SERVICE_PS_NAME_GET cff_service_ps_name -#define CFF_SERVICE_GET_CMAP_INFO_GET cff_service_get_cmap_info -#define CFF_SERVICE_CID_INFO_GET cff_service_cid_info -#define CFF_SERVICE_PROPERTIES_GET cff_service_properties -#define CFF_SERVICES_GET cff_services -#define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec -#define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec -#define CFF_FIELD_HANDLERS_GET cff_field_handlers - -#else /* FT_CONFIG_OPTION_PIC */ - -#include FT_SERVICE_GLYPH_DICT_H -#include "cffparse.h" -#include FT_SERVICE_POSTSCRIPT_INFO_H -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_TT_CMAP_H -#include FT_SERVICE_CID_H -#include FT_SERVICE_PROPERTIES_H - - -FT_BEGIN_HEADER - - typedef struct CffModulePIC_ - { - FT_ServiceDescRec* cff_services; - CFF_Field_Handler* cff_field_handlers; - FT_Service_PsInfoRec cff_service_ps_info; - FT_Service_GlyphDictRec cff_service_glyph_dict; - FT_Service_PsFontNameRec cff_service_ps_name; - FT_Service_TTCMapsRec cff_service_get_cmap_info; - FT_Service_CIDRec cff_service_cid_info; - FT_Service_PropertiesRec cff_service_properties; - FT_CMap_ClassRec cff_cmap_encoding_class_rec; - FT_CMap_ClassRec cff_cmap_unicode_class_rec; - - } CffModulePIC; - - -#define GET_PIC( lib ) \ - ( (CffModulePIC*)( (lib)->pic_container.cff ) ) - -#define CFF_SERVICE_PS_INFO_GET \ - ( GET_PIC( library )->cff_service_ps_info ) -#define CFF_SERVICE_GLYPH_DICT_GET \ - ( GET_PIC( library )->cff_service_glyph_dict ) -#define CFF_SERVICE_PS_NAME_GET \ - ( GET_PIC( library )->cff_service_ps_name ) -#define CFF_SERVICE_GET_CMAP_INFO_GET \ - ( GET_PIC( library )->cff_service_get_cmap_info ) -#define CFF_SERVICE_CID_INFO_GET \ - ( GET_PIC( library )->cff_service_cid_info ) -#define CFF_SERVICE_PROPERTIES_GET \ - ( GET_PIC( library )->cff_service_properties ) -#define CFF_SERVICES_GET \ - ( GET_PIC( library )->cff_services ) -#define CFF_CMAP_ENCODING_CLASS_REC_GET \ - ( GET_PIC( library )->cff_cmap_encoding_class_rec ) -#define CFF_CMAP_UNICODE_CLASS_REC_GET \ - ( GET_PIC( library )->cff_cmap_unicode_class_rec ) -#define CFF_FIELD_HANDLERS_GET \ - ( GET_PIC( library )->cff_field_handlers ) - - /* see cffpic.c for the implementation */ - void - cff_driver_class_pic_free( FT_Library library ); - - FT_Error - cff_driver_class_pic_init( FT_Library library ); - -FT_END_HEADER - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -#endif /* __CFFPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cff/cfftoken.h b/third_party/freetype/src/cff/cfftoken.h deleted file mode 100644 index 5b32076ab8ff495e53b056f11d0318d1ae11bdc7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cfftoken.h +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************/ -/* */ -/* cfftoken.h */ -/* */ -/* CFF token definitions (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#undef FT_STRUCTURE -#define FT_STRUCTURE CFF_FontRecDictRec - -#undef CFFCODE -#define CFFCODE CFFCODE_TOPDICT - - CFF_FIELD_STRING ( 0, version, "Version" ) - CFF_FIELD_STRING ( 1, notice, "Notice" ) - CFF_FIELD_STRING ( 0x100, copyright, "Copyright" ) - CFF_FIELD_STRING ( 2, full_name, "FullName" ) - CFF_FIELD_STRING ( 3, family_name, "FamilyName" ) - CFF_FIELD_STRING ( 4, weight, "Weight" ) - CFF_FIELD_BOOL ( 0x101, is_fixed_pitch, "isFixedPitch" ) - CFF_FIELD_FIXED ( 0x102, italic_angle, "ItalicAngle" ) - CFF_FIELD_FIXED ( 0x103, underline_position, "UnderlinePosition" ) - CFF_FIELD_FIXED ( 0x104, underline_thickness, "UnderlineThickness" ) - CFF_FIELD_NUM ( 0x105, paint_type, "PaintType" ) - CFF_FIELD_NUM ( 0x106, charstring_type, "CharstringType" ) - CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" ) - CFF_FIELD_NUM ( 13, unique_id, "UniqueID" ) - CFF_FIELD_CALLBACK( 5, font_bbox, "FontBBox" ) - CFF_FIELD_NUM ( 0x108, stroke_width, "StrokeWidth" ) - CFF_FIELD_NUM ( 15, charset_offset, "charset" ) - CFF_FIELD_NUM ( 16, encoding_offset, "Encoding" ) - CFF_FIELD_NUM ( 17, charstrings_offset, "CharStrings" ) - CFF_FIELD_CALLBACK( 18, private_dict, "Private" ) - CFF_FIELD_NUM ( 0x114, synthetic_base, "SyntheticBase" ) - CFF_FIELD_STRING ( 0x115, embedded_postscript, "PostScript" ) - -#if 0 - CFF_FIELD_STRING ( 0x116, base_font_name, "BaseFontName" ) - CFF_FIELD_DELTA ( 0x117, base_font_blend, 16, "BaseFontBlend" ) - CFF_FIELD_CALLBACK( 0x118, multiple_master, "MultipleMaster" ) - CFF_FIELD_CALLBACK( 0x119, blend_axis_types, "BlendAxisTypes" ) -#endif - - CFF_FIELD_CALLBACK( 0x11E, cid_ros, "ROS" ) - CFF_FIELD_NUM ( 0x11F, cid_font_version, "CIDFontVersion" ) - CFF_FIELD_NUM ( 0x120, cid_font_revision, "CIDFontRevision" ) - CFF_FIELD_NUM ( 0x121, cid_font_type, "CIDFontType" ) - CFF_FIELD_NUM ( 0x122, cid_count, "CIDCount" ) - CFF_FIELD_NUM ( 0x123, cid_uid_base, "UIDBase" ) - CFF_FIELD_NUM ( 0x124, cid_fd_array_offset, "FDArray" ) - CFF_FIELD_NUM ( 0x125, cid_fd_select_offset, "FDSelect" ) - CFF_FIELD_STRING ( 0x126, cid_font_name, "FontName" ) - -#if 0 - CFF_FIELD_NUM ( 0x127, chameleon, "Chameleon" ) -#endif - - -#undef FT_STRUCTURE -#define FT_STRUCTURE CFF_PrivateRec -#undef CFFCODE -#define CFFCODE CFFCODE_PRIVATE - - CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" ) - CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" ) - CFF_FIELD_DELTA ( 8, family_blues, 14, "FamilyBlues" ) - CFF_FIELD_DELTA ( 9, family_other_blues, 10, "FamilyOtherBlues" ) - CFF_FIELD_FIXED_1000( 0x109, blue_scale, "BlueScale" ) - CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" ) - CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" ) - CFF_FIELD_NUM ( 10, standard_width, "StdHW" ) - CFF_FIELD_NUM ( 11, standard_height, "StdVW" ) - CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" ) - CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" ) - CFF_FIELD_BOOL ( 0x10E, force_bold, "ForceBold" ) - CFF_FIELD_FIXED ( 0x10F, force_bold_threshold, "ForceBoldThreshold" ) - CFF_FIELD_NUM ( 0x110, lenIV, "lenIV" ) - CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" ) - CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" ) - CFF_FIELD_NUM ( 0x113, initial_random_seed, "initialRandomSeed" ) - CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" ) - CFF_FIELD_NUM ( 20, default_width, "defaultWidthX" ) - CFF_FIELD_NUM ( 21, nominal_width, "nominalWidthX" ) - - -/* END */ diff --git a/third_party/freetype/src/cff/cfftypes.h b/third_party/freetype/src/cff/cfftypes.h deleted file mode 100644 index de8a5ee9b44c5078a83e306e8a170cbad4506aa7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cff/cfftypes.h +++ /dev/null @@ -1,284 +0,0 @@ -/***************************************************************************/ -/* */ -/* cfftypes.h */ -/* */ -/* Basic OpenType/CFF type definitions and interface (specification */ -/* only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CFFTYPES_H__ -#define __CFFTYPES_H__ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TYPE1_TABLES_H -#include FT_INTERNAL_SERVICE_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CFF_IndexRec */ - /* */ - /* <Description> */ - /* A structure used to model a CFF Index table. */ - /* */ - /* <Fields> */ - /* stream :: The source input stream. */ - /* */ - /* start :: The position of the first index byte in the */ - /* input stream. */ - /* */ - /* count :: The number of elements in the index. */ - /* */ - /* off_size :: The size in bytes of object offsets in index. */ - /* */ - /* data_offset :: The position of first data byte in the index's */ - /* bytes. */ - /* */ - /* data_size :: The size of the data table in this index. */ - /* */ - /* offsets :: A table of element offsets in the index. Must be */ - /* loaded explicitly. */ - /* */ - /* bytes :: If the index is loaded in memory, its bytes. */ - /* */ - typedef struct CFF_IndexRec_ - { - FT_Stream stream; - FT_ULong start; - FT_UInt count; - FT_Byte off_size; - FT_ULong data_offset; - FT_ULong data_size; - - FT_ULong* offsets; - FT_Byte* bytes; - - } CFF_IndexRec, *CFF_Index; - - - typedef struct CFF_EncodingRec_ - { - FT_UInt format; - FT_ULong offset; - - FT_UInt count; - FT_UShort sids [256]; /* avoid dynamic allocations */ - FT_UShort codes[256]; - - } CFF_EncodingRec, *CFF_Encoding; - - - typedef struct CFF_CharsetRec_ - { - - FT_UInt format; - FT_ULong offset; - - FT_UShort* sids; - FT_UShort* cids; /* the inverse mapping of `sids'; only needed */ - /* for CID-keyed fonts */ - FT_UInt max_cid; - FT_UInt num_glyphs; - - } CFF_CharsetRec, *CFF_Charset; - - - typedef struct CFF_FontRecDictRec_ - { - FT_UInt version; - FT_UInt notice; - FT_UInt copyright; - FT_UInt full_name; - FT_UInt family_name; - FT_UInt weight; - FT_Bool is_fixed_pitch; - FT_Fixed italic_angle; - FT_Fixed underline_position; - FT_Fixed underline_thickness; - FT_Int paint_type; - FT_Int charstring_type; - FT_Matrix font_matrix; - FT_Bool has_font_matrix; - FT_ULong units_per_em; /* temporarily used as scaling value also */ - FT_Vector font_offset; - FT_ULong unique_id; - FT_BBox font_bbox; - FT_Pos stroke_width; - FT_ULong charset_offset; - FT_ULong encoding_offset; - FT_ULong charstrings_offset; - FT_ULong private_offset; - FT_ULong private_size; - FT_Long synthetic_base; - FT_UInt embedded_postscript; - - /* these should only be used for the top-level font dictionary */ - FT_UInt cid_registry; - FT_UInt cid_ordering; - FT_Long cid_supplement; - - FT_Long cid_font_version; - FT_Long cid_font_revision; - FT_Long cid_font_type; - FT_ULong cid_count; - FT_ULong cid_uid_base; - FT_ULong cid_fd_array_offset; - FT_ULong cid_fd_select_offset; - FT_UInt cid_font_name; - - } CFF_FontRecDictRec, *CFF_FontRecDict; - - - typedef struct CFF_PrivateRec_ - { - FT_Byte num_blue_values; - FT_Byte num_other_blues; - FT_Byte num_family_blues; - FT_Byte num_family_other_blues; - - FT_Pos blue_values[14]; - FT_Pos other_blues[10]; - FT_Pos family_blues[14]; - FT_Pos family_other_blues[10]; - - FT_Fixed blue_scale; - FT_Pos blue_shift; - FT_Pos blue_fuzz; - FT_Pos standard_width; - FT_Pos standard_height; - - FT_Byte num_snap_widths; - FT_Byte num_snap_heights; - FT_Pos snap_widths[13]; - FT_Pos snap_heights[13]; - FT_Bool force_bold; - FT_Fixed force_bold_threshold; - FT_Int lenIV; - FT_Int language_group; - FT_Fixed expansion_factor; - FT_Long initial_random_seed; - FT_ULong local_subrs_offset; - FT_Pos default_width; - FT_Pos nominal_width; - - } CFF_PrivateRec, *CFF_Private; - - - typedef struct CFF_FDSelectRec_ - { - FT_Byte format; - FT_UInt range_count; - - /* that's the table, taken from the file `as is' */ - FT_Byte* data; - FT_UInt data_size; - - /* small cache for format 3 only */ - FT_UInt cache_first; - FT_UInt cache_count; - FT_Byte cache_fd; - - } CFF_FDSelectRec, *CFF_FDSelect; - - - /* A SubFont packs a font dict and a private dict together. They are */ - /* needed to support CID-keyed CFF fonts. */ - typedef struct CFF_SubFontRec_ - { - CFF_FontRecDictRec font_dict; - CFF_PrivateRec private_dict; - - CFF_IndexRec local_subrs_index; - FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */ - - } CFF_SubFontRec, *CFF_SubFont; - - -#define CFF_MAX_CID_FONTS 256 - - - typedef struct CFF_FontRec_ - { - FT_Stream stream; - FT_Memory memory; - FT_UInt num_faces; - FT_UInt num_glyphs; - - FT_Byte version_major; - FT_Byte version_minor; - FT_Byte header_size; - FT_Byte absolute_offsize; - - - CFF_IndexRec name_index; - CFF_IndexRec top_dict_index; - CFF_IndexRec global_subrs_index; - - CFF_EncodingRec encoding; - CFF_CharsetRec charset; - - CFF_IndexRec charstrings_index; - CFF_IndexRec font_dict_index; - CFF_IndexRec private_index; - CFF_IndexRec local_subrs_index; - - FT_String* font_name; - - /* array of pointers into Global Subrs INDEX data */ - FT_Byte** global_subrs; - - /* array of pointers into String INDEX data stored at string_pool */ - FT_UInt num_strings; - FT_Byte** strings; - FT_Byte* string_pool; - - CFF_SubFontRec top_font; - FT_UInt num_subfonts; - CFF_SubFont subfonts[CFF_MAX_CID_FONTS]; - - CFF_FDSelectRec fd_select; - - /* interface to PostScript hinter */ - PSHinter_Service pshinter; - - /* interface to Postscript Names service */ - FT_Service_PsCMaps psnames; - - /* since version 2.3.0 */ - PS_FontInfoRec* font_info; /* font info dictionary */ - - /* since version 2.3.6 */ - FT_String* registry; - FT_String* ordering; - - /* since version 2.4.12 */ - FT_Generic cf2_instance; - - } CFF_FontRec, *CFF_Font; - - -FT_END_HEADER - -#endif /* __CFFTYPES_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/Jamfile b/third_party/freetype/src/cid/Jamfile deleted file mode 100644 index 64e1523157b72df6d650fa2ddc23e08c4973eabd..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/Jamfile +++ /dev/null @@ -1,34 +0,0 @@ -# FreeType 2 src/cid Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) cid ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = cidgload - cidload - cidobjs - cidparse - cidriver - ; - } - else - { - _sources = type1cid ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/cid Jamfile diff --git a/third_party/freetype/src/cid/ciderrs.h b/third_party/freetype/src/cid/ciderrs.h deleted file mode 100644 index 5e0e776ee16ce4dc1b6bb27c22122b202fe630da..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/ciderrs.h +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************/ -/* */ -/* ciderrs.h */ -/* */ -/* CID error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the CID error enumeration constants. */ - /* */ - /*************************************************************************/ - -#ifndef __CIDERRS_H__ -#define __CIDERRS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX CID_Err_ -#define FT_ERR_BASE FT_Mod_Err_CID - -#include FT_ERRORS_H - -#endif /* __CIDERRS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/cidgload.c b/third_party/freetype/src/cid/cidgload.c deleted file mode 100644 index d00674fe0d373df32d425fcf15cc59b97bd84c6c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidgload.c +++ /dev/null @@ -1,446 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidgload.c */ -/* */ -/* CID-keyed Type1 Glyph Loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "cidload.h" -#include "cidgload.h" -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_OUTLINE_H -#include FT_INTERNAL_CALC_H - -#include "ciderrs.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cidgload - - - FT_CALLBACK_DEF( FT_Error ) - cid_load_glyph( T1_Decoder decoder, - FT_UInt glyph_index ) - { - CID_Face face = (CID_Face)decoder->builder.face; - CID_FaceInfo cid = &face->cid; - FT_Byte* p; - FT_ULong fd_select; - FT_Stream stream = face->cid_stream; - FT_Error error = FT_Err_Ok; - FT_Byte* charstring = NULL; - FT_Memory memory = face->root.memory; - FT_ULong glyph_length = 0; - PSAux_Service psaux = (PSAux_Service)face->psaux; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - FT_Incremental_InterfaceRec *inc = - face->root.internal->incremental_interface; -#endif - - - FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index )); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* For incremental fonts get the character data using */ - /* the callback function. */ - if ( inc ) - { - FT_Data glyph_data; - - - error = inc->funcs->get_glyph_data( inc->object, - glyph_index, &glyph_data ); - if ( error ) - goto Exit; - - p = (FT_Byte*)glyph_data.pointer; - fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); - - if ( glyph_data.length != 0 ) - { - glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes ); - (void)FT_ALLOC( charstring, glyph_length ); - if ( !error ) - ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes, - glyph_length ); - } - - inc->funcs->free_glyph_data( inc->object, &glyph_data ); - - if ( error ) - goto Exit; - } - - else - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - /* For ordinary fonts read the CID font dictionary index */ - /* and charstring offset from the CIDMap. */ - { - FT_UInt entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes ); - FT_ULong off1; - - - if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + - glyph_index * entry_len ) || - FT_FRAME_ENTER( 2 * entry_len ) ) - goto Exit; - - p = (FT_Byte*)stream->cursor; - fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); - off1 = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); - p += cid->fd_bytes; - glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; - FT_FRAME_EXIT(); - - if ( fd_select >= (FT_ULong)cid->num_dicts ) - { - error = FT_THROW( Invalid_Offset ); - goto Exit; - } - if ( glyph_length == 0 ) - goto Exit; - if ( FT_ALLOC( charstring, glyph_length ) ) - goto Exit; - if ( FT_STREAM_READ_AT( cid->data_offset + off1, - charstring, glyph_length ) ) - goto Exit; - } - - /* Now set up the subrs array and parse the charstrings. */ - { - CID_FaceDict dict; - CID_Subrs cid_subrs = face->subrs + fd_select; - FT_UInt cs_offset; - - - /* Set up subrs */ - decoder->num_subrs = cid_subrs->num_subrs; - decoder->subrs = cid_subrs->code; - decoder->subrs_len = 0; - - /* Set up font matrix */ - dict = cid->font_dicts + fd_select; - - decoder->font_matrix = dict->font_matrix; - decoder->font_offset = dict->font_offset; - decoder->lenIV = dict->private_dict.lenIV; - - /* Decode the charstring. */ - - /* Adjustment for seed bytes. */ - cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; - - /* Decrypt only if lenIV >= 0. */ - if ( decoder->lenIV >= 0 ) - psaux->t1_decrypt( charstring, glyph_length, 4330 ); - - error = decoder->funcs.parse_charstrings( - decoder, charstring + cs_offset, - glyph_length - cs_offset ); - } - - FT_FREE( charstring ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* Incremental fonts can optionally override the metrics. */ - if ( !error && inc && inc->funcs->get_glyph_metrics ) - { - FT_Incremental_MetricsRec metrics; - - - metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); - metrics.bearing_y = 0; - metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); - metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); - - error = inc->funcs->get_glyph_metrics( inc->object, - glyph_index, FALSE, &metrics ); - - decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); - decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); - decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); - } - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - Exit: - return error; - } - - -#if 0 - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** *********/ - /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ - /********** *********/ - /********** The following code is in charge of computing *********/ - /********** the maximum advance width of the font. It *********/ - /********** quickly processes each glyph charstring to *********/ - /********** extract the value from either a `sbw' or `seac' *********/ - /********** operator. *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_LOCAL_DEF( FT_Error ) - cid_face_compute_max_advance( CID_Face face, - FT_Int* max_advance ) - { - FT_Error error; - T1_DecoderRec decoder; - FT_Int glyph_index; - - PSAux_Service psaux = (PSAux_Service)face->psaux; - - - *max_advance = 0; - - /* Initialize load decoder */ - error = psaux->t1_decoder_funcs->init( &decoder, - (FT_Face)face, - 0, /* size */ - 0, /* glyph slot */ - 0, /* glyph names! XXX */ - 0, /* blend == 0 */ - 0, /* hinting == 0 */ - cid_load_glyph ); - if ( error ) - return error; - - /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ - /* if we ever support CID-keyed multiple master fonts */ - - decoder.builder.metrics_only = 1; - decoder.builder.load_points = 0; - - /* for each glyph, parse the glyph charstring and extract */ - /* the advance width */ - for ( glyph_index = 0; glyph_index < face->root.num_glyphs; - glyph_index++ ) - { - /* now get load the unscaled outline */ - error = cid_load_glyph( &decoder, glyph_index ); - /* ignore the error if one occurred - skip to next glyph */ - } - - *max_advance = FIXED_TO_INT( decoder.builder.advance.x ); - - psaux->t1_decoder_funcs->done( &decoder ); - - return FT_Err_Ok; - } - - -#endif /* 0 */ - - - FT_LOCAL_DEF( FT_Error ) - cid_slot_load_glyph( FT_GlyphSlot cidglyph, /* CID_GlyphSlot */ - FT_Size cidsize, /* CID_Size */ - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - CID_GlyphSlot glyph = (CID_GlyphSlot)cidglyph; - FT_Error error; - T1_DecoderRec decoder; - CID_Face face = (CID_Face)cidglyph->face; - FT_Bool hinting; - - PSAux_Service psaux = (PSAux_Service)face->psaux; - FT_Matrix font_matrix; - FT_Vector font_offset; - - - if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( load_flags & FT_LOAD_NO_RECURSE ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; - - glyph->x_scale = cidsize->metrics.x_scale; - glyph->y_scale = cidsize->metrics.y_scale; - - cidglyph->outline.n_points = 0; - cidglyph->outline.n_contours = 0; - - hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && - ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); - - cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; - - error = psaux->t1_decoder_funcs->init( &decoder, - cidglyph->face, - cidsize, - cidglyph, - 0, /* glyph names -- XXX */ - 0, /* blend == 0 */ - hinting, - FT_LOAD_TARGET_MODE( load_flags ), - cid_load_glyph ); - if ( error ) - goto Exit; - - /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ - /* if we ever support CID-keyed multiple master fonts */ - - /* set up the decoder */ - decoder.builder.no_recurse = FT_BOOL( - ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) ); - - error = cid_load_glyph( &decoder, glyph_index ); - if ( error ) - goto Exit; - - font_matrix = decoder.font_matrix; - font_offset = decoder.font_offset; - - /* save new glyph tables */ - psaux->t1_decoder_funcs->done( &decoder ); - - /* now set the metrics -- this is rather simple, as */ - /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax */ - cidglyph->outline.flags &= FT_OUTLINE_OWNER; - cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; - - /* for composite glyphs, return only left side bearing and */ - /* advance width */ - if ( load_flags & FT_LOAD_NO_RECURSE ) - { - FT_Slot_Internal internal = cidglyph->internal; - - - cidglyph->metrics.horiBearingX = - FIXED_TO_INT( decoder.builder.left_bearing.x ); - cidglyph->metrics.horiAdvance = - FIXED_TO_INT( decoder.builder.advance.x ); - - internal->glyph_matrix = font_matrix; - internal->glyph_delta = font_offset; - internal->glyph_transformed = 1; - } - else - { - FT_BBox cbox; - FT_Glyph_Metrics* metrics = &cidglyph->metrics; - - - /* copy the _unscaled_ advance width */ - metrics->horiAdvance = - FIXED_TO_INT( decoder.builder.advance.x ); - cidglyph->linearHoriAdvance = - FIXED_TO_INT( decoder.builder.advance.x ); - cidglyph->internal->glyph_transformed = 0; - - /* make up vertical ones */ - metrics->vertAdvance = ( face->cid.font_bbox.yMax - - face->cid.font_bbox.yMin ) >> 16; - cidglyph->linearVertAdvance = metrics->vertAdvance; - - cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; - - if ( cidsize->metrics.y_ppem < 24 ) - cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - - /* apply the font matrix, if any */ - if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || - font_matrix.xy != 0 || font_matrix.yx != 0 ) - { - FT_Outline_Transform( &cidglyph->outline, &font_matrix ); - - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, - font_matrix.xx ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, - font_matrix.yy ); - } - - if ( font_offset.x || font_offset.y ) - { - FT_Outline_Translate( &cidglyph->outline, - font_offset.x, - font_offset.y ); - - metrics->horiAdvance += font_offset.x; - metrics->vertAdvance += font_offset.y; - } - - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) - { - /* scale the outline and the metrics */ - FT_Int n; - FT_Outline* cur = decoder.builder.base; - FT_Vector* vec = cur->points; - FT_Fixed x_scale = glyph->x_scale; - FT_Fixed y_scale = glyph->y_scale; - - - /* First of all, scale the points */ - if ( !hinting || !decoder.builder.hints_funcs ) - for ( n = cur->n_points; n > 0; n--, vec++ ) - { - vec->x = FT_MulFix( vec->x, x_scale ); - vec->y = FT_MulFix( vec->y, y_scale ); - } - - /* Then scale the metrics */ - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); - } - - /* compute the other metrics */ - FT_Outline_Get_CBox( &cidglyph->outline, &cbox ); - - metrics->width = cbox.xMax - cbox.xMin; - metrics->height = cbox.yMax - cbox.yMin; - - metrics->horiBearingX = cbox.xMin; - metrics->horiBearingY = cbox.yMax; - - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - /* make up vertical ones */ - ft_synthesize_vertical_metrics( metrics, - metrics->vertAdvance ); - } - } - - Exit: - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/cid/cidgload.h b/third_party/freetype/src/cid/cidgload.h deleted file mode 100644 index 4a10ce505c386685494fcced41186b5722a30c20..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidgload.h +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidgload.h */ -/* */ -/* OpenType Glyph Loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CIDGLOAD_H__ -#define __CIDGLOAD_H__ - - -#include <ft2build.h> -#include "cidobjs.h" - - -FT_BEGIN_HEADER - - -#if 0 - - /* Compute the maximum advance width of a font through quick parsing */ - FT_LOCAL( FT_Error ) - cid_face_compute_max_advance( CID_Face face, - FT_Int* max_advance ); - -#endif /* 0 */ - - FT_LOCAL( FT_Error ) - cid_slot_load_glyph( FT_GlyphSlot glyph, /* CID_Glyph_Slot */ - FT_Size size, /* CID_Size */ - FT_UInt glyph_index, - FT_Int32 load_flags ); - - -FT_END_HEADER - -#endif /* __CIDGLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/cidload.c b/third_party/freetype/src/cid/cidload.c deleted file mode 100644 index e23b82f6738ebf65370ed3aa967e1bc36f612703..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidload.c +++ /dev/null @@ -1,705 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidload.c */ -/* */ -/* CID-keyed Type1 font loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_CONFIG_CONFIG_H -#include FT_MULTIPLE_MASTERS_H -#include FT_INTERNAL_TYPE1_TYPES_H - -#include "cidload.h" - -#include "ciderrs.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cidload - - - /* read a single offset */ - FT_LOCAL_DEF( FT_ULong ) - cid_get_offset( FT_Byte* *start, - FT_Byte offsize ) - { - FT_ULong result; - FT_Byte* p = *start; - - - for ( result = 0; offsize > 0; offsize-- ) - { - result <<= 8; - result |= *p++; - } - - *start = p; - return result; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE 1 SYMBOL PARSING *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - static FT_Error - cid_load_keyword( CID_Face face, - CID_Loader* loader, - const T1_Field keyword ) - { - FT_Error error; - CID_Parser* parser = &loader->parser; - FT_Byte* object; - void* dummy_object; - CID_FaceInfo cid = &face->cid; - - - /* if the keyword has a dedicated callback, call it */ - if ( keyword->type == T1_FIELD_TYPE_CALLBACK ) - { - keyword->reader( (FT_Face)face, parser ); - error = parser->root.error; - goto Exit; - } - - /* we must now compute the address of our target object */ - switch ( keyword->location ) - { - case T1_FIELD_LOCATION_CID_INFO: - object = (FT_Byte*)cid; - break; - - case T1_FIELD_LOCATION_FONT_INFO: - object = (FT_Byte*)&cid->font_info; - break; - - case T1_FIELD_LOCATION_FONT_EXTRA: - object = (FT_Byte*)&face->font_extra; - break; - - case T1_FIELD_LOCATION_BBOX: - object = (FT_Byte*)&cid->font_bbox; - break; - - default: - { - CID_FaceDict dict; - - - if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts ) - { - FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n", - keyword->ident )); - error = FT_THROW( Syntax_Error ); - goto Exit; - } - - dict = cid->font_dicts + parser->num_dict; - switch ( keyword->location ) - { - case T1_FIELD_LOCATION_PRIVATE: - object = (FT_Byte*)&dict->private_dict; - break; - - default: - object = (FT_Byte*)dict; - } - } - } - - dummy_object = object; - - /* now, load the keyword data in the object's field(s) */ - if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY || - keyword->type == T1_FIELD_TYPE_FIXED_ARRAY ) - error = cid_parser_load_field_table( &loader->parser, keyword, - &dummy_object ); - else - error = cid_parser_load_field( &loader->parser, - keyword, &dummy_object ); - Exit: - return error; - } - - - FT_CALLBACK_DEF( FT_Error ) - cid_parse_font_matrix( CID_Face face, - CID_Parser* parser ) - { - CID_FaceDict dict; - FT_Face root = (FT_Face)&face->root; - FT_Fixed temp[6]; - FT_Fixed temp_scale; - - - if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) - { - FT_Matrix* matrix; - FT_Vector* offset; - FT_Int result; - - - dict = face->cid.font_dicts + parser->num_dict; - matrix = &dict->font_matrix; - offset = &dict->font_offset; - - /* input is scaled by 1000 to accommodate default FontMatrix */ - result = cid_parser_to_fixed_array( parser, 6, temp, 3 ); - - if ( result < 6 ) - return FT_THROW( Invalid_File_Format ); - - temp_scale = FT_ABS( temp[3] ); - - if ( temp_scale == 0 ) - { - FT_ERROR(( "cid_parse_font_matrix: invalid font matrix\n" )); - return FT_THROW( Invalid_File_Format ); - } - - /* atypical case */ - if ( temp_scale != 0x10000L ) - { - /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); - - temp[0] = FT_DivFix( temp[0], temp_scale ); - temp[1] = FT_DivFix( temp[1], temp_scale ); - temp[2] = FT_DivFix( temp[2], temp_scale ); - temp[4] = FT_DivFix( temp[4], temp_scale ); - temp[5] = FT_DivFix( temp[5], temp_scale ); - temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L; - } - - matrix->xx = temp[0]; - matrix->yx = temp[1]; - matrix->xy = temp[2]; - matrix->yy = temp[3]; - - /* note that the font offsets are expressed in integer font units */ - offset->x = temp[4] >> 16; - offset->y = temp[5] >> 16; - } - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_Error ) - parse_fd_array( CID_Face face, - CID_Parser* parser ) - { - CID_FaceInfo cid = &face->cid; - FT_Memory memory = face->root.memory; - FT_Error error = FT_Err_Ok; - FT_Long num_dicts; - - - num_dicts = cid_parser_to_int( parser ); - if ( num_dicts < 0 ) - { - FT_ERROR(( "parse_fd_array: invalid number of dictionaries\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( !cid->font_dicts ) - { - FT_Int n; - - - if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) ) - goto Exit; - - cid->num_dicts = num_dicts; - - /* don't forget to set a few defaults */ - for ( n = 0; n < cid->num_dicts; n++ ) - { - CID_FaceDict dict = cid->font_dicts + n; - - - /* default value for lenIV */ - dict->private_dict.lenIV = 4; - } - } - - Exit: - return error; - } - - - /* by mistake, `expansion_factor' appears both in PS_PrivateRec */ - /* and CID_FaceDictRec (both are public header files and can't */ - /* changed); we simply copy the value */ - - FT_CALLBACK_DEF( FT_Error ) - parse_expansion_factor( CID_Face face, - CID_Parser* parser ) - { - CID_FaceDict dict; - - - if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) - { - dict = face->cid.font_dicts + parser->num_dict; - - dict->expansion_factor = cid_parser_to_fixed( parser, 0 ); - dict->private_dict.expansion_factor = dict->expansion_factor; - } - - return FT_Err_Ok; - } - - - static - const T1_FieldRec cid_field_records[] = - { - -#include "cidtoken.h" - - T1_FIELD_CALLBACK( "FDArray", parse_fd_array, 0 ) - T1_FIELD_CALLBACK( "FontMatrix", cid_parse_font_matrix, 0 ) - T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 ) - - { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } - }; - - - static FT_Error - cid_parse_dict( CID_Face face, - CID_Loader* loader, - FT_Byte* base, - FT_ULong size ) - { - CID_Parser* parser = &loader->parser; - - - parser->root.cursor = base; - parser->root.limit = base + size; - parser->root.error = FT_Err_Ok; - - { - FT_Byte* cur = base; - FT_Byte* limit = cur + size; - - - for (;;) - { - FT_Byte* newlimit; - - - parser->root.cursor = cur; - cid_parser_skip_spaces( parser ); - - if ( parser->root.cursor >= limit ) - newlimit = limit - 1 - 17; - else - newlimit = parser->root.cursor - 17; - - /* look for `%ADOBeginFontDict' */ - for ( ; cur < newlimit; cur++ ) - { - if ( *cur == '%' && - ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 ) - { - /* if /FDArray was found, then cid->num_dicts is > 0, and */ - /* we can start increasing parser->num_dict */ - if ( face->cid.num_dicts > 0 ) - parser->num_dict++; - } - } - - cur = parser->root.cursor; - /* no error can occur in cid_parser_skip_spaces */ - if ( cur >= limit ) - break; - - cid_parser_skip_PS_token( parser ); - if ( parser->root.cursor >= limit || parser->root.error ) - break; - - /* look for immediates */ - if ( *cur == '/' && cur + 2 < limit ) - { - FT_UInt len; - - - cur++; - len = (FT_UInt)( parser->root.cursor - cur ); - - if ( len > 0 && len < 22 ) - { - /* now compare the immediate name to the keyword table */ - T1_Field keyword = (T1_Field)cid_field_records; - - - for (;;) - { - FT_Byte* name; - - - name = (FT_Byte*)keyword->ident; - if ( !name ) - break; - - if ( cur[0] == name[0] && - len == ft_strlen( (const char*)name ) ) - { - FT_UInt n; - - - for ( n = 1; n < len; n++ ) - if ( cur[n] != name[n] ) - break; - - if ( n >= len ) - { - /* we found it - run the parsing callback */ - parser->root.error = cid_load_keyword( face, - loader, - keyword ); - if ( parser->root.error ) - return parser->root.error; - break; - } - } - keyword++; - } - } - } - - cur = parser->root.cursor; - } - } - return parser->root.error; - } - - - /* read the subrmap and the subrs of each font dict */ - static FT_Error - cid_read_subrs( CID_Face face ) - { - CID_FaceInfo cid = &face->cid; - FT_Memory memory = face->root.memory; - FT_Stream stream = face->cid_stream; - FT_Error error; - FT_Int n; - CID_Subrs subr; - FT_UInt max_offsets = 0; - FT_ULong* offsets = NULL; - PSAux_Service psaux = (PSAux_Service)face->psaux; - - - if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) ) - goto Exit; - - subr = face->subrs; - for ( n = 0; n < cid->num_dicts; n++, subr++ ) - { - CID_FaceDict dict = cid->font_dicts + n; - FT_Int lenIV = dict->private_dict.lenIV; - FT_UInt count, num_subrs = dict->num_subrs; - FT_ULong data_len; - FT_Byte* p; - - - /* Check for possible overflow. */ - if ( num_subrs == FT_UINT_MAX ) - { - error = FT_THROW( Syntax_Error ); - goto Fail; - } - - /* reallocate offsets array if needed */ - if ( num_subrs + 1 > max_offsets ) - { - FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 ); - - - if ( new_max <= max_offsets ) - { - error = FT_THROW( Syntax_Error ); - goto Fail; - } - - if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) ) - goto Fail; - - max_offsets = new_max; - } - - /* read the subrmap's offsets */ - if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) || - FT_FRAME_ENTER( ( num_subrs + 1 ) * (FT_UInt)dict->sd_bytes ) ) - goto Fail; - - p = (FT_Byte*)stream->cursor; - for ( count = 0; count <= num_subrs; count++ ) - offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes ); - - FT_FRAME_EXIT(); - - /* offsets must be ordered */ - for ( count = 1; count <= num_subrs; count++ ) - if ( offsets[count - 1] > offsets[count] ) - goto Fail; - - /* now, compute the size of subrs charstrings, */ - /* allocate, and read them */ - data_len = offsets[num_subrs] - offsets[0]; - - if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) || - FT_ALLOC( subr->code[0], data_len ) ) - goto Fail; - - if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) || - FT_STREAM_READ( subr->code[0], data_len ) ) - goto Fail; - - /* set up pointers */ - for ( count = 1; count <= num_subrs; count++ ) - { - FT_ULong len; - - - len = offsets[count] - offsets[count - 1]; - subr->code[count] = subr->code[count - 1] + len; - } - - /* decrypt subroutines, but only if lenIV >= 0 */ - if ( lenIV >= 0 ) - { - for ( count = 0; count < num_subrs; count++ ) - { - FT_ULong len; - - - len = offsets[count + 1] - offsets[count]; - psaux->t1_decrypt( subr->code[count], len, 4330 ); - } - } - - subr->num_subrs = (FT_Int)num_subrs; - } - - Exit: - FT_FREE( offsets ); - return error; - - Fail: - if ( face->subrs ) - { - for ( n = 0; n < cid->num_dicts; n++ ) - { - if ( face->subrs[n].code ) - FT_FREE( face->subrs[n].code[0] ); - - FT_FREE( face->subrs[n].code ); - } - FT_FREE( face->subrs ); - } - goto Exit; - } - - - static void - cid_init_loader( CID_Loader* loader, - CID_Face face ) - { - FT_UNUSED( face ); - - FT_MEM_ZERO( loader, sizeof ( *loader ) ); - } - - - static void - cid_done_loader( CID_Loader* loader ) - { - CID_Parser* parser = &loader->parser; - - - /* finalize parser */ - cid_parser_done( parser ); - } - - - static FT_Error - cid_hex_to_binary( FT_Byte* data, - FT_ULong data_len, - FT_ULong offset, - CID_Face face ) - { - FT_Stream stream = face->root.stream; - FT_Error error; - - FT_Byte buffer[256]; - FT_Byte *p, *plimit; - FT_Byte *d, *dlimit; - FT_Byte val; - - FT_Bool upper_nibble, done; - - - if ( FT_STREAM_SEEK( offset ) ) - goto Exit; - - d = data; - dlimit = d + data_len; - p = buffer; - plimit = p; - - upper_nibble = 1; - done = 0; - - while ( d < dlimit ) - { - if ( p >= plimit ) - { - FT_ULong oldpos = FT_STREAM_POS(); - FT_ULong size = stream->size - oldpos; - - - if ( size == 0 ) - { - error = FT_THROW( Syntax_Error ); - goto Exit; - } - - if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) ) - goto Exit; - p = buffer; - plimit = p + FT_STREAM_POS() - oldpos; - } - - if ( ft_isdigit( *p ) ) - val = (FT_Byte)( *p - '0' ); - else if ( *p >= 'a' && *p <= 'f' ) - val = (FT_Byte)( *p - 'a' ); - else if ( *p >= 'A' && *p <= 'F' ) - val = (FT_Byte)( *p - 'A' + 10 ); - else if ( *p == ' ' || - *p == '\t' || - *p == '\r' || - *p == '\n' || - *p == '\f' || - *p == '\0' ) - { - p++; - continue; - } - else if ( *p == '>' ) - { - val = 0; - done = 1; - } - else - { - error = FT_THROW( Syntax_Error ); - goto Exit; - } - - if ( upper_nibble ) - *d = (FT_Byte)( val << 4 ); - else - { - *d = (FT_Byte)( *d + val ); - d++; - } - - upper_nibble = (FT_Byte)( 1 - upper_nibble ); - - if ( done ) - break; - - p++; - } - - error = FT_Err_Ok; - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - cid_face_open( CID_Face face, - FT_Int face_index ) - { - CID_Loader loader; - CID_Parser* parser; - FT_Memory memory = face->root.memory; - FT_Error error; - - - cid_init_loader( &loader, face ); - - parser = &loader.parser; - error = cid_parser_new( parser, face->root.stream, face->root.memory, - (PSAux_Service)face->psaux ); - if ( error ) - goto Exit; - - error = cid_parse_dict( face, &loader, - parser->postscript, - parser->postscript_len ); - if ( error ) - goto Exit; - - if ( face_index < 0 ) - goto Exit; - - if ( FT_NEW( face->cid_stream ) ) - goto Exit; - - if ( parser->binary_length ) - { - /* we must convert the data section from hexadecimal to binary */ - if ( FT_ALLOC( face->binary_data, parser->binary_length ) || - cid_hex_to_binary( face->binary_data, parser->binary_length, - parser->data_offset, face ) ) - goto Exit; - - FT_Stream_OpenMemory( face->cid_stream, - face->binary_data, parser->binary_length ); - face->cid.data_offset = 0; - } - else - { - *face->cid_stream = *face->root.stream; - face->cid.data_offset = loader.parser.data_offset; - } - - error = cid_read_subrs( face ); - - Exit: - cid_done_loader( &loader ); - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/cid/cidload.h b/third_party/freetype/src/cid/cidload.h deleted file mode 100644 index d7776d2f88af0294a90bb3be81e40a020c44aef0..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidload.h +++ /dev/null @@ -1,53 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidload.h */ -/* */ -/* CID-keyed Type1 font loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CIDLOAD_H__ -#define __CIDLOAD_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_STREAM_H -#include "cidparse.h" - - -FT_BEGIN_HEADER - - - typedef struct CID_Loader_ - { - CID_Parser parser; /* parser used to read the stream */ - FT_Int num_chars; /* number of characters in encoding */ - - } CID_Loader; - - - FT_LOCAL( FT_ULong ) - cid_get_offset( FT_Byte** start, - FT_Byte offsize ); - - FT_LOCAL( FT_Error ) - cid_face_open( CID_Face face, - FT_Int face_index ); - - -FT_END_HEADER - -#endif /* __CIDLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/cidobjs.c b/third_party/freetype/src/cid/cidobjs.c deleted file mode 100644 index bf1519bc6e7a1b4a5936161ab76c327e4f94f1a3..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidobjs.c +++ /dev/null @@ -1,492 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidobjs.c */ -/* */ -/* CID objects manager (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H - -#include "cidgload.h" -#include "cidload.h" - -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - -#include "ciderrs.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cidobjs - - - /*************************************************************************/ - /* */ - /* SLOT FUNCTIONS */ - /* */ - /*************************************************************************/ - - FT_LOCAL_DEF( void ) - cid_slot_done( FT_GlyphSlot slot ) - { - slot->internal->glyph_hints = NULL; - } - - - FT_LOCAL_DEF( FT_Error ) - cid_slot_init( FT_GlyphSlot slot ) - { - CID_Face face; - PSHinter_Service pshinter; - - - face = (CID_Face)slot->face; - pshinter = (PSHinter_Service)face->pshinter; - - if ( pshinter ) - { - FT_Module module; - - - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); - if ( module ) - { - T1_Hints_Funcs funcs; - - - funcs = pshinter->get_t1_funcs( module ); - slot->internal->glyph_hints = (void*)funcs; - } - } - - return 0; - } - - - /*************************************************************************/ - /* */ - /* SIZE FUNCTIONS */ - /* */ - /*************************************************************************/ - - - static PSH_Globals_Funcs - cid_size_get_globals_funcs( CID_Size size ) - { - CID_Face face = (CID_Face)size->root.face; - PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; - FT_Module module; - - - module = FT_Get_Module( size->root.face->driver->root.library, - "pshinter" ); - return ( module && pshinter && pshinter->get_globals_funcs ) - ? pshinter->get_globals_funcs( module ) - : 0; - } - - - FT_LOCAL_DEF( void ) - cid_size_done( FT_Size cidsize ) /* CID_Size */ - { - CID_Size size = (CID_Size)cidsize; - - - if ( cidsize->internal ) - { - PSH_Globals_Funcs funcs; - - - funcs = cid_size_get_globals_funcs( size ); - if ( funcs ) - funcs->destroy( (PSH_Globals)cidsize->internal ); - - cidsize->internal = NULL; - } - } - - - FT_LOCAL_DEF( FT_Error ) - cid_size_init( FT_Size cidsize ) /* CID_Size */ - { - CID_Size size = (CID_Size)cidsize; - FT_Error error = FT_Err_Ok; - PSH_Globals_Funcs funcs = cid_size_get_globals_funcs( size ); - - - if ( funcs ) - { - PSH_Globals globals; - CID_Face face = (CID_Face)cidsize->face; - CID_FaceDict dict = face->cid.font_dicts + face->root.face_index; - PS_Private priv = &dict->private_dict; - - - error = funcs->create( cidsize->face->memory, priv, &globals ); - if ( !error ) - cidsize->internal = (FT_Size_Internal)(void*)globals; - } - - return error; - } - - - FT_LOCAL( FT_Error ) - cid_size_request( FT_Size size, - FT_Size_Request req ) - { - PSH_Globals_Funcs funcs; - - - FT_Request_Metrics( size->face, req ); - - funcs = cid_size_get_globals_funcs( (CID_Size)size ); - - if ( funcs ) - funcs->set_scale( (PSH_Globals)size->internal, - size->metrics.x_scale, - size->metrics.y_scale, - 0, 0 ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* FACE FUNCTIONS */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cid_face_done */ - /* */ - /* <Description> */ - /* Finalizes a given face object. */ - /* */ - /* <Input> */ - /* face :: A pointer to the face object to destroy. */ - /* */ - FT_LOCAL_DEF( void ) - cid_face_done( FT_Face cidface ) /* CID_Face */ - { - CID_Face face = (CID_Face)cidface; - FT_Memory memory; - CID_FaceInfo cid; - PS_FontInfo info; - - - if ( !face ) - return; - - cid = &face->cid; - info = &cid->font_info; - memory = cidface->memory; - - /* release subrs */ - if ( face->subrs ) - { - FT_Int n; - - - for ( n = 0; n < cid->num_dicts; n++ ) - { - CID_Subrs subr = face->subrs + n; - - - if ( subr->code ) - { - FT_FREE( subr->code[0] ); - FT_FREE( subr->code ); - } - } - - FT_FREE( face->subrs ); - } - - /* release FontInfo strings */ - FT_FREE( info->version ); - FT_FREE( info->notice ); - FT_FREE( info->full_name ); - FT_FREE( info->family_name ); - FT_FREE( info->weight ); - - /* release font dictionaries */ - FT_FREE( cid->font_dicts ); - cid->num_dicts = 0; - - /* release other strings */ - FT_FREE( cid->cid_font_name ); - FT_FREE( cid->registry ); - FT_FREE( cid->ordering ); - - cidface->family_name = NULL; - cidface->style_name = NULL; - - FT_FREE( face->binary_data ); - FT_FREE( face->cid_stream ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cid_face_init */ - /* */ - /* <Description> */ - /* Initializes a given CID face object. */ - /* */ - /* <Input> */ - /* stream :: The source font stream. */ - /* */ - /* face_index :: The index of the font face in the resource. */ - /* */ - /* num_params :: Number of additional generic parameters. Ignored. */ - /* */ - /* params :: Additional generic parameters. Ignored. */ - /* */ - /* <InOut> */ - /* face :: The newly built face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - cid_face_init( FT_Stream stream, - FT_Face cidface, /* CID_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ) - { - CID_Face face = (CID_Face)cidface; - FT_Error error; - PSAux_Service psaux; - PSHinter_Service pshinter; - - FT_UNUSED( num_params ); - FT_UNUSED( params ); - FT_UNUSED( stream ); - - - cidface->num_faces = 1; - - psaux = (PSAux_Service)face->psaux; - if ( !psaux ) - { - psaux = (PSAux_Service)FT_Get_Module_Interface( - FT_FACE_LIBRARY( face ), "psaux" ); - - if ( !psaux ) - { - FT_ERROR(( "cid_face_init: cannot access `psaux' module\n" )); - error = FT_THROW( Missing_Module ); - goto Exit; - } - - face->psaux = psaux; - } - - pshinter = (PSHinter_Service)face->pshinter; - if ( !pshinter ) - { - pshinter = (PSHinter_Service)FT_Get_Module_Interface( - FT_FACE_LIBRARY( face ), "pshinter" ); - - face->pshinter = pshinter; - } - - FT_TRACE2(( "CID driver\n" )); - - /* open the tokenizer; this will also check the font format */ - if ( FT_STREAM_SEEK( 0 ) ) - goto Exit; - - error = cid_face_open( face, face_index ); - if ( error ) - goto Exit; - - /* if we just wanted to check the format, leave successfully now */ - if ( face_index < 0 ) - goto Exit; - - /* check the face index */ - /* XXX: handle CID fonts with more than a single face */ - if ( ( face_index & 0xFFFF ) != 0 ) - { - FT_ERROR(( "cid_face_init: invalid face index\n" )); - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - /* now load the font program into the face object */ - - /* initialize the face object fields */ - - /* set up root face fields */ - { - CID_FaceInfo cid = &face->cid; - PS_FontInfo info = &cid->font_info; - - - cidface->num_glyphs = (FT_Long)cid->cid_count; - cidface->num_charmaps = 0; - - cidface->face_index = face_index & 0xFFFF; - - cidface->face_flags |= FT_FACE_FLAG_SCALABLE | /* scalable outlines */ - FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ - FT_FACE_FLAG_HINTER; /* has native hinter */ - - if ( info->is_fixed_pitch ) - cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; - - /* XXX: TODO: add kerning with .afm support */ - - /* get style name -- be careful, some broken fonts only */ - /* have a /FontName dictionary entry! */ - cidface->family_name = info->family_name; - /* assume "Regular" style if we don't know better */ - cidface->style_name = (char *)"Regular"; - if ( cidface->family_name ) - { - char* full = info->full_name; - char* family = cidface->family_name; - - - if ( full ) - { - while ( *full ) - { - if ( *full == *family ) - { - family++; - full++; - } - else - { - if ( *full == ' ' || *full == '-' ) - full++; - else if ( *family == ' ' || *family == '-' ) - family++; - else - { - if ( !*family ) - cidface->style_name = full; - break; - } - } - } - } - } - else - { - /* do we have a `/FontName'? */ - if ( cid->cid_font_name ) - cidface->family_name = cid->cid_font_name; - } - - /* compute style flags */ - cidface->style_flags = 0; - if ( info->italic_angle ) - cidface->style_flags |= FT_STYLE_FLAG_ITALIC; - if ( info->weight ) - { - if ( !ft_strcmp( info->weight, "Bold" ) || - !ft_strcmp( info->weight, "Black" ) ) - cidface->style_flags |= FT_STYLE_FLAG_BOLD; - } - - /* no embedded bitmap support */ - cidface->num_fixed_sizes = 0; - cidface->available_sizes = NULL; - - cidface->bbox.xMin = cid->font_bbox.xMin >> 16; - cidface->bbox.yMin = cid->font_bbox.yMin >> 16; - /* no `U' suffix here to 0xFFFF! */ - cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFF ) >> 16; - cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFF ) >> 16; - - if ( !cidface->units_per_EM ) - cidface->units_per_EM = 1000; - - cidface->ascender = (FT_Short)( cidface->bbox.yMax ); - cidface->descender = (FT_Short)( cidface->bbox.yMin ); - - cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 ); - if ( cidface->height < cidface->ascender - cidface->descender ) - cidface->height = (FT_Short)( cidface->ascender - cidface->descender ); - - cidface->underline_position = (FT_Short)info->underline_position; - cidface->underline_thickness = (FT_Short)info->underline_thickness; - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cid_driver_init */ - /* */ - /* <Description> */ - /* Initializes a given CID driver object. */ - /* */ - /* <Input> */ - /* driver :: A handle to the target driver object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - cid_driver_init( FT_Module driver ) - { - FT_UNUSED( driver ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cid_driver_done */ - /* */ - /* <Description> */ - /* Finalizes a given CID driver. */ - /* */ - /* <Input> */ - /* driver :: A handle to the target CID driver. */ - /* */ - FT_LOCAL_DEF( void ) - cid_driver_done( FT_Module driver ) - { - FT_UNUSED( driver ); - } - - -/* END */ diff --git a/third_party/freetype/src/cid/cidobjs.h b/third_party/freetype/src/cid/cidobjs.h deleted file mode 100644 index e9095ca68eb906b64f336fdb0ef53524d4e23afa..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidobjs.h +++ /dev/null @@ -1,154 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidobjs.h */ -/* */ -/* CID objects manager (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CIDOBJS_H__ -#define __CIDOBJS_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_TYPE1_TYPES_H - - -FT_BEGIN_HEADER - - - /* The following structures must be defined by the hinter */ - typedef struct CID_Size_Hints_ CID_Size_Hints; - typedef struct CID_Glyph_Hints_ CID_Glyph_Hints; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CID_Driver */ - /* */ - /* <Description> */ - /* A handle to a Type 1 driver object. */ - /* */ - typedef struct CID_DriverRec_* CID_Driver; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CID_Size */ - /* */ - /* <Description> */ - /* A handle to a Type 1 size object. */ - /* */ - typedef struct CID_SizeRec_* CID_Size; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CID_GlyphSlot */ - /* */ - /* <Description> */ - /* A handle to a Type 1 glyph slot object. */ - /* */ - typedef struct CID_GlyphSlotRec_* CID_GlyphSlot; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CID_CharMap */ - /* */ - /* <Description> */ - /* A handle to a Type 1 character mapping object. */ - /* */ - /* <Note> */ - /* The Type 1 format doesn't use a charmap but an encoding table. */ - /* The driver is responsible for making up charmap objects */ - /* corresponding to these tables. */ - /* */ - typedef struct CID_CharMapRec_* CID_CharMap; - - - /*************************************************************************/ - /* */ - /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */ - /* */ - /*************************************************************************/ - - - typedef struct CID_SizeRec_ - { - FT_SizeRec root; - FT_Bool valid; - - } CID_SizeRec; - - - typedef struct CID_GlyphSlotRec_ - { - FT_GlyphSlotRec root; - - FT_Bool hint; - FT_Bool scaled; - - FT_Fixed x_scale; - FT_Fixed y_scale; - - } CID_GlyphSlotRec; - - - FT_LOCAL( void ) - cid_slot_done( FT_GlyphSlot slot ); - - FT_LOCAL( FT_Error ) - cid_slot_init( FT_GlyphSlot slot ); - - - FT_LOCAL( void ) - cid_size_done( FT_Size size ); /* CID_Size */ - - FT_LOCAL( FT_Error ) - cid_size_init( FT_Size size ); /* CID_Size */ - - FT_LOCAL( FT_Error ) - cid_size_request( FT_Size size, /* CID_Size */ - FT_Size_Request req ); - - FT_LOCAL( FT_Error ) - cid_face_init( FT_Stream stream, - FT_Face face, /* CID_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ); - - FT_LOCAL( void ) - cid_face_done( FT_Face face ); /* CID_Face */ - - - FT_LOCAL( FT_Error ) - cid_driver_init( FT_Module driver ); - - FT_LOCAL( void ) - cid_driver_done( FT_Module driver ); - - -FT_END_HEADER - -#endif /* __CIDOBJS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/cidparse.c b/third_party/freetype/src/cid/cidparse.c deleted file mode 100644 index c276949779b1c5f676fb83289e1b78c3be6da758..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidparse.c +++ /dev/null @@ -1,234 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidparse.c */ -/* */ -/* CID-keyed Type1 parser (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_STREAM_H - -#include "cidparse.h" - -#include "ciderrs.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_cidparse - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** INPUT STREAM PARSER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_LOCAL_DEF( FT_Error ) - cid_parser_new( CID_Parser* parser, - FT_Stream stream, - FT_Memory memory, - PSAux_Service psaux ) - { - FT_Error error; - FT_ULong base_offset, offset, ps_len; - FT_Byte *cur, *limit; - FT_Byte *arg1, *arg2; - - - FT_MEM_ZERO( parser, sizeof ( *parser ) ); - psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); - - parser->stream = stream; - - base_offset = FT_STREAM_POS(); - - /* first of all, check the font format in the header */ - if ( FT_FRAME_ENTER( 31 ) ) - goto Exit; - - if ( ft_strncmp( (char *)stream->cursor, - "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) - { - FT_TRACE2(( " not a CID-keyed font\n" )); - error = FT_THROW( Unknown_File_Format ); - } - - FT_FRAME_EXIT(); - if ( error ) - goto Exit; - - Again: - /* now, read the rest of the file until we find */ - /* `StartData' or `/sfnts' */ - { - FT_Byte buffer[256 + 10]; - FT_ULong read_len = 256 + 10; - FT_Byte* p = buffer; - - - for ( offset = FT_STREAM_POS(); ; offset += 256 ) - { - FT_ULong stream_len; - - - stream_len = stream->size - FT_STREAM_POS(); - if ( stream_len == 0 ) - { - FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - read_len = FT_MIN( read_len, stream_len ); - if ( FT_STREAM_READ( p, read_len ) ) - goto Exit; - - if ( read_len < 256 ) - p[read_len] = '\0'; - - limit = p + read_len - 10; - - for ( p = buffer; p < limit; p++ ) - { - if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) - { - /* save offset of binary data after `StartData' */ - offset += (FT_ULong)( p - buffer + 10 ); - goto Found; - } - else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 ) - { - offset += (FT_ULong)( p - buffer + 7 ); - goto Found; - } - } - - FT_MEM_MOVE( buffer, p, 10 ); - read_len = 256; - p = buffer + 10; - } - } - - Found: - /* We have found the start of the binary data or the `/sfnts' token. */ - /* Now rewind and extract the frame corresponding to this PostScript */ - /* section. */ - - ps_len = offset - base_offset; - if ( FT_STREAM_SEEK( base_offset ) || - FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) - goto Exit; - - parser->data_offset = offset; - parser->postscript_len = ps_len; - parser->root.base = parser->postscript; - parser->root.cursor = parser->postscript; - parser->root.limit = parser->root.cursor + ps_len; - parser->num_dict = -1; - - /* Finally, we check whether `StartData' or `/sfnts' was real -- */ - /* it could be in a comment or string. We also get the arguments */ - /* of `StartData' to find out whether the data is represented in */ - /* binary or hex format. */ - - arg1 = parser->root.cursor; - cid_parser_skip_PS_token( parser ); - cid_parser_skip_spaces ( parser ); - arg2 = parser->root.cursor; - cid_parser_skip_PS_token( parser ); - cid_parser_skip_spaces ( parser ); - - limit = parser->root.limit; - cur = parser->root.cursor; - - while ( cur < limit ) - { - if ( parser->root.error ) - { - error = parser->root.error; - goto Exit; - } - - if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) - { - if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) - { - FT_Long tmp = ft_atol( (const char *)arg2 ); - - - if ( tmp < 0 ) - { - FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); - error = FT_THROW( Invalid_File_Format ); - } - else - parser->binary_length = (FT_ULong)tmp; - } - - goto Exit; - } - else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 ) - { - FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" )); - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - cid_parser_skip_PS_token( parser ); - cid_parser_skip_spaces ( parser ); - arg1 = arg2; - arg2 = cur; - cur = parser->root.cursor; - } - - /* we haven't found the correct `StartData'; go back and continue */ - /* searching */ - FT_FRAME_RELEASE( parser->postscript ); - if ( !FT_STREAM_SEEK( offset ) ) - goto Again; - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - cid_parser_done( CID_Parser* parser ) - { - /* always free the private dictionary */ - if ( parser->postscript ) - { - FT_Stream stream = parser->stream; - - - FT_FRAME_RELEASE( parser->postscript ); - } - parser->root.funcs.done( &parser->root ); - } - - -/* END */ diff --git a/third_party/freetype/src/cid/cidparse.h b/third_party/freetype/src/cid/cidparse.h deleted file mode 100644 index f581bb43ff3892f1a76e5c24aa9b60d1400cea50..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidparse.h +++ /dev/null @@ -1,123 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidparse.h */ -/* */ -/* CID-keyed Type1 parser (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CIDPARSE_H__ -#define __CIDPARSE_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_TYPE1_TYPES_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CID_Parser */ - /* */ - /* <Description> */ - /* A CID_Parser is an object used to parse a Type 1 fonts very */ - /* quickly. */ - /* */ - /* <Fields> */ - /* root :: The root PS_ParserRec fields. */ - /* */ - /* stream :: The current input stream. */ - /* */ - /* postscript :: A pointer to the data to be parsed. */ - /* */ - /* postscript_len :: The length of the data to be parsed. */ - /* */ - /* data_offset :: The start position of the binary data (i.e., the */ - /* end of the data to be parsed. */ - /* */ - /* binary_length :: The length of the data after the `StartData' */ - /* command if the data format is hexadecimal. */ - /* */ - /* cid :: A structure which holds the information about */ - /* the current font. */ - /* */ - /* num_dict :: The number of font dictionaries. */ - /* */ - typedef struct CID_Parser_ - { - PS_ParserRec root; - FT_Stream stream; - - FT_Byte* postscript; - FT_ULong postscript_len; - - FT_ULong data_offset; - - FT_ULong binary_length; - - CID_FaceInfo cid; - FT_Int num_dict; - - } CID_Parser; - - - FT_LOCAL( FT_Error ) - cid_parser_new( CID_Parser* parser, - FT_Stream stream, - FT_Memory memory, - PSAux_Service psaux ); - - FT_LOCAL( void ) - cid_parser_done( CID_Parser* parser ); - - - /*************************************************************************/ - /* */ - /* PARSING ROUTINES */ - /* */ - /*************************************************************************/ - -#define cid_parser_skip_spaces( p ) \ - (p)->root.funcs.skip_spaces( &(p)->root ) -#define cid_parser_skip_PS_token( p ) \ - (p)->root.funcs.skip_PS_token( &(p)->root ) - -#define cid_parser_to_int( p ) (p)->root.funcs.to_int( &(p)->root ) -#define cid_parser_to_fixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t ) - -#define cid_parser_to_coord_array( p, m, c ) \ - (p)->root.funcs.to_coord_array( &(p)->root, m, c ) -#define cid_parser_to_fixed_array( p, m, f, t ) \ - (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t ) -#define cid_parser_to_token( p, t ) \ - (p)->root.funcs.to_token( &(p)->root, t ) -#define cid_parser_to_token_array( p, t, m, c ) \ - (p)->root.funcs.to_token_array( &(p)->root, t, m, c ) - -#define cid_parser_load_field( p, f, o ) \ - (p)->root.funcs.load_field( &(p)->root, f, o, 0, 0 ) -#define cid_parser_load_field_table( p, f, o ) \ - (p)->root.funcs.load_field_table( &(p)->root, f, o, 0, 0 ) - - -FT_END_HEADER - -#endif /* __CIDPARSE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/cidriver.c b/third_party/freetype/src/cid/cidriver.c deleted file mode 100644 index 07c4cc410ba14e3032fe62b45d27e6d6a2343991..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidriver.c +++ /dev/null @@ -1,236 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidriver.c */ -/* */ -/* CID driver interface (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "cidriver.h" -#include "cidgload.h" -#include FT_INTERNAL_DEBUG_H - -#include "ciderrs.h" - -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_FONT_FORMAT_H -#include FT_SERVICE_POSTSCRIPT_INFO_H -#include FT_SERVICE_CID_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ciddriver - - - /* - * POSTSCRIPT NAME SERVICE - * - */ - - static const char* - cid_get_postscript_name( CID_Face face ) - { - const char* result = face->cid.cid_font_name; - - - if ( result && result[0] == '/' ) - result++; - - return result; - } - - - static const FT_Service_PsFontNameRec cid_service_ps_name = - { - (FT_PsName_GetFunc) cid_get_postscript_name - }; - - - /* - * POSTSCRIPT INFO SERVICE - * - */ - - static FT_Error - cid_ps_get_font_info( FT_Face face, - PS_FontInfoRec* afont_info ) - { - *afont_info = ((CID_Face)face)->cid.font_info; - - return FT_Err_Ok; - } - - static FT_Error - cid_ps_get_font_extra( FT_Face face, - PS_FontExtraRec* afont_extra ) - { - *afont_extra = ((CID_Face)face)->font_extra; - - return FT_Err_Ok; - } - - static const FT_Service_PsInfoRec cid_service_ps_info = - { - (PS_GetFontInfoFunc) cid_ps_get_font_info, - (PS_GetFontExtraFunc) cid_ps_get_font_extra, - (PS_HasGlyphNamesFunc) NULL, /* unsupported with CID fonts */ - (PS_GetFontPrivateFunc)NULL, /* unsupported */ - (PS_GetFontValueFunc) NULL /* not implemented */ - }; - - - /* - * CID INFO SERVICE - * - */ - static FT_Error - cid_get_ros( CID_Face face, - const char* *registry, - const char* *ordering, - FT_Int *supplement ) - { - CID_FaceInfo cid = &face->cid; - - - if ( registry ) - *registry = cid->registry; - - if ( ordering ) - *ordering = cid->ordering; - - if ( supplement ) - *supplement = cid->supplement; - - return FT_Err_Ok; - } - - - static FT_Error - cid_get_is_cid( CID_Face face, - FT_Bool *is_cid ) - { - FT_Error error = FT_Err_Ok; - FT_UNUSED( face ); - - - if ( is_cid ) - *is_cid = 1; /* cid driver is only used for CID keyed fonts */ - - return error; - } - - - static FT_Error - cid_get_cid_from_glyph_index( CID_Face face, - FT_UInt glyph_index, - FT_UInt *cid ) - { - FT_Error error = FT_Err_Ok; - FT_UNUSED( face ); - - - if ( cid ) - *cid = glyph_index; /* identity mapping */ - - return error; - } - - - static const FT_Service_CIDRec cid_service_cid_info = - { - (FT_CID_GetRegistryOrderingSupplementFunc)cid_get_ros, - (FT_CID_GetIsInternallyCIDKeyedFunc) cid_get_is_cid, - (FT_CID_GetCIDFromGlyphIndexFunc) cid_get_cid_from_glyph_index - }; - - - /* - * SERVICE LIST - * - */ - - static const FT_ServiceDescRec cid_services[] = - { - { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CID }, - { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cid_service_ps_name }, - { FT_SERVICE_ID_POSTSCRIPT_INFO, &cid_service_ps_info }, - { FT_SERVICE_ID_CID, &cid_service_cid_info }, - { NULL, NULL } - }; - - - FT_CALLBACK_DEF( FT_Module_Interface ) - cid_get_interface( FT_Module module, - const char* cid_interface ) - { - FT_UNUSED( module ); - - return ft_service_list_lookup( cid_services, cid_interface ); - } - - - - FT_CALLBACK_TABLE_DEF - const FT_Driver_ClassRec t1cid_driver_class = - { - /* first of all, the FT_Module_Class fields */ - { - FT_MODULE_FONT_DRIVER | - FT_MODULE_DRIVER_SCALABLE | - FT_MODULE_DRIVER_HAS_HINTER, - - sizeof ( FT_DriverRec ), - "t1cid", /* module name */ - 0x10000L, /* version 1.0 of driver */ - 0x20000L, /* requires FreeType 2.0 */ - - 0, - - cid_driver_init, - cid_driver_done, - cid_get_interface - }, - - /* then the other font drivers fields */ - sizeof ( CID_FaceRec ), - sizeof ( CID_SizeRec ), - sizeof ( CID_GlyphSlotRec ), - - cid_face_init, - cid_face_done, - - cid_size_init, - cid_size_done, - cid_slot_init, - cid_slot_done, - - cid_slot_load_glyph, - - 0, /* FT_Face_GetKerningFunc */ - 0, /* FT_Face_AttachFunc */ - - 0, /* FT_Face_GetAdvancesFunc */ - - cid_size_request, - 0 /* FT_Size_SelectFunc */ - }; - - -/* END */ diff --git a/third_party/freetype/src/cid/cidriver.h b/third_party/freetype/src/cid/cidriver.h deleted file mode 100644 index e5b8678464d241122a1b994ed0145d88b89dae91..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidriver.h +++ /dev/null @@ -1,43 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidriver.h */ -/* */ -/* High-level CID driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __CIDRIVER_H__ -#define __CIDRIVER_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_DRIVER_H - - -FT_BEGIN_HEADER - -#ifdef FT_CONFIG_OPTION_PIC -#error "this module does not support PIC yet" -#endif - - - FT_CALLBACK_TABLE - const FT_Driver_ClassRec t1cid_driver_class; - - -FT_END_HEADER - -#endif /* __CIDRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/cid/cidtoken.h b/third_party/freetype/src/cid/cidtoken.h deleted file mode 100644 index 82eae0ca6b0df3e0e90308cd4bf49b7b83d2cd3e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/cidtoken.h +++ /dev/null @@ -1,112 +0,0 @@ -/***************************************************************************/ -/* */ -/* cidtoken.h */ -/* */ -/* CID token definitions (specification only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#undef FT_STRUCTURE -#define FT_STRUCTURE CID_FaceInfoRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_CID_INFO - - T1_FIELD_KEY ( "CIDFontName", cid_font_name, 0 ) - T1_FIELD_FIXED ( "CIDFontVersion", cid_version, 0 ) - T1_FIELD_NUM ( "CIDFontType", cid_font_type, 0 ) - T1_FIELD_STRING( "Registry", registry, 0 ) - T1_FIELD_STRING( "Ordering", ordering, 0 ) - T1_FIELD_NUM ( "Supplement", supplement, 0 ) - T1_FIELD_NUM ( "UIDBase", uid_base, 0 ) - T1_FIELD_NUM ( "CIDMapOffset", cidmap_offset, 0 ) - T1_FIELD_NUM ( "FDBytes", fd_bytes, 0 ) - T1_FIELD_NUM ( "GDBytes", gd_bytes, 0 ) - T1_FIELD_NUM ( "CIDCount", cid_count, 0 ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_FontInfoRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FONT_INFO - - T1_FIELD_STRING( "version", version, 0 ) - T1_FIELD_STRING( "Notice", notice, 0 ) - T1_FIELD_STRING( "FullName", full_name, 0 ) - T1_FIELD_STRING( "FamilyName", family_name, 0 ) - T1_FIELD_STRING( "Weight", weight, 0 ) - T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 ) - T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 ) - T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 ) - T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 ) - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_FontExtraRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FONT_EXTRA - - T1_FIELD_NUM ( "FSType", fs_type, 0 ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE CID_FaceDictRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FONT_DICT - - T1_FIELD_NUM ( "PaintType", paint_type, 0 ) - T1_FIELD_NUM ( "FontType", font_type, 0 ) - T1_FIELD_NUM ( "SubrMapOffset", subrmap_offset, 0 ) - T1_FIELD_NUM ( "SDBytes", sd_bytes, 0 ) - T1_FIELD_NUM ( "SubrCount", num_subrs, 0 ) - T1_FIELD_NUM ( "lenBuildCharArray", len_buildchar, 0 ) - T1_FIELD_FIXED( "ForceBoldThreshold", forcebold_threshold, 0 ) - T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_PrivateRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_PRIVATE - - T1_FIELD_NUM ( "UniqueID", unique_id, 0 ) - T1_FIELD_NUM ( "lenIV", lenIV, 0 ) - T1_FIELD_NUM ( "LanguageGroup", language_group, 0 ) - T1_FIELD_NUM ( "password", password, 0 ) - - T1_FIELD_FIXED_1000( "BlueScale", blue_scale, 0 ) - T1_FIELD_NUM ( "BlueShift", blue_shift, 0 ) - T1_FIELD_NUM ( "BlueFuzz", blue_fuzz, 0 ) - - T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14, 0 ) - T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10, 0 ) - T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14, 0 ) - T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, 0 ) - - T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1, 0 ) - T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1, 0 ) - T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2, 0 ) - - T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12, 0 ) - T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12, 0 ) - - T1_FIELD_BOOL ( "ForceBold", force_bold, 0 ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE FT_BBox -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_BBOX - - T1_FIELD_BBOX( "FontBBox", xMin, 0 ) - - -/* END */ diff --git a/third_party/freetype/src/cid/type1cid.c b/third_party/freetype/src/cid/type1cid.c deleted file mode 100644 index 0d54ca7f44fc5039ba200ccb40078fb626af5623..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/cid/type1cid.c +++ /dev/null @@ -1,29 +0,0 @@ -/***************************************************************************/ -/* */ -/* type1cid.c */ -/* */ -/* FreeType OpenType driver component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "cidparse.c" -#include "cidload.c" -#include "cidobjs.c" -#include "cidriver.c" -#include "cidgload.c" - - -/* END */ diff --git a/third_party/freetype/src/psaux/Jamfile b/third_party/freetype/src/psaux/Jamfile deleted file mode 100644 index 6793f0d5816104d1cedfafa7d6962f5c67870d8b..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/Jamfile +++ /dev/null @@ -1,35 +0,0 @@ -# FreeType 2 src/psaux Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) psaux ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = afmparse - psauxmod - psconv - psobjs - t1cmap - t1decode - ; - } - else - { - _sources = psaux ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/psaux Jamfile diff --git a/third_party/freetype/src/psaux/afmparse.c b/third_party/freetype/src/psaux/afmparse.c deleted file mode 100644 index 3ad44ec7240fe4c376daeee1f3ce79c6440c2636..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/afmparse.c +++ /dev/null @@ -1,977 +0,0 @@ -/***************************************************************************/ -/* */ -/* afmparse.c */ -/* */ -/* AFM parser (body). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H - -#include "afmparse.h" -#include "psconv.h" - -#include "psauxerr.h" - - -/***************************************************************************/ -/* */ -/* AFM_Stream */ -/* */ -/* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */ -/* */ -/* */ - - enum - { - AFM_STREAM_STATUS_NORMAL, - AFM_STREAM_STATUS_EOC, - AFM_STREAM_STATUS_EOL, - AFM_STREAM_STATUS_EOF - }; - - - typedef struct AFM_StreamRec_ - { - FT_Byte* cursor; - FT_Byte* base; - FT_Byte* limit; - - FT_Int status; - - } AFM_StreamRec; - - -#ifndef EOF -#define EOF -1 -#endif - - - /* this works because empty lines are ignored */ -#define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' ) - -#define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' ) -#define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' ) - - /* column separator; there is no `column' in the spec actually */ -#define AFM_IS_SEP( ch ) ( (ch) == ';' ) - -#define AFM_GETC() \ - ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \ - : EOF ) - -#define AFM_STREAM_KEY_BEGIN( stream ) \ - (char*)( (stream)->cursor - 1 ) - -#define AFM_STREAM_KEY_LEN( stream, key ) \ - (FT_Offset)( (char*)(stream)->cursor - key - 1 ) - -#define AFM_STATUS_EOC( stream ) \ - ( (stream)->status >= AFM_STREAM_STATUS_EOC ) - -#define AFM_STATUS_EOL( stream ) \ - ( (stream)->status >= AFM_STREAM_STATUS_EOL ) - -#define AFM_STATUS_EOF( stream ) \ - ( (stream)->status >= AFM_STREAM_STATUS_EOF ) - - - static int - afm_stream_skip_spaces( AFM_Stream stream ) - { - int ch = 0; /* make stupid compiler happy */ - - - if ( AFM_STATUS_EOC( stream ) ) - return ';'; - - while ( 1 ) - { - ch = AFM_GETC(); - if ( !AFM_IS_SPACE( ch ) ) - break; - } - - if ( AFM_IS_NEWLINE( ch ) ) - stream->status = AFM_STREAM_STATUS_EOL; - else if ( AFM_IS_SEP( ch ) ) - stream->status = AFM_STREAM_STATUS_EOC; - else if ( AFM_IS_EOF( ch ) ) - stream->status = AFM_STREAM_STATUS_EOF; - - return ch; - } - - - /* read a key or value in current column */ - static char* - afm_stream_read_one( AFM_Stream stream ) - { - char* str; - - - afm_stream_skip_spaces( stream ); - if ( AFM_STATUS_EOC( stream ) ) - return NULL; - - str = AFM_STREAM_KEY_BEGIN( stream ); - - while ( 1 ) - { - int ch = AFM_GETC(); - - - if ( AFM_IS_SPACE( ch ) ) - break; - else if ( AFM_IS_NEWLINE( ch ) ) - { - stream->status = AFM_STREAM_STATUS_EOL; - break; - } - else if ( AFM_IS_SEP( ch ) ) - { - stream->status = AFM_STREAM_STATUS_EOC; - break; - } - else if ( AFM_IS_EOF( ch ) ) - { - stream->status = AFM_STREAM_STATUS_EOF; - break; - } - } - - return str; - } - - - /* read a string (i.e., read to EOL) */ - static char* - afm_stream_read_string( AFM_Stream stream ) - { - char* str; - - - afm_stream_skip_spaces( stream ); - if ( AFM_STATUS_EOL( stream ) ) - return NULL; - - str = AFM_STREAM_KEY_BEGIN( stream ); - - /* scan to eol */ - while ( 1 ) - { - int ch = AFM_GETC(); - - - if ( AFM_IS_NEWLINE( ch ) ) - { - stream->status = AFM_STREAM_STATUS_EOL; - break; - } - else if ( AFM_IS_EOF( ch ) ) - { - stream->status = AFM_STREAM_STATUS_EOF; - break; - } - } - - return str; - } - - - /*************************************************************************/ - /* */ - /* AFM_Parser */ - /* */ - /* */ - - /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */ - typedef enum AFM_Token_ - { - AFM_TOKEN_ASCENDER, - AFM_TOKEN_AXISLABEL, - AFM_TOKEN_AXISTYPE, - AFM_TOKEN_B, - AFM_TOKEN_BLENDAXISTYPES, - AFM_TOKEN_BLENDDESIGNMAP, - AFM_TOKEN_BLENDDESIGNPOSITIONS, - AFM_TOKEN_C, - AFM_TOKEN_CC, - AFM_TOKEN_CH, - AFM_TOKEN_CAPHEIGHT, - AFM_TOKEN_CHARWIDTH, - AFM_TOKEN_CHARACTERSET, - AFM_TOKEN_CHARACTERS, - AFM_TOKEN_DESCENDER, - AFM_TOKEN_ENCODINGSCHEME, - AFM_TOKEN_ENDAXIS, - AFM_TOKEN_ENDCHARMETRICS, - AFM_TOKEN_ENDCOMPOSITES, - AFM_TOKEN_ENDDIRECTION, - AFM_TOKEN_ENDFONTMETRICS, - AFM_TOKEN_ENDKERNDATA, - AFM_TOKEN_ENDKERNPAIRS, - AFM_TOKEN_ENDTRACKKERN, - AFM_TOKEN_ESCCHAR, - AFM_TOKEN_FAMILYNAME, - AFM_TOKEN_FONTBBOX, - AFM_TOKEN_FONTNAME, - AFM_TOKEN_FULLNAME, - AFM_TOKEN_ISBASEFONT, - AFM_TOKEN_ISCIDFONT, - AFM_TOKEN_ISFIXEDPITCH, - AFM_TOKEN_ISFIXEDV, - AFM_TOKEN_ITALICANGLE, - AFM_TOKEN_KP, - AFM_TOKEN_KPH, - AFM_TOKEN_KPX, - AFM_TOKEN_KPY, - AFM_TOKEN_L, - AFM_TOKEN_MAPPINGSCHEME, - AFM_TOKEN_METRICSSETS, - AFM_TOKEN_N, - AFM_TOKEN_NOTICE, - AFM_TOKEN_PCC, - AFM_TOKEN_STARTAXIS, - AFM_TOKEN_STARTCHARMETRICS, - AFM_TOKEN_STARTCOMPOSITES, - AFM_TOKEN_STARTDIRECTION, - AFM_TOKEN_STARTFONTMETRICS, - AFM_TOKEN_STARTKERNDATA, - AFM_TOKEN_STARTKERNPAIRS, - AFM_TOKEN_STARTKERNPAIRS0, - AFM_TOKEN_STARTKERNPAIRS1, - AFM_TOKEN_STARTTRACKKERN, - AFM_TOKEN_STDHW, - AFM_TOKEN_STDVW, - AFM_TOKEN_TRACKKERN, - AFM_TOKEN_UNDERLINEPOSITION, - AFM_TOKEN_UNDERLINETHICKNESS, - AFM_TOKEN_VV, - AFM_TOKEN_VVECTOR, - AFM_TOKEN_VERSION, - AFM_TOKEN_W, - AFM_TOKEN_W0, - AFM_TOKEN_W0X, - AFM_TOKEN_W0Y, - AFM_TOKEN_W1, - AFM_TOKEN_W1X, - AFM_TOKEN_W1Y, - AFM_TOKEN_WX, - AFM_TOKEN_WY, - AFM_TOKEN_WEIGHT, - AFM_TOKEN_WEIGHTVECTOR, - AFM_TOKEN_XHEIGHT, - N_AFM_TOKENS, - AFM_TOKEN_UNKNOWN - - } AFM_Token; - - - static const char* const afm_key_table[N_AFM_TOKENS] = - { - "Ascender", - "AxisLabel", - "AxisType", - "B", - "BlendAxisTypes", - "BlendDesignMap", - "BlendDesignPositions", - "C", - "CC", - "CH", - "CapHeight", - "CharWidth", - "CharacterSet", - "Characters", - "Descender", - "EncodingScheme", - "EndAxis", - "EndCharMetrics", - "EndComposites", - "EndDirection", - "EndFontMetrics", - "EndKernData", - "EndKernPairs", - "EndTrackKern", - "EscChar", - "FamilyName", - "FontBBox", - "FontName", - "FullName", - "IsBaseFont", - "IsCIDFont", - "IsFixedPitch", - "IsFixedV", - "ItalicAngle", - "KP", - "KPH", - "KPX", - "KPY", - "L", - "MappingScheme", - "MetricsSets", - "N", - "Notice", - "PCC", - "StartAxis", - "StartCharMetrics", - "StartComposites", - "StartDirection", - "StartFontMetrics", - "StartKernData", - "StartKernPairs", - "StartKernPairs0", - "StartKernPairs1", - "StartTrackKern", - "StdHW", - "StdVW", - "TrackKern", - "UnderlinePosition", - "UnderlineThickness", - "VV", - "VVector", - "Version", - "W", - "W0", - "W0X", - "W0Y", - "W1", - "W1X", - "W1Y", - "WX", - "WY", - "Weight", - "WeightVector", - "XHeight" - }; - - - /* - * `afm_parser_read_vals' and `afm_parser_next_key' provide - * high-level operations to an AFM_Stream. The rest of the - * parser functions should use them without accessing the - * AFM_Stream directly. - */ - - FT_LOCAL_DEF( FT_Int ) - afm_parser_read_vals( AFM_Parser parser, - AFM_Value vals, - FT_Int n ) - { - AFM_Stream stream = parser->stream; - char* str; - FT_Int i; - - - if ( n > AFM_MAX_ARGUMENTS ) - return 0; - - for ( i = 0; i < n; i++ ) - { - FT_Offset len; - AFM_Value val = vals + i; - - - if ( val->type == AFM_VALUE_TYPE_STRING ) - str = afm_stream_read_string( stream ); - else - str = afm_stream_read_one( stream ); - - if ( !str ) - break; - - len = AFM_STREAM_KEY_LEN( stream, str ); - - switch ( val->type ) - { - case AFM_VALUE_TYPE_STRING: - case AFM_VALUE_TYPE_NAME: - { - FT_Memory memory = parser->memory; - FT_Error error; - - - if ( !FT_QALLOC( val->u.s, len + 1 ) ) - { - ft_memcpy( val->u.s, str, len ); - val->u.s[len] = '\0'; - } - } - break; - - case AFM_VALUE_TYPE_FIXED: - val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str, - (FT_Byte*)str + len, 0 ); - break; - - case AFM_VALUE_TYPE_INTEGER: - val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str, - (FT_Byte*)str + len ); - break; - - case AFM_VALUE_TYPE_BOOL: - val->u.b = FT_BOOL( len == 4 && - !ft_strncmp( str, "true", 4 ) ); - break; - - case AFM_VALUE_TYPE_INDEX: - if ( parser->get_index ) - val->u.i = parser->get_index( str, len, parser->user_data ); - else - val->u.i = 0; - break; - } - } - - return i; - } - - - FT_LOCAL_DEF( char* ) - afm_parser_next_key( AFM_Parser parser, - FT_Bool line, - FT_Offset* len ) - { - AFM_Stream stream = parser->stream; - char* key = NULL; /* make stupid compiler happy */ - - - if ( line ) - { - while ( 1 ) - { - /* skip current line */ - if ( !AFM_STATUS_EOL( stream ) ) - afm_stream_read_string( stream ); - - stream->status = AFM_STREAM_STATUS_NORMAL; - key = afm_stream_read_one( stream ); - - /* skip empty line */ - if ( !key && - !AFM_STATUS_EOF( stream ) && - AFM_STATUS_EOL( stream ) ) - continue; - - break; - } - } - else - { - while ( 1 ) - { - /* skip current column */ - while ( !AFM_STATUS_EOC( stream ) ) - afm_stream_read_one( stream ); - - stream->status = AFM_STREAM_STATUS_NORMAL; - key = afm_stream_read_one( stream ); - - /* skip empty column */ - if ( !key && - !AFM_STATUS_EOF( stream ) && - AFM_STATUS_EOC( stream ) ) - continue; - - break; - } - } - - if ( len ) - *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key ) - : 0; - - return key; - } - - - static AFM_Token - afm_tokenize( const char* key, - FT_Offset len ) - { - int n; - - - for ( n = 0; n < N_AFM_TOKENS; n++ ) - { - if ( *( afm_key_table[n] ) == *key ) - { - for ( ; n < N_AFM_TOKENS; n++ ) - { - if ( *( afm_key_table[n] ) != *key ) - return AFM_TOKEN_UNKNOWN; - - if ( ft_strncmp( afm_key_table[n], key, len ) == 0 ) - return (AFM_Token) n; - } - } - } - - return AFM_TOKEN_UNKNOWN; - } - - - FT_LOCAL_DEF( FT_Error ) - afm_parser_init( AFM_Parser parser, - FT_Memory memory, - FT_Byte* base, - FT_Byte* limit ) - { - AFM_Stream stream = NULL; - FT_Error error; - - - if ( FT_NEW( stream ) ) - return error; - - stream->cursor = stream->base = base; - stream->limit = limit; - - /* don't skip the first line during the first call */ - stream->status = AFM_STREAM_STATUS_EOL; - - parser->memory = memory; - parser->stream = stream; - parser->FontInfo = NULL; - parser->get_index = NULL; - - return FT_Err_Ok; - } - - - FT_LOCAL( void ) - afm_parser_done( AFM_Parser parser ) - { - FT_Memory memory = parser->memory; - - - FT_FREE( parser->stream ); - } - - - static FT_Error - afm_parser_read_int( AFM_Parser parser, - FT_Int* aint ) - { - AFM_ValueRec val; - - - val.type = AFM_VALUE_TYPE_INTEGER; - - if ( afm_parser_read_vals( parser, &val, 1 ) == 1 ) - { - *aint = val.u.i; - - return FT_Err_Ok; - } - else - return FT_THROW( Syntax_Error ); - } - - - static FT_Error - afm_parse_track_kern( AFM_Parser parser ) - { - AFM_FontInfo fi = parser->FontInfo; - AFM_TrackKern tk; - char* key; - FT_Offset len; - int n = -1; - FT_Int tmp; - - - if ( afm_parser_read_int( parser, &tmp ) ) - goto Fail; - - if ( tmp < 0 ) - goto Fail; - - fi->NumTrackKern = (FT_UInt)tmp; - - if ( fi->NumTrackKern ) - { - FT_Memory memory = parser->memory; - FT_Error error; - - - if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) ) - return error; - } - - while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) - { - AFM_ValueRec shared_vals[5]; - - - switch ( afm_tokenize( key, len ) ) - { - case AFM_TOKEN_TRACKKERN: - n++; - - if ( n >= (int)fi->NumTrackKern ) - goto Fail; - - tk = fi->TrackKerns + n; - - shared_vals[0].type = AFM_VALUE_TYPE_INTEGER; - shared_vals[1].type = AFM_VALUE_TYPE_FIXED; - shared_vals[2].type = AFM_VALUE_TYPE_FIXED; - shared_vals[3].type = AFM_VALUE_TYPE_FIXED; - shared_vals[4].type = AFM_VALUE_TYPE_FIXED; - if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 ) - goto Fail; - - tk->degree = shared_vals[0].u.i; - tk->min_ptsize = shared_vals[1].u.f; - tk->min_kern = shared_vals[2].u.f; - tk->max_ptsize = shared_vals[3].u.f; - tk->max_kern = shared_vals[4].u.f; - - break; - - case AFM_TOKEN_ENDTRACKKERN: - case AFM_TOKEN_ENDKERNDATA: - case AFM_TOKEN_ENDFONTMETRICS: - fi->NumTrackKern = (FT_UInt)( n + 1 ); - return FT_Err_Ok; - - case AFM_TOKEN_UNKNOWN: - break; - - default: - goto Fail; - } - } - - Fail: - return FT_THROW( Syntax_Error ); - } - - -#undef KERN_INDEX -#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) - - - /* compare two kerning pairs */ - FT_CALLBACK_DEF( int ) - afm_compare_kern_pairs( const void* a, - const void* b ) - { - AFM_KernPair kp1 = (AFM_KernPair)a; - AFM_KernPair kp2 = (AFM_KernPair)b; - - FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 ); - FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 ); - - - if ( index1 > index2 ) - return 1; - else if ( index1 < index2 ) - return -1; - else - return 0; - } - - - static FT_Error - afm_parse_kern_pairs( AFM_Parser parser ) - { - AFM_FontInfo fi = parser->FontInfo; - AFM_KernPair kp; - char* key; - FT_Offset len; - int n = -1; - FT_Int tmp; - - - if ( afm_parser_read_int( parser, &tmp ) ) - goto Fail; - - if ( tmp < 0 ) - goto Fail; - - fi->NumKernPair = (FT_UInt)tmp; - - if ( fi->NumKernPair ) - { - FT_Memory memory = parser->memory; - FT_Error error; - - - if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) - return error; - } - - while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) - { - AFM_Token token = afm_tokenize( key, len ); - - - switch ( token ) - { - case AFM_TOKEN_KP: - case AFM_TOKEN_KPX: - case AFM_TOKEN_KPY: - { - FT_Int r; - AFM_ValueRec shared_vals[4]; - - - n++; - - if ( n >= (int)fi->NumKernPair ) - goto Fail; - - kp = fi->KernPairs + n; - - shared_vals[0].type = AFM_VALUE_TYPE_INDEX; - shared_vals[1].type = AFM_VALUE_TYPE_INDEX; - shared_vals[2].type = AFM_VALUE_TYPE_INTEGER; - shared_vals[3].type = AFM_VALUE_TYPE_INTEGER; - r = afm_parser_read_vals( parser, shared_vals, 4 ); - if ( r < 3 ) - goto Fail; - - /* index values can't be negative */ - kp->index1 = shared_vals[0].u.u; - kp->index2 = shared_vals[1].u.u; - if ( token == AFM_TOKEN_KPY ) - { - kp->x = 0; - kp->y = shared_vals[2].u.i; - } - else - { - kp->x = shared_vals[2].u.i; - kp->y = ( token == AFM_TOKEN_KP && r == 4 ) - ? shared_vals[3].u.i : 0; - } - } - break; - - case AFM_TOKEN_ENDKERNPAIRS: - case AFM_TOKEN_ENDKERNDATA: - case AFM_TOKEN_ENDFONTMETRICS: - fi->NumKernPair = (FT_UInt)( n + 1 ); - ft_qsort( fi->KernPairs, fi->NumKernPair, - sizeof ( AFM_KernPairRec ), - afm_compare_kern_pairs ); - return FT_Err_Ok; - - case AFM_TOKEN_UNKNOWN: - break; - - default: - goto Fail; - } - } - - Fail: - return FT_THROW( Syntax_Error ); - } - - - static FT_Error - afm_parse_kern_data( AFM_Parser parser ) - { - FT_Error error; - char* key; - FT_Offset len; - - - while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) - { - switch ( afm_tokenize( key, len ) ) - { - case AFM_TOKEN_STARTTRACKKERN: - error = afm_parse_track_kern( parser ); - if ( error ) - return error; - break; - - case AFM_TOKEN_STARTKERNPAIRS: - case AFM_TOKEN_STARTKERNPAIRS0: - error = afm_parse_kern_pairs( parser ); - if ( error ) - return error; - break; - - case AFM_TOKEN_ENDKERNDATA: - case AFM_TOKEN_ENDFONTMETRICS: - return FT_Err_Ok; - - case AFM_TOKEN_UNKNOWN: - break; - - default: - goto Fail; - } - } - - Fail: - return FT_THROW( Syntax_Error ); - } - - - static FT_Error - afm_parser_skip_section( AFM_Parser parser, - FT_Int n, - AFM_Token end_section ) - { - char* key; - FT_Offset len; - - - while ( n-- > 0 ) - { - key = afm_parser_next_key( parser, 1, NULL ); - if ( !key ) - goto Fail; - } - - while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) - { - AFM_Token token = afm_tokenize( key, len ); - - - if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS ) - return FT_Err_Ok; - } - - Fail: - return FT_THROW( Syntax_Error ); - } - - - FT_LOCAL_DEF( FT_Error ) - afm_parser_parse( AFM_Parser parser ) - { - FT_Memory memory = parser->memory; - AFM_FontInfo fi = parser->FontInfo; - FT_Error error = FT_ERR( Syntax_Error ); - char* key; - FT_Offset len; - FT_Int metrics_sets = 0; - - - if ( !fi ) - return FT_THROW( Invalid_Argument ); - - key = afm_parser_next_key( parser, 1, &len ); - if ( !key || len != 16 || - ft_strncmp( key, "StartFontMetrics", 16 ) != 0 ) - return FT_THROW( Unknown_File_Format ); - - while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) - { - AFM_ValueRec shared_vals[4]; - - - switch ( afm_tokenize( key, len ) ) - { - case AFM_TOKEN_METRICSSETS: - if ( afm_parser_read_int( parser, &metrics_sets ) ) - goto Fail; - - if ( metrics_sets != 0 && metrics_sets != 2 ) - { - error = FT_THROW( Unimplemented_Feature ); - - goto Fail; - } - break; - - case AFM_TOKEN_ISCIDFONT: - shared_vals[0].type = AFM_VALUE_TYPE_BOOL; - if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) - goto Fail; - - fi->IsCIDFont = shared_vals[0].u.b; - break; - - case AFM_TOKEN_FONTBBOX: - shared_vals[0].type = AFM_VALUE_TYPE_FIXED; - shared_vals[1].type = AFM_VALUE_TYPE_FIXED; - shared_vals[2].type = AFM_VALUE_TYPE_FIXED; - shared_vals[3].type = AFM_VALUE_TYPE_FIXED; - if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 ) - goto Fail; - - fi->FontBBox.xMin = shared_vals[0].u.f; - fi->FontBBox.yMin = shared_vals[1].u.f; - fi->FontBBox.xMax = shared_vals[2].u.f; - fi->FontBBox.yMax = shared_vals[3].u.f; - break; - - case AFM_TOKEN_ASCENDER: - shared_vals[0].type = AFM_VALUE_TYPE_FIXED; - if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) - goto Fail; - - fi->Ascender = shared_vals[0].u.f; - break; - - case AFM_TOKEN_DESCENDER: - shared_vals[0].type = AFM_VALUE_TYPE_FIXED; - if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) - goto Fail; - - fi->Descender = shared_vals[0].u.f; - break; - - case AFM_TOKEN_STARTCHARMETRICS: - { - FT_Int n = 0; - - - if ( afm_parser_read_int( parser, &n ) ) - goto Fail; - - error = afm_parser_skip_section( parser, n, - AFM_TOKEN_ENDCHARMETRICS ); - if ( error ) - return error; - } - break; - - case AFM_TOKEN_STARTKERNDATA: - error = afm_parse_kern_data( parser ); - if ( error ) - goto Fail; - /* fall through since we only support kern data */ - - case AFM_TOKEN_ENDFONTMETRICS: - return FT_Err_Ok; - - default: - break; - } - } - - Fail: - FT_FREE( fi->TrackKerns ); - fi->NumTrackKern = 0; - - FT_FREE( fi->KernPairs ); - fi->NumKernPair = 0; - - fi->IsCIDFont = 0; - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/psaux/afmparse.h b/third_party/freetype/src/psaux/afmparse.h deleted file mode 100644 index f922c4ebde6523f32a44a0e50ea75dfd973ddd65..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/afmparse.h +++ /dev/null @@ -1,89 +0,0 @@ -/***************************************************************************/ -/* */ -/* afmparse.h */ -/* */ -/* AFM parser (specification). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __AFMPARSE_H__ -#define __AFMPARSE_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_AUX_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - afm_parser_init( AFM_Parser parser, - FT_Memory memory, - FT_Byte* base, - FT_Byte* limit ); - - - FT_LOCAL( void ) - afm_parser_done( AFM_Parser parser ); - - - FT_LOCAL( FT_Error ) - afm_parser_parse( AFM_Parser parser ); - - - enum AFM_ValueType_ - { - AFM_VALUE_TYPE_STRING, - AFM_VALUE_TYPE_NAME, - AFM_VALUE_TYPE_FIXED, /* real number */ - AFM_VALUE_TYPE_INTEGER, - AFM_VALUE_TYPE_BOOL, - AFM_VALUE_TYPE_INDEX /* glyph index */ - }; - - - typedef struct AFM_ValueRec_ - { - enum AFM_ValueType_ type; - union - { - char* s; - FT_Fixed f; - FT_Int i; - FT_UInt u; - FT_Bool b; - - } u; - - } AFM_ValueRec, *AFM_Value; - -#define AFM_MAX_ARGUMENTS 5 - - FT_LOCAL( FT_Int ) - afm_parser_read_vals( AFM_Parser parser, - AFM_Value vals, - FT_Int n ); - - /* read the next key from the next line or column */ - FT_LOCAL( char* ) - afm_parser_next_key( AFM_Parser parser, - FT_Bool line, - FT_Offset* len ); - -FT_END_HEADER - -#endif /* __AFMPARSE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psaux/psaux.c b/third_party/freetype/src/psaux/psaux.c deleted file mode 100644 index 7f1d9aa59507aabf03b7c84d6239635c947b42a7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psaux.c +++ /dev/null @@ -1,34 +0,0 @@ -/***************************************************************************/ -/* */ -/* psaux.c */ -/* */ -/* FreeType auxiliary PostScript driver component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "psobjs.c" -#include "psauxmod.c" -#include "t1decode.c" -#include "t1cmap.c" - -#ifndef T1_CONFIG_OPTION_NO_AFM -#include "afmparse.c" -#endif - -#include "psconv.c" - - -/* END */ diff --git a/third_party/freetype/src/psaux/psauxerr.h b/third_party/freetype/src/psaux/psauxerr.h deleted file mode 100644 index 97712f0795b3e50411d02bb34bb4cbd5223b1c14..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psauxerr.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* psauxerr.h */ -/* */ -/* PS auxiliary module error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the PS auxiliary module error enumeration */ - /* constants. */ - /* */ - /*************************************************************************/ - -#ifndef __PSAUXERR_H__ -#define __PSAUXERR_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX PSaux_Err_ -#define FT_ERR_BASE FT_Mod_Err_PSaux - -#include FT_ERRORS_H - -#endif /* __PSAUXERR_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psaux/psauxmod.c b/third_party/freetype/src/psaux/psauxmod.c deleted file mode 100644 index 06fcab0c4ac5ab68c696bd91d633970f03c5976c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psauxmod.c +++ /dev/null @@ -1,139 +0,0 @@ -/***************************************************************************/ -/* */ -/* psauxmod.c */ -/* */ -/* FreeType auxiliary PostScript module implementation (body). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "psauxmod.h" -#include "psobjs.h" -#include "t1decode.h" -#include "t1cmap.h" - -#ifndef T1_CONFIG_OPTION_NO_AFM -#include "afmparse.h" -#endif - - - FT_CALLBACK_TABLE_DEF - const PS_Table_FuncsRec ps_table_funcs = - { - ps_table_new, - ps_table_done, - ps_table_add, - ps_table_release - }; - - - FT_CALLBACK_TABLE_DEF - const PS_Parser_FuncsRec ps_parser_funcs = - { - ps_parser_init, - ps_parser_done, - ps_parser_skip_spaces, - ps_parser_skip_PS_token, - ps_parser_to_int, - ps_parser_to_fixed, - ps_parser_to_bytes, - ps_parser_to_coord_array, - ps_parser_to_fixed_array, - ps_parser_to_token, - ps_parser_to_token_array, - ps_parser_load_field, - ps_parser_load_field_table - }; - - - FT_CALLBACK_TABLE_DEF - const T1_Builder_FuncsRec t1_builder_funcs = - { - t1_builder_init, - t1_builder_done, - t1_builder_check_points, - t1_builder_add_point, - t1_builder_add_point1, - t1_builder_add_contour, - t1_builder_start_point, - t1_builder_close_contour - }; - - - FT_CALLBACK_TABLE_DEF - const T1_Decoder_FuncsRec t1_decoder_funcs = - { - t1_decoder_init, - t1_decoder_done, - t1_decoder_parse_charstrings - }; - - -#ifndef T1_CONFIG_OPTION_NO_AFM - FT_CALLBACK_TABLE_DEF - const AFM_Parser_FuncsRec afm_parser_funcs = - { - afm_parser_init, - afm_parser_done, - afm_parser_parse - }; -#endif - - - FT_CALLBACK_TABLE_DEF - const T1_CMap_ClassesRec t1_cmap_classes = - { - &t1_cmap_standard_class_rec, - &t1_cmap_expert_class_rec, - &t1_cmap_custom_class_rec, - &t1_cmap_unicode_class_rec - }; - - - static - const PSAux_Interface psaux_interface = - { - &ps_table_funcs, - &ps_parser_funcs, - &t1_builder_funcs, - &t1_decoder_funcs, - t1_decrypt, - - (const T1_CMap_ClassesRec*) &t1_cmap_classes, - -#ifndef T1_CONFIG_OPTION_NO_AFM - &afm_parser_funcs, -#else - 0, -#endif - }; - - - FT_CALLBACK_TABLE_DEF - const FT_Module_Class psaux_module_class = - { - 0, - sizeof ( FT_ModuleRec ), - "psaux", - 0x20000L, - 0x20000L, - - &psaux_interface, /* module-specific interface */ - - (FT_Module_Constructor)0, - (FT_Module_Destructor) 0, - (FT_Module_Requester) 0 - }; - - -/* END */ diff --git a/third_party/freetype/src/psaux/psauxmod.h b/third_party/freetype/src/psaux/psauxmod.h deleted file mode 100644 index ae6a8f9383a2e1050c9bf589853db8efc2d5d190..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psauxmod.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* psauxmod.h */ -/* */ -/* FreeType auxiliary PostScript module implementation (specification). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSAUXMOD_H__ -#define __PSAUXMOD_H__ - - -#include <ft2build.h> -#include FT_MODULE_H - - -FT_BEGIN_HEADER - -#ifdef FT_CONFIG_OPTION_PIC -#error "this module does not support PIC yet" -#endif - - - FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class; - - -FT_END_HEADER - -#endif /* __PSAUXMOD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psaux/psconv.c b/third_party/freetype/src/psaux/psconv.c deleted file mode 100644 index aca741204fb40576562457aa39ebefcacc68faf9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psconv.c +++ /dev/null @@ -1,603 +0,0 @@ -/***************************************************************************/ -/* */ -/* psconv.c */ -/* */ -/* Some convenience conversions (body). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_AUX_H -#include FT_INTERNAL_DEBUG_H - -#include "psconv.h" -#include "psauxerr.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_psconv - - - /* The following array is used by various functions to quickly convert */ - /* digits (both decimal and non-decimal) into numbers. */ - -#if 'A' == 65 - /* ASCII */ - - static const FT_Char ft_char_table[128] = - { - /* 0x00 */ - -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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, - }; - - /* no character >= 0x80 can represent a valid number */ -#define OP >= - -#endif /* 'A' == 65 */ - -#if 'A' == 193 - /* EBCDIC */ - - static const FT_Char ft_char_table[128] = - { - /* 0x80 */ - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, - -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, - -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, - -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, - -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - }; - - /* no character < 0x80 can represent a valid number */ -#define OP < - -#endif /* 'A' == 193 */ - - - FT_LOCAL_DEF( FT_Long ) - PS_Conv_Strtol( FT_Byte** cursor, - FT_Byte* limit, - FT_Long base ) - { - FT_Byte* p = *cursor; - - FT_Long num = 0; - FT_Bool sign = 0; - FT_Bool have_overflow = 0; - - FT_Long num_limit; - FT_Char c_limit; - - - if ( p >= limit ) - goto Bad; - - if ( base < 2 || base > 36 ) - { - FT_TRACE4(( "!!!INVALID BASE:!!!" )); - return 0; - } - - if ( *p == '-' || *p == '+' ) - { - sign = FT_BOOL( *p == '-' ); - - p++; - if ( p == limit ) - goto Bad; - } - - num_limit = 0x7FFFFFFFL / base; - c_limit = (FT_Char)( 0x7FFFFFFFL % base ); - - for ( ; p < limit; p++ ) - { - FT_Char c; - - - if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) - break; - - c = ft_char_table[*p & 0x7F]; - - if ( c < 0 || c >= base ) - break; - - if ( num > num_limit || ( num == num_limit && c > c_limit ) ) - have_overflow = 1; - else - num = num * base + c; - } - - *cursor = p; - - if ( have_overflow ) - { - num = 0x7FFFFFFFL; - FT_TRACE4(( "!!!OVERFLOW:!!!" )); - } - - if ( sign ) - num = -num; - - return num; - - Bad: - FT_TRACE4(( "!!!END OF DATA:!!!" )); - return 0; - } - - - FT_LOCAL_DEF( FT_Long ) - PS_Conv_ToInt( FT_Byte** cursor, - FT_Byte* limit ) - - { - FT_Byte* p = *cursor; - FT_Byte* curp; - - FT_Long num; - - - curp = p; - num = PS_Conv_Strtol( &p, limit, 10 ); - - if ( p == curp ) - return 0; - - if ( p < limit && *p == '#' ) - { - p++; - - curp = p; - num = PS_Conv_Strtol( &p, limit, num ); - - if ( p == curp ) - return 0; - } - - *cursor = p; - - return num; - } - - - FT_LOCAL_DEF( FT_Fixed ) - PS_Conv_ToFixed( FT_Byte** cursor, - FT_Byte* limit, - FT_Long power_ten ) - { - FT_Byte* p = *cursor; - FT_Byte* curp; - - FT_Fixed integral = 0; - FT_Long decimal = 0; - FT_Long divider = 1; - - FT_Bool sign = 0; - FT_Bool have_overflow = 0; - FT_Bool have_underflow = 0; - - - if ( p >= limit ) - goto Bad; - - if ( *p == '-' || *p == '+' ) - { - sign = FT_BOOL( *p == '-' ); - - p++; - if ( p == limit ) - goto Bad; - } - - /* read the integer part */ - if ( *p != '.' ) - { - curp = p; - integral = PS_Conv_ToInt( &p, limit ); - - if ( p == curp ) - return 0; - - if ( integral > 0x7FFF ) - have_overflow = 1; - else - integral = (FT_Fixed)( (FT_UInt32)integral << 16 ); - } - - /* read the decimal part */ - if ( p < limit && *p == '.' ) - { - p++; - - for ( ; p < limit; p++ ) - { - FT_Char c; - - - if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) - break; - - c = ft_char_table[*p & 0x7F]; - - if ( c < 0 || c >= 10 ) - break; - - /* only add digit if we don't overflow */ - if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL ) - { - decimal = decimal * 10 + c; - - if ( !integral && power_ten > 0 ) - power_ten--; - else - divider *= 10; - } - } - } - - /* read exponent, if any */ - if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) ) - { - FT_Long exponent; - - - p++; - - curp = p; - exponent = PS_Conv_ToInt( &p, limit ); - - if ( curp == p ) - return 0; - - /* arbitrarily limit exponent */ - if ( exponent > 1000 ) - have_overflow = 1; - else if ( exponent < -1000 ) - have_underflow = 1; - else - power_ten += exponent; - } - - *cursor = p; - - if ( !integral && !decimal ) - return 0; - - if ( have_overflow ) - goto Overflow; - if ( have_underflow ) - goto Underflow; - - while ( power_ten > 0 ) - { - if ( integral >= 0xCCCCCCCL ) - goto Overflow; - integral *= 10; - - if ( decimal >= 0xCCCCCCCL ) - { - if ( divider == 1 ) - goto Overflow; - divider /= 10; - } - else - decimal *= 10; - - power_ten--; - } - - while ( power_ten < 0 ) - { - integral /= 10; - if ( divider < 0xCCCCCCCL ) - divider *= 10; - else - decimal /= 10; - - if ( !integral && !decimal ) - goto Underflow; - - power_ten++; - } - - if ( decimal ) - { - decimal = FT_DivFix( decimal, divider ); - /* it's not necessary to check this addition for overflow */ - /* due to the structure of the real number representation */ - integral += decimal; - } - - Exit: - if ( sign ) - integral = -integral; - - return integral; - - Bad: - FT_TRACE4(( "!!!END OF DATA:!!!" )); - return 0; - - Overflow: - integral = 0x7FFFFFFFL; - FT_TRACE4(( "!!!OVERFLOW:!!!" )); - goto Exit; - - Underflow: - FT_TRACE4(( "!!!UNDERFLOW:!!!" )); - return 0; - } - - -#if 0 - FT_LOCAL_DEF( FT_UInt ) - PS_Conv_StringDecode( FT_Byte** cursor, - FT_Byte* limit, - FT_Byte* buffer, - FT_Offset n ) - { - FT_Byte* p; - FT_UInt r = 0; - - - for ( p = *cursor; r < n && p < limit; p++ ) - { - FT_Byte b; - - - if ( *p != '\\' ) - { - buffer[r++] = *p; - - continue; - } - - p++; - - switch ( *p ) - { - case 'n': - b = '\n'; - break; - case 'r': - b = '\r'; - break; - case 't': - b = '\t'; - break; - case 'b': - b = '\b'; - break; - case 'f': - b = '\f'; - break; - case '\r': - p++; - if ( *p != '\n' ) - { - b = *p; - - break; - } - /* no break */ - case '\n': - continue; - break; - default: - if ( IS_PS_DIGIT( *p ) ) - { - b = *p - '0'; - - p++; - - if ( IS_PS_DIGIT( *p ) ) - { - b = b * 8 + *p - '0'; - - p++; - - if ( IS_PS_DIGIT( *p ) ) - b = b * 8 + *p - '0'; - else - { - buffer[r++] = b; - b = *p; - } - } - else - { - buffer[r++] = b; - b = *p; - } - } - else - b = *p; - break; - } - - buffer[r++] = b; - } - - *cursor = p; - - return r; - } -#endif /* 0 */ - - - FT_LOCAL_DEF( FT_UInt ) - PS_Conv_ASCIIHexDecode( FT_Byte** cursor, - FT_Byte* limit, - FT_Byte* buffer, - FT_Offset n ) - { - FT_Byte* p; - FT_UInt r = 0; - FT_UInt w = 0; - FT_UInt pad = 0x01; - - - n *= 2; - -#if 1 - - p = *cursor; - - if ( p >= limit ) - return 0; - - if ( n > (FT_UInt)( limit - p ) ) - n = (FT_UInt)( limit - p ); - - /* we try to process two nibbles at a time to be as fast as possible */ - for ( ; r < n; r++ ) - { - FT_UInt c = p[r]; - - - if ( IS_PS_SPACE( c ) ) - continue; - - if ( c OP 0x80 ) - break; - - c = (FT_UInt)ft_char_table[c & 0x7F]; - if ( c >= 16 ) - break; - - pad = ( pad << 4 ) | c; - if ( pad & 0x100 ) - { - buffer[w++] = (FT_Byte)pad; - pad = 0x01; - } - } - - if ( pad != 0x01 ) - buffer[w++] = (FT_Byte)( pad << 4 ); - - *cursor = p + r; - - return w; - -#else /* 0 */ - - for ( r = 0; r < n; r++ ) - { - FT_Char c; - - - if ( IS_PS_SPACE( *p ) ) - continue; - - if ( *p OP 0x80 ) - break; - - c = ft_char_table[*p & 0x7F]; - - if ( (unsigned)c >= 16 ) - break; - - if ( r & 1 ) - { - *buffer = (FT_Byte)(*buffer + c); - buffer++; - } - else - *buffer = (FT_Byte)(c << 4); - - r++; - } - - *cursor = p; - - return ( r + 1 ) / 2; - -#endif /* 0 */ - - } - - - FT_LOCAL_DEF( FT_UInt ) - PS_Conv_EexecDecode( FT_Byte** cursor, - FT_Byte* limit, - FT_Byte* buffer, - FT_Offset n, - FT_UShort* seed ) - { - FT_Byte* p; - FT_UInt r; - FT_UInt s = *seed; - - -#if 1 - - p = *cursor; - - if ( p >= limit ) - return 0; - - if ( n > (FT_UInt)(limit - p) ) - n = (FT_UInt)(limit - p); - - for ( r = 0; r < n; r++ ) - { - FT_UInt val = p[r]; - FT_UInt b = ( val ^ ( s >> 8 ) ); - - - s = ( (val + s)*52845U + 22719 ) & 0xFFFFU; - buffer[r] = (FT_Byte) b; - } - - *cursor = p + n; - *seed = (FT_UShort)s; - -#else /* 0 */ - - for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ ) - { - FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) ); - - - s = (FT_UShort)( ( *p + s ) * 52845U + 22719 ); - *buffer++ = b; - } - *cursor = p; - *seed = s; - -#endif /* 0 */ - - return r; - } - - -/* END */ diff --git a/third_party/freetype/src/psaux/psconv.h b/third_party/freetype/src/psaux/psconv.h deleted file mode 100644 index 10f1ff7fb1a9b9ea9a12dc46197998c5a45018f5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psconv.h +++ /dev/null @@ -1,71 +0,0 @@ -/***************************************************************************/ -/* */ -/* psconv.h */ -/* */ -/* Some convenience conversions (specification). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSCONV_H__ -#define __PSCONV_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_AUX_H - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Long ) - PS_Conv_Strtol( FT_Byte** cursor, - FT_Byte* limit, - FT_Long base ); - - - FT_LOCAL( FT_Long ) - PS_Conv_ToInt( FT_Byte** cursor, - FT_Byte* limit ); - - FT_LOCAL( FT_Fixed ) - PS_Conv_ToFixed( FT_Byte** cursor, - FT_Byte* limit, - FT_Long power_ten ); - -#if 0 - FT_LOCAL( FT_UInt ) - PS_Conv_StringDecode( FT_Byte** cursor, - FT_Byte* limit, - FT_Byte* buffer, - FT_Offset n ); -#endif - - FT_LOCAL( FT_UInt ) - PS_Conv_ASCIIHexDecode( FT_Byte** cursor, - FT_Byte* limit, - FT_Byte* buffer, - FT_Offset n ); - - FT_LOCAL( FT_UInt ) - PS_Conv_EexecDecode( FT_Byte** cursor, - FT_Byte* limit, - FT_Byte* buffer, - FT_Offset n, - FT_UShort* seed ); - - -FT_END_HEADER - -#endif /* __PSCONV_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psaux/psobjs.c b/third_party/freetype/src/psaux/psobjs.c deleted file mode 100644 index 1d3c7e662cefdb2286024b91efb478ed90722c4e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psobjs.c +++ /dev/null @@ -1,1774 +0,0 @@ -/***************************************************************************/ -/* */ -/* psobjs.c */ -/* */ -/* Auxiliary functions for PostScript fonts (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_AUX_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H - -#include "psobjs.h" -#include "psconv.h" - -#include "psauxerr.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_psobjs - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PS_TABLE *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ps_table_new */ - /* */ - /* <Description> */ - /* Initializes a PS_Table. */ - /* */ - /* <InOut> */ - /* table :: The address of the target table. */ - /* */ - /* <Input> */ - /* count :: The table size = the maximum number of elements. */ - /* */ - /* memory :: The memory object to use for all subsequent */ - /* reallocations. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - ps_table_new( PS_Table table, - FT_Int count, - FT_Memory memory ) - { - FT_Error error; - - - table->memory = memory; - if ( FT_NEW_ARRAY( table->elements, count ) || - FT_NEW_ARRAY( table->lengths, count ) ) - goto Exit; - - table->max_elems = count; - table->init = 0xDEADBEEFUL; - table->num_elems = 0; - table->block = NULL; - table->capacity = 0; - table->cursor = 0; - - *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs; - - Exit: - if ( error ) - FT_FREE( table->elements ); - - return error; - } - - - static void - shift_elements( PS_Table table, - FT_Byte* old_base ) - { - FT_PtrDist delta = table->block - old_base; - FT_Byte** offset = table->elements; - FT_Byte** limit = offset + table->max_elems; - - - for ( ; offset < limit; offset++ ) - { - if ( offset[0] ) - offset[0] += delta; - } - } - - - static FT_Error - reallocate_t1_table( PS_Table table, - FT_Offset new_size ) - { - FT_Memory memory = table->memory; - FT_Byte* old_base = table->block; - FT_Error error; - - - /* allocate new base block */ - if ( FT_ALLOC( table->block, new_size ) ) - { - table->block = old_base; - return error; - } - - /* copy elements and shift offsets */ - if ( old_base ) - { - FT_MEM_COPY( table->block, old_base, table->capacity ); - shift_elements( table, old_base ); - FT_FREE( old_base ); - } - - table->capacity = new_size; - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ps_table_add */ - /* */ - /* <Description> */ - /* Adds an object to a PS_Table, possibly growing its memory block. */ - /* */ - /* <InOut> */ - /* table :: The target table. */ - /* */ - /* <Input> */ - /* idx :: The index of the object in the table. */ - /* */ - /* object :: The address of the object to copy in memory. */ - /* */ - /* length :: The length in bytes of the source object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. An error is returned if a */ - /* reallocation fails. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - ps_table_add( PS_Table table, - FT_Int idx, - void* object, - FT_UInt length ) - { - if ( idx < 0 || idx >= table->max_elems ) - { - FT_ERROR(( "ps_table_add: invalid index\n" )); - return FT_THROW( Invalid_Argument ); - } - - /* grow the base block if needed */ - if ( table->cursor + length > table->capacity ) - { - FT_Error error; - FT_Offset new_size = table->capacity; - FT_PtrDist in_offset; - - - in_offset = (FT_Byte*)object - table->block; - if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity ) - in_offset = -1; - - while ( new_size < table->cursor + length ) - { - /* increase size by 25% and round up to the nearest multiple - of 1024 */ - new_size += ( new_size >> 2 ) + 1; - new_size = FT_PAD_CEIL( new_size, 1024 ); - } - - error = reallocate_t1_table( table, new_size ); - if ( error ) - return error; - - if ( in_offset >= 0 ) - object = table->block + in_offset; - } - - /* add the object to the base block and adjust offset */ - table->elements[idx] = table->block + table->cursor; - table->lengths [idx] = length; - FT_MEM_COPY( table->block + table->cursor, object, length ); - - table->cursor += length; - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ps_table_done */ - /* */ - /* <Description> */ - /* Finalizes a PS_TableRec (i.e., reallocate it to its current */ - /* cursor). */ - /* */ - /* <InOut> */ - /* table :: The target table. */ - /* */ - /* <Note> */ - /* This function does NOT release the heap's memory block. It is up */ - /* to the caller to clean it, or reference it in its own structures. */ - /* */ - FT_LOCAL_DEF( void ) - ps_table_done( PS_Table table ) - { - FT_Memory memory = table->memory; - FT_Error error; - FT_Byte* old_base = table->block; - - - /* should never fail, because rec.cursor <= rec.size */ - if ( !old_base ) - return; - - if ( FT_ALLOC( table->block, table->cursor ) ) - return; - FT_MEM_COPY( table->block, old_base, table->cursor ); - shift_elements( table, old_base ); - - table->capacity = table->cursor; - FT_FREE( old_base ); - - FT_UNUSED( error ); - } - - - FT_LOCAL_DEF( void ) - ps_table_release( PS_Table table ) - { - FT_Memory memory = table->memory; - - - if ( (FT_ULong)table->init == 0xDEADBEEFUL ) - { - FT_FREE( table->block ); - FT_FREE( table->elements ); - FT_FREE( table->lengths ); - table->init = 0; - } - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 PARSER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /* first character must be already part of the comment */ - - static void - skip_comment( FT_Byte* *acur, - FT_Byte* limit ) - { - FT_Byte* cur = *acur; - - - while ( cur < limit ) - { - if ( IS_PS_NEWLINE( *cur ) ) - break; - cur++; - } - - *acur = cur; - } - - - static void - skip_spaces( FT_Byte* *acur, - FT_Byte* limit ) - { - FT_Byte* cur = *acur; - - - while ( cur < limit ) - { - if ( !IS_PS_SPACE( *cur ) ) - { - if ( *cur == '%' ) - /* According to the PLRM, a comment is equal to a space. */ - skip_comment( &cur, limit ); - else - break; - } - cur++; - } - - *acur = cur; - } - - -#define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' ) - - - /* first character must be `('; */ - /* *acur is positioned at the character after the closing `)' */ - - static FT_Error - skip_literal_string( FT_Byte* *acur, - FT_Byte* limit ) - { - FT_Byte* cur = *acur; - FT_Int embed = 0; - FT_Error error = FT_ERR( Invalid_File_Format ); - unsigned int i; - - - while ( cur < limit ) - { - FT_Byte c = *cur; - - - ++cur; - - if ( c == '\\' ) - { - /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */ - /* A backslash can introduce three different types */ - /* of escape sequences: */ - /* - a special escaped char like \r, \n, etc. */ - /* - a one-, two-, or three-digit octal number */ - /* - none of the above in which case the backslash is ignored */ - - if ( cur == limit ) - /* error (or to be ignored?) */ - break; - - switch ( *cur ) - { - /* skip `special' escape */ - case 'n': - case 'r': - case 't': - case 'b': - case 'f': - case '\\': - case '(': - case ')': - ++cur; - break; - - default: - /* skip octal escape or ignore backslash */ - for ( i = 0; i < 3 && cur < limit; ++i ) - { - if ( !IS_OCTAL_DIGIT( *cur ) ) - break; - - ++cur; - } - } - } - else if ( c == '(' ) - embed++; - else if ( c == ')' ) - { - embed--; - if ( embed == 0 ) - { - error = FT_Err_Ok; - break; - } - } - } - - *acur = cur; - - return error; - } - - - /* first character must be `<' */ - - static FT_Error - skip_string( FT_Byte* *acur, - FT_Byte* limit ) - { - FT_Byte* cur = *acur; - FT_Error err = FT_Err_Ok; - - - while ( ++cur < limit ) - { - /* All whitespace characters are ignored. */ - skip_spaces( &cur, limit ); - if ( cur >= limit ) - break; - - if ( !IS_PS_XDIGIT( *cur ) ) - break; - } - - if ( cur < limit && *cur != '>' ) - { - FT_ERROR(( "skip_string: missing closing delimiter `>'\n" )); - err = FT_THROW( Invalid_File_Format ); - } - else - cur++; - - *acur = cur; - return err; - } - - - /* first character must be the opening brace that */ - /* starts the procedure */ - - /* NB: [ and ] need not match: */ - /* `/foo {[} def' is a valid PostScript fragment, */ - /* even within a Type1 font */ - - static FT_Error - skip_procedure( FT_Byte* *acur, - FT_Byte* limit ) - { - FT_Byte* cur; - FT_Int embed = 0; - FT_Error error = FT_Err_Ok; - - - FT_ASSERT( **acur == '{' ); - - for ( cur = *acur; cur < limit && error == FT_Err_Ok; ++cur ) - { - switch ( *cur ) - { - case '{': - ++embed; - break; - - case '}': - --embed; - if ( embed == 0 ) - { - ++cur; - goto end; - } - break; - - case '(': - error = skip_literal_string( &cur, limit ); - break; - - case '<': - error = skip_string( &cur, limit ); - break; - - case '%': - skip_comment( &cur, limit ); - break; - } - } - - end: - if ( embed != 0 ) - error = FT_THROW( Invalid_File_Format ); - - *acur = cur; - - return error; - } - - - /***********************************************************************/ - /* */ - /* All exported parsing routines handle leading whitespace and stop at */ - /* the first character which isn't part of the just handled token. */ - /* */ - /***********************************************************************/ - - - FT_LOCAL_DEF( void ) - ps_parser_skip_PS_token( PS_Parser parser ) - { - /* Note: PostScript allows any non-delimiting, non-whitespace */ - /* character in a name (PS Ref Manual, 3rd ed, p31). */ - /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */ - - FT_Byte* cur = parser->cursor; - FT_Byte* limit = parser->limit; - FT_Error error = FT_Err_Ok; - - - skip_spaces( &cur, limit ); /* this also skips comments */ - if ( cur >= limit ) - goto Exit; - - /* self-delimiting, single-character tokens */ - if ( *cur == '[' || *cur == ']' ) - { - cur++; - goto Exit; - } - - /* skip balanced expressions (procedures and strings) */ - - if ( *cur == '{' ) /* {...} */ - { - error = skip_procedure( &cur, limit ); - goto Exit; - } - - if ( *cur == '(' ) /* (...) */ - { - error = skip_literal_string( &cur, limit ); - goto Exit; - } - - if ( *cur == '<' ) /* <...> */ - { - if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ - { - cur++; - cur++; - } - else - error = skip_string( &cur, limit ); - - goto Exit; - } - - if ( *cur == '>' ) - { - cur++; - if ( cur >= limit || *cur != '>' ) /* >> */ - { - FT_ERROR(( "ps_parser_skip_PS_token:" - " unexpected closing delimiter `>'\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - cur++; - goto Exit; - } - - if ( *cur == '/' ) - cur++; - - /* anything else */ - while ( cur < limit ) - { - /* *cur might be invalid (e.g., ')' or '}'), but this */ - /* is handled by the test `cur == parser->cursor' below */ - if ( IS_PS_DELIM( *cur ) ) - break; - - cur++; - } - - Exit: - if ( cur < limit && cur == parser->cursor ) - { - FT_ERROR(( "ps_parser_skip_PS_token:" - " current token is `%c' which is self-delimiting\n" - " " - " but invalid at this point\n", - *cur )); - - error = FT_THROW( Invalid_File_Format ); - } - - if ( cur > limit ) - cur = limit; - - parser->error = error; - parser->cursor = cur; - } - - - FT_LOCAL_DEF( void ) - ps_parser_skip_spaces( PS_Parser parser ) - { - skip_spaces( &parser->cursor, parser->limit ); - } - - - /* `token' here means either something between balanced delimiters */ - /* or the next token; the delimiters are not removed. */ - - FT_LOCAL_DEF( void ) - ps_parser_to_token( PS_Parser parser, - T1_Token token ) - { - FT_Byte* cur; - FT_Byte* limit; - FT_Int embed; - - - token->type = T1_TOKEN_TYPE_NONE; - token->start = NULL; - token->limit = NULL; - - /* first of all, skip leading whitespace */ - ps_parser_skip_spaces( parser ); - - cur = parser->cursor; - limit = parser->limit; - - if ( cur >= limit ) - return; - - switch ( *cur ) - { - /************* check for literal string *****************/ - case '(': - token->type = T1_TOKEN_TYPE_STRING; - token->start = cur; - - if ( skip_literal_string( &cur, limit ) == FT_Err_Ok ) - token->limit = cur; - break; - - /************* check for programs/array *****************/ - case '{': - token->type = T1_TOKEN_TYPE_ARRAY; - token->start = cur; - - if ( skip_procedure( &cur, limit ) == FT_Err_Ok ) - token->limit = cur; - break; - - /************* check for table/array ********************/ - /* XXX: in theory we should also look for "<<" */ - /* since this is semantically equivalent to "["; */ - /* in practice it doesn't matter (?) */ - case '[': - token->type = T1_TOKEN_TYPE_ARRAY; - embed = 1; - token->start = cur++; - - /* we need this to catch `[ ]' */ - parser->cursor = cur; - ps_parser_skip_spaces( parser ); - cur = parser->cursor; - - while ( cur < limit && !parser->error ) - { - /* XXX: this is wrong because it does not */ - /* skip comments, procedures, and strings */ - if ( *cur == '[' ) - embed++; - else if ( *cur == ']' ) - { - embed--; - if ( embed <= 0 ) - { - token->limit = ++cur; - break; - } - } - - parser->cursor = cur; - ps_parser_skip_PS_token( parser ); - /* we need this to catch `[XXX ]' */ - ps_parser_skip_spaces ( parser ); - cur = parser->cursor; - } - break; - - /* ************ otherwise, it is any token **************/ - default: - token->start = cur; - token->type = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY ); - ps_parser_skip_PS_token( parser ); - cur = parser->cursor; - if ( !parser->error ) - token->limit = cur; - } - - if ( !token->limit ) - { - token->start = NULL; - token->type = T1_TOKEN_TYPE_NONE; - } - - parser->cursor = cur; - } - - - /* NB: `tokens' can be NULL if we only want to count */ - /* the number of array elements */ - - FT_LOCAL_DEF( void ) - ps_parser_to_token_array( PS_Parser parser, - T1_Token tokens, - FT_UInt max_tokens, - FT_Int* pnum_tokens ) - { - T1_TokenRec master; - - - *pnum_tokens = -1; - - /* this also handles leading whitespace */ - ps_parser_to_token( parser, &master ); - - if ( master.type == T1_TOKEN_TYPE_ARRAY ) - { - FT_Byte* old_cursor = parser->cursor; - FT_Byte* old_limit = parser->limit; - T1_Token cur = tokens; - T1_Token limit = cur + max_tokens; - - - /* don't include outermost delimiters */ - parser->cursor = master.start + 1; - parser->limit = master.limit - 1; - - while ( parser->cursor < parser->limit ) - { - T1_TokenRec token; - - - ps_parser_to_token( parser, &token ); - if ( !token.type ) - break; - - if ( tokens != NULL && cur < limit ) - *cur = token; - - cur++; - } - - *pnum_tokens = (FT_Int)( cur - tokens ); - - parser->cursor = old_cursor; - parser->limit = old_limit; - } - } - - - /* first character must be a delimiter or a part of a number */ - /* NB: `coords' can be NULL if we just want to skip the */ - /* array; in this case we ignore `max_coords' */ - - static FT_Int - ps_tocoordarray( FT_Byte* *acur, - FT_Byte* limit, - FT_Int max_coords, - FT_Short* coords ) - { - FT_Byte* cur = *acur; - FT_Int count = 0; - FT_Byte c, ender; - - - if ( cur >= limit ) - goto Exit; - - /* check for the beginning of an array; otherwise, only one number */ - /* will be read */ - c = *cur; - ender = 0; - - if ( c == '[' ) - ender = ']'; - else if ( c == '{' ) - ender = '}'; - - if ( ender ) - cur++; - - /* now, read the coordinates */ - while ( cur < limit ) - { - FT_Short dummy; - FT_Byte* old_cur; - - - /* skip whitespace in front of data */ - skip_spaces( &cur, limit ); - if ( cur >= limit ) - goto Exit; - - if ( *cur == ender ) - { - cur++; - break; - } - - old_cur = cur; - - if ( coords != NULL && count >= max_coords ) - break; - - /* call PS_Conv_ToFixed() even if coords == NULL */ - /* to properly parse number at `cur' */ - *( coords != NULL ? &coords[count] : &dummy ) = - (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 ); - - if ( old_cur == cur ) - { - count = -1; - goto Exit; - } - else - count++; - - if ( !ender ) - break; - } - - Exit: - *acur = cur; - return count; - } - - - /* first character must be a delimiter or a part of a number */ - /* NB: `values' can be NULL if we just want to skip the */ - /* array; in this case we ignore `max_values' */ - /* */ - /* return number of successfully parsed values */ - - static FT_Int - ps_tofixedarray( FT_Byte* *acur, - FT_Byte* limit, - FT_Int max_values, - FT_Fixed* values, - FT_Int power_ten ) - { - FT_Byte* cur = *acur; - FT_Int count = 0; - FT_Byte c, ender; - - - if ( cur >= limit ) - goto Exit; - - /* Check for the beginning of an array. Otherwise, only one number */ - /* will be read. */ - c = *cur; - ender = 0; - - if ( c == '[' ) - ender = ']'; - else if ( c == '{' ) - ender = '}'; - - if ( ender ) - cur++; - - /* now, read the values */ - while ( cur < limit ) - { - FT_Fixed dummy; - FT_Byte* old_cur; - - - /* skip whitespace in front of data */ - skip_spaces( &cur, limit ); - if ( cur >= limit ) - goto Exit; - - if ( *cur == ender ) - { - cur++; - break; - } - - old_cur = cur; - - if ( values != NULL && count >= max_values ) - break; - - /* call PS_Conv_ToFixed() even if coords == NULL */ - /* to properly parse number at `cur' */ - *( values != NULL ? &values[count] : &dummy ) = - PS_Conv_ToFixed( &cur, limit, power_ten ); - - if ( old_cur == cur ) - { - count = -1; - goto Exit; - } - else - count++; - - if ( !ender ) - break; - } - - Exit: - *acur = cur; - return count; - } - - -#if 0 - - static FT_String* - ps_tostring( FT_Byte** cursor, - FT_Byte* limit, - FT_Memory memory ) - { - FT_Byte* cur = *cursor; - FT_UInt len = 0; - FT_Int count; - FT_String* result; - FT_Error error; - - - /* XXX: some stupid fonts have a `Notice' or `Copyright' string */ - /* that simply doesn't begin with an opening parenthesis, even */ - /* though they have a closing one! E.g. "amuncial.pfb" */ - /* */ - /* We must deal with these ill-fated cases there. Note that */ - /* these fonts didn't work with the old Type 1 driver as the */ - /* notice/copyright was not recognized as a valid string token */ - /* and made the old token parser commit errors. */ - - while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) ) - cur++; - if ( cur + 1 >= limit ) - return 0; - - if ( *cur == '(' ) - cur++; /* skip the opening parenthesis, if there is one */ - - *cursor = cur; - count = 0; - - /* then, count its length */ - for ( ; cur < limit; cur++ ) - { - if ( *cur == '(' ) - count++; - - else if ( *cur == ')' ) - { - count--; - if ( count < 0 ) - break; - } - } - - len = (FT_UInt)( cur - *cursor ); - if ( cur >= limit || FT_ALLOC( result, len + 1 ) ) - return 0; - - /* now copy the string */ - FT_MEM_COPY( result, *cursor, len ); - result[len] = '\0'; - *cursor = cur; - return result; - } - -#endif /* 0 */ - - - static int - ps_tobool( FT_Byte* *acur, - FT_Byte* limit ) - { - FT_Byte* cur = *acur; - FT_Bool result = 0; - - - /* return 1 if we find `true', 0 otherwise */ - if ( cur + 3 < limit && - cur[0] == 't' && - cur[1] == 'r' && - cur[2] == 'u' && - cur[3] == 'e' ) - { - result = 1; - cur += 5; - } - else if ( cur + 4 < limit && - cur[0] == 'f' && - cur[1] == 'a' && - cur[2] == 'l' && - cur[3] == 's' && - cur[4] == 'e' ) - { - result = 0; - cur += 6; - } - - *acur = cur; - return result; - } - - - /* load a simple field (i.e. non-table) into the current list of objects */ - - FT_LOCAL_DEF( FT_Error ) - ps_parser_load_field( PS_Parser parser, - const T1_Field field, - void** objects, - FT_UInt max_objects, - FT_ULong* pflags ) - { - T1_TokenRec token; - FT_Byte* cur; - FT_Byte* limit; - FT_UInt count; - FT_UInt idx; - FT_Error error; - T1_FieldType type; - - - /* this also skips leading whitespace */ - ps_parser_to_token( parser, &token ); - if ( !token.type ) - goto Fail; - - count = 1; - idx = 0; - cur = token.start; - limit = token.limit; - - type = field->type; - - /* we must detect arrays in /FontBBox */ - if ( type == T1_FIELD_TYPE_BBOX ) - { - T1_TokenRec token2; - FT_Byte* old_cur = parser->cursor; - FT_Byte* old_limit = parser->limit; - - - /* don't include delimiters */ - parser->cursor = token.start + 1; - parser->limit = token.limit - 1; - - ps_parser_to_token( parser, &token2 ); - parser->cursor = old_cur; - parser->limit = old_limit; - - if ( token2.type == T1_TOKEN_TYPE_ARRAY ) - { - type = T1_FIELD_TYPE_MM_BBOX; - goto FieldArray; - } - } - else if ( token.type == T1_TOKEN_TYPE_ARRAY ) - { - count = max_objects; - - FieldArray: - /* if this is an array and we have no blend, an error occurs */ - if ( max_objects == 0 ) - goto Fail; - - idx = 1; - - /* don't include delimiters */ - cur++; - limit--; - } - - for ( ; count > 0; count--, idx++ ) - { - FT_Byte* q = (FT_Byte*)objects[idx] + field->offset; - FT_Long val; - FT_String* string; - - - skip_spaces( &cur, limit ); - - switch ( type ) - { - case T1_FIELD_TYPE_BOOL: - val = ps_tobool( &cur, limit ); - goto Store_Integer; - - case T1_FIELD_TYPE_FIXED: - val = PS_Conv_ToFixed( &cur, limit, 0 ); - goto Store_Integer; - - case T1_FIELD_TYPE_FIXED_1000: - val = PS_Conv_ToFixed( &cur, limit, 3 ); - goto Store_Integer; - - case T1_FIELD_TYPE_INTEGER: - val = PS_Conv_ToInt( &cur, limit ); - /* fall through */ - - Store_Integer: - switch ( field->size ) - { - case (8 / FT_CHAR_BIT): - *(FT_Byte*)q = (FT_Byte)val; - break; - - case (16 / FT_CHAR_BIT): - *(FT_UShort*)q = (FT_UShort)val; - break; - - case (32 / FT_CHAR_BIT): - *(FT_UInt32*)q = (FT_UInt32)val; - break; - - default: /* for 64-bit systems */ - *(FT_Long*)q = val; - } - break; - - case T1_FIELD_TYPE_STRING: - case T1_FIELD_TYPE_KEY: - { - FT_Memory memory = parser->memory; - FT_UInt len = (FT_UInt)( limit - cur ); - - - if ( cur >= limit ) - break; - - /* we allow both a string or a name */ - /* for cases like /FontName (foo) def */ - if ( token.type == T1_TOKEN_TYPE_KEY ) - { - /* don't include leading `/' */ - len--; - cur++; - } - else if ( token.type == T1_TOKEN_TYPE_STRING ) - { - /* don't include delimiting parentheses */ - /* XXX we don't handle <<...>> here */ - /* XXX should we convert octal escapes? */ - /* if so, what encoding should we use? */ - cur++; - len -= 2; - } - else - { - FT_ERROR(( "ps_parser_load_field:" - " expected a name or string\n" - " " - " but found token of type %d instead\n", - token.type )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* for this to work (FT_String**)q must have been */ - /* initialized to NULL */ - if ( *(FT_String**)q != NULL ) - { - FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n", - field->ident )); - FT_FREE( *(FT_String**)q ); - *(FT_String**)q = NULL; - } - - if ( FT_ALLOC( string, len + 1 ) ) - goto Exit; - - FT_MEM_COPY( string, cur, len ); - string[len] = 0; - - *(FT_String**)q = string; - } - break; - - case T1_FIELD_TYPE_BBOX: - { - FT_Fixed temp[4]; - FT_BBox* bbox = (FT_BBox*)q; - FT_Int result; - - - result = ps_tofixedarray( &cur, limit, 4, temp, 0 ); - - if ( result < 4 ) - { - FT_ERROR(( "ps_parser_load_field:" - " expected four integers in bounding box\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - bbox->xMin = FT_RoundFix( temp[0] ); - bbox->yMin = FT_RoundFix( temp[1] ); - bbox->xMax = FT_RoundFix( temp[2] ); - bbox->yMax = FT_RoundFix( temp[3] ); - } - break; - - case T1_FIELD_TYPE_MM_BBOX: - { - FT_Memory memory = parser->memory; - FT_Fixed* temp; - FT_Int result; - FT_UInt i; - - - if ( FT_NEW_ARRAY( temp, max_objects * 4 ) ) - goto Exit; - - for ( i = 0; i < 4; i++ ) - { - result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects, - temp + i * max_objects, 0 ); - if ( result < 0 || (FT_UInt)result < max_objects ) - { - FT_ERROR(( "ps_parser_load_field:" - " expected %d integer%s in the %s subarray\n" - " " - " of /FontBBox in the /Blend dictionary\n", - max_objects, max_objects > 1 ? "s" : "", - i == 0 ? "first" - : ( i == 1 ? "second" - : ( i == 2 ? "third" - : "fourth" ) ) )); - error = FT_THROW( Invalid_File_Format ); - - FT_FREE( temp ); - goto Exit; - } - - skip_spaces( &cur, limit ); - } - - for ( i = 0; i < max_objects; i++ ) - { - FT_BBox* bbox = (FT_BBox*)objects[i]; - - - bbox->xMin = FT_RoundFix( temp[i ] ); - bbox->yMin = FT_RoundFix( temp[i + max_objects] ); - bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] ); - bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] ); - } - - FT_FREE( temp ); - } - break; - - default: - /* an error occurred */ - goto Fail; - } - } - -#if 0 /* obsolete -- keep for reference */ - if ( pflags ) - *pflags |= 1L << field->flag_bit; -#else - FT_UNUSED( pflags ); -#endif - - error = FT_Err_Ok; - - Exit: - return error; - - Fail: - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - -#define T1_MAX_TABLE_ELEMENTS 32 - - - FT_LOCAL_DEF( FT_Error ) - ps_parser_load_field_table( PS_Parser parser, - const T1_Field field, - void** objects, - FT_UInt max_objects, - FT_ULong* pflags ) - { - T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS]; - T1_Token token; - FT_Int num_elements; - FT_Error error = FT_Err_Ok; - FT_Byte* old_cursor; - FT_Byte* old_limit; - T1_FieldRec fieldrec = *(T1_Field)field; - - - fieldrec.type = T1_FIELD_TYPE_INTEGER; - if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY || - field->type == T1_FIELD_TYPE_BBOX ) - fieldrec.type = T1_FIELD_TYPE_FIXED; - - ps_parser_to_token_array( parser, elements, - T1_MAX_TABLE_ELEMENTS, &num_elements ); - if ( num_elements < 0 ) - { - error = FT_ERR( Ignore ); - goto Exit; - } - if ( (FT_UInt)num_elements > field->array_max ) - num_elements = (FT_Int)field->array_max; - - old_cursor = parser->cursor; - old_limit = parser->limit; - - /* we store the elements count if necessary; */ - /* we further assume that `count_offset' can't be zero */ - if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 ) - *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = - (FT_Byte)num_elements; - - /* we now load each element, adjusting the field.offset on each one */ - token = elements; - for ( ; num_elements > 0; num_elements--, token++ ) - { - parser->cursor = token->start; - parser->limit = token->limit; - - error = ps_parser_load_field( parser, - &fieldrec, - objects, - max_objects, - 0 ); - if ( error ) - break; - - fieldrec.offset += fieldrec.size; - } - -#if 0 /* obsolete -- keep for reference */ - if ( pflags ) - *pflags |= 1L << field->flag_bit; -#else - FT_UNUSED( pflags ); -#endif - - parser->cursor = old_cursor; - parser->limit = old_limit; - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Long ) - ps_parser_to_int( PS_Parser parser ) - { - ps_parser_skip_spaces( parser ); - return PS_Conv_ToInt( &parser->cursor, parser->limit ); - } - - - /* first character must be `<' if `delimiters' is non-zero */ - - FT_LOCAL_DEF( FT_Error ) - ps_parser_to_bytes( PS_Parser parser, - FT_Byte* bytes, - FT_Offset max_bytes, - FT_ULong* pnum_bytes, - FT_Bool delimiters ) - { - FT_Error error = FT_Err_Ok; - FT_Byte* cur; - - - ps_parser_skip_spaces( parser ); - cur = parser->cursor; - - if ( cur >= parser->limit ) - goto Exit; - - if ( delimiters ) - { - if ( *cur != '<' ) - { - FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - cur++; - } - - *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur, - parser->limit, - bytes, - max_bytes ); - - if ( delimiters ) - { - if ( cur < parser->limit && *cur != '>' ) - { - FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - cur++; - } - - parser->cursor = cur; - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Fixed ) - ps_parser_to_fixed( PS_Parser parser, - FT_Int power_ten ) - { - ps_parser_skip_spaces( parser ); - return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten ); - } - - - FT_LOCAL_DEF( FT_Int ) - ps_parser_to_coord_array( PS_Parser parser, - FT_Int max_coords, - FT_Short* coords ) - { - ps_parser_skip_spaces( parser ); - return ps_tocoordarray( &parser->cursor, parser->limit, - max_coords, coords ); - } - - - FT_LOCAL_DEF( FT_Int ) - ps_parser_to_fixed_array( PS_Parser parser, - FT_Int max_values, - FT_Fixed* values, - FT_Int power_ten ) - { - ps_parser_skip_spaces( parser ); - return ps_tofixedarray( &parser->cursor, parser->limit, - max_values, values, power_ten ); - } - - -#if 0 - - FT_LOCAL_DEF( FT_String* ) - T1_ToString( PS_Parser parser ) - { - return ps_tostring( &parser->cursor, parser->limit, parser->memory ); - } - - - FT_LOCAL_DEF( FT_Bool ) - T1_ToBool( PS_Parser parser ) - { - return ps_tobool( &parser->cursor, parser->limit ); - } - -#endif /* 0 */ - - - FT_LOCAL_DEF( void ) - ps_parser_init( PS_Parser parser, - FT_Byte* base, - FT_Byte* limit, - FT_Memory memory ) - { - parser->error = FT_Err_Ok; - parser->base = base; - parser->limit = limit; - parser->cursor = base; - parser->memory = memory; - parser->funcs = ps_parser_funcs; - } - - - FT_LOCAL_DEF( void ) - ps_parser_done( PS_Parser parser ) - { - FT_UNUSED( parser ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 BUILDER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Function> */ - /* t1_builder_init */ - /* */ - /* <Description> */ - /* Initializes a given glyph builder. */ - /* */ - /* <InOut> */ - /* builder :: A pointer to the glyph builder to initialize. */ - /* */ - /* <Input> */ - /* face :: The current face object. */ - /* */ - /* size :: The current size object. */ - /* */ - /* glyph :: The current glyph object. */ - /* */ - /* hinting :: Whether hinting should be applied. */ - /* */ - FT_LOCAL_DEF( void ) - t1_builder_init( T1_Builder builder, - FT_Face face, - FT_Size size, - FT_GlyphSlot glyph, - FT_Bool hinting ) - { - builder->parse_state = T1_Parse_Start; - builder->load_points = 1; - - builder->face = face; - builder->glyph = glyph; - builder->memory = face->memory; - - if ( glyph ) - { - FT_GlyphLoader loader = glyph->internal->loader; - - - builder->loader = loader; - builder->base = &loader->base.outline; - builder->current = &loader->current.outline; - FT_GlyphLoader_Rewind( loader ); - - builder->hints_globals = size->internal; - builder->hints_funcs = NULL; - - if ( hinting ) - builder->hints_funcs = glyph->internal->glyph_hints; - } - - builder->pos_x = 0; - builder->pos_y = 0; - - builder->left_bearing.x = 0; - builder->left_bearing.y = 0; - builder->advance.x = 0; - builder->advance.y = 0; - - builder->funcs = t1_builder_funcs; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* t1_builder_done */ - /* */ - /* <Description> */ - /* Finalizes a given glyph builder. Its contents can still be used */ - /* after the call, but the function saves important information */ - /* within the corresponding glyph slot. */ - /* */ - /* <Input> */ - /* builder :: A pointer to the glyph builder to finalize. */ - /* */ - FT_LOCAL_DEF( void ) - t1_builder_done( T1_Builder builder ) - { - FT_GlyphSlot glyph = builder->glyph; - - - if ( glyph ) - glyph->outline = *builder->base; - } - - - /* check that there is enough space for `count' more points */ - FT_LOCAL_DEF( FT_Error ) - t1_builder_check_points( T1_Builder builder, - FT_Int count ) - { - return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); - } - - - /* add a new point, do not check space */ - FT_LOCAL_DEF( void ) - t1_builder_add_point( T1_Builder builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ) - { - FT_Outline* outline = builder->current; - - - if ( builder->load_points ) - { - FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; - - - point->x = FIXED_TO_INT( x ); - point->y = FIXED_TO_INT( y ); - *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); - } - outline->n_points++; - } - - - /* check space for a new on-curve point, then add it */ - FT_LOCAL_DEF( FT_Error ) - t1_builder_add_point1( T1_Builder builder, - FT_Pos x, - FT_Pos y ) - { - FT_Error error; - - - error = t1_builder_check_points( builder, 1 ); - if ( !error ) - t1_builder_add_point( builder, x, y, 1 ); - - return error; - } - - - /* check space for a new contour, then add it */ - FT_LOCAL_DEF( FT_Error ) - t1_builder_add_contour( T1_Builder builder ) - { - FT_Outline* outline = builder->current; - FT_Error error; - - - /* this might happen in invalid fonts */ - if ( !outline ) - { - FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" )); - return FT_THROW( Invalid_File_Format ); - } - - if ( !builder->load_points ) - { - outline->n_contours++; - return FT_Err_Ok; - } - - error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); - if ( !error ) - { - if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); - - outline->n_contours++; - } - - return error; - } - - - /* if a path was begun, add its first on-curve point */ - FT_LOCAL_DEF( FT_Error ) - t1_builder_start_point( T1_Builder builder, - FT_Pos x, - FT_Pos y ) - { - FT_Error error = FT_ERR( Invalid_File_Format ); - - - /* test whether we are building a new contour */ - - if ( builder->parse_state == T1_Parse_Have_Path ) - error = FT_Err_Ok; - else - { - builder->parse_state = T1_Parse_Have_Path; - error = t1_builder_add_contour( builder ); - if ( !error ) - error = t1_builder_add_point1( builder, x, y ); - } - - return error; - } - - - /* close the current contour */ - FT_LOCAL_DEF( void ) - t1_builder_close_contour( T1_Builder builder ) - { - FT_Outline* outline = builder->current; - FT_Int first; - - - if ( !outline ) - return; - - first = outline->n_contours <= 1 - ? 0 : outline->contours[outline->n_contours - 2] + 1; - - /* We must not include the last point in the path if it */ - /* is located on the first point. */ - if ( outline->n_points > 1 ) - { - FT_Vector* p1 = outline->points + first; - FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; - - - /* `delete' last point only if it coincides with the first */ - /* point and it is not a control point (which can happen). */ - if ( p1->x == p2->x && p1->y == p2->y ) - if ( *control == FT_CURVE_TAG_ON ) - outline->n_points--; - } - - if ( outline->n_contours > 0 ) - { - /* Don't add contours only consisting of one point, i.e., */ - /* check whether the first and the last point is the same. */ - if ( first == outline->n_points - 1 ) - { - outline->n_contours--; - outline->n_points--; - } - else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); - } - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** OTHER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_LOCAL_DEF( void ) - t1_decrypt( FT_Byte* buffer, - FT_Offset length, - FT_UShort seed ) - { - PS_Conv_EexecDecode( &buffer, - buffer + length, - buffer, - length, - &seed ); - } - - -/* END */ diff --git a/third_party/freetype/src/psaux/psobjs.h b/third_party/freetype/src/psaux/psobjs.h deleted file mode 100644 index bf879c1faf2d1bb941a1c2a59951de040594be4b..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/psobjs.h +++ /dev/null @@ -1,212 +0,0 @@ -/***************************************************************************/ -/* */ -/* psobjs.h */ -/* */ -/* Auxiliary functions for PostScript fonts (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSOBJS_H__ -#define __PSOBJS_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_AUX_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1_TABLE *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_CALLBACK_TABLE - const PS_Table_FuncsRec ps_table_funcs; - - FT_CALLBACK_TABLE - const PS_Parser_FuncsRec ps_parser_funcs; - - FT_CALLBACK_TABLE - const T1_Builder_FuncsRec t1_builder_funcs; - - - FT_LOCAL( FT_Error ) - ps_table_new( PS_Table table, - FT_Int count, - FT_Memory memory ); - - FT_LOCAL( FT_Error ) - ps_table_add( PS_Table table, - FT_Int idx, - void* object, - FT_UInt length ); - - FT_LOCAL( void ) - ps_table_done( PS_Table table ); - - - FT_LOCAL( void ) - ps_table_release( PS_Table table ); - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 PARSER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_LOCAL( void ) - ps_parser_skip_spaces( PS_Parser parser ); - - FT_LOCAL( void ) - ps_parser_skip_PS_token( PS_Parser parser ); - - FT_LOCAL( void ) - ps_parser_to_token( PS_Parser parser, - T1_Token token ); - - FT_LOCAL( void ) - ps_parser_to_token_array( PS_Parser parser, - T1_Token tokens, - FT_UInt max_tokens, - FT_Int* pnum_tokens ); - - FT_LOCAL( FT_Error ) - ps_parser_load_field( PS_Parser parser, - const T1_Field field, - void** objects, - FT_UInt max_objects, - FT_ULong* pflags ); - - FT_LOCAL( FT_Error ) - ps_parser_load_field_table( PS_Parser parser, - const T1_Field field, - void** objects, - FT_UInt max_objects, - FT_ULong* pflags ); - - FT_LOCAL( FT_Long ) - ps_parser_to_int( PS_Parser parser ); - - - FT_LOCAL( FT_Error ) - ps_parser_to_bytes( PS_Parser parser, - FT_Byte* bytes, - FT_Offset max_bytes, - FT_ULong* pnum_bytes, - FT_Bool delimiters ); - - - FT_LOCAL( FT_Fixed ) - ps_parser_to_fixed( PS_Parser parser, - FT_Int power_ten ); - - - FT_LOCAL( FT_Int ) - ps_parser_to_coord_array( PS_Parser parser, - FT_Int max_coords, - FT_Short* coords ); - - FT_LOCAL( FT_Int ) - ps_parser_to_fixed_array( PS_Parser parser, - FT_Int max_values, - FT_Fixed* values, - FT_Int power_ten ); - - - FT_LOCAL( void ) - ps_parser_init( PS_Parser parser, - FT_Byte* base, - FT_Byte* limit, - FT_Memory memory ); - - FT_LOCAL( void ) - ps_parser_done( PS_Parser parser ); - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** T1 BUILDER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_LOCAL( void ) - t1_builder_init( T1_Builder builder, - FT_Face face, - FT_Size size, - FT_GlyphSlot glyph, - FT_Bool hinting ); - - FT_LOCAL( void ) - t1_builder_done( T1_Builder builder ); - - FT_LOCAL( FT_Error ) - t1_builder_check_points( T1_Builder builder, - FT_Int count ); - - FT_LOCAL( void ) - t1_builder_add_point( T1_Builder builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ); - - FT_LOCAL( FT_Error ) - t1_builder_add_point1( T1_Builder builder, - FT_Pos x, - FT_Pos y ); - - FT_LOCAL( FT_Error ) - t1_builder_add_contour( T1_Builder builder ); - - - FT_LOCAL( FT_Error ) - t1_builder_start_point( T1_Builder builder, - FT_Pos x, - FT_Pos y ); - - - FT_LOCAL( void ) - t1_builder_close_contour( T1_Builder builder ); - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** OTHER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_LOCAL( void ) - t1_decrypt( FT_Byte* buffer, - FT_Offset length, - FT_UShort seed ); - - -FT_END_HEADER - -#endif /* __PSOBJS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psaux/t1cmap.c b/third_party/freetype/src/psaux/t1cmap.c deleted file mode 100644 index 2e2d433fc498b36a9818d9c5dd2a37ea4806009f..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/t1cmap.c +++ /dev/null @@ -1,355 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1cmap.c */ -/* */ -/* Type 1 character map support (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include "t1cmap.h" - -#include FT_INTERNAL_DEBUG_H - -#include "psauxerr.h" - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static void - t1_cmap_std_init( T1_CMapStd cmap, - FT_Int is_expert ) - { - T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; - - - cmap->num_glyphs = (FT_UInt)face->type1.num_glyphs; - cmap->glyph_names = (const char* const*)face->type1.glyph_names; - cmap->sid_to_string = psnames->adobe_std_strings; - cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding - : psnames->adobe_std_encoding; - - FT_ASSERT( cmap->code_to_sid != NULL ); - } - - - FT_CALLBACK_DEF( void ) - t1_cmap_std_done( T1_CMapStd cmap ) - { - cmap->num_glyphs = 0; - cmap->glyph_names = NULL; - cmap->sid_to_string = NULL; - cmap->code_to_sid = NULL; - } - - - FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_std_char_index( T1_CMapStd cmap, - FT_UInt32 char_code ) - { - FT_UInt result = 0; - - - if ( char_code < 256 ) - { - FT_UInt code, n; - const char* glyph_name; - - - /* convert character code to Adobe SID string */ - code = cmap->code_to_sid[char_code]; - glyph_name = cmap->sid_to_string( code ); - - /* look for the corresponding glyph name */ - for ( n = 0; n < cmap->num_glyphs; n++ ) - { - const char* gname = cmap->glyph_names[n]; - - - if ( gname && gname[0] == glyph_name[0] && - ft_strcmp( gname, glyph_name ) == 0 ) - { - result = n; - break; - } - } - } - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_std_char_next( T1_CMapStd cmap, - FT_UInt32 *pchar_code ) - { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code + 1; - - - while ( char_code < 256 ) - { - result = t1_cmap_std_char_index( cmap, char_code ); - if ( result != 0 ) - goto Exit; - - char_code++; - } - char_code = 0; - - Exit: - *pchar_code = char_code; - return result; - } - - - FT_CALLBACK_DEF( FT_Error ) - t1_cmap_standard_init( T1_CMapStd cmap, - FT_Pointer pointer ) - { - FT_UNUSED( pointer ); - - - t1_cmap_std_init( cmap, 0 ); - return 0; - } - - - FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec - t1_cmap_standard_class_rec = - { - sizeof ( T1_CMapStdRec ), - - (FT_CMap_InitFunc) t1_cmap_standard_init, - (FT_CMap_DoneFunc) t1_cmap_std_done, - (FT_CMap_CharIndexFunc)t1_cmap_std_char_index, - (FT_CMap_CharNextFunc) t1_cmap_std_char_next, - - NULL, NULL, NULL, NULL, NULL - }; - - - FT_CALLBACK_DEF( FT_Error ) - t1_cmap_expert_init( T1_CMapStd cmap, - FT_Pointer pointer ) - { - FT_UNUSED( pointer ); - - - t1_cmap_std_init( cmap, 1 ); - return 0; - } - - FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec - t1_cmap_expert_class_rec = - { - sizeof ( T1_CMapStdRec ), - - (FT_CMap_InitFunc) t1_cmap_expert_init, - (FT_CMap_DoneFunc) t1_cmap_std_done, - (FT_CMap_CharIndexFunc)t1_cmap_std_char_index, - (FT_CMap_CharNextFunc) t1_cmap_std_char_next, - - NULL, NULL, NULL, NULL, NULL - }; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 CUSTOM ENCODING CMAP *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - FT_CALLBACK_DEF( FT_Error ) - t1_cmap_custom_init( T1_CMapCustom cmap, - FT_Pointer pointer ) - { - T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); - T1_Encoding encoding = &face->type1.encoding; - - FT_UNUSED( pointer ); - - - cmap->first = (FT_UInt)encoding->code_first; - cmap->count = (FT_UInt)encoding->code_last - cmap->first; - cmap->indices = encoding->char_index; - - FT_ASSERT( cmap->indices != NULL ); - FT_ASSERT( encoding->code_first <= encoding->code_last ); - - return 0; - } - - - FT_CALLBACK_DEF( void ) - t1_cmap_custom_done( T1_CMapCustom cmap ) - { - cmap->indices = NULL; - cmap->first = 0; - cmap->count = 0; - } - - - FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_custom_char_index( T1_CMapCustom cmap, - FT_UInt32 char_code ) - { - FT_UInt result = 0; - - - if ( ( char_code >= cmap->first ) && - ( char_code < ( cmap->first + cmap->count ) ) ) - result = cmap->indices[char_code]; - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_custom_char_next( T1_CMapCustom cmap, - FT_UInt32 *pchar_code ) - { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; - - - ++char_code; - - if ( char_code < cmap->first ) - char_code = cmap->first; - - for ( ; char_code < ( cmap->first + cmap->count ); char_code++ ) - { - result = cmap->indices[char_code]; - if ( result != 0 ) - goto Exit; - } - - char_code = 0; - - Exit: - *pchar_code = char_code; - return result; - } - - - FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec - t1_cmap_custom_class_rec = - { - sizeof ( T1_CMapCustomRec ), - - (FT_CMap_InitFunc) t1_cmap_custom_init, - (FT_CMap_DoneFunc) t1_cmap_custom_done, - (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index, - (FT_CMap_CharNextFunc) t1_cmap_custom_char_next, - - NULL, NULL, NULL, NULL, NULL - }; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_CALLBACK_DEF( const char * ) - psaux_get_glyph_name( T1_Face face, - FT_UInt idx ) - { - return face->type1.glyph_names[idx]; - } - - - FT_CALLBACK_DEF( FT_Error ) - t1_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) - { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; - - FT_UNUSED( pointer ); - - - return psnames->unicodes_init( memory, - unicodes, - (FT_UInt)face->type1.num_glyphs, - (PS_GetGlyphNameFunc)&psaux_get_glyph_name, - (PS_FreeGlyphNameFunc)NULL, - (FT_Pointer)face ); - } - - - FT_CALLBACK_DEF( void ) - t1_cmap_unicode_done( PS_Unicodes unicodes ) - { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - - - FT_FREE( unicodes->maps ); - unicodes->num_maps = 0; - } - - - FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) - { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; - - - return psnames->unicodes_char_index( unicodes, char_code ); - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) - { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; - - - return psnames->unicodes_char_next( unicodes, pchar_code ); - } - - - FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec - t1_cmap_unicode_class_rec = - { - sizeof ( PS_UnicodesRec ), - - (FT_CMap_InitFunc) t1_cmap_unicode_init, - (FT_CMap_DoneFunc) t1_cmap_unicode_done, - (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index, - (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next, - - NULL, NULL, NULL, NULL, NULL - }; - - -/* END */ diff --git a/third_party/freetype/src/psaux/t1cmap.h b/third_party/freetype/src/psaux/t1cmap.h deleted file mode 100644 index b8ba06cc3bc2915634352e9e0d653bb792f6412e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/t1cmap.h +++ /dev/null @@ -1,105 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1cmap.h */ -/* */ -/* Type 1 character map support (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1CMAP_H__ -#define __T1CMAP_H__ - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_TYPE1_TYPES_H - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* standard (and expert) encoding cmaps */ - typedef struct T1_CMapStdRec_* T1_CMapStd; - - typedef struct T1_CMapStdRec_ - { - FT_CMapRec cmap; - - const FT_UShort* code_to_sid; - PS_Adobe_Std_StringsFunc sid_to_string; - - FT_UInt num_glyphs; - const char* const* glyph_names; - - } T1_CMapStdRec; - - - FT_CALLBACK_TABLE const FT_CMap_ClassRec - t1_cmap_standard_class_rec; - - FT_CALLBACK_TABLE const FT_CMap_ClassRec - t1_cmap_expert_class_rec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 CUSTOM ENCODING CMAP *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - typedef struct T1_CMapCustomRec_* T1_CMapCustom; - - typedef struct T1_CMapCustomRec_ - { - FT_CMapRec cmap; - FT_UInt first; - FT_UInt count; - FT_UShort* indices; - - } T1_CMapCustomRec; - - - FT_CALLBACK_TABLE const FT_CMap_ClassRec - t1_cmap_custom_class_rec; - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* unicode (synthetic) cmaps */ - - FT_CALLBACK_TABLE const FT_CMap_ClassRec - t1_cmap_unicode_class_rec; - - /* */ - - -FT_END_HEADER - -#endif /* __T1CMAP_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psaux/t1decode.c b/third_party/freetype/src/psaux/t1decode.c deleted file mode 100644 index 2e199286f6e93732cfc295532e160ffb3878b946..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/t1decode.c +++ /dev/null @@ -1,1624 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1decode.c */ -/* */ -/* PostScript Type 1 decoding routines (body). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H -#include FT_OUTLINE_H - -#include "t1decode.h" -#include "psobjs.h" - -#include "psauxerr.h" - -/* ensure proper sign extension */ -#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1decode - - - typedef enum T1_Operator_ - { - op_none = 0, - op_endchar, - op_hsbw, - op_seac, - op_sbw, - op_closepath, - op_hlineto, - op_hmoveto, - op_hvcurveto, - op_rlineto, - op_rmoveto, - op_rrcurveto, - op_vhcurveto, - op_vlineto, - op_vmoveto, - op_dotsection, - op_hstem, - op_hstem3, - op_vstem, - op_vstem3, - op_div, - op_callothersubr, - op_callsubr, - op_pop, - op_return, - op_setcurrentpoint, - op_unknown15, - - op_max /* never remove this one */ - - } T1_Operator; - - - static - const FT_Int t1_args_count[op_max] = - { - 0, /* none */ - 0, /* endchar */ - 2, /* hsbw */ - 5, /* seac */ - 4, /* sbw */ - 0, /* closepath */ - 1, /* hlineto */ - 1, /* hmoveto */ - 4, /* hvcurveto */ - 2, /* rlineto */ - 2, /* rmoveto */ - 6, /* rrcurveto */ - 4, /* vhcurveto */ - 1, /* vlineto */ - 1, /* vmoveto */ - 0, /* dotsection */ - 2, /* hstem */ - 6, /* hstem3 */ - 2, /* vstem */ - 6, /* vstem3 */ - 2, /* div */ - -1, /* callothersubr */ - 1, /* callsubr */ - 0, /* pop */ - 0, /* return */ - 2, /* setcurrentpoint */ - 2 /* opcode 15 (undocumented and obsolete) */ - }; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* t1_lookup_glyph_by_stdcharcode */ - /* */ - /* <Description> */ - /* Looks up a given glyph by its StandardEncoding charcode. Used to */ - /* implement the SEAC Type 1 operator. */ - /* */ - /* <Input> */ - /* face :: The current face object. */ - /* */ - /* charcode :: The character code to look for. */ - /* */ - /* <Return> */ - /* A glyph index in the font face. Returns -1 if the corresponding */ - /* glyph wasn't found. */ - /* */ - static FT_Int - t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder, - FT_Int charcode ) - { - FT_UInt n; - const FT_String* glyph_name; - FT_Service_PsCMaps psnames = decoder->psnames; - - - /* check range of standard char code */ - if ( charcode < 0 || charcode > 255 ) - return -1; - - glyph_name = psnames->adobe_std_strings( - psnames->adobe_std_encoding[charcode]); - - for ( n = 0; n < decoder->num_glyphs; n++ ) - { - FT_String* name = (FT_String*)decoder->glyph_names[n]; - - - if ( name && - name[0] == glyph_name[0] && - ft_strcmp( name, glyph_name ) == 0 ) - return (FT_Int)n; - } - - return -1; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* t1operator_seac */ - /* */ - /* <Description> */ - /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ - /* */ - /* <Input> */ - /* decoder :: The current CID decoder. */ - /* */ - /* asb :: The accent's side bearing. */ - /* */ - /* adx :: The horizontal offset of the accent. */ - /* */ - /* ady :: The vertical offset of the accent. */ - /* */ - /* bchar :: The base character's StandardEncoding charcode. */ - /* */ - /* achar :: The accent character's StandardEncoding charcode. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - static FT_Error - t1operator_seac( T1_Decoder decoder, - FT_Pos asb, - FT_Pos adx, - FT_Pos ady, - FT_Int bchar, - FT_Int achar ) - { - FT_Error error; - FT_Int bchar_index, achar_index; -#if 0 - FT_Int n_base_points; - FT_Outline* base = decoder->builder.base; -#endif - FT_Vector left_bearing, advance; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - T1_Face face = (T1_Face)decoder->builder.face; -#endif - - - if ( decoder->seac ) - { - FT_ERROR(( "t1operator_seac: invalid nested seac\n" )); - return FT_THROW( Syntax_Error ); - } - - if ( decoder->builder.metrics_only ) - { - FT_ERROR(( "t1operator_seac: unexpected seac\n" )); - return FT_THROW( Syntax_Error ); - } - - /* seac weirdness */ - adx += decoder->builder.left_bearing.x; - - /* `glyph_names' is set to 0 for CID fonts which do not */ - /* include an encoding. How can we deal with these? */ -#ifdef FT_CONFIG_OPTION_INCREMENTAL - if ( decoder->glyph_names == 0 && - !face->root.internal->incremental_interface ) -#else - if ( decoder->glyph_names == 0 ) -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - FT_ERROR(( "t1operator_seac:" - " glyph names table not available in this font\n" )); - return FT_THROW( Syntax_Error ); - } - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - if ( face->root.internal->incremental_interface ) - { - /* the caller must handle the font encoding also */ - bchar_index = bchar; - achar_index = achar; - } - else -#endif - { - bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); - achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); - } - - if ( bchar_index < 0 || achar_index < 0 ) - { - FT_ERROR(( "t1operator_seac:" - " invalid seac character code arguments\n" )); - return FT_THROW( Syntax_Error ); - } - - /* if we are trying to load a composite glyph, do not load the */ - /* accent character and return the array of subglyphs. */ - if ( decoder->builder.no_recurse ) - { - FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; - FT_GlyphLoader loader = glyph->internal->loader; - FT_SubGlyph subg; - - - /* reallocate subglyph array if necessary */ - error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); - if ( error ) - goto Exit; - - subg = loader->current.subglyphs; - - /* subglyph 0 = base character */ - subg->index = bchar_index; - subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | - FT_SUBGLYPH_FLAG_USE_MY_METRICS; - subg->arg1 = 0; - subg->arg2 = 0; - subg++; - - /* subglyph 1 = accent character */ - subg->index = achar_index; - subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; - subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); - subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); - - /* set up remaining glyph fields */ - glyph->num_subglyphs = 2; - glyph->subglyphs = loader->base.subglyphs; - glyph->format = FT_GLYPH_FORMAT_COMPOSITE; - - loader->current.num_subglyphs = 2; - goto Exit; - } - - /* First load `bchar' in builder */ - /* now load the unscaled outline */ - - FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ - - /* the seac operator must not be nested */ - decoder->seac = TRUE; - error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index ); - decoder->seac = FALSE; - if ( error ) - goto Exit; - - /* save the left bearing and width of the base character */ - /* as they will be erased by the next load. */ - - left_bearing = decoder->builder.left_bearing; - advance = decoder->builder.advance; - - decoder->builder.left_bearing.x = 0; - decoder->builder.left_bearing.y = 0; - - decoder->builder.pos_x = adx - asb; - decoder->builder.pos_y = ady; - - /* Now load `achar' on top of */ - /* the base outline */ - - /* the seac operator must not be nested */ - decoder->seac = TRUE; - error = t1_decoder_parse_glyph( decoder, (FT_UInt)achar_index ); - decoder->seac = FALSE; - if ( error ) - goto Exit; - - /* restore the left side bearing and */ - /* advance width of the base character */ - - decoder->builder.left_bearing = left_bearing; - decoder->builder.advance = advance; - - decoder->builder.pos_x = 0; - decoder->builder.pos_y = 0; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* t1_decoder_parse_charstrings */ - /* */ - /* <Description> */ - /* Parses a given Type 1 charstrings program. */ - /* */ - /* <Input> */ - /* decoder :: The current Type 1 decoder. */ - /* */ - /* charstring_base :: The base address of the charstring stream. */ - /* */ - /* charstring_len :: The length in bytes of the charstring stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - t1_decoder_parse_charstrings( T1_Decoder decoder, - FT_Byte* charstring_base, - FT_UInt charstring_len ) - { - FT_Error error; - T1_Decoder_Zone zone; - FT_Byte* ip; - FT_Byte* limit; - T1_Builder builder = &decoder->builder; - FT_Pos x, y, orig_x, orig_y; - FT_Int known_othersubr_result_cnt = 0; - FT_Int unknown_othersubr_result_cnt = 0; - FT_Bool large_int; - FT_Fixed seed; - - T1_Hints_Funcs hinter; - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_Bool bol = TRUE; -#endif - - - /* compute random seed from stack address of parameter */ - seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^ - (FT_Offset)(char*)&decoder ^ - (FT_Offset)(char*)&charstring_base ) & - FT_ULONG_MAX ); - seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; - if ( seed == 0 ) - seed = 0x7384; - - /* First of all, initialize the decoder */ - decoder->top = decoder->stack; - decoder->zone = decoder->zones; - zone = decoder->zones; - - builder->parse_state = T1_Parse_Start; - - hinter = (T1_Hints_Funcs)builder->hints_funcs; - - /* a font that reads BuildCharArray without setting */ - /* its values first is buggy, but ... */ - FT_ASSERT( ( decoder->len_buildchar == 0 ) == - ( decoder->buildchar == NULL ) ); - - if ( decoder->buildchar && decoder->len_buildchar > 0 ) - ft_memset( &decoder->buildchar[0], - 0, - sizeof ( decoder->buildchar[0] ) * decoder->len_buildchar ); - - FT_TRACE4(( "\n" - "Start charstring\n" )); - - zone->base = charstring_base; - limit = zone->limit = charstring_base + charstring_len; - ip = zone->cursor = zone->base; - - error = FT_Err_Ok; - - x = orig_x = builder->pos_x; - y = orig_y = builder->pos_y; - - /* begin hints recording session, if any */ - if ( hinter ) - hinter->open( hinter->hints ); - - large_int = FALSE; - - /* now, execute loop */ - while ( ip < limit ) - { - FT_Long* top = decoder->top; - T1_Operator op = op_none; - FT_Int32 value = 0; - - - FT_ASSERT( known_othersubr_result_cnt == 0 || - unknown_othersubr_result_cnt == 0 ); - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( bol ) - { - FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); - bol = FALSE; - } -#endif - - /*********************************************************************/ - /* */ - /* Decode operator or operand */ - /* */ - /* */ - - /* first of all, decompress operator or value */ - switch ( *ip++ ) - { - case 1: - op = op_hstem; - break; - - case 3: - op = op_vstem; - break; - case 4: - op = op_vmoveto; - break; - case 5: - op = op_rlineto; - break; - case 6: - op = op_hlineto; - break; - case 7: - op = op_vlineto; - break; - case 8: - op = op_rrcurveto; - break; - case 9: - op = op_closepath; - break; - case 10: - op = op_callsubr; - break; - case 11: - op = op_return; - break; - - case 13: - op = op_hsbw; - break; - case 14: - op = op_endchar; - break; - - case 15: /* undocumented, obsolete operator */ - op = op_unknown15; - break; - - case 21: - op = op_rmoveto; - break; - case 22: - op = op_hmoveto; - break; - - case 30: - op = op_vhcurveto; - break; - case 31: - op = op_hvcurveto; - break; - - case 12: - if ( ip > limit ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " invalid escape (12+EOF)\n" )); - goto Syntax_Error; - } - - switch ( *ip++ ) - { - case 0: - op = op_dotsection; - break; - case 1: - op = op_vstem3; - break; - case 2: - op = op_hstem3; - break; - case 6: - op = op_seac; - break; - case 7: - op = op_sbw; - break; - case 12: - op = op_div; - break; - case 16: - op = op_callothersubr; - break; - case 17: - op = op_pop; - break; - case 33: - op = op_setcurrentpoint; - break; - - default: - FT_ERROR(( "t1_decoder_parse_charstrings:" - " invalid escape (12+%d)\n", - ip[-1] )); - goto Syntax_Error; - } - break; - - case 255: /* four bytes integer */ - if ( ip + 4 > limit ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected EOF in integer\n" )); - goto Syntax_Error; - } - - value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | - ( (FT_UInt32)ip[1] << 16 ) | - ( (FT_UInt32)ip[2] << 8 ) | - (FT_UInt32)ip[3] ); - ip += 4; - - /* According to the specification, values > 32000 or < -32000 must */ - /* be followed by a `div' operator to make the result be in the */ - /* range [-32000;32000]. We expect that the second argument of */ - /* `div' is not a large number. Additionally, we don't handle */ - /* stuff like `<large1> <large2> <num> div <num> div' or */ - /* <large1> <large2> <num> div div'. This is probably not allowed */ - /* anyway. */ - if ( value > 32000 || value < -32000 ) - { - if ( large_int ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " no `div' after large integer\n" )); - } - else - large_int = TRUE; - } - else - { - if ( !large_int ) - value = (FT_Int32)( (FT_UInt32)value << 16 ); - } - - break; - - default: - if ( ip[-1] >= 32 ) - { - if ( ip[-1] < 247 ) - value = (FT_Int32)ip[-1] - 139; - else - { - if ( ++ip > limit ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected EOF in integer\n" )); - goto Syntax_Error; - } - - if ( ip[-2] < 251 ) - value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108; - else - value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 ); - } - - if ( !large_int ) - value = (FT_Int32)( (FT_UInt32)value << 16 ); - } - else - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " invalid byte (%d)\n", ip[-1] )); - goto Syntax_Error; - } - } - - if ( unknown_othersubr_result_cnt > 0 ) - { - switch ( op ) - { - case op_callsubr: - case op_return: - case op_none: - case op_pop: - break; - - default: - /* all operands have been transferred by previous pops */ - unknown_othersubr_result_cnt = 0; - break; - } - } - - if ( large_int && !( op == op_none || op == op_div ) ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " no `div' after large integer\n" )); - - large_int = FALSE; - } - - /*********************************************************************/ - /* */ - /* Push value on stack, or process operator */ - /* */ - /* */ - if ( op == op_none ) - { - if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) - { - FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" )); - goto Syntax_Error; - } - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( large_int ) - FT_TRACE4(( " %ld", value )); - else - FT_TRACE4(( " %ld", Fix2Int( value ) )); -#endif - - *top++ = value; - decoder->top = top; - } - else if ( op == op_callothersubr ) /* callothersubr */ - { - FT_Int subr_no; - FT_Int arg_cnt; - - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( " callothersubr\n" )); - bol = TRUE; -#endif - - if ( top - decoder->stack < 2 ) - goto Stack_Underflow; - - top -= 2; - - subr_no = Fix2Int( top[1] ); - arg_cnt = Fix2Int( top[0] ); - - /***********************************************************/ - /* */ - /* remove all operands to callothersubr from the stack */ - /* */ - /* for handled othersubrs, where we know the number of */ - /* arguments, we increase the stack by the value of */ - /* known_othersubr_result_cnt */ - /* */ - /* for unhandled othersubrs the following pops adjust the */ - /* stack pointer as necessary */ - - if ( arg_cnt > top - decoder->stack ) - goto Stack_Underflow; - - top -= arg_cnt; - - known_othersubr_result_cnt = 0; - unknown_othersubr_result_cnt = 0; - - /* XXX TODO: The checks to `arg_count == <whatever>' */ - /* might not be correct; an othersubr expects a certain */ - /* number of operands on the PostScript stack (as opposed */ - /* to the T1 stack) but it doesn't have to put them there */ - /* by itself; previous othersubrs might have left the */ - /* operands there if they were not followed by an */ - /* appropriate number of pops */ - /* */ - /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */ - /* accept a font that contains charstrings like */ - /* */ - /* 100 200 2 20 callothersubr */ - /* 300 1 20 callothersubr pop */ - /* */ - /* Perhaps this is the reason why BuildCharArray exists. */ - - switch ( subr_no ) - { - case 0: /* end flex feature */ - if ( arg_cnt != 3 ) - goto Unexpected_OtherSubr; - - if ( decoder->flex_state == 0 || - decoder->num_flex_vectors != 7 ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected flex end\n" )); - goto Syntax_Error; - } - - /* the two `results' are popped by the following setcurrentpoint */ - top[0] = x; - top[1] = y; - known_othersubr_result_cnt = 2; - break; - - case 1: /* start flex feature */ - if ( arg_cnt != 0 ) - goto Unexpected_OtherSubr; - - decoder->flex_state = 1; - decoder->num_flex_vectors = 0; - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok || - ( error = t1_builder_check_points( builder, 6 ) ) - != FT_Err_Ok ) - goto Fail; - break; - - case 2: /* add flex vectors */ - { - FT_Int idx; - - - if ( arg_cnt != 0 ) - goto Unexpected_OtherSubr; - - if ( decoder->flex_state == 0 ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " missing flex start\n" )); - goto Syntax_Error; - } - - /* note that we should not add a point for index 0; */ - /* this will move our current position to the flex */ - /* point without adding any point to the outline */ - idx = decoder->num_flex_vectors++; - if ( idx > 0 && idx < 7 ) - t1_builder_add_point( builder, - x, - y, - (FT_Byte)( idx == 3 || idx == 6 ) ); - } - break; - - case 3: /* change hints */ - if ( arg_cnt != 1 ) - goto Unexpected_OtherSubr; - - known_othersubr_result_cnt = 1; - - if ( hinter ) - hinter->reset( hinter->hints, - (FT_UInt)builder->current->n_points ); - break; - - case 12: - case 13: - /* counter control hints, clear stack */ - top = decoder->stack; - break; - - case 14: - case 15: - case 16: - case 17: - case 18: /* multiple masters */ - { - PS_Blend blend = decoder->blend; - FT_UInt num_points, nn, mm; - FT_Long* delta; - FT_Long* values; - - - if ( !blend ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected multiple masters operator\n" )); - goto Syntax_Error; - } - - num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); - if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " incorrect number of multiple masters arguments\n" )); - goto Syntax_Error; - } - - /* We want to compute */ - /* */ - /* a0*w0 + a1*w1 + ... + ak*wk */ - /* */ - /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ - /* */ - /* However, given that w0 + w1 + ... + wk == 1, we can */ - /* rewrite it easily as */ - /* */ - /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ - /* */ - /* where k == num_designs-1. */ - /* */ - /* I guess that's why it's written in this `compact' */ - /* form. */ - /* */ - delta = top + num_points; - values = top; - for ( nn = 0; nn < num_points; nn++ ) - { - FT_Long tmp = values[0]; - - - for ( mm = 1; mm < blend->num_designs; mm++ ) - tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); - - *values++ = tmp; - } - - known_othersubr_result_cnt = (FT_Int)num_points; - break; - } - - case 19: - /* <idx> 1 19 callothersubr */ - /* => replace elements starting from index cvi( <idx> ) */ - /* of BuildCharArray with WeightVector */ - { - FT_Int idx; - PS_Blend blend = decoder->blend; - - - if ( arg_cnt != 1 || blend == NULL ) - goto Unexpected_OtherSubr; - - idx = Fix2Int( top[0] ); - - if ( idx < 0 || - (FT_UInt)idx + blend->num_designs > decoder->len_buildchar ) - goto Unexpected_OtherSubr; - - ft_memcpy( &decoder->buildchar[idx], - blend->weight_vector, - blend->num_designs * - sizeof ( blend->weight_vector[0] ) ); - } - break; - - case 20: - /* <arg1> <arg2> 2 20 callothersubr pop */ - /* ==> push <arg1> + <arg2> onto T1 stack */ - if ( arg_cnt != 2 ) - goto Unexpected_OtherSubr; - - top[0] += top[1]; /* XXX (over|under)flow */ - - known_othersubr_result_cnt = 1; - break; - - case 21: - /* <arg1> <arg2> 2 21 callothersubr pop */ - /* ==> push <arg1> - <arg2> onto T1 stack */ - if ( arg_cnt != 2 ) - goto Unexpected_OtherSubr; - - top[0] -= top[1]; /* XXX (over|under)flow */ - - known_othersubr_result_cnt = 1; - break; - - case 22: - /* <arg1> <arg2> 2 22 callothersubr pop */ - /* ==> push <arg1> * <arg2> onto T1 stack */ - if ( arg_cnt != 2 ) - goto Unexpected_OtherSubr; - - top[0] = FT_MulFix( top[0], top[1] ); - - known_othersubr_result_cnt = 1; - break; - - case 23: - /* <arg1> <arg2> 2 23 callothersubr pop */ - /* ==> push <arg1> / <arg2> onto T1 stack */ - if ( arg_cnt != 2 || top[1] == 0 ) - goto Unexpected_OtherSubr; - - top[0] = FT_DivFix( top[0], top[1] ); - - known_othersubr_result_cnt = 1; - break; - - case 24: - /* <val> <idx> 2 24 callothersubr */ - /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ - { - FT_Int idx; - PS_Blend blend = decoder->blend; - - - if ( arg_cnt != 2 || blend == NULL ) - goto Unexpected_OtherSubr; - - idx = Fix2Int( top[1] ); - - if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) - goto Unexpected_OtherSubr; - - decoder->buildchar[idx] = top[0]; - } - break; - - case 25: - /* <idx> 1 25 callothersubr pop */ - /* ==> push BuildCharArray[cvi( idx )] */ - /* onto T1 stack */ - { - FT_Int idx; - PS_Blend blend = decoder->blend; - - - if ( arg_cnt != 1 || blend == NULL ) - goto Unexpected_OtherSubr; - - idx = Fix2Int( top[0] ); - - if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) - goto Unexpected_OtherSubr; - - top[0] = decoder->buildchar[idx]; - } - - known_othersubr_result_cnt = 1; - break; - -#if 0 - case 26: - /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */ - /* leave mark on T1 stack */ - /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */ - XXX which routine has left its mark on the (PostScript) stack?; - break; -#endif - - case 27: - /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ - /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ - /* otherwise push <res2> */ - if ( arg_cnt != 4 ) - goto Unexpected_OtherSubr; - - if ( top[2] > top[3] ) - top[0] = top[1]; - - known_othersubr_result_cnt = 1; - break; - - case 28: - /* 0 28 callothersubr pop */ - /* => push random value from interval [0, 1) onto stack */ - if ( arg_cnt != 0 ) - goto Unexpected_OtherSubr; - - { - FT_Fixed Rand; - - - Rand = seed; - if ( Rand >= 0x8000L ) - Rand++; - - top[0] = Rand; - - seed = FT_MulFix( seed, 0x10000L - seed ); - if ( seed == 0 ) - seed += 0x2873; - } - - known_othersubr_result_cnt = 1; - break; - - default: - if ( arg_cnt >= 0 && subr_no >= 0 ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unknown othersubr [%d %d], wish me luck\n", - arg_cnt, subr_no )); - unknown_othersubr_result_cnt = arg_cnt; - break; - } - /* fall through */ - - Unexpected_OtherSubr: - FT_ERROR(( "t1_decoder_parse_charstrings:" - " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); - goto Syntax_Error; - } - - top += known_othersubr_result_cnt; - - decoder->top = top; - } - else /* general operator */ - { - FT_Int num_args = t1_args_count[op]; - - - FT_ASSERT( num_args >= 0 ); - - if ( top - decoder->stack < num_args ) - goto Stack_Underflow; - - /* XXX Operators usually take their operands from the */ - /* bottom of the stack, i.e., the operands are */ - /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ - /* only div, callsubr, and callothersubr are different. */ - /* In practice it doesn't matter (?). */ - -#ifdef FT_DEBUG_LEVEL_TRACE - - switch ( op ) - { - case op_callsubr: - case op_div: - case op_callothersubr: - case op_pop: - case op_return: - break; - - default: - if ( top - decoder->stack != num_args ) - FT_TRACE0(( "t1_decoder_parse_charstrings:" - " too much operands on the stack" - " (seen %d, expected %d)\n", - top - decoder->stack, num_args )); - break; - } - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - top -= num_args; - - switch ( op ) - { - case op_endchar: - FT_TRACE4(( " endchar\n" )); - - t1_builder_close_contour( builder ); - - /* close hints recording session */ - if ( hinter ) - { - if ( hinter->close( hinter->hints, - (FT_UInt)builder->current->n_points ) ) - goto Syntax_Error; - - /* apply hints to the loaded glyph outline now */ - error = hinter->apply( hinter->hints, - builder->current, - (PSH_Globals)builder->hints_globals, - decoder->hint_mode ); - if ( error ) - goto Fail; - } - - /* add current outline to the glyph slot */ - FT_GlyphLoader_Add( builder->loader ); - - /* the compiler should optimize away this empty loop but ... */ - -#ifdef FT_DEBUG_LEVEL_TRACE - - if ( decoder->len_buildchar > 0 ) - { - FT_UInt i; - - - FT_TRACE4(( "BuildCharArray = [ " )); - - for ( i = 0; i < decoder->len_buildchar; ++i ) - FT_TRACE4(( "%d ", decoder->buildchar[i] )); - - FT_TRACE4(( "]\n" )); - } - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - FT_TRACE4(( "\n" )); - - /* return now! */ - return FT_Err_Ok; - - case op_hsbw: - FT_TRACE4(( " hsbw" )); - - builder->parse_state = T1_Parse_Have_Width; - - builder->left_bearing.x += top[0]; - builder->advance.x = top[1]; - builder->advance.y = 0; - - orig_x = x = builder->pos_x + top[0]; - orig_y = y = builder->pos_y; - - FT_UNUSED( orig_y ); - - /* the `metrics_only' indicates that we only want to compute */ - /* the glyph's metrics (lsb + advance width), not load the */ - /* rest of it; so exit immediately */ - if ( builder->metrics_only ) - return FT_Err_Ok; - - break; - - case op_seac: - return t1operator_seac( decoder, - top[0], - top[1], - top[2], - Fix2Int( top[3] ), - Fix2Int( top[4] ) ); - - case op_sbw: - FT_TRACE4(( " sbw" )); - - builder->parse_state = T1_Parse_Have_Width; - - builder->left_bearing.x += top[0]; - builder->left_bearing.y += top[1]; - builder->advance.x = top[2]; - builder->advance.y = top[3]; - - x = builder->pos_x + top[0]; - y = builder->pos_y + top[1]; - - /* the `metrics_only' indicates that we only want to compute */ - /* the glyph's metrics (lsb + advance width), not load the */ - /* rest of it; so exit immediately */ - if ( builder->metrics_only ) - return FT_Err_Ok; - - break; - - case op_closepath: - FT_TRACE4(( " closepath" )); - - /* if there is no path, `closepath' is a no-op */ - if ( builder->parse_state == T1_Parse_Have_Path || - builder->parse_state == T1_Parse_Have_Moveto ) - t1_builder_close_contour( builder ); - - builder->parse_state = T1_Parse_Have_Width; - break; - - case op_hlineto: - FT_TRACE4(( " hlineto" )); - - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok ) - goto Fail; - - x += top[0]; - goto Add_Line; - - case op_hmoveto: - FT_TRACE4(( " hmoveto" )); - - x += top[0]; - if ( !decoder->flex_state ) - { - if ( builder->parse_state == T1_Parse_Start ) - goto Syntax_Error; - builder->parse_state = T1_Parse_Have_Moveto; - } - break; - - case op_hvcurveto: - FT_TRACE4(( " hvcurveto" )); - - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok || - ( error = t1_builder_check_points( builder, 3 ) ) - != FT_Err_Ok ) - goto Fail; - - x += top[0]; - t1_builder_add_point( builder, x, y, 0 ); - x += top[1]; - y += top[2]; - t1_builder_add_point( builder, x, y, 0 ); - y += top[3]; - t1_builder_add_point( builder, x, y, 1 ); - break; - - case op_rlineto: - FT_TRACE4(( " rlineto" )); - - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok ) - goto Fail; - - x += top[0]; - y += top[1]; - - Add_Line: - if ( ( error = t1_builder_add_point1( builder, x, y ) ) - != FT_Err_Ok ) - goto Fail; - break; - - case op_rmoveto: - FT_TRACE4(( " rmoveto" )); - - x += top[0]; - y += top[1]; - if ( !decoder->flex_state ) - { - if ( builder->parse_state == T1_Parse_Start ) - goto Syntax_Error; - builder->parse_state = T1_Parse_Have_Moveto; - } - break; - - case op_rrcurveto: - FT_TRACE4(( " rrcurveto" )); - - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok || - ( error = t1_builder_check_points( builder, 3 ) ) - != FT_Err_Ok ) - goto Fail; - - x += top[0]; - y += top[1]; - t1_builder_add_point( builder, x, y, 0 ); - - x += top[2]; - y += top[3]; - t1_builder_add_point( builder, x, y, 0 ); - - x += top[4]; - y += top[5]; - t1_builder_add_point( builder, x, y, 1 ); - break; - - case op_vhcurveto: - FT_TRACE4(( " vhcurveto" )); - - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok || - ( error = t1_builder_check_points( builder, 3 ) ) - != FT_Err_Ok ) - goto Fail; - - y += top[0]; - t1_builder_add_point( builder, x, y, 0 ); - x += top[1]; - y += top[2]; - t1_builder_add_point( builder, x, y, 0 ); - x += top[3]; - t1_builder_add_point( builder, x, y, 1 ); - break; - - case op_vlineto: - FT_TRACE4(( " vlineto" )); - - if ( ( error = t1_builder_start_point( builder, x, y ) ) - != FT_Err_Ok ) - goto Fail; - - y += top[0]; - goto Add_Line; - - case op_vmoveto: - FT_TRACE4(( " vmoveto" )); - - y += top[0]; - if ( !decoder->flex_state ) - { - if ( builder->parse_state == T1_Parse_Start ) - goto Syntax_Error; - builder->parse_state = T1_Parse_Have_Moveto; - } - break; - - case op_div: - FT_TRACE4(( " div" )); - - /* if `large_int' is set, we divide unscaled numbers; */ - /* otherwise, we divide numbers in 16.16 format -- */ - /* in both cases, it is the same operation */ - *top = FT_DivFix( top[0], top[1] ); - ++top; - - large_int = FALSE; - break; - - case op_callsubr: - { - FT_Int idx; - - - FT_TRACE4(( " callsubr" )); - - idx = Fix2Int( top[0] ); - if ( idx < 0 || idx >= decoder->num_subrs ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " invalid subrs index\n" )); - goto Syntax_Error; - } - - if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " too many nested subrs\n" )); - goto Syntax_Error; - } - - zone->cursor = ip; /* save current instruction pointer */ - - zone++; - - /* The Type 1 driver stores subroutines without the seed bytes. */ - /* The CID driver stores subroutines with seed bytes. This */ - /* case is taken care of when decoder->subrs_len == 0. */ - zone->base = decoder->subrs[idx]; - - if ( decoder->subrs_len ) - zone->limit = zone->base + decoder->subrs_len[idx]; - else - { - /* We are using subroutines from a CID font. We must adjust */ - /* for the seed bytes. */ - zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); - zone->limit = decoder->subrs[idx + 1]; - } - - zone->cursor = zone->base; - - if ( !zone->base ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " invoking empty subrs\n" )); - goto Syntax_Error; - } - - decoder->zone = zone; - ip = zone->base; - limit = zone->limit; - break; - } - - case op_pop: - FT_TRACE4(( " pop" )); - - if ( known_othersubr_result_cnt > 0 ) - { - known_othersubr_result_cnt--; - /* ignore, we pushed the operands ourselves */ - break; - } - - if ( unknown_othersubr_result_cnt == 0 ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " no more operands for othersubr\n" )); - goto Syntax_Error; - } - - unknown_othersubr_result_cnt--; - top++; /* `push' the operand to callothersubr onto the stack */ - break; - - case op_return: - FT_TRACE4(( " return" )); - - if ( zone <= decoder->zones ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected return\n" )); - goto Syntax_Error; - } - - zone--; - ip = zone->cursor; - limit = zone->limit; - decoder->zone = zone; - break; - - case op_dotsection: - FT_TRACE4(( " dotsection" )); - - break; - - case op_hstem: - FT_TRACE4(( " hstem" )); - - /* record horizontal hint */ - if ( hinter ) - { - /* top[0] += builder->left_bearing.y; */ - hinter->stem( hinter->hints, 1, top ); - } - break; - - case op_hstem3: - FT_TRACE4(( " hstem3" )); - - /* record horizontal counter-controlled hints */ - if ( hinter ) - hinter->stem3( hinter->hints, 1, top ); - break; - - case op_vstem: - FT_TRACE4(( " vstem" )); - - /* record vertical hint */ - if ( hinter ) - { - top[0] += orig_x; - hinter->stem( hinter->hints, 0, top ); - } - break; - - case op_vstem3: - FT_TRACE4(( " vstem3" )); - - /* record vertical counter-controlled hints */ - if ( hinter ) - { - FT_Pos dx = orig_x; - - - top[0] += dx; - top[2] += dx; - top[4] += dx; - hinter->stem3( hinter->hints, 0, top ); - } - break; - - case op_setcurrentpoint: - FT_TRACE4(( " setcurrentpoint" )); - - /* From the T1 specification, section 6.4: */ - /* */ - /* The setcurrentpoint command is used only in */ - /* conjunction with results from OtherSubrs procedures. */ - - /* known_othersubr_result_cnt != 0 is already handled */ - /* above. */ - - /* Note, however, that both Ghostscript and Adobe */ - /* Distiller handle this situation by silently ignoring */ - /* the inappropriate `setcurrentpoint' instruction. So */ - /* we do the same. */ -#if 0 - - if ( decoder->flex_state != 1 ) - { - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unexpected `setcurrentpoint'\n" )); - goto Syntax_Error; - } - else - ... -#endif - - x = top[0]; - y = top[1]; - decoder->flex_state = 0; - break; - - case op_unknown15: - FT_TRACE4(( " opcode_15" )); - /* nothing to do except to pop the two arguments */ - break; - - default: - FT_ERROR(( "t1_decoder_parse_charstrings:" - " unhandled opcode %d\n", op )); - goto Syntax_Error; - } - - /* XXX Operators usually clear the operand stack; */ - /* only div, callsubr, callothersubr, pop, and */ - /* return are different. */ - /* In practice it doesn't matter (?). */ - - decoder->top = top; - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( "\n" )); - bol = TRUE; -#endif - - } /* general operator processing */ - - } /* while ip < limit */ - - FT_TRACE4(( "..end..\n\n" )); - - Fail: - return error; - - Syntax_Error: - return FT_THROW( Syntax_Error ); - - Stack_Underflow: - return FT_THROW( Stack_Underflow ); - } - - - /* parse a single Type 1 glyph */ - FT_LOCAL_DEF( FT_Error ) - t1_decoder_parse_glyph( T1_Decoder decoder, - FT_UInt glyph ) - { - return decoder->parse_callback( decoder, glyph ); - } - - - /* initialize T1 decoder */ - FT_LOCAL_DEF( FT_Error ) - t1_decoder_init( T1_Decoder decoder, - FT_Face face, - FT_Size size, - FT_GlyphSlot slot, - FT_Byte** glyph_names, - PS_Blend blend, - FT_Bool hinting, - FT_Render_Mode hint_mode, - T1_Decoder_Callback parse_callback ) - { - FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); - - /* retrieve PSNames interface from list of current modules */ - { - FT_Service_PsCMaps psnames; - - - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); - if ( !psnames ) - { - FT_ERROR(( "t1_decoder_init:" - " the `psnames' module is not available\n" )); - return FT_THROW( Unimplemented_Feature ); - } - - decoder->psnames = psnames; - } - - t1_builder_init( &decoder->builder, face, size, slot, hinting ); - - /* decoder->buildchar and decoder->len_buildchar have to be */ - /* initialized by the caller since we cannot know the length */ - /* of the BuildCharArray */ - - decoder->num_glyphs = (FT_UInt)face->num_glyphs; - decoder->glyph_names = glyph_names; - decoder->hint_mode = hint_mode; - decoder->blend = blend; - decoder->parse_callback = parse_callback; - - decoder->funcs = t1_decoder_funcs; - - return FT_Err_Ok; - } - - - /* finalize T1 decoder */ - FT_LOCAL_DEF( void ) - t1_decoder_done( T1_Decoder decoder ) - { - t1_builder_done( &decoder->builder ); - } - - -/* END */ diff --git a/third_party/freetype/src/psaux/t1decode.h b/third_party/freetype/src/psaux/t1decode.h deleted file mode 100644 index e83078f7195f69bca95a04f59b84fef5250aa523..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psaux/t1decode.h +++ /dev/null @@ -1,64 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1decode.h */ -/* */ -/* PostScript Type 1 decoding routines (specification). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1DECODE_H__ -#define __T1DECODE_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_AUX_H -#include FT_INTERNAL_TYPE1_TYPES_H - - -FT_BEGIN_HEADER - - - FT_CALLBACK_TABLE - const T1_Decoder_FuncsRec t1_decoder_funcs; - - - FT_LOCAL( FT_Error ) - t1_decoder_parse_glyph( T1_Decoder decoder, - FT_UInt glyph_index ); - - FT_LOCAL( FT_Error ) - t1_decoder_parse_charstrings( T1_Decoder decoder, - FT_Byte* base, - FT_UInt len ); - - FT_LOCAL( FT_Error ) - t1_decoder_init( T1_Decoder decoder, - FT_Face face, - FT_Size size, - FT_GlyphSlot slot, - FT_Byte** glyph_names, - PS_Blend blend, - FT_Bool hinting, - FT_Render_Mode hint_mode, - T1_Decoder_Callback parse_glyph ); - - FT_LOCAL( void ) - t1_decoder_done( T1_Decoder decoder ); - - -FT_END_HEADER - -#endif /* __T1DECODE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/Jamfile b/third_party/freetype/src/pshinter/Jamfile deleted file mode 100644 index 6fb3be11c707626182fc9d1c4159952ac93554d5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/Jamfile +++ /dev/null @@ -1,34 +0,0 @@ -# FreeType 2 src/pshinter Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) pshinter ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = pshalgo - pshglob - pshmod - pshpic - pshrec - ; - } - else - { - _sources = pshinter ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/pshinter Jamfile diff --git a/third_party/freetype/src/pshinter/pshalgo.c b/third_party/freetype/src/pshinter/pshalgo.c deleted file mode 100644 index 6e654cb1ef886ae9fce21066f34bb8699518c4c6..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshalgo.c +++ /dev/null @@ -1,2195 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshalgo.c */ -/* */ -/* PostScript hinting algorithm (body). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used */ -/* modified and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H -#include "pshalgo.h" - -#include "pshnterr.h" - - -#undef FT_COMPONENT -#define FT_COMPONENT trace_pshalgo2 - - -#ifdef DEBUG_HINTER - PSH_Hint_Table ps_debug_hint_table = NULL; - PSH_HintFunc ps_debug_hint_func = NULL; - PSH_Glyph ps_debug_glyph = NULL; -#endif - - -#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */ - /* and similar glyphs */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** BASIC HINTS RECORDINGS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* return true if two stem hints overlap */ - static FT_Int - psh_hint_overlap( PSH_Hint hint1, - PSH_Hint hint2 ) - { - return hint1->org_pos + hint1->org_len >= hint2->org_pos && - hint2->org_pos + hint2->org_len >= hint1->org_pos; - } - - - /* destroy hints table */ - static void - psh_hint_table_done( PSH_Hint_Table table, - FT_Memory memory ) - { - FT_FREE( table->zones ); - table->num_zones = 0; - table->zone = NULL; - - FT_FREE( table->sort ); - FT_FREE( table->hints ); - table->num_hints = 0; - table->max_hints = 0; - table->sort_global = NULL; - } - - - /* deactivate all hints in a table */ - static void - psh_hint_table_deactivate( PSH_Hint_Table table ) - { - FT_UInt count = table->max_hints; - PSH_Hint hint = table->hints; - - - for ( ; count > 0; count--, hint++ ) - { - psh_hint_deactivate( hint ); - hint->order = -1; - } - } - - - /* internal function to record a new hint */ - static void - psh_hint_table_record( PSH_Hint_Table table, - FT_UInt idx ) - { - PSH_Hint hint = table->hints + idx; - - - if ( idx >= table->max_hints ) - { - FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx )); - return; - } - - /* ignore active hints */ - if ( psh_hint_is_active( hint ) ) - return; - - psh_hint_activate( hint ); - - /* now scan the current active hint set to check */ - /* whether `hint' overlaps with another hint */ - { - PSH_Hint* sorted = table->sort_global; - FT_UInt count = table->num_hints; - PSH_Hint hint2; - - - hint->parent = NULL; - for ( ; count > 0; count--, sorted++ ) - { - hint2 = sorted[0]; - - if ( psh_hint_overlap( hint, hint2 ) ) - { - hint->parent = hint2; - break; - } - } - } - - if ( table->num_hints < table->max_hints ) - table->sort_global[table->num_hints++] = hint; - else - FT_TRACE0(( "psh_hint_table_record: too many sorted hints! BUG!\n" )); - } - - - static void - psh_hint_table_record_mask( PSH_Hint_Table table, - PS_Mask hint_mask ) - { - FT_Int mask = 0, val = 0; - FT_Byte* cursor = hint_mask->bytes; - FT_UInt idx, limit; - - - limit = hint_mask->num_bits; - - for ( idx = 0; idx < limit; idx++ ) - { - if ( mask == 0 ) - { - val = *cursor++; - mask = 0x80; - } - - if ( val & mask ) - psh_hint_table_record( table, idx ); - - mask >>= 1; - } - } - - - /* create hints table */ - static FT_Error - psh_hint_table_init( PSH_Hint_Table table, - PS_Hint_Table hints, - PS_Mask_Table hint_masks, - PS_Mask_Table counter_masks, - FT_Memory memory ) - { - FT_UInt count; - FT_Error error; - - FT_UNUSED( counter_masks ); - - - count = hints->num_hints; - - /* allocate our tables */ - if ( FT_NEW_ARRAY( table->sort, 2 * count ) || - FT_NEW_ARRAY( table->hints, count ) || - FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) - goto Exit; - - table->max_hints = count; - table->sort_global = table->sort + count; - table->num_hints = 0; - table->num_zones = 0; - table->zone = NULL; - - /* initialize the `table->hints' array */ - { - PSH_Hint write = table->hints; - PS_Hint read = hints->hints; - - - for ( ; count > 0; count--, write++, read++ ) - { - write->org_pos = read->pos; - write->org_len = read->len; - write->flags = read->flags; - } - } - - /* we now need to determine the initial `parent' stems; first */ - /* activate the hints that are given by the initial hint masks */ - if ( hint_masks ) - { - PS_Mask mask = hint_masks->masks; - - - count = hint_masks->num_masks; - table->hint_masks = hint_masks; - - for ( ; count > 0; count--, mask++ ) - psh_hint_table_record_mask( table, mask ); - } - - /* finally, do a linear parse in case some hints were left alone */ - if ( table->num_hints != table->max_hints ) - { - FT_UInt idx; - - - FT_TRACE0(( "psh_hint_table_init: missing/incorrect hint masks\n" )); - - count = table->max_hints; - for ( idx = 0; idx < count; idx++ ) - psh_hint_table_record( table, idx ); - } - - Exit: - return error; - } - - - static void - psh_hint_table_activate_mask( PSH_Hint_Table table, - PS_Mask hint_mask ) - { - FT_Int mask = 0, val = 0; - FT_Byte* cursor = hint_mask->bytes; - FT_UInt idx, limit, count; - - - limit = hint_mask->num_bits; - count = 0; - - psh_hint_table_deactivate( table ); - - for ( idx = 0; idx < limit; idx++ ) - { - if ( mask == 0 ) - { - val = *cursor++; - mask = 0x80; - } - - if ( val & mask ) - { - PSH_Hint hint = &table->hints[idx]; - - - if ( !psh_hint_is_active( hint ) ) - { - FT_UInt count2; - -#if 0 - PSH_Hint* sort = table->sort; - PSH_Hint hint2; - - - for ( count2 = count; count2 > 0; count2--, sort++ ) - { - hint2 = sort[0]; - if ( psh_hint_overlap( hint, hint2 ) ) - FT_TRACE0(( "psh_hint_table_activate_mask:" - " found overlapping hints\n" )) - } -#else - count2 = 0; -#endif - - if ( count2 == 0 ) - { - psh_hint_activate( hint ); - if ( count < table->max_hints ) - table->sort[count++] = hint; - else - FT_TRACE0(( "psh_hint_tableactivate_mask:" - " too many active hints\n" )); - } - } - } - - mask >>= 1; - } - table->num_hints = count; - - /* now, sort the hints; they are guaranteed to not overlap */ - /* so we can compare their "org_pos" field directly */ - { - FT_Int i1, i2; - PSH_Hint hint1, hint2; - PSH_Hint* sort = table->sort; - - - /* a simple bubble sort will do, since in 99% of cases, the hints */ - /* will be already sorted -- and the sort will be linear */ - for ( i1 = 1; i1 < (FT_Int)count; i1++ ) - { - hint1 = sort[i1]; - for ( i2 = i1 - 1; i2 >= 0; i2-- ) - { - hint2 = sort[i2]; - - if ( hint2->org_pos < hint1->org_pos ) - break; - - sort[i2 + 1] = hint2; - sort[i2] = hint1; - } - } - } - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** HINTS GRID-FITTING AND OPTIMIZATION *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#if 1 - static FT_Pos - psh_dimension_quantize_len( PSH_Dimension dim, - FT_Pos len, - FT_Bool do_snapping ) - { - if ( len <= 64 ) - len = 64; - else - { - FT_Pos delta = len - dim->stdw.widths[0].cur; - - - if ( delta < 0 ) - delta = -delta; - - if ( delta < 40 ) - { - len = dim->stdw.widths[0].cur; - if ( len < 48 ) - len = 48; - } - - if ( len < 3 * 64 ) - { - delta = ( len & 63 ); - len &= -64; - - if ( delta < 10 ) - len += delta; - - else if ( delta < 32 ) - len += 10; - - else if ( delta < 54 ) - len += 54; - - else - len += delta; - } - else - len = FT_PIX_ROUND( len ); - } - - if ( do_snapping ) - len = FT_PIX_ROUND( len ); - - return len; - } -#endif /* 0 */ - - -#ifdef DEBUG_HINTER - - static void - ps_simple_scale( PSH_Hint_Table table, - FT_Fixed scale, - FT_Fixed delta, - FT_Int dimension ) - { - FT_UInt count; - - - for ( count = 0; count < table->max_hints; count++ ) - { - PSH_Hint hint = table->hints + count; - - - hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta; - hint->cur_len = FT_MulFix( hint->org_len, scale ); - - if ( ps_debug_hint_func ) - ps_debug_hint_func( hint, dimension ); - } - } - -#endif /* DEBUG_HINTER */ - - - static FT_Fixed - psh_hint_snap_stem_side_delta( FT_Fixed pos, - FT_Fixed len ) - { - FT_Fixed delta1 = FT_PIX_ROUND( pos ) - pos; - FT_Fixed delta2 = FT_PIX_ROUND( pos + len ) - pos - len; - - - if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) ) - return delta1; - else - return delta2; - } - - - static void - psh_hint_align( PSH_Hint hint, - PSH_Globals globals, - FT_Int dimension, - PSH_Glyph glyph ) - { - PSH_Dimension dim = &globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Fixed delta = dim->scale_delta; - - - if ( !psh_hint_is_fitted( hint ) ) - { - FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; - FT_Pos len = FT_MulFix( hint->org_len, scale ); - - FT_Int do_snapping; - FT_Pos fit_len; - PSH_AlignmentRec align; - - - /* ignore stem alignments when requested through the hint flags */ - if ( ( dimension == 0 && !glyph->do_horz_hints ) || - ( dimension == 1 && !glyph->do_vert_hints ) ) - { - hint->cur_pos = pos; - hint->cur_len = len; - - psh_hint_set_fitted( hint ); - return; - } - - /* perform stem snapping when requested - this is necessary - * for monochrome and LCD hinting modes only - */ - do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) || - ( dimension == 1 && glyph->do_vert_snapping ); - - hint->cur_len = fit_len = len; - - /* check blue zones for horizontal stems */ - align.align = PSH_BLUE_ALIGN_NONE; - align.align_bot = align.align_top = 0; - - if ( dimension == 1 ) - psh_blues_snap_stem( &globals->blues, - hint->org_pos + hint->org_len, - hint->org_pos, - &align ); - - switch ( align.align ) - { - case PSH_BLUE_ALIGN_TOP: - /* the top of the stem is aligned against a blue zone */ - hint->cur_pos = align.align_top - fit_len; - break; - - case PSH_BLUE_ALIGN_BOT: - /* the bottom of the stem is aligned against a blue zone */ - hint->cur_pos = align.align_bot; - break; - - case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: - /* both edges of the stem are aligned against blue zones */ - hint->cur_pos = align.align_bot; - hint->cur_len = align.align_top - align.align_bot; - break; - - default: - { - PSH_Hint parent = hint->parent; - - - if ( parent ) - { - FT_Pos par_org_center, par_cur_center; - FT_Pos cur_org_center, cur_delta; - - - /* ensure that parent is already fitted */ - if ( !psh_hint_is_fitted( parent ) ) - psh_hint_align( parent, globals, dimension, glyph ); - - /* keep original relation between hints, this is, use the */ - /* scaled distance between the centers of the hints to */ - /* compute the new position */ - par_org_center = parent->org_pos + ( parent->org_len >> 1 ); - par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 ); - cur_org_center = hint->org_pos + ( hint->org_len >> 1 ); - - cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); - pos = par_cur_center + cur_delta - ( len >> 1 ); - } - - hint->cur_pos = pos; - hint->cur_len = fit_len; - - /* Stem adjustment tries to snap stem widths to standard - * ones. This is important to prevent unpleasant rounding - * artefacts. - */ - if ( glyph->do_stem_adjust ) - { - if ( len <= 64 ) - { - /* the stem is less than one pixel; we will center it - * around the nearest pixel center - */ - if ( len >= 32 ) - { - /* This is a special case where we also widen the stem - * and align it to the pixel grid. - * - * stem_center = pos + (len/2) - * nearest_pixel_center = FT_ROUND(stem_center-32)+32 - * new_pos = nearest_pixel_center-32 - * = FT_ROUND(stem_center-32) - * = FT_FLOOR(stem_center-32+32) - * = FT_FLOOR(stem_center) - * new_len = 64 - */ - pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ); - len = 64; - } - else if ( len > 0 ) - { - /* This is a very small stem; we simply align it to the - * pixel grid, trying to find the minimum displacement. - * - * left = pos - * right = pos + len - * left_nearest_edge = ROUND(pos) - * right_nearest_edge = ROUND(right) - * - * if ( ABS(left_nearest_edge - left) <= - * ABS(right_nearest_edge - right) ) - * new_pos = left - * else - * new_pos = right - */ - FT_Pos left_nearest = FT_PIX_ROUND( pos ); - FT_Pos right_nearest = FT_PIX_ROUND( pos + len ); - FT_Pos left_disp = left_nearest - pos; - FT_Pos right_disp = right_nearest - ( pos + len ); - - - if ( left_disp < 0 ) - left_disp = -left_disp; - if ( right_disp < 0 ) - right_disp = -right_disp; - if ( left_disp <= right_disp ) - pos = left_nearest; - else - pos = right_nearest; - } - else - { - /* this is a ghost stem; we simply round it */ - pos = FT_PIX_ROUND( pos ); - } - } - else - { - len = psh_dimension_quantize_len( dim, len, 0 ); - } - } - - /* now that we have a good hinted stem width, try to position */ - /* the stem along a pixel grid integer coordinate */ - hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len ); - hint->cur_len = len; - } - } - - if ( do_snapping ) - { - pos = hint->cur_pos; - len = hint->cur_len; - - if ( len < 64 ) - len = 64; - else - len = FT_PIX_ROUND( len ); - - switch ( align.align ) - { - case PSH_BLUE_ALIGN_TOP: - hint->cur_pos = align.align_top - len; - hint->cur_len = len; - break; - - case PSH_BLUE_ALIGN_BOT: - hint->cur_len = len; - break; - - case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP: - /* don't touch */ - break; - - - default: - hint->cur_len = len; - if ( len & 64 ) - pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32; - else - pos = FT_PIX_ROUND( pos + ( len >> 1 ) ); - - hint->cur_pos = pos - ( len >> 1 ); - hint->cur_len = len; - } - } - - psh_hint_set_fitted( hint ); - -#ifdef DEBUG_HINTER - if ( ps_debug_hint_func ) - ps_debug_hint_func( hint, dimension ); -#endif - } - } - - -#if 0 /* not used for now, experimental */ - - /* - * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT) - * of stems - */ - static void - psh_hint_align_light( PSH_Hint hint, - PSH_Globals globals, - FT_Int dimension, - PSH_Glyph glyph ) - { - PSH_Dimension dim = &globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Fixed delta = dim->scale_delta; - - - if ( !psh_hint_is_fitted( hint ) ) - { - FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; - FT_Pos len = FT_MulFix( hint->org_len, scale ); - - FT_Pos fit_len; - - PSH_AlignmentRec align; - - - /* ignore stem alignments when requested through the hint flags */ - if ( ( dimension == 0 && !glyph->do_horz_hints ) || - ( dimension == 1 && !glyph->do_vert_hints ) ) - { - hint->cur_pos = pos; - hint->cur_len = len; - - psh_hint_set_fitted( hint ); - return; - } - - fit_len = len; - - hint->cur_len = fit_len; - - /* check blue zones for horizontal stems */ - align.align = PSH_BLUE_ALIGN_NONE; - align.align_bot = align.align_top = 0; - - if ( dimension == 1 ) - psh_blues_snap_stem( &globals->blues, - hint->org_pos + hint->org_len, - hint->org_pos, - &align ); - - switch ( align.align ) - { - case PSH_BLUE_ALIGN_TOP: - /* the top of the stem is aligned against a blue zone */ - hint->cur_pos = align.align_top - fit_len; - break; - - case PSH_BLUE_ALIGN_BOT: - /* the bottom of the stem is aligned against a blue zone */ - hint->cur_pos = align.align_bot; - break; - - case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: - /* both edges of the stem are aligned against blue zones */ - hint->cur_pos = align.align_bot; - hint->cur_len = align.align_top - align.align_bot; - break; - - default: - { - PSH_Hint parent = hint->parent; - - - if ( parent ) - { - FT_Pos par_org_center, par_cur_center; - FT_Pos cur_org_center, cur_delta; - - - /* ensure that parent is already fitted */ - if ( !psh_hint_is_fitted( parent ) ) - psh_hint_align_light( parent, globals, dimension, glyph ); - - par_org_center = parent->org_pos + ( parent->org_len / 2 ); - par_cur_center = parent->cur_pos + ( parent->cur_len / 2 ); - cur_org_center = hint->org_pos + ( hint->org_len / 2 ); - - cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); - pos = par_cur_center + cur_delta - ( len >> 1 ); - } - - /* Stems less than one pixel wide are easy -- we want to - * make them as dark as possible, so they must fall within - * one pixel. If the stem is split between two pixels - * then snap the edge that is nearer to the pixel boundary - * to the pixel boundary. - */ - if ( len <= 64 ) - { - if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 ) - pos += psh_hint_snap_stem_side_delta ( pos, len ); - } - - /* Position stems other to minimize the amount of mid-grays. - * There are, in general, two positions that do this, - * illustrated as A) and B) below. - * - * + + + + - * - * A) |--------------------------------| - * B) |--------------------------------| - * C) |--------------------------------| - * - * Position A) (split the excess stem equally) should be better - * for stems of width N + f where f < 0.5. - * - * Position B) (split the deficiency equally) should be better - * for stems of width N + f where f > 0.5. - * - * It turns out though that minimizing the total number of lit - * pixels is also important, so position C), with one edge - * aligned with a pixel boundary is actually preferable - * to A). There are also more possibile positions for C) than - * for A) or B), so it involves less distortion of the overall - * character shape. - */ - else /* len > 64 */ - { - FT_Fixed frac_len = len & 63; - FT_Fixed center = pos + ( len >> 1 ); - FT_Fixed delta_a, delta_b; - - - if ( ( len / 64 ) & 1 ) - { - delta_a = FT_PIX_FLOOR( center ) + 32 - center; - delta_b = FT_PIX_ROUND( center ) - center; - } - else - { - delta_a = FT_PIX_ROUND( center ) - center; - delta_b = FT_PIX_FLOOR( center ) + 32 - center; - } - - /* We choose between B) and C) above based on the amount - * of fractinal stem width; for small amounts, choose - * C) always, for large amounts, B) always, and inbetween, - * pick whichever one involves less stem movement. - */ - if ( frac_len < 32 ) - { - pos += psh_hint_snap_stem_side_delta ( pos, len ); - } - else if ( frac_len < 48 ) - { - FT_Fixed side_delta = psh_hint_snap_stem_side_delta ( pos, - len ); - - if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) ) - pos += side_delta; - else - pos += delta_b; - } - else - { - pos += delta_b; - } - } - - hint->cur_pos = pos; - } - } /* switch */ - - psh_hint_set_fitted( hint ); - -#ifdef DEBUG_HINTER - if ( ps_debug_hint_func ) - ps_debug_hint_func( hint, dimension ); -#endif - } - } - -#endif /* 0 */ - - - static void - psh_hint_table_align_hints( PSH_Hint_Table table, - PSH_Globals globals, - FT_Int dimension, - PSH_Glyph glyph ) - { - PSH_Hint hint; - FT_UInt count; - -#ifdef DEBUG_HINTER - - PSH_Dimension dim = &globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Fixed delta = dim->scale_delta; - - - if ( ps_debug_no_vert_hints && dimension == 0 ) - { - ps_simple_scale( table, scale, delta, dimension ); - return; - } - - if ( ps_debug_no_horz_hints && dimension == 1 ) - { - ps_simple_scale( table, scale, delta, dimension ); - return; - } - -#endif /* DEBUG_HINTER*/ - - hint = table->hints; - count = table->max_hints; - - for ( ; count > 0; count--, hint++ ) - psh_hint_align( hint, globals, dimension, glyph ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** POINTS INTERPOLATION ROUTINES *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define xxDEBUG_ZONES - - -#ifdef DEBUG_ZONES - -#include FT_CONFIG_STANDARD_LIBRARY_H - - static void - psh_print_zone( PSH_Zone zone ) - { - printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n", - zone->scale / 65536.0, - zone->delta / 64.0, - zone->min, - zone->max ); - } - -#endif /* DEBUG_ZONES */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** HINTER GLYPH MANAGEMENT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define psh_corner_is_flat ft_corner_is_flat -#define psh_corner_orientation ft_corner_orientation - - -#ifdef COMPUTE_INFLEXS - - /* compute all inflex points in a given glyph */ - static void - psh_glyph_compute_inflections( PSH_Glyph glyph ) - { - FT_UInt n; - - - for ( n = 0; n < glyph->num_contours; n++ ) - { - PSH_Point first, start, end, before, after; - FT_Pos in_x, in_y, out_x, out_y; - FT_Int orient_prev, orient_cur; - FT_Int finished = 0; - - - /* we need at least 4 points to create an inflection point */ - if ( glyph->contours[n].count < 4 ) - continue; - - /* compute first segment in contour */ - first = glyph->contours[n].start; - - start = end = first; - do - { - end = end->next; - if ( end == first ) - goto Skip; - - in_x = end->org_u - start->org_u; - in_y = end->org_v - start->org_v; - - } while ( in_x == 0 && in_y == 0 ); - - /* extend the segment start whenever possible */ - before = start; - do - { - do - { - start = before; - before = before->prev; - if ( before == first ) - goto Skip; - - out_x = start->org_u - before->org_u; - out_y = start->org_v - before->org_v; - - } while ( out_x == 0 && out_y == 0 ); - - orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y ); - - } while ( orient_prev == 0 ); - - first = start; - in_x = out_x; - in_y = out_y; - - /* now, process all segments in the contour */ - do - { - /* first, extend current segment's end whenever possible */ - after = end; - do - { - do - { - end = after; - after = after->next; - if ( after == first ) - finished = 1; - - out_x = after->org_u - end->org_u; - out_y = after->org_v - end->org_v; - - } while ( out_x == 0 && out_y == 0 ); - - orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y ); - - } while ( orient_cur == 0 ); - - if ( ( orient_cur ^ orient_prev ) < 0 ) - { - do - { - psh_point_set_inflex( start ); - start = start->next; - } - while ( start != end ); - - psh_point_set_inflex( start ); - } - - start = end; - end = after; - orient_prev = orient_cur; - in_x = out_x; - in_y = out_y; - - } while ( !finished ); - - Skip: - ; - } - } - -#endif /* COMPUTE_INFLEXS */ - - - static void - psh_glyph_done( PSH_Glyph glyph ) - { - FT_Memory memory = glyph->memory; - - - psh_hint_table_done( &glyph->hint_tables[1], memory ); - psh_hint_table_done( &glyph->hint_tables[0], memory ); - - FT_FREE( glyph->points ); - FT_FREE( glyph->contours ); - - glyph->num_points = 0; - glyph->num_contours = 0; - - glyph->memory = NULL; - } - - - static int - psh_compute_dir( FT_Pos dx, - FT_Pos dy ) - { - FT_Pos ax, ay; - int result = PSH_DIR_NONE; - - - ax = FT_ABS( dx ); - ay = FT_ABS( dy ); - - if ( ay * 12 < ax ) - { - /* |dy| <<< |dx| means a near-horizontal segment */ - result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT; - } - else if ( ax * 12 < ay ) - { - /* |dx| <<< |dy| means a near-vertical segment */ - result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN; - } - - return result; - } - - - /* load outline point coordinates into hinter glyph */ - static void - psh_glyph_load_points( PSH_Glyph glyph, - FT_Int dimension ) - { - FT_Vector* vec = glyph->outline->points; - PSH_Point point = glyph->points; - FT_UInt count = glyph->num_points; - - - for ( ; count > 0; count--, point++, vec++ ) - { - point->flags2 = 0; - point->hint = NULL; - if ( dimension == 0 ) - { - point->org_u = vec->x; - point->org_v = vec->y; - } - else - { - point->org_u = vec->y; - point->org_v = vec->x; - } - -#ifdef DEBUG_HINTER - point->org_x = vec->x; - point->org_y = vec->y; -#endif - - } - } - - - /* save hinted point coordinates back to outline */ - static void - psh_glyph_save_points( PSH_Glyph glyph, - FT_Int dimension ) - { - FT_UInt n; - PSH_Point point = glyph->points; - FT_Vector* vec = glyph->outline->points; - char* tags = glyph->outline->tags; - - - for ( n = 0; n < glyph->num_points; n++ ) - { - if ( dimension == 0 ) - vec[n].x = point->cur_u; - else - vec[n].y = point->cur_u; - - if ( psh_point_is_strong( point ) ) - tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 ); - -#ifdef DEBUG_HINTER - - if ( dimension == 0 ) - { - point->cur_x = point->cur_u; - point->flags_x = point->flags2 | point->flags; - } - else - { - point->cur_y = point->cur_u; - point->flags_y = point->flags2 | point->flags; - } - -#endif - - point++; - } - } - - - static FT_Error - psh_glyph_init( PSH_Glyph glyph, - FT_Outline* outline, - PS_Hints ps_hints, - PSH_Globals globals ) - { - FT_Error error; - FT_Memory memory; - - - /* clear all fields */ - FT_MEM_ZERO( glyph, sizeof ( *glyph ) ); - - memory = glyph->memory = globals->memory; - - /* allocate and setup points + contours arrays */ - if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || - FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) - goto Exit; - - glyph->num_points = (FT_UInt)outline->n_points; - glyph->num_contours = (FT_UInt)outline->n_contours; - - { - FT_UInt first = 0, next, n; - PSH_Point points = glyph->points; - PSH_Contour contour = glyph->contours; - - - for ( n = 0; n < glyph->num_contours; n++ ) - { - FT_UInt count; - PSH_Point point; - - - next = (FT_UInt)outline->contours[n] + 1; - count = next - first; - - contour->start = points + first; - contour->count = count; - - if ( count > 0 ) - { - point = points + first; - - point->prev = points + next - 1; - point->contour = contour; - - for ( ; count > 1; count-- ) - { - point[0].next = point + 1; - point[1].prev = point; - point++; - point->contour = contour; - } - point->next = points + first; - } - - contour++; - first = next; - } - } - - { - PSH_Point points = glyph->points; - PSH_Point point = points; - FT_Vector* vec = outline->points; - FT_UInt n; - - - for ( n = 0; n < glyph->num_points; n++, point++ ) - { - FT_Int n_prev = (FT_Int)( point->prev - points ); - FT_Int n_next = (FT_Int)( point->next - points ); - FT_Pos dxi, dyi, dxo, dyo; - - - if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) ) - point->flags = PSH_POINT_OFF; - - dxi = vec[n].x - vec[n_prev].x; - dyi = vec[n].y - vec[n_prev].y; - - point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi ); - - dxo = vec[n_next].x - vec[n].x; - dyo = vec[n_next].y - vec[n].y; - - point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo ); - - /* detect smooth points */ - if ( point->flags & PSH_POINT_OFF ) - point->flags |= PSH_POINT_SMOOTH; - - else if ( point->dir_in == point->dir_out ) - { - if ( point->dir_out != PSH_DIR_NONE || - psh_corner_is_flat( dxi, dyi, dxo, dyo ) ) - point->flags |= PSH_POINT_SMOOTH; - } - } - } - - glyph->outline = outline; - glyph->globals = globals; - -#ifdef COMPUTE_INFLEXS - psh_glyph_load_points( glyph, 0 ); - psh_glyph_compute_inflections( glyph ); -#endif /* COMPUTE_INFLEXS */ - - /* now deal with hints tables */ - error = psh_hint_table_init( &glyph->hint_tables [0], - &ps_hints->dimension[0].hints, - &ps_hints->dimension[0].masks, - &ps_hints->dimension[0].counters, - memory ); - if ( error ) - goto Exit; - - error = psh_hint_table_init( &glyph->hint_tables [1], - &ps_hints->dimension[1].hints, - &ps_hints->dimension[1].masks, - &ps_hints->dimension[1].counters, - memory ); - if ( error ) - goto Exit; - - Exit: - return error; - } - - - /* compute all extrema in a glyph for a given dimension */ - static void - psh_glyph_compute_extrema( PSH_Glyph glyph ) - { - FT_UInt n; - - - /* first of all, compute all local extrema */ - for ( n = 0; n < glyph->num_contours; n++ ) - { - PSH_Point first = glyph->contours[n].start; - PSH_Point point, before, after; - - - if ( glyph->contours[n].count == 0 ) - continue; - - point = first; - before = point; - - do - { - before = before->prev; - if ( before == first ) - goto Skip; - - } while ( before->org_u == point->org_u ); - - first = point = before->next; - - for (;;) - { - after = point; - do - { - after = after->next; - if ( after == first ) - goto Next; - - } while ( after->org_u == point->org_u ); - - if ( before->org_u < point->org_u ) - { - if ( after->org_u < point->org_u ) - { - /* local maximum */ - goto Extremum; - } - } - else /* before->org_u > point->org_u */ - { - if ( after->org_u > point->org_u ) - { - /* local minimum */ - Extremum: - do - { - psh_point_set_extremum( point ); - point = point->next; - - } while ( point != after ); - } - } - - before = after->prev; - point = after; - - } /* for */ - - Next: - ; - } - - /* for each extremum, determine its direction along the */ - /* orthogonal axis */ - for ( n = 0; n < glyph->num_points; n++ ) - { - PSH_Point point, before, after; - - - point = &glyph->points[n]; - before = point; - after = point; - - if ( psh_point_is_extremum( point ) ) - { - do - { - before = before->prev; - if ( before == point ) - goto Skip; - - } while ( before->org_v == point->org_v ); - - do - { - after = after->next; - if ( after == point ) - goto Skip; - - } while ( after->org_v == point->org_v ); - } - - if ( before->org_v < point->org_v && - after->org_v > point->org_v ) - { - psh_point_set_positive( point ); - } - else if ( before->org_v > point->org_v && - after->org_v < point->org_v ) - { - psh_point_set_negative( point ); - } - - Skip: - ; - } - } - - - /* major_dir is the direction for points on the bottom/left of the stem; */ - /* Points on the top/right of the stem will have a direction of */ - /* -major_dir. */ - - static void - psh_hint_table_find_strong_points( PSH_Hint_Table table, - PSH_Point point, - FT_UInt count, - FT_Int threshold, - FT_Int major_dir ) - { - PSH_Hint* sort = table->sort; - FT_UInt num_hints = table->num_hints; - - - for ( ; count > 0; count--, point++ ) - { - FT_Int point_dir = 0; - FT_Pos org_u = point->org_u; - - - if ( psh_point_is_strong( point ) ) - continue; - - if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) ) - point_dir = point->dir_in; - - else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) ) - point_dir = point->dir_out; - - if ( point_dir ) - { - if ( point_dir == major_dir ) - { - FT_UInt nn; - - - for ( nn = 0; nn < num_hints; nn++ ) - { - PSH_Hint hint = sort[nn]; - FT_Pos d = org_u - hint->org_pos; - - - if ( d < threshold && -d < threshold ) - { - psh_point_set_strong( point ); - point->flags2 |= PSH_POINT_EDGE_MIN; - point->hint = hint; - break; - } - } - } - else if ( point_dir == -major_dir ) - { - FT_UInt nn; - - - for ( nn = 0; nn < num_hints; nn++ ) - { - PSH_Hint hint = sort[nn]; - FT_Pos d = org_u - hint->org_pos - hint->org_len; - - - if ( d < threshold && -d < threshold ) - { - psh_point_set_strong( point ); - point->flags2 |= PSH_POINT_EDGE_MAX; - point->hint = hint; - break; - } - } - } - } - -#if 1 - else if ( psh_point_is_extremum( point ) ) - { - /* treat extrema as special cases for stem edge alignment */ - FT_UInt nn, min_flag, max_flag; - - - if ( major_dir == PSH_DIR_HORIZONTAL ) - { - min_flag = PSH_POINT_POSITIVE; - max_flag = PSH_POINT_NEGATIVE; - } - else - { - min_flag = PSH_POINT_NEGATIVE; - max_flag = PSH_POINT_POSITIVE; - } - - if ( point->flags2 & min_flag ) - { - for ( nn = 0; nn < num_hints; nn++ ) - { - PSH_Hint hint = sort[nn]; - FT_Pos d = org_u - hint->org_pos; - - - if ( d < threshold && -d < threshold ) - { - point->flags2 |= PSH_POINT_EDGE_MIN; - point->hint = hint; - psh_point_set_strong( point ); - break; - } - } - } - else if ( point->flags2 & max_flag ) - { - for ( nn = 0; nn < num_hints; nn++ ) - { - PSH_Hint hint = sort[nn]; - FT_Pos d = org_u - hint->org_pos - hint->org_len; - - - if ( d < threshold && -d < threshold ) - { - point->flags2 |= PSH_POINT_EDGE_MAX; - point->hint = hint; - psh_point_set_strong( point ); - break; - } - } - } - - if ( point->hint == NULL ) - { - for ( nn = 0; nn < num_hints; nn++ ) - { - PSH_Hint hint = sort[nn]; - - - if ( org_u >= hint->org_pos && - org_u <= hint->org_pos + hint->org_len ) - { - point->hint = hint; - break; - } - } - } - } - -#endif /* 1 */ - } - } - - - /* the accepted shift for strong points in fractional pixels */ -#define PSH_STRONG_THRESHOLD 32 - - /* the maximum shift value in font units */ -#define PSH_STRONG_THRESHOLD_MAXIMUM 30 - - - /* find strong points in a glyph */ - static void - psh_glyph_find_strong_points( PSH_Glyph glyph, - FT_Int dimension ) - { - /* a point is `strong' if it is located on a stem edge and */ - /* has an `in' or `out' tangent parallel to the hint's direction */ - - PSH_Hint_Table table = &glyph->hint_tables[dimension]; - PS_Mask mask = table->hint_masks->masks; - FT_UInt num_masks = table->hint_masks->num_masks; - FT_UInt first = 0; - FT_Int major_dir = dimension == 0 ? PSH_DIR_VERTICAL - : PSH_DIR_HORIZONTAL; - PSH_Dimension dim = &glyph->globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Int threshold; - - - threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale ); - if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM ) - threshold = PSH_STRONG_THRESHOLD_MAXIMUM; - - /* process secondary hints to `selected' points */ - if ( num_masks > 1 && glyph->num_points > 0 ) - { - /* the `endchar' op can reduce the number of points */ - first = mask->end_point > glyph->num_points - ? glyph->num_points - : mask->end_point; - mask++; - for ( ; num_masks > 1; num_masks--, mask++ ) - { - FT_UInt next = FT_MIN( mask->end_point, glyph->num_points ); - - - if ( next > first ) - { - FT_UInt count = next - first; - PSH_Point point = glyph->points + first; - - - psh_hint_table_activate_mask( table, mask ); - - psh_hint_table_find_strong_points( table, point, count, - threshold, major_dir ); - } - first = next; - } - } - - /* process primary hints for all points */ - if ( num_masks == 1 ) - { - FT_UInt count = glyph->num_points; - PSH_Point point = glyph->points; - - - psh_hint_table_activate_mask( table, table->hint_masks->masks ); - - psh_hint_table_find_strong_points( table, point, count, - threshold, major_dir ); - } - - /* now, certain points may have been attached to a hint and */ - /* not marked as strong; update their flags then */ - { - FT_UInt count = glyph->num_points; - PSH_Point point = glyph->points; - - - for ( ; count > 0; count--, point++ ) - if ( point->hint && !psh_point_is_strong( point ) ) - psh_point_set_strong( point ); - } - } - - - /* find points in a glyph which are in a blue zone and have `in' or */ - /* `out' tangents parallel to the horizontal axis */ - static void - psh_glyph_find_blue_points( PSH_Blues blues, - PSH_Glyph glyph ) - { - PSH_Blue_Table table; - PSH_Blue_Zone zone; - FT_UInt glyph_count = glyph->num_points; - FT_UInt blue_count; - PSH_Point point = glyph->points; - - - for ( ; glyph_count > 0; glyph_count--, point++ ) - { - FT_Pos y; - - - /* check tangents */ - if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) && - !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) ) - continue; - - /* skip strong points */ - if ( psh_point_is_strong( point ) ) - continue; - - y = point->org_u; - - /* look up top zones */ - table = &blues->normal_top; - blue_count = table->count; - zone = table->zones; - - for ( ; blue_count > 0; blue_count--, zone++ ) - { - FT_Pos delta = y - zone->org_bottom; - - - if ( delta < -blues->blue_fuzz ) - break; - - if ( y <= zone->org_top + blues->blue_fuzz ) - if ( blues->no_overshoots || delta <= blues->blue_threshold ) - { - point->cur_u = zone->cur_bottom; - psh_point_set_strong( point ); - psh_point_set_fitted( point ); - } - } - - /* look up bottom zones */ - table = &blues->normal_bottom; - blue_count = table->count; - zone = table->zones + blue_count - 1; - - for ( ; blue_count > 0; blue_count--, zone-- ) - { - FT_Pos delta = zone->org_top - y; - - - if ( delta < -blues->blue_fuzz ) - break; - - if ( y >= zone->org_bottom - blues->blue_fuzz ) - if ( blues->no_overshoots || delta < blues->blue_threshold ) - { - point->cur_u = zone->cur_top; - psh_point_set_strong( point ); - psh_point_set_fitted( point ); - } - } - } - } - - - /* interpolate strong points with the help of hinted coordinates */ - static void - psh_glyph_interpolate_strong_points( PSH_Glyph glyph, - FT_Int dimension ) - { - PSH_Dimension dim = &glyph->globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - - FT_UInt count = glyph->num_points; - PSH_Point point = glyph->points; - - - for ( ; count > 0; count--, point++ ) - { - PSH_Hint hint = point->hint; - - - if ( hint ) - { - FT_Pos delta; - - - if ( psh_point_is_edge_min( point ) ) - point->cur_u = hint->cur_pos; - - else if ( psh_point_is_edge_max( point ) ) - point->cur_u = hint->cur_pos + hint->cur_len; - - else - { - delta = point->org_u - hint->org_pos; - - if ( delta <= 0 ) - point->cur_u = hint->cur_pos + FT_MulFix( delta, scale ); - - else if ( delta >= hint->org_len ) - point->cur_u = hint->cur_pos + hint->cur_len + - FT_MulFix( delta - hint->org_len, scale ); - - else /* hint->org_len > 0 */ - point->cur_u = hint->cur_pos + - FT_MulDiv( delta, hint->cur_len, - hint->org_len ); - } - psh_point_set_fitted( point ); - } - } - } - - -#define PSH_MAX_STRONG_INTERNAL 16 - - static void - psh_glyph_interpolate_normal_points( PSH_Glyph glyph, - FT_Int dimension ) - { - -#if 1 - /* first technique: a point is strong if it is a local extremum */ - - PSH_Dimension dim = &glyph->globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Memory memory = glyph->memory; - - PSH_Point* strongs = NULL; - PSH_Point strongs_0[PSH_MAX_STRONG_INTERNAL]; - FT_UInt num_strongs = 0; - - PSH_Point points = glyph->points; - PSH_Point points_end = points + glyph->num_points; - PSH_Point point; - - - /* first count the number of strong points */ - for ( point = points; point < points_end; point++ ) - { - if ( psh_point_is_strong( point ) ) - num_strongs++; - } - - if ( num_strongs == 0 ) /* nothing to do here */ - return; - - /* allocate an array to store a list of points, */ - /* stored in increasing org_u order */ - if ( num_strongs <= PSH_MAX_STRONG_INTERNAL ) - strongs = strongs_0; - else - { - FT_Error error; - - - if ( FT_NEW_ARRAY( strongs, num_strongs ) ) - return; - } - - num_strongs = 0; - for ( point = points; point < points_end; point++ ) - { - PSH_Point* insert; - - - if ( !psh_point_is_strong( point ) ) - continue; - - for ( insert = strongs + num_strongs; insert > strongs; insert-- ) - { - if ( insert[-1]->org_u <= point->org_u ) - break; - - insert[0] = insert[-1]; - } - insert[0] = point; - num_strongs++; - } - - /* now try to interpolate all normal points */ - for ( point = points; point < points_end; point++ ) - { - if ( psh_point_is_strong( point ) ) - continue; - - /* sometimes, some local extrema are smooth points */ - if ( psh_point_is_smooth( point ) ) - { - if ( point->dir_in == PSH_DIR_NONE || - point->dir_in != point->dir_out ) - continue; - - if ( !psh_point_is_extremum( point ) && - !psh_point_is_inflex( point ) ) - continue; - - point->flags &= ~PSH_POINT_SMOOTH; - } - - /* find best enclosing point coordinates then interpolate */ - { - PSH_Point before, after; - FT_UInt nn; - - - for ( nn = 0; nn < num_strongs; nn++ ) - if ( strongs[nn]->org_u > point->org_u ) - break; - - if ( nn == 0 ) /* point before the first strong point */ - { - after = strongs[0]; - - point->cur_u = after->cur_u + - FT_MulFix( point->org_u - after->org_u, - scale ); - } - else - { - before = strongs[nn - 1]; - - for ( nn = num_strongs; nn > 0; nn-- ) - if ( strongs[nn - 1]->org_u < point->org_u ) - break; - - if ( nn == num_strongs ) /* point is after last strong point */ - { - before = strongs[nn - 1]; - - point->cur_u = before->cur_u + - FT_MulFix( point->org_u - before->org_u, - scale ); - } - else - { - FT_Pos u; - - - after = strongs[nn]; - - /* now interpolate point between before and after */ - u = point->org_u; - - if ( u == before->org_u ) - point->cur_u = before->cur_u; - - else if ( u == after->org_u ) - point->cur_u = after->cur_u; - - else - point->cur_u = before->cur_u + - FT_MulDiv( u - before->org_u, - after->cur_u - before->cur_u, - after->org_u - before->org_u ); - } - } - psh_point_set_fitted( point ); - } - } - - if ( strongs != strongs_0 ) - FT_FREE( strongs ); - -#endif /* 1 */ - - } - - - /* interpolate other points */ - static void - psh_glyph_interpolate_other_points( PSH_Glyph glyph, - FT_Int dimension ) - { - PSH_Dimension dim = &glyph->globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Fixed delta = dim->scale_delta; - PSH_Contour contour = glyph->contours; - FT_UInt num_contours = glyph->num_contours; - - - for ( ; num_contours > 0; num_contours--, contour++ ) - { - PSH_Point start = contour->start; - PSH_Point first, next, point; - FT_UInt fit_count; - - - /* count the number of strong points in this contour */ - next = start + contour->count; - fit_count = 0; - first = NULL; - - for ( point = start; point < next; point++ ) - if ( psh_point_is_fitted( point ) ) - { - if ( !first ) - first = point; - - fit_count++; - } - - /* if there are less than 2 fitted points in the contour, we */ - /* simply scale and eventually translate the contour points */ - if ( fit_count < 2 ) - { - if ( fit_count == 1 ) - delta = first->cur_u - FT_MulFix( first->org_u, scale ); - - for ( point = start; point < next; point++ ) - if ( point != first ) - point->cur_u = FT_MulFix( point->org_u, scale ) + delta; - - goto Next_Contour; - } - - /* there are more than 2 strong points in this contour; we */ - /* need to interpolate weak points between them */ - start = first; - do - { - /* skip consecutive fitted points */ - for (;;) - { - next = first->next; - if ( next == start ) - goto Next_Contour; - - if ( !psh_point_is_fitted( next ) ) - break; - - first = next; - } - - /* find next fitted point after unfitted one */ - for (;;) - { - next = next->next; - if ( psh_point_is_fitted( next ) ) - break; - } - - /* now interpolate between them */ - { - FT_Pos org_a, org_ab, cur_a, cur_ab; - FT_Pos org_c, org_ac, cur_c; - FT_Fixed scale_ab; - - - if ( first->org_u <= next->org_u ) - { - org_a = first->org_u; - cur_a = first->cur_u; - org_ab = next->org_u - org_a; - cur_ab = next->cur_u - cur_a; - } - else - { - org_a = next->org_u; - cur_a = next->cur_u; - org_ab = first->org_u - org_a; - cur_ab = first->cur_u - cur_a; - } - - scale_ab = 0x10000L; - if ( org_ab > 0 ) - scale_ab = FT_DivFix( cur_ab, org_ab ); - - point = first->next; - do - { - org_c = point->org_u; - org_ac = org_c - org_a; - - if ( org_ac <= 0 ) - { - /* on the left of the interpolation zone */ - cur_c = cur_a + FT_MulFix( org_ac, scale ); - } - else if ( org_ac >= org_ab ) - { - /* on the right on the interpolation zone */ - cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale ); - } - else - { - /* within the interpolation zone */ - cur_c = cur_a + FT_MulFix( org_ac, scale_ab ); - } - - point->cur_u = cur_c; - - point = point->next; - - } while ( point != next ); - } - - /* keep going until all points in the contours have been processed */ - first = next; - - } while ( first != start ); - - Next_Contour: - ; - } - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** HIGH-LEVEL INTERFACE *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_Error - ps_hints_apply( PS_Hints ps_hints, - FT_Outline* outline, - PSH_Globals globals, - FT_Render_Mode hint_mode ) - { - PSH_GlyphRec glyphrec; - PSH_Glyph glyph = &glyphrec; - FT_Error error; -#ifdef DEBUG_HINTER - FT_Memory memory; -#endif - FT_Int dimension; - - - /* something to do? */ - if ( outline->n_points == 0 || outline->n_contours == 0 ) - return FT_Err_Ok; - -#ifdef DEBUG_HINTER - - memory = globals->memory; - - if ( ps_debug_glyph ) - { - psh_glyph_done( ps_debug_glyph ); - FT_FREE( ps_debug_glyph ); - } - - if ( FT_NEW( glyph ) ) - return error; - - ps_debug_glyph = glyph; - -#endif /* DEBUG_HINTER */ - - error = psh_glyph_init( glyph, outline, ps_hints, globals ); - if ( error ) - goto Exit; - - /* try to optimize the y_scale so that the top of non-capital letters - * is aligned on a pixel boundary whenever possible - */ - { - PSH_Dimension dim_x = &glyph->globals->dimension[0]; - PSH_Dimension dim_y = &glyph->globals->dimension[1]; - - FT_Fixed x_scale = dim_x->scale_mult; - FT_Fixed y_scale = dim_y->scale_mult; - - FT_Fixed old_x_scale = x_scale; - FT_Fixed old_y_scale = y_scale; - - FT_Fixed scaled; - FT_Fixed fitted; - - FT_Bool rescale = FALSE; - - - scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); - fitted = FT_PIX_ROUND( scaled ); - - if ( fitted != 0 && scaled != fitted ) - { - rescale = TRUE; - - y_scale = FT_MulDiv( y_scale, fitted, scaled ); - - if ( fitted < scaled ) - x_scale -= x_scale / 50; - - psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 ); - } - - glyph->do_horz_hints = 1; - glyph->do_vert_hints = 1; - - glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || - hint_mode == FT_RENDER_MODE_LCD ); - - glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || - hint_mode == FT_RENDER_MODE_LCD_V ); - - glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); - - for ( dimension = 0; dimension < 2; dimension++ ) - { - /* load outline coordinates into glyph */ - psh_glyph_load_points( glyph, dimension ); - - /* compute local extrema */ - psh_glyph_compute_extrema( glyph ); - - /* compute aligned stem/hints positions */ - psh_hint_table_align_hints( &glyph->hint_tables[dimension], - glyph->globals, - dimension, - glyph ); - - /* find strong points, align them, then interpolate others */ - psh_glyph_find_strong_points( glyph, dimension ); - if ( dimension == 1 ) - psh_glyph_find_blue_points( &globals->blues, glyph ); - psh_glyph_interpolate_strong_points( glyph, dimension ); - psh_glyph_interpolate_normal_points( glyph, dimension ); - psh_glyph_interpolate_other_points( glyph, dimension ); - - /* save hinted coordinates back to outline */ - psh_glyph_save_points( glyph, dimension ); - - if ( rescale ) - psh_globals_set_scale( glyph->globals, - old_x_scale, old_y_scale, 0, 0 ); - } - } - - Exit: - -#ifndef DEBUG_HINTER - psh_glyph_done( glyph ); -#endif - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshalgo.h b/third_party/freetype/src/pshinter/pshalgo.h deleted file mode 100644 index 8373e5ec29e4366fcb3ec79fcd1b80fe3a2fed46..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshalgo.h +++ /dev/null @@ -1,241 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshalgo.h */ -/* */ -/* PostScript hinting algorithm (specification). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSHALGO_H__ -#define __PSHALGO_H__ - - -#include "pshrec.h" -#include "pshglob.h" - - -FT_BEGIN_HEADER - - - /* handle to Hint structure */ - typedef struct PSH_HintRec_* PSH_Hint; - - - /* hint bit-flags */ -#define PSH_HINT_GHOST PS_HINT_FLAG_GHOST -#define PSH_HINT_BOTTOM PS_HINT_FLAG_BOTTOM -#define PSH_HINT_ACTIVE 4U -#define PSH_HINT_FITTED 8U - - -#define psh_hint_is_active( x ) ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 ) -#define psh_hint_is_ghost( x ) ( ( (x)->flags & PSH_HINT_GHOST ) != 0 ) -#define psh_hint_is_fitted( x ) ( ( (x)->flags & PSH_HINT_FITTED ) != 0 ) - -#define psh_hint_activate( x ) (x)->flags |= PSH_HINT_ACTIVE -#define psh_hint_deactivate( x ) (x)->flags &= ~PSH_HINT_ACTIVE -#define psh_hint_set_fitted( x ) (x)->flags |= PSH_HINT_FITTED - - - /* hint structure */ - typedef struct PSH_HintRec_ - { - FT_Int org_pos; - FT_Int org_len; - FT_Pos cur_pos; - FT_Pos cur_len; - FT_UInt flags; - PSH_Hint parent; - FT_Int order; - - } PSH_HintRec; - - - /* this is an interpolation zone used for strong points; */ - /* weak points are interpolated according to their strong */ - /* neighbours */ - typedef struct PSH_ZoneRec_ - { - FT_Fixed scale; - FT_Fixed delta; - FT_Pos min; - FT_Pos max; - - } PSH_ZoneRec, *PSH_Zone; - - - typedef struct PSH_Hint_TableRec_ - { - FT_UInt max_hints; - FT_UInt num_hints; - PSH_Hint hints; - PSH_Hint* sort; - PSH_Hint* sort_global; - FT_UInt num_zones; - PSH_ZoneRec* zones; - PSH_Zone zone; - PS_Mask_Table hint_masks; - PS_Mask_Table counter_masks; - - } PSH_Hint_TableRec, *PSH_Hint_Table; - - - typedef struct PSH_PointRec_* PSH_Point; - typedef struct PSH_ContourRec_* PSH_Contour; - - enum - { - PSH_DIR_NONE = 4, - PSH_DIR_UP = -1, - PSH_DIR_DOWN = 1, - PSH_DIR_LEFT = -2, - PSH_DIR_RIGHT = 2 - }; - -#define PSH_DIR_HORIZONTAL 2 -#define PSH_DIR_VERTICAL 1 - -#define PSH_DIR_COMPARE( d1, d2 ) ( (d1) == (d2) || (d1) == -(d2) ) -#define PSH_DIR_IS_HORIZONTAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL ) -#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL ) - - - /* the following bit-flags are computed once by the glyph */ - /* analyzer, for both dimensions */ -#define PSH_POINT_OFF 1U /* point is off the curve */ -#define PSH_POINT_SMOOTH 2U /* point is smooth */ -#define PSH_POINT_INFLEX 4U /* point is inflection */ - - -#define psh_point_is_smooth( p ) ( (p)->flags & PSH_POINT_SMOOTH ) -#define psh_point_is_off( p ) ( (p)->flags & PSH_POINT_OFF ) -#define psh_point_is_inflex( p ) ( (p)->flags & PSH_POINT_INFLEX ) - -#define psh_point_set_smooth( p ) (p)->flags |= PSH_POINT_SMOOTH -#define psh_point_set_off( p ) (p)->flags |= PSH_POINT_OFF -#define psh_point_set_inflex( p ) (p)->flags |= PSH_POINT_INFLEX - - - /* the following bit-flags are re-computed for each dimension */ -#define PSH_POINT_STRONG 16U /* point is strong */ -#define PSH_POINT_FITTED 32U /* point is already fitted */ -#define PSH_POINT_EXTREMUM 64U /* point is local extremum */ -#define PSH_POINT_POSITIVE 128U /* extremum has positive contour flow */ -#define PSH_POINT_NEGATIVE 256U /* extremum has negative contour flow */ -#define PSH_POINT_EDGE_MIN 512U /* point is aligned to left/bottom stem edge */ -#define PSH_POINT_EDGE_MAX 1024U /* point is aligned to top/right stem edge */ - - -#define psh_point_is_strong( p ) ( (p)->flags2 & PSH_POINT_STRONG ) -#define psh_point_is_fitted( p ) ( (p)->flags2 & PSH_POINT_FITTED ) -#define psh_point_is_extremum( p ) ( (p)->flags2 & PSH_POINT_EXTREMUM ) -#define psh_point_is_positive( p ) ( (p)->flags2 & PSH_POINT_POSITIVE ) -#define psh_point_is_negative( p ) ( (p)->flags2 & PSH_POINT_NEGATIVE ) -#define psh_point_is_edge_min( p ) ( (p)->flags2 & PSH_POINT_EDGE_MIN ) -#define psh_point_is_edge_max( p ) ( (p)->flags2 & PSH_POINT_EDGE_MAX ) - -#define psh_point_set_strong( p ) (p)->flags2 |= PSH_POINT_STRONG -#define psh_point_set_fitted( p ) (p)->flags2 |= PSH_POINT_FITTED -#define psh_point_set_extremum( p ) (p)->flags2 |= PSH_POINT_EXTREMUM -#define psh_point_set_positive( p ) (p)->flags2 |= PSH_POINT_POSITIVE -#define psh_point_set_negative( p ) (p)->flags2 |= PSH_POINT_NEGATIVE -#define psh_point_set_edge_min( p ) (p)->flags2 |= PSH_POINT_EDGE_MIN -#define psh_point_set_edge_max( p ) (p)->flags2 |= PSH_POINT_EDGE_MAX - - - typedef struct PSH_PointRec_ - { - PSH_Point prev; - PSH_Point next; - PSH_Contour contour; - FT_UInt flags; - FT_UInt flags2; - FT_Char dir_in; - FT_Char dir_out; - PSH_Hint hint; - FT_Pos org_u; - FT_Pos org_v; - FT_Pos cur_u; -#ifdef DEBUG_HINTER - FT_Pos org_x; - FT_Pos cur_x; - FT_Pos org_y; - FT_Pos cur_y; - FT_UInt flags_x; - FT_UInt flags_y; -#endif - - } PSH_PointRec; - - - typedef struct PSH_ContourRec_ - { - PSH_Point start; - FT_UInt count; - - } PSH_ContourRec; - - - typedef struct PSH_GlyphRec_ - { - FT_UInt num_points; - FT_UInt num_contours; - - PSH_Point points; - PSH_Contour contours; - - FT_Memory memory; - FT_Outline* outline; - PSH_Globals globals; - PSH_Hint_TableRec hint_tables[2]; - - FT_Bool vertical; - FT_Int major_dir; - FT_Int minor_dir; - - FT_Bool do_horz_hints; - FT_Bool do_vert_hints; - FT_Bool do_horz_snapping; - FT_Bool do_vert_snapping; - FT_Bool do_stem_adjust; - - } PSH_GlyphRec, *PSH_Glyph; - - -#ifdef DEBUG_HINTER - extern PSH_Hint_Table ps_debug_hint_table; - - typedef void - (*PSH_HintFunc)( PSH_Hint hint, - FT_Bool vertical ); - - extern PSH_HintFunc ps_debug_hint_func; - - extern PSH_Glyph ps_debug_glyph; -#endif - - - extern FT_Error - ps_hints_apply( PS_Hints ps_hints, - FT_Outline* outline, - PSH_Globals globals, - FT_Render_Mode hint_mode ); - - -FT_END_HEADER - - -#endif /* __PSHALGO_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshglob.c b/third_party/freetype/src/pshinter/pshglob.c deleted file mode 100644 index 4616bdc6cf35abc7b6a4b130e8b86dec284ab8ad..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshglob.c +++ /dev/null @@ -1,795 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshglob.c */ -/* */ -/* PostScript hinter global hinting management (body). */ -/* Inspired by the new auto-hinter module. */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used */ -/* modified and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "pshglob.h" - -#ifdef DEBUG_HINTER - PSH_Globals ps_debug_globals = NULL; -#endif - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** STANDARD WIDTHS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /* scale the widths/heights table */ - static void - psh_globals_scale_widths( PSH_Globals globals, - FT_UInt direction ) - { - PSH_Dimension dim = &globals->dimension[direction]; - PSH_Widths stdw = &dim->stdw; - FT_UInt count = stdw->count; - PSH_Width width = stdw->widths; - PSH_Width stand = width; /* standard width/height */ - FT_Fixed scale = dim->scale_mult; - - - if ( count > 0 ) - { - width->cur = FT_MulFix( width->org, scale ); - width->fit = FT_PIX_ROUND( width->cur ); - - width++; - count--; - - for ( ; count > 0; count--, width++ ) - { - FT_Pos w, dist; - - - w = FT_MulFix( width->org, scale ); - dist = w - stand->cur; - - if ( dist < 0 ) - dist = -dist; - - if ( dist < 128 ) - w = stand->cur; - - width->cur = w; - width->fit = FT_PIX_ROUND( w ); - } - } - } - - -#if 0 - - /* org_width is is font units, result in device pixels, 26.6 format */ - FT_LOCAL_DEF( FT_Pos ) - psh_dimension_snap_width( PSH_Dimension dimension, - FT_Int org_width ) - { - FT_UInt n; - FT_Pos width = FT_MulFix( org_width, dimension->scale_mult ); - FT_Pos best = 64 + 32 + 2; - FT_Pos reference = width; - - - for ( n = 0; n < dimension->stdw.count; n++ ) - { - FT_Pos w; - FT_Pos dist; - - - w = dimension->stdw.widths[n].cur; - dist = width - w; - if ( dist < 0 ) - dist = -dist; - if ( dist < best ) - { - best = dist; - reference = w; - } - } - - if ( width >= reference ) - { - width -= 0x21; - if ( width < reference ) - width = reference; - } - else - { - width += 0x21; - if ( width > reference ) - width = reference; - } - - return width; - } - -#endif /* 0 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** BLUE ZONES *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static void - psh_blues_set_zones_0( PSH_Blues target, - FT_Bool is_others, - FT_UInt read_count, - FT_Short* read, - PSH_Blue_Table top_table, - PSH_Blue_Table bot_table ) - { - FT_UInt count_top = top_table->count; - FT_UInt count_bot = bot_table->count; - FT_Bool first = 1; - - FT_UNUSED( target ); - - - for ( ; read_count > 1; read_count -= 2 ) - { - FT_Int reference, delta; - FT_UInt count; - PSH_Blue_Zone zones, zone; - FT_Bool top; - - - /* read blue zone entry, and select target top/bottom zone */ - top = 0; - if ( first || is_others ) - { - reference = read[1]; - delta = read[0] - reference; - - zones = bot_table->zones; - count = count_bot; - first = 0; - } - else - { - reference = read[0]; - delta = read[1] - reference; - - zones = top_table->zones; - count = count_top; - top = 1; - } - - /* insert into sorted table */ - zone = zones; - for ( ; count > 0; count--, zone++ ) - { - if ( reference < zone->org_ref ) - break; - - if ( reference == zone->org_ref ) - { - FT_Int delta0 = zone->org_delta; - - - /* we have two zones on the same reference position -- */ - /* only keep the largest one */ - if ( delta < 0 ) - { - if ( delta < delta0 ) - zone->org_delta = delta; - } - else - { - if ( delta > delta0 ) - zone->org_delta = delta; - } - goto Skip; - } - } - - for ( ; count > 0; count-- ) - zone[count] = zone[count-1]; - - zone->org_ref = reference; - zone->org_delta = delta; - - if ( top ) - count_top++; - else - count_bot++; - - Skip: - read += 2; - } - - top_table->count = count_top; - bot_table->count = count_bot; - } - - - /* Re-read blue zones from the original fonts and store them into out */ - /* private structure. This function re-orders, sanitizes and */ - /* fuzz-expands the zones as well. */ - static void - psh_blues_set_zones( PSH_Blues target, - FT_UInt count, - FT_Short* blues, - FT_UInt count_others, - FT_Short* other_blues, - FT_Int fuzz, - FT_Int family ) - { - PSH_Blue_Table top_table, bot_table; - FT_UInt count_top, count_bot; - - - if ( family ) - { - top_table = &target->family_top; - bot_table = &target->family_bottom; - } - else - { - top_table = &target->normal_top; - bot_table = &target->normal_bottom; - } - - /* read the input blue zones, and build two sorted tables */ - /* (one for the top zones, the other for the bottom zones) */ - top_table->count = 0; - bot_table->count = 0; - - /* first, the blues */ - psh_blues_set_zones_0( target, 0, - count, blues, top_table, bot_table ); - psh_blues_set_zones_0( target, 1, - count_others, other_blues, top_table, bot_table ); - - count_top = top_table->count; - count_bot = bot_table->count; - - /* sanitize top table */ - if ( count_top > 0 ) - { - PSH_Blue_Zone zone = top_table->zones; - - - for ( count = count_top; count > 0; count--, zone++ ) - { - FT_Int delta; - - - if ( count > 1 ) - { - delta = zone[1].org_ref - zone[0].org_ref; - if ( zone->org_delta > delta ) - zone->org_delta = delta; - } - - zone->org_bottom = zone->org_ref; - zone->org_top = zone->org_delta + zone->org_ref; - } - } - - /* sanitize bottom table */ - if ( count_bot > 0 ) - { - PSH_Blue_Zone zone = bot_table->zones; - - - for ( count = count_bot; count > 0; count--, zone++ ) - { - FT_Int delta; - - - if ( count > 1 ) - { - delta = zone[0].org_ref - zone[1].org_ref; - if ( zone->org_delta < delta ) - zone->org_delta = delta; - } - - zone->org_top = zone->org_ref; - zone->org_bottom = zone->org_delta + zone->org_ref; - } - } - - /* expand top and bottom tables with blue fuzz */ - { - FT_Int dim, top, bot, delta; - PSH_Blue_Zone zone; - - - zone = top_table->zones; - count = count_top; - - for ( dim = 1; dim >= 0; dim-- ) - { - if ( count > 0 ) - { - /* expand the bottom of the lowest zone normally */ - zone->org_bottom -= fuzz; - - /* expand the top and bottom of intermediate zones; */ - /* checking that the interval is smaller than the fuzz */ - top = zone->org_top; - - for ( count--; count > 0; count-- ) - { - bot = zone[1].org_bottom; - delta = bot - top; - - if ( delta / 2 < fuzz ) - zone[0].org_top = zone[1].org_bottom = top + delta / 2; - else - { - zone[0].org_top = top + fuzz; - zone[1].org_bottom = bot - fuzz; - } - - zone++; - top = zone->org_top; - } - - /* expand the top of the highest zone normally */ - zone->org_top = top + fuzz; - } - zone = bot_table->zones; - count = count_bot; - } - } - } - - - /* reset the blues table when the device transform changes */ - static void - psh_blues_scale_zones( PSH_Blues blues, - FT_Fixed scale, - FT_Pos delta ) - { - FT_UInt count; - FT_UInt num; - PSH_Blue_Table table = NULL; - - /* */ - /* Determine whether we need to suppress overshoots or */ - /* not. We simply need to compare the vertical scale */ - /* parameter to the raw bluescale value. Here is why: */ - /* */ - /* We need to suppress overshoots for all pointsizes. */ - /* At 300dpi that satisfies: */ - /* */ - /* pointsize < 240*bluescale + 0.49 */ - /* */ - /* This corresponds to: */ - /* */ - /* pixelsize < 1000*bluescale + 49/24 */ - /* */ - /* scale*EM_Size < 1000*bluescale + 49/24 */ - /* */ - /* However, for normal Type 1 fonts, EM_Size is 1000! */ - /* We thus only check: */ - /* */ - /* scale < bluescale + 49/24000 */ - /* */ - /* which we shorten to */ - /* */ - /* "scale < bluescale" */ - /* */ - /* Note that `blue_scale' is stored 1000 times its real */ - /* value, and that `scale' converts from font units to */ - /* fractional pixels. */ - /* */ - - /* 1000 / 64 = 125 / 8 */ - if ( scale >= 0x20C49BAL ) - blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 ); - else - blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 ); - - /* */ - /* The blue threshold is the font units distance under */ - /* which overshoots are suppressed due to the BlueShift */ - /* even if the scale is greater than BlueScale. */ - /* */ - /* It is the smallest distance such that */ - /* */ - /* dist <= BlueShift && dist*scale <= 0.5 pixels */ - /* */ - { - FT_Int threshold = blues->blue_shift; - - - while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) - threshold--; - - blues->blue_threshold = threshold; - } - - for ( num = 0; num < 4; num++ ) - { - PSH_Blue_Zone zone; - - - switch ( num ) - { - case 0: - table = &blues->normal_top; - break; - case 1: - table = &blues->normal_bottom; - break; - case 2: - table = &blues->family_top; - break; - default: - table = &blues->family_bottom; - break; - } - - zone = table->zones; - count = table->count; - for ( ; count > 0; count--, zone++ ) - { - zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta; - zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta; - zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta; - zone->cur_delta = FT_MulFix( zone->org_delta, scale ); - - /* round scaled reference position */ - zone->cur_ref = FT_PIX_ROUND( zone->cur_ref ); - -#if 0 - if ( zone->cur_ref > zone->cur_top ) - zone->cur_ref -= 64; - else if ( zone->cur_ref < zone->cur_bottom ) - zone->cur_ref += 64; -#endif - } - } - - /* process the families now */ - - for ( num = 0; num < 2; num++ ) - { - PSH_Blue_Zone zone1, zone2; - FT_UInt count1, count2; - PSH_Blue_Table normal, family; - - - switch ( num ) - { - case 0: - normal = &blues->normal_top; - family = &blues->family_top; - break; - - default: - normal = &blues->normal_bottom; - family = &blues->family_bottom; - } - - zone1 = normal->zones; - count1 = normal->count; - - for ( ; count1 > 0; count1--, zone1++ ) - { - /* try to find a family zone whose reference position is less */ - /* than 1 pixel far from the current zone */ - zone2 = family->zones; - count2 = family->count; - - for ( ; count2 > 0; count2--, zone2++ ) - { - FT_Pos Delta; - - - Delta = zone1->org_ref - zone2->org_ref; - if ( Delta < 0 ) - Delta = -Delta; - - if ( FT_MulFix( Delta, scale ) < 64 ) - { - zone1->cur_top = zone2->cur_top; - zone1->cur_bottom = zone2->cur_bottom; - zone1->cur_ref = zone2->cur_ref; - zone1->cur_delta = zone2->cur_delta; - break; - } - } - } - } - } - - - /* calculate the maximum height of given blue zones */ - static FT_Short - psh_calc_max_height( FT_UInt num, - const FT_Short* values, - FT_Short cur_max ) - { - FT_UInt count; - - - for ( count = 0; count < num; count += 2 ) - { - FT_Short cur_height = values[count + 1] - values[count]; - - - if ( cur_height > cur_max ) - cur_max = cur_height; - } - - return cur_max; - } - - - FT_LOCAL_DEF( void ) - psh_blues_snap_stem( PSH_Blues blues, - FT_Int stem_top, - FT_Int stem_bot, - PSH_Alignment alignment ) - { - PSH_Blue_Table table; - FT_UInt count; - FT_Pos delta; - PSH_Blue_Zone zone; - FT_Int no_shoots; - - - alignment->align = PSH_BLUE_ALIGN_NONE; - - no_shoots = blues->no_overshoots; - - /* look up stem top in top zones table */ - table = &blues->normal_top; - count = table->count; - zone = table->zones; - - for ( ; count > 0; count--, zone++ ) - { - delta = stem_top - zone->org_bottom; - if ( delta < -blues->blue_fuzz ) - break; - - if ( stem_top <= zone->org_top + blues->blue_fuzz ) - { - if ( no_shoots || delta <= blues->blue_threshold ) - { - alignment->align |= PSH_BLUE_ALIGN_TOP; - alignment->align_top = zone->cur_ref; - } - break; - } - } - - /* look up stem bottom in bottom zones table */ - table = &blues->normal_bottom; - count = table->count; - zone = table->zones + count-1; - - for ( ; count > 0; count--, zone-- ) - { - delta = zone->org_top - stem_bot; - if ( delta < -blues->blue_fuzz ) - break; - - if ( stem_bot >= zone->org_bottom - blues->blue_fuzz ) - { - if ( no_shoots || delta < blues->blue_threshold ) - { - alignment->align |= PSH_BLUE_ALIGN_BOT; - alignment->align_bot = zone->cur_ref; - } - break; - } - } - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** GLOBAL HINTS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static void - psh_globals_destroy( PSH_Globals globals ) - { - if ( globals ) - { - FT_Memory memory; - - - memory = globals->memory; - globals->dimension[0].stdw.count = 0; - globals->dimension[1].stdw.count = 0; - - globals->blues.normal_top.count = 0; - globals->blues.normal_bottom.count = 0; - globals->blues.family_top.count = 0; - globals->blues.family_bottom.count = 0; - - FT_FREE( globals ); - -#ifdef DEBUG_HINTER - ps_debug_globals = NULL; -#endif - } - } - - - static FT_Error - psh_globals_new( FT_Memory memory, - T1_Private* priv, - PSH_Globals *aglobals ) - { - PSH_Globals globals = NULL; - FT_Error error; - - - if ( !FT_NEW( globals ) ) - { - FT_UInt count; - FT_Short* read; - - - globals->memory = memory; - - /* copy standard widths */ - { - PSH_Dimension dim = &globals->dimension[1]; - PSH_Width write = dim->stdw.widths; - - - write->org = priv->standard_width[0]; - write++; - - read = priv->snap_widths; - for ( count = priv->num_snap_widths; count > 0; count-- ) - { - write->org = *read; - write++; - read++; - } - - dim->stdw.count = priv->num_snap_widths + 1; - } - - /* copy standard heights */ - { - PSH_Dimension dim = &globals->dimension[0]; - PSH_Width write = dim->stdw.widths; - - - write->org = priv->standard_height[0]; - write++; - read = priv->snap_heights; - for ( count = priv->num_snap_heights; count > 0; count-- ) - { - write->org = *read; - write++; - read++; - } - - dim->stdw.count = priv->num_snap_heights + 1; - } - - /* copy blue zones */ - psh_blues_set_zones( &globals->blues, priv->num_blue_values, - priv->blue_values, priv->num_other_blues, - priv->other_blues, priv->blue_fuzz, 0 ); - - psh_blues_set_zones( &globals->blues, priv->num_family_blues, - priv->family_blues, priv->num_family_other_blues, - priv->family_other_blues, priv->blue_fuzz, 1 ); - - /* limit the BlueScale value to `1 / max_of_blue_zone_heights' */ - { - FT_Fixed max_scale; - FT_Short max_height = 1; - - - max_height = psh_calc_max_height( priv->num_blue_values, - priv->blue_values, - max_height ); - max_height = psh_calc_max_height( priv->num_other_blues, - priv->other_blues, - max_height ); - max_height = psh_calc_max_height( priv->num_family_blues, - priv->family_blues, - max_height ); - max_height = psh_calc_max_height( priv->num_family_other_blues, - priv->family_other_blues, - max_height ); - - /* BlueScale is scaled 1000 times */ - max_scale = FT_DivFix( 1000, max_height ); - globals->blues.blue_scale = priv->blue_scale < max_scale - ? priv->blue_scale - : max_scale; - } - - globals->blues.blue_shift = priv->blue_shift; - globals->blues.blue_fuzz = priv->blue_fuzz; - - globals->dimension[0].scale_mult = 0; - globals->dimension[0].scale_delta = 0; - globals->dimension[1].scale_mult = 0; - globals->dimension[1].scale_delta = 0; - -#ifdef DEBUG_HINTER - ps_debug_globals = globals; -#endif - } - - *aglobals = globals; - return error; - } - - - FT_LOCAL_DEF( void ) - psh_globals_set_scale( PSH_Globals globals, - FT_Fixed x_scale, - FT_Fixed y_scale, - FT_Fixed x_delta, - FT_Fixed y_delta ) - { - PSH_Dimension dim; - - - dim = &globals->dimension[0]; - if ( x_scale != dim->scale_mult || - x_delta != dim->scale_delta ) - { - dim->scale_mult = x_scale; - dim->scale_delta = x_delta; - - psh_globals_scale_widths( globals, 0 ); - } - - dim = &globals->dimension[1]; - if ( y_scale != dim->scale_mult || - y_delta != dim->scale_delta ) - { - dim->scale_mult = y_scale; - dim->scale_delta = y_delta; - - psh_globals_scale_widths( globals, 1 ); - psh_blues_scale_zones( &globals->blues, y_scale, y_delta ); - } - } - - - FT_LOCAL_DEF( void ) - psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ) - { - funcs->create = psh_globals_new; - funcs->set_scale = psh_globals_set_scale; - funcs->destroy = psh_globals_destroy; - } - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshglob.h b/third_party/freetype/src/pshinter/pshglob.h deleted file mode 100644 index c376df7b9fce802ffa5e9b15c5fe005fb590126a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshglob.h +++ /dev/null @@ -1,196 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshglob.h */ -/* */ -/* PostScript hinter global hinting management. */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSHGLOB_H__ -#define __PSHGLOB_H__ - - -#include FT_FREETYPE_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** GLOBAL HINTS INTERNALS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* @constant: */ - /* PS_GLOBALS_MAX_BLUE_ZONES */ - /* */ - /* @description: */ - /* The maximum number of blue zones in a font global hints structure. */ - /* See @PS_Globals_BluesRec. */ - /* */ -#define PS_GLOBALS_MAX_BLUE_ZONES 16 - - - /*************************************************************************/ - /* */ - /* @constant: */ - /* PS_GLOBALS_MAX_STD_WIDTHS */ - /* */ - /* @description: */ - /* The maximum number of standard and snap widths in either the */ - /* horizontal or vertical direction. See @PS_Globals_WidthsRec. */ - /* */ -#define PS_GLOBALS_MAX_STD_WIDTHS 16 - - - /* standard and snap width */ - typedef struct PSH_WidthRec_ - { - FT_Int org; - FT_Pos cur; - FT_Pos fit; - - } PSH_WidthRec, *PSH_Width; - - - /* standard and snap widths table */ - typedef struct PSH_WidthsRec_ - { - FT_UInt count; - PSH_WidthRec widths[PS_GLOBALS_MAX_STD_WIDTHS]; - - } PSH_WidthsRec, *PSH_Widths; - - - typedef struct PSH_DimensionRec_ - { - PSH_WidthsRec stdw; - FT_Fixed scale_mult; - FT_Fixed scale_delta; - - } PSH_DimensionRec, *PSH_Dimension; - - - /* blue zone descriptor */ - typedef struct PSH_Blue_ZoneRec_ - { - FT_Int org_ref; - FT_Int org_delta; - FT_Int org_top; - FT_Int org_bottom; - - FT_Pos cur_ref; - FT_Pos cur_delta; - FT_Pos cur_bottom; - FT_Pos cur_top; - - } PSH_Blue_ZoneRec, *PSH_Blue_Zone; - - - typedef struct PSH_Blue_TableRec_ - { - FT_UInt count; - PSH_Blue_ZoneRec zones[PS_GLOBALS_MAX_BLUE_ZONES]; - - } PSH_Blue_TableRec, *PSH_Blue_Table; - - - /* blue zones table */ - typedef struct PSH_BluesRec_ - { - PSH_Blue_TableRec normal_top; - PSH_Blue_TableRec normal_bottom; - PSH_Blue_TableRec family_top; - PSH_Blue_TableRec family_bottom; - - FT_Fixed blue_scale; - FT_Int blue_shift; - FT_Int blue_threshold; - FT_Int blue_fuzz; - FT_Bool no_overshoots; - - } PSH_BluesRec, *PSH_Blues; - - - /* font globals. */ - /* dimension 0 => X coordinates + vertical hints/stems */ - /* dimension 1 => Y coordinates + horizontal hints/stems */ - typedef struct PSH_GlobalsRec_ - { - FT_Memory memory; - PSH_DimensionRec dimension[2]; - PSH_BluesRec blues; - - } PSH_GlobalsRec; - - -#define PSH_BLUE_ALIGN_NONE 0 -#define PSH_BLUE_ALIGN_TOP 1 -#define PSH_BLUE_ALIGN_BOT 2 - - - typedef struct PSH_AlignmentRec_ - { - int align; - FT_Pos align_top; - FT_Pos align_bot; - - } PSH_AlignmentRec, *PSH_Alignment; - - - FT_LOCAL( void ) - psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ); - - -#if 0 - /* snap a stem width to fitter coordinates. `org_width' is in font */ - /* units. The result is in device pixels (26.6 format). */ - FT_LOCAL( FT_Pos ) - psh_dimension_snap_width( PSH_Dimension dimension, - FT_Int org_width ); -#endif - - FT_LOCAL( void ) - psh_globals_set_scale( PSH_Globals globals, - FT_Fixed x_scale, - FT_Fixed y_scale, - FT_Fixed x_delta, - FT_Fixed y_delta ); - - /* snap a stem to one or two blue zones */ - FT_LOCAL( void ) - psh_blues_snap_stem( PSH_Blues blues, - FT_Int stem_top, - FT_Int stem_bot, - PSH_Alignment alignment ); - /* */ - -#ifdef DEBUG_HINTER - extern PSH_Globals ps_debug_globals; -#endif - - -FT_END_HEADER - - -#endif /* __PSHGLOB_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshinter.c b/third_party/freetype/src/pshinter/pshinter.c deleted file mode 100644 index 9e65fe2a4242127fa77db85bf99383ea6faabcad..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshinter.c +++ /dev/null @@ -1,29 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshinter.c */ -/* */ -/* FreeType PostScript Hinting module */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "pshpic.c" -#include "pshrec.c" -#include "pshglob.c" -#include "pshalgo.c" -#include "pshmod.c" - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshmod.c b/third_party/freetype/src/pshinter/pshmod.c deleted file mode 100644 index 961b468506057bc4f0240109efe5d46c4bcd11b1..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshmod.c +++ /dev/null @@ -1,119 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshmod.c */ -/* */ -/* FreeType PostScript hinter module implementation (body). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include "pshrec.h" -#include "pshalgo.h" -#include "pshpic.h" - - - /* the Postscript Hinter module structure */ - typedef struct PS_Hinter_Module_Rec_ - { - FT_ModuleRec root; - PS_HintsRec ps_hints; - - PSH_Globals_FuncsRec globals_funcs; - T1_Hints_FuncsRec t1_funcs; - T2_Hints_FuncsRec t2_funcs; - - } PS_Hinter_ModuleRec, *PS_Hinter_Module; - - - /* finalize module */ - FT_CALLBACK_DEF( void ) - ps_hinter_done( PS_Hinter_Module module ) - { - module->t1_funcs.hints = NULL; - module->t2_funcs.hints = NULL; - - ps_hints_done( &module->ps_hints ); - } - - - /* initialize module, create hints recorder and the interface */ - FT_CALLBACK_DEF( FT_Error ) - ps_hinter_init( PS_Hinter_Module module ) - { - FT_Memory memory = module->root.memory; - void* ph = &module->ps_hints; - - - ps_hints_init( &module->ps_hints, memory ); - - psh_globals_funcs_init( &module->globals_funcs ); - - t1_hints_funcs_init( &module->t1_funcs ); - module->t1_funcs.hints = (T1_Hints)ph; - - t2_hints_funcs_init( &module->t2_funcs ); - module->t2_funcs.hints = (T2_Hints)ph; - - return 0; - } - - - /* returns global hints interface */ - FT_CALLBACK_DEF( PSH_Globals_Funcs ) - pshinter_get_globals_funcs( FT_Module module ) - { - return &((PS_Hinter_Module)module)->globals_funcs; - } - - - /* return Type 1 hints interface */ - FT_CALLBACK_DEF( T1_Hints_Funcs ) - pshinter_get_t1_funcs( FT_Module module ) - { - return &((PS_Hinter_Module)module)->t1_funcs; - } - - - /* return Type 2 hints interface */ - FT_CALLBACK_DEF( T2_Hints_Funcs ) - pshinter_get_t2_funcs( FT_Module module ) - { - return &((PS_Hinter_Module)module)->t2_funcs; - } - - - FT_DEFINE_PSHINTER_INTERFACE( - pshinter_interface, - pshinter_get_globals_funcs, - pshinter_get_t1_funcs, - pshinter_get_t2_funcs ) - - - FT_DEFINE_MODULE( - pshinter_module_class, - - 0, - sizeof ( PS_Hinter_ModuleRec ), - "pshinter", - 0x10000L, - 0x20000L, - - &PSHINTER_INTERFACE_GET, /* module-specific interface */ - - (FT_Module_Constructor)ps_hinter_init, - (FT_Module_Destructor) ps_hinter_done, - (FT_Module_Requester) NULL ) /* no additional interface for now */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshmod.h b/third_party/freetype/src/pshinter/pshmod.h deleted file mode 100644 index a58d85653376a079dcc66b6b7a0f324b16951581..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshmod.h +++ /dev/null @@ -1,39 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshmod.h */ -/* */ -/* PostScript hinter module interface (specification). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSHMOD_H__ -#define __PSHMOD_H__ - - -#include <ft2build.h> -#include FT_MODULE_H - - -FT_BEGIN_HEADER - - - FT_DECLARE_MODULE( pshinter_module_class ) - - -FT_END_HEADER - - -#endif /* __PSHMOD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshnterr.h b/third_party/freetype/src/pshinter/pshnterr.h deleted file mode 100644 index ce790a8ef51a0b60770a7a8690f56bdce290e2c9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshnterr.h +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshnterr.h */ -/* */ -/* PS Hinter error codes (specification only). */ -/* */ -/* Copyright 2003-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the PSHinter error enumeration constants. */ - /* */ - /*************************************************************************/ - -#ifndef __PSHNTERR_H__ -#define __PSHNTERR_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX PSH_Err_ -#define FT_ERR_BASE FT_Mod_Err_PShinter - -#include FT_ERRORS_H - -#endif /* __PSHNTERR_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshpic.c b/third_party/freetype/src/pshinter/pshpic.c deleted file mode 100644 index afd8fb9678ee19e514129f173aef29258a7383e2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshpic.c +++ /dev/null @@ -1,76 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshpic.c */ -/* */ -/* The FreeType position independent code services for pshinter module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "pshpic.h" -#include "pshnterr.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from pshmod.c */ - void - FT_Init_Class_pshinter_interface( FT_Library library, - PSHinter_Interface* clazz ); - - void - pshinter_module_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->pshinter ) - { - FT_FREE( pic_container->pshinter ); - pic_container->pshinter = NULL; - } - } - - - FT_Error - pshinter_module_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - PSHinterPIC* container = NULL; - FT_Memory memory = library->memory; - - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->pshinter = container; - - /* add call to initialization function when you add new scripts */ - FT_Init_Class_pshinter_interface( - library, &container->pshinter_interface ); - - if ( error ) - pshinter_module_class_pic_free( library ); - - return error; - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshpic.h b/third_party/freetype/src/pshinter/pshpic.h deleted file mode 100644 index ca35cd6fa9f1a949167d715260c0dd1c6b5f33eb..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshpic.h +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshpic.h */ -/* */ -/* The FreeType position independent code services for pshinter module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSHPIC_H__ -#define __PSHPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -#ifndef FT_CONFIG_OPTION_PIC - -#define PSHINTER_INTERFACE_GET pshinter_interface - -#else /* FT_CONFIG_OPTION_PIC */ - -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - -FT_BEGIN_HEADER - - typedef struct PSHinterPIC_ - { - PSHinter_Interface pshinter_interface; - - } PSHinterPIC; - - -#define GET_PIC( lib ) ( (PSHinterPIC*)( (lib)->pic_container.pshinter ) ) - -#define PSHINTER_INTERFACE_GET ( GET_PIC( library )->pshinter_interface ) - - /* see pshpic.c for the implementation */ - void - pshinter_module_class_pic_free( FT_Library library ); - - FT_Error - pshinter_module_class_pic_init( FT_Library library ); - -FT_END_HEADER - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -#endif /* __PSHPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshrec.c b/third_party/freetype/src/pshinter/pshrec.c deleted file mode 100644 index f8895fc8d630d4393b3f6c9c8e5178b4f6b7cca3..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshrec.c +++ /dev/null @@ -1,1220 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshrec.c */ -/* */ -/* FreeType PostScript hints recorder (body). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H - -#include "pshrec.h" -#include "pshalgo.h" - -#include "pshnterr.h" - -#undef FT_COMPONENT -#define FT_COMPONENT trace_pshrec - -#ifdef DEBUG_HINTER - PS_Hints ps_debug_hints = NULL; - int ps_debug_no_horz_hints = 0; - int ps_debug_no_vert_hints = 0; -#endif - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PS_HINT MANAGEMENT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* destroy hints table */ - static void - ps_hint_table_done( PS_Hint_Table table, - FT_Memory memory ) - { - FT_FREE( table->hints ); - table->num_hints = 0; - table->max_hints = 0; - } - - - /* ensure that a table can contain "count" elements */ - static FT_Error - ps_hint_table_ensure( PS_Hint_Table table, - FT_UInt count, - FT_Memory memory ) - { - FT_UInt old_max = table->max_hints; - FT_UInt new_max = count; - FT_Error error = FT_Err_Ok; - - - if ( new_max > old_max ) - { - /* try to grow the table */ - new_max = FT_PAD_CEIL( new_max, 8 ); - if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) ) - table->max_hints = new_max; - } - return error; - } - - - static FT_Error - ps_hint_table_alloc( PS_Hint_Table table, - FT_Memory memory, - PS_Hint *ahint ) - { - FT_Error error = FT_Err_Ok; - FT_UInt count; - PS_Hint hint = NULL; - - - count = table->num_hints; - count++; - - if ( count >= table->max_hints ) - { - error = ps_hint_table_ensure( table, count, memory ); - if ( error ) - goto Exit; - } - - hint = table->hints + count - 1; - hint->pos = 0; - hint->len = 0; - hint->flags = 0; - - table->num_hints = count; - - Exit: - *ahint = hint; - return error; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PS_MASK MANAGEMENT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* destroy mask */ - static void - ps_mask_done( PS_Mask mask, - FT_Memory memory ) - { - FT_FREE( mask->bytes ); - mask->num_bits = 0; - mask->max_bits = 0; - mask->end_point = 0; - } - - - /* ensure that a mask can contain "count" bits */ - static FT_Error - ps_mask_ensure( PS_Mask mask, - FT_UInt count, - FT_Memory memory ) - { - FT_UInt old_max = ( mask->max_bits + 7 ) >> 3; - FT_UInt new_max = ( count + 7 ) >> 3; - FT_Error error = FT_Err_Ok; - - - if ( new_max > old_max ) - { - new_max = FT_PAD_CEIL( new_max, 8 ); - if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) ) - mask->max_bits = new_max * 8; - } - return error; - } - - - /* test a bit value in a given mask */ - static FT_Int - ps_mask_test_bit( PS_Mask mask, - FT_Int idx ) - { - if ( (FT_UInt)idx >= mask->num_bits ) - return 0; - - return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) ); - } - - - /* clear a given bit */ - static void - ps_mask_clear_bit( PS_Mask mask, - FT_UInt idx ) - { - FT_Byte* p; - - - if ( idx >= mask->num_bits ) - return; - - p = mask->bytes + ( idx >> 3 ); - p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) ); - } - - - /* set a given bit, possibly grow the mask */ - static FT_Error - ps_mask_set_bit( PS_Mask mask, - FT_UInt idx, - FT_Memory memory ) - { - FT_Error error = FT_Err_Ok; - FT_Byte* p; - - - if ( idx >= mask->num_bits ) - { - error = ps_mask_ensure( mask, idx + 1, memory ); - if ( error ) - goto Exit; - - mask->num_bits = idx + 1; - } - - p = mask->bytes + ( idx >> 3 ); - p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) ); - - Exit: - return error; - } - - - /* destroy mask table */ - static void - ps_mask_table_done( PS_Mask_Table table, - FT_Memory memory ) - { - FT_UInt count = table->max_masks; - PS_Mask mask = table->masks; - - - for ( ; count > 0; count--, mask++ ) - ps_mask_done( mask, memory ); - - FT_FREE( table->masks ); - table->num_masks = 0; - table->max_masks = 0; - } - - - /* ensure that a mask table can contain "count" masks */ - static FT_Error - ps_mask_table_ensure( PS_Mask_Table table, - FT_UInt count, - FT_Memory memory ) - { - FT_UInt old_max = table->max_masks; - FT_UInt new_max = count; - FT_Error error = FT_Err_Ok; - - - if ( new_max > old_max ) - { - new_max = FT_PAD_CEIL( new_max, 8 ); - if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) ) - table->max_masks = new_max; - } - return error; - } - - - /* allocate a new mask in a table */ - static FT_Error - ps_mask_table_alloc( PS_Mask_Table table, - FT_Memory memory, - PS_Mask *amask ) - { - FT_UInt count; - FT_Error error = FT_Err_Ok; - PS_Mask mask = NULL; - - - count = table->num_masks; - count++; - - if ( count > table->max_masks ) - { - error = ps_mask_table_ensure( table, count, memory ); - if ( error ) - goto Exit; - } - - mask = table->masks + count - 1; - mask->num_bits = 0; - mask->end_point = 0; - table->num_masks = count; - - Exit: - *amask = mask; - return error; - } - - - /* return last hint mask in a table, create one if the table is empty */ - static FT_Error - ps_mask_table_last( PS_Mask_Table table, - FT_Memory memory, - PS_Mask *amask ) - { - FT_Error error = FT_Err_Ok; - FT_UInt count; - PS_Mask mask; - - - count = table->num_masks; - if ( count == 0 ) - { - error = ps_mask_table_alloc( table, memory, &mask ); - if ( error ) - goto Exit; - } - else - mask = table->masks + count - 1; - - Exit: - *amask = mask; - return error; - } - - - /* set a new mask to a given bit range */ - static FT_Error - ps_mask_table_set_bits( PS_Mask_Table table, - const FT_Byte* source, - FT_UInt bit_pos, - FT_UInt bit_count, - FT_Memory memory ) - { - FT_Error error; - PS_Mask mask; - - - error = ps_mask_table_last( table, memory, &mask ); - if ( error ) - goto Exit; - - error = ps_mask_ensure( mask, bit_count, memory ); - if ( error ) - goto Exit; - - mask->num_bits = bit_count; - - /* now, copy bits */ - { - FT_Byte* read = (FT_Byte*)source + ( bit_pos >> 3 ); - FT_Int rmask = 0x80 >> ( bit_pos & 7 ); - FT_Byte* write = mask->bytes; - FT_Int wmask = 0x80; - FT_Int val; - - - for ( ; bit_count > 0; bit_count-- ) - { - val = write[0] & ~wmask; - - if ( read[0] & rmask ) - val |= wmask; - - write[0] = (FT_Byte)val; - - rmask >>= 1; - if ( rmask == 0 ) - { - read++; - rmask = 0x80; - } - - wmask >>= 1; - if ( wmask == 0 ) - { - write++; - wmask = 0x80; - } - } - } - - Exit: - return error; - } - - - /* test whether two masks in a table intersect */ - static FT_Int - ps_mask_table_test_intersect( PS_Mask_Table table, - FT_UInt index1, - FT_UInt index2 ) - { - PS_Mask mask1 = table->masks + index1; - PS_Mask mask2 = table->masks + index2; - FT_Byte* p1 = mask1->bytes; - FT_Byte* p2 = mask2->bytes; - FT_UInt count1 = mask1->num_bits; - FT_UInt count2 = mask2->num_bits; - FT_UInt count; - - - count = FT_MIN( count1, count2 ); - for ( ; count >= 8; count -= 8 ) - { - if ( p1[0] & p2[0] ) - return 1; - - p1++; - p2++; - } - - if ( count == 0 ) - return 0; - - return ( p1[0] & p2[0] ) & ~( 0xFF >> count ); - } - - - /* merge two masks, used by ps_mask_table_merge_all */ - static FT_Error - ps_mask_table_merge( PS_Mask_Table table, - FT_UInt index1, - FT_UInt index2, - FT_Memory memory ) - { - FT_Error error = FT_Err_Ok; - - - /* swap index1 and index2 so that index1 < index2 */ - if ( index1 > index2 ) - { - FT_UInt temp; - - - temp = index1; - index1 = index2; - index2 = temp; - } - - if ( index1 < index2 && index2 < table->num_masks ) - { - /* we need to merge the bitsets of index1 and index2 with a */ - /* simple union */ - PS_Mask mask1 = table->masks + index1; - PS_Mask mask2 = table->masks + index2; - FT_UInt count1 = mask1->num_bits; - FT_UInt count2 = mask2->num_bits; - FT_Int delta; - - - if ( count2 > 0 ) - { - FT_UInt pos; - FT_Byte* read; - FT_Byte* write; - - - /* if "count2" is greater than "count1", we need to grow the */ - /* first bitset, and clear the highest bits */ - if ( count2 > count1 ) - { - error = ps_mask_ensure( mask1, count2, memory ); - if ( error ) - goto Exit; - - for ( pos = count1; pos < count2; pos++ ) - ps_mask_clear_bit( mask1, pos ); - } - - /* merge (unite) the bitsets */ - read = mask2->bytes; - write = mask1->bytes; - pos = ( count2 + 7 ) >> 3; - - for ( ; pos > 0; pos-- ) - { - write[0] = (FT_Byte)( write[0] | read[0] ); - write++; - read++; - } - } - - /* Now, remove "mask2" from the list. We need to keep the masks */ - /* sorted in order of importance, so move table elements. */ - mask2->num_bits = 0; - mask2->end_point = 0; - - /* number of masks to move */ - delta = (FT_Int)( table->num_masks - 1 - index2 ); - if ( delta > 0 ) - { - /* move to end of table for reuse */ - PS_MaskRec dummy = *mask2; - - - ft_memmove( mask2, - mask2 + 1, - (FT_UInt)delta * sizeof ( PS_MaskRec ) ); - - mask2[delta] = dummy; - } - - table->num_masks--; - } - else - FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n", - index1, index2 )); - - Exit: - return error; - } - - - /* Try to merge all masks in a given table. This is used to merge */ - /* all counter masks into independent counter "paths". */ - /* */ - static FT_Error - ps_mask_table_merge_all( PS_Mask_Table table, - FT_Memory memory ) - { - FT_Int index1, index2; - FT_Error error = FT_Err_Ok; - - - /* both loops go down to 0, thus FT_Int for index1 and index2 */ - for ( index1 = (FT_Int)table->num_masks - 1; index1 > 0; index1-- ) - { - for ( index2 = index1 - 1; index2 >= 0; index2-- ) - { - if ( ps_mask_table_test_intersect( table, - (FT_UInt)index1, - (FT_UInt)index2 ) ) - { - error = ps_mask_table_merge( table, - (FT_UInt)index2, - (FT_UInt)index1, - memory ); - if ( error ) - goto Exit; - - break; - } - } - } - - Exit: - return error; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PS_DIMENSION MANAGEMENT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /* finalize a given dimension */ - static void - ps_dimension_done( PS_Dimension dimension, - FT_Memory memory ) - { - ps_mask_table_done( &dimension->counters, memory ); - ps_mask_table_done( &dimension->masks, memory ); - ps_hint_table_done( &dimension->hints, memory ); - } - - - /* initialize a given dimension */ - static void - ps_dimension_init( PS_Dimension dimension ) - { - dimension->hints.num_hints = 0; - dimension->masks.num_masks = 0; - dimension->counters.num_masks = 0; - } - - -#if 0 - - /* set a bit at a given index in the current hint mask */ - static FT_Error - ps_dimension_set_mask_bit( PS_Dimension dim, - FT_UInt idx, - FT_Memory memory ) - { - PS_Mask mask; - FT_Error error = FT_Err_Ok; - - - /* get last hint mask */ - error = ps_mask_table_last( &dim->masks, memory, &mask ); - if ( error ) - goto Exit; - - error = ps_mask_set_bit( mask, idx, memory ); - - Exit: - return error; - } - -#endif - - /* set the end point in a mask, called from "End" & "Reset" methods */ - static void - ps_dimension_end_mask( PS_Dimension dim, - FT_UInt end_point ) - { - FT_UInt count = dim->masks.num_masks; - - - if ( count > 0 ) - { - PS_Mask mask = dim->masks.masks + count - 1; - - - mask->end_point = end_point; - } - } - - - /* set the end point in the current mask, then create a new empty one */ - /* (called by "Reset" method) */ - static FT_Error - ps_dimension_reset_mask( PS_Dimension dim, - FT_UInt end_point, - FT_Memory memory ) - { - PS_Mask mask; - - - /* end current mask */ - ps_dimension_end_mask( dim, end_point ); - - /* allocate new one */ - return ps_mask_table_alloc( &dim->masks, memory, &mask ); - } - - - /* set a new mask, called from the "T2Stem" method */ - static FT_Error - ps_dimension_set_mask_bits( PS_Dimension dim, - const FT_Byte* source, - FT_UInt source_pos, - FT_UInt source_bits, - FT_UInt end_point, - FT_Memory memory ) - { - FT_Error error; - - - /* reset current mask, if any */ - error = ps_dimension_reset_mask( dim, end_point, memory ); - if ( error ) - goto Exit; - - /* set bits in new mask */ - error = ps_mask_table_set_bits( &dim->masks, source, - source_pos, source_bits, memory ); - - Exit: - return error; - } - - - /* add a new single stem (called from "T1Stem" method) */ - static FT_Error - ps_dimension_add_t1stem( PS_Dimension dim, - FT_Int pos, - FT_Int len, - FT_Memory memory, - FT_Int *aindex ) - { - FT_Error error = FT_Err_Ok; - FT_UInt flags = 0; - - - /* detect ghost stem */ - if ( len < 0 ) - { - flags |= PS_HINT_FLAG_GHOST; - if ( len == -21 ) - { - flags |= PS_HINT_FLAG_BOTTOM; - pos += len; - } - len = 0; - } - - if ( aindex ) - *aindex = -1; - - /* now, lookup stem in the current hints table */ - { - PS_Mask mask; - FT_UInt idx; - FT_UInt max = dim->hints.num_hints; - PS_Hint hint = dim->hints.hints; - - - for ( idx = 0; idx < max; idx++, hint++ ) - { - if ( hint->pos == pos && hint->len == len ) - break; - } - - /* we need to create a new hint in the table */ - if ( idx >= max ) - { - error = ps_hint_table_alloc( &dim->hints, memory, &hint ); - if ( error ) - goto Exit; - - hint->pos = pos; - hint->len = len; - hint->flags = flags; - } - - /* now, store the hint in the current mask */ - error = ps_mask_table_last( &dim->masks, memory, &mask ); - if ( error ) - goto Exit; - - error = ps_mask_set_bit( mask, idx, memory ); - if ( error ) - goto Exit; - - if ( aindex ) - *aindex = (FT_Int)idx; - } - - Exit: - return error; - } - - - /* add a "hstem3/vstem3" counter to our dimension table */ - static FT_Error - ps_dimension_add_counter( PS_Dimension dim, - FT_Int hint1, - FT_Int hint2, - FT_Int hint3, - FT_Memory memory ) - { - FT_Error error = FT_Err_Ok; - FT_UInt count = dim->counters.num_masks; - PS_Mask counter = dim->counters.masks; - - - /* try to find an existing counter mask that already uses */ - /* one of these stems here */ - for ( ; count > 0; count--, counter++ ) - { - if ( ps_mask_test_bit( counter, hint1 ) || - ps_mask_test_bit( counter, hint2 ) || - ps_mask_test_bit( counter, hint3 ) ) - break; - } - - /* create a new counter when needed */ - if ( count == 0 ) - { - error = ps_mask_table_alloc( &dim->counters, memory, &counter ); - if ( error ) - goto Exit; - } - - /* now, set the bits for our hints in the counter mask */ - if ( hint1 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint1, memory ); - if ( error ) - goto Exit; - } - - if ( hint2 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint2, memory ); - if ( error ) - goto Exit; - } - - if ( hint3 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint3, memory ); - if ( error ) - goto Exit; - } - - Exit: - return error; - } - - - /* end of recording session for a given dimension */ - static FT_Error - ps_dimension_end( PS_Dimension dim, - FT_UInt end_point, - FT_Memory memory ) - { - /* end hint mask table */ - ps_dimension_end_mask( dim, end_point ); - - /* merge all counter masks into independent "paths" */ - return ps_mask_table_merge_all( &dim->counters, memory ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** PS_RECORDER MANAGEMENT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /* destroy hints */ - FT_LOCAL( void ) - ps_hints_done( PS_Hints hints ) - { - FT_Memory memory = hints->memory; - - - ps_dimension_done( &hints->dimension[0], memory ); - ps_dimension_done( &hints->dimension[1], memory ); - - hints->error = FT_Err_Ok; - hints->memory = NULL; - } - - - FT_LOCAL( void ) - ps_hints_init( PS_Hints hints, - FT_Memory memory ) - { - FT_MEM_ZERO( hints, sizeof ( *hints ) ); - hints->memory = memory; - } - - - /* initialize a hints for a new session */ - static void - ps_hints_open( PS_Hints hints, - PS_Hint_Type hint_type ) - { - hints->error = FT_Err_Ok; - hints->hint_type = hint_type; - - ps_dimension_init( &hints->dimension[0] ); - ps_dimension_init( &hints->dimension[1] ); - } - - - /* add one or more stems to the current hints table */ - static void - ps_hints_stem( PS_Hints hints, - FT_UInt dimension, - FT_Int count, - FT_Long* stems ) - { - PS_Dimension dim; - - - if ( hints->error ) - return; - - /* limit "dimension" to 0..1 */ - if ( dimension > 1 ) - { - FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n", - dimension )); - dimension = ( dimension != 0 ); - } - - /* record the stems in the current hints/masks table */ - /* (Type 1 & 2's `hstem' or `vstem' operators) */ - dim = &hints->dimension[dimension]; - - for ( ; count > 0; count--, stems += 2 ) - { - FT_Error error; - FT_Memory memory = hints->memory; - - - error = ps_dimension_add_t1stem( dim, - (FT_Int)stems[0], - (FT_Int)stems[1], - memory, - NULL ); - if ( error ) - { - FT_ERROR(( "ps_hints_stem: could not add stem" - " (%d,%d) to hints table\n", stems[0], stems[1] )); - - hints->error = error; - return; - } - } - } - - - /* add one Type1 counter stem to the current hints table */ - static void - ps_hints_t1stem3( PS_Hints hints, - FT_UInt dimension, - FT_Fixed* stems ) - { - FT_Error error = FT_Err_Ok; - - - if ( !hints->error ) - { - PS_Dimension dim; - FT_Memory memory = hints->memory; - FT_Int count; - FT_Int idx[3]; - - - /* limit "dimension" to 0..1 */ - if ( dimension > 1 ) - { - FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n", - dimension )); - dimension = ( dimension != 0 ); - } - - dim = &hints->dimension[dimension]; - - /* there must be 6 elements in the 'stem' array */ - if ( hints->hint_type == PS_HINT_TYPE_1 ) - { - /* add the three stems to our hints/masks table */ - for ( count = 0; count < 3; count++, stems += 2 ) - { - error = ps_dimension_add_t1stem( dim, - (FT_Int)FIXED_TO_INT( stems[0] ), - (FT_Int)FIXED_TO_INT( stems[1] ), - memory, &idx[count] ); - if ( error ) - goto Fail; - } - - /* now, add the hints to the counters table */ - error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2], - memory ); - if ( error ) - goto Fail; - } - else - { - FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type\n" )); - error = FT_THROW( Invalid_Argument ); - goto Fail; - } - } - - return; - - Fail: - FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" )); - hints->error = error; - } - - - /* reset hints (only with Type 1 hints) */ - static void - ps_hints_t1reset( PS_Hints hints, - FT_UInt end_point ) - { - FT_Error error = FT_Err_Ok; - - - if ( !hints->error ) - { - FT_Memory memory = hints->memory; - - - if ( hints->hint_type == PS_HINT_TYPE_1 ) - { - error = ps_dimension_reset_mask( &hints->dimension[0], - end_point, memory ); - if ( error ) - goto Fail; - - error = ps_dimension_reset_mask( &hints->dimension[1], - end_point, memory ); - if ( error ) - goto Fail; - } - else - { - /* invalid hint type */ - error = FT_THROW( Invalid_Argument ); - goto Fail; - } - } - return; - - Fail: - hints->error = error; - } - - - /* Type2 "hintmask" operator, add a new hintmask to each direction */ - static void - ps_hints_t2mask( PS_Hints hints, - FT_UInt end_point, - FT_UInt bit_count, - const FT_Byte* bytes ) - { - FT_Error error; - - - if ( !hints->error ) - { - PS_Dimension dim = hints->dimension; - FT_Memory memory = hints->memory; - FT_UInt count1 = dim[0].hints.num_hints; - FT_UInt count2 = dim[1].hints.num_hints; - - - /* check bit count; must be equal to current total hint count */ - if ( bit_count != count1 + count2 ) - { - FT_TRACE0(( "ps_hints_t2mask:" - " called with invalid bitcount %d (instead of %d)\n", - bit_count, count1 + count2 )); - - /* simply ignore the operator */ - return; - } - - /* set-up new horizontal and vertical hint mask now */ - error = ps_dimension_set_mask_bits( &dim[0], bytes, count2, count1, - end_point, memory ); - if ( error ) - goto Fail; - - error = ps_dimension_set_mask_bits( &dim[1], bytes, 0, count2, - end_point, memory ); - if ( error ) - goto Fail; - } - return; - - Fail: - hints->error = error; - } - - - static void - ps_hints_t2counter( PS_Hints hints, - FT_UInt bit_count, - const FT_Byte* bytes ) - { - FT_Error error; - - - if ( !hints->error ) - { - PS_Dimension dim = hints->dimension; - FT_Memory memory = hints->memory; - FT_UInt count1 = dim[0].hints.num_hints; - FT_UInt count2 = dim[1].hints.num_hints; - - - /* check bit count, must be equal to current total hint count */ - if ( bit_count != count1 + count2 ) - { - FT_TRACE0(( "ps_hints_t2counter:" - " called with invalid bitcount %d (instead of %d)\n", - bit_count, count1 + count2 )); - - /* simply ignore the operator */ - return; - } - - /* set-up new horizontal and vertical hint mask now */ - error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1, - 0, memory ); - if ( error ) - goto Fail; - - error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2, - 0, memory ); - if ( error ) - goto Fail; - } - return; - - Fail: - hints->error = error; - } - - - /* end recording session */ - static FT_Error - ps_hints_close( PS_Hints hints, - FT_UInt end_point ) - { - FT_Error error; - - - error = hints->error; - if ( !error ) - { - FT_Memory memory = hints->memory; - PS_Dimension dim = hints->dimension; - - - error = ps_dimension_end( &dim[0], end_point, memory ); - if ( !error ) - { - error = ps_dimension_end( &dim[1], end_point, memory ); - } - } - -#ifdef DEBUG_HINTER - if ( !error ) - ps_debug_hints = hints; -#endif - return error; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE 1 HINTS RECORDING INTERFACE *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static void - t1_hints_open( T1_Hints hints ) - { - ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); - } - - static void - t1_hints_stem( T1_Hints hints, - FT_UInt dimension, - FT_Fixed* coords ) - { - FT_Pos stems[2]; - - - stems[0] = FIXED_TO_INT( coords[0] ); - stems[1] = FIXED_TO_INT( coords[1] ); - - ps_hints_stem( (PS_Hints)hints, dimension, 1, stems ); - } - - - FT_LOCAL_DEF( void ) - t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) - { - FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) ); - - funcs->open = (T1_Hints_OpenFunc) t1_hints_open; - funcs->close = (T1_Hints_CloseFunc) ps_hints_close; - funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; - funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3; - funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; - funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE 2 HINTS RECORDING INTERFACE *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static void - t2_hints_open( T2_Hints hints ) - { - ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 ); - } - - - static void - t2_hints_stems( T2_Hints hints, - FT_UInt dimension, - FT_Int count, - FT_Fixed* coords ) - { - FT_Pos stems[32], y; - FT_Int total = count, n; - - - y = 0; - while ( total > 0 ) - { - /* determine number of stems to write */ - count = total; - if ( count > 16 ) - count = 16; - - /* compute integer stem positions in font units */ - for ( n = 0; n < count * 2; n++ ) - { - y += coords[n]; - stems[n] = FIXED_TO_INT( y ); - } - - /* compute lengths */ - for ( n = 0; n < count * 2; n += 2 ) - stems[n + 1] = stems[n + 1] - stems[n]; - - /* add them to the current dimension */ - ps_hints_stem( (PS_Hints)hints, dimension, count, stems ); - - total -= count; - } - } - - - FT_LOCAL_DEF( void ) - t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) - { - FT_MEM_ZERO( funcs, sizeof ( *funcs ) ); - - funcs->open = (T2_Hints_OpenFunc) t2_hints_open; - funcs->close = (T2_Hints_CloseFunc) ps_hints_close; - funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; - funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask; - funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; - funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply; - } - - -/* END */ diff --git a/third_party/freetype/src/pshinter/pshrec.h b/third_party/freetype/src/pshinter/pshrec.h deleted file mode 100644 index 2b1ad949368bb426a3cdf5a9a8f4baf6b9285046..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/pshinter/pshrec.h +++ /dev/null @@ -1,172 +0,0 @@ -/***************************************************************************/ -/* */ -/* pshrec.h */ -/* */ -/* Postscript (Type1/Type2) hints recorder (specification). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /**************************************************************************/ - /* */ - /* The functions defined here are called from the Type 1, CID and CFF */ - /* font drivers to record the hints of a given character/glyph. */ - /* */ - /* The hints are recorded in a unified format, and are later processed */ - /* by the `optimizer' and `fitter' to adjust the outlines to the pixel */ - /* grid. */ - /* */ - /**************************************************************************/ - - -#ifndef __PSHREC_H__ -#define __PSHREC_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_POSTSCRIPT_HINTS_H -#include "pshglob.h" - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** GLYPH HINTS RECORDER INTERNALS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* handle to hint record */ - typedef struct PS_HintRec_* PS_Hint; - - /* hint types */ - typedef enum PS_Hint_Type_ - { - PS_HINT_TYPE_1 = 1, - PS_HINT_TYPE_2 = 2 - - } PS_Hint_Type; - - - /* hint flags */ -#define PS_HINT_FLAG_GHOST 1U -#define PS_HINT_FLAG_BOTTOM 2U - - - /* hint descriptor */ - typedef struct PS_HintRec_ - { - FT_Int pos; - FT_Int len; - FT_UInt flags; - - } PS_HintRec; - - -#define ps_hint_is_active( x ) ( (x)->flags & PS_HINT_FLAG_ACTIVE ) -#define ps_hint_is_ghost( x ) ( (x)->flags & PS_HINT_FLAG_GHOST ) -#define ps_hint_is_bottom( x ) ( (x)->flags & PS_HINT_FLAG_BOTTOM ) - - - /* hints table descriptor */ - typedef struct PS_Hint_TableRec_ - { - FT_UInt num_hints; - FT_UInt max_hints; - PS_Hint hints; - - } PS_Hint_TableRec, *PS_Hint_Table; - - - /* hint and counter mask descriptor */ - typedef struct PS_MaskRec_ - { - FT_UInt num_bits; - FT_UInt max_bits; - FT_Byte* bytes; - FT_UInt end_point; - - } PS_MaskRec, *PS_Mask; - - - /* masks and counters table descriptor */ - typedef struct PS_Mask_TableRec_ - { - FT_UInt num_masks; - FT_UInt max_masks; - PS_Mask masks; - - } PS_Mask_TableRec, *PS_Mask_Table; - - - /* dimension-specific hints descriptor */ - typedef struct PS_DimensionRec_ - { - PS_Hint_TableRec hints; - PS_Mask_TableRec masks; - PS_Mask_TableRec counters; - - } PS_DimensionRec, *PS_Dimension; - - - /* glyph hints descriptor */ - /* dimension 0 => X coordinates + vertical hints/stems */ - /* dimension 1 => Y coordinates + horizontal hints/stems */ - typedef struct PS_HintsRec_ - { - FT_Memory memory; - FT_Error error; - FT_UInt32 magic; - PS_Hint_Type hint_type; - PS_DimensionRec dimension[2]; - - } PS_HintsRec, *PS_Hints; - - /* */ - - /* initialize hints recorder */ - FT_LOCAL( void ) - ps_hints_init( PS_Hints hints, - FT_Memory memory ); - - /* finalize hints recorder */ - FT_LOCAL( void ) - ps_hints_done( PS_Hints hints ); - - /* initialize Type1 hints recorder interface */ - FT_LOCAL( void ) - t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ); - - /* initialize Type2 hints recorder interface */ - FT_LOCAL( void ) - t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ); - - -#ifdef DEBUG_HINTER - extern PS_Hints ps_debug_hints; - extern int ps_debug_no_horz_hints; - extern int ps_debug_no_vert_hints; -#endif - - /* */ - - -FT_END_HEADER - - -#endif /* __PS_HINTER_RECORD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psnames/Jamfile b/third_party/freetype/src/psnames/Jamfile deleted file mode 100644 index 6dcc8b8e94d34dd53102301a48f20f3a66f310f9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/Jamfile +++ /dev/null @@ -1,31 +0,0 @@ -# FreeType 2 src/psnames Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) psnames ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = psmodule - pspic - ; - } - else - { - _sources = psnames ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/psnames Jamfile diff --git a/third_party/freetype/src/psnames/psmodule.c b/third_party/freetype/src/psnames/psmodule.c deleted file mode 100644 index 0f04c2fa7d25ca93602bc631f17cd0343c972306..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/psmodule.c +++ /dev/null @@ -1,609 +0,0 @@ -/***************************************************************************/ -/* */ -/* psmodule.c */ -/* */ -/* PSNames module implementation (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H - -#include "psmodule.h" -#include "pstables.h" - -#include "psnamerr.h" -#include "pspic.h" - - -#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES - - -#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST - - -#define VARIANT_BIT 0x80000000UL -#define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) ) - - - /* Return the Unicode value corresponding to a given glyph. Note that */ - /* we do deal with glyph variants by detecting a non-initial dot in */ - /* the name, as in `A.swash' or `e.final'; in this case, the */ - /* VARIANT_BIT is set in the return value. */ - /* */ - static FT_UInt32 - ps_unicode_value( const char* glyph_name ) - { - /* If the name begins with `uni', then the glyph name may be a */ - /* hard-coded unicode character code. */ - if ( glyph_name[0] == 'u' && - glyph_name[1] == 'n' && - glyph_name[2] == 'i' ) - { - /* determine whether the next four characters following are */ - /* hexadecimal. */ - - /* XXX: Add code to deal with ligatures, i.e. glyph names like */ - /* `uniXXXXYYYYZZZZ'... */ - - FT_Int count; - FT_UInt32 value = 0; - const char* p = glyph_name + 3; - - - for ( count = 4; count > 0; count--, p++ ) - { - char c = *p; - unsigned int d; - - - d = (unsigned char)c - '0'; - if ( d >= 10 ) - { - d = (unsigned char)c - 'A'; - if ( d >= 6 ) - d = 16; - else - d += 10; - } - - /* Exit if a non-uppercase hexadecimal character was found */ - /* -- this also catches character codes below `0' since such */ - /* negative numbers cast to `unsigned int' are far too big. */ - if ( d >= 16 ) - break; - - value = ( value << 4 ) + d; - } - - /* there must be exactly four hex digits */ - if ( count == 0 ) - { - if ( *p == '\0' ) - return value; - if ( *p == '.' ) - return (FT_UInt32)( value | VARIANT_BIT ); - } - } - - /* If the name begins with `u', followed by four to six uppercase */ - /* hexadecimal digits, it is a hard-coded unicode character code. */ - if ( glyph_name[0] == 'u' ) - { - FT_Int count; - FT_UInt32 value = 0; - const char* p = glyph_name + 1; - - - for ( count = 6; count > 0; count--, p++ ) - { - char c = *p; - unsigned int d; - - - d = (unsigned char)c - '0'; - if ( d >= 10 ) - { - d = (unsigned char)c - 'A'; - if ( d >= 6 ) - d = 16; - else - d += 10; - } - - if ( d >= 16 ) - break; - - value = ( value << 4 ) + d; - } - - if ( count <= 2 ) - { - if ( *p == '\0' ) - return value; - if ( *p == '.' ) - return (FT_UInt32)( value | VARIANT_BIT ); - } - } - - /* Look for a non-initial dot in the glyph name in order to */ - /* find variants like `A.swash', `e.final', etc. */ - { - const char* p = glyph_name; - const char* dot = NULL; - - - for ( ; *p; p++ ) - { - if ( *p == '.' && p > glyph_name ) - { - dot = p; - break; - } - } - - /* now look up the glyph in the Adobe Glyph List */ - if ( !dot ) - return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p ); - else - return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) | - VARIANT_BIT ); - } - } - - - /* ft_qsort callback to sort the unicode map */ - FT_CALLBACK_DEF( int ) - compare_uni_maps( const void* a, - const void* b ) - { - PS_UniMap* map1 = (PS_UniMap*)a; - PS_UniMap* map2 = (PS_UniMap*)b; - FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode ); - FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode ); - - - /* sort base glyphs before glyph variants */ - if ( unicode1 == unicode2 ) - { - if ( map1->unicode > map2->unicode ) - return 1; - else if ( map1->unicode < map2->unicode ) - return -1; - else - return 0; - } - else - { - if ( unicode1 > unicode2 ) - return 1; - else if ( unicode1 < unicode2 ) - return -1; - else - return 0; - } - } - - - /* support for extra glyphs not handled (well) in AGL; */ - /* we add extra mappings for them if necessary */ - -#define EXTRA_GLYPH_LIST_SIZE 10 - - static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] = - { - /* WGL 4 */ - 0x0394, - 0x03A9, - 0x2215, - 0x00AD, - 0x02C9, - 0x03BC, - 0x2219, - 0x00A0, - /* Romanian */ - 0x021A, - 0x021B - }; - - static const char ft_extra_glyph_names[] = - { - 'D','e','l','t','a',0, - 'O','m','e','g','a',0, - 'f','r','a','c','t','i','o','n',0, - 'h','y','p','h','e','n',0, - 'm','a','c','r','o','n',0, - 'm','u',0, - 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0, - 's','p','a','c','e',0, - 'T','c','o','m','m','a','a','c','c','e','n','t',0, - 't','c','o','m','m','a','a','c','c','e','n','t',0 - }; - - static const FT_Int - ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] = - { - 0, - 6, - 12, - 21, - 28, - 35, - 38, - 53, - 59, - 72 - }; - - - static void - ps_check_extra_glyph_name( const char* gname, - FT_UInt glyph, - FT_UInt* extra_glyphs, - FT_UInt *states ) - { - FT_UInt n; - - - for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) - { - if ( ft_strcmp( ft_extra_glyph_names + - ft_extra_glyph_name_offsets[n], gname ) == 0 ) - { - if ( states[n] == 0 ) - { - /* mark this extra glyph as a candidate for the cmap */ - states[n] = 1; - extra_glyphs[n] = glyph; - } - - return; - } - } - } - - - static void - ps_check_extra_glyph_unicode( FT_UInt32 uni_char, - FT_UInt *states ) - { - FT_UInt n; - - - for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) - { - if ( uni_char == ft_extra_glyph_unicodes[n] ) - { - /* disable this extra glyph from being added to the cmap */ - states[n] = 2; - - return; - } - } - } - - - /* Build a table that maps Unicode values to glyph indices. */ - static FT_Error - ps_unicodes_init( FT_Memory memory, - PS_Unicodes table, - FT_UInt num_glyphs, - PS_GetGlyphNameFunc get_glyph_name, - PS_FreeGlyphNameFunc free_glyph_name, - FT_Pointer glyph_data ) - { - FT_Error error; - - FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE]; - - - /* we first allocate the table */ - table->num_maps = 0; - table->maps = NULL; - - if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) ) - { - FT_UInt n; - FT_UInt count; - PS_UniMap* map; - FT_UInt32 uni_char; - - - map = table->maps; - - for ( n = 0; n < num_glyphs; n++ ) - { - const char* gname = get_glyph_name( glyph_data, n ); - - - if ( gname ) - { - ps_check_extra_glyph_name( gname, n, - extra_glyphs, extra_glyph_list_states ); - uni_char = ps_unicode_value( gname ); - - if ( BASE_GLYPH( uni_char ) != 0 ) - { - ps_check_extra_glyph_unicode( uni_char, - extra_glyph_list_states ); - map->unicode = uni_char; - map->glyph_index = n; - map++; - } - - if ( free_glyph_name ) - free_glyph_name( glyph_data, gname ); - } - } - - for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) - { - if ( extra_glyph_list_states[n] == 1 ) - { - /* This glyph name has an additional representation. */ - /* Add it to the cmap. */ - - map->unicode = ft_extra_glyph_unicodes[n]; - map->glyph_index = extra_glyphs[n]; - map++; - } - } - - /* now compress the table a bit */ - count = (FT_UInt)( map - table->maps ); - - if ( count == 0 ) - { - /* No unicode chars here! */ - FT_FREE( table->maps ); - if ( !error ) - error = FT_THROW( No_Unicode_Glyph_Name ); - } - else - { - /* Reallocate if the number of used entries is much smaller. */ - if ( count < num_glyphs / 2 ) - { - (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count ); - error = FT_Err_Ok; - } - - /* Sort the table in increasing order of unicode values, */ - /* taking care of glyph variants. */ - ft_qsort( table->maps, count, sizeof ( PS_UniMap ), - compare_uni_maps ); - } - - table->num_maps = count; - } - - return error; - } - - - static FT_UInt - ps_unicodes_char_index( PS_Unicodes table, - FT_UInt32 unicode ) - { - PS_UniMap *min, *max, *mid, *result = NULL; - - - /* Perform a binary search on the table. */ - - min = table->maps; - max = min + table->num_maps - 1; - - while ( min <= max ) - { - FT_UInt32 base_glyph; - - - mid = min + ( ( max - min ) >> 1 ); - - if ( mid->unicode == unicode ) - { - result = mid; - break; - } - - base_glyph = BASE_GLYPH( mid->unicode ); - - if ( base_glyph == unicode ) - result = mid; /* remember match but continue search for base glyph */ - - if ( min == max ) - break; - - if ( base_glyph < unicode ) - min = mid + 1; - else - max = mid - 1; - } - - if ( result ) - return result->glyph_index; - else - return 0; - } - - - static FT_UInt32 - ps_unicodes_char_next( PS_Unicodes table, - FT_UInt32 *unicode ) - { - FT_UInt result = 0; - FT_UInt32 char_code = *unicode + 1; - - - { - FT_UInt min = 0; - FT_UInt max = table->num_maps; - FT_UInt mid; - PS_UniMap* map; - FT_UInt32 base_glyph; - - - while ( min < max ) - { - mid = min + ( ( max - min ) >> 1 ); - map = table->maps + mid; - - if ( map->unicode == char_code ) - { - result = map->glyph_index; - goto Exit; - } - - base_glyph = BASE_GLYPH( map->unicode ); - - if ( base_glyph == char_code ) - result = map->glyph_index; - - if ( base_glyph < char_code ) - min = mid + 1; - else - max = mid; - } - - if ( result ) - goto Exit; /* we have a variant glyph */ - - /* we didn't find it; check whether we have a map just above it */ - char_code = 0; - - if ( min < table->num_maps ) - { - map = table->maps + min; - result = map->glyph_index; - char_code = BASE_GLYPH( map->unicode ); - } - } - - Exit: - *unicode = char_code; - return result; - } - - -#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ - - - static const char* - ps_get_macintosh_name( FT_UInt name_index ) - { - if ( name_index >= FT_NUM_MAC_NAMES ) - name_index = 0; - - return ft_standard_glyph_names + ft_mac_names[name_index]; - } - - - static const char* - ps_get_standard_strings( FT_UInt sid ) - { - if ( sid >= FT_NUM_SID_NAMES ) - return 0; - - return ft_standard_glyph_names + ft_sid_names[sid]; - } - - -#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST - - FT_DEFINE_SERVICE_PSCMAPSREC( - pscmaps_interface, - (PS_Unicode_ValueFunc) ps_unicode_value, - (PS_Unicodes_InitFunc) ps_unicodes_init, - (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, - (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, - - (PS_Macintosh_NameFunc) ps_get_macintosh_name, - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, - - t1_standard_encoding, - t1_expert_encoding ) - -#else - - FT_DEFINE_SERVICE_PSCMAPSREC( - pscmaps_interface, - NULL, - NULL, - NULL, - NULL, - - (PS_Macintosh_NameFunc) ps_get_macintosh_name, - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, - - t1_standard_encoding, - t1_expert_encoding ) - -#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ - - - FT_DEFINE_SERVICEDESCREC1( - pscmaps_services, - FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET ) - - - static FT_Pointer - psnames_get_service( FT_Module module, - const char* service_id ) - { - /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */ -#ifdef FT_CONFIG_OPTION_PIC - FT_Library library; - - - if ( !module ) - return NULL; - library = module->library; - if ( !library ) - return NULL; -#else - FT_UNUSED( module ); -#endif - - return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id ); - } - -#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ - - -#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES -#define PUT_PS_NAMES_SERVICE( a ) NULL -#else -#define PUT_PS_NAMES_SERVICE( a ) a -#endif - - FT_DEFINE_MODULE( - psnames_module_class, - - 0, /* this is not a font driver, nor a renderer */ - sizeof ( FT_ModuleRec ), - - "psnames", /* driver name */ - 0x10000L, /* driver version */ - 0x20000L, /* driver requires FreeType 2 or above */ - - PUT_PS_NAMES_SERVICE( - (void*)&PSCMAPS_INTERFACE_GET ), /* module specific interface */ - (FT_Module_Constructor)NULL, - (FT_Module_Destructor) NULL, - (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) ) - - -/* END */ diff --git a/third_party/freetype/src/psnames/psmodule.h b/third_party/freetype/src/psnames/psmodule.h deleted file mode 100644 index f85f322193a71963f526a1aa5b163451c380c41b..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/psmodule.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************/ -/* */ -/* psmodule.h */ -/* */ -/* High-level PSNames module interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSMODULE_H__ -#define __PSMODULE_H__ - - -#include <ft2build.h> -#include FT_MODULE_H - - -FT_BEGIN_HEADER - - - FT_DECLARE_MODULE( psnames_module_class ) - - -FT_END_HEADER - -#endif /* __PSMODULE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psnames/psnamerr.h b/third_party/freetype/src/psnames/psnamerr.h deleted file mode 100644 index 09cc247b7d987fb1bde7ca9a64d09b675fcf8400..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/psnamerr.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* psnamerr.h */ -/* */ -/* PS names module error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the PS names module error enumeration */ - /* constants. */ - /* */ - /*************************************************************************/ - -#ifndef __PSNAMERR_H__ -#define __PSNAMERR_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX PSnames_Err_ -#define FT_ERR_BASE FT_Mod_Err_PSnames - -#include FT_ERRORS_H - -#endif /* __PSNAMERR_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/psnames/psnames.c b/third_party/freetype/src/psnames/psnames.c deleted file mode 100644 index a4385961e5a9f2924914ab990eb6ea06dfb38d0c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/psnames.c +++ /dev/null @@ -1,26 +0,0 @@ -/***************************************************************************/ -/* */ -/* psnames.c */ -/* */ -/* FreeType PSNames module component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "pspic.c" -#include "psmodule.c" - - -/* END */ diff --git a/third_party/freetype/src/psnames/pspic.c b/third_party/freetype/src/psnames/pspic.c deleted file mode 100644 index 1394f977e0060878c3c420d63bd612c829f86b1e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/pspic.c +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************/ -/* */ -/* pspic.c */ -/* */ -/* The FreeType position independent code services for psnames module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "pspic.h" -#include "psnamerr.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from psmodule.c */ - FT_Error - FT_Create_Class_pscmaps_services( FT_Library library, - FT_ServiceDescRec** output_class ); - void - FT_Destroy_Class_pscmaps_services( FT_Library library, - FT_ServiceDescRec* clazz ); - - void - FT_Init_Class_pscmaps_interface( FT_Library library, - FT_Service_PsCMapsRec* clazz ); - - - void - psnames_module_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->psnames ) - { - PSModulePIC* container = (PSModulePIC*)pic_container->psnames; - - - if ( container->pscmaps_services ) - FT_Destroy_Class_pscmaps_services( library, - container->pscmaps_services ); - container->pscmaps_services = NULL; - FT_FREE( container ); - pic_container->psnames = NULL; - } - } - - - FT_Error - psnames_module_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - PSModulePIC* container = NULL; - FT_Memory memory = library->memory; - - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->psnames = container; - - /* initialize pointer table - */ - /* this is how the module usually expects this data */ - error = FT_Create_Class_pscmaps_services( - library, &container->pscmaps_services ); - if ( error ) - goto Exit; - FT_Init_Class_pscmaps_interface( library, - &container->pscmaps_interface ); - - Exit: - if ( error ) - psnames_module_class_pic_free( library ); - return error; - } - - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/psnames/pspic.h b/third_party/freetype/src/psnames/pspic.h deleted file mode 100644 index 443225af61527e9bdd97b6cd8186fc6818cc29ad..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/psnames/pspic.h +++ /dev/null @@ -1,68 +0,0 @@ -/***************************************************************************/ -/* */ -/* pspic.h */ -/* */ -/* The FreeType position independent code services for psnames module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PSPIC_H__ -#define __PSPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -#ifndef FT_CONFIG_OPTION_PIC - -#define PSCMAPS_SERVICES_GET pscmaps_services -#define PSCMAPS_INTERFACE_GET pscmaps_interface - -#else /* FT_CONFIG_OPTION_PIC */ - -#include FT_SERVICE_POSTSCRIPT_CMAPS_H - - -FT_BEGIN_HEADER - - typedef struct PSModulePIC_ - { - FT_ServiceDescRec* pscmaps_services; - FT_Service_PsCMapsRec pscmaps_interface; - - } PSModulePIC; - - -#define GET_PIC( lib ) \ - ( (PSModulePIC*)((lib)->pic_container.psnames) ) -#define PSCMAPS_SERVICES_GET ( GET_PIC( library )->pscmaps_services ) -#define PSCMAPS_INTERFACE_GET ( GET_PIC( library )->pscmaps_interface ) - - - /* see pspic.c for the implementation */ - void - psnames_module_class_pic_free( FT_Library library ); - - FT_Error - psnames_module_class_pic_init( FT_Library library ); - -FT_END_HEADER - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -#endif /* __PSPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/raster/Jamfile b/third_party/freetype/src/raster/Jamfile deleted file mode 100644 index 71df5689eebab7349f65a1b34e0680fc5b2719f9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -# FreeType 2 src/raster Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) raster ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ftraster - ftrend1 - rastpic - ; - } - else - { - _sources = raster ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/raster Jamfile diff --git a/third_party/freetype/src/raster/ftmisc.h b/third_party/freetype/src/raster/ftmisc.h deleted file mode 100644 index b87e0b62b727e3580cd04e56d7167f43fda39c5d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/ftmisc.h +++ /dev/null @@ -1,142 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftmisc.h */ -/* */ -/* Miscellaneous macros for stand-alone rasterizer (specification */ -/* only). */ -/* */ -/* Copyright 2005-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used */ -/* modified and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /***************************************************/ - /* */ - /* This file is *not* portable! You have to adapt */ - /* its definitions to your platform. */ - /* */ - /***************************************************/ - -#ifndef __FTMISC_H__ -#define __FTMISC_H__ - - - /* memset */ -#include FT_CONFIG_STANDARD_LIBRARY_H - -#define FT_BEGIN_HEADER -#define FT_END_HEADER - -#define FT_LOCAL_DEF( x ) static x - - - /* from include/freetype/fttypes.h */ - - typedef unsigned char FT_Byte; - typedef signed int FT_Int; - typedef unsigned int FT_UInt; - typedef signed long FT_Long; - typedef unsigned long FT_ULong; - typedef signed long FT_F26Dot6; - typedef int FT_Error; - -#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ - ( ( (FT_ULong)_x1 << 24 ) | \ - ( (FT_ULong)_x2 << 16 ) | \ - ( (FT_ULong)_x3 << 8 ) | \ - (FT_ULong)_x4 ) - - - /* from include/freetype/ftsystem.h */ - - typedef struct FT_MemoryRec_* FT_Memory; - - typedef void* (*FT_Alloc_Func)( FT_Memory memory, - long size ); - - typedef void (*FT_Free_Func)( FT_Memory memory, - void* block ); - - typedef void* (*FT_Realloc_Func)( FT_Memory memory, - long cur_size, - long new_size, - void* block ); - - typedef struct FT_MemoryRec_ - { - void* user; - - FT_Alloc_Func alloc; - FT_Free_Func free; - FT_Realloc_Func realloc; - - } FT_MemoryRec; - - - /* from src/ftcalc.c */ - -#if ( defined _WIN32 || defined _WIN64 ) - - typedef __int64 FT_Int64; - -#else - -#include "inttypes.h" - - typedef int64_t FT_Int64; - -#endif - - - static FT_Long - FT_MulDiv( FT_Long a, - FT_Long b, - FT_Long c ) - { - FT_Int s; - FT_Long d; - - - s = 1; - if ( a < 0 ) { a = -a; s = -1; } - if ( b < 0 ) { b = -b; s = -s; } - if ( c < 0 ) { c = -c; s = -s; } - - d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c - : 0x7FFFFFFFL ); - - return ( s > 0 ) ? d : -d; - } - - - static FT_Long - FT_MulDiv_No_Round( FT_Long a, - FT_Long b, - FT_Long c ) - { - FT_Int s; - FT_Long d; - - - s = 1; - if ( a < 0 ) { a = -a; s = -1; } - if ( b < 0 ) { b = -b; s = -s; } - if ( c < 0 ) { c = -c; s = -s; } - - d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c - : 0x7FFFFFFFL ); - - return ( s > 0 ) ? d : -d; - } - -#endif /* __FTMISC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/raster/ftraster.c b/third_party/freetype/src/raster/ftraster.c deleted file mode 100644 index e4bab987285993858cad2f99c31e8bba066cc173..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/ftraster.c +++ /dev/null @@ -1,3200 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftraster.c */ -/* */ -/* The FreeType glyph rasterizer (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* This file can be compiled without the rest of the FreeType engine, by */ - /* defining the _STANDALONE_ macro when compiling it. You also need to */ - /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir) */ - /* directory. Typically, you should do something like */ - /* */ - /* - copy `src/raster/ftraster.c' (this file) to your current directory */ - /* */ - /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */ - /* current directory */ - /* */ - /* - compile `ftraster' with the _STANDALONE_ macro defined, as in */ - /* */ - /* cc -c -D_STANDALONE_ ftraster.c */ - /* */ - /* The renderer can be initialized with a call to */ - /* `ft_standard_raster.raster_new'; a bitmap can be generated */ - /* with a call to `ft_standard_raster.raster_render'. */ - /* */ - /* See the comments and documentation in the file `ftimage.h' for more */ - /* details on how the raster works. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This is a rewrite of the FreeType 1.x scan-line converter */ - /* */ - /*************************************************************************/ - -#ifdef _STANDALONE_ - - /* The size in bytes of the render pool used by the scan-line converter */ - /* to do all of its work. */ -#define FT_RENDER_POOL_SIZE 16384L - -#define FT_CONFIG_STANDARD_LIBRARY_H <stdlib.h> - -#include <string.h> /* for memset */ - -#include "ftmisc.h" -#include "ftimage.h" - -#else /* !_STANDALONE_ */ - -#include <ft2build.h> -#include "ftraster.h" -#include FT_INTERNAL_CALC_H /* for FT_MulDiv and FT_MulDiv_No_Round */ - -#include "rastpic.h" - -#endif /* !_STANDALONE_ */ - - - /*************************************************************************/ - /* */ - /* A simple technical note on how the raster works */ - /* ----------------------------------------------- */ - /* */ - /* Converting an outline into a bitmap is achieved in several steps: */ - /* */ - /* 1 - Decomposing the outline into successive `profiles'. Each */ - /* profile is simply an array of scanline intersections on a given */ - /* dimension. A profile's main attributes are */ - /* */ - /* o its scanline position boundaries, i.e. `Ymin' and `Ymax' */ - /* */ - /* o an array of intersection coordinates for each scanline */ - /* between `Ymin' and `Ymax' */ - /* */ - /* o a direction, indicating whether it was built going `up' or */ - /* `down', as this is very important for filling rules */ - /* */ - /* o its drop-out mode */ - /* */ - /* 2 - Sweeping the target map's scanlines in order to compute segment */ - /* `spans' which are then filled. Additionally, this pass */ - /* performs drop-out control. */ - /* */ - /* The outline data is parsed during step 1 only. The profiles are */ - /* built from the bottom of the render pool, used as a stack. The */ - /* following graphics shows the profile list under construction: */ - /* */ - /* __________________________________________________________ _ _ */ - /* | | | | | */ - /* | profile | coordinates for | profile | coordinates for |--> */ - /* | 1 | profile 1 | 2 | profile 2 |--> */ - /* |_________|_________________|_________|_________________|__ _ _ */ - /* */ - /* ^ ^ */ - /* | | */ - /* start of render pool top */ - /* */ - /* The top of the profile stack is kept in the `top' variable. */ - /* */ - /* As you can see, a profile record is pushed on top of the render */ - /* pool, which is then followed by its coordinates/intersections. If */ - /* a change of direction is detected in the outline, a new profile is */ - /* generated until the end of the outline. */ - /* */ - /* Note that when all profiles have been generated, the function */ - /* Finalize_Profile_Table() is used to record, for each profile, its */ - /* bottom-most scanline as well as the scanline above its upmost */ - /* boundary. These positions are called `y-turns' because they (sort */ - /* of) correspond to local extrema. They are stored in a sorted list */ - /* built from the top of the render pool as a downwards stack: */ - /* */ - /* _ _ _______________________________________ */ - /* | | */ - /* <--| sorted list of | */ - /* <--| extrema scanlines | */ - /* _ _ __________________|____________________| */ - /* */ - /* ^ ^ */ - /* | | */ - /* maxBuff sizeBuff = end of pool */ - /* */ - /* This list is later used during the sweep phase in order to */ - /* optimize performance (see technical note on the sweep below). */ - /* */ - /* Of course, the raster detects whether the two stacks collide and */ - /* handles the situation properly. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /*************************************************************************/ - /** **/ - /** CONFIGURATION MACROS **/ - /** **/ - /*************************************************************************/ - /*************************************************************************/ - - /* define DEBUG_RASTER if you want to compile a debugging version */ -/* #define DEBUG_RASTER */ - - - /*************************************************************************/ - /*************************************************************************/ - /** **/ - /** OTHER MACROS (do not change) **/ - /** **/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_raster - - -#ifdef _STANDALONE_ - - /* Auxiliary macros for token concatenation. */ -#define FT_ERR_XCAT( x, y ) x ## y -#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) - -#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) ) - - /* This macro is used to indicate that a function parameter is unused. */ - /* Its purpose is simply to reduce compiler warnings. Note also that */ - /* simply defining it as `(void)x' doesn't avoid warnings with certain */ - /* ANSI compilers (e.g. LCC). */ -#define FT_UNUSED( x ) (x) = (x) - - /* Disable the tracing mechanism for simplicity -- developers can */ - /* activate it easily by redefining these macros. */ -#ifndef FT_ERROR -#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */ -#endif - -#ifndef FT_TRACE -#define FT_TRACE( x ) do { } while ( 0 ) /* nothing */ -#define FT_TRACE1( x ) do { } while ( 0 ) /* nothing */ -#define FT_TRACE6( x ) do { } while ( 0 ) /* nothing */ -#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */ -#endif - -#ifndef FT_THROW -#define FT_THROW( e ) FT_ERR_CAT( Raster_Err_, e ) -#endif - -#define Raster_Err_None 0 -#define Raster_Err_Not_Ini -1 -#define Raster_Err_Overflow -2 -#define Raster_Err_Neg_Height -3 -#define Raster_Err_Invalid -4 -#define Raster_Err_Unsupported -5 - -#define ft_memset memset - -#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \ - raster_reset_, raster_set_mode_, \ - raster_render_, raster_done_ ) \ - const FT_Raster_Funcs class_ = \ - { \ - glyph_format_, \ - raster_new_, \ - raster_reset_, \ - raster_set_mode_, \ - raster_render_, \ - raster_done_ \ - }; - -#else /* !_STANDALONE_ */ - - -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H /* for FT_TRACE, FT_ERROR, and FT_THROW */ - -#include "rasterrs.h" - -#define Raster_Err_None FT_Err_Ok -#define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized -#define Raster_Err_Overflow Raster_Err_Raster_Overflow -#define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height -#define Raster_Err_Invalid Raster_Err_Invalid_Outline -#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph - - -#endif /* !_STANDALONE_ */ - - -#ifndef FT_MEM_SET -#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c ) -#endif - -#ifndef FT_MEM_ZERO -#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count ) -#endif - - /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */ - /* typically a small value and the result of a*b is known to fit into */ - /* 32 bits. */ -#define FMulDiv( a, b, c ) ( (a) * (b) / (c) ) - - /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */ - /* for clipping computations. It simply uses the FT_MulDiv() function */ - /* defined in `ftcalc.h'. */ -#define SMulDiv FT_MulDiv -#define SMulDiv_No_Round FT_MulDiv_No_Round - - /* The rasterizer is a very general purpose component; please leave */ - /* the following redefinitions there (you never know your target */ - /* environment). */ - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef NULL -#define NULL (void*)0 -#endif - -#ifndef SUCCESS -#define SUCCESS 0 -#endif - -#ifndef FAILURE -#define FAILURE 1 -#endif - - -#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */ - /* Setting this constant to more than 32 is a */ - /* pure waste of space. */ - -#define Pixel_Bits 6 /* fractional bits of *input* coordinates */ - - - /*************************************************************************/ - /*************************************************************************/ - /** **/ - /** SIMPLE TYPE DECLARATIONS **/ - /** **/ - /*************************************************************************/ - /*************************************************************************/ - - typedef int Int; - typedef unsigned int UInt; - typedef short Short; - typedef unsigned short UShort, *PUShort; - typedef long Long, *PLong; - typedef unsigned long ULong; - - typedef unsigned char Byte, *PByte; - typedef char Bool; - - - typedef union Alignment_ - { - Long l; - void* p; - void (*f)(void); - - } Alignment, *PAlignment; - - - typedef struct TPoint_ - { - Long x; - Long y; - - } TPoint; - - - /* values for the `flags' bit field */ -#define Flow_Up 0x08U -#define Overshoot_Top 0x10U -#define Overshoot_Bottom 0x20U - - - /* States of each line, arc, and profile */ - typedef enum TStates_ - { - Unknown_State, - Ascending_State, - Descending_State, - Flat_State - - } TStates; - - - typedef struct TProfile_ TProfile; - typedef TProfile* PProfile; - - struct TProfile_ - { - FT_F26Dot6 X; /* current coordinate during sweep */ - PProfile link; /* link to next profile (various purposes) */ - PLong offset; /* start of profile's data in render pool */ - UShort flags; /* Bit 0-2: drop-out mode */ - /* Bit 3: profile orientation (up/down) */ - /* Bit 4: is top profile? */ - /* Bit 5: is bottom profile? */ - Long height; /* profile's height in scanlines */ - Long start; /* profile's starting scanline */ - - Int countL; /* number of lines to step before this */ - /* profile becomes drawable */ - - PProfile next; /* next profile in same contour, used */ - /* during drop-out control */ - }; - - typedef PProfile TProfileList; - typedef PProfile* PProfileList; - - - /* Simple record used to implement a stack of bands, required */ - /* by the sub-banding mechanism */ - typedef struct black_TBand_ - { - Short y_min; /* band's minimum */ - Short y_max; /* band's maximum */ - - } black_TBand; - - -#define AlignProfileSize \ - ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) ) - - -#undef RAS_ARG -#undef RAS_ARGS -#undef RAS_VAR -#undef RAS_VARS - -#ifdef FT_STATIC_RASTER - - -#define RAS_ARGS /* void */ -#define RAS_ARG /* void */ - -#define RAS_VARS /* void */ -#define RAS_VAR /* void */ - -#define FT_UNUSED_RASTER do { } while ( 0 ) - - -#else /* !FT_STATIC_RASTER */ - - -#define RAS_ARGS black_PWorker worker, -#define RAS_ARG black_PWorker worker - -#define RAS_VARS worker, -#define RAS_VAR worker - -#define FT_UNUSED_RASTER FT_UNUSED( worker ) - - -#endif /* !FT_STATIC_RASTER */ - - - typedef struct black_TWorker_ black_TWorker, *black_PWorker; - - - /* prototypes used for sweep function dispatch */ - typedef void - Function_Sweep_Init( RAS_ARGS Short* min, - Short* max ); - - typedef void - Function_Sweep_Span( RAS_ARGS Short y, - FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ); - - typedef void - Function_Sweep_Step( RAS_ARG ); - - - /* NOTE: These operations are only valid on 2's complement processors */ -#undef FLOOR -#undef CEILING -#undef TRUNC -#undef SCALED - -#define FLOOR( x ) ( (x) & -ras.precision ) -#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision ) -#define TRUNC( x ) ( (Long)(x) >> ras.precision_bits ) -#define FRAC( x ) ( (x) & ( ras.precision - 1 ) ) -#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << ras.scale_shift ) \ - : ( (x) << ras.scale_shift ) ) \ - - ras.precision_half ) - -#define IS_BOTTOM_OVERSHOOT( x ) \ - (Bool)( CEILING( x ) - x >= ras.precision_half ) -#define IS_TOP_OVERSHOOT( x ) \ - (Bool)( x - FLOOR( x ) >= ras.precision_half ) - - /* The most used variables are positioned at the top of the structure. */ - /* Thus, their offset can be coded with less opcodes, resulting in a */ - /* smaller executable. */ - - struct black_TWorker_ - { - Int precision_bits; /* precision related variables */ - Int precision; - Int precision_half; - Int precision_shift; - Int precision_step; - Int precision_jitter; - - Int scale_shift; /* == precision_shift for bitmaps */ - /* == precision_shift+1 for pixmaps */ - - PLong buff; /* The profiles buffer */ - PLong sizeBuff; /* Render pool size */ - PLong maxBuff; /* Profiles buffer size */ - PLong top; /* Current cursor in buffer */ - - FT_Error error; - - Int numTurns; /* number of Y-turns in outline */ - - TPoint* arc; /* current Bezier arc pointer */ - - UShort bWidth; /* target bitmap width */ - PByte bTarget; /* target bitmap buffer */ - PByte gTarget; /* target pixmap buffer */ - - Long lastX, lastY; - Long minY, maxY; - - UShort num_Profs; /* current number of profiles */ - - Bool fresh; /* signals a fresh new profile which */ - /* `start' field must be completed */ - Bool joint; /* signals that the last arc ended */ - /* exactly on a scanline. Allows */ - /* removal of doublets */ - PProfile cProfile; /* current profile */ - PProfile fProfile; /* head of linked list of profiles */ - PProfile gProfile; /* contour's first profile in case */ - /* of impact */ - - TStates state; /* rendering state */ - - FT_Bitmap target; /* description of target bit/pixmap */ - FT_Outline outline; - - Long traceOfs; /* current offset in target bitmap */ - Long traceG; /* current offset in target pixmap */ - - Short traceIncr; /* sweep's increment in target bitmap */ - - /* dispatch variables */ - - Function_Sweep_Init* Proc_Sweep_Init; - Function_Sweep_Span* Proc_Sweep_Span; - Function_Sweep_Span* Proc_Sweep_Drop; - Function_Sweep_Step* Proc_Sweep_Step; - - Byte dropOutControl; /* current drop_out control method */ - - Bool second_pass; /* indicates whether a horizontal pass */ - /* should be performed to control */ - /* drop-out accurately when calling */ - /* Render_Glyph. */ - - TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */ - - black_TBand band_stack[16]; /* band stack used for sub-banding */ - Int band_top; /* band stack top */ - - }; - - - typedef struct black_TRaster_ - { - void* memory; - - } black_TRaster, *black_PRaster; - -#ifdef FT_STATIC_RASTER - - static black_TWorker cur_ras; -#define ras cur_ras - -#else /* !FT_STATIC_RASTER */ - -#define ras (*worker) - -#endif /* !FT_STATIC_RASTER */ - - - /*************************************************************************/ - /*************************************************************************/ - /** **/ - /** PROFILES COMPUTATION **/ - /** **/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Set_High_Precision */ - /* */ - /* <Description> */ - /* Set precision variables according to param flag. */ - /* */ - /* <Input> */ - /* High :: Set to True for high precision (typically for ppem < 24), */ - /* false otherwise. */ - /* */ - static void - Set_High_Precision( RAS_ARGS Int High ) - { - /* - * `precision_step' is used in `Bezier_Up' to decide when to split a - * given y-monotonous Bezier arc that crosses a scanline before - * approximating it as a straight segment. The default value of 32 (for - * low accuracy) corresponds to - * - * 32 / 64 == 0.5 pixels, - * - * while for the high accuracy case we have - * - * 256 / (1 << 12) = 0.0625 pixels. - * - * `precision_jitter' is an epsilon threshold used in - * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier - * decomposition (after all, we are working with approximations only); - * it avoids switching on additional pixels which would cause artifacts - * otherwise. - * - * The value of `precision_jitter' has been determined heuristically. - * - */ - - if ( High ) - { - ras.precision_bits = 12; - ras.precision_step = 256; - ras.precision_jitter = 30; - } - else - { - ras.precision_bits = 6; - ras.precision_step = 32; - ras.precision_jitter = 2; - } - - FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" )); - - ras.precision = 1 << ras.precision_bits; - ras.precision_half = ras.precision / 2; - ras.precision_shift = ras.precision_bits - Pixel_Bits; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* New_Profile */ - /* */ - /* <Description> */ - /* Create a new profile in the render pool. */ - /* */ - /* <Input> */ - /* aState :: The state/orientation of the new profile. */ - /* */ - /* overshoot :: Whether the profile's unrounded start position */ - /* differs by at least a half pixel. */ - /* */ - /* <Return> */ - /* SUCCESS on success. FAILURE in case of overflow or of incoherent */ - /* profile. */ - /* */ - static Bool - New_Profile( RAS_ARGS TStates aState, - Bool overshoot ) - { - if ( !ras.fProfile ) - { - ras.cProfile = (PProfile)ras.top; - ras.fProfile = ras.cProfile; - ras.top += AlignProfileSize; - } - - if ( ras.top >= ras.maxBuff ) - { - ras.error = FT_THROW( Overflow ); - return FAILURE; - } - - ras.cProfile->flags = 0; - ras.cProfile->start = 0; - ras.cProfile->height = 0; - ras.cProfile->offset = ras.top; - ras.cProfile->link = (PProfile)0; - ras.cProfile->next = (PProfile)0; - ras.cProfile->flags = ras.dropOutControl; - - switch ( aState ) - { - case Ascending_State: - ras.cProfile->flags |= Flow_Up; - if ( overshoot ) - ras.cProfile->flags |= Overshoot_Bottom; - - FT_TRACE6(( " new ascending profile = %p\n", ras.cProfile )); - break; - - case Descending_State: - if ( overshoot ) - ras.cProfile->flags |= Overshoot_Top; - FT_TRACE6(( " new descending profile = %p\n", ras.cProfile )); - break; - - default: - FT_ERROR(( "New_Profile: invalid profile direction\n" )); - ras.error = FT_THROW( Invalid ); - return FAILURE; - } - - if ( !ras.gProfile ) - ras.gProfile = ras.cProfile; - - ras.state = aState; - ras.fresh = TRUE; - ras.joint = FALSE; - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* End_Profile */ - /* */ - /* <Description> */ - /* Finalize the current profile. */ - /* */ - /* <Input> */ - /* overshoot :: Whether the profile's unrounded end position differs */ - /* by at least a half pixel. */ - /* */ - /* <Return> */ - /* SUCCESS on success. FAILURE in case of overflow or incoherency. */ - /* */ - static Bool - End_Profile( RAS_ARGS Bool overshoot ) - { - Long h; - - - h = (Long)( ras.top - ras.cProfile->offset ); - - if ( h < 0 ) - { - FT_ERROR(( "End_Profile: negative height encountered\n" )); - ras.error = FT_THROW( Neg_Height ); - return FAILURE; - } - - if ( h > 0 ) - { - PProfile oldProfile; - - - FT_TRACE6(( " ending profile %p, start = %ld, height = %ld\n", - ras.cProfile, ras.cProfile->start, h )); - - ras.cProfile->height = h; - if ( overshoot ) - { - if ( ras.cProfile->flags & Flow_Up ) - ras.cProfile->flags |= Overshoot_Top; - else - ras.cProfile->flags |= Overshoot_Bottom; - } - - oldProfile = ras.cProfile; - ras.cProfile = (PProfile)ras.top; - - ras.top += AlignProfileSize; - - ras.cProfile->height = 0; - ras.cProfile->offset = ras.top; - - oldProfile->next = ras.cProfile; - ras.num_Profs++; - } - - if ( ras.top >= ras.maxBuff ) - { - FT_TRACE1(( "overflow in End_Profile\n" )); - ras.error = FT_THROW( Overflow ); - return FAILURE; - } - - ras.joint = FALSE; - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Insert_Y_Turn */ - /* */ - /* <Description> */ - /* Insert a salient into the sorted list placed on top of the render */ - /* pool. */ - /* */ - /* <Input> */ - /* New y scanline position. */ - /* */ - /* <Return> */ - /* SUCCESS on success. FAILURE in case of overflow. */ - /* */ - static Bool - Insert_Y_Turn( RAS_ARGS Int y ) - { - PLong y_turns; - Int n; - - - n = ras.numTurns - 1; - y_turns = ras.sizeBuff - ras.numTurns; - - /* look for first y value that is <= */ - while ( n >= 0 && y < y_turns[n] ) - n--; - - /* if it is <, simply insert it, ignore if == */ - if ( n >= 0 && y > y_turns[n] ) - do - { - Int y2 = (Int)y_turns[n]; - - - y_turns[n] = y; - y = y2; - } while ( --n >= 0 ); - - if ( n < 0 ) - { - ras.maxBuff--; - if ( ras.maxBuff <= ras.top ) - { - ras.error = FT_THROW( Overflow ); - return FAILURE; - } - ras.numTurns++; - ras.sizeBuff[-ras.numTurns] = y; - } - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Finalize_Profile_Table */ - /* */ - /* <Description> */ - /* Adjust all links in the profiles list. */ - /* */ - /* <Return> */ - /* SUCCESS on success. FAILURE in case of overflow. */ - /* */ - static Bool - Finalize_Profile_Table( RAS_ARG ) - { - UShort n; - PProfile p; - - - n = ras.num_Profs; - p = ras.fProfile; - - if ( n > 1 && p ) - { - do - { - Int bottom, top; - - - if ( n > 1 ) - p->link = (PProfile)( p->offset + p->height ); - else - p->link = NULL; - - if ( p->flags & Flow_Up ) - { - bottom = (Int)p->start; - top = (Int)( p->start + p->height - 1 ); - } - else - { - bottom = (Int)( p->start - p->height + 1 ); - top = (Int)p->start; - p->start = bottom; - p->offset += p->height - 1; - } - - if ( Insert_Y_Turn( RAS_VARS bottom ) || - Insert_Y_Turn( RAS_VARS top + 1 ) ) - return FAILURE; - - p = p->link; - } while ( --n ); - } - else - ras.fProfile = NULL; - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Split_Conic */ - /* */ - /* <Description> */ - /* Subdivide one conic Bezier into two joint sub-arcs in the Bezier */ - /* stack. */ - /* */ - /* <Input> */ - /* None (subdivided Bezier is taken from the top of the stack). */ - /* */ - /* <Note> */ - /* This routine is the `beef' of this component. It is _the_ inner */ - /* loop that should be optimized to hell to get the best performance. */ - /* */ - static void - Split_Conic( TPoint* base ) - { - Long a, b; - - - base[4].x = base[2].x; - b = base[1].x; - a = base[3].x = ( base[2].x + b ) / 2; - b = base[1].x = ( base[0].x + b ) / 2; - base[2].x = ( a + b ) / 2; - - base[4].y = base[2].y; - b = base[1].y; - a = base[3].y = ( base[2].y + b ) / 2; - b = base[1].y = ( base[0].y + b ) / 2; - base[2].y = ( a + b ) / 2; - - /* hand optimized. gcc doesn't seem to be too good at common */ - /* expression substitution and instruction scheduling ;-) */ - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Split_Cubic */ - /* */ - /* <Description> */ - /* Subdivide a third-order Bezier arc into two joint sub-arcs in the */ - /* Bezier stack. */ - /* */ - /* <Note> */ - /* This routine is the `beef' of the component. It is one of _the_ */ - /* inner loops that should be optimized like hell to get the best */ - /* performance. */ - /* */ - static void - Split_Cubic( TPoint* base ) - { - Long a, b, c, d; - - - base[6].x = base[3].x; - c = base[1].x; - d = base[2].x; - base[1].x = a = ( base[0].x + c + 1 ) >> 1; - base[5].x = b = ( base[3].x + d + 1 ) >> 1; - c = ( c + d + 1 ) >> 1; - base[2].x = a = ( a + c + 1 ) >> 1; - base[4].x = b = ( b + c + 1 ) >> 1; - base[3].x = ( a + b + 1 ) >> 1; - - base[6].y = base[3].y; - c = base[1].y; - d = base[2].y; - base[1].y = a = ( base[0].y + c + 1 ) >> 1; - base[5].y = b = ( base[3].y + d + 1 ) >> 1; - c = ( c + d + 1 ) >> 1; - base[2].y = a = ( a + c + 1 ) >> 1; - base[4].y = b = ( b + c + 1 ) >> 1; - base[3].y = ( a + b + 1 ) >> 1; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Line_Up */ - /* */ - /* <Description> */ - /* Compute the x-coordinates of an ascending line segment and store */ - /* them in the render pool. */ - /* */ - /* <Input> */ - /* x1 :: The x-coordinate of the segment's start point. */ - /* */ - /* y1 :: The y-coordinate of the segment's start point. */ - /* */ - /* x2 :: The x-coordinate of the segment's end point. */ - /* */ - /* y2 :: The y-coordinate of the segment's end point. */ - /* */ - /* miny :: A lower vertical clipping bound value. */ - /* */ - /* maxy :: An upper vertical clipping bound value. */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow. */ - /* */ - static Bool - Line_Up( RAS_ARGS Long x1, - Long y1, - Long x2, - Long y2, - Long miny, - Long maxy ) - { - Long Dx, Dy; - Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */ - Long Ix, Rx, Ax; - - PLong top; - - - Dx = x2 - x1; - Dy = y2 - y1; - - if ( Dy <= 0 || y2 < miny || y1 > maxy ) - return SUCCESS; - - if ( y1 < miny ) - { - /* Take care: miny-y1 can be a very large value; we use */ - /* a slow MulDiv function to avoid clipping bugs */ - x1 += SMulDiv( Dx, miny - y1, Dy ); - e1 = (Int)TRUNC( miny ); - f1 = 0; - } - else - { - e1 = (Int)TRUNC( y1 ); - f1 = (Int)FRAC( y1 ); - } - - if ( y2 > maxy ) - { - /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */ - e2 = (Int)TRUNC( maxy ); - f2 = 0; - } - else - { - e2 = (Int)TRUNC( y2 ); - f2 = (Int)FRAC( y2 ); - } - - if ( f1 > 0 ) - { - if ( e1 == e2 ) - return SUCCESS; - else - { - x1 += SMulDiv( Dx, ras.precision - f1, Dy ); - e1 += 1; - } - } - else - if ( ras.joint ) - { - ras.top--; - ras.joint = FALSE; - } - - ras.joint = (char)( f2 == 0 ); - - if ( ras.fresh ) - { - ras.cProfile->start = e1; - ras.fresh = FALSE; - } - - size = e2 - e1 + 1; - if ( ras.top + size >= ras.maxBuff ) - { - ras.error = FT_THROW( Overflow ); - return FAILURE; - } - - if ( Dx > 0 ) - { - Ix = SMulDiv_No_Round( ras.precision, Dx, Dy ); - Rx = ( ras.precision * Dx ) % Dy; - Dx = 1; - } - else - { - Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy ); - Rx = ( ras.precision * -Dx ) % Dy; - Dx = -1; - } - - Ax = -Dy; - top = ras.top; - - while ( size > 0 ) - { - *top++ = x1; - - x1 += Ix; - Ax += Rx; - if ( Ax >= 0 ) - { - Ax -= Dy; - x1 += Dx; - } - size--; - } - - ras.top = top; - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Line_Down */ - /* */ - /* <Description> */ - /* Compute the x-coordinates of an descending line segment and store */ - /* them in the render pool. */ - /* */ - /* <Input> */ - /* x1 :: The x-coordinate of the segment's start point. */ - /* */ - /* y1 :: The y-coordinate of the segment's start point. */ - /* */ - /* x2 :: The x-coordinate of the segment's end point. */ - /* */ - /* y2 :: The y-coordinate of the segment's end point. */ - /* */ - /* miny :: A lower vertical clipping bound value. */ - /* */ - /* maxy :: An upper vertical clipping bound value. */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow. */ - /* */ - static Bool - Line_Down( RAS_ARGS Long x1, - Long y1, - Long x2, - Long y2, - Long miny, - Long maxy ) - { - Bool result, fresh; - - - fresh = ras.fresh; - - result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); - - if ( fresh && !ras.fresh ) - ras.cProfile->start = -ras.cProfile->start; - - return result; - } - - - /* A function type describing the functions used to split Bezier arcs */ - typedef void (*TSplitter)( TPoint* base ); - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Bezier_Up */ - /* */ - /* <Description> */ - /* Compute the x-coordinates of an ascending Bezier arc and store */ - /* them in the render pool. */ - /* */ - /* <Input> */ - /* degree :: The degree of the Bezier arc (either 2 or 3). */ - /* */ - /* splitter :: The function to split Bezier arcs. */ - /* */ - /* miny :: A lower vertical clipping bound value. */ - /* */ - /* maxy :: An upper vertical clipping bound value. */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow. */ - /* */ - static Bool - Bezier_Up( RAS_ARGS Int degree, - TSplitter splitter, - Long miny, - Long maxy ) - { - Long y1, y2, e, e2, e0; - Short f1; - - TPoint* arc; - TPoint* start_arc; - - PLong top; - - - arc = ras.arc; - y1 = arc[degree].y; - y2 = arc[0].y; - top = ras.top; - - if ( y2 < miny || y1 > maxy ) - goto Fin; - - e2 = FLOOR( y2 ); - - if ( e2 > maxy ) - e2 = maxy; - - e0 = miny; - - if ( y1 < miny ) - e = miny; - else - { - e = CEILING( y1 ); - f1 = (Short)( FRAC( y1 ) ); - e0 = e; - - if ( f1 == 0 ) - { - if ( ras.joint ) - { - top--; - ras.joint = FALSE; - } - - *top++ = arc[degree].x; - - e += ras.precision; - } - } - - if ( ras.fresh ) - { - ras.cProfile->start = TRUNC( e0 ); - ras.fresh = FALSE; - } - - if ( e2 < e ) - goto Fin; - - if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) - { - ras.top = top; - ras.error = FT_THROW( Overflow ); - return FAILURE; - } - - start_arc = arc; - - do - { - ras.joint = FALSE; - - y2 = arc[0].y; - - if ( y2 > e ) - { - y1 = arc[degree].y; - if ( y2 - y1 >= ras.precision_step ) - { - splitter( arc ); - arc += degree; - } - else - { - *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x, - e - y1, y2 - y1 ); - arc -= degree; - e += ras.precision; - } - } - else - { - if ( y2 == e ) - { - ras.joint = TRUE; - *top++ = arc[0].x; - - e += ras.precision; - } - arc -= degree; - } - } while ( arc >= start_arc && e <= e2 ); - - Fin: - ras.top = top; - ras.arc -= degree; - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Bezier_Down */ - /* */ - /* <Description> */ - /* Compute the x-coordinates of an descending Bezier arc and store */ - /* them in the render pool. */ - /* */ - /* <Input> */ - /* degree :: The degree of the Bezier arc (either 2 or 3). */ - /* */ - /* splitter :: The function to split Bezier arcs. */ - /* */ - /* miny :: A lower vertical clipping bound value. */ - /* */ - /* maxy :: An upper vertical clipping bound value. */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow. */ - /* */ - static Bool - Bezier_Down( RAS_ARGS Int degree, - TSplitter splitter, - Long miny, - Long maxy ) - { - TPoint* arc = ras.arc; - Bool result, fresh; - - - arc[0].y = -arc[0].y; - arc[1].y = -arc[1].y; - arc[2].y = -arc[2].y; - if ( degree > 2 ) - arc[3].y = -arc[3].y; - - fresh = ras.fresh; - - result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny ); - - if ( fresh && !ras.fresh ) - ras.cProfile->start = -ras.cProfile->start; - - arc[0].y = -arc[0].y; - return result; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Line_To */ - /* */ - /* <Description> */ - /* Inject a new line segment and adjust the Profiles list. */ - /* */ - /* <Input> */ - /* x :: The x-coordinate of the segment's end point (its start point */ - /* is stored in `lastX'). */ - /* */ - /* y :: The y-coordinate of the segment's end point (its start point */ - /* is stored in `lastY'). */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ - /* profile. */ - /* */ - static Bool - Line_To( RAS_ARGS Long x, - Long y ) - { - /* First, detect a change of direction */ - - switch ( ras.state ) - { - case Unknown_State: - if ( y > ras.lastY ) - { - if ( New_Profile( RAS_VARS Ascending_State, - IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - else - { - if ( y < ras.lastY ) - if ( New_Profile( RAS_VARS Descending_State, - IS_TOP_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - break; - - case Ascending_State: - if ( y < ras.lastY ) - { - if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) || - New_Profile( RAS_VARS Descending_State, - IS_TOP_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - break; - - case Descending_State: - if ( y > ras.lastY ) - { - if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) || - New_Profile( RAS_VARS Ascending_State, - IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ) - return FAILURE; - } - break; - - default: - ; - } - - /* Then compute the lines */ - - switch ( ras.state ) - { - case Ascending_State: - if ( Line_Up( RAS_VARS ras.lastX, ras.lastY, - x, y, ras.minY, ras.maxY ) ) - return FAILURE; - break; - - case Descending_State: - if ( Line_Down( RAS_VARS ras.lastX, ras.lastY, - x, y, ras.minY, ras.maxY ) ) - return FAILURE; - break; - - default: - ; - } - - ras.lastX = x; - ras.lastY = y; - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Conic_To */ - /* */ - /* <Description> */ - /* Inject a new conic arc and adjust the profile list. */ - /* */ - /* <Input> */ - /* cx :: The x-coordinate of the arc's new control point. */ - /* */ - /* cy :: The y-coordinate of the arc's new control point. */ - /* */ - /* x :: The x-coordinate of the arc's end point (its start point is */ - /* stored in `lastX'). */ - /* */ - /* y :: The y-coordinate of the arc's end point (its start point is */ - /* stored in `lastY'). */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ - /* profile. */ - /* */ - static Bool - Conic_To( RAS_ARGS Long cx, - Long cy, - Long x, - Long y ) - { - Long y1, y2, y3, x3, ymin, ymax; - TStates state_bez; - - - ras.arc = ras.arcs; - ras.arc[2].x = ras.lastX; - ras.arc[2].y = ras.lastY; - ras.arc[1].x = cx; - ras.arc[1].y = cy; - ras.arc[0].x = x; - ras.arc[0].y = y; - - do - { - y1 = ras.arc[2].y; - y2 = ras.arc[1].y; - y3 = ras.arc[0].y; - x3 = ras.arc[0].x; - - /* first, categorize the Bezier arc */ - - if ( y1 <= y3 ) - { - ymin = y1; - ymax = y3; - } - else - { - ymin = y3; - ymax = y1; - } - - if ( y2 < ymin || y2 > ymax ) - { - /* this arc has no given direction, split it! */ - Split_Conic( ras.arc ); - ras.arc += 2; - } - else if ( y1 == y3 ) - { - /* this arc is flat, ignore it and pop it from the Bezier stack */ - ras.arc -= 2; - } - else - { - /* the arc is y-monotonous, either ascending or descending */ - /* detect a change of direction */ - state_bez = y1 < y3 ? Ascending_State : Descending_State; - if ( ras.state != state_bez ) - { - Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 ) - : IS_TOP_OVERSHOOT( y1 ); - - - /* finalize current profile if any */ - if ( ras.state != Unknown_State && - End_Profile( RAS_VARS o ) ) - goto Fail; - - /* create a new profile */ - if ( New_Profile( RAS_VARS state_bez, o ) ) - goto Fail; - } - - /* now call the appropriate routine */ - if ( state_bez == Ascending_State ) - { - if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) - goto Fail; - } - else - if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) - goto Fail; - } - - } while ( ras.arc >= ras.arcs ); - - ras.lastX = x3; - ras.lastY = y3; - - return SUCCESS; - - Fail: - return FAILURE; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Cubic_To */ - /* */ - /* <Description> */ - /* Inject a new cubic arc and adjust the profile list. */ - /* */ - /* <Input> */ - /* cx1 :: The x-coordinate of the arc's first new control point. */ - /* */ - /* cy1 :: The y-coordinate of the arc's first new control point. */ - /* */ - /* cx2 :: The x-coordinate of the arc's second new control point. */ - /* */ - /* cy2 :: The y-coordinate of the arc's second new control point. */ - /* */ - /* x :: The x-coordinate of the arc's end point (its start point is */ - /* stored in `lastX'). */ - /* */ - /* y :: The y-coordinate of the arc's end point (its start point is */ - /* stored in `lastY'). */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ - /* profile. */ - /* */ - static Bool - Cubic_To( RAS_ARGS Long cx1, - Long cy1, - Long cx2, - Long cy2, - Long x, - Long y ) - { - Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2; - TStates state_bez; - - - ras.arc = ras.arcs; - ras.arc[3].x = ras.lastX; - ras.arc[3].y = ras.lastY; - ras.arc[2].x = cx1; - ras.arc[2].y = cy1; - ras.arc[1].x = cx2; - ras.arc[1].y = cy2; - ras.arc[0].x = x; - ras.arc[0].y = y; - - do - { - y1 = ras.arc[3].y; - y2 = ras.arc[2].y; - y3 = ras.arc[1].y; - y4 = ras.arc[0].y; - x4 = ras.arc[0].x; - - /* first, categorize the Bezier arc */ - - if ( y1 <= y4 ) - { - ymin1 = y1; - ymax1 = y4; - } - else - { - ymin1 = y4; - ymax1 = y1; - } - - if ( y2 <= y3 ) - { - ymin2 = y2; - ymax2 = y3; - } - else - { - ymin2 = y3; - ymax2 = y2; - } - - if ( ymin2 < ymin1 || ymax2 > ymax1 ) - { - /* this arc has no given direction, split it! */ - Split_Cubic( ras.arc ); - ras.arc += 3; - } - else if ( y1 == y4 ) - { - /* this arc is flat, ignore it and pop it from the Bezier stack */ - ras.arc -= 3; - } - else - { - state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State; - - /* detect a change of direction */ - if ( ras.state != state_bez ) - { - Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 ) - : IS_TOP_OVERSHOOT( y1 ); - - - /* finalize current profile if any */ - if ( ras.state != Unknown_State && - End_Profile( RAS_VARS o ) ) - goto Fail; - - if ( New_Profile( RAS_VARS state_bez, o ) ) - goto Fail; - } - - /* compute intersections */ - if ( state_bez == Ascending_State ) - { - if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) - goto Fail; - } - else - if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) - goto Fail; - } - - } while ( ras.arc >= ras.arcs ); - - ras.lastX = x4; - ras.lastY = y4; - - return SUCCESS; - - Fail: - return FAILURE; - } - - -#undef SWAP_ -#define SWAP_( x, y ) do \ - { \ - Long swap = x; \ - \ - \ - x = y; \ - y = swap; \ - } while ( 0 ) - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Decompose_Curve */ - /* */ - /* <Description> */ - /* Scan the outline arrays in order to emit individual segments and */ - /* Beziers by calling Line_To() and Bezier_To(). It handles all */ - /* weird cases, like when the first point is off the curve, or when */ - /* there are simply no `on' points in the contour! */ - /* */ - /* <Input> */ - /* first :: The index of the first point in the contour. */ - /* */ - /* last :: The index of the last point in the contour. */ - /* */ - /* flipped :: If set, flip the direction of the curve. */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE on error. */ - /* */ - static Bool - Decompose_Curve( RAS_ARGS UShort first, - UShort last, - Int flipped ) - { - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_start; - - FT_Vector* points; - FT_Vector* point; - FT_Vector* limit; - char* tags; - - UInt tag; /* current point's state */ - - - points = ras.outline.points; - limit = points + last; - - v_start.x = SCALED( points[first].x ); - v_start.y = SCALED( points[first].y ); - v_last.x = SCALED( points[last].x ); - v_last.y = SCALED( points[last].y ); - - if ( flipped ) - { - SWAP_( v_start.x, v_start.y ); - SWAP_( v_last.x, v_last.y ); - } - - v_control = v_start; - - point = points + first; - tags = ras.outline.tags + first; - - /* set scan mode if necessary */ - if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE ) - ras.dropOutControl = (Byte)tags[0] >> 5; - - tag = FT_CURVE_TAG( tags[0] ); - - /* A contour cannot start with a cubic control point! */ - if ( tag == FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - /* check first point to determine origin */ - if ( tag == FT_CURVE_TAG_CONIC ) - { - /* first point is conic control. Yes, this happens. */ - if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - limit--; - } - else - { - /* if both first and last points are conic, */ - /* start at their middle and record its position */ - /* for closure */ - v_start.x = ( v_start.x + v_last.x ) / 2; - v_start.y = ( v_start.y + v_last.y ) / 2; - - /* v_last = v_start; */ - } - point--; - tags--; - } - - ras.lastX = v_start.x; - ras.lastY = v_start.y; - - while ( point < limit ) - { - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - - switch ( tag ) - { - case FT_CURVE_TAG_ON: /* emit a single line_to */ - { - Long x, y; - - - x = SCALED( point->x ); - y = SCALED( point->y ); - if ( flipped ) - SWAP_( x, y ); - - if ( Line_To( RAS_VARS x, y ) ) - goto Fail; - continue; - } - - case FT_CURVE_TAG_CONIC: /* consume conic arcs */ - v_control.x = SCALED( point[0].x ); - v_control.y = SCALED( point[0].y ); - - if ( flipped ) - SWAP_( v_control.x, v_control.y ); - - Do_Conic: - if ( point < limit ) - { - FT_Vector v_middle; - Long x, y; - - - point++; - tags++; - tag = FT_CURVE_TAG( tags[0] ); - - x = SCALED( point[0].x ); - y = SCALED( point[0].y ); - - if ( flipped ) - SWAP_( x, y ); - - if ( tag == FT_CURVE_TAG_ON ) - { - if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) ) - goto Fail; - continue; - } - - if ( tag != FT_CURVE_TAG_CONIC ) - goto Invalid_Outline; - - v_middle.x = ( v_control.x + x ) / 2; - v_middle.y = ( v_control.y + y ) / 2; - - if ( Conic_To( RAS_VARS v_control.x, v_control.y, - v_middle.x, v_middle.y ) ) - goto Fail; - - v_control.x = x; - v_control.y = y; - - goto Do_Conic; - } - - if ( Conic_To( RAS_VARS v_control.x, v_control.y, - v_start.x, v_start.y ) ) - goto Fail; - - goto Close; - - default: /* FT_CURVE_TAG_CUBIC */ - { - Long x1, y1, x2, y2, x3, y3; - - - if ( point + 1 > limit || - FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - point += 2; - tags += 2; - - x1 = SCALED( point[-2].x ); - y1 = SCALED( point[-2].y ); - x2 = SCALED( point[-1].x ); - y2 = SCALED( point[-1].y ); - - if ( flipped ) - { - SWAP_( x1, y1 ); - SWAP_( x2, y2 ); - } - - if ( point <= limit ) - { - x3 = SCALED( point[0].x ); - y3 = SCALED( point[0].y ); - - if ( flipped ) - SWAP_( x3, y3 ); - - if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) ) - goto Fail; - continue; - } - - if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) ) - goto Fail; - goto Close; - } - } - } - - /* close the contour with a line segment */ - if ( Line_To( RAS_VARS v_start.x, v_start.y ) ) - goto Fail; - - Close: - return SUCCESS; - - Invalid_Outline: - ras.error = FT_THROW( Invalid ); - - Fail: - return FAILURE; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Convert_Glyph */ - /* */ - /* <Description> */ - /* Convert a glyph into a series of segments and arcs and make a */ - /* profiles list with them. */ - /* */ - /* <Input> */ - /* flipped :: If set, flip the direction of curve. */ - /* */ - /* <Return> */ - /* SUCCESS on success, FAILURE if any error was encountered during */ - /* rendering. */ - /* */ - static Bool - Convert_Glyph( RAS_ARGS Int flipped ) - { - Int i; - UInt start; - - - ras.fProfile = NULL; - ras.joint = FALSE; - ras.fresh = FALSE; - - ras.maxBuff = ras.sizeBuff - AlignProfileSize; - - ras.numTurns = 0; - - ras.cProfile = (PProfile)ras.top; - ras.cProfile->offset = ras.top; - ras.num_Profs = 0; - - start = 0; - - for ( i = 0; i < ras.outline.n_contours; i++ ) - { - PProfile lastProfile; - Bool o; - - - ras.state = Unknown_State; - ras.gProfile = NULL; - - if ( Decompose_Curve( RAS_VARS (UShort)start, - (UShort)ras.outline.contours[i], - flipped ) ) - return FAILURE; - - start = (UShort)ras.outline.contours[i] + 1; - - /* we must now check whether the extreme arcs join or not */ - if ( FRAC( ras.lastY ) == 0 && - ras.lastY >= ras.minY && - ras.lastY <= ras.maxY ) - if ( ras.gProfile && - ( ras.gProfile->flags & Flow_Up ) == - ( ras.cProfile->flags & Flow_Up ) ) - ras.top--; - /* Note that ras.gProfile can be nil if the contour was too small */ - /* to be drawn. */ - - lastProfile = ras.cProfile; - if ( ras.top != ras.cProfile->offset && - ( ras.cProfile->flags & Flow_Up ) ) - o = IS_TOP_OVERSHOOT( ras.lastY ); - else - o = IS_BOTTOM_OVERSHOOT( ras.lastY ); - if ( End_Profile( RAS_VARS o ) ) - return FAILURE; - - /* close the `next profile in contour' linked list */ - if ( ras.gProfile ) - lastProfile->next = ras.gProfile; - } - - if ( Finalize_Profile_Table( RAS_VAR ) ) - return FAILURE; - - return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /** **/ - /** SCAN-LINE SWEEPS AND DRAWING **/ - /** **/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* Init_Linked */ - /* */ - /* Initializes an empty linked list. */ - /* */ - static void - Init_Linked( TProfileList* l ) - { - *l = NULL; - } - - - /*************************************************************************/ - /* */ - /* InsNew */ - /* */ - /* Inserts a new profile in a linked list. */ - /* */ - static void - InsNew( PProfileList list, - PProfile profile ) - { - PProfile *old, current; - Long x; - - - old = list; - current = *old; - x = profile->X; - - while ( current ) - { - if ( x < current->X ) - break; - old = ¤t->link; - current = *old; - } - - profile->link = current; - *old = profile; - } - - - /*************************************************************************/ - /* */ - /* DelOld */ - /* */ - /* Removes an old profile from a linked list. */ - /* */ - static void - DelOld( PProfileList list, - PProfile profile ) - { - PProfile *old, current; - - - old = list; - current = *old; - - while ( current ) - { - if ( current == profile ) - { - *old = current->link; - return; - } - - old = ¤t->link; - current = *old; - } - - /* we should never get there, unless the profile was not part of */ - /* the list. */ - } - - - /*************************************************************************/ - /* */ - /* Sort */ - /* */ - /* Sorts a trace list. In 95%, the list is already sorted. We need */ - /* an algorithm which is fast in this case. Bubble sort is enough */ - /* and simple. */ - /* */ - static void - Sort( PProfileList list ) - { - PProfile *old, current, next; - - - /* First, set the new X coordinate of each profile */ - current = *list; - while ( current ) - { - current->X = *current->offset; - current->offset += ( current->flags & Flow_Up ) ? 1 : -1; - current->height--; - current = current->link; - } - - /* Then sort them */ - old = list; - current = *old; - - if ( !current ) - return; - - next = current->link; - - while ( next ) - { - if ( current->X <= next->X ) - { - old = ¤t->link; - current = *old; - - if ( !current ) - return; - } - else - { - *old = next; - current->link = next->link; - next->link = current; - - old = list; - current = *old; - } - - next = current->link; - } - } - - - /*************************************************************************/ - /* */ - /* Vertical Sweep Procedure Set */ - /* */ - /* These four routines are used during the vertical black/white sweep */ - /* phase by the generic Draw_Sweep() function. */ - /* */ - /*************************************************************************/ - - static void - Vertical_Sweep_Init( RAS_ARGS Short* min, - Short* max ) - { - Long pitch = ras.target.pitch; - - FT_UNUSED( max ); - - - ras.traceIncr = (Short)-pitch; - ras.traceOfs = -*min * pitch; - if ( pitch > 0 ) - ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch; - } - - - static void - Vertical_Sweep_Span( RAS_ARGS Short y, - FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) - { - Long e1, e2; - Byte* target; - - Int dropOutControl = left->flags & 7; - - FT_UNUSED( y ); - FT_UNUSED( left ); - FT_UNUSED( right ); - - - /* in high-precision mode, we need 12 digits after the comma to */ - /* represent multiples of 1/(1<<12) = 1/4096 */ - FT_TRACE7(( " y=%d x=[%.12f;%.12f], drop-out=%d", - y, - x1 / (double)ras.precision, - x2 / (double)ras.precision, - dropOutControl )); - - /* Drop-out control */ - - e1 = TRUNC( CEILING( x1 ) ); - - if ( dropOutControl != 2 && - x2 - x1 - ras.precision <= ras.precision_jitter ) - e2 = e1; - else - e2 = TRUNC( FLOOR( x2 ) ); - - if ( e2 >= 0 && e1 < ras.bWidth ) - { - Int c1, c2; - Byte f1, f2; - - - if ( e1 < 0 ) - e1 = 0; - if ( e2 >= ras.bWidth ) - e2 = ras.bWidth - 1; - - FT_TRACE7(( " -> x=[%d;%d]", e1, e2 )); - - c1 = (Short)( e1 >> 3 ); - c2 = (Short)( e2 >> 3 ); - - f1 = (Byte) ( 0xFF >> ( e1 & 7 ) ); - f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) ); - - target = ras.bTarget + ras.traceOfs + c1; - c2 -= c1; - - if ( c2 > 0 ) - { - target[0] |= f1; - - /* memset() is slower than the following code on many platforms. */ - /* This is due to the fact that, in the vast majority of cases, */ - /* the span length in bytes is relatively small. */ - c2--; - while ( c2 > 0 ) - { - *(++target) = 0xFF; - c2--; - } - target[1] |= f2; - } - else - *target |= ( f1 & f2 ); - } - - FT_TRACE7(( "\n" )); - } - - - static void - Vertical_Sweep_Drop( RAS_ARGS Short y, - FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) - { - Long e1, e2, pxl; - Short c1, f1; - - - FT_TRACE7(( " y=%d x=[%.12f;%.12f]", - y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); - - /* Drop-out control */ - - /* e2 x2 x1 e1 */ - /* */ - /* ^ | */ - /* | | */ - /* +-------------+---------------------+------------+ */ - /* | | */ - /* | v */ - /* */ - /* pixel contour contour pixel */ - /* center center */ - - /* drop-out mode scan conversion rules (as defined in OpenType) */ - /* --------------------------------------------------------------- */ - /* 0 1, 2, 3 */ - /* 1 1, 2, 4 */ - /* 2 1, 2 */ - /* 3 same as mode 2 */ - /* 4 1, 2, 5 */ - /* 5 1, 2, 6 */ - /* 6, 7 same as mode 2 */ - - e1 = CEILING( x1 ); - e2 = FLOOR ( x2 ); - pxl = e1; - - if ( e1 > e2 ) - { - Int dropOutControl = left->flags & 7; - - - FT_TRACE7(( ", drop-out=%d", dropOutControl )); - - if ( e1 == e2 + ras.precision ) - { - switch ( dropOutControl ) - { - case 0: /* simple drop-outs including stubs */ - pxl = e2; - break; - - case 4: /* smart drop-outs including stubs */ - pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); - break; - - case 1: /* simple drop-outs excluding stubs */ - case 5: /* smart drop-outs excluding stubs */ - - /* Drop-out Control Rules #4 and #6 */ - - /* The specification neither provides an exact definition */ - /* of a `stub' nor gives exact rules to exclude them. */ - /* */ - /* Here the constraints we use to recognize a stub. */ - /* */ - /* upper stub: */ - /* */ - /* - P_Left and P_Right are in the same contour */ - /* - P_Right is the successor of P_Left in that contour */ - /* - y is the top of P_Left and P_Right */ - /* */ - /* lower stub: */ - /* */ - /* - P_Left and P_Right are in the same contour */ - /* - P_Left is the successor of P_Right in that contour */ - /* - y is the bottom of P_Left */ - /* */ - /* We draw a stub if the following constraints are met. */ - /* */ - /* - for an upper or lower stub, there is top or bottom */ - /* overshoot, respectively */ - /* - the covered interval is greater or equal to a half */ - /* pixel */ - - /* upper stub test */ - if ( left->next == right && - left->height <= 0 && - !( left->flags & Overshoot_Top && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - /* lower stub test */ - if ( right->next == left && - left->start == y && - !( left->flags & Overshoot_Bottom && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - if ( dropOutControl == 1 ) - pxl = e2; - else - pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); - break; - - default: /* modes 2, 3, 6, 7 */ - goto Exit; /* no drop-out control */ - } - - /* undocumented but confirmed: If the drop-out would result in a */ - /* pixel outside of the bounding box, use the pixel inside of the */ - /* bounding box instead */ - if ( pxl < 0 ) - pxl = e1; - else if ( TRUNC( pxl ) >= ras.bWidth ) - pxl = e2; - - /* check that the other pixel isn't set */ - e1 = pxl == e1 ? e2 : e1; - - e1 = TRUNC( e1 ); - - c1 = (Short)( e1 >> 3 ); - f1 = (Short)( e1 & 7 ); - - if ( e1 >= 0 && e1 < ras.bWidth && - ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) ) - goto Exit; - } - else - goto Exit; - } - - e1 = TRUNC( pxl ); - - if ( e1 >= 0 && e1 < ras.bWidth ) - { - FT_TRACE7(( " -> x=%d (drop-out)", e1 )); - - c1 = (Short)( e1 >> 3 ); - f1 = (Short)( e1 & 7 ); - - ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 ); - } - - Exit: - FT_TRACE7(( "\n" )); - } - - - static void - Vertical_Sweep_Step( RAS_ARG ) - { - ras.traceOfs += ras.traceIncr; - } - - - /***********************************************************************/ - /* */ - /* Horizontal Sweep Procedure Set */ - /* */ - /* These four routines are used during the horizontal black/white */ - /* sweep phase by the generic Draw_Sweep() function. */ - /* */ - /***********************************************************************/ - - static void - Horizontal_Sweep_Init( RAS_ARGS Short* min, - Short* max ) - { - /* nothing, really */ - FT_UNUSED_RASTER; - FT_UNUSED( min ); - FT_UNUSED( max ); - } - - - static void - Horizontal_Sweep_Span( RAS_ARGS Short y, - FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) - { - FT_UNUSED( left ); - FT_UNUSED( right ); - - - if ( x2 - x1 < ras.precision ) - { - Long e1, e2; - - - FT_TRACE7(( " x=%d y=[%.12f;%.12f]", - y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); - - e1 = CEILING( x1 ); - e2 = FLOOR ( x2 ); - - if ( e1 == e2 ) - { - e1 = TRUNC( e1 ); - - if ( e1 >= 0 && (ULong)e1 < ras.target.rows ) - { - Byte f1; - PByte bits; - PByte p; - - - FT_TRACE7(( " -> y=%d (drop-out)", e1 )); - - bits = ras.bTarget + ( y >> 3 ); - f1 = (Byte)( 0x80 >> ( y & 7 ) ); - p = bits - e1 * ras.target.pitch; - - if ( ras.target.pitch > 0 ) - p += (Long)( ras.target.rows - 1 ) * ras.target.pitch; - - p[0] |= f1; - } - } - - FT_TRACE7(( "\n" )); - } - } - - - static void - Horizontal_Sweep_Drop( RAS_ARGS Short y, - FT_F26Dot6 x1, - FT_F26Dot6 x2, - PProfile left, - PProfile right ) - { - Long e1, e2, pxl; - PByte bits; - Byte f1; - - - FT_TRACE7(( " x=%d y=[%.12f;%.12f]", - y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); - - /* During the horizontal sweep, we only take care of drop-outs */ - - /* e1 + <-- pixel center */ - /* | */ - /* x1 ---+--> <-- contour */ - /* | */ - /* | */ - /* x2 <--+--- <-- contour */ - /* | */ - /* | */ - /* e2 + <-- pixel center */ - - e1 = CEILING( x1 ); - e2 = FLOOR ( x2 ); - pxl = e1; - - if ( e1 > e2 ) - { - Int dropOutControl = left->flags & 7; - - - FT_TRACE7(( ", dropout=%d", dropOutControl )); - - if ( e1 == e2 + ras.precision ) - { - switch ( dropOutControl ) - { - case 0: /* simple drop-outs including stubs */ - pxl = e2; - break; - - case 4: /* smart drop-outs including stubs */ - pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); - break; - - case 1: /* simple drop-outs excluding stubs */ - case 5: /* smart drop-outs excluding stubs */ - /* see Vertical_Sweep_Drop for details */ - - /* rightmost stub test */ - if ( left->next == right && - left->height <= 0 && - !( left->flags & Overshoot_Top && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - /* leftmost stub test */ - if ( right->next == left && - left->start == y && - !( left->flags & Overshoot_Bottom && - x2 - x1 >= ras.precision_half ) ) - goto Exit; - - if ( dropOutControl == 1 ) - pxl = e2; - else - pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); - break; - - default: /* modes 2, 3, 6, 7 */ - goto Exit; /* no drop-out control */ - } - - /* undocumented but confirmed: If the drop-out would result in a */ - /* pixel outside of the bounding box, use the pixel inside of the */ - /* bounding box instead */ - if ( pxl < 0 ) - pxl = e1; - else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows ) - pxl = e2; - - /* check that the other pixel isn't set */ - e1 = pxl == e1 ? e2 : e1; - - e1 = TRUNC( e1 ); - - bits = ras.bTarget + ( y >> 3 ); - f1 = (Byte)( 0x80 >> ( y & 7 ) ); - - bits -= e1 * ras.target.pitch; - if ( ras.target.pitch > 0 ) - bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch; - - if ( e1 >= 0 && - (ULong)e1 < ras.target.rows && - *bits & f1 ) - goto Exit; - } - else - goto Exit; - } - - e1 = TRUNC( pxl ); - - if ( e1 >= 0 && (ULong)e1 < ras.target.rows ) - { - FT_TRACE7(( " -> y=%d (drop-out)", e1 )); - - bits = ras.bTarget + ( y >> 3 ); - f1 = (Byte)( 0x80 >> ( y & 7 ) ); - bits -= e1 * ras.target.pitch; - - if ( ras.target.pitch > 0 ) - bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch; - - bits[0] |= f1; - } - - Exit: - FT_TRACE7(( "\n" )); - } - - - static void - Horizontal_Sweep_Step( RAS_ARG ) - { - /* Nothing, really */ - FT_UNUSED_RASTER; - } - - - /*************************************************************************/ - /* */ - /* Generic Sweep Drawing routine */ - /* */ - /*************************************************************************/ - - static Bool - Draw_Sweep( RAS_ARG ) - { - Short y, y_change, y_height; - - PProfile P, Q, P_Left, P_Right; - - Short min_Y, max_Y, top, bottom, dropouts; - - Long x1, x2, xs, e1, e2; - - TProfileList waiting; - TProfileList draw_left, draw_right; - - - /* initialize empty linked lists */ - - Init_Linked( &waiting ); - - Init_Linked( &draw_left ); - Init_Linked( &draw_right ); - - /* first, compute min and max Y */ - - P = ras.fProfile; - max_Y = (Short)TRUNC( ras.minY ); - min_Y = (Short)TRUNC( ras.maxY ); - - while ( P ) - { - Q = P->link; - - bottom = (Short)P->start; - top = (Short)( P->start + P->height - 1 ); - - if ( min_Y > bottom ) - min_Y = bottom; - if ( max_Y < top ) - max_Y = top; - - P->X = 0; - InsNew( &waiting, P ); - - P = Q; - } - - /* check the Y-turns */ - if ( ras.numTurns == 0 ) - { - ras.error = FT_THROW( Invalid ); - return FAILURE; - } - - /* now initialize the sweep */ - - ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y ); - - /* then compute the distance of each profile from min_Y */ - - P = waiting; - - while ( P ) - { - P->countL = P->start - min_Y; - P = P->link; - } - - /* let's go */ - - y = min_Y; - y_height = 0; - - if ( ras.numTurns > 0 && - ras.sizeBuff[-ras.numTurns] == min_Y ) - ras.numTurns--; - - while ( ras.numTurns > 0 ) - { - /* check waiting list for new activations */ - - P = waiting; - - while ( P ) - { - Q = P->link; - P->countL -= y_height; - if ( P->countL == 0 ) - { - DelOld( &waiting, P ); - - if ( P->flags & Flow_Up ) - InsNew( &draw_left, P ); - else - InsNew( &draw_right, P ); - } - - P = Q; - } - - /* sort the drawing lists */ - - Sort( &draw_left ); - Sort( &draw_right ); - - y_change = (Short)ras.sizeBuff[-ras.numTurns--]; - y_height = (Short)( y_change - y ); - - while ( y < y_change ) - { - /* let's trace */ - - dropouts = 0; - - P_Left = draw_left; - P_Right = draw_right; - - while ( P_Left ) - { - x1 = P_Left ->X; - x2 = P_Right->X; - - if ( x1 > x2 ) - { - xs = x1; - x1 = x2; - x2 = xs; - } - - e1 = FLOOR( x1 ); - e2 = CEILING( x2 ); - - if ( x2 - x1 <= ras.precision && - e1 != x1 && e2 != x2 ) - { - if ( e1 > e2 || e2 == e1 + ras.precision ) - { - Int dropOutControl = P_Left->flags & 7; - - - if ( dropOutControl != 2 ) - { - /* a drop-out was detected */ - - P_Left ->X = x1; - P_Right->X = x2; - - /* mark profile for drop-out processing */ - P_Left->countL = 1; - dropouts++; - } - - goto Skip_To_Next; - } - } - - ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right ); - - Skip_To_Next: - - P_Left = P_Left->link; - P_Right = P_Right->link; - } - - /* handle drop-outs _after_ the span drawing -- */ - /* drop-out processing has been moved out of the loop */ - /* for performance tuning */ - if ( dropouts > 0 ) - goto Scan_DropOuts; - - Next_Line: - - ras.Proc_Sweep_Step( RAS_VAR ); - - y++; - - if ( y < y_change ) - { - Sort( &draw_left ); - Sort( &draw_right ); - } - } - - /* now finalize the profiles that need it */ - - P = draw_left; - while ( P ) - { - Q = P->link; - if ( P->height == 0 ) - DelOld( &draw_left, P ); - P = Q; - } - - P = draw_right; - while ( P ) - { - Q = P->link; - if ( P->height == 0 ) - DelOld( &draw_right, P ); - P = Q; - } - } - - /* for gray-scaling, flush the bitmap scanline cache */ - while ( y <= max_Y ) - { - ras.Proc_Sweep_Step( RAS_VAR ); - y++; - } - - return SUCCESS; - - Scan_DropOuts: - - P_Left = draw_left; - P_Right = draw_right; - - while ( P_Left ) - { - if ( P_Left->countL ) - { - P_Left->countL = 0; -#if 0 - dropouts--; /* -- this is useful when debugging only */ -#endif - ras.Proc_Sweep_Drop( RAS_VARS y, - P_Left->X, - P_Right->X, - P_Left, - P_Right ); - } - - P_Left = P_Left->link; - P_Right = P_Right->link; - } - - goto Next_Line; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Render_Single_Pass */ - /* */ - /* <Description> */ - /* Perform one sweep with sub-banding. */ - /* */ - /* <Input> */ - /* flipped :: If set, flip the direction of the outline. */ - /* */ - /* <Return> */ - /* Renderer error code. */ - /* */ - static int - Render_Single_Pass( RAS_ARGS Bool flipped ) - { - Short i, j, k; - - - while ( ras.band_top >= 0 ) - { - ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision; - ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision; - - ras.top = ras.buff; - - ras.error = Raster_Err_None; - - if ( Convert_Glyph( RAS_VARS flipped ) ) - { - if ( ras.error != Raster_Err_Overflow ) - return FAILURE; - - ras.error = Raster_Err_None; - - /* sub-banding */ - -#ifdef DEBUG_RASTER - ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) ); -#endif - - i = ras.band_stack[ras.band_top].y_min; - j = ras.band_stack[ras.band_top].y_max; - - k = (Short)( ( i + j ) / 2 ); - - if ( ras.band_top >= 7 || k < i ) - { - ras.band_top = 0; - ras.error = FT_THROW( Invalid ); - - return ras.error; - } - - ras.band_stack[ras.band_top + 1].y_min = k; - ras.band_stack[ras.band_top + 1].y_max = j; - - ras.band_stack[ras.band_top].y_max = (Short)( k - 1 ); - - ras.band_top++; - } - else - { - if ( ras.fProfile ) - if ( Draw_Sweep( RAS_VAR ) ) - return ras.error; - ras.band_top--; - } - } - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Render_Glyph */ - /* */ - /* <Description> */ - /* Render a glyph in a bitmap. Sub-banding if needed. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - static FT_Error - Render_Glyph( RAS_ARG ) - { - FT_Error error; - - - Set_High_Precision( RAS_VARS ras.outline.flags & - FT_OUTLINE_HIGH_PRECISION ); - ras.scale_shift = ras.precision_shift; - - if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS ) - ras.dropOutControl = 2; - else - { - if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS ) - ras.dropOutControl = 4; - else - ras.dropOutControl = 0; - - if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) ) - ras.dropOutControl += 1; - } - - ras.second_pass = (Bool)( !( ras.outline.flags & - FT_OUTLINE_SINGLE_PASS ) ); - - /* Vertical Sweep */ - FT_TRACE7(( "Vertical pass (ftraster)\n" )); - - ras.Proc_Sweep_Init = Vertical_Sweep_Init; - ras.Proc_Sweep_Span = Vertical_Sweep_Span; - ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; - ras.Proc_Sweep_Step = Vertical_Sweep_Step; - - ras.band_top = 0; - ras.band_stack[0].y_min = 0; - ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 ); - - ras.bWidth = (UShort)ras.target.width; - ras.bTarget = (Byte*)ras.target.buffer; - - if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 ) - return error; - - /* Horizontal Sweep */ - if ( ras.second_pass && ras.dropOutControl != 2 ) - { - FT_TRACE7(( "Horizontal pass (ftraster)\n" )); - - ras.Proc_Sweep_Init = Horizontal_Sweep_Init; - ras.Proc_Sweep_Span = Horizontal_Sweep_Span; - ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop; - ras.Proc_Sweep_Step = Horizontal_Sweep_Step; - - ras.band_top = 0; - ras.band_stack[0].y_min = 0; - ras.band_stack[0].y_max = (Short)( ras.target.width - 1 ); - - if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 ) - return error; - } - - return Raster_Err_None; - } - - - static void - ft_black_init( black_PRaster raster ) - { - FT_UNUSED( raster ); - } - - - /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ - /**** a static object. *****/ - - -#ifdef _STANDALONE_ - - - static int - ft_black_new( void* memory, - FT_Raster *araster ) - { - static black_TRaster the_raster; - FT_UNUSED( memory ); - - - *araster = (FT_Raster)&the_raster; - FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); - ft_black_init( &the_raster ); - - return 0; - } - - - static void - ft_black_done( FT_Raster raster ) - { - /* nothing */ - FT_UNUSED( raster ); - } - - -#else /* !_STANDALONE_ */ - - - static int - ft_black_new( FT_Memory memory, - black_PRaster *araster ) - { - FT_Error error; - black_PRaster raster = NULL; - - - *araster = 0; - if ( !FT_NEW( raster ) ) - { - raster->memory = memory; - ft_black_init( raster ); - - *araster = raster; - } - - return error; - } - - - static void - ft_black_done( black_PRaster raster ) - { - FT_Memory memory = (FT_Memory)raster->memory; - - - FT_FREE( raster ); - } - - -#endif /* !_STANDALONE_ */ - - - static void - ft_black_reset( black_PRaster raster, - char* pool_base, - Long pool_size ) - { - FT_UNUSED( raster ); - FT_UNUSED( pool_base ); - FT_UNUSED( pool_size ); - } - - - static int - ft_black_set_mode( black_PRaster raster, - ULong mode, - const char* palette ) - { - FT_UNUSED( raster ); - FT_UNUSED( mode ); - FT_UNUSED( palette ); - - return 0; - } - - - static int - ft_black_render( black_PRaster raster, - const FT_Raster_Params* params ) - { - const FT_Outline* outline = (const FT_Outline*)params->source; - const FT_Bitmap* target_map = params->target; - - black_TWorker worker[1]; - - Long buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( Long )]; - - - if ( !raster ) - return FT_THROW( Not_Ini ); - - if ( !outline ) - return FT_THROW( Invalid ); - - /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) - return Raster_Err_None; - - if ( !outline->contours || !outline->points ) - return FT_THROW( Invalid ); - - if ( outline->n_points != - outline->contours[outline->n_contours - 1] + 1 ) - return FT_THROW( Invalid ); - - /* this version of the raster does not support direct rendering, sorry */ - if ( params->flags & FT_RASTER_FLAG_DIRECT ) - return FT_THROW( Unsupported ); - - if ( params->flags & FT_RASTER_FLAG_AA ) - return FT_THROW( Unsupported ); - - if ( !target_map ) - return FT_THROW( Invalid ); - - /* nothing to do */ - if ( !target_map->width || !target_map->rows ) - return Raster_Err_None; - - if ( !target_map->buffer ) - return FT_THROW( Invalid ); - - ras.outline = *outline; - ras.target = *target_map; - - worker->buff = buffer; - worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */ - - return Render_Glyph( RAS_VAR ); - } - - - FT_DEFINE_RASTER_FUNCS( - ft_standard_raster, - - FT_GLYPH_FORMAT_OUTLINE, - - (FT_Raster_New_Func) ft_black_new, - (FT_Raster_Reset_Func) ft_black_reset, - (FT_Raster_Set_Mode_Func)ft_black_set_mode, - (FT_Raster_Render_Func) ft_black_render, - (FT_Raster_Done_Func) ft_black_done ) - - -/* END */ diff --git a/third_party/freetype/src/raster/ftraster.h b/third_party/freetype/src/raster/ftraster.h deleted file mode 100644 index a270d487b9376315390e9f72152772f1d263ac63..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/ftraster.h +++ /dev/null @@ -1,46 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftraster.h */ -/* */ -/* The FreeType glyph rasterizer (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used */ -/* modified and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTRASTER_H__ -#define __FTRASTER_H__ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_IMAGE_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* Uncomment the following line if you are using ftraster.c as a */ - /* standalone module, fully independent of FreeType. */ - /* */ -/* #define _STANDALONE_ */ - - FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_standard_raster; - - -FT_END_HEADER - -#endif /* __FTRASTER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/raster/ftrend1.c b/third_party/freetype/src/raster/ftrend1.c deleted file mode 100644 index f3143928399e8090c082eb0d08985e4a858ab00c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/ftrend1.c +++ /dev/null @@ -1,254 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftrend1.c */ -/* */ -/* The FreeType glyph rasterizer interface (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_OUTLINE_H -#include "ftrend1.h" -#include "ftraster.h" -#include "rastpic.h" - -#include "rasterrs.h" - - - /* initialize renderer -- init its raster */ - static FT_Error - ft_raster1_init( FT_Renderer render ) - { - FT_Library library = FT_MODULE_LIBRARY( render ); - - - render->clazz->raster_class->raster_reset( render->raster, - library->raster_pool, - library->raster_pool_size ); - - return FT_Err_Ok; - } - - - /* set render-specific mode */ - static FT_Error - ft_raster1_set_mode( FT_Renderer render, - FT_ULong mode_tag, - FT_Pointer data ) - { - /* we simply pass it to the raster */ - return render->clazz->raster_class->raster_set_mode( render->raster, - mode_tag, - data ); - } - - - /* transform a given glyph image */ - static FT_Error - ft_raster1_transform( FT_Renderer render, - FT_GlyphSlot slot, - const FT_Matrix* matrix, - const FT_Vector* delta ) - { - FT_Error error = FT_Err_Ok; - - - if ( slot->format != render->glyph_format ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( matrix ) - FT_Outline_Transform( &slot->outline, matrix ); - - if ( delta ) - FT_Outline_Translate( &slot->outline, delta->x, delta->y ); - - Exit: - return error; - } - - - /* return the glyph's control box */ - static void - ft_raster1_get_cbox( FT_Renderer render, - FT_GlyphSlot slot, - FT_BBox* cbox ) - { - FT_MEM_ZERO( cbox, sizeof ( *cbox ) ); - - if ( slot->format == render->glyph_format ) - FT_Outline_Get_CBox( &slot->outline, cbox ); - } - - - /* convert a slot's glyph image into a bitmap */ - static FT_Error - ft_raster1_render( FT_Renderer render, - FT_GlyphSlot slot, - FT_Render_Mode mode, - const FT_Vector* origin ) - { - FT_Error error; - FT_Outline* outline; - FT_BBox cbox, cbox0; - FT_UInt width, height, pitch; - FT_Bitmap* bitmap; - FT_Memory memory; - - FT_Raster_Params params; - - - /* check glyph image format */ - if ( slot->format != render->glyph_format ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - /* check rendering mode */ - if ( mode != FT_RENDER_MODE_MONO ) - { - /* raster1 is only capable of producing monochrome bitmaps */ - return FT_THROW( Cannot_Render_Glyph ); - } - - outline = &slot->outline; - - /* translate the outline to the new origin if needed */ - if ( origin ) - FT_Outline_Translate( outline, origin->x, origin->y ); - - /* compute the control box, and grid fit it */ - FT_Outline_Get_CBox( outline, &cbox0 ); - - /* undocumented but confirmed: bbox values get rounded */ -#if 1 - cbox.xMin = FT_PIX_ROUND( cbox0.xMin ); - cbox.yMin = FT_PIX_ROUND( cbox0.yMin ); - cbox.xMax = FT_PIX_ROUND( cbox0.xMax ); - cbox.yMax = FT_PIX_ROUND( cbox0.yMax ); -#else - cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); - cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); - cbox.xMax = FT_PIX_CEIL( cbox.xMax ); - cbox.yMax = FT_PIX_CEIL( cbox.yMax ); -#endif - - /* If either `width' or `height' round to 0, try */ - /* explicitly rounding up/down. In the case of */ - /* glyphs containing only one very narrow feature, */ - /* this gives the drop-out compensation in the scan */ - /* conversion code a chance to do its stuff. */ - width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 ); - if ( width == 0 ) - { - cbox.xMin = FT_PIX_FLOOR( cbox0.xMin ); - cbox.xMax = FT_PIX_CEIL( cbox0.xMax ); - - width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 ); - } - - height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 ); - if ( height == 0 ) - { - cbox.yMin = FT_PIX_FLOOR( cbox0.yMin ); - cbox.yMax = FT_PIX_CEIL( cbox0.yMax ); - - height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 ); - } - - if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - bitmap = &slot->bitmap; - memory = render->root.memory; - - /* release old bitmap buffer */ - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { - FT_FREE( bitmap->buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - - pitch = ( ( width + 15 ) >> 4 ) << 1; - bitmap->pixel_mode = FT_PIXEL_MODE_MONO; - - bitmap->width = width; - bitmap->rows = height; - bitmap->pitch = (int)pitch; - - if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) ) - goto Exit; - - slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - - /* translate outline to render it into the bitmap */ - FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); - - /* set up parameters */ - params.target = bitmap; - params.source = outline; - params.flags = 0; - - /* render outline into the bitmap */ - error = render->raster_render( render->raster, ¶ms ); - - FT_Outline_Translate( outline, cbox.xMin, cbox.yMin ); - - if ( error ) - goto Exit; - - slot->format = FT_GLYPH_FORMAT_BITMAP; - slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 ); - slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 ); - - Exit: - return error; - } - - - FT_DEFINE_RENDERER( ft_raster1_renderer_class, - - FT_MODULE_RENDERER, - sizeof ( FT_RendererRec ), - - "raster1", - 0x10000L, - 0x20000L, - - 0, /* module specific interface */ - - (FT_Module_Constructor)ft_raster1_init, - (FT_Module_Destructor) 0, - (FT_Module_Requester) 0 - , - - FT_GLYPH_FORMAT_OUTLINE, - - (FT_Renderer_RenderFunc) ft_raster1_render, - (FT_Renderer_TransformFunc)ft_raster1_transform, - (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, - (FT_Renderer_SetModeFunc) ft_raster1_set_mode, - - (FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET - ) - - -/* END */ diff --git a/third_party/freetype/src/raster/ftrend1.h b/third_party/freetype/src/raster/ftrend1.h deleted file mode 100644 index edc5d13f4cd3f89b65fc74170c299e453c3bd860..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/ftrend1.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftrend1.h */ -/* */ -/* The FreeType glyph rasterizer interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTREND1_H__ -#define __FTREND1_H__ - - -#include <ft2build.h> -#include FT_RENDER_H - - -FT_BEGIN_HEADER - - - FT_DECLARE_RENDERER( ft_raster1_renderer_class ) - - -FT_END_HEADER - -#endif /* __FTREND1_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/raster/raster.c b/third_party/freetype/src/raster/raster.c deleted file mode 100644 index 21bb16de1e528c288312d779b2e514f30efc794c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/raster.c +++ /dev/null @@ -1,27 +0,0 @@ -/***************************************************************************/ -/* */ -/* raster.c */ -/* */ -/* FreeType monochrome rasterer module component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "rastpic.c" -#include "ftraster.c" -#include "ftrend1.c" - - -/* END */ diff --git a/third_party/freetype/src/raster/rasterrs.h b/third_party/freetype/src/raster/rasterrs.h deleted file mode 100644 index e7f00bcace3c92c31c83f465128c338ea3794f7c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/rasterrs.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* rasterrs.h */ -/* */ -/* monochrome renderer error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the monochrome renderer error enumeration */ - /* constants. */ - /* */ - /*************************************************************************/ - -#ifndef __RASTERRS_H__ -#define __RASTERRS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX Raster_Err_ -#define FT_ERR_BASE FT_Mod_Err_Raster - -#include FT_ERRORS_H - -#endif /* __RASTERRS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/raster/rastpic.c b/third_party/freetype/src/raster/rastpic.c deleted file mode 100644 index 77e7ec3f9035797c86c28124bb33d4c41d87e3ce..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/rastpic.c +++ /dev/null @@ -1,89 +0,0 @@ -/***************************************************************************/ -/* */ -/* rastpic.c */ -/* */ -/* The FreeType position independent code services for raster module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "rastpic.h" -#include "rasterrs.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from ftraster.c */ - void - FT_Init_Class_ft_standard_raster( FT_Raster_Funcs* funcs ); - - - void - ft_raster1_renderer_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->raster ) - { - RasterPIC* container = (RasterPIC*)pic_container->raster; - - - if ( --container->ref_count ) - return; - FT_FREE( container ); - pic_container->raster = NULL; - } - } - - - FT_Error - ft_raster1_renderer_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - RasterPIC* container = NULL; - FT_Memory memory = library->memory; - - - /* XXX: since this function also served the no longer available */ - /* raster5 renderer it uses reference counting, which could */ - /* be removed now */ - if ( pic_container->raster ) - { - ((RasterPIC*)pic_container->raster)->ref_count++; - return error; - } - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->raster = container; - - container->ref_count = 1; - - /* initialize pointer table - */ - /* this is how the module usually expects this data */ - FT_Init_Class_ft_standard_raster( &container->ft_standard_raster ); - - return error; - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/raster/rastpic.h b/third_party/freetype/src/raster/rastpic.h deleted file mode 100644 index 408996a908989f6871bf501f423a45d887434ff1..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/raster/rastpic.h +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************/ -/* */ -/* rastpic.h */ -/* */ -/* The FreeType position independent code services for raster module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __RASTPIC_H__ -#define __RASTPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -FT_BEGIN_HEADER - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_STANDARD_RASTER_GET ft_standard_raster - -#else /* FT_CONFIG_OPTION_PIC */ - - typedef struct RasterPIC_ - { - int ref_count; - FT_Raster_Funcs ft_standard_raster; - - } RasterPIC; - - -#define GET_PIC( lib ) \ - ( (RasterPIC*)( (lib)->pic_container.raster ) ) -#define FT_STANDARD_RASTER_GET ( GET_PIC( library )->ft_standard_raster ) - - - /* see rastpic.c for the implementation */ - void - ft_raster1_renderer_class_pic_free( FT_Library library ); - - FT_Error - ft_raster1_renderer_class_pic_init( FT_Library library ); - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -FT_END_HEADER - -#endif /* __RASTPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/Jamfile b/third_party/freetype/src/sfnt/Jamfile deleted file mode 100644 index cc98d1011ea4522cd71d0b52d58b2bb85b08c98d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/Jamfile +++ /dev/null @@ -1,40 +0,0 @@ -# FreeType 2 src/sfnt Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) sfnt ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = pngshim - sfdriver - sfntpic - sfobjs - ttbdf - ttcmap - ttkern - ttload - ttmtx - ttpost - ttsbit - ; - } - else - { - _sources = sfnt ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/sfnt Jamfile diff --git a/third_party/freetype/src/sfnt/pngshim.c b/third_party/freetype/src/sfnt/pngshim.c deleted file mode 100644 index ea60452635a34c58d71c20bdec182fd4c1cc573b..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/pngshim.c +++ /dev/null @@ -1,378 +0,0 @@ -/***************************************************************************/ -/* */ -/* pngshim.c */ -/* */ -/* PNG Bitmap glyph support. */ -/* */ -/* Copyright 2013-2015 by */ -/* Google, Inc. */ -/* Written by Stuart Gill and Behdad Esfahbod. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include FT_CONFIG_STANDARD_LIBRARY_H - - -#ifdef FT_CONFIG_OPTION_USE_PNG - - /* We always include <stjmp.h>, so make libpng shut up! */ -#define PNG_SKIP_SETJMP_CHECK 1 -#include <png.h> -#include "pngshim.h" - -#include "sferrors.h" - - - /* This code is freely based on cairo-png.c. There's so many ways */ - /* to call libpng, and the way cairo does it is defacto standard. */ - - static unsigned int - multiply_alpha( unsigned int alpha, - unsigned int color ) - { - unsigned int temp = alpha * color + 0x80; - - - return ( temp + ( temp >> 8 ) ) >> 8; - } - - - /* Premultiplies data and converts RGBA bytes => native endian. */ - static void - premultiply_data( png_structp png, - png_row_infop row_info, - png_bytep data ) - { - unsigned int i; - - FT_UNUSED( png ); - - - for ( i = 0; i < row_info->rowbytes; i += 4 ) - { - unsigned char* base = &data[i]; - unsigned int alpha = base[3]; - - - if ( alpha == 0 ) - base[0] = base[1] = base[2] = base[3] = 0; - - else - { - unsigned int red = base[0]; - unsigned int green = base[1]; - unsigned int blue = base[2]; - - - if ( alpha != 0xFF ) - { - red = multiply_alpha( alpha, red ); - green = multiply_alpha( alpha, green ); - blue = multiply_alpha( alpha, blue ); - } - - base[0] = (unsigned char)blue; - base[1] = (unsigned char)green; - base[2] = (unsigned char)red; - base[3] = (unsigned char)alpha; - } - } - } - - - /* Converts RGBx bytes to BGRA. */ - static void - convert_bytes_to_data( png_structp png, - png_row_infop row_info, - png_bytep data ) - { - unsigned int i; - - FT_UNUSED( png ); - - - for ( i = 0; i < row_info->rowbytes; i += 4 ) - { - unsigned char* base = &data[i]; - unsigned int red = base[0]; - unsigned int green = base[1]; - unsigned int blue = base[2]; - - - base[0] = (unsigned char)blue; - base[1] = (unsigned char)green; - base[2] = (unsigned char)red; - base[3] = 0xFF; - } - } - - - /* Use error callback to avoid png writing to stderr. */ - static void - error_callback( png_structp png, - png_const_charp error_msg ) - { - FT_Error* error = (FT_Error*)png_get_error_ptr( png ); - - FT_UNUSED( error_msg ); - - - *error = FT_THROW( Out_Of_Memory ); -#ifdef PNG_SETJMP_SUPPORTED - ft_longjmp( png_jmpbuf( png ), 1 ); -#endif - /* if we get here, then we have no choice but to abort ... */ - } - - - /* Use warning callback to avoid png writing to stderr. */ - static void - warning_callback( png_structp png, - png_const_charp error_msg ) - { - FT_UNUSED( png ); - FT_UNUSED( error_msg ); - - /* Just ignore warnings. */ - } - - - static void - read_data_from_FT_Stream( png_structp png, - png_bytep data, - png_size_t length ) - { - FT_Error error; - png_voidp p = png_get_io_ptr( png ); - FT_Stream stream = (FT_Stream)p; - - - if ( FT_FRAME_ENTER( length ) ) - { - FT_Error* e = (FT_Error*)png_get_error_ptr( png ); - - - *e = FT_THROW( Invalid_Stream_Read ); - png_error( png, NULL ); - - return; - } - - memcpy( data, stream->cursor, length ); - - FT_FRAME_EXIT(); - } - - - FT_LOCAL_DEF( FT_Error ) - Load_SBit_Png( FT_GlyphSlot slot, - FT_Int x_offset, - FT_Int y_offset, - FT_Int pix_bits, - TT_SBit_Metrics metrics, - FT_Memory memory, - FT_Byte* data, - FT_UInt png_len, - FT_Bool populate_map_and_metrics ) - { - FT_Bitmap *map = &slot->bitmap; - FT_Error error = FT_Err_Ok; - FT_StreamRec stream; - - png_structp png; - png_infop info; - png_uint_32 imgWidth, imgHeight; - - int bitdepth, color_type, interlace; - FT_Int i; - png_byte* *rows = NULL; /* pacify compiler */ - - - if ( x_offset < 0 || - y_offset < 0 ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( !populate_map_and_metrics && - ( (FT_UInt)x_offset + metrics->width > map->width || - (FT_UInt)y_offset + metrics->height > map->rows || - pix_bits != 32 || - map->pixel_mode != FT_PIXEL_MODE_BGRA ) ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - FT_Stream_OpenMemory( &stream, data, png_len ); - - png = png_create_read_struct( PNG_LIBPNG_VER_STRING, - &error, - error_callback, - warning_callback ); - if ( !png ) - { - error = FT_THROW( Out_Of_Memory ); - goto Exit; - } - - info = png_create_info_struct( png ); - if ( !info ) - { - error = FT_THROW( Out_Of_Memory ); - png_destroy_read_struct( &png, NULL, NULL ); - goto Exit; - } - - if ( ft_setjmp( png_jmpbuf( png ) ) ) - { - error = FT_THROW( Invalid_File_Format ); - goto DestroyExit; - } - - png_set_read_fn( png, &stream, read_data_from_FT_Stream ); - - png_read_info( png, info ); - png_get_IHDR( png, info, - &imgWidth, &imgHeight, - &bitdepth, &color_type, &interlace, - NULL, NULL ); - - if ( error || - ( !populate_map_and_metrics && - ( (FT_Int)imgWidth != metrics->width || - (FT_Int)imgHeight != metrics->height ) ) ) - goto DestroyExit; - - if ( populate_map_and_metrics ) - { - FT_ULong size; - - - metrics->width = (FT_UShort)imgWidth; - metrics->height = (FT_UShort)imgHeight; - - map->width = metrics->width; - map->rows = metrics->height; - map->pixel_mode = FT_PIXEL_MODE_BGRA; - map->pitch = (int)( map->width * 4 ); - map->num_grays = 256; - - /* reject too large bitmaps similarly to the rasterizer */ - if ( map->rows > 0x7FFF || map->width > 0x7FFF ) - { - error = FT_THROW( Array_Too_Large ); - goto DestroyExit; - } - - /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */ - size = map->rows * (FT_ULong)map->pitch; - - error = ft_glyphslot_alloc_bitmap( slot, size ); - if ( error ) - goto DestroyExit; - } - - /* convert palette/gray image to rgb */ - if ( color_type == PNG_COLOR_TYPE_PALETTE ) - png_set_palette_to_rgb( png ); - - /* expand gray bit depth if needed */ - if ( color_type == PNG_COLOR_TYPE_GRAY ) - { -#if PNG_LIBPNG_VER >= 10209 - png_set_expand_gray_1_2_4_to_8( png ); -#else - png_set_gray_1_2_4_to_8( png ); -#endif - } - - /* transform transparency to alpha */ - if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) - png_set_tRNS_to_alpha( png ); - - if ( bitdepth == 16 ) - png_set_strip_16( png ); - - if ( bitdepth < 8 ) - png_set_packing( png ); - - /* convert grayscale to RGB */ - if ( color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) - png_set_gray_to_rgb( png ); - - if ( interlace != PNG_INTERLACE_NONE ) - png_set_interlace_handling( png ); - - png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); - - /* recheck header after setting EXPAND options */ - png_read_update_info(png, info ); - png_get_IHDR( png, info, - &imgWidth, &imgHeight, - &bitdepth, &color_type, &interlace, - NULL, NULL ); - - if ( bitdepth != 8 || - !( color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA ) ) - { - error = FT_THROW( Invalid_File_Format ); - goto DestroyExit; - } - - switch ( color_type ) - { - default: - /* Shouldn't happen, but fall through. */ - - case PNG_COLOR_TYPE_RGB_ALPHA: - png_set_read_user_transform_fn( png, premultiply_data ); - break; - - case PNG_COLOR_TYPE_RGB: - /* Humm, this smells. Carry on though. */ - png_set_read_user_transform_fn( png, convert_bytes_to_data ); - break; - } - - if ( FT_NEW_ARRAY( rows, imgHeight ) ) - { - error = FT_THROW( Out_Of_Memory ); - goto DestroyExit; - } - - for ( i = 0; i < (FT_Int)imgHeight; i++ ) - rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4; - - png_read_image( png, rows ); - - FT_FREE( rows ); - - png_read_end( png, info ); - - DestroyExit: - png_destroy_read_struct( &png, &info, NULL ); - FT_Stream_Close( &stream ); - - Exit: - return error; - } - -#endif /* FT_CONFIG_OPTION_USE_PNG */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/pngshim.h b/third_party/freetype/src/sfnt/pngshim.h deleted file mode 100644 index 4cc5c2b3a058f8f4f468246a091cff3fa920d22d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/pngshim.h +++ /dev/null @@ -1,50 +0,0 @@ -/***************************************************************************/ -/* */ -/* pngshim.h */ -/* */ -/* PNG Bitmap glyph support. */ -/* */ -/* Copyright 2013-2015 by */ -/* Google, Inc. */ -/* Written by Stuart Gill and Behdad Esfahbod. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __PNGSHIM_H__ -#define __PNGSHIM_H__ - - -#include <ft2build.h> -#include "ttload.h" - - -FT_BEGIN_HEADER - -#ifdef FT_CONFIG_OPTION_USE_PNG - - FT_LOCAL( FT_Error ) - Load_SBit_Png( FT_GlyphSlot slot, - FT_Int x_offset, - FT_Int y_offset, - FT_Int pix_bits, - TT_SBit_Metrics metrics, - FT_Memory memory, - FT_Byte* data, - FT_UInt png_len, - FT_Bool populate_map_and_metrics ); - -#endif - -FT_END_HEADER - -#endif /* __PNGSHIM_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfdriver.c b/third_party/freetype/src/sfnt/sfdriver.c deleted file mode 100644 index 6a3f0d993334b801052774a72f5cbe1966797611..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfdriver.c +++ /dev/null @@ -1,531 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfdriver.c */ -/* */ -/* High-level SFNT driver interface (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_SFNT_H -#include FT_INTERNAL_OBJECTS_H - -#include "sfdriver.h" -#include "ttload.h" -#include "sfobjs.h" -#include "sfntpic.h" - -#include "sferrors.h" - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#include "ttsbit.h" -#endif - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES -#include "ttpost.h" -#endif - -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.h" -#include FT_SERVICE_BDF_H -#endif - -#include "ttcmap.h" -#include "ttkern.h" -#include "ttmtx.h" - -#include FT_SERVICE_GLYPH_DICT_H -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_SFNT_H -#include FT_SERVICE_TT_CMAP_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_sfdriver - - - /* - * SFNT TABLE SERVICE - * - */ - - static void* - get_sfnt_table( TT_Face face, - FT_Sfnt_Tag tag ) - { - void* table; - - - switch ( tag ) - { - case FT_SFNT_HEAD: - table = &face->header; - break; - - case FT_SFNT_HHEA: - table = &face->horizontal; - break; - - case FT_SFNT_VHEA: - table = face->vertical_info ? &face->vertical : NULL; - break; - - case FT_SFNT_OS2: - table = face->os2.version == 0xFFFFU ? NULL : &face->os2; - break; - - case FT_SFNT_POST: - table = &face->postscript; - break; - - case FT_SFNT_MAXP: - table = &face->max_profile; - break; - - case FT_SFNT_PCLT: - table = face->pclt.Version ? &face->pclt : NULL; - break; - - default: - table = NULL; - } - - return table; - } - - - static FT_Error - sfnt_table_info( TT_Face face, - FT_UInt idx, - FT_ULong *tag, - FT_ULong *offset, - FT_ULong *length ) - { - if ( !offset || !length ) - return FT_THROW( Invalid_Argument ); - - if ( !tag ) - *length = face->num_tables; - else - { - if ( idx >= face->num_tables ) - return FT_THROW( Table_Missing ); - - *tag = face->dir_tables[idx].Tag; - *offset = face->dir_tables[idx].Offset; - *length = face->dir_tables[idx].Length; - } - - return FT_Err_Ok; - } - - - FT_DEFINE_SERVICE_SFNT_TABLEREC( - sfnt_service_sfnt_table, - (FT_SFNT_TableLoadFunc)tt_face_load_any, - (FT_SFNT_TableGetFunc) get_sfnt_table, - (FT_SFNT_TableInfoFunc)sfnt_table_info ) - - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES - - /* - * GLYPH DICT SERVICE - * - */ - - static FT_Error - sfnt_get_glyph_name( TT_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ) - { - FT_String* gname; - FT_Error error; - - - error = tt_face_get_ps_name( face, glyph_index, &gname ); - if ( !error ) - FT_STRCPYN( buffer, gname, buffer_max ); - - return error; - } - - - static FT_UInt - sfnt_get_name_index( TT_Face face, - FT_String* glyph_name ) - { - FT_Face root = &face->root; - - FT_UInt i, max_gid = FT_UINT_MAX; - - - if ( root->num_glyphs < 0 ) - return 0; - else if ( (FT_ULong)root->num_glyphs < FT_UINT_MAX ) - max_gid = (FT_UInt)root->num_glyphs; - else - FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n", - FT_UINT_MAX, root->num_glyphs )); - - for ( i = 0; i < max_gid; i++ ) - { - FT_String* gname; - FT_Error error = tt_face_get_ps_name( face, i, &gname ); - - - if ( error ) - continue; - - if ( !ft_strcmp( glyph_name, gname ) ) - return i; - } - - return 0; - } - - - FT_DEFINE_SERVICE_GLYPHDICTREC( - sfnt_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, - (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index ) - - -#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ - - - /* - * POSTSCRIPT NAME SERVICE - * - */ - - static const char* - sfnt_get_ps_name( TT_Face face ) - { - FT_Int n, found_win, found_apple; - const char* result = NULL; - - - /* shouldn't happen, but just in case to avoid memory leaks */ - if ( face->postscript_name ) - return face->postscript_name; - - /* scan the name table to see whether we have a Postscript name here, */ - /* either in Macintosh or Windows platform encodings */ - found_win = -1; - found_apple = -1; - - for ( n = 0; n < face->num_names; n++ ) - { - TT_NameEntryRec* name = face->name_table.names + n; - - - if ( name->nameID == 6 && name->stringLength > 0 ) - { - if ( name->platformID == 3 && - name->encodingID == 1 && - name->languageID == 0x409 ) - found_win = n; - - if ( name->platformID == 1 && - name->encodingID == 0 && - name->languageID == 0 ) - found_apple = n; - } - } - - if ( found_win != -1 ) - { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_win; - FT_UInt len = name->stringLength / 2; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); - - - if ( !FT_ALLOC( result, name->stringLength + 1 ) ) - { - FT_Stream stream = face->name_table.stream; - FT_String* r = (FT_String*)result; - FT_Char* p; - - - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_FRAME_ENTER( name->stringLength ) ) - { - FT_FREE( result ); - name->stringLength = 0; - name->stringOffset = 0; - FT_FREE( name->string ); - - goto Exit; - } - - p = (FT_Char*)stream->cursor; - - for ( ; len > 0; len--, p += 2 ) - { - if ( p[0] == 0 && p[1] >= 32 ) - *r++ = p[1]; - } - *r = '\0'; - - FT_FRAME_EXIT(); - } - goto Exit; - } - - if ( found_apple != -1 ) - { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_apple; - FT_UInt len = name->stringLength; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); - - - if ( !FT_ALLOC( result, len + 1 ) ) - { - FT_Stream stream = face->name_table.stream; - - - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_STREAM_READ( result, len ) ) - { - name->stringOffset = 0; - name->stringLength = 0; - FT_FREE( name->string ); - FT_FREE( result ); - goto Exit; - } - ((char*)result)[len] = '\0'; - } - } - - Exit: - face->postscript_name = result; - return result; - } - - - FT_DEFINE_SERVICE_PSFONTNAMEREC( - sfnt_service_ps_name, - (FT_PsName_GetFunc)sfnt_get_ps_name ) - - - /* - * TT CMAP INFO - */ - FT_DEFINE_SERVICE_TTCMAPSREC( - tt_service_get_cmap_info, - (TT_CMap_Info_GetFunc)tt_get_cmap_info ) - - -#ifdef TT_CONFIG_OPTION_BDF - - static FT_Error - sfnt_get_charset_id( TT_Face face, - const char* *acharset_encoding, - const char* *acharset_registry ) - { - BDF_PropertyRec encoding, registry; - FT_Error error; - - - /* XXX: I don't know whether this is correct, since - * tt_face_find_bdf_prop only returns something correct if we have - * previously selected a size that is listed in the BDF table. - * Should we change the BDF table format to include single offsets - * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'? - */ - error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); - if ( !error ) - { - error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding ); - if ( !error ) - { - if ( registry.type == BDF_PROPERTY_TYPE_ATOM && - encoding.type == BDF_PROPERTY_TYPE_ATOM ) - { - *acharset_encoding = encoding.u.atom; - *acharset_registry = registry.u.atom; - } - else - error = FT_THROW( Invalid_Argument ); - } - } - - return error; - } - - - FT_DEFINE_SERVICE_BDFRec( - sfnt_service_bdf, - (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, - (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop ) - - -#endif /* TT_CONFIG_OPTION_BDF */ - - - /* - * SERVICE LIST - */ - -#if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF - FT_DEFINE_SERVICEDESCREC5( - sfnt_services, - FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, - FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET, - FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET, - FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) -#elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES - FT_DEFINE_SERVICEDESCREC4( - sfnt_services, - FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, - FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET, - FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) -#elif defined TT_CONFIG_OPTION_BDF - FT_DEFINE_SERVICEDESCREC4( - sfnt_services, - FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, - FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET, - FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) -#else - FT_DEFINE_SERVICEDESCREC3( - sfnt_services, - FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, - FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) -#endif - - - FT_CALLBACK_DEF( FT_Module_Interface ) - sfnt_get_interface( FT_Module module, - const char* module_interface ) - { - /* SFNT_SERVICES_GET dereferences `library' in PIC mode */ -#ifdef FT_CONFIG_OPTION_PIC - FT_Library library; - - - if ( !module ) - return NULL; - library = module->library; - if ( !library ) - return NULL; -#else - FT_UNUSED( module ); -#endif - - return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface ); - } - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#define PUT_EMBEDDED_BITMAPS( a ) a -#else -#define PUT_EMBEDDED_BITMAPS( a ) NULL -#endif - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES -#define PUT_PS_NAMES( a ) a -#else -#define PUT_PS_NAMES( a ) NULL -#endif - - FT_DEFINE_SFNT_INTERFACE( - sfnt_interface, - tt_face_goto_table, - - sfnt_init_face, - sfnt_load_face, - sfnt_done_face, - sfnt_get_interface, - - tt_face_load_any, - - tt_face_load_head, - tt_face_load_hhea, - tt_face_load_cmap, - tt_face_load_maxp, - tt_face_load_os2, - tt_face_load_post, - - tt_face_load_name, - tt_face_free_name, - - tt_face_load_kern, - tt_face_load_gasp, - tt_face_load_pclt, - - /* see `ttload.h' */ - PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ), - - PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ), - - /* see `ttpost.h' */ - PUT_PS_NAMES( tt_face_get_ps_name ), - PUT_PS_NAMES( tt_face_free_ps_names ), - - /* since version 2.1.8 */ - tt_face_get_kerning, - - /* since version 2.2 */ - tt_face_load_font_dir, - tt_face_load_hmtx, - - /* see `ttsbit.h' and `sfnt.h' */ - PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ), - PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ), - - PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ), - PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), - - tt_face_get_metrics, - - tt_face_get_name - ) - - - FT_DEFINE_MODULE( - sfnt_module_class, - - 0, /* not a font driver or renderer */ - sizeof ( FT_ModuleRec ), - - "sfnt", /* driver name */ - 0x10000L, /* driver version 1.0 */ - 0x20000L, /* driver requires FreeType 2.0 or higher */ - - (const void*)&SFNT_INTERFACE_GET, /* module specific interface */ - - (FT_Module_Constructor)0, - (FT_Module_Destructor) 0, - (FT_Module_Requester) sfnt_get_interface ) - - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfdriver.h b/third_party/freetype/src/sfnt/sfdriver.h deleted file mode 100644 index 944119cc2285fc9268d6a9743df58051468bab03..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfdriver.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfdriver.h */ -/* */ -/* High-level SFNT driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SFDRIVER_H__ -#define __SFDRIVER_H__ - - -#include <ft2build.h> -#include FT_MODULE_H - - -FT_BEGIN_HEADER - - - FT_DECLARE_MODULE( sfnt_module_class ) - - -FT_END_HEADER - -#endif /* __SFDRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/sferrors.h b/third_party/freetype/src/sfnt/sferrors.h deleted file mode 100644 index e3bef3f743bf8505a477fc91a326e9f1aed66e23..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sferrors.h +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************/ -/* */ -/* sferrors.h */ -/* */ -/* SFNT error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the SFNT error enumeration constants. */ - /* */ - /*************************************************************************/ - -#ifndef __SFERRORS_H__ -#define __SFERRORS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX SFNT_Err_ -#define FT_ERR_BASE FT_Mod_Err_SFNT - -#include FT_ERRORS_H - -#endif /* __SFERRORS_H__ */ - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfnt.c b/third_party/freetype/src/sfnt/sfnt.c deleted file mode 100644 index 0b8b5f4578546db58e8f36d95d70421fa4a9f705..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfnt.c +++ /dev/null @@ -1,43 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfnt.c */ -/* */ -/* Single object library component. */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "sfntpic.c" -#include "ttload.c" -#include "ttmtx.c" -#include "ttcmap.c" -#include "ttkern.c" -#include "sfobjs.c" -#include "sfdriver.c" - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#include "pngshim.c" -#include "ttsbit.c" -#endif - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES -#include "ttpost.c" -#endif - -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.c" -#endif - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfntpic.c b/third_party/freetype/src/sfnt/sfntpic.c deleted file mode 100644 index 2aaf4bcc40aa7e241293db4f630d04e3cc7ecf39..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfntpic.c +++ /dev/null @@ -1,143 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfntpic.c */ -/* */ -/* The FreeType position independent code services for sfnt module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "sfntpic.h" -#include "sferrors.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from sfdriver.c */ - FT_Error - FT_Create_Class_sfnt_services( FT_Library library, - FT_ServiceDescRec** output_class ); - void - FT_Destroy_Class_sfnt_services( FT_Library library, - FT_ServiceDescRec* clazz ); - void - FT_Init_Class_sfnt_service_bdf( FT_Service_BDFRec* clazz ); - void - FT_Init_Class_sfnt_interface( FT_Library library, - SFNT_Interface* clazz ); - void - FT_Init_Class_sfnt_service_glyph_dict( - FT_Library library, - FT_Service_GlyphDictRec* clazz ); - void - FT_Init_Class_sfnt_service_ps_name( - FT_Library library, - FT_Service_PsFontNameRec* clazz ); - void - FT_Init_Class_tt_service_get_cmap_info( - FT_Library library, - FT_Service_TTCMapsRec* clazz ); - void - FT_Init_Class_sfnt_service_sfnt_table( - FT_Service_SFNT_TableRec* clazz ); - - - /* forward declaration of PIC init functions from ttcmap.c */ - FT_Error - FT_Create_Class_tt_cmap_classes( FT_Library library, - TT_CMap_Class** output_class ); - void - FT_Destroy_Class_tt_cmap_classes( FT_Library library, - TT_CMap_Class* clazz ); - - - void - sfnt_module_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->sfnt ) - { - sfntModulePIC* container = (sfntModulePIC*)pic_container->sfnt; - - - if ( container->sfnt_services ) - FT_Destroy_Class_sfnt_services( library, - container->sfnt_services ); - container->sfnt_services = NULL; - - if ( container->tt_cmap_classes ) - FT_Destroy_Class_tt_cmap_classes( library, - container->tt_cmap_classes ); - container->tt_cmap_classes = NULL; - - FT_FREE( container ); - pic_container->sfnt = NULL; - } - } - - - FT_Error - sfnt_module_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - sfntModulePIC* container = NULL; - FT_Memory memory = library->memory; - - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->sfnt = container; - - /* initialize pointer table - */ - /* this is how the module usually expects this data */ - error = FT_Create_Class_sfnt_services( library, - &container->sfnt_services ); - if ( error ) - goto Exit; - - error = FT_Create_Class_tt_cmap_classes( library, - &container->tt_cmap_classes ); - if ( error ) - goto Exit; - - FT_Init_Class_sfnt_service_glyph_dict( - library, &container->sfnt_service_glyph_dict ); - FT_Init_Class_sfnt_service_ps_name( - library, &container->sfnt_service_ps_name ); - FT_Init_Class_tt_service_get_cmap_info( - library, &container->tt_service_get_cmap_info ); - FT_Init_Class_sfnt_service_sfnt_table( - &container->sfnt_service_sfnt_table ); -#ifdef TT_CONFIG_OPTION_BDF - FT_Init_Class_sfnt_service_bdf( &container->sfnt_service_bdf ); -#endif - FT_Init_Class_sfnt_interface( library, &container->sfnt_interface ); - - Exit: - if ( error ) - sfnt_module_class_pic_free( library ); - return error; - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfntpic.h b/third_party/freetype/src/sfnt/sfntpic.h deleted file mode 100644 index d99be6a8248572dc1994bd66601a03f3d1f0d2a9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfntpic.h +++ /dev/null @@ -1,112 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfntpic.h */ -/* */ -/* The FreeType position independent code services for sfnt module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SFNTPIC_H__ -#define __SFNTPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -#ifndef FT_CONFIG_OPTION_PIC - -#define SFNT_SERVICES_GET sfnt_services -#define SFNT_SERVICE_GLYPH_DICT_GET sfnt_service_glyph_dict -#define SFNT_SERVICE_PS_NAME_GET sfnt_service_ps_name -#define TT_SERVICE_CMAP_INFO_GET tt_service_get_cmap_info -#define TT_CMAP_CLASSES_GET tt_cmap_classes -#define SFNT_SERVICE_SFNT_TABLE_GET sfnt_service_sfnt_table -#define SFNT_SERVICE_BDF_GET sfnt_service_bdf -#define SFNT_INTERFACE_GET sfnt_interface - -#else /* FT_CONFIG_OPTION_PIC */ - - /* some include files required for members of sfntModulePIC */ -#include FT_SERVICE_GLYPH_DICT_H -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_SFNT_H -#include FT_SERVICE_TT_CMAP_H - -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.h" -#include FT_SERVICE_BDF_H -#endif - -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include "ttcmap.h" - - -FT_BEGIN_HEADER - - typedef struct sfntModulePIC_ - { - FT_ServiceDescRec* sfnt_services; - FT_Service_GlyphDictRec sfnt_service_glyph_dict; - FT_Service_PsFontNameRec sfnt_service_ps_name; - FT_Service_TTCMapsRec tt_service_get_cmap_info; - TT_CMap_Class* tt_cmap_classes; - FT_Service_SFNT_TableRec sfnt_service_sfnt_table; -#ifdef TT_CONFIG_OPTION_BDF - FT_Service_BDFRec sfnt_service_bdf; -#endif - SFNT_Interface sfnt_interface; - - } sfntModulePIC; - - -#define GET_PIC( lib ) \ - ( (sfntModulePIC*)( (lib)->pic_container.sfnt ) ) - -#define SFNT_SERVICES_GET \ - ( GET_PIC( library )->sfnt_services ) -#define SFNT_SERVICE_GLYPH_DICT_GET \ - ( GET_PIC( library )->sfnt_service_glyph_dict ) -#define SFNT_SERVICE_PS_NAME_GET \ - ( GET_PIC( library )->sfnt_service_ps_name ) -#define TT_SERVICE_CMAP_INFO_GET \ - ( GET_PIC( library )->tt_service_get_cmap_info ) -#define TT_CMAP_CLASSES_GET \ - ( GET_PIC( library )->tt_cmap_classes ) -#define SFNT_SERVICE_SFNT_TABLE_GET \ - ( GET_PIC( library )->sfnt_service_sfnt_table ) -#define SFNT_SERVICE_BDF_GET \ - ( GET_PIC( library )->sfnt_service_bdf ) -#define SFNT_INTERFACE_GET \ - ( GET_PIC( library )->sfnt_interface ) - - - /* see sfntpic.c for the implementation */ - void - sfnt_module_class_pic_free( FT_Library library ); - - FT_Error - sfnt_module_class_pic_init( FT_Library library ); - - -FT_END_HEADER - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -#endif /* __SFNTPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfobjs.c b/third_party/freetype/src/sfnt/sfobjs.c deleted file mode 100644 index 14d3adef212e6ce023faeca797daa63dfb0c776a..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfobjs.c +++ /dev/null @@ -1,1603 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfobjs.c */ -/* */ -/* SFNT object management (base). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "sfobjs.h" -#include "ttload.h" -#include "ttcmap.h" -#include "ttkern.h" -#include FT_INTERNAL_SFNT_H -#include FT_INTERNAL_DEBUG_H -#include FT_TRUETYPE_IDS_H -#include FT_TRUETYPE_TAGS_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_SFNT_NAMES_H -#include FT_GZIP_H -#include "sferrors.h" - -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.h" -#endif - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_sfobjs - - - - /* convert a UTF-16 name entry to ASCII */ - static FT_String* - tt_name_entry_ascii_from_utf16( TT_NameEntry entry, - FT_Memory memory ) - { - FT_String* string = NULL; - FT_UInt len, code, n; - FT_Byte* read = (FT_Byte*)entry->string; - FT_Error error; - - - len = (FT_UInt)entry->stringLength / 2; - - if ( FT_NEW_ARRAY( string, len + 1 ) ) - return NULL; - - for ( n = 0; n < len; n++ ) - { - code = FT_NEXT_USHORT( read ); - - if ( code == 0 ) - break; - - if ( code < 32 || code > 127 ) - code = '?'; - - string[n] = (char)code; - } - - string[n] = 0; - - return string; - } - - - /* convert an Apple Roman or symbol name entry to ASCII */ - static FT_String* - tt_name_entry_ascii_from_other( TT_NameEntry entry, - FT_Memory memory ) - { - FT_String* string = NULL; - FT_UInt len, code, n; - FT_Byte* read = (FT_Byte*)entry->string; - FT_Error error; - - - len = (FT_UInt)entry->stringLength; - - if ( FT_NEW_ARRAY( string, len + 1 ) ) - return NULL; - - for ( n = 0; n < len; n++ ) - { - code = *read++; - - if ( code == 0 ) - break; - - if ( code < 32 || code > 127 ) - code = '?'; - - string[n] = (char)code; - } - - string[n] = 0; - - return string; - } - - - typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, - FT_Memory memory ); - - - /* documentation is in sfnt.h */ - - FT_LOCAL_DEF( FT_Error ) - tt_face_get_name( TT_Face face, - FT_UShort nameid, - FT_String** name ) - { - FT_Memory memory = face->root.memory; - FT_Error error = FT_Err_Ok; - FT_String* result = NULL; - FT_UShort n; - TT_NameEntryRec* rec; - FT_Int found_apple = -1; - FT_Int found_apple_roman = -1; - FT_Int found_apple_english = -1; - FT_Int found_win = -1; - FT_Int found_unicode = -1; - - FT_Bool is_english = 0; - - TT_NameEntry_ConvertFunc convert; - - - FT_ASSERT( name ); - - rec = face->name_table.names; - for ( n = 0; n < face->num_names; n++, rec++ ) - { - /* According to the OpenType 1.3 specification, only Microsoft or */ - /* Apple platform IDs might be used in the `name' table. The */ - /* `Unicode' platform is reserved for the `cmap' table, and the */ - /* `ISO' one is deprecated. */ - /* */ - /* However, the Apple TrueType specification doesn't say the same */ - /* thing and goes to suggest that all Unicode `name' table entries */ - /* should be coded in UTF-16 (in big-endian format I suppose). */ - /* */ - if ( rec->nameID == nameid && rec->stringLength > 0 ) - { - switch ( rec->platformID ) - { - case TT_PLATFORM_APPLE_UNICODE: - case TT_PLATFORM_ISO: - /* there is `languageID' to check there. We should use this */ - /* field only as a last solution when nothing else is */ - /* available. */ - /* */ - found_unicode = n; - break; - - case TT_PLATFORM_MACINTOSH: - /* This is a bit special because some fonts will use either */ - /* an English language id, or a Roman encoding id, to indicate */ - /* the English version of its font name. */ - /* */ - if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) - found_apple_english = n; - else if ( rec->encodingID == TT_MAC_ID_ROMAN ) - found_apple_roman = n; - break; - - case TT_PLATFORM_MICROSOFT: - /* we only take a non-English name when there is nothing */ - /* else available in the font */ - /* */ - if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) - { - switch ( rec->encodingID ) - { - case TT_MS_ID_SYMBOL_CS: - case TT_MS_ID_UNICODE_CS: - case TT_MS_ID_UCS_4: - is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); - found_win = n; - break; - - default: - ; - } - } - break; - - default: - ; - } - } - } - - found_apple = found_apple_roman; - if ( found_apple_english >= 0 ) - found_apple = found_apple_english; - - /* some fonts contain invalid Unicode or Macintosh formatted entries; */ - /* we will thus favor names encoded in Windows formats if available */ - /* (provided it is an English name) */ - /* */ - convert = NULL; - if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) - { - rec = face->name_table.names + found_win; - switch ( rec->encodingID ) - { - /* all Unicode strings are encoded using UTF-16BE */ - case TT_MS_ID_UNICODE_CS: - case TT_MS_ID_SYMBOL_CS: - convert = tt_name_entry_ascii_from_utf16; - break; - - case TT_MS_ID_UCS_4: - /* Apparently, if this value is found in a name table entry, it is */ - /* documented as `full Unicode repertoire'. Experience with the */ - /* MsGothic font shipped with Windows Vista shows that this really */ - /* means UTF-16 encoded names (UCS-4 values are only used within */ - /* charmaps). */ - convert = tt_name_entry_ascii_from_utf16; - break; - - default: - ; - } - } - else if ( found_apple >= 0 ) - { - rec = face->name_table.names + found_apple; - convert = tt_name_entry_ascii_from_other; - } - else if ( found_unicode >= 0 ) - { - rec = face->name_table.names + found_unicode; - convert = tt_name_entry_ascii_from_utf16; - } - - if ( rec && convert ) - { - if ( rec->string == NULL ) - { - FT_Stream stream = face->name_table.stream; - - - if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || - FT_STREAM_SEEK( rec->stringOffset ) || - FT_STREAM_READ( rec->string, rec->stringLength ) ) - { - FT_FREE( rec->string ); - rec->stringLength = 0; - result = NULL; - goto Exit; - } - } - - result = convert( rec, memory ); - } - - Exit: - *name = result; - return error; - } - - - static FT_Encoding - sfnt_find_encoding( int platform_id, - int encoding_id ) - { - typedef struct TEncoding_ - { - int platform_id; - int encoding_id; - FT_Encoding encoding; - - } TEncoding; - - static - const TEncoding tt_encodings[] = - { - { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, - - { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, - - { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, - - { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } - }; - - const TEncoding *cur, *limit; - - - cur = tt_encodings; - limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); - - for ( ; cur < limit; cur++ ) - { - if ( cur->platform_id == platform_id ) - { - if ( cur->encoding_id == encoding_id || - cur->encoding_id == -1 ) - return cur->encoding; - } - } - - return FT_ENCODING_NONE; - } - - -#define WRITE_USHORT( p, v ) \ - do \ - { \ - *(p)++ = (FT_Byte)( (v) >> 8 ); \ - *(p)++ = (FT_Byte)( (v) >> 0 ); \ - \ - } while ( 0 ) - -#define WRITE_ULONG( p, v ) \ - do \ - { \ - *(p)++ = (FT_Byte)( (v) >> 24 ); \ - *(p)++ = (FT_Byte)( (v) >> 16 ); \ - *(p)++ = (FT_Byte)( (v) >> 8 ); \ - *(p)++ = (FT_Byte)( (v) >> 0 ); \ - \ - } while ( 0 ) - - - static void - sfnt_stream_close( FT_Stream stream ) - { - FT_Memory memory = stream->memory; - - - FT_FREE( stream->base ); - - stream->size = 0; - stream->base = NULL; - stream->close = NULL; - } - - - FT_CALLBACK_DEF( int ) - compare_offsets( const void* a, - const void* b ) - { - WOFF_Table table1 = *(WOFF_Table*)a; - WOFF_Table table2 = *(WOFF_Table*)b; - - FT_ULong offset1 = table1->Offset; - FT_ULong offset2 = table2->Offset; - - - if ( offset1 > offset2 ) - return 1; - else if ( offset1 < offset2 ) - return -1; - else - return 0; - } - - - /* Replace `face->root.stream' with a stream containing the extracted */ - /* SFNT of a WOFF font. */ - - static FT_Error - woff_open_font( FT_Stream stream, - TT_Face face ) - { - FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - WOFF_HeaderRec woff; - WOFF_Table tables = NULL; - WOFF_Table* indices = NULL; - - FT_ULong woff_offset; - - FT_Byte* sfnt = NULL; - FT_Stream sfnt_stream = NULL; - - FT_Byte* sfnt_header; - FT_ULong sfnt_offset; - - FT_Int nn; - FT_ULong old_tag = 0; - - static const FT_Frame_Field woff_header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE WOFF_HeaderRec - - FT_FRAME_START( 44 ), - FT_FRAME_ULONG ( signature ), - FT_FRAME_ULONG ( flavor ), - FT_FRAME_ULONG ( length ), - FT_FRAME_USHORT( num_tables ), - FT_FRAME_USHORT( reserved ), - FT_FRAME_ULONG ( totalSfntSize ), - FT_FRAME_USHORT( majorVersion ), - FT_FRAME_USHORT( minorVersion ), - FT_FRAME_ULONG ( metaOffset ), - FT_FRAME_ULONG ( metaLength ), - FT_FRAME_ULONG ( metaOrigLength ), - FT_FRAME_ULONG ( privOffset ), - FT_FRAME_ULONG ( privLength ), - FT_FRAME_END - }; - - - FT_ASSERT( stream == face->root.stream ); - FT_ASSERT( FT_STREAM_POS() == 0 ); - - if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) ) - return error; - - /* Make sure we don't recurse back here or hit TTC code. */ - if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf ) - return FT_THROW( Invalid_Table ); - - /* Miscellaneous checks. */ - if ( woff.length != stream->size || - woff.num_tables == 0 || - 44 + woff.num_tables * 20UL >= woff.length || - 12 + woff.num_tables * 16UL >= woff.totalSfntSize || - ( woff.totalSfntSize & 3 ) != 0 || - ( woff.metaOffset == 0 && ( woff.metaLength != 0 || - woff.metaOrigLength != 0 ) ) || - ( woff.metaLength != 0 && woff.metaOrigLength == 0 ) || - ( woff.privOffset == 0 && woff.privLength != 0 ) ) - return FT_THROW( Invalid_Table ); - - if ( FT_ALLOC( sfnt, woff.totalSfntSize ) || - FT_NEW( sfnt_stream ) ) - goto Exit; - - sfnt_header = sfnt; - - /* Write sfnt header. */ - { - FT_UInt searchRange, entrySelector, rangeShift, x; - - - x = woff.num_tables; - entrySelector = 0; - while ( x ) - { - x >>= 1; - entrySelector += 1; - } - entrySelector--; - - searchRange = ( 1 << entrySelector ) * 16; - rangeShift = woff.num_tables * 16 - searchRange; - - WRITE_ULONG ( sfnt_header, woff.flavor ); - WRITE_USHORT( sfnt_header, woff.num_tables ); - WRITE_USHORT( sfnt_header, searchRange ); - WRITE_USHORT( sfnt_header, entrySelector ); - WRITE_USHORT( sfnt_header, rangeShift ); - } - - /* While the entries in the sfnt header must be sorted by the */ - /* tag value, the tables themselves are not. We thus have to */ - /* sort them by offset and check that they don't overlap. */ - - if ( FT_NEW_ARRAY( tables, woff.num_tables ) || - FT_NEW_ARRAY( indices, woff.num_tables ) ) - goto Exit; - - FT_TRACE2(( "\n" - " tag offset compLen origLen checksum\n" - " -------------------------------------------\n" )); - - if ( FT_FRAME_ENTER( 20L * woff.num_tables ) ) - goto Exit; - - for ( nn = 0; nn < woff.num_tables; nn++ ) - { - WOFF_Table table = tables + nn; - - table->Tag = FT_GET_TAG4(); - table->Offset = FT_GET_ULONG(); - table->CompLength = FT_GET_ULONG(); - table->OrigLength = FT_GET_ULONG(); - table->CheckSum = FT_GET_ULONG(); - - FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx %08lx\n", - (FT_Char)( table->Tag >> 24 ), - (FT_Char)( table->Tag >> 16 ), - (FT_Char)( table->Tag >> 8 ), - (FT_Char)( table->Tag ), - table->Offset, - table->CompLength, - table->OrigLength, - table->CheckSum )); - - if ( table->Tag <= old_tag ) - { - FT_FRAME_EXIT(); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - old_tag = table->Tag; - indices[nn] = table; - } - - FT_FRAME_EXIT(); - - /* Sort by offset. */ - - ft_qsort( indices, - woff.num_tables, - sizeof ( WOFF_Table ), - compare_offsets ); - - /* Check offsets and lengths. */ - - woff_offset = 44 + woff.num_tables * 20L; - sfnt_offset = 12 + woff.num_tables * 16L; - - for ( nn = 0; nn < woff.num_tables; nn++ ) - { - WOFF_Table table = indices[nn]; - - - if ( table->Offset != woff_offset || - table->CompLength > woff.length || - table->Offset > woff.length - table->CompLength || - table->OrigLength > woff.totalSfntSize || - sfnt_offset > woff.totalSfntSize - table->OrigLength || - table->CompLength > table->OrigLength ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - table->OrigOffset = sfnt_offset; - - /* The offsets must be multiples of 4. */ - woff_offset += ( table->CompLength + 3 ) & ~3U; - sfnt_offset += ( table->OrigLength + 3 ) & ~3U; - } - - /* - * Final checks! - * - * We don't decode and check the metadata block. - * We don't check table checksums either. - * But other than those, I think we implement all - * `MUST' checks from the spec. - */ - - if ( woff.metaOffset ) - { - if ( woff.metaOffset != woff_offset || - woff.metaOffset + woff.metaLength > woff.length ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - /* We have padding only ... */ - woff_offset += woff.metaLength; - } - - if ( woff.privOffset ) - { - /* ... if it isn't the last block. */ - woff_offset = ( woff_offset + 3 ) & ~3U; - - if ( woff.privOffset != woff_offset || - woff.privOffset + woff.privLength > woff.length ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - /* No padding for the last block. */ - woff_offset += woff.privLength; - } - - if ( sfnt_offset != woff.totalSfntSize || - woff_offset != woff.length ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - /* Write the tables. */ - - for ( nn = 0; nn < woff.num_tables; nn++ ) - { - WOFF_Table table = tables + nn; - - - /* Write SFNT table entry. */ - WRITE_ULONG( sfnt_header, table->Tag ); - WRITE_ULONG( sfnt_header, table->CheckSum ); - WRITE_ULONG( sfnt_header, table->OrigOffset ); - WRITE_ULONG( sfnt_header, table->OrigLength ); - - /* Write table data. */ - if ( FT_STREAM_SEEK( table->Offset ) || - FT_FRAME_ENTER( table->CompLength ) ) - goto Exit; - - if ( table->CompLength == table->OrigLength ) - { - /* Uncompressed data; just copy. */ - ft_memcpy( sfnt + table->OrigOffset, - stream->cursor, - table->OrigLength ); - } - else - { -#ifdef FT_CONFIG_OPTION_USE_ZLIB - - /* Uncompress with zlib. */ - FT_ULong output_len = table->OrigLength; - - - error = FT_Gzip_Uncompress( memory, - sfnt + table->OrigOffset, &output_len, - stream->cursor, table->CompLength ); - if ( error ) - goto Exit; - if ( output_len != table->OrigLength ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - -#else /* !FT_CONFIG_OPTION_USE_ZLIB */ - - error = FT_THROW( Unimplemented_Feature ); - goto Exit; - -#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ - } - - FT_FRAME_EXIT(); - - /* We don't check whether the padding bytes in the WOFF file are */ - /* actually '\0'. For the output, however, we do set them properly. */ - sfnt_offset = table->OrigOffset + table->OrigLength; - while ( sfnt_offset & 3 ) - { - sfnt[sfnt_offset] = '\0'; - sfnt_offset++; - } - } - - /* Ok! Finally ready. Swap out stream and return. */ - FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize ); - sfnt_stream->memory = stream->memory; - sfnt_stream->close = sfnt_stream_close; - - FT_Stream_Free( - face->root.stream, - ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); - - face->root.stream = sfnt_stream; - - face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; - - Exit: - FT_FREE( tables ); - FT_FREE( indices ); - - if ( error ) - { - FT_FREE( sfnt ); - FT_Stream_Close( sfnt_stream ); - FT_FREE( sfnt_stream ); - } - - return error; - } - - -#undef WRITE_USHORT -#undef WRITE_ULONG - - - /* Fill in face->ttc_header. If the font is not a TTC, it is */ - /* synthesized into a TTC with one offset table. */ - static FT_Error - sfnt_open_font( FT_Stream stream, - TT_Face face ) - { - FT_Memory memory = stream->memory; - FT_Error error; - FT_ULong tag, offset; - - static const FT_Frame_Field ttc_header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TTC_HeaderRec - - FT_FRAME_START( 8 ), - FT_FRAME_LONG( version ), - FT_FRAME_LONG( count ), /* this is ULong in the specs */ - FT_FRAME_END - }; - - - face->ttc_header.tag = 0; - face->ttc_header.version = 0; - face->ttc_header.count = 0; - - retry: - offset = FT_STREAM_POS(); - - if ( FT_READ_ULONG( tag ) ) - return error; - - if ( tag == TTAG_wOFF ) - { - FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" )); - - if ( FT_STREAM_SEEK( offset ) ) - return error; - - error = woff_open_font( stream, face ); - if ( error ) - return error; - - /* Swap out stream and retry! */ - stream = face->root.stream; - goto retry; - } - - if ( tag != 0x00010000UL && - tag != TTAG_ttcf && - tag != TTAG_OTTO && - tag != TTAG_true && - tag != TTAG_typ1 && - tag != 0x00020000UL ) - { - FT_TRACE2(( " not a font using the SFNT container format\n" )); - return FT_THROW( Unknown_File_Format ); - } - - face->ttc_header.tag = TTAG_ttcf; - - if ( tag == TTAG_ttcf ) - { - FT_Int n; - - - FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); - - if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) - return error; - - if ( face->ttc_header.count == 0 ) - return FT_THROW( Invalid_Table ); - - /* a rough size estimate: let's conservatively assume that there */ - /* is just a single table info in each subfont header (12 + 16*1 = */ - /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ - /* size of the TTC header plus `28*count' bytes for all subfont */ - /* headers */ - if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) - return FT_THROW( Array_Too_Large ); - - /* now read the offsets of each font in the file */ - if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) - return error; - - if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) - return error; - - for ( n = 0; n < face->ttc_header.count; n++ ) - face->ttc_header.offsets[n] = FT_GET_ULONG(); - - FT_FRAME_EXIT(); - } - else - { - FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); - - face->ttc_header.version = 1 << 16; - face->ttc_header.count = 1; - - if ( FT_NEW( face->ttc_header.offsets ) ) - return error; - - face->ttc_header.offsets[0] = offset; - } - - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - sfnt_init_face( FT_Stream stream, - TT_Face face, - FT_Int face_instance_index, - FT_Int num_params, - FT_Parameter* params ) - { - FT_Error error; - FT_Library library = face->root.driver->root.library; - SFNT_Service sfnt; - FT_Int face_index; - - - /* for now, parameters are unused */ - FT_UNUSED( num_params ); - FT_UNUSED( params ); - - - sfnt = (SFNT_Service)face->sfnt; - if ( !sfnt ) - { - sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); - if ( !sfnt ) - { - FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); - return FT_THROW( Missing_Module ); - } - - face->sfnt = sfnt; - face->goto_table = sfnt->goto_table; - } - - FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); - - FT_TRACE2(( "SFNT driver\n" )); - - error = sfnt_open_font( stream, face ); - if ( error ) - return error; - - /* Stream may have changed in sfnt_open_font. */ - stream = face->root.stream; - - FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index )); - - face_index = FT_ABS( face_instance_index ) & 0xFFFF; - - if ( face_index >= face->ttc_header.count ) - { - if ( face_instance_index >= 0 ) - return FT_THROW( Invalid_Argument ); - else - face_index = 0; - } - - if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) - return error; - - /* check whether we have a valid TrueType file */ - error = sfnt->load_font_dir( face, stream ); - if ( error ) - return error; - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - { - FT_ULong fvar_len; - FT_UShort num_instances; - FT_Int instance_index; - - - instance_index = FT_ABS( face_instance_index ) >> 16; - - /* test whether current face is a GX font with named instances */ - if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) || - fvar_len < 20 || - FT_STREAM_SKIP( 12 ) || - FT_READ_USHORT( num_instances ) ) - num_instances = 0; - - /* we support at most 2^15 - 1 instances */ - if ( num_instances >= ( 1U << 15 ) - 1 ) - { - if ( face_instance_index >= 0 ) - return FT_THROW( Invalid_Argument ); - else - num_instances = 0; - } - - /* instance indices in `face_instance_index' start with index 1, */ - /* thus `>' and not `>=' */ - if ( instance_index > num_instances ) - { - if ( face_instance_index >= 0 ) - return FT_THROW( Invalid_Argument ); - else - num_instances = 0; - } - - face->root.style_flags = (FT_Long)num_instances << 16; - } -#endif - - face->root.num_faces = face->ttc_header.count; - face->root.face_index = face_index; - - return error; - } - - -#define LOAD_( x ) \ - do \ - { \ - FT_TRACE2(( "`" #x "' " )); \ - FT_TRACE3(( "-->\n" )); \ - \ - error = sfnt->load_ ## x( face, stream ); \ - \ - FT_TRACE2(( "%s\n", ( !error ) \ - ? "loaded" \ - : FT_ERR_EQ( error, Table_Missing ) \ - ? "missing" \ - : "failed to load" )); \ - FT_TRACE3(( "\n" )); \ - } while ( 0 ) - -#define LOADM_( x, vertical ) \ - do \ - { \ - FT_TRACE2(( "`%s" #x "' ", \ - vertical ? "vertical " : "" )); \ - FT_TRACE3(( "-->\n" )); \ - \ - error = sfnt->load_ ## x( face, stream, vertical ); \ - \ - FT_TRACE2(( "%s\n", ( !error ) \ - ? "loaded" \ - : FT_ERR_EQ( error, Table_Missing ) \ - ? "missing" \ - : "failed to load" )); \ - FT_TRACE3(( "\n" )); \ - } while ( 0 ) - -#define GET_NAME( id, field ) \ - do \ - { \ - error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ - if ( error ) \ - goto Exit; \ - } while ( 0 ) - - - FT_LOCAL_DEF( FT_Error ) - sfnt_load_face( FT_Stream stream, - TT_Face face, - FT_Int face_instance_index, - FT_Int num_params, - FT_Parameter* params ) - { - FT_Error error; -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES - FT_Error psnames_error; -#endif - FT_Bool has_outline; - FT_Bool is_apple_sbit; - FT_Bool is_apple_sbix; - FT_Bool ignore_preferred_family = FALSE; - FT_Bool ignore_preferred_subfamily = FALSE; - - SFNT_Service sfnt = (SFNT_Service)face->sfnt; - - FT_UNUSED( face_instance_index ); - - - /* Check parameters */ - - { - FT_Int i; - - - for ( i = 0; i < num_params; i++ ) - { - if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) - ignore_preferred_family = TRUE; - else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) - ignore_preferred_subfamily = TRUE; - } - } - - /* Load tables */ - - /* We now support two SFNT-based bitmapped font formats. They */ - /* are recognized easily as they do not include a `glyf' */ - /* table. */ - /* */ - /* The first format comes from Apple, and uses a table named */ - /* `bhed' instead of `head' to store the font header (using */ - /* the same format). It also doesn't include horizontal and */ - /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ - /* missing). */ - /* */ - /* The other format comes from Microsoft, and is used with */ - /* WinCE/PocketPC. It looks like a standard TTF, except that */ - /* it doesn't contain outlines. */ - /* */ - - FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); - - /* do we have outlines in there? */ -#ifdef FT_CONFIG_OPTION_INCREMENTAL - has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || - tt_face_lookup_table( face, TTAG_glyf ) != 0 || - tt_face_lookup_table( face, TTAG_CFF ) != 0 ); -#else - has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || - tt_face_lookup_table( face, TTAG_CFF ) != 0 ); -#endif - - is_apple_sbit = 0; - is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); - - /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' - * outline rendered on top. We don't support that yet, so just ignore - * the 'glyf' outline and advertise it as a bitmap-only font. */ - if ( is_apple_sbix ) - has_outline = FALSE; - - /* if this font doesn't contain outlines, we try to load */ - /* a `bhed' table */ - if ( !has_outline && sfnt->load_bhed ) - { - LOAD_( bhed ); - is_apple_sbit = FT_BOOL( !error ); - } - - /* load the font header (`head' table) if this isn't an Apple */ - /* sbit font file */ - if ( !is_apple_sbit || is_apple_sbix ) - { - LOAD_( head ); - if ( error ) - goto Exit; - } - - if ( face->header.Units_Per_EM == 0 ) - { - error = FT_THROW( Invalid_Table ); - - goto Exit; - } - - /* the following tables are often not present in embedded TrueType */ - /* fonts within PDF documents, so don't check for them. */ - LOAD_( maxp ); - LOAD_( cmap ); - - /* the following tables are optional in PCL fonts -- */ - /* don't check for errors */ - LOAD_( name ); - LOAD_( post ); - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES - psnames_error = error; -#endif - - /* do not load the metrics headers and tables if this is an Apple */ - /* sbit font file */ - if ( !is_apple_sbit ) - { - /* load the `hhea' and `hmtx' tables */ - LOADM_( hhea, 0 ); - if ( !error ) - { - LOADM_( hmtx, 0 ); - if ( FT_ERR_EQ( error, Table_Missing ) ) - { - error = FT_THROW( Hmtx_Table_Missing ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* If this is an incrementally loaded font and there are */ - /* overriding metrics, tolerate a missing `hmtx' table. */ - if ( face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs-> - get_glyph_metrics ) - { - face->horizontal.number_Of_HMetrics = 0; - error = FT_Err_Ok; - } -#endif - } - } - else if ( FT_ERR_EQ( error, Table_Missing ) ) - { - /* No `hhea' table necessary for SFNT Mac fonts. */ - if ( face->format_tag == TTAG_true ) - { - FT_TRACE2(( "This is an SFNT Mac font.\n" )); - - has_outline = 0; - error = FT_Err_Ok; - } - else - { - error = FT_THROW( Horiz_Header_Missing ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* If this is an incrementally loaded font and there are */ - /* overriding metrics, tolerate a missing `hhea' table. */ - if ( face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs-> - get_glyph_metrics ) - { - face->horizontal.number_Of_HMetrics = 0; - error = FT_Err_Ok; - } -#endif - - } - } - - if ( error ) - goto Exit; - - /* try to load the `vhea' and `vmtx' tables */ - LOADM_( hhea, 1 ); - if ( !error ) - { - LOADM_( hmtx, 1 ); - if ( !error ) - face->vertical_info = 1; - } - - if ( error && FT_ERR_NEQ( error, Table_Missing ) ) - goto Exit; - - LOAD_( os2 ); - if ( error ) - { - /* we treat the table as missing if there are any errors */ - face->os2.version = 0xFFFFU; - } - } - - /* the optional tables */ - - /* embedded bitmap support */ - if ( sfnt->load_eblc ) - { - LOAD_( eblc ); - if ( error ) - { - /* a font which contains neither bitmaps nor outlines is */ - /* still valid (although rather useless in most cases); */ - /* however, you can find such stripped fonts in PDFs */ - if ( FT_ERR_EQ( error, Table_Missing ) ) - error = FT_Err_Ok; - else - goto Exit; - } - } - - LOAD_( pclt ); - if ( error ) - { - if ( FT_ERR_NEQ( error, Table_Missing ) ) - goto Exit; - - face->pclt.Version = 0; - } - - /* consider the kerning and gasp tables as optional */ - LOAD_( gasp ); - LOAD_( kern ); - - face->root.num_glyphs = face->max_profile.numGlyphs; - - /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ - /* a WWS-only font face. `WWS' stands for `weight', width', and */ - /* `slope', a term used by Microsoft's Windows Presentation */ - /* Foundation (WPF). This flag has been introduced in version */ - /* 1.5 of the OpenType specification (May 2008). */ - - face->root.family_name = NULL; - face->root.style_name = NULL; - if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) - { - if ( !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); - if ( !face->root.family_name ) - GET_NAME( FONT_FAMILY, &face->root.family_name ); - - if ( !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); - if ( !face->root.style_name ) - GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); - } - else - { - GET_NAME( WWS_FAMILY, &face->root.family_name ); - if ( !face->root.family_name && !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); - if ( !face->root.family_name ) - GET_NAME( FONT_FAMILY, &face->root.family_name ); - - GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); - if ( !face->root.style_name && !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); - if ( !face->root.style_name ) - GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); - } - - /* now set up root fields */ - { - FT_Face root = &face->root; - FT_Long flags = root->face_flags; - - - /*********************************************************************/ - /* */ - /* Compute face flags. */ - /* */ - if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || - face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ) - flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ - - if ( has_outline == TRUE ) - flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ - - /* The sfnt driver only supports bitmap fonts natively, thus we */ - /* don't set FT_FACE_FLAG_HINTER. */ - flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ - FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES - if ( !psnames_error && - face->postscript.FormatType != 0x00030000L ) - flags |= FT_FACE_FLAG_GLYPH_NAMES; -#endif - - /* fixed width font? */ - if ( face->postscript.isFixedPitch ) - flags |= FT_FACE_FLAG_FIXED_WIDTH; - - /* vertical information? */ - if ( face->vertical_info ) - flags |= FT_FACE_FLAG_VERTICAL; - - /* kerning available ? */ - if ( TT_FACE_HAS_KERNING( face ) ) - flags |= FT_FACE_FLAG_KERNING; - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - /* Don't bother to load the tables unless somebody asks for them. */ - /* No need to do work which will (probably) not be used. */ - if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && - tt_face_lookup_table( face, TTAG_fvar ) != 0 && - tt_face_lookup_table( face, TTAG_gvar ) != 0 ) - flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; -#endif - - root->face_flags = flags; - - /*********************************************************************/ - /* */ - /* Compute style flags. */ - /* */ - - flags = 0; - if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) - { - /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ - /* indicates an oblique font face. This flag has been */ - /* introduced in version 1.5 of the OpenType specification. */ - - if ( face->os2.fsSelection & 512 ) /* bit 9 */ - flags |= FT_STYLE_FLAG_ITALIC; - else if ( face->os2.fsSelection & 1 ) /* bit 0 */ - flags |= FT_STYLE_FLAG_ITALIC; - - if ( face->os2.fsSelection & 32 ) /* bit 5 */ - flags |= FT_STYLE_FLAG_BOLD; - } - else - { - /* this is an old Mac font, use the header field */ - - if ( face->header.Mac_Style & 1 ) - flags |= FT_STYLE_FLAG_BOLD; - - if ( face->header.Mac_Style & 2 ) - flags |= FT_STYLE_FLAG_ITALIC; - } - - root->style_flags |= flags; - - /*********************************************************************/ - /* */ - /* Polish the charmaps. */ - /* */ - /* Try to set the charmap encoding according to the platform & */ - /* encoding ID of each charmap. */ - /* */ - - tt_face_build_cmaps( face ); /* ignore errors */ - - - /* set the encoding fields */ - { - FT_Int m; - - - for ( m = 0; m < root->num_charmaps; m++ ) - { - FT_CharMap charmap = root->charmaps[m]; - - - charmap->encoding = sfnt_find_encoding( charmap->platform_id, - charmap->encoding_id ); - -#if 0 - if ( root->charmap == NULL && - charmap->encoding == FT_ENCODING_UNICODE ) - { - /* set 'root->charmap' to the first Unicode encoding we find */ - root->charmap = charmap; - } -#endif - } - } - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - /* - * Now allocate the root array of FT_Bitmap_Size records and - * populate them. Unfortunately, it isn't possible to indicate bit - * depths in the FT_Bitmap_Size record. This is a design error. - */ - { - FT_UInt i, count; - - - count = face->sbit_num_strikes; - - if ( count > 0 ) - { - FT_Memory memory = face->root.stream->memory; - FT_UShort em_size = face->header.Units_Per_EM; - FT_Short avgwidth = face->os2.xAvgCharWidth; - FT_Size_Metrics metrics; - - - if ( em_size == 0 || face->os2.version == 0xFFFFU ) - { - avgwidth = 1; - em_size = 1; - } - - if ( FT_NEW_ARRAY( root->available_sizes, count ) ) - goto Exit; - - for ( i = 0; i < count; i++ ) - { - FT_Bitmap_Size* bsize = root->available_sizes + i; - - - error = sfnt->load_strike_metrics( face, i, &metrics ); - if ( error ) - goto Exit; - - bsize->height = (FT_Short)( metrics.height >> 6 ); - bsize->width = (FT_Short)( - ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); - - bsize->x_ppem = metrics.x_ppem << 6; - bsize->y_ppem = metrics.y_ppem << 6; - - /* assume 72dpi */ - bsize->size = metrics.y_ppem << 6; - } - - root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; - root->num_fixed_sizes = (FT_Int)count; - } - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - /* a font with no bitmaps and no outlines is scalable; */ - /* it has only empty glyphs then */ - if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) - root->face_flags |= FT_FACE_FLAG_SCALABLE; - - - /*********************************************************************/ - /* */ - /* Set up metrics. */ - /* */ - if ( FT_IS_SCALABLE( root ) ) - { - /* XXX What about if outline header is missing */ - /* (e.g. sfnt wrapped bitmap)? */ - root->bbox.xMin = face->header.xMin; - root->bbox.yMin = face->header.yMin; - root->bbox.xMax = face->header.xMax; - root->bbox.yMax = face->header.yMax; - root->units_per_EM = face->header.Units_Per_EM; - - - /* XXX: Computing the ascender/descender/height is very different */ - /* from what the specification tells you. Apparently, we */ - /* must be careful because */ - /* */ - /* - not all fonts have an OS/2 table; in this case, we take */ - /* the values in the horizontal header. However, these */ - /* values very often are not reliable. */ - /* */ - /* - otherwise, the correct typographic values are in the */ - /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ - /* */ - /* However, certain fonts have these fields set to 0. */ - /* Rather, they have usWinAscent & usWinDescent correctly */ - /* set (but with different values). */ - /* */ - /* As an example, Arial Narrow is implemented through four */ - /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ - /* */ - /* Strangely, all fonts have the same values in their */ - /* sTypoXXX fields, except ARIALNB which sets them to 0. */ - /* */ - /* On the other hand, they all have different */ - /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ - /* table cannot be used to compute the text height reliably! */ - /* */ - - /* The ascender and descender are taken from the `hhea' table. */ - /* If zero, they are taken from the `OS/2' table. */ - - root->ascender = face->horizontal.Ascender; - root->descender = face->horizontal.Descender; - - root->height = root->ascender - root->descender + - face->horizontal.Line_Gap; - - if ( !( root->ascender || root->descender ) ) - { - if ( face->os2.version != 0xFFFFU ) - { - if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) - { - root->ascender = face->os2.sTypoAscender; - root->descender = face->os2.sTypoDescender; - - root->height = root->ascender - root->descender + - face->os2.sTypoLineGap; - } - else - { - root->ascender = (FT_Short)face->os2.usWinAscent; - root->descender = -(FT_Short)face->os2.usWinDescent; - - root->height = root->ascender - root->descender; - } - } - } - - root->max_advance_width = - (FT_Short)face->horizontal.advance_Width_Max; - root->max_advance_height = - (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max - : root->height ); - - /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ - /* Adjust underline position from top edge to centre of */ - /* stroke to convert TrueType meaning to FreeType meaning. */ - root->underline_position = face->postscript.underlinePosition - - face->postscript.underlineThickness / 2; - root->underline_thickness = face->postscript.underlineThickness; - } - - } - - Exit: - FT_TRACE2(( "sfnt_load_face: done\n" )); - - return error; - } - - -#undef LOAD_ -#undef LOADM_ -#undef GET_NAME - - - FT_LOCAL_DEF( void ) - sfnt_done_face( TT_Face face ) - { - FT_Memory memory; - SFNT_Service sfnt; - - - if ( !face ) - return; - - memory = face->root.memory; - sfnt = (SFNT_Service)face->sfnt; - - if ( sfnt ) - { - /* destroy the postscript names table if it is loaded */ - if ( sfnt->free_psnames ) - sfnt->free_psnames( face ); - - /* destroy the embedded bitmaps table if it is loaded */ - if ( sfnt->free_eblc ) - sfnt->free_eblc( face ); - } - -#ifdef TT_CONFIG_OPTION_BDF - /* freeing the embedded BDF properties */ - tt_face_free_bdf_props( face ); -#endif - - /* freeing the kerning table */ - tt_face_done_kern( face ); - - /* freeing the collection table */ - FT_FREE( face->ttc_header.offsets ); - face->ttc_header.count = 0; - - /* freeing table directory */ - FT_FREE( face->dir_tables ); - face->num_tables = 0; - - { - FT_Stream stream = FT_FACE_STREAM( face ); - - - /* simply release the 'cmap' table frame */ - FT_FRAME_RELEASE( face->cmap_table ); - face->cmap_size = 0; - } - - /* freeing the horizontal metrics */ - { - FT_Stream stream = FT_FACE_STREAM( face ); - - - FT_FRAME_RELEASE( face->horz_metrics ); - FT_FRAME_RELEASE( face->vert_metrics ); - face->horz_metrics_size = 0; - face->vert_metrics_size = 0; - } - - /* freeing the vertical ones, if any */ - if ( face->vertical_info ) - { - FT_FREE( face->vertical.long_metrics ); - FT_FREE( face->vertical.short_metrics ); - face->vertical_info = 0; - } - - /* freeing the gasp table */ - FT_FREE( face->gasp.gaspRanges ); - face->gasp.numRanges = 0; - - /* freeing the name table */ - if ( sfnt ) - sfnt->free_name( face ); - - /* freeing family and style name */ - FT_FREE( face->root.family_name ); - FT_FREE( face->root.style_name ); - - /* freeing sbit size table */ - FT_FREE( face->root.available_sizes ); - face->root.num_fixed_sizes = 0; - - FT_FREE( face->postscript_name ); - - face->sfnt = NULL; - } - - -/* END */ diff --git a/third_party/freetype/src/sfnt/sfobjs.h b/third_party/freetype/src/sfnt/sfobjs.h deleted file mode 100644 index 455f86772f8990159ef21d9a3bbfa8c6023a7589..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/sfobjs.h +++ /dev/null @@ -1,59 +0,0 @@ -/***************************************************************************/ -/* */ -/* sfobjs.h */ -/* */ -/* SFNT object management (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __SFOBJS_H__ -#define __SFOBJS_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_SFNT_H -#include FT_INTERNAL_OBJECTS_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - sfnt_init_face( FT_Stream stream, - TT_Face face, - FT_Int face_instance_index, - FT_Int num_params, - FT_Parameter* params ); - - FT_LOCAL( FT_Error ) - sfnt_load_face( FT_Stream stream, - TT_Face face, - FT_Int face_instance_index, - FT_Int num_params, - FT_Parameter* params ); - - FT_LOCAL( void ) - sfnt_done_face( TT_Face face ); - - FT_LOCAL( FT_Error ) - tt_face_get_name( TT_Face face, - FT_UShort nameid, - FT_String** name ); - - -FT_END_HEADER - -#endif /* __SFDRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttbdf.c b/third_party/freetype/src/sfnt/ttbdf.c deleted file mode 100644 index 098b781a146a51fa69e22f03958fee22212c0256..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttbdf.c +++ /dev/null @@ -1,250 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttbdf.c */ -/* */ -/* TrueType and OpenType embedded BDF properties (body). */ -/* */ -/* Copyright 2005-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include "ttbdf.h" - -#include "sferrors.h" - - -#ifdef TT_CONFIG_OPTION_BDF - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttbdf - - - FT_LOCAL_DEF( void ) - tt_face_free_bdf_props( TT_Face face ) - { - TT_BDF bdf = &face->bdf; - - - if ( bdf->loaded ) - { - FT_Stream stream = FT_FACE(face)->stream; - - - if ( bdf->table != NULL ) - FT_FRAME_RELEASE( bdf->table ); - - bdf->table_end = NULL; - bdf->strings = NULL; - bdf->strings_size = 0; - } - } - - - static FT_Error - tt_face_load_bdf_props( TT_Face face, - FT_Stream stream ) - { - TT_BDF bdf = &face->bdf; - FT_ULong length; - FT_Error error; - - - FT_ZERO( bdf ); - - error = tt_face_goto_table( face, TTAG_BDF, stream, &length ); - if ( error || - length < 8 || - FT_FRAME_EXTRACT( length, bdf->table ) ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - bdf->table_end = bdf->table + length; - - { - FT_Byte* p = bdf->table; - FT_UInt version = FT_NEXT_USHORT( p ); - FT_UInt num_strikes = FT_NEXT_USHORT( p ); - FT_ULong strings = FT_NEXT_ULONG ( p ); - FT_UInt count; - FT_Byte* strike; - - - if ( version != 0x0001 || - strings < 8 || - ( strings - 8 ) / 4 < num_strikes || - strings + 1 > length ) - { - goto BadTable; - } - - bdf->num_strikes = num_strikes; - bdf->strings = bdf->table + strings; - bdf->strings_size = length - strings; - - count = bdf->num_strikes; - p = bdf->table + 8; - strike = p + count * 4; - - - for ( ; count > 0; count-- ) - { - FT_UInt num_items = FT_PEEK_USHORT( p + 2 ); - - /* - * We don't need to check the value sets themselves, since this - * is done later. - */ - strike += 10 * num_items; - - p += 4; - } - - if ( strike > bdf->strings ) - goto BadTable; - } - - bdf->loaded = 1; - - Exit: - return error; - - BadTable: - FT_FRAME_RELEASE( bdf->table ); - FT_ZERO( bdf ); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - - FT_LOCAL_DEF( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, - const char* property_name, - BDF_PropertyRec *aprop ) - { - TT_BDF bdf = &face->bdf; - FT_Size size = FT_FACE(face)->size; - FT_Error error = FT_Err_Ok; - FT_Byte* p; - FT_UInt count; - FT_Byte* strike; - FT_Offset property_len; - - - aprop->type = BDF_PROPERTY_TYPE_NONE; - - if ( bdf->loaded == 0 ) - { - error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); - if ( error ) - goto Exit; - } - - count = bdf->num_strikes; - p = bdf->table + 8; - strike = p + 4 * count; - - error = FT_ERR( Invalid_Argument ); - - if ( size == NULL || property_name == NULL ) - goto Exit; - - property_len = ft_strlen( property_name ); - if ( property_len == 0 ) - goto Exit; - - for ( ; count > 0; count-- ) - { - FT_UInt _ppem = FT_NEXT_USHORT( p ); - FT_UInt _count = FT_NEXT_USHORT( p ); - - if ( _ppem == size->metrics.y_ppem ) - { - count = _count; - goto FoundStrike; - } - - strike += 10 * _count; - } - goto Exit; - - FoundStrike: - p = strike; - for ( ; count > 0; count-- ) - { - FT_UInt type = FT_PEEK_USHORT( p + 4 ); - - if ( ( type & 0x10 ) != 0 ) - { - FT_UInt32 name_offset = FT_PEEK_ULONG( p ); - FT_UInt32 value = FT_PEEK_ULONG( p + 6 ); - - /* be a bit paranoid for invalid entries here */ - if ( name_offset < bdf->strings_size && - property_len < bdf->strings_size - name_offset && - ft_strncmp( property_name, - (const char*)bdf->strings + name_offset, - bdf->strings_size - name_offset ) == 0 ) - { - switch ( type & 0x0F ) - { - case 0x00: /* string */ - case 0x01: /* atoms */ - /* check that the content is really 0-terminated */ - if ( value < bdf->strings_size && - ft_memchr( bdf->strings + value, 0, bdf->strings_size ) ) - { - aprop->type = BDF_PROPERTY_TYPE_ATOM; - aprop->u.atom = (const char*)bdf->strings + value; - error = FT_Err_Ok; - goto Exit; - } - break; - - case 0x02: - aprop->type = BDF_PROPERTY_TYPE_INTEGER; - aprop->u.integer = (FT_Int32)value; - error = FT_Err_Ok; - goto Exit; - - case 0x03: - aprop->type = BDF_PROPERTY_TYPE_CARDINAL; - aprop->u.cardinal = value; - error = FT_Err_Ok; - goto Exit; - - default: - ; - } - } - } - p += 10; - } - - Exit: - return error; - } - -#endif /* TT_CONFIG_OPTION_BDF */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttbdf.h b/third_party/freetype/src/sfnt/ttbdf.h deleted file mode 100644 index fe4ba489e8dbdbf4f10a4a185c3025961a34c73c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttbdf.h +++ /dev/null @@ -1,46 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttbdf.h */ -/* */ -/* TrueType and OpenType embedded BDF properties (specification). */ -/* */ -/* Copyright 2005-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTBDF_H__ -#define __TTBDF_H__ - - -#include <ft2build.h> -#include "ttload.h" -#include FT_BDF_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( void ) - tt_face_free_bdf_props( TT_Face face ); - - - FT_LOCAL( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, - const char* property_name, - BDF_PropertyRec *aprop ); - - -FT_END_HEADER - -#endif /* __TTBDF_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttcmap.c b/third_party/freetype/src/sfnt/ttcmap.c deleted file mode 100644 index c4d9abdfe6800edc47cbef350419f5f7c3d6ab8e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttcmap.c +++ /dev/null @@ -1,3721 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttcmap.c */ -/* */ -/* TrueType character mapping table (cmap) support (body). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H - -#include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */ - -#include FT_INTERNAL_VALIDATE_H -#include FT_INTERNAL_STREAM_H -#include "ttload.h" -#include "ttcmap.h" -#include "sfntpic.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttcmap - - -#define TT_PEEK_SHORT FT_PEEK_SHORT -#define TT_PEEK_USHORT FT_PEEK_USHORT -#define TT_PEEK_UINT24 FT_PEEK_UOFF3 -#define TT_PEEK_LONG FT_PEEK_LONG -#define TT_PEEK_ULONG FT_PEEK_ULONG - -#define TT_NEXT_SHORT FT_NEXT_SHORT -#define TT_NEXT_USHORT FT_NEXT_USHORT -#define TT_NEXT_UINT24 FT_NEXT_UOFF3 -#define TT_NEXT_LONG FT_NEXT_LONG -#define TT_NEXT_ULONG FT_NEXT_ULONG - - - /* Too large glyph index return values are caught in `FT_Get_Char_Index' */ - /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */ - /* again in this case). To mark character code return values as invalid */ - /* it is sufficient to set the corresponding glyph index return value to */ - /* zero. */ - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap_init( TT_CMap cmap, - FT_Byte* table ) - { - cmap->data = table; - return FT_Err_Ok; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 0 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 0 */ - /* length 2 USHORT table length in bytes */ - /* language 4 USHORT Mac language code */ - /* glyph_ids 6 BYTE[256] array of glyph indices */ - /* 262 */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_0 - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap0_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_UInt length; - - - if ( table + 2 + 2 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 2; /* skip format */ - length = TT_NEXT_USHORT( p ); - - if ( table + length > valid->limit || length < 262 ) - FT_INVALID_TOO_SHORT; - - /* check glyph indices whenever necessary */ - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_UInt n, idx; - - - p = table + 6; - for ( n = 0; n < 256; n++ ) - { - idx = *p++; - if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - } - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap0_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - FT_Byte* table = cmap->data; - - - return char_code < 256 ? table[6 + char_code] : 0; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap0_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - FT_Byte* table = cmap->data; - FT_UInt32 charcode = *pchar_code; - FT_UInt32 result = 0; - FT_UInt gindex = 0; - - - table += 6; /* go to glyph IDs */ - while ( ++charcode < 256 ) - { - gindex = table[charcode]; - if ( gindex != 0 ) - { - result = charcode; - break; - } - } - - *pchar_code = result; - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap0_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 4; - - - cmap_info->format = 0; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap0_class_rec, - sizeof ( TT_CMapRec ), - - (FT_CMap_InitFunc) tt_cmap_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap0_char_index, - (FT_CMap_CharNextFunc) tt_cmap0_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 0, - (TT_CMap_ValidateFunc)tt_cmap0_validate, - (TT_CMap_Info_GetFunc)tt_cmap0_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_0 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 2 *****/ - /***** *****/ - /***** This is used for certain CJK encodings that encode text in a *****/ - /***** mixed 8/16 bits encoding along the following lines. *****/ - /***** *****/ - /***** * Certain byte values correspond to an 8-bit character code *****/ - /***** (typically in the range 0..127 for ASCII compatibility). *****/ - /***** *****/ - /***** * Certain byte values signal the first byte of a 2-byte *****/ - /***** character code (but these values are also valid as the *****/ - /***** second byte of a 2-byte character). *****/ - /***** *****/ - /***** The following charmap lookup and iteration functions all *****/ - /***** assume that the value `charcode' fulfills the following. *****/ - /***** *****/ - /***** - For one byte characters, `charcode' is simply the *****/ - /***** character code. *****/ - /***** *****/ - /***** - For two byte characters, `charcode' is the 2-byte *****/ - /***** character code in big endian format. More precisely: *****/ - /***** *****/ - /***** (charcode >> 8) is the first byte value *****/ - /***** (charcode & 0xFF) is the second byte value *****/ - /***** *****/ - /***** Note that not all values of `charcode' are valid according *****/ - /***** to these rules, and the function moderately checks the *****/ - /***** arguments. *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 2 */ - /* length 2 USHORT table length in bytes */ - /* language 4 USHORT Mac language code */ - /* keys 6 USHORT[256] sub-header keys */ - /* subs 518 SUBHEAD[NSUBS] sub-headers array */ - /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ - /* */ - /* The `keys' table is used to map charcode high-bytes to sub-headers. */ - /* The value of `NSUBS' is the number of sub-headers defined in the */ - /* table and is computed by finding the maximum of the `keys' table. */ - /* */ - /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ - /* table, i.e., it is the corresponding sub-header index multiplied */ - /* by 8. */ - /* */ - /* Each sub-header has the following format. */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* first 0 USHORT first valid low-byte */ - /* count 2 USHORT number of valid low-bytes */ - /* delta 4 SHORT see below */ - /* offset 6 USHORT see below */ - /* */ - /* A sub-header defines, for each high-byte, the range of valid */ - /* low-bytes within the charmap. Note that the range defined by `first' */ - /* and `count' must be completely included in the interval [0..255] */ - /* according to the specification. */ - /* */ - /* If a character code is contained within a given sub-header, then */ - /* mapping it to a glyph index is done as follows. */ - /* */ - /* * The value of `offset' is read. This is a _byte_ distance from the */ - /* location of the `offset' field itself into a slice of the */ - /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). */ - /* */ - /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ - /* no glyph for the charcode. Otherwise, the value of `delta' is */ - /* added to it (modulo 65536) to form a new glyph index. */ - /* */ - /* It is up to the validation routine to check that all offsets fall */ - /* within the glyph IDs table (and not within the `subs' table itself or */ - /* outside of the CMap). */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_2 - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap2_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_UInt length; - - FT_UInt n, max_subs; - FT_Byte* keys; /* keys table */ - FT_Byte* subs; /* sub-headers */ - FT_Byte* glyph_ids; /* glyph ID array */ - - - if ( table + 2 + 2 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 2; /* skip format */ - length = TT_NEXT_USHORT( p ); - - if ( table + length > valid->limit || length < 6 + 512 ) - FT_INVALID_TOO_SHORT; - - keys = table + 6; - - /* parse keys to compute sub-headers count */ - p = keys; - max_subs = 0; - for ( n = 0; n < 256; n++ ) - { - FT_UInt idx = TT_NEXT_USHORT( p ); - - - /* value must be multiple of 8 */ - if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) - FT_INVALID_DATA; - - idx >>= 3; - - if ( idx > max_subs ) - max_subs = idx; - } - - FT_ASSERT( p == table + 518 ); - - subs = p; - glyph_ids = subs + ( max_subs + 1 ) * 8; - if ( glyph_ids > valid->limit ) - FT_INVALID_TOO_SHORT; - - /* parse sub-headers */ - for ( n = 0; n <= max_subs; n++ ) - { - FT_UInt first_code, code_count, offset; - FT_Int delta; - - - first_code = TT_NEXT_USHORT( p ); - code_count = TT_NEXT_USHORT( p ); - delta = TT_NEXT_SHORT( p ); - offset = TT_NEXT_USHORT( p ); - - /* many Dynalab fonts have empty sub-headers */ - if ( code_count == 0 ) - continue; - - /* check range within 0..255 */ - if ( valid->level >= FT_VALIDATE_PARANOID ) - { - if ( first_code >= 256 || first_code + code_count > 256 ) - FT_INVALID_DATA; - } - - /* check offset */ - if ( offset != 0 ) - { - FT_Byte* ids; - - - ids = p - 2 + offset; - if ( ids < glyph_ids || ids + code_count * 2 > table + length ) - FT_INVALID_OFFSET; - - /* check glyph IDs */ - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_Byte* limit = p + code_count * 2; - FT_UInt idx; - - - for ( ; p < limit; ) - { - idx = TT_NEXT_USHORT( p ); - if ( idx != 0 ) - { - idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU; - if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - } - } - } - } - - return FT_Err_Ok; - } - - - /* return sub header corresponding to a given character code */ - /* NULL on invalid charcode */ - static FT_Byte* - tt_cmap2_get_subheader( FT_Byte* table, - FT_UInt32 char_code ) - { - FT_Byte* result = NULL; - - - if ( char_code < 0x10000UL ) - { - FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); - FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); - FT_Byte* p = table + 6; /* keys table */ - FT_Byte* subs = table + 518; /* subheaders table */ - FT_Byte* sub; - - - if ( char_hi == 0 ) - { - /* an 8-bit character code -- we use subHeader 0 in this case */ - /* to test whether the character code is in the charmap */ - /* */ - sub = subs; /* jump to first sub-header */ - - /* check that the sub-header for this byte is 0, which */ - /* indicates that it is really a valid one-byte value */ - /* Otherwise, return 0 */ - /* */ - p += char_lo * 2; - if ( TT_PEEK_USHORT( p ) != 0 ) - goto Exit; - } - else - { - /* a 16-bit character code */ - - /* jump to key entry */ - p += char_hi * 2; - /* jump to sub-header */ - sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) ); - - /* check that the high byte isn't a valid one-byte value */ - if ( sub == subs ) - goto Exit; - } - result = sub; - } - - Exit: - return result; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap2_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - FT_Byte* table = cmap->data; - FT_UInt result = 0; - FT_Byte* subheader; - - - subheader = tt_cmap2_get_subheader( table, char_code ); - if ( subheader ) - { - FT_Byte* p = subheader; - FT_UInt idx = (FT_UInt)(char_code & 0xFF); - FT_UInt start, count; - FT_Int delta; - FT_UInt offset; - - - start = TT_NEXT_USHORT( p ); - count = TT_NEXT_USHORT( p ); - delta = TT_NEXT_SHORT ( p ); - offset = TT_PEEK_USHORT( p ); - - idx -= start; - if ( idx < count && offset != 0 ) - { - p += offset + 2 * idx; - idx = TT_PEEK_USHORT( p ); - - if ( idx != 0 ) - result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU; - } - } - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap2_char_next( TT_CMap cmap, - FT_UInt32 *pcharcode ) - { - FT_Byte* table = cmap->data; - FT_UInt gindex = 0; - FT_UInt32 result = 0; - FT_UInt32 charcode = *pcharcode + 1; - FT_Byte* subheader; - - - while ( charcode < 0x10000UL ) - { - subheader = tt_cmap2_get_subheader( table, charcode ); - if ( subheader ) - { - FT_Byte* p = subheader; - FT_UInt start = TT_NEXT_USHORT( p ); - FT_UInt count = TT_NEXT_USHORT( p ); - FT_Int delta = TT_NEXT_SHORT ( p ); - FT_UInt offset = TT_PEEK_USHORT( p ); - FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); - FT_UInt pos, idx; - - - if ( offset == 0 ) - goto Next_SubHeader; - - if ( char_lo < start ) - { - char_lo = start; - pos = 0; - } - else - pos = (FT_UInt)( char_lo - start ); - - p += offset + pos * 2; - charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo; - - for ( ; pos < count; pos++, charcode++ ) - { - idx = TT_NEXT_USHORT( p ); - - if ( idx != 0 ) - { - gindex = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU; - if ( gindex != 0 ) - { - result = charcode; - goto Exit; - } - } - } - } - - /* jump to next sub-header, i.e. higher byte value */ - Next_SubHeader: - charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; - } - - Exit: - *pcharcode = result; - - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap2_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 4; - - - cmap_info->format = 2; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap2_class_rec, - sizeof ( TT_CMapRec ), - - (FT_CMap_InitFunc) tt_cmap_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap2_char_index, - (FT_CMap_CharNextFunc) tt_cmap2_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 2, - (TT_CMap_ValidateFunc)tt_cmap2_validate, - (TT_CMap_Info_GetFunc)tt_cmap2_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_2 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 4 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 4 */ - /* length 2 USHORT table length */ - /* in bytes */ - /* language 4 USHORT Mac language code */ - /* */ - /* segCountX2 6 USHORT 2*NUM_SEGS */ - /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ - /* entrySelector 10 USHORT LOG_SEGS */ - /* rangeShift 12 USHORT segCountX2 - */ - /* searchRange */ - /* */ - /* endCount 14 USHORT[NUM_SEGS] end charcode for */ - /* each segment; last */ - /* is 0xFFFF */ - /* */ - /* pad 14+NUM_SEGS*2 USHORT padding */ - /* */ - /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ - /* each segment */ - /* */ - /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ - /* segment */ - /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ - /* each segment; can be */ - /* zero */ - /* */ - /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */ - /* ranges */ - /* */ - /* Character codes are modelled by a series of ordered (increasing) */ - /* intervals called segments. Each segment has start and end codes, */ - /* provided by the `startCount' and `endCount' arrays. Segments must */ - /* not overlap, and the last segment should always contain the value */ - /* 0xFFFF for `endCount'. */ - /* */ - /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ - /* ignored (they are traces of over-engineering in the TrueType */ - /* specification). */ - /* */ - /* Each segment also has a signed `delta', as well as an optional offset */ - /* within the `glyphIds' table. */ - /* */ - /* If a segment's idOffset is 0, the glyph index corresponding to any */ - /* charcode within the segment is obtained by adding the value of */ - /* `idDelta' directly to the charcode, modulo 65536. */ - /* */ - /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */ - /* the segment, and the value of `idDelta' is added to it. */ - /* */ - /* */ - /* Finally, note that a lot of fonts contain an invalid last segment, */ - /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */ - /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */ - /* OpenOffice.org). We need special code to deal with them correctly. */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_4 - - typedef struct TT_CMap4Rec_ - { - TT_CMapRec cmap; - FT_UInt32 cur_charcode; /* current charcode */ - FT_UInt cur_gindex; /* current glyph index */ - - FT_UInt num_ranges; - FT_UInt cur_range; - FT_UInt cur_start; - FT_UInt cur_end; - FT_Int cur_delta; - FT_Byte* cur_values; - - } TT_CMap4Rec, *TT_CMap4; - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_init( TT_CMap4 cmap, - FT_Byte* table ) - { - FT_Byte* p; - - - cmap->cmap.data = table; - - p = table + 6; - cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; - cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; - cmap->cur_gindex = 0; - - return FT_Err_Ok; - } - - - static FT_Int - tt_cmap4_set_range( TT_CMap4 cmap, - FT_UInt range_index ) - { - FT_Byte* table = cmap->cmap.data; - FT_Byte* p; - FT_UInt num_ranges = cmap->num_ranges; - - - while ( range_index < num_ranges ) - { - FT_UInt offset; - - - p = table + 14 + range_index * 2; - cmap->cur_end = FT_PEEK_USHORT( p ); - - p += 2 + num_ranges * 2; - cmap->cur_start = FT_PEEK_USHORT( p ); - - p += num_ranges * 2; - cmap->cur_delta = FT_PEEK_SHORT( p ); - - p += num_ranges * 2; - offset = FT_PEEK_USHORT( p ); - - /* some fonts have an incorrect last segment; */ - /* we have to catch it */ - if ( range_index >= num_ranges - 1 && - cmap->cur_start == 0xFFFFU && - cmap->cur_end == 0xFFFFU ) - { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; - FT_Byte* limit = face->cmap_table + face->cmap_size; - - - if ( offset && p + offset + 2 > limit ) - { - cmap->cur_delta = 1; - offset = 0; - } - } - - if ( offset != 0xFFFFU ) - { - cmap->cur_values = offset ? p + offset : NULL; - cmap->cur_range = range_index; - return 0; - } - - /* we skip empty segments */ - range_index++; - } - - return -1; - } - - - /* search the index of the charcode next to cmap->cur_charcode; */ - /* caller should call tt_cmap4_set_range with proper range */ - /* before calling this function */ - /* */ - static void - tt_cmap4_next( TT_CMap4 cmap ) - { - FT_UInt charcode; - - - if ( cmap->cur_charcode >= 0xFFFFUL ) - goto Fail; - - charcode = (FT_UInt)cmap->cur_charcode + 1; - - if ( charcode < cmap->cur_start ) - charcode = cmap->cur_start; - - for ( ;; ) - { - FT_Byte* values = cmap->cur_values; - FT_UInt end = cmap->cur_end; - FT_Int delta = cmap->cur_delta; - - - if ( charcode <= end ) - { - if ( values ) - { - FT_Byte* p = values + 2 * ( charcode - cmap->cur_start ); - - - do - { - FT_UInt gindex = FT_NEXT_USHORT( p ); - - - if ( gindex != 0 ) - { - gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU; - if ( gindex != 0 ) - { - cmap->cur_charcode = charcode; - cmap->cur_gindex = gindex; - return; - } - } - } while ( ++charcode <= end ); - } - else - { - do - { - FT_UInt gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU; - - - if ( gindex != 0 ) - { - cmap->cur_charcode = charcode; - cmap->cur_gindex = gindex; - return; - } - } while ( ++charcode <= end ); - } - } - - /* we need to find another range */ - if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) - break; - - if ( charcode < cmap->cur_start ) - charcode = cmap->cur_start; - } - - Fail: - cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; - cmap->cur_gindex = 0; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_UInt length; - - FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; - FT_UInt num_segs; - FT_Error error = FT_Err_Ok; - - - if ( table + 2 + 2 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 2; /* skip format */ - length = TT_NEXT_USHORT( p ); - - /* in certain fonts, the `length' field is invalid and goes */ - /* out of bound. We try to correct this here... */ - if ( table + length > valid->limit ) - { - if ( valid->level >= FT_VALIDATE_TIGHT ) - FT_INVALID_TOO_SHORT; - - length = (FT_UInt)( valid->limit - table ); - } - - if ( length < 16 ) - FT_INVALID_TOO_SHORT; - - p = table + 6; - num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ - - if ( valid->level >= FT_VALIDATE_PARANOID ) - { - /* check that we have an even value here */ - if ( num_segs & 1 ) - FT_INVALID_DATA; - } - - num_segs /= 2; - - if ( length < 16 + num_segs * 2 * 4 ) - FT_INVALID_TOO_SHORT; - - /* check the search parameters - even though we never use them */ - /* */ - if ( valid->level >= FT_VALIDATE_PARANOID ) - { - /* check the values of `searchRange', `entrySelector', `rangeShift' */ - FT_UInt search_range = TT_NEXT_USHORT( p ); - FT_UInt entry_selector = TT_NEXT_USHORT( p ); - FT_UInt range_shift = TT_NEXT_USHORT( p ); - - - if ( ( search_range | range_shift ) & 1 ) /* must be even values */ - FT_INVALID_DATA; - - search_range /= 2; - range_shift /= 2; - - /* `search range' is the greatest power of 2 that is <= num_segs */ - - if ( search_range > num_segs || - search_range * 2 < num_segs || - search_range + range_shift != num_segs || - search_range != ( 1U << entry_selector ) ) - FT_INVALID_DATA; - } - - ends = table + 14; - starts = table + 16 + num_segs * 2; - deltas = starts + num_segs * 2; - offsets = deltas + num_segs * 2; - glyph_ids = offsets + num_segs * 2; - - /* check last segment; its end count value must be 0xFFFF */ - if ( valid->level >= FT_VALIDATE_PARANOID ) - { - p = ends + ( num_segs - 1 ) * 2; - if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) - FT_INVALID_DATA; - } - - { - FT_UInt start, end, offset, n; - FT_UInt last_start = 0, last_end = 0; - FT_Int delta; - FT_Byte* p_start = starts; - FT_Byte* p_end = ends; - FT_Byte* p_delta = deltas; - FT_Byte* p_offset = offsets; - - - for ( n = 0; n < num_segs; n++ ) - { - p = p_offset; - start = TT_NEXT_USHORT( p_start ); - end = TT_NEXT_USHORT( p_end ); - delta = TT_NEXT_SHORT( p_delta ); - offset = TT_NEXT_USHORT( p_offset ); - - if ( start > end ) - FT_INVALID_DATA; - - /* this test should be performed at default validation level; */ - /* unfortunately, some popular Asian fonts have overlapping */ - /* ranges in their charmaps */ - /* */ - if ( start <= last_end && n > 0 ) - { - if ( valid->level >= FT_VALIDATE_TIGHT ) - FT_INVALID_DATA; - else - { - /* allow overlapping segments, provided their start points */ - /* and end points, respectively, are in ascending order */ - /* */ - if ( last_start > start || last_end > end ) - error |= TT_CMAP_FLAG_UNSORTED; - else - error |= TT_CMAP_FLAG_OVERLAPPING; - } - } - - if ( offset && offset != 0xFFFFU ) - { - p += offset; /* start of glyph ID array */ - - /* check that we point within the glyph IDs table only */ - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - if ( p < glyph_ids || - p + ( end - start + 1 ) * 2 > table + length ) - FT_INVALID_DATA; - } - /* Some fonts handle the last segment incorrectly. In */ - /* theory, 0xFFFF might point to an ordinary glyph -- */ - /* a cmap 4 is versatile and could be used for any */ - /* encoding, not only Unicode. However, reality shows */ - /* that far too many fonts are sloppy and incorrectly */ - /* set all fields but `start' and `end' for the last */ - /* segment if it contains only a single character. */ - /* */ - /* We thus omit the test here, delaying it to the */ - /* routines that actually access the cmap. */ - else if ( n != num_segs - 1 || - !( start == 0xFFFFU && end == 0xFFFFU ) ) - { - if ( p < glyph_ids || - p + ( end - start + 1 ) * 2 > valid->limit ) - FT_INVALID_DATA; - } - - /* check glyph indices within the segment range */ - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_UInt i, idx; - - - for ( i = start; i < end; i++ ) - { - idx = FT_NEXT_USHORT( p ); - if ( idx != 0 ) - { - idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU; - - if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - } - } - } - else if ( offset == 0xFFFFU ) - { - /* some fonts (erroneously?) use a range offset of 0xFFFF */ - /* to mean missing glyph in cmap table */ - /* */ - if ( valid->level >= FT_VALIDATE_PARANOID || - n != num_segs - 1 || - !( start == 0xFFFFU && end == 0xFFFFU ) ) - FT_INVALID_DATA; - } - - last_start = start; - last_end = end; - } - } - - return error; - } - - - static FT_UInt - tt_cmap4_char_map_linear( TT_CMap cmap, - FT_UInt32* pcharcode, - FT_Bool next ) - { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; - FT_Byte* limit = face->cmap_table + face->cmap_size; - - - FT_UInt num_segs2, start, end, offset; - FT_Int delta; - FT_UInt i, num_segs; - FT_UInt32 charcode = *pcharcode; - FT_UInt gindex = 0; - FT_Byte* p; - FT_Byte* q; - - - p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); - - num_segs = num_segs2 >> 1; - - if ( !num_segs ) - return 0; - - if ( next ) - charcode++; - - if ( charcode > 0xFFFFU ) - return 0; - - /* linear search */ - p = cmap->data + 14; /* ends table */ - q = cmap->data + 16 + num_segs2; /* starts table */ - - for ( i = 0; i < num_segs; i++ ) - { - end = TT_NEXT_USHORT( p ); - start = TT_NEXT_USHORT( q ); - - if ( charcode < start ) - { - if ( next ) - charcode = start; - else - break; - } - - Again: - if ( charcode <= end ) - { - FT_Byte* r; - - - r = q - 2 + num_segs2; - delta = TT_PEEK_SHORT( r ); - r += num_segs2; - offset = TT_PEEK_USHORT( r ); - - /* some fonts have an incorrect last segment; */ - /* we have to catch it */ - if ( i >= num_segs - 1 && - start == 0xFFFFU && end == 0xFFFFU ) - { - if ( offset && r + offset + 2 > limit ) - { - delta = 1; - offset = 0; - } - } - - if ( offset == 0xFFFFU ) - continue; - - if ( offset ) - { - r += offset + ( charcode - start ) * 2; - - /* if r > limit, the whole segment is invalid */ - if ( next && r > limit ) - continue; - - gindex = TT_PEEK_USHORT( r ); - if ( gindex ) - { - gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU; - if ( gindex >= (FT_UInt)face->root.num_glyphs ) - gindex = 0; - } - } - else - { - gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU; - - if ( next && gindex >= (FT_UInt)face->root.num_glyphs ) - { - /* we have an invalid glyph index; if there is an overflow, */ - /* we can adjust `charcode', otherwise the whole segment is */ - /* invalid */ - gindex = 0; - - if ( (FT_Int)charcode + delta < 0 && - (FT_Int)end + delta >= 0 ) - charcode = (FT_UInt)( -delta ); - - else if ( (FT_Int)charcode + delta < 0x10000L && - (FT_Int)end + delta >= 0x10000L ) - charcode = (FT_UInt)( 0x10000L - delta ); - - else - continue; - } - } - - if ( next && !gindex ) - { - if ( charcode >= 0xFFFFU ) - break; - - charcode++; - goto Again; - } - - break; - } - } - - if ( next ) - *pcharcode = charcode; - - return gindex; - } - - - static FT_UInt - tt_cmap4_char_map_binary( TT_CMap cmap, - FT_UInt32* pcharcode, - FT_Bool next ) - { - FT_UInt num_segs2, start, end, offset; - FT_Int delta; - FT_UInt max, min, mid, num_segs; - FT_UInt charcode = (FT_UInt)*pcharcode; - FT_UInt gindex = 0; - FT_Byte* p; - - - p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); - - if ( !num_segs2 ) - return 0; - - num_segs = num_segs2 >> 1; - - /* make compiler happy */ - mid = num_segs; - end = 0xFFFFU; - - if ( next ) - charcode++; - - min = 0; - max = num_segs; - - /* binary search */ - while ( min < max ) - { - mid = ( min + max ) >> 1; - p = cmap->data + 14 + mid * 2; - end = TT_PEEK_USHORT( p ); - p += 2 + num_segs2; - start = TT_PEEK_USHORT( p ); - - if ( charcode < start ) - max = mid; - else if ( charcode > end ) - min = mid + 1; - else - { - p += num_segs2; - delta = TT_PEEK_SHORT( p ); - p += num_segs2; - offset = TT_PEEK_USHORT( p ); - - /* some fonts have an incorrect last segment; */ - /* we have to catch it */ - if ( mid >= num_segs - 1 && - start == 0xFFFFU && end == 0xFFFFU ) - { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; - FT_Byte* limit = face->cmap_table + face->cmap_size; - - - if ( offset && p + offset + 2 > limit ) - { - delta = 1; - offset = 0; - } - } - - /* search the first segment containing `charcode' */ - if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) - { - FT_UInt i; - - - /* call the current segment `max' */ - max = mid; - - if ( offset == 0xFFFFU ) - mid = max + 1; - - /* search in segments before the current segment */ - for ( i = max ; i > 0; i-- ) - { - FT_UInt prev_end; - FT_Byte* old_p; - - - old_p = p; - p = cmap->data + 14 + ( i - 1 ) * 2; - prev_end = TT_PEEK_USHORT( p ); - - if ( charcode > prev_end ) - { - p = old_p; - break; - } - - end = prev_end; - p += 2 + num_segs2; - start = TT_PEEK_USHORT( p ); - p += num_segs2; - delta = TT_PEEK_SHORT( p ); - p += num_segs2; - offset = TT_PEEK_USHORT( p ); - - if ( offset != 0xFFFFU ) - mid = i - 1; - } - - /* no luck */ - if ( mid == max + 1 ) - { - if ( i != max ) - { - p = cmap->data + 14 + max * 2; - end = TT_PEEK_USHORT( p ); - p += 2 + num_segs2; - start = TT_PEEK_USHORT( p ); - p += num_segs2; - delta = TT_PEEK_SHORT( p ); - p += num_segs2; - offset = TT_PEEK_USHORT( p ); - } - - mid = max; - - /* search in segments after the current segment */ - for ( i = max + 1; i < num_segs; i++ ) - { - FT_UInt next_end, next_start; - - - p = cmap->data + 14 + i * 2; - next_end = TT_PEEK_USHORT( p ); - p += 2 + num_segs2; - next_start = TT_PEEK_USHORT( p ); - - if ( charcode < next_start ) - break; - - end = next_end; - start = next_start; - p += num_segs2; - delta = TT_PEEK_SHORT( p ); - p += num_segs2; - offset = TT_PEEK_USHORT( p ); - - if ( offset != 0xFFFFU ) - mid = i; - } - i--; - - /* still no luck */ - if ( mid == max ) - { - mid = i; - - break; - } - } - - /* end, start, delta, and offset are for the i'th segment */ - if ( mid != i ) - { - p = cmap->data + 14 + mid * 2; - end = TT_PEEK_USHORT( p ); - p += 2 + num_segs2; - start = TT_PEEK_USHORT( p ); - p += num_segs2; - delta = TT_PEEK_SHORT( p ); - p += num_segs2; - offset = TT_PEEK_USHORT( p ); - } - } - else - { - if ( offset == 0xFFFFU ) - break; - } - - if ( offset ) - { - p += offset + ( charcode - start ) * 2; - gindex = TT_PEEK_USHORT( p ); - if ( gindex != 0 ) - gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU; - } - else - gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU; - - break; - } - } - - if ( next ) - { - TT_CMap4 cmap4 = (TT_CMap4)cmap; - - - /* if `charcode' is not in any segment, then `mid' is */ - /* the segment nearest to `charcode' */ - - if ( charcode > end ) - { - mid++; - if ( mid == num_segs ) - return 0; - } - - if ( tt_cmap4_set_range( cmap4, mid ) ) - { - if ( gindex ) - *pcharcode = charcode; - } - else - { - cmap4->cur_charcode = charcode; - - if ( gindex ) - cmap4->cur_gindex = gindex; - else - { - cmap4->cur_charcode = charcode; - tt_cmap4_next( cmap4 ); - gindex = cmap4->cur_gindex; - } - - if ( gindex ) - *pcharcode = cmap4->cur_charcode; - } - } - - return gindex; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap4_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - if ( char_code >= 0x10000UL ) - return 0; - - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); - else - return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap4_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - FT_UInt gindex; - - - if ( *pchar_code >= 0xFFFFU ) - return 0; - - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); - else - { - TT_CMap4 cmap4 = (TT_CMap4)cmap; - - - /* no need to search */ - if ( *pchar_code == cmap4->cur_charcode ) - { - tt_cmap4_next( cmap4 ); - gindex = cmap4->cur_gindex; - if ( gindex ) - *pchar_code = cmap4->cur_charcode; - } - else - gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); - } - - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 4; - - - cmap_info->format = 4; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap4_class_rec, - sizeof ( TT_CMap4Rec ), - (FT_CMap_InitFunc) tt_cmap4_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap4_char_index, - (FT_CMap_CharNextFunc) tt_cmap4_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 4, - (TT_CMap_ValidateFunc)tt_cmap4_validate, - (TT_CMap_Info_GetFunc)tt_cmap4_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_4 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 6 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 6 */ - /* length 2 USHORT table length in bytes */ - /* language 4 USHORT Mac language code */ - /* */ - /* first 6 USHORT first segment code */ - /* count 8 USHORT segment size in chars */ - /* glyphIds 10 USHORT[count] glyph IDs */ - /* */ - /* A very simplified segment mapping. */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_6 - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap6_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_UInt length, count; - - - if ( table + 10 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 2; - length = TT_NEXT_USHORT( p ); - - p = table + 8; /* skip language and start index */ - count = TT_NEXT_USHORT( p ); - - if ( table + length > valid->limit || length < 10 + count * 2 ) - FT_INVALID_TOO_SHORT; - - /* check glyph indices */ - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_UInt gindex; - - - for ( ; count > 0; count-- ) - { - gindex = TT_NEXT_USHORT( p ); - if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - } - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap6_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - FT_Byte* table = cmap->data; - FT_UInt result = 0; - FT_Byte* p = table + 6; - FT_UInt start = TT_NEXT_USHORT( p ); - FT_UInt count = TT_NEXT_USHORT( p ); - FT_UInt idx = (FT_UInt)( char_code - start ); - - - if ( idx < count ) - { - p += 2 * idx; - result = TT_PEEK_USHORT( p ); - } - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap6_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - FT_Byte* table = cmap->data; - FT_UInt32 result = 0; - FT_UInt32 char_code = *pchar_code + 1; - FT_UInt gindex = 0; - - FT_Byte* p = table + 6; - FT_UInt start = TT_NEXT_USHORT( p ); - FT_UInt count = TT_NEXT_USHORT( p ); - FT_UInt idx; - - - if ( char_code >= 0x10000UL ) - return 0; - - if ( char_code < start ) - char_code = start; - - idx = (FT_UInt)( char_code - start ); - p += 2 * idx; - - for ( ; idx < count; idx++ ) - { - gindex = TT_NEXT_USHORT( p ); - if ( gindex != 0 ) - { - result = char_code; - break; - } - - if ( char_code >= 0xFFFFU ) - return 0; - - char_code++; - } - - *pchar_code = result; - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap6_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 4; - - - cmap_info->format = 6; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap6_class_rec, - sizeof ( TT_CMapRec ), - - (FT_CMap_InitFunc) tt_cmap_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap6_char_index, - (FT_CMap_CharNextFunc) tt_cmap6_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 6, - (TT_CMap_ValidateFunc)tt_cmap6_validate, - (TT_CMap_Info_GetFunc)tt_cmap6_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_6 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 8 *****/ - /***** *****/ - /***** It is hard to completely understand what the OpenType spec *****/ - /***** says about this format, but here is my conclusion. *****/ - /***** *****/ - /***** The purpose of this format is to easily map UTF-16 text to *****/ - /***** glyph indices. Basically, the `char_code' must be in one of *****/ - /***** the following formats. *****/ - /***** *****/ - /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ - /***** Area (i.e. U+D800-U+DFFF). *****/ - /***** *****/ - /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ - /***** `char_code = (char_hi << 16) | char_lo', then both *****/ - /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ - /***** Area. *****/ - /***** *****/ - /***** The `is32' table embedded in the charmap indicates whether a *****/ - /***** given 16-bit value is in the surrogates area or not. *****/ - /***** *****/ - /***** So, for any given `char_code', we can assert the following. *****/ - /***** *****/ - /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ - /***** *****/ - /***** If `char_hi != 0' then we must have both *****/ - /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 8 */ - /* reserved 2 USHORT reserved */ - /* length 4 ULONG length in bytes */ - /* language 8 ULONG Mac language code */ - /* is32 12 BYTE[8192] 32-bitness bitmap */ - /* count 8204 ULONG number of groups */ - /* */ - /* This header is followed by `count' groups of the following format: */ - /* */ - /* start 0 ULONG first charcode */ - /* end 4 ULONG last charcode */ - /* startId 8 ULONG start glyph ID for the group */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_8 - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap8_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p = table + 4; - FT_Byte* is32; - FT_UInt32 length; - FT_UInt32 num_groups; - - - if ( table + 16 + 8192 > valid->limit ) - FT_INVALID_TOO_SHORT; - - length = TT_NEXT_ULONG( p ); - if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 ) - FT_INVALID_TOO_SHORT; - - is32 = table + 12; - p = is32 + 8192; /* skip `is32' array */ - num_groups = TT_NEXT_ULONG( p ); - - /* p + num_groups * 12 > valid->limit ? */ - if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 ) - FT_INVALID_TOO_SHORT; - - /* check groups, they must be in increasing order */ - { - FT_UInt32 n, start, end, start_id, count, last = 0; - - - for ( n = 0; n < num_groups; n++ ) - { - FT_UInt hi, lo; - - - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - start_id = TT_NEXT_ULONG( p ); - - if ( start > end ) - FT_INVALID_DATA; - - if ( n > 0 && start <= last ) - FT_INVALID_DATA; - - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_UInt32 d = end - start; - - - /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */ - if ( d > TT_VALID_GLYPH_COUNT( valid ) || - start_id >= TT_VALID_GLYPH_COUNT( valid ) - d ) - FT_INVALID_GLYPH_ID; - - count = (FT_UInt32)( end - start + 1 ); - - if ( start & ~0xFFFFU ) - { - /* start_hi != 0; check that is32[i] is 1 for each i in */ - /* the `hi' and `lo' of the range [start..end] */ - for ( ; count > 0; count--, start++ ) - { - hi = (FT_UInt)( start >> 16 ); - lo = (FT_UInt)( start & 0xFFFFU ); - - if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) - FT_INVALID_DATA; - - if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) - FT_INVALID_DATA; - } - } - else - { - /* start_hi == 0; check that is32[i] is 0 for each i in */ - /* the range [start..end] */ - - /* end_hi cannot be != 0! */ - if ( end & ~0xFFFFU ) - FT_INVALID_DATA; - - for ( ; count > 0; count--, start++ ) - { - lo = (FT_UInt)( start & 0xFFFFU ); - - if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) - FT_INVALID_DATA; - } - } - } - - last = end; - } - } - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap8_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - FT_Byte* table = cmap->data; - FT_UInt result = 0; - FT_Byte* p = table + 8204; - FT_UInt32 num_groups = TT_NEXT_ULONG( p ); - FT_UInt32 start, end, start_id; - - - for ( ; num_groups > 0; num_groups-- ) - { - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - start_id = TT_NEXT_ULONG( p ); - - if ( char_code < start ) - break; - - if ( char_code <= end ) - { - if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) - return 0; - - result = (FT_UInt)( start_id + ( char_code - start ) ); - break; - } - } - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap8_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - FT_Face face = cmap->cmap.charmap.face; - FT_UInt32 result = 0; - FT_UInt32 char_code; - FT_UInt gindex = 0; - FT_Byte* table = cmap->data; - FT_Byte* p = table + 8204; - FT_UInt32 num_groups = TT_NEXT_ULONG( p ); - FT_UInt32 start, end, start_id; - - - if ( *pchar_code >= 0xFFFFFFFFUL ) - return 0; - - char_code = *pchar_code + 1; - - p = table + 8208; - - for ( ; num_groups > 0; num_groups-- ) - { - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - start_id = TT_NEXT_ULONG( p ); - - if ( char_code < start ) - char_code = start; - - Again: - if ( char_code <= end ) - { - /* ignore invalid group */ - if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) - continue; - - gindex = (FT_UInt)( start_id + ( char_code - start ) ); - - /* does first element of group point to `.notdef' glyph? */ - if ( gindex == 0 ) - { - if ( char_code >= 0xFFFFFFFFUL ) - break; - - char_code++; - goto Again; - } - - /* if `gindex' is invalid, the remaining values */ - /* in this group are invalid, too */ - if ( gindex >= (FT_UInt)face->num_glyphs ) - continue; - - result = char_code; - break; - } - } - - *pchar_code = result; - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap8_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 8; - - - cmap_info->format = 8; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap8_class_rec, - sizeof ( TT_CMapRec ), - - (FT_CMap_InitFunc) tt_cmap_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap8_char_index, - (FT_CMap_CharNextFunc) tt_cmap8_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 8, - (TT_CMap_ValidateFunc)tt_cmap8_validate, - (TT_CMap_Info_GetFunc)tt_cmap8_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_8 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 10 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 10 */ - /* reserved 2 USHORT reserved */ - /* length 4 ULONG length in bytes */ - /* language 8 ULONG Mac language code */ - /* */ - /* start 12 ULONG first char in range */ - /* count 16 ULONG number of chars in range */ - /* glyphIds 20 USHORT[count] glyph indices covered */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_10 - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap10_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p = table + 4; - FT_ULong length, count; - - - if ( table + 20 > valid->limit ) - FT_INVALID_TOO_SHORT; - - length = TT_NEXT_ULONG( p ); - p = table + 16; - count = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || - /* length < 20 + count * 2 ? */ - length < 20 || - ( length - 20 ) / 2 < count ) - FT_INVALID_TOO_SHORT; - - /* check glyph indices */ - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_UInt gindex; - - - for ( ; count > 0; count-- ) - { - gindex = TT_NEXT_USHORT( p ); - if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - } - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap10_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - FT_Byte* table = cmap->data; - FT_UInt result = 0; - FT_Byte* p = table + 12; - FT_UInt32 start = TT_NEXT_ULONG( p ); - FT_UInt32 count = TT_NEXT_ULONG( p ); - FT_UInt32 idx; - - - if ( char_code < start ) - return 0; - - idx = char_code - start; - - if ( idx < count ) - { - p += 2 * idx; - result = TT_PEEK_USHORT( p ); - } - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap10_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - FT_Byte* table = cmap->data; - FT_UInt32 char_code; - FT_UInt gindex = 0; - FT_Byte* p = table + 12; - FT_UInt32 start = TT_NEXT_ULONG( p ); - FT_UInt32 count = TT_NEXT_ULONG( p ); - FT_UInt32 idx; - - - if ( *pchar_code >= 0xFFFFFFFFUL ) - return 0; - - char_code = *pchar_code + 1; - - if ( char_code < start ) - char_code = start; - - idx = char_code - start; - p += 2 * idx; - - for ( ; idx < count; idx++ ) - { - gindex = TT_NEXT_USHORT( p ); - if ( gindex != 0 ) - break; - - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - - *pchar_code = char_code; - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap10_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 8; - - - cmap_info->format = 10; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap10_class_rec, - sizeof ( TT_CMapRec ), - - (FT_CMap_InitFunc) tt_cmap_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap10_char_index, - (FT_CMap_CharNextFunc) tt_cmap10_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 10, - (TT_CMap_ValidateFunc)tt_cmap10_validate, - (TT_CMap_Info_GetFunc)tt_cmap10_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_10 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 12 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 12 */ - /* reserved 2 USHORT reserved */ - /* length 4 ULONG length in bytes */ - /* language 8 ULONG Mac language code */ - /* count 12 ULONG number of groups */ - /* 16 */ - /* */ - /* This header is followed by `count' groups of the following format: */ - /* */ - /* start 0 ULONG first charcode */ - /* end 4 ULONG last charcode */ - /* startId 8 ULONG start glyph ID for the group */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_12 - - typedef struct TT_CMap12Rec_ - { - TT_CMapRec cmap; - FT_Bool valid; - FT_ULong cur_charcode; - FT_UInt cur_gindex; - FT_ULong cur_group; - FT_ULong num_groups; - - } TT_CMap12Rec, *TT_CMap12; - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_init( TT_CMap12 cmap, - FT_Byte* table ) - { - cmap->cmap.data = table; - - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - - cmap->valid = 0; - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_ULong length; - FT_ULong num_groups; - - - if ( table + 16 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 4; - length = TT_NEXT_ULONG( p ); - - p = table + 12; - num_groups = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || - /* length < 16 + 12 * num_groups ? */ - length < 16 || - ( length - 16 ) / 12 < num_groups ) - FT_INVALID_TOO_SHORT; - - /* check groups, they must be in increasing order */ - { - FT_ULong n, start, end, start_id, last = 0; - - - for ( n = 0; n < num_groups; n++ ) - { - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - start_id = TT_NEXT_ULONG( p ); - - if ( start > end ) - FT_INVALID_DATA; - - if ( n > 0 && start <= last ) - FT_INVALID_DATA; - - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - FT_UInt32 d = end - start; - - - /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */ - if ( d > TT_VALID_GLYPH_COUNT( valid ) || - start_id >= TT_VALID_GLYPH_COUNT( valid ) - d ) - FT_INVALID_GLYPH_ID; - } - - last = end; - } - } - - return FT_Err_Ok; - } - - - /* search the index of the charcode next to cmap->cur_charcode */ - /* cmap->cur_group should be set up properly by caller */ - /* */ - static void - tt_cmap12_next( TT_CMap12 cmap ) - { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, start_id, char_code; - FT_ULong n; - FT_UInt gindex; - - - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; - - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) - { - p = cmap->cmap.data + 16 + 12 * n; - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - start_id = TT_PEEK_ULONG( p ); - - if ( char_code < start ) - char_code = start; - - Again: - if ( char_code <= end ) - { - /* ignore invalid group */ - if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) - continue; - - gindex = (FT_UInt)( start_id + ( char_code - start ) ); - - /* does first element of group point to `.notdef' glyph? */ - if ( gindex == 0 ) - { - if ( char_code >= 0xFFFFFFFFUL ) - goto Fail; - - char_code++; - goto Again; - } - - /* if `gindex' is invalid, the remaining values */ - /* in this group are invalid, too */ - if ( gindex >= (FT_UInt)face->num_glyphs ) - continue; - - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; - - return; - } - } - - Fail: - cmap->valid = 0; - } - - - static FT_UInt - tt_cmap12_char_map_binary( TT_CMap cmap, - FT_UInt32* pchar_code, - FT_Bool next ) - { - FT_UInt gindex = 0; - FT_Byte* p = cmap->data + 12; - FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; - FT_UInt32 start, end, start_id; - FT_UInt32 max, min, mid; - - - if ( !num_groups ) - return 0; - - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - - min = 0; - max = num_groups; - - /* binary search */ - while ( min < max ) - { - mid = ( min + max ) >> 1; - p = cmap->data + 16 + 12 * mid; - - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - - if ( char_code < start ) - max = mid; - else if ( char_code > end ) - min = mid + 1; - else - { - start_id = TT_PEEK_ULONG( p ); - - /* reject invalid glyph index */ - if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) - gindex = 0; - else - gindex = (FT_UInt)( start_id + ( char_code - start ) ); - break; - } - } - - if ( next ) - { - FT_Face face = cmap->cmap.charmap.face; - TT_CMap12 cmap12 = (TT_CMap12)cmap; - - - /* if `char_code' is not in any group, then `mid' is */ - /* the group nearest to `char_code' */ - - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } - - cmap12->valid = 1; - cmap12->cur_charcode = char_code; - cmap12->cur_group = mid; - - if ( gindex >= (FT_UInt)face->num_glyphs ) - gindex = 0; - - if ( !gindex ) - { - tt_cmap12_next( cmap12 ); - - if ( cmap12->valid ) - gindex = cmap12->cur_gindex; - } - else - cmap12->cur_gindex = gindex; - - *pchar_code = cmap12->cur_charcode; - } - - return gindex; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap12_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap12_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - TT_CMap12 cmap12 = (TT_CMap12)cmap; - FT_UInt gindex; - - - /* no need to search */ - if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) - { - tt_cmap12_next( cmap12 ); - if ( cmap12->valid ) - { - gindex = cmap12->cur_gindex; - *pchar_code = (FT_UInt32)cmap12->cur_charcode; - } - else - gindex = 0; - } - else - gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); - - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 8; - - - cmap_info->format = 12; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap12_class_rec, - sizeof ( TT_CMap12Rec ), - - (FT_CMap_InitFunc) tt_cmap12_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap12_char_index, - (FT_CMap_CharNextFunc) tt_cmap12_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 12, - (TT_CMap_ValidateFunc)tt_cmap12_validate, - (TT_CMap_Info_GetFunc)tt_cmap12_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_12 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 13 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 13 */ - /* reserved 2 USHORT reserved */ - /* length 4 ULONG length in bytes */ - /* language 8 ULONG Mac language code */ - /* count 12 ULONG number of groups */ - /* 16 */ - /* */ - /* This header is followed by `count' groups of the following format: */ - /* */ - /* start 0 ULONG first charcode */ - /* end 4 ULONG last charcode */ - /* glyphId 8 ULONG glyph ID for the whole group */ - /* */ - -#ifdef TT_CONFIG_CMAP_FORMAT_13 - - typedef struct TT_CMap13Rec_ - { - TT_CMapRec cmap; - FT_Bool valid; - FT_ULong cur_charcode; - FT_UInt cur_gindex; - FT_ULong cur_group; - FT_ULong num_groups; - - } TT_CMap13Rec, *TT_CMap13; - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_init( TT_CMap13 cmap, - FT_Byte* table ) - { - cmap->cmap.data = table; - - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - - cmap->valid = 0; - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_ULong length; - FT_ULong num_groups; - - - if ( table + 16 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 4; - length = TT_NEXT_ULONG( p ); - - p = table + 12; - num_groups = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || - /* length < 16 + 12 * num_groups ? */ - length < 16 || - ( length - 16 ) / 12 < num_groups ) - FT_INVALID_TOO_SHORT; - - /* check groups, they must be in increasing order */ - { - FT_ULong n, start, end, glyph_id, last = 0; - - - for ( n = 0; n < num_groups; n++ ) - { - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - glyph_id = TT_NEXT_ULONG( p ); - - if ( start > end ) - FT_INVALID_DATA; - - if ( n > 0 && start <= last ) - FT_INVALID_DATA; - - if ( valid->level >= FT_VALIDATE_TIGHT ) - { - if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - - last = end; - } - } - - return FT_Err_Ok; - } - - - /* search the index of the charcode next to cmap->cur_charcode */ - /* cmap->cur_group should be set up properly by caller */ - /* */ - static void - tt_cmap13_next( TT_CMap13 cmap ) - { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, glyph_id, char_code; - FT_ULong n; - FT_UInt gindex; - - - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; - - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) - { - p = cmap->cmap.data + 16 + 12 * n; - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - glyph_id = TT_PEEK_ULONG( p ); - - if ( char_code < start ) - char_code = start; - - if ( char_code <= end ) - { - gindex = (FT_UInt)glyph_id; - - if ( gindex && gindex < (FT_UInt)face->num_glyphs ) - { - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; - - return; - } - } - } - - Fail: - cmap->valid = 0; - } - - - static FT_UInt - tt_cmap13_char_map_binary( TT_CMap cmap, - FT_UInt32* pchar_code, - FT_Bool next ) - { - FT_UInt gindex = 0; - FT_Byte* p = cmap->data + 12; - FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; - FT_UInt32 start, end; - FT_UInt32 max, min, mid; - - - if ( !num_groups ) - return 0; - - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - - min = 0; - max = num_groups; - - /* binary search */ - while ( min < max ) - { - mid = ( min + max ) >> 1; - p = cmap->data + 16 + 12 * mid; - - start = TT_NEXT_ULONG( p ); - end = TT_NEXT_ULONG( p ); - - if ( char_code < start ) - max = mid; - else if ( char_code > end ) - min = mid + 1; - else - { - gindex = (FT_UInt)TT_PEEK_ULONG( p ); - - break; - } - } - - if ( next ) - { - FT_Face face = cmap->cmap.charmap.face; - TT_CMap13 cmap13 = (TT_CMap13)cmap; - - - /* if `char_code' is not in any group, then `mid' is */ - /* the group nearest to `char_code' */ - - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } - - cmap13->valid = 1; - cmap13->cur_charcode = char_code; - cmap13->cur_group = mid; - - if ( gindex >= (FT_UInt)face->num_glyphs ) - gindex = 0; - - if ( !gindex ) - { - tt_cmap13_next( cmap13 ); - - if ( cmap13->valid ) - gindex = cmap13->cur_gindex; - } - else - cmap13->cur_gindex = gindex; - - *pchar_code = cmap13->cur_charcode; - } - - return gindex; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap13_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap13_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - TT_CMap13 cmap13 = (TT_CMap13)cmap; - FT_UInt gindex; - - - /* no need to search */ - if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) - { - tt_cmap13_next( cmap13 ); - if ( cmap13->valid ) - { - gindex = cmap13->cur_gindex; - *pchar_code = cmap13->cur_charcode; - } - else - gindex = 0; - } - else - gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); - - return gindex; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_Byte* p = cmap->data + 8; - - - cmap_info->format = 13; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); - - return FT_Err_Ok; - } - - - FT_DEFINE_TT_CMAP( - tt_cmap13_class_rec, - sizeof ( TT_CMap13Rec ), - - (FT_CMap_InitFunc) tt_cmap13_init, - (FT_CMap_DoneFunc) NULL, - (FT_CMap_CharIndexFunc)tt_cmap13_char_index, - (FT_CMap_CharNextFunc) tt_cmap13_char_next, - - NULL, - NULL, - NULL, - NULL, - NULL, - - 13, - (TT_CMap_ValidateFunc)tt_cmap13_validate, - (TT_CMap_Info_GetFunc)tt_cmap13_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_13 */ - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** FORMAT 14 *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* TABLE OVERVIEW */ - /* -------------- */ - /* */ - /* NAME OFFSET TYPE DESCRIPTION */ - /* */ - /* format 0 USHORT must be 14 */ - /* length 2 ULONG table length in bytes */ - /* numSelector 6 ULONG number of variation sel. records */ - /* */ - /* Followed by numSelector records, each of which looks like */ - /* */ - /* varSelector 0 UINT24 Unicode codepoint of sel. */ - /* defaultOff 3 ULONG offset to a default UVS table */ - /* describing any variants to be found in */ - /* the normal Unicode subtable. */ - /* nonDefOff 7 ULONG offset to a non-default UVS table */ - /* describing any variants not in the */ - /* standard cmap, with GIDs here */ - /* (either offset may be 0 NULL) */ - /* */ - /* Selectors are sorted by code point. */ - /* */ - /* A default Unicode Variation Selector (UVS) subtable is just a list of */ - /* ranges of code points which are to be found in the standard cmap. No */ - /* glyph IDs (GIDs) here. */ - /* */ - /* numRanges 0 ULONG number of ranges following */ - /* */ - /* A range looks like */ - /* */ - /* uniStart 0 UINT24 code point of the first character in */ - /* this range */ - /* additionalCnt 3 UBYTE count of additional characters in this */ - /* range (zero means a range of a single */ - /* character) */ - /* */ - /* Ranges are sorted by `uniStart'. */ - /* */ - /* A non-default Unicode Variation Selector (UVS) subtable is a list of */ - /* mappings from codepoint to GID. */ - /* */ - /* numMappings 0 ULONG number of mappings */ - /* */ - /* A range looks like */ - /* */ - /* uniStart 0 UINT24 code point of the first character in */ - /* this range */ - /* GID 3 USHORT and its GID */ - /* */ - /* Ranges are sorted by `uniStart'. */ - -#ifdef TT_CONFIG_CMAP_FORMAT_14 - - typedef struct TT_CMap14Rec_ - { - TT_CMapRec cmap; - FT_ULong num_selectors; - - /* This array is used to store the results of various - * cmap 14 query functions. The data is overwritten - * on each call to these functions. - */ - FT_UInt32 max_results; - FT_UInt32* results; - FT_Memory memory; - - } TT_CMap14Rec, *TT_CMap14; - - - FT_CALLBACK_DEF( void ) - tt_cmap14_done( TT_CMap14 cmap ) - { - FT_Memory memory = cmap->memory; - - - cmap->max_results = 0; - if ( memory != NULL && cmap->results != NULL ) - FT_FREE( cmap->results ); - } - - - static FT_Error - tt_cmap14_ensure( TT_CMap14 cmap, - FT_UInt32 num_results, - FT_Memory memory ) - { - FT_UInt32 old_max = cmap->max_results; - FT_Error error = FT_Err_Ok; - - - if ( num_results > cmap->max_results ) - { - cmap->memory = memory; - - if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) ) - return error; - - cmap->max_results = num_results; - } - - return error; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_init( TT_CMap14 cmap, - FT_Byte* table ) - { - cmap->cmap.data = table; - - table += 6; - cmap->num_selectors = FT_PEEK_ULONG( table ); - cmap->max_results = 0; - cmap->results = NULL; - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_validate( FT_Byte* table, - FT_Validator valid ) - { - FT_Byte* p; - FT_ULong length; - FT_ULong num_selectors; - - - if ( table + 2 + 4 + 4 > valid->limit ) - FT_INVALID_TOO_SHORT; - - p = table + 2; - length = TT_NEXT_ULONG( p ); - num_selectors = TT_NEXT_ULONG( p ); - - if ( length > (FT_ULong)( valid->limit - table ) || - /* length < 10 + 11 * num_selectors ? */ - length < 10 || - ( length - 10 ) / 11 < num_selectors ) - FT_INVALID_TOO_SHORT; - - /* check selectors, they must be in increasing order */ - { - /* we start lastVarSel at 1 because a variant selector value of 0 - * isn't valid. - */ - FT_ULong n, lastVarSel = 1; - - - for ( n = 0; n < num_selectors; n++ ) - { - FT_ULong varSel = TT_NEXT_UINT24( p ); - FT_ULong defOff = TT_NEXT_ULONG( p ); - FT_ULong nondefOff = TT_NEXT_ULONG( p ); - - - if ( defOff >= length || nondefOff >= length ) - FT_INVALID_TOO_SHORT; - - if ( varSel < lastVarSel ) - FT_INVALID_DATA; - - lastVarSel = varSel + 1; - - /* check the default table (these glyphs should be reached */ - /* through the normal Unicode cmap, no GIDs, just check order) */ - if ( defOff != 0 ) - { - FT_Byte* defp = table + defOff; - FT_ULong numRanges = TT_NEXT_ULONG( defp ); - FT_ULong i; - FT_ULong lastBase = 0; - - - /* defp + numRanges * 4 > valid->limit ? */ - if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 ) - FT_INVALID_TOO_SHORT; - - for ( i = 0; i < numRanges; ++i ) - { - FT_ULong base = TT_NEXT_UINT24( defp ); - FT_ULong cnt = FT_NEXT_BYTE( defp ); - - - if ( base + cnt >= 0x110000UL ) /* end of Unicode */ - FT_INVALID_DATA; - - if ( base < lastBase ) - FT_INVALID_DATA; - - lastBase = base + cnt + 1U; - } - } - - /* and the non-default table (these glyphs are specified here) */ - if ( nondefOff != 0 ) - { - FT_Byte* ndp = table + nondefOff; - FT_ULong numMappings = TT_NEXT_ULONG( ndp ); - FT_ULong i, lastUni = 0; - - - /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */ - if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 ) - FT_INVALID_TOO_SHORT; - - for ( i = 0; i < numMappings; ++i ) - { - FT_ULong uni = TT_NEXT_UINT24( ndp ); - FT_ULong gid = TT_NEXT_USHORT( ndp ); - - - if ( uni >= 0x110000UL ) /* end of Unicode */ - FT_INVALID_DATA; - - if ( uni < lastUni ) - FT_INVALID_DATA; - - lastUni = uni + 1U; - - if ( valid->level >= FT_VALIDATE_TIGHT && - gid >= TT_VALID_GLYPH_COUNT( valid ) ) - FT_INVALID_GLYPH_ID; - } - } - } - } - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_index( TT_CMap cmap, - FT_UInt32 char_code ) - { - FT_UNUSED( cmap ); - FT_UNUSED( char_code ); - - /* This can't happen */ - return 0; - } - - - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap14_char_next( TT_CMap cmap, - FT_UInt32 *pchar_code ) - { - FT_UNUSED( cmap ); - - /* This can't happen */ - *pchar_code = 0; - return 0; - } - - - FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_get_info( TT_CMap cmap, - TT_CMapInfo *cmap_info ) - { - FT_UNUSED( cmap ); - - cmap_info->format = 14; - /* subtable 14 does not define a language field */ - cmap_info->language = 0xFFFFFFFFUL; - - return FT_Err_Ok; - } - - - static FT_UInt - tt_cmap14_char_map_def_binary( FT_Byte *base, - FT_UInt32 char_code ) - { - FT_UInt32 numRanges = TT_PEEK_ULONG( base ); - FT_UInt32 max, min; - - - min = 0; - max = numRanges; - - base += 4; - - /* binary search */ - while ( min < max ) - { - FT_UInt32 mid = ( min + max ) >> 1; - FT_Byte* p = base + 4 * mid; - FT_ULong start = TT_NEXT_UINT24( p ); - FT_UInt cnt = FT_NEXT_BYTE( p ); - - - if ( char_code < start ) - max = mid; - else if ( char_code > start+cnt ) - min = mid + 1; - else - return TRUE; - } - - return FALSE; - } - - - static FT_UInt - tt_cmap14_char_map_nondef_binary( FT_Byte *base, - FT_UInt32 char_code ) - { - FT_UInt32 numMappings = TT_PEEK_ULONG( base ); - FT_UInt32 max, min; - - - min = 0; - max = numMappings; - - base += 4; - - /* binary search */ - while ( min < max ) - { - FT_UInt32 mid = ( min + max ) >> 1; - FT_Byte* p = base + 5 * mid; - FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); - - - if ( char_code < uni ) - max = mid; - else if ( char_code > uni ) - min = mid + 1; - else - return TT_PEEK_USHORT( p ); - } - - return 0; - } - - - static FT_Byte* - tt_cmap14_find_variant( FT_Byte *base, - FT_UInt32 variantCode ) - { - FT_UInt32 numVar = TT_PEEK_ULONG( base ); - FT_UInt32 max, min; - - - min = 0; - max = numVar; - - base += 4; - - /* binary search */ - while ( min < max ) - { - FT_UInt32 mid = ( min + max ) >> 1; - FT_Byte* p = base + 11 * mid; - FT_ULong varSel = TT_NEXT_UINT24( p ); - - - if ( variantCode < varSel ) - max = mid; - else if ( variantCode > varSel ) - min = mid + 1; - else - return p; - } - - return NULL; - } - - - FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_var_index( TT_CMap cmap, - TT_CMap ucmap, - FT_UInt32 charcode, - FT_UInt32 variantSelector ) - { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); - FT_ULong defOff; - FT_ULong nondefOff; - - - if ( !p ) - return 0; - - defOff = TT_NEXT_ULONG( p ); - nondefOff = TT_PEEK_ULONG( p ); - - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) - { - /* This is the default variant of this charcode. GID not stored */ - /* here; stored in the normal Unicode charmap instead. */ - return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); - } - - if ( nondefOff != 0 ) - return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charcode ); - - return 0; - } - - - FT_CALLBACK_DEF( FT_Int ) - tt_cmap14_char_var_isdefault( TT_CMap cmap, - FT_UInt32 charcode, - FT_UInt32 variantSelector ) - { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); - FT_ULong defOff; - FT_ULong nondefOff; - - - if ( !p ) - return -1; - - defOff = TT_NEXT_ULONG( p ); - nondefOff = TT_NEXT_ULONG( p ); - - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) - return 1; - - if ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charcode ) != 0 ) - return 0; - - return -1; - } - - - FT_CALLBACK_DEF( FT_UInt32* ) - tt_cmap14_variants( TT_CMap cmap, - FT_Memory memory ) - { - TT_CMap14 cmap14 = (TT_CMap14)cmap; - FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; - FT_UInt32* result; - FT_UInt32 i; - - - if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) - return NULL; - - result = cmap14->results; - for ( i = 0; i < count; ++i ) - { - result[i] = (FT_UInt32)TT_NEXT_UINT24( p ); - p += 8; - } - result[i] = 0; - - return result; - } - - - FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_char_variants( TT_CMap cmap, - FT_Memory memory, - FT_UInt32 charCode ) - { - TT_CMap14 cmap14 = (TT_CMap14) cmap; - FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; - FT_UInt32* q; - - - if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) - return NULL; - - for ( q = cmap14->results; count > 0; --count ) - { - FT_UInt32 varSel = TT_NEXT_UINT24( p ); - FT_ULong defOff = TT_NEXT_ULONG( p ); - FT_ULong nondefOff = TT_NEXT_ULONG( p ); - - - if ( ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, - charCode ) ) || - ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charCode ) != 0 ) ) - { - q[0] = varSel; - q++; - } - } - q[0] = 0; - - return cmap14->results; - } - - - static FT_UInt - tt_cmap14_def_char_count( FT_Byte *p ) - { - FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); - FT_UInt tot = 0; - - - p += 3; /* point to the first `cnt' field */ - for ( ; numRanges > 0; numRanges-- ) - { - tot += 1 + p[0]; - p += 4; - } - - return tot; - } - - - static FT_UInt32* - tt_cmap14_get_def_chars( TT_CMap cmap, - FT_Byte* p, - FT_Memory memory ) - { - TT_CMap14 cmap14 = (TT_CMap14) cmap; - FT_UInt32 numRanges; - FT_UInt cnt; - FT_UInt32* q; - - - cnt = tt_cmap14_def_char_count( p ); - numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); - - if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) ) - return NULL; - - for ( q = cmap14->results; numRanges > 0; --numRanges ) - { - FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); - - - cnt = FT_NEXT_BYTE( p ) + 1; - do - { - q[0] = uni; - uni += 1; - q += 1; - - } while ( --cnt != 0 ); - } - q[0] = 0; - - return cmap14->results; - } - - - static FT_UInt32* - tt_cmap14_get_nondef_chars( TT_CMap cmap, - FT_Byte *p, - FT_Memory memory ) - { - TT_CMap14 cmap14 = (TT_CMap14) cmap; - FT_UInt32 numMappings; - FT_UInt i; - FT_UInt32 *ret; - - - numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); - - if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) ) - return NULL; - - ret = cmap14->results; - for ( i = 0; i < numMappings; ++i ) - { - ret[i] = (FT_UInt32)TT_NEXT_UINT24( p ); - p += 2; - } - ret[i] = 0; - - return ret; - } - - - FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_variant_chars( TT_CMap cmap, - FT_Memory memory, - FT_UInt32 variantSelector ) - { - FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, - variantSelector ); - FT_Int i; - FT_ULong defOff; - FT_ULong nondefOff; - - - if ( !p ) - return NULL; - - defOff = TT_NEXT_ULONG( p ); - nondefOff = TT_NEXT_ULONG( p ); - - if ( defOff == 0 && nondefOff == 0 ) - return NULL; - - if ( defOff == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, - memory ); - else if ( nondefOff == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, - memory ); - else - { - /* Both a default and a non-default glyph set? That's probably not */ - /* good font design, but the spec allows for it... */ - TT_CMap14 cmap14 = (TT_CMap14) cmap; - FT_UInt32 numRanges; - FT_UInt32 numMappings; - FT_UInt32 duni; - FT_UInt32 dcnt; - FT_UInt32 nuni; - FT_Byte* dp; - FT_UInt di, ni, k; - - FT_UInt32 *ret; - - - p = cmap->data + nondefOff; - dp = cmap->data + defOff; - - numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); - dcnt = tt_cmap14_def_char_count( dp ); - numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); - - if ( numMappings == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, - memory ); - if ( dcnt == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, - memory ); - - if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) - return NULL; - - ret = cmap14->results; - duni = (FT_UInt32)TT_NEXT_UINT24( dp ); - dcnt = FT_NEXT_BYTE( dp ); - di = 1; - nuni = (FT_UInt32)TT_NEXT_UINT24( p ); - p += 2; - ni = 1; - i = 0; - - for ( ;; ) - { - if ( nuni > duni + dcnt ) - { - for ( k = 0; k <= dcnt; ++k ) - ret[i++] = duni + k; - - ++di; - - if ( di > numRanges ) - break; - - duni = (FT_UInt32)TT_NEXT_UINT24( dp ); - dcnt = FT_NEXT_BYTE( dp ); - } - else - { - if ( nuni < duni ) - ret[i++] = nuni; - /* If it is within the default range then ignore it -- */ - /* that should not have happened */ - ++ni; - if ( ni > numMappings ) - break; - - nuni = (FT_UInt32)TT_NEXT_UINT24( p ); - p += 2; - } - } - - if ( ni <= numMappings ) - { - /* If we get here then we have run out of all default ranges. */ - /* We have read one non-default mapping which we haven't stored */ - /* and there may be others that need to be read. */ - ret[i++] = nuni; - while ( ni < numMappings ) - { - ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p ); - p += 2; - ++ni; - } - } - else if ( di <= numRanges ) - { - /* If we get here then we have run out of all non-default */ - /* mappings. We have read one default range which we haven't */ - /* stored and there may be others that need to be read. */ - for ( k = 0; k <= dcnt; ++k ) - ret[i++] = duni + k; - - while ( di < numRanges ) - { - duni = (FT_UInt32)TT_NEXT_UINT24( dp ); - dcnt = FT_NEXT_BYTE( dp ); - - for ( k = 0; k <= dcnt; ++k ) - ret[i++] = duni + k; - ++di; - } - } - - ret[i] = 0; - - return ret; - } - } - - - FT_DEFINE_TT_CMAP( - tt_cmap14_class_rec, - sizeof ( TT_CMap14Rec ), - - (FT_CMap_InitFunc) tt_cmap14_init, - (FT_CMap_DoneFunc) tt_cmap14_done, - (FT_CMap_CharIndexFunc)tt_cmap14_char_index, - (FT_CMap_CharNextFunc) tt_cmap14_char_next, - - /* Format 14 extension functions */ - (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, - (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, - (FT_CMap_VariantListFunc) tt_cmap14_variants, - (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, - (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars, - - 14, - (TT_CMap_ValidateFunc)tt_cmap14_validate, - (TT_CMap_Info_GetFunc)tt_cmap14_get_info ) - -#endif /* TT_CONFIG_CMAP_FORMAT_14 */ - - -#ifndef FT_CONFIG_OPTION_PIC - - static const TT_CMap_Class tt_cmap_classes[] = - { -#define TTCMAPCITEM( a ) &a, -#include "ttcmapc.h" - NULL, - }; - -#else /*FT_CONFIG_OPTION_PIC*/ - - void - FT_Destroy_Class_tt_cmap_classes( FT_Library library, - TT_CMap_Class* clazz ) - { - FT_Memory memory = library->memory; - - - if ( clazz ) - FT_FREE( clazz ); - } - - - FT_Error - FT_Create_Class_tt_cmap_classes( FT_Library library, - TT_CMap_Class** output_class ) - { - TT_CMap_Class* clazz = NULL; - TT_CMap_ClassRec* recs; - FT_Error error; - FT_Memory memory = library->memory; - - int i = 0; - - -#define TTCMAPCITEM( a ) i++; -#include "ttcmapc.h" - - /* allocate enough space for both the pointers */ - /* plus terminator and the class instances */ - if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) + - sizeof ( TT_CMap_ClassRec ) * i ) ) - return error; - - /* the location of the class instances follows the array of pointers */ - recs = (TT_CMap_ClassRec*)( (char*)clazz + - sizeof ( *clazz ) * ( i + 1 ) ); - i = 0; - -#undef TTCMAPCITEM -#define TTCMAPCITEM( a ) \ - FT_Init_Class_ ## a( &recs[i] ); \ - clazz[i] = &recs[i]; \ - i++; -#include "ttcmapc.h" - - clazz[i] = NULL; - - *output_class = clazz; - return FT_Err_Ok; - } - -#endif /*FT_CONFIG_OPTION_PIC*/ - - - /* parse the `cmap' table and build the corresponding TT_CMap objects */ - /* in the current face */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_build_cmaps( TT_Face face ) - { - FT_Byte* table = face->cmap_table; - FT_Byte* limit = table + face->cmap_size; - FT_UInt volatile num_cmaps; - FT_Byte* volatile p = table; - FT_Library library = FT_FACE_LIBRARY( face ); - - FT_UNUSED( library ); - - - if ( !p || p + 4 > limit ) - return FT_THROW( Invalid_Table ); - - /* only recognize format 0 */ - if ( TT_NEXT_USHORT( p ) != 0 ) - { - FT_ERROR(( "tt_face_build_cmaps:" - " unsupported `cmap' table format = %d\n", - TT_PEEK_USHORT( p - 2 ) )); - return FT_THROW( Invalid_Table ); - } - - num_cmaps = TT_NEXT_USHORT( p ); - - for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) - { - FT_CharMapRec charmap; - FT_UInt32 offset; - - - charmap.platform_id = TT_NEXT_USHORT( p ); - charmap.encoding_id = TT_NEXT_USHORT( p ); - charmap.face = FT_FACE( face ); - charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ - offset = TT_NEXT_ULONG( p ); - - if ( offset && offset <= face->cmap_size - 2 ) - { - FT_Byte* volatile cmap = table + offset; - volatile FT_UInt format = TT_PEEK_USHORT( cmap ); - const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET; - TT_CMap_Class volatile clazz; - - - for ( ; *pclazz; pclazz++ ) - { - clazz = *pclazz; - if ( clazz->format == format ) - { - volatile TT_ValidatorRec valid; - volatile FT_Error error = FT_Err_Ok; - - - ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, - FT_VALIDATE_DEFAULT ); - - valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs; - - if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 ) - { - /* validate this cmap sub-table */ - error = clazz->validate( cmap, FT_VALIDATOR( &valid ) ); - } - - if ( valid.validator.error == 0 ) - { - FT_CMap ttcmap; - - - /* It might make sense to store the single variation */ - /* selector cmap somewhere special. But it would have to be */ - /* in the public FT_FaceRec, and we can't change that. */ - - if ( !FT_CMap_New( (FT_CMap_Class)clazz, - cmap, &charmap, &ttcmap ) ) - { - /* it is simpler to directly set `flags' than adding */ - /* a parameter to FT_CMap_New */ - ((TT_CMap)ttcmap)->flags = (FT_Int)error; - } - } - else - { - FT_TRACE0(( "tt_face_build_cmaps:" - " broken cmap sub-table ignored\n" )); - } - break; - } - } - - if ( *pclazz == NULL ) - { - FT_TRACE0(( "tt_face_build_cmaps:" - " unsupported cmap sub-table ignored\n" )); - } - } - } - - return FT_Err_Ok; - } - - - FT_LOCAL( FT_Error ) - tt_get_cmap_info( FT_CharMap charmap, - TT_CMapInfo *cmap_info ) - { - FT_CMap cmap = (FT_CMap)charmap; - TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; - - - return clazz->get_cmap_info( charmap, cmap_info ); - } - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttcmap.h b/third_party/freetype/src/sfnt/ttcmap.h deleted file mode 100644 index b7ea8ee37736898547a7b06b735fc5025511c201..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttcmap.h +++ /dev/null @@ -1,158 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttcmap.h */ -/* */ -/* TrueType character mapping table (cmap) support (specification). */ -/* */ -/* Copyright 2002-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTCMAP_H__ -#define __TTCMAP_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_TRUETYPE_TYPES_H -#include FT_INTERNAL_VALIDATE_H -#include FT_SERVICE_TT_CMAP_H - -FT_BEGIN_HEADER - - -#define TT_CMAP_FLAG_UNSORTED 1 -#define TT_CMAP_FLAG_OVERLAPPING 2 - - typedef struct TT_CMapRec_ - { - FT_CMapRec cmap; - FT_Byte* data; /* pointer to in-memory cmap table */ - FT_Int flags; /* for format 4 only */ - - } TT_CMapRec, *TT_CMap; - - typedef const struct TT_CMap_ClassRec_* TT_CMap_Class; - - - typedef FT_Error - (*TT_CMap_ValidateFunc)( FT_Byte* data, - FT_Validator valid ); - - typedef struct TT_CMap_ClassRec_ - { - FT_CMap_ClassRec clazz; - FT_UInt format; - TT_CMap_ValidateFunc validate; - TT_CMap_Info_GetFunc get_cmap_info; - - } TT_CMap_ClassRec; - - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_DEFINE_TT_CMAP( class_, \ - size_, \ - init_, \ - done_, \ - char_index_, \ - char_next_, \ - char_var_index_, \ - char_var_default_, \ - variant_list_, \ - charvariant_list_, \ - variantchar_list_, \ - format_, \ - validate_, \ - get_cmap_info_ ) \ - FT_CALLBACK_TABLE_DEF \ - const TT_CMap_ClassRec class_ = \ - { \ - { size_, \ - init_, \ - done_, \ - char_index_, \ - char_next_, \ - char_var_index_, \ - char_var_default_, \ - variant_list_, \ - charvariant_list_, \ - variantchar_list_ \ - }, \ - \ - format_, \ - validate_, \ - get_cmap_info_ \ - }; - -#else /* FT_CONFIG_OPTION_PIC */ - -#define FT_DEFINE_TT_CMAP( class_, \ - size_, \ - init_, \ - done_, \ - char_index_, \ - char_next_, \ - char_var_index_, \ - char_var_default_, \ - variant_list_, \ - charvariant_list_, \ - variantchar_list_, \ - format_, \ - validate_, \ - get_cmap_info_ ) \ - void \ - FT_Init_Class_ ## class_( TT_CMap_ClassRec* clazz ) \ - { \ - clazz->clazz.size = size_; \ - clazz->clazz.init = init_; \ - clazz->clazz.done = done_; \ - clazz->clazz.char_index = char_index_; \ - clazz->clazz.char_next = char_next_; \ - clazz->clazz.char_var_index = char_var_index_; \ - clazz->clazz.char_var_default = char_var_default_; \ - clazz->clazz.variant_list = variant_list_; \ - clazz->clazz.charvariant_list = charvariant_list_; \ - clazz->clazz.variantchar_list = variantchar_list_; \ - clazz->format = format_; \ - clazz->validate = validate_; \ - clazz->get_cmap_info = get_cmap_info_; \ - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - - typedef struct TT_ValidatorRec_ - { - FT_ValidatorRec validator; - FT_UInt num_glyphs; - - } TT_ValidatorRec, *TT_Validator; - - -#define TT_VALIDATOR( x ) ( (TT_Validator)( x ) ) -#define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs - - - FT_LOCAL( FT_Error ) - tt_face_build_cmaps( TT_Face face ); - - /* used in tt-cmaps service */ - FT_LOCAL( FT_Error ) - tt_get_cmap_info( FT_CharMap charmap, - TT_CMapInfo *cmap_info ); - - -FT_END_HEADER - -#endif /* __TTCMAP_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttcmapc.h b/third_party/freetype/src/sfnt/ttcmapc.h deleted file mode 100644 index 4a489402cfffeb0e420b50c6cdbdbec4ab17881e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttcmapc.h +++ /dev/null @@ -1,56 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttcmapc.h */ -/* */ -/* TT CMAP classes definitions (specification only). */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifdef TT_CONFIG_CMAP_FORMAT_0 - TTCMAPCITEM( tt_cmap0_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_2 - TTCMAPCITEM( tt_cmap2_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_4 - TTCMAPCITEM( tt_cmap4_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_6 - TTCMAPCITEM( tt_cmap6_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_8 - TTCMAPCITEM( tt_cmap8_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_10 - TTCMAPCITEM( tt_cmap10_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_12 - TTCMAPCITEM( tt_cmap12_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_13 - TTCMAPCITEM( tt_cmap13_class_rec ) -#endif - -#ifdef TT_CONFIG_CMAP_FORMAT_14 - TTCMAPCITEM( tt_cmap14_class_rec ) -#endif - - - /* END */ diff --git a/third_party/freetype/src/sfnt/ttkern.c b/third_party/freetype/src/sfnt/ttkern.c deleted file mode 100644 index 4fccc535cedc952ba99a6eb14d1e1db82aa267ea..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttkern.c +++ /dev/null @@ -1,306 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttkern.c */ -/* */ -/* Load the basic TrueType kerning table. This doesn't handle */ -/* kerning data within the GPOS table at the moment. */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include "ttkern.h" - -#include "sferrors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttkern - - -#undef TT_KERN_INDEX -#define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) ) - - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_kern( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_ULong table_size; - FT_Byte* p; - FT_Byte* p_limit; - FT_UInt nn, num_tables; - FT_UInt32 avail = 0, ordered = 0; - - - /* the kern table is optional; exit silently if it is missing */ - error = face->goto_table( face, TTAG_kern, stream, &table_size ); - if ( error ) - goto Exit; - - if ( table_size < 4 ) /* the case of a malformed table */ - { - FT_ERROR(( "tt_face_load_kern:" - " kerning table is too small - ignored\n" )); - error = FT_THROW( Table_Missing ); - goto Exit; - } - - if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) ) - { - FT_ERROR(( "tt_face_load_kern:" - " could not extract kerning table\n" )); - goto Exit; - } - - face->kern_table_size = table_size; - - p = face->kern_table; - p_limit = p + table_size; - - p += 2; /* skip version */ - num_tables = FT_NEXT_USHORT( p ); - - if ( num_tables > 32 ) /* we only support up to 32 sub-tables */ - num_tables = 32; - - for ( nn = 0; nn < num_tables; nn++ ) - { - FT_UInt num_pairs, length, coverage; - FT_Byte* p_next; - FT_UInt32 mask = (FT_UInt32)1UL << nn; - - - if ( p + 6 > p_limit ) - break; - - p_next = p; - - p += 2; /* skip version */ - length = FT_NEXT_USHORT( p ); - coverage = FT_NEXT_USHORT( p ); - - if ( length <= 6 + 8 ) - break; - - p_next += length; - - if ( p_next > p_limit ) /* handle broken table */ - p_next = p_limit; - - /* only use horizontal kerning tables */ - if ( ( coverage & ~8U ) != 0x0001 || - p + 8 > p_limit ) - goto NextTable; - - num_pairs = FT_NEXT_USHORT( p ); - p += 6; - - if ( ( p_next - p ) < 6 * (int)num_pairs ) /* handle broken count */ - num_pairs = (FT_UInt)( ( p_next - p ) / 6 ); - - avail |= mask; - - /* - * Now check whether the pairs in this table are ordered. - * We then can use binary search. - */ - if ( num_pairs > 0 ) - { - FT_ULong count; - FT_ULong old_pair; - - - old_pair = FT_NEXT_ULONG( p ); - p += 2; - - for ( count = num_pairs - 1; count > 0; count-- ) - { - FT_UInt32 cur_pair; - - - cur_pair = FT_NEXT_ULONG( p ); - if ( cur_pair <= old_pair ) - break; - - p += 2; - old_pair = cur_pair; - } - - if ( count == 0 ) - ordered |= mask; - } - - NextTable: - p = p_next; - } - - face->num_kern_tables = nn; - face->kern_avail_bits = avail; - face->kern_order_bits = ordered; - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - tt_face_done_kern( TT_Face face ) - { - FT_Stream stream = face->root.stream; - - - FT_FRAME_RELEASE( face->kern_table ); - face->kern_table_size = 0; - face->num_kern_tables = 0; - face->kern_avail_bits = 0; - face->kern_order_bits = 0; - } - - - FT_LOCAL_DEF( FT_Int ) - tt_face_get_kerning( TT_Face face, - FT_UInt left_glyph, - FT_UInt right_glyph ) - { - FT_Int result = 0; - FT_UInt count, mask; - FT_Byte* p = face->kern_table; - FT_Byte* p_limit = p + face->kern_table_size; - - - p += 4; - mask = 0x0001; - - for ( count = face->num_kern_tables; - count > 0 && p + 6 <= p_limit; - count--, mask <<= 1 ) - { - FT_Byte* base = p; - FT_Byte* next; - FT_UInt version = FT_NEXT_USHORT( p ); - FT_UInt length = FT_NEXT_USHORT( p ); - FT_UInt coverage = FT_NEXT_USHORT( p ); - FT_UInt num_pairs; - FT_Int value = 0; - - FT_UNUSED( version ); - - - next = base + length; - - if ( next > p_limit ) /* handle broken table */ - next = p_limit; - - if ( ( face->kern_avail_bits & mask ) == 0 ) - goto NextTable; - - if ( p + 8 > next ) - goto NextTable; - - num_pairs = FT_NEXT_USHORT( p ); - p += 6; - - if ( ( next - p ) < 6 * (int)num_pairs ) /* handle broken count */ - num_pairs = (FT_UInt)( ( next - p ) / 6 ); - - switch ( coverage >> 8 ) - { - case 0: - { - FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); - - - if ( face->kern_order_bits & mask ) /* binary search */ - { - FT_UInt min = 0; - FT_UInt max = num_pairs; - - - while ( min < max ) - { - FT_UInt mid = ( min + max ) >> 1; - FT_Byte* q = p + 6 * mid; - FT_ULong key; - - - key = FT_NEXT_ULONG( q ); - - if ( key == key0 ) - { - value = FT_PEEK_SHORT( q ); - goto Found; - } - if ( key < key0 ) - min = mid + 1; - else - max = mid; - } - } - else /* linear search */ - { - FT_UInt count2; - - - for ( count2 = num_pairs; count2 > 0; count2-- ) - { - FT_ULong key = FT_NEXT_ULONG( p ); - - - if ( key == key0 ) - { - value = FT_PEEK_SHORT( p ); - goto Found; - } - p += 2; - } - } - } - break; - - /* - * We don't support format 2 because we haven't seen a single font - * using it in real life... - */ - - default: - ; - } - - goto NextTable; - - Found: - if ( coverage & 8 ) /* override or add */ - result = value; - else - result += value; - - NextTable: - p = next; - } - - return result; - } - -#undef TT_KERN_INDEX - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttkern.h b/third_party/freetype/src/sfnt/ttkern.h deleted file mode 100644 index 89cb24f07ce26d6e7b4b376cbb7b692abcf21be2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttkern.h +++ /dev/null @@ -1,52 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttkern.h */ -/* */ -/* Load the basic TrueType kerning table. This doesn't handle */ -/* kerning data within the GPOS table at the moment. */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTKERN_H__ -#define __TTKERN_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - tt_face_load_kern( TT_Face face, - FT_Stream stream ); - - FT_LOCAL( void ) - tt_face_done_kern( TT_Face face ); - - FT_LOCAL( FT_Int ) - tt_face_get_kerning( TT_Face face, - FT_UInt left_glyph, - FT_UInt right_glyph ); - -#define TT_FACE_HAS_KERNING( face ) ( (face)->kern_avail_bits != 0 ) - - -FT_END_HEADER - -#endif /* __TTKERN_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttload.c b/third_party/freetype/src/sfnt/ttload.c deleted file mode 100644 index c1bd7f0c82eb8686e5eb31a0bbb2b579954e2f60..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttload.c +++ /dev/null @@ -1,1363 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttload.c */ -/* */ -/* Load the basic TrueType tables, i.e., tables that can be either in */ -/* TTF or OTF fonts (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include "ttload.h" - -#include "sferrors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttload - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_lookup_table */ - /* */ - /* <Description> */ - /* Looks for a TrueType table by name. */ - /* */ - /* <Input> */ - /* face :: A face object handle. */ - /* */ - /* tag :: The searched tag. */ - /* */ - /* <Return> */ - /* A pointer to the table directory entry. 0 if not found. */ - /* */ - FT_LOCAL_DEF( TT_Table ) - tt_face_lookup_table( TT_Face face, - FT_ULong tag ) - { - TT_Table entry; - TT_Table limit; -#ifdef FT_DEBUG_LEVEL_TRACE - FT_Bool zero_length = FALSE; -#endif - - - FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", - face, - (FT_Char)( tag >> 24 ), - (FT_Char)( tag >> 16 ), - (FT_Char)( tag >> 8 ), - (FT_Char)( tag ) )); - - entry = face->dir_tables; - limit = entry + face->num_tables; - - for ( ; entry < limit; entry++ ) - { - /* For compatibility with Windows, we consider */ - /* zero-length tables the same as missing tables. */ - if ( entry->Tag == tag ) - { - if ( entry->Length != 0 ) - { - FT_TRACE4(( "found table.\n" )); - return entry; - } -#ifdef FT_DEBUG_LEVEL_TRACE - zero_length = TRUE; -#endif - } - } - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( zero_length ) - FT_TRACE4(( "ignoring empty table\n" )); - else - FT_TRACE4(( "could not find table\n" )); -#endif - - return NULL; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_goto_table */ - /* */ - /* <Description> */ - /* Looks for a TrueType table by name, then seek a stream to it. */ - /* */ - /* <Input> */ - /* face :: A face object handle. */ - /* */ - /* tag :: The searched tag. */ - /* */ - /* stream :: The stream to seek when the table is found. */ - /* */ - /* <Output> */ - /* length :: The length of the table if found, undefined otherwise. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_goto_table( TT_Face face, - FT_ULong tag, - FT_Stream stream, - FT_ULong* length ) - { - TT_Table table; - FT_Error error; - - - table = tt_face_lookup_table( face, tag ); - if ( table ) - { - if ( length ) - *length = table->Length; - - if ( FT_STREAM_SEEK( table->Offset ) ) - goto Exit; - } - else - error = FT_THROW( Table_Missing ); - - Exit: - return error; - } - - - /* Here, we */ - /* */ - /* - check that `num_tables' is valid (and adjust it if necessary); */ - /* also return the number of valid table entries */ - /* */ - /* - look for a `head' table, check its size, and parse it to check */ - /* whether its `magic' field is correctly set */ - /* */ - /* - errors (except errors returned by stream handling) */ - /* */ - /* SFNT_Err_Unknown_File_Format: */ - /* no table is defined in directory, it is not sfnt-wrapped */ - /* data */ - /* SFNT_Err_Table_Missing: */ - /* table directory is valid, but essential tables */ - /* (head/bhed/SING) are missing */ - /* */ - static FT_Error - check_table_dir( SFNT_Header sfnt, - FT_Stream stream, - FT_UShort* valid ) - { - FT_Error error; - FT_UShort nn, valid_entries = 0; - FT_UInt has_head = 0, has_sing = 0, has_meta = 0; - FT_ULong offset = sfnt->offset + 12; - - static const FT_Frame_Field table_dir_entry_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_TableRec - - FT_FRAME_START( 16 ), - FT_FRAME_ULONG( Tag ), - FT_FRAME_ULONG( CheckSum ), - FT_FRAME_ULONG( Offset ), - FT_FRAME_ULONG( Length ), - FT_FRAME_END - }; - - - if ( FT_STREAM_SEEK( offset ) ) - goto Exit; - - for ( nn = 0; nn < sfnt->num_tables; nn++ ) - { - TT_TableRec table; - - - if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) - { - nn--; - FT_TRACE2(( "check_table_dir:" - " can read only %d table%s in font (instead of %d)\n", - nn, nn == 1 ? "" : "s", sfnt->num_tables )); - sfnt->num_tables = nn; - break; - } - - /* we ignore invalid tables */ - - if ( table.Offset > stream->size ) - { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); - continue; - } - else if ( table.Length > stream->size - table.Offset ) - { - /* Some tables have such a simple structure that clipping its */ - /* contents is harmless. This also makes FreeType less sensitive */ - /* to invalid table lengths (which programs like Acroread seem to */ - /* ignore in general). */ - - if ( table.Tag == TTAG_hmtx || - table.Tag == TTAG_vmtx ) - valid_entries++; - else - { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); - continue; - } - } - else - valid_entries++; - - if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed ) - { - FT_UInt32 magic; - - -#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - if ( table.Tag == TTAG_head ) -#endif - has_head = 1; - - /* - * The table length should be 0x36, but certain font tools make it - * 0x38, so we will just check that it is greater. - * - * Note that according to the specification, the table must be - * padded to 32-bit lengths, but this doesn't apply to the value of - * its `Length' field! - * - */ - if ( table.Length < 0x36 ) - { - FT_TRACE2(( "check_table_dir:" - " `head' or `bhed' table too small\n" )); - error = FT_THROW( Table_Missing ); - goto Exit; - } - - if ( FT_STREAM_SEEK( table.Offset + 12 ) || - FT_READ_ULONG( magic ) ) - goto Exit; - - if ( magic != 0x5F0F3CF5UL ) - FT_TRACE2(( "check_table_dir:" - " invalid magic number in `head' or `bhed' table\n")); - - if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) ) - goto Exit; - } - else if ( table.Tag == TTAG_SING ) - has_sing = 1; - else if ( table.Tag == TTAG_META ) - has_meta = 1; - } - - *valid = valid_entries; - - if ( !valid_entries ) - { - FT_TRACE2(( "check_table_dir: no valid tables found\n" )); - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - /* if `sing' and `meta' tables are present, there is no `head' table */ - if ( has_head || ( has_sing && has_meta ) ) - { - error = FT_Err_Ok; - goto Exit; - } - else - { - FT_TRACE2(( "check_table_dir:" )); -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" )); -#else - FT_TRACE2(( " neither `head' nor `sing' table found\n" )); -#endif - error = FT_THROW( Table_Missing ); - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_font_dir */ - /* */ - /* <Description> */ - /* Loads the header of a SFNT font file. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Output> */ - /* sfnt :: The SFNT header. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* The stream cursor must be at the beginning of the font directory. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_font_dir( TT_Face face, - FT_Stream stream ) - { - SFNT_HeaderRec sfnt; - FT_Error error; - FT_Memory memory = stream->memory; - FT_UShort nn, valid_entries; - - static const FT_Frame_Field offset_table_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE SFNT_HeaderRec - - FT_FRAME_START( 8 ), - FT_FRAME_USHORT( num_tables ), - FT_FRAME_USHORT( search_range ), - FT_FRAME_USHORT( entry_selector ), - FT_FRAME_USHORT( range_shift ), - FT_FRAME_END - }; - - - FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face )); - - /* read the offset table */ - - sfnt.offset = FT_STREAM_POS(); - - if ( FT_READ_ULONG( sfnt.format_tag ) || - FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) ) - goto Exit; - - /* many fonts don't have these fields set correctly */ -#if 0 - if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) || - sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 ) - return FT_THROW( Unknown_File_Format ); -#endif - - /* load the table directory */ - - FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables )); - FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag )); - - if ( sfnt.format_tag != TTAG_OTTO ) - { - /* check first */ - error = check_table_dir( &sfnt, stream, &valid_entries ); - if ( error ) - { - FT_TRACE2(( "tt_face_load_font_dir:" - " invalid table directory for TrueType\n" )); - goto Exit; - } - } - else - valid_entries = sfnt.num_tables; - - face->num_tables = valid_entries; - face->format_tag = sfnt.format_tag; - - if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) - goto Exit; - - if ( FT_STREAM_SEEK( sfnt.offset + 12 ) || - FT_FRAME_ENTER( sfnt.num_tables * 16L ) ) - goto Exit; - - FT_TRACE2(( "\n" - " tag offset length checksum\n" - " ----------------------------------\n" )); - - valid_entries = 0; - for ( nn = 0; nn < sfnt.num_tables; nn++ ) - { - TT_TableRec entry; - FT_UShort i; - FT_Bool duplicate; - - - entry.Tag = FT_GET_TAG4(); - entry.CheckSum = FT_GET_ULONG(); - entry.Offset = FT_GET_ULONG(); - entry.Length = FT_GET_ULONG(); - - /* ignore invalid tables that can't be sanitized */ - - if ( entry.Offset > stream->size ) - continue; - else if ( entry.Length > stream->size - entry.Offset ) - { - if ( entry.Tag == TTAG_hmtx || - entry.Tag == TTAG_vmtx ) - { -#ifdef FT_DEBUG_LEVEL_TRACE - FT_ULong old_length = entry.Length; -#endif - - - /* make metrics table length a multiple of 4 */ - entry.Length = ( stream->size - entry.Offset ) & ~3U; - - FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx" - " (sanitized; original length %08lx)", - (FT_Char)( entry.Tag >> 24 ), - (FT_Char)( entry.Tag >> 16 ), - (FT_Char)( entry.Tag >> 8 ), - (FT_Char)( entry.Tag ), - entry.Offset, - entry.Length, - entry.CheckSum, - old_length )); - } - else - continue; - } -#ifdef FT_DEBUG_LEVEL_TRACE - else - FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx", - (FT_Char)( entry.Tag >> 24 ), - (FT_Char)( entry.Tag >> 16 ), - (FT_Char)( entry.Tag >> 8 ), - (FT_Char)( entry.Tag ), - entry.Offset, - entry.Length, - entry.CheckSum )); -#endif - - /* ignore duplicate tables – the first one wins */ - duplicate = 0; - for ( i = 0; i < valid_entries; i++ ) - { - if ( face->dir_tables[i].Tag == entry.Tag ) - { - duplicate = 1; - break; - } - } - if ( duplicate ) - { - FT_TRACE2(( " (duplicate, ignored)\n" )); - continue; - } - else - { - FT_TRACE2(( "\n" )); - - /* we finally have a valid entry */ - face->dir_tables[valid_entries++] = entry; - } - } - - /* final adjustment to number of tables */ - face->num_tables = valid_entries; - - FT_FRAME_EXIT(); - - FT_TRACE2(( "table directory loaded\n\n" )); - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_any */ - /* */ - /* <Description> */ - /* Loads any font table into client memory. */ - /* */ - /* <Input> */ - /* face :: The face object to look for. */ - /* */ - /* tag :: The tag of table to load. Use the value 0 if you want */ - /* to access the whole font file, else set this parameter */ - /* to a valid TrueType table tag that you can forge with */ - /* the MAKE_TT_TAG macro. */ - /* */ - /* offset :: The starting offset in the table (or the file if */ - /* tag == 0). */ - /* */ - /* length :: The address of the decision variable: */ - /* */ - /* If length == NULL: */ - /* Loads the whole table. Returns an error if */ - /* `offset' == 0! */ - /* */ - /* If *length == 0: */ - /* Exits immediately; returning the length of the given */ - /* table or of the font file, depending on the value of */ - /* `tag'. */ - /* */ - /* If *length != 0: */ - /* Loads the next `length' bytes of table or font, */ - /* starting at offset `offset' (in table or font too). */ - /* */ - /* <Output> */ - /* buffer :: The address of target buffer. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_any( TT_Face face, - FT_ULong tag, - FT_Long offset, - FT_Byte* buffer, - FT_ULong* length ) - { - FT_Error error; - FT_Stream stream; - TT_Table table; - FT_ULong size; - - - if ( tag != 0 ) - { - /* look for tag in font directory */ - table = tt_face_lookup_table( face, tag ); - if ( !table ) - { - error = FT_THROW( Table_Missing ); - goto Exit; - } - - offset += table->Offset; - size = table->Length; - } - else - /* tag == 0 -- the user wants to access the font file directly */ - size = face->root.stream->size; - - if ( length && *length == 0 ) - { - *length = size; - - return FT_Err_Ok; - } - - if ( length ) - size = *length; - - stream = face->root.stream; - /* the `if' is syntactic sugar for picky compilers */ - if ( FT_STREAM_READ_AT( offset, buffer, size ) ) - goto Exit; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_generic_header */ - /* */ - /* <Description> */ - /* Loads the TrueType table `head' or `bhed'. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - static FT_Error - tt_face_load_generic_header( TT_Face face, - FT_Stream stream, - FT_ULong tag ) - { - FT_Error error; - TT_Header* header; - - static const FT_Frame_Field header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_Header - - FT_FRAME_START( 54 ), - FT_FRAME_ULONG ( Table_Version ), - FT_FRAME_ULONG ( Font_Revision ), - FT_FRAME_LONG ( CheckSum_Adjust ), - FT_FRAME_LONG ( Magic_Number ), - FT_FRAME_USHORT( Flags ), - FT_FRAME_USHORT( Units_Per_EM ), - FT_FRAME_LONG ( Created[0] ), - FT_FRAME_LONG ( Created[1] ), - FT_FRAME_LONG ( Modified[0] ), - FT_FRAME_LONG ( Modified[1] ), - FT_FRAME_SHORT ( xMin ), - FT_FRAME_SHORT ( yMin ), - FT_FRAME_SHORT ( xMax ), - FT_FRAME_SHORT ( yMax ), - FT_FRAME_USHORT( Mac_Style ), - FT_FRAME_USHORT( Lowest_Rec_PPEM ), - FT_FRAME_SHORT ( Font_Direction ), - FT_FRAME_SHORT ( Index_To_Loc_Format ), - FT_FRAME_SHORT ( Glyph_Data_Format ), - FT_FRAME_END - }; - - - error = face->goto_table( face, tag, stream, 0 ); - if ( error ) - goto Exit; - - header = &face->header; - - if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) - goto Exit; - - FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM )); - FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format )); - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_head( TT_Face face, - FT_Stream stream ) - { - return tt_face_load_generic_header( face, stream, TTAG_head ); - } - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_bhed( TT_Face face, - FT_Stream stream ) - { - return tt_face_load_generic_header( face, stream, TTAG_bhed ); - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_max_profile */ - /* */ - /* <Description> */ - /* Loads the maximum profile into a face object. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_maxp( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - TT_MaxProfile* maxProfile = &face->max_profile; - - static const FT_Frame_Field maxp_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_MaxProfile - - FT_FRAME_START( 6 ), - FT_FRAME_LONG ( version ), - FT_FRAME_USHORT( numGlyphs ), - FT_FRAME_END - }; - - static const FT_Frame_Field maxp_fields_extra[] = - { - FT_FRAME_START( 26 ), - FT_FRAME_USHORT( maxPoints ), - FT_FRAME_USHORT( maxContours ), - FT_FRAME_USHORT( maxCompositePoints ), - FT_FRAME_USHORT( maxCompositeContours ), - FT_FRAME_USHORT( maxZones ), - FT_FRAME_USHORT( maxTwilightPoints ), - FT_FRAME_USHORT( maxStorage ), - FT_FRAME_USHORT( maxFunctionDefs ), - FT_FRAME_USHORT( maxInstructionDefs ), - FT_FRAME_USHORT( maxStackElements ), - FT_FRAME_USHORT( maxSizeOfInstructions ), - FT_FRAME_USHORT( maxComponentElements ), - FT_FRAME_USHORT( maxComponentDepth ), - FT_FRAME_END - }; - - - error = face->goto_table( face, TTAG_maxp, stream, 0 ); - if ( error ) - goto Exit; - - if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) ) - goto Exit; - - maxProfile->maxPoints = 0; - maxProfile->maxContours = 0; - maxProfile->maxCompositePoints = 0; - maxProfile->maxCompositeContours = 0; - maxProfile->maxZones = 0; - maxProfile->maxTwilightPoints = 0; - maxProfile->maxStorage = 0; - maxProfile->maxFunctionDefs = 0; - maxProfile->maxInstructionDefs = 0; - maxProfile->maxStackElements = 0; - maxProfile->maxSizeOfInstructions = 0; - maxProfile->maxComponentElements = 0; - maxProfile->maxComponentDepth = 0; - - if ( maxProfile->version >= 0x10000L ) - { - if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) ) - goto Exit; - - /* XXX: an adjustment that is necessary to load certain */ - /* broken fonts like `Keystrokes MT' :-( */ - /* */ - /* We allocate 64 function entries by default when */ - /* the maxFunctionDefs value is smaller. */ - - if ( maxProfile->maxFunctionDefs < 64 ) - maxProfile->maxFunctionDefs = 64; - - /* we add 4 phantom points later */ - if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) ) - { - FT_TRACE0(( "tt_face_load_maxp:" - " too much twilight points in `maxp' table;\n" - " " - " some glyphs might be rendered incorrectly\n" )); - - maxProfile->maxTwilightPoints = 0xFFFFU - 4; - } - - /* we arbitrarily limit recursion to avoid stack exhaustion */ - if ( maxProfile->maxComponentDepth > 100 ) - { - FT_TRACE0(( "tt_face_load_maxp:" - " abnormally large component depth (%d) set to 100\n", - maxProfile->maxComponentDepth )); - maxProfile->maxComponentDepth = 100; - } - } - - FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_name */ - /* */ - /* <Description> */ - /* Loads the name records. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_name( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - FT_ULong table_pos, table_len; - FT_ULong storage_start, storage_limit; - FT_UInt count; - TT_NameTable table; - - static const FT_Frame_Field name_table_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_NameTableRec - - FT_FRAME_START( 6 ), - FT_FRAME_USHORT( format ), - FT_FRAME_USHORT( numNameRecords ), - FT_FRAME_USHORT( storageOffset ), - FT_FRAME_END - }; - - static const FT_Frame_Field name_record_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_NameEntryRec - - /* no FT_FRAME_START */ - FT_FRAME_USHORT( platformID ), - FT_FRAME_USHORT( encodingID ), - FT_FRAME_USHORT( languageID ), - FT_FRAME_USHORT( nameID ), - FT_FRAME_USHORT( stringLength ), - FT_FRAME_USHORT( stringOffset ), - FT_FRAME_END - }; - - - table = &face->name_table; - table->stream = stream; - - error = face->goto_table( face, TTAG_name, stream, &table_len ); - if ( error ) - goto Exit; - - table_pos = FT_STREAM_POS(); - - - if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) - goto Exit; - - /* Some popular Asian fonts have an invalid `storageOffset' value */ - /* (it should be at least "6 + 12*num_names"). However, the string */ - /* offsets, computed as "storageOffset + entry->stringOffset", are */ - /* valid pointers within the name table... */ - /* */ - /* We thus can't check `storageOffset' right now. */ - /* */ - storage_start = table_pos + 6 + 12*table->numNameRecords; - storage_limit = table_pos + table_len; - - if ( storage_start > storage_limit ) - { - FT_ERROR(( "tt_face_load_name: invalid `name' table\n" )); - error = FT_THROW( Name_Table_Missing ); - goto Exit; - } - - /* Allocate the array of name records. */ - count = table->numNameRecords; - table->numNameRecords = 0; - - if ( FT_NEW_ARRAY( table->names, count ) || - FT_FRAME_ENTER( count * 12 ) ) - goto Exit; - - /* Load the name records and determine how much storage is needed */ - /* to hold the strings themselves. */ - { - TT_NameEntryRec* entry = table->names; - - - for ( ; count > 0; count-- ) - { - if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) ) - continue; - - /* check that the name is not empty */ - if ( entry->stringLength == 0 ) - continue; - - /* check that the name string is within the table */ - entry->stringOffset += table_pos + table->storageOffset; - if ( entry->stringOffset < storage_start || - entry->stringOffset + entry->stringLength > storage_limit ) - { - /* invalid entry - ignore it */ - entry->stringOffset = 0; - entry->stringLength = 0; - continue; - } - - entry++; - } - - table->numNameRecords = (FT_UInt)( entry - table->names ); - } - - FT_FRAME_EXIT(); - - /* everything went well, update face->num_names */ - face->num_names = (FT_UShort) table->numNameRecords; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_free_names */ - /* */ - /* <Description> */ - /* Frees the name records. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - FT_LOCAL_DEF( void ) - tt_face_free_name( TT_Face face ) - { - FT_Memory memory = face->root.driver->root.memory; - TT_NameTable table = &face->name_table; - TT_NameEntry entry = table->names; - FT_UInt count = table->numNameRecords; - - - if ( table->names ) - { - for ( ; count > 0; count--, entry++ ) - { - FT_FREE( entry->string ); - entry->stringLength = 0; - } - - /* free strings table */ - FT_FREE( table->names ); - } - - table->numNameRecords = 0; - table->format = 0; - table->storageOffset = 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_cmap */ - /* */ - /* <Description> */ - /* Loads the cmap directory in a face object. The cmaps themselves */ - /* are loaded on demand in the `ttcmap.c' module. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_cmap( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - - - error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); - if ( error ) - goto Exit; - - if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) - face->cmap_size = 0; - - Exit: - return error; - } - - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_os2 */ - /* */ - /* <Description> */ - /* Loads the OS2 table. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_os2( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - TT_OS2* os2; - - static const FT_Frame_Field os2_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_OS2 - - FT_FRAME_START( 78 ), - FT_FRAME_USHORT( version ), - FT_FRAME_SHORT ( xAvgCharWidth ), - FT_FRAME_USHORT( usWeightClass ), - FT_FRAME_USHORT( usWidthClass ), - FT_FRAME_SHORT ( fsType ), - FT_FRAME_SHORT ( ySubscriptXSize ), - FT_FRAME_SHORT ( ySubscriptYSize ), - FT_FRAME_SHORT ( ySubscriptXOffset ), - FT_FRAME_SHORT ( ySubscriptYOffset ), - FT_FRAME_SHORT ( ySuperscriptXSize ), - FT_FRAME_SHORT ( ySuperscriptYSize ), - FT_FRAME_SHORT ( ySuperscriptXOffset ), - FT_FRAME_SHORT ( ySuperscriptYOffset ), - FT_FRAME_SHORT ( yStrikeoutSize ), - FT_FRAME_SHORT ( yStrikeoutPosition ), - FT_FRAME_SHORT ( sFamilyClass ), - FT_FRAME_BYTE ( panose[0] ), - FT_FRAME_BYTE ( panose[1] ), - FT_FRAME_BYTE ( panose[2] ), - FT_FRAME_BYTE ( panose[3] ), - FT_FRAME_BYTE ( panose[4] ), - FT_FRAME_BYTE ( panose[5] ), - FT_FRAME_BYTE ( panose[6] ), - FT_FRAME_BYTE ( panose[7] ), - FT_FRAME_BYTE ( panose[8] ), - FT_FRAME_BYTE ( panose[9] ), - FT_FRAME_ULONG ( ulUnicodeRange1 ), - FT_FRAME_ULONG ( ulUnicodeRange2 ), - FT_FRAME_ULONG ( ulUnicodeRange3 ), - FT_FRAME_ULONG ( ulUnicodeRange4 ), - FT_FRAME_BYTE ( achVendID[0] ), - FT_FRAME_BYTE ( achVendID[1] ), - FT_FRAME_BYTE ( achVendID[2] ), - FT_FRAME_BYTE ( achVendID[3] ), - - FT_FRAME_USHORT( fsSelection ), - FT_FRAME_USHORT( usFirstCharIndex ), - FT_FRAME_USHORT( usLastCharIndex ), - FT_FRAME_SHORT ( sTypoAscender ), - FT_FRAME_SHORT ( sTypoDescender ), - FT_FRAME_SHORT ( sTypoLineGap ), - FT_FRAME_USHORT( usWinAscent ), - FT_FRAME_USHORT( usWinDescent ), - FT_FRAME_END - }; - - /* `OS/2' version 1 and newer */ - static const FT_Frame_Field os2_fields_extra1[] = - { - FT_FRAME_START( 8 ), - FT_FRAME_ULONG( ulCodePageRange1 ), - FT_FRAME_ULONG( ulCodePageRange2 ), - FT_FRAME_END - }; - - /* `OS/2' version 2 and newer */ - static const FT_Frame_Field os2_fields_extra2[] = - { - FT_FRAME_START( 10 ), - FT_FRAME_SHORT ( sxHeight ), - FT_FRAME_SHORT ( sCapHeight ), - FT_FRAME_USHORT( usDefaultChar ), - FT_FRAME_USHORT( usBreakChar ), - FT_FRAME_USHORT( usMaxContext ), - FT_FRAME_END - }; - - /* `OS/2' version 5 and newer */ - static const FT_Frame_Field os2_fields_extra5[] = - { - FT_FRAME_START( 4 ), - FT_FRAME_USHORT( usLowerOpticalPointSize ), - FT_FRAME_USHORT( usUpperOpticalPointSize ), - FT_FRAME_END - }; - - - /* We now support old Mac fonts where the OS/2 table doesn't */ - /* exist. Simply put, we set the `version' field to 0xFFFF */ - /* and test this value each time we need to access the table. */ - error = face->goto_table( face, TTAG_OS2, stream, 0 ); - if ( error ) - goto Exit; - - os2 = &face->os2; - - if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) ) - goto Exit; - - os2->ulCodePageRange1 = 0; - os2->ulCodePageRange2 = 0; - os2->sxHeight = 0; - os2->sCapHeight = 0; - os2->usDefaultChar = 0; - os2->usBreakChar = 0; - os2->usMaxContext = 0; - os2->usLowerOpticalPointSize = 0; - os2->usUpperOpticalPointSize = 0xFFFF; - - if ( os2->version >= 0x0001 ) - { - /* only version 1 tables */ - if ( FT_STREAM_READ_FIELDS( os2_fields_extra1, os2 ) ) - goto Exit; - - if ( os2->version >= 0x0002 ) - { - /* only version 2 tables */ - if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) ) - goto Exit; - - if ( os2->version >= 0x0005 ) - { - /* only version 5 tables */ - if ( FT_STREAM_READ_FIELDS( os2_fields_extra5, os2 ) ) - goto Exit; - } - } - } - - FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); - FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); - FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); - FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); - FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_postscript */ - /* */ - /* <Description> */ - /* Loads the Postscript table. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_post( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - TT_Postscript* post = &face->postscript; - - static const FT_Frame_Field post_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_Postscript - - FT_FRAME_START( 32 ), - FT_FRAME_ULONG( FormatType ), - FT_FRAME_ULONG( italicAngle ), - FT_FRAME_SHORT( underlinePosition ), - FT_FRAME_SHORT( underlineThickness ), - FT_FRAME_ULONG( isFixedPitch ), - FT_FRAME_ULONG( minMemType42 ), - FT_FRAME_ULONG( maxMemType42 ), - FT_FRAME_ULONG( minMemType1 ), - FT_FRAME_ULONG( maxMemType1 ), - FT_FRAME_END - }; - - - error = face->goto_table( face, TTAG_post, stream, 0 ); - if ( error ) - return error; - - if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) - return error; - - /* we don't load the glyph names, we do that in another */ - /* module (ttpost). */ - - FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType )); - FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch - ? " yes" : " no" )); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_pclt */ - /* */ - /* <Description> */ - /* Loads the PCL 5 Table. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_pclt( TT_Face face, - FT_Stream stream ) - { - static const FT_Frame_Field pclt_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_PCLT - - FT_FRAME_START( 54 ), - FT_FRAME_ULONG ( Version ), - FT_FRAME_ULONG ( FontNumber ), - FT_FRAME_USHORT( Pitch ), - FT_FRAME_USHORT( xHeight ), - FT_FRAME_USHORT( Style ), - FT_FRAME_USHORT( TypeFamily ), - FT_FRAME_USHORT( CapHeight ), - FT_FRAME_USHORT( SymbolSet ), - FT_FRAME_BYTES ( TypeFace, 16 ), - FT_FRAME_BYTES ( CharacterComplement, 8 ), - FT_FRAME_BYTES ( FileName, 6 ), - FT_FRAME_CHAR ( StrokeWeight ), - FT_FRAME_CHAR ( WidthType ), - FT_FRAME_BYTE ( SerifStyle ), - FT_FRAME_BYTE ( Reserved ), - FT_FRAME_END - }; - - FT_Error error; - TT_PCLT* pclt = &face->pclt; - - - /* optional table */ - error = face->goto_table( face, TTAG_PCLT, stream, 0 ); - if ( error ) - goto Exit; - - if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) - goto Exit; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_gasp */ - /* */ - /* <Description> */ - /* Loads the `gasp' table into a face object. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_gasp( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UInt j,num_ranges; - TT_GaspRange gaspranges = NULL; - - - /* the gasp table is optional */ - error = face->goto_table( face, TTAG_gasp, stream, 0 ); - if ( error ) - goto Exit; - - if ( FT_FRAME_ENTER( 4L ) ) - goto Exit; - - face->gasp.version = FT_GET_USHORT(); - face->gasp.numRanges = FT_GET_USHORT(); - - FT_FRAME_EXIT(); - - /* only support versions 0 and 1 of the table */ - if ( face->gasp.version >= 2 ) - { - face->gasp.numRanges = 0; - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - num_ranges = face->gasp.numRanges; - FT_TRACE3(( "numRanges: %u\n", num_ranges )); - - if ( FT_QNEW_ARRAY( face->gasp.gaspRanges, num_ranges ) || - FT_FRAME_ENTER( num_ranges * 4L ) ) - goto Exit; - - gaspranges = face->gasp.gaspRanges; - - for ( j = 0; j < num_ranges; j++ ) - { - gaspranges[j].maxPPEM = FT_GET_USHORT(); - gaspranges[j].gaspFlag = FT_GET_USHORT(); - - FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n", - j, - gaspranges[j].maxPPEM, - gaspranges[j].gaspFlag )); - } - - FT_FRAME_EXIT(); - - Exit: - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttload.h b/third_party/freetype/src/sfnt/ttload.h deleted file mode 100644 index a6d91c5b702a38b6dcb94503a252131af8aaaf8d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttload.h +++ /dev/null @@ -1,112 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttload.h */ -/* */ -/* Load the basic TrueType tables, i.e., tables that can be either in */ -/* TTF or OTF fonts (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTLOAD_H__ -#define __TTLOAD_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( TT_Table ) - tt_face_lookup_table( TT_Face face, - FT_ULong tag ); - - FT_LOCAL( FT_Error ) - tt_face_goto_table( TT_Face face, - FT_ULong tag, - FT_Stream stream, - FT_ULong* length ); - - - FT_LOCAL( FT_Error ) - tt_face_load_font_dir( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_any( TT_Face face, - FT_ULong tag, - FT_Long offset, - FT_Byte* buffer, - FT_ULong* length ); - - - FT_LOCAL( FT_Error ) - tt_face_load_head( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_cmap( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_maxp( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_name( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_os2( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_post( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_pclt( TT_Face face, - FT_Stream stream ); - - FT_LOCAL( void ) - tt_face_free_name( TT_Face face ); - - - FT_LOCAL( FT_Error ) - tt_face_load_gasp( TT_Face face, - FT_Stream stream ); - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - FT_LOCAL( FT_Error ) - tt_face_load_bhed( TT_Face face, - FT_Stream stream ); - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - -FT_END_HEADER - -#endif /* __TTLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttmtx.c b/third_party/freetype/src/sfnt/ttmtx.c deleted file mode 100644 index 58309aa496efb097fc892e036b89f13a1500c115..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttmtx.c +++ /dev/null @@ -1,280 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttmtx.c */ -/* */ -/* Load the metrics tables common to TTF and OTF fonts (body). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include "ttmtx.h" - -#include "sferrors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttmtx - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_hmtx */ - /* */ - /* <Description> */ - /* Load the `hmtx' or `vmtx' table into a face object. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* vertical :: A boolean flag. If set, load `vmtx'. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_hmtx( TT_Face face, - FT_Stream stream, - FT_Bool vertical ) - { - FT_Error error; - FT_ULong tag, table_size; - FT_ULong* ptable_offset; - FT_ULong* ptable_size; - - - if ( vertical ) - { - tag = TTAG_vmtx; - ptable_offset = &face->vert_metrics_offset; - ptable_size = &face->vert_metrics_size; - } - else - { - tag = TTAG_hmtx; - ptable_offset = &face->horz_metrics_offset; - ptable_size = &face->horz_metrics_size; - } - - error = face->goto_table( face, tag, stream, &table_size ); - if ( error ) - goto Fail; - - *ptable_size = table_size; - *ptable_offset = FT_STREAM_POS(); - - Fail: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_hhea */ - /* */ - /* <Description> */ - /* Load the `hhea' or 'vhea' table into a face object. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: The input stream. */ - /* */ - /* vertical :: A boolean flag. If set, load `vhea'. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_hhea( TT_Face face, - FT_Stream stream, - FT_Bool vertical ) - { - FT_Error error; - TT_HoriHeader* header; - - static const FT_Frame_Field metrics_header_fields[] = - { -#undef FT_STRUCTURE -#define FT_STRUCTURE TT_HoriHeader - - FT_FRAME_START( 36 ), - FT_FRAME_ULONG ( Version ), - FT_FRAME_SHORT ( Ascender ), - FT_FRAME_SHORT ( Descender ), - FT_FRAME_SHORT ( Line_Gap ), - FT_FRAME_USHORT( advance_Width_Max ), - FT_FRAME_SHORT ( min_Left_Side_Bearing ), - FT_FRAME_SHORT ( min_Right_Side_Bearing ), - FT_FRAME_SHORT ( xMax_Extent ), - FT_FRAME_SHORT ( caret_Slope_Rise ), - FT_FRAME_SHORT ( caret_Slope_Run ), - FT_FRAME_SHORT ( caret_Offset ), - FT_FRAME_SHORT ( Reserved[0] ), - FT_FRAME_SHORT ( Reserved[1] ), - FT_FRAME_SHORT ( Reserved[2] ), - FT_FRAME_SHORT ( Reserved[3] ), - FT_FRAME_SHORT ( metric_Data_Format ), - FT_FRAME_USHORT( number_Of_HMetrics ), - FT_FRAME_END - }; - - - if ( vertical ) - { - void *v = &face->vertical; - - - error = face->goto_table( face, TTAG_vhea, stream, 0 ); - if ( error ) - goto Fail; - - header = (TT_HoriHeader*)v; - } - else - { - error = face->goto_table( face, TTAG_hhea, stream, 0 ); - if ( error ) - goto Fail; - - header = &face->horizontal; - } - - if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) - goto Fail; - - FT_TRACE3(( "Ascender: %5d\n", header->Ascender )); - FT_TRACE3(( "Descender: %5d\n", header->Descender )); - FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics )); - - header->long_metrics = NULL; - header->short_metrics = NULL; - - Fail: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_get_metrics */ - /* */ - /* <Description> */ - /* Return the horizontal or vertical metrics in font units for a */ - /* given glyph. The values are the left side bearing (top side */ - /* bearing for vertical metrics) and advance width (advance height */ - /* for vertical metrics). */ - /* */ - /* <Input> */ - /* face :: A pointer to the TrueType face structure. */ - /* */ - /* vertical :: If set to TRUE, get vertical metrics. */ - /* */ - /* gindex :: The glyph index. */ - /* */ - /* <Output> */ - /* abearing :: The bearing, either left side or top side. */ - /* */ - /* aadvance :: The advance width or advance height, depending on */ - /* the `vertical' flag. */ - /* */ - FT_LOCAL_DEF( void ) - tt_face_get_metrics( TT_Face face, - FT_Bool vertical, - FT_UInt gindex, - FT_Short *abearing, - FT_UShort *aadvance ) - { - FT_Error error; - FT_Stream stream = face->root.stream; - TT_HoriHeader* header; - FT_ULong table_pos, table_size, table_end; - FT_UShort k; - - - if ( vertical ) - { - void* v = &face->vertical; - - - header = (TT_HoriHeader*)v; - table_pos = face->vert_metrics_offset; - table_size = face->vert_metrics_size; - } - else - { - header = &face->horizontal; - table_pos = face->horz_metrics_offset; - table_size = face->horz_metrics_size; - } - - table_end = table_pos + table_size; - - k = header->number_Of_HMetrics; - - if ( k > 0 ) - { - if ( gindex < (FT_UInt)k ) - { - table_pos += 4 * gindex; - if ( table_pos + 4 > table_end ) - goto NoData; - - if ( FT_STREAM_SEEK( table_pos ) || - FT_READ_USHORT( *aadvance ) || - FT_READ_SHORT( *abearing ) ) - goto NoData; - } - else - { - table_pos += 4 * ( k - 1 ); - if ( table_pos + 4 > table_end ) - goto NoData; - - if ( FT_STREAM_SEEK( table_pos ) || - FT_READ_USHORT( *aadvance ) ) - goto NoData; - - table_pos += 4 + 2 * ( gindex - k ); - if ( table_pos + 2 > table_end ) - *abearing = 0; - else - { - if ( !FT_STREAM_SEEK( table_pos ) ) - (void)FT_READ_SHORT( *abearing ); - } - } - } - else - { - NoData: - *abearing = 0; - *aadvance = 0; - } - } - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttmtx.h b/third_party/freetype/src/sfnt/ttmtx.h deleted file mode 100644 index 096ee062cf078ba14384c65fd6951d7459725bd3..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttmtx.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttmtx.h */ -/* */ -/* Load the metrics tables common to TTF and OTF fonts (specification). */ -/* */ -/* Copyright 2006-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTMTX_H__ -#define __TTMTX_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - tt_face_load_hhea( TT_Face face, - FT_Stream stream, - FT_Bool vertical ); - - - FT_LOCAL( FT_Error ) - tt_face_load_hmtx( TT_Face face, - FT_Stream stream, - FT_Bool vertical ); - - - FT_LOCAL( void ) - tt_face_get_metrics( TT_Face face, - FT_Bool vertical, - FT_UInt gindex, - FT_Short* abearing, - FT_UShort* aadvance ); - -FT_END_HEADER - -#endif /* __TTMTX_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttpost.c b/third_party/freetype/src/sfnt/ttpost.c deleted file mode 100644 index 8d29d1e9f6d34c334b17ca8b3abd1d52ad6e618c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttpost.c +++ /dev/null @@ -1,563 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttpost.c */ -/* */ -/* Postcript name table processing for TrueType and OpenType fonts */ -/* (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* The post table is not completely loaded by the core engine. This */ - /* file loads the missing PS glyph names and implements an API to access */ - /* them. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include "ttpost.h" - -#include "sferrors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttpost - - - /* If this configuration macro is defined, we rely on the `PSNames' */ - /* module to grab the glyph names. */ - -#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES - - -#include FT_SERVICE_POSTSCRIPT_CMAPS_H - -#define MAC_NAME( x ) (FT_String*)psnames->macintosh_name( (FT_UInt)(x) ) - - -#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ - - - /* Otherwise, we ignore the `PSNames' module, and provide our own */ - /* table of Mac names. Thus, it is possible to build a version of */ - /* FreeType without the Type 1 driver & PSNames module. */ - -#define MAC_NAME( x ) (FT_String*)tt_post_default_names[x] - - /* the 258 default Mac PS glyph names; see file `tools/glnames.py' */ - - static const FT_String* const tt_post_default_names[258] = - { - /* 0 */ - ".notdef", ".null", "nonmarkingreturn", "space", "exclam", - "quotedbl", "numbersign", "dollar", "percent", "ampersand", - /* 10 */ - "quotesingle", "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", "zero", - /* 20 */ - "one", "two", "three", "four", "five", - "six", "seven", "eight", "nine", "colon", - /* 30 */ - "semicolon", "less", "equal", "greater", "question", - "at", "A", "B", "C", "D", - /* 40 */ - "E", "F", "G", "H", "I", - "J", "K", "L", "M", "N", - /* 50 */ - "O", "P", "Q", "R", "S", - "T", "U", "V", "W", "X", - /* 60 */ - "Y", "Z", "bracketleft", "backslash", "bracketright", - "asciicircum", "underscore", "grave", "a", "b", - /* 70 */ - "c", "d", "e", "f", "g", - "h", "i", "j", "k", "l", - /* 80 */ - "m", "n", "o", "p", "q", - "r", "s", "t", "u", "v", - /* 90 */ - "w", "x", "y", "z", "braceleft", - "bar", "braceright", "asciitilde", "Adieresis", "Aring", - /* 100 */ - "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", - "aacute", "agrave", "acircumflex", "adieresis", "atilde", - /* 110 */ - "aring", "ccedilla", "eacute", "egrave", "ecircumflex", - "edieresis", "iacute", "igrave", "icircumflex", "idieresis", - /* 120 */ - "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", - "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", - /* 130 */ - "dagger", "degree", "cent", "sterling", "section", - "bullet", "paragraph", "germandbls", "registered", "copyright", - /* 140 */ - "trademark", "acute", "dieresis", "notequal", "AE", - "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", - /* 150 */ - "yen", "mu", "partialdiff", "summation", "product", - "pi", "integral", "ordfeminine", "ordmasculine", "Omega", - /* 160 */ - "ae", "oslash", "questiondown", "exclamdown", "logicalnot", - "radical", "florin", "approxequal", "Delta", "guillemotleft", - /* 170 */ - "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", - "Otilde", "OE", "oe", "endash", "emdash", - /* 180 */ - "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", - "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", - /* 190 */ - "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", - "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", - /* 200 */ - "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", - "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", - /* 210 */ - "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", - "dotlessi", "circumflex", "tilde", "macron", "breve", - /* 220 */ - "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", - "caron", "Lslash", "lslash", "Scaron", "scaron", - /* 230 */ - "Zcaron", "zcaron", "brokenbar", "Eth", "eth", - "Yacute", "yacute", "Thorn", "thorn", "minus", - /* 240 */ - "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", - "onequarter", "threequarters", "franc", "Gbreve", "gbreve", - /* 250 */ - "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", - "Ccaron", "ccaron", "dcroat", - }; - - -#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ - - - static FT_Error - load_format_20( TT_Face face, - FT_Stream stream, - FT_ULong post_limit ) - { - FT_Memory memory = stream->memory; - FT_Error error; - - FT_Int num_glyphs; - FT_UShort num_names; - - FT_UShort* glyph_indices = NULL; - FT_Char** name_strings = NULL; - - - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ - /* than the value in the maxp table (cf. cyberbit.ttf). */ - - /* There already exist fonts which have more than 32768 glyph names */ - /* in this table, so the test for this threshold has been dropped. */ - - if ( num_glyphs > face->max_profile.numGlyphs ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* load the indices */ - { - FT_Int n; - - - if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) || - FT_FRAME_ENTER( num_glyphs * 2L ) ) - goto Fail; - - for ( n = 0; n < num_glyphs; n++ ) - glyph_indices[n] = FT_GET_USHORT(); - - FT_FRAME_EXIT(); - } - - /* compute number of names stored in table */ - { - FT_Int n; - - - num_names = 0; - - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Int idx; - - - idx = glyph_indices[n]; - if ( idx >= 258 ) - { - idx -= 257; - if ( idx > num_names ) - num_names = (FT_UShort)idx; - } - } - } - - /* now load the name strings */ - { - FT_UShort n; - - - if ( FT_NEW_ARRAY( name_strings, num_names ) ) - goto Fail; - - for ( n = 0; n < num_names; n++ ) - { - FT_UInt len; - - - if ( FT_STREAM_POS() >= post_limit ) - break; - else - { - FT_TRACE6(( "load_format_20: %d byte left in post table\n", - post_limit - FT_STREAM_POS() )); - - if ( FT_READ_BYTE( len ) ) - goto Fail1; - } - - if ( len > post_limit || - FT_STREAM_POS() > post_limit - len ) - { - FT_Int d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS(); - - - FT_ERROR(( "load_format_20:" - " exceeding string length (%d)," - " truncating at end of post table (%d byte left)\n", - len, d )); - len = (FT_UInt)FT_MAX( 0, d ); - } - - if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) || - FT_STREAM_READ( name_strings[n], len ) ) - goto Fail1; - - name_strings[n][len] = '\0'; - } - - if ( n < num_names ) - { - FT_ERROR(( "load_format_20:" - " all entries in post table are already parsed," - " using NULL names for gid %d - %d\n", - n, num_names - 1 )); - for ( ; n < num_names; n++ ) - if ( FT_NEW_ARRAY( name_strings[n], 1 ) ) - goto Fail1; - else - name_strings[n][0] = '\0'; - } - } - - /* all right, set table fields and exit successfully */ - { - TT_Post_20 table = &face->postscript_names.names.format_20; - - - table->num_glyphs = (FT_UShort)num_glyphs; - table->num_names = (FT_UShort)num_names; - table->glyph_indices = glyph_indices; - table->glyph_names = name_strings; - } - return FT_Err_Ok; - - Fail1: - { - FT_UShort n; - - - for ( n = 0; n < num_names; n++ ) - FT_FREE( name_strings[n] ); - } - - Fail: - FT_FREE( name_strings ); - FT_FREE( glyph_indices ); - - Exit: - return error; - } - - - static FT_Error - load_format_25( TT_Face face, - FT_Stream stream, - FT_ULong post_limit ) - { - FT_Memory memory = stream->memory; - FT_Error error; - - FT_Int num_glyphs; - FT_Char* offset_table = NULL; - - FT_UNUSED( post_limit ); - - - /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* check the number of glyphs */ - if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( FT_NEW_ARRAY( offset_table, num_glyphs ) || - FT_STREAM_READ( offset_table, num_glyphs ) ) - goto Fail; - - /* now check the offset table */ - { - FT_Int n; - - - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Long idx = (FT_Long)n + offset_table[n]; - - - if ( idx < 0 || idx > num_glyphs ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - } - } - - /* OK, set table fields and exit successfully */ - { - TT_Post_25 table = &face->postscript_names.names.format_25; - - - table->num_glyphs = (FT_UShort)num_glyphs; - table->offsets = offset_table; - } - - return FT_Err_Ok; - - Fail: - FT_FREE( offset_table ); - - Exit: - return error; - } - - - static FT_Error - load_post_names( TT_Face face ) - { - FT_Stream stream; - FT_Error error; - FT_Fixed format; - FT_ULong post_len; - FT_ULong post_limit; - - - /* get a stream for the face's resource */ - stream = face->root.stream; - - /* seek to the beginning of the PS names table */ - error = face->goto_table( face, TTAG_post, stream, &post_len ); - if ( error ) - goto Exit; - - post_limit = FT_STREAM_POS() + post_len; - - format = face->postscript.FormatType; - - /* go to beginning of subtable */ - if ( FT_STREAM_SKIP( 32 ) ) - goto Exit; - - /* now read postscript table */ - if ( format == 0x00020000L ) - error = load_format_20( face, stream, post_limit ); - else if ( format == 0x00028000L ) - error = load_format_25( face, stream, post_limit ); - else - error = FT_THROW( Invalid_File_Format ); - - face->postscript_names.loaded = 1; - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - tt_face_free_ps_names( TT_Face face ) - { - FT_Memory memory = face->root.memory; - TT_Post_Names names = &face->postscript_names; - FT_Fixed format; - - - if ( names->loaded ) - { - format = face->postscript.FormatType; - - if ( format == 0x00020000L ) - { - TT_Post_20 table = &names->names.format_20; - FT_UShort n; - - - FT_FREE( table->glyph_indices ); - table->num_glyphs = 0; - - for ( n = 0; n < table->num_names; n++ ) - FT_FREE( table->glyph_names[n] ); - - FT_FREE( table->glyph_names ); - table->num_names = 0; - } - else if ( format == 0x00028000L ) - { - TT_Post_25 table = &names->names.format_25; - - - FT_FREE( table->offsets ); - table->num_glyphs = 0; - } - } - names->loaded = 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_get_ps_name */ - /* */ - /* <Description> */ - /* Get the PostScript glyph name of a glyph. */ - /* */ - /* <Input> */ - /* face :: A handle to the parent face. */ - /* */ - /* idx :: The glyph index. */ - /* */ - /* <InOut> */ - /* PSname :: The address of a string pointer. Will be NULL in case */ - /* of error, otherwise it is a pointer to the glyph name. */ - /* */ - /* You must not modify the returned string! */ - /* */ - /* <Output> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_get_ps_name( TT_Face face, - FT_UInt idx, - FT_String** PSname ) - { - FT_Error error; - TT_Post_Names names; - FT_Fixed format; - -#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES - FT_Service_PsCMaps psnames; -#endif - - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - - if ( idx >= (FT_UInt)face->max_profile.numGlyphs ) - return FT_THROW( Invalid_Glyph_Index ); - -#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES - psnames = (FT_Service_PsCMaps)face->psnames; - if ( !psnames ) - return FT_THROW( Unimplemented_Feature ); -#endif - - names = &face->postscript_names; - - /* `.notdef' by default */ - *PSname = MAC_NAME( 0 ); - - format = face->postscript.FormatType; - - if ( format == 0x00010000L ) - { - if ( idx < 258 ) /* paranoid checking */ - *PSname = MAC_NAME( idx ); - } - else if ( format == 0x00020000L ) - { - TT_Post_20 table = &names->names.format_20; - - - if ( !names->loaded ) - { - error = load_post_names( face ); - if ( error ) - goto End; - } - - if ( idx < (FT_UInt)table->num_glyphs ) - { - FT_UShort name_index = table->glyph_indices[idx]; - - - if ( name_index < 258 ) - *PSname = MAC_NAME( name_index ); - else - *PSname = (FT_String*)table->glyph_names[name_index - 258]; - } - } - else if ( format == 0x00028000L ) - { - TT_Post_25 table = &names->names.format_25; - - - if ( !names->loaded ) - { - error = load_post_names( face ); - if ( error ) - goto End; - } - - if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ - *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] ); - } - - /* nothing to do for format == 0x00030000L */ - - End: - return FT_Err_Ok; - } - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttpost.h b/third_party/freetype/src/sfnt/ttpost.h deleted file mode 100644 index e3eca02c62324a0900edacd178d2b9af9860247e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttpost.h +++ /dev/null @@ -1,46 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttpost.h */ -/* */ -/* Postcript name table processing for TrueType and OpenType fonts */ -/* (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTPOST_H__ -#define __TTPOST_H__ - - -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - tt_face_get_ps_name( TT_Face face, - FT_UInt idx, - FT_String** PSname ); - - FT_LOCAL( void ) - tt_face_free_ps_names( TT_Face face ); - - -FT_END_HEADER - -#endif /* __TTPOST_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/sfnt/ttsbit.c b/third_party/freetype/src/sfnt/ttsbit.c deleted file mode 100644 index 3b351ecfce458b8408b48faab2fc324a8cb81499..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttsbit.c +++ /dev/null @@ -1,1472 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttsbit.c */ -/* */ -/* TrueType and OpenType embedded bitmap support (body). */ -/* */ -/* Copyright 2005-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* Copyright 2013 by Google, Inc. */ -/* Google Author(s): Behdad Esfahbod. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include FT_BITMAP_H -#include "ttsbit.h" - -#include "sferrors.h" - -#include "ttmtx.h" -#include "pngshim.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttsbit - - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_sbit( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_ULong table_size; - - - face->sbit_table = NULL; - face->sbit_table_size = 0; - face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE; - face->sbit_num_strikes = 0; - - error = face->goto_table( face, TTAG_CBLC, stream, &table_size ); - if ( !error ) - face->sbit_table_type = TT_SBIT_TABLE_TYPE_CBLC; - else - { - error = face->goto_table( face, TTAG_EBLC, stream, &table_size ); - if ( error ) - error = face->goto_table( face, TTAG_bloc, stream, &table_size ); - if ( !error ) - face->sbit_table_type = TT_SBIT_TABLE_TYPE_EBLC; - } - - if ( error ) - { - error = face->goto_table( face, TTAG_sbix, stream, &table_size ); - if ( !error ) - face->sbit_table_type = TT_SBIT_TABLE_TYPE_SBIX; - } - if ( error ) - goto Exit; - - if ( table_size < 8 ) - { - FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - switch ( (FT_UInt)face->sbit_table_type ) - { - case TT_SBIT_TABLE_TYPE_EBLC: - case TT_SBIT_TABLE_TYPE_CBLC: - { - FT_Byte* p; - FT_Fixed version; - FT_ULong num_strikes; - FT_UInt count; - - - if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) ) - goto Exit; - - face->sbit_table_size = table_size; - - p = face->sbit_table; - - version = FT_NEXT_LONG( p ); - num_strikes = FT_NEXT_ULONG( p ); - - if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL ) - { - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - if ( num_strikes >= 0x10000UL ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* - * Count the number of strikes available in the table. We are a bit - * paranoid there and don't trust the data. - */ - count = (FT_UInt)num_strikes; - if ( 8 + 48UL * count > table_size ) - count = (FT_UInt)( ( table_size - 8 ) / 48 ); - - face->sbit_num_strikes = count; - } - break; - - case TT_SBIT_TABLE_TYPE_SBIX: - { - FT_UShort version; - FT_UShort flags; - FT_ULong num_strikes; - FT_UInt count; - - - if ( FT_FRAME_ENTER( 8 ) ) - goto Exit; - - version = FT_GET_USHORT(); - flags = FT_GET_USHORT(); - num_strikes = FT_GET_ULONG(); - - FT_FRAME_EXIT(); - - if ( version < 1 ) - { - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - /* Bit 0 must always be `1'. */ - /* Bit 1 controls the overlay of bitmaps with outlines. */ - /* All other bits should be zero. */ - if ( !( flags == 1 || flags == 3 ) || - num_strikes >= 0x10000UL ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* we currently don't support bit 1; however, it is better to */ - /* draw at least something... */ - if ( flags == 3 ) - FT_TRACE1(( "tt_face_load_sbit_strikes:" - " sbix overlay not supported yet\n" - " " - " expect bad rendering results\n" )); - - /* - * Count the number of strikes available in the table. We are a bit - * paranoid there and don't trust the data. - */ - count = (FT_UInt)num_strikes; - if ( 8 + 4UL * count > table_size ) - count = (FT_UInt)( ( table_size - 8 ) / 4 ); - - if ( FT_STREAM_SEEK( FT_STREAM_POS() - 8 ) ) - goto Exit; - - face->sbit_table_size = 8 + count * 4; - if ( FT_FRAME_EXTRACT( face->sbit_table_size, face->sbit_table ) ) - goto Exit; - - face->sbit_num_strikes = count; - } - break; - - default: - error = FT_THROW( Unknown_File_Format ); - break; - } - - if ( !error ) - FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes )); - - return FT_Err_Ok; - - Exit: - if ( error ) - { - if ( face->sbit_table ) - FT_FRAME_RELEASE( face->sbit_table ); - face->sbit_table_size = 0; - face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE; - } - - return error; - } - - - FT_LOCAL_DEF( void ) - tt_face_free_sbit( TT_Face face ) - { - FT_Stream stream = face->root.stream; - - - FT_FRAME_RELEASE( face->sbit_table ); - face->sbit_table_size = 0; - face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE; - face->sbit_num_strikes = 0; - } - - - FT_LOCAL_DEF( FT_Error ) - tt_face_set_sbit_strike( TT_Face face, - FT_Size_Request req, - FT_ULong* astrike_index ) - { - return FT_Match_Size( (FT_Face)face, req, 0, astrike_index ); - } - - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_strike_metrics( TT_Face face, - FT_ULong strike_index, - FT_Size_Metrics* metrics ) - { - if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) - return FT_THROW( Invalid_Argument ); - - switch ( (FT_UInt)face->sbit_table_type ) - { - case TT_SBIT_TABLE_TYPE_EBLC: - case TT_SBIT_TABLE_TYPE_CBLC: - { - FT_Byte* strike; - - - strike = face->sbit_table + 8 + strike_index * 48; - - metrics->x_ppem = (FT_UShort)strike[44]; - metrics->y_ppem = (FT_UShort)strike[45]; - - metrics->ascender = (FT_Char)strike[16] * 64; /* hori.ascender */ - metrics->descender = (FT_Char)strike[17] * 64; /* hori.descender */ - metrics->height = metrics->ascender - metrics->descender; - - /* Is this correct? */ - metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */ - strike[18] + /* max_width */ - (FT_Char)strike[23] /* min_advance_SB */ - ) * 64; - return FT_Err_Ok; - } - - case TT_SBIT_TABLE_TYPE_SBIX: - { - FT_Stream stream = face->root.stream; - FT_UInt offset, upem; - FT_UShort ppem, resolution; - TT_HoriHeader *hori; - FT_ULong table_size; - FT_Pos ppem_, upem_; /* to reduce casts */ - - FT_Error error; - FT_Byte* p; - - - p = face->sbit_table + 8 + 4 * strike_index; - offset = FT_NEXT_ULONG( p ); - - error = face->goto_table( face, TTAG_sbix, stream, &table_size ); - if ( error ) - return error; - - if ( offset + 4 > table_size ) - return FT_THROW( Invalid_File_Format ); - - if ( FT_STREAM_SEEK( FT_STREAM_POS() + offset ) || - FT_FRAME_ENTER( 4 ) ) - return error; - - ppem = FT_GET_USHORT(); - resolution = FT_GET_USHORT(); - - FT_UNUSED( resolution ); /* What to do with this? */ - - FT_FRAME_EXIT(); - - upem = face->header.Units_Per_EM; - hori = &face->horizontal; - - metrics->x_ppem = ppem; - metrics->y_ppem = ppem; - - ppem_ = (FT_Pos)ppem; - upem_ = (FT_Pos)upem; - - metrics->ascender = ppem_ * hori->Ascender * 64 / upem_; - metrics->descender = ppem_ * hori->Descender * 64 / upem_; - metrics->height = ppem_ * ( hori->Ascender - - hori->Descender + - hori->Line_Gap ) * 64 / upem_; - metrics->max_advance = ppem_ * hori->advance_Width_Max * 64 / upem_; - - return error; - } - - default: - return FT_THROW( Unknown_File_Format ); - } - } - - - typedef struct TT_SBitDecoderRec_ - { - TT_Face face; - FT_Stream stream; - FT_Bitmap* bitmap; - TT_SBit_Metrics metrics; - FT_Bool metrics_loaded; - FT_Bool bitmap_allocated; - FT_Byte bit_depth; - - FT_ULong ebdt_start; - FT_ULong ebdt_size; - - FT_ULong strike_index_array; - FT_ULong strike_index_count; - FT_Byte* eblc_base; - FT_Byte* eblc_limit; - - } TT_SBitDecoderRec, *TT_SBitDecoder; - - - static FT_Error - tt_sbit_decoder_init( TT_SBitDecoder decoder, - TT_Face face, - FT_ULong strike_index, - TT_SBit_MetricsRec* metrics ) - { - FT_Error error; - FT_Stream stream = face->root.stream; - FT_ULong ebdt_size; - - - error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size ); - if ( error ) - error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size ); - if ( error ) - error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size ); - if ( error ) - goto Exit; - - decoder->face = face; - decoder->stream = stream; - decoder->bitmap = &face->root.glyph->bitmap; - decoder->metrics = metrics; - - decoder->metrics_loaded = 0; - decoder->bitmap_allocated = 0; - - decoder->ebdt_start = FT_STREAM_POS(); - decoder->ebdt_size = ebdt_size; - - decoder->eblc_base = face->sbit_table; - decoder->eblc_limit = face->sbit_table + face->sbit_table_size; - - /* now find the strike corresponding to the index */ - { - FT_Byte* p; - - - if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - p = decoder->eblc_base + 8 + 48 * strike_index; - - decoder->strike_index_array = FT_NEXT_ULONG( p ); - p += 4; - decoder->strike_index_count = FT_NEXT_ULONG( p ); - p += 34; - decoder->bit_depth = *p; - - /* decoder->strike_index_array + */ - /* 8 * decoder->strike_index_count > face->sbit_table_size ? */ - if ( decoder->strike_index_array > face->sbit_table_size || - decoder->strike_index_count > - ( face->sbit_table_size - decoder->strike_index_array ) / 8 ) - error = FT_THROW( Invalid_File_Format ); - } - - Exit: - return error; - } - - - static void - tt_sbit_decoder_done( TT_SBitDecoder decoder ) - { - FT_UNUSED( decoder ); - } - - - static FT_Error - tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder ) - { - FT_Error error = FT_Err_Ok; - FT_UInt width, height; - FT_Bitmap* map = decoder->bitmap; - FT_ULong size; - - - if ( !decoder->metrics_loaded ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - width = decoder->metrics->width; - height = decoder->metrics->height; - - map->width = width; - map->rows = height; - - switch ( decoder->bit_depth ) - { - case 1: - map->pixel_mode = FT_PIXEL_MODE_MONO; - map->pitch = (int)( ( map->width + 7 ) >> 3 ); - map->num_grays = 2; - break; - - case 2: - map->pixel_mode = FT_PIXEL_MODE_GRAY2; - map->pitch = (int)( ( map->width + 3 ) >> 2 ); - map->num_grays = 4; - break; - - case 4: - map->pixel_mode = FT_PIXEL_MODE_GRAY4; - map->pitch = (int)( ( map->width + 1 ) >> 1 ); - map->num_grays = 16; - break; - - case 8: - map->pixel_mode = FT_PIXEL_MODE_GRAY; - map->pitch = (int)( map->width ); - map->num_grays = 256; - break; - - case 32: - map->pixel_mode = FT_PIXEL_MODE_BGRA; - map->pitch = (int)( map->width * 4 ); - map->num_grays = 256; - break; - - default: - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - size = map->rows * (FT_ULong)map->pitch; - - /* check that there is no empty image */ - if ( size == 0 ) - goto Exit; /* exit successfully! */ - - error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size ); - if ( error ) - goto Exit; - - decoder->bitmap_allocated = 1; - - Exit: - return error; - } - - - static FT_Error - tt_sbit_decoder_load_metrics( TT_SBitDecoder decoder, - FT_Byte* *pp, - FT_Byte* limit, - FT_Bool big ) - { - FT_Byte* p = *pp; - TT_SBit_Metrics metrics = decoder->metrics; - - - if ( p + 5 > limit ) - goto Fail; - - metrics->height = p[0]; - metrics->width = p[1]; - metrics->horiBearingX = (FT_Char)p[2]; - metrics->horiBearingY = (FT_Char)p[3]; - metrics->horiAdvance = p[4]; - - p += 5; - if ( big ) - { - if ( p + 3 > limit ) - goto Fail; - - metrics->vertBearingX = (FT_Char)p[0]; - metrics->vertBearingY = (FT_Char)p[1]; - metrics->vertAdvance = p[2]; - - p += 3; - } - else - { - /* avoid uninitialized data in case there is no vertical info -- */ - metrics->vertBearingX = 0; - metrics->vertBearingY = 0; - metrics->vertAdvance = 0; - } - - decoder->metrics_loaded = 1; - *pp = p; - return FT_Err_Ok; - - Fail: - FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table\n" )); - return FT_THROW( Invalid_Argument ); - } - - - /* forward declaration */ - static FT_Error - tt_sbit_decoder_load_image( TT_SBitDecoder decoder, - FT_UInt glyph_index, - FT_Int x_pos, - FT_Int y_pos ); - - typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder, - FT_Byte* p, - FT_Byte* plimit, - FT_Int x_pos, - FT_Int y_pos ); - - - static FT_Error - tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder, - FT_Byte* p, - FT_Byte* limit, - FT_Int x_pos, - FT_Int y_pos ) - { - FT_Error error = FT_Err_Ok; - FT_Byte* line; - FT_Int pitch, width, height, line_bits, h; - FT_UInt bit_height, bit_width; - FT_Bitmap* bitmap; - - - /* check that we can write the glyph into the bitmap */ - bitmap = decoder->bitmap; - bit_width = bitmap->width; - bit_height = bitmap->rows; - pitch = bitmap->pitch; - line = bitmap->buffer; - - width = decoder->metrics->width; - height = decoder->metrics->height; - - line_bits = width * decoder->bit_depth; - - if ( x_pos < 0 || (FT_UInt)( x_pos + width ) > bit_width || - y_pos < 0 || (FT_UInt)( y_pos + height ) > bit_height ) - { - FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:" - " invalid bitmap dimensions\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( p + ( ( line_bits + 7 ) >> 3 ) * height > limit ) - { - FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned: broken bitmap\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* now do the blit */ - line += y_pos * pitch + ( x_pos >> 3 ); - x_pos &= 7; - - if ( x_pos == 0 ) /* the easy one */ - { - for ( h = height; h > 0; h--, line += pitch ) - { - FT_Byte* pwrite = line; - FT_Int w; - - - for ( w = line_bits; w >= 8; w -= 8 ) - { - pwrite[0] = (FT_Byte)( pwrite[0] | *p++ ); - pwrite += 1; - } - - if ( w > 0 ) - pwrite[0] = (FT_Byte)( pwrite[0] | ( *p++ & ( 0xFF00U >> w ) ) ); - } - } - else /* x_pos > 0 */ - { - for ( h = height; h > 0; h--, line += pitch ) - { - FT_Byte* pwrite = line; - FT_Int w; - FT_UInt wval = 0; - - - for ( w = line_bits; w >= 8; w -= 8 ) - { - wval = (FT_UInt)( wval | *p++ ); - pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) ); - pwrite += 1; - wval <<= 8; - } - - if ( w > 0 ) - wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) ); - - /* all bits read and there are `x_pos + w' bits to be written */ - - pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) ); - - if ( x_pos + w > 8 ) - { - pwrite++; - wval <<= 8; - pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) ); - } - } - } - - Exit: - if ( !error ) - FT_TRACE3(( "tt_sbit_decoder_load_byte_aligned: loaded\n" )); - return error; - } - - - /* - * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap - * (with pointer `pwrite'). In the example below, the width is 3 pixel, - * and `x_pos' is 1 pixel. - * - * p p+1 - * | | | - * | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |... - * | | | - * +-------+ +-------+ +-------+ ... - * . . . - * . . . - * v . . - * +-------+ . . - * | | . - * | 7 6 5 4 3 2 1 0 | . - * | | . - * pwrite . . - * . . - * v . - * +-------+ . - * | | - * | 7 6 5 4 3 2 1 0 | - * | | - * pwrite+1 . - * . - * v - * +-------+ - * | | - * | 7 6 5 4 3 2 1 0 | - * | | - * pwrite+2 - * - */ - - static FT_Error - tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder, - FT_Byte* p, - FT_Byte* limit, - FT_Int x_pos, - FT_Int y_pos ) - { - FT_Error error = FT_Err_Ok; - FT_Byte* line; - FT_Int pitch, width, height, line_bits, h, nbits; - FT_UInt bit_height, bit_width; - FT_Bitmap* bitmap; - FT_UShort rval; - - - /* check that we can write the glyph into the bitmap */ - bitmap = decoder->bitmap; - bit_width = bitmap->width; - bit_height = bitmap->rows; - pitch = bitmap->pitch; - line = bitmap->buffer; - - width = decoder->metrics->width; - height = decoder->metrics->height; - - line_bits = width * decoder->bit_depth; - - if ( x_pos < 0 || (FT_UInt)( x_pos + width ) > bit_width || - y_pos < 0 || (FT_UInt)( y_pos + height ) > bit_height ) - { - FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:" - " invalid bitmap dimensions\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( p + ( ( line_bits * height + 7 ) >> 3 ) > limit ) - { - FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned: broken bitmap\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* now do the blit */ - - /* adjust `line' to point to the first byte of the bitmap */ - line += y_pos * pitch + ( x_pos >> 3 ); - x_pos &= 7; - - /* the higher byte of `rval' is used as a buffer */ - rval = 0; - nbits = 0; - - for ( h = height; h > 0; h--, line += pitch ) - { - FT_Byte* pwrite = line; - FT_Int w = line_bits; - - - /* handle initial byte (in target bitmap) specially if necessary */ - if ( x_pos ) - { - w = ( line_bits < 8 - x_pos ) ? line_bits : 8 - x_pos; - - if ( h == height ) - { - rval = *p++; - nbits = x_pos; - } - else if ( nbits < w ) - { - if ( p < limit ) - rval |= *p++; - nbits += 8 - w; - } - else - { - rval >>= 8; - nbits -= w; - } - - *pwrite++ |= ( ( rval >> nbits ) & 0xFF ) & - ( ~( 0xFF << w ) << ( 8 - w - x_pos ) ); - rval <<= 8; - - w = line_bits - w; - } - - /* handle medial bytes */ - for ( ; w >= 8; w -= 8 ) - { - rval |= *p++; - *pwrite++ |= ( rval >> nbits ) & 0xFF; - - rval <<= 8; - } - - /* handle final byte if necessary */ - if ( w > 0 ) - { - if ( nbits < w ) - { - if ( p < limit ) - rval |= *p++; - *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w ); - nbits += 8 - w; - - rval <<= 8; - } - else - { - *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w ); - nbits -= w; - } - } - } - - Exit: - if ( !error ) - FT_TRACE3(( "tt_sbit_decoder_load_bit_aligned: loaded\n" )); - return error; - } - - - static FT_Error - tt_sbit_decoder_load_compound( TT_SBitDecoder decoder, - FT_Byte* p, - FT_Byte* limit, - FT_Int x_pos, - FT_Int y_pos ) - { - FT_Error error = FT_Err_Ok; - FT_UInt num_components, nn; - - FT_Char horiBearingX = (FT_Char)decoder->metrics->horiBearingX; - FT_Char horiBearingY = (FT_Char)decoder->metrics->horiBearingY; - FT_Byte horiAdvance = (FT_Byte)decoder->metrics->horiAdvance; - FT_Char vertBearingX = (FT_Char)decoder->metrics->vertBearingX; - FT_Char vertBearingY = (FT_Char)decoder->metrics->vertBearingY; - FT_Byte vertAdvance = (FT_Byte)decoder->metrics->vertAdvance; - - - if ( p + 2 > limit ) - goto Fail; - - num_components = FT_NEXT_USHORT( p ); - if ( p + 4 * num_components > limit ) - { - FT_TRACE1(( "tt_sbit_decoder_load_compound: broken table\n" )); - goto Fail; - } - - FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n", - num_components )); - - for ( nn = 0; nn < num_components; nn++ ) - { - FT_UInt gindex = FT_NEXT_USHORT( p ); - FT_Byte dx = FT_NEXT_BYTE( p ); - FT_Byte dy = FT_NEXT_BYTE( p ); - - - /* NB: a recursive call */ - error = tt_sbit_decoder_load_image( decoder, gindex, - x_pos + dx, y_pos + dy ); - if ( error ) - break; - } - - FT_TRACE3(( "tt_sbit_decoder_load_compound: done\n" )); - - decoder->metrics->horiBearingX = horiBearingX; - decoder->metrics->horiBearingY = horiBearingY; - decoder->metrics->horiAdvance = horiAdvance; - decoder->metrics->vertBearingX = vertBearingX; - decoder->metrics->vertBearingY = vertBearingY; - decoder->metrics->vertAdvance = vertAdvance; - decoder->metrics->width = (FT_Byte)decoder->bitmap->width; - decoder->metrics->height = (FT_Byte)decoder->bitmap->rows; - - Exit: - return error; - - Fail: - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - -#ifdef FT_CONFIG_OPTION_USE_PNG - - static FT_Error - tt_sbit_decoder_load_png( TT_SBitDecoder decoder, - FT_Byte* p, - FT_Byte* limit, - FT_Int x_pos, - FT_Int y_pos ) - { - FT_Error error = FT_Err_Ok; - FT_ULong png_len; - - - if ( limit - p < 4 ) - { - FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - png_len = FT_NEXT_ULONG( p ); - if ( (FT_ULong)( limit - p ) < png_len ) - { - FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - error = Load_SBit_Png( decoder->face->root.glyph, - x_pos, - y_pos, - decoder->bit_depth, - decoder->metrics, - decoder->stream->memory, - p, - png_len, - FALSE ); - - Exit: - if ( !error ) - FT_TRACE3(( "tt_sbit_decoder_load_png: loaded\n" )); - return error; - } - -#endif /* FT_CONFIG_OPTION_USE_PNG */ - - - static FT_Error - tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder, - FT_UInt glyph_format, - FT_ULong glyph_start, - FT_ULong glyph_size, - FT_Int x_pos, - FT_Int y_pos ) - { - FT_Error error; - FT_Stream stream = decoder->stream; - FT_Byte* p; - FT_Byte* p_limit; - FT_Byte* data; - - - /* seek into the EBDT table now */ - if ( glyph_start + glyph_size > decoder->ebdt_size ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) || - FT_FRAME_EXTRACT( glyph_size, data ) ) - goto Exit; - - p = data; - p_limit = p + glyph_size; - - /* read the data, depending on the glyph format */ - switch ( glyph_format ) - { - case 1: - case 2: - case 8: - case 17: - error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 ); - break; - - case 6: - case 7: - case 9: - case 18: - error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ); - break; - - default: - error = FT_Err_Ok; - } - - if ( error ) - goto Fail; - - { - TT_SBitDecoder_LoadFunc loader; - - - switch ( glyph_format ) - { - case 1: - case 6: - loader = tt_sbit_decoder_load_byte_aligned; - break; - - case 2: - case 7: - { - /* Don't trust `glyph_format'. For example, Apple's main Korean */ - /* system font, `AppleMyungJo.ttf' (version 7.0d2e6), uses glyph */ - /* format 7, but the data is format 6. We check whether we have */ - /* an excessive number of bytes in the image: If it is equal to */ - /* the value for a byte-aligned glyph, use the other loading */ - /* routine. */ - /* */ - /* Note that for some (width,height) combinations, where the */ - /* width is not a multiple of 8, the sizes for bit- and */ - /* byte-aligned data are equal, for example (7,7) or (15,6). We */ - /* then prefer what `glyph_format' specifies. */ - - FT_UInt width = decoder->metrics->width; - FT_UInt height = decoder->metrics->height; - - FT_UInt bit_size = ( width * height + 7 ) >> 3; - FT_UInt byte_size = height * ( ( width + 7 ) >> 3 ); - - - if ( bit_size < byte_size && - byte_size == (FT_UInt)( p_limit - p ) ) - loader = tt_sbit_decoder_load_byte_aligned; - else - loader = tt_sbit_decoder_load_bit_aligned; - } - break; - - case 5: - loader = tt_sbit_decoder_load_bit_aligned; - break; - - case 8: - if ( p + 1 > p_limit ) - goto Fail; - - p += 1; /* skip padding */ - /* fall-through */ - - case 9: - loader = tt_sbit_decoder_load_compound; - break; - - case 17: /* small metrics, PNG image data */ - case 18: /* big metrics, PNG image data */ - case 19: /* metrics in EBLC, PNG image data */ -#ifdef FT_CONFIG_OPTION_USE_PNG - loader = tt_sbit_decoder_load_png; - break; -#else - error = FT_THROW( Unimplemented_Feature ); - goto Fail; -#endif /* FT_CONFIG_OPTION_USE_PNG */ - - default: - error = FT_THROW( Invalid_Table ); - goto Fail; - } - - if ( !decoder->bitmap_allocated ) - { - error = tt_sbit_decoder_alloc_bitmap( decoder ); - if ( error ) - goto Fail; - } - - error = loader( decoder, p, p_limit, x_pos, y_pos ); - } - - Fail: - FT_FRAME_RELEASE( data ); - - Exit: - return error; - } - - - static FT_Error - tt_sbit_decoder_load_image( TT_SBitDecoder decoder, - FT_UInt glyph_index, - FT_Int x_pos, - FT_Int y_pos ) - { - /* - * First, we find the correct strike range that applies to this - * glyph index. - */ - - FT_Byte* p = decoder->eblc_base + decoder->strike_index_array; - FT_Byte* p_limit = decoder->eblc_limit; - FT_ULong num_ranges = decoder->strike_index_count; - FT_UInt start, end, index_format, image_format; - FT_ULong image_start = 0, image_end = 0, image_offset; - - - for ( ; num_ranges > 0; num_ranges-- ) - { - start = FT_NEXT_USHORT( p ); - end = FT_NEXT_USHORT( p ); - - if ( glyph_index >= start && glyph_index <= end ) - goto FoundRange; - - p += 4; /* ignore index offset */ - } - goto NoBitmap; - - FoundRange: - image_offset = FT_NEXT_ULONG( p ); - - /* overflow check */ - p = decoder->eblc_base + decoder->strike_index_array; - if ( image_offset > (FT_ULong)( p_limit - p ) ) - goto Failure; - - p += image_offset; - if ( p + 8 > p_limit ) - goto NoBitmap; - - /* now find the glyph's location and extend within the ebdt table */ - index_format = FT_NEXT_USHORT( p ); - image_format = FT_NEXT_USHORT( p ); - image_offset = FT_NEXT_ULONG ( p ); - - switch ( index_format ) - { - case 1: /* 4-byte offsets relative to `image_offset' */ - p += 4 * ( glyph_index - start ); - if ( p + 8 > p_limit ) - goto NoBitmap; - - image_start = FT_NEXT_ULONG( p ); - image_end = FT_NEXT_ULONG( p ); - - if ( image_start == image_end ) /* missing glyph */ - goto NoBitmap; - break; - - case 2: /* big metrics, constant image size */ - { - FT_ULong image_size; - - - if ( p + 12 > p_limit ) - goto NoBitmap; - - image_size = FT_NEXT_ULONG( p ); - - if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) - goto NoBitmap; - - image_start = image_size * ( glyph_index - start ); - image_end = image_start + image_size; - } - break; - - case 3: /* 2-byte offsets relative to 'image_offset' */ - p += 2 * ( glyph_index - start ); - if ( p + 4 > p_limit ) - goto NoBitmap; - - image_start = FT_NEXT_USHORT( p ); - image_end = FT_NEXT_USHORT( p ); - - if ( image_start == image_end ) /* missing glyph */ - goto NoBitmap; - break; - - case 4: /* sparse glyph array with (glyph,offset) pairs */ - { - FT_ULong mm, num_glyphs; - - - if ( p + 4 > p_limit ) - goto NoBitmap; - - num_glyphs = FT_NEXT_ULONG( p ); - - /* overflow check for p + ( num_glyphs + 1 ) * 4 */ - if ( p + 4 > p_limit || - num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) ) - goto NoBitmap; - - for ( mm = 0; mm < num_glyphs; mm++ ) - { - FT_UInt gindex = FT_NEXT_USHORT( p ); - - - if ( gindex == glyph_index ) - { - image_start = FT_NEXT_USHORT( p ); - p += 2; - image_end = FT_PEEK_USHORT( p ); - break; - } - p += 2; - } - - if ( mm >= num_glyphs ) - goto NoBitmap; - } - break; - - case 5: /* constant metrics with sparse glyph codes */ - case 19: - { - FT_ULong image_size, mm, num_glyphs; - - - if ( p + 16 > p_limit ) - goto NoBitmap; - - image_size = FT_NEXT_ULONG( p ); - - if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) - goto NoBitmap; - - num_glyphs = FT_NEXT_ULONG( p ); - - /* overflow check for p + 2 * num_glyphs */ - if ( num_glyphs > (FT_ULong)( ( p_limit - p ) >> 1 ) ) - goto NoBitmap; - - for ( mm = 0; mm < num_glyphs; mm++ ) - { - FT_UInt gindex = FT_NEXT_USHORT( p ); - - - if ( gindex == glyph_index ) - break; - } - - if ( mm >= num_glyphs ) - goto NoBitmap; - - image_start = image_size * mm; - image_end = image_start + image_size; - } - break; - - default: - goto NoBitmap; - } - - if ( image_start > image_end ) - goto NoBitmap; - - image_end -= image_start; - image_start = image_offset + image_start; - - FT_TRACE3(( "tt_sbit_decoder_load_image:" - " found sbit (format %d) for glyph index %d\n", - image_format, glyph_index )); - - return tt_sbit_decoder_load_bitmap( decoder, - image_format, - image_start, - image_end, - x_pos, - y_pos ); - - Failure: - return FT_THROW( Invalid_Table ); - - NoBitmap: - FT_TRACE4(( "tt_sbit_decoder_load_image:" - " no sbit found for glyph index %d\n", glyph_index )); - - return FT_THROW( Invalid_Argument ); - } - - - static FT_Error - tt_face_load_sbix_image( TT_Face face, - FT_ULong strike_index, - FT_UInt glyph_index, - FT_Stream stream, - FT_Bitmap *map, - TT_SBit_MetricsRec *metrics ) - { - FT_UInt sbix_pos, strike_offset, glyph_start, glyph_end; - FT_ULong table_size; - FT_Int originOffsetX, originOffsetY; - FT_Tag graphicType; - FT_Int recurse_depth = 0; - - FT_Error error; - FT_Byte* p; - - FT_UNUSED( map ); - - - metrics->width = 0; - metrics->height = 0; - - p = face->sbit_table + 8 + 4 * strike_index; - strike_offset = FT_NEXT_ULONG( p ); - - error = face->goto_table( face, TTAG_sbix, stream, &table_size ); - if ( error ) - return error; - sbix_pos = FT_STREAM_POS(); - - retry: - if ( glyph_index > (FT_UInt)face->root.num_glyphs ) - return FT_THROW( Invalid_Argument ); - - if ( strike_offset >= table_size || - table_size - strike_offset < 4 + glyph_index * 4 + 8 ) - return FT_THROW( Invalid_File_Format ); - - if ( FT_STREAM_SEEK( sbix_pos + strike_offset + 4 + glyph_index * 4 ) || - FT_FRAME_ENTER( 8 ) ) - return error; - - glyph_start = FT_GET_ULONG(); - glyph_end = FT_GET_ULONG(); - - FT_FRAME_EXIT(); - - if ( glyph_start == glyph_end ) - return FT_THROW( Invalid_Argument ); - if ( glyph_start > glyph_end || - glyph_end - glyph_start < 8 || - table_size - strike_offset < glyph_end ) - return FT_THROW( Invalid_File_Format ); - - if ( FT_STREAM_SEEK( sbix_pos + strike_offset + glyph_start ) || - FT_FRAME_ENTER( glyph_end - glyph_start ) ) - return error; - - originOffsetX = FT_GET_SHORT(); - originOffsetY = FT_GET_SHORT(); - - graphicType = FT_GET_TAG4(); - - switch ( graphicType ) - { - case FT_MAKE_TAG( 'd', 'u', 'p', 'e' ): - if ( recurse_depth < 4 ) - { - glyph_index = FT_GET_USHORT(); - FT_FRAME_EXIT(); - recurse_depth++; - goto retry; - } - error = FT_THROW( Invalid_File_Format ); - break; - - case FT_MAKE_TAG( 'p', 'n', 'g', ' ' ): -#ifdef FT_CONFIG_OPTION_USE_PNG - error = Load_SBit_Png( face->root.glyph, - 0, - 0, - 32, - metrics, - stream->memory, - stream->cursor, - glyph_end - glyph_start - 8, - TRUE ); -#else - error = FT_THROW( Unimplemented_Feature ); -#endif - break; - - case FT_MAKE_TAG( 'j', 'p', 'g', ' ' ): - case FT_MAKE_TAG( 't', 'i', 'f', 'f' ): - case FT_MAKE_TAG( 'r', 'g', 'b', 'l' ): /* used on iOS 7.1 */ - error = FT_THROW( Unknown_File_Format ); - break; - - default: - error = FT_THROW( Unimplemented_Feature ); - break; - } - - FT_FRAME_EXIT(); - - if ( !error ) - { - FT_Short abearing; - FT_UShort aadvance; - - - tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance ); - - metrics->horiBearingX = (FT_Short)originOffsetX; - metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height ); - metrics->horiAdvance = (FT_UShort)( aadvance * - face->root.size->metrics.x_ppem / - face->header.Units_Per_EM ); - } - - return error; - } - - FT_LOCAL( FT_Error ) - tt_face_load_sbit_image( TT_Face face, - FT_ULong strike_index, - FT_UInt glyph_index, - FT_UInt load_flags, - FT_Stream stream, - FT_Bitmap *map, - TT_SBit_MetricsRec *metrics ) - { - FT_Error error = FT_Err_Ok; - - - switch ( (FT_UInt)face->sbit_table_type ) - { - case TT_SBIT_TABLE_TYPE_EBLC: - case TT_SBIT_TABLE_TYPE_CBLC: - { - TT_SBitDecoderRec decoder[1]; - - - error = tt_sbit_decoder_init( decoder, face, strike_index, metrics ); - if ( !error ) - { - error = tt_sbit_decoder_load_image( decoder, - glyph_index, - 0, - 0 ); - tt_sbit_decoder_done( decoder ); - } - } - break; - - case TT_SBIT_TABLE_TYPE_SBIX: - error = tt_face_load_sbix_image( face, - strike_index, - glyph_index, - stream, - map, - metrics ); - break; - - default: - error = FT_THROW( Unknown_File_Format ); - break; - } - - /* Flatten color bitmaps if color was not requested. */ - if ( !error && - !( load_flags & FT_LOAD_COLOR ) && - map->pixel_mode == FT_PIXEL_MODE_BGRA ) - { - FT_Bitmap new_map; - FT_Library library = face->root.glyph->library; - - - FT_Bitmap_Init( &new_map ); - - /* Convert to 8bit grayscale. */ - error = FT_Bitmap_Convert( library, map, &new_map, 1 ); - if ( error ) - FT_Bitmap_Done( library, &new_map ); - else - { - map->pixel_mode = new_map.pixel_mode; - map->pitch = new_map.pitch; - map->num_grays = new_map.num_grays; - - ft_glyphslot_set_bitmap( face->root.glyph, new_map.buffer ); - face->root.glyph->internal->flags |= FT_GLYPH_OWN_BITMAP; - } - } - - return error; - } - - -/* EOF */ diff --git a/third_party/freetype/src/sfnt/ttsbit.h b/third_party/freetype/src/sfnt/ttsbit.h deleted file mode 100644 index d4e13aefb8d71a94374cafc9ce0daa0a65bf41b4..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/sfnt/ttsbit.h +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttsbit.h */ -/* */ -/* TrueType and OpenType embedded bitmap support (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTSBIT_H__ -#define __TTSBIT_H__ - - -#include <ft2build.h> -#include "ttload.h" - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - tt_face_load_sbit( TT_Face face, - FT_Stream stream ); - - FT_LOCAL( void ) - tt_face_free_sbit( TT_Face face ); - - - FT_LOCAL( FT_Error ) - tt_face_set_sbit_strike( TT_Face face, - FT_Size_Request req, - FT_ULong* astrike_index ); - - FT_LOCAL( FT_Error ) - tt_face_load_strike_metrics( TT_Face face, - FT_ULong strike_index, - FT_Size_Metrics* metrics ); - - FT_LOCAL( FT_Error ) - tt_face_load_sbit_image( TT_Face face, - FT_ULong strike_index, - FT_UInt glyph_index, - FT_UInt load_flags, - FT_Stream stream, - FT_Bitmap *map, - TT_SBit_MetricsRec *metrics ); - - -FT_END_HEADER - -#endif /* __TTSBIT_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/smooth/Jamfile b/third_party/freetype/src/smooth/Jamfile deleted file mode 100644 index b1887c2c6efdaf7dd66ee191e3bbaca362ce14a0..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/Jamfile +++ /dev/null @@ -1,32 +0,0 @@ -# FreeType 2 src/smooth Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) smooth ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ftgrays - ftsmooth - ftspic - ; - } - else - { - _sources = smooth ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/smooth Jamfile diff --git a/third_party/freetype/src/smooth/ftgrays.c b/third_party/freetype/src/smooth/ftgrays.c deleted file mode 100644 index ba2944559c3335bfb05ffd4cdcb2054cd45866c9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftgrays.c +++ /dev/null @@ -1,2116 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgrays.c */ -/* */ -/* A new `perfect' anti-aliasing renderer (body). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - /*************************************************************************/ - /* */ - /* This file can be compiled without the rest of the FreeType engine, by */ - /* defining the _STANDALONE_ macro when compiling it. You also need to */ - /* put the files `ftgrays.h' and `ftimage.h' into the current */ - /* compilation directory. Typically, you could do something like */ - /* */ - /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */ - /* */ - /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */ - /* same directory */ - /* */ - /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */ - /* */ - /* cc -c -D_STANDALONE_ ftgrays.c */ - /* */ - /* The renderer can be initialized with a call to */ - /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */ - /* with a call to `ft_gray_raster.raster_render'. */ - /* */ - /* See the comments and documentation in the file `ftimage.h' for more */ - /* details on how the raster works. */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* This is a new anti-aliasing scan-converter for FreeType 2. The */ - /* algorithm used here is _very_ different from the one in the standard */ - /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */ - /* coverage of the outline on each pixel cell. */ - /* */ - /* It is based on ideas that I initially found in Raph Levien's */ - /* excellent LibArt graphics library (see http://www.levien.com/libart */ - /* for more information, though the web pages do not tell anything */ - /* about the renderer; you'll have to dive into the source code to */ - /* understand how it works). */ - /* */ - /* Note, however, that this is a _very_ different implementation */ - /* compared to Raph's. Coverage information is stored in a very */ - /* different way, and I don't use sorted vector paths. Also, it doesn't */ - /* use floating point values. */ - /* */ - /* This renderer has the following advantages: */ - /* */ - /* - It doesn't need an intermediate bitmap. Instead, one can supply a */ - /* callback function that will be called by the renderer to draw gray */ - /* spans on any target surface. You can thus do direct composition on */ - /* any kind of bitmap, provided that you give the renderer the right */ - /* callback. */ - /* */ - /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */ - /* each pixel cell. */ - /* */ - /* - It performs a single pass on the outline (the `standard' FT2 */ - /* renderer makes two passes). */ - /* */ - /* - It can easily be modified to render to _any_ number of gray levels */ - /* cheaply. */ - /* */ - /* - For small (< 20) pixel sizes, it is faster than the standard */ - /* renderer. */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_smooth - - -#ifdef _STANDALONE_ - - - /* The size in bytes of the render pool used by the scan-line converter */ - /* to do all of its work. */ -#define FT_RENDER_POOL_SIZE 16384L - - - /* Auxiliary macros for token concatenation. */ -#define FT_ERR_XCAT( x, y ) x ## y -#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) - -#define FT_BEGIN_STMNT do { -#define FT_END_STMNT } while ( 0 ) - -#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) ) -#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) ) - - - /* - * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min' - * algorithm. We use alpha = 1, beta = 3/8, giving us results with a - * largest error less than 7% compared to the exact value. - */ -#define FT_HYPOT( x, y ) \ - ( x = FT_ABS( x ), \ - y = FT_ABS( y ), \ - x > y ? x + ( 3 * y >> 3 ) \ - : y + ( 3 * x >> 3 ) ) - - - /* define this to dump debugging information */ -/* #define FT_DEBUG_LEVEL_TRACE */ - - -#ifdef FT_DEBUG_LEVEL_TRACE -#include <stdio.h> -#include <stdarg.h> -#endif - -#include <stddef.h> -#include <string.h> -#include <setjmp.h> -#include <limits.h> -#define FT_UINT_MAX UINT_MAX -#define FT_INT_MAX INT_MAX - -#define ft_memset memset - -#define ft_setjmp setjmp -#define ft_longjmp longjmp -#define ft_jmp_buf jmp_buf - -typedef ptrdiff_t FT_PtrDist; - - -#define ErrRaster_Invalid_Mode -2 -#define ErrRaster_Invalid_Outline -1 -#define ErrRaster_Invalid_Argument -3 -#define ErrRaster_Memory_Overflow -4 - -#define FT_BEGIN_HEADER -#define FT_END_HEADER - -#include "ftimage.h" -#include "ftgrays.h" - - - /* This macro is used to indicate that a function parameter is unused. */ - /* Its purpose is simply to reduce compiler warnings. Note also that */ - /* simply defining it as `(void)x' doesn't avoid warnings with certain */ - /* ANSI compilers (e.g. LCC). */ -#define FT_UNUSED( x ) (x) = (x) - - - /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */ - -#ifdef FT_DEBUG_LEVEL_TRACE - - void - FT_Message( const char* fmt, - ... ) - { - va_list ap; - - - va_start( ap, fmt ); - vfprintf( stderr, fmt, ap ); - va_end( ap ); - } - - - /* empty function useful for setting a breakpoint to catch errors */ - int - FT_Throw( int error, - int line, - const char* file ) - { - FT_UNUSED( error ); - FT_UNUSED( line ); - FT_UNUSED( file ); - - return 0; - } - - - /* we don't handle tracing levels in stand-alone mode; */ -#ifndef FT_TRACE5 -#define FT_TRACE5( varformat ) FT_Message varformat -#endif -#ifndef FT_TRACE7 -#define FT_TRACE7( varformat ) FT_Message varformat -#endif -#ifndef FT_ERROR -#define FT_ERROR( varformat ) FT_Message varformat -#endif - -#define FT_THROW( e ) \ - ( FT_Throw( FT_ERR_CAT( ErrRaster, e ), \ - __LINE__, \ - __FILE__ ) | \ - FT_ERR_CAT( ErrRaster, e ) ) - -#else /* !FT_DEBUG_LEVEL_TRACE */ - -#define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */ -#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */ -#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */ -#define FT_THROW( e ) FT_ERR_CAT( ErrRaster_, e ) - - -#endif /* !FT_DEBUG_LEVEL_TRACE */ - - -#define FT_DEFINE_OUTLINE_FUNCS( class_, \ - move_to_, line_to_, \ - conic_to_, cubic_to_, \ - shift_, delta_ ) \ - static const FT_Outline_Funcs class_ = \ - { \ - move_to_, \ - line_to_, \ - conic_to_, \ - cubic_to_, \ - shift_, \ - delta_ \ - }; - -#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \ - raster_new_, raster_reset_, \ - raster_set_mode_, raster_render_, \ - raster_done_ ) \ - const FT_Raster_Funcs class_ = \ - { \ - glyph_format_, \ - raster_new_, \ - raster_reset_, \ - raster_set_mode_, \ - raster_render_, \ - raster_done_ \ - }; - - -#else /* !_STANDALONE_ */ - - -#include <ft2build.h> -#include "ftgrays.h" -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_DEBUG_H -#include FT_OUTLINE_H - -#include "ftsmerrs.h" - -#include "ftspic.h" - -#define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph -#define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory -#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory - - -#endif /* !_STANDALONE_ */ - - -#ifndef FT_MEM_SET -#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c ) -#endif - -#ifndef FT_MEM_ZERO -#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count ) -#endif - - /* as usual, for the speed hungry :-) */ - -#undef RAS_ARG -#undef RAS_ARG_ -#undef RAS_VAR -#undef RAS_VAR_ - -#ifndef FT_STATIC_RASTER - -#define RAS_ARG gray_PWorker worker -#define RAS_ARG_ gray_PWorker worker, - -#define RAS_VAR worker -#define RAS_VAR_ worker, - -#else /* FT_STATIC_RASTER */ - -#define RAS_ARG /* empty */ -#define RAS_ARG_ /* empty */ -#define RAS_VAR /* empty */ -#define RAS_VAR_ /* empty */ - -#endif /* FT_STATIC_RASTER */ - - - /* must be at least 6 bits! */ -#define PIXEL_BITS 8 - -#undef FLOOR -#undef CEILING -#undef TRUNC -#undef SCALED - -#define ONE_PIXEL ( 1L << PIXEL_BITS ) -#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) ) -#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS ) -#define FLOOR( x ) ( (x) & -ONE_PIXEL ) -#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) -#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL ) - -#if PIXEL_BITS >= 6 -#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) ) -#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) ) -#else -#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) ) -#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) -#endif - - - /* Compute `dividend / divisor' and return both its quotient and */ - /* remainder, cast to a specific type. This macro also ensures that */ - /* the remainder is always positive. */ -#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ - FT_BEGIN_STMNT \ - (quotient) = (type)( (dividend) / (divisor) ); \ - (remainder) = (type)( (dividend) % (divisor) ); \ - if ( (remainder) < 0 ) \ - { \ - (quotient)--; \ - (remainder) += (type)(divisor); \ - } \ - FT_END_STMNT - -#ifdef __arm__ - /* Work around a bug specific to GCC which make the compiler fail to */ - /* optimize a division and modulo operation on the same parameters */ - /* into a single call to `__aeabi_idivmod'. See */ - /* */ - /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */ -#undef FT_DIV_MOD -#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ - FT_BEGIN_STMNT \ - (quotient) = (type)( (dividend) / (divisor) ); \ - (remainder) = (type)( (dividend) - (quotient) * (divisor) ); \ - if ( (remainder) < 0 ) \ - { \ - (quotient)--; \ - (remainder) += (type)(divisor); \ - } \ - FT_END_STMNT -#endif /* __arm__ */ - - - /*************************************************************************/ - /* */ - /* TYPE DEFINITIONS */ - /* */ - - /* don't change the following types to FT_Int or FT_Pos, since we might */ - /* need to define them to "float" or "double" when experimenting with */ - /* new algorithms */ - - typedef long TCoord; /* integer scanline/pixel coordinate */ - typedef long TPos; /* sub-pixel coordinate */ - - /* determine the type used to store cell areas. This normally takes at */ - /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */ - /* `long' instead of `int', otherwise bad things happen */ - -#if PIXEL_BITS <= 7 - - typedef int TArea; - -#else /* PIXEL_BITS >= 8 */ - - /* approximately determine the size of integers using an ANSI-C header */ -#if FT_UINT_MAX == 0xFFFFU - typedef long TArea; -#else - typedef int TArea; -#endif - -#endif /* PIXEL_BITS >= 8 */ - - - /* maximum number of gray spans in a call to the span callback */ -#define FT_MAX_GRAY_SPANS 32 - - - typedef struct TCell_* PCell; - - typedef struct TCell_ - { - TPos x; /* same with gray_TWorker.ex */ - TCoord cover; /* same with gray_TWorker.cover */ - TArea area; - PCell next; - - } TCell; - - -#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ - /* We disable the warning `structure was padded due to */ - /* __declspec(align())' in order to compile cleanly with */ - /* the maximum level of warnings. */ -#pragma warning( push ) -#pragma warning( disable : 4324 ) -#endif /* _MSC_VER */ - - typedef struct gray_TWorker_ - { - ft_jmp_buf jump_buffer; - - TCoord ex, ey; - TPos min_ex, max_ex; - TPos min_ey, max_ey; - TPos count_ex, count_ey; - - TArea area; - TCoord cover; - int invalid; - - PCell cells; - FT_PtrDist max_cells; - FT_PtrDist num_cells; - - TPos x, y; - - FT_Vector bez_stack[32 * 3 + 1]; - int lev_stack[32]; - - FT_Outline outline; - FT_Bitmap target; - FT_BBox clip_box; - - FT_Span gray_spans[FT_MAX_GRAY_SPANS]; - int num_gray_spans; - - FT_Raster_Span_Func render_span; - void* render_span_data; - int span_y; - - int band_size; - int band_shoot; - - void* buffer; - long buffer_size; - - PCell* ycells; - TPos ycount; - - } gray_TWorker, *gray_PWorker; - -#if defined( _MSC_VER ) -#pragma warning( pop ) -#endif - - -#ifndef FT_STATIC_RASTER -#define ras (*worker) -#else - static gray_TWorker ras; -#endif - - - typedef struct gray_TRaster_ - { - void* memory; - - } gray_TRaster, *gray_PRaster; - - - - /*************************************************************************/ - /* */ - /* Initialize the cells table. */ - /* */ - static void - gray_init_cells( RAS_ARG_ void* buffer, - long byte_size ) - { - ras.buffer = buffer; - ras.buffer_size = byte_size; - - ras.ycells = (PCell*) buffer; - ras.cells = NULL; - ras.max_cells = 0; - ras.num_cells = 0; - ras.area = 0; - ras.cover = 0; - ras.invalid = 1; - } - - - /*************************************************************************/ - /* */ - /* Compute the outline bounding box. */ - /* */ - static void - gray_compute_cbox( RAS_ARG ) - { - FT_Outline* outline = &ras.outline; - FT_Vector* vec = outline->points; - FT_Vector* limit = vec + outline->n_points; - - - if ( outline->n_points <= 0 ) - { - ras.min_ex = ras.max_ex = 0; - ras.min_ey = ras.max_ey = 0; - return; - } - - ras.min_ex = ras.max_ex = vec->x; - ras.min_ey = ras.max_ey = vec->y; - - vec++; - - for ( ; vec < limit; vec++ ) - { - TPos x = vec->x; - TPos y = vec->y; - - - if ( x < ras.min_ex ) ras.min_ex = x; - if ( x > ras.max_ex ) ras.max_ex = x; - if ( y < ras.min_ey ) ras.min_ey = y; - if ( y > ras.max_ey ) ras.max_ey = y; - } - - /* truncate the bounding box to integer pixels */ - ras.min_ex = ras.min_ex >> 6; - ras.min_ey = ras.min_ey >> 6; - ras.max_ex = ( ras.max_ex + 63 ) >> 6; - ras.max_ey = ( ras.max_ey + 63 ) >> 6; - } - - - /*************************************************************************/ - /* */ - /* Record the current cell in the table. */ - /* */ - static PCell - gray_find_cell( RAS_ARG ) - { - PCell *pcell, cell; - TPos x = ras.ex; - - - if ( x > ras.count_ex ) - x = ras.count_ex; - - pcell = &ras.ycells[ras.ey]; - for (;;) - { - cell = *pcell; - if ( cell == NULL || cell->x > x ) - break; - - if ( cell->x == x ) - goto Exit; - - pcell = &cell->next; - } - - if ( ras.num_cells >= ras.max_cells ) - ft_longjmp( ras.jump_buffer, 1 ); - - cell = ras.cells + ras.num_cells++; - cell->x = x; - cell->area = 0; - cell->cover = 0; - - cell->next = *pcell; - *pcell = cell; - - Exit: - return cell; - } - - - static void - gray_record_cell( RAS_ARG ) - { - if ( ras.area | ras.cover ) - { - PCell cell = gray_find_cell( RAS_VAR ); - - - cell->area += ras.area; - cell->cover += ras.cover; - } - } - - - /*************************************************************************/ - /* */ - /* Set the current cell to a new position. */ - /* */ - static void - gray_set_cell( RAS_ARG_ TCoord ex, - TCoord ey ) - { - /* Move the cell pointer to a new position. We set the `invalid' */ - /* flag to indicate that the cell isn't part of those we're interested */ - /* in during the render phase. This means that: */ - /* */ - /* . the new vertical position must be within min_ey..max_ey-1. */ - /* . the new horizontal position must be strictly less than max_ex */ - /* */ - /* Note that if a cell is to the left of the clipping region, it is */ - /* actually set to the (min_ex-1) horizontal position. */ - - /* All cells that are on the left of the clipping region go to the */ - /* min_ex - 1 horizontal position. */ - ey -= ras.min_ey; - - if ( ex > ras.max_ex ) - ex = ras.max_ex; - - ex -= ras.min_ex; - if ( ex < 0 ) - ex = -1; - - /* are we moving to a different cell ? */ - if ( ex != ras.ex || ey != ras.ey ) - { - /* record the current one if it is valid */ - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - - ras.area = 0; - ras.cover = 0; - ras.ex = ex; - ras.ey = ey; - } - - ras.invalid = ( (unsigned int)ey >= (unsigned int)ras.count_ey || - ex >= ras.count_ex ); - } - - - /*************************************************************************/ - /* */ - /* Start a new contour at a given cell. */ - /* */ - static void - gray_start_cell( RAS_ARG_ TCoord ex, - TCoord ey ) - { - if ( ex > ras.max_ex ) - ex = (TCoord)( ras.max_ex ); - - if ( ex < ras.min_ex ) - ex = (TCoord)( ras.min_ex - 1 ); - - ras.area = 0; - ras.cover = 0; - ras.ex = ex - ras.min_ex; - ras.ey = ey - ras.min_ey; - ras.invalid = 0; - - gray_set_cell( RAS_VAR_ ex, ey ); - } - - - /*************************************************************************/ - /* */ - /* Render a scanline as one or more cells. */ - /* */ - static void - gray_render_scanline( RAS_ARG_ TCoord ey, - TPos x1, - TCoord y1, - TPos x2, - TCoord y2 ) - { - TCoord ex1, ex2, fx1, fx2, delta, mod; - long p, first, dx; - int incr; - - - dx = x2 - x1; - - ex1 = TRUNC( x1 ); - ex2 = TRUNC( x2 ); - fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); - fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); - - /* trivial case. Happens often */ - if ( y1 == y2 ) - { - gray_set_cell( RAS_VAR_ ex2, ey ); - return; - } - - /* everything is located in a single cell. That is easy! */ - /* */ - if ( ex1 == ex2 ) - { - delta = y2 - y1; - ras.area += (TArea)(( fx1 + fx2 ) * delta); - ras.cover += delta; - return; - } - - /* ok, we'll have to render a run of adjacent cells on the same */ - /* scanline... */ - /* */ - p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 ); - first = ONE_PIXEL; - incr = 1; - - if ( dx < 0 ) - { - p = fx1 * ( y2 - y1 ); - first = 0; - incr = -1; - dx = -dx; - } - - FT_DIV_MOD( TCoord, p, dx, delta, mod ); - - ras.area += (TArea)(( fx1 + first ) * delta); - ras.cover += delta; - - ex1 += incr; - gray_set_cell( RAS_VAR_ ex1, ey ); - y1 += delta; - - if ( ex1 != ex2 ) - { - TCoord lift, rem; - - - p = ONE_PIXEL * ( y2 - y1 + delta ); - FT_DIV_MOD( TCoord, p, dx, lift, rem ); - - mod -= (int)dx; - - do - { - delta = lift; - mod += rem; - if ( mod >= 0 ) - { - mod -= (TCoord)dx; - delta++; - } - - ras.area += (TArea)(ONE_PIXEL * delta); - ras.cover += delta; - y1 += delta; - ex1 += incr; - gray_set_cell( RAS_VAR_ ex1, ey ); - } while ( ex1 != ex2 ); - } - - delta = y2 - y1; - ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta); - ras.cover += delta; - } - - - /*************************************************************************/ - /* */ - /* Render a given line as a series of scanlines. */ - /* */ - static void - gray_render_line( RAS_ARG_ TPos to_x, - TPos to_y ) - { - TCoord ey1, ey2, fy1, fy2, mod; - TPos dx, dy, x, x2; - long p, first; - int delta, rem, lift, incr; - - - ey1 = TRUNC( ras.y ); - ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ - fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) ); - fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) ); - - dx = to_x - ras.x; - dy = to_y - ras.y; - - /* perform vertical clipping */ - if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) || - ( ey1 < ras.min_ey && ey2 < ras.min_ey ) ) - goto End; - - /* everything is on a single scanline */ - if ( ey1 == ey2 ) - { - gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ); - goto End; - } - - /* vertical line - avoid calling gray_render_scanline */ - incr = 1; - - if ( dx == 0 ) - { - TCoord ex = TRUNC( ras.x ); - TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 ); - TArea area; - - - first = ONE_PIXEL; - if ( dy < 0 ) - { - first = 0; - incr = -1; - } - - delta = (int)( first - fy1 ); - ras.area += (TArea)two_fx * delta; - ras.cover += delta; - ey1 += incr; - - gray_set_cell( RAS_VAR_ ex, ey1 ); - - delta = (int)( first + first - ONE_PIXEL ); - area = (TArea)two_fx * delta; - while ( ey1 != ey2 ) - { - ras.area += area; - ras.cover += delta; - ey1 += incr; - - gray_set_cell( RAS_VAR_ ex, ey1 ); - } - - delta = (int)( fy2 - ONE_PIXEL + first ); - ras.area += (TArea)two_fx * delta; - ras.cover += delta; - - goto End; - } - - /* ok, we have to render several scanlines */ - p = ( ONE_PIXEL - fy1 ) * dx; - first = ONE_PIXEL; - incr = 1; - - if ( dy < 0 ) - { - p = fy1 * dx; - first = 0; - incr = -1; - dy = -dy; - } - - FT_DIV_MOD( int, p, dy, delta, mod ); - - x = ras.x + delta; - gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first ); - - ey1 += incr; - gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 ); - - if ( ey1 != ey2 ) - { - p = ONE_PIXEL * dx; - FT_DIV_MOD( int, p, dy, lift, rem ); - mod -= (int)dy; - - do - { - delta = lift; - mod += rem; - if ( mod >= 0 ) - { - mod -= (int)dy; - delta++; - } - - x2 = x + delta; - gray_render_scanline( RAS_VAR_ ey1, x, - (TCoord)( ONE_PIXEL - first ), x2, - (TCoord)first ); - x = x2; - - ey1 += incr; - gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 ); - } while ( ey1 != ey2 ); - } - - gray_render_scanline( RAS_VAR_ ey1, x, - (TCoord)( ONE_PIXEL - first ), to_x, - fy2 ); - - End: - ras.x = to_x; - ras.y = to_y; - } - - - static void - gray_split_conic( FT_Vector* base ) - { - TPos a, b; - - - base[4].x = base[2].x; - b = base[1].x; - a = base[3].x = ( base[2].x + b ) / 2; - b = base[1].x = ( base[0].x + b ) / 2; - base[2].x = ( a + b ) / 2; - - base[4].y = base[2].y; - b = base[1].y; - a = base[3].y = ( base[2].y + b ) / 2; - b = base[1].y = ( base[0].y + b ) / 2; - base[2].y = ( a + b ) / 2; - } - - - static void - gray_render_conic( RAS_ARG_ const FT_Vector* control, - const FT_Vector* to ) - { - TPos dx, dy; - TPos min, max, y; - int top, level; - int* levels; - FT_Vector* arc; - - - levels = ras.lev_stack; - - arc = ras.bez_stack; - arc[0].x = UPSCALE( to->x ); - arc[0].y = UPSCALE( to->y ); - arc[1].x = UPSCALE( control->x ); - arc[1].y = UPSCALE( control->y ); - arc[2].x = ras.x; - arc[2].y = ras.y; - top = 0; - - dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x ); - dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y ); - if ( dx < dy ) - dx = dy; - - if ( dx < ONE_PIXEL / 4 ) - goto Draw; - - /* short-cut the arc that crosses the current band */ - min = max = arc[0].y; - - y = arc[1].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - - y = arc[2].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; - - level = 0; - do - { - dx >>= 2; - level++; - } while ( dx > ONE_PIXEL / 4 ); - - levels[0] = level; - - do - { - level = levels[top]; - if ( level > 0 ) - { - gray_split_conic( arc ); - arc += 2; - top++; - levels[top] = levels[top - 1] = level - 1; - continue; - } - - Draw: - gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); - top--; - arc -= 2; - - } while ( top >= 0 ); - } - - - static void - gray_split_cubic( FT_Vector* base ) - { - TPos a, b, c, d; - - - base[6].x = base[3].x; - c = base[1].x; - d = base[2].x; - base[1].x = a = ( base[0].x + c ) / 2; - base[5].x = b = ( base[3].x + d ) / 2; - c = ( c + d ) / 2; - base[2].x = a = ( a + c ) / 2; - base[4].x = b = ( b + c ) / 2; - base[3].x = ( a + b ) / 2; - - base[6].y = base[3].y; - c = base[1].y; - d = base[2].y; - base[1].y = a = ( base[0].y + c ) / 2; - base[5].y = b = ( base[3].y + d ) / 2; - c = ( c + d ) / 2; - base[2].y = a = ( a + c ) / 2; - base[4].y = b = ( b + c ) / 2; - base[3].y = ( a + b ) / 2; - } - - - static void - gray_render_cubic( RAS_ARG_ const FT_Vector* control1, - const FT_Vector* control2, - const FT_Vector* to ) - { - FT_Vector* arc; - TPos min, max, y; - - - arc = ras.bez_stack; - arc[0].x = UPSCALE( to->x ); - arc[0].y = UPSCALE( to->y ); - arc[1].x = UPSCALE( control2->x ); - arc[1].y = UPSCALE( control2->y ); - arc[2].x = UPSCALE( control1->x ); - arc[2].y = UPSCALE( control1->y ); - arc[3].x = ras.x; - arc[3].y = ras.y; - - /* Short-cut the arc that crosses the current band. */ - min = max = arc[0].y; - - y = arc[1].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - y = arc[2].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - y = arc[3].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; - - for (;;) - { - /* Decide whether to split or draw. See `Rapid Termination */ - /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */ - /* F. Hain, at */ - /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */ - - { - TPos dx, dy, dx_, dy_; - TPos dx1, dy1, dx2, dy2; - TPos L, s, s_limit; - - - /* dx and dy are x and y components of the P0-P3 chord vector. */ - dx = dx_ = arc[3].x - arc[0].x; - dy = dy_ = arc[3].y - arc[0].y; - - L = FT_HYPOT( dx_, dy_ ); - - /* Avoid possible arithmetic overflow below by splitting. */ - if ( L > 32767 ) - goto Split; - - /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ - s_limit = L * (TPos)( ONE_PIXEL / 6 ); - - /* s is L * the perpendicular distance from P1 to the line P0-P3. */ - dx1 = arc[1].x - arc[0].x; - dy1 = arc[1].y - arc[0].y; - s = FT_ABS( dy * dx1 - dx * dy1 ); - - if ( s > s_limit ) - goto Split; - - /* s is L * the perpendicular distance from P2 to the line P0-P3. */ - dx2 = arc[2].x - arc[0].x; - dy2 = arc[2].y - arc[0].y; - s = FT_ABS( dy * dx2 - dx * dy2 ); - - if ( s > s_limit ) - goto Split; - - /* Split super curvy segments where the off points are so far - from the chord that the angles P0-P1-P3 or P0-P2-P3 become - acute as detected by appropriate dot products. */ - if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 || - dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 ) - goto Split; - - /* No reason to split. */ - goto Draw; - } - - Split: - gray_split_cubic( arc ); - arc += 3; - continue; - - Draw: - gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); - - if ( arc == ras.bez_stack ) - return; - - arc -= 3; - } - } - - - static int - gray_move_to( const FT_Vector* to, - gray_PWorker worker ) - { - TPos x, y; - - - /* record current cell, if any */ - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - - /* start to a new position */ - x = UPSCALE( to->x ); - y = UPSCALE( to->y ); - - gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) ); - - worker->x = x; - worker->y = y; - return 0; - } - - - static int - gray_line_to( const FT_Vector* to, - gray_PWorker worker ) - { - gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); - return 0; - } - - - static int - gray_conic_to( const FT_Vector* control, - const FT_Vector* to, - gray_PWorker worker ) - { - gray_render_conic( RAS_VAR_ control, to ); - return 0; - } - - - static int - gray_cubic_to( const FT_Vector* control1, - const FT_Vector* control2, - const FT_Vector* to, - gray_PWorker worker ) - { - gray_render_cubic( RAS_VAR_ control1, control2, to ); - return 0; - } - - - static void - gray_render_span( int y, - int count, - const FT_Span* spans, - gray_PWorker worker ) - { - unsigned char* p; - FT_Bitmap* map = &worker->target; - - - /* first of all, compute the scanline offset */ - p = (unsigned char*)map->buffer - y * map->pitch; - if ( map->pitch >= 0 ) - p += ( map->rows - 1 ) * (unsigned int)map->pitch; - - for ( ; count > 0; count--, spans++ ) - { - unsigned char coverage = spans->coverage; - - - if ( coverage ) - { - /* For small-spans it is faster to do it by ourselves than - * calling `memset'. This is mainly due to the cost of the - * function call. - */ - if ( spans->len >= 8 ) - FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len ); - else - { - unsigned char* q = p + spans->x; - - - switch ( spans->len ) - { - case 7: *q++ = (unsigned char)coverage; - case 6: *q++ = (unsigned char)coverage; - case 5: *q++ = (unsigned char)coverage; - case 4: *q++ = (unsigned char)coverage; - case 3: *q++ = (unsigned char)coverage; - case 2: *q++ = (unsigned char)coverage; - case 1: *q = (unsigned char)coverage; - default: - ; - } - } - } - } - } - - - static void - gray_hline( RAS_ARG_ TCoord x, - TCoord y, - TPos area, - TCoord acount ) - { - int coverage; - - - /* compute the coverage line's coverage, depending on the */ - /* outline fill rule */ - /* */ - /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ - /* */ - coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); - /* use range 0..256 */ - if ( coverage < 0 ) - coverage = -coverage; - - if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) - { - coverage &= 511; - - if ( coverage > 256 ) - coverage = 512 - coverage; - else if ( coverage == 256 ) - coverage = 255; - } - else - { - /* normal non-zero winding rule */ - if ( coverage >= 256 ) - coverage = 255; - } - - y += (TCoord)ras.min_ey; - x += (TCoord)ras.min_ex; - - /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */ - if ( x >= 32767 ) - x = 32767; - - /* FT_Span.y is an integer, so limit our coordinates appropriately */ - if ( y >= FT_INT_MAX ) - y = FT_INT_MAX; - - if ( coverage ) - { - FT_Span* span; - int count; - - - /* see whether we can add this span to the current list */ - count = ras.num_gray_spans; - span = ras.gray_spans + count - 1; - if ( count > 0 && - ras.span_y == y && - (int)span->x + span->len == (int)x && - span->coverage == coverage ) - { - span->len = (unsigned short)( span->len + acount ); - return; - } - - if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) - { - if ( ras.render_span && count > 0 ) - ras.render_span( ras.span_y, count, ras.gray_spans, - ras.render_span_data ); - -#ifdef FT_DEBUG_LEVEL_TRACE - - if ( count > 0 ) - { - int n; - - - FT_TRACE7(( "y = %3d ", ras.span_y )); - span = ras.gray_spans; - for ( n = 0; n < count; n++, span++ ) - FT_TRACE7(( "[%d..%d]:%02x ", - span->x, span->x + span->len - 1, span->coverage )); - FT_TRACE7(( "\n" )); - } - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - ras.num_gray_spans = 0; - ras.span_y = (int)y; - - span = ras.gray_spans; - } - else - span++; - - /* add a gray span to the current list */ - span->x = (short)x; - span->len = (unsigned short)acount; - span->coverage = (unsigned char)coverage; - - ras.num_gray_spans++; - } - } - - -#ifdef FT_DEBUG_LEVEL_TRACE - - /* to be called while in the debugger -- */ - /* this function causes a compiler warning since it is unused otherwise */ - static void - gray_dump_cells( RAS_ARG ) - { - int yindex; - - - for ( yindex = 0; yindex < ras.ycount; yindex++ ) - { - PCell cell; - - - printf( "%3d:", yindex ); - - for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next ) - printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area ); - printf( "\n" ); - } - } - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - - static void - gray_sweep( RAS_ARG_ const FT_Bitmap* target ) - { - int yindex; - - FT_UNUSED( target ); - - - if ( ras.num_cells == 0 ) - return; - - ras.num_gray_spans = 0; - - FT_TRACE7(( "gray_sweep: start\n" )); - - for ( yindex = 0; yindex < ras.ycount; yindex++ ) - { - PCell cell = ras.ycells[yindex]; - TCoord cover = 0; - TCoord x = 0; - - - for ( ; cell != NULL; cell = cell->next ) - { - TPos area; - - - if ( cell->x > x && cover != 0 ) - gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), - cell->x - x ); - - cover += cell->cover; - area = cover * ( ONE_PIXEL * 2 ) - cell->area; - - if ( area != 0 && cell->x >= 0 ) - gray_hline( RAS_VAR_ cell->x, yindex, area, 1 ); - - x = cell->x + 1; - } - - if ( cover != 0 ) - gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), - ras.count_ex - x ); - } - - if ( ras.render_span && ras.num_gray_spans > 0 ) - ras.render_span( ras.span_y, ras.num_gray_spans, - ras.gray_spans, ras.render_span_data ); - -#ifdef FT_DEBUG_LEVEL_TRACE - - if ( ras.num_gray_spans > 0 ) - { - FT_Span* span; - int n; - - - FT_TRACE7(( "y = %3d ", ras.span_y )); - span = ras.gray_spans; - for ( n = 0; n < ras.num_gray_spans; n++, span++ ) - FT_TRACE7(( "[%d..%d]:%02x ", - span->x, span->x + span->len - 1, span->coverage )); - FT_TRACE7(( "\n" )); - } - - FT_TRACE7(( "gray_sweep: end\n" )); - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - } - - -#ifdef _STANDALONE_ - - /*************************************************************************/ - /* */ - /* The following function should only compile in stand-alone mode, */ - /* i.e., when building this component without the rest of FreeType. */ - /* */ - /*************************************************************************/ - - /*************************************************************************/ - /* */ - /* <Function> */ - /* FT_Outline_Decompose */ - /* */ - /* <Description> */ - /* Walk over an outline's structure to decompose it into individual */ - /* segments and Bézier arcs. This function is also able to emit */ - /* `move to' and `close to' operations to indicate the start and end */ - /* of new contours in the outline. */ - /* */ - /* <Input> */ - /* outline :: A pointer to the source target. */ - /* */ - /* func_interface :: A table of `emitters', i.e., function pointers */ - /* called during decomposition to indicate path */ - /* operations. */ - /* */ - /* <InOut> */ - /* user :: A typeless pointer which is passed to each */ - /* emitter during the decomposition. It can be */ - /* used to store the state during the */ - /* decomposition. */ - /* */ - /* <Return> */ - /* Error code. 0 means success. */ - /* */ - static int - FT_Outline_Decompose( const FT_Outline* outline, - const FT_Outline_Funcs* func_interface, - void* user ) - { -#undef SCALED -#define SCALED( x ) ( ( (x) << shift ) - delta ) - - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_start; - - FT_Vector* point; - FT_Vector* limit; - char* tags; - - int error; - - int n; /* index of contour in outline */ - int first; /* index of first point in contour */ - char tag; /* current point's state */ - - int shift; - TPos delta; - - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - if ( !func_interface ) - return FT_THROW( Invalid_Argument ); - - shift = func_interface->shift; - delta = func_interface->delta; - first = 0; - - for ( n = 0; n < outline->n_contours; n++ ) - { - int last; /* index of last point in contour */ - - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); - - last = outline->contours[n]; - if ( last < 0 ) - goto Invalid_Outline; - limit = outline->points + last; - - v_start = outline->points[first]; - v_start.x = SCALED( v_start.x ); - v_start.y = SCALED( v_start.y ); - - v_last = outline->points[last]; - v_last.x = SCALED( v_last.x ); - v_last.y = SCALED( v_last.y ); - - v_control = v_start; - - point = outline->points + first; - tags = outline->tags + first; - tag = FT_CURVE_TAG( tags[0] ); - - /* A contour cannot start with a cubic control point! */ - if ( tag == FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - /* check first point to determine origin */ - if ( tag == FT_CURVE_TAG_CONIC ) - { - /* first point is conic control. Yes, this happens. */ - if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) - { - /* start at last point if it is on the curve */ - v_start = v_last; - limit--; - } - else - { - /* if both first and last points are conic, */ - /* start at their middle and record its position */ - /* for closure */ - v_start.x = ( v_start.x + v_last.x ) / 2; - v_start.y = ( v_start.y + v_last.y ) / 2; - - v_last = v_start; - } - point--; - tags--; - } - - FT_TRACE5(( " move to (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0 )); - error = func_interface->move_to( &v_start, user ); - if ( error ) - goto Exit; - - while ( point < limit ) - { - point++; - tags++; - - tag = FT_CURVE_TAG( tags[0] ); - switch ( tag ) - { - case FT_CURVE_TAG_ON: /* emit a single line_to */ - { - FT_Vector vec; - - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); - - FT_TRACE5(( " line to (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0 )); - error = func_interface->line_to( &vec, user ); - if ( error ) - goto Exit; - continue; - } - - case FT_CURVE_TAG_CONIC: /* consume conic arcs */ - v_control.x = SCALED( point->x ); - v_control.y = SCALED( point->y ); - - Do_Conic: - if ( point < limit ) - { - FT_Vector vec; - FT_Vector v_middle; - - - point++; - tags++; - tag = FT_CURVE_TAG( tags[0] ); - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); - - if ( tag == FT_CURVE_TAG_ON ) - { - FT_TRACE5(( " conic to (%.2f, %.2f)" - " with control (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); - error = func_interface->conic_to( &v_control, &vec, user ); - if ( error ) - goto Exit; - continue; - } - - if ( tag != FT_CURVE_TAG_CONIC ) - goto Invalid_Outline; - - v_middle.x = ( v_control.x + vec.x ) / 2; - v_middle.y = ( v_control.y + vec.y ) / 2; - - FT_TRACE5(( " conic to (%.2f, %.2f)" - " with control (%.2f, %.2f)\n", - v_middle.x / 64.0, v_middle.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); - error = func_interface->conic_to( &v_control, &v_middle, user ); - if ( error ) - goto Exit; - - v_control = vec; - goto Do_Conic; - } - - FT_TRACE5(( " conic to (%.2f, %.2f)" - " with control (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); - error = func_interface->conic_to( &v_control, &v_start, user ); - goto Close; - - default: /* FT_CURVE_TAG_CUBIC */ - { - FT_Vector vec1, vec2; - - - if ( point + 1 > limit || - FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) - goto Invalid_Outline; - - point += 2; - tags += 2; - - vec1.x = SCALED( point[-2].x ); - vec1.y = SCALED( point[-2].y ); - - vec2.x = SCALED( point[-1].x ); - vec2.y = SCALED( point[-1].y ); - - if ( point <= limit ) - { - FT_Vector vec; - - - vec.x = SCALED( point->x ); - vec.y = SCALED( point->y ); - - FT_TRACE5(( " cubic to (%.2f, %.2f)" - " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0, - vec1.x / 64.0, vec1.y / 64.0, - vec2.x / 64.0, vec2.y / 64.0 )); - error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); - if ( error ) - goto Exit; - continue; - } - - FT_TRACE5(( " cubic to (%.2f, %.2f)" - " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0, - vec1.x / 64.0, vec1.y / 64.0, - vec2.x / 64.0, vec2.y / 64.0 )); - error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); - goto Close; - } - } - } - - /* close the contour with a line segment */ - FT_TRACE5(( " line to (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0 )); - error = func_interface->line_to( &v_start, user ); - - Close: - if ( error ) - goto Exit; - - first = last + 1; - } - - FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); - return 0; - - Exit: - FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); - return error; - - Invalid_Outline: - return FT_THROW( Invalid_Outline ); - } - -#endif /* _STANDALONE_ */ - - - typedef struct gray_TBand_ - { - TPos min, max; - - } gray_TBand; - - - FT_DEFINE_OUTLINE_FUNCS( - func_interface, - - (FT_Outline_MoveTo_Func) gray_move_to, - (FT_Outline_LineTo_Func) gray_line_to, - (FT_Outline_ConicTo_Func)gray_conic_to, - (FT_Outline_CubicTo_Func)gray_cubic_to, - 0, - 0 ) - - - static int - gray_convert_glyph_inner( RAS_ARG ) - { - - volatile int error = 0; - -#ifdef FT_CONFIG_OPTION_PIC - FT_Outline_Funcs func_interface; - Init_Class_func_interface(&func_interface); -#endif - - if ( ft_setjmp( ras.jump_buffer ) == 0 ) - { - error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - } - else - error = FT_THROW( Memory_Overflow ); - - return error; - } - - - static int - gray_convert_glyph( RAS_ARG ) - { - gray_TBand bands[40]; - gray_TBand* volatile band; - int volatile n, num_bands; - TPos volatile min, max, max_y; - FT_BBox* clip; - - - /* Set up state in the raster object */ - gray_compute_cbox( RAS_VAR ); - - /* clip to target bitmap, exit if nothing to do */ - clip = &ras.clip_box; - - if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || - ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax ) - return 0; - - if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin; - if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin; - - if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax; - if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax; - - ras.count_ex = ras.max_ex - ras.min_ex; - ras.count_ey = ras.max_ey - ras.min_ey; - - /* set up vertical bands */ - num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size ); - if ( num_bands == 0 ) - num_bands = 1; - if ( num_bands >= 39 ) - num_bands = 39; - - ras.band_shoot = 0; - - min = ras.min_ey; - max_y = ras.max_ey; - - for ( n = 0; n < num_bands; n++, min = max ) - { - max = min + ras.band_size; - if ( n == num_bands - 1 || max > max_y ) - max = max_y; - - bands[0].min = min; - bands[0].max = max; - band = bands; - - do - { - TPos bottom, top, middle; - int error; - - { - PCell cells_max; - int yindex; - long cell_start, cell_end, cell_mod; - - - ras.ycells = (PCell*)ras.buffer; - ras.ycount = band->max - band->min; - - cell_start = (long)sizeof ( PCell ) * ras.ycount; - cell_mod = cell_start % (long)sizeof ( TCell ); - if ( cell_mod > 0 ) - cell_start += (long)sizeof ( TCell ) - cell_mod; - - cell_end = ras.buffer_size; - cell_end -= cell_end % (long)sizeof ( TCell ); - - cells_max = (PCell)( (char*)ras.buffer + cell_end ); - ras.cells = (PCell)( (char*)ras.buffer + cell_start ); - if ( ras.cells >= cells_max ) - goto ReduceBands; - - ras.max_cells = cells_max - ras.cells; - if ( ras.max_cells < 2 ) - goto ReduceBands; - - for ( yindex = 0; yindex < ras.ycount; yindex++ ) - ras.ycells[yindex] = NULL; - } - - ras.num_cells = 0; - ras.invalid = 1; - ras.min_ey = band->min; - ras.max_ey = band->max; - ras.count_ey = band->max - band->min; - - error = gray_convert_glyph_inner( RAS_VAR ); - - if ( !error ) - { - gray_sweep( RAS_VAR_ &ras.target ); - band--; - continue; - } - else if ( error != ErrRaster_Memory_Overflow ) - return 1; - - ReduceBands: - /* render pool overflow; we will reduce the render band by half */ - bottom = band->min; - top = band->max; - middle = bottom + ( ( top - bottom ) >> 1 ); - - /* This is too complex for a single scanline; there must */ - /* be some problems. */ - if ( middle == bottom ) - { -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); -#endif - return 1; - } - - if ( bottom-top >= ras.band_size ) - ras.band_shoot++; - - band[1].min = bottom; - band[1].max = middle; - band[0].min = middle; - band[0].max = top; - band++; - } while ( band >= bands ); - } - - if ( ras.band_shoot > 8 && ras.band_size > 16 ) - ras.band_size = ras.band_size / 2; - - return 0; - } - - - static int - gray_raster_render( gray_PRaster raster, - const FT_Raster_Params* params ) - { - const FT_Outline* outline = (const FT_Outline*)params->source; - const FT_Bitmap* target_map = params->target; - - gray_TWorker worker[1]; - - TCell buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( TCell )]; - long buffer_size = sizeof ( buffer ); - int band_size = (int)( buffer_size / - (long)( sizeof ( TCell ) * 8 ) ); - - - if ( !raster ) - return FT_THROW( Invalid_Argument ); - - if ( !outline ) - return FT_THROW( Invalid_Outline ); - - /* return immediately if the outline is empty */ - if ( outline->n_points == 0 || outline->n_contours <= 0 ) - return 0; - - if ( !outline->contours || !outline->points ) - return FT_THROW( Invalid_Outline ); - - if ( outline->n_points != - outline->contours[outline->n_contours - 1] + 1 ) - return FT_THROW( Invalid_Outline ); - - /* if direct mode is not set, we must have a target bitmap */ - if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) ) - { - if ( !target_map ) - return FT_THROW( Invalid_Argument ); - - /* nothing to do */ - if ( !target_map->width || !target_map->rows ) - return 0; - - if ( !target_map->buffer ) - return FT_THROW( Invalid_Argument ); - } - - /* this version does not support monochrome rendering */ - if ( !( params->flags & FT_RASTER_FLAG_AA ) ) - return FT_THROW( Invalid_Mode ); - - /* compute clipping box */ - if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) ) - { - /* compute clip box from target pixmap */ - ras.clip_box.xMin = 0; - ras.clip_box.yMin = 0; - ras.clip_box.xMax = (FT_Pos)target_map->width; - ras.clip_box.yMax = (FT_Pos)target_map->rows; - } - else if ( params->flags & FT_RASTER_FLAG_CLIP ) - ras.clip_box = params->clip_box; - else - { - ras.clip_box.xMin = -32768L; - ras.clip_box.yMin = -32768L; - ras.clip_box.xMax = 32767L; - ras.clip_box.yMax = 32767L; - } - - gray_init_cells( RAS_VAR_ buffer, buffer_size ); - - ras.outline = *outline; - ras.num_cells = 0; - ras.invalid = 1; - ras.band_size = band_size; - ras.num_gray_spans = 0; - ras.span_y = 0; - - if ( params->flags & FT_RASTER_FLAG_DIRECT ) - { - ras.render_span = (FT_Raster_Span_Func)params->gray_spans; - ras.render_span_data = params->user; - } - else - { - ras.target = *target_map; - ras.render_span = (FT_Raster_Span_Func)gray_render_span; - ras.render_span_data = &ras; - } - - return gray_convert_glyph( RAS_VAR ); - } - - - /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/ - /**** a static object. *****/ - -#ifdef _STANDALONE_ - - static int - gray_raster_new( void* memory, - FT_Raster* araster ) - { - static gray_TRaster the_raster; - - FT_UNUSED( memory ); - - - *araster = (FT_Raster)&the_raster; - FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); - - return 0; - } - - - static void - gray_raster_done( FT_Raster raster ) - { - /* nothing */ - FT_UNUSED( raster ); - } - -#else /* !_STANDALONE_ */ - - static int - gray_raster_new( FT_Memory memory, - FT_Raster* araster ) - { - FT_Error error; - gray_PRaster raster = NULL; - - - *araster = 0; - if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) ) - { - raster->memory = memory; - *araster = (FT_Raster)raster; - } - - return error; - } - - - static void - gray_raster_done( FT_Raster raster ) - { - FT_Memory memory = (FT_Memory)((gray_PRaster)raster)->memory; - - - FT_FREE( raster ); - } - -#endif /* !_STANDALONE_ */ - - - static void - gray_raster_reset( FT_Raster raster, - char* pool_base, - long pool_size ) - { - FT_UNUSED( raster ); - FT_UNUSED( pool_base ); - FT_UNUSED( pool_size ); - } - - - static int - gray_raster_set_mode( FT_Raster raster, - unsigned long mode, - void* args ) - { - FT_UNUSED( raster ); - FT_UNUSED( mode ); - FT_UNUSED( args ); - - - return 0; /* nothing to do */ - } - - - FT_DEFINE_RASTER_FUNCS( - ft_grays_raster, - - FT_GLYPH_FORMAT_OUTLINE, - - (FT_Raster_New_Func) gray_raster_new, - (FT_Raster_Reset_Func) gray_raster_reset, - (FT_Raster_Set_Mode_Func)gray_raster_set_mode, - (FT_Raster_Render_Func) gray_raster_render, - (FT_Raster_Done_Func) gray_raster_done ) - - -/* END */ - - -/* Local Variables: */ -/* coding: utf-8 */ -/* End: */ diff --git a/third_party/freetype/src/smooth/ftgrays.h b/third_party/freetype/src/smooth/ftgrays.h deleted file mode 100644 index 1b5760330c47e512e34e31d492a05573f36d1fe7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftgrays.h +++ /dev/null @@ -1,58 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftgrays.h */ -/* */ -/* FreeType smooth renderer declaration */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTGRAYS_H__ -#define __FTGRAYS_H__ - -#ifdef __cplusplus - extern "C" { -#endif - - -#ifdef _STANDALONE_ -#include "ftimage.h" -#else -#include <ft2build.h> -#include FT_CONFIG_CONFIG_H /* for FT_CONFIG_OPTION_PIC */ -#include FT_IMAGE_H -#endif - - - /*************************************************************************/ - /* */ - /* To make ftgrays.h independent from configuration files we check */ - /* whether FT_EXPORT_VAR has been defined already. */ - /* */ - /* On some systems and compilers (Win32 mostly), an extra keyword is */ - /* necessary to compile the library as a DLL. */ - /* */ -#ifndef FT_EXPORT_VAR -#define FT_EXPORT_VAR( x ) extern x -#endif - - FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_grays_raster; - - -#ifdef __cplusplus - } -#endif - -#endif /* __FTGRAYS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/smooth/ftsmerrs.h b/third_party/freetype/src/smooth/ftsmerrs.h deleted file mode 100644 index cc38aa1996e6ab9cc22b7ccb43d0c1629dfa8ac1..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftsmerrs.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsmerrs.h */ -/* */ -/* smooth renderer error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the smooth renderer error enumeration */ - /* constants. */ - /* */ - /*************************************************************************/ - -#ifndef __FTSMERRS_H__ -#define __FTSMERRS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX Smooth_Err_ -#define FT_ERR_BASE FT_Mod_Err_Smooth - -#include FT_ERRORS_H - -#endif /* __FTSMERRS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/smooth/ftsmooth.c b/third_party/freetype/src/smooth/ftsmooth.c deleted file mode 100644 index 3620550534022444cb4b25195eb9be635f6b9d12..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftsmooth.c +++ /dev/null @@ -1,511 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsmooth.c */ -/* */ -/* Anti-aliasing renderer interface (body). */ -/* */ -/* Copyright 2000-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_OUTLINE_H -#include "ftsmooth.h" -#include "ftgrays.h" -#include "ftspic.h" - -#include "ftsmerrs.h" - - - /* initialize renderer -- init its raster */ - static FT_Error - ft_smooth_init( FT_Renderer render ) - { - FT_Library library = FT_MODULE_LIBRARY( render ); - - - render->clazz->raster_class->raster_reset( render->raster, - library->raster_pool, - library->raster_pool_size ); - - return 0; - } - - - /* sets render-specific mode */ - static FT_Error - ft_smooth_set_mode( FT_Renderer render, - FT_ULong mode_tag, - FT_Pointer data ) - { - /* we simply pass it to the raster */ - return render->clazz->raster_class->raster_set_mode( render->raster, - mode_tag, - data ); - } - - /* transform a given glyph image */ - static FT_Error - ft_smooth_transform( FT_Renderer render, - FT_GlyphSlot slot, - const FT_Matrix* matrix, - const FT_Vector* delta ) - { - FT_Error error = FT_Err_Ok; - - - if ( slot->format != render->glyph_format ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( matrix ) - FT_Outline_Transform( &slot->outline, matrix ); - - if ( delta ) - FT_Outline_Translate( &slot->outline, delta->x, delta->y ); - - Exit: - return error; - } - - - /* return the glyph's control box */ - static void - ft_smooth_get_cbox( FT_Renderer render, - FT_GlyphSlot slot, - FT_BBox* cbox ) - { - FT_MEM_ZERO( cbox, sizeof ( *cbox ) ); - - if ( slot->format == render->glyph_format ) - FT_Outline_Get_CBox( &slot->outline, cbox ); - } - - - /* convert a slot's glyph image into a bitmap */ - static FT_Error - ft_smooth_render_generic( FT_Renderer render, - FT_GlyphSlot slot, - FT_Render_Mode mode, - const FT_Vector* origin, - FT_Render_Mode required_mode ) - { - FT_Error error; - FT_Outline* outline = &slot->outline; - FT_Bitmap* bitmap = &slot->bitmap; - FT_Memory memory = render->root.memory; - FT_BBox cbox; - FT_Pos x_shift = 0; - FT_Pos y_shift = 0; - FT_Pos x_left, y_top; - FT_Pos width, height, pitch; -#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - FT_Pos height_org, width_org; -#endif - FT_Int hmul = mode == FT_RENDER_MODE_LCD; - FT_Int vmul = mode == FT_RENDER_MODE_LCD_V; - - FT_Raster_Params params; - - FT_Bool have_outline_shifted = FALSE; - FT_Bool have_buffer = FALSE; - - - /* check glyph image format */ - if ( slot->format != render->glyph_format ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - /* check mode */ - if ( mode != required_mode ) - { - error = FT_THROW( Cannot_Render_Glyph ); - goto Exit; - } - - if ( origin ) - { - x_shift = origin->x; - y_shift = origin->y; - } - - /* compute the control box, and grid fit it */ - /* taking into account the origin shift */ - FT_Outline_Get_CBox( outline, &cbox ); - - cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift ); - cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift ); - cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift ); - cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift ); - - x_shift -= cbox.xMin; - y_shift -= cbox.yMin; - - x_left = cbox.xMin >> 6; - y_top = cbox.yMax >> 6; - - width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6; - height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6; - -#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - width_org = width; - height_org = height; -#endif - - pitch = width; - if ( hmul ) - { - width *= 3; - pitch = FT_PAD_CEIL( width, 4 ); - } - - if ( vmul ) - height *= 3; - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - if ( slot->library->lcd_filter_func ) - { - FT_Int extra = slot->library->lcd_extra; - - - if ( hmul ) - { - x_shift += 64 * ( extra >> 1 ); - x_left -= extra >> 1; - width += 3 * extra; - pitch = FT_PAD_CEIL( width, 4 ); - } - - if ( vmul ) - { - y_shift += 64 * ( extra >> 1 ); - y_top += extra >> 1; - height += 3 * extra; - } - } - -#endif - - /* - * XXX: on 16bit system, we return an error for huge bitmap - * to prevent an overflow. - */ - if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX || - x_left < FT_INT_MIN || y_top < FT_INT_MIN ) - { - error = FT_THROW( Invalid_Pixel_Size ); - goto Exit; - } - - /* Required check is (pitch * height < FT_ULONG_MAX), */ - /* but we care realistic cases only. Always pitch <= width. */ - if ( width > 0x7FFF || height > 0x7FFF ) - { - FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n", - width, height )); - error = FT_THROW( Raster_Overflow ); - goto Exit; - } - - /* release old bitmap buffer */ - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { - FT_FREE( bitmap->buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - - /* allocate new one */ - if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) ) - goto Exit; - else - have_buffer = TRUE; - - slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - - slot->format = FT_GLYPH_FORMAT_BITMAP; - slot->bitmap_left = (FT_Int)x_left; - slot->bitmap_top = (FT_Int)y_top; - - bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; - bitmap->num_grays = 256; - bitmap->width = (unsigned int)width; - bitmap->rows = (unsigned int)height; - bitmap->pitch = pitch; - - /* translate outline to render it into the bitmap */ - if ( x_shift || y_shift ) - { - FT_Outline_Translate( outline, x_shift, y_shift ); - have_outline_shifted = TRUE; - } - - /* set up parameters */ - params.target = bitmap; - params.source = outline; - params.flags = FT_RASTER_FLAG_AA; - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - /* implode outline if needed */ - { - FT_Vector* points = outline->points; - FT_Vector* points_end = points + outline->n_points; - FT_Vector* vec; - - - if ( hmul ) - for ( vec = points; vec < points_end; vec++ ) - vec->x *= 3; - - if ( vmul ) - for ( vec = points; vec < points_end; vec++ ) - vec->y *= 3; - } - - /* render outline into the bitmap */ - error = render->raster_render( render->raster, ¶ms ); - - /* deflate outline if needed */ - { - FT_Vector* points = outline->points; - FT_Vector* points_end = points + outline->n_points; - FT_Vector* vec; - - - if ( hmul ) - for ( vec = points; vec < points_end; vec++ ) - vec->x /= 3; - - if ( vmul ) - for ( vec = points; vec < points_end; vec++ ) - vec->y /= 3; - } - - if ( error ) - goto Exit; - - if ( slot->library->lcd_filter_func ) - slot->library->lcd_filter_func( bitmap, mode, slot->library ); - -#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - - /* render outline into bitmap */ - error = render->raster_render( render->raster, ¶ms ); - if ( error ) - goto Exit; - - /* expand it horizontally */ - if ( hmul ) - { - FT_Byte* line = bitmap->buffer; - FT_UInt hh; - - - for ( hh = height_org; hh > 0; hh--, line += pitch ) - { - FT_UInt xx; - FT_Byte* end = line + width; - - - for ( xx = width_org; xx > 0; xx-- ) - { - FT_UInt pixel = line[xx-1]; - - - end[-3] = (FT_Byte)pixel; - end[-2] = (FT_Byte)pixel; - end[-1] = (FT_Byte)pixel; - end -= 3; - } - } - } - - /* expand it vertically */ - if ( vmul ) - { - FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch; - FT_Byte* write = bitmap->buffer; - FT_UInt hh; - - - for ( hh = height_org; hh > 0; hh-- ) - { - ft_memcpy( write, read, pitch ); - write += pitch; - - ft_memcpy( write, read, pitch ); - write += pitch; - - ft_memcpy( write, read, pitch ); - write += pitch; - read += pitch; - } - } - -#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - - /* everything is fine; don't deallocate buffer */ - have_buffer = FALSE; - - error = FT_Err_Ok; - - Exit: - if ( have_outline_shifted ) - FT_Outline_Translate( outline, -x_shift, -y_shift ); - if ( have_buffer ) - { - FT_FREE( bitmap->buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - - return error; - } - - - /* convert a slot's glyph image into a bitmap */ - static FT_Error - ft_smooth_render( FT_Renderer render, - FT_GlyphSlot slot, - FT_Render_Mode mode, - const FT_Vector* origin ) - { - if ( mode == FT_RENDER_MODE_LIGHT ) - mode = FT_RENDER_MODE_NORMAL; - - return ft_smooth_render_generic( render, slot, mode, origin, - FT_RENDER_MODE_NORMAL ); - } - - - /* convert a slot's glyph image into a horizontal LCD bitmap */ - static FT_Error - ft_smooth_render_lcd( FT_Renderer render, - FT_GlyphSlot slot, - FT_Render_Mode mode, - const FT_Vector* origin ) - { - FT_Error error; - - error = ft_smooth_render_generic( render, slot, mode, origin, - FT_RENDER_MODE_LCD ); - if ( !error ) - slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD; - - return error; - } - - - /* convert a slot's glyph image into a vertical LCD bitmap */ - static FT_Error - ft_smooth_render_lcd_v( FT_Renderer render, - FT_GlyphSlot slot, - FT_Render_Mode mode, - const FT_Vector* origin ) - { - FT_Error error; - - error = ft_smooth_render_generic( render, slot, mode, origin, - FT_RENDER_MODE_LCD_V ); - if ( !error ) - slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V; - - return error; - } - - - FT_DEFINE_RENDERER( ft_smooth_renderer_class, - - FT_MODULE_RENDERER, - sizeof ( FT_RendererRec ), - - "smooth", - 0x10000L, - 0x20000L, - - 0, /* module specific interface */ - - (FT_Module_Constructor)ft_smooth_init, - (FT_Module_Destructor) 0, - (FT_Module_Requester) 0 - , - - FT_GLYPH_FORMAT_OUTLINE, - - (FT_Renderer_RenderFunc) ft_smooth_render, - (FT_Renderer_TransformFunc)ft_smooth_transform, - (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, - (FT_Renderer_SetModeFunc) ft_smooth_set_mode, - - (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET - ) - - - FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class, - - FT_MODULE_RENDERER, - sizeof ( FT_RendererRec ), - - "smooth-lcd", - 0x10000L, - 0x20000L, - - 0, /* module specific interface */ - - (FT_Module_Constructor)ft_smooth_init, - (FT_Module_Destructor) 0, - (FT_Module_Requester) 0 - , - - FT_GLYPH_FORMAT_OUTLINE, - - (FT_Renderer_RenderFunc) ft_smooth_render_lcd, - (FT_Renderer_TransformFunc)ft_smooth_transform, - (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, - (FT_Renderer_SetModeFunc) ft_smooth_set_mode, - - (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET - ) - - FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class, - - FT_MODULE_RENDERER, - sizeof ( FT_RendererRec ), - - "smooth-lcdv", - 0x10000L, - 0x20000L, - - 0, /* module specific interface */ - - (FT_Module_Constructor)ft_smooth_init, - (FT_Module_Destructor) 0, - (FT_Module_Requester) 0 - , - - FT_GLYPH_FORMAT_OUTLINE, - - (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v, - (FT_Renderer_TransformFunc)ft_smooth_transform, - (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, - (FT_Renderer_SetModeFunc) ft_smooth_set_mode, - - (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET - ) - - -/* END */ diff --git a/third_party/freetype/src/smooth/ftsmooth.h b/third_party/freetype/src/smooth/ftsmooth.h deleted file mode 100644 index 765018c239b86098aaeccd1b8c56abc1de68f9ea..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftsmooth.h +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftsmooth.h */ -/* */ -/* Anti-aliasing renderer interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTSMOOTH_H__ -#define __FTSMOOTH_H__ - - -#include <ft2build.h> -#include FT_RENDER_H - - -FT_BEGIN_HEADER - - -#ifndef FT_CONFIG_OPTION_NO_STD_RASTER - FT_DECLARE_RENDERER( ft_std_renderer_class ) -#endif - -#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER - FT_DECLARE_RENDERER( ft_smooth_renderer_class ) - - FT_DECLARE_RENDERER( ft_smooth_lcd_renderer_class ) - - FT_DECLARE_RENDERER( ft_smooth_lcd_v_renderer_class ) -#endif - - - -FT_END_HEADER - -#endif /* __FTSMOOTH_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/smooth/ftspic.c b/third_party/freetype/src/smooth/ftspic.c deleted file mode 100644 index 8e6ed57eecb30c618d3612f125f09b6e7b0a0a02..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftspic.c +++ /dev/null @@ -1,118 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftspic.c */ -/* */ -/* The FreeType position independent code services for smooth module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "ftspic.h" -#include "ftsmerrs.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from ftgrays.c */ - void - FT_Init_Class_ft_grays_raster( FT_Raster_Funcs* funcs ); - - - void - ft_smooth_renderer_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->smooth ) - { - SmoothPIC* container = (SmoothPIC*)pic_container->smooth; - - - if ( --container->ref_count ) - return; - - FT_FREE( container ); - pic_container->smooth = NULL; - } - } - - - FT_Error - ft_smooth_renderer_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - SmoothPIC* container = NULL; - FT_Memory memory = library->memory; - - - /* since this function also serve smooth_lcd and smooth_lcdv renderers, - it implements reference counting */ - if ( pic_container->smooth ) - { - ((SmoothPIC*)pic_container->smooth)->ref_count++; - return error; - } - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->smooth = container; - - container->ref_count = 1; - - /* initialize pointer table - */ - /* this is how the module usually expects this data */ - FT_Init_Class_ft_grays_raster( &container->ft_grays_raster ); - - return error; - } - - - /* re-route these init and free functions to the above functions */ - FT_Error - ft_smooth_lcd_renderer_class_pic_init( FT_Library library ) - { - return ft_smooth_renderer_class_pic_init( library ); - } - - - void - ft_smooth_lcd_renderer_class_pic_free( FT_Library library ) - { - ft_smooth_renderer_class_pic_free( library ); - } - - - FT_Error - ft_smooth_lcdv_renderer_class_pic_init( FT_Library library ) - { - return ft_smooth_renderer_class_pic_init( library ); - } - - - void - ft_smooth_lcdv_renderer_class_pic_free( FT_Library library ) - { - ft_smooth_renderer_class_pic_free( library ); - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/smooth/ftspic.h b/third_party/freetype/src/smooth/ftspic.h deleted file mode 100644 index 071afcff20313a17fc841f6ee37be55872f94383..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/ftspic.h +++ /dev/null @@ -1,75 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftspic.h */ -/* */ -/* The FreeType position independent code services for smooth module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __FTSPIC_H__ -#define __FTSPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -FT_BEGIN_HEADER - -#ifndef FT_CONFIG_OPTION_PIC - -#define FT_GRAYS_RASTER_GET ft_grays_raster - -#else /* FT_CONFIG_OPTION_PIC */ - - typedef struct SmoothPIC_ - { - int ref_count; - FT_Raster_Funcs ft_grays_raster; - - } SmoothPIC; - - -#define GET_PIC( lib ) \ - ( (SmoothPIC*)( (lib)->pic_container.smooth ) ) -#define FT_GRAYS_RASTER_GET ( GET_PIC( library )->ft_grays_raster ) - - - /* see ftspic.c for the implementation */ - void - ft_smooth_renderer_class_pic_free( FT_Library library ); - - void - ft_smooth_lcd_renderer_class_pic_free( FT_Library library ); - - void - ft_smooth_lcdv_renderer_class_pic_free( FT_Library library ); - - FT_Error - ft_smooth_renderer_class_pic_init( FT_Library library ); - - FT_Error - ft_smooth_lcd_renderer_class_pic_init( FT_Library library ); - - FT_Error - ft_smooth_lcdv_renderer_class_pic_init( FT_Library library ); - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -FT_END_HEADER - -#endif /* __FTSPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/smooth/smooth.c b/third_party/freetype/src/smooth/smooth.c deleted file mode 100644 index 4ca4344c892027f0fd3c7e75b97838db870e1b86..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/smooth/smooth.c +++ /dev/null @@ -1,27 +0,0 @@ -/***************************************************************************/ -/* */ -/* smooth.c */ -/* */ -/* FreeType anti-aliasing rasterer module component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "ftspic.c" -#include "ftgrays.c" -#include "ftsmooth.c" - - -/* END */ diff --git a/third_party/freetype/src/truetype/Jamfile b/third_party/freetype/src/truetype/Jamfile deleted file mode 100644 index 88cc26f2b13a22007db125938d6a991842021e7e..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/Jamfile +++ /dev/null @@ -1,37 +0,0 @@ -# FreeType 2 src/truetype Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) truetype ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = ttdriver - ttgload - ttgxvar - ttinterp - ttobjs - ttpic - ttpload - ttsubpix - ; - } - else - { - _sources = truetype ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/truetype Jamfile diff --git a/third_party/freetype/src/truetype/truetype.c b/third_party/freetype/src/truetype/truetype.c deleted file mode 100644 index f929437dc17c5da8444d44240c4939765b90748f..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/truetype.c +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************/ -/* */ -/* truetype.c */ -/* */ -/* FreeType TrueType driver component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "ttpic.c" -#include "ttdriver.c" /* driver interface */ -#include "ttpload.c" /* tables loader */ -#include "ttgload.c" /* glyph loader */ -#include "ttobjs.c" /* object manager */ - -#ifdef TT_USE_BYTECODE_INTERPRETER -#include "ttinterp.c" -#include "ttsubpix.c" -#endif - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.c" /* gx distortable font */ -#endif - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttdriver.c b/third_party/freetype/src/truetype/ttdriver.c deleted file mode 100644 index 08b30c95ad06014d1726a2972dbe148b6560f5f7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttdriver.c +++ /dev/null @@ -1,565 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttdriver.c */ -/* */ -/* TrueType font driver implementation (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_SERVICE_FONT_FORMAT_H - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include FT_MULTIPLE_MASTERS_H -#include FT_SERVICE_MULTIPLE_MASTERS_H -#endif - -#include FT_SERVICE_TRUETYPE_ENGINE_H -#include FT_SERVICE_TRUETYPE_GLYF_H -#include FT_SERVICE_PROPERTIES_H -#include FT_TRUETYPE_DRIVER_H - -#include "ttdriver.h" -#include "ttgload.h" -#include "ttpload.h" - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.h" -#endif - -#include "tterrors.h" - -#include "ttpic.h" - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttdriver - - - /* - * PROPERTY SERVICE - * - */ - static FT_Error - tt_property_set( FT_Module module, /* TT_Driver */ - const char* property_name, - const void* value ) - { - FT_Error error = FT_Err_Ok; - TT_Driver driver = (TT_Driver)module; - - - if ( !ft_strcmp( property_name, "interpreter-version" ) ) - { - FT_UInt* interpreter_version = (FT_UInt*)value; - - -#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( *interpreter_version != TT_INTERPRETER_VERSION_35 ) - error = FT_ERR( Unimplemented_Feature ); - else -#endif - driver->interpreter_version = *interpreter_version; - - return error; - } - - FT_TRACE0(( "tt_property_set: missing property `%s'\n", - property_name )); - return FT_THROW( Missing_Property ); - } - - - static FT_Error - tt_property_get( FT_Module module, /* TT_Driver */ - const char* property_name, - const void* value ) - { - FT_Error error = FT_Err_Ok; - TT_Driver driver = (TT_Driver)module; - - FT_UInt interpreter_version = driver->interpreter_version; - - - if ( !ft_strcmp( property_name, "interpreter-version" ) ) - { - FT_UInt* val = (FT_UInt*)value; - - - *val = interpreter_version; - - return error; - } - - FT_TRACE0(( "tt_property_get: missing property `%s'\n", - property_name )); - return FT_THROW( Missing_Property ); - } - - - FT_DEFINE_SERVICE_PROPERTIESREC( - tt_service_properties, - (FT_Properties_SetFunc)tt_property_set, - (FT_Properties_GetFunc)tt_property_get ) - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** F A C E S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_get_kerning */ - /* */ - /* <Description> */ - /* A driver method used to return the kerning vector between two */ - /* glyphs of the same face. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* left_glyph :: The index of the left glyph in the kern pair. */ - /* */ - /* right_glyph :: The index of the right glyph in the kern pair. */ - /* */ - /* <Output> */ - /* kerning :: The kerning vector. This is in font units for */ - /* scalable formats, and in pixels for fixed-sizes */ - /* formats. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* Only horizontal layouts (left-to-right & right-to-left) are */ - /* supported by this function. Other layouts, or more sophisticated */ - /* kernings, are out of scope of this method (the basic driver */ - /* interface is meant to be simple). */ - /* */ - /* They can be implemented by format-specific interfaces. */ - /* */ - static FT_Error - tt_get_kerning( FT_Face ttface, /* TT_Face */ - FT_UInt left_glyph, - FT_UInt right_glyph, - FT_Vector* kerning ) - { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; - - - kerning->x = 0; - kerning->y = 0; - - if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); - - return 0; - } - - - static FT_Error - tt_get_advances( FT_Face ttface, - FT_UInt start, - FT_UInt count, - FT_Int32 flags, - FT_Fixed *advances ) - { - FT_UInt nn; - TT_Face face = (TT_Face) ttface; - - - /* XXX: TODO: check for sbits */ - - if ( flags & FT_LOAD_VERTICAL_LAYOUT ) - { - for ( nn = 0; nn < count; nn++ ) - { - FT_Short tsb; - FT_UShort ah; - - - /* since we don't need `tsb', we use zero for `yMax' parameter */ - TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah ); - advances[nn] = ah; - } - } - else - { - for ( nn = 0; nn < count; nn++ ) - { - FT_Short lsb; - FT_UShort aw; - - - TT_Get_HMetrics( face, start + nn, &lsb, &aw ); - advances[nn] = aw; - } - } - - return FT_Err_Ok; - } - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** S I Z E S ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - static FT_Error - tt_size_select( FT_Size size, - FT_ULong strike_index ) - { - TT_Face ttface = (TT_Face)size->face; - TT_Size ttsize = (TT_Size)size; - FT_Error error = FT_Err_Ok; - - - ttsize->strike_index = strike_index; - - if ( FT_IS_SCALABLE( size->face ) ) - { - /* use the scaled metrics, even when tt_size_reset fails */ - FT_Select_Metrics( size->face, strike_index ); - - tt_size_reset( ttsize ); /* ignore return value */ - } - else - { - SFNT_Service sfnt = (SFNT_Service) ttface->sfnt; - FT_Size_Metrics* metrics = &size->metrics; - - - error = sfnt->load_strike_metrics( ttface, strike_index, metrics ); - if ( error ) - ttsize->strike_index = 0xFFFFFFFFUL; - } - - return error; - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - - static FT_Error - tt_size_request( FT_Size size, - FT_Size_Request req ) - { - TT_Size ttsize = (TT_Size)size; - FT_Error error = FT_Err_Ok; - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - if ( FT_HAS_FIXED_SIZES( size->face ) ) - { - TT_Face ttface = (TT_Face)size->face; - SFNT_Service sfnt = (SFNT_Service) ttface->sfnt; - FT_ULong strike_index; - - - error = sfnt->set_sbit_strike( ttface, req, &strike_index ); - - if ( error ) - ttsize->strike_index = 0xFFFFFFFFUL; - else - return tt_size_select( size, strike_index ); - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - FT_Request_Metrics( size->face, req ); - - if ( FT_IS_SCALABLE( size->face ) ) - { - error = tt_size_reset( ttsize ); - ttsize->root.metrics = ttsize->metrics; - } - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_glyph_load */ - /* */ - /* <Description> */ - /* A driver method used to load a glyph within a given glyph slot. */ - /* */ - /* <Input> */ - /* slot :: A handle to the target slot object where the glyph */ - /* will be loaded. */ - /* */ - /* size :: A handle to the source face size at which the glyph */ - /* must be scaled, loaded, etc. */ - /* */ - /* glyph_index :: The index of the glyph in the font file. */ - /* */ - /* load_flags :: A flag indicating what to load for this glyph. The */ - /* FT_LOAD_XXX constants can be used to control the */ - /* glyph loading process (e.g., whether the outline */ - /* should be scaled, whether to load bitmaps or not, */ - /* whether to hint the outline, etc). */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - static FT_Error - tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ - FT_Size ttsize, /* TT_Size */ - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; - TT_Size size = (TT_Size)ttsize; - FT_Face face = ttslot->face; - FT_Error error; - - - if ( !slot ) - return FT_THROW( Invalid_Slot_Handle ); - - if ( !size ) - return FT_THROW( Invalid_Size_Handle ); - - if ( !face ) - return FT_THROW( Invalid_Face_Handle ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - if ( glyph_index >= (FT_UInt)face->num_glyphs && - !face->internal->incremental_interface ) -#else - if ( glyph_index >= (FT_UInt)face->num_glyphs ) -#endif - return FT_THROW( Invalid_Argument ); - - if ( load_flags & FT_LOAD_NO_HINTING ) - { - /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */ - /* are necessary to disable hinting for tricky fonts */ - - if ( FT_IS_TRICKY( face ) ) - load_flags &= ~FT_LOAD_NO_HINTING; - - if ( load_flags & FT_LOAD_NO_AUTOHINT ) - load_flags |= FT_LOAD_NO_HINTING; - } - - if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) ) - { - load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE; - - if ( !FT_IS_TRICKY( face ) ) - load_flags |= FT_LOAD_NO_HINTING; - } - - /* now load the glyph outline if necessary */ - error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); - - /* force drop-out mode to 2 - irrelevant now */ - /* slot->outline.dropout_mode = 2; */ - - return error; - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** ****/ - /**** D R I V E R I N T E R F A C E ****/ - /**** ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICE_MULTIMASTERSREC( - tt_service_gx_multi_masters, - (FT_Get_MM_Func) NULL, - (FT_Set_MM_Design_Func) NULL, - (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, - (FT_Get_MM_Var_Func) TT_Get_MM_Var, - (FT_Set_Var_Design_Func)TT_Set_Var_Design ) -#endif - - static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine = - { -#ifdef TT_USE_BYTECODE_INTERPRETER - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_TRUETYPE_ENGINE_TYPE_UNPATENTED -#else - FT_TRUETYPE_ENGINE_TYPE_PATENTED -#endif - -#else /* !TT_USE_BYTECODE_INTERPRETER */ - - FT_TRUETYPE_ENGINE_TYPE_NONE - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - }; - - FT_DEFINE_SERVICE_TTGLYFREC( - tt_service_truetype_glyf, - (TT_Glyf_GetLocationFunc)tt_face_get_location ) - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC5( - tt_services, - FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE, - FT_SERVICE_ID_MULTI_MASTERS, &TT_SERVICE_GX_MULTI_MASTERS_GET, - FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, - FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET, - FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET ) -#else - FT_DEFINE_SERVICEDESCREC4( - tt_services, - FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE, - FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, - FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET, - FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET ) -#endif - - - FT_CALLBACK_DEF( FT_Module_Interface ) - tt_get_interface( FT_Module driver, /* TT_Driver */ - const char* tt_interface ) - { - FT_Library library; - FT_Module_Interface result; - FT_Module sfntd; - SFNT_Service sfnt; - - - /* TT_SERVICES_GET dereferences `library' in PIC mode */ -#ifdef FT_CONFIG_OPTION_PIC - if ( !driver ) - return NULL; - library = driver->library; - if ( !library ) - return NULL; -#endif - - result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface ); - if ( result != NULL ) - return result; - -#ifndef FT_CONFIG_OPTION_PIC - if ( !driver ) - return NULL; - library = driver->library; - if ( !library ) - return NULL; -#endif - - /* only return the default interface from the SFNT module */ - sfntd = FT_Get_Module( library, "sfnt" ); - if ( sfntd ) - { - sfnt = (SFNT_Service)( sfntd->clazz->module_interface ); - if ( sfnt ) - return sfnt->get_interface( driver, tt_interface ); - } - - return 0; - } - - - /* The FT_DriverInterface structure is defined in ftdriver.h. */ - -#ifdef TT_USE_BYTECODE_INTERPRETER -#define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER -#else -#define TT_HINTER_FLAG 0 -#endif - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#define TT_SIZE_SELECT tt_size_select -#else -#define TT_SIZE_SELECT 0 -#endif - - FT_DEFINE_DRIVER( - tt_driver_class, - - FT_MODULE_FONT_DRIVER | - FT_MODULE_DRIVER_SCALABLE | - TT_HINTER_FLAG, - - sizeof ( TT_DriverRec ), - - "truetype", /* driver name */ - 0x10000L, /* driver version == 1.0 */ - 0x20000L, /* driver requires FreeType 2.0 or above */ - - (void*)0, /* driver specific interface */ - - tt_driver_init, - tt_driver_done, - tt_get_interface, - - sizeof ( TT_FaceRec ), - sizeof ( TT_SizeRec ), - sizeof ( FT_GlyphSlotRec ), - - tt_face_init, - tt_face_done, - tt_size_init, - tt_size_done, - tt_slot_init, - 0, /* FT_Slot_DoneFunc */ - - tt_glyph_load, - - tt_get_kerning, - 0, /* FT_Face_AttachFunc */ - tt_get_advances, - - tt_size_request, - TT_SIZE_SELECT - ) - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttdriver.h b/third_party/freetype/src/truetype/ttdriver.h deleted file mode 100644 index 6cacd60966e7e695c2c66130f1d0b9eb00f08699..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttdriver.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttdriver.h */ -/* */ -/* High-level TrueType driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTDRIVER_H__ -#define __TTDRIVER_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_DRIVER_H - - -FT_BEGIN_HEADER - - - FT_DECLARE_DRIVER( tt_driver_class ) - - -FT_END_HEADER - -#endif /* __TTDRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/tterrors.h b/third_party/freetype/src/truetype/tterrors.h deleted file mode 100644 index ba32cf744cefac5449c2f374c2a6de355d1331e9..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/tterrors.h +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************/ -/* */ -/* tterrors.h */ -/* */ -/* TrueType error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the TrueType error enumeration */ - /* constants. */ - /* */ - /*************************************************************************/ - -#ifndef __TTERRORS_H__ -#define __TTERRORS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX TT_Err_ -#define FT_ERR_BASE FT_Mod_Err_TrueType - -#include FT_ERRORS_H - -#endif /* __TTERRORS_H__ */ - -/* END */ diff --git a/third_party/freetype/src/truetype/ttgload.c b/third_party/freetype/src/truetype/ttgload.c deleted file mode 100644 index a792ad44a067d736c1ce0afc66b8f3f731166339..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttgload.c +++ /dev/null @@ -1,2563 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttgload.c */ -/* */ -/* TrueType Glyph Loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_TRUETYPE_TAGS_H -#include FT_OUTLINE_H -#include FT_TRUETYPE_DRIVER_H - -#include "ttgload.h" -#include "ttpload.h" - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.h" -#endif - -#include "tterrors.h" -#include "ttsubpix.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttgload - - - /*************************************************************************/ - /* */ - /* Composite glyph flags. */ - /* */ -#define ARGS_ARE_WORDS 0x0001 -#define ARGS_ARE_XY_VALUES 0x0002 -#define ROUND_XY_TO_GRID 0x0004 -#define WE_HAVE_A_SCALE 0x0008 -/* reserved 0x0010 */ -#define MORE_COMPONENTS 0x0020 -#define WE_HAVE_AN_XY_SCALE 0x0040 -#define WE_HAVE_A_2X2 0x0080 -#define WE_HAVE_INSTR 0x0100 -#define USE_MY_METRICS 0x0200 -#define OVERLAP_COMPOUND 0x0400 -#define SCALED_COMPONENT_OFFSET 0x0800 -#define UNSCALED_COMPONENT_OFFSET 0x1000 - - - /*************************************************************************/ - /* */ - /* Return the horizontal metrics in font units for a given glyph. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Get_HMetrics( TT_Face face, - FT_UInt idx, - FT_Short* lsb, - FT_UShort* aw ) - { - ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); - - FT_TRACE5(( " advance width (font units): %d\n", *aw )); - FT_TRACE5(( " left side bearing (font units): %d\n", *lsb )); - } - - - /*************************************************************************/ - /* */ - /* Return the vertical metrics in font units for a given glyph. */ - /* See macro `TT_LOADER_SET_PP' below for explanations. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Get_VMetrics( TT_Face face, - FT_UInt idx, - FT_Pos yMax, - FT_Short* tsb, - FT_UShort* ah ) - { - if ( face->vertical_info ) - ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah ); - - else if ( face->os2.version != 0xFFFFU ) - { - *tsb = (FT_Short)( face->os2.sTypoAscender - yMax ); - *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender - - face->os2.sTypoDescender ); - } - - else - { - *tsb = (FT_Short)( face->horizontal.Ascender - yMax ); - *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender - - face->horizontal.Descender ); - } - - FT_TRACE5(( " advance height (font units): %d\n", *ah )); - FT_TRACE5(( " top side bearing (font units): %d\n", *tsb )); - } - - - static FT_Error - tt_get_metrics( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif - - FT_Error error; - FT_Stream stream = loader->stream; - - FT_Short left_bearing = 0, top_bearing = 0; - FT_UShort advance_width = 0, advance_height = 0; - - /* we must preserve the stream position */ - /* (which gets altered by the metrics functions) */ - FT_ULong pos = FT_STREAM_POS(); - - - TT_Get_HMetrics( face, glyph_index, - &left_bearing, - &advance_width ); - TT_Get_VMetrics( face, glyph_index, - loader->bbox.yMax, - &top_bearing, - &advance_height ); - - if ( FT_STREAM_SEEK( pos ) ) - return error; - - loader->left_bearing = left_bearing; - loader->advance = advance_width; - loader->top_bearing = top_bearing; - loader->vadvance = advance_height; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && - loader->exec ) - { - loader->exec->sph_tweak_flags = 0; - - /* This may not be the right place for this, but it works... */ - /* Note that we have to unconditionally load the tweaks since */ - /* it is possible that glyphs individually switch ClearType's */ - /* backwards compatibility mode on and off. */ - sph_set_tweaks( loader, glyph_index ); - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - if ( !loader->linear_def ) - { - loader->linear_def = 1; - loader->linear = advance_width; - } - - return FT_Err_Ok; - } - - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - static void - tt_get_metrics_incr_overrides( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; - - FT_Short left_bearing = 0, top_bearing = 0; - FT_UShort advance_width = 0, advance_height = 0; - - - /* If this is an incrementally loaded font check whether there are */ - /* overriding metrics for this glyph. */ - if ( face->root.internal->incremental_interface && - face->root.internal->incremental_interface->funcs->get_glyph_metrics ) - { - FT_Incremental_MetricsRec metrics; - FT_Error error; - - - metrics.bearing_x = loader->left_bearing; - metrics.bearing_y = 0; - metrics.advance = loader->advance; - metrics.advance_v = 0; - - error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( - face->root.internal->incremental_interface->object, - glyph_index, FALSE, &metrics ); - if ( error ) - goto Exit; - - left_bearing = (FT_Short)metrics.bearing_x; - advance_width = (FT_UShort)metrics.advance; - -#if 0 - - /* GWW: Do I do the same for vertical metrics? */ - metrics.bearing_x = 0; - metrics.bearing_y = loader->top_bearing; - metrics.advance = loader->vadvance; - - error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( - face->root.internal->incremental_interface->object, - glyph_index, TRUE, &metrics ); - if ( error ) - goto Exit; - - top_bearing = (FT_Short)metrics.bearing_y; - advance_height = (FT_UShort)metrics.advance; - -#endif /* 0 */ - - loader->left_bearing = left_bearing; - loader->advance = advance_width; - loader->top_bearing = top_bearing; - loader->vadvance = advance_height; - - if ( !loader->linear_def ) - { - loader->linear_def = 1; - loader->linear = advance_width; - } - } - - Exit: - return; - } - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - - /*************************************************************************/ - /* */ - /* The following functions are used by default with TrueType fonts. */ - /* However, they can be replaced by alternatives if we need to support */ - /* TrueType-compressed formats (like MicroType) in the future. */ - /* */ - /*************************************************************************/ - - FT_CALLBACK_DEF( FT_Error ) - TT_Access_Glyph_Frame( TT_Loader loader, - FT_UInt glyph_index, - FT_ULong offset, - FT_UInt byte_count ) - { - FT_Error error; - FT_Stream stream = loader->stream; - - /* for non-debug mode */ - FT_UNUSED( glyph_index ); - - - FT_TRACE4(( "Glyph %ld\n", glyph_index )); - - /* the following line sets the `error' variable through macros! */ - if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) - return error; - - loader->cursor = stream->cursor; - loader->limit = stream->limit; - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( void ) - TT_Forget_Glyph_Frame( TT_Loader loader ) - { - FT_Stream stream = loader->stream; - - - FT_FRAME_EXIT(); - } - - - FT_CALLBACK_DEF( FT_Error ) - TT_Load_Glyph_Header( TT_Loader loader ) - { - FT_Byte* p = loader->cursor; - FT_Byte* limit = loader->limit; - - - if ( p + 10 > limit ) - return FT_THROW( Invalid_Outline ); - - loader->n_contours = FT_NEXT_SHORT( p ); - - loader->bbox.xMin = FT_NEXT_SHORT( p ); - loader->bbox.yMin = FT_NEXT_SHORT( p ); - loader->bbox.xMax = FT_NEXT_SHORT( p ); - loader->bbox.yMax = FT_NEXT_SHORT( p ); - - FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); - FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, - loader->bbox.xMax )); - FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, - loader->bbox.yMax )); - loader->cursor = p; - - return FT_Err_Ok; - } - - - FT_CALLBACK_DEF( FT_Error ) - TT_Load_Simple_Glyph( TT_Loader load ) - { - FT_Error error; - FT_Byte* p = load->cursor; - FT_Byte* limit = load->limit; - FT_GlyphLoader gloader = load->gloader; - FT_Int n_contours = load->n_contours; - FT_Outline* outline; - FT_UShort n_ins; - FT_Int n_points; - FT_ULong tmp; - - FT_Byte *flag, *flag_limit; - FT_Byte c, count; - FT_Vector *vec, *vec_limit; - FT_Pos x; - FT_Short *cont, *cont_limit, prev_cont; - FT_Int xy_size = 0; - - - /* check that we can add the contours to the glyph */ - error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours ); - if ( error ) - goto Fail; - - /* reading the contours' endpoints & number of points */ - cont = gloader->current.outline.contours; - cont_limit = cont + n_contours; - - /* check space for contours array + instructions count */ - if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) - goto Invalid_Outline; - - prev_cont = FT_NEXT_SHORT( p ); - - if ( n_contours > 0 ) - cont[0] = prev_cont; - - if ( prev_cont < 0 ) - goto Invalid_Outline; - - for ( cont++; cont < cont_limit; cont++ ) - { - cont[0] = FT_NEXT_SHORT( p ); - if ( cont[0] <= prev_cont ) - { - /* unordered contours: this is invalid */ - goto Invalid_Outline; - } - prev_cont = cont[0]; - } - - n_points = 0; - if ( n_contours > 0 ) - { - n_points = cont[-1] + 1; - if ( n_points < 0 ) - goto Invalid_Outline; - } - - /* note that we will add four phantom points later */ - error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); - if ( error ) - goto Fail; - - /* reading the bytecode instructions */ - load->glyph->control_len = 0; - load->glyph->control_data = NULL; - - if ( p + 2 > limit ) - goto Invalid_Outline; - - n_ins = FT_NEXT_USHORT( p ); - - FT_TRACE5(( " Instructions size: %u\n", n_ins )); - - /* check it */ - if ( ( limit - p ) < n_ins ) - { - FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = FT_THROW( Too_Many_Hints ); - goto Fail; - } - -#ifdef TT_USE_BYTECODE_INTERPRETER - - if ( IS_HINTED( load->load_flags ) ) - { - /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ - /* and thus update the bytecode array size by ourselves */ - - tmp = load->exec->glyphSize; - error = Update_Max( load->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&load->exec->glyphIns, - n_ins ); - - load->exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - - load->glyph->control_len = n_ins; - load->glyph->control_data = load->exec->glyphIns; - - FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); - } - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - p += n_ins; - - outline = &gloader->current.outline; - - /* reading the point tags */ - flag = (FT_Byte*)outline->tags; - flag_limit = flag + n_points; - - FT_ASSERT( flag != NULL ); - - while ( flag < flag_limit ) - { - if ( p + 1 > limit ) - goto Invalid_Outline; - - *flag++ = c = FT_NEXT_BYTE( p ); - if ( c & 8 ) - { - if ( p + 1 > limit ) - goto Invalid_Outline; - - count = FT_NEXT_BYTE( p ); - if ( flag + (FT_Int)count > flag_limit ) - goto Invalid_Outline; - - for ( ; count > 0; count-- ) - *flag++ = c; - } - } - - /* reading the X coordinates */ - - vec = outline->points; - vec_limit = vec + n_points; - flag = (FT_Byte*)outline->tags; - x = 0; - - if ( p + xy_size > limit ) - goto Invalid_Outline; - - for ( ; vec < vec_limit; vec++, flag++ ) - { - FT_Pos y = 0; - FT_Byte f = *flag; - - - if ( f & 2 ) - { - if ( p + 1 > limit ) - goto Invalid_Outline; - - y = (FT_Pos)FT_NEXT_BYTE( p ); - if ( ( f & 16 ) == 0 ) - y = -y; - } - else if ( ( f & 16 ) == 0 ) - { - if ( p + 2 > limit ) - goto Invalid_Outline; - - y = (FT_Pos)FT_NEXT_SHORT( p ); - } - - x += y; - vec->x = x; - /* the cast is for stupid compilers */ - *flag = (FT_Byte)( f & ~( 2 | 16 ) ); - } - - /* reading the Y coordinates */ - - vec = gloader->current.outline.points; - vec_limit = vec + n_points; - flag = (FT_Byte*)outline->tags; - x = 0; - - for ( ; vec < vec_limit; vec++, flag++ ) - { - FT_Pos y = 0; - FT_Byte f = *flag; - - - if ( f & 4 ) - { - if ( p + 1 > limit ) - goto Invalid_Outline; - - y = (FT_Pos)FT_NEXT_BYTE( p ); - if ( ( f & 32 ) == 0 ) - y = -y; - } - else if ( ( f & 32 ) == 0 ) - { - if ( p + 2 > limit ) - goto Invalid_Outline; - - y = (FT_Pos)FT_NEXT_SHORT( p ); - } - - x += y; - vec->y = x; - /* the cast is for stupid compilers */ - *flag = (FT_Byte)( f & FT_CURVE_TAG_ON ); - } - - outline->n_points = (FT_Short)n_points; - outline->n_contours = (FT_Short)n_contours; - - load->cursor = p; - - Fail: - return error; - - Invalid_Outline: - error = FT_THROW( Invalid_Outline ); - goto Fail; - } - - - FT_CALLBACK_DEF( FT_Error ) - TT_Load_Composite_Glyph( TT_Loader loader ) - { - FT_Error error; - FT_Byte* p = loader->cursor; - FT_Byte* limit = loader->limit; - FT_GlyphLoader gloader = loader->gloader; - FT_SubGlyph subglyph; - FT_UInt num_subglyphs; - - - num_subglyphs = 0; - - do - { - FT_Fixed xx, xy, yy, yx; - FT_UInt count; - - - /* check that we can load a new subglyph */ - error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); - if ( error ) - goto Fail; - - /* check space */ - if ( p + 4 > limit ) - goto Invalid_Composite; - - subglyph = gloader->current.subglyphs + num_subglyphs; - - subglyph->arg1 = subglyph->arg2 = 0; - - subglyph->flags = FT_NEXT_USHORT( p ); - subglyph->index = FT_NEXT_USHORT( p ); - - /* check space */ - count = 2; - if ( subglyph->flags & ARGS_ARE_WORDS ) - count += 2; - if ( subglyph->flags & WE_HAVE_A_SCALE ) - count += 2; - else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) - count += 4; - else if ( subglyph->flags & WE_HAVE_A_2X2 ) - count += 8; - - if ( p + count > limit ) - goto Invalid_Composite; - - /* read arguments */ - if ( subglyph->flags & ARGS_ARE_XY_VALUES ) - { - if ( subglyph->flags & ARGS_ARE_WORDS ) - { - subglyph->arg1 = FT_NEXT_SHORT( p ); - subglyph->arg2 = FT_NEXT_SHORT( p ); - } - else - { - subglyph->arg1 = FT_NEXT_CHAR( p ); - subglyph->arg2 = FT_NEXT_CHAR( p ); - } - } - else - { - if ( subglyph->flags & ARGS_ARE_WORDS ) - { - subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p ); - subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p ); - } - else - { - subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p ); - subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p ); - } - } - - /* read transform */ - xx = yy = 0x10000L; - xy = yx = 0; - - if ( subglyph->flags & WE_HAVE_A_SCALE ) - { - xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - yy = xx; - } - else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) - { - xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - } - else if ( subglyph->flags & WE_HAVE_A_2X2 ) - { - xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; - } - - subglyph->transform.xx = xx; - subglyph->transform.xy = xy; - subglyph->transform.yx = yx; - subglyph->transform.yy = yy; - - num_subglyphs++; - - } while ( subglyph->flags & MORE_COMPONENTS ); - - gloader->current.num_subglyphs = num_subglyphs; - -#ifdef TT_USE_BYTECODE_INTERPRETER - - { - FT_Stream stream = loader->stream; - - - /* we must undo the FT_FRAME_ENTER in order to point */ - /* to the composite instructions, if we find some. */ - /* We will process them later. */ - /* */ - loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + - p - limit ); - } - -#endif - - loader->cursor = p; - - Fail: - return error; - - Invalid_Composite: - error = FT_THROW( Invalid_Composite ); - goto Fail; - } - - - FT_LOCAL_DEF( void ) - TT_Init_Glyph_Loading( TT_Face face ) - { - face->access_glyph_frame = TT_Access_Glyph_Frame; - face->read_glyph_header = TT_Load_Glyph_Header; - face->read_simple_glyph = TT_Load_Simple_Glyph; - face->read_composite_glyph = TT_Load_Composite_Glyph; - face->forget_glyph_frame = TT_Forget_Glyph_Frame; - } - - - static void - tt_prepare_zone( TT_GlyphZone zone, - FT_GlyphLoad load, - FT_UInt start_point, - FT_UInt start_contour ) - { - zone->n_points = (FT_UShort)load->outline.n_points - - (FT_UShort)start_point; - zone->n_contours = load->outline.n_contours - - (FT_Short)start_contour; - zone->org = load->extra_points + start_point; - zone->cur = load->outline.points + start_point; - zone->orus = load->extra_points2 + start_point; - zone->tags = (FT_Byte*)load->outline.tags + start_point; - zone->contours = (FT_UShort*)load->outline.contours + start_contour; - zone->first_point = (FT_UShort)start_point; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Hint_Glyph */ - /* */ - /* <Description> */ - /* Hint the glyph using the zone prepared by the caller. Note that */ - /* the zone is supposed to include four phantom points. */ - /* */ - static FT_Error - TT_Hint_Glyph( TT_Loader loader, - FT_Bool is_composite ) - { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Face face = loader->face; - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif - - TT_GlyphZone zone = &loader->zone; - -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_Long n_ins; -#else - FT_UNUSED( is_composite ); -#endif - - -#ifdef TT_USE_BYTECODE_INTERPRETER - if ( loader->glyph->control_len > 0xFFFFL ) - { - FT_TRACE1(( "TT_Hint_Glyph: too long instructions" )); - FT_TRACE1(( " (0x%lx byte) is truncated\n", - loader->glyph->control_len )); - } - n_ins = loader->glyph->control_len; - - /* save original point position in org */ - if ( n_ins > 0 ) - FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); - - /* Reset graphics state. */ - loader->exec->GS = loader->size->GS; - - /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ - /* completely refer to the (already) hinted subglyphs. */ - if ( is_composite ) - { - loader->exec->metrics.x_scale = 1 << 16; - loader->exec->metrics.y_scale = 1 << 16; - - FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); - } - else - { - loader->exec->metrics.x_scale = loader->size->metrics.x_scale; - loader->exec->metrics.y_scale = loader->size->metrics.y_scale; - } -#endif - - /* round phantom points */ - zone->cur[zone->n_points - 4].x = - FT_PIX_ROUND( zone->cur[zone->n_points - 4].x ); - zone->cur[zone->n_points - 3].x = - FT_PIX_ROUND( zone->cur[zone->n_points - 3].x ); - zone->cur[zone->n_points - 2].y = - FT_PIX_ROUND( zone->cur[zone->n_points - 2].y ); - zone->cur[zone->n_points - 1].y = - FT_PIX_ROUND( zone->cur[zone->n_points - 1].y ); - -#ifdef TT_USE_BYTECODE_INTERPRETER - - if ( n_ins > 0 ) - { - FT_Error error; - - FT_GlyphLoader gloader = loader->gloader; - FT_Outline current_outline = gloader->current.outline; - - - TT_Set_CodeRange( loader->exec, tt_coderange_glyph, - loader->exec->glyphIns, n_ins ); - - loader->exec->is_composite = is_composite; - loader->exec->pts = *zone; - - error = TT_Run_Context( loader->exec ); - if ( error && loader->exec->pedantic_hinting ) - return error; - - /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ - current_outline.tags[0] |= - ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; - } - -#endif - - /* save glyph phantom points */ - loader->pp1 = zone->cur[zone->n_points - 4]; - loader->pp2 = zone->cur[zone->n_points - 3]; - loader->pp3 = zone->cur[zone->n_points - 2]; - loader->pp4 = zone->cur[zone->n_points - 1]; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) - FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 ); - - else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) - FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Process_Simple_Glyph */ - /* */ - /* <Description> */ - /* Once a simple glyph has been loaded, it needs to be processed. */ - /* Usually, this means scaling and hinting through bytecode */ - /* interpretation. */ - /* */ - static FT_Error - TT_Process_Simple_Glyph( TT_Loader loader ) - { - FT_GlyphLoader gloader = loader->gloader; - FT_Error error = FT_Err_Ok; - FT_Outline* outline; - FT_Int n_points; - - - outline = &gloader->current.outline; - n_points = outline->n_points; - - /* set phantom points */ - - outline->points[n_points ] = loader->pp1; - outline->points[n_points + 1] = loader->pp2; - outline->points[n_points + 2] = loader->pp3; - outline->points[n_points + 3] = loader->pp4; - - outline->tags[n_points ] = 0; - outline->tags[n_points + 1] = 0; - outline->tags[n_points + 2] = 0; - outline->tags[n_points + 3] = 0; - - n_points += 4; - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - if ( loader->face->doblend ) - { - /* Deltas apply to the unscaled data. */ - error = TT_Vary_Apply_Glyph_Deltas( loader->face, - loader->glyph_index, - outline, - (FT_UInt)n_points ); - if ( error ) - return error; - } - -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - - if ( IS_HINTED( loader->load_flags ) ) - { - tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); - - FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur, - loader->zone.n_points + 4 ); - } - - { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Face face = loader->face; - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); - - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics.x_ppem; - FT_String* style = face->root.style_name; - FT_UInt x_scale_factor = 1000; -#endif - - FT_Vector* vec = outline->points; - FT_Vector* limit = outline->points + n_points; - - FT_Fixed x_scale = 0; /* pacify compiler */ - FT_Fixed y_scale = 0; - - FT_Bool do_scale = FALSE; - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - /* scale, but only if enabled and only if TT hinting is being used */ - if ( IS_HINTED( loader->load_flags ) ) - x_scale_factor = sph_test_tweak_x_scaling( face, - family, - ppem, - style, - loader->glyph_index ); - /* scale the glyph */ - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || - x_scale_factor != 1000 ) - { - x_scale = FT_MulDiv( loader->size->metrics.x_scale, - (FT_Long)x_scale_factor, 1000 ); - y_scale = loader->size->metrics.y_scale; - - /* compensate for any scaling by de/emboldening; */ - /* the amount was determined via experimentation */ - if ( x_scale_factor != 1000 && ppem > 11 ) - FT_Outline_EmboldenXY( outline, - FT_MulFix( 1280 * ppem, - 1000 - x_scale_factor ), - 0 ); - do_scale = TRUE; - } - } - else - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - { - /* scale the glyph */ - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - { - x_scale = loader->size->metrics.x_scale; - y_scale = loader->size->metrics.y_scale; - - do_scale = TRUE; - } - } - - if ( do_scale ) - { - for ( ; vec < limit; vec++ ) - { - vec->x = FT_MulFix( vec->x, x_scale ); - vec->y = FT_MulFix( vec->y, y_scale ); - } - - loader->pp1 = outline->points[n_points - 4]; - loader->pp2 = outline->points[n_points - 3]; - loader->pp3 = outline->points[n_points - 2]; - loader->pp4 = outline->points[n_points - 1]; - } - } - - if ( IS_HINTED( loader->load_flags ) ) - { - loader->zone.n_points += 4; - - error = TT_Hint_Glyph( loader, 0 ); - } - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Process_Composite_Component */ - /* */ - /* <Description> */ - /* Once a composite component has been loaded, it needs to be */ - /* processed. Usually, this means transforming and translating. */ - /* */ - static FT_Error - TT_Process_Composite_Component( TT_Loader loader, - FT_SubGlyph subglyph, - FT_UInt start_point, - FT_UInt num_base_points ) - { - FT_GlyphLoader gloader = loader->gloader; - FT_Outline current; - FT_Bool have_scale; - FT_Pos x, y; - - - current.points = gloader->base.outline.points + - num_base_points; - current.n_points = gloader->base.outline.n_points - - (short)num_base_points; - - have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | - WE_HAVE_AN_XY_SCALE | - WE_HAVE_A_2X2 ) ); - - /* perform the transform required for this subglyph */ - if ( have_scale ) - FT_Outline_Transform( ¤t, &subglyph->transform ); - - /* get offset */ - if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) - { - FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points; - FT_UInt k = (FT_UInt)subglyph->arg1; - FT_UInt l = (FT_UInt)subglyph->arg2; - FT_Vector* p1; - FT_Vector* p2; - - - /* match l-th point of the newly loaded component to the k-th point */ - /* of the previously loaded components. */ - - /* change to the point numbers used by our outline */ - k += start_point; - l += num_base_points; - if ( k >= num_base_points || - l >= num_points ) - return FT_THROW( Invalid_Composite ); - - p1 = gloader->base.outline.points + k; - p2 = gloader->base.outline.points + l; - - x = p1->x - p2->x; - y = p1->y - p2->y; - } - else - { - x = subglyph->arg1; - y = subglyph->arg2; - - if ( !x && !y ) - return FT_Err_Ok; - - /* Use a default value dependent on */ - /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */ - /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */ - - if ( have_scale && -#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED - !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) ) -#else - ( subglyph->flags & SCALED_COMPONENT_OFFSET ) ) -#endif - { - -#if 0 - - /*******************************************************************/ - /* */ - /* This algorithm is what Apple documents. But it doesn't work. */ - /* */ - int a = subglyph->transform.xx > 0 ? subglyph->transform.xx - : -subglyph->transform.xx; - int b = subglyph->transform.yx > 0 ? subglyph->transform.yx - : -subglyph->transform.yx; - int c = subglyph->transform.xy > 0 ? subglyph->transform.xy - : -subglyph->transform.xy; - int d = subglyph->transform.yy > 0 ? subglyph->transform.yy - : -subglyph->transform.yy; - int m = a > b ? a : b; - int n = c > d ? c : d; - - - if ( a - b <= 33 && a - b >= -33 ) - m *= 2; - if ( c - d <= 33 && c - d >= -33 ) - n *= 2; - x = FT_MulFix( x, m ); - y = FT_MulFix( y, n ); - -#else /* 1 */ - - /*******************************************************************/ - /* */ - /* This algorithm is a guess and works much better than the above. */ - /* */ - FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx, - subglyph->transform.xy ); - FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy, - subglyph->transform.yx ); - - - x = FT_MulFix( x, mac_xscale ); - y = FT_MulFix( y, mac_yscale ); - -#endif /* 1 */ - - } - - if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) - { - FT_Fixed x_scale = loader->size->metrics.x_scale; - FT_Fixed y_scale = loader->size->metrics.y_scale; - - - x = FT_MulFix( x, x_scale ); - y = FT_MulFix( y, y_scale ); - - if ( subglyph->flags & ROUND_XY_TO_GRID ) - { - x = FT_PIX_ROUND( x ); - y = FT_PIX_ROUND( y ); - } - } - } - - if ( x || y ) - FT_Outline_Translate( ¤t, x, y ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Process_Composite_Glyph */ - /* */ - /* <Description> */ - /* This is slightly different from TT_Process_Simple_Glyph, in that */ - /* its sole purpose is to hint the glyph. Thus this function is */ - /* only available when bytecode interpreter is enabled. */ - /* */ - static FT_Error - TT_Process_Composite_Glyph( TT_Loader loader, - FT_UInt start_point, - FT_UInt start_contour ) - { - FT_Error error; - FT_Outline* outline; - FT_UInt i; - - - outline = &loader->gloader->base.outline; - - /* make room for phantom points */ - error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, - outline->n_points + 4, - 0 ); - if ( error ) - return error; - - outline->points[outline->n_points ] = loader->pp1; - outline->points[outline->n_points + 1] = loader->pp2; - outline->points[outline->n_points + 2] = loader->pp3; - outline->points[outline->n_points + 3] = loader->pp4; - - outline->tags[outline->n_points ] = 0; - outline->tags[outline->n_points + 1] = 0; - outline->tags[outline->n_points + 2] = 0; - outline->tags[outline->n_points + 3] = 0; - -#ifdef TT_USE_BYTECODE_INTERPRETER - - { - FT_Stream stream = loader->stream; - FT_UShort n_ins, max_ins; - FT_ULong tmp; - - - /* TT_Load_Composite_Glyph only gives us the offset of instructions */ - /* so we read them here */ - if ( FT_STREAM_SEEK( loader->ins_pos ) || - FT_READ_USHORT( n_ins ) ) - return error; - - FT_TRACE5(( " Instructions size = %d\n", n_ins )); - - /* check it */ - max_ins = loader->face->max_profile.maxSizeOfInstructions; - if ( n_ins > max_ins ) - { - /* don't trust `maxSizeOfInstructions'; */ - /* only do a rough safety check */ - if ( (FT_Int)n_ins > loader->byte_len ) - { - FT_TRACE1(( "TT_Process_Composite_Glyph:" - " too many instructions (%d) for glyph with length %d\n", - n_ins, loader->byte_len )); - return FT_THROW( Too_Many_Hints ); - } - - tmp = loader->exec->glyphSize; - error = Update_Max( loader->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&loader->exec->glyphIns, - n_ins ); - - loader->exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - } - else if ( n_ins == 0 ) - return FT_Err_Ok; - - if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) - return error; - - loader->glyph->control_data = loader->exec->glyphIns; - loader->glyph->control_len = n_ins; - } - -#endif - - tt_prepare_zone( &loader->zone, &loader->gloader->base, - start_point, start_contour ); - - /* Some points are likely touched during execution of */ - /* instructions on components. So let's untouch them. */ - for ( i = 0; i < loader->zone.n_points; i++ ) - loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH; - - loader->zone.n_points += 4; - - return TT_Hint_Glyph( loader, 1 ); - } - - - /* - * Calculate the phantom points - * - * Defining the right side bearing (rsb) as - * - * rsb = aw - (lsb + xmax - xmin) - * - * (with `aw' the advance width, `lsb' the left side bearing, and `xmin' - * and `xmax' the glyph's minimum and maximum x value), the OpenType - * specification defines the initial position of horizontal phantom points - * as - * - * pp1 = (round(xmin - lsb), 0) , - * pp2 = (round(pp1 + aw), 0) . - * - * Note that the rounding to the grid (in the device space) is not - * documented currently in the specification. - * - * However, the specification lacks the precise definition of vertical - * phantom points. Greg Hitchcock provided the following explanation. - * - * - a `vmtx' table is present - * - * For any glyph, the minimum and maximum y values (`ymin' and `ymax') - * are given in the `glyf' table, the top side bearing (tsb) and advance - * height (ah) are given in the `vmtx' table. The bottom side bearing - * (bsb) is then calculated as - * - * bsb = ah - (tsb + ymax - ymin) , - * - * and the initial position of vertical phantom points is - * - * pp3 = (x, round(ymax + tsb)) , - * pp4 = (x, round(pp3 - ah)) . - * - * See below for value `x'. - * - * - no `vmtx' table in the font - * - * If there is an `OS/2' table, we set - * - * DefaultAscender = sTypoAscender , - * DefaultDescender = sTypoDescender , - * - * otherwise we use data from the `hhea' table: - * - * DefaultAscender = Ascender , - * DefaultDescender = Descender . - * - * With these two variables we can now set - * - * ah = DefaultAscender - sDefaultDescender , - * tsb = DefaultAscender - yMax , - * - * and proceed as if a `vmtx' table was present. - * - * Usually we have - * - * x = aw / 2 , (1) - * - * but there is one compatibility case where it can be set to - * - * x = -DefaultDescender - - * ((DefaultAscender - DefaultDescender - aw) / 2) . (2) - * - * and another one with - * - * x = 0 . (3) - * - * In Windows, the history of those values is quite complicated, - * depending on the hinting engine (that is, the graphics framework). - * - * framework from to formula - * ---------------------------------------------------------- - * GDI Windows 98 current (1) - * (Windows 2000 for NT) - * GDI+ Windows XP Windows 7 (2) - * GDI+ Windows 8 current (3) - * DWrite Windows 7 current (3) - * - * For simplicity, FreeType uses (1) for grayscale subpixel hinting and - * (3) for everything else. - * - */ -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - -#define TT_LOADER_SET_PP( loader ) \ - do \ - { \ - FT_Bool subpixel_hinting_ = loader->exec \ - ? loader->exec->subpixel_hinting \ - : 0; \ - FT_Bool grayscale_ = loader->exec \ - ? loader->exec->grayscale \ - : 0; \ - FT_Bool use_aw_2_ = (FT_Bool)( subpixel_hinting_ && \ - grayscale_ ); \ - \ - \ - (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \ - (loader)->pp1.y = 0; \ - (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \ - (loader)->pp2.y = 0; \ - \ - (loader)->pp3.x = use_aw_2_ ? (loader)->advance / 2 : 0; \ - (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \ - (loader)->pp4.x = use_aw_2_ ? (loader)->advance / 2 : 0; \ - (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \ - } while ( 0 ) - -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - -#define TT_LOADER_SET_PP( loader ) \ - do \ - { \ - (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \ - (loader)->pp1.y = 0; \ - (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \ - (loader)->pp2.y = 0; \ - \ - (loader)->pp3.x = 0; \ - (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \ - (loader)->pp4.x = 0; \ - (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \ - } while ( 0 ) - -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* load_truetype_glyph */ - /* */ - /* <Description> */ - /* Loads a given truetype glyph. Handles composites and uses a */ - /* TT_Loader object. */ - /* */ - static FT_Error - load_truetype_glyph( TT_Loader loader, - FT_UInt glyph_index, - FT_UInt recurse_count, - FT_Bool header_only ) - { - FT_Error error = FT_Err_Ok; - FT_Fixed x_scale, y_scale; - FT_ULong offset; - TT_Face face = loader->face; - FT_GlyphLoader gloader = loader->gloader; - FT_Bool opened_frame = 0; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - FT_StreamRec inc_stream; - FT_Data glyph_data; - FT_Bool glyph_data_loaded = 0; -#endif - - - /* some fonts have an incorrect value of `maxComponentDepth', */ - /* thus we allow depth 1 to catch the majority of them */ - if ( recurse_count > 1 && - recurse_count > face->max_profile.maxComponentDepth ) - { - error = FT_THROW( Invalid_Composite ); - goto Exit; - } - -#ifndef FT_CONFIG_OPTION_INCREMENTAL - /* check glyph index */ - if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) - { - error = FT_THROW( Invalid_Glyph_Index ); - goto Exit; - } -#endif - - loader->glyph_index = glyph_index; - - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - { - x_scale = loader->size->metrics.x_scale; - y_scale = loader->size->metrics.y_scale; - } - else - { - x_scale = 0x10000L; - y_scale = 0x10000L; - } - - /* Set `offset' to the start of the glyph relative to the start of */ - /* the `glyf' table, and `byte_len' to the length of the glyph in */ - /* bytes. */ - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* If we are loading glyph data via the incremental interface, set */ - /* the loader stream to a memory stream reading the data returned */ - /* by the interface. */ - if ( face->root.internal->incremental_interface ) - { - error = face->root.internal->incremental_interface->funcs->get_glyph_data( - face->root.internal->incremental_interface->object, - glyph_index, &glyph_data ); - if ( error ) - goto Exit; - - glyph_data_loaded = 1; - offset = 0; - loader->byte_len = glyph_data.length; - - FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) ); - FT_Stream_OpenMemory( &inc_stream, - glyph_data.pointer, - (FT_ULong)glyph_data.length ); - - loader->stream = &inc_stream; - } - else - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - offset = tt_face_get_location( face, glyph_index, - (FT_UInt*)&loader->byte_len ); - - if ( loader->byte_len > 0 ) - { -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* for the incremental interface, `glyf_offset' is always zero */ - if ( !loader->glyf_offset && - !face->root.internal->incremental_interface ) -#else - if ( !loader->glyf_offset ) -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - error = face->access_glyph_frame( loader, glyph_index, - loader->glyf_offset + offset, - (FT_UInt)loader->byte_len ); - if ( error ) - goto Exit; - - opened_frame = 1; - - /* read glyph header first */ - error = face->read_glyph_header( loader ); - if ( error ) - goto Exit; - - /* the metrics must be computed after loading the glyph header */ - /* since we need the glyph's `yMax' value in case the vertical */ - /* metrics must be emulated */ - error = tt_get_metrics( loader, glyph_index ); - if ( error ) - goto Exit; - - if ( header_only ) - goto Exit; - } - - if ( loader->byte_len == 0 || loader->n_contours == 0 ) - { - loader->bbox.xMin = 0; - loader->bbox.xMax = 0; - loader->bbox.yMin = 0; - loader->bbox.yMax = 0; - - error = tt_get_metrics( loader, glyph_index ); - if ( error ) - goto Exit; - - if ( header_only ) - goto Exit; - - /* must initialize points before (possibly) overriding */ - /* glyph metrics from the incremental interface */ - TT_LOADER_SET_PP( loader ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - tt_get_metrics_incr_overrides( loader, glyph_index ); -#endif - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - if ( loader->face->doblend ) - { - /* a small outline structure with four elements for */ - /* communication with `TT_Vary_Apply_Glyph_Deltas' */ - FT_Vector points[4]; - char tags[4] = { 1, 1, 1, 1 }; - short contours[4] = { 0, 1, 2, 3 }; - FT_Outline outline; - - - points[0].x = loader->pp1.x; - points[0].y = loader->pp1.y; - points[1].x = loader->pp2.x; - points[1].y = loader->pp2.y; - - points[2].x = loader->pp3.x; - points[2].y = loader->pp3.y; - points[3].x = loader->pp4.x; - points[3].y = loader->pp4.y; - - outline.n_points = 4; - outline.n_contours = 4; - outline.points = points; - outline.tags = tags; - outline.contours = contours; - - /* this must be done before scaling */ - error = TT_Vary_Apply_Glyph_Deltas( loader->face, - glyph_index, - &outline, - (FT_UInt)outline.n_points ); - if ( error ) - goto Exit; - - loader->pp1.x = points[0].x; - loader->pp1.y = points[0].y; - loader->pp2.x = points[1].x; - loader->pp2.y = points[1].y; - - loader->pp3.x = points[2].x; - loader->pp3.y = points[2].y; - loader->pp4.x = points[3].x; - loader->pp4.y = points[3].y; - } - -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - - /* scale phantom points, if necessary; */ - /* they get rounded in `TT_Hint_Glyph' */ - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - { - loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); - loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); - /* pp1.y and pp2.y are always zero */ - - loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale ); - loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); - loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale ); - loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); - } - - error = FT_Err_Ok; - goto Exit; - } - - /* must initialize phantom points before (possibly) overriding */ - /* glyph metrics from the incremental interface */ - TT_LOADER_SET_PP( loader ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - tt_get_metrics_incr_overrides( loader, glyph_index ); -#endif - - /***********************************************************************/ - /***********************************************************************/ - /***********************************************************************/ - - /* if it is a simple glyph, load it */ - - if ( loader->n_contours > 0 ) - { - error = face->read_simple_glyph( loader ); - if ( error ) - goto Exit; - - /* all data have been read */ - face->forget_glyph_frame( loader ); - opened_frame = 0; - - error = TT_Process_Simple_Glyph( loader ); - if ( error ) - goto Exit; - - FT_GlyphLoader_Add( gloader ); - } - - /***********************************************************************/ - /***********************************************************************/ - /***********************************************************************/ - - /* otherwise, load a composite! */ - else if ( loader->n_contours == -1 ) - { - FT_UInt start_point; - FT_UInt start_contour; - FT_ULong ins_pos; /* position of composite instructions, if any */ - - - start_point = (FT_UInt)gloader->base.outline.n_points; - start_contour = (FT_UInt)gloader->base.outline.n_contours; - - /* for each subglyph, read composite header */ - error = face->read_composite_glyph( loader ); - if ( error ) - goto Exit; - - /* store the offset of instructions */ - ins_pos = loader->ins_pos; - - /* all data we need are read */ - face->forget_glyph_frame( loader ); - opened_frame = 0; - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - if ( face->doblend ) - { - short i, limit; - FT_SubGlyph subglyph; - - FT_Outline outline; - FT_Vector* points = NULL; - char* tags = NULL; - short* contours = NULL; - - FT_Memory memory = face->root.memory; - - - limit = (short)gloader->current.num_subglyphs; - - /* construct an outline structure for */ - /* communication with `TT_Vary_Apply_Glyph_Deltas' */ - outline.n_points = (short)( gloader->current.num_subglyphs + 4 ); - outline.n_contours = outline.n_points; - - if ( FT_NEW_ARRAY( points, outline.n_points ) || - FT_NEW_ARRAY( tags, outline.n_points ) || - FT_NEW_ARRAY( contours, outline.n_points ) ) - goto Exit1; - - subglyph = gloader->current.subglyphs; - - for ( i = 0; i < limit; i++, subglyph++ ) - { - /* applying deltas for anchor points doesn't make sense, */ - /* but we don't have to specially check this since */ - /* unused delta values are zero anyways */ - points[i].x = subglyph->arg1; - points[i].y = subglyph->arg2; - tags[i] = 1; - contours[i] = i; - } - - points[i].x = loader->pp1.x; - points[i].y = loader->pp1.y; - tags[i] = 1; - contours[i] = i; - - i++; - points[i].x = loader->pp2.x; - points[i].y = loader->pp2.y; - tags[i] = 1; - contours[i] = i; - - i++; - points[i].x = loader->pp3.x; - points[i].y = loader->pp3.y; - tags[i] = 1; - contours[i] = i; - - i++; - points[i].x = loader->pp4.x; - points[i].y = loader->pp4.y; - tags[i] = 1; - contours[i] = i; - - outline.points = points; - outline.tags = tags; - outline.contours = contours; - - /* this call provides additional offsets */ - /* for each component's translation */ - if ( ( error = TT_Vary_Apply_Glyph_Deltas( - face, - glyph_index, - &outline, - (FT_UInt)outline.n_points ) ) != 0 ) - goto Exit1; - - subglyph = gloader->current.subglyphs; - - for ( i = 0; i < limit; i++, subglyph++ ) - { - /* XXX: overflow check for subglyph->{arg1,arg2}. */ - /* Deltas must be within signed 16-bit, */ - /* but the restriction of summed deltas is not clear */ - subglyph->arg1 = (FT_Int16)points[i].x; - subglyph->arg2 = (FT_Int16)points[i].y; - } - - loader->pp1.x = points[i + 0].x; - loader->pp1.y = points[i + 0].y; - loader->pp2.x = points[i + 1].x; - loader->pp2.y = points[i + 1].y; - - loader->pp3.x = points[i + 2].x; - loader->pp3.y = points[i + 2].y; - loader->pp4.x = points[i + 3].x; - loader->pp4.y = points[i + 3].y; - - Exit1: - FT_FREE( outline.points ); - FT_FREE( outline.tags ); - FT_FREE( outline.contours ); - - if ( error ) - goto Exit; - } - -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - - /* scale phantom points, if necessary; */ - /* they get rounded in `TT_Hint_Glyph' */ - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - { - loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); - loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); - /* pp1.y and pp2.y are always zero */ - - loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale ); - loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); - loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale ); - loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); - } - - /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ - /* `as is' in the glyph slot (the client application will be */ - /* responsible for interpreting these data)... */ - if ( loader->load_flags & FT_LOAD_NO_RECURSE ) - { - FT_GlyphLoader_Add( gloader ); - loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; - - goto Exit; - } - - /*********************************************************************/ - /*********************************************************************/ - /*********************************************************************/ - - { - FT_UInt n, num_base_points; - FT_SubGlyph subglyph = NULL; - - FT_UInt num_points = start_point; - FT_UInt num_subglyphs = gloader->current.num_subglyphs; - FT_UInt num_base_subgs = gloader->base.num_subglyphs; - - FT_Stream old_stream = loader->stream; - FT_Int old_byte_len = loader->byte_len; - - - FT_GlyphLoader_Add( gloader ); - - /* read each subglyph independently */ - for ( n = 0; n < num_subglyphs; n++ ) - { - FT_Vector pp[4]; - - - /* Each time we call load_truetype_glyph in this loop, the */ - /* value of `gloader.base.subglyphs' can change due to table */ - /* reallocations. We thus need to recompute the subglyph */ - /* pointer on each iteration. */ - subglyph = gloader->base.subglyphs + num_base_subgs + n; - - pp[0] = loader->pp1; - pp[1] = loader->pp2; - pp[2] = loader->pp3; - pp[3] = loader->pp4; - - num_base_points = (FT_UInt)gloader->base.outline.n_points; - - error = load_truetype_glyph( loader, - (FT_UInt)subglyph->index, - recurse_count + 1, - FALSE ); - if ( error ) - goto Exit; - - /* restore subglyph pointer */ - subglyph = gloader->base.subglyphs + num_base_subgs + n; - - /* restore phantom points if necessary */ - if ( !( subglyph->flags & USE_MY_METRICS ) ) - { - loader->pp1 = pp[0]; - loader->pp2 = pp[1]; - loader->pp3 = pp[2]; - loader->pp4 = pp[3]; - } - - num_points = (FT_UInt)gloader->base.outline.n_points; - - if ( num_points == num_base_points ) - continue; - - /* gloader->base.outline consists of three parts: */ - /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ - /* */ - /* (1): exists from the beginning */ - /* (2): components that have been loaded so far */ - /* (3): the newly loaded component */ - error = TT_Process_Composite_Component( loader, - subglyph, - start_point, - num_base_points ); - if ( error ) - goto Exit; - } - - loader->stream = old_stream; - loader->byte_len = old_byte_len; - - /* process the glyph */ - loader->ins_pos = ins_pos; - if ( IS_HINTED( loader->load_flags ) && -#ifdef TT_USE_BYTECODE_INTERPRETER - subglyph->flags & WE_HAVE_INSTR && -#endif - num_points > start_point ) - { - error = TT_Process_Composite_Glyph( loader, - start_point, - start_contour ); - if ( error ) - goto Exit; - } - } - } - else - { - /* invalid composite count (negative but not -1) */ - error = FT_THROW( Invalid_Outline ); - goto Exit; - } - - /***********************************************************************/ - /***********************************************************************/ - /***********************************************************************/ - - Exit: - - if ( opened_frame ) - face->forget_glyph_frame( loader ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - if ( glyph_data_loaded ) - face->root.internal->incremental_interface->funcs->free_glyph_data( - face->root.internal->incremental_interface->object, - &glyph_data ); - -#endif - - return error; - } - - - static FT_Error - compute_glyph_metrics( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif - - FT_BBox bbox; - FT_Fixed y_scale; - TT_GlyphSlot glyph = loader->glyph; - TT_Size size = loader->size; - - - y_scale = 0x10000L; - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - y_scale = size->root.metrics.y_scale; - - if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) - FT_Outline_Get_CBox( &glyph->outline, &bbox ); - else - bbox = loader->bbox; - - /* get the device-independent horizontal advance; it is scaled later */ - /* by the base layer. */ - glyph->linearHoriAdvance = loader->linear; - - glyph->metrics.horiBearingX = bbox.xMin; - glyph->metrics.horiBearingY = bbox.yMax; - glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; - - /* adjust advance width to the value contained in the hdmx table */ - /* unless FT_LOAD_COMPUTE_METRICS is set */ - if ( !face->postscript.isFixedPitch && - IS_HINTED( loader->load_flags ) && - !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) - { - FT_Byte* widthp; - - - widthp = tt_face_get_device_metrics( face, - size->root.metrics.x_ppem, - glyph_index ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - FT_Bool ignore_x_mode; - - - ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) != - FT_RENDER_MODE_MONO ); - - if ( widthp && - ( ( ignore_x_mode && loader->exec->compatible_widths ) || - !ignore_x_mode || - SPH_OPTION_BITMAP_WIDTHS ) ) - glyph->metrics.horiAdvance = *widthp * 64; - } - else - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - { - if ( widthp ) - glyph->metrics.horiAdvance = *widthp * 64; - } - } - - /* set glyph dimensions */ - glyph->metrics.width = bbox.xMax - bbox.xMin; - glyph->metrics.height = bbox.yMax - bbox.yMin; - - /* Now take care of vertical metrics. In the case where there is */ - /* no vertical information within the font (relatively common), */ - /* create some metrics manually */ - { - FT_Pos top; /* scaled vertical top side bearing */ - FT_Pos advance; /* scaled vertical advance height */ - - - /* Get the unscaled top bearing and advance height. */ - if ( face->vertical_info && - face->vertical.number_Of_VMetrics > 0 ) - { - top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax, - y_scale ); - - if ( loader->pp3.y <= loader->pp4.y ) - advance = 0; - else - advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y, - y_scale ); - } - else - { - FT_Pos height; - - - /* XXX Compute top side bearing and advance height in */ - /* Get_VMetrics instead of here. */ - - /* NOTE: The OS/2 values are the only `portable' ones, */ - /* which is why we use them, if there is an OS/2 */ - /* table in the font. Otherwise, we use the */ - /* values defined in the horizontal header. */ - - height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin, - y_scale ); - if ( face->os2.version != 0xFFFFU ) - advance = (FT_Pos)( face->os2.sTypoAscender - - face->os2.sTypoDescender ); - else - advance = (FT_Pos)( face->horizontal.Ascender - - face->horizontal.Descender ); - - top = ( advance - height ) / 2; - } - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - { - FT_Incremental_InterfaceRec* incr; - FT_Incremental_MetricsRec metrics; - FT_Error error; - - - incr = face->root.internal->incremental_interface; - - /* If this is an incrementally loaded font see if there are */ - /* overriding metrics for this glyph. */ - if ( incr && incr->funcs->get_glyph_metrics ) - { - metrics.bearing_x = 0; - metrics.bearing_y = top; - metrics.advance = advance; - - error = incr->funcs->get_glyph_metrics( incr->object, - glyph_index, - TRUE, - &metrics ); - if ( error ) - return error; - - top = metrics.bearing_y; - advance = metrics.advance; - } - } - - /* GWW: Do vertical metrics get loaded incrementally too? */ - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - glyph->linearVertAdvance = advance; - - /* scale the metrics */ - if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) - { - top = FT_MulFix( top, y_scale ); - advance = FT_MulFix( advance, y_scale ); - } - - /* XXX: for now, we have no better algorithm for the lsb, but it */ - /* should work fine. */ - /* */ - glyph->metrics.vertBearingX = glyph->metrics.horiBearingX - - glyph->metrics.horiAdvance / 2; - glyph->metrics.vertBearingY = top; - glyph->metrics.vertAdvance = advance; - } - - return 0; - } - - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - static FT_Error - load_sbit_image( TT_Size size, - TT_GlyphSlot glyph, - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - TT_Face face; - SFNT_Service sfnt; - FT_Stream stream; - FT_Error error; - TT_SBit_MetricsRec metrics; - - - face = (TT_Face)glyph->face; - sfnt = (SFNT_Service)face->sfnt; - stream = face->root.stream; - - error = sfnt->load_sbit_image( face, - size->strike_index, - glyph_index, - (FT_UInt)load_flags, - stream, - &glyph->bitmap, - &metrics ); - if ( !error ) - { - glyph->outline.n_points = 0; - glyph->outline.n_contours = 0; - - glyph->metrics.width = (FT_Pos)metrics.width * 64; - glyph->metrics.height = (FT_Pos)metrics.height * 64; - - glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64; - glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64; - glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64; - - glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64; - glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64; - glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64; - - glyph->format = FT_GLYPH_FORMAT_BITMAP; - - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - glyph->bitmap_left = metrics.vertBearingX; - glyph->bitmap_top = metrics.vertBearingY; - } - else - { - glyph->bitmap_left = metrics.horiBearingX; - glyph->bitmap_top = metrics.horiBearingY; - } - } - - return error; - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - - static FT_Error - tt_loader_init( TT_Loader loader, - TT_Size size, - TT_GlyphSlot glyph, - FT_Int32 load_flags, - FT_Bool glyf_table_only ) - { - FT_Error error; - - TT_Face face; - FT_Stream stream; -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); -#endif - - - face = (TT_Face)glyph->face; - stream = face->root.stream; - - FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) ); - -#ifdef TT_USE_BYTECODE_INTERPRETER - - /* load execution context */ - if ( IS_HINTED( load_flags ) && !glyf_table_only ) - { - TT_ExecContext exec; - FT_Bool grayscale; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); - - FT_Bool subpixel_hinting = FALSE; - -#if 0 - /* not used yet */ - FT_Bool compatible_widths; - FT_Bool symmetrical_smoothing; - FT_Bool bgr; - FT_Bool vertical_lcd; - FT_Bool subpixel_positioned; - FT_Bool gray_cleartype; -#endif -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - FT_Bool reexecute = FALSE; - - - if ( size->bytecode_ready < 0 || size->cvt_ready < 0 ) - { - error = tt_size_ready_bytecode( size, pedantic ); - if ( error ) - return error; - } - else if ( size->bytecode_ready ) - return size->bytecode_ready; - else if ( size->cvt_ready ) - return size->cvt_ready; - - /* query new execution context */ - exec = size->context; - if ( !exec ) - return FT_THROW( Could_Not_Find_Context ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ) && - SPH_OPTION_SET_SUBPIXEL ); - - if ( subpixel_hinting ) - grayscale = FALSE; - else if ( SPH_OPTION_SET_GRAYSCALE ) - { - grayscale = TRUE; - subpixel_hinting = FALSE; - } - else - grayscale = FALSE; - - if ( FT_IS_TRICKY( glyph->face ) ) - subpixel_hinting = FALSE; - - exec->ignore_x_mode = subpixel_hinting || grayscale; - exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - -#if 1 - exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; - exec->symmetrical_smoothing = TRUE; - exec->bgr = FALSE; - exec->vertical_lcd = FALSE; - exec->subpixel_positioned = TRUE; - exec->gray_cleartype = FALSE; -#else /* 0 */ - exec->compatible_widths = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_COMPATIBLE_WIDTHS ); - exec->symmetrical_smoothing = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SYMMETRICAL_SMOOTHING ); - exec->bgr = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_BGR ); - exec->vertical_lcd = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_VERTICAL_LCD ); - exec->subpixel_positioned = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SUBPIXEL_POSITIONED ); - exec->gray_cleartype = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_GRAY_CLEARTYPE ); -#endif /* 0 */ - - } - else - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - { - grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); - } - - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - /* a change from mono to subpixel rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( subpixel_hinting != exec->subpixel_hinting ) - { - FT_TRACE4(( "tt_loader_init: subpixel hinting change," - " re-executing `prep' table\n" )); - - exec->subpixel_hinting = subpixel_hinting; - reexecute = TRUE; - } - - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale ) - { - FT_TRACE4(( "tt_loader_init: grayscale hinting change," - " re-executing `prep' table\n" )); - - exec->grayscale = grayscale; - reexecute = TRUE; - } - } - else - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - { - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale ) - { - FT_TRACE4(( "tt_loader_init: grayscale hinting change," - " re-executing `prep' table\n" )); - - exec->grayscale = grayscale; - reexecute = TRUE; - } - } - - if ( reexecute ) - { - FT_UInt i; - - - for ( i = 0; i < size->cvt_size; i++ ) - size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); - error = tt_size_run_prep( size, pedantic ); - if ( error ) - return error; - } - - /* check whether the cvt program has disabled hinting */ - if ( exec->GS.instruct_control & 1 ) - load_flags |= FT_LOAD_NO_HINTING; - - /* load default graphics state -- if needed */ - if ( exec->GS.instruct_control & 2 ) - exec->GS = tt_default_graphics_state; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* check whether we have a font hinted for ClearType -- */ - /* note that this flag can also be modified in a glyph's bytecode */ - if ( exec->GS.instruct_control & 4 ) - exec->ignore_x_mode = 0; -#endif - - exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); - loader->exec = exec; - loader->instructions = exec->glyphIns; - } - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - /* seek to the beginning of the glyph table -- for Type 42 fonts */ - /* the table might be accessed from a Postscript stream or something */ - /* else... */ - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - if ( face->root.internal->incremental_interface ) - loader->glyf_offset = 0; - else - -#endif - - { - error = face->goto_table( face, TTAG_glyf, stream, 0 ); - - if ( FT_ERR_EQ( error, Table_Missing ) ) - loader->glyf_offset = 0; - else if ( error ) - { - FT_ERROR(( "tt_loader_init: could not access glyph table\n" )); - return error; - } - else - loader->glyf_offset = FT_STREAM_POS(); - } - - /* get face's glyph loader */ - if ( !glyf_table_only ) - { - FT_GlyphLoader gloader = glyph->internal->loader; - - - FT_GlyphLoader_Rewind( gloader ); - loader->gloader = gloader; - } - - loader->load_flags = (FT_ULong)load_flags; - - loader->face = face; - loader->size = size; - loader->glyph = (FT_GlyphSlot)glyph; - loader->stream = stream; - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Load_Glyph */ - /* */ - /* <Description> */ - /* A function used to load a single glyph within a given glyph slot, */ - /* for a given size. */ - /* */ - /* <Input> */ - /* glyph :: A handle to a target slot object where the glyph */ - /* will be loaded. */ - /* */ - /* size :: A handle to the source face size at which the glyph */ - /* must be scaled/loaded. */ - /* */ - /* glyph_index :: The index of the glyph in the font file. */ - /* */ - /* load_flags :: A flag indicating what to load for this glyph. The */ - /* FT_LOAD_XXX constants can be used to control the */ - /* glyph loading process (e.g., whether the outline */ - /* should be scaled, whether to load bitmaps or not, */ - /* whether to hint the outline, etc). */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Load_Glyph( TT_Size size, - TT_GlyphSlot glyph, - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - FT_Error error; - TT_LoaderRec loader; - - - FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index )); - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - - /* try to load embedded bitmap if any */ - /* */ - /* XXX: The convention should be emphasized in */ - /* the documents because it can be confusing. */ - if ( size->strike_index != 0xFFFFFFFFUL && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) - { - error = load_sbit_image( size, glyph, glyph_index, load_flags ); - if ( !error ) - { - if ( FT_IS_SCALABLE( glyph->face ) ) - { - /* for the bbox we need the header only */ - (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); - (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); - glyph->linearHoriAdvance = loader.linear; - glyph->linearVertAdvance = loader.vadvance; - - /* sanity checks: if `xxxAdvance' in the sbit metric */ - /* structure isn't set, use `linearXXXAdvance' */ - if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) - glyph->metrics.horiAdvance = - FT_MulFix( glyph->linearHoriAdvance, - size->root.metrics.x_scale ); - if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance ) - glyph->metrics.vertAdvance = - FT_MulFix( glyph->linearVertAdvance, - size->root.metrics.y_scale ); - } - - return FT_Err_Ok; - } - } - -#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - - /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ - if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) - return FT_THROW( Invalid_Size_Handle ); - - if ( load_flags & FT_LOAD_SBITS_ONLY ) - return FT_THROW( Invalid_Argument ); - - error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); - if ( error ) - return error; - - glyph->format = FT_GLYPH_FORMAT_OUTLINE; - glyph->num_subglyphs = 0; - glyph->outline.flags = 0; - - /* main loading loop */ - error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); - if ( !error ) - { - if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) - { - glyph->num_subglyphs = loader.gloader->base.num_subglyphs; - glyph->subglyphs = loader.gloader->base.subglyphs; - } - else - { - glyph->outline = loader.gloader->base.outline; - glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; - - /* Translate array so that (0,0) is the glyph's origin. Note */ - /* that this behaviour is independent on the value of bit 1 of */ - /* the `flags' field in the `head' table -- at least major */ - /* applications like Acroread indicate that. */ - if ( loader.pp1.x ) - FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); - } - -#ifdef TT_USE_BYTECODE_INTERPRETER - - if ( IS_HINTED( load_flags ) ) - { - if ( loader.exec->GS.scan_control ) - { - /* convert scan conversion mode to FT_OUTLINE_XXX flags */ - switch ( loader.exec->GS.scan_type ) - { - case 0: /* simple drop-outs including stubs */ - glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS; - break; - case 1: /* simple drop-outs excluding stubs */ - /* nothing; it's the default rendering mode */ - break; - case 4: /* smart drop-outs including stubs */ - glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS | - FT_OUTLINE_INCLUDE_STUBS; - break; - case 5: /* smart drop-outs excluding stubs */ - glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS; - break; - - default: /* no drop-out control */ - glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; - break; - } - } - else - glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; - } - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - error = compute_glyph_metrics( &loader, glyph_index ); - } - - /* Set the `high precision' bit flag. */ - /* This is _critical_ to get correct output for monochrome */ - /* TrueType glyphs at all sizes using the bytecode interpreter. */ - /* */ - if ( !( load_flags & FT_LOAD_NO_SCALE ) && - size->root.metrics.y_ppem < 24 ) - glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttgload.h b/third_party/freetype/src/truetype/ttgload.h deleted file mode 100644 index 8e3255e106d303526b3fb516d4c363926a5593d2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttgload.h +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttgload.h */ -/* */ -/* TrueType Glyph Loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTGLOAD_H__ -#define __TTGLOAD_H__ - - -#include <ft2build.h> -#include "ttobjs.h" - -#ifdef TT_USE_BYTECODE_INTERPRETER -#include "ttinterp.h" -#endif - - -FT_BEGIN_HEADER - - - FT_LOCAL( void ) - TT_Init_Glyph_Loading( TT_Face face ); - - FT_LOCAL( void ) - TT_Get_HMetrics( TT_Face face, - FT_UInt idx, - FT_Short* lsb, - FT_UShort* aw ); - - FT_LOCAL( void ) - TT_Get_VMetrics( TT_Face face, - FT_UInt idx, - FT_Pos yMax, - FT_Short* tsb, - FT_UShort* ah ); - - FT_LOCAL( FT_Error ) - TT_Load_Glyph( TT_Size size, - TT_GlyphSlot glyph, - FT_UInt glyph_index, - FT_Int32 load_flags ); - - -FT_END_HEADER - -#endif /* __TTGLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttgxvar.c b/third_party/freetype/src/truetype/ttgxvar.c deleted file mode 100644 index dd9e250c9419b0127789f4bbc8cd220b86518967..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttgxvar.c +++ /dev/null @@ -1,2074 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttgxvar.c */ -/* */ -/* TrueType GX Font Variation loader */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */ - /* */ - /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */ - /* */ - /* The documentation for `fvar' is inconsistent. At one point it says */ - /* that `countSizePairs' should be 3, at another point 2. It should */ - /* be 2. */ - /* */ - /* The documentation for `gvar' is not intelligible; `cvar' refers you */ - /* to `gvar' and is thus also incomprehensible. */ - /* */ - /* The documentation for `avar' appears correct, but Apple has no fonts */ - /* with an `avar' table, so it is hard to test. */ - /* */ - /* Many thanks to John Jenkins (at Apple) in figuring this out. */ - /* */ - /* */ - /* Apple's `kern' table has some references to tuple indices, but as */ - /* there is no indication where these indices are defined, nor how to */ - /* interpolate the kerning values (different tuples have different */ - /* classes) this issue is ignored. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_TRUETYPE_TAGS_H -#include FT_MULTIPLE_MASTERS_H - -#include "ttpload.h" -#include "ttgxvar.h" - -#include "tterrors.h" - - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - -#define FT_Stream_FTell( stream ) \ - (FT_ULong)( (stream)->cursor - (stream)->base ) -#define FT_Stream_SeekSet( stream, off ) \ - ( (stream)->cursor = (stream)->base + (off) ) - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttgxvar - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** Internal Routines *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */ - /* indicates that there is a delta for every point without needing to */ - /* enumerate all of them. */ - /* */ - - /* ensure that value `0' has the same width as a pointer */ -#define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0 - - -#define GX_PT_POINTS_ARE_WORDS 0x80U -#define GX_PT_POINT_RUN_COUNT_MASK 0x7FU - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_readpackedpoints */ - /* */ - /* <Description> */ - /* Read a set of points to which the following deltas will apply. */ - /* Points are packed with a run length encoding. */ - /* */ - /* <Input> */ - /* stream :: The data stream. */ - /* */ - /* <Output> */ - /* point_cnt :: The number of points read. A zero value means that */ - /* all points in the glyph will be affected, without */ - /* enumerating them individually. */ - /* */ - /* <Return> */ - /* An array of FT_UShort containing the affected points or the */ - /* special value ALL_POINTS. */ - /* */ - static FT_UShort* - ft_var_readpackedpoints( FT_Stream stream, - FT_UInt *point_cnt ) - { - FT_UShort *points = NULL; - FT_UInt n; - FT_UInt runcnt; - FT_UInt i, j; - FT_UShort first; - FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); - - - *point_cnt = 0; - - n = FT_GET_BYTE(); - if ( n == 0 ) - return ALL_POINTS; - - if ( n & GX_PT_POINTS_ARE_WORDS ) - { - n &= GX_PT_POINT_RUN_COUNT_MASK; - n <<= 8; - n |= FT_GET_BYTE(); - } - - if ( FT_NEW_ARRAY( points, n ) ) - return NULL; - - *point_cnt = n; - - i = 0; - while ( i < n ) - { - runcnt = FT_GET_BYTE(); - if ( runcnt & GX_PT_POINTS_ARE_WORDS ) - { - runcnt &= GX_PT_POINT_RUN_COUNT_MASK; - first = FT_GET_USHORT(); - points[i++] = first; - - if ( runcnt < 1 || i + runcnt > n ) - goto Exit; - - /* first point not included in run count */ - for ( j = 0; j < runcnt; j++ ) - { - first += FT_GET_USHORT(); - points[i++] = first; - } - } - else - { - first = FT_GET_BYTE(); - points[i++] = first; - - if ( runcnt < 1 || i + runcnt > n ) - goto Exit; - - for ( j = 0; j < runcnt; j++ ) - { - first += FT_GET_BYTE(); - points[i++] = first; - } - } - } - - Exit: - return points; - } - - -#define GX_DT_DELTAS_ARE_ZERO 0x80U -#define GX_DT_DELTAS_ARE_WORDS 0x40U -#define GX_DT_DELTA_RUN_COUNT_MASK 0x3FU - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_readpackeddeltas */ - /* */ - /* <Description> */ - /* Read a set of deltas. These are packed slightly differently than */ - /* points. In particular there is no overall count. */ - /* */ - /* <Input> */ - /* stream :: The data stream. */ - /* */ - /* delta_cnt :: The number of deltas to be read. */ - /* */ - /* <Return> */ - /* An array of FT_Short containing the deltas for the affected */ - /* points. (This only gets the deltas for one dimension. It will */ - /* generally be called twice, once for x, once for y. When used in */ - /* cvt table, it will only be called once.) */ - /* */ - static FT_Short* - ft_var_readpackeddeltas( FT_Stream stream, - FT_UInt delta_cnt ) - { - FT_Short *deltas = NULL; - FT_UInt runcnt, cnt; - FT_UInt i, j; - FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); - - - if ( FT_NEW_ARRAY( deltas, delta_cnt ) ) - return NULL; - - i = 0; - while ( i < delta_cnt ) - { - runcnt = FT_GET_BYTE(); - cnt = runcnt & GX_DT_DELTA_RUN_COUNT_MASK; - - if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) - { - /* `runcnt' zeroes get added */ - for ( j = 0; j <= cnt && i < delta_cnt; j++ ) - deltas[i++] = 0; - } - else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) - { - /* `runcnt' shorts from the stack */ - for ( j = 0; j <= cnt && i < delta_cnt; j++ ) - deltas[i++] = FT_GET_SHORT(); - } - else - { - /* `runcnt' signed bytes from the stack */ - for ( j = 0; j <= cnt && i < delta_cnt; j++ ) - deltas[i++] = FT_GET_CHAR(); - } - - if ( j <= cnt ) - { - /* bad format */ - FT_FREE( deltas ); - return NULL; - } - } - - return deltas; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_load_avar */ - /* */ - /* <Description> */ - /* Parse the `avar' table if present. It need not be, so we return */ - /* nothing. */ - /* */ - /* <InOut> */ - /* face :: The font face. */ - /* */ - static void - ft_var_load_avar( TT_Face face ) - { - FT_Stream stream = FT_FACE_STREAM( face ); - FT_Memory memory = stream->memory; - GX_Blend blend = face->blend; - GX_AVarSegment segment; - FT_Error error = FT_Err_Ok; - FT_Long version; - FT_Long axisCount; - FT_Int i, j; - FT_ULong table_len; - - FT_UNUSED( error ); - - - FT_TRACE2(( "AVAR " )); - - blend->avar_checked = TRUE; - error = face->goto_table( face, TTAG_avar, stream, &table_len ); - if ( error ) - { - FT_TRACE2(( "is missing\n" )); - return; - } - - if ( FT_FRAME_ENTER( table_len ) ) - return; - - version = FT_GET_LONG(); - axisCount = FT_GET_LONG(); - - if ( version != 0x00010000L ) - { - FT_TRACE2(( "bad table version\n" )); - goto Exit; - } - - FT_TRACE2(( "loaded\n" )); - - if ( axisCount != (FT_Long)blend->mmvar->num_axis ) - { - FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n" - " table are different\n" )); - goto Exit; - } - - if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) ) - goto Exit; - - segment = &blend->avar_segment[0]; - for ( i = 0; i < axisCount; i++, segment++ ) - { - FT_TRACE5(( " axis %d:\n", i )); - - segment->pairCount = FT_GET_USHORT(); - if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) ) - { - /* Failure. Free everything we have done so far. We must do */ - /* it right now since loading the `avar' table is optional. */ - - for ( j = i - 1; j >= 0; j-- ) - FT_FREE( blend->avar_segment[j].correspondence ); - - FT_FREE( blend->avar_segment ); - blend->avar_segment = NULL; - goto Exit; - } - - for ( j = 0; j < segment->pairCount; j++ ) - { - /* convert to Fixed */ - segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4; - segment->correspondence[j].toCoord = FT_GET_SHORT() * 4; - - FT_TRACE5(( " mapping %.4f to %.4f\n", - segment->correspondence[j].fromCoord / 65536.0, - segment->correspondence[j].toCoord / 65536.0 )); - } - - FT_TRACE5(( "\n" )); - } - - Exit: - FT_FRAME_EXIT(); - } - - - typedef struct GX_GVar_Head_ - { - FT_Long version; - FT_UShort axisCount; - FT_UShort globalCoordCount; - FT_ULong offsetToCoord; - FT_UShort glyphCount; - FT_UShort flags; - FT_ULong offsetToData; - - } GX_GVar_Head; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_load_gvar */ - /* */ - /* <Description> */ - /* Parse the `gvar' table if present. If `fvar' is there, `gvar' had */ - /* better be there too. */ - /* */ - /* <InOut> */ - /* face :: The font face. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - static FT_Error - ft_var_load_gvar( TT_Face face ) - { - FT_Stream stream = FT_FACE_STREAM( face ); - FT_Memory memory = stream->memory; - GX_Blend blend = face->blend; - FT_Error error; - FT_UInt i, j; - FT_ULong table_len; - FT_ULong gvar_start; - FT_ULong offsetToData; - GX_GVar_Head gvar_head; - - static const FT_Frame_Field gvar_fields[] = - { - -#undef FT_STRUCTURE -#define FT_STRUCTURE GX_GVar_Head - - FT_FRAME_START( 20 ), - FT_FRAME_LONG ( version ), - FT_FRAME_USHORT( axisCount ), - FT_FRAME_USHORT( globalCoordCount ), - FT_FRAME_ULONG ( offsetToCoord ), - FT_FRAME_USHORT( glyphCount ), - FT_FRAME_USHORT( flags ), - FT_FRAME_ULONG ( offsetToData ), - FT_FRAME_END - }; - - - FT_TRACE2(( "GVAR " )); - - if ( ( error = face->goto_table( face, - TTAG_gvar, - stream, - &table_len ) ) != 0 ) - { - FT_TRACE2(( "is missing\n" )); - goto Exit; - } - - gvar_start = FT_STREAM_POS( ); - if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) ) - goto Exit; - - blend->tuplecount = gvar_head.globalCoordCount; - blend->gv_glyphcnt = gvar_head.glyphCount; - offsetToData = gvar_start + gvar_head.offsetToData; - - if ( gvar_head.version != 0x00010000L ) - { - FT_TRACE1(( "bad table version\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - FT_TRACE2(( "loaded\n" )); - - if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis ) - { - FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n" - " table are different\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - FT_TRACE5(( "gvar: there are %d shared coordinates:\n", - blend->tuplecount )); - - if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) ) - goto Exit; - - if ( gvar_head.flags & 1 ) - { - /* long offsets (one more offset than glyphs, to mark size of last) */ - if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) ) - goto Exit; - - for ( i = 0; i <= blend->gv_glyphcnt; i++ ) - blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG(); - - FT_FRAME_EXIT(); - } - else - { - /* short offsets (one more offset than glyphs, to mark size of last) */ - if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) ) - goto Exit; - - for ( i = 0; i <= blend->gv_glyphcnt; i++ ) - blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2; - /* XXX: Undocumented: `*2'! */ - - FT_FRAME_EXIT(); - } - - if ( blend->tuplecount != 0 ) - { - if ( FT_NEW_ARRAY( blend->tuplecoords, - gvar_head.axisCount * blend->tuplecount ) ) - goto Exit; - - if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) || - FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) ) - goto Exit; - - for ( i = 0; i < blend->tuplecount; i++ ) - { - FT_TRACE5(( " [ " )); - for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ ) - { - blend->tuplecoords[i * gvar_head.axisCount + j] = - FT_GET_SHORT() * 4; /* convert to FT_Fixed */ - FT_TRACE5(( "%.4f ", - blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 )); - } - FT_TRACE5(( "]\n" )); - } - - FT_TRACE5(( "\n" )); - - FT_FRAME_EXIT(); - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_apply_tuple */ - /* */ - /* <Description> */ - /* Figure out whether a given tuple (design) applies to the current */ - /* blend, and if so, what is the scaling factor. */ - /* */ - /* <Input> */ - /* blend :: The current blend of the font. */ - /* */ - /* tupleIndex :: A flag saying whether this is an intermediate */ - /* tuple or not. */ - /* */ - /* tuple_coords :: The coordinates of the tuple in normalized axis */ - /* units. */ - /* */ - /* im_start_coords :: The initial coordinates where this tuple starts */ - /* to apply (for intermediate coordinates). */ - /* */ - /* im_end_coords :: The final coordinates after which this tuple no */ - /* longer applies (for intermediate coordinates). */ - /* */ - /* <Return> */ - /* An FT_Fixed value containing the scaling factor. */ - /* */ - static FT_Fixed - ft_var_apply_tuple( GX_Blend blend, - FT_UShort tupleIndex, - FT_Fixed* tuple_coords, - FT_Fixed* im_start_coords, - FT_Fixed* im_end_coords ) - { - FT_UInt i; - FT_Fixed apply = 0x10000L; - - - for ( i = 0; i < blend->num_axis; i++ ) - { - FT_TRACE6(( " axis coordinate %d (%.4f):\n", - i, blend->normalizedcoords[i] / 65536.0 )); - - /* It's not clear why (for intermediate tuples) we don't need */ - /* to check against start/end -- the documentation says we don't. */ - /* Similarly, it's unclear why we don't need to scale along the */ - /* axis. */ - - if ( tuple_coords[i] == 0 ) - { - FT_TRACE6(( " tuple coordinate is zero, ignored\n", i )); - continue; - } - - else if ( blend->normalizedcoords[i] == 0 ) - { - FT_TRACE6(( " axis coordinate is zero, stop\n" )); - apply = 0; - break; - } - - else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) || - ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) ) - { - FT_TRACE6(( " tuple coordinate value %.4f is exceeded, stop\n", - tuple_coords[i] / 65536.0 )); - apply = 0; - break; - } - - else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) - { - FT_TRACE6(( " tuple coordinate value %.4f fits\n", - tuple_coords[i] / 65536.0 )); - /* not an intermediate tuple */ - apply = FT_MulFix( apply, - blend->normalizedcoords[i] > 0 - ? blend->normalizedcoords[i] - : -blend->normalizedcoords[i] ); - } - - else if ( blend->normalizedcoords[i] < im_start_coords[i] || - blend->normalizedcoords[i] > im_end_coords[i] ) - { - FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] is exceeded," - " stop\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); - apply = 0; - break; - } - - else if ( blend->normalizedcoords[i] < tuple_coords[i] ) - { - FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); - apply = FT_MulDiv( apply, - blend->normalizedcoords[i] - im_start_coords[i], - tuple_coords[i] - im_start_coords[i] ); - } - - else - { - FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); - apply = FT_MulDiv( apply, - im_end_coords[i] - blend->normalizedcoords[i], - im_end_coords[i] - tuple_coords[i] ); - } - } - - FT_TRACE6(( " apply factor is %.4f\n", apply / 65536.0 )); - - return apply; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - typedef struct GX_FVar_Head_ - { - FT_Long version; - FT_UShort offsetToData; - FT_UShort countSizePairs; - FT_UShort axisCount; - FT_UShort axisSize; - FT_UShort instanceCount; - FT_UShort instanceSize; - - } GX_FVar_Head; - - - typedef struct fvar_axis_ - { - FT_ULong axisTag; - FT_Fixed minValue; - FT_Fixed defaultValue; - FT_Fixed maxValue; - FT_UShort flags; - FT_UShort nameID; - - } GX_FVar_Axis; - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Get_MM_Var */ - /* */ - /* <Description> */ - /* Check that the font's `fvar' table is valid, parse it, and return */ - /* those data. */ - /* */ - /* <InOut> */ - /* face :: The font face. */ - /* TT_Get_MM_Var initializes the blend structure. */ - /* */ - /* <Output> */ - /* master :: The `fvar' data (must be freed by caller). Can be NULL, */ - /* which makes this function simply load MM support. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Var( TT_Face face, - FT_MM_Var* *master ) - { - FT_Stream stream = face->root.stream; - FT_Memory memory = face->root.memory; - FT_ULong table_len; - FT_Error error = FT_Err_Ok; - FT_ULong fvar_start; - FT_Int i, j; - FT_MM_Var* mmvar = NULL; - FT_Fixed* next_coords; - FT_String* next_name; - FT_Var_Axis* a; - FT_Var_Named_Style* ns; - GX_FVar_Head fvar_head; - - static const FT_Frame_Field fvar_fields[] = - { - -#undef FT_STRUCTURE -#define FT_STRUCTURE GX_FVar_Head - - FT_FRAME_START( 16 ), - FT_FRAME_LONG ( version ), - FT_FRAME_USHORT( offsetToData ), - FT_FRAME_USHORT( countSizePairs ), - FT_FRAME_USHORT( axisCount ), - FT_FRAME_USHORT( axisSize ), - FT_FRAME_USHORT( instanceCount ), - FT_FRAME_USHORT( instanceSize ), - FT_FRAME_END - }; - - static const FT_Frame_Field fvaraxis_fields[] = - { - -#undef FT_STRUCTURE -#define FT_STRUCTURE GX_FVar_Axis - - FT_FRAME_START( 20 ), - FT_FRAME_ULONG ( axisTag ), - FT_FRAME_LONG ( minValue ), - FT_FRAME_LONG ( defaultValue ), - FT_FRAME_LONG ( maxValue ), - FT_FRAME_USHORT( flags ), - FT_FRAME_USHORT( nameID ), - FT_FRAME_END - }; - - - /* read the font data and set up the internal representation */ - /* if not already done */ - - if ( face->blend == NULL ) - { - FT_TRACE2(( "FVAR " )); - - /* both `fvar' and `gvar' must be present */ - if ( ( error = face->goto_table( face, TTAG_gvar, - stream, &table_len ) ) != 0 ) - { - FT_TRACE1(( "\n" - "TT_Get_MM_Var: `gvar' table is missing\n" )); - goto Exit; - } - - if ( ( error = face->goto_table( face, TTAG_fvar, - stream, &table_len ) ) != 0 ) - { - FT_TRACE1(( "is missing\n" )); - goto Exit; - } - - fvar_start = FT_STREAM_POS( ); - - if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) ) - goto Exit; - - if ( fvar_head.version != (FT_Long)0x00010000L || -#if 0 - /* fonts like `JamRegular.ttf' have an incorrect value for */ - /* `countSizePairs'; since value 2 is hard-coded in `fvar' */ - /* version 1.0, we simply ignore it */ - fvar_head.countSizePairs != 2 || -#endif - fvar_head.axisSize != 20 || - /* axisCount limit implied by 16-bit instanceSize */ - fvar_head.axisCount > 0x3FFE || - fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount || - /* instanceCount limit implied by limited range of name IDs */ - fvar_head.instanceCount > 0x7EFF || - fvar_head.offsetToData + fvar_head.axisCount * 20U + - fvar_head.instanceCount * fvar_head.instanceSize > table_len ) - { - FT_TRACE1(( "\n" - "TT_Get_MM_Var: invalid `fvar' header\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - FT_TRACE2(( "loaded\n" )); - - FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount )); - - if ( FT_NEW( face->blend ) ) - goto Exit; - - /* cannot overflow 32-bit arithmetic because of limits above */ - face->blend->mmvar_len = - sizeof ( FT_MM_Var ) + - fvar_head.axisCount * sizeof ( FT_Var_Axis ) + - fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + - fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + - 5 * fvar_head.axisCount; - - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) - goto Exit; - face->blend->mmvar = mmvar; - - /* set up pointers and offsets into the `mmvar' array; */ - /* the data gets filled in later on */ - - mmvar->num_axis = - fvar_head.axisCount; - mmvar->num_designs = - ~0U; /* meaningless in this context; each glyph */ - /* may have a different number of designs */ - /* (or tuples, as called by Apple) */ - mmvar->num_namedstyles = - fvar_head.instanceCount; - mmvar->axis = - (FT_Var_Axis*)&( mmvar[1] ); - mmvar->namedstyle = - (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] ); - - next_coords = - (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] ); - for ( i = 0; i < fvar_head.instanceCount; i++ ) - { - mmvar->namedstyle[i].coords = next_coords; - next_coords += fvar_head.axisCount; - } - - next_name = (FT_String*)next_coords; - for ( i = 0; i < fvar_head.axisCount; i++ ) - { - mmvar->axis[i].name = next_name; - next_name += 5; - } - - /* now fill in the data */ - - if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) ) - goto Exit; - - a = mmvar->axis; - for ( i = 0; i < fvar_head.axisCount; i++ ) - { - GX_FVar_Axis axis_rec; - - - if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) ) - goto Exit; - a->tag = axis_rec.axisTag; - a->minimum = axis_rec.minValue; - a->def = axis_rec.defaultValue; - a->maximum = axis_rec.maxValue; - a->strid = axis_rec.nameID; - - a->name[0] = (FT_String)( a->tag >> 24 ); - a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF ); - a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF ); - a->name[3] = (FT_String)( ( a->tag ) & 0xFF ); - a->name[4] = '\0'; - - FT_TRACE5(( " \"%s\": minimum=%.4f, default=%.4f, maximum=%.4f\n", - a->name, - a->minimum / 65536.0, - a->def / 65536.0, - a->maximum / 65536.0 )); - - a++; - } - - FT_TRACE5(( "\n" )); - - ns = mmvar->namedstyle; - for ( i = 0; i < fvar_head.instanceCount; i++, ns++ ) - { - if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) ) - goto Exit; - - ns->strid = FT_GET_USHORT(); - (void) /* flags = */ FT_GET_USHORT(); - - for ( j = 0; j < fvar_head.axisCount; j++ ) - ns->coords[j] = FT_GET_LONG(); - - FT_FRAME_EXIT(); - } - } - - /* fill the output array if requested */ - - if ( master != NULL ) - { - FT_UInt n; - - - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) - goto Exit; - FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); - - mmvar->axis = - (FT_Var_Axis*)&( mmvar[1] ); - mmvar->namedstyle = - (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] ); - next_coords = - (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] ); - - for ( n = 0; n < mmvar->num_namedstyles; n++ ) - { - mmvar->namedstyle[n].coords = next_coords; - next_coords += mmvar->num_axis; - } - - a = mmvar->axis; - next_name = (FT_String*)next_coords; - for ( n = 0; n < mmvar->num_axis; n++ ) - { - a->name = next_name; - - /* standard PostScript names for some standard apple tags */ - if ( a->tag == TTAG_wght ) - a->name = (char*)"Weight"; - else if ( a->tag == TTAG_wdth ) - a->name = (char*)"Width"; - else if ( a->tag == TTAG_opsz ) - a->name = (char*)"OpticalSize"; - else if ( a->tag == TTAG_slnt ) - a->name = (char*)"Slant"; - - next_name += 5; - a++; - } - - *master = mmvar; - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Set_MM_Blend */ - /* */ - /* <Description> */ - /* Set the blend (normalized) coordinates for this instance of the */ - /* font. Check that the `gvar' table is reasonable and does some */ - /* initial preparation. */ - /* */ - /* <InOut> */ - /* face :: The font. */ - /* Initialize the blend structure with `gvar' data. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available coordinates. If it is */ - /* larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use the default value (0) for the remaining axes. */ - /* */ - /* coords :: An array of `num_coords', each between [-1,1]. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Set_MM_Blend( TT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - FT_Error error = FT_Err_Ok; - GX_Blend blend; - FT_MM_Var* mmvar; - FT_UInt i; - FT_Memory memory = face->root.memory; - - enum - { - mcvt_retain, - mcvt_modify, - mcvt_load - - } manageCvt; - - - face->doblend = FALSE; - - if ( face->blend == NULL ) - { - if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 ) - goto Exit; - } - - blend = face->blend; - mmvar = blend->mmvar; - - if ( num_coords > mmvar->num_axis ) - { - FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n", - mmvar->num_axis, num_coords )); - num_coords = mmvar->num_axis; - } - - FT_TRACE5(( "normalized design coordinates:\n" )); - - for ( i = 0; i < num_coords; i++ ) - { - FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 )); - if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) - { - FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.4f\n" - " is out of range [-1;1]\n", - coords[i] / 65536.0 )); - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - } - - FT_TRACE5(( "\n" )); - - if ( blend->glyphoffsets == NULL ) - if ( ( error = ft_var_load_gvar( face ) ) != 0 ) - goto Exit; - - if ( blend->normalizedcoords == NULL ) - { - if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) ) - goto Exit; - - manageCvt = mcvt_modify; - - /* If we have not set the blend coordinates before this, then the */ - /* cvt table will still be what we read from the `cvt ' table and */ - /* we don't need to reload it. We may need to change it though... */ - } - else - { - manageCvt = mcvt_retain; - - for ( i = 0; i < num_coords; i++ ) - { - if ( blend->normalizedcoords[i] != coords[i] ) - { - manageCvt = mcvt_load; - break; - } - } - - for ( ; i < mmvar->num_axis; i++ ) - { - if ( blend->normalizedcoords[i] != 0 ) - { - manageCvt = mcvt_load; - break; - } - } - - /* If we don't change the blend coords then we don't need to do */ - /* anything to the cvt table. It will be correct. Otherwise we */ - /* no longer have the original cvt (it was modified when we set */ - /* the blend last time), so we must reload and then modify it. */ - } - - blend->num_axis = mmvar->num_axis; - FT_MEM_COPY( blend->normalizedcoords, - coords, - num_coords * sizeof ( FT_Fixed ) ); - - face->doblend = TRUE; - - if ( face->cvt != NULL ) - { - switch ( manageCvt ) - { - case mcvt_load: - /* The cvt table has been loaded already; every time we change the */ - /* blend we may need to reload and remodify the cvt table. */ - FT_FREE( face->cvt ); - face->cvt = NULL; - - error = tt_face_load_cvt( face, face->root.stream ); - break; - - case mcvt_modify: - /* The original cvt table is in memory. All we need to do is */ - /* apply the `cvar' table (if any). */ - error = tt_face_vary_cvt( face, face->root.stream ); - break; - - case mcvt_retain: - /* The cvt table is correct for this set of coordinates. */ - break; - } - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Set_Var_Design */ - /* */ - /* <Description> */ - /* Set the coordinates for the instance, measured in the user */ - /* coordinate system. Parse the `avar' table (if present) to convert */ - /* from user to normalized coordinates. */ - /* */ - /* <InOut> */ - /* face :: The font face. */ - /* Initialize the blend struct with `gvar' data. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available coordinates. If it is */ - /* larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use the default values for the remaining axes. */ - /* */ - /* coords :: A coordinate array with `num_coords' elements. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Set_Var_Design( TT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - FT_Error error = FT_Err_Ok; - FT_Fixed* normalized = NULL; - GX_Blend blend; - FT_MM_Var* mmvar; - FT_UInt i, j; - FT_Var_Axis* a; - GX_AVarSegment av; - FT_Memory memory = face->root.memory; - - - if ( face->blend == NULL ) - { - if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 ) - goto Exit; - } - - blend = face->blend; - mmvar = blend->mmvar; - - if ( num_coords > mmvar->num_axis ) - { - FT_TRACE2(( "TT_Set_Var_Design:" - " only using first %d of %d coordinates\n", - mmvar->num_axis, num_coords )); - num_coords = mmvar->num_axis; - } - - /* Axis normalization is a two stage process. First we normalize */ - /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ - /* Then, if there's an `avar' table, we renormalize this range. */ - - if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) - goto Exit; - - FT_TRACE5(( "design coordinates:\n" )); - - a = mmvar->axis; - for ( i = 0; i < num_coords; i++, a++ ) - { - FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 )); - if ( coords[i] > a->maximum || coords[i] < a->minimum ) - { - FT_TRACE1(( "TT_Set_Var_Design: normalized design coordinate %.4f\n" - " is out of range [%.4f;%.4f]\n", - coords[i] / 65536.0, - a->minimum / 65536.0, - a->maximum / 65536.0 )); - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - if ( coords[i] < a->def ) - normalized[i] = -FT_DivFix( coords[i] - a->def, - a->minimum - a->def ); - else if ( a->maximum == a->def ) - normalized[i] = 0; - else - normalized[i] = FT_DivFix( coords[i] - a->def, - a->maximum - a->def ); - } - - FT_TRACE5(( "\n" )); - - for ( ; i < mmvar->num_axis; i++ ) - normalized[i] = 0; - - if ( !blend->avar_checked ) - ft_var_load_avar( face ); - - if ( blend->avar_segment != NULL ) - { - FT_TRACE5(( "normalized design coordinates" - " before applying `avar' data:\n" )); - - av = blend->avar_segment; - for ( i = 0; i < mmvar->num_axis; i++, av++ ) - { - for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) - { - FT_TRACE5(( " %.4f\n", normalized[i] / 65536.0 )); - if ( normalized[i] < av->correspondence[j].fromCoord ) - { - normalized[i] = - FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord ) + - av->correspondence[j - 1].toCoord; - break; - } - } - } - } - - error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized ); - - Exit: - FT_FREE( normalized ); - return error; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** GX VAR PARSING ROUTINES *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_vary_cvt */ - /* */ - /* <Description> */ - /* Modify the loaded cvt table according to the `cvar' table and the */ - /* font's blend. */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Input> */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* Most errors are ignored. It is perfectly valid not to have a */ - /* `cvar' table even if there is a `gvar' and `fvar' table. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_vary_cvt( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - FT_ULong table_start; - FT_ULong table_len; - FT_UInt tupleCount; - FT_ULong offsetToData; - FT_ULong here; - FT_UInt i, j; - FT_Fixed* tuple_coords = NULL; - FT_Fixed* im_start_coords = NULL; - FT_Fixed* im_end_coords = NULL; - GX_Blend blend = face->blend; - FT_UInt point_count; - FT_UShort* localpoints; - FT_Short* deltas; - - - FT_TRACE2(( "CVAR " )); - - if ( blend == NULL ) - { - FT_TRACE2(( "\n" - "tt_face_vary_cvt: no blend specified\n" )); - error = FT_Err_Ok; - goto Exit; - } - - if ( face->cvt == NULL ) - { - FT_TRACE2(( "\n" - "tt_face_vary_cvt: no `cvt ' table\n" )); - error = FT_Err_Ok; - goto Exit; - } - - error = face->goto_table( face, TTAG_cvar, stream, &table_len ); - if ( error ) - { - FT_TRACE2(( "is missing\n" )); - - error = FT_Err_Ok; - goto Exit; - } - - if ( FT_FRAME_ENTER( table_len ) ) - { - error = FT_Err_Ok; - goto Exit; - } - - table_start = FT_Stream_FTell( stream ); - if ( FT_GET_LONG() != 0x00010000L ) - { - FT_TRACE2(( "bad table version\n" )); - - error = FT_Err_Ok; - goto FExit; - } - - FT_TRACE2(( "loaded\n" )); - - if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) - goto FExit; - - tupleCount = FT_GET_USHORT(); - offsetToData = table_start + FT_GET_USHORT(); - - /* The documentation implies there are flags packed into the */ - /* tuplecount, but John Jenkins says that shared points don't apply */ - /* to `cvar', and no other flags are defined. */ - - FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount )); - - for ( i = 0; i < ( tupleCount & 0xFFF ); i++ ) - { - FT_UInt tupleDataSize; - FT_UInt tupleIndex; - FT_Fixed apply; - - - FT_TRACE6(( " tuple %d:\n", i )); - - tupleDataSize = FT_GET_USHORT(); - tupleIndex = FT_GET_USHORT(); - - /* There is no provision here for a global tuple coordinate section, */ - /* so John says. There are no tuple indices, just embedded tuples. */ - - if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) - { - for ( j = 0; j < blend->num_axis; j++ ) - tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */ - /* short frac to fixed */ - } - else - { - /* skip this tuple; it makes no sense */ - - if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) - for ( j = 0; j < 2 * blend->num_axis; j++ ) - (void)FT_GET_SHORT(); - - offsetToData += tupleDataSize; - continue; - } - - if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) - { - for ( j = 0; j < blend->num_axis; j++ ) - im_start_coords[j] = FT_GET_SHORT() * 4; - for ( j = 0; j < blend->num_axis; j++ ) - im_end_coords[j] = FT_GET_SHORT() * 4; - } - - apply = ft_var_apply_tuple( blend, - (FT_UShort)tupleIndex, - tuple_coords, - im_start_coords, - im_end_coords ); - if ( /* tuple isn't active for our blend */ - apply == 0 || - /* global points not allowed, */ - /* if they aren't local, makes no sense */ - !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) ) - { - offsetToData += tupleDataSize; - continue; - } - - here = FT_Stream_FTell( stream ); - - FT_Stream_SeekSet( stream, offsetToData ); - - localpoints = ft_var_readpackedpoints( stream, &point_count ); - deltas = ft_var_readpackeddeltas( stream, - point_count == 0 ? face->cvt_size - : point_count ); - if ( localpoints == NULL || deltas == NULL ) - ; /* failure, ignore it */ - - else if ( localpoints == ALL_POINTS ) - { -#ifdef FT_DEBUG_LEVEL_TRACE - int count = 0; -#endif - - - FT_TRACE7(( " CVT deltas:\n" )); - - /* this means that there are deltas for every entry in cvt */ - for ( j = 0; j < face->cvt_size; j++ ) - { - FT_Long orig_cvt = face->cvt[j]; - - - face->cvt[j] = (FT_Short)( orig_cvt + - FT_MulFix( deltas[j], apply ) ); - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( orig_cvt != face->cvt[j] ) - { - FT_TRACE7(( " %d: %d -> %d\n", - j, orig_cvt, face->cvt[j] )); - count++; - } -#endif - } - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( !count ) - FT_TRACE7(( " none\n" )); -#endif - } - - else - { -#ifdef FT_DEBUG_LEVEL_TRACE - int count = 0; -#endif - - - FT_TRACE7(( " CVT deltas:\n" )); - - for ( j = 0; j < point_count; j++ ) - { - int pindex = localpoints[j]; - FT_Long orig_cvt = face->cvt[pindex]; - - - face->cvt[pindex] = (FT_Short)( orig_cvt + - FT_MulFix( deltas[j], apply ) ); - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( orig_cvt != face->cvt[pindex] ) - { - FT_TRACE7(( " %d: %d -> %d\n", - pindex, orig_cvt, face->cvt[pindex] )); - count++; - } -#endif - } - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( !count ) - FT_TRACE7(( " none\n" )); -#endif - } - - if ( localpoints != ALL_POINTS ) - FT_FREE( localpoints ); - FT_FREE( deltas ); - - offsetToData += tupleDataSize; - - FT_Stream_SeekSet( stream, here ); - } - - FT_TRACE5(( "\n" )); - - FExit: - FT_FRAME_EXIT(); - - Exit: - FT_FREE( tuple_coords ); - FT_FREE( im_start_coords ); - FT_FREE( im_end_coords ); - - return error; - } - - - /* Shift the original coordinates of all points between indices `p1' */ - /* and `p2', using the same difference as given by index `ref'. */ - - /* modeled after `af_iup_shift' */ - - static void - tt_delta_shift( int p1, - int p2, - int ref, - FT_Vector* in_points, - FT_Vector* out_points ) - { - int p; - FT_Vector delta; - - - delta.x = out_points[ref].x - in_points[ref].x; - delta.y = out_points[ref].y - in_points[ref].y; - - if ( delta.x == 0 && delta.y == 0 ) - return; - - for ( p = p1; p < ref; p++ ) - { - out_points[p].x += delta.x; - out_points[p].y += delta.y; - } - - for ( p = ref + 1; p <= p2; p++ ) - { - out_points[p].x += delta.x; - out_points[p].y += delta.y; - } - } - - - /* Interpolate the original coordinates of all points with indices */ - /* between `p1' and `p2', using `ref1' and `ref2' as the reference */ - /* point indices. */ - - /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */ - /* `Ins_IUP' */ - - static void - tt_delta_interpolate( int p1, - int p2, - int ref1, - int ref2, - FT_Vector* in_points, - FT_Vector* out_points ) - { - int p, i; - - FT_Pos out, in1, in2, out1, out2, d1, d2; - - - if ( p1 > p2 ) - return; - - /* handle both horizontal and vertical coordinates */ - for ( i = 0; i <= 1; i++ ) - { - /* shift array pointers so that we can access `foo.y' as `foo.x' */ - in_points = (FT_Vector*)( (FT_Pos*)in_points + i ); - out_points = (FT_Vector*)( (FT_Pos*)out_points + i ); - - if ( in_points[ref1].x > in_points[ref2].x ) - { - p = ref1; - ref1 = ref2; - ref2 = p; - } - - in1 = in_points[ref1].x; - in2 = in_points[ref2].x; - out1 = out_points[ref1].x; - out2 = out_points[ref2].x; - d1 = out1 - in1; - d2 = out2 - in2; - - if ( out1 == out2 || in1 == in2 ) - { - for ( p = p1; p <= p2; p++ ) - { - out = in_points[p].x; - - if ( out <= in1 ) - out += d1; - else if ( out >= in2 ) - out += d2; - else - out = out1; - - out_points[p].x = out; - } - } - else - { - FT_Fixed scale = FT_DivFix( out2 - out1, in2 - in1 ); - - - for ( p = p1; p <= p2; p++ ) - { - out = in_points[p].x; - - if ( out <= in1 ) - out += d1; - else if ( out >= in2 ) - out += d2; - else - out = out1 + FT_MulFix( out - in1, scale ); - - out_points[p].x = out; - } - } - } - } - - - /* Interpolate points without delta values, similar to */ - /* the `IUP' hinting instruction. */ - - /* modeled after `Ins_IUP */ - - static void - tt_handle_deltas( FT_Outline* outline, - FT_Vector* in_points, - FT_Bool* has_delta ) - { - FT_Vector* out_points; - - FT_Int first_point; - FT_Int end_point; - - FT_Int first_delta; - FT_Int cur_delta; - - FT_Int point; - FT_Short contour; - - - /* ignore empty outlines */ - if ( !outline->n_contours ) - return; - - out_points = outline->points; - - contour = 0; - point = 0; - - do - { - end_point = outline->contours[contour]; - first_point = point; - - /* search first point that has a delta */ - while ( point <= end_point && !has_delta[point] ) - point++; - - if ( point <= end_point ) - { - first_delta = point; - cur_delta = point; - - point++; - - while ( point <= end_point ) - { - /* search next point that has a delta */ - /* and interpolate intermediate points */ - if ( has_delta[point] ) - { - tt_delta_interpolate( cur_delta + 1, - point - 1, - cur_delta, - point, - in_points, - out_points ); - cur_delta = point; - } - - point++; - } - - /* shift contour if we only have a single delta */ - if ( cur_delta == first_delta ) - tt_delta_shift( first_point, - end_point, - cur_delta, - in_points, - out_points ); - else - { - /* otherwise handle remaining points */ - /* at the end and beginning of the contour */ - tt_delta_interpolate( cur_delta + 1, - end_point, - cur_delta, - first_delta, - in_points, - out_points ); - - if ( first_delta > 0 ) - tt_delta_interpolate( first_point, - first_delta - 1, - cur_delta, - first_delta, - in_points, - out_points ); - } - } - contour++; - - } while ( contour < outline->n_contours ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Vary_Apply_Glyph_Deltas */ - /* */ - /* <Description> */ - /* Apply the appropriate deltas to the current glyph. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* glyph_index :: The index of the glyph being modified. */ - /* */ - /* n_points :: The number of the points in the glyph, including */ - /* phantom points. */ - /* */ - /* <InOut> */ - /* outline :: The outline to change. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Vary_Apply_Glyph_Deltas( TT_Face face, - FT_UInt glyph_index, - FT_Outline* outline, - FT_UInt n_points ) - { - FT_Stream stream = face->root.stream; - FT_Memory memory = stream->memory; - GX_Blend blend = face->blend; - - FT_Vector* points_org = NULL; - FT_Bool* has_delta = NULL; - - FT_Error error; - FT_ULong glyph_start; - FT_UInt tupleCount; - FT_ULong offsetToData; - FT_ULong here; - FT_UInt i, j; - FT_Fixed* tuple_coords = NULL; - FT_Fixed* im_start_coords = NULL; - FT_Fixed* im_end_coords = NULL; - FT_UInt point_count, spoint_count = 0; - FT_UShort* sharedpoints = NULL; - FT_UShort* localpoints = NULL; - FT_UShort* points; - FT_Short *deltas_x, *deltas_y; - - - if ( !face->doblend || blend == NULL ) - return FT_THROW( Invalid_Argument ); - - if ( glyph_index >= blend->gv_glyphcnt || - blend->glyphoffsets[glyph_index] == - blend->glyphoffsets[glyph_index + 1] ) - { - FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" - " no variation data for this glyph\n" )); - return FT_Err_Ok; - } - - if ( FT_NEW_ARRAY( points_org, n_points ) || - FT_NEW_ARRAY( has_delta, n_points ) ) - goto Fail1; - - if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || - FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] - - blend->glyphoffsets[glyph_index] ) ) - goto Fail1; - - glyph_start = FT_Stream_FTell( stream ); - - /* each set of glyph variation data is formatted similarly to `cvar' */ - /* (except we get shared points and global tuples) */ - - if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || - FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) - goto Fail2; - - tupleCount = FT_GET_USHORT(); - offsetToData = glyph_start + FT_GET_USHORT(); - - if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS ) - { - here = FT_Stream_FTell( stream ); - - FT_Stream_SeekSet( stream, offsetToData ); - - sharedpoints = ft_var_readpackedpoints( stream, &spoint_count ); - offsetToData = FT_Stream_FTell( stream ); - - FT_Stream_SeekSet( stream, here ); - } - - FT_TRACE5(( "gvar: there are %d tuples:\n", tupleCount )); - - for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) - { - FT_UInt tupleDataSize; - FT_UInt tupleIndex; - FT_Fixed apply; - - - FT_TRACE6(( " tuple %d:\n", i )); - - tupleDataSize = FT_GET_USHORT(); - tupleIndex = FT_GET_USHORT(); - - if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) - { - for ( j = 0; j < blend->num_axis; j++ ) - tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */ - /* short frac to fixed */ - } - else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) - { - error = FT_THROW( Invalid_Table ); - goto Fail2; - } - else - FT_MEM_COPY( - tuple_coords, - &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis], - blend->num_axis * sizeof ( FT_Fixed ) ); - - if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) - { - for ( j = 0; j < blend->num_axis; j++ ) - im_start_coords[j] = FT_GET_SHORT() * 4; - for ( j = 0; j < blend->num_axis; j++ ) - im_end_coords[j] = FT_GET_SHORT() * 4; - } - - apply = ft_var_apply_tuple( blend, - (FT_UShort)tupleIndex, - tuple_coords, - im_start_coords, - im_end_coords ); - - if ( apply == 0 ) /* tuple isn't active for our blend */ - { - offsetToData += tupleDataSize; - continue; - } - - here = FT_Stream_FTell( stream ); - - if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) - { - FT_Stream_SeekSet( stream, offsetToData ); - - localpoints = ft_var_readpackedpoints( stream, &point_count ); - points = localpoints; - } - else - { - points = sharedpoints; - point_count = spoint_count; - } - - deltas_x = ft_var_readpackeddeltas( stream, - point_count == 0 ? n_points - : point_count ); - deltas_y = ft_var_readpackeddeltas( stream, - point_count == 0 ? n_points - : point_count ); - - if ( points == NULL || deltas_y == NULL || deltas_x == NULL ) - ; /* failure, ignore it */ - - else if ( points == ALL_POINTS ) - { -#ifdef FT_DEBUG_LEVEL_TRACE - int count = 0; -#endif - - - FT_TRACE7(( " point deltas:\n" )); - - /* this means that there are deltas for every point in the glyph */ - for ( j = 0; j < n_points; j++ ) - { -#ifdef FT_DEBUG_LEVEL_TRACE - FT_Vector point_org = outline->points[j]; -#endif - - - outline->points[j].x += FT_MulFix( deltas_x[j], apply ); - outline->points[j].y += FT_MulFix( deltas_y[j], apply ); - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( ( point_org.x != outline->points[j].x ) || - ( point_org.y != outline->points[j].y ) ) - { - FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n", - j, - point_org.x, - point_org.y, - outline->points[j].x, - outline->points[j].y )); - count++; - } -#endif - } - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( !count ) - FT_TRACE7(( " none\n" )); -#endif - } - - else - { -#ifdef FT_DEBUG_LEVEL_TRACE - int count = 0; -#endif - - - /* we have to interpolate the missing deltas similar to the */ - /* IUP bytecode instruction */ - for ( j = 0; j < n_points; j++ ) - { - points_org[j] = outline->points[j]; - has_delta[j] = FALSE; - } - - for ( j = 0; j < point_count; j++ ) - { - FT_UShort idx = localpoints[j]; - - - if ( idx >= n_points ) - continue; - - has_delta[idx] = TRUE; - - outline->points[idx].x += FT_MulFix( deltas_x[j], apply ); - outline->points[idx].y += FT_MulFix( deltas_y[j], apply ); - } - - /* no need to handle phantom points here, */ - /* since solitary points can't be interpolated */ - tt_handle_deltas( outline, - points_org, - has_delta ); - -#ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE7(( " point deltas:\n" )); - - for ( j = 0; j < n_points; j++) - { - if ( ( points_org[j].x != outline->points[j].x ) || - ( points_org[j].y != outline->points[j].y ) ) - { - FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n", - j, - points_org[j].x, - points_org[j].y, - outline->points[j].x, - outline->points[j].y )); - count++; - } - } - - if ( !count ) - FT_TRACE7(( " none\n" )); -#endif - } - - if ( localpoints != ALL_POINTS ) - FT_FREE( localpoints ); - FT_FREE( deltas_x ); - FT_FREE( deltas_y ); - - offsetToData += tupleDataSize; - - FT_Stream_SeekSet( stream, here ); - } - - FT_TRACE5(( "\n" )); - - Fail2: - FT_FREE( tuple_coords ); - FT_FREE( im_start_coords ); - FT_FREE( im_end_coords ); - - FT_FRAME_EXIT(); - - Fail1: - FT_FREE( points_org ); - FT_FREE( has_delta ); - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_done_blend */ - /* */ - /* <Description> */ - /* Free the blend internal data structure. */ - /* */ - FT_LOCAL_DEF( void ) - tt_done_blend( FT_Memory memory, - GX_Blend blend ) - { - if ( blend != NULL ) - { - FT_UInt i; - - - FT_FREE( blend->normalizedcoords ); - FT_FREE( blend->mmvar ); - - if ( blend->avar_segment != NULL ) - { - for ( i = 0; i < blend->num_axis; i++ ) - FT_FREE( blend->avar_segment[i].correspondence ); - FT_FREE( blend->avar_segment ); - } - - FT_FREE( blend->tuplecoords ); - FT_FREE( blend->glyphoffsets ); - FT_FREE( blend ); - } - } - -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttgxvar.h b/third_party/freetype/src/truetype/ttgxvar.h deleted file mode 100644 index 060d4d60eaf68a854b0a31a9116a20c73d597260..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttgxvar.h +++ /dev/null @@ -1,182 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttgxvar.h */ -/* */ -/* TrueType GX Font Variation loader (specification) */ -/* */ -/* Copyright 2004-2015 by */ -/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTGXVAR_H__ -#define __TTGXVAR_H__ - - -#include <ft2build.h> -#include "ttobjs.h" - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* GX_AVarCorrespondenceRec */ - /* */ - /* <Description> */ - /* A data structure representing `shortFracCorrespondence' in `avar' */ - /* table according to the specifications from Apple. */ - /* */ - typedef struct GX_AVarCorrespondenceRec_ - { - FT_Fixed fromCoord; - FT_Fixed toCoord; - - } GX_AVarCorrespondenceRec_, *GX_AVarCorrespondence; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* GX_AVarRec */ - /* */ - /* <Description> */ - /* Data from the segment field of `avar' table. */ - /* There is one of these for each axis. */ - /* */ - typedef struct GX_AVarSegmentRec_ - { - FT_UShort pairCount; - GX_AVarCorrespondence correspondence; /* array with pairCount entries */ - - } GX_AVarSegmentRec, *GX_AVarSegment; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* GX_BlendRec */ - /* */ - /* <Description> */ - /* Data for interpolating a font from a distortable font specified */ - /* by the GX *var tables ([fgca]var). */ - /* */ - /* <Fields> */ - /* num_axis :: The number of axes along which interpolation */ - /* may happen */ - /* */ - /* normalizedcoords :: A normalized value (between [-1,1]) indicating */ - /* the contribution along each axis to the final */ - /* interpolated font. */ - /* */ - typedef struct GX_BlendRec_ - { - FT_UInt num_axis; - FT_Fixed* normalizedcoords; - - FT_MM_Var* mmvar; - FT_Offset mmvar_len; - - FT_Bool avar_checked; - GX_AVarSegment avar_segment; - - FT_UInt tuplecount; /* shared tuples in `gvar' */ - FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ - - FT_UInt gv_glyphcnt; - FT_ULong* glyphoffsets; - - } GX_BlendRec; - - - /*************************************************************************/ - /* */ - /* <enum> */ - /* GX_TupleCountFlags */ - /* */ - /* <Description> */ - /* Flags used within the `TupleCount' field of the `gvar' table. */ - /* */ - typedef enum GX_TupleCountFlags_ - { - GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000, - GX_TC_RESERVED_TUPLE_FLAGS = 0x7000, - GX_TC_TUPLE_COUNT_MASK = 0x0FFF - - } GX_TupleCountFlags; - - - /*************************************************************************/ - /* */ - /* <enum> */ - /* GX_TupleIndexFlags */ - /* */ - /* <Description> */ - /* Flags used within the `TupleIndex' field of the `gvar' and `cvar' */ - /* tables. */ - /* */ - typedef enum GX_TupleIndexFlags_ - { - GX_TI_EMBEDDED_TUPLE_COORD = 0x8000, - GX_TI_INTERMEDIATE_TUPLE = 0x4000, - GX_TI_PRIVATE_POINT_NUMBERS = 0x2000, - GX_TI_RESERVED_TUPLE_FLAG = 0x1000, - GX_TI_TUPLE_INDEX_MASK = 0x0FFF - - } GX_TupleIndexFlags; - - -#define TTAG_wght FT_MAKE_TAG( 'w', 'g', 'h', 't' ) -#define TTAG_wdth FT_MAKE_TAG( 'w', 'd', 't', 'h' ) -#define TTAG_opsz FT_MAKE_TAG( 'o', 'p', 's', 'z' ) -#define TTAG_slnt FT_MAKE_TAG( 's', 'l', 'n', 't' ) - - - FT_LOCAL( FT_Error ) - TT_Set_MM_Blend( TT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - FT_LOCAL( FT_Error ) - TT_Set_Var_Design( TT_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - FT_LOCAL( FT_Error ) - TT_Get_MM_Var( TT_Face face, - FT_MM_Var* *master ); - - - FT_LOCAL( FT_Error ) - tt_face_vary_cvt( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - TT_Vary_Apply_Glyph_Deltas( TT_Face face, - FT_UInt glyph_index, - FT_Outline* outline, - FT_UInt n_points ); - - - FT_LOCAL( void ) - tt_done_blend( FT_Memory memory, - GX_Blend blend ); - - -FT_END_HEADER - - -#endif /* __TTGXVAR_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttinterp.c b/third_party/freetype/src/truetype/ttinterp.c deleted file mode 100644 index ae2a82adc5ede6a1206fbd8482237d9d8cbab309..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttinterp.c +++ /dev/null @@ -1,8275 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttinterp.c */ -/* */ -/* TrueType bytecode interpreter (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -/* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */ -/* issues; many thanks! */ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H -#include FT_TRIGONOMETRY_H -#include FT_SYSTEM_H -#include FT_TRUETYPE_DRIVER_H - -#include "ttinterp.h" -#include "tterrors.h" -#include "ttsubpix.h" - - -#ifdef TT_USE_BYTECODE_INTERPRETER - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttinterp - - - /*************************************************************************/ - /* */ - /* In order to detect infinite loops in the code, we set up a counter */ - /* within the run loop. A single stroke of interpretation is now */ - /* limited to a maximum number of opcodes defined below. */ - /* */ -#define MAX_RUNNABLE_OPCODES 1000000L - - -#define SUBPIXEL_HINTING \ - ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ - TT_INTERPRETER_VERSION_38 ) - - -#define PROJECT( v1, v2 ) \ - exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y ) - -#define DUALPROJ( v1, v2 ) \ - exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y ) - -#define FAST_PROJECT( v ) \ - exc->func_project( exc, (v)->x, (v)->y ) - -#define FAST_DUALPROJ( v ) \ - exc->func_dualproj( exc, (v)->x, (v)->y ) - - - /*************************************************************************/ - /* */ - /* Instruction dispatch function, as used by the interpreter. */ - /* */ - typedef void (*TInstruction_Function)( TT_ExecContext exc, - FT_Long* args ); - - - /*************************************************************************/ - /* */ - /* Two simple bounds-checking macros. */ - /* */ -#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) -#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) ) - - -#undef SUCCESS -#define SUCCESS 0 - -#undef FAILURE -#define FAILURE 1 - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING -#define GUESS_VECTOR( V ) \ - do \ - { \ - if ( exc->face->unpatented_hinting ) \ - { \ - exc->GS.V.x = (FT_F2Dot14)( exc->GS.both_x_axis ? 0x4000 : 0 ); \ - exc->GS.V.y = (FT_F2Dot14)( exc->GS.both_x_axis ? 0 : 0x4000 ); \ - } \ - } while (0) -#else -#define GUESS_VECTOR( V ) do { } while (0) -#endif - - - /*************************************************************************/ - /* */ - /* CODERANGE FUNCTIONS */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Goto_CodeRange */ - /* */ - /* <Description> */ - /* Switches to a new code range (updates the code related elements in */ - /* `exec', and `IP'). */ - /* */ - /* <Input> */ - /* range :: The new execution code range. */ - /* */ - /* IP :: The new IP in the new code range. */ - /* */ - /* <InOut> */ - /* exec :: The target execution context. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Goto_CodeRange( TT_ExecContext exec, - FT_Int range, - FT_Long IP ) - { - TT_CodeRange* coderange; - - - FT_ASSERT( range >= 1 && range <= 3 ); - - coderange = &exec->codeRangeTable[range - 1]; - - FT_ASSERT( coderange->base != NULL ); - - /* NOTE: Because the last instruction of a program may be a CALL */ - /* which will return to the first byte *after* the code */ - /* range, we test for IP <= Size instead of IP < Size. */ - /* */ - FT_ASSERT( IP <= coderange->size ); - - exec->code = coderange->base; - exec->codeSize = coderange->size; - exec->IP = IP; - exec->curRange = range; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Set_CodeRange */ - /* */ - /* <Description> */ - /* Sets a code range. */ - /* */ - /* <Input> */ - /* range :: The code range index. */ - /* */ - /* base :: The new code base. */ - /* */ - /* length :: The range size in bytes. */ - /* */ - /* <InOut> */ - /* exec :: The target execution context. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Set_CodeRange( TT_ExecContext exec, - FT_Int range, - void* base, - FT_Long length ) - { - FT_ASSERT( range >= 1 && range <= 3 ); - - exec->codeRangeTable[range - 1].base = (FT_Byte*)base; - exec->codeRangeTable[range - 1].size = length; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Clear_CodeRange */ - /* */ - /* <Description> */ - /* Clears a code range. */ - /* */ - /* <Input> */ - /* range :: The code range index. */ - /* */ - /* <InOut> */ - /* exec :: The target execution context. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Clear_CodeRange( TT_ExecContext exec, - FT_Int range ) - { - FT_ASSERT( range >= 1 && range <= 3 ); - - exec->codeRangeTable[range - 1].base = NULL; - exec->codeRangeTable[range - 1].size = 0; - } - - - /*************************************************************************/ - /* */ - /* EXECUTION CONTEXT ROUTINES */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Done_Context */ - /* */ - /* <Description> */ - /* Destroys a given context. */ - /* */ - /* <Input> */ - /* exec :: A handle to the target execution context. */ - /* */ - /* memory :: A handle to the parent memory object. */ - /* */ - /* <Note> */ - /* Only the glyph loader and debugger should call this function. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Done_Context( TT_ExecContext exec ) - { - FT_Memory memory = exec->memory; - - - /* points zone */ - exec->maxPoints = 0; - exec->maxContours = 0; - - /* free stack */ - FT_FREE( exec->stack ); - exec->stackSize = 0; - - /* free call stack */ - FT_FREE( exec->callStack ); - exec->callSize = 0; - exec->callTop = 0; - - /* free glyph code range */ - FT_FREE( exec->glyphIns ); - exec->glyphSize = 0; - - exec->size = NULL; - exec->face = NULL; - - FT_FREE( exec ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Init_Context */ - /* */ - /* <Description> */ - /* Initializes a context object. */ - /* */ - /* <Input> */ - /* memory :: A handle to the parent memory object. */ - /* */ - /* <InOut> */ - /* exec :: A handle to the target execution context. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - static FT_Error - Init_Context( TT_ExecContext exec, - FT_Memory memory ) - { - FT_Error error; - - - FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec )); - - exec->memory = memory; - exec->callSize = 32; - - if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) ) - goto Fail_Memory; - - /* all values in the context are set to 0 already, but this is */ - /* here as a remainder */ - exec->maxPoints = 0; - exec->maxContours = 0; - - exec->stackSize = 0; - exec->glyphSize = 0; - - exec->stack = NULL; - exec->glyphIns = NULL; - - exec->face = NULL; - exec->size = NULL; - - return FT_Err_Ok; - - Fail_Memory: - FT_ERROR(( "Init_Context: not enough memory for %p\n", exec )); - TT_Done_Context( exec ); - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Update_Max */ - /* */ - /* <Description> */ - /* Checks the size of a buffer and reallocates it if necessary. */ - /* */ - /* <Input> */ - /* memory :: A handle to the parent memory object. */ - /* */ - /* multiplier :: The size in bytes of each element in the buffer. */ - /* */ - /* new_max :: The new capacity (size) of the buffer. */ - /* */ - /* <InOut> */ - /* size :: The address of the buffer's current size expressed */ - /* in elements. */ - /* */ - /* buff :: The address of the buffer base pointer. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ) - { - FT_Error error; - void** pbuff = (void**)_pbuff; - - - if ( *size < new_max ) - { - if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) ) - return error; - *size = new_max; - } - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Load_Context */ - /* */ - /* <Description> */ - /* Prepare an execution context for glyph hinting. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* size :: A handle to the source size object. */ - /* */ - /* <InOut> */ - /* exec :: A handle to the target execution context. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* Only the glyph loader and debugger should call this function. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Load_Context( TT_ExecContext exec, - TT_Face face, - TT_Size size ) - { - FT_Int i; - FT_ULong tmp; - TT_MaxProfile* maxp; - FT_Error error; - - - exec->face = face; - maxp = &face->max_profile; - exec->size = size; - - if ( size ) - { - exec->numFDefs = size->num_function_defs; - exec->maxFDefs = size->max_function_defs; - exec->numIDefs = size->num_instruction_defs; - exec->maxIDefs = size->max_instruction_defs; - exec->FDefs = size->function_defs; - exec->IDefs = size->instruction_defs; - exec->tt_metrics = size->ttmetrics; - exec->metrics = size->metrics; - - exec->maxFunc = size->max_func; - exec->maxIns = size->max_ins; - - for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) - exec->codeRangeTable[i] = size->codeRangeTable[i]; - - /* set graphics state */ - exec->GS = size->GS; - - exec->cvtSize = size->cvt_size; - exec->cvt = size->cvt; - - exec->storeSize = size->storage_size; - exec->storage = size->storage; - - exec->twilight = size->twilight; - - /* In case of multi-threading it can happen that the old size object */ - /* no longer exists, thus we must clear all glyph zone references. */ - ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) ); - exec->zp1 = exec->zp0; - exec->zp2 = exec->zp0; - } - - /* XXX: We reserve a little more elements on the stack to deal safely */ - /* with broken fonts like arialbs, courbs, timesbs, etc. */ - tmp = (FT_ULong)exec->stackSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_F26Dot6 ), - (void*)&exec->stack, - maxp->maxStackElements + 32 ); - exec->stackSize = (FT_Long)tmp; - if ( error ) - return error; - - tmp = exec->glyphSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&exec->glyphIns, - maxp->maxSizeOfInstructions ); - exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - - exec->pts.n_points = 0; - exec->pts.n_contours = 0; - - exec->zp1 = exec->pts; - exec->zp2 = exec->pts; - exec->zp0 = exec->pts; - - exec->instruction_trap = FALSE; - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Save_Context */ - /* */ - /* <Description> */ - /* Saves the code ranges in a `size' object. */ - /* */ - /* <Input> */ - /* exec :: A handle to the source execution context. */ - /* */ - /* <InOut> */ - /* size :: A handle to the target size object. */ - /* */ - /* <Note> */ - /* Only the glyph loader and debugger should call this function. */ - /* */ - FT_LOCAL_DEF( void ) - TT_Save_Context( TT_ExecContext exec, - TT_Size size ) - { - FT_Int i; - - - /* XXX: Will probably disappear soon with all the code range */ - /* management, which is now rather obsolete. */ - /* */ - size->num_function_defs = exec->numFDefs; - size->num_instruction_defs = exec->numIDefs; - - size->max_func = exec->maxFunc; - size->max_ins = exec->maxIns; - - for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) - size->codeRangeTable[i] = exec->codeRangeTable[i]; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Run_Context */ - /* */ - /* <Description> */ - /* Executes one or more instructions in the execution context. */ - /* */ - /* <Input> */ - /* debug :: A Boolean flag. If set, the function sets some internal */ - /* variables and returns immediately, otherwise TT_RunIns() */ - /* is called. */ - /* */ - /* This is commented out currently. */ - /* */ - /* <Input> */ - /* exec :: A handle to the target execution context. */ - /* */ - /* <Return> */ - /* TrueType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Run_Context( TT_ExecContext exec ) - { - TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ); - - exec->zp0 = exec->pts; - exec->zp1 = exec->pts; - exec->zp2 = exec->pts; - - exec->GS.gep0 = 1; - exec->GS.gep1 = 1; - exec->GS.gep2 = 1; - - exec->GS.projVector.x = 0x4000; - exec->GS.projVector.y = 0x0000; - - exec->GS.freeVector = exec->GS.projVector; - exec->GS.dualVector = exec->GS.projVector; - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - exec->GS.both_x_axis = TRUE; -#endif - - exec->GS.round_state = 1; - exec->GS.loop = 1; - - /* some glyphs leave something on the stack. so we clean it */ - /* before a new execution. */ - exec->top = 0; - exec->callTop = 0; - - return exec->face->interpreter( exec ); - } - - - /* The default value for `scan_control' is documented as FALSE in the */ - /* TrueType specification. This is confusing since it implies a */ - /* Boolean value. However, this is not the case, thus both the */ - /* default values of our `scan_type' and `scan_control' fields (which */ - /* the documentation's `scan_control' variable is split into) are */ - /* zero. */ - - const TT_GraphicsState tt_default_graphics_state = - { - 0, 0, 0, - { 0x4000, 0 }, - { 0x4000, 0 }, - { 0x4000, 0 }, - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - TRUE, -#endif - - 1, 64, 1, - TRUE, 68, 0, 0, 9, 3, - 0, FALSE, 0, 1, 1, 1 - }; - - - /* documentation is in ttinterp.h */ - - FT_EXPORT_DEF( TT_ExecContext ) - TT_New_Context( TT_Driver driver ) - { - FT_Memory memory; - FT_Error error; - - TT_ExecContext exec = NULL; - - - if ( !driver ) - goto Fail; - - memory = driver->root.root.memory; - - /* allocate object */ - if ( FT_NEW( exec ) ) - goto Fail; - - /* initialize it; in case of error this deallocates `exec' too */ - error = Init_Context( exec, memory ); - if ( error ) - goto Fail; - - return exec; - - Fail: - return NULL; - } - - - /*************************************************************************/ - /* */ - /* Before an opcode is executed, the interpreter verifies that there are */ - /* enough arguments on the stack, with the help of the `Pop_Push_Count' */ - /* table. */ - /* */ - /* For each opcode, the first column gives the number of arguments that */ - /* are popped from the stack; the second one gives the number of those */ - /* that are pushed in result. */ - /* */ - /* Opcodes which have a varying number of parameters in the data stream */ - /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */ - /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */ - /* to zero. */ - /* */ - /*************************************************************************/ - - -#undef PACK -#define PACK( x, y ) ( ( x << 4 ) | y ) - - - static - const FT_Byte Pop_Push_Count[256] = - { - /* opcodes are gathered in groups of 16 */ - /* please keep the spaces as they are */ - - /* SVTCA y */ PACK( 0, 0 ), - /* SVTCA x */ PACK( 0, 0 ), - /* SPvTCA y */ PACK( 0, 0 ), - /* SPvTCA x */ PACK( 0, 0 ), - /* SFvTCA y */ PACK( 0, 0 ), - /* SFvTCA x */ PACK( 0, 0 ), - /* SPvTL // */ PACK( 2, 0 ), - /* SPvTL + */ PACK( 2, 0 ), - /* SFvTL // */ PACK( 2, 0 ), - /* SFvTL + */ PACK( 2, 0 ), - /* SPvFS */ PACK( 2, 0 ), - /* SFvFS */ PACK( 2, 0 ), - /* GPv */ PACK( 0, 2 ), - /* GFv */ PACK( 0, 2 ), - /* SFvTPv */ PACK( 0, 0 ), - /* ISECT */ PACK( 5, 0 ), - - /* SRP0 */ PACK( 1, 0 ), - /* SRP1 */ PACK( 1, 0 ), - /* SRP2 */ PACK( 1, 0 ), - /* SZP0 */ PACK( 1, 0 ), - /* SZP1 */ PACK( 1, 0 ), - /* SZP2 */ PACK( 1, 0 ), - /* SZPS */ PACK( 1, 0 ), - /* SLOOP */ PACK( 1, 0 ), - /* RTG */ PACK( 0, 0 ), - /* RTHG */ PACK( 0, 0 ), - /* SMD */ PACK( 1, 0 ), - /* ELSE */ PACK( 0, 0 ), - /* JMPR */ PACK( 1, 0 ), - /* SCvTCi */ PACK( 1, 0 ), - /* SSwCi */ PACK( 1, 0 ), - /* SSW */ PACK( 1, 0 ), - - /* DUP */ PACK( 1, 2 ), - /* POP */ PACK( 1, 0 ), - /* CLEAR */ PACK( 0, 0 ), - /* SWAP */ PACK( 2, 2 ), - /* DEPTH */ PACK( 0, 1 ), - /* CINDEX */ PACK( 1, 1 ), - /* MINDEX */ PACK( 1, 0 ), - /* AlignPTS */ PACK( 2, 0 ), - /* INS_$28 */ PACK( 0, 0 ), - /* UTP */ PACK( 1, 0 ), - /* LOOPCALL */ PACK( 2, 0 ), - /* CALL */ PACK( 1, 0 ), - /* FDEF */ PACK( 1, 0 ), - /* ENDF */ PACK( 0, 0 ), - /* MDAP[0] */ PACK( 1, 0 ), - /* MDAP[1] */ PACK( 1, 0 ), - - /* IUP[0] */ PACK( 0, 0 ), - /* IUP[1] */ PACK( 0, 0 ), - /* SHP[0] */ PACK( 0, 0 ), - /* SHP[1] */ PACK( 0, 0 ), - /* SHC[0] */ PACK( 1, 0 ), - /* SHC[1] */ PACK( 1, 0 ), - /* SHZ[0] */ PACK( 1, 0 ), - /* SHZ[1] */ PACK( 1, 0 ), - /* SHPIX */ PACK( 1, 0 ), - /* IP */ PACK( 0, 0 ), - /* MSIRP[0] */ PACK( 2, 0 ), - /* MSIRP[1] */ PACK( 2, 0 ), - /* AlignRP */ PACK( 0, 0 ), - /* RTDG */ PACK( 0, 0 ), - /* MIAP[0] */ PACK( 2, 0 ), - /* MIAP[1] */ PACK( 2, 0 ), - - /* NPushB */ PACK( 0, 0 ), - /* NPushW */ PACK( 0, 0 ), - /* WS */ PACK( 2, 0 ), - /* RS */ PACK( 1, 1 ), - /* WCvtP */ PACK( 2, 0 ), - /* RCvt */ PACK( 1, 1 ), - /* GC[0] */ PACK( 1, 1 ), - /* GC[1] */ PACK( 1, 1 ), - /* SCFS */ PACK( 2, 0 ), - /* MD[0] */ PACK( 2, 1 ), - /* MD[1] */ PACK( 2, 1 ), - /* MPPEM */ PACK( 0, 1 ), - /* MPS */ PACK( 0, 1 ), - /* FlipON */ PACK( 0, 0 ), - /* FlipOFF */ PACK( 0, 0 ), - /* DEBUG */ PACK( 1, 0 ), - - /* LT */ PACK( 2, 1 ), - /* LTEQ */ PACK( 2, 1 ), - /* GT */ PACK( 2, 1 ), - /* GTEQ */ PACK( 2, 1 ), - /* EQ */ PACK( 2, 1 ), - /* NEQ */ PACK( 2, 1 ), - /* ODD */ PACK( 1, 1 ), - /* EVEN */ PACK( 1, 1 ), - /* IF */ PACK( 1, 0 ), - /* EIF */ PACK( 0, 0 ), - /* AND */ PACK( 2, 1 ), - /* OR */ PACK( 2, 1 ), - /* NOT */ PACK( 1, 1 ), - /* DeltaP1 */ PACK( 1, 0 ), - /* SDB */ PACK( 1, 0 ), - /* SDS */ PACK( 1, 0 ), - - /* ADD */ PACK( 2, 1 ), - /* SUB */ PACK( 2, 1 ), - /* DIV */ PACK( 2, 1 ), - /* MUL */ PACK( 2, 1 ), - /* ABS */ PACK( 1, 1 ), - /* NEG */ PACK( 1, 1 ), - /* FLOOR */ PACK( 1, 1 ), - /* CEILING */ PACK( 1, 1 ), - /* ROUND[0] */ PACK( 1, 1 ), - /* ROUND[1] */ PACK( 1, 1 ), - /* ROUND[2] */ PACK( 1, 1 ), - /* ROUND[3] */ PACK( 1, 1 ), - /* NROUND[0] */ PACK( 1, 1 ), - /* NROUND[1] */ PACK( 1, 1 ), - /* NROUND[2] */ PACK( 1, 1 ), - /* NROUND[3] */ PACK( 1, 1 ), - - /* WCvtF */ PACK( 2, 0 ), - /* DeltaP2 */ PACK( 1, 0 ), - /* DeltaP3 */ PACK( 1, 0 ), - /* DeltaCn[0] */ PACK( 1, 0 ), - /* DeltaCn[1] */ PACK( 1, 0 ), - /* DeltaCn[2] */ PACK( 1, 0 ), - /* SROUND */ PACK( 1, 0 ), - /* S45Round */ PACK( 1, 0 ), - /* JROT */ PACK( 2, 0 ), - /* JROF */ PACK( 2, 0 ), - /* ROFF */ PACK( 0, 0 ), - /* INS_$7B */ PACK( 0, 0 ), - /* RUTG */ PACK( 0, 0 ), - /* RDTG */ PACK( 0, 0 ), - /* SANGW */ PACK( 1, 0 ), - /* AA */ PACK( 1, 0 ), - - /* FlipPT */ PACK( 0, 0 ), - /* FlipRgON */ PACK( 2, 0 ), - /* FlipRgOFF */ PACK( 2, 0 ), - /* INS_$83 */ PACK( 0, 0 ), - /* INS_$84 */ PACK( 0, 0 ), - /* ScanCTRL */ PACK( 1, 0 ), - /* SDPvTL[0] */ PACK( 2, 0 ), - /* SDPvTL[1] */ PACK( 2, 0 ), - /* GetINFO */ PACK( 1, 1 ), - /* IDEF */ PACK( 1, 0 ), - /* ROLL */ PACK( 3, 3 ), - /* MAX */ PACK( 2, 1 ), - /* MIN */ PACK( 2, 1 ), - /* ScanTYPE */ PACK( 1, 0 ), - /* InstCTRL */ PACK( 2, 0 ), - /* INS_$8F */ PACK( 0, 0 ), - - /* INS_$90 */ PACK( 0, 0 ), - /* INS_$91 */ PACK( 0, 0 ), - /* INS_$92 */ PACK( 0, 0 ), - /* INS_$93 */ PACK( 0, 0 ), - /* INS_$94 */ PACK( 0, 0 ), - /* INS_$95 */ PACK( 0, 0 ), - /* INS_$96 */ PACK( 0, 0 ), - /* INS_$97 */ PACK( 0, 0 ), - /* INS_$98 */ PACK( 0, 0 ), - /* INS_$99 */ PACK( 0, 0 ), - /* INS_$9A */ PACK( 0, 0 ), - /* INS_$9B */ PACK( 0, 0 ), - /* INS_$9C */ PACK( 0, 0 ), - /* INS_$9D */ PACK( 0, 0 ), - /* INS_$9E */ PACK( 0, 0 ), - /* INS_$9F */ PACK( 0, 0 ), - - /* INS_$A0 */ PACK( 0, 0 ), - /* INS_$A1 */ PACK( 0, 0 ), - /* INS_$A2 */ PACK( 0, 0 ), - /* INS_$A3 */ PACK( 0, 0 ), - /* INS_$A4 */ PACK( 0, 0 ), - /* INS_$A5 */ PACK( 0, 0 ), - /* INS_$A6 */ PACK( 0, 0 ), - /* INS_$A7 */ PACK( 0, 0 ), - /* INS_$A8 */ PACK( 0, 0 ), - /* INS_$A9 */ PACK( 0, 0 ), - /* INS_$AA */ PACK( 0, 0 ), - /* INS_$AB */ PACK( 0, 0 ), - /* INS_$AC */ PACK( 0, 0 ), - /* INS_$AD */ PACK( 0, 0 ), - /* INS_$AE */ PACK( 0, 0 ), - /* INS_$AF */ PACK( 0, 0 ), - - /* PushB[0] */ PACK( 0, 1 ), - /* PushB[1] */ PACK( 0, 2 ), - /* PushB[2] */ PACK( 0, 3 ), - /* PushB[3] */ PACK( 0, 4 ), - /* PushB[4] */ PACK( 0, 5 ), - /* PushB[5] */ PACK( 0, 6 ), - /* PushB[6] */ PACK( 0, 7 ), - /* PushB[7] */ PACK( 0, 8 ), - /* PushW[0] */ PACK( 0, 1 ), - /* PushW[1] */ PACK( 0, 2 ), - /* PushW[2] */ PACK( 0, 3 ), - /* PushW[3] */ PACK( 0, 4 ), - /* PushW[4] */ PACK( 0, 5 ), - /* PushW[5] */ PACK( 0, 6 ), - /* PushW[6] */ PACK( 0, 7 ), - /* PushW[7] */ PACK( 0, 8 ), - - /* MDRP[00] */ PACK( 1, 0 ), - /* MDRP[01] */ PACK( 1, 0 ), - /* MDRP[02] */ PACK( 1, 0 ), - /* MDRP[03] */ PACK( 1, 0 ), - /* MDRP[04] */ PACK( 1, 0 ), - /* MDRP[05] */ PACK( 1, 0 ), - /* MDRP[06] */ PACK( 1, 0 ), - /* MDRP[07] */ PACK( 1, 0 ), - /* MDRP[08] */ PACK( 1, 0 ), - /* MDRP[09] */ PACK( 1, 0 ), - /* MDRP[10] */ PACK( 1, 0 ), - /* MDRP[11] */ PACK( 1, 0 ), - /* MDRP[12] */ PACK( 1, 0 ), - /* MDRP[13] */ PACK( 1, 0 ), - /* MDRP[14] */ PACK( 1, 0 ), - /* MDRP[15] */ PACK( 1, 0 ), - - /* MDRP[16] */ PACK( 1, 0 ), - /* MDRP[17] */ PACK( 1, 0 ), - /* MDRP[18] */ PACK( 1, 0 ), - /* MDRP[19] */ PACK( 1, 0 ), - /* MDRP[20] */ PACK( 1, 0 ), - /* MDRP[21] */ PACK( 1, 0 ), - /* MDRP[22] */ PACK( 1, 0 ), - /* MDRP[23] */ PACK( 1, 0 ), - /* MDRP[24] */ PACK( 1, 0 ), - /* MDRP[25] */ PACK( 1, 0 ), - /* MDRP[26] */ PACK( 1, 0 ), - /* MDRP[27] */ PACK( 1, 0 ), - /* MDRP[28] */ PACK( 1, 0 ), - /* MDRP[29] */ PACK( 1, 0 ), - /* MDRP[30] */ PACK( 1, 0 ), - /* MDRP[31] */ PACK( 1, 0 ), - - /* MIRP[00] */ PACK( 2, 0 ), - /* MIRP[01] */ PACK( 2, 0 ), - /* MIRP[02] */ PACK( 2, 0 ), - /* MIRP[03] */ PACK( 2, 0 ), - /* MIRP[04] */ PACK( 2, 0 ), - /* MIRP[05] */ PACK( 2, 0 ), - /* MIRP[06] */ PACK( 2, 0 ), - /* MIRP[07] */ PACK( 2, 0 ), - /* MIRP[08] */ PACK( 2, 0 ), - /* MIRP[09] */ PACK( 2, 0 ), - /* MIRP[10] */ PACK( 2, 0 ), - /* MIRP[11] */ PACK( 2, 0 ), - /* MIRP[12] */ PACK( 2, 0 ), - /* MIRP[13] */ PACK( 2, 0 ), - /* MIRP[14] */ PACK( 2, 0 ), - /* MIRP[15] */ PACK( 2, 0 ), - - /* MIRP[16] */ PACK( 2, 0 ), - /* MIRP[17] */ PACK( 2, 0 ), - /* MIRP[18] */ PACK( 2, 0 ), - /* MIRP[19] */ PACK( 2, 0 ), - /* MIRP[20] */ PACK( 2, 0 ), - /* MIRP[21] */ PACK( 2, 0 ), - /* MIRP[22] */ PACK( 2, 0 ), - /* MIRP[23] */ PACK( 2, 0 ), - /* MIRP[24] */ PACK( 2, 0 ), - /* MIRP[25] */ PACK( 2, 0 ), - /* MIRP[26] */ PACK( 2, 0 ), - /* MIRP[27] */ PACK( 2, 0 ), - /* MIRP[28] */ PACK( 2, 0 ), - /* MIRP[29] */ PACK( 2, 0 ), - /* MIRP[30] */ PACK( 2, 0 ), - /* MIRP[31] */ PACK( 2, 0 ) - }; - - -#ifdef FT_DEBUG_LEVEL_TRACE - - /* the first hex digit gives the length of the opcode name; the space */ - /* after the digit is here just to increase readability of the source */ - /* code */ - - static - const char* const opcode_name[256] = - { - "7 SVTCA y", - "7 SVTCA x", - "8 SPvTCA y", - "8 SPvTCA x", - "8 SFvTCA y", - "8 SFvTCA x", - "8 SPvTL ||", - "7 SPvTL +", - "8 SFvTL ||", - "7 SFvTL +", - "5 SPvFS", - "5 SFvFS", - "3 GPv", - "3 GFv", - "6 SFvTPv", - "5 ISECT", - - "4 SRP0", - "4 SRP1", - "4 SRP2", - "4 SZP0", - "4 SZP1", - "4 SZP2", - "4 SZPS", - "5 SLOOP", - "3 RTG", - "4 RTHG", - "3 SMD", - "4 ELSE", - "4 JMPR", - "6 SCvTCi", - "5 SSwCi", - "3 SSW", - - "3 DUP", - "3 POP", - "5 CLEAR", - "4 SWAP", - "5 DEPTH", - "6 CINDEX", - "6 MINDEX", - "8 AlignPTS", - "7 INS_$28", - "3 UTP", - "8 LOOPCALL", - "4 CALL", - "4 FDEF", - "4 ENDF", - "7 MDAP[0]", - "7 MDAP[1]", - - "6 IUP[0]", - "6 IUP[1]", - "6 SHP[0]", - "6 SHP[1]", - "6 SHC[0]", - "6 SHC[1]", - "6 SHZ[0]", - "6 SHZ[1]", - "5 SHPIX", - "2 IP", - "8 MSIRP[0]", - "8 MSIRP[1]", - "7 AlignRP", - "4 RTDG", - "7 MIAP[0]", - "7 MIAP[1]", - - "6 NPushB", - "6 NPushW", - "2 WS", - "2 RS", - "5 WCvtP", - "4 RCvt", - "5 GC[0]", - "5 GC[1]", - "4 SCFS", - "5 MD[0]", - "5 MD[1]", - "5 MPPEM", - "3 MPS", - "6 FlipON", - "7 FlipOFF", - "5 DEBUG", - - "2 LT", - "4 LTEQ", - "2 GT", - "4 GTEQ", - "2 EQ", - "3 NEQ", - "3 ODD", - "4 EVEN", - "2 IF", - "3 EIF", - "3 AND", - "2 OR", - "3 NOT", - "7 DeltaP1", - "3 SDB", - "3 SDS", - - "3 ADD", - "3 SUB", - "3 DIV", - "3 MUL", - "3 ABS", - "3 NEG", - "5 FLOOR", - "7 CEILING", - "8 ROUND[0]", - "8 ROUND[1]", - "8 ROUND[2]", - "8 ROUND[3]", - "9 NROUND[0]", - "9 NROUND[1]", - "9 NROUND[2]", - "9 NROUND[3]", - - "5 WCvtF", - "7 DeltaP2", - "7 DeltaP3", - "A DeltaCn[0]", - "A DeltaCn[1]", - "A DeltaCn[2]", - "6 SROUND", - "8 S45Round", - "4 JROT", - "4 JROF", - "4 ROFF", - "7 INS_$7B", - "4 RUTG", - "4 RDTG", - "5 SANGW", - "2 AA", - - "6 FlipPT", - "8 FlipRgON", - "9 FlipRgOFF", - "7 INS_$83", - "7 INS_$84", - "8 ScanCTRL", - "9 SDPvTL[0]", - "9 SDPvTL[1]", - "7 GetINFO", - "4 IDEF", - "4 ROLL", - "3 MAX", - "3 MIN", - "8 ScanTYPE", - "8 InstCTRL", - "7 INS_$8F", - - "7 INS_$90", - "7 INS_$91", - "7 INS_$92", - "7 INS_$93", - "7 INS_$94", - "7 INS_$95", - "7 INS_$96", - "7 INS_$97", - "7 INS_$98", - "7 INS_$99", - "7 INS_$9A", - "7 INS_$9B", - "7 INS_$9C", - "7 INS_$9D", - "7 INS_$9E", - "7 INS_$9F", - - "7 INS_$A0", - "7 INS_$A1", - "7 INS_$A2", - "7 INS_$A3", - "7 INS_$A4", - "7 INS_$A5", - "7 INS_$A6", - "7 INS_$A7", - "7 INS_$A8", - "7 INS_$A9", - "7 INS_$AA", - "7 INS_$AB", - "7 INS_$AC", - "7 INS_$AD", - "7 INS_$AE", - "7 INS_$AF", - - "8 PushB[0]", - "8 PushB[1]", - "8 PushB[2]", - "8 PushB[3]", - "8 PushB[4]", - "8 PushB[5]", - "8 PushB[6]", - "8 PushB[7]", - "8 PushW[0]", - "8 PushW[1]", - "8 PushW[2]", - "8 PushW[3]", - "8 PushW[4]", - "8 PushW[5]", - "8 PushW[6]", - "8 PushW[7]", - - "8 MDRP[00]", - "8 MDRP[01]", - "8 MDRP[02]", - "8 MDRP[03]", - "8 MDRP[04]", - "8 MDRP[05]", - "8 MDRP[06]", - "8 MDRP[07]", - "8 MDRP[08]", - "8 MDRP[09]", - "8 MDRP[10]", - "8 MDRP[11]", - "8 MDRP[12]", - "8 MDRP[13]", - "8 MDRP[14]", - "8 MDRP[15]", - - "8 MDRP[16]", - "8 MDRP[17]", - "8 MDRP[18]", - "8 MDRP[19]", - "8 MDRP[20]", - "8 MDRP[21]", - "8 MDRP[22]", - "8 MDRP[23]", - "8 MDRP[24]", - "8 MDRP[25]", - "8 MDRP[26]", - "8 MDRP[27]", - "8 MDRP[28]", - "8 MDRP[29]", - "8 MDRP[30]", - "8 MDRP[31]", - - "8 MIRP[00]", - "8 MIRP[01]", - "8 MIRP[02]", - "8 MIRP[03]", - "8 MIRP[04]", - "8 MIRP[05]", - "8 MIRP[06]", - "8 MIRP[07]", - "8 MIRP[08]", - "8 MIRP[09]", - "8 MIRP[10]", - "8 MIRP[11]", - "8 MIRP[12]", - "8 MIRP[13]", - "8 MIRP[14]", - "8 MIRP[15]", - - "8 MIRP[16]", - "8 MIRP[17]", - "8 MIRP[18]", - "8 MIRP[19]", - "8 MIRP[20]", - "8 MIRP[21]", - "8 MIRP[22]", - "8 MIRP[23]", - "8 MIRP[24]", - "8 MIRP[25]", - "8 MIRP[26]", - "8 MIRP[27]", - "8 MIRP[28]", - "8 MIRP[29]", - "8 MIRP[30]", - "8 MIRP[31]" - }; - -#endif /* FT_DEBUG_LEVEL_TRACE */ - - - static - const FT_Char opcode_length[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, 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,-2, 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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17, - - 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, 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 - }; - -#undef PACK - - -#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER - -#if defined( __arm__ ) && \ - ( defined( __thumb2__ ) || !defined( __thumb__ ) ) - -#define TT_MulFix14 TT_MulFix14_arm - - static FT_Int32 - TT_MulFix14_arm( FT_Int32 a, - FT_Int b ) - { - FT_Int32 t, t2; - - -#if defined( __CC_ARM ) || defined( __ARMCC__ ) - - __asm - { - smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ - mov a, t, asr #31 /* a = (hi >> 31) */ - add a, a, #0x2000 /* a += 0x2000 */ - adds t2, t2, a /* t2 += a */ - adc t, t, #0 /* t += carry */ - mov a, t2, lsr #14 /* a = t2 >> 14 */ - orr a, a, t, lsl #18 /* a |= t << 18 */ - } - -#elif defined( __GNUC__ ) - - __asm__ __volatile__ ( - "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ - "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ -#if defined( __clang__ ) && defined( __thumb2__ ) - "add.w %0, %0, #0x2000\n\t" /* %0 += 0x2000 */ -#else - "add %0, %0, #0x2000\n\t" /* %0 += 0x2000 */ -#endif - "adds %1, %1, %0\n\t" /* %1 += %0 */ - "adc %2, %2, #0\n\t" /* %2 += carry */ - "mov %0, %1, lsr #14\n\t" /* %0 = %1 >> 16 */ - "orr %0, %0, %2, lsl #18\n\t" /* %0 |= %2 << 16 */ - : "=r"(a), "=&r"(t2), "=&r"(t) - : "r"(a), "r"(b) - : "cc" ); - -#endif - - return a; - } - -#endif /* __arm__ && ( __thumb2__ || !__thumb__ ) */ - -#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ - - -#if defined( __GNUC__ ) && \ - ( defined( __i386__ ) || defined( __x86_64__ ) ) - -#define TT_MulFix14 TT_MulFix14_long_long - - /* Temporarily disable the warning that C90 doesn't support `long long'. */ -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wlong-long" - - /* This is declared `noinline' because inlining the function results */ - /* in slower code. The `pure' attribute indicates that the result */ - /* only depends on the parameters. */ - static __attribute__(( noinline )) - __attribute__(( pure )) FT_Int32 - TT_MulFix14_long_long( FT_Int32 a, - FT_Int b ) - { - - long long ret = (long long)a * b; - - /* The following line assumes that right shifting of signed values */ - /* will actually preserve the sign bit. The exact behaviour is */ - /* undefined, but this is true on x86 and x86_64. */ - long long tmp = ret >> 63; - - - ret += 0x2000 + tmp; - - return (FT_Int32)( ret >> 14 ); - } - -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic pop -#endif - -#endif /* __GNUC__ && ( __i386__ || __x86_64__ ) */ - - -#ifndef TT_MulFix14 - - /* Compute (a*b)/2^14 with maximum accuracy and rounding. */ - /* This is optimized to be faster than calling FT_MulFix() */ - /* for platforms where sizeof(int) == 2. */ - static FT_Int32 - TT_MulFix14( FT_Int32 a, - FT_Int b ) - { - FT_Int32 sign; - FT_UInt32 ah, al, mid, lo, hi; - - - sign = a ^ b; - - if ( a < 0 ) - a = -a; - if ( b < 0 ) - b = -b; - - ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU ); - al = (FT_UInt32)( a & 0xFFFFU ); - - lo = al * b; - mid = ah * b; - hi = mid >> 16; - mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */ - lo += mid; - if ( lo < mid ) - hi += 1; - - mid = ( lo >> 14 ) | ( hi << 18 ); - - return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid; - } - -#endif /* !TT_MulFix14 */ - - -#if defined( __GNUC__ ) && \ - ( defined( __i386__ ) || \ - defined( __x86_64__ ) || \ - defined( __arm__ ) ) - -#define TT_DotFix14 TT_DotFix14_long_long - -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wlong-long" - - static __attribute__(( pure )) FT_Int32 - TT_DotFix14_long_long( FT_Int32 ax, - FT_Int32 ay, - FT_Int bx, - FT_Int by ) - { - /* Temporarily disable the warning that C90 doesn't support */ - /* `long long'. */ - - long long temp1 = (long long)ax * bx; - long long temp2 = (long long)ay * by; - - - temp1 += temp2; - temp2 = temp1 >> 63; - temp1 += 0x2000 + temp2; - - return (FT_Int32)( temp1 >> 14 ); - - } - -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic pop -#endif - -#endif /* __GNUC__ && (__arm__ || __i386__ || __x86_64__) */ - - -#ifndef TT_DotFix14 - - /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */ - static FT_Int32 - TT_DotFix14( FT_Int32 ax, - FT_Int32 ay, - FT_Int bx, - FT_Int by ) - { - FT_Int32 m, s, hi1, hi2, hi; - FT_UInt32 l, lo1, lo2, lo; - - - /* compute ax*bx as 64-bit value */ - l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx ); - m = ( ax >> 16 ) * bx; - - lo1 = l + ( (FT_UInt32)m << 16 ); - hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l ); - - /* compute ay*by as 64-bit value */ - l = (FT_UInt32)( ( ay & 0xFFFFU ) * by ); - m = ( ay >> 16 ) * by; - - lo2 = l + ( (FT_UInt32)m << 16 ); - hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l ); - - /* add them */ - lo = lo1 + lo2; - hi = hi1 + hi2 + ( lo < lo1 ); - - /* divide the result by 2^14 with rounding */ - s = hi >> 31; - l = lo + (FT_UInt32)s; - hi += s + ( l < lo ); - lo = l; - - l = lo + 0x2000U; - hi += ( l < lo ); - - return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) ); - } - -#endif /* TT_DotFix14 */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Current_Ratio */ - /* */ - /* <Description> */ - /* Returns the current aspect ratio scaling factor depending on the */ - /* projection vector's state and device resolutions. */ - /* */ - /* <Return> */ - /* The aspect ratio in 16.16 format, always <= 1.0 . */ - /* */ - static FT_Long - Current_Ratio( TT_ExecContext exc ) - { - if ( !exc->tt_metrics.ratio ) - { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - exc->tt_metrics.ratio = exc->tt_metrics.x_ratio; - else - exc->tt_metrics.ratio = exc->tt_metrics.y_ratio; - } - else -#endif - { - if ( exc->GS.projVector.y == 0 ) - exc->tt_metrics.ratio = exc->tt_metrics.x_ratio; - - else if ( exc->GS.projVector.x == 0 ) - exc->tt_metrics.ratio = exc->tt_metrics.y_ratio; - - else - { - FT_F26Dot6 x, y; - - - x = TT_MulFix14( exc->tt_metrics.x_ratio, - exc->GS.projVector.x ); - y = TT_MulFix14( exc->tt_metrics.y_ratio, - exc->GS.projVector.y ); - exc->tt_metrics.ratio = FT_Hypot( x, y ); - } - } - } - return exc->tt_metrics.ratio; - } - - - FT_CALLBACK_DEF( FT_Long ) - Current_Ppem( TT_ExecContext exc ) - { - return exc->tt_metrics.ppem; - } - - - FT_CALLBACK_DEF( FT_Long ) - Current_Ppem_Stretched( TT_ExecContext exc ) - { - return FT_MulFix( exc->tt_metrics.ppem, Current_Ratio( exc ) ); - } - - - /*************************************************************************/ - /* */ - /* Functions related to the control value table (CVT). */ - /* */ - /*************************************************************************/ - - - FT_CALLBACK_DEF( FT_F26Dot6 ) - Read_CVT( TT_ExecContext exc, - FT_ULong idx ) - { - return exc->cvt[idx]; - } - - - FT_CALLBACK_DEF( FT_F26Dot6 ) - Read_CVT_Stretched( TT_ExecContext exc, - FT_ULong idx ) - { - return FT_MulFix( exc->cvt[idx], Current_Ratio( exc ) ); - } - - - FT_CALLBACK_DEF( void ) - Write_CVT( TT_ExecContext exc, - FT_ULong idx, - FT_F26Dot6 value ) - { - exc->cvt[idx] = value; - } - - - FT_CALLBACK_DEF( void ) - Write_CVT_Stretched( TT_ExecContext exc, - FT_ULong idx, - FT_F26Dot6 value ) - { - exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) ); - } - - - FT_CALLBACK_DEF( void ) - Move_CVT( TT_ExecContext exc, - FT_ULong idx, - FT_F26Dot6 value ) - { - exc->cvt[idx] += value; - } - - - FT_CALLBACK_DEF( void ) - Move_CVT_Stretched( TT_ExecContext exc, - FT_ULong idx, - FT_F26Dot6 value ) - { - exc->cvt[idx] += FT_DivFix( value, Current_Ratio( exc ) ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* GetShortIns */ - /* */ - /* <Description> */ - /* Returns a short integer taken from the instruction stream at */ - /* address IP. */ - /* */ - /* <Return> */ - /* Short read at code[IP]. */ - /* */ - /* <Note> */ - /* This one could become a macro. */ - /* */ - static FT_Short - GetShortIns( TT_ExecContext exc ) - { - /* Reading a byte stream so there is no endianess (DaveP) */ - exc->IP += 2; - return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) + - exc->code[exc->IP - 1] ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Ins_Goto_CodeRange */ - /* */ - /* <Description> */ - /* Goes to a certain code range in the instruction stream. */ - /* */ - /* <Input> */ - /* aRange :: The index of the code range. */ - /* */ - /* aIP :: The new IP address in the code range. */ - /* */ - /* <Return> */ - /* SUCCESS or FAILURE. */ - /* */ - static FT_Bool - Ins_Goto_CodeRange( TT_ExecContext exc, - FT_Int aRange, - FT_Long aIP ) - { - TT_CodeRange* range; - - - if ( aRange < 1 || aRange > 3 ) - { - exc->error = FT_THROW( Bad_Argument ); - return FAILURE; - } - - range = &exc->codeRangeTable[aRange - 1]; - - if ( range->base == NULL ) /* invalid coderange */ - { - exc->error = FT_THROW( Invalid_CodeRange ); - return FAILURE; - } - - /* NOTE: Because the last instruction of a program may be a CALL */ - /* which will return to the first byte *after* the code */ - /* range, we test for aIP <= Size, instead of aIP < Size. */ - - if ( aIP > range->size ) - { - exc->error = FT_THROW( Code_Overflow ); - return FAILURE; - } - - exc->code = range->base; - exc->codeSize = range->size; - exc->IP = aIP; - exc->curRange = aRange; - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Direct_Move */ - /* */ - /* <Description> */ - /* Moves a point by a given distance along the freedom vector. The */ - /* point will be `touched'. */ - /* */ - /* <Input> */ - /* point :: The index of the point to move. */ - /* */ - /* distance :: The distance to apply. */ - /* */ - /* <InOut> */ - /* zone :: The affected glyph zone. */ - /* */ - static void - Direct_Move( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ) - { - FT_F26Dot6 v; - - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_ASSERT( !exc->face->unpatented_hinting ); -#endif - - v = exc->GS.freeVector.x; - - if ( v != 0 ) - { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( !SUBPIXEL_HINTING || - ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); - - zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; - } - - v = exc->GS.freeVector.y; - - if ( v != 0 ) - { - zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); - - zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; - } - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Direct_Move_Orig */ - /* */ - /* <Description> */ - /* Moves the *original* position of a point by a given distance along */ - /* the freedom vector. Obviously, the point will not be `touched'. */ - /* */ - /* <Input> */ - /* point :: The index of the point to move. */ - /* */ - /* distance :: The distance to apply. */ - /* */ - /* <InOut> */ - /* zone :: The affected glyph zone. */ - /* */ - static void - Direct_Move_Orig( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ) - { - FT_F26Dot6 v; - - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_ASSERT( !exc->face->unpatented_hinting ); -#endif - - v = exc->GS.freeVector.x; - - if ( v != 0 ) - zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); - - v = exc->GS.freeVector.y; - - if ( v != 0 ) - zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); - } - - - /*************************************************************************/ - /* */ - /* Special versions of Direct_Move() */ - /* */ - /* The following versions are used whenever both vectors are both */ - /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ - /* */ - /*************************************************************************/ - - - static void - Direct_Move_X( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ) - { - FT_UNUSED( exc ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( !SUBPIXEL_HINTING || - !exc->ignore_x_mode ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += distance; - - zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; - } - - - static void - Direct_Move_Y( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ) - { - FT_UNUSED( exc ); - - zone->cur[point].y += distance; - zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; - } - - - /*************************************************************************/ - /* */ - /* Special versions of Direct_Move_Orig() */ - /* */ - /* The following versions are used whenever both vectors are both */ - /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ - /* */ - /*************************************************************************/ - - - static void - Direct_Move_Orig_X( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ) - { - FT_UNUSED( exc ); - - zone->org[point].x += distance; - } - - - static void - Direct_Move_Orig_Y( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ) - { - FT_UNUSED( exc ); - - zone->org[point].y += distance; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_None */ - /* */ - /* <Description> */ - /* Does not round, but adds engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance (not) to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* The compensated distance. */ - /* */ - /* <Note> */ - /* The TrueType specification says very few about the relationship */ - /* between rounding and engine compensation. However, it seems from */ - /* the description of super round that we should add the compensation */ - /* before rounding. */ - /* */ - static FT_F26Dot6 - Round_None( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - FT_UNUSED( exc ); - - - if ( distance >= 0 ) - { - val = distance + compensation; - if ( val < 0 ) - val = 0; - } - else - { - val = distance - compensation; - if ( val > 0 ) - val = 0; - } - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_To_Grid */ - /* */ - /* <Description> */ - /* Rounds value to grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - static FT_F26Dot6 - Round_To_Grid( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - FT_UNUSED( exc ); - - - if ( distance >= 0 ) - { - val = FT_PIX_ROUND( distance + compensation ); - if ( val < 0 ) - val = 0; - } - else - { - val = -FT_PIX_ROUND( compensation - distance ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_To_Half_Grid */ - /* */ - /* <Description> */ - /* Rounds value to half grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - static FT_F26Dot6 - Round_To_Half_Grid( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - FT_UNUSED( exc ); - - - if ( distance >= 0 ) - { - val = FT_PIX_FLOOR( distance + compensation ) + 32; - if ( val < 0 ) - val = 32; - } - else - { - val = -( FT_PIX_FLOOR( compensation - distance ) + 32 ); - if ( val > 0 ) - val = -32; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_Down_To_Grid */ - /* */ - /* <Description> */ - /* Rounds value down to grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - static FT_F26Dot6 - Round_Down_To_Grid( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - FT_UNUSED( exc ); - - - if ( distance >= 0 ) - { - val = FT_PIX_FLOOR( distance + compensation ); - if ( val < 0 ) - val = 0; - } - else - { - val = -FT_PIX_FLOOR( compensation - distance ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_Up_To_Grid */ - /* */ - /* <Description> */ - /* Rounds value up to grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - static FT_F26Dot6 - Round_Up_To_Grid( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - FT_UNUSED( exc ); - - - if ( distance >= 0 ) - { - val = FT_PIX_CEIL( distance + compensation ); - if ( val < 0 ) - val = 0; - } - else - { - val = -FT_PIX_CEIL( compensation - distance ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_To_Double_Grid */ - /* */ - /* <Description> */ - /* Rounds value to double grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - static FT_F26Dot6 - Round_To_Double_Grid( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - FT_UNUSED( exc ); - - - if ( distance >= 0 ) - { - val = FT_PAD_ROUND( distance + compensation, 32 ); - if ( val < 0 ) - val = 0; - } - else - { - val = -FT_PAD_ROUND( compensation - distance, 32 ); - if ( val > 0 ) - val = 0; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_Super */ - /* */ - /* <Description> */ - /* Super-rounds value to grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - /* <Note> */ - /* The TrueType specification says very few about the relationship */ - /* between rounding and engine compensation. However, it seems from */ - /* the description of super round that we should add the compensation */ - /* before rounding. */ - /* */ - static FT_F26Dot6 - Round_Super( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = ( distance - exc->phase + exc->threshold + compensation ) & - -exc->period; - val += exc->phase; - if ( val < 0 ) - val = exc->phase; - } - else - { - val = -( ( exc->threshold - exc->phase - distance + compensation ) & - -exc->period ); - val -= exc->phase; - if ( val > 0 ) - val = -exc->phase; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Round_Super_45 */ - /* */ - /* <Description> */ - /* Super-rounds value to grid after adding engine compensation. */ - /* */ - /* <Input> */ - /* distance :: The distance to round. */ - /* */ - /* compensation :: The engine compensation. */ - /* */ - /* <Return> */ - /* Rounded distance. */ - /* */ - /* <Note> */ - /* There is a separate function for Round_Super_45() as we may need */ - /* greater precision. */ - /* */ - static FT_F26Dot6 - Round_Super_45( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ) - { - FT_F26Dot6 val; - - - if ( distance >= 0 ) - { - val = ( ( distance - exc->phase + exc->threshold + compensation ) / - exc->period ) * exc->period; - val += exc->phase; - if ( val < 0 ) - val = exc->phase; - } - else - { - val = -( ( ( exc->threshold - exc->phase - distance + compensation ) / - exc->period ) * exc->period ); - val -= exc->phase; - if ( val > 0 ) - val = -exc->phase; - } - - return val; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Compute_Round */ - /* */ - /* <Description> */ - /* Sets the rounding mode. */ - /* */ - /* <Input> */ - /* round_mode :: The rounding mode to be used. */ - /* */ - static void - Compute_Round( TT_ExecContext exc, - FT_Byte round_mode ) - { - switch ( round_mode ) - { - case TT_Round_Off: - exc->func_round = (TT_Round_Func)Round_None; - break; - - case TT_Round_To_Grid: - exc->func_round = (TT_Round_Func)Round_To_Grid; - break; - - case TT_Round_Up_To_Grid: - exc->func_round = (TT_Round_Func)Round_Up_To_Grid; - break; - - case TT_Round_Down_To_Grid: - exc->func_round = (TT_Round_Func)Round_Down_To_Grid; - break; - - case TT_Round_To_Half_Grid: - exc->func_round = (TT_Round_Func)Round_To_Half_Grid; - break; - - case TT_Round_To_Double_Grid: - exc->func_round = (TT_Round_Func)Round_To_Double_Grid; - break; - - case TT_Round_Super: - exc->func_round = (TT_Round_Func)Round_Super; - break; - - case TT_Round_Super_45: - exc->func_round = (TT_Round_Func)Round_Super_45; - break; - } - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* SetSuperRound */ - /* */ - /* <Description> */ - /* Sets Super Round parameters. */ - /* */ - /* <Input> */ - /* GridPeriod :: The grid period. */ - /* */ - /* selector :: The SROUND opcode. */ - /* */ - static void - SetSuperRound( TT_ExecContext exc, - FT_F2Dot14 GridPeriod, - FT_Long selector ) - { - switch ( (FT_Int)( selector & 0xC0 ) ) - { - case 0: - exc->period = GridPeriod / 2; - break; - - case 0x40: - exc->period = GridPeriod; - break; - - case 0x80: - exc->period = GridPeriod * 2; - break; - - /* This opcode is reserved, but... */ - case 0xC0: - exc->period = GridPeriod; - break; - } - - switch ( (FT_Int)( selector & 0x30 ) ) - { - case 0: - exc->phase = 0; - break; - - case 0x10: - exc->phase = exc->period / 4; - break; - - case 0x20: - exc->phase = exc->period / 2; - break; - - case 0x30: - exc->phase = exc->period * 3 / 4; - break; - } - - if ( ( selector & 0x0F ) == 0 ) - exc->threshold = exc->period - 1; - else - exc->threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * exc->period / 8; - - /* convert to F26Dot6 format */ - exc->period >>= 8; - exc->phase >>= 8; - exc->threshold >>= 8; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Project */ - /* */ - /* <Description> */ - /* Computes the projection of vector given by (v2-v1) along the */ - /* current projection vector. */ - /* */ - /* <Input> */ - /* v1 :: First input vector. */ - /* v2 :: Second input vector. */ - /* */ - /* <Return> */ - /* The distance in F26dot6 format. */ - /* */ - static FT_F26Dot6 - Project( TT_ExecContext exc, - FT_Pos dx, - FT_Pos dy ) - { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_ASSERT( !exc->face->unpatented_hinting ); -#endif - - return TT_DotFix14( dx, dy, - exc->GS.projVector.x, - exc->GS.projVector.y ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Dual_Project */ - /* */ - /* <Description> */ - /* Computes the projection of the vector given by (v2-v1) along the */ - /* current dual vector. */ - /* */ - /* <Input> */ - /* v1 :: First input vector. */ - /* v2 :: Second input vector. */ - /* */ - /* <Return> */ - /* The distance in F26dot6 format. */ - /* */ - static FT_F26Dot6 - Dual_Project( TT_ExecContext exc, - FT_Pos dx, - FT_Pos dy ) - { - return TT_DotFix14( dx, dy, - exc->GS.dualVector.x, - exc->GS.dualVector.y ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Project_x */ - /* */ - /* <Description> */ - /* Computes the projection of the vector given by (v2-v1) along the */ - /* horizontal axis. */ - /* */ - /* <Input> */ - /* v1 :: First input vector. */ - /* v2 :: Second input vector. */ - /* */ - /* <Return> */ - /* The distance in F26dot6 format. */ - /* */ - static FT_F26Dot6 - Project_x( TT_ExecContext exc, - FT_Pos dx, - FT_Pos dy ) - { - FT_UNUSED( exc ); - FT_UNUSED( dy ); - - return dx; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Project_y */ - /* */ - /* <Description> */ - /* Computes the projection of the vector given by (v2-v1) along the */ - /* vertical axis. */ - /* */ - /* <Input> */ - /* v1 :: First input vector. */ - /* v2 :: Second input vector. */ - /* */ - /* <Return> */ - /* The distance in F26dot6 format. */ - /* */ - static FT_F26Dot6 - Project_y( TT_ExecContext exc, - FT_Pos dx, - FT_Pos dy ) - { - FT_UNUSED( exc ); - FT_UNUSED( dx ); - - return dy; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Compute_Funcs */ - /* */ - /* <Description> */ - /* Computes the projection and movement function pointers according */ - /* to the current graphics state. */ - /* */ - static void - Compute_Funcs( TT_ExecContext exc ) - { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - /* If both vectors point rightwards along the x axis, set */ - /* `both-x-axis' true, otherwise set it false. The x values only */ - /* need be tested because the vector has been normalised to a unit */ - /* vector of length 0x4000 = unity. */ - exc->GS.both_x_axis = (FT_Bool)( exc->GS.projVector.x == 0x4000 && - exc->GS.freeVector.x == 0x4000 ); - - /* Throw away projection and freedom vector information */ - /* because the patents don't allow them to be stored. */ - /* The relevant US Patents are 5155805 and 5325479. */ - exc->GS.projVector.x = 0; - exc->GS.projVector.y = 0; - exc->GS.freeVector.x = 0; - exc->GS.freeVector.y = 0; - - if ( exc->GS.both_x_axis ) - { - exc->func_project = Project_x; - exc->func_move = Direct_Move_X; - exc->func_move_orig = Direct_Move_Orig_X; - } - else - { - exc->func_project = Project_y; - exc->func_move = Direct_Move_Y; - exc->func_move_orig = Direct_Move_Orig_Y; - } - - if ( exc->GS.dualVector.x == 0x4000 ) - exc->func_dualproj = Project_x; - else if ( exc->GS.dualVector.y == 0x4000 ) - exc->func_dualproj = Project_y; - else - exc->func_dualproj = Dual_Project; - - /* Force recalculation of cached aspect ratio */ - exc->tt_metrics.ratio = 0; - - return; - } -#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ - - if ( exc->GS.freeVector.x == 0x4000 ) - exc->F_dot_P = exc->GS.projVector.x; - else if ( exc->GS.freeVector.y == 0x4000 ) - exc->F_dot_P = exc->GS.projVector.y; - else - exc->F_dot_P = - ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x + - (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14; - - if ( exc->GS.projVector.x == 0x4000 ) - exc->func_project = (TT_Project_Func)Project_x; - else if ( exc->GS.projVector.y == 0x4000 ) - exc->func_project = (TT_Project_Func)Project_y; - else - exc->func_project = (TT_Project_Func)Project; - - if ( exc->GS.dualVector.x == 0x4000 ) - exc->func_dualproj = (TT_Project_Func)Project_x; - else if ( exc->GS.dualVector.y == 0x4000 ) - exc->func_dualproj = (TT_Project_Func)Project_y; - else - exc->func_dualproj = (TT_Project_Func)Dual_Project; - - exc->func_move = (TT_Move_Func)Direct_Move; - exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig; - - if ( exc->F_dot_P == 0x4000L ) - { - if ( exc->GS.freeVector.x == 0x4000 ) - { - exc->func_move = (TT_Move_Func)Direct_Move_X; - exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X; - } - else if ( exc->GS.freeVector.y == 0x4000 ) - { - exc->func_move = (TT_Move_Func)Direct_Move_Y; - exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y; - } - } - - /* at small sizes, F_dot_P can become too small, resulting */ - /* in overflows and `spikes' in a number of glyphs like `w'. */ - - if ( FT_ABS( exc->F_dot_P ) < 0x400L ) - exc->F_dot_P = 0x4000L; - - /* Disable cached aspect ratio */ - exc->tt_metrics.ratio = 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Normalize */ - /* */ - /* <Description> */ - /* Norms a vector. */ - /* */ - /* <Input> */ - /* Vx :: The horizontal input vector coordinate. */ - /* Vy :: The vertical input vector coordinate. */ - /* */ - /* <Output> */ - /* R :: The normed unit vector. */ - /* */ - /* <Return> */ - /* Returns FAILURE if a vector parameter is zero. */ - /* */ - /* <Note> */ - /* In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and */ - /* R is undefined. */ - /* */ - static FT_Bool - Normalize( FT_F26Dot6 Vx, - FT_F26Dot6 Vy, - FT_UnitVector* R ) - { - FT_Vector V; - - - if ( Vx == 0 && Vy == 0 ) - { - /* XXX: UNDOCUMENTED! It seems that it is possible to try */ - /* to normalize the vector (0,0). Return immediately. */ - return SUCCESS; - } - - V.x = Vx; - V.y = Vy; - - FT_Vector_NormLen( &V ); - - R->x = (FT_F2Dot14)( V.x / 4 ); - R->y = (FT_F2Dot14)( V.y / 4 ); - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* Here we start with the implementation of the various opcodes. */ - /* */ - /*************************************************************************/ - - -#define ARRAY_BOUND_ERROR \ - do \ - { \ - exc->error = FT_THROW( Invalid_Reference ); \ - return; \ - } while (0) - - - /*************************************************************************/ - /* */ - /* MPPEM[]: Measure Pixel Per EM */ - /* Opcode range: 0x4B */ - /* Stack: --> Euint16 */ - /* */ - static void - Ins_MPPEM( TT_ExecContext exc, - FT_Long* args ) - { - args[0] = exc->func_cur_ppem( exc ); - } - - - /*************************************************************************/ - /* */ - /* MPS[]: Measure Point Size */ - /* Opcode range: 0x4C */ - /* Stack: --> Euint16 */ - /* */ - static void - Ins_MPS( TT_ExecContext exc, - FT_Long* args ) - { - /* Note: The point size should be irrelevant in a given font program; */ - /* we thus decide to return only the PPEM value. */ -#if 0 - args[0] = exc->metrics.pointSize; -#else - args[0] = exc->func_cur_ppem( exc ); -#endif - } - - - /*************************************************************************/ - /* */ - /* DUP[]: DUPlicate the stack's top element */ - /* Opcode range: 0x20 */ - /* Stack: StkElt --> StkElt StkElt */ - /* */ - static void - Ins_DUP( FT_Long* args ) - { - args[1] = args[0]; - } - - - /*************************************************************************/ - /* */ - /* POP[]: POP the stack's top element */ - /* Opcode range: 0x21 */ - /* Stack: StkElt --> */ - /* */ - static void - Ins_POP( void ) - { - /* nothing to do */ - } - - - /*************************************************************************/ - /* */ - /* CLEAR[]: CLEAR the entire stack */ - /* Opcode range: 0x22 */ - /* Stack: StkElt... --> */ - /* */ - static void - Ins_CLEAR( TT_ExecContext exc ) - { - exc->new_top = 0; - } - - - /*************************************************************************/ - /* */ - /* SWAP[]: SWAP the stack's top two elements */ - /* Opcode range: 0x23 */ - /* Stack: 2 * StkElt --> 2 * StkElt */ - /* */ - static void - Ins_SWAP( FT_Long* args ) - { - FT_Long L; - - - L = args[0]; - args[0] = args[1]; - args[1] = L; - } - - - /*************************************************************************/ - /* */ - /* DEPTH[]: return the stack DEPTH */ - /* Opcode range: 0x24 */ - /* Stack: --> uint32 */ - /* */ - static void - Ins_DEPTH( TT_ExecContext exc, - FT_Long* args ) - { - args[0] = exc->top; - } - - - /*************************************************************************/ - /* */ - /* LT[]: Less Than */ - /* Opcode range: 0x50 */ - /* Stack: int32? int32? --> bool */ - /* */ - static void - Ins_LT( FT_Long* args ) - { - args[0] = ( args[0] < args[1] ); - } - - - /*************************************************************************/ - /* */ - /* LTEQ[]: Less Than or EQual */ - /* Opcode range: 0x51 */ - /* Stack: int32? int32? --> bool */ - /* */ - static void - Ins_LTEQ( FT_Long* args ) - { - args[0] = ( args[0] <= args[1] ); - } - - - /*************************************************************************/ - /* */ - /* GT[]: Greater Than */ - /* Opcode range: 0x52 */ - /* Stack: int32? int32? --> bool */ - /* */ - static void - Ins_GT( FT_Long* args ) - { - args[0] = ( args[0] > args[1] ); - } - - - /*************************************************************************/ - /* */ - /* GTEQ[]: Greater Than or EQual */ - /* Opcode range: 0x53 */ - /* Stack: int32? int32? --> bool */ - /* */ - static void - Ins_GTEQ( FT_Long* args ) - { - args[0] = ( args[0] >= args[1] ); - } - - - /*************************************************************************/ - /* */ - /* EQ[]: EQual */ - /* Opcode range: 0x54 */ - /* Stack: StkElt StkElt --> bool */ - /* */ - static void - Ins_EQ( FT_Long* args ) - { - args[0] = ( args[0] == args[1] ); - } - - - /*************************************************************************/ - /* */ - /* NEQ[]: Not EQual */ - /* Opcode range: 0x55 */ - /* Stack: StkElt StkElt --> bool */ - /* */ - static void - Ins_NEQ( FT_Long* args ) - { - args[0] = ( args[0] != args[1] ); - } - - - /*************************************************************************/ - /* */ - /* ODD[]: Is ODD */ - /* Opcode range: 0x56 */ - /* Stack: f26.6 --> bool */ - /* */ - static void - Ins_ODD( TT_ExecContext exc, - FT_Long* args ) - { - args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 64 ); - } - - - /*************************************************************************/ - /* */ - /* EVEN[]: Is EVEN */ - /* Opcode range: 0x57 */ - /* Stack: f26.6 --> bool */ - /* */ - static void - Ins_EVEN( TT_ExecContext exc, - FT_Long* args ) - { - args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 0 ); - } - - - /*************************************************************************/ - /* */ - /* AND[]: logical AND */ - /* Opcode range: 0x5A */ - /* Stack: uint32 uint32 --> uint32 */ - /* */ - static void - Ins_AND( FT_Long* args ) - { - args[0] = ( args[0] && args[1] ); - } - - - /*************************************************************************/ - /* */ - /* OR[]: logical OR */ - /* Opcode range: 0x5B */ - /* Stack: uint32 uint32 --> uint32 */ - /* */ - static void - Ins_OR( FT_Long* args ) - { - args[0] = ( args[0] || args[1] ); - } - - - /*************************************************************************/ - /* */ - /* NOT[]: logical NOT */ - /* Opcode range: 0x5C */ - /* Stack: StkElt --> uint32 */ - /* */ - static void - Ins_NOT( FT_Long* args ) - { - args[0] = !args[0]; - } - - - /*************************************************************************/ - /* */ - /* ADD[]: ADD */ - /* Opcode range: 0x60 */ - /* Stack: f26.6 f26.6 --> f26.6 */ - /* */ - static void - Ins_ADD( FT_Long* args ) - { - args[0] += args[1]; - } - - - /*************************************************************************/ - /* */ - /* SUB[]: SUBtract */ - /* Opcode range: 0x61 */ - /* Stack: f26.6 f26.6 --> f26.6 */ - /* */ - static void - Ins_SUB( FT_Long* args ) - { - args[0] -= args[1]; - } - - - /*************************************************************************/ - /* */ - /* DIV[]: DIVide */ - /* Opcode range: 0x62 */ - /* Stack: f26.6 f26.6 --> f26.6 */ - /* */ - static void - Ins_DIV( TT_ExecContext exc, - FT_Long* args ) - { - if ( args[1] == 0 ) - exc->error = FT_THROW( Divide_By_Zero ); - else - args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] ); - } - - - /*************************************************************************/ - /* */ - /* MUL[]: MULtiply */ - /* Opcode range: 0x63 */ - /* Stack: f26.6 f26.6 --> f26.6 */ - /* */ - static void - Ins_MUL( FT_Long* args ) - { - args[0] = FT_MulDiv( args[0], args[1], 64L ); - } - - - /*************************************************************************/ - /* */ - /* ABS[]: ABSolute value */ - /* Opcode range: 0x64 */ - /* Stack: f26.6 --> f26.6 */ - /* */ - static void - Ins_ABS( FT_Long* args ) - { - args[0] = FT_ABS( args[0] ); - } - - - /*************************************************************************/ - /* */ - /* NEG[]: NEGate */ - /* Opcode range: 0x65 */ - /* Stack: f26.6 --> f26.6 */ - /* */ - static void - Ins_NEG( FT_Long* args ) - { - args[0] = -args[0]; - } - - - /*************************************************************************/ - /* */ - /* FLOOR[]: FLOOR */ - /* Opcode range: 0x66 */ - /* Stack: f26.6 --> f26.6 */ - /* */ - static void - Ins_FLOOR( FT_Long* args ) - { - args[0] = FT_PIX_FLOOR( args[0] ); - } - - - /*************************************************************************/ - /* */ - /* CEILING[]: CEILING */ - /* Opcode range: 0x67 */ - /* Stack: f26.6 --> f26.6 */ - /* */ - static void - Ins_CEILING( FT_Long* args ) - { - args[0] = FT_PIX_CEIL( args[0] ); - } - - - /*************************************************************************/ - /* */ - /* RS[]: Read Store */ - /* Opcode range: 0x43 */ - /* Stack: uint32 --> uint32 */ - /* */ - static void - Ins_RS( TT_ExecContext exc, - FT_Long* args ) - { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->storeSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - else - args[0] = 0; - } - else - { - /* subpixel hinting - avoid Typeman Dstroke and */ - /* IStroke and Vacuform rounds */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - ( ( I == 24 && - ( exc->face->sph_found_func_flags & - ( SPH_FDEF_SPACING_1 | - SPH_FDEF_SPACING_2 ) ) ) || - ( I == 22 && - ( exc->sph_in_func_flags & - SPH_FDEF_TYPEMAN_STROKES ) ) || - ( I == 8 && - ( exc->face->sph_found_func_flags & - SPH_FDEF_VACUFORM_ROUND_1 ) && - exc->iup_called ) ) ) - args[0] = 0; - else - args[0] = exc->storage[I]; - } - -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->storeSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - else - args[0] = 0; - } - else - args[0] = exc->storage[I]; - -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - } - - - /*************************************************************************/ - /* */ - /* WS[]: Write Store */ - /* Opcode range: 0x42 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_WS( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->storeSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - } - else - exc->storage[I] = args[1]; - } - - - /*************************************************************************/ - /* */ - /* WCVTP[]: Write CVT in Pixel units */ - /* Opcode range: 0x44 */ - /* Stack: f26.6 uint32 --> */ - /* */ - static void - Ins_WCVTP( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->cvtSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - } - else - exc->func_write_cvt( exc, I, args[1] ); - } - - - /*************************************************************************/ - /* */ - /* WCVTF[]: Write CVT in Funits */ - /* Opcode range: 0x70 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_WCVTF( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->cvtSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - } - else - exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale ); - } - - - /*************************************************************************/ - /* */ - /* RCVT[]: Read CVT */ - /* Opcode range: 0x45 */ - /* Stack: uint32 --> f26.6 */ - /* */ - static void - Ins_RCVT( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong I = (FT_ULong)args[0]; - - - if ( BOUNDSL( I, exc->cvtSize ) ) - { - if ( exc->pedantic_hinting ) - ARRAY_BOUND_ERROR; - else - args[0] = 0; - } - else - args[0] = exc->func_read_cvt( exc, I ); - } - - - /*************************************************************************/ - /* */ - /* AA[]: Adjust Angle */ - /* Opcode range: 0x7F */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_AA( void ) - { - /* intentionally no longer supported */ - } - - - /*************************************************************************/ - /* */ - /* DEBUG[]: DEBUG. Unsupported. */ - /* Opcode range: 0x4F */ - /* Stack: uint32 --> */ - /* */ - /* Note: The original instruction pops a value from the stack. */ - /* */ - static void - Ins_DEBUG( TT_ExecContext exc ) - { - exc->error = FT_THROW( Debug_OpCode ); - } - - - /*************************************************************************/ - /* */ - /* ROUND[ab]: ROUND value */ - /* Opcode range: 0x68-0x6B */ - /* Stack: f26.6 --> f26.6 */ - /* */ - static void - Ins_ROUND( TT_ExecContext exc, - FT_Long* args ) - { - args[0] = exc->func_round( - exc, - args[0], - exc->tt_metrics.compensations[exc->opcode - 0x68] ); - } - - - /*************************************************************************/ - /* */ - /* NROUND[ab]: No ROUNDing of value */ - /* Opcode range: 0x6C-0x6F */ - /* Stack: f26.6 --> f26.6 */ - /* */ - static void - Ins_NROUND( TT_ExecContext exc, - FT_Long* args ) - { - args[0] = Round_None( - exc, - args[0], - exc->tt_metrics.compensations[exc->opcode - 0x6C] ); - } - - - /*************************************************************************/ - /* */ - /* MAX[]: MAXimum */ - /* Opcode range: 0x68 */ - /* Stack: int32? int32? --> int32 */ - /* */ - static void - Ins_MAX( FT_Long* args ) - { - if ( args[1] > args[0] ) - args[0] = args[1]; - } - - - /*************************************************************************/ - /* */ - /* MIN[]: MINimum */ - /* Opcode range: 0x69 */ - /* Stack: int32? int32? --> int32 */ - /* */ - static void - Ins_MIN( FT_Long* args ) - { - if ( args[1] < args[0] ) - args[0] = args[1]; - } - - - /*************************************************************************/ - /* */ - /* MINDEX[]: Move INDEXed element */ - /* Opcode range: 0x26 */ - /* Stack: int32? --> StkElt */ - /* */ - static void - Ins_MINDEX( TT_ExecContext exc, - FT_Long* args ) - { - FT_Long L, K; - - - L = args[0]; - - if ( L <= 0 || L > exc->args ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - } - else - { - K = exc->stack[exc->args - L]; - - FT_ARRAY_MOVE( &exc->stack[exc->args - L ], - &exc->stack[exc->args - L + 1], - ( L - 1 ) ); - - exc->stack[exc->args - 1] = K; - } - } - - - /*************************************************************************/ - /* */ - /* CINDEX[]: Copy INDEXed element */ - /* Opcode range: 0x25 */ - /* Stack: int32 --> StkElt */ - /* */ - static void - Ins_CINDEX( TT_ExecContext exc, - FT_Long* args ) - { - FT_Long L; - - - L = args[0]; - - if ( L <= 0 || L > exc->args ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - args[0] = 0; - } - else - args[0] = exc->stack[exc->args - L]; - } - - - /*************************************************************************/ - /* */ - /* ROLL[]: ROLL top three elements */ - /* Opcode range: 0x8A */ - /* Stack: 3 * StkElt --> 3 * StkElt */ - /* */ - static void - Ins_ROLL( FT_Long* args ) - { - FT_Long A, B, C; - - - A = args[2]; - B = args[1]; - C = args[0]; - - args[2] = C; - args[1] = A; - args[0] = B; - } - - - /*************************************************************************/ - /* */ - /* MANAGING THE FLOW OF CONTROL */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* SLOOP[]: Set LOOP variable */ - /* Opcode range: 0x17 */ - /* Stack: int32? --> */ - /* */ - static void - Ins_SLOOP( TT_ExecContext exc, - FT_Long* args ) - { - if ( args[0] < 0 ) - exc->error = FT_THROW( Bad_Argument ); - else - exc->GS.loop = args[0]; - } - - - static FT_Bool - SkipCode( TT_ExecContext exc ) - { - exc->IP += exc->length; - - if ( exc->IP < exc->codeSize ) - { - exc->opcode = exc->code[exc->IP]; - - exc->length = opcode_length[exc->opcode]; - if ( exc->length < 0 ) - { - if ( exc->IP + 1 >= exc->codeSize ) - goto Fail_Overflow; - exc->length = 2 - exc->length * exc->code[exc->IP + 1]; - } - - if ( exc->IP + exc->length <= exc->codeSize ) - return SUCCESS; - } - - Fail_Overflow: - exc->error = FT_THROW( Code_Overflow ); - return FAILURE; - } - - - /*************************************************************************/ - /* */ - /* IF[]: IF test */ - /* Opcode range: 0x58 */ - /* Stack: StkElt --> */ - /* */ - static void - Ins_IF( TT_ExecContext exc, - FT_Long* args ) - { - FT_Int nIfs; - FT_Bool Out; - - - if ( args[0] != 0 ) - return; - - nIfs = 1; - Out = 0; - - do - { - if ( SkipCode( exc ) == FAILURE ) - return; - - switch ( exc->opcode ) - { - case 0x58: /* IF */ - nIfs++; - break; - - case 0x1B: /* ELSE */ - Out = FT_BOOL( nIfs == 1 ); - break; - - case 0x59: /* EIF */ - nIfs--; - Out = FT_BOOL( nIfs == 0 ); - break; - } - } while ( Out == 0 ); - } - - - /*************************************************************************/ - /* */ - /* ELSE[]: ELSE */ - /* Opcode range: 0x1B */ - /* Stack: --> */ - /* */ - static void - Ins_ELSE( TT_ExecContext exc ) - { - FT_Int nIfs; - - - nIfs = 1; - - do - { - if ( SkipCode( exc ) == FAILURE ) - return; - - switch ( exc->opcode ) - { - case 0x58: /* IF */ - nIfs++; - break; - - case 0x59: /* EIF */ - nIfs--; - break; - } - } while ( nIfs != 0 ); - } - - - /*************************************************************************/ - /* */ - /* EIF[]: End IF */ - /* Opcode range: 0x59 */ - /* Stack: --> */ - /* */ - static void - Ins_EIF( void ) - { - /* nothing to do */ - } - - - /*************************************************************************/ - /* */ - /* JMPR[]: JuMP Relative */ - /* Opcode range: 0x1C */ - /* Stack: int32 --> */ - /* */ - static void - Ins_JMPR( TT_ExecContext exc, - FT_Long* args ) - { - if ( args[0] == 0 && exc->args == 0 ) - exc->error = FT_THROW( Bad_Argument ); - exc->IP += args[0]; - if ( exc->IP < 0 || - ( exc->callTop > 0 && - exc->IP > exc->callStack[exc->callTop - 1].Def->end ) ) - exc->error = FT_THROW( Bad_Argument ); - exc->step_ins = FALSE; - } - - - /*************************************************************************/ - /* */ - /* JROT[]: Jump Relative On True */ - /* Opcode range: 0x78 */ - /* Stack: StkElt int32 --> */ - /* */ - static void - Ins_JROT( TT_ExecContext exc, - FT_Long* args ) - { - if ( args[1] != 0 ) - Ins_JMPR( exc, args ); - } - - - /*************************************************************************/ - /* */ - /* JROF[]: Jump Relative On False */ - /* Opcode range: 0x79 */ - /* Stack: StkElt int32 --> */ - /* */ - static void - Ins_JROF( TT_ExecContext exc, - FT_Long* args ) - { - if ( args[1] == 0 ) - Ins_JMPR( exc, args ); - } - - - /*************************************************************************/ - /* */ - /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* FDEF[]: Function DEFinition */ - /* Opcode range: 0x2C */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_FDEF( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong n; - TT_DefRecord* rec; - TT_DefRecord* limit; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* arguments to opcodes are skipped by `SKIP_Code' */ - FT_Byte opcode_pattern[9][12] = { - /* #0 inline delta function 1 */ - { - 0x4B, /* PPEM */ - 0x53, /* GTEQ */ - 0x23, /* SWAP */ - 0x4B, /* PPEM */ - 0x51, /* LTEQ */ - 0x5A, /* AND */ - 0x58, /* IF */ - 0x38, /* SHPIX */ - 0x1B, /* ELSE */ - 0x21, /* POP */ - 0x21, /* POP */ - 0x59 /* EIF */ - }, - /* #1 inline delta function 2 */ - { - 0x4B, /* PPEM */ - 0x54, /* EQ */ - 0x58, /* IF */ - 0x38, /* SHPIX */ - 0x1B, /* ELSE */ - 0x21, /* POP */ - 0x21, /* POP */ - 0x59 /* EIF */ - }, - /* #2 diagonal stroke function */ - { - 0x20, /* DUP */ - 0x20, /* DUP */ - 0xB0, /* PUSHB_1 */ - /* 1 */ - 0x60, /* ADD */ - 0x46, /* GC_cur */ - 0xB0, /* PUSHB_1 */ - /* 64 */ - 0x23, /* SWAP */ - 0x42 /* WS */ - }, - /* #3 VacuFormRound function */ - { - 0x45, /* RCVT */ - 0x23, /* SWAP */ - 0x46, /* GC_cur */ - 0x60, /* ADD */ - 0x20, /* DUP */ - 0xB0 /* PUSHB_1 */ - /* 38 */ - }, - /* #4 TTFautohint bytecode (old) */ - { - 0x20, /* DUP */ - 0x64, /* ABS */ - 0xB0, /* PUSHB_1 */ - /* 32 */ - 0x60, /* ADD */ - 0x66, /* FLOOR */ - 0x23, /* SWAP */ - 0xB0 /* PUSHB_1 */ - }, - /* #5 spacing function 1 */ - { - 0x01, /* SVTCA_x */ - 0xB0, /* PUSHB_1 */ - /* 24 */ - 0x43, /* RS */ - 0x58 /* IF */ - }, - /* #6 spacing function 2 */ - { - 0x01, /* SVTCA_x */ - 0x18, /* RTG */ - 0xB0, /* PUSHB_1 */ - /* 24 */ - 0x43, /* RS */ - 0x58 /* IF */ - }, - /* #7 TypeMan Talk DiagEndCtrl function */ - { - 0x01, /* SVTCA_x */ - 0x20, /* DUP */ - 0xB0, /* PUSHB_1 */ - /* 3 */ - 0x25, /* CINDEX */ - }, - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; - FT_UShort opcode_patterns = 9; - FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 }; - FT_UShort i; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - - /* some font programs are broken enough to redefine functions! */ - /* We will then parse the current table. */ - - rec = exc->FDefs; - limit = rec + exc->numFDefs; - n = (FT_ULong)args[0]; - - for ( ; rec < limit; rec++ ) - { - if ( rec->opc == n ) - break; - } - - if ( rec == limit ) - { - /* check that there is enough room for new functions */ - if ( exc->numFDefs >= exc->maxFDefs ) - { - exc->error = FT_THROW( Too_Many_Function_Defs ); - return; - } - exc->numFDefs++; - } - - /* Although FDEF takes unsigned 32-bit integer, */ - /* func # must be within unsigned 16-bit integer */ - if ( n > 0xFFFFU ) - { - exc->error = FT_THROW( Too_Many_Function_Defs ); - return; - } - - rec->range = exc->curRange; - rec->opc = (FT_UInt16)n; - rec->start = exc->IP + 1; - rec->active = TRUE; - rec->inline_delta = FALSE; - rec->sph_fdef_flags = 0x0000; - - if ( n > exc->maxFunc ) - exc->maxFunc = (FT_UInt16)n; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* We don't know for sure these are typeman functions, */ - /* however they are only active when RS 22 is called */ - if ( n >= 64 && n <= 66 ) - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES; -#endif - - /* Now skip the whole function definition. */ - /* We don't allow nested IDEFS & FDEFs. */ - - while ( SkipCode( exc ) == SUCCESS ) - { - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( SUBPIXEL_HINTING ) - { - for ( i = 0; i < opcode_patterns; i++ ) - { - if ( opcode_pointer[i] < opcode_size[i] && - exc->opcode == opcode_pattern[i][opcode_pointer[i]] ) - { - opcode_pointer[i] += 1; - - if ( opcode_pointer[i] == opcode_size[i] ) - { - FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n", - i, n, - exc->face->root.family_name, - exc->face->root.style_name )); - - switch ( i ) - { - case 0: - rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1; - exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1; - break; - - case 1: - rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2; - exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2; - break; - - case 2: - switch ( n ) - { - /* needs to be implemented still */ - case 58: - rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE; - exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE; - } - break; - - case 3: - switch ( n ) - { - case 0: - rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1; - exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1; - } - break; - - case 4: - /* probably not necessary to detect anymore */ - rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1; - exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1; - break; - - case 5: - switch ( n ) - { - case 0: - case 1: - case 2: - case 4: - case 7: - case 8: - rec->sph_fdef_flags |= SPH_FDEF_SPACING_1; - exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1; - } - break; - - case 6: - switch ( n ) - { - case 0: - case 1: - case 2: - case 4: - case 7: - case 8: - rec->sph_fdef_flags |= SPH_FDEF_SPACING_2; - exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2; - } - break; - - case 7: - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - break; - - case 8: -#if 0 - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; -#endif - break; - } - opcode_pointer[i] = 0; - } - } - - else - opcode_pointer[i] = 0; - } - - /* Set sph_compatibility_mode only when deltas are detected */ - exc->face->sph_compatibility_mode = - ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) | - ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ); - } - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - switch ( exc->opcode ) - { - case 0x89: /* IDEF */ - case 0x2C: /* FDEF */ - exc->error = FT_THROW( Nested_DEFS ); - return; - - case 0x2D: /* ENDF */ - rec->end = exc->IP; - return; - } - } - } - - - /*************************************************************************/ - /* */ - /* ENDF[]: END Function definition */ - /* Opcode range: 0x2D */ - /* Stack: --> */ - /* */ - static void - Ins_ENDF( TT_ExecContext exc ) - { - TT_CallRec* pRec; - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - exc->sph_in_func_flags = 0x0000; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - if ( exc->callTop <= 0 ) /* We encountered an ENDF without a call */ - { - exc->error = FT_THROW( ENDF_In_Exec_Stream ); - return; - } - - exc->callTop--; - - pRec = &exc->callStack[exc->callTop]; - - pRec->Cur_Count--; - - exc->step_ins = FALSE; - - if ( pRec->Cur_Count > 0 ) - { - exc->callTop++; - exc->IP = pRec->Def->start; - } - else - /* Loop through the current function */ - Ins_Goto_CodeRange( exc, pRec->Caller_Range, pRec->Caller_IP ); - - /* Exit the current call frame. */ - - /* NOTE: If the last instruction of a program is a */ - /* CALL or LOOPCALL, the return address is */ - /* always out of the code range. This is a */ - /* valid address, and it is why we do not test */ - /* the result of Ins_Goto_CodeRange() here! */ - } - - - /*************************************************************************/ - /* */ - /* CALL[]: CALL function */ - /* Opcode range: 0x2B */ - /* Stack: uint32? --> */ - /* */ - static void - Ins_CALL( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong F; - TT_CallRec* pCrec; - TT_DefRecord* def; - - - /* first of all, check the index */ - - F = (FT_ULong)args[0]; - if ( BOUNDSL( F, exc->maxFunc + 1 ) ) - goto Fail; - - /* Except for some old Apple fonts, all functions in a TrueType */ - /* font are defined in increasing order, starting from 0. This */ - /* means that we normally have */ - /* */ - /* exc->maxFunc+1 == exc->numFDefs */ - /* exc->FDefs[n].opc == n for n in 0..exc->maxFunc */ - /* */ - /* If this isn't true, we need to look up the function table. */ - - def = exc->FDefs + F; - if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F ) - { - /* look up the FDefs table */ - TT_DefRecord* limit; - - - def = exc->FDefs; - limit = def + exc->numFDefs; - - while ( def < limit && def->opc != F ) - def++; - - if ( def == limit ) - goto Fail; - } - - /* check that the function is active */ - if ( !def->active ) - goto Fail; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - ( ( exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) ) - goto Fail; - else - exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* check the call stack */ - if ( exc->callTop >= exc->callSize ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - pCrec = exc->callStack + exc->callTop; - - pCrec->Caller_Range = exc->curRange; - pCrec->Caller_IP = exc->IP + 1; - pCrec->Cur_Count = 1; - pCrec->Def = def; - - exc->callTop++; - - Ins_Goto_CodeRange( exc, def->range, def->start ); - - exc->step_ins = FALSE; - - return; - - Fail: - exc->error = FT_THROW( Invalid_Reference ); - } - - - /*************************************************************************/ - /* */ - /* LOOPCALL[]: LOOP and CALL function */ - /* Opcode range: 0x2A */ - /* Stack: uint32? Eint16? --> */ - /* */ - static void - Ins_LOOPCALL( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong F; - TT_CallRec* pCrec; - TT_DefRecord* def; - - - /* first of all, check the index */ - F = (FT_ULong)args[1]; - if ( BOUNDSL( F, exc->maxFunc + 1 ) ) - goto Fail; - - /* Except for some old Apple fonts, all functions in a TrueType */ - /* font are defined in increasing order, starting from 0. This */ - /* means that we normally have */ - /* */ - /* exc->maxFunc+1 == exc->numFDefs */ - /* exc->FDefs[n].opc == n for n in 0..exc->maxFunc */ - /* */ - /* If this isn't true, we need to look up the function table. */ - - def = exc->FDefs + F; - if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F ) - { - /* look up the FDefs table */ - TT_DefRecord* limit; - - - def = exc->FDefs; - limit = def + exc->numFDefs; - - while ( def < limit && def->opc != F ) - def++; - - if ( def == limit ) - goto Fail; - } - - /* check that the function is active */ - if ( !def->active ) - goto Fail; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) - goto Fail; - else - exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* check stack */ - if ( exc->callTop >= exc->callSize ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - if ( args[0] > 0 ) - { - pCrec = exc->callStack + exc->callTop; - - pCrec->Caller_Range = exc->curRange; - pCrec->Caller_IP = exc->IP + 1; - pCrec->Cur_Count = (FT_Int)args[0]; - pCrec->Def = def; - - exc->callTop++; - - Ins_Goto_CodeRange( exc, def->range, def->start ); - - exc->step_ins = FALSE; - } - - return; - - Fail: - exc->error = FT_THROW( Invalid_Reference ); - } - - - /*************************************************************************/ - /* */ - /* IDEF[]: Instruction DEFinition */ - /* Opcode range: 0x89 */ - /* Stack: Eint8 --> */ - /* */ - static void - Ins_IDEF( TT_ExecContext exc, - FT_Long* args ) - { - TT_DefRecord* def; - TT_DefRecord* limit; - - - /* First of all, look for the same function in our table */ - - def = exc->IDefs; - limit = def + exc->numIDefs; - - for ( ; def < limit; def++ ) - if ( def->opc == (FT_ULong)args[0] ) - break; - - if ( def == limit ) - { - /* check that there is enough room for a new instruction */ - if ( exc->numIDefs >= exc->maxIDefs ) - { - exc->error = FT_THROW( Too_Many_Instruction_Defs ); - return; - } - exc->numIDefs++; - } - - /* opcode must be unsigned 8-bit integer */ - if ( 0 > args[0] || args[0] > 0x00FF ) - { - exc->error = FT_THROW( Too_Many_Instruction_Defs ); - return; - } - - def->opc = (FT_Byte)args[0]; - def->start = exc->IP + 1; - def->range = exc->curRange; - def->active = TRUE; - - if ( (FT_ULong)args[0] > exc->maxIns ) - exc->maxIns = (FT_Byte)args[0]; - - /* Now skip the whole function definition. */ - /* We don't allow nested IDEFs & FDEFs. */ - - while ( SkipCode( exc ) == SUCCESS ) - { - switch ( exc->opcode ) - { - case 0x89: /* IDEF */ - case 0x2C: /* FDEF */ - exc->error = FT_THROW( Nested_DEFS ); - return; - case 0x2D: /* ENDF */ - return; - } - } - } - - - /*************************************************************************/ - /* */ - /* PUSHING DATA ONTO THE INTERPRETER STACK */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* NPUSHB[]: PUSH N Bytes */ - /* Opcode range: 0x40 */ - /* Stack: --> uint32... */ - /* */ - static void - Ins_NPUSHB( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort L, K; - - - L = (FT_UShort)exc->code[exc->IP + 1]; - - if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - for ( K = 1; K <= L; K++ ) - args[K - 1] = exc->code[exc->IP + K + 1]; - - exc->new_top += L; - } - - - /*************************************************************************/ - /* */ - /* NPUSHW[]: PUSH N Words */ - /* Opcode range: 0x41 */ - /* Stack: --> int32... */ - /* */ - static void - Ins_NPUSHW( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort L, K; - - - L = (FT_UShort)exc->code[exc->IP + 1]; - - if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - exc->IP += 2; - - for ( K = 0; K < L; K++ ) - args[K] = GetShortIns( exc ); - - exc->step_ins = FALSE; - exc->new_top += L; - } - - - /*************************************************************************/ - /* */ - /* PUSHB[abc]: PUSH Bytes */ - /* Opcode range: 0xB0-0xB7 */ - /* Stack: --> uint32... */ - /* */ - static void - Ins_PUSHB( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort L, K; - - - L = (FT_UShort)( exc->opcode - 0xB0 + 1 ); - - if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - for ( K = 1; K <= L; K++ ) - args[K - 1] = exc->code[exc->IP + K]; - } - - - /*************************************************************************/ - /* */ - /* PUSHW[abc]: PUSH Words */ - /* Opcode range: 0xB8-0xBF */ - /* Stack: --> int32... */ - /* */ - static void - Ins_PUSHW( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort L, K; - - - L = (FT_UShort)( exc->opcode - 0xB8 + 1 ); - - if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - exc->IP++; - - for ( K = 0; K < L; K++ ) - args[K] = GetShortIns( exc ); - - exc->step_ins = FALSE; - } - - - /*************************************************************************/ - /* */ - /* MANAGING THE GRAPHICS STATE */ - /* */ - /*************************************************************************/ - - - static FT_Bool - Ins_SxVTL( TT_ExecContext exc, - FT_UShort aIdx1, - FT_UShort aIdx2, - FT_UnitVector* Vec ) - { - FT_Long A, B, C; - FT_Vector* p1; - FT_Vector* p2; - - FT_Byte opcode = exc->opcode; - - - if ( BOUNDS( aIdx1, exc->zp2.n_points ) || - BOUNDS( aIdx2, exc->zp1.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return FAILURE; - } - - p1 = exc->zp1.cur + aIdx2; - p2 = exc->zp2.cur + aIdx1; - - A = p1->x - p2->x; - B = p1->y - p2->y; - - /* If p1 == p2, SPvTL and SFvTL behave the same as */ - /* SPvTCA[X] and SFvTCA[X], respectively. */ - /* */ - /* Confirmed by Greg Hitchcock. */ - - if ( A == 0 && B == 0 ) - { - A = 0x4000; - opcode = 0; - } - - if ( ( opcode & 1 ) != 0 ) - { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; - } - - Normalize( A, B, Vec ); - - return SUCCESS; - } - - - /*************************************************************************/ - /* */ - /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */ - /* Opcode range: 0x00-0x01 */ - /* Stack: --> */ - /* */ - /* SPvTCA[a]: Set PVector to Coordinate Axis */ - /* Opcode range: 0x02-0x03 */ - /* Stack: --> */ - /* */ - /* SFvTCA[a]: Set FVector to Coordinate Axis */ - /* Opcode range: 0x04-0x05 */ - /* Stack: --> */ - /* */ - static void - Ins_SxyTCA( TT_ExecContext exc ) - { - FT_Short AA, BB; - - FT_Byte opcode = exc->opcode; - - - AA = (FT_Short)( ( opcode & 1 ) << 14 ); - BB = (FT_Short)( AA ^ 0x4000 ); - - if ( opcode < 4 ) - { - exc->GS.projVector.x = AA; - exc->GS.projVector.y = BB; - - exc->GS.dualVector.x = AA; - exc->GS.dualVector.y = BB; - } - else - GUESS_VECTOR( projVector ); - - if ( ( opcode & 2 ) == 0 ) - { - exc->GS.freeVector.x = AA; - exc->GS.freeVector.y = BB; - } - else - GUESS_VECTOR( freeVector ); - - Compute_Funcs( exc ); - } - - - /*************************************************************************/ - /* */ - /* SPvTL[a]: Set PVector To Line */ - /* Opcode range: 0x06-0x07 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_SPVTL( TT_ExecContext exc, - FT_Long* args ) - { - if ( Ins_SxVTL( exc, - (FT_UShort)args[1], - (FT_UShort)args[0], - &exc->GS.projVector ) == SUCCESS ) - { - exc->GS.dualVector = exc->GS.projVector; - GUESS_VECTOR( freeVector ); - Compute_Funcs( exc ); - } - } - - - /*************************************************************************/ - /* */ - /* SFvTL[a]: Set FVector To Line */ - /* Opcode range: 0x08-0x09 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_SFVTL( TT_ExecContext exc, - FT_Long* args ) - { - if ( Ins_SxVTL( exc, - (FT_UShort)args[1], - (FT_UShort)args[0], - &exc->GS.freeVector ) == SUCCESS ) - { - GUESS_VECTOR( projVector ); - Compute_Funcs( exc ); - } - } - - - /*************************************************************************/ - /* */ - /* SFvTPv[]: Set FVector To PVector */ - /* Opcode range: 0x0E */ - /* Stack: --> */ - /* */ - static void - Ins_SFVTPV( TT_ExecContext exc ) - { - GUESS_VECTOR( projVector ); - exc->GS.freeVector = exc->GS.projVector; - Compute_Funcs( exc ); - } - - - /*************************************************************************/ - /* */ - /* SPvFS[]: Set PVector From Stack */ - /* Opcode range: 0x0A */ - /* Stack: f2.14 f2.14 --> */ - /* */ - static void - Ins_SPVFS( TT_ExecContext exc, - FT_Long* args ) - { - FT_Short S; - FT_Long X, Y; - - - /* Only use low 16bits, then sign extend */ - S = (FT_Short)args[1]; - Y = (FT_Long)S; - S = (FT_Short)args[0]; - X = (FT_Long)S; - - Normalize( X, Y, &exc->GS.projVector ); - - exc->GS.dualVector = exc->GS.projVector; - GUESS_VECTOR( freeVector ); - Compute_Funcs( exc ); - } - - - /*************************************************************************/ - /* */ - /* SFvFS[]: Set FVector From Stack */ - /* Opcode range: 0x0B */ - /* Stack: f2.14 f2.14 --> */ - /* */ - static void - Ins_SFVFS( TT_ExecContext exc, - FT_Long* args ) - { - FT_Short S; - FT_Long X, Y; - - - /* Only use low 16bits, then sign extend */ - S = (FT_Short)args[1]; - Y = (FT_Long)S; - S = (FT_Short)args[0]; - X = S; - - Normalize( X, Y, &exc->GS.freeVector ); - GUESS_VECTOR( projVector ); - Compute_Funcs( exc ); - } - - - /*************************************************************************/ - /* */ - /* GPv[]: Get Projection Vector */ - /* Opcode range: 0x0C */ - /* Stack: ef2.14 --> ef2.14 */ - /* */ - static void - Ins_GPV( TT_ExecContext exc, - FT_Long* args ) - { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - args[0] = exc->GS.both_x_axis ? 0x4000 : 0; - args[1] = exc->GS.both_x_axis ? 0 : 0x4000; - } - else - { - args[0] = exc->GS.projVector.x; - args[1] = exc->GS.projVector.y; - } -#else - args[0] = exc->GS.projVector.x; - args[1] = exc->GS.projVector.y; -#endif - } - - - /*************************************************************************/ - /* */ - /* GFv[]: Get Freedom Vector */ - /* Opcode range: 0x0D */ - /* Stack: ef2.14 --> ef2.14 */ - /* */ - static void - Ins_GFV( TT_ExecContext exc, - FT_Long* args ) - { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - args[0] = exc->GS.both_x_axis ? 0x4000 : 0; - args[1] = exc->GS.both_x_axis ? 0 : 0x4000; - } - else - { - args[0] = exc->GS.freeVector.x; - args[1] = exc->GS.freeVector.y; - } -#else - args[0] = exc->GS.freeVector.x; - args[1] = exc->GS.freeVector.y; -#endif - } - - - /*************************************************************************/ - /* */ - /* SRP0[]: Set Reference Point 0 */ - /* Opcode range: 0x10 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SRP0( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.rp0 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SRP1[]: Set Reference Point 1 */ - /* Opcode range: 0x11 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SRP1( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.rp1 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SRP2[]: Set Reference Point 2 */ - /* Opcode range: 0x12 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SRP2( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.rp2 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SMD[]: Set Minimum Distance */ - /* Opcode range: 0x1A */ - /* Stack: f26.6 --> */ - /* */ - static void - Ins_SMD( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.minimum_distance = args[0]; - } - - - /*************************************************************************/ - /* */ - /* SCVTCI[]: Set Control Value Table Cut In */ - /* Opcode range: 0x1D */ - /* Stack: f26.6 --> */ - /* */ - static void - Ins_SCVTCI( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.control_value_cutin = (FT_F26Dot6)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SSWCI[]: Set Single Width Cut In */ - /* Opcode range: 0x1E */ - /* Stack: f26.6 --> */ - /* */ - static void - Ins_SSWCI( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.single_width_cutin = (FT_F26Dot6)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SSW[]: Set Single Width */ - /* Opcode range: 0x1F */ - /* Stack: int32? --> */ - /* */ - static void - Ins_SSW( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.single_width_value = FT_MulFix( args[0], - exc->tt_metrics.scale ); - } - - - /*************************************************************************/ - /* */ - /* FLIPON[]: Set auto-FLIP to ON */ - /* Opcode range: 0x4D */ - /* Stack: --> */ - /* */ - static void - Ins_FLIPON( TT_ExecContext exc ) - { - exc->GS.auto_flip = TRUE; - } - - - /*************************************************************************/ - /* */ - /* FLIPOFF[]: Set auto-FLIP to OFF */ - /* Opcode range: 0x4E */ - /* Stack: --> */ - /* */ - static void - Ins_FLIPOFF( TT_ExecContext exc ) - { - exc->GS.auto_flip = FALSE; - } - - - /*************************************************************************/ - /* */ - /* SANGW[]: Set ANGle Weight */ - /* Opcode range: 0x7E */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SANGW( void ) - { - /* instruction not supported anymore */ - } - - - /*************************************************************************/ - /* */ - /* SDB[]: Set Delta Base */ - /* Opcode range: 0x5E */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SDB( TT_ExecContext exc, - FT_Long* args ) - { - exc->GS.delta_base = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SDS[]: Set Delta Shift */ - /* Opcode range: 0x5F */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SDS( TT_ExecContext exc, - FT_Long* args ) - { - if ( (FT_ULong)args[0] > 6UL ) - exc->error = FT_THROW( Bad_Argument ); - else - exc->GS.delta_shift = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* RTHG[]: Round To Half Grid */ - /* Opcode range: 0x19 */ - /* Stack: --> */ - /* */ - static void - Ins_RTHG( TT_ExecContext exc ) - { - exc->GS.round_state = TT_Round_To_Half_Grid; - exc->func_round = (TT_Round_Func)Round_To_Half_Grid; - } - - - /*************************************************************************/ - /* */ - /* RTG[]: Round To Grid */ - /* Opcode range: 0x18 */ - /* Stack: --> */ - /* */ - static void - Ins_RTG( TT_ExecContext exc ) - { - exc->GS.round_state = TT_Round_To_Grid; - exc->func_round = (TT_Round_Func)Round_To_Grid; - } - - - /*************************************************************************/ - /* RTDG[]: Round To Double Grid */ - /* Opcode range: 0x3D */ - /* Stack: --> */ - /* */ - static void - Ins_RTDG( TT_ExecContext exc ) - { - exc->GS.round_state = TT_Round_To_Double_Grid; - exc->func_round = (TT_Round_Func)Round_To_Double_Grid; - } - - - /*************************************************************************/ - /* RUTG[]: Round Up To Grid */ - /* Opcode range: 0x7C */ - /* Stack: --> */ - /* */ - static void - Ins_RUTG( TT_ExecContext exc ) - { - exc->GS.round_state = TT_Round_Up_To_Grid; - exc->func_round = (TT_Round_Func)Round_Up_To_Grid; - } - - - /*************************************************************************/ - /* */ - /* RDTG[]: Round Down To Grid */ - /* Opcode range: 0x7D */ - /* Stack: --> */ - /* */ - static void - Ins_RDTG( TT_ExecContext exc ) - { - exc->GS.round_state = TT_Round_Down_To_Grid; - exc->func_round = (TT_Round_Func)Round_Down_To_Grid; - } - - - /*************************************************************************/ - /* */ - /* ROFF[]: Round OFF */ - /* Opcode range: 0x7A */ - /* Stack: --> */ - /* */ - static void - Ins_ROFF( TT_ExecContext exc ) - { - exc->GS.round_state = TT_Round_Off; - exc->func_round = (TT_Round_Func)Round_None; - } - - - /*************************************************************************/ - /* */ - /* SROUND[]: Super ROUND */ - /* Opcode range: 0x76 */ - /* Stack: Eint8 --> */ - /* */ - static void - Ins_SROUND( TT_ExecContext exc, - FT_Long* args ) - { - SetSuperRound( exc, 0x4000, args[0] ); - - exc->GS.round_state = TT_Round_Super; - exc->func_round = (TT_Round_Func)Round_Super; - } - - - /*************************************************************************/ - /* */ - /* S45ROUND[]: Super ROUND 45 degrees */ - /* Opcode range: 0x77 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_S45ROUND( TT_ExecContext exc, - FT_Long* args ) - { - SetSuperRound( exc, 0x2D41, args[0] ); - - exc->GS.round_state = TT_Round_Super_45; - exc->func_round = (TT_Round_Func)Round_Super_45; - } - - - /*************************************************************************/ - /* */ - /* GC[a]: Get Coordinate projected onto */ - /* Opcode range: 0x46-0x47 */ - /* Stack: uint32 --> f26.6 */ - /* */ - /* XXX: UNDOCUMENTED: Measures from the original glyph must be taken */ - /* along the dual projection vector! */ - /* */ - static void - Ins_GC( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong L; - FT_F26Dot6 R; - - - L = (FT_ULong)args[0]; - - if ( BOUNDSL( L, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - R = 0; - } - else - { - if ( exc->opcode & 1 ) - R = FAST_DUALPROJ( &exc->zp2.org[L] ); - else - R = FAST_PROJECT( &exc->zp2.cur[L] ); - } - - args[0] = R; - } - - - /*************************************************************************/ - /* */ - /* SCFS[]: Set Coordinate From Stack */ - /* Opcode range: 0x48 */ - /* Stack: f26.6 uint32 --> */ - /* */ - /* Formula: */ - /* */ - /* OA := OA + ( value - OA.p )/( f.p ) * f */ - /* */ - static void - Ins_SCFS( TT_ExecContext exc, - FT_Long* args ) - { - FT_Long K; - FT_UShort L; - - - L = (FT_UShort)args[0]; - - if ( BOUNDS( L, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - K = FAST_PROJECT( &exc->zp2.cur[L] ); - - exc->func_move( exc, &exc->zp2, L, args[1] - K ); - - /* UNDOCUMENTED! The MS rasterizer does that with */ - /* twilight points (confirmed by Greg Hitchcock) */ - if ( exc->GS.gep2 == 0 ) - exc->zp2.org[L] = exc->zp2.cur[L]; - } - - - /*************************************************************************/ - /* */ - /* MD[a]: Measure Distance */ - /* Opcode range: 0x49-0x4A */ - /* Stack: uint32 uint32 --> f26.6 */ - /* */ - /* XXX: UNDOCUMENTED: Measure taken in the original glyph must be along */ - /* the dual projection vector. */ - /* */ - /* XXX: UNDOCUMENTED: Flag attributes are inverted! */ - /* 0 => measure distance in original outline */ - /* 1 => measure distance in grid-fitted outline */ - /* */ - /* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1! */ - /* */ - static void - Ins_MD( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort K, L; - FT_F26Dot6 D; - - - K = (FT_UShort)args[1]; - L = (FT_UShort)args[0]; - - if ( BOUNDS( L, exc->zp0.n_points ) || - BOUNDS( K, exc->zp1.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - D = 0; - } - else - { - if ( exc->opcode & 1 ) - D = PROJECT( exc->zp0.cur + L, exc->zp1.cur + K ); - else - { - /* XXX: UNDOCUMENTED: twilight zone special case */ - - if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 ) - { - FT_Vector* vec1 = exc->zp0.org + L; - FT_Vector* vec2 = exc->zp1.org + K; - - - D = DUALPROJ( vec1, vec2 ); - } - else - { - FT_Vector* vec1 = exc->zp0.orus + L; - FT_Vector* vec2 = exc->zp1.orus + K; - - - if ( exc->metrics.x_scale == exc->metrics.y_scale ) - { - /* this should be faster */ - D = DUALPROJ( vec1, vec2 ); - D = FT_MulFix( D, exc->metrics.x_scale ); - } - else - { - FT_Vector vec; - - - vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale ); - vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale ); - - D = FAST_DUALPROJ( &vec ); - } - } - } - } - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - FT_ABS( D ) == 64 ) - D += 1; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - args[0] = D; - } - - - /*************************************************************************/ - /* */ - /* SDPvTL[a]: Set Dual PVector to Line */ - /* Opcode range: 0x86-0x87 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_SDPVTL( TT_ExecContext exc, - FT_Long* args ) - { - FT_Long A, B, C; - FT_UShort p1, p2; /* was FT_Int in pas type ERROR */ - - FT_Byte opcode = exc->opcode; - - - p1 = (FT_UShort)args[1]; - p2 = (FT_UShort)args[0]; - - if ( BOUNDS( p2, exc->zp1.n_points ) || - BOUNDS( p1, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - { - FT_Vector* v1 = exc->zp1.org + p2; - FT_Vector* v2 = exc->zp2.org + p1; - - - A = v1->x - v2->x; - B = v1->y - v2->y; - - /* If v1 == v2, SDPvTL behaves the same as */ - /* SVTCA[X], respectively. */ - /* */ - /* Confirmed by Greg Hitchcock. */ - - if ( A == 0 && B == 0 ) - { - A = 0x4000; - opcode = 0; - } - } - - if ( ( opcode & 1 ) != 0 ) - { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; - } - - Normalize( A, B, &exc->GS.dualVector ); - - { - FT_Vector* v1 = exc->zp1.cur + p2; - FT_Vector* v2 = exc->zp2.cur + p1; - - - A = v1->x - v2->x; - B = v1->y - v2->y; - - if ( A == 0 && B == 0 ) - { - A = 0x4000; - opcode = 0; - } - } - - if ( ( opcode & 1 ) != 0 ) - { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; - } - - Normalize( A, B, &exc->GS.projVector ); - GUESS_VECTOR( freeVector ); - Compute_Funcs( exc ); - } - - - /*************************************************************************/ - /* */ - /* SZP0[]: Set Zone Pointer 0 */ - /* Opcode range: 0x13 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SZP0( TT_ExecContext exc, - FT_Long* args ) - { - switch ( (FT_Int)args[0] ) - { - case 0: - exc->zp0 = exc->twilight; - break; - - case 1: - exc->zp0 = exc->pts; - break; - - default: - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - exc->GS.gep0 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SZP1[]: Set Zone Pointer 1 */ - /* Opcode range: 0x14 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SZP1( TT_ExecContext exc, - FT_Long* args ) - { - switch ( (FT_Int)args[0] ) - { - case 0: - exc->zp1 = exc->twilight; - break; - - case 1: - exc->zp1 = exc->pts; - break; - - default: - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - exc->GS.gep1 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SZP2[]: Set Zone Pointer 2 */ - /* Opcode range: 0x15 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SZP2( TT_ExecContext exc, - FT_Long* args ) - { - switch ( (FT_Int)args[0] ) - { - case 0: - exc->zp2 = exc->twilight; - break; - - case 1: - exc->zp2 = exc->pts; - break; - - default: - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - exc->GS.gep2 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* SZPS[]: Set Zone PointerS */ - /* Opcode range: 0x16 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SZPS( TT_ExecContext exc, - FT_Long* args ) - { - switch ( (FT_Int)args[0] ) - { - case 0: - exc->zp0 = exc->twilight; - break; - - case 1: - exc->zp0 = exc->pts; - break; - - default: - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - exc->zp1 = exc->zp0; - exc->zp2 = exc->zp0; - - exc->GS.gep0 = (FT_UShort)args[0]; - exc->GS.gep1 = (FT_UShort)args[0]; - exc->GS.gep2 = (FT_UShort)args[0]; - } - - - /*************************************************************************/ - /* */ - /* INSTCTRL[]: INSTruction ConTRoL */ - /* Opcode range: 0x8E */ - /* Stack: int32 int32 --> */ - /* */ - static void - Ins_INSTCTRL( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong K, L, Kf; - - - K = (FT_ULong)args[1]; - L = (FT_ULong)args[0]; - - /* selector values cannot be `OR'ed; */ - /* they are indices starting with index 1, not flags */ - if ( K < 1 || K > 3 ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - /* convert index to flag value */ - Kf = 1 << ( K - 1 ); - - if ( L != 0 ) - { - /* arguments to selectors look like flag values */ - if ( L != Kf ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - } - - exc->GS.instruct_control &= ~(FT_Byte)Kf; - exc->GS.instruct_control |= (FT_Byte)L; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* INSTCTRL modifying flag 3 also has an effect */ - /* outside of the CVT program */ - if ( K == 3 ) - exc->ignore_x_mode = FT_BOOL( L == 4 ); -#endif - } - - - /*************************************************************************/ - /* */ - /* SCANCTRL[]: SCAN ConTRoL */ - /* Opcode range: 0x85 */ - /* Stack: uint32? --> */ - /* */ - static void - Ins_SCANCTRL( TT_ExecContext exc, - FT_Long* args ) - { - FT_Int A; - - - /* Get Threshold */ - A = (FT_Int)( args[0] & 0xFF ); - - if ( A == 0xFF ) - { - exc->GS.scan_control = TRUE; - return; - } - else if ( A == 0 ) - { - exc->GS.scan_control = FALSE; - return; - } - - if ( ( args[0] & 0x100 ) != 0 && exc->tt_metrics.ppem <= A ) - exc->GS.scan_control = TRUE; - - if ( ( args[0] & 0x200 ) != 0 && exc->tt_metrics.rotated ) - exc->GS.scan_control = TRUE; - - if ( ( args[0] & 0x400 ) != 0 && exc->tt_metrics.stretched ) - exc->GS.scan_control = TRUE; - - if ( ( args[0] & 0x800 ) != 0 && exc->tt_metrics.ppem > A ) - exc->GS.scan_control = FALSE; - - if ( ( args[0] & 0x1000 ) != 0 && exc->tt_metrics.rotated ) - exc->GS.scan_control = FALSE; - - if ( ( args[0] & 0x2000 ) != 0 && exc->tt_metrics.stretched ) - exc->GS.scan_control = FALSE; - } - - - /*************************************************************************/ - /* */ - /* SCANTYPE[]: SCAN TYPE */ - /* Opcode range: 0x8D */ - /* Stack: uint32? --> */ - /* */ - static void - Ins_SCANTYPE( TT_ExecContext exc, - FT_Long* args ) - { - if ( args[0] >= 0 ) - exc->GS.scan_type = (FT_Int)args[0]; - } - - - /*************************************************************************/ - /* */ - /* MANAGING OUTLINES */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* FLIPPT[]: FLIP PoinT */ - /* Opcode range: 0x80 */ - /* Stack: uint32... --> */ - /* */ - static void - Ins_FLIPPT( TT_ExecContext exc ) - { - FT_UShort point; - - - if ( exc->top < exc->GS.loop ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - goto Fail; - } - - while ( exc->GS.loop > 0 ) - { - exc->args--; - - point = (FT_UShort)exc->stack[exc->args]; - - if ( BOUNDS( point, exc->pts.n_points ) ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Invalid_Reference ); - return; - } - } - else - exc->pts.tags[point] ^= FT_CURVE_TAG_ON; - - exc->GS.loop--; - } - - Fail: - exc->GS.loop = 1; - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* FLIPRGON[]: FLIP RanGe ON */ - /* Opcode range: 0x81 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_FLIPRGON( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort I, K, L; - - - K = (FT_UShort)args[1]; - L = (FT_UShort)args[0]; - - if ( BOUNDS( K, exc->pts.n_points ) || - BOUNDS( L, exc->pts.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - for ( I = L; I <= K; I++ ) - exc->pts.tags[I] |= FT_CURVE_TAG_ON; - } - - - /*************************************************************************/ - /* */ - /* FLIPRGOFF: FLIP RanGe OFF */ - /* Opcode range: 0x82 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_FLIPRGOFF( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort I, K, L; - - - K = (FT_UShort)args[1]; - L = (FT_UShort)args[0]; - - if ( BOUNDS( K, exc->pts.n_points ) || - BOUNDS( L, exc->pts.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - for ( I = L; I <= K; I++ ) - exc->pts.tags[I] &= ~FT_CURVE_TAG_ON; - } - - - static FT_Bool - Compute_Point_Displacement( TT_ExecContext exc, - FT_F26Dot6* x, - FT_F26Dot6* y, - TT_GlyphZone zone, - FT_UShort* refp ) - { - TT_GlyphZoneRec zp; - FT_UShort p; - FT_F26Dot6 d; - - - if ( exc->opcode & 1 ) - { - zp = exc->zp0; - p = exc->GS.rp1; - } - else - { - zp = exc->zp1; - p = exc->GS.rp2; - } - - if ( BOUNDS( p, zp.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - *refp = 0; - return FAILURE; - } - - *zone = zp; - *refp = p; - - d = PROJECT( zp.cur + p, zp.org + p ); - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - { - *x = d; - *y = 0; - } - else - { - *x = 0; - *y = d; - } - } - else -#endif - { - *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P ); - *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P ); - } - - return SUCCESS; - } - - - static void - Move_Zp2_Point( TT_ExecContext exc, - FT_UShort point, - FT_F26Dot6 dx, - FT_F26Dot6 dy, - FT_Bool touch ) - { -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - { - exc->zp2.cur[point].x += dx; - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; - } - else - { - exc->zp2.cur[point].y += dy; - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; - } - return; - } -#endif - - if ( exc->GS.freeVector.x != 0 ) - { - exc->zp2.cur[point].x += dx; - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; - } - - if ( exc->GS.freeVector.y != 0 ) - { - exc->zp2.cur[point].y += dy; - if ( touch ) - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; - } - } - - - /*************************************************************************/ - /* */ - /* SHP[a]: SHift Point by the last point */ - /* Opcode range: 0x32-0x33 */ - /* Stack: uint32... --> */ - /* */ - static void - Ins_SHP( TT_ExecContext exc ) - { - TT_GlyphZoneRec zp; - FT_UShort refp; - - FT_F26Dot6 dx, dy; - FT_UShort point; - - - if ( exc->top < exc->GS.loop ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) - return; - - while ( exc->GS.loop > 0 ) - { - exc->args--; - point = (FT_UShort)exc->stack[exc->args]; - - if ( BOUNDS( point, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Invalid_Reference ); - return; - } - } - else -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* doesn't follow Cleartype spec but produces better result */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); - else -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - - exc->GS.loop--; - } - - Fail: - exc->GS.loop = 1; - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* SHC[a]: SHift Contour */ - /* Opcode range: 0x34-35 */ - /* Stack: uint32 --> */ - /* */ - /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */ - /* contour in the twilight zone, namely contour number */ - /* zero which includes all points of it. */ - /* */ - static void - Ins_SHC( TT_ExecContext exc, - FT_Long* args ) - { - TT_GlyphZoneRec zp; - FT_UShort refp; - FT_F26Dot6 dx, dy; - - FT_Short contour, bounds; - FT_UShort start, limit, i; - - - contour = (FT_Short)args[0]; - bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours; - - if ( BOUNDS( contour, bounds ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) - return; - - if ( contour == 0 ) - start = 0; - else - start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 - - exc->zp2.first_point ); - - /* we use the number of points if in the twilight zone */ - if ( exc->GS.gep2 == 0 ) - limit = exc->zp2.n_points; - else - limit = (FT_UShort)( exc->zp2.contours[contour] - - exc->zp2.first_point + 1 ); - - for ( i = start; i < limit; i++ ) - { - if ( zp.cur != exc->zp2.cur || refp != i ) - Move_Zp2_Point( exc, i, dx, dy, TRUE ); - } - } - - - /*************************************************************************/ - /* */ - /* SHZ[a]: SHift Zone */ - /* Opcode range: 0x36-37 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_SHZ( TT_ExecContext exc, - FT_Long* args ) - { - TT_GlyphZoneRec zp; - FT_UShort refp; - FT_F26Dot6 dx, - dy; - - FT_UShort limit, i; - - - if ( BOUNDS( args[0], 2 ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) - return; - - /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */ - /* Twilight zone has no real contours, so use `n_points'. */ - /* Normal zone's `n_points' includes phantoms, so must */ - /* use end of last contour. */ - if ( exc->GS.gep2 == 0 ) - limit = (FT_UShort)exc->zp2.n_points; - else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 ) - limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 ); - else - limit = 0; - - /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ - for ( i = 0; i < limit; i++ ) - { - if ( zp.cur != exc->zp2.cur || refp != i ) - Move_Zp2_Point( exc, i, dx, dy, FALSE ); - } - } - - - /*************************************************************************/ - /* */ - /* SHPIX[]: SHift points by a PIXel amount */ - /* Opcode range: 0x38 */ - /* Stack: f26.6 uint32... --> */ - /* */ - static void - Ins_SHPIX( TT_ExecContext exc, - FT_Long* args ) - { - FT_F26Dot6 dx, dy; - FT_UShort point; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_Int B1, B2; -#endif - - - if ( exc->top < exc->GS.loop + 1 ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - if ( exc->face->unpatented_hinting ) - { - if ( exc->GS.both_x_axis ) - { - dx = (FT_UInt32)args[0]; - dy = 0; - } - else - { - dx = 0; - dy = (FT_UInt32)args[0]; - } - } - else -#endif - { - dx = TT_MulFix14( args[0], exc->GS.freeVector.x ); - dy = TT_MulFix14( args[0], exc->GS.freeVector.y ); - } - - while ( exc->GS.loop > 0 ) - { - exc->args--; - - point = (FT_UShort)exc->stack[exc->args]; - - if ( BOUNDS( point, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Invalid_Reference ); - return; - } - } - else -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - { - /* If not using ignore_x_mode rendering, allow ZP2 move. */ - /* If inline deltas aren't allowed, skip ZP2 move. */ - /* If using ignore_x_mode rendering, allow ZP2 point move if: */ - /* - freedom vector is y and sph_compatibility_mode is off */ - /* - the glyph is composite and the move is in the Y direction */ - /* - the glyph is specifically set to allow SHPIX moves */ - /* - the move is on a previously Y-touched point */ - - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) - { - /* save point for later comparison */ - if ( exc->GS.freeVector.y != 0 ) - B1 = exc->zp2.cur[point].y; - else - B1 = exc->zp2.cur[point].x; - - if ( !exc->face->sph_compatibility_mode && - exc->GS.freeVector.y != 0 ) - { - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - - /* save new point */ - if ( exc->GS.freeVector.y != 0 ) - { - B2 = exc->zp2.cur[point].y; - - /* reverse any disallowed moves */ - if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 && - B1 != B2 ) - Move_Zp2_Point( exc, point, -dx, -dy, TRUE ); - } - } - else if ( exc->face->sph_compatibility_mode ) - { - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - { - dx = FT_PIX_ROUND( B1 + dx ) - B1; - dy = FT_PIX_ROUND( B1 + dy ) - B1; - } - - /* skip post-iup deltas */ - if ( exc->iup_called && - ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) || - ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) ) - goto Skip; - - if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) && - ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || - ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) || - ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); - - /* save new point */ - if ( exc->GS.freeVector.y != 0 ) - { - B2 = exc->zp2.cur[point].y; - - /* reverse any disallowed moves */ - if ( ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 && - B1 != B2 ) - Move_Zp2_Point( exc, point, 0, -dy, TRUE ); - } - } - else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL ) - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - } - else - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - } - - Skip: - -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - exc->GS.loop--; - } - - Fail: - exc->GS.loop = 1; - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* MSIRP[a]: Move Stack Indirect Relative Position */ - /* Opcode range: 0x3A-0x3B */ - /* Stack: f26.6 uint32 --> */ - /* */ - static void - Ins_MSIRP( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort point; - FT_F26Dot6 distance; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_F26Dot6 control_value_cutin = 0; /* pacify compiler */ - - - if ( SUBPIXEL_HINTING ) - { - control_value_cutin = exc->GS.control_value_cutin; - - if ( exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; - } - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - point = (FT_UShort)args[0]; - - if ( BOUNDS( point, exc->zp1.n_points ) || - BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - /* UNDOCUMENTED! The MS rasterizer does that with */ - /* twilight points (confirmed by Greg Hitchcock) */ - if ( exc->GS.gep1 == 0 ) - { - exc->zp1.org[point] = exc->zp0.org[exc->GS.rp0]; - exc->func_move_orig( exc, &exc->zp1, point, args[1] ); - exc->zp1.cur[point] = exc->zp1.org[point]; - } - - distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* subpixel hinting - make MSIRP respect CVT cut-in; */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - FT_ABS( distance - args[1] ) >= control_value_cutin ) - distance = args[1]; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - exc->func_move( exc, &exc->zp1, point, args[1] - distance ); - - exc->GS.rp1 = exc->GS.rp0; - exc->GS.rp2 = point; - - if ( ( exc->opcode & 1 ) != 0 ) - exc->GS.rp0 = point; - } - - - /*************************************************************************/ - /* */ - /* MDAP[a]: Move Direct Absolute Point */ - /* Opcode range: 0x2E-0x2F */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_MDAP( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort point; - FT_F26Dot6 cur_dist; - FT_F26Dot6 distance; - - - point = (FT_UShort)args[0]; - - if ( BOUNDS( point, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - if ( ( exc->opcode & 1 ) != 0 ) - { - cur_dist = FAST_PROJECT( &exc->zp0.cur[point] ); -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( - exc, - cur_dist, - exc->tt_metrics.compensations[0] ) - cur_dist; - else -#endif - distance = exc->func_round( - exc, - cur_dist, - exc->tt_metrics.compensations[0] ) - cur_dist; - } - else - distance = 0; - - exc->func_move( exc, &exc->zp0, point, distance ); - - exc->GS.rp0 = point; - exc->GS.rp1 = point; - } - - - /*************************************************************************/ - /* */ - /* MIAP[a]: Move Indirect Absolute Point */ - /* Opcode range: 0x3E-0x3F */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_MIAP( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong cvtEntry; - FT_UShort point; - FT_F26Dot6 distance; - FT_F26Dot6 org_dist; - FT_F26Dot6 control_value_cutin; - - - control_value_cutin = exc->GS.control_value_cutin; - cvtEntry = (FT_ULong)args[1]; - point = (FT_UShort)args[0]; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - exc->GS.freeVector.y == 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - if ( BOUNDS( point, exc->zp0.n_points ) || - BOUNDSL( cvtEntry, exc->cvtSize ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - /* UNDOCUMENTED! */ - /* */ - /* The behaviour of an MIAP instruction is quite different when used */ - /* in the twilight zone. */ - /* */ - /* First, no control value cut-in test is performed as it would fail */ - /* anyway. Second, the original point, i.e. (org_x,org_y) of */ - /* zp0.point, is set to the absolute, unrounded distance found in the */ - /* CVT. */ - /* */ - /* This is used in the CVT programs of the Microsoft fonts Arial, */ - /* Times, etc., in order to re-adjust some key font heights. It */ - /* allows the use of the IP instruction in the twilight zone, which */ - /* otherwise would be invalid according to the specification. */ - /* */ - /* We implement it with a special sequence for the twilight zone. */ - /* This is a bad hack, but it seems to work. */ - /* */ - /* Confirmed by Greg Hitchcock. */ - - distance = exc->func_read_cvt( exc, cvtEntry ); - - if ( exc->GS.gep0 == 0 ) /* If in twilight zone */ - { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */ - /* Determined via experimentation and may be incorrect... */ - if ( !SUBPIXEL_HINTING || - ( !exc->ignore_x_mode || - !exc->face->sph_compatibility_mode ) ) -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - exc->zp0.org[point].x = TT_MulFix14( distance, - exc->GS.freeVector.x ); - exc->zp0.org[point].y = TT_MulFix14( distance, - exc->GS.freeVector.y ), - exc->zp0.cur[point] = exc->zp0.org[point]; - } -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && - distance > 0 && - exc->GS.freeVector.y != 0 ) - distance = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - org_dist = FAST_PROJECT( &exc->zp0.cur[point] ); - - if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */ - { - if ( FT_ABS( distance - org_dist ) > control_value_cutin ) - distance = org_dist; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( exc, - distance, - exc->tt_metrics.compensations[0] ); - else -#endif - distance = exc->func_round( exc, - distance, - exc->tt_metrics.compensations[0] ); - } - - exc->func_move( exc, &exc->zp0, point, distance - org_dist ); - - Fail: - exc->GS.rp0 = point; - exc->GS.rp1 = point; - } - - - /*************************************************************************/ - /* */ - /* MDRP[abcde]: Move Direct Relative Point */ - /* Opcode range: 0xC0-0xDF */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_MDRP( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort point; - FT_F26Dot6 org_dist, distance, minimum_distance; - - - minimum_distance = exc->GS.minimum_distance; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - minimum_distance = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - point = (FT_UShort)args[0]; - - if ( BOUNDS( point, exc->zp1.n_points ) || - BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - /* XXX: Is there some undocumented feature while in the */ - /* twilight zone? */ - - /* XXX: UNDOCUMENTED: twilight zone special case */ - - if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 ) - { - FT_Vector* vec1 = &exc->zp1.org[point]; - FT_Vector* vec2 = &exc->zp0.org[exc->GS.rp0]; - - - org_dist = DUALPROJ( vec1, vec2 ); - } - else - { - FT_Vector* vec1 = &exc->zp1.orus[point]; - FT_Vector* vec2 = &exc->zp0.orus[exc->GS.rp0]; - - - if ( exc->metrics.x_scale == exc->metrics.y_scale ) - { - /* this should be faster */ - org_dist = DUALPROJ( vec1, vec2 ); - org_dist = FT_MulFix( org_dist, exc->metrics.x_scale ); - } - else - { - FT_Vector vec; - - - vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale ); - vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale ); - - org_dist = FAST_DUALPROJ( &vec ); - } - } - - /* single width cut-in test */ - - if ( FT_ABS( org_dist - exc->GS.single_width_value ) < - exc->GS.single_width_cutin ) - { - if ( org_dist >= 0 ) - org_dist = exc->GS.single_width_value; - else - org_dist = -exc->GS.single_width_value; - } - - /* round flag */ - - if ( ( exc->opcode & 4 ) != 0 ) - { -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( - exc, - org_dist, - exc->tt_metrics.compensations[exc->opcode & 3] ); - else -#endif - distance = exc->func_round( - exc, - org_dist, - exc->tt_metrics.compensations[exc->opcode & 3] ); - } - else - distance = Round_None( - exc, - org_dist, - exc->tt_metrics.compensations[exc->opcode & 3] ); - - /* minimum distance flag */ - - if ( ( exc->opcode & 8 ) != 0 ) - { - if ( org_dist >= 0 ) - { - if ( distance < minimum_distance ) - distance = minimum_distance; - } - else - { - if ( distance > -minimum_distance ) - distance = -minimum_distance; - } - } - - /* now move the point */ - - org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); - - exc->func_move( exc, &exc->zp1, point, distance - org_dist ); - - Fail: - exc->GS.rp1 = exc->GS.rp0; - exc->GS.rp2 = point; - - if ( ( exc->opcode & 16 ) != 0 ) - exc->GS.rp0 = point; - } - - - /*************************************************************************/ - /* */ - /* MIRP[abcde]: Move Indirect Relative Point */ - /* Opcode range: 0xE0-0xFF */ - /* Stack: int32? uint32 --> */ - /* */ - static void - Ins_MIRP( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort point; - FT_ULong cvtEntry; - - FT_F26Dot6 cvt_dist, - distance, - cur_dist, - org_dist, - control_value_cutin, - minimum_distance; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_Int B1 = 0; /* pacify compiler */ - FT_Int B2 = 0; - FT_Bool reverse_move = FALSE; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - - minimum_distance = exc->GS.minimum_distance; - control_value_cutin = exc->GS.control_value_cutin; - point = (FT_UShort)args[0]; - cvtEntry = (FT_ULong)( args[1] + 1 ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = minimum_distance = 0; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ - - if ( BOUNDS( point, exc->zp1.n_points ) || - BOUNDSL( cvtEntry, exc->cvtSize + 1 ) || - BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - if ( !cvtEntry ) - cvt_dist = 0; - else - cvt_dist = exc->func_read_cvt( exc, cvtEntry - 1 ); - - /* single width test */ - - if ( FT_ABS( cvt_dist - exc->GS.single_width_value ) < - exc->GS.single_width_cutin ) - { - if ( cvt_dist >= 0 ) - cvt_dist = exc->GS.single_width_value; - else - cvt_dist = -exc->GS.single_width_value; - } - - /* UNDOCUMENTED! The MS rasterizer does that with */ - /* twilight points (confirmed by Greg Hitchcock) */ - if ( exc->GS.gep1 == 0 ) - { - exc->zp1.org[point].x = exc->zp0.org[exc->GS.rp0].x + - TT_MulFix14( cvt_dist, - exc->GS.freeVector.x ); - exc->zp1.org[point].y = exc->zp0.org[exc->GS.rp0].y + - TT_MulFix14( cvt_dist, - exc->GS.freeVector.y ); - exc->zp1.cur[point] = exc->zp1.org[point]; - } - - org_dist = DUALPROJ( &exc->zp1.org[point], &exc->zp0.org[exc->GS.rp0] ); - cur_dist = PROJECT ( &exc->zp1.cur[point], &exc->zp0.cur[exc->GS.rp0] ); - - /* auto-flip test */ - - if ( exc->GS.auto_flip ) - { - if ( ( org_dist ^ cvt_dist ) < 0 ) - cvt_dist = -cvt_dist; - } - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.freeVector.y != 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) - { - if ( cur_dist < -64 ) - cvt_dist -= 16; - else if ( cur_dist > 64 && cur_dist < 84 ) - cvt_dist += 32; - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* control value cut-in and round */ - - if ( ( exc->opcode & 4 ) != 0 ) - { - /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ - /* refer to the same zone. */ - - if ( exc->GS.gep0 == exc->GS.gep1 ) - { - /* XXX: According to Greg Hitchcock, the following wording is */ - /* the right one: */ - /* */ - /* When the absolute difference between the value in */ - /* the table [CVT] and the measurement directly from */ - /* the outline is _greater_ than the cut_in value, the */ - /* outline measurement is used. */ - /* */ - /* This is from `instgly.doc'. The description in */ - /* `ttinst2.doc', version 1.66, is thus incorrect since */ - /* it implies `>=' instead of `>'. */ - - if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) - cvt_dist = org_dist; - } - - distance = exc->func_round( - exc, - cvt_dist, - exc->tt_metrics.compensations[exc->opcode & 3] ); - } - else - { - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /* do cvt cut-in always in MIRP for sph */ - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->GS.gep0 == exc->GS.gep1 ) - { - if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) - cvt_dist = org_dist; - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - distance = Round_None( - exc, - cvt_dist, - exc->tt_metrics.compensations[exc->opcode & 3] ); - } - - /* minimum distance test */ - - if ( ( exc->opcode & 8 ) != 0 ) - { - if ( org_dist >= 0 ) - { - if ( distance < minimum_distance ) - distance = minimum_distance; - } - else - { - if ( distance > -minimum_distance ) - distance = -minimum_distance; - } - } - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) - { - B1 = exc->zp1.cur[point].y; - - /* Round moves if necessary */ - if ( exc->ignore_x_mode && - exc->GS.freeVector.y != 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) ) - distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist; - - if ( exc->ignore_x_mode && - exc->GS.freeVector.y != 0 && - ( exc->opcode & 16 ) == 0 && - ( exc->opcode & 8 ) == 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) ) - distance += 64; - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - exc->func_move( exc, &exc->zp1, point, distance - cur_dist ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING ) - { - B2 = exc->zp1.cur[point].y; - - /* Reverse move if necessary */ - if ( exc->ignore_x_mode ) - { - if ( exc->face->sph_compatibility_mode && - exc->GS.freeVector.y != 0 && - ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 ) - reverse_move = TRUE; - - if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && - exc->GS.freeVector.y != 0 && - ( B2 & 63 ) != 0 && - ( B1 & 63 ) != 0 ) - reverse_move = TRUE; - } - - if ( reverse_move ) - exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) ); - } - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - Fail: - exc->GS.rp1 = exc->GS.rp0; - - if ( ( exc->opcode & 16 ) != 0 ) - exc->GS.rp0 = point; - - exc->GS.rp2 = point; - } - - - /*************************************************************************/ - /* */ - /* ALIGNRP[]: ALIGN Relative Point */ - /* Opcode range: 0x3C */ - /* Stack: uint32 uint32... --> */ - /* */ - static void - Ins_ALIGNRP( TT_ExecContext exc ) - { - FT_UShort point; - FT_F26Dot6 distance; - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) ) - { - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - if ( exc->top < exc->GS.loop || - BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - while ( exc->GS.loop > 0 ) - { - exc->args--; - - point = (FT_UShort)exc->stack[exc->args]; - - if ( BOUNDS( point, exc->zp1.n_points ) ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Invalid_Reference ); - return; - } - } - else - { - distance = PROJECT( exc->zp1.cur + point, - exc->zp0.cur + exc->GS.rp0 ); - - exc->func_move( exc, &exc->zp1, point, -distance ); - } - - exc->GS.loop--; - } - - Fail: - exc->GS.loop = 1; - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* ISECT[]: moves point to InterSECTion */ - /* Opcode range: 0x0F */ - /* Stack: 5 * uint32 --> */ - /* */ - static void - Ins_ISECT( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort point, - a0, a1, - b0, b1; - - FT_F26Dot6 discriminant, dotproduct; - - FT_F26Dot6 dx, dy, - dax, day, - dbx, dby; - - FT_F26Dot6 val; - - FT_Vector R; - - - point = (FT_UShort)args[0]; - - a0 = (FT_UShort)args[1]; - a1 = (FT_UShort)args[2]; - b0 = (FT_UShort)args[3]; - b1 = (FT_UShort)args[4]; - - if ( BOUNDS( b0, exc->zp0.n_points ) || - BOUNDS( b1, exc->zp0.n_points ) || - BOUNDS( a0, exc->zp1.n_points ) || - BOUNDS( a1, exc->zp1.n_points ) || - BOUNDS( point, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - /* Cramer's rule */ - - dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x; - dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y; - - dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x; - day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y; - - dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x; - dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y; - - discriminant = FT_MulDiv( dax, -dby, 0x40 ) + - FT_MulDiv( day, dbx, 0x40 ); - dotproduct = FT_MulDiv( dax, dbx, 0x40 ) + - FT_MulDiv( day, dby, 0x40 ); - - /* The discriminant above is actually a cross product of vectors */ - /* da and db. Together with the dot product, they can be used as */ - /* surrogates for sine and cosine of the angle between the vectors. */ - /* Indeed, */ - /* dotproduct = |da||db|cos(angle) */ - /* discriminant = |da||db|sin(angle) . */ - /* We use these equations to reject grazing intersections by */ - /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */ - if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) ) - { - val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 ); - - R.x = FT_MulDiv( val, dax, discriminant ); - R.y = FT_MulDiv( val, day, discriminant ); - - exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x; - exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y; - } - else - { - /* else, take the middle of the middles of A and B */ - - exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x + - exc->zp1.cur[a1].x + - exc->zp0.cur[b0].x + - exc->zp0.cur[b1].x ) / 4; - exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y + - exc->zp1.cur[a1].y + - exc->zp0.cur[b0].y + - exc->zp0.cur[b1].y ) / 4; - } - - exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH; - } - - - /*************************************************************************/ - /* */ - /* ALIGNPTS[]: ALIGN PoinTS */ - /* Opcode range: 0x27 */ - /* Stack: uint32 uint32 --> */ - /* */ - static void - Ins_ALIGNPTS( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort p1, p2; - FT_F26Dot6 distance; - - - p1 = (FT_UShort)args[0]; - p2 = (FT_UShort)args[1]; - - if ( BOUNDS( p1, exc->zp1.n_points ) || - BOUNDS( p2, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2; - - exc->func_move( exc, &exc->zp1, p1, distance ); - exc->func_move( exc, &exc->zp0, p2, -distance ); - } - - - /*************************************************************************/ - /* */ - /* IP[]: Interpolate Point */ - /* Opcode range: 0x39 */ - /* Stack: uint32... --> */ - /* */ - - /* SOMETIMES, DUMBER CODE IS BETTER CODE */ - - static void - Ins_IP( TT_ExecContext exc ) - { - FT_F26Dot6 old_range, cur_range; - FT_Vector* orus_base; - FT_Vector* cur_base; - FT_Int twilight; - - - if ( exc->top < exc->GS.loop ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - /* - * We need to deal in a special way with the twilight zone. - * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0), - * for every n. - */ - twilight = exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || exc->GS.gep2 == 0; - - if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - - if ( twilight ) - orus_base = &exc->zp0.org[exc->GS.rp1]; - else - orus_base = &exc->zp0.orus[exc->GS.rp1]; - - cur_base = &exc->zp0.cur[exc->GS.rp1]; - - /* XXX: There are some glyphs in some braindead but popular */ - /* fonts out there (e.g. [aeu]grave in monotype.ttf) */ - /* calling IP[] with bad values of rp[12]. */ - /* Do something sane when this odd thing happens. */ - if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) || - BOUNDS( exc->GS.rp2, exc->zp1.n_points ) ) - { - old_range = 0; - cur_range = 0; - } - else - { - if ( twilight ) - old_range = DUALPROJ( &exc->zp1.org[exc->GS.rp2], orus_base ); - else if ( exc->metrics.x_scale == exc->metrics.y_scale ) - old_range = DUALPROJ( &exc->zp1.orus[exc->GS.rp2], orus_base ); - else - { - FT_Vector vec; - - - vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x, - exc->metrics.x_scale ); - vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y, - exc->metrics.y_scale ); - - old_range = FAST_DUALPROJ( &vec ); - } - - cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base ); - } - - for ( ; exc->GS.loop > 0; --exc->GS.loop ) - { - FT_UInt point = (FT_UInt)exc->stack[--exc->args]; - FT_F26Dot6 org_dist, cur_dist, new_dist; - - - /* check point bounds */ - if ( BOUNDS( point, exc->zp2.n_points ) ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Invalid_Reference ); - return; - } - continue; - } - - if ( twilight ) - org_dist = DUALPROJ( &exc->zp2.org[point], orus_base ); - else if ( exc->metrics.x_scale == exc->metrics.y_scale ) - org_dist = DUALPROJ( &exc->zp2.orus[point], orus_base ); - else - { - FT_Vector vec; - - - vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x, - exc->metrics.x_scale ); - vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y, - exc->metrics.y_scale ); - - org_dist = FAST_DUALPROJ( &vec ); - } - - cur_dist = PROJECT( &exc->zp2.cur[point], cur_base ); - - if ( org_dist ) - { - if ( old_range ) - new_dist = FT_MulDiv( org_dist, cur_range, old_range ); - else - { - /* This is the same as what MS does for the invalid case: */ - /* */ - /* delta = (Original_Pt - Original_RP1) - */ - /* (Current_Pt - Current_RP1) ; */ - /* */ - /* In FreeType speak: */ - /* */ - /* delta = org_dist - cur_dist . */ - /* */ - /* We move `point' by `new_dist - cur_dist' after leaving */ - /* this block, thus we have */ - /* */ - /* new_dist - cur_dist = delta , */ - /* new_dist - cur_dist = org_dist - cur_dist , */ - /* new_dist = org_dist . */ - - new_dist = org_dist; - } - } - else - new_dist = 0; - - exc->func_move( exc, - &exc->zp2, - (FT_UShort)point, - new_dist - cur_dist ); - } - - Fail: - exc->GS.loop = 1; - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* UTP[a]: UnTouch Point */ - /* Opcode range: 0x29 */ - /* Stack: uint32 --> */ - /* */ - static void - Ins_UTP( TT_ExecContext exc, - FT_Long* args ) - { - FT_UShort point; - FT_Byte mask; - - - point = (FT_UShort)args[0]; - - if ( BOUNDS( point, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - return; - } - - mask = 0xFF; - - if ( exc->GS.freeVector.x != 0 ) - mask &= ~FT_CURVE_TAG_TOUCH_X; - - if ( exc->GS.freeVector.y != 0 ) - mask &= ~FT_CURVE_TAG_TOUCH_Y; - - exc->zp0.tags[point] &= mask; - } - - - /* Local variables for Ins_IUP: */ - typedef struct IUP_WorkerRec_ - { - FT_Vector* orgs; /* original and current coordinate */ - FT_Vector* curs; /* arrays */ - FT_Vector* orus; - FT_UInt max_points; - - } IUP_WorkerRec, *IUP_Worker; - - - static void - _iup_worker_shift( IUP_Worker worker, - FT_UInt p1, - FT_UInt p2, - FT_UInt p ) - { - FT_UInt i; - FT_F26Dot6 dx; - - - dx = worker->curs[p].x - worker->orgs[p].x; - if ( dx != 0 ) - { - for ( i = p1; i < p; i++ ) - worker->curs[i].x += dx; - - for ( i = p + 1; i <= p2; i++ ) - worker->curs[i].x += dx; - } - } - - - static void - _iup_worker_interpolate( IUP_Worker worker, - FT_UInt p1, - FT_UInt p2, - FT_UInt ref1, - FT_UInt ref2 ) - { - FT_UInt i; - FT_F26Dot6 orus1, orus2, org1, org2, cur1, cur2, delta1, delta2; - - - if ( p1 > p2 ) - return; - - if ( BOUNDS( ref1, worker->max_points ) || - BOUNDS( ref2, worker->max_points ) ) - return; - - orus1 = worker->orus[ref1].x; - orus2 = worker->orus[ref2].x; - - if ( orus1 > orus2 ) - { - FT_F26Dot6 tmp_o; - FT_UInt tmp_r; - - - tmp_o = orus1; - orus1 = orus2; - orus2 = tmp_o; - - tmp_r = ref1; - ref1 = ref2; - ref2 = tmp_r; - } - - org1 = worker->orgs[ref1].x; - org2 = worker->orgs[ref2].x; - cur1 = worker->curs[ref1].x; - cur2 = worker->curs[ref2].x; - delta1 = cur1 - org1; - delta2 = cur2 - org2; - - if ( cur1 == cur2 || orus1 == orus2 ) - { - - /* trivial snap or shift of untouched points */ - for ( i = p1; i <= p2; i++ ) - { - FT_F26Dot6 x = worker->orgs[i].x; - - - if ( x <= org1 ) - x += delta1; - - else if ( x >= org2 ) - x += delta2; - - else - x = cur1; - - worker->curs[i].x = x; - } - } - else - { - FT_Fixed scale = 0; - FT_Bool scale_valid = 0; - - - /* interpolation */ - for ( i = p1; i <= p2; i++ ) - { - FT_F26Dot6 x = worker->orgs[i].x; - - - if ( x <= org1 ) - x += delta1; - - else if ( x >= org2 ) - x += delta2; - - else - { - if ( !scale_valid ) - { - scale_valid = 1; - scale = FT_DivFix( cur2 - cur1, orus2 - orus1 ); - } - - x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale ); - } - worker->curs[i].x = x; - } - } - } - - - /*************************************************************************/ - /* */ - /* IUP[a]: Interpolate Untouched Points */ - /* Opcode range: 0x30-0x31 */ - /* Stack: --> */ - /* */ - static void - Ins_IUP( TT_ExecContext exc ) - { - IUP_WorkerRec V; - FT_Byte mask; - - FT_UInt first_point; /* first point of contour */ - FT_UInt end_point; /* end point (last+1) of contour */ - - FT_UInt first_touched; /* first touched point in contour */ - FT_UInt cur_touched; /* current touched point in contour */ - - FT_UInt point; /* current point */ - FT_Short contour; /* current contour */ - - - /* ignore empty outlines */ - if ( exc->pts.n_contours == 0 ) - return; - - if ( exc->opcode & 1 ) - { - mask = FT_CURVE_TAG_TOUCH_X; - V.orgs = exc->pts.org; - V.curs = exc->pts.cur; - V.orus = exc->pts.orus; - } - else - { - mask = FT_CURVE_TAG_TOUCH_Y; - V.orgs = (FT_Vector*)( (FT_Pos*)exc->pts.org + 1 ); - V.curs = (FT_Vector*)( (FT_Pos*)exc->pts.cur + 1 ); - V.orus = (FT_Vector*)( (FT_Pos*)exc->pts.orus + 1 ); - } - V.max_points = exc->pts.n_points; - - contour = 0; - point = 0; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode ) - { - exc->iup_called = TRUE; - if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) - return; - } -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - do - { - end_point = exc->pts.contours[contour] - exc->pts.first_point; - first_point = point; - - if ( BOUNDS( end_point, exc->pts.n_points ) ) - end_point = exc->pts.n_points - 1; - - while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 ) - point++; - - if ( point <= end_point ) - { - first_touched = point; - cur_touched = point; - - point++; - - while ( point <= end_point ) - { - if ( ( exc->pts.tags[point] & mask ) != 0 ) - { - _iup_worker_interpolate( &V, - cur_touched + 1, - point - 1, - cur_touched, - point ); - cur_touched = point; - } - - point++; - } - - if ( cur_touched == first_touched ) - _iup_worker_shift( &V, first_point, end_point, cur_touched ); - else - { - _iup_worker_interpolate( &V, - (FT_UShort)( cur_touched + 1 ), - end_point, - cur_touched, - first_touched ); - - if ( first_touched > 0 ) - _iup_worker_interpolate( &V, - first_point, - first_touched - 1, - cur_touched, - first_touched ); - } - } - contour++; - } while ( contour < exc->pts.n_contours ); - } - - - /*************************************************************************/ - /* */ - /* DELTAPn[]: DELTA exceptions P1, P2, P3 */ - /* Opcode range: 0x5D,0x71,0x72 */ - /* Stack: uint32 (2 * uint32)... --> */ - /* */ - static void - Ins_DELTAP( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong nump, k; - FT_UShort A; - FT_ULong C, P; - FT_Long B; -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_UShort B1, B2; - - - if ( SUBPIXEL_HINTING && - exc->ignore_x_mode && - exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) - goto Fail; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - /* Delta hinting is covered by US Patent 5159668. */ - if ( exc->face->unpatented_hinting ) - { - FT_Long n = args[0] * 2; - - - if ( exc->args < n ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - n = exc->args; - } - - exc->args -= n; - exc->new_top = exc->args; - return; - } -#endif - - P = (FT_ULong)exc->func_cur_ppem( exc ); - nump = (FT_ULong)args[0]; /* some points theoretically may occur more - than once, thus UShort isn't enough */ - - for ( k = 1; k <= nump; k++ ) - { - if ( exc->args < 2 ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - exc->args = 0; - goto Fail; - } - - exc->args -= 2; - - A = (FT_UShort)exc->stack[exc->args + 1]; - B = exc->stack[exc->args]; - - /* XXX: Because some popular fonts contain some invalid DeltaP */ - /* instructions, we simply ignore them when the stacked */ - /* point reference is off limit, rather than returning an */ - /* error. As a delta instruction doesn't change a glyph */ - /* in great ways, this shouldn't be a problem. */ - - if ( !BOUNDS( A, exc->zp0.n_points ) ) - { - C = ( (FT_ULong)B & 0xF0 ) >> 4; - - switch ( exc->opcode ) - { - case 0x5D: - break; - - case 0x71: - C += 16; - break; - - case 0x72: - C += 32; - break; - } - - C += exc->GS.delta_base; - - if ( P == C ) - { - B = ( (FT_ULong)B & 0xF ) - 8; - if ( B >= 0 ) - B++; - B *= 1L << ( 6 - exc->GS.delta_shift ); - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( SUBPIXEL_HINTING ) - { - /* - * Allow delta move if - * - * - not using ignore_x_mode rendering, - * - glyph is specifically set to allow it, or - * - glyph is composite and freedom vector is not in subpixel - * direction. - */ - if ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) || - ( exc->is_composite && exc->GS.freeVector.y != 0 ) ) - exc->func_move( exc, &exc->zp0, A, B ); - - /* Otherwise, apply subpixel hinting and compatibility mode */ - /* rules, always skipping deltas in subpixel direction. */ - else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 ) - { - /* save the y value of the point now; compare after move */ - B1 = (FT_UShort)exc->zp0.cur[A].y; - - /* Standard subpixel hinting: Allow y move for y-touched */ - /* points. This messes up DejaVu ... */ - if ( !exc->face->sph_compatibility_mode && - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) - exc->func_move( exc, &exc->zp0, A, B ); - - /* compatibility mode */ - else if ( exc->face->sph_compatibility_mode && - !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) ) - { - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - B = FT_PIX_ROUND( B1 + B ) - B1; - - /* Allow delta move if using sph_compatibility_mode, */ - /* IUP has not been called, and point is touched on Y. */ - if ( !exc->iup_called && - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) - exc->func_move( exc, &exc->zp0, A, B ); - } - - B2 = (FT_UShort)exc->zp0.cur[A].y; - - /* Reverse this move if it results in a disallowed move */ - if ( exc->GS.freeVector.y != 0 && - ( ( exc->face->sph_compatibility_mode && - ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 ) || - ( ( exc->sph_tweak_flags & - SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 ) ) ) - exc->func_move( exc, &exc->zp0, A, -B ); - } - } - else -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - exc->func_move( exc, &exc->zp0, A, B ); - } - } - else - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - } - - Fail: - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* DELTACn[]: DELTA exceptions C1, C2, C3 */ - /* Opcode range: 0x73,0x74,0x75 */ - /* Stack: uint32 (2 * uint32)... --> */ - /* */ - static void - Ins_DELTAC( TT_ExecContext exc, - FT_Long* args ) - { - FT_ULong nump, k; - FT_ULong A, C, P; - FT_Long B; - - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - /* Delta hinting is covered by US Patent 5159668. */ - if ( exc->face->unpatented_hinting ) - { - FT_Long n = args[0] * 2; - - - if ( exc->args < n ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - n = exc->args; - } - - exc->args -= n; - exc->new_top = exc->args; - return; - } -#endif - - P = (FT_ULong)exc->func_cur_ppem( exc ); - nump = (FT_ULong)args[0]; - - for ( k = 1; k <= nump; k++ ) - { - if ( exc->args < 2 ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - exc->args = 0; - goto Fail; - } - - exc->args -= 2; - - A = (FT_ULong)exc->stack[exc->args + 1]; - B = exc->stack[exc->args]; - - if ( BOUNDSL( A, exc->cvtSize ) ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Invalid_Reference ); - return; - } - } - else - { - C = ( (FT_ULong)B & 0xF0 ) >> 4; - - switch ( exc->opcode ) - { - case 0x73: - break; - - case 0x74: - C += 16; - break; - - case 0x75: - C += 32; - break; - } - - C += exc->GS.delta_base; - - if ( P == C ) - { - B = ( (FT_ULong)B & 0xF ) - 8; - if ( B >= 0 ) - B++; - B *= 1L << ( 6 - exc->GS.delta_shift ); - - exc->func_move_cvt( exc, A, B ); - } - } - } - - Fail: - exc->new_top = exc->args; - } - - - /*************************************************************************/ - /* */ - /* MISC. INSTRUCTIONS */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* GETINFO[]: GET INFOrmation */ - /* Opcode range: 0x88 */ - /* Stack: uint32 --> uint32 */ - /* */ - /* XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May */ - /* 2015) not documented in the OpenType specification. */ - /* */ - /* Selector bit 11 is incorrectly described as bit 8, while the */ - /* real meaning of bit 8 (vertical LCD subpixels) stays */ - /* undocumented. The same mistake can be found in Greg Hitchcock's */ - /* whitepaper. */ - /* */ - static void - Ins_GETINFO( TT_ExecContext exc, - FT_Long* args ) - { - FT_Long K; - - - K = 0; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - /********************************/ - /* RASTERIZER VERSION */ - /* Selector Bit: 0 */ - /* Return Bit(s): 0-7 */ - /* */ - if ( SUBPIXEL_HINTING && - ( args[0] & 1 ) != 0 && - exc->subpixel_hinting ) - { - if ( exc->ignore_x_mode ) - { - /* if in ClearType backwards compatibility mode, */ - /* we sometimes change the TrueType version dynamically */ - K = exc->rasterizer_version; - FT_TRACE6(( "Setting rasterizer version %d\n", - exc->rasterizer_version )); - } - else - K = TT_INTERPRETER_VERSION_38; - } - else -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - if ( ( args[0] & 1 ) != 0 ) - K = TT_INTERPRETER_VERSION_35; - - /********************************/ - /* GLYPH ROTATED */ - /* Selector Bit: 1 */ - /* Return Bit(s): 8 */ - /* */ - if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated ) - K |= 0x80; - - /********************************/ - /* GLYPH STRETCHED */ - /* Selector Bit: 2 */ - /* Return Bit(s): 9 */ - /* */ - if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched ) - K |= 1 << 8; - - /********************************/ - /* HINTING FOR GRAYSCALE */ - /* Selector Bit: 5 */ - /* Return Bit(s): 12 */ - /* */ - if ( ( args[0] & 32 ) != 0 && exc->grayscale ) - K |= 1 << 12; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( SUBPIXEL_HINTING && - exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 ) - { - - if ( exc->rasterizer_version >= 37 ) - { - /********************************/ - /* HINTING FOR SUBPIXEL */ - /* Selector Bit: 6 */ - /* Return Bit(s): 13 */ - /* */ - if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting ) - K |= 1 << 13; - - /********************************/ - /* COMPATIBLE WIDTHS ENABLED */ - /* Selector Bit: 7 */ - /* Return Bit(s): 14 */ - /* */ - /* Functionality still needs to be added */ - if ( ( args[0] & 128 ) != 0 && exc->compatible_widths ) - K |= 1 << 14; - - /********************************/ - /* VERTICAL LCD SUBPIXELS? */ - /* Selector Bit: 8 */ - /* Return Bit(s): 15 */ - /* */ - /* Functionality still needs to be added */ - if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd ) - K |= 1 << 15; - - /********************************/ - /* HINTING FOR BGR? */ - /* Selector Bit: 9 */ - /* Return Bit(s): 16 */ - /* */ - /* Functionality still needs to be added */ - if ( ( args[0] & 512 ) != 0 && exc->bgr ) - K |= 1 << 16; - - if ( exc->rasterizer_version >= 38 ) - { - /********************************/ - /* SUBPIXEL POSITIONED? */ - /* Selector Bit: 10 */ - /* Return Bit(s): 17 */ - /* */ - /* Functionality still needs to be added */ - if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned ) - K |= 1 << 17; - - /********************************/ - /* SYMMETRICAL SMOOTHING */ - /* Selector Bit: 11 */ - /* Return Bit(s): 18 */ - /* */ - /* Functionality still needs to be added */ - if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing ) - K |= 1 << 18; - - /********************************/ - /* GRAY CLEARTYPE */ - /* Selector Bit: 12 */ - /* Return Bit(s): 19 */ - /* */ - /* Functionality still needs to be added */ - if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype ) - K |= 1 << 19; - } - } - } - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - args[0] = K; - } - - - static void - Ins_UNKNOWN( TT_ExecContext exc ) - { - TT_DefRecord* def = exc->IDefs; - TT_DefRecord* limit = def + exc->numIDefs; - - - for ( ; def < limit; def++ ) - { - if ( (FT_Byte)def->opc == exc->opcode && def->active ) - { - TT_CallRec* call; - - - if ( exc->callTop >= exc->callSize ) - { - exc->error = FT_THROW( Stack_Overflow ); - return; - } - - call = exc->callStack + exc->callTop++; - - call->Caller_Range = exc->curRange; - call->Caller_IP = exc->IP + 1; - call->Cur_Count = 1; - call->Def = def; - - Ins_Goto_CodeRange( exc, def->range, def->start ); - - exc->step_ins = FALSE; - return; - } - } - - exc->error = FT_THROW( Invalid_Opcode ); - } - - - /*************************************************************************/ - /* */ - /* RUN */ - /* */ - /* This function executes a run of opcodes. It will exit in the */ - /* following cases: */ - /* */ - /* - Errors (in which case it returns FALSE). */ - /* */ - /* - Reaching the end of the main code range (returns TRUE). */ - /* Reaching the end of a code range within a function call is an */ - /* error. */ - /* */ - /* - After executing one single opcode, if the flag `Instruction_Trap' */ - /* is set to TRUE (returns TRUE). */ - /* */ - /* On exit with TRUE, test IP < CodeSize to know whether it comes from */ - /* an instruction trap or a normal termination. */ - /* */ - /* */ - /* Note: The documented DEBUG opcode pops a value from the stack. This */ - /* behaviour is unsupported; here a DEBUG opcode is always an */ - /* error. */ - /* */ - /* */ - /* THIS IS THE INTERPRETER'S MAIN LOOP. */ - /* */ - /*************************************************************************/ - - - /* documentation is in ttinterp.h */ - - FT_EXPORT_DEF( FT_Error ) - TT_RunIns( TT_ExecContext exc ) - { - FT_Long ins_counter = 0; /* executed instructions counter */ - FT_UShort i; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - FT_Byte opcode_pattern[1][2] = { - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; - FT_UShort opcode_patterns = 1; - FT_UShort opcode_pointer[1] = { 0 }; - FT_UShort opcode_size[1] = { 1 }; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - exc->iup_called = FALSE; -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* set PPEM and CVT functions */ - exc->tt_metrics.ratio = 0; - if ( exc->metrics.x_ppem != exc->metrics.y_ppem ) - { - /* non-square pixels, use the stretched routines */ - exc->func_cur_ppem = Current_Ppem_Stretched; - exc->func_read_cvt = Read_CVT_Stretched; - exc->func_write_cvt = Write_CVT_Stretched; - exc->func_move_cvt = Move_CVT_Stretched; - } - else - { - /* square pixels, use normal routines */ - exc->func_cur_ppem = Current_Ppem; - exc->func_read_cvt = Read_CVT; - exc->func_write_cvt = Write_CVT; - exc->func_move_cvt = Move_CVT; - } - - Compute_Funcs( exc ); - Compute_Round( exc, (FT_Byte)exc->GS.round_state ); - - do - { - exc->opcode = exc->code[exc->IP]; - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_Long cnt = FT_MIN( 8, exc->top ); - FT_Long n; - - - /* if tracing level is 7, show current code position */ - /* and the first few stack elements also */ - FT_TRACE6(( " " )); - FT_TRACE7(( "%06d ", exc->IP )); - FT_TRACE6(( opcode_name[exc->opcode] + 2 )); - FT_TRACE7(( "%*s", *opcode_name[exc->opcode] == 'A' - ? 2 - : 12 - ( *opcode_name[exc->opcode] - '0' ), - "#" )); - for ( n = 0; n < cnt; n++ ) - FT_TRACE7(( " %d", exc->stack[exc->top - n] )); - FT_TRACE6(( "\n" )); - } -#endif /* FT_DEBUG_LEVEL_TRACE */ - - if ( ( exc->length = opcode_length[exc->opcode] ) < 0 ) - { - if ( exc->IP + 1 >= exc->codeSize ) - goto LErrorCodeOverflow_; - - exc->length = 2 - exc->length * exc->code[exc->IP + 1]; - } - - if ( exc->IP + exc->length > exc->codeSize ) - goto LErrorCodeOverflow_; - - /* First, let's check for empty stack and overflow */ - exc->args = exc->top - ( Pop_Push_Count[exc->opcode] >> 4 ); - - /* `args' is the top of the stack once arguments have been popped. */ - /* One can also interpret it as the index of the last argument. */ - if ( exc->args < 0 ) - { - if ( exc->pedantic_hinting ) - { - exc->error = FT_THROW( Too_Few_Arguments ); - goto LErrorLabel_; - } - - /* push zeroes onto the stack */ - for ( i = 0; i < Pop_Push_Count[exc->opcode] >> 4; i++ ) - exc->stack[i] = 0; - exc->args = 0; - } - - exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 ); - - /* `new_top' is the new top of the stack, after the instruction's */ - /* execution. `top' will be set to `new_top' after the `switch' */ - /* statement. */ - if ( exc->new_top > exc->stackSize ) - { - exc->error = FT_THROW( Stack_Overflow ); - goto LErrorLabel_; - } - - exc->step_ins = TRUE; - exc->error = FT_Err_Ok; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - if ( SUBPIXEL_HINTING ) - { - for ( i = 0; i < opcode_patterns; i++ ) - { - if ( opcode_pointer[i] < opcode_size[i] && - exc->opcode == opcode_pattern[i][opcode_pointer[i]] ) - { - opcode_pointer[i] += 1; - - if ( opcode_pointer[i] == opcode_size[i] ) - { - FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n", - i, - exc->face->root.family_name, - exc->face->root.style_name )); - - switch ( i ) - { - case 0: - break; - } - opcode_pointer[i] = 0; - } - } - else - opcode_pointer[i] = 0; - } - } - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - { - FT_Long* args = exc->stack + exc->args; - FT_Byte opcode = exc->opcode; - - - switch ( opcode ) - { - case 0x00: /* SVTCA y */ - case 0x01: /* SVTCA x */ - case 0x02: /* SPvTCA y */ - case 0x03: /* SPvTCA x */ - case 0x04: /* SFvTCA y */ - case 0x05: /* SFvTCA x */ - Ins_SxyTCA( exc ); - break; - - case 0x06: /* SPvTL // */ - case 0x07: /* SPvTL + */ - Ins_SPVTL( exc, args ); - break; - - case 0x08: /* SFvTL // */ - case 0x09: /* SFvTL + */ - Ins_SFVTL( exc, args ); - break; - - case 0x0A: /* SPvFS */ - Ins_SPVFS( exc, args ); - break; - - case 0x0B: /* SFvFS */ - Ins_SFVFS( exc, args ); - break; - - case 0x0C: /* GPv */ - Ins_GPV( exc, args ); - break; - - case 0x0D: /* GFv */ - Ins_GFV( exc, args ); - break; - - case 0x0E: /* SFvTPv */ - Ins_SFVTPV( exc ); - break; - - case 0x0F: /* ISECT */ - Ins_ISECT( exc, args ); - break; - - case 0x10: /* SRP0 */ - Ins_SRP0( exc, args ); - break; - - case 0x11: /* SRP1 */ - Ins_SRP1( exc, args ); - break; - - case 0x12: /* SRP2 */ - Ins_SRP2( exc, args ); - break; - - case 0x13: /* SZP0 */ - Ins_SZP0( exc, args ); - break; - - case 0x14: /* SZP1 */ - Ins_SZP1( exc, args ); - break; - - case 0x15: /* SZP2 */ - Ins_SZP2( exc, args ); - break; - - case 0x16: /* SZPS */ - Ins_SZPS( exc, args ); - break; - - case 0x17: /* SLOOP */ - Ins_SLOOP( exc, args ); - break; - - case 0x18: /* RTG */ - Ins_RTG( exc ); - break; - - case 0x19: /* RTHG */ - Ins_RTHG( exc ); - break; - - case 0x1A: /* SMD */ - Ins_SMD( exc, args ); - break; - - case 0x1B: /* ELSE */ - Ins_ELSE( exc ); - break; - - case 0x1C: /* JMPR */ - Ins_JMPR( exc, args ); - break; - - case 0x1D: /* SCVTCI */ - Ins_SCVTCI( exc, args ); - break; - - case 0x1E: /* SSWCI */ - Ins_SSWCI( exc, args ); - break; - - case 0x1F: /* SSW */ - Ins_SSW( exc, args ); - break; - - case 0x20: /* DUP */ - Ins_DUP( args ); - break; - - case 0x21: /* POP */ - Ins_POP(); - break; - - case 0x22: /* CLEAR */ - Ins_CLEAR( exc ); - break; - - case 0x23: /* SWAP */ - Ins_SWAP( args ); - break; - - case 0x24: /* DEPTH */ - Ins_DEPTH( exc, args ); - break; - - case 0x25: /* CINDEX */ - Ins_CINDEX( exc, args ); - break; - - case 0x26: /* MINDEX */ - Ins_MINDEX( exc, args ); - break; - - case 0x27: /* ALIGNPTS */ - Ins_ALIGNPTS( exc, args ); - break; - - case 0x28: /* ???? */ - Ins_UNKNOWN( exc ); - break; - - case 0x29: /* UTP */ - Ins_UTP( exc, args ); - break; - - case 0x2A: /* LOOPCALL */ - Ins_LOOPCALL( exc, args ); - break; - - case 0x2B: /* CALL */ - Ins_CALL( exc, args ); - break; - - case 0x2C: /* FDEF */ - Ins_FDEF( exc, args ); - break; - - case 0x2D: /* ENDF */ - Ins_ENDF( exc ); - break; - - case 0x2E: /* MDAP */ - case 0x2F: /* MDAP */ - Ins_MDAP( exc, args ); - break; - - case 0x30: /* IUP */ - case 0x31: /* IUP */ - Ins_IUP( exc ); - break; - - case 0x32: /* SHP */ - case 0x33: /* SHP */ - Ins_SHP( exc ); - break; - - case 0x34: /* SHC */ - case 0x35: /* SHC */ - Ins_SHC( exc, args ); - break; - - case 0x36: /* SHZ */ - case 0x37: /* SHZ */ - Ins_SHZ( exc, args ); - break; - - case 0x38: /* SHPIX */ - Ins_SHPIX( exc, args ); - break; - - case 0x39: /* IP */ - Ins_IP( exc ); - break; - - case 0x3A: /* MSIRP */ - case 0x3B: /* MSIRP */ - Ins_MSIRP( exc, args ); - break; - - case 0x3C: /* AlignRP */ - Ins_ALIGNRP( exc ); - break; - - case 0x3D: /* RTDG */ - Ins_RTDG( exc ); - break; - - case 0x3E: /* MIAP */ - case 0x3F: /* MIAP */ - Ins_MIAP( exc, args ); - break; - - case 0x40: /* NPUSHB */ - Ins_NPUSHB( exc, args ); - break; - - case 0x41: /* NPUSHW */ - Ins_NPUSHW( exc, args ); - break; - - case 0x42: /* WS */ - Ins_WS( exc, args ); - break; - - case 0x43: /* RS */ - Ins_RS( exc, args ); - break; - - case 0x44: /* WCVTP */ - Ins_WCVTP( exc, args ); - break; - - case 0x45: /* RCVT */ - Ins_RCVT( exc, args ); - break; - - case 0x46: /* GC */ - case 0x47: /* GC */ - Ins_GC( exc, args ); - break; - - case 0x48: /* SCFS */ - Ins_SCFS( exc, args ); - break; - - case 0x49: /* MD */ - case 0x4A: /* MD */ - Ins_MD( exc, args ); - break; - - case 0x4B: /* MPPEM */ - Ins_MPPEM( exc, args ); - break; - - case 0x4C: /* MPS */ - Ins_MPS( exc, args ); - break; - - case 0x4D: /* FLIPON */ - Ins_FLIPON( exc ); - break; - - case 0x4E: /* FLIPOFF */ - Ins_FLIPOFF( exc ); - break; - - case 0x4F: /* DEBUG */ - Ins_DEBUG( exc ); - break; - - case 0x50: /* LT */ - Ins_LT( args ); - break; - - case 0x51: /* LTEQ */ - Ins_LTEQ( args ); - break; - - case 0x52: /* GT */ - Ins_GT( args ); - break; - - case 0x53: /* GTEQ */ - Ins_GTEQ( args ); - break; - - case 0x54: /* EQ */ - Ins_EQ( args ); - break; - - case 0x55: /* NEQ */ - Ins_NEQ( args ); - break; - - case 0x56: /* ODD */ - Ins_ODD( exc, args ); - break; - - case 0x57: /* EVEN */ - Ins_EVEN( exc, args ); - break; - - case 0x58: /* IF */ - Ins_IF( exc, args ); - break; - - case 0x59: /* EIF */ - Ins_EIF(); - break; - - case 0x5A: /* AND */ - Ins_AND( args ); - break; - - case 0x5B: /* OR */ - Ins_OR( args ); - break; - - case 0x5C: /* NOT */ - Ins_NOT( args ); - break; - - case 0x5D: /* DELTAP1 */ - Ins_DELTAP( exc, args ); - break; - - case 0x5E: /* SDB */ - Ins_SDB( exc, args ); - break; - - case 0x5F: /* SDS */ - Ins_SDS( exc, args ); - break; - - case 0x60: /* ADD */ - Ins_ADD( args ); - break; - - case 0x61: /* SUB */ - Ins_SUB( args ); - break; - - case 0x62: /* DIV */ - Ins_DIV( exc, args ); - break; - - case 0x63: /* MUL */ - Ins_MUL( args ); - break; - - case 0x64: /* ABS */ - Ins_ABS( args ); - break; - - case 0x65: /* NEG */ - Ins_NEG( args ); - break; - - case 0x66: /* FLOOR */ - Ins_FLOOR( args ); - break; - - case 0x67: /* CEILING */ - Ins_CEILING( args ); - break; - - case 0x68: /* ROUND */ - case 0x69: /* ROUND */ - case 0x6A: /* ROUND */ - case 0x6B: /* ROUND */ - Ins_ROUND( exc, args ); - break; - - case 0x6C: /* NROUND */ - case 0x6D: /* NROUND */ - case 0x6E: /* NRRUND */ - case 0x6F: /* NROUND */ - Ins_NROUND( exc, args ); - break; - - case 0x70: /* WCVTF */ - Ins_WCVTF( exc, args ); - break; - - case 0x71: /* DELTAP2 */ - case 0x72: /* DELTAP3 */ - Ins_DELTAP( exc, args ); - break; - - case 0x73: /* DELTAC0 */ - case 0x74: /* DELTAC1 */ - case 0x75: /* DELTAC2 */ - Ins_DELTAC( exc, args ); - break; - - case 0x76: /* SROUND */ - Ins_SROUND( exc, args ); - break; - - case 0x77: /* S45Round */ - Ins_S45ROUND( exc, args ); - break; - - case 0x78: /* JROT */ - Ins_JROT( exc, args ); - break; - - case 0x79: /* JROF */ - Ins_JROF( exc, args ); - break; - - case 0x7A: /* ROFF */ - Ins_ROFF( exc ); - break; - - case 0x7B: /* ???? */ - Ins_UNKNOWN( exc ); - break; - - case 0x7C: /* RUTG */ - Ins_RUTG( exc ); - break; - - case 0x7D: /* RDTG */ - Ins_RDTG( exc ); - break; - - case 0x7E: /* SANGW */ - Ins_SANGW(); - break; - - case 0x7F: /* AA */ - Ins_AA(); - break; - - case 0x80: /* FLIPPT */ - Ins_FLIPPT( exc ); - break; - - case 0x81: /* FLIPRGON */ - Ins_FLIPRGON( exc, args ); - break; - - case 0x82: /* FLIPRGOFF */ - Ins_FLIPRGOFF( exc, args ); - break; - - case 0x83: /* UNKNOWN */ - case 0x84: /* UNKNOWN */ - Ins_UNKNOWN( exc ); - break; - - case 0x85: /* SCANCTRL */ - Ins_SCANCTRL( exc, args ); - break; - - case 0x86: /* SDPvTL */ - case 0x87: /* SDPvTL */ - Ins_SDPVTL( exc, args ); - break; - - case 0x88: /* GETINFO */ - Ins_GETINFO( exc, args ); - break; - - case 0x89: /* IDEF */ - Ins_IDEF( exc, args ); - break; - - case 0x8A: /* ROLL */ - Ins_ROLL( args ); - break; - - case 0x8B: /* MAX */ - Ins_MAX( args ); - break; - - case 0x8C: /* MIN */ - Ins_MIN( args ); - break; - - case 0x8D: /* SCANTYPE */ - Ins_SCANTYPE( exc, args ); - break; - - case 0x8E: /* INSTCTRL */ - Ins_INSTCTRL( exc, args ); - break; - - case 0x8F: - Ins_UNKNOWN( exc ); - break; - - default: - if ( opcode >= 0xE0 ) - Ins_MIRP( exc, args ); - else if ( opcode >= 0xC0 ) - Ins_MDRP( exc, args ); - else if ( opcode >= 0xB8 ) - Ins_PUSHW( exc, args ); - else if ( opcode >= 0xB0 ) - Ins_PUSHB( exc, args ); - else - Ins_UNKNOWN( exc ); - } - } - - if ( exc->error ) - { - switch ( exc->error ) - { - /* looking for redefined instructions */ - case FT_ERR( Invalid_Opcode ): - { - TT_DefRecord* def = exc->IDefs; - TT_DefRecord* limit = def + exc->numIDefs; - - - for ( ; def < limit; def++ ) - { - if ( def->active && exc->opcode == (FT_Byte)def->opc ) - { - TT_CallRec* callrec; - - - if ( exc->callTop >= exc->callSize ) - { - exc->error = FT_THROW( Invalid_Reference ); - goto LErrorLabel_; - } - - callrec = &exc->callStack[exc->callTop]; - - callrec->Caller_Range = exc->curRange; - callrec->Caller_IP = exc->IP + 1; - callrec->Cur_Count = 1; - callrec->Def = def; - - if ( Ins_Goto_CodeRange( exc, - def->range, - def->start ) == FAILURE ) - goto LErrorLabel_; - - goto LSuiteLabel_; - } - } - } - - exc->error = FT_THROW( Invalid_Opcode ); - goto LErrorLabel_; - -#if 0 - break; /* Unreachable code warning suppression. */ - /* Leave to remind in case a later change the editor */ - /* to consider break; */ -#endif - - default: - goto LErrorLabel_; - -#if 0 - break; -#endif - } - } - - exc->top = exc->new_top; - - if ( exc->step_ins ) - exc->IP += exc->length; - - /* increment instruction counter and check if we didn't */ - /* run this program for too long (e.g. infinite loops). */ - if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) - return FT_THROW( Execution_Too_Long ); - - LSuiteLabel_: - if ( exc->IP >= exc->codeSize ) - { - if ( exc->callTop > 0 ) - { - exc->error = FT_THROW( Code_Overflow ); - goto LErrorLabel_; - } - else - goto LNo_Error_; - } - } while ( !exc->instruction_trap ); - - LNo_Error_: - return FT_Err_Ok; - - LErrorCodeOverflow_: - exc->error = FT_THROW( Code_Overflow ); - - LErrorLabel_: - /* If any errors have occurred, function tables may be broken. */ - /* Force a re-execution of `prep' and `fpgm' tables if no */ - /* bytecode debugger is run. */ - if ( exc->error && - !exc->instruction_trap && - exc->curRange == tt_coderange_glyph ) - { - FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error )); - exc->size->bytecode_ready = -1; - exc->size->cvt_ready = -1; - } - - return exc->error; - } - - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttinterp.h b/third_party/freetype/src/truetype/ttinterp.h deleted file mode 100644 index 32706d076047a04b2a6cc8dad56300a8e40788fd..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttinterp.h +++ /dev/null @@ -1,388 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttinterp.h */ -/* */ -/* TrueType bytecode interpreter (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTINTERP_H__ -#define __TTINTERP_H__ - -#include <ft2build.h> -#include "ttobjs.h" - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* Rounding mode constants. */ - /* */ -#define TT_Round_Off 5 -#define TT_Round_To_Half_Grid 0 -#define TT_Round_To_Grid 1 -#define TT_Round_To_Double_Grid 2 -#define TT_Round_Up_To_Grid 4 -#define TT_Round_Down_To_Grid 3 -#define TT_Round_Super 6 -#define TT_Round_Super_45 7 - - - /*************************************************************************/ - /* */ - /* Function types used by the interpreter, depending on various modes */ - /* (e.g. the rounding mode, whether to render a vertical or horizontal */ - /* line etc). */ - /* */ - /*************************************************************************/ - - /* Rounding function */ - typedef FT_F26Dot6 - (*TT_Round_Func)( TT_ExecContext exc, - FT_F26Dot6 distance, - FT_F26Dot6 compensation ); - - /* Point displacement along the freedom vector routine */ - typedef void - (*TT_Move_Func)( TT_ExecContext exc, - TT_GlyphZone zone, - FT_UShort point, - FT_F26Dot6 distance ); - - /* Distance projection along one of the projection vectors */ - typedef FT_F26Dot6 - (*TT_Project_Func)( TT_ExecContext exc, - FT_Pos dx, - FT_Pos dy ); - - /* getting current ppem. Take care of non-square pixels if necessary */ - typedef FT_Long - (*TT_Cur_Ppem_Func)( TT_ExecContext exc ); - - /* reading a cvt value. Take care of non-square pixels if necessary */ - typedef FT_F26Dot6 - (*TT_Get_CVT_Func)( TT_ExecContext exc, - FT_ULong idx ); - - /* setting or moving a cvt value. Take care of non-square pixels */ - /* if necessary */ - typedef void - (*TT_Set_CVT_Func)( TT_ExecContext exc, - FT_ULong idx, - FT_F26Dot6 value ); - - - /*************************************************************************/ - /* */ - /* This structure defines a call record, used to manage function calls. */ - /* */ - typedef struct TT_CallRec_ - { - FT_Int Caller_Range; - FT_Long Caller_IP; - FT_Long Cur_Count; - - TT_DefRecord *Def; /* either FDEF or IDEF */ - - } TT_CallRec, *TT_CallStack; - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - /*************************************************************************/ - /* */ - /* These structures define rules used to tweak subpixel hinting for */ - /* various fonts. "", 0, "", NULL value indicates to match any value. */ - /* */ - -#define SPH_MAX_NAME_SIZE 32 -#define SPH_MAX_CLASS_MEMBERS 100 - - typedef struct SPH_TweakRule_ - { - const char family[SPH_MAX_NAME_SIZE]; - const FT_UInt ppem; - const char style[SPH_MAX_NAME_SIZE]; - const FT_ULong glyph; - - } SPH_TweakRule; - - - typedef struct SPH_ScaleRule_ - { - const char family[SPH_MAX_NAME_SIZE]; - const FT_UInt ppem; - const char style[SPH_MAX_NAME_SIZE]; - const FT_ULong glyph; - const FT_ULong scale; - - } SPH_ScaleRule; - - - typedef struct SPH_Font_Class_ - { - const char name[SPH_MAX_NAME_SIZE]; - const char member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE]; - - } SPH_Font_Class; - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - - /*************************************************************************/ - /* */ - /* The main structure for the interpreter which collects all necessary */ - /* variables and states. */ - /* */ - typedef struct TT_ExecContextRec_ - { - TT_Face face; - TT_Size size; - FT_Memory memory; - - /* instructions state */ - - FT_Error error; /* last execution error */ - - FT_Long top; /* top of exec. stack */ - - FT_Long stackSize; /* size of exec. stack */ - FT_Long* stack; /* current exec. stack */ - - FT_Long args; - FT_Long new_top; /* new top after exec. */ - - TT_GlyphZoneRec zp0, /* zone records */ - zp1, - zp2, - pts, - twilight; - - FT_Size_Metrics metrics; - TT_Size_Metrics tt_metrics; /* size metrics */ - - TT_GraphicsState GS; /* current graphics state */ - - FT_Int curRange; /* current code range number */ - FT_Byte* code; /* current code range */ - FT_Long IP; /* current instruction pointer */ - FT_Long codeSize; /* size of current range */ - - FT_Byte opcode; /* current opcode */ - FT_Int length; /* length of current opcode */ - - FT_Bool step_ins; /* true if the interpreter must */ - /* increment IP after ins. exec */ - FT_ULong cvtSize; - FT_Long* cvt; - - FT_UInt glyphSize; /* glyph instructions buffer size */ - FT_Byte* glyphIns; /* glyph instructions buffer */ - - FT_UInt numFDefs; /* number of function defs */ - FT_UInt maxFDefs; /* maximum number of function defs */ - TT_DefArray FDefs; /* table of FDefs entries */ - - FT_UInt numIDefs; /* number of instruction defs */ - FT_UInt maxIDefs; /* maximum number of ins defs */ - TT_DefArray IDefs; /* table of IDefs entries */ - - FT_UInt maxFunc; /* maximum function index */ - FT_UInt maxIns; /* maximum instruction index */ - - FT_Int callTop, /* top of call stack during execution */ - callSize; /* size of call stack */ - TT_CallStack callStack; /* call stack */ - - FT_UShort maxPoints; /* capacity of this context's `pts' */ - FT_Short maxContours; /* record, expressed in points and */ - /* contours. */ - - TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */ - /* useful for the debugger */ - - FT_UShort storeSize; /* size of current storage */ - FT_Long* storage; /* storage area */ - - FT_F26Dot6 period; /* values used for the */ - FT_F26Dot6 phase; /* `SuperRounding' */ - FT_F26Dot6 threshold; - - FT_Bool instruction_trap; /* If `True', the interpreter will */ - /* exit after each instruction */ - - TT_GraphicsState default_GS; /* graphics state resulting from */ - /* the prep program */ - FT_Bool is_composite; /* true if the glyph is composite */ - FT_Bool pedantic_hinting; /* true if pedantic interpretation */ - - /* latest interpreter additions */ - - FT_Long F_dot_P; /* dot product of freedom and projection */ - /* vectors */ - TT_Round_Func func_round; /* current rounding function */ - - TT_Project_Func func_project, /* current projection function */ - func_dualproj, /* current dual proj. function */ - func_freeProj; /* current freedom proj. func */ - - TT_Move_Func func_move; /* current point move function */ - TT_Move_Func func_move_orig; /* move original position function */ - - TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */ - - TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */ - TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */ - TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */ - - FT_Bool grayscale; /* are we hinting for grayscale? */ - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Round_Func func_round_sphn; /* subpixel rounding function */ - - FT_Bool subpixel_hinting; /* Using subpixel hinting? */ - FT_Bool ignore_x_mode; /* Standard rendering mode for */ - /* subpixel hinting. On if gray */ - /* or subpixel hinting is on. */ - - /* The following 6 aren't fully implemented but here for MS rasterizer */ - /* compatibility. */ - FT_Bool compatible_widths; /* compatible widths? */ - FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */ - FT_Bool bgr; /* bgr instead of rgb? */ - FT_Bool vertical_lcd; /* long side of LCD subpixel */ - /* rectangles is horizontal */ - FT_Bool subpixel_positioned; /* subpixel positioned */ - /* (DirectWrite ClearType)? */ - FT_Bool gray_cleartype; /* ClearType hinting but */ - /* grayscale rendering */ - - FT_Int rasterizer_version; /* MS rasterizer version */ - - FT_Bool iup_called; /* IUP called for glyph? */ - - FT_ULong sph_tweak_flags; /* flags to control */ - /* hint tweaks */ - - FT_ULong sph_in_func_flags; /* flags to indicate if in */ - /* special functions */ - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - } TT_ExecContextRec; - - - extern const TT_GraphicsState tt_default_graphics_state; - - -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_LOCAL( void ) - TT_Goto_CodeRange( TT_ExecContext exec, - FT_Int range, - FT_Long IP ); - - FT_LOCAL( void ) - TT_Set_CodeRange( TT_ExecContext exec, - FT_Int range, - void* base, - FT_Long length ); - - FT_LOCAL( void ) - TT_Clear_CodeRange( TT_ExecContext exec, - FT_Int range ); - - - FT_LOCAL( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ); -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_New_Context */ - /* */ - /* <Description> */ - /* Queries the face context for a given font. Note that there is */ - /* now a _single_ execution context in the TrueType driver which is */ - /* shared among faces. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* <Return> */ - /* A handle to the execution context. Initialized for `face'. */ - /* */ - /* <Note> */ - /* Only the glyph loader and debugger should call this function. */ - /* (And right now only the glyph loader uses it.) */ - /* */ - FT_EXPORT( TT_ExecContext ) - TT_New_Context( TT_Driver driver ); - - -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_LOCAL( void ) - TT_Done_Context( TT_ExecContext exec ); - - FT_LOCAL( FT_Error ) - TT_Load_Context( TT_ExecContext exec, - TT_Face face, - TT_Size size ); - - FT_LOCAL( void ) - TT_Save_Context( TT_ExecContext exec, - TT_Size ins ); - - FT_LOCAL( FT_Error ) - TT_Run_Context( TT_ExecContext exec ); -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_RunIns */ - /* */ - /* <Description> */ - /* Executes one or more instruction in the execution context. This */ - /* is the main function of the TrueType opcode interpreter. */ - /* */ - /* <Input> */ - /* exec :: A handle to the target execution context. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* Only the object manager and debugger should call this function. */ - /* */ - /* This function is publicly exported because it is directly */ - /* invoked by the TrueType debugger. */ - /* */ - FT_EXPORT( FT_Error ) - TT_RunIns( TT_ExecContext exec ); - - -FT_END_HEADER - -#endif /* __TTINTERP_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttobjs.c b/third_party/freetype/src/truetype/ttobjs.c deleted file mode 100644 index 6060d6f5d1e49f97ed2e256220257119c2e0611d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttobjs.c +++ /dev/null @@ -1,1359 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttobjs.c */ -/* */ -/* Objects manager (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H -#include FT_INTERNAL_SFNT_H -#include FT_TRUETYPE_DRIVER_H - -#include "ttgload.h" -#include "ttpload.h" - -#include "tterrors.h" - -#ifdef TT_USE_BYTECODE_INTERPRETER -#include "ttinterp.h" -#endif - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING -#include FT_TRUETYPE_UNPATENTED_H -#endif - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.h" -#endif - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttobjs - - -#ifdef TT_USE_BYTECODE_INTERPRETER - - /*************************************************************************/ - /* */ - /* GLYPH ZONE FUNCTIONS */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_glyphzone_done */ - /* */ - /* <Description> */ - /* Deallocate a glyph zone. */ - /* */ - /* <Input> */ - /* zone :: A pointer to the target glyph zone. */ - /* */ - FT_LOCAL_DEF( void ) - tt_glyphzone_done( TT_GlyphZone zone ) - { - FT_Memory memory = zone->memory; - - - if ( memory ) - { - FT_FREE( zone->contours ); - FT_FREE( zone->tags ); - FT_FREE( zone->cur ); - FT_FREE( zone->org ); - FT_FREE( zone->orus ); - - zone->max_points = zone->n_points = 0; - zone->max_contours = zone->n_contours = 0; - zone->memory = NULL; - } - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_glyphzone_new */ - /* */ - /* <Description> */ - /* Allocate a new glyph zone. */ - /* */ - /* <Input> */ - /* memory :: A handle to the current memory object. */ - /* */ - /* maxPoints :: The capacity of glyph zone in points. */ - /* */ - /* maxContours :: The capacity of glyph zone in contours. */ - /* */ - /* <Output> */ - /* zone :: A pointer to the target glyph zone record. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_glyphzone_new( FT_Memory memory, - FT_UShort maxPoints, - FT_Short maxContours, - TT_GlyphZone zone ) - { - FT_Error error; - - - FT_MEM_ZERO( zone, sizeof ( *zone ) ); - zone->memory = memory; - - if ( FT_NEW_ARRAY( zone->org, maxPoints ) || - FT_NEW_ARRAY( zone->cur, maxPoints ) || - FT_NEW_ARRAY( zone->orus, maxPoints ) || - FT_NEW_ARRAY( zone->tags, maxPoints ) || - FT_NEW_ARRAY( zone->contours, maxContours ) ) - { - tt_glyphzone_done( zone ); - } - else - { - zone->max_points = maxPoints; - zone->max_contours = maxContours; - } - - return error; - } -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - - /* Compare the face with a list of well-known `tricky' fonts. */ - /* This list shall be expanded as we find more of them. */ - - static FT_Bool - tt_check_trickyness_family( FT_String* name ) - { - -#define TRICK_NAMES_MAX_CHARACTERS 19 -#define TRICK_NAMES_COUNT 9 - - static const char trick_names[TRICK_NAMES_COUNT] - [TRICK_NAMES_MAX_CHARACTERS + 1] = - { - "DFKaiSho-SB", /* dfkaisb.ttf */ - "DFKaiShu", - "DFKai-SB", /* kaiu.ttf */ - "HuaTianKaiTi?", /* htkt2.ttf */ - "HuaTianSongTi?", /* htst3.ttf */ - "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */ - "MingLiU", /* mingliu.ttf & mingliu.ttc */ - "PMingLiU", /* mingliu.ttc */ - "MingLi43", /* mingli.ttf */ - }; - - int nn; - - - for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) - if ( ft_strstr( name, trick_names[nn] ) ) - return TRUE; - - return FALSE; - } - - - /* XXX: This function should be in the `sfnt' module. */ - - /* Some PDF generators clear the checksums in the TrueType header table. */ - /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */ - /* Printer clears the entries for subsetted subtables. We thus have to */ - /* recalculate the checksums where necessary. */ - - static FT_UInt32 - tt_synth_sfnt_checksum( FT_Stream stream, - FT_ULong length ) - { - FT_Error error; - FT_UInt32 checksum = 0; - FT_UInt i; - - - if ( FT_FRAME_ENTER( length ) ) - return 0; - - for ( ; length > 3; length -= 4 ) - checksum += (FT_UInt32)FT_GET_ULONG(); - - for ( i = 3; length > 0; length--, i-- ) - checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 ); - - FT_FRAME_EXIT(); - - return checksum; - } - - - /* XXX: This function should be in the `sfnt' module. */ - - static FT_ULong - tt_get_sfnt_checksum( TT_Face face, - FT_UShort i ) - { -#if 0 /* if we believe the written value, use following part. */ - if ( face->dir_tables[i].CheckSum ) - return face->dir_tables[i].CheckSum; -#endif - - if ( !face->goto_table ) - return 0; - - if ( face->goto_table( face, - face->dir_tables[i].Tag, - face->root.stream, - NULL ) ) - return 0; - - return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream, - face->dir_tables[i].Length ); - } - - - typedef struct tt_sfnt_id_rec_ - { - FT_ULong CheckSum; - FT_ULong Length; - - } tt_sfnt_id_rec; - - - static FT_Bool - tt_check_trickyness_sfnt_ids( TT_Face face ) - { -#define TRICK_SFNT_IDS_PER_FACE 3 -#define TRICK_SFNT_IDS_NUM_FACES 17 - - static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] - [TRICK_SFNT_IDS_PER_FACE] = { - -#define TRICK_SFNT_ID_cvt 0 -#define TRICK_SFNT_ID_fpgm 1 -#define TRICK_SFNT_ID_prep 2 - - { /* MingLiU 1995 */ - { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ - { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ - { 0xA344A1EAUL, 0x000001E1UL } /* prep */ - }, - { /* MingLiU 1996- */ - { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ - { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ - { 0xA344A1EBUL, 0x000001E1UL } /* prep */ - }, - { /* DFKaiShu */ - { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ - { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */ - { 0x13A42602UL, 0x0000007EUL } /* prep */ - }, - { /* HuaTianKaiTi */ - { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ - { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */ - { 0x70020112UL, 0x00000008UL } /* prep */ - }, - { /* HuaTianSongTi */ - { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ - { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */ - { 0x70020112UL, 0x00000008UL } /* prep */ - }, - { /* NEC fadpop7.ttf */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ - { 0xA39B58E3UL, 0x0000117CUL } /* prep */ - }, - { /* NEC fadrei5.ttf */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x33C41652UL, 0x000000E5UL }, /* fpgm */ - { 0x26D6C52AUL, 0x00000F6AUL } /* prep */ - }, - { /* NEC fangot7.ttf */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */ - { 0x6C6E4B03UL, 0x00002492UL } /* prep */ - }, - { /* NEC fangyo5.ttf */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ - { 0xDE51FAD0UL, 0x0000117CUL } /* prep */ - }, - { /* NEC fankyo5.ttf */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x85E47664UL, 0x000000E5UL }, /* fpgm */ - { 0xA6C62831UL, 0x00001CAAUL } /* prep */ - }, - { /* NEC fanrgo5.ttf */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */ - { 0xA0604633UL, 0x00001DE8UL } /* prep */ - }, - { /* NEC fangot5.ttc */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */ - { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */ - }, - { /* NEC fanmin3.ttc */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */ - { 0xD4127766UL, 0x00002280UL } /* prep */ - }, - { /* NEC FA-Gothic, 1996 */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x4A692698UL, 0x000001F0UL }, /* fpgm */ - { 0x340D4346UL, 0x00001FCAUL } /* prep */ - }, - { /* NEC FA-Minchou, 1996 */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0xCD34C604UL, 0x00000166UL }, /* fpgm */ - { 0x6CF31046UL, 0x000022B0UL } /* prep */ - }, - { /* NEC FA-RoundGothicB, 1996 */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */ - { 0x40745A5FUL, 0x000022E0UL } /* prep */ - }, - { /* NEC FA-RoundGothicM, 1996 */ - { 0x00000000UL, 0x00000000UL }, /* cvt */ - { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */ - { 0x3900DED3UL, 0x00001E18UL } /* prep */ - } - }; - - FT_ULong checksum; - int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES]; - FT_Bool has_cvt, has_fpgm, has_prep; - FT_UShort i; - int j, k; - - - FT_MEM_SET( num_matched_ids, 0, - sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES ); - has_cvt = FALSE; - has_fpgm = FALSE; - has_prep = FALSE; - - for ( i = 0; i < face->num_tables; i++ ) - { - checksum = 0; - - switch( face->dir_tables[i].Tag ) - { - case TTAG_cvt: - k = TRICK_SFNT_ID_cvt; - has_cvt = TRUE; - break; - - case TTAG_fpgm: - k = TRICK_SFNT_ID_fpgm; - has_fpgm = TRUE; - break; - - case TTAG_prep: - k = TRICK_SFNT_ID_prep; - has_prep = TRUE; - break; - - default: - continue; - } - - for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) - if ( face->dir_tables[i].Length == sfnt_id[j][k].Length ) - { - if ( !checksum ) - checksum = tt_get_sfnt_checksum( face, i ); - - if ( sfnt_id[j][k].CheckSum == checksum ) - num_matched_ids[j]++; - - if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) - return TRUE; - } - } - - for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) - { - if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length ) - num_matched_ids[j] ++; - if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length ) - num_matched_ids[j] ++; - if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length ) - num_matched_ids[j] ++; - if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) - return TRUE; - } - - return FALSE; - } - - - static FT_Bool - tt_check_trickyness( FT_Face face ) - { - if ( !face ) - return FALSE; - - /* For first, check the face name for quick check. */ - if ( face->family_name && - tt_check_trickyness_family( face->family_name ) ) - return TRUE; - - /* Type42 fonts may lack `name' tables, we thus try to identify */ - /* tricky fonts by checking the checksums of Type42-persistent */ - /* sfnt tables (`cvt', `fpgm', and `prep'). */ - if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) ) - return TRUE; - - return FALSE; - } - - - /* Check whether `.notdef' is the only glyph in the `loca' table. */ - static FT_Bool - tt_check_single_notdef( FT_Face ttface ) - { - FT_Bool result = FALSE; - - TT_Face face = (TT_Face)ttface; - FT_UInt asize; - FT_ULong i; - FT_ULong glyph_index = 0; - FT_UInt count = 0; - - - for( i = 0; i < face->num_locations; i++ ) - { - tt_face_get_location( face, i, &asize ); - if ( asize > 0 ) - { - count += 1; - if ( count > 1 ) - break; - glyph_index = i; - } - } - - /* Only have a single outline. */ - if ( count == 1 ) - { - if ( glyph_index == 0 ) - result = TRUE; - else - { - /* FIXME: Need to test glyphname == .notdef ? */ - FT_Error error; - char buf[8]; - - - error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 ); - if ( !error && - buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) ) - result = TRUE; - } - } - - return result; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_init */ - /* */ - /* <Description> */ - /* Initialize a given TrueType face object. */ - /* */ - /* <Input> */ - /* stream :: The source font stream. */ - /* */ - /* face_index :: The index of the TrueType font, if we are opening a */ - /* collection, in bits 0-15. The numbered instance */ - /* index~+~1 of a GX (sub)font, if applicable, in bits */ - /* 16-30. */ - /* */ - /* num_params :: Number of additional generic parameters. Ignored. */ - /* */ - /* params :: Additional generic parameters. Ignored. */ - /* */ - /* <InOut> */ - /* face :: The newly built face object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_init( FT_Stream stream, - FT_Face ttface, /* TT_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ) - { - FT_Error error; - FT_Library library; - SFNT_Service sfnt; - TT_Face face = (TT_Face)ttface; - - - FT_TRACE2(( "TTF driver\n" )); - - library = ttface->driver->root.library; - - sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); - if ( !sfnt ) - { - FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" )); - error = FT_THROW( Missing_Module ); - goto Exit; - } - - /* create input stream from resource */ - if ( FT_STREAM_SEEK( 0 ) ) - goto Exit; - - /* check that we have a valid TrueType file */ - error = sfnt->init_face( stream, face, face_index, num_params, params ); - - /* Stream may have changed. */ - stream = face->root.stream; - - if ( error ) - goto Exit; - - /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ - /* The 0x00020000 tag is completely undocumented; some fonts from */ - /* Arphic made for Chinese Windows 3.1 have this. */ - if ( face->format_tag != 0x00010000L && /* MS fonts */ - face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ - face->format_tag != TTAG_true ) /* Mac fonts */ - { - FT_TRACE2(( " not a TTF font\n" )); - goto Bad_Format; - } - -#ifdef TT_USE_BYTECODE_INTERPRETER - ttface->face_flags |= FT_FACE_FLAG_HINTER; -#endif - - /* If we are performing a simple font format check, exit immediately. */ - if ( face_index < 0 ) - return FT_Err_Ok; - - /* Load font directory */ - error = sfnt->load_face( stream, face, face_index, num_params, params ); - if ( error ) - goto Exit; - - if ( tt_check_trickyness( ttface ) ) - ttface->face_flags |= FT_FACE_FLAG_TRICKY; - - error = tt_face_load_hdmx( face, stream ); - if ( error ) - goto Exit; - - if ( FT_IS_SCALABLE( ttface ) ) - { - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - if ( !ttface->internal->incremental_interface ) - error = tt_face_load_loca( face, stream ); - if ( !error ) - error = tt_face_load_cvt( face, stream ); - if ( !error ) - error = tt_face_load_fpgm( face, stream ); - if ( !error ) - error = tt_face_load_prep( face, stream ); - - /* Check the scalable flag based on `loca'. */ - if ( !ttface->internal->incremental_interface && - ttface->num_fixed_sizes && - face->glyph_locations && - tt_check_single_notdef( ttface ) ) - { - FT_TRACE5(( "tt_face_init:" - " Only the `.notdef' glyph has an outline.\n" - " " - " Resetting scalable flag to FALSE.\n" )); - - ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; - } - -#else /* !FT_CONFIG_OPTION_INCREMENTAL */ - - if ( !error ) - error = tt_face_load_loca( face, stream ); - if ( !error ) - error = tt_face_load_cvt( face, stream ); - if ( !error ) - error = tt_face_load_fpgm( face, stream ); - if ( !error ) - error = tt_face_load_prep( face, stream ); - - /* Check the scalable flag based on `loca'. */ - if ( ttface->num_fixed_sizes && - face->glyph_locations && - tt_check_single_notdef( ttface ) ) - { - FT_TRACE5(( "tt_face_init:" - " Only the `.notdef' glyph has an outline.\n" - " " - " Resetting scalable flag to FALSE.\n" )); - - ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; - } - -#endif /* !FT_CONFIG_OPTION_INCREMENTAL */ - - } - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - { - FT_Int instance_index = face_index >> 16; - - - if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && - instance_index > 0 ) - { - error = TT_Get_MM_Var( face, NULL ); - if ( error ) - goto Exit; - - if ( face->blend->mmvar->namedstyle ) - { - FT_Memory memory = ttface->memory; - - FT_Var_Named_Style* named_style; - FT_String* style_name; - - - /* in `face_index', the instance index starts with value 1 */ - named_style = face->blend->mmvar->namedstyle + instance_index - 1; - error = sfnt->get_name( face, - (FT_UShort)named_style->strid, - &style_name ); - if ( error ) - goto Exit; - - /* set style name; if already set, replace it */ - if ( face->root.style_name ) - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; - - /* finally, select the named instance */ - error = TT_Set_Var_Design( face, - face->blend->mmvar->num_axis, - named_style->coords ); - if ( error ) - goto Exit; - } - } - } - -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - -#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ - !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) - - { - FT_Bool unpatented_hinting; - int i; - - - /* Determine whether unpatented hinting is to be used for this face. */ - unpatented_hinting = FT_BOOL - ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL ); - - for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) - if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) - unpatented_hinting = TRUE; - - if ( !unpatented_hinting ) - ttface->internal->ignore_unpatented_hinter = TRUE; - } - -#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING && - !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ - - /* initialize standard glyph loading routines */ - TT_Init_Glyph_Loading( face ); - - Exit: - return error; - - Bad_Format: - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_done */ - /* */ - /* <Description> */ - /* Finalize a given face object. */ - /* */ - /* <Input> */ - /* face :: A pointer to the face object to destroy. */ - /* */ - FT_LOCAL_DEF( void ) - tt_face_done( FT_Face ttface ) /* TT_Face */ - { - TT_Face face = (TT_Face)ttface; - FT_Memory memory; - FT_Stream stream; - SFNT_Service sfnt; - - - if ( !face ) - return; - - memory = ttface->memory; - stream = ttface->stream; - sfnt = (SFNT_Service)face->sfnt; - - /* for `extended TrueType formats' (i.e. compressed versions) */ - if ( face->extra.finalizer ) - face->extra.finalizer( face->extra.data ); - - if ( sfnt ) - sfnt->done_face( face ); - - /* freeing the locations table */ - tt_face_done_loca( face ); - - tt_face_free_hdmx( face ); - - /* freeing the CVT */ - FT_FREE( face->cvt ); - face->cvt_size = 0; - - /* freeing the programs */ - FT_FRAME_RELEASE( face->font_program ); - FT_FRAME_RELEASE( face->cvt_program ); - face->font_program_size = 0; - face->cvt_program_size = 0; - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - tt_done_blend( memory, face->blend ); - face->blend = NULL; -#endif - } - - - /*************************************************************************/ - /* */ - /* SIZE FUNCTIONS */ - /* */ - /*************************************************************************/ - -#ifdef TT_USE_BYTECODE_INTERPRETER - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_size_run_fpgm */ - /* */ - /* <Description> */ - /* Run the font program. */ - /* */ - /* <Input> */ - /* size :: A handle to the size object. */ - /* */ - /* pedantic :: Set if bytecode execution should be pedantic. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_size_run_fpgm( TT_Size size, - FT_Bool pedantic ) - { - TT_Face face = (TT_Face)size->root.face; - TT_ExecContext exec; - FT_Error error; - - - exec = size->context; - - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; - - exec->callTop = 0; - exec->top = 0; - - exec->period = 64; - exec->phase = 0; - exec->threshold = 0; - - exec->instruction_trap = FALSE; - exec->F_dot_P = 0x4000L; - - exec->pedantic_hinting = pedantic; - - { - FT_Size_Metrics* metrics = &exec->metrics; - TT_Size_Metrics* tt_metrics = &exec->tt_metrics; - - - metrics->x_ppem = 0; - metrics->y_ppem = 0; - metrics->x_scale = 0; - metrics->y_scale = 0; - - tt_metrics->ppem = 0; - tt_metrics->scale = 0; - tt_metrics->ratio = 0x10000L; - } - - /* allow font program execution */ - TT_Set_CodeRange( exec, - tt_coderange_font, - face->font_program, - (FT_Long)face->font_program_size ); - - /* disable CVT and glyph programs coderange */ - TT_Clear_CodeRange( exec, tt_coderange_cvt ); - TT_Clear_CodeRange( exec, tt_coderange_glyph ); - - if ( face->font_program_size > 0 ) - { - TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); - - FT_TRACE4(( "Executing `fpgm' table.\n" )); - error = face->interpreter( exec ); - } - else - error = FT_Err_Ok; - - size->bytecode_ready = error; - - if ( !error ) - TT_Save_Context( exec, size ); - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_size_run_prep */ - /* */ - /* <Description> */ - /* Run the control value program. */ - /* */ - /* <Input> */ - /* size :: A handle to the size object. */ - /* */ - /* pedantic :: Set if bytecode execution should be pedantic. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_size_run_prep( TT_Size size, - FT_Bool pedantic ) - { - TT_Face face = (TT_Face)size->root.face; - TT_ExecContext exec; - FT_Error error; - - - exec = size->context; - - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; - - exec->callTop = 0; - exec->top = 0; - - exec->instruction_trap = FALSE; - - exec->pedantic_hinting = pedantic; - - TT_Set_CodeRange( exec, - tt_coderange_cvt, - face->cvt_program, - (FT_Long)face->cvt_program_size ); - - TT_Clear_CodeRange( exec, tt_coderange_glyph ); - - if ( face->cvt_program_size > 0 ) - { - TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); - - FT_TRACE4(( "Executing `prep' table.\n" )); - - error = face->interpreter( exec ); - } - else - error = FT_Err_Ok; - - size->cvt_ready = error; - - /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ - /* graphics state variables to be modified by the CVT program. */ - - exec->GS.dualVector.x = 0x4000; - exec->GS.dualVector.y = 0; - exec->GS.projVector.x = 0x4000; - exec->GS.projVector.y = 0x0; - exec->GS.freeVector.x = 0x4000; - exec->GS.freeVector.y = 0x0; - - exec->GS.rp0 = 0; - exec->GS.rp1 = 0; - exec->GS.rp2 = 0; - - exec->GS.gep0 = 1; - exec->GS.gep1 = 1; - exec->GS.gep2 = 1; - - exec->GS.loop = 1; - - /* save as default graphics state */ - size->GS = exec->GS; - - TT_Save_Context( exec, size ); - - return error; - } - - - static void - tt_size_done_bytecode( FT_Size ftsize ) - { - TT_Size size = (TT_Size)ftsize; - TT_Face face = (TT_Face)ftsize->face; - FT_Memory memory = face->root.memory; - - if ( size->context ) - { - TT_Done_Context( size->context ); - size->context = NULL; - } - - FT_FREE( size->cvt ); - size->cvt_size = 0; - - /* free storage area */ - FT_FREE( size->storage ); - size->storage_size = 0; - - /* twilight zone */ - tt_glyphzone_done( &size->twilight ); - - FT_FREE( size->function_defs ); - FT_FREE( size->instruction_defs ); - - size->num_function_defs = 0; - size->max_function_defs = 0; - size->num_instruction_defs = 0; - size->max_instruction_defs = 0; - - size->max_func = 0; - size->max_ins = 0; - - size->bytecode_ready = -1; - size->cvt_ready = -1; - } - - - /* Initialize bytecode-related fields in the size object. */ - /* We do this only if bytecode interpretation is really needed. */ - static FT_Error - tt_size_init_bytecode( FT_Size ftsize, - FT_Bool pedantic ) - { - FT_Error error; - TT_Size size = (TT_Size)ftsize; - TT_Face face = (TT_Face)ftsize->face; - FT_Memory memory = face->root.memory; - - FT_UShort n_twilight; - TT_MaxProfile* maxp = &face->max_profile; - - - /* clean up bytecode related data */ - FT_FREE( size->function_defs ); - FT_FREE( size->instruction_defs ); - FT_FREE( size->cvt ); - FT_FREE( size->storage ); - - if ( size->context ) - TT_Done_Context( size->context ); - tt_glyphzone_done( &size->twilight ); - - size->bytecode_ready = -1; - size->cvt_ready = -1; - - size->context = TT_New_Context( (TT_Driver)face->root.driver ); - - size->max_function_defs = maxp->maxFunctionDefs; - size->max_instruction_defs = maxp->maxInstructionDefs; - - size->num_function_defs = 0; - size->num_instruction_defs = 0; - - size->max_func = 0; - size->max_ins = 0; - - size->cvt_size = face->cvt_size; - size->storage_size = maxp->maxStorage; - - /* Set default metrics */ - { - TT_Size_Metrics* metrics = &size->ttmetrics; - - - metrics->rotated = FALSE; - metrics->stretched = FALSE; - - /* set default engine compensation */ - metrics->compensations[0] = 0; /* gray */ - metrics->compensations[1] = 0; /* black */ - metrics->compensations[2] = 0; /* white */ - metrics->compensations[3] = 0; /* reserved */ - } - - /* allocate function defs, instruction defs, cvt, and storage area */ - if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || - FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || - FT_NEW_ARRAY( size->cvt, size->cvt_size ) || - FT_NEW_ARRAY( size->storage, size->storage_size ) ) - goto Exit; - - /* reserve twilight zone */ - n_twilight = maxp->maxTwilightPoints; - - /* there are 4 phantom points (do we need this?) */ - n_twilight += 4; - - error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); - if ( error ) - goto Exit; - - size->twilight.n_points = n_twilight; - - size->GS = tt_default_graphics_state; - - /* set `face->interpreter' according to the debug hook present */ - { - FT_Library library = face->root.driver->root.library; - - - face->interpreter = (TT_Interpreter) - library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; - if ( !face->interpreter ) - face->interpreter = (TT_Interpreter)TT_RunIns; - } - - /* Fine, now run the font program! */ - error = tt_size_run_fpgm( size, pedantic ); - - Exit: - if ( error ) - tt_size_done_bytecode( ftsize ); - - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - tt_size_ready_bytecode( TT_Size size, - FT_Bool pedantic ) - { - FT_Error error = FT_Err_Ok; - - - if ( size->bytecode_ready < 0 ) - error = tt_size_init_bytecode( (FT_Size)size, pedantic ); - - if ( error || size->bytecode_ready ) - goto Exit; - - /* rescale CVT when needed */ - if ( size->cvt_ready < 0 ) - { - FT_UInt i; - TT_Face face = (TT_Face)size->root.face; - - - /* Scale the cvt values to the new ppem. */ - /* We use by default the y ppem to scale the CVT. */ - for ( i = 0; i < size->cvt_size; i++ ) - size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); - - /* all twilight points are originally zero */ - for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) - { - size->twilight.org[i].x = 0; - size->twilight.org[i].y = 0; - size->twilight.cur[i].x = 0; - size->twilight.cur[i].y = 0; - } - - /* clear storage area */ - for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) - size->storage[i] = 0; - - size->GS = tt_default_graphics_state; - - error = tt_size_run_prep( size, pedantic ); - } - - Exit: - return error; - } - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_size_init */ - /* */ - /* <Description> */ - /* Initialize a new TrueType size object. */ - /* */ - /* <InOut> */ - /* size :: A handle to the size object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_size_init( FT_Size ttsize ) /* TT_Size */ - { - TT_Size size = (TT_Size)ttsize; - FT_Error error = FT_Err_Ok; - - -#ifdef TT_USE_BYTECODE_INTERPRETER - size->bytecode_ready = -1; - size->cvt_ready = -1; -#endif - - size->ttmetrics.valid = FALSE; - size->strike_index = 0xFFFFFFFFUL; - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_size_done */ - /* */ - /* <Description> */ - /* The TrueType size object finalizer. */ - /* */ - /* <Input> */ - /* size :: A handle to the target size object. */ - /* */ - FT_LOCAL_DEF( void ) - tt_size_done( FT_Size ttsize ) /* TT_Size */ - { - TT_Size size = (TT_Size)ttsize; - - -#ifdef TT_USE_BYTECODE_INTERPRETER - tt_size_done_bytecode( ttsize ); -#endif - - size->ttmetrics.valid = FALSE; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_size_reset */ - /* */ - /* <Description> */ - /* Reset a TrueType size when resolutions and character dimensions */ - /* have been changed. */ - /* */ - /* <Input> */ - /* size :: A handle to the target size object. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_size_reset( TT_Size size ) - { - TT_Face face; - FT_Error error = FT_Err_Ok; - FT_Size_Metrics* metrics; - - - size->ttmetrics.valid = FALSE; - - face = (TT_Face)size->root.face; - - metrics = &size->metrics; - - /* copy the result from base layer */ - *metrics = size->root.metrics; - - if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) - return FT_THROW( Invalid_PPem ); - - /* This bit flag, if set, indicates that the ppems must be */ - /* rounded to integers. Nearly all TrueType fonts have this bit */ - /* set, as hinting won't work really well otherwise. */ - /* */ - if ( face->header.Flags & 8 ) - { - metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, - face->root.units_per_EM ); - metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, - face->root.units_per_EM ); - - metrics->ascender = - FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); - metrics->descender = - FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); - metrics->height = - FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); - metrics->max_advance = - FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, - metrics->x_scale ) ); - } - - /* compute new transformation */ - if ( metrics->x_ppem >= metrics->y_ppem ) - { - size->ttmetrics.scale = metrics->x_scale; - size->ttmetrics.ppem = metrics->x_ppem; - size->ttmetrics.x_ratio = 0x10000L; - size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, - metrics->x_ppem ); - } - else - { - size->ttmetrics.scale = metrics->y_scale; - size->ttmetrics.ppem = metrics->y_ppem; - size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, - metrics->y_ppem ); - size->ttmetrics.y_ratio = 0x10000L; - } - -#ifdef TT_USE_BYTECODE_INTERPRETER - size->cvt_ready = -1; -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - if ( !error ) - size->ttmetrics.valid = TRUE; - - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_driver_init */ - /* */ - /* <Description> */ - /* Initialize a given TrueType driver object. */ - /* */ - /* <Input> */ - /* driver :: A handle to the target driver object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ - { - -#ifdef TT_USE_BYTECODE_INTERPRETER - - TT_Driver driver = (TT_Driver)ttdriver; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - driver->interpreter_version = TT_INTERPRETER_VERSION_38; -#else - driver->interpreter_version = TT_INTERPRETER_VERSION_35; -#endif - -#else /* !TT_USE_BYTECODE_INTERPRETER */ - - FT_UNUSED( ttdriver ); - -#endif /* !TT_USE_BYTECODE_INTERPRETER */ - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_driver_done */ - /* */ - /* <Description> */ - /* Finalize a given TrueType driver. */ - /* */ - /* <Input> */ - /* driver :: A handle to the target TrueType driver. */ - /* */ - FT_LOCAL_DEF( void ) - tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ - { - FT_UNUSED( ttdriver ); - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_slot_init */ - /* */ - /* <Description> */ - /* Initialize a new slot object. */ - /* */ - /* <InOut> */ - /* slot :: A handle to the slot object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_slot_init( FT_GlyphSlot slot ) - { - return FT_GlyphLoader_CreateExtra( slot->internal->loader ); - } - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttobjs.h b/third_party/freetype/src/truetype/ttobjs.h deleted file mode 100644 index 9396089a991168a61dfc3663e18d7648cb64e9e7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttobjs.h +++ /dev/null @@ -1,425 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttobjs.h */ -/* */ -/* Objects manager (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTOBJS_H__ -#define __TTOBJS_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* TT_Driver */ - /* */ - /* <Description> */ - /* A handle to a TrueType driver object. */ - /* */ - typedef struct TT_DriverRec_* TT_Driver; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* TT_GlyphSlot */ - /* */ - /* <Description> */ - /* A handle to a TrueType glyph slot object. */ - /* */ - /* <Note> */ - /* This is a direct typedef of FT_GlyphSlot, as there is nothing */ - /* specific about the TrueType glyph slot. */ - /* */ - typedef FT_GlyphSlot TT_GlyphSlot; - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* TT_GraphicsState */ - /* */ - /* <Description> */ - /* The TrueType graphics state used during bytecode interpretation. */ - /* */ - typedef struct TT_GraphicsState_ - { - FT_UShort rp0; - FT_UShort rp1; - FT_UShort rp2; - - FT_UnitVector dualVector; - FT_UnitVector projVector; - FT_UnitVector freeVector; - -#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING - FT_Bool both_x_axis; -#endif - - FT_Long loop; - FT_F26Dot6 minimum_distance; - FT_Int round_state; - - FT_Bool auto_flip; - FT_F26Dot6 control_value_cutin; - FT_F26Dot6 single_width_cutin; - FT_F26Dot6 single_width_value; - FT_UShort delta_base; - FT_UShort delta_shift; - - FT_Byte instruct_control; - /* According to Greg Hitchcock from Microsoft, the `scan_control' */ - /* variable as documented in the TrueType specification is a 32-bit */ - /* integer; the high-word part holds the SCANTYPE value, the low-word */ - /* part the SCANCTRL value. We separate it into two fields. */ - FT_Bool scan_control; - FT_Int scan_type; - - FT_UShort gep0; - FT_UShort gep1; - FT_UShort gep2; - - } TT_GraphicsState; - - -#ifdef TT_USE_BYTECODE_INTERPRETER - - FT_LOCAL( void ) - tt_glyphzone_done( TT_GlyphZone zone ); - - FT_LOCAL( FT_Error ) - tt_glyphzone_new( FT_Memory memory, - FT_UShort maxPoints, - FT_Short maxContours, - TT_GlyphZone zone ); - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - - - /*************************************************************************/ - /* */ - /* EXECUTION SUBTABLES */ - /* */ - /* These sub-tables relate to instruction execution. */ - /* */ - /*************************************************************************/ - - -#define TT_MAX_CODE_RANGES 3 - - - /*************************************************************************/ - /* */ - /* There can only be 3 active code ranges at once: */ - /* - the Font Program */ - /* - the CVT Program */ - /* - a glyph's instructions set */ - /* */ - typedef enum TT_CodeRange_Tag_ - { - tt_coderange_none = 0, - tt_coderange_font, - tt_coderange_cvt, - tt_coderange_glyph - - } TT_CodeRange_Tag; - - - typedef struct TT_CodeRange_ - { - FT_Byte* base; - FT_Long size; - - } TT_CodeRange; - - typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES]; - - - /*************************************************************************/ - /* */ - /* Defines a function/instruction definition record. */ - /* */ - typedef struct TT_DefRecord_ - { - FT_Int range; /* in which code range is it located? */ - FT_Long start; /* where does it start? */ - FT_Long end; /* where does it end? */ - FT_UInt opc; /* function #, or instruction code */ - FT_Bool active; /* is it active? */ - FT_Bool inline_delta; /* is function that defines inline delta? */ - FT_ULong sph_fdef_flags; /* flags to identify special functions */ - - } TT_DefRecord, *TT_DefArray; - - - /*************************************************************************/ - /* */ - /* Subglyph transformation record. */ - /* */ - typedef struct TT_Transform_ - { - FT_Fixed xx, xy; /* transformation matrix coefficients */ - FT_Fixed yx, yy; - FT_F26Dot6 ox, oy; /* offsets */ - - } TT_Transform; - - - /*************************************************************************/ - /* */ - /* A note regarding non-squared pixels: */ - /* */ - /* (This text will probably go into some docs at some time; for now, it */ - /* is kept here to explain some definitions in the TT_Size_Metrics */ - /* record). */ - /* */ - /* The CVT is a one-dimensional array containing values that control */ - /* certain important characteristics in a font, like the height of all */ - /* capitals, all lowercase letter, default spacing or stem width/height. */ - /* */ - /* These values are found in FUnits in the font file, and must be scaled */ - /* to pixel coordinates before being used by the CVT and glyph programs. */ - /* Unfortunately, when using distinct x and y resolutions (or distinct x */ - /* and y pointsizes), there are two possible scalings. */ - /* */ - /* A first try was to implement a `lazy' scheme where all values were */ - /* scaled when first used. However, while some values are always used */ - /* in the same direction, some others are used under many different */ - /* circumstances and orientations. */ - /* */ - /* I have found a simpler way to do the same, and it even seems to work */ - /* in most of the cases: */ - /* */ - /* - All CVT values are scaled to the maximum ppem size. */ - /* */ - /* - When performing a read or write in the CVT, a ratio factor is used */ - /* to perform adequate scaling. Example: */ - /* */ - /* x_ppem = 14 */ - /* y_ppem = 10 */ - /* */ - /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */ - /* entries are scaled to it. */ - /* */ - /* x_ratio = 1.0 */ - /* y_ratio = y_ppem/ppem (< 1.0) */ - /* */ - /* We compute the current ratio like: */ - /* */ - /* - If projVector is horizontal, */ - /* ratio = x_ratio = 1.0 */ - /* */ - /* - if projVector is vertical, */ - /* ratio = y_ratio */ - /* */ - /* - else, */ - /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */ - /* */ - /* Reading a cvt value returns */ - /* ratio * cvt[index] */ - /* */ - /* Writing a cvt value in pixels: */ - /* cvt[index] / ratio */ - /* */ - /* The current ppem is simply */ - /* ratio * ppem */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* Metrics used by the TrueType size and context objects. */ - /* */ - typedef struct TT_Size_Metrics_ - { - /* for non-square pixels */ - FT_Long x_ratio; - FT_Long y_ratio; - - FT_UShort ppem; /* maximum ppem size */ - FT_Long ratio; /* current ratio */ - FT_Fixed scale; - - FT_F26Dot6 compensations[4]; /* device-specific compensations */ - - FT_Bool valid; - - FT_Bool rotated; /* `is the glyph rotated?'-flag */ - FT_Bool stretched; /* `is the glyph stretched?'-flag */ - - } TT_Size_Metrics; - - - /*************************************************************************/ - /* */ - /* TrueType size class. */ - /* */ - typedef struct TT_SizeRec_ - { - FT_SizeRec root; - - /* we have our own copy of metrics so that we can modify */ - /* it without affecting auto-hinting (when used) */ - FT_Size_Metrics metrics; - - TT_Size_Metrics ttmetrics; - - FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ - -#ifdef TT_USE_BYTECODE_INTERPRETER - - FT_UInt num_function_defs; /* number of function definitions */ - FT_UInt max_function_defs; - TT_DefArray function_defs; /* table of function definitions */ - - FT_UInt num_instruction_defs; /* number of ins. definitions */ - FT_UInt max_instruction_defs; - TT_DefArray instruction_defs; /* table of ins. definitions */ - - FT_UInt max_func; - FT_UInt max_ins; - - TT_CodeRangeTable codeRangeTable; - - TT_GraphicsState GS; - - FT_ULong cvt_size; /* the scaled control value table */ - FT_Long* cvt; - - FT_UShort storage_size; /* The storage area is now part of */ - FT_Long* storage; /* the instance */ - - TT_GlyphZoneRec twilight; /* The instance's twilight zone */ - - TT_ExecContext context; - - /* if negative, `fpgm' (resp. `prep'), wasn't executed yet; */ - /* otherwise it is the returned error code */ - FT_Error bytecode_ready; - FT_Error cvt_ready; - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - } TT_SizeRec; - - - /*************************************************************************/ - /* */ - /* TrueType driver class. */ - /* */ - typedef struct TT_DriverRec_ - { - FT_DriverRec root; - - TT_GlyphZoneRec zone; /* glyph loader points zone */ - - FT_UInt interpreter_version; - - } TT_DriverRec; - - - /* Note: All of the functions below (except tt_size_reset()) are used */ - /* as function pointers in a FT_Driver_ClassRec. Therefore their */ - /* parameters are of types FT_Face, FT_Size, etc., rather than TT_Face, */ - /* TT_Size, etc., so that the compiler can confirm that the types and */ - /* number of parameters are correct. In all cases the FT_xxx types are */ - /* cast to their TT_xxx counterparts inside the functions since FreeType */ - /* will always use the TT driver to create them. */ - - - /*************************************************************************/ - /* */ - /* Face functions */ - /* */ - FT_LOCAL( FT_Error ) - tt_face_init( FT_Stream stream, - FT_Face ttface, /* TT_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ); - - FT_LOCAL( void ) - tt_face_done( FT_Face ttface ); /* TT_Face */ - - - /*************************************************************************/ - /* */ - /* Size functions */ - /* */ - FT_LOCAL( FT_Error ) - tt_size_init( FT_Size ttsize ); /* TT_Size */ - - FT_LOCAL( void ) - tt_size_done( FT_Size ttsize ); /* TT_Size */ - -#ifdef TT_USE_BYTECODE_INTERPRETER - - FT_LOCAL( FT_Error ) - tt_size_run_fpgm( TT_Size size, - FT_Bool pedantic ); - - FT_LOCAL( FT_Error ) - tt_size_run_prep( TT_Size size, - FT_Bool pedantic ); - - FT_LOCAL( FT_Error ) - tt_size_ready_bytecode( TT_Size size, - FT_Bool pedantic ); - -#endif /* TT_USE_BYTECODE_INTERPRETER */ - - FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size ); - - - /*************************************************************************/ - /* */ - /* Driver functions */ - /* */ - FT_LOCAL( FT_Error ) - tt_driver_init( FT_Module ttdriver ); /* TT_Driver */ - - FT_LOCAL( void ) - tt_driver_done( FT_Module ttdriver ); /* TT_Driver */ - - - /*************************************************************************/ - /* */ - /* Slot functions */ - /* */ - FT_LOCAL( FT_Error ) - tt_slot_init( FT_GlyphSlot slot ); - - - /* auxiliary */ -#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) - - -FT_END_HEADER - -#endif /* __TTOBJS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttpic.c b/third_party/freetype/src/truetype/ttpic.c deleted file mode 100644 index 242a6b76ddb2607274e1109c644d5d907716bf83..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttpic.c +++ /dev/null @@ -1,101 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttpic.c */ -/* */ -/* The FreeType position independent code services for truetype module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_INTERNAL_OBJECTS_H -#include "ttpic.h" -#include "tterrors.h" - - -#ifdef FT_CONFIG_OPTION_PIC - - /* forward declaration of PIC init functions from ttdriver.c */ - FT_Error - FT_Create_Class_tt_services( FT_Library library, - FT_ServiceDescRec** output_class ); - void - FT_Destroy_Class_tt_services( FT_Library library, - FT_ServiceDescRec* clazz ); - void - FT_Init_Class_tt_service_gx_multi_masters( - FT_Service_MultiMastersRec* sv_mm ); - void - FT_Init_Class_tt_service_truetype_glyf( - FT_Service_TTGlyfRec* sv_ttglyf ); - - - void - tt_driver_class_pic_free( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Memory memory = library->memory; - - - if ( pic_container->truetype ) - { - TTModulePIC* container = (TTModulePIC*)pic_container->truetype; - - - if ( container->tt_services ) - FT_Destroy_Class_tt_services( library, container->tt_services ); - container->tt_services = NULL; - FT_FREE( container ); - pic_container->truetype = NULL; - } - } - - - FT_Error - tt_driver_class_pic_init( FT_Library library ) - { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - TTModulePIC* container = NULL; - FT_Memory memory = library->memory; - - - /* allocate pointer, clear and set global container pointer */ - if ( FT_ALLOC( container, sizeof ( *container ) ) ) - return error; - FT_MEM_SET( container, 0, sizeof ( *container ) ); - pic_container->truetype = container; - - /* initialize pointer table - this is how the module usually */ - /* expects this data */ - error = FT_Create_Class_tt_services( library, - &container->tt_services ); - if ( error ) - goto Exit; -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_Init_Class_tt_service_gx_multi_masters( - &container->tt_service_gx_multi_masters ); -#endif - FT_Init_Class_tt_service_truetype_glyf( - &container->tt_service_truetype_glyf ); - - Exit: - if ( error ) - tt_driver_class_pic_free( library ); - return error; - } - -#endif /* FT_CONFIG_OPTION_PIC */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttpic.h b/third_party/freetype/src/truetype/ttpic.h deleted file mode 100644 index 076ae56efa8d3fa7fc41899223264867a7f21b31..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttpic.h +++ /dev/null @@ -1,83 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttpic.h */ -/* */ -/* The FreeType position independent code services for truetype module. */ -/* */ -/* Copyright 2009-2015 by */ -/* Oran Agra and Mickey Gabel. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTPIC_H__ -#define __TTPIC_H__ - - -#include FT_INTERNAL_PIC_H - - -#ifndef FT_CONFIG_OPTION_PIC - -#define TT_SERVICES_GET tt_services -#define TT_SERVICE_GX_MULTI_MASTERS_GET tt_service_gx_multi_masters -#define TT_SERVICE_TRUETYPE_GLYF_GET tt_service_truetype_glyf -#define TT_SERVICE_PROPERTIES_GET tt_service_properties - -#else /* FT_CONFIG_OPTION_PIC */ - -#include FT_MULTIPLE_MASTERS_H -#include FT_SERVICE_MULTIPLE_MASTERS_H -#include FT_SERVICE_TRUETYPE_GLYF_H -#include FT_SERVICE_PROPERTIES_H - - -FT_BEGIN_HEADER - - typedef struct TTModulePIC_ - { - FT_ServiceDescRec* tt_services; -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_Service_MultiMastersRec tt_service_gx_multi_masters; -#endif - FT_Service_TTGlyfRec tt_service_truetype_glyf; - FT_Service_PropertiesRec tt_service_properties; - - } TTModulePIC; - - -#define GET_PIC( lib ) \ - ( (TTModulePIC*)((lib)->pic_container.truetype) ) -#define TT_SERVICES_GET \ - ( GET_PIC( library )->tt_services ) -#define TT_SERVICE_GX_MULTI_MASTERS_GET \ - ( GET_PIC( library )->tt_service_gx_multi_masters ) -#define TT_SERVICE_TRUETYPE_GLYF_GET \ - ( GET_PIC( library )->tt_service_truetype_glyf ) -#define TT_SERVICE_PROPERTIES_GET \ - ( GET_PIC( library )->tt_service_properties ) - - - /* see ttpic.c for the implementation */ - void - tt_driver_class_pic_free( FT_Library library ); - - FT_Error - tt_driver_class_pic_init( FT_Library library ); - -FT_END_HEADER - -#endif /* FT_CONFIG_OPTION_PIC */ - - /* */ - -#endif /* __TTPIC_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttpload.c b/third_party/freetype/src/truetype/ttpload.c deleted file mode 100644 index 4647c938aeadf3ca3d4ba55fd9236ebd9e3d0926..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttpload.c +++ /dev/null @@ -1,609 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttpload.c */ -/* */ -/* TrueType-specific tables loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_OBJECTS_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_TAGS_H - -#include "ttpload.h" - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.h" -#endif - -#include "tterrors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_ttpload - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_loca */ - /* */ - /* <Description> */ - /* Load the locations table. */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Input> */ - /* stream :: The input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_loca( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_ULong table_len; - FT_Int shift; - - - /* we need the size of the `glyf' table for malformed `loca' tables */ - error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len ); - - /* it is possible that a font doesn't have a glyf table at all */ - /* or its size is zero */ - if ( FT_ERR_EQ( error, Table_Missing ) ) - face->glyf_len = 0; - else if ( error ) - goto Exit; - - FT_TRACE2(( "Locations " )); - error = face->goto_table( face, TTAG_loca, stream, &table_len ); - if ( error ) - { - error = FT_THROW( Locations_Missing ); - goto Exit; - } - - if ( face->header.Index_To_Loc_Format != 0 ) - { - shift = 2; - - if ( table_len >= 0x40000L ) - { - FT_TRACE2(( "table too large\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - face->num_locations = table_len >> shift; - } - else - { - shift = 1; - - if ( table_len >= 0x20000L ) - { - FT_TRACE2(( "table too large\n" )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - face->num_locations = table_len >> shift; - } - - if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 ) - { - FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n", - face->num_locations - 1, face->root.num_glyphs )); - - /* we only handle the case where `maxp' gives a larger value */ - if ( face->num_locations <= (FT_ULong)face->root.num_glyphs ) - { - FT_ULong new_loca_len = - ( (FT_ULong)face->root.num_glyphs + 1 ) << shift; - - TT_Table entry = face->dir_tables; - TT_Table limit = entry + face->num_tables; - - FT_Long pos = (FT_Long)FT_STREAM_POS(); - FT_Long dist = 0x7FFFFFFFL; - - - /* compute the distance to next table in font file */ - for ( ; entry < limit; entry++ ) - { - FT_Long diff = (FT_Long)entry->Offset - pos; - - - if ( diff > 0 && diff < dist ) - dist = diff; - } - - if ( entry == limit ) - { - /* `loca' is the last table */ - dist = (FT_Long)stream->size - pos; - } - - if ( new_loca_len <= (FT_ULong)dist ) - { - face->num_locations = (FT_ULong)face->root.num_glyphs + 1; - table_len = new_loca_len; - - FT_TRACE2(( "adjusting num_locations to %d\n", - face->num_locations )); - } - else - { - face->root.num_glyphs = face->num_locations - ? (FT_Long)face->num_locations - 1 : 0; - - FT_TRACE2(( "adjusting num_glyphs to %d\n", - face->root.num_glyphs )); - } - } - } - - /* - * Extract the frame. We don't need to decompress it since - * we are able to parse it directly. - */ - if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) ) - goto Exit; - - FT_TRACE2(( "loaded\n" )); - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ) - { - FT_ULong pos1, pos2; - FT_Byte* p; - FT_Byte* p_limit; - - - pos1 = pos2 = 0; - - if ( gindex < face->num_locations ) - { - if ( face->header.Index_To_Loc_Format != 0 ) - { - p = face->glyph_locations + gindex * 4; - p_limit = face->glyph_locations + face->num_locations * 4; - - pos1 = FT_NEXT_ULONG( p ); - pos2 = pos1; - - if ( p + 4 <= p_limit ) - pos2 = FT_NEXT_ULONG( p ); - } - else - { - p = face->glyph_locations + gindex * 2; - p_limit = face->glyph_locations + face->num_locations * 2; - - pos1 = FT_NEXT_USHORT( p ); - pos2 = pos1; - - if ( p + 2 <= p_limit ) - pos2 = FT_NEXT_USHORT( p ); - - pos1 <<= 1; - pos2 <<= 1; - } - } - - /* Check broken location data */ - if ( pos1 > face->glyf_len ) - { - FT_TRACE1(( "tt_face_get_location:" - " too large offset=0x%08lx found for gid=0x%04lx," - " exceeding the end of glyf table (0x%08lx)\n", - pos1, gindex, face->glyf_len )); - *asize = 0; - return 0; - } - - if ( pos2 > face->glyf_len ) - { - FT_TRACE1(( "tt_face_get_location:" - " too large offset=0x%08lx found for gid=0x%04lx," - " truncate at the end of glyf table (0x%08lx)\n", - pos2, gindex + 1, face->glyf_len )); - pos2 = face->glyf_len; - } - - /* The `loca' table must be ordered; it refers to the length of */ - /* an entry as the difference between the current and the next */ - /* position. However, there do exist (malformed) fonts which */ - /* don't obey this rule, so we are only able to provide an */ - /* upper bound for the size. */ - /* */ - /* We get (intentionally) a wrong, non-zero result in case the */ - /* `glyf' table is missing. */ - if ( pos2 >= pos1 ) - *asize = (FT_UInt)( pos2 - pos1 ); - else - *asize = (FT_UInt)( face->glyf_len - pos1 ); - - return pos1; - } - - - FT_LOCAL_DEF( void ) - tt_face_done_loca( TT_Face face ) - { - FT_Stream stream = face->root.stream; - - - FT_FRAME_RELEASE( face->glyph_locations ); - face->num_locations = 0; - } - - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_cvt */ - /* */ - /* <Description> */ - /* Load the control value table into a face object. */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Input> */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_cvt( TT_Face face, - FT_Stream stream ) - { -#ifdef TT_USE_BYTECODE_INTERPRETER - - FT_Error error; - FT_Memory memory = stream->memory; - FT_ULong table_len; - - - FT_TRACE2(( "CVT " )); - - error = face->goto_table( face, TTAG_cvt, stream, &table_len ); - if ( error ) - { - FT_TRACE2(( "is missing\n" )); - - face->cvt_size = 0; - face->cvt = NULL; - error = FT_Err_Ok; - - goto Exit; - } - - face->cvt_size = table_len / 2; - - if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) ) - goto Exit; - - if ( FT_FRAME_ENTER( face->cvt_size * 2L ) ) - goto Exit; - - { - FT_Short* cur = face->cvt; - FT_Short* limit = cur + face->cvt_size; - - - for ( ; cur < limit; cur++ ) - *cur = FT_GET_SHORT(); - } - - FT_FRAME_EXIT(); - FT_TRACE2(( "loaded\n" )); - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->doblend ) - error = tt_face_vary_cvt( face, stream ); -#endif - - Exit: - return error; - -#else /* !TT_USE_BYTECODE_INTERPRETER */ - - FT_UNUSED( face ); - FT_UNUSED( stream ); - - return FT_Err_Ok; - -#endif - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_fpgm */ - /* */ - /* <Description> */ - /* Load the font program. */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Input> */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_fpgm( TT_Face face, - FT_Stream stream ) - { -#ifdef TT_USE_BYTECODE_INTERPRETER - - FT_Error error; - FT_ULong table_len; - - - FT_TRACE2(( "Font program " )); - - /* The font program is optional */ - error = face->goto_table( face, TTAG_fpgm, stream, &table_len ); - if ( error ) - { - face->font_program = NULL; - face->font_program_size = 0; - error = FT_Err_Ok; - - FT_TRACE2(( "is missing\n" )); - } - else - { - face->font_program_size = table_len; - if ( FT_FRAME_EXTRACT( table_len, face->font_program ) ) - goto Exit; - - FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size )); - } - - Exit: - return error; - -#else /* !TT_USE_BYTECODE_INTERPRETER */ - - FT_UNUSED( face ); - FT_UNUSED( stream ); - - return FT_Err_Ok; - -#endif - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_prep */ - /* */ - /* <Description> */ - /* Load the cvt program. */ - /* */ - /* <InOut> */ - /* face :: A handle to the target face object. */ - /* */ - /* <Input> */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - tt_face_load_prep( TT_Face face, - FT_Stream stream ) - { -#ifdef TT_USE_BYTECODE_INTERPRETER - - FT_Error error; - FT_ULong table_len; - - - FT_TRACE2(( "Prep program " )); - - error = face->goto_table( face, TTAG_prep, stream, &table_len ); - if ( error ) - { - face->cvt_program = NULL; - face->cvt_program_size = 0; - error = FT_Err_Ok; - - FT_TRACE2(( "is missing\n" )); - } - else - { - face->cvt_program_size = table_len; - if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) ) - goto Exit; - - FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size )); - } - - Exit: - return error; - -#else /* !TT_USE_BYTECODE_INTERPRETER */ - - FT_UNUSED( face ); - FT_UNUSED( stream ); - - return FT_Err_Ok; - -#endif - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* tt_face_load_hdmx */ - /* */ - /* <Description> */ - /* Load the `hdmx' table into the face object. */ - /* */ - /* <Input> */ - /* face :: A handle to the target face object. */ - /* */ - /* stream :: A handle to the input stream. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - - FT_LOCAL_DEF( FT_Error ) - tt_face_load_hdmx( TT_Face face, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - FT_UInt version, nn, num_records; - FT_ULong table_size, record_size; - FT_Byte* p; - FT_Byte* limit; - - - /* this table is optional */ - error = face->goto_table( face, TTAG_hdmx, stream, &table_size ); - if ( error || table_size < 8 ) - return FT_Err_Ok; - - if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) ) - goto Exit; - - p = face->hdmx_table; - limit = p + table_size; - - version = FT_NEXT_USHORT( p ); - num_records = FT_NEXT_USHORT( p ); - record_size = FT_NEXT_ULONG( p ); - - /* The maximum number of bytes in an hdmx device record is the */ - /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */ - /* explaining why `record_size' is a long (which we read as */ - /* unsigned long for convenience). In practice, two bytes are */ - /* sufficient to hold the size value. */ - /* */ - /* There are at least two fonts, HANNOM-A and HANNOM-B version */ - /* 2.0 (2005), which get this wrong: The upper two bytes of */ - /* the size value are set to 0xFF instead of 0x00. We catch */ - /* and fix this. */ - - if ( record_size >= 0xFFFF0000UL ) - record_size &= 0xFFFFU; - - /* The limit for `num_records' is a heuristic value. */ - if ( version != 0 || - num_records > 255 || - record_size > 0x10001L || - record_size < 4 ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) ) - goto Fail; - - for ( nn = 0; nn < num_records; nn++ ) - { - if ( p + record_size > limit ) - break; - - face->hdmx_record_sizes[nn] = p[0]; - p += record_size; - } - - face->hdmx_record_count = nn; - face->hdmx_table_size = table_size; - face->hdmx_record_size = record_size; - - Exit: - return error; - - Fail: - FT_FRAME_RELEASE( face->hdmx_table ); - face->hdmx_table_size = 0; - goto Exit; - } - - - FT_LOCAL_DEF( void ) - tt_face_free_hdmx( TT_Face face ) - { - FT_Stream stream = face->root.stream; - FT_Memory memory = stream->memory; - - - FT_FREE( face->hdmx_record_sizes ); - FT_FRAME_RELEASE( face->hdmx_table ); - } - - - /*************************************************************************/ - /* */ - /* Return the advance width table for a given pixel size if it is found */ - /* in the font's `hdmx' table (if any). */ - /* */ - FT_LOCAL_DEF( FT_Byte* ) - tt_face_get_device_metrics( TT_Face face, - FT_UInt ppem, - FT_UInt gindex ) - { - FT_UInt nn; - FT_Byte* result = NULL; - FT_ULong record_size = face->hdmx_record_size; - FT_Byte* record = face->hdmx_table + 8; - - - for ( nn = 0; nn < face->hdmx_record_count; nn++ ) - if ( face->hdmx_record_sizes[nn] == ppem ) - { - gindex += 2; - if ( gindex < record_size ) - result = record + nn * record_size + gindex; - break; - } - - return result; - } - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttpload.h b/third_party/freetype/src/truetype/ttpload.h deleted file mode 100644 index bc923698273c2217afde433dc395294fe07d4639..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttpload.h +++ /dev/null @@ -1,75 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttpload.h */ -/* */ -/* TrueType-specific tables loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTPLOAD_H__ -#define __TTPLOAD_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_TRUETYPE_TYPES_H - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - tt_face_load_loca( TT_Face face, - FT_Stream stream ); - - FT_LOCAL( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ); - - FT_LOCAL( void ) - tt_face_done_loca( TT_Face face ); - - FT_LOCAL( FT_Error ) - tt_face_load_cvt( TT_Face face, - FT_Stream stream ); - - FT_LOCAL( FT_Error ) - tt_face_load_fpgm( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_prep( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( FT_Error ) - tt_face_load_hdmx( TT_Face face, - FT_Stream stream ); - - - FT_LOCAL( void ) - tt_face_free_hdmx( TT_Face face ); - - - FT_LOCAL( FT_Byte* ) - tt_face_get_device_metrics( TT_Face face, - FT_UInt ppem, - FT_UInt gindex ); - -FT_END_HEADER - -#endif /* __TTPLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttsubpix.c b/third_party/freetype/src/truetype/ttsubpix.c deleted file mode 100644 index 0d391e95a0725f2e1f327f1d07f393b503a2f6d6..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttsubpix.c +++ /dev/null @@ -1,1011 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttsubpix.c */ -/* */ -/* TrueType Subpixel Hinting. */ -/* */ -/* Copyright 2010-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H -#include FT_TRUETYPE_TAGS_H -#include FT_OUTLINE_H -#include FT_TRUETYPE_DRIVER_H - -#include "ttsubpix.h" - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - /*************************************************************************/ - /* */ - /* These rules affect how the TT Interpreter does hinting, with the */ - /* goal of doing subpixel hinting by (in general) ignoring x moves. */ - /* Some of these rules are fixes that go above and beyond the */ - /* stated techniques in the MS whitepaper on Cleartype, due to */ - /* artifacts in many glyphs. So, these rules make some glyphs render */ - /* better than they do in the MS rasterizer. */ - /* */ - /* "" string or 0 int/char indicates to apply to all glyphs. */ - /* "-" used as dummy placeholders, but any non-matching string works. */ - /* */ - /* Some of this could arguably be implemented in fontconfig, however: */ - /* */ - /* - Fontconfig can't set things on a glyph-by-glyph basis. */ - /* - The tweaks that happen here are very low-level, from an average */ - /* user's point of view and are best implemented in the hinter. */ - /* */ - /* The goal is to make the subpixel hinting techniques as generalized */ - /* as possible across all fonts to prevent the need for extra rules such */ - /* as these. */ - /* */ - /* The rule structure is designed so that entirely new rules can easily */ - /* be added when a new compatibility feature is discovered. */ - /* */ - /* The rule structures could also use some enhancement to handle ranges. */ - /* */ - /* ****************** WORK IN PROGRESS ******************* */ - /* */ - - /* These are `classes' of fonts that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define FAMILY_CLASS_RULES_SIZE 7 - - static const SPH_Font_Class FAMILY_CLASS_Rules - [FAMILY_CLASS_RULES_SIZE] = - { - { "MS Legacy Fonts", - { "Aharoni", - "Andale Mono", - "Andalus", - "Angsana New", - "AngsanaUPC", - "Arabic Transparent", - "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Batang", - "Browallia New", - "BrowalliaUPC", - "Comic Sans MS", - "Cordia New", - "CordiaUPC", - "Courier New", - "DFKai-SB", - "David Transparent", - "David", - "DilleniaUPC", - "Estrangelo Edessa", - "EucrosiaUPC", - "FangSong_GB2312", - "Fixed Miriam Transparent", - "FrankRuehl", - "Franklin Gothic Medium", - "FreesiaUPC", - "Garamond", - "Gautami", - "Georgia", - "Gulim", - "Impact", - "IrisUPC", - "JasmineUPC", - "KaiTi_GB2312", - "KodchiangUPC", - "Latha", - "Levenim MT", - "LilyUPC", - "Lucida Console", - "Lucida Sans Unicode", - "MS Gothic", - "MS Mincho", - "MV Boli", - "Mangal", - "Marlett", - "Microsoft Sans Serif", - "Mingliu", - "Miriam Fixed", - "Miriam Transparent", - "Miriam", - "Narkisim", - "Palatino Linotype", - "Raavi", - "Rod Transparent", - "Rod", - "Shruti", - "SimHei", - "Simplified Arabic Fixed", - "Simplified Arabic", - "Simsun", - "Sylfaen", - "Symbol", - "Tahoma", - "Times New Roman", - "Traditional Arabic", - "Trebuchet MS", - "Tunga", - "Verdana", - "Webdings", - "Wingdings", - "", - }, - }, - { "Core MS Legacy Fonts", - { "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Comic Sans MS", - "Courier New", - "Garamond", - "Georgia", - "Impact", - "Lucida Console", - "Lucida Sans Unicode", - "Microsoft Sans Serif", - "Palatino Linotype", - "Tahoma", - "Times New Roman", - "Trebuchet MS", - "Verdana", - "", - }, - }, - { "Apple Legacy Fonts", - { "Geneva", - "Times", - "Monaco", - "Century", - "Chalkboard", - "Lobster", - "Century Gothic", - "Optima", - "Lucida Grande", - "Gill Sans", - "Baskerville", - "Helvetica", - "Helvetica Neue", - "", - }, - }, - { "Legacy Sans Fonts", - { "Andale Mono", - "Arial Unicode MS", - "Arial", - "Century Gothic", - "Comic Sans MS", - "Franklin Gothic Medium", - "Geneva", - "Lucida Console", - "Lucida Grande", - "Lucida Sans Unicode", - "Lucida Sans Typewriter", - "Microsoft Sans Serif", - "Monaco", - "Tahoma", - "Trebuchet MS", - "Verdana", - "", - }, - }, - - { "Misc Legacy Fonts", - { "Dark Courier", "", }, }, - { "Verdana Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", "", }, }, - { "Verdana and Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", - "Verdana", "", }, }, - }; - - - /* Define this to force natural (i.e. not bitmap-compatible) widths. */ - /* The default leans strongly towards natural widths except for a few */ - /* legacy fonts where a selective combination produces nicer results. */ -/* #define FORCE_NATURAL_WIDTHS */ - - - /* Define `classes' of styles that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define STYLE_CLASS_RULES_SIZE 5 - - static const SPH_Font_Class STYLE_CLASS_Rules - [STYLE_CLASS_RULES_SIZE] = - { - { "Regular Class", - { "Regular", - "Book", - "Medium", - "Roman", - "Normal", - "", - }, - }, - { "Regular/Italic Class", - { "Regular", - "Book", - "Medium", - "Italic", - "Oblique", - "Roman", - "Normal", - "", - }, - }, - { "Bold/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "", - }, - }, - { "Bold/Italic/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "Italic", - "Oblique", - "", - }, - }, - { "Regular/Bold Class", - { "Regular", - "Book", - "Medium", - "Normal", - "Roman", - "Bold", - "Black", - "", - }, - }, - }; - - - /* Force special legacy fixes for fonts. */ -#define COMPATIBILITY_MODE_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBILITY_MODE_Rules - [COMPATIBILITY_MODE_RULES_SIZE] = - { - { "Verdana Clones", 0, "", 0 }, - }; - - - /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */ -#define PIXEL_HINTING_RULES_SIZE 2 - - static const SPH_TweakRule PIXEL_HINTING_Rules - [PIXEL_HINTING_RULES_SIZE] = - { - /* these characters are almost always safe */ - { "Courier New", 12, "Italic", 'z' }, - { "Courier New", 11, "Italic", 'z' }, - }; - - - /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ -#define DO_SHPIX_RULES_SIZE 1 - - static const SPH_TweakRule DO_SHPIX_Rules - [DO_SHPIX_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 4 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules - [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* fix vwxyz thinness*/ - { "Consolas", 0, "", 0 }, - /* Fix thin middle stems */ - { "Core MS Legacy Fonts", 0, "Regular", 0 }, - /* Cyrillic small letter I */ - { "Legacy Sans Fonts", 0, "", 0 }, - /* Fix artifacts with some Regular & Bold */ - { "Verdana Clones", 0, "", 0 }, - }; - - -#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - /* Fixes < and > */ - { "Courier New", 0, "Regular", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules - [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] = - { - /* Maintain thickness of diagonal in 'N' */ - { "Times New Roman", 0, "Regular/Bold Class", 'N' }, - { "Georgia", 0, "Regular/Bold Class", 'N' }, - }; - - - /* Skip Y moves that move a point off a Y pixel boundary. */ -#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules - [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Round moves that don't move a point to a Y pixel boundary. */ -#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules - [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* Droid font instructions don't snap Y to pixels */ - { "Droid Sans", 0, "Regular/Italic Class", 0 }, - { "Droid Sans Mono", 0, "", 0 }, - }; - - -#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions - [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Allow a Direct_Move along X freedom vector if matched. */ -#define ALLOW_X_DMOVE_RULES_SIZE 1 - - static const SPH_TweakRule ALLOW_X_DMOVE_Rules - [ALLOW_X_DMOVE_RULES_SIZE] = - { - /* Fixes vanishing diagonal in 4 */ - { "Verdana", 0, "Regular", '4' }, - }; - - - /* Return MS rasterizer version 35 if matched. */ -#define RASTERIZER_35_RULES_SIZE 8 - - static const SPH_TweakRule RASTERIZER_35_Rules - [RASTERIZER_35_RULES_SIZE] = - { - /* This seems to be the only way to make these look good */ - { "Times New Roman", 0, "Regular", 'i' }, - { "Times New Roman", 0, "Regular", 'j' }, - { "Times New Roman", 0, "Regular", 'm' }, - { "Times New Roman", 0, "Regular", 'r' }, - { "Times New Roman", 0, "Regular", 'a' }, - { "Times New Roman", 0, "Regular", 'n' }, - { "Times New Roman", 0, "Regular", 'p' }, - { "Times", 0, "", 0 }, - }; - - - /* Don't round to the subpixel grid. Round to pixel grid. */ -#define NORMAL_ROUND_RULES_SIZE 1 - - static const SPH_TweakRule NORMAL_ROUND_Rules - [NORMAL_ROUND_RULES_SIZE] = - { - /* Fix serif thickness for certain ppems */ - /* Can probably be generalized somehow */ - { "Courier New", 0, "", 0 }, - }; - - - /* Skip IUP instructions if matched. */ -#define SKIP_IUP_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_IUP_Rules - [SKIP_IUP_RULES_SIZE] = - { - { "Arial", 13, "Regular", 'a' }, - }; - - - /* Skip MIAP Twilight hack if matched. */ -#define MIAP_HACK_RULES_SIZE 1 - - static const SPH_TweakRule MIAP_HACK_Rules - [MIAP_HACK_RULES_SIZE] = - { - { "Geneva", 12, "", 0 }, - }; - - - /* Skip DELTAP instructions if matched. */ -#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23 - - static const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules - [ALWAYS_SKIP_DELTAP_RULES_SIZE] = - { - { "Georgia", 0, "Regular", 'k' }, - /* fix various problems with e in different versions */ - { "Trebuchet MS", 14, "Regular", 'e' }, - { "Trebuchet MS", 13, "Regular", 'e' }, - { "Trebuchet MS", 15, "Regular", 'e' }, - { "Trebuchet MS", 0, "Italic", 'v' }, - { "Trebuchet MS", 0, "Italic", 'w' }, - { "Trebuchet MS", 0, "Regular", 'Y' }, - { "Arial", 11, "Regular", 's' }, - /* prevent problems with '3' and others */ - { "Verdana", 10, "Regular", 0 }, - { "Verdana", 9, "Regular", 0 }, - /* Cyrillic small letter short I */ - { "Legacy Sans Fonts", 0, "", 0x438 }, - { "Legacy Sans Fonts", 0, "", 0x439 }, - { "Arial", 10, "Regular", '6' }, - { "Arial", 0, "Bold/BoldItalic Class", 'a' }, - /* Make horizontal stems consistent with the rest */ - { "Arial", 24, "Bold", 'a' }, - { "Arial", 25, "Bold", 'a' }, - { "Arial", 24, "Bold", 's' }, - { "Arial", 25, "Bold", 's' }, - { "Arial", 34, "Bold", 's' }, - { "Arial", 35, "Bold", 's' }, - { "Arial", 36, "Bold", 's' }, - { "Arial", 25, "Regular", 's' }, - { "Arial", 26, "Regular", 's' }, - }; - - - /* Always do DELTAP instructions if matched. */ -#define ALWAYS_DO_DELTAP_RULES_SIZE 1 - - static const SPH_TweakRule ALWAYS_DO_DELTAP_Rules - [ALWAYS_DO_DELTAP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow ALIGNRP after IUP. */ -#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules - [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* Don't allow DELTAP after IUP. */ -#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules - [NO_DELTAP_AFTER_IUP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow CALL after IUP. */ -#define NO_CALL_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules - [NO_CALL_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* De-embolden these glyphs slightly. */ -#define DEEMBOLDEN_RULES_SIZE 9 - - static const SPH_TweakRule DEEMBOLDEN_Rules - [DEEMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Bold", 'A' }, - { "Courier New", 0, "Bold", 'W' }, - { "Courier New", 0, "Bold", 'w' }, - { "Courier New", 0, "Bold", 'M' }, - { "Courier New", 0, "Bold", 'X' }, - { "Courier New", 0, "Bold", 'K' }, - { "Courier New", 0, "Bold", 'x' }, - { "Courier New", 0, "Bold", 'z' }, - { "Courier New", 0, "Bold", 'v' }, - }; - - - /* Embolden these glyphs slightly. */ -#define EMBOLDEN_RULES_SIZE 2 - - static const SPH_TweakRule EMBOLDEN_Rules - [EMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Regular", 0 }, - { "Courier New", 0, "Italic", 0 }, - }; - - - /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */ - /* similar to Windows XP. */ -#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12 - - static const SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules - [TIMES_NEW_ROMAN_HACK_RULES_SIZE] = - { - { "Times New Roman", 16, "Italic", '2' }, - { "Times New Roman", 16, "Italic", '5' }, - { "Times New Roman", 16, "Italic", '7' }, - { "Times New Roman", 16, "Regular", '2' }, - { "Times New Roman", 16, "Regular", '5' }, - { "Times New Roman", 16, "Regular", '7' }, - { "Times New Roman", 17, "Italic", '2' }, - { "Times New Roman", 17, "Italic", '5' }, - { "Times New Roman", 17, "Italic", '7' }, - { "Times New Roman", 17, "Regular", '2' }, - { "Times New Roman", 17, "Regular", '5' }, - { "Times New Roman", 17, "Regular", '7' }, - }; - - - /* This fudges distance on 2 to get rid of the vanishing stem issue. */ - /* A real solution to this is certainly welcome. */ -#define COURIER_NEW_2_HACK_RULES_SIZE 15 - - static const SPH_TweakRule COURIER_NEW_2_HACK_Rules - [COURIER_NEW_2_HACK_RULES_SIZE] = - { - { "Courier New", 10, "Regular", '2' }, - { "Courier New", 11, "Regular", '2' }, - { "Courier New", 12, "Regular", '2' }, - { "Courier New", 13, "Regular", '2' }, - { "Courier New", 14, "Regular", '2' }, - { "Courier New", 15, "Regular", '2' }, - { "Courier New", 16, "Regular", '2' }, - { "Courier New", 17, "Regular", '2' }, - { "Courier New", 18, "Regular", '2' }, - { "Courier New", 19, "Regular", '2' }, - { "Courier New", 20, "Regular", '2' }, - { "Courier New", 21, "Regular", '2' }, - { "Courier New", 22, "Regular", '2' }, - { "Courier New", 23, "Regular", '2' }, - { "Courier New", 24, "Regular", '2' }, - }; - - -#ifndef FORCE_NATURAL_WIDTHS - - /* Use compatible widths with these glyphs. Compatible widths is always */ - /* on when doing B/W TrueType instructing, but is used selectively here, */ - /* typically on glyphs with 3 or more vertical stems. */ -#define COMPATIBLE_WIDTHS_RULES_SIZE 38 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "Arial Unicode MS", 12, "Regular Class", 'm' }, - { "Arial Unicode MS", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 10, "Regular Class", 0x448 }, - { "Arial", 11, "Regular Class", 'm' }, - { "Arial", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 12, "Regular Class", 0x448 }, - { "Arial", 13, "Regular Class", 0x448 }, - { "Arial", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 14, "Regular Class", 0x448 }, - { "Arial", 15, "Regular Class", 0x448 }, - { "Arial", 17, "Regular Class", 'm' }, - { "DejaVu Sans", 15, "Regular Class", 0 }, - { "Microsoft Sans Serif", 11, "Regular Class", 0 }, - { "Microsoft Sans Serif", 12, "Regular Class", 0 }, - { "Segoe UI", 11, "Regular Class", 0 }, - { "Monaco", 0, "Regular Class", 0 }, - { "Segoe UI", 12, "Regular Class", 'm' }, - { "Segoe UI", 14, "Regular Class", 'm' }, - { "Tahoma", 11, "Regular Class", 0 }, - { "Times New Roman", 16, "Regular Class", 'c' }, - { "Times New Roman", 16, "Regular Class", 'm' }, - { "Times New Roman", 16, "Regular Class", 'o' }, - { "Times New Roman", 16, "Regular Class", 'w' }, - { "Trebuchet MS", 11, "Regular Class", 0 }, - { "Trebuchet MS", 12, "Regular Class", 0 }, - { "Trebuchet MS", 14, "Regular Class", 0 }, - { "Trebuchet MS", 15, "Regular Class", 0 }, - { "Ubuntu", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Verdana", 10, "Regular Class", 0x448 }, - { "Verdana", 11, "Regular Class", 0x448 }, - { "Verdana and Clones", 12, "Regular Class", 'i' }, - { "Verdana and Clones", 12, "Regular Class", 'j' }, - { "Verdana and Clones", 12, "Regular Class", 'l' }, - { "Verdana and Clones", 12, "Regular Class", 'm' }, - { "Verdana and Clones", 13, "Regular Class", 'i' }, - { "Verdana and Clones", 13, "Regular Class", 'j' }, - { "Verdana and Clones", 13, "Regular Class", 'l' }, - { "Verdana and Clones", 14, "Regular Class", 'm' }, - }; - - - /* Scaling slightly in the x-direction prior to hinting results in */ - /* more visually pleasing glyphs in certain cases. */ - /* This sometimes needs to be coordinated with compatible width rules. */ - /* A value of 1000 corresponds to a scaled value of 1.0. */ - -#define X_SCALING_RULES_SIZE 50 - - static const SPH_ScaleRule X_SCALING_Rules[X_SCALING_RULES_SIZE] = - { - { "DejaVu Sans", 12, "Regular Class", 'm', 950 }, - { "Verdana and Clones", 12, "Regular Class", 'a', 1100 }, - { "Verdana and Clones", 13, "Regular Class", 'a', 1050 }, - { "Arial", 11, "Regular Class", 'm', 975 }, - { "Arial", 12, "Regular Class", 'm', 1050 }, - /* Cyrillic small letter el */ - { "Arial", 13, "Regular Class", 0x43B, 950 }, - { "Arial", 13, "Regular Class", 'o', 950 }, - { "Arial", 13, "Regular Class", 'e', 950 }, - { "Arial", 14, "Regular Class", 'm', 950 }, - /* Cyrillic small letter el */ - { "Arial", 15, "Regular Class", 0x43B, 925 }, - { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 }, - { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 }, - { "DejaVu Sans", 12, "Regular Class", 'l', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'i', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'j', 975 }, - { "DejaVu Sans", 13, "Regular Class", 'l', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'i', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'j', 950 }, - { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Georgia", 10, "", 0, 1050 }, - { "Georgia", 11, "", 0, 1100 }, - { "Georgia", 12, "", 0, 1025 }, - { "Georgia", 13, "", 0, 1050 }, - { "Georgia", 16, "", 0, 1050 }, - { "Georgia", 17, "", 0, 1030 }, - { "Liberation Sans", 12, "Regular Class", 'm', 1100 }, - { "Lucida Grande", 11, "Regular Class", 'm', 1100 }, - { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 }, - { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 12, "Regular Class", 'H', 1050 }, - { "Segoe UI", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 14, "Regular Class", 'm', 1050 }, - { "Tahoma", 11, "Regular Class", 'i', 975 }, - { "Tahoma", 11, "Regular Class", 'l', 975 }, - { "Tahoma", 11, "Regular Class", 'j', 900 }, - { "Tahoma", 11, "Regular Class", 'm', 918 }, - { "Verdana", 10, "Regular/Italic Class", 0, 1100 }, - { "Verdana", 12, "Regular Class", 'm', 975 }, - { "Verdana", 12, "Regular/Italic Class", 0, 1050 }, - { "Verdana", 13, "Regular/Italic Class", 'i', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'j', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'l', 950 }, - { "Verdana", 16, "Regular Class", 0, 1050 }, - { "Verdana", 9, "Regular/Italic Class", 0, 1050 }, - { "Times New Roman", 16, "Regular Class", 'm', 918 }, - { "Trebuchet MS", 11, "Regular Class", 'm', 800 }, - { "Trebuchet MS", 12, "Regular Class", 'm', 800 }, - }; - -#else - -#define COMPATIBLE_WIDTHS_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define X_SCALING_RULES_SIZE 1 - - static const SPH_ScaleRule X_SCALING_Rules - [X_SCALING_RULES_SIZE] = - { - { "-", 0, "", 0, 1000 }, - }; - -#endif /* FORCE_NATURAL_WIDTHS */ - - - static FT_Bool - is_member_of_family_class( const FT_String* detected_font_name, - const FT_String* rule_font_name ) - { - FT_UInt i, j; - - - /* Does font name match rule family? */ - if ( strcmp( detected_font_name, rule_font_name ) == 0 ) - return TRUE; - - /* Is font name a wildcard ""? */ - if ( strcmp( rule_font_name, "" ) == 0 ) - return TRUE; - - /* Is font name contained in a class list? */ - for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) - { - if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( strcmp( FAMILY_CLASS_Rules[i].member[j], - detected_font_name ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - static FT_Bool - is_member_of_style_class( const FT_String* detected_font_style, - const FT_String* rule_font_style ) - { - FT_UInt i, j; - - - /* Does font style match rule style? */ - if ( strcmp( detected_font_style, rule_font_style ) == 0 ) - return TRUE; - - /* Is font style a wildcard ""? */ - if ( strcmp( rule_font_style, "" ) == 0 ) - return TRUE; - - /* Is font style contained in a class list? */ - for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) - { - if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( strcmp( STYLE_CLASS_Rules[i].member[j], - detected_font_style ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - FT_LOCAL_DEF( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class ( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return TRUE; - } - - return FALSE; - } - - - static FT_UInt - scale_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_ScaleRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return rule[i].scale; - } - - return 1000; - } - - - FT_LOCAL_DEF( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ) - { - return scale_test_tweak( face, family, ppem, style, glyph_index, - X_SCALING_Rules, X_SCALING_RULES_SIZE ); - } - - -#define TWEAK_RULES( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules, x##_RULES_SIZE ) ) \ - loader->exec->sph_tweak_flags |= SPH_TWEAK_##x; - -#define TWEAK_RULES_EXCEPTIONS( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \ - loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x; - - - FT_LOCAL_DEF( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics.x_ppem; - FT_String* style = face->root.style_name; - - - /* don't apply rules if style isn't set */ - if ( !face->root.style_name ) - return; - -#ifdef SPH_DEBUG_MORE_VERBOSE - printf( "%s,%d,%s,%c=%d ", - family, ppem, style, glyph_index, glyph_index ); -#endif - - TWEAK_RULES( PIXEL_HINTING ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ) - { - loader->exec->ignore_x_mode = FALSE; - return; - } - - TWEAK_RULES( ALLOW_X_DMOVE ); - TWEAK_RULES( ALWAYS_DO_DELTAP ); - TWEAK_RULES( ALWAYS_SKIP_DELTAP ); - TWEAK_RULES( DEEMBOLDEN ); - TWEAK_RULES( DO_SHPIX ); - TWEAK_RULES( EMBOLDEN ); - TWEAK_RULES( MIAP_HACK ); - TWEAK_RULES( NORMAL_ROUND ); - TWEAK_RULES( NO_ALIGNRP_AFTER_IUP ); - TWEAK_RULES( NO_CALL_AFTER_IUP ); - TWEAK_RULES( NO_DELTAP_AFTER_IUP ); - TWEAK_RULES( RASTERIZER_35 ); - TWEAK_RULES( SKIP_IUP ); - - TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); - - TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - { - if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) - { - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - } - else - { - if ( loader->exec->rasterizer_version != - SPH_OPTION_SET_RASTERIZER_VERSION ) - { - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - } - - if ( IS_HINTED( loader->load_flags ) ) - { - TWEAK_RULES( TIMES_NEW_ROMAN_HACK ); - TWEAK_RULES( COURIER_NEW_2_HACK ); - } - - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) ) - loader->exec->face->sph_compatibility_mode = TRUE; - - - if ( IS_HINTED( loader->load_flags ) ) - { - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) ) - loader->exec->compatible_widths |= TRUE; - } - } - -#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - /* ANSI C doesn't like empty source files */ - typedef int _tt_subpix_dummy; - -#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - -/* END */ diff --git a/third_party/freetype/src/truetype/ttsubpix.h b/third_party/freetype/src/truetype/ttsubpix.h deleted file mode 100644 index 9151aa3250c8a392176370f09850aa3e0a45bff6..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/truetype/ttsubpix.h +++ /dev/null @@ -1,110 +0,0 @@ -/***************************************************************************/ -/* */ -/* ttsubpix.h */ -/* */ -/* TrueType Subpixel Hinting. */ -/* */ -/* Copyright 2010-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __TTSUBPIX_H__ -#define __TTSUBPIX_H__ - -#include <ft2build.h> -#include "ttobjs.h" -#include "ttinterp.h" - - -FT_BEGIN_HEADER - - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - - /*************************************************************************/ - /* */ - /* ID flags to identify special functions at FDEF and runtime. */ - /* */ - /* */ -#define SPH_FDEF_INLINE_DELTA_1 0x0000001 -#define SPH_FDEF_INLINE_DELTA_2 0x0000002 -#define SPH_FDEF_DIAGONAL_STROKE 0x0000004 -#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008 -#define SPH_FDEF_TTFAUTOHINT_1 0x0000010 -#define SPH_FDEF_SPACING_1 0x0000020 -#define SPH_FDEF_SPACING_2 0x0000040 -#define SPH_FDEF_TYPEMAN_STROKES 0x0000080 -#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100 - - - /*************************************************************************/ - /* */ - /* Tweak flags that are set for each glyph by the below rules. */ - /* */ - /* */ -#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL -#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL -#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL -#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL -#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL -#define SPH_TWEAK_DO_SHPIX 0x0000020UL -#define SPH_TWEAK_EMBOLDEN 0x0000040UL -#define SPH_TWEAK_MIAP_HACK 0x0000080UL -#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL -#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL -#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL -#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL -#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL -#define SPH_TWEAK_RASTERIZER_35 0x0002000UL -#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL -#define SPH_TWEAK_SKIP_IUP 0x0008000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL -#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL -#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL - - - FT_LOCAL( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ); - - FT_LOCAL( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ); - - FT_LOCAL( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ); - - - /* These macros are defined absent a method for setting them */ -#define SPH_OPTION_BITMAP_WIDTHS FALSE -#define SPH_OPTION_SET_SUBPIXEL TRUE -#define SPH_OPTION_SET_GRAYSCALE FALSE -#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE -#define SPH_OPTION_SET_RASTERIZER_VERSION 38 - -#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - - -FT_END_HEADER - -#endif /* __TTSUBPIX_H__ */ - -/* END */ diff --git a/third_party/freetype/src/type1/Jamfile b/third_party/freetype/src/type1/Jamfile deleted file mode 100644 index d1a3af57e90333f9a0a8321b5a20ff08fc32d64f..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/Jamfile +++ /dev/null @@ -1,35 +0,0 @@ -# FreeType 2 src/type1 Jamfile -# -# Copyright 2001-2015 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - -SubDir FT2_TOP $(FT2_SRC_DIR) type1 ; - -{ - local _sources ; - - if $(FT2_MULTI) - { - _sources = t1afm - t1driver - t1gload - t1load - t1objs - t1parse - ; - } - else - { - _sources = type1 ; - } - - Library $(FT2_LIB) : $(_sources).c ; -} - -# end of src/type1 Jamfile diff --git a/third_party/freetype/src/type1/t1afm.c b/third_party/freetype/src/type1/t1afm.c deleted file mode 100644 index 7f32059f850c26dc795a70088c31384abeee97db..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1afm.c +++ /dev/null @@ -1,396 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1afm.c */ -/* */ -/* AFM support for Type 1 fonts (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "t1afm.h" -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H -#include "t1errors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1afm - - - FT_LOCAL_DEF( void ) - T1_Done_Metrics( FT_Memory memory, - AFM_FontInfo fi ) - { - FT_FREE( fi->KernPairs ); - fi->NumKernPair = 0; - - FT_FREE( fi->TrackKerns ); - fi->NumTrackKern = 0; - - FT_FREE( fi ); - } - - - /* read a glyph name and return the equivalent glyph index */ - static FT_Int - t1_get_index( const char* name, - FT_Offset len, - void* user_data ) - { - T1_Font type1 = (T1_Font)user_data; - FT_Int n; - - - /* PS string/name length must be < 16-bit */ - if ( len > 0xFFFFU ) - return 0; - - for ( n = 0; n < type1->num_glyphs; n++ ) - { - char* gname = (char*)type1->glyph_names[n]; - - - if ( gname && gname[0] == name[0] && - ft_strlen( gname ) == len && - ft_strncmp( gname, name, len ) == 0 ) - return n; - } - - return 0; - } - - -#undef KERN_INDEX -#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) ) - - - /* compare two kerning pairs */ - FT_CALLBACK_DEF( int ) - compare_kern_pairs( const void* a, - const void* b ) - { - AFM_KernPair pair1 = (AFM_KernPair)a; - AFM_KernPair pair2 = (AFM_KernPair)b; - - FT_ULong index1 = KERN_INDEX( pair1->index1, pair1->index2 ); - FT_ULong index2 = KERN_INDEX( pair2->index1, pair2->index2 ); - - - if ( index1 > index2 ) - return 1; - else if ( index1 < index2 ) - return -1; - else - return 0; - } - - - /* parse a PFM file -- for now, only read the kerning pairs */ - static FT_Error - T1_Read_PFM( FT_Face t1_face, - FT_Stream stream, - AFM_FontInfo fi ) - { - FT_Error error = FT_Err_Ok; - FT_Memory memory = stream->memory; - FT_Byte* start; - FT_Byte* limit; - FT_Byte* p; - AFM_KernPair kp; - FT_Int width_table_length; - FT_CharMap oldcharmap; - FT_CharMap charmap; - FT_Int n; - - - start = (FT_Byte*)stream->cursor; - limit = (FT_Byte*)stream->limit; - - /* Figure out how long the width table is. */ - /* This info is a little-endian short at offset 99. */ - p = start + 99; - if ( p + 2 > limit ) - { - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - width_table_length = FT_PEEK_USHORT_LE( p ); - - p += 18 + width_table_length; - if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 ) - /* extension table is probably optional */ - goto Exit; - - /* Kerning offset is 14 bytes from start of extensions table. */ - p += 14; - p = start + FT_PEEK_ULONG_LE( p ); - - if ( p == start ) - /* zero offset means no table */ - goto Exit; - - if ( p + 2 > limit ) - { - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - fi->NumKernPair = FT_PEEK_USHORT_LE( p ); - p += 2; - if ( p + 4 * fi->NumKernPair > limit ) - { - error = FT_THROW( Unknown_File_Format ); - goto Exit; - } - - /* Actually, kerning pairs are simply optional! */ - if ( fi->NumKernPair == 0 ) - goto Exit; - - /* allocate the pairs */ - if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) - goto Exit; - - /* now, read each kern pair */ - kp = fi->KernPairs; - limit = p + 4 * fi->NumKernPair; - - /* PFM kerning data are stored by encoding rather than glyph index, */ - /* so find the PostScript charmap of this font and install it */ - /* temporarily. If we find no PostScript charmap, then just use */ - /* the default and hope it is the right one. */ - oldcharmap = t1_face->charmap; - charmap = NULL; - - for ( n = 0; n < t1_face->num_charmaps; n++ ) - { - charmap = t1_face->charmaps[n]; - /* check against PostScript pseudo platform */ - if ( charmap->platform_id == 7 ) - { - error = FT_Set_Charmap( t1_face, charmap ); - if ( error ) - goto Exit; - break; - } - } - - /* Kerning info is stored as: */ - /* */ - /* encoding of first glyph (1 byte) */ - /* encoding of second glyph (1 byte) */ - /* offset (little-endian short) */ - for ( ; p < limit ; p += 4 ) - { - kp->index1 = FT_Get_Char_Index( t1_face, p[0] ); - kp->index2 = FT_Get_Char_Index( t1_face, p[1] ); - - kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2); - kp->y = 0; - - kp++; - } - - if ( oldcharmap != NULL ) - error = FT_Set_Charmap( t1_face, oldcharmap ); - if ( error ) - goto Exit; - - /* now, sort the kern pairs according to their glyph indices */ - ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ), - compare_kern_pairs ); - - Exit: - if ( error ) - { - FT_FREE( fi->KernPairs ); - fi->NumKernPair = 0; - } - - return error; - } - - - /* parse a metrics file -- either AFM or PFM depending on what */ - /* it turns out to be */ - FT_LOCAL_DEF( FT_Error ) - T1_Read_Metrics( FT_Face t1_face, - FT_Stream stream ) - { - PSAux_Service psaux; - FT_Memory memory = stream->memory; - AFM_ParserRec parser; - AFM_FontInfo fi = NULL; - FT_Error error = FT_ERR( Unknown_File_Format ); - T1_Font t1_font = &( (T1_Face)t1_face )->type1; - - - if ( FT_NEW( fi ) || - FT_FRAME_ENTER( stream->size ) ) - goto Exit; - - fi->FontBBox = t1_font->font_bbox; - fi->Ascender = t1_font->font_bbox.yMax; - fi->Descender = t1_font->font_bbox.yMin; - - psaux = (PSAux_Service)( (T1_Face)t1_face )->psaux; - if ( psaux->afm_parser_funcs ) - { - error = psaux->afm_parser_funcs->init( &parser, - stream->memory, - stream->cursor, - stream->limit ); - - if ( !error ) - { - parser.FontInfo = fi; - parser.get_index = t1_get_index; - parser.user_data = t1_font; - - error = psaux->afm_parser_funcs->parse( &parser ); - psaux->afm_parser_funcs->done( &parser ); - } - } - - if ( FT_ERR_EQ( error, Unknown_File_Format ) ) - { - FT_Byte* start = stream->cursor; - - - /* MS Windows allows versions up to 0x3FF without complaining */ - if ( stream->size > 6 && - start[1] < 4 && - FT_PEEK_ULONG_LE( start + 2 ) == stream->size ) - error = T1_Read_PFM( t1_face, stream, fi ); - } - - if ( !error ) - { - t1_font->font_bbox = fi->FontBBox; - - t1_face->bbox.xMin = fi->FontBBox.xMin >> 16; - t1_face->bbox.yMin = fi->FontBBox.yMin >> 16; - /* no `U' suffix here to 0xFFFF! */ - t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16; - t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16; - - /* no `U' suffix here to 0x8000! */ - t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 ); - t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 ); - - if ( fi->NumKernPair ) - { - t1_face->face_flags |= FT_FACE_FLAG_KERNING; - ( (T1_Face)t1_face )->afm_data = fi; - fi = NULL; - } - } - - FT_FRAME_EXIT(); - - Exit: - if ( fi != NULL ) - T1_Done_Metrics( memory, fi ); - - return error; - } - - - /* find the kerning for a given glyph pair */ - FT_LOCAL_DEF( void ) - T1_Get_Kerning( AFM_FontInfo fi, - FT_UInt glyph1, - FT_UInt glyph2, - FT_Vector* kerning ) - { - AFM_KernPair min, mid, max; - FT_ULong idx = KERN_INDEX( glyph1, glyph2 ); - - - /* simple binary search */ - min = fi->KernPairs; - max = min + fi->NumKernPair - 1; - - while ( min <= max ) - { - FT_ULong midi; - - - mid = min + ( max - min ) / 2; - midi = KERN_INDEX( mid->index1, mid->index2 ); - - if ( midi == idx ) - { - kerning->x = mid->x; - kerning->y = mid->y; - - return; - } - - if ( midi < idx ) - min = mid + 1; - else - max = mid - 1; - } - - kerning->x = 0; - kerning->y = 0; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Get_Track_Kerning( FT_Face face, - FT_Fixed ptsize, - FT_Int degree, - FT_Fixed* kerning ) - { - AFM_FontInfo fi = (AFM_FontInfo)( (T1_Face)face )->afm_data; - FT_UInt i; - - - if ( !fi ) - return FT_THROW( Invalid_Argument ); - - for ( i = 0; i < fi->NumTrackKern; i++ ) - { - AFM_TrackKern tk = fi->TrackKerns + i; - - - if ( tk->degree != degree ) - continue; - - if ( ptsize < tk->min_ptsize ) - *kerning = tk->min_kern; - else if ( ptsize > tk->max_ptsize ) - *kerning = tk->max_kern; - else - { - *kerning = FT_MulDiv( ptsize - tk->min_ptsize, - tk->max_kern - tk->min_kern, - tk->max_ptsize - tk->min_ptsize ) + - tk->min_kern; - } - } - - return FT_Err_Ok; - } - - -/* END */ diff --git a/third_party/freetype/src/type1/t1afm.h b/third_party/freetype/src/type1/t1afm.h deleted file mode 100644 index 0f42f3e3a83f2982283aaebc3869beef836303f5..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1afm.h +++ /dev/null @@ -1,54 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1afm.h */ -/* */ -/* AFM support for Type 1 fonts (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1AFM_H__ -#define __T1AFM_H__ - -#include <ft2build.h> -#include "t1objs.h" -#include FT_INTERNAL_TYPE1_TYPES_H - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - T1_Read_Metrics( FT_Face face, - FT_Stream stream ); - - FT_LOCAL( void ) - T1_Done_Metrics( FT_Memory memory, - AFM_FontInfo fi ); - - FT_LOCAL( void ) - T1_Get_Kerning( AFM_FontInfo fi, - FT_UInt glyph1, - FT_UInt glyph2, - FT_Vector* kerning ); - - FT_LOCAL( FT_Error ) - T1_Get_Track_Kerning( FT_Face face, - FT_Fixed ptsize, - FT_Int degree, - FT_Fixed* kerning ); - -FT_END_HEADER - -#endif /* __T1AFM_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1driver.c b/third_party/freetype/src/type1/t1driver.c deleted file mode 100644 index 571f2d2f8cde69efa8cc6f0d64f469befd1ae17d..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1driver.c +++ /dev/null @@ -1,725 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1driver.c */ -/* */ -/* Type 1 driver interface (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "t1driver.h" -#include "t1gload.h" -#include "t1load.h" - -#include "t1errors.h" - -#ifndef T1_CONFIG_OPTION_NO_AFM -#include "t1afm.h" -#endif - -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H - -#include FT_SERVICE_MULTIPLE_MASTERS_H -#include FT_SERVICE_GLYPH_DICT_H -#include FT_SERVICE_FONT_FORMAT_H -#include FT_SERVICE_POSTSCRIPT_NAME_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_SERVICE_POSTSCRIPT_INFO_H -#include FT_SERVICE_KERNING_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1driver - - /* - * GLYPH DICT SERVICE - * - */ - - static FT_Error - t1_get_glyph_name( T1_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ) - { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); - - return FT_Err_Ok; - } - - - static FT_UInt - t1_get_name_index( T1_Face face, - FT_String* glyph_name ) - { - FT_Int i; - - - for ( i = 0; i < face->type1.num_glyphs; i++ ) - { - FT_String* gname = face->type1.glyph_names[i]; - - - if ( !ft_strcmp( glyph_name, gname ) ) - return (FT_UInt)i; - } - - return 0; - } - - - static const FT_Service_GlyphDictRec t1_service_glyph_dict = - { - (FT_GlyphDict_GetNameFunc) t1_get_glyph_name, - (FT_GlyphDict_NameIndexFunc)t1_get_name_index - }; - - - /* - * POSTSCRIPT NAME SERVICE - * - */ - - static const char* - t1_get_ps_name( T1_Face face ) - { - return (const char*) face->type1.font_name; - } - - - static const FT_Service_PsFontNameRec t1_service_ps_name = - { - (FT_PsName_GetFunc)t1_get_ps_name - }; - - - /* - * MULTIPLE MASTERS SERVICE - * - */ - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - static const FT_Service_MultiMastersRec t1_service_multi_masters = - { - (FT_Get_MM_Func) T1_Get_Multi_Master, - (FT_Set_MM_Design_Func) T1_Set_MM_Design, - (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, - (FT_Get_MM_Var_Func) T1_Get_MM_Var, - (FT_Set_Var_Design_Func)T1_Set_Var_Design - }; -#endif - - - /* - * POSTSCRIPT INFO SERVICE - * - */ - - static FT_Error - t1_ps_get_font_info( FT_Face face, - PS_FontInfoRec* afont_info ) - { - *afont_info = ((T1_Face)face)->type1.font_info; - - return FT_Err_Ok; - } - - - static FT_Error - t1_ps_get_font_extra( FT_Face face, - PS_FontExtraRec* afont_extra ) - { - *afont_extra = ((T1_Face)face)->type1.font_extra; - - return FT_Err_Ok; - } - - - static FT_Int - t1_ps_has_glyph_names( FT_Face face ) - { - FT_UNUSED( face ); - - return 1; - } - - - static FT_Error - t1_ps_get_font_private( FT_Face face, - PS_PrivateRec* afont_private ) - { - *afont_private = ((T1_Face)face)->type1.private_dict; - - return FT_Err_Ok; - } - - - static FT_Long - t1_ps_get_font_value( FT_Face face, - PS_Dict_Keys key, - FT_UInt idx, - void *value, - FT_Long value_len_ ) - { - FT_ULong retval = 0; /* always >= 1 if valid */ - FT_ULong value_len = value_len_ < 0 ? 0 : (FT_ULong)value_len_; - - T1_Face t1face = (T1_Face)face; - T1_Font type1 = &t1face->type1; - - - switch ( key ) - { - case PS_DICT_FONT_TYPE: - retval = sizeof ( type1->font_type ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->font_type; - break; - - case PS_DICT_FONT_MATRIX: - if ( idx < sizeof ( type1->font_matrix ) / - sizeof ( type1->font_matrix.xx ) ) - { - FT_Fixed val = 0; - - - retval = sizeof ( val ); - if ( value && value_len >= retval ) - { - switch ( idx ) - { - case 0: - val = type1->font_matrix.xx; - break; - case 1: - val = type1->font_matrix.xy; - break; - case 2: - val = type1->font_matrix.yx; - break; - case 3: - val = type1->font_matrix.yy; - break; - } - *((FT_Fixed *)value) = val; - } - } - break; - - case PS_DICT_FONT_BBOX: - if ( idx < sizeof ( type1->font_bbox ) / - sizeof ( type1->font_bbox.xMin ) ) - { - FT_Fixed val = 0; - - - retval = sizeof ( val ); - if ( value && value_len >= retval ) - { - switch ( idx ) - { - case 0: - val = type1->font_bbox.xMin; - break; - case 1: - val = type1->font_bbox.yMin; - break; - case 2: - val = type1->font_bbox.xMax; - break; - case 3: - val = type1->font_bbox.yMax; - break; - } - *((FT_Fixed *)value) = val; - } - } - break; - - case PS_DICT_PAINT_TYPE: - retval = sizeof ( type1->paint_type ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->paint_type; - break; - - case PS_DICT_FONT_NAME: - retval = ft_strlen( type1->font_name ) + 1; - if ( value && value_len >= retval ) - ft_memcpy( value, (void *)( type1->font_name ), retval ); - break; - - case PS_DICT_UNIQUE_ID: - retval = sizeof ( type1->private_dict.unique_id ); - if ( value && value_len >= retval ) - *((FT_Int *)value) = type1->private_dict.unique_id; - break; - - case PS_DICT_NUM_CHAR_STRINGS: - retval = sizeof ( type1->num_glyphs ); - if ( value && value_len >= retval ) - *((FT_Int *)value) = type1->num_glyphs; - break; - - case PS_DICT_CHAR_STRING_KEY: - if ( idx < (FT_UInt)type1->num_glyphs ) - { - retval = ft_strlen( type1->glyph_names[idx] ) + 1; - if ( value && value_len >= retval ) - { - ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval ); - ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; - } - } - break; - - case PS_DICT_CHAR_STRING: - if ( idx < (FT_UInt)type1->num_glyphs ) - { - retval = type1->charstrings_len[idx] + 1; - if ( value && value_len >= retval ) - { - ft_memcpy( value, (void *)( type1->charstrings[idx] ), - retval - 1 ); - ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; - } - } - break; - - case PS_DICT_ENCODING_TYPE: - retval = sizeof ( type1->encoding_type ); - if ( value && value_len >= retval ) - *((T1_EncodingType *)value) = type1->encoding_type; - break; - - case PS_DICT_ENCODING_ENTRY: - if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY && - idx < (FT_UInt)type1->encoding.num_chars ) - { - retval = ft_strlen( type1->encoding.char_name[idx] ) + 1; - if ( value && value_len >= retval ) - { - ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ), - retval - 1 ); - ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; - } - } - break; - - case PS_DICT_NUM_SUBRS: - retval = sizeof ( type1->num_subrs ); - if ( value && value_len >= retval ) - *((FT_Int *)value) = type1->num_subrs; - break; - - case PS_DICT_SUBR: - if ( idx < (FT_UInt)type1->num_subrs ) - { - retval = type1->subrs_len[idx] + 1; - if ( value && value_len >= retval ) - { - ft_memcpy( value, (void *)( type1->subrs[idx] ), retval - 1 ); - ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; - } - } - break; - - case PS_DICT_STD_HW: - retval = sizeof ( type1->private_dict.standard_width[0] ); - if ( value && value_len >= retval ) - *((FT_UShort *)value) = type1->private_dict.standard_width[0]; - break; - - case PS_DICT_STD_VW: - retval = sizeof ( type1->private_dict.standard_height[0] ); - if ( value && value_len >= retval ) - *((FT_UShort *)value) = type1->private_dict.standard_height[0]; - break; - - case PS_DICT_NUM_BLUE_VALUES: - retval = sizeof ( type1->private_dict.num_blue_values ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->private_dict.num_blue_values; - break; - - case PS_DICT_BLUE_VALUE: - if ( idx < type1->private_dict.num_blue_values ) - { - retval = sizeof ( type1->private_dict.blue_values[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.blue_values[idx]; - } - break; - - case PS_DICT_BLUE_SCALE: - retval = sizeof ( type1->private_dict.blue_scale ); - if ( value && value_len >= retval ) - *((FT_Fixed *)value) = type1->private_dict.blue_scale; - break; - - case PS_DICT_BLUE_FUZZ: - retval = sizeof ( type1->private_dict.blue_fuzz ); - if ( value && value_len >= retval ) - *((FT_Int *)value) = type1->private_dict.blue_fuzz; - break; - - case PS_DICT_BLUE_SHIFT: - retval = sizeof ( type1->private_dict.blue_shift ); - if ( value && value_len >= retval ) - *((FT_Int *)value) = type1->private_dict.blue_shift; - break; - - case PS_DICT_NUM_OTHER_BLUES: - retval = sizeof ( type1->private_dict.num_other_blues ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->private_dict.num_other_blues; - break; - - case PS_DICT_OTHER_BLUE: - if ( idx < type1->private_dict.num_other_blues ) - { - retval = sizeof ( type1->private_dict.other_blues[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.other_blues[idx]; - } - break; - - case PS_DICT_NUM_FAMILY_BLUES: - retval = sizeof ( type1->private_dict.num_family_blues ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->private_dict.num_family_blues; - break; - - case PS_DICT_FAMILY_BLUE: - if ( idx < type1->private_dict.num_family_blues ) - { - retval = sizeof ( type1->private_dict.family_blues[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.family_blues[idx]; - } - break; - - case PS_DICT_NUM_FAMILY_OTHER_BLUES: - retval = sizeof ( type1->private_dict.num_family_other_blues ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->private_dict.num_family_other_blues; - break; - - case PS_DICT_FAMILY_OTHER_BLUE: - if ( idx < type1->private_dict.num_family_other_blues ) - { - retval = sizeof ( type1->private_dict.family_other_blues[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.family_other_blues[idx]; - } - break; - - case PS_DICT_NUM_STEM_SNAP_H: - retval = sizeof ( type1->private_dict.num_snap_widths ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->private_dict.num_snap_widths; - break; - - case PS_DICT_STEM_SNAP_H: - if ( idx < type1->private_dict.num_snap_widths ) - { - retval = sizeof ( type1->private_dict.snap_widths[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.snap_widths[idx]; - } - break; - - case PS_DICT_NUM_STEM_SNAP_V: - retval = sizeof ( type1->private_dict.num_snap_heights ); - if ( value && value_len >= retval ) - *((FT_Byte *)value) = type1->private_dict.num_snap_heights; - break; - - case PS_DICT_STEM_SNAP_V: - if ( idx < type1->private_dict.num_snap_heights ) - { - retval = sizeof ( type1->private_dict.snap_heights[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.snap_heights[idx]; - } - break; - - case PS_DICT_RND_STEM_UP: - retval = sizeof ( type1->private_dict.round_stem_up ); - if ( value && value_len >= retval ) - *((FT_Bool *)value) = type1->private_dict.round_stem_up; - break; - - case PS_DICT_FORCE_BOLD: - retval = sizeof ( type1->private_dict.force_bold ); - if ( value && value_len >= retval ) - *((FT_Bool *)value) = type1->private_dict.force_bold; - break; - - case PS_DICT_MIN_FEATURE: - if ( idx < sizeof ( type1->private_dict.min_feature ) / - sizeof ( type1->private_dict.min_feature[0] ) ) - { - retval = sizeof ( type1->private_dict.min_feature[idx] ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->private_dict.min_feature[idx]; - } - break; - - case PS_DICT_LEN_IV: - retval = sizeof ( type1->private_dict.lenIV ); - if ( value && value_len >= retval ) - *((FT_Int *)value) = type1->private_dict.lenIV; - break; - - case PS_DICT_PASSWORD: - retval = sizeof ( type1->private_dict.password ); - if ( value && value_len >= retval ) - *((FT_Long *)value) = type1->private_dict.password; - break; - - case PS_DICT_LANGUAGE_GROUP: - retval = sizeof ( type1->private_dict.language_group ); - if ( value && value_len >= retval ) - *((FT_Long *)value) = type1->private_dict.language_group; - break; - - case PS_DICT_IS_FIXED_PITCH: - retval = sizeof ( type1->font_info.is_fixed_pitch ); - if ( value && value_len >= retval ) - *((FT_Bool *)value) = type1->font_info.is_fixed_pitch; - break; - - case PS_DICT_UNDERLINE_POSITION: - retval = sizeof ( type1->font_info.underline_position ); - if ( value && value_len >= retval ) - *((FT_Short *)value) = type1->font_info.underline_position; - break; - - case PS_DICT_UNDERLINE_THICKNESS: - retval = sizeof ( type1->font_info.underline_thickness ); - if ( value && value_len >= retval ) - *((FT_UShort *)value) = type1->font_info.underline_thickness; - break; - - case PS_DICT_FS_TYPE: - retval = sizeof ( type1->font_extra.fs_type ); - if ( value && value_len >= retval ) - *((FT_UShort *)value) = type1->font_extra.fs_type; - break; - - case PS_DICT_VERSION: - retval = ft_strlen( type1->font_info.version ) + 1; - if ( value && value_len >= retval ) - ft_memcpy( value, (void *)( type1->font_info.version ), retval ); - break; - - case PS_DICT_NOTICE: - retval = ft_strlen( type1->font_info.notice ) + 1; - if ( value && value_len >= retval ) - ft_memcpy( value, (void *)( type1->font_info.notice ), retval ); - break; - - case PS_DICT_FULL_NAME: - retval = ft_strlen( type1->font_info.full_name ) + 1; - if ( value && value_len >= retval ) - ft_memcpy( value, (void *)( type1->font_info.full_name ), retval ); - break; - - case PS_DICT_FAMILY_NAME: - retval = ft_strlen( type1->font_info.family_name ) + 1; - if ( value && value_len >= retval ) - ft_memcpy( value, (void *)( type1->font_info.family_name ), retval ); - break; - - case PS_DICT_WEIGHT: - retval = ft_strlen( type1->font_info.weight ) + 1; - if ( value && value_len >= retval ) - ft_memcpy( value, (void *)( type1->font_info.weight ), retval ); - break; - - case PS_DICT_ITALIC_ANGLE: - retval = sizeof ( type1->font_info.italic_angle ); - if ( value && value_len >= retval ) - *((FT_Long *)value) = type1->font_info.italic_angle; - break; - } - - return retval == 0 ? -1 : (FT_Long)retval; - } - - - static const FT_Service_PsInfoRec t1_service_ps_info = - { - (PS_GetFontInfoFunc) t1_ps_get_font_info, - (PS_GetFontExtraFunc) t1_ps_get_font_extra, - (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names, - (PS_GetFontPrivateFunc)t1_ps_get_font_private, - (PS_GetFontValueFunc) t1_ps_get_font_value, - }; - - -#ifndef T1_CONFIG_OPTION_NO_AFM - static const FT_Service_KerningRec t1_service_kerning = - { - T1_Get_Track_Kerning, - }; -#endif - - - /* - * SERVICE LIST - * - */ - - static const FT_ServiceDescRec t1_services[] = - { - { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t1_service_ps_name }, - { FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict }, - { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TYPE_1 }, - { FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info }, - -#ifndef T1_CONFIG_OPTION_NO_AFM - { FT_SERVICE_ID_KERNING, &t1_service_kerning }, -#endif - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - { FT_SERVICE_ID_MULTI_MASTERS, &t1_service_multi_masters }, -#endif - { NULL, NULL } - }; - - - FT_CALLBACK_DEF( FT_Module_Interface ) - Get_Interface( FT_Module module, - const FT_String* t1_interface ) - { - FT_UNUSED( module ); - - return ft_service_list_lookup( t1_services, t1_interface ); - } - - -#ifndef T1_CONFIG_OPTION_NO_AFM - - /*************************************************************************/ - /* */ - /* <Function> */ - /* Get_Kerning */ - /* */ - /* <Description> */ - /* A driver method used to return the kerning vector between two */ - /* glyphs of the same face. */ - /* */ - /* <Input> */ - /* face :: A handle to the source face object. */ - /* */ - /* left_glyph :: The index of the left glyph in the kern pair. */ - /* */ - /* right_glyph :: The index of the right glyph in the kern pair. */ - /* */ - /* <Output> */ - /* kerning :: The kerning vector. This is in font units for */ - /* scalable formats, and in pixels for fixed-sizes */ - /* formats. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - /* <Note> */ - /* Only horizontal layouts (left-to-right & right-to-left) are */ - /* supported by this function. Other layouts, or more sophisticated */ - /* kernings are out of scope of this method (the basic driver */ - /* interface is meant to be simple). */ - /* */ - /* They can be implemented by format-specific interfaces. */ - /* */ - static FT_Error - Get_Kerning( FT_Face t1face, /* T1_Face */ - FT_UInt left_glyph, - FT_UInt right_glyph, - FT_Vector* kerning ) - { - T1_Face face = (T1_Face)t1face; - - - kerning->x = 0; - kerning->y = 0; - - if ( face->afm_data ) - T1_Get_Kerning( (AFM_FontInfo)face->afm_data, - left_glyph, - right_glyph, - kerning ); - - return FT_Err_Ok; - } - - -#endif /* T1_CONFIG_OPTION_NO_AFM */ - - - FT_CALLBACK_TABLE_DEF - const FT_Driver_ClassRec t1_driver_class = - { - { - FT_MODULE_FONT_DRIVER | - FT_MODULE_DRIVER_SCALABLE | - FT_MODULE_DRIVER_HAS_HINTER, - - sizeof ( FT_DriverRec ), - - "type1", - 0x10000L, - 0x20000L, - - 0, /* format interface */ - - T1_Driver_Init, - T1_Driver_Done, - Get_Interface, - }, - - sizeof ( T1_FaceRec ), - sizeof ( T1_SizeRec ), - sizeof ( T1_GlyphSlotRec ), - - T1_Face_Init, - T1_Face_Done, - T1_Size_Init, - T1_Size_Done, - T1_GlyphSlot_Init, - T1_GlyphSlot_Done, - - T1_Load_Glyph, - -#ifdef T1_CONFIG_OPTION_NO_AFM - 0, /* FT_Face_GetKerningFunc */ - 0, /* FT_Face_AttachFunc */ -#else - Get_Kerning, - T1_Read_Metrics, -#endif - T1_Get_Advances, - T1_Size_Request, - 0 /* FT_Size_SelectFunc */ - }; - - -/* END */ diff --git a/third_party/freetype/src/type1/t1driver.h b/third_party/freetype/src/type1/t1driver.h deleted file mode 100644 index 34bcf81ccf394c43a78581c6a19286d3d32e4429..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1driver.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1driver.h */ -/* */ -/* High-level Type 1 driver interface (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1DRIVER_H__ -#define __T1DRIVER_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_DRIVER_H - - -FT_BEGIN_HEADER - -#ifdef FT_CONFIG_OPTION_PIC -#error "this module does not support PIC yet" -#endif - - - FT_EXPORT_VAR( const FT_Driver_ClassRec ) t1_driver_class; - - -FT_END_HEADER - -#endif /* __T1DRIVER_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1errors.h b/third_party/freetype/src/type1/t1errors.h deleted file mode 100644 index fc7a9bd64e438ea380a015bca522f3f9c79db7a2..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1errors.h +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1errors.h */ -/* */ -/* Type 1 error codes (specification only). */ -/* */ -/* Copyright 2001-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This file is used to define the Type 1 error enumeration constants. */ - /* */ - /*************************************************************************/ - -#ifndef __T1ERRORS_H__ -#define __T1ERRORS_H__ - -#include FT_MODULE_ERRORS_H - -#undef __FTERRORS_H__ - -#undef FT_ERR_PREFIX -#define FT_ERR_PREFIX T1_Err_ -#define FT_ERR_BASE FT_Mod_Err_Type1 - -#include FT_ERRORS_H - -#endif /* __T1ERRORS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1gload.c b/third_party/freetype/src/type1/t1gload.c deleted file mode 100644 index 85ada2ea6a91c6e0a59a27ab5a48bece27fd1f75..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1gload.c +++ /dev/null @@ -1,521 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1gload.c */ -/* */ -/* Type 1 Glyph Loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include "t1gload.h" -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_OUTLINE_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H - -#include "t1errors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1gload - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ - /********** *********/ - /********** The following code is in charge of computing *********/ - /********** the maximum advance width of the font. It *********/ - /********** quickly processes each glyph charstring to *********/ - /********** extract the value from either a `sbw' or `seac' *********/ - /********** operator. *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - static FT_Error - T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, - FT_UInt glyph_index, - FT_Data* char_string ) - { - T1_Face face = (T1_Face)decoder->builder.face; - T1_Font type1 = &face->type1; - FT_Error error = FT_Err_Ok; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - FT_Incremental_InterfaceRec *inc = - face->root.internal->incremental_interface; -#endif - - - decoder->font_matrix = type1->font_matrix; - decoder->font_offset = type1->font_offset; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* For incremental fonts get the character data using the */ - /* callback function. */ - if ( inc ) - error = inc->funcs->get_glyph_data( inc->object, - glyph_index, char_string ); - else - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - /* For ordinary fonts get the character data stored in the face record. */ - { - char_string->pointer = type1->charstrings[glyph_index]; - char_string->length = (FT_Int)type1->charstrings_len[glyph_index]; - } - - if ( !error ) - error = decoder->funcs.parse_charstrings( - decoder, (FT_Byte*)char_string->pointer, - (FT_UInt)char_string->length ); - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - /* Incremental fonts can optionally override the metrics. */ - if ( !error && inc && inc->funcs->get_glyph_metrics ) - { - FT_Incremental_MetricsRec metrics; - - - metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); - metrics.bearing_y = 0; - metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); - metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); - - error = inc->funcs->get_glyph_metrics( inc->object, - glyph_index, FALSE, &metrics ); - - decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); - decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); - decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); - } - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - return error; - } - - - FT_CALLBACK_DEF( FT_Error ) - T1_Parse_Glyph( T1_Decoder decoder, - FT_UInt glyph_index ) - { - FT_Data glyph_data; - FT_Error error = T1_Parse_Glyph_And_Get_Char_String( - decoder, glyph_index, &glyph_data ); - - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - - if ( !error ) - { - T1_Face face = (T1_Face)decoder->builder.face; - - - if ( face->root.internal->incremental_interface ) - face->root.internal->incremental_interface->funcs->free_glyph_data( - face->root.internal->incremental_interface->object, - &glyph_data ); - } - -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Compute_Max_Advance( T1_Face face, - FT_Pos* max_advance ) - { - FT_Error error; - T1_DecoderRec decoder; - FT_Int glyph_index; - T1_Font type1 = &face->type1; - PSAux_Service psaux = (PSAux_Service)face->psaux; - - - FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); - - *max_advance = 0; - - /* initialize load decoder */ - error = psaux->t1_decoder_funcs->init( &decoder, - (FT_Face)face, - 0, /* size */ - 0, /* glyph slot */ - (FT_Byte**)type1->glyph_names, - face->blend, - 0, - FT_RENDER_MODE_NORMAL, - T1_Parse_Glyph ); - if ( error ) - return error; - - decoder.builder.metrics_only = 1; - decoder.builder.load_points = 0; - - decoder.num_subrs = type1->num_subrs; - decoder.subrs = type1->subrs; - decoder.subrs_len = type1->subrs_len; - - decoder.buildchar = face->buildchar; - decoder.len_buildchar = face->len_buildchar; - - *max_advance = 0; - - /* for each glyph, parse the glyph charstring and extract */ - /* the advance width */ - for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) - { - /* now get load the unscaled outline */ - (void)T1_Parse_Glyph( &decoder, (FT_UInt)glyph_index ); - if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance ) - *max_advance = decoder.builder.advance.x; - - /* ignore the error if one occurred - skip to next glyph */ - } - - psaux->t1_decoder_funcs->done( &decoder ); - - return FT_Err_Ok; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Get_Advances( FT_Face t1face, /* T1_Face */ - FT_UInt first, - FT_UInt count, - FT_Int32 load_flags, - FT_Fixed* advances ) - { - T1_Face face = (T1_Face)t1face; - T1_DecoderRec decoder; - T1_Font type1 = &face->type1; - PSAux_Service psaux = (PSAux_Service)face->psaux; - FT_UInt nn; - FT_Error error; - - - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - for ( nn = 0; nn < count; nn++ ) - advances[nn] = 0; - - return FT_Err_Ok; - } - - error = psaux->t1_decoder_funcs->init( &decoder, - (FT_Face)face, - 0, /* size */ - 0, /* glyph slot */ - (FT_Byte**)type1->glyph_names, - face->blend, - 0, - FT_RENDER_MODE_NORMAL, - T1_Parse_Glyph ); - if ( error ) - return error; - - decoder.builder.metrics_only = 1; - decoder.builder.load_points = 0; - - decoder.num_subrs = type1->num_subrs; - decoder.subrs = type1->subrs; - decoder.subrs_len = type1->subrs_len; - - decoder.buildchar = face->buildchar; - decoder.len_buildchar = face->len_buildchar; - - for ( nn = 0; nn < count; nn++ ) - { - error = T1_Parse_Glyph( &decoder, first + nn ); - if ( !error ) - advances[nn] = FIXED_TO_INT( decoder.builder.advance.x ); - else - advances[nn] = 0; - } - - return FT_Err_Ok; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ - FT_Size t1size, /* T1_Size */ - FT_UInt glyph_index, - FT_Int32 load_flags ) - { - T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; - FT_Error error; - T1_DecoderRec decoder; - T1_Face face = (T1_Face)t1glyph->face; - FT_Bool hinting; - T1_Font type1 = &face->type1; - PSAux_Service psaux = (PSAux_Service)face->psaux; - const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; - - FT_Matrix font_matrix; - FT_Vector font_offset; - FT_Data glyph_data; - FT_Bool must_finish_decoder = FALSE; -#ifdef FT_CONFIG_OPTION_INCREMENTAL - FT_Bool glyph_data_loaded = 0; -#endif - - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - if ( glyph_index >= (FT_UInt)face->root.num_glyphs && - !face->root.internal->incremental_interface ) -#else - if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index )); - - FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); - - if ( load_flags & FT_LOAD_NO_RECURSE ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; - - if ( t1size ) - { - glyph->x_scale = t1size->metrics.x_scale; - glyph->y_scale = t1size->metrics.y_scale; - } - else - { - glyph->x_scale = 0x10000L; - glyph->y_scale = 0x10000L; - } - - t1glyph->outline.n_points = 0; - t1glyph->outline.n_contours = 0; - - hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && - ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); - - t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; - - error = decoder_funcs->init( &decoder, - t1glyph->face, - t1size, - t1glyph, - (FT_Byte**)type1->glyph_names, - face->blend, - FT_BOOL( hinting ), - FT_LOAD_TARGET_MODE( load_flags ), - T1_Parse_Glyph ); - if ( error ) - goto Exit; - - must_finish_decoder = TRUE; - - decoder.builder.no_recurse = FT_BOOL( - ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); - - decoder.num_subrs = type1->num_subrs; - decoder.subrs = type1->subrs; - decoder.subrs_len = type1->subrs_len; - - decoder.buildchar = face->buildchar; - decoder.len_buildchar = face->len_buildchar; - - /* now load the unscaled outline */ - error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, - &glyph_data ); - if ( error ) - goto Exit; -#ifdef FT_CONFIG_OPTION_INCREMENTAL - glyph_data_loaded = 1; -#endif - - font_matrix = decoder.font_matrix; - font_offset = decoder.font_offset; - - /* save new glyph tables */ - decoder_funcs->done( &decoder ); - - must_finish_decoder = FALSE; - - /* now, set the metrics -- this is rather simple, as */ - /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax */ - if ( !error ) - { - t1glyph->outline.flags &= FT_OUTLINE_OWNER; - t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; - - /* for composite glyphs, return only left side bearing and */ - /* advance width */ - if ( load_flags & FT_LOAD_NO_RECURSE ) - { - FT_Slot_Internal internal = t1glyph->internal; - - - t1glyph->metrics.horiBearingX = - FIXED_TO_INT( decoder.builder.left_bearing.x ); - t1glyph->metrics.horiAdvance = - FIXED_TO_INT( decoder.builder.advance.x ); - - internal->glyph_matrix = font_matrix; - internal->glyph_delta = font_offset; - internal->glyph_transformed = 1; - } - else - { - FT_BBox cbox; - FT_Glyph_Metrics* metrics = &t1glyph->metrics; - - - /* copy the _unscaled_ advance width */ - metrics->horiAdvance = - FIXED_TO_INT( decoder.builder.advance.x ); - t1glyph->linearHoriAdvance = - FIXED_TO_INT( decoder.builder.advance.x ); - t1glyph->internal->glyph_transformed = 0; - - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - /* make up vertical ones */ - metrics->vertAdvance = ( face->type1.font_bbox.yMax - - face->type1.font_bbox.yMin ) >> 16; - t1glyph->linearVertAdvance = metrics->vertAdvance; - } - else - { - metrics->vertAdvance = - FIXED_TO_INT( decoder.builder.advance.y ); - t1glyph->linearVertAdvance = - FIXED_TO_INT( decoder.builder.advance.y ); - } - - t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; - - if ( t1size && t1size->metrics.y_ppem < 24 ) - t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - -#if 1 - /* apply the font matrix, if any */ - if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || - font_matrix.xy != 0 || font_matrix.yx != 0 ) - { - FT_Outline_Transform( &t1glyph->outline, &font_matrix ); - - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, - font_matrix.xx ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, - font_matrix.yy ); - } - - if ( font_offset.x || font_offset.y ) - { - FT_Outline_Translate( &t1glyph->outline, - font_offset.x, - font_offset.y ); - - metrics->horiAdvance += font_offset.x; - metrics->vertAdvance += font_offset.y; - } -#endif - - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) - { - /* scale the outline and the metrics */ - FT_Int n; - FT_Outline* cur = decoder.builder.base; - FT_Vector* vec = cur->points; - FT_Fixed x_scale = glyph->x_scale; - FT_Fixed y_scale = glyph->y_scale; - - - /* First of all, scale the points, if we are not hinting */ - if ( !hinting || ! decoder.builder.hints_funcs ) - for ( n = cur->n_points; n > 0; n--, vec++ ) - { - vec->x = FT_MulFix( vec->x, x_scale ); - vec->y = FT_MulFix( vec->y, y_scale ); - } - - /* Then scale the metrics */ - metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); - metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); - } - - /* compute the other metrics */ - FT_Outline_Get_CBox( &t1glyph->outline, &cbox ); - - metrics->width = cbox.xMax - cbox.xMin; - metrics->height = cbox.yMax - cbox.yMin; - - metrics->horiBearingX = cbox.xMin; - metrics->horiBearingY = cbox.yMax; - - if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) - { - /* make up vertical ones */ - ft_synthesize_vertical_metrics( metrics, - metrics->vertAdvance ); - } - } - - /* Set control data to the glyph charstrings. Note that this is */ - /* _not_ zero-terminated. */ - t1glyph->control_data = (FT_Byte*)glyph_data.pointer; - t1glyph->control_len = glyph_data.length; - } - - - Exit: - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - if ( glyph_data_loaded && face->root.internal->incremental_interface ) - { - face->root.internal->incremental_interface->funcs->free_glyph_data( - face->root.internal->incremental_interface->object, - &glyph_data ); - - /* Set the control data to null - it is no longer available if */ - /* loaded incrementally. */ - t1glyph->control_data = NULL; - t1glyph->control_len = 0; - } -#endif - - if ( must_finish_decoder ) - decoder_funcs->done( &decoder ); - - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/type1/t1gload.h b/third_party/freetype/src/type1/t1gload.h deleted file mode 100644 index 05f60d586a1df05914bb5a8a1551b4469093a6dc..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1gload.h +++ /dev/null @@ -1,53 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1gload.h */ -/* */ -/* Type 1 Glyph Loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1GLOAD_H__ -#define __T1GLOAD_H__ - - -#include <ft2build.h> -#include "t1objs.h" - - -FT_BEGIN_HEADER - - - FT_LOCAL( FT_Error ) - T1_Compute_Max_Advance( T1_Face face, - FT_Pos* max_advance ); - - FT_LOCAL( FT_Error ) - T1_Get_Advances( FT_Face face, - FT_UInt first, - FT_UInt count, - FT_Int32 load_flags, - FT_Fixed* advances ); - - FT_LOCAL( FT_Error ) - T1_Load_Glyph( FT_GlyphSlot glyph, - FT_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ); - - -FT_END_HEADER - -#endif /* __T1GLOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1load.c b/third_party/freetype/src/type1/t1load.c deleted file mode 100644 index dbf4eafd716a31760b7273b9e2f9606cbebab261..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1load.c +++ /dev/null @@ -1,2320 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1load.c */ -/* */ -/* Type 1 font loader (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* This is the new and improved Type 1 data loader for FreeType 2. The */ - /* old loader has several problems: it is slow, complex, difficult to */ - /* maintain, and contains incredible hacks to make it accept some */ - /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ - /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ - /* */ - /* This version is much simpler, much faster and also easier to read and */ - /* maintain by a great order of magnitude. The idea behind it is to */ - /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ - /* a Postscript-like interpreter) but rather to perform simple pattern */ - /* matching. */ - /* */ - /* Indeed, nearly all data definitions follow a simple pattern like */ - /* */ - /* ... /Field <data> ... */ - /* */ - /* where <data> can be a number, a boolean, a string, or an array of */ - /* numbers. There are a few exceptions, namely the encoding, font name, */ - /* charstrings, and subrs; they are handled with a special pattern */ - /* matching routine. */ - /* */ - /* All other common cases are handled very simply. The matching rules */ - /* are defined in the file `t1tokens.h' through the use of several */ - /* macros calls PARSE_XXX. This file is included twice here; the first */ - /* time to generate parsing callback functions, the second time to */ - /* generate a table of keywords (with pointers to the associated */ - /* callback functions). */ - /* */ - /* The function `parse_dict' simply scans *linearly* a given dictionary */ - /* (either the top-level or private one) and calls the appropriate */ - /* callback when it encounters an immediate keyword. */ - /* */ - /* This is by far the fastest way one can find to parse and read all */ - /* data. */ - /* */ - /* This led to tremendous code size reduction. Note that later, the */ - /* glyph loader will also be _greatly_ simplified, and the automatic */ - /* hinter will replace the clumsy `t1hinter'. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_CONFIG_CONFIG_H -#include FT_MULTIPLE_MASTERS_H -#include FT_INTERNAL_TYPE1_TYPES_H -#include FT_INTERNAL_CALC_H - -#include "t1load.h" -#include "t1errors.h" - - -#ifdef FT_CONFIG_OPTION_INCREMENTAL -#define IS_INCREMENTAL (FT_Bool)( face->root.internal->incremental_interface != 0 ) -#else -#define IS_INCREMENTAL 0 -#endif - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1load - - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** MULTIPLE MASTERS SUPPORT *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static FT_Error - t1_allocate_blend( T1_Face face, - FT_UInt num_designs, - FT_UInt num_axis ) - { - PS_Blend blend; - FT_Memory memory = face->root.memory; - FT_Error error = FT_Err_Ok; - - - blend = face->blend; - if ( !blend ) - { - if ( FT_NEW( blend ) ) - goto Exit; - - blend->num_default_design_vector = 0; - - face->blend = blend; - } - - /* allocate design data if needed */ - if ( num_designs > 0 ) - { - if ( blend->num_designs == 0 ) - { - FT_UInt nn; - - - /* allocate the blend `private' and `font_info' dictionaries */ - if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || - FT_NEW_ARRAY( blend->privates [1], num_designs ) || - FT_NEW_ARRAY( blend->bboxes [1], num_designs ) || - FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) - goto Exit; - - blend->default_weight_vector = blend->weight_vector + num_designs; - - blend->font_infos[0] = &face->type1.font_info; - blend->privates [0] = &face->type1.private_dict; - blend->bboxes [0] = &face->type1.font_bbox; - - for ( nn = 2; nn <= num_designs; nn++ ) - { - blend->font_infos[nn] = blend->font_infos[nn - 1] + 1; - blend->privates [nn] = blend->privates [nn - 1] + 1; - blend->bboxes [nn] = blend->bboxes [nn - 1] + 1; - } - - blend->num_designs = num_designs; - } - else if ( blend->num_designs != num_designs ) - goto Fail; - } - - /* allocate axis data if needed */ - if ( num_axis > 0 ) - { - if ( blend->num_axis != 0 && blend->num_axis != num_axis ) - goto Fail; - - blend->num_axis = num_axis; - } - - /* allocate the blend design pos table if needed */ - num_designs = blend->num_designs; - num_axis = blend->num_axis; - if ( num_designs && num_axis && blend->design_pos[0] == 0 ) - { - FT_UInt n; - - - if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) ) - goto Exit; - - for ( n = 1; n < num_designs; n++ ) - blend->design_pos[n] = blend->design_pos[0] + num_axis * n; - } - - Exit: - return error; - - Fail: - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Get_Multi_Master( T1_Face face, - FT_Multi_Master* master ) - { - PS_Blend blend = face->blend; - FT_UInt n; - FT_Error error; - - - error = FT_THROW( Invalid_Argument ); - - if ( blend ) - { - master->num_axis = blend->num_axis; - master->num_designs = blend->num_designs; - - for ( n = 0; n < blend->num_axis; n++ ) - { - FT_MM_Axis* axis = master->axis + n; - PS_DesignMap map = blend->design_map + n; - - - axis->name = blend->axis_names[n]; - axis->minimum = map->design_points[0]; - axis->maximum = map->design_points[map->num_points - 1]; - } - - error = FT_Err_Ok; - } - - return error; - } - - - /*************************************************************************/ - /* */ - /* Given a normalized (blend) coordinate, figure out the design */ - /* coordinate appropriate for that value. */ - /* */ - static FT_Fixed - mm_axis_unmap( PS_DesignMap axismap, - FT_Fixed ncv ) - { - int j; - - - if ( ncv <= axismap->blend_points[0] ) - return INT_TO_FIXED( axismap->design_points[0] ); - - for ( j = 1; j < axismap->num_points; ++j ) - { - if ( ncv <= axismap->blend_points[j] ) - return INT_TO_FIXED( axismap->design_points[j - 1] ) + - ( axismap->design_points[j] - axismap->design_points[j - 1] ) * - FT_DivFix( ncv - axismap->blend_points[j - 1], - axismap->blend_points[j] - - axismap->blend_points[j - 1] ); - } - - return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); - } - - - /*************************************************************************/ - /* */ - /* Given a vector of weights, one for each design, figure out the */ - /* normalized axis coordinates which gave rise to those weights. */ - /* */ - static void - mm_weights_unmap( FT_Fixed* weights, - FT_Fixed* axiscoords, - FT_UInt axis_count ) - { - FT_ASSERT( axis_count <= T1_MAX_MM_AXIS ); - - if ( axis_count == 1 ) - axiscoords[0] = weights[1]; - - else if ( axis_count == 2 ) - { - axiscoords[0] = weights[3] + weights[1]; - axiscoords[1] = weights[3] + weights[2]; - } - - else if ( axis_count == 3 ) - { - axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1]; - axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2]; - axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4]; - } - - else - { - axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] + - weights[7] + weights[5] + weights[3] + weights[1]; - axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] + - weights[7] + weights[6] + weights[3] + weights[2]; - axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] + - weights[7] + weights[6] + weights[5] + weights[4]; - axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] + - weights[11] + weights[10] + weights[9] + weights[8]; - } - } - - - /*************************************************************************/ - /* */ - /* Just a wrapper around T1_Get_Multi_Master to support the different */ - /* arguments needed by the GX var distortable fonts. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Var( T1_Face face, - FT_MM_Var* *master ) - { - FT_Memory memory = face->root.memory; - FT_MM_Var *mmvar = NULL; - FT_Multi_Master mmaster; - FT_Error error; - FT_UInt i; - FT_Fixed axiscoords[T1_MAX_MM_AXIS]; - PS_Blend blend = face->blend; - - - error = T1_Get_Multi_Master( face, &mmaster ); - if ( error ) - goto Exit; - if ( FT_ALLOC( mmvar, - sizeof ( FT_MM_Var ) + - mmaster.num_axis * sizeof ( FT_Var_Axis ) ) ) - goto Exit; - - mmvar->num_axis = mmaster.num_axis; - mmvar->num_designs = mmaster.num_designs; - mmvar->num_namedstyles = ~0U; /* Does not apply */ - mmvar->axis = (FT_Var_Axis*)&mmvar[1]; - /* Point to axes after MM_Var struct */ - mmvar->namedstyle = NULL; - - for ( i = 0 ; i < mmaster.num_axis; ++i ) - { - mmvar->axis[i].name = mmaster.axis[i].name; - mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum); - mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum); - mmvar->axis[i].def = ( mmvar->axis[i].minimum + - mmvar->axis[i].maximum ) / 2; - /* Does not apply. But this value is in range */ - mmvar->axis[i].strid = ~0U; /* Does not apply */ - mmvar->axis[i].tag = ~0U; /* Does not apply */ - - if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 ) - mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' ); - else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 ) - mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); - else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) - mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); - } - - if ( blend->num_designs == ( 1U << blend->num_axis ) ) - { - mm_weights_unmap( blend->default_weight_vector, - axiscoords, - blend->num_axis ); - - for ( i = 0; i < mmaster.num_axis; ++i ) - mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i], - axiscoords[i] ); - } - - *master = mmvar; - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Blend( T1_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - PS_Blend blend = face->blend; - FT_UInt n, m; - - - if ( !blend ) - return FT_THROW( Invalid_Argument ); - - if ( num_coords > blend->num_axis ) - num_coords = blend->num_axis; - - /* recompute the weight vector from the blend coordinates */ - for ( n = 0; n < blend->num_designs; n++ ) - { - FT_Fixed result = 0x10000L; /* 1.0 fixed */ - - - for ( m = 0; m < blend->num_axis; m++ ) - { - FT_Fixed factor; - - - /* get current blend axis position; */ - /* use a default value if we don't have a coordinate */ - factor = m < num_coords ? coords[m] : 0x8000; - if ( factor < 0 ) - factor = 0; - if ( factor > 0x10000L ) - factor = 0x10000L; - - if ( ( n & ( 1 << m ) ) == 0 ) - factor = 0x10000L - factor; - - result = FT_MulFix( result, factor ); - } - blend->weight_vector[n] = result; - } - - return FT_Err_Ok; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Design( T1_Face face, - FT_UInt num_coords, - FT_Long* coords ) - { - PS_Blend blend = face->blend; - FT_UInt n, p; - FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; - - - if ( !blend ) - return FT_THROW( Invalid_Argument ); - - if ( num_coords > blend->num_axis ) - num_coords = blend->num_axis; - - /* compute the blend coordinates through the blend design map */ - - for ( n = 0; n < blend->num_axis; n++ ) - { - FT_Long design; - FT_Fixed the_blend; - PS_DesignMap map = blend->design_map + n; - FT_Long* designs = map->design_points; - FT_Fixed* blends = map->blend_points; - FT_Int before = -1, after = -1; - - - /* use a default value if we don't have a coordinate */ - if ( n < num_coords ) - design = coords[n]; - else - design = ( designs[map->num_points - 1] - designs[0] ) / 2; - - for ( p = 0; p < (FT_UInt)map->num_points; p++ ) - { - FT_Long p_design = designs[p]; - - - /* exact match? */ - if ( design == p_design ) - { - the_blend = blends[p]; - goto Found; - } - - if ( design < p_design ) - { - after = (FT_Int)p; - break; - } - - before = (FT_Int)p; - } - - /* now interpolate if necessary */ - if ( before < 0 ) - the_blend = blends[0]; - - else if ( after < 0 ) - the_blend = blends[map->num_points - 1]; - - else - the_blend = FT_MulDiv( design - designs[before], - blends [after] - blends [before], - designs[after] - designs[before] ); - - Found: - final_blends[n] = the_blend; - } - - return T1_Set_MM_Blend( face, blend->num_axis, final_blends ); - } - - - /*************************************************************************/ - /* */ - /* Just a wrapper around T1_Set_MM_Design to support the different */ - /* arguments needed by the GX var distortable fonts. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - T1_Set_Var_Design( T1_Face face, - FT_UInt num_coords, - FT_Fixed* coords ) - { - FT_Long lcoords[T1_MAX_MM_AXIS]; - FT_UInt i; - - - if ( num_coords > T1_MAX_MM_AXIS ) - num_coords = T1_MAX_MM_AXIS; - - for ( i = 0; i < num_coords; ++i ) - lcoords[i] = FIXED_TO_INT( coords[i] ); - - return T1_Set_MM_Design( face, num_coords, lcoords ); - } - - - FT_LOCAL_DEF( void ) - T1_Done_Blend( T1_Face face ) - { - FT_Memory memory = face->root.memory; - PS_Blend blend = face->blend; - - - if ( blend ) - { - FT_UInt num_designs = blend->num_designs; - FT_UInt num_axis = blend->num_axis; - FT_UInt n; - - - /* release design pos table */ - FT_FREE( blend->design_pos[0] ); - for ( n = 1; n < num_designs; n++ ) - blend->design_pos[n] = NULL; - - /* release blend `private' and `font info' dictionaries */ - FT_FREE( blend->privates[1] ); - FT_FREE( blend->font_infos[1] ); - FT_FREE( blend->bboxes[1] ); - - for ( n = 0; n < num_designs; n++ ) - { - blend->privates [n] = NULL; - blend->font_infos[n] = NULL; - blend->bboxes [n] = NULL; - } - - /* release weight vectors */ - FT_FREE( blend->weight_vector ); - blend->default_weight_vector = NULL; - - /* release axis names */ - for ( n = 0; n < num_axis; n++ ) - FT_FREE( blend->axis_names[n] ); - - /* release design map */ - for ( n = 0; n < num_axis; n++ ) - { - PS_DesignMap dmap = blend->design_map + n; - - - FT_FREE( dmap->design_points ); - dmap->num_points = 0; - } - - FT_FREE( face->blend ); - } - } - - - static void - parse_blend_axis_types( T1_Face face, - T1_Loader loader ) - { - T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; - FT_Int n, num_axis; - FT_Error error = FT_Err_Ok; - PS_Blend blend; - FT_Memory memory; - - - /* take an array of objects */ - T1_ToTokenArray( &loader->parser, axis_tokens, - T1_MAX_MM_AXIS, &num_axis ); - if ( num_axis < 0 ) - { - error = FT_ERR( Ignore ); - goto Exit; - } - if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) - { - FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", - num_axis )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* allocate blend if necessary */ - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); - if ( error ) - goto Exit; - - blend = face->blend; - memory = face->root.memory; - - /* each token is an immediate containing the name of the axis */ - for ( n = 0; n < num_axis; n++ ) - { - T1_Token token = axis_tokens + n; - FT_Byte* name; - FT_UInt len; - - - /* skip first slash, if any */ - if ( token->start[0] == '/' ) - token->start++; - - len = (FT_UInt)( token->limit - token->start ); - if ( len == 0 ) - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - name = (FT_Byte*)blend->axis_names[n]; - if ( name ) - { - FT_TRACE0(( "parse_blend_axis_types:" - " overwriting axis name `%s' with `%*.s'\n", - name, len, token->start )); - FT_FREE( name ); - } - - if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) - goto Exit; - - name = (FT_Byte*)blend->axis_names[n]; - FT_MEM_COPY( name, token->start, len ); - name[len] = '\0'; - } - - Exit: - loader->parser.root.error = error; - } - - - static void - parse_blend_design_positions( T1_Face face, - T1_Loader loader ) - { - T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; - FT_Int num_designs; - FT_Int num_axis; - T1_Parser parser = &loader->parser; - - FT_Error error = FT_Err_Ok; - PS_Blend blend; - - - /* get the array of design tokens -- compute number of designs */ - T1_ToTokenArray( parser, design_tokens, - T1_MAX_MM_DESIGNS, &num_designs ); - if ( num_designs < 0 ) - { - error = FT_ERR( Ignore ); - goto Exit; - } - if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) - { - FT_ERROR(( "parse_blend_design_positions:" - " incorrect number of designs: %d\n", - num_designs )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - { - FT_Byte* old_cursor = parser->root.cursor; - FT_Byte* old_limit = parser->root.limit; - FT_Int n; - - - blend = face->blend; - num_axis = 0; /* make compiler happy */ - - for ( n = 0; n < num_designs; n++ ) - { - T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; - T1_Token token; - FT_Int axis, n_axis; - - - /* read axis/coordinates tokens */ - token = design_tokens + n; - parser->root.cursor = token->start; - parser->root.limit = token->limit; - T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis ); - - if ( n == 0 ) - { - if ( n_axis <= 0 || n_axis > T1_MAX_MM_AXIS ) - { - FT_ERROR(( "parse_blend_design_positions:" - " invalid number of axes: %d\n", - n_axis )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - num_axis = n_axis; - error = t1_allocate_blend( face, - (FT_UInt)num_designs, - (FT_UInt)num_axis ); - if ( error ) - goto Exit; - blend = face->blend; - } - else if ( n_axis != num_axis ) - { - FT_ERROR(( "parse_blend_design_positions: incorrect table\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* now read each axis token into the design position */ - for ( axis = 0; axis < n_axis; axis++ ) - { - T1_Token token2 = axis_tokens + axis; - - - parser->root.cursor = token2->start; - parser->root.limit = token2->limit; - blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); - } - } - - loader->parser.root.cursor = old_cursor; - loader->parser.root.limit = old_limit; - } - - Exit: - loader->parser.root.error = error; - } - - - static void - parse_blend_design_map( T1_Face face, - T1_Loader loader ) - { - FT_Error error = FT_Err_Ok; - T1_Parser parser = &loader->parser; - PS_Blend blend; - T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; - FT_Int n, num_axis; - FT_Byte* old_cursor; - FT_Byte* old_limit; - FT_Memory memory = face->root.memory; - - - T1_ToTokenArray( parser, axis_tokens, - T1_MAX_MM_AXIS, &num_axis ); - if ( num_axis < 0 ) - { - error = FT_ERR( Ignore ); - goto Exit; - } - if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) - { - FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", - num_axis )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - old_cursor = parser->root.cursor; - old_limit = parser->root.limit; - - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); - if ( error ) - goto Exit; - blend = face->blend; - - /* now read each axis design map */ - for ( n = 0; n < num_axis; n++ ) - { - PS_DesignMap map = blend->design_map + n; - T1_Token axis_token; - T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS]; - FT_Int p, num_points; - - - axis_token = axis_tokens + n; - - parser->root.cursor = axis_token->start; - parser->root.limit = axis_token->limit; - T1_ToTokenArray( parser, point_tokens, - T1_MAX_MM_MAP_POINTS, &num_points ); - - if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) - { - FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( map->design_points ) - { - FT_ERROR(( "parse_blend_design_map: duplicate table\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - /* allocate design map data */ - if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) - goto Exit; - map->blend_points = map->design_points + num_points; - map->num_points = (FT_Byte)num_points; - - for ( p = 0; p < num_points; p++ ) - { - T1_Token point_token; - - - point_token = point_tokens + p; - - /* don't include delimiting brackets */ - parser->root.cursor = point_token->start + 1; - parser->root.limit = point_token->limit - 1; - - map->design_points[p] = T1_ToInt( parser ); - map->blend_points [p] = T1_ToFixed( parser, 0 ); - } - } - - parser->root.cursor = old_cursor; - parser->root.limit = old_limit; - - Exit: - parser->root.error = error; - } - - - static void - parse_weight_vector( T1_Face face, - T1_Loader loader ) - { - T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; - FT_Int num_designs; - FT_Error error = FT_Err_Ok; - T1_Parser parser = &loader->parser; - PS_Blend blend = face->blend; - T1_Token token; - FT_Int n; - FT_Byte* old_cursor; - FT_Byte* old_limit; - - - T1_ToTokenArray( parser, design_tokens, - T1_MAX_MM_DESIGNS, &num_designs ); - if ( num_designs < 0 ) - { - error = FT_ERR( Ignore ); - goto Exit; - } - if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) - { - FT_ERROR(( "parse_weight_vector:" - " incorrect number of designs: %d\n", - num_designs )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( !blend || !blend->num_designs ) - { - error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 ); - if ( error ) - goto Exit; - blend = face->blend; - } - else if ( blend->num_designs != (FT_UInt)num_designs ) - { - FT_ERROR(( "parse_weight_vector:" - " /BlendDesignPosition and /WeightVector have\n" - " " - " different number of elements\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - old_cursor = parser->root.cursor; - old_limit = parser->root.limit; - - for ( n = 0; n < num_designs; n++ ) - { - token = design_tokens + n; - parser->root.cursor = token->start; - parser->root.limit = token->limit; - - blend->default_weight_vector[n] = - blend->weight_vector[n] = T1_ToFixed( parser, 0 ); - } - - parser->root.cursor = old_cursor; - parser->root.limit = old_limit; - - Exit: - parser->root.error = error; - } - - - /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ - /* we're only interested in the number of array elements */ - static void - parse_buildchar( T1_Face face, - T1_Loader loader ) - { - face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, - 0, NULL, 0 ); - return; - } - - -#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ - - - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** TYPE 1 SYMBOL PARSING *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - static FT_Error - t1_load_keyword( T1_Face face, - T1_Loader loader, - const T1_Field field ) - { - FT_Error error; - void* dummy_object; - void** objects; - FT_UInt max_objects; - PS_Blend blend = face->blend; - - - if ( blend && blend->num_designs == 0 ) - blend = NULL; - - /* if the keyword has a dedicated callback, call it */ - if ( field->type == T1_FIELD_TYPE_CALLBACK ) - { - field->reader( (FT_Face)face, loader ); - error = loader->parser.root.error; - goto Exit; - } - - /* now, the keyword is either a simple field, or a table of fields; */ - /* we are now going to take care of it */ - switch ( field->location ) - { - case T1_FIELD_LOCATION_FONT_INFO: - dummy_object = &face->type1.font_info; - objects = &dummy_object; - max_objects = 0; - - if ( blend ) - { - objects = (void**)blend->font_infos; - max_objects = blend->num_designs; - } - break; - - case T1_FIELD_LOCATION_FONT_EXTRA: - dummy_object = &face->type1.font_extra; - objects = &dummy_object; - max_objects = 0; - break; - - case T1_FIELD_LOCATION_PRIVATE: - dummy_object = &face->type1.private_dict; - objects = &dummy_object; - max_objects = 0; - - if ( blend ) - { - objects = (void**)blend->privates; - max_objects = blend->num_designs; - } - break; - - case T1_FIELD_LOCATION_BBOX: - dummy_object = &face->type1.font_bbox; - objects = &dummy_object; - max_objects = 0; - - if ( blend ) - { - objects = (void**)blend->bboxes; - max_objects = blend->num_designs; - } - break; - - case T1_FIELD_LOCATION_LOADER: - dummy_object = loader; - objects = &dummy_object; - max_objects = 0; - break; - - case T1_FIELD_LOCATION_FACE: - dummy_object = face; - objects = &dummy_object; - max_objects = 0; - break; - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - case T1_FIELD_LOCATION_BLEND: - dummy_object = face->blend; - objects = &dummy_object; - max_objects = 0; - break; -#endif - - default: - dummy_object = &face->type1; - objects = &dummy_object; - max_objects = 0; - } - - if ( *objects ) - { - if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || - field->type == T1_FIELD_TYPE_FIXED_ARRAY ) - error = T1_Load_Field_Table( &loader->parser, field, - objects, max_objects, 0 ); - else - error = T1_Load_Field( &loader->parser, field, - objects, max_objects, 0 ); - } - else - { - FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'" - " which is not valid at this point\n" - " (probably due to missing keywords)\n", - field->ident )); - error = FT_Err_Ok; - } - - Exit: - return error; - } - - - static void - parse_private( T1_Face face, - T1_Loader loader ) - { - FT_UNUSED( face ); - - loader->keywords_encountered |= T1_PRIVATE; - } - - - /* return 1 in case of success */ - - static int - read_binary_data( T1_Parser parser, - FT_ULong* size, - FT_Byte** base, - FT_Bool incremental ) - { - FT_Byte* cur; - FT_Byte* limit = parser->root.limit; - - - /* the binary data has one of the following formats */ - /* */ - /* `size' [white*] RD white ....... ND */ - /* `size' [white*] -| white ....... |- */ - /* */ - - T1_Skip_Spaces( parser ); - - cur = parser->root.cursor; - - if ( cur < limit && ft_isdigit( *cur ) ) - { - FT_Long s = T1_ToInt( parser ); - - - T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */ - - /* there is only one whitespace char after the */ - /* `RD' or `-|' token */ - *base = parser->root.cursor + 1; - - if ( s >= 0 && s < limit - *base ) - { - parser->root.cursor += s + 1; - *size = (FT_ULong)s; - return !parser->root.error; - } - } - - if( !incremental ) - { - FT_ERROR(( "read_binary_data: invalid size field\n" )); - parser->root.error = FT_THROW( Invalid_File_Format ); - } - - return 0; - } - - - /* We now define the routines to handle the `/Encoding', `/Subrs', */ - /* and `/CharStrings' dictionaries. */ - - static void - t1_parse_font_matrix( T1_Face face, - T1_Loader loader ) - { - T1_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; - FT_Face root = (FT_Face)&face->root; - FT_Fixed temp[6]; - FT_Fixed temp_scale; - FT_Int result; - - - /* input is scaled by 1000 to accommodate default FontMatrix */ - result = T1_ToFixedArray( parser, 6, temp, 3 ); - - if ( result < 6 ) - { - parser->root.error = FT_THROW( Invalid_File_Format ); - return; - } - - temp_scale = FT_ABS( temp[3] ); - - if ( temp_scale == 0 ) - { - FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" )); - parser->root.error = FT_THROW( Invalid_File_Format ); - return; - } - - /* atypical case */ - if ( temp_scale != 0x10000L ) - { - /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); - - temp[0] = FT_DivFix( temp[0], temp_scale ); - temp[1] = FT_DivFix( temp[1], temp_scale ); - temp[2] = FT_DivFix( temp[2], temp_scale ); - temp[4] = FT_DivFix( temp[4], temp_scale ); - temp[5] = FT_DivFix( temp[5], temp_scale ); - temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L; - } - - matrix->xx = temp[0]; - matrix->yx = temp[1]; - matrix->xy = temp[2]; - matrix->yy = temp[3]; - - /* note that the offsets must be expressed in integer font units */ - offset->x = temp[4] >> 16; - offset->y = temp[5] >> 16; - } - - - static void - parse_encoding( T1_Face face, - T1_Loader loader ) - { - T1_Parser parser = &loader->parser; - FT_Byte* cur; - FT_Byte* limit = parser->root.limit; - - PSAux_Service psaux = (PSAux_Service)face->psaux; - - - T1_Skip_Spaces( parser ); - cur = parser->root.cursor; - if ( cur >= limit ) - { - FT_ERROR(( "parse_encoding: out of bounds\n" )); - parser->root.error = FT_THROW( Invalid_File_Format ); - return; - } - - /* if we have a number or `[', the encoding is an array, */ - /* and we must load it now */ - if ( ft_isdigit( *cur ) || *cur == '[' ) - { - T1_Encoding encode = &face->type1.encoding; - FT_Int count, n; - PS_Table char_table = &loader->encoding_table; - FT_Memory memory = parser->root.memory; - FT_Error error; - FT_Bool only_immediates = 0; - - - /* read the number of entries in the encoding; should be 256 */ - if ( *cur == '[' ) - { - count = 256; - only_immediates = 1; - parser->root.cursor++; - } - else - count = (FT_Int)T1_ToInt( parser ); - - /* only composite fonts (which we don't support) */ - /* can have larger values */ - if ( count > 256 ) - { - FT_ERROR(( "parse_encoding: invalid encoding array size\n" )); - parser->root.error = FT_THROW( Invalid_File_Format ); - return; - } - - T1_Skip_Spaces( parser ); - if ( parser->root.cursor >= limit ) - return; - - /* PostScript happily allows overwriting of encoding arrays */ - if ( encode->char_index ) - { - FT_FREE( encode->char_index ); - FT_FREE( encode->char_name ); - T1_Release_Table( char_table ); - } - - /* we use a T1_Table to store our charnames */ - loader->num_chars = encode->num_chars = count; - if ( FT_NEW_ARRAY( encode->char_index, count ) || - FT_NEW_ARRAY( encode->char_name, count ) || - FT_SET_ERROR( psaux->ps_table_funcs->init( - char_table, count, memory ) ) ) - { - parser->root.error = error; - return; - } - - /* We need to `zero' out encoding_table.elements */ - for ( n = 0; n < count; n++ ) - { - char* notdef = (char *)".notdef"; - - - (void)T1_Add_Table( char_table, n, notdef, 8 ); - } - - /* Now we need to read records of the form */ - /* */ - /* ... charcode /charname ... */ - /* */ - /* for each entry in our table. */ - /* */ - /* We simply look for a number followed by an immediate */ - /* name. Note that this ignores correctly the sequence */ - /* that is often seen in type1 fonts: */ - /* */ - /* 0 1 255 { 1 index exch /.notdef put } for dup */ - /* */ - /* used to clean the encoding array before anything else. */ - /* */ - /* Alternatively, if the array is directly given as */ - /* */ - /* /Encoding [ ... ] */ - /* */ - /* we only read immediates. */ - - n = 0; - T1_Skip_Spaces( parser ); - - while ( parser->root.cursor < limit ) - { - cur = parser->root.cursor; - - /* we stop when we encounter a `def' or `]' */ - if ( *cur == 'd' && cur + 3 < limit ) - { - if ( cur[1] == 'e' && - cur[2] == 'f' && - IS_PS_DELIM( cur[3] ) ) - { - FT_TRACE6(( "encoding end\n" )); - cur += 3; - break; - } - } - if ( *cur == ']' ) - { - FT_TRACE6(( "encoding end\n" )); - cur++; - break; - } - - /* check whether we've found an entry */ - if ( ft_isdigit( *cur ) || only_immediates ) - { - FT_Int charcode; - - - if ( only_immediates ) - charcode = n; - else - { - charcode = (FT_Int)T1_ToInt( parser ); - T1_Skip_Spaces( parser ); - - /* protect against invalid charcode */ - if ( cur == parser->root.cursor ) - { - parser->root.error = FT_THROW( Unknown_File_Format ); - return; - } - } - - cur = parser->root.cursor; - - if ( cur + 2 < limit && *cur == '/' && n < count ) - { - FT_UInt len; - - - cur++; - - parser->root.cursor = cur; - T1_Skip_PS_Token( parser ); - if ( parser->root.cursor >= limit ) - return; - if ( parser->root.error ) - return; - - len = (FT_UInt)( parser->root.cursor - cur ); - - parser->root.error = T1_Add_Table( char_table, charcode, - cur, len + 1 ); - if ( parser->root.error ) - return; - char_table->elements[charcode][len] = '\0'; - - n++; - } - else if ( only_immediates ) - { - /* Since the current position is not updated for */ - /* immediates-only mode we would get an infinite loop if */ - /* we don't do anything here. */ - /* */ - /* This encoding array is not valid according to the type1 */ - /* specification (it might be an encoding for a CID type1 */ - /* font, however), so we conclude that this font is NOT a */ - /* type1 font. */ - parser->root.error = FT_THROW( Unknown_File_Format ); - return; - } - } - else - { - T1_Skip_PS_Token( parser ); - if ( parser->root.error ) - return; - } - - T1_Skip_Spaces( parser ); - } - - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; - parser->root.cursor = cur; - } - - /* Otherwise, we should have either `StandardEncoding', */ - /* `ExpertEncoding', or `ISOLatin1Encoding' */ - else - { - if ( cur + 17 < limit && - ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; - - else if ( cur + 15 < limit && - ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; - - else if ( cur + 18 < limit && - ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; - - else - parser->root.error = FT_ERR( Ignore ); - } - } - - - static void - parse_subrs( T1_Face face, - T1_Loader loader ) - { - T1_Parser parser = &loader->parser; - PS_Table table = &loader->subrs; - FT_Memory memory = parser->root.memory; - FT_Error error; - FT_Int num_subrs; - - PSAux_Service psaux = (PSAux_Service)face->psaux; - - - T1_Skip_Spaces( parser ); - - /* test for empty array */ - if ( parser->root.cursor < parser->root.limit && - *parser->root.cursor == '[' ) - { - T1_Skip_PS_Token( parser ); - T1_Skip_Spaces ( parser ); - if ( parser->root.cursor >= parser->root.limit || - *parser->root.cursor != ']' ) - parser->root.error = FT_THROW( Invalid_File_Format ); - return; - } - - num_subrs = (FT_Int)T1_ToInt( parser ); - - /* position the parser right before the `dup' of the first subr */ - T1_Skip_PS_Token( parser ); /* `array' */ - if ( parser->root.error ) - return; - T1_Skip_Spaces( parser ); - - /* initialize subrs array -- with synthetic fonts it is possible */ - /* we get here twice */ - if ( !loader->num_subrs ) - { - error = psaux->ps_table_funcs->init( table, num_subrs, memory ); - if ( error ) - goto Fail; - } - - /* the format is simple: */ - /* */ - /* `index' + binary data */ - /* */ - for (;;) - { - FT_Long idx; - FT_ULong size; - FT_Byte* base; - - - /* If we are out of data, or if the next token isn't `dup', */ - /* we are done. */ - if ( parser->root.cursor + 4 >= parser->root.limit || - ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 ) - break; - - T1_Skip_PS_Token( parser ); /* `dup' */ - - idx = T1_ToInt( parser ); - - if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) ) - return; - - /* The binary string is followed by one token, e.g. `NP' */ - /* (bound to `noaccess put') or by two separate tokens: */ - /* `noaccess' & `put'. We position the parser right */ - /* before the next `dup', if any. */ - T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */ - if ( parser->root.error ) - return; - T1_Skip_Spaces ( parser ); - - if ( parser->root.cursor + 4 < parser->root.limit && - ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 ) - { - T1_Skip_PS_Token( parser ); /* skip `put' */ - T1_Skip_Spaces ( parser ); - } - - /* with synthetic fonts it is possible we get here twice */ - if ( loader->num_subrs ) - continue; - - /* some fonts use a value of -1 for lenIV to indicate that */ - /* the charstrings are unencoded */ - /* */ - /* thanks to Tom Kacvinsky for pointing this out */ - /* */ - if ( face->type1.private_dict.lenIV >= 0 ) - { - FT_Byte* temp; - - - /* some fonts define empty subr records -- this is not totally */ - /* compliant to the specification (which says they should at */ - /* least contain a `return'), but we support them anyway */ - if ( size < (FT_ULong)face->type1.private_dict.lenIV ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_ALLOC( temp, size ) ) - goto Fail; - FT_MEM_COPY( temp, base, size ); - psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( table, (FT_Int)idx, - temp + face->type1.private_dict.lenIV, size ); - FT_FREE( temp ); - } - else - error = T1_Add_Table( table, (FT_Int)idx, base, size ); - if ( error ) - goto Fail; - } - - if ( !loader->num_subrs ) - loader->num_subrs = num_subrs; - - return; - - Fail: - parser->root.error = error; - } - - -#define TABLE_EXTEND 5 - - - static void - parse_charstrings( T1_Face face, - T1_Loader loader ) - { - T1_Parser parser = &loader->parser; - PS_Table code_table = &loader->charstrings; - PS_Table name_table = &loader->glyph_names; - PS_Table swap_table = &loader->swap_table; - FT_Memory memory = parser->root.memory; - FT_Error error; - - PSAux_Service psaux = (PSAux_Service)face->psaux; - - FT_Byte* cur = parser->root.cursor; - FT_Byte* limit = parser->root.limit; - FT_Int n, num_glyphs; - FT_Int notdef_index = 0; - FT_Byte notdef_found = 0; - - - num_glyphs = (FT_Int)T1_ToInt( parser ); - if ( num_glyphs < 0 ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - /* we certainly need more than 8 bytes per glyph */ - if ( num_glyphs > ( limit - cur ) >> 3 ) - { - FT_TRACE0(( "parse_charstrings: adjusting number of glyphs" - " (from %d to %d)\n", - num_glyphs, ( limit - cur ) >> 3 )); - num_glyphs = ( limit - cur ) >> 3; - } - - /* some fonts like Optima-Oblique not only define the /CharStrings */ - /* array but access it also */ - if ( num_glyphs == 0 || parser->root.error ) - return; - - /* initialize tables, leaving space for addition of .notdef, */ - /* if necessary, and a few other glyphs to handle buggy */ - /* fonts which have more glyphs than specified. */ - - /* for some non-standard fonts like `Optima' which provides */ - /* different outlines depending on the resolution it is */ - /* possible to get here twice */ - if ( !loader->num_glyphs ) - { - error = psaux->ps_table_funcs->init( - code_table, num_glyphs + 1 + TABLE_EXTEND, memory ); - if ( error ) - goto Fail; - - error = psaux->ps_table_funcs->init( - name_table, num_glyphs + 1 + TABLE_EXTEND, memory ); - if ( error ) - goto Fail; - - /* Initialize table for swapping index notdef_index and */ - /* index 0 names and codes (if necessary). */ - - error = psaux->ps_table_funcs->init( swap_table, 4, memory ); - if ( error ) - goto Fail; - } - - n = 0; - - for (;;) - { - FT_ULong size; - FT_Byte* base; - - - /* the format is simple: */ - /* `/glyphname' + binary data */ - - T1_Skip_Spaces( parser ); - - cur = parser->root.cursor; - if ( cur >= limit ) - break; - - /* we stop when we find a `def' or `end' keyword */ - if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) ) - { - if ( cur[0] == 'd' && - cur[1] == 'e' && - cur[2] == 'f' ) - { - /* There are fonts which have this: */ - /* */ - /* /CharStrings 118 dict def */ - /* Private begin */ - /* CharStrings begin */ - /* ... */ - /* */ - /* To catch this we ignore `def' if */ - /* no charstring has actually been */ - /* seen. */ - if ( n ) - break; - } - - if ( cur[0] == 'e' && - cur[1] == 'n' && - cur[2] == 'd' ) - break; - } - - T1_Skip_PS_Token( parser ); - if ( parser->root.cursor >= limit ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - if ( parser->root.error ) - return; - - if ( *cur == '/' ) - { - FT_UInt len; - - - if ( cur + 2 >= limit ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - cur++; /* skip `/' */ - len = (FT_UInt)( parser->root.cursor - cur ); - - if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) ) - return; - - /* for some non-standard fonts like `Optima' which provides */ - /* different outlines depending on the resolution it is */ - /* possible to get here twice */ - if ( loader->num_glyphs ) - continue; - - error = T1_Add_Table( name_table, n, cur, len + 1 ); - if ( error ) - goto Fail; - - /* add a trailing zero to the name table */ - name_table->elements[n][len] = '\0'; - - /* record index of /.notdef */ - if ( *cur == '.' && - ft_strcmp( ".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) - { - notdef_index = n; - notdef_found = 1; - } - - if ( face->type1.private_dict.lenIV >= 0 && - n < num_glyphs + TABLE_EXTEND ) - { - FT_Byte* temp; - - - if ( size <= (FT_ULong)face->type1.private_dict.lenIV ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_ALLOC( temp, size ) ) - goto Fail; - FT_MEM_COPY( temp, base, size ); - psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( code_table, n, - temp + face->type1.private_dict.lenIV, size ); - FT_FREE( temp ); - } - else - error = T1_Add_Table( code_table, n, base, size ); - if ( error ) - goto Fail; - - n++; - } - } - - loader->num_glyphs = n; - - /* if /.notdef is found but does not occupy index 0, do our magic. */ - if ( notdef_found && - ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) ) - { - /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ - /* name and code entries to swap_table. Then place notdef_index */ - /* name and code entries into swap_table. Then swap name and code */ - /* entries at indices notdef_index and 0 using values stored in */ - /* swap_table. */ - - /* Index 0 name */ - error = T1_Add_Table( swap_table, 0, - name_table->elements[0], - name_table->lengths [0] ); - if ( error ) - goto Fail; - - /* Index 0 code */ - error = T1_Add_Table( swap_table, 1, - code_table->elements[0], - code_table->lengths [0] ); - if ( error ) - goto Fail; - - /* Index notdef_index name */ - error = T1_Add_Table( swap_table, 2, - name_table->elements[notdef_index], - name_table->lengths [notdef_index] ); - if ( error ) - goto Fail; - - /* Index notdef_index code */ - error = T1_Add_Table( swap_table, 3, - code_table->elements[notdef_index], - code_table->lengths [notdef_index] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( name_table, notdef_index, - swap_table->elements[0], - swap_table->lengths [0] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( code_table, notdef_index, - swap_table->elements[1], - swap_table->lengths [1] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( name_table, 0, - swap_table->elements[2], - swap_table->lengths [2] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( code_table, 0, - swap_table->elements[3], - swap_table->lengths [3] ); - if ( error ) - goto Fail; - - } - else if ( !notdef_found ) - { - /* notdef_index is already 0, or /.notdef is undefined in */ - /* charstrings dictionary. Worry about /.notdef undefined. */ - /* We take index 0 and add it to the end of the table(s) */ - /* and add our own /.notdef glyph to index 0. */ - - /* 0 333 hsbw endchar */ - FT_Byte notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E }; - char* notdef_name = (char *)".notdef"; - - - error = T1_Add_Table( swap_table, 0, - name_table->elements[0], - name_table->lengths [0] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( swap_table, 1, - code_table->elements[0], - code_table->lengths [0] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( name_table, 0, notdef_name, 8 ); - if ( error ) - goto Fail; - - error = T1_Add_Table( code_table, 0, notdef_glyph, 5 ); - - if ( error ) - goto Fail; - - error = T1_Add_Table( name_table, n, - swap_table->elements[0], - swap_table->lengths [0] ); - if ( error ) - goto Fail; - - error = T1_Add_Table( code_table, n, - swap_table->elements[1], - swap_table->lengths [1] ); - if ( error ) - goto Fail; - - /* we added a glyph. */ - loader->num_glyphs += 1; - } - - return; - - Fail: - parser->root.error = error; - } - - - /*************************************************************************/ - /* */ - /* Define the token field static variables. This is a set of */ - /* T1_FieldRec variables. */ - /* */ - /*************************************************************************/ - - - static - const T1_FieldRec t1_keywords[] = - { - -#include "t1tokens.h" - - /* now add the special functions... */ - T1_FIELD_CALLBACK( "FontMatrix", t1_parse_font_matrix, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_CALLBACK( "Encoding", parse_encoding, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_CALLBACK( "Subrs", parse_subrs, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_CALLBACK( "CharStrings", parse_charstrings, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_CALLBACK( "Private", parse_private, - T1_FIELD_DICT_FONTDICT ) - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar, - T1_FIELD_DICT_PRIVATE ) -#endif - - { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } - }; - - - static FT_Error - parse_dict( T1_Face face, - T1_Loader loader, - FT_Byte* base, - FT_ULong size ) - { - T1_Parser parser = &loader->parser; - FT_Byte *limit, *start_binary = NULL; - FT_Bool have_integer = 0; - - - parser->root.cursor = base; - parser->root.limit = base + size; - parser->root.error = FT_Err_Ok; - - limit = parser->root.limit; - - T1_Skip_Spaces( parser ); - - while ( parser->root.cursor < limit ) - { - FT_Byte* cur; - - - cur = parser->root.cursor; - - /* look for `eexec' */ - if ( IS_PS_TOKEN( cur, limit, "eexec" ) ) - break; - - /* look for `closefile' which ends the eexec section */ - else if ( IS_PS_TOKEN( cur, limit, "closefile" ) ) - break; - - /* in a synthetic font the base font starts after a */ - /* `FontDictionary' token that is placed after a Private dict */ - else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) ) - { - if ( loader->keywords_encountered & T1_PRIVATE ) - loader->keywords_encountered |= - T1_FONTDIR_AFTER_PRIVATE; - parser->root.cursor += 13; - } - - /* check whether we have an integer */ - else if ( ft_isdigit( *cur ) ) - { - start_binary = cur; - T1_Skip_PS_Token( parser ); - if ( parser->root.error ) - goto Exit; - have_integer = 1; - } - - /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ - /* since those tokens are handled by parse_subrs and */ - /* parse_charstrings */ - else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && - have_integer ) - { - FT_ULong s; - FT_Byte* b; - - - parser->root.cursor = start_binary; - if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) ) - return FT_THROW( Invalid_File_Format ); - have_integer = 0; - } - - else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && - have_integer ) - { - FT_ULong s; - FT_Byte* b; - - - parser->root.cursor = start_binary; - if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) ) - return FT_THROW( Invalid_File_Format ); - have_integer = 0; - } - - /* look for immediates */ - else if ( *cur == '/' && cur + 2 < limit ) - { - FT_UInt len; - - - cur++; - - parser->root.cursor = cur; - T1_Skip_PS_Token( parser ); - if ( parser->root.error ) - goto Exit; - - len = (FT_UInt)( parser->root.cursor - cur ); - - if ( len > 0 && len < 22 && parser->root.cursor < limit ) - { - /* now compare the immediate name to the keyword table */ - T1_Field keyword = (T1_Field)t1_keywords; - - - for (;;) - { - FT_Byte* name; - - - name = (FT_Byte*)keyword->ident; - if ( !name ) - break; - - if ( cur[0] == name[0] && - len == ft_strlen( (const char *)name ) && - ft_memcmp( cur, name, len ) == 0 ) - { - /* We found it -- run the parsing callback! */ - /* We record every instance of every field */ - /* (until we reach the base font of a */ - /* synthetic font) to deal adequately with */ - /* multiple master fonts; this is also */ - /* necessary because later PostScript */ - /* definitions override earlier ones. */ - - /* Once we encounter `FontDirectory' after */ - /* `/Private', we know that this is a synthetic */ - /* font; except for `/CharStrings' we are not */ - /* interested in anything that follows this */ - /* `FontDirectory'. */ - - /* MM fonts have more than one /Private token at */ - /* the top level; let's hope that all the junk */ - /* that follows the first /Private token is not */ - /* interesting to us. */ - - /* According to Adobe Tech Note #5175 (CID-Keyed */ - /* Font Installation for ATM Software) a `begin' */ - /* must be followed by exactly one `end', and */ - /* `begin' -- `end' pairs must be accurately */ - /* paired. We could use this to distinguish */ - /* between the global Private and the Private */ - /* dict that is a member of the Blend dict. */ - - const FT_UInt dict = - ( loader->keywords_encountered & T1_PRIVATE ) - ? T1_FIELD_DICT_PRIVATE - : T1_FIELD_DICT_FONTDICT; - - if ( !( dict & keyword->dict ) ) - { - FT_TRACE1(( "parse_dict: found `%s' but ignoring it" - " since it is in the wrong dictionary\n", - keyword->ident )); - break; - } - - if ( !( loader->keywords_encountered & - T1_FONTDIR_AFTER_PRIVATE ) || - ft_strcmp( (const char*)name, "CharStrings" ) == 0 ) - { - parser->root.error = t1_load_keyword( face, - loader, - keyword ); - if ( parser->root.error != FT_Err_Ok ) - { - if ( FT_ERR_EQ( parser->root.error, Ignore ) ) - parser->root.error = FT_Err_Ok; - else - return parser->root.error; - } - } - break; - } - - keyword++; - } - } - - have_integer = 0; - } - else - { - T1_Skip_PS_Token( parser ); - if ( parser->root.error ) - goto Exit; - have_integer = 0; - } - - T1_Skip_Spaces( parser ); - } - - Exit: - return parser->root.error; - } - - - static void - t1_init_loader( T1_Loader loader, - T1_Face face ) - { - FT_UNUSED( face ); - - FT_MEM_ZERO( loader, sizeof ( *loader ) ); - loader->num_glyphs = 0; - loader->num_chars = 0; - - /* initialize the tables -- simply set their `init' field to 0 */ - loader->encoding_table.init = 0; - loader->charstrings.init = 0; - loader->glyph_names.init = 0; - loader->subrs.init = 0; - loader->swap_table.init = 0; - loader->fontdata = 0; - loader->keywords_encountered = 0; - } - - - static void - t1_done_loader( T1_Loader loader ) - { - T1_Parser parser = &loader->parser; - - - /* finalize tables */ - T1_Release_Table( &loader->encoding_table ); - T1_Release_Table( &loader->charstrings ); - T1_Release_Table( &loader->glyph_names ); - T1_Release_Table( &loader->swap_table ); - T1_Release_Table( &loader->subrs ); - - /* finalize parser */ - T1_Finalize_Parser( parser ); - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Open_Face( T1_Face face ) - { - T1_LoaderRec loader; - T1_Parser parser; - T1_Font type1 = &face->type1; - PS_Private priv = &type1->private_dict; - FT_Error error; - - PSAux_Service psaux = (PSAux_Service)face->psaux; - - - t1_init_loader( &loader, face ); - - /* default values */ - face->ndv_idx = -1; - face->cdv_idx = -1; - face->len_buildchar = 0; - - priv->blue_shift = 7; - priv->blue_fuzz = 1; - priv->lenIV = 4; - priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); - priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); - - parser = &loader.parser; - error = T1_New_Parser( parser, - face->root.stream, - face->root.memory, - psaux ); - if ( error ) - goto Exit; - - error = parse_dict( face, &loader, - parser->base_dict, parser->base_len ); - if ( error ) - goto Exit; - - error = T1_Get_Private_Dict( parser, psaux ); - if ( error ) - goto Exit; - - error = parse_dict( face, &loader, - parser->private_dict, parser->private_len ); - if ( error ) - goto Exit; - - /* ensure even-ness of `num_blue_values' */ - priv->num_blue_values &= ~1; - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - - if ( face->blend && - face->blend->num_default_design_vector != 0 && - face->blend->num_default_design_vector != face->blend->num_axis ) - { - /* we don't use it currently so just warn, reset, and ignore */ - FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries " - "while there are %u axes.\n", - face->blend->num_default_design_vector, - face->blend->num_axis )); - - face->blend->num_default_design_vector = 0; - } - - /* the following can happen for MM instances; we then treat the */ - /* font as a normal PS font */ - if ( face->blend && - ( !face->blend->num_designs || !face->blend->num_axis ) ) - T1_Done_Blend( face ); - - /* another safety check */ - if ( face->blend ) - { - FT_UInt i; - - - for ( i = 0; i < face->blend->num_axis; i++ ) - if ( !face->blend->design_map[i].num_points ) - { - T1_Done_Blend( face ); - break; - } - } - - if ( face->blend ) - { - if ( face->len_buildchar > 0 ) - { - FT_Memory memory = face->root.memory; - - - if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) ) - { - FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" )); - face->len_buildchar = 0; - goto Exit; - } - } - } - else - face->len_buildchar = 0; - -#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ - - /* now, propagate the subrs, charstrings, and glyphnames tables */ - /* to the Type1 data */ - type1->num_glyphs = loader.num_glyphs; - - if ( loader.subrs.init ) - { - loader.subrs.init = 0; - type1->num_subrs = loader.num_subrs; - type1->subrs_block = loader.subrs.block; - type1->subrs = loader.subrs.elements; - type1->subrs_len = loader.subrs.lengths; - } - - if ( !IS_INCREMENTAL ) - if ( !loader.charstrings.init ) - { - FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" )); - error = FT_THROW( Invalid_File_Format ); - } - - loader.charstrings.init = 0; - type1->charstrings_block = loader.charstrings.block; - type1->charstrings = loader.charstrings.elements; - type1->charstrings_len = loader.charstrings.lengths; - - /* we copy the glyph names `block' and `elements' fields; */ - /* the `lengths' field must be released later */ - type1->glyph_names_block = loader.glyph_names.block; - type1->glyph_names = (FT_String**)loader.glyph_names.elements; - loader.glyph_names.block = NULL; - loader.glyph_names.elements = NULL; - - /* we must now build type1.encoding when we have a custom array */ - if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) - { - FT_Int charcode, idx, min_char, max_char; - FT_Byte* glyph_name; - - - /* OK, we do the following: for each element in the encoding */ - /* table, look up the index of the glyph having the same name */ - /* the index is then stored in type1.encoding.char_index, and */ - /* the name to type1.encoding.char_name */ - - min_char = 0; - max_char = 0; - - charcode = 0; - for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) - { - FT_Byte* char_name; - - - type1->encoding.char_index[charcode] = 0; - type1->encoding.char_name [charcode] = (char *)".notdef"; - - char_name = loader.encoding_table.elements[charcode]; - if ( char_name ) - for ( idx = 0; idx < type1->num_glyphs; idx++ ) - { - glyph_name = (FT_Byte*)type1->glyph_names[idx]; - if ( ft_strcmp( (const char*)char_name, - (const char*)glyph_name ) == 0 ) - { - type1->encoding.char_index[charcode] = (FT_UShort)idx; - type1->encoding.char_name [charcode] = (char*)glyph_name; - - /* Change min/max encoded char only if glyph name is */ - /* not /.notdef */ - if ( ft_strcmp( (const char*)".notdef", - (const char*)glyph_name ) != 0 ) - { - if ( charcode < min_char ) - min_char = charcode; - if ( charcode >= max_char ) - max_char = charcode + 1; - } - break; - } - } - } - - type1->encoding.code_first = min_char; - type1->encoding.code_last = max_char; - type1->encoding.num_chars = loader.num_chars; - } - - Exit: - t1_done_loader( &loader ); - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/type1/t1load.h b/third_party/freetype/src/type1/t1load.h deleted file mode 100644 index de422e7ecd1c8873544926e920948c729bed75ec..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1load.h +++ /dev/null @@ -1,102 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1load.h */ -/* */ -/* Type 1 font loader (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1LOAD_H__ -#define __T1LOAD_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H -#include FT_MULTIPLE_MASTERS_H - -#include "t1parse.h" - - -FT_BEGIN_HEADER - - - typedef struct T1_Loader_ - { - T1_ParserRec parser; /* parser used to read the stream */ - - FT_Int num_chars; /* number of characters in encoding */ - PS_TableRec encoding_table; /* PS_Table used to store the */ - /* encoding character names */ - - FT_Int num_glyphs; - PS_TableRec glyph_names; - PS_TableRec charstrings; - PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */ - - FT_Int num_subrs; - PS_TableRec subrs; - FT_Bool fontdata; - - FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */ - - } T1_LoaderRec, *T1_Loader; - - - /* treatment of some keywords differs depending on whether */ - /* they precede or follow certain other keywords */ - -#define T1_PRIVATE ( 1 << 0 ) -#define T1_FONTDIR_AFTER_PRIVATE ( 1 << 1 ) - - - FT_LOCAL( FT_Error ) - T1_Open_Face( T1_Face face ); - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - - FT_LOCAL( FT_Error ) - T1_Get_Multi_Master( T1_Face face, - FT_Multi_Master* master ); - - FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Var( T1_Face face, - FT_MM_Var* *master ); - - FT_LOCAL( FT_Error ) - T1_Set_MM_Blend( T1_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - FT_LOCAL( FT_Error ) - T1_Set_MM_Design( T1_Face face, - FT_UInt num_coords, - FT_Long* coords ); - - FT_LOCAL_DEF( FT_Error ) - T1_Set_Var_Design( T1_Face face, - FT_UInt num_coords, - FT_Fixed* coords ); - - FT_LOCAL( void ) - T1_Done_Blend( T1_Face face ); - -#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ - - -FT_END_HEADER - -#endif /* __T1LOAD_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1objs.c b/third_party/freetype/src/type1/t1objs.c deleted file mode 100644 index d921063eaa4af8b1976e452acabaa76aeb8008a7..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1objs.c +++ /dev/null @@ -1,613 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1objs.c */ -/* */ -/* Type 1 objects manager (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_CALC_H -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_TRUETYPE_IDS_H - -#include "t1gload.h" -#include "t1load.h" - -#include "t1errors.h" - -#ifndef T1_CONFIG_OPTION_NO_AFM -#include "t1afm.h" -#endif - -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1objs - - - /*************************************************************************/ - /* */ - /* SIZE FUNCTIONS */ - /* */ - /* note that we store the global hints in the size's "internal" root */ - /* field */ - /* */ - /*************************************************************************/ - - - static PSH_Globals_Funcs - T1_Size_Get_Globals_Funcs( T1_Size size ) - { - T1_Face face = (T1_Face)size->root.face; - PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; - FT_Module module; - - - module = FT_Get_Module( size->root.face->driver->root.library, - "pshinter" ); - return ( module && pshinter && pshinter->get_globals_funcs ) - ? pshinter->get_globals_funcs( module ) - : 0 ; - } - - - FT_LOCAL_DEF( void ) - T1_Size_Done( FT_Size t1size ) /* T1_Size */ - { - T1_Size size = (T1_Size)t1size; - - - if ( size->root.internal ) - { - PSH_Globals_Funcs funcs; - - - funcs = T1_Size_Get_Globals_Funcs( size ); - if ( funcs ) - funcs->destroy( (PSH_Globals)size->root.internal ); - - size->root.internal = NULL; - } - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Size_Init( FT_Size t1size ) /* T1_Size */ - { - T1_Size size = (T1_Size)t1size; - FT_Error error = FT_Err_Ok; - PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); - - - if ( funcs ) - { - PSH_Globals globals; - T1_Face face = (T1_Face)size->root.face; - - - error = funcs->create( size->root.face->memory, - &face->type1.private_dict, &globals ); - if ( !error ) - size->root.internal = (FT_Size_Internal)(void*)globals; - } - - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Size_Request( FT_Size t1size, /* T1_Size */ - FT_Size_Request req ) - { - T1_Size size = (T1_Size)t1size; - PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); - - - FT_Request_Metrics( size->root.face, req ); - - if ( funcs ) - funcs->set_scale( (PSH_Globals)size->root.internal, - size->root.metrics.x_scale, - size->root.metrics.y_scale, - 0, 0 ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* SLOT FUNCTIONS */ - /* */ - /*************************************************************************/ - - FT_LOCAL_DEF( void ) - T1_GlyphSlot_Done( FT_GlyphSlot slot ) - { - slot->internal->glyph_hints = NULL; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_GlyphSlot_Init( FT_GlyphSlot slot ) - { - T1_Face face; - PSHinter_Service pshinter; - - - face = (T1_Face)slot->face; - pshinter = (PSHinter_Service)face->pshinter; - - if ( pshinter ) - { - FT_Module module; - - - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); - if ( module ) - { - T1_Hints_Funcs funcs; - - - funcs = pshinter->get_t1_funcs( module ); - slot->internal->glyph_hints = (void*)funcs; - } - } - - return 0; - } - - - /*************************************************************************/ - /* */ - /* FACE FUNCTIONS */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* T1_Face_Done */ - /* */ - /* <Description> */ - /* The face object destructor. */ - /* */ - /* <Input> */ - /* face :: A typeless pointer to the face object to destroy. */ - /* */ - FT_LOCAL_DEF( void ) - T1_Face_Done( FT_Face t1face ) /* T1_Face */ - { - T1_Face face = (T1_Face)t1face; - FT_Memory memory; - T1_Font type1; - - - if ( !face ) - return; - - memory = face->root.memory; - type1 = &face->type1; - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - /* release multiple masters information */ - FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); - - if ( face->buildchar ) - { - FT_FREE( face->buildchar ); - - face->buildchar = NULL; - face->len_buildchar = 0; - } - - T1_Done_Blend( face ); - face->blend = NULL; -#endif - - /* release font info strings */ - { - PS_FontInfo info = &type1->font_info; - - - FT_FREE( info->version ); - FT_FREE( info->notice ); - FT_FREE( info->full_name ); - FT_FREE( info->family_name ); - FT_FREE( info->weight ); - } - - /* release top dictionary */ - FT_FREE( type1->charstrings_len ); - FT_FREE( type1->charstrings ); - FT_FREE( type1->glyph_names ); - - FT_FREE( type1->subrs ); - FT_FREE( type1->subrs_len ); - - FT_FREE( type1->subrs_block ); - FT_FREE( type1->charstrings_block ); - FT_FREE( type1->glyph_names_block ); - - FT_FREE( type1->encoding.char_index ); - FT_FREE( type1->encoding.char_name ); - FT_FREE( type1->font_name ); - -#ifndef T1_CONFIG_OPTION_NO_AFM - /* release afm data if present */ - if ( face->afm_data ) - T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data ); -#endif - - /* release unicode map, if any */ -#if 0 - FT_FREE( face->unicode_map_rec.maps ); - face->unicode_map_rec.num_maps = 0; - face->unicode_map = NULL; -#endif - - face->root.family_name = NULL; - face->root.style_name = NULL; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* T1_Face_Init */ - /* */ - /* <Description> */ - /* The face object constructor. */ - /* */ - /* <Input> */ - /* stream :: input stream where to load font data. */ - /* */ - /* face_index :: The index of the font face in the resource. */ - /* */ - /* num_params :: Number of additional generic parameters. Ignored. */ - /* */ - /* params :: Additional generic parameters. Ignored. */ - /* */ - /* <InOut> */ - /* face :: The face record to build. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - T1_Face_Init( FT_Stream stream, - FT_Face t1face, /* T1_Face */ - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ) - { - T1_Face face = (T1_Face)t1face; - FT_Error error; - FT_Service_PsCMaps psnames; - PSAux_Service psaux; - T1_Font type1 = &face->type1; - PS_FontInfo info = &type1->font_info; - - FT_UNUSED( num_params ); - FT_UNUSED( params ); - FT_UNUSED( stream ); - - - face->root.num_faces = 1; - - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); - face->psnames = psnames; - - face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), - "psaux" ); - psaux = (PSAux_Service)face->psaux; - if ( !psaux ) - { - FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" )); - error = FT_THROW( Missing_Module ); - goto Exit; - } - - face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), - "pshinter" ); - - FT_TRACE2(( "Type 1 driver\n" )); - - /* open the tokenizer; this will also check the font format */ - error = T1_Open_Face( face ); - if ( error ) - goto Exit; - - /* if we just wanted to check the format, leave successfully now */ - if ( face_index < 0 ) - goto Exit; - - /* check the face index */ - if ( ( face_index & 0xFFFF ) > 0 ) - { - FT_ERROR(( "T1_Face_Init: invalid face index\n" )); - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - /* now load the font program into the face object */ - - /* initialize the face object fields */ - - /* set up root face fields */ - { - FT_Face root = (FT_Face)&face->root; - - - root->num_glyphs = type1->num_glyphs; - root->face_index = 0; - - root->face_flags |= FT_FACE_FLAG_SCALABLE | - FT_FACE_FLAG_HORIZONTAL | - FT_FACE_FLAG_GLYPH_NAMES | - FT_FACE_FLAG_HINTER; - - if ( info->is_fixed_pitch ) - root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; - - if ( face->blend ) - root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; - - /* The following code to extract the family and the style is very */ - /* simplistic and might get some things wrong. For a full-featured */ - /* algorithm you might have a look at the whitepaper given at */ - /* */ - /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ - - /* get style name -- be careful, some broken fonts only */ - /* have a `/FontName' dictionary entry! */ - root->family_name = info->family_name; - root->style_name = NULL; - - if ( root->family_name ) - { - char* full = info->full_name; - char* family = root->family_name; - - - if ( full ) - { - FT_Bool the_same = TRUE; - - - while ( *full ) - { - if ( *full == *family ) - { - family++; - full++; - } - else - { - if ( *full == ' ' || *full == '-' ) - full++; - else if ( *family == ' ' || *family == '-' ) - family++; - else - { - the_same = FALSE; - - if ( !*family ) - root->style_name = full; - break; - } - } - } - - if ( the_same ) - root->style_name = (char *)"Regular"; - } - } - else - { - /* do we have a `/FontName'? */ - if ( type1->font_name ) - root->family_name = type1->font_name; - } - - if ( !root->style_name ) - { - if ( info->weight ) - root->style_name = info->weight; - else - /* assume `Regular' style because we don't know better */ - root->style_name = (char *)"Regular"; - } - - /* compute style flags */ - root->style_flags = 0; - if ( info->italic_angle ) - root->style_flags |= FT_STYLE_FLAG_ITALIC; - if ( info->weight ) - { - if ( !ft_strcmp( info->weight, "Bold" ) || - !ft_strcmp( info->weight, "Black" ) ) - root->style_flags |= FT_STYLE_FLAG_BOLD; - } - - /* no embedded bitmap support */ - root->num_fixed_sizes = 0; - root->available_sizes = NULL; - - root->bbox.xMin = type1->font_bbox.xMin >> 16; - root->bbox.yMin = type1->font_bbox.yMin >> 16; - /* no `U' suffix here to 0xFFFF! */ - root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16; - root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16; - - /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */ - if ( !root->units_per_EM ) - root->units_per_EM = 1000; - - root->ascender = (FT_Short)( root->bbox.yMax ); - root->descender = (FT_Short)( root->bbox.yMin ); - - root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 ); - if ( root->height < root->ascender - root->descender ) - root->height = (FT_Short)( root->ascender - root->descender ); - - /* now compute the maximum advance width */ - root->max_advance_width = - (FT_Short)( root->bbox.xMax ); - { - FT_Pos max_advance; - - - error = T1_Compute_Max_Advance( face, &max_advance ); - - /* in case of error, keep the standard width */ - if ( !error ) - root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance ); - else - error = FT_Err_Ok; /* clear error */ - } - - root->max_advance_height = root->height; - - root->underline_position = (FT_Short)info->underline_position; - root->underline_thickness = (FT_Short)info->underline_thickness; - } - - { - FT_Face root = &face->root; - - - if ( psnames ) - { - FT_CharMapRec charmap; - T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; - FT_CMap_Class clazz; - - - charmap.face = root; - - /* first of all, try to synthesize a Unicode charmap */ - charmap.platform_id = TT_PLATFORM_MICROSOFT; - charmap.encoding_id = TT_MS_ID_UNICODE_CS; - charmap.encoding = FT_ENCODING_UNICODE; - - error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); - if ( error && - FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) - goto Exit; - error = FT_Err_Ok; - - /* now, generate an Adobe Standard encoding when appropriate */ - charmap.platform_id = TT_PLATFORM_ADOBE; - clazz = NULL; - - switch ( type1->encoding_type ) - { - case T1_ENCODING_TYPE_STANDARD: - charmap.encoding = FT_ENCODING_ADOBE_STANDARD; - charmap.encoding_id = TT_ADOBE_ID_STANDARD; - clazz = cmap_classes->standard; - break; - - case T1_ENCODING_TYPE_EXPERT: - charmap.encoding = FT_ENCODING_ADOBE_EXPERT; - charmap.encoding_id = TT_ADOBE_ID_EXPERT; - clazz = cmap_classes->expert; - break; - - case T1_ENCODING_TYPE_ARRAY: - charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; - charmap.encoding_id = TT_ADOBE_ID_CUSTOM; - clazz = cmap_classes->custom; - break; - - case T1_ENCODING_TYPE_ISOLATIN1: - charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; - charmap.encoding_id = TT_ADOBE_ID_LATIN_1; - clazz = cmap_classes->unicode; - break; - - default: - ; - } - - if ( clazz ) - error = FT_CMap_New( clazz, NULL, &charmap, NULL ); - -#if 0 - /* Select default charmap */ - if (root->num_charmaps) - root->charmap = root->charmaps[0]; -#endif - } - } - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* T1_Driver_Init */ - /* */ - /* <Description> */ - /* Initializes a given Type 1 driver object. */ - /* */ - /* <Input> */ - /* driver :: A handle to the target driver object. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - T1_Driver_Init( FT_Module driver ) - { - FT_UNUSED( driver ); - - return FT_Err_Ok; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* T1_Driver_Done */ - /* */ - /* <Description> */ - /* Finalizes a given Type 1 driver. */ - /* */ - /* <Input> */ - /* driver :: A handle to the target Type 1 driver. */ - /* */ - FT_LOCAL_DEF( void ) - T1_Driver_Done( FT_Module driver ) - { - FT_UNUSED( driver ); - } - - -/* END */ diff --git a/third_party/freetype/src/type1/t1objs.h b/third_party/freetype/src/type1/t1objs.h deleted file mode 100644 index 6b4f3cb56d4c1d50ede439a1d7c70dd390ae4e5c..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1objs.h +++ /dev/null @@ -1,160 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1objs.h */ -/* */ -/* Type 1 objects manager (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1OBJS_H__ -#define __T1OBJS_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include FT_CONFIG_CONFIG_H -#include FT_INTERNAL_TYPE1_TYPES_H - - -FT_BEGIN_HEADER - - - /* The following structures must be defined by the hinter */ - typedef struct T1_Size_Hints_ T1_Size_Hints; - typedef struct T1_Glyph_Hints_ T1_Glyph_Hints; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* T1_Size */ - /* */ - /* <Description> */ - /* A handle to a Type 1 size object. */ - /* */ - typedef struct T1_SizeRec_* T1_Size; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* T1_GlyphSlot */ - /* */ - /* <Description> */ - /* A handle to a Type 1 glyph slot object. */ - /* */ - typedef struct T1_GlyphSlotRec_* T1_GlyphSlot; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* T1_CharMap */ - /* */ - /* <Description> */ - /* A handle to a Type 1 character mapping object. */ - /* */ - /* <Note> */ - /* The Type 1 format doesn't use a charmap but an encoding table. */ - /* The driver is responsible for making up charmap objects */ - /* corresponding to these tables. */ - /* */ - typedef struct T1_CharMapRec_* T1_CharMap; - - - /*************************************************************************/ - /* */ - /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */ - /* */ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* T1_SizeRec */ - /* */ - /* <Description> */ - /* Type 1 size record. */ - /* */ - typedef struct T1_SizeRec_ - { - FT_SizeRec root; - - } T1_SizeRec; - - - FT_LOCAL( void ) - T1_Size_Done( FT_Size size ); - - FT_LOCAL( FT_Error ) - T1_Size_Request( FT_Size size, - FT_Size_Request req ); - - FT_LOCAL( FT_Error ) - T1_Size_Init( FT_Size size ); - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* T1_GlyphSlotRec */ - /* */ - /* <Description> */ - /* Type 1 glyph slot record. */ - /* */ - typedef struct T1_GlyphSlotRec_ - { - FT_GlyphSlotRec root; - - FT_Bool hint; - FT_Bool scaled; - - FT_Int max_points; - FT_Int max_contours; - - FT_Fixed x_scale; - FT_Fixed y_scale; - - } T1_GlyphSlotRec; - - - FT_LOCAL( FT_Error ) - T1_Face_Init( FT_Stream stream, - FT_Face face, - FT_Int face_index, - FT_Int num_params, - FT_Parameter* params ); - - FT_LOCAL( void ) - T1_Face_Done( FT_Face face ); - - FT_LOCAL( FT_Error ) - T1_GlyphSlot_Init( FT_GlyphSlot slot ); - - FT_LOCAL( void ) - T1_GlyphSlot_Done( FT_GlyphSlot slot ); - - FT_LOCAL( FT_Error ) - T1_Driver_Init( FT_Module driver ); - - FT_LOCAL( void ) - T1_Driver_Done( FT_Module driver ); - - -FT_END_HEADER - -#endif /* __T1OBJS_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1parse.c b/third_party/freetype/src/type1/t1parse.c deleted file mode 100644 index 0b685026067910bcf7fb45e4bfe3d13c9fe36be8..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1parse.c +++ /dev/null @@ -1,525 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1parse.c */ -/* */ -/* Type 1 parser (body). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - - /*************************************************************************/ - /* */ - /* The Type 1 parser is in charge of the following: */ - /* */ - /* - provide an implementation of a growing sequence of objects called */ - /* a `T1_Table' (used to build various tables needed by the loader). */ - /* */ - /* - opening .pfb and .pfa files to extract their top-level and private */ - /* dictionaries. */ - /* */ - /* - read numbers, arrays & strings from any dictionary. */ - /* */ - /* See `t1load.c' to see how data is loaded from the font file. */ - /* */ - /*************************************************************************/ - - -#include <ft2build.h> -#include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_POSTSCRIPT_AUX_H - -#include "t1parse.h" - -#include "t1errors.h" - - - /*************************************************************************/ - /* */ - /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ - /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ - /* messages during execution. */ - /* */ -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1parse - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** INPUT STREAM PARSER *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /* see Adobe Technical Note 5040.Download_Fonts.pdf */ - - static FT_Error - read_pfb_tag( FT_Stream stream, - FT_UShort *atag, - FT_ULong *asize ) - { - FT_Error error; - FT_UShort tag; - FT_ULong size; - - - *atag = 0; - *asize = 0; - - if ( !FT_READ_USHORT( tag ) ) - { - if ( tag == 0x8001U || tag == 0x8002U ) - { - if ( !FT_READ_ULONG_LE( size ) ) - *asize = size; - } - - *atag = tag; - } - - return error; - } - - - static FT_Error - check_type1_format( FT_Stream stream, - const char* header_string, - size_t header_length ) - { - FT_Error error; - FT_UShort tag; - FT_ULong dummy; - - - if ( FT_STREAM_SEEK( 0 ) ) - goto Exit; - - error = read_pfb_tag( stream, &tag, &dummy ); - if ( error ) - goto Exit; - - /* We assume that the first segment in a PFB is always encoded as */ - /* text. This might be wrong (and the specification doesn't insist */ - /* on that), but we have never seen a counterexample. */ - if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) ) - goto Exit; - - if ( !FT_FRAME_ENTER( header_length ) ) - { - error = FT_Err_Ok; - - if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 ) - error = FT_THROW( Unknown_File_Format ); - - FT_FRAME_EXIT(); - } - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - T1_New_Parser( T1_Parser parser, - FT_Stream stream, - FT_Memory memory, - PSAux_Service psaux ) - { - FT_Error error; - FT_UShort tag; - FT_ULong size; - - - psaux->ps_parser_funcs->init( &parser->root, NULL, NULL, memory ); - - parser->stream = stream; - parser->base_len = 0; - parser->base_dict = NULL; - parser->private_len = 0; - parser->private_dict = NULL; - parser->in_pfb = 0; - parser->in_memory = 0; - parser->single_block = 0; - - /* check the header format */ - error = check_type1_format( stream, "%!PS-AdobeFont", 14 ); - if ( error ) - { - if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) - goto Exit; - - error = check_type1_format( stream, "%!FontType", 10 ); - if ( error ) - { - FT_TRACE2(( " not a Type 1 font\n" )); - goto Exit; - } - } - - /******************************************************************/ - /* */ - /* Here a short summary of what is going on: */ - /* */ - /* When creating a new Type 1 parser, we try to locate and load */ - /* the base dictionary if this is possible (i.e., for PFB */ - /* files). Otherwise, we load the whole font into memory. */ - /* */ - /* When `loading' the base dictionary, we only setup pointers */ - /* in the case of a memory-based stream. Otherwise, we */ - /* allocate and load the base dictionary in it. */ - /* */ - /* parser->in_pfb is set if we are in a binary (`.pfb') font. */ - /* parser->in_memory is set if we have a memory stream. */ - /* */ - - /* try to compute the size of the base dictionary; */ - /* look for a Postscript binary file tag, i.e., 0x8001 */ - if ( FT_STREAM_SEEK( 0L ) ) - goto Exit; - - error = read_pfb_tag( stream, &tag, &size ); - if ( error ) - goto Exit; - - if ( tag != 0x8001U ) - { - /* assume that this is a PFA file for now; an error will */ - /* be produced later when more things are checked */ - if ( FT_STREAM_SEEK( 0L ) ) - goto Exit; - size = stream->size; - } - else - parser->in_pfb = 1; - - /* now, try to load `size' bytes of the `base' dictionary we */ - /* found previously */ - - /* if it is a memory-based resource, set up pointers */ - if ( !stream->read ) - { - parser->base_dict = (FT_Byte*)stream->base + stream->pos; - parser->base_len = size; - parser->in_memory = 1; - - /* check that the `size' field is valid */ - if ( FT_STREAM_SKIP( size ) ) - goto Exit; - } - else - { - /* read segment in memory -- this is clumsy, but so does the format */ - if ( FT_ALLOC( parser->base_dict, size ) || - FT_STREAM_READ( parser->base_dict, size ) ) - goto Exit; - parser->base_len = size; - } - - parser->root.base = parser->base_dict; - parser->root.cursor = parser->base_dict; - parser->root.limit = parser->root.cursor + parser->base_len; - - Exit: - if ( error && !parser->in_memory ) - FT_FREE( parser->base_dict ); - - return error; - } - - - FT_LOCAL_DEF( void ) - T1_Finalize_Parser( T1_Parser parser ) - { - FT_Memory memory = parser->root.memory; - - - /* always free the private dictionary */ - FT_FREE( parser->private_dict ); - - /* free the base dictionary only when we have a disk stream */ - if ( !parser->in_memory ) - FT_FREE( parser->base_dict ); - - parser->root.funcs.done( &parser->root ); - } - - - FT_LOCAL_DEF( FT_Error ) - T1_Get_Private_Dict( T1_Parser parser, - PSAux_Service psaux ) - { - FT_Stream stream = parser->stream; - FT_Memory memory = parser->root.memory; - FT_Error error = FT_Err_Ok; - FT_ULong size; - - - if ( parser->in_pfb ) - { - /* in the case of the PFB format, the private dictionary can be */ - /* made of several segments. We thus first read the number of */ - /* segments to compute the total size of the private dictionary */ - /* then re-read them into memory. */ - FT_ULong start_pos = FT_STREAM_POS(); - FT_UShort tag; - - - parser->private_len = 0; - for (;;) - { - error = read_pfb_tag( stream, &tag, &size ); - if ( error ) - goto Fail; - - if ( tag != 0x8002U ) - break; - - parser->private_len += size; - - if ( FT_STREAM_SKIP( size ) ) - goto Fail; - } - - /* Check that we have a private dictionary there */ - /* and allocate private dictionary buffer */ - if ( parser->private_len == 0 ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " invalid private dictionary section\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - if ( FT_STREAM_SEEK( start_pos ) || - FT_ALLOC( parser->private_dict, parser->private_len ) ) - goto Fail; - - parser->private_len = 0; - for (;;) - { - error = read_pfb_tag( stream, &tag, &size ); - if ( error || tag != 0x8002U ) - { - error = FT_Err_Ok; - break; - } - - if ( FT_STREAM_READ( parser->private_dict + parser->private_len, - size ) ) - goto Fail; - - parser->private_len += size; - } - } - else - { - /* We have already `loaded' the whole PFA font file into memory; */ - /* if this is a memory resource, allocate a new block to hold */ - /* the private dict. Otherwise, simply overwrite into the base */ - /* dictionary block in the heap. */ - - /* first of all, look at the `eexec' keyword */ - FT_Byte* cur = parser->base_dict; - FT_Byte* limit = cur + parser->base_len; - FT_Pointer pos_lf; - FT_Bool test_cr; - - - Again: - for (;;) - { - if ( cur[0] == 'e' && - cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ - /* whitespace + 4 chars */ - { - if ( cur[1] == 'e' && - cur[2] == 'x' && - cur[3] == 'e' && - cur[4] == 'c' ) - break; - } - cur++; - if ( cur >= limit ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " could not find `eexec' keyword\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - } - - /* check whether `eexec' was real -- it could be in a comment */ - /* or string (as e.g. in u003043t.gsf from ghostscript) */ - - parser->root.cursor = parser->base_dict; - /* set limit to `eexec' + whitespace + 4 characters */ - parser->root.limit = cur + 10; - - cur = parser->root.cursor; - limit = parser->root.limit; - - while ( cur < limit ) - { - if ( cur[0] == 'e' && - cur + 5 < limit ) - { - if ( cur[1] == 'e' && - cur[2] == 'x' && - cur[3] == 'e' && - cur[4] == 'c' ) - goto Found; - } - - T1_Skip_PS_Token( parser ); - if ( parser->root.error ) - break; - T1_Skip_Spaces ( parser ); - cur = parser->root.cursor; - } - - /* we haven't found the correct `eexec'; go back and continue */ - /* searching */ - - cur = limit; - limit = parser->base_dict + parser->base_len; - - if ( cur >= limit ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " premature end in private dictionary\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - goto Again; - - /* now determine where to write the _encrypted_ binary private */ - /* dictionary. We overwrite the base dictionary for disk-based */ - /* resources and allocate a new block otherwise */ - - Found: - parser->root.limit = parser->base_dict + parser->base_len; - - T1_Skip_PS_Token( parser ); - cur = parser->root.cursor; - limit = parser->root.limit; - - /* According to the Type 1 spec, the first cipher byte must not be */ - /* an ASCII whitespace character code (blank, tab, carriage return */ - /* or line feed). We have seen Type 1 fonts with two line feed */ - /* characters... So skip now all whitespace character codes. */ - /* */ - /* On the other hand, Adobe's Type 1 parser handles fonts just */ - /* fine that are violating this limitation, so we add a heuristic */ - /* test to stop at \r only if it is not used for EOL. */ - - pos_lf = ft_memchr( cur, '\n', (size_t)( limit - cur ) ); - test_cr = FT_BOOL( !pos_lf || - pos_lf > ft_memchr( cur, - '\r', - (size_t)( limit - cur ) ) ); - - while ( cur < limit && - ( *cur == ' ' || - *cur == '\t' || - (test_cr && *cur == '\r' ) || - *cur == '\n' ) ) - ++cur; - if ( cur >= limit ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " `eexec' not properly terminated\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - size = parser->base_len - (FT_ULong)( cur - parser->base_dict ); - - if ( parser->in_memory ) - { - /* note that we allocate one more byte to put a terminating `0' */ - if ( FT_ALLOC( parser->private_dict, size + 1 ) ) - goto Fail; - parser->private_len = size; - } - else - { - parser->single_block = 1; - parser->private_dict = parser->base_dict; - parser->private_len = size; - parser->base_dict = NULL; - parser->base_len = 0; - } - - /* now determine whether the private dictionary is encoded in binary */ - /* or hexadecimal ASCII format -- decode it accordingly */ - - /* we need to access the next 4 bytes (after the final whitespace */ - /* following the `eexec' keyword); if they all are hexadecimal */ - /* digits, then we have a case of ASCII storage */ - - if ( cur + 3 < limit && - ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && - ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) - { - /* ASCII hexadecimal encoding */ - FT_ULong len; - - - parser->root.cursor = cur; - (void)psaux->ps_parser_funcs->to_bytes( &parser->root, - parser->private_dict, - parser->private_len, - &len, - 0 ); - parser->private_len = len; - - /* put a safeguard */ - parser->private_dict[len] = '\0'; - } - else - /* binary encoding -- copy the private dict */ - FT_MEM_MOVE( parser->private_dict, cur, size ); - } - - /* we now decrypt the encoded binary private dictionary */ - psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U ); - - if ( parser->private_len < 4 ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " invalid private dictionary section\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - - /* replace the four random bytes at the beginning with whitespace */ - parser->private_dict[0] = ' '; - parser->private_dict[1] = ' '; - parser->private_dict[2] = ' '; - parser->private_dict[3] = ' '; - - parser->root.base = parser->private_dict; - parser->root.cursor = parser->private_dict; - parser->root.limit = parser->root.cursor + parser->private_len; - - Fail: - Exit: - return error; - } - - -/* END */ diff --git a/third_party/freetype/src/type1/t1parse.h b/third_party/freetype/src/type1/t1parse.h deleted file mode 100644 index 93b02e3d317c3cf5da74a740ecf2ac06c0acbb72..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1parse.h +++ /dev/null @@ -1,129 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1parse.h */ -/* */ -/* Type 1 parser (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#ifndef __T1PARSE_H__ -#define __T1PARSE_H__ - - -#include <ft2build.h> -#include FT_INTERNAL_TYPE1_TYPES_H -#include FT_INTERNAL_STREAM_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* T1_ParserRec */ - /* */ - /* <Description> */ - /* A PS_ParserRec is an object used to parse a Type 1 fonts very */ - /* quickly. */ - /* */ - /* <Fields> */ - /* root :: The root parser. */ - /* */ - /* stream :: The current input stream. */ - /* */ - /* base_dict :: A pointer to the top-level dictionary. */ - /* */ - /* base_len :: The length in bytes of the top dictionary. */ - /* */ - /* private_dict :: A pointer to the private dictionary. */ - /* */ - /* private_len :: The length in bytes of the private dictionary. */ - /* */ - /* in_pfb :: A boolean. Indicates that we are handling a PFB */ - /* file. */ - /* */ - /* in_memory :: A boolean. Indicates a memory-based stream. */ - /* */ - /* single_block :: A boolean. Indicates that the private dictionary */ - /* is stored in lieu of the base dictionary. */ - /* */ - typedef struct T1_ParserRec_ - { - PS_ParserRec root; - FT_Stream stream; - - FT_Byte* base_dict; - FT_ULong base_len; - - FT_Byte* private_dict; - FT_ULong private_len; - - FT_Bool in_pfb; - FT_Bool in_memory; - FT_Bool single_block; - - } T1_ParserRec, *T1_Parser; - - -#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l ) -#define T1_Release_Table( p ) \ - do \ - { \ - if ( (p)->funcs.release ) \ - (p)->funcs.release( p ); \ - } while ( 0 ) - - -#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root ) -#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root ) - -#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root ) -#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t ) - -#define T1_ToCoordArray( p, m, c ) \ - (p)->root.funcs.to_coord_array( &(p)->root, m, c ) -#define T1_ToFixedArray( p, m, f, t ) \ - (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t ) -#define T1_ToToken( p, t ) \ - (p)->root.funcs.to_token( &(p)->root, t ) -#define T1_ToTokenArray( p, t, m, c ) \ - (p)->root.funcs.to_token_array( &(p)->root, t, m, c ) - -#define T1_Load_Field( p, f, o, m, pf ) \ - (p)->root.funcs.load_field( &(p)->root, f, o, m, pf ) - -#define T1_Load_Field_Table( p, f, o, m, pf ) \ - (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf ) - - - FT_LOCAL( FT_Error ) - T1_New_Parser( T1_Parser parser, - FT_Stream stream, - FT_Memory memory, - PSAux_Service psaux ); - - FT_LOCAL( FT_Error ) - T1_Get_Private_Dict( T1_Parser parser, - PSAux_Service psaux ); - - FT_LOCAL( void ) - T1_Finalize_Parser( T1_Parser parser ); - - -FT_END_HEADER - -#endif /* __T1PARSE_H__ */ - - -/* END */ diff --git a/third_party/freetype/src/type1/t1tokens.h b/third_party/freetype/src/type1/t1tokens.h deleted file mode 100644 index 399265243525cd45c8dfa39a3fddcbd22994a1bf..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/t1tokens.h +++ /dev/null @@ -1,143 +0,0 @@ -/***************************************************************************/ -/* */ -/* t1tokens.h */ -/* */ -/* Type 1 tokenizer (specification). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_FontInfoRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FONT_INFO - - T1_FIELD_STRING( "version", version, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_STRING( "Notice", notice, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_STRING( "FullName", full_name, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_STRING( "FamilyName", family_name, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_STRING( "Weight", weight, - T1_FIELD_DICT_FONTDICT ) - - /* we use pointers to detect modifications made by synthetic fonts */ - T1_FIELD_NUM ( "ItalicAngle", italic_angle, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_NUM ( "UnderlinePosition", underline_position, - T1_FIELD_DICT_FONTDICT ) - T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, - T1_FIELD_DICT_FONTDICT ) - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_FontExtraRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FONT_EXTRA - - T1_FIELD_NUM ( "FSType", fs_type, - T1_FIELD_DICT_FONTDICT ) - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_PrivateRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_PRIVATE - - T1_FIELD_NUM ( "UniqueID", unique_id, - T1_FIELD_DICT_FONTDICT | T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM ( "lenIV", lenIV, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM ( "LanguageGroup", language_group, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM ( "password", password, - T1_FIELD_DICT_PRIVATE ) - - T1_FIELD_FIXED_1000( "BlueScale", blue_scale, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM ( "BlueShift", blue_shift, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM ( "BlueFuzz", blue_fuzz, - T1_FIELD_DICT_PRIVATE ) - - T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, - T1_FIELD_DICT_PRIVATE ) - - T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2, - T1_FIELD_DICT_PRIVATE ) - - T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12, - T1_FIELD_DICT_PRIVATE ) - - T1_FIELD_FIXED ( "ExpansionFactor", expansion_factor, - T1_FIELD_DICT_PRIVATE ) - T1_FIELD_BOOL ( "ForceBold", force_bold, - T1_FIELD_DICT_PRIVATE ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE T1_FontRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FONT_DICT - - T1_FIELD_KEY ( "FontName", font_name, T1_FIELD_DICT_FONTDICT ) - T1_FIELD_NUM ( "PaintType", paint_type, T1_FIELD_DICT_FONTDICT ) - T1_FIELD_NUM ( "FontType", font_type, T1_FIELD_DICT_FONTDICT ) - T1_FIELD_FIXED( "StrokeWidth", stroke_width, T1_FIELD_DICT_FONTDICT ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE FT_BBox -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_BBOX - - T1_FIELD_BBOX( "FontBBox", xMin, T1_FIELD_DICT_FONTDICT ) - - -#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT - -#undef FT_STRUCTURE -#define FT_STRUCTURE T1_FaceRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_FACE - - T1_FIELD_NUM( "NDV", ndv_idx, T1_FIELD_DICT_PRIVATE ) - T1_FIELD_NUM( "CDV", cdv_idx, T1_FIELD_DICT_PRIVATE ) - - -#undef FT_STRUCTURE -#define FT_STRUCTURE PS_BlendRec -#undef T1CODE -#define T1CODE T1_FIELD_LOCATION_BLEND - - T1_FIELD_NUM_TABLE( "DesignVector", default_design_vector, - T1_MAX_MM_DESIGNS, T1_FIELD_DICT_FONTDICT ) - - -#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */ - - -/* END */ diff --git a/third_party/freetype/src/type1/type1.c b/third_party/freetype/src/type1/type1.c deleted file mode 100644 index 4c70ea7630be1ff3fd773ce3f225261cf2af3cb6..0000000000000000000000000000000000000000 --- a/third_party/freetype/src/type1/type1.c +++ /dev/null @@ -1,33 +0,0 @@ -/***************************************************************************/ -/* */ -/* type1.c */ -/* */ -/* FreeType Type 1 driver component (body only). */ -/* */ -/* Copyright 1996-2015 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ -/* */ -/* This file is part of the FreeType project, and may only be used, */ -/* modified, and distributed under the terms of the FreeType project */ -/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ -/* this file you indicate that you have read the license and */ -/* understand and accept it fully. */ -/* */ -/***************************************************************************/ - - -#define FT_MAKE_OPTION_SINGLE_OBJECT - -#include <ft2build.h> -#include "t1parse.c" -#include "t1load.c" -#include "t1objs.c" -#include "t1driver.c" -#include "t1gload.c" - -#ifndef T1_CONFIG_OPTION_NO_AFM -#include "t1afm.c" -#endif - - -/* END */ diff --git a/third_party/lcms/0000-cmserr-changes.patch b/third_party/lcms/0000-cmserr-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..baf35772a0b878d842c08bebd4fe67bb34bf885c --- /dev/null +++ b/third_party/lcms/0000-cmserr-changes.patch @@ -0,0 +1,285 @@ +diff --git a/third_party/lcms/src/cmserr.c b/third_party/lcms/src/cmserr.c +index 700152ee3..3c3848b2a 100644 +--- a/third_party/lcms/src/cmserr.c ++++ b/third_party/lcms/src/cmserr.c +@@ -25,6 +25,8 @@ + + #include "lcms2_internal.h" + ++#include "core/fxcrt/fx_memory.h" ++#include "core/fxcrt/fx_system.h" + + // This function is here to help applications to prevent mixing lcms versions on header and shared objects. + int CMSEXPORT cmsGetEncodedCMMversion(void) +@@ -65,140 +67,75 @@ long int CMSEXPORT cmsfilelength(FILE* f) + return n; + } + +- +-// Memory handling ------------------------------------------------------------------ +-// +-// This is the interface to low-level memory management routines. By default a simple +-// wrapping to malloc/free/realloc is provided, although there is a limit on the max +-// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent +-// bogus or evil code to allocate huge blocks that otherwise lcms would never need. +- +-#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U)) +- +-// User may override this behaviour by using a memory plug-in, which basically replaces +-// the default memory management functions. In this case, no check is performed and it +-// is up to the plug-in writter to keep in the safe side. There are only three functions +-// required to be implemented: malloc, realloc and free, although the user may want to +-// replace the optional mallocZero, calloc and dup as well. +- +-cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); +- +-// ********************************************************************************* +- +-// This is the default memory allocation function. It does a very coarse +-// check of amout of memory, just to prevent exploits +-static +-void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size) ++cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin) + { +- if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never allow over maximum +- +- return (void*) malloc(size); ++ return TRUE; ++} + +- cmsUNUSED_PARAMETER(ContextID); ++// Generic allocate ++void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) ++{ ++ return FXMEM_DefaultAlloc(size); + } + + // Generic allocate & zero +-static +-void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size) ++void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) + { +- void *pt = _cmsMalloc(ContextID, size); +- if (pt == NULL) return NULL; +- +- memset(pt, 0, size); +- return pt; ++ void* p = FXMEM_DefaultAlloc(size); ++ if (p) memset(p, 0, size); ++ return p; + } + +- +-// The default free function. The only check proformed is against NULL pointers +-static +-void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr) ++// Generic calloc ++void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) + { +- // free(NULL) is defined a no-op by C99, therefore it is safe to +- // avoid the check, but it is here just in case... +- +- if (Ptr) free(Ptr); ++ cmsUInt32Number total = num * size; ++ if (total == 0 || total / size != num || total >= 512 * 1024 * 1024) ++ return NULL; + +- cmsUNUSED_PARAMETER(ContextID); ++ return _cmsMallocZero(ContextID, num * size); + } + +-// The default realloc function. Again it checks for exploits. If Ptr is NULL, +-// realloc behaves the same way as malloc and allocates a new block of size bytes. +-static +-void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) ++// Generic reallocate ++void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) + { +- +- if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never realloc over 512Mb +- +- return realloc(Ptr, size); +- +- cmsUNUSED_PARAMETER(ContextID); ++ return FXMEM_DefaultRealloc(Ptr, size); + } + +- +-// The default calloc function. Allocates an array of num elements, each one of size bytes +-// all memory is initialized to zero. +-static +-void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) ++// Generic free memory ++void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) + { +- cmsUInt32Number Total = num * size; +- +- // Preserve calloc behaviour +- if (Total == 0) return NULL; +- +- // Safe check for overflow. +- if (num >= UINT_MAX / size) return NULL; +- +- // Check for overflow +- if (Total < num || Total < size) { +- return NULL; +- } +- +- if (Total > MAX_MEMORY_FOR_ALLOC) return NULL; // Never alloc over 512Mb +- +- return _cmsMallocZero(ContextID, Total); ++ if (Ptr != NULL) FXMEM_DefaultFree(Ptr); + } + + // Generic block duplication +-static +-void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size) ++void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) + { +- void* mem; +- +- if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb +- +- mem = _cmsMalloc(ContextID, size); +- +- if (mem != NULL && Org != NULL) +- memmove(mem, Org, size); +- +- return mem; ++ void* p = FXMEM_DefaultAlloc(size); ++ memmove(p, Org, size); ++ return p; + } + +- +-// Pointers to memory manager functions in Context0 +-_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn, +- _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn ++_cmsMemPluginChunkType _cmsMemPluginChunk = {_cmsMalloc, _cmsMallocZero, _cmsFree, ++ _cmsRealloc, _cmsCalloc, _cmsDupMem + }; + +- +-// Reset and duplicate memory manager + void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) + { + _cmsAssert(ctx != NULL); + +- if (src != NULL) { ++ if (src != NULL) { + + // Duplicate +- ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); ++ ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); + } + else { + + // To reset it, we use the default allocators, which cannot be overriden + ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; +- } ++ } + } + +-// Auxiliary to fill memory management functions from plugin (or context 0 defaults) + void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) + { + if (Plugin == NULL) { +@@ -212,94 +149,15 @@ void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkTy + ptr ->ReallocPtr = Plugin -> ReallocPtr; + + // Make sure we revert to defaults +- ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn; +- ptr ->CallocPtr = _cmsCallocDefaultFn; +- ptr ->DupPtr = _cmsDupDefaultFn; +- ++ ptr ->MallocZeroPtr= _cmsMallocZero; ++ ptr ->CallocPtr = _cmsCalloc; ++ ptr ->DupPtr = _cmsDupMem; ++ + if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; + if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; + if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; +- +- } +-} +- + +-// Plug-in replacement entry +-cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data) +-{ +- cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data; +- _cmsMemPluginChunkType* ptr; +- +- // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure. +- // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the +- // context internal data should be malloce'd by using those functions. +- if (Data == NULL) { +- +- struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID; +- +- // Return to the default allocators +- if (ContextID != NULL) { +- ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager; +- } +- return TRUE; + } +- +- // Check for required callbacks +- if (Plugin -> MallocPtr == NULL || +- Plugin -> FreePtr == NULL || +- Plugin -> ReallocPtr == NULL) return FALSE; +- +- // Set replacement functions +- ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- if (ptr == NULL) +- return FALSE; +- +- _cmsInstallAllocFunctions(Plugin, ptr); +- return TRUE; +-} +- +-// Generic allocate +-void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) +-{ +- _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- return ptr ->MallocPtr(ContextID, size); +-} +- +-// Generic allocate & zero +-void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) +-{ +- _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- return ptr->MallocZeroPtr(ContextID, size); +-} +- +-// Generic calloc +-void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) +-{ +- _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- return ptr->CallocPtr(ContextID, num, size); +-} +- +-// Generic reallocate +-void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) +-{ +- _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- return ptr->ReallocPtr(ContextID, Ptr, size); +-} +- +-// Generic free memory +-void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) +-{ +- if (Ptr != NULL) { +- _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- ptr ->FreePtr(ContextID, Ptr); +- } +-} +- +-// Generic block duplication +-void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) +-{ +- _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); +- return ptr ->DupPtr(ContextID, Org, size); + } + + // ******************************************************************************************** diff --git a/third_party/lcms/0001-fix-include.patch b/third_party/lcms/0001-fix-include.patch new file mode 100644 index 0000000000000000000000000000000000000000..d95dba6ee26bda75105ac873a0776ea97ab8f34c --- /dev/null +++ b/third_party/lcms/0001-fix-include.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/src/lcms2_internal.h b/third_party/lcms/src/lcms2_internal.h +index 727cb06e3..115ac5970 100644 +--- a/third_party/lcms/src/lcms2_internal.h ++++ b/third_party/lcms/src/lcms2_internal.h +@@ -28,7 +28,7 @@ + + // Include plug-in foundation + #ifndef _lcms_plugin_H +-# include "lcms2_plugin.h" ++# include "third_party/lcms/include/lcms2_plugin.h" + #endif + + // ctype is part of C99 as per 7.1.2 diff --git a/third_party/lcms/0002-old-performance-fix.patch b/third_party/lcms/0002-old-performance-fix.patch new file mode 100644 index 0000000000000000000000000000000000000000..cea2bee94b97bb9465a1178007e478f60c2b95b8 --- /dev/null +++ b/third_party/lcms/0002-old-performance-fix.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/src/cmsgamma.c b/third_party/lcms/src/cmsgamma.c +index edb8f6bba..eb3dd881c 100644 +--- a/third_party/lcms/src/cmsgamma.c ++++ b/third_party/lcms/src/cmsgamma.c +@@ -799,7 +799,7 @@ void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]) + // Duplicate a gamma table + cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In) + { +- if (In == NULL) return NULL; ++ if (In == NULL || In ->Segments == NULL || In ->Table16 == NULL) return NULL; + + return AllocateToneCurveStruct(In ->InterpParams ->ContextID, In ->nEntries, In ->nSegments, In ->Segments, In ->Table16); + } diff --git a/third_party/lcms/0003-old-uninitialized-in-LUTevalFloat.patch b/third_party/lcms/0003-old-uninitialized-in-LUTevalFloat.patch new file mode 100644 index 0000000000000000000000000000000000000000..8091eefd7cdeaa6566303f03560d5c6dec9ce052 --- /dev/null +++ b/third_party/lcms/0003-old-uninitialized-in-LUTevalFloat.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c +index df3dfc1ad..45f05c61d 100644 +--- a/third_party/lcms/src/cmslut.c ++++ b/third_party/lcms/src/cmslut.c +@@ -1321,7 +1321,7 @@ void _LUTevalFloat(register const cmsFloat32Number In[], register cmsFloat32Numb + { + cmsPipeline* lut = (cmsPipeline*) D; + cmsStage *mpe; +- cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS]; ++ cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS] = {0.0f}; + int Phase = 0, NextPhase; + + memmove(&Storage[Phase][0], In, lut ->InputChannels * sizeof(cmsFloat32Number)); diff --git a/third_party/lcms/0004-old-uninitialized-in-LUTeval16.patch b/third_party/lcms/0004-old-uninitialized-in-LUTeval16.patch new file mode 100644 index 0000000000000000000000000000000000000000..dce315257d8b8b1173b8253ac78b037815e6a70b --- /dev/null +++ b/third_party/lcms/0004-old-uninitialized-in-LUTeval16.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c +index 45f05c61d..18b88a545 100644 +--- a/third_party/lcms/src/cmslut.c ++++ b/third_party/lcms/src/cmslut.c +@@ -1295,7 +1295,7 @@ void _LUTeval16(register const cmsUInt16Number In[], register cmsUInt16Number Ou + { + cmsPipeline* lut = (cmsPipeline*) D; + cmsStage *mpe; +- cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS]; ++ cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS] = {0.0f}; + int Phase = 0, NextPhase; + + From16ToFloat(In, &Storage[Phase][0], lut ->InputChannels); diff --git a/third_party/lcms/0005-old-fix-e-with-tilde.patch b/third_party/lcms/0005-old-fix-e-with-tilde.patch new file mode 100644 index 0000000000000000000000000000000000000000..2fc054dae8b4b7612c15d74d98b000dbe820de15 --- /dev/null +++ b/third_party/lcms/0005-old-fix-e-with-tilde.patch @@ -0,0 +1,61 @@ +diff --git a/third_party/lcms/src/cmsxform.c b/third_party/lcms/src/cmsxform.c +index 4a5a4f093..9c20c49b0 100644 +--- a/third_party/lcms/src/cmsxform.c ++++ b/third_party/lcms/src/cmsxform.c +@@ -338,7 +338,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p, + + // 16 bit precision ----------------------------------------------------------------------------------------------------------- + +-// Null transformation, only applies formatters. No cach<E9> ++// Null transformation, only applies formatters. No cache + static + void NullXFORM(_cmsTRANSFORM* p, + const void* in, +@@ -436,7 +436,7 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, + p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); + } + +-// Gamut check, No cach<E9>, 16 bits. ++// Gamut check, No cache, 16 bits. + static + void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, + const void* in, +@@ -473,7 +473,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, + } + + +-// No gamut check, Cach<E9>, 16 bits, ++// No gamut check, Cache, 16 bits, + static + void CachedXFORM(_cmsTRANSFORM* p, + const void* in, +@@ -828,7 +828,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + p ->xform = NullFloatXFORM; + } + else { +- // Float transforms don't use cach<E9>, always are non-NULL ++ // Float transforms don't use cache, always are non-NULL + p ->xform = FloatXFORM; + } + +@@ -867,16 +867,16 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + if (*dwFlags & cmsFLAGS_NOCACHE) { + + if (*dwFlags & cmsFLAGS_GAMUTCHECK) +- p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cach<E9> ++ p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cache + else +- p ->xform = PrecalculatedXFORM; // No cach<E9>, no gamut check ++ p ->xform = PrecalculatedXFORM; // No cache, no gamut check + } + else { + + if (*dwFlags & cmsFLAGS_GAMUTCHECK) +- p ->xform = CachedXFORMGamutCheck; // Gamut check, cach<E9> ++ p ->xform = CachedXFORMGamutCheck; // Gamut check, cache + else +- p ->xform = CachedXFORM; // No gamut check, cach<E9> ++ p ->xform = CachedXFORM; // No gamut check, cache + + } + } diff --git a/third_party/lcms/0006-tag-type-confusion.patch b/third_party/lcms/0006-tag-type-confusion.patch new file mode 100644 index 0000000000000000000000000000000000000000..97d3c7f4d984d7a4175086af885d8d29d9a83898 --- /dev/null +++ b/third_party/lcms/0006-tag-type-confusion.patch @@ -0,0 +1,14 @@ +diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c +index 6549d15..5f9f08a 100644 +--- a/third_party/lcms/src/cmsio0.c ++++ b/third_party/lcms/src/cmsio0.c +@@ -719,7 +719,8 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) + for (j=0; j < Icc ->TagCount; j++) { + + if ((Icc ->TagOffsets[j] == Tag.offset) && +- (Icc ->TagSizes[j] == Tag.size)) { ++ (Icc ->TagSizes[j] == Tag.size) && ++ (Icc ->TagNames[j] == Tag.sig)) { + + Icc ->TagLinked[Icc ->TagCount] = Icc ->TagNames[j]; + } diff --git a/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch b/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch new file mode 100644 index 0000000000000000000000000000000000000000..eabf6a938d3b34c327fdc59bf41293ba7c46a15c --- /dev/null +++ b/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch @@ -0,0 +1,28 @@ +diff --git a/third_party/lcms/src/cmsnamed.c b/third_party/lcms/src/cmsnamed.c +index 9b27ca0cc..9ed4cad39 100644 +--- a/third_party/lcms/src/cmsnamed.c ++++ b/third_party/lcms/src/cmsnamed.c +@@ -540,7 +540,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn + v ->ContextID = ContextID; + + while (v -> Allocated < n){ +- if (!GrowNamedColorList(v)) return NULL; ++ if (!GrowNamedColorList(v)) { ++ cmsFreeNamedColorList(v); ++ return NULL; ++ } + } + + strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1); +@@ -571,7 +574,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) + + // For really large tables we need this + while (NewNC ->Allocated < v ->Allocated){ +- if (!GrowNamedColorList(NewNC)) return NULL; ++ if (!GrowNamedColorList(NewNC)) { ++ cmsFreeNamedColorList(NewNC); ++ return NULL; ++ } + } + + memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix)); diff --git a/third_party/lcms/0009-uninit.patch b/third_party/lcms/0009-uninit.patch new file mode 100644 index 0000000000000000000000000000000000000000..e9538c1f228c7f82543dcd943b5361760a9fec5e --- /dev/null +++ b/third_party/lcms/0009-uninit.patch @@ -0,0 +1,23 @@ +npm@npm0:~/pdfium/pdfium/third_party/lcms$ git diff src/cmstypes.c +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index cb618600a..2a0ea9448 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -2966,7 +2966,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER + { + cmsUInt32Number i, Count; + cmsNAMEDCOLORLIST* List; +- char Name[34]; ++ char Name[33]; + cmsUInt16Number PCS[3]; + + +@@ -2981,7 +2981,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER + for (i=0; i < Count; i++) { + + if (io ->Read(io, Name, 32, 1) != 1) goto Error; +- Name[33] = 0; ++ Name[32] = 0; + + if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; + diff --git a/third_party/lcms/0010-memory-leak-Type_Curve_Read.patch b/third_party/lcms/0010-memory-leak-Type_Curve_Read.patch new file mode 100644 index 0000000000000000000000000000000000000000..7edc7f9e0fc9db85a042f35bd71d2f303ba52e3c --- /dev/null +++ b/third_party/lcms/0010-memory-leak-Type_Curve_Read.patch @@ -0,0 +1,28 @@ +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 06742b5..9fe5e2a 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -1112,7 +1112,10 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm + NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL); + if (!NewGamma) return NULL; + +- if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL; ++ if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) { ++ cmsFreeToneCurve(NewGamma); ++ return NULL; ++ } + + *nItems = 1; + return NewGamma; +@@ -2350,7 +2353,10 @@ cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUI + + for (i=0; i < Data ->nEntries; i++) { + +- if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; ++ if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) { ++ cmsStageFree(CLUT); ++ return NULL; ++ } + Data ->Tab.T[i] = FROM_8_TO_16(v); + } + diff --git a/third_party/lcms/0011-memory-leak-AllocEmptyTransform.patch b/third_party/lcms/0011-memory-leak-AllocEmptyTransform.patch new file mode 100644 index 0000000000000000000000000000000000000000..332519601e0b9dbabbd0e98ff2a7293f22e277a4 --- /dev/null +++ b/third_party/lcms/0011-memory-leak-AllocEmptyTransform.patch @@ -0,0 +1,34 @@ +diff --git a/third_party/lcms/src/cmsxform.c b/third_party/lcms/src/cmsxform.c +index 9c20c49b0..b3802f0d5 100644 +--- a/third_party/lcms/src/cmsxform.c ++++ b/third_party/lcms/src/cmsxform.c +@@ -761,7 +761,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + + // Allocate needed memory + _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); +- if (!p) return NULL; ++ if (!p) { ++ cmsPipelineFree(lut); ++ return NULL; ++ } + + // Store the proposed pipeline + p->Lut = lut; +@@ -819,7 +822,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); +- _cmsFree(ContextID, p); ++ cmsDeleteTransform(p); + return NULL; + } + +@@ -849,7 +852,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + if (p ->FromInput == NULL || p ->ToOutput == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); +- _cmsFree(ContextID, p); ++ cmsDeleteTransform(p); + return NULL; + } + diff --git a/third_party/lcms/0012-memory-leak-Type_NamedColor_Read.patch b/third_party/lcms/0012-memory-leak-Type_NamedColor_Read.patch new file mode 100644 index 0000000000000000000000000000000000000000..ce9e1bf5b607d45988eab9f72a90aa142c1dba58 --- /dev/null +++ b/third_party/lcms/0012-memory-leak-Type_NamedColor_Read.patch @@ -0,0 +1,22 @@ +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 941107e1a..f2119ae0a 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -3105,7 +3105,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i + + if (nDeviceCoords > cmsMAXCHANNELS) { + cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords); +- return 0; ++ goto Error; + } + for (i=0; i < count; i++) { + +@@ -3114,7 +3114,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i + char Root[33]; + + memset(Colorant, 0, sizeof(Colorant)); +- if (io -> Read(io, Root, 32, 1) != 1) return NULL; ++ if (io -> Read(io, Root, 32, 1) != 1) goto Error; + Root[32] = 0; // To prevent exploits + + if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; diff --git a/third_party/lcms/0013-memory-leak-OptimizeByResampling.patch b/third_party/lcms/0013-memory-leak-OptimizeByResampling.patch new file mode 100644 index 0000000000000000000000000000000000000000..48645d1f0158fdd66745c6a46c447c818c3742ad --- /dev/null +++ b/third_party/lcms/0013-memory-leak-OptimizeByResampling.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c +index f885ef3..684910d 100644 +--- a/third_party/lcms/src/cmsopt.c ++++ b/third_party/lcms/src/cmsopt.c +@@ -612,7 +612,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 + + // Allocate the CLUT + CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL); +- if (CLUT == NULL) return FALSE; ++ if (CLUT == NULL) goto Error; + + // Add the CLUT to the destination LUT + if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) { diff --git a/third_party/lcms/0014-memory-leak-Type_MPEmatrix_Read.patch b/third_party/lcms/0014-memory-leak-Type_MPEmatrix_Read.patch new file mode 100644 index 0000000000000000000000000000000000000000..8cc477fb8ee1128fd9bc8dedb9d1b988096d68ae --- /dev/null +++ b/third_party/lcms/0014-memory-leak-Type_MPEmatrix_Read.patch @@ -0,0 +1,30 @@ +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 441d6bb..15199c7 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -4203,7 +4203,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io + + cmsFloat32Number v; + +- if (!_cmsReadFloat32Number(io, &v)) return NULL; ++ if (!_cmsReadFloat32Number(io, &v)) { ++ _cmsFree(self ->ContextID, Matrix); ++ _cmsFree(self ->ContextID, Offsets); ++ return NULL; ++ } + Matrix[i] = v; + } + +@@ -4212,7 +4216,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io + + cmsFloat32Number v; + +- if (!_cmsReadFloat32Number(io, &v)) return NULL; ++ if (!_cmsReadFloat32Number(io, &v)) { ++ _cmsFree(self ->ContextID, Matrix); ++ _cmsFree(self ->ContextID, Offsets); ++ return NULL; ++ } + Offsets[i] = v; + } + diff --git a/third_party/lcms/0015-cmsStageAllocMatrix-param-swap.patch b/third_party/lcms/0015-cmsStageAllocMatrix-param-swap.patch new file mode 100644 index 0000000000000000000000000000000000000000..04f854398ccf62faed6632e6731dffaf709c965a --- /dev/null +++ b/third_party/lcms/0015-cmsStageAllocMatrix-param-swap.patch @@ -0,0 +1,20 @@ +diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c +index 73e6726..9b0eb4b 100644 +--- a/third_party/lcms/src/cmslut.c ++++ b/third_party/lcms/src/cmslut.c +@@ -414,13 +414,13 @@ cmsStage* CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number R + + if (Offset != NULL) { + +- NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Cols, sizeof(cmsFloat64Number)); ++ NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Rows, sizeof(cmsFloat64Number)); + if (NewElem->Offset == NULL) { + MatrixElemTypeFree(NewMPE); + return NULL; + } + +- for (i=0; i < Cols; i++) { ++ for (i=0; i < Rows; i++) { + NewElem ->Offset[i] = Offset[i]; + } + diff --git a/third_party/lcms/0016-reject-nan.patch b/third_party/lcms/0016-reject-nan.patch new file mode 100644 index 0000000000000000000000000000000000000000..c2b5068645e4fd31b6dc328b4e1f3985aa654999 --- /dev/null +++ b/third_party/lcms/0016-reject-nan.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/src/cmsplugin.c b/third_party/lcms/src/cmsplugin.c +index 79b145d2d..29ddd9a49 100644 +--- a/third_party/lcms/src/cmsplugin.c ++++ b/third_party/lcms/src/cmsplugin.c +@@ -179,6 +179,8 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) + + tmp = _cmsAdjustEndianess32(tmp); + *n = *(cmsFloat32Number*) (void*) &tmp; ++ if (isnan(*n)) ++ return FALSE; + } + return TRUE; + } diff --git a/third_party/lcms/0017-memory-leak-ReadSegmentedCurve.patch b/third_party/lcms/0017-memory-leak-ReadSegmentedCurve.patch new file mode 100644 index 0000000000000000000000000000000000000000..472bcadf05021513aeca885e773ad7c3123c1f20 --- /dev/null +++ b/third_party/lcms/0017-memory-leak-ReadSegmentedCurve.patch @@ -0,0 +1,36 @@ +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 15199c7..04dd0c4 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -3968,7 +3968,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND + case cmsSigSampledCurveSeg: { + cmsUInt32Number Count; + +- if (!_cmsReadUInt32Number(io, &Count)) return NULL; ++ if (!_cmsReadUInt32Number(io, &Count)) goto Error; + + Segments[i].nGridPoints = Count; + Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number)); +@@ -3987,7 +3987,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND + _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String); + } +- return NULL; ++ goto Error; + + } + } +@@ -4001,7 +4001,12 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND + return Curve; + + Error: +- if (Segments) _cmsFree(self ->ContextID, Segments); ++ if (Segments) { ++ for (i=0; i < nSegments; i++) { ++ if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints); ++ } ++ _cmsFree(self ->ContextID, Segments); ++ } + return NULL; + } + diff --git a/third_party/lcms/0018-backport-c0a98d86.patch b/third_party/lcms/0018-backport-c0a98d86.patch new file mode 100644 index 0000000000000000000000000000000000000000..34b5477b343f533055ff74794757b062836061fe --- /dev/null +++ b/third_party/lcms/0018-backport-c0a98d86.patch @@ -0,0 +1,53 @@ +diff --git a/third_party/lcms/src/cmsintrp.c b/third_party/lcms/src/cmsintrp.c +index 5d5f35d..14c6856 100644 +--- a/third_party/lcms/src/cmsintrp.c ++++ b/third_party/lcms/src/cmsintrp.c +@@ -215,7 +215,7 @@ void LinLerp1D(register const cmsUInt16Number Value[], + // To prevent out of bounds indexing + cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) + { +- return v < 0.0f ? 0.0f : (v > 1.0f ? 1.0f : v); ++ return ((v < 0.0f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v); + } + + // Floating-point version of 1D interpolation +diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c +index 5f9f08a..3ed730a 100644 +--- a/third_party/lcms/src/cmsio0.c ++++ b/third_party/lcms/src/cmsio0.c +@@ -1475,6 +1475,17 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) + // If the element is already in memory, return the pointer + if (Icc -> TagPtrs[n]) { + ++ if (Icc->TagTypeHandlers[n] == NULL) goto Error; ++ ++ // Sanity check ++ BaseType = Icc->TagTypeHandlers[n]->Signature; ++ if (BaseType == 0) goto Error; ++ ++ TagDescriptor = _cmsGetTagDescriptor(Icc->ContextID, sig); ++ if (TagDescriptor == NULL) goto Error; ++ ++ if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; ++ + if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked + + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 04dd0c4..386439b 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -4297,8 +4297,12 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, + + // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number + nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans; +- for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i]; + ++ for (i = 0; i < nMaxGrids; i++) { ++ if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least ++ GridPoints[i] = (cmsUInt32Number)Dimensions8[i]; ++ } ++ + // Allocate the true CLUT + mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL); + if (mpe == NULL) goto Error; diff --git a/third_party/lcms/0019-utf8.patch b/third_party/lcms/0019-utf8.patch new file mode 100644 index 0000000000000000000000000000000000000000..351659d409a56ec8093195b1f1166a7a359434d8 --- /dev/null +++ b/third_party/lcms/0019-utf8.patch @@ -0,0 +1,98 @@ +diff --git a/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c +index 6011fb201..d53360b1f 100644 +--- a/third_party/lcms/src/cmscgats.c ++++ b/third_party/lcms/src/cmscgats.c +@@ -255,7 +255,7 @@ static PROPERTY PredefinedProperties[] = { + // needed. + + {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during +- // measurement. Allowed values are <93>black<94>, <93>white<94>, or {"na". ++ // measurement. Allowed values are "black" "white" or "na". + + {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic + +@@ -271,7 +271,7 @@ static PROPERTY PredefinedProperties[] = { + // denote the use of filters such as none, D65, Red, Green or Blue. + + {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed +- // values are {"yes<94>, <93>white<94>, <93>none<94> or <93>na<94>. ++ // values are "yes" "white" "none" or "na". + + {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the + // calculation of various data parameters (2 degree and 10 degree), CIE standard +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 5647264a6..64845e263 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -962,7 +962,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO + len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0); + + // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data +- //(see clause 4.1 for the definition of <93>aligned<94>). Because the Unicode language ++ //(see clause 4.1 for the definition of 'aligned'. Because the Unicode language + // code and Unicode count immediately follow the ASCII description, their + // alignment is not correct if the ASCII count is not a multiple of four. The + // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and +@@ -3066,10 +3066,10 @@ void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr) + //The namedColor2Type is a count value and array of structures that provide color + //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional + //device representation of the color are given. Both representations are 16-bit values. +-//The device representation corresponds to the header<92>s <93>color space of data<94> field. +-//This representation should be consistent with the <93>number of device components<94> ++//The device representation corresponds to the header's 'color space of data' field. ++//This representation should be consistent with the 'number of device components' + //field in the namedColor2Type. If this field is 0, device coordinates are not provided. +-//The PCS representation corresponds to the header<92>s PCS field. The PCS representation ++//The PCS representation corresponds to the header's PCS field. The PCS representation + //is always provided. Color names are fixed-length, 32-byte fields including null + //termination. In order to maintain maximum portability, it is strongly recommended + //that special characters of the 7-bit ASCII set not be used. +@@ -3814,7 +3814,7 @@ void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr) + // ******************************************************************************** + // + //This type represents a set of viewing condition parameters including: +-//CIE <92>absolute<92> illuminant white point tristimulus values and CIE <92>absolute<92> ++//CIE 'absolute'illuminant white point tristimulus values and CIE 'absolute' + //surround tristimulus values. + + static +@@ -3901,7 +3901,7 @@ void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr) + } + + // Each curve is stored in one or more curve segments, with break-points specified between curve segments. +-// The first curve segment always starts at <96>Infinity, and the last curve segment always ends at +Infinity. The ++// The first curve segment always starts at -Infinity, and the last curve segment always ends at +Infinity. The + // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be + // specified either in terms of a formula, or by a sampled curve. + +diff --git a/third_party/lcms/src/cmsvirt.c b/third_party/lcms/src/cmsvirt.c +index b8795be2c..9eff1f7be 100644 +--- a/third_party/lcms/src/cmsvirt.c ++++ b/third_party/lcms/src/cmsvirt.c +@@ -612,18 +612,18 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void) + + //sRGB Curves are defined by: + // +-//If R<92>sRGB,G<92>sRGB, B<92>sRGB < 0.04045 ++//If R'sRGB,G'sRGB, B'sRGB < 0.04045 + // +-// R = R<92>sRGB / 12.92 +-// G = G<92>sRGB / 12.92 +-// B = B<92>sRGB / 12.92 ++// R = R'sRGB / 12.92 ++// G = G'sRGB / 12.92 ++// B = B'sRGB / 12.92 + // + // +-//else if R<92>sRGB,G<92>sRGB, B<92>sRGB >= 0.04045 ++//else if R'sRGB,G'sRGB, B'sRGB >= 0.04045 + // +-// R = ((R<92>sRGB + 0.055) / 1.055)^2.4 +-// G = ((G<92>sRGB + 0.055) / 1.055)^2.4 +-// B = ((B<92>sRGB + 0.055) / 1.055)^2.4 ++// R = ((R'sRGB + 0.055) / 1.055)^2.4 ++// G = ((G'sRGB + 0.055) / 1.055)^2.4 ++// B = ((B'sRGB + 0.055) / 1.055)^2.4 + + static + cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) diff --git a/third_party/lcms/0020-avoid-fixed-inf.patch b/third_party/lcms/0020-avoid-fixed-inf.patch new file mode 100644 index 0000000000000000000000000000000000000000..b2397d73f9c8fbd82c839fcc17e5b401592fd951 --- /dev/null +++ b/third_party/lcms/0020-avoid-fixed-inf.patch @@ -0,0 +1,95 @@ +diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c +index e4a7e4521..23aa54402 100644 +--- a/third_party/lcms/src/cmsopt.c ++++ b/third_party/lcms/src/cmsopt.c +@@ -1546,7 +1546,7 @@ void MatShaperEval16(register const cmsUInt16Number In[], + + // This table converts from 8 bits to 1.14 after applying the curve + static +-void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) ++cmsBool FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) + { + int i; + cmsFloat32Number R, y; +@@ -1555,14 +1555,17 @@ void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) + + R = (cmsFloat32Number) (i / 255.0); + y = cmsEvalToneCurveFloat(Curve, R); ++ if (isinf(y)) ++ return FALSE; + + Table[i] = DOUBLE_TO_1FIXED14(y); + } ++ return TRUE; + } + + // This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve + static +-void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput) ++cmsBool FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput) + { + int i; + cmsFloat32Number R, Val; +@@ -1571,6 +1574,8 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi + + R = (cmsFloat32Number) (i / 16384.0); + Val = cmsEvalToneCurveFloat(Curve, R); // Val comes 0..1.0 ++ if (isinf(Val)) ++ return FALSE; + + if (Is8BitsOutput) { + +@@ -1585,6 +1590,7 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi + } + else Table[i] = _cmsQuickSaturateWord(Val * 65535.0); + } ++ return TRUE; + } + + // Compute the matrix-shaper structure +@@ -1602,13 +1608,19 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c + p -> ContextID = Dest -> ContextID; + + // Precompute tables +- FillFirstShaper(p ->Shaper1R, Curve1[0]); +- FillFirstShaper(p ->Shaper1G, Curve1[1]); +- FillFirstShaper(p ->Shaper1B, Curve1[2]); ++ if (!FillFirstShaper(p ->Shaper1R, Curve1[0])) ++ goto Error; ++ if (!FillFirstShaper(p ->Shaper1G, Curve1[1])) ++ goto Error; ++ if (!FillFirstShaper(p ->Shaper1B, Curve1[2])) ++ goto Error; + +- FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits); +- FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits); +- FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits); ++ if (!FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits)) ++ goto Error; ++ if (!FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits)) ++ goto Error; ++ if (!FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits)) ++ goto Error; + + // Convert matrix to nFixed14. Note that those values may take more than 16 bits as + for (i=0; i < 3; i++) { +@@ -1634,6 +1646,9 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c + // Fill function pointers + _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper); + return TRUE; ++ Error: ++ _cmsFree(Dest->ContextID, p); ++ return FALSE; + } + + // 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast! +@@ -1746,7 +1761,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 + *dwFlags |= cmsFLAGS_NOCACHE; + + // Setup the optimizarion routines +- SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat); ++ if (!SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat)) ++ goto Error; + } + + cmsPipelineFree(Src); diff --git a/third_party/lcms/0021-sanitize-float-read.patch b/third_party/lcms/0021-sanitize-float-read.patch new file mode 100644 index 0000000000000000000000000000000000000000..568fd0e112ba04c24b89db80cf4bf4ce36f335ff --- /dev/null +++ b/third_party/lcms/0021-sanitize-float-read.patch @@ -0,0 +1,15 @@ +diff --git a/third_party/lcms/src/cmsplugin.c b/third_party/lcms/src/cmsplugin.c +index b95befb..4ba998b 100644 +--- a/third_party/lcms/src/cmsplugin.c ++++ b/third_party/lcms/src/cmsplugin.c +@@ -182,7 +182,9 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) + if (isnan(*n)) + return FALSE; + } +- return TRUE; ++ ++ // fpclassify() required by C99 ++ return (fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL); + } + + diff --git a/third_party/lcms/0022-check-LUT-and-MPE.patch b/third_party/lcms/0022-check-LUT-and-MPE.patch new file mode 100644 index 0000000000000000000000000000000000000000..04ddac81ed0c10f59fd3a84d04a9e087268c3780 --- /dev/null +++ b/third_party/lcms/0022-check-LUT-and-MPE.patch @@ -0,0 +1,170 @@ +diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c +index 9b0eb4b54..19d43361f 100644 +--- a/third_party/lcms/src/cmslut.c ++++ b/third_party/lcms/src/cmslut.c +@@ -1255,21 +1255,39 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) + // *********************************************************************************************************** + + // This function sets up the channel count +- + static +-void BlessLUT(cmsPipeline* lut) ++cmsBool BlessLUT(cmsPipeline* lut) + { + // We can set the input/ouput channels only if we have elements. + if (lut ->Elements != NULL) { + +- cmsStage *First, *Last; ++ cmsStage* prev; ++ cmsStage* next; ++ cmsStage* First; ++ cmsStage* Last; + + First = cmsPipelineGetPtrToFirstStage(lut); + Last = cmsPipelineGetPtrToLastStage(lut); + +- if (First != NULL)lut ->InputChannels = First ->InputChannels; +- if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels; ++ if (First == NULL || Last == NULL) return FALSE; ++ ++ lut->InputChannels = First->InputChannels; ++ lut->OutputChannels = Last->OutputChannels; ++ ++ // Check chain consistency ++ prev = First; ++ next = prev->Next; ++ ++ while (next != NULL) ++ { ++ if (next->InputChannels != prev->OutputChannels) ++ return FALSE; ++ ++ next = next->Next; ++ prev = prev->Next; ++ } + } ++ return TRUE; + } + + +@@ -1331,6 +1349,7 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In + { + cmsPipeline* NewLUT; + ++ // A value of zero in channels is allowed as placeholder + if (InputChannels >= cmsMAXCHANNELS || + OutputChannels >= cmsMAXCHANNELS) return NULL; + +@@ -1348,7 +1367,11 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In + NewLUT ->Data = NewLUT; + NewLUT ->ContextID = ContextID; + +- BlessLUT(NewLUT); ++ if (!BlessLUT(NewLUT)) ++ { ++ _cmsFree(ContextID, NewLUT); ++ return NULL; ++ } + + return NewLUT; + } +@@ -1454,7 +1477,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) + + NewLUT ->SaveAs8Bits = lut ->SaveAs8Bits; + +- BlessLUT(NewLUT); ++ if (!BlessLUT(NewLUT)) ++ { ++ _cmsFree(lut->ContextID, NewLUT); ++ return NULL; ++ } ++ + return NewLUT; + } + +@@ -1491,8 +1519,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage + return FALSE; + } + +- BlessLUT(lut); +- return TRUE; ++ return BlessLUT(lut); + } + + // Unlink an element and return the pointer to it +@@ -1547,6 +1574,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag + else + cmsStageFree(Unlinked); + ++ // May fail, but we ignore it + BlessLUT(lut); + } + +@@ -1573,8 +1601,7 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) + return FALSE; + } + +- BlessLUT(l1); +- return TRUE; ++ return BlessLUT(l1); + } + + +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index e5ed06c33..0256e247b 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -1755,8 +1755,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms + if (!_cmsReadUInt8Number(io, NULL)) goto Error; + + // Do some checking +- if (InputChannels > cmsMAXCHANNELS) goto Error; +- if (OutputChannels > cmsMAXCHANNELS) goto Error; ++ if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; ++ if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; + + // Allocates an empty Pipeline + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); +@@ -2048,8 +2048,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm + if (!_cmsReadUInt8Number(io, NULL)) return NULL; + + // Do some checking +- if (InputChannels > cmsMAXCHANNELS) goto Error; +- if (OutputChannels > cmsMAXCHANNELS) goto Error; ++ if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; ++ if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; + + // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); +@@ -2486,7 +2486,10 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c + if (!_cmsReadUInt32Number(io, &offsetC)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetA)) return NULL; + +- // Allocates an empty LUT ++ if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; ++ if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; ++ ++ // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); + if (NewLUT == NULL) return NULL; + +@@ -2794,6 +2797,9 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c + if (!_cmsReadUInt8Number(io, &inputChan)) return NULL; + if (!_cmsReadUInt8Number(io, &outputChan)) return NULL; + ++ if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; ++ if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; ++ + // Padding + if (!_cmsReadUInt16Number(io, NULL)) return NULL; + +@@ -4443,6 +4449,9 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU + if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; + if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + ++ if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) return NULL; ++ if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) return NULL; ++ + // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); + if (NewLUT == NULL) return NULL; diff --git a/third_party/lcms/0023-upstream-integer-overflow-MPEmatrix_Read.patch b/third_party/lcms/0023-upstream-integer-overflow-MPEmatrix_Read.patch new file mode 100644 index 0000000000000000000000000000000000000000..70a6bb9b204e7ebdefdeff33a1d02586d9069462 --- /dev/null +++ b/third_party/lcms/0023-upstream-integer-overflow-MPEmatrix_Read.patch @@ -0,0 +1,85 @@ +diff --git a/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c +index 5720c66a7..cce4cedba 100644 +--- a/third_party/lcms/src/cmscgats.c ++++ b/third_party/lcms/src/cmscgats.c +@@ -150,23 +150,24 @@ typedef struct { + SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast + + // Parser state machine +- SYMBOL sy; // Current symbol +- int ch; // Current character ++ SYMBOL sy; // Current symbol ++ int ch; // Current character ++ ++ cmsInt32Number inum; // integer value ++ cmsFloat64Number dnum; // real value + +- int inum; // integer value +- cmsFloat64Number dnum; // real value + char id[MAXID]; // identifier + char str[MAXSTR]; // string + + // Allowed keywords & datasets. They have visibility on whole stream +- KEYVALUE* ValidKeywords; +- KEYVALUE* ValidSampleID; ++ KEYVALUE* ValidKeywords; ++ KEYVALUE* ValidSampleID; + + char* Source; // Points to loc. being parsed +- int lineno; // line counter for error reporting ++ cmsInt32Number lineno; // line counter for error reporting + + FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed +- int IncludeSP; // Include Stack Pointer ++ cmsInt32Number IncludeSP; // Include Stack Pointer + + char* MemoryBlock; // The stream if holded in memory + +@@ -568,8 +569,8 @@ void ReadReal(cmsIT8* it8, int inum) + // Exponent, example 34.00E+20 + if (toupper(it8->ch) == 'E') { + +- int e; +- int sgn; ++ cmsInt32Number e; ++ cmsInt32Number sgn; + + NextCh(it8); sgn = 1; + +@@ -587,7 +588,7 @@ void ReadReal(cmsIT8* it8, int inum) + e = 0; + while (isdigit(it8->ch)) { + +- if ((cmsFloat64Number) e * 10L < INT_MAX) ++ if ((cmsFloat64Number) e * 10L < (cmsFloat64Number) +2147483647.0) + e = e * 10 + (it8->ch - '0'); + + NextCh(it8); +@@ -777,7 +778,7 @@ void InSymbol(cmsIT8* it8) + + while (isdigit(it8->ch)) { + +- if ((long) it8->inum * 10L > (long) INT_MAX) { ++ if ((cmsFloat64Number) it8->inum * 10L > (cmsFloat64Number) +2147483647.0) { + ReadReal(it8, it8->inum); + it8->sy = SDNUM; + it8->dnum *= sign; +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 0256e247b..75f1fae32 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -4199,9 +4199,13 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io + if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + + ++ // Input and output chans may be ANY (up to 0xffff), ++ // but we choose to limit to 16 channels for now ++ if (InputChans >= cmsMAXCHANNELS) return NULL; ++ if (OutputChans >= cmsMAXCHANNELS) return NULL; ++ + nElems = InputChans * OutputChans; + +- // Input and output chans may be ANY (up to 0xffff) + Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number)); + if (Matrix == NULL) return NULL; + diff --git a/third_party/lcms/0024-verify-size-before-reading.patch b/third_party/lcms/0024-verify-size-before-reading.patch new file mode 100644 index 0000000000000000000000000000000000000000..e72e310a1b138c8053c5c6351f1c33a1b60e7c85 --- /dev/null +++ b/third_party/lcms/0024-verify-size-before-reading.patch @@ -0,0 +1,17 @@ +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 75f1fae32..4d96a1ed6 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -173,6 +173,12 @@ cmsBool ReadPositionTable(struct _cms_typehandler_struct* self, + { + cmsUInt32Number i; + cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; ++ cmsUInt32Number currentPosition; ++ ++ currentPosition = io->Tell(io); ++ // Verify there is enough space left to read two cmsUInt32Number items for Count items. ++ if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count) ++ return FALSE; + + // Let's take the offsets to each element + ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); diff --git a/third_party/lcms/0025-upstream-direct-leak-Type_MPE_Read.patch b/third_party/lcms/0025-upstream-direct-leak-Type_MPE_Read.patch new file mode 100644 index 0000000000000000000000000000000000000000..339333188ae0d33e4027f2d426497193d2f9f77d --- /dev/null +++ b/third_party/lcms/0025-upstream-direct-leak-Type_MPE_Read.patch @@ -0,0 +1,31 @@ +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 75f1fae32..f92a92822 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -4460,18 +4460,19 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); + if (NewLUT == NULL) return NULL; + +- if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL; +- +- if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) { +- if (NewLUT != NULL) cmsPipelineFree(NewLUT); +- *nItems = 0; +- return NULL; +- } ++ if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error; ++ if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error; + + // Success + *nItems = 1; + return NewLUT; + ++ // Error ++Error: ++ if (NewLUT != NULL) cmsPipelineFree(NewLUT); ++ *nItems = 0; ++ return NULL; ++ + cmsUNUSED_PARAMETER(SizeOfTag); + } + diff --git a/third_party/lcms/0026-more-unsupported-characters.patch b/third_party/lcms/0026-more-unsupported-characters.patch new file mode 100644 index 0000000000000000000000000000000000000000..a66d50ca9abb5b39704935bb83a921ff2017c3a2 --- /dev/null +++ b/third_party/lcms/0026-more-unsupported-characters.patch @@ -0,0 +1,73 @@ +diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c +index 23aa54402..abe26b93a 100644 +--- a/third_party/lcms/src/cmsopt.c ++++ b/third_party/lcms/src/cmsopt.c +@@ -1756,8 +1756,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 + _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1); + _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2); + +- // In this particular optimization, cach<E9> does not help as it takes more time to deal with +- // the cach<E9> that with the pixel handling ++ // In this particular optimization, cache does not help as it takes more time to deal with ++ // the cache that with the pixel handling + *dwFlags |= cmsFLAGS_NOCACHE; + + // Setup the optimizarion routines +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 38091f159..5ea1d2d87 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -4194,7 +4194,7 @@ cmsBool Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* + // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the + // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array + // is organized as follows: +-// array = [e11, e12, <85>, e1P, e21, e22, <85>, e2P, <85>, eQ1, eQ2, <85>, eQP, e1, e2, <85>, eQ] ++// array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ] + + static + void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +npm@npm0:~/pdfium/pdfium$ +npm@npm0:~/pdfium/pdfium$ +npm@npm0:~/pdfium/pdfium$ +npm@npm0:~/pdfium/pdfium$ git diff +diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c +index 23aa54402..abe26b93a 100644 +--- a/third_party/lcms/src/cmsopt.c ++++ b/third_party/lcms/src/cmsopt.c +@@ -1756,8 +1756,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 + _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1); + _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2); + +- // In this particular optimization, cach<E9> does not help as it takes more time to deal with +- // the cach<E9> that with the pixel handling ++ // In this particular optimization, cache does not help as it takes more time to deal with ++ // the cache that with the pixel handling + *dwFlags |= cmsFLAGS_NOCACHE; + + // Setup the optimizarion routines +diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c +index 38091f159..8b02f86ca 100644 +--- a/third_party/lcms/src/cmstypes.c ++++ b/third_party/lcms/src/cmstypes.c +@@ -4194,7 +4194,7 @@ cmsBool Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* + // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the + // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array + // is organized as follows: +-// array = [e11, e12, <85>, e1P, e21, e22, <85>, e2P, <85>, eQ1, eQ2, <85>, eQP, e1, e2, <85>, eQ] ++// array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ] + + static + void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +@@ -4713,10 +4713,10 @@ void *Type_vcgt_Read(struct _cms_typehandler_struct* self, + // Y = cX + f | X < d + + // vcgt formula is: +- // Y = (Max <96> Min) * (X ^ Gamma) + Min ++ // Y = (Max - Min) * (X ^ Gamma) + Min + + // So, the translation is +- // a = (Max <96> Min) ^ ( 1 / Gamma) ++ // a = (Max - Min) ^ ( 1 / Gamma) + // e = Min + // b=c=d=f=0 + diff --git a/third_party/lcms/0027-changes-from-beginning-of-time.patch b/third_party/lcms/0027-changes-from-beginning-of-time.patch new file mode 100644 index 0000000000000000000000000000000000000000..9eeedd8102f1a0845f405ef6787962e52e639537 --- /dev/null +++ b/third_party/lcms/0027-changes-from-beginning-of-time.patch @@ -0,0 +1,152 @@ +diff --git a/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c +index a0c25c024..55f74ede8 100644 +--- a/third_party/lcms/src/cmscgats.c ++++ b/third_party/lcms/src/cmscgats.c +@@ -38,7 +38,10 @@ + #define DEFAULT_DBL_FORMAT "%.10g" // Double formatting + + #ifdef CMS_IS_WINDOWS_ +-# include <io.h> ++//sunliang.liu modified 2010426 for wince error ++# ifndef _WIN32_WCE ++# include <io.h> ++# endif + # define DIR_CHAR '\\' + #else + # define DIR_CHAR '/' +diff --git a/third_party/lcms/src/cmsgamma.c b/third_party/lcms/src/cmsgamma.c +index eb3dd881c..6e36cf462 100644 +--- a/third_party/lcms/src/cmsgamma.c ++++ b/third_party/lcms/src/cmsgamma.c +@@ -749,14 +749,19 @@ void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve) + { + cmsContext ContextID; + +- if (Curve == NULL) return; ++ // added by Xiaochuan Liu ++ // Curve->InterpParams may be null ++ if (Curve == NULL || Curve->InterpParams == NULL) return; + + ContextID = Curve ->InterpParams->ContextID; + + _cmsFreeInterpParams(Curve ->InterpParams); ++ Curve ->InterpParams = NULL; + +- if (Curve -> Table16) ++ if (Curve -> Table16) { + _cmsFree(ContextID, Curve ->Table16); ++ Curve ->Table16 = NULL; ++ } + + if (Curve ->Segments) { + +@@ -766,20 +771,30 @@ void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve) + + if (Curve ->Segments[i].SampledPoints) { + _cmsFree(ContextID, Curve ->Segments[i].SampledPoints); ++ Curve ->Segments[i].SampledPoints = NULL; + } + +- if (Curve ->SegInterp[i] != 0) ++ if (Curve ->SegInterp[i] != 0) { + _cmsFreeInterpParams(Curve->SegInterp[i]); ++ Curve->SegInterp[i] = NULL; ++ } + } + + _cmsFree(ContextID, Curve ->Segments); ++ Curve ->Segments = NULL; + _cmsFree(ContextID, Curve ->SegInterp); ++ Curve ->SegInterp = NULL; + } + +- if (Curve -> Evals) ++ if (Curve -> Evals) { + _cmsFree(ContextID, Curve -> Evals); ++ Curve -> Evals = NULL; ++ } + +- if (Curve) _cmsFree(ContextID, Curve); ++ if (Curve) { ++ _cmsFree(ContextID, Curve); ++ Curve = NULL; ++ } + } + + // Utility function, free 3 gamma tables +@@ -799,7 +814,10 @@ void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]) + // Duplicate a gamma table + cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In) + { +- if (In == NULL || In ->Segments == NULL || In ->Table16 == NULL) return NULL; ++ // Xiaochuan Liu ++ // fix openpdf bug(mantis id:0055683, google id:360198) ++ // the function CurveSetElemTypeFree in cmslut.c also needs to check pointer ++ if (In == NULL || In ->InterpParams == NULL || In ->Segments == NULL || In ->Table16 == NULL) return NULL; + + return AllocateToneCurveStruct(In ->InterpParams ->ContextID, In ->nEntries, In ->nSegments, In ->Segments, In ->Table16); + } +diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c +index 1b026488d..cc5f89064 100644 +--- a/third_party/lcms/src/cmsio0.c ++++ b/third_party/lcms/src/cmsio0.c +@@ -479,6 +479,14 @@ cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile) + return Icc->IOhandler; + } + ++#ifdef _WIN32_WCE ++time_t wceex_time(time_t *timer); ++struct tm * wceex_gmtime(const time_t *timer); ++ ++#define time wceex_time ++#define gmtime wceex_gmtime ++#endif ++ + // Creates an empty structure holding all required parameters + cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID) + { +@@ -570,6 +578,14 @@ int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks + + // Yes, follow link + if (LinkedSig != (cmsTagSignature) 0) { ++ // fix bug mantis id#0055942 ++ // assume that TRCTag and ColorantTag can't be linked. ++ // Xiaochuan Liu 2014-04-23 ++ if ((sig == cmsSigRedTRCTag || sig == cmsSigGreenTRCTag || sig == cmsSigBlueTRCTag) && ++ (LinkedSig == cmsSigRedColorantTag || LinkedSig == cmsSigGreenColorantTag || LinkedSig == cmsSigBlueColorantTag)) ++ { ++ return n; ++ } + sig = LinkedSig; + } + +@@ -1363,6 +1379,12 @@ Error: + return 0; + } + ++#ifdef _WIN32_WCE ++int wceex_unlink(const char *filename); ++#ifndef remove ++# define remove wceex_unlink ++#endif ++#endif + + // Low-level save to disk. + cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName) +diff --git a/third_party/lcms/src/cmsio1.c b/third_party/lcms/src/cmsio1.c +index 364741c9e..4b12ae18e 100644 +--- a/third_party/lcms/src/cmsio1.c ++++ b/third_party/lcms/src/cmsio1.c +@@ -201,7 +201,11 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile) + return Lut; + + Error: +- cmsFreeToneCurve(GrayTRC); ++ // memory pointed by GrayTRC is not a new malloc memory, so don't free it here, ++ // memory pointed by GrayTRC will be freed when hProfile is closed. ++ // test file :0047776_Pocket Medicine_ The Massachusetts General Hospital Handbook of Internal Medicine-2.pdf ++ // Xiaochuan Liu, 20140421 ++ //cmsFreeToneCurve(GrayTRC); + cmsPipelineFree(Lut); + return NULL; + } diff --git a/third_party/lcms/0028-do-not-quickfloor.patch b/third_party/lcms/0028-do-not-quickfloor.patch new file mode 100644 index 0000000000000000000000000000000000000000..598917a939933a55d4b294e2c3dc8034a2397c59 --- /dev/null +++ b/third_party/lcms/0028-do-not-quickfloor.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/lcms/include/lcms2.h b/third_party/lcms/include/lcms2.h +index 739e6e1f8..c84a4fd93 100644 +--- a/third_party/lcms/include/lcms2.h ++++ b/third_party/lcms/include/lcms2.h +@@ -38,7 +38,7 @@ + // #define CMS_DONT_USE_INT64 1 + + // Uncomment this if your compiler doesn't work with fast floor function +-// #define CMS_DONT_USE_FAST_FLOOR 1 ++#define CMS_DONT_USE_FAST_FLOOR 1 + + // Uncomment this line if you want lcms to use the black point tag in profile, + // if commented, lcms will compute the black point by its own. diff --git a/third_party/lcms/0029-drop-register-keyword.patch b/third_party/lcms/0029-drop-register-keyword.patch new file mode 100644 index 0000000000000000000000000000000000000000..7680f2c4457913defbf8d79b414cab83f66ec6f5 --- /dev/null +++ b/third_party/lcms/0029-drop-register-keyword.patch @@ -0,0 +1,24 @@ +diff --git a/third_party/lcms/include/lcms2.h b/third_party/lcms/include/lcms2.h +index c84a4fd93..2bf6f2472 100644 +--- a/third_party/lcms/include/lcms2.h ++++ b/third_party/lcms/include/lcms2.h +@@ -1239,13 +1239,13 @@ CMSAPI cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe); + CMSAPI void* CMSEXPORT cmsStageData(const cmsStage* mpe); + + // Sampling +-typedef cmsInt32Number (* cmsSAMPLER16) (register const cmsUInt16Number In[], +- register cmsUInt16Number Out[], +- register void * Cargo); ++typedef cmsInt32Number (*cmsSAMPLER16)(const cmsUInt16Number In[], ++ cmsUInt16Number Out[], ++ void* Cargo); + +-typedef cmsInt32Number (* cmsSAMPLERFLOAT)(register const cmsFloat32Number In[], +- register cmsFloat32Number Out[], +- register void * Cargo); ++typedef cmsInt32Number (*cmsSAMPLERFLOAT)(const cmsFloat32Number In[], ++ cmsFloat32Number Out[], ++ void* Cargo); + + // Use this flag to prevent changes being written to destination + #define SAMPLER_INSPECT 0x01000000 diff --git a/third_party/lcms/README.pdfium b/third_party/lcms/README.pdfium new file mode 100644 index 0000000000000000000000000000000000000000..b04da7df21aedc43470e51377c95d102f42480ec --- /dev/null +++ b/third_party/lcms/README.pdfium @@ -0,0 +1,43 @@ +Name: Little CMS +URL: http://www.littlecms.com/ +Version: 2.8 +Security Critical: yes +License: MIT License + +Description: +Color Management Engine. + +Local Modifications: + +0000-cmserr-changes.patch: change LCMS memory management methods to use PDFium's. +0001-fix-include.patch: fix include in lcms2_internal.h. +0002-old-performance-fix.patch: https://codereview.chromium.org/534363002/ +0003-old-uninitialized-in-LUTevalFloat.patch: https://codereview.chromium.org/380293002/ +0004-old-uninitialized-in-LUTeval16.patch: https://codereview.chromium.org/387273002/ +0005-old-fix-e-with-tilde.patch: like https://codereview.chromium.org/2411123003/ but better. +0006-tag-type-confusion.patch: Fix a type confusion. +0008-infinite-loop-GrowNamedColorList.patch: Fix infinite loop when calling GrowNamedColorList. +0009-uninit.patch: Fix use uninitialized value and stack buffer overflow read. +0010-memory-leak-Type_Curve_Read.patch: Fix memory leak in Type_Curve_Read. +0011-memory-leak-AllocEmptyTransform.patch: Fix memory leak in AllocEmptyTransform. +0012-memory-leak-Type_NamedColor_Read.patch: Fix memory leak in Type_NamedColor_Read. +0013-memory-leak-OptimizeByResampling.patch: Fix memory leak in OptimizeByResampling. +0014-memory-leak-Type_MPEmatrix_Read.patch: Fix memory leak in MPEmatrix_Read. +0015-cmsStageAllocMatrix-param-swap.patch: Fix rows/cols swap in cmsStageAllocMatrix. +0016-reject-nan.patch: Reject NaN when reading float numbers. +0017-memory-leak-ReadSegmentedCurve.patch: Fix memory leak in ReadSegmentedCurve. +0018-backport-c0a98d86.patch: Fix several issues. Backport from upstream + https://github.com/mm2/Little-CMS/commit/c0a98d86 +0019-utf8.patch: Encode source files as utf-8. +0020-avoid-fixed-inf.patch: Avoid fixed number LUT optimization on inf values. +0021-sanitize-float-read.patch: Sanitize floating point read. Partially backport + from upstream https://github.com/mm2/Little-CMS/commit/4011a6e3 +0022-check-LUT-and-MPE.patch: check LUT consistency and sanitize MPE profiles. +0023-upstream-integer-overflow-MPEmatrix_Read.patch: fix some integer overflows. +0024-verify-size-before-reading.patch: fix OOM issue when there won't be enough + data to read anyway. +0025-upstream-direct-leak-Type_MPE_Read.patch: fix leak in cmstypes.c. +0026-more-unsupported-characters.patch: remove other unsupported characters. +0027-changes-from-beginning-of-time.patch: commented changes from initial commit. +0028-do-not-quickfloor.patch: flooring errors may cause heap-buffer-overflow. +0029-drop-register-keyword.patch: Remove deprecated 'register' keyword. diff --git a/third_party/lcms2-2.6/include/lcms2.h b/third_party/lcms/include/lcms2.h similarity index 96% rename from third_party/lcms2-2.6/include/lcms2.h rename to third_party/lcms/include/lcms2.h index 8595f70203365c448ef12f9929fd57d9d08295ed..2bf6f24725a59cb1bf2ef71494a44dcef727e809 100644 --- a/third_party/lcms2-2.6/include/lcms2.h +++ b/third_party/lcms/include/lcms2.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -23,7 +23,7 @@ // //--------------------------------------------------------------------------------- // -// Version 2.6 +// Version 2.8 // #ifndef _lcms2_H @@ -38,7 +38,7 @@ // #define CMS_DONT_USE_INT64 1 // Uncomment this if your compiler doesn't work with fast floor function -// #define CMS_DONT_USE_FAST_FLOOR 1 +#define CMS_DONT_USE_FAST_FLOOR 1 // Uncomment this line if you want lcms to use the black point tag in profile, // if commented, lcms will compute the black point by its own. @@ -75,7 +75,7 @@ extern "C" { #endif // Version/release -#define LCMS_VERSION 2060 +#define LCMS_VERSION 2080 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED @@ -173,46 +173,45 @@ typedef int cmsBool; # define CMS_IS_WINDOWS_ 1 #endif -// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here. -// you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar +// Try to detect big endian platforms. This list can be endless, so primarily rely on the configure script +// on Unix-like systems, and allow it to be set on the compiler command line using +// -DCMS_USE_BIG_ENDIAN or something similar +#ifdef CMS_USE_BIG_ENDIAN // set at compiler command line takes overall precedence -#if defined(__sgi__) || defined(__sgi) || defined(sparc) -# define CMS_USE_BIG_ENDIAN 1 -#endif +# if CMS_USE_BIG_ENDIAN == 0 +# undef CMS_USE_BIG_ENDIAN +# endif -#if defined(__s390__) || defined(__s390x__) -# define CMS_USE_BIG_ENDIAN 1 -#endif +#else // CMS_USE_BIG_ENDIAN -# ifdef TARGET_CPU_PPC -# if TARGET_CPU_PPC +# ifdef WORDS_BIGENDIAN // set by configure (or explicitly on compiler command line) +# define CMS_USE_BIG_ENDIAN 1 +# else // WORDS_BIGENDIAN +// Fall back to platform/compiler specific tests +# if defined(__sgi__) || defined(__sgi) || defined(sparc) +# define CMS_USE_BIG_ENDIAN 1 +# endif + +# if defined(__s390__) || defined(__s390x__) # define CMS_USE_BIG_ENDIAN 1 # endif -# endif -#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC) -# define CMS_USE_BIG_ENDIAN 1 -# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) -# if __BYTE_ORDER == __LITTLE_ENDIAN -// // Don't use big endian for PowerPC little endian mode -# undef CMS_USE_BIG_ENDIAN -# endif -# endif -#endif +# ifdef macintosh +# ifdef __BIG_ENDIAN__ +# define CMS_USE_BIG_ENDIAN 1 +# endif +# ifdef __LITTLE_ENDIAN__ +# undef CMS_USE_BIG_ENDIAN +# endif +# endif +# endif // WORDS_BIGENDIAN -// WORDS_BIGENDIAN takes precedence -#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN) -# define CMS_USE_BIG_ENDIAN 1 -#endif +# if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) +# define CMS_USE_BIG_ENDIAN 1 +# endif + +#endif // CMS_USE_BIG_ENDIAN -#ifdef macintosh -# ifdef __BIG_ENDIAN__ -# define CMS_USE_BIG_ENDIAN 1 -# endif -# ifdef __LITTLE_ENDIAN__ -# undef CMS_USE_BIG_ENDIAN -# endif -#endif // Calling convention -- this is hardly platform and compiler dependent #ifdef CMS_IS_WINDOWS_ @@ -221,7 +220,7 @@ typedef int cmsBool; # define CMSEXPORT __stdcall _export # define CMSAPI # else -# define CMSEXPORT _stdcall +# define CMSEXPORT __stdcall # ifdef CMS_DLL_BUILD # define CMSAPI __declspec(dllexport) # else @@ -383,7 +382,8 @@ typedef enum { cmsSigViewingCondDescTag = 0x76756564, // 'vued' cmsSigViewingConditionsTag = 0x76696577, // 'view' cmsSigVcgtTag = 0x76636774, // 'vcgt' - cmsSigMetaTag = 0x6D657461 // 'meta' + cmsSigMetaTag = 0x6D657461, // 'meta' + cmsSigArgyllArtsTag = 0x61727473 // 'arts' } cmsTagSignature; @@ -516,7 +516,7 @@ typedef enum { cmsSigNamedColorElemType = 0x6E636C20, // 'ncl ' cmsSigLabV2toV4 = 0x32203420, // '2 4 ' cmsSigLabV4toV2 = 0x34203220, // '4 2 ' - + // Identities cmsSigIdentityElemType = 0x69646E20, // 'idn ' @@ -524,7 +524,8 @@ typedef enum { cmsSigLab2FloatPCS = 0x64326C20, // 'd2l ' cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d ' cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x ' - cmsSigFloatPCS2XYZ = 0x78326420 // 'x2d ' + cmsSigFloatPCS2XYZ = 0x78326420, // 'x2d ' + cmsSigClipNegativesElemType = 0x636c7020 // 'clp ' } cmsStageSignature; @@ -655,7 +656,7 @@ typedef void* cmsHTRANSFORM; // T: Pixeltype // F: Flavor 0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla) // P: Planar? 0=Chunky, 1=Planar -// X: swap 16 bps endianess? +// X: swap 16 bps endianness? // S: Do swap? ie, BGR, KYMC // E: Extra samples // C: Channels (Samples per pixel) @@ -898,7 +899,7 @@ typedef void* cmsHTRANSFORM; #define TYPE_ARGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|SWAPFIRST_SH(1)) #define TYPE_BGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)) #define TYPE_BGRA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|SWAPFIRST_SH(1)) -#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)) +#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)) #define TYPE_CMYK_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(4)) @@ -1002,6 +1003,10 @@ typedef struct { } cmsICCViewingConditions; +// Get LittleCMS version (for shared objects) ----------------------------------------------------------------------------- + +CMSAPI int CMSEXPORT cmsGetEncodedCMMversion(void); + // Support of non-standard functions -------------------------------------------------------------------------------------- CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2); @@ -1011,7 +1016,7 @@ CMSAPI long int CMSEXPORT cmsfilelength(FILE* f); // Context handling -------------------------------------------------------------------------------------------------------- // Each context holds its owns globals and its own plug-ins. There is a global context with the id = 0 for lecacy compatibility -// though using the global context is not recomended. Proper context handling makes lcms more thread-safe. +// though using the global context is not recommended. Proper context handling makes lcms more thread-safe. typedef struct _cmsContext_struct* cmsContext; @@ -1234,13 +1239,13 @@ CMSAPI cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe); CMSAPI void* CMSEXPORT cmsStageData(const cmsStage* mpe); // Sampling -typedef cmsInt32Number (* cmsSAMPLER16) (register const cmsUInt16Number In[], - register cmsUInt16Number Out[], - register void * Cargo); +typedef cmsInt32Number (*cmsSAMPLER16)(const cmsUInt16Number In[], + cmsUInt16Number Out[], + void* Cargo); -typedef cmsInt32Number (* cmsSAMPLERFLOAT)(register const cmsFloat32Number In[], - register cmsFloat32Number Out[], - register void * Cargo); +typedef cmsInt32Number (*cmsSAMPLERFLOAT)(const cmsFloat32Number In[], + cmsFloat32Number Out[], + void* Cargo); // Use this flag to prevent changes being written to destination #define SAMPLER_INSPECT 0x01000000 @@ -1380,7 +1385,7 @@ typedef struct { typedef struct { cmsUInt32Number n; - cmsContext ContextID; + cmsContext ContextID; cmsPSEQDESC* seq; } cmsSEQ; @@ -1480,7 +1485,7 @@ CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignat CMSAPI cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace); -// Build a suitable formatter for the colorspace of this profile +// Build a suitable formatter for the colorspace of this profile. nBytes=1 means 8 bits, nBytes=2 means 16 bits. CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat); CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat); @@ -1509,12 +1514,12 @@ CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream); CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode); CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID); +CMSAPI cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile); CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io); // MD5 message digest -------------------------------------------------------------------------------------------------- CMSAPI cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile); -CMSAPI cmsBool CMSEXPORT cmsMD5computeIDExt(const void* buf, unsigned long size, unsigned char ProfileID[16]); // Profile high level funtions ------------------------------------------------------------------------------------------ @@ -1644,6 +1649,12 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID #define cmsFLAGS_CLUT_POST_LINEARIZATION 0x0001 // create postlinearization tables if possible #define cmsFLAGS_CLUT_PRE_LINEARIZATION 0x0010 // create prelinearization tables if possible +// Specific to unbounded mode +#define cmsFLAGS_NONEGATIVES 0x8000 // Prevent negative numbers in floating point transforms + +// Copy alpha channels when transforming +#define cmsFLAGS_COPY_ALPHA 0x04000000 // Alpha channels are copied on cmsDoTransform() + // Fine-tune control over number of gridpoints #define cmsFLAGS_GRIDPOINTS(n) (((n) & 0xFF) << 16) @@ -1721,12 +1732,22 @@ CMSAPI void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, void * OutputBuffer, cmsUInt32Number Size); -CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, +CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, // Deprecated const void * InputBuffer, void * OutputBuffer, cmsUInt32Number Size, cmsUInt32Number Stride); +CMSAPI void CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + cmsUInt32Number BytesPerLineIn, + cmsUInt32Number BytesPerLineOut, + cmsUInt32Number BytesPerPlaneIn, + cmsUInt32Number BytesPerPlaneOut); + CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); diff --git a/third_party/lcms2-2.6/include/lcms2_plugin.h b/third_party/lcms/include/lcms2_plugin.h similarity index 94% rename from third_party/lcms2-2.6/include/lcms2_plugin.h rename to third_party/lcms/include/lcms2_plugin.h index 0c95d1f73cd5763942cd7e886fbed63cb5e9d0af..7eda009608b9f27b7f2c1532c0ffde7364fe3f1a 100644 --- a/third_party/lcms2-2.6/include/lcms2_plugin.h +++ b/third_party/lcms/include/lcms2_plugin.h @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -128,7 +128,7 @@ struct _cms_io_handler { const void* Buffer); }; -// Endianess adjust functions +// Endianness adjust functions CMSAPI cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word); CMSAPI cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number Value); CMSAPI void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord); @@ -342,8 +342,8 @@ struct _cmstransform_struct; typedef cmsUInt8Number* (* cmsFormatter16)(register struct _cmstransform_struct* CMMcargo, register cmsUInt16Number Values[], - register cmsUInt8Number* Buffer, - register cmsUInt32Number Stride); + register cmsUInt8Number* Buffer, + register cmsUInt32Number Stride); typedef cmsUInt8Number* (* cmsFormatterFloat)(struct _cmstransform_struct* CMMcargo, cmsFloat32Number Values[], @@ -571,11 +571,28 @@ typedef struct { //---------------------------------------------------------------------------------------------------------- // Full xform -typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo, + +typedef struct { + cmsUInt32Number BytesPerLineIn; + cmsUInt32Number BytesPerLineOut; + cmsUInt32Number BytesPerPlaneIn; + cmsUInt32Number BytesPerPlaneOut; + +} cmsStride; + +typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo, // Legacy function, handles just ONE scanline. const void* InputBuffer, void* OutputBuffer, cmsUInt32Number Size, - cmsUInt32Number Stride); + cmsUInt32Number Stride); // Stride in bytes to the next plana in planar formats + + +typedef void (*_cmsTransform2Fn)(struct _cmstransform_struct *CMMcargo, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride); typedef cmsBool (* _cmsTransformFactory)(_cmsTransformFn* xform, void** UserData, @@ -585,6 +602,14 @@ typedef cmsBool (* _cmsTransformFactory)(_cmsTransformFn* xform, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags); +typedef cmsBool (* _cmsTransform2Factory)(_cmsTransform2Fn* xform, + void** UserData, + _cmsFreeUserDataFn* FreePrivateDataFn, + cmsPipeline** Lut, + cmsUInt32Number* InputFormat, + cmsUInt32Number* OutputFormat, + cmsUInt32Number* dwFlags); + // Retrieve user data as specified by the factory CMSAPI void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn); @@ -599,7 +624,10 @@ typedef struct { cmsPluginBase base; // Transform entry point - _cmsTransformFactory Factory; + union { + _cmsTransformFactory legacy_xform; + _cmsTransform2Factory xform; + } factories; } cmsPluginTransform; diff --git a/third_party/lcms/src/cmsalpha.c b/third_party/lcms/src/cmsalpha.c new file mode 100644 index 0000000000000000000000000000000000000000..7d6aa345f4b5f2ff2c378ce04b56a601d9870a79 --- /dev/null +++ b/third_party/lcms/src/cmsalpha.c @@ -0,0 +1,518 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2016 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// Alpha copy ------------------------------------------------------------------------------------------------------------------ + +// Floor to byte, taking care of saturation +cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d) +{ + d += 0.5; + if (d <= 0) return 0; + if (d >= 255.0) return 255; + + return (cmsUInt8Number) _cmsQuickFloorWord(d); +} + + +// Return the size in bytes of a given formatter +static +int trueBytesSize(cmsUInt32Number Format) +{ + int fmt_bytes = T_BYTES(Format); + + // For double, the T_BYTES field returns zero + if (fmt_bytes == 0) + return sizeof(double); + + // Otherwise, it is already correct for all formats + return fmt_bytes; +} + + +// Several format converters + +typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src); + + +// From 8 + +static +void copy8(void* dst, const void* src) +{ + memmove(dst, src, 1); +} + +static +void from8to16(void* dst, const void* src) +{ + cmsUInt8Number n = *(cmsUInt8Number*)src; + *(cmsUInt16Number*) dst = FROM_8_TO_16(n); +} + +static +void from8toFLT(void* dst, const void* src) +{ + *(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f; +} + +static +void from8toDBL(void* dst, const void* src) +{ + *(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0; +} + +static +void from8toHLF(void* dst, const void* src) +{ + cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + +// From 16 + +static +void from16to8(void* dst, const void* src) +{ + cmsUInt16Number n = *(cmsUInt16Number*)src; + *(cmsUInt8Number*) dst = FROM_16_TO_8(n); +} + +static +void copy16(void* dst, const void* src) +{ + memmove(dst, src, 2); +} + +void from16toFLT(void* dst, const void* src) +{ + *(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; +} + +void from16toDBL(void* dst, const void* src) +{ + *(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; +} + +static +void from16toHLF(void* dst, const void* src) +{ + cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + +// From Float + +static +void fromFLTto8(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); +} + +static +void fromFLTto16(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +} + +static +void copy32(void* dst, const void* src) +{ + memmove(dst, src, sizeof(cmsFloat32Number)); +} + +static +void fromFLTtoDBL(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsFloat64Number*)dst = (cmsFloat64Number)n; +} + +static +void fromFLTtoHLF(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + + +// From HALF + +static +void fromHLFto8(void* dst, const void* src) +{ + cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); + *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); +} + +static +void fromHLFto16(void* dst, const void* src) +{ + cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); + *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +} + +static +void fromHLFtoFLT(void* dst, const void* src) +{ + *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src); +} + +static +void fromHLFtoDBL(void* dst, const void* src) +{ + *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src); +} + +// From double +static +void fromDBLto8(void* dst, const void* src) +{ + cmsFloat64Number n = *(cmsFloat64Number*)src; + *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0); +} + +static +void fromDBLto16(void* dst, const void* src) +{ + cmsFloat64Number n = *(cmsFloat64Number*)src; + *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +} + +static +void fromDBLtoFLT(void* dst, const void* src) +{ + cmsFloat64Number n = *(cmsFloat64Number*)src; + *(cmsFloat32Number*)dst = (cmsFloat32Number) n; +} + +static +void fromDBLtoHLF(void* dst, const void* src) +{ + cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + +static +void copy64(void* dst, const void* src) +{ + memmove(dst, src, sizeof(cmsFloat64Number)); +} + + +// Returns the position (x or y) of the formatter in the table of functions +static +int FormatterPos(cmsUInt32Number frm) +{ + int b = T_BYTES(frm); + + if (b == 0 && T_FLOAT(frm)) + return 4; // DBL + if (b == 2 && T_FLOAT(frm)) + return 2; // HLF + if (b == 4 && T_FLOAT(frm)) + return 3; // FLT + if (b == 2 && !T_FLOAT(frm)) + return 1; // 16 + if (b == 1 && !T_FLOAT(frm)) + return 0; // 8 + + return -1; // not recognized + +} + +// Obtains a alpha-to-alpha funmction formatter +static +cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out) +{ +static cmsFormatterAlphaFn FormattersAlpha[5][5] = { + + /* from 8 */ { copy8, from8to16, from8toHLF, from8toFLT, from8toDBL }, + /* from 16*/ { from16to8, copy16, from16toHLF, from16toFLT, from16toDBL }, + /* from HLF*/ { fromHLFto8, fromHLFto16, copy16, fromHLFtoFLT, fromHLFtoDBL }, + /* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTtoHLF, copy32, fromFLTtoDBL }, + /* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLtoHLF, fromDBLtoFLT, copy64 }}; + + int in_n = FormatterPos(in); + int out_n = FormatterPos(out); + + if (in_n < 0 || out_n < 0 || in_n > 4 || out_n > 4) { + + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width"); + return NULL; + } + + return FormattersAlpha[in_n][out_n]; +} + + + +// This function computes the distance from each component to the next one in bytes. +static +void ComputeIncrementsForChunky(cmsUInt32Number Format, + cmsUInt32Number ComponentStartingOrder[], + cmsUInt32Number ComponentPointerIncrements[]) +{ + cmsUInt32Number channels[cmsMAXCHANNELS]; + int extra = T_EXTRA(Format); + int nchannels = T_CHANNELS(Format); + int total_chans = nchannels + extra; + int i; + int channelSize = trueBytesSize(Format); + int pixelSize = channelSize * total_chans; + + // Sanity check + if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) + return; + + memset(channels, 0, sizeof(channels)); + + // Separation is independent of starting point and only depends on channel size + for (i = 0; i < extra; i++) + ComponentPointerIncrements[i] = pixelSize; + + // Handle do swap + for (i = 0; i < total_chans; i++) + { + if (T_DOSWAP(Format)) { + channels[i] = total_chans - i - 1; + } + else { + channels[i] = i; + } + } + + // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 + if (T_SWAPFIRST(Format) && total_chans > 1) { + + cmsUInt32Number tmp = channels[0]; + for (i = 0; i < total_chans-1; i++) + channels[i] = channels[i + 1]; + + channels[total_chans - 1] = tmp; + } + + // Handle size + if (channelSize > 1) + for (i = 0; i < total_chans; i++) { + channels[i] *= channelSize; + } + + for (i = 0; i < extra; i++) + ComponentStartingOrder[i] = channels[i + nchannels]; +} + + + +// On planar configurations, the distance is the stride added to any non-negative +static +void ComputeIncrementsForPlanar(cmsUInt32Number Format, + cmsUInt32Number BytesPerPlane, + cmsUInt32Number ComponentStartingOrder[], + cmsUInt32Number ComponentPointerIncrements[]) +{ + cmsUInt32Number channels[cmsMAXCHANNELS]; + int extra = T_EXTRA(Format); + int nchannels = T_CHANNELS(Format); + int total_chans = nchannels + extra; + int i; + int channelSize = trueBytesSize(Format); + + // Sanity check + if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) + return; + + memset(channels, 0, sizeof(channels)); + + // Separation is independent of starting point and only depends on channel size + for (i = 0; i < extra; i++) + ComponentPointerIncrements[i] = channelSize; + + // Handle do swap + for (i = 0; i < total_chans; i++) + { + if (T_DOSWAP(Format)) { + channels[i] = total_chans - i - 1; + } + else { + channels[i] = i; + } + } + + // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 + if (T_SWAPFIRST(Format) && total_chans > 0) { + + cmsUInt32Number tmp = channels[0]; + for (i = 0; i < total_chans - 1; i++) + channels[i] = channels[i + 1]; + + channels[total_chans - 1] = tmp; + } + + // Handle size + for (i = 0; i < total_chans; i++) { + channels[i] *= BytesPerPlane; + } + + for (i = 0; i < extra; i++) + ComponentStartingOrder[i] = channels[i + nchannels]; +} + + + +// Dispatcher por chunky and planar RGB +static +void ComputeComponentIncrements(cmsUInt32Number Format, + cmsUInt32Number BytesPerPlane, + cmsUInt32Number ComponentStartingOrder[], + cmsUInt32Number ComponentPointerIncrements[]) +{ + if (T_PLANAR(Format)) { + + ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements); + } + else { + ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements); + } + +} + + + +// Handles extra channels copying alpha if requested by the flags +void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt32Number i, j, k; + cmsUInt32Number nExtra; + cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS]; + cmsUInt32Number SourceIncrements[cmsMAXCHANNELS]; + cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS]; + cmsUInt32Number DestIncrements[cmsMAXCHANNELS]; + + cmsFormatterAlphaFn copyValueFn; + + // Make sure we need some copy + if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA)) + return; + + // Exit early if in-place color-management is occurring - no need to copy extra channels to themselves. + if (p->InputFormat == p->OutputFormat && in == out) + return; + + // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time. + nExtra = T_EXTRA(p->InputFormat); + if (nExtra != T_EXTRA(p->OutputFormat)) + return; + + // Anything to do? + if (nExtra == 0) + return; + + // Compute the increments + ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements); + ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements); + + // Check for conversions 8, 16, half, float, dbl + copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat); + + if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly + + cmsUInt8Number* SourcePtr; + cmsUInt8Number* DestPtr; + + cmsUInt32Number SourceStrideIncrement = 0; + cmsUInt32Number DestStrideIncrement = 0; + + // The loop itself + for (i = 0; i < LineCount; i++) { + + // Prepare pointers for the loop + SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement; + DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement; + + for (j = 0; j < PixelsPerLine; j++) { + + copyValueFn(DestPtr, SourcePtr); + + SourcePtr += SourceIncrements[0]; + DestPtr += DestIncrements[0]; + } + + SourceStrideIncrement += Stride->BytesPerLineIn; + DestStrideIncrement += Stride->BytesPerLineOut; + } + + } + else { // General case with more than one extra channel + + cmsUInt8Number* SourcePtr[cmsMAXCHANNELS]; + cmsUInt8Number* DestPtr[cmsMAXCHANNELS]; + + cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS]; + cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS]; + + memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements)); + memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements)); + + // The loop itself + for (i = 0; i < LineCount; i++) { + + // Prepare pointers for the loop + for (j = 0; j < nExtra; j++) { + + SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j]; + DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j]; + } + + for (j = 0; j < PixelsPerLine; j++) { + + for (k = 0; k < nExtra; k++) { + + copyValueFn(DestPtr[k], SourcePtr[k]); + + SourcePtr[k] += SourceIncrements[k]; + DestPtr[k] += DestIncrements[k]; + } + } + + for (j = 0; j < nExtra; j++) { + + SourceStrideIncrements[j] += Stride->BytesPerLineIn; + DestStrideIncrements[j] += Stride->BytesPerLineOut; + } + } + } +} + + diff --git a/third_party/lcms2-2.6/src/cmscam02.c b/third_party/lcms/src/cmscam02.c similarity index 99% rename from third_party/lcms2-2.6/src/cmscam02.c rename to third_party/lcms/src/cmscam02.c index 9d874aa205149fecd5e587b0db366bd92a3c88c4..5f0ac1f878f231b1a38911d30b75d4df7728a674 100644 --- a/third_party/lcms2-2.6/src/cmscam02.c +++ b/third_party/lcms/src/cmscam02.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/third_party/lcms2-2.6/src/cmscgats.c b/third_party/lcms/src/cmscgats.c similarity index 98% rename from third_party/lcms2-2.6/src/cmscgats.c rename to third_party/lcms/src/cmscgats.c index cce4cedbad92c6b8e6902a1b7a15157ddfa62d43..55f74ede8b05db29460ea6bea65d6098401409c7 100644 --- a/third_party/lcms2-2.6/src/cmscgats.c +++ b/third_party/lcms/src/cmscgats.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -39,9 +39,9 @@ #ifdef CMS_IS_WINDOWS_ //sunliang.liu modified 2010426 for wince error -# ifndef _WIN32_WCE -# include <io.h> -# endif +# ifndef _WIN32_WCE +# include <io.h> +# endif # define DIR_CHAR '\\' #else # define DIR_CHAR '/' @@ -51,7 +51,7 @@ // Symbols typedef enum { - SNONE, + SUNDEFINED, SINUM, // Integer SDNUM, // Real SIDENT, // Identifier @@ -275,7 +275,7 @@ static PROPERTY PredefinedProperties[] = { // denote the use of filters such as none, D65, Red, Green or Blue. {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed - // values are "yes" "white" "none" or "na" + // values are "yes" "white" "none" or "na". {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the // calculation of various data parameters (2 degree and 10 degree), CIE standard @@ -328,7 +328,7 @@ static const char* PredefinedSampleID[] = { "XYZ_X", // X component of tristimulus data "XYZ_Y", // Y component of tristimulus data "XYZ_Z", // Z component of tristimulus data - "XYY_X" // x component of chromaticity data + "XYY_X", // x component of chromaticity data "XYY_Y", // y component of chromaticity data "XYY_CAPY", // Y component of tristimulus data "LAB_L", // L* component of Lab data @@ -525,7 +525,7 @@ SYMBOL BinSrchKey(const char *id) else l = x + 1; } - return SNONE; + return SUNDEFINED; } @@ -600,7 +600,7 @@ void ReadReal(cmsIT8* it8, int inum) } // Parses a float number -// This can not call directly atof because it uses locale dependant +// This can not call directly atof because it uses locale dependent // parsing, while CCMX files always use . as decimal separator static cmsFloat64Number ParseFloatNumber(const char *Buffer) @@ -710,7 +710,7 @@ void InSymbol(cmsIT8* it8) key = BinSrchKey(it8->id); - if (key == SNONE) it8->sy = SIDENT; + if (key == SUNDEFINED) it8->sy = SIDENT; else it8->sy = key; } @@ -805,11 +805,11 @@ void InSymbol(cmsIT8* it8) if (it8 ->sy == SINUM) { - sprintf(it8->id, "%d", it8->inum); + snprintf(it8->id, 127, "%d", it8->inum); } else { - sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum); + snprintf(it8->id, 127, it8 ->DoubleFormatter, it8->dnum); } k = (int) strlen(it8 ->id); @@ -1301,7 +1301,7 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID) it8->ValidKeywords = NULL; it8->ValidSampleID = NULL; - it8 -> sy = SNONE; + it8 -> sy = SUNDEFINED; it8 -> ch = ' '; it8 -> Source = NULL; it8 -> inum = 0; @@ -1367,7 +1367,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFlo cmsIT8* it8 = (cmsIT8*) hIT8; char Buffer[1024]; - sprintf(Buffer, it8->DoubleFormatter, Val); + snprintf(Buffer, 1023, it8->DoubleFormatter, Val); return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; } @@ -1377,7 +1377,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUIn cmsIT8* it8 = (cmsIT8*) hIT8; char Buffer[1024]; - sprintf(Buffer, "%u", Val); + snprintf(Buffer, 1023, "%u", Val); return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; } @@ -1821,7 +1821,7 @@ cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* } -// -------------------------------------------------------------- Higer level parsing +// -------------------------------------------------------------- Higher level parsing static cmsBool DataFormatSection(cmsIT8* it8) @@ -2124,7 +2124,7 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet) -// Init usefull pointers +// Init useful pointers static void CookPointers(cmsIT8* it8) @@ -2520,8 +2520,10 @@ int LocateSample(cmsIT8* it8, const char* cSample) for (i=0; i < t->nSamples; i++) { fld = GetDataFormat(it8, i); - if (cmsstrcasecmp(fld, cSample) == 0) - return i; + if (fld != NULL) { + if (cmsstrcasecmp(fld, cSample) == 0) + return i; + } } return -1; @@ -2579,7 +2581,7 @@ cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFl _cmsAssert(hIT8 != NULL); - sprintf(Buff, it8->DoubleFormatter, Val); + snprintf(Buff, 255, it8->DoubleFormatter, Val); return SetData(it8, row, col, Buff); } @@ -2774,3 +2776,4 @@ void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter) it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0; } + diff --git a/third_party/lcms2-2.6/src/cmscnvrt.c b/third_party/lcms/src/cmscnvrt.c similarity index 97% rename from third_party/lcms2-2.6/src/cmscnvrt.c rename to third_party/lcms/src/cmscnvrt.c index 1a93e83f90655c552e92ab0dd6488915828cd064..6c9214850ed699898c20aefd3cec144fb63c5f3a 100644 --- a/third_party/lcms2-2.6/src/cmscnvrt.c +++ b/third_party/lcms/src/cmscnvrt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -107,7 +107,7 @@ static cmsIntentsList DefaultIntents[] = { }; -// A pointer to the begining of the list +// A pointer to the beginning of the list _cmsIntentsPluginChunkType _cmsIntentsPluginChunk = { NULL }; // Duplicates the zone of memory used by the plug-in in the new context @@ -269,6 +269,9 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, { cmsMAT3 Scale, m1, m2, m3, m4; + // TODO: Follow Marc Mahy's recommendation to check if CHAD is same by using M1*M2 == M2*M1. If so, do nothing. + // TODO: Add support for ArgyllArts tag + // Adaptation state if (AdaptationState == 1.0) { @@ -288,7 +291,7 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, if (AdaptationState == 0.0) { - + m1 = *ChromaticAdaptationMatrixOut; _cmsMAT3per(&m2, &m1, &Scale); // m2 holds CHAD from output white to D50 times abs. col. scaling @@ -530,7 +533,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, cmsHPROFILE hProfile; cmsMAT3 m; cmsVEC3 off; - cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace; + cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut = cmsSigLabData, CurrentColorSpace; cmsProfileClassSignature ClassSig; cmsUInt32Number i, Intent; @@ -632,6 +635,22 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, CurrentColorSpace = ColorSpaceOut; } + // Check for non-negatives clip + if (dwFlags & cmsFLAGS_NONEGATIVES) { + + if (ColorSpaceOut == cmsSigGrayData || + ColorSpaceOut == cmsSigRgbData || + ColorSpaceOut == cmsSigCmykData) { + + cmsStage* clip = _cmsStageClipNegatives(Result->ContextID, cmsChannelsOf(ColorSpaceOut)); + if (clip == NULL) goto Error; + + if (!cmsPipelineInsertStage(Result, cmsAT_END, clip)) + goto Error; + } + + } + return Result; Error: @@ -870,7 +889,7 @@ int BlackPreservingSampler(register const cmsUInt16Number In[], register cmsUInt return TRUE; } - // Make sure to pass thru K (which now is fixed) + // Make sure to pass through K (which now is fixed) Outf[3] = LabK[3]; // Apply TAC if needed @@ -938,7 +957,7 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID, memset(&bp, 0, sizeof(bp)); // We need the input LUT of the last profile, assuming this one is responsible of - // black generation. This LUT will be seached in inverse order. + // black generation. This LUT will be searched in inverse order. bp.LabK2cmyk = _cmsReadInputLUT(hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC); if (bp.LabK2cmyk == NULL) goto Cleanup; @@ -1045,7 +1064,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) { // Force BPC for V4 profiles in perceptual and saturation - if (cmsGetProfileVersion(hProfiles[i]) >= 4.0) + if (cmsGetEncodedICCversion(hProfiles[i]) >= 0x4000000) BPC[i] = TRUE; } } diff --git a/third_party/lcms/src/cmserr.c b/third_party/lcms/src/cmserr.c new file mode 100644 index 0000000000000000000000000000000000000000..69b0550a41cb6b4f120fdccaf09eaf291e2e4c84 --- /dev/null +++ b/third_party/lcms/src/cmserr.c @@ -0,0 +1,519 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2016 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- + +#include "lcms2_internal.h" + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_system.h" + +// This function is here to help applications to prevent mixing lcms versions on header and shared objects. +int CMSEXPORT cmsGetEncodedCMMversion(void) +{ + return LCMS_VERSION; +} + +// I am so tired about incompatibilities on those functions that here are some replacements +// that hopefully would be fully portable. + +// compare two strings ignoring case +int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2) +{ + register const unsigned char *us1 = (const unsigned char *)s1, + *us2 = (const unsigned char *)s2; + + while (toupper(*us1) == toupper(*us2++)) + if (*us1++ == '\0') + return 0; + + return (toupper(*us1) - toupper(*--us2)); +} + +// long int because C99 specifies ftell in such way (7.19.9.2) +long int CMSEXPORT cmsfilelength(FILE* f) +{ + long int p , n; + + p = ftell(f); // register current file position + + if (fseek(f, 0, SEEK_END) != 0) { + return -1; + } + + n = ftell(f); + fseek(f, p, SEEK_SET); // file position restored + + return n; +} + +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin) +{ + return TRUE; +} + +// Generic allocate +void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) +{ + return FXMEM_DefaultAlloc(size); +} + +// Generic allocate & zero +void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) +{ + void* p = FXMEM_DefaultAlloc(size); + if (p) memset(p, 0, size); + return p; +} + +// Generic calloc +void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) +{ + cmsUInt32Number total = num * size; + if (total == 0 || total / size != num || total >= 512 * 1024 * 1024) + return NULL; + + return _cmsMallocZero(ContextID, num * size); +} + +// Generic reallocate +void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) +{ + return FXMEM_DefaultRealloc(Ptr, size); +} + +// Generic free memory +void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) +{ + if (Ptr != NULL) FXMEM_DefaultFree(Ptr); +} + +// Generic block duplication +void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) +{ + void* p = FXMEM_DefaultAlloc(size); + memmove(p, Org, size); + return p; +} + +_cmsMemPluginChunkType _cmsMemPluginChunk = {_cmsMalloc, _cmsMallocZero, _cmsFree, + _cmsRealloc, _cmsCalloc, _cmsDupMem + }; + +void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Duplicate + ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); + } + else { + + // To reset it, we use the default allocators, which cannot be overriden + ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; + } +} + +void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) +{ + if (Plugin == NULL) { + + memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk)); + } + else { + + ptr ->MallocPtr = Plugin -> MallocPtr; + ptr ->FreePtr = Plugin -> FreePtr; + ptr ->ReallocPtr = Plugin -> ReallocPtr; + + // Make sure we revert to defaults + ptr ->MallocZeroPtr= _cmsMallocZero; + ptr ->CallocPtr = _cmsCalloc; + ptr ->DupPtr = _cmsDupMem; + + if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; + if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; + if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; + + } +} + +// ******************************************************************************************** + +// Sub allocation takes care of many pointers of small size. The memory allocated in +// this way have be freed at once. Next function allocates a single chunk for linked list +// I prefer this method over realloc due to the big inpact on xput realloc may have if +// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms) +static +_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial) +{ + _cmsSubAllocator_chunk* chunk; + + // 20K by default + if (Initial == 0) + Initial = 20*1024; + + // Create the container + chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk)); + if (chunk == NULL) return NULL; + + // Initialize values + chunk ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial); + if (chunk ->Block == NULL) { + + // Something went wrong + _cmsFree(ContextID, chunk); + return NULL; + } + + chunk ->BlockSize = Initial; + chunk ->Used = 0; + chunk ->next = NULL; + + return chunk; +} + +// The suballocated is nothing but a pointer to the first element in the list. We also keep +// the thread ID in this structure. +_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial) +{ + _cmsSubAllocator* sub; + + // Create the container + sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator)); + if (sub == NULL) return NULL; + + sub ->ContextID = ContextID; + + sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial); + if (sub ->h == NULL) { + _cmsFree(ContextID, sub); + return NULL; + } + + return sub; +} + + +// Get rid of whole linked list +void _cmsSubAllocDestroy(_cmsSubAllocator* sub) +{ + _cmsSubAllocator_chunk *chunk, *n; + + for (chunk = sub ->h; chunk != NULL; chunk = n) { + + n = chunk->next; + if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block); + _cmsFree(sub ->ContextID, chunk); + } + + // Free the header + _cmsFree(sub ->ContextID, sub); +} + + +// Get a pointer to small memory block. +void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size) +{ + cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used; + cmsUInt8Number* ptr; + + size = _cmsALIGNMEM(size); + + // Check for memory. If there is no room, allocate a new chunk of double memory size. + if (size > Free) { + + _cmsSubAllocator_chunk* chunk; + cmsUInt32Number newSize; + + newSize = sub -> h ->BlockSize * 2; + if (newSize < size) newSize = size; + + chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize); + if (chunk == NULL) return NULL; + + // Link list + chunk ->next = sub ->h; + sub ->h = chunk; + + } + + ptr = sub -> h ->Block + sub -> h ->Used; + sub -> h -> Used += size; + + return (void*) ptr; +} + +// Duplicate in pool +void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size) +{ + void *NewPtr; + + // Dup of null pointer is also NULL + if (ptr == NULL) + return NULL; + + NewPtr = _cmsSubAlloc(s, size); + + if (ptr != NULL && NewPtr != NULL) { + memcpy(NewPtr, ptr, size); + } + + return NewPtr; +} + + + +// Error logging ****************************************************************** + +// There is no error handling at all. When a function fails, it returns proper value. +// For example, all create functions does return NULL on failure. Other return FALSE +// It may be interesting, for the developer, to know why the function is failing. +// for that reason, lcms2 does offer a logging function. This function does recive +// a ENGLISH string with some clues on what is going wrong. You can show this +// info to the end user, or just create some sort of log. +// The logging function should NOT terminate the program, as this obviously can leave +// resources. It is the programmer's responsibility to check each function return code +// to make sure it didn't fail. + +// Error messages are limited to MAX_ERROR_MESSAGE_LEN + +#define MAX_ERROR_MESSAGE_LEN 1024 + +// --------------------------------------------------------------------------------------------------------- + +// This is our default log error +static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); + +// Context0 storage, which is global +_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction }; + +// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value +// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients +void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction }; + void* from; + + if (src != NULL) { + from = src ->chunks[Logger]; + } + else { + from = &LogErrorChunk; + } + + ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType)); +} + +// The default error logger does nothing. +static +void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text) +{ + // fprintf(stderr, "[lcms]: %s\n", Text); + // fflush(stderr); + + cmsUNUSED_PARAMETER(ContextID); + cmsUNUSED_PARAMETER(ErrorCode); + cmsUNUSED_PARAMETER(Text); +} + +// Change log error, context based +void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn) +{ + _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); + + if (lhg != NULL) { + + if (Fn == NULL) + lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction; + else + lhg -> LogErrorHandler = Fn; + } +} + +// Change log error, legacy +void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn) +{ + cmsSetLogErrorHandlerTHR(NULL, Fn); +} + +// Log an error +// ErrorText is a text holding an english description of error. +void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...) +{ + va_list args; + char Buffer[MAX_ERROR_MESSAGE_LEN]; + _cmsLogErrorChunkType* lhg; + + + va_start(args, ErrorText); + vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args); + va_end(args); + + // Check for the context, if specified go there. If not, go for the global + lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); + if (lhg ->LogErrorHandler) { + lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer); + } +} + +// Utility function to print signatures +void _cmsTagSignature2String(char String[5], cmsTagSignature sig) +{ + cmsUInt32Number be; + + // Convert to big endian + be = _cmsAdjustEndianess32((cmsUInt32Number) sig); + + // Move chars + memmove(String, &be, 4); + + // Make sure of terminator + String[4] = 0; +} + +//-------------------------------------------------------------------------------------------------- + + +static +void* defMtxCreate(cmsContext id) +{ + _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); + _cmsInitMutexPrimitive(ptr_mutex); + return (void*) ptr_mutex; +} + +static +void defMtxDestroy(cmsContext id, void* mtx) +{ + _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); + _cmsFree(id, mtx); +} + +static +cmsBool defMtxLock(cmsContext id, void* mtx) +{ + cmsUNUSED_PARAMETER(id); + return _cmsLockPrimitive((_cmsMutex *) mtx) == 0; +} + +static +void defMtxUnlock(cmsContext id, void* mtx) +{ + cmsUNUSED_PARAMETER(id); + _cmsUnlockPrimitive((_cmsMutex *) mtx); +} + + + +// Pointers to memory manager functions in Context0 +_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; + +// Allocate and init mutex container. +void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; + void* from; + + if (src != NULL) { + from = src ->chunks[MutexPlugin]; + } + else { + from = &MutexChunk; + } + + ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType)); +} + +// Register new ways to transform +cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data) +{ + cmsPluginMutex* Plugin = (cmsPluginMutex*) Data; + _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (Data == NULL) { + + // No lock routines + ctx->CreateMutexPtr = NULL; + ctx->DestroyMutexPtr = NULL; + ctx->LockMutexPtr = NULL; + ctx ->UnlockMutexPtr = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL || + Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE; + + + ctx->CreateMutexPtr = Plugin->CreateMutexPtr; + ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr; + ctx ->LockMutexPtr = Plugin ->LockMutexPtr; + ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr; + + // All is ok + return TRUE; +} + +// Generic Mutex fns +void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->CreateMutexPtr == NULL) return NULL; + + return ptr ->CreateMutexPtr(ContextID); +} + +void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->DestroyMutexPtr != NULL) { + + ptr ->DestroyMutexPtr(ContextID, mtx); + } +} + +cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->LockMutexPtr == NULL) return TRUE; + + return ptr ->LockMutexPtr(ContextID, mtx); +} + +void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->UnlockMutexPtr != NULL) { + + ptr ->UnlockMutexPtr(ContextID, mtx); + } +} diff --git a/third_party/lcms2-2.6/src/cmsgamma.c b/third_party/lcms/src/cmsgamma.c similarity index 97% rename from third_party/lcms2-2.6/src/cmsgamma.c rename to third_party/lcms/src/cmsgamma.c index 97aeb7cc16c2c00698d0529fdb4c08be9555ff42..6e36cf462efeee0f990175f2f72286585f8edfbe 100644 --- a/third_party/lcms2-2.6/src/cmsgamma.c +++ b/third_party/lcms/src/cmsgamma.c @@ -23,7 +23,6 @@ // //--------------------------------------------------------------------------------- // - #include "lcms2_internal.h" // Tone curves are powerful constructs that can contain curves specified in diverse ways. @@ -568,7 +567,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu return Val; } -// Evaluate a segmented funtion for a single value. Return -1 if no valid segment found . +// Evaluate a segmented function for a single value. Return -1 if no valid segment found . // If fn type is 0, perform an interpolation on the table static cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R) @@ -750,20 +749,19 @@ void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve) { cmsContext ContextID; - // added by Xiaochuan Liu - // Curve->InterpParams may be null + // added by Xiaochuan Liu + // Curve->InterpParams may be null if (Curve == NULL || Curve->InterpParams == NULL) return; ContextID = Curve ->InterpParams->ContextID; _cmsFreeInterpParams(Curve ->InterpParams); - Curve ->InterpParams = NULL; + Curve ->InterpParams = NULL; - if (Curve -> Table16) - { + if (Curve -> Table16) { _cmsFree(ContextID, Curve ->Table16); - Curve ->Table16 = NULL; - } + Curve ->Table16 = NULL; + } if (Curve ->Segments) { @@ -773,33 +771,30 @@ void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve) if (Curve ->Segments[i].SampledPoints) { _cmsFree(ContextID, Curve ->Segments[i].SampledPoints); - Curve ->Segments[i].SampledPoints = NULL; + Curve ->Segments[i].SampledPoints = NULL; } - if (Curve ->SegInterp[i] != 0) - { + if (Curve ->SegInterp[i] != 0) { _cmsFreeInterpParams(Curve->SegInterp[i]); - Curve->SegInterp[i] = NULL; - } + Curve->SegInterp[i] = NULL; + } } _cmsFree(ContextID, Curve ->Segments); - Curve ->Segments = NULL; + Curve ->Segments = NULL; _cmsFree(ContextID, Curve ->SegInterp); - Curve ->SegInterp = NULL; + Curve ->SegInterp = NULL; } - if (Curve -> Evals) - { + if (Curve -> Evals) { _cmsFree(ContextID, Curve -> Evals); - Curve -> Evals = NULL; - } - - if (Curve) - { - _cmsFree(ContextID, Curve); - Curve = NULL; - } + Curve -> Evals = NULL; + } + + if (Curve) { + _cmsFree(ContextID, Curve); + Curve = NULL; + } } // Utility function, free 3 gamma tables @@ -818,10 +813,10 @@ void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]) // Duplicate a gamma table cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In) -{ - // Xiaochuan Liu - // fix openpdf bug(mantis id:0055683, google id:360198) - // the function CurveSetElemTypeFree in cmslut.c also needs to check pointer +{ + // Xiaochuan Liu + // fix openpdf bug(mantis id:0055683, google id:360198) + // the function CurveSetElemTypeFree in cmslut.c also needs to check pointer if (In == NULL || In ->InterpParams == NULL || In ->Segments == NULL || In ->Table16 == NULL) return NULL; return AllocateToneCurveStruct(In ->InterpParams ->ContextID, In ->nEntries, In ->nSegments, In ->Segments, In ->Table16); diff --git a/third_party/lcms2-2.6/src/cmsgmt.c b/third_party/lcms/src/cmsgmt.c similarity index 95% rename from third_party/lcms2-2.6/src/cmsgmt.c rename to third_party/lcms/src/cmsgmt.c index 1103363a786d9e8d01b6dfacfe4baf737b52e63b..b82f3beca88938d7d9ec5b28f95984ad6e3db1bc 100644 --- a/third_party/lcms2-2.6/src/cmsgmt.c +++ b/third_party/lcms/src/cmsgmt.c @@ -1,590 +1,590 @@ -//--------------------------------------------------------------------------------- -// -// Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -//--------------------------------------------------------------------------------- -// - -#include "lcms2_internal.h" - - -// Auxiliar: append a Lab identity after the given sequence of profiles -// and return the transform. Lab profile is closed, rest of profiles are kept open. -cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID, - cmsUInt32Number nProfiles, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat, - const cmsUInt32Number Intents[], - const cmsHPROFILE hProfiles[], - const cmsBool BPC[], - const cmsFloat64Number AdaptationStates[], - cmsUInt32Number dwFlags) -{ - cmsHTRANSFORM xform; - cmsHPROFILE hLab; - cmsHPROFILE ProfileList[256]; - cmsBool BPCList[256]; - cmsFloat64Number AdaptationList[256]; - cmsUInt32Number IntentList[256]; - cmsUInt32Number i; - - // This is a rather big number and there is no need of dynamic memory - // since we are adding a profile, 254 + 1 = 255 and this is the limit - if (nProfiles > 254) return NULL; - - // The output space - hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); - if (hLab == NULL) return NULL; - - // Create a copy of parameters - for (i=0; i < nProfiles; i++) { - - ProfileList[i] = hProfiles[i]; - BPCList[i] = BPC[i]; - AdaptationList[i] = AdaptationStates[i]; - IntentList[i] = Intents[i]; - } - - // Place Lab identity at chain's end. - ProfileList[nProfiles] = hLab; - BPCList[nProfiles] = 0; - AdaptationList[nProfiles] = 1.0; - IntentList[nProfiles] = INTENT_RELATIVE_COLORIMETRIC; - - // Create the transform - xform = cmsCreateExtendedTransform(ContextID, nProfiles + 1, ProfileList, - BPCList, - IntentList, - AdaptationList, - NULL, 0, - InputFormat, - OutputFormat, - dwFlags); - - cmsCloseProfile(hLab); - - return xform; -} - - -// Compute K -> L* relationship. Flags may include black point compensation. In this case, -// the relationship is assumed from the profile with BPC to a black point zero. -static -cmsToneCurve* ComputeKToLstar(cmsContext ContextID, - cmsUInt32Number nPoints, - cmsUInt32Number nProfiles, - const cmsUInt32Number Intents[], - const cmsHPROFILE hProfiles[], - const cmsBool BPC[], - const cmsFloat64Number AdaptationStates[], - cmsUInt32Number dwFlags) -{ - cmsToneCurve* out = NULL; - cmsUInt32Number i; - cmsHTRANSFORM xform; - cmsCIELab Lab; - cmsFloat32Number cmyk[4]; - cmsFloat32Number* SampledPoints; - - xform = _cmsChain2Lab(ContextID, nProfiles, TYPE_CMYK_FLT, TYPE_Lab_DBL, Intents, hProfiles, BPC, AdaptationStates, dwFlags); - if (xform == NULL) return NULL; - - SampledPoints = (cmsFloat32Number*) _cmsCalloc(ContextID, nPoints, sizeof(cmsFloat32Number)); - if (SampledPoints == NULL) goto Error; - - for (i=0; i < nPoints; i++) { - - cmyk[0] = 0; - cmyk[1] = 0; - cmyk[2] = 0; - cmyk[3] = (cmsFloat32Number) ((i * 100.0) / (nPoints-1)); - - cmsDoTransform(xform, cmyk, &Lab, 1); - SampledPoints[i]= (cmsFloat32Number) (1.0 - Lab.L / 100.0); // Negate K for easier operation - } - - out = cmsBuildTabulatedToneCurveFloat(ContextID, nPoints, SampledPoints); - -Error: - - cmsDeleteTransform(xform); - if (SampledPoints) _cmsFree(ContextID, SampledPoints); - - return out; -} - - -// Compute Black tone curve on a CMYK -> CMYK transform. This is done by -// using the proof direction on both profiles to find K->L* relationship -// then joining both curves. dwFlags may include black point compensation. -cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID, - cmsUInt32Number nPoints, - cmsUInt32Number nProfiles, - const cmsUInt32Number Intents[], - const cmsHPROFILE hProfiles[], - const cmsBool BPC[], - const cmsFloat64Number AdaptationStates[], - cmsUInt32Number dwFlags) -{ - cmsToneCurve *in, *out, *KTone; - - // Make sure CMYK -> CMYK - if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData || - cmsGetColorSpace(hProfiles[nProfiles-1])!= cmsSigCmykData) return NULL; - - - // Make sure last is an output profile - if (cmsGetDeviceClass(hProfiles[nProfiles - 1]) != cmsSigOutputClass) return NULL; - - // Create individual curves. BPC works also as each K to L* is - // computed as a BPC to zero black point in case of L* - in = ComputeKToLstar(ContextID, nPoints, nProfiles - 1, Intents, hProfiles, BPC, AdaptationStates, dwFlags); - if (in == NULL) return NULL; - - out = ComputeKToLstar(ContextID, nPoints, 1, - Intents + (nProfiles - 1), - &hProfiles [nProfiles - 1], - BPC + (nProfiles - 1), - AdaptationStates + (nProfiles - 1), - dwFlags); - if (out == NULL) { - cmsFreeToneCurve(in); - return NULL; - } - - // Build the relationship. This effectively limits the maximum accuracy to 16 bits, but - // since this is used on black-preserving LUTs, we are not loosing accuracy in any case - KTone = cmsJoinToneCurve(ContextID, in, out, nPoints); - - // Get rid of components - cmsFreeToneCurve(in); cmsFreeToneCurve(out); - - // Something went wrong... - if (KTone == NULL) return NULL; - - // Make sure it is monotonic - if (!cmsIsToneCurveMonotonic(KTone)) { - cmsFreeToneCurve(KTone); - return NULL; - } - - return KTone; -} - - -// Gamut LUT Creation ----------------------------------------------------------------------------------------- - -// Used by gamut & softproofing - -typedef struct { - - cmsHTRANSFORM hInput; // From whatever input color space. 16 bits to DBL - cmsHTRANSFORM hForward, hReverse; // Transforms going from Lab to colorant and back - cmsFloat64Number Thereshold; // The thereshold after which is considered out of gamut - - } GAMUTCHAIN; - -// This sampler does compute gamut boundaries by comparing original -// values with a transform going back and forth. Values above ERR_THERESHOLD -// of maximum are considered out of gamut. - -#define ERR_THERESHOLD 5 - - -static -int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) -{ - GAMUTCHAIN* t = (GAMUTCHAIN* ) Cargo; - cmsCIELab LabIn1, LabOut1; - cmsCIELab LabIn2, LabOut2; - cmsUInt16Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS]; - cmsFloat64Number dE1, dE2, ErrorRatio; - - // Assume in-gamut by default. - ErrorRatio = 1.0; - - // Convert input to Lab - cmsDoTransform(t -> hInput, In, &LabIn1, 1); - - // converts from PCS to colorant. This always - // does return in-gamut values, - cmsDoTransform(t -> hForward, &LabIn1, Proof, 1); - - // Now, do the inverse, from colorant to PCS. - cmsDoTransform(t -> hReverse, Proof, &LabOut1, 1); - - memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab)); - - // Try again, but this time taking Check as input - cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1); - cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1); - - // Take difference of direct value - dE1 = cmsDeltaE(&LabIn1, &LabOut1); - - // Take difference of converted value - dE2 = cmsDeltaE(&LabIn2, &LabOut2); - - - // if dE1 is small and dE2 is small, value is likely to be in gamut - if (dE1 < t->Thereshold && dE2 < t->Thereshold) - Out[0] = 0; - else { - - // if dE1 is small and dE2 is big, undefined. Assume in gamut - if (dE1 < t->Thereshold && dE2 > t->Thereshold) - Out[0] = 0; - else - // dE1 is big and dE2 is small, clearly out of gamut - if (dE1 > t->Thereshold && dE2 < t->Thereshold) - Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5); - else { - - // dE1 is big and dE2 is also big, could be due to perceptual mapping - // so take error ratio - if (dE2 == 0.0) - ErrorRatio = dE1; - else - ErrorRatio = dE1 / dE2; - - if (ErrorRatio > t->Thereshold) - Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5); - else - Out[0] = 0; - } - } - - - return TRUE; -} - -// Does compute a gamut LUT going back and forth across pcs -> relativ. colorimetric intent -> pcs -// the dE obtained is then annotated on the LUT. Values truely out of gamut are clipped to dE = 0xFFFE -// and values changed are supposed to be handled by any gamut remapping, so, are out of gamut as well. -// -// **WARNING: This algorithm does assume that gamut remapping algorithms does NOT move in-gamut colors, -// of course, many perceptual and saturation intents does not work in such way, but relativ. ones should. - -cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, - cmsHPROFILE hProfiles[], - cmsBool BPC[], - cmsUInt32Number Intents[], - cmsFloat64Number AdaptationStates[], - cmsUInt32Number nGamutPCSposition, - cmsHPROFILE hGamut) -{ - cmsHPROFILE hLab; - cmsPipeline* Gamut; - cmsStage* CLUT; - cmsUInt32Number dwFormat; - GAMUTCHAIN Chain; - int nChannels, nGridpoints; - cmsColorSpaceSignature ColorSpace; - cmsUInt32Number i; - cmsHPROFILE ProfileList[256]; - cmsBool BPCList[256]; - cmsFloat64Number AdaptationList[256]; - cmsUInt32Number IntentList[256]; - - memset(&Chain, 0, sizeof(GAMUTCHAIN)); - - - if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) { - cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition); - return NULL; - } - - hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); - if (hLab == NULL) return NULL; - - - // The figure of merit. On matrix-shaper profiles, should be almost zero as - // the conversion is pretty exact. On LUT based profiles, different resolutions - // of input and output CLUT may result in differences. - - if (cmsIsMatrixShaper(hGamut)) { - - Chain.Thereshold = 1.0; - } - else { - Chain.Thereshold = ERR_THERESHOLD; - } - - - // Create a copy of parameters - for (i=0; i < nGamutPCSposition; i++) { - ProfileList[i] = hProfiles[i]; - BPCList[i] = BPC[i]; - AdaptationList[i] = AdaptationStates[i]; - IntentList[i] = Intents[i]; - } - - // Fill Lab identity - ProfileList[nGamutPCSposition] = hLab; - BPCList[nGamutPCSposition] = 0; - AdaptationList[nGamutPCSposition] = 1.0; - IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC; - - - ColorSpace = cmsGetColorSpace(hGamut); - - nChannels = cmsChannelsOf(ColorSpace); - nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC); - dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2)); - - // 16 bits to Lab double - Chain.hInput = cmsCreateExtendedTransform(ContextID, - nGamutPCSposition + 1, - ProfileList, - BPCList, - IntentList, - AdaptationList, - NULL, 0, - dwFormat, TYPE_Lab_DBL, - cmsFLAGS_NOCACHE); - - - // Does create the forward step. Lab double to device - dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2)); - Chain.hForward = cmsCreateTransformTHR(ContextID, - hLab, TYPE_Lab_DBL, - hGamut, dwFormat, - INTENT_RELATIVE_COLORIMETRIC, - cmsFLAGS_NOCACHE); - - // Does create the backwards step - Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat, - hLab, TYPE_Lab_DBL, - INTENT_RELATIVE_COLORIMETRIC, - cmsFLAGS_NOCACHE); - - - // All ok? - if (Chain.hInput && Chain.hForward && Chain.hReverse) { - - // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing - // dE when doing a transform back and forth on the colorimetric intent. - - Gamut = cmsPipelineAlloc(ContextID, 3, 1); - if (Gamut != NULL) { - - CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL); - if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) { - cmsPipelineFree(Gamut); - Gamut = NULL; - } - else { - cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0); - } - } - } - else - Gamut = NULL; // Didn't work... - - // Free all needed stuff. - if (Chain.hInput) cmsDeleteTransform(Chain.hInput); - if (Chain.hForward) cmsDeleteTransform(Chain.hForward); - if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse); - if (hLab) cmsCloseProfile(hLab); - - // And return computed hull - return Gamut; -} - -// Total Area Coverage estimation ---------------------------------------------------------------- - -typedef struct { - cmsUInt32Number nOutputChans; - cmsHTRANSFORM hRoundTrip; - cmsFloat32Number MaxTAC; - cmsFloat32Number MaxInput[cmsMAXCHANNELS]; - -} cmsTACestimator; - - -// This callback just accounts the maximum ink dropped in the given node. It does not populate any -// memory, as the destination table is NULL. Its only purpose it to know the global maximum. -static -int EstimateTAC(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo) -{ - cmsTACestimator* bp = (cmsTACestimator*) Cargo; - cmsFloat32Number RoundTrip[cmsMAXCHANNELS]; - cmsUInt32Number i; - cmsFloat32Number Sum; - - - // Evaluate the xform - cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1); - - // All all amounts of ink - for (Sum=0, i=0; i < bp ->nOutputChans; i++) - Sum += RoundTrip[i]; - - // If above maximum, keep track of input values - if (Sum > bp ->MaxTAC) { - - bp ->MaxTAC = Sum; - - for (i=0; i < bp ->nOutputChans; i++) { - bp ->MaxInput[i] = In[i]; - } - } - - return TRUE; - - cmsUNUSED_PARAMETER(Out); -} - - -// Detect Total area coverage of the profile -cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile) -{ - cmsTACestimator bp; - cmsUInt32Number dwFormatter; - cmsUInt32Number GridPoints[MAX_INPUT_DIMENSIONS]; - cmsHPROFILE hLab; - cmsContext ContextID = cmsGetProfileContextID(hProfile); - - // TAC only works on output profiles - if (cmsGetDeviceClass(hProfile) != cmsSigOutputClass) { - return 0; - } - - // Create a fake formatter for result - dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE); - - bp.nOutputChans = T_CHANNELS(dwFormatter); - bp.MaxTAC = 0; // Initial TAC is 0 - - // for safety - if (bp.nOutputChans >= cmsMAXCHANNELS) return 0; - - hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); - if (hLab == NULL) return 0; - // Setup a roundtrip on perceptual intent in output profile for TAC estimation - bp.hRoundTrip = cmsCreateTransformTHR(ContextID, hLab, TYPE_Lab_16, - hProfile, dwFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE); - - cmsCloseProfile(hLab); - if (bp.hRoundTrip == NULL) return 0; - - // For L* we only need black and white. For C* we need many points - GridPoints[0] = 6; - GridPoints[1] = 74; - GridPoints[2] = 74; - - - if (!cmsSliceSpace16(3, GridPoints, EstimateTAC, &bp)) { - bp.MaxTAC = 0; - } - - cmsDeleteTransform(bp.hRoundTrip); - - // Results in % - return bp.MaxTAC; -} - - -// Carefully, clamp on CIELab space. - -cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab, - double amax, double amin, - double bmax, double bmin) -{ - - // Whole Luma surface to zero - - if (Lab -> L < 0) { - - Lab-> L = Lab->a = Lab-> b = 0.0; - return FALSE; - } - - // Clamp white, DISCARD HIGHLIGHTS. This is done - // in such way because icc spec doesn't allow the - // use of L>100 as a highlight means. - - if (Lab->L > 100) - Lab -> L = 100; - - // Check out gamut prism, on a, b faces - - if (Lab -> a < amin || Lab->a > amax|| - Lab -> b < bmin || Lab->b > bmax) { - - cmsCIELCh LCh; - double h, slope; - - // Falls outside a, b limits. Transports to LCh space, - // and then do the clipping - - - if (Lab -> a == 0.0) { // Is hue exactly 90? - - // atan will not work, so clamp here - Lab -> b = Lab->b < 0 ? bmin : bmax; - return TRUE; - } - - cmsLab2LCh(&LCh, Lab); - - slope = Lab -> b / Lab -> a; - h = LCh.h; - - // There are 4 zones - - if ((h >= 0. && h < 45.) || - (h >= 315 && h <= 360.)) { - - // clip by amax - Lab -> a = amax; - Lab -> b = amax * slope; - } - else - if (h >= 45. && h < 135.) - { - // clip by bmax - Lab -> b = bmax; - Lab -> a = bmax / slope; - } - else - if (h >= 135. && h < 225.) { - // clip by amin - Lab -> a = amin; - Lab -> b = amin * slope; - - } - else - if (h >= 225. && h < 315.) { - // clip by bmin - Lab -> b = bmin; - Lab -> a = bmin / slope; - } - else { - cmsSignalError(0, cmsERROR_RANGE, "Invalid angle"); - return FALSE; - } - - } - - return TRUE; -} +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2016 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// Auxiliary: append a Lab identity after the given sequence of profiles +// and return the transform. Lab profile is closed, rest of profiles are kept open. +cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsHTRANSFORM xform; + cmsHPROFILE hLab; + cmsHPROFILE ProfileList[256]; + cmsBool BPCList[256]; + cmsFloat64Number AdaptationList[256]; + cmsUInt32Number IntentList[256]; + cmsUInt32Number i; + + // This is a rather big number and there is no need of dynamic memory + // since we are adding a profile, 254 + 1 = 255 and this is the limit + if (nProfiles > 254) return NULL; + + // The output space + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + if (hLab == NULL) return NULL; + + // Create a copy of parameters + for (i=0; i < nProfiles; i++) { + + ProfileList[i] = hProfiles[i]; + BPCList[i] = BPC[i]; + AdaptationList[i] = AdaptationStates[i]; + IntentList[i] = Intents[i]; + } + + // Place Lab identity at chain's end. + ProfileList[nProfiles] = hLab; + BPCList[nProfiles] = 0; + AdaptationList[nProfiles] = 1.0; + IntentList[nProfiles] = INTENT_RELATIVE_COLORIMETRIC; + + // Create the transform + xform = cmsCreateExtendedTransform(ContextID, nProfiles + 1, ProfileList, + BPCList, + IntentList, + AdaptationList, + NULL, 0, + InputFormat, + OutputFormat, + dwFlags); + + cmsCloseProfile(hLab); + + return xform; +} + + +// Compute K -> L* relationship. Flags may include black point compensation. In this case, +// the relationship is assumed from the profile with BPC to a black point zero. +static +cmsToneCurve* ComputeKToLstar(cmsContext ContextID, + cmsUInt32Number nPoints, + cmsUInt32Number nProfiles, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsToneCurve* out = NULL; + cmsUInt32Number i; + cmsHTRANSFORM xform; + cmsCIELab Lab; + cmsFloat32Number cmyk[4]; + cmsFloat32Number* SampledPoints; + + xform = _cmsChain2Lab(ContextID, nProfiles, TYPE_CMYK_FLT, TYPE_Lab_DBL, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (xform == NULL) return NULL; + + SampledPoints = (cmsFloat32Number*) _cmsCalloc(ContextID, nPoints, sizeof(cmsFloat32Number)); + if (SampledPoints == NULL) goto Error; + + for (i=0; i < nPoints; i++) { + + cmyk[0] = 0; + cmyk[1] = 0; + cmyk[2] = 0; + cmyk[3] = (cmsFloat32Number) ((i * 100.0) / (nPoints-1)); + + cmsDoTransform(xform, cmyk, &Lab, 1); + SampledPoints[i]= (cmsFloat32Number) (1.0 - Lab.L / 100.0); // Negate K for easier operation + } + + out = cmsBuildTabulatedToneCurveFloat(ContextID, nPoints, SampledPoints); + +Error: + + cmsDeleteTransform(xform); + if (SampledPoints) _cmsFree(ContextID, SampledPoints); + + return out; +} + + +// Compute Black tone curve on a CMYK -> CMYK transform. This is done by +// using the proof direction on both profiles to find K->L* relationship +// then joining both curves. dwFlags may include black point compensation. +cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID, + cmsUInt32Number nPoints, + cmsUInt32Number nProfiles, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsToneCurve *in, *out, *KTone; + + // Make sure CMYK -> CMYK + if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData || + cmsGetColorSpace(hProfiles[nProfiles-1])!= cmsSigCmykData) return NULL; + + + // Make sure last is an output profile + if (cmsGetDeviceClass(hProfiles[nProfiles - 1]) != cmsSigOutputClass) return NULL; + + // Create individual curves. BPC works also as each K to L* is + // computed as a BPC to zero black point in case of L* + in = ComputeKToLstar(ContextID, nPoints, nProfiles - 1, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (in == NULL) return NULL; + + out = ComputeKToLstar(ContextID, nPoints, 1, + Intents + (nProfiles - 1), + &hProfiles [nProfiles - 1], + BPC + (nProfiles - 1), + AdaptationStates + (nProfiles - 1), + dwFlags); + if (out == NULL) { + cmsFreeToneCurve(in); + return NULL; + } + + // Build the relationship. This effectively limits the maximum accuracy to 16 bits, but + // since this is used on black-preserving LUTs, we are not losing accuracy in any case + KTone = cmsJoinToneCurve(ContextID, in, out, nPoints); + + // Get rid of components + cmsFreeToneCurve(in); cmsFreeToneCurve(out); + + // Something went wrong... + if (KTone == NULL) return NULL; + + // Make sure it is monotonic + if (!cmsIsToneCurveMonotonic(KTone)) { + cmsFreeToneCurve(KTone); + return NULL; + } + + return KTone; +} + + +// Gamut LUT Creation ----------------------------------------------------------------------------------------- + +// Used by gamut & softproofing + +typedef struct { + + cmsHTRANSFORM hInput; // From whatever input color space. 16 bits to DBL + cmsHTRANSFORM hForward, hReverse; // Transforms going from Lab to colorant and back + cmsFloat64Number Thereshold; // The thereshold after which is considered out of gamut + + } GAMUTCHAIN; + +// This sampler does compute gamut boundaries by comparing original +// values with a transform going back and forth. Values above ERR_THERESHOLD +// of maximum are considered out of gamut. + +#define ERR_THERESHOLD 5 + + +static +int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + GAMUTCHAIN* t = (GAMUTCHAIN* ) Cargo; + cmsCIELab LabIn1, LabOut1; + cmsCIELab LabIn2, LabOut2; + cmsUInt16Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS]; + cmsFloat64Number dE1, dE2, ErrorRatio; + + // Assume in-gamut by default. + ErrorRatio = 1.0; + + // Convert input to Lab + cmsDoTransform(t -> hInput, In, &LabIn1, 1); + + // converts from PCS to colorant. This always + // does return in-gamut values, + cmsDoTransform(t -> hForward, &LabIn1, Proof, 1); + + // Now, do the inverse, from colorant to PCS. + cmsDoTransform(t -> hReverse, Proof, &LabOut1, 1); + + memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab)); + + // Try again, but this time taking Check as input + cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1); + cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1); + + // Take difference of direct value + dE1 = cmsDeltaE(&LabIn1, &LabOut1); + + // Take difference of converted value + dE2 = cmsDeltaE(&LabIn2, &LabOut2); + + + // if dE1 is small and dE2 is small, value is likely to be in gamut + if (dE1 < t->Thereshold && dE2 < t->Thereshold) + Out[0] = 0; + else { + + // if dE1 is small and dE2 is big, undefined. Assume in gamut + if (dE1 < t->Thereshold && dE2 > t->Thereshold) + Out[0] = 0; + else + // dE1 is big and dE2 is small, clearly out of gamut + if (dE1 > t->Thereshold && dE2 < t->Thereshold) + Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5); + else { + + // dE1 is big and dE2 is also big, could be due to perceptual mapping + // so take error ratio + if (dE2 == 0.0) + ErrorRatio = dE1; + else + ErrorRatio = dE1 / dE2; + + if (ErrorRatio > t->Thereshold) + Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5); + else + Out[0] = 0; + } + } + + + return TRUE; +} + +// Does compute a gamut LUT going back and forth across pcs -> relativ. colorimetric intent -> pcs +// the dE obtained is then annotated on the LUT. Values truly out of gamut are clipped to dE = 0xFFFE +// and values changed are supposed to be handled by any gamut remapping, so, are out of gamut as well. +// +// **WARNING: This algorithm does assume that gamut remapping algorithms does NOT move in-gamut colors, +// of course, many perceptual and saturation intents does not work in such way, but relativ. ones should. + +cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number nGamutPCSposition, + cmsHPROFILE hGamut) +{ + cmsHPROFILE hLab; + cmsPipeline* Gamut; + cmsStage* CLUT; + cmsUInt32Number dwFormat; + GAMUTCHAIN Chain; + int nChannels, nGridpoints; + cmsColorSpaceSignature ColorSpace; + cmsUInt32Number i; + cmsHPROFILE ProfileList[256]; + cmsBool BPCList[256]; + cmsFloat64Number AdaptationList[256]; + cmsUInt32Number IntentList[256]; + + memset(&Chain, 0, sizeof(GAMUTCHAIN)); + + + if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition); + return NULL; + } + + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + if (hLab == NULL) return NULL; + + + // The figure of merit. On matrix-shaper profiles, should be almost zero as + // the conversion is pretty exact. On LUT based profiles, different resolutions + // of input and output CLUT may result in differences. + + if (cmsIsMatrixShaper(hGamut)) { + + Chain.Thereshold = 1.0; + } + else { + Chain.Thereshold = ERR_THERESHOLD; + } + + + // Create a copy of parameters + for (i=0; i < nGamutPCSposition; i++) { + ProfileList[i] = hProfiles[i]; + BPCList[i] = BPC[i]; + AdaptationList[i] = AdaptationStates[i]; + IntentList[i] = Intents[i]; + } + + // Fill Lab identity + ProfileList[nGamutPCSposition] = hLab; + BPCList[nGamutPCSposition] = 0; + AdaptationList[nGamutPCSposition] = 1.0; + IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC; + + + ColorSpace = cmsGetColorSpace(hGamut); + + nChannels = cmsChannelsOf(ColorSpace); + nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC); + dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2)); + + // 16 bits to Lab double + Chain.hInput = cmsCreateExtendedTransform(ContextID, + nGamutPCSposition + 1, + ProfileList, + BPCList, + IntentList, + AdaptationList, + NULL, 0, + dwFormat, TYPE_Lab_DBL, + cmsFLAGS_NOCACHE); + + + // Does create the forward step. Lab double to device + dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2)); + Chain.hForward = cmsCreateTransformTHR(ContextID, + hLab, TYPE_Lab_DBL, + hGamut, dwFormat, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE); + + // Does create the backwards step + Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat, + hLab, TYPE_Lab_DBL, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE); + + + // All ok? + if (Chain.hInput && Chain.hForward && Chain.hReverse) { + + // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing + // dE when doing a transform back and forth on the colorimetric intent. + + Gamut = cmsPipelineAlloc(ContextID, 3, 1); + if (Gamut != NULL) { + + CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL); + if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) { + cmsPipelineFree(Gamut); + Gamut = NULL; + } + else { + cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0); + } + } + } + else + Gamut = NULL; // Didn't work... + + // Free all needed stuff. + if (Chain.hInput) cmsDeleteTransform(Chain.hInput); + if (Chain.hForward) cmsDeleteTransform(Chain.hForward); + if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse); + if (hLab) cmsCloseProfile(hLab); + + // And return computed hull + return Gamut; +} + +// Total Area Coverage estimation ---------------------------------------------------------------- + +typedef struct { + cmsUInt32Number nOutputChans; + cmsHTRANSFORM hRoundTrip; + cmsFloat32Number MaxTAC; + cmsFloat32Number MaxInput[cmsMAXCHANNELS]; + +} cmsTACestimator; + + +// This callback just accounts the maximum ink dropped in the given node. It does not populate any +// memory, as the destination table is NULL. Its only purpose it to know the global maximum. +static +int EstimateTAC(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo) +{ + cmsTACestimator* bp = (cmsTACestimator*) Cargo; + cmsFloat32Number RoundTrip[cmsMAXCHANNELS]; + cmsUInt32Number i; + cmsFloat32Number Sum; + + + // Evaluate the xform + cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1); + + // All all amounts of ink + for (Sum=0, i=0; i < bp ->nOutputChans; i++) + Sum += RoundTrip[i]; + + // If above maximum, keep track of input values + if (Sum > bp ->MaxTAC) { + + bp ->MaxTAC = Sum; + + for (i=0; i < bp ->nOutputChans; i++) { + bp ->MaxInput[i] = In[i]; + } + } + + return TRUE; + + cmsUNUSED_PARAMETER(Out); +} + + +// Detect Total area coverage of the profile +cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile) +{ + cmsTACestimator bp; + cmsUInt32Number dwFormatter; + cmsUInt32Number GridPoints[MAX_INPUT_DIMENSIONS]; + cmsHPROFILE hLab; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + // TAC only works on output profiles + if (cmsGetDeviceClass(hProfile) != cmsSigOutputClass) { + return 0; + } + + // Create a fake formatter for result + dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE); + + bp.nOutputChans = T_CHANNELS(dwFormatter); + bp.MaxTAC = 0; // Initial TAC is 0 + + // for safety + if (bp.nOutputChans >= cmsMAXCHANNELS) return 0; + + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + if (hLab == NULL) return 0; + // Setup a roundtrip on perceptual intent in output profile for TAC estimation + bp.hRoundTrip = cmsCreateTransformTHR(ContextID, hLab, TYPE_Lab_16, + hProfile, dwFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE); + + cmsCloseProfile(hLab); + if (bp.hRoundTrip == NULL) return 0; + + // For L* we only need black and white. For C* we need many points + GridPoints[0] = 6; + GridPoints[1] = 74; + GridPoints[2] = 74; + + + if (!cmsSliceSpace16(3, GridPoints, EstimateTAC, &bp)) { + bp.MaxTAC = 0; + } + + cmsDeleteTransform(bp.hRoundTrip); + + // Results in % + return bp.MaxTAC; +} + + +// Carefully, clamp on CIELab space. + +cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab, + double amax, double amin, + double bmax, double bmin) +{ + + // Whole Luma surface to zero + + if (Lab -> L < 0) { + + Lab-> L = Lab->a = Lab-> b = 0.0; + return FALSE; + } + + // Clamp white, DISCARD HIGHLIGHTS. This is done + // in such way because icc spec doesn't allow the + // use of L>100 as a highlight means. + + if (Lab->L > 100) + Lab -> L = 100; + + // Check out gamut prism, on a, b faces + + if (Lab -> a < amin || Lab->a > amax|| + Lab -> b < bmin || Lab->b > bmax) { + + cmsCIELCh LCh; + double h, slope; + + // Falls outside a, b limits. Transports to LCh space, + // and then do the clipping + + + if (Lab -> a == 0.0) { // Is hue exactly 90? + + // atan will not work, so clamp here + Lab -> b = Lab->b < 0 ? bmin : bmax; + return TRUE; + } + + cmsLab2LCh(&LCh, Lab); + + slope = Lab -> b / Lab -> a; + h = LCh.h; + + // There are 4 zones + + if ((h >= 0. && h < 45.) || + (h >= 315 && h <= 360.)) { + + // clip by amax + Lab -> a = amax; + Lab -> b = amax * slope; + } + else + if (h >= 45. && h < 135.) + { + // clip by bmax + Lab -> b = bmax; + Lab -> a = bmax / slope; + } + else + if (h >= 135. && h < 225.) { + // clip by amin + Lab -> a = amin; + Lab -> b = amin * slope; + + } + else + if (h >= 225. && h < 315.) { + // clip by bmin + Lab -> b = bmin; + Lab -> a = bmin / slope; + } + else { + cmsSignalError(0, cmsERROR_RANGE, "Invalid angle"); + return FALSE; + } + + } + + return TRUE; +} diff --git a/third_party/lcms2-2.6/src/cmshalf.c b/third_party/lcms/src/cmshalf.c similarity index 99% rename from third_party/lcms2-2.6/src/cmshalf.c rename to third_party/lcms/src/cmshalf.c index f038b57b4cbe4a9812b26381a9b7fdd3347969bb..cdd4e37b7f171943ccefa92d6c73a278eb34b8c1 100644 --- a/third_party/lcms2-2.6/src/cmshalf.c +++ b/third_party/lcms/src/cmshalf.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -22,7 +22,8 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //--------------------------------------------------------------------------------- - +// +// #include "lcms2_internal.h" #ifndef CMS_NO_HALF_SUPPORT diff --git a/third_party/lcms2-2.6/src/cmsintrp.c b/third_party/lcms/src/cmsintrp.c similarity index 99% rename from third_party/lcms2-2.6/src/cmsintrp.c rename to third_party/lcms/src/cmsintrp.c index 14c68563cad0294dc95bc63907a3e7149aa5cdf8..60d6a0e497199a56f9ae0b830661b7fa41278f3d 100644 --- a/third_party/lcms2-2.6/src/cmsintrp.c +++ b/third_party/lcms/src/cmsintrp.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -156,7 +156,7 @@ cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int int i; cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS]; - // Fill the auxiliar array + // Fill the auxiliary array for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Samples[i] = nSamples; @@ -929,7 +929,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], Rest = c1 * rx + c2 * ry + c3 * rz; - Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); + Tmp1[OutChan] = (cmsUInt16Number) ( c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))); } @@ -993,7 +993,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], Rest = c1 * rx + c2 * ry + c3 * rz; - Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); + Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))); } diff --git a/third_party/lcms2-2.6/src/cmsio0.c b/third_party/lcms/src/cmsio0.c similarity index 94% rename from third_party/lcms2-2.6/src/cmsio0.c rename to third_party/lcms/src/cmsio0.c index 3ed730a92a8b7a20aa72b1d901c6b78faa1fba98..cc5f890644d9d2d3cf9c0d502b5395300b371de5 100644 --- a/third_party/lcms2-2.6/src/cmsio0.c +++ b/third_party/lcms/src/cmsio0.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ // //--------------------------------------------------------------------------------- // + #include "lcms2_internal.h" // Generic I/O, tag dictionary management, profile struct @@ -323,7 +324,7 @@ cmsUInt32Number FileRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number return nReaded; } -// Postion file pointer in the file +// Position file pointer in the file static cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) { @@ -367,6 +368,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha { cmsIOHANDLER* iohandler = NULL; FILE* fm = NULL; + cmsInt32Number fileLen; _cmsAssert(FileName != NULL); _cmsAssert(AccessMode != NULL); @@ -382,8 +384,17 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha _cmsFree(ContextID, iohandler); cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName); return NULL; + } + fileLen = cmsfilelength(fm); + if (fileLen < 0) + { + fclose(fm); + _cmsFree(ContextID, iohandler); + cmsSignalError(ContextID, cmsERROR_FILE, "Cannot get size of file '%s'", FileName); + return NULL; } - iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(fm); + + iohandler -> ReportedSize = (cmsUInt32Number) fileLen; break; case 'w': @@ -423,6 +434,14 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream) { cmsIOHANDLER* iohandler = NULL; + cmsInt32Number fileSize; + + fileSize = cmsfilelength(Stream); + if (fileSize < 0) + { + cmsSignalError(ContextID, cmsERROR_FILE, "Cannot get size of stream"); + return NULL; + } iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); if (iohandler == NULL) return NULL; @@ -430,7 +449,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* S iohandler -> ContextID = ContextID; iohandler -> stream = (void*) Stream; iohandler -> UsedSpace = 0; - iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(Stream); + iohandler -> ReportedSize = (cmsUInt32Number) fileSize; iohandler -> PhysicalFile[0] = 0; iohandler ->Read = FileRead; @@ -452,6 +471,14 @@ cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io) // ------------------------------------------------------------------------------------------------------- +cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile; + + if (Icc == NULL) return NULL; + return Icc->IOhandler; +} + #ifdef _WIN32_WCE time_t wceex_time(time_t *timer); struct tm * wceex_gmtime(const time_t *timer); @@ -551,14 +578,14 @@ int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks // Yes, follow link if (LinkedSig != (cmsTagSignature) 0) { - // fix bug mantis id#0055942 - // assume that TRCTag and ColorantTag can't be linked. - // Xiaochuan Liu 2014-04-23 - if ((sig == cmsSigRedTRCTag || sig == cmsSigGreenTRCTag || sig == cmsSigBlueTRCTag) && - (LinkedSig == cmsSigRedColorantTag || LinkedSig == cmsSigGreenColorantTag || LinkedSig == cmsSigBlueColorantTag)) - { - return n; - } + // fix bug mantis id#0055942 + // assume that TRCTag and ColorantTag can't be linked. + // Xiaochuan Liu 2014-04-23 + if ((sig == cmsSigRedTRCTag || sig == cmsSigGreenTRCTag || sig == cmsSigBlueTRCTag) && + (LinkedSig == cmsSigRedColorantTag || LinkedSig == cmsSigGreenColorantTag || LinkedSig == cmsSigBlueColorantTag)) + { + return n; + } sig = LinkedSig; } @@ -630,7 +657,7 @@ cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) } -// Check existance +// Check existence cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig) { _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) (void*) hProfile; @@ -638,6 +665,32 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig) } + +// Enforces that the profile version is per. spec. +// Operates on the big endian bytes from the profile. +// Called before converting to platform endianness. +// Byte 0 is BCD major version, so max 9. +// Byte 1 is 2 BCD digits, one per nibble. +// Reserved bytes 2 & 3 must be 0. +static +cmsUInt32Number _validatedVersion(cmsUInt32Number DWord) +{ + cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord; + cmsUInt8Number temp1; + cmsUInt8Number temp2; + + if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09; + temp1 = *(pByte+1) & 0xf0; + temp2 = *(pByte+1) & 0x0f; + if (temp1 > 0x90) temp1 = 0x90; + if (temp2 > 0x09) temp2 = 0x09; + *(pByte+1) = (cmsUInt8Number)(temp1 | temp2); + *(pByte+2) = (cmsUInt8Number)0; + *(pByte+3) = (cmsUInt8Number)0; + + return DWord; +} + // Read profile header and validate it cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) { @@ -660,7 +713,7 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) return FALSE; } - // Adjust endianess of the used parameters + // Adjust endianness of the used parameters Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass); Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace); Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs); @@ -672,7 +725,7 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) Icc -> creator = _cmsAdjustEndianess32(Header.creator); _cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes); - Icc -> Version = _cmsAdjustEndianess32(Header.version); + Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version)); // Get size as reported in header HeaderSize = _cmsAdjustEndianess32(Header.size); @@ -779,7 +832,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) memset(&Header.reserved, 0, sizeof(Header.reserved)); - // Set profile ID. Endianess is always big endian + // Set profile ID. Endianness is always big endian memmove(&Header.profileID, &Icc ->ProfileID, 16); // Dump the header @@ -789,7 +842,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) // Get true count for (i=0; i < Icc -> TagCount; i++) { - if (Icc ->TagNames[i] != 0) + if (Icc ->TagNames[i] != (cmsTagSignature) 0) Count++; } @@ -798,7 +851,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) for (i=0; i < Icc -> TagCount; i++) { - if (Icc ->TagNames[i] == 0) continue; // It is just a placeholder + if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // It is just a placeholder Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]); Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]); @@ -1148,7 +1201,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) for (i=0; i < Icc -> TagCount; i++) { - if (Icc ->TagNames[i] == 0) continue; + if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // Linked tags are not written if (Icc ->TagLinked[i] != (cmsTagSignature) 0) continue; @@ -1281,12 +1334,16 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH cmsContext ContextID; _cmsAssert(hProfile != NULL); - + + if (!_cmsLockMutex(Icc->ContextID, Icc->UsrMutex)) return 0; memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); ContextID = cmsGetProfileContextID(hProfile); PrevIO = Icc ->IOhandler = cmsOpenIOhandlerFromNULL(ContextID); - if (PrevIO == NULL) return 0; + if (PrevIO == NULL) { + _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); + return 0; + } // Pass #1 does compute offsets @@ -1306,7 +1363,10 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH } memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); - if (!cmsCloseIOhandler(PrevIO)) return 0; + if (!cmsCloseIOhandler(PrevIO)) + UsedSpace = 0; // As a error marker + + _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); return UsedSpace; @@ -1314,13 +1374,15 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH Error: cmsCloseIOhandler(PrevIO); memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); + _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); + return 0; } #ifdef _WIN32_WCE int wceex_unlink(const char *filename); #ifndef remove -# define remove wceex_unlink +# define remove wceex_unlink #endif #endif @@ -1534,7 +1596,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) LocalTypeHandler.ICCVersion = Icc ->Version; Icc -> TagPtrs[n] = LocalTypeHandler.ReadPtr(&LocalTypeHandler, io, &ElemCount, TagSize); - // The tag type is supported, but something wrong happend and we cannot read the tag. + // The tag type is supported, but something wrong happened and we cannot read the tag. // let know the user about this (although it is just a warning) if (Icc -> TagPtrs[n] == NULL) { @@ -1827,7 +1889,7 @@ Error: // Similar to the anterior. This function allows to write directly to the ICC profile any data, without // checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading -// it as cooked without serializing does result into an error. If that is wha you want, you will need to dump +// it as cooked without serializing does result into an error. If that is what you want, you will need to dump // the profile to memry or disk and then reopen it. cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size) { @@ -1851,6 +1913,11 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons Icc ->TagSizes[i] = Size; _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + + if (Icc->TagPtrs[i] == NULL) { + Icc->TagNames[i] = (cmsTagSignature) 0; + return FALSE; + } return TRUE; } diff --git a/third_party/lcms2-2.6/src/cmsio1.c b/third_party/lcms/src/cmsio1.c similarity index 93% rename from third_party/lcms2-2.6/src/cmsio1.c rename to third_party/lcms/src/cmsio1.c index 778aa2b4fc525eecb3ada54145f35cb51fa08b7c..4b12ae18ea920f544fcd9b0540988a4bb5d2d91e 100644 --- a/third_party/lcms2-2.6/src/cmsio1.c +++ b/third_party/lcms/src/cmsio1.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -128,7 +128,7 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile) } -// Auxiliar, read colorants as a MAT3 structure. Used by any function that needs a matrix-shaper +// Auxiliary, read colorants as a MAT3 structure. Used by any function that needs a matrix-shaper static cmsBool ReadICCMatrixRGB2XYZ(cmsMAT3* r, cmsHPROFILE hProfile) { @@ -201,10 +201,10 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile) return Lut; Error: - // memory pointed by GrayTRC is not a new malloc memory, so don't free it here, - // memory pointed by GrayTRC will be freed when hProfile is closed. - // test file :0047776_Pocket Medicine_ The Massachusetts General Hospital Handbook of Internal Medicine-2.pdf - // Xiaochuan Liu, 20140421 + // memory pointed by GrayTRC is not a new malloc memory, so don't free it here, + // memory pointed by GrayTRC will be freed when hProfile is closed. + // test file :0047776_Pocket Medicine_ The Massachusetts General Hospital Handbook of Internal Medicine-2.pdf + // Xiaochuan Liu, 20140421 //cmsFreeToneCurve(GrayTRC); cmsPipelineFree(Lut); return NULL; @@ -314,11 +314,11 @@ Error: cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) { cmsTagTypeSignature OriginalType; - cmsTagSignature tag16 = Device2PCS16[Intent]; - cmsTagSignature tagFloat = Device2PCSFloat[Intent]; + cmsTagSignature tag16; + cmsTagSignature tagFloat; cmsContext ContextID = cmsGetProfileContextID(hProfile); - // On named color, take the appropiate tag + // On named color, take the appropriate tag if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { cmsPipeline* Lut; @@ -340,9 +340,12 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) return Lut; } - // This is an attempt to reuse this funtion to retrieve the matrix-shaper as pipeline no + // This is an attempt to reuse this function to retrieve the matrix-shaper as pipeline no // matter other LUT are present and have precedence. Intent = -1 means just this. - if (Intent != -1) { + if (Intent >= INTENT_PERCEPTUAL && Intent <= INTENT_ABSOLUTE_COLORIMETRIC) { + + tag16 = Device2PCS16[Intent]; + tagFloat = Device2PCSFloat[Intent]; if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence @@ -395,7 +398,7 @@ Error: // Check if this is a grayscale profile. if (cmsGetColorSpace(hProfile) == cmsSigGrayData) { - // if so, build appropiate conversion tables. + // if so, build appropriate conversion tables. // The tables are the PCS iluminant, scaled across GrayTRC return BuildGrayInputMatrixPipeline(hProfile); } @@ -550,7 +553,7 @@ cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFlo if (Lut == NULL) return NULL; // If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding, - // and since the formatter has already accomodated to 0..1.0, we should undo this change + // and since the formatter has already accommodated to 0..1.0, we should undo this change if ( PCS == cmsSigLabData) { if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID))) @@ -586,12 +589,15 @@ Error: cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) { cmsTagTypeSignature OriginalType; - cmsTagSignature tag16 = PCS2Device16[Intent]; - cmsTagSignature tagFloat = PCS2DeviceFloat[Intent]; - cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsTagSignature tag16; + cmsTagSignature tagFloat; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + if (Intent >= INTENT_PERCEPTUAL && Intent <= INTENT_ABSOLUTE_COLORIMETRIC) { - if (Intent != -1) { + tag16 = PCS2Device16[Intent]; + tagFloat = PCS2DeviceFloat[Intent]; if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence @@ -649,7 +655,7 @@ Error: // Check if this is a grayscale profile. if (cmsGetColorSpace(hProfile) == cmsSigGrayData) { - // if so, build appropiate conversion tables. + // if so, build appropriate conversion tables. // The tables are the PCS iluminant, scaled across GrayTRC return BuildGrayOutputPipeline(hProfile); } @@ -707,15 +713,21 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) { cmsPipeline* Lut; cmsTagTypeSignature OriginalType; - cmsTagSignature tag16 = Device2PCS16[Intent]; - cmsTagSignature tagFloat = Device2PCSFloat[Intent]; + cmsTagSignature tag16; + cmsTagSignature tagFloat; cmsContext ContextID = cmsGetProfileContextID(hProfile); - // On named color, take the appropiate tag + if (Intent < INTENT_PERCEPTUAL || Intent > INTENT_ABSOLUTE_COLORIMETRIC) + return NULL; + + tag16 = Device2PCS16[Intent]; + tagFloat = Device2PCSFloat[Intent]; + + // On named color, take the appropriate tag if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { - cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag); + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*)cmsReadTag(hProfile, cmsSigNamedColor2Tag); if (nc == NULL) return NULL; @@ -731,12 +743,13 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) goto Error; return Lut; -Error: + Error: cmsPipelineFree(Lut); cmsFreeNamedColorList(nc); return NULL; } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence // Floating point LUT are always V @@ -746,19 +759,19 @@ Error: tagFloat = Device2PCSFloat[0]; if (cmsIsTag(hProfile, tagFloat)) { - return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat)); + return cmsPipelineDup((cmsPipeline*)cmsReadTag(hProfile, tagFloat)); } if (!cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? - tag16 = Device2PCS16[0]; + tag16 = Device2PCS16[0]; if (!cmsIsTag(hProfile, tag16)) return NULL; } // Check profile version and LUT type. Do the necessary adjustments if needed // Read the tag - Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + Lut = (cmsPipeline*)cmsReadTag(hProfile, tag16); if (Lut == NULL) return NULL; // The profile owns the Lut, so we need to copy it @@ -771,7 +784,7 @@ Error: ChangeInterpolationToTrilinear(Lut); // After reading it, we have info about the original type - OriginalType = _cmsGetTagTrueType(hProfile, tag16); + OriginalType = _cmsGetTagTrueType(hProfile, tag16); // We need to adjust data for Lab16 on output if (OriginalType != cmsSigLut16Type) return Lut; @@ -779,12 +792,12 @@ Error: // Here it is possible to get Lab on both sides if (cmsGetColorSpace(hProfile) == cmsSigLabData) { - if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) goto Error2; } if (cmsGetPCS(hProfile) == cmsSigLabData) { - if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) goto Error2; } @@ -910,7 +923,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq) { if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE; - if (cmsGetProfileVersion(hProfile) >= 4.0) { + if (cmsGetEncodedICCversion(hProfile) >= 0x4000000) { if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE; } @@ -919,7 +932,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq) } -// Auxiliar, read and duplicate a MLU if found. +// Auxiliary, read and duplicate a MLU if found. static cmsMLU* GetMLUFromProfile(cmsHPROFILE h, cmsTagSignature sig) { diff --git a/third_party/lcms2-2.6/src/cmslut.c b/third_party/lcms/src/cmslut.c similarity index 98% rename from third_party/lcms2-2.6/src/cmslut.c rename to third_party/lcms/src/cmslut.c index 19d43361f09b43b7c7ebfd3df15749166547bb08..8d5815902a259b885c471cdadcfbf81a40e01292 100644 --- a/third_party/lcms2-2.6/src/cmslut.c +++ b/third_party/lcms/src/cmslut.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -505,7 +505,7 @@ void* CLUTElemDup(cmsStage* mpe) goto Error; } else { NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number)); - if (NewElem ->Tab.TFloat == NULL) + if (NewElem ->Tab.T == NULL) goto Error; } } @@ -1125,7 +1125,23 @@ cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID) return mpe; } +// Clips values smaller than zero +static +void Clipper(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + cmsUInt32Number i; + for (i = 0; i < mpe->InputChannels; i++) { + + cmsFloat32Number n = In[i]; + Out[i] = n < 0 ? 0 : n; + } +} +cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels) +{ + return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType, + nChannels, nChannels, Clipper, NULL, NULL, NULL); +} // ******************************************************************************** // Type cmsSigXYZ2LabElemType @@ -1287,7 +1303,7 @@ cmsBool BlessLUT(cmsPipeline* lut) prev = prev->Next; } } - return TRUE; + return TRUE; } @@ -1460,7 +1476,8 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) First = FALSE; } else { - Anterior ->Next = NewMPE; + if (Anterior != NULL) + Anterior ->Next = NewMPE; } Anterior = NewMPE; @@ -1510,7 +1527,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage for (pt = lut ->Elements; pt != NULL; pt = pt -> Next) Anterior = pt; - + Anterior ->Next = mpe; mpe ->Next = NULL; } @@ -1519,7 +1536,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage return FALSE; } - return BlessLUT(lut); + return BlessLUT(lut); } // Unlink an element and return the pointer to it @@ -1601,7 +1618,7 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) return FALSE; } - return BlessLUT(l1); + return BlessLUT(l1); } @@ -1818,3 +1835,5 @@ cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[], return TRUE; } + + diff --git a/third_party/lcms2-2.6/src/cmsmd5.c b/third_party/lcms/src/cmsmd5.c similarity index 93% rename from third_party/lcms2-2.6/src/cmsmd5.c rename to third_party/lcms/src/cmsmd5.c index a4758ff662f942430675ec23df9aad2c1416c4ee..c7380ca8f03fa667822bb8c0cf00009fa5c9a4b7 100644 --- a/third_party/lcms2-2.6/src/cmsmd5.c +++ b/third_party/lcms/src/cmsmd5.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ // //--------------------------------------------------------------------------------- + #include "lcms2_internal.h" #ifdef CMS_USE_BIG_ENDIAN @@ -314,30 +315,3 @@ Error: return FALSE; } -cmsBool CMSEXPORT cmsMD5computeIDExt(const void* buf, unsigned long size, unsigned char ProfileID[16]) -{ - cmsHANDLE MD5; - cmsUInt8Number* Mem; - - if (buf == NULL) - return FALSE; - MD5 = NULL; - Mem = (cmsUInt8Number*)_cmsMalloc(NULL,size); - memmove(Mem,buf,size); - // Create MD5 object - MD5 = MD5alloc(NULL); - if (MD5 == NULL) goto Error; - - // Add all bytes - MD5add(MD5, Mem, size); - - // Temp storage is no longer needed - _cmsFree(NULL, Mem); - - // And store the ID - MD5finish((cmsProfileID*)ProfileID, MD5); - return TRUE; -Error: - if (MD5 != NULL) _cmsFree(NULL, MD5); - return FALSE; -} diff --git a/third_party/lcms2-2.6/src/cmsmtrx.c b/third_party/lcms/src/cmsmtrx.c similarity index 98% rename from third_party/lcms2-2.6/src/cmsmtrx.c rename to third_party/lcms/src/cmsmtrx.c index fb7b91caf1aa20bcbf2c759012e8dad498007da7..d0e5461e9fcaa1e53e79c7399ef4704896dd4af5 100644 --- a/third_party/lcms2-2.6/src/cmsmtrx.c +++ b/third_party/lcms/src/cmsmtrx.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -38,7 +38,7 @@ void CMSEXPORT _cmsVEC3init(cmsVEC3* r, cmsFloat64Number x, cmsFloat64Number y, r -> n[VZ] = z; } -// Vector substraction +// Vector subtraction void CMSEXPORT _cmsVEC3minus(cmsVEC3* r, const cmsVEC3* a, const cmsVEC3* b) { r -> n[VX] = a -> n[VX] - b -> n[VX]; @@ -173,3 +173,4 @@ void CMSEXPORT _cmsMAT3eval(cmsVEC3* r, const cmsMAT3* a, const cmsVEC3* v) r->n[VZ] = a->v[2].n[VX]*v->n[VX] + a->v[2].n[VY]*v->n[VY] + a->v[2].n[VZ]*v->n[VZ]; } + diff --git a/third_party/lcms2-2.6/src/cmsnamed.c b/third_party/lcms/src/cmsnamed.c similarity index 93% rename from third_party/lcms2-2.6/src/cmsnamed.c rename to third_party/lcms/src/cmsnamed.c index ef1eb3089ecc7ba5af4134e458dbdf88e1df7b2d..9ed4cad39871feb308b96dd3661366987f443139 100644 --- a/third_party/lcms2-2.6/src/cmsnamed.c +++ b/third_party/lcms/src/cmsnamed.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -92,7 +92,7 @@ cmsBool GrowMLUpool(cmsMLU* mlu) static cmsBool GrowMLUtable(cmsMLU* mlu) { - int AllocatedEntries; + cmsUInt32Number AllocatedEntries; _cmsMLUentry *NewPtr; // Sanity check @@ -118,7 +118,7 @@ cmsBool GrowMLUtable(cmsMLU* mlu) static int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode) { - int i; + cmsUInt32Number i; // Sanity check if (mlu == NULL) return -1; @@ -178,15 +178,42 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block, return TRUE; } +// Convert from a 3-char code to a cmsUInt16Number. It is done inthis way because some +// compilers don't properly align beginning of strings + +static +cmsUInt16Number strTo16(const char str[3]) +{ + cmsUInt16Number n = ((cmsUInt16Number) str[0] << 8) | str[1]; + + return n; // Always big endian in this case +} + +static +void strFrom16(char str[3], cmsUInt16Number n) +{ + // Assiming this would be aligned + union { + + cmsUInt16Number n; + char str[2]; + + } c; + + c.n = n; // Always big endian in this case + + str[0] = c.str[0]; str[1] = c.str[1]; str[2] = 0; -// Add an ASCII entry. +} + +// Add an ASCII entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61) cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString) { - cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1; + cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString); wchar_t* WStr; cmsBool rc; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); if (mlu == NULL) return FALSE; @@ -216,18 +243,17 @@ cmsUInt32Number mywcslen(const wchar_t *s) return (cmsUInt32Number)(p - s); } - -// Add a wide entry +// Add a wide entry. Do not add any \0 terminator (ICC1v43_2010-12.pdf page 61) cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString) { - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country); + cmsUInt16Number Lang = strTo16(Language); + cmsUInt16Number Cntry = strTo16(Country); cmsUInt32Number len; if (mlu == NULL) return FALSE; if (WideString == NULL) return FALSE; - len = (cmsUInt32Number) (mywcslen(WideString) + 1) * sizeof(wchar_t); + len = (cmsUInt32Number) (mywcslen(WideString)) * sizeof(wchar_t); return AddMLUBlock(mlu, len, WideString, Lang, Cntry); } @@ -298,8 +324,8 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode, cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode) { - int i; - int Best = -1; + cmsUInt32Number i; + cmsInt32Number Best = -1; _cmsMLUentry* v; if (mlu == NULL) return NULL; @@ -350,8 +376,8 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu, cmsUInt32Number StrLen = 0; cmsUInt32Number ASCIIlen, i; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); // Sanitize if (mlu == NULL) return 0; @@ -394,8 +420,8 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu, const wchar_t *Wide; cmsUInt32Number StrLen = 0; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); // Sanitize if (mlu == NULL) return 0; @@ -427,8 +453,8 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, { const wchar_t *Wide; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); cmsUInt16Number ObtLang, ObtCode; // Sanitize @@ -438,10 +464,9 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, if (Wide == NULL) return FALSE; // Get used language and code - *(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang); - *(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode); + strFrom16(ObtainedLanguage, ObtLang); + strFrom16(ObtainedCountry, ObtCode); - ObtainedLanguage[2] = ObtainedCountry[2] = 0; return TRUE; } @@ -464,12 +489,12 @@ cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu, if (mlu == NULL) return FALSE; - if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE; + if (idx >= mlu->UsedEntries) return FALSE; entry = &mlu->Entries[idx]; - *(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language); - *(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country); + strFrom16(LanguageCode, entry->Language); + strFrom16(CountryCode, entry->Country); return TRUE; } @@ -514,7 +539,7 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn v ->nColors = 0; v ->ContextID = ContextID; - while (v -> Allocated < n) { + while (v -> Allocated < n){ if (!GrowNamedColorList(v)) { cmsFreeNamedColorList(v); return NULL; @@ -548,7 +573,7 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) if (NewNC == NULL) return NULL; // For really large tables we need this - while (NewNC ->Allocated < v ->Allocated) { + while (NewNC ->Allocated < v ->Allocated){ if (!GrowNamedColorList(NewNC)) { cmsFreeNamedColorList(NewNC); return NULL; diff --git a/third_party/lcms2-2.6/src/cmsopt.c b/third_party/lcms/src/cmsopt.c similarity index 87% rename from third_party/lcms2-2.6/src/cmsopt.c rename to third_party/lcms/src/cmsopt.c index 76de01554cdb5f52f19d18ef0df88aba46458a02..abe26b93af9c834d117cf79861835152ff715d54 100644 --- a/third_party/lcms2-2.6/src/cmsopt.c +++ b/third_party/lcms/src/cmsopt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -162,6 +162,89 @@ cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op return AnyOpt; } + +static +cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b) +{ + return fabs(b - a) < 0.00001f; +} + +static +cmsBool isFloatMatrixIdentity(const cmsMAT3* a) +{ + cmsMAT3 Identity; + int i, j; + + _cmsMAT3identity(&Identity); + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE; + + return TRUE; +} +// if two adjacent matrices are found, multiply them. +static +cmsBool _MultiplyMatrix(cmsPipeline* Lut) +{ + cmsStage** pt1; + cmsStage** pt2; + cmsStage* chain; + cmsBool AnyOpt = FALSE; + + pt1 = &Lut->Elements; + if (*pt1 == NULL) return AnyOpt; + + while (*pt1 != NULL) { + + pt2 = &((*pt1)->Next); + if (*pt2 == NULL) return AnyOpt; + + if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) { + + // Get both matrices + _cmsStageMatrixData* m1 = (_cmsStageMatrixData*) cmsStageData(*pt1); + _cmsStageMatrixData* m2 = (_cmsStageMatrixData*) cmsStageData(*pt2); + cmsMAT3 res; + + // Input offset and output offset should be zero to use this optimization + if (m1->Offset != NULL || m2 ->Offset != NULL || + cmsStageInputChannels(*pt1) != 3 || cmsStageOutputChannels(*pt1) != 3 || + cmsStageInputChannels(*pt2) != 3 || cmsStageOutputChannels(*pt2) != 3) + return FALSE; + + // Multiply both matrices to get the result + _cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double); + + // Get the next in chain afer the matrices + chain = (*pt2)->Next; + + // Remove both matrices + _RemoveElement(pt2); + _RemoveElement(pt1); + + // Now what if the result is a plain identity? + if (!isFloatMatrixIdentity(&res)) { + + // We can not get rid of full matrix + cmsStage* Multmat = cmsStageAllocMatrix(Lut->ContextID, 3, 3, (const cmsFloat64Number*) &res, NULL); + if (Multmat == NULL) return FALSE; // Should never happen + + // Recover the chain + Multmat->Next = chain; + *pt1 = Multmat; + } + + AnyOpt = TRUE; + } + else + pt1 = &((*pt1)->Next); + } + + return AnyOpt; +} + + // Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed // by a v4 to v2 and vice-versa. The elements are then discarded. static @@ -194,6 +277,9 @@ cmsBool PreOptimize(cmsPipeline* Lut) // Remove float pcs Lab conversions Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ); + // Simplify matrix. + Opt |= _MultiplyMatrix(Lut); + if (Opt) AnyOpt = TRUE; } while (Opt); @@ -250,12 +336,12 @@ static void* Prelin16dup(cmsContext ContextID, const void* ptr) { Prelin16Data* p16 = (Prelin16Data*) ptr; - Prelin16Data* Duped = _cmsDupMem(ContextID, p16, sizeof(Prelin16Data)); + Prelin16Data* Duped = (Prelin16Data*) _cmsDupMem(ContextID, p16, sizeof(Prelin16Data)); if (Duped == NULL) return NULL; - Duped ->EvalCurveOut16 = (_cmsInterpFn16*)_cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16)); - Duped ->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* )); + Duped->EvalCurveOut16 = (_cmsInterpFn16*) _cmsDupMem(ContextID, p16->EvalCurveOut16, p16->nOutputs * sizeof(_cmsInterpFn16)); + Duped->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16->ParamsCurveOut16, p16->nOutputs * sizeof(cmsInterpParams*)); return Duped; } @@ -268,7 +354,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, int nOutputs, cmsToneCurve** Out ) { int i; - Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data)); + Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data)); if (p16 == NULL) return NULL; p16 ->nInputs = nInputs; @@ -380,10 +466,6 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], return FALSE; } - if (nChannelsIn != 1 && nChannelsIn != 3 && nChannelsIn != 4) { - cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn); - return FALSE; - } if (nChannelsIn == 4) { px = ((cmsFloat64Number) At[0] * (p16->Domain[0])) / 65535.0; @@ -447,7 +529,7 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], return TRUE; } -// Auxiliar, to see if two values are equal or very different +// Auxiliary, to see if two values are equal or very different static cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] ) { @@ -455,7 +537,7 @@ cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] for (i=0; i < n; i++) { - if (abs(White1[i] - White2[i]) > 0xf000) return TRUE; // Values are so extremly different that the fixup should be avoided + if (abs(White1[i] - White2[i]) > 0xf000) return TRUE; // Values are so extremely different that the fixup should be avoided if (White1[i] != White2[i]) return FALSE; } return TRUE; @@ -593,7 +675,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 cmsStage* PreLin = cmsPipelineGetPtrToFirstStage(Src); // Check if suitable - if (PreLin ->Type == cmsSigCurveSetElemType) { + if (PreLin && PreLin ->Type == cmsSigCurveSetElemType) { // Maybe this is a linear tram, so we can avoid the whole stuff if (!AllCurvesAreLinear(PreLin)) { @@ -626,7 +708,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 cmsStage* PostLin = cmsPipelineGetPtrToLastStage(Src); // Check if suitable - if (cmsStageType(PostLin) == cmsSigCurveSetElemType) { + if (PostLin && cmsStageType(PostLin) == cmsSigCurveSetElemType) { // Maybe this is a linear tram, so we can avoid the whole stuff if (!AllCurvesAreLinear(PostLin)) { @@ -835,7 +917,7 @@ void PrelinEval8(register const cmsUInt16Number Input[], Prelin8Data* p8 = (Prelin8Data*) D; register const cmsInterpParams* p = p8 ->p; int TotalOut = p -> nOutputs; - const cmsUInt16Number* LutTable = (const cmsUInt16Number*)p -> Table; + const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table; r = Input[0] >> 8; g = Input[1] >> 8; @@ -928,8 +1010,8 @@ cmsBool IsDegenerated(const cmsToneCurve* g) } if (Zeros == 1 && Poles == 1) return FALSE; // For linear tables - if (Zeros > (nEntries / 4)) return TRUE; // Degenerated, mostly zeros - if (Poles > (nEntries / 4)) return TRUE; // Degenerated, mostly poles + if (Zeros > (nEntries / 20)) return TRUE; // Degenerated, many zeros + if (Poles > (nEntries / 20)) return TRUE; // Degenerated, many poles return FALSE; } @@ -951,17 +1033,19 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte cmsColorSpaceSignature ColorSpace, OutputColorSpace; cmsStage* OptimizedPrelinMpe; cmsStage* mpe; - cmsToneCurve** OptimizedPrelinCurves; - _cmsStageCLutData* OptimizedPrelinCLUT; + cmsToneCurve** OptimizedPrelinCurves; + _cmsStageCLutData* OptimizedPrelinCLUT; // This is a loosy optimization! does not apply in floating-point cases if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; - // Only on RGB + // Only on chunky RGB if (T_COLORSPACE(*InputFormat) != PT_RGB) return FALSE; - if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE; + if (T_PLANAR(*InputFormat)) return FALSE; + if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE; + if (T_PLANAR(*OutputFormat)) return FALSE; // On 16 bits, user has to specify the feature if (!_cmsFormatterIs8bit(*InputFormat)) { @@ -985,6 +1069,22 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte memset(Trans, 0, sizeof(Trans)); memset(TransReverse, 0, sizeof(TransReverse)); + // If the last stage of the original lut are curves, and those curves are + // degenerated, it is likely the transform is squeezing and clipping + // the output from previous CLUT. We cannot optimize this case + { + cmsStage* last = cmsPipelineGetPtrToLastStage(OriginalLut); + + if (cmsStageType(last) == cmsSigCurveSetElemType) { + + _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*)cmsStageData(last); + for (i = 0; i < Data->nCurves; i++) { + if (IsDegenerated(Data->TheCurves[i])) + goto Error; + } + } + } + for (t = 0; t < OriginalLut ->InputChannels; t++) { Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL); if (Trans[t] == NULL) goto Error; @@ -1159,10 +1259,10 @@ void* CurvesDup(cmsContext ContextID, const void* ptr) if (Data == NULL) return NULL; - Data ->Curves = (cmsUInt16Number**)_cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*)); + Data->Curves = (cmsUInt16Number**) _cmsDupMem(ContextID, Data->Curves, Data->nCurves * sizeof(cmsUInt16Number*)); for (i=0; i < Data -> nCurves; i++) { - Data ->Curves[i] = (cmsUInt16Number*)_cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number)); + Data->Curves[i] = (cmsUInt16Number*) _cmsDupMem(ContextID, Data->Curves[i], Data->nElements * sizeof(cmsUInt16Number)); } return (void*) Data; @@ -1181,12 +1281,12 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT c16 ->nCurves = nCurves; c16 ->nElements = nElements; - c16 ->Curves = (cmsUInt16Number**)_cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); + c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); if (c16 ->Curves == NULL) return NULL; for (i=0; i < nCurves; i++) { - c16->Curves[i] = (cmsUInt16Number*)_cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); + c16->Curves[i] = (cmsUInt16Number*) _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); if (c16->Curves[i] == NULL) { @@ -1318,7 +1418,10 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI GammaTables[i] = NULL; } - if (GammaTables != NULL) _cmsFree(Src ->ContextID, GammaTables); + if (GammaTables != NULL) { + _cmsFree(Src->ContextID, GammaTables); + GammaTables = NULL; + } // Maybe the curves are linear at the end if (!AllCurvesAreLinear(ObtainedCurves)) { @@ -1543,55 +1646,89 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c // Fill function pointers _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper); return TRUE; -Error: - _cmsFree(Dest->ContextID, p); - return FALSE; + Error: + _cmsFree(Dest->ContextID, p); + return FALSE; } // 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast! -// TODO: Allow a third matrix for abs. colorimetric static cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { - cmsStage* Curve1, *Curve2; - cmsStage* Matrix1, *Matrix2; - _cmsStageMatrixData* Data1; - _cmsStageMatrixData* Data2; - cmsMAT3 res; - cmsBool IdentityMat; - cmsPipeline* Dest, *Src; + cmsStage* Curve1, *Curve2; + cmsStage* Matrix1, *Matrix2; + cmsMAT3 res; + cmsBool IdentityMat; + cmsPipeline* Dest, *Src; + cmsFloat64Number* Offset; - // Only works on RGB to RGB - if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE; + // Only works on RGB to RGB + if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE; - // Only works on 8 bit input - if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE; + // Only works on 8 bit input + if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE; - // Seems suitable, proceed - Src = *Lut; + // Seems suitable, proceed + Src = *Lut; - // Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for - if (!cmsPipelineCheckAndRetreiveStages(Src, 4, - cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, - &Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE; + // Check for: + // + // shaper-matrix-matrix-shaper + // shaper-matrix-shaper + // + // Both of those constructs are possible (first because abs. colorimetric). + // additionally, In the first case, the input matrix offset should be zero. - // Get both matrices - Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1); - Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2); + IdentityMat = FALSE; + if (cmsPipelineCheckAndRetreiveStages(Src, 4, + cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, + &Curve1, &Matrix1, &Matrix2, &Curve2)) { - // Input offset should be zero - if (Data1 ->Offset != NULL) return FALSE; + // Get both matrices + _cmsStageMatrixData* Data1 = (_cmsStageMatrixData*)cmsStageData(Matrix1); + _cmsStageMatrixData* Data2 = (_cmsStageMatrixData*)cmsStageData(Matrix2); - // Multiply both matrices to get the result - _cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double); + // Input offset should be zero + if (Data1->Offset != NULL) return FALSE; - // Now the result is in res + Data2 -> Offset. Maybe is a plain identity? - IdentityMat = FALSE; - if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) { + // Multiply both matrices to get the result + _cmsMAT3per(&res, (cmsMAT3*)Data2->Double, (cmsMAT3*)Data1->Double); - // We can get rid of full matrix - IdentityMat = TRUE; - } + // Only 2nd matrix has offset, or it is zero + Offset = Data2->Offset; + + // Now the result is in res + Data2 -> Offset. Maybe is a plain identity? + if (_cmsMAT3isIdentity(&res) && Offset == NULL) { + + // We can get rid of full matrix + IdentityMat = TRUE; + } + + } + else { + + if (cmsPipelineCheckAndRetreiveStages(Src, 3, + cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, + &Curve1, &Matrix1, &Curve2)) { + + _cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1); + + // Copy the matrix to our result + memcpy(&res, Data->Double, sizeof(res)); + + // Preserve the Odffset (may be NULL as a zero offset) + Offset = Data->Offset; + + if (_cmsMAT3isIdentity(&res) && Offset == NULL) { + + // We can get rid of full matrix + IdentityMat = TRUE; + } + } + else + return FALSE; // Not optimizeable this time + + } // Allocate an empty LUT Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels); @@ -1601,9 +1738,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1))) goto Error; - if (!IdentityMat) - if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset))) - goto Error; + if (!IdentityMat) { + + if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset))) + goto Error; + } + if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2))) goto Error; @@ -1616,12 +1756,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1); _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2); - // In this particular optimization, cach?does not help as it takes more time to deal with - // the cach?that with the pixel handling + // In this particular optimization, cache does not help as it takes more time to deal with + // the cache that with the pixel handling *dwFlags |= cmsFLAGS_NOCACHE; // Setup the optimizarion routines - if (!SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat)) + if (!SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat)) goto Error; } @@ -1809,3 +1949,6 @@ cmsBool _cmsOptimizePipeline(cmsContext ContextID, // Only simple optimizations succeeded return AnySuccess; } + + + diff --git a/third_party/lcms2-2.6/src/cmspack.c b/third_party/lcms/src/cmspack.c similarity index 93% rename from third_party/lcms2-2.6/src/cmspack.c rename to third_party/lcms/src/cmspack.c index 9323b53ec537755b93c562674995c9882b05cc1d..6ed41da87095cdc70f6b16bc6cb579f19def562a 100644 --- a/third_party/lcms2-2.6/src/cmspack.c +++ b/third_party/lcms/src/cmspack.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ // //--------------------------------------------------------------------------------- // + #include "lcms2_internal.h" // This module handles all formats supported by lcms. There are two flavors, 16 bits and @@ -80,7 +81,7 @@ typedef struct { #define ANYFLAVOR FLAVOR_SH(1) -// Supress waning about info never being used +// Suppress waning about info never being used #ifdef _MSC_VER #pragma warning(disable : 4100) @@ -2408,9 +2409,6 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, ((cmsFloat64Number*) output)[i + start] = v; } - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat64Number); - } if (Extra == 0 && SwapFirst) { @@ -2421,7 +2419,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, if (T_PLANAR(info -> OutputFormat)) return output + sizeof(cmsFloat64Number); else - return output + nChan * sizeof(cmsFloat64Number); + return output + (nChan + Extra) * sizeof(cmsFloat64Number); } @@ -2432,50 +2430,47 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; - cmsFloat64Number v = 0; - cmsFloat32Number* swap1 = (cmsFloat32Number*) output; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0; + cmsFloat64Number v = 0; + cmsFloat32Number* swap1 = (cmsFloat32Number*)output; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = (cmsFloat64Number) wOut[index] / maximum; - - if (Reverse) - v = maximum - v; + v = (cmsFloat64Number)wOut[index] / maximum; - if (Planar) - ((cmsFloat32Number*) output)[(i + start ) * Stride]= (cmsFloat32Number) v; - else - ((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; - } + if (Reverse) + v = maximum - v; - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat32Number); - } + if (Planar) + ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v; + else + ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v; + } - if (Extra == 0 && SwapFirst) { + + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); - *swap1 = (cmsFloat32Number) v; - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number)); + *swap1 = (cmsFloat32Number)v; + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsFloat32Number); - else - return output + nChan * sizeof(cmsFloat32Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsFloat32Number); + else + return output + (nChan + Extra) * sizeof(cmsFloat32Number); } @@ -2488,50 +2483,47 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; - cmsFloat32Number* swap1 = (cmsFloat32Number*) output; - cmsFloat64Number v = 0; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; + cmsFloat32Number* swap1 = (cmsFloat32Number*)output; + cmsFloat64Number v = 0; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = wOut[index] * maximum; + v = wOut[index] * maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsFloat32Number*) output)[(i + start)* Stride]= (cmsFloat32Number) v; - else - ((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; - } + if (Planar) + ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v; + else + ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v; + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat32Number); - } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); - *swap1 = (cmsFloat32Number) v; - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number)); + *swap1 = (cmsFloat32Number)v; + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsFloat32Number); - else - return output + nChan * sizeof(cmsFloat32Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsFloat32Number); + else + return output + (nChan + Extra) * sizeof(cmsFloat32Number); } static @@ -2540,51 +2532,47 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; - cmsFloat64Number v = 0; - cmsFloat64Number* swap1 = (cmsFloat64Number*) output; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; + cmsFloat64Number v = 0; + cmsFloat64Number* swap1 = (cmsFloat64Number*)output; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = wOut[index] * maximum; + v = wOut[index] * maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsFloat64Number*) output)[(i + start) * Stride] = v; - else - ((cmsFloat64Number*) output)[i + start] = v; - } + if (Planar) + ((cmsFloat64Number*)output)[(i + start) * Stride] = v; + else + ((cmsFloat64Number*)output)[i + start] = v; + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat64Number); - } + if (Extra == 0 && SwapFirst) { - if (Extra == 0 && SwapFirst) { + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number)); + *swap1 = v; + } - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number)); - *swap1 = v; - } - - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsFloat64Number); - else - return output + nChan * sizeof(cmsFloat64Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsFloat64Number); + else + return output + (nChan + Extra) * sizeof(cmsFloat64Number); } @@ -2820,50 +2808,47 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35F : 65535.0F; - cmsFloat32Number v = 0; - cmsUInt16Number* swap1 = (cmsUInt16Number*) output; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F; + cmsFloat32Number v = 0; + cmsUInt16Number* swap1 = (cmsUInt16Number*)output; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = (cmsFloat32Number) wOut[index] / maximum; + v = (cmsFloat32Number)wOut[index] / maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsUInt16Number*) output)[(i + start ) * Stride]= _cmsFloat2Half(v); - else - ((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half(v); - } + if (Planar) + ((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v); + else + ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v); + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsUInt16Number); - } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); - *swap1 = _cmsFloat2Half(v); - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number)); + *swap1 = _cmsFloat2Half(v); + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsUInt16Number); - else - return output + nChan * sizeof(cmsUInt16Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsUInt16Number); + else + return output + (nChan + Extra) * sizeof(cmsUInt16Number); } @@ -2874,50 +2859,47 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0F : 1.0F; - cmsUInt16Number* swap1 = (cmsUInt16Number*) output; - cmsFloat32Number v = 0; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F; + cmsUInt16Number* swap1 = (cmsUInt16Number*)output; + cmsFloat32Number v = 0; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = wOut[index] * maximum; + v = wOut[index] * maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsUInt16Number*) output)[(i + start)* Stride]= _cmsFloat2Half( v ); - else - ((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half( v ); - } + if (Planar) + ((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v); + else + ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v); + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsUInt16Number); - } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); - *swap1 = (cmsUInt16Number) _cmsFloat2Half( v ); - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number)); + *swap1 = (cmsUInt16Number)_cmsFloat2Half(v); + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsUInt16Number); - else - return output + nChan * sizeof(cmsUInt16Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsUInt16Number); + else + return output + (nChan + Extra)* sizeof(cmsUInt16Number); } #endif @@ -3177,6 +3159,8 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe cmsUInt32Number i; cmsFormatter fr; + // Optimization is only a hint + dwInput &= ~OPTIMIZED_SH(1); switch (dwFlags) { @@ -3367,3 +3351,4 @@ cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsU // Create a fake formatter for result return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); } + diff --git a/third_party/lcms2-2.6/src/cmspcs.c b/third_party/lcms/src/cmspcs.c similarity index 97% rename from third_party/lcms2-2.6/src/cmspcs.c rename to third_party/lcms/src/cmspcs.c index 102cd7d21ed85976c30f68236750ce321c340e44..0cd8ecbf693859d02c6d3b963780ad06ff3ce7fc 100644 --- a/third_party/lcms2-2.6/src/cmspcs.c +++ b/third_party/lcms/src/cmspcs.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -106,6 +106,15 @@ void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source) Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y; } +/* + The break point (24/116)^3 = (6/29)^3 is a very small amount of tristimulus + primary (0.008856). Generally, this only happens for + nearly ideal blacks and for some orange / amber colors in transmission mode. + For example, the Z value of the orange turn indicator lamp lens on an + automobile will often be below this value. But the Z does not + contribute to the perceived color directly. +*/ + static cmsFloat64Number f(cmsFloat64Number t) { @@ -299,7 +308,7 @@ void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* fLa wLab[2] = ab2Fix4(Lab.b); } -// Auxiliar: convert to Radians +// Auxiliary: convert to Radians static cmsFloat64Number RADIANS(cmsFloat64Number deg) { @@ -307,7 +316,7 @@ cmsFloat64Number RADIANS(cmsFloat64Number deg) } -// Auxiliar: atan2 but operating in degrees and returning 0 if a==b==0 +// Auxiliary: atan2 but operating in degrees and returning 0 if a==b==0 static cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b) { @@ -330,7 +339,7 @@ cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b) } -// Auxiliar: Square +// Auxiliary: Square static cmsFloat64Number Sqr(cmsFloat64Number v) { diff --git a/third_party/lcms2-2.6/src/cmsplugin.c b/third_party/lcms/src/cmsplugin.c similarity index 96% rename from third_party/lcms2-2.6/src/cmsplugin.c rename to third_party/lcms/src/cmsplugin.c index 42c4002b55f2eb5aeaf91b187a2678ae1340ba64..80dd8d48c1fcd3b4fe5a5d8dbc6d5898d469b90e 100644 --- a/third_party/lcms2-2.6/src/cmsplugin.c +++ b/third_party/lcms/src/cmsplugin.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -107,7 +107,7 @@ void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* #endif } -// Auxiliar -- read 8, 16 and 32-bit numbers +// Auxiliary -- read 8, 16 and 32-bit numbers cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n) { cmsUInt8Number tmp; @@ -172,13 +172,13 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) _cmsAssert(io != NULL); - if (io -> Read(io, &tmp, sizeof(cmsFloat32Number), 1) != 1) + if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) return FALSE; if (n != NULL) { tmp = _cmsAdjustEndianess32(tmp); - *n = *(cmsFloat32Number*) &tmp; + *n = *(cmsFloat32Number*) (void*) &tmp; if (isnan(*n)) return FALSE; } @@ -219,22 +219,6 @@ cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n } -// Jun-21-2000: Some profiles (those that comes with W2K) comes -// with the media white (media black?) x 100. Add a sanity check - -static -void NormalizeXYZ(cmsCIEXYZ* Dest) -{ - while (Dest -> X > 2. && - Dest -> Y > 2. && - Dest -> Z > 2.) { - - Dest -> X /= 10.; - Dest -> Y /= 10.; - Dest -> Z /= 10.; - } -} - cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) { cmsEncodedXYZNumber xyz; @@ -248,8 +232,6 @@ cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X)); XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y)); XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z)); - - NormalizeXYZ(XYZ); } return TRUE; } @@ -311,7 +293,7 @@ cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n) _cmsAssert(io != NULL); - tmp = *(cmsUInt32Number*) &n; + tmp = *(cmsUInt32Number*) (void*) &n; tmp = _cmsAdjustEndianess32(tmp); if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) return FALSE; @@ -507,7 +489,10 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...) va_start(args, frm); len = vsnprintf((char*) Buffer, 2047, frm, args); - if (len < 0) return FALSE; // Truncated, which is a fatal error for us + if (len < 0) { + va_end(args); + return FALSE; // Truncated, which is a fatal error for us + } rc = io ->Write(io, len, Buffer); @@ -529,6 +514,7 @@ void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size) if (ContextID == NULL) { ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024); + if (ctx->MemPool == NULL) return NULL; } else { cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context"); @@ -687,15 +673,21 @@ struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID) // Internal: get the memory area associanted with each context client -// Returns the block assigned to the specific zone. +// Returns the block assigned to the specific zone. Never return NULL. void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc) { struct _cmsContext_struct* ctx; void *ptr; - if (mc >= MemoryClientMax) { - cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client"); - return NULL; + if ((int) mc < 0 || mc >= MemoryClientMax) { + + cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption"); + + // This is catastrophic. Should never reach here + _cmsAssert(0); + + // Reverts to global context + return globalContext.chunks[UserPtr]; } ctx = _cmsGetContext(ContextID); @@ -884,7 +876,7 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) } - +/* static struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) { @@ -901,6 +893,7 @@ struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) return NULL; // List is empty or only one element! } +*/ // Frees any resources associated with the given context, // and destroys the context placeholder. @@ -936,8 +929,8 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID) // Search for previous for (prev = _cmsContextPoolHead; - prev != NULL; - prev = prev ->Next) + prev != NULL; + prev = prev ->Next) { if (prev -> Next == ctx) { prev -> Next = ctx ->Next; @@ -957,3 +950,5 @@ void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID) { return _cmsContextGetClientChunk(ContextID, UserPtr); } + + diff --git a/third_party/lcms2-2.6/src/cmsps2.c b/third_party/lcms/src/cmsps2.c similarity index 99% rename from third_party/lcms2-2.6/src/cmsps2.c rename to third_party/lcms/src/cmsps2.c index 224b44b54268a2aec44705553afd1089395042c2..9635eaf8c094f934d2968a169cda364d48f264df 100644 --- a/third_party/lcms2-2.6/src/cmsps2.c +++ b/third_party/lcms/src/cmsps2.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -579,7 +579,7 @@ void EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[]) // // Each row contains Pipeline values for all but first component. So, I // detect row changing by keeping a copy of last value of first -// component. -1 is used to mark begining of whole block. +// component. -1 is used to mark beginning of whole block. static int OutputValueSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) @@ -1393,14 +1393,15 @@ void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) if (nColorant > cmsMAXCHANNELS) nColorant = cmsMAXCHANNELS; - for (j=0; j < nColorant; j++) { + for (j = 0; j < nColorant; j++) { - sprintf(Buff, "%.3f", Out[j] / 65535.0); - strcat(Colorant, Buff); - if (j < nColorant -1) - strcat(Colorant, " "); + snprintf(Buff, 31, "%.3f", Out[j] / 65535.0); + Buff[31] = 0; + strcat(Colorant, Buff); + if (j < nColorant - 1) + strcat(Colorant, " "); - } + } } diff --git a/third_party/lcms2-2.6/src/cmssamp.c b/third_party/lcms/src/cmssamp.c similarity index 98% rename from third_party/lcms2-2.6/src/cmssamp.c rename to third_party/lcms/src/cmssamp.c index 70e469161fc1a6a4319cca30ed10a18585200f93..a9997fa8eec31c43af49eb5da39a22dbde541712 100644 --- a/third_party/lcms2-2.6/src/cmssamp.c +++ b/third_party/lcms/src/cmssamp.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -340,28 +340,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[] } -/* -static -cmsBool IsMonotonic(int n, const cmsFloat64Number Table[]) -{ - int i; - cmsFloat64Number last; - - last = Table[n-1]; - - for (i = n-2; i >= 0; --i) { - - if (Table[i] > last) - - return FALSE; - else - last = Table[i]; - } - - return TRUE; -} -*/ // Calculates the black point of a destination profile. // This algorithm comes from the Adobe paper disclosing its black point compensation method. @@ -486,7 +465,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF // Test for mid range straight (only on relative colorimetric) - NearlyStraightMidrange = TRUE; MinL = outRamp[0]; MaxL = outRamp[255]; if (Intent == INTENT_RELATIVE_COLORIMETRIC) { @@ -502,7 +480,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF // DestinationBlackPoint shall be the same as initialLab. // Otherwise, the DestinationBlackPoint shall be determined // using curve fitting. - if (NearlyStraightMidrange) { cmsLab2XYZ(NULL, BlackPoint, &InitialLab); @@ -513,15 +490,13 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point, - // with a corner and a nearly straight line to the white point. - + // with a corner and a nearly straight line to the white point. for (l=0; l < 256; l++) { yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL); } // find the black point using the least squares error quadratic curve fitting - if (Intent == INTENT_RELATIVE_COLORIMETRIC) { lo = 0.1; hi = 0.5; diff --git a/third_party/lcms2-2.6/src/cmssm.c b/third_party/lcms/src/cmssm.c similarity index 98% rename from third_party/lcms2-2.6/src/cmssm.c rename to third_party/lcms/src/cmssm.c index 5836e15506bd49b0b14e012dc20a1396d3f87963..0f7cb7f637180756b787f08cad16ec9e02d08fd0 100644 --- a/third_party/lcms2-2.6/src/cmssm.c +++ b/third_party/lcms/src/cmssm.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -218,7 +218,8 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2 { cmsFloat64Number a, b, c, d, e, D; cmsFloat64Number sc, sN, sD; - cmsFloat64Number tc, tN, tD; + //cmsFloat64Number tc; // left for future use + cmsFloat64Number tN, tD; cmsVEC3 w0; _cmsVEC3minus(&w0, &line1 ->a, &line2 ->a); @@ -286,7 +287,7 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2 } // finally do the division to get sc and tc sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD); - tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); + //tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); // left for future use. GetPointOfLine(r, line1, sc); return TRUE; @@ -317,7 +318,7 @@ void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD) } -// Auxiliar to retrieve a pointer to the segmentr containing the Lab value +// Auxiliary to retrieve a pointer to the segmentr containing the Lab value static cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp) { @@ -329,7 +330,7 @@ cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp) _cmsAssert(Lab != NULL); _cmsAssert(sp != NULL); - // Center L* by substracting half of its domain, that's 50 + // Center L* by subtracting half of its domain, that's 50 _cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b); // Convert to spherical coordinates @@ -732,3 +733,4 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname) return TRUE; } #endif + diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms/src/cmstypes.c similarity index 98% rename from third_party/lcms2-2.6/src/cmstypes.c rename to third_party/lcms/src/cmstypes.c index 75f1fae32ad3619495860d479343c8b5922a9722..8b02f86ca50203c1ca8eaf56dc6eacb66e77b2f4 100644 --- a/third_party/lcms2-2.6/src/cmstypes.c +++ b/third_party/lcms/src/cmstypes.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -30,7 +30,7 @@ // This file implements every single tag and tag type as described in the ICC spec. Some types // have been deprecated, like ncl and Data. There is no implementation for those types as there // are no profiles holding them. The programmer can also extend this list by defining his own types -// by using the appropiate plug-in. There are three types of plug ins regarding that. First type +// by using the appropriate plug-in. There are three types of plug ins regarding that. First type // allows to define new tags using any existing type. Next plug-in type allows to define new types // and the third one is very specific: allows to extend the number of elements in the multiprocessing // elements special type. @@ -113,7 +113,7 @@ cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* Pl } -// Auxiliar to convert UTF-32 to UTF-16 in some cases +// Auxiliary to convert UTF-32 to UTF-16 in some cases static cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array) { @@ -129,7 +129,7 @@ cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* return TRUE; } -// Auxiliar to read an array of wchar_t +// Auxiliary to read an array of wchar_t static cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array) { @@ -160,7 +160,7 @@ typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self, cmsUInt32Number n, cmsUInt32Number SizeOfTag); -// Helper function to deal with position tables as decribed in ICC spec 4.3 +// Helper function to deal with position tables as described in ICC spec 4.3 // A table of n elements is readed, where first comes n records containing offsets and sizes and // then a block containing the data itself. This allows to reuse same data in more than one entry static @@ -173,6 +173,12 @@ cmsBool ReadPositionTable(struct _cms_typehandler_struct* self, { cmsUInt32Number i; cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; + cmsUInt32Number currentPosition; + + currentPosition = io->Tell(io); + // Verify there is enough space left to read two cmsUInt32Number items for Count items. + if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count) + return FALSE; // Let's take the offsets to each element ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); @@ -951,7 +957,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO cmsMLU* mlu = (cmsMLU*) Ptr; char *Text = NULL; wchar_t *Wide = NULL; - cmsUInt32Number len, len_aligned, len_filler_alignment; + cmsUInt32Number len, len_text, len_tag_requirement, len_aligned; cmsBool rc = FALSE; char Filler[68]; @@ -961,17 +967,18 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO // Get the len of string len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0); - // From ICC3.4: It has been found that textDescriptionType can contain misaligned data + // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data //(see clause 4.1 for the definition of 'aligned'. Because the Unicode language // code and Unicode count immediately follow the ASCII description, their // alignment is not correct if the ASCII count is not a multiple of four. The // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and // writing software must be written carefully in order to handle these alignment // problems. - - // Compute an aligned size - len_aligned = _cmsALIGNLONG(len); - len_filler_alignment = len_aligned - len; + // + // The above last sentence suggest to handle alignment issues in the + // parser. The provided example (Table 69 on Page 60) makes this clear. + // The padding only in the ASCII count is not sufficient for a aligned tag + // size, with the same text size in ASCII and Unicode. // Null strings if (len <= 0) { @@ -992,6 +999,12 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO cmsMLUgetWide(mlu, cmsNoLanguage, cmsNoCountry, Wide, len * sizeof(wchar_t)); } + // Tell the real text len including the null terminator and padding + len_text = (cmsUInt32Number) strlen(Text) + 1; + // Compute an total tag size requirement + len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67); + len_aligned = _cmsALIGNLONG(len_tag_requirement); + // * cmsUInt32Number count; * Description length // * cmsInt8Number desc[count] * NULL terminated ascii string // * cmsUInt32Number ucLangCode; * UniCode language code @@ -1001,20 +1014,14 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO // * cmsUInt8Number scCount; * ScriptCode count // * cmsInt8Number scDesc[67]; * ScriptCode Description - if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error; - if (!io ->Write(io, len, Text)) goto Error; - if (!io ->Write(io, len_filler_alignment, Filler)) goto Error; + if (!_cmsWriteUInt32Number(io, len_text)) goto Error; + if (!io ->Write(io, len_text, Text)) goto Error; if (!_cmsWriteUInt32Number(io, 0)) goto Error; // ucLanguageCode - // This part is tricky: we need an aligned tag size, and the ScriptCode part - // takes 70 bytes, so we need 2 extra bytes to do the alignment - - if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error; - + if (!_cmsWriteUInt32Number(io, len_text)) goto Error; // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t) - if (!_cmsWriteWCharArray(io, len, Wide)) goto Error; - if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error; + if (!_cmsWriteWCharArray(io, len_text, Wide)) goto Error; // ScriptCode Code & count (unused) if (!_cmsWriteUInt16Number(io, 0)) goto Error; @@ -1022,6 +1029,10 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO if (!io ->Write(io, 67, Filler)) goto Error; + // possibly add pad at the end of tag + if(len_aligned - len_tag_requirement > 0) + if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error; + rc = TRUE; Error: @@ -1472,7 +1483,7 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU LargestPosition = EndOfThisString; } - // Now read the remaining of tag and fill all strings. Substract the directory + // Now read the remaining of tag and fill all strings. Subtract the directory SizeOfTag = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number); if (SizeOfTag == 0) { @@ -1506,7 +1517,7 @@ cmsBool Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu =(cmsMLU*) Ptr; cmsUInt32Number HeaderSize; cmsUInt32Number Len, Offset; - int i; + cmsUInt32Number i; if (Ptr == NULL) { @@ -1692,10 +1703,7 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number else for (j=0; j < 256; j++) { - if (Tables != NULL) - val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]); - else - val = (cmsUInt8Number) j; + val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]); if (!_cmsWriteUInt8Number(io, val)) return FALSE; } @@ -3119,7 +3127,8 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i memset(Colorant, 0, sizeof(Colorant)); if (io -> Read(io, Root, 32, 1) != 1) goto Error; - Root[32] = 0; + Root[32] = 0; // To prevent exploits + if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error; @@ -3142,8 +3151,8 @@ static cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; - char prefix[32]; // Prefix for each color name - char suffix[32]; // Suffix for each color name + char prefix[33]; // Prefix for each color name + char suffix[33]; // Suffix for each color name int i, nColors; nColors = cmsNamedColorCount(NamedColorList); @@ -3155,7 +3164,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER strncpy(prefix, (const char*) NamedColorList->Prefix, 32); strncpy(suffix, (const char*) NamedColorList->Suffix, 32); - suffix[31] = prefix[31] = 0; + suffix[32] = prefix[32] = 0; if (!io ->Write(io, 32, prefix)) return FALSE; if (!io ->Write(io, 32, suffix)) return FALSE; @@ -3167,6 +3176,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER char Root[33]; if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0; + Root[32] = 0; if (!io ->Write(io, 32 , Root)) return FALSE; if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE; if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE; @@ -3617,7 +3627,7 @@ country varies for each element: -// Auxiliar, read an string specified as count + string +// Auxiliary, read an string specified as count + string static cmsBool ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section) { @@ -3866,7 +3876,7 @@ cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIO static void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) { - return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening)); + return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsICCViewingConditions)); cmsUNUSED_PARAMETER(n); } @@ -4184,7 +4194,7 @@ cmsBool Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array // is organized as follows: -// array = [e11, e12, ? e1P, e21, e22, ? e2P, ? eQ1, eQ2, ? eQP, e1, e2, ? eQ] +// array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ] static void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) @@ -4314,7 +4324,7 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least GridPoints[i] = (cmsUInt32Number)Dimensions8[i]; } - + // Allocate the true CLUT mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL); if (mpe == NULL) goto Error; @@ -4341,13 +4351,13 @@ Error: static cmsBool Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { - cmsUInt8Number Dimensions8[16]; + cmsUInt8Number Dimensions8[16]; // 16 because the spec says 16 and not max number of channels cmsUInt32Number i; cmsStage* mpe = (cmsStage*) Ptr; _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data; - // Check for maximum number of channels - if (mpe -> InputChannels > 15) return FALSE; + // Check for maximum number of channels supported by lcms + if (mpe -> InputChannels > MAX_INPUT_DIMENSIONS) return FALSE; // Only floats are supported in MPE if (clut ->HasFloatValues == FALSE) return FALSE; @@ -4460,18 +4470,19 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); if (NewLUT == NULL) return NULL; - if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL; - - if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) { - if (NewLUT != NULL) cmsPipelineFree(NewLUT); - *nItems = 0; - return NULL; - } + if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error; + if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error; // Success *nItems = 1; return NewLUT; + // Error +Error: + if (NewLUT != NULL) cmsPipelineFree(NewLUT); + *nItems = 0; + return NULL; + cmsUNUSED_PARAMETER(SizeOfTag); } @@ -4702,10 +4713,10 @@ void *Type_vcgt_Read(struct _cms_typehandler_struct* self, // Y = cX + f | X < d // vcgt formula is: - // Y = (Max ?Min) * (X ^ Gamma) + Min + // Y = (Max - Min) * (X ^ Gamma) + Min // So, the translation is - // a = (Max ?Min) ^ ( 1 / Gamma) + // a = (Max - Min) ^ ( 1 / Gamma) // e = Min // b=c=d=f=0 @@ -5488,8 +5499,9 @@ static _cmsTagLinkedList SupportedTags[] = { { cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]}, { cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]}, { cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]}, - { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]}, - { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL} + { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]}, + { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]}, + { cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, NULL} }; @@ -5601,3 +5613,4 @@ cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig return NULL; } + diff --git a/third_party/lcms2-2.6/src/cmsvirt.c b/third_party/lcms/src/cmsvirt.c similarity index 95% rename from third_party/lcms2-2.6/src/cmsvirt.c rename to third_party/lcms/src/cmsvirt.c index d19ace1651057c96f36d676b3f8490b6dc3475cc..9eff1f7beddc1fd23347c2caa3827da5a279e5eb 100644 --- a/third_party/lcms2-2.6/src/cmsvirt.c +++ b/third_party/lcms/src/cmsvirt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -642,7 +642,7 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) // Create the ICC virtual profile for sRGB space cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) { - cmsCIExyY D65; + cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 }; cmsCIExyYTRIPLE Rec709Primaries = { {0.6400, 0.3300, 1.0}, {0.3000, 0.6000, 1.0}, @@ -651,7 +651,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) cmsToneCurve* Gamma22[3]; cmsHPROFILE hsRGB; - cmsWhitePointFromTemp(&D65, 6504); + // cmsWhitePointFromTemp(&D65, 6504); Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID); if (Gamma22[0] == NULL) return NULL; @@ -679,6 +679,7 @@ typedef struct { cmsFloat64Number Contrast; cmsFloat64Number Hue; cmsFloat64Number Saturation; + cmsBool lAdjustWP; cmsCIEXYZ WPsrc, WPdest; } BCHSWADJUSTS, *LPBCHSWADJUSTS; @@ -708,9 +709,10 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O cmsLCh2Lab(&LabOut, &LChOut); // Move white point in Lab - - cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut); - cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ); + if (bchsw->lAdjustWP) { + cmsLab2XYZ(&bchsw->WPsrc, &XYZ, &LabOut); + cmsXYZ2Lab(&bchsw->WPdest, &LabOut, &XYZ); + } // Back to encoded @@ -744,18 +746,23 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, bchsw.Contrast = Contrast; bchsw.Hue = Hue; bchsw.Saturation = Saturation; + if (TempSrc == TempDest) { - cmsWhitePointFromTemp(&WhitePnt, TempSrc ); - cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); - - cmsWhitePointFromTemp(&WhitePnt, TempDest); - cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); + bchsw.lAdjustWP = FALSE; + } + else { + bchsw.lAdjustWP = TRUE; + cmsWhitePointFromTemp(&WhitePnt, TempSrc); + cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); + cmsWhitePointFromTemp(&WhitePnt, TempDest); + cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); + + } hICC = cmsCreateProfilePlaceholder(ContextID); if (!hICC) // can't allocate return NULL; - cmsSetDeviceClass(hICC, cmsSigAbstractClass); cmsSetColorSpace(hICC, cmsSigLabData); cmsSetPCS(hICC, cmsSigLabData); @@ -988,12 +995,14 @@ typedef struct { } cmsAllowedLUT; +#define cmsSig0 ((cmsTagSignature) 0) + static const cmsAllowedLUT AllowedLUTTypes[] = { - { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, - { FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, - { FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}}, - { TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, + { FALSE, cmsSig0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, + { FALSE, cmsSig0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, + { FALSE, cmsSig0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType } }, + { TRUE, cmsSig0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }}, @@ -1129,15 +1138,20 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat // If no way, then force CLUT that for sure can be written if (AllowedLUT == NULL) { + cmsStage* FirstStage; + cmsStage* LastStage; + dwFlags |= cmsFLAGS_FORCE_CLUT; _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); // Put identity curves if needed - if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) + FirstStage = cmsPipelineGetPtrToFirstStage(LUT); + if (FirstStage != NULL && FirstStage ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn))) goto Error; - if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType) + LastStage = cmsPipelineGetPtrToLastStage(LUT); + if (LastStage != NULL && LastStage ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut))) goto Error; diff --git a/third_party/lcms2-2.6/src/cmswtpnt.c b/third_party/lcms/src/cmswtpnt.c similarity index 99% rename from third_party/lcms2-2.6/src/cmswtpnt.c rename to third_party/lcms/src/cmswtpnt.c index 903fdd74975668efa749487668ce3616a33ecfa6..c6b612584b7d62b7cef010ccc3150feb91532fda 100644 --- a/third_party/lcms2-2.6/src/cmswtpnt.c +++ b/third_party/lcms/src/cmswtpnt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -347,3 +347,5 @@ cmsBool CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result, return TRUE; } + + diff --git a/third_party/lcms/src/cmsxform.c b/third_party/lcms/src/cmsxform.c new file mode 100644 index 0000000000000000000000000000000000000000..b3802f0d57834b10e3115432b23277993f944316 --- /dev/null +++ b/third_party/lcms/src/cmsxform.c @@ -0,0 +1,1331 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2016 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Transformations stuff +// ----------------------------------------------------------------------- + +#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 + +// The Context0 observer adaptation state. +_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + +// Init and duplicate observer adaptation state +void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AdaptationStateContext]; + } + else { + from = &AdaptationStateChunk; + } + + ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); +} + + +// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all +// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states. +cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d) +{ + cmsFloat64Number prev; + _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); + + // Get previous value for return + prev = ptr ->AdaptationState; + + // Set the value if d is positive or zero + if (d >= 0.0) { + + ptr ->AdaptationState = d; + } + + // Always return previous value + return prev; +} + + +// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine +cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) +{ + return cmsSetAdaptationStateTHR(NULL, d); +} + +// ----------------------------------------------------------------------- + +// Alarm codes for 16-bit transformations, because the fixed range of containers there are +// no values left to mark out of gamut. + +#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + +// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be +// encoded in 16 bits. +void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) +{ + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); +} + +// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. +// Values are meant to be encoded in 16 bits. +void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) +{ + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); +} + +void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) +{ + _cmsAssert(NewAlarm != NULL); + + cmsSetAlarmCodesTHR(NULL, NewAlarm); +} + +void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) +{ + _cmsAssert(OldAlarm != NULL); + cmsGetAlarmCodesTHR(NULL, OldAlarm); +} + + +// Init and duplicate alarm codes +void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AlarmCodesContext]; + } + else { + from = &AlarmCodesChunk; + } + + ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); +} + +// ----------------------------------------------------------------------- + +// Get rid of transform resources +void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; + + _cmsAssert(p != NULL); + + if (p -> GamutCheck) + cmsPipelineFree(p -> GamutCheck); + + if (p -> Lut) + cmsPipelineFree(p -> Lut); + + if (p ->InputColorant) + cmsFreeNamedColorList(p ->InputColorant); + + if (p -> OutputColorant) + cmsFreeNamedColorList(p ->OutputColorant); + + if (p ->Sequence) + cmsFreeProfileSequenceDescription(p ->Sequence); + + if (p ->UserData) + p ->FreeUserData(p ->ContextID, p ->UserData); + + _cmsFree(p ->ContextID, (void *) p); +} + +// Apply transform. +void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = 0; // Not used + stride.BytesPerLineOut = 0; + stride.BytesPerPlaneIn = Size; + stride.BytesPerPlaneOut = Size; + + p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride); +} + + +// This is a legacy stride for planar +void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size, cmsUInt32Number Stride) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = 0; + stride.BytesPerLineOut = 0; + stride.BytesPerPlaneIn = Stride; + stride.BytesPerPlaneOut = Stride; + + p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride); +} + +// This is the "fast" function for plugins +void CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + cmsUInt32Number BytesPerLineIn, + cmsUInt32Number BytesPerLineOut, + cmsUInt32Number BytesPerPlaneIn, + cmsUInt32Number BytesPerPlaneOut) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = BytesPerLineIn; + stride.BytesPerLineOut = BytesPerLineOut; + stride.BytesPerPlaneIn = BytesPerPlaneIn; + stride.BytesPerPlaneOut = BytesPerPlaneOut; + + p->xform(p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride); +} + + + +// Transform routines ---------------------------------------------------------------------------------------------------------- + +// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. +// Note that because extended range, we can use a -1.0 value for out of gamut in this case. +static +void FloatXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; + cmsFloat32Number OutOfGamut; + cmsUInt32Number i, j, c, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn); + + // Any gamut chack to do? + if (p->GamutCheck != NULL) { + + // Evaluate gamut marker. + cmsPipelineEvalFloat(fIn, &OutOfGamut, p->GamutCheck); + + // Is current color out of gamut? + if (OutOfGamut > 0.0) { + + // Certainly, out of gamut + for (c = 0; c < cmsMAXCHANNELS; c++) + fOut[c] = -1.0; + + } + else { + // No, proceed normally + cmsPipelineEvalFloat(fIn, fOut, p->Lut); + } + } + else { + + // No gamut check at all + cmsPipelineEvalFloat(fIn, fOut, p->Lut); + } + + + output = p->ToOutputFloat(p, fOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } + +} + + +static +void NullFloatXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) + +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS]; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*) in + strideIn; + output = (cmsUInt8Number*) out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInputFloat(p, fIn, accum, Stride ->BytesPerPlaneIn); + output = p->ToOutputFloat(p, fIn, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + +// 16 bit precision ----------------------------------------------------------------------------------------------------------- + +// Null transformation, only applies formatters. No cache +static +void NullXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS]; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } + +} + + +// No gamut check, no cache, 16 bits +static +void PrecalculatedXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + register cmsUInt8Number* accum; + register cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data); + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } + +} + + +// Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. +static +void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, + const cmsUInt16Number wIn[], + cmsUInt16Number wOut[]) +{ + cmsUInt16Number wOutOfGamut; + + p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data); + if (wOutOfGamut >= 1) { + + cmsUInt16Number i; + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext); + + for (i=0; i < p ->Lut->OutputChannels; i++) { + + wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; + } + } + else + p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); +} + +// Gamut check, No cache, 16 bits. +static +void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + TransformOnePixelWithGamutCheck(p, wIn, wOut); + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + + +// No gamut check, Cache, 16 bits, +static +void CachedXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + _cmsCACHE Cache; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + // Empty buffers for quick memcmp + memset(wIn, 0, sizeof(wIn)); + memset(wOut, 0, sizeof(wOut)); + + // Get copy of zero cache + memcpy(&Cache, &p->Cache, sizeof(Cache)); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + + if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { + + memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); + } + else { + p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data); + + memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); + memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + } + + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + +// All those nice features together +static +void CachedXFORMGamutCheck(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + _cmsCACHE Cache; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + // Empty buffers for quick memcmp + memset(wIn, 0, sizeof(wIn)); + memset(wOut, 0, sizeof(wOut)); + + // Get copy of zero cache + memcpy(&Cache, &p->Cache, sizeof(Cache)); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + + if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { + + memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); + } + else { + TransformOnePixelWithGamutCheck(p, wIn, wOut); + + memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); + memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + } + + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + +// Transform plug-ins ---------------------------------------------------------------------------------------------------- + +// List of used-defined transform factories +typedef struct _cmsTransformCollection_st { + + _cmsTransform2Factory Factory; + cmsBool OldXform; // Factory returns xform function in the old style + + struct _cmsTransformCollection_st *Next; + +} _cmsTransformCollection; + +// The linked list head +_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginTransformList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsTransformPluginChunkType newHead = { NULL }; + _cmsTransformCollection* entry; + _cmsTransformCollection* Anterior = NULL; + _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; + + // Walk the list copying all nodes + for (entry = head->TransformCollection; + entry != NULL; + entry = entry ->Next) { + + _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.TransformCollection == NULL) + newHead.TransformCollection = newEntry; + } + + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); +} + +// Allocates memory for transform plugin factory +void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginTransformList(ctx, src); + } + else { + static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); + } +} + +// Adaptor for old versions of plug-in +static +void _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + + cmsUInt32Number i, strideIn, strideOut; + + _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + void *accum = (cmsUInt8Number*)InputBuffer + strideIn; + void *output = (cmsUInt8Number*)OutputBuffer + strideOut; + + CMMcargo->OldXform(CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn); + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + + + +// Register new ways to transform +cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) +{ + cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; + _cmsTransformCollection* fl; + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); + + if (Data == NULL) { + + // Free the chain. Memory is safely freed at exit + ctx->TransformCollection = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin->factories.xform == NULL) return FALSE; + + + fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); + if (fl == NULL) return FALSE; + + // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case + if (Plugin->base.ExpectedVersion < 2080) { + + fl->OldXform = TRUE; + } + else + fl->OldXform = FALSE; + + // Copy the parameters + fl->Factory = Plugin->factories.xform; + + // Keep linked list + fl ->Next = ctx->TransformCollection; + ctx->TransformCollection = fl; + + // All is ok + return TRUE; +} + + +void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) +{ + _cmsAssert(CMMcargo != NULL); + CMMcargo ->UserData = ptr; + CMMcargo ->FreeUserData = FreePrivateDataFn; +} + +// returns the pointer defined by the plug-in to store private data +void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo ->UserData; +} + +// returns the current formatters +void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) +{ + _cmsAssert(CMMcargo != NULL); + if (FromInput) *FromInput = CMMcargo ->FromInput; + if (ToOutput) *ToOutput = CMMcargo ->ToOutput; +} + +void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) +{ + _cmsAssert(CMMcargo != NULL); + if (FromInput) *FromInput = CMMcargo ->FromInputFloat; + if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; +} + + +// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper +// for separated transforms. If this is the case, +static +_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); + _cmsTransformCollection* Plugin; + + // Allocate needed memory + _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); + if (!p) { + cmsPipelineFree(lut); + return NULL; + } + + // Store the proposed pipeline + p->Lut = lut; + + // Let's see if any plug-in want to do the transform by itself + if (p->Lut != NULL) { + + for (Plugin = ctx->TransformCollection; + Plugin != NULL; + Plugin = Plugin->Next) { + + if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) { + + // Last plugin in the declaration order takes control. We just keep + // the original parameters as a logging. + // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default + // an optimized transform is not reusable. The plug-in can, however, change + // the flags and make it suitable. + + p->ContextID = ContextID; + p->InputFormat = *InputFormat; + p->OutputFormat = *OutputFormat; + p->dwOriginalFlags = *dwFlags; + + // Fill the formatters just in case the optimized routine is interested. + // No error is thrown if the formatter doesn't exist. It is up to the optimization + // factory to decide what to do in those cases. + p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + + // Save the day? + if (Plugin->OldXform) { + p->OldXform = (_cmsTransformFn) p->xform; + p->xform = _cmsTransform2toTransformAdaptor; + } + + return p; + } + } + + // Not suitable for the transform plug-in, let's check the pipeline plug-in + _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + } + + // Check whatever this is a true floating point transform + if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { + + // Get formatter function always return a valid union, but the contents of this union may be NULL. + p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + + if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + cmsDeleteTransform(p); + return NULL; + } + + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { + + p ->xform = NullFloatXFORM; + } + else { + // Float transforms don't use cache, always are non-NULL + p ->xform = FloatXFORM; + } + + } + else { + + if (*InputFormat == 0 && *OutputFormat == 0) { + p ->FromInput = p ->ToOutput = NULL; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + } + else { + + int BytesPerPixelInput; + + p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + + if (p ->FromInput == NULL || p ->ToOutput == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + cmsDeleteTransform(p); + return NULL; + } + + BytesPerPixelInput = T_BYTES(p ->InputFormat); + if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + + } + + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { + + p ->xform = NullXFORM; + } + else { + if (*dwFlags & cmsFLAGS_NOCACHE) { + + if (*dwFlags & cmsFLAGS_GAMUTCHECK) + p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cache + else + p ->xform = PrecalculatedXFORM; // No cache, no gamut check + } + else { + + if (*dwFlags & cmsFLAGS_GAMUTCHECK) + p ->xform = CachedXFORMGamutCheck; // Gamut check, cache + else + p ->xform = CachedXFORM; // No gamut check, cache + + } + } + } + + p ->InputFormat = *InputFormat; + p ->OutputFormat = *OutputFormat; + p ->dwOriginalFlags = *dwFlags; + p ->ContextID = ContextID; + p ->UserData = NULL; + return p; +} + +static +cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) +{ + cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; + cmsColorSpaceSignature PostColorSpace; + int i; + + if (nProfiles <= 0) return FALSE; + if (hProfiles[0] == NULL) return FALSE; + + *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); + + for (i=0; i < nProfiles; i++) { + + cmsProfileClassSignature cls; + cmsHPROFILE hProfile = hProfiles[i]; + + int lIsInput = (PostColorSpace != cmsSigXYZData) && + (PostColorSpace != cmsSigLabData); + + if (hProfile == NULL) return FALSE; + + cls = cmsGetDeviceClass(hProfile); + + if (cls == cmsSigNamedColorClass) { + + ColorSpaceIn = cmsSig1colorData; + ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(hProfile) : cmsGetColorSpace(hProfile); + } + else + if (lIsInput || (cls == cmsSigLinkClass)) { + + ColorSpaceIn = cmsGetColorSpace(hProfile); + ColorSpaceOut = cmsGetPCS(hProfile); + } + else + { + ColorSpaceIn = cmsGetPCS(hProfile); + ColorSpaceOut = cmsGetColorSpace(hProfile); + } + + if (i==0) + *Input = ColorSpaceIn; + + PostColorSpace = ColorSpaceOut; + } + + *Output = PostColorSpace; + + return TRUE; +} + +// Check colorspace +static +cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) +{ + int Space1 = T_COLORSPACE(dwFormat); + int Space2 = _cmsLCMScolorSpace(Check); + + if (Space1 == PT_ANY) return TRUE; + if (Space1 == Space2) return TRUE; + + if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; + if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; + + return FALSE; +} + +// ---------------------------------------------------------------------------------------------------------------- + +// Jun-21-2000: Some profiles (those that comes with W2K) comes +// with the media white (media black?) x 100. Add a sanity check + +static +void NormalizeXYZ(cmsCIEXYZ* Dest) +{ + while (Dest -> X > 2. && + Dest -> Y > 2. && + Dest -> Z > 2.) { + + Dest -> X /= 10.; + Dest -> Y /= 10.; + Dest -> Z /= 10.; + } +} + +static +void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) +{ + if (src == NULL) { + wtPt ->X = cmsD50X; + wtPt ->Y = cmsD50Y; + wtPt ->Z = cmsD50Z; + } + else { + wtPt ->X = src->X; + wtPt ->Y = src->Y; + wtPt ->Z = src->Z; + + NormalizeXYZ(wtPt); + } + +} + +// New to lcms 2.0 -- have all parameters available. +cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, + cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsHPROFILE hGamutProfile, + cmsUInt32Number nGamutPCSposition, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number dwFlags) +{ + _cmsTRANSFORM* xform; + cmsColorSpaceSignature EntryColorSpace; + cmsColorSpaceSignature ExitColorSpace; + cmsPipeline* Lut; + cmsUInt32Number LastIntent = Intents[nProfiles-1]; + + // If it is a fake transform + if (dwFlags & cmsFLAGS_NULLTRANSFORM) + { + return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); + } + + // If gamut check is requested, make sure we have a gamut profile + if (dwFlags & cmsFLAGS_GAMUTCHECK) { + if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; + } + + // On floating point transforms, inhibit cache + if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) + dwFlags |= cmsFLAGS_NOCACHE; + + // Mark entry/exit spaces + if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { + cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); + return NULL; + } + + // Check if proper colorspaces + if (!IsProperColorSpace(EntryColorSpace, InputFormat)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); + return NULL; + } + + if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); + return NULL; + } + + // Create a pipeline with all transformations + Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (Lut == NULL) { + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); + return NULL; + } + + // Check channel count + if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || + (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { + cmsPipelineFree(Lut); + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); + return NULL; + } + + + // All seems ok + xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); + if (xform == NULL) { + return NULL; + } + + // Keep values + xform ->EntryColorSpace = EntryColorSpace; + xform ->ExitColorSpace = ExitColorSpace; + xform ->RenderingIntent = Intents[nProfiles-1]; + + // Take white points + SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag)); + SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); + + + // Create a gamut check LUT if requested + if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) + xform ->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, + BPC, Intents, + AdaptationStates, + nGamutPCSposition, + hGamutProfile); + + + // Try to read input and output colorant table + if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) { + + // Input table can only come in this way. + xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag)); + } + + // Output is a little bit more complex. + if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) { + + // This tag may exist only on devicelink profiles. + if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { + + // It may be NULL if error + xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); + } + + } else { + + if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) { + + xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)); + } + } + + // Store the sequence of profiles + if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { + xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); + } + else + xform ->Sequence = NULL; + + // If this is a cached transform, init first value, which is zero (16 bits only) + if (!(dwFlags & cmsFLAGS_NOCACHE)) { + + memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); + + if (xform ->GamutCheck != NULL) { + TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut); + } + else { + + xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data); + } + + } + + return (cmsHTRANSFORM) xform; +} + +// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + cmsUInt32Number i; + cmsBool BPC[256]; + cmsUInt32Number Intents[256]; + cmsFloat64Number AdaptationStates[256]; + + if (nProfiles <= 0 || nProfiles > 255) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); + return NULL; + } + + for (i=0; i < nProfiles; i++) { + BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; + Intents[i] = Intent; + AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1); + } + + + return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); +} + + + +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + + if (nProfiles <= 0 || nProfiles > 255) { + cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); + return NULL; + } + + return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]), + hProfiles, + nProfiles, + InputFormat, + OutputFormat, + Intent, + dwFlags); +} + +cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, + cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + + cmsHPROFILE hArray[2]; + + hArray[0] = Input; + hArray[1] = Output; + + return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags); +} + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags); +} + + +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, + cmsHPROFILE InputProfile, + cmsUInt32Number InputFormat, + cmsHPROFILE OutputProfile, + cmsUInt32Number OutputFormat, + cmsHPROFILE ProofingProfile, + cmsUInt32Number nIntent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags) +{ + cmsHPROFILE hArray[4]; + cmsUInt32Number Intents[4]; + cmsBool BPC[4]; + cmsFloat64Number Adaptation[4]; + cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; + + + hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; + Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; + BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; + + Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1); + + if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) + return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); + + return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, + ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); + +} + + +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile, + cmsUInt32Number InputFormat, + cmsHPROFILE OutputProfile, + cmsUInt32Number OutputFormat, + cmsHPROFILE ProofingProfile, + cmsUInt32Number nIntent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags) +{ + return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile), + InputProfile, + InputFormat, + OutputProfile, + OutputFormat, + ProofingProfile, + nIntent, + ProofingIntent, + dwFlags); +} + + +// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed +cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + + if (xform == NULL) return NULL; + return xform -> ContextID; +} + +// Grab the input/output formats +cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + + if (xform == NULL) return 0; + return xform->InputFormat; +} + +cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + + if (xform == NULL) return 0; + return xform->OutputFormat; +} + +// For backwards compatibility +cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + cmsFormatter16 FromInput, ToOutput; + + + // We only can afford to change formatters if previous transform is at least 16 bits + if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { + + cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision"); + return FALSE; + } + + FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + + if (FromInput == NULL || ToOutput == NULL) { + + cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + return FALSE; + } + + xform ->InputFormat = InputFormat; + xform ->OutputFormat = OutputFormat; + xform ->FromInput = FromInput; + xform ->ToOutput = ToOutput; + return TRUE; +} diff --git a/third_party/lcms2-2.6/src/lcms2_internal.h b/third_party/lcms/src/lcms2_internal.h similarity index 95% rename from third_party/lcms2-2.6/src/lcms2_internal.h rename to third_party/lcms/src/lcms2_internal.h index cc76d488d0dcb9f8e0d2004076d79ecffbbfe797..115ac59701879e1a716fd24a6f85def67b368359 100644 --- a/third_party/lcms2-2.6/src/lcms2_internal.h +++ b/third_party/lcms/src/lcms2_internal.h @@ -1,8 +1,7 @@ -//<<<+++OPENSOURCE -//<<<+++OPENSOURCE_MUST_BEGIN COMMENT==TRUE + // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -29,7 +28,7 @@ // Include plug-in foundation #ifndef _lcms_plugin_H -#include "third_party/lcms2-2.6/include/lcms2_plugin.h" +# include "third_party/lcms/include/lcms2_plugin.h" #endif // ctype is part of C99 as per 7.1.2 @@ -58,7 +57,15 @@ #define _cmsALIGNLONG(x) (((x)+(sizeof(cmsUInt32Number)-1)) & ~(sizeof(cmsUInt32Number)-1)) // Alignment to memory pointer -#define _cmsALIGNMEM(x) (((x)+(sizeof(void *) - 1)) & ~(sizeof(void *) - 1)) + +// (Ultra)SPARC with gcc requires ptr alignment of 8 bytes +// even though sizeof(void *) is only four: for greatest flexibility +// allow the build to specify ptr alignment. +#ifndef CMS_PTR_ALIGNMENT +# define CMS_PTR_ALIGNMENT sizeof(void *) +#endif + +#define _cmsALIGNMEM(x) (((x)+(CMS_PTR_ALIGNMENT - 1)) & ~(CMS_PTR_ALIGNMENT - 1)) // Maximum encodeable values in floating point #define MAX_ENCODEABLE_XYZ (1.0 + 32767.0/32768.0) @@ -195,11 +202,17 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) // Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical // section, even when they changed the underlying algorithm to be more scalable. // The final parts of the critical section object are unimportant, and can be set -// to zero for their defaults. This yields an initialization macro: +// to zero for their defaults. This yields to an initialization macro: typedef CRITICAL_SECTION _cmsMutex; -#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0} +#define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0} + +#ifdef _MSC_VER +# if (_MSC_VER >= 1800) +# pragma warning(disable : 26135) +# endif +#endif cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) { @@ -285,38 +298,38 @@ typedef int _cmsMutex; cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } #endif @@ -657,8 +670,8 @@ struct _cms_MLU_struct { cmsContext ContextID; // The directory - int AllocatedEntries; - int UsedEntries; + cmsUInt32Number AllocatedEntries; + cmsUInt32Number UsedEntries; _cmsMLUentry* Entries; // Array of pointers to strings allocated in MemPool // The Pool @@ -726,7 +739,7 @@ typedef struct _cms_iccprofile_struct { // Dictionary cmsUInt32Number TagCount; cmsTagSignature TagNames[MAX_TABLE_TAG]; - cmsTagSignature TagLinked[MAX_TABLE_TAG]; // The tag to wich is linked (0=none) + cmsTagSignature TagLinked[MAX_TABLE_TAG]; // The tag to which is linked (0=none) cmsUInt32Number TagSizes[MAX_TABLE_TAG]; // Size on disk cmsUInt32Number TagOffsets[MAX_TABLE_TAG]; cmsBool TagSaveAsRaw[MAX_TABLE_TAG]; // True to write uncooked @@ -824,6 +837,8 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID); +cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels); + // For curve set only cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe); @@ -952,7 +967,7 @@ typedef struct _cmstransform_struct { cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference // Points to transform code - _cmsTransformFn xform; + _cmsTransform2Fn xform; // Formatters, cannot be embedded into LUT because cache cmsFormatter16 FromInput; @@ -998,9 +1013,20 @@ typedef struct _cmstransform_struct { void* UserData; _cmsFreeUserDataFn FreeUserData; + // A way to provide backwards compatibility with full xform plugins + _cmsTransformFn OldXform; + } _cmsTRANSFORM; -// -------------------------------------------------------------------------------------------------- +// Copies extra channels from input to output if the original flags in the transform structure +// instructs to do so. This function is called on all standard transform functions. +void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride); + +// ----------------------------------------------------------------------------------------------------------------------- cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID, cmsUInt32Number nProfiles, @@ -1029,4 +1055,3 @@ cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePoint #define _lcms_internal_H #endif -//<<<+++OPENSOURCE_MUST_END diff --git a/third_party/lcms2-2.6/0000-tag-type-confusion.patch b/third_party/lcms2-2.6/0000-tag-type-confusion.patch deleted file mode 100644 index df94cb7bfef6fd9563117120e19636cb1b23b406..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0000-tag-type-confusion.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsio0.c b/third_party/lcms2-2.6/src/cmsio0.c -index 6549d15..5f9f08a 100644 ---- a/third_party/lcms2-2.6/src/cmsio0.c -+++ b/third_party/lcms2-2.6/src/cmsio0.c -@@ -719,7 +719,8 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) - for (j=0; j < Icc ->TagCount; j++) { - - if ((Icc ->TagOffsets[j] == Tag.offset) && -- (Icc ->TagSizes[j] == Tag.size)) { -+ (Icc ->TagSizes[j] == Tag.size) && -+ (Icc ->TagNames[j] == Tag.sig)) { - - Icc ->TagLinked[Icc ->TagCount] = Icc ->TagNames[j]; - } diff --git a/third_party/lcms2-2.6/0001-from16-to-8-overflow.patch b/third_party/lcms2-2.6/0001-from16-to-8-overflow.patch deleted file mode 100644 index 6e7b16d061f69e55f553a445065d3f0867eafa01..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0001-from16-to-8-overflow.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/lcms2_internal.h b/third_party/lcms2-2.6/src/lcms2_internal.h -index 8617e92..cc76d48 100644 ---- a/third_party/lcms2-2.6/src/lcms2_internal.h -+++ b/third_party/lcms2-2.6/src/lcms2_internal.h -@@ -94,7 +94,7 @@ - - // A fast way to convert from/to 16 <-> 8 bits - #define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb)) --#define FROM_16_TO_8(rgb) (cmsUInt8Number) ((((rgb) * 65281 + 8388608) >> 24) & 0xFF) -+#define FROM_16_TO_8(rgb) (cmsUInt8Number) ((((cmsUInt32Number)(rgb) * 65281U + 8388608U) >> 24) & 0xFFU) - - // Code analysis is broken on asserts - #ifdef _MSC_VER diff --git a/third_party/lcms2-2.6/0002-infinite-loop-GrowNamedColorList.patch b/third_party/lcms2-2.6/0002-infinite-loop-GrowNamedColorList.patch deleted file mode 100644 index 9c01a51579df36102546024b95f6c703e92c391b..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0002-infinite-loop-GrowNamedColorList.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsnamed.c b/third_party/lcms2-2.6/src/cmsnamed.c -index acfd1c8..ef1eb30 100644 ---- a/third_party/lcms2-2.6/src/cmsnamed.c -+++ b/third_party/lcms2-2.6/src/cmsnamed.c -@@ -514,8 +514,12 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn - v ->nColors = 0; - v ->ContextID = ContextID; - -- while (v -> Allocated < n) -- GrowNamedColorList(v); -+ while (v -> Allocated < n) { -+ if (!GrowNamedColorList(v)) { -+ cmsFreeNamedColorList(v); -+ return NULL; -+ } -+ } - - strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1); - strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1); -@@ -544,8 +548,12 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) - if (NewNC == NULL) return NULL; - - // For really large tables we need this -- while (NewNC ->Allocated < v ->Allocated) -- GrowNamedColorList(NewNC); -+ while (NewNC ->Allocated < v ->Allocated) { -+ if (!GrowNamedColorList(NewNC)) { -+ cmsFreeNamedColorList(NewNC); -+ return NULL; -+ } -+ } - - memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix)); - memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix)); diff --git a/third_party/lcms2-2.6/0003-uninit.patch b/third_party/lcms2-2.6/0003-uninit.patch deleted file mode 100644 index 476007e7765ec8fa6348f96d3befe598d5fc58e2..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0003-uninit.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 06742b5..44c5b87 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -2964,7 +2964,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER - { - cmsUInt32Number i, Count; - cmsNAMEDCOLORLIST* List; -- char Name[34]; -+ char Name[33]; - cmsUInt16Number PCS[3]; - - -@@ -2979,7 +2979,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER - for (i=0; i < Count; i++) { - - if (io ->Read(io, Name, 32, 1) != 1) goto Error; -- Name[33] = 0; -+ Name[32] = 0; - - if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; - -@@ -3106,6 +3106,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i - - memset(Colorant, 0, sizeof(Colorant)); - if (io -> Read(io, Root, 32, 1) != 1) return NULL; -+ Root[32] = 0; - if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; - if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error; - diff --git a/third_party/lcms2-2.6/0004-memory-leak-Type_Curve_Read.patch b/third_party/lcms2-2.6/0004-memory-leak-Type_Curve_Read.patch deleted file mode 100644 index 341a1c6b47cac9727669b6ebe5c618044456ee15..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0004-memory-leak-Type_Curve_Read.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 06742b5..9fe5e2a 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -1112,7 +1112,10 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm - NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL); - if (!NewGamma) return NULL; - -- if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL; -+ if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) { -+ cmsFreeToneCurve(NewGamma); -+ return NULL; -+ } - - *nItems = 1; - return NewGamma; -@@ -2350,7 +2353,10 @@ cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUI - - for (i=0; i < Data ->nEntries; i++) { - -- if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; -+ if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) { -+ cmsStageFree(CLUT); -+ return NULL; -+ } - Data ->Tab.T[i] = FROM_8_TO_16(v); - } - diff --git a/third_party/lcms2-2.6/0005-memory-leak-AllocEmptyTransform.patch b/third_party/lcms2-2.6/0005-memory-leak-AllocEmptyTransform.patch deleted file mode 100644 index a85a9682bd9e11223da66a9811b2e673b130cbbc..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0005-memory-leak-AllocEmptyTransform.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsxform.c b/third_party/lcms2-2.6/src/cmsxform.c -index eddb9bd..6466d27 100644 ---- a/third_party/lcms2-2.6/src/cmsxform.c -+++ b/third_party/lcms2-2.6/src/cmsxform.c -@@ -593,7 +593,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, - - // Allocate needed memory - _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); -- if (!p) return NULL; -+ if (!p) { -+ cmsPipelineFree(lut); -+ return NULL; -+ } - - // Store the proposed pipeline - p ->Lut = lut; -@@ -643,7 +646,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, - if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { - - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); -- _cmsFree(ContextID, p); -+ cmsDeleteTransform(p); - return NULL; - } - -@@ -673,7 +676,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, - if (p ->FromInput == NULL || p ->ToOutput == NULL) { - - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); -- _cmsFree(ContextID, p); -+ cmsDeleteTransform(p); - return NULL; - } - diff --git a/third_party/lcms2-2.6/0006-memory-leak-Type_NamedColor_Read.patch b/third_party/lcms2-2.6/0006-memory-leak-Type_NamedColor_Read.patch deleted file mode 100644 index 5d25d5a737ca1d2962c65a18dce6be7fe300ac89..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0006-memory-leak-Type_NamedColor_Read.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index feba387..4d24fc2 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -3102,7 +3102,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i - - if (nDeviceCoords > cmsMAXCHANNELS) { - cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords); -- return 0; -+ goto Error; - } - for (i=0; i < count; i++) { - -@@ -3111,7 +3111,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i - char Root[33]; - - memset(Colorant, 0, sizeof(Colorant)); -- if (io -> Read(io, Root, 32, 1) != 1) return NULL; -+ if (io -> Read(io, Root, 32, 1) != 1) goto Error; - Root[32] = 0; - if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; - if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error; diff --git a/third_party/lcms2-2.6/0007-memory-leak-OptimizeByResampling.patch b/third_party/lcms2-2.6/0007-memory-leak-OptimizeByResampling.patch deleted file mode 100644 index 2c55b94fa1d278bba1a648cc2115a71e8ed2e5bb..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0007-memory-leak-OptimizeByResampling.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsopt.c b/third_party/lcms2-2.6/src/cmsopt.c -index f885ef3..684910d 100644 ---- a/third_party/lcms2-2.6/src/cmsopt.c -+++ b/third_party/lcms2-2.6/src/cmsopt.c -@@ -612,7 +612,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 - - // Allocate the CLUT - CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL); -- if (CLUT == NULL) return FALSE; -+ if (CLUT == NULL) goto Error; - - // Add the CLUT to the destination LUT - if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) { diff --git a/third_party/lcms2-2.6/0008-memory-leak-Type_MPEmatrix_Read.patch b/third_party/lcms2-2.6/0008-memory-leak-Type_MPEmatrix_Read.patch deleted file mode 100644 index 93ee3d3fde1cf547d130eaecceb949a52e3fd8b1..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0008-memory-leak-Type_MPEmatrix_Read.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 441d6bb..15199c7 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -4203,7 +4203,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io - - cmsFloat32Number v; - -- if (!_cmsReadFloat32Number(io, &v)) return NULL; -+ if (!_cmsReadFloat32Number(io, &v)) { -+ _cmsFree(self ->ContextID, Matrix); -+ _cmsFree(self ->ContextID, Offsets); -+ return NULL; -+ } - Matrix[i] = v; - } - -@@ -4212,7 +4216,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io - - cmsFloat32Number v; - -- if (!_cmsReadFloat32Number(io, &v)) return NULL; -+ if (!_cmsReadFloat32Number(io, &v)) { -+ _cmsFree(self ->ContextID, Matrix); -+ _cmsFree(self ->ContextID, Offsets); -+ return NULL; -+ } - Offsets[i] = v; - } - diff --git a/third_party/lcms2-2.6/0009-cmsStageAllocMatrix-param-swap.patch b/third_party/lcms2-2.6/0009-cmsStageAllocMatrix-param-swap.patch deleted file mode 100644 index 26db3dd2235c857e4f9fc8b147d47f0337e734f9..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0009-cmsStageAllocMatrix-param-swap.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmslut.c b/third_party/lcms2-2.6/src/cmslut.c -index 73e6726..9b0eb4b 100644 ---- a/third_party/lcms2-2.6/src/cmslut.c -+++ b/third_party/lcms2-2.6/src/cmslut.c -@@ -414,13 +414,13 @@ cmsStage* CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number R - - if (Offset != NULL) { - -- NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Cols, sizeof(cmsFloat64Number)); -+ NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Rows, sizeof(cmsFloat64Number)); - if (NewElem->Offset == NULL) { - MatrixElemTypeFree(NewMPE); - return NULL; - } - -- for (i=0; i < Cols; i++) { -+ for (i=0; i < Rows; i++) { - NewElem ->Offset[i] = Offset[i]; - } - diff --git a/third_party/lcms2-2.6/0010-reject-nan.patch b/third_party/lcms2-2.6/0010-reject-nan.patch deleted file mode 100644 index 2cf49ca0f7b805aa67adfb5f0b2a725b7e53e321..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0010-reject-nan.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsplugin.c b/third_party/lcms2-2.6/src/cmsplugin.c -index 8903d2b..b95befb 100644 ---- a/third_party/lcms2-2.6/src/cmsplugin.c -+++ b/third_party/lcms2-2.6/src/cmsplugin.c -@@ -179,6 +179,8 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) - - tmp = _cmsAdjustEndianess32(tmp); - *n = *(cmsFloat32Number*) &tmp; -+ if (isnan(*n)) -+ return FALSE; - } - return TRUE; - } diff --git a/third_party/lcms2-2.6/0011-memory-leak-ReadSegmentedCurve.patch b/third_party/lcms2-2.6/0011-memory-leak-ReadSegmentedCurve.patch deleted file mode 100644 index a6cfe02b8c93b35fe10685f529837e5c72713db1..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0011-memory-leak-ReadSegmentedCurve.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 15199c7..04dd0c4 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -3968,7 +3968,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND - case cmsSigSampledCurveSeg: { - cmsUInt32Number Count; - -- if (!_cmsReadUInt32Number(io, &Count)) return NULL; -+ if (!_cmsReadUInt32Number(io, &Count)) goto Error; - - Segments[i].nGridPoints = Count; - Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number)); -@@ -3987,7 +3987,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND - _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); - cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String); - } -- return NULL; -+ goto Error; - - } - } -@@ -4001,7 +4001,12 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND - return Curve; - - Error: -- if (Segments) _cmsFree(self ->ContextID, Segments); -+ if (Segments) { -+ for (i=0; i < nSegments; i++) { -+ if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints); -+ } -+ _cmsFree(self ->ContextID, Segments); -+ } - return NULL; - } - diff --git a/third_party/lcms2-2.6/0012-backport-c0a98d86.patch b/third_party/lcms2-2.6/0012-backport-c0a98d86.patch deleted file mode 100644 index 3041e31d76871aa8f9e436c79f0299bda2fa8c68..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0012-backport-c0a98d86.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsintrp.c b/third_party/lcms2-2.6/src/cmsintrp.c -index 5d5f35d..14c6856 100644 ---- a/third_party/lcms2-2.6/src/cmsintrp.c -+++ b/third_party/lcms2-2.6/src/cmsintrp.c -@@ -215,7 +215,7 @@ void LinLerp1D(register const cmsUInt16Number Value[], - // To prevent out of bounds indexing - cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) - { -- return v < 0.0f ? 0.0f : (v > 1.0f ? 1.0f : v); -+ return ((v < 0.0f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v); - } - - // Floating-point version of 1D interpolation -diff --git a/third_party/lcms2-2.6/src/cmsio0.c b/third_party/lcms2-2.6/src/cmsio0.c -index 5f9f08a..3ed730a 100644 ---- a/third_party/lcms2-2.6/src/cmsio0.c -+++ b/third_party/lcms2-2.6/src/cmsio0.c -@@ -1475,6 +1475,17 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) - // If the element is already in memory, return the pointer - if (Icc -> TagPtrs[n]) { - -+ if (Icc->TagTypeHandlers[n] == NULL) goto Error; -+ -+ // Sanity check -+ BaseType = Icc->TagTypeHandlers[n]->Signature; -+ if (BaseType == 0) goto Error; -+ -+ TagDescriptor = _cmsGetTagDescriptor(Icc->ContextID, sig); -+ if (TagDescriptor == NULL) goto Error; -+ -+ if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; -+ - if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked - - _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 04dd0c4..386439b 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -4297,8 +4297,12 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, - - // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number - nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans; -- for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i]; - -+ for (i = 0; i < nMaxGrids; i++) { -+ if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least -+ GridPoints[i] = (cmsUInt32Number)Dimensions8[i]; -+ } -+ - // Allocate the true CLUT - mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL); - if (mpe == NULL) goto Error; diff --git a/third_party/lcms2-2.6/0013-utf8.patch b/third_party/lcms2-2.6/0013-utf8.patch deleted file mode 100644 index c28d2c281bea0ac612f7513c56dfe62cafd90e7f..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0013-utf8.patch +++ /dev/null @@ -1,99 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmscgats.c b/third_party/lcms2-2.6/src/cmscgats.c -index 9017435..5720c66 100644 ---- a/third_party/lcms2-2.6/src/cmscgats.c -+++ b/third_party/lcms2-2.6/src/cmscgats.c -@@ -258,7 +258,7 @@ static PROPERTY PredefinedProperties[] = { - // needed. - - {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during -- // measurement. Allowed values are black? white? or {"na". -+ // measurement. Allowed values are "black" "white" or "na". - - {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic - -@@ -274,7 +274,7 @@ static PROPERTY PredefinedProperties[] = { - // denote the use of filters such as none, D65, Red, Green or Blue. - - {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed -- // values are {"yes? white? none?or na? -+ // values are "yes" "white" "none" or "na" - - {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the - // calculation of various data parameters (2 degree and 10 degree), CIE standard -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 386439b..e5ed06c 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -962,7 +962,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO - len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0); - - // From ICC3.4: It has been found that textDescriptionType can contain misaligned data -- //(see clause 4.1 for the definition of aligned?. Because the Unicode language -+ //(see clause 4.1 for the definition of 'aligned'. Because the Unicode language - // code and Unicode count immediately follow the ASCII description, their - // alignment is not correct if the ASCII count is not a multiple of four. The - // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and -@@ -3064,9 +3064,10 @@ void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr) - //The namedColor2Type is a count value and array of structures that provide color - //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional - //device representation of the color are given. Both representations are 16-bit values. --//The device representation corresponds to the headers color space of data?field. --//This representation should be consistent with the number of device components?//field in the namedColor2Type. If this field is 0, device coordinates are not provided. --//The PCS representation corresponds to the headers PCS field. The PCS representation -+//The device representation corresponds to the header's 'color space of data' field. -+//This representation should be consistent with the 'number of device components' -+//field in the namedColor2Type. If this field is 0, device coordinates are not provided. -+//The PCS representation corresponds to the header's PCS field. The PCS representation - //is always provided. Color names are fixed-length, 32-byte fields including null - //termination. In order to maintain maximum portability, it is strongly recommended - //that special characters of the 7-bit ASCII set not be used. -@@ -3809,7 +3810,8 @@ void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr) - // ******************************************************************************** - // - //This type represents a set of viewing condition parameters including: --//CIE absolute?illuminant white point tristimulus values and CIE absolute?//surround tristimulus values. -+//CIE 'absolute'illuminant white point tristimulus values and CIE 'absolute' -+//surround tristimulus values. - - static - void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) -@@ -3895,7 +3897,7 @@ void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr) - } - - // Each curve is stored in one or more curve segments, with break-points specified between curve segments. --// The first curve segment always starts at Infinity, and the last curve segment always ends at +Infinity. The -+// The first curve segment always starts at -Infinity, and the last curve segment always ends at +Infinity. The - // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be - // specified either in terms of a formula, or by a sampled curve. - -diff --git a/third_party/lcms2-2.6/src/cmsvirt.c b/third_party/lcms2-2.6/src/cmsvirt.c -index b324c99..d19ace1 100644 ---- a/third_party/lcms2-2.6/src/cmsvirt.c -+++ b/third_party/lcms2-2.6/src/cmsvirt.c -@@ -612,18 +612,18 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void) - - //sRGB Curves are defined by: - // --//If RsRGB,GsRGB, BsRGB < 0.04045 -+//If R'sRGB,G'sRGB, B'sRGB < 0.04045 - // --// R = RsRGB / 12.92 --// G = GsRGB / 12.92 --// B = BsRGB / 12.92 -+// R = R'sRGB / 12.92 -+// G = G'sRGB / 12.92 -+// B = B'sRGB / 12.92 - // - // --//else if RsRGB,GsRGB, BsRGB >= 0.04045 -+//else if R'sRGB,G'sRGB, B'sRGB >= 0.04045 - // --// R = ((RsRGB + 0.055) / 1.055)^2.4 --// G = ((GsRGB + 0.055) / 1.055)^2.4 --// B = ((BsRGB + 0.055) / 1.055)^2.4 -+// R = ((R'sRGB + 0.055) / 1.055)^2.4 -+// G = ((G'sRGB + 0.055) / 1.055)^2.4 -+// B = ((B'sRGB + 0.055) / 1.055)^2.4 - - static - cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) diff --git a/third_party/lcms2-2.6/0014-avoid-fixed-inf.patch b/third_party/lcms2-2.6/0014-avoid-fixed-inf.patch deleted file mode 100644 index 563787a9416fc60e52092d8a79125a76c317757d..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0014-avoid-fixed-inf.patch +++ /dev/null @@ -1,95 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsopt.c b/third_party/lcms2-2.6/src/cmsopt.c -index 684910d..76de015 100644 ---- a/third_party/lcms2-2.6/src/cmsopt.c -+++ b/third_party/lcms2-2.6/src/cmsopt.c -@@ -1443,7 +1443,7 @@ void MatShaperEval16(register const cmsUInt16Number In[], - - // This table converts from 8 bits to 1.14 after applying the curve - static --void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) -+cmsBool FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) - { - int i; - cmsFloat32Number R, y; -@@ -1452,14 +1452,17 @@ void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) - - R = (cmsFloat32Number) (i / 255.0); - y = cmsEvalToneCurveFloat(Curve, R); -+ if (isinf(y)) -+ return FALSE; - - Table[i] = DOUBLE_TO_1FIXED14(y); - } -+ return TRUE; - } - - // This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve - static --void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput) -+cmsBool FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput) - { - int i; - cmsFloat32Number R, Val; -@@ -1468,6 +1471,8 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi - - R = (cmsFloat32Number) (i / 16384.0); - Val = cmsEvalToneCurveFloat(Curve, R); // Val comes 0..1.0 -+ if (isinf(Val)) -+ return FALSE; - - if (Is8BitsOutput) { - -@@ -1482,6 +1487,7 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi - } - else Table[i] = _cmsQuickSaturateWord(Val * 65535.0); - } -+ return TRUE; - } - - // Compute the matrix-shaper structure -@@ -1499,13 +1505,19 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c - p -> ContextID = Dest -> ContextID; - - // Precompute tables -- FillFirstShaper(p ->Shaper1R, Curve1[0]); -- FillFirstShaper(p ->Shaper1G, Curve1[1]); -- FillFirstShaper(p ->Shaper1B, Curve1[2]); -+ if (!FillFirstShaper(p ->Shaper1R, Curve1[0])) -+ goto Error; -+ if (!FillFirstShaper(p ->Shaper1G, Curve1[1])) -+ goto Error; -+ if (!FillFirstShaper(p ->Shaper1B, Curve1[2])) -+ goto Error; - -- FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits); -- FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits); -- FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits); -+ if (!FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits)) -+ goto Error; -+ if (!FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits)) -+ goto Error; -+ if (!FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits)) -+ goto Error; - - // Convert matrix to nFixed14. Note that those values may take more than 16 bits as - for (i=0; i < 3; i++) { -@@ -1531,6 +1543,9 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c - // Fill function pointers - _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper); - return TRUE; -+Error: -+ _cmsFree(Dest->ContextID, p); -+ return FALSE; - } - - // 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast! -@@ -1606,7 +1621,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 - *dwFlags |= cmsFLAGS_NOCACHE; - - // Setup the optimizarion routines -- SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat); -+ if (!SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat)) -+ goto Error; - } - - cmsPipelineFree(Src); diff --git a/third_party/lcms2-2.6/0015-sanitize-float-read.patch b/third_party/lcms2-2.6/0015-sanitize-float-read.patch deleted file mode 100644 index 70dc7b35cfea6d8f2e07359661f9c9744efe1897..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0015-sanitize-float-read.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmsplugin.c b/third_party/lcms2-2.6/src/cmsplugin.c -index b95befb..4ba998b 100644 ---- a/third_party/lcms2-2.6/src/cmsplugin.c -+++ b/third_party/lcms2-2.6/src/cmsplugin.c -@@ -182,7 +182,9 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) - if (isnan(*n)) - return FALSE; - } -- return TRUE; -+ -+ // fpclassify() required by C99 -+ return (fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL); - } - - diff --git a/third_party/lcms2-2.6/0016-check-LUT-and-MPE.patch b/third_party/lcms2-2.6/0016-check-LUT-and-MPE.patch deleted file mode 100644 index bfa84e2eedaca03f71de37f0b016c7b502e804ec..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0016-check-LUT-and-MPE.patch +++ /dev/null @@ -1,170 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmslut.c b/third_party/lcms2-2.6/src/cmslut.c -index 9b0eb4b54..19d43361f 100644 ---- a/third_party/lcms2-2.6/src/cmslut.c -+++ b/third_party/lcms2-2.6/src/cmslut.c -@@ -1255,21 +1255,39 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) - // *********************************************************************************************************** - - // This function sets up the channel count -- - static --void BlessLUT(cmsPipeline* lut) -+cmsBool BlessLUT(cmsPipeline* lut) - { - // We can set the input/ouput channels only if we have elements. - if (lut ->Elements != NULL) { - -- cmsStage *First, *Last; -+ cmsStage* prev; -+ cmsStage* next; -+ cmsStage* First; -+ cmsStage* Last; - - First = cmsPipelineGetPtrToFirstStage(lut); - Last = cmsPipelineGetPtrToLastStage(lut); - -- if (First != NULL)lut ->InputChannels = First ->InputChannels; -- if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels; -+ if (First == NULL || Last == NULL) return FALSE; -+ -+ lut->InputChannels = First->InputChannels; -+ lut->OutputChannels = Last->OutputChannels; -+ -+ // Check chain consistency -+ prev = First; -+ next = prev->Next; -+ -+ while (next != NULL) -+ { -+ if (next->InputChannels != prev->OutputChannels) -+ return FALSE; -+ -+ next = next->Next; -+ prev = prev->Next; -+ } - } -+ return TRUE; - } - - -@@ -1331,6 +1349,7 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In - { - cmsPipeline* NewLUT; - -+ // A value of zero in channels is allowed as placeholder - if (InputChannels >= cmsMAXCHANNELS || - OutputChannels >= cmsMAXCHANNELS) return NULL; - -@@ -1348,7 +1367,11 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In - NewLUT ->Data = NewLUT; - NewLUT ->ContextID = ContextID; - -- BlessLUT(NewLUT); -+ if (!BlessLUT(NewLUT)) -+ { -+ _cmsFree(ContextID, NewLUT); -+ return NULL; -+ } - - return NewLUT; - } -@@ -1454,7 +1477,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) - - NewLUT ->SaveAs8Bits = lut ->SaveAs8Bits; - -- BlessLUT(NewLUT); -+ if (!BlessLUT(NewLUT)) -+ { -+ _cmsFree(lut->ContextID, NewLUT); -+ return NULL; -+ } -+ - return NewLUT; - } - -@@ -1491,8 +1519,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage - return FALSE; - } - -- BlessLUT(lut); -- return TRUE; -+ return BlessLUT(lut); - } - - // Unlink an element and return the pointer to it -@@ -1547,6 +1574,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag - else - cmsStageFree(Unlinked); - -+ // May fail, but we ignore it - BlessLUT(lut); - } - -@@ -1573,8 +1601,7 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) - return FALSE; - } - -- BlessLUT(l1); -- return TRUE; -+ return BlessLUT(l1); - } - - -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index e5ed06c33..0256e247b 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -1755,8 +1755,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms - if (!_cmsReadUInt8Number(io, NULL)) goto Error; - - // Do some checking -- if (InputChannels > cmsMAXCHANNELS) goto Error; -- if (OutputChannels > cmsMAXCHANNELS) goto Error; -+ if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; -+ if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; - - // Allocates an empty Pipeline - NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); -@@ -2048,8 +2048,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm - if (!_cmsReadUInt8Number(io, NULL)) return NULL; - - // Do some checking -- if (InputChannels > cmsMAXCHANNELS) goto Error; -- if (OutputChannels > cmsMAXCHANNELS) goto Error; -+ if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; -+ if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; - - // Allocates an empty LUT - NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); -@@ -2486,7 +2486,10 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c - if (!_cmsReadUInt32Number(io, &offsetC)) return NULL; - if (!_cmsReadUInt32Number(io, &offsetA)) return NULL; - -- // Allocates an empty LUT -+ if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; -+ if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; -+ -+ // Allocates an empty LUT - NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); - if (NewLUT == NULL) return NULL; - -@@ -2794,6 +2797,9 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c - if (!_cmsReadUInt8Number(io, &inputChan)) return NULL; - if (!_cmsReadUInt8Number(io, &outputChan)) return NULL; - -+ if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; -+ if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; -+ - // Padding - if (!_cmsReadUInt16Number(io, NULL)) return NULL; - -@@ -4443,6 +4449,9 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU - if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; - if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; - -+ if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) return NULL; -+ if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) return NULL; -+ - // Allocates an empty LUT - NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); - if (NewLUT == NULL) return NULL; diff --git a/third_party/lcms2-2.6/0017-upstream-integer-overflow-MPEmatrix_Read.patch b/third_party/lcms2-2.6/0017-upstream-integer-overflow-MPEmatrix_Read.patch deleted file mode 100644 index 47df7a887d5681b7a469b8ea2ffcc6412083a3b3..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/0017-upstream-integer-overflow-MPEmatrix_Read.patch +++ /dev/null @@ -1,85 +0,0 @@ -diff --git a/third_party/lcms2-2.6/src/cmscgats.c b/third_party/lcms2-2.6/src/cmscgats.c -index 5720c66a7..cce4cedba 100644 ---- a/third_party/lcms2-2.6/src/cmscgats.c -+++ b/third_party/lcms2-2.6/src/cmscgats.c -@@ -150,23 +150,24 @@ typedef struct { - SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast - - // Parser state machine -- SYMBOL sy; // Current symbol -- int ch; // Current character -+ SYMBOL sy; // Current symbol -+ int ch; // Current character -+ -+ cmsInt32Number inum; // integer value -+ cmsFloat64Number dnum; // real value - -- int inum; // integer value -- cmsFloat64Number dnum; // real value - char id[MAXID]; // identifier - char str[MAXSTR]; // string - - // Allowed keywords & datasets. They have visibility on whole stream -- KEYVALUE* ValidKeywords; -- KEYVALUE* ValidSampleID; -+ KEYVALUE* ValidKeywords; -+ KEYVALUE* ValidSampleID; - - char* Source; // Points to loc. being parsed -- int lineno; // line counter for error reporting -+ cmsInt32Number lineno; // line counter for error reporting - - FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed -- int IncludeSP; // Include Stack Pointer -+ cmsInt32Number IncludeSP; // Include Stack Pointer - - char* MemoryBlock; // The stream if holded in memory - -@@ -568,8 +569,8 @@ void ReadReal(cmsIT8* it8, int inum) - // Exponent, example 34.00E+20 - if (toupper(it8->ch) == 'E') { - -- int e; -- int sgn; -+ cmsInt32Number e; -+ cmsInt32Number sgn; - - NextCh(it8); sgn = 1; - -@@ -587,7 +588,7 @@ void ReadReal(cmsIT8* it8, int inum) - e = 0; - while (isdigit(it8->ch)) { - -- if ((cmsFloat64Number) e * 10L < INT_MAX) -+ if ((cmsFloat64Number) e * 10L < (cmsFloat64Number) +2147483647.0) - e = e * 10 + (it8->ch - '0'); - - NextCh(it8); -@@ -777,7 +778,7 @@ void InSymbol(cmsIT8* it8) - - while (isdigit(it8->ch)) { - -- if ((long) it8->inum * 10L > (long) INT_MAX) { -+ if ((cmsFloat64Number) it8->inum * 10L > (cmsFloat64Number) +2147483647.0) { - ReadReal(it8, it8->inum); - it8->sy = SDNUM; - it8->dnum *= sign; -diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c -index 0256e247b..75f1fae32 100644 ---- a/third_party/lcms2-2.6/src/cmstypes.c -+++ b/third_party/lcms2-2.6/src/cmstypes.c -@@ -4199,9 +4199,13 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io - if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; - - -+ // Input and output chans may be ANY (up to 0xffff), -+ // but we choose to limit to 16 channels for now -+ if (InputChans >= cmsMAXCHANNELS) return NULL; -+ if (OutputChans >= cmsMAXCHANNELS) return NULL; -+ - nElems = InputChans * OutputChans; - -- // Input and output chans may be ANY (up to 0xffff) - Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number)); - if (Matrix == NULL) return NULL; - diff --git a/third_party/lcms2-2.6/README.pdfium b/third_party/lcms2-2.6/README.pdfium deleted file mode 100644 index 650429826c6b33c6281a153c6f20ad3a3c9fee75..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/README.pdfium +++ /dev/null @@ -1,32 +0,0 @@ -Name: Little CMS -URL: http://www.littlecms.com/ -Version: 2.6 -Security Critical: yes -License: MIT License - -Description: -Color Management Engine. - -Local Modifications: - -0000-tag-type-confusion.patch: Fix a type confusion. -0001-from16-to-8-overflow.patch: Prevent a UBSan warning. -0002-infinite-loop-GrowNamedColorList.patch: Fix infinite loop when calling GrowNamedColorList. -0003-uninit.patch: Fix use uninitialized value and stack buffer overflow read. -0004-memory-leak-Type_Curve_Read.patch: Fix memory leak in Type_Curve_Read. -0005-memory-leak-AllocEmptyTransform.patch: Fix memory leak in AllocEmptyTransform. -0006-memory-leak-Type_NamedColor_Read.patch: Fix memory leak in Type_NamedColor_Read. -0007-memory-leak-OptimizeByResampling.patch: Fix memory leak in OptimizeByResampling. -0008-memory-leak-Type_MPEmatrix_Read.patch: Fix memory leak in MPEmatrix_Read. -0009-cmsStageAllocMatrix-param-swap.patch: Fix rows/cols swap in cmsStageAllocMatrix. -0010-reject-nan.patch: Reject NaN when reading float numbers. -0011-memory-leak-ReadSegmentedCurve.patch: Fix memory leak in ReadSegmentedCurve. -0012-backport-c0a98d86.patch: Fix several issues. Backport from upstream - https://github.com/mm2/Little-CMS/commit/c0a98d86 -0013-utf8.patch: Encode source files as utf-8. -0014-avoid-fixed-inf.patch: Avoid fixed number LUT optimization on inf values. -0015-sanitize-float-read.patch: Sanitize floating point read. Partially backport - from upstream https://github.com/mm2/Little-CMS/commit/4011a6e3 -0016-check-LUT-and-MPE.patch: check LUT consistency and sanitize MPE profiles. -0017-upstream-integer-overflow-MPEmatrix_Read.patch: fix some integer overflows. -TODO(ochang): List other patches. diff --git a/third_party/lcms2-2.6/src/cmserr.c b/third_party/lcms2-2.6/src/cmserr.c deleted file mode 100644 index 77b67b43aa800f3a04d0587c59f1457965c63039..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/src/cmserr.c +++ /dev/null @@ -1,707 +0,0 @@ -//--------------------------------------------------------------------------------- -// -// Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -//--------------------------------------------------------------------------------- - -#include "lcms2_internal.h" - -// I am so tired about incompatibilities on those functions that here are some replacements -// that hopefully would be fully portable. - -// compare two strings ignoring case -int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2) -{ - register const unsigned char *us1 = (const unsigned char *)s1, - *us2 = (const unsigned char *)s2; - - while (toupper(*us1) == toupper(*us2++)) - if (*us1++ == '\0') - return 0; - - return (toupper(*us1) - toupper(*--us2)); -} - -// long int because C99 specifies ftell in such way (7.19.9.2) -long int CMSEXPORT cmsfilelength(FILE* f) -{ - long int p , n; - - p = ftell(f); // register current file position - - if (fseek(f, 0, SEEK_END) != 0) { - return -1; - } - - n = ftell(f); - fseek(f, p, SEEK_SET); // file position restored - - return n; -} - -#if 0 -// Memory handling ------------------------------------------------------------------ -// -// This is the interface to low-level memory management routines. By default a simple -// wrapping to malloc/free/realloc is provided, although there is a limit on the max -// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent -// bogus or evil code to allocate huge blocks that otherwise lcms would never need. - -#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U)) - -// User may override this behaviour by using a memory plug-in, which basically replaces -// the default memory management functions. In this case, no check is performed and it -// is up to the plug-in writter to keep in the safe side. There are only three functions -// required to be implemented: malloc, realloc and free, although the user may want to -// replace the optional mallocZero, calloc and dup as well. - -cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); - -// ********************************************************************************* - -// This is the default memory allocation function. It does a very coarse -// check of amout of memory, just to prevent exploits -static -void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size) -{ - if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never allow over maximum - - return (void*) malloc(size); - - cmsUNUSED_PARAMETER(ContextID); -} - -// Generic allocate & zero -static -void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size) -{ - void *pt = _cmsMalloc(ContextID, size); - if (pt == NULL) return NULL; - - memset(pt, 0, size); - return pt; -} - - -// The default free function. The only check proformed is against NULL pointers -static -void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr) -{ - // free(NULL) is defined a no-op by C99, therefore it is safe to - // avoid the check, but it is here just in case... - - if (Ptr) free(Ptr); - - cmsUNUSED_PARAMETER(ContextID); -} - -// The default realloc function. Again it checks for exploits. If Ptr is NULL, -// realloc behaves the same way as malloc and allocates a new block of size bytes. -static -void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) -{ - - if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never realloc over 512Mb - - return realloc(Ptr, size); - - cmsUNUSED_PARAMETER(ContextID); -} - - -// The default calloc function. Allocates an array of num elements, each one of size bytes -// all memory is initialized to zero. -static -void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) -{ - cmsUInt32Number Total = num * size; - - // Preserve calloc behaviour - if (Total == 0) return NULL; - - // Safe check for overflow. - if (num >= UINT_MAX / size) return NULL; - - // Check for overflow - if (Total < num || Total < size) { - return NULL; - } - - if (Total > MAX_MEMORY_FOR_ALLOC) return NULL; // Never alloc over 512Mb - - return _cmsMallocZero(ContextID, Total); -} - -// Generic block duplication -static -void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size) -{ - void* mem; - - if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb - - mem = _cmsMalloc(ContextID, size); - - if (mem != NULL && Org != NULL) - memmove(mem, Org, size); - - return mem; -} - - -// Pointers to memory manager functions in Context0 -_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn, - _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn - }; - - -// Reset and duplicate memory manager -void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) -{ - _cmsAssert(ctx != NULL); - - if (src != NULL) { - - // Duplicate - ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); - } - else { - - // To reset it, we use the default allocators, which cannot be overriden - ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; - } -} - -// Auxiliar to fill memory management functions from plugin (or context 0 defaults) -void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) -{ - if (Plugin == NULL) { - - memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk)); - } - else { - - ptr ->MallocPtr = Plugin -> MallocPtr; - ptr ->FreePtr = Plugin -> FreePtr; - ptr ->ReallocPtr = Plugin -> ReallocPtr; - - // Make sure we revert to defaults - ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn; - ptr ->CallocPtr = _cmsCallocDefaultFn; - ptr ->DupPtr = _cmsDupDefaultFn; - - if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; - if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; - if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; - - } -} - - -// Plug-in replacement entry -cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data) -{ - cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data; - _cmsMemPluginChunkType* ptr; - - // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure. - // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the - // context internal data should be malloce'd by using those functions. - if (Data == NULL) { - - struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID; - - // Return to the default allocators - if (ContextID != NULL) { - ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager; - } - return TRUE; - } - - // Check for required callbacks - if (Plugin -> MallocPtr == NULL || - Plugin -> FreePtr == NULL || - Plugin -> ReallocPtr == NULL) return FALSE; - - // Set replacement functions - ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); - if (ptr == NULL) - return FALSE; - - _cmsInstallAllocFunctions(Plugin, ptr); - return TRUE; -} -#else -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" - -cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin) -{ - return TRUE; -} - -// Generic allocate -void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) -{ - return FXMEM_DefaultAlloc(size, 1); -} - -// Generic allocate & zero -void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) -{ - void* p = FXMEM_DefaultAlloc(size, 1); - if (p) FXSYS_memset(p, 0, size); - return p; -} - -// Generic calloc -void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) -{ - cmsUInt32Number total = num * size; - if (total == 0 || total / size != num || total >= 512 * 1024 * 1024) - return NULL; - - return _cmsMallocZero(ContextID, num * size); -} - -// Generic reallocate -void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) -{ - return FXMEM_DefaultRealloc(Ptr, size, 1); -} - -// Generic free memory -void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) -{ - if (Ptr != NULL) FXMEM_DefaultFree(Ptr, 0); -} - -// Generic block duplication -void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) -{ - void* p = FXMEM_DefaultAlloc(size, 1); - FXSYS_memmove(p, Org, size); - return p; -} - -_cmsMemPluginChunkType _cmsMemPluginChunk = {_cmsMalloc, _cmsMallocZero, _cmsFree, - _cmsRealloc, _cmsCalloc, _cmsDupMem - }; - -void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) -{ - _cmsAssert(ctx != NULL); - - if (src != NULL) { - - // Duplicate - ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); - } - else { - - // To reset it, we use the default allocators, which cannot be overriden - ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; - } -} - -void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) -{ - if (Plugin == NULL) { - - memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk)); - } - else { - - ptr ->MallocPtr = Plugin -> MallocPtr; - ptr ->FreePtr = Plugin -> FreePtr; - ptr ->ReallocPtr = Plugin -> ReallocPtr; - - // Make sure we revert to defaults - ptr ->MallocZeroPtr= _cmsMallocZero; - ptr ->CallocPtr = _cmsCalloc; - ptr ->DupPtr = _cmsDupMem; - - if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; - if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; - if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; - - } -} -#endif - -// ******************************************************************************************** - -// Sub allocation takes care of many pointers of small size. The memory allocated in -// this way have be freed at once. Next function allocates a single chunk for linked list -// I prefer this method over realloc due to the big inpact on xput realloc may have if -// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms) -static -_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial) -{ - _cmsSubAllocator_chunk* chunk; - - // 20K by default - if (Initial == 0) - Initial = 20*1024; - - // Create the container - chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk)); - if (chunk == NULL) return NULL; - - // Initialize values - chunk ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial); - if (chunk ->Block == NULL) { - - // Something went wrong - _cmsFree(ContextID, chunk); - return NULL; - } - - chunk ->BlockSize = Initial; - chunk ->Used = 0; - chunk ->next = NULL; - - return chunk; -} - -// The suballocated is nothing but a pointer to the first element in the list. We also keep -// the thread ID in this structure. -_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial) -{ - _cmsSubAllocator* sub; - - // Create the container - sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator)); - if (sub == NULL) return NULL; - - sub ->ContextID = ContextID; - - sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial); - if (sub ->h == NULL) { - _cmsFree(ContextID, sub); - return NULL; - } - - return sub; -} - - -// Get rid of whole linked list -void _cmsSubAllocDestroy(_cmsSubAllocator* sub) -{ - _cmsSubAllocator_chunk *chunk, *n; - - for (chunk = sub ->h; chunk != NULL; chunk = n) { - - n = chunk->next; - if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block); - _cmsFree(sub ->ContextID, chunk); - } - - // Free the header - _cmsFree(sub ->ContextID, sub); -} - - -// Get a pointer to small memory block. -void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size) -{ - cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used; - cmsUInt8Number* ptr; - - size = _cmsALIGNMEM(size); - - // Check for memory. If there is no room, allocate a new chunk of double memory size. - if (size > Free) { - - _cmsSubAllocator_chunk* chunk; - cmsUInt32Number newSize; - - newSize = sub -> h ->BlockSize * 2; - if (newSize < size) newSize = size; - - chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize); - if (chunk == NULL) return NULL; - - // Link list - chunk ->next = sub ->h; - sub ->h = chunk; - - } - - ptr = sub -> h ->Block + sub -> h ->Used; - sub -> h -> Used += size; - - return (void*) ptr; -} - -// Duplicate in pool -void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size) -{ - void *NewPtr; - - // Dup of null pointer is also NULL - if (ptr == NULL) - return NULL; - - NewPtr = _cmsSubAlloc(s, size); - - if (ptr != NULL && NewPtr != NULL) { - memcpy(NewPtr, ptr, size); - } - - return NewPtr; -} - - - -// Error logging ****************************************************************** - -// There is no error handling at all. When a funtion fails, it returns proper value. -// For example, all create functions does return NULL on failure. Other return FALSE -// It may be interesting, for the developer, to know why the function is failing. -// for that reason, lcms2 does offer a logging function. This function does recive -// a ENGLISH string with some clues on what is going wrong. You can show this -// info to the end user, or just create some sort of log. -// The logging function should NOT terminate the program, as this obviously can leave -// resources. It is the programmer's responsability to check each function return code -// to make sure it didn't fail. - -// Error messages are limited to MAX_ERROR_MESSAGE_LEN - -#define MAX_ERROR_MESSAGE_LEN 1024 - -// --------------------------------------------------------------------------------------------------------- - -// This is our default log error -static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); - -// Context0 storage, which is global -_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction }; - -// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value -// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients -void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction }; - void* from; - - if (src != NULL) { - from = src ->chunks[Logger]; - } - else { - from = &LogErrorChunk; - } - - ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType)); -} - -// The default error logger does nothing. -static -void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text) -{ - // fprintf(stderr, "[lcms]: %s\n", Text); - // fflush(stderr); - - cmsUNUSED_PARAMETER(ContextID); - cmsUNUSED_PARAMETER(ErrorCode); - cmsUNUSED_PARAMETER(Text); -} - -// Change log error, context based -void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn) -{ - _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); - - if (lhg != NULL) { - - if (Fn == NULL) - lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction; - else - lhg -> LogErrorHandler = Fn; - } -} - -// Change log error, legacy -void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn) -{ - cmsSetLogErrorHandlerTHR(NULL, Fn); -} - -// Log an error -// ErrorText is a text holding an english description of error. -void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...) -{ - va_list args; - char Buffer[MAX_ERROR_MESSAGE_LEN]; - _cmsLogErrorChunkType* lhg; - - - va_start(args, ErrorText); - vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args); - va_end(args); - - // Check for the context, if specified go there. If not, go for the global - lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); - if (lhg ->LogErrorHandler) { - lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer); - } -} - -// Utility function to print signatures -void _cmsTagSignature2String(char String[5], cmsTagSignature sig) -{ - cmsUInt32Number be; - - // Convert to big endian - be = _cmsAdjustEndianess32((cmsUInt32Number) sig); - - // Move chars - memmove(String, &be, 4); - - // Make sure of terminator - String[4] = 0; -} - -//-------------------------------------------------------------------------------------------------- - - -static -void* defMtxCreate(cmsContext id) -{ - _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); - _cmsInitMutexPrimitive(ptr_mutex); - return (void*) ptr_mutex; -} - -static -void defMtxDestroy(cmsContext id, void* mtx) -{ - _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); - _cmsFree(id, mtx); -} - -static -cmsBool defMtxLock(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - return _cmsLockPrimitive((_cmsMutex *) mtx) == 0; -} - -static -void defMtxUnlock(cmsContext id, void* mtx) -{ - cmsUNUSED_PARAMETER(id); - _cmsUnlockPrimitive((_cmsMutex *) mtx); -} - - - -// Pointers to memory manager functions in Context0 -_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; - -// Allocate and init mutex container. -void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; - void* from; - - if (src != NULL) { - from = src ->chunks[MutexPlugin]; - } - else { - from = &MutexChunk; - } - - ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType)); -} - -// Register new ways to transform -cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data) -{ - cmsPluginMutex* Plugin = (cmsPluginMutex*) Data; - _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); - - if (Data == NULL) { - - // No lock routines - ctx->CreateMutexPtr = NULL; - ctx->DestroyMutexPtr = NULL; - ctx->LockMutexPtr = NULL; - ctx ->UnlockMutexPtr = NULL; - return TRUE; - } - - // Factory callback is required - if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL || - Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE; - - - ctx->CreateMutexPtr = Plugin->CreateMutexPtr; - ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr; - ctx ->LockMutexPtr = Plugin ->LockMutexPtr; - ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr; - - // All is ok - return TRUE; -} - -// Generic Mutex fns -void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID) -{ - _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); - - if (ptr ->CreateMutexPtr == NULL) return NULL; - - return ptr ->CreateMutexPtr(ContextID); -} - -void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx) -{ - _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); - - if (ptr ->DestroyMutexPtr != NULL) { - - ptr ->DestroyMutexPtr(ContextID, mtx); - } -} - -cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx) -{ - _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); - - if (ptr ->LockMutexPtr == NULL) return TRUE; - - return ptr ->LockMutexPtr(ContextID, mtx); -} - -void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx) -{ - _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); - - if (ptr ->UnlockMutexPtr != NULL) { - - ptr ->UnlockMutexPtr(ContextID, mtx); - } -} diff --git a/third_party/lcms2-2.6/src/cmsxform.c b/third_party/lcms2-2.6/src/cmsxform.c deleted file mode 100644 index dffe6b2fb7df0b4264683026b19ea97f4c64dd88..0000000000000000000000000000000000000000 --- a/third_party/lcms2-2.6/src/cmsxform.c +++ /dev/null @@ -1,1137 +0,0 @@ -//--------------------------------------------------------------------------------- -// -// Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -//--------------------------------------------------------------------------------- -// - -#include "lcms2_internal.h" - -// Transformations stuff -// ----------------------------------------------------------------------- - -#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 - -// The Context0 observer adaptation state. -_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; - -// Init and duplicate observer adaptation state -void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; - void* from; - - if (src != NULL) { - from = src ->chunks[AdaptationStateContext]; - } - else { - from = &AdaptationStateChunk; - } - - ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); -} - - -// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all -// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states. -cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d) -{ - cmsFloat64Number prev; - _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); - - // Get previous value for return - prev = ptr ->AdaptationState; - - // Set the value if d is positive or zero - if (d >= 0.0) { - - ptr ->AdaptationState = d; - } - - // Always return previous value - return prev; -} - - -// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine -cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) -{ - return cmsSetAdaptationStateTHR(NULL, d); -} - -// ----------------------------------------------------------------------- - -// Alarm codes for 16-bit transformations, because the fixed range of containers there are -// no values left to mark out of gamut. - -#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; - -// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be -// encoded in 16 bits. -void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) -{ - _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); - - _cmsAssert(ContextAlarmCodes != NULL); // Can't happen - - memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); -} - -// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. -// Values are meant to be encoded in 16 bits. -void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) -{ - _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); - - _cmsAssert(ContextAlarmCodes != NULL); // Can't happen - - memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); -} - -void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) -{ - _cmsAssert(NewAlarm != NULL); - - cmsSetAlarmCodesTHR(NULL, NewAlarm); -} - -void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) -{ - _cmsAssert(OldAlarm != NULL); - cmsGetAlarmCodesTHR(NULL, OldAlarm); -} - - -// Init and duplicate alarm codes -void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; - void* from; - - if (src != NULL) { - from = src ->chunks[AlarmCodesContext]; - } - else { - from = &AlarmCodesChunk; - } - - ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); -} - -// ----------------------------------------------------------------------- - -// Get rid of transform resources -void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; - - _cmsAssert(p != NULL); - - if (p -> GamutCheck) - cmsPipelineFree(p -> GamutCheck); - - if (p -> Lut) - cmsPipelineFree(p -> Lut); - - if (p ->InputColorant) - cmsFreeNamedColorList(p ->InputColorant); - - if (p -> OutputColorant) - cmsFreeNamedColorList(p ->OutputColorant); - - if (p ->Sequence) - cmsFreeProfileSequenceDescription(p ->Sequence); - - if (p ->UserData) - p ->FreeUserData(p ->ContextID, p ->UserData); - - _cmsFree(p ->ContextID, (void *) p); -} - -// Apply transform. -void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, - const void* InputBuffer, - void* OutputBuffer, - cmsUInt32Number Size) - -{ - _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; - - p -> xform(p, InputBuffer, OutputBuffer, Size, Size); -} - - -// Apply transform. -void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, - const void* InputBuffer, - void* OutputBuffer, - cmsUInt32Number Size, cmsUInt32Number Stride) - -{ - _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; - - p -> xform(p, InputBuffer, OutputBuffer, Size, Stride); -} - - -// Transform routines ---------------------------------------------------------------------------------------------------------- - -// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. -// Note that because extended range, we can use a -1.0 value for out of gamut in this case. -static -void FloatXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; - cmsFloat32Number OutOfGamut; - cmsUInt32Number i, j; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - - for (i=0; i < Size; i++) { - - accum = p -> FromInputFloat(p, fIn, accum, Stride); - - // Any gamut chack to do? - if (p ->GamutCheck != NULL) { - - // Evaluate gamut marker. - cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck); - - // Is current color out of gamut? - if (OutOfGamut > 0.0) { - - // Certainly, out of gamut - for (j=0; j < cmsMAXCHANNELS; j++) - fOut[j] = -1.0; - - } - else { - // No, proceed normally - cmsPipelineEvalFloat(fIn, fOut, p -> Lut); - } - } - else { - - // No gamut check at all - cmsPipelineEvalFloat(fIn, fOut, p -> Lut); - } - - // Back to asked representation - output = p -> ToOutputFloat(p, fOut, output, Stride); - } -} - - -static -void NullFloatXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, - cmsUInt32Number Size, - cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsFloat32Number fIn[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; - - for (i=0; i < n; i++) { - - accum = p -> FromInputFloat(p, fIn, accum, Stride); - output = p -> ToOutputFloat(p, fIn, output, Stride); - } -} - -// 16 bit precision ----------------------------------------------------------------------------------------------------------- - -// Null transformation, only applies formatters. No cach?static -void NullXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, - cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - output = p -> ToOutput(p, wIn, output, Stride); - } -} - - -// No gamut check, no cache, 16 bits -static -void PrecalculatedXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - register cmsUInt8Number* accum; - register cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); - output = p -> ToOutput(p, wOut, output, Stride); - } -} - - -// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. -static -void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, - const cmsUInt16Number wIn[], - cmsUInt16Number wOut[]) -{ - cmsUInt16Number wOutOfGamut; - - p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data); - if (wOutOfGamut >= 1) { - - cmsUInt16Number i; - _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext); - - for (i=0; i < p ->Lut->OutputChannels; i++) { - - wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; - } - } - else - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); -} - -// Gamut check, No cach? 16 bits. -static -void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - TransformOnePixelWithGamutCheck(p, wIn, wOut); - output = p -> ToOutput(p, wOut, output, Stride); - } -} - - -// No gamut check, Cach? 16 bits, -static -void CachedXFORM(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - _cmsCACHE Cache; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - // Empty buffers for quick memcmp - memset(wIn, 0, sizeof(wIn)); - memset(wOut, 0, sizeof(wOut)); - - // Get copy of zero cache - memcpy(&Cache, &p ->Cache, sizeof(Cache)); - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - - if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { - - memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); - } - else { - - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); - - memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); - memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); - } - - output = p -> ToOutput(p, wOut, output, Stride); - } - -} - - -// All those nice features together -static -void CachedXFORMGamutCheck(_cmsTRANSFORM* p, - const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) -{ - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - _cmsCACHE Cache; - - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len - - // Empty buffers for quick memcmp - memset(wIn, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); - memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); - - // Get copy of zero cache - memcpy(&Cache, &p ->Cache, sizeof(Cache)); - - for (i=0; i < n; i++) { - - accum = p -> FromInput(p, wIn, accum, Stride); - - if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { - memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); - } - else { - TransformOnePixelWithGamutCheck(p, wIn, wOut); - memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); - memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); - } - - output = p -> ToOutput(p, wOut, output, Stride); - } - -} - -// ------------------------------------------------------------------------------------------------------------- - -// List of used-defined transform factories -typedef struct _cmsTransformCollection_st { - - _cmsTransformFactory Factory; - struct _cmsTransformCollection_st *Next; - -} _cmsTransformCollection; - -// The linked list head -_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; - - -// Duplicates the zone of memory used by the plug-in in the new context -static -void DupPluginTransformList(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - _cmsTransformPluginChunkType newHead = { NULL }; - _cmsTransformCollection* entry; - _cmsTransformCollection* Anterior = NULL; - _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; - - // Walk the list copying all nodes - for (entry = head->TransformCollection; - entry != NULL; - entry = entry ->Next) { - - _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); - - if (newEntry == NULL) - return; - - // We want to keep the linked list order, so this is a little bit tricky - newEntry -> Next = NULL; - if (Anterior) - Anterior -> Next = newEntry; - - Anterior = newEntry; - - if (newHead.TransformCollection == NULL) - newHead.TransformCollection = newEntry; - } - - ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); -} - -void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, - const struct _cmsContext_struct* src) -{ - if (src != NULL) { - - // Copy all linked list - DupPluginTransformList(ctx, src); - } - else { - static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; - ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); - } -} - - - -// Register new ways to transform -cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) -{ - cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; - _cmsTransformCollection* fl; - _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); - - if (Data == NULL) { - - // Free the chain. Memory is safely freed at exit - ctx->TransformCollection = NULL; - return TRUE; - } - - // Factory callback is required - if (Plugin ->Factory == NULL) return FALSE; - - - fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); - if (fl == NULL) return FALSE; - - // Copy the parameters - fl ->Factory = Plugin ->Factory; - - // Keep linked list - fl ->Next = ctx->TransformCollection; - ctx->TransformCollection = fl; - - // All is ok - return TRUE; -} - - -void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) -{ - _cmsAssert(CMMcargo != NULL); - CMMcargo ->UserData = ptr; - CMMcargo ->FreeUserData = FreePrivateDataFn; -} - -// returns the pointer defined by the plug-in to store private data -void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) -{ - _cmsAssert(CMMcargo != NULL); - return CMMcargo ->UserData; -} - -// returns the current formatters -void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) -{ - _cmsAssert(CMMcargo != NULL); - if (FromInput) *FromInput = CMMcargo ->FromInput; - if (ToOutput) *ToOutput = CMMcargo ->ToOutput; -} - -void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) -{ - _cmsAssert(CMMcargo != NULL); - if (FromInput) *FromInput = CMMcargo ->FromInputFloat; - if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; -} - - -// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper -// for separated transforms. If this is the case, -static -_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, - cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) -{ - _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); - _cmsTransformCollection* Plugin; - - // Allocate needed memory - _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); - if (!p) { - cmsPipelineFree(lut); - return NULL; - } - - // Store the proposed pipeline - p ->Lut = lut; - - // Let's see if any plug-in want to do the transform by itself - for (Plugin = ctx ->TransformCollection; - Plugin != NULL; - Plugin = Plugin ->Next) { - - if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) { - - // Last plugin in the declaration order takes control. We just keep - // the original parameters as a logging. - // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default - // an optimized transform is not reusable. The plug-in can, however, change - // the flags and make it suitable. - - p ->ContextID = ContextID; - p ->InputFormat = *InputFormat; - p ->OutputFormat = *OutputFormat; - p ->dwOriginalFlags = *dwFlags; - - // Fill the formatters just in case the optimized routine is interested. - // No error is thrown if the formatter doesn't exist. It is up to the optimization - // factory to decide what to do in those cases. - p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - - return p; - } - } - - // Not suitable for the transform plug-in, let's check the pipeline plug-in - if (p ->Lut != NULL) - _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); - - // Check whatever this is a true floating point transform - if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { - - // Get formatter function always return a valid union, but the contents of this union may be NULL. - p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; - - if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { - - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - cmsDeleteTransform(p); - return NULL; - } - - if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { - - p ->xform = NullFloatXFORM; - } - else { - // Float transforms don't use cach? always are non-NULL - p ->xform = FloatXFORM; - } - - } - else { - - if (*InputFormat == 0 && *OutputFormat == 0) { - p ->FromInput = p ->ToOutput = NULL; - *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; - } - else { - - int BytesPerPixelInput; - - p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - - if (p ->FromInput == NULL || p ->ToOutput == NULL) { - - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - cmsDeleteTransform(p); - return NULL; - } - - BytesPerPixelInput = T_BYTES(p ->InputFormat); - if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) - *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; - - } - - if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { - - p ->xform = NullXFORM; - } - else { - if (*dwFlags & cmsFLAGS_NOCACHE) { - - if (*dwFlags & cmsFLAGS_GAMUTCHECK) - p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cach? - else - p ->xform = PrecalculatedXFORM; // No cach? no gamut check - } - else { - - if (*dwFlags & cmsFLAGS_GAMUTCHECK) - p ->xform = CachedXFORMGamutCheck; // Gamut check, cach? - else - p ->xform = CachedXFORM; // No gamut check, cach? - } - } - } - - p ->InputFormat = *InputFormat; - p ->OutputFormat = *OutputFormat; - p ->dwOriginalFlags = *dwFlags; - p ->ContextID = ContextID; - p ->UserData = NULL; - return p; -} - -static -cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) -{ - cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; - cmsColorSpaceSignature PostColorSpace; - int i; - - if (nProfiles <= 0) return FALSE; - if (hProfiles[0] == NULL) return FALSE; - - *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); - - for (i=0; i < nProfiles; i++) { - - cmsProfileClassSignature cls; - cmsHPROFILE hProfile = hProfiles[i]; - - int lIsInput = (PostColorSpace != cmsSigXYZData) && - (PostColorSpace != cmsSigLabData); - - if (hProfile == NULL) return FALSE; - - cls = cmsGetDeviceClass(hProfile); - - if (cls == cmsSigNamedColorClass) { - - ColorSpaceIn = cmsSig1colorData; - ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(hProfile) : cmsGetColorSpace(hProfile); - } - else - if (lIsInput || (cls == cmsSigLinkClass)) { - - ColorSpaceIn = cmsGetColorSpace(hProfile); - ColorSpaceOut = cmsGetPCS(hProfile); - } - else - { - ColorSpaceIn = cmsGetPCS(hProfile); - ColorSpaceOut = cmsGetColorSpace(hProfile); - } - - if (i==0) - *Input = ColorSpaceIn; - - PostColorSpace = ColorSpaceOut; - } - - *Output = PostColorSpace; - - return TRUE; -} - -// Check colorspace -static -cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) -{ - int Space1 = T_COLORSPACE(dwFormat); - int Space2 = _cmsLCMScolorSpace(Check); - - if (Space1 == PT_ANY) return TRUE; - if (Space1 == Space2) return TRUE; - - if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; - if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; - - return FALSE; -} - -// ---------------------------------------------------------------------------------------------------------------- - -static -void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) -{ - if (src == NULL) { - wtPt ->X = cmsD50X; - wtPt ->Y = cmsD50Y; - wtPt ->Z = cmsD50Z; - } - else { - wtPt ->X = src->X; - wtPt ->Y = src->Y; - wtPt ->Z = src->Z; - } - -} - -// New to lcms 2.0 -- have all parameters available. -cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, - cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], - cmsBool BPC[], - cmsUInt32Number Intents[], - cmsFloat64Number AdaptationStates[], - cmsHPROFILE hGamutProfile, - cmsUInt32Number nGamutPCSposition, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat, - cmsUInt32Number dwFlags) -{ - _cmsTRANSFORM* xform; - cmsColorSpaceSignature EntryColorSpace; - cmsColorSpaceSignature ExitColorSpace; - cmsPipeline* Lut; - cmsUInt32Number LastIntent = Intents[nProfiles-1]; - - // If it is a fake transform - if (dwFlags & cmsFLAGS_NULLTRANSFORM) - { - return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); - } - - // If gamut check is requested, make sure we have a gamut profile - if (dwFlags & cmsFLAGS_GAMUTCHECK) { - if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; - } - - // On floating point transforms, inhibit cache - if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) - dwFlags |= cmsFLAGS_NOCACHE; - - // Mark entry/exit spaces - if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { - cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); - return NULL; - } - - // Check if proper colorspaces - if (!IsProperColorSpace(EntryColorSpace, InputFormat)) { - cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); - return NULL; - } - - if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) { - cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); - return NULL; - } - - // Create a pipeline with all transformations - Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); - if (Lut == NULL) { - cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); - return NULL; - } - - // Check channel count - if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || - (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { - cmsPipelineFree(Lut); - cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); - return NULL; - } - - - // All seems ok - xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); - if (xform == NULL) { - return NULL; - } - - // Keep values - xform ->EntryColorSpace = EntryColorSpace; - xform ->ExitColorSpace = ExitColorSpace; - xform ->RenderingIntent = Intents[nProfiles-1]; - - // Take white points - SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag)); - SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); - - - // Create a gamut check LUT if requested - if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) - xform ->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, - BPC, Intents, - AdaptationStates, - nGamutPCSposition, - hGamutProfile); - - - // Try to read input and output colorant table - if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) { - - // Input table can only come in this way. - xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag)); - } - - // Output is a little bit more complex. - if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) { - - // This tag may exist only on devicelink profiles. - if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { - - // It may be NULL if error - xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); - } - - } else { - - if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) { - - xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)); - } - } - - // Store the sequence of profiles - if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { - xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); - } - else - xform ->Sequence = NULL; - - // If this is a cached transform, init first value, which is zero (16 bits only) - if (!(dwFlags & cmsFLAGS_NOCACHE)) { - - memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); - - if (xform ->GamutCheck != NULL) { - TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut); - } - else { - - xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data); - } - - } - - return (cmsHTRANSFORM) xform; -} - -// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. -cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, - cmsHPROFILE hProfiles[], - cmsUInt32Number nProfiles, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - cmsUInt32Number i; - cmsBool BPC[256]; - cmsUInt32Number Intents[256]; - cmsFloat64Number AdaptationStates[256]; - - if (nProfiles <= 0 || nProfiles > 255) { - cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); - return NULL; - } - - for (i=0; i < nProfiles; i++) { - BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; - Intents[i] = Intent; - AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1); - } - - - return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); -} - - - -cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[], - cmsUInt32Number nProfiles, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - - if (nProfiles <= 0 || nProfiles > 255) { - cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); - return NULL; - } - - return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]), - hProfiles, - nProfiles, - InputFormat, - OutputFormat, - Intent, - dwFlags); -} - -cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, - cmsHPROFILE Input, - cmsUInt32Number InputFormat, - cmsHPROFILE Output, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - - cmsHPROFILE hArray[2]; - - hArray[0] = Input; - hArray[1] = Output; - - return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags); -} - -CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, - cmsUInt32Number InputFormat, - cmsHPROFILE Output, - cmsUInt32Number OutputFormat, - cmsUInt32Number Intent, - cmsUInt32Number dwFlags) -{ - return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags); -} - - -cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, - cmsHPROFILE InputProfile, - cmsUInt32Number InputFormat, - cmsHPROFILE OutputProfile, - cmsUInt32Number OutputFormat, - cmsHPROFILE ProofingProfile, - cmsUInt32Number nIntent, - cmsUInt32Number ProofingIntent, - cmsUInt32Number dwFlags) -{ - cmsHPROFILE hArray[4]; - cmsUInt32Number Intents[4]; - cmsBool BPC[4]; - cmsFloat64Number Adaptation[4]; - cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; - - - hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; - Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; - BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; - - Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1); - - if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) - return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); - - return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, - ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); - -} - - -cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile, - cmsUInt32Number InputFormat, - cmsHPROFILE OutputProfile, - cmsUInt32Number OutputFormat, - cmsHPROFILE ProofingProfile, - cmsUInt32Number nIntent, - cmsUInt32Number ProofingIntent, - cmsUInt32Number dwFlags) -{ - return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile), - InputProfile, - InputFormat, - OutputProfile, - OutputFormat, - ProofingProfile, - nIntent, - ProofingIntent, - dwFlags); -} - - -// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed -cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - - if (xform == NULL) return NULL; - return xform -> ContextID; -} - -// Grab the input/output formats -cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - - if (xform == NULL) return 0; - return xform->InputFormat; -} - -cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform) -{ - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - - if (xform == NULL) return 0; - return xform->OutputFormat; -} - -// For backwards compatibility -cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, - cmsUInt32Number InputFormat, - cmsUInt32Number OutputFormat) -{ - - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; - cmsFormatter16 FromInput, ToOutput; - - - // We only can afford to change formatters if previous transform is at least 16 bits - if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { - - cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision"); - return FALSE; - } - - FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - - if (FromInput == NULL || ToOutput == NULL) { - - cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - return FALSE; - } - - xform ->InputFormat = InputFormat; - xform ->OutputFormat = OutputFormat; - xform ->FromInput = FromInput; - xform ->ToOutput = ToOutput; - return TRUE; -} diff --git a/third_party/libjpeg/cderror.h b/third_party/libjpeg/cderror.h deleted file mode 100644 index 70435e161c01773d458bb0d00af4446a9158d58a..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/cderror.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * cderror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the cjpeg/djpeg - * applications. These strings are not needed as part of the JPEG library - * proper. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef CDERROR_H -#define CDERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* CDERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ - -#ifdef BMP_SUPPORTED -JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") -JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") -JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") -JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") -JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") -JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") -JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") -JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") -JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") -JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") -JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") -#endif /* BMP_SUPPORTED */ - -#ifdef GIF_SUPPORTED -JMESSAGE(JERR_GIF_BUG, "GIF output got confused") -JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") -JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") -JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") -JMESSAGE(JERR_GIF_NOT, "Not a GIF file") -JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") -JMESSAGE(JTRC_GIF_BADVERSION, - "Warning: unexpected GIF version number '%c%c%c'") -JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") -JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") -JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") -JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") -JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") -JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") -#endif /* GIF_SUPPORTED */ - -#ifdef PPM_SUPPORTED -JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") -JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") -JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") -JMESSAGE(JTRC_PGM, "%ux%u PGM image") -JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") -JMESSAGE(JTRC_PPM, "%ux%u PPM image") -JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") -#endif /* PPM_SUPPORTED */ - -#ifdef RLE_SUPPORTED -JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") -JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") -JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") -JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") -JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") -JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") -JMESSAGE(JERR_RLE_NOT, "Not an RLE file") -JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") -JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") -JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") -JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") -JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") -JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") -JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") -#endif /* RLE_SUPPORTED */ - -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") -JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") -JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") -JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") -JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") -JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") -#else -JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") -#endif /* TARGA_SUPPORTED */ - -JMESSAGE(JERR_BAD_CMAP_FILE, - "Color map file is invalid or of unsupported format") -JMESSAGE(JERR_TOO_MANY_COLORS, - "Output file format cannot handle %d colormap entries") -JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_UNKNOWN_FORMAT, - "Unrecognized input file format --- perhaps you need -targa") -#else -JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") -#endif -JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTADDONCODE -} ADDON_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE diff --git a/third_party/libjpeg/cdjpeg.h b/third_party/libjpeg/cdjpeg.h deleted file mode 100644 index 3d728ee9c70dfa42fed23e172c8d0e308fecec7f..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/cdjpeg.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * cdjpeg.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains common declarations for the sample applications - * cjpeg and djpeg. It is NOT used by the core JPEG library. - */ - -#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ -#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" /* get library error codes too */ -#include "cderror.h" /* get application-specific error codes */ - - -/* - * Object interface for cjpeg's source file decoding modules - */ - -typedef struct cjpeg_source_struct * cjpeg_source_ptr; - -struct cjpeg_source_struct { - JMETHOD(void, start_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(void, finish_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - - FXSYS_FILE *input_file; - - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - - -/* - * Object interface for djpeg's output file encoding modules - */ - -typedef struct djpeg_dest_struct * djpeg_dest_ptr; - -struct djpeg_dest_struct { - /* start_output is called after jpeg_start_decompress finishes. - * The color map will be ready at this time, if one is needed. - */ - JMETHOD(void, start_output, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo)); - /* Emit the specified number of pixel rows from the buffer. */ - JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo, - JDIMENSION rows_supplied)); - /* Finish up at the end of the image. */ - JMETHOD(void, finish_output, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo)); - - /* Target file spec; filled in by djpeg.c after object is created. */ - FXSYS_FILE * output_file; - - /* Output pixel-row buffer. Created by module init or start_output. - * Width is cinfo->output_width * cinfo->output_components; - * height is buffer_height. - */ - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - - -/* - * cjpeg/djpeg may need to perform extra passes to convert to or from - * the source/destination file format. The JPEG library does not know - * about these passes, but we'd like them to be counted by the progress - * monitor. We use an expanded progress monitor object to hold the - * additional pass count. - */ - -struct cdjpeg_progress_mgr { - struct jpeg_progress_mgr pub; /* fields known to JPEG library */ - int completed_extra_passes; /* extra passes completed */ - int total_extra_passes; /* total extra */ - /* last printed percentage stored here to avoid multiple printouts */ - int percent_done; -}; - -typedef struct cdjpeg_progress_mgr * cd_progress_ptr; - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_read_bmp jIRdBMP -#define jinit_write_bmp jIWrBMP -#define jinit_read_gif jIRdGIF -#define jinit_write_gif jIWrGIF -#define jinit_read_ppm jIRdPPM -#define jinit_write_ppm jIWrPPM -#define jinit_read_rle jIRdRLE -#define jinit_write_rle jIWrRLE -#define jinit_read_targa jIRdTarga -#define jinit_write_targa jIWrTarga -#define read_quant_tables RdQTables -#define read_scan_script RdScnScript -#define set_quant_slots SetQSlots -#define set_sample_factors SetSFacts -#define read_color_map RdCMap -#define enable_signal_catcher EnSigCatcher -#define start_progress_monitor StProgMon -#define end_progress_monitor EnProgMon -#define read_stdin RdStdin -#define write_stdout WrStdout -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Module selection routines for I/O modules. */ - -EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, - boolean is_os2)); -EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); - -/* cjpeg support routines (in rdswitch.c) */ - -EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, - int scale_factor, boolean force_baseline)); -EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); -EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); -EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); - -/* djpeg support routines (in rdcolmap.c) */ - -EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FXSYS_FILE * infile)); - -/* common support routines (in cdjpeg.c) */ - -EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); -EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, - cd_progress_ptr progress)); -EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); -EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); -EXTERN(FXSYS_FILE *) read_stdin JPP((void)); -EXTERN(FXSYS_FILE *) write_stdout JPP((void)); - -/* miscellaneous useful macros */ - -#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ -#define READ_BINARY "r" -#define WRITE_BINARY "w" -#else -#ifdef VMS /* VMS is very nonstandard */ -#define READ_BINARY "rb", "ctx=stm" -#define WRITE_BINARY "wb", "ctx=stm" -#else /* standard ANSI-compliant case */ -#define READ_BINARY "rb" -#define WRITE_BINARY "wb" -#endif -#endif - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif -#ifndef EXIT_SUCCESS -#ifdef VMS -#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ -#else -#define EXIT_SUCCESS 0 -#endif -#endif -#ifndef EXIT_WARNING -#ifdef VMS -#define EXIT_WARNING 1 /* VMS is very nonstandard */ -#else -#define EXIT_WARNING 2 -#endif -#endif diff --git a/third_party/libjpeg/fpdfapi_jcapimin.c b/third_party/libjpeg/fpdfapi_jcapimin.c deleted file mode 100644 index 54fb8c58c5656947c285fc8d98d5c23815aec1eb..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcapimin.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * jcapimin.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the compression half - * of the JPEG library. These are the "minimum" API routines that may be - * needed in either the normal full-compression case or the transcoding-only - * case. - * - * Most of the routines intended to be called directly by an application - * are in this file or in jcapistd.c. But also see jcparam.c for - * parameter-setup helper routines, jcomapi.c for routines shared by - * compression and decompression, and jctrans.c for the transcoding case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Initialization of a JPEG compression object. - * The error manager must already be set up (in case memory manager fails). - */ - -GLOBAL(void) -jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) -{ - int i; - - /* Guard against version mismatches between library and caller. */ - cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ - if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); - if (structsize != SIZEOF(struct jpeg_compress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); - - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ - { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; - } - cinfo->is_decompressor = FALSE; - - /* Initialize a memory manager instance for this object */ - jinit_memory_mgr((j_common_ptr) cinfo); - - /* Zero out pointers to permanent structures. */ - cinfo->progress = NULL; - cinfo->dest = NULL; - - cinfo->comp_info = NULL; - - for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; - } - - cinfo->script_space = NULL; - - cinfo->input_gamma = 1.0; /* in case application forgets */ - - /* OK, I'm ready */ - cinfo->global_state = CSTATE_START; -} - - -/* - * Destruction of a JPEG compression object - */ - -GLOBAL(void) -jpeg_destroy_compress (j_compress_ptr cinfo) -{ - jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Abort processing of a JPEG compression operation, - * but don't destroy the object itself. - */ - -GLOBAL(void) -jpeg_abort_compress (j_compress_ptr cinfo) -{ - jpeg_abort((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Forcibly suppress or un-suppress all quantization and Huffman tables. - * Marks all currently defined tables as already written (if suppress) - * or not written (if !suppress). This will control whether they get emitted - * by a subsequent jpeg_start_compress call. - * - * This routine is exported for use by applications that want to produce - * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but - * since it is called by jpeg_start_compress, we put it here --- otherwise - * jcparam.o would be linked whether the application used it or not. - */ - -GLOBAL(void) -jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) -{ - int i; - JQUANT_TBL * qtbl; - JHUFF_TBL * htbl; - - for (i = 0; i < NUM_QUANT_TBLS; i++) { - if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) - qtbl->sent_table = suppress; - } - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) - htbl->sent_table = suppress; - if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) - htbl->sent_table = suppress; - } -} - - -/* - * Finish JPEG compression. - * - * If a multipass operating mode was selected, this may do a great deal of - * work including most of the actual output. - */ - -GLOBAL(void) -jpeg_finish_compress (j_compress_ptr cinfo) -{ - JDIMENSION iMCU_row; - - if (cinfo->global_state == CSTATE_SCANNING || - cinfo->global_state == CSTATE_RAW_OK) { - /* Terminate first pass */ - if (cinfo->next_scanline < cinfo->image_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_pass) (cinfo); - } else if (cinfo->global_state != CSTATE_WRCOEFS) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any remaining passes */ - while (! cinfo->master->is_last_pass) { - (*cinfo->master->prepare_for_pass) (cinfo); - for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) iMCU_row; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* We bypass the main controller and invoke coef controller directly; - * all work is being done from the coefficient buffer. - */ - if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - } - (*cinfo->master->finish_pass) (cinfo); - } - /* Write EOI, do final cleanup */ - (*cinfo->marker->write_file_trailer) (cinfo); - (*cinfo->dest->term_destination) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ - jpeg_abort((j_common_ptr) cinfo); -} - - -/* - * Write a special marker. - * This is only recommended for writing COM or APPn markers. - * Must be called after jpeg_start_compress() and before - * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). - */ - -GLOBAL(void) -jpeg_write_marker (j_compress_ptr cinfo, int marker, - const JOCTET *dataptr, unsigned int datalen) -{ - JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); - - if (cinfo->next_scanline != 0 || - (cinfo->global_state != CSTATE_SCANNING && - cinfo->global_state != CSTATE_RAW_OK && - cinfo->global_state != CSTATE_WRCOEFS)) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); - write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ - while (datalen--) { - (*write_marker_byte) (cinfo, *dataptr); - dataptr++; - } -} - -/* Same, but piecemeal. */ - -GLOBAL(void) -jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) -{ - if (cinfo->next_scanline != 0 || - (cinfo->global_state != CSTATE_SCANNING && - cinfo->global_state != CSTATE_RAW_OK && - cinfo->global_state != CSTATE_WRCOEFS)) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); -} - -GLOBAL(void) -jpeg_write_m_byte (j_compress_ptr cinfo, int val) -{ - (*cinfo->marker->write_marker_byte) (cinfo, val); -} - - -/* - * Alternate compression function: just write an abbreviated table file. - * Before calling this, all parameters and a data destination must be set up. - * - * To produce a pair of files containing abbreviated tables and abbreviated - * image data, one would proceed as follows: - * - * initialize JPEG object - * set JPEG parameters - * set destination to table file - * jpeg_write_tables(cinfo); - * set destination to image file - * jpeg_start_compress(cinfo, FALSE); - * write data... - * jpeg_finish_compress(cinfo); - * - * jpeg_write_tables has the side effect of marking all tables written - * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress - * will not re-emit the tables unless it is passed write_all_tables=TRUE. - */ - -GLOBAL(void) -jpeg_write_tables (j_compress_ptr cinfo) -{ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* (Re)initialize error mgr and destination modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->dest->init_destination) (cinfo); - /* Initialize the marker writer ... bit of a crock to do it here. */ - jinit_marker_writer(cinfo); - /* Write them tables! */ - (*cinfo->marker->write_tables_only) (cinfo); - /* And clean up. */ - (*cinfo->dest->term_destination) (cinfo); - /* - * In library releases up through v6a, we called jpeg_abort() here to free - * any working memory allocated by the destination manager and marker - * writer. Some applications had a problem with that: they allocated space - * of their own from the library memory manager, and didn't want it to go - * away during write_tables. So now we do nothing. This will cause a - * memory leak if an app calls write_tables repeatedly without doing a full - * compression cycle or otherwise resetting the JPEG object. However, that - * seems less bad than unexpectedly freeing memory in the normal case. - * An app that prefers the old behavior can call jpeg_abort for itself after - * each call to jpeg_write_tables(). - */ -} diff --git a/third_party/libjpeg/fpdfapi_jcapistd.c b/third_party/libjpeg/fpdfapi_jcapistd.c deleted file mode 100644 index c0320b1b190f5b3b14e9f903bcd0a5cba8c84ef2..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcapistd.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * jcapistd.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the compression half - * of the JPEG library. These are the "standard" API routines that are - * used in the normal full-compression case. They are not used by a - * transcoding-only application. Note that if an application links in - * jpeg_start_compress, it will end up linking in the entire compressor. - * We thus must separate this file from jcapimin.c to avoid linking the - * whole compression library into a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Compression initialization. - * Before calling this, all parameters and a data destination must be set up. - * - * We require a write_all_tables parameter as a failsafe check when writing - * multiple datastreams from the same compression object. Since prior runs - * will have left all the tables marked sent_table=TRUE, a subsequent run - * would emit an abbreviated stream (no tables) by default. This may be what - * is wanted, but for safety's sake it should not be the default behavior: - * programmers should have to make a deliberate choice to emit abbreviated - * images. Therefore the documentation and examples should encourage people - * to pass write_all_tables=TRUE; then it will take active thought to do the - * wrong thing. - */ - -GLOBAL(void) -jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) -{ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (write_all_tables) - jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ - - /* (Re)initialize error mgr and destination modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->dest->init_destination) (cinfo); - /* Perform master selection of active modules */ - jinit_compress_master(cinfo); - /* Set up for the first pass */ - (*cinfo->master->prepare_for_pass) (cinfo); - /* Ready for application to drive first pass through jpeg_write_scanlines - * or jpeg_write_raw_data. - */ - cinfo->next_scanline = 0; - cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); -} - - -/* - * Write some scanlines of data to the JPEG compressor. - * - * The return value will be the number of lines actually written. - * This should be less than the supplied num_lines only in case that - * the data destination module has requested suspension of the compressor, - * or if more than image_height scanlines are passed in. - * - * Note: we warn about excess calls to jpeg_write_scanlines() since - * this likely signals an application programmer error. However, - * excess scanlines passed in the last valid call are *silently* ignored, - * so that the application need not adjust num_lines for end-of-image - * when using a multiple-scanline buffer. - */ - -GLOBAL(JDIMENSION) -jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION num_lines) -{ - JDIMENSION row_ctr, rows_left; - - if (cinfo->global_state != CSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->next_scanline >= cinfo->image_height) - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->next_scanline; - cinfo->progress->pass_limit = (long) cinfo->image_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Give master control module another chance if this is first call to - * jpeg_write_scanlines. This lets output of the frame/scan headers be - * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_scanlines. - */ - if (cinfo->master->call_pass_startup) - (*cinfo->master->pass_startup) (cinfo); - - /* Ignore any extra scanlines at bottom of image. */ - rows_left = cinfo->image_height - cinfo->next_scanline; - if (num_lines > rows_left) - num_lines = rows_left; - - row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); - cinfo->next_scanline += row_ctr; - return row_ctr; -} - - -/* - * Alternate entry point to write raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - -GLOBAL(JDIMENSION) -jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION num_lines) -{ - JDIMENSION lines_per_iMCU_row; - - if (cinfo->global_state != CSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->next_scanline >= cinfo->image_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->next_scanline; - cinfo->progress->pass_limit = (long) cinfo->image_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Give master control module another chance if this is first call to - * jpeg_write_raw_data. This lets output of the frame/scan headers be - * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_raw_data. - */ - if (cinfo->master->call_pass_startup) - (*cinfo->master->pass_startup) (cinfo); - - /* Verify that at least one iMCU row has been passed. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; - if (num_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* Directly compress the row. */ - if (! (*cinfo->coef->compress_data) (cinfo, data)) { - /* If compressor did not consume the whole row, suspend processing. */ - return 0; - } - - /* OK, we processed one iMCU row. */ - cinfo->next_scanline += lines_per_iMCU_row; - return lines_per_iMCU_row; -} diff --git a/third_party/libjpeg/fpdfapi_jccoefct.c b/third_party/libjpeg/fpdfapi_jccoefct.c deleted file mode 100644 index 1963ddb61b15689e36e3f1774007d3583b787a26..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jccoefct.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * jccoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the coefficient buffer controller for compression. - * This controller is the top level of the JPEG compressor proper. - * The coefficient buffer lies between forward-DCT and entropy encoding steps. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* We use a full-image coefficient buffer when doing Huffman optimization, - * and also for writing multiple-scan JPEG files. In all cases, the DCT - * step is run during the first pass, and subsequent passes need only read - * the buffered coefficients. - */ -#ifdef ENTROPY_OPT_SUPPORTED -#define FULL_COEF_BUFFER_SUPPORTED -#else -#ifdef C_MULTISCAN_FILES_SUPPORTED -#define FULL_COEF_BUFFER_SUPPORTED -#endif -#endif - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_coef_controller pub; /* public fields */ - - JDIMENSION iMCU_row_num; /* iMCU row # within image */ - JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* For single-pass compression, it's sufficient to buffer just one MCU - * (although this may prove a bit slow in practice). We allocate a - * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each - * MCU constructed and sent. (On 80x86, the workspace is FAR even though - * it's not really very big; this is to keep the module interfaces unchanged - * when a large coefficient buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays. - */ - JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; - - /* In multi-pass modes, we need a virtual block array for each component. */ - jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - - -/* Forward declarations */ -METHODDEF(boolean) compress_data - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -#ifdef FULL_COEF_BUFFER_SUPPORTED -METHODDEF(boolean) compress_first_pass - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -METHODDEF(boolean) compress_output - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->mcu_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - coef->iMCU_row_num = 0; - start_iMCU_row(cinfo); - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (coef->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_data; - break; -#ifdef FULL_COEF_BUFFER_SUPPORTED - case JBUF_SAVE_AND_PASS: - if (coef->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_first_pass; - break; - case JBUF_CRANK_DEST: - if (coef->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_output; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data in the single-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the image. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(boolean) -compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, bi, ci, yindex, yoffset, blockcnt; - JDIMENSION ypos, xpos; - jpeg_component_info *compptr; - - /* Loop to write as much as one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { - /* Determine where data comes from in input_buf and do the DCT thing. - * Each call on forward_DCT processes a horizontal row of DCT blocks - * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks - * sequentially. Dummy blocks at the right or bottom edge are filled in - * specially. The data in them does not matter for image reconstruction, - * so we fill them with values that will encode to the smallest amount of - * data, viz: all zeroes in the AC entries, DC entries equal to previous - * block's DC value. (Thanks to Thomas Kinsman for this idea.) - */ - blkn = 0; - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - xpos = MCU_col_num * compptr->MCU_sample_width; - ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (coef->iMCU_row_num < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION) blockcnt); - if (blockcnt < compptr->MCU_width) { - /* Create some dummy blocks at the right edge of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], - (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); - for (bi = blockcnt; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; - } - } - } else { - /* Create a row of dummy blocks at the bottom of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn], - compptr->MCU_width * SIZEOF(JBLOCK)); - for (bi = 0; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; - } - } - blkn += compptr->MCU_width; - ypos += DCTSIZE; - } - } - /* Try to write the MCU. In event of a suspension failure, we will - * re-DCT the MCU on restart (a bit inefficient, could be fixed...) - */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - coef->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - - -#ifdef FULL_COEF_BUFFER_SUPPORTED - -/* - * Process some data in the first pass of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the image. - * This amount of data is read from the source buffer, DCT'd and quantized, - * and saved into the virtual arrays. We also generate suitable dummy blocks - * as needed at the right and lower edges. (The dummy blocks are constructed - * in the virtual arrays, which have been padded appropriately.) This makes - * it possible for subsequent passes not to worry about real vs. dummy blocks. - * - * We must also emit the data to the entropy encoder. This is conveniently - * done by calling compress_output() after we've loaded the current strip - * of the virtual arrays. - * - * NB: input_buf contains a plane for each component in image. All - * components are DCT'd and loaded into the virtual arrays in this pass. - * However, it may be that only a subset of the components are emitted to - * the entropy encoder during this first pass; be careful about looking - * at the scan-dependent variables (MCU dimensions, etc). - */ - -METHODDEF(boolean) -compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION blocks_across, MCUs_across, MCUindex; - int bi, ci, h_samp_factor, block_row, block_rows, ndummy; - JCOEF lastDC; - jpeg_component_info *compptr; - JBLOCKARRAY buffer; - JBLOCKROW thisblockrow, lastblockrow; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (coef->iMCU_row_num < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here, since may not be set! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - blocks_across = compptr->width_in_blocks; - h_samp_factor = compptr->h_samp_factor; - /* Count number of dummy blocks to be added at the right margin. */ - ndummy = (int) (blocks_across % h_samp_factor); - if (ndummy > 0) - ndummy = h_samp_factor - ndummy; - /* Perform DCT for all non-dummy blocks in this iMCU row. Each call - * on forward_DCT processes a complete horizontal row of DCT blocks. - */ - for (block_row = 0; block_row < block_rows; block_row++) { - thisblockrow = buffer[block_row]; - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[ci], thisblockrow, - (JDIMENSION) (block_row * DCTSIZE), - (JDIMENSION) 0, blocks_across); - if (ndummy > 0) { - /* Create dummy blocks at the right edge of the image. */ - thisblockrow += blocks_across; /* => first dummy block */ - jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); - lastDC = thisblockrow[-1][0]; - for (bi = 0; bi < ndummy; bi++) { - thisblockrow[bi][0] = lastDC; - } - } - } - /* If at end of image, create dummy block rows as needed. - * The tricky part here is that within each MCU, we want the DC values - * of the dummy blocks to match the last real block's DC value. - * This squeezes a few more bytes out of the resulting file... - */ - if (coef->iMCU_row_num == last_iMCU_row) { - blocks_across += ndummy; /* include lower right corner */ - MCUs_across = blocks_across / h_samp_factor; - for (block_row = block_rows; block_row < compptr->v_samp_factor; - block_row++) { - thisblockrow = buffer[block_row]; - lastblockrow = buffer[block_row-1]; - jzero_far((void FAR *) thisblockrow, - (size_t) (blocks_across * SIZEOF(JBLOCK))); - for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { - lastDC = lastblockrow[h_samp_factor-1][0]; - for (bi = 0; bi < h_samp_factor; bi++) { - thisblockrow[bi][0] = lastDC; - } - thisblockrow += h_samp_factor; /* advance to next MCU in row */ - lastblockrow += h_samp_factor; - } - } - } - } - /* NB: compress_output will increment iMCU_row_num if successful. - * A suspension return will result in redoing all the work above next time. - */ - - /* Emit data to the entropy encoder, sharing code with subsequent passes */ - return compress_output(cinfo, input_buf); -} - - -/* - * Process some data in subsequent passes of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the entropy coder. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - -METHODDEF(boolean) -compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - int blkn, ci, xindex, yindex, yoffset; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. - * NB: during first pass, this is safe only because the buffers will - * already be aligned properly, so jmemmgr.c won't need to do any I/O. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } - } - /* Try to write the MCU. */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - coef->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - -#endif /* FULL_COEF_BUFFER_SUPPORTED */ - - -/* - * Initialize coefficient buffer controller. - */ - -GLOBAL(void) -jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - my_coef_ptr coef; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_c_coef_controller *) coef; - coef->pub.start_pass = start_pass_coef; - - /* Create the coefficient buffer. */ - if (need_full_buffer) { -#ifdef FULL_COEF_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - int ci; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) compptr->v_samp_factor); - } -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; - - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->whole_image[0] = NULL; /* flag for no virtual arrays */ - } -} diff --git a/third_party/libjpeg/fpdfapi_jccolor.c b/third_party/libjpeg/fpdfapi_jccolor.c deleted file mode 100644 index 0a8a4b5d13c303c4d14cd5b4333adcbb3cfcc4a2..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jccolor.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * jccolor.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains input colorspace conversion routines. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private subobject */ - -typedef struct { - struct jpeg_color_converter pub; /* public fields */ - - /* Private state for RGB->YCC conversion */ - INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ -} my_color_converter; - -typedef my_color_converter * my_cconvert_ptr; - - -/**************** RGB -> YCbCr conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, - * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and - * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) - * were not represented exactly. Now we sacrifice exact representation of - * maximum red and maximum blue in order to get exact grayscales. - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times R,G,B for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included - * in the tables to save adding them separately in the inner loop. - */ - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) - -/* We allocate one big table and divide it up into eight parts, instead of - * doing eight alloc_small requests. This lets us use a single table base - * address, which can be held in a register in the inner loops on many - * machines (more than can hold all eight addresses, anyway). - */ - -#define R_Y_OFF 0 /* offset to R => Y section */ -#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ -#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ -#define R_CB_OFF (3*(MAXJSAMPLE+1)) -#define G_CB_OFF (4*(MAXJSAMPLE+1)) -#define B_CB_OFF (5*(MAXJSAMPLE+1)) -#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ -#define G_CR_OFF (6*(MAXJSAMPLE+1)) -#define B_CR_OFF (7*(MAXJSAMPLE+1)) -#define TABLE_SIZE (8*(MAXJSAMPLE+1)) - - -/* - * Initialize for RGB->YCC colorspace conversion. - */ - -METHODDEF(void) -rgb_ycc_start (j_compress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - INT32 * rgb_ycc_tab; - INT32 i; - - /* Allocate and fill in the conversion tables. */ - cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (TABLE_SIZE * SIZEOF(INT32))); - - for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; - rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; - rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; - /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. - * This ensures that the maximum output will round to MAXJSAMPLE - * not MAXJSAMPLE+1, and thus that we don't have to range-limit. - */ - rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; -/* B=>Cb and R=>Cr tables are the same - rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; -*/ - rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; - rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * - * Note that we change from the application's interleaved-pixel format - * to our internal noninterleaved, one-plane-per-component format. - * The input buffer is therefore three times as wide as the output buffer. - * - * A starting row offset is provided only for the output buffer. The caller - * can easily adjust the passed input_buf value to accommodate any row - * offset required on that side. - */ - -METHODDEF(void) -rgb_ycc_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[RGB_RED]); - g = GETJSAMPLE(inptr[RGB_GREEN]); - b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); - } - } -} - - -/**************** Cases other than RGB -> YCbCr **************/ - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles RGB->grayscale conversion, which is the same - * as the RGB->Y portion of RGB->YCbCr. - * We assume rgb_ycc_start has been called (we only use the Y tables). - */ - -METHODDEF(void) -rgb_gray_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[RGB_RED]); - g = GETJSAMPLE(inptr[RGB_GREEN]); - b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; - /* Y */ - outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles Adobe-style CMYK->YCCK conversion, - * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same - * conversion as above, while passing K (black) unchanged. - * We assume rgb_ycc_start has been called. - */ - -METHODDEF(void) -cmyk_ycck_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int r, g, b; - register INT32 * ctab = cconvert->rgb_ycc_tab; - register JSAMPROW inptr; - register JSAMPROW outptr0, outptr1, outptr2, outptr3; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - outptr3 = output_buf[3][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); - g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); - b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); - /* K passes through as-is */ - outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ - inptr += 4; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles grayscale output with no conversion. - * The source can be either plain grayscale or YCbCr (since Y == gray). - */ - -METHODDEF(void) -grayscale_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - register JSAMPROW inptr; - register JSAMPROW outptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->image_width; - int instride = cinfo->input_components; - - while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ - inptr += instride; - } - } -} - - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles multi-component colorspaces without conversion. - * We assume input_components == num_components. - */ - -METHODDEF(void) -null_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - register JSAMPROW inptr; - register JSAMPROW outptr; - register JDIMENSION col; - register int ci; - int nc = cinfo->num_components; - JDIMENSION num_cols = cinfo->image_width; - - while (--num_rows >= 0) { - /* It seems fastest to make a separate pass for each component. */ - for (ci = 0; ci < nc; ci++) { - inptr = *input_buf; - outptr = output_buf[ci][output_row]; - for (col = 0; col < num_cols; col++) { - outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ - inptr += nc; - } - } - input_buf++; - output_row++; - } -} - - -/* - * Empty method for start_pass. - */ - -METHODDEF(void) -null_method (j_compress_ptr cinfo) -{ - /* no work needed */ -} - - -/* - * Module initialization routine for input colorspace conversion. - */ - -GLOBAL(void) -jinit_color_converter (j_compress_ptr cinfo) -{ - my_cconvert_ptr cconvert; - - cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_converter)); - cinfo->cconvert = (struct jpeg_color_converter *) cconvert; - /* set start_pass to null method until we find out differently */ - cconvert->pub.start_pass = null_method; - - /* Make sure input_components agrees with in_color_space */ - switch (cinfo->in_color_space) { - case JCS_GRAYSCALE: - if (cinfo->input_components != 1) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - case JCS_RGB: -#if RGB_PIXELSIZE != 3 - if (cinfo->input_components != RGB_PIXELSIZE) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; -#endif /* else share code with YCbCr */ - - case JCS_YCbCr: - if (cinfo->input_components != 3) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - case JCS_CMYK: - case JCS_YCCK: - if (cinfo->input_components != 4) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - default: /* JCS_UNKNOWN can be anything */ - if (cinfo->input_components < 1) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - } - - /* Check num_components, set conversion method based on requested space */ - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_GRAYSCALE) - cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_gray_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = grayscale_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_RGB: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_ycc_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_CMYK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = cmyk_ycck_convert; - } else if (cinfo->in_color_space == JCS_YCCK) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - default: /* allow null conversion of JCS_UNKNOWN */ - if (cinfo->jpeg_color_space != cinfo->in_color_space || - cinfo->num_components != cinfo->input_components) - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - cconvert->pub.color_convert = null_convert; - break; - } -} diff --git a/third_party/libjpeg/fpdfapi_jcdctmgr.c b/third_party/libjpeg/fpdfapi_jcdctmgr.c deleted file mode 100644 index 61fa79b9e68bcc3e3bfe84b9a50af55a9598214b..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcdctmgr.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * jcdctmgr.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the forward-DCT management logic. - * This code selects a particular DCT implementation to be used, - * and it performs related housekeeping chores including coefficient - * quantization. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - - -/* Private subobject for this module */ - -typedef struct { - struct jpeg_forward_dct pub; /* public fields */ - - /* Pointer to the DCT routine actually in use */ - forward_DCT_method_ptr do_dct; - - /* The actual post-DCT divisors --- not identical to the quant table - * entries, because of scaling (especially for an unnormalized DCT). - * Each table is given in normal array order. - */ - DCTELEM * divisors[NUM_QUANT_TBLS]; - -#ifdef DCT_FLOAT_SUPPORTED - /* Same as above for the floating-point case. */ - float_DCT_method_ptr do_float_dct; - FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; -#endif -} my_fdct_controller; - -typedef my_fdct_controller * my_fdct_ptr; - - -/* - * Initialize for a processing pass. - * Verify that all referenced Q-tables are present, and set up - * the divisor table for each one. - * In the current implementation, DCT of all components is done during - * the first pass, even if only some components will be output in the - * first scan. Hence all components should be examined here. - */ - -METHODDEF(void) -start_pass_fdctmgr (j_compress_ptr cinfo) -{ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - int ci, qtblno, i; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - DCTELEM * dtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - qtblno = compptr->quant_tbl_no; - /* Make sure specified quantization table is present */ - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - qtbl = cinfo->quant_tbl_ptrs[qtblno]; - /* Compute divisors for this quant table */ - /* We may do this more than once for same table, but it's not a big deal */ - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - /* For LL&M IDCT method, divisors are equal to raw quantization - * coefficients multiplied by 8 (to counteract scaling). - */ - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - */ -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = (DCTELEM) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-3); - } - } - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - FAST_FLOAT * fdtbl; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - if (fdct->float_divisors[qtblno] == NULL) { - fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(FAST_FLOAT)); - } - fdtbl = fdct->float_divisors[qtblno]; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} - - -/* - * Perform forward DCT on one or more blocks of a component. - * - * The input samples are taken from the sample_data[] array starting at - * position start_row/start_col, and moving to the right for any additional - * blocks. The quantized coefficients are returned in coef_blocks[]. - */ - -METHODDEF(void) -forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) -/* This version is used for integer DCT implementations. */ -{ - /* This routine is heavily used, so it's worth coding it tightly. */ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - forward_DCT_method_ptr do_dct = fdct->do_dct; - DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; - DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ - JDIMENSION bi; - - sample_data += start_row; /* fold in the vertical offset once */ - - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - } - } -#endif - } - } - - /* Perform the DCT */ - (*do_dct) (workspace); - - /* Quantize/descale the coefficients, and store into coef_blocks[] */ - { register DCTELEM temp, qval; - register int i; - register JCOEFPTR output_ptr = coef_blocks[bi]; - - for (i = 0; i < DCTSIZE2; i++) { - qval = divisors[i]; - temp = workspace[i]; - /* Divide the coefficient value by qval, ensuring proper rounding. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * - * In most files, at least half of the output values will be zero - * (at default quantization settings, more like three-quarters...) - * so we should ensure that this case is fast. On many machines, - * a comparison is enough cheaper than a divide to make a special test - * a win. Since both inputs will be nonnegative, we need only test - * for a < b to discover whether a/b is 0. - * If your machine's division is fast enough, define FAST_DIVIDE. - */ -#ifdef FAST_DIVIDE -#define DIVIDE_BY(a,b) a /= b -#else -#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 -#endif - if (temp < 0) { - temp = -temp; - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - temp = -temp; - } else { - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - } - output_ptr[i] = (JCOEF) temp; - } - } - } -} - - -#ifdef DCT_FLOAT_SUPPORTED - -METHODDEF(void) -forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) -/* This version is used for floating-point DCT implementations. */ -{ - /* This routine is heavily used, so it's worth coding it tightly. */ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - float_DCT_method_ptr do_dct = fdct->do_float_dct; - FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; - FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ - JDIMENSION bi; - - sample_data += start_row; /* fold in the vertical offset once */ - - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = (FAST_FLOAT) - (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - } - } -#endif - } - } - - /* Perform the DCT */ - (*do_dct) (workspace); - - /* Quantize/descale the coefficients, and store into coef_blocks[] */ - { register FAST_FLOAT temp; - register int i; - register JCOEFPTR output_ptr = coef_blocks[bi]; - - for (i = 0; i < DCTSIZE2; i++) { - /* Apply the quantization and scaling factor */ - temp = workspace[i] * divisors[i]; - /* Round to nearest integer. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * The maximum coefficient size is +-16K (for 12-bit data), so this - * code should work for either 16-bit or 32-bit ints. - */ - output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); - } - } - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ - - -/* - * Initialize FDCT manager. - */ - -GLOBAL(void) -jinit_forward_dct (j_compress_ptr cinfo) -{ - my_fdct_ptr fdct; - int i; - - fdct = (my_fdct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_fdct_controller)); - cinfo->fdct = (struct jpeg_forward_dct *) fdct; - fdct->pub.start_pass = start_pass_fdctmgr; - - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_islow; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_ifast; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - fdct->pub.forward_DCT = forward_DCT_float; - fdct->do_float_dct = jpeg_fdct_float; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - - /* Mark divisor tables unallocated */ - for (i = 0; i < NUM_QUANT_TBLS; i++) { - fdct->divisors[i] = NULL; -#ifdef DCT_FLOAT_SUPPORTED - fdct->float_divisors[i] = NULL; -#endif - } -} diff --git a/third_party/libjpeg/fpdfapi_jchuff.c b/third_party/libjpeg/fpdfapi_jchuff.c deleted file mode 100644 index 005220c3b2dfac57007c84a4b19bec05c95fb305..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jchuff.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - * jchuff.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines. - * - * Much of the complexity here has to do with supporting output suspension. - * If the data destination module demands suspension, we want to be able to - * back up to the start of the current MCU. To do this, we copy state - * variables into local working storage, and update them back to the - * permanent JPEG objects only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jcphuff.c */ - -/* Expanded entropy encoder object for Huffman encoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).put_buffer = (src).put_buffer, \ - (dest).put_bits = (src).put_bits, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_encoder pub; /* public fields */ - - savable_state saved; /* Bit buffer & DC state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - -#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ - long * dc_count_ptrs[NUM_HUFF_TBLS]; - long * ac_count_ptrs[NUM_HUFF_TBLS]; -#endif -} huff_entropy_encoder; - -typedef huff_entropy_encoder * huff_entropy_ptr; - -/* Working state while writing an MCU. - * This struct contains all the fields that are needed by subroutines. - */ - -typedef struct { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - savable_state cur; /* Current bit buffer & DC state */ - j_compress_ptr cinfo; /* dump_buffer needs access to this */ -} working_state; - - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); -#ifdef ENTROPY_OPT_SUPPORTED -METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); -#endif - - -/* - * Initialize for a Huffman-compressed scan. - * If gather_statistics is TRUE, we do not output anything during the scan, - * just count the Huffman symbols used and generate Huffman code tables. - */ - -METHODDEF(void) -start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - entropy->pub.encode_mcu = encode_mcu_gather; - entropy->pub.finish_pass = finish_pass_gather; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - entropy->pub.encode_mcu = encode_mcu_huff; - entropy->pub.finish_pass = finish_pass_huff; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - /* Check for invalid table indexes */ - /* (make_c_derived_tbl does this in the other path) */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - if (actbl < 0 || actbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->dc_count_ptrs[dctbl] == NULL) - entropy->dc_count_ptrs[dctbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); - if (entropy->ac_count_ptrs[actbl] == NULL) - entropy->ac_count_ptrs[actbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); -#endif - } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bit buffer to empty */ - entropy->saved.put_buffer = 0; - entropy->saved.put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - * - * Note this is also used by jcphuff.c. - */ - -GLOBAL(void) -jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl) -{ - JHUFF_TBL *htbl; - c_derived_tbl *dtbl; - int p, i, l, lastp, _si, maxsymbol; - char huffsize[257]; - unsigned int huffcode[257]; - unsigned int code; - - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ - if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - - /* Allocate a workspace if we haven't already done so. */ - if (*pdtbl == NULL) - *pdtbl = (c_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_derived_tbl)); - dtbl = *pdtbl; - - /* Figure C.1: make table of Huffman code length for each symbol */ - - p = 0; - for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; - } - huffsize[p] = 0; - lastp = p; - - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - - code = 0; - _si = huffsize[0]; - p = 0; - while (huffsize[p]) { - while (((int) huffsize[p]) == _si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << _si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - _si++; - } - - /* Figure C.3: generate encoding tables */ - /* These are code and size indexed by symbol value */ - - /* Set all codeless symbols to have code length 0; - * this lets us detect duplicate VAL entries here, and later - * allows emit_bits to detect any attempt to emit such symbols. - */ - MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); - - /* This is also a convenient place to check for out-of-range - * and duplicated VAL entries. We allow 0..255 for AC symbols - * but only 0..15 for DC. (We could constrain them further - * based on data depth and mode, but this seems enough.) - */ - maxsymbol = isDC ? 15 : 255; - - for (p = 0; p < lastp; p++) { - i = htbl->huffval[p]; - if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - dtbl->ehufco[i] = huffcode[p]; - dtbl->ehufsi[i] = huffsize[p]; - } -} - - -/* Outputting bytes to the file */ - -/* Emit a byte, taking 'action' if must suspend. */ -#define emit_byte(state,val,action) \ - { *(state)->next_output_byte++ = (JOCTET) (val); \ - if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ - { action; } } - - -LOCAL(boolean) -dump_buffer (working_state * state) -/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ -{ - struct jpeg_destination_mgr * dest = state->cinfo->dest; - - if (! (*dest->empty_output_buffer) (state->cinfo)) - return FALSE; - /* After a successful buffer dump, must reset buffer pointers */ - state->next_output_byte = dest->next_output_byte; - state->free_in_buffer = dest->free_in_buffer; - return TRUE; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(boolean) -emit_bits (working_state * state, unsigned int code, int size) -/* Emit some bits; return TRUE if successful, FALSE if must suspend */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = state->cur.put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); - - put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */ - - put_bits += size; /* new number of bits in buffer */ - - put_buffer <<= 24 - put_bits; /* align incoming bits */ - - put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(state, c, return FALSE); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); - } - put_buffer <<= 8; - put_bits -= 8; - } - - state->cur.put_buffer = put_buffer; /* update state variables */ - state->cur.put_bits = put_bits; - - return TRUE; -} - - -LOCAL(boolean) -flush_bits (working_state * state) -{ - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; - state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ - state->cur.put_bits = 0; - return TRUE; -} - - -/* Encode a single block's worth of coefficients */ - -LOCAL(boolean) -encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, - c_derived_tbl *dctbl, c_derived_tbl *actbl) -{ - register int temp, temp2; - register int nbits; - register int k, r, i; - - /* Encode the DC coefficient difference per section F.1.2.1 */ - - temp = temp2 = block[0] - last_dc_val; - - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit the Huffman-coded symbol for the number of bits */ - if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) - return FALSE; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - /* Encode the AC coefficients per section F.1.2.2 */ - - r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) - return FALSE; - r -= 16; - } - - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - - /* Emit Huffman symbol for run length / number of bits */ - i = (r << 4) + nbits; - if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) - return FALSE; - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - r = 0; - } - } - - /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) - return FALSE; - - return TRUE; -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(boolean) -emit_restart (working_state * state, int restart_num) -{ - int ci; - - if (! flush_bits(state)) - return FALSE; - - emit_byte(state, 0xFF, return FALSE); - emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) - state->cur.last_dc_val[ci] = 0; - - /* The restart counter is not updated until we successfully write the MCU. */ - - return TRUE; -} - - -/* - * Encode and output one MCU's worth of Huffman-compressed coefficients. - */ - -METHODDEF(boolean) -encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - working_state state; - int blkn, ci; - jpeg_component_info * compptr; - - /* Load up working state */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) - return FALSE; - } - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - if (! encode_one_block(&state, - MCU_data[blkn][0], state.cur.last_dc_val[ci], - entropy->dc_derived_tbls[compptr->dc_tbl_no], - entropy->ac_derived_tbls[compptr->ac_tbl_no])) - return FALSE; - /* Update last_dc_val */ - state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - /* Completed MCU, so update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed scan. - */ - -METHODDEF(void) -finish_pass_huff (j_compress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - working_state state; - - /* Load up working state ... flush_bits needs it */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; - - /* Flush out the last data */ - if (! flush_bits(&state)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - - /* Update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); -} - - -/* - * Huffman coding optimization. - * - * We first scan the supplied data and count the number of uses of each symbol - * that is to be Huffman-coded. (This process MUST agree with the code above.) - * Then we build a Huffman coding tree for the observed counts. - * Symbols which are not needed at all for the particular image are not - * assigned any code, which saves space in the DHT marker as well as in - * the compressed data. - */ - -#ifdef ENTROPY_OPT_SUPPORTED - - -/* Process a single block's worth of coefficients */ - -LOCAL(void) -htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, - long dc_counts[], long ac_counts[]) -{ - register int temp; - register int nbits; - register int k, r; - - /* Encode the DC coefficient difference per section F.1.2.1 */ - - temp = block[0] - last_dc_val; - if (temp < 0) - temp = -temp; - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count the Huffman symbol for the number of bits */ - dc_counts[nbits]++; - - /* Encode the AC coefficients per section F.1.2.2 */ - - r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - ac_counts[0xF0]++; - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - if (temp < 0) - temp = -temp; - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count Huffman symbol for run length / number of bits */ - ac_counts[(r << 4) + nbits]++; - - r = 0; - } - } - - /* If the last coef(s) were zero, emit an end-of-block code */ - if (r > 0) - ac_counts[0]++; -} - - -/* - * Trial-encode one MCU's worth of Huffman-compressed coefficients. - * No data is actually output, so no suspension return is possible. - */ - -METHODDEF(boolean) -encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int blkn, ci; - jpeg_component_info * compptr; - - /* Take care of restart intervals if needed */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Update restart state */ - entropy->restarts_to_go = cinfo->restart_interval; - } - entropy->restarts_to_go--; - } - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], - entropy->dc_count_ptrs[compptr->dc_tbl_no], - entropy->ac_count_ptrs[compptr->ac_tbl_no]); - entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; - } - - return TRUE; -} - - -/* - * Generate the best Huffman code table for the given counts, fill htbl. - * Note this is also used by jcphuff.c. - * - * The JPEG standard requires that no symbol be assigned a codeword of all - * one bits (so that padding bits added at the end of a compressed segment - * can't look like a valid code). Because of the canonical ordering of - * codewords, this just means that there must be an unused slot in the - * longest codeword length category. Section K.2 of the JPEG spec suggests - * reserving such a slot by pretending that symbol 256 is a valid symbol - * with count 1. In theory that's not optimal; giving it count zero but - * including it in the symbol set anyway should give a better Huffman code. - * But the theoretically better code actually seems to come out worse in - * practice, because it produces more all-ones bytes (which incur stuffed - * zero bytes in the final file). In any case the difference is tiny. - * - * The JPEG standard requires Huffman codes to be no more than 16 bits long. - * If some symbols have a very small but nonzero probability, the Huffman tree - * must be adjusted to meet the code length restriction. We currently use - * the adjustment method suggested in JPEG section K.2. This method is *not* - * optimal; it may not choose the best possible limited-length code. But - * typically only very-low-frequency symbols will be given less-than-optimal - * lengths, so the code is almost optimal. Experimental comparisons against - * an optimal limited-length-code algorithm indicate that the difference is - * microscopic --- usually less than a hundredth of a percent of total size. - * So the extra complexity of an optimal algorithm doesn't seem worthwhile. - */ - -GLOBAL(void) -jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) -{ -#define MAX_CLEN 32 /* assumed maximum initial code length */ - UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ - int codesize[257]; /* codesize[k] = code length of symbol k */ - int others[257]; /* next symbol in current branch of tree */ - int c1, c2; - int p, i, j; - long v; - - /* This algorithm is explained in section K.2 of the JPEG standard */ - - MEMZERO(bits, SIZEOF(bits)); - MEMZERO(codesize, SIZEOF(codesize)); - for (i = 0; i < 257; i++) - others[i] = -1; /* init links to empty */ - - freq[256] = 1; /* make sure 256 has a nonzero count */ - /* Including the pseudo-symbol 256 in the Huffman procedure guarantees - * that no real symbol is given code-value of all ones, because 256 - * will be placed last in the largest codeword category. - */ - - /* Huffman's basic algorithm to assign optimal code lengths to symbols */ - - for (;;) { - /* Find the smallest nonzero frequency, set c1 = its symbol */ - /* In case of ties, take the larger symbol number */ - c1 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v) { - v = freq[i]; - c1 = i; - } - } - - /* Find the next smallest nonzero frequency, set c2 = its symbol */ - /* In case of ties, take the larger symbol number */ - c2 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v && i != c1) { - v = freq[i]; - c2 = i; - } - } - - /* Done if we've merged everything into one frequency */ - if (c2 < 0) - break; - - /* Else merge the two counts/trees */ - freq[c1] += freq[c2]; - freq[c2] = 0; - - /* Increment the codesize of everything in c1's tree branch */ - codesize[c1]++; - while (others[c1] >= 0) { - c1 = others[c1]; - codesize[c1]++; - } - - others[c1] = c2; /* chain c2 onto c1's tree branch */ - - /* Increment the codesize of everything in c2's tree branch */ - codesize[c2]++; - while (others[c2] >= 0) { - c2 = others[c2]; - codesize[c2]++; - } - } - - /* Now count the number of symbols of each code length */ - for (i = 0; i <= 256; i++) { - if (codesize[i]) { - /* The JPEG standard seems to think that this can't happen, */ - /* but I'm paranoid... */ - if (codesize[i] > MAX_CLEN) - ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); - - bits[codesize[i]]++; - } - } - - /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure - * Huffman procedure assigned any such lengths, we must adjust the coding. - * Here is what the JPEG spec says about how this next bit works: - * Since symbols are paired for the longest Huffman code, the symbols are - * removed from this length category two at a time. The prefix for the pair - * (which is one bit shorter) is allocated to one of the pair; then, - * skipping the BITS entry for that prefix length, a code word from the next - * shortest nonzero BITS entry is converted into a prefix for two code words - * one bit longer. - */ - - for (i = MAX_CLEN; i > 16; i--) { - while (bits[i] > 0) { - j = i - 2; /* find length of new prefix to be used */ - while (bits[j] == 0) - j--; - - bits[i] -= 2; /* remove two symbols */ - bits[i-1]++; /* one goes in this length */ - bits[j+1] += 2; /* two new symbols in this length */ - bits[j]--; /* symbol of this length is now a prefix */ - } - } - - /* Remove the count for the pseudo-symbol 256 from the largest codelength */ - while (bits[i] == 0) /* find largest codelength still in use */ - i--; - bits[i]--; - - /* Return final symbol counts (only for lengths 0..16) */ - MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); - - /* Return a list of the symbols sorted by code length */ - /* It's not real clear to me why we don't need to consider the codelength - * changes made above, but the JPEG spec seems to think this works. - */ - p = 0; - for (i = 1; i <= MAX_CLEN; i++) { - for (j = 0; j <= 255; j++) { - if (codesize[j] == i) { - htbl->huffval[p] = (UINT8) j; - p++; - } - } - } - - /* Set sent_table FALSE so updated table will be written to JPEG file. */ - htbl->sent_table = FALSE; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather (j_compress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did_dc[NUM_HUFF_TBLS]; - boolean did_ac[NUM_HUFF_TBLS]; - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did_dc, SIZEOF(did_dc)); - MEMZERO(did_ac, SIZEOF(did_ac)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (! did_dc[dctbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); - did_dc[dctbl] = TRUE; - } - if (! did_ac[actbl]) { - htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); - did_ac[actbl] = TRUE; - } - } -} - - -#endif /* ENTROPY_OPT_SUPPORTED */ - - -/* - * Module initialization routine for Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_huff_encoder (j_compress_ptr cinfo) -{ - huff_entropy_ptr entropy; - int i; - - entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_encoder)); - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; - entropy->pub.start_pass = start_pass_huff; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; -#ifdef ENTROPY_OPT_SUPPORTED - entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; -#endif - } -} diff --git a/third_party/libjpeg/fpdfapi_jcinit.c b/third_party/libjpeg/fpdfapi_jcinit.c deleted file mode 100644 index 5efffe33166bc0d6ac7ea8c691a00be5b9ff0de8..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcinit.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * jcinit.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains initialization logic for the JPEG compressor. - * This routine is in charge of selecting the modules to be executed and - * making an initialization call to each one. - * - * Logically, this code belongs in jcmaster.c. It's split out because - * linking this routine implies linking the entire compression library. - * For a transcoding-only application, we want to be able to use jcmaster.c - * without linking in the whole library. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Master selection of compression modules. - * This is done once at the start of processing an image. We determine - * which modules will be used and give them appropriate initialization calls. - */ - -GLOBAL(void) -jinit_compress_master (j_compress_ptr cinfo) -{ - /* Initialize master control (includes parameter checking/processing) */ - jinit_c_master_control(cinfo, FALSE /* full compression */); - - /* Preprocessing */ - if (! cinfo->raw_data_in) { - jinit_color_converter(cinfo); - jinit_downsampler(cinfo); - jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); - } - /* Forward DCT */ - jinit_forward_dct(cinfo); - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); - } - - /* Need a full-image coefficient buffer in any multi-pass mode. */ - jinit_c_coef_controller(cinfo, - (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); - jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); - - jinit_marker_writer(cinfo); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Write the datastream header (SOI) immediately. - * Frame and scan headers are postponed till later. - * This lets application insert special markers after the SOI. - */ - (*cinfo->marker->write_file_header) (cinfo); -} diff --git a/third_party/libjpeg/fpdfapi_jcmainct.c b/third_party/libjpeg/fpdfapi_jcmainct.c deleted file mode 100644 index e0279a7e017a2ee5a3c6f5bc434e220ddcebbfc5..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcmainct.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * jcmainct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the main buffer controller for compression. - * The main buffer lies between the pre-processor and the JPEG - * compressor proper; it holds downsampled data in the JPEG colorspace. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Note: currently, there is no operating mode in which a full-image buffer - * is needed at this step. If there were, that mode could not be used with - * "raw data" input, since this module is bypassed in that case. However, - * we've left the code here for possible use in special applications. - */ -#undef FULL_MAIN_BUFFER_SUPPORTED - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_main_controller pub; /* public fields */ - - JDIMENSION cur_iMCU_row; /* number of current iMCU row */ - JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ - boolean suspended; /* remember if we suspended output */ - J_BUF_MODE pass_mode; /* current operating mode */ - - /* If using just a strip buffer, this points to the entire set of buffers - * (we allocate one for each component). In the full-image case, this - * points to the currently accessible strips of the virtual arrays. - */ - JSAMPARRAY buffer[MAX_COMPONENTS]; - -#ifdef FULL_MAIN_BUFFER_SUPPORTED - /* If using full-image storage, this array holds pointers to virtual-array - * control blocks for each component. Unused if not full-image storage. - */ - jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; -#endif -} my_main_controller; - -typedef my_main_controller * my_main_ptr; - - -/* Forward declarations */ -METHODDEF(void) process_data_simple_main - JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); -#ifdef FULL_MAIN_BUFFER_SUPPORTED -METHODDEF(void) process_data_buffer_main - JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); -#endif - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - - /* Do nothing in raw-data mode. */ - if (cinfo->raw_data_in) - return; - - main->cur_iMCU_row = 0; /* initialize counters */ - main->rowgroup_ctr = 0; - main->suspended = FALSE; - main->pass_mode = pass_mode; /* save mode for use by process_data */ - - switch (pass_mode) { - case JBUF_PASS_THRU: -#ifdef FULL_MAIN_BUFFER_SUPPORTED - if (main->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - main->pub.process_data = process_data_simple_main; - break; -#ifdef FULL_MAIN_BUFFER_SUPPORTED - case JBUF_SAVE_SOURCE: - case JBUF_CRANK_DEST: - case JBUF_SAVE_AND_PASS: - if (main->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - main->pub.process_data = process_data_buffer_main; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data. - * This routine handles the simple pass-through mode, - * where we have only a strip buffer. - */ - -METHODDEF(void) -process_data_simple_main (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - - while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Read input data if we haven't filled the main buffer yet */ - if (main->rowgroup_ctr < DCTSIZE) - (*cinfo->prep->pre_process_data) (cinfo, - input_buf, in_row_ctr, in_rows_avail, - main->buffer, &main->rowgroup_ctr, - (JDIMENSION) DCTSIZE); - - /* If we don't have a full iMCU row buffered, return to application for - * more data. Note that preprocessor will always pad to fill the iMCU row - * at the bottom of the image. - */ - if (main->rowgroup_ctr != DCTSIZE) - return; - - /* Send the completed row to the compressor */ - if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ - if (! main->suspended) { - (*in_row_ctr)--; - main->suspended = TRUE; - } - return; - } - /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main buffer empty. - */ - if (main->suspended) { - (*in_row_ctr)++; - main->suspended = FALSE; - } - main->rowgroup_ctr = 0; - main->cur_iMCU_row++; - } -} - - -#ifdef FULL_MAIN_BUFFER_SUPPORTED - -/* - * Process some data. - * This routine handles all of the modes that use a full-size buffer. - */ - -METHODDEF(void) -process_data_buffer_main (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci; - jpeg_component_info *compptr; - boolean writing = (main->pass_mode != JBUF_CRANK_DEST); - - while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Realign the virtual buffers if at the start of an iMCU row. */ - if (main->rowgroup_ctr == 0) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - main->buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, main->whole_image[ci], - main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); - } - /* In a read pass, pretend we just read some source data. */ - if (! writing) { - *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; - main->rowgroup_ctr = DCTSIZE; - } - } - - /* If a write pass, read input data until the current iMCU row is full. */ - /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ - if (writing) { - (*cinfo->prep->pre_process_data) (cinfo, - input_buf, in_row_ctr, in_rows_avail, - main->buffer, &main->rowgroup_ctr, - (JDIMENSION) DCTSIZE); - /* Return to application if we need more data to fill the iMCU row. */ - if (main->rowgroup_ctr < DCTSIZE) - return; - } - - /* Emit data, unless this is a sink-only pass. */ - if (main->pass_mode != JBUF_SAVE_SOURCE) { - if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ - if (! main->suspended) { - (*in_row_ctr)--; - main->suspended = TRUE; - } - return; - } - /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main buffer empty. - */ - if (main->suspended) { - (*in_row_ctr)++; - main->suspended = FALSE; - } - } - - /* If get here, we are done with this iMCU row. Mark buffer empty. */ - main->rowgroup_ctr = 0; - main->cur_iMCU_row++; - } -} - -#endif /* FULL_MAIN_BUFFER_SUPPORTED */ - - -/* - * Initialize main buffer controller. - */ - -GLOBAL(void) -jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - my_main_ptr main; - int ci; - jpeg_component_info *compptr; - - main = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_c_main_controller *) main; - main->pub.start_pass = start_pass_main; - - /* We don't need to create a buffer in raw-data mode. */ - if (cinfo->raw_data_in) - return; - - /* Create the buffer. It holds downsampled data, so each component - * may be of a different size. - */ - if (need_full_buffer) { -#ifdef FULL_MAIN_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component */ - /* Note we pad the bottom to a multiple of the iMCU height */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor) * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); - } -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif - } else { -#ifdef FULL_MAIN_BUFFER_SUPPORTED - main->whole_image[0] = NULL; /* flag for no virtual arrays */ -#endif - /* Allocate a strip buffer for each component */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - main->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); - } - } -} diff --git a/third_party/libjpeg/fpdfapi_jcmarker.c b/third_party/libjpeg/fpdfapi_jcmarker.c deleted file mode 100644 index 3d1e6c6d524850e0d401fcec9f590d5648d13ee7..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcmarker.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * jcmarker.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains routines to write JPEG datastream markers. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - - M_JPG0 = 0xf0, - M_JPG13 = 0xfd, - M_COM = 0xfe, - - M_TEM = 0x01, - - M_ERROR = 0x100 -} JPEG_MARKER; - - -/* Private state */ - -typedef struct { - struct jpeg_marker_writer pub; /* public fields */ - - unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ -} my_marker_writer; - -typedef my_marker_writer * my_marker_ptr; - - -/* - * Basic output routines. - * - * Note that we do not support suspension while writing a marker. - * Therefore, an application using suspension must ensure that there is - * enough buffer space for the initial markers (typ. 600-700 bytes) before - * calling jpeg_start_compress, and enough space to write the trailing EOI - * (a few bytes) before calling jpeg_finish_compress. Multipass compression - * modes are not supported at all with suspension, so those two are the only - * points where markers will be written. - */ - -LOCAL(void) -emit_byte (j_compress_ptr cinfo, int val) -/* Emit a byte */ -{ - struct jpeg_destination_mgr * dest = cinfo->dest; - - *(dest->next_output_byte)++ = (JOCTET) val; - if (--dest->free_in_buffer == 0) { - if (! (*dest->empty_output_buffer) (cinfo)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); - } -} - - -LOCAL(void) -emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) -/* Emit a marker code */ -{ - emit_byte(cinfo, 0xFF); - emit_byte(cinfo, (int) mark); -} - - -LOCAL(void) -emit_2bytes (j_compress_ptr cinfo, int value) -/* Emit a 2-byte integer; these are always MSB first in JPEG files */ -{ - emit_byte(cinfo, (value >> 8) & 0xFF); - emit_byte(cinfo, value & 0xFF); -} - - -/* - * Routines to write specific marker types. - */ - -LOCAL(int) -emit_dqt (j_compress_ptr cinfo, int index) -/* Emit a DQT marker */ -/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ -{ - JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; - int prec; - int i; - - if (qtbl == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); - - prec = 0; - for (i = 0; i < DCTSIZE2; i++) { - if (qtbl->quantval[i] > 255) - prec = 1; - } - - if (! qtbl->sent_table) { - emit_marker(cinfo, M_DQT); - - emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); - - emit_byte(cinfo, index + (prec<<4)); - - for (i = 0; i < DCTSIZE2; i++) { - /* The table entries must be emitted in zigzag order. */ - unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; - if (prec) - emit_byte(cinfo, (int) (qval >> 8)); - emit_byte(cinfo, (int) (qval & 0xFF)); - } - - qtbl->sent_table = TRUE; - } - - return prec; -} - - -LOCAL(void) -emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) -/* Emit a DHT marker */ -{ - JHUFF_TBL * htbl; - int length, i; - - if (is_ac) { - htbl = cinfo->ac_huff_tbl_ptrs[index]; - index += 0x10; /* output index has AC bit set */ - } else { - htbl = cinfo->dc_huff_tbl_ptrs[index]; - } - - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); - - if (! htbl->sent_table) { - emit_marker(cinfo, M_DHT); - - length = 0; - for (i = 1; i <= 16; i++) - length += htbl->bits[i]; - - emit_2bytes(cinfo, length + 2 + 1 + 16); - emit_byte(cinfo, index); - - for (i = 1; i <= 16; i++) - emit_byte(cinfo, htbl->bits[i]); - - for (i = 0; i < length; i++) - emit_byte(cinfo, htbl->huffval[i]); - - htbl->sent_table = TRUE; - } -} - - -LOCAL(void) -emit_dac (j_compress_ptr cinfo) -/* Emit a DAC marker */ -/* Since the useful info is so small, we want to emit all the tables in */ -/* one DAC marker. Therefore this routine does its own scan of the table. */ -{ -#ifdef C_ARITH_CODING_SUPPORTED - char dc_in_use[NUM_ARITH_TBLS]; - char ac_in_use[NUM_ARITH_TBLS]; - int length, i; - jpeg_component_info *compptr; - - for (i = 0; i < NUM_ARITH_TBLS; i++) - dc_in_use[i] = ac_in_use[i] = 0; - - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - dc_in_use[compptr->dc_tbl_no] = 1; - ac_in_use[compptr->ac_tbl_no] = 1; - } - - length = 0; - for (i = 0; i < NUM_ARITH_TBLS; i++) - length += dc_in_use[i] + ac_in_use[i]; - - emit_marker(cinfo, M_DAC); - - emit_2bytes(cinfo, length*2 + 2); - - for (i = 0; i < NUM_ARITH_TBLS; i++) { - if (dc_in_use[i]) { - emit_byte(cinfo, i); - emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); - } - if (ac_in_use[i]) { - emit_byte(cinfo, i + 0x10); - emit_byte(cinfo, cinfo->arith_ac_K[i]); - } - } -#endif /* C_ARITH_CODING_SUPPORTED */ -} - - -LOCAL(void) -emit_dri (j_compress_ptr cinfo) -/* Emit a DRI marker */ -{ - emit_marker(cinfo, M_DRI); - - emit_2bytes(cinfo, 4); /* fixed length */ - - emit_2bytes(cinfo, (int) cinfo->restart_interval); -} - - -LOCAL(void) -emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) -/* Emit a SOF marker */ -{ - int ci; - jpeg_component_info *compptr; - - emit_marker(cinfo, code); - - emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ - - /* Make sure image isn't bigger than SOF field can handle */ - if ((long) cinfo->image_height > 65535L || - (long) cinfo->image_width > 65535L) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); - - emit_byte(cinfo, cinfo->data_precision); - emit_2bytes(cinfo, (int) cinfo->image_height); - emit_2bytes(cinfo, (int) cinfo->image_width); - - emit_byte(cinfo, cinfo->num_components); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - emit_byte(cinfo, compptr->component_id); - emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); - emit_byte(cinfo, compptr->quant_tbl_no); - } -} - - -LOCAL(void) -emit_sos (j_compress_ptr cinfo) -/* Emit a SOS marker */ -{ - int i, td, ta; - jpeg_component_info *compptr; - - emit_marker(cinfo, M_SOS); - - emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ - - emit_byte(cinfo, cinfo->comps_in_scan); - - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - emit_byte(cinfo, compptr->component_id); - td = compptr->dc_tbl_no; - ta = compptr->ac_tbl_no; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan; - * furthermore, Huffman coding of DC refinement uses no table at all. - * We emit 0 for unused field(s); this is recommended by the P&M text - * but does not seem to be specified in the standard. - */ - if (cinfo->Ss == 0) { - ta = 0; /* DC scan */ - if (cinfo->Ah != 0 && !cinfo->arith_code) - td = 0; /* no DC table either */ - } else { - td = 0; /* AC scan */ - } - } - emit_byte(cinfo, (td << 4) + ta); - } - - emit_byte(cinfo, cinfo->Ss); - emit_byte(cinfo, cinfo->Se); - emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); -} - - -LOCAL(void) -emit_jfif_app0 (j_compress_ptr cinfo) -/* Emit a JFIF-compliant APP0 marker */ -{ - /* - * Length of APP0 block (2 bytes) - * Block ID (4 bytes - ASCII "JFIF") - * Zero byte (1 byte to terminate the ID string) - * Version Major, Minor (2 bytes - major first) - * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) - * Xdpu (2 bytes - dots per unit horizontal) - * Ydpu (2 bytes - dots per unit vertical) - * Thumbnail X size (1 byte) - * Thumbnail Y size (1 byte) - */ - - emit_marker(cinfo, M_APP0); - - emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ - - emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ - emit_byte(cinfo, 0x46); - emit_byte(cinfo, 0x49); - emit_byte(cinfo, 0x46); - emit_byte(cinfo, 0); - emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ - emit_byte(cinfo, cinfo->JFIF_minor_version); - emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ - emit_2bytes(cinfo, (int) cinfo->X_density); - emit_2bytes(cinfo, (int) cinfo->Y_density); - emit_byte(cinfo, 0); /* No thumbnail image */ - emit_byte(cinfo, 0); -} - - -LOCAL(void) -emit_adobe_app14 (j_compress_ptr cinfo) -/* Emit an Adobe APP14 marker */ -{ - /* - * Length of APP14 block (2 bytes) - * Block ID (5 bytes - ASCII "Adobe") - * Version Number (2 bytes - currently 100) - * Flags0 (2 bytes - currently 0) - * Flags1 (2 bytes - currently 0) - * Color transform (1 byte) - * - * Although Adobe TN 5116 mentions Version = 101, all the Adobe files - * now in circulation seem to use Version = 100, so that's what we write. - * - * We write the color transform byte as 1 if the JPEG color space is - * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with - * whether the encoder performed a transformation, which is pretty useless. - */ - - emit_marker(cinfo, M_APP14); - - emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ - - emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ - emit_byte(cinfo, 0x64); - emit_byte(cinfo, 0x6F); - emit_byte(cinfo, 0x62); - emit_byte(cinfo, 0x65); - emit_2bytes(cinfo, 100); /* Version */ - emit_2bytes(cinfo, 0); /* Flags0 */ - emit_2bytes(cinfo, 0); /* Flags1 */ - switch (cinfo->jpeg_color_space) { - case JCS_YCbCr: - emit_byte(cinfo, 1); /* Color transform = 1 */ - break; - case JCS_YCCK: - emit_byte(cinfo, 2); /* Color transform = 2 */ - break; - default: - emit_byte(cinfo, 0); /* Color transform = 0 */ - break; - } -} - - -/* - * These routines allow writing an arbitrary marker with parameters. - * The only intended use is to emit COM or APPn markers after calling - * write_file_header and before calling write_frame_header. - * Other uses are not guaranteed to produce desirable results. - * Counting the parameter bytes properly is the caller's responsibility. - */ - -METHODDEF(void) -write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) -/* Emit an arbitrary marker header */ -{ - if (datalen > (unsigned int) 65533) /* safety check */ - ERREXIT(cinfo, JERR_BAD_LENGTH); - - emit_marker(cinfo, (JPEG_MARKER) marker); - - emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ -} - -METHODDEF(void) -write_marker_byte (j_compress_ptr cinfo, int val) -/* Emit one byte of marker parameters following write_marker_header */ -{ - emit_byte(cinfo, val); -} - - -/* - * Write datastream header. - * This consists of an SOI and optional APPn markers. - * We recommend use of the JFIF marker, but not the Adobe marker, - * when using YCbCr or grayscale data. The JFIF marker should NOT - * be used for any other JPEG colorspace. The Adobe marker is helpful - * to distinguish RGB, CMYK, and YCCK colorspaces. - * Note that an application can write additional header markers after - * jpeg_start_compress returns. - */ - -METHODDEF(void) -write_file_header (j_compress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - emit_marker(cinfo, M_SOI); /* first the SOI */ - - /* SOI is defined to reset restart interval to 0 */ - marker->last_restart_interval = 0; - - if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ - emit_jfif_app0(cinfo); - if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ - emit_adobe_app14(cinfo); -} - - -/* - * Write frame header. - * This consists of DQT and SOFn markers. - * Note that we do not emit the SOF until we have emitted the DQT(s). - * This avoids compatibility problems with incorrect implementations that - * try to error-check the quant table numbers as soon as they see the SOF. - */ - -METHODDEF(void) -write_frame_header (j_compress_ptr cinfo) -{ - int ci, prec; - boolean is_baseline; - jpeg_component_info *compptr; - - /* Emit DQT for each quantization table. - * Note that emit_dqt() suppresses any duplicate tables. - */ - prec = 0; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prec += emit_dqt(cinfo, compptr->quant_tbl_no); - } - /* now prec is nonzero iff there are any 16-bit quant tables. */ - - /* Check for a non-baseline specification. - * Note we assume that Huffman table numbers won't be changed later. - */ - if (cinfo->arith_code || cinfo->progressive_mode || - cinfo->data_precision != 8) { - is_baseline = FALSE; - } else { - is_baseline = TRUE; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) - is_baseline = FALSE; - } - if (prec && is_baseline) { - is_baseline = FALSE; - /* If it's baseline except for quantizer size, warn the user */ - TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); - } - } - - /* Emit the proper SOF marker */ - if (cinfo->arith_code) { - emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ - } else { - if (cinfo->progressive_mode) - emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ - else if (is_baseline) - emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ - else - emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ - } -} - - -/* - * Write scan header. - * This consists of DHT or DAC markers, optional DRI, and SOS. - * Compressed data will be written following the SOS. - */ - -METHODDEF(void) -write_scan_header (j_compress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - int i; - jpeg_component_info *compptr; - - if (cinfo->arith_code) { - /* Emit arith conditioning info. We may have some duplication - * if the file has multiple scans, but it's so small it's hardly - * worth worrying about. - */ - emit_dac(cinfo); - } else { - /* Emit Huffman tables. - * Note that emit_dht() suppresses any duplicate tables. - */ - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan */ - if (cinfo->Ss == 0) { - if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - } else { - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } else { - /* Sequential mode: need both DC and AC tables */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } - } - - /* Emit DRI if required --- note that DRI value could change for each scan. - * We avoid wasting space with unnecessary DRIs, however. - */ - if (cinfo->restart_interval != marker->last_restart_interval) { - emit_dri(cinfo); - marker->last_restart_interval = cinfo->restart_interval; - } - - emit_sos(cinfo); -} - - -/* - * Write datastream trailer. - */ - -METHODDEF(void) -write_file_trailer (j_compress_ptr cinfo) -{ - emit_marker(cinfo, M_EOI); -} - - -/* - * Write an abbreviated table-specification datastream. - * This consists of SOI, DQT and DHT tables, and EOI. - * Any table that is defined and not marked sent_table = TRUE will be - * emitted. Note that all tables will be marked sent_table = TRUE at exit. - */ - -METHODDEF(void) -write_tables_only (j_compress_ptr cinfo) -{ - int i; - - emit_marker(cinfo, M_SOI); - - for (i = 0; i < NUM_QUANT_TBLS; i++) { - if (cinfo->quant_tbl_ptrs[i] != NULL) - (void) emit_dqt(cinfo, i); - } - - if (! cinfo->arith_code) { - for (i = 0; i < NUM_HUFF_TBLS; i++) { - if (cinfo->dc_huff_tbl_ptrs[i] != NULL) - emit_dht(cinfo, i, FALSE); - if (cinfo->ac_huff_tbl_ptrs[i] != NULL) - emit_dht(cinfo, i, TRUE); - } - } - - emit_marker(cinfo, M_EOI); -} - - -/* - * Initialize the marker writer module. - */ - -GLOBAL(void) -jinit_marker_writer (j_compress_ptr cinfo) -{ - my_marker_ptr marker; - - /* Create the subobject */ - marker = (my_marker_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_marker_writer)); - cinfo->marker = (struct jpeg_marker_writer *) marker; - /* Initialize method pointers */ - marker->pub.write_file_header = write_file_header; - marker->pub.write_frame_header = write_frame_header; - marker->pub.write_scan_header = write_scan_header; - marker->pub.write_file_trailer = write_file_trailer; - marker->pub.write_tables_only = write_tables_only; - marker->pub.write_marker_header = write_marker_header; - marker->pub.write_marker_byte = write_marker_byte; - /* Initialize private state */ - marker->last_restart_interval = 0; -} diff --git a/third_party/libjpeg/fpdfapi_jcmaster.c b/third_party/libjpeg/fpdfapi_jcmaster.c deleted file mode 100644 index aab4020b8796ab29492aa1780898f3ccacc45413..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcmaster.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * jcmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains master control logic for the JPEG compressor. - * These routines are concerned with parameter validation, initial setup, - * and inter-pass control (determining the number of passes and the work - * to be done in each pass). - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef enum { - main_pass, /* input data, also do first output step */ - huff_opt_pass, /* Huffman code optimization pass */ - output_pass /* data output pass */ -} c_pass_type; - -typedef struct { - struct jpeg_comp_master pub; /* public fields */ - - c_pass_type pass_type; /* the type of the current pass */ - - int pass_number; /* # of passes completed */ - int total_passes; /* total # of passes needed */ - - int scan_number; /* current index in scan_info[] */ -} my_comp_master; - -typedef my_comp_master * my_master_ptr; - - -/* - * Support routines that do various essential calculations. - */ - -LOCAL(void) -initial_setup (j_compress_ptr cinfo) -/* Do computations that are needed before master selection phase */ -{ - int ci; - jpeg_component_info *compptr; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - /* Sanity check on image dimensions */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0 || cinfo->input_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* Width of an input scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Check that number of components won't exceed internal array sizes */ - if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - - /* Compute maximum sampling factors; check factor validity */ - cinfo->max_h_samp_factor = 1; - cinfo->max_v_samp_factor = 1; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); - } - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Fill in the correct component_index value; don't rely on application */ - compptr->component_index = ci; - /* For compression, we never do DCT scaling. */ - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed (this flag isn't actually used for compression) */ - compptr->component_needed = TRUE; - } - - /* Compute number of fully interleaved MCU rows (number of times that - * main controller will call coefficient controller). - */ - cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); -} - - -#ifdef C_MULTISCAN_FILES_SUPPORTED - -LOCAL(void) -validate_script (j_compress_ptr cinfo) -/* Verify that the scan script in cinfo->scan_info[] is valid; also - * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. - */ -{ - const jpeg_scan_info * scanptr; - int scanno, ncomps, ci, coefi, thisi; - int Ss, Se, Ah, Al; - boolean component_sent[MAX_COMPONENTS]; -#ifdef C_PROGRESSIVE_SUPPORTED - int * last_bitpos_ptr; - int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; - /* -1 until that coefficient has been seen; then last Al for it */ -#endif - - if (cinfo->num_scans <= 0) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); - - /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; - * for progressive JPEG, no scan can have this. - */ - scanptr = cinfo->scan_info; - if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { -#ifdef C_PROGRESSIVE_SUPPORTED - cinfo->progressive_mode = TRUE; - last_bitpos_ptr = & last_bitpos[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (coefi = 0; coefi < DCTSIZE2; coefi++) - *last_bitpos_ptr++ = -1; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - cinfo->progressive_mode = FALSE; - for (ci = 0; ci < cinfo->num_components; ci++) - component_sent[ci] = FALSE; - } - - for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { - /* Validate component indexes */ - ncomps = scanptr->comps_in_scan; - if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); - for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (thisi < 0 || thisi >= cinfo->num_components) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - /* Components must appear in SOF order within each scan */ - if (ci > 0 && thisi <= scanptr->component_index[ci-1]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - } - /* Validate progression parameters */ - Ss = scanptr->Ss; - Se = scanptr->Se; - Ah = scanptr->Ah; - Al = scanptr->Al; - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that - * seems wrong: the upper bound ought to depend on data precision. - * Perhaps they really meant 0..N+1 for N-bit precision. - * Here we allow 0..10 for 8-bit data; Al larger than 10 results in - * out-of-range reconstructed DC values during the first DC scan, - * which might cause problems for some decoders. - */ -#if BITS_IN_JSAMPLE == 8 -#define MAX_AH_AL 10 -#else -#define MAX_AH_AL 13 -#endif - if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || - Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - if (Ss == 0) { - if (Se != 0) /* DC and AC together not OK */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } else { - if (ncomps != 1) /* AC scans must be for only one component */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } - for (ci = 0; ci < ncomps; ci++) { - last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; - if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - for (coefi = Ss; coefi <= Se; coefi++) { - if (last_bitpos_ptr[coefi] < 0) { - /* first scan of this coefficient */ - if (Ah != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } else { - /* not first scan */ - if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } - last_bitpos_ptr[coefi] = Al; - } - } -#endif - } else { - /* For sequential JPEG, all progression parameters must be these: */ - if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - /* Make sure components are not sent twice */ - for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (component_sent[thisi]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - component_sent[thisi] = TRUE; - } - } - } - - /* Now verify that everything got sent. */ - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - /* For progressive mode, we only check that at least some DC data - * got sent for each component; the spec does not require that all bits - * of all coefficients be transmitted. Would it be wiser to enforce - * transmission of all coefficient bits?? - */ - for (ci = 0; ci < cinfo->num_components; ci++) { - if (last_bitpos[ci][0] < 0) - ERREXIT(cinfo, JERR_MISSING_DATA); - } -#endif - } else { - for (ci = 0; ci < cinfo->num_components; ci++) { - if (! component_sent[ci]) - ERREXIT(cinfo, JERR_MISSING_DATA); - } - } -} - -#endif /* C_MULTISCAN_FILES_SUPPORTED */ - - -LOCAL(void) -select_scan_parameters (j_compress_ptr cinfo) -/* Set up the scan parameters for the current scan */ -{ - int ci; - -#ifdef C_MULTISCAN_FILES_SUPPORTED - if (cinfo->scan_info != NULL) { - /* Prepare for current scan --- the script is already validated */ - my_master_ptr master = (my_master_ptr) cinfo->master; - const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; - - cinfo->comps_in_scan = scanptr->comps_in_scan; - for (ci = 0; ci < scanptr->comps_in_scan; ci++) { - cinfo->cur_comp_info[ci] = - &cinfo->comp_info[scanptr->component_index[ci]]; - } - cinfo->Ss = scanptr->Ss; - cinfo->Se = scanptr->Se; - cinfo->Ah = scanptr->Ah; - cinfo->Al = scanptr->Al; - } - else -#endif - { - /* Prepare for single sequential-JPEG scan containing all components */ - if (cinfo->num_components > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPS_IN_SCAN); - cinfo->comps_in_scan = cinfo->num_components; - for (ci = 0; ci < cinfo->num_components; ci++) { - cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; - } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2-1; - cinfo->Ah = 0; - cinfo->Al = 0; - } -} - - -LOCAL(void) -per_scan_setup (j_compress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ -{ - int ci, mcublks, tmp; - jpeg_component_info *compptr; - - if (cinfo->comps_in_scan == 1) { - - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; - - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; - - } else { - - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - cinfo->blocks_in_MCU = 0; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } - - } - - /* Convert restart specified in rows to actual MCU count. */ - /* Note that count must fit in 16 bits, so we provide limiting. */ - if (cinfo->restart_in_rows > 0) { - long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; - cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); - } -} - - -/* - * Per-pass setup. - * This is called at the beginning of each pass. We determine which modules - * will be active during this pass and give them appropriate start_pass calls. - * We also set is_last_pass to indicate whether any more passes will be - * required. - */ - -METHODDEF(void) -prepare_for_pass (j_compress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - switch (master->pass_type) { - case main_pass: - /* Initial pass: will collect input data, and do either Huffman - * optimization or data output for the first scan. - */ - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - if (! cinfo->raw_data_in) { - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->downsample->start_pass) (cinfo); - (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); - } - (*cinfo->fdct->start_pass) (cinfo); - (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); - (*cinfo->coef->start_pass) (cinfo, - (master->total_passes > 1 ? - JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - if (cinfo->optimize_coding) { - /* No immediate data output; postpone writing frame/scan headers */ - master->pub.call_pass_startup = FALSE; - } else { - /* Will write frame/scan headers at first jpeg_write_scanlines call */ - master->pub.call_pass_startup = TRUE; - } - break; -#ifdef ENTROPY_OPT_SUPPORTED - case huff_opt_pass: - /* Do Huffman optimization for a scan after the first one. */ - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { - (*cinfo->entropy->start_pass) (cinfo, TRUE); - (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); - master->pub.call_pass_startup = FALSE; - break; - } - /* Special case: Huffman DC refinement scans need no Huffman table - * and therefore we can skip the optimization pass for them. - */ - master->pass_type = output_pass; - master->pass_number++; - /*FALLTHROUGH*/ -#endif - case output_pass: - /* Do a data-output pass. */ - /* We need not repeat per-scan setup if prior optimization pass did it. */ - if (! cinfo->optimize_coding) { - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - } - (*cinfo->entropy->start_pass) (cinfo, FALSE); - (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); - /* We emit frame/scan headers now */ - if (master->scan_number == 0) - (*cinfo->marker->write_frame_header) (cinfo); - (*cinfo->marker->write_scan_header) (cinfo); - master->pub.call_pass_startup = FALSE; - break; - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - } - - master->pub.is_last_pass = (master->pass_number == master->total_passes-1); - - /* Set up progress monitor's pass info if present */ - if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->total_passes; - } -} - - -/* - * Special start-of-pass hook. - * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. - * In single-pass processing, we need this hook because we don't want to - * write frame/scan headers during jpeg_start_compress; we want to let the - * application write COM markers etc. between jpeg_start_compress and the - * jpeg_write_scanlines loop. - * In multi-pass processing, this routine is not used. - */ - -METHODDEF(void) -pass_startup (j_compress_ptr cinfo) -{ - cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ - - (*cinfo->marker->write_frame_header) (cinfo); - (*cinfo->marker->write_scan_header) (cinfo); -} - - -/* - * Finish up at end of pass. - */ - -METHODDEF(void) -finish_pass_master (j_compress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - /* The entropy coder always needs an end-of-pass call, - * either to analyze statistics or to flush its output buffer. - */ - (*cinfo->entropy->finish_pass) (cinfo); - - /* Update state for next pass */ - switch (master->pass_type) { - case main_pass: - /* next pass is either output of scan 0 (after optimization) - * or output of scan 1 (if no optimization). - */ - master->pass_type = output_pass; - if (! cinfo->optimize_coding) - master->scan_number++; - break; - case huff_opt_pass: - /* next pass is always output of current scan */ - master->pass_type = output_pass; - break; - case output_pass: - /* next pass is either optimization or output of next scan */ - if (cinfo->optimize_coding) - master->pass_type = huff_opt_pass; - master->scan_number++; - break; - } - - master->pass_number++; -} - - -/* - * Initialize master compression control. - */ - -GLOBAL(void) -jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) -{ - my_master_ptr master; - - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *) master; - master->pub.prepare_for_pass = prepare_for_pass; - master->pub.pass_startup = pass_startup; - master->pub.finish_pass = finish_pass_master; - master->pub.is_last_pass = FALSE; - - /* Validate parameters, determine derived values */ - initial_setup(cinfo); - - if (cinfo->scan_info != NULL) { -#ifdef C_MULTISCAN_FILES_SUPPORTED - validate_script(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - cinfo->progressive_mode = FALSE; - cinfo->num_scans = 1; - } - - if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ - - /* Initialize my private state */ - if (transcode_only) { - /* no main pass in transcoding */ - if (cinfo->optimize_coding) - master->pass_type = huff_opt_pass; - else - master->pass_type = output_pass; - } else { - /* for normal compression, first pass is always this type: */ - master->pass_type = main_pass; - } - master->scan_number = 0; - master->pass_number = 0; - if (cinfo->optimize_coding) - master->total_passes = cinfo->num_scans * 2; - else - master->total_passes = cinfo->num_scans; -} diff --git a/third_party/libjpeg/fpdfapi_jcomapi.c b/third_party/libjpeg/fpdfapi_jcomapi.c deleted file mode 100644 index 9b1fa7568a67a7c25a599976ada93c53db665c57..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcomapi.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * jcomapi.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface routines that are used for both - * compression and decompression. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Abort processing of a JPEG compression or decompression operation, - * but don't destroy the object itself. - * - * For this, we merely clean up all the nonpermanent memory pools. - * Note that temp files (virtual arrays) are not allowed to belong to - * the permanent pool, so we will be able to close all temp files here. - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL(void) -jpeg_abort (j_common_ptr cinfo) -{ - int pool; - - /* Do nothing if called on a not-initialized or destroyed JPEG object. */ - if (cinfo->mem == NULL) - return; - - /* Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { - (*cinfo->mem->free_pool) (cinfo, pool); - } - - /* Reset overall state for possible reuse of object */ - if (cinfo->is_decompressor) { - cinfo->global_state = DSTATE_START; - /* Try to keep application from accessing now-deleted marker list. - * A bit kludgy to do it here, but this is the most central place. - */ - ((j_decompress_ptr) cinfo)->marker_list = NULL; - } else { - cinfo->global_state = CSTATE_START; - } -} - - -/* - * Destruction of a JPEG object. - * - * Everything gets deallocated except the master jpeg_compress_struct itself - * and the error manager struct. Both of these are supplied by the application - * and must be freed, if necessary, by the application. (Often they are on - * the stack and so don't need to be freed anyway.) - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - -GLOBAL(void) -jpeg_destroy (j_common_ptr cinfo) -{ - /* We need only tell the memory manager to release everything. */ - /* NB: mem pointer is NULL if memory mgr failed to initialize. */ - if (cinfo->mem != NULL) - (*cinfo->mem->self_destruct) (cinfo); - cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ - cinfo->global_state = 0; /* mark it destroyed */ -} - - -/* - * Convenience routines for allocating quantization and Huffman tables. - * (Would jutils.c be a more reasonable place to put these?) - */ - -GLOBAL(JQUANT_TBL *) -jpeg_alloc_quant_table (j_common_ptr cinfo) -{ - JQUANT_TBL *tbl; - - tbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} - - -GLOBAL(JHUFF_TBL *) -jpeg_alloc_huff_table (j_common_ptr cinfo) -{ - JHUFF_TBL *tbl; - - tbl = (JHUFF_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); - tbl->sent_table = FALSE; /* make sure this is false in any new table */ - return tbl; -} diff --git a/third_party/libjpeg/fpdfapi_jcparam.c b/third_party/libjpeg/fpdfapi_jcparam.c deleted file mode 100644 index 6fc48f53653315537ffd098d83c25c0d3db502b5..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcparam.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * jcparam.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains optional default-setting code for the JPEG compressor. - * Applications do not have to use this file, but those that don't use it - * must know a lot more about the innards of the JPEG code. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Quantization table setup routines - */ - -GLOBAL(void) -jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, boolean force_baseline) -/* Define a quantization table equal to the basic_table times - * a scale factor (given as a percentage). - * If force_baseline is TRUE, the computed quantization table entries - * are limited to 1..255 for JPEG baseline compatibility. - */ -{ - JQUANT_TBL ** qtblptr; - int i; - long temp; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); - - qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; - - if (*qtblptr == NULL) - *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); - - for (i = 0; i < DCTSIZE2; i++) { - temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; - /* limit the values to the valid range */ - if (temp <= 0L) temp = 1L; - if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ - if (force_baseline && temp > 255L) - temp = 255L; /* limit to baseline range if requested */ - (*qtblptr)->quantval[i] = (UINT16) temp; - } - - /* Initialize sent_table FALSE so table will be written to JPEG file. */ - (*qtblptr)->sent_table = FALSE; -} - - -GLOBAL(void) -jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, - boolean force_baseline) -/* Set or change the 'quality' (quantization) setting, using default tables - * and a straight percentage-scaling quality scale. In most cases it's better - * to use jpeg_set_quality (below); this entry point is provided for - * applications that insist on a linear percentage scaling. - */ -{ - /* These are the sample quantization tables given in JPEG spec section K.1. - * The spec says that the values given produce "good" quality, and - * when divided by 2, "very good" quality. - */ - static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 - }; - static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 - }; - - /* Set up two quantization tables using the specified scaling */ - jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, - scale_factor, force_baseline); - jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, - scale_factor, force_baseline); -} - - -GLOBAL(int) -jpeg_quality_scaling (int quality) -/* Convert a user-specified quality rating to a percentage scaling factor - * for an underlying quantization table, using our recommended scaling curve. - * The input 'quality' factor should be 0 (terrible) to 100 (very good). - */ -{ - /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ - if (quality <= 0) quality = 1; - if (quality > 100) quality = 100; - - /* The basic table is used as-is (scaling 100) for a quality of 50. - * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; - * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table - * to make all the table entries 1 (hence, minimum quantization loss). - * Qualities 1..50 are converted to scaling percentage 5000/Q. - */ - if (quality < 50) - quality = 5000 / quality; - else - quality = 200 - quality*2; - - return quality; -} - - -GLOBAL(void) -jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) -/* Set or change the 'quality' (quantization) setting, using default tables. - * This is the standard quality-adjusting entry point for typical user - * interfaces; only those who want detailed control over quantization tables - * would use the preceding three routines directly. - */ -{ - /* Convert user 0-100 rating to percentage scaling */ - quality = jpeg_quality_scaling(quality); - - /* Set up standard quality tables */ - jpeg_set_linear_quality(cinfo, quality, force_baseline); -} - - -/* - * Huffman table setup routines - */ - -LOCAL(void) -add_huff_table (j_compress_ptr cinfo, - JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) -/* Define a Huffman table */ -{ - int nsymbols, len; - - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - - /* Copy the number-of-symbols-of-each-code-length counts */ - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - - /* Validate the counts. We do this here mainly so we can copy the right - * number of symbols from the val[] array, without risking marching off - * the end of memory. jchuff.c will do a more thorough test later. - */ - nsymbols = 0; - for (len = 1; len <= 16; len++) - nsymbols += bits[len]; - if (nsymbols < 1 || nsymbols > 256) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - - MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); - - /* Initialize sent_table FALSE so table will be written to JPEG file. */ - (*htblptr)->sent_table = FALSE; -} - - -LOCAL(void) -std_huff_tables (j_compress_ptr cinfo) -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ -{ - static const UINT8 bits_dc_luminance[17] = - { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; - static const UINT8 val_dc_luminance[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - - static const UINT8 bits_dc_chrominance[17] = - { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; - static const UINT8 val_dc_chrominance[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - - static const UINT8 bits_ac_luminance[17] = - { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; - static const UINT8 val_ac_luminance[] = - { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }; - - static const UINT8 bits_ac_chrominance[17] = - { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; - static const UINT8 val_ac_chrominance[] = - { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }; - - add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], - bits_dc_luminance, val_dc_luminance); - add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], - bits_ac_luminance, val_ac_luminance); - add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], - bits_dc_chrominance, val_dc_chrominance); - add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], - bits_ac_chrominance, val_ac_chrominance); -} - - -/* - * Default parameter setup for compression. - * - * Applications that don't choose to use this routine must do their - * own setup of all these parameters. Alternately, you can call this - * to establish defaults and then alter parameters selectively. This - * is the recommended approach since, if we add any new parameters, - * your code will still work (they'll be set to reasonable defaults). - */ - -GLOBAL(void) -jpeg_set_defaults (j_compress_ptr cinfo) -{ - int i; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* Allocate comp_info array large enough for maximum component count. - * Array is made permanent in case application wants to compress - * multiple images at same param settings. - */ - if (cinfo->comp_info == NULL) - cinfo->comp_info = (jpeg_component_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - MAX_COMPONENTS * SIZEOF(jpeg_component_info)); - - /* Initialize everything not dependent on the color space */ - - cinfo->data_precision = BITS_IN_JSAMPLE; - /* Set up two quantization tables using default quality of 75 */ - jpeg_set_quality(cinfo, 75, TRUE); - /* Set up two Huffman tables */ - std_huff_tables(cinfo); - - /* Initialize default arithmetic coding conditioning */ - for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; - } - - /* Default is no multiple-scan output */ - cinfo->scan_info = NULL; - cinfo->num_scans = 0; - - /* Expect normal source image, not raw downsampled data */ - cinfo->raw_data_in = FALSE; - - /* Use Huffman coding, not arithmetic coding, by default */ - cinfo->arith_code = FALSE; - - /* By default, don't do extra passes to optimize entropy coding */ - cinfo->optimize_coding = FALSE; - /* The standard Huffman tables are only valid for 8-bit data precision. - * If the precision is higher, force optimization on so that usable - * tables will be computed. This test can be removed if default tables - * are supplied that are valid for the desired precision. - */ - if (cinfo->data_precision > 8) - cinfo->optimize_coding = TRUE; - - /* By default, use the simpler non-cosited sampling alignment */ - cinfo->CCIR601_sampling = FALSE; - - /* No input smoothing */ - cinfo->smoothing_factor = 0; - - /* DCT algorithm preference */ - cinfo->dct_method = JDCT_DEFAULT; - - /* No restart markers */ - cinfo->restart_interval = 0; - cinfo->restart_in_rows = 0; - - /* Fill in default JFIF marker parameters. Note that whether the marker - * will actually be written is determined by jpeg_set_colorspace. - * - * By default, the library emits JFIF version code 1.01. - * An application that wants to emit JFIF 1.02 extension markers should set - * JFIF_minor_version to 2. We could probably get away with just defaulting - * to 1.02, but there may still be some decoders in use that will complain - * about that; saying 1.01 should minimize compatibility problems. - */ - cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ - cinfo->JFIF_minor_version = 1; - cinfo->density_unit = 0; /* Pixel size is unknown by default */ - cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ - cinfo->Y_density = 1; - - /* Choose JPEG colorspace based on input space, set defaults accordingly */ - - jpeg_default_colorspace(cinfo); -} - - -/* - * Select an appropriate JPEG colorspace for in_color_space. - */ - -GLOBAL(void) -jpeg_default_colorspace (j_compress_ptr cinfo) -{ - switch (cinfo->in_color_space) { - case JCS_GRAYSCALE: - jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); - break; - case JCS_RGB: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; - case JCS_YCbCr: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; - case JCS_CMYK: - jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ - break; - case JCS_YCCK: - jpeg_set_colorspace(cinfo, JCS_YCCK); - break; - case JCS_UNKNOWN: - jpeg_set_colorspace(cinfo, JCS_UNKNOWN); - break; - default: - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - } -} - - -/* - * Set the JPEG colorspace, and choose colorspace-dependent default values. - */ - -GLOBAL(void) -jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) -{ - jpeg_component_info * compptr; - int ci; - -#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ - (compptr = &cinfo->comp_info[index], \ - compptr->component_id = (id), \ - compptr->h_samp_factor = (hsamp), \ - compptr->v_samp_factor = (vsamp), \ - compptr->quant_tbl_no = (quant), \ - compptr->dc_tbl_no = (dctbl), \ - compptr->ac_tbl_no = (actbl) ) - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* For all colorspaces, we use Q and Huff tables 0 for luminance components, - * tables 1 for chrominance components. - */ - - cinfo->jpeg_color_space = colorspace; - - cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ - cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ - - switch (colorspace) { - case JCS_GRAYSCALE: - cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ - cinfo->num_components = 1; - /* JFIF specifies component ID 1 */ - SET_COMP(0, 1, 1,1, 0, 0,0); - break; - case JCS_RGB: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ - cinfo->num_components = 3; - SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); - SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); - SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); - break; - case JCS_YCbCr: - cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ - cinfo->num_components = 3; - /* JFIF specifies component IDs 1,2,3 */ - /* We default to 2x2 subsamples of chrominance */ - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - break; - case JCS_CMYK: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ - cinfo->num_components = 4; - SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); - SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); - SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); - SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); - break; - case JCS_YCCK: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ - cinfo->num_components = 4; - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - SET_COMP(3, 4, 2,2, 0, 0,0); - break; - case JCS_UNKNOWN: - cinfo->num_components = cinfo->input_components; - if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - for (ci = 0; ci < cinfo->num_components; ci++) { - SET_COMP(ci, ci, 1,1, 0, 0,0); - } - break; - default: - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - } -} - - -#ifdef C_PROGRESSIVE_SUPPORTED - -LOCAL(jpeg_scan_info *) -fill_a_scan (jpeg_scan_info * scanptr, int ci, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for specified component */ -{ - scanptr->comps_in_scan = 1; - scanptr->component_index[0] = ci; - scanptr->Ss = Ss; - scanptr->Se = Se; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - return scanptr; -} - -LOCAL(jpeg_scan_info *) -fill_scans (jpeg_scan_info * scanptr, int ncomps, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for each component */ -{ - int ci; - - for (ci = 0; ci < ncomps; ci++) { - scanptr->comps_in_scan = 1; - scanptr->component_index[0] = ci; - scanptr->Ss = Ss; - scanptr->Se = Se; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - } - return scanptr; -} - -LOCAL(jpeg_scan_info *) -fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) -/* Support routine: generate interleaved DC scan if possible, else N scans */ -{ - int ci; - - if (ncomps <= MAX_COMPS_IN_SCAN) { - /* Single interleaved DC scan */ - scanptr->comps_in_scan = ncomps; - for (ci = 0; ci < ncomps; ci++) - scanptr->component_index[ci] = ci; - scanptr->Ss = scanptr->Se = 0; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; - } else { - /* Noninterleaved DC scan for each component */ - scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); - } - return scanptr; -} - - -/* - * Create a recommended progressive-JPEG script. - * cinfo->num_components and cinfo->jpeg_color_space must be correct. - */ - -GLOBAL(void) -jpeg_simple_progression (j_compress_ptr cinfo) -{ - int ncomps = cinfo->num_components; - int nscans; - jpeg_scan_info * scanptr; - - /* Safety check to ensure start_compress not called yet. */ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* Figure space needed for script. Calculation must match code below! */ - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ - nscans = 10; - } else { - /* All-purpose script for other color spaces. */ - if (ncomps > MAX_COMPS_IN_SCAN) - nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ - else - nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ - } - - /* Allocate space for script. - * We need to put it in the permanent pool in case the application performs - * multiple compressions without changing the settings. To avoid a memory - * leak if jpeg_simple_progression is called repeatedly for the same JPEG - * object, we try to re-use previously allocated space, and we allocate - * enough space to handle YCbCr even if initially asked for grayscale. - */ - if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { - cinfo->script_space_size = MAX(nscans, 10); - cinfo->script_space = (jpeg_scan_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - cinfo->script_space_size * SIZEOF(jpeg_scan_info)); - } - scanptr = cinfo->script_space; - cinfo->scan_info = scanptr; - cinfo->num_scans = nscans; - - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ - /* Initial DC scan */ - scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); - /* Initial AC scan: get some luma data out in a hurry */ - scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); - /* Chroma data is too small to be worth expending many scans on */ - scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); - scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); - /* Complete spectral selection for luma AC */ - scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); - /* Refine next bit of luma AC */ - scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); - /* Finish DC successive approximation */ - scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); - /* Finish AC successive approximation */ - scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); - scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); - /* Luma bottom bit comes last since it's usually largest scan */ - scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); - } else { - /* All-purpose script for other color spaces. */ - /* Successive approximation first pass */ - scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); - scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); - scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); - /* Successive approximation second pass */ - scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); - /* Successive approximation final pass */ - scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); - scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); - } -} - -#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jcphuff.c b/third_party/libjpeg/fpdfapi_jcphuff.c deleted file mode 100644 index 07f9178b01c885820889cf377c0e73d444f5dd1b..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcphuff.c +++ /dev/null @@ -1,833 +0,0 @@ -/* - * jcphuff.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines for progressive JPEG. - * - * We do not support output suspension in this module, since the library - * currently does not allow multiple-scan files to be written with output - * suspension. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jchuff.c */ - -#ifdef C_PROGRESSIVE_SUPPORTED - -/* Expanded entropy encoder object for progressive Huffman encoding. */ - -typedef struct { - struct jpeg_entropy_encoder pub; /* public fields */ - - /* Mode flag: TRUE for optimization, FALSE for actual data output */ - boolean gather_statistics; - - /* Bit-level coding status. - * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. - */ - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ - - /* Coding status for DC components */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ - - /* Coding status for AC components */ - int ac_tbl_no; /* the table number of the single component */ - unsigned int EOBRUN; /* run length of EOBs */ - unsigned int BE; /* # of buffered correction bits before MCU */ - char * bit_buffer; /* buffer for correction bits (1 per char) */ - /* packing correction bits tightly would save some space but cost time... */ - - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan). - * Since any one scan codes only DC or only AC, we only need one set - * of tables, not one for DC and one for AC. - */ - c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - /* Statistics tables for optimization; again, one set is enough */ - long * count_ptrs[NUM_HUFF_TBLS]; -} phuff_entropy_encoder; - -typedef phuff_entropy_encoder * phuff_entropy_ptr; - -/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit - * buffer can hold. Larger sizes may slightly improve compression, but - * 1000 is already well into the realm of overkill. - * The minimum safe size is 64 bits. - */ - -#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ - -/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. - * We assume that int right shift is unsigned if INT32 right shift is, - * which should be safe. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS int ishift_temp; -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); -METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); - - -/* - * Initialize for a Huffman-compressed scan using progressive JPEG. - */ - -METHODDEF(void) -start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - - entropy->cinfo = cinfo; - entropy->gather_statistics = gather_statistics; - - is_DC_band = (cinfo->Ss == 0); - - /* We assume jcmaster.c already validated the scan parameters. */ - - /* Select execution routines */ - if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_first; - else - entropy->pub.encode_mcu = encode_mcu_AC_first; - } else { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_refine; - else { - entropy->pub.encode_mcu = encode_mcu_AC_refine; - /* AC refinement needs a correction bit buffer */ - if (entropy->bit_buffer == NULL) - entropy->bit_buffer = (char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - MAX_CORR_BITS * SIZEOF(char)); - } - } - if (gather_statistics) - entropy->pub.finish_pass = finish_pass_gather_phuff; - else - entropy->pub.finish_pass = finish_pass_phuff; - - /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 - * for AC coefficients. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Initialize DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - /* Get table index */ - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; - } - if (gather_statistics) { - /* Check for invalid table index */ - /* (make_c_derived_tbl does this in the other path) */ - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->count_ptrs[tbl] == NULL) - entropy->count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); - } else { - /* Compute derived values for Huffman table */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, - & entropy->derived_tbls[tbl]); - } - } - - /* Initialize AC stuff */ - entropy->EOBRUN = 0; - entropy->BE = 0; - - /* Initialize bit buffer to empty */ - entropy->put_buffer = 0; - entropy->put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* Outputting bytes to the file. - * NB: these must be called only when actually outputting, - * that is, entropy->gather_statistics == FALSE. - */ - -/* Emit a byte */ -#define emit_byte(entropy,val) \ - { *(entropy)->next_output_byte++ = (JOCTET) (val); \ - if (--(entropy)->free_in_buffer == 0) \ - dump_buffer(entropy); } - - -LOCAL(void) -dump_buffer (phuff_entropy_ptr entropy) -/* Empty the output buffer; we do not support suspension in this module. */ -{ - struct jpeg_destination_mgr * dest = entropy->cinfo->dest; - - if (! (*dest->empty_output_buffer) (entropy->cinfo)) - ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); - /* After a successful buffer dump, must reset buffer pointers */ - entropy->next_output_byte = dest->next_output_byte; - entropy->free_in_buffer = dest->free_in_buffer; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(void) -emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) -/* Emit some bits, unless we are in gather mode */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = entropy->put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - if (entropy->gather_statistics) - return; /* do nothing if we're only getting stats */ - - put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */ - - put_bits += size; /* new number of bits in buffer */ - - put_buffer <<= 24 - put_bits; /* align incoming bits */ - - put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(entropy, c); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(entropy, 0); - } - put_buffer <<= 8; - put_bits -= 8; - } - - entropy->put_buffer = put_buffer; /* update variables */ - entropy->put_bits = put_bits; -} - - -LOCAL(void) -flush_bits (phuff_entropy_ptr entropy) -{ - emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ - entropy->put_buffer = 0; /* and reset bit-buffer to empty */ - entropy->put_bits = 0; -} - - -/* - * Emit (or just count) a Huffman symbol. - */ - -INLINE -LOCAL(void) -emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) -{ - if (entropy->gather_statistics) - entropy->count_ptrs[tbl_no][symbol]++; - else { - c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; - emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); - } -} - - -/* - * Emit bits from a correction bit buffer. - */ - -LOCAL(void) -emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, - unsigned int nbits) -{ - if (entropy->gather_statistics) - return; /* no real work */ - - while (nbits > 0) { - emit_bits(entropy, (unsigned int) (*bufstart), 1); - bufstart++; - nbits--; - } -} - - -/* - * Emit any pending EOBRUN symbol. - */ - -LOCAL(void) -emit_eobrun (phuff_entropy_ptr entropy) -{ - register int temp, nbits; - - if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ - temp = entropy->EOBRUN; - nbits = 0; - while ((temp >>= 1)) - nbits++; - /* safety check: shouldn't happen given limited correction-bit buffer */ - if (nbits > 14) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); - if (nbits) - emit_bits(entropy, entropy->EOBRUN, nbits); - - entropy->EOBRUN = 0; - - /* Emit any buffered correction bits */ - emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); - entropy->BE = 0; - } -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(void) -emit_restart (phuff_entropy_ptr entropy, int restart_num) -{ - int ci; - - emit_eobrun(entropy); - - if (! entropy->gather_statistics) { - flush_bits(entropy); - emit_byte(entropy, 0xFF); - emit_byte(entropy, JPEG_RST0 + restart_num); - } - - if (entropy->cinfo->Ss == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) - entropy->last_dc_val[ci] = 0; - } else { - /* Re-initialize all AC-related fields to 0 */ - entropy->EOBRUN = 0; - entropy->BE = 0; - } -} - - -/* - * MCU encoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, temp2; - register int nbits; - int blkn, ci; - int Al = cinfo->Al; - JBLOCKROW block; - jpeg_component_info * compptr; - ISHIFT_TEMPS - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - - /* Compute the DC value after the required point transform by Al. - * This is simply an arithmetic right shift. - */ - temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); - - /* DC differences are figured on the point-transformed values. */ - temp = temp2 - entropy->last_dc_val[ci]; - entropy->last_dc_val[ci] = temp2; - - /* Encode the DC coefficient difference per section G.1.2.1 */ - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit the Huffman-coded symbol for the number of bits */ - emit_symbol(entropy, compptr->dc_tbl_no, nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - emit_bits(entropy, (unsigned int) temp2, nbits); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, temp2; - register int nbits; - register int r, k; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ - - r = 0; /* r = run length of zeros */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { - r++; - continue; - } - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value; so the code is - * interwoven with finding the abs value (temp) and output bits (temp2). - */ - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ - temp2 = ~temp; - } else { - temp >>= Al; /* apply the point transform */ - temp2 = temp; - } - /* Watch out for case that nonzero coef is zero after point transform */ - if (temp == 0) { - r++; - continue; - } - - /* Emit any pending EOBRUN */ - if (entropy->EOBRUN > 0) - emit_eobrun(entropy); - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - emit_bits(entropy, (unsigned int) temp2, nbits); - - r = 0; /* reset zero run length */ - } - - if (r > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - if (entropy->EOBRUN == 0x7FFF) - emit_eobrun(entropy); /* force it out to avoid overflow */ - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp; - int blkn; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* We simply emit the Al'th bit of the DC coefficient value. */ - temp = (*block)[0]; - emit_bits(entropy, (unsigned int) (temp >> Al), 1); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp; - register int r, k; - int EOB; - char *BR_buffer; - unsigned int BR; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - int absvalues[DCTSIZE2]; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* It is convenient to make a pre-pass to determine the transformed - * coefficients' absolute values and the EOB position. - */ - EOB = 0; - for (k = cinfo->Ss; k <= Se; k++) { - temp = (*block)[jpeg_natural_order[k]]; - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value. - */ - if (temp < 0) - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - absvalues[k] = temp; /* save abs value for main pass */ - if (temp == 1) - EOB = k; /* EOB = index of last newly-nonzero coef */ - } - - /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ - - r = 0; /* r = run length of zeros */ - BR = 0; /* BR = count of buffered bits added now */ - BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = absvalues[k]) == 0) { - r++; - continue; - } - - /* Emit any required ZRLs, but not if they can be folded into EOB */ - while (r > 15 && k <= EOB) { - /* emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - /* Emit ZRL */ - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - /* Emit buffered correction bits that must be associated with ZRL */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - } - - /* If the coef was previously nonzero, it only needs a correction bit. - * NOTE: a straight translation of the spec's figure G.7 would suggest - * that we also need to test r > 15. But if r > 15, we can only get here - * if k > EOB, which implies that this coefficient is not 1. - */ - if (temp > 1) { - /* The correction bit is the next bit of the absolute value. */ - BR_buffer[BR++] = (char) (temp & 1); - continue; - } - - /* Emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); - - /* Emit output bit for newly-nonzero coef */ - temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; - emit_bits(entropy, (unsigned int) temp, 1); - - /* Emit buffered correction bits that must be associated with this code */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - r = 0; /* reset zero run length */ - } - - if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - entropy->BE += BR; /* concat my correction bits to older ones */ - /* We force out the EOB if we risk either: - * 1. overflow of the EOB counter; - * 2. overflow of the correction bit buffer during the next MCU. - */ - if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) - emit_eobrun(entropy); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed progressive scan. - */ - -METHODDEF(void) -finish_pass_phuff (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Flush out any buffered data */ - emit_eobrun(entropy); - flush_bits(entropy); - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather_phuff (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did[NUM_HUFF_TBLS]; - - /* Flush out buffered data (all we care about is counting the EOB symbol) */ - emit_eobrun(entropy); - - is_DC_band = (cinfo->Ss == 0); - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did, SIZEOF(did)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - tbl = compptr->ac_tbl_no; - } - if (! did[tbl]) { - if (is_DC_band) - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - else - htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); - did[tbl] = TRUE; - } - } -} - - -/* - * Module initialization routine for progressive Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_phuff_encoder (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy; - int i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_encoder)); - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; - entropy->pub.start_pass = start_pass_phuff; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - entropy->count_ptrs[i] = NULL; - } - entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ -} - -#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jcprepct.c b/third_party/libjpeg/fpdfapi_jcprepct.c deleted file mode 100644 index fa93333db20f74cbcc3b660523b7dc26688d06ef..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcprepct.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * jcprepct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the compression preprocessing controller. - * This controller manages the color conversion, downsampling, - * and edge expansion steps. - * - * Most of the complexity here is associated with buffering input rows - * as required by the downsampler. See the comments at the head of - * jcsample.c for the downsampler's needs. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* At present, jcsample.c can request context rows only for smoothing. - * In the future, we might also need context rows for CCIR601 sampling - * or other more-complex downsampling procedures. The code to support - * context rows should be compiled only if needed. - */ -#ifdef INPUT_SMOOTHING_SUPPORTED -#define CONTEXT_ROWS_SUPPORTED -#endif - - -/* - * For the simple (no-context-row) case, we just need to buffer one - * row group's worth of pixels for the downsampling step. At the bottom of - * the image, we pad to a full row group by replicating the last pixel row. - * The downsampler's last output row is then replicated if needed to pad - * out to a full iMCU row. - * - * When providing context rows, we must buffer three row groups' worth of - * pixels. Three row groups are physically allocated, but the row pointer - * arrays are made five row groups high, with the extra pointers above and - * below "wrapping around" to point to the last and first real row groups. - * This allows the downsampler to access the proper context rows. - * At the top and bottom of the image, we create dummy context rows by - * copying the first or last real pixel row. This copying could be avoided - * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the - * trouble on the compression side. - */ - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_prep_controller pub; /* public fields */ - - /* Downsampling input buffer. This buffer holds color-converted data - * until we have enough to do a downsample step. - */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; - - JDIMENSION rows_to_go; /* counts rows remaining in source image */ - int next_buf_row; /* index of next row to store in color_buf */ - -#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ - int this_row_group; /* starting row index of group to process */ - int next_buf_stop; /* downsample when we reach this index */ -#endif -} my_prep_controller; - -typedef my_prep_controller * my_prep_ptr; - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - - if (pass_mode != JBUF_PASS_THRU) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - /* Initialize total-height counter for detecting bottom of image */ - prep->rows_to_go = cinfo->image_height; - /* Mark the conversion buffer empty */ - prep->next_buf_row = 0; -#ifdef CONTEXT_ROWS_SUPPORTED - /* Preset additional state variables for context mode. - * These aren't used in non-context mode, so we needn't test which mode. - */ - prep->this_row_group = 0; - /* Set next_buf_stop to stop after two row groups have been read in. */ - prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; -#endif -} - - -/* - * Expand an image vertically from height input_rows to height output_rows, - * by duplicating the bottom row. - */ - -LOCAL(void) -expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, - int input_rows, int output_rows) -{ - register int row; - - for (row = input_rows; row < output_rows; row++) { - jcopy_sample_rows(image_data, input_rows-1, image_data, row, - 1, num_cols); - } -} - - -/* - * Process some data in the simple no-context case. - * - * Preprocessor output data is counted in "row groups". A row group - * is defined to be v_samp_factor sample rows of each component. - * Downsampling will produce this much data from each max_v_samp_factor - * input rows. - */ - -METHODDEF(void) -pre_process_data (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - int numrows, ci; - JDIMENSION inrows; - jpeg_component_info * compptr; - - while (*in_row_ctr < in_rows_avail && - *out_row_group_ctr < out_row_groups_avail) { - /* Do color conversion to fill the conversion buffer. */ - inrows = in_rows_avail - *in_row_ctr; - numrows = cinfo->max_v_samp_factor - prep->next_buf_row; - numrows = (int) MIN((JDIMENSION) numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); - *in_row_ctr += numrows; - prep->next_buf_row += numrows; - prep->rows_to_go -= numrows; - /* If at bottom of image, pad to fill the conversion buffer. */ - if (prep->rows_to_go == 0 && - prep->next_buf_row < cinfo->max_v_samp_factor) { - for (ci = 0; ci < cinfo->num_components; ci++) { - expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, cinfo->max_v_samp_factor); - } - prep->next_buf_row = cinfo->max_v_samp_factor; - } - /* If we've filled the conversion buffer, empty it. */ - if (prep->next_buf_row == cinfo->max_v_samp_factor) { - (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, (JDIMENSION) 0, - output_buf, *out_row_group_ctr); - prep->next_buf_row = 0; - (*out_row_group_ctr)++; - } - /* If at bottom of image, pad the output to a full iMCU height. - * Note we assume the caller is providing a one-iMCU-height output buffer! - */ - if (prep->rows_to_go == 0 && - *out_row_group_ctr < out_row_groups_avail) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - expand_bottom_edge(output_buf[ci], - compptr->width_in_blocks * DCTSIZE, - (int) (*out_row_group_ctr * compptr->v_samp_factor), - (int) (out_row_groups_avail * compptr->v_samp_factor)); - } - *out_row_group_ctr = out_row_groups_avail; - break; /* can exit outer loop without test */ - } - } -} - - -#ifdef CONTEXT_ROWS_SUPPORTED - -/* - * Process some data in the context case. - */ - -METHODDEF(void) -pre_process_context (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - int numrows, ci; - int buf_height = cinfo->max_v_samp_factor * 3; - JDIMENSION inrows; - - while (*out_row_group_ctr < out_row_groups_avail) { - if (*in_row_ctr < in_rows_avail) { - /* Do color conversion to fill the conversion buffer. */ - inrows = in_rows_avail - *in_row_ctr; - numrows = prep->next_buf_stop - prep->next_buf_row; - numrows = (int) MIN((JDIMENSION) numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); - /* Pad at top of image, if first time through */ - if (prep->rows_to_go == cinfo->image_height) { - for (ci = 0; ci < cinfo->num_components; ci++) { - int row; - for (row = 1; row <= cinfo->max_v_samp_factor; row++) { - jcopy_sample_rows(prep->color_buf[ci], 0, - prep->color_buf[ci], -row, - 1, cinfo->image_width); - } - } - } - *in_row_ctr += numrows; - prep->next_buf_row += numrows; - prep->rows_to_go -= numrows; - } else { - /* Return for more data, unless we are at the bottom of the image. */ - if (prep->rows_to_go != 0) - break; - /* When at bottom of image, pad to fill the conversion buffer. */ - if (prep->next_buf_row < prep->next_buf_stop) { - for (ci = 0; ci < cinfo->num_components; ci++) { - expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, prep->next_buf_stop); - } - prep->next_buf_row = prep->next_buf_stop; - } - } - /* If we've gotten enough data, downsample a row group. */ - if (prep->next_buf_row == prep->next_buf_stop) { - (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, - (JDIMENSION) prep->this_row_group, - output_buf, *out_row_group_ctr); - (*out_row_group_ctr)++; - /* Advance pointers with wraparound as necessary. */ - prep->this_row_group += cinfo->max_v_samp_factor; - if (prep->this_row_group >= buf_height) - prep->this_row_group = 0; - if (prep->next_buf_row >= buf_height) - prep->next_buf_row = 0; - prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; - } - } -} - - -/* - * Create the wrapped-around downsampling input buffer needed for context mode. - */ - -LOCAL(void) -create_context_buffer (j_compress_ptr cinfo) -{ - my_prep_ptr prep = (my_prep_ptr) cinfo->prep; - int rgroup_height = cinfo->max_v_samp_factor; - int ci, i; - jpeg_component_info * compptr; - JSAMPARRAY true_buffer, fake_buffer; - - /* Grab enough space for fake row pointers for all the components; - * we need five row groups' worth of pointers for each component. - */ - fake_buffer = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (cinfo->num_components * 5 * rgroup_height) * - SIZEOF(JSAMPROW)); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate the actual buffer space (3 row groups) for this component. - * We make the buffer wide enough to allow the downsampler to edge-expand - * horizontally within the buffer, if it so chooses. - */ - true_buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), - (JDIMENSION) (3 * rgroup_height)); - /* Copy true buffer row pointers into the middle of the fake row array */ - MEMCOPY(fake_buffer + rgroup_height, true_buffer, - 3 * rgroup_height * SIZEOF(JSAMPROW)); - /* Fill in the above and below wraparound pointers */ - for (i = 0; i < rgroup_height; i++) { - fake_buffer[i] = true_buffer[2 * rgroup_height + i]; - fake_buffer[4 * rgroup_height + i] = true_buffer[i]; - } - prep->color_buf[ci] = fake_buffer + rgroup_height; - fake_buffer += 5 * rgroup_height; /* point to space for next component */ - } -} - -#endif /* CONTEXT_ROWS_SUPPORTED */ - - -/* - * Initialize preprocessing controller. - */ - -GLOBAL(void) -jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) -{ - my_prep_ptr prep; - int ci; - jpeg_component_info * compptr; - - if (need_full_buffer) /* safety check */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - prep = (my_prep_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_prep_controller)); - cinfo->prep = (struct jpeg_c_prep_controller *) prep; - prep->pub.start_pass = start_pass_prep; - - /* Allocate the color conversion buffer. - * We make the buffer wide enough to allow the downsampler to edge-expand - * horizontally within the buffer, if it so chooses. - */ - if (cinfo->downsample->need_context_rows) { - /* Set up to provide context rows */ -#ifdef CONTEXT_ROWS_SUPPORTED - prep->pub.pre_process_data = pre_process_context; - create_context_buffer(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - /* No context, just make it tall enough for one row group */ - prep->pub.pre_process_data = pre_process_data; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } - } -} diff --git a/third_party/libjpeg/fpdfapi_jcsample.c b/third_party/libjpeg/fpdfapi_jcsample.c deleted file mode 100644 index 212ec8757c4ca865eba34a80530d42e8d371dec7..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jcsample.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * jcsample.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains downsampling routines. - * - * Downsampling input data is counted in "row groups". A row group - * is defined to be max_v_samp_factor pixel rows of each component, - * from which the downsampler produces v_samp_factor sample rows. - * A single row group is processed in each call to the downsampler module. - * - * The downsampler is responsible for edge-expansion of its output data - * to fill an integral number of DCT blocks horizontally. The source buffer - * may be modified if it is helpful for this purpose (the source buffer is - * allocated wide enough to correspond to the desired output width). - * The caller (the prep controller) is responsible for vertical padding. - * - * The downsampler may request "context rows" by setting need_context_rows - * during startup. In this case, the input arrays will contain at least - * one row group's worth of pixels above and below the passed-in data; - * the caller will create dummy rows at image top and bottom by replicating - * the first or last real pixel row. - * - * An excellent reference for image resampling is - * Digital Image Warping, George Wolberg, 1990. - * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. - * - * The downsampling algorithm used here is a simple average of the source - * pixels covered by the output pixel. The hi-falutin sampling literature - * refers to this as a "box filter". In general the characteristics of a box - * filter are not very good, but for the specific cases we normally use (1:1 - * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not - * nearly so bad. If you intend to use other sampling ratios, you'd be well - * advised to improve this code. - * - * A simple input-smoothing capability is provided. This is mainly intended - * for cleaning up color-dithered GIF input files (if you find it inadequate, - * we suggest using an external filtering program such as pnmconvol). When - * enabled, each input pixel P is replaced by a weighted sum of itself and its - * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, - * where SF = (smoothing_factor / 1024). - * Currently, smoothing is only supported for 2h2v sampling factors. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Pointer to routine to downsample a single component */ -typedef JMETHOD(void, downsample1_ptr, - (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data)); - -/* Private subobject */ - -typedef struct { - struct jpeg_downsampler pub; /* public fields */ - - /* Downsampling method pointers, one per component */ - downsample1_ptr methods[MAX_COMPONENTS]; -} my_downsampler; - -typedef my_downsampler * my_downsample_ptr; - - -/* - * Initialize for a downsampling pass. - */ - -METHODDEF(void) -start_pass_downsample (j_compress_ptr cinfo) -{ - /* no work for now */ -} - - -/* - * Expand a component horizontally from width input_cols to width output_cols, - * by duplicating the rightmost samples. - */ - -LOCAL(void) -expand_right_edge (JSAMPARRAY image_data, int num_rows, - JDIMENSION input_cols, JDIMENSION output_cols) -{ - register JSAMPROW ptr; - register JSAMPLE pixval; - register int count; - int row; - int numcols = (int) (output_cols - input_cols); - - if (numcols > 0) { - for (row = 0; row < num_rows; row++) { - ptr = image_data[row] + input_cols; - pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ - for (count = numcols; count > 0; count--) - *ptr++ = pixval; - } - } -} - - -/* - * Do downsampling for a whole row group (all components). - * - * In this version we simply downsample each component independently. - */ - -METHODDEF(void) -sep_downsample (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) -{ - my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; - int ci; - jpeg_component_info * compptr; - JSAMPARRAY in_ptr, out_ptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - in_ptr = input_buf[ci] + in_row_index; - out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); - (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); - } -} - - -/* - * Downsample pixel values of a single component. - * One row group is processed per call. - * This version handles arbitrary integral sampling ratios, without smoothing. - * Note that this version is not actually used for customary sampling ratios. - */ - -METHODDEF(void) -int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; - JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - JSAMPROW inptr, outptr; - INT32 outvalue; - - h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; - v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; - numpix = h_expand * v_expand; - numpix2 = numpix/2; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * h_expand); - - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - for (outcol = 0, outcol_h = 0; outcol < output_cols; - outcol++, outcol_h += h_expand) { - outvalue = 0; - for (v = 0; v < v_expand; v++) { - inptr = input_data[inrow+v] + outcol_h; - for (h = 0; h < h_expand; h++) { - outvalue += (INT32) GETJSAMPLE(*inptr++); - } - } - *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); - } - inrow += v_expand; - } -} - - -/* - * Downsample pixel values of a single component. - * This version handles the special case of a full-size component, - * without smoothing. - */ - -METHODDEF(void) -fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - /* Copy the data */ - jcopy_sample_rows(input_data, 0, output_data, 0, - cinfo->max_v_samp_factor, cinfo->image_width); - /* Edge-expand */ - expand_right_edge(output_data, cinfo->max_v_samp_factor, - cinfo->image_width, compptr->width_in_blocks * DCTSIZE); -} - - -/* - * Downsample pixel values of a single component. - * This version handles the common case of 2:1 horizontal and 1:1 vertical, - * without smoothing. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF(void) -h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int outrow; - JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, outptr; - register int bias; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); - - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - bias = 0; /* bias = 0,1,0,1,... for successive samples */ - for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) - + bias) >> 1); - bias ^= 1; /* 0=>1, 1=>0 */ - inptr += 2; - } - } -} - - -/* - * Downsample pixel values of a single component. - * This version handles the standard case of 2:1 horizontal and 2:1 vertical, - * without smoothing. - */ - -METHODDEF(void) -h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int inrow, outrow; - JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, outptr; - register int bias; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); - - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr0 = input_data[inrow]; - inptr1 = input_data[inrow+1]; - bias = 1; /* bias = 1,2,1,2,... for successive samples */ - for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) - + bias) >> 2); - bias ^= 3; /* 1=>2, 2=>1 */ - inptr0 += 2; inptr1 += 2; - } - inrow += 2; - } -} - - -#ifdef INPUT_SMOOTHING_SUPPORTED - -/* - * Downsample pixel values of a single component. - * This version handles the standard case of 2:1 horizontal and 2:1 vertical, - * with smoothing. One row of context is required. - */ - -METHODDEF(void) -h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int inrow, outrow; - JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; - INT32 membersum, neighsum, memberscale, neighscale; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols * 2); - - /* We don't bother to form the individual "smoothed" input pixel values; - * we can directly compute the output which is the average of the four - * smoothed values. Each of the four member pixels contributes a fraction - * (1-8*SF) to its own smoothed image and a fraction SF to each of the three - * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final - * output. The four corner-adjacent neighbor pixels contribute a fraction - * SF to just one smoothed pixel, or SF/4 to the final output; while the - * eight edge-adjacent neighbors contribute SF to each of two smoothed - * pixels, or SF/2 overall. In order to use integer arithmetic, these - * factors are scaled by 2^16 = 65536. - * Also recall that SF = smoothing_factor / 1024. - */ - - memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ - neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ - - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr0 = input_data[inrow]; - inptr1 = input_data[inrow+1]; - above_ptr = input_data[inrow-1]; - below_ptr = input_data[inrow+2]; - - /* Special case for first column: pretend column -1 is same as column 0 */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); - neighsum += neighsum; - neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; - - for (colctr = output_cols - 2; colctr > 0; colctr--) { - /* sum of pixels directly mapped to this output element */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - /* sum of edge-neighbor pixels */ - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); - /* The edge-neighbors count twice as much as corner-neighbors */ - neighsum += neighsum; - /* Add in the corner-neighbors */ - neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + - GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); - /* form final output scaled up by 2^16 */ - membersum = membersum * memberscale + neighsum * neighscale; - /* round, descale and output it */ - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; - } - - /* Special case for last column */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); - neighsum += neighsum; - neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); - membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE) ((membersum + 32768) >> 16); - - inrow += 2; - } -} - - -/* - * Downsample pixel values of a single component. - * This version handles the special case of a full-size component, - * with smoothing. One row of context is required. - */ - -METHODDEF(void) -fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) -{ - int outrow; - JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; - register JSAMPROW inptr, above_ptr, below_ptr, outptr; - INT32 membersum, neighsum, memberscale, neighscale; - int colsum, lastcolsum, nextcolsum; - - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ - expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols); - - /* Each of the eight neighbor pixels contributes a fraction SF to the - * smoothed pixel, while the main pixel contributes (1-8*SF). In order - * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. - * Also recall that SF = smoothing_factor / 1024. - */ - - memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ - neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ - - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - above_ptr = input_data[outrow-1]; - below_ptr = input_data[outrow+1]; - - /* Special case for first column */ - colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + - GETJSAMPLE(*inptr); - membersum = GETJSAMPLE(*inptr++); - nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + - GETJSAMPLE(*inptr); - neighsum = colsum + (colsum - membersum) + nextcolsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - lastcolsum = colsum; colsum = nextcolsum; - - for (colctr = output_cols - 2; colctr > 0; colctr--) { - membersum = GETJSAMPLE(*inptr++); - above_ptr++; below_ptr++; - nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + - GETJSAMPLE(*inptr); - neighsum = lastcolsum + (colsum - membersum) + nextcolsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - lastcolsum = colsum; colsum = nextcolsum; - } - - /* Special case for last column */ - membersum = GETJSAMPLE(*inptr); - neighsum = lastcolsum + (colsum - membersum) + colsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE) ((membersum + 32768) >> 16); - - } -} - -#endif /* INPUT_SMOOTHING_SUPPORTED */ - - -/* - * Module initialization routine for downsampling. - * Note that we must select a routine for each component. - */ - -GLOBAL(void) -jinit_downsampler (j_compress_ptr cinfo) -{ - my_downsample_ptr downsample; - int ci; - jpeg_component_info * compptr; - boolean smoothok = TRUE; - - downsample = (my_downsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_downsampler)); - cinfo->downsample = (struct jpeg_downsampler *) downsample; - downsample->pub.start_pass = start_pass_downsample; - downsample->pub.downsample = sep_downsample; - downsample->pub.need_context_rows = FALSE; - - if (cinfo->CCIR601_sampling) - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - - /* Verify we can handle the sampling factors, and set up method pointers */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { -#ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor) { - downsample->methods[ci] = fullsize_smooth_downsample; - downsample->pub.need_context_rows = TRUE; - } else -#endif - downsample->methods[ci] = fullsize_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { - smoothok = FALSE; - downsample->methods[ci] = h2v1_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { -#ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor) { - downsample->methods[ci] = h2v2_smooth_downsample; - downsample->pub.need_context_rows = TRUE; - } else -#endif - downsample->methods[ci] = h2v2_downsample; - } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && - (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { - smoothok = FALSE; - downsample->methods[ci] = int_downsample; - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - } - -#ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor && !smoothok) - TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); -#endif -} diff --git a/third_party/libjpeg/fpdfapi_jctrans.c b/third_party/libjpeg/fpdfapi_jctrans.c deleted file mode 100644 index 0e6d70769df543d84cd5a2bec154443648e5c61a..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jctrans.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * jctrans.c - * - * Copyright (C) 1995-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains library routines for transcoding compression, - * that is, writing raw DCT coefficient arrays to an output JPEG file. - * The routines in jcapimin.c will also be needed by a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(void) transencode_master_selection - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); -LOCAL(void) transencode_coef_controller - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); - - -/* - * Compression initialization for writing raw-coefficient data. - * Before calling this, all parameters and a data destination must be set up. - * Call jpeg_finish_compress() to actually write the data. - * - * The number of passed virtual arrays must match cinfo->num_components. - * Note that the virtual arrays need not be filled or even realized at - * the time write_coefficients is called; indeed, if the virtual arrays - * were requested from this compression object's memory manager, they - * typically will be realized during this routine and filled afterwards. - */ - -GLOBAL(void) -jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) -{ - if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Mark all tables to be written */ - jpeg_suppress_tables(cinfo, FALSE); - /* (Re)initialize error mgr and destination modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->dest->init_destination) (cinfo); - /* Perform master selection of active modules */ - transencode_master_selection(cinfo, coef_arrays); - /* Wait for jpeg_finish_compress() call */ - cinfo->next_scanline = 0; /* so jpeg_write_marker works */ - cinfo->global_state = CSTATE_WRCOEFS; -} - - -/* - * Initialize the compression object with default parameters, - * then copy from the source object all parameters needed for lossless - * transcoding. Parameters that can be varied without loss (such as - * scan script and Huffman optimization) are left in their default states. - */ - -GLOBAL(void) -jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, - j_compress_ptr dstinfo) -{ - JQUANT_TBL ** qtblptr; - jpeg_component_info *incomp, *outcomp; - JQUANT_TBL *c_quant, *slot_quant; - int tblno, ci, coefi; - - /* Safety check to ensure start_compress not called yet. */ - if (dstinfo->global_state != CSTATE_START) - ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); - /* Copy fundamental image dimensions */ - dstinfo->image_width = srcinfo->image_width; - dstinfo->image_height = srcinfo->image_height; - dstinfo->input_components = srcinfo->num_components; - dstinfo->in_color_space = srcinfo->jpeg_color_space; - /* Initialize all parameters to default values */ - jpeg_set_defaults(dstinfo); - /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. - * Fix it to get the right header markers for the image colorspace. - */ - jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); - dstinfo->data_precision = srcinfo->data_precision; - dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; - /* Copy the source's quantization tables. */ - for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { - if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { - qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; - if (*qtblptr == NULL) - *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); - MEMCOPY((*qtblptr)->quantval, - srcinfo->quant_tbl_ptrs[tblno]->quantval, - SIZEOF((*qtblptr)->quantval)); - (*qtblptr)->sent_table = FALSE; - } - } - /* Copy the source's per-component info. - * Note we assume jpeg_set_defaults has allocated the dest comp_info array. - */ - dstinfo->num_components = srcinfo->num_components; - if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) - ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, - MAX_COMPONENTS); - for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; - ci < dstinfo->num_components; ci++, incomp++, outcomp++) { - outcomp->component_id = incomp->component_id; - outcomp->h_samp_factor = incomp->h_samp_factor; - outcomp->v_samp_factor = incomp->v_samp_factor; - outcomp->quant_tbl_no = incomp->quant_tbl_no; - /* Make sure saved quantization table for component matches the qtable - * slot. If not, the input file re-used this qtable slot. - * IJG encoder currently cannot duplicate this. - */ - tblno = outcomp->quant_tbl_no; - if (tblno < 0 || tblno >= NUM_QUANT_TBLS || - srcinfo->quant_tbl_ptrs[tblno] == NULL) - ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); - slot_quant = srcinfo->quant_tbl_ptrs[tblno]; - c_quant = incomp->quant_table; - if (c_quant != NULL) { - for (coefi = 0; coefi < DCTSIZE2; coefi++) { - if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) - ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); - } - } - /* Note: we do not copy the source's Huffman table assignments; - * instead we rely on jpeg_set_colorspace to have made a suitable choice. - */ - } - /* Also copy JFIF version and resolution information, if available. - * Strictly speaking this isn't "critical" info, but it's nearly - * always appropriate to copy it if available. In particular, - * if the application chooses to copy JFIF 1.02 extension markers from - * the source file, we need to copy the version to make sure we don't - * emit a file that has 1.02 extensions but a claimed version of 1.01. - * We will *not*, however, copy version info from mislabeled "2.01" files. - */ - if (srcinfo->saw_JFIF_marker) { - if (srcinfo->JFIF_major_version == 1) { - dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; - dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; - } - dstinfo->density_unit = srcinfo->density_unit; - dstinfo->X_density = srcinfo->X_density; - dstinfo->Y_density = srcinfo->Y_density; - } -} - - -/* - * Master selection of compression modules for transcoding. - * This substitutes for jcinit.c's initialization of the full compressor. - */ - -LOCAL(void) -transencode_master_selection (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) -{ - /* Although we don't actually use input_components for transcoding, - * jcmaster.c's initial_setup will complain if input_components is 0. - */ - cinfo->input_components = 1; - /* Initialize master control (includes parameter checking/processing) */ - jinit_c_master_control(cinfo, TRUE /* transcode only */); - - /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); - } - - /* We need a special coefficient buffer controller. */ - transencode_coef_controller(cinfo, coef_arrays); - - jinit_marker_writer(cinfo); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Write the datastream header (SOI, JFIF) immediately. - * Frame and scan headers are postponed till later. - * This lets application insert special markers after the SOI. - */ - (*cinfo->marker->write_file_header) (cinfo); -} - - -/* - * The rest of this file is a special implementation of the coefficient - * buffer controller. This is similar to jccoefct.c, but it handles only - * output from presupplied virtual arrays. Furthermore, we generate any - * dummy padding blocks on-the-fly rather than expecting them to be present - * in the arrays. - */ - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_c_coef_controller pub; /* public fields */ - - JDIMENSION iMCU_row_num; /* iMCU row # within image */ - JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* Virtual block array for each component. */ - jvirt_barray_ptr * whole_image; - - /* Workspace for constructing dummy blocks at right/bottom edges. */ - JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - - -LOCAL(void) -start_iMCU_row (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->mcu_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - if (pass_mode != JBUF_CRANK_DEST) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - coef->iMCU_row_num = 0; - start_iMCU_row(cinfo); -} - - -/* - * Process some data. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the entropy coder. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - -METHODDEF(boolean) -compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, ci, xindex, yindex, yoffset, blockcnt; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (coef->iMCU_row_num < last_iMCU_row || - yindex+yoffset < compptr->last_row_height) { - /* Fill in pointers to real blocks in this row */ - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < blockcnt; xindex++) - MCU_buffer[blkn++] = buffer_ptr++; - } else { - /* At bottom of image, need a whole row of dummy blocks */ - xindex = 0; - } - /* Fill in any dummy blocks needed in this row. - * Dummy blocks are filled in the same way as in jccoefct.c: - * all zeroes in the AC entries, DC entries equal to previous - * block's DC value. The init routine has already zeroed the - * AC entries, so we need only set the DC entries correctly. - */ - for (; xindex < compptr->MCU_width; xindex++) { - MCU_buffer[blkn] = coef->dummy_buffer[blkn]; - MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; - blkn++; - } - } - } - /* Try to write the MCU. */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - coef->iMCU_row_num++; - start_iMCU_row(cinfo); - return TRUE; -} - - -/* - * Initialize coefficient buffer controller. - * - * Each passed coefficient array must be the right size for that - * coefficient: width_in_blocks wide and height_in_blocks high, - * with unitheight at least v_samp_factor. - */ - -LOCAL(void) -transencode_coef_controller (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) -{ - my_coef_ptr coef; - JBLOCKROW buffer; - int i; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_c_coef_controller *) coef; - coef->pub.start_pass = start_pass_coef; - coef->pub.compress_data = compress_output; - - /* Save pointer to virtual arrays */ - coef->whole_image = coef_arrays; - - /* Allocate and pre-zero space for dummy DCT blocks. */ - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { - coef->dummy_buffer[i] = buffer + i; - } -} diff --git a/third_party/libjpeg/fpdfapi_jdapimin.c b/third_party/libjpeg/fpdfapi_jdapimin.c deleted file mode 100644 index cadb59fce3aa1cc239e86c592774cc500e109613..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdapimin.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * jdapimin.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "minimum" API routines that may be - * needed in either the normal full-decompression case or the - * transcoding-only case. - * - * Most of the routines intended to be called directly by an application - * are in this file or in jdapistd.c. But also see jcomapi.c for routines - * shared by compression and decompression, and jdtrans.c for the transcoding - * case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * Initialization of a JPEG decompression object. - * The error manager must already be set up (in case memory manager fails). - */ - -GLOBAL(void) -jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) -{ - int i; - - /* Guard against version mismatches between library and caller. */ - cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ - if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); - if (structsize != SIZEOF(struct jpeg_decompress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); - - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ - { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; - } - cinfo->is_decompressor = TRUE; - - /* Initialize a memory manager instance for this object */ - jinit_memory_mgr((j_common_ptr) cinfo); - - /* Zero out pointers to permanent structures. */ - cinfo->progress = NULL; - cinfo->src = NULL; - - for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; - - for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; - } - - /* Initialize marker processor so application can override methods - * for COM, APPn markers before calling jpeg_read_header. - */ - cinfo->marker_list = NULL; - jinit_marker_reader(cinfo); - - /* And initialize the overall input controller. */ - jinit_input_controller(cinfo); - - /* OK, I'm ready */ - cinfo->global_state = DSTATE_START; -} - - -/* - * Destruction of a JPEG decompression object - */ - -GLOBAL(void) -jpeg_destroy_decompress (j_decompress_ptr cinfo) -{ - jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Abort processing of a JPEG decompression operation, - * but don't destroy the object itself. - */ - -GLOBAL(void) -jpeg_abort_decompress (j_decompress_ptr cinfo) -{ - jpeg_abort((j_common_ptr) cinfo); /* use common routine */ -} - - -/* - * Set default decompression parameters. - */ - -LOCAL(void) -default_decompress_parms (j_decompress_ptr cinfo) -{ - /* Guess the input colorspace, and set output colorspace accordingly. */ - /* (Wish JPEG committee had provided a real way to specify this...) */ - /* Note application may override our guesses. */ - switch (cinfo->num_components) { - case 1: - cinfo->jpeg_color_space = JCS_GRAYSCALE; - cinfo->out_color_space = JCS_GRAYSCALE; - break; - - case 3: - if (cinfo->saw_JFIF_marker) { - cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ - } else if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_RGB; - break; - case 1: - cinfo->jpeg_color_space = JCS_YCbCr; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - break; - } - } else { - /* Saw no special markers, try to guess from the component IDs */ - int cid0 = cinfo->comp_info[0].component_id; - int cid1 = cinfo->comp_info[1].component_id; - int cid2 = cinfo->comp_info[2].component_id; - - if (cid0 == 1 && cid1 == 2 && cid2 == 3) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) - cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else { - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } - } - /* Always guess RGB is proper output colorspace. */ - cinfo->out_color_space = JCS_RGB; - break; - - case 4: - if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: - cinfo->jpeg_color_space = JCS_CMYK; - break; - case 2: - cinfo->jpeg_color_space = JCS_YCCK; - break; - default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ - break; - } - } else { - /* No special markers, assume straight CMYK. */ - cinfo->jpeg_color_space = JCS_CMYK; - } - cinfo->out_color_space = JCS_CMYK; - break; - - default: - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->out_color_space = JCS_UNKNOWN; - break; - } - - /* Set defaults for other decompression parameters. */ - cinfo->scale_num = 1; /* 1:1 scaling */ - cinfo->scale_denom = 1; - cinfo->output_gamma = 1.0; - cinfo->buffered_image = FALSE; - cinfo->raw_data_out = FALSE; - cinfo->dct_method = JDCT_DEFAULT; - cinfo->do_fancy_upsampling = TRUE; - cinfo->do_block_smoothing = TRUE; - cinfo->quantize_colors = FALSE; - /* We set these in case application only sets quantize_colors. */ - cinfo->dither_mode = JDITHER_FS; -#ifdef QUANT_2PASS_SUPPORTED - cinfo->two_pass_quantize = TRUE; -#else - cinfo->two_pass_quantize = FALSE; -#endif - cinfo->desired_number_of_colors = 256; - cinfo->colormap = NULL; - /* Initialize for no mode change in buffered-image mode. */ - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; -} - - -/* - * Decompression startup: read start of JPEG datastream to see what's there. - * Need only initialize JPEG object and supply a data source before calling. - * - * This routine will read as far as the first SOS marker (ie, actual start of - * compressed data), and will save all tables and parameters in the JPEG - * object. It will also initialize the decompression parameters to default - * values, and finally return JPEG_HEADER_OK. On return, the application may - * adjust the decompression parameters and then call jpeg_start_decompress. - * (Or, if the application only wanted to determine the image parameters, - * the data need not be decompressed. In that case, call jpeg_abort or - * jpeg_destroy to release any temporary space.) - * If an abbreviated (tables only) datastream is presented, the routine will - * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then - * re-use the JPEG object to read the abbreviated image datastream(s). - * It is unnecessary (but OK) to call jpeg_abort in this case. - * The JPEG_SUSPENDED return code only occurs if the data source module - * requests suspension of the decompressor. In this case the application - * should load more source data and then re-call jpeg_read_header to resume - * processing. - * If a non-suspending data source is used and require_image is TRUE, then the - * return code need not be inspected since only JPEG_HEADER_OK is possible. - * - * This routine is now just a front end to jpeg_consume_input, with some - * extra error checking. - */ - -GLOBAL(int) -jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) -{ - int retcode; - - if (cinfo->global_state != DSTATE_START && - cinfo->global_state != DSTATE_INHEADER) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - retcode = jpeg_consume_input(cinfo); - - switch (retcode) { - case JPEG_REACHED_SOS: - retcode = JPEG_HEADER_OK; - break; - case JPEG_REACHED_EOI: - if (require_image) /* Complain if application wanted an image */ - ERREXIT(cinfo, JERR_NO_IMAGE); - /* Reset to start state; it would be safer to require the application to - * call jpeg_abort, but we can't change it now for compatibility reasons. - * A side effect is to free any temporary memory (there shouldn't be any). - */ - jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ - retcode = JPEG_HEADER_TABLES_ONLY; - break; - case JPEG_SUSPENDED: - /* no work */ - break; - } - - return retcode; -} - - -/* - * Consume data in advance of what the decompressor requires. - * This can be called at any time once the decompressor object has - * been created and a data source has been set up. - * - * This routine is essentially a state machine that handles a couple - * of critical state-transition actions, namely initial setup and - * transition from header scanning to ready-for-start_decompress. - * All the actual input is done via the input controller's consume_input - * method. - */ - -GLOBAL(int) -jpeg_consume_input (j_decompress_ptr cinfo) -{ - int retcode = JPEG_SUSPENDED; - - /* NB: every possible DSTATE value should be listed in this switch */ - switch (cinfo->global_state) { - case DSTATE_START: - /* Start-of-datastream actions: reset appropriate modules */ - (*cinfo->inputctl->reset_input_controller) (cinfo); - /* Initialize application's data source module */ - (*cinfo->src->init_source) (cinfo); - cinfo->global_state = DSTATE_INHEADER; - /*FALLTHROUGH*/ - case DSTATE_INHEADER: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ - /* Set up default parameters based on header data */ - default_decompress_parms(cinfo); - /* Set global state: ready for start_decompress */ - cinfo->global_state = DSTATE_READY; - } - break; - case DSTATE_READY: - /* Can't advance past first SOS until start_decompress is called */ - retcode = JPEG_REACHED_SOS; - break; - case DSTATE_PRELOAD: - case DSTATE_PRESCAN: - case DSTATE_SCANNING: - case DSTATE_RAW_OK: - case DSTATE_BUFIMAGE: - case DSTATE_BUFPOST: - case DSTATE_STOPPING: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - break; - default: - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - return retcode; -} - - -/* - * Have we finished reading the input file? - */ - -GLOBAL(boolean) -jpeg_input_complete (j_decompress_ptr cinfo) -{ - /* Check for valid jpeg object */ - if (cinfo->global_state < DSTATE_START || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->eoi_reached; -} - - -/* - * Is there more than one scan? - */ - -GLOBAL(boolean) -jpeg_has_multiple_scans (j_decompress_ptr cinfo) -{ - /* Only valid after jpeg_read_header completes */ - if (cinfo->global_state < DSTATE_READY || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return cinfo->inputctl->has_multiple_scans; -} - - -/* - * Finish JPEG decompression. - * - * This will normally just verify the file trailer and release temp storage. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_finish_decompress (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { - /* Terminate final pass of non-buffered mode */ - if (cinfo->output_scanline < cinfo->output_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state == DSTATE_BUFIMAGE) { - /* Finishing after a buffered-image operation */ - cinfo->global_state = DSTATE_STOPPING; - } else if (cinfo->global_state != DSTATE_STOPPING) { - /* STOPPING = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read until EOI */ - while (! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - /* Do final cleanup */ - (*cinfo->src->term_source) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ - jpeg_abort((j_common_ptr) cinfo); - return TRUE; -} diff --git a/third_party/libjpeg/fpdfapi_jdapistd.c b/third_party/libjpeg/fpdfapi_jdapistd.c deleted file mode 100644 index 39bbb969bf9d34cbf15476545b6ce7901b19944d..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdapistd.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * jdapistd.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains application interface code for the decompression half - * of the JPEG library. These are the "standard" API routines that are - * used in the normal full-decompression case. They are not used by a - * transcoding-only application. Note that if an application links in - * jpeg_start_decompress, it will end up linking in the entire decompressor. - * We thus must separate this file from jdapimin.c to avoid linking the - * whole decompression library into a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); - - -/* - * Decompression initialization. - * jpeg_read_header must be completed before calling this. - * - * If a multipass operating mode was selected, this will do all but the - * last pass, and thus may take a great deal of time. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_start_decompress (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize master control, select active modules */ - jinit_master_decompress(cinfo); - if (cinfo->buffered_image) { - /* No more work here; expecting jpeg_start_output next */ - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; - } - cinfo->global_state = DSTATE_PRELOAD; - } - if (cinfo->global_state == DSTATE_PRELOAD) { - /* If file has multiple scans, absorb them all into the coef buffer */ - if (cinfo->inputctl->has_multiple_scans) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return FALSE; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* jdmaster underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - } - cinfo->output_scan_number = cinfo->input_scan_number; - } else if (cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any dummy output passes, and set up for the final pass */ - return output_pass_setup(cinfo); -} - - -/* - * Set up for an output pass, and perform any dummy pass(es) needed. - * Common subroutine for jpeg_start_decompress and jpeg_start_output. - * Entry: global_state = DSTATE_PRESCAN only if previously suspended. - * Exit: If done, returns TRUE and sets global_state for proper output mode. - * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. - */ - -LOCAL(boolean) -output_pass_setup (j_decompress_ptr cinfo) -{ - if (cinfo->global_state != DSTATE_PRESCAN) { - /* First call: do pass setup */ - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; - cinfo->global_state = DSTATE_PRESCAN; - } - /* Loop over any required dummy passes */ - while (cinfo->master->is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Crank through the dummy pass */ - while (cinfo->output_scanline < cinfo->output_height) { - JDIMENSION last_scanline; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* Process some data */ - last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, - &cinfo->output_scanline, (JDIMENSION) 0); - if (cinfo->output_scanline == last_scanline) - return FALSE; /* No progress made, must suspend */ - } - /* Finish up dummy pass, and set up for another one */ - (*cinfo->master->finish_output_pass) (cinfo); - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } - /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. - */ - cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; - return TRUE; -} - - -/* - * Read some scanlines of data from the JPEG decompressor. - * - * The return value will be the number of lines actually read. - * This may be less than the number requested in several cases, - * including bottom of image, data source suspension, and operating - * modes that emit multiple scanlines at a time. - * - * Note: we warn about excess calls to jpeg_read_scanlines() since - * this likely signals an application programmer error. However, - * an oversize buffer (max_lines > scanlines remaining) is not an error. - */ - -GLOBAL(JDIMENSION) -jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) -{ - JDIMENSION row_ctr; - - if (cinfo->global_state != DSTATE_SCANNING) - return 0; /* XYQ 2010-6-27: don't throw exception here */ -/* ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); */ - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Process some data */ - row_ctr = 0; - (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); - cinfo->output_scanline += row_ctr; - return row_ctr; -} - - -/* - * Alternate entry point to read raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - -GLOBAL(JDIMENSION) -jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) -{ - JDIMENSION lines_per_iMCU_row; - - if (cinfo->global_state != DSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; - } - - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - - /* Verify that at least one iMCU row can be returned. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; - if (max_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* Decompress directly into user's buffer. */ - if (! (*cinfo->coef->decompress_data) (cinfo, data)) - return 0; /* suspension forced, can do nothing more */ - - /* OK, we processed one iMCU row. */ - cinfo->output_scanline += lines_per_iMCU_row; - return lines_per_iMCU_row; -} - - -/* Additional entry points for buffered-image mode. */ - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Initialize for an output pass in buffered-image mode. - */ - -GLOBAL(boolean) -jpeg_start_output (j_decompress_ptr cinfo, int scan_number) -{ - if (cinfo->global_state != DSTATE_BUFIMAGE && - cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Limit scan number to valid range */ - if (scan_number <= 0) - scan_number = 1; - if (cinfo->inputctl->eoi_reached && - scan_number > cinfo->input_scan_number) - scan_number = cinfo->input_scan_number; - cinfo->output_scan_number = scan_number; - /* Perform any dummy output passes, and set up for the real pass */ - return output_pass_setup(cinfo); -} - - -/* - * Finish up after an output pass in buffered-image mode. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - -GLOBAL(boolean) -jpeg_finish_output (j_decompress_ptr cinfo) -{ - if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { - /* Terminate this pass. */ - /* We do not require the whole pass to have been completed. */ - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_BUFPOST; - } else if (cinfo->global_state != DSTATE_BUFPOST) { - /* BUFPOST = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - } - /* Read markers looking for SOS or EOI */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ - } - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jdcoefct.c b/third_party/libjpeg/fpdfapi_jdcoefct.c deleted file mode 100644 index 4938d20fcb655632d640534ba19e73f0c8fdccbc..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdcoefct.c +++ /dev/null @@ -1,736 +0,0 @@ -/* - * jdcoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the coefficient buffer controller for decompression. - * This controller is the top level of the JPEG decompressor proper. - * The coefficient buffer lies between entropy decoding and inverse-DCT steps. - * - * In buffered-image mode, this controller is the interface between - * input-oriented processing and output-oriented processing. - * Also, the input side (only) is used when reading a file for transcoding. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -/* Block smoothing is only applicable for progressive JPEG, so: */ -#ifndef D_PROGRESSIVE_SUPPORTED -#undef BLOCK_SMOOTHING_SUPPORTED -#endif - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_coef_controller pub; /* public fields */ - - /* These variables keep track of the current location of the input side. */ - /* cinfo->input_iMCU_row is also used for this. */ - JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ - int MCU_vert_offset; /* counts MCU rows within iMCU row */ - int MCU_rows_per_iMCU_row; /* number of such rows needed */ - - /* The output side's location is represented by cinfo->output_iMCU_row. */ - - /* In single-pass modes, it's sufficient to buffer just one MCU. - * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, - * and let the entropy decoder write into that workspace each time. - * (On 80x86, the workspace is FAR even though it's not really very big; - * this is to keep the module interfaces unchanged when a large coefficient - * buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays; it is used only by the input side. - */ - JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* In multi-pass modes, we need a virtual block array for each component. */ - jvirt_barray_ptr whole_image[MAX_COMPONENTS]; -#endif - -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* When doing block smoothing, we latch coefficient Al values here */ - int * coef_bits_latch; -#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ -#endif -} my_coef_controller; - -typedef my_coef_controller * my_coef_ptr; - -/* Forward declarations */ -METHODDEF(int) decompress_onepass - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#ifdef D_MULTISCAN_FILES_SUPPORTED -METHODDEF(int) decompress_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif -#ifdef BLOCK_SMOOTHING_SUPPORTED -LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); -METHODDEF(int) decompress_smooth_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); -#endif - - -LOCAL(void) -start_iMCU_row (j_decompress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row (input side) */ -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ - if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; - } else { - if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; - } - - coef->MCU_ctr = 0; - coef->MCU_vert_offset = 0; -} - - -/* - * Initialize for an input processing pass. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - cinfo->input_iMCU_row = 0; - start_iMCU_row(cinfo); -} - - -/* - * Initialize for an output processing pass. - */ - -METHODDEF(void) -start_output_pass (j_decompress_ptr cinfo) -{ -#ifdef BLOCK_SMOOTHING_SUPPORTED - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - - /* If multipass, check to see whether to use block smoothing on this pass */ - if (coef->pub.coef_arrays != NULL) { - if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; - else - coef->pub.decompress_data = decompress_data; - } -#endif - cinfo->output_iMCU_row = 0; -} - - -/* - * Decompress and return some data in the single-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Input and output must run in lockstep since we have only a one-MCU buffer. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - -METHODDEF(int) -decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - int blkn, ci, xindex, yindex, yoffset, useful_width; - JSAMPARRAY output_ptr; - JDIMENSION start_col, output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Loop to process as much as one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { - /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ - jzero_far((void FAR *) coef->MCU_buffer[0], - (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - /* Determine where data should go in output_buf and do the IDCT thing. - * We skip dummy blocks at the right and bottom edges (but blkn gets - * incremented past them!). Note the inner loop relies on having - * allocated the MCU_buffer[] blocks sequentially. - */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) { - blkn += compptr->MCU_blocks; - continue; - } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; - useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - output_ptr = output_buf[compptr->component_index] + - yoffset * compptr->DCT_scaled_size; - start_col = MCU_col_num * compptr->MCU_sample_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (cinfo->input_iMCU_row < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - output_col = start_col; - for (xindex = 0; xindex < useful_width; xindex++) { - (*inverse_DCT) (cinfo, compptr, - (JCOEFPTR) coef->MCU_buffer[blkn+xindex], - output_ptr, output_col); - output_col += compptr->DCT_scaled_size; - } - } - blkn += compptr->MCU_width; - output_ptr += compptr->DCT_scaled_size; - } - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - cinfo->output_iMCU_row++; - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Dummy consume-input routine for single-pass operation. - */ - -METHODDEF(int) -dummy_consume_data (j_decompress_ptr cinfo) -{ - return JPEG_SUSPENDED; /* Always indicate nothing was done */ -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Consume input data and store it in the full-image coefficient buffer. - * We read as much as one fully interleaved MCU row ("iMCU" row) per call, - * ie, v_samp_factor block rows for each component in the scan. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - */ - -METHODDEF(int) -consume_data (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION MCU_col_num; /* index of current MCU within row */ - int blkn, ci, xindex, yindex, yoffset; - JDIMENSION start_col; - JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; - JBLOCKROW buffer_ptr; - jpeg_component_info *compptr; - - /* Align the virtual buffers for the components used in this scan. */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - cinfo->input_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Note: entropy decoder expects buffer to be zeroed, - * but this is handled automatically by the memory manager - * because we requested a pre-zeroed array. - */ - } - - /* Loop to process one whole iMCU row */ - for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } - } - /* Try to fetch the MCU. */ - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; - } - /* Completed the iMCU row, advance counters for next one */ - if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row(cinfo); - return JPEG_ROW_COMPLETED; - } - /* Completed the scan */ - (*cinfo->inputctl->finish_input_pass) (cinfo); - return JPEG_SCAN_COMPLETED; -} - - -/* - * Decompress and return some data in the multi-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - */ - -METHODDEF(int) -decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num; - int ci, block_row, block_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number < cinfo->output_scan_number || - (cinfo->input_scan_number == cinfo->output_scan_number && - cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - cinfo->output_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - output_col = 0; - for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, - output_ptr, output_col); - buffer_ptr++; - output_col += compptr->DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -#ifdef BLOCK_SMOOTHING_SUPPORTED - -/* - * This code applies interblock smoothing as described by section K.8 - * of the JPEG standard: the first 5 AC coefficients are estimated from - * the DC values of a DCT block and its 8 neighboring blocks. - * We apply smoothing only for progressive JPEG decoding, and only if - * the coefficients it can estimate are not yet known to full precision. - */ - -/* Natural-order array positions of the first 5 zigzag-order coefficients */ -#define Q01_POS 1 -#define Q10_POS 8 -#define Q20_POS 16 -#define Q11_POS 9 -#define Q02_POS 2 - -/* - * Determine whether block smoothing is applicable and safe. - * We also latch the current states of the coef_bits[] entries for the - * AC coefficients; otherwise, if the input side of the decompressor - * advances into a new scan, we might think the coefficients are known - * more accurately than they really are. - */ - -LOCAL(boolean) -smoothing_ok (j_decompress_ptr cinfo) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - boolean smoothing_useful = FALSE; - int ci, coefi; - jpeg_component_info *compptr; - JQUANT_TBL * qtable; - int * coef_bits; - int * coef_bits_latch; - - if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) - return FALSE; - - /* Allocate latch area if not already done */ - if (coef->coef_bits_latch == NULL) - coef->coef_bits_latch = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * - (SAVED_COEFS * SIZEOF(int))); - coef_bits_latch = coef->coef_bits_latch; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* All components' quantization values must already be latched. */ - if ((qtable = compptr->quant_table) == NULL) - return FALSE; - /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ - if (qtable->quantval[0] == 0 || - qtable->quantval[Q01_POS] == 0 || - qtable->quantval[Q10_POS] == 0 || - qtable->quantval[Q20_POS] == 0 || - qtable->quantval[Q11_POS] == 0 || - qtable->quantval[Q02_POS] == 0) - return FALSE; - /* DC values must be at least partly known for all components. */ - coef_bits = cinfo->coef_bits[ci]; - if (coef_bits[0] < 0) - return FALSE; - /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ - for (coefi = 1; coefi <= 5; coefi++) { - coef_bits_latch[coefi] = coef_bits[coefi]; - if (coef_bits[coefi] != 0) - smoothing_useful = TRUE; - } - coef_bits_latch += SAVED_COEFS; - } - - return smoothing_useful; -} - - -/* - * Variant of decompress_data for use when doing block smoothing. - */ - -METHODDEF(int) -decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) -{ - my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; - JDIMENSION block_num, last_block_column; - int ci, block_row, block_rows, access_rows; - JBLOCKARRAY buffer; - JBLOCKROW buffer_ptr, prev_block_row, next_block_row; - JSAMPARRAY output_ptr; - JDIMENSION output_col; - jpeg_component_info *compptr; - inverse_DCT_method_ptr inverse_DCT; - boolean first_row, last_row; - JBLOCK workspace; - int *coef_bits; - JQUANT_TBL *quanttbl; - INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; - int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; - int Al, pred; - - /* Force some input to be done if we are getting ahead of the input. */ - while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { - if (cinfo->input_scan_number == cinfo->output_scan_number) { - /* If input is working on current scan, we ordinarily want it to - * have completed the current row. But if input scan is DC, - * we want it to keep one row ahead so that next block row's DC - * values are up to date. - */ - JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; - if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) - break; - } - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; - } - - /* OK, output from the virtual arrays. */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) { - block_rows = compptr->v_samp_factor; - access_rows = block_rows * 2; /* this and next iMCU row */ - last_row = FALSE; - } else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - access_rows = block_rows; /* this iMCU row only */ - last_row = TRUE; - } - /* Align the virtual buffer for this component. */ - if (cinfo->output_iMCU_row > 0) { - access_rows += compptr->v_samp_factor; /* prior iMCU row too */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, - (JDIMENSION) access_rows, FALSE); - buffer += compptr->v_samp_factor; /* point to current iMCU row */ - first_row = FALSE; - } else { - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); - first_row = TRUE; - } - /* Fetch component-dependent info */ - coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); - quanttbl = compptr->quant_table; - Q00 = quanttbl->quantval[0]; - Q01 = quanttbl->quantval[Q01_POS]; - Q10 = quanttbl->quantval[Q10_POS]; - Q20 = quanttbl->quantval[Q20_POS]; - Q11 = quanttbl->quantval[Q11_POS]; - Q02 = quanttbl->quantval[Q02_POS]; - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - if (first_row && block_row == 0) - prev_block_row = buffer_ptr; - else - prev_block_row = buffer[block_row-1]; - if (last_row && block_row == block_rows-1) - next_block_row = buffer_ptr; - else - next_block_row = buffer[block_row+1]; - /* We fetch the surrounding DC values using a sliding-register approach. - * Initialize all nine here so as to do the right thing on narrow pics. - */ - DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; - DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; - DC7 = DC8 = DC9 = (int) next_block_row[0][0]; - output_col = 0; - last_block_column = compptr->width_in_blocks - 1; - for (block_num = 0; block_num <= last_block_column; block_num++) { - /* Fetch current DCT block into workspace so we can modify it. */ - jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); - /* Update DC values */ - if (block_num < last_block_column) { - DC3 = (int) prev_block_row[1][0]; - DC6 = (int) buffer_ptr[1][0]; - DC9 = (int) next_block_row[1][0]; - } - /* Compute coefficient estimates per K.8. - * An estimate is applied only if coefficient is still zero, - * and is not known to be fully accurate. - */ - /* AC01 */ - if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { - num = 36 * Q00 * (DC4 - DC6); - if (num >= 0) { - pred = (int) (((Q01<<7) + num) / (Q01<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q01<<7) - num) / (Q01<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[1] = (JCOEF) pred; - } - /* AC10 */ - if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) { - num = 36 * Q00 * (DC2 - DC8); - if (num >= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q10<<7) - num) / (Q10<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[8] = (JCOEF) pred; - } - /* AC20 */ - if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) { - num = 9 * Q00 * (DC2 + DC8 - 2*DC5); - if (num >= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q20<<7) - num) / (Q20<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[16] = (JCOEF) pred; - } - /* AC11 */ - if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) { - num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9); - if (num >= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q11<<7) - num) / (Q11<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[9] = (JCOEF) pred; - } - /* AC02 */ - if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) { - num = 9 * Q00 * (DC4 + DC6 - 2*DC5); - if (num >= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - } else { - pred = (int) (((Q02<<7) - num) / (Q02<<8)); - if (Al > 0 && pred >= (1<<Al)) - pred = (1<<Al)-1; - pred = -pred; - } - workspace[2] = (JCOEF) pred; - } - /* OK, do the IDCT */ - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace, - output_ptr, output_col); - /* Advance for next column */ - DC1 = DC2; DC2 = DC3; - DC4 = DC5; DC5 = DC6; - DC7 = DC8; DC8 = DC9; - buffer_ptr++, prev_block_row++, next_block_row++; - output_col += compptr->DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } - } - - if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; - return JPEG_SCAN_COMPLETED; -} - -#endif /* BLOCK_SMOOTHING_SUPPORTED */ - - -/* - * Initialize coefficient buffer controller. - */ - -GLOBAL(void) -jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_coef_ptr coef; - - coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); - cinfo->coef = (struct jpeg_d_coef_controller *) coef; - coef->pub.start_input_pass = start_input_pass; - coef->pub.start_output_pass = start_output_pass; -#ifdef BLOCK_SMOOTHING_SUPPORTED - coef->coef_bits_latch = NULL; -#endif - - /* Create the coefficient buffer. */ - if (need_full_buffer) { -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - /* Note we ask for a pre-zeroed array. */ - int ci, access_rows; - jpeg_component_info *compptr; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - access_rows = compptr->v_samp_factor; -#ifdef BLOCK_SMOOTHING_SUPPORTED - /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) - access_rows *= 3; -#endif - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) access_rows); - } - coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; - coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; - - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; - coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ - } -} diff --git a/third_party/libjpeg/fpdfapi_jdcolor.c b/third_party/libjpeg/fpdfapi_jdcolor.c deleted file mode 100644 index 6c04dfe8aa1b36e4ab4c9909c77e9cd26b74e9d7..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdcolor.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * jdcolor.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains output colorspace conversion routines. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private subobject */ - -typedef struct { - struct jpeg_color_deconverter pub; /* public fields */ - - /* Private state for YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ -} my_color_deconverter; - -typedef my_color_deconverter * my_cconvert_ptr; - - -/**************** YCbCr -> RGB conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * Notice that Y, being an integral input, does not contribute any fraction - * so it need not participate in the rounding. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The Cr=>R and Cb=>B values can be rounded to integers in advance; the - * values for the G calculation are left scaled up, since we must add them - * together before rounding. - */ - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) - - -/* - * Initialize tables for YCC->RGB colorspace conversion. - */ - -LOCAL(void) -build_ycc_rgb_table (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - int i; - INT32 x; - SHIFT_TEMPS - - cconvert->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - cconvert->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - cconvert->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; - } -} - - -/* - * Convert some rows of samples to the output colorspace. - * - * Note that we change from noninterleaved, one-plane-per-component format - * to interleaved-pixel format. The output buffer is therefore three times - * as wide as the input buffer. - * A starting row offset is provided only for the input buffer. The caller - * can easily adjust the passed output_buf value to accommodate any row - * offset required on that side. - */ - -METHODDEF(void) -ycc_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; - outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/**************** Cases other than YCbCr -> RGB **************/ - - -/* - * Color conversion for no colorspace change: just copy the data, - * converting from separate-planes to interleaved representation. - */ - -METHODDEF(void) -null_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW inptr, outptr; - register JDIMENSION count; - register int num_components = cinfo->num_components; - JDIMENSION num_cols = cinfo->output_width; - int ci; - - while (--num_rows >= 0) { - for (ci = 0; ci < num_components; ci++) { - inptr = input_buf[ci][input_row]; - outptr = output_buf[0] + ci; - for (count = num_cols; count > 0; count--) { - *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ - outptr += num_components; - } - } - input_row++; - output_buf++; - } -} - - -/* - * Color conversion for grayscale: just copy the data. - * This also works for YCbCr -> grayscale conversion, in which - * we just copy the Y (luminance) component and ignore chrominance. - */ - -METHODDEF(void) -grayscale_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, - num_rows, cinfo->output_width); -} - - -/* - * Convert grayscale to RGB: just duplicate the graylevel three times. - * This is provided to support applications that don't want to cope - * with grayscale as a separate case. - */ - -METHODDEF(void) -gray_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW inptr, outptr; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - while (--num_rows >= 0) { - inptr = input_buf[0][input_row++]; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - /* We can dispense with GETJSAMPLE() here */ - outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/* - * Adobe-style YCCK->CMYK conversion. - * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same - * conversion as above, while passing K (black) unchanged. - * We assume build_ycc_rgb_table has been called. - */ - -METHODDEF(void) -ycck_cmyk_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - register int y, cb, cr; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2, inptr3; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - register int * Crrtab = cconvert->Cr_r_tab; - register int * Cbbtab = cconvert->Cb_b_tab; - register INT32 * Crgtab = cconvert->Cr_g_tab; - register INT32 * Cbgtab = cconvert->Cb_g_tab; - SHIFT_TEMPS - - while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - inptr3 = input_buf[3][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ - /* K passes through unchanged */ - outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ - outptr += 4; - } - } -} - - -/* - * Empty method for start_pass. - */ - -METHODDEF(void) -start_pass_dcolor (j_decompress_ptr cinfo) -{ - /* no work needed */ -} - - -/* - * Module initialization routine for output colorspace conversion. - */ - -GLOBAL(void) -jinit_color_deconverter (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert; - int ci; - - cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_deconverter)); - cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; - cconvert->pub.start_pass = start_pass_dcolor; - - /* Make sure num_components agrees with jpeg_color_space */ - switch (cinfo->jpeg_color_space) { - case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_RGB: - case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - case JCS_CMYK: - case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - - default: /* JCS_UNKNOWN can be anything */ - if (cinfo->num_components < 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; - } - - /* Set out_color_components and conversion method based on requested space. - * Also clear the component_needed flags for any unused components, - * so that earlier pipeline stages can avoid useless computation. - */ - - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - if (cinfo->jpeg_color_space == JCS_GRAYSCALE || - cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = grayscale_convert; - /* For color->grayscale conversion, only the Y (0) component is needed */ - for (ci = 1; ci < cinfo->num_components; ci++) - cinfo->comp_info[ci].component_needed = FALSE; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; - } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { - cconvert->pub.color_convert = null_convert; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - case JCS_CMYK: - cinfo->out_color_components = 4; - if (cinfo->jpeg_color_space == JCS_YCCK) { - cconvert->pub.color_convert = ycck_cmyk_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_CMYK) { - cconvert->pub.color_convert = null_convert; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - - default: - /* Permit null conversion to same output space */ - if (cinfo->out_color_space == cinfo->jpeg_color_space) { - cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert; - } else /* unsupported non-null conversion */ - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; - } - - if (cinfo->quantize_colors) - cinfo->output_components = 1; /* single colormapped output component */ - else - cinfo->output_components = cinfo->out_color_components; -} diff --git a/third_party/libjpeg/fpdfapi_jddctmgr.c b/third_party/libjpeg/fpdfapi_jddctmgr.c deleted file mode 100644 index bbf8d0e92fdd84ddaa0017a2df039d224a740898..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jddctmgr.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * jddctmgr.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the inverse-DCT management logic. - * This code selects a particular IDCT implementation to be used, - * and it performs related housekeeping chores. No code in this file - * is executed per IDCT step, only during output pass setup. - * - * Note that the IDCT routines are responsible for performing coefficient - * dequantization as well as the IDCT proper. This module sets up the - * dequantization multiplier table needed by the IDCT routine. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - - -/* - * The decompressor input side (jdinput.c) saves away the appropriate - * quantization table for each component at the start of the first scan - * involving that component. (This is necessary in order to correctly - * decode files that reuse Q-table slots.) - * When we are ready to make an output pass, the saved Q-table is converted - * to a multiplier table that will actually be used by the IDCT routine. - * The multiplier table contents are IDCT-method-dependent. To support - * application changes in IDCT method between scans, we can remake the - * multiplier tables if necessary. - * In buffered-image mode, the first output pass may occur before any data - * has been seen for some components, and thus before their Q-tables have - * been saved away. To handle this case, multiplier tables are preset - * to zeroes; the result of the IDCT will be a neutral gray level. - */ - - -/* Private subobject for this module */ - -typedef struct { - struct jpeg_inverse_dct pub; /* public fields */ - - /* This array contains the IDCT method code that each multiplier table - * is currently set up for, or -1 if it's not yet set up. - * The actual multiplier tables are pointed to by dct_table in the - * per-component comp_info structures. - */ - int cur_method[MAX_COMPONENTS]; -} my_idct_controller; - -typedef my_idct_controller * my_idct_ptr; - - -/* Allocated multiplier tables: big enough for any supported variant */ - -typedef union { - ISLOW_MULT_TYPE islow_array[DCTSIZE2]; -#ifdef DCT_IFAST_SUPPORTED - IFAST_MULT_TYPE ifast_array[DCTSIZE2]; -#endif -#ifdef DCT_FLOAT_SUPPORTED - FLOAT_MULT_TYPE float_array[DCTSIZE2]; -#endif -} multiplier_table; - - -/* The current scaled-IDCT routines require ISLOW-style multiplier tables, - * so be sure to compile that code if either ISLOW or SCALING is requested. - */ -#ifdef DCT_ISLOW_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#else -#ifdef IDCT_SCALING_SUPPORTED -#define PROVIDE_ISLOW_TABLES -#endif -#endif - - -/* - * Prepare for an output pass. - * Here we select the proper IDCT routine for each component and build - * a matching multiplier table. - */ - -METHODDEF(void) -start_pass (j_decompress_ptr cinfo) -{ - my_idct_ptr idct = (my_idct_ptr) cinfo->idct; - int ci, i; - jpeg_component_info *compptr; - int method = 0; - inverse_DCT_method_ptr method_ptr = NULL; - JQUANT_TBL * qtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Select the proper IDCT routine for this component's scaling */ - switch (compptr->DCT_scaled_size) { -#ifdef IDCT_SCALING_SUPPORTED - case 1: - method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 2: - method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 4: - method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; -#endif - case DCTSIZE: - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - method_ptr = jpeg_idct_islow; - method = JDCT_ISLOW; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - method_ptr = jpeg_idct_ifast; - method = JDCT_IFAST; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - method_ptr = jpeg_idct_float; - method = JDCT_FLOAT; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - break; - default: - ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); - break; - } - idct->pub.inverse_DCT[ci] = method_ptr; - /* Create multiplier table from quant table. - * However, we can skip this if the component is uninteresting - * or if we already built the table. Also, if no quant table - * has yet been saved for the component, we leave the - * multiplier table all-zero; we'll be reading zeroes from the - * coefficient controller's buffer anyway. - */ - if (! compptr->component_needed || idct->cur_method[ci] == method) - continue; - qtbl = compptr->quant_table; - if (qtbl == NULL) /* happens if no data yet for component */ - continue; - idct->cur_method[ci] = method; - switch (method) { -#ifdef PROVIDE_ISLOW_TABLES - case JDCT_ISLOW: - { - /* For LL&M IDCT method, multipliers are equal to raw quantization - * coefficients, but are stored as ints to ensure access efficiency. - */ - ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; - for (i = 0; i < DCTSIZE2; i++) { - ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; - } - } - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * For integer operation, the multiplier table is to be scaled by - * IFAST_SCALE_BITS. - */ - IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - for (i = 0; i < DCTSIZE2; i++) { - ifmtbl[i] = (IFAST_MULT_TYPE) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-IFAST_SCALE_BITS); - } - } - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - */ - FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fmtbl[i] = (FLOAT_MULT_TYPE) - ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col]); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} - - -/* - * Initialize IDCT manager. - */ - -GLOBAL(void) -jinit_inverse_dct (j_decompress_ptr cinfo) -{ - my_idct_ptr idct; - int ci; - jpeg_component_info *compptr; - - idct = (my_idct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_idct_controller)); - cinfo->idct = (struct jpeg_inverse_dct *) idct; - idct->pub.start_pass = start_pass; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate and pre-zero a multiplier table for each component */ - compptr->dct_table = - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(multiplier_table)); - MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); - /* Mark multiplier table not yet set up for any method */ - idct->cur_method[ci] = -1; - } -} diff --git a/third_party/libjpeg/fpdfapi_jdhuff.c b/third_party/libjpeg/fpdfapi_jdhuff.c deleted file mode 100644 index 2c9495c2b4f2cc90b5bf1f6866d9f5558d81badb..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdhuff.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * jdhuff.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdphuff.c */ - -/* - * Expanded entropy decoder object for Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; - d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - - /* Precalculated info set up by start_pass for use in decode_mcu: */ - - /* Pointers to derived tables to be used for each block within an MCU */ - d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - /* Whether we care about the DC and AC coefficient values for each block */ - boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; - boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; -} huff_entropy_decoder; - -typedef huff_entropy_decoder * huff_entropy_ptr; - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, blkn, dctbl, actbl; - jpeg_component_info * compptr; - - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ - if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || - cinfo->Ah != 0 || cinfo->Al != 0) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Precalculate decoding info for each block in an MCU of this scan */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - /* Precalculate which table to use for each block */ - entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - /* Decide whether we really care about the coefficient values */ - if (compptr->component_needed) { - entropy->dc_needed[blkn] = TRUE; - /* we don't need the ACs if producing a 1/8th-size image */ - entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); - } else { - entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; - } - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->pub.insufficient_data = FALSE; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - * - * Note this is also used by jdphuff.c. - */ - -GLOBAL(void) -jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, - d_derived_tbl ** pdtbl) -{ - JHUFF_TBL *htbl; - d_derived_tbl *dtbl; - int p, i, l, _si, numsymbols; - int lookbits, ctr; - char huffsize[257]; - unsigned int huffcode[257]; - unsigned int code; - - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ - if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; - if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - - /* Allocate a workspace if we haven't already done so. */ - if (*pdtbl == NULL) - *pdtbl = (d_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_derived_tbl)); - dtbl = *pdtbl; - dtbl->pub = htbl; /* fill in back link */ - - /* Figure C.1: make table of Huffman code length for each symbol */ - - p = 0; - for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; - } - huffsize[p] = 0; - numsymbols = p; - - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - - code = 0; - _si = huffsize[0]; - p = 0; - while (huffsize[p]) { - while (((int) huffsize[p]) == _si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << _si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - _si++; - } - - /* Figure F.15: generate decoding tables for bit-sequential decoding */ - - p = 0; - for (l = 1; l <= 16; l++) { - if (htbl->bits[l]) { - /* valoffset[l] = huffval[] index of 1st symbol of code length l, - * minus the minimum code of length l - */ - dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; - p += htbl->bits[l]; - dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ - } else { - dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ - } - } - dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ - - /* Compute lookahead tables to speed up decoding. - * First we set all the table entries to 0, indicating "too long"; - * then we iterate through the Huffman codes that are short enough and - * fill in all the entries that correspond to bit sequences starting - * with that code. - */ - - MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); - - p = 0; - for (l = 1; l <= HUFF_LOOKAHEAD; l++) { - for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { - /* l = current code's length, p = its index in huffcode[] & huffval[]. */ - /* Generate left-justified code followed by all possible bit sequences */ - lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); - for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { - dtbl->look_nbits[lookbits] = l; - dtbl->look_sym[lookbits] = htbl->huffval[p]; - lookbits++; - } - } - } - - /* Validate symbols as being reasonable. - * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..15. - * (Tighter bounds could be applied depending on the data depth and mode, - * but this is sufficient to ensure safe decoding.) - */ - if (isDC) { - for (i = 0; i < numsymbols; i++) { - int sym = htbl->huffval[i]; - if (sym < 0 || sym > 15) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - } - } -} - - -/* - * Out-of-line code for bit fetching (shared with jdphuff.c). - * See jdhuff.h for info about usage. - * Note: current values of get_buffer and bits_left are passed as parameters, - * but are returned in the corresponding fields of the state struct. - * - * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width - * of get_buffer to be used. (On machines with wider words, an even larger - * buffer could be used.) However, on some machines 32-bit shifts are - * quite slow and take time proportional to the number of places shifted. - * (This is true with most PC compilers, for instance.) In this case it may - * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the - * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. - */ - -#ifdef SLOW_SHIFT_32 -#define MIN_GET_BITS 15 /* minimum allowable value */ -#else -#define MIN_GET_BITS (BIT_BUF_SIZE-7) -#endif - - -GLOBAL(boolean) -jpeg_fill_bit_buffer (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits) -/* Load up the bit buffer to a depth of at least nbits */ -{ - /* Copy heavily used state fields into locals (hopefully registers) */ - register const JOCTET * next_input_byte = state->next_input_byte; - register size_t bytes_in_buffer = state->bytes_in_buffer; - j_decompress_ptr cinfo = state->cinfo; - - /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ - /* (It is assumed that no request will be for more than that many bits.) */ - /* We fail to do so only if we hit a marker or are forced to suspend. */ - - if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ - while (bits_left < MIN_GET_BITS) { - register int c; - - /* Attempt to read a byte */ - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - - /* If it's 0xFF, check and discard stuffed zero byte */ - if (c == 0xFF) { - /* Loop here to discard any padding FF's on terminating marker, - * so that we can save a valid unread_marker value. NOTE: we will - * accept multiple FF's followed by a 0 as meaning a single FF data - * byte. This data pattern is not valid according to the standard. - */ - do { - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - } while (c == 0xFF); - - if (c == 0) { - /* Found FF/00, which represents an FF data byte */ - c = 0xFF; - } else { - /* Oops, it's actually a marker indicating end of compressed data. - * Save the marker code for later use. - * Fine point: it might appear that we should save the marker into - * bitread working state, not straight into permanent state. But - * once we have hit a marker, we cannot need to suspend within the - * current MCU, because we will read no more bytes from the data - * source. So it is OK to update permanent state right away. - */ - cinfo->unread_marker = c; - /* See if we need to insert some fake zero bits. */ - goto no_more_bytes; - } - } - - /* OK, load c into get_buffer */ - get_buffer = (get_buffer << 8) | c; - bits_left += 8; - } /* end while */ - } else { - no_more_bytes: - /* We get here if we've read the marker that terminates the compressed - * data segment. There should be enough bits in the buffer register - * to satisfy the request; if so, no problem. - */ - if (nbits > bits_left) { - /* Uh-oh. Report corrupted data to user and stuff zeroes into - * the data stream, so that we can produce some kind of image. - * We use a nonvolatile flag to ensure that only one warning message - * appears per data segment. - */ - if (! cinfo->entropy->insufficient_data) { - WARNMS(cinfo, JWRN_HIT_MARKER); - cinfo->entropy->insufficient_data = TRUE; - } - /* Fill the buffer with zero bits */ - get_buffer <<= MIN_GET_BITS - bits_left; - bits_left = MIN_GET_BITS; - } - } - - /* Unload the local registers */ - state->next_input_byte = next_input_byte; - state->bytes_in_buffer = bytes_in_buffer; - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - return TRUE; -} - - -/* - * Out-of-line code for Huffman code decoding. - * See jdhuff.h for info about usage. - */ - -GLOBAL(int) -jpeg_huff_decode (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - d_derived_tbl * htbl, int min_bits) -{ - register int l = min_bits; - register INT32 code; - - /* HUFF_DECODE has determined that the code is at least min_bits */ - /* bits long, so fetch that many bits in one swoop. */ - - CHECK_BIT_BUFFER(*state, l, return -1); - code = GET_BITS(l); - - /* Collect the rest of the Huffman code one bit at a time. */ - /* This is per Figure F.16 in the JPEG spec. */ - - while (code > htbl->maxcode[l]) { - code <<= 1; - CHECK_BIT_BUFFER(*state, 1, return -1); - code |= GET_BITS(1); - l++; - } - - /* Unload the local registers */ - state->get_buffer = get_buffer; - state->bits_left = bits_left; - - /* With garbage input we may reach the sentinel value l = 17. */ - - if (l > 16) { - WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); - return 0; /* fake a zero as the safest result */ - } - - return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Decode and return one MCU's worth of Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. - * (Wholesale zeroing is usually a little faster than retail...) - * - * Returns FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * this module, since we'll just re-assign them on the next call.) - */ - -METHODDEF(boolean) -decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int blkn; - BITREAD_STATE_VARS; - savable_state state; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; - d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; - register int s, k, r; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - if (entropy->dc_needed[blkn]) { - /* Convert DC difference to actual value, update last_dc_val */ - int ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ - (*block)[0] = (JCOEF) s; - } - - if (entropy->ac_needed[blkn]) { - - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label2); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - break; - k += 15; - } - } - - } else { - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } - } - - } - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * Module initialization routine for Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy; - int i; - - entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_decoder)); - cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; - entropy->pub.start_pass = start_pass_huff_decoder; - entropy->pub.decode_mcu = decode_mcu; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; - } -} diff --git a/third_party/libjpeg/fpdfapi_jdinput.c b/third_party/libjpeg/fpdfapi_jdinput.c deleted file mode 100644 index 0c2ac8f120bca16bff13b989d8879ac9db85a011..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdinput.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * jdinput.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains input control logic for the JPEG decompressor. - * These routines are concerned with controlling the decompressor's input - * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_input_controller pub; /* public fields */ - - boolean inheaders; /* TRUE until first SOS is reached */ -} my_input_controller; - -typedef my_input_controller * my_inputctl_ptr; - - -/* Forward declarations */ -METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); - - -/* - * Routines to calculate various quantities related to the size of the image. - */ - -LOCAL(void) -initial_setup (j_decompress_ptr cinfo) -/* Called once, when first SOS marker is reached */ -{ - int ci; - jpeg_component_info *compptr; - - /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - - /* Check that number of components won't exceed internal array sizes */ - if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - - /* Compute maximum sampling factors; check factor validity */ - cinfo->max_h_samp_factor = 1; - cinfo->max_v_samp_factor = 1; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); - } - - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; - * but in the transcoder, jdmaster.c is not used, so we must do it here. - */ - cinfo->min_DCT_scaled_size = DCTSIZE; - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* downsampled_width and downsampled_height will also be overridden by - * jdmaster.c if we are doing full decompression. The transcoder library - * doesn't use these values, but the calling application might. - */ - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed, until color conversion says otherwise */ - compptr->component_needed = TRUE; - /* Mark no quantization table yet saved for component */ - compptr->quant_table = NULL; - } - - /* Compute number of fully interleaved MCU rows. */ - cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - /* Decide whether file contains multiple scans */ - if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) - cinfo->inputctl->has_multiple_scans = TRUE; - else - cinfo->inputctl->has_multiple_scans = FALSE; -} - - -LOCAL(void) -per_scan_setup (j_decompress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ -{ - int ci, mcublks, tmp; - jpeg_component_info *compptr; - - if (cinfo->comps_in_scan == 1) { - - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = compptr->DCT_scaled_size; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; - - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; - - } else { - - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); - - cinfo->blocks_in_MCU = 0; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } - - } -} - - -/* - * Save away a copy of the Q-table referenced by each component present - * in the current scan, unless already saved during a prior scan. - * - * In a multiple-scan JPEG file, the encoder could assign different components - * the same Q-table slot number, but change table definitions between scans - * so that each component uses a different Q-table. (The IJG encoder is not - * currently capable of doing this, but other encoders might.) Since we want - * to be able to dequantize all the components at the end of the file, this - * means that we have to save away the table actually used for each component. - * We do this by copying the table at the start of the first scan containing - * the component. - * The JPEG spec prohibits the encoder from changing the contents of a Q-table - * slot between scans of a component using that slot. If the encoder does so - * anyway, this decoder will simply use the Q-table values that were current - * at the start of the first scan for the component. - * - * The decompressor output side looks only at the saved quant tables, - * not at the current Q-table slots. - */ - -LOCAL(void) -latch_quant_tables (j_decompress_ptr cinfo) -{ - int ci, qtblno; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* No work if we already saved Q-table for this component */ - if (compptr->quant_table != NULL) - continue; - /* Make sure specified quantization table is present */ - qtblno = compptr->quant_tbl_no; - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - /* OK, save away the quantization table */ - qtbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(JQUANT_TBL)); - MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); - compptr->quant_table = qtbl; - } -} - - -/* - * Initialize the input modules to read a scan of compressed data. - * The first call to this is done by jdmaster.c after initializing - * the entire decompressor (during jpeg_start_decompress). - * Subsequent calls come from consume_markers, below. - */ - -METHODDEF(void) -start_input_pass (j_decompress_ptr cinfo) -{ - per_scan_setup(cinfo); - latch_quant_tables(cinfo); - (*cinfo->entropy->start_pass) (cinfo); - (*cinfo->coef->start_input_pass) (cinfo); - cinfo->inputctl->consume_input = cinfo->coef->consume_data; -} - - -/* - * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. - */ - -METHODDEF(void) -finish_input_pass (j_decompress_ptr cinfo) -{ - cinfo->inputctl->consume_input = consume_markers; -} - - -/* - * Read JPEG markers before, between, or after compressed-data scans. - * Change state as necessary when a new scan is reached. - * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - * - * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. - */ - -METHODDEF(int) -consume_markers (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - int val; - - if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ - return JPEG_REACHED_EOI; - - val = (*cinfo->marker->read_markers) (cinfo); - - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - initial_setup(cinfo); - inputctl->inheaders = FALSE; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - start_input_pass(cinfo); - } - break; - case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; - } - break; - case JPEG_SUSPENDED: - break; - } - - return val; -} - - -/* - * Reset state to begin a fresh datastream. - */ - -METHODDEF(void) -reset_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; - - inputctl->pub.consume_input = consume_markers; - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; - /* Reset other modules */ - (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); - (*cinfo->marker->reset_marker_reader) (cinfo); - /* Reset progression state -- would be cleaner if entropy decoder did this */ - cinfo->coef_bits = NULL; -} - - -/* - * Initialize the input controller module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL(void) -jinit_input_controller (j_decompress_ptr cinfo) -{ - my_inputctl_ptr inputctl; - - /* Create subobject in permanent pool */ - inputctl = (my_inputctl_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_input_controller)); - cinfo->inputctl = (struct jpeg_input_controller *) inputctl; - /* Initialize method pointers */ - inputctl->pub.consume_input = consume_markers; - inputctl->pub.reset_input_controller = reset_input_controller; - inputctl->pub.start_input_pass = start_input_pass; - inputctl->pub.finish_input_pass = finish_input_pass; - /* Initialize state: can't use reset_input_controller since we don't - * want to try to reset other modules yet. - */ - inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ - inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; -} diff --git a/third_party/libjpeg/fpdfapi_jdmainct.c b/third_party/libjpeg/fpdfapi_jdmainct.c deleted file mode 100644 index 13c956f5deb7da999d6d22c0bc25b81751b96815..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdmainct.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * jdmainct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the main buffer controller for decompression. - * The main buffer lies between the JPEG decompressor proper and the - * post-processor; it holds downsampled data in the JPEG colorspace. - * - * Note that this code is bypassed in raw-data mode, since the application - * supplies the equivalent of the main buffer in that case. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. - * - * Postprocessor input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. (We require DCT_scaled_size values to be - * chosen such that these numbers are integers. In practice DCT_scaled_size - * values will likely be powers of two, so we actually have the stronger - * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) - * Upsampling will typically produce max_v_samp_factor pixel rows from each - * row group (times any additional scale factor that the upsampler is - * applying). - * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or - * exactly min_DCT_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. - * - * Depending on the vertical scaling algorithm used, the upsampler may need - * access to the sample row(s) above and below its current input row group. - * The upsampler is required to set need_context_rows TRUE at global selection - * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. - * - * When need_context_rows is TRUE, this controller guarantees that the buffer - * passed to postprocessing contains at least one row group's worth of samples - * above and below the row group(s) being processed. Note that the context - * rows "above" the first passed row group appear at negative row offsets in - * the passed buffer. At the top and bottom of the image, the required - * context rows are manufactured by duplicating the first or last real sample - * row; this avoids having special cases in the upsampling inner loops. - * - * The amount of context is fixed at one row group just because that's a - * convenient number for this controller to work with. The existing - * upsamplers really only need one sample row of context. An upsampler - * supporting arbitrary output rescaling might wish for more than one row - * group of context when shrinking the image; tough, we don't handle that. - * (This is justified by the assumption that downsizing will be handled mostly - * by adjusting the DCT_scaled_size values, so that the actual scale factor at - * the upsample step needn't be much less than one.) - * - * To provide the desired context, we have to retain the last two row groups - * of one iMCU row while reading in the next iMCU row. (The last row group - * can't be processed until we have another row group for its below-context, - * and so we have to save the next-to-last group too for its above-context.) - * We could do this most simply by copying data around in our buffer, but - * that'd be very slow. We can avoid copying any data by creating a rather - * strange pointer structure. Here's how it works. We allocate a workspace - * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number - * of row groups per iMCU row). We create two sets of redundant pointers to - * the workspace. Labeling the physical row groups 0 to M+1, the synthesized - * pointer lists look like this: - * M+1 M-1 - * master pointer --> 0 master pointer --> 0 - * 1 1 - * ... ... - * M-3 M-3 - * M-2 M - * M-1 M+1 - * M M-2 - * M+1 M-1 - * 0 0 - * We read alternate iMCU rows using each master pointer; thus the last two - * row groups of the previous iMCU row remain un-overwritten in the workspace. - * The pointer lists are set up so that the required context rows appear to - * be adjacent to the proper places when we pass the pointer lists to the - * upsampler. - * - * The above pictures describe the normal state of the pointer lists. - * At top and bottom of the image, we diddle the pointer lists to duplicate - * the first or last sample row as necessary (this is cheaper than copying - * sample rows around). - * - * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that - * situation each iMCU row provides only one row group so the buffering logic - * must be different (eg, we must read two iMCU rows before we can emit the - * first row group). For now, we simply do not support providing context - * rows when min_DCT_scaled_size is 1. That combination seems unlikely to - * be worth providing --- if someone wants a 1/8th-size preview, they probably - * want it quick and dirty, so a context-free upsampler is sufficient. - */ - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_main_controller pub; /* public fields */ - - /* Pointer to allocated workspace (M or M+2 row groups). */ - JSAMPARRAY buffer[MAX_COMPONENTS]; - - boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ - JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ - - /* Remaining fields are only used in the context case. */ - - /* These are the master pointers to the funny-order pointer lists. */ - JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ - - int whichptr; /* indicates which pointer set is now in use */ - int context_state; /* process_data state machine status */ - JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ - JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ -} my_main_controller; - -typedef my_main_controller * my_main_ptr; - -/* context_state values: */ -#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ -#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ -#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ - - -/* Forward declarations */ -METHODDEF(void) process_data_simple_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -METHODDEF(void) process_data_context_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF(void) process_data_crank_post - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); -#endif - - -LOCAL(void) -alloc_funny_pointers (j_decompress_ptr cinfo) -/* Allocate space for the funny pointer lists. - * This is done only once, not once per pass. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - /* Get top-level space for component array pointers. - * We alloc both arrays with one call to save a few cycles. - */ - main->xbuffer[0] = (JSAMPIMAGE) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); - main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - /* Get space for pointer lists --- M+4 row groups in each list. - * We alloc both pointer lists with one call to save a few cycles. - */ - xbuf = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); - xbuf += rgroup; /* want one row group at negative offsets */ - main->xbuffer[0][ci] = xbuf; - xbuf += rgroup * (M + 4); - main->xbuffer[1][ci] = xbuf; - } -} - - -LOCAL(void) -make_funny_pointers (j_decompress_ptr cinfo) -/* Create the funny pointer lists discussed in the comments above. - * The actual workspace is already allocated (in main->buffer), - * and the space for the pointer lists is allocated too. - * This routine just fills in the curiously ordered lists. - * This will be repeated at the beginning of each pass. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY buf, xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main->xbuffer[0][ci]; - xbuf1 = main->xbuffer[1][ci]; - /* First copy the workspace pointers as-is */ - buf = main->buffer[ci]; - for (i = 0; i < rgroup * (M + 2); i++) { - xbuf0[i] = xbuf1[i] = buf[i]; - } - /* In the second list, put the last four row groups in swapped order */ - for (i = 0; i < rgroup * 2; i++) { - xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; - xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; - } - /* The wraparound pointers at top and bottom will be filled later - * (see set_wraparound_pointers, below). Initially we want the "above" - * pointers to duplicate the first actual data line. This only needs - * to happen in xbuffer[0]. - */ - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[0]; - } - } -} - - -LOCAL(void) -set_wraparound_pointers (j_decompress_ptr cinfo) -/* Set up the "wraparound" pointers at top and bottom of the pointer lists. - * This changes the pointer list state from top-of-image to the normal state. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; - jpeg_component_info *compptr; - JSAMPARRAY xbuf0, xbuf1; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main->xbuffer[0][ci]; - xbuf1 = main->xbuffer[1][ci]; - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; - xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; - xbuf0[rgroup*(M+2) + i] = xbuf0[i]; - xbuf1[rgroup*(M+2) + i] = xbuf1[i]; - } - } -} - - -LOCAL(void) -set_bottom_pointers (j_decompress_ptr cinfo) -/* Change the pointer lists to duplicate the last sample row at the bottom - * of the image. whichptr indicates which xbuffer holds the final iMCU row. - * Also sets rowgroups_avail to indicate number of nondummy row groups in row. - */ -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - int ci, i, rgroup, iMCUheight, rows_left; - jpeg_component_info *compptr; - JSAMPARRAY xbuf; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; - rgroup = iMCUheight / cinfo->min_DCT_scaled_size; - /* Count nondummy sample rows remaining for this component */ - rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); - if (rows_left == 0) rows_left = iMCUheight; - /* Count nondummy row groups. Should get same answer for each component, - * so we need only do it once. - */ - if (ci == 0) { - main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); - } - /* Duplicate the last real sample row rgroup*2 times; this pads out the - * last partial rowgroup and ensures at least one full rowgroup of context. - */ - xbuf = main->xbuffer[main->whichptr][ci]; - for (i = 0; i < rgroup * 2; i++) { - xbuf[rows_left + i] = xbuf[rows_left-1]; - } - } -} - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->upsample->need_context_rows) { - main->pub.process_data = process_data_context_main; - make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - main->context_state = CTX_PREPARE_FOR_IMCU; - main->iMCU_row_ctr = 0; - } else { - /* Simple case with no context needed */ - main->pub.process_data = process_data_simple_main; - } - main->buffer_full = FALSE; /* Mark buffer empty */ - main->rowgroup_ctr = 0; - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_CRANK_DEST: - /* For last pass of 2-pass quantization, just crank the postprocessor */ - main->pub.process_data = process_data_crank_post; - break; -#endif - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } -} - - -/* - * Process some data. - * This handles the simple case where no context is required. - */ - -METHODDEF(void) -process_data_simple_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - JDIMENSION rowgroups_avail; - - /* Read input data if we haven't filled the main buffer yet */ - if (! main->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) - return; /* suspension forced, can do nothing more */ - main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - } - - /* There are always min_DCT_scaled_size row groups in an iMCU row. */ - rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; - /* Note: at the bottom of the image, we may pass extra garbage row groups - * to the postprocessor. The postprocessor has to check for bottom - * of image anyway (at row resolution), so no point in us doing it too. - */ - - /* Feed the postprocessor */ - (*cinfo->post->post_process_data) (cinfo, main->buffer, - &main->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - - /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ - if (main->rowgroup_ctr >= rowgroups_avail) { - main->buffer_full = FALSE; - main->rowgroup_ctr = 0; - } -} - - -/* - * Process some data. - * This handles the case where context rows must be provided. - */ - -METHODDEF(void) -process_data_context_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_main_ptr main = (my_main_ptr) cinfo->main; - - /* Read input data if we haven't filled the main buffer yet */ - if (! main->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, - main->xbuffer[main->whichptr])) - return; /* suspension forced, can do nothing more */ - main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - main->iMCU_row_ctr++; /* count rows received */ - } - - /* Postprocessor typically will not swallow all the input data it is handed - * in one call (due to filling the output buffer first). Must be prepared - * to exit and restart. This switch lets us keep track of how far we got. - * Note that each case falls through to the next on successful completion. - */ - switch (main->context_state) { - case CTX_POSTPONED_ROW: - /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], - &main->rowgroup_ctr, main->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (main->rowgroup_ctr < main->rowgroups_avail) - return; /* Need to suspend */ - main->context_state = CTX_PREPARE_FOR_IMCU; - if (*out_row_ctr >= out_rows_avail) - return; /* Postprocessor exactly filled output buf */ - /*FALLTHROUGH*/ - case CTX_PREPARE_FOR_IMCU: - /* Prepare to process first M-1 row groups of this iMCU row */ - main->rowgroup_ctr = 0; - main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); - /* Check for bottom of image: if so, tweak pointers to "duplicate" - * the last sample row, and adjust rowgroups_avail to ignore padding rows. - */ - if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) - set_bottom_pointers(cinfo); - main->context_state = CTX_PROCESS_IMCU; - /*FALLTHROUGH*/ - case CTX_PROCESS_IMCU: - /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], - &main->rowgroup_ctr, main->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); - if (main->rowgroup_ctr < main->rowgroups_avail) - return; /* Need to suspend */ - /* After the first iMCU, change wraparound pointers to normal state */ - if (main->iMCU_row_ctr == 1) - set_wraparound_pointers(cinfo); - /* Prepare to load new iMCU row using other xbuffer list */ - main->whichptr ^= 1; /* 0=>1 or 1=>0 */ - main->buffer_full = FALSE; - /* Still need to process last row group of this iMCU row, */ - /* which is saved at index M+1 of the other xbuffer */ - main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); - main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); - main->context_state = CTX_POSTPONED_ROW; - } -} - - -/* - * Process some data. - * Final pass of two-pass quantization: just call the postprocessor. - * Source data will be the postprocessor controller's internal buffer. - */ - -#ifdef QUANT_2PASS_SUPPORTED - -METHODDEF(void) -process_data_crank_post (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, - (JDIMENSION *) NULL, (JDIMENSION) 0, - output_buf, out_row_ctr, out_rows_avail); -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize main buffer controller. - */ - -GLOBAL(void) -jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_main_ptr main; - int ci, rgroup, ngroups; - jpeg_component_info *compptr; - - main = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); - cinfo->main = (struct jpeg_d_main_controller *) main; - main->pub.start_pass = start_pass_main; - - if (need_full_buffer) /* shouldn't happen */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - - /* Allocate the workspace. - * ngroups is the number of row groups we need. - */ - if (cinfo->upsample->need_context_rows) { - if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ - ERREXIT(cinfo, JERR_NOTIMPL); - alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_DCT_scaled_size + 2; - } else { - ngroups = cinfo->min_DCT_scaled_size; - } - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - main->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * compptr->DCT_scaled_size, - (JDIMENSION) (rgroup * ngroups)); - } -} diff --git a/third_party/libjpeg/fpdfapi_jdmarker.c b/third_party/libjpeg/fpdfapi_jdmarker.c deleted file mode 100644 index 449a3c0f682c4d82cf0a4c33acc412416d2a8d65..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdmarker.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* - * jdmarker.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains routines to decode JPEG datastream markers. - * Most of the complexity arises from our desire to support input - * suspension: if not all of the data for a marker is available, - * we must exit back to the application. On resumption, we reprocess - * the marker. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - - M_JPG0 = 0xf0, - M_JPG13 = 0xfd, - M_COM = 0xfe, - - M_TEM = 0x01, - - M_ERROR = 0x100 -} JPEG_MARKER; - - -/* Private state */ - -typedef struct { - struct jpeg_marker_reader pub; /* public fields */ - - /* Application-overridable marker processing methods */ - jpeg_marker_parser_method process_COM; - jpeg_marker_parser_method process_APPn[16]; - - /* Limit on marker data length to save for each marker type */ - unsigned int length_limit_COM; - unsigned int length_limit_APPn[16]; - - /* Status of COM/APPn marker saving */ - jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ - unsigned int bytes_read; /* data bytes read so far in marker */ - /* Note: cur_marker is not linked into marker_list until it's all read. */ -} my_marker_reader; - -typedef my_marker_reader * my_marker_ptr; - - -/* - * Macros for fetching data from the data source module. - * - * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect - * the current restart point; we update them only when we have reached a - * suitable place to restart if a suspension occurs. - */ - -/* Declare and initialize local copies of input pointer/count */ -#define INPUT_VARS(cinfo) \ - struct jpeg_source_mgr * datasrc = (cinfo)->src; \ - const JOCTET * next_input_byte = datasrc->next_input_byte; \ - size_t bytes_in_buffer = datasrc->bytes_in_buffer - -/* Unload the local copies --- do this only at a restart boundary */ -#define INPUT_SYNC(cinfo) \ - ( datasrc->next_input_byte = next_input_byte, \ - datasrc->bytes_in_buffer = bytes_in_buffer ) - -/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ -#define INPUT_RELOAD(cinfo) \ - ( next_input_byte = datasrc->next_input_byte, \ - bytes_in_buffer = datasrc->bytes_in_buffer ) - -/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. - * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, - * but we must reload the local copies after a successful fill. - */ -#define MAKE_BYTE_AVAIL(cinfo,action) \ - if (bytes_in_buffer == 0) { \ - if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ - INPUT_RELOAD(cinfo); \ - } - -/* Read a byte into variable V. - * If must suspend, take the specified action (typically "return FALSE"). - */ -#define INPUT_BYTE(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) - -/* As above, but read two bytes interpreted as an unsigned 16-bit integer. - * V should be declared unsigned int or perhaps INT32. - */ -#define INPUT_2BYTES(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) - - -/* - * Routines to process JPEG markers. - * - * Entry condition: JPEG marker itself has been read and its code saved - * in cinfo->unread_marker; input restart point is just after the marker. - * - * Exit: if return TRUE, have read and processed any parameters, and have - * updated the restart point to point after the parameters. - * If return FALSE, was forced to suspend before reaching end of - * marker parameters; restart point has not been moved. Same routine - * will be called again after application supplies more input data. - * - * This approach to suspension assumes that all of a marker's parameters - * can fit into a single input bufferload. This should hold for "normal" - * markers. Some COM/APPn markers might have large parameter segments - * that might not fit. If we are simply dropping such a marker, we use - * skip_input_data to get past it, and thereby put the problem on the - * source manager's shoulders. If we are saving the marker's contents - * into memory, we use a slightly different convention: when forced to - * suspend, the marker processor updates the restart point to the end of - * what it's consumed (ie, the end of the buffer) before returning FALSE. - * On resumption, cinfo->unread_marker still contains the marker code, - * but the data source will point to the next chunk of marker data. - * The marker processor must retain internal state to deal with this. - * - * Note that we don't bother to avoid duplicate trace messages if a - * suspension occurs within marker parameters. Other side effects - * require more care. - */ - - -LOCAL(boolean) -get_soi (j_decompress_ptr cinfo) -/* Process an SOI marker */ -{ - int i; - - TRACEMS(cinfo, 1, JTRC_SOI); - - if (cinfo->marker->saw_SOI) - ERREXIT(cinfo, JERR_SOI_DUPLICATE); - - /* Reset all parameters that are defined to be reset by SOI */ - - for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; - } - cinfo->restart_interval = 0; - - /* Set initial assumptions for colorspace etc */ - - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ - - cinfo->saw_JFIF_marker = FALSE; - cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ - cinfo->JFIF_minor_version = 1; - cinfo->density_unit = 0; - cinfo->X_density = 1; - cinfo->Y_density = 1; - cinfo->saw_Adobe_marker = FALSE; - cinfo->Adobe_transform = 0; - - cinfo->marker->saw_SOI = TRUE; - - return TRUE; -} - - -LOCAL(boolean) -get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) -/* Process a SOFn marker */ -{ - INT32 length; - int c, ci; - jpeg_component_info * compptr; - /* LiuSunliang added 20111209 */ - JDIMENSION image_width, image_height; - INPUT_VARS(cinfo); - - cinfo->progressive_mode = is_prog; - cinfo->arith_code = is_arith; - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); - INPUT_2BYTES(cinfo, image_height, return FALSE); - INPUT_2BYTES(cinfo, image_width, return FALSE); - INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); - - if (image_width <= JPEG_MAX_DIMENSION) - cinfo->image_width = image_width; - - if (image_height <= JPEG_MAX_DIMENSION) - cinfo->image_height = image_height; - - length -= 8; - - TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, - (int) cinfo->image_width, (int) cinfo->image_height, - cinfo->num_components); - - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_DUPLICATE); - - /* We don't support files in which the image height is initially specified */ - /* as 0 and is later redefined by DNL. As long as we have to check that, */ - /* might as well have a general sanity check. */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); - - if (length != (cinfo->num_components * 3)) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - if (cinfo->comp_info == NULL) /* do only once, even if suspend */ - cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * SIZEOF(jpeg_component_info)); - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->component_index = ci; - INPUT_BYTE(cinfo, compptr->component_id, return FALSE); - /* XYQ 2008-03-25: Adobe CMYK JPEG has serious flaw: the K channel has same component id as C channel */ - { - int i; - for (i = 0; i < ci; i ++) - if (compptr->component_id == cinfo->comp_info[i].component_id) break; - if (i < ci) - /* Found the error! We replace the id with something unlikely used elsewhere */ - compptr->component_id += 0xf0; - } - /* end of modification */ - INPUT_BYTE(cinfo, c, return FALSE); - compptr->h_samp_factor = (c >> 4) & 15; - compptr->v_samp_factor = (c ) & 15; - INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); - - TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, - compptr->component_id, compptr->h_samp_factor, - compptr->v_samp_factor, compptr->quant_tbl_no); - } - - cinfo->marker->saw_SOF = TRUE; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_sos (j_decompress_ptr cinfo) -/* Process a SOS marker */ -{ - INT32 length; - int i, ci, n, c, cc; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - if (! cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOS_NO_SOF); - - INPUT_2BYTES(cinfo, length, return FALSE); - - INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ - - TRACEMS1(cinfo, 1, JTRC_SOS, n); - - if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - cinfo->comps_in_scan = n; - - /* Collect the component-spec parameters */ - - for (i = 0; i < n; i++) { - INPUT_BYTE(cinfo, cc, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); - - /* XYQ 2008-03-25: Adobe CMYK JPEG has serious flaw: the K channel has same component id as C channel */ - { - int j; - for (j = 0; j < i; j ++) - if (cc == cinfo->cur_comp_info[j]->component_id) break; - if (j < i) - /* found the error! */ - cc += 0xf0; - } - /* end of modification */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (cc == compptr->component_id) - goto id_found; - } - - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); - - id_found: - - cinfo->cur_comp_info[i] = compptr; - compptr->dc_tbl_no = (c >> 4) & 15; - compptr->ac_tbl_no = (c ) & 15; - - TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, - compptr->dc_tbl_no, compptr->ac_tbl_no); - /* This CSi (cc) should differ from the previous CSi */ - for (ci = 0; ci < i; ci++) { - if (cinfo->cur_comp_info[ci] == compptr) - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); - } - } - - /* Collect the additional scan parameters Ss, Se, Ah/Al. */ - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ss = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Se = c; - INPUT_BYTE(cinfo, c, return FALSE); - cinfo->Ah = (c >> 4) & 15; - cinfo->Al = (c ) & 15; - - TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, - cinfo->Ah, cinfo->Al); - - /* Prepare to scan data & restart markers */ - cinfo->marker->next_restart_num = 0; - - /* Count another SOS marker */ - cinfo->input_scan_number++; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -#ifdef D_ARITH_CODING_SUPPORTED - -LOCAL(boolean) -get_dac (j_decompress_ptr cinfo) -/* Process a DAC marker */ -{ - INT32 length; - int index, val; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, index, return FALSE); - INPUT_BYTE(cinfo, val, return FALSE); - - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_DAC, index, val); - - if (index < 0 || index >= (2*NUM_ARITH_TBLS)) - ERREXIT1(cinfo, JERR_DAC_INDEX, index); - - if (index >= NUM_ARITH_TBLS) { /* define AC table */ - cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; - } else { /* define DC table */ - cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); - cinfo->arith_dc_U[index] = (UINT8) (val >> 4); - if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) - ERREXIT1(cinfo, JERR_DAC_VALUE, val); - } - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - -#else /* ! D_ARITH_CODING_SUPPORTED */ - -#define get_dac(cinfo) skip_variable(cinfo) - -#endif /* D_ARITH_CODING_SUPPORTED */ - - -LOCAL(boolean) -get_dht (j_decompress_ptr cinfo) -/* Process a DHT marker */ -{ - INT32 length; - UINT8 bits[17]; - UINT8 huffval[256]; - int i, index, count; - JHUFF_TBL **htblptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 16) { - INPUT_BYTE(cinfo, index, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DHT, index); - - bits[0] = 0; - count = 0; - for (i = 1; i <= 16; i++) { - INPUT_BYTE(cinfo, bits[i], return FALSE); - count += bits[i]; - } - - length -= 1 + 16; - - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[1], bits[2], bits[3], bits[4], - bits[5], bits[6], bits[7], bits[8]); - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[9], bits[10], bits[11], bits[12], - bits[13], bits[14], bits[15], bits[16]); - - /* Here we just do minimal validation of the counts to avoid walking - * off the end of our table space. jdhuff.c will check more carefully. - */ - if (count > 256 || ((INT32) count) > length) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - - for (i = 0; i < count; i++) - INPUT_BYTE(cinfo, huffval[i], return FALSE); - - length -= count; - - if (index & 0x10) { /* AC table definition */ - index -= 0x10; - htblptr = &cinfo->ac_huff_tbl_ptrs[index]; - } else { /* DC table definition */ - htblptr = &cinfo->dc_huff_tbl_ptrs[index]; - } - - if (index < 0 || index >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_DHT_INDEX, index); - - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_dqt (j_decompress_ptr cinfo) -/* Process a DQT marker */ -{ - INT32 length; - int n, i, prec; - unsigned int tmp; - JQUANT_TBL *quant_ptr; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - INPUT_BYTE(cinfo, n, return FALSE); - prec = n >> 4; - n &= 0x0F; - - TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); - - if (n >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, n); - - if (cinfo->quant_tbl_ptrs[n] == NULL) - cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); - quant_ptr = cinfo->quant_tbl_ptrs[n]; - - for (i = 0; i < DCTSIZE2; i++) { - if (prec) - INPUT_2BYTES(cinfo, tmp, return FALSE); - else - INPUT_BYTE(cinfo, tmp, return FALSE); - /* We convert the zigzag-order table to natural array order. */ - quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; - } - - if (cinfo->err->trace_level >= 2) { - for (i = 0; i < DCTSIZE2; i += 8) { - TRACEMS8(cinfo, 2, JTRC_QUANTVALS, - quant_ptr->quantval[i], quant_ptr->quantval[i+1], - quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], - quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], - quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); - } - } - - length -= DCTSIZE2+1; - if (prec) length -= DCTSIZE2; - } - - if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -get_dri (j_decompress_ptr cinfo) -/* Process a DRI marker */ -{ - INT32 length; - unsigned int tmp; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - - if (length != 4) - ERREXIT(cinfo, JERR_BAD_LENGTH); - - INPUT_2BYTES(cinfo, tmp, return FALSE); - - TRACEMS1(cinfo, 1, JTRC_DRI, tmp); - - cinfo->restart_interval = tmp; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Routines for processing APPn and COM markers. - * These are either saved in memory or discarded, per application request. - * APP0 and APP14 are specially checked to see if they are - * JFIF and Adobe markers, respectively. - */ - -#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ -#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ -#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ - - -LOCAL(void) -examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP0. - * Take appropriate action if it is a JFIF marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ -{ - INT32 totallen = (INT32) datalen + remaining; - - if (datalen >= APP0_DATA_LEN && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x49 && - GETJOCTET(data[3]) == 0x46 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF APP0 marker: save info */ - cinfo->saw_JFIF_marker = TRUE; - cinfo->JFIF_major_version = GETJOCTET(data[5]); - cinfo->JFIF_minor_version = GETJOCTET(data[6]); - cinfo->density_unit = GETJOCTET(data[7]); - cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); - cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); - /* Check version. - * Major version must be 1, anything else signals an incompatible change. - * (We used to treat this as an error, but now it's a nonfatal warning, - * because some bozo at Hijaak couldn't read the spec.) - * Minor version should be 0..2, but process anyway if newer. - */ - if (cinfo->JFIF_major_version != 1) - WARNMS2(cinfo, JWRN_JFIF_MAJOR, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version); - /* Generate trace messages */ - TRACEMS5(cinfo, 1, JTRC_JFIF, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version, - cinfo->X_density, cinfo->Y_density, cinfo->density_unit); - /* Validate thumbnail dimensions and issue appropriate messages */ - if (GETJOCTET(data[12]) | GETJOCTET(data[13])) - TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, - GETJOCTET(data[12]), GETJOCTET(data[13])); - totallen -= APP0_DATA_LEN; - if (totallen != - ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) - TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); - } else if (datalen >= 6 && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x58 && - GETJOCTET(data[3]) == 0x58 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF "JFXX" extension APP0 marker */ - /* The library doesn't actually do anything with these, - * but we try to produce a helpful trace message. - */ - switch (GETJOCTET(data[5])) { - case 0x10: - TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); - break; - case 0x11: - TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); - break; - case 0x13: - TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); - break; - default: - TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, - GETJOCTET(data[5]), (int) totallen); - break; - } - } else { - /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); - } -} - - -LOCAL(void) -examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP14. - * Take appropriate action if it is an Adobe marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ -{ - unsigned int version, flags0, flags1, transform; - - if (datalen >= APP14_DATA_LEN && - GETJOCTET(data[0]) == 0x41 && - GETJOCTET(data[1]) == 0x64 && - GETJOCTET(data[2]) == 0x6F && - GETJOCTET(data[3]) == 0x62 && - GETJOCTET(data[4]) == 0x65) { - /* Found Adobe APP14 marker */ - version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); - flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); - flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); - transform = GETJOCTET(data[11]); - TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); - cinfo->saw_Adobe_marker = TRUE; - cinfo->Adobe_transform = (UINT8) transform; - } else { - /* Start of APP14 does not match "Adobe", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); - } -} - - -METHODDEF(boolean) -get_interesting_appn (j_decompress_ptr cinfo) -/* Process an APP0 or APP14 marker without saving it */ -{ - INT32 length; - JOCTET b[APPN_DATA_LEN]; - unsigned int i, numtoread; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - /* get the interesting part of the marker data */ - if (length >= APPN_DATA_LEN) - numtoread = APPN_DATA_LEN; - else if (length > 0) - numtoread = (unsigned int) length; - else - numtoread = 0; - for (i = 0; i < numtoread; i++) - INPUT_BYTE(cinfo, b[i], return FALSE); - length -= numtoread; - - /* process it */ - switch (cinfo->unread_marker) { - case M_APP0: - examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); - break; - case M_APP14: - examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); - break; - default: - /* can't get here unless jpeg_save_markers chooses wrong processor */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - - /* skip any remaining data -- could be lots */ - INPUT_SYNC(cinfo); - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -#ifdef SAVE_MARKERS_SUPPORTED - -METHODDEF(boolean) -save_marker (j_decompress_ptr cinfo) -/* Save an APPn or COM marker into the marker list */ -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - jpeg_saved_marker_ptr cur_marker = marker->cur_marker; - unsigned int bytes_read, data_length; - JOCTET FAR * data; - INT32 length = 0; - INPUT_VARS(cinfo); - - if (cur_marker == NULL) { - /* begin reading a marker */ - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - if (length >= 0) { /* watch out for bogus length word */ - /* figure out how much we want to save */ - unsigned int limit; - if (cinfo->unread_marker == (int) M_COM) - limit = marker->length_limit_COM; - else - limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; - if ((unsigned int) length < limit) - limit = (unsigned int) length; - /* allocate and initialize the marker item */ - cur_marker = (jpeg_saved_marker_ptr) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(struct jpeg_marker_struct) + limit); - cur_marker->next = NULL; - cur_marker->marker = (UINT8) cinfo->unread_marker; - cur_marker->original_length = (unsigned int) length; - cur_marker->data_length = limit; - /* data area is just beyond the jpeg_marker_struct */ - data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); - marker->cur_marker = cur_marker; - marker->bytes_read = 0; - bytes_read = 0; - data_length = limit; - } else { - /* deal with bogus length word */ - bytes_read = data_length = 0; - data = NULL; - } - } else { - /* resume reading a marker */ - bytes_read = marker->bytes_read; - data_length = cur_marker->data_length; - data = cur_marker->data + bytes_read; - } - - while (bytes_read < data_length) { - INPUT_SYNC(cinfo); /* move the restart point to here */ - marker->bytes_read = bytes_read; - /* If there's not at least one byte in buffer, suspend */ - MAKE_BYTE_AVAIL(cinfo, return FALSE); - /* Copy bytes with reasonable rapidity */ - while (bytes_read < data_length && bytes_in_buffer > 0) { - *data++ = *next_input_byte++; - bytes_in_buffer--; - bytes_read++; - } - } - - /* Done reading what we want to read */ - if (cur_marker != NULL) { /* will be NULL if bogus length word */ - /* Add new marker to end of list */ - if (cinfo->marker_list == NULL) { - cinfo->marker_list = cur_marker; - } else { - jpeg_saved_marker_ptr prev = cinfo->marker_list; - while (prev->next != NULL) - prev = prev->next; - prev->next = cur_marker; - } - /* Reset pointer & calc remaining data length */ - data = cur_marker->data; - length = cur_marker->original_length - data_length; - } - /* Reset to initial state for next marker */ - marker->cur_marker = NULL; - - /* Process the marker if interesting; else just make a generic trace msg */ - switch (cinfo->unread_marker) { - case M_APP0: - examine_app0(cinfo, data, data_length, length); - break; - case M_APP14: - examine_app14(cinfo, data, data_length, length); - break; - default: - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, - (int) (data_length + length)); - break; - } - - /* skip any remaining data -- could be lots */ - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - -#endif /* SAVE_MARKERS_SUPPORTED */ - - -METHODDEF(boolean) -skip_variable (j_decompress_ptr cinfo) -/* Skip over an unknown or uninteresting variable-length marker */ -{ - INT32 length; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); - - INPUT_SYNC(cinfo); /* do before skip_input_data */ - if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); - - return TRUE; -} - - -/* - * Find the next JPEG marker, save it in cinfo->unread_marker. - * Returns FALSE if had to suspend before reaching a marker; - * in that case cinfo->unread_marker is unchanged. - * - * Note that the result might not be a valid marker code, - * but it will never be 0 or FF. - */ - -LOCAL(boolean) -next_marker (j_decompress_ptr cinfo) -{ - int c; - INPUT_VARS(cinfo); - - for (;;) { - INPUT_BYTE(cinfo, c, return FALSE); - /* Skip any non-FF bytes. - * This may look a bit inefficient, but it will not occur in a valid file. - * We sync after each discarded byte so that a suspending data source - * can discard the byte from its buffer. - */ - while (c != 0xFF) { - cinfo->marker->discarded_bytes++; - INPUT_SYNC(cinfo); - INPUT_BYTE(cinfo, c, return FALSE); - } - /* This loop swallows any duplicate FF bytes. Extra FFs are legal as - * pad bytes, so don't count them in discarded_bytes. We assume there - * will not be so many consecutive FF bytes as to overflow a suspending - * data source's input buffer. - */ - do { - INPUT_BYTE(cinfo, c, return FALSE); - } while (c == 0xFF); - if (c != 0) - break; /* found a valid marker, exit loop */ - /* Reach here if we found a stuffed-zero data sequence (FF/00). - * Discard it and loop back to try again. - */ - cinfo->marker->discarded_bytes += 2; - INPUT_SYNC(cinfo); - } - - if (cinfo->marker->discarded_bytes != 0) { - WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); - cinfo->marker->discarded_bytes = 0; - } - - cinfo->unread_marker = c; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -LOCAL(boolean) -first_marker (j_decompress_ptr cinfo) -/* Like next_marker, but used to obtain the initial SOI marker. */ -/* For this marker, we do not allow preceding garbage or fill; otherwise, - * we might well scan an entire input file before realizing it ain't JPEG. - * If an application wants to process non-JFIF files, it must seek to the - * SOI before calling the JPEG library. - */ -{ - int c, c2; - INPUT_VARS(cinfo); - - INPUT_BYTE(cinfo, c, return FALSE); - INPUT_BYTE(cinfo, c2, return FALSE); - if (c != 0xFF || c2 != (int) M_SOI) - ERREXIT2(cinfo, JERR_NO_SOI, c, c2); - - cinfo->unread_marker = c2; - - INPUT_SYNC(cinfo); - return TRUE; -} - - -/* - * Read markers until SOS or EOI. - * - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - -METHODDEF(int) -read_markers (j_decompress_ptr cinfo) -{ - /* Outer loop repeats once for each marker. */ - for (;;) { - /* Collect the marker proper, unless we already did. */ - /* NB: first_marker() enforces the requirement that SOI appear first. */ - if (cinfo->unread_marker == 0) { - if (! cinfo->marker->saw_SOI) { - if (! first_marker(cinfo)) - return JPEG_SUSPENDED; - } else { - if (! next_marker(cinfo)) - return JPEG_SUSPENDED; - } - } - /* At this point cinfo->unread_marker contains the marker code and the - * input point is just past the marker proper, but before any parameters. - * A suspension will cause us to return with this state still true. - */ - switch (cinfo->unread_marker) { - case M_SOI: - if (! get_soi(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_SOF0: /* Baseline */ - case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, TRUE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, TRUE)) - return JPEG_SUSPENDED; - break; - - case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, TRUE, TRUE)) - return JPEG_SUSPENDED; - break; - - /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ - case M_SOF5: /* Differential sequential, Huffman */ - case M_SOF6: /* Differential progressive, Huffman */ - case M_SOF7: /* Differential lossless, Huffman */ - case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ - case M_SOF13: /* Differential sequential, arithmetic */ - case M_SOF14: /* Differential progressive, arithmetic */ - case M_SOF15: /* Differential lossless, arithmetic */ - ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); - break; - - case M_SOS: - if (! get_sos(cinfo)) - return JPEG_SUSPENDED; - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_SOS; - - case M_EOI: - TRACEMS(cinfo, 1, JTRC_EOI); - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_EOI; - - case M_DAC: - if (! get_dac(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DHT: - if (! get_dht(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DQT: - if (! get_dqt(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_DRI: - if (! get_dri(cinfo)) - return JPEG_SUSPENDED; - break; - - case M_APP0: - case M_APP1: - case M_APP2: - case M_APP3: - case M_APP4: - case M_APP5: - case M_APP6: - case M_APP7: - case M_APP8: - case M_APP9: - case M_APP10: - case M_APP11: - case M_APP12: - case M_APP13: - case M_APP14: - case M_APP15: - if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ - cinfo->unread_marker - (int) M_APP0]) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_COM: - if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) - return JPEG_SUSPENDED; - break; - - case M_RST0: /* these are all parameterless */ - case M_RST1: - case M_RST2: - case M_RST3: - case M_RST4: - case M_RST5: - case M_RST6: - case M_RST7: - case M_TEM: - TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); - break; - - case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ - if (! skip_variable(cinfo)) - return JPEG_SUSPENDED; - break; - - default: /* must be DHP, EXP, JPGn, or RESn */ - /* For now, we treat the reserved markers as fatal errors since they are - * likely to be used to signal incompatible JPEG Part 3 extensions. - * Once the JPEG 3 version-number marker is well defined, this code - * ought to change! - */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - /* Successfully processed marker, so reset state variable */ - cinfo->unread_marker = 0; - } /* end loop */ -} - - -/* - * Read a restart marker, which is expected to appear next in the datastream; - * if the marker is not there, take appropriate recovery action. - * Returns FALSE if suspension is required. - * - * This is called by the entropy decoder after it has read an appropriate - * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder - * has already read a marker from the data source. Under normal conditions - * cinfo->unread_marker will be reset to 0 before returning; if not reset, - * it holds a marker which the decoder will be unable to read past. - */ - -METHODDEF(boolean) -read_restart_marker (j_decompress_ptr cinfo) -{ - /* Obtain a marker unless we already did. */ - /* Note that next_marker will complain if it skips any data. */ - if (cinfo->unread_marker == 0) { - if (! next_marker(cinfo)) - return FALSE; - } - - if (cinfo->unread_marker == - ((int) M_RST0 + cinfo->marker->next_restart_num)) { - /* Normal case --- swallow the marker and let entropy decoder continue */ - TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); - cinfo->unread_marker = 0; - } else { - /* Uh-oh, the restart markers have been messed up. */ - /* Let the data source manager determine how to resync. */ - if (! (*cinfo->src->resync_to_restart) (cinfo, - cinfo->marker->next_restart_num)) - return FALSE; - } - - /* Update next-restart state */ - cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; - - return TRUE; -} - - -/* - * This is the default resync_to_restart method for data source managers - * to use if they don't have any better approach. Some data source managers - * may be able to back up, or may have additional knowledge about the data - * which permits a more intelligent recovery strategy; such managers would - * presumably supply their own resync method. - * - * read_restart_marker calls resync_to_restart if it finds a marker other than - * the restart marker it was expecting. (This code is *not* used unless - * a nonzero restart interval has been declared.) cinfo->unread_marker is - * the marker code actually found (might be anything, except 0 or FF). - * The desired restart marker number (0..7) is passed as a parameter. - * This routine is supposed to apply whatever error recovery strategy seems - * appropriate in order to position the input stream to the next data segment. - * Note that cinfo->unread_marker is treated as a marker appearing before - * the current data-source input point; usually it should be reset to zero - * before returning. - * Returns FALSE if suspension is required. - * - * This implementation is substantially constrained by wanting to treat the - * input as a data stream; this means we can't back up. Therefore, we have - * only the following actions to work with: - * 1. Simply discard the marker and let the entropy decoder resume at next - * byte of file. - * 2. Read forward until we find another marker, discarding intervening - * data. (In theory we could look ahead within the current bufferload, - * without having to discard data if we don't find the desired marker. - * This idea is not implemented here, in part because it makes behavior - * dependent on buffer size and chance buffer-boundary positions.) - * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). - * This will cause the entropy decoder to process an empty data segment, - * inserting dummy zeroes, and then we will reprocess the marker. - * - * #2 is appropriate if we think the desired marker lies ahead, while #3 is - * appropriate if the found marker is a future restart marker (indicating - * that we have missed the desired restart marker, probably because it got - * corrupted). - * We apply #2 or #3 if the found marker is a restart marker no more than - * two counts behind or ahead of the expected one. We also apply #2 if the - * found marker is not a legal JPEG marker code (it's certainly bogus data). - * If the found marker is a restart marker more than 2 counts away, we do #1 - * (too much risk that the marker is erroneous; with luck we will be able to - * resync at some future point). - * For any valid non-restart JPEG marker, we apply #3. This keeps us from - * overrunning the end of a scan. An implementation limited to single-scan - * files might find it better to apply #2 for markers other than EOI, since - * any other marker would have to be bogus data in that case. - */ - -GLOBAL(boolean) -jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) -{ - int marker = cinfo->unread_marker; - int action = 1; - - /* Always put up a warning. */ - WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - - /* Outer loop handles repeated decision after scanning forward. */ - for (;;) { - if (marker < (int) M_SOF0) - action = 2; /* invalid marker */ - else if (marker < (int) M_RST0 || marker > (int) M_RST7) - action = 3; /* valid non-restart marker */ - else { - if (marker == ((int) M_RST0 + ((desired+1) & 7)) || - marker == ((int) M_RST0 + ((desired+2) & 7))) - action = 3; /* one of the next two expected restarts */ - else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || - marker == ((int) M_RST0 + ((desired-2) & 7))) - action = 2; /* a prior restart, so advance */ - else - action = 1; /* desired restart or too far away */ - } - TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); - switch (action) { - case 1: - /* Discard marker and let entropy decoder resume processing. */ - cinfo->unread_marker = 0; - return TRUE; - case 2: - /* Scan to the next marker, and repeat the decision loop. */ - if (! next_marker(cinfo)) - return FALSE; - marker = cinfo->unread_marker; - break; - case 3: - /* Return without advancing past this marker. */ - /* Entropy decoder will be forced to process an empty segment. */ - return TRUE; - } - } /* end loop */ -} - - -/* - * Reset marker processing state to begin a fresh datastream. - */ - -METHODDEF(void) -reset_marker_reader (j_decompress_ptr cinfo) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - cinfo->comp_info = NULL; /* until allocated by get_sof */ - cinfo->input_scan_number = 0; /* no SOS seen yet */ - cinfo->unread_marker = 0; /* no pending marker */ - marker->pub.saw_SOI = FALSE; /* set internal state too */ - marker->pub.saw_SOF = FALSE; - marker->pub.discarded_bytes = 0; - marker->cur_marker = NULL; -} - - -/* - * Initialize the marker reader module. - * This is called only once, when the decompression object is created. - */ - -GLOBAL(void) -jinit_marker_reader (j_decompress_ptr cinfo) -{ - my_marker_ptr marker; - int i; - - /* Create subobject in permanent pool */ - marker = (my_marker_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_marker_reader)); - cinfo->marker = (struct jpeg_marker_reader *) marker; - /* Initialize public method pointers */ - marker->pub.reset_marker_reader = reset_marker_reader; - marker->pub.read_markers = read_markers; - marker->pub.read_restart_marker = read_restart_marker; - /* Initialize COM/APPn processing. - * By default, we examine and then discard APP0 and APP14, - * but simply discard COM and all other APPn. - */ - marker->process_COM = skip_variable; - marker->length_limit_COM = 0; - for (i = 0; i < 16; i++) { - marker->process_APPn[i] = skip_variable; - marker->length_limit_APPn[i] = 0; - } - marker->process_APPn[0] = get_interesting_appn; - marker->process_APPn[14] = get_interesting_appn; - /* Reset marker processing state */ - reset_marker_reader(cinfo); -} - - -/* - * Control saving of COM and APPn markers into marker_list. - */ - -#ifdef SAVE_MARKERS_SUPPORTED - -GLOBAL(void) -jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - long maxlength; - jpeg_marker_parser_method processor; - - /* Length limit mustn't be larger than what we can allocate - * (should only be a concern in a 16-bit environment). - */ - maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); - if (((long) length_limit) > maxlength) - length_limit = (unsigned int) maxlength; - - /* Choose processor routine to use. - * APP0/APP14 have special requirements. - */ - if (length_limit) { - processor = save_marker; - /* If saving APP0/APP14, save at least enough for our internal use. */ - if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) - length_limit = APP0_DATA_LEN; - else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) - length_limit = APP14_DATA_LEN; - } else { - processor = skip_variable; - /* If discarding APP0/APP14, use our regular on-the-fly processor. */ - if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) - processor = get_interesting_appn; - } - - if (marker_code == (int) M_COM) { - marker->process_COM = processor; - marker->length_limit_COM = length_limit; - } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { - marker->process_APPn[marker_code - (int) M_APP0] = processor; - marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; - } else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} - -#endif /* SAVE_MARKERS_SUPPORTED */ - - -/* - * Install a special processing method for COM or APPn markers. - */ - -GLOBAL(void) -jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine) -{ - my_marker_ptr marker = (my_marker_ptr) cinfo->marker; - - if (marker_code == (int) M_COM) - marker->process_COM = routine; - else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) - marker->process_APPn[marker_code - (int) M_APP0] = routine; - else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); -} diff --git a/third_party/libjpeg/fpdfapi_jdmaster.c b/third_party/libjpeg/fpdfapi_jdmaster.c deleted file mode 100644 index 2802c5b7b29757e27b561ccccedba169deb9b42c..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdmaster.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * jdmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains master control logic for the JPEG decompressor. - * These routines are concerned with selecting the modules to be executed - * and with determining the number of passes and the work to be done in each - * pass. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private state */ - -typedef struct { - struct jpeg_decomp_master pub; /* public fields */ - - int pass_number; /* # of passes completed */ - - boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ - - /* Saved references to initialized quantizer modules, - * in case we need to switch modes. - */ - struct jpeg_color_quantizer * quantizer_1pass; - struct jpeg_color_quantizer * quantizer_2pass; -} my_decomp_master; - -typedef my_decomp_master * my_master_ptr; - - -/* - * Determine whether merged upsample/color conversion should be used. - * CRUCIAL: this must match the actual capabilities of jdmerge.c! - */ - -LOCAL(boolean) -use_merged_upsample (j_decompress_ptr cinfo) -{ -#ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling */ - if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) - return FALSE; - /* jdmerge.c only supports YCC=>RGB color conversion */ - if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || - cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE) - return FALSE; - /* and it only handles 2h1v or 2h2v sampling ratios */ - if (cinfo->comp_info[0].h_samp_factor != 2 || - cinfo->comp_info[1].h_samp_factor != 1 || - cinfo->comp_info[2].h_samp_factor != 1 || - cinfo->comp_info[0].v_samp_factor > 2 || - cinfo->comp_info[1].v_samp_factor != 1 || - cinfo->comp_info[2].v_samp_factor != 1) - return FALSE; - /* furthermore, it doesn't work if we've scaled the IDCTs differently */ - if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) - return FALSE; - /* ??? also need to test for upsample-time rescaling, when & if supported */ - return TRUE; /* by golly, it'll work... */ -#else - return FALSE; -#endif -} - - -/* - * Compute output image dimensions and related values. - * NOTE: this is exported for possible use by application. - * Hence it mustn't do anything that can't be done twice. - * Also note that it may be called before the master module is initialized! - */ - -GLOBAL(void) -jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase */ -{ -#ifdef IDCT_SCALING_SUPPORTED - int ci; - jpeg_component_info *compptr; -#endif - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_READY) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - -#ifdef IDCT_SCALING_SUPPORTED - - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * 8 <= cinfo->scale_denom) { - /* Provide 1/8 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 8L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 8L); - cinfo->min_DCT_scaled_size = 1; - } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { - /* Provide 1/4 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 4L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 4L); - cinfo->min_DCT_scaled_size = 2; - } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { - /* Provide 1/2 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 2L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 2L); - cinfo->min_DCT_scaled_size = 4; - } else { - /* Provide 1/1 scaling */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - cinfo->min_DCT_scaled_size = DCTSIZE; - } - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code assumes that the supported DCT scalings are powers of 2. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->min_DCT_scaled_size; - while (ssize < DCTSIZE && - (compptr->h_samp_factor * ssize * 2 <= - cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && - (compptr->v_samp_factor * ssize * 2 <= - cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { - ssize = ssize * 2; - } - compptr->DCT_scaled_size = ssize; - } - - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - } - -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ - - /* Report number of components in selected colorspace. */ - /* Probably this should be in the color conversion module... */ - switch (cinfo->out_color_space) { - case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - break; - case JCS_RGB: -#if RGB_PIXELSIZE != 3 - cinfo->out_color_components = RGB_PIXELSIZE; - break; -#endif /* else share code with YCbCr */ - case JCS_YCbCr: - cinfo->out_color_components = 3; - break; - case JCS_CMYK: - case JCS_YCCK: - cinfo->out_color_components = 4; - break; - default: /* else must be same colorspace as in file */ - cinfo->out_color_components = cinfo->num_components; - break; - } - cinfo->output_components = (cinfo->quantize_colors ? 1 : - cinfo->out_color_components); - - /* See if upsampler will want to emit more than one row at a time */ - if (use_merged_upsample(cinfo)) - cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; - else - cinfo->rec_outbuf_height = 1; -} - - -/* - * Several decompression processes need to range-limit values to the range - * 0..MAXJSAMPLE; the input value may fall somewhat outside this range - * due to noise introduced by quantization, roundoff error, etc. These - * processes are inner loops and need to be as fast as possible. On most - * machines, particularly CPUs with pipelines or instruction prefetch, - * a (subscript-check-less) C table lookup - * x = sample_range_limit[x]; - * is faster than explicit tests - * if (x < 0) x = 0; - * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; - * These processes all use a common table prepared by the routine below. - * - * For most steps we can mathematically guarantee that the initial value - * of x is within MAXJSAMPLE+1 of the legal range, so a table running from - * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial - * limiting step (just after the IDCT), a wildly out-of-range value is - * possible if the input data is corrupt. To avoid any chance of indexing - * off the end of memory and getting a bad-pointer trap, we perform the - * post-IDCT limiting thus: - * x = range_limit[x & MASK]; - * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit - * samples. Under normal circumstances this is more than enough range and - * a correct output will be generated; with bogus input data the mask will - * cause wraparound, and we will safely generate a bogus-but-in-range output. - * For the post-IDCT step, we want to convert the data from signed to unsigned - * representation by adding CENTERJSAMPLE at the same time that we limit it. - * So the post-IDCT limiting table ends up looking like this: - * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, - * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0,1,...,CENTERJSAMPLE-1 - * Negative inputs select values from the upper half of the table after - * masking. - * - * We can save some space by overlapping the start of the post-IDCT table - * with the simpler range limiting table. The post-IDCT table begins at - * sample_range_limit + CENTERJSAMPLE. - * - * Note that the table is allocated in near data space on PCs; it's small - * enough and used often enough to justify this. - */ - -LOCAL(void) -prepare_range_limit_table (j_decompress_ptr cinfo) -/* Allocate and fill in the sample_range_limit table */ -{ - JSAMPLE * table; - int i; - - table = (JSAMPLE *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ - cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ - for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE) i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) - table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - MEMZERO(table + (2 * (MAXJSAMPLE+1)), - (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); -} - - -/* - * Master selection of decompression modules. - * This is done once at jpeg_start_decompress time. We determine - * which modules will be used and give them appropriate initialization calls. - * We also initialize the decompressor input side to begin consuming data. - * - * Since jpeg_read_header has finished, we know what is in the SOF - * and (first) SOS markers. We also have all the application parameter - * settings. - */ - -LOCAL(void) -master_selection (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - boolean use_c_buffer; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - /* Initialize dimensions and other stuff */ - jpeg_calc_output_dimensions(cinfo); - prepare_range_limit_table(cinfo); - - /* Width of an output scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* Initialize my private state */ - master->pass_number = 0; - master->using_merged_upsample = use_merged_upsample(cinfo); - - /* Color quantizer selection */ - master->quantizer_1pass = NULL; - master->quantizer_2pass = NULL; - /* No mode changes if not using buffered-image mode. */ - if (! cinfo->quantize_colors || ! cinfo->buffered_image) { - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - } - if (cinfo->quantize_colors) { - if (cinfo->raw_data_out) - ERREXIT(cinfo, JERR_NOTIMPL); - /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { - cinfo->enable_1pass_quant = TRUE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - cinfo->colormap = NULL; - } else if (cinfo->colormap != NULL) { - cinfo->enable_external_quant = TRUE; - } else if (cinfo->two_pass_quantize) { - cinfo->enable_2pass_quant = TRUE; - } else { - cinfo->enable_1pass_quant = TRUE; - } - - if (cinfo->enable_1pass_quant) { -#ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); - master->quantizer_1pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - - /* We use the 2-pass code to map to external colormaps. */ - if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { -#ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); - master->quantizer_2pass = cinfo->cquantize; -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } - /* If both quantizers are initialized, the 2-pass one is left active; - * this is necessary for starting with quantization to an external map. - */ - } - - /* Post-processing: in particular, color conversion first */ - if (! cinfo->raw_data_out) { - if (master->using_merged_upsample) { -#ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); - } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); - } - /* Inverse DCT */ - jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); - } - - /* Initialize principal buffer controllers. */ - use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; - jinit_d_coef_controller(cinfo, use_c_buffer); - - if (! cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - -#ifdef D_MULTISCAN_FILES_SUPPORTED - /* If jpeg_start_decompress will read the whole file, initialize - * progress monitoring appropriately. The input step is counted - * as one pass. - */ - if (cinfo->progress != NULL && ! cinfo->buffered_image && - cinfo->inputctl->has_multiple_scans) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); - /* Count the input pass as done */ - master->pass_number++; - } -#endif /* D_MULTISCAN_FILES_SUPPORTED */ -} - - -/* - * Per-pass setup. - * This is called at the beginning of each output pass. We determine which - * modules will be active during this pass and give them appropriate - * start_pass calls. We also set is_dummy_pass to indicate whether this - * is a "real" output pass or a dummy pass for color quantization. - * (In the latter case, jdapistd.c will crank the pass to completion.) - */ - -METHODDEF(void) -prepare_for_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (master->pub.is_dummy_pass) { -#ifdef QUANT_2PASS_SUPPORTED - /* Final pass of 2-pass quantization */ - master->pub.is_dummy_pass = FALSE; - (*cinfo->cquantize->start_pass) (cinfo, FALSE); - (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); - (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - if (cinfo->quantize_colors && cinfo->colormap == NULL) { - /* Select new quantization method */ - if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { - cinfo->cquantize = master->quantizer_2pass; - master->pub.is_dummy_pass = TRUE; - } else if (cinfo->enable_1pass_quant) { - cinfo->cquantize = master->quantizer_1pass; - } else { - ERREXIT(cinfo, JERR_MODE_CHANGE); - } - } - (*cinfo->idct->start_pass) (cinfo); - (*cinfo->coef->start_output_pass) (cinfo); - if (! cinfo->raw_data_out) { - if (! master->using_merged_upsample) - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->upsample->start_pass) (cinfo); - if (cinfo->quantize_colors) - (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); - (*cinfo->post->start_pass) (cinfo, - (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - } - } - - /* Set up progress monitor's pass info if present */ - if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->pass_number + - (master->pub.is_dummy_pass ? 2 : 1); - /* In buffered-image mode, we assume one more output pass if EOI not - * yet reached, but no more passes if EOI has been reached. - */ - if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { - cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); - } - } -} - - -/* - * Finish up at end of an output pass. - */ - -METHODDEF(void) -finish_output_pass (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - if (cinfo->quantize_colors) - (*cinfo->cquantize->finish_pass) (cinfo); - master->pass_number++; -} - - -#ifdef D_MULTISCAN_FILES_SUPPORTED - -/* - * Switch to a new external colormap between output passes. - */ - -GLOBAL(void) -jpeg_new_colormap (j_decompress_ptr cinfo) -{ - my_master_ptr master = (my_master_ptr) cinfo->master; - - /* Prevent application from calling me at wrong times */ - if (cinfo->global_state != DSTATE_BUFIMAGE) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - if (cinfo->quantize_colors && cinfo->enable_external_quant && - cinfo->colormap != NULL) { - /* Select 2-pass quantizer for external colormap use */ - cinfo->cquantize = master->quantizer_2pass; - /* Notify quantizer of colormap change */ - (*cinfo->cquantize->new_color_map) (cinfo); - master->pub.is_dummy_pass = FALSE; /* just in case */ - } else - ERREXIT(cinfo, JERR_MODE_CHANGE); -} - -#endif /* D_MULTISCAN_FILES_SUPPORTED */ - - -/* - * Initialize master decompression control and select active modules. - * This is performed at the start of jpeg_start_decompress. - */ - -GLOBAL(void) -jinit_master_decompress (j_decompress_ptr cinfo) -{ - my_master_ptr master; - - master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_decomp_master)); - cinfo->master = (struct jpeg_decomp_master *) master; - master->pub.prepare_for_output_pass = prepare_for_output_pass; - master->pub.finish_output_pass = finish_output_pass; - - master->pub.is_dummy_pass = FALSE; - - master_selection(cinfo); -} diff --git a/third_party/libjpeg/fpdfapi_jdmerge.c b/third_party/libjpeg/fpdfapi_jdmerge.c deleted file mode 100644 index a175a56bf793a3e762ab963616a8b42e9bd5f715..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdmerge.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * jdmerge.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains code for merged upsampling/color conversion. - * - * This file combines functions from jdsample.c and jdcolor.c; - * read those files first to understand what's going on. - * - * When the chroma components are to be upsampled by simple replication - * (ie, box filtering), we can save some work in color conversion by - * calculating all the output pixels corresponding to a pair of chroma - * samples at one time. In the conversion equations - * R = Y + K1 * Cr - * G = Y + K2 * Cb + K3 * Cr - * B = Y + K4 * Cb - * only the Y term varies among the group of pixels corresponding to a pair - * of chroma samples, so the rest of the terms can be calculated just once. - * At typical sampling ratios, this eliminates half or three-quarters of the - * multiplications needed for color conversion. - * - * This file currently provides implementations for the following cases: - * YCbCr => RGB color conversion only. - * Sampling ratios of 2h1v or 2h2v. - * No scaling needed at upsample time. - * Corner-aligned (non-CCIR601) sampling alignment. - * Other special cases could be added, but in most applications these are - * the only common cases. (For uncommon cases we fall back on the more - * general code in jdsample.c and jdcolor.c.) - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - -#ifdef UPSAMPLE_MERGING_SUPPORTED - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Pointer to routine to do actual upsampling/conversion of one row group */ - JMETHOD(void, upmethod, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf)); - - /* Private state for YCC->RGB conversion */ - int * Cr_r_tab; /* => table for Cr to R conversion */ - int * Cb_b_tab; /* => table for Cb to B conversion */ - INT32 * Cr_g_tab; /* => table for Cr to G conversion */ - INT32 * Cb_g_tab; /* => table for Cb to G conversion */ - - /* For 2:1 vertical sampling, we produce two output rows at a time. - * We need a "spare" row buffer to hold the second output row if the - * application provides just a one-row buffer; we also use the spare - * to discard the dummy last row if the image height is odd. - */ - JSAMPROW spare_row; - boolean spare_full; /* T if spare buffer is occupied */ - - JDIMENSION out_row_width; /* samples per output row */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - -#define SCALEBITS 16 /* speediest right-shift on some machines */ -#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) -#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) - - -/* - * Initialize tables for YCC->RGB colorspace conversion. - * This is taken directly from jdcolor.c; see that file for more info. - */ - -LOCAL(void) -build_ycc_rgb_table (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int i; - INT32 x; - SHIFT_TEMPS - - upsample->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); - upsample->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - upsample->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); - - for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; - } -} - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF(void) -start_pass_merged_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the spare buffer empty */ - upsample->spare_full = FALSE; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * The control routine just handles the row buffering considerations. - */ - -METHODDEF(void) -merged_2v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 2:1 vertical sampling case: may need a spare row. */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPROW work_ptrs[2]; - JDIMENSION num_rows; /* number of rows returned to caller */ - - if (upsample->spare_full) { - /* If we have a spare row saved from a previous cycle, just return it. */ - jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, - 1, upsample->out_row_width); - num_rows = 1; - upsample->spare_full = FALSE; - } else { - /* Figure number of rows to return to caller. */ - num_rows = 2; - /* Not more than the distance to the end of the image. */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - /* Create output pointer array for upsampler. */ - work_ptrs[0] = output_buf[*out_row_ctr]; - if (num_rows > 1) { - work_ptrs[1] = output_buf[*out_row_ctr + 1]; - } else { - work_ptrs[1] = upsample->spare_row; - upsample->spare_full = TRUE; - } - /* Now do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); - } - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (! upsample->spare_full) - (*in_row_group_ctr)++; -} - - -METHODDEF(void) -merged_1v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 1:1 vertical sampling case: much easier, never need a spare row. */ -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Just do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, - output_buf + *out_row_ctr); - /* Adjust counts */ - (*out_row_ctr)++; - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by the control routines to do - * the actual upsampling/conversion. One row group is processed per call. - * - * Note: since we may be writing directly into application-supplied buffers, - * we have to be honest about the output width; we can't assume the buffer - * has been rounded up to an even width. - */ - - -/* - * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. - */ - -METHODDEF(void) -h2v1_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr; - JSAMPROW inptr0, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr0 = input_buf[0][in_row_group_ctr]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr = output_buf[0]; - /* Loop for each pair of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 2 Y values and emit 2 pixels */ - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr0); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - } -} - - -/* - * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. - */ - -METHODDEF(void) -h2v2_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - register int y, cred, cgreen, cblue; - int cb, cr; - register JSAMPROW outptr0, outptr1; - JSAMPROW inptr00, inptr01, inptr1, inptr2; - JDIMENSION col; - /* copy these pointers into registers if possible */ - register JSAMPLE * range_limit = cinfo->sample_range_limit; - int * Crrtab = upsample->Cr_r_tab; - int * Cbbtab = upsample->Cb_b_tab; - INT32 * Crgtab = upsample->Cr_g_tab; - INT32 * Cbgtab = upsample->Cb_g_tab; - SHIFT_TEMPS - - inptr00 = input_buf[0][in_row_group_ctr*2]; - inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; - inptr1 = input_buf[1][in_row_group_ctr]; - inptr2 = input_buf[2][in_row_group_ctr]; - outptr0 = output_buf[0]; - outptr1 = output_buf[1]; - /* Loop for each group of output pixels */ - for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 4 Y values and emit 4 pixels */ - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - } - /* If image width is odd, do the last output column separately */ - if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr00); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - y = GETJSAMPLE(*inptr01); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - } -} - - -/* - * Module initialization routine for merged upsampling/color conversion. - * - * NB: this is called under the conditions determined by use_merged_upsample() - * in jdmaster.c. That routine MUST correspond to the actual capabilities - * of this module; no safety checks are made here. - */ - -GLOBAL(void) -jinit_merged_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; - upsample->pub.start_pass = start_pass_merged_upsample; - upsample->pub.need_context_rows = FALSE; - - upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; - - if (cinfo->max_v_samp_factor == 2) { - upsample->pub.upsample = merged_2v_upsample; - upsample->upmethod = h2v2_merged_upsample; - /* Allocate a spare row buffer */ - upsample->spare_row = (JSAMPROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); - } else { - upsample->pub.upsample = merged_1v_upsample; - upsample->upmethod = h2v1_merged_upsample; - /* No spare row needed */ - upsample->spare_row = NULL; - } - - build_ycc_rgb_table(cinfo); -} - -#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jdphuff.c b/third_party/libjpeg/fpdfapi_jdphuff.c deleted file mode 100644 index 22678099451a7f606c5cb2652940d569ba7885d5..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdphuff.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * jdphuff.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines for progressive JPEG. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdhuff.c */ - - -#ifdef D_PROGRESSIVE_SUPPORTED - -/* - * Expanded entropy decoder object for progressive Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).EOBRUN = (src).EOBRUN, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ -} phuff_entropy_decoder; - -typedef phuff_entropy_decoder * phuff_entropy_ptr; - -/* Forward declarations */ -METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_phuff_decoder (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band, bad; - int ci, coefi, tbl; - int *coef_bit_ptr; - jpeg_component_info * compptr; - - is_DC_band = (cinfo->Ss == 0); - - /* Validate scan parameters */ - bad = FALSE; - if (is_DC_band) { - if (cinfo->Se != 0) - bad = TRUE; - } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) - bad = TRUE; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - bad = TRUE; - } - if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Al != cinfo->Ah-1) - bad = TRUE; - } - if (cinfo->Al > 13) /* need not check for < 0 */ - bad = TRUE; - /* Arguably the maximum Al value should be less than 13 for 8-bit precision, - * but the spec doesn't say so, and we try to be liberal about what we - * accept. Note: large Al values could result in out-of-range DC - * coefficients during early scans, leading to bizarre displays due to - * overflows in the IDCT math. But we won't crash. - */ - if (bad) - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int cindex = cinfo->cur_comp_info[ci]->component_index; - coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } - } - - /* Select MCU decoding routine */ - if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_first; - else - entropy->pub.decode_mcu = decode_mcu_AC_first; - } else { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_refine; - else - entropy->pub.decode_mcu = decode_mcu_AC_refine; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Make sure requested tables are present, and compute derived tables. - * We may build same derived table more than once, but it's not expensive. - */ - if (is_DC_band) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->pub.insufficient_data = FALSE; - - /* Initialize private state variables */ - entropy->saved.EOBRUN = 0; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Re-init EOB run count, too */ - entropy->saved.EOBRUN = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Huffman MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - * - * We return FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * spectral selection, since we'll just re-assign them on the next call. - * Successive approximation AC refinement has to be more careful, however.) - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Al = cinfo->Al; - register int s, r; - int blkn, ci; - JBLOCKROW block; - BITREAD_STATE_VARS; - savable_state state; - d_derived_tbl * tbl; - jpeg_component_info * compptr; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, tbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (s << Al); - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Se = cinfo->Se; - int Al = cinfo->Al; - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state. - * We can avoid loading/saving bitread state if in an EOB run. - */ - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - - if (EOBRUN > 0) /* if it's a band of zeroes... */ - EOBRUN--; /* ...process it now (we do nothing) */ - else { - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - for (k = cinfo->Ss; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, return FALSE, label2); - r = s >> 4; - s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); - } else { - if (r == 15) { /* ZRL */ - k += 15; /* skip 15 zeroes in band */ - } else { /* EOBr, run length is 2^r + appended bits */ - EOBRUN = 1 << r; - if (r) { /* EOBr, r > 0 */ - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - } - EOBRUN--; /* this band is processed at this moment */ - break; /* force end-of-band */ - } - } - } - - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } - - /* Completed MCU, so update state */ - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int blkn; - JBLOCKROW block; - BITREAD_STATE_VARS; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* Not worth the cycles to check insufficient_data here, - * since we will not change the data anyway if we read zeroes. - */ - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* Encoded data is simply the next bit of the two's-complement DC value */ - CHECK_BIT_BUFFER(br_state, 1, return FALSE); - if (GET_BITS(1)) - (*block)[0] |= p1; - /* Note: since we use |=, repeating the assignment later is safe */ - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Se = cinfo->Se; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - JCOEFPTR thiscoef; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - int num_newnz; - int newnz_pos[DCTSIZE2]; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, don't modify the MCU. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - /* If we are forced to suspend, we must undo the assignments to any newly - * nonzero coefficients in the block, because otherwise we'd get confused - * next time about which coefficients were already nonzero. - * But we need not undo addition of bits to already-nonzero coefficients; - * instead, we can test the current bit to see if we already did it. - */ - num_newnz = 0; - - /* initialize coefficient loop counter to start of band */ - k = cinfo->Ss; - - if (EOBRUN == 0) { - for (; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, goto undoit, label3); - r = s >> 4; - s &= 15; - if (s) { - if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ - else - s = m1; /* newly nonzero coef is negative */ - } else { - if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ - } - /* note s = 0 for processing ZRL */ - } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } else { - if (--r < 0) - break; /* reached target zero coefficient */ - } - k++; - } while (k <= Se); - if (s) { - int pos = jpeg_natural_order[k]; - /* Output newly nonzero coefficient */ - (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ - newnz_pos[num_newnz++] = pos; - } - } - } - - if (EOBRUN > 0) { - /* Scan any remaining coefficient positions after the end-of-band - * (the last newly nonzero coefficient, if any). Append a correction - * bit to each already-nonzero coefficient. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - for (; k <= Se; k++) { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } - } - /* Count one block completed in EOB run */ - EOBRUN--; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; - -undoit: - /* Re-zero any output coefficients that we made newly nonzero */ - while (num_newnz > 0) - (*block)[newnz_pos[--num_newnz]] = 0; - - return FALSE; -} - - -/* - * Module initialization routine for progressive Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_phuff_decoder (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy; - int *coef_bit_ptr; - int ci, i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_decoder)); - cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; - entropy->pub.start_pass = start_pass_phuff_decoder; - - /* Mark derived tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - } - - /* Create progression status table */ - cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); - coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; -} - -#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jdpostct.c b/third_party/libjpeg/fpdfapi_jdpostct.c deleted file mode 100644 index 571563d728e7135996cc982b8f8dfba3d69a9846..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdpostct.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * jdpostct.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the decompression postprocessing controller. - * This controller manages the upsampling, color conversion, and color - * quantization/reduction steps; specifically, it controls the buffering - * between upsample/color conversion and color quantization/reduction. - * - * If no color quantization/reduction is required, then this module has no - * work to do, and it just hands off to the upsample/color conversion code. - * An integrated upsample/convert/quantize process would replace this module - * entirely. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Private buffer controller object */ - -typedef struct { - struct jpeg_d_post_controller pub; /* public fields */ - - /* Color quantization source buffer: this holds output data from - * the upsample/color conversion step to be passed to the quantizer. - * For two-pass color quantization, we need a full-image buffer; - * for one-pass operation, a strip buffer is sufficient. - */ - jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ - JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ - JDIMENSION strip_height; /* buffer size in rows */ - /* for two-pass mode only: */ - JDIMENSION starting_row; /* row # of first row in current strip */ - JDIMENSION next_row; /* index of next row to fill/empty in strip */ -} my_post_controller; - -typedef my_post_controller * my_post_ptr; - - -/* Forward declarations */ -METHODDEF(void) post_process_1pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#ifdef QUANT_2PASS_SUPPORTED -METHODDEF(void) post_process_prepass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -METHODDEF(void) post_process_2pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -#endif - - -/* - * Initialize for a processing pass. - */ - -METHODDEF(void) -start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - - switch (pass_mode) { - case JBUF_PASS_THRU: - if (cinfo->quantize_colors) { - /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; - /* We could be doing buffered-image output before starting a 2-pass - * color quantization; in that case, jinit_d_post_controller did not - * allocate a strip buffer. Use the virtual-array buffer as workspace. - */ - if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - (JDIMENSION) 0, post->strip_height, TRUE); - } - } else { - /* For single-pass processing without color quantization, - * I have no work to do; just call the upsampler directly. - */ - post->pub.post_process_data = cinfo->upsample->upsample; - } - break; -#ifdef QUANT_2PASS_SUPPORTED - case JBUF_SAVE_AND_PASS: - /* First pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; - break; - case JBUF_CRANK_DEST: - /* Second pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; - break; -#endif /* QUANT_2PASS_SUPPORTED */ - default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; - } - post->starting_row = post->next_row = 0; -} - - -/* - * Process some data in the one-pass (strip buffer) case. - * This is used for color precision reduction as well as one-pass quantization. - */ - -METHODDEF(void) -post_process_1pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Fill the buffer, but not more than what we can dump out in one go. */ - /* Note we rely on the upsampler to detect bottom of image. */ - max_rows = out_rows_avail - *out_row_ctr; - if (max_rows > post->strip_height) - max_rows = post->strip_height; - num_rows = 0; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &num_rows, max_rows); - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer, output_buf + *out_row_ctr, (int) num_rows); - *out_row_ctr += num_rows; -} - - -#ifdef QUANT_2PASS_SUPPORTED - -/* - * Process some data in the first pass of 2-pass quantization. - */ - -METHODDEF(void) -post_process_prepass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION old_next_row, num_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, TRUE); - } - - /* Upsample some data (up to a strip height's worth). */ - old_next_row = post->next_row; - (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &post->next_row, post->strip_height); - - /* Allow quantizer to scan new data. No data is emitted, */ - /* but we advance out_row_ctr so outer loop can tell when we're done. */ - if (post->next_row > old_next_row) { - num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY) NULL, (int) num_rows); - *out_row_ctr += num_rows; - } - - /* Advance if we filled the strip. */ - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - - -/* - * Process some data in the second pass of 2-pass quantization. - */ - -METHODDEF(void) -post_process_2pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_post_ptr post = (my_post_ptr) cinfo->post; - JDIMENSION num_rows, max_rows; - - /* Reposition virtual buffer if at start of strip. */ - if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, FALSE); - } - - /* Determine number of rows to emit. */ - num_rows = post->strip_height - post->next_row; /* available in strip */ - max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ - if (num_rows > max_rows) - num_rows = max_rows; - /* We have to check bottom of image here, can't depend on upsampler. */ - max_rows = cinfo->output_height - post->starting_row; - if (num_rows > max_rows) - num_rows = max_rows; - - /* Quantize and emit data. */ - (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer + post->next_row, output_buf + *out_row_ctr, - (int) num_rows); - *out_row_ctr += num_rows; - - /* Advance if we filled the strip. */ - post->next_row += num_rows; - if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; - } -} - -#endif /* QUANT_2PASS_SUPPORTED */ - - -/* - * Initialize postprocessing controller. - */ - -GLOBAL(void) -jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) -{ - my_post_ptr post; - - post = (my_post_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_post_controller)); - cinfo->post = (struct jpeg_d_post_controller *) post; - post->pub.start_pass = start_pass_dpost; - post->whole_image = NULL; /* flag for no virtual arrays */ - post->buffer = NULL; /* flag for no strip buffer */ - - /* Create the quantization buffer, if needed */ - if (cinfo->quantize_colors) { - /* The buffer strip height is max_v_samp_factor, which is typically - * an efficient number of rows for upsampling to return. - * (In the presence of output rescaling, we might want to be smarter?) - */ - post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; - if (need_full_buffer) { - /* Two-pass color quantization: need full-image storage. */ - /* We round up the number of rows to a multiple of the strip height. */ -#ifdef QUANT_2PASS_SUPPORTED - post->whole_image = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - cinfo->output_width * cinfo->out_color_components, - (JDIMENSION) jround_up((long) cinfo->output_height, - (long) post->strip_height), - post->strip_height); -#else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); -#endif /* QUANT_2PASS_SUPPORTED */ - } else { - /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->output_width * cinfo->out_color_components, - post->strip_height); - } - } -} diff --git a/third_party/libjpeg/fpdfapi_jdsample.c b/third_party/libjpeg/fpdfapi_jdsample.c deleted file mode 100644 index 80ffefb2a1ccf5ddc1530b921df0eef6e3e45c18..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdsample.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * jdsample.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains upsampling routines. - * - * Upsampling input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. Upsampling will normally produce - * max_v_samp_factor pixel rows from each row group (but this could vary - * if the upsampler is applying a scale factor of its own). - * - * An excellent reference for image resampling is - * Digital Image Warping, George Wolberg, 1990. - * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Pointer to routine to upsample a single component */ -typedef JMETHOD(void, upsample1_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); - -/* Private subobject */ - -typedef struct { - struct jpeg_upsampler pub; /* public fields */ - - /* Color conversion buffer. When using separate upsampling and color - * conversion steps, this buffer holds one upsampled row group until it - * has been color converted and output. - * Note: we do not allocate any storage for component(s) which are full-size, - * ie do not need rescaling. The corresponding entry of color_buf[] is - * simply set to point to the input data array, thereby avoiding copying. - */ - JSAMPARRAY color_buf[MAX_COMPONENTS]; - - /* Per-component upsampling method pointers */ - upsample1_ptr methods[MAX_COMPONENTS]; - - int next_row_out; /* counts rows emitted from color_buf */ - JDIMENSION rows_to_go; /* counts rows remaining in image */ - - /* Height of an input row group for each component. */ - int rowgroup_height[MAX_COMPONENTS]; - - /* These arrays save pixel expansion factors so that int_expand need not - * recompute them each time. They are unused for other upsampling methods. - */ - UINT8 h_expand[MAX_COMPONENTS]; - UINT8 v_expand[MAX_COMPONENTS]; -} my_upsampler; - -typedef my_upsampler * my_upsample_ptr; - - -/* - * Initialize for an upsampling pass. - */ - -METHODDEF(void) -start_pass_upsample (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - - /* Mark the conversion buffer empty */ - upsample->next_row_out = cinfo->max_v_samp_factor; - /* Initialize total-height counter for detecting bottom of image */ - upsample->rows_to_go = cinfo->output_height; -} - - -/* - * Control routine to do upsampling (and color conversion). - * - * In this version we upsample each component independently. - * We upsample one row group into the conversion buffer, then apply - * color conversion a row at a time. - */ - -METHODDEF(void) -sep_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - int ci; - jpeg_component_info * compptr; - JDIMENSION num_rows; - - /* Fill the conversion buffer, if it's empty */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Invoke per-component upsample method. Notice we pass a POINTER - * to color_buf[ci], so that fullsize_upsample can change it. - */ - (*upsample->methods[ci]) (cinfo, compptr, - input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), - upsample->color_buf + ci); - } - upsample->next_row_out = 0; - } - - /* Color-convert and emit rows */ - - /* How many we have in the buffer: */ - num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); - /* Not more than the distance to the end of the image. Need this test - * in case the image height is not a multiple of max_v_samp_factor: - */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - - (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION) upsample->next_row_out, - output_buf + *out_row_ctr, - (int) num_rows); - - /* Adjust counts */ - *out_row_ctr += num_rows; - upsample->rows_to_go -= num_rows; - upsample->next_row_out += num_rows; - /* When the buffer is emptied, declare this input row group consumed */ - if (upsample->next_row_out >= cinfo->max_v_samp_factor) - (*in_row_group_ctr)++; -} - - -/* - * These are the routines invoked by sep_upsample to upsample pixel values - * of a single component. One row group is processed per call. - */ - - -/* - * For full-size components, we just make color_buf[ci] point at the - * input buffer, and thus avoid copying any data. Note that this is - * safe only because sep_upsample doesn't declare the input row group - * "consumed" until we are done color converting and emitting it. - */ - -METHODDEF(void) -fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = input_data; -} - - -/* - * This is a no-op version used for "uninteresting" components. - * These components will not be referenced by color conversion. - */ - -METHODDEF(void) -noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - *output_data_ptr = NULL; /* safety check */ -} - - -/* - * This version handles any integral sampling ratios. - * This is not used for typical JPEG files, so it need not be fast. - * Nor, for that matter, is it particularly accurate: the algorithm is - * simple replication of the input pixel onto the corresponding output - * pixels. The hi-falutin sampling literature refers to this as a - * "box filter". A box filter tends to introduce visible artifacts, - * so if you are actually going to use 3:1 or 4:1 sampling ratios - * you would be well advised to improve this code. - */ - -METHODDEF(void) -int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - register int h; - JSAMPROW outend; - int h_expand, v_expand; - int inrow, outrow; - - h_expand = upsample->h_expand[compptr->component_index]; - v_expand = upsample->v_expand[compptr->component_index]; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - /* Generate one output row with proper horizontal expansion */ - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - for (h = h_expand; h > 0; h--) { - *outptr++ = invalue; - } - } - /* Generate any additional output rows by duplicating the first one */ - if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - v_expand-1, cinfo->output_width); - } - inrow++; - outrow += v_expand; - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. - * It's still a box filter. - */ - -METHODDEF(void) -h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - } -} - - -/* - * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. - * It's still a box filter. - */ - -METHODDEF(void) -h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register JSAMPLE invalue; - JSAMPROW outend; - int inrow, outrow; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - 1, cinfo->output_width); - inrow++; - outrow += 2; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. - * - * The upsampling algorithm is linear interpolation between pixel centers, - * also known as a "triangle filter". This is a good compromise between - * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 - * of the way between input pixel centers. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF(void) -h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register int invalue; - register JDIMENSION colctr; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - /* Special case for first column */ - invalue = GETJSAMPLE(*inptr++); - *outptr++ = (JSAMPLE) invalue; - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ - invalue = GETJSAMPLE(*inptr++) * 3; - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); - } - - /* Special case for last column */ - invalue = GETJSAMPLE(*inptr); - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); - *outptr++ = (JSAMPLE) invalue; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. - * Again a triangle filter; see comments for h2v1 case, above. - * - * It is OK for us to reference the adjacent input rows because we demanded - * context from the main buffer controller (see initialization code). - */ - -METHODDEF(void) -h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; -#if BITS_IN_JSAMPLE == 8 - register int thiscolsum, lastcolsum, nextcolsum; -#else - register INT32 thiscolsum, lastcolsum, nextcolsum; -#endif - register JDIMENSION colctr; - int inrow, outrow, v; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - for (v = 0; v < 2; v++) { - /* inptr0 points to nearest input row, inptr1 points to next nearest */ - inptr0 = input_data[inrow]; - if (v == 0) /* next nearest is row above */ - inptr1 = input_data[inrow-1]; - else /* next nearest is row below */ - inptr1 = input_data[inrow+1]; - outptr = output_data[outrow++]; - - /* Special case for first column */ - thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ - /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - } - - /* Special case for last column */ - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); - } - inrow++; - } -} - - -/* - * Module initialization routine for upsampling. - */ - -GLOBAL(void) -jinit_upsampler (j_decompress_ptr cinfo) -{ - my_upsample_ptr upsample; - int ci; - jpeg_component_info * compptr; - boolean need_buffer, do_fancy; - int h_in_group, v_in_group, h_out_group, v_out_group; - - upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; - upsample->pub.start_pass = start_pass_upsample; - upsample->pub.upsample = sep_upsample; - upsample->pub.need_context_rows = FALSE; /* until we find out differently */ - - if (cinfo->CCIR601_sampling) /* this isn't supported */ - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - - /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, - * so don't ask for it. - */ - do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; - - /* Verify we can handle the sampling factors, select per-component methods, - * and create storage as needed. - */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Compute size of an "input group" after IDCT scaling. This many samples - * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. - */ - h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - h_out_group = cinfo->max_h_samp_factor; - v_out_group = cinfo->max_v_samp_factor; - upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - need_buffer = TRUE; - if (! compptr->component_needed) { - /* Don't bother to upsample an uninteresting component. */ - upsample->methods[ci] = noop_upsample; - need_buffer = FALSE; - } else if (h_in_group == h_out_group && v_in_group == v_out_group) { - /* Fullsize components can be processed without any work. */ - upsample->methods[ci] = fullsize_upsample; - need_buffer = FALSE; - } else if (h_in_group * 2 == h_out_group && - v_in_group == v_out_group) { - /* Special cases for 2h1v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) - upsample->methods[ci] = h2v1_fancy_upsample; - else - upsample->methods[ci] = h2v1_upsample; - } else if (h_in_group * 2 == h_out_group && - v_in_group * 2 == v_out_group) { - /* Special cases for 2h2v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) { - upsample->methods[ci] = h2v2_fancy_upsample; - upsample->pub.need_context_rows = TRUE; - } else - upsample->methods[ci] = h2v2_upsample; - } else if ((h_out_group % h_in_group) == 0 && - (v_out_group % v_in_group) == 0) { - /* Generic integral-factors upsampling method */ - upsample->methods[ci] = int_upsample; - upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); - upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - if (need_buffer) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) cinfo->output_width, - (long) cinfo->max_h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } - } -} diff --git a/third_party/libjpeg/fpdfapi_jdtrans.c b/third_party/libjpeg/fpdfapi_jdtrans.c deleted file mode 100644 index 6c0ab715d32ab470950f6db9537381adced9741d..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jdtrans.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * jdtrans.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains library routines for transcoding decompression, - * that is, reading raw DCT coefficient arrays from an input JPEG file. - * The routines in jdapimin.c will also be needed by a transcoder. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* Forward declarations */ -LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); - - -/* - * Read the coefficient arrays from a JPEG file. - * jpeg_read_header must be completed before calling this. - * - * The entire image is read into a set of virtual coefficient-block arrays, - * one per component. The return value is a pointer to the array of - * virtual-array descriptors. These can be manipulated directly via the - * JPEG memory manager, or handed off to jpeg_write_coefficients(). - * To release the memory occupied by the virtual arrays, call - * jpeg_finish_decompress() when done with the data. - * - * An alternative usage is to simply obtain access to the coefficient arrays - * during a buffered-image-mode decompression operation. This is allowed - * after any jpeg_finish_output() call. The arrays can be accessed until - * jpeg_finish_decompress() is called. (Note that any call to the library - * may reposition the arrays, so don't rely on access_virt_barray() results - * to stay valid across library calls.) - * - * Returns NULL if suspended. This case need be checked only if - * a suspending data source is used. - */ - -GLOBAL(jvirt_barray_ptr *) -jpeg_read_coefficients (j_decompress_ptr cinfo) -{ - if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize active modules */ - transdecode_master_selection(cinfo); - cinfo->global_state = DSTATE_RDCOEFS; - } - if (cinfo->global_state == DSTATE_RDCOEFS) { - /* Absorb whole file into the coef buffer */ - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return NULL; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* startup underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } - } - /* Set state so that jpeg_finish_decompress does the right thing */ - cinfo->global_state = DSTATE_STOPPING; - } - /* At this point we should be in state DSTATE_STOPPING if being used - * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access - * to the coefficients during a full buffered-image-mode decompression. - */ - if ((cinfo->global_state == DSTATE_STOPPING || - cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { - return cinfo->coef->coef_arrays; - } - /* Oops, improper usage */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - return NULL; /* keep compiler happy */ -} - - -/* - * Master selection of decompression modules for transcoding. - * This substitutes for jdmaster.c's initialization of the full decompressor. - */ - -LOCAL(void) -transdecode_master_selection (j_decompress_ptr cinfo) -{ - /* This is effectively a buffered-image operation. */ - cinfo->buffered_image = TRUE; - - /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); - } - - /* Always get a full-image coefficient buffer. */ - jinit_d_coef_controller(cinfo, TRUE); - - /* We can now tell the memory manager to allocate virtual arrays. */ - (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - - /* Initialize input side of decompressor to consume first scan. */ - (*cinfo->inputctl->start_input_pass) (cinfo); - - /* Initialize progress monitoring. */ - if (cinfo->progress != NULL) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else if (cinfo->inputctl->has_multiple_scans) { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } else { - nscans = 1; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = 1; - } -} diff --git a/third_party/libjpeg/fpdfapi_jerror.c b/third_party/libjpeg/fpdfapi_jerror.c deleted file mode 100644 index adfb9fe19dba1f0f245bc50b27d3dc202214272b..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jerror.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * jerror.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains simple error-reporting and trace-message routines. - * These are suitable for Unix-like systems and others where writing to - * stderr is the right thing to do. Many applications will want to replace - * some or all of these routines. - * - * These routines are used by both the compression and decompression code. - */ - -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jversion.h" -#include "jerror.h" - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif - - -/* - * Create the message string table. - * We do this from the master message list in jerror.h by re-reading - * jerror.h with a suitable definition for macro JMESSAGE. - * The message table is made an external symbol just in case any applications - * want to refer to it directly. - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_message_table jMsgTable -#endif - -#define JMESSAGE(code,string) string , - -const char * const jpeg_std_message_table[] = { -#include "jerror.h" - NULL -}; - - -/* - * Error exit handler: must not return to caller. - * - * Applications may override this if they want to get control back after - * an error. Typically one would longjmp somewhere instead of exiting. - * The setjmp buffer can be made a private field within an expanded error - * handler object. Note that the info needed to generate an error message - * is stored in the error object, so you can generate the message now or - * later, at your convenience. - * You should make sure that the JPEG object is cleaned up (with jpeg_abort - * or jpeg_destroy) at some point. - */ - -METHODDEF(void) -error_exit (j_common_ptr cinfo) -{ - /* Always display the message */ - (*cinfo->err->output_message) (cinfo); - - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); - -// exit(EXIT_FAILURE); -} - - -/* - * Actual output of an error or trace message. - * Applications may override this method to send JPEG messages somewhere - * other than stderr. - * - * On Windows, printing to stderr is generally completely useless, - * so we provide optional code to produce an error-dialog popup. - * Most Windows applications will still prefer to override this routine, - * but if they don't, it'll do something at least marginally useful. - * - * NOTE: to use the library in an environment that doesn't support the - * C stdio library, you may have to delete the call to fprintf() entirely, - * not just not use this routine. - */ - -METHODDEF(void) -output_message (j_common_ptr cinfo) -{ - char buffer[JMSG_LENGTH_MAX]; - - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); - - /* Send it to stderr, adding a newline */ - FXSYS_fprintf(stderr, "%s\n", buffer); -} - - -/* - * Decide whether to emit a trace or warning message. - * msg_level is one of: - * -1: recoverable corrupt-data warning, may want to abort. - * 0: important advisory messages (always display to user). - * 1: first level of tracing detail. - * 2,3,...: successively more detailed tracing messages. - * An application might override this method if it wanted to abort on warnings - * or change the policy about which messages to display. - */ - -METHODDEF(void) -emit_message (j_common_ptr cinfo, int msg_level) -{ - struct jpeg_error_mgr * err = cinfo->err; - - if (msg_level < 0) { - /* It's a warning message. Since corrupt files may generate many warnings, - * the policy implemented here is to show only the first warning, - * unless trace_level >= 3. - */ - if (err->num_warnings == 0 || err->trace_level >= 3) - (*err->output_message) (cinfo); - /* Always count warnings in num_warnings. */ - err->num_warnings++; - } else { - /* It's a trace message. Show it if trace_level >= msg_level. */ - if (err->trace_level >= msg_level) - (*err->output_message) (cinfo); - } -} - - -/* - * Format a message string for the most recent JPEG error or message. - * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX - * characters. Note that no '\n' character is added to the string. - * Few applications should need to override this method. - */ - -METHODDEF(void) -format_message (j_common_ptr cinfo, char * buffer) -{ -#if 0 /* XYQ */ - struct jpeg_error_mgr * err = cinfo->err; - int msg_code = err->msg_code; - const char * msgtext = NULL; - const char * msgptr; - char ch; - boolean isstring; - - /* Look up message string in proper table */ - if (msg_code > 0 && msg_code <= err->last_jpeg_message) { - msgtext = err->jpeg_message_table[msg_code]; - } else if (err->addon_message_table != NULL && - msg_code >= err->first_addon_message && - msg_code <= err->last_addon_message) { - msgtext = err->addon_message_table[msg_code - err->first_addon_message]; - } - - /* Defend against bogus message number */ - if (msgtext == NULL) { - err->msg_parm.i[0] = msg_code; - msgtext = err->jpeg_message_table[0]; - } - - /* Check for string parameter, as indicated by %s in the message text */ - isstring = FALSE; - msgptr = msgtext; - while ((ch = *msgptr++) != '\0') { - if (ch == '%') { - if (*msgptr == 's') isstring = TRUE; - break; - } - } - - /* Format the message into the passed buffer */ - if (isstring) - sprintf(buffer, msgtext, err->msg_parm.s); - else - sprintf(buffer, msgtext, - err->msg_parm.i[0], err->msg_parm.i[1], - err->msg_parm.i[2], err->msg_parm.i[3], - err->msg_parm.i[4], err->msg_parm.i[5], - err->msg_parm.i[6], err->msg_parm.i[7]); -#endif -} - - -/* - * Reset error state variables at start of a new image. - * This is called during compression startup to reset trace/error - * processing to default state, without losing any application-specific - * method pointers. An application might possibly want to override - * this method if it has additional error processing state. - */ - -METHODDEF(void) -reset_error_mgr (j_common_ptr cinfo) -{ - cinfo->err->num_warnings = 0; - /* trace_level is not reset since it is an application-supplied parameter */ - cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ -} - - -/* - * Fill in the standard error-handling methods in a jpeg_error_mgr object. - * Typical call is: - * struct jpeg_compress_struct cinfo; - * struct jpeg_error_mgr err; - * - * cinfo.err = jpeg_std_error(&err); - * after which the application may override some of the methods. - */ - -GLOBAL(struct jpeg_error_mgr *) -jpeg_std_error (struct jpeg_error_mgr * err) -{ - err->error_exit = error_exit; - err->emit_message = emit_message; - err->output_message = output_message; - err->format_message = format_message; - err->reset_error_mgr = reset_error_mgr; - - err->trace_level = 0; /* default = no tracing */ - err->num_warnings = 0; /* no warnings emitted yet */ - err->msg_code = 0; /* may be useful as a flag for "no error" */ - - /* Initialize message table pointers */ - err->jpeg_message_table = jpeg_std_message_table; - err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; - - err->addon_message_table = NULL; - err->first_addon_message = 0; /* for safety */ - err->last_addon_message = 0; - - return err; -} diff --git a/third_party/libjpeg/fpdfapi_jfdctfst.c b/third_party/libjpeg/fpdfapi_jfdctfst.c deleted file mode 100644 index ccb378a3b45339e05167514a038cc2db616e8fe7..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jfdctfst.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * jfdctfst.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a fast, not so accurate integer implementation of the - * forward DCT (Discrete Cosine Transform). - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with fixed-point math, - * accuracy is lost due to imprecise representation of the scaled - * quantization values. The smaller the quantization table entry, the less - * precise the scaled value, so this implementation does worse with high- - * quality-setting files than with low-quality ones. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_IFAST_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jfdctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * Again to save a few shifts, the intermediate results between pass 1 and - * pass 2 are not upscaled, but are represented only to integral precision. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - -#define CONST_BITS 8 - - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 8 -#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ -#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ -#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ -#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ -#else -#define FIX_0_382683433 FIX(0.382683433) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_707106781 FIX(0.707106781) -#define FIX_1_306562965 FIX(1.306562965) -#endif - - -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - -#ifndef USE_ACCURATE_ROUNDING -#undef DESCALE -#define DESCALE(x,n) RIGHT_SHIFT(x, n) -#endif - - -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - -#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL(void) -jpeg_fdct_ifast (DCTELEM * data) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - DCTELEM tmp10, tmp11, tmp12, tmp13; - DCTELEM z1, z2, z3, z4, z5, z11, z13; - DCTELEM *dataptr; - int ctr; - SHIFT_TEMPS - - /* Pass 1: process rows. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ - } -} - -#endif /* DCT_IFAST_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jfdctint.c b/third_party/libjpeg/fpdfapi_jfdctint.c deleted file mode 100644 index 0a78b64aee8ffd7fc6c3469495ec577a59d44ed1..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jfdctint.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * jfdctint.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a slow-but-accurate integer implementation of the - * forward DCT (Discrete Cosine Transform). - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on an algorithm described in - * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT - * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, - * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. - * The primary algorithm described there uses 11 multiplies and 29 adds. - * We use their alternate method with 12 multiplies and 32 adds. - * The advantage of this method is that no data path contains more than one - * multiplication; this allows a very simple and accurate implementation in - * scaled fixed-point arithmetic, with a minimal number of shifts. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_ISLOW_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D DCT step produces outputs which are a factor of sqrt(N) - * larger than the true DCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D DCT, - * because the y0 and y4 outputs need not be divided by sqrt(N). - * In the IJG code, this factor of 8 is removed by the quantization step - * (in jcdctmgr.c), NOT in this module. - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (For 12-bit sample data, the intermediate - * array is INT32 anyway.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ -#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ -#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ -#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ -#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ -#else -#define FIX_0_298631336 FIX(0.298631336) -#define FIX_0_390180644 FIX(0.390180644) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_175875602 FIX(1.175875602) -#define FIX_1_501321110 FIX(1.501321110) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_1_961570560 FIX(1.961570560) -#define FIX_2_053119869 FIX(2.053119869) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_072711026 FIX(3.072711026) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL(void) -jpeg_fdct_islow (DCTELEM * data) -{ - INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; - DCTELEM *dataptr; - int ctr; - SHIFT_TEMPS - - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); - dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS-PASS1_BITS); - - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); - dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. - * We remove the PASS1_BITS scaling, but leave the results scaled up - * by an overall factor of 8. - */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); - dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS+PASS1_BITS); - - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, - CONST_BITS+PASS1_BITS); - - dataptr++; /* advance pointer to next column */ - } -} - -#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jidctfst.c b/third_party/libjpeg/fpdfapi_jidctfst.c deleted file mode 100644 index dba4216fb95e7148c24f2d6f6bba8309bb9be24e..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jidctfst.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * jidctfst.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a fast, not so accurate integer implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with fixed-point math, - * accuracy is lost due to imprecise representation of the scaled - * quantization values. The smaller the quantization table entry, the less - * precise the scaled value, so this implementation does worse with high- - * quality-setting files than with low-quality ones. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_IFAST_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jidctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * The dequantized coefficients are not integers because the AA&N scaling - * factors have been incorporated. We represent them scaled up by PASS1_BITS, - * so that the first and second IDCT rounds have the same input scaling. - * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to - * avoid a descaling shift; this compromises accuracy rather drastically - * for small quantization table entries, but it saves a lot of shifts. - * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, - * so we use a much larger scaling factor to preserve accuracy. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 8 -#define PASS1_BITS 2 -#else -#define CONST_BITS 8 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 8 -#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ -#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ -#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ -#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ -#else -#define FIX_1_082392200 FIX(1.082392200) -#define FIX_1_414213562 FIX(1.414213562) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_613125930 FIX(2.613125930) -#endif - - -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - -#ifndef USE_ACCURATE_ROUNDING -#undef DESCALE -#define DESCALE(x,n) RIGHT_SHIFT(x, n) -#endif - - -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - -#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 - * multiplication will do. For 12-bit data, the multiplier table is - * declared INT32, so a 32-bit multiply will be used. - */ - -#if BITS_IN_JSAMPLE == 8 -#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) -#else -#define DEQUANTIZE(coef,quantval) \ - DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) -#endif - - -/* Like DESCALE, but applies to a DCTELEM and produces an int. - * We assume that int right shift is unsigned if INT32 right shift is. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS DCTELEM ishift_temp; -#if BITS_IN_JSAMPLE == 8 -#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ -#else -#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ -#endif -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -#ifdef USE_ACCURATE_ROUNDING -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) -#else -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) -#endif - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -GLOBAL(void) -jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - DCTELEM tmp10, tmp11, tmp12, tmp13; - DCTELEM z5, z10, z11, z12, z13; - JCOEFPTR inptr; - IFAST_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS /* for DESCALE */ - ISHIFT_TEMPS /* for IDESCALE */ - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); - wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); - wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); - wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); - wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); - wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); - wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); - wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); - tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); - - tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); - tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - - tmp13; - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; - z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; - z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; - z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_IFAST_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jidctint.c b/third_party/libjpeg/fpdfapi_jidctint.c deleted file mode 100644 index a72b3207caf5556457b8ed1f60f7446fa101f8f8..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jidctint.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * jidctint.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a slow-but-accurate integer implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on an algorithm described in - * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT - * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, - * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. - * The primary algorithm described there uses 11 multiplies and 29 adds. - * We use their alternate method with 12 multiplies and 32 adds. - * The advantage of this method is that no data path contains more than one - * multiplication; this allows a very simple and accurate implementation in - * scaled fixed-point arithmetic, with a minimal number of shifts. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef DCT_ISLOW_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) - * larger than the true IDCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D IDCT, - * because the y0 and y4 inputs need not be divided by sqrt(N). - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (To scale up 12-bit sample data further, an - * intermediate INT32 array would be needed.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ -#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ -#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ -#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ -#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ -#else -#define FIX_0_298631336 FIX(0.298631336) -#define FIX_0_390180644 FIX(0.390180644) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_175875602 FIX(1.175875602) -#define FIX_1_501321110 FIX(1.501321110) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_1_961570560 FIX(1.961570560) -#define FIX_2_053119869 FIX(2.053119869) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_072711026 FIX(3.072711026) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -GLOBAL(void) -jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); - - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - - wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); - - tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; - tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - tmp0 = (INT32) wsptr[7]; - tmp1 = (INT32) wsptr[5]; - tmp2 = (INT32) wsptr[3]; - tmp3 = (INT32) wsptr[1]; - - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jidctred.c b/third_party/libjpeg/fpdfapi_jidctred.c deleted file mode 100644 index 421f3c7ca1ed2ebc9335aeb29c990a08840a5b1d..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jidctred.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * jidctred.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains inverse-DCT routines that produce reduced-size output: - * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. - * - * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) - * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step - * with an 8-to-4 step that produces the four averages of two adjacent outputs - * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). - * These steps were derived by computing the corresponding values at the end - * of the normal LL&M code, then simplifying as much as possible. - * - * 1x1 is trivial: just take the DC coefficient divided by 8. - * - * See jidctint.c for additional comments. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef IDCT_SCALING_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling is the same as in jidctint.c. */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ -#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ -#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ -#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ -#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ -#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ -#else -#define FIX_0_211164243 FIX(0.211164243) -#define FIX_0_509795579 FIX(0.509795579) -#define FIX_0_601344887 FIX(0.601344887) -#define FIX_0_720959822 FIX(0.720959822) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_850430095 FIX(0.850430095) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_061594337 FIX(1.061594337) -#define FIX_1_272758580 FIX(1.272758580) -#define FIX_1_451774981 FIX(1.451774981) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_172734803 FIX(2.172734803) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_624509785 FIX(3.624509785) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 4x4 output block. - */ - -GLOBAL(void) -jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process column 4, because second pass won't use it */ - if (ctr == DCTSIZE-4) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && - inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine term 4 for 4x4 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= (CONST_BITS+1); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); - } - - /* Pass 2: process 4 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); - - tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) - + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = (INT32) wsptr[7]; - z2 = (INT32) wsptr[5]; - z3 = (INT32) wsptr[3]; - z4 = (INT32) wsptr[1]; - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 2x2 output block. - */ - -GLOBAL(void) -jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp10, z1; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process columns 2,4,6 */ - if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - - continue; - } - - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 = z1 << (CONST_BITS+2); - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); - } - - /* Pass 2: process 2 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 2; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); - - /* Odd part */ - - tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ - + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ - + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ - + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 1x1 output block. - */ - -GLOBAL(void) -jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - int dcval; - ISLOW_MULT_TYPE * quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS - - /* We hardly need an inverse DCT routine for this: just take the - * average pixel value, which is one-eighth of the DC coefficient. - */ - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - dcval = DEQUANTIZE(coef_block[0], quantptr[0]); - dcval = (int) DESCALE((INT32) dcval, 3); - - output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; -} - -#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/third_party/libjpeg/fpdfapi_jmemmgr.c b/third_party/libjpeg/fpdfapi_jmemmgr.c deleted file mode 100644 index 47ead48ac47c80f703c02526037b51bbf1125a30..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jmemmgr.c +++ /dev/null @@ -1,1120 +0,0 @@ -/* - * jmemmgr.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the JPEG system-independent memory management - * routines. This code is usable across a wide variety of machines; most - * of the system dependencies have been isolated in a separate file. - * The major functions provided here are: - * * pool-based allocation and freeing of memory; - * * policy decisions about how to divide available memory among the - * virtual arrays; - * * control logic for swapping virtual arrays between main memory and - * backing storage. - * The separate system-dependent file provides the actual backing-storage - * access code, and it contains the policy decision about how much total - * main memory to use. - * This file is system-dependent in the sense that some of its functions - * are unnecessary in some systems. For example, if there is enough virtual - * memory so that backing storage will never be used, much of the virtual - * array control logic could be removed. (Of course, if you have that much - * memory then you shouldn't care about a little bit of unused code...) - */ - -#define JPEG_INTERNALS -#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#define NO_GETENV /* XYQ: 2007-5-22 Don't use it */ - -#ifndef NO_GETENV -#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */ -extern char * getenv JPP((const char * name)); -#endif -#endif - - -/* - * Some important notes: - * The allocation routines provided here must never return NULL. - * They should exit to error_exit if unsuccessful. - * - * It's not a good idea to try to merge the sarray and barray routines, - * even though they are textually almost the same, because samples are - * usually stored as bytes while coefficients are shorts or ints. Thus, - * in machines where byte pointers have a different representation from - * word pointers, the resulting machine code could not be the same. - */ - - -/* - * Many machines require storage alignment: longs must start on 4-byte - * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() - * always returns pointers that are multiples of the worst-case alignment - * requirement, and we had better do so too. - * There isn't any really portable way to determine the worst-case alignment - * requirement. This module assumes that the alignment requirement is - * multiples of sizeof(ALIGN_TYPE). - * By default, we define ALIGN_TYPE as double. This is necessary on some - * workstations (where doubles really do need 8-byte alignment) and will work - * fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_TYPE smaller. - * The only place I know of where this will NOT work is certain Macintosh - * 680x0 compilers that define double as a 10-byte IEEE extended float. - * Doing 10-byte alignment is counterproductive because longwords won't be - * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have - * such a compiler. - */ - -#ifndef ALIGN_TYPE /* so can override from jconfig.h */ -#define ALIGN_TYPE double -#endif - - -/* - * We allocate objects from "pools", where each pool is gotten with a single - * request to jpeg_get_small() or jpeg_get_large(). There is no per-object - * overhead within a pool, except for alignment padding. Each pool has a - * header with a link to the next pool of the same class. - * Small and large pool headers are identical except that the latter's - * link pointer must be FAR on 80x86 machines. - * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE - * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple - * of the alignment requirement of ALIGN_TYPE. - */ - -typedef union small_pool_struct * small_pool_ptr; - -typedef union small_pool_struct { - struct { - small_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} small_pool_hdr; - -typedef union large_pool_struct FAR * large_pool_ptr; - -typedef union large_pool_struct { - struct { - large_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ - } hdr; - ALIGN_TYPE dummy; /* included in union to ensure alignment */ -} large_pool_hdr; - - -/* - * Here is the full definition of a memory manager object. - */ - -typedef struct { - struct jpeg_memory_mgr pub; /* public fields */ - - /* Each pool identifier (lifetime class) names a linked list of pools. */ - small_pool_ptr small_list[JPOOL_NUMPOOLS]; - large_pool_ptr large_list[JPOOL_NUMPOOLS]; - - /* Since we only have one lifetime class of virtual arrays, only one - * linked list is necessary (for each datatype). Note that the virtual - * array control blocks being linked together are actually stored somewhere - * in the small-pool list. - */ - jvirt_sarray_ptr virt_sarray_list; - jvirt_barray_ptr virt_barray_list; - - /* This counts total space obtained from jpeg_get_small/large */ - long total_space_allocated; - - /* alloc_sarray and alloc_barray set this value for use by virtual - * array routines. - */ - JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ -} my_memory_mgr; - -typedef my_memory_mgr * my_mem_ptr; - - -/* - * The control blocks for virtual arrays. - * Note that these blocks are allocated in the "small" pool area. - * System-dependent info for the associated backing store (if any) is hidden - * inside the backing_store_info struct. - */ - -struct jvirt_sarray_control { - JSAMPARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_sarray_ptr next; /* link to next virtual sarray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - -struct jvirt_barray_control { - JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ - JDIMENSION rows_in_array; /* total virtual array height */ - JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ - JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ - JDIMENSION rows_in_mem; /* height of memory buffer */ - JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ - JDIMENSION cur_start_row; /* first logical row # in the buffer */ - JDIMENSION first_undef_row; /* row # of first uninitialized row */ - boolean pre_zero; /* pre-zero mode requested? */ - boolean dirty; /* do current buffer contents need written? */ - boolean b_s_open; /* is backing-store data valid? */ - jvirt_barray_ptr next; /* link to next virtual barray control block */ - backing_store_info b_s_info; /* System-dependent control info */ -}; - - -#ifdef MEM_STATS /* optional extra stuff for statistics */ - -LOCAL(void) -print_mem_stats (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - - /* Since this is only a debugging stub, we can cheat a little by using - * fprintf directly rather than going through the trace message code. - * This is helpful because message parm array can't handle longs. - */ - FXSYS_fprintf(stderr, "Freeing pool %d, total space = %ld\n", - pool_id, mem->total_space_allocated); - - for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; - lhdr_ptr = lhdr_ptr->hdr.next) { - FXSYS_fprintf(stderr, " Large chunk used %ld\n", - (long) lhdr_ptr->hdr.bytes_used); - } - - for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; - shdr_ptr = shdr_ptr->hdr.next) { - FXSYS_fprintf(stderr, " Small chunk used %ld free %ld\n", - (long) shdr_ptr->hdr.bytes_used, - (long) shdr_ptr->hdr.bytes_left); - } -} - -#endif /* MEM_STATS */ - - -LOCAL(void) -out_of_memory (j_common_ptr cinfo, int which) -/* Report an out-of-memory error and stop execution */ -/* If we compiled MEM_STATS support, report alloc requests before dying */ -{ -#ifdef MEM_STATS - cinfo->err->trace_level = 2; /* force self_destruct to report stats */ -#endif - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); -} - - -/* - * Allocation of "small" objects. - * - * For these, we use pooled storage. When a new pool must be created, - * we try to get enough space for the current request plus a "slop" factor, - * where the slop will be the amount of leftover space in the new pool. - * The speed vs. space tradeoff is largely determined by the slop values. - * A different slop value is provided for each pool class (lifetime), - * and we also distinguish the first pool of a class from later ones. - * NOTE: the values given work fairly well on both 16- and 32-bit-int - * machines, but may be too small if longs are 64 bits or more. - */ - -static const size_t first_pool_slop[JPOOL_NUMPOOLS] = -{ - 1600, /* first PERMANENT pool */ - 16000 /* first IMAGE pool */ -}; - -static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = -{ - 0, /* additional PERMANENT pools */ - 5000 /* additional IMAGE pools */ -}; - -#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ - - -METHODDEF(void *) -alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "small" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr hdr_ptr, prev_hdr_ptr; - char * data_ptr; - size_t odd_bytes, min_request, slop; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) - out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* See if space is available in any existing pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - prev_hdr_ptr = NULL; - hdr_ptr = mem->small_list[pool_id]; - while (hdr_ptr != NULL) { - if (hdr_ptr->hdr.bytes_left >= sizeofobject) - break; /* found pool with enough space */ - prev_hdr_ptr = hdr_ptr; - hdr_ptr = hdr_ptr->hdr.next; - } - - /* Time to make a new pool? */ - if (hdr_ptr == NULL) { - /* min_request is what we need now, slop is what will be leftover */ - min_request = sizeofobject + SIZEOF(small_pool_hdr); - if (prev_hdr_ptr == NULL) /* first pool in class? */ - slop = first_pool_slop[pool_id]; - else - slop = extra_pool_slop[pool_id]; - /* Don't ask for more than MAX_ALLOC_CHUNK */ - if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) - slop = (size_t) (MAX_ALLOC_CHUNK-min_request); - /* Try to get space, if fail reduce slop and try again */ - for (;;) { - hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); - if (hdr_ptr != NULL) - break; - slop /= 2; - if (slop < MIN_SLOP) /* give up when it gets real small */ - out_of_memory(cinfo, 2); /* jpeg_get_small failed */ - } - mem->total_space_allocated += min_request + slop; - /* Success, initialize the new pool header and add to end of list */ - hdr_ptr->hdr.next = NULL; - hdr_ptr->hdr.bytes_used = 0; - hdr_ptr->hdr.bytes_left = sizeofobject + slop; - if (prev_hdr_ptr == NULL) /* first pool in class? */ - mem->small_list[pool_id] = hdr_ptr; - else - prev_hdr_ptr->hdr.next = hdr_ptr; - } - - /* OK, allocate the object from the current pool */ - data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ - data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ - hdr_ptr->hdr.bytes_used += sizeofobject; - hdr_ptr->hdr.bytes_left -= sizeofobject; - - return (void *) data_ptr; -} - - -/* - * Allocation of "large" objects. - * - * The external semantics of these are the same as "small" objects, - * except that FAR pointers are used on 80x86. However the pool - * management heuristics are quite different. We assume that each - * request is large enough that it may as well be passed directly to - * jpeg_get_large; the pool management just links everything together - * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. - */ - -METHODDEF(void FAR *) -alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "large" object */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - large_pool_ptr hdr_ptr; - size_t odd_bytes; - - /* Check for unsatisfiable request (do now to ensure no overflow below) */ - if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) - out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ - - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ - odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); - if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - - /* Always make a new pool */ - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + - SIZEOF(large_pool_hdr)); - if (hdr_ptr == NULL) - out_of_memory(cinfo, 4); /* jpeg_get_large failed */ - mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); - - /* Success, initialize the new pool header and add to list */ - hdr_ptr->hdr.next = mem->large_list[pool_id]; - /* We maintain space counts in each pool header for statistical purposes, - * even though they are not needed for allocation. - */ - hdr_ptr->hdr.bytes_used = sizeofobject; - hdr_ptr->hdr.bytes_left = 0; - mem->large_list[pool_id] = hdr_ptr; - - return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ -} - - -/* - * Creation of 2-D sample arrays. - * The pointers are in near heap, the samples themselves in FAR heap. - * - * To minimize allocation overhead and to allow I/O of large contiguous - * blocks, we allocate the sample rows in groups of as many rows as possible - * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. - * NB: the virtual array control routines, later in this file, know about - * this chunking of rows. The rowsperchunk value is left in the mem manager - * object so that it can be saved away if this sarray is the workspace for - * a virtual array. - */ - -METHODDEF(JSAMPARRAY) -alloc_sarray (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) -/* Allocate a 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JSAMPARRAY result; - JSAMPROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) samplesperrow * SIZEOF(JSAMPLE)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JSAMPARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JSAMPROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow - * SIZEOF(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; - } - } - - return result; -} - - -/* - * Creation of 2-D coefficient-block arrays. - * This is essentially the same as the code for sample arrays, above. - */ - -METHODDEF(JBLOCKARRAY) -alloc_barray (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, JDIMENSION numrows) -/* Allocate a 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - JBLOCKARRAY result; - JBLOCKROW workspace; - JDIMENSION rowsperchunk, currow, i; - long ltemp; - - /* Calculate max # of rows allowed in one allocation chunk */ - ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) blocksperrow * SIZEOF(JBLOCK)); - if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; - else - rowsperchunk = numrows; - mem->last_rowsperchunk = rowsperchunk; - - /* Get space for row pointers (small object) */ - result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JBLOCKROW))); - - /* Get the rows themselves (large objects) */ - currow = 0; - while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow - * SIZEOF(JBLOCK))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += blocksperrow; - } - } - - return result; -} - - -/* - * About virtual array management: - * - * The above "normal" array routines are only used to allocate strip buffers - * (as wide as the image, but just a few rows high). Full-image-sized buffers - * are handled as "virtual" arrays. The array is still accessed a strip at a - * time, but the memory manager must save the whole array for repeated - * accesses. The intended implementation is that there is a strip buffer in - * memory (as high as is possible given the desired memory limit), plus a - * backing file that holds the rest of the array. - * - * The request_virt_array routines are told the total size of the image and - * the maximum number of rows that will be accessed at once. The in-memory - * buffer must be at least as large as the maxaccess value. - * - * The request routines create control blocks but not the in-memory buffers. - * That is postponed until realize_virt_arrays is called. At that time the - * total amount of space needed is known (approximately, anyway), so free - * memory can be divided up fairly. - * - * The access_virt_array routines are responsible for making a specific strip - * area accessible (after reading or writing the backing file, if necessary). - * Note that the access routines are told whether the caller intends to modify - * the accessed strip; during a read-only pass this saves having to rewrite - * data to disk. The access routines are also responsible for pre-zeroing - * any newly accessed rows, if pre-zeroing was requested. - * - * In current usage, the access requests are usually for nonoverlapping - * strips; that is, successive access start_row numbers differ by exactly - * num_rows = maxaccess. This means we can get good performance with simple - * buffer dump/reload logic, by making the in-memory buffer be a multiple - * of the access height; then there will never be accesses across bufferload - * boundaries. The code will still work with overlapping access requests, - * but it doesn't handle bufferload overlaps very efficiently. - */ - - -METHODDEF(jvirt_sarray_ptr) -request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION samplesperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D sample array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_sarray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_sarray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->samplesperrow = samplesperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ - mem->virt_sarray_list = result; - - return result; -} - - -METHODDEF(jvirt_barray_ptr) -request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D coefficient-block array */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - jvirt_barray_ptr result; - - /* Only IMAGE-lifetime virtual arrays are currently supported */ - if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - - /* get control block */ - result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_barray_control)); - - result->mem_buffer = NULL; /* marks array not yet realized */ - result->rows_in_array = numrows; - result->blocksperrow = blocksperrow; - result->maxaccess = maxaccess; - result->pre_zero = pre_zero; - result->b_s_open = FALSE; /* no associated backing-store object */ - result->next = mem->virt_barray_list; /* add to list of virtual arrays */ - mem->virt_barray_list = result; - - return result; -} - - -METHODDEF(void) -realize_virt_arrays (j_common_ptr cinfo) -/* Allocate the in-memory buffers for any unrealized virtual arrays */ -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - long space_per_minheight, maximum_space, avail_mem; - long minheights, max_minheights; - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - /* Compute the minimum space needed (maxaccess rows in each buffer) - * and the maximum space needed (full image height in each buffer). - * These may be of use to the system-dependent jpeg_mem_available routine. - */ - space_per_minheight = 0; - maximum_space = 0; - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) sptr->maxaccess * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - maximum_space += (long) sptr->rows_in_array * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - } - } - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) bptr->maxaccess * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - maximum_space += (long) bptr->rows_in_array * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - } - } - - if (space_per_minheight <= 0) - return; /* no unrealized arrays, no work */ - - /* Determine amount of memory to actually use; this is system-dependent. */ - avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, - mem->total_space_allocated); - - /* If the maximum space needed is available, make all the buffers full - * height; otherwise parcel it out with the same number of minheights - * in each buffer. - */ - if (avail_mem >= maximum_space) - max_minheights = 1000000000L; - else { - max_minheights = avail_mem / space_per_minheight; - /* If there doesn't seem to be enough space, try to get the minimum - * anyway. This allows a "stub" implementation of jpeg_mem_available(). - */ - if (max_minheights <= 0) - max_minheights = 1; - } - - /* Allocate the in-memory buffers and initialize backing store as needed. */ - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - sptr->rows_in_mem = sptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); - jpeg_open_backing_store(cinfo, & sptr->b_s_info, - (long) sptr->rows_in_array * - (long) sptr->samplesperrow * - (long) SIZEOF(JSAMPLE)); - sptr->b_s_open = TRUE; - } - sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, - sptr->samplesperrow, sptr->rows_in_mem); - sptr->rowsperchunk = mem->last_rowsperchunk; - sptr->cur_start_row = 0; - sptr->first_undef_row = 0; - sptr->dirty = FALSE; - } - } - - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ - bptr->rows_in_mem = bptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ - bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); - jpeg_open_backing_store(cinfo, & bptr->b_s_info, - (long) bptr->rows_in_array * - (long) bptr->blocksperrow * - (long) SIZEOF(JBLOCK)); - bptr->b_s_open = TRUE; - } - bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, - bptr->blocksperrow, bptr->rows_in_mem); - bptr->rowsperchunk = mem->last_rowsperchunk; - bptr->cur_start_row = 0; - bptr->first_undef_row = 0; - bptr->dirty = FALSE; - } - } -} - - -LOCAL(void) -do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual sample array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -LOCAL(void) -do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual coefficient-block array */ -{ - long bytesperrow, file_offset, byte_count, rows, thisrow, i; - - bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); - file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ - for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - file_offset += byte_count; - } -} - - -METHODDEF(JSAMPARRAY) -access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual sample array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_sarray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_sarray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -METHODDEF(JBLOCKARRAY) -access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual block array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ -{ - JDIMENSION end_row = start_row + num_rows; - JDIMENSION undef_row; - - /* debugging check */ - if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_barray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_barray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { - jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } - } - /* Flag the buffer dirty if caller will write in it */ - if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ - return ptr->mem_buffer + (start_row - ptr->cur_start_row); -} - - -/* - * Release all objects belonging to a specified pool. - */ - -METHODDEF(void) -free_pool (j_common_ptr cinfo, int pool_id) -{ - my_mem_ptr mem = (my_mem_ptr) cinfo->mem; - small_pool_ptr shdr_ptr; - large_pool_ptr lhdr_ptr; - size_t space_freed; - - if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - -#ifdef MEM_STATS - if (cinfo->err->trace_level > 1) - print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ -#endif - - /* If freeing IMAGE pool, close any virtual arrays first */ - if (pool_id == JPOOL_IMAGE) { - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; - - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->b_s_open) { /* there may be no backing store */ - sptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); - } - } - mem->virt_sarray_list = NULL; - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->b_s_open) { /* there may be no backing store */ - bptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); - } - } - mem->virt_barray_list = NULL; - } - - /* Release large objects */ - lhdr_ptr = mem->large_list[pool_id]; - mem->large_list[pool_id] = NULL; - - while (lhdr_ptr != NULL) { - large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; - space_freed = lhdr_ptr->hdr.bytes_used + - lhdr_ptr->hdr.bytes_left + - SIZEOF(large_pool_hdr); - jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - lhdr_ptr = next_lhdr_ptr; - } - - /* Release small objects */ - shdr_ptr = mem->small_list[pool_id]; - mem->small_list[pool_id] = NULL; - - while (shdr_ptr != NULL) { - small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; - space_freed = shdr_ptr->hdr.bytes_used + - shdr_ptr->hdr.bytes_left + - SIZEOF(small_pool_hdr); - jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - shdr_ptr = next_shdr_ptr; - } -} - - -/* - * Close up shop entirely. - * Note that this cannot be called unless cinfo->mem is non-NULL. - */ - -METHODDEF(void) -self_destruct (j_common_ptr cinfo) -{ - int pool; - - /* Close all backing store, release all memory. - * Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - free_pool(cinfo, pool); - } - - /* Release the memory manager control block too. */ - jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); - cinfo->mem = NULL; /* ensures I will be called only once */ - - jpeg_mem_term(cinfo); /* system-dependent cleanup */ -} - - -/* - * Memory manager initialization. - * When this is called, only the error manager pointer is valid in cinfo! - */ - -GLOBAL(void) -jinit_memory_mgr (j_common_ptr cinfo) -{ - my_mem_ptr mem; - long max_to_use; - int pool; - size_t test_mac; - - cinfo->mem = NULL; /* for safety if init fails */ - - /* Check for configuration errors. - * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably - * doesn't reflect any real hardware alignment requirement. - * The test is a little tricky: for X>0, X and X-1 have no one-bits - * in common if and only if X is a power of 2, ie has only one one-bit. - * Some compilers may give an "unreachable code" warning here; ignore it. - */ - if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) - ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); - /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be - * a multiple of SIZEOF(ALIGN_TYPE). - * Again, an "unreachable code" warning may be ignored here. - * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. - */ - test_mac = (size_t) MAX_ALLOC_CHUNK; - if ((long) test_mac != MAX_ALLOC_CHUNK || - (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) - ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); - - max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ - - /* Attempt to allocate memory manager's control block */ - mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); - - if (mem == NULL) { - jpeg_mem_term(cinfo); /* system-dependent cleanup */ - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); - } - - /* OK, fill in the method pointers */ - mem->pub.alloc_small = alloc_small; - mem->pub.alloc_large = alloc_large; - mem->pub.alloc_sarray = alloc_sarray; - mem->pub.alloc_barray = alloc_barray; - mem->pub.request_virt_sarray = request_virt_sarray; - mem->pub.request_virt_barray = request_virt_barray; - mem->pub.realize_virt_arrays = realize_virt_arrays; - mem->pub.access_virt_sarray = access_virt_sarray; - mem->pub.access_virt_barray = access_virt_barray; - mem->pub.free_pool = free_pool; - mem->pub.self_destruct = self_destruct; - - /* Make MAX_ALLOC_CHUNK accessible to other modules */ - mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; - - /* Initialize working state */ - mem->pub.max_memory_to_use = max_to_use; - - for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - mem->small_list[pool] = NULL; - mem->large_list[pool] = NULL; - } - mem->virt_sarray_list = NULL; - mem->virt_barray_list = NULL; - - mem->total_space_allocated = SIZEOF(my_memory_mgr); - - /* Declare ourselves open for business */ - cinfo->mem = & mem->pub; - - /* Check for an environment variable JPEGMEM; if found, override the - * default max_memory setting from jpeg_mem_init. Note that the - * surrounding application may again override this value. - * If your system doesn't support getenv(), define NO_GETENV to disable - * this feature. - */ -#ifndef NO_GETENV - { char * memenv; - - if ((memenv = getenv("JPEGMEM")) != NULL) { - char ch = 'x'; - - if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { - if (ch == 'm' || ch == 'M') - max_to_use *= 1000L; - mem->pub.max_memory_to_use = max_to_use * 1000L; - } - } - } -#endif - -} diff --git a/third_party/libjpeg/fpdfapi_jmemnobs.c b/third_party/libjpeg/fpdfapi_jmemnobs.c deleted file mode 100644 index 0344f6fd7387102cbc1aae77c1db20331d198f0c..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jmemnobs.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * jmemnobs.c - * - * Copyright (C) 1992-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides a really simple implementation of the system- - * dependent portion of the JPEG memory manager. This implementation - * assumes that no backing-store files are needed: all required space - * can be obtained from malloc(). - * This is very portable in the sense that it'll compile on almost anything, - * but you'd better have lots of main memory (or virtual memory) if you want - * to process big images. - * Note that the max_memory_to_use option is ignored by this implementation. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jmemsys.h" /* import the system-dependent declarations */ - -#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */ -extern void * malloc JPP((size_t size)); -extern void free JPP((void *ptr)); -#endif - -void* FXMEM_DefaultAlloc(int byte_size, int); -void FXMEM_DefaultFree(void* pointer, int); - -/* - * Memory allocation and freeing are controlled by the regular library - * routines malloc() and free(). - */ - -GLOBAL(void *) -jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) -{ -// return (void *) malloc(sizeofobject); - return FXMEM_DefaultAlloc(sizeofobject, 0); -} - -GLOBAL(void) -jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) -{ -// free(object); - FXMEM_DefaultFree(object, 0); -} - - -/* - * "Large" objects are treated the same as "small" ones. - * NB: although we include FAR keywords in the routine declarations, - * this file won't actually work in 80x86 small/medium model; at least, - * you probably won't be able to process useful-size images in only 64KB. - */ - -GLOBAL(void FAR *) -jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) -{ -// return (void FAR *) malloc(sizeofobject); - return FXMEM_DefaultAlloc(sizeofobject, 0); -} - -GLOBAL(void) -jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) -{ -// free(object); - FXMEM_DefaultFree(object, 0); -} - - -/* - * This routine computes the total memory space available for allocation. - * Here we always say, "we got all you want bud!" - */ - -GLOBAL(long) -jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) -{ - return max_bytes_needed; -} - - -/* - * Backing store (temporary file) management. - * Since jpeg_mem_available always promised the moon, - * this should never be called and we can just error out. - */ - -GLOBAL(void) -jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, - long total_bytes_needed) -{ - ERREXIT(cinfo, JERR_NO_BACKING_STORE); -} - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. Here, there isn't any. - */ - -GLOBAL(long) -jpeg_mem_init (j_common_ptr cinfo) -{ - return 0; /* just set max_memory_to_use to 0 */ -} - -GLOBAL(void) -jpeg_mem_term (j_common_ptr cinfo) -{ - /* no work */ -} diff --git a/third_party/libjpeg/fpdfapi_jutils.c b/third_party/libjpeg/fpdfapi_jutils.c deleted file mode 100644 index d18a9555621bae9dce0b814e8afc7c05e877a4cb..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/fpdfapi_jutils.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * jutils.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains tables and miscellaneous utility routines needed - * for both compression and decompression. - * Note we prefix all global names with "j" to minimize conflicts with - * a surrounding application. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" - - -/* - * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element - * of a DCT block read in natural order (left to right, top to bottom). - */ - -#if 0 /* This table is not actually needed in v6a */ - -const int jpeg_zigzag_order[DCTSIZE2] = { - 0, 1, 5, 6, 14, 15, 27, 28, - 2, 4, 7, 13, 16, 26, 29, 42, - 3, 8, 12, 17, 25, 30, 41, 43, - 9, 11, 18, 24, 31, 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, - 20, 22, 33, 38, 46, 51, 55, 60, - 21, 34, 37, 47, 50, 56, 59, 61, - 35, 36, 48, 49, 57, 58, 62, 63 -}; - -#endif - -/* - * jpeg_natural_order[i] is the natural-order position of the i'th element - * of zigzag order. - * - * When reading corrupted data, the Huffman decoders could attempt - * to reference an entry beyond the end of this array (if the decoded - * zero run length reaches past the end of the block). To prevent - * wild stores without adding an inner-loop test, we put some extra - * "63"s after the real entries. This will cause the extra coefficient - * to be stored in location 63 of the block, not somewhere random. - * The worst case would be a run-length of 15, which means we need 16 - * fake entries. - */ - -const int jpeg_natural_order[DCTSIZE2+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - - -/* - * Arithmetic utilities - */ - -GLOBAL(long) -jdiv_round_up (long a, long b) -/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ -/* Assumes a >= 0, b > 0 */ -{ - return (a + b - 1L) / b; -} - - -GLOBAL(long) -jround_up (long a, long b) -/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ -/* Assumes a >= 0, b > 0 */ -{ - a += b - 1L; - return a - (a % b); -} - - -/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays - * and coefficient-block arrays. This won't work on 80x86 because the arrays - * are FAR and we're assuming a small-pointer memory model. However, some - * DOS compilers provide far-pointer versions of memcpy() and memset() even - * in the small-model libraries. These will be used if USE_FMEM is defined. - * Otherwise, the routines below do it the hard way. (The performance cost - * is not all that great, because these routines aren't very heavily used.) - */ - -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ -#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) -#define FMEMZERO(target,size) MEMZERO(target,size) -#else /* 80x86 case, define if we can */ -#ifdef USE_FMEM -#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) -#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) -#endif -#endif - - -GLOBAL(void) -jcopy_sample_rows (JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols) -/* Copy some rows of samples from one place to another. - * num_rows rows are copied from input_array[source_row++] - * to output_array[dest_row++]; these areas may overlap for duplication. - * The source and destination arrays must be at least as wide as num_cols. - */ -{ - register JSAMPROW inptr, outptr; -#ifdef FMEMCOPY - register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); -#else - register JDIMENSION count; -#endif - register int row; - - input_array += source_row; - output_array += dest_row; - - for (row = num_rows; row > 0; row--) { - inptr = *input_array++; - outptr = *output_array++; -#ifdef FMEMCOPY - FMEMCOPY(outptr, inptr, count); -#else - for (count = num_cols; count > 0; count--) - *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ -#endif - } -} - - -GLOBAL(void) -jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks) -/* Copy a row of coefficient blocks from one place to another. */ -{ -#ifdef FMEMCOPY - FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); -#else - register JCOEFPTR inptr, outptr; - register long count; - - inptr = (JCOEFPTR) input_row; - outptr = (JCOEFPTR) output_row; - for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { - *outptr++ = *inptr++; - } -#endif -} - - -GLOBAL(void) -jzero_far (void FAR * target, size_t bytestozero) -/* Zero out a chunk of FAR memory. */ -/* This might be sample-array data, block-array data, or alloc_large data. */ -{ -#ifdef FMEMZERO - FMEMZERO(target, bytestozero); -#else - register char FAR * ptr = (char FAR *) target; - register size_t count; - - for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; - } -#endif -} diff --git a/third_party/libjpeg/jchuff.h b/third_party/libjpeg/jchuff.h deleted file mode 100644 index a9599fc1e6f9613ca5b7ce02a3b734f0c89cba51..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jchuff.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * jchuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy encoding routines - * that are shared between the sequential encoder (jchuff.c) and the - * progressive encoder (jcphuff.c). No other modules need to see these. - */ - -/* The legal range of a DCT coefficient is - * -1024 .. +1023 for 8-bit data; - * -16384 .. +16383 for 12-bit data. - * Hence the magnitude should always fit in 10 or 14 bits respectively. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif - -/* Derived data constructed for each Huffman table */ - -typedef struct { - unsigned int ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ -} c_derived_tbl; - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_c_derived_tbl jMkCDerived -#define jpeg_gen_optimal_table jGenOptTbl -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Expand a Huffman table definition into the derived format */ -EXTERN(void) jpeg_make_c_derived_tbl - JPP((j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl)); - -/* Generate an optimal table definition given the specified counts */ -EXTERN(void) jpeg_gen_optimal_table - JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/third_party/libjpeg/jconfig.h b/third_party/libjpeg/jconfig.h deleted file mode 100644 index ea3c39779966bf6eb555b1a7ba3d665ba20d92f0..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jconfig.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ -/* see jconfig.doc for explanations */ - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ -#undef CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ -#undef NEED_SHORT_EXTERNAL_NAMES -#undef INCOMPLETE_TYPES_BROKEN - -/* Define "boolean" as unsigned char, not int, per Windows custom */ -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ - - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED - -#endif /* JPEG_INTERNALS */ - -#ifdef JPEG_CJPEG_DJPEG - -#define BMP_SUPPORTED /* BMP image file format */ -#define GIF_SUPPORTED /* GIF image file format */ -#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ -#undef RLE_SUPPORTED /* Utah RLE image file format */ -#define TARGA_SUPPORTED /* Targa image file format */ - -#define TWO_FILE_COMMANDLINE /* optional */ -#define USE_SETMODE /* Microsoft has setmode() */ -#undef NEED_SIGNAL_CATCHER -#undef DONT_USE_B_MODE -#undef PROGRESS_REPORT /* optional */ - -#endif /* JPEG_CJPEG_DJPEG */ diff --git a/third_party/libjpeg/jdct.h b/third_party/libjpeg/jdct.h deleted file mode 100644 index 04192a266ae148072feecb5feff6bca796c2b71a..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jdct.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * jdct.h - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the forward and - * inverse DCT modules. These declarations are private to the DCT managers - * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease - * machine-dependent tuning (e.g., assembly coding). - */ - - -/* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). - * The DCT outputs are returned scaled up by a factor of 8; they therefore - * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This - * convention improves accuracy in integer implementations and saves some - * work in floating-point ones. - * Quantization of the output coefficients is done by jcdctmgr.c. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef int DCTELEM; /* 16 or 32 bits is fine */ -#else -typedef INT32 DCTELEM; /* must have 32 bits */ -#endif - -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); - - -/* - * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer - * to an output sample array. The routine must dequantize the input data as - * well as perform the IDCT; for dequantization, it uses the multiplier table - * pointed to by compptr->dct_table. The output data is to be placed into the - * sample array starting at a specified column. (Any row offset needed will - * be applied to the array pointer before it is passed to the IDCT code.) - * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. - */ - -/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ - -/* - * Each IDCT routine has its own ideas about the best dct_table element type. - */ - -typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ -#if BITS_IN_JSAMPLE == 8 -typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ -#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ -#else -typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ -#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ -#endif -typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ - - -/* - * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could - * be quite far out of range if the input data is corrupt, so a bulletproof - * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. - */ - -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) - -#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_fdct_islow jFDislow -#define jpeg_fdct_ifast jFDifast -#define jpeg_fdct_float jFDfloat -#define jpeg_idct_islow jRDislow -#define jpeg_idct_ifast jRDifast -#define jpeg_idct_float jRDfloat -#define jpeg_idct_4x4 jRD4x4 -#define jpeg_idct_2x2 jRD2x2 -#define jpeg_idct_1x1 jRD1x1 -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Extern declarations for the forward and inverse DCT routines. */ - -EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); - -EXTERN(void) jpeg_idct_islow - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_ifast - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_float - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_1x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); - - -/* - * Macros for handling fixed-point arithmetic; these are used by many - * but not all of the DCT/IDCT modules. - * - * All values are expected to be of type INT32. - * Fractional constants are scaled left by CONST_BITS bits. - * CONST_BITS is defined within each module using these macros, - * and may differ from one module to the next. - */ - -#define ONE ((INT32) 1) -#define CONST_SCALE (ONE << CONST_BITS) - -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, - * thus causing a lot of useless floating-point operations at run time. - */ - -#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) - -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - -#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * This macro is used only when the two inputs will actually be no more than - * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a - * full 32x32 multiply. This provides a useful speedup on many machines. - * Unfortunately there is no way to specify a 16x16->32 multiply portably - * in C, but some C compilers will do the right thing if you provide the - * correct combination of casts. - */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) -#endif -#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) -#endif - -#ifndef MULTIPLY16C16 /* default definition */ -#define MULTIPLY16C16(var,const) ((var) * (const)) -#endif - -/* Same except both inputs are variables. */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) -#endif - -#ifndef MULTIPLY16V16 /* default definition */ -#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) -#endif diff --git a/third_party/libjpeg/jdhuff.h b/third_party/libjpeg/jdhuff.h deleted file mode 100644 index ae19b6cafd7e81f94499d92876a6cf88bcafda86..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jdhuff.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * jdhuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. - */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_d_derived_tbl jMkDDerived -#define jpeg_fill_bit_buffer jFilBitBuf -#define jpeg_huff_decode jHufDecode -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */ - UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */ -} d_derived_tbl; - -/* Expand a Huffman table definition into the derived format */ -EXTERN(void) jpeg_make_d_derived_tbl - JPP((j_decompress_ptr cinfo, boolean isDC, int tblno, - d_derived_tbl ** pdtbl)); - - -/* - * Fetching the next N bits from the input stream is a time-critical operation - * for the Huffman decoders. We implement it with a combination of inline - * macros and out-of-line subroutines. Note that N (the number of bits - * demanded at one time) never exceeds 15 for JPEG use. - * - * We read source bytes into get_buffer and dole out bits as needed. - * If get_buffer already contains enough bits, they are fetched in-line - * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough - * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer - * as full as possible (not just to the number of bits needed; this - * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer). - * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension. - * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains - * at least the requested number of bits --- dummy zeroes are inserted if - * necessary. - */ - -typedef INT32 bit_buf_type; /* type of bit-extraction buffer */ -#define BIT_BUF_SIZE 32 /* size of buffer in bits */ - -/* If long is > 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ - j_decompress_ptr cinfo; /* back link to decompress master record */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - -/* Load up the bit buffer to a depth of at least nbits */ -EXTERN(boolean) jpeg_fill_bit_buffer - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, int nbits)); - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - -/* Out-of-line case for Huffman code fetching */ -EXTERN(int) jpeg_huff_decode - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/third_party/libjpeg/jerror.h b/third_party/libjpeg/jerror.h deleted file mode 100644 index 06d344067a3a4a3c4787cc7813fb1173fabb7d78..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jerror.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * jerror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the JPEG library. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - * A set of error-reporting macros are defined too. Some applications using - * the JPEG library may wish to include this file to get the error codes - * and/or the macros. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef JERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* JERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ - -/* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_ARITH_NOTIMPL, - "Sorry, there are legal restrictions on arithmetic coding") -JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") -JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") -JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") -JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") -JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") -JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") -JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") -JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") -JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") -JMESSAGE(JERR_BAD_LIB_VERSION, - "Wrong JPEG library version: library is %d, caller expects %d") -JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") -JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") -JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") -JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") -JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") -JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") -JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") -JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") -JMESSAGE(JERR_BAD_STRUCT_SIZE, - "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") -JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") -JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") -JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") -JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") -JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") -JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") -JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") -JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") -JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") -JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") -JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") -JMESSAGE(JERR_EMS_READ, "Read from EMS failed") -JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") -JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") -JMESSAGE(JERR_FILE_READ, "Input file read error") -JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") -JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") -JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") -JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") -JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") -JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") -JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") -JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, - "Cannot transcode due to multiple use of quantization table %d") -JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") -JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") -JMESSAGE(JERR_NOTIMPL, "Not implemented yet") -JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") -JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") -JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") -JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") -JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") -JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") -JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") -JMESSAGE(JERR_QUANT_COMPONENTS, - "Cannot quantize more than %d color components") -JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") -JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") -JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") -JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") -JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") -JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") -JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") -JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") -JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") -JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") -JMESSAGE(JERR_TFILE_WRITE, - "Write failed on temporary file --- out of disk space?") -JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") -JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") -JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") -JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") -JMESSAGE(JERR_XMS_READ, "Read from XMS failed") -JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") -JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) -JMESSAGE(JMSG_VERSION, JVERSION) -JMESSAGE(JTRC_16BIT_TABLES, - "Caution: quantization tables are too coarse for baseline JPEG") -JMESSAGE(JTRC_ADOBE, - "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") -JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") -JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") -JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") -JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") -JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") -JMESSAGE(JTRC_DRI, "Define Restart Interval %u") -JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") -JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") -JMESSAGE(JTRC_EOI, "End Of Image") -JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") -JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") -JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, - "Warning: thumbnail image size does not match data length %u") -JMESSAGE(JTRC_JFIF_EXTENSION, - "JFIF extension marker: type 0x%02x, length %u") -JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") -JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") -JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") -JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") -JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") -JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") -JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") -JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") -JMESSAGE(JTRC_RST, "RST%d") -JMESSAGE(JTRC_SMOOTH_NOTIMPL, - "Smoothing not supported with nonstandard sampling ratios") -JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") -JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") -JMESSAGE(JTRC_SOI, "Start of Image") -JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") -JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") -JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") -JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") -JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") -JMESSAGE(JTRC_THUMB_JPEG, - "JFIF extension marker: JPEG-compressed thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_PALETTE, - "JFIF extension marker: palette thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_RGB, - "JFIF extension marker: RGB thumbnail image, length %u") -JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") -JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") -JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") -JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") -JMESSAGE(JWRN_BOGUS_PROGRESSION, - "Inconsistent progression sequence for component %d coefficient %d") -JMESSAGE(JWRN_EXTRANEOUS_DATA, - "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") -JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") -JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") -JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") -JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") -JMESSAGE(JWRN_MUST_RESYNC, - "Corrupt JPEG data: found marker 0x%02x instead of RST%d") -JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") -JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTMSGCODE -} J_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE - - -#ifndef JERROR_H -#define JERROR_H - -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ -#define ERREXIT(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT3(cinfo,code,p1,p2,p3) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXITS(cinfo,code,str) \ - ((cinfo)->err->msg_code = (code), \ - FXSYS_strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) - -#define MAKESTMT(stuff) do { stuff } while (0) - -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ -#define WARNMS(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) - -/* Informational/debugging messages */ -#define TRACEMS(cinfo,lvl,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS1(cinfo,lvl,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS2(cinfo,lvl,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMSS(cinfo,lvl,code,str) \ - ((cinfo)->err->msg_code = (code), \ - FXSYS_strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) - -#endif /* JERROR_H */ diff --git a/third_party/libjpeg/jinclude.h b/third_party/libjpeg/jinclude.h deleted file mode 100644 index 6f6a87c79ea518eff10f9d41c2f905a2bc632e52..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jinclude.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * jinclude.h - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file exists to provide a single place to fix any problems with - * including the wrong system include files. (Common problems are taken - * care of by the standard jconfig symbols, but on really weird systems - * you may have to edit this file.) - * - * NOTE: this file is NOT intended to be included by applications using the - * JPEG library. Most applications need only include jpeglib.h. - */ - - -/* Include auto-config file to find out which system include files we need. */ - -#include "jconfig.h" /* auto configuration options */ -#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ - -#include "core/fxcrt/fx_system.h" - -/* - * We need the NULL macro and size_t typedef. - * On an ANSI-conforming system it is sufficient to include <stddef.h>. - * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to - * pull in <sys/types.h> as well. - * Note that the core JPEG library does not require <stdio.h>; - * only the default error handler and data source/destination modules do. - * But we must pull it in because of the references to FILE in jpeglib.h. - * You can remove those references if you want to compile without <stdio.h>. - */ - -#ifdef _DEBUG -#define CRTDBG_MAP_ALLOC -//#include <stdlib.h> -//#include <crtdbg.h> -#endif - -#ifdef HAVE_STDDEF_H -#include <stddef.h> -#endif - -#ifdef HAVE_STDLIB_H -//#include <stdlib.h> -#endif - -#ifdef NEED_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifndef FAR -#define FAR -#endif - -//#include <stdio.h> - -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in <string.h>. - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in <memory.h>. - * - * NOTE: we assume the size parameters to these functions are of type size_t. - * Change the casts in these macros if not! - */ - -#ifdef NEED_BSD_STRINGS - -//#include <strings.h> -#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) -#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) - -#else /* not BSD, assume ANSI/SysV string lib */ - -//#include <string.h> -#define MEMZERO(target,size) FXSYS_memset((void *)(target), 0, (size_t)(size)) -#define MEMCOPY(dest,src,size) FXSYS_memcpy((void *)(dest), (const void *)(src), (size_t)(size)) - -#endif - -/* - * In ANSI C, and indeed any rational implementation, size_t is also the - * type returned by sizeof(). However, it seems there are some irrational - * implementations out there, in which sizeof() returns an int even though - * size_t is defined as long or unsigned long. To ensure consistent results - * we always use this SIZEOF() macro in place of using sizeof() directly. - */ - -#define SIZEOF(object) ((size_t) sizeof(object)) - -/* - * The modules that use fread() and fwrite() always invoke them through - * these macros. On some systems you may need to twiddle the argument casts. - * CAUTION: argument order is different from underlying functions! - */ - -#define JFREAD(file,buf,sizeofbuf) \ - ((size_t) FXSYS_fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFWRITE(file,buf,sizeofbuf) \ - ((size_t) FXSYS_fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/third_party/libjpeg/jmemsys.h b/third_party/libjpeg/jmemsys.h deleted file mode 100644 index 896688181bf54b9ba0f10224a5a4c2ef42c9c099..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jmemsys.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * jmemsys.h - * - * Copyright (C) 1992-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file defines the interface between the system-independent - * and system-dependent portions of the JPEG memory manager. No other - * modules need include it. (The system-independent portion is jmemmgr.c; - * there are several different versions of the system-dependent portion.) - * - * This file works as-is for the system-dependent memory managers supplied - * in the IJG distribution. You may need to modify it if you write a - * custom memory manager. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_get_small jGetSmall -#define jpeg_free_small jFreeSmall -#define jpeg_get_large jGetLarge -#define jpeg_free_large jFreeLarge -#define jpeg_mem_available jMemAvail -#define jpeg_open_backing_store jOpenBackStore -#define jpeg_mem_init jMemInit -#define jpeg_mem_term jMemTerm -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * These two functions are used to allocate and release small chunks of - * memory. (Typically the total amount requested through jpeg_get_small is - * no more than 20K or so; this will be requested in chunks of a few K each.) - * Behavior should be the same as for the standard library functions malloc - * and free; in particular, jpeg_get_small must return NULL on failure. - * On most systems, these ARE malloc and free. jpeg_free_small is passed the - * size of the object being freed, just in case it's needed. - * On an 80x86 machine using small-data memory model, these manage near heap. - */ - -EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); -EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, - size_t sizeofobject)); - -/* - * These two functions are used to allocate and release large chunks of - * memory (up to the total free space designated by jpeg_mem_available). - * The interface is the same as above, except that on an 80x86 machine, - * far pointers are used. On most other machines these are identical to - * the jpeg_get/free_small routines; but we keep them separate anyway, - * in case a different allocation strategy is desirable for large chunks. - */ - -EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, - size_t sizeofobject)); -EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, - size_t sizeofobject)); - -/* - * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may - * be requested in a single call to jpeg_get_large (and jpeg_get_small for that - * matter, but that case should never come into play). This macro is needed - * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. - * On those machines, we expect that jconfig.h will provide a proper value. - * On machines with 32-bit flat address spaces, any large constant may be used. - * - * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type - * size_t and will be a multiple of sizeof(align_type). - */ - -#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ -#define MAX_ALLOC_CHUNK 1000000000L -#endif - -/* - * This routine computes the total space still available for allocation by - * jpeg_get_large. If more space than this is needed, backing store will be - * used. NOTE: any memory already allocated must not be counted. - * - * There is a minimum space requirement, corresponding to the minimum - * feasible buffer sizes; jmemmgr.c will request that much space even if - * jpeg_mem_available returns zero. The maximum space needed, enough to hold - * all working storage in memory, is also passed in case it is useful. - * Finally, the total space already allocated is passed. If no better - * method is available, cinfo->mem->max_memory_to_use - already_allocated - * is often a suitable calculation. - * - * It is OK for jpeg_mem_available to underestimate the space available - * (that'll just lead to more backing-store access than is really necessary). - * However, an overestimate will lead to failure. Hence it's wise to subtract - * a slop factor from the true available space. 5% should be enough. - * - * On machines with lots of virtual memory, any large constant may be returned. - * Conversely, zero may be returned to always use the minimum amount of memory. - */ - -EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); - - -/* - * This structure holds whatever state is needed to access a single - * backing-store object. The read/write/close method pointers are called - * by jmemmgr.c to manipulate the backing-store object; all other fields - * are private to the system-dependent backing store routines. - */ - -#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ - -typedef struct backing_store_struct * backing_store_ptr; - -typedef struct backing_store_struct { - /* Methods for reading/writing/closing this backing-store object */ - JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - backing_store_ptr info)); - - /* Private fields for system-dependent backing-store management */ - /* For a typical implementation with temp files, we need: */ - FXSYS_FILE * temp_file; /* stdio reference to temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ -} backing_store_info; - - -/* - * Initial opening of a backing-store object. This must fill in the - * read/write/close pointers in the object. The read/write routines - * may take an error exit if the specified maximum file size is exceeded. - * (If jpeg_mem_available always returns a large value, this routine can - * just take an error exit.) - */ - -EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, - backing_store_ptr info, - long total_bytes_needed)); - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. jpeg_mem_init will be called before anything is - * allocated (and, therefore, nothing in cinfo is of use except the error - * manager pointer). It should return a suitable default value for - * max_memory_to_use; this may subsequently be overridden by the surrounding - * application. (Note that max_memory_to_use is only important if - * jpeg_mem_available chooses to consult it ... no one else will.) - * jpeg_mem_term may assume that all requested memory has been freed and that - * all opened backing-store objects have been closed. - */ - -EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/third_party/libjpeg/jmorecfg.h b/third_party/libjpeg/jmorecfg.h deleted file mode 100644 index a80d90495eaf082c3647fdeedadc21207738fcc8..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jmorecfg.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains additional configuration options that customize the - * JPEG software for special applications or support machine-dependent - * optimizations. Most users will not need to touch this file. - */ - -#ifdef _MSC_VER -#pragma warning (disable : 4142) -#endif - -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ - -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ - - -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - -#define MAX_COMPONENTS 10 /* maximum number of image components */ - - -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JSAMPLE; -#ifdef CHAR_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ - - -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 - -#endif /* BITS_IN_JSAMPLE == 12 */ - - -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - -typedef short JCOEF; - - -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JOCTET; -#define GETJOCTET(value) (value) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JOCTET; -#ifdef CHAR_IS_UNSIGNED -#define GETJOCTET(value) (value) -#else -#define GETJOCTET(value) ((value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -#if _FX_OS_ != _FX_VXWORKS_ - -/* UINT8 must hold at least the values 0..255. */ - -#ifdef HAVE_UNSIGNED_CHAR -typedef unsigned char UINT8; -#else /* not HAVE_UNSIGNED_CHAR */ -#ifdef CHAR_IS_UNSIGNED -typedef char UINT8; -#else /* not CHAR_IS_UNSIGNED */ -typedef short UINT8; -#endif /* CHAR_IS_UNSIGNED */ -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* UINT16 must hold at least the values 0..65535. */ - -#ifdef HAVE_UNSIGNED_SHORT -typedef unsigned short UINT16; -#else /* not HAVE_UNSIGNED_SHORT */ -typedef unsigned int UINT16; -#endif /* HAVE_UNSIGNED_SHORT */ - -/* INT16 must hold at least the values -32768..32767. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ -typedef short INT16; -#endif - -/* INT32 must hold at least signed 32-bit values. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ -typedef int INT32; -#endif - -#endif - -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - -typedef unsigned int JDIMENSION; - -#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ - - -/* These macros are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions; - * in particular, you'll need to do that to make the library a Windows DLL. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -/* a function called through method pointers: */ -#define METHODDEF(type) static type -/* a function used only in its module: */ -#define LOCAL(type) static type -/* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type - -/* a reference to a GLOBAL function: */ -#define EXTERN(type) extern type - - -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - * Again, you can customize this if you need special linkage keywords. - */ - -#ifdef HAVE_PROTOTYPES -#define JMETHOD(type,methodname,arglist) type (*methodname) arglist -#else -#define JMETHOD(type,methodname,arglist) type (*methodname) () -#endif - - -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - -#ifdef NEED_FAR_POINTERS -#define FAR far -#else -//#define FAR -#endif - - -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - -#ifndef HAVE_BOOLEAN -typedef int boolean; -#endif -#ifndef FALSE /* in case these macros already exist */ -#define FALSE 0 /* values of boolean */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif - - -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - -#ifdef JPEG_INTERNALS -#define JPEG_INTERNAL_OPTIONS -#endif - -#ifdef JPEG_INTERNAL_OPTIONS - - -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - -/* Capability options common to encoder and decoder: */ - -#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ -#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ -#undef DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ - -/* Encoder capability options: */ - -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ -#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ - -/* Decoder capability options: */ - -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ -#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ -#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ -#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#undef QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ - -#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ -#define RGB_GREEN 1 /* Offset of Green */ -#define RGB_BLUE 2 /* Offset of Blue */ -#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ - - -/* Definitions for speed-related optimizations. */ - - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - -#ifndef INLINE -#ifdef __GNUC__ /* for instance, GNU C knows about inline */ -#define INLINE __inline__ -#endif -#ifndef INLINE -#define INLINE /* default is to define it as empty */ -#endif -#endif - - -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - -#ifndef MULTIPLIER -#define MULTIPLIER int /* type for fastest integer multiply */ -#endif - - -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - -#ifndef FAST_FLOAT -#ifdef HAVE_PROTOTYPES -#define FAST_FLOAT float -#else -#define FAST_FLOAT double -#endif -#endif - -#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/third_party/libjpeg/jpegint.h b/third_party/libjpeg/jpegint.h deleted file mode 100644 index 95b00d405caeca1dc971b37a94bbadc566f3074b..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jpegint.h +++ /dev/null @@ -1,392 +0,0 @@ -/* - * jpegint.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides common declarations for the various JPEG modules. - * These declarations are considered internal to the JPEG library; most - * applications using the library shouldn't need to include this file. - */ - - -/* Declarations for both compression & decompression */ - -typedef enum { /* Operating modes for buffer controllers */ - JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ - JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ - JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ - JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ -} J_BUF_MODE; - -/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ -#define CSTATE_START 100 /* after create_compress */ -#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ -#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ -#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ -#define DSTATE_START 200 /* after create_decompress */ -#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ -#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ -#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ -#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ -#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ -#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ -#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ -#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ -#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ -#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ - - -/* Declarations for compression modules */ - -/* Master control module */ -struct jpeg_comp_master { - JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); - JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean call_pass_startup; /* True if pass_startup must be called */ - boolean is_last_pass; /* True during last pass */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_c_main_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); -}; - -/* Compression preprocessing (downsampling input buffer control) */ -struct jpeg_c_prep_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, - JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_c_coef_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf)); -}; - -/* Colorspace conversion */ -struct jpeg_color_converter { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, color_convert, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows)); -}; - -/* Downsampling */ -struct jpeg_downsampler { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Forward DCT (also controls coefficient quantization) */ -struct jpeg_forward_dct { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ - JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); -}; - -/* Entropy encoding */ -struct jpeg_entropy_encoder { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); - JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); -}; - -/* Marker writing */ -struct jpeg_marker_writer { - JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); - JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); - /* These routines are exported to allow insertion of extra markers */ - /* Probably only COM and APPn markers should be written this way */ - JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, - unsigned int datalen)); - JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); -}; - - -/* Declarations for decompression modules */ - -/* Master control module */ -struct jpeg_decomp_master { - JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ -}; - -/* Input control module */ -struct jpeg_input_controller { - JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); - JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean has_multiple_scans; /* True if file has multiple scans */ - boolean eoi_reached; /* True when EOI has been consumed */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_d_main_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_d_coef_controller { - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); - JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, - JSAMPIMAGE output_buf)); - /* Pointer to array of coefficient virtual arrays, or NULL if none */ - jvirt_barray_ptr *coef_arrays; -}; - -/* Decompression postprocessing (color quantization buffer control) */ -struct jpeg_d_post_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Marker reading & parsing */ -struct jpeg_marker_reader { - JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); - /* Read markers until SOS or EOI. - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); - /* Read a restart marker --- exported for use by entropy decoder only */ - jpeg_marker_parser_method read_restart_marker; - - /* State of marker reader --- nominally internal, but applications - * supplying COM or APPn handlers might like to know the state. - */ - boolean saw_SOI; /* found SOI? */ - boolean saw_SOF; /* found SOF? */ - int next_restart_num; /* next restart number expected (0-7) */ - unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ -}; - -/* Entropy decoding */ -struct jpeg_entropy_decoder { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - /* This is here to share code between baseline and progressive decoders; */ - /* other modules probably should not use it */ - boolean insufficient_data; /* set TRUE after emitting warning */ -}; - -/* Inverse DCT (also performs dequantization) */ -typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); - -struct jpeg_inverse_dct { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - /* It is useful to allow each component to have a separate IDCT method. */ - inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; -}; - -/* Upsampling (note that upsampler must also call color converter) */ -struct jpeg_upsampler { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, upsample, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Colorspace conversion */ -struct jpeg_color_deconverter { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, color_convert, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows)); -}; - -/* Color quantization or color precision reduction */ -struct jpeg_color_quantizer { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); - JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, - int num_rows)); - JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); -}; - - -/* Miscellaneous useful macros */ - -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#undef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - - -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define SHIFT_TEMPS INT32 shift_temp; -#define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) -#else -#define SHIFT_TEMPS -#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_compress_master jICompress -#define jinit_c_master_control jICMaster -#define jinit_c_main_controller jICMainC -#define jinit_c_prep_controller jICPrepC -#define jinit_c_coef_controller jICCoefC -#define jinit_color_converter jICColor -#define jinit_downsampler jIDownsampler -#define jinit_forward_dct jIFDCT -#define jinit_huff_encoder jIHEncoder -#define jinit_phuff_encoder jIPHEncoder -#define jinit_marker_writer jIMWriter -#define jinit_master_decompress jIDMaster -#define jinit_d_main_controller jIDMainC -#define jinit_d_coef_controller jIDCoefC -#define jinit_d_post_controller jIDPostC -#define jinit_input_controller jIInCtlr -#define jinit_marker_reader jIMReader -#define jinit_huff_decoder jIHDecoder -#define jinit_phuff_decoder jIPHDecoder -#define jinit_inverse_dct jIIDCT -#define jinit_upsampler jIUpsampler -#define jinit_color_deconverter jIDColor -#define jinit_1pass_quantizer jI1Quant -#define jinit_2pass_quantizer jI2Quant -#define jinit_merged_upsampler jIMUpsampler -#define jinit_memory_mgr jIMemMgr -#define jdiv_round_up jDivRound -#define jround_up jRound -#define jcopy_sample_rows jCopySamples -#define jcopy_block_row jCopyBlocks -#define jzero_far jZeroFar -#define jpeg_zigzag_order jZIGTable -#define jpeg_natural_order jZAGTable -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Compression module initialization routines */ -EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, - boolean transcode_only)); -EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ -EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); -/* Memory manager initialization */ -EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); - -/* Utility routines in jutils.c */ -EXTERN(long) jdiv_round_up JPP((long a, long b)); -EXTERN(long) jround_up JPP((long a, long b)); -EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); -EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks)); -EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); -/* Constant tables in jutils.c */ -#if 0 /* This table is not actually needed in v6a */ -extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ -#endif -extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ - -/* Suppress undefined-structure complaints if necessary. */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -#endif -#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/third_party/libjpeg/jpeglib.h b/third_party/libjpeg/jpeglib.h deleted file mode 100644 index f6af4f2b4798b7062da0cfdb7d13e23da97dc59d..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jpeglib.h +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the application interface for the JPEG library. - * Most applications using the library need only include this file, - * and perhaps jerror.h if they want to know the exact error codes. - */ - -#ifndef JPEGLIB_H -#define JPEGLIB_H - -#define FOXIT_PREFIX(origName) FPDFAPIJPEG_##origName - -#define jcopy_block_row FOXIT_PREFIX(jcopy_block_row) -#define jcopy_sample_rows FOXIT_PREFIX(jcopy_sample_rows) -#define jdiv_round_up FOXIT_PREFIX(jdiv_round_up) -#define jinit_1pass_quantizer FOXIT_PREFIX(jinit_1pass_quantizer) -#define jinit_2pass_quantizer FOXIT_PREFIX(jinit_2pass_quantizer) -#define jinit_c_coef_controller FOXIT_PREFIX(jinit_c_coef_controller) -#define jinit_c_main_controller FOXIT_PREFIX(jinit_c_main_controller) -#define jinit_c_master_control FOXIT_PREFIX(jinit_c_master_control) -#define jinit_c_prep_controller FOXIT_PREFIX(jinit_c_prep_controller) -#define jinit_color_converter FOXIT_PREFIX(jinit_color_converter) -#define jinit_color_deconverter FOXIT_PREFIX(jinit_color_deconverter) -#define jinit_compress_master FOXIT_PREFIX(jinit_compress_master) -#define jinit_d_coef_controller FOXIT_PREFIX(jinit_d_coef_controller) -#define jinit_d_main_controller FOXIT_PREFIX(jinit_d_main_controller) -#define jinit_d_post_controller FOXIT_PREFIX(jinit_d_post_controller) -#define jinit_downsampler FOXIT_PREFIX(jinit_downsampler) -#define jinit_forward_dct FOXIT_PREFIX(jinit_forward_dct) -#define jinit_huff_decoder FOXIT_PREFIX(jinit_huff_decoder) -#define jinit_huff_encoder FOXIT_PREFIX(jinit_huff_encoder) -#define jinit_input_controller FOXIT_PREFIX(jinit_input_controller) -#define jinit_inverse_dct FOXIT_PREFIX(jinit_inverse_dct) -#define jinit_marker_reader FOXIT_PREFIX(jinit_marker_reader) -#define jinit_marker_writer FOXIT_PREFIX(jinit_marker_writer) -#define jinit_master_decompress FOXIT_PREFIX(jinit_master_decompress) -#define jinit_memory_mgr FOXIT_PREFIX(jinit_memory_mgr) -#define jinit_merged_upsampler FOXIT_PREFIX(jinit_merged_upsampler) -#define jinit_phuff_decoder FOXIT_PREFIX(jinit_phuff_decoder) -#define jinit_phuff_encoder FOXIT_PREFIX(jinit_phuff_encoder) -#define jinit_upsampler FOXIT_PREFIX(jinit_upsampler) -#define jpeg_CreateCompress FOXIT_PREFIX(jpeg_CreateCompress) -#define jpeg_CreateDecompress FOXIT_PREFIX(jpeg_CreateDecompress) -#define jpeg_abort FOXIT_PREFIX(jpeg_abort) -#define jpeg_abort_compress FOXIT_PREFIX(jpeg_abort_compress) -#define jpeg_abort_decompress FOXIT_PREFIX(jpeg_abort_decompress) -#define jpeg_add_quant_table FOXIT_PREFIX(jpeg_add_quant_table) -#define jpeg_alloc_huff_table FOXIT_PREFIX(jpeg_alloc_huff_table) -#define jpeg_alloc_quant_table FOXIT_PREFIX(jpeg_alloc_quant_table) -#define jpeg_calc_output_dimensions FOXIT_PREFIX(jpeg_calc_output_dimensions) -#define jpeg_consume_input FOXIT_PREFIX(jpeg_consume_input) -#define jpeg_default_colorspace FOXIT_PREFIX(jpeg_default_colorspace) -#define jpeg_destroy FOXIT_PREFIX(jpeg_destroy) -#define jpeg_destroy_compress FOXIT_PREFIX(jpeg_destroy_compress) -#define jpeg_destroy_decompress FOXIT_PREFIX(jpeg_destroy_decompress) -#define jpeg_fdct_ifast FOXIT_PREFIX(jpeg_fdct_ifast) -#define jpeg_fdct_islow FOXIT_PREFIX(jpeg_fdct_islow) -#define jpeg_fill_bit_buffer FOXIT_PREFIX(jpeg_fill_bit_buffer) -#define jpeg_finish_compress FOXIT_PREFIX(jpeg_finish_compress) -#define jpeg_finish_decompress FOXIT_PREFIX(jpeg_finish_decompress) -#define jpeg_finish_output FOXIT_PREFIX(jpeg_finish_output) -#define jpeg_free_large FOXIT_PREFIX(jpeg_free_large) -#define jpeg_free_small FOXIT_PREFIX(jpeg_free_small) -#define jpeg_gen_optimal_table FOXIT_PREFIX(jpeg_gen_optimal_table) -#define jpeg_get_large FOXIT_PREFIX(jpeg_get_large) -#define jpeg_get_small FOXIT_PREFIX(jpeg_get_small) -#define jpeg_has_multiple_scans FOXIT_PREFIX(jpeg_has_multiple_scans) -#define jpeg_huff_decode FOXIT_PREFIX(jpeg_huff_decode) -#define jpeg_idct_1x1 FOXIT_PREFIX(jpeg_idct_1x1) -#define jpeg_idct_2x2 FOXIT_PREFIX(jpeg_idct_2x2) -#define jpeg_idct_4x4 FOXIT_PREFIX(jpeg_idct_4x4) -#define jpeg_idct_float FOXIT_PREFIX(jpeg_idct_float) -#define jpeg_idct_ifast FOXIT_PREFIX(jpeg_idct_ifast) -#define jpeg_idct_islow FOXIT_PREFIX(jpeg_idct_islow) -#define jpeg_input_complete FOXIT_PREFIX(jpeg_input_complete) -#define jpeg_make_c_derived_tbl FOXIT_PREFIX(jpeg_make_c_derived_tbl) -#define jpeg_make_d_derived_tbl FOXIT_PREFIX(jpeg_make_d_derived_tbl) -#define jpeg_mem_available FOXIT_PREFIX(jpeg_mem_available) -#define jpeg_mem_init FOXIT_PREFIX(jpeg_mem_init) -#define jpeg_mem_term FOXIT_PREFIX(jpeg_mem_term) -#define jpeg_natural_order FOXIT_PREFIX(jpeg_natural_order) -#define jpeg_new_colormap FOXIT_PREFIX(jpeg_new_colormap) -#define jpeg_open_backing_store FOXIT_PREFIX(jpeg_open_backing_store) -#define jpeg_quality_scaling FOXIT_PREFIX(jpeg_quality_scaling) -#define jpeg_read_coefficients FOXIT_PREFIX(jpeg_read_coefficients) -#define jpeg_read_header FOXIT_PREFIX(jpeg_read_header) -#define jpeg_read_raw_data FOXIT_PREFIX(jpeg_read_raw_data) -#define jpeg_read_scanlines FOXIT_PREFIX(jpeg_read_scanlines) -#define jpeg_resync_to_restart FOXIT_PREFIX(jpeg_resync_to_restart) -#define jpeg_save_markers FOXIT_PREFIX(jpeg_save_markers) -#define jpeg_set_colorspace FOXIT_PREFIX(jpeg_set_colorspace) -#define jpeg_set_defaults FOXIT_PREFIX(jpeg_set_defaults) -#define jpeg_set_linear_quality FOXIT_PREFIX(jpeg_set_linear_quality) -#define jpeg_set_marker_processor FOXIT_PREFIX(jpeg_set_marker_processor) -#define jpeg_set_quality FOXIT_PREFIX(jpeg_set_quality) -#define jpeg_simple_progression FOXIT_PREFIX(jpeg_simple_progression) -#define jpeg_start_compress FOXIT_PREFIX(jpeg_start_compress) -#define jpeg_start_decompress FOXIT_PREFIX(jpeg_start_decompress) -#define jpeg_start_output FOXIT_PREFIX(jpeg_start_output) -#define jpeg_std_error FOXIT_PREFIX(jpeg_std_error) -#define jpeg_std_message_table FOXIT_PREFIX(jpeg_std_message_table) -#define jpeg_stdio_src FOXIT_PREFIX(jpeg_stdio_src) -#define jpeg_suppress_tables FOXIT_PREFIX(jpeg_suppress_tables) -#define jpeg_write_m_byte FOXIT_PREFIX(jpeg_write_m_byte) -#define jpeg_write_m_header FOXIT_PREFIX(jpeg_write_m_header) -#define jpeg_write_marker FOXIT_PREFIX(jpeg_write_marker) -#define jpeg_write_raw_data FOXIT_PREFIX(jpeg_write_raw_data) -#define jpeg_write_scanlines FOXIT_PREFIX(jpeg_write_scanlines) -#define jpeg_write_tables FOXIT_PREFIX(jpeg_write_tables) -#define jround_up FOXIT_PREFIX(jround_up) -#define jzero_far FOXIT_PREFIX(jzero_far) - - /* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - -#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ -#include "jconfig.h" /* widely used configuration options */ -#endif -#include "jmorecfg.h" /* seldom changed options */ - - -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". - */ - -#define JPEG_LIB_VERSION 62 /* Version 6b */ - - -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ -#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ -#ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ -#endif - - -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - -typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ -typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ -typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ - -typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ -typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ -typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ -typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ - -typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ - - -/* Types for JPEG compression parameters and working tables. */ - - -/* DCT coefficient quantization tables. */ - -typedef struct { - /* This array gives the coefficient quantizers in natural array order - * (not the zigzag order in which they are stored in a JPEG DQT marker). - * CAUTION: IJG versions prior to v6a kept this array in zigzag order. - */ - UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JQUANT_TBL; - - -/* Huffman coding tables. */ - -typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ - UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ - UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JHUFF_TBL; - - -/* Basic info about one component (color channel). */ - -typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ - int component_id; /* identifier for this component (0..255) */ - int component_index; /* its index in SOF or cinfo->comp_info[] */ - int h_samp_factor; /* horizontal sampling factor (1..4) */ - int v_samp_factor; /* vertical sampling factor (1..4) */ - int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ - int dc_tbl_no; /* DC entropy table selector (0..3) */ - int ac_tbl_no; /* AC entropy table selector (0..3) */ - - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ - JDIMENSION width_in_blocks; - JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. - */ - int DCT_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) - */ - JDIMENSION downsampled_width; /* actual width in samples */ - JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. - */ - boolean component_needed; /* do we need the value of this component? */ - - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ - int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ - - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is currently used only for decompression. - */ - JQUANT_TBL * quant_table; - - /* Private per-component storage for DCT or IDCT subsystem. */ - void * dct_table; -} jpeg_component_info; - - -/* The script for encoding a multiple-scan file is an array of these: */ - -typedef struct { - int comps_in_scan; /* number of components encoded in this scan */ - int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ -} jpeg_scan_info; - -/* The decompressor can save APPn and COM markers in a list of these: */ - -typedef struct jpeg_marker_struct * jpeg_saved_marker_ptr; - -struct jpeg_marker_struct { - jpeg_saved_marker_ptr next; /* next in list, or NULL */ - UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ - unsigned int original_length; /* # bytes of data in the file */ - unsigned int data_length; /* # bytes of data saved at data[] */ - JOCTET * data; /* the data contained in the marker */ - /* the marker length word is not counted in data_length or original_length */ -}; - -/* Known color spaces. */ - -typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ -} J_COLOR_SPACE; - -/* DCT/IDCT algorithm options. */ - -typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ -} J_DCT_METHOD; - -#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ -#define JDCT_DEFAULT JDCT_ISLOW -#endif -#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ -#define JDCT_FASTEST JDCT_IFAST -#endif - -/* Dithering options for decompression. */ - -typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ -} J_DITHER_MODE; - - -/* Common fields between JPEG compression and decompression master structs. */ - -#define jpeg_common_fields \ - struct jpeg_error_mgr * err; /* Error handler module */\ - struct jpeg_memory_mgr * mem; /* Memory manager module */\ - struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ - void * client_data; /* Available for use by application */\ - boolean is_decompressor; /* So common code can tell which is which */\ - int global_state /* For checking call sequence validity */ - -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ -struct jpeg_common_struct { - jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct jpeg_common_struct * j_common_ptr; -typedef struct jpeg_compress_struct * j_compress_ptr; -typedef struct jpeg_decompress_struct * j_decompress_ptr; - - -/* Master record for a compression instance */ - -struct jpeg_compress_struct { - jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - - /* Destination for compressed data */ - struct jpeg_destination_mgr * dest; - - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - - JDIMENSION image_width; /* input image width */ - JDIMENSION image_height; /* input image height */ - int input_components; /* # of color components in input image */ - J_COLOR_SPACE in_color_space; /* colorspace of input image */ - - double input_gamma; /* image gamma of input image */ - - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - - int data_precision; /* bits of precision in image data */ - - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - int num_scans; /* # of entries in scan_info array */ - const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ - - boolean raw_data_in; /* TRUE=caller supplies downsampled data */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - int smoothing_factor; /* 1..100, or 0 for no input smoothing */ - J_DCT_METHOD dct_method; /* DCT algorithm selector */ - - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ - unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ - int restart_in_rows; /* if > 0, MCU rows per restart interval */ - - /* Parameters controlling emission of special markers. */ - - boolean write_JFIF_header; /* should a JFIF marker be written? */ - UINT8 JFIF_major_version; /* What to write for the JFIF version number */ - UINT8 JFIF_minor_version; - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean write_Adobe_marker; /* should an Adobe marker be written? */ - - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ - boolean progressive_mode; /* TRUE if scan script uses progressive mode */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. - */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* - * Links to compression subobjects (methods and private variables of modules) - */ - struct jpeg_comp_master * master; - struct jpeg_c_main_controller * main; - struct jpeg_c_prep_controller * prep; - struct jpeg_c_coef_controller * coef; - struct jpeg_marker_writer * marker; - struct jpeg_color_converter * cconvert; - struct jpeg_downsampler * downsample; - struct jpeg_forward_dct * fdct; - struct jpeg_entropy_encoder * entropy; - jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ - int script_space_size; -}; - - -/* Master record for a decompression instance */ - -struct jpeg_decompress_struct { - jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - - /* Source of compressed data */ - struct jpeg_source_mgr * src; - - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - - JDIMENSION image_width; /* nominal image width (from SOF marker) */ - JDIMENSION image_height; /* nominal image height */ - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - - J_COLOR_SPACE out_color_space; /* colorspace for output */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - double output_gamma; /* image gamma wanted in output */ - - boolean buffered_image; /* TRUE=multiple output passes */ - boolean raw_data_out; /* TRUE=downsampled data wanted */ - - J_DCT_METHOD dct_method; /* IDCT algorithm selector */ - boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ - boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ - - boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ - J_DITHER_MODE dither_mode; /* type of color dithering to use */ - boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ - int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ - boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ - boolean enable_external_quant;/* enable future use of external colormap */ - boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - - JDIMENSION output_width; /* scaled image width */ - JDIMENSION output_height; /* scaled image height */ - int out_color_components; /* # of color components in out_color_space */ - int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ - int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ - int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ - JDIMENSION output_scanline; /* 0 .. output_height-1 */ - - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ - int input_scan_number; /* Number of SOS markers seen so far */ - JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ - int output_scan_number; /* Nominal scan number being displayed */ - JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ - int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ - - int data_precision; /* bits of precision in image data */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ - boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ - UINT8 JFIF_major_version; /* JFIF version number */ - UINT8 JFIF_minor_version; - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ - UINT8 Adobe_transform; /* Color transform code from Adobe marker */ - - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - - /* Aside from the specific data retained from APPn markers known to the - * library, the uninterpreted contents of any or all APPn and COM markers - * can be saved in a list for examination by the application. - */ - jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ - - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. - */ - - JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ - int unread_marker; - - /* - * Links to decompression subobjects (methods, private variables of modules) - */ - struct jpeg_decomp_master * master; - struct jpeg_d_main_controller * main; - struct jpeg_d_coef_controller * coef; - struct jpeg_d_post_controller * post; - struct jpeg_input_controller * inputctl; - struct jpeg_marker_reader * marker; - struct jpeg_entropy_decoder * entropy; - struct jpeg_inverse_dct * idct; - struct jpeg_upsampler * upsample; - struct jpeg_color_deconverter * cconvert; - struct jpeg_color_quantizer * cquantize; -}; - - -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - - -/* Error handler object */ - -struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ - JMETHOD(void, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ - JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ - JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ - JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); -#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ - JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ - int msg_code; -#define JMSG_STR_PARM_MAX 80 - union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; - } msg_parm; - - /* Standard state variables for error facility */ - - int trace_level; /* max msg_level that will be displayed */ - - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ - long num_warnings; /* number of corrupt-data warnings */ - - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ - const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ - const char * const * addon_message_table; /* Non-library errors */ - int first_addon_message; /* code for first string in addon table */ - int last_addon_message; /* code for last string in addon table */ -}; - - -/* Progress monitor object */ - -struct jpeg_progress_mgr { - JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); - - long pass_counter; /* work units completed in this pass */ - long pass_limit; /* total number of work units in this pass */ - int completed_passes; /* passes completed so far */ - int total_passes; /* total number of passes expected */ -}; - - -/* Data destination object for compression */ - -struct jpeg_destination_mgr { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - - JMETHOD(void, init_destination, (j_compress_ptr cinfo)); - JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); - JMETHOD(void, term_destination, (j_compress_ptr cinfo)); -}; - - -/* Data source object for decompression */ - -struct jpeg_source_mgr { - const JOCTET * next_input_byte; /* => next byte to read from buffer */ - size_t bytes_in_buffer; /* # of bytes remaining in buffer */ - - JMETHOD(void, init_source, (j_decompress_ptr cinfo)); - JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); - JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); - JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); - JMETHOD(void, term_source, (j_decompress_ptr cinfo)); -}; - - -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - -#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ -#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ -#define JPOOL_NUMPOOLS 2 - -typedef struct jvirt_sarray_control * jvirt_sarray_ptr; -typedef struct jvirt_barray_control * jvirt_barray_ptr; - - -struct jpeg_memory_mgr { - /* Method pointers */ - JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(void *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); - JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); - JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); - JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); - JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ - long max_memory_to_use; - - /* Maximum allocation request accepted by alloc_large. */ - long max_alloc_chunk; -}; - - -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ -typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); - - -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - -#ifdef HAVE_PROTOTYPES -#define JPP(arglist) arglist -#else -#define JPP(arglist) () -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_error jStdError -#define jpeg_CreateCompress jCreaCompress -#define jpeg_CreateDecompress jCreaDecompress -#define jpeg_destroy_compress jDestCompress -#define jpeg_destroy_decompress jDestDecompress -#define jpeg_stdio_dest jStdDest -#define jpeg_stdio_src jStdSrc -#define jpeg_set_defaults jSetDefaults -#define jpeg_set_colorspace jSetColorspace -#define jpeg_default_colorspace jDefColorspace -#define jpeg_set_quality jSetQuality -#define jpeg_set_linear_quality jSetLQuality -#define jpeg_add_quant_table jAddQuantTable -#define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_progression jSimProgress -#define jpeg_suppress_tables jSuppressTables -#define jpeg_alloc_quant_table jAlcQTable -#define jpeg_alloc_huff_table jAlcHTable -#define jpeg_start_compress jStrtCompress -#define jpeg_write_scanlines jWrtScanlines -#define jpeg_finish_compress jFinCompress -#define jpeg_write_raw_data jWrtRawData -#define jpeg_write_marker jWrtMarker -#define jpeg_write_m_header jWrtMHeader -#define jpeg_write_m_byte jWrtMByte -#define jpeg_write_tables jWrtTables -#define jpeg_read_header jReadHeader -#define jpeg_start_decompress jStrtDecompress -#define jpeg_read_scanlines jReadScanlines -#define jpeg_finish_decompress jFinDecompress -#define jpeg_read_raw_data jReadRawData -#define jpeg_has_multiple_scans jHasMultScn -#define jpeg_start_output jStrtOutput -#define jpeg_finish_output jFinOutput -#define jpeg_input_complete jInComplete -#define jpeg_new_colormap jNewCMap -#define jpeg_consume_input jConsumeInput -#define jpeg_calc_output_dimensions jCalcDimensions -#define jpeg_save_markers jSaveMarkers -#define jpeg_set_marker_processor jSetMarker -#define jpeg_read_coefficients jReadCoefs -#define jpeg_write_coefficients jWrtCoefs -#define jpeg_copy_critical_parameters jCopyCrit -#define jpeg_abort_compress jAbrtCompress -#define jpeg_abort_decompress jAbrtDecompress -#define jpeg_abort jAbort -#define jpeg_destroy jDestroy -#define jpeg_resync_to_restart jResyncRestart -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Default error-management setup */ -EXTERN(struct jpeg_error_mgr *) jpeg_std_error - JPP((struct jpeg_error_mgr * err)); - -/* Initialization of JPEG compression objects. - * jpeg_create_compress() and jpeg_create_decompress() are the exported - * names that applications should call. These expand to calls on - * jpeg_CreateCompress and jpeg_CreateDecompress with additional information - * passed for version mismatch checking. - * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. - */ -#define jpeg_create_compress(cinfo) \ - jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_compress_struct)) -#define jpeg_create_decompress(cinfo) \ - jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_decompress_struct)) -EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); -EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, - int version, size_t structsize)); -/* Destruction of JPEG compression objects */ -EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); - -#if 0 -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ -EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FXSYS_FILE * outfile)); -EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FXSYS_FILE * infile)); -#endif - -/* Default parameter setup for compression */ -EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ -EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); -EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); -EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); -EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); -EXTERN(int) jpeg_quality_scaling JPP((int quality)); -EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); -EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); -EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); - -/* Main entry points for compression */ -EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); -EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); -EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); - -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); - -/* Write a special marker. See libjpeg.doc concerning safe usage. */ -EXTERN(void) jpeg_write_marker - JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); -/* Same, but piecemeal. */ -EXTERN(void) jpeg_write_m_header - JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); -EXTERN(void) jpeg_write_m_byte - JPP((j_compress_ptr cinfo, int val)); - -/* Alternate compression function: just write an abbreviated table file */ -EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); - -/* Decompression startup: read start of JPEG datastream to see what's there */ -EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); -/* Return value is one of: */ -#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ -#define JPEG_HEADER_OK 1 /* Found valid image datastream */ -#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ - -/* Main entry points for decompression */ -EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); -EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); - -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); - -/* Additional entry points for buffered-image mode. */ -EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); -EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); -EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ -#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ -#define JPEG_REACHED_EOI 2 /* Reached end of image */ -#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ -#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ - -/* Precalculate output dimensions for current decompression parameters. */ -EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); - -/* Control saving of COM and APPn markers into marker_list. */ -EXTERN(void) jpeg_save_markers - JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); - -/* Install a special processing method for COM or APPn markers. */ -EXTERN(void) jpeg_set_marker_processor - JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); - -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ -EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); -EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); - -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ -EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); - -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ -EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); - -/* Default restart-marker-resync procedure for use by data source modules */ -EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ - -#define JPEG_RST0 0xD0 /* RST0 marker code */ -#define JPEG_EOI 0xD9 /* EOI marker code */ -#define JPEG_APP0 0xE0 /* APP0 marker code */ -#define JPEG_COM 0xFE /* COM marker code */ - - -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -struct jpeg_comp_master { long dummy; }; -struct jpeg_c_main_controller { long dummy; }; -struct jpeg_c_prep_controller { long dummy; }; -struct jpeg_c_coef_controller { long dummy; }; -struct jpeg_marker_writer { long dummy; }; -struct jpeg_color_converter { long dummy; }; -struct jpeg_downsampler { long dummy; }; -struct jpeg_forward_dct { long dummy; }; -struct jpeg_entropy_encoder { long dummy; }; -struct jpeg_decomp_master { long dummy; }; -struct jpeg_d_main_controller { long dummy; }; -struct jpeg_d_coef_controller { long dummy; }; -struct jpeg_d_post_controller { long dummy; }; -struct jpeg_input_controller { long dummy; }; -struct jpeg_marker_reader { long dummy; }; -struct jpeg_entropy_decoder { long dummy; }; -struct jpeg_inverse_dct { long dummy; }; -struct jpeg_upsampler { long dummy; }; -struct jpeg_color_deconverter { long dummy; }; -struct jpeg_color_quantizer { long dummy; }; -#endif /* JPEG_INTERNALS */ -#endif /* INCOMPLETE_TYPES_BROKEN */ - - -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - -#ifdef JPEG_INTERNALS -#include "jpegint.h" /* fetch private declarations */ -#include "jerror.h" /* fetch error codes too */ -#endif - -#endif /* JPEGLIB_H */ diff --git a/third_party/libjpeg/jversion.h b/third_party/libjpeg/jversion.h deleted file mode 100644 index 6472c58d351ac6a286443f692a8ec07a4a752877..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/jversion.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * jversion.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains software version identification. - */ - - -#define JVERSION "6b 27-Mar-1998" - -#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/third_party/libjpeg/transupp.h b/third_party/libjpeg/transupp.h deleted file mode 100644 index 5c2d32aff50122873e78f5f3030d7135e257073a..0000000000000000000000000000000000000000 --- a/third_party/libjpeg/transupp.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * transupp.h - * - * Copyright (C) 1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for image transformation routines and - * other utility code used by the jpegtran sample application. These are - * NOT part of the core JPEG library. But we keep these routines separate - * from jpegtran.c to ease the task of maintaining jpegtran-like programs - * that have other user interfaces. - * - * NOTE: all the routines declared here have very specific requirements - * about when they are to be executed during the reading and writing of the - * source and destination files. See the comments in transupp.c, or see - * jpegtran.c for an example of correct usage. - */ - -/* If you happen not to want the image transform support, disable it here */ -#ifndef TRANSFORMS_SUPPORTED -#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ -#endif - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jtransform_request_workspace jTrRequest -#define jtransform_adjust_parameters jTrAdjust -#define jtransform_execute_transformation jTrExec -#define jcopy_markers_setup jCMrkSetup -#define jcopy_markers_execute jCMrkExec -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * Codes for supported types of image transformations. - */ - -typedef enum { - JXFORM_NONE, /* no transformation */ - JXFORM_FLIP_H, /* horizontal flip */ - JXFORM_FLIP_V, /* vertical flip */ - JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ - JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ - JXFORM_ROT_90, /* 90-degree clockwise rotation */ - JXFORM_ROT_180, /* 180-degree rotation */ - JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ -} JXFORM_CODE; - -/* - * Although rotating and flipping data expressed as DCT coefficients is not - * hard, there is an asymmetry in the JPEG format specification for images - * whose dimensions aren't multiples of the iMCU size. The right and bottom - * image edges are padded out to the next iMCU boundary with junk data; but - * no padding is possible at the top and left edges. If we were to flip - * the whole image including the pad data, then pad garbage would become - * visible at the top and/or left, and real pixels would disappear into the - * pad margins --- perhaps permanently, since encoders & decoders may not - * bother to preserve DCT blocks that appear to be completely outside the - * nominal image area. So, we have to exclude any partial iMCUs from the - * basic transformation. - * - * Transpose is the only transformation that can handle partial iMCUs at the - * right and bottom edges completely cleanly. flip_h can flip partial iMCUs - * at the bottom, but leaves any partial iMCUs at the right edge untouched. - * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. - * The other transforms are defined as combinations of these basic transforms - * and process edge blocks in a way that preserves the equivalence. - * - * The "trim" option causes untransformable partial iMCUs to be dropped; - * this is not strictly lossless, but it usually gives the best-looking - * result for odd-size images. Note that when this option is active, - * the expected mathematical equivalences between the transforms may not hold. - * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim - * followed by -rot 180 -trim trims both edges.) - * - * We also offer a "force to grayscale" option, which simply discards the - * chrominance channels of a YCbCr image. This is lossless in the sense that - * the luminance channel is preserved exactly. It's not the same kind of - * thing as the rotate/flip transformations, but it's convenient to handle it - * as part of this package, mainly because the transformation routines have to - * be aware of the option to know how many components to work on. - */ - -typedef struct { - /* Options: set by caller */ - JXFORM_CODE transform; /* image transform operator */ - boolean trim; /* if TRUE, trim partial MCUs as needed */ - boolean force_grayscale; /* if TRUE, convert color image to grayscale */ - - /* Internal workspace: caller should not touch these */ - int num_components; /* # of components in workspace */ - jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ -} jpeg_transform_info; - - -#if TRANSFORMS_SUPPORTED - -/* Request any required workspace */ -EXTERN(void) jtransform_request_workspace - JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); -/* Adjust output image parameters */ -EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -/* Execute the actual transformation, if any */ -EXTERN(void) jtransform_execute_transformation - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); - -#endif /* TRANSFORMS_SUPPORTED */ - - -/* - * Support for copying optional markers from source to destination file. - */ - -typedef enum { - JCOPYOPT_NONE, /* copy no optional markers */ - JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ - JCOPYOPT_ALL /* copy all optional markers */ -} JCOPY_OPTION; - -#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ - -/* Setup decompression object to save desired markers in memory */ -EXTERN(void) jcopy_markers_setup - JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); -/* Copy markers saved in the given source object to the destination object */ -EXTERN(void) jcopy_markers_execute - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JCOPY_OPTION option)); diff --git a/third_party/libopenjpeg20/0000-use-colorspace.patch b/third_party/libopenjpeg20/0000-use-colorspace.patch index b40692ce13cbccd918932a55cb6fea613ddb5bb0..4d89efffbf6ea8146ef2bcf2ecb58456ebcc458f 100644 --- a/third_party/libopenjpeg20/0000-use-colorspace.patch +++ b/third_party/libopenjpeg20/0000-use-colorspace.patch @@ -1,27 +1,28 @@ diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c -index 8bf60f6..47f83a1 100644 +index f3ccb9974..882f1b649 100644 --- a/third_party/libopenjpeg20/jp2.c +++ b/third_party/libopenjpeg20/jp2.c -@@ -1508,7 +1508,7 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, - /* Part 1, I.5.3.4: Either both or none : */ - if( !jp2->color.jp2_pclr->cmap) - opj_jp2_free_pclr(&(jp2->color)); -- else -+ else if (p_image->pdfium_use_colorspace) - opj_jp2_apply_pclr(p_image, &(jp2->color)); - } - +@@ -1624,7 +1624,7 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, + /* Part 1, I.5.3.4: Either both or none : */ + if (!jp2->color.jp2_pclr->cmap) { + opj_jp2_free_pclr(&(jp2->color)); +- } else { ++ } else if (p_image->pdfium_use_colorspace) { + if (!opj_jp2_apply_pclr(p_image, &(jp2->color), p_manager)) { + return OPJ_FALSE; + } diff --git a/third_party/libopenjpeg20/openjpeg.h b/third_party/libopenjpeg20/openjpeg.h -index c07e9c8..e571672 100644 +index d571c516e..e8dbe4ff7 100644 --- a/third_party/libopenjpeg20/openjpeg.h +++ b/third_party/libopenjpeg20/openjpeg.h -@@ -677,6 +677,9 @@ typedef struct opj_image { - OPJ_BYTE *icc_profile_buf; - /** size of ICC profile */ - OPJ_UINT32 icc_profile_len; +@@ -682,6 +682,10 @@ typedef struct opj_image { + OPJ_BYTE *icc_profile_buf; + /** size of ICC profile */ + OPJ_UINT32 icc_profile_len; ++ + -+ /** Whether to apply PCLR or not */ -+ OPJ_BOOL pdfium_use_colorspace; ++ /** Whether to apply PCLR or not */ ++ OPJ_BOOL pdfium_use_colorspace; } opj_image_t; diff --git a/third_party/libopenjpeg20/0001-image-data.patch b/third_party/libopenjpeg20/0001-image-data.patch deleted file mode 100644 index 5ae0149538c276fc2b3f0bcdf31ca7675e399332..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0001-image-data.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index e612d06..d515798 100644 ---- a/third_party/libopenjpeg20/j2k.c -+++ b/third_party/libopenjpeg20/j2k.c -@@ -8148,11 +8148,16 @@ static OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, - - /* Allocate output component buffer if necessary */ - if (!l_img_comp_dest->data) { -- -- l_img_comp_dest->data = (OPJ_INT32*) opj_calloc((OPJ_SIZE_T)l_img_comp_dest->w * (OPJ_SIZE_T)l_img_comp_dest->h, sizeof(OPJ_INT32)); -- if (! l_img_comp_dest->data) { -- return OPJ_FALSE; -- } -+ OPJ_UINT32 width = l_img_comp_dest->w; -+ OPJ_UINT32 height = l_img_comp_dest->h; -+ const OPJ_UINT32 MAX_SIZE = UINT32_MAX / sizeof(OPJ_INT32); -+ if (height == 0 || width > MAX_SIZE / height) { -+ return OPJ_FALSE; -+ } -+ l_img_comp_dest->data = (OPJ_INT32*)opj_calloc(width * height, sizeof(OPJ_INT32)); -+ if (!l_img_comp_dest->data) { -+ return OPJ_FALSE; -+ } - } - - /* Copy info from decoded comp image to output image */ diff --git a/third_party/libopenjpeg20/0002-packet-iterator.patch b/third_party/libopenjpeg20/0002-packet-iterator.patch deleted file mode 100644 index ac755ed03daf649a43aa1f4011c921e52b4901d1..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0002-packet-iterator.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c -index 1697bcb..06f1e41 100644 ---- a/third_party/libopenjpeg20/pi.c -+++ b/third_party/libopenjpeg20/pi.c -@@ -36,6 +36,7 @@ - * POSSIBILITY OF SUCH DAMAGE. - */ - -+#include <limits.h> - #include "opj_includes.h" - - /** @defgroup PI PI - Implementation of a packet iterator */ -@@ -1236,7 +1237,13 @@ opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image, - l_current_pi = l_pi; - - /* memory allocation for include */ -- l_current_pi->include = (OPJ_INT16*) opj_calloc((l_tcp->numlayers +1) * l_step_l, sizeof(OPJ_INT16)); -+ l_current_pi->include = 00; -+ if -+ (l_step_l && l_tcp->numlayers < UINT_MAX / l_step_l - 1) -+ { -+ l_current_pi->include = (OPJ_INT16*)opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16)); -+ } -+ - if - (!l_current_pi->include) - { diff --git a/third_party/libopenjpeg20/0003-dwt-decode.patch b/third_party/libopenjpeg20/0003-dwt-decode.patch index c500f0c336fd1f47dbe0c71f122b136ccf6ade18..631219a8b351195529a90608eeee04fd7d28bfcb 100644 --- a/third_party/libopenjpeg20/0003-dwt-decode.patch +++ b/third_party/libopenjpeg20/0003-dwt-decode.patch @@ -1,58 +1,62 @@ diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c -index 4ad99ed..975a97e 100644 +index 83c148002..1455ee84a 100644 --- a/third_party/libopenjpeg20/dwt.c +++ b/third_party/libopenjpeg20/dwt.c -@@ -46,14 +46,12 @@ +@@ -62,8 +62,6 @@ + /** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ /*@{*/ - -#define OPJ_WS(i) v->mem[(i)*2] -#define OPJ_WD(i) v->mem[(1+(i)*2)] -- - /** @name Local data structures */ - /*@{*/ + + #ifdef __AVX2__ + /** Number of int32 values in a AVX2 register */ +@@ -81,6 +79,7 @@ typedef struct dwt_local { - OPJ_INT32* mem; -+ OPJ_SIZE_T mem_count; - OPJ_INT32 dn; - OPJ_INT32 sn; - OPJ_INT32 cas; -@@ -107,16 +105,16 @@ static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x); + OPJ_INT32* mem; ++ OPJ_SIZE_T mem_count; + OPJ_INT32 dn; /* number of elements in high pass band */ + OPJ_INT32 sn; /* number of elements in low pass band */ + OPJ_INT32 cas; /* 0 = start on even coord, 1 = start on odd coord */ +@@ -132,13 +131,14 @@ static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, /** Forward 5-3 wavelet transform in 1-D */ --static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -+static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); - /** - Inverse 5-3 wavelet transform in 1-D - */ - static void opj_dwt_decode_1(opj_dwt_t *v); --static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -+static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +-static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, +- OPJ_INT32 cas); ++static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, ++ OPJ_INT32 sn, OPJ_INT32 cas); /** Forward 9-7 wavelet transform in 1-D */ --static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -+static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); - /** - Explicit calculation of the Quantization Stepsizes - */ -@@ -124,10 +122,10 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_st +-static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, +- OPJ_INT32 cas); ++static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, ++ OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); ++ + /** + Explicit calculation of the Quantization Stepsizes +@@ -149,14 +149,14 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, Inverse wavelet transform in 2-D. */ --static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn); -+static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn); + static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, +- opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i); ++ const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i); --static OPJ_BOOL opj_dwt_encode_procedure( opj_tcd_tilecomp_t * tilec, -- void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) ); -+static OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, -+ void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)); + static OPJ_BOOL opj_dwt_decode_partial_tile( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres); - static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i); +-static OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec, +- void (*p_function)(OPJ_INT32 *, OPJ_INT32, OPJ_INT32, OPJ_INT32)); ++static OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, ++ void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)); -@@ -156,13 +154,20 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_IN + static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, + OPJ_UINT32 i); +@@ -205,13 +205,20 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, /*@}*/ @@ -60,9 +64,6 @@ index 4ad99ed..975a97e 100644 -#define OPJ_D(i) a[(1+(i)*2)] -#define OPJ_S_(i) ((i)<0?OPJ_S(0):((i)>=sn?OPJ_S(sn-1):OPJ_S(i))) -#define OPJ_D_(i) ((i)<0?OPJ_D(0):((i)>=dn?OPJ_D(dn-1):OPJ_D(i))) --/* new */ --#define OPJ_SS_(i) ((i)<0?OPJ_S(0):((i)>=dn?OPJ_S(dn-1):OPJ_S(i))) --#define OPJ_DD_(i) ((i)<0?OPJ_D(0):((i)>=sn?OPJ_D(sn-1):OPJ_D(i))) +#define IDX_S(i) (i)*2 +#define IDX_D(i) 1 + (i)* 2 +#define UNDERFLOW_SN(i) ((i) >= sn&&sn>0) @@ -74,118 +75,190 @@ index 4ad99ed..975a97e 100644 +#define OPJ_D(i) a[IDX_D(i)] +#define OPJ_S_(i) ((i)<0 ? OPJ_S(0) : (UNDERFLOW_SN(i) ? OPJ_S(sn - 1) : OVERFLOW_S(i) ? OPJ_S(i - 1) : OPJ_S(i))) +#define OPJ_D_(i) ((i)<0 ? OPJ_D(0) : (UNDERFLOW_DN(i) ? OPJ_D(dn - 1) : OVERFLOW_D(i) ? OPJ_D(i - 1) : OPJ_D(i))) -+/* new */ + /* new */ +-#define OPJ_SS_(i) ((i)<0?OPJ_S(0):((i)>=dn?OPJ_S(dn-1):OPJ_S(i))) +-#define OPJ_DD_(i) ((i)<0?OPJ_D(0):((i)>=sn?OPJ_D(sn-1):OPJ_D(i))) +#define OPJ_SS_(i) ((i)<0 ? OPJ_S(0) : (UNDERFLOW_DN(i) ? OPJ_S(dn - 1) : OVERFLOW_S(i) ? OPJ_S(i - 1) : OPJ_S(i))) +#define OPJ_DD_(i) ((i)<0 ? OPJ_D(0) : (UNDERFLOW_SN(i) ? OPJ_D(sn - 1) : OVERFLOW_D(i) ? OPJ_D(i - 1) : OPJ_D(i))) /* <summary> */ /* This table contains the norms of the 5-3 wavelets for different bands. */ -@@ -283,7 +288,7 @@ static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) { +@@ -344,8 +351,8 @@ static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) /* <summary> */ /* Forward 5-3 wavelet transform in 1-D. */ /* </summary> */ --static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { -+static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - - if (!cas) { -@@ -304,7 +309,7 @@ static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 +-static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, +- OPJ_INT32 cas) ++static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, ++ OPJ_INT32 sn, OPJ_INT32 cas) + { + OPJ_INT32 i; + +@@ -376,8 +383,8 @@ static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, /* <summary> */ /* Inverse 5-3 wavelet transform in 1-D. */ - /* </summary> */ --static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { -+static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - - if (!cas) { -@@ -326,13 +331,13 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT3 - /* Inverse 5-3 wavelet transform in 1-D. */ - /* </summary> */ - static void opj_dwt_decode_1(opj_dwt_t *v) { -- opj_dwt_decode_1_(v->mem, v->dn, v->sn, v->cas); -+ opj_dwt_decode_1_(v->mem, v->mem_count, v->dn, v->sn, v->cas); + /* </summary> */ +-static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, +- OPJ_INT32 cas) ++static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, ++ OPJ_INT32 sn, OPJ_INT32 cas) + { + OPJ_INT32 i; + +@@ -406,7 +413,7 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, + + static void opj_dwt_decode_1(const opj_dwt_t *v) + { +- opj_dwt_decode_1_(v->mem, v->dn, v->sn, v->cas); ++ opj_dwt_decode_1_(v->mem, v->mem_count, v->dn, v->sn, v->cas); } + #endif /* STANDARD_SLOW_VERSION */ +@@ -1037,8 +1044,8 @@ static void opj_idwt53_v(const opj_dwt_t *dwt, /* <summary> */ /* Forward 9-7 wavelet transform in 1-D. */ /* </summary> */ --static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { -+static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - if (!cas) { - if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ -@@ -385,7 +390,7 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_st +-static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, +- OPJ_INT32 cas) ++static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, ++ OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) + { + OPJ_INT32 i; + if (!cas) { +@@ -1106,8 +1113,8 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, /* <summary> */ /* Forward 5-3 wavelet transform in 2-D. */ /* </summary> */ --static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) ) -+static INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)) +-static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec, +- void (*p_function)(OPJ_INT32 *, OPJ_INT32, OPJ_INT32, OPJ_INT32)) ++static INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, ++ void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)) { - OPJ_INT32 i, j, k; - OPJ_INT32 *a = 00; -@@ -395,7 +400,8 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void - - OPJ_INT32 rw; /* width of the resolution level computed */ - OPJ_INT32 rh; /* height of the resolution level computed */ -- OPJ_UINT32 l_data_size; -+ OPJ_SIZE_T l_data_count; -+ OPJ_SIZE_T l_data_size; - - opj_tcd_resolution_t * l_cur_res = 0; - opj_tcd_resolution_t * l_last_res = 0; -@@ -407,8 +413,9 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void - l_cur_res = tilec->resolutions + l; - l_last_res = l_cur_res - 1; - -- l_data_size = opj_dwt_max_resolution( tilec->resolutions,tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32); -- bj = (OPJ_INT32*)opj_malloc((size_t)l_data_size); -+ l_data_count = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32); -+ l_data_size = l_data_count * (OPJ_UINT32)sizeof(OPJ_INT32); -+ bj = (OPJ_INT32*)opj_malloc(l_data_size); - if (! bj) { - return OPJ_FALSE; - } -@@ -437,7 +444,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void - bj[k] = aj[k*w]; - } - -- (*p_function) (bj, dn, sn, cas_col); -+ (*p_function) (bj, l_data_count, dn, sn, cas_col); - - opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); - } -@@ -448,7 +455,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void - for (j = 0; j < rh; j++) { - aj = a + j * w; - for (k = 0; k < rw; k++) bj[k] = aj[k]; -- (*p_function) (bj, dn, sn, cas_row); -+ (*p_function) (bj, l_data_count, dn, sn, cas_row); - opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row); - } - -@@ -557,7 +564,7 @@ static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_U - /* <summary> */ - /* Inverse wavelet transform in 2-D. */ + OPJ_INT32 i, j, k; + OPJ_INT32 *a = 00; +@@ -1117,6 +1124,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec, + + OPJ_INT32 rw; /* width of the resolution level computed */ + OPJ_INT32 rh; /* height of the resolution level computed */ ++ OPJ_SIZE_T l_data_count; + OPJ_SIZE_T l_data_size; + + opj_tcd_resolution_t * l_cur_res = 0; +@@ -1129,13 +1137,13 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec, + l_cur_res = tilec->resolutions + l; + l_last_res = l_cur_res - 1; + +- l_data_size = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions); ++ l_data_count = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions); + /* overflow check */ +- if (l_data_size > (SIZE_MAX / sizeof(OPJ_INT32))) { ++ if (l_data_count > (SIZE_MAX / sizeof(OPJ_INT32))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } +- l_data_size *= sizeof(OPJ_INT32); ++ l_data_size = l_data_count * sizeof(OPJ_INT32); + bj = (OPJ_INT32*)opj_malloc(l_data_size); + /* l_data_size is equal to 0 when numresolutions == 1 but bj is not used */ + /* in that case, so do not error out */ +@@ -1167,7 +1175,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec, + bj[k] = aj[k * w]; + } + +- (*p_function)(bj, dn, sn, cas_col); ++ (*p_function) (bj, l_data_count, dn, sn, cas_col); + + opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } +@@ -1180,7 +1188,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec, + for (k = 0; k < rw; k++) { + bj[k] = aj[k]; + } +- (*p_function)(bj, dn, sn, cas_row); ++ (*p_function) (bj, l_data_count, dn, sn, cas_row); + opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + +@@ -1379,7 +1387,7 @@ static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls) + /* Inverse wavelet transform in 2-D. */ /* </summary> */ --static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) { -+static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) { - opj_dwt_t h; - opj_dwt_t v; + static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, +- opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) ++ const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) + { + opj_dwt_t h; + opj_dwt_t v; +@@ -1401,22 +1409,23 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, + return OPJ_TRUE; + } + num_threads = opj_thread_pool_get_thread_count(tp); +- h_mem_size = opj_dwt_max_resolution(tr, numres); ++ h.mem_count = opj_dwt_max_resolution(tr, numres); + /* overflow check */ +- if (h_mem_size > (SIZE_MAX / PARALLEL_COLS_53 / sizeof(OPJ_INT32))) { ++ if (h.mem_count > (SIZE_MAX / PARALLEL_COLS_53 / sizeof(OPJ_INT32))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + /* We need PARALLEL_COLS_53 times the height of the array, */ + /* since for the vertical pass */ + /* we process PARALLEL_COLS_53 columns at a time */ +- h_mem_size *= PARALLEL_COLS_53 * sizeof(OPJ_INT32); ++ h_mem_size = h.mem_count * PARALLEL_COLS_53 * sizeof(OPJ_INT32); + h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (! h.mem) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } -@@ -568,13 +575,14 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres ++ v.mem_count = h.mem_count; + v.mem = h.mem; + + while (--numres) { +@@ -1594,7 +1603,8 @@ static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest, + OPJ_UNUSED(ret); + } - OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0); +-static void opj_dwt_decode_partial_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, ++static void opj_dwt_decode_partial_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, ++ OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas, + OPJ_INT32 win_l_x0, + OPJ_INT32 win_l_x1, +@@ -1974,16 +1984,16 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; + } +- h_mem_size = opj_dwt_max_resolution(tr, numres); ++ h.mem_count = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + /* in vertical pass, we process 4 columns at a time */ +- if (h_mem_size > (SIZE_MAX / (4 * sizeof(OPJ_INT32)))) { ++ if (h.mem_count > (SIZE_MAX / (4 * sizeof(OPJ_INT32)))) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } -- h.mem = (OPJ_INT32*) -- opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32)); -+ h.mem_count = opj_dwt_max_resolution(tr, numres); -+ h.mem = (OPJ_INT32*)opj_aligned_malloc(h.mem_count * sizeof(OPJ_INT32)); - if (! h.mem){ - /* FIXME event manager error callback */ - return OPJ_FALSE; - } +- h_mem_size *= 4 * sizeof(OPJ_INT32); ++ h_mem_size = h.mem_count * 4 * sizeof(OPJ_INT32); + h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (! h.mem) { + /* FIXME event manager error callback */ +@@ -1991,6 +2001,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( + return OPJ_FALSE; + } -+ v.mem_count = h.mem_count; - v.mem = h.mem; ++ v.mem_count = h.mem_count; + v.mem = h.mem; - while( --numres) { + for (resno = 1; resno < numres; resno ++) { +@@ -2101,7 +2112,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile( + win_ll_x1, + win_hl_x0, + win_hl_x1); +- opj_dwt_decode_partial_1(h.mem, h.dn, h.sn, h.cas, ++ opj_dwt_decode_partial_1(h.mem, h.mem_count, h.dn, h.sn, h.cas, + (OPJ_INT32)win_ll_x0, + (OPJ_INT32)win_ll_x1, + (OPJ_INT32)win_hl_x0, diff --git a/third_party/libopenjpeg20/0004-j2k_read_mcc.patch b/third_party/libopenjpeg20/0004-j2k_read_mcc.patch deleted file mode 100644 index 39c847d7651b51b1828448532a6e8efd94caacd5..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0004-j2k_read_mcc.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index 849d0b4..b20f219 100644 ---- a/third_party/libopenjpeg20/j2k.c -+++ b/third_party/libopenjpeg20/j2k.c -@@ -5341,6 +5341,7 @@ static OPJ_BOOL opj_j2k_read_mcc ( opj_j2k_t *p_j2k, - OPJ_UINT32 l_nb_collections; - OPJ_UINT32 l_nb_comps; - OPJ_UINT32 l_nb_bytes_by_comp; -+ OPJ_BOOL new_mcc = OPJ_FALSE; - - /* preconditions */ - assert(p_header_data != 00); -@@ -5402,6 +5403,7 @@ static OPJ_BOOL opj_j2k_read_mcc ( opj_j2k_t *p_j2k, - memset(l_mcc_record,0,(l_tcp->m_nb_max_mcc_records-l_tcp->m_nb_mcc_records) * sizeof(opj_simple_mcc_decorrelation_data_t)); - } - l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; -+ new_mcc = OPJ_TRUE; - } - l_mcc_record->m_index = l_indix; - -@@ -5537,7 +5539,9 @@ static OPJ_BOOL opj_j2k_read_mcc ( opj_j2k_t *p_j2k, - return OPJ_FALSE; - } - -- ++l_tcp->m_nb_mcc_records; -+ if (new_mcc) { -+ ++l_tcp->m_nb_mcc_records; -+ } - - return OPJ_TRUE; - } diff --git a/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch b/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch index fd3ca634ca03c19d46248e813d2839d925dfaa67..c8caea853c22c0e03d41a64fd8328a92c33c2469 100644 --- a/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch +++ b/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch @@ -1,49 +1,39 @@ diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c -index 47f83a1..6e910a9 100644 +index da4e05f82..c9562f705 100644 --- a/third_party/libopenjpeg20/jp2.c +++ b/third_party/libopenjpeg20/jp2.c -@@ -902,7 +902,7 @@ static OPJ_BOOL opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, - opj_event_msg(p_manager, EVT_ERROR, "Invalid component/palette index for direct mapping %d.\n", pcol); - is_sane = OPJ_FALSE; - } -- else if (pcol_usage[pcol] && cmap[i].mtyp == 1) { -+ else if (pcol_usage[pcol] && cmap[i].mtyp != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Component %d is mapped twice.\n", pcol); - is_sane = OPJ_FALSE; - } -@@ -982,8 +982,8 @@ static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color) - assert( pcol == 0 ); - new_comps[i] = old_comps[cmp]; - } else { -- assert( i == pcol ); -- new_comps[pcol] = old_comps[cmp]; -+ assert( i == pcol ); // probably wrong? -+ new_comps[i] = old_comps[cmp]; - } +@@ -1073,8 +1073,8 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + assert(pcol == 0); + new_comps[i] = old_comps[cmp]; + } else { +- assert(i == pcol); +- new_comps[pcol] = old_comps[cmp]; ++ assert( i == pcol ); // probably wrong? ++ new_comps[i] = old_comps[cmp]; + } - /* Palette mapping: */ -@@ -1007,11 +1007,11 @@ static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color) - cmp = cmap[i].cmp; pcol = cmap[i].pcol; - src = old_comps[cmp].data; - assert( src ); -- max = new_comps[pcol].w * new_comps[pcol].h; -+ max = new_comps[i].w * new_comps[i].h; + /* Palette mapping: */ +@@ -1102,19 +1102,19 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + pcol = cmap[i].pcol; + src = old_comps[cmp].data; + assert(src); /* verified above */ +- max = new_comps[pcol].w * new_comps[pcol].h; ++ max = new_comps[i].w * new_comps[i].h; - /* Direct use: */ - if(cmap[i].mtyp == 0) { -- assert( cmp == 0 ); -+ assert( cmp == 0 ); // probably wrong. - dst = new_comps[i].data; - assert( dst ); - for(j = 0; j < max; ++j) { -@@ -1019,8 +1019,8 @@ static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color) - } - } - else { -- assert( i == pcol ); -- dst = new_comps[pcol].data; -+ assert( i == pcol ); // probably wrong? -+ dst = new_comps[i].data; - assert( dst ); - for(j = 0; j < max; ++j) { - /* The index */ + /* Direct use: */ + if (cmap[i].mtyp == 0) { +- assert(cmp == 0); ++ assert( cmp == 0 ); // probably wrong. + dst = new_comps[i].data; + assert(dst); + for (j = 0; j < max; ++j) { + dst[j] = src[j]; + } + } else { +- assert(i == pcol); +- dst = new_comps[pcol].data; ++ assert( i == pcol ); // probably wrong? ++ dst = new_comps[i].data; + assert(dst); + for (j = 0; j < max; ++j) { + /* The index */ diff --git a/third_party/libopenjpeg20/0006-tcd_init_tile.patch b/third_party/libopenjpeg20/0006-tcd_init_tile.patch index 6c00f4096b1952c54298e5f69310d90e19c94522..8c37fc2733d685c99b60acf7544fa580d6a0c774 100644 --- a/third_party/libopenjpeg20/0006-tcd_init_tile.patch +++ b/third_party/libopenjpeg20/0006-tcd_init_tile.patch @@ -1,16 +1,16 @@ diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c -index 2fccff1..aebe9be 100644 +index 1dd15405d..acc28dd55 100644 --- a/third_party/libopenjpeg20/tcd.c +++ b/third_party/libopenjpeg20/tcd.c -@@ -727,7 +727,10 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, - l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx); - l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy); - /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ -- -+ if (l_tilec->x0 >= l_tilec->x1 || l_tilec->y0 >= l_tilec->y1) { -+ opj_event_msg(manager, EVT_ERROR, "Invalid tile data\n"); -+ return OPJ_FALSE; -+ } - /* compute l_data_size with overflow check */ - l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); - if ((((OPJ_UINT32)-1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0)) { +@@ -818,6 +818,11 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + if (isEncoder) { + OPJ_SIZE_T l_tile_data_size; + ++ if (l_tilec->x0 >= l_tilec->x1 || l_tilec->y0 >= l_tilec->y1) { ++ opj_event_msg(manager, EVT_ERROR, "Invalid tile data\n"); ++ return OPJ_FALSE; ++ } ++ + /* compute l_data_size with overflow check */ + OPJ_SIZE_T w = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0); + OPJ_SIZE_T h = (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); diff --git a/third_party/libopenjpeg20/0007-jp2_read_cmap.patch b/third_party/libopenjpeg20/0007-jp2_read_cmap.patch index 30f9e4b2d7a2f6c9ee9fd65c05dd966f551a08ec..4cc434099ff0f14414a8000ee8fcb28d68948215 100644 --- a/third_party/libopenjpeg20/0007-jp2_read_cmap.patch +++ b/third_party/libopenjpeg20/0007-jp2_read_cmap.patch @@ -1,13 +1,13 @@ diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c -index 6e910a9..f3baca5 100644 +index 3ace09654..7ef7c9139 100644 --- a/third_party/libopenjpeg20/jp2.c +++ b/third_party/libopenjpeg20/jp2.c -@@ -1194,7 +1194,7 @@ static OPJ_BOOL opj_jp2_read_cmap( opj_jp2_t * jp2, +@@ -1296,7 +1296,7 @@ static OPJ_BOOL opj_jp2_read_cmap(opj_jp2_t * jp2, - for(i = 0; i < nr_channels; ++i) { -- opj_read_bytes(p_cmap_header_data, &l_value, 2); /* CMP^i */ -+ opj_read_bytes_BE(p_cmap_header_data, &l_value, 2); /* CMP^i */ - p_cmap_header_data +=2; - cmap[i].cmp = (OPJ_UINT16) l_value; + for (i = 0; i < nr_channels; ++i) { +- opj_read_bytes(p_cmap_header_data, &l_value, 2); /* CMP^i */ ++ opj_read_bytes_BE(p_cmap_header_data, &l_value, 2); /* CMP^i */ + p_cmap_header_data += 2; + cmap[i].cmp = (OPJ_UINT16) l_value; diff --git a/third_party/libopenjpeg20/0008-jp2_check_color.patch b/third_party/libopenjpeg20/0008-jp2_check_color.patch deleted file mode 100644 index 3810c8669eecc24bafcc547a7ad9f0f7eae6351b..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0008-jp2_check_color.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c -index f3baca5..3bcb42e 100644 ---- a/third_party/libopenjpeg20/jp2.c -+++ b/third_party/libopenjpeg20/jp2.c -@@ -896,8 +896,12 @@ static OPJ_BOOL opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, - } - /* verify that no component is targeted more than once */ - for (i = 0; i < nr_channels; i++) { -- OPJ_UINT16 pcol = cmap[i].pcol; -- assert(cmap[i].mtyp == 0 || cmap[i].mtyp == 1); -+ if (cmap[i].mtyp != 0 && cmap[i].mtyp != 1) { -+ opj_event_msg(p_manager, EVT_ERROR, "Unexpected MTYP value.\n"); -+ opj_free(pcol_usage); -+ return OPJ_FALSE; -+ } -+ OPJ_UINT16 pcol = cmap[i].pcol; - if (pcol >= nr_channels) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid component/palette index for direct mapping %d.\n", pcol); - is_sane = OPJ_FALSE; diff --git a/third_party/libopenjpeg20/0009-opj_pi_next.patch b/third_party/libopenjpeg20/0009-opj_pi_next.patch index a7701f0d05a8bd2e7ab1af7ea8b3e4addf4ae1f6..99f17d313836b18d52d6bb49bea4c2061fa29766 100644 --- a/third_party/libopenjpeg20/0009-opj_pi_next.patch +++ b/third_party/libopenjpeg20/0009-opj_pi_next.patch @@ -1,34 +1,34 @@ diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c -index 06f1e41..462e07c 100644 +index 91642ee4e..256fe37a1 100644 --- a/third_party/libopenjpeg20/pi.c +++ b/third_party/libopenjpeg20/pi.c -@@ -377,6 +377,9 @@ if (!pi->tp_on){ - prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) - - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); - pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); -+ if (pi->precno >= res->pw * res->ph) { -+ return OPJ_FALSE; -+ } - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { -@@ -458,6 +461,9 @@ static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) { - prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) - - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); - pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); -+ if (pi->precno >= res->pw * res->ph) { -+ return OPJ_FALSE; -+ } - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { -@@ -537,6 +543,9 @@ static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) { - prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) - - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); - pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); -+ if (pi->precno >= res->pw * res->ph) { -+ return OPJ_FALSE; -+ } - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { +@@ -445,6 +445,9 @@ static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) + (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) + - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); ++ if (pi->precno >= res->pw * res->ph) { ++ return OPJ_FALSE; ++ } + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; +@@ -576,6 +579,9 @@ static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) + (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) + - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); ++ if (pi->precno >= res->pw * res->ph) { ++ return OPJ_FALSE; ++ } + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; +@@ -704,6 +710,9 @@ static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) + (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) + - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); ++ if (pi->precno >= res->pw * res->ph) { ++ return OPJ_FALSE; ++ } + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; diff --git a/third_party/libopenjpeg20/0010-pi_update_decode_poc.patch b/third_party/libopenjpeg20/0010-pi_update_decode_poc.patch deleted file mode 100644 index d596b76b8f5d84b7f029a62fe4c0c0881761293f..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0010-pi_update_decode_poc.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c -index 462e07c..9097e31 100644 ---- a/third_party/libopenjpeg20/pi.c -+++ b/third_party/libopenjpeg20/pi.c -@@ -1028,7 +1028,7 @@ static void opj_pi_update_decode_poc (opj_pi_iterator_t * p_pi, - l_current_pi->poc.precno0 = 0; - l_current_pi->poc.resno1 = l_current_poc->resno1; /* Resolution Level Index #0 (End) */ - l_current_pi->poc.compno1 = l_current_poc->compno1; /* Component Index #0 (End) */ -- l_current_pi->poc.layno1 = l_current_poc->layno1; /* Layer Index #0 (End) */ -+ l_current_pi->poc.layno1 = opj_uint_min(l_current_poc->layno1, p_tcp->numlayers); /* Layer Index #0 (End) */ - l_current_pi->poc.precno1 = p_max_precision; - ++l_current_pi; - ++l_current_poc; diff --git a/third_party/libopenjpeg20/0011-j2k_update_image_data.patch b/third_party/libopenjpeg20/0011-j2k_update_image_data.patch index 697c48f18b0f1605ea02c4b94993ab16de46e6e4..b61324a6b4d967ff369442824331b6e6c96ecb61 100644 --- a/third_party/libopenjpeg20/0011-j2k_update_image_data.patch +++ b/third_party/libopenjpeg20/0011-j2k_update_image_data.patch @@ -1,17 +1,17 @@ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index b20f219..9056feb 100644 +index ad6e1b86f..bf1cb4f36 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c -@@ -8211,6 +8211,12 @@ static OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, - * */ - assert( l_res->x0 >= 0); - assert( l_res->x1 >= 0); +@@ -9086,6 +9086,12 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, + * */ + assert(res_x0 >= 0); + assert(res_x1 >= 0); + -+ /* Prevent bad casting to unsigned values in the subsequent lines. */ -+ if ( l_res->x0 < 0 || l_res->x1 < 0 || l_res->y0 < 0 || l_res->y1 < 0 ) { -+ return OPJ_FALSE; -+ } ++ /* Prevent bad casting to unsigned values in the subsequent lines. */ ++ if ( res_x0 < 0 || res_x1 < 0 || res_y0 < 0 || res_y1 < 0 ) { ++ return OPJ_FALSE; ++ } + - if ( l_x0_dest < (OPJ_UINT32)l_res->x0 ) { - l_start_x_dest = (OPJ_UINT32)l_res->x0 - l_x0_dest; - l_offset_x0_src = 0; + if (l_x0_dest < (OPJ_UINT32)res_x0) { + l_start_x_dest = (OPJ_UINT32)res_x0 - l_x0_dest; + l_offset_x0_src = 0; diff --git a/third_party/libopenjpeg20/0012-mct_sse.patch b/third_party/libopenjpeg20/0012-mct_sse.patch index bf0827676407ea02cae5a17155fb950200420e4d..9bc2e6f0dc6d551580e0235e23d2c6b02ffd50cb 100644 --- a/third_party/libopenjpeg20/0012-mct_sse.patch +++ b/third_party/libopenjpeg20/0012-mct_sse.patch @@ -1,5 +1,5 @@ diff --git a/third_party/libopenjpeg20/mct.c b/third_party/libopenjpeg20/mct.c -index 8b0276f..7731c15 100644 +index b79d4b87c..81ec223d8 100644 --- a/third_party/libopenjpeg20/mct.c +++ b/third_party/libopenjpeg20/mct.c @@ -37,13 +37,16 @@ @@ -22,39 +22,39 @@ index 8b0276f..7731c15 100644 #include <smmintrin.h> #endif -@@ -72,7 +75,7 @@ const OPJ_FLOAT64 * opj_mct_get_mct_norms_real () +@@ -72,7 +75,7 @@ const OPJ_FLOAT64 * opj_mct_get_mct_norms_real() /* <summary> */ /* Forward reversible MCT. */ /* </summary> */ -#ifdef __SSE2__ +#ifdef USE_SSE2 void opj_mct_encode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, -@@ -137,7 +140,7 @@ void opj_mct_encode( + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, +@@ -141,7 +144,7 @@ void opj_mct_encode( /* <summary> */ /* Inverse reversible MCT. */ /* </summary> */ -#ifdef __SSE2__ +#ifdef USE_SSE2 void opj_mct_decode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, -@@ -204,7 +207,7 @@ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) { + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, +@@ -209,7 +212,7 @@ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) /* <summary> */ /* Forward irreversible MCT. */ /* </summary> */ -#ifdef __SSE4_1__ +#ifdef USE_SSE4 void opj_mct_encode_real( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, -@@ -377,7 +380,7 @@ void opj_mct_decode_real( - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, +@@ -389,7 +392,7 @@ void opj_mct_decode_real( + OPJ_SIZE_T n) { - OPJ_UINT32 i; + OPJ_UINT32 i; -#ifdef __SSE__ +#ifdef USE_SSE - __m128 vrv, vgu, vgv, vbu; - vrv = _mm_set1_ps(1.402f); - vgu = _mm_set1_ps(0.34413f); + __m128 vrv, vgu, vgv, vbu; + vrv = _mm_set1_ps(1.402f); + vgu = _mm_set1_ps(0.34413f); diff --git a/third_party/libopenjpeg20/0013-attrib_fix.patch b/third_party/libopenjpeg20/0013-attrib_fix.patch deleted file mode 100644 index 4c1330420b28f0f9d43c0a0e18529fea9da8f124..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0013-attrib_fix.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/third_party/libopenjpeg20/opj_includes.h b/third_party/libopenjpeg20/opj_includes.h -index f855b7c..5add091 100644 ---- a/third_party/libopenjpeg20/opj_includes.h -+++ b/third_party/libopenjpeg20/opj_includes.h -@@ -102,12 +102,6 @@ - ========================================================== - */ - --/* Ignore GCC attributes if this is not GCC */ --#ifndef __GNUC__ -- #define __attribute__(x) /* __attribute__(x) */ --#endif -- -- - /* Are restricted pointers available? (C99) */ - #if (__STDC_VERSION__ != 199901L) - /* Not a C99 compiler */ - diff --git a/third_party/libopenjpeg20/0014-opj_jp2_read_ihdr_leak.patch b/third_party/libopenjpeg20/0014-opj_jp2_read_ihdr_leak.patch index f5645330a31e6494778079db98f45f25864fbe4c..0ae0cfcb1b80560a9d21cbc57233f4f45bdc3927 100644 --- a/third_party/libopenjpeg20/0014-opj_jp2_read_ihdr_leak.patch +++ b/third_party/libopenjpeg20/0014-opj_jp2_read_ihdr_leak.patch @@ -1,28 +1,20 @@ diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c -index 3bcb42e..a6648f6 100644 +index 7ef7c9139..1fa607d66 100644 --- a/third_party/libopenjpeg20/jp2.c +++ b/third_party/libopenjpeg20/jp2.c -@@ -561,6 +561,7 @@ static OPJ_BOOL opj_jp2_read_ihdr( opj_jp2_t *jp2, - p_image_header_data += 2; +@@ -593,6 +593,7 @@ static OPJ_BOOL opj_jp2_read_ihdr(opj_jp2_t *jp2, + } - /* allocate memory for components */ -+ opj_free(jp2->comps); - jp2->comps = (opj_jp2_comps_t*) opj_calloc(jp2->numcomps, sizeof(opj_jp2_comps_t)); - if (jp2->comps == 0) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle image header (ihdr)\n"); -@@ -1758,6 +1759,7 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) + /* allocate memory for components */ ++ opj_free(jp2->comps); + jp2->comps = (opj_jp2_comps_t*) opj_calloc(jp2->numcomps, + sizeof(opj_jp2_comps_t)); + if (jp2->comps == 0) { +@@ -1882,6 +1883,7 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) - /* further JP2 initializations go here */ - jp2->color.jp2_has_colr = 0; -+ jp2->comps = NULL; - jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; + /* further JP2 initializations go here */ + jp2->color.jp2_has_colr = 0; ++ jp2->comps = NULL; + jp2->ignore_pclr_cmap_cdef = parameters->flags & + OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; } - -@@ -1815,7 +1817,6 @@ OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2, - jp2->numcomps = image->numcomps; /* NC */ - jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); - if (!jp2->comps) { -- jp2->comps = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory when setup the JP2 encoder\n"); - /* Memory of jp2->cl will be freed by opj_jp2_destroy */ - return OPJ_FALSE; diff --git a/third_party/libopenjpeg20/0015-read_SPCod_SPCoc_overflow.patch b/third_party/libopenjpeg20/0015-read_SPCod_SPCoc_overflow.patch index 56f0cf0e8e0c0fdfc2de389b66f0b7e2f58cf431..760ed7462bdda26055cb370b7e8a8a73ab75d9fc 100644 --- a/third_party/libopenjpeg20/0015-read_SPCod_SPCoc_overflow.patch +++ b/third_party/libopenjpeg20/0015-read_SPCod_SPCoc_overflow.patch @@ -1,15 +1,15 @@ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index 9056feb..c7aa8db 100644 +index 8e35b33ee..d95963a5c 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c -@@ -8744,7 +8744,9 @@ static OPJ_BOOL opj_j2k_read_SPCod_SPCoc( opj_j2k_t *p_j2k, - p_j2k->m_specific_param.m_decoder.m_default_tcp; +@@ -9527,6 +9527,10 @@ static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(opj_j2k_t *p_j2k, + p_j2k->m_specific_param.m_decoder.m_default_tcp; - /* precondition again */ -- assert(compno < p_j2k->m_private_image->numcomps); -+ if (compno >= p_j2k->m_private_image->numcomps) { -+ return OPJ_FALSE; -+ } + /* precondition again */ ++ if (compno >= p_j2k->m_private_image->numcomps) { ++ return OPJ_FALSE; ++ } ++ + assert(compno < p_j2k->m_private_image->numcomps); - l_tccp = &l_tcp->tccps[compno]; - l_current_ptr = p_header_data; + l_tccp = &l_tcp->tccps[compno]; diff --git a/third_party/libopenjpeg20/0016-read_SQcd_SQcc_overflow.patch b/third_party/libopenjpeg20/0016-read_SQcd_SQcc_overflow.patch index 7b8bfca42f31226483121b5cf5eeadbf99030288..d7e06ead8fce73e6f71cb9f6b0b5542e6b00589c 100644 --- a/third_party/libopenjpeg20/0016-read_SQcd_SQcc_overflow.patch +++ b/third_party/libopenjpeg20/0016-read_SQcd_SQcc_overflow.patch @@ -1,15 +1,15 @@ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index c7aa8db..b5f6fe9 100644 +index d95963a5c..ed449684f 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c -@@ -9010,7 +9010,9 @@ static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, - p_j2k->m_specific_param.m_decoder.m_default_tcp; +@@ -9864,7 +9864,9 @@ static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, + p_j2k->m_specific_param.m_decoder.m_default_tcp; - /* precondition again*/ -- assert(p_comp_no < p_j2k->m_private_image->numcomps); -+ if (p_comp_no >= p_j2k->m_private_image->numcomps) { -+ return OPJ_FALSE; -+ } + /* precondition again*/ +- assert(p_comp_no < p_j2k->m_private_image->numcomps); ++ if (p_comp_no >= p_j2k->m_private_image->numcomps) { ++ return OPJ_FALSE; ++ } - l_tccp = &l_tcp->tccps[p_comp_no]; - l_current_ptr = p_header_data; + l_tccp = &l_tcp->tccps[p_comp_no]; + l_current_ptr = p_header_data; diff --git a/third_party/libopenjpeg20/0017-tcd_init_tile.patch b/third_party/libopenjpeg20/0017-tcd_init_tile.patch deleted file mode 100644 index a04ac9f1186222d991dbaee97c6dafb3cbcaeec0..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0017-tcd_init_tile.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff --git a/third_party/libopenjpeg20/0017-tcd_init_tile.patch b/third_party/libopenjpeg20/0017-tcd_init_tile.patch -new file mode 100644 -index 0000000..e69de29 -diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium -index 4852a42..97e6e8c 100644 ---- a/third_party/libopenjpeg20/README.pdfium -+++ b/third_party/libopenjpeg20/README.pdfium -@@ -26,4 +26,5 @@ Local Modifications: - 0014-opj_jp2_read_ihdr_leak.patch: Memory leak in opj_jp2_read_ihdr(). - 0015-read_SPCod_SPCoc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SPCod_SPCoc. - 0016-read_SQcd_SQcc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SQcd_SQcc. -+0017-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_precinct_size|. - TODO(thestig): List all the other patches. -diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c -index aebe9be..673633c 100644 ---- a/third_party/libopenjpeg20/tcd.c -+++ b/third_party/libopenjpeg20/tcd.c -@@ -822,7 +822,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, - l_res->ph = (l_res->y0 == l_res->y1) ? 0 : (OPJ_UINT32)((l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy); - /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ - -+ if (l_res->pw && ((OPJ_UINT32)-1) / l_res->pw < l_res->ph) { -+ return OPJ_FALSE; -+ } - l_nb_precincts = l_res->pw * l_res->ph; -+ -+ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t) < l_nb_precincts) { -+ return OPJ_FALSE; -+ } - l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t); - if (resno == 0) { - tlcbgxstart = l_tl_prc_x_start; diff --git a/third_party/libopenjpeg20/0018-tcd_get_decoded_tile_size.patch b/third_party/libopenjpeg20/0018-tcd_get_decoded_tile_size.patch deleted file mode 100644 index b1af68744fde87610e7b4851b64ea12d789213f9..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0018-tcd_get_decoded_tile_size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/third_party/libopenjpeg20/0018-tcd_get_decoded_tile_size.patch b/third_party/libopenjpeg20/0018-tcd_get_decoded_tile_size.patch -new file mode 100644 -index 0000000..e69de29 -diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium -index 97e6e8c..a9e289d 100644 ---- a/third_party/libopenjpeg20/README.pdfium -+++ b/third_party/libopenjpeg20/README.pdfium -@@ -27,4 +27,5 @@ Local Modifications: - 0015-read_SPCod_SPCoc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SPCod_SPCoc. - 0016-read_SQcd_SQcc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SQcd_SQcc. - 0017-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_precinct_size|. -+0018-tcd_get_decoded_tile_size.patch: Fix an integer overflow in opj_tcd_get_decoded_tile_size. - TODO(thestig): List all the other patches. -diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index b5f6fe9..6346c21 100644 ---- a/third_party/libopenjpeg20/j2k.c -+++ b/third_party/libopenjpeg20/j2k.c -@@ -8028,6 +8028,10 @@ OPJ_BOOL opj_j2k_read_tile_header( opj_j2k_t * p_j2k, - *p_tile_index = p_j2k->m_current_tile_number; - *p_go_on = OPJ_TRUE; - *p_data_size = opj_tcd_get_decoded_tile_size(p_j2k->m_tcd); -+ if (*p_data_size == (OPJ_UINT32)-1) { -+ return OPJ_FALSE; -+ } -+ - *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; - *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; - *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; -diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c -index 673633c..cd1c439 100644 ---- a/third_party/libopenjpeg20/tcd.c -+++ b/third_party/libopenjpeg20/tcd.c -@@ -1150,6 +1150,7 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size ( opj_tcd_t *p_tcd ) - opj_tcd_tilecomp_t * l_tile_comp = 00; - opj_tcd_resolution_t * l_res = 00; - OPJ_UINT32 l_size_comp, l_remaining; -+ OPJ_UINT32 l_temp; - - l_tile_comp = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; -@@ -1167,7 +1168,18 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size ( opj_tcd_t *p_tcd ) - } - - l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; -- l_data_size += l_size_comp * (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0)); -+ l_temp = (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0)); /* x1*y1 can't overflow */ -+ -+ if (l_size_comp && ((OPJ_UINT32)-1) / l_size_comp < l_temp) { -+ return (OPJ_UINT32)-1; -+ } -+ l_temp *= l_size_comp; -+ -+ if (l_temp > ((OPJ_UINT32)-1) - l_data_size) { -+ return (OPJ_UINT32)-1; -+ } -+ l_data_size += l_temp; -+ - ++l_img_comp; - ++l_tile_comp; - } -@@ -1362,7 +1374,7 @@ OPJ_BOOL opj_tcd_update_tile_data ( opj_tcd_t *p_tcd, - OPJ_UINT32 l_stride, l_width,l_height; - - l_data_size = opj_tcd_get_decoded_tile_size(p_tcd); -- if (l_data_size > p_dest_length) { -+ if (l_data_size == (OPJ_UINT32)-1 || l_data_size > p_dest_length) { - return OPJ_FALSE; - } - diff --git a/third_party/libopenjpeg20/0019-tcd_init_tile.patch b/third_party/libopenjpeg20/0019-tcd_init_tile.patch index d8e18facc9961e837e273f427d641a9c0fc0d47e..fc5a3aac91f2555a2e7f99e2cb5ba06f52edcf79 100644 --- a/third_party/libopenjpeg20/0019-tcd_init_tile.patch +++ b/third_party/libopenjpeg20/0019-tcd_init_tile.patch @@ -1,30 +1,21 @@ -diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium -index a9e289d..b1012af 100644 ---- a/third_party/libopenjpeg20/README.pdfium -+++ b/third_party/libopenjpeg20/README.pdfium -@@ -28,4 +28,5 @@ Local Modifications: - 0016-read_SQcd_SQcc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SQcd_SQcc. - 0017-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_precinct_size|. - 0018-tcd_get_decoded_tile_size.patch: Fix an integer overflow in opj_tcd_get_decoded_tile_size. -+0019-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_code_blocks_size|. - TODO(thestig): List all the other patches. diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c -index cd1c439..9270efe 100644 +index f0710cd14..35d15e3d1 100644 --- a/third_party/libopenjpeg20/tcd.c +++ b/third_party/libopenjpeg20/tcd.c -@@ -939,8 +939,15 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, - l_current_precinct->cw = (OPJ_UINT32)((brcblkxend - tlcblkxstart) >> cblkwidthexpn); - l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> cblkheightexpn); - -+ if (l_current_precinct->cw && ((OPJ_UINT32)-1) / l_current_precinct->cw < l_current_precinct->ch) { -+ return OPJ_FALSE; -+ } - l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; - /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ -+ -+ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof_block < l_nb_code_blocks) { -+ return OPJ_FALSE; -+ } - l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; - - if (! l_current_precinct->cblks.blocks) { +@@ -1040,9 +1040,15 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + cblkwidthexpn); + l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> + cblkheightexpn); +- ++ if (l_current_precinct->cw && ((OPJ_UINT32)-1) / l_current_precinct->cw < l_current_precinct->ch) { ++ return OPJ_FALSE; ++ } + l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; + /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ ++ ++ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof_block < l_nb_code_blocks) { ++ return OPJ_FALSE; ++ } + l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; + + if (!l_current_precinct->cblks.blocks && (l_nb_code_blocks > 0U)) { diff --git a/third_party/libopenjpeg20/0020-opj_aligned_malloc.patch b/third_party/libopenjpeg20/0020-opj_aligned_malloc.patch deleted file mode 100644 index 7de6e967b6560ef1e77da9ef7f4782e047b2f47b..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0020-opj_aligned_malloc.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium -index b1012af..a40ed7b 100644 ---- a/third_party/libopenjpeg20/README.pdfium -+++ b/third_party/libopenjpeg20/README.pdfium -@@ -29,4 +29,5 @@ Local Modifications: - 0017-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_precinct_size|. - 0018-tcd_get_decoded_tile_size.patch: Fix an integer overflow in opj_tcd_get_decoded_tile_size. - 0019-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_code_blocks_size|. -+0020-opj_aligned_malloc.patch: Prevent overflows when using opj_aligned_malloc(). - TODO(thestig): List all the other patches. -diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c -index 3b92bdf..a666d1c 100644 ---- a/third_party/libopenjpeg20/dwt.c -+++ b/third_party/libopenjpeg20/dwt.c -@@ -576,6 +576,9 @@ static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 - OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0); - - h.mem_count = opj_dwt_max_resolution(tr, numres); -+ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_INT32) < (OPJ_UINT32)h.mem_count) { -+ return OPJ_FALSE; -+ } - h.mem = (OPJ_INT32*)opj_aligned_malloc(h.mem_count * sizeof(OPJ_INT32)); - if (! h.mem){ - /* FIXME event manager error callback */ -@@ -850,7 +853,17 @@ OPJ_BOOL opj_dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numr - - OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0); - -- h.wavelet = (opj_v4_t*) opj_aligned_malloc((opj_dwt_max_resolution(res, numres)+5) * sizeof(opj_v4_t)); -+ OPJ_UINT32 mr = opj_dwt_max_resolution(res, numres); -+ -+ if (mr >= ((OPJ_UINT32)-5)) { -+ return OPJ_FALSE; -+ } -+ mr += 5; -+ -+ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(opj_v4_t) < mr) { -+ return OPJ_FALSE; -+ } -+ h.wavelet = (opj_v4_t*) opj_aligned_malloc(mr * sizeof(opj_v4_t)); - if (!h.wavelet) { - /* FIXME event manager error callback */ - return OPJ_FALSE; -diff --git a/third_party/libopenjpeg20/t1.c b/third_party/libopenjpeg20/t1.c -index 108ce78..a119db1 100644 ---- a/third_party/libopenjpeg20/t1.c -+++ b/third_party/libopenjpeg20/t1.c -@@ -1173,6 +1173,9 @@ static OPJ_BOOL opj_t1_allocate_buffers( - if (!t1->encoder) { - if(datasize > t1->datasize){ - opj_aligned_free(t1->data); -+ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_INT32) < datasize) { -+ return OPJ_FALSE; -+ } - t1->data = (OPJ_INT32*) opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); - if(!t1->data){ - /* FIXME event manager error callback */ -@@ -1187,6 +1190,9 @@ static OPJ_BOOL opj_t1_allocate_buffers( - - if(flagssize > t1->flagssize){ - opj_aligned_free(t1->flags); -+ if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(opj_flag_t) < flagssize) { -+ return OPJ_FALSE; -+ } - t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof(opj_flag_t)); - if(!t1->flags){ - /* FIXME event manager error callback */ diff --git a/third_party/libopenjpeg20/0021-tcd_init_tile_negative.patch b/third_party/libopenjpeg20/0021-tcd_init_tile_negative.patch deleted file mode 100644 index 33694f81fcc0a6211c7fbf4d5d3b0538c845c31e..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0021-tcd_init_tile_negative.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c -index 9270efe..06eee4e 100644 ---- a/third_party/libopenjpeg20/tcd.c -+++ b/third_party/libopenjpeg20/tcd.c -@@ -706,9 +706,16 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, - l_tx0 = l_cp->tx0 + p * l_cp->tdx; /* can't be greater than l_image->x1 so won't overflow */ - l_tile->x0 = (OPJ_INT32)opj_uint_max(l_tx0, l_image->x0); - l_tile->x1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, l_cp->tdx), l_image->x1); -+ if (l_tile->x0 < 0 || l_tile->x1 < 0) { -+ return OPJ_FALSE; -+ } -+ - l_ty0 = l_cp->ty0 + q * l_cp->tdy; /* can't be greater than l_image->y1 so won't overflow */ - l_tile->y0 = (OPJ_INT32)opj_uint_max(l_ty0, l_image->y0); - l_tile->y1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, l_cp->tdy), l_image->y1); -+ if (l_tile->y0 < 0 || l_tile->y1 < 0) { -+ return OPJ_FALSE; -+ } - - /* testcase 1888.pdf.asan.35.988 */ - if (l_tccp->numresolutions == 0) { diff --git a/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch b/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch index 72105fec4ffdbb5e1e4e7849712f5d9ab8ebc963..f4f2ef5c014b8c0d8282b0360dd5e92397c47d00 100644 --- a/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch +++ b/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch @@ -1,53 +1,52 @@ diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c -index a6648f6..8128d98 100644 +index 1fa607d66..78a2d22ff 100644 --- a/third_party/libopenjpeg20/jp2.c +++ b/third_party/libopenjpeg20/jp2.c -@@ -972,6 +972,14 @@ static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color) - nr_channels = color->jp2_pclr->nr_channels; +@@ -1049,6 +1049,14 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + } - old_comps = image->comps; -+ /* Overflow check: prevent integer overflow */ -+ for (i = 0; i < nr_channels; ++i) { -+ cmp = cmap[i].cmp; -+ if (old_comps[cmp].h == 0 || old_comps[cmp].w > ((OPJ_UINT32)-1) / sizeof(OPJ_INT32) / old_comps[cmp].h) { -+ return; -+ } -+ } + old_comps = image->comps; ++ /* Overflow check: prevent integer overflow */ ++ for (i = 0; i < nr_channels; ++i) { ++ cmp = cmap[i].cmp; ++ if (old_comps[cmp].h == 0 || old_comps[cmp].w > ((OPJ_UINT32)-1) / sizeof(OPJ_INT32) / old_comps[cmp].h) { ++ return OPJ_FALSE; ++ } ++ } + - new_comps = (opj_image_comp_t*) - opj_malloc(nr_channels * sizeof(opj_image_comp_t)); - if (!new_comps) { -@@ -1011,22 +1019,28 @@ static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color) - /* Palette mapping: */ - cmp = cmap[i].cmp; pcol = cmap[i].pcol; - src = old_comps[cmp].data; -- assert( src ); -+ dst = new_comps[i].data; - max = new_comps[i].w * new_comps[i].h; + new_comps = (opj_image_comp_t*) + opj_malloc(nr_channels * sizeof(opj_image_comp_t)); + if (!new_comps) { +@@ -1093,21 +1101,27 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + cmp = cmap[i].cmp; + pcol = cmap[i].pcol; + src = old_comps[cmp].data; +- assert(src); /* verified above */ ++ dst = new_comps[i].data; + max = new_comps[i].w * new_comps[i].h; -+ /* Prevent null pointer access */ -+ if (!src || !dst) { -+ for (j = 0; j < nr_channels; ++j) { -+ opj_free(new_comps[j].data); -+ } -+ opj_free(new_comps); -+ new_comps = NULL; -+ return; -+ } ++ /* Prevent null pointer access */ ++ if (!src || !dst) { ++ for (j = 0; j < nr_channels; ++j) { ++ opj_free(new_comps[j].data); ++ } ++ opj_free(new_comps); ++ new_comps = NULL; ++ return OPJ_FALSE; ++ } + - /* Direct use: */ - if(cmap[i].mtyp == 0) { - assert( cmp == 0 ); // probably wrong. -- dst = new_comps[i].data; -- assert( dst ); - for(j = 0; j < max; ++j) { - dst[j] = src[j]; - } - } - else { - assert( i == pcol ); // probably wrong? -- dst = new_comps[i].data; -- assert( dst ); - for(j = 0; j < max; ++j) { - /* The index */ - if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; + /* Direct use: */ + if (cmap[i].mtyp == 0) { + assert( cmp == 0 ); // probably wrong. +- dst = new_comps[i].data; +- assert(dst); + for (j = 0; j < max; ++j) { + dst[j] = src[j]; + } + } else { + assert( i == pcol ); // probably wrong? +- dst = new_comps[i].data; +- assert(dst); + for (j = 0; j < max; ++j) { + /* The index */ + if ((k = src[j]) < 0) { diff --git a/third_party/libopenjpeg20/0023-opj_j2k_read_mct_records.patch b/third_party/libopenjpeg20/0023-opj_j2k_read_mct_records.patch index 6775f4f3dc954427bdc9a2a0480fd929f94dbf75..c8415ae4eee6f82d5c61865121ab1fb96c42099c 100644 --- a/third_party/libopenjpeg20/0023-opj_j2k_read_mct_records.patch +++ b/third_party/libopenjpeg20/0023-opj_j2k_read_mct_records.patch @@ -1,30 +1,31 @@ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index 6346c2190..45187e8e6 100644 +index ed449684f..c5f9dd53e 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c -@@ -5129,6 +5129,7 @@ static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, - OPJ_UINT32 l_tmp; - OPJ_UINT32 l_indix; - opj_mct_data_t * l_mct_data; -+ OPJ_BOOL new_mct = OPJ_FALSE; +@@ -5553,6 +5553,7 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_mct_data_t * l_mct_data; ++ OPJ_BOOL new_mct = OPJ_FALSE; - /* preconditions */ - assert(p_header_data != 00); -@@ -5191,7 +5192,7 @@ static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, - } - - l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; -- ++l_tcp->m_nb_mct_records; -+ new_mct = OPJ_TRUE; + /* preconditions */ + assert(p_header_data != 00); +@@ -5640,7 +5641,7 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, } - if (l_mct_data->m_data) { -@@ -5221,6 +5222,9 @@ static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; +- ++l_tcp->m_nb_mct_records; ++ new_mct = OPJ_TRUE; + } + + if (l_mct_data->m_data) { +@@ -5672,6 +5673,9 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, - l_mct_data->m_data_size = p_header_size; + l_mct_data->m_data_size = p_header_size; -+ if (new_mct) { -+ ++l_tcp->m_nb_mct_records; -+ } - return OPJ_TRUE; ++ if (new_mct) { ++ ++l_tcp->m_nb_mct_records; ++ } + return OPJ_TRUE; } + diff --git a/third_party/libopenjpeg20/0024-l_marker_size_check.patch b/third_party/libopenjpeg20/0024-l_marker_size_check.patch deleted file mode 100644 index cb020c9d0e7831c3c8ed6831d5f5d31a35b78305..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0024-l_marker_size_check.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index 45187e8e6..5de89cf0e 100644 ---- a/third_party/libopenjpeg20/j2k.c -+++ b/third_party/libopenjpeg20/j2k.c -@@ -7195,6 +7195,10 @@ static OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k, - - /* read 2 bytes as the marker size */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); -+ if (l_marker_size < 2) { -+ opj_event_msg(p_manager, EVT_ERROR, "Invalid marker size\n"); -+ return OPJ_FALSE; -+ } - l_marker_size -= 2; /* Subtract the size of the marker ID already read */ - - /* Check if the marker size is compatible with the header data size */ diff --git a/third_party/libopenjpeg20/0025-opj_j2k_add_mct_null_data.patch b/third_party/libopenjpeg20/0025-opj_j2k_add_mct_null_data.patch index 4a371e5c88945bcc985606225bd90d2d4aabd891..b2e7cdc75aa4ba8b0d3541ccceb37f4a0b90c34d 100644 --- a/third_party/libopenjpeg20/0025-opj_j2k_add_mct_null_data.patch +++ b/third_party/libopenjpeg20/0025-opj_j2k_add_mct_null_data.patch @@ -1,22 +1,22 @@ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index 5de89cf0e..400ca8098 100644 +index c5f9dd53e..d31eb29a7 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c -@@ -5715,7 +5715,7 @@ static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, OPJ_UI +@@ -6201,7 +6201,7 @@ static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, + if (l_deco_array) { + l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps + * p_image->numcomps; +- if (l_deco_array->m_data_size != l_data_size) { ++ if (l_deco_array->m_data_size != l_data_size || ! l_deco_array->m_data) { + return OPJ_FALSE; + } - if (l_deco_array) { - l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps * p_image->numcomps; -- if (l_deco_array->m_data_size != l_data_size) { -+ if (l_deco_array->m_data_size != l_data_size || ! l_deco_array->m_data) { - return OPJ_FALSE; - } - -@@ -5734,7 +5734,7 @@ static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, OPJ_UI - - if (l_offset_array) { - l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * p_image->numcomps; -- if (l_offset_array->m_data_size != l_data_size) { -+ if (l_offset_array->m_data_size != l_data_size || ! l_offset_array->m_data) { - return OPJ_FALSE; - } +@@ -6222,7 +6222,7 @@ static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, + if (l_offset_array) { + l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * + p_image->numcomps; +- if (l_offset_array->m_data_size != l_data_size) { ++ if (l_offset_array->m_data_size != l_data_size || ! l_offset_array->m_data) { + return OPJ_FALSE; + } diff --git a/third_party/libopenjpeg20/0026-use_opj_uint_ceildiv.patch b/third_party/libopenjpeg20/0026-use_opj_uint_ceildiv.patch index a196a44349ae7653c8adb79239e19cb1392814a1..038fb90ff4611dedf005410d485edd628fb4694a 100644 --- a/third_party/libopenjpeg20/0026-use_opj_uint_ceildiv.patch +++ b/third_party/libopenjpeg20/0026-use_opj_uint_ceildiv.patch @@ -1,70 +1,86 @@ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index 400ca8098..e77edd22b 100644 +index c5f9dd53e..1869833f7 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c -@@ -2155,8 +2155,8 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, - } +@@ -2311,10 +2311,8 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, + } - /* Compute the number of tiles */ -- l_cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->x1 - l_cp->tx0), (OPJ_INT32)l_cp->tdx); -- l_cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->y1 - l_cp->ty0), (OPJ_INT32)l_cp->tdy); -+ l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); -+ l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); + /* Compute the number of tiles */ +- l_cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->x1 - l_cp->tx0), +- (OPJ_INT32)l_cp->tdx); +- l_cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->y1 - l_cp->ty0), +- (OPJ_INT32)l_cp->tdy); ++ l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); ++ l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); - /* Check that the number of tiles is valid */ - if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) { -@@ -2171,8 +2171,8 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, - if (p_j2k->m_specific_param.m_decoder.m_discard_tiles) { - p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy; -- p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0), (OPJ_INT32)l_cp->tdx); -- p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0), (OPJ_INT32)l_cp->tdy); -+ p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv(p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, l_cp->tdx); -+ p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv(p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, l_cp->tdy); - } - else { - p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; -@@ -6354,8 +6354,8 @@ OPJ_BOOL opj_j2k_setup_encoder( opj_j2k_t *p_j2k, - */ + /* Check that the number of tiles is valid */ + if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) { +@@ -2331,12 +2329,10 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, + (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = + (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy; +- p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv(( +- OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0), +- (OPJ_INT32)l_cp->tdx); +- p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv(( +- OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0), +- (OPJ_INT32)l_cp->tdy); ++ p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv( ++ p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, l_cp->tdx); ++ p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv( ++ p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, l_cp->tdy); + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; +@@ -6922,10 +6918,8 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, + */ - if (parameters->tile_size_on) { -- cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->x1 - cp->tx0), (OPJ_INT32)cp->tdx); -- cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->y1 - cp->ty0), (OPJ_INT32)cp->tdy); -+ cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx); -+ cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy); - } else { - cp->tdx = image->x1 - cp->tx0; - cp->tdy = image->y1 - cp->ty0; -@@ -8529,8 +8529,8 @@ OPJ_BOOL opj_j2k_set_decode_area( opj_j2k_t *p_j2k, - { - OPJ_INT32 l_h,l_w; + if (parameters->tile_size_on) { +- cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->x1 - cp->tx0), +- (OPJ_INT32)cp->tdx); +- cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->y1 - cp->ty0), +- (OPJ_INT32)cp->tdy); ++ cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx); ++ cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy); + } else { + cp->tdx = image->x1 - cp->tx0; + cp->tdy = image->y1 - cp->ty0; +@@ -9237,10 +9231,8 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + OPJ_INT32 l_h, l_w; -- l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0, (OPJ_INT32)l_img_comp->dx); -- l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0, (OPJ_INT32)l_img_comp->dy); -+ l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); -+ l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); - l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); - l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); +- l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0, +- (OPJ_INT32)l_img_comp->dx); +- l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0, +- (OPJ_INT32)l_img_comp->dy); ++ l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); ++ l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); -@@ -9887,8 +9887,8 @@ OPJ_BOOL opj_j2k_get_tile( opj_j2k_t *p_j2k, +@@ -10848,10 +10840,8 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, - l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; + l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; -- l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0, (OPJ_INT32)l_img_comp->dx); -- l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0, (OPJ_INT32)l_img_comp->dy); -+ l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); -+ l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); - l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); - l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); +- l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0, +- (OPJ_INT32)l_img_comp->dx); +- l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0, +- (OPJ_INT32)l_img_comp->dy); ++ l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); ++ l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); -@@ -10169,8 +10169,8 @@ static void opj_get_tile_dimensions(opj_image_t * l_image, +@@ -11161,10 +11151,8 @@ static void opj_get_tile_dimensions(opj_image_t * l_image, - *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); - *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); -- *l_offset_x = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx); -- *l_offset_y = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->y0, (OPJ_INT32)l_img_comp->dy); -+ *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx); -+ *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy); - *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 - (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx); - *l_stride = *l_image_width - *l_width; - *l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + ((OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width; + *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); + *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); +- *l_offset_x = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x0, +- (OPJ_INT32)l_img_comp->dx); +- *l_offset_y = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->y0, +- (OPJ_INT32)l_img_comp->dy); ++ *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx); ++ *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy); + *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 - + (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx); + *l_stride = *l_image_width - *l_width; diff --git a/third_party/libopenjpeg20/0027-undefined-shift-opj_t1_decode_cblk.patch b/third_party/libopenjpeg20/0027-undefined-shift-opj_t1_decode_cblk.patch deleted file mode 100644 index 7ba877ab98123b37106b07dfdb43f4cf3b49754d..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0027-undefined-shift-opj_t1_decode_cblk.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/libopenjpeg20/t1.c b/third_party/libopenjpeg20/t1.c -index a119db1f7..1ad850c77 100644 ---- a/third_party/libopenjpeg20/t1.c -+++ b/third_party/libopenjpeg20/t1.c -@@ -1411,7 +1411,7 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, - } - } - -- for (passno = 0; passno < seg->real_num_passes; ++passno) { -+ for (passno = 0; (passno < seg->real_num_passes) && (bpno_plus_one >= 1); ++passno) { - switch (passtype) { - case 0: - if (type == T1_TYPE_RAW) { diff --git a/third_party/libopenjpeg20/0028-upstream-check-size-in-opj_j2k_read_siz.patch b/third_party/libopenjpeg20/0028-upstream-check-size-in-opj_j2k_read_siz.patch deleted file mode 100644 index 22d5562a7715600bea36dcc8e4ee2dcc7edbf763..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/0028-upstream-check-size-in-opj_j2k_read_siz.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c -index e77edd22b..cb5a28373 100644 ---- a/third_party/libopenjpeg20/j2k.c -+++ b/third_party/libopenjpeg20/j2k.c -@@ -2117,10 +2117,16 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, - if( l_img_comp->dx < 1 || l_img_comp->dx > 255 || - l_img_comp->dy < 1 || l_img_comp->dy > 255 ) { - opj_event_msg(p_manager, EVT_ERROR, -- "Invalid values for comp = %d : dx=%u dy=%u\n (should be between 1 and 255 according the JPEG2000 norm)", -+ "Invalid values for comp = %d : dx=%u dy=%u (should be between 1 and 255 according to the JPEG2000 norm)\n", - i, l_img_comp->dx, l_img_comp->dy); - return OPJ_FALSE; - } -+ if( l_img_comp->prec > 38) { /* TODO openjpeg won't handle more than ? */ -+ opj_event_msg(p_manager, EVT_ERROR, -+ "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm)\n", -+ i, l_img_comp->prec); -+ return OPJ_FALSE; -+ } - - #ifdef USE_JPWL - if (l_cp->correct) { diff --git a/third_party/libopenjpeg20/0034-opj_malloc.patch b/third_party/libopenjpeg20/0034-opj_malloc.patch new file mode 100644 index 0000000000000000000000000000000000000000..b2bc99ce739fe12cd224cff84401c9a46709e0dc --- /dev/null +++ b/third_party/libopenjpeg20/0034-opj_malloc.patch @@ -0,0 +1,170 @@ +diff --git a/third_party/libopenjpeg20/opj_malloc.h b/third_party/libopenjpeg20/opj_malloc.h +index cbc4106c7..79b3a6410 100644 +--- a/third_party/libopenjpeg20/opj_malloc.h ++++ b/third_party/libopenjpeg20/opj_malloc.h +@@ -31,8 +31,6 @@ + */ + #ifndef OPJ_MALLOC_H + #define OPJ_MALLOC_H +- +-#include <stddef.h> + /** + @file opj_malloc.h + @brief Internal functions +@@ -52,7 +50,16 @@ Allocate an uninitialized memory block + @param size Bytes to allocate + @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available + */ +-void * opj_malloc(size_t size); ++#ifdef ALLOC_PERF_OPT ++void * OPJ_CALLCONV opj_malloc(size_t size); ++#else ++/* prevent assertion on overflow for MSVC */ ++#ifdef _MSC_VER ++#define opj_malloc(size) ((size_t)(size) >= (size_t)-0x100 ? NULL : malloc(size)) ++#else ++#define opj_malloc(size) malloc(size) ++#endif ++#endif + + /** + Allocate a memory block with elements initialized to 0 +@@ -60,24 +67,98 @@ Allocate a memory block with elements initialized to 0 + @param sizeOfElements Bytes per block to allocate + @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available + */ +-void * opj_calloc(size_t numOfElements, size_t sizeOfElements); ++#ifdef ALLOC_PERF_OPT ++void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements); ++#else ++/* prevent assertion on overflow for MSVC */ ++#ifdef _MSC_VER ++#define opj_calloc(num, size) ((size_t)(num) != 0 && (size_t)(num) >= (size_t)-0x100 / (size_t)(size) ? NULL : calloc(num, size)) ++#else ++#define opj_calloc(num, size) calloc(num, size) ++#endif ++#endif + + /** + Allocate memory aligned to a 16 byte boundary + @param size Bytes to allocate + @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available + */ +-void * opj_aligned_malloc(size_t size); +-void * opj_aligned_realloc(void *ptr, size_t size); +-void opj_aligned_free(void* ptr); ++/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ ++#ifdef _WIN32 ++ /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ ++ #ifdef __GNUC__ ++ #include <mm_malloc.h> ++ #define HAVE_MM_MALLOC ++ #else /* MSVC, Intel C++ */ ++ #include <malloc.h> ++ #ifdef _mm_malloc ++ #define HAVE_MM_MALLOC ++ #endif ++ #endif ++#else /* Not _WIN32 */ ++ #if defined(__sun) ++ #define HAVE_MEMALIGN ++ #elif defined(__FreeBSD__) ++ #define HAVE_POSIX_MEMALIGN ++ /* Linux x86_64 and OSX always align allocations to 16 bytes */ ++ #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX) ++ #define HAVE_MEMALIGN ++ #include <malloc.h> ++ #endif ++#endif + +-/** +-Allocate memory aligned to a 32 byte boundary +-@param size Bytes to allocate +-@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +-*/ +-void * opj_aligned_32_malloc(size_t size); +-void * opj_aligned_32_realloc(void *ptr, size_t size); ++#define opj_aligned_malloc(size) malloc(size) ++#define opj_aligned_32_malloc(size) malloc(size) ++#define opj_aligned_free(m) free(m) ++ ++#ifdef HAVE_MM_MALLOC ++ #undef opj_aligned_malloc ++ #define opj_aligned_malloc(size) _mm_malloc((size), 16) ++ #undef opj_aligned_32_malloc ++ #define opj_aligned_32_malloc(size) _mm_malloc((size), 32) ++ #undef opj_aligned_free ++ #define opj_aligned_free(m) _mm_free(m) ++#endif ++ ++#ifdef HAVE_MEMALIGN ++ extern void* memalign(size_t, size_t); ++ #undef opj_aligned_malloc ++ #define opj_aligned_malloc(size) memalign(16, (size)) ++ #undef opj_aligned_32_malloc ++ #define opj_aligned_32_malloc(size) memalign(32, (size)) ++ #undef opj_aligned_free ++ #define opj_aligned_free(m) free(m) ++#endif ++ ++#ifdef HAVE_POSIX_MEMALIGN ++ #undef opj_aligned_malloc ++ extern int posix_memalign(void**, size_t, size_t); ++ ++ static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ ++ void* mem = NULL; ++ posix_memalign(&mem, 16, size); ++ return mem; ++ } ++ ++ #undef opj_aligned_32_malloc ++ static INLINE void* __attribute__ ((malloc)) opj_aligned_32_malloc(size_t size){ ++ void* mem = NULL; ++ posix_memalign(&mem, 32, size); ++ return mem; ++ } ++ ++ #undef opj_aligned_free ++ #define opj_aligned_free(m) free(m) ++#endif ++ ++#ifdef ALLOC_PERF_OPT ++ #undef opj_aligned_malloc ++ #define opj_aligned_malloc(size) opj_malloc(size) ++ #undef opj_aligned_32_malloc ++ #define opj_aligned_32_malloc(size) opj_malloc(size) ++ #undef opj_aligned_free ++ #define opj_aligned_free(m) opj_free(m) ++#endif + + /** + Reallocate memory blocks. +@@ -85,13 +166,26 @@ Reallocate memory blocks. + @param s New size in bytes + @return Returns a void pointer to the reallocated (and possibly moved) memory block + */ +-void * opj_realloc(void * m, size_t s); ++#ifdef ALLOC_PERF_OPT ++void * OPJ_CALLCONV opj_realloc(void * m, size_t s); ++#else ++/* prevent assertion on overflow for MSVC */ ++#ifdef _MSC_VER ++#define opj_realloc(m, s) ((size_t)(s) >= (size_t)-0x100 ? NULL : realloc(m, s)) ++#else ++#define opj_realloc(m, s) realloc(m, s) ++#endif ++#endif + + /** + Deallocates or frees a memory block. + @param m Previously allocated memory block to be freed + */ +-void opj_free(void * m); ++#ifdef ALLOC_PERF_OPT ++void OPJ_CALLCONV opj_free(void * m); ++#else ++#define opj_free(m) free(m) ++#endif + + #if defined(__GNUC__) && !defined(OPJ_SKIP_POISON) + #pragma GCC poison malloc calloc realloc free diff --git a/third_party/libopenjpeg20/0035-opj_image_data_free.patch b/third_party/libopenjpeg20/0035-opj_image_data_free.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc674da378f2277784223255f21ab975d590eb35 --- /dev/null +++ b/third_party/libopenjpeg20/0035-opj_image_data_free.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c +index 298648a77..2374d459f 100644 +--- a/third_party/libopenjpeg20/jp2.c ++++ b/third_party/libopenjpeg20/jp2.c +@@ -1116,7 +1116,7 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + /* Prevent null pointer access */ + if (!src || !dst) { + for (j = 0; j < nr_channels; ++j) { +- opj_free(new_comps[j].data); ++ opj_image_data_free(new_comps[j].data); + } + opj_free(new_comps); + new_comps = NULL; diff --git a/third_party/libopenjpeg20/0035-opj_j2k_update_image_dimensions.patch b/third_party/libopenjpeg20/0035-opj_j2k_update_image_dimensions.patch new file mode 100644 index 0000000000000000000000000000000000000000..b918c0586e0f22ae080bcd041f984f3526419983 --- /dev/null +++ b/third_party/libopenjpeg20/0035-opj_j2k_update_image_dimensions.patch @@ -0,0 +1,49 @@ +diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c +index 784a0620a..cea614709 100644 +--- a/third_party/libopenjpeg20/j2k.c ++++ b/third_party/libopenjpeg20/j2k.c +@@ -9223,32 +9223,30 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image, + + l_img_comp = p_image->comps; + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { +- OPJ_INT32 l_h, l_w; +- + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); + +- l_w = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor) +- - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor); +- if (l_w < 0) { ++ OPJ_INT32 l_1 = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor); ++ OPJ_INT32 l_2 = opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor); ++ if (l_1 < l_2) { + opj_event_msg(p_manager, EVT_ERROR, +- "Size x of the decoded component image is incorrect (comp[%d].w=%d).\n", +- it_comp, l_w); ++ "Size x of the decoded component image is incorrect (comp[%d].w<0).\n", ++ it_comp); + return OPJ_FALSE; + } +- l_img_comp->w = (OPJ_UINT32)l_w; ++ l_img_comp->w = (OPJ_UINT32)(l_1-l_2); + +- l_h = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor) +- - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor); +- if (l_h < 0) { ++ l_1 = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor); ++ l_2 = opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor); ++ if (l_1 < l_2) { + opj_event_msg(p_manager, EVT_ERROR, +- "Size y of the decoded component image is incorrect (comp[%d].h=%d).\n", +- it_comp, l_h); ++ "Size y of the decoded component image is incorrect (comp[%d].h<0).\n", ++ it_comp); + return OPJ_FALSE; + } +- l_img_comp->h = (OPJ_UINT32)l_h; ++ l_img_comp->h = (OPJ_UINT32)(l_1-l_2); + + l_img_comp++; + } diff --git a/third_party/libopenjpeg20/CMakeLists.txt b/third_party/libopenjpeg20/CMakeLists.txt index 7f16834660a2f766443ebef80bd38950017138e9..800dc9aac7fbf93697a0fb085326ffbd26c09d0c 100644 --- a/third_party/libopenjpeg20/CMakeLists.txt +++ b/third_party/libopenjpeg20/CMakeLists.txt @@ -13,6 +13,7 @@ set(OPENJPEG_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/cio.c ${CMAKE_CURRENT_SOURCE_DIR}/dwt.c ${CMAKE_CURRENT_SOURCE_DIR}/event.c + ${CMAKE_CURRENT_SOURCE_DIR}/function_list.c ${CMAKE_CURRENT_SOURCE_DIR}/image.c ${CMAKE_CURRENT_SOURCE_DIR}/invert.c ${CMAKE_CURRENT_SOURCE_DIR}/j2k.c @@ -23,11 +24,11 @@ set(OPENJPEG_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/opj_clock.c ${CMAKE_CURRENT_SOURCE_DIR}/pi.c ${CMAKE_CURRENT_SOURCE_DIR}/raw.c + ${CMAKE_CURRENT_SOURCE_DIR}/sparse_array.c ${CMAKE_CURRENT_SOURCE_DIR}/t1.c ${CMAKE_CURRENT_SOURCE_DIR}/t2.c ${CMAKE_CURRENT_SOURCE_DIR}/tcd.c ${CMAKE_CURRENT_SOURCE_DIR}/tgt.c - ${CMAKE_CURRENT_SOURCE_DIR}/function_list.c ) if(BUILD_JPIP) add_definitions(-DUSE_JPIP) diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium index 6c2a3c74ba01d1810a8a8869c36ee465ee2a2d2c..1805000634eacd7d358ba4a882bf2e663848790d 100644 --- a/third_party/libopenjpeg20/README.pdfium +++ b/third_party/libopenjpeg20/README.pdfium @@ -1,6 +1,6 @@ Name: OpenJPEG URL: http://www.openjpeg.org/ -Version: 0fa5a17c98c4b8f9ee2286f4f0a50cf52a5fccb0 +Version: 2.3.0 (also update in opj_config*) Security Critical: yes License: 2-clause BSD @@ -10,32 +10,21 @@ JPEG 2000 library. Local Modifications: 0000-use-colorspace.patch: Makes it possible to not call opj_jp2_apply_pclr(). -0001-image-data.patch: Fix a crasher in opj_j2k_update_image_data(). -0002-packet-iterator.patch: Fix integer overflow in opj_pi_create_decode(). 0003-dwt-decode.patch: Check array bounds for opj_dwt_decode_1() and friends. -0004-j2k_read_mcc.patch: Move incrementing of l_tcp->m_nb_mcc_records to the right place. 0005-jp2_apply_pclr.patch: Fix out of bounds access. 0006-tcd_init_tile.patch: Fix a divide by zero bug in opj_tcd_init_tile(). 0007-jp2_read_cmap.patch: Fix wrong rendering on greyscale images with index colorspace. -0008-jp2_check_color.patch: Replace an assertion with returning false. 0009-opj_pi_next.patch: Fix potential bad precno value in opj_pi_next* functions. -0010-pi_update_decode_poc.patch: Set proper upper bound for an array in opj_pi_update_decode_poc(). 0011-j2k_update_image_data.patch: Prevent bad signed -> unsigned casting. 0012-mct_sse.patch: Don't use SSE intrinsics in 32-bit builds. -0013-attrib_fix.patch: Don't needlessly redefine __attribute__, https://github.com/uclouvain/openjpeg/issues/727 0014-opj_jp2_read_ihdr_leak.patch: Memory leak in opj_jp2_read_ihdr(). 0015-read_SPCod_SPCoc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SPCod_SPCoc. 0016-read_SQcd_SQcc_overflow.patch: Prevent a buffer overflow in opj_j2k_read_SQcd_SQcc. -0017-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_precinct_size|. -0018-tcd_get_decoded_tile_size.patch: Fix an integer overflow in opj_tcd_get_decoded_tile_size. 0019-tcd_init_tile.patch: Prevent integer overflows during calculation of |l_nb_code_blocks_size|. -0020-opj_aligned_malloc.patch: Prevent overflows when using opj_aligned_malloc(). -0021-tcd_init_tile_negative.patch: Prevent negative x, y values in opj_tcd_init_tile. 0022-jp2_apply_pclr_overflow.patch: Prevent integer overflow in opj_jp2_apply_pclr. 0023-opj_j2k_read_mct_records.patch: Fix opj_j2k_read to prevent heap-use-after-free. -0024-l_marker_size_check.patch: Return error before overflow in opj_j2k_read_header_procedure. 0025-opj_j2k_add_mct_null_data.patch: Check m_data != null before trying to read from it. 0026-use_opj_uint_ceildiv.patch: Remove (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)a, (OPJ_INT32) b). -0027-undefined-shift-opj_t1_decode_cblk.patch: upstream fix for a ubsan bug. -0028-upstream-check-size-in-opj_j2k_read_siz.patch: upstream patch in j2k.c. -TODO(thestig): List all the other patches. +0033-undefined-shift-opj_t1_dec_clnpass.patch: fix undefined shifts originated from opj_t1_decode_cblk. +0034-opj_malloc.patch: PDFium changes in opj_malloc. +0035-opj_j2k_update_image_dimensions.patch: fix integer overflow. diff --git a/third_party/libopenjpeg20/bio.c b/third_party/libopenjpeg20/bio.c index e4edb3724e44e3753ed7e184f1e39ead93c60eca..09dcd7f524926da0a89509c7a025ccd34102c279 100644 --- a/third_party/libopenjpeg20/bio.c +++ b/third_party/libopenjpeg20/bio.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. @@ -72,120 +72,146 @@ static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio); /*@}*/ -/* +/* ========================================================== local functions ========================================================== */ -static OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) { - bio->buf = (bio->buf << 8) & 0xffff; - bio->ct = bio->buf == 0xff00 ? 7 : 8; - if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { - return OPJ_FALSE; - } - *bio->bp++ = (OPJ_BYTE)(bio->buf >> 8); - return OPJ_TRUE; +static OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) +{ + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { + return OPJ_FALSE; + } + *bio->bp++ = (OPJ_BYTE)(bio->buf >> 8); + return OPJ_TRUE; } -static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) { - bio->buf = (bio->buf << 8) & 0xffff; - bio->ct = bio->buf == 0xff00 ? 7 : 8; - if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { - return OPJ_FALSE; - } - bio->buf |= *bio->bp++; - return OPJ_TRUE; +static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) +{ + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { + return OPJ_FALSE; + } + bio->buf |= *bio->bp++; + return OPJ_TRUE; } -static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) { - if (bio->ct == 0) { - opj_bio_byteout(bio); /* MSD: why not check the return value of this function ? */ - } - bio->ct--; - bio->buf |= b << bio->ct; +static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) +{ + if (bio->ct == 0) { + opj_bio_byteout( + bio); /* MSD: why not check the return value of this function ? */ + } + bio->ct--; + bio->buf |= b << bio->ct; } -static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) { - if (bio->ct == 0) { - opj_bio_bytein(bio); /* MSD: why not check the return value of this function ? */ - } - bio->ct--; - return (bio->buf >> bio->ct) & 1; +static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) +{ + if (bio->ct == 0) { + opj_bio_bytein( + bio); /* MSD: why not check the return value of this function ? */ + } + bio->ct--; + return (bio->buf >> bio->ct) & 1; } -/* +/* ========================================================== Bit Input/Output interface ========================================================== */ -opj_bio_t* opj_bio_create(void) { - opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t)); - return bio; +opj_bio_t* opj_bio_create(void) +{ + opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t)); + return bio; } -void opj_bio_destroy(opj_bio_t *bio) { - if(bio) { - opj_free(bio); - } +void opj_bio_destroy(opj_bio_t *bio) +{ + if (bio) { + opj_free(bio); + } } -ptrdiff_t opj_bio_numbytes(opj_bio_t *bio) { - return (bio->bp - bio->start); +ptrdiff_t opj_bio_numbytes(opj_bio_t *bio) +{ + return (bio->bp - bio->start); } -void opj_bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) { - bio->start = bp; - bio->end = bp + len; - bio->bp = bp; - bio->buf = 0; - bio->ct = 8; +void opj_bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) +{ + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 8; } -void opj_bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) { - bio->start = bp; - bio->end = bp + len; - bio->bp = bp; - bio->buf = 0; - bio->ct = 0; +void opj_bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) +{ + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 0; } -void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n) { - OPJ_UINT32 i; - for (i = n - 1; i < n; i--) { - opj_bio_putbit(bio, (v >> i) & 1); - } +void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n) +{ + OPJ_INT32 i; + + assert((n > 0U) && (n <= 32U)); + for (i = (OPJ_INT32)n - 1; i >= 0; i--) { + opj_bio_putbit(bio, (v >> i) & 1); + } } -OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n) { - OPJ_UINT32 i; +OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n) +{ + OPJ_INT32 i; OPJ_UINT32 v; - v = 0; - for (i = n - 1; i < n; i--) { - v += opj_bio_getbit(bio) << i; - } - return v; + + assert((n > 0U) /* && (n <= 32U)*/); +#ifdef OPJ_UBSAN_BUILD + /* This assert fails for some corrupted images which are gracefully rejected */ + /* Add this assert only for ubsan build. */ + /* This is the condition for overflow not to occur below which is needed because of OPJ_NOSANITIZE */ + assert(n <= 32U); +#endif + v = 0U; + for (i = (OPJ_INT32)n - 1; i >= 0; i--) { + v |= opj_bio_getbit(bio) << + i; /* can't overflow, opj_bio_getbit returns 0 or 1 */ + } + return v; } -OPJ_BOOL opj_bio_flush(opj_bio_t *bio) { - if (! opj_bio_byteout(bio)) { - return OPJ_FALSE; - } - if (bio->ct == 7) { - if (! opj_bio_byteout(bio)) { - return OPJ_FALSE; - } - } - return OPJ_TRUE; +OPJ_BOOL opj_bio_flush(opj_bio_t *bio) +{ + if (! opj_bio_byteout(bio)) { + return OPJ_FALSE; + } + if (bio->ct == 7) { + if (! opj_bio_byteout(bio)) { + return OPJ_FALSE; + } + } + return OPJ_TRUE; } -OPJ_BOOL opj_bio_inalign(opj_bio_t *bio) { - if ((bio->buf & 0xff) == 0xff) { - if (! opj_bio_bytein(bio)) { - return OPJ_FALSE; - } - } - bio->ct = 0; - return OPJ_TRUE; +OPJ_BOOL opj_bio_inalign(opj_bio_t *bio) +{ + if ((bio->buf & 0xff) == 0xff) { + if (! opj_bio_bytein(bio)) { + return OPJ_FALSE; + } + } + bio->ct = 0; + return OPJ_TRUE; } diff --git a/third_party/libopenjpeg20/bio.h b/third_party/libopenjpeg20/bio.h index fba2428476a555c7a5aaba4915b1a23ff36c1419..448fdda2190c95fba08c64717c7b8749321c03f5 100644 --- a/third_party/libopenjpeg20/bio.h +++ b/third_party/libopenjpeg20/bio.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. @@ -35,12 +35,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BIO_H -#define __BIO_H +#ifndef OPJ_BIO_H +#define OPJ_BIO_H #include <stddef.h> /* ptrdiff_t */ -/** +/** @file bio.h @brief Implementation of an individual bit input-output (BIO) @@ -54,23 +54,23 @@ The functions in BIO.C have for goal to realize an individual bit input - output Individual bit input-output stream (BIO) */ typedef struct opj_bio { - /** pointer to the start of the buffer */ - OPJ_BYTE *start; - /** pointer to the end of the buffer */ - OPJ_BYTE *end; - /** pointer to the present position in the buffer */ - OPJ_BYTE *bp; - /** temporary place where each byte is read or written */ - OPJ_UINT32 buf; - /** coder : number of bits free to write. decoder : number of bits read */ - OPJ_UINT32 ct; + /** pointer to the start of the buffer */ + OPJ_BYTE *start; + /** pointer to the end of the buffer */ + OPJ_BYTE *end; + /** pointer to the present position in the buffer */ + OPJ_BYTE *bp; + /** temporary place where each byte is read or written */ + OPJ_UINT32 buf; + /** coder : number of bits free to write. decoder : number of bits read */ + OPJ_UINT32 ct; } opj_bio_t; /** @name Exported functions */ /*@{*/ /* ----------------------------------------------------------------------- */ /** -Create a new BIO handle +Create a new BIO handle @return Returns a new BIO handle if successful, returns NULL otherwise */ opj_bio_t* opj_bio_create(void); @@ -89,14 +89,14 @@ ptrdiff_t opj_bio_numbytes(opj_bio_t *bio); Init encoder @param bio BIO handle @param bp Output buffer -@param len Output buffer length +@param len Output buffer length */ void opj_bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len); /** Init decoder @param bio BIO handle @param bp Input buffer -@param len Input buffer length +@param len Input buffer length */ void opj_bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len); /** @@ -109,7 +109,7 @@ void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n); /** Read bits @param bio BIO handle -@param n Number of bits to read +@param n Number of bits to read @return Returns the corresponding read number */ OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n); @@ -130,5 +130,5 @@ OPJ_BOOL opj_bio_inalign(opj_bio_t *bio); /*@}*/ -#endif /* __BIO_H */ +#endif /* OPJ_BIO_H */ diff --git a/third_party/libopenjpeg20/cio.c b/third_party/libopenjpeg20/cio.c index b2f6405f6d032c85fdfc1ee73ad1a5e07235ead2..4fde9fe239b12977badb31639a525a47cd4fb672 100644 --- a/third_party/libopenjpeg20/cio.c +++ b/third_party/libopenjpeg20/cio.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,10 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -44,601 +44,640 @@ /* ----------------------------------------------------------------------- */ -void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes) +void opj_write_bytes_BE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes) { - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value)+sizeof(OPJ_UINT32)-p_nb_bytes; + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof( + OPJ_UINT32) - p_nb_bytes; - assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); - memcpy(p_buffer,l_data_ptr,p_nb_bytes); + memcpy(p_buffer, l_data_ptr, p_nb_bytes); } -void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes) +void opj_write_bytes_LE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes) { - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1; - OPJ_UINT32 i; + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1; + OPJ_UINT32 i; - assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); - for (i=0;i<p_nb_bytes;++i) { - *(p_buffer++) = *(l_data_ptr--); - } + for (i = 0; i < p_nb_bytes; ++i) { + *(p_buffer++) = *(l_data_ptr--); + } } -void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes) +void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes) { - OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); - assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); - *p_value = 0; - memcpy(l_data_ptr+sizeof(OPJ_UINT32)-p_nb_bytes,p_buffer,p_nb_bytes); + *p_value = 0; + memcpy(l_data_ptr + sizeof(OPJ_UINT32) - p_nb_bytes, p_buffer, p_nb_bytes); } -void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes) +void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes) { - OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes-1; - OPJ_UINT32 i; + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes - 1; + OPJ_UINT32 i; - assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); - *p_value = 0; - for (i=0;i<p_nb_bytes;++i) { - *(l_data_ptr--) = *(p_buffer++); - } + *p_value = 0; + for (i = 0; i < p_nb_bytes; ++i) { + *(l_data_ptr--) = *(p_buffer++); + } } void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value) { - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value); - memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT64)); + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value); + memcpy(p_buffer, l_data_ptr, sizeof(OPJ_FLOAT64)); } void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value) { - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT64) - 1; - OPJ_UINT32 i; - for (i=0;i<sizeof(OPJ_FLOAT64);++i) { - *(p_buffer++) = *(l_data_ptr--); - } + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof( + OPJ_FLOAT64) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT64); ++i) { + *(p_buffer++) = *(l_data_ptr--); + } } void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value) { - OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); - memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT64)); + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); + memcpy(l_data_ptr, p_buffer, sizeof(OPJ_FLOAT64)); } void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value) { - OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64)-1; - OPJ_UINT32 i; - for (i=0;i<sizeof(OPJ_FLOAT64);++i) { - *(l_data_ptr--) = *(p_buffer++); - } + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT64); ++i) { + *(l_data_ptr--) = *(p_buffer++); + } } void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value) { - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value); - memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT32)); + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value); + memcpy(p_buffer, l_data_ptr, sizeof(OPJ_FLOAT32)); } void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value) { - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT32) - 1; - OPJ_UINT32 i; - for (i=0;i<sizeof(OPJ_FLOAT32);++i) { - *(p_buffer++) = *(l_data_ptr--); - } + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof( + OPJ_FLOAT32) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT32); ++i) { + *(p_buffer++) = *(l_data_ptr--); + } } void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value) { - OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); - memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT32)); + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); + memcpy(l_data_ptr, p_buffer, sizeof(OPJ_FLOAT32)); } void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value) { - OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32)-1; - OPJ_UINT32 i; - for (i=0;i<sizeof(OPJ_FLOAT32);++i) { - *(l_data_ptr--) = *(p_buffer++); - } + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT32); ++i) { + *(l_data_ptr--) = *(p_buffer++); + } } -opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size,OPJ_BOOL l_is_input) +opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size, + OPJ_BOOL l_is_input) { - opj_stream_private_t * l_stream = 00; - l_stream = (opj_stream_private_t*) opj_calloc(1,sizeof(opj_stream_private_t)); - if (! l_stream) { - return 00; - } + opj_stream_private_t * l_stream = 00; + l_stream = (opj_stream_private_t*) opj_calloc(1, sizeof(opj_stream_private_t)); + if (! l_stream) { + return 00; + } - l_stream->m_buffer_size = p_buffer_size; - l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size); - if (! l_stream->m_stored_data) { - opj_free(l_stream); - return 00; - } + l_stream->m_buffer_size = p_buffer_size; + l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size); + if (! l_stream->m_stored_data) { + opj_free(l_stream); + return 00; + } - l_stream->m_current_data = l_stream->m_stored_data; + l_stream->m_current_data = l_stream->m_stored_data; - if (l_is_input) { - l_stream->m_status |= opj_stream_e_input; - l_stream->m_opj_skip = opj_stream_read_skip; - l_stream->m_opj_seek = opj_stream_read_seek; - } - else { - l_stream->m_status |= opj_stream_e_output; - l_stream->m_opj_skip = opj_stream_write_skip; - l_stream->m_opj_seek = opj_stream_write_seek; - } + if (l_is_input) { + l_stream->m_status |= OPJ_STREAM_STATUS_INPUT; + l_stream->m_opj_skip = opj_stream_read_skip; + l_stream->m_opj_seek = opj_stream_read_seek; + } else { + l_stream->m_status |= OPJ_STREAM_STATUS_OUTPUT; + l_stream->m_opj_skip = opj_stream_write_skip; + l_stream->m_opj_seek = opj_stream_write_seek; + } - l_stream->m_read_fn = opj_stream_default_read; - l_stream->m_write_fn = opj_stream_default_write; - l_stream->m_skip_fn = opj_stream_default_skip; - l_stream->m_seek_fn = opj_stream_default_seek; + l_stream->m_read_fn = opj_stream_default_read; + l_stream->m_write_fn = opj_stream_default_write; + l_stream->m_skip_fn = opj_stream_default_skip; + l_stream->m_seek_fn = opj_stream_default_seek; - return (opj_stream_t *) l_stream; + return (opj_stream_t *) l_stream; } opj_stream_t* OPJ_CALLCONV opj_stream_default_create(OPJ_BOOL l_is_input) { - return opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,l_is_input); + return opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, l_is_input); } void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream) { - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - - if (l_stream) { - if (l_stream->m_free_user_data_fn) { - l_stream->m_free_user_data_fn(l_stream->m_user_data); - } - opj_free(l_stream->m_stored_data); - l_stream->m_stored_data = 00; - opj_free(l_stream); - } + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (l_stream) { + if (l_stream->m_free_user_data_fn) { + l_stream->m_free_user_data_fn(l_stream->m_user_data); + } + opj_free(l_stream->m_stored_data); + l_stream->m_stored_data = 00; + opj_free(l_stream); + } } -void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function) +void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, + opj_stream_read_fn p_function) { - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_INPUT))) { + return; + } + + l_stream->m_read_fn = p_function; +} - if ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) { - return; - } +void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, + opj_stream_seek_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - l_stream->m_read_fn = p_function; + if (!l_stream) { + return; + } + l_stream->m_seek_fn = p_function; } -void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function) +void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, + opj_stream_write_fn p_function) { - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - - if (!l_stream) { - return; - } - l_stream->m_seek_fn = p_function; -} - -void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - - if ((!l_stream )|| (! (l_stream->m_status & opj_stream_e_output))) { - return; - } - - l_stream->m_write_fn = p_function; -} - -void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - - if (! l_stream) { - return; - } - - l_stream->m_skip_fn = p_function; -} - -void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void * p_data, opj_stream_free_user_data_fn p_function) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - if (!l_stream) - return; - l_stream->m_user_data = p_data; - l_stream->m_free_user_data_fn = p_function; -} - -void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT64 data_length) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - if (!l_stream) - return; - l_stream->m_user_data_length = data_length; -} - -OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) -{ - OPJ_SIZE_T l_read_nb_bytes = 0; - if (p_stream->m_bytes_in_buffer >= p_size) { - memcpy(p_buffer,p_stream->m_current_data,p_size); - p_stream->m_current_data += p_size; - p_stream->m_bytes_in_buffer -= p_size; - l_read_nb_bytes += p_size; - p_stream->m_byte_offset += (OPJ_OFF_T)p_size; - return l_read_nb_bytes; - } - - /* we are now in the case when the remaining data if not sufficient */ - if (p_stream->m_status & opj_stream_e_end) { - l_read_nb_bytes += p_stream->m_bytes_in_buffer; - memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); - p_stream->m_current_data += p_stream->m_bytes_in_buffer; - p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1; - } - - /* the flag is not set, we copy data and then do an actual read on the stream */ - if (p_stream->m_bytes_in_buffer) { - l_read_nb_bytes += p_stream->m_bytes_in_buffer; - memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); - p_stream->m_current_data = p_stream->m_stored_data; - p_buffer += p_stream->m_bytes_in_buffer; - p_size -= p_stream->m_bytes_in_buffer; - p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - } - else { - /* case where we are already at the end of the buffer - so reset the m_current_data to point to the start of the - stored buffer to get ready to read from disk*/ - p_stream->m_current_data = p_stream->m_stored_data; - } - - for (;;) { - /* we should read less than a chunk -> read a chunk */ - if (p_size < p_stream->m_buffer_size) { - /* we should do an actual read on the media */ - p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,p_stream->m_buffer_size,p_stream->m_user_data); - - if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T)-1) { - /* end of stream */ - opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); - - p_stream->m_bytes_in_buffer = 0; - p_stream->m_status |= opj_stream_e_end; - /* end of stream */ - return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1; - } - else if (p_stream->m_bytes_in_buffer < p_size) { - /* not enough data */ - l_read_nb_bytes += p_stream->m_bytes_in_buffer; - memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); - p_stream->m_current_data = p_stream->m_stored_data; - p_buffer += p_stream->m_bytes_in_buffer; - p_size -= p_stream->m_bytes_in_buffer; - p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - } - else { - l_read_nb_bytes += p_size; - memcpy(p_buffer,p_stream->m_current_data,p_size); - p_stream->m_current_data += p_size; - p_stream->m_bytes_in_buffer -= p_size; - p_stream->m_byte_offset += (OPJ_OFF_T)p_size; - return l_read_nb_bytes; - } - } - else { - /* direct read on the dest buffer */ - p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data); - - if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T)-1) { - /* end of stream */ - opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); - - p_stream->m_bytes_in_buffer = 0; - p_stream->m_status |= opj_stream_e_end; - /* end of stream */ - return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-1; - } - else if (p_stream->m_bytes_in_buffer < p_size) { - /* not enough data */ - l_read_nb_bytes += p_stream->m_bytes_in_buffer; - p_stream->m_current_data = p_stream->m_stored_data; - p_buffer += p_stream->m_bytes_in_buffer; - p_size -= p_stream->m_bytes_in_buffer; - p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - } - else { - /* we have read the exact size */ - l_read_nb_bytes += p_stream->m_bytes_in_buffer; - p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_current_data = p_stream->m_stored_data; - p_stream->m_bytes_in_buffer = 0; - return l_read_nb_bytes; - } - } - } -} - -OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream, - const OPJ_BYTE * p_buffer, - OPJ_SIZE_T p_size, - opj_event_mgr_t * p_event_mgr) -{ - OPJ_SIZE_T l_remaining_bytes = 0; - OPJ_SIZE_T l_write_nb_bytes = 0; - - if (p_stream->m_status & opj_stream_e_error) { - return (OPJ_SIZE_T)-1; - } - - for (;;) { - l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer; - - /* we have more memory than required */ - if (l_remaining_bytes >= p_size) { - memcpy(p_stream->m_current_data, p_buffer, p_size); - - p_stream->m_current_data += p_size; - p_stream->m_bytes_in_buffer += p_size; - l_write_nb_bytes += p_size; - p_stream->m_byte_offset += (OPJ_OFF_T)p_size; - - return l_write_nb_bytes; - } - - /* we copy data and then do an actual read on the stream */ - if (l_remaining_bytes) { - l_write_nb_bytes += l_remaining_bytes; - - memcpy(p_stream->m_current_data,p_buffer,l_remaining_bytes); - - p_stream->m_current_data = p_stream->m_stored_data; - - p_buffer += l_remaining_bytes; - p_size -= l_remaining_bytes; - p_stream->m_bytes_in_buffer += l_remaining_bytes; - p_stream->m_byte_offset += (OPJ_OFF_T)l_remaining_bytes; - } - - if (! opj_stream_flush(p_stream, p_event_mgr)) { - return (OPJ_SIZE_T)-1; - } - } - -} - -OPJ_BOOL opj_stream_flush (opj_stream_private_t * p_stream, opj_event_mgr_t * p_event_mgr) -{ - /* the number of bytes written on the media. */ - OPJ_SIZE_T l_current_write_nb_bytes = 0; - - p_stream->m_current_data = p_stream->m_stored_data; - - while (p_stream->m_bytes_in_buffer) { - /* we should do an actual write on the media */ - l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data, - p_stream->m_bytes_in_buffer, - p_stream->m_user_data); - - if (l_current_write_nb_bytes == (OPJ_SIZE_T)-1) { - p_stream->m_status |= opj_stream_e_error; - opj_event_msg(p_event_mgr, EVT_INFO, "Error on writing stream!\n"); - - return OPJ_FALSE; - } - - p_stream->m_current_data += l_current_write_nb_bytes; - p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes; - } - - p_stream->m_current_data = p_stream->m_stored_data; - - return OPJ_TRUE; -} - -OPJ_OFF_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) -{ - OPJ_OFF_T l_skip_nb_bytes = 0; - OPJ_OFF_T l_current_skip_nb_bytes = 0; - - assert( p_size >= 0 ); - - if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) { - p_stream->m_current_data += p_size; - /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer - which is of type OPJ_SIZE_T */ - p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)p_size; - l_skip_nb_bytes += p_size; - p_stream->m_byte_offset += l_skip_nb_bytes; - return l_skip_nb_bytes; - } - - /* we are now in the case when the remaining data if not sufficient */ - if (p_stream->m_status & opj_stream_e_end) { - l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_current_data += p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - p_stream->m_byte_offset += l_skip_nb_bytes; - return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) -1; - } - - /* the flag is not set, we copy data and then do an actual skip on the stream */ - if (p_stream->m_bytes_in_buffer) { - l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_current_data = p_stream->m_stored_data; - p_size -= (OPJ_OFF_T)p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - } - - while (p_size > 0) { - /* we should do an actual skip on the media */ - l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); - if (l_current_skip_nb_bytes == (OPJ_OFF_T) -1) { - opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); - - p_stream->m_status |= opj_stream_e_end; - p_stream->m_byte_offset += l_skip_nb_bytes; - /* end if stream */ - return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) -1; - } - p_size -= l_current_skip_nb_bytes; - l_skip_nb_bytes += l_current_skip_nb_bytes; - } - - p_stream->m_byte_offset += l_skip_nb_bytes; - - return l_skip_nb_bytes; -} - -OPJ_OFF_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) -{ - OPJ_BOOL l_is_written = 0; - OPJ_OFF_T l_current_skip_nb_bytes = 0; - OPJ_OFF_T l_skip_nb_bytes = 0; + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_OUTPUT))) { + return; + } + + l_stream->m_write_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, + opj_stream_skip_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (! l_stream) { + return; + } + + l_stream->m_skip_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, + void * p_data, opj_stream_free_user_data_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if (!l_stream) { + return; + } + l_stream->m_user_data = p_data; + l_stream->m_free_user_data_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, + OPJ_UINT64 data_length) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if (!l_stream) { + return; + } + l_stream->m_user_data_length = data_length; +} + +OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream, + OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_SIZE_T l_read_nb_bytes = 0; + if (p_stream->m_bytes_in_buffer >= p_size) { + memcpy(p_buffer, p_stream->m_current_data, p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + l_read_nb_bytes += p_size; + p_stream->m_byte_offset += (OPJ_OFF_T)p_size; + return l_read_nb_bytes; + } + + /* we are now in the case when the remaining data if not sufficient */ + if (p_stream->m_status & OPJ_STREAM_STATUS_END) { + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer); + p_stream->m_current_data += p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1; + } + + /* the flag is not set, we copy data and then do an actual read on the stream */ + if (p_stream->m_bytes_in_buffer) { + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } else { + /* case where we are already at the end of the buffer + so reset the m_current_data to point to the start of the + stored buffer to get ready to read from disk*/ + p_stream->m_current_data = p_stream->m_stored_data; + } + + for (;;) { + /* we should read less than a chunk -> read a chunk */ + if (p_size < p_stream->m_buffer_size) { + /* we should do an actual read on the media */ + p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data, + p_stream->m_buffer_size, p_stream->m_user_data); + + if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) { + /* end of stream */ + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_bytes_in_buffer = 0; + p_stream->m_status |= OPJ_STREAM_STATUS_END; + /* end of stream */ + return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1; + } else if (p_stream->m_bytes_in_buffer < p_size) { + /* not enough data */ + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } else { + l_read_nb_bytes += p_size; + memcpy(p_buffer, p_stream->m_current_data, p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + p_stream->m_byte_offset += (OPJ_OFF_T)p_size; + return l_read_nb_bytes; + } + } else { + /* direct read on the dest buffer */ + p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer, p_size, + p_stream->m_user_data); + + if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) { + /* end of stream */ + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_bytes_in_buffer = 0; + p_stream->m_status |= OPJ_STREAM_STATUS_END; + /* end of stream */ + return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1; + } else if (p_stream->m_bytes_in_buffer < p_size) { + /* not enough data */ + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } else { + /* we have read the exact size */ + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + return l_read_nb_bytes; + } + } + } +} + +OPJ_SIZE_T opj_stream_write_data(opj_stream_private_t * p_stream, + const OPJ_BYTE * p_buffer, + OPJ_SIZE_T p_size, + opj_event_mgr_t * p_event_mgr) +{ + OPJ_SIZE_T l_remaining_bytes = 0; + OPJ_SIZE_T l_write_nb_bytes = 0; + + if (p_stream->m_status & OPJ_STREAM_STATUS_ERROR) { + return (OPJ_SIZE_T) - 1; + } + + for (;;) { + l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer; + + /* we have more memory than required */ + if (l_remaining_bytes >= p_size) { + memcpy(p_stream->m_current_data, p_buffer, p_size); + + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer += p_size; + l_write_nb_bytes += p_size; + p_stream->m_byte_offset += (OPJ_OFF_T)p_size; + + return l_write_nb_bytes; + } + + /* we copy data and then do an actual read on the stream */ + if (l_remaining_bytes) { + l_write_nb_bytes += l_remaining_bytes; + + memcpy(p_stream->m_current_data, p_buffer, l_remaining_bytes); + + p_stream->m_current_data = p_stream->m_stored_data; + + p_buffer += l_remaining_bytes; + p_size -= l_remaining_bytes; + p_stream->m_bytes_in_buffer += l_remaining_bytes; + p_stream->m_byte_offset += (OPJ_OFF_T)l_remaining_bytes; + } + + if (! opj_stream_flush(p_stream, p_event_mgr)) { + return (OPJ_SIZE_T) - 1; + } + } + +} + +OPJ_BOOL opj_stream_flush(opj_stream_private_t * p_stream, + opj_event_mgr_t * p_event_mgr) +{ + /* the number of bytes written on the media. */ + OPJ_SIZE_T l_current_write_nb_bytes = 0; + + p_stream->m_current_data = p_stream->m_stored_data; + + while (p_stream->m_bytes_in_buffer) { + /* we should do an actual write on the media */ + l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data, + p_stream->m_bytes_in_buffer, + p_stream->m_user_data); + + if (l_current_write_nb_bytes == (OPJ_SIZE_T) - 1) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + opj_event_msg(p_event_mgr, EVT_INFO, "Error on writing stream!\n"); + + return OPJ_FALSE; + } + + p_stream->m_current_data += l_current_write_nb_bytes; + p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes; + } + + p_stream->m_current_data = p_stream->m_stored_data; + + return OPJ_TRUE; +} + +OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_OFF_T l_skip_nb_bytes = 0; + OPJ_OFF_T l_current_skip_nb_bytes = 0; + + assert(p_size >= 0); + + if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) { + p_stream->m_current_data += p_size; + /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer + which is of type OPJ_SIZE_T */ + p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)p_size; + l_skip_nb_bytes += p_size; + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes; + } + + /* we are now in the case when the remaining data if not sufficient */ + if (p_stream->m_status & OPJ_STREAM_STATUS_END) { + l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_current_data += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + + /* the flag is not set, we copy data and then do an actual skip on the stream */ + if (p_stream->m_bytes_in_buffer) { + l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_size -= (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } + + while (p_size > 0) { + /* Check if we are going beyond the end of file. Most skip_fn do not */ + /* check that, but we must be careful not to advance m_byte_offset */ + /* beyond m_user_data_length, otherwise */ + /* opj_stream_get_number_byte_left() will assert. */ + if ((OPJ_UINT64)(p_stream->m_byte_offset + l_skip_nb_bytes + p_size) > + p_stream->m_user_data_length) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_byte_offset += l_skip_nb_bytes; + l_skip_nb_bytes = (OPJ_OFF_T)(p_stream->m_user_data_length - + (OPJ_UINT64)p_stream->m_byte_offset); + + opj_stream_read_seek(p_stream, (OPJ_OFF_T)p_stream->m_user_data_length, + p_event_mgr); + p_stream->m_status |= OPJ_STREAM_STATUS_END; + + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + + /* we should do an actual skip on the media */ + l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); + if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_status |= OPJ_STREAM_STATUS_END; + p_stream->m_byte_offset += l_skip_nb_bytes; + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + p_size -= l_current_skip_nb_bytes; + l_skip_nb_bytes += l_current_skip_nb_bytes; + } + + p_stream->m_byte_offset += l_skip_nb_bytes; + + return l_skip_nb_bytes; +} + +OPJ_OFF_T opj_stream_write_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_BOOL l_is_written = 0; + OPJ_OFF_T l_current_skip_nb_bytes = 0; + OPJ_OFF_T l_skip_nb_bytes = 0; + + if (p_stream->m_status & OPJ_STREAM_STATUS_ERROR) { + return (OPJ_OFF_T) - 1; + } + + /* we should flush data */ + l_is_written = opj_stream_flush(p_stream, p_event_mgr); + if (! l_is_written) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + p_stream->m_bytes_in_buffer = 0; + return (OPJ_OFF_T) - 1; + } + /* then skip */ - if (p_stream->m_status & opj_stream_e_error) { - return (OPJ_OFF_T) -1; - } + while (p_size > 0) { + /* we should do an actual skip on the media */ + l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); - /* we should flush data */ - l_is_written = opj_stream_flush (p_stream, p_event_mgr); - if (! l_is_written) { - p_stream->m_status |= opj_stream_e_error; - p_stream->m_bytes_in_buffer = 0; - return (OPJ_OFF_T) -1; - } - /* then skip */ + if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n"); - while (p_size > 0) { - /* we should do an actual skip on the media */ - l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); - - if (l_current_skip_nb_bytes == (OPJ_OFF_T)-1) { - opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n"); + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + p_stream->m_byte_offset += l_skip_nb_bytes; + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + p_size -= l_current_skip_nb_bytes; + l_skip_nb_bytes += l_current_skip_nb_bytes; + } - p_stream->m_status |= opj_stream_e_error; - p_stream->m_byte_offset += l_skip_nb_bytes; - /* end if stream */ - return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T)-1; - } - p_size -= l_current_skip_nb_bytes; - l_skip_nb_bytes += l_current_skip_nb_bytes; - } + p_stream->m_byte_offset += l_skip_nb_bytes; - p_stream->m_byte_offset += l_skip_nb_bytes; - - return l_skip_nb_bytes; + return l_skip_nb_bytes; } -OPJ_OFF_T opj_stream_tell (const opj_stream_private_t * p_stream) +OPJ_OFF_T opj_stream_tell(const opj_stream_private_t * p_stream) { - return p_stream->m_byte_offset; + return p_stream->m_byte_offset; } -OPJ_OFF_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream) +OPJ_OFF_T opj_stream_get_number_byte_left(const opj_stream_private_t * p_stream) { - assert( p_stream->m_byte_offset >= 0 ); - assert( p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset); - return p_stream->m_user_data_length ? - (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset : - 0; + assert(p_stream->m_byte_offset >= 0); + assert(p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset); + return p_stream->m_user_data_length ? + (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset : + 0; } -OPJ_OFF_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +OPJ_OFF_T opj_stream_skip(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + opj_event_mgr_t * p_event_mgr) { - assert(p_size >= 0); - return p_stream->m_opj_skip(p_stream,p_size,p_event_mgr); + assert(p_size >= 0); + return p_stream->m_opj_skip(p_stream, p_size, p_event_mgr); } -OPJ_BOOL opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +OPJ_BOOL opj_stream_read_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + opj_event_mgr_t * p_event_mgr) { - OPJ_ARG_NOT_USED(p_event_mgr); - p_stream->m_current_data = p_stream->m_stored_data; - p_stream->m_bytes_in_buffer = 0; + OPJ_ARG_NOT_USED(p_event_mgr); + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; - if( !(p_stream->m_seek_fn(p_size,p_stream->m_user_data)) ) { - p_stream->m_status |= opj_stream_e_end; - return OPJ_FALSE; - } - else { - /* reset stream status */ - p_stream->m_status &= (~opj_stream_e_end); - p_stream->m_byte_offset = p_size; + if (!(p_stream->m_seek_fn(p_size, p_stream->m_user_data))) { + p_stream->m_status |= OPJ_STREAM_STATUS_END; + return OPJ_FALSE; + } else { + /* reset stream status */ + p_stream->m_status &= (~OPJ_STREAM_STATUS_END); + p_stream->m_byte_offset = p_size; - } + } - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_BOOL opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +OPJ_BOOL opj_stream_write_seek(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) { - if (! opj_stream_flush(p_stream,p_event_mgr)) { - p_stream->m_status |= opj_stream_e_error; - return OPJ_FALSE; - } + if (! opj_stream_flush(p_stream, p_event_mgr)) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + return OPJ_FALSE; + } - p_stream->m_current_data = p_stream->m_stored_data; - p_stream->m_bytes_in_buffer = 0; + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; - if (! p_stream->m_seek_fn(p_size,p_stream->m_user_data)) { - p_stream->m_status |= opj_stream_e_error; - return OPJ_FALSE; - } - else { - p_stream->m_byte_offset = p_size; - } + if (! p_stream->m_seek_fn(p_size, p_stream->m_user_data)) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + return OPJ_FALSE; + } else { + p_stream->m_byte_offset = p_size; + } - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_BOOL opj_stream_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr) +OPJ_BOOL opj_stream_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr) { - assert(p_size >= 0); - return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr); + assert(p_size >= 0); + return p_stream->m_opj_seek(p_stream, p_size, p_event_mgr); } -OPJ_BOOL opj_stream_has_seek (const opj_stream_private_t * p_stream) +OPJ_BOOL opj_stream_has_seek(const opj_stream_private_t * p_stream) { - return p_stream->m_seek_fn != opj_stream_default_seek; + return p_stream->m_seek_fn != opj_stream_default_seek; } -OPJ_SIZE_T opj_stream_default_read (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) +OPJ_SIZE_T opj_stream_default_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) { - OPJ_ARG_NOT_USED(p_buffer); - OPJ_ARG_NOT_USED(p_nb_bytes); - OPJ_ARG_NOT_USED(p_user_data); - return (OPJ_SIZE_T) -1; + OPJ_ARG_NOT_USED(p_buffer); + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return (OPJ_SIZE_T) - 1; } -OPJ_SIZE_T opj_stream_default_write (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) +OPJ_SIZE_T opj_stream_default_write(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) { - OPJ_ARG_NOT_USED(p_buffer); - OPJ_ARG_NOT_USED(p_nb_bytes); - OPJ_ARG_NOT_USED(p_user_data); - return (OPJ_SIZE_T) -1; + OPJ_ARG_NOT_USED(p_buffer); + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return (OPJ_SIZE_T) - 1; } -OPJ_OFF_T opj_stream_default_skip (OPJ_OFF_T p_nb_bytes, void * p_user_data) +OPJ_OFF_T opj_stream_default_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data) { - OPJ_ARG_NOT_USED(p_nb_bytes); - OPJ_ARG_NOT_USED(p_user_data); - return (OPJ_OFF_T) -1; + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return (OPJ_OFF_T) - 1; } -OPJ_BOOL opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data) +OPJ_BOOL opj_stream_default_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data) { - OPJ_ARG_NOT_USED(p_nb_bytes); - OPJ_ARG_NOT_USED(p_user_data); - return OPJ_FALSE; + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return OPJ_FALSE; } diff --git a/third_party/libopenjpeg20/cio.h b/third_party/libopenjpeg20/cio.h index 1b684ef881356f64de55b2c9e5cc971d943db766..6996a9a0a1186f0db768caa7f17e6d6b1b423aa5 100644 --- a/third_party/libopenjpeg20/cio.h +++ b/third_party/libopenjpeg20/cio.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,10 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -37,8 +37,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __CIO_H -#define __CIO_H +#ifndef OPJ_CIO_H +#define OPJ_CIO_H /** @file cio.h @brief Implementation of a byte input-output process (CIO) @@ -54,116 +54,112 @@ The functions in CIO.C have for goal to realize a byte input / output process. /* ----------------------------------------------------------------------- */ #if defined(OPJ_BIG_ENDIAN) - #define opj_write_bytes opj_write_bytes_BE - #define opj_read_bytes opj_read_bytes_BE - #define opj_write_double opj_write_double_BE - #define opj_read_double opj_read_double_BE - #define opj_write_float opj_write_float_BE - #define opj_read_float opj_read_float_BE +#define opj_write_bytes opj_write_bytes_BE +#define opj_read_bytes opj_read_bytes_BE +#define opj_write_double opj_write_double_BE +#define opj_read_double opj_read_double_BE +#define opj_write_float opj_write_float_BE +#define opj_read_float opj_read_float_BE #else - #define opj_write_bytes opj_write_bytes_LE - #define opj_read_bytes opj_read_bytes_LE - #define opj_write_double opj_write_double_LE - #define opj_read_double opj_read_double_LE - #define opj_write_float opj_write_float_LE - #define opj_read_float opj_read_float_LE +#define opj_write_bytes opj_write_bytes_LE +#define opj_read_bytes opj_read_bytes_LE +#define opj_write_double opj_write_double_LE +#define opj_read_double opj_read_double_LE +#define opj_write_float opj_write_float_LE +#define opj_read_float opj_read_float_LE #endif - -typedef enum -{ - opj_signed_sentinel = -1, /* do not use in code */ - opj_stream_e_output = 0x1, - opj_stream_e_input = 0x2, - opj_stream_e_end = 0x4, - opj_stream_e_error = 0x8 -} -opj_stream_flag ; +#define OPJ_STREAM_STATUS_OUTPUT 0x1U +#define OPJ_STREAM_STATUS_INPUT 0x2U +#define OPJ_STREAM_STATUS_END 0x4U +#define OPJ_STREAM_STATUS_ERROR 0x8U /** Byte input-output stream. */ -typedef struct opj_stream_private -{ - /** - * User data, be it files, ... The actual data depends on the type of the stream. - */ - void * m_user_data; - - /** - * Pointer to function to free m_user_data (NULL at initialization) - * when destroying the stream. If pointer is NULL the function is not - * called and the m_user_data is not freed (even if non-NULL). - */ - opj_stream_free_user_data_fn m_free_user_data_fn; - - /** - * User data length - */ - OPJ_UINT64 m_user_data_length; - - /** - * Pointer to actual read function (NULL at the initialization of the cio. - */ - opj_stream_read_fn m_read_fn; - - /** - * Pointer to actual write function (NULL at the initialization of the cio. - */ - opj_stream_write_fn m_write_fn; - - /** - * Pointer to actual skip function (NULL at the initialization of the cio. - * There is no seek function to prevent from back and forth slow procedures. - */ - opj_stream_skip_fn m_skip_fn; - - /** - * Pointer to actual seek function (if available). - */ - opj_stream_seek_fn m_seek_fn; - - /** - * Actual data stored into the stream if readed from. Data is read by chunk of fixed size. - * you should never access this data directly. - */ - OPJ_BYTE * m_stored_data; - - /** - * Pointer to the current read data. - */ - OPJ_BYTE * m_current_data; +typedef struct opj_stream_private { + /** + * User data, be it files, ... The actual data depends on the type of the stream. + */ + void * m_user_data; + + /** + * Pointer to function to free m_user_data (NULL at initialization) + * when destroying the stream. If pointer is NULL the function is not + * called and the m_user_data is not freed (even if non-NULL). + */ + opj_stream_free_user_data_fn m_free_user_data_fn; + + /** + * User data length + */ + OPJ_UINT64 m_user_data_length; + + /** + * Pointer to actual read function (NULL at the initialization of the cio. + */ + opj_stream_read_fn m_read_fn; + + /** + * Pointer to actual write function (NULL at the initialization of the cio. + */ + opj_stream_write_fn m_write_fn; + + /** + * Pointer to actual skip function (NULL at the initialization of the cio. + * There is no seek function to prevent from back and forth slow procedures. + */ + opj_stream_skip_fn m_skip_fn; + + /** + * Pointer to actual seek function (if available). + */ + opj_stream_seek_fn m_seek_fn; + + /** + * Actual data stored into the stream if readed from. Data is read by chunk of fixed size. + * you should never access this data directly. + */ + OPJ_BYTE * m_stored_data; + + /** + * Pointer to the current read data. + */ + OPJ_BYTE * m_current_data; /** * FIXME DOC. */ - OPJ_OFF_T (* m_opj_skip)(struct opj_stream_private * ,OPJ_OFF_T , struct opj_event_mgr *); + OPJ_OFF_T(* m_opj_skip)(struct opj_stream_private *, OPJ_OFF_T, + struct opj_event_mgr *); /** * FIXME DOC. */ - OPJ_BOOL (* m_opj_seek) (struct opj_stream_private * , OPJ_OFF_T , struct opj_event_mgr *); + OPJ_BOOL(* m_opj_seek)(struct opj_stream_private *, OPJ_OFF_T, + struct opj_event_mgr *); - /** - * number of bytes containing in the buffer. - */ - OPJ_SIZE_T m_bytes_in_buffer; + /** + * number of bytes containing in the buffer. + */ + OPJ_SIZE_T m_bytes_in_buffer; - /** - * The number of bytes read/written from the beginning of the stream - */ - OPJ_OFF_T m_byte_offset; + /** + * The number of bytes read/written from the beginning of the stream + */ + OPJ_OFF_T m_byte_offset; - /** - * The size of the buffer. - */ - OPJ_SIZE_T m_buffer_size; + /** + * The size of the buffer. + */ + OPJ_SIZE_T m_buffer_size; - /** - * Flags to tell the status of the stream. - */ - opj_stream_flag m_status; + /** + * Flags to tell the status of the stream. + * Used with OPJ_STREAM_STATUS_* defines. + */ + OPJ_UINT32 m_status; } opj_stream_private_t; @@ -173,221 +169,238 @@ opj_stream_private_t; /* ----------------------------------------------------------------------- */ /** * Write some bytes to the given data buffer, this function is used in Big Endian cpus. - * @param p_buffer pointer the data buffer to write data to. - * @param p_value the value to write - * @param p_nb_bytes the number of bytes to write + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write */ -void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes); +void opj_write_bytes_BE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes); /** * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. - * @param p_buffer pointer the data buffer to read data from. - * @param p_value pointer to the value that will store the data. - * @param p_nb_bytes the nb bytes to read. - * @return the number of bytes read or -1 if an error occurred. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occurred. */ -void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes); +void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes); /** * Write some bytes to the given data buffer, this function is used in Little Endian cpus. - * @param p_buffer pointer the data buffer to write data to. - * @param p_value the value to write - * @param p_nb_bytes the number of bytes to write - * @return the number of bytes written or -1 if an error occurred + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write + * @return the number of bytes written or -1 if an error occurred */ -void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes); +void opj_write_bytes_LE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes); /** * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. - * @param p_buffer pointer the data buffer to read data from. - * @param p_value pointer to the value that will store the data. - * @param p_nb_bytes the nb bytes to read. - * @return the number of bytes read or -1 if an error occurred. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occurred. */ -void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes); +void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes); /** * Write some bytes to the given data buffer, this function is used in Little Endian cpus. - * @param p_buffer pointer the data buffer to write data to. - * @param p_value the value to write + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write */ void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value); /*** * Write some bytes to the given data buffer, this function is used in Big Endian cpus. - * @param p_buffer pointer the data buffer to write data to. - * @param p_value the value to write + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write */ void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value); /** * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. - * @param p_buffer pointer the data buffer to read data from. - * @param p_value pointer to the value that will store the data. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. */ void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value); /** * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. - * @param p_buffer pointer the data buffer to read data from. - * @param p_value pointer to the value that will store the data. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. */ void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value); /** * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. - * @param p_buffer pointer the data buffer to read data from. - * @param p_value pointer to the value that will store the data. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. */ void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value); /** * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. - * @param p_buffer pointer the data buffer to read data from. - * @param p_value pointer to the value that will store the data. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. */ void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value); /** * Write some bytes to the given data buffer, this function is used in Little Endian cpus. - * @param p_buffer pointer the data buffer to write data to. - * @param p_value the value to write + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write */ void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value); /*** * Write some bytes to the given data buffer, this function is used in Big Endian cpus. - * @param p_buffer pointer the data buffer to write data to. - * @param p_value the value to write + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write */ void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value); /** * Reads some bytes from the stream. - * @param p_stream the stream to read data from. - * @param p_buffer pointer to the data buffer that will receive the data. - * @param p_size number of bytes to read. - * @param p_event_mgr the user event manager to be notified of special events. - * @return the number of bytes read, or -1 if an error occurred or if the stream is at the end. + * @param p_stream the stream to read data from. + * @param p_buffer pointer to the data buffer that will receive the data. + * @param p_size number of bytes to read. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes read, or -1 if an error occurred or if the stream is at the end. */ -OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream, + OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); /** * Writes some bytes to the stream. - * @param p_stream the stream to write data to. - * @param p_buffer pointer to the data buffer holds the data to be writtent. - * @param p_size number of bytes to write. - * @param p_event_mgr the user event manager to be notified of special events. - * @return the number of bytes writtent, or -1 if an error occurred. + * @param p_stream the stream to write data to. + * @param p_buffer pointer to the data buffer holds the data to be writtent. + * @param p_size number of bytes to write. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes writtent, or -1 if an error occurred. */ -OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_SIZE_T opj_stream_write_data(opj_stream_private_t * p_stream, + const OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, + struct opj_event_mgr * p_event_mgr); /** * Writes the content of the stream buffer to the stream. - * @param p_stream the stream to write data to. - * @param p_event_mgr the user event manager to be notified of special events. - * @return true if the data could be flushed, false else. + * @param p_stream the stream to write data to. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the data could be flushed, false else. */ -OPJ_BOOL opj_stream_flush (opj_stream_private_t * p_stream, struct opj_event_mgr * p_event_mgr); +OPJ_BOOL opj_stream_flush(opj_stream_private_t * p_stream, + struct opj_event_mgr * p_event_mgr); /** * Skips a number of bytes from the stream. - * @param p_stream the stream to skip data from. - * @param p_size the number of bytes to skip. - * @param p_event_mgr the user event manager to be notified of special events. - * @return the number of bytes skipped, or -1 if an error occurred. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. */ -OPJ_OFF_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_OFF_T opj_stream_skip(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr); /** * Tells the byte offset on the stream (similar to ftell). * - * @param p_stream the stream to get the information from. + * @param p_stream the stream to get the information from. * - * @return the current position o fthe stream. + * @return the current position o fthe stream. */ -OPJ_OFF_T opj_stream_tell (const opj_stream_private_t * p_stream); +OPJ_OFF_T opj_stream_tell(const opj_stream_private_t * p_stream); /** * Get the number of bytes left before the end of the stream (similar to cio_numbytesleft). * - * @param p_stream the stream to get the information from. + * @param p_stream the stream to get the information from. * - * @return Number of bytes left before the end of the stream. + * @return Number of bytes left before the end of the stream. */ -OPJ_OFF_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream); +OPJ_OFF_T opj_stream_get_number_byte_left(const opj_stream_private_t * + p_stream); /** * Skips a number of bytes from the stream. - * @param p_stream the stream to skip data from. - * @param p_size the number of bytes to skip. - * @param p_event_mgr the user event manager to be notified of special events. - * @return the number of bytes skipped, or -1 if an error occurred. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. */ -OPJ_OFF_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_OFF_T opj_stream_write_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); /** * Skips a number of bytes from the stream. - * @param p_stream the stream to skip data from. - * @param p_size the number of bytes to skip. - * @param p_event_mgr the user event manager to be notified of special events. - * @return the number of bytes skipped, or -1 if an error occurred. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. */ -OPJ_OFF_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); /** * Skips a number of bytes from the stream. - * @param p_stream the stream to skip data from. - * @param p_size the number of bytes to skip. - * @param p_event_mgr the user event manager to be notified of special events. - * @return OPJ_TRUE if success, or OPJ_FALSE if an error occurred. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return OPJ_TRUE if success, or OPJ_FALSE if an error occurred. */ -OPJ_BOOL opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_BOOL opj_stream_read_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr); /** * Skips a number of bytes from the stream. - * @param p_stream the stream to skip data from. - * @param p_size the number of bytes to skip. - * @param p_event_mgr the user event manager to be notified of special events. - * @return the number of bytes skipped, or -1 if an error occurred. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. */ -OPJ_BOOL opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_BOOL opj_stream_write_seek(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); /** * Seeks a number of bytes from the stream. - * @param p_stream the stream to skip data from. - * @param p_size the number of bytes to skip. - * @param p_event_mgr the user event manager to be notified of special events. - * @return true if the stream is seekable. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the stream is seekable. */ -OPJ_BOOL opj_stream_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); +OPJ_BOOL opj_stream_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr); /** * Tells if the given stream is seekable. */ -OPJ_BOOL opj_stream_has_seek (const opj_stream_private_t * p_stream); +OPJ_BOOL opj_stream_has_seek(const opj_stream_private_t * p_stream); /** * FIXME DOC. */ -OPJ_SIZE_T opj_stream_default_read (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data); +OPJ_SIZE_T opj_stream_default_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data); /** * FIXME DOC. */ -OPJ_SIZE_T opj_stream_default_write (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data); +OPJ_SIZE_T opj_stream_default_write(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data); /** * FIXME DOC. */ -OPJ_OFF_T opj_stream_default_skip (OPJ_OFF_T p_nb_bytes, void * p_user_data); +OPJ_OFF_T opj_stream_default_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data); /** * FIXME DOC. */ -OPJ_BOOL opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data); +OPJ_BOOL opj_stream_default_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data); /* ----------------------------------------------------------------------- */ /*@}*/ @@ -395,5 +408,5 @@ OPJ_BOOL opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data); /*@}*/ -#endif /* __CIO_H */ +#endif /* OPJ_CIO_H */ diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c index 1bcb10816318198724c12d2e0e38d02133675314..1455ee84a1fe47b5996ac3c0288ba99db00422e5 100644 --- a/third_party/libopenjpeg20/dwt.c +++ b/third_party/libopenjpeg20/dwt.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,11 +8,12 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2007, Jonathan Ballard <dzonatas@dzonux.net> * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com> + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,35 +38,66 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <assert.h> + +#define OPJ_SKIP_POISON +#include "opj_includes.h" + #ifdef __SSE__ #include <xmmintrin.h> #endif +#ifdef __SSE2__ +#include <emmintrin.h> +#endif +#ifdef __SSSE3__ +#include <tmmintrin.h> +#endif +#ifdef __AVX2__ +#include <immintrin.h> +#endif -#include "opj_includes.h" +#if defined(__GNUC__) +#pragma GCC poison malloc calloc realloc free +#endif /** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ /*@{*/ +#ifdef __AVX2__ +/** Number of int32 values in a AVX2 register */ +#define VREG_INT_COUNT 8 +#else +/** Number of int32 values in a SSE2 register */ +#define VREG_INT_COUNT 4 +#endif + +/** Number of columns that we can process in parallel in the vertical pass */ +#define PARALLEL_COLS_53 (2*VREG_INT_COUNT) + /** @name Local data structures */ /*@{*/ typedef struct dwt_local { - OPJ_INT32* mem; - OPJ_SIZE_T mem_count; - OPJ_INT32 dn; - OPJ_INT32 sn; - OPJ_INT32 cas; + OPJ_INT32* mem; + OPJ_SIZE_T mem_count; + OPJ_INT32 dn; /* number of elements in high pass band */ + OPJ_INT32 sn; /* number of elements in low pass band */ + OPJ_INT32 cas; /* 0 = start on even coord, 1 = start on odd coord */ } opj_dwt_t; typedef union { - OPJ_FLOAT32 f[4]; + OPJ_FLOAT32 f[4]; } opj_v4_t; typedef struct v4dwt_local { - opj_v4_t* wavelet ; - OPJ_INT32 dn ; - OPJ_INT32 sn ; - OPJ_INT32 cas ; + opj_v4_t* wavelet ; + OPJ_INT32 dn ; /* number of elements in high pass band */ + OPJ_INT32 sn ; /* number of elements in low pass band */ + OPJ_INT32 cas ; /* 0 = start on even coord, 1 = start on odd coord */ + OPJ_UINT32 win_l_x0; /* start coord in low pass band */ + OPJ_UINT32 win_l_x1; /* end coord in low pass band */ + OPJ_UINT32 win_h_x0; /* start coord in high pass band */ + OPJ_UINT32 win_h_x1; /* end coord in high pass band */ } opj_v4dwt_t ; static const OPJ_FLOAT32 opj_dwt_alpha = 1.586134342f; /* 12994 */ @@ -79,9 +111,9 @@ static const OPJ_FLOAT32 opj_c13318 = 1.625732422f; /*@}*/ /** -Virtual function type for wavelet transform in 1-D +Virtual function type for wavelet transform in 1-D */ -typedef void (*DWT1DFN)(opj_dwt_t* v); +typedef void (*DWT1DFN)(const opj_dwt_t* v); /** @name Local static functions */ /*@{*/ @@ -89,64 +121,83 @@ typedef void (*DWT1DFN)(opj_dwt_t* v); /** Forward lazy transform (horizontal) */ -static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas); /** Forward lazy transform (vertical) */ -static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas); -/** -Inverse lazy transform (horizontal) -*/ -static void opj_dwt_interleave_h(opj_dwt_t* h, OPJ_INT32 *a); -/** -Inverse lazy transform (vertical) -*/ -static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x); +static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas); /** Forward 5-3 wavelet transform in 1-D */ -static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -/** -Inverse 5-3 wavelet transform in 1-D -*/ -static void opj_dwt_decode_1(opj_dwt_t *v); -static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas); /** Forward 9-7 wavelet transform in 1-D */ -static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, + OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); + + /** -Explicit calculation of the Quantization Stepsizes +Explicit calculation of the Quantization Stepsizes */ -static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize); +static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, + opj_stepsize_t *bandno_stepsize); /** Inverse wavelet transform in 2-D. */ -static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn); +static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, + const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i); + +static OPJ_BOOL opj_dwt_decode_partial_tile( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres); static OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, - void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)); + void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)); -static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i); +static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, + OPJ_UINT32 i); /* <summary> */ /* Inverse 9-7 wavelet transform in 1-D. */ /* </summary> */ -static void opj_v4dwt_decode(opj_v4dwt_t* restrict dwt); +static void opj_v4dwt_decode(opj_v4dwt_t* OPJ_RESTRICT dwt); -static void opj_v4dwt_interleave_h(opj_v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size); +static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT dwt, + OPJ_FLOAT32* OPJ_RESTRICT a, + OPJ_UINT32 width, + OPJ_UINT32 remaining_height); -static void opj_v4dwt_interleave_v(opj_v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x, OPJ_INT32 nb_elts_read); +static void opj_v4dwt_interleave_v(opj_v4dwt_t* OPJ_RESTRICT dwt, + OPJ_FLOAT32* OPJ_RESTRICT a, + OPJ_UINT32 width, + OPJ_UINT32 nb_elts_read); #ifdef __SSE__ -static void opj_v4dwt_decode_step1_sse(opj_v4_t* w, OPJ_INT32 count, const __m128 c); +static void opj_v4dwt_decode_step1_sse(opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + const __m128 c); -static void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_INT32 m, __m128 c); +static void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + OPJ_UINT32 m, __m128 c); #else -static void opj_v4dwt_decode_step1(opj_v4_t* w, OPJ_INT32 count, const OPJ_FLOAT32 c); +static void opj_v4dwt_decode_step1(opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + const OPJ_FLOAT32 c); -static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c); +static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + OPJ_UINT32 m, + OPJ_FLOAT32 c); #endif @@ -172,333 +223,1033 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_IN /* <summary> */ /* This table contains the norms of the 5-3 wavelets for different bands. */ /* </summary> */ +/* FIXME! the array should really be extended up to 33 resolution levels */ +/* See https://github.com/uclouvain/openjpeg/issues/493 */ static const OPJ_FLOAT64 opj_dwt_norms[4][10] = { - {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, - {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, - {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, - {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93} + {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93} }; /* <summary> */ /* This table contains the norms of the 9-7 wavelets for different bands. */ /* </summary> */ +/* FIXME! the array should really be extended up to 33 resolution levels */ +/* See https://github.com/uclouvain/openjpeg/issues/493 */ static const OPJ_FLOAT64 opj_dwt_norms_real[4][10] = { - {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9}, - {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, - {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, - {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2} + {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2} }; -/* +/* ========================================================== local functions ========================================================== */ -/* <summary> */ +/* <summary> */ /* Forward lazy transform (horizontal). */ -/* </summary> */ -static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - OPJ_INT32 * l_dest = b; - OPJ_INT32 * l_src = a+cas; - - for (i=0; i<sn; ++i) { - *l_dest++ = *l_src; - l_src += 2; - } - +/* </summary> */ +static void opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas) +{ + OPJ_INT32 i; + OPJ_INT32 * l_dest = b; + OPJ_INT32 * l_src = a + cas; + + for (i = 0; i < sn; ++i) { + *l_dest++ = *l_src; + l_src += 2; + } + l_dest = b + sn; - l_src = a + 1 - cas; + l_src = a + 1 - cas; - for (i=0; i<dn; ++i) { - *l_dest++=*l_src; - l_src += 2; - } + for (i = 0; i < dn; ++i) { + *l_dest++ = *l_src; + l_src += 2; + } } -/* <summary> */ +/* <summary> */ /* Forward lazy transform (vertical). */ -/* </summary> */ -static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas) { +/* </summary> */ +static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas) +{ OPJ_INT32 i = sn; - OPJ_INT32 * l_dest = b; - OPJ_INT32 * l_src = a+cas; + OPJ_INT32 * l_dest = b; + OPJ_INT32 * l_src = a + cas; while (i--) { - *l_dest = *l_src; - l_dest += x; - l_src += 2; - } /* b[i*x]=a[2*i+cas]; */ - - l_dest = b + sn * x; - l_src = a + 1 - cas; - - i = dn; + *l_dest = *l_src; + l_dest += x; + l_src += 2; + } /* b[i*x]=a[2*i+cas]; */ + + l_dest = b + (OPJ_SIZE_T)sn * (OPJ_SIZE_T)x; + l_src = a + 1 - cas; + + i = dn; while (i--) { - *l_dest = *l_src; - l_dest += x; - l_src += 2; - } /*b[(sn+i)*x]=a[(2*i+1-cas)];*/ + *l_dest = *l_src; + l_dest += x; + l_src += 2; + } /*b[(sn+i)*x]=a[(2*i+1-cas)];*/ } +#ifdef STANDARD_SLOW_VERSION /* <summary> */ /* Inverse lazy transform (horizontal). */ /* </summary> */ -static void opj_dwt_interleave_h(opj_dwt_t* h, OPJ_INT32 *a) { +static void opj_dwt_interleave_h(const opj_dwt_t* h, OPJ_INT32 *a) +{ OPJ_INT32 *ai = a; OPJ_INT32 *bi = h->mem + h->cas; - OPJ_INT32 i = h->sn; - while( i-- ) { - *bi = *(ai++); - bi += 2; + OPJ_INT32 i = h->sn; + while (i--) { + *bi = *(ai++); + bi += 2; } - ai = a + h->sn; - bi = h->mem + 1 - h->cas; - i = h->dn ; - while( i-- ) { - *bi = *(ai++); - bi += 2; + ai = a + h->sn; + bi = h->mem + 1 - h->cas; + i = h->dn ; + while (i--) { + *bi = *(ai++); + bi += 2; } } -/* <summary> */ +/* <summary> */ /* Inverse lazy transform (vertical). */ -/* </summary> */ -static void opj_dwt_interleave_v(opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) { +/* </summary> */ +static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) +{ OPJ_INT32 *ai = a; OPJ_INT32 *bi = v->mem + v->cas; OPJ_INT32 i = v->sn; - while( i-- ) { - *bi = *ai; - bi += 2; - ai += x; + while (i--) { + *bi = *ai; + bi += 2; + ai += x; } - ai = a + (v->sn * x); + ai = a + (v->sn * (OPJ_SIZE_T)x); bi = v->mem + 1 - v->cas; i = v->dn ; - while( i-- ) { - *bi = *ai; - bi += 2; - ai += x; + while (i--) { + *bi = *ai; + bi += 2; + ai += x; } } +#endif /* STANDARD_SLOW_VERSION */ /* <summary> */ /* Forward 5-3 wavelet transform in 1-D. */ /* </summary> */ -static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - - if (!cas) { - if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ - for (i = 0; i < dn; i++) OPJ_D(i) -= (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; - for (i = 0; i < sn; i++) OPJ_S(i) += (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; - } - } else { - if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ - OPJ_S(0) *= 2; - else { - for (i = 0; i < dn; i++) OPJ_S(i) -= (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1; - for (i = 0; i < sn; i++) OPJ_D(i) += (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2; - } - } +static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas) +{ + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) { + OPJ_D(i) -= (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + for (i = 0; i < sn; i++) { + OPJ_S(i) += (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + OPJ_S(0) *= 2; + } else { + for (i = 0; i < dn; i++) { + OPJ_S(i) -= (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1; + } + for (i = 0; i < sn; i++) { + OPJ_D(i) += (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2; + } + } + } } +#ifdef STANDARD_SLOW_VERSION /* <summary> */ /* Inverse 5-3 wavelet transform in 1-D. */ -/* </summary> */ -static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - - if (!cas) { - if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ - for (i = 0; i < sn; i++) OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; - for (i = 0; i < dn; i++) OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; - } - } else { - if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ - OPJ_S(0) /= 2; - else { - for (i = 0; i < sn; i++) OPJ_D(i) -= (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2; - for (i = 0; i < dn; i++) OPJ_S(i) += (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1; - } - } +/* </summary> */ +static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas) +{ + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < sn; i++) { + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + for (i = 0; i < dn; i++) { + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + OPJ_S(0) /= 2; + } else { + for (i = 0; i < sn; i++) { + OPJ_D(i) -= (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2; + } + for (i = 0; i < dn; i++) { + OPJ_S(i) += (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1; + } + } + } } -/* <summary> */ -/* Inverse 5-3 wavelet transform in 1-D. */ -/* </summary> */ -static void opj_dwt_decode_1(opj_dwt_t *v) { - opj_dwt_decode_1_(v->mem, v->mem_count, v->dn, v->sn, v->cas); +static void opj_dwt_decode_1(const opj_dwt_t *v) +{ + opj_dwt_decode_1_(v->mem, v->mem_count, v->dn, v->sn, v->cas); } -/* <summary> */ -/* Forward 9-7 wavelet transform in 1-D. */ -/* </summary> */ -static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - if (!cas) { - if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ - for (i = 0; i < dn; i++) - OPJ_D(i) -= opj_int_fix_mul(OPJ_S_(i) + OPJ_S_(i + 1), 12993); - for (i = 0; i < sn; i++) - OPJ_S(i) -= opj_int_fix_mul(OPJ_D_(i - 1) + OPJ_D_(i), 434); - for (i = 0; i < dn; i++) - OPJ_D(i) += opj_int_fix_mul(OPJ_S_(i) + OPJ_S_(i + 1), 7233); - for (i = 0; i < sn; i++) - OPJ_S(i) += opj_int_fix_mul(OPJ_D_(i - 1) + OPJ_D_(i), 3633); - for (i = 0; i < dn; i++) - OPJ_D(i) = opj_int_fix_mul(OPJ_D(i), 5038); /*5038 */ - for (i = 0; i < sn; i++) - OPJ_S(i) = opj_int_fix_mul(OPJ_S(i), 6659); /*6660 */ - } - } else { - if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */ - for (i = 0; i < dn; i++) - OPJ_S(i) -= opj_int_fix_mul(OPJ_DD_(i) + OPJ_DD_(i - 1), 12993); - for (i = 0; i < sn; i++) - OPJ_D(i) -= opj_int_fix_mul(OPJ_SS_(i) + OPJ_SS_(i + 1), 434); - for (i = 0; i < dn; i++) - OPJ_S(i) += opj_int_fix_mul(OPJ_DD_(i) + OPJ_DD_(i - 1), 7233); - for (i = 0; i < sn; i++) - OPJ_D(i) += opj_int_fix_mul(OPJ_SS_(i) + OPJ_SS_(i + 1), 3633); - for (i = 0; i < dn; i++) - OPJ_S(i) = opj_int_fix_mul(OPJ_S(i), 5038); /*5038 */ - for (i = 0; i < sn; i++) - OPJ_D(i) = opj_int_fix_mul(OPJ_D(i), 6659); /*6660 */ - } - } -} - -static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize) { - OPJ_INT32 p, n; - p = opj_int_floorlog2(stepsize) - 13; - n = 11 - opj_int_floorlog2(stepsize); - bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff; - bandno_stepsize->expn = numbps - p; -} - -/* -========================================================== - DWT interface -========================================================== -*/ +#endif /* STANDARD_SLOW_VERSION */ + +#if !defined(STANDARD_SLOW_VERSION) +static void opj_idwt53_h_cas0(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp) +{ + OPJ_INT32 i, j; + const OPJ_INT32* in_even = &tiledp[0]; + const OPJ_INT32* in_odd = &tiledp[sn]; + +#ifdef TWO_PASS_VERSION + /* For documentation purpose: performs lifting in two iterations, */ + /* but without explicit interleaving */ + + assert(len > 1); + + /* Even */ + tmp[0] = in_even[0] - ((in_odd[0] + 1) >> 1); + for (i = 2, j = 0; i <= len - 2; i += 2, j++) { + tmp[i] = in_even[j + 1] - ((in_odd[j] + in_odd[j + 1] + 2) >> 2); + } + if (len & 1) { /* if len is odd */ + tmp[len - 1] = in_even[(len - 1) / 2] - ((in_odd[(len - 2) / 2] + 1) >> 1); + } + + /* Odd */ + for (i = 1, j = 0; i < len - 1; i += 2, j++) { + tmp[i] = in_odd[j] + ((tmp[i - 1] + tmp[i + 1]) >> 1); + } + if (!(len & 1)) { /* if len is even */ + tmp[len - 1] = in_odd[(len - 1) / 2] + tmp[len - 2]; + } +#else + OPJ_INT32 d1c, d1n, s1n, s0c, s0n; + + assert(len > 1); + + /* Improved version of the TWO_PASS_VERSION: */ + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ + s1n = in_even[0]; + d1n = in_odd[0]; + s0n = s1n - ((d1n + 1) >> 1); + + for (i = 0, j = 1; i < (len - 3); i += 2, j++) { + d1c = d1n; + s0c = s0n; + + s1n = in_even[j]; + d1n = in_odd[j]; + + s0n = s1n - ((d1c + d1n + 2) >> 2); + + tmp[i ] = s0c; + tmp[i + 1] = d1c + ((s0c + s0n) >> 1); + } + + tmp[i] = s0n; + + if (len & 1) { + tmp[len - 1] = in_even[(len - 1) / 2] - ((d1n + 1) >> 1); + tmp[len - 2] = d1n + ((s0n + tmp[len - 1]) >> 1); + } else { + tmp[len - 1] = d1n + s0n; + } +#endif + memcpy(tiledp, tmp, (OPJ_UINT32)len * sizeof(OPJ_INT32)); +} + +static void opj_idwt53_h_cas1(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp) +{ + OPJ_INT32 i, j; + const OPJ_INT32* in_even = &tiledp[sn]; + const OPJ_INT32* in_odd = &tiledp[0]; + +#ifdef TWO_PASS_VERSION + /* For documentation purpose: performs lifting in two iterations, */ + /* but without explicit interleaving */ + + assert(len > 2); + + /* Odd */ + for (i = 1, j = 0; i < len - 1; i += 2, j++) { + tmp[i] = in_odd[j] - ((in_even[j] + in_even[j + 1] + 2) >> 2); + } + if (!(len & 1)) { + tmp[len - 1] = in_odd[len / 2 - 1] - ((in_even[len / 2 - 1] + 1) >> 1); + } + + /* Even */ + tmp[0] = in_even[0] + tmp[1]; + for (i = 2, j = 1; i < len - 1; i += 2, j++) { + tmp[i] = in_even[j] + ((tmp[i + 1] + tmp[i - 1]) >> 1); + } + if (len & 1) { + tmp[len - 1] = in_even[len / 2] + tmp[len - 2]; + } +#else + OPJ_INT32 s1, s2, dc, dn; + + assert(len > 2); + + /* Improved version of the TWO_PASS_VERSION: */ + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ + + s1 = in_even[1]; + dc = in_odd[0] - ((in_even[0] + s1 + 2) >> 2); + tmp[0] = in_even[0] + dc; + + for (i = 1, j = 1; i < (len - 2 - !(len & 1)); i += 2, j++) { + + s2 = in_even[j + 1]; + dn = in_odd[j] - ((s1 + s2 + 2) >> 2); + tmp[i ] = dc; + tmp[i + 1] = s1 + ((dn + dc) >> 1); + + dc = dn; + s1 = s2; + } + + tmp[i] = dc; + + if (!(len & 1)) { + dn = in_odd[len / 2 - 1] - ((s1 + 1) >> 1); + tmp[len - 2] = s1 + ((dn + dc) >> 1); + tmp[len - 1] = dn; + } else { + tmp[len - 1] = s1 + dc; + } +#endif + memcpy(tiledp, tmp, (OPJ_UINT32)len * sizeof(OPJ_INT32)); +} + + +#endif /* !defined(STANDARD_SLOW_VERSION) */ /* <summary> */ -/* Forward 5-3 wavelet transform in 2-D. */ +/* Inverse 5-3 wavelet transform in 1-D for one row. */ /* </summary> */ -static INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)) +/* Performs interleave, inverse wavelet transform and copy back to buffer */ +static void opj_idwt53_h(const opj_dwt_t *dwt, + OPJ_INT32* tiledp) +{ +#ifdef STANDARD_SLOW_VERSION + /* For documentation purpose */ + opj_dwt_interleave_h(dwt, tiledp); + opj_dwt_decode_1(dwt); + memcpy(tiledp, dwt->mem, (OPJ_UINT32)(dwt->sn + dwt->dn) * sizeof(OPJ_INT32)); +#else + const OPJ_INT32 sn = dwt->sn; + const OPJ_INT32 len = sn + dwt->dn; + if (dwt->cas == 0) { /* Left-most sample is on even coordinate */ + if (len > 1) { + opj_idwt53_h_cas0(dwt->mem, sn, len, tiledp); + } else { + /* Unmodified value */ + } + } else { /* Left-most sample is on odd coordinate */ + if (len == 1) { + tiledp[0] /= 2; + } else if (len == 2) { + OPJ_INT32* out = dwt->mem; + const OPJ_INT32* in_even = &tiledp[sn]; + const OPJ_INT32* in_odd = &tiledp[0]; + out[1] = in_odd[0] - ((in_even[0] + 1) >> 1); + out[0] = in_even[0] + out[1]; + memcpy(tiledp, dwt->mem, (OPJ_UINT32)len * sizeof(OPJ_INT32)); + } else if (len > 2) { + opj_idwt53_h_cas1(dwt->mem, sn, len, tiledp); + } + } +#endif +} + +#if (defined(__SSE2__) || defined(__AVX2__)) && !defined(STANDARD_SLOW_VERSION) + +/* Conveniency macros to improve the readabilty of the formulas */ +#if __AVX2__ +#define VREG __m256i +#define LOAD_CST(x) _mm256_set1_epi32(x) +#define LOAD(x) _mm256_load_si256((const VREG*)(x)) +#define LOADU(x) _mm256_loadu_si256((const VREG*)(x)) +#define STORE(x,y) _mm256_store_si256((VREG*)(x),(y)) +#define STOREU(x,y) _mm256_storeu_si256((VREG*)(x),(y)) +#define ADD(x,y) _mm256_add_epi32((x),(y)) +#define SUB(x,y) _mm256_sub_epi32((x),(y)) +#define SAR(x,y) _mm256_srai_epi32((x),(y)) +#else +#define VREG __m128i +#define LOAD_CST(x) _mm_set1_epi32(x) +#define LOAD(x) _mm_load_si128((const VREG*)(x)) +#define LOADU(x) _mm_loadu_si128((const VREG*)(x)) +#define STORE(x,y) _mm_store_si128((VREG*)(x),(y)) +#define STOREU(x,y) _mm_storeu_si128((VREG*)(x),(y)) +#define ADD(x,y) _mm_add_epi32((x),(y)) +#define SUB(x,y) _mm_sub_epi32((x),(y)) +#define SAR(x,y) _mm_srai_epi32((x),(y)) +#endif +#define ADD3(x,y,z) ADD(ADD(x,y),z) + +static +void opj_idwt53_v_final_memcpy(OPJ_INT32* tiledp_col, + const OPJ_INT32* tmp, + OPJ_INT32 len, + OPJ_SIZE_T stride) +{ + OPJ_INT32 i; + for (i = 0; i < len; ++i) { + /* A memcpy(&tiledp_col[i * stride + 0], + &tmp[PARALLEL_COLS_53 * i + 0], + PARALLEL_COLS_53 * sizeof(OPJ_INT32)) + would do but would be a tiny bit slower. + We can take here advantage of our knowledge of alignment */ + STOREU(&tiledp_col[(OPJ_SIZE_T)i * stride + 0], + LOAD(&tmp[PARALLEL_COLS_53 * i + 0])); + STOREU(&tiledp_col[(OPJ_SIZE_T)i * stride + VREG_INT_COUNT], + LOAD(&tmp[PARALLEL_COLS_53 * i + VREG_INT_COUNT])); + } +} + +/** Vertical inverse 5x3 wavelet transform for 8 columns in SSE2, or + * 16 in AVX2, when top-most pixel is on even coordinate */ +static void opj_idwt53_v_cas0_mcols_SSE2_OR_AVX2( + OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + const OPJ_INT32* in_even = &tiledp_col[0]; + const OPJ_INT32* in_odd = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + + OPJ_INT32 i; + OPJ_SIZE_T j; + VREG d1c_0, d1n_0, s1n_0, s0c_0, s0n_0; + VREG d1c_1, d1n_1, s1n_1, s0c_1, s0n_1; + const VREG two = LOAD_CST(2); + + assert(len > 1); +#if __AVX2__ + assert(PARALLEL_COLS_53 == 16); + assert(VREG_INT_COUNT == 8); +#else + assert(PARALLEL_COLS_53 == 8); + assert(VREG_INT_COUNT == 4); +#endif + + /* Note: loads of input even/odd values must be done in a unaligned */ + /* fashion. But stores in tmp can be done with aligned store, since */ + /* the temporary buffer is properly aligned */ + assert((OPJ_SIZE_T)tmp % (sizeof(OPJ_INT32) * VREG_INT_COUNT) == 0); + + s1n_0 = LOADU(in_even + 0); + s1n_1 = LOADU(in_even + VREG_INT_COUNT); + d1n_0 = LOADU(in_odd); + d1n_1 = LOADU(in_odd + VREG_INT_COUNT); + + /* s0n = s1n - ((d1n + 1) >> 1); <==> */ + /* s0n = s1n - ((d1n + d1n + 2) >> 2); */ + s0n_0 = SUB(s1n_0, SAR(ADD3(d1n_0, d1n_0, two), 2)); + s0n_1 = SUB(s1n_1, SAR(ADD3(d1n_1, d1n_1, two), 2)); + + for (i = 0, j = 1; i < (len - 3); i += 2, j++) { + d1c_0 = d1n_0; + s0c_0 = s0n_0; + d1c_1 = d1n_1; + s0c_1 = s0n_1; + + s1n_0 = LOADU(in_even + j * stride); + s1n_1 = LOADU(in_even + j * stride + VREG_INT_COUNT); + d1n_0 = LOADU(in_odd + j * stride); + d1n_1 = LOADU(in_odd + j * stride + VREG_INT_COUNT); + + /*s0n = s1n - ((d1c + d1n + 2) >> 2);*/ + s0n_0 = SUB(s1n_0, SAR(ADD3(d1c_0, d1n_0, two), 2)); + s0n_1 = SUB(s1n_1, SAR(ADD3(d1c_1, d1n_1, two), 2)); + + STORE(tmp + PARALLEL_COLS_53 * (i + 0), s0c_0); + STORE(tmp + PARALLEL_COLS_53 * (i + 0) + VREG_INT_COUNT, s0c_1); + + /* d1c + ((s0c + s0n) >> 1) */ + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + 0, + ADD(d1c_0, SAR(ADD(s0c_0, s0n_0), 1))); + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + VREG_INT_COUNT, + ADD(d1c_1, SAR(ADD(s0c_1, s0n_1), 1))); + } + + STORE(tmp + PARALLEL_COLS_53 * (i + 0) + 0, s0n_0); + STORE(tmp + PARALLEL_COLS_53 * (i + 0) + VREG_INT_COUNT, s0n_1); + + if (len & 1) { + VREG tmp_len_minus_1; + s1n_0 = LOADU(in_even + (OPJ_SIZE_T)((len - 1) / 2) * stride); + /* tmp_len_minus_1 = s1n - ((d1n + 1) >> 1); */ + tmp_len_minus_1 = SUB(s1n_0, SAR(ADD3(d1n_0, d1n_0, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1), tmp_len_minus_1); + /* d1n + ((s0n + tmp_len_minus_1) >> 1) */ + STORE(tmp + PARALLEL_COLS_53 * (len - 2), + ADD(d1n_0, SAR(ADD(s0n_0, tmp_len_minus_1), 1))); + + s1n_1 = LOADU(in_even + (OPJ_SIZE_T)((len - 1) / 2) * stride + VREG_INT_COUNT); + /* tmp_len_minus_1 = s1n - ((d1n + 1) >> 1); */ + tmp_len_minus_1 = SUB(s1n_1, SAR(ADD3(d1n_1, d1n_1, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, + tmp_len_minus_1); + /* d1n + ((s0n + tmp_len_minus_1) >> 1) */ + STORE(tmp + PARALLEL_COLS_53 * (len - 2) + VREG_INT_COUNT, + ADD(d1n_1, SAR(ADD(s0n_1, tmp_len_minus_1), 1))); + + + } else { + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + 0, + ADD(d1n_0, s0n_0)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, + ADD(d1n_1, s0n_1)); + } + + opj_idwt53_v_final_memcpy(tiledp_col, tmp, len, stride); +} + + +/** Vertical inverse 5x3 wavelet transform for 8 columns in SSE2, or + * 16 in AVX2, when top-most pixel is on odd coordinate */ +static void opj_idwt53_v_cas1_mcols_SSE2_OR_AVX2( + OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + OPJ_INT32 i; + OPJ_SIZE_T j; + + VREG s1_0, s2_0, dc_0, dn_0; + VREG s1_1, s2_1, dc_1, dn_1; + const VREG two = LOAD_CST(2); + + const OPJ_INT32* in_even = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + const OPJ_INT32* in_odd = &tiledp_col[0]; + + assert(len > 2); +#if __AVX2__ + assert(PARALLEL_COLS_53 == 16); + assert(VREG_INT_COUNT == 8); +#else + assert(PARALLEL_COLS_53 == 8); + assert(VREG_INT_COUNT == 4); +#endif + + /* Note: loads of input even/odd values must be done in a unaligned */ + /* fashion. But stores in tmp can be done with aligned store, since */ + /* the temporary buffer is properly aligned */ + assert((OPJ_SIZE_T)tmp % (sizeof(OPJ_INT32) * VREG_INT_COUNT) == 0); + + s1_0 = LOADU(in_even + stride); + /* in_odd[0] - ((in_even[0] + s1 + 2) >> 2); */ + dc_0 = SUB(LOADU(in_odd + 0), + SAR(ADD3(LOADU(in_even + 0), s1_0, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * 0, ADD(LOADU(in_even + 0), dc_0)); + + s1_1 = LOADU(in_even + stride + VREG_INT_COUNT); + /* in_odd[0] - ((in_even[0] + s1 + 2) >> 2); */ + dc_1 = SUB(LOADU(in_odd + VREG_INT_COUNT), + SAR(ADD3(LOADU(in_even + VREG_INT_COUNT), s1_1, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * 0 + VREG_INT_COUNT, + ADD(LOADU(in_even + VREG_INT_COUNT), dc_1)); + + for (i = 1, j = 1; i < (len - 2 - !(len & 1)); i += 2, j++) { + + s2_0 = LOADU(in_even + (j + 1) * stride); + s2_1 = LOADU(in_even + (j + 1) * stride + VREG_INT_COUNT); + + /* dn = in_odd[j * stride] - ((s1 + s2 + 2) >> 2); */ + dn_0 = SUB(LOADU(in_odd + j * stride), + SAR(ADD3(s1_0, s2_0, two), 2)); + dn_1 = SUB(LOADU(in_odd + j * stride + VREG_INT_COUNT), + SAR(ADD3(s1_1, s2_1, two), 2)); + + STORE(tmp + PARALLEL_COLS_53 * i, dc_0); + STORE(tmp + PARALLEL_COLS_53 * i + VREG_INT_COUNT, dc_1); + + /* tmp[i + 1] = s1 + ((dn + dc) >> 1); */ + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + 0, + ADD(s1_0, SAR(ADD(dn_0, dc_0), 1))); + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + VREG_INT_COUNT, + ADD(s1_1, SAR(ADD(dn_1, dc_1), 1))); + + dc_0 = dn_0; + s1_0 = s2_0; + dc_1 = dn_1; + s1_1 = s2_1; + } + STORE(tmp + PARALLEL_COLS_53 * i, dc_0); + STORE(tmp + PARALLEL_COLS_53 * i + VREG_INT_COUNT, dc_1); + + if (!(len & 1)) { + /*dn = in_odd[(len / 2 - 1) * stride] - ((s1 + 1) >> 1); */ + dn_0 = SUB(LOADU(in_odd + (OPJ_SIZE_T)(len / 2 - 1) * stride), + SAR(ADD3(s1_0, s1_0, two), 2)); + dn_1 = SUB(LOADU(in_odd + (OPJ_SIZE_T)(len / 2 - 1) * stride + VREG_INT_COUNT), + SAR(ADD3(s1_1, s1_1, two), 2)); + + /* tmp[len - 2] = s1 + ((dn + dc) >> 1); */ + STORE(tmp + PARALLEL_COLS_53 * (len - 2) + 0, + ADD(s1_0, SAR(ADD(dn_0, dc_0), 1))); + STORE(tmp + PARALLEL_COLS_53 * (len - 2) + VREG_INT_COUNT, + ADD(s1_1, SAR(ADD(dn_1, dc_1), 1))); + + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + 0, dn_0); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, dn_1); + } else { + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + 0, ADD(s1_0, dc_0)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, + ADD(s1_1, dc_1)); + } + + opj_idwt53_v_final_memcpy(tiledp_col, tmp, len, stride); +} + +#undef VREG +#undef LOAD_CST +#undef LOADU +#undef LOAD +#undef STORE +#undef STOREU +#undef ADD +#undef ADD3 +#undef SUB +#undef SAR + +#endif /* (defined(__SSE2__) || defined(__AVX2__)) && !defined(STANDARD_SLOW_VERSION) */ + +#if !defined(STANDARD_SLOW_VERSION) +/** Vertical inverse 5x3 wavelet transform for one column, when top-most + * pixel is on even coordinate */ +static void opj_idwt3_v_cas0(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) { - OPJ_INT32 i, j, k; - OPJ_INT32 *a = 00; - OPJ_INT32 *aj = 00; - OPJ_INT32 *bj = 00; - OPJ_INT32 w, l; + OPJ_INT32 i, j; + OPJ_INT32 d1c, d1n, s1n, s0c, s0n; - OPJ_INT32 rw; /* width of the resolution level computed */ - OPJ_INT32 rh; /* height of the resolution level computed */ - OPJ_SIZE_T l_data_count; - OPJ_SIZE_T l_data_size; + assert(len > 1); - opj_tcd_resolution_t * l_cur_res = 0; - opj_tcd_resolution_t * l_last_res = 0; + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ - w = tilec->x1-tilec->x0; - l = (OPJ_INT32)tilec->numresolutions-1; - a = tilec->data; + s1n = tiledp_col[0]; + d1n = tiledp_col[(OPJ_SIZE_T)sn * stride]; + s0n = s1n - ((d1n + 1) >> 1); - l_cur_res = tilec->resolutions + l; - l_last_res = l_cur_res - 1; + for (i = 0, j = 0; i < (len - 3); i += 2, j++) { + d1c = d1n; + s0c = s0n; - l_data_count = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions) * (OPJ_UINT32)sizeof(OPJ_INT32); - l_data_size = l_data_count * (OPJ_UINT32)sizeof(OPJ_INT32); - bj = (OPJ_INT32*)opj_malloc(l_data_size); - if (! bj) { - return OPJ_FALSE; - } - i = l; + s1n = tiledp_col[(OPJ_SIZE_T)(j + 1) * stride]; + d1n = tiledp_col[(OPJ_SIZE_T)(sn + j + 1) * stride]; - while (i--) { - OPJ_INT32 rw1; /* width of the resolution level once lower than computed one */ - OPJ_INT32 rh1; /* height of the resolution level once lower than computed one */ - OPJ_INT32 cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ - OPJ_INT32 cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ - OPJ_INT32 dn, sn; + s0n = s1n - ((d1c + d1n + 2) >> 2); - rw = l_cur_res->x1 - l_cur_res->x0; - rh = l_cur_res->y1 - l_cur_res->y0; - rw1 = l_last_res->x1 - l_last_res->x0; - rh1 = l_last_res->y1 - l_last_res->y0; + tmp[i ] = s0c; + tmp[i + 1] = d1c + ((s0c + s0n) >> 1); + } - cas_row = l_cur_res->x0 & 1; - cas_col = l_cur_res->y0 & 1; + tmp[i] = s0n; - sn = rh1; - dn = rh - rh1; - for (j = 0; j < rw; ++j) { - aj = a + j; - for (k = 0; k < rh; ++k) { - bj[k] = aj[k*w]; - } + if (len & 1) { + tmp[len - 1] = + tiledp_col[(OPJ_SIZE_T)((len - 1) / 2) * stride] - + ((d1n + 1) >> 1); + tmp[len - 2] = d1n + ((s0n + tmp[len - 1]) >> 1); + } else { + tmp[len - 1] = d1n + s0n; + } - (*p_function) (bj, l_data_count, dn, sn, cas_col); + for (i = 0; i < len; ++i) { + tiledp_col[(OPJ_SIZE_T)i * stride] = tmp[i]; + } +} - opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); - } - sn = rw1; - dn = rw - rw1; +/** Vertical inverse 5x3 wavelet transform for one column, when top-most + * pixel is on odd coordinate */ +static void opj_idwt3_v_cas1(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + OPJ_INT32 i, j; + OPJ_INT32 s1, s2, dc, dn; + const OPJ_INT32* in_even = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + const OPJ_INT32* in_odd = &tiledp_col[0]; - for (j = 0; j < rh; j++) { - aj = a + j * w; - for (k = 0; k < rw; k++) bj[k] = aj[k]; - (*p_function) (bj, l_data_count, dn, sn, cas_row); - opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row); - } + assert(len > 2); - l_cur_res = l_last_res; + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ - --l_last_res; - } + s1 = in_even[stride]; + dc = in_odd[0] - ((in_even[0] + s1 + 2) >> 2); + tmp[0] = in_even[0] + dc; + for (i = 1, j = 1; i < (len - 2 - !(len & 1)); i += 2, j++) { - opj_free(bj); - return OPJ_TRUE; + s2 = in_even[(OPJ_SIZE_T)(j + 1) * stride]; + + dn = in_odd[(OPJ_SIZE_T)j * stride] - ((s1 + s2 + 2) >> 2); + tmp[i ] = dc; + tmp[i + 1] = s1 + ((dn + dc) >> 1); + + dc = dn; + s1 = s2; + } + tmp[i] = dc; + if (!(len & 1)) { + dn = in_odd[(OPJ_SIZE_T)(len / 2 - 1) * stride] - ((s1 + 1) >> 1); + tmp[len - 2] = s1 + ((dn + dc) >> 1); + tmp[len - 1] = dn; + } else { + tmp[len - 1] = s1 + dc; + } + + for (i = 0; i < len; ++i) { + tiledp_col[(OPJ_SIZE_T)i * stride] = tmp[i]; + } +} +#endif /* !defined(STANDARD_SLOW_VERSION) */ + +/* <summary> */ +/* Inverse vertical 5-3 wavelet transform in 1-D for several columns. */ +/* </summary> */ +/* Performs interleave, inverse wavelet transform and copy back to buffer */ +static void opj_idwt53_v(const opj_dwt_t *dwt, + OPJ_INT32* tiledp_col, + OPJ_SIZE_T stride, + OPJ_INT32 nb_cols) +{ +#ifdef STANDARD_SLOW_VERSION + /* For documentation purpose */ + OPJ_INT32 k, c; + for (c = 0; c < nb_cols; c ++) { + opj_dwt_interleave_v(dwt, tiledp_col + c, stride); + opj_dwt_decode_1(dwt); + for (k = 0; k < dwt->sn + dwt->dn; ++k) { + tiledp_col[c + k * stride] = dwt->mem[k]; + } + } +#else + const OPJ_INT32 sn = dwt->sn; + const OPJ_INT32 len = sn + dwt->dn; + if (dwt->cas == 0) { + /* If len == 1, unmodified value */ + +#if (defined(__SSE2__) || defined(__AVX2__)) + if (len > 1 && nb_cols == PARALLEL_COLS_53) { + /* Same as below general case, except that thanks to SSE2/AVX2 */ + /* we can efficently process 8/16 columns in parallel */ + opj_idwt53_v_cas0_mcols_SSE2_OR_AVX2(dwt->mem, sn, len, tiledp_col, stride); + return; + } +#endif + if (len > 1) { + OPJ_INT32 c; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + opj_idwt3_v_cas0(dwt->mem, sn, len, tiledp_col, stride); + } + return; + } + } else { + if (len == 1) { + OPJ_INT32 c; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + tiledp_col[0] /= 2; + } + return; + } + + if (len == 2) { + OPJ_INT32 c; + OPJ_INT32* out = dwt->mem; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + OPJ_INT32 i; + const OPJ_INT32* in_even = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + const OPJ_INT32* in_odd = &tiledp_col[0]; + + out[1] = in_odd[0] - ((in_even[0] + 1) >> 1); + out[0] = in_even[0] + out[1]; + + for (i = 0; i < len; ++i) { + tiledp_col[(OPJ_SIZE_T)i * stride] = out[i]; + } + } + + return; + } + +#if (defined(__SSE2__) || defined(__AVX2__)) + if (len > 2 && nb_cols == PARALLEL_COLS_53) { + /* Same as below general case, except that thanks to SSE2/AVX2 */ + /* we can efficently process 8/16 columns in parallel */ + opj_idwt53_v_cas1_mcols_SSE2_OR_AVX2(dwt->mem, sn, len, tiledp_col, stride); + return; + } +#endif + if (len > 2) { + OPJ_INT32 c; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + opj_idwt3_v_cas1(dwt->mem, sn, len, tiledp_col, stride); + } + return; + } + } +#endif +} + + +/* <summary> */ +/* Forward 9-7 wavelet transform in 1-D. */ +/* </summary> */ +static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count, + OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) +{ + OPJ_INT32 i; + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) { + OPJ_D(i) -= opj_int_fix_mul(OPJ_S_(i) + OPJ_S_(i + 1), 12993); + } + for (i = 0; i < sn; i++) { + OPJ_S(i) -= opj_int_fix_mul(OPJ_D_(i - 1) + OPJ_D_(i), 434); + } + for (i = 0; i < dn; i++) { + OPJ_D(i) += opj_int_fix_mul(OPJ_S_(i) + OPJ_S_(i + 1), 7233); + } + for (i = 0; i < sn; i++) { + OPJ_S(i) += opj_int_fix_mul(OPJ_D_(i - 1) + OPJ_D_(i), 3633); + } + for (i = 0; i < dn; i++) { + OPJ_D(i) = opj_int_fix_mul(OPJ_D(i), 5038); /*5038 */ + } + for (i = 0; i < sn; i++) { + OPJ_S(i) = opj_int_fix_mul(OPJ_S(i), 6659); /*6660 */ + } + } + } else { + if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) { + OPJ_S(i) -= opj_int_fix_mul(OPJ_DD_(i) + OPJ_DD_(i - 1), 12993); + } + for (i = 0; i < sn; i++) { + OPJ_D(i) -= opj_int_fix_mul(OPJ_SS_(i) + OPJ_SS_(i + 1), 434); + } + for (i = 0; i < dn; i++) { + OPJ_S(i) += opj_int_fix_mul(OPJ_DD_(i) + OPJ_DD_(i - 1), 7233); + } + for (i = 0; i < sn; i++) { + OPJ_D(i) += opj_int_fix_mul(OPJ_SS_(i) + OPJ_SS_(i + 1), 3633); + } + for (i = 0; i < dn; i++) { + OPJ_S(i) = opj_int_fix_mul(OPJ_S(i), 5038); /*5038 */ + } + for (i = 0; i < sn; i++) { + OPJ_D(i) = opj_int_fix_mul(OPJ_D(i), 6659); /*6660 */ + } + } + } +} + +static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, + opj_stepsize_t *bandno_stepsize) +{ + OPJ_INT32 p, n; + p = opj_int_floorlog2(stepsize) - 13; + n = 11 - opj_int_floorlog2(stepsize); + bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff; + bandno_stepsize->expn = numbps - p; +} + +/* +========================================================== + DWT interface +========================================================== +*/ + + +/* <summary> */ +/* Forward 5-3 wavelet transform in 2-D. */ +/* </summary> */ +static INLINE OPJ_BOOL opj_dwt_encode_procedure(const opj_tcd_tilecomp_t * tilec, + void(*p_function)(OPJ_INT32 *, OPJ_SIZE_T, OPJ_INT32, OPJ_INT32, OPJ_INT32)) +{ + OPJ_INT32 i, j, k; + OPJ_INT32 *a = 00; + OPJ_INT32 *aj = 00; + OPJ_INT32 *bj = 00; + OPJ_INT32 w, l; + + OPJ_INT32 rw; /* width of the resolution level computed */ + OPJ_INT32 rh; /* height of the resolution level computed */ + OPJ_SIZE_T l_data_count; + OPJ_SIZE_T l_data_size; + + opj_tcd_resolution_t * l_cur_res = 0; + opj_tcd_resolution_t * l_last_res = 0; + + w = tilec->x1 - tilec->x0; + l = (OPJ_INT32)tilec->numresolutions - 1; + a = tilec->data; + + l_cur_res = tilec->resolutions + l; + l_last_res = l_cur_res - 1; + + l_data_count = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions); + /* overflow check */ + if (l_data_count > (SIZE_MAX / sizeof(OPJ_INT32))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + l_data_size = l_data_count * sizeof(OPJ_INT32); + bj = (OPJ_INT32*)opj_malloc(l_data_size); + /* l_data_size is equal to 0 when numresolutions == 1 but bj is not used */ + /* in that case, so do not error out */ + if (l_data_size != 0 && ! bj) { + return OPJ_FALSE; + } + i = l; + + while (i--) { + OPJ_INT32 rw1; /* width of the resolution level once lower than computed one */ + OPJ_INT32 rh1; /* height of the resolution level once lower than computed one */ + OPJ_INT32 cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + OPJ_INT32 cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + OPJ_INT32 dn, sn; + + rw = l_cur_res->x1 - l_cur_res->x0; + rh = l_cur_res->y1 - l_cur_res->y0; + rw1 = l_last_res->x1 - l_last_res->x0; + rh1 = l_last_res->y1 - l_last_res->y0; + + cas_row = l_cur_res->x0 & 1; + cas_col = l_cur_res->y0 & 1; + + sn = rh1; + dn = rh - rh1; + for (j = 0; j < rw; ++j) { + aj = a + j; + for (k = 0; k < rh; ++k) { + bj[k] = aj[k * w]; + } + + (*p_function) (bj, l_data_count, dn, sn, cas_col); + + opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } + + sn = rw1; + dn = rw - rw1; + + for (j = 0; j < rh; j++) { + aj = a + j * w; + for (k = 0; k < rw; k++) { + bj[k] = aj[k]; + } + (*p_function) (bj, l_data_count, dn, sn, cas_row); + opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + + l_cur_res = l_last_res; + + --l_last_res; + } + + opj_free(bj); + return OPJ_TRUE; } /* Forward 5-3 wavelet transform in 2-D. */ /* </summary> */ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec) { - return opj_dwt_encode_procedure(tilec,opj_dwt_encode_1); + return opj_dwt_encode_procedure(tilec, opj_dwt_encode_1); } /* <summary> */ /* Inverse 5-3 wavelet transform in 2-D. */ /* </summary> */ -OPJ_BOOL opj_dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) { - return opj_dwt_decode_tile(tilec, numres, &opj_dwt_decode_1); +OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd, opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres) +{ + if (p_tcd->whole_tile_decoding) { + return opj_dwt_decode_tile(p_tcd->thread_pool, tilec, numres); + } else { + return opj_dwt_decode_partial_tile(tilec, numres); + } } /* <summary> */ /* Get gain of 5-3 wavelet transform. */ /* </summary> */ -OPJ_UINT32 opj_dwt_getgain(OPJ_UINT32 orient) { - if (orient == 0) - return 0; - if (orient == 1 || orient == 2) - return 1; - return 2; +OPJ_UINT32 opj_dwt_getgain(OPJ_UINT32 orient) +{ + if (orient == 0) { + return 0; + } + if (orient == 1 || orient == 2) { + return 1; + } + return 2; } /* <summary> */ /* Get norm of 5-3 wavelet. */ /* </summary> */ -OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) { - return opj_dwt_norms[orient][level]; +OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) +{ + /* FIXME ! This is just a band-aid to avoid a buffer overflow */ + /* but the array should really be extended up to 33 resolution levels */ + /* See https://github.com/uclouvain/openjpeg/issues/493 */ + if (orient == 0 && level >= 10) { + level = 9; + } else if (orient > 0 && level >= 9) { + level = 8; + } + return opj_dwt_norms[orient][level]; } /* <summary> */ @@ -506,297 +1257,1194 @@ OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) { /* </summary> */ OPJ_BOOL opj_dwt_encode_real(opj_tcd_tilecomp_t * tilec) { - return opj_dwt_encode_procedure(tilec,opj_dwt_encode_1_real); + return opj_dwt_encode_procedure(tilec, opj_dwt_encode_1_real); } /* <summary> */ /* Get gain of 9-7 wavelet transform. */ /* </summary> */ -OPJ_UINT32 opj_dwt_getgain_real(OPJ_UINT32 orient) { - (void)orient; - return 0; +OPJ_UINT32 opj_dwt_getgain_real(OPJ_UINT32 orient) +{ + (void)orient; + return 0; } /* <summary> */ /* Get norm of 9-7 wavelet. */ /* </summary> */ -OPJ_FLOAT64 opj_dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient) { - return opj_dwt_norms_real[orient][level]; -} - -void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec) { - OPJ_UINT32 numbands, bandno; - numbands = 3 * tccp->numresolutions - 2; - for (bandno = 0; bandno < numbands; bandno++) { - OPJ_FLOAT64 stepsize; - OPJ_UINT32 resno, level, orient, gain; - - resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1); - orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1); - level = tccp->numresolutions - 1 - resno; - gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || (orient == 2)) ? 1 : 2)); - if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { - stepsize = 1.0; - } else { - OPJ_FLOAT64 norm = opj_dwt_norms_real[orient][level]; - stepsize = (1 << (gain)) / norm; - } - opj_dwt_encode_stepsize((OPJ_INT32) floor(stepsize * 8192.0), (OPJ_INT32)(prec + gain), &tccp->stepsizes[bandno]); - } +OPJ_FLOAT64 opj_dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient) +{ + /* FIXME ! This is just a band-aid to avoid a buffer overflow */ + /* but the array should really be extended up to 33 resolution levels */ + /* See https://github.com/uclouvain/openjpeg/issues/493 */ + if (orient == 0 && level >= 10) { + level = 9; + } else if (orient > 0 && level >= 9) { + level = 8; + } + return opj_dwt_norms_real[orient][level]; +} + +void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec) +{ + OPJ_UINT32 numbands, bandno; + numbands = 3 * tccp->numresolutions - 2; + for (bandno = 0; bandno < numbands; bandno++) { + OPJ_FLOAT64 stepsize; + OPJ_UINT32 resno, level, orient, gain; + + resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1); + orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1); + level = tccp->numresolutions - 1 - resno; + gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || + (orient == 2)) ? 1 : 2)); + if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + stepsize = 1.0; + } else { + OPJ_FLOAT64 norm = opj_dwt_norms_real[orient][level]; + stepsize = (1 << (gain)) / norm; + } + opj_dwt_encode_stepsize((OPJ_INT32) floor(stepsize * 8192.0), + (OPJ_INT32)(prec + gain), &tccp->stepsizes[bandno]); + } } /* <summary> */ /* Determine maximum computed resolution level for inverse wavelet transform */ /* </summary> */ -static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) { - OPJ_UINT32 mr = 0; - OPJ_UINT32 w; - while( --i ) { - ++r; - if( mr < ( w = (OPJ_UINT32)(r->x1 - r->x0) ) ) - mr = w ; - if( mr < ( w = (OPJ_UINT32)(r->y1 - r->y0) ) ) - mr = w ; - } - return mr ; +static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, + OPJ_UINT32 i) +{ + OPJ_UINT32 mr = 0; + OPJ_UINT32 w; + while (--i) { + ++r; + if (mr < (w = (OPJ_UINT32)(r->x1 - r->x0))) { + mr = w ; + } + if (mr < (w = (OPJ_UINT32)(r->y1 - r->y0))) { + mr = w ; + } + } + return mr ; +} + +typedef struct { + opj_dwt_t h; + OPJ_UINT32 rw; + OPJ_UINT32 w; + OPJ_INT32 * OPJ_RESTRICT tiledp; + OPJ_UINT32 min_j; + OPJ_UINT32 max_j; +} opj_dwd_decode_h_job_t; + +static void opj_dwt_decode_h_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwd_decode_h_job_t* job; + (void)tls; + + job = (opj_dwd_decode_h_job_t*)user_data; + for (j = job->min_j; j < job->max_j; j++) { + opj_idwt53_h(&job->h, &job->tiledp[j * job->w]); + } + + opj_aligned_free(job->h.mem); + opj_free(job); } +typedef struct { + opj_dwt_t v; + OPJ_UINT32 rh; + OPJ_UINT32 w; + OPJ_INT32 * OPJ_RESTRICT tiledp; + OPJ_UINT32 min_j; + OPJ_UINT32 max_j; +} opj_dwd_decode_v_job_t; + +static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwd_decode_v_job_t* job; + (void)tls; + + job = (opj_dwd_decode_v_job_t*)user_data; + for (j = job->min_j; j + PARALLEL_COLS_53 <= job->max_j; + j += PARALLEL_COLS_53) { + opj_idwt53_v(&job->v, &job->tiledp[j], (OPJ_SIZE_T)job->w, + PARALLEL_COLS_53); + } + if (j < job->max_j) + opj_idwt53_v(&job->v, &job->tiledp[j], (OPJ_SIZE_T)job->w, + (OPJ_INT32)(job->max_j - j)); + + opj_aligned_free(job->v.mem); + opj_free(job); +} + + /* <summary> */ -/* Inverse wavelet transform in 2-D. */ +/* Inverse wavelet transform in 2-D. */ /* </summary> */ -static OPJ_BOOL opj_dwt_decode_tile(const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) { - opj_dwt_t h; - opj_dwt_t v; - - opj_tcd_resolution_t* tr = tilec->resolutions; - - OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - tr->x0); /* width of the resolution level computed */ - OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - tr->y0); /* height of the resolution level computed */ - - OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0); - - h.mem_count = opj_dwt_max_resolution(tr, numres); - if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_INT32) < (OPJ_UINT32)h.mem_count) { - return OPJ_FALSE; - } - h.mem = (OPJ_INT32*)opj_aligned_malloc(h.mem_count * sizeof(OPJ_INT32)); - if (! h.mem){ - /* FIXME event manager error callback */ - return OPJ_FALSE; - } - - v.mem_count = h.mem_count; - v.mem = h.mem; - - while( --numres) { - OPJ_INT32 * restrict tiledp = tilec->data; - OPJ_UINT32 j; - - ++tr; - h.sn = (OPJ_INT32)rw; - v.sn = (OPJ_INT32)rh; - - rw = (OPJ_UINT32)(tr->x1 - tr->x0); - rh = (OPJ_UINT32)(tr->y1 - tr->y0); - - h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); - h.cas = tr->x0 % 2; - - for(j = 0; j < rh; ++j) { - opj_dwt_interleave_h(&h, &tiledp[j*w]); - (dwt_1D)(&h); - memcpy(&tiledp[j*w], h.mem, rw * sizeof(OPJ_INT32)); - } - - v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); - v.cas = tr->y0 % 2; - - for(j = 0; j < rw; ++j){ - OPJ_UINT32 k; - opj_dwt_interleave_v(&v, &tiledp[j], (OPJ_INT32)w); - (dwt_1D)(&v); - for(k = 0; k < rh; ++k) { - tiledp[k * w + j] = v.mem[k]; - } - } - } - opj_aligned_free(h.mem); - return OPJ_TRUE; -} - -static void opj_v4dwt_interleave_h(opj_v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size){ - OPJ_FLOAT32* restrict bi = (OPJ_FLOAT32*) (w->wavelet + w->cas); - OPJ_INT32 count = w->sn; - OPJ_INT32 i, k; - - for(k = 0; k < 2; ++k){ - if ( count + 3 * x < size && ((size_t) a & 0x0f) == 0 && ((size_t) bi & 0x0f) == 0 && (x & 0x0f) == 0 ) { - /* Fast code path */ - for(i = 0; i < count; ++i){ - OPJ_INT32 j = i; - bi[i*8 ] = a[j]; - j += x; - bi[i*8 + 1] = a[j]; - j += x; - bi[i*8 + 2] = a[j]; - j += x; - bi[i*8 + 3] = a[j]; - } - } - else { - /* Slow code path */ - for(i = 0; i < count; ++i){ - OPJ_INT32 j = i; - bi[i*8 ] = a[j]; - j += x; - if(j >= size) continue; - bi[i*8 + 1] = a[j]; - j += x; - if(j >= size) continue; - bi[i*8 + 2] = a[j]; - j += x; - if(j >= size) continue; - bi[i*8 + 3] = a[j]; /* This one*/ - } - } - - bi = (OPJ_FLOAT32*) (w->wavelet + 1 - w->cas); - a += w->sn; - size -= w->sn; - count = w->dn; - } -} - -static void opj_v4dwt_interleave_v(opj_v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x, OPJ_INT32 nb_elts_read){ - opj_v4_t* restrict bi = v->wavelet + v->cas; - OPJ_INT32 i; - - for(i = 0; i < v->sn; ++i){ - memcpy(&bi[i*2], &a[i*x], (size_t)nb_elts_read * sizeof(OPJ_FLOAT32)); - } - - a += v->sn * x; - bi = v->wavelet + 1 - v->cas; - - for(i = 0; i < v->dn; ++i){ - memcpy(&bi[i*2], &a[i*x], (size_t)nb_elts_read * sizeof(OPJ_FLOAT32)); - } +static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, + const opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) +{ + opj_dwt_t h; + opj_dwt_t v; + + opj_tcd_resolution_t* tr = tilec->resolutions; + + OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - + tr->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - + tr->y0); /* height of the resolution level computed */ + + OPJ_UINT32 w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - + 1].x1 - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); + OPJ_SIZE_T h_mem_size; + int num_threads; + + if (numres == 1U) { + return OPJ_TRUE; + } + num_threads = opj_thread_pool_get_thread_count(tp); + h.mem_count = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + if (h.mem_count > (SIZE_MAX / PARALLEL_COLS_53 / sizeof(OPJ_INT32))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + /* We need PARALLEL_COLS_53 times the height of the array, */ + /* since for the vertical pass */ + /* we process PARALLEL_COLS_53 columns at a time */ + h_mem_size = h.mem_count * PARALLEL_COLS_53 * sizeof(OPJ_INT32); + h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (! h.mem) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + + v.mem_count = h.mem_count; + v.mem = h.mem; + + while (--numres) { + OPJ_INT32 * OPJ_RESTRICT tiledp = tilec->data; + OPJ_UINT32 j; + + ++tr; + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + rw = (OPJ_UINT32)(tr->x1 - tr->x0); + rh = (OPJ_UINT32)(tr->y1 - tr->y0); + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = tr->x0 % 2; + + if (num_threads <= 1 || rh <= 1) { + for (j = 0; j < rh; ++j) { + opj_idwt53_h(&h, &tiledp[(OPJ_SIZE_T)j * w]); + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if (rh < num_jobs) { + num_jobs = rh; + } + step_j = (rh / num_jobs); + + for (j = 0; j < num_jobs; j++) { + opj_dwd_decode_h_job_t* job; + + job = (opj_dwd_decode_h_job_t*) opj_malloc(sizeof(opj_dwd_decode_h_job_t)); + if (!job) { + /* It would be nice to fallback to single thread case, but */ + /* unfortunately some jobs may be launched and have modified */ + /* tiledp, so it is not practical to recover from that error */ + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + job->h = h; + job->rw = rw; + job->w = w; + job->tiledp = tiledp; + job->min_j = j * step_j; + job->max_j = (j + 1U) * step_j; /* this can overflow */ + if (j == (num_jobs - 1U)) { /* this will take care of the overflow */ + job->max_j = rh; + } + job->h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (!job->h.mem) { + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + opj_thread_pool_submit_job(tp, opj_dwt_decode_h_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = tr->y0 % 2; + + if (num_threads <= 1 || rw <= 1) { + for (j = 0; j + PARALLEL_COLS_53 <= rw; + j += PARALLEL_COLS_53) { + opj_idwt53_v(&v, &tiledp[j], (OPJ_SIZE_T)w, PARALLEL_COLS_53); + } + if (j < rw) { + opj_idwt53_v(&v, &tiledp[j], (OPJ_SIZE_T)w, (OPJ_INT32)(rw - j)); + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if (rw < num_jobs) { + num_jobs = rw; + } + step_j = (rw / num_jobs); + + for (j = 0; j < num_jobs; j++) { + opj_dwd_decode_v_job_t* job; + + job = (opj_dwd_decode_v_job_t*) opj_malloc(sizeof(opj_dwd_decode_v_job_t)); + if (!job) { + /* It would be nice to fallback to single thread case, but */ + /* unfortunately some jobs may be launched and have modified */ + /* tiledp, so it is not practical to recover from that error */ + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(v.mem); + return OPJ_FALSE; + } + job->v = v; + job->rh = rh; + job->w = w; + job->tiledp = tiledp; + job->min_j = j * step_j; + job->max_j = (j + 1U) * step_j; /* this can overflow */ + if (j == (num_jobs - 1U)) { /* this will take care of the overflow */ + job->max_j = rw; + } + job->v.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (!job->v.mem) { + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(v.mem); + return OPJ_FALSE; + } + opj_thread_pool_submit_job(tp, opj_dwt_decode_v_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + } + opj_aligned_free(h.mem); + return OPJ_TRUE; +} + +static void opj_dwt_interleave_partial_h(OPJ_INT32 *dest, + OPJ_INT32 cas, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_line, + OPJ_UINT32 sn, + OPJ_UINT32 win_l_x0, + OPJ_UINT32 win_l_x1, + OPJ_UINT32 win_h_x0, + OPJ_UINT32 win_h_x1) +{ + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + win_l_x0, sa_line, + win_l_x1, sa_line + 1, + dest + cas + 2 * win_l_x0, + 2, 0, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + sn + win_h_x0, sa_line, + sn + win_h_x1, sa_line + 1, + dest + 1 - cas + 2 * win_h_x0, + 2, 0, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); +} + + +static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest, + OPJ_INT32 cas, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_col, + OPJ_UINT32 nb_cols, + OPJ_UINT32 sn, + OPJ_UINT32 win_l_y0, + OPJ_UINT32 win_l_y1, + OPJ_UINT32 win_h_y0, + OPJ_UINT32 win_h_y1) +{ + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + sa_col, win_l_y0, + sa_col + nb_cols, win_l_y1, + dest + cas * 4 + 2 * 4 * win_l_y0, + 1, 2 * 4, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + sa_col, sn + win_h_y0, + sa_col + nb_cols, sn + win_h_y1, + dest + (1 - cas) * 4 + 2 * 4 * win_h_y0, + 1, 2 * 4, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); +} + +static void opj_dwt_decode_partial_1(OPJ_INT32 *a, OPJ_SIZE_T a_count, + OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas, + OPJ_INT32 win_l_x0, + OPJ_INT32 win_l_x1, + OPJ_INT32 win_h_x0, + OPJ_INT32 win_h_x1) +{ + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + + /* Naive version is : + for (i = win_l_x0; i < i_max; i++) { + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + for (i = win_h_x0; i < win_h_x1; i++) { + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + but the compiler doesn't manage to unroll it to avoid bound + checking in OPJ_S_ and OPJ_D_ macros + */ + + i = win_l_x0; + if (i < win_l_x1) { + OPJ_INT32 i_max; + + /* Left-most case */ + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + i ++; + + i_max = win_l_x1; + if (i_max > dn) { + i_max = dn; + } + for (; i < i_max; i++) { + /* No bound checking */ + OPJ_S(i) -= (OPJ_D(i - 1) + OPJ_D(i) + 2) >> 2; + } + for (; i < win_l_x1; i++) { + /* Right-most case */ + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + } + + i = win_h_x0; + if (i < win_h_x1) { + OPJ_INT32 i_max = win_h_x1; + if (i_max >= sn) { + i_max = sn - 1; + } + for (; i < i_max; i++) { + /* No bound checking */ + OPJ_D(i) += (OPJ_S(i) + OPJ_S(i + 1)) >> 1; + } + for (; i < win_h_x1; i++) { + /* Right-most case */ + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + OPJ_S(0) /= 2; + } else { + for (i = win_l_x0; i < win_l_x1; i++) { + OPJ_D(i) -= (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2; + } + for (i = win_h_x0; i < win_h_x1; i++) { + OPJ_S(i) += (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1; + } + } + } +} + +#define OPJ_S_off(i,off) a[(OPJ_UINT32)(i)*2*4+off] +#define OPJ_D_off(i,off) a[(1+(OPJ_UINT32)(i)*2)*4+off] +#define OPJ_S__off(i,off) ((i)<0?OPJ_S_off(0,off):((i)>=sn?OPJ_S_off(sn-1,off):OPJ_S_off(i,off))) +#define OPJ_D__off(i,off) ((i)<0?OPJ_D_off(0,off):((i)>=dn?OPJ_D_off(dn-1,off):OPJ_D_off(i,off))) +#define OPJ_SS__off(i,off) ((i)<0?OPJ_S_off(0,off):((i)>=dn?OPJ_S_off(dn-1,off):OPJ_S_off(i,off))) +#define OPJ_DD__off(i,off) ((i)<0?OPJ_D_off(0,off):((i)>=sn?OPJ_D_off(sn-1,off):OPJ_D_off(i,off))) + +static void opj_dwt_decode_partial_1_parallel(OPJ_INT32 *a, + OPJ_UINT32 nb_cols, + OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas, + OPJ_INT32 win_l_x0, + OPJ_INT32 win_l_x1, + OPJ_INT32 win_h_x0, + OPJ_INT32 win_h_x1) +{ + OPJ_INT32 i; + OPJ_UINT32 off; + + (void)nb_cols; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + + /* Naive version is : + for (i = win_l_x0; i < i_max; i++) { + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + for (i = win_h_x0; i < win_h_x1; i++) { + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + but the compiler doesn't manage to unroll it to avoid bound + checking in OPJ_S_ and OPJ_D_ macros + */ + + i = win_l_x0; + if (i < win_l_x1) { + OPJ_INT32 i_max; + + /* Left-most case */ + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) -= (OPJ_D__off(i - 1, off) + OPJ_D__off(i, off) + 2) >> 2; + } + i ++; + + i_max = win_l_x1; + if (i_max > dn) { + i_max = dn; + } + +#ifdef __SSE2__ + if (i + 1 < i_max) { + const __m128i two = _mm_set1_epi32(2); + __m128i Dm1 = _mm_load_si128((__m128i * const)(a + 4 + (i - 1) * 8)); + for (; i + 1 < i_max; i += 2) { + /* No bound checking */ + __m128i S = _mm_load_si128((__m128i * const)(a + i * 8)); + __m128i D = _mm_load_si128((__m128i * const)(a + 4 + i * 8)); + __m128i S1 = _mm_load_si128((__m128i * const)(a + (i + 1) * 8)); + __m128i D1 = _mm_load_si128((__m128i * const)(a + 4 + (i + 1) * 8)); + S = _mm_sub_epi32(S, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(Dm1, D), two), 2)); + S1 = _mm_sub_epi32(S1, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(D, D1), two), 2)); + _mm_store_si128((__m128i*)(a + i * 8), S); + _mm_store_si128((__m128i*)(a + (i + 1) * 8), S1); + Dm1 = D1; + } + } +#endif + + for (; i < i_max; i++) { + /* No bound checking */ + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) -= (OPJ_D_off(i - 1, off) + OPJ_D_off(i, off) + 2) >> 2; + } + } + for (; i < win_l_x1; i++) { + /* Right-most case */ + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) -= (OPJ_D__off(i - 1, off) + OPJ_D__off(i, off) + 2) >> 2; + } + } + } + + i = win_h_x0; + if (i < win_h_x1) { + OPJ_INT32 i_max = win_h_x1; + if (i_max >= sn) { + i_max = sn - 1; + } + +#ifdef __SSE2__ + if (i + 1 < i_max) { + __m128i S = _mm_load_si128((__m128i * const)(a + i * 8)); + for (; i + 1 < i_max; i += 2) { + /* No bound checking */ + __m128i D = _mm_load_si128((__m128i * const)(a + 4 + i * 8)); + __m128i S1 = _mm_load_si128((__m128i * const)(a + (i + 1) * 8)); + __m128i D1 = _mm_load_si128((__m128i * const)(a + 4 + (i + 1) * 8)); + __m128i S2 = _mm_load_si128((__m128i * const)(a + (i + 2) * 8)); + D = _mm_add_epi32(D, _mm_srai_epi32(_mm_add_epi32(S, S1), 1)); + D1 = _mm_add_epi32(D1, _mm_srai_epi32(_mm_add_epi32(S1, S2), 1)); + _mm_store_si128((__m128i*)(a + 4 + i * 8), D); + _mm_store_si128((__m128i*)(a + 4 + (i + 1) * 8), D1); + S = S2; + } + } +#endif + + for (; i < i_max; i++) { + /* No bound checking */ + for (off = 0; off < 4; off++) { + OPJ_D_off(i, off) += (OPJ_S_off(i, off) + OPJ_S_off(i + 1, off)) >> 1; + } + } + for (; i < win_h_x1; i++) { + /* Right-most case */ + for (off = 0; off < 4; off++) { + OPJ_D_off(i, off) += (OPJ_S__off(i, off) + OPJ_S__off(i + 1, off)) >> 1; + } + } + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + for (off = 0; off < 4; off++) { + OPJ_S_off(0, off) /= 2; + } + } else { + for (i = win_l_x0; i < win_l_x1; i++) { + for (off = 0; off < 4; off++) { + OPJ_D_off(i, off) -= (OPJ_SS__off(i, off) + OPJ_SS__off(i + 1, off) + 2) >> 2; + } + } + for (i = win_h_x0; i < win_h_x1; i++) { + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) += (OPJ_DD__off(i, off) + OPJ_DD__off(i - 1, off)) >> 1; + } + } + } + } +} + +static void opj_dwt_get_band_coordinates(opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 tcx0, + OPJ_UINT32 tcy0, + OPJ_UINT32 tcx1, + OPJ_UINT32 tcy1, + OPJ_UINT32* tbx0, + OPJ_UINT32* tby0, + OPJ_UINT32* tbx1, + OPJ_UINT32* tby1) +{ + /* Compute number of decomposition for this band. See table F-1 */ + OPJ_UINT32 nb = (resno == 0) ? + tilec->numresolutions - 1 : + tilec->numresolutions - resno; + /* Map above tile-based coordinates to sub-band-based coordinates per */ + /* equation B-15 of the standard */ + OPJ_UINT32 x0b = bandno & 1; + OPJ_UINT32 y0b = bandno >> 1; + if (tbx0) { + *tbx0 = (nb == 0) ? tcx0 : + (tcx0 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx0 - (1U << (nb - 1)) * x0b, nb); + } + if (tby0) { + *tby0 = (nb == 0) ? tcy0 : + (tcy0 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy0 - (1U << (nb - 1)) * y0b, nb); + } + if (tbx1) { + *tbx1 = (nb == 0) ? tcx1 : + (tcx1 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx1 - (1U << (nb - 1)) * x0b, nb); + } + if (tby1) { + *tby1 = (nb == 0) ? tcy1 : + (tcy1 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy1 - (1U << (nb - 1)) * y0b, nb); + } +} + +static void opj_dwt_segment_grow(OPJ_UINT32 filter_width, + OPJ_UINT32 max_size, + OPJ_UINT32* start, + OPJ_UINT32* end) +{ + *start = opj_uint_subs(*start, filter_width); + *end = opj_uint_adds(*end, filter_width); + *end = opj_uint_min(*end, max_size); +} + + +static opj_sparse_array_int32_t* opj_dwt_init_sparse_array( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres) +{ + opj_tcd_resolution_t* tr_max = &(tilec->resolutions[numres - 1]); + OPJ_UINT32 w = (OPJ_UINT32)(tr_max->x1 - tr_max->x0); + OPJ_UINT32 h = (OPJ_UINT32)(tr_max->y1 - tr_max->y0); + OPJ_UINT32 resno, bandno, precno, cblkno; + opj_sparse_array_int32_t* sa = opj_sparse_array_int32_create( + w, h, opj_uint_min(w, 64), opj_uint_min(h, 64)); + if (sa == NULL) { + return NULL; + } + + for (resno = 0; resno < numres; ++resno) { + opj_tcd_resolution_t* res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t* precinct = &band->precincts[precno]; + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + if (cblk->decoded_data != NULL) { + OPJ_UINT32 x = (OPJ_UINT32)(cblk->x0 - band->x0); + OPJ_UINT32 y = (OPJ_UINT32)(cblk->y0 - band->y0); + OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + + if (band->bandno & 1) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + x += (OPJ_UINT32)(pres->x1 - pres->x0); + } + if (band->bandno & 2) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + y += (OPJ_UINT32)(pres->y1 - pres->y0); + } + + if (!opj_sparse_array_int32_write(sa, x, y, + x + cblk_w, y + cblk_h, + cblk->decoded_data, + 1, cblk_w, OPJ_TRUE)) { + opj_sparse_array_int32_free(sa); + return NULL; + } + } + } + } + } + } + + return sa; +} + + +static OPJ_BOOL opj_dwt_decode_partial_tile( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres) +{ + opj_sparse_array_int32_t* sa; + opj_dwt_t h; + opj_dwt_t v; + OPJ_UINT32 resno; + /* This value matches the maximum left/right extension given in tables */ + /* F.2 and F.3 of the standard. */ + const OPJ_UINT32 filter_width = 2U; + + opj_tcd_resolution_t* tr = tilec->resolutions; + opj_tcd_resolution_t* tr_max = &(tilec->resolutions[numres - 1]); + + OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - + tr->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - + tr->y0); /* height of the resolution level computed */ + + OPJ_SIZE_T h_mem_size; + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 win_tcx0 = tilec->win_x0; + OPJ_UINT32 win_tcy0 = tilec->win_y0; + OPJ_UINT32 win_tcx1 = tilec->win_x1; + OPJ_UINT32 win_tcy1 = tilec->win_y1; + + if (tr_max->x0 == tr_max->x1 || tr_max->y0 == tr_max->y1) { + return OPJ_TRUE; + } + + sa = opj_dwt_init_sparse_array(tilec, numres); + if (sa == NULL) { + return OPJ_FALSE; + } + + if (numres == 1U) { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; + } + h.mem_count = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + /* in vertical pass, we process 4 columns at a time */ + if (h.mem_count > (SIZE_MAX / (4 * sizeof(OPJ_INT32)))) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } + + h_mem_size = h.mem_count * 4 * sizeof(OPJ_INT32); + h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (! h.mem) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } + + v.mem_count = h.mem_count; + v.mem = h.mem; + + for (resno = 1; resno < numres; resno ++) { + OPJ_UINT32 i, j; + /* Window of interest subband-based coordinates */ + OPJ_UINT32 win_ll_x0, win_ll_y0, win_ll_x1, win_ll_y1; + OPJ_UINT32 win_hl_x0, win_hl_x1; + OPJ_UINT32 win_lh_y0, win_lh_y1; + /* Window of interest tile-resolution-based coordinates */ + OPJ_UINT32 win_tr_x0, win_tr_x1, win_tr_y0, win_tr_y1; + /* Tile-resolution subband-based coordinates */ + OPJ_UINT32 tr_ll_x0, tr_ll_y0, tr_hl_x0, tr_lh_y0; + + ++tr; + + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + rw = (OPJ_UINT32)(tr->x1 - tr->x0); + rh = (OPJ_UINT32)(tr->y1 - tr->y0); + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = tr->x0 % 2; + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = tr->y0 % 2; + + /* Get the subband coordinates for the window of interest */ + /* LL band */ + opj_dwt_get_band_coordinates(tilec, resno, 0, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_ll_x0, &win_ll_y0, + &win_ll_x1, &win_ll_y1); + + /* HL band */ + opj_dwt_get_band_coordinates(tilec, resno, 1, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_hl_x0, NULL, &win_hl_x1, NULL); + + /* LH band */ + opj_dwt_get_band_coordinates(tilec, resno, 2, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + NULL, &win_lh_y0, NULL, &win_lh_y1); + + /* Beware: band index for non-LL0 resolution are 0=HL, 1=LH and 2=HH */ + tr_ll_x0 = (OPJ_UINT32)tr->bands[1].x0; + tr_ll_y0 = (OPJ_UINT32)tr->bands[0].y0; + tr_hl_x0 = (OPJ_UINT32)tr->bands[0].x0; + tr_lh_y0 = (OPJ_UINT32)tr->bands[1].y0; + + /* Substract the origin of the bands for this tile, to the subwindow */ + /* of interest band coordinates, so as to get them relative to the */ + /* tile */ + win_ll_x0 = opj_uint_subs(win_ll_x0, tr_ll_x0); + win_ll_y0 = opj_uint_subs(win_ll_y0, tr_ll_y0); + win_ll_x1 = opj_uint_subs(win_ll_x1, tr_ll_x0); + win_ll_y1 = opj_uint_subs(win_ll_y1, tr_ll_y0); + win_hl_x0 = opj_uint_subs(win_hl_x0, tr_hl_x0); + win_hl_x1 = opj_uint_subs(win_hl_x1, tr_hl_x0); + win_lh_y0 = opj_uint_subs(win_lh_y0, tr_lh_y0); + win_lh_y1 = opj_uint_subs(win_lh_y1, tr_lh_y0); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.sn, &win_ll_x0, &win_ll_x1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.dn, &win_hl_x0, &win_hl_x1); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.sn, &win_ll_y0, &win_ll_y1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.dn, &win_lh_y0, &win_lh_y1); + + /* Compute the tile-resolution-based coordinates for the window of interest */ + if (h.cas == 0) { + win_tr_x0 = opj_uint_min(2 * win_ll_x0, 2 * win_hl_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_ll_x1, 2 * win_hl_x1 + 1), rw); + } else { + win_tr_x0 = opj_uint_min(2 * win_hl_x0, 2 * win_ll_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_hl_x1, 2 * win_ll_x1 + 1), rw); + } + + if (v.cas == 0) { + win_tr_y0 = opj_uint_min(2 * win_ll_y0, 2 * win_lh_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_ll_y1, 2 * win_lh_y1 + 1), rh); + } else { + win_tr_y0 = opj_uint_min(2 * win_lh_y0, 2 * win_ll_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_lh_y1, 2 * win_ll_y1 + 1), rh); + } + + for (j = 0; j < rh; ++j) { + if ((j >= win_ll_y0 && j < win_ll_y1) || + (j >= win_lh_y0 + (OPJ_UINT32)v.sn && j < win_lh_y1 + (OPJ_UINT32)v.sn)) { + + /* Avoids dwt.c:1584:44 (in opj_dwt_decode_partial_1): runtime error: */ + /* signed integer overflow: -1094795586 + -1094795586 cannot be represented in type 'int' */ + /* on opj_decompress -i ../../openjpeg/MAPA.jp2 -o out.tif -d 0,0,256,256 */ + /* This is less extreme than memsetting the whole buffer to 0 */ + /* although we could potentially do better with better handling of edge conditions */ + if (win_tr_x1 >= 1 && win_tr_x1 < rw) { + h.mem[win_tr_x1 - 1] = 0; + } + if (win_tr_x1 < rw) { + h.mem[win_tr_x1] = 0; + } + + opj_dwt_interleave_partial_h(h.mem, + h.cas, + sa, + j, + (OPJ_UINT32)h.sn, + win_ll_x0, + win_ll_x1, + win_hl_x0, + win_hl_x1); + opj_dwt_decode_partial_1(h.mem, h.mem_count, h.dn, h.sn, h.cas, + (OPJ_INT32)win_ll_x0, + (OPJ_INT32)win_ll_x1, + (OPJ_INT32)win_hl_x0, + (OPJ_INT32)win_hl_x1); + if (!opj_sparse_array_int32_write(sa, + win_tr_x0, j, + win_tr_x1, j + 1, + h.mem + win_tr_x0, + 1, 0, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + } + } + + for (i = win_tr_x0; i < win_tr_x1;) { + OPJ_UINT32 nb_cols = opj_uint_min(4U, win_tr_x1 - i); + opj_dwt_interleave_partial_v(v.mem, + v.cas, + sa, + i, + nb_cols, + (OPJ_UINT32)v.sn, + win_ll_y0, + win_ll_y1, + win_lh_y0, + win_lh_y1); + opj_dwt_decode_partial_1_parallel(v.mem, nb_cols, v.dn, v.sn, v.cas, + (OPJ_INT32)win_ll_y0, + (OPJ_INT32)win_ll_y1, + (OPJ_INT32)win_lh_y0, + (OPJ_INT32)win_lh_y1); + if (!opj_sparse_array_int32_write(sa, + i, win_tr_y0, + i + nb_cols, win_tr_y1, + v.mem + 4 * win_tr_y0, + 1, 4, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + + i += nb_cols; + } + } + opj_aligned_free(h.mem); + + { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + } + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; +} + +static void opj_v4dwt_interleave_h(opj_v4dwt_t* OPJ_RESTRICT dwt, + OPJ_FLOAT32* OPJ_RESTRICT a, + OPJ_UINT32 width, + OPJ_UINT32 remaining_height) +{ + OPJ_FLOAT32* OPJ_RESTRICT bi = (OPJ_FLOAT32*)(dwt->wavelet + dwt->cas); + OPJ_UINT32 i, k; + OPJ_UINT32 x0 = dwt->win_l_x0; + OPJ_UINT32 x1 = dwt->win_l_x1; + + for (k = 0; k < 2; ++k) { + if (remaining_height >= 4 && ((OPJ_SIZE_T) a & 0x0f) == 0 && + ((OPJ_SIZE_T) bi & 0x0f) == 0 && (width & 0x0f) == 0) { + /* Fast code path */ + for (i = x0; i < x1; ++i) { + OPJ_UINT32 j = i; + bi[i * 8 ] = a[j]; + j += width; + bi[i * 8 + 1] = a[j]; + j += width; + bi[i * 8 + 2] = a[j]; + j += width; + bi[i * 8 + 3] = a[j]; + } + } else { + /* Slow code path */ + for (i = x0; i < x1; ++i) { + OPJ_UINT32 j = i; + bi[i * 8 ] = a[j]; + j += width; + if (remaining_height == 1) { + continue; + } + bi[i * 8 + 1] = a[j]; + j += width; + if (remaining_height == 2) { + continue; + } + bi[i * 8 + 2] = a[j]; + j += width; + if (remaining_height == 3) { + continue; + } + bi[i * 8 + 3] = a[j]; /* This one*/ + } + } + + bi = (OPJ_FLOAT32*)(dwt->wavelet + 1 - dwt->cas); + a += dwt->sn; + x0 = dwt->win_h_x0; + x1 = dwt->win_h_x1; + } +} + +static void opj_v4dwt_interleave_partial_h(opj_v4dwt_t* dwt, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_line, + OPJ_UINT32 remaining_height) +{ + OPJ_UINT32 i; + for (i = 0; i < remaining_height; i++) { + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + dwt->win_l_x0, sa_line + i, + dwt->win_l_x1, sa_line + i + 1, + /* Nasty cast from float* to int32* */ + (OPJ_INT32*)(dwt->wavelet + dwt->cas + 2 * dwt->win_l_x0) + i, + 8, 0, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + (OPJ_UINT32)dwt->sn + dwt->win_h_x0, sa_line + i, + (OPJ_UINT32)dwt->sn + dwt->win_h_x1, sa_line + i + 1, + /* Nasty cast from float* to int32* */ + (OPJ_INT32*)(dwt->wavelet + 1 - dwt->cas + 2 * dwt->win_h_x0) + i, + 8, 0, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + } +} + +static void opj_v4dwt_interleave_v(opj_v4dwt_t* OPJ_RESTRICT dwt, + OPJ_FLOAT32* OPJ_RESTRICT a, + OPJ_UINT32 width, + OPJ_UINT32 nb_elts_read) +{ + opj_v4_t* OPJ_RESTRICT bi = dwt->wavelet + dwt->cas; + OPJ_UINT32 i; + + for (i = dwt->win_l_x0; i < dwt->win_l_x1; ++i) { + memcpy(&bi[i * 2], &a[i * (OPJ_SIZE_T)width], + (OPJ_SIZE_T)nb_elts_read * sizeof(OPJ_FLOAT32)); + } + + a += (OPJ_UINT32)dwt->sn * (OPJ_SIZE_T)width; + bi = dwt->wavelet + 1 - dwt->cas; + + for (i = dwt->win_h_x0; i < dwt->win_h_x1; ++i) { + memcpy(&bi[i * 2], &a[i * (OPJ_SIZE_T)width], + (OPJ_SIZE_T)nb_elts_read * sizeof(OPJ_FLOAT32)); + } +} + +static void opj_v4dwt_interleave_partial_v(opj_v4dwt_t* OPJ_RESTRICT dwt, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_col, + OPJ_UINT32 nb_elts_read) +{ + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + sa_col, dwt->win_l_x0, + sa_col + nb_elts_read, dwt->win_l_x1, + (OPJ_INT32*)(dwt->wavelet + dwt->cas + 2 * dwt->win_l_x0), + 1, 8, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + sa_col, (OPJ_UINT32)dwt->sn + dwt->win_h_x0, + sa_col + nb_elts_read, (OPJ_UINT32)dwt->sn + dwt->win_h_x1, + (OPJ_INT32*)(dwt->wavelet + 1 - dwt->cas + 2 * dwt->win_h_x0), + 1, 8, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); } #ifdef __SSE__ -static void opj_v4dwt_decode_step1_sse(opj_v4_t* w, OPJ_INT32 count, const __m128 c){ - __m128* restrict vw = (__m128*) w; - OPJ_INT32 i; - /* 4x unrolled loop */ - for(i = 0; i < count >> 2; ++i){ - *vw = _mm_mul_ps(*vw, c); - vw += 2; - *vw = _mm_mul_ps(*vw, c); - vw += 2; - *vw = _mm_mul_ps(*vw, c); - vw += 2; - *vw = _mm_mul_ps(*vw, c); - vw += 2; - } - count &= 3; - for(i = 0; i < count; ++i){ - *vw = _mm_mul_ps(*vw, c); - vw += 2; - } -} - -void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_INT32 m, __m128 c){ - __m128* restrict vl = (__m128*) l; - __m128* restrict vw = (__m128*) w; - OPJ_INT32 i; - __m128 tmp1, tmp2, tmp3; - tmp1 = vl[0]; - for(i = 0; i < m; ++i){ - tmp2 = vw[-1]; - tmp3 = vw[ 0]; - vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c)); - tmp1 = tmp3; - vw += 2; - } - vl = vw - 2; - if(m >= k){ - return; - } - c = _mm_add_ps(c, c); - c = _mm_mul_ps(c, vl[0]); - for(; m < k; ++m){ - __m128 tmp = vw[-1]; - vw[-1] = _mm_add_ps(tmp, c); - vw += 2; - } +static void opj_v4dwt_decode_step1_sse(opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + const __m128 c) +{ + __m128* OPJ_RESTRICT vw = (__m128*) w; + OPJ_UINT32 i; + /* 4x unrolled loop */ + vw += 2 * start; + for (i = start; i + 3 < end; i += 4, vw += 8) { + __m128 xmm0 = _mm_mul_ps(vw[0], c); + __m128 xmm2 = _mm_mul_ps(vw[2], c); + __m128 xmm4 = _mm_mul_ps(vw[4], c); + __m128 xmm6 = _mm_mul_ps(vw[6], c); + vw[0] = xmm0; + vw[2] = xmm2; + vw[4] = xmm4; + vw[6] = xmm6; + } + for (; i < end; ++i, vw += 2) { + vw[0] = _mm_mul_ps(vw[0], c); + } +} + +static void opj_v4dwt_decode_step2_sse(opj_v4_t* l, opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + OPJ_UINT32 m, + __m128 c) +{ + __m128* OPJ_RESTRICT vl = (__m128*) l; + __m128* OPJ_RESTRICT vw = (__m128*) w; + OPJ_UINT32 i; + OPJ_UINT32 imax = opj_uint_min(end, m); + __m128 tmp1, tmp2, tmp3; + if (start == 0) { + tmp1 = vl[0]; + } else { + vw += start * 2; + tmp1 = vw[-3]; + } + + i = start; + + /* 4x loop unrolling */ + for (; i + 3 < imax; i += 4) { + __m128 tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; + tmp2 = vw[-1]; + tmp3 = vw[ 0]; + tmp4 = vw[ 1]; + tmp5 = vw[ 2]; + tmp6 = vw[ 3]; + tmp7 = vw[ 4]; + tmp8 = vw[ 5]; + tmp9 = vw[ 6]; + vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c)); + vw[ 1] = _mm_add_ps(tmp4, _mm_mul_ps(_mm_add_ps(tmp3, tmp5), c)); + vw[ 3] = _mm_add_ps(tmp6, _mm_mul_ps(_mm_add_ps(tmp5, tmp7), c)); + vw[ 5] = _mm_add_ps(tmp8, _mm_mul_ps(_mm_add_ps(tmp7, tmp9), c)); + tmp1 = tmp9; + vw += 8; + } + + for (; i < imax; ++i) { + tmp2 = vw[-1]; + tmp3 = vw[ 0]; + vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c)); + tmp1 = tmp3; + vw += 2; + } + if (m < end) { + assert(m + 1 == end); + c = _mm_add_ps(c, c); + c = _mm_mul_ps(c, vw[-2]); + vw[-1] = _mm_add_ps(vw[-1], c); + } } #else -static void opj_v4dwt_decode_step1(opj_v4_t* w, OPJ_INT32 count, const OPJ_FLOAT32 c) -{ - OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w; - OPJ_INT32 i; - for(i = 0; i < count; ++i){ - OPJ_FLOAT32 tmp1 = fw[i*8 ]; - OPJ_FLOAT32 tmp2 = fw[i*8 + 1]; - OPJ_FLOAT32 tmp3 = fw[i*8 + 2]; - OPJ_FLOAT32 tmp4 = fw[i*8 + 3]; - fw[i*8 ] = tmp1 * c; - fw[i*8 + 1] = tmp2 * c; - fw[i*8 + 2] = tmp3 * c; - fw[i*8 + 3] = tmp4 * c; - } -} - -static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c) -{ - OPJ_FLOAT32* restrict fl = (OPJ_FLOAT32*) l; - OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w; - OPJ_INT32 i; - for(i = 0; i < m; ++i){ - OPJ_FLOAT32 tmp1_1 = fl[0]; - OPJ_FLOAT32 tmp1_2 = fl[1]; - OPJ_FLOAT32 tmp1_3 = fl[2]; - OPJ_FLOAT32 tmp1_4 = fl[3]; - OPJ_FLOAT32 tmp2_1 = fw[-4]; - OPJ_FLOAT32 tmp2_2 = fw[-3]; - OPJ_FLOAT32 tmp2_3 = fw[-2]; - OPJ_FLOAT32 tmp2_4 = fw[-1]; - OPJ_FLOAT32 tmp3_1 = fw[0]; - OPJ_FLOAT32 tmp3_2 = fw[1]; - OPJ_FLOAT32 tmp3_3 = fw[2]; - OPJ_FLOAT32 tmp3_4 = fw[3]; - fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c); - fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c); - fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c); - fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c); - fl = fw; - fw += 8; - } - if(m < k){ - OPJ_FLOAT32 c1; - OPJ_FLOAT32 c2; - OPJ_FLOAT32 c3; - OPJ_FLOAT32 c4; - c += c; - c1 = fl[0] * c; - c2 = fl[1] * c; - c3 = fl[2] * c; - c4 = fl[3] * c; - for(; m < k; ++m){ - OPJ_FLOAT32 tmp1 = fw[-4]; - OPJ_FLOAT32 tmp2 = fw[-3]; - OPJ_FLOAT32 tmp3 = fw[-2]; - OPJ_FLOAT32 tmp4 = fw[-1]; - fw[-4] = tmp1 + c1; - fw[-3] = tmp2 + c2; - fw[-2] = tmp3 + c3; - fw[-1] = tmp4 + c4; - fw += 8; - } - } +static void opj_v4dwt_decode_step1(opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + const OPJ_FLOAT32 c) +{ + OPJ_FLOAT32* OPJ_RESTRICT fw = (OPJ_FLOAT32*) w; + OPJ_UINT32 i; + for (i = start; i < end; ++i) { + OPJ_FLOAT32 tmp1 = fw[i * 8 ]; + OPJ_FLOAT32 tmp2 = fw[i * 8 + 1]; + OPJ_FLOAT32 tmp3 = fw[i * 8 + 2]; + OPJ_FLOAT32 tmp4 = fw[i * 8 + 3]; + fw[i * 8 ] = tmp1 * c; + fw[i * 8 + 1] = tmp2 * c; + fw[i * 8 + 2] = tmp3 * c; + fw[i * 8 + 3] = tmp4 * c; + } +} + +static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + OPJ_UINT32 m, + OPJ_FLOAT32 c) +{ + OPJ_FLOAT32* fl = (OPJ_FLOAT32*) l; + OPJ_FLOAT32* fw = (OPJ_FLOAT32*) w; + OPJ_UINT32 i; + OPJ_UINT32 imax = opj_uint_min(end, m); + if (start > 0) { + fw += 8 * start; + fl = fw - 8; + } + for (i = start; i < imax; ++i) { + OPJ_FLOAT32 tmp1_1 = fl[0]; + OPJ_FLOAT32 tmp1_2 = fl[1]; + OPJ_FLOAT32 tmp1_3 = fl[2]; + OPJ_FLOAT32 tmp1_4 = fl[3]; + OPJ_FLOAT32 tmp2_1 = fw[-4]; + OPJ_FLOAT32 tmp2_2 = fw[-3]; + OPJ_FLOAT32 tmp2_3 = fw[-2]; + OPJ_FLOAT32 tmp2_4 = fw[-1]; + OPJ_FLOAT32 tmp3_1 = fw[0]; + OPJ_FLOAT32 tmp3_2 = fw[1]; + OPJ_FLOAT32 tmp3_3 = fw[2]; + OPJ_FLOAT32 tmp3_4 = fw[3]; + fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c); + fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c); + fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c); + fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c); + fl = fw; + fw += 8; + } + if (m < end) { + assert(m + 1 == end); + c += c; + fw[-4] = fw[-4] + fl[0] * c; + fw[-3] = fw[-3] + fl[1] * c; + fw[-2] = fw[-2] + fl[2] * c; + fw[-1] = fw[-1] + fl[3] * c; + } } #endif @@ -804,36 +2452,64 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w, OPJ_INT32 k, OPJ_IN /* <summary> */ /* Inverse 9-7 wavelet transform in 1-D. */ /* </summary> */ -void opj_v4dwt_decode(opj_v4dwt_t* restrict dwt) -{ - OPJ_INT32 a, b; - if(dwt->cas == 0) { - if(!((dwt->dn > 0) || (dwt->sn > 1))){ - return; - } - a = 0; - b = 1; - }else{ - if(!((dwt->sn > 0) || (dwt->dn > 1))) { - return; - } - a = 1; - b = 0; - } +static void opj_v4dwt_decode(opj_v4dwt_t* OPJ_RESTRICT dwt) +{ + OPJ_INT32 a, b; + if (dwt->cas == 0) { + if (!((dwt->dn > 0) || (dwt->sn > 1))) { + return; + } + a = 0; + b = 1; + } else { + if (!((dwt->sn > 0) || (dwt->dn > 1))) { + return; + } + a = 1; + b = 0; + } #ifdef __SSE__ - opj_v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(opj_K)); - opj_v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(opj_c13318)); - opj_v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, opj_int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(opj_dwt_delta)); - opj_v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, opj_int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(opj_dwt_gamma)); - opj_v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, opj_int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(opj_dwt_beta)); - opj_v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, opj_int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(opj_dwt_alpha)); + opj_v4dwt_decode_step1_sse(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1, + _mm_set1_ps(opj_K)); + opj_v4dwt_decode_step1_sse(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1, + _mm_set1_ps(opj_c13318)); + opj_v4dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + _mm_set1_ps(opj_dwt_delta)); + opj_v4dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + _mm_set1_ps(opj_dwt_gamma)); + opj_v4dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + _mm_set1_ps(opj_dwt_beta)); + opj_v4dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + _mm_set1_ps(opj_dwt_alpha)); #else - opj_v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, opj_K); - opj_v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, opj_c13318); - opj_v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, opj_int_min(dwt->sn, dwt->dn-a), opj_dwt_delta); - opj_v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, opj_int_min(dwt->dn, dwt->sn-b), opj_dwt_gamma); - opj_v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, opj_int_min(dwt->sn, dwt->dn-a), opj_dwt_beta); - opj_v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, opj_int_min(dwt->dn, dwt->sn-b), opj_dwt_alpha); + opj_v4dwt_decode_step1(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1, + opj_K); + opj_v4dwt_decode_step1(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1, + opj_c13318); + opj_v4dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + opj_dwt_delta); + opj_v4dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + opj_dwt_gamma); + opj_v4dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + opj_dwt_beta); + opj_v4dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + opj_dwt_alpha); #endif } @@ -841,111 +2517,384 @@ void opj_v4dwt_decode(opj_v4dwt_t* restrict dwt) /* <summary> */ /* Inverse 9-7 wavelet transform in 2-D. */ /* </summary> */ -OPJ_BOOL opj_dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numres) -{ - opj_v4dwt_t h; - opj_v4dwt_t v; - - opj_tcd_resolution_t* res = tilec->resolutions; - - OPJ_UINT32 rw = (OPJ_UINT32)(res->x1 - res->x0); /* width of the resolution level computed */ - OPJ_UINT32 rh = (OPJ_UINT32)(res->y1 - res->y0); /* height of the resolution level computed */ - - OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0); - - OPJ_UINT32 mr = opj_dwt_max_resolution(res, numres); - - if (mr >= ((OPJ_UINT32)-5)) { - return OPJ_FALSE; - } - mr += 5; - - if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(opj_v4_t) < mr) { - return OPJ_FALSE; - } - h.wavelet = (opj_v4_t*) opj_aligned_malloc(mr * sizeof(opj_v4_t)); - if (!h.wavelet) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } - v.wavelet = h.wavelet; - - while( --numres) { - OPJ_FLOAT32 * restrict aj = (OPJ_FLOAT32*) tilec->data; - OPJ_UINT32 bufsize = (OPJ_UINT32)((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)); - OPJ_INT32 j; - - h.sn = (OPJ_INT32)rw; - v.sn = (OPJ_INT32)rh; - - ++res; - - rw = (OPJ_UINT32)(res->x1 - res->x0); /* width of the resolution level computed */ - rh = (OPJ_UINT32)(res->y1 - res->y0); /* height of the resolution level computed */ - - h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); - h.cas = res->x0 % 2; - - for(j = (OPJ_INT32)rh; j > 3; j -= 4) { - OPJ_INT32 k; - opj_v4dwt_interleave_h(&h, aj, (OPJ_INT32)w, (OPJ_INT32)bufsize); - opj_v4dwt_decode(&h); - - for(k = (OPJ_INT32)rw; --k >= 0;){ - aj[k ] = h.wavelet[k].f[0]; - aj[k+(OPJ_INT32)w ] = h.wavelet[k].f[1]; - aj[k+(OPJ_INT32)w*2] = h.wavelet[k].f[2]; - aj[k+(OPJ_INT32)w*3] = h.wavelet[k].f[3]; - } - - aj += w*4; - bufsize -= w*4; - } - - if (rh & 0x03) { - OPJ_INT32 k; - j = rh & 0x03; - opj_v4dwt_interleave_h(&h, aj, (OPJ_INT32)w, (OPJ_INT32)bufsize); - opj_v4dwt_decode(&h); - for(k = (OPJ_INT32)rw; --k >= 0;){ - switch(j) { - case 3: aj[k+(OPJ_INT32)w*2] = h.wavelet[k].f[2]; - case 2: aj[k+(OPJ_INT32)w ] = h.wavelet[k].f[1]; - case 1: aj[k ] = h.wavelet[k].f[0]; - } - } - } - - v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); - v.cas = res->y0 % 2; - - aj = (OPJ_FLOAT32*) tilec->data; - for(j = (OPJ_INT32)rw; j > 3; j -= 4){ - OPJ_UINT32 k; - - opj_v4dwt_interleave_v(&v, aj, (OPJ_INT32)w, 4); - opj_v4dwt_decode(&v); - - for(k = 0; k < rh; ++k){ - memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(OPJ_FLOAT32)); - } - aj += 4; - } - - if (rw & 0x03){ - OPJ_UINT32 k; - - j = rw & 0x03; - - opj_v4dwt_interleave_v(&v, aj, (OPJ_INT32)w, j); - opj_v4dwt_decode(&v); - - for(k = 0; k < rh; ++k){ - memcpy(&aj[k*w], &v.wavelet[k], (size_t)j * sizeof(OPJ_FLOAT32)); - } - } - } - - opj_aligned_free(h.wavelet); - return OPJ_TRUE; +static +OPJ_BOOL opj_dwt_decode_tile_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres) +{ + opj_v4dwt_t h; + opj_v4dwt_t v; + + opj_tcd_resolution_t* res = tilec->resolutions; + + OPJ_UINT32 rw = (OPJ_UINT32)(res->x1 - + res->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(res->y1 - + res->y0); /* height of the resolution level computed */ + + OPJ_UINT32 w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - + 1].x1 - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); + + OPJ_SIZE_T l_data_size; + + l_data_size = opj_dwt_max_resolution(res, numres); + /* overflow check */ + if (l_data_size > (SIZE_MAX - 5U)) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + l_data_size += 5U; + /* overflow check */ + if (l_data_size > (SIZE_MAX / sizeof(opj_v4_t))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + h.wavelet = (opj_v4_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v4_t)); + if (!h.wavelet) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + v.wavelet = h.wavelet; + + while (--numres) { + OPJ_FLOAT32 * OPJ_RESTRICT aj = (OPJ_FLOAT32*) tilec->data; + OPJ_UINT32 j; + + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + ++res; + + rw = (OPJ_UINT32)(res->x1 - + res->x0); /* width of the resolution level computed */ + rh = (OPJ_UINT32)(res->y1 - + res->y0); /* height of the resolution level computed */ + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = res->x0 % 2; + + h.win_l_x0 = 0; + h.win_l_x1 = (OPJ_UINT32)h.sn; + h.win_h_x0 = 0; + h.win_h_x1 = (OPJ_UINT32)h.dn; + for (j = 0; j + 3 < rh; j += 4) { + OPJ_UINT32 k; + opj_v4dwt_interleave_h(&h, aj, w, rh - j); + opj_v4dwt_decode(&h); + + for (k = 0; k < rw; k++) { + aj[k ] = h.wavelet[k].f[0]; + aj[k + (OPJ_SIZE_T)w ] = h.wavelet[k].f[1]; + aj[k + (OPJ_SIZE_T)w * 2] = h.wavelet[k].f[2]; + aj[k + (OPJ_SIZE_T)w * 3] = h.wavelet[k].f[3]; + } + + aj += w * 4; + } + + if (j < rh) { + OPJ_UINT32 k; + opj_v4dwt_interleave_h(&h, aj, w, rh - j); + opj_v4dwt_decode(&h); + for (k = 0; k < rw; k++) { + switch (rh - j) { + case 3: + aj[k + (OPJ_SIZE_T)w * 2] = h.wavelet[k].f[2]; + /* FALLTHRU */ + case 2: + aj[k + (OPJ_SIZE_T)w ] = h.wavelet[k].f[1]; + /* FALLTHRU */ + case 1: + aj[k] = h.wavelet[k].f[0]; + } + } + } + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = res->y0 % 2; + v.win_l_x0 = 0; + v.win_l_x1 = (OPJ_UINT32)v.sn; + v.win_h_x0 = 0; + v.win_h_x1 = (OPJ_UINT32)v.dn; + + aj = (OPJ_FLOAT32*) tilec->data; + for (j = rw; j > 3; j -= 4) { + OPJ_UINT32 k; + + opj_v4dwt_interleave_v(&v, aj, w, 4); + opj_v4dwt_decode(&v); + + for (k = 0; k < rh; ++k) { + memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k], 4 * sizeof(OPJ_FLOAT32)); + } + aj += 4; + } + + if (rw & 0x03) { + OPJ_UINT32 k; + + j = rw & 0x03; + + opj_v4dwt_interleave_v(&v, aj, w, j); + opj_v4dwt_decode(&v); + + for (k = 0; k < rh; ++k) { + memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k], + (OPJ_SIZE_T)j * sizeof(OPJ_FLOAT32)); + } + } + } + + opj_aligned_free(h.wavelet); + return OPJ_TRUE; +} + +static +OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres) +{ + opj_sparse_array_int32_t* sa; + opj_v4dwt_t h; + opj_v4dwt_t v; + OPJ_UINT32 resno; + /* This value matches the maximum left/right extension given in tables */ + /* F.2 and F.3 of the standard. Note: in opj_tcd_is_subband_area_of_interest() */ + /* we currently use 3. */ + const OPJ_UINT32 filter_width = 4U; + + opj_tcd_resolution_t* tr = tilec->resolutions; + opj_tcd_resolution_t* tr_max = &(tilec->resolutions[numres - 1]); + + OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - + tr->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - + tr->y0); /* height of the resolution level computed */ + + OPJ_SIZE_T l_data_size; + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 win_tcx0 = tilec->win_x0; + OPJ_UINT32 win_tcy0 = tilec->win_y0; + OPJ_UINT32 win_tcx1 = tilec->win_x1; + OPJ_UINT32 win_tcy1 = tilec->win_y1; + + if (tr_max->x0 == tr_max->x1 || tr_max->y0 == tr_max->y1) { + return OPJ_TRUE; + } + + sa = opj_dwt_init_sparse_array(tilec, numres); + if (sa == NULL) { + return OPJ_FALSE; + } + + if (numres == 1U) { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; + } + + l_data_size = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + if (l_data_size > (SIZE_MAX - 5U)) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + l_data_size += 5U; + /* overflow check */ + if (l_data_size > (SIZE_MAX / sizeof(opj_v4_t))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + h.wavelet = (opj_v4_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v4_t)); + if (!h.wavelet) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + v.wavelet = h.wavelet; + + for (resno = 1; resno < numres; resno ++) { + OPJ_UINT32 j; + /* Window of interest subband-based coordinates */ + OPJ_UINT32 win_ll_x0, win_ll_y0, win_ll_x1, win_ll_y1; + OPJ_UINT32 win_hl_x0, win_hl_x1; + OPJ_UINT32 win_lh_y0, win_lh_y1; + /* Window of interest tile-resolution-based coordinates */ + OPJ_UINT32 win_tr_x0, win_tr_x1, win_tr_y0, win_tr_y1; + /* Tile-resolution subband-based coordinates */ + OPJ_UINT32 tr_ll_x0, tr_ll_y0, tr_hl_x0, tr_lh_y0; + + ++tr; + + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + rw = (OPJ_UINT32)(tr->x1 - tr->x0); + rh = (OPJ_UINT32)(tr->y1 - tr->y0); + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = tr->x0 % 2; + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = tr->y0 % 2; + + /* Get the subband coordinates for the window of interest */ + /* LL band */ + opj_dwt_get_band_coordinates(tilec, resno, 0, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_ll_x0, &win_ll_y0, + &win_ll_x1, &win_ll_y1); + + /* HL band */ + opj_dwt_get_band_coordinates(tilec, resno, 1, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_hl_x0, NULL, &win_hl_x1, NULL); + + /* LH band */ + opj_dwt_get_band_coordinates(tilec, resno, 2, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + NULL, &win_lh_y0, NULL, &win_lh_y1); + + /* Beware: band index for non-LL0 resolution are 0=HL, 1=LH and 2=HH */ + tr_ll_x0 = (OPJ_UINT32)tr->bands[1].x0; + tr_ll_y0 = (OPJ_UINT32)tr->bands[0].y0; + tr_hl_x0 = (OPJ_UINT32)tr->bands[0].x0; + tr_lh_y0 = (OPJ_UINT32)tr->bands[1].y0; + + /* Substract the origin of the bands for this tile, to the subwindow */ + /* of interest band coordinates, so as to get them relative to the */ + /* tile */ + win_ll_x0 = opj_uint_subs(win_ll_x0, tr_ll_x0); + win_ll_y0 = opj_uint_subs(win_ll_y0, tr_ll_y0); + win_ll_x1 = opj_uint_subs(win_ll_x1, tr_ll_x0); + win_ll_y1 = opj_uint_subs(win_ll_y1, tr_ll_y0); + win_hl_x0 = opj_uint_subs(win_hl_x0, tr_hl_x0); + win_hl_x1 = opj_uint_subs(win_hl_x1, tr_hl_x0); + win_lh_y0 = opj_uint_subs(win_lh_y0, tr_lh_y0); + win_lh_y1 = opj_uint_subs(win_lh_y1, tr_lh_y0); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.sn, &win_ll_x0, &win_ll_x1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.dn, &win_hl_x0, &win_hl_x1); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.sn, &win_ll_y0, &win_ll_y1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.dn, &win_lh_y0, &win_lh_y1); + + /* Compute the tile-resolution-based coordinates for the window of interest */ + if (h.cas == 0) { + win_tr_x0 = opj_uint_min(2 * win_ll_x0, 2 * win_hl_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_ll_x1, 2 * win_hl_x1 + 1), rw); + } else { + win_tr_x0 = opj_uint_min(2 * win_hl_x0, 2 * win_ll_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_hl_x1, 2 * win_ll_x1 + 1), rw); + } + + if (v.cas == 0) { + win_tr_y0 = opj_uint_min(2 * win_ll_y0, 2 * win_lh_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_ll_y1, 2 * win_lh_y1 + 1), rh); + } else { + win_tr_y0 = opj_uint_min(2 * win_lh_y0, 2 * win_ll_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_lh_y1, 2 * win_ll_y1 + 1), rh); + } + + h.win_l_x0 = win_ll_x0; + h.win_l_x1 = win_ll_x1; + h.win_h_x0 = win_hl_x0; + h.win_h_x1 = win_hl_x1; + for (j = 0; j + 3 < rh; j += 4) { + if ((j + 3 >= win_ll_y0 && j < win_ll_y1) || + (j + 3 >= win_lh_y0 + (OPJ_UINT32)v.sn && + j < win_lh_y1 + (OPJ_UINT32)v.sn)) { + opj_v4dwt_interleave_partial_h(&h, sa, j, opj_uint_min(4U, rh - j)); + opj_v4dwt_decode(&h); + if (!opj_sparse_array_int32_write(sa, + win_tr_x0, j, + win_tr_x1, j + 4, + (OPJ_INT32*)&h.wavelet[win_tr_x0].f[0], + 4, 1, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + } + } + + if (j < rh && + ((j + 3 >= win_ll_y0 && j < win_ll_y1) || + (j + 3 >= win_lh_y0 + (OPJ_UINT32)v.sn && + j < win_lh_y1 + (OPJ_UINT32)v.sn))) { + opj_v4dwt_interleave_partial_h(&h, sa, j, rh - j); + opj_v4dwt_decode(&h); + if (!opj_sparse_array_int32_write(sa, + win_tr_x0, j, + win_tr_x1, rh, + (OPJ_INT32*)&h.wavelet[win_tr_x0].f[0], + 4, 1, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + } + + v.win_l_x0 = win_ll_y0; + v.win_l_x1 = win_ll_y1; + v.win_h_x0 = win_lh_y0; + v.win_h_x1 = win_lh_y1; + for (j = win_tr_x0; j < win_tr_x1; j += 4) { + OPJ_UINT32 nb_elts = opj_uint_min(4U, win_tr_x1 - j); + + opj_v4dwt_interleave_partial_v(&v, sa, j, nb_elts); + opj_v4dwt_decode(&v); + + if (!opj_sparse_array_int32_write(sa, + j, win_tr_y0, + j + nb_elts, win_tr_y1, + (OPJ_INT32*)&h.wavelet[win_tr_y0].f[0], + 1, 4, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + } + } + + { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + } + opj_sparse_array_int32_free(sa); + + opj_aligned_free(h.wavelet); + return OPJ_TRUE; +} + + +OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres) +{ + if (p_tcd->whole_tile_decoding) { + return opj_dwt_decode_tile_97(tilec, numres); + } else { + return opj_dwt_decode_partial_97(tilec, numres); + } } diff --git a/third_party/libopenjpeg20/dwt.h b/third_party/libopenjpeg20/dwt.h index 21fe942a984e5c3b6568025fa1051f3bec677757..4f63e524a60fd75577e5b579438990cfbf6d540f 100644 --- a/third_party/libopenjpeg20/dwt.h +++ b/third_party/libopenjpeg20/dwt.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. @@ -35,8 +35,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __DWT_H -#define __DWT_H +#ifndef OPJ_DWT_H +#define OPJ_DWT_H /** @file dwt.h @brief Implementation of a discrete wavelet transform (DWT) @@ -63,10 +63,13 @@ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec); /** Inverse 5-3 wavelet transform in 2-D. Apply a reversible inverse DWT transform to a component of an image. +@param p_tcd TCD handle @param tilec Tile component information (current tile) @param numres Number of resolution levels to decode */ -OPJ_BOOL opj_dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres); +OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres); /** Get the gain of a subband for the reversible 5-3 DWT. @@ -82,18 +85,21 @@ Get the norm of a wavelet function of a subband at a specified level for the rev */ OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient); /** -Forward 9-7 wavelet transform in 2-D. +Forward 9-7 wavelet transform in 2-D. Apply an irreversible DWT transform to a component of an image. @param tilec Tile component information (current tile) */ OPJ_BOOL opj_dwt_encode_real(opj_tcd_tilecomp_t * tilec); /** -Inverse 9-7 wavelet transform in 2-D. +Inverse 9-7 wavelet transform in 2-D. Apply an irreversible inverse DWT transform to a component of an image. +@param p_tcd TCD handle @param tilec Tile component information (current tile) @param numres Number of resolution levels to decode */ -OPJ_BOOL opj_dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numres); +OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres); /** Get the gain of a subband for the irreversible 9-7 DWT. @@ -109,7 +115,7 @@ Get the norm of a wavelet function of a subband at a specified level for the irr */ OPJ_FLOAT64 opj_dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient); /** -Explicit calculation of the Quantization Stepsizes +Explicit calculation of the Quantization Stepsizes @param tccp Tile-component coding parameters @param prec Precint analyzed */ @@ -119,4 +125,4 @@ void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec); /*@}*/ -#endif /* __DWT_H */ +#endif /* OPJ_DWT_H */ diff --git a/third_party/libopenjpeg20/event.c b/third_party/libopenjpeg20/event.c index b6034b42d0a3cf3ed6c173a90afae61a0d09be99..aad9d76c98d425451e4c69cd3d7375304addaecf 100644 --- a/third_party/libopenjpeg20/event.c +++ b/third_party/libopenjpeg20/event.c @@ -1,11 +1,11 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -40,14 +40,17 @@ #ifdef OPJ_CODE_NOT_USED #ifndef _WIN32 static char* -i2a(unsigned i, char *a, unsigned r) { - if (i/r > 0) a = i2a(i/r,a,r); - *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r]; - return a+1; +i2a(unsigned i, char *a, unsigned r) +{ + if (i / r > 0) { + a = i2a(i / r, a, r); + } + *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % r]; + return a + 1; } -/** - Transforms integer i into an ascii string and stores the result in a; +/** + Transforms integer i into an ascii string and stores the result in a; string is encoded in the base indicated by r. @param i Number to be converted @param a String result @@ -55,14 +58,16 @@ i2a(unsigned i, char *a, unsigned r) { @return Returns a */ static char * -_itoa(int i, char *a, int r) { - r = ((r < 2) || (r > 36)) ? 10 : r; - if(i < 0) { - *a = '-'; - *i2a(-i, a+1, r) = 0; - } - else *i2a(i, a, r) = 0; - return a; +_itoa(int i, char *a, int r) +{ + r = ((r < 2) || (r > 36)) ? 10 : r; + if (i < 0) { + *a = '-'; + *i2a(-i, a + 1, r) = 0; + } else { + *i2a(i, a, r) = 0; + } + return a; } #endif /* !_WIN32 */ @@ -73,7 +78,7 @@ _itoa(int i, char *a, int r) { * Default callback function. * Do nothing. */ -static void opj_default_callback (const char *msg, void *client_data) +static void opj_default_callback(const char *msg, void *client_data) { OPJ_ARG_NOT_USED(msg); OPJ_ARG_NOT_USED(client_data); @@ -83,64 +88,64 @@ static void opj_default_callback (const char *msg, void *client_data) /* ----------------------------------------------------------------------- */ -OPJ_BOOL opj_event_msg(opj_event_mgr_t* p_event_mgr, OPJ_INT32 event_type, const char *fmt, ...) { +OPJ_BOOL opj_event_msg(opj_event_mgr_t* p_event_mgr, OPJ_INT32 event_type, + const char *fmt, ...) +{ #define OPJ_MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */ - opj_msg_callback msg_handler = 00; - void * l_data = 00; + opj_msg_callback msg_handler = 00; + void * l_data = 00; - if(p_event_mgr != 00) { - switch(event_type) { - case EVT_ERROR: - msg_handler = p_event_mgr->error_handler; - l_data = p_event_mgr->m_error_data; - break; - case EVT_WARNING: - msg_handler = p_event_mgr->warning_handler; - l_data = p_event_mgr->m_warning_data; - break; - case EVT_INFO: - msg_handler = p_event_mgr->info_handler; - l_data = p_event_mgr->m_info_data; - break; - default: - break; - } - if(msg_handler == 00) { - return OPJ_FALSE; - } - } else { - return OPJ_FALSE; - } + if (p_event_mgr != 00) { + switch (event_type) { + case EVT_ERROR: + msg_handler = p_event_mgr->error_handler; + l_data = p_event_mgr->m_error_data; + break; + case EVT_WARNING: + msg_handler = p_event_mgr->warning_handler; + l_data = p_event_mgr->m_warning_data; + break; + case EVT_INFO: + msg_handler = p_event_mgr->info_handler; + l_data = p_event_mgr->m_info_data; + break; + default: + break; + } + if (msg_handler == 00) { + return OPJ_FALSE; + } + } else { + return OPJ_FALSE; + } - if ((fmt != 00) && (p_event_mgr != 00)) { - va_list arg; - size_t str_length/*, i, j*/; /* UniPG */ - char message[OPJ_MSG_SIZE]; - memset(message, 0, OPJ_MSG_SIZE); - /* initialize the optional parameter list */ - va_start(arg, fmt); - /* check the length of the format string */ - str_length = (strlen(fmt) > OPJ_MSG_SIZE) ? OPJ_MSG_SIZE : strlen(fmt); - (void)str_length; - /* parse the format string and put the result in 'message' */ - vsnprintf(message, OPJ_MSG_SIZE, fmt, arg); /* UniPG */ - /* deinitialize the optional parameter list */ - va_end(arg); + if ((fmt != 00) && (p_event_mgr != 00)) { + va_list arg; + char message[OPJ_MSG_SIZE]; + memset(message, 0, OPJ_MSG_SIZE); + /* initialize the optional parameter list */ + va_start(arg, fmt); + /* parse the format string and put the result in 'message' */ + vsnprintf(message, OPJ_MSG_SIZE, fmt, arg); + /* force zero termination for Windows _vsnprintf() of old MSVC */ + message[OPJ_MSG_SIZE - 1] = '\0'; + /* deinitialize the optional parameter list */ + va_end(arg); - /* output the message to the user program */ - msg_handler(message, l_data); - } + /* output the message to the user program */ + msg_handler(message, l_data); + } - return OPJ_TRUE; + return OPJ_TRUE; } void opj_set_default_event_handler(opj_event_mgr_t * p_manager) { - p_manager->m_error_data = 00; - p_manager->m_warning_data = 00; - p_manager->m_info_data = 00; - p_manager->error_handler = opj_default_callback; - p_manager->info_handler = opj_default_callback; - p_manager->warning_handler = opj_default_callback; + p_manager->m_error_data = 00; + p_manager->m_warning_data = 00; + p_manager->m_info_data = 00; + p_manager->error_handler = opj_default_callback; + p_manager->info_handler = opj_default_callback; + p_manager->warning_handler = opj_default_callback; } diff --git a/third_party/libopenjpeg20/event.h b/third_party/libopenjpeg20/event.h index fa8604ed0b7dc3bead0a432f1a9720c3028e7c8b..d880388d0741fa0a0b9b48ccad1576be2ef0c3cd 100644 --- a/third_party/libopenjpeg20/event.h +++ b/third_party/libopenjpeg20/event.h @@ -1,11 +1,11 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -30,8 +30,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __EVENT_H -#define __EVENT_H +#ifndef OPJ_EVENT_H +#define OPJ_EVENT_H /** @file event.h @brief Implementation of a event callback system @@ -40,33 +40,32 @@ The functions in EVENT.C have for goal to send output messages (errors, warnings */ /** Message handler object -used for +used for <ul> <li>Error messages <li>Warning messages <li>Debugging messages </ul> */ -typedef struct opj_event_mgr -{ - /** Data to call the event manager upon */ - void * m_error_data; - /** Data to call the event manager upon */ - void * m_warning_data; - /** Data to call the event manager upon */ - void * m_info_data; - /** Error message callback if available, NULL otherwise */ - opj_msg_callback error_handler; - /** Warning message callback if available, NULL otherwise */ - opj_msg_callback warning_handler; - /** Debug message callback if available, NULL otherwise */ - opj_msg_callback info_handler; +typedef struct opj_event_mgr { + /** Data to call the event manager upon */ + void * m_error_data; + /** Data to call the event manager upon */ + void * m_warning_data; + /** Data to call the event manager upon */ + void * m_info_data; + /** Error message callback if available, NULL otherwise */ + opj_msg_callback error_handler; + /** Warning message callback if available, NULL otherwise */ + opj_msg_callback warning_handler; + /** Debug message callback if available, NULL otherwise */ + opj_msg_callback info_handler; } opj_event_mgr_t; -#define EVT_ERROR 1 /**< Error event type */ -#define EVT_WARNING 2 /**< Warning event type */ -#define EVT_INFO 4 /**< Debug event type */ +#define EVT_ERROR 1 /**< Error event type */ +#define EVT_WARNING 2 /**< Warning event type */ +#define EVT_INFO 4 /**< Debug event type */ /** @defgroup EVENT EVENT - Implementation of a event callback system */ /*@{*/ @@ -81,13 +80,14 @@ typedef struct opj_event_mgr /** * Write formatted data to a string and send the string to a user callback. * - * @param event_mgr Event handler - * @param event_type Event type or callback to use to send the message - * @param fmt Format-control string (plus optional arguments) + * @param event_mgr Event handler + * @param event_type Event type or callback to use to send the message + * @param fmt Format-control string (plus optional arguments) * * @return Returns true if successful, returns false otherwise */ -OPJ_BOOL opj_event_msg(opj_event_mgr_t* event_mgr, OPJ_INT32 event_type, const char *fmt, ...); +OPJ_BOOL opj_event_msg(opj_event_mgr_t* event_mgr, OPJ_INT32 event_type, + const char *fmt, ...); /* ----------------------------------------------------------------------- */ /** @@ -105,4 +105,4 @@ void opj_set_default_event_handler(opj_event_mgr_t * p_manager); /*@}*/ -#endif /* __EVENT_H */ +#endif /* OPJ_EVENT_H */ diff --git a/third_party/libopenjpeg20/function_list.c b/third_party/libopenjpeg20/function_list.c index a7ea11d59b28c7cbd1df0b00694d8617b0a37f45..e1c1af3897c72599774e28e20783a87efb4d9801 100644 --- a/third_party/libopenjpeg20/function_list.c +++ b/third_party/libopenjpeg20/function_list.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -38,80 +38,80 @@ opj_procedure_list_t * opj_procedure_list_create() { - /* memory allocation */ - opj_procedure_list_t * l_validation = (opj_procedure_list_t *) opj_calloc(1,sizeof(opj_procedure_list_t)); - if (! l_validation) - { - return 00; - } - /* initialization */ - l_validation->m_nb_max_procedures = OPJ_VALIDATION_SIZE; - l_validation->m_procedures = (opj_procedure*)opj_calloc(OPJ_VALIDATION_SIZE, sizeof(opj_procedure)); - if (! l_validation->m_procedures) - { - opj_free(l_validation); - return 00; - } - return l_validation; + /* memory allocation */ + opj_procedure_list_t * l_validation = (opj_procedure_list_t *) opj_calloc(1, + sizeof(opj_procedure_list_t)); + if (! l_validation) { + return 00; + } + /* initialization */ + l_validation->m_nb_max_procedures = OPJ_VALIDATION_SIZE; + l_validation->m_procedures = (opj_procedure*)opj_calloc(OPJ_VALIDATION_SIZE, + sizeof(opj_procedure)); + if (! l_validation->m_procedures) { + opj_free(l_validation); + return 00; + } + return l_validation; } void opj_procedure_list_destroy(opj_procedure_list_t * p_list) { - if (! p_list) - { - return; - } - /* initialization */ - if (p_list->m_procedures) - { - opj_free(p_list->m_procedures); - } - opj_free(p_list); + if (! p_list) { + return; + } + /* initialization */ + if (p_list->m_procedures) { + opj_free(p_list->m_procedures); + } + opj_free(p_list); } -OPJ_BOOL opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager ) +OPJ_BOOL opj_procedure_list_add_procedure(opj_procedure_list_t * + p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager) { - - assert(p_manager != NULL); - - if (p_validation_list->m_nb_max_procedures == p_validation_list->m_nb_procedures) - { - opj_procedure * new_procedures; - p_validation_list->m_nb_max_procedures += OPJ_VALIDATION_SIZE; - new_procedures = (opj_procedure*)opj_realloc( - p_validation_list->m_procedures, - p_validation_list->m_nb_max_procedures * sizeof(opj_procedure)); - if (! new_procedures) - { - opj_free(p_validation_list->m_procedures); - p_validation_list->m_nb_max_procedures = 0; - p_validation_list->m_nb_procedures = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add a new validation procedure\n"); - return OPJ_FALSE; - } - else - { - p_validation_list->m_procedures = new_procedures; - } + assert(p_manager != NULL); + + if (p_validation_list->m_nb_max_procedures == + p_validation_list->m_nb_procedures) { + opj_procedure * new_procedures; + + p_validation_list->m_nb_max_procedures += OPJ_VALIDATION_SIZE; + new_procedures = (opj_procedure*)opj_realloc( + p_validation_list->m_procedures, + p_validation_list->m_nb_max_procedures * sizeof(opj_procedure)); + if (! new_procedures) { + opj_free(p_validation_list->m_procedures); + p_validation_list->m_nb_max_procedures = 0; + p_validation_list->m_nb_procedures = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to add a new validation procedure\n"); + return OPJ_FALSE; + } else { + p_validation_list->m_procedures = new_procedures; } - p_validation_list->m_procedures[p_validation_list->m_nb_procedures] = p_procedure; - ++p_validation_list->m_nb_procedures; + } + p_validation_list->m_procedures[p_validation_list->m_nb_procedures] = + p_procedure; + ++p_validation_list->m_nb_procedures; - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_UINT32 opj_procedure_list_get_nb_procedures (opj_procedure_list_t * p_validation_list) +OPJ_UINT32 opj_procedure_list_get_nb_procedures(opj_procedure_list_t * + p_validation_list) { - return p_validation_list->m_nb_procedures; + return p_validation_list->m_nb_procedures; } -opj_procedure* opj_procedure_list_get_first_procedure (opj_procedure_list_t * p_validation_list) +opj_procedure* opj_procedure_list_get_first_procedure(opj_procedure_list_t * + p_validation_list) { - return p_validation_list->m_procedures; + return p_validation_list->m_procedures; } -void opj_procedure_list_clear (opj_procedure_list_t * p_validation_list) +void opj_procedure_list_clear(opj_procedure_list_t * p_validation_list) { - p_validation_list->m_nb_procedures = 0; + p_validation_list->m_nb_procedures = 0; } diff --git a/third_party/libopenjpeg20/function_list.h b/third_party/libopenjpeg20/function_list.h index ab091b7be102286100baf1b7d9f5413a52e585c6..81a3954a1630c6a079ac2b4778a892a23c1af186 100644 --- a/third_party/libopenjpeg20/function_list.h +++ b/third_party/libopenjpeg20/function_list.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -29,10 +29,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __FUNCTION_LIST_H -#define __FUNCTION_LIST_H +#ifndef OPJ_FUNCTION_LIST_H +#define OPJ_FUNCTION_LIST_H -/** +/** * @file function_list.h * @brief Implementation of a list of procedures. @@ -54,20 +54,19 @@ typedef void (*opj_procedure)(void); /** * A list of procedures. */ -typedef struct opj_procedure_list -{ - /** - * The number of validation procedures. - */ - OPJ_UINT32 m_nb_procedures; - /** - * The number of the array of validation procedures. - */ - OPJ_UINT32 m_nb_max_procedures; - /** - * The array of procedures. - */ - opj_procedure * m_procedures; +typedef struct opj_procedure_list { + /** + * The number of validation procedures. + */ + OPJ_UINT32 m_nb_procedures; + /** + * The number of the array of validation procedures. + */ + OPJ_UINT32 m_nb_max_procedures; + /** + * The array of procedures. + */ + opj_procedure * m_procedures; } opj_procedure_list_t; @@ -76,7 +75,7 @@ typedef struct opj_procedure_list /** * Creates a validation list. * - * @return the newly created validation list. + * @return the newly created validation list. */ opj_procedure_list_t * opj_procedure_list_create(void); @@ -90,42 +89,46 @@ void opj_procedure_list_destroy(opj_procedure_list_t * p_list); /** * Adds a new validation procedure. * - * @param p_validation_list the list of procedure to modify. - * @param p_procedure the procedure to add. + * @param p_validation_list the list of procedure to modify. + * @param p_procedure the procedure to add. + * @param p_manager the user event manager. * - * @return OPJ_TRUE if the procedure could be added. + * @return OPJ_TRUE if the procedure could be added. */ -OPJ_BOOL opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager); +OPJ_BOOL opj_procedure_list_add_procedure(opj_procedure_list_t * + p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager); /** * Gets the number of validation procedures. * - * @param p_validation_list the list of procedure to modify. + * @param p_validation_list the list of procedure to modify. * * @return the number of validation procedures. */ -OPJ_UINT32 opj_procedure_list_get_nb_procedures (opj_procedure_list_t * p_validation_list); +OPJ_UINT32 opj_procedure_list_get_nb_procedures(opj_procedure_list_t * + p_validation_list); /** * Gets the pointer on the first validation procedure. This function is similar to the C++ * iterator class to iterate through all the procedures inside the validation list. * the caller does not take ownership of the pointer. * - * @param p_validation_list the list of procedure to get the first procedure from. + * @param p_validation_list the list of procedure to get the first procedure from. * - * @return a pointer to the first procedure. + * @return a pointer to the first procedure. */ -opj_procedure* opj_procedure_list_get_first_procedure (opj_procedure_list_t * p_validation_list); +opj_procedure* opj_procedure_list_get_first_procedure(opj_procedure_list_t * + p_validation_list); /** * Clears the list of validation procedures. * - * @param p_validation_list the list of procedure to clear. + * @param p_validation_list the list of procedure to clear. * */ -void opj_procedure_list_clear (opj_procedure_list_t * p_validation_list); +void opj_procedure_list_clear(opj_procedure_list_t * p_validation_list); /*@}*/ -#endif /* __FUNCTION_LIST_H */ +#endif /* OPJ_FUNCTION_LIST_H */ diff --git a/third_party/libopenjpeg20/image.c b/third_party/libopenjpeg20/image.c index 23462f05ff4d1638f88569942a3968ec667bf57f..13bcb8e45f69149fcb7063b6226de07b7b6f2d2f 100644 --- a/third_party/libopenjpeg20/image.c +++ b/third_party/libopenjpeg20/image.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -31,109 +31,126 @@ #include "opj_includes.h" -opj_image_t* opj_image_create0(void) { - opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t)); - return image; +opj_image_t* opj_image_create0(void) +{ + opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t)); + return image; } -opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) { - OPJ_UINT32 compno; - opj_image_t *image = NULL; - - image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t)); - if(image) { - image->color_space = clrspc; - image->numcomps = numcmpts; - /* allocate memory for the per-component information */ - image->comps = (opj_image_comp_t*)opj_calloc(1,image->numcomps * sizeof(opj_image_comp_t)); - if(!image->comps) { - /* TODO replace with event manager, breaks API */ - /* fprintf(stderr,"Unable to allocate memory for image.\n"); */ - opj_image_destroy(image); - return NULL; - } - /* create the individual image components */ - for(compno = 0; compno < numcmpts; compno++) { - opj_image_comp_t *comp = &image->comps[compno]; - comp->dx = cmptparms[compno].dx; - comp->dy = cmptparms[compno].dy; - comp->w = cmptparms[compno].w; - comp->h = cmptparms[compno].h; - comp->x0 = cmptparms[compno].x0; - comp->y0 = cmptparms[compno].y0; - comp->prec = cmptparms[compno].prec; - comp->bpp = cmptparms[compno].bpp; - comp->sgnd = cmptparms[compno].sgnd; - comp->data = (OPJ_INT32*) opj_calloc(comp->w * comp->h, sizeof(OPJ_INT32)); - if(!comp->data) { - /* TODO replace with event manager, breaks API */ - /* fprintf(stderr,"Unable to allocate memory for image.\n"); */ - opj_image_destroy(image); - return NULL; - } - } - } - - return image; +opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) +{ + OPJ_UINT32 compno; + opj_image_t *image = NULL; + + image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t)); + if (image) { + image->color_space = clrspc; + image->numcomps = numcmpts; + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_calloc(1, + image->numcomps * sizeof(opj_image_comp_t)); + if (!image->comps) { + /* TODO replace with event manager, breaks API */ + /* fprintf(stderr,"Unable to allocate memory for image.\n"); */ + opj_image_destroy(image); + return NULL; + } + /* create the individual image components */ + for (compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->bpp = cmptparms[compno].bpp; + comp->sgnd = cmptparms[compno].sgnd; + if (comp->h != 0 && + (OPJ_SIZE_T)comp->w > SIZE_MAX / comp->h / sizeof(OPJ_INT32)) { + /* TODO event manager */ + opj_image_destroy(image); + return NULL; + } + comp->data = (OPJ_INT32*) opj_image_data_alloc( + (size_t)comp->w * comp->h * sizeof(OPJ_INT32)); + if (!comp->data) { + /* TODO replace with event manager, breaks API */ + /* fprintf(stderr,"Unable to allocate memory for image.\n"); */ + opj_image_destroy(image); + return NULL; + } + memset(comp->data, 0, (size_t)comp->w * comp->h * sizeof(OPJ_INT32)); + } + } + + return image; } -void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) { - if(image) { - if(image->comps) { - OPJ_UINT32 compno; - - /* image components */ - for(compno = 0; compno < image->numcomps; compno++) { - opj_image_comp_t *image_comp = &(image->comps[compno]); - if(image_comp->data) { - opj_free(image_comp->data); - } - } - opj_free(image->comps); - } - - if(image->icc_profile_buf) { - opj_free(image->icc_profile_buf); - } - - opj_free(image); - } +void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) +{ + if (image) { + if (image->comps) { + OPJ_UINT32 compno; + + /* image components */ + for (compno = 0; compno < image->numcomps; compno++) { + opj_image_comp_t *image_comp = &(image->comps[compno]); + if (image_comp->data) { + opj_image_data_free(image_comp->data); + } + } + opj_free(image->comps); + } + + if (image->icc_profile_buf) { + opj_free(image->icc_profile_buf); + } + + opj_free(image); + } } /** * Updates the components characteristics of the image from the coding parameters. * - * @param p_image_header the image header to update. - * @param p_cp the coding parameters from which to update the image. + * @param p_image_header the image header to update. + * @param p_cp the coding parameters from which to update the image. */ -void opj_image_comp_header_update(opj_image_t * p_image_header, const struct opj_cp * p_cp) +void opj_image_comp_header_update(opj_image_t * p_image_header, + const struct opj_cp * p_cp) { - OPJ_UINT32 i, l_width, l_height; - OPJ_UINT32 l_x0, l_y0, l_x1, l_y1; - OPJ_UINT32 l_comp_x0, l_comp_y0, l_comp_x1, l_comp_y1; - opj_image_comp_t* l_img_comp = NULL; - - l_x0 = opj_uint_max(p_cp->tx0 , p_image_header->x0); - l_y0 = opj_uint_max(p_cp->ty0 , p_image_header->y0); - l_x1 = p_cp->tx0 + (p_cp->tw - 1U) * p_cp->tdx; /* validity of p_cp members used here checked in opj_j2k_read_siz. Can't overflow. */ - l_y1 = p_cp->ty0 + (p_cp->th - 1U) * p_cp->tdy; /* can't overflow */ - l_x1 = opj_uint_min(opj_uint_adds(l_x1, p_cp->tdx), p_image_header->x1); /* use add saturated to prevent overflow */ - l_y1 = opj_uint_min(opj_uint_adds(l_y1, p_cp->tdy), p_image_header->y1); /* use add saturated to prevent overflow */ - - l_img_comp = p_image_header->comps; - for (i = 0; i < p_image_header->numcomps; ++i) { - l_comp_x0 = opj_uint_ceildiv(l_x0, l_img_comp->dx); - l_comp_y0 = opj_uint_ceildiv(l_y0, l_img_comp->dy); - l_comp_x1 = opj_uint_ceildiv(l_x1, l_img_comp->dx); - l_comp_y1 = opj_uint_ceildiv(l_y1, l_img_comp->dy); - l_width = opj_uint_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor); - l_height = opj_uint_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor); - l_img_comp->w = l_width; - l_img_comp->h = l_height; - l_img_comp->x0 = l_comp_x0; - l_img_comp->y0 = l_comp_y0; - ++l_img_comp; - } + OPJ_UINT32 i, l_width, l_height; + OPJ_UINT32 l_x0, l_y0, l_x1, l_y1; + OPJ_UINT32 l_comp_x0, l_comp_y0, l_comp_x1, l_comp_y1; + opj_image_comp_t* l_img_comp = NULL; + + l_x0 = opj_uint_max(p_cp->tx0, p_image_header->x0); + l_y0 = opj_uint_max(p_cp->ty0, p_image_header->y0); + l_x1 = p_cp->tx0 + (p_cp->tw - 1U) * + p_cp->tdx; /* validity of p_cp members used here checked in opj_j2k_read_siz. Can't overflow. */ + l_y1 = p_cp->ty0 + (p_cp->th - 1U) * p_cp->tdy; /* can't overflow */ + l_x1 = opj_uint_min(opj_uint_adds(l_x1, p_cp->tdx), + p_image_header->x1); /* use add saturated to prevent overflow */ + l_y1 = opj_uint_min(opj_uint_adds(l_y1, p_cp->tdy), + p_image_header->y1); /* use add saturated to prevent overflow */ + + l_img_comp = p_image_header->comps; + for (i = 0; i < p_image_header->numcomps; ++i) { + l_comp_x0 = opj_uint_ceildiv(l_x0, l_img_comp->dx); + l_comp_y0 = opj_uint_ceildiv(l_y0, l_img_comp->dy); + l_comp_x1 = opj_uint_ceildiv(l_x1, l_img_comp->dx); + l_comp_y1 = opj_uint_ceildiv(l_y1, l_img_comp->dy); + l_width = opj_uint_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor); + l_height = opj_uint_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor); + l_img_comp->w = l_width; + l_img_comp->h = l_height; + l_img_comp->x0 = l_comp_x0; + l_img_comp->y0 = l_comp_y0; + ++l_img_comp; + } } @@ -141,102 +158,107 @@ void opj_image_comp_header_update(opj_image_t * p_image_header, const struct opj * Copy only header of image and its component header (no data are copied) * if dest image have data, they will be freed * - * @param p_image_src the src image - * @param p_image_dest the dest image + * @param p_image_src the src image + * @param p_image_dest the dest image * */ -void opj_copy_image_header(const opj_image_t* p_image_src, opj_image_t* p_image_dest) +void opj_copy_image_header(const opj_image_t* p_image_src, + opj_image_t* p_image_dest) { - OPJ_UINT32 compno; - - /* preconditions */ - assert(p_image_src != 00); - assert(p_image_dest != 00); - - p_image_dest->x0 = p_image_src->x0; - p_image_dest->y0 = p_image_src->y0; - p_image_dest->x1 = p_image_src->x1; - p_image_dest->y1 = p_image_src->y1; - - if (p_image_dest->comps){ - for(compno = 0; compno < p_image_dest->numcomps; compno++) { - opj_image_comp_t *image_comp = &(p_image_dest->comps[compno]); - if(image_comp->data) { - opj_free(image_comp->data); - } - } - opj_free(p_image_dest->comps); - p_image_dest->comps = NULL; - } - - p_image_dest->numcomps = p_image_src->numcomps; - - p_image_dest->comps = (opj_image_comp_t*) opj_malloc(p_image_dest->numcomps * sizeof(opj_image_comp_t)); - if (!p_image_dest->comps){ - p_image_dest->comps = NULL; - p_image_dest->numcomps = 0; - return; - } - - for (compno=0; compno < p_image_dest->numcomps; compno++){ - memcpy( &(p_image_dest->comps[compno]), - &(p_image_src->comps[compno]), - sizeof(opj_image_comp_t)); - p_image_dest->comps[compno].data = NULL; - } - - p_image_dest->color_space = p_image_src->color_space; - p_image_dest->icc_profile_len = p_image_src->icc_profile_len; - - if (p_image_dest->icc_profile_len) { - p_image_dest->icc_profile_buf = (OPJ_BYTE*)opj_malloc(p_image_dest->icc_profile_len); - if (!p_image_dest->icc_profile_buf){ - p_image_dest->icc_profile_buf = NULL; - p_image_dest->icc_profile_len = 0; - return; - } - memcpy( p_image_dest->icc_profile_buf, - p_image_src->icc_profile_buf, - p_image_src->icc_profile_len); - } - else - p_image_dest->icc_profile_buf = NULL; - - return; + OPJ_UINT32 compno; + + /* preconditions */ + assert(p_image_src != 00); + assert(p_image_dest != 00); + + p_image_dest->x0 = p_image_src->x0; + p_image_dest->y0 = p_image_src->y0; + p_image_dest->x1 = p_image_src->x1; + p_image_dest->y1 = p_image_src->y1; + + if (p_image_dest->comps) { + for (compno = 0; compno < p_image_dest->numcomps; compno++) { + opj_image_comp_t *image_comp = &(p_image_dest->comps[compno]); + if (image_comp->data) { + opj_image_data_free(image_comp->data); + } + } + opj_free(p_image_dest->comps); + p_image_dest->comps = NULL; + } + + p_image_dest->numcomps = p_image_src->numcomps; + + p_image_dest->comps = (opj_image_comp_t*) opj_malloc(p_image_dest->numcomps * + sizeof(opj_image_comp_t)); + if (!p_image_dest->comps) { + p_image_dest->comps = NULL; + p_image_dest->numcomps = 0; + return; + } + + for (compno = 0; compno < p_image_dest->numcomps; compno++) { + memcpy(&(p_image_dest->comps[compno]), + &(p_image_src->comps[compno]), + sizeof(opj_image_comp_t)); + p_image_dest->comps[compno].data = NULL; + } + + p_image_dest->color_space = p_image_src->color_space; + p_image_dest->icc_profile_len = p_image_src->icc_profile_len; + + if (p_image_dest->icc_profile_len) { + p_image_dest->icc_profile_buf = (OPJ_BYTE*)opj_malloc( + p_image_dest->icc_profile_len); + if (!p_image_dest->icc_profile_buf) { + p_image_dest->icc_profile_buf = NULL; + p_image_dest->icc_profile_len = 0; + return; + } + memcpy(p_image_dest->icc_profile_buf, + p_image_src->icc_profile_buf, + p_image_src->icc_profile_len); + } else { + p_image_dest->icc_profile_buf = NULL; + } + + return; } -opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) { - OPJ_UINT32 compno; - opj_image_t *image = 00; - - image = (opj_image_t*) opj_calloc(1,sizeof(opj_image_t)); - if (image) - { - - image->color_space = clrspc; - image->numcomps = numcmpts; - - /* allocate memory for the per-component information */ - image->comps = (opj_image_comp_t*)opj_calloc(image->numcomps, sizeof(opj_image_comp_t)); - if (!image->comps) { - opj_image_destroy(image); - return 00; - } - - /* create the individual image components */ - for(compno = 0; compno < numcmpts; compno++) { - opj_image_comp_t *comp = &image->comps[compno]; - comp->dx = cmptparms[compno].dx; - comp->dy = cmptparms[compno].dy; - comp->w = cmptparms[compno].w; - comp->h = cmptparms[compno].h; - comp->x0 = cmptparms[compno].x0; - comp->y0 = cmptparms[compno].y0; - comp->prec = cmptparms[compno].prec; - comp->sgnd = cmptparms[compno].sgnd; - comp->data = 0; - } - } - - return image; +opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) +{ + OPJ_UINT32 compno; + opj_image_t *image = 00; + + image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t)); + if (image) { + + image->color_space = clrspc; + image->numcomps = numcmpts; + + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_calloc(image->numcomps, + sizeof(opj_image_comp_t)); + if (!image->comps) { + opj_image_destroy(image); + return 00; + } + + /* create the individual image components */ + for (compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->sgnd = cmptparms[compno].sgnd; + comp->data = 0; + } + } + + return image; } diff --git a/third_party/libopenjpeg20/image.h b/third_party/libopenjpeg20/image.h index e0e2772d406472c782d081af55f235d6dc554000..bad83c61359b2f4cac5676bd435540637dec7e5e 100644 --- a/third_party/libopenjpeg20/image.h +++ b/third_party/libopenjpeg20/image.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -28,8 +28,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __IMAGE_H -#define __IMAGE_H +#ifndef OPJ_IMAGE_H +#define OPJ_IMAGE_H /** @file image.h @brief Implementation of operations on images (IMAGE) @@ -55,14 +55,16 @@ opj_image_t* opj_image_create0(void); /** * Updates the components characteristics of the image from the coding parameters. * - * @param p_image_header the image header to update. - * @param p_cp the coding parameters from which to update the image. + * @param p_image_header the image header to update. + * @param p_cp the coding parameters from which to update the image. */ -void opj_image_comp_header_update(opj_image_t * p_image, const struct opj_cp* p_cp); +void opj_image_comp_header_update(opj_image_t * p_image, + const struct opj_cp* p_cp); -void opj_copy_image_header(const opj_image_t* p_image_src, opj_image_t* p_image_dest); +void opj_copy_image_header(const opj_image_t* p_image_src, + opj_image_t* p_image_dest); /*@}*/ -#endif /* __IMAGE_H */ +#endif /* OPJ_IMAGE_H */ diff --git a/third_party/libopenjpeg20/indexbox_manager.h b/third_party/libopenjpeg20/indexbox_manager.h index ebcde8fec4c580fa9c2907a13905c1d4444bdc52..238114bd133f3624bbb565ee900869bf97df8986 100644 --- a/third_party/libopenjpeg20/indexbox_manager.h +++ b/third_party/libopenjpeg20/indexbox_manager.h @@ -56,7 +56,7 @@ #define JPIP_PHLD 0x70686c64 /* Place holder */ -/* +/* * Write tile-part Index table box (superbox) * * @param[in] coff offset of j2k codestream @@ -65,11 +65,12 @@ * @param[in] cio file output handle * @return length of tpix box */ -int opj_write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_tpix(int coff, opj_codestream_info_t cstr_info, int j2klen, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -/* +/* * Write tile header index table box (superbox) * * @param[in] coff offset of j2k codestream @@ -77,10 +78,11 @@ int opj_write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_s * @param[in] cio file output handle * @return length of thix box */ -int opj_write_thix( int coff, opj_codestream_info_t cstr_info, opj_stream_private_t *cio, opj_event_mgr_t * p_manager ); +int opj_write_thix(int coff, opj_codestream_info_t cstr_info, + opj_stream_private_t *cio, opj_event_mgr_t * p_manager); -/* +/* * Write precinct packet index table box (superbox) * * @param[in] coff offset of j2k codestream @@ -90,11 +92,12 @@ int opj_write_thix( int coff, opj_codestream_info_t cstr_info, opj_stream_privat * @param[in] cio file output handle * @return length of ppix box */ -int opj_write_ppix( int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_ppix(int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -/* +/* * Write packet header index table box (superbox) * * @param[in] coff offset of j2k codestream @@ -104,10 +107,11 @@ int opj_write_ppix( int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, * @param[in] cio file output handle * @return length of ppix box */ -int opj_write_phix( int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_phix(int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -/* +/* * Write manifest box (box) * * @param[in] second number to be visited @@ -116,13 +120,13 @@ int opj_write_phix( int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, * @param[in] cio file output handle */ -void opj_write_manf(int second, - int v, - opj_jp2_box_t *box, +void opj_write_manf(int second, + int v, + opj_jp2_box_t *box, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); + opj_event_mgr_t * p_manager); -/* +/* * Write main header index table (box) * * @param[in] coff offset of j2k codestream @@ -130,19 +134,24 @@ void opj_write_manf(int second, * @param[in] cio file output handle * @return length of mainmhix box */ -int opj_write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_mainmhix(int coff, opj_codestream_info_t cstr_info, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -int opj_write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_phixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -int opj_write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_ppixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -int opj_write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_tilemhix(int coff, opj_codestream_info_t cstr_info, int tileno, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -int opj_write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +int opj_write_tpixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); #endif /* !INDEXBOX_MANAGER_H_ */ diff --git a/third_party/libopenjpeg20/invert.c b/third_party/libopenjpeg20/invert.c index 7efaf6eca24f2e7c7680dea7a6f69a50eb5386d6..89f607155fd40d8f625a4f7bb804de8b208f2ef7 100644 --- a/third_party/libopenjpeg20/invert.c +++ b/third_party/libopenjpeg20/invert.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -31,33 +31,33 @@ #include "opj_includes.h" -/** +/** * LUP decomposition */ static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix, - OPJ_UINT32 * permutations, + OPJ_UINT32 * permutations, OPJ_FLOAT32 * p_swap_area, OPJ_UINT32 nb_compo); -/** +/** * LUP solving */ -static void opj_lupSolve(OPJ_FLOAT32 * pResult, - OPJ_FLOAT32* pMatrix, - OPJ_FLOAT32* pVector, - OPJ_UINT32* pPermutations, +static void opj_lupSolve(OPJ_FLOAT32 * pResult, + OPJ_FLOAT32* pMatrix, + OPJ_FLOAT32* pVector, + OPJ_UINT32* pPermutations, OPJ_UINT32 nb_compo, OPJ_FLOAT32 * p_intermediate_data); -/** +/** *LUP inversion (call with the result of lupDecompose) */ -static void opj_lupInvert ( OPJ_FLOAT32 * pSrcMatrix, - OPJ_FLOAT32 * pDestMatrix, - OPJ_UINT32 nb_compo, - OPJ_UINT32 * pPermutations, - OPJ_FLOAT32 * p_src_temp, - OPJ_FLOAT32 * p_dest_temp, - OPJ_FLOAT32 * p_swap_area); +static void opj_lupInvert(OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 nb_compo, + OPJ_UINT32 * pPermutations, + OPJ_FLOAT32 * p_src_temp, + OPJ_FLOAT32 * p_dest_temp, + OPJ_FLOAT32 * p_swap_area); /* ========================================================== @@ -68,32 +68,33 @@ static void opj_lupInvert ( OPJ_FLOAT32 * pSrcMatrix, * Matrix inversion. */ OPJ_BOOL opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix, - OPJ_FLOAT32 * pDestMatrix, + OPJ_FLOAT32 * pDestMatrix, OPJ_UINT32 nb_compo) { - OPJ_BYTE * l_data = 00; - OPJ_UINT32 l_permutation_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_UINT32); - OPJ_UINT32 l_swap_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - OPJ_UINT32 l_total_size = l_permutation_size + 3 * l_swap_size; - OPJ_UINT32 * lPermutations = 00; - OPJ_FLOAT32 * l_double_data = 00; - - l_data = (OPJ_BYTE *) opj_malloc(l_total_size); - if (l_data == 0) { - return OPJ_FALSE; - } - lPermutations = (OPJ_UINT32 *) l_data; - l_double_data = (OPJ_FLOAT32 *) (l_data + l_permutation_size); - memset(lPermutations,0,l_permutation_size); - - if(! opj_lupDecompose(pSrcMatrix,lPermutations,l_double_data,nb_compo)) { - opj_free(l_data); - return OPJ_FALSE; - } - - opj_lupInvert(pSrcMatrix,pDestMatrix,nb_compo,lPermutations,l_double_data,l_double_data + nb_compo,l_double_data + 2*nb_compo); - opj_free(l_data); - + OPJ_BYTE * l_data = 00; + OPJ_UINT32 l_permutation_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_UINT32); + OPJ_UINT32 l_swap_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + OPJ_UINT32 l_total_size = l_permutation_size + 3 * l_swap_size; + OPJ_UINT32 * lPermutations = 00; + OPJ_FLOAT32 * l_double_data = 00; + + l_data = (OPJ_BYTE *) opj_malloc(l_total_size); + if (l_data == 0) { + return OPJ_FALSE; + } + lPermutations = (OPJ_UINT32 *) l_data; + l_double_data = (OPJ_FLOAT32 *)(l_data + l_permutation_size); + memset(lPermutations, 0, l_permutation_size); + + if (! opj_lupDecompose(pSrcMatrix, lPermutations, l_double_data, nb_compo)) { + opj_free(l_data); + return OPJ_FALSE; + } + + opj_lupInvert(pSrcMatrix, pDestMatrix, nb_compo, lPermutations, l_double_data, + l_double_data + nb_compo, l_double_data + 2 * nb_compo); + opj_free(l_data); + return OPJ_TRUE; } @@ -103,192 +104,192 @@ OPJ_BOOL opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix, Local functions ========================================================== */ -static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, - OPJ_FLOAT32 * p_swap_area, - OPJ_UINT32 nb_compo) +static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix, + OPJ_UINT32 * permutations, + OPJ_FLOAT32 * p_swap_area, + OPJ_UINT32 nb_compo) { - OPJ_UINT32 * tmpPermutations = permutations; - OPJ_UINT32 * dstPermutations; - OPJ_UINT32 k2=0,t; - OPJ_FLOAT32 temp; - OPJ_UINT32 i,j,k; - OPJ_FLOAT32 p; - OPJ_UINT32 lLastColum = nb_compo - 1; - OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - OPJ_FLOAT32 * lTmpMatrix = matrix; - OPJ_FLOAT32 * lColumnMatrix,* lDestMatrix; - OPJ_UINT32 offset = 1; - OPJ_UINT32 lStride = nb_compo-1; - - /*initialize permutations */ - for (i = 0; i < nb_compo; ++i) - { - *tmpPermutations++ = i; - } - /* now make a pivot with column switch */ - tmpPermutations = permutations; - for (k = 0; k < lLastColum; ++k) { - p = 0.0; - - /* take the middle element */ - lColumnMatrix = lTmpMatrix + k; - - /* make permutation with the biggest value in the column */ + OPJ_UINT32 * tmpPermutations = permutations; + OPJ_UINT32 * dstPermutations; + OPJ_UINT32 k2 = 0, t; + OPJ_FLOAT32 temp; + OPJ_UINT32 i, j, k; + OPJ_FLOAT32 p; + OPJ_UINT32 lLastColum = nb_compo - 1; + OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpMatrix = matrix; + OPJ_FLOAT32 * lColumnMatrix, * lDestMatrix; + OPJ_UINT32 offset = 1; + OPJ_UINT32 lStride = nb_compo - 1; + + /*initialize permutations */ + for (i = 0; i < nb_compo; ++i) { + *tmpPermutations++ = i; + } + /* now make a pivot with column switch */ + tmpPermutations = permutations; + for (k = 0; k < lLastColum; ++k) { + p = 0.0; + + /* take the middle element */ + lColumnMatrix = lTmpMatrix + k; + + /* make permutation with the biggest value in the column */ for (i = k; i < nb_compo; ++i) { - temp = ((*lColumnMatrix > 0) ? *lColumnMatrix : -(*lColumnMatrix)); - if (temp > p) { - p = temp; - k2 = i; - } - /* next line */ - lColumnMatrix += nb_compo; - } - - /* a whole rest of 0 -> non singular */ - if (p == 0.0) { - return OPJ_FALSE; - } - - /* should we permute ? */ - if (k2 != k) { - /*exchange of line */ - /* k2 > k */ - dstPermutations = tmpPermutations + k2 - k; - /* swap indices */ - t = *tmpPermutations; - *tmpPermutations = *dstPermutations; - *dstPermutations = t; - - /* and swap entire line. */ - lColumnMatrix = lTmpMatrix + (k2 - k) * nb_compo; - memcpy(p_swap_area,lColumnMatrix,lSwapSize); - memcpy(lColumnMatrix,lTmpMatrix,lSwapSize); - memcpy(lTmpMatrix,p_swap_area,lSwapSize); - } - - /* now update data in the rest of the line and line after */ - lDestMatrix = lTmpMatrix + k; - lColumnMatrix = lDestMatrix + nb_compo; - /* take the middle element */ - temp = *(lDestMatrix++); - - /* now compute up data (i.e. coeff up of the diagonal). */ - for (i = offset; i < nb_compo; ++i) { - /*lColumnMatrix; */ - /* divide the lower column elements by the diagonal value */ - - /* matrix[i][k] /= matrix[k][k]; */ - /* p = matrix[i][k] */ - p = *lColumnMatrix / temp; - *(lColumnMatrix++) = p; - + temp = ((*lColumnMatrix > 0) ? *lColumnMatrix : -(*lColumnMatrix)); + if (temp > p) { + p = temp; + k2 = i; + } + /* next line */ + lColumnMatrix += nb_compo; + } + + /* a whole rest of 0 -> non singular */ + if (p == 0.0) { + return OPJ_FALSE; + } + + /* should we permute ? */ + if (k2 != k) { + /*exchange of line */ + /* k2 > k */ + dstPermutations = tmpPermutations + k2 - k; + /* swap indices */ + t = *tmpPermutations; + *tmpPermutations = *dstPermutations; + *dstPermutations = t; + + /* and swap entire line. */ + lColumnMatrix = lTmpMatrix + (k2 - k) * nb_compo; + memcpy(p_swap_area, lColumnMatrix, lSwapSize); + memcpy(lColumnMatrix, lTmpMatrix, lSwapSize); + memcpy(lTmpMatrix, p_swap_area, lSwapSize); + } + + /* now update data in the rest of the line and line after */ + lDestMatrix = lTmpMatrix + k; + lColumnMatrix = lDestMatrix + nb_compo; + /* take the middle element */ + temp = *(lDestMatrix++); + + /* now compute up data (i.e. coeff up of the diagonal). */ + for (i = offset; i < nb_compo; ++i) { + /*lColumnMatrix; */ + /* divide the lower column elements by the diagonal value */ + + /* matrix[i][k] /= matrix[k][k]; */ + /* p = matrix[i][k] */ + p = *lColumnMatrix / temp; + *(lColumnMatrix++) = p; + for (j = /* k + 1 */ offset; j < nb_compo; ++j) { - /* matrix[i][j] -= matrix[i][k] * matrix[k][j]; */ - *(lColumnMatrix++) -= p * (*(lDestMatrix++)); - } - /* come back to the k+1th element */ - lDestMatrix -= lStride; - /* go to kth element of the next line */ - lColumnMatrix += k; - } - - /* offset is now k+2 */ - ++offset; - /* 1 element less for stride */ - --lStride; - /* next line */ - lTmpMatrix+=nb_compo; - /* next permutation element */ - ++tmpPermutations; - } + /* matrix[i][j] -= matrix[i][k] * matrix[k][j]; */ + *(lColumnMatrix++) -= p * (*(lDestMatrix++)); + } + /* come back to the k+1th element */ + lDestMatrix -= lStride; + /* go to kth element of the next line */ + lColumnMatrix += k; + } + + /* offset is now k+2 */ + ++offset; + /* 1 element less for stride */ + --lStride; + /* next line */ + lTmpMatrix += nb_compo; + /* next permutation element */ + ++tmpPermutations; + } return OPJ_TRUE; } - -static void opj_lupSolve (OPJ_FLOAT32 * pResult, - OPJ_FLOAT32 * pMatrix, - OPJ_FLOAT32 * pVector, - OPJ_UINT32* pPermutations, - OPJ_UINT32 nb_compo,OPJ_FLOAT32 * p_intermediate_data) + +static void opj_lupSolve(OPJ_FLOAT32 * pResult, + OPJ_FLOAT32 * pMatrix, + OPJ_FLOAT32 * pVector, + OPJ_UINT32* pPermutations, + OPJ_UINT32 nb_compo, OPJ_FLOAT32 * p_intermediate_data) { - OPJ_INT32 k; - OPJ_UINT32 i,j; - OPJ_FLOAT32 sum; - OPJ_FLOAT32 u; - OPJ_UINT32 lStride = nb_compo+1; - OPJ_FLOAT32 * lCurrentPtr; - OPJ_FLOAT32 * lIntermediatePtr; - OPJ_FLOAT32 * lDestPtr; - OPJ_FLOAT32 * lTmpMatrix; - OPJ_FLOAT32 * lLineMatrix = pMatrix; - OPJ_FLOAT32 * lBeginPtr = pResult + nb_compo - 1; - OPJ_FLOAT32 * lGeneratedData; - OPJ_UINT32 * lCurrentPermutationPtr = pPermutations; - - - lIntermediatePtr = p_intermediate_data; - lGeneratedData = p_intermediate_data + nb_compo - 1; - + OPJ_INT32 k; + OPJ_UINT32 i, j; + OPJ_FLOAT32 sum; + OPJ_FLOAT32 u; + OPJ_UINT32 lStride = nb_compo + 1; + OPJ_FLOAT32 * lCurrentPtr; + OPJ_FLOAT32 * lIntermediatePtr; + OPJ_FLOAT32 * lDestPtr; + OPJ_FLOAT32 * lTmpMatrix; + OPJ_FLOAT32 * lLineMatrix = pMatrix; + OPJ_FLOAT32 * lBeginPtr = pResult + nb_compo - 1; + OPJ_FLOAT32 * lGeneratedData; + OPJ_UINT32 * lCurrentPermutationPtr = pPermutations; + + + lIntermediatePtr = p_intermediate_data; + lGeneratedData = p_intermediate_data + nb_compo - 1; + for (i = 0; i < nb_compo; ++i) { - sum = 0.0; - lCurrentPtr = p_intermediate_data; - lTmpMatrix = lLineMatrix; - for (j = 1; j <= i; ++j) - { - /* sum += matrix[i][j-1] * y[j-1]; */ - sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); + sum = 0.0; + lCurrentPtr = p_intermediate_data; + lTmpMatrix = lLineMatrix; + for (j = 1; j <= i; ++j) { + /* sum += matrix[i][j-1] * y[j-1]; */ + sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); } - /*y[i] = pVector[pPermutations[i]] - sum; */ + /*y[i] = pVector[pPermutations[i]] - sum; */ *(lIntermediatePtr++) = pVector[*(lCurrentPermutationPtr++)] - sum; - lLineMatrix += nb_compo; - } + lLineMatrix += nb_compo; + } - /* we take the last point of the matrix */ - lLineMatrix = pMatrix + nb_compo*nb_compo - 1; + /* we take the last point of the matrix */ + lLineMatrix = pMatrix + nb_compo * nb_compo - 1; - /* and we take after the last point of the destination vector */ - lDestPtr = pResult + nb_compo; + /* and we take after the last point of the destination vector */ + lDestPtr = pResult + nb_compo; assert(nb_compo != 0); - for (k = (OPJ_INT32)nb_compo - 1; k != -1 ; --k) { - sum = 0.0; - lTmpMatrix = lLineMatrix; + for (k = (OPJ_INT32)nb_compo - 1; k != -1 ; --k) { + sum = 0.0; + lTmpMatrix = lLineMatrix; u = *(lTmpMatrix++); - lCurrentPtr = lDestPtr--; + lCurrentPtr = lDestPtr--; for (j = (OPJ_UINT32)(k + 1); j < nb_compo; ++j) { - /* sum += matrix[k][j] * x[j] */ - sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); - } - /*x[k] = (y[k] - sum) / u; */ + /* sum += matrix[k][j] * x[j] */ + sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); + } + /*x[k] = (y[k] - sum) / u; */ *(lBeginPtr--) = (*(lGeneratedData--) - sum) / u; - lLineMatrix -= lStride; - } + lLineMatrix -= lStride; + } } - - -static void opj_lupInvert (OPJ_FLOAT32 * pSrcMatrix, - OPJ_FLOAT32 * pDestMatrix, - OPJ_UINT32 nb_compo, - OPJ_UINT32 * pPermutations, - OPJ_FLOAT32 * p_src_temp, - OPJ_FLOAT32 * p_dest_temp, - OPJ_FLOAT32 * p_swap_area ) + + +static void opj_lupInvert(OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 nb_compo, + OPJ_UINT32 * pPermutations, + OPJ_FLOAT32 * p_src_temp, + OPJ_FLOAT32 * p_dest_temp, + OPJ_FLOAT32 * p_swap_area) { - OPJ_UINT32 j,i; - OPJ_FLOAT32 * lCurrentPtr; - OPJ_FLOAT32 * lLineMatrix = pDestMatrix; - OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - - for (j = 0; j < nb_compo; ++j) { - lCurrentPtr = lLineMatrix++; - memset(p_src_temp,0,lSwapSize); - p_src_temp[j] = 1.0; - opj_lupSolve(p_dest_temp,pSrcMatrix,p_src_temp, pPermutations, nb_compo , p_swap_area); - - for (i = 0; i < nb_compo; ++i) { - *(lCurrentPtr) = p_dest_temp[i]; - lCurrentPtr+=nb_compo; - } + OPJ_UINT32 j, i; + OPJ_FLOAT32 * lCurrentPtr; + OPJ_FLOAT32 * lLineMatrix = pDestMatrix; + OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + + for (j = 0; j < nb_compo; ++j) { + lCurrentPtr = lLineMatrix++; + memset(p_src_temp, 0, lSwapSize); + p_src_temp[j] = 1.0; + opj_lupSolve(p_dest_temp, pSrcMatrix, p_src_temp, pPermutations, nb_compo, + p_swap_area); + + for (i = 0; i < nb_compo; ++i) { + *(lCurrentPtr) = p_dest_temp[i]; + lCurrentPtr += nb_compo; + } } } diff --git a/third_party/libopenjpeg20/invert.h b/third_party/libopenjpeg20/invert.h index 2fae8e54bdf163a3718b11d55738622dd099d69d..70402135593e38f18d5da0dd6cdbaeb809bffae4 100644 --- a/third_party/libopenjpeg20/invert.h +++ b/third_party/libopenjpeg20/invert.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -29,8 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __INVERT_H -#define __INVERT_H +#ifndef OPJ_INVERT_H +#define OPJ_INVERT_H /** @file invert.h @brief Implementation of the matrix inversion @@ -48,17 +48,17 @@ The function in INVERT.H compute a matrix inversion with a LUP method * Calculates a n x n double matrix inversion with a LUP method. Data is aligned, rows after rows (or columns after columns). * The function does not take ownership of any memory block, data must be fred by the user. * - * @param pSrcMatrix the matrix to invert. - * @param pDestMatrix data to store the inverted matrix. - * @param n size of the matrix + * @param pSrcMatrix the matrix to invert. + * @param pDestMatrix data to store the inverted matrix. + * @param nb_compo size of the matrix * @return OPJ_TRUE if the inversion is successful, OPJ_FALSE if the matrix is singular. */ OPJ_BOOL opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix, - OPJ_FLOAT32 * pDestMatrix, + OPJ_FLOAT32 * pDestMatrix, OPJ_UINT32 nb_compo); /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ -#endif /* __INVERT_H */ +#endif /* OPJ_INVERT_H */ diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c index cb5a28373259a7ca930718acd733e950aa1f93f0..cea61470961ade7bf609b80e3743ee446840264f 100644 --- a/third_party/libopenjpeg20/j2k.c +++ b/third_party/libopenjpeg20/j2k.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,14 +8,15 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> * Copyright (c) 2006-2007, Parvatha Elangovan * Copyright (c) 2010-2011, Kaori Hagihara - * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,14 +52,15 @@ /** * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures. */ -static OPJ_BOOL opj_j2k_setup_header_reading (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_setup_header_reading(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); /** * The read header procedure. */ -static OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_read_header_procedure(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * The default encoding validation procedure without any extension. @@ -69,9 +71,9 @@ static OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k, * * @return true if the parameters are correct. */ -static OPJ_BOOL opj_j2k_encoding_validation ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_encoding_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * The default decoding validation procedure without any extension. @@ -82,27 +84,30 @@ static OPJ_BOOL opj_j2k_encoding_validation ( opj_j2k_t * p_j2k, * * @return true if the parameters are correct. */ -static OPJ_BOOL opj_j2k_decoding_validation ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_decoding_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters * are valid. Developpers wanting to extend the library can add their own validation procedures. */ -static OPJ_BOOL opj_j2k_setup_encoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_setup_encoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); /** * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters * are valid. Developpers wanting to extend the library can add their own validation procedures. */ -static OPJ_BOOL opj_j2k_setup_decoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_setup_decoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); /** * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters * are valid. Developpers wanting to extend the library can add their own validation procedures. */ -static OPJ_BOOL opj_j2k_setup_end_compress (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_setup_end_compress(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); /** * The mct encoding validation procedure. @@ -113,33 +118,33 @@ static OPJ_BOOL opj_j2k_setup_end_compress (opj_j2k_t *p_j2k, opj_event_mgr_t * * * @return true if the parameters are correct. */ -static OPJ_BOOL opj_j2k_mct_validation (opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_mct_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Builds the tcd decoder to use to decode tile. */ -static OPJ_BOOL opj_j2k_build_decoder ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_build_decoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Builds the tcd encoder to use to encode tile. */ -static OPJ_BOOL opj_j2k_build_encoder ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_build_encoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** - * Creates a tile-coder decoder. + * Creates a tile-coder encoder. * * @param p_stream the stream to write data to. * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_create_tcd( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Excutes the given procedures on the given codec. @@ -151,10 +156,10 @@ static OPJ_BOOL opj_j2k_create_tcd( opj_j2k_t *p_j2k, * * @return true if all the procedures were successfully executed. */ -static OPJ_BOOL opj_j2k_exec ( opj_j2k_t * p_j2k, - opj_procedure_list_t * p_procedure_list, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_exec(opj_j2k_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Updates the rates of the tcp. @@ -163,24 +168,24 @@ static OPJ_BOOL opj_j2k_exec ( opj_j2k_t * p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_update_rates( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Copies the decoding tile parameters onto all the tile parameters. * Creates also the tile decoder. */ -static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Destroys the memory associated with the decoding of headers. */ -static OPJ_BOOL opj_j2k_destroy_header_memory ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_destroy_header_memory(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads the lookup table containing all the marker, status and action, and returns the handler associated @@ -189,28 +194,42 @@ static OPJ_BOOL opj_j2k_destroy_header_memory ( opj_j2k_t * p_j2k, * * @return the handler associated with the id. */ -static const struct opj_dec_memory_marker_handler * opj_j2k_get_marker_handler (OPJ_UINT32 p_id); +static const struct opj_dec_memory_marker_handler * opj_j2k_get_marker_handler( + OPJ_UINT32 p_id); /** * Destroys a tile coding parameter structure. * * @param p_tcp the tile coding parameter to destroy. */ -static void opj_j2k_tcp_destroy (opj_tcp_t *p_tcp); +static void opj_j2k_tcp_destroy(opj_tcp_t *p_tcp); /** * Destroys the data inside a tile coding parameter structure. * * @param p_tcp the tile coding parameter which contain data to destroy. */ -static void opj_j2k_tcp_data_destroy (opj_tcp_t *p_tcp); +static void opj_j2k_tcp_data_destroy(opj_tcp_t *p_tcp); /** * Destroys a coding parameter structure. * * @param p_cp the coding parameter to destroy. */ -static void opj_j2k_cp_destroy (opj_cp_t *p_cp); +static void opj_j2k_cp_destroy(opj_cp_t *p_cp); + +/** + * Compare 2 a SPCod/ SPCoc elements, i.e. the coding style of a given component of a tile. + * + * @param p_j2k J2K codec. + * @param p_tile_no Tile number + * @param p_first_comp_no The 1st component number to compare. + * @param p_second_comp_no The 1st component number to compare. + * + * @return OPJ_TRUE if SPCdod are equals. + */ +static OPJ_BOOL opj_j2k_compare_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); /** * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. @@ -224,12 +243,12 @@ static void opj_j2k_cp_destroy (opj_cp_t *p_cp); * * @return FIXME DOC */ -static OPJ_BOOL opj_j2k_write_SPCod_SPCoc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); /** * Gets the size taken by writing a SPCod or SPCoc for the given tile and component. @@ -240,9 +259,9 @@ static OPJ_BOOL opj_j2k_write_SPCod_SPCoc( opj_j2k_t *p_j2k, * * @return the number of bytes taken by the SPCod element. */ -static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size (opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no ); +static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no); /** * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. @@ -252,11 +271,11 @@ static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size (opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the COM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_SPCod_SPCoc( opj_j2k_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); /** * Gets the size taken by writing SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. @@ -267,9 +286,23 @@ static OPJ_BOOL opj_j2k_read_SPCod_SPCoc( opj_j2k_t *p_j2k, * * @return the number of bytes taken by the SPCod element. */ -static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no ); +static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no); + +/** + * Compares 2 SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_j2k J2K codec. + * @param p_tile_no the tile to output. + * @param p_first_comp_no the first component number to compare. + * @param p_second_comp_no the second component number to compare. + * + * @return OPJ_TRUE if equals. + */ +static OPJ_BOOL opj_j2k_compare_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); + /** * Writes a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. @@ -283,16 +316,16 @@ static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_t *p_j2k, * */ static OPJ_BOOL opj_j2k_write_SQcd_SQcc(opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_header_size, - opj_event_mgr_t * p_manager); + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); /** * Updates the Tile Length Marker. */ -static void opj_j2k_update_tlm ( opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size); +static void opj_j2k_update_tlm(opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size); /** * Reads a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. @@ -304,77 +337,79 @@ static void opj_j2k_update_tlm ( opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size) * @param p_manager the user event manager. * */ -static OPJ_BOOL opj_j2k_read_SQcd_SQcc( opj_j2k_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); /** * Copies the tile component parameters of all the component from the first tile component. * * @param p_j2k the J2k codec. */ -static void opj_j2k_copy_tile_component_parameters( opj_j2k_t *p_j2k ); +static void opj_j2k_copy_tile_component_parameters(opj_j2k_t *p_j2k); /** * Copies the tile quantization parameters of all the component from the first tile component. * * @param p_j2k the J2k codec. */ -static void opj_j2k_copy_tile_quantization_parameters( opj_j2k_t *p_j2k ); +static void opj_j2k_copy_tile_quantization_parameters(opj_j2k_t *p_j2k); /** * Reads the tiles. */ -static OPJ_BOOL opj_j2k_decode_tiles ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); -static OPJ_BOOL opj_j2k_pre_write_tile ( opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_pre_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); -static OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image); +static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, + opj_image_t* p_output_image); static void opj_get_tile_dimensions(opj_image_t * l_image, - opj_tcd_tilecomp_t * l_tilec, - opj_image_comp_t * l_img_comp, - OPJ_UINT32* l_size_comp, - OPJ_UINT32* l_width, - OPJ_UINT32* l_height, - OPJ_UINT32* l_offset_x, - OPJ_UINT32* l_offset_y, - OPJ_UINT32* l_image_width, - OPJ_UINT32* l_stride, - OPJ_UINT32* l_tile_offset); - -static void opj_j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data); - -static OPJ_BOOL opj_j2k_post_write_tile (opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); + opj_tcd_tilecomp_t * l_tilec, + opj_image_comp_t * l_img_comp, + OPJ_UINT32* l_size_comp, + OPJ_UINT32* l_width, + OPJ_UINT32* l_height, + OPJ_UINT32* l_offset_x, + OPJ_UINT32* l_offset_y, + OPJ_UINT32* l_image_width, + OPJ_UINT32* l_stride, + OPJ_UINT32* l_tile_offset); + +static void opj_j2k_get_tile_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data); + +static OPJ_BOOL opj_j2k_post_write_tile(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Sets up the procedures to do on writing header. * Developers wanting to extend the library can add their own writing procedures. */ -static OPJ_BOOL opj_j2k_setup_header_writing (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager); - -static OPJ_BOOL opj_j2k_write_first_tile_part( opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * p_manager ); - -static OPJ_BOOL opj_j2k_write_all_tile_parts( opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * p_manager ); +static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager); + +static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager); /** * Gets the offset of the header. @@ -383,9 +418,9 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_get_end_header( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); static OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k); @@ -402,9 +437,9 @@ static OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k); * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_soc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a SOC marker (Start of Codestream) @@ -412,9 +447,9 @@ static OPJ_BOOL opj_j2k_write_soc( opj_j2k_t *p_j2k, * @param p_stream XXX needs data * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_soc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes the SIZ marker (image and tile size) @@ -423,9 +458,9 @@ static OPJ_BOOL opj_j2k_read_soc( opj_j2k_t *p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_siz( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_siz(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a SIZ marker (image and tile size) @@ -446,9 +481,9 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_com( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_com(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a COM marker (comments) @@ -457,10 +492,10 @@ static OPJ_BOOL opj_j2k_write_com( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the COM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_com ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_com(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the COD marker (Coding style default) * @@ -468,9 +503,9 @@ static OPJ_BOOL opj_j2k_read_com ( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_cod( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_cod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a COD marker (Coding Styke defaults) @@ -479,12 +514,23 @@ static OPJ_BOOL opj_j2k_write_cod( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the COD marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_cod ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_read_cod(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Compares 2 COC markers (Coding style component) + * + * @param p_j2k J2K codec. + * @param p_first_comp_no the index of the first component to compare. + * @param p_second_comp_no the index of the second component to compare. + * + * @return OPJ_TRUE if equals + */ +static OPJ_BOOL opj_j2k_compare_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); -#if 0 /** * Writes the COC marker (Coding style component) * @@ -493,13 +539,11 @@ static OPJ_BOOL opj_j2k_read_cod ( opj_j2k_t *p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); -#endif +static OPJ_BOOL opj_j2k_write_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); -#if 0 /** * Writes the COC marker (Coding style component) * @@ -510,11 +554,10 @@ static OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k, * @param p_manager the user event manager. */ static void opj_j2k_write_coc_in_memory(opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - opj_event_mgr_t * p_manager ); -#endif + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager); /** * Gets the maximum size taken by a coc. @@ -530,10 +573,10 @@ static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k); * @param p_header_size the size of the data contained in the COC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_coc ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_coc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the QCD marker (quantization default) @@ -542,9 +585,9 @@ static OPJ_BOOL opj_j2k_read_coc ( opj_j2k_t *p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_qcd( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_qcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a QCD marker (Quantization defaults) @@ -553,11 +596,23 @@ static OPJ_BOOL opj_j2k_write_qcd( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the QCD marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_qcd ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); -#if 0 +static OPJ_BOOL opj_j2k_read_qcd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Compare QCC markers (quantization component) + * + * @param p_j2k J2K codec. + * @param p_first_comp_no the index of the first component to compare. + * @param p_second_comp_no the index of the second component to compare. + * + * @return OPJ_TRUE if equals. + */ +static OPJ_BOOL opj_j2k_compare_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); + /** * Writes the QCC marker (quantization component) * @@ -566,13 +621,11 @@ static OPJ_BOOL opj_j2k_read_qcd ( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_qcc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); -#endif +static OPJ_BOOL opj_j2k_write_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); -#if 0 /** * Writes the QCC marker (quantization component) * @@ -583,16 +636,15 @@ static OPJ_BOOL opj_j2k_write_qcc( opj_j2k_t *p_j2k, * @param p_manager the user event manager. */ static void opj_j2k_write_qcc_in_memory(opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - opj_event_mgr_t * p_manager ); -#endif + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager); /** * Gets the maximum size taken by a qcc. */ -static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k); +static OPJ_UINT32 opj_j2k_get_max_qcc_size(opj_j2k_t *p_j2k); /** * Reads a QCC marker (Quantization component) @@ -601,10 +653,10 @@ static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k); * @param p_header_size the size of the data contained in the QCC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_qcc( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_read_qcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the POC marker (Progression Order Change) * @@ -612,9 +664,9 @@ static OPJ_BOOL opj_j2k_read_qcc( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_poc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_poc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes the POC marker (Progression Order Change) * @@ -624,9 +676,9 @@ static OPJ_BOOL opj_j2k_write_poc( opj_j2k_t *p_j2k, * @param p_manager the user event manager. */ static void opj_j2k_write_poc_in_memory(opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - opj_event_mgr_t * p_manager ); + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager); /** * Gets the maximum size taken by the writing of a POC. */ @@ -640,15 +692,15 @@ static OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_t *p_j2k); * @param p_header_size the size of the data contained in the POC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_poc ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_poc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Gets the maximum size taken by the toc headers of all the tile parts of any given tile. */ -static OPJ_UINT32 opj_j2k_get_max_toc_size (opj_j2k_t *p_j2k); +static OPJ_UINT32 opj_j2k_get_max_toc_size(opj_j2k_t *p_j2k); /** * Gets the maximum size taken by the headers of the SOT. @@ -665,10 +717,10 @@ static OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k); * @param p_header_size the size of the data contained in the TLM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_crg ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_crg(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Reads a TLM marker (Tile Length Marker) * @@ -677,10 +729,10 @@ static OPJ_BOOL opj_j2k_read_crg ( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the TLM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_tlm ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_read_tlm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the updated tlm. @@ -689,9 +741,9 @@ static OPJ_BOOL opj_j2k_read_tlm ( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_updated_tlm( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_updated_tlm(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a PLM marker (Packet length, main header marker) @@ -701,10 +753,10 @@ static OPJ_BOOL opj_j2k_write_updated_tlm( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the TLM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_plm ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_read_plm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Reads a PLT marker (Packet length, tile-part header) * @@ -713,10 +765,10 @@ static OPJ_BOOL opj_j2k_read_plm ( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the PLT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_plt ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_plt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Reads a PPM marker (Packed headers, main header) @@ -727,11 +779,11 @@ static OPJ_BOOL opj_j2k_read_plt ( opj_j2k_t *p_j2k, * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_ppm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_ppm( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Merges all PPM markers read (Packed headers, main header) @@ -739,7 +791,7 @@ static OPJ_BOOL opj_j2k_read_ppm ( * @param p_cp main coding parameters. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_merge_ppm ( opj_cp_t *p_cp, opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_merge_ppm(opj_cp_t *p_cp, opj_event_mgr_t * p_manager); /** * Reads a PPT marker (Packed packet headers, tile-part header) @@ -749,10 +801,10 @@ static OPJ_BOOL opj_j2k_merge_ppm ( opj_cp_t *p_cp, opj_event_mgr_t * p_manager * @param p_header_size the size of the data contained in the PPT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_ppt ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_ppt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Merges all PPT markers read (Packed headers, tile-part header) @@ -760,8 +812,8 @@ static OPJ_BOOL opj_j2k_read_ppt ( opj_j2k_t *p_j2k, * @param p_tcp the tile. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_merge_ppt ( opj_tcp_t *p_tcp, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_merge_ppt(opj_tcp_t *p_tcp, + opj_event_mgr_t * p_manager); /** @@ -771,24 +823,26 @@ static OPJ_BOOL opj_j2k_merge_ppt ( opj_tcp_t *p_tcp, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_tlm( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes the SOT marker (Start of tile-part) * * @param p_j2k J2K codec. - * @param p_data FIXME DOC - * @param p_data_written FIXME DOC + * @param p_data Output buffer + * @param p_total_data_size Output buffer size + * @param p_data_written Number of bytes written into stream * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_sot( opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - const opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 p_total_data_size, + OPJ_UINT32 * p_data_written, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads values from a SOT marker (Start of tile-part) @@ -804,12 +858,12 @@ static OPJ_BOOL opj_j2k_write_sot( opj_j2k_t *p_j2k, * @param p_manager the user event manager. */ static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - OPJ_UINT32* p_tile_no, - OPJ_UINT32* p_tot_len, - OPJ_UINT32* p_current_part, - OPJ_UINT32* p_num_parts, - opj_event_mgr_t * p_manager ); + OPJ_UINT32 p_header_size, + OPJ_UINT32* p_tile_no, + OPJ_UINT32* p_tot_len, + OPJ_UINT32* p_current_part, + OPJ_UINT32* p_num_parts, + opj_event_mgr_t * p_manager); /** * Reads a SOT marker (Start of tile-part) * @@ -818,10 +872,10 @@ static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE * p_header_data, * @param p_header_size the size of the data contained in the PPT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the SOD marker (Start of data) * @@ -833,13 +887,13 @@ static OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_sod( opj_j2k_t *p_j2k, - opj_tcd_t * p_tile_coder, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - const opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k, + opj_tcd_t * p_tile_coder, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a SOD marker (Start Of Data) @@ -848,17 +902,19 @@ static OPJ_BOOL opj_j2k_write_sod( opj_j2k_t *p_j2k, * @param p_stream FIXME DOC * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_sod( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); -static void opj_j2k_update_tlm (opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size ) +static void opj_j2k_update_tlm(opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size) { - opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_j2k->m_current_tile_number,1); /* PSOT */ - ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current; + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current, + p_j2k->m_current_tile_number, 1); /* PSOT */ + ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current; - opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_tile_part_size,4); /* PSOT */ - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 4; + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current, + p_tile_part_size, 4); /* PSOT */ + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 4; } /** @@ -871,12 +927,12 @@ static void opj_j2k_update_tlm (opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size ) * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_rgn( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - OPJ_UINT32 nb_comps, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_rgn(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_UINT32 nb_comps, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a RGN marker (Region Of Interest) @@ -886,10 +942,10 @@ static OPJ_BOOL opj_j2k_write_rgn( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the POC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_rgn (opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_rgn(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the EOC marker (End of Codestream) @@ -898,9 +954,9 @@ static OPJ_BOOL opj_j2k_read_rgn (opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_eoc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); #if 0 /** @@ -910,9 +966,9 @@ static OPJ_BOOL opj_j2k_write_eoc( opj_j2k_t *p_j2k, * @param p_stream FIXME DOC * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_eoc ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); #endif /** @@ -922,9 +978,9 @@ static OPJ_BOOL opj_j2k_read_eoc ( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_mct_data_group( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_mct_data_group(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Inits the Info @@ -933,9 +989,9 @@ static OPJ_BOOL opj_j2k_write_mct_data_group( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_init_info( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_init_info(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** Add main header marker information @@ -944,7 +1000,8 @@ Add main header marker information @param pos byte offset of marker segment @param len length of marker segment */ -static OPJ_BOOL opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) ; +static OPJ_BOOL opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, + OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) ; /** Add tile header marker information @param tileno tile index number @@ -953,7 +1010,9 @@ Add tile header marker information @param pos byte offset of marker segment @param len length of marker segment */ -static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len); +static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, + opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, + OPJ_UINT32 len); /** * Reads an unknown marker @@ -965,10 +1024,10 @@ static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, opj_codestream_index_t * * * @return true if the marker could be deduced. */ -static OPJ_BOOL opj_j2k_read_unk( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - OPJ_UINT32 *output_marker, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_unk(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + OPJ_UINT32 *output_marker, + opj_event_mgr_t * p_manager); /** * Writes the MCT marker (Multiple Component Transform) @@ -978,10 +1037,10 @@ static OPJ_BOOL opj_j2k_read_unk( opj_j2k_t *p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_mct_record( opj_j2k_t *p_j2k, - opj_mct_data_t * p_mct_record, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_mct_record(opj_j2k_t *p_j2k, + opj_mct_data_t * p_mct_record, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a MCT marker (Multiple Component Transform) @@ -991,10 +1050,10 @@ static OPJ_BOOL opj_j2k_write_mct_record( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the MCT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the MCC marker (Multiple Component Collection) @@ -1004,10 +1063,10 @@ static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_mcc_record( opj_j2k_t *p_j2k, - opj_simple_mcc_decorrelation_data_t * p_mcc_record, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_mcc_record(opj_j2k_t *p_j2k, + opj_simple_mcc_decorrelation_data_t * p_mcc_record, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a MCC marker (Multiple Component Collection) @@ -1017,10 +1076,10 @@ static OPJ_BOOL opj_j2k_write_mcc_record( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the MCC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_mcc ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_read_mcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the MCO marker (Multiple component transformation ordering) @@ -1029,9 +1088,9 @@ static OPJ_BOOL opj_j2k_read_mcc ( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_mco( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_mco(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a MCO marker (Multiple Component Transform Ordering) @@ -1041,27 +1100,40 @@ static OPJ_BOOL opj_j2k_write_mco( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the MCO marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_mco ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); - -static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index); - -static void opj_j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); - -static void opj_j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static OPJ_BOOL opj_j2k_read_mco(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); -static void opj_j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, + OPJ_UINT32 p_index); + +static void opj_j2k_read_int16_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_int32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float64_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static void opj_j2k_read_int16_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_int32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float64_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static void opj_j2k_write_float_to_int16(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_write_float_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_write_float_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_write_float_to_float64(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); /** * Ends the encoding, i.e. frees memory. @@ -1070,9 +1142,9 @@ static void opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_d * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_end_encoding( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_end_encoding(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes the CBD marker (Component bit depth definition) @@ -1081,9 +1153,9 @@ static OPJ_BOOL opj_j2k_end_encoding( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_cbd( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_cbd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a CBD marker (Component bit depth definition) @@ -1092,12 +1164,12 @@ static OPJ_BOOL opj_j2k_write_cbd( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the CBD marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_cbd ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_read_cbd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + -#if 0 /** * Writes COC marker for each component. * @@ -1105,12 +1177,10 @@ static OPJ_BOOL opj_j2k_read_cbd ( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_all_coc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); -#endif +static OPJ_BOOL opj_j2k_write_all_coc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); -#if 0 /** * Writes QCC marker for each component. * @@ -1118,10 +1188,9 @@ static OPJ_BOOL opj_j2k_write_all_coc( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_all_qcc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); -#endif +static OPJ_BOOL opj_j2k_write_all_qcc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes regions of interests. @@ -1130,9 +1199,9 @@ static OPJ_BOOL opj_j2k_write_all_qcc( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_regions( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_regions(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes EPC ???? @@ -1141,9 +1210,9 @@ static OPJ_BOOL opj_j2k_write_regions( opj_j2k_t *p_j2k, * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_write_epc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_write_epc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Checks the progression order changes values. Tells of the poc given as input are valid. @@ -1158,12 +1227,12 @@ static OPJ_BOOL opj_j2k_write_epc( opj_j2k_t *p_j2k, * * @return true if the pocs are valid. */ -static OPJ_BOOL opj_j2k_check_poc_val( const opj_poc_t *p_pocs, - OPJ_UINT32 p_nb_pocs, - OPJ_UINT32 p_nb_resolutions, - OPJ_UINT32 numcomps, - OPJ_UINT32 numlayers, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_check_poc_val(const opj_poc_t *p_pocs, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 numcomps, + OPJ_UINT32 numlayers, + opj_event_mgr_t * p_manager); /** * Gets the number of tile parts used for the given change of progression (if any) and the given tile. @@ -1174,7 +1243,8 @@ static OPJ_BOOL opj_j2k_check_poc_val( const opj_poc_t *p_pocs, * * @return the number of tile parts. */ -static OPJ_UINT32 opj_j2k_get_num_tp( opj_cp_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno); +static OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, + OPJ_UINT32 tileno); /** * Calculates the total number of tile parts needed by the encoder to @@ -1188,11 +1258,11 @@ static OPJ_UINT32 opj_j2k_get_num_tp( opj_cp_t *cp, OPJ_UINT32 pino, OPJ_UINT32 * * @return true if the function was successful, false else. */ -static OPJ_BOOL opj_j2k_calculate_tp( opj_j2k_t *p_j2k, - opj_cp_t *cp, - OPJ_UINT32 * p_nb_tiles, - opj_image_t *image, - opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_j2k_calculate_tp(opj_j2k_t *p_j2k, + opj_cp_t *cp, + OPJ_UINT32 * p_nb_tiles, + opj_image_t *image, + opj_event_mgr_t * p_manager); static void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream); @@ -1200,15 +1270,17 @@ static void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream); static opj_codestream_index_t* opj_j2k_create_cstr_index(void); -static OPJ_FLOAT32 opj_j2k_get_tp_stride (opj_tcp_t * p_tcp); +static OPJ_FLOAT32 opj_j2k_get_tp_stride(opj_tcp_t * p_tcp); -static OPJ_FLOAT32 opj_j2k_get_default_stride (opj_tcp_t * p_tcp); +static OPJ_FLOAT32 opj_j2k_get_default_stride(opj_tcp_t * p_tcp); static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres); -static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_image_t *image, opj_event_mgr_t *p_manager); +static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, + opj_image_t *image, opj_event_mgr_t *p_manager); -static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, opj_event_mgr_t *p_manager); +static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, + opj_event_mgr_t *p_manager); /** * Checks for invalid number of tile-parts in SOT marker (TPsot==TNsot). See issue 254. @@ -1220,589 +1292,603 @@ static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, * * @return true if the function was successful, false else. */ -static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t + *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, + opj_event_mgr_t * p_manager); /*@}*/ /*@}*/ /* ----------------------------------------------------------------------- */ -typedef struct j2k_prog_order{ - OPJ_PROG_ORDER enum_prog; - char str_prog[5]; -}j2k_prog_order_t; - -static j2k_prog_order_t j2k_prog_order_list[] = { - {OPJ_CPRL, "CPRL"}, - {OPJ_LRCP, "LRCP"}, - {OPJ_PCRL, "PCRL"}, - {OPJ_RLCP, "RLCP"}, - {OPJ_RPCL, "RPCL"}, - {(OPJ_PROG_ORDER)-1, ""} +typedef struct j2k_prog_order { + OPJ_PROG_ORDER enum_prog; + char str_prog[5]; +} j2k_prog_order_t; + +static const j2k_prog_order_t j2k_prog_order_list[] = { + {OPJ_CPRL, "CPRL"}, + {OPJ_LRCP, "LRCP"}, + {OPJ_PCRL, "PCRL"}, + {OPJ_RLCP, "RLCP"}, + {OPJ_RPCL, "RPCL"}, + {(OPJ_PROG_ORDER) - 1, ""} }; /** * FIXME DOC */ -static const OPJ_UINT32 MCT_ELEMENT_SIZE [] = -{ - 2, - 4, - 4, - 8 +static const OPJ_UINT32 MCT_ELEMENT_SIZE [] = { + 2, + 4, + 4, + 8 }; -typedef void (* opj_j2k_mct_function) (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +typedef void (* opj_j2k_mct_function)(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); -static const opj_j2k_mct_function j2k_mct_read_functions_to_float [] = -{ - opj_j2k_read_int16_to_float, - opj_j2k_read_int32_to_float, - opj_j2k_read_float32_to_float, - opj_j2k_read_float64_to_float +static const opj_j2k_mct_function j2k_mct_read_functions_to_float [] = { + opj_j2k_read_int16_to_float, + opj_j2k_read_int32_to_float, + opj_j2k_read_float32_to_float, + opj_j2k_read_float64_to_float }; -static const opj_j2k_mct_function j2k_mct_read_functions_to_int32 [] = -{ - opj_j2k_read_int16_to_int32, - opj_j2k_read_int32_to_int32, - opj_j2k_read_float32_to_int32, - opj_j2k_read_float64_to_int32 +static const opj_j2k_mct_function j2k_mct_read_functions_to_int32 [] = { + opj_j2k_read_int16_to_int32, + opj_j2k_read_int32_to_int32, + opj_j2k_read_float32_to_int32, + opj_j2k_read_float64_to_int32 }; -static const opj_j2k_mct_function j2k_mct_write_functions_from_float [] = -{ - opj_j2k_write_float_to_int16, - opj_j2k_write_float_to_int32, - opj_j2k_write_float_to_float, - opj_j2k_write_float_to_float64 +static const opj_j2k_mct_function j2k_mct_write_functions_from_float [] = { + opj_j2k_write_float_to_int16, + opj_j2k_write_float_to_int32, + opj_j2k_write_float_to_float, + opj_j2k_write_float_to_float64 }; -typedef struct opj_dec_memory_marker_handler -{ - /** marker value */ - OPJ_UINT32 id; - /** value of the state when the marker can appear */ - OPJ_UINT32 states; - /** action linked to the marker */ - OPJ_BOOL (*handler) ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +typedef struct opj_dec_memory_marker_handler { + /** marker value */ + OPJ_UINT32 id; + /** value of the state when the marker can appear */ + OPJ_UINT32 states; + /** action linked to the marker */ + OPJ_BOOL(*handler)(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); } opj_dec_memory_marker_handler_t; static const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] = { - {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, opj_j2k_read_sot}, - {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_cod}, - {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_coc}, - {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_rgn}, - {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcd}, - {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcc}, - {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_poc}, - {J2K_MS_SIZ, J2K_STATE_MHSIZ, opj_j2k_read_siz}, - {J2K_MS_TLM, J2K_STATE_MH, opj_j2k_read_tlm}, - {J2K_MS_PLM, J2K_STATE_MH, opj_j2k_read_plm}, - {J2K_MS_PLT, J2K_STATE_TPH, opj_j2k_read_plt}, - {J2K_MS_PPM, J2K_STATE_MH, opj_j2k_read_ppm}, - {J2K_MS_PPT, J2K_STATE_TPH, opj_j2k_read_ppt}, - {J2K_MS_SOP, 0, 0}, - {J2K_MS_CRG, J2K_STATE_MH, opj_j2k_read_crg}, - {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_com}, - {J2K_MS_MCT, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mct}, - {J2K_MS_CBD, J2K_STATE_MH , opj_j2k_read_cbd}, - {J2K_MS_MCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mcc}, - {J2K_MS_MCO, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mco}, + {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, opj_j2k_read_sot}, + {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_cod}, + {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_coc}, + {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_rgn}, + {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcd}, + {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcc}, + {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_poc}, + {J2K_MS_SIZ, J2K_STATE_MHSIZ, opj_j2k_read_siz}, + {J2K_MS_TLM, J2K_STATE_MH, opj_j2k_read_tlm}, + {J2K_MS_PLM, J2K_STATE_MH, opj_j2k_read_plm}, + {J2K_MS_PLT, J2K_STATE_TPH, opj_j2k_read_plt}, + {J2K_MS_PPM, J2K_STATE_MH, opj_j2k_read_ppm}, + {J2K_MS_PPT, J2K_STATE_TPH, opj_j2k_read_ppt}, + {J2K_MS_SOP, 0, 0}, + {J2K_MS_CRG, J2K_STATE_MH, opj_j2k_read_crg}, + {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_com}, + {J2K_MS_MCT, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mct}, + {J2K_MS_CBD, J2K_STATE_MH, opj_j2k_read_cbd}, + {J2K_MS_MCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mcc}, + {J2K_MS_MCO, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mco}, #ifdef USE_JPWL #ifdef TODO_MS /* remove these functions which are not commpatible with the v2 API */ - {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc}, - {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb}, - {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd}, - {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red}, + {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc}, + {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb}, + {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd}, + {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red}, #endif #endif /* USE_JPWL */ #ifdef USE_JPSEC - {J2K_MS_SEC, J2K_DEC_STATE_MH, j2k_read_sec}, - {J2K_MS_INSEC, 0, j2k_read_insec} + {J2K_MS_SEC, J2K_DEC_STATE_MH, j2k_read_sec}, + {J2K_MS_INSEC, 0, j2k_read_insec} #endif /* USE_JPSEC */ - {J2K_MS_UNK, J2K_STATE_MH | J2K_STATE_TPH, 0}/*opj_j2k_read_unk is directly used*/ + {J2K_MS_UNK, J2K_STATE_MH | J2K_STATE_TPH, 0}/*opj_j2k_read_unk is directly used*/ }; -static void opj_j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_int16_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_UINT32 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_bytes(l_src_data,&l_temp,2); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 2); - l_src_data+=sizeof(OPJ_INT16); + l_src_data += sizeof(OPJ_INT16); - *(l_dest_data++) = (OPJ_FLOAT32) l_temp; - } + *(l_dest_data++) = (OPJ_FLOAT32) l_temp; + } } -static void opj_j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_int32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_UINT32 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_bytes(l_src_data,&l_temp,4); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 4); - l_src_data+=sizeof(OPJ_INT32); + l_src_data += sizeof(OPJ_INT32); - *(l_dest_data++) = (OPJ_FLOAT32) l_temp; - } + *(l_dest_data++) = (OPJ_FLOAT32) l_temp; + } } -static void opj_j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_float32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_FLOAT32 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_float(l_src_data,&l_temp); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_float(l_src_data, &l_temp); - l_src_data+=sizeof(OPJ_FLOAT32); + l_src_data += sizeof(OPJ_FLOAT32); - *(l_dest_data++) = l_temp; - } + *(l_dest_data++) = l_temp; + } } -static void opj_j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_float64_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_FLOAT64 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT64 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_double(l_src_data,&l_temp); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_double(l_src_data, &l_temp); - l_src_data+=sizeof(OPJ_FLOAT64); + l_src_data += sizeof(OPJ_FLOAT64); - *(l_dest_data++) = (OPJ_FLOAT32) l_temp; - } + *(l_dest_data++) = (OPJ_FLOAT32) l_temp; + } } -static void opj_j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_int16_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_UINT32 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_bytes(l_src_data,&l_temp,2); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 2); - l_src_data+=sizeof(OPJ_INT16); + l_src_data += sizeof(OPJ_INT16); - *(l_dest_data++) = (OPJ_INT32) l_temp; - } + *(l_dest_data++) = (OPJ_INT32) l_temp; + } } -static void opj_j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_int32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_UINT32 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_bytes(l_src_data,&l_temp,4); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 4); - l_src_data+=sizeof(OPJ_INT32); + l_src_data += sizeof(OPJ_INT32); - *(l_dest_data++) = (OPJ_INT32) l_temp; - } + *(l_dest_data++) = (OPJ_INT32) l_temp; + } } -static void opj_j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_float32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_FLOAT32 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_float(l_src_data,&l_temp); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_float(l_src_data, &l_temp); - l_src_data+=sizeof(OPJ_FLOAT32); + l_src_data += sizeof(OPJ_FLOAT32); - *(l_dest_data++) = (OPJ_INT32) l_temp; - } + *(l_dest_data++) = (OPJ_INT32) l_temp; + } } -static void opj_j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_read_float64_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; - OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; - OPJ_UINT32 i; - OPJ_FLOAT64 l_temp; + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT64 l_temp; - for (i=0;i<p_nb_elem;++i) { - opj_read_double(l_src_data,&l_temp); + for (i = 0; i < p_nb_elem; ++i) { + opj_read_double(l_src_data, &l_temp); - l_src_data+=sizeof(OPJ_FLOAT64); + l_src_data += sizeof(OPJ_FLOAT64); - *(l_dest_data++) = (OPJ_INT32) l_temp; - } + *(l_dest_data++) = (OPJ_INT32) l_temp; + } } -static void opj_j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_write_float_to_int16(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; - OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; - OPJ_UINT32 i; - OPJ_UINT32 l_temp; + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - l_temp = (OPJ_UINT32) *(l_src_data++); + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_UINT32) * (l_src_data++); - opj_write_bytes(l_dest_data,l_temp,sizeof(OPJ_INT16)); + opj_write_bytes(l_dest_data, l_temp, sizeof(OPJ_INT16)); - l_dest_data+=sizeof(OPJ_INT16); - } + l_dest_data += sizeof(OPJ_INT16); + } } -static void opj_j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_write_float_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; - OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; - OPJ_UINT32 i; - OPJ_UINT32 l_temp; + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - l_temp = (OPJ_UINT32) *(l_src_data++); + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_UINT32) * (l_src_data++); - opj_write_bytes(l_dest_data,l_temp,sizeof(OPJ_INT32)); + opj_write_bytes(l_dest_data, l_temp, sizeof(OPJ_INT32)); - l_dest_data+=sizeof(OPJ_INT32); - } + l_dest_data += sizeof(OPJ_INT32); + } } -static void opj_j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_write_float_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; - OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; - OPJ_UINT32 i; - OPJ_FLOAT32 l_temp; + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_FLOAT32 l_temp; - for (i=0;i<p_nb_elem;++i) { - l_temp = (OPJ_FLOAT32) *(l_src_data++); + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_FLOAT32) * (l_src_data++); - opj_write_float(l_dest_data,l_temp); + opj_write_float(l_dest_data, l_temp); - l_dest_data+=sizeof(OPJ_FLOAT32); - } + l_dest_data += sizeof(OPJ_FLOAT32); + } } -static void opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +static void opj_j2k_write_float_to_float64(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) { - OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; - OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; - OPJ_UINT32 i; - OPJ_FLOAT64 l_temp; + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_FLOAT64 l_temp; - for (i=0;i<p_nb_elem;++i) { - l_temp = (OPJ_FLOAT64) *(l_src_data++); + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_FLOAT64) * (l_src_data++); - opj_write_double(l_dest_data,l_temp); + opj_write_double(l_dest_data, l_temp); - l_dest_data+=sizeof(OPJ_FLOAT64); - } + l_dest_data += sizeof(OPJ_FLOAT64); + } } -char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){ - j2k_prog_order_t *po; - for(po = j2k_prog_order_list; po->enum_prog != -1; po++ ){ - if(po->enum_prog == prg_order){ - return po->str_prog; - } +const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order) +{ + const j2k_prog_order_t *po; + for (po = j2k_prog_order_list; po->enum_prog != -1; po++) { + if (po->enum_prog == prg_order) { + return po->str_prog; } - return po->str_prog; + } + return po->str_prog; } -static OPJ_BOOL opj_j2k_check_poc_val( const opj_poc_t *p_pocs, - OPJ_UINT32 p_nb_pocs, - OPJ_UINT32 p_nb_resolutions, - OPJ_UINT32 p_num_comps, - OPJ_UINT32 p_num_layers, - opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_check_poc_val(const opj_poc_t *p_pocs, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_num_layers, + opj_event_mgr_t * p_manager) { - OPJ_UINT32* packet_array; - OPJ_UINT32 index , resno, compno, layno; - OPJ_UINT32 i; - OPJ_UINT32 step_c = 1; - OPJ_UINT32 step_r = p_num_comps * step_c; - OPJ_UINT32 step_l = p_nb_resolutions * step_r; - OPJ_BOOL loss = OPJ_FALSE; - OPJ_UINT32 layno0 = 0; - - packet_array = (OPJ_UINT32*) opj_calloc(step_l * p_num_layers, sizeof(OPJ_UINT32)); - if (packet_array == 00) { - opj_event_msg(p_manager , EVT_ERROR, "Not enough memory for checking the poc values.\n"); - return OPJ_FALSE; - } + OPJ_UINT32* packet_array; + OPJ_UINT32 index, resno, compno, layno; + OPJ_UINT32 i; + OPJ_UINT32 step_c = 1; + OPJ_UINT32 step_r = p_num_comps * step_c; + OPJ_UINT32 step_l = p_nb_resolutions * step_r; + OPJ_BOOL loss = OPJ_FALSE; + OPJ_UINT32 layno0 = 0; + + packet_array = (OPJ_UINT32*) opj_calloc(step_l * p_num_layers, + sizeof(OPJ_UINT32)); + if (packet_array == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory for checking the poc values.\n"); + return OPJ_FALSE; + } - if (p_nb_pocs == 0) { + if (p_nb_pocs == 0) { opj_free(packet_array); - return OPJ_TRUE; - } - - index = step_r * p_pocs->resno0; - /* take each resolution for each poc */ - for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) - { - OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; + return OPJ_TRUE; + } - /* take each comp of each resolution for each poc */ - for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) { - OPJ_UINT32 comp_index = res_index + layno0 * step_l; + index = step_r * p_pocs->resno0; + /* take each resolution for each poc */ + for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) { + OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; - /* and finally take each layer of each res of ... */ - for (layno = layno0; layno < p_pocs->layno1 ; ++layno) { - /*index = step_r * resno + step_c * compno + step_l * layno;*/ - packet_array[comp_index] = 1; - comp_index += step_l; - } + /* take each comp of each resolution for each poc */ + for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) { + OPJ_UINT32 comp_index = res_index + layno0 * step_l; - res_index += step_c; - } + /* and finally take each layer of each res of ... */ + for (layno = layno0; layno < p_pocs->layno1 ; ++layno) { + /*index = step_r * resno + step_c * compno + step_l * layno;*/ + packet_array[comp_index] = 1; + comp_index += step_l; + } - index += step_r; + res_index += step_c; } - ++p_pocs; - - /* iterate through all the pocs */ - for (i = 1; i < p_nb_pocs ; ++i) { - OPJ_UINT32 l_last_layno1 = (p_pocs-1)->layno1 ; - layno0 = (p_pocs->layno1 > l_last_layno1)? l_last_layno1 : 0; - index = step_r * p_pocs->resno0; + index += step_r; + } + ++p_pocs; - /* take each resolution for each poc */ - for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) { - OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; + /* iterate through all the pocs */ + for (i = 1; i < p_nb_pocs ; ++i) { + OPJ_UINT32 l_last_layno1 = (p_pocs - 1)->layno1 ; - /* take each comp of each resolution for each poc */ - for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) { - OPJ_UINT32 comp_index = res_index + layno0 * step_l; + layno0 = (p_pocs->layno1 > l_last_layno1) ? l_last_layno1 : 0; + index = step_r * p_pocs->resno0; - /* and finally take each layer of each res of ... */ - for (layno = layno0; layno < p_pocs->layno1 ; ++layno) { - /*index = step_r * resno + step_c * compno + step_l * layno;*/ - packet_array[comp_index] = 1; - comp_index += step_l; - } + /* take each resolution for each poc */ + for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) { + OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; - res_index += step_c; - } + /* take each comp of each resolution for each poc */ + for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) { + OPJ_UINT32 comp_index = res_index + layno0 * step_l; - index += step_r; + /* and finally take each layer of each res of ... */ + for (layno = layno0; layno < p_pocs->layno1 ; ++layno) { + /*index = step_r * resno + step_c * compno + step_l * layno;*/ + packet_array[comp_index] = 1; + comp_index += step_l; } - ++p_pocs; - } + res_index += step_c; + } - index = 0; - for (layno = 0; layno < p_num_layers ; ++layno) { - for (resno = 0; resno < p_nb_resolutions; ++resno) { - for (compno = 0; compno < p_num_comps; ++compno) { - loss |= (packet_array[index]!=1); - /*index = step_r * resno + step_c * compno + step_l * layno;*/ - index += step_c; - } - } + index += step_r; } - if (loss) { - opj_event_msg(p_manager , EVT_ERROR, "Missing packets possible loss of data\n"); + ++p_pocs; + } + + index = 0; + for (layno = 0; layno < p_num_layers ; ++layno) { + for (resno = 0; resno < p_nb_resolutions; ++resno) { + for (compno = 0; compno < p_num_comps; ++compno) { + loss |= (packet_array[index] != 1); + /*index = step_r * resno + step_c * compno + step_l * layno;*/ + index += step_c; + } } + } - opj_free(packet_array); + if (loss) { + opj_event_msg(p_manager, EVT_ERROR, "Missing packets possible loss of data\n"); + } + + opj_free(packet_array); - return !loss; + return !loss; } /* ----------------------------------------------------------------------- */ -static OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno) +static OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, + OPJ_UINT32 tileno) { - const OPJ_CHAR *prog = 00; - OPJ_INT32 i; - OPJ_UINT32 tpnum = 1; - opj_tcp_t *tcp = 00; - opj_poc_t * l_current_poc = 00; - - /* preconditions */ - assert(tileno < (cp->tw * cp->th)); - assert(pino < (cp->tcps[tileno].numpocs + 1)); - - /* get the given tile coding parameter */ - tcp = &cp->tcps[tileno]; - assert(tcp != 00); - - l_current_poc = &(tcp->pocs[pino]); - assert(l_current_poc != 0); - - /* get the progression order as a character string */ - prog = opj_j2k_convert_progression_order(tcp->prg); - assert(strlen(prog) > 0); - - if (cp->m_specific_param.m_enc.m_tp_on == 1) { - for (i=0;i<4;++i) { - switch (prog[i]) - { - /* component wise */ - case 'C': - tpnum *= l_current_poc->compE; - break; - /* resolution wise */ - case 'R': - tpnum *= l_current_poc->resE; - break; - /* precinct wise */ - case 'P': - tpnum *= l_current_poc->prcE; - break; - /* layer wise */ - case 'L': - tpnum *= l_current_poc->layE; - break; - } - /* whould we split here ? */ - if ( cp->m_specific_param.m_enc.m_tp_flag == prog[i] ) { - cp->m_specific_param.m_enc.m_tp_pos=i; - break; - } - } - } - else { - tpnum=1; + const OPJ_CHAR *prog = 00; + OPJ_INT32 i; + OPJ_UINT32 tpnum = 1; + opj_tcp_t *tcp = 00; + opj_poc_t * l_current_poc = 00; + + /* preconditions */ + assert(tileno < (cp->tw * cp->th)); + assert(pino < (cp->tcps[tileno].numpocs + 1)); + + /* get the given tile coding parameter */ + tcp = &cp->tcps[tileno]; + assert(tcp != 00); + + l_current_poc = &(tcp->pocs[pino]); + assert(l_current_poc != 0); + + /* get the progression order as a character string */ + prog = opj_j2k_convert_progression_order(tcp->prg); + assert(strlen(prog) > 0); + + if (cp->m_specific_param.m_enc.m_tp_on == 1) { + for (i = 0; i < 4; ++i) { + switch (prog[i]) { + /* component wise */ + case 'C': + tpnum *= l_current_poc->compE; + break; + /* resolution wise */ + case 'R': + tpnum *= l_current_poc->resE; + break; + /* precinct wise */ + case 'P': + tpnum *= l_current_poc->prcE; + break; + /* layer wise */ + case 'L': + tpnum *= l_current_poc->layE; + break; + } + /* whould we split here ? */ + if (cp->m_specific_param.m_enc.m_tp_flag == prog[i]) { + cp->m_specific_param.m_enc.m_tp_pos = i; + break; + } } + } else { + tpnum = 1; + } - return tpnum; + return tpnum; } -static OPJ_BOOL opj_j2k_calculate_tp( opj_j2k_t *p_j2k, - opj_cp_t *cp, - OPJ_UINT32 * p_nb_tiles, - opj_image_t *image, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_calculate_tp(opj_j2k_t *p_j2k, + opj_cp_t *cp, + OPJ_UINT32 * p_nb_tiles, + opj_image_t *image, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 pino,tileno; - OPJ_UINT32 l_nb_tiles; - opj_tcp_t *tcp; + OPJ_UINT32 pino, tileno; + OPJ_UINT32 l_nb_tiles; + opj_tcp_t *tcp; - /* preconditions */ - assert(p_nb_tiles != 00); - assert(cp != 00); - assert(image != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_nb_tiles != 00); + assert(cp != 00); + assert(image != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_nb_tiles = cp->tw * cp->th; - * p_nb_tiles = 0; - tcp = cp->tcps; + OPJ_UNUSED(p_j2k); + OPJ_UNUSED(p_manager); - /* INDEX >> */ - /* TODO mergeV2: check this part which use cstr_info */ - /*if (p_j2k->cstr_info) { - opj_tile_info_t * l_info_tile_ptr = p_j2k->cstr_info->tile; + l_nb_tiles = cp->tw * cp->th; + * p_nb_tiles = 0; + tcp = cp->tcps; - for (tileno = 0; tileno < l_nb_tiles; ++tileno) { - OPJ_UINT32 cur_totnum_tp = 0; + /* INDEX >> */ + /* TODO mergeV2: check this part which use cstr_info */ + /*if (p_j2k->cstr_info) { + opj_tile_info_t * l_info_tile_ptr = p_j2k->cstr_info->tile; - opj_pi_update_encoding_parameters(image,cp,tileno); + for (tileno = 0; tileno < l_nb_tiles; ++tileno) { + OPJ_UINT32 cur_totnum_tp = 0; - for (pino = 0; pino <= tcp->numpocs; ++pino) - { - OPJ_UINT32 tp_num = opj_j2k_get_num_tp(cp,pino,tileno); + opj_pi_update_encoding_parameters(image,cp,tileno); - *p_nb_tiles = *p_nb_tiles + tp_num; + for (pino = 0; pino <= tcp->numpocs; ++pino) + { + OPJ_UINT32 tp_num = opj_j2k_get_num_tp(cp,pino,tileno); - cur_totnum_tp += tp_num; - } + *p_nb_tiles = *p_nb_tiles + tp_num; - tcp->m_nb_tile_parts = cur_totnum_tp; + cur_totnum_tp += tp_num; + } - l_info_tile_ptr->tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t)); - if (l_info_tile_ptr->tp == 00) { - return OPJ_FALSE; - } + tcp->m_nb_tile_parts = cur_totnum_tp; - memset(l_info_tile_ptr->tp,0,cur_totnum_tp * sizeof(opj_tp_info_t)); + l_info_tile_ptr->tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t)); + if (l_info_tile_ptr->tp == 00) { + return OPJ_FALSE; + } - l_info_tile_ptr->num_tps = cur_totnum_tp; + memset(l_info_tile_ptr->tp,0,cur_totnum_tp * sizeof(opj_tp_info_t)); - ++l_info_tile_ptr; - ++tcp; - } - } - else */{ - for (tileno = 0; tileno < l_nb_tiles; ++tileno) { - OPJ_UINT32 cur_totnum_tp = 0; + l_info_tile_ptr->num_tps = cur_totnum_tp; - opj_pi_update_encoding_parameters(image,cp,tileno); + ++l_info_tile_ptr; + ++tcp; + } + } + else */{ + for (tileno = 0; tileno < l_nb_tiles; ++tileno) { + OPJ_UINT32 cur_totnum_tp = 0; - for (pino = 0; pino <= tcp->numpocs; ++pino) { - OPJ_UINT32 tp_num = opj_j2k_get_num_tp(cp,pino,tileno); + opj_pi_update_encoding_parameters(image, cp, tileno); - *p_nb_tiles = *p_nb_tiles + tp_num; + for (pino = 0; pino <= tcp->numpocs; ++pino) { + OPJ_UINT32 tp_num = opj_j2k_get_num_tp(cp, pino, tileno); - cur_totnum_tp += tp_num; - } - tcp->m_nb_tile_parts = cur_totnum_tp; + *p_nb_tiles = *p_nb_tiles + tp_num; - ++tcp; - } + cur_totnum_tp += tp_num; + } + tcp->m_nb_tile_parts = cur_totnum_tp; + + ++tcp; } + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_soc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_write_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - /* 2 bytes will be written */ - OPJ_BYTE * l_start_stream = 00; + /* 2 bytes will be written */ + OPJ_BYTE * l_start_stream = 00; - /* preconditions */ - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_start_stream = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_start_stream = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - /* write SOC identifier */ - opj_write_bytes(l_start_stream,J2K_MS_SOC,2); + /* write SOC identifier */ + opj_write_bytes(l_start_stream, J2K_MS_SOC, 2); - if (opj_stream_write_data(p_stream,l_start_stream,2,p_manager) != 2) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, l_start_stream, 2, p_manager) != 2) { + return OPJ_FALSE; + } -/* UniPG>> */ + /* UniPG>> */ #ifdef USE_JPWL - /* update markers struct */ -/* - OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2); -*/ - assert( 0 && "TODO" ); + /* update markers struct */ + /* + OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2); + */ + assert(0 && "TODO"); #endif /* USE_JPWL */ -/* <<UniPG */ + /* <<UniPG */ - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -1811,137 +1897,143 @@ static OPJ_BOOL opj_j2k_write_soc( opj_j2k_t *p_j2k, * @param p_stream FIXME DOC * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_soc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - OPJ_BYTE l_data [2]; - OPJ_UINT32 l_marker; + OPJ_BYTE l_data [2]; + OPJ_UINT32 l_marker; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - if (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) { - return OPJ_FALSE; - } + if (opj_stream_read_data(p_stream, l_data, 2, p_manager) != 2) { + return OPJ_FALSE; + } - opj_read_bytes(l_data,&l_marker,2); - if (l_marker != J2K_MS_SOC) { - return OPJ_FALSE; - } + opj_read_bytes(l_data, &l_marker, 2); + if (l_marker != J2K_MS_SOC) { + return OPJ_FALSE; + } - /* Next marker should be a SIZ marker in the main header */ - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSIZ; + /* Next marker should be a SIZ marker in the main header */ + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSIZ; - /* FIXME move it in a index structure included in p_j2k*/ - p_j2k->cstr_index->main_head_start = opj_stream_tell(p_stream) - 2; + /* FIXME move it in a index structure included in p_j2k*/ + p_j2k->cstr_index->main_head_start = opj_stream_tell(p_stream) - 2; - opj_event_msg(p_manager, EVT_INFO, "Start to read j2k main header (%d).\n", p_j2k->cstr_index->main_head_start); + opj_event_msg(p_manager, EVT_INFO, "Start to read j2k main header (%d).\n", + p_j2k->cstr_index->main_head_start); - /* Add the marker to the codestream index*/ - if (OPJ_FALSE == opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_SOC, p_j2k->cstr_index->main_head_start, 2)) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); - return OPJ_FALSE; - } - return OPJ_TRUE; + /* Add the marker to the codestream index*/ + if (OPJ_FALSE == opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_SOC, + p_j2k->cstr_index->main_head_start, 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_siz( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_write_siz(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 i; - OPJ_UINT32 l_size_len; - OPJ_BYTE * l_current_ptr; - opj_image_t * l_image = 00; - opj_cp_t *cp = 00; - opj_image_comp_t * l_img_comp = 00; - - /* preconditions */ - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_private_image; - cp = &(p_j2k->m_cp); - l_size_len = 40 + 3 * l_image->numcomps; - l_img_comp = l_image->comps; - - if (l_size_len > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_size_len); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for the SIZ marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_size_len; + OPJ_UINT32 i; + OPJ_UINT32 l_size_len; + OPJ_BYTE * l_current_ptr; + opj_image_t * l_image = 00; + opj_cp_t *cp = 00; + opj_image_comp_t * l_img_comp = 00; + + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + cp = &(p_j2k->m_cp); + l_size_len = 40 + 3 * l_image->numcomps; + l_img_comp = l_image->comps; + + if (l_size_len > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_size_len); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for the SIZ marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_size_len; + } - l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - /* write SOC identifier */ - opj_write_bytes(l_current_ptr,J2K_MS_SIZ,2); /* SIZ */ - l_current_ptr+=2; + /* write SOC identifier */ + opj_write_bytes(l_current_ptr, J2K_MS_SIZ, 2); /* SIZ */ + l_current_ptr += 2; - opj_write_bytes(l_current_ptr,l_size_len-2,2); /* L_SIZ */ - l_current_ptr+=2; + opj_write_bytes(l_current_ptr, l_size_len - 2, 2); /* L_SIZ */ + l_current_ptr += 2; - opj_write_bytes(l_current_ptr, cp->rsiz, 2); /* Rsiz (capabilities) */ - l_current_ptr+=2; + opj_write_bytes(l_current_ptr, cp->rsiz, 2); /* Rsiz (capabilities) */ + l_current_ptr += 2; - opj_write_bytes(l_current_ptr, l_image->x1, 4); /* Xsiz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->x1, 4); /* Xsiz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, l_image->y1, 4); /* Ysiz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->y1, 4); /* Ysiz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, l_image->x0, 4); /* X0siz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->x0, 4); /* X0siz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, l_image->y0, 4); /* Y0siz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->y0, 4); /* Y0siz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, cp->tdx, 4); /* XTsiz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->tdx, 4); /* XTsiz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, cp->tdy, 4); /* YTsiz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->tdy, 4); /* YTsiz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, cp->tx0, 4); /* XT0siz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->tx0, 4); /* XT0siz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, cp->ty0, 4); /* YT0siz */ - l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->ty0, 4); /* YT0siz */ + l_current_ptr += 4; - opj_write_bytes(l_current_ptr, l_image->numcomps, 2); /* Csiz */ - l_current_ptr+=2; + opj_write_bytes(l_current_ptr, l_image->numcomps, 2); /* Csiz */ + l_current_ptr += 2; - for (i = 0; i < l_image->numcomps; ++i) { - /* TODO here with MCT ? */ - opj_write_bytes(l_current_ptr, l_img_comp->prec - 1 + (l_img_comp->sgnd << 7), 1); /* Ssiz_i */ - ++l_current_ptr; + for (i = 0; i < l_image->numcomps; ++i) { + /* TODO here with MCT ? */ + opj_write_bytes(l_current_ptr, l_img_comp->prec - 1 + (l_img_comp->sgnd << 7), + 1); /* Ssiz_i */ + ++l_current_ptr; - opj_write_bytes(l_current_ptr, l_img_comp->dx, 1); /* XRsiz_i */ - ++l_current_ptr; + opj_write_bytes(l_current_ptr, l_img_comp->dx, 1); /* XRsiz_i */ + ++l_current_ptr; - opj_write_bytes(l_current_ptr, l_img_comp->dy, 1); /* YRsiz_i */ - ++l_current_ptr; + opj_write_bytes(l_current_ptr, l_img_comp->dy, 1); /* YRsiz_i */ + ++l_current_ptr; - ++l_img_comp; - } + ++l_img_comp; + } - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_size_len,p_manager) != l_size_len) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_size_len, + p_manager) != l_size_len) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -1955,113 +2047,137 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, OPJ_BYTE * p_header_data, OPJ_UINT32 p_header_size, opj_event_mgr_t * p_manager - ) + ) { - OPJ_UINT32 i; - OPJ_UINT32 l_nb_comp; - OPJ_UINT32 l_nb_comp_remain; - OPJ_UINT32 l_remaining_size; - OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 l_tmp, l_tx1, l_ty1; - opj_image_t *l_image = 00; - opj_cp_t *l_cp = 00; - opj_image_comp_t * l_img_comp = 00; - opj_tcp_t * l_current_tile_param = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_header_data != 00); - - l_image = p_j2k->m_private_image; - l_cp = &(p_j2k->m_cp); - - /* minimum size == 39 - 3 (= minimum component parameter) */ - if (p_header_size < 36) { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); - return OPJ_FALSE; - } + OPJ_UINT32 i; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_comp_remain; + OPJ_UINT32 l_remaining_size; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_tmp, l_tx1, l_ty1; + OPJ_UINT32 l_prec0, l_sgnd0; + opj_image_t *l_image = 00; + opj_cp_t *l_cp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcp_t * l_current_tile_param = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_image = p_j2k->m_private_image; + l_cp = &(p_j2k->m_cp); + + /* minimum size == 39 - 3 (= minimum component parameter) */ + if (p_header_size < 36) { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return OPJ_FALSE; + } - l_remaining_size = p_header_size - 36; - l_nb_comp = l_remaining_size / 3; - l_nb_comp_remain = l_remaining_size % 3; - if (l_nb_comp_remain != 0){ - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); - return OPJ_FALSE; - } + l_remaining_size = p_header_size - 36; + l_nb_comp = l_remaining_size / 3; + l_nb_comp_remain = l_remaining_size % 3; + if (l_nb_comp_remain != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return OPJ_FALSE; + } - opj_read_bytes(p_header_data,&l_tmp ,2); /* Rsiz (capabilities) */ - p_header_data+=2; - l_cp->rsiz = (OPJ_UINT16) l_tmp; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->x1, 4); /* Xsiz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->y1, 4); /* Ysiz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->x0, 4); /* X0siz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->y0, 4); /* Y0siz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tdx, 4); /* XTsiz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tdy, 4); /* YTsiz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tx0, 4); /* XT0siz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->ty0, 4); /* YT0siz */ - p_header_data+=4; - opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_tmp, 2); /* Csiz */ - p_header_data+=2; - if (l_tmp < 16385) - l_image->numcomps = (OPJ_UINT16) l_tmp; - else { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: number of component is illegal -> %d\n", l_tmp); - return OPJ_FALSE; - } + opj_read_bytes(p_header_data, &l_tmp, + 2); /* Rsiz (capabilities) */ + p_header_data += 2; + l_cp->rsiz = (OPJ_UINT16) l_tmp; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->x1, 4); /* Xsiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->y1, 4); /* Ysiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->x0, 4); /* X0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->y0, 4); /* Y0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tdx, + 4); /* XTsiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tdy, + 4); /* YTsiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tx0, + 4); /* XT0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->ty0, + 4); /* YT0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_tmp, + 2); /* Csiz */ + p_header_data += 2; + if (l_tmp < 16385) { + l_image->numcomps = (OPJ_UINT16) l_tmp; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: number of component is illegal -> %d\n", l_tmp); + return OPJ_FALSE; + } - if (l_image->numcomps != l_nb_comp) { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: number of component is not compatible with the remaining number of parameters ( %d vs %d)\n", l_image->numcomps, l_nb_comp); - return OPJ_FALSE; - } + if (l_image->numcomps != l_nb_comp) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: number of component is not compatible with the remaining number of parameters ( %d vs %d)\n", + l_image->numcomps, l_nb_comp); + return OPJ_FALSE; + } - /* testcase 4035.pdf.SIGSEGV.d8b.3375 */ - /* testcase issue427-null-image-size.jp2 */ - if ((l_image->x0 >= l_image->x1) || (l_image->y0 >= l_image->y1)) { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative or zero image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0); - return OPJ_FALSE; - } - /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */ - if (!(l_cp->tdx * l_cp->tdy)) { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: invalid tile size (tdx: %d, tdy: %d)\n", l_cp->tdx, l_cp->tdy); - return OPJ_FALSE; - } + /* testcase 4035.pdf.SIGSEGV.d8b.3375 */ + /* testcase issue427-null-image-size.jp2 */ + if ((l_image->x0 >= l_image->x1) || (l_image->y0 >= l_image->y1)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: negative or zero image size (%" PRId64 " x %" PRId64 + ")\n", (OPJ_INT64)l_image->x1 - l_image->x0, + (OPJ_INT64)l_image->y1 - l_image->y0); + return OPJ_FALSE; + } + /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */ + if ((l_cp->tdx == 0U) || (l_cp->tdy == 0U)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: invalid tile size (tdx: %d, tdy: %d)\n", l_cp->tdx, + l_cp->tdy); + return OPJ_FALSE; + } - /* testcase 1610.pdf.SIGSEGV.59c.681 */ - if (((OPJ_UINT64)l_image->x1) * ((OPJ_UINT64)l_image->y1) != (l_image->x1 * l_image->y1)) { - opj_event_msg(p_manager, EVT_ERROR, "Prevent buffer overflow (x1: %d, y1: %d)\n", l_image->x1, l_image->y1); - return OPJ_FALSE; - } + /* testcase issue427-illegal-tile-offset.jp2 */ + l_tx1 = opj_uint_adds(l_cp->tx0, l_cp->tdx); /* manage overflow */ + l_ty1 = opj_uint_adds(l_cp->ty0, l_cp->tdy); /* manage overflow */ + if ((l_cp->tx0 > l_image->x0) || (l_cp->ty0 > l_image->y0) || + (l_tx1 <= l_image->x0) || (l_ty1 <= l_image->y0)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: illegal tile offset\n"); + return OPJ_FALSE; + } + if (!p_j2k->dump_state) { + OPJ_UINT32 siz_w, siz_h; - /* testcase issue427-illegal-tile-offset.jp2 */ - l_tx1 = opj_uint_adds(l_cp->tx0, l_cp->tdx); /* manage overflow */ - l_ty1 = opj_uint_adds(l_cp->ty0, l_cp->tdy); /* manage overflow */ - if ((l_cp->tx0 > l_image->x0) || (l_cp->ty0 > l_image->y0) || (l_tx1 <= l_image->x0) || (l_ty1 <= l_image->y0) ) { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: illegal tile offset\n"); - return OPJ_FALSE; - } + siz_w = l_image->x1 - l_image->x0; + siz_h = l_image->y1 - l_image->y0; + if (p_j2k->ihdr_w > 0 && p_j2k->ihdr_h > 0 + && (p_j2k->ihdr_w != siz_w || p_j2k->ihdr_h != siz_h)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: IHDR w(%u) h(%u) vs. SIZ w(%u) h(%u)\n", p_j2k->ihdr_w, + p_j2k->ihdr_h, siz_w, siz_h); + return OPJ_FALSE; + } + } #ifdef USE_JPWL - if (l_cp->correct) { - /* if JPWL is on, we check whether TX errors have damaged - too much the SIZ parameters */ - if (!(l_image->x1 * l_image->y1)) { - opj_event_msg(p_manager, EVT_ERROR, - "JPWL: bad image size (%d x %d)\n", - l_image->x1, l_image->y1); - if (!JPWL_ASSUME || JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - } + if (l_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if (!(l_image->x1 * l_image->y1)) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad image size (%d x %d)\n", + l_image->x1, l_image->y1); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + } /* FIXME check previously in the function so why keep this piece of code ? Need by the norm ? if (l_image->numcomps != ((len - 38) / 3)) { @@ -2086,267 +2202,320 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, } */ - /* update components number in the jpwl_exp_comps filed */ - l_cp->exp_comps = l_image->numcomps; - } + /* update components number in the jpwl_exp_comps filed */ + l_cp->exp_comps = l_image->numcomps; + } #endif /* USE_JPWL */ - /* Allocate the resulting image components */ - l_image->comps = (opj_image_comp_t*) opj_calloc(l_image->numcomps, sizeof(opj_image_comp_t)); - if (l_image->comps == 00){ - l_image->numcomps = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); - return OPJ_FALSE; - } + /* Allocate the resulting image components */ + l_image->comps = (opj_image_comp_t*) opj_calloc(l_image->numcomps, + sizeof(opj_image_comp_t)); + if (l_image->comps == 00) { + l_image->numcomps = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } - l_img_comp = l_image->comps; - - /* Read the component information */ - for (i = 0; i < l_image->numcomps; ++i){ - OPJ_UINT32 tmp; - opj_read_bytes(p_header_data,&tmp,1); /* Ssiz_i */ - ++p_header_data; - l_img_comp->prec = (tmp & 0x7f) + 1; - l_img_comp->sgnd = tmp >> 7; - opj_read_bytes(p_header_data,&tmp,1); /* XRsiz_i */ - ++p_header_data; - l_img_comp->dx = (OPJ_UINT32)tmp; /* should be between 1 and 255 */ - opj_read_bytes(p_header_data,&tmp,1); /* YRsiz_i */ - ++p_header_data; - l_img_comp->dy = (OPJ_UINT32)tmp; /* should be between 1 and 255 */ - if( l_img_comp->dx < 1 || l_img_comp->dx > 255 || - l_img_comp->dy < 1 || l_img_comp->dy > 255 ) { - opj_event_msg(p_manager, EVT_ERROR, - "Invalid values for comp = %d : dx=%u dy=%u (should be between 1 and 255 according to the JPEG2000 norm)\n", - i, l_img_comp->dx, l_img_comp->dy); - return OPJ_FALSE; - } - if( l_img_comp->prec > 38) { /* TODO openjpeg won't handle more than ? */ - opj_event_msg(p_manager, EVT_ERROR, - "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm)\n", - i, l_img_comp->prec); - return OPJ_FALSE; - } + l_img_comp = l_image->comps; -#ifdef USE_JPWL - if (l_cp->correct) { - /* if JPWL is on, we check whether TX errors have damaged - too much the SIZ parameters, again */ - if (!(l_image->comps[i].dx * l_image->comps[i].dy)) { - opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n", - i, i, l_image->comps[i].dx, l_image->comps[i].dy); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - /* we try to correct */ - opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n"); - if (!l_image->comps[i].dx) { - l_image->comps[i].dx = 1; - opj_event_msg(p_manager, EVT_WARNING, "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n", - i, l_image->comps[i].dx); - } - if (!l_image->comps[i].dy) { - l_image->comps[i].dy = 1; - opj_event_msg(p_manager, EVT_WARNING, "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n", - i, l_image->comps[i].dy); - } - } - } -#endif /* USE_JPWL */ - l_img_comp->resno_decoded = 0; /* number of resolution decoded */ - l_img_comp->factor = l_cp->m_specific_param.m_dec.m_reduce; /* reducing factor per component */ - ++l_img_comp; + l_prec0 = 0; + l_sgnd0 = 0; + /* Read the component information */ + for (i = 0; i < l_image->numcomps; ++i) { + OPJ_UINT32 tmp; + opj_read_bytes(p_header_data, &tmp, 1); /* Ssiz_i */ + ++p_header_data; + l_img_comp->prec = (tmp & 0x7f) + 1; + l_img_comp->sgnd = tmp >> 7; + + if (p_j2k->dump_state == 0) { + if (i == 0) { + l_prec0 = l_img_comp->prec; + l_sgnd0 = l_img_comp->sgnd; + } else if (!l_cp->allow_different_bit_depth_sign + && (l_img_comp->prec != l_prec0 || l_img_comp->sgnd != l_sgnd0)) { + opj_event_msg(p_manager, EVT_WARNING, + "Despite JP2 BPC!=255, precision and/or sgnd values for comp[%d] is different than comp[0]:\n" + " [0] prec(%d) sgnd(%d) [%d] prec(%d) sgnd(%d)\n", i, l_prec0, l_sgnd0, + i, l_img_comp->prec, l_img_comp->sgnd); + } + /* TODO: we should perhaps also check against JP2 BPCC values */ } - - /* Compute the number of tiles */ - l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); - l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); - - /* Check that the number of tiles is valid */ - if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) { - opj_event_msg( p_manager, EVT_ERROR, - "Invalid number of tiles : %u x %u (maximum fixed by jpeg2000 norm is 65535 tiles)\n", - l_cp->tw, l_cp->th); + opj_read_bytes(p_header_data, &tmp, 1); /* XRsiz_i */ + ++p_header_data; + l_img_comp->dx = (OPJ_UINT32)tmp; /* should be between 1 and 255 */ + opj_read_bytes(p_header_data, &tmp, 1); /* YRsiz_i */ + ++p_header_data; + l_img_comp->dy = (OPJ_UINT32)tmp; /* should be between 1 and 255 */ + if (l_img_comp->dx < 1 || l_img_comp->dx > 255 || + l_img_comp->dy < 1 || l_img_comp->dy > 255) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid values for comp = %d : dx=%u dy=%u (should be between 1 and 255 according to the JPEG2000 norm)\n", + i, l_img_comp->dx, l_img_comp->dy); return OPJ_FALSE; } - l_nb_tiles = l_cp->tw * l_cp->th; - - /* Define the tiles which will be decoded */ - if (p_j2k->m_specific_param.m_decoder.m_discard_tiles) { - p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv(p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, l_cp->tdx); - p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv(p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, l_cp->tdy); - } - else { - p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; - p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + /* Avoids later undefined shift in computation of */ + /* p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1 + << (l_image->comps[i].prec - 1); */ + if (l_img_comp->prec > 31) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm. OpenJpeg only supports up to 31)\n", + i, l_img_comp->prec); + return OPJ_FALSE; } - #ifdef USE_JPWL if (l_cp->correct) { - /* if JPWL is on, we check whether TX errors have damaged - too much the SIZ parameters */ - if ((l_cp->tw < 1) || (l_cp->th < 1) || (l_cp->tw > l_cp->max_tiles) || (l_cp->th > l_cp->max_tiles)) { - opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: bad number of tiles (%d x %d)\n", - l_cp->tw, l_cp->th); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - /* we try to correct */ - opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n"); - if (l_cp->tw < 1) { - l_cp->tw= 1; - opj_event_msg(p_manager, EVT_WARNING, "- setting %d tiles in x => HYPOTHESIS!!!\n", - l_cp->tw); - } - if (l_cp->tw > l_cp->max_tiles) { - l_cp->tw= 1; - opj_event_msg(p_manager, EVT_WARNING, "- too large x, increase expectance of %d\n" - "- setting %d tiles in x => HYPOTHESIS!!!\n", - l_cp->max_tiles, l_cp->tw); - } - if (l_cp->th < 1) { - l_cp->th= 1; - opj_event_msg(p_manager, EVT_WARNING, "- setting %d tiles in y => HYPOTHESIS!!!\n", - l_cp->th); - } - if (l_cp->th > l_cp->max_tiles) { - l_cp->th= 1; - opj_event_msg(p_manager, EVT_WARNING, "- too large y, increase expectance of %d to continue\n", - "- setting %d tiles in y => HYPOTHESIS!!!\n", - l_cp->max_tiles, l_cp->th); - } + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters, again */ + if (!(l_image->comps[i].dx * l_image->comps[i].dy)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n", + i, i, l_image->comps[i].dx, l_image->comps[i].dy); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n"); + if (!l_image->comps[i].dx) { + l_image->comps[i].dx = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n", + i, l_image->comps[i].dx); } + if (!l_image->comps[i].dy) { + l_image->comps[i].dy = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n", + i, l_image->comps[i].dy); + } + } } #endif /* USE_JPWL */ + l_img_comp->resno_decoded = + 0; /* number of resolution decoded */ + l_img_comp->factor = + l_cp->m_specific_param.m_dec.m_reduce; /* reducing factor per component */ + ++l_img_comp; + } - /* memory allocations */ - l_cp->tcps = (opj_tcp_t*) opj_calloc(l_nb_tiles, sizeof(opj_tcp_t)); - if (l_cp->tcps == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); - return OPJ_FALSE; - } + if (l_cp->tdx == 0 || l_cp->tdy == 0) { + return OPJ_FALSE; + } + + /* Compute the number of tiles */ + l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); + l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); + + /* Check that the number of tiles is valid */ + if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of tiles : %u x %u (maximum fixed by jpeg2000 norm is 65535 tiles)\n", + l_cp->tw, l_cp->th); + return OPJ_FALSE; + } + l_nb_tiles = l_cp->tw * l_cp->th; + + /* Define the tiles which will be decoded */ + if (p_j2k->m_specific_param.m_decoder.m_discard_tiles) { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = + (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = + (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv( + p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, l_cp->tdx); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv( + p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, l_cp->tdy); + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + } #ifdef USE_JPWL - if (l_cp->correct) { - if (!l_cp->tcps) { - opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: could not alloc tcps field of cp\n"); - if (!JPWL_ASSUME || JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - } + if (l_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if ((l_cp->tw < 1) || (l_cp->th < 1) || (l_cp->tw > l_cp->max_tiles) || + (l_cp->th > l_cp->max_tiles)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of tiles (%d x %d)\n", + l_cp->tw, l_cp->th); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n"); + if (l_cp->tw < 1) { + l_cp->tw = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting %d tiles in x => HYPOTHESIS!!!\n", + l_cp->tw); + } + if (l_cp->tw > l_cp->max_tiles) { + l_cp->tw = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- too large x, increase expectance of %d\n" + "- setting %d tiles in x => HYPOTHESIS!!!\n", + l_cp->max_tiles, l_cp->tw); + } + if (l_cp->th < 1) { + l_cp->th = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting %d tiles in y => HYPOTHESIS!!!\n", + l_cp->th); + } + if (l_cp->th > l_cp->max_tiles) { + l_cp->th = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- too large y, increase expectance of %d to continue\n", + "- setting %d tiles in y => HYPOTHESIS!!!\n", + l_cp->max_tiles, l_cp->th); + } } + } #endif /* USE_JPWL */ - p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps = - (opj_tccp_t*) opj_calloc(l_image->numcomps, sizeof(opj_tccp_t)); - if(p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + /* memory allocations */ + l_cp->tcps = (opj_tcp_t*) opj_calloc(l_nb_tiles, sizeof(opj_tcp_t)); + if (l_cp->tcps == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + +#ifdef USE_JPWL + if (l_cp->correct) { + if (!l_cp->tcps) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: could not alloc tcps field of cp\n"); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); return OPJ_FALSE; + } } + } +#endif /* USE_JPWL */ + + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps = + (opj_tccp_t*) opj_calloc(l_image->numcomps, sizeof(opj_tccp_t)); + if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records = - (opj_mct_data_t*)opj_calloc(OPJ_J2K_MCT_DEFAULT_NB_RECORDS ,sizeof(opj_mct_data_t)); + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records = + (opj_mct_data_t*)opj_calloc(OPJ_J2K_MCT_DEFAULT_NB_RECORDS, + sizeof(opj_mct_data_t)); - if (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mct_records = OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + if (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mct_records = + OPJ_J2K_MCT_DEFAULT_NB_RECORDS; - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records = - (opj_simple_mcc_decorrelation_data_t*) - opj_calloc(OPJ_J2K_MCC_DEFAULT_NB_RECORDS, sizeof(opj_simple_mcc_decorrelation_data_t)); + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records = + (opj_simple_mcc_decorrelation_data_t*) + opj_calloc(OPJ_J2K_MCC_DEFAULT_NB_RECORDS, + sizeof(opj_simple_mcc_decorrelation_data_t)); - if (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mcc_records = OPJ_J2K_MCC_DEFAULT_NB_RECORDS; + if (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mcc_records = + OPJ_J2K_MCC_DEFAULT_NB_RECORDS; - /* set up default dc level shift */ - for (i=0;i<l_image->numcomps;++i) { - if (! l_image->comps[i].sgnd) { - p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1 << (l_image->comps[i].prec - 1); - } + /* set up default dc level shift */ + for (i = 0; i < l_image->numcomps; ++i) { + if (! l_image->comps[i].sgnd) { + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1 + << (l_image->comps[i].prec - 1); } + } - l_current_tile_param = l_cp->tcps; - for (i = 0; i < l_nb_tiles; ++i) { - l_current_tile_param->tccps = (opj_tccp_t*) opj_calloc(l_image->numcomps, sizeof(opj_tccp_t)); - if (l_current_tile_param->tccps == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); - return OPJ_FALSE; - } - - ++l_current_tile_param; + l_current_tile_param = l_cp->tcps; + for (i = 0; i < l_nb_tiles; ++i) { + l_current_tile_param->tccps = (opj_tccp_t*) opj_calloc(l_image->numcomps, + sizeof(opj_tccp_t)); + if (l_current_tile_param->tccps == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; } - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MH; /* FIXME J2K_DEC_STATE_MH; */ - opj_image_comp_header_update(l_image,l_cp); + ++l_current_tile_param; + } - return OPJ_TRUE; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MH; + opj_image_comp_header_update(l_image, l_cp); + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_com( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - OPJ_UINT32 l_comment_size; - OPJ_UINT32 l_total_com_size; - const OPJ_CHAR *l_comment; - OPJ_BYTE * l_current_ptr = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - l_comment = p_j2k->m_cp.comment; - l_comment_size = (OPJ_UINT32)strlen(l_comment); - l_total_com_size = l_comment_size + 6; - - if (l_total_com_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_total_com_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write the COM marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_total_com_size; +static OPJ_BOOL opj_j2k_write_com(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_comment_size; + OPJ_UINT32 l_total_com_size; + const OPJ_CHAR *l_comment; + OPJ_BYTE * l_current_ptr = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_comment = p_j2k->m_cp.comment; + l_comment_size = (OPJ_UINT32)strlen(l_comment); + l_total_com_size = l_comment_size + 6; + + if (l_total_com_size > + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_total_com_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to write the COM marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_total_com_size; + } - l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_ptr,J2K_MS_COM , 2); /* COM */ - l_current_ptr+=2; + opj_write_bytes(l_current_ptr, J2K_MS_COM, 2); /* COM */ + l_current_ptr += 2; - opj_write_bytes(l_current_ptr,l_total_com_size - 2 , 2); /* L_COM */ - l_current_ptr+=2; + opj_write_bytes(l_current_ptr, l_total_com_size - 2, 2); /* L_COM */ + l_current_ptr += 2; - opj_write_bytes(l_current_ptr,1 , 2); /* General use (IS 8859-15:1999 (Latin) values) */ - l_current_ptr+=2; + opj_write_bytes(l_current_ptr, 1, + 2); /* General use (IS 8859-15:1999 (Latin) values) */ + l_current_ptr += 2; - memcpy( l_current_ptr,l_comment,l_comment_size); + memcpy(l_current_ptr, l_comment, l_comment_size); - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_total_com_size,p_manager) != l_total_com_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_total_com_size, + p_manager) != l_total_com_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -2356,90 +2525,99 @@ static OPJ_BOOL opj_j2k_write_com( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the COM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_com ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_com(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_header_data != 00); - (void)p_header_size; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); - return OPJ_TRUE; + OPJ_UNUSED(p_j2k); + OPJ_UNUSED(p_header_data); + OPJ_UNUSED(p_header_size); + OPJ_UNUSED(p_manager); + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_cod( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) -{ - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_code_size,l_remaining_size; - OPJ_BYTE * l_current_data = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; - l_code_size = 9 + opj_j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,0); - l_remaining_size = l_code_size; - - if (l_code_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_code_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write COD marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_code_size; +static OPJ_BOOL opj_j2k_write_cod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_code_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_code_size = 9 + opj_j2k_get_SPCod_SPCoc_size(p_j2k, + p_j2k->m_current_tile_number, 0); + l_remaining_size = l_code_size; + + if (l_code_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_code_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write COD marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_code_size; + } - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_COD,2); /* COD */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_COD, 2); /* COD */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_code_size-2,2); /* L_COD */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_code_size - 2, 2); /* L_COD */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_tcp->csty,1); /* Scod */ - ++l_current_data; + opj_write_bytes(l_current_data, l_tcp->csty, 1); /* Scod */ + ++l_current_data; - opj_write_bytes(l_current_data,l_tcp->prg,1); /* SGcod (A) */ - ++l_current_data; + opj_write_bytes(l_current_data, (OPJ_UINT32)l_tcp->prg, 1); /* SGcod (A) */ + ++l_current_data; - opj_write_bytes(l_current_data,l_tcp->numlayers,2); /* SGcod (B) */ - l_current_data+=2; + opj_write_bytes(l_current_data, l_tcp->numlayers, 2); /* SGcod (B) */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_tcp->mct,1); /* SGcod (C) */ - ++l_current_data; + opj_write_bytes(l_current_data, l_tcp->mct, 1); /* SGcod (C) */ + ++l_current_data; - l_remaining_size -= 9; + l_remaining_size -= 9; - if (! opj_j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing COD marker\n"); - return OPJ_FALSE; - } + if (! opj_j2k_write_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, 0, + l_current_data, &l_remaining_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing COD marker\n"); + return OPJ_FALSE; + } - if (l_remaining_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing COD marker\n"); - return OPJ_FALSE; - } + if (l_remaining_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing COD marker\n"); + return OPJ_FALSE; + } - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_code_size,p_manager) != l_code_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_code_size, + p_manager) != l_code_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -2449,226 +2627,263 @@ static OPJ_BOOL opj_j2k_write_cod( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the COD marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_cod ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_cod(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - /* loop */ - OPJ_UINT32 i; - OPJ_UINT32 l_tmp; - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_image_t *l_image = 00; - - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_private_image; - l_cp = &(p_j2k->m_cp); - - /* If we are in the first tile-part header of the current tile */ - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; - - /* Only one COD per tile */ - if (l_tcp->cod) { - opj_event_msg(p_manager, EVT_ERROR, "COD marker already read. No more than one COD marker per tile.\n"); - return OPJ_FALSE; - } - l_tcp->cod = 1; - - /* Make sure room is sufficient */ - if (p_header_size < 5) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); - return OPJ_FALSE; - } + /* loop */ + OPJ_UINT32 i; + OPJ_UINT32 l_tmp; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_image_t *l_image = 00; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + l_cp = &(p_j2k->m_cp); + + /* If we are in the first tile-part header of the current tile */ + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + /* Only one COD per tile */ + if (l_tcp->cod) { + opj_event_msg(p_manager, EVT_ERROR, + "COD marker already read. No more than one COD marker per tile.\n"); + return OPJ_FALSE; + } + l_tcp->cod = 1; - opj_read_bytes(p_header_data,&l_tcp->csty,1); /* Scod */ - ++p_header_data; - /* Make sure we know how to decode this */ - if ((l_tcp->csty & ~(OPJ_UINT32)(J2K_CP_CSTY_PRT | J2K_CP_CSTY_SOP | J2K_CP_CSTY_EPH)) != 0U) { - opj_event_msg(p_manager, EVT_ERROR, "Unknown Scod value in COD marker\n"); - return OPJ_FALSE; - } - opj_read_bytes(p_header_data,&l_tmp,1); /* SGcod (A) */ - ++p_header_data; - l_tcp->prg = (OPJ_PROG_ORDER) l_tmp; - /* Make sure progression order is valid */ - if (l_tcp->prg > OPJ_CPRL ) { - opj_event_msg(p_manager, EVT_ERROR, "Unknown progression order in COD marker\n"); - l_tcp->prg = OPJ_PROG_UNKNOWN; - } - opj_read_bytes(p_header_data,&l_tcp->numlayers,2); /* SGcod (B) */ - p_header_data+=2; - - if ((l_tcp->numlayers < 1U) || (l_tcp->numlayers > 65535U)) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid number of layers in COD marker : %d not in range [1-65535]\n", l_tcp->numlayers); - return OPJ_FALSE; - } + /* Make sure room is sufficient */ + if (p_header_size < 5) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return OPJ_FALSE; + } - /* If user didn't set a number layer to decode take the max specify in the codestream. */ - if (l_cp->m_specific_param.m_dec.m_layer) { - l_tcp->num_layers_to_decode = l_cp->m_specific_param.m_dec.m_layer; - } - else { - l_tcp->num_layers_to_decode = l_tcp->numlayers; - } + opj_read_bytes(p_header_data, &l_tcp->csty, 1); /* Scod */ + ++p_header_data; + /* Make sure we know how to decode this */ + if ((l_tcp->csty & ~(OPJ_UINT32)(J2K_CP_CSTY_PRT | J2K_CP_CSTY_SOP | + J2K_CP_CSTY_EPH)) != 0U) { + opj_event_msg(p_manager, EVT_ERROR, "Unknown Scod value in COD marker\n"); + return OPJ_FALSE; + } + opj_read_bytes(p_header_data, &l_tmp, 1); /* SGcod (A) */ + ++p_header_data; + l_tcp->prg = (OPJ_PROG_ORDER) l_tmp; + /* Make sure progression order is valid */ + if (l_tcp->prg > OPJ_CPRL) { + opj_event_msg(p_manager, EVT_ERROR, + "Unknown progression order in COD marker\n"); + l_tcp->prg = OPJ_PROG_UNKNOWN; + } + opj_read_bytes(p_header_data, &l_tcp->numlayers, 2); /* SGcod (B) */ + p_header_data += 2; - opj_read_bytes(p_header_data,&l_tcp->mct,1); /* SGcod (C) */ - ++p_header_data; + if ((l_tcp->numlayers < 1U) || (l_tcp->numlayers > 65535U)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of layers in COD marker : %d not in range [1-65535]\n", + l_tcp->numlayers); + return OPJ_FALSE; + } - p_header_size -= 5; - for (i = 0; i < l_image->numcomps; ++i) { - l_tcp->tccps[i].csty = l_tcp->csty & J2K_CCP_CSTY_PRT; - } + /* If user didn't set a number layer to decode take the max specify in the codestream. */ + if (l_cp->m_specific_param.m_dec.m_layer) { + l_tcp->num_layers_to_decode = l_cp->m_specific_param.m_dec.m_layer; + } else { + l_tcp->num_layers_to_decode = l_tcp->numlayers; + } - if (! opj_j2k_read_SPCod_SPCoc(p_j2k,0,p_header_data,&p_header_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); - return OPJ_FALSE; - } + opj_read_bytes(p_header_data, &l_tcp->mct, 1); /* SGcod (C) */ + ++p_header_data; - if (p_header_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); - return OPJ_FALSE; - } + p_header_size -= 5; + for (i = 0; i < l_image->numcomps; ++i) { + l_tcp->tccps[i].csty = l_tcp->csty & J2K_CCP_CSTY_PRT; + } + + if (! opj_j2k_read_SPCod_SPCoc(p_j2k, 0, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return OPJ_FALSE; + } + + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return OPJ_FALSE; + } - /* Apply the coding style to other components of the current tile or the m_default_tcp*/ - opj_j2k_copy_tile_component_parameters(p_j2k); + /* Apply the coding style to other components of the current tile or the m_default_tcp*/ + opj_j2k_copy_tile_component_parameters(p_j2k); - /* Index */ + /* Index */ #ifdef WIP_REMOVE_MSD - if (p_j2k->cstr_info) { - /*opj_codestream_info_t *l_cstr_info = p_j2k->cstr_info;*/ - p_j2k->cstr_info->prog = l_tcp->prg; - p_j2k->cstr_info->numlayers = l_tcp->numlayers; - p_j2k->cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(l_image->numcomps * sizeof(OPJ_UINT32)); - for (i = 0; i < l_image->numcomps; ++i) { - p_j2k->cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1; - } + if (p_j2k->cstr_info) { + /*opj_codestream_info_t *l_cstr_info = p_j2k->cstr_info;*/ + p_j2k->cstr_info->prog = l_tcp->prg; + p_j2k->cstr_info->numlayers = l_tcp->numlayers; + p_j2k->cstr_info->numdecompos = (OPJ_INT32*) opj_malloc( + l_image->numcomps * sizeof(OPJ_UINT32)); + if (!p_j2k->cstr_info->numdecompos) { + return OPJ_FALSE; + } + for (i = 0; i < l_image->numcomps; ++i) { + p_j2k->cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1; } + } #endif - return OPJ_TRUE; + return OPJ_TRUE; } -#if 0 -static OPJ_BOOL opj_j2k_write_coc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 l_coc_size,l_remaining_size; - OPJ_UINT32 l_comp_room; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_comp_room = (p_j2k->m_private_image->numcomps <= 256) ? 1 : 2; - - l_coc_size = 5 + l_comp_room + opj_j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); - - if (l_coc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data; - /*p_j2k->m_specific_param.m_encoder.m_header_tile_data - = (OPJ_BYTE*)opj_realloc( - p_j2k->m_specific_param.m_encoder.m_header_tile_data, - l_coc_size);*/ - - new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_coc_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write COC marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size; +static OPJ_BOOL opj_j2k_write_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_coc_size, l_remaining_size; + OPJ_UINT32 l_comp_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_comp_room = (p_j2k->m_private_image->numcomps <= 256) ? 1 : 2; + + l_coc_size = 5 + l_comp_room + opj_j2k_get_SPCod_SPCoc_size(p_j2k, + p_j2k->m_current_tile_number, p_comp_no); + + if (l_coc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data; + /*p_j2k->m_specific_param.m_encoder.m_header_tile_data + = (OPJ_BYTE*)opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_coc_size);*/ + + new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_coc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write COC marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size; + } - opj_j2k_write_coc_in_memory(p_j2k,p_comp_no,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_remaining_size,p_manager); + opj_j2k_write_coc_in_memory(p_j2k, p_comp_no, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, &l_remaining_size, + p_manager); - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_coc_size,p_manager) != l_coc_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_coc_size, + p_manager) != l_coc_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -#endif -#if 0 -static void opj_j2k_write_coc_in_memory( opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_compare_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) { - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_coc_size,l_remaining_size; - OPJ_BYTE * l_current_data = 00; - opj_image_t *l_image = 00; - OPJ_UINT32 l_comp_room; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; - l_image = p_j2k->m_private_image; - l_comp_room = (l_image->numcomps <= 256) ? 1 : 2; + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; - l_coc_size = 5 + l_comp_room + opj_j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); - l_remaining_size = l_coc_size; + if (l_tcp->tccps[p_first_comp_no].csty != l_tcp->tccps[p_second_comp_no].csty) { + return OPJ_FALSE; + } - l_current_data = p_data; - opj_write_bytes(l_current_data,J2K_MS_COC,2); /* COC */ - l_current_data += 2; + return opj_j2k_compare_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, + p_first_comp_no, p_second_comp_no); +} - opj_write_bytes(l_current_data,l_coc_size-2,2); /* L_COC */ - l_current_data += 2; +static void opj_j2k_write_coc_in_memory(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_coc_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + opj_image_t *l_image = 00; + OPJ_UINT32 l_comp_room; - opj_write_bytes(l_current_data,p_comp_no, l_comp_room); /* Ccoc */ - l_current_data+=l_comp_room; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); - opj_write_bytes(l_current_data, l_tcp->tccps[p_comp_no].csty, 1); /* Scoc */ - ++l_current_data; + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_image = p_j2k->m_private_image; + l_comp_room = (l_image->numcomps <= 256) ? 1 : 2; + + l_coc_size = 5 + l_comp_room + opj_j2k_get_SPCod_SPCoc_size(p_j2k, + p_j2k->m_current_tile_number, p_comp_no); + l_remaining_size = l_coc_size; + + l_current_data = p_data; + + opj_write_bytes(l_current_data, J2K_MS_COC, + 2); /* COC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_coc_size - 2, + 2); /* L_COC */ + l_current_data += 2; - l_remaining_size -= (5 + l_comp_room); - opj_j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager); - * p_data_written = l_coc_size; + opj_write_bytes(l_current_data, p_comp_no, l_comp_room); /* Ccoc */ + l_current_data += l_comp_room; + + opj_write_bytes(l_current_data, l_tcp->tccps[p_comp_no].csty, + 1); /* Scoc */ + ++l_current_data; + + l_remaining_size -= (5 + l_comp_room); + opj_j2k_write_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, 0, + l_current_data, &l_remaining_size, p_manager); + * p_data_written = l_coc_size; } -#endif static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k) { - OPJ_UINT32 i,j; - OPJ_UINT32 l_nb_comp; - OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 l_max = 0; + OPJ_UINT32 i, j; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_max = 0; - /* preconditions */ + /* preconditions */ - l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; - l_nb_comp = p_j2k->m_private_image->numcomps; + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; + l_nb_comp = p_j2k->m_private_image->numcomps; - for (i=0;i<l_nb_tiles;++i) { - for (j=0;j<l_nb_comp;++j) { - l_max = opj_uint_max(l_max,opj_j2k_get_SPCod_SPCoc_size(p_j2k,i,j)); - } + for (i = 0; i < l_nb_tiles; ++i) { + for (j = 0; j < l_nb_comp; ++j) { + l_max = opj_uint_max(l_max, opj_j2k_get_SPCod_SPCoc_size(p_j2k, i, j)); } + } - return 6 + l_max; + return 6 + l_max; } /** @@ -2678,114 +2893,124 @@ static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k) * @param p_header_size the size of the data contained in the COC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_coc ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_coc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - opj_cp_t *l_cp = NULL; - opj_tcp_t *l_tcp = NULL; - opj_image_t *l_image = NULL; - OPJ_UINT32 l_comp_room; - OPJ_UINT32 l_comp_no; - - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ) ? /*FIXME J2K_DEC_STATE_TPH*/ - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; - l_image = p_j2k->m_private_image; - - l_comp_room = l_image->numcomps <= 256 ? 1 : 2; - - /* make sure room is sufficient*/ - if (p_header_size < l_comp_room + 1) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); - return OPJ_FALSE; - } - p_header_size -= l_comp_room + 1; - - opj_read_bytes(p_header_data,&l_comp_no,l_comp_room); /* Ccoc */ - p_header_data += l_comp_room; - if (l_comp_no >= l_image->numcomps) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker (bad number of components)\n"); - return OPJ_FALSE; - } + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_image_t *l_image = NULL; + OPJ_UINT32 l_comp_room; + OPJ_UINT32 l_comp_no; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) + ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_image = p_j2k->m_private_image; + + l_comp_room = l_image->numcomps <= 256 ? 1 : 2; + + /* make sure room is sufficient*/ + if (p_header_size < l_comp_room + 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return OPJ_FALSE; + } + p_header_size -= l_comp_room + 1; + + opj_read_bytes(p_header_data, &l_comp_no, + l_comp_room); /* Ccoc */ + p_header_data += l_comp_room; + if (l_comp_no >= l_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading COC marker (bad number of components)\n"); + return OPJ_FALSE; + } - opj_read_bytes(p_header_data,&l_tcp->tccps[l_comp_no].csty,1); /* Scoc */ - ++p_header_data ; + opj_read_bytes(p_header_data, &l_tcp->tccps[l_comp_no].csty, + 1); /* Scoc */ + ++p_header_data ; - if (! opj_j2k_read_SPCod_SPCoc(p_j2k,l_comp_no,p_header_data,&p_header_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); - return OPJ_FALSE; - } + if (! opj_j2k_read_SPCod_SPCoc(p_j2k, l_comp_no, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return OPJ_FALSE; + } - if (p_header_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); - return OPJ_FALSE; - } - return OPJ_TRUE; + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_qcd( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_write_qcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_qcd_size,l_remaining_size; - OPJ_BYTE * l_current_data = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_qcd_size = 4 + opj_j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,0); - l_remaining_size = l_qcd_size; - - if (l_qcd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcd_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write QCD marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcd_size; + OPJ_UINT32 l_qcd_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_qcd_size = 4 + opj_j2k_get_SQcd_SQcc_size(p_j2k, p_j2k->m_current_tile_number, + 0); + l_remaining_size = l_qcd_size; + + if (l_qcd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcd_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write QCD marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcd_size; + } - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_QCD,2); /* QCD */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_QCD, 2); /* QCD */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_qcd_size-2,2); /* L_QCD */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_qcd_size - 2, 2); /* L_QCD */ + l_current_data += 2; - l_remaining_size -= 4; + l_remaining_size -= 4; - if (! opj_j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing QCD marker\n"); - return OPJ_FALSE; - } + if (! opj_j2k_write_SQcd_SQcc(p_j2k, p_j2k->m_current_tile_number, 0, + l_current_data, &l_remaining_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing QCD marker\n"); + return OPJ_FALSE; + } - if (l_remaining_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing QCD marker\n"); - return OPJ_FALSE; - } + if (l_remaining_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing QCD marker\n"); + return OPJ_FALSE; + } - if (opj_stream_write_data(p_stream, p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcd_size,p_manager) != l_qcd_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcd_size, + p_manager) != l_qcd_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -2795,128 +3020,139 @@ static OPJ_BOOL opj_j2k_write_qcd( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the QCD marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_qcd ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_qcd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - if (! opj_j2k_read_SQcd_SQcc(p_j2k,0,p_header_data,&p_header_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); - return OPJ_FALSE; - } + if (! opj_j2k_read_SQcd_SQcc(p_j2k, 0, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); + return OPJ_FALSE; + } - if (p_header_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); - return OPJ_FALSE; - } + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); + return OPJ_FALSE; + } - /* Apply the quantization parameters to other components of the current tile or the m_default_tcp */ - opj_j2k_copy_tile_quantization_parameters(p_j2k); + /* Apply the quantization parameters to other components of the current tile or the m_default_tcp */ + opj_j2k_copy_tile_quantization_parameters(p_j2k); - return OPJ_TRUE; + return OPJ_TRUE; } -#if 0 -static OPJ_BOOL opj_j2k_write_qcc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - OPJ_UINT32 l_qcc_size,l_remaining_size; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_qcc_size = 5 + opj_j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); - l_qcc_size += p_j2k->m_private_image->numcomps <= 256 ? 0:1; - l_remaining_size = l_qcc_size; - - if (l_qcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcc_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write QCC marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size; +static OPJ_BOOL opj_j2k_write_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_qcc_size, l_remaining_size; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_qcc_size = 5 + opj_j2k_get_SQcd_SQcc_size(p_j2k, p_j2k->m_current_tile_number, + p_comp_no); + l_qcc_size += p_j2k->m_private_image->numcomps <= 256 ? 0 : 1; + l_remaining_size = l_qcc_size; + + if (l_qcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write QCC marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size; + } - opj_j2k_write_qcc_in_memory(p_j2k,p_comp_no,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_remaining_size,p_manager); + opj_j2k_write_qcc_in_memory(p_j2k, p_comp_no, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, &l_remaining_size, + p_manager); - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcc_size,p_manager) != l_qcc_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcc_size, + p_manager) != l_qcc_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -#endif -#if 0 -static void opj_j2k_write_qcc_in_memory( opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_compare_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) +{ + return opj_j2k_compare_SQcd_SQcc(p_j2k, p_j2k->m_current_tile_number, + p_first_comp_no, p_second_comp_no); +} + +static void opj_j2k_write_qcc_in_memory(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_qcc_size,l_remaining_size; - OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_qcc_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); - l_qcc_size = 6 + opj_j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); - l_remaining_size = l_qcc_size; + l_qcc_size = 6 + opj_j2k_get_SQcd_SQcc_size(p_j2k, p_j2k->m_current_tile_number, + p_comp_no); + l_remaining_size = l_qcc_size; - l_current_data = p_data; + l_current_data = p_data; - opj_write_bytes(l_current_data,J2K_MS_QCC,2); /* QCC */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_QCC, 2); /* QCC */ + l_current_data += 2; - if (p_j2k->m_private_image->numcomps <= 256) { - --l_qcc_size; + if (p_j2k->m_private_image->numcomps <= 256) { + --l_qcc_size; - opj_write_bytes(l_current_data,l_qcc_size-2,2); /* L_QCC */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_qcc_size - 2, 2); /* L_QCC */ + l_current_data += 2; - opj_write_bytes(l_current_data, p_comp_no, 1); /* Cqcc */ - ++l_current_data; + opj_write_bytes(l_current_data, p_comp_no, 1); /* Cqcc */ + ++l_current_data; - /* in the case only one byte is sufficient the last byte allocated is useless -> still do -6 for available */ - l_remaining_size -= 6; - } - else { - opj_write_bytes(l_current_data,l_qcc_size-2,2); /* L_QCC */ - l_current_data += 2; + /* in the case only one byte is sufficient the last byte allocated is useless -> still do -6 for available */ + l_remaining_size -= 6; + } else { + opj_write_bytes(l_current_data, l_qcc_size - 2, 2); /* L_QCC */ + l_current_data += 2; - opj_write_bytes(l_current_data, p_comp_no, 2); /* Cqcc */ - l_current_data+=2; + opj_write_bytes(l_current_data, p_comp_no, 2); /* Cqcc */ + l_current_data += 2; - l_remaining_size -= 6; - } + l_remaining_size -= 6; + } - opj_j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,p_comp_no,l_current_data,&l_remaining_size,p_manager); + opj_j2k_write_SQcd_SQcc(p_j2k, p_j2k->m_current_tile_number, p_comp_no, + l_current_data, &l_remaining_size, p_manager); - *p_data_written = l_qcc_size; + *p_data_written = l_qcc_size; } -#endif -static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k) +static OPJ_UINT32 opj_j2k_get_max_qcc_size(opj_j2k_t *p_j2k) { - return opj_j2k_get_max_coc_size(p_j2k); + return opj_j2k_get_max_coc_size(p_j2k); } /** @@ -2926,273 +3162,289 @@ static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_t *p_j2k) * @param p_header_size the size of the data contained in the QCC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_qcc( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_qcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_num_comp,l_comp_no; + OPJ_UINT32 l_num_comp, l_comp_no; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_num_comp = p_j2k->m_private_image->numcomps; + l_num_comp = p_j2k->m_private_image->numcomps; - if (l_num_comp <= 256) { - if (p_header_size < 1) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); - return OPJ_FALSE; - } - opj_read_bytes(p_header_data,&l_comp_no,1); - ++p_header_data; - --p_header_size; + if (l_num_comp <= 256) { + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; } - else { - if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); - return OPJ_FALSE; - } - opj_read_bytes(p_header_data,&l_comp_no,2); - p_header_data+=2; - p_header_size-=2; + opj_read_bytes(p_header_data, &l_comp_no, 1); + ++p_header_data; + --p_header_size; + } else { + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; } + opj_read_bytes(p_header_data, &l_comp_no, 2); + p_header_data += 2; + p_header_size -= 2; + } #ifdef USE_JPWL - if (p_j2k->m_cp.correct) { + if (p_j2k->m_cp.correct) { - static OPJ_UINT32 backup_compno = 0; + static OPJ_UINT32 backup_compno = 0; - /* compno is negative or larger than the number of components!!! */ - if (/*(l_comp_no < 0) ||*/ (l_comp_no >= l_num_comp)) { - opj_event_msg(p_manager, EVT_ERROR, - "JPWL: bad component number in QCC (%d out of a maximum of %d)\n", - l_comp_no, l_num_comp); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - /* we try to correct */ - l_comp_no = backup_compno % l_num_comp; - opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" - "- setting component number to %d\n", - l_comp_no); - } + /* compno is negative or larger than the number of components!!! */ + if (/*(l_comp_no < 0) ||*/ (l_comp_no >= l_num_comp)) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad component number in QCC (%d out of a maximum of %d)\n", + l_comp_no, l_num_comp); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + l_comp_no = backup_compno % l_num_comp; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" + "- setting component number to %d\n", + l_comp_no); + } - /* keep your private count of tiles */ - backup_compno++; - }; + /* keep your private count of tiles */ + backup_compno++; + }; #endif /* USE_JPWL */ - if (l_comp_no >= p_j2k->m_private_image->numcomps) { - opj_event_msg(p_manager, EVT_ERROR, - "Invalid component number: %d, regarding the number of components %d\n", - l_comp_no, p_j2k->m_private_image->numcomps); - return OPJ_FALSE; - } + if (l_comp_no >= p_j2k->m_private_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid component number: %d, regarding the number of components %d\n", + l_comp_no, p_j2k->m_private_image->numcomps); + return OPJ_FALSE; + } - if (! opj_j2k_read_SQcd_SQcc(p_j2k,l_comp_no,p_header_data,&p_header_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); - return OPJ_FALSE; - } + if (! opj_j2k_read_SQcd_SQcc(p_j2k, l_comp_no, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; + } - if (p_header_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); - return OPJ_FALSE; - } + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_poc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_write_poc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_nb_comp; - OPJ_UINT32 l_nb_poc; - OPJ_UINT32 l_poc_size; - OPJ_UINT32 l_written_size = 0; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_poc_room; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + OPJ_UINT32 l_written_size = 0; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_poc_room; - l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; - l_nb_comp = p_j2k->m_private_image->numcomps; - l_nb_poc = 1 + l_tcp->numpocs; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - if (l_nb_comp <= 256) { - l_poc_room = 1; - } - else { - l_poc_room = 2; - } - l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_nb_comp = p_j2k->m_private_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; - if (l_poc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_poc_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write POC marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size; + if (l_nb_comp <= 256) { + l_poc_room = 1; + } else { + l_poc_room = 2; + } + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + + if (l_poc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_poc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write POC marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size; + } - opj_j2k_write_poc_in_memory(p_j2k,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_written_size,p_manager); + opj_j2k_write_poc_in_memory(p_j2k, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, &l_written_size, + p_manager); - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_poc_size,p_manager) != l_poc_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_poc_size, + p_manager) != l_poc_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static void opj_j2k_write_poc_in_memory( opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - opj_event_mgr_t * p_manager - ) +static void opj_j2k_write_poc_in_memory(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 i; - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_nb_comp; - OPJ_UINT32 l_nb_poc; - OPJ_UINT32 l_poc_size; - opj_image_t *l_image = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; - opj_poc_t *l_current_poc = 00; - OPJ_UINT32 l_poc_room; + OPJ_UINT32 i; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + opj_image_t *l_image = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + opj_poc_t *l_current_poc = 00; + OPJ_UINT32 l_poc_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_manager); + + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_tccp = &l_tcp->tccps[0]; + l_image = p_j2k->m_private_image; + l_nb_comp = l_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; + + if (l_nb_comp <= 256) { + l_poc_room = 1; + } else { + l_poc_room = 2; + } - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; - l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; - l_tccp = &l_tcp->tccps[0]; - l_image = p_j2k->m_private_image; - l_nb_comp = l_image->numcomps; - l_nb_poc = 1 + l_tcp->numpocs; + l_current_data = p_data; - if (l_nb_comp <= 256) { - l_poc_room = 1; - } - else { - l_poc_room = 2; - } + opj_write_bytes(l_current_data, J2K_MS_POC, + 2); /* POC */ + l_current_data += 2; - l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + opj_write_bytes(l_current_data, l_poc_size - 2, + 2); /* Lpoc */ + l_current_data += 2; - l_current_data = p_data; + l_current_poc = l_tcp->pocs; + for (i = 0; i < l_nb_poc; ++i) { + opj_write_bytes(l_current_data, l_current_poc->resno0, + 1); /* RSpoc_i */ + ++l_current_data; - opj_write_bytes(l_current_data,J2K_MS_POC,2); /* POC */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_current_poc->compno0, + l_poc_room); /* CSpoc_i */ + l_current_data += l_poc_room; - opj_write_bytes(l_current_data,l_poc_size-2,2); /* Lpoc */ + opj_write_bytes(l_current_data, l_current_poc->layno1, + 2); /* LYEpoc_i */ l_current_data += 2; - l_current_poc = l_tcp->pocs; - for (i = 0; i < l_nb_poc; ++i) { - opj_write_bytes(l_current_data,l_current_poc->resno0,1); /* RSpoc_i */ - ++l_current_data; - - opj_write_bytes(l_current_data,l_current_poc->compno0,l_poc_room); /* CSpoc_i */ - l_current_data+=l_poc_room; - - opj_write_bytes(l_current_data,l_current_poc->layno1,2); /* LYEpoc_i */ - l_current_data+=2; - - opj_write_bytes(l_current_data,l_current_poc->resno1,1); /* REpoc_i */ - ++l_current_data; + opj_write_bytes(l_current_data, l_current_poc->resno1, + 1); /* REpoc_i */ + ++l_current_data; - opj_write_bytes(l_current_data,l_current_poc->compno1,l_poc_room); /* CEpoc_i */ - l_current_data+=l_poc_room; + opj_write_bytes(l_current_data, l_current_poc->compno1, + l_poc_room); /* CEpoc_i */ + l_current_data += l_poc_room; - opj_write_bytes(l_current_data,l_current_poc->prg,1); /* Ppoc_i */ - ++l_current_data; + opj_write_bytes(l_current_data, (OPJ_UINT32)l_current_poc->prg, + 1); /* Ppoc_i */ + ++l_current_data; - /* change the value of the max layer according to the actual number of layers in the file, components and resolutions*/ - l_current_poc->layno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32)l_current_poc->layno1, (OPJ_INT32)l_tcp->numlayers); - l_current_poc->resno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32)l_current_poc->resno1, (OPJ_INT32)l_tccp->numresolutions); - l_current_poc->compno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32)l_current_poc->compno1, (OPJ_INT32)l_nb_comp); + /* change the value of the max layer according to the actual number of layers in the file, components and resolutions*/ + l_current_poc->layno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32) + l_current_poc->layno1, (OPJ_INT32)l_tcp->numlayers); + l_current_poc->resno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32) + l_current_poc->resno1, (OPJ_INT32)l_tccp->numresolutions); + l_current_poc->compno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32) + l_current_poc->compno1, (OPJ_INT32)l_nb_comp); - ++l_current_poc; - } + ++l_current_poc; + } - *p_data_written = l_poc_size; + *p_data_written = l_poc_size; } static OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_t *p_j2k) { - opj_tcp_t * l_tcp = 00; - OPJ_UINT32 l_nb_tiles = 0; - OPJ_UINT32 l_max_poc = 0; - OPJ_UINT32 i; + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 l_nb_tiles = 0; + OPJ_UINT32 l_max_poc = 0; + OPJ_UINT32 i; - l_tcp = p_j2k->m_cp.tcps; - l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - for (i=0;i<l_nb_tiles;++i) { - l_max_poc = opj_uint_max(l_max_poc,l_tcp->numpocs); - ++l_tcp; - } + for (i = 0; i < l_nb_tiles; ++i) { + l_max_poc = opj_uint_max(l_max_poc, l_tcp->numpocs); + ++l_tcp; + } - ++l_max_poc; + ++l_max_poc; - return 4 + 9 * l_max_poc; + return 4 + 9 * l_max_poc; } -static OPJ_UINT32 opj_j2k_get_max_toc_size (opj_j2k_t *p_j2k) +static OPJ_UINT32 opj_j2k_get_max_toc_size(opj_j2k_t *p_j2k) { - OPJ_UINT32 i; - OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 l_max = 0; - opj_tcp_t * l_tcp = 00; + OPJ_UINT32 i; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_max = 0; + opj_tcp_t * l_tcp = 00; - l_tcp = p_j2k->m_cp.tcps; - l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; + l_tcp = p_j2k->m_cp.tcps; + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; - for (i=0;i<l_nb_tiles;++i) { - l_max = opj_uint_max(l_max,l_tcp->m_nb_tile_parts); + for (i = 0; i < l_nb_tiles; ++i) { + l_max = opj_uint_max(l_max, l_tcp->m_nb_tile_parts); - ++l_tcp; - } + ++l_tcp; + } - return 12 * l_max; + return 12 * l_max; } static OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k) { - OPJ_UINT32 l_nb_bytes = 0; - OPJ_UINT32 l_nb_comps; - OPJ_UINT32 l_coc_bytes,l_qcc_bytes; + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_coc_bytes, l_qcc_bytes; - l_nb_comps = p_j2k->m_private_image->numcomps - 1; - l_nb_bytes += opj_j2k_get_max_toc_size(p_j2k); + l_nb_comps = p_j2k->m_private_image->numcomps - 1; + l_nb_bytes += opj_j2k_get_max_toc_size(p_j2k); - if (!(OPJ_IS_CINEMA(p_j2k->m_cp.rsiz))) { - l_coc_bytes = opj_j2k_get_max_coc_size(p_j2k); - l_nb_bytes += l_nb_comps * l_coc_bytes; + if (!(OPJ_IS_CINEMA(p_j2k->m_cp.rsiz))) { + l_coc_bytes = opj_j2k_get_max_coc_size(p_j2k); + l_nb_bytes += l_nb_comps * l_coc_bytes; - l_qcc_bytes = opj_j2k_get_max_qcc_size(p_j2k); - l_nb_bytes += l_nb_comps * l_qcc_bytes; - } + l_qcc_bytes = opj_j2k_get_max_qcc_size(p_j2k); + l_nb_bytes += l_nb_comps * l_qcc_bytes; + } - l_nb_bytes += opj_j2k_get_max_poc_size(p_j2k); + l_nb_bytes += opj_j2k_get_max_poc_size(p_j2k); - /*** DEVELOPER CORNER, Add room for your headers ***/ + /*** DEVELOPER CORNER, Add room for your headers ***/ - return l_nb_bytes; + return l_nb_bytes; } /** @@ -3203,84 +3455,87 @@ static OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k) * @param p_header_size the size of the data contained in the POC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_poc ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_poc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 i, l_nb_comp, l_tmp; - opj_image_t * l_image = 00; - OPJ_UINT32 l_old_poc_nb, l_current_poc_nb, l_current_poc_remaining; - OPJ_UINT32 l_chunk_size, l_comp_room; + OPJ_UINT32 i, l_nb_comp, l_tmp; + opj_image_t * l_image = 00; + OPJ_UINT32 l_old_poc_nb, l_current_poc_nb, l_current_poc_remaining; + OPJ_UINT32 l_chunk_size, l_comp_room; - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_poc_t *l_current_poc = 00; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_poc_t *l_current_poc = 00; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_image = p_j2k->m_private_image; - l_nb_comp = l_image->numcomps; - if (l_nb_comp <= 256) { - l_comp_room = 1; - } - else { - l_comp_room = 2; - } - l_chunk_size = 5 + 2 * l_comp_room; - l_current_poc_nb = p_header_size / l_chunk_size; - l_current_poc_remaining = p_header_size % l_chunk_size; + l_image = p_j2k->m_private_image; + l_nb_comp = l_image->numcomps; + if (l_nb_comp <= 256) { + l_comp_room = 1; + } else { + l_comp_room = 2; + } + l_chunk_size = 5 + 2 * l_comp_room; + l_current_poc_nb = p_header_size / l_chunk_size; + l_current_poc_remaining = p_header_size % l_chunk_size; - if ((l_current_poc_nb <= 0) || (l_current_poc_remaining != 0)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading POC marker\n"); - return OPJ_FALSE; - } + if ((l_current_poc_nb <= 0) || (l_current_poc_remaining != 0)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading POC marker\n"); + return OPJ_FALSE; + } - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; - l_old_poc_nb = l_tcp->POC ? l_tcp->numpocs + 1 : 0; - l_current_poc_nb += l_old_poc_nb; - - if(l_current_poc_nb >= 32) - { - opj_event_msg(p_manager, EVT_ERROR, "Too many POCs %d\n", l_current_poc_nb); - return OPJ_FALSE; - } - assert(l_current_poc_nb < 32); - - /* now poc is in use.*/ - l_tcp->POC = 1; - - l_current_poc = &l_tcp->pocs[l_old_poc_nb]; - for (i = l_old_poc_nb; i < l_current_poc_nb; ++i) { - opj_read_bytes(p_header_data,&(l_current_poc->resno0),1); /* RSpoc_i */ - ++p_header_data; - opj_read_bytes(p_header_data,&(l_current_poc->compno0),l_comp_room); /* CSpoc_i */ - p_header_data+=l_comp_room; - opj_read_bytes(p_header_data,&(l_current_poc->layno1),2); /* LYEpoc_i */ - /* make sure layer end is in acceptable bounds */ - l_current_poc->layno1 = opj_uint_min(l_current_poc->layno1, l_tcp->numlayers); - p_header_data+=2; - opj_read_bytes(p_header_data,&(l_current_poc->resno1),1); /* REpoc_i */ - ++p_header_data; - opj_read_bytes(p_header_data,&(l_current_poc->compno1),l_comp_room); /* CEpoc_i */ - p_header_data+=l_comp_room; - opj_read_bytes(p_header_data,&l_tmp,1); /* Ppoc_i */ - ++p_header_data; - l_current_poc->prg = (OPJ_PROG_ORDER) l_tmp; - /* make sure comp is in acceptable bounds */ - l_current_poc->compno1 = opj_uint_min(l_current_poc->compno1, l_nb_comp); - ++l_current_poc; - } - - l_tcp->numpocs = l_current_poc_nb - 1; - return OPJ_TRUE; + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_old_poc_nb = l_tcp->POC ? l_tcp->numpocs + 1 : 0; + l_current_poc_nb += l_old_poc_nb; + + if (l_current_poc_nb >= J2K_MAX_POCS) { + opj_event_msg(p_manager, EVT_ERROR, "Too many POCs %d\n", l_current_poc_nb); + return OPJ_FALSE; + } + + /* now poc is in use.*/ + l_tcp->POC = 1; + + l_current_poc = &l_tcp->pocs[l_old_poc_nb]; + for (i = l_old_poc_nb; i < l_current_poc_nb; ++i) { + opj_read_bytes(p_header_data, &(l_current_poc->resno0), + 1); /* RSpoc_i */ + ++p_header_data; + opj_read_bytes(p_header_data, &(l_current_poc->compno0), + l_comp_room); /* CSpoc_i */ + p_header_data += l_comp_room; + opj_read_bytes(p_header_data, &(l_current_poc->layno1), + 2); /* LYEpoc_i */ + /* make sure layer end is in acceptable bounds */ + l_current_poc->layno1 = opj_uint_min(l_current_poc->layno1, l_tcp->numlayers); + p_header_data += 2; + opj_read_bytes(p_header_data, &(l_current_poc->resno1), + 1); /* REpoc_i */ + ++p_header_data; + opj_read_bytes(p_header_data, &(l_current_poc->compno1), + l_comp_room); /* CEpoc_i */ + p_header_data += l_comp_room; + opj_read_bytes(p_header_data, &l_tmp, + 1); /* Ppoc_i */ + ++p_header_data; + l_current_poc->prg = (OPJ_PROG_ORDER) l_tmp; + /* make sure comp is in acceptable bounds */ + l_current_poc->compno1 = opj_uint_min(l_current_poc->compno1, l_nb_comp); + ++l_current_poc; + } + + l_tcp->numpocs = l_current_poc_nb - 1; + return OPJ_TRUE; } /** @@ -3291,36 +3546,38 @@ static OPJ_BOOL opj_j2k_read_poc ( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the TLM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_crg ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_crg(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_nb_comp; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + OPJ_UINT32 l_nb_comp; + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_nb_comp = p_j2k->m_private_image->numcomps; + OPJ_UNUSED(p_header_data); - if (p_header_size != l_nb_comp *4) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading CRG marker\n"); - return OPJ_FALSE; - } - /* Do not care of this at the moment since only local variables are set here */ - /* - for - (i = 0; i < l_nb_comp; ++i) - { - opj_read_bytes(p_header_data,&l_Xcrg_i,2); // Xcrg_i - p_header_data+=2; - opj_read_bytes(p_header_data,&l_Ycrg_i,2); // Xcrg_i - p_header_data+=2; - } - */ - return OPJ_TRUE; + l_nb_comp = p_j2k->m_private_image->numcomps; + + if (p_header_size != l_nb_comp * 4) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading CRG marker\n"); + return OPJ_FALSE; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + for + (i = 0; i < l_nb_comp; ++i) + { + opj_read_bytes(p_header_data,&l_Xcrg_i,2); // Xcrg_i + p_header_data+=2; + opj_read_bytes(p_header_data,&l_Ycrg_i,2); // Xcrg_i + p_header_data+=2; + } + */ + return OPJ_TRUE; } /** @@ -3331,52 +3588,57 @@ static OPJ_BOOL opj_j2k_read_crg ( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the TLM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_tlm ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_tlm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, l_tot_num_tp_remaining, l_quotient, l_Ptlm_size; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, l_tot_num_tp_remaining, l_quotient, + l_Ptlm_size; + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); - return OPJ_FALSE; - } - p_header_size -= 2; + OPJ_UNUSED(p_j2k); - opj_read_bytes(p_header_data,&l_Ztlm,1); /* Ztlm */ - ++p_header_data; - opj_read_bytes(p_header_data,&l_Stlm,1); /* Stlm */ - ++p_header_data; + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + return OPJ_FALSE; + } + p_header_size -= 2; - l_ST = ((l_Stlm >> 4) & 0x3); - l_SP = (l_Stlm >> 6) & 0x1; + opj_read_bytes(p_header_data, &l_Ztlm, + 1); /* Ztlm */ + ++p_header_data; + opj_read_bytes(p_header_data, &l_Stlm, + 1); /* Stlm */ + ++p_header_data; - l_Ptlm_size = (l_SP + 1) * 2; - l_quotient = l_Ptlm_size + l_ST; + l_ST = ((l_Stlm >> 4) & 0x3); + l_SP = (l_Stlm >> 6) & 0x1; - l_tot_num_tp_remaining = p_header_size % l_quotient; + l_Ptlm_size = (l_SP + 1) * 2; + l_quotient = l_Ptlm_size + l_ST; - if (l_tot_num_tp_remaining != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); - return OPJ_FALSE; - } - /* FIXME Do not care of this at the moment since only local variables are set here */ - /* - for - (i = 0; i < l_tot_num_tp; ++i) - { - opj_read_bytes(p_header_data,&l_Ttlm_i,l_ST); // Ttlm_i - p_header_data += l_ST; - opj_read_bytes(p_header_data,&l_Ptlm_i,l_Ptlm_size); // Ptlm_i - p_header_data += l_Ptlm_size; - }*/ - return OPJ_TRUE; + l_tot_num_tp_remaining = p_header_size % l_quotient; + + if (l_tot_num_tp_remaining != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + return OPJ_FALSE; + } + /* FIXME Do not care of this at the moment since only local variables are set here */ + /* + for + (i = 0; i < l_tot_num_tp; ++i) + { + opj_read_bytes(p_header_data,&l_Ttlm_i,l_ST); // Ttlm_i + p_header_data += l_ST; + opj_read_bytes(p_header_data,&l_Ptlm_i,l_Ptlm_size); // Ptlm_i + p_header_data += l_Ptlm_size; + }*/ + return OPJ_TRUE; } /** @@ -3387,66 +3649,69 @@ static OPJ_BOOL opj_j2k_read_tlm ( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the TLM marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_plm ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_plm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - if (p_header_size < 1) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); - return OPJ_FALSE; - } - /* Do not care of this at the moment since only local variables are set here */ - /* - opj_read_bytes(p_header_data,&l_Zplm,1); // Zplm - ++p_header_data; - --p_header_size; + OPJ_UNUSED(p_j2k); + OPJ_UNUSED(p_header_data); - while - (p_header_size > 0) - { - opj_read_bytes(p_header_data,&l_Nplm,1); // Nplm - ++p_header_data; - p_header_size -= (1+l_Nplm); - if - (p_header_size < 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); - return false; - } - for - (i = 0; i < l_Nplm; ++i) - { - opj_read_bytes(p_header_data,&l_tmp,1); // Iplm_ij - ++p_header_data; - // take only the last seven bytes - l_packet_len |= (l_tmp & 0x7f); - if - (l_tmp & 0x80) - { - l_packet_len <<= 7; - } - else - { - // store packet length and proceed to next packet - l_packet_len = 0; - } - } - if - (l_packet_len != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); - return false; - } - } - */ - return OPJ_TRUE; + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return OPJ_FALSE; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + opj_read_bytes(p_header_data,&l_Zplm,1); // Zplm + ++p_header_data; + --p_header_size; + + while + (p_header_size > 0) + { + opj_read_bytes(p_header_data,&l_Nplm,1); // Nplm + ++p_header_data; + p_header_size -= (1+l_Nplm); + if + (p_header_size < 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + for + (i = 0; i < l_Nplm; ++i) + { + opj_read_bytes(p_header_data,&l_tmp,1); // Iplm_ij + ++p_header_data; + // take only the last seven bytes + l_packet_len |= (l_tmp & 0x7f); + if + (l_tmp & 0x80) + { + l_packet_len <<= 7; + } + else + { + // store packet length and proceed to next packet + l_packet_len = 0; + } + } + if + (l_packet_len != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + } + */ + return OPJ_TRUE; } /** @@ -3457,48 +3722,49 @@ static OPJ_BOOL opj_j2k_read_plm ( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the PLT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_plt ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_plt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_Zplt, l_tmp, l_packet_len = 0, i; + OPJ_UINT32 l_Zplt, l_tmp, l_packet_len = 0, i; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - if (p_header_size < 1) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n"); - return OPJ_FALSE; - } + OPJ_UNUSED(p_j2k); - opj_read_bytes(p_header_data,&l_Zplt,1); /* Zplt */ - ++p_header_data; - --p_header_size; + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n"); + return OPJ_FALSE; + } - for (i = 0; i < p_header_size; ++i) { - opj_read_bytes(p_header_data,&l_tmp,1); /* Iplt_ij */ - ++p_header_data; - /* take only the last seven bytes */ - l_packet_len |= (l_tmp & 0x7f); - if (l_tmp & 0x80) { - l_packet_len <<= 7; - } - else { + opj_read_bytes(p_header_data, &l_Zplt, 1); /* Zplt */ + ++p_header_data; + --p_header_size; + + for (i = 0; i < p_header_size; ++i) { + opj_read_bytes(p_header_data, &l_tmp, 1); /* Iplt_ij */ + ++p_header_data; + /* take only the last seven bytes */ + l_packet_len |= (l_tmp & 0x7f); + if (l_tmp & 0x80) { + l_packet_len <<= 7; + } else { /* store packet length and proceed to next packet */ - l_packet_len = 0; - } + l_packet_len = 0; } + } - if (l_packet_len != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n"); - return OPJ_FALSE; - } + if (l_packet_len != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -3510,74 +3776,76 @@ static OPJ_BOOL opj_j2k_read_plt ( opj_j2k_t *p_j2k, * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_ppm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ) -{ - opj_cp_t *l_cp = 00; - OPJ_UINT32 l_Z_ppm; - - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - /* We need to have the Z_ppm element + 1 byte of Nppm/Ippm at minimum */ - if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n"); - return OPJ_FALSE; - } - - l_cp = &(p_j2k->m_cp); - l_cp->ppm = 1; - - opj_read_bytes(p_header_data,&l_Z_ppm,1); /* Z_ppm */ - ++p_header_data; - --p_header_size; - - /* check allocation needed */ - if (l_cp->ppm_markers == NULL) { /* first PPM marker */ - OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */ - assert(l_cp->ppm_markers_count == 0U); - - l_cp->ppm_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx)); - if (l_cp->ppm_markers == NULL) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); - return OPJ_FALSE; - } - l_cp->ppm_markers_count = l_newCount; - } else if (l_cp->ppm_markers_count <= l_Z_ppm) { - OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */ - opj_ppx *new_ppm_markers; - new_ppm_markers = (opj_ppx *) opj_realloc(l_cp->ppm_markers, l_newCount * sizeof(opj_ppx)); - if (new_ppm_markers == NULL) { - /* clean up to be done on l_cp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); - return OPJ_FALSE; - } - l_cp->ppm_markers = new_ppm_markers; - memset(l_cp->ppm_markers + l_cp->ppm_markers_count, 0, (l_newCount - l_cp->ppm_markers_count) * sizeof(opj_ppx)); - l_cp->ppm_markers_count = l_newCount; - } - - if (l_cp->ppm_markers[l_Z_ppm].m_data != NULL) { - /* clean up to be done on l_cp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Zppm %u already read\n", l_Z_ppm); - return OPJ_FALSE; - } - - l_cp->ppm_markers[l_Z_ppm].m_data = opj_malloc(p_header_size); - if (l_cp->ppm_markers[l_Z_ppm].m_data == NULL) { - /* clean up to be done on l_cp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); - return OPJ_FALSE; - } - l_cp->ppm_markers[l_Z_ppm].m_data_size = p_header_size; - memcpy(l_cp->ppm_markers[l_Z_ppm].m_data, p_header_data, p_header_size); - - return OPJ_TRUE; +static OPJ_BOOL opj_j2k_read_ppm( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager) +{ + opj_cp_t *l_cp = 00; + OPJ_UINT32 l_Z_ppm; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + /* We need to have the Z_ppm element + 1 byte of Nppm/Ippm at minimum */ + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n"); + return OPJ_FALSE; + } + + l_cp = &(p_j2k->m_cp); + l_cp->ppm = 1; + + opj_read_bytes(p_header_data, &l_Z_ppm, 1); /* Z_ppm */ + ++p_header_data; + --p_header_size; + + /* check allocation needed */ + if (l_cp->ppm_markers == NULL) { /* first PPM marker */ + OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */ + assert(l_cp->ppm_markers_count == 0U); + + l_cp->ppm_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx)); + if (l_cp->ppm_markers == NULL) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + l_cp->ppm_markers_count = l_newCount; + } else if (l_cp->ppm_markers_count <= l_Z_ppm) { + OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */ + opj_ppx *new_ppm_markers; + new_ppm_markers = (opj_ppx *) opj_realloc(l_cp->ppm_markers, + l_newCount * sizeof(opj_ppx)); + if (new_ppm_markers == NULL) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + l_cp->ppm_markers = new_ppm_markers; + memset(l_cp->ppm_markers + l_cp->ppm_markers_count, 0, + (l_newCount - l_cp->ppm_markers_count) * sizeof(opj_ppx)); + l_cp->ppm_markers_count = l_newCount; + } + + if (l_cp->ppm_markers[l_Z_ppm].m_data != NULL) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Zppm %u already read\n", l_Z_ppm); + return OPJ_FALSE; + } + + l_cp->ppm_markers[l_Z_ppm].m_data = (OPJ_BYTE *) opj_malloc(p_header_size); + if (l_cp->ppm_markers[l_Z_ppm].m_data == NULL) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + l_cp->ppm_markers[l_Z_ppm].m_data_size = p_header_size; + memcpy(l_cp->ppm_markers[l_Z_ppm].m_data, p_header_data, p_header_size); + + return OPJ_TRUE; } /** @@ -3586,135 +3854,136 @@ static OPJ_BOOL opj_j2k_read_ppm ( * @param p_cp main coding parameters. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_merge_ppm ( opj_cp_t *p_cp, opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 i, l_ppm_data_size, l_N_ppm_remaining; - - /* preconditions */ - assert(p_cp != 00); - assert(p_manager != 00); - assert(p_cp->ppm_buffer == NULL); - - if (p_cp->ppm == 0U) { - return OPJ_TRUE; - } - - l_ppm_data_size = 0U; - l_N_ppm_remaining = 0U; - for (i = 0U; i < p_cp->ppm_markers_count; ++i) { - if (p_cp->ppm_markers[i].m_data != NULL) { /* standard doesn't seem to require contiguous Zppm */ - OPJ_UINT32 l_N_ppm; - OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size; - const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data; - - if (l_N_ppm_remaining >= l_data_size) { - l_N_ppm_remaining -= l_data_size; - l_data_size = 0U; - } else { - l_data += l_N_ppm_remaining; - l_data_size -= l_N_ppm_remaining; - l_N_ppm_remaining = 0U; - } - - if (l_data_size > 0U) { - do - { - /* read Nppm */ - if (l_data_size < 4U) { - /* clean up to be done on l_cp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n"); - return OPJ_FALSE; - } - opj_read_bytes(l_data, &l_N_ppm, 4); - l_data+=4; - l_data_size-=4; - l_ppm_data_size += l_N_ppm; /* can't overflow, max 256 markers of max 65536 bytes, that is when PPM markers are not corrupted which is checked elsewhere */ - - if (l_data_size >= l_N_ppm) { - l_data_size -= l_N_ppm; - l_data += l_N_ppm; - } else { - l_N_ppm_remaining = l_N_ppm - l_data_size; - l_data_size = 0U; - } - } while (l_data_size > 0U); - } - } - } - - if (l_N_ppm_remaining != 0U) { - /* clean up to be done on l_cp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Corrupted PPM markers\n"); - return OPJ_FALSE; - } - - p_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_ppm_data_size); - if (p_cp->ppm_buffer == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); - return OPJ_FALSE; - } - p_cp->ppm_len = l_ppm_data_size; - l_ppm_data_size = 0U; - l_N_ppm_remaining = 0U; - for (i = 0U; i < p_cp->ppm_markers_count; ++i) { - if (p_cp->ppm_markers[i].m_data != NULL) { /* standard doesn't seem to require contiguous Zppm */ - OPJ_UINT32 l_N_ppm; - OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size; - const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data; - - if (l_N_ppm_remaining >= l_data_size) { - memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size); - l_ppm_data_size += l_data_size; - l_N_ppm_remaining -= l_data_size; - l_data_size = 0U; - } else { - memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm_remaining); - l_ppm_data_size += l_N_ppm_remaining; - l_data += l_N_ppm_remaining; - l_data_size -= l_N_ppm_remaining; - l_N_ppm_remaining = 0U; - } - - if (l_data_size > 0U) { - do - { - /* read Nppm */ - if (l_data_size < 4U) { - /* clean up to be done on l_cp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n"); - return OPJ_FALSE; - } - opj_read_bytes(l_data, &l_N_ppm, 4); - l_data+=4; - l_data_size-=4; - - if (l_data_size >= l_N_ppm) { - memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm); - l_ppm_data_size += l_N_ppm; - l_data_size -= l_N_ppm; - l_data += l_N_ppm; - } else { - memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size); - l_ppm_data_size += l_data_size; - l_N_ppm_remaining = l_N_ppm - l_data_size; - l_data_size = 0U; - } - } while (l_data_size > 0U); - } - opj_free(p_cp->ppm_markers[i].m_data); - p_cp->ppm_markers[i].m_data = NULL; - p_cp->ppm_markers[i].m_data_size = 0U; - } - } - - p_cp->ppm_data = p_cp->ppm_buffer; - p_cp->ppm_data_size = p_cp->ppm_len; - - p_cp->ppm_markers_count = 0U; - opj_free(p_cp->ppm_markers); - p_cp->ppm_markers = NULL; - - return OPJ_TRUE; +static OPJ_BOOL opj_j2k_merge_ppm(opj_cp_t *p_cp, opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, l_ppm_data_size, l_N_ppm_remaining; + + /* preconditions */ + assert(p_cp != 00); + assert(p_manager != 00); + assert(p_cp->ppm_buffer == NULL); + + if (p_cp->ppm == 0U) { + return OPJ_TRUE; + } + + l_ppm_data_size = 0U; + l_N_ppm_remaining = 0U; + for (i = 0U; i < p_cp->ppm_markers_count; ++i) { + if (p_cp->ppm_markers[i].m_data != + NULL) { /* standard doesn't seem to require contiguous Zppm */ + OPJ_UINT32 l_N_ppm; + OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size; + const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data; + + if (l_N_ppm_remaining >= l_data_size) { + l_N_ppm_remaining -= l_data_size; + l_data_size = 0U; + } else { + l_data += l_N_ppm_remaining; + l_data_size -= l_N_ppm_remaining; + l_N_ppm_remaining = 0U; + } + + if (l_data_size > 0U) { + do { + /* read Nppm */ + if (l_data_size < 4U) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n"); + return OPJ_FALSE; + } + opj_read_bytes(l_data, &l_N_ppm, 4); + l_data += 4; + l_data_size -= 4; + l_ppm_data_size += + l_N_ppm; /* can't overflow, max 256 markers of max 65536 bytes, that is when PPM markers are not corrupted which is checked elsewhere */ + + if (l_data_size >= l_N_ppm) { + l_data_size -= l_N_ppm; + l_data += l_N_ppm; + } else { + l_N_ppm_remaining = l_N_ppm - l_data_size; + l_data_size = 0U; + } + } while (l_data_size > 0U); + } + } + } + + if (l_N_ppm_remaining != 0U) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Corrupted PPM markers\n"); + return OPJ_FALSE; + } + + p_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_ppm_data_size); + if (p_cp->ppm_buffer == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + p_cp->ppm_len = l_ppm_data_size; + l_ppm_data_size = 0U; + l_N_ppm_remaining = 0U; + for (i = 0U; i < p_cp->ppm_markers_count; ++i) { + if (p_cp->ppm_markers[i].m_data != + NULL) { /* standard doesn't seem to require contiguous Zppm */ + OPJ_UINT32 l_N_ppm; + OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size; + const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data; + + if (l_N_ppm_remaining >= l_data_size) { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size); + l_ppm_data_size += l_data_size; + l_N_ppm_remaining -= l_data_size; + l_data_size = 0U; + } else { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm_remaining); + l_ppm_data_size += l_N_ppm_remaining; + l_data += l_N_ppm_remaining; + l_data_size -= l_N_ppm_remaining; + l_N_ppm_remaining = 0U; + } + + if (l_data_size > 0U) { + do { + /* read Nppm */ + if (l_data_size < 4U) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n"); + return OPJ_FALSE; + } + opj_read_bytes(l_data, &l_N_ppm, 4); + l_data += 4; + l_data_size -= 4; + + if (l_data_size >= l_N_ppm) { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm); + l_ppm_data_size += l_N_ppm; + l_data_size -= l_N_ppm; + l_data += l_N_ppm; + } else { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size); + l_ppm_data_size += l_data_size; + l_N_ppm_remaining = l_N_ppm - l_data_size; + l_data_size = 0U; + } + } while (l_data_size > 0U); + } + opj_free(p_cp->ppm_markers[i].m_data); + p_cp->ppm_markers[i].m_data = NULL; + p_cp->ppm_markers[i].m_data_size = 0U; + } + } + + p_cp->ppm_data = p_cp->ppm_buffer; + p_cp->ppm_data_size = p_cp->ppm_len; + + p_cp->ppm_markers_count = 0U; + opj_free(p_cp->ppm_markers); + p_cp->ppm_markers = NULL; + + return OPJ_TRUE; } /** @@ -3725,80 +3994,83 @@ static OPJ_BOOL opj_j2k_merge_ppm ( opj_cp_t *p_cp, opj_event_mgr_t * p_manager * @param p_header_size the size of the data contained in the PPT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_ppt ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_ppt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_Z_ppt; - - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - /* We need to have the Z_ppt element + 1 byte of Ippt at minimum */ - if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n"); - return OPJ_FALSE; - } - - l_cp = &(p_j2k->m_cp); - if (l_cp->ppm){ - opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker: packet header have been previously found in the main header (PPM marker).\n"); - return OPJ_FALSE; - } - - l_tcp = &(l_cp->tcps[p_j2k->m_current_tile_number]); - l_tcp->ppt = 1; - - opj_read_bytes(p_header_data,&l_Z_ppt,1); /* Z_ppt */ - ++p_header_data; - --p_header_size; - - /* check allocation needed */ - if (l_tcp->ppt_markers == NULL) { /* first PPT marker */ - OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */ - assert(l_tcp->ppt_markers_count == 0U); - - l_tcp->ppt_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx)); - if (l_tcp->ppt_markers == NULL) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); - return OPJ_FALSE; - } - l_tcp->ppt_markers_count = l_newCount; - } else if (l_tcp->ppt_markers_count <= l_Z_ppt) { - OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */ - opj_ppx *new_ppt_markers; - new_ppt_markers = (opj_ppx *) opj_realloc(l_tcp->ppt_markers, l_newCount * sizeof(opj_ppx)); - if (new_ppt_markers == NULL) { - /* clean up to be done on l_tcp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); - return OPJ_FALSE; - } - l_tcp->ppt_markers = new_ppt_markers; - memset(l_tcp->ppt_markers + l_tcp->ppt_markers_count, 0, (l_newCount - l_tcp->ppt_markers_count) * sizeof(opj_ppx)); - l_tcp->ppt_markers_count = l_newCount; - } - - if (l_tcp->ppt_markers[l_Z_ppt].m_data != NULL) { - /* clean up to be done on l_tcp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Zppt %u already read\n", l_Z_ppt); - return OPJ_FALSE; - } - - l_tcp->ppt_markers[l_Z_ppt].m_data = opj_malloc(p_header_size); - if (l_tcp->ppt_markers[l_Z_ppt].m_data == NULL) { - /* clean up to be done on l_tcp destruction */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); - return OPJ_FALSE; - } - l_tcp->ppt_markers[l_Z_ppt].m_data_size = p_header_size; - memcpy(l_tcp->ppt_markers[l_Z_ppt].m_data, p_header_data, p_header_size); - return OPJ_TRUE; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_Z_ppt; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + /* We need to have the Z_ppt element + 1 byte of Ippt at minimum */ + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n"); + return OPJ_FALSE; + } + + l_cp = &(p_j2k->m_cp); + if (l_cp->ppm) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading PPT marker: packet header have been previously found in the main header (PPM marker).\n"); + return OPJ_FALSE; + } + + l_tcp = &(l_cp->tcps[p_j2k->m_current_tile_number]); + l_tcp->ppt = 1; + + opj_read_bytes(p_header_data, &l_Z_ppt, 1); /* Z_ppt */ + ++p_header_data; + --p_header_size; + + /* check allocation needed */ + if (l_tcp->ppt_markers == NULL) { /* first PPT marker */ + OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */ + assert(l_tcp->ppt_markers_count == 0U); + + l_tcp->ppt_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx)); + if (l_tcp->ppt_markers == NULL) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + l_tcp->ppt_markers_count = l_newCount; + } else if (l_tcp->ppt_markers_count <= l_Z_ppt) { + OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */ + opj_ppx *new_ppt_markers; + new_ppt_markers = (opj_ppx *) opj_realloc(l_tcp->ppt_markers, + l_newCount * sizeof(opj_ppx)); + if (new_ppt_markers == NULL) { + /* clean up to be done on l_tcp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + l_tcp->ppt_markers = new_ppt_markers; + memset(l_tcp->ppt_markers + l_tcp->ppt_markers_count, 0, + (l_newCount - l_tcp->ppt_markers_count) * sizeof(opj_ppx)); + l_tcp->ppt_markers_count = l_newCount; + } + + if (l_tcp->ppt_markers[l_Z_ppt].m_data != NULL) { + /* clean up to be done on l_tcp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Zppt %u already read\n", l_Z_ppt); + return OPJ_FALSE; + } + + l_tcp->ppt_markers[l_Z_ppt].m_data = (OPJ_BYTE *) opj_malloc(p_header_size); + if (l_tcp->ppt_markers[l_Z_ppt].m_data == NULL) { + /* clean up to be done on l_tcp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + l_tcp->ppt_markers[l_Z_ppt].m_data_size = p_header_size; + memcpy(l_tcp->ppt_markers[l_Z_ppt].m_data, p_header_data, p_header_size); + return OPJ_TRUE; } /** @@ -3809,713 +4081,847 @@ static OPJ_BOOL opj_j2k_read_ppt ( opj_j2k_t *p_j2k, */ static OPJ_BOOL opj_j2k_merge_ppt(opj_tcp_t *p_tcp, opj_event_mgr_t * p_manager) { - OPJ_UINT32 i, l_ppt_data_size; - /* preconditions */ - assert(p_tcp != 00); - assert(p_manager != 00); - assert(p_tcp->ppt_buffer == NULL); - - if (p_tcp->ppt == 0U) { - return OPJ_TRUE; - } - - l_ppt_data_size = 0U; - for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { - l_ppt_data_size += p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */ - } - - p_tcp->ppt_buffer = (OPJ_BYTE *) opj_malloc(l_ppt_data_size); - if (p_tcp->ppt_buffer == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); - return OPJ_FALSE; - } - p_tcp->ppt_len = l_ppt_data_size; - l_ppt_data_size = 0U; - for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { - if (p_tcp->ppt_markers[i].m_data != NULL) { /* standard doesn't seem to require contiguous Zppt */ - memcpy(p_tcp->ppt_buffer + l_ppt_data_size, p_tcp->ppt_markers[i].m_data, p_tcp->ppt_markers[i].m_data_size); - l_ppt_data_size += p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */ - - opj_free(p_tcp->ppt_markers[i].m_data); - p_tcp->ppt_markers[i].m_data = NULL; - p_tcp->ppt_markers[i].m_data_size = 0U; - } - } - - p_tcp->ppt_markers_count = 0U; - opj_free(p_tcp->ppt_markers); - p_tcp->ppt_markers = NULL; - - p_tcp->ppt_data = p_tcp->ppt_buffer; - p_tcp->ppt_data_size = p_tcp->ppt_len; - return OPJ_TRUE; -} - -static OPJ_BOOL opj_j2k_write_tlm( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_tlm_size; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_tlm_size = 6 + (5*p_j2k->m_specific_param.m_encoder.m_total_tile_parts); - - if (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write TLM marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size; - } - - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - - /* change the way data is written to avoid seeking if possible */ - /* TODO */ - p_j2k->m_specific_param.m_encoder.m_tlm_start = opj_stream_tell(p_stream); - - opj_write_bytes(l_current_data,J2K_MS_TLM,2); /* TLM */ - l_current_data += 2; - - opj_write_bytes(l_current_data,l_tlm_size-2,2); /* Lpoc */ - l_current_data += 2; + OPJ_UINT32 i, l_ppt_data_size; + /* preconditions */ + assert(p_tcp != 00); + assert(p_manager != 00); + assert(p_tcp->ppt_buffer == NULL); - opj_write_bytes(l_current_data,0,1); /* Ztlm=0*/ - ++l_current_data; + if (p_tcp->ppt == 0U) { + return OPJ_TRUE; + } - opj_write_bytes(l_current_data,0x50,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ - ++l_current_data; + l_ppt_data_size = 0U; + for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { + l_ppt_data_size += + p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */ + } - /* do nothing on the 5 * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */ - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_tlm_size,p_manager) != l_tlm_size) { - return OPJ_FALSE; + p_tcp->ppt_buffer = (OPJ_BYTE *) opj_malloc(l_ppt_data_size); + if (p_tcp->ppt_buffer == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + p_tcp->ppt_len = l_ppt_data_size; + l_ppt_data_size = 0U; + for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { + if (p_tcp->ppt_markers[i].m_data != + NULL) { /* standard doesn't seem to require contiguous Zppt */ + memcpy(p_tcp->ppt_buffer + l_ppt_data_size, p_tcp->ppt_markers[i].m_data, + p_tcp->ppt_markers[i].m_data_size); + l_ppt_data_size += + p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */ + + opj_free(p_tcp->ppt_markers[i].m_data); + p_tcp->ppt_markers[i].m_data = NULL; + p_tcp->ppt_markers[i].m_data_size = 0U; } + } - return OPJ_TRUE; + p_tcp->ppt_markers_count = 0U; + opj_free(p_tcp->ppt_markers); + p_tcp->ppt_markers = NULL; + + p_tcp->ppt_data = p_tcp->ppt_buffer; + p_tcp->ppt_data_size = p_tcp->ppt_len; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_sot( opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - const opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tlm_size; - opj_write_bytes(p_data,J2K_MS_SOT,2); /* SOT */ - p_data += 2; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - opj_write_bytes(p_data,10,2); /* Lsot */ - p_data += 2; + l_tlm_size = 6 + (5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts); - opj_write_bytes(p_data, p_j2k->m_current_tile_number,2); /* Isot */ - p_data += 2; + if (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write TLM marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size; + } - /* Psot */ - p_data += 4; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(p_data, p_j2k->m_specific_param.m_encoder.m_current_tile_part_number,1); /* TPsot */ - ++p_data; + /* change the way data is written to avoid seeking if possible */ + /* TODO */ + p_j2k->m_specific_param.m_encoder.m_tlm_start = opj_stream_tell(p_stream); - opj_write_bytes(p_data, p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts,1); /* TNsot */ - ++p_data; + opj_write_bytes(l_current_data, J2K_MS_TLM, + 2); /* TLM */ + l_current_data += 2; - /* UniPG>> */ -#ifdef USE_JPWL - /* update markers struct */ -/* - OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2); -*/ - assert( 0 && "TODO" ); -#endif /* USE_JPWL */ + opj_write_bytes(l_current_data, l_tlm_size - 2, + 2); /* Lpoc */ + l_current_data += 2; - * p_data_written = 12; + opj_write_bytes(l_current_data, 0, + 1); /* Ztlm=0*/ + ++l_current_data; - return OPJ_TRUE; -} + opj_write_bytes(l_current_data, 0x50, + 1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ + ++l_current_data; -static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - OPJ_UINT32* p_tile_no, - OPJ_UINT32* p_tot_len, - OPJ_UINT32* p_current_part, - OPJ_UINT32* p_num_parts, - opj_event_mgr_t * p_manager ) -{ - /* preconditions */ - assert(p_header_data != 00); - assert(p_manager != 00); - - /* Size of this marker is fixed = 12 (we have already read marker and its size)*/ - if (p_header_size != 8) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_header_data,p_tile_no,2); /* Isot */ - p_header_data+=2; - opj_read_bytes(p_header_data,p_tot_len,4); /* Psot */ - p_header_data+=4; - opj_read_bytes(p_header_data,p_current_part,1); /* TPsot */ - ++p_header_data; - opj_read_bytes(p_header_data,p_num_parts ,1); /* TNsot */ - ++p_header_data; - return OPJ_TRUE; -} - -static OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ) -{ - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_tot_len, l_num_parts = 0; - OPJ_UINT32 l_current_part; - OPJ_UINT32 l_tile_x,l_tile_y; - - /* preconditions */ - - assert(p_j2k != 00); - assert(p_manager != 00); - - if (! opj_j2k_get_sot_values(p_header_data, p_header_size, &(p_j2k->m_current_tile_number), &l_tot_len, &l_current_part, &l_num_parts, p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); - return OPJ_FALSE; - } + /* do nothing on the 5 * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */ + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size, + p_manager) != l_tlm_size) { + return OPJ_FALSE; + } - l_cp = &(p_j2k->m_cp); + return OPJ_TRUE; +} - /* testcase 2.pdf.SIGFPE.706.1112 */ - if (p_j2k->m_current_tile_number >= l_cp->tw * l_cp->th) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid tile number %d\n", p_j2k->m_current_tile_number); - return OPJ_FALSE; - } +static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 p_total_data_size, + OPJ_UINT32 * p_data_written, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; - l_tile_x = p_j2k->m_current_tile_number % l_cp->tw; - l_tile_y = p_j2k->m_current_tile_number / l_cp->tw; + OPJ_UNUSED(p_stream); -#ifdef USE_JPWL - if (l_cp->correct) { + if (p_total_data_size < 12) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOT marker\n"); + return OPJ_FALSE; + } - OPJ_UINT32 tileno = p_j2k->m_current_tile_number; - static OPJ_UINT32 backup_tileno = 0; + opj_write_bytes(p_data, J2K_MS_SOT, + 2); /* SOT */ + p_data += 2; - /* tileno is negative or larger than the number of tiles!!! */ - if (tileno > (l_cp->tw * l_cp->th)) { - opj_event_msg(p_manager, EVT_ERROR, - "JPWL: bad tile number (%d out of a maximum of %d)\n", - tileno, (l_cp->tw * l_cp->th)); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - /* we try to correct */ - tileno = backup_tileno; - opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" - "- setting tile number to %d\n", - tileno); - } + opj_write_bytes(p_data, 10, + 2); /* Lsot */ + p_data += 2; - /* keep your private count of tiles */ - backup_tileno++; - }; -#endif /* USE_JPWL */ + opj_write_bytes(p_data, p_j2k->m_current_tile_number, + 2); /* Isot */ + p_data += 2; - /* look for the tile in the list of already processed tile (in parts). */ - /* Optimization possible here with a more complex data structure and with the removing of tiles */ - /* since the time taken by this function can only grow at the time */ + /* Psot */ + p_data += 4; - /* PSot should be equal to zero or >=14 or <= 2^32-1 */ - if ((l_tot_len !=0 ) && (l_tot_len < 14) ) - { - if (l_tot_len == 12 ) /* MSD: Special case for the PHR data which are read by kakadu*/ - { - opj_event_msg(p_manager, EVT_WARNING, "Empty SOT marker detected: Psot=%d.\n", l_tot_len); - } - else - { - opj_event_msg(p_manager, EVT_ERROR, "Psot value is not correct regards to the JPEG2000 norm: %d.\n", l_tot_len); - return OPJ_FALSE; - } - } + opj_write_bytes(p_data, + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number, + 1); /* TPsot */ + ++p_data; -#ifdef USE_JPWL - if (l_cp->correct) { + opj_write_bytes(p_data, + p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts, + 1); /* TNsot */ + ++p_data; - /* totlen is negative or larger than the bytes left!!! */ - if (/*(l_tot_len < 0) ||*/ (l_tot_len > p_header_size ) ) { /* FIXME it seems correct; for info in V1 -> (p_stream_numbytesleft(p_stream) + 8))) { */ - opj_event_msg(p_manager, EVT_ERROR, - "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", - l_tot_len, p_header_size ); /* FIXME it seems correct; for info in V1 -> p_stream_numbytesleft(p_stream) + 8); */ - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - /* we try to correct */ - l_tot_len = 0; - opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" - "- setting Psot to %d => assuming it is the last tile\n", - l_tot_len); - } - }; + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /* + OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2); + */ + assert(0 && "TODO"); #endif /* USE_JPWL */ - /* Ref A.4.2: Psot could be equal zero if it is the last tile-part of the codestream.*/ - if (!l_tot_len) { - opj_event_msg(p_manager, EVT_INFO, "Psot value of the current tile-part is equal to zero, " - "we assuming it is the last tile-part of the codestream.\n"); - p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; - } + * p_data_written = 12; - if (l_num_parts != 0) { /* Number of tile-part header is provided by this tile-part header */ - l_num_parts += p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction; - /* Useful to manage the case of textGBR.jp2 file because two values of TNSot are allowed: the correct numbers of - * tile-parts for that tile and zero (A.4.2 of 15444-1 : 2002). */ - if (l_tcp->m_nb_tile_parts) { - if (l_current_part >= l_tcp->m_nb_tile_parts){ - opj_event_msg(p_manager, EVT_ERROR, "In SOT marker, TPSot (%d) is not valid regards to the current " - "number of tile-part (%d), giving up\n", l_current_part, l_tcp->m_nb_tile_parts ); - p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; - return OPJ_FALSE; - } - } - if( l_current_part >= l_num_parts ) { - /* testcase 451.pdf.SIGSEGV.ce9.3723 */ - opj_event_msg(p_manager, EVT_ERROR, "In SOT marker, TPSot (%d) is not valid regards to the current " - "number of tile-part (header) (%d), giving up\n", l_current_part, l_num_parts ); - p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; - return OPJ_FALSE; - } - l_tcp->m_nb_tile_parts = l_num_parts; - } + return OPJ_TRUE; +} - /* If know the number of tile part header we will check if we didn't read the last*/ - if (l_tcp->m_nb_tile_parts) { - if (l_tcp->m_nb_tile_parts == (l_current_part+1)) { - p_j2k->m_specific_param.m_decoder.m_can_decode = 1; /* Process the last tile-part header*/ - } - } +static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + OPJ_UINT32* p_tile_no, + OPJ_UINT32* p_tot_len, + OPJ_UINT32* p_current_part, + OPJ_UINT32* p_num_parts, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_header_data != 00); + assert(p_manager != 00); + + /* Size of this marker is fixed = 12 (we have already read marker and its size)*/ + if (p_header_size != 8) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); + return OPJ_FALSE; + } - if (!p_j2k->m_specific_param.m_decoder.m_last_tile_part){ - /* Keep the size of data to skip after this marker */ - p_j2k->m_specific_param.m_decoder.m_sot_length = l_tot_len - 12; /* SOT_marker_size = 12 */ - } - else { - /* FIXME: need to be computed from the number of bytes remaining in the codestream */ - p_j2k->m_specific_param.m_decoder.m_sot_length = 0; - } + opj_read_bytes(p_header_data, p_tile_no, 2); /* Isot */ + p_header_data += 2; + opj_read_bytes(p_header_data, p_tot_len, 4); /* Psot */ + p_header_data += 4; + opj_read_bytes(p_header_data, p_current_part, 1); /* TPsot */ + ++p_header_data; + opj_read_bytes(p_header_data, p_num_parts, 1); /* TNsot */ + ++p_header_data; + return OPJ_TRUE; +} - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPH; +static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_tot_len, l_num_parts = 0; + OPJ_UINT32 l_current_part; + OPJ_UINT32 l_tile_x, l_tile_y; - /* Check if the current tile is outside the area we want decode or not corresponding to the tile index*/ - if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec == -1) { - p_j2k->m_specific_param.m_decoder.m_skip_data = - (l_tile_x < p_j2k->m_specific_param.m_decoder.m_start_tile_x) - || (l_tile_x >= p_j2k->m_specific_param.m_decoder.m_end_tile_x) - || (l_tile_y < p_j2k->m_specific_param.m_decoder.m_start_tile_y) - || (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y); - } - else { - assert( p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec >= 0 ); - p_j2k->m_specific_param.m_decoder.m_skip_data = - (p_j2k->m_current_tile_number != (OPJ_UINT32)p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec); - } + /* preconditions */ - /* Index */ - if (p_j2k->cstr_index) - { - assert(p_j2k->cstr_index->tile_index != 00); - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = l_current_part; - - if (l_num_parts != 0){ - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps = l_num_parts; - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = l_num_parts; - - if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = - (opj_tp_index_t*)opj_calloc(l_num_parts, sizeof(opj_tp_index_t)); - if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read SOT marker. Tile index allocation failed\n"); - return OPJ_FALSE; - } - } - else { - opj_tp_index_t *new_tp_index = (opj_tp_index_t *) opj_realloc( - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, l_num_parts* sizeof(opj_tp_index_t)); - if (! new_tp_index) { - opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index); - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read SOT marker. Tile index allocation failed\n"); - return OPJ_FALSE; - } - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = new_tp_index; - } - } - else{ - /*if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index)*/ { - - if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 10; - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = - (opj_tp_index_t*)opj_calloc( p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps, - sizeof(opj_tp_index_t)); - if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read SOT marker. Tile index allocation failed\n"); - return OPJ_FALSE; - } - } - - if ( l_current_part >= p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps ){ - opj_tp_index_t *new_tp_index; - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = l_current_part + 1; - new_tp_index = (opj_tp_index_t *) opj_realloc( - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps * sizeof(opj_tp_index_t)); - if (! new_tp_index) { - opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index); - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL; - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read SOT marker. Tile index allocation failed\n"); - return OPJ_FALSE; - } - p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = new_tp_index; - } - } + assert(p_j2k != 00); + assert(p_manager != 00); - } + if (! opj_j2k_get_sot_values(p_header_data, p_header_size, + &(p_j2k->m_current_tile_number), &l_tot_len, &l_current_part, &l_num_parts, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); + return OPJ_FALSE; + } +#ifdef DEBUG_VERBOSE + fprintf(stderr, "SOT %d %d %d %d\n", + p_j2k->m_current_tile_number, l_tot_len, l_current_part, l_num_parts); +#endif - } + l_cp = &(p_j2k->m_cp); - /* FIXME move this onto a separate method to call before reading any SOT, remove part about main_end header, use a index struct inside p_j2k */ - /* if (p_j2k->cstr_info) { - if (l_tcp->first) { - if (tileno == 0) { - p_j2k->cstr_info->main_head_end = p_stream_tell(p_stream) - 13; - } - - p_j2k->cstr_info->tile[tileno].tileno = tileno; - p_j2k->cstr_info->tile[tileno].start_pos = p_stream_tell(p_stream) - 12; - p_j2k->cstr_info->tile[tileno].end_pos = p_j2k->cstr_info->tile[tileno].start_pos + totlen - 1; - p_j2k->cstr_info->tile[tileno].num_tps = numparts; - - if (numparts) { - p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); - } - else { - p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) - } - } - else { - p_j2k->cstr_info->tile[tileno].end_pos += totlen; - } - - p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = p_stream_tell(p_stream) - 12; - p_j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = - p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; - }*/ - return OPJ_TRUE; - } + /* testcase 2.pdf.SIGFPE.706.1112 */ + if (p_j2k->m_current_tile_number >= l_cp->tw * l_cp->th) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid tile number %d\n", + p_j2k->m_current_tile_number); + return OPJ_FALSE; + } -static OPJ_BOOL opj_j2k_write_sod( opj_j2k_t *p_j2k, - opj_tcd_t * p_tile_coder, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - const opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - opj_codestream_info_t *l_cstr_info = 00; - OPJ_UINT32 l_remaining_data; + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_tile_x = p_j2k->m_current_tile_number % l_cp->tw; + l_tile_y = p_j2k->m_current_tile_number / l_cp->tw; + + if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec < 0 || + p_j2k->m_current_tile_number == (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec) { + /* Do only this check if we decode all tile part headers, or if */ + /* we decode one precise tile. Otherwise the m_current_tile_part_number */ + /* might not be valid */ + /* Fixes issue with id_000020,sig_06,src_001958,op_flip4,pos_149 */ + /* of https://github.com/uclouvain/openjpeg/issues/939 */ + /* We must avoid reading twice the same tile part number for a given tile */ + /* so as to avoid various issues, like opj_j2k_merge_ppt being called */ + /* several times. */ + /* ISO 15444-1 A.4.2 Start of tile-part (SOT) mandates that tile parts */ + /* should appear in increasing order. */ + if (l_tcp->m_current_tile_part_number + 1 != (OPJ_INT32)l_current_part) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid tile part index for tile number %d. " + "Got %d, expected %d\n", + p_j2k->m_current_tile_number, + l_current_part, + l_tcp->m_current_tile_part_number + 1); + return OPJ_FALSE; + } + } - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + l_tcp->m_current_tile_part_number = (OPJ_INT32) l_current_part; - opj_write_bytes(p_data,J2K_MS_SOD,2); /* SOD */ - p_data += 2; +#ifdef USE_JPWL + if (l_cp->correct) { - /* make room for the EOF marker */ - l_remaining_data = p_total_data_size - 4; + OPJ_UINT32 tileno = p_j2k->m_current_tile_number; + static OPJ_UINT32 backup_tileno = 0; - /* update tile coder */ - p_tile_coder->tp_num = p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number ; - p_tile_coder->cur_tp_num = p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + /* tileno is negative or larger than the number of tiles!!! */ + if (tileno > (l_cp->tw * l_cp->th)) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (l_cp->tw * l_cp->th)); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + tileno = backup_tileno; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" + "- setting tile number to %d\n", + tileno); + } - /* INDEX >> */ - /* TODO mergeV2: check this part which use cstr_info */ - /*l_cstr_info = p_j2k->cstr_info; - if (l_cstr_info) { - if (!p_j2k->m_specific_param.m_encoder.m_current_tile_part_number ) { - //TODO cstr_info->tile[p_j2k->m_current_tile_number].end_header = p_stream_tell(p_stream) + p_j2k->pos_correction - 1; - l_cstr_info->tile[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; - } - else {*/ - /* - TODO - if - (cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno - 1].end_pos < p_stream_tell(p_stream)) - { - cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno].start_pos = p_stream_tell(p_stream); - }*/ - /*}*/ - /* UniPG>> */ -#ifdef USE_JPWL - /* update markers struct */ - /*OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2); -*/ - assert( 0 && "TODO" ); + /* keep your private count of tiles */ + backup_tileno++; + }; #endif /* USE_JPWL */ - /* <<UniPG */ - /*}*/ - /* << INDEX */ - - if (p_j2k->m_specific_param.m_encoder.m_current_tile_part_number == 0) { - p_tile_coder->tcd_image->tiles->packno = 0; - if (l_cstr_info) { - l_cstr_info->packno = 0; - } - } - *p_data_written = 0; + /* look for the tile in the list of already processed tile (in parts). */ + /* Optimization possible here with a more complex data structure and with the removing of tiles */ + /* since the time taken by this function can only grow at the time */ + + /* PSot should be equal to zero or >=14 or <= 2^32-1 */ + if ((l_tot_len != 0) && (l_tot_len < 14)) { + if (l_tot_len == + 12) { /* MSD: Special case for the PHR data which are read by kakadu*/ + opj_event_msg(p_manager, EVT_WARNING, "Empty SOT marker detected: Psot=%d.\n", + l_tot_len); + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Psot value is not correct regards to the JPEG2000 norm: %d.\n", l_tot_len); + return OPJ_FALSE; + } + } - if (! opj_tcd_encode_tile(p_tile_coder, p_j2k->m_current_tile_number, p_data, p_data_written, l_remaining_data , l_cstr_info)) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot encode tile\n"); +#ifdef USE_JPWL + if (l_cp->correct) { + + /* totlen is negative or larger than the bytes left!!! */ + if (/*(l_tot_len < 0) ||*/ (l_tot_len > + p_header_size)) { /* FIXME it seems correct; for info in V1 -> (p_stream_numbytesleft(p_stream) + 8))) { */ + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + l_tot_len, + p_header_size); /* FIXME it seems correct; for info in V1 -> p_stream_numbytesleft(p_stream) + 8); */ + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); return OPJ_FALSE; + } + /* we try to correct */ + l_tot_len = 0; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" + "- setting Psot to %d => assuming it is the last tile\n", + l_tot_len); } + }; +#endif /* USE_JPWL */ - *p_data_written += 2; + /* Ref A.4.2: Psot could be equal zero if it is the last tile-part of the codestream.*/ + if (!l_tot_len) { + opj_event_msg(p_manager, EVT_INFO, + "Psot value of the current tile-part is equal to zero, " + "we assuming it is the last tile-part of the codestream.\n"); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + } - return OPJ_TRUE; -} + if (l_tcp->m_nb_tile_parts != 0 && l_current_part >= l_tcp->m_nb_tile_parts) { + /* Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2851 */ + opj_event_msg(p_manager, EVT_ERROR, + "In SOT marker, TPSot (%d) is not valid regards to the previous " + "number of tile-part (%d), giving up\n", l_current_part, + l_tcp->m_nb_tile_parts); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + return OPJ_FALSE; + } -static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - OPJ_SIZE_T l_current_read_size; - opj_codestream_index_t * l_cstr_index = 00; - OPJ_BYTE ** l_current_data = 00; - opj_tcp_t * l_tcp = 00; - OPJ_UINT32 * l_tile_len = 00; - OPJ_BOOL l_sot_length_pb_detected = OPJ_FALSE; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); - - if (p_j2k->m_specific_param.m_decoder.m_last_tile_part) { - /* opj_stream_get_number_byte_left returns OPJ_OFF_T - // but we are in the last tile part, - // so its result will fit on OPJ_UINT32 unless we find - // a file with a single tile part of more than 4 GB...*/ - p_j2k->m_specific_param.m_decoder.m_sot_length = (OPJ_UINT32)(opj_stream_get_number_byte_left(p_stream) - 2); - } - else { - /* Check to avoid pass the limit of OPJ_UINT32 */ - if (p_j2k->m_specific_param.m_decoder.m_sot_length >= 2 ) - p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; - else { - /* MSD: case commented to support empty SOT marker (PHR data) */ + if (l_num_parts != + 0) { /* Number of tile-part header is provided by this tile-part header */ + l_num_parts += p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction; + /* Useful to manage the case of textGBR.jp2 file because two values of TNSot are allowed: the correct numbers of + * tile-parts for that tile and zero (A.4.2 of 15444-1 : 2002). */ + if (l_tcp->m_nb_tile_parts) { + if (l_current_part >= l_tcp->m_nb_tile_parts) { + opj_event_msg(p_manager, EVT_ERROR, + "In SOT marker, TPSot (%d) is not valid regards to the current " + "number of tile-part (%d), giving up\n", l_current_part, + l_tcp->m_nb_tile_parts); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + return OPJ_FALSE; } } + if (l_current_part >= l_num_parts) { + /* testcase 451.pdf.SIGSEGV.ce9.3723 */ + opj_event_msg(p_manager, EVT_ERROR, + "In SOT marker, TPSot (%d) is not valid regards to the current " + "number of tile-part (header) (%d), giving up\n", l_current_part, l_num_parts); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + return OPJ_FALSE; + } + l_tcp->m_nb_tile_parts = l_num_parts; + } - l_current_data = &(l_tcp->m_data); - l_tile_len = &l_tcp->m_data_size; + /* If know the number of tile part header we will check if we didn't read the last*/ + if (l_tcp->m_nb_tile_parts) { + if (l_tcp->m_nb_tile_parts == (l_current_part + 1)) { + p_j2k->m_specific_param.m_decoder.m_can_decode = + 1; /* Process the last tile-part header*/ + } + } - /* Patch to support new PHR data */ - if (p_j2k->m_specific_param.m_decoder.m_sot_length) { - /* If we are here, we'll try to read the data after allocation */ - /* Check enough bytes left in stream before allocation */ - if ((OPJ_OFF_T)p_j2k->m_specific_param.m_decoder.m_sot_length > opj_stream_get_number_byte_left(p_stream)) { - opj_event_msg(p_manager, EVT_ERROR, "Tile part length size inconsistent with stream length\n"); - return OPJ_FALSE; - } - if (! *l_current_data) { - /* LH: oddly enough, in this path, l_tile_len!=0. - * TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...). - */ - *l_current_data = (OPJ_BYTE*) opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length); - } - else { - OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data, *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length); - if (! l_new_current_data) { - opj_free(*l_current_data); - /*nothing more is done as l_current_data will be set to null, and just - afterward we enter in the error path - and the actual tile_len is updated (committed) at the end of the - function. */ + if (!p_j2k->m_specific_param.m_decoder.m_last_tile_part) { + /* Keep the size of data to skip after this marker */ + p_j2k->m_specific_param.m_decoder.m_sot_length = l_tot_len - + 12; /* SOT_marker_size = 12 */ + } else { + /* FIXME: need to be computed from the number of bytes remaining in the codestream */ + p_j2k->m_specific_param.m_decoder.m_sot_length = 0; + } + + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPH; + + /* Check if the current tile is outside the area we want decode or not corresponding to the tile index*/ + if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec == -1) { + p_j2k->m_specific_param.m_decoder.m_skip_data = + (l_tile_x < p_j2k->m_specific_param.m_decoder.m_start_tile_x) + || (l_tile_x >= p_j2k->m_specific_param.m_decoder.m_end_tile_x) + || (l_tile_y < p_j2k->m_specific_param.m_decoder.m_start_tile_y) + || (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y); + } else { + assert(p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec >= 0); + p_j2k->m_specific_param.m_decoder.m_skip_data = + (p_j2k->m_current_tile_number != (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec); + } + + /* Index */ + if (p_j2k->cstr_index) { + assert(p_j2k->cstr_index->tile_index != 00); + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = + p_j2k->m_current_tile_number; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = + l_current_part; + + if (l_num_parts != 0) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps = + l_num_parts; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = + l_num_parts; + + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_calloc(l_num_parts, sizeof(opj_tp_index_t)); + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + } else { + opj_tp_index_t *new_tp_index = (opj_tp_index_t *) opj_realloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, + l_num_parts * sizeof(opj_tp_index_t)); + if (! new_tp_index) { + opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index); + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; } - *l_current_data = l_new_current_data; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + new_tp_index; } - - if (*l_current_data == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile\n"); - return OPJ_FALSE; + } else { + /*if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index)*/ { + + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 10; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_calloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps, + sizeof(opj_tp_index_t)); + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + } + + if (l_current_part >= + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps) { + opj_tp_index_t *new_tp_index; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = + l_current_part + 1; + new_tp_index = (opj_tp_index_t *) opj_realloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps * + sizeof(opj_tp_index_t)); + if (! new_tp_index) { + opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index); + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + new_tp_index; + } } + } - else { - l_sot_length_pb_detected = OPJ_TRUE; + + } + + /* FIXME move this onto a separate method to call before reading any SOT, remove part about main_end header, use a index struct inside p_j2k */ + /* if (p_j2k->cstr_info) { + if (l_tcp->first) { + if (tileno == 0) { + p_j2k->cstr_info->main_head_end = p_stream_tell(p_stream) - 13; + } + + p_j2k->cstr_info->tile[tileno].tileno = tileno; + p_j2k->cstr_info->tile[tileno].start_pos = p_stream_tell(p_stream) - 12; + p_j2k->cstr_info->tile[tileno].end_pos = p_j2k->cstr_info->tile[tileno].start_pos + totlen - 1; + p_j2k->cstr_info->tile[tileno].num_tps = numparts; + + if (numparts) { + p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); + } + else { + p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) + } + } + else { + p_j2k->cstr_info->tile[tileno].end_pos += totlen; + } + + p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = p_stream_tell(p_stream) - 12; + p_j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = + p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; + }*/ + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k, + opj_tcd_t * p_tile_coder, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + opj_codestream_info_t *l_cstr_info = 00; + OPJ_UINT32 l_remaining_data; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_stream); + + if (p_total_data_size < 4) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOD marker\n"); + return OPJ_FALSE; + } + + opj_write_bytes(p_data, J2K_MS_SOD, + 2); /* SOD */ + p_data += 2; + + /* make room for the EOF marker */ + l_remaining_data = p_total_data_size - 4; + + /* update tile coder */ + p_tile_coder->tp_num = + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number ; + p_tile_coder->cur_tp_num = + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + + /* INDEX >> */ + /* TODO mergeV2: check this part which use cstr_info */ + /*l_cstr_info = p_j2k->cstr_info; + if (l_cstr_info) { + if (!p_j2k->m_specific_param.m_encoder.m_current_tile_part_number ) { + //TODO cstr_info->tile[p_j2k->m_current_tile_number].end_header = p_stream_tell(p_stream) + p_j2k->pos_correction - 1; + l_cstr_info->tile[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; + } + else {*/ + /* + TODO + if + (cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno - 1].end_pos < p_stream_tell(p_stream)) + { + cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno].start_pos = p_stream_tell(p_stream); + }*/ + /*}*/ + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /*OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2); + */ + assert(0 && "TODO"); +#endif /* USE_JPWL */ + /* <<UniPG */ + /*}*/ + /* << INDEX */ + + if (p_j2k->m_specific_param.m_encoder.m_current_tile_part_number == 0) { + p_tile_coder->tcd_image->tiles->packno = 0; +#ifdef deadcode + if (l_cstr_info) { + l_cstr_info->packno = 0; } +#endif + } - /* Index */ - l_cstr_index = p_j2k->cstr_index; - if (l_cstr_index) { - OPJ_OFF_T l_current_pos = opj_stream_tell(p_stream) - 2; + *p_data_written = 0; + + if (! opj_tcd_encode_tile(p_tile_coder, p_j2k->m_current_tile_number, p_data, + p_data_written, l_remaining_data, l_cstr_info, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot encode tile\n"); + return OPJ_FALSE; + } - OPJ_UINT32 l_current_tile_part = l_cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno; - l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_header = - l_current_pos; - l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_pos = - l_current_pos + p_j2k->m_specific_param.m_decoder.m_sot_length + 2; + *p_data_written += 2; - if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number, - l_cstr_index, - J2K_MS_SOD, - l_current_pos, - p_j2k->m_specific_param.m_decoder.m_sot_length + 2)) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); - return OPJ_FALSE; - } + return OPJ_TRUE; +} - /*l_cstr_index->packno = 0;*/ +static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_SIZE_T l_current_read_size; + opj_codestream_index_t * l_cstr_index = 00; + OPJ_BYTE ** l_current_data = 00; + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 * l_tile_len = 00; + OPJ_BOOL l_sot_length_pb_detected = OPJ_FALSE; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + + if (p_j2k->m_specific_param.m_decoder.m_last_tile_part) { + /* opj_stream_get_number_byte_left returns OPJ_OFF_T + // but we are in the last tile part, + // so its result will fit on OPJ_UINT32 unless we find + // a file with a single tile part of more than 4 GB...*/ + p_j2k->m_specific_param.m_decoder.m_sot_length = (OPJ_UINT32)( + opj_stream_get_number_byte_left(p_stream) - 2); + } else { + /* Check to avoid pass the limit of OPJ_UINT32 */ + if (p_j2k->m_specific_param.m_decoder.m_sot_length >= 2) { + p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; + } else { + /* MSD: case commented to support empty SOT marker (PHR data) */ } + } - /* Patch to support new PHR data */ - if (!l_sot_length_pb_detected) { - l_current_read_size = opj_stream_read_data( - p_stream, - *l_current_data + *l_tile_len, - p_j2k->m_specific_param.m_decoder.m_sot_length, - p_manager); + l_current_data = &(l_tcp->m_data); + l_tile_len = &l_tcp->m_data_size; + + /* Patch to support new PHR data */ + if (p_j2k->m_specific_param.m_decoder.m_sot_length) { + /* If we are here, we'll try to read the data after allocation */ + /* Check enough bytes left in stream before allocation */ + if ((OPJ_OFF_T)p_j2k->m_specific_param.m_decoder.m_sot_length > + opj_stream_get_number_byte_left(p_stream)) { + opj_event_msg(p_manager, EVT_ERROR, + "Tile part length size inconsistent with stream length\n"); + return OPJ_FALSE; } - else - { - l_current_read_size = 0; + if (p_j2k->m_specific_param.m_decoder.m_sot_length > + UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA) { + opj_event_msg(p_manager, EVT_ERROR, + "p_j2k->m_specific_param.m_decoder.m_sot_length > " + "UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA"); + return OPJ_FALSE; } + /* Add a margin of OPJ_COMMON_CBLK_DATA_EXTRA to the allocation we */ + /* do so that opj_mqc_init_dec_common() can safely add a synthetic */ + /* 0xFFFF marker. */ + if (! *l_current_data) { + /* LH: oddly enough, in this path, l_tile_len!=0. + * TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...). + */ + *l_current_data = (OPJ_BYTE*) opj_malloc( + p_j2k->m_specific_param.m_decoder.m_sot_length + OPJ_COMMON_CBLK_DATA_EXTRA); + } else { + OPJ_BYTE *l_new_current_data; + if (*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA - + p_j2k->m_specific_param.m_decoder.m_sot_length) { + opj_event_msg(p_manager, EVT_ERROR, + "*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA - " + "p_j2k->m_specific_param.m_decoder.m_sot_length"); + return OPJ_FALSE; + } - if (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) { - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data, + *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length + + OPJ_COMMON_CBLK_DATA_EXTRA); + if (! l_new_current_data) { + opj_free(*l_current_data); + /*nothing more is done as l_current_data will be set to null, and just + afterward we enter in the error path + and the actual tile_len is updated (committed) at the end of the + function. */ + } + *l_current_data = l_new_current_data; } - else { - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + + if (*l_current_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile\n"); + return OPJ_FALSE; } + } else { + l_sot_length_pb_detected = OPJ_TRUE; + } - *l_tile_len += (OPJ_UINT32)l_current_read_size; + /* Index */ + l_cstr_index = p_j2k->cstr_index; + if (l_cstr_index) { + OPJ_OFF_T l_current_pos = opj_stream_tell(p_stream) - 2; + + OPJ_UINT32 l_current_tile_part = + l_cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno; + l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_header + = + l_current_pos; + l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_pos + = + l_current_pos + p_j2k->m_specific_param.m_decoder.m_sot_length + 2; + + if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number, + l_cstr_index, + J2K_MS_SOD, + l_current_pos, + p_j2k->m_specific_param.m_decoder.m_sot_length + 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + /*l_cstr_index->packno = 0;*/ + } + + /* Patch to support new PHR data */ + if (!l_sot_length_pb_detected) { + l_current_read_size = opj_stream_read_data( + p_stream, + *l_current_data + *l_tile_len, + p_j2k->m_specific_param.m_decoder.m_sot_length, + p_manager); + } else { + l_current_read_size = 0; + } + + if (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + } else { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + } + + *l_tile_len += (OPJ_UINT32)l_current_read_size; + + return OPJ_TRUE; } static OPJ_BOOL opj_j2k_write_rgn(opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - OPJ_UINT32 nb_comps, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_UINT32 nb_comps, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_rgn_size; - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; - OPJ_UINT32 l_comp_room; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_rgn_size; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_UINT32 l_comp_room; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_tile_no]; - l_tccp = &l_tcp->tccps[p_comp_no]; + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; - if (nb_comps <= 256) { - l_comp_room = 1; - } - else { - l_comp_room = 2; - } + if (nb_comps <= 256) { + l_comp_room = 1; + } else { + l_comp_room = 2; + } - l_rgn_size = 6 + l_comp_room; + l_rgn_size = 6 + l_comp_room; - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_RGN,2); /* RGN */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_RGN, + 2); /* RGN */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_rgn_size-2,2); /* Lrgn */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_rgn_size - 2, + 2); /* Lrgn */ + l_current_data += 2; - opj_write_bytes(l_current_data,p_comp_no,l_comp_room); /* Crgn */ - l_current_data+=l_comp_room; + opj_write_bytes(l_current_data, p_comp_no, + l_comp_room); /* Crgn */ + l_current_data += l_comp_room; - opj_write_bytes(l_current_data, 0,1); /* Srgn */ - ++l_current_data; + opj_write_bytes(l_current_data, 0, + 1); /* Srgn */ + ++l_current_data; - opj_write_bytes(l_current_data, (OPJ_UINT32)l_tccp->roishift,1); /* SPrgn */ - ++l_current_data; + opj_write_bytes(l_current_data, (OPJ_UINT32)l_tccp->roishift, + 1); /* SPrgn */ + ++l_current_data; - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_rgn_size,p_manager) != l_rgn_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_rgn_size, + p_manager) != l_rgn_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_eoc( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_write_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_header_tile_data,J2K_MS_EOC,2); /* EOC */ + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_header_tile_data, + J2K_MS_EOC, 2); /* EOC */ -/* UniPG>> */ + /* UniPG>> */ #ifdef USE_JPWL - /* update markers struct */ - /* - OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_EOC, p_stream_tell(p_stream) - 2, 2); -*/ + /* update markers struct */ + /* + OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_EOC, p_stream_tell(p_stream) - 2, 2); + */ #endif /* USE_JPWL */ - if ( opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,2,p_manager) != 2) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, 2, p_manager) != 2) { + return OPJ_FALSE; + } - if ( ! opj_stream_flush(p_stream,p_manager) ) { - return OPJ_FALSE; - } + if (! opj_stream_flush(p_stream, p_manager)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -4526,594 +4932,632 @@ static OPJ_BOOL opj_j2k_write_eoc( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the POC marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_rgn (opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_rgn(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_nb_comp; - opj_image_t * l_image = 00; + OPJ_UINT32 l_nb_comp; + opj_image_t * l_image = 00; - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_comp_room, l_comp_no, l_roi_sty; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_comp_room, l_comp_no, l_roi_sty; - /* preconditions*/ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_image = p_j2k->m_private_image; - l_nb_comp = l_image->numcomps; + l_image = p_j2k->m_private_image; + l_nb_comp = l_image->numcomps; - if (l_nb_comp <= 256) { - l_comp_room = 1; } - else { - l_comp_room = 2; } + if (l_nb_comp <= 256) { + l_comp_room = 1; + } else { + l_comp_room = 2; + } - if (p_header_size != 2 + l_comp_room) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading RGN marker\n"); - return OPJ_FALSE; - } + if (p_header_size != 2 + l_comp_room) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading RGN marker\n"); + return OPJ_FALSE; + } - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; - opj_read_bytes(p_header_data,&l_comp_no,l_comp_room); /* Crgn */ - p_header_data+=l_comp_room; - opj_read_bytes(p_header_data,&l_roi_sty,1); /* Srgn */ - ++p_header_data; + opj_read_bytes(p_header_data, &l_comp_no, l_comp_room); /* Crgn */ + p_header_data += l_comp_room; + opj_read_bytes(p_header_data, &l_roi_sty, + 1); /* Srgn */ + ++p_header_data; #ifdef USE_JPWL - if (l_cp->correct) { - /* totlen is negative or larger than the bytes left!!! */ - if (l_comp_room >= l_nb_comp) { - opj_event_msg(p_manager, EVT_ERROR, - "JPWL: bad component number in RGN (%d when there are only %d)\n", - l_comp_room, l_nb_comp); - if (!JPWL_ASSUME || JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - } - }; -#endif /* USE_JPWL */ - - /* testcase 3635.pdf.asan.77.2930 */ - if (l_comp_no >= l_nb_comp) { - opj_event_msg(p_manager, EVT_ERROR, - "bad component number in RGN (%d when there are only %d)\n", - l_comp_no, l_nb_comp); + if (l_cp->correct) { + /* totlen is negative or larger than the bytes left!!! */ + if (l_comp_room >= l_nb_comp) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad component number in RGN (%d when there are only %d)\n", + l_comp_room, l_nb_comp); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); return OPJ_FALSE; + } } + }; +#endif /* USE_JPWL */ - opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&(l_tcp->tccps[l_comp_no].roishift)),1); /* SPrgn */ - ++p_header_data; + /* testcase 3635.pdf.asan.77.2930 */ + if (l_comp_no >= l_nb_comp) { + opj_event_msg(p_manager, EVT_ERROR, + "bad component number in RGN (%d when there are only %d)\n", + l_comp_no, l_nb_comp); + return OPJ_FALSE; + } - return OPJ_TRUE; + opj_read_bytes(p_header_data, + (OPJ_UINT32 *)(&(l_tcp->tccps[l_comp_no].roishift)), 1); /* SPrgn */ + ++p_header_data; + + return OPJ_TRUE; } -static OPJ_FLOAT32 opj_j2k_get_tp_stride (opj_tcp_t * p_tcp) +static OPJ_FLOAT32 opj_j2k_get_tp_stride(opj_tcp_t * p_tcp) { - return (OPJ_FLOAT32) ((p_tcp->m_nb_tile_parts - 1) * 14); + return (OPJ_FLOAT32)((p_tcp->m_nb_tile_parts - 1) * 14); } -static OPJ_FLOAT32 opj_j2k_get_default_stride (opj_tcp_t * p_tcp) +static OPJ_FLOAT32 opj_j2k_get_default_stride(opj_tcp_t * p_tcp) { (void)p_tcp; return 0; } -static OPJ_BOOL opj_j2k_update_rates( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) -{ - opj_cp_t * l_cp = 00; - opj_image_t * l_image = 00; - opj_tcp_t * l_tcp = 00; - opj_image_comp_t * l_img_comp = 00; - - OPJ_UINT32 i,j,k; - OPJ_INT32 l_x0,l_y0,l_x1,l_y1; - OPJ_FLOAT32 * l_rates = 0; - OPJ_FLOAT32 l_sot_remove; - OPJ_UINT32 l_bits_empty, l_size_pixel; - OPJ_UINT32 l_tile_size = 0; - OPJ_UINT32 l_last_res; - OPJ_FLOAT32 (* l_tp_stride_func)(opj_tcp_t *) = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_cp = &(p_j2k->m_cp); - l_image = p_j2k->m_private_image; - l_tcp = l_cp->tcps; - - l_bits_empty = 8 * l_image->comps->dx * l_image->comps->dy; - l_size_pixel = l_image->numcomps * l_image->comps->prec; - l_sot_remove = (OPJ_FLOAT32) opj_stream_tell(p_stream) / (OPJ_FLOAT32)(l_cp->th * l_cp->tw); - - if (l_cp->m_specific_param.m_enc.m_tp_on) { - l_tp_stride_func = opj_j2k_get_tp_stride; - } - else { - l_tp_stride_func = opj_j2k_get_default_stride; - } - - for (i=0;i<l_cp->th;++i) { - for (j=0;j<l_cp->tw;++j) { - OPJ_FLOAT32 l_offset = (OPJ_FLOAT32)(*l_tp_stride_func)(l_tcp) / (OPJ_FLOAT32)l_tcp->numlayers; - - /* 4 borders of the tile rescale on the image if necessary */ - l_x0 = opj_int_max((OPJ_INT32)(l_cp->tx0 + j * l_cp->tdx), (OPJ_INT32)l_image->x0); - l_y0 = opj_int_max((OPJ_INT32)(l_cp->ty0 + i * l_cp->tdy), (OPJ_INT32)l_image->y0); - l_x1 = opj_int_min((OPJ_INT32)(l_cp->tx0 + (j + 1) * l_cp->tdx), (OPJ_INT32)l_image->x1); - l_y1 = opj_int_min((OPJ_INT32)(l_cp->ty0 + (i + 1) * l_cp->tdy), (OPJ_INT32)l_image->y1); - - l_rates = l_tcp->rates; - - /* Modification of the RATE >> */ - if (*l_rates) { - *l_rates = (( (OPJ_FLOAT32) (l_size_pixel * (OPJ_UINT32)(l_x1 - l_x0) * (OPJ_UINT32)(l_y1 - l_y0))) - / - ((*l_rates) * (OPJ_FLOAT32)l_bits_empty) - ) - - - l_offset; - } +static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + opj_cp_t * l_cp = 00; + opj_image_t * l_image = 00; + opj_tcp_t * l_tcp = 00; + opj_image_comp_t * l_img_comp = 00; - ++l_rates; + OPJ_UINT32 i, j, k; + OPJ_INT32 l_x0, l_y0, l_x1, l_y1; + OPJ_FLOAT32 * l_rates = 0; + OPJ_FLOAT32 l_sot_remove; + OPJ_UINT32 l_bits_empty, l_size_pixel; + OPJ_UINT32 l_tile_size = 0; + OPJ_UINT32 l_last_res; + OPJ_FLOAT32(* l_tp_stride_func)(opj_tcp_t *) = 00; - for (k = 1; k < l_tcp->numlayers; ++k) { - if (*l_rates) { - *l_rates = (( (OPJ_FLOAT32) (l_size_pixel * (OPJ_UINT32)(l_x1 - l_x0) * (OPJ_UINT32)(l_y1 - l_y0))) - / - ((*l_rates) * (OPJ_FLOAT32)l_bits_empty) - ) - - - l_offset; - } + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - ++l_rates; - } + OPJ_UNUSED(p_manager); + + l_cp = &(p_j2k->m_cp); + l_image = p_j2k->m_private_image; + l_tcp = l_cp->tcps; + + l_bits_empty = 8 * l_image->comps->dx * l_image->comps->dy; + l_size_pixel = l_image->numcomps * l_image->comps->prec; + l_sot_remove = (OPJ_FLOAT32) opj_stream_tell(p_stream) / (OPJ_FLOAT32)( + l_cp->th * l_cp->tw); - ++l_tcp; + if (l_cp->m_specific_param.m_enc.m_tp_on) { + l_tp_stride_func = opj_j2k_get_tp_stride; + } else { + l_tp_stride_func = opj_j2k_get_default_stride; + } + + for (i = 0; i < l_cp->th; ++i) { + for (j = 0; j < l_cp->tw; ++j) { + OPJ_FLOAT32 l_offset = (OPJ_FLOAT32)(*l_tp_stride_func)(l_tcp) / + (OPJ_FLOAT32)l_tcp->numlayers; + + /* 4 borders of the tile rescale on the image if necessary */ + l_x0 = opj_int_max((OPJ_INT32)(l_cp->tx0 + j * l_cp->tdx), + (OPJ_INT32)l_image->x0); + l_y0 = opj_int_max((OPJ_INT32)(l_cp->ty0 + i * l_cp->tdy), + (OPJ_INT32)l_image->y0); + l_x1 = opj_int_min((OPJ_INT32)(l_cp->tx0 + (j + 1) * l_cp->tdx), + (OPJ_INT32)l_image->x1); + l_y1 = opj_int_min((OPJ_INT32)(l_cp->ty0 + (i + 1) * l_cp->tdy), + (OPJ_INT32)l_image->y1); + + l_rates = l_tcp->rates; + + /* Modification of the RATE >> */ + if (*l_rates > 0.0f) { + *l_rates = (((OPJ_FLOAT32)(l_size_pixel * (OPJ_UINT32)(l_x1 - l_x0) * + (OPJ_UINT32)(l_y1 - l_y0))) + / + ((*l_rates) * (OPJ_FLOAT32)l_bits_empty) + ) + - + l_offset; + } + + ++l_rates; + for (k = 1; k < l_tcp->numlayers; ++k) { + if (*l_rates > 0.0f) { + *l_rates = (((OPJ_FLOAT32)(l_size_pixel * (OPJ_UINT32)(l_x1 - l_x0) * + (OPJ_UINT32)(l_y1 - l_y0))) + / + ((*l_rates) * (OPJ_FLOAT32)l_bits_empty) + ) + - + l_offset; } - } - l_tcp = l_cp->tcps; + ++l_rates; + } + + ++l_tcp; - for (i=0;i<l_cp->th;++i) { - for (j=0;j<l_cp->tw;++j) { - l_rates = l_tcp->rates; + } + } - if (*l_rates) { - *l_rates -= l_sot_remove; + l_tcp = l_cp->tcps; - if (*l_rates < 30) { - *l_rates = 30; - } - } + for (i = 0; i < l_cp->th; ++i) { + for (j = 0; j < l_cp->tw; ++j) { + l_rates = l_tcp->rates; - ++l_rates; + if (*l_rates > 0.0f) { + *l_rates -= l_sot_remove; - l_last_res = l_tcp->numlayers - 1; + if (*l_rates < 30.0f) { + *l_rates = 30.0f; + } + } - for (k = 1; k < l_last_res; ++k) { + ++l_rates; - if (*l_rates) { - *l_rates -= l_sot_remove; + l_last_res = l_tcp->numlayers - 1; - if (*l_rates < *(l_rates - 1) + 10) { - *l_rates = (*(l_rates - 1)) + 20; - } - } + for (k = 1; k < l_last_res; ++k) { - ++l_rates; - } + if (*l_rates > 0.0f) { + *l_rates -= l_sot_remove; - if (*l_rates) { - *l_rates -= (l_sot_remove + 2.f); + if (*l_rates < * (l_rates - 1) + 10.0f) { + *l_rates = (*(l_rates - 1)) + 20.0f; + } + } - if (*l_rates < *(l_rates - 1) + 10) { - *l_rates = (*(l_rates - 1)) + 20; - } - } + ++l_rates; + } - ++l_tcp; + if (*l_rates > 0.0f) { + *l_rates -= (l_sot_remove + 2.f); + + if (*l_rates < * (l_rates - 1) + 10.0f) { + *l_rates = (*(l_rates - 1)) + 20.0f; } + } + + ++l_tcp; } + } - l_img_comp = l_image->comps; - l_tile_size = 0; + l_img_comp = l_image->comps; + l_tile_size = 0; - for (i=0;i<l_image->numcomps;++i) { - l_tile_size += ( opj_uint_ceildiv(l_cp->tdx,l_img_comp->dx) - * - opj_uint_ceildiv(l_cp->tdy,l_img_comp->dy) - * - l_img_comp->prec - ); + for (i = 0; i < l_image->numcomps; ++i) { + l_tile_size += (opj_uint_ceildiv(l_cp->tdx, l_img_comp->dx) + * + opj_uint_ceildiv(l_cp->tdy, l_img_comp->dy) + * + l_img_comp->prec + ); - ++l_img_comp; - } + ++l_img_comp; + } - l_tile_size = (OPJ_UINT32) (l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */ + /* TODO: where does this magic value come from ? */ + /* This used to be 1.3 / 8, but with random data and very small code */ + /* block sizes, this is not enough. For example with */ + /* bin/test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16 */ + /* TODO revise this to take into account the overhead linked to the */ + /* number of packets and number of code blocks in packets */ + l_tile_size = (OPJ_UINT32)(l_tile_size * 1.4 / 8); - l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k); + /* Arbitrary amount to make the following work: */ + /* bin/test_tile_encoder 1 256 256 17 16 8 0 reversible_no_precinct.j2k 4 4 3 0 0 1 */ + l_tile_size += 500; - p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = l_tile_size; - p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = - (OPJ_BYTE *) opj_malloc(p_j2k->m_specific_param.m_encoder.m_encoded_tile_size); - if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data == 00) { - return OPJ_FALSE; - } + l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k); - if (OPJ_IS_CINEMA(l_cp->rsiz)) { - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = - (OPJ_BYTE *) opj_malloc(5*p_j2k->m_specific_param.m_encoder.m_total_tile_parts); - if (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { - return OPJ_FALSE; - } + p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = l_tile_size; + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = + (OPJ_BYTE *) opj_malloc(p_j2k->m_specific_param.m_encoder.m_encoded_tile_size); + if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data == 00) { + return OPJ_FALSE; + } - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer; + if (OPJ_IS_CINEMA(l_cp->rsiz)) { + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = + (OPJ_BYTE *) opj_malloc(5 * + p_j2k->m_specific_param.m_encoder.m_total_tile_parts); + if (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { + return OPJ_FALSE; } - return OPJ_TRUE; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer; + } + + return OPJ_TRUE; } #if 0 -static OPJ_BOOL opj_j2k_read_eoc ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_read_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 i; - opj_tcd_t * l_tcd = 00; - OPJ_UINT32 l_nb_tiles; - opj_tcp_t * l_tcp = 00; - OPJ_BOOL l_success; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - l_tcp = p_j2k->m_cp.tcps; + OPJ_UINT32 i; + opj_tcd_t * l_tcd = 00; + OPJ_UINT32 l_nb_tiles; + opj_tcp_t * l_tcp = 00; + OPJ_BOOL l_success; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + + l_tcd = opj_tcd_create(OPJ_TRUE); + if (l_tcd == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } - l_tcd = opj_tcd_create(OPJ_TRUE); - if (l_tcd == 00) { + for (i = 0; i < l_nb_tiles; ++i) { + if (l_tcp->m_data) { + if (! opj_tcd_init_decode_tile(l_tcd, i)) { + opj_tcd_destroy(l_tcd); opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); return OPJ_FALSE; - } - - for (i = 0; i < l_nb_tiles; ++i) { - if (l_tcp->m_data) { - if (! opj_tcd_init_decode_tile(l_tcd, i)) { - opj_tcd_destroy(l_tcd); - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); - return OPJ_FALSE; - } - - l_success = opj_tcd_decode_tile(l_tcd, l_tcp->m_data, l_tcp->m_data_size, i, p_j2k->cstr_index); - /* cleanup */ + } - if (! l_success) { - p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR; - break; - } - } + l_success = opj_tcd_decode_tile(l_tcd, l_tcp->m_data, l_tcp->m_data_size, i, + p_j2k->cstr_index); + /* cleanup */ - opj_j2k_tcp_destroy(l_tcp); - ++l_tcp; + if (! l_success) { + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR; + break; + } } - opj_tcd_destroy(l_tcd); - return OPJ_TRUE; + opj_j2k_tcp_destroy(l_tcp); + ++l_tcp; + } + + opj_tcd_destroy(l_tcd); + return OPJ_TRUE; } #endif static OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - p_j2k->cstr_index->main_head_end = opj_stream_tell(p_stream); + OPJ_UNUSED(p_manager); - return OPJ_TRUE; + p_j2k->cstr_index->main_head_end = opj_stream_tell(p_stream); + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_mct_data_group( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_mct_data_group(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 i; - opj_simple_mcc_decorrelation_data_t * l_mcc_record; - opj_mct_data_t * l_mct_record; - opj_tcp_t * l_tcp; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); + OPJ_UINT32 i; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_mct_record; + opj_tcp_t * l_tcp; - if (! opj_j2k_write_cbd(p_j2k,p_stream,p_manager)) { - return OPJ_FALSE; - } + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); - l_mct_record = l_tcp->m_mct_records; + if (! opj_j2k_write_cbd(p_j2k, p_stream, p_manager)) { + return OPJ_FALSE; + } - for (i=0;i<l_tcp->m_nb_mct_records;++i) { + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + l_mct_record = l_tcp->m_mct_records; - if (! opj_j2k_write_mct_record(p_j2k,l_mct_record,p_stream,p_manager)) { - return OPJ_FALSE; - } + for (i = 0; i < l_tcp->m_nb_mct_records; ++i) { - ++l_mct_record; + if (! opj_j2k_write_mct_record(p_j2k, l_mct_record, p_stream, p_manager)) { + return OPJ_FALSE; } - l_mcc_record = l_tcp->m_mcc_records; + ++l_mct_record; + } - for (i=0;i<l_tcp->m_nb_mcc_records;++i) { + l_mcc_record = l_tcp->m_mcc_records; - if (! opj_j2k_write_mcc_record(p_j2k,l_mcc_record,p_stream,p_manager)) { - return OPJ_FALSE; - } + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { - ++l_mcc_record; + if (! opj_j2k_write_mcc_record(p_j2k, l_mcc_record, p_stream, p_manager)) { + return OPJ_FALSE; } - if (! opj_j2k_write_mco(p_j2k,p_stream,p_manager)) { - return OPJ_FALSE; - } + ++l_mcc_record; + } - return OPJ_TRUE; + if (! opj_j2k_write_mco(p_j2k, p_stream, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -#if 0 -static OPJ_BOOL opj_j2k_write_all_coc(opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_all_coc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 compno; + OPJ_UINT32 compno; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) - { - if (! opj_j2k_write_coc(p_j2k,compno,p_stream, p_manager)) { - return OPJ_FALSE; - } + for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno) { + /* cod is first component of first tile */ + if (! opj_j2k_compare_coc(p_j2k, 0, compno)) { + if (! opj_j2k_write_coc(p_j2k, compno, p_stream, p_manager)) { + return OPJ_FALSE; + } } + } - return OPJ_TRUE; + return OPJ_TRUE; } -#endif -#if 0 -static OPJ_BOOL opj_j2k_write_all_qcc(opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_all_qcc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 compno; + OPJ_UINT32 compno; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) - { - if (! opj_j2k_write_qcc(p_j2k,compno,p_stream, p_manager)) { - return OPJ_FALSE; - } + for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno) { + /* qcd is first component of first tile */ + if (! opj_j2k_compare_qcc(p_j2k, 0, compno)) { + if (! opj_j2k_write_qcc(p_j2k, compno, p_stream, p_manager)) { + return OPJ_FALSE; + } } - - return OPJ_TRUE; + } + return OPJ_TRUE; } -#endif - -static OPJ_BOOL opj_j2k_write_regions( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_regions(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 compno; - const opj_tccp_t *l_tccp = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + OPJ_UINT32 compno; + const opj_tccp_t *l_tccp = 00; - l_tccp = p_j2k->m_cp.tcps->tccps; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) { - if (l_tccp->roishift) { + l_tccp = p_j2k->m_cp.tcps->tccps; - if (! opj_j2k_write_rgn(p_j2k,0,compno,p_j2k->m_private_image->numcomps,p_stream,p_manager)) { - return OPJ_FALSE; - } - } + for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) { + if (l_tccp->roishift) { - ++l_tccp; + if (! opj_j2k_write_rgn(p_j2k, 0, compno, p_j2k->m_private_image->numcomps, + p_stream, p_manager)) { + return OPJ_FALSE; + } } - return OPJ_TRUE; + ++l_tccp; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_epc( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_epc(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - opj_codestream_index_t * l_cstr_index = 00; + opj_codestream_index_t * l_cstr_index = 00; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - l_cstr_index = p_j2k->cstr_index; - if (l_cstr_index) { - l_cstr_index->codestream_size = (OPJ_UINT64)opj_stream_tell(p_stream); - /* UniPG>> */ - /* The following adjustment is done to adjust the codestream size */ - /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */ - /* the first bunch of bytes is not in the codestream */ - l_cstr_index->codestream_size -= (OPJ_UINT64)l_cstr_index->main_head_start; - /* <<UniPG */ - } + OPJ_UNUSED(p_manager); + + l_cstr_index = p_j2k->cstr_index; + if (l_cstr_index) { + l_cstr_index->codestream_size = (OPJ_UINT64)opj_stream_tell(p_stream); + /* UniPG>> */ + /* The following adjustment is done to adjust the codestream size */ + /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */ + /* the first bunch of bytes is not in the codestream */ + l_cstr_index->codestream_size -= (OPJ_UINT64)l_cstr_index->main_head_start; + /* <<UniPG */ + } #ifdef USE_JPWL - /* preparation of JPWL marker segments */ + /* preparation of JPWL marker segments */ #if 0 - if(cp->epc_on) { + if (cp->epc_on) { - /* encode according to JPWL */ - jpwl_encode(p_j2k, p_stream, image); + /* encode according to JPWL */ + jpwl_encode(p_j2k, p_stream, image); - } + } #endif - assert( 0 && "TODO" ); + assert(0 && "TODO"); #endif /* USE_JPWL */ - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_read_unk ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - OPJ_UINT32 *output_marker, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_unk(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + OPJ_UINT32 *output_marker, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_unknown_marker; - const opj_dec_memory_marker_handler_t * l_marker_handler; - OPJ_UINT32 l_size_unk = 2; + OPJ_UINT32 l_unknown_marker; + const opj_dec_memory_marker_handler_t * l_marker_handler; + OPJ_UINT32 l_size_unk = 2; - /* preconditions*/ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); + opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); - for (;;) { - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + for (;;) { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } - /* read 2 bytes as the new marker ID*/ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_unknown_marker,2); + /* read 2 bytes as the new marker ID*/ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_unknown_marker, 2); - if (!(l_unknown_marker < 0xff00)) { + if (!(l_unknown_marker < 0xff00)) { - /* Get the marker handler from the marker ID*/ - l_marker_handler = opj_j2k_get_marker_handler(l_unknown_marker); + /* Get the marker handler from the marker ID*/ + l_marker_handler = opj_j2k_get_marker_handler(l_unknown_marker); - if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { - opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); - return OPJ_FALSE; - } - else { - if (l_marker_handler->id != J2K_MS_UNK) { - /* Add the marker to the codestream index*/ - if (l_marker_handler->id != J2K_MS_SOT) - { - OPJ_BOOL res = opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_UNK, - (OPJ_UINT32) opj_stream_tell(p_stream) - l_size_unk, - l_size_unk); - if (res == OPJ_FALSE) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); - return OPJ_FALSE; - } - } - break; /* next marker is known and well located */ - } - else - l_size_unk += 2; + if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker is not compliant with its position\n"); + return OPJ_FALSE; + } else { + if (l_marker_handler->id != J2K_MS_UNK) { + /* Add the marker to the codestream index*/ + if (l_marker_handler->id != J2K_MS_SOT) { + OPJ_BOOL res = opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_UNK, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_size_unk, + l_size_unk); + if (res == OPJ_FALSE) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); + return OPJ_FALSE; } + } + break; /* next marker is known and well located */ + } else { + l_size_unk += 2; } + } } + } - *output_marker = l_marker_handler->id ; + *output_marker = l_marker_handler->id ; - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_mct_record( opj_j2k_t *p_j2k, - opj_mct_data_t * p_mct_record, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_mct_record(opj_j2k_t *p_j2k, + opj_mct_data_t * p_mct_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 l_mct_size; - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_tmp; + OPJ_UINT32 l_mct_size; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tmp; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - l_mct_size = 10 + p_mct_record->m_data_size; + l_mct_size = 10 + p_mct_record->m_data_size; - if (l_mct_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mct_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCT marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mct_size; + if (l_mct_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mct_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCT marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mct_size; + } - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_MCT,2); /* MCT */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_MCT, + 2); /* MCT */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_mct_size-2,2); /* Lmct */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_mct_size - 2, + 2); /* Lmct */ + l_current_data += 2; - opj_write_bytes(l_current_data,0,2); /* Zmct */ - l_current_data += 2; + opj_write_bytes(l_current_data, 0, + 2); /* Zmct */ + l_current_data += 2; - /* only one marker atm */ - l_tmp = (p_mct_record->m_index & 0xff) | (p_mct_record->m_array_type << 8) | (p_mct_record->m_element_type << 10); + /* only one marker atm */ + l_tmp = (p_mct_record->m_index & 0xff) | (p_mct_record->m_array_type << 8) | + (p_mct_record->m_element_type << 10); - opj_write_bytes(l_current_data,l_tmp,2); - l_current_data += 2; + opj_write_bytes(l_current_data, l_tmp, 2); + l_current_data += 2; - opj_write_bytes(l_current_data,0,2); /* Ymct */ - l_current_data+=2; + opj_write_bytes(l_current_data, 0, + 2); /* Ymct */ + l_current_data += 2; - memcpy(l_current_data,p_mct_record->m_data,p_mct_record->m_data_size); + memcpy(l_current_data, p_mct_record->m_data, p_mct_record->m_data_size); - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mct_size,p_manager) != l_mct_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mct_size, + p_manager) != l_mct_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -5124,494 +5568,552 @@ static OPJ_BOOL opj_j2k_write_mct_record( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the MCT marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_mct ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 i; - opj_tcp_t *l_tcp = 00; - OPJ_UINT32 l_tmp; - OPJ_UINT32 l_indix; - opj_mct_data_t * l_mct_data; - OPJ_BOOL new_mct = OPJ_FALSE; - - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - - l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? - &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; - - if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); - return OPJ_FALSE; - } + OPJ_UINT32 i; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_mct_data_t * l_mct_data; + OPJ_BOOL new_mct = OPJ_FALSE; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return OPJ_FALSE; + } - /* first marker */ - opj_read_bytes(p_header_data,&l_tmp,2); /* Zmct */ - p_header_data += 2; - if (l_tmp != 0) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge mct data within multiple MCT records\n"); - return OPJ_TRUE; - } + /* first marker */ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Zmct */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge mct data within multiple MCT records\n"); + return OPJ_TRUE; + } - if(p_header_size <= 6) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); - return OPJ_FALSE; - } + if (p_header_size <= 6) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return OPJ_FALSE; + } - /* Imct -> no need for other values, take the first, type is double with decorrelation x0000 1101 0000 0000*/ - opj_read_bytes(p_header_data,&l_tmp,2); /* Imct */ - p_header_data += 2; + /* Imct -> no need for other values, take the first, type is double with decorrelation x0000 1101 0000 0000*/ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Imct */ + p_header_data += 2; - l_indix = l_tmp & 0xff; - l_mct_data = l_tcp->m_mct_records; + l_indix = l_tmp & 0xff; + l_mct_data = l_tcp->m_mct_records; - for (i=0;i<l_tcp->m_nb_mct_records;++i) { - if (l_mct_data->m_index == l_indix) { - break; - } - ++l_mct_data; + for (i = 0; i < l_tcp->m_nb_mct_records; ++i) { + if (l_mct_data->m_index == l_indix) { + break; } + ++l_mct_data; + } - /* NOT FOUND */ - if (i == l_tcp->m_nb_mct_records) { - if (l_tcp->m_nb_mct_records == l_tcp->m_nb_max_mct_records) { - opj_mct_data_t *new_mct_records; - l_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + /* NOT FOUND */ + if (i == l_tcp->m_nb_mct_records) { + if (l_tcp->m_nb_mct_records == l_tcp->m_nb_max_mct_records) { + opj_mct_data_t *new_mct_records; + l_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + + new_mct_records = (opj_mct_data_t *) opj_realloc(l_tcp->m_mct_records, + l_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! new_mct_records) { + opj_free(l_tcp->m_mct_records); + l_tcp->m_mct_records = NULL; + l_tcp->m_nb_max_mct_records = 0; + l_tcp->m_nb_mct_records = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCT marker\n"); + return OPJ_FALSE; + } - new_mct_records = (opj_mct_data_t *) opj_realloc(l_tcp->m_mct_records, l_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); - if (! new_mct_records) { - opj_free(l_tcp->m_mct_records); - l_tcp->m_mct_records = NULL; - l_tcp->m_nb_max_mct_records = 0; - l_tcp->m_nb_mct_records = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCT marker\n"); - return OPJ_FALSE; - } - l_tcp->m_mct_records = new_mct_records; - l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; - memset(l_mct_data ,0,(l_tcp->m_nb_max_mct_records - l_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + /* Update m_mcc_records[].m_offset_array and m_decorrelation_array + * to point to the new addresses */ + if (new_mct_records != l_tcp->m_mct_records) { + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + opj_simple_mcc_decorrelation_data_t* l_mcc_record = + &(l_tcp->m_mcc_records[i]); + if (l_mcc_record->m_decorrelation_array) { + l_mcc_record->m_decorrelation_array = + new_mct_records + + (l_mcc_record->m_decorrelation_array - + l_tcp->m_mct_records); + } + if (l_mcc_record->m_offset_array) { + l_mcc_record->m_offset_array = + new_mct_records + + (l_mcc_record->m_offset_array - + l_tcp->m_mct_records); + } } + } - l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; - new_mct = OPJ_TRUE; + l_tcp->m_mct_records = new_mct_records; + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + memset(l_mct_data, 0, (l_tcp->m_nb_max_mct_records - l_tcp->m_nb_mct_records) * + sizeof(opj_mct_data_t)); } - if (l_mct_data->m_data) { - opj_free(l_mct_data->m_data); - l_mct_data->m_data = 00; - } + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + new_mct = OPJ_TRUE; + } - l_mct_data->m_index = l_indix; - l_mct_data->m_array_type = (J2K_MCT_ARRAY_TYPE)((l_tmp >> 8) & 3); - l_mct_data->m_element_type = (J2K_MCT_ELEMENT_TYPE)((l_tmp >> 10) & 3); + if (l_mct_data->m_data) { + opj_free(l_mct_data->m_data); + l_mct_data->m_data = 00; + l_mct_data->m_data_size = 0; + } - opj_read_bytes(p_header_data,&l_tmp,2); /* Ymct */ - p_header_data+=2; - if (l_tmp != 0) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple MCT markers\n"); - return OPJ_TRUE; - } + l_mct_data->m_index = l_indix; + l_mct_data->m_array_type = (J2K_MCT_ARRAY_TYPE)((l_tmp >> 8) & 3); + l_mct_data->m_element_type = (J2K_MCT_ELEMENT_TYPE)((l_tmp >> 10) & 3); + + opj_read_bytes(p_header_data, &l_tmp, 2); /* Ymct */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple MCT markers\n"); + return OPJ_TRUE; + } - p_header_size -= 6; + p_header_size -= 6; - l_mct_data->m_data = (OPJ_BYTE*)opj_malloc(p_header_size); - if (! l_mct_data->m_data) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); - return OPJ_FALSE; - } - memcpy(l_mct_data->m_data,p_header_data,p_header_size); + l_mct_data->m_data = (OPJ_BYTE*)opj_malloc(p_header_size); + if (! l_mct_data->m_data) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return OPJ_FALSE; + } + memcpy(l_mct_data->m_data, p_header_data, p_header_size); - l_mct_data->m_data_size = p_header_size; + l_mct_data->m_data_size = p_header_size; - if (new_mct) { - ++l_tcp->m_nb_mct_records; - } - return OPJ_TRUE; + if (new_mct) { + ++l_tcp->m_nb_mct_records; + } + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_mcc_record( opj_j2k_t *p_j2k, - struct opj_simple_mcc_decorrelation_data * p_mcc_record, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_mcc_record(opj_j2k_t *p_j2k, + struct opj_simple_mcc_decorrelation_data * p_mcc_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 i; - OPJ_UINT32 l_mcc_size; - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_nb_bytes_for_comp; - OPJ_UINT32 l_mask; - OPJ_UINT32 l_tmcc; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - if (p_mcc_record->m_nb_comps > 255 ) { + OPJ_UINT32 i; + OPJ_UINT32 l_mcc_size; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_bytes_for_comp; + OPJ_UINT32 l_mask; + OPJ_UINT32 l_tmcc; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + if (p_mcc_record->m_nb_comps > 255) { l_nb_bytes_for_comp = 2; - l_mask = 0x8000; - } - else { - l_nb_bytes_for_comp = 1; - l_mask = 0; - } + l_mask = 0x8000; + } else { + l_nb_bytes_for_comp = 1; + l_mask = 0; + } - l_mcc_size = p_mcc_record->m_nb_comps * 2 * l_nb_bytes_for_comp + 19; - if (l_mcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) - { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mcc_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCC marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mcc_size; + l_mcc_size = p_mcc_record->m_nb_comps * 2 * l_nb_bytes_for_comp + 19; + if (l_mcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mcc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCC marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mcc_size; + } - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_MCC,2); /* MCC */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_MCC, + 2); /* MCC */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_mcc_size-2,2); /* Lmcc */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_mcc_size - 2, + 2); /* Lmcc */ + l_current_data += 2; - /* first marker */ - opj_write_bytes(l_current_data,0,2); /* Zmcc */ - l_current_data += 2; + /* first marker */ + opj_write_bytes(l_current_data, 0, + 2); /* Zmcc */ + l_current_data += 2; - opj_write_bytes(l_current_data,p_mcc_record->m_index,1); /* Imcc -> no need for other values, take the first */ - ++l_current_data; + opj_write_bytes(l_current_data, p_mcc_record->m_index, + 1); /* Imcc -> no need for other values, take the first */ + ++l_current_data; - /* only one marker atm */ - opj_write_bytes(l_current_data,0,2); /* Ymcc */ - l_current_data+=2; + /* only one marker atm */ + opj_write_bytes(l_current_data, 0, + 2); /* Ymcc */ + l_current_data += 2; - opj_write_bytes(l_current_data,1,2); /* Qmcc -> number of collections -> 1 */ - l_current_data+=2; + opj_write_bytes(l_current_data, 1, + 2); /* Qmcc -> number of collections -> 1 */ + l_current_data += 2; - opj_write_bytes(l_current_data,0x1,1); /* Xmcci type of component transformation -> array based decorrelation */ - ++l_current_data; + opj_write_bytes(l_current_data, 0x1, + 1); /* Xmcci type of component transformation -> array based decorrelation */ + ++l_current_data; - opj_write_bytes(l_current_data,p_mcc_record->m_nb_comps | l_mask,2); /* Nmcci number of input components involved and size for each component offset = 8 bits */ - l_current_data+=2; + opj_write_bytes(l_current_data, p_mcc_record->m_nb_comps | l_mask, + 2); /* Nmcci number of input components involved and size for each component offset = 8 bits */ + l_current_data += 2; - for (i=0;i<p_mcc_record->m_nb_comps;++i) { - opj_write_bytes(l_current_data,i,l_nb_bytes_for_comp); /* Cmccij Component offset*/ - l_current_data+=l_nb_bytes_for_comp; - } + for (i = 0; i < p_mcc_record->m_nb_comps; ++i) { + opj_write_bytes(l_current_data, i, + l_nb_bytes_for_comp); /* Cmccij Component offset*/ + l_current_data += l_nb_bytes_for_comp; + } - opj_write_bytes(l_current_data,p_mcc_record->m_nb_comps|l_mask,2); /* Mmcci number of output components involved and size for each component offset = 8 bits */ - l_current_data+=2; + opj_write_bytes(l_current_data, p_mcc_record->m_nb_comps | l_mask, + 2); /* Mmcci number of output components involved and size for each component offset = 8 bits */ + l_current_data += 2; - for (i=0;i<p_mcc_record->m_nb_comps;++i) - { - opj_write_bytes(l_current_data,i,l_nb_bytes_for_comp); /* Wmccij Component offset*/ - l_current_data+=l_nb_bytes_for_comp; - } + for (i = 0; i < p_mcc_record->m_nb_comps; ++i) { + opj_write_bytes(l_current_data, i, + l_nb_bytes_for_comp); /* Wmccij Component offset*/ + l_current_data += l_nb_bytes_for_comp; + } - l_tmcc = ((!p_mcc_record->m_is_irreversible)&1)<<16; + l_tmcc = ((!p_mcc_record->m_is_irreversible) & 1U) << 16; - if (p_mcc_record->m_decorrelation_array) { - l_tmcc |= p_mcc_record->m_decorrelation_array->m_index; - } + if (p_mcc_record->m_decorrelation_array) { + l_tmcc |= p_mcc_record->m_decorrelation_array->m_index; + } - if (p_mcc_record->m_offset_array) { - l_tmcc |= ((p_mcc_record->m_offset_array->m_index)<<8); - } + if (p_mcc_record->m_offset_array) { + l_tmcc |= ((p_mcc_record->m_offset_array->m_index) << 8); + } - opj_write_bytes(l_current_data,l_tmcc,3); /* Tmcci : use MCT defined as number 1 and irreversible array based. */ - l_current_data+=3; + opj_write_bytes(l_current_data, l_tmcc, + 3); /* Tmcci : use MCT defined as number 1 and irreversible array based. */ + l_current_data += 3; - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mcc_size,p_manager) != l_mcc_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mcc_size, + p_manager) != l_mcc_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_read_mcc ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 i,j; - OPJ_UINT32 l_tmp; - OPJ_UINT32 l_indix; - opj_tcp_t * l_tcp; - opj_simple_mcc_decorrelation_data_t * l_mcc_record; - opj_mct_data_t * l_mct_data; - OPJ_UINT32 l_nb_collections; - OPJ_UINT32 l_nb_comps; - OPJ_UINT32 l_nb_bytes_by_comp; - OPJ_BOOL new_mcc = OPJ_FALSE; +static OPJ_BOOL opj_j2k_read_mcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_tcp_t * l_tcp; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_mct_data; + OPJ_UINT32 l_nb_collections; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_nb_bytes_by_comp; + OPJ_BOOL l_new_mcc = OPJ_FALSE; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* first marker */ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Zmcc */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple data spanning\n"); + return OPJ_TRUE; + } - l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? - &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; + if (p_header_size < 7) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } - if (p_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return OPJ_FALSE; - } + opj_read_bytes(p_header_data, &l_indix, + 1); /* Imcc -> no need for other values, take the first */ + ++p_header_data; - /* first marker */ - opj_read_bytes(p_header_data,&l_tmp,2); /* Zmcc */ - p_header_data += 2; - if (l_tmp != 0) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple data spanning\n"); - return OPJ_TRUE; + l_mcc_record = l_tcp->m_mcc_records; + + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + if (l_mcc_record->m_index == l_indix) { + break; } + ++l_mcc_record; + } - if (p_header_size < 7) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + /** NOT FOUND */ + if (i == l_tcp->m_nb_mcc_records) { + if (l_tcp->m_nb_mcc_records == l_tcp->m_nb_max_mcc_records) { + opj_simple_mcc_decorrelation_data_t *new_mcc_records; + l_tcp->m_nb_max_mcc_records += OPJ_J2K_MCC_DEFAULT_NB_RECORDS; + + new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc( + l_tcp->m_mcc_records, l_tcp->m_nb_max_mcc_records * sizeof( + opj_simple_mcc_decorrelation_data_t)); + if (! new_mcc_records) { + opj_free(l_tcp->m_mcc_records); + l_tcp->m_mcc_records = NULL; + l_tcp->m_nb_max_mcc_records = 0; + l_tcp->m_nb_mcc_records = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCC marker\n"); return OPJ_FALSE; + } + l_tcp->m_mcc_records = new_mcc_records; + l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; + memset(l_mcc_record, 0, (l_tcp->m_nb_max_mcc_records - l_tcp->m_nb_mcc_records) + * sizeof(opj_simple_mcc_decorrelation_data_t)); } + l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; + l_new_mcc = OPJ_TRUE; + } + l_mcc_record->m_index = l_indix; - opj_read_bytes(p_header_data,&l_indix,1); /* Imcc -> no need for other values, take the first */ - ++p_header_data; - - l_mcc_record = l_tcp->m_mcc_records; + /* only one marker atm */ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Ymcc */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple data spanning\n"); + return OPJ_TRUE; + } - for(i=0;i<l_tcp->m_nb_mcc_records;++i) { - if (l_mcc_record->m_index == l_indix) { - break; - } - ++l_mcc_record; - } - - /** NOT FOUND */ - if (i == l_tcp->m_nb_mcc_records) { - if (l_tcp->m_nb_mcc_records == l_tcp->m_nb_max_mcc_records) { - opj_simple_mcc_decorrelation_data_t *new_mcc_records; - l_tcp->m_nb_max_mcc_records += OPJ_J2K_MCC_DEFAULT_NB_RECORDS; - - new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc( - l_tcp->m_mcc_records, l_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t)); - if (! new_mcc_records) { - opj_free(l_tcp->m_mcc_records); - l_tcp->m_mcc_records = NULL; - l_tcp->m_nb_max_mcc_records = 0; - l_tcp->m_nb_mcc_records = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCC marker\n"); - return OPJ_FALSE; - } - l_tcp->m_mcc_records = new_mcc_records; - l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; - memset(l_mcc_record,0,(l_tcp->m_nb_max_mcc_records-l_tcp->m_nb_mcc_records) * sizeof(opj_simple_mcc_decorrelation_data_t)); - } - l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; - new_mcc = OPJ_TRUE; - } - l_mcc_record->m_index = l_indix; + opj_read_bytes(p_header_data, &l_nb_collections, + 2); /* Qmcc -> number of collections -> 1 */ + p_header_data += 2; - /* only one marker atm */ - opj_read_bytes(p_header_data,&l_tmp,2); /* Ymcc */ - p_header_data+=2; - if (l_tmp != 0) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple data spanning\n"); - return OPJ_TRUE; - } + if (l_nb_collections > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple collections\n"); + return OPJ_TRUE; + } - opj_read_bytes(p_header_data,&l_nb_collections,2); /* Qmcc -> number of collections -> 1 */ - p_header_data+=2; + p_header_size -= 7; - if (l_nb_collections > 1) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple collections\n"); - return OPJ_TRUE; + for (i = 0; i < l_nb_collections; ++i) { + if (p_header_size < 3) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; } - p_header_size -= 7; - - for (i=0;i<l_nb_collections;++i) { - if (p_header_size < 3) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return OPJ_FALSE; - } + opj_read_bytes(p_header_data, &l_tmp, + 1); /* Xmcci type of component transformation -> array based decorrelation */ + ++p_header_data; - opj_read_bytes(p_header_data,&l_tmp,1); /* Xmcci type of component transformation -> array based decorrelation */ - ++p_header_data; + if (l_tmp != 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections other than array decorrelation\n"); + return OPJ_TRUE; + } - if (l_tmp != 1) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections other than array decorrelation\n"); - return OPJ_TRUE; - } + opj_read_bytes(p_header_data, &l_nb_comps, 2); - opj_read_bytes(p_header_data,&l_nb_comps,2); + p_header_data += 2; + p_header_size -= 3; - p_header_data+=2; - p_header_size-=3; + l_nb_bytes_by_comp = 1 + (l_nb_comps >> 15); + l_mcc_record->m_nb_comps = l_nb_comps & 0x7fff; - l_nb_bytes_by_comp = 1 + (l_nb_comps>>15); - l_mcc_record->m_nb_comps = l_nb_comps & 0x7fff; + if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } - if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return OPJ_FALSE; - } + p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2); - p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2); + for (j = 0; j < l_mcc_record->m_nb_comps; ++j) { + opj_read_bytes(p_header_data, &l_tmp, + l_nb_bytes_by_comp); /* Cmccij Component offset*/ + p_header_data += l_nb_bytes_by_comp; - for (j=0;j<l_mcc_record->m_nb_comps;++j) { - opj_read_bytes(p_header_data,&l_tmp,l_nb_bytes_by_comp); /* Cmccij Component offset*/ - p_header_data+=l_nb_bytes_by_comp; + if (l_tmp != j) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections with indix shuffle\n"); + return OPJ_TRUE; + } + } - if (l_tmp != j) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections with indix shuffle\n"); - return OPJ_TRUE; - } - } + opj_read_bytes(p_header_data, &l_nb_comps, 2); + p_header_data += 2; - opj_read_bytes(p_header_data,&l_nb_comps,2); - p_header_data+=2; + l_nb_bytes_by_comp = 1 + (l_nb_comps >> 15); + l_nb_comps &= 0x7fff; - l_nb_bytes_by_comp = 1 + (l_nb_comps>>15); - l_nb_comps &= 0x7fff; + if (l_nb_comps != l_mcc_record->m_nb_comps) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections without same number of indixes\n"); + return OPJ_TRUE; + } - if (l_nb_comps != l_mcc_record->m_nb_comps) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections without same number of indixes\n"); - return OPJ_TRUE; - } + if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } - if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return OPJ_FALSE; - } + p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3); - p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3); + for (j = 0; j < l_mcc_record->m_nb_comps; ++j) { + opj_read_bytes(p_header_data, &l_tmp, + l_nb_bytes_by_comp); /* Wmccij Component offset*/ + p_header_data += l_nb_bytes_by_comp; - for (j=0;j<l_mcc_record->m_nb_comps;++j) { - opj_read_bytes(p_header_data,&l_tmp,l_nb_bytes_by_comp); /* Wmccij Component offset*/ - p_header_data+=l_nb_bytes_by_comp; + if (l_tmp != j) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections with indix shuffle\n"); + return OPJ_TRUE; + } + } - if (l_tmp != j) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections with indix shuffle\n"); - return OPJ_TRUE; - } - } + opj_read_bytes(p_header_data, &l_tmp, 3); /* Wmccij Component offset*/ + p_header_data += 3; - opj_read_bytes(p_header_data,&l_tmp,3); /* Wmccij Component offset*/ - p_header_data += 3; - - l_mcc_record->m_is_irreversible = ! ((l_tmp>>16) & 1); - l_mcc_record->m_decorrelation_array = 00; - l_mcc_record->m_offset_array = 00; - - l_indix = l_tmp & 0xff; - if (l_indix != 0) { - l_mct_data = l_tcp->m_mct_records; - for (j=0;j<l_tcp->m_nb_mct_records;++j) { - if (l_mct_data->m_index == l_indix) { - l_mcc_record->m_decorrelation_array = l_mct_data; - break; - } - ++l_mct_data; - } + l_mcc_record->m_is_irreversible = !((l_tmp >> 16) & 1); + l_mcc_record->m_decorrelation_array = 00; + l_mcc_record->m_offset_array = 00; - if (l_mcc_record->m_decorrelation_array == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return OPJ_FALSE; - } + l_indix = l_tmp & 0xff; + if (l_indix != 0) { + l_mct_data = l_tcp->m_mct_records; + for (j = 0; j < l_tcp->m_nb_mct_records; ++j) { + if (l_mct_data->m_index == l_indix) { + l_mcc_record->m_decorrelation_array = l_mct_data; + break; } + ++l_mct_data; + } - l_indix = (l_tmp >> 8) & 0xff; - if (l_indix != 0) { - l_mct_data = l_tcp->m_mct_records; - for (j=0;j<l_tcp->m_nb_mct_records;++j) { - if (l_mct_data->m_index == l_indix) { - l_mcc_record->m_offset_array = l_mct_data; - break; - } - ++l_mct_data; - } + if (l_mcc_record->m_decorrelation_array == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + } - if (l_mcc_record->m_offset_array == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return OPJ_FALSE; - } + l_indix = (l_tmp >> 8) & 0xff; + if (l_indix != 0) { + l_mct_data = l_tcp->m_mct_records; + for (j = 0; j < l_tcp->m_nb_mct_records; ++j) { + if (l_mct_data->m_index == l_indix) { + l_mcc_record->m_offset_array = l_mct_data; + break; } - } + ++l_mct_data; + } - if (p_header_size != 0) { + if (l_mcc_record->m_offset_array == 00) { opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); return OPJ_FALSE; + } } + } - if (new_mcc) { - ++l_tcp->m_nb_mcc_records; - } + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + if (l_new_mcc) { + ++l_tcp->m_nb_mcc_records; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_mco( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) +static OPJ_BOOL opj_j2k_write_mco(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) { - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_mco_size; - opj_tcp_t * l_tcp = 00; - opj_simple_mcc_decorrelation_data_t * l_mcc_record; - OPJ_UINT32 i; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_mco_size; + opj_tcp_t * l_tcp = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + OPJ_UINT32 i; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_tcp =&(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); - - l_mco_size = 5 + l_tcp->m_nb_mcc_records; - if (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mco_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCO marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + + l_mco_size = 5 + l_tcp->m_nb_mcc_records; + if (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mco_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCO marker\n"); + return OPJ_FALSE; } - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size; + } + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_MCO,2); /* MCO */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_MCO, 2); /* MCO */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_mco_size-2,2); /* Lmco */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_mco_size - 2, 2); /* Lmco */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1); /* Nmco : only one transform stage*/ - ++l_current_data; + opj_write_bytes(l_current_data, l_tcp->m_nb_mcc_records, + 1); /* Nmco : only one transform stage*/ + ++l_current_data; - l_mcc_record = l_tcp->m_mcc_records; - for (i=0;i<l_tcp->m_nb_mcc_records;++i) { - opj_write_bytes(l_current_data,l_mcc_record->m_index,1);/* Imco -> use the mcc indicated by 1*/ - ++l_current_data; - ++l_mcc_record; - } + l_mcc_record = l_tcp->m_mcc_records; + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + opj_write_bytes(l_current_data, l_mcc_record->m_index, + 1); /* Imco -> use the mcc indicated by 1*/ + ++l_current_data; + ++l_mcc_record; + } - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mco_size,p_manager) != l_mco_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mco_size, + p_manager) != l_mco_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -5622,208 +6124,219 @@ static OPJ_BOOL opj_j2k_write_mco( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the MCO marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_mco ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_mco(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_tmp, i; - OPJ_UINT32 l_nb_stages; - opj_tcp_t * l_tcp; - opj_tccp_t * l_tccp; - opj_image_t * l_image; + OPJ_UINT32 l_tmp, i; + OPJ_UINT32 l_nb_stages; + opj_tcp_t * l_tcp; + opj_tccp_t * l_tccp; + opj_image_t * l_image; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_image = p_j2k->m_private_image; - l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? - &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_image = p_j2k->m_private_image; + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; - if (p_header_size < 1) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCO marker\n"); - return OPJ_FALSE; - } + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCO marker\n"); + return OPJ_FALSE; + } - opj_read_bytes(p_header_data,&l_nb_stages,1); /* Nmco : only one transform stage*/ - ++p_header_data; + opj_read_bytes(p_header_data, &l_nb_stages, + 1); /* Nmco : only one transform stage*/ + ++p_header_data; - if (l_nb_stages > 1) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple transformation stages.\n"); - return OPJ_TRUE; - } + if (l_nb_stages > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple transformation stages.\n"); + return OPJ_TRUE; + } - if (p_header_size != l_nb_stages + 1) { - opj_event_msg(p_manager, EVT_WARNING, "Error reading MCO marker\n"); - return OPJ_FALSE; - } + if (p_header_size != l_nb_stages + 1) { + opj_event_msg(p_manager, EVT_WARNING, "Error reading MCO marker\n"); + return OPJ_FALSE; + } - l_tccp = l_tcp->tccps; + l_tccp = l_tcp->tccps; - for (i=0;i<l_image->numcomps;++i) { - l_tccp->m_dc_level_shift = 0; - ++l_tccp; - } + for (i = 0; i < l_image->numcomps; ++i) { + l_tccp->m_dc_level_shift = 0; + ++l_tccp; + } - if (l_tcp->m_mct_decoding_matrix) { - opj_free(l_tcp->m_mct_decoding_matrix); - l_tcp->m_mct_decoding_matrix = 00; - } + if (l_tcp->m_mct_decoding_matrix) { + opj_free(l_tcp->m_mct_decoding_matrix); + l_tcp->m_mct_decoding_matrix = 00; + } - for (i=0;i<l_nb_stages;++i) { - opj_read_bytes(p_header_data,&l_tmp,1); - ++p_header_data; + for (i = 0; i < l_nb_stages; ++i) { + opj_read_bytes(p_header_data, &l_tmp, 1); + ++p_header_data; - if (! opj_j2k_add_mct(l_tcp,p_j2k->m_private_image,l_tmp)) { - return OPJ_FALSE; - } + if (! opj_j2k_add_mct(l_tcp, p_j2k->m_private_image, l_tmp)) { + return OPJ_FALSE; } + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index) +static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, + OPJ_UINT32 p_index) { - OPJ_UINT32 i; - opj_simple_mcc_decorrelation_data_t * l_mcc_record; - opj_mct_data_t * l_deco_array, * l_offset_array; - OPJ_UINT32 l_data_size,l_mct_size, l_offset_size; - OPJ_UINT32 l_nb_elem; - OPJ_UINT32 * l_offset_data, * l_current_offset_data; - opj_tccp_t * l_tccp; - - /* preconditions */ - assert(p_tcp != 00); + OPJ_UINT32 i; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_deco_array, * l_offset_array; + OPJ_UINT32 l_data_size, l_mct_size, l_offset_size; + OPJ_UINT32 l_nb_elem; + OPJ_UINT32 * l_offset_data, * l_current_offset_data; + opj_tccp_t * l_tccp; - l_mcc_record = p_tcp->m_mcc_records; + /* preconditions */ + assert(p_tcp != 00); - for (i=0;i<p_tcp->m_nb_mcc_records;++i) { - if (l_mcc_record->m_index == p_index) { - break; - } - } + l_mcc_record = p_tcp->m_mcc_records; - if (i==p_tcp->m_nb_mcc_records) { - /** element discarded **/ - return OPJ_TRUE; + for (i = 0; i < p_tcp->m_nb_mcc_records; ++i) { + if (l_mcc_record->m_index == p_index) { + break; } + } - if (l_mcc_record->m_nb_comps != p_image->numcomps) { - /** do not support number of comps != image */ - return OPJ_TRUE; - } + if (i == p_tcp->m_nb_mcc_records) { + /** element discarded **/ + return OPJ_TRUE; + } - l_deco_array = l_mcc_record->m_decorrelation_array; + if (l_mcc_record->m_nb_comps != p_image->numcomps) { + /** do not support number of comps != image */ + return OPJ_TRUE; + } - if (l_deco_array) { - l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps * p_image->numcomps; - if (l_deco_array->m_data_size != l_data_size || ! l_deco_array->m_data) { - return OPJ_FALSE; - } + l_deco_array = l_mcc_record->m_decorrelation_array; - l_nb_elem = p_image->numcomps * p_image->numcomps; - l_mct_size = l_nb_elem * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - p_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); + if (l_deco_array) { + l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps + * p_image->numcomps; + if (l_deco_array->m_data_size != l_data_size || ! l_deco_array->m_data) { + return OPJ_FALSE; + } - if (! p_tcp->m_mct_decoding_matrix ) { - return OPJ_FALSE; - } + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + p_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); - j2k_mct_read_functions_to_float[l_deco_array->m_element_type](l_deco_array->m_data,p_tcp->m_mct_decoding_matrix,l_nb_elem); + if (! p_tcp->m_mct_decoding_matrix) { + return OPJ_FALSE; } - l_offset_array = l_mcc_record->m_offset_array; + j2k_mct_read_functions_to_float[l_deco_array->m_element_type]( + l_deco_array->m_data, p_tcp->m_mct_decoding_matrix, l_nb_elem); + } - if (l_offset_array) { - l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * p_image->numcomps; - if (l_offset_array->m_data_size != l_data_size || ! l_offset_array->m_data) { - return OPJ_FALSE; - } + l_offset_array = l_mcc_record->m_offset_array; - l_nb_elem = p_image->numcomps; - l_offset_size = l_nb_elem * (OPJ_UINT32)sizeof(OPJ_UINT32); - l_offset_data = (OPJ_UINT32*)opj_malloc(l_offset_size); + if (l_offset_array) { + l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * + p_image->numcomps; + if (l_offset_array->m_data_size != l_data_size || ! l_offset_array->m_data) { + return OPJ_FALSE; + } - if (! l_offset_data ) { - return OPJ_FALSE; - } + l_nb_elem = p_image->numcomps; + l_offset_size = l_nb_elem * (OPJ_UINT32)sizeof(OPJ_UINT32); + l_offset_data = (OPJ_UINT32*)opj_malloc(l_offset_size); - j2k_mct_read_functions_to_int32[l_offset_array->m_element_type](l_offset_array->m_data,l_offset_data,l_nb_elem); + if (! l_offset_data) { + return OPJ_FALSE; + } - l_tccp = p_tcp->tccps; - l_current_offset_data = l_offset_data; + j2k_mct_read_functions_to_int32[l_offset_array->m_element_type]( + l_offset_array->m_data, l_offset_data, l_nb_elem); - for (i=0;i<p_image->numcomps;++i) { - l_tccp->m_dc_level_shift = (OPJ_INT32)*(l_current_offset_data++); - ++l_tccp; - } + l_tccp = p_tcp->tccps; + l_current_offset_data = l_offset_data; - opj_free(l_offset_data); + for (i = 0; i < p_image->numcomps; ++i) { + l_tccp->m_dc_level_shift = (OPJ_INT32) * (l_current_offset_data++); + ++l_tccp; } - return OPJ_TRUE; + opj_free(l_offset_data); + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_cbd( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_cbd(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 i; - OPJ_UINT32 l_cbd_size; - OPJ_BYTE * l_current_data = 00; - opj_image_t *l_image = 00; - opj_image_comp_t * l_comp = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_image = p_j2k->m_private_image; - l_cbd_size = 6 + p_j2k->m_private_image->numcomps; - - if (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { - OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_cbd_size); - if (! new_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write CBD marker\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_cbd_size; + OPJ_UINT32 i; + OPJ_UINT32 l_cbd_size; + OPJ_BYTE * l_current_data = 00; + opj_image_t *l_image = 00; + opj_image_comp_t * l_comp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_image = p_j2k->m_private_image; + l_cbd_size = 6 + p_j2k->m_private_image->numcomps; + + if (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_cbd_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write CBD marker\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_cbd_size; + } - l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - opj_write_bytes(l_current_data,J2K_MS_CBD,2); /* CBD */ - l_current_data += 2; + opj_write_bytes(l_current_data, J2K_MS_CBD, 2); /* CBD */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_cbd_size-2,2); /* L_CBD */ - l_current_data += 2; + opj_write_bytes(l_current_data, l_cbd_size - 2, 2); /* L_CBD */ + l_current_data += 2; - opj_write_bytes(l_current_data,l_image->numcomps, 2); /* Ncbd */ - l_current_data+=2; + opj_write_bytes(l_current_data, l_image->numcomps, 2); /* Ncbd */ + l_current_data += 2; - l_comp = l_image->comps; + l_comp = l_image->comps; - for (i=0;i<l_image->numcomps;++i) { - opj_write_bytes(l_current_data, (l_comp->sgnd << 7) | (l_comp->prec - 1), 1); /* Component bit depth */ - ++l_current_data; + for (i = 0; i < l_image->numcomps; ++i) { + opj_write_bytes(l_current_data, (l_comp->sgnd << 7) | (l_comp->prec - 1), + 1); /* Component bit depth */ + ++l_current_data; - ++l_comp; - } + ++l_comp; + } - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_cbd_size,p_manager) != l_cbd_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_cbd_size, + p_manager) != l_cbd_size) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** @@ -5833,47 +6346,56 @@ static OPJ_BOOL opj_j2k_write_cbd( opj_j2k_t *p_j2k, * @param p_header_size the size of the data contained in the CBD marker. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_read_cbd ( opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_read_cbd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_nb_comp,l_num_comp; - OPJ_UINT32 l_comp_def; - OPJ_UINT32 i; - opj_image_comp_t * l_comp = 00; + OPJ_UINT32 l_nb_comp, l_num_comp; + OPJ_UINT32 l_comp_def; + OPJ_UINT32 i; + opj_image_comp_t * l_comp = 00; - /* preconditions */ - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - l_num_comp = p_j2k->m_private_image->numcomps; + l_num_comp = p_j2k->m_private_image->numcomps; - if (p_header_size != (p_j2k->m_private_image->numcomps + 2)) { - opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); - return OPJ_FALSE; - } + if (p_header_size != (p_j2k->m_private_image->numcomps + 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); + return OPJ_FALSE; + } - opj_read_bytes(p_header_data,&l_nb_comp,2); /* Ncbd */ - p_header_data+=2; + opj_read_bytes(p_header_data, &l_nb_comp, + 2); /* Ncbd */ + p_header_data += 2; - if (l_nb_comp != l_num_comp) { - opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); - return OPJ_FALSE; - } + if (l_nb_comp != l_num_comp) { + opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); + return OPJ_FALSE; + } - l_comp = p_j2k->m_private_image->comps; - for (i=0;i<l_num_comp;++i) { - opj_read_bytes(p_header_data,&l_comp_def,1); /* Component bit depth */ - ++p_header_data; - l_comp->sgnd = (l_comp_def>>7) & 1; - l_comp->prec = (l_comp_def&0x7f) + 1; - ++l_comp; + l_comp = p_j2k->m_private_image->comps; + for (i = 0; i < l_num_comp; ++i) { + opj_read_bytes(p_header_data, &l_comp_def, + 1); /* Component bit depth */ + ++p_header_data; + l_comp->sgnd = (l_comp_def >> 7) & 1; + l_comp->prec = (l_comp_def & 0x7f) + 1; + + if (l_comp->prec > 31) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm. OpenJpeg only supports up to 31)\n", + i, l_comp->prec); + return OPJ_FALSE; } + ++l_comp; + } - return OPJ_TRUE; + return OPJ_TRUE; } /* ----------------------------------------------------------------------- */ @@ -5882,16 +6404,59 @@ static OPJ_BOOL opj_j2k_read_cbd ( opj_j2k_t *p_j2k, void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) { - if(j2k && parameters) { - j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer; - j2k->m_cp.m_specific_param.m_dec.m_reduce = parameters->cp_reduce; + if (j2k && parameters) { + j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer; + j2k->m_cp.m_specific_param.m_dec.m_reduce = parameters->cp_reduce; + j2k->dump_state = (parameters->flags & OPJ_DPARAMETERS_DUMP_FLAG); #ifdef USE_JPWL - j2k->m_cp.correct = parameters->jpwl_correct; - j2k->m_cp.exp_comps = parameters->jpwl_exp_comps; - j2k->m_cp.max_tiles = parameters->jpwl_max_tiles; + j2k->m_cp.correct = parameters->jpwl_correct; + j2k->m_cp.exp_comps = parameters->jpwl_exp_comps; + j2k->m_cp.max_tiles = parameters->jpwl_max_tiles; #endif /* USE_JPWL */ + } +} + +OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads) +{ + if (opj_has_thread_support()) { + opj_thread_pool_destroy(j2k->m_tp); + j2k->m_tp = NULL; + if (num_threads <= (OPJ_UINT32)INT_MAX) { + j2k->m_tp = opj_thread_pool_create((int)num_threads); + } + if (j2k->m_tp == NULL) { + j2k->m_tp = opj_thread_pool_create(0); + return OPJ_FALSE; } + return OPJ_TRUE; + } + return OPJ_FALSE; +} + +static int opj_j2k_get_default_thread_count() +{ + const char* num_threads_str = getenv("OPJ_NUM_THREADS"); + int num_cpus; + int num_threads; + + if (num_threads_str == NULL || !opj_has_thread_support()) { + return 0; + } + num_cpus = opj_get_num_cpus(); + if (strcmp(num_threads_str, "ALL_CPUS") == 0) { + return num_cpus; + } + if (num_cpus == 0) { + num_cpus = 32; + } + num_threads = atoi(num_threads_str); + if (num_threads < 0) { + num_threads = 0; + } else if (num_threads > 2 * num_cpus) { + num_threads = 2 * num_cpus; + } + return num_threads; } /* ----------------------------------------------------------------------- */ @@ -5900,50 +6465,62 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) opj_j2k_t* opj_j2k_create_compress(void) { - opj_j2k_t *l_j2k = (opj_j2k_t*) opj_calloc(1,sizeof(opj_j2k_t)); - if (!l_j2k) { - return NULL; - } + opj_j2k_t *l_j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); + if (!l_j2k) { + return NULL; + } - l_j2k->m_is_decoder = 0; - l_j2k->m_cp.m_is_decoder = 0; + l_j2k->m_is_decoder = 0; + l_j2k->m_cp.m_is_decoder = 0; - l_j2k->m_specific_param.m_encoder.m_header_tile_data = (OPJ_BYTE *) opj_malloc(OPJ_J2K_DEFAULT_HEADER_SIZE); - if (! l_j2k->m_specific_param.m_encoder.m_header_tile_data) { - opj_j2k_destroy(l_j2k); - return NULL; - } + l_j2k->m_specific_param.m_encoder.m_header_tile_data = (OPJ_BYTE *) opj_malloc( + OPJ_J2K_DEFAULT_HEADER_SIZE); + if (! l_j2k->m_specific_param.m_encoder.m_header_tile_data) { + opj_j2k_destroy(l_j2k); + return NULL; + } - l_j2k->m_specific_param.m_encoder.m_header_tile_data_size = OPJ_J2K_DEFAULT_HEADER_SIZE; + l_j2k->m_specific_param.m_encoder.m_header_tile_data_size = + OPJ_J2K_DEFAULT_HEADER_SIZE; - /* validation list creation*/ - l_j2k->m_validation_list = opj_procedure_list_create(); - if (! l_j2k->m_validation_list) { - opj_j2k_destroy(l_j2k); - return NULL; - } + /* validation list creation*/ + l_j2k->m_validation_list = opj_procedure_list_create(); + if (! l_j2k->m_validation_list) { + opj_j2k_destroy(l_j2k); + return NULL; + } - /* execution list creation*/ - l_j2k->m_procedure_list = opj_procedure_list_create(); - if (! l_j2k->m_procedure_list) { - opj_j2k_destroy(l_j2k); - return NULL; - } + /* execution list creation*/ + l_j2k->m_procedure_list = opj_procedure_list_create(); + if (! l_j2k->m_procedure_list) { + opj_j2k_destroy(l_j2k); + return NULL; + } + + l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count()); + if (!l_j2k->m_tp) { + l_j2k->m_tp = opj_thread_pool_create(0); + } + if (!l_j2k->m_tp) { + opj_j2k_destroy(l_j2k); + return NULL; + } - return l_j2k; + return l_j2k; } -static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres){ +static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres) +{ POC[0].tile = 1; POC[0].resno0 = 0; POC[0].compno0 = 0; POC[0].layno1 = 1; - POC[0].resno1 = (OPJ_UINT32)(numres-1); + POC[0].resno1 = (OPJ_UINT32)(numres - 1); POC[0].compno1 = 3; POC[0].prg1 = OPJ_CPRL; POC[1].tile = 1; - POC[1].resno0 = (OPJ_UINT32)(numres-1); + POC[1].resno0 = (OPJ_UINT32)(numres - 1); POC[1].compno0 = 0; POC[1].layno1 = 1; POC[1].resno1 = (OPJ_UINT32)numres; @@ -5952,15 +6529,16 @@ static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres){ return 2; } -static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_image_t *image, opj_event_mgr_t *p_manager) +static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, + opj_image_t *image, opj_event_mgr_t *p_manager) { /* Configure cinema parameters */ int i; /* No tiling */ parameters->tile_size_on = OPJ_FALSE; - parameters->cp_tdx=1; - parameters->cp_tdy=1; + parameters->cp_tdx = 1; + parameters->cp_tdy = 1; /* One tile part for each component */ parameters->tp_flag = 'C'; @@ -5990,43 +6568,44 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_ima parameters->irreversible = 1; /* Number of layers */ - if (parameters->tcp_numlayers > 1){ + if (parameters->tcp_numlayers > 1) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" - "1 single quality layer" - "-> Number of layers forced to 1 (rather than %d)\n" - "-> Rate of the last layer (%3.1f) will be used", - parameters->tcp_numlayers, parameters->tcp_rates[parameters->tcp_numlayers-1]); - parameters->tcp_rates[0] = parameters->tcp_rates[parameters->tcp_numlayers-1]; + "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" + "1 single quality layer" + "-> Number of layers forced to 1 (rather than %d)\n" + "-> Rate of the last layer (%3.1f) will be used", + parameters->tcp_numlayers, + parameters->tcp_rates[parameters->tcp_numlayers - 1]); + parameters->tcp_rates[0] = parameters->tcp_rates[parameters->tcp_numlayers - 1]; parameters->tcp_numlayers = 1; } /* Resolution levels */ - switch (parameters->rsiz){ + switch (parameters->rsiz) { case OPJ_PROFILE_CINEMA_2K: - if(parameters->numresolution > 6){ + if (parameters->numresolution > 6) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-3 (2k dc profile) requires:\n" - "Number of decomposition levels <= 5\n" - "-> Number of decomposition levels forced to 5 (rather than %d)\n", - parameters->numresolution+1); + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "Number of decomposition levels <= 5\n" + "-> Number of decomposition levels forced to 5 (rather than %d)\n", + parameters->numresolution + 1); parameters->numresolution = 6; } break; case OPJ_PROFILE_CINEMA_4K: - if(parameters->numresolution < 2){ + if (parameters->numresolution < 2) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-4 (4k dc profile) requires:\n" - "Number of decomposition levels >= 1 && <= 6\n" - "-> Number of decomposition levels forced to 1 (rather than %d)\n", - parameters->numresolution+1); + "JPEG 2000 Profile-4 (4k dc profile) requires:\n" + "Number of decomposition levels >= 1 && <= 6\n" + "-> Number of decomposition levels forced to 1 (rather than %d)\n", + parameters->numresolution + 1); parameters->numresolution = 1; - }else if(parameters->numresolution > 7){ + } else if (parameters->numresolution > 7) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-4 (4k dc profile) requires:\n" - "Number of decomposition levels >= 1 && <= 6\n" - "-> Number of decomposition levels forced to 6 (rather than %d)\n", - parameters->numresolution+1); + "JPEG 2000 Profile-4 (4k dc profile) requires:\n" + "Number of decomposition levels >= 1 && <= 6\n" + "-> Number of decomposition levels forced to 6 (rather than %d)\n", + parameters->numresolution + 1); parameters->numresolution = 7; } break; @@ -6036,10 +6615,16 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_ima /* Precincts */ parameters->csty |= 0x01; - parameters->res_spec = parameters->numresolution-1; - for (i = 0; i<parameters->res_spec; i++) { - parameters->prcw_init[i] = 256; - parameters->prch_init[i] = 256; + if (parameters->numresolution == 1) { + parameters->res_spec = 1; + parameters->prcw_init[0] = 128; + parameters->prch_init[0] = 128; + } else { + parameters->res_spec = parameters->numresolution - 1; + for (i = 0; i < parameters->res_spec; i++) { + parameters->prcw_init[i] = 256; + parameters->prch_init[i] = 256; + } } /* The progression order shall be CPRL */ @@ -6047,7 +6632,8 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_ima /* Progression order changes for 4K, disallowed for 2K */ if (parameters->rsiz == OPJ_PROFILE_CINEMA_4K) { - parameters->numpocs = (OPJ_UINT32)opj_j2k_initialise_4K_poc(parameters->POC,parameters->numresolution); + parameters->numpocs = (OPJ_UINT32)opj_j2k_initialise_4K_poc(parameters->POC, + parameters->numresolution); } else { parameters->numpocs = 0; } @@ -6084,63 +6670,66 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_ima parameters->max_comp_size = OPJ_CINEMA_24_COMP; } - parameters->tcp_rates[0] = (OPJ_FLOAT32) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)/ - (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx * image->comps[0].dy); + parameters->tcp_rates[0] = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx * + image->comps[0].dy); } -static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, opj_event_mgr_t *p_manager) +static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, + opj_event_mgr_t *p_manager) { OPJ_UINT32 i; /* Number of components */ - if (image->numcomps != 3){ + if (image->numcomps != 3) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-3 (2k dc profile) requires:\n" - "3 components" - "-> Number of components of input image (%d) is not compliant\n" - "-> Non-profile-3 codestream will be generated\n", - image->numcomps); + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "3 components" + "-> Number of components of input image (%d) is not compliant\n" + "-> Non-profile-3 codestream will be generated\n", + image->numcomps); return OPJ_FALSE; } /* Bitdepth */ for (i = 0; i < image->numcomps; i++) { - if ((image->comps[i].bpp != 12) | (image->comps[i].sgnd)){ + if ((image->comps[i].bpp != 12) | (image->comps[i].sgnd)) { char signed_str[] = "signed"; char unsigned_str[] = "unsigned"; - char *tmp_str = image->comps[i].sgnd?signed_str:unsigned_str; + char *tmp_str = image->comps[i].sgnd ? signed_str : unsigned_str; opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-3 (2k dc profile) requires:\n" - "Precision of each component shall be 12 bits unsigned" - "-> At least component %d of input image (%d bits, %s) is not compliant\n" - "-> Non-profile-3 codestream will be generated\n", - i,image->comps[i].bpp, tmp_str); + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "Precision of each component shall be 12 bits unsigned" + "-> At least component %d of input image (%d bits, %s) is not compliant\n" + "-> Non-profile-3 codestream will be generated\n", + i, image->comps[i].bpp, tmp_str); return OPJ_FALSE; } } /* Image size */ - switch (rsiz){ + switch (rsiz) { case OPJ_PROFILE_CINEMA_2K: - if (((image->comps[0].w > 2048) | (image->comps[0].h > 1080))){ + if (((image->comps[0].w > 2048) | (image->comps[0].h > 1080))) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-3 (2k dc profile) requires:\n" - "width <= 2048 and height <= 1080\n" - "-> Input image size %d x %d is not compliant\n" - "-> Non-profile-3 codestream will be generated\n", - image->comps[0].w,image->comps[0].h); + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "width <= 2048 and height <= 1080\n" + "-> Input image size %d x %d is not compliant\n" + "-> Non-profile-3 codestream will be generated\n", + image->comps[0].w, image->comps[0].h); return OPJ_FALSE; } break; case OPJ_PROFILE_CINEMA_4K: - if (((image->comps[0].w > 4096) | (image->comps[0].h > 2160))){ + if (((image->comps[0].w > 4096) | (image->comps[0].h > 2160))) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Profile-4 (4k dc profile) requires:\n" - "width <= 4096 and height <= 2160\n" - "-> Image size %d x %d is not compliant\n" - "-> Non-profile-4 codestream will be generated\n", - image->comps[0].w,image->comps[0].h); + "JPEG 2000 Profile-4 (4k dc profile) requires:\n" + "width <= 4096 and height <= 2160\n" + "-> Image size %d x %d is not compliant\n" + "-> Non-profile-4 codestream will be generated\n", + image->comps[0].w, image->comps[0].h); return OPJ_FALSE; } break; @@ -6151,573 +6740,720 @@ static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, return OPJ_TRUE; } -OPJ_BOOL opj_j2k_setup_encoder( opj_j2k_t *p_j2k, - opj_cparameters_t *parameters, - opj_image_t *image, - opj_event_mgr_t * p_manager) +OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 i, j, tileno, numpocs_tile; - opj_cp_t *cp = 00; + OPJ_UINT32 i, j, tileno, numpocs_tile; + opj_cp_t *cp = 00; + OPJ_UINT32 cblkw, cblkh; - if(!p_j2k || !parameters || ! image) { - return OPJ_FALSE; - } + if (!p_j2k || !parameters || ! image) { + return OPJ_FALSE; + } - if ((parameters->numresolution <= 0) || (parameters->numresolution > OPJ_J2K_MAXRLVLS)) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid number of resolutions : %d not in range [1,%d]\n", parameters->numresolution, OPJ_J2K_MAXRLVLS); - return OPJ_FALSE; - } + if ((parameters->numresolution <= 0) || + (parameters->numresolution > OPJ_J2K_MAXRLVLS)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of resolutions : %d not in range [1,%d]\n", + parameters->numresolution, OPJ_J2K_MAXRLVLS); + return OPJ_FALSE; + } + + if (parameters->cblockw_init < 4 || parameters->cblockw_init > 1024) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init: %d not a power of 2 in range [4,1024]\n", + parameters->cblockw_init); + return OPJ_FALSE; + } + if (parameters->cblockh_init < 4 || parameters->cblockh_init > 1024) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockh_init: %d not a power of 2 not in range [4,1024]\n", + parameters->cblockh_init); + return OPJ_FALSE; + } + if (parameters->cblockw_init * parameters->cblockh_init > 4096) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init * cblockh_init: should be <= 4096\n"); + return OPJ_FALSE; + } + cblkw = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockw_init); + cblkh = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockh_init); + if (parameters->cblockw_init != (1 << cblkw)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init: %d not a power of 2 in range [4,1024]\n", + parameters->cblockw_init); + return OPJ_FALSE; + } + if (parameters->cblockh_init != (1 << cblkh)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init: %d not a power of 2 in range [4,1024]\n", + parameters->cblockh_init); + return OPJ_FALSE; + } - /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ - cp = &(p_j2k->m_cp); + /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ + cp = &(p_j2k->m_cp); + + /* set default values for cp */ + cp->tw = 1; + cp->th = 1; + + /* FIXME ADE: to be removed once deprecated cp_cinema and cp_rsiz have been removed */ + if (parameters->rsiz == + OPJ_PROFILE_NONE) { /* consider deprecated fields only if RSIZ has not been set */ + OPJ_BOOL deprecated_used = OPJ_FALSE; + switch (parameters->cp_cinema) { + case OPJ_CINEMA2K_24: + parameters->rsiz = OPJ_PROFILE_CINEMA_2K; + parameters->max_cs_size = OPJ_CINEMA_24_CS; + parameters->max_comp_size = OPJ_CINEMA_24_COMP; + deprecated_used = OPJ_TRUE; + break; + case OPJ_CINEMA2K_48: + parameters->rsiz = OPJ_PROFILE_CINEMA_2K; + parameters->max_cs_size = OPJ_CINEMA_48_CS; + parameters->max_comp_size = OPJ_CINEMA_48_COMP; + deprecated_used = OPJ_TRUE; + break; + case OPJ_CINEMA4K_24: + parameters->rsiz = OPJ_PROFILE_CINEMA_4K; + parameters->max_cs_size = OPJ_CINEMA_24_CS; + parameters->max_comp_size = OPJ_CINEMA_24_COMP; + deprecated_used = OPJ_TRUE; + break; + case OPJ_OFF: + default: + break; + } + switch (parameters->cp_rsiz) { + case OPJ_CINEMA2K: + parameters->rsiz = OPJ_PROFILE_CINEMA_2K; + deprecated_used = OPJ_TRUE; + break; + case OPJ_CINEMA4K: + parameters->rsiz = OPJ_PROFILE_CINEMA_4K; + deprecated_used = OPJ_TRUE; + break; + case OPJ_MCT: + parameters->rsiz = OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT; + deprecated_used = OPJ_TRUE; + case OPJ_STD_RSIZ: + default: + break; + } + if (deprecated_used) { + opj_event_msg(p_manager, EVT_WARNING, + "Deprecated fields cp_cinema or cp_rsiz are used\n" + "Please consider using only the rsiz field\n" + "See openjpeg.h documentation for more details\n"); + } + } - /* set default values for cp */ - cp->tw = 1; - cp->th = 1; + /* If no explicit layers are provided, use lossless settings */ + if (parameters->tcp_numlayers == 0) { + parameters->tcp_numlayers = 1; + parameters->cp_disto_alloc = 1; + parameters->tcp_rates[0] = 0; + } - /* FIXME ADE: to be removed once deprecated cp_cinema and cp_rsiz have been removed */ - if (parameters->rsiz == OPJ_PROFILE_NONE) { /* consider deprecated fields only if RSIZ has not been set */ - OPJ_BOOL deprecated_used = OPJ_FALSE; - switch (parameters->cp_cinema){ - case OPJ_CINEMA2K_24: - parameters->rsiz = OPJ_PROFILE_CINEMA_2K; - parameters->max_cs_size = OPJ_CINEMA_24_CS; - parameters->max_comp_size = OPJ_CINEMA_24_COMP; - deprecated_used = OPJ_TRUE; - break; - case OPJ_CINEMA2K_48: - parameters->rsiz = OPJ_PROFILE_CINEMA_2K; - parameters->max_cs_size = OPJ_CINEMA_48_CS; - parameters->max_comp_size = OPJ_CINEMA_48_COMP; - deprecated_used = OPJ_TRUE; - break; - case OPJ_CINEMA4K_24: - parameters->rsiz = OPJ_PROFILE_CINEMA_4K; - parameters->max_cs_size = OPJ_CINEMA_24_CS; - parameters->max_comp_size = OPJ_CINEMA_24_COMP; - deprecated_used = OPJ_TRUE; - break; - case OPJ_OFF: - default: - break; + if (parameters->cp_disto_alloc) { + /* Emit warnings if tcp_rates are not decreasing */ + for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { + OPJ_FLOAT32 rate_i_corr = parameters->tcp_rates[i]; + OPJ_FLOAT32 rate_i_m_1_corr = parameters->tcp_rates[i - 1]; + if (rate_i_corr <= 1.0) { + rate_i_corr = 1.0; } - switch (parameters->cp_rsiz){ - case OPJ_CINEMA2K: - parameters->rsiz = OPJ_PROFILE_CINEMA_2K; - deprecated_used = OPJ_TRUE; - break; - case OPJ_CINEMA4K: - parameters->rsiz = OPJ_PROFILE_CINEMA_4K; - deprecated_used = OPJ_TRUE; - break; - case OPJ_MCT: - parameters->rsiz = OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT; - deprecated_used = OPJ_TRUE; - case OPJ_STD_RSIZ: - default: - break; + if (rate_i_m_1_corr <= 1.0) { + rate_i_m_1_corr = 1.0; } - if (deprecated_used) { + if (rate_i_corr >= rate_i_m_1_corr) { + if (rate_i_corr != parameters->tcp_rates[i] && + rate_i_m_1_corr != parameters->tcp_rates[i - 1]) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser " + "than tcp_rates[%d]=%f (corrected as %f)\n", + i, parameters->tcp_rates[i], rate_i_corr, + i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr); + } else if (rate_i_corr != parameters->tcp_rates[i]) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser " + "than tcp_rates[%d]=%f\n", + i, parameters->tcp_rates[i], rate_i_corr, + i - 1, parameters->tcp_rates[i - 1]); + } else if (rate_i_m_1_corr != parameters->tcp_rates[i - 1]) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f should be strictly lesser " + "than tcp_rates[%d]=%f (corrected as %f)\n", + i, parameters->tcp_rates[i], + i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr); + } else { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f should be strictly lesser " + "than tcp_rates[%d]=%f\n", + i, parameters->tcp_rates[i], + i - 1, parameters->tcp_rates[i - 1]); + } + } + } + } else if (parameters->cp_fixed_quality) { + /* Emit warnings if tcp_distoratio are not increasing */ + for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { + if (parameters->tcp_distoratio[i] < parameters->tcp_distoratio[i - 1] && + !(i == (OPJ_UINT32)parameters->tcp_numlayers - 1 && + parameters->tcp_distoratio[i] == 0)) { opj_event_msg(p_manager, EVT_WARNING, - "Deprecated fields cp_cinema or cp_rsiz are used\n" - "Please consider using only the rsiz field\n" - "See openjpeg.h documentation for more details\n"); + "tcp_distoratio[%d]=%f should be strictly greater " + "than tcp_distoratio[%d]=%f\n", + i, parameters->tcp_distoratio[i], i - 1, + parameters->tcp_distoratio[i - 1]); } } + } - /* see if max_codestream_size does limit input rate */ - if (parameters->max_cs_size <= 0) { - if (parameters->tcp_rates[parameters->tcp_numlayers-1] > 0) { - OPJ_FLOAT32 temp_size; - temp_size =(OPJ_FLOAT32)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)/ - (parameters->tcp_rates[parameters->tcp_numlayers-1] * 8 * (OPJ_FLOAT32)image->comps[0].dx * (OPJ_FLOAT32)image->comps[0].dy); - parameters->max_cs_size = (int) floor(temp_size); + /* see if max_codestream_size does limit input rate */ + if (parameters->max_cs_size <= 0) { + if (parameters->tcp_rates[parameters->tcp_numlayers - 1] > 0) { + OPJ_FLOAT32 temp_size; + temp_size = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + ((double)parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 * + image->comps[0].dx * image->comps[0].dy)); + if (temp_size > INT_MAX) { + parameters->max_cs_size = INT_MAX; } else { - parameters->max_cs_size = 0; + parameters->max_cs_size = (int) floor(temp_size); } } else { - OPJ_FLOAT32 temp_rate; - OPJ_BOOL cap = OPJ_FALSE; - temp_rate = (OPJ_FLOAT32) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)/ - (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx * image->comps[0].dy); - for (i = 0; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { - if (parameters->tcp_rates[i] < temp_rate) { - parameters->tcp_rates[i] = temp_rate; - cap = OPJ_TRUE; - } - } - if (cap) { - opj_event_msg(p_manager, EVT_WARNING, - "The desired maximum codestream size has limited\n" - "at least one of the desired quality layers\n"); + parameters->max_cs_size = 0; + } + } else { + OPJ_FLOAT32 temp_rate; + OPJ_BOOL cap = OPJ_FALSE; + temp_rate = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + (((double)parameters->max_cs_size) * 8 * image->comps[0].dx * + image->comps[0].dy)); + for (i = 0; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { + if (parameters->tcp_rates[i] < temp_rate) { + parameters->tcp_rates[i] = temp_rate; + cap = OPJ_TRUE; } } + if (cap) { + opj_event_msg(p_manager, EVT_WARNING, + "The desired maximum codestream size has limited\n" + "at least one of the desired quality layers\n"); + } + } - /* Manage profiles and applications and set RSIZ */ - /* set cinema parameters if required */ - if (OPJ_IS_CINEMA(parameters->rsiz)){ - if ((parameters->rsiz == OPJ_PROFILE_CINEMA_S2K) - || (parameters->rsiz == OPJ_PROFILE_CINEMA_S4K)){ - opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Scalable Digital Cinema profiles not yet supported\n"); - parameters->rsiz = OPJ_PROFILE_NONE; - } else { - opj_j2k_set_cinema_parameters(parameters,image,p_manager); - if (!opj_j2k_is_cinema_compliant(image,parameters->rsiz,p_manager)) { - parameters->rsiz = OPJ_PROFILE_NONE; - } - } - } else if (OPJ_IS_STORAGE(parameters->rsiz)) { + /* Manage profiles and applications and set RSIZ */ + /* set cinema parameters if required */ + if (OPJ_IS_CINEMA(parameters->rsiz)) { + if ((parameters->rsiz == OPJ_PROFILE_CINEMA_S2K) + || (parameters->rsiz == OPJ_PROFILE_CINEMA_S4K)) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Long Term Storage profile not yet supported\n"); + "JPEG 2000 Scalable Digital Cinema profiles not yet supported\n"); parameters->rsiz = OPJ_PROFILE_NONE; - } else if (OPJ_IS_BROADCAST(parameters->rsiz)) { + } else { + opj_j2k_set_cinema_parameters(parameters, image, p_manager); + if (!opj_j2k_is_cinema_compliant(image, parameters->rsiz, p_manager)) { + parameters->rsiz = OPJ_PROFILE_NONE; + } + } + } else if (OPJ_IS_STORAGE(parameters->rsiz)) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Long Term Storage profile not yet supported\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else if (OPJ_IS_BROADCAST(parameters->rsiz)) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Broadcast profiles not yet supported\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else if (OPJ_IS_IMF(parameters->rsiz)) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 IMF profiles not yet supported\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else if (OPJ_IS_PART2(parameters->rsiz)) { + if (parameters->rsiz == ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_NONE))) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Broadcast profiles not yet supported\n"); + "JPEG 2000 Part-2 profile defined\n" + "but no Part-2 extension enabled.\n" + "Profile set to NONE.\n"); parameters->rsiz = OPJ_PROFILE_NONE; - } else if (OPJ_IS_IMF(parameters->rsiz)) { + } else if (parameters->rsiz != ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_MCT))) { opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 IMF profiles not yet supported\n"); + "Unsupported Part-2 extension enabled\n" + "Profile set to NONE.\n"); parameters->rsiz = OPJ_PROFILE_NONE; - } else if (OPJ_IS_PART2(parameters->rsiz)) { - if (parameters->rsiz == ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_NONE))) { - opj_event_msg(p_manager, EVT_WARNING, - "JPEG 2000 Part-2 profile defined\n" - "but no Part-2 extension enabled.\n" - "Profile set to NONE.\n"); - parameters->rsiz = OPJ_PROFILE_NONE; - } else if (parameters->rsiz != ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_MCT))) { - opj_event_msg(p_manager, EVT_WARNING, - "Unsupported Part-2 extension enabled\n" - "Profile set to NONE.\n"); - parameters->rsiz = OPJ_PROFILE_NONE; - } } + } - /* - copy user encoding parameters - */ - cp->m_specific_param.m_enc.m_max_comp_size = (OPJ_UINT32)parameters->max_comp_size; - cp->rsiz = parameters->rsiz; - cp->m_specific_param.m_enc.m_disto_alloc = (OPJ_UINT32)parameters->cp_disto_alloc & 1u; - cp->m_specific_param.m_enc.m_fixed_alloc = (OPJ_UINT32)parameters->cp_fixed_alloc & 1u; - cp->m_specific_param.m_enc.m_fixed_quality = (OPJ_UINT32)parameters->cp_fixed_quality & 1u; - - /* mod fixed_quality */ - if (parameters->cp_fixed_alloc && parameters->cp_matrice) { - size_t array_size = (size_t)parameters->tcp_numlayers * (size_t)parameters->numresolution * 3 * sizeof(OPJ_INT32); - cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); - if (!cp->m_specific_param.m_enc.m_matrice) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate copy of user encoding parameters matrix \n"); - return OPJ_FALSE; - } - memcpy(cp->m_specific_param.m_enc.m_matrice, parameters->cp_matrice, array_size); - } - - /* tiles */ - cp->tdx = (OPJ_UINT32)parameters->cp_tdx; - cp->tdy = (OPJ_UINT32)parameters->cp_tdy; - - /* tile offset */ - cp->tx0 = (OPJ_UINT32)parameters->cp_tx0; - cp->ty0 = (OPJ_UINT32)parameters->cp_ty0; - - /* comment string */ - if(parameters->cp_comment) { - cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1U); - if(!cp->comment) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate copy of comment string\n"); - return OPJ_FALSE; - } - strcpy(cp->comment, parameters->cp_comment); - } else { - /* Create default comment for codestream */ - const char comment[] = "Created by OpenJPEG version "; - const size_t clen = strlen(comment); - const char *version = opj_version(); + /* + copy user encoding parameters + */ + cp->m_specific_param.m_enc.m_max_comp_size = (OPJ_UINT32) + parameters->max_comp_size; + cp->rsiz = parameters->rsiz; + cp->m_specific_param.m_enc.m_disto_alloc = (OPJ_UINT32) + parameters->cp_disto_alloc & 1u; + cp->m_specific_param.m_enc.m_fixed_alloc = (OPJ_UINT32) + parameters->cp_fixed_alloc & 1u; + cp->m_specific_param.m_enc.m_fixed_quality = (OPJ_UINT32) + parameters->cp_fixed_quality & 1u; + + /* mod fixed_quality */ + if (parameters->cp_fixed_alloc && parameters->cp_matrice) { + size_t array_size = (size_t)parameters->tcp_numlayers * + (size_t)parameters->numresolution * 3 * sizeof(OPJ_INT32); + cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); + if (!cp->m_specific_param.m_enc.m_matrice) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate copy of user encoding parameters matrix \n"); + return OPJ_FALSE; + } + memcpy(cp->m_specific_param.m_enc.m_matrice, parameters->cp_matrice, + array_size); + } + + /* tiles */ + cp->tdx = (OPJ_UINT32)parameters->cp_tdx; + cp->tdy = (OPJ_UINT32)parameters->cp_tdy; + + /* tile offset */ + cp->tx0 = (OPJ_UINT32)parameters->cp_tx0; + cp->ty0 = (OPJ_UINT32)parameters->cp_ty0; + + /* comment string */ + if (parameters->cp_comment) { + cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1U); + if (!cp->comment) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate copy of comment string\n"); + return OPJ_FALSE; + } + strcpy(cp->comment, parameters->cp_comment); + } else { + /* Create default comment for codestream */ + const char comment[] = "Created by OpenJPEG version "; + const size_t clen = strlen(comment); + const char *version = opj_version(); - /* UniPG>> */ + /* UniPG>> */ #ifdef USE_JPWL - cp->comment = (char*)opj_malloc(clen+strlen(version)+11); - if(!cp->comment) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate comment string\n"); - return OPJ_FALSE; - } - sprintf(cp->comment,"%s%s with JPWL", comment, version); + cp->comment = (char*)opj_malloc(clen + strlen(version) + 11); + if (!cp->comment) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate comment string\n"); + return OPJ_FALSE; + } + sprintf(cp->comment, "%s%s with JPWL", comment, version); #else - cp->comment = (char*)opj_malloc(clen+strlen(version)+1); - if(!cp->comment) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate comment string\n"); - return OPJ_FALSE; - } - sprintf(cp->comment,"%s%s", comment, version); + cp->comment = (char*)opj_malloc(clen + strlen(version) + 1); + if (!cp->comment) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate comment string\n"); + return OPJ_FALSE; + } + sprintf(cp->comment, "%s%s", comment, version); #endif - /* <<UniPG */ - } + /* <<UniPG */ + } - /* - calculate other encoding parameters - */ + /* + calculate other encoding parameters + */ - if (parameters->tile_size_on) { - cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx); - cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy); - } else { - cp->tdx = image->x1 - cp->tx0; - cp->tdy = image->y1 - cp->ty0; + if (parameters->tile_size_on) { + cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy); + } else { + cp->tdx = image->x1 - cp->tx0; + cp->tdy = image->y1 - cp->ty0; + } + + if (parameters->tp_on) { + cp->m_specific_param.m_enc.m_tp_flag = (OPJ_BYTE)parameters->tp_flag; + cp->m_specific_param.m_enc.m_tp_on = 1; + } + +#ifdef USE_JPWL + /* + calculate JPWL encoding parameters + */ + + if (parameters->jpwl_epc_on) { + OPJ_INT32 i; + + /* set JPWL on */ + cp->epc_on = OPJ_TRUE; + cp->info_on = OPJ_FALSE; /* no informative technique */ + + /* set EPB on */ + if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { + cp->epb_on = OPJ_TRUE; + + cp->hprot_MH = parameters->jpwl_hprot_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i]; + cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i]; + } + /* if tile specs are not specified, copy MH specs */ + if (cp->hprot_TPH[0] == -1) { + cp->hprot_TPH_tileno[0] = 0; + cp->hprot_TPH[0] = parameters->jpwl_hprot_MH; + } + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i]; + cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i]; + cp->pprot[i] = parameters->jpwl_pprot[i]; + } } - if (parameters->tp_on) { - cp->m_specific_param.m_enc.m_tp_flag = (OPJ_BYTE)parameters->tp_flag; - cp->m_specific_param.m_enc.m_tp_on = 1; + /* set ESD writing */ + if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { + cp->esd_on = OPJ_TRUE; + + cp->sens_size = parameters->jpwl_sens_size; + cp->sens_addr = parameters->jpwl_sens_addr; + cp->sens_range = parameters->jpwl_sens_range; + + cp->sens_MH = parameters->jpwl_sens_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i]; + cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i]; + } } -#ifdef USE_JPWL - /* - calculate JPWL encoding parameters - */ + /* always set RED writing to false: we are at the encoder */ + cp->red_on = OPJ_FALSE; - if (parameters->jpwl_epc_on) { - OPJ_INT32 i; + } else { + cp->epc_on = OPJ_FALSE; + } +#endif /* USE_JPWL */ - /* set JPWL on */ - cp->epc_on = OPJ_TRUE; - cp->info_on = OPJ_FALSE; /* no informative technique */ + /* initialize the mutiple tiles */ + /* ---------------------------- */ + cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + if (!cp->tcps) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate tile coding parameters\n"); + return OPJ_FALSE; + } + if (parameters->numpocs) { + /* initialisation of POC */ + opj_j2k_check_poc_val(parameters->POC, parameters->numpocs, + (OPJ_UINT32)parameters->numresolution, image->numcomps, + (OPJ_UINT32)parameters->tcp_numlayers, p_manager); + /* TODO MSD use the return value*/ + } - /* set EPB on */ - if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { - cp->epb_on = OPJ_TRUE; + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_tcp_t *tcp = &cp->tcps[tileno]; + tcp->numlayers = (OPJ_UINT32)parameters->tcp_numlayers; - cp->hprot_MH = parameters->jpwl_hprot_MH; - for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { - cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i]; - cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i]; - } - /* if tile specs are not specified, copy MH specs */ - if (cp->hprot_TPH[0] == -1) { - cp->hprot_TPH_tileno[0] = 0; - cp->hprot_TPH[0] = parameters->jpwl_hprot_MH; - } - for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { - cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i]; - cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i]; - cp->pprot[i] = parameters->jpwl_pprot[i]; - } + for (j = 0; j < tcp->numlayers; j++) { + if (OPJ_IS_CINEMA(cp->rsiz)) { + if (cp->m_specific_param.m_enc.m_fixed_quality) { + tcp->distoratio[j] = parameters->tcp_distoratio[j]; } + tcp->rates[j] = parameters->tcp_rates[j]; + } else { + if (cp->m_specific_param.m_enc.m_fixed_quality) { /* add fixed_quality */ + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } else { + tcp->rates[j] = parameters->tcp_rates[j]; + } + } + if (!cp->m_specific_param.m_enc.m_fixed_quality && + tcp->rates[j] <= 1.0) { + tcp->rates[j] = 0.0; /* force lossless */ + } + } - /* set ESD writing */ - if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { - cp->esd_on = OPJ_TRUE; + tcp->csty = (OPJ_UINT32)parameters->csty; + tcp->prg = parameters->prog_order; + tcp->mct = (OPJ_UINT32)parameters->tcp_mct; - cp->sens_size = parameters->jpwl_sens_size; - cp->sens_addr = parameters->jpwl_sens_addr; - cp->sens_range = parameters->jpwl_sens_range; + numpocs_tile = 0; + tcp->POC = 0; - cp->sens_MH = parameters->jpwl_sens_MH; - for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { - cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i]; - cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i]; - } + if (parameters->numpocs) { + /* initialisation of POC */ + tcp->POC = 1; + for (i = 0; i < parameters->numpocs; i++) { + if (tileno + 1 == parameters->POC[i].tile) { + opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; + + tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0; + tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0; + tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1; + tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1; + tcp_poc->compno1 = parameters->POC[numpocs_tile].compno1; + tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; + tcp_poc->tile = parameters->POC[numpocs_tile].tile; + + numpocs_tile++; } + } - /* always set RED writing to false: we are at the encoder */ - cp->red_on = OPJ_FALSE; - + tcp->numpocs = numpocs_tile - 1 ; } else { - cp->epc_on = OPJ_FALSE; + tcp->numpocs = 0; } -#endif /* USE_JPWL */ - /* initialize the mutiple tiles */ - /* ---------------------------- */ - cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); - if (!cp->tcps) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate tile coding parameters\n"); - return OPJ_FALSE; + tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); + if (!tcp->tccps) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate tile component coding parameters\n"); + return OPJ_FALSE; } - if (parameters->numpocs) { - /* initialisation of POC */ - opj_j2k_check_poc_val(parameters->POC,parameters->numpocs, (OPJ_UINT32)parameters->numresolution, image->numcomps, (OPJ_UINT32)parameters->tcp_numlayers, p_manager); - /* TODO MSD use the return value*/ - } - - for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { - opj_tcp_t *tcp = &cp->tcps[tileno]; - tcp->numlayers = (OPJ_UINT32)parameters->tcp_numlayers; - - for (j = 0; j < tcp->numlayers; j++) { - if(OPJ_IS_CINEMA(cp->rsiz)){ - if (cp->m_specific_param.m_enc.m_fixed_quality) { - tcp->distoratio[j] = parameters->tcp_distoratio[j]; - } - tcp->rates[j] = parameters->tcp_rates[j]; - }else{ - if (cp->m_specific_param.m_enc.m_fixed_quality) { /* add fixed_quality */ - tcp->distoratio[j] = parameters->tcp_distoratio[j]; - } else { - tcp->rates[j] = parameters->tcp_rates[j]; - } - } - } + if (parameters->mct_data) { - tcp->csty = (OPJ_UINT32)parameters->csty; - tcp->prg = parameters->prog_order; - tcp->mct = (OPJ_UINT32)parameters->tcp_mct; - - numpocs_tile = 0; - tcp->POC = 0; - - if (parameters->numpocs) { - /* initialisation of POC */ - tcp->POC = 1; - for (i = 0; i < parameters->numpocs; i++) { - if (tileno + 1 == parameters->POC[i].tile ) { - opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; - - tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0; - tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0; - tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1; - tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1; - tcp_poc->compno1 = parameters->POC[numpocs_tile].compno1; - tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; - tcp_poc->tile = parameters->POC[numpocs_tile].tile; - - numpocs_tile++; - } - } + OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * (OPJ_UINT32)sizeof( + OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpBuf = (OPJ_FLOAT32*)opj_malloc(lMctSize); + OPJ_INT32 * l_dc_shift = (OPJ_INT32 *)((OPJ_BYTE *) parameters->mct_data + + lMctSize); + + if (!lTmpBuf) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate temp buffer\n"); + return OPJ_FALSE; + } + + tcp->mct = 2; + tcp->m_mct_coding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); + if (! tcp->m_mct_coding_matrix) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate encoder MCT coding matrix \n"); + return OPJ_FALSE; + } + memcpy(tcp->m_mct_coding_matrix, parameters->mct_data, lMctSize); + memcpy(lTmpBuf, parameters->mct_data, lMctSize); + + tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); + if (! tcp->m_mct_decoding_matrix) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate encoder MCT decoding matrix \n"); + return OPJ_FALSE; + } + if (opj_matrix_inversion_f(lTmpBuf, (tcp->m_mct_decoding_matrix), + image->numcomps) == OPJ_FALSE) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Failed to inverse encoder MCT decoding matrix \n"); + return OPJ_FALSE; + } + + tcp->mct_norms = (OPJ_FLOAT64*) + opj_malloc(image->numcomps * sizeof(OPJ_FLOAT64)); + if (! tcp->mct_norms) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate encoder MCT norms \n"); + return OPJ_FALSE; + } + opj_calculate_norms(tcp->mct_norms, image->numcomps, + tcp->m_mct_decoding_matrix); + opj_free(lTmpBuf); - tcp->numpocs = numpocs_tile -1 ; - }else{ - tcp->numpocs = 0; + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->m_dc_level_shift = l_dc_shift[i]; + } + + if (opj_j2k_setup_mct_encoding(tcp, image) == OPJ_FALSE) { + /* free will be handled by opj_j2k_destroy */ + opj_event_msg(p_manager, EVT_ERROR, "Failed to setup j2k mct encoding\n"); + return OPJ_FALSE; + } + } else { + if (tcp->mct == 1 && image->numcomps >= 3) { /* RGB->YCC MCT is enabled */ + if ((image->comps[0].dx != image->comps[1].dx) || + (image->comps[0].dx != image->comps[2].dx) || + (image->comps[0].dy != image->comps[1].dy) || + (image->comps[0].dy != image->comps[2].dy)) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot perform MCT on components with different sizes. Disabling MCT.\n"); + tcp->mct = 0; } + } + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + opj_image_comp_t * l_comp = &(image->comps[i]); - tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); - if (!tcp->tccps) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate tile component coding parameters\n"); - return OPJ_FALSE; + if (! l_comp->sgnd) { + tccp->m_dc_level_shift = 1 << (l_comp->prec - 1); } - if (parameters->mct_data) { - - OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - OPJ_FLOAT32 * lTmpBuf = (OPJ_FLOAT32*)opj_malloc(lMctSize); - OPJ_INT32 * l_dc_shift = (OPJ_INT32 *) ((OPJ_BYTE *) parameters->mct_data + lMctSize); - - if (!lTmpBuf) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate temp buffer\n"); - return OPJ_FALSE; - } + } + } - tcp->mct = 2; - tcp->m_mct_coding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); - if (! tcp->m_mct_coding_matrix) { - opj_free(lTmpBuf); - lTmpBuf = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate encoder MCT coding matrix \n"); - return OPJ_FALSE; - } - memcpy(tcp->m_mct_coding_matrix,parameters->mct_data,lMctSize); - memcpy(lTmpBuf,parameters->mct_data,lMctSize); - - tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); - if (! tcp->m_mct_decoding_matrix) { - opj_free(lTmpBuf); - lTmpBuf = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate encoder MCT decoding matrix \n"); - return OPJ_FALSE; - } - if(opj_matrix_inversion_f(lTmpBuf,(tcp->m_mct_decoding_matrix),image->numcomps) == OPJ_FALSE) { - opj_free(lTmpBuf); - lTmpBuf = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Failed to inverse encoder MCT decoding matrix \n"); - return OPJ_FALSE; - } - - tcp->mct_norms = (OPJ_FLOAT64*) - opj_malloc(image->numcomps * sizeof(OPJ_FLOAT64)); - if (! tcp->mct_norms) { - opj_free(lTmpBuf); - lTmpBuf = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to allocate encoder MCT norms \n"); - return OPJ_FALSE; - } - opj_calculate_norms(tcp->mct_norms,image->numcomps,tcp->m_mct_decoding_matrix); - opj_free(lTmpBuf); + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; - for (i = 0; i < image->numcomps; i++) { - opj_tccp_t *tccp = &tcp->tccps[i]; - tccp->m_dc_level_shift = l_dc_shift[i]; - } + tccp->csty = parameters->csty & + 0x01; /* 0 => one precinct || 1 => custom precinct */ + tccp->numresolutions = (OPJ_UINT32)parameters->numresolution; + tccp->cblkw = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockw_init); + tccp->cblkh = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockh_init); + tccp->cblksty = (OPJ_UINT32)parameters->mode; + tccp->qmfbid = parameters->irreversible ? 0 : 1; + tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : + J2K_CCP_QNTSTY_NOQNT; + tccp->numgbits = 2; - if (opj_j2k_setup_mct_encoding(tcp,image) == OPJ_FALSE) { - /* free will be handled by opj_j2k_destroy */ - opj_event_msg(p_manager, EVT_ERROR, "Failed to setup j2k mct encoding\n"); - return OPJ_FALSE; - } - } - else { - if(tcp->mct==1 && image->numcomps >= 3) { /* RGB->YCC MCT is enabled */ - if ((image->comps[0].dx != image->comps[1].dx) || - (image->comps[0].dx != image->comps[2].dx) || - (image->comps[0].dy != image->comps[1].dy) || - (image->comps[0].dy != image->comps[2].dy)) { - opj_event_msg(p_manager, EVT_WARNING, "Cannot perform MCT on components with different sizes. Disabling MCT.\n"); - tcp->mct = 0; + if ((OPJ_INT32)i == parameters->roi_compno) { + tccp->roishift = parameters->roi_shift; + } else { + tccp->roishift = 0; + } + + if (parameters->csty & J2K_CCP_CSTY_PRT) { + OPJ_INT32 p = 0, it_res; + assert(tccp->numresolutions > 0); + for (it_res = (OPJ_INT32)tccp->numresolutions - 1; it_res >= 0; it_res--) { + if (p < parameters->res_spec) { + + if (parameters->prcw_init[p] < 1) { + tccp->prcw[it_res] = 1; + } else { + tccp->prcw[it_res] = (OPJ_UINT32)opj_int_floorlog2(parameters->prcw_init[p]); } - } - for (i = 0; i < image->numcomps; i++) { - opj_tccp_t *tccp = &tcp->tccps[i]; - opj_image_comp_t * l_comp = &(image->comps[i]); - if (! l_comp->sgnd) { - tccp->m_dc_level_shift = 1 << (l_comp->prec - 1); - } + if (parameters->prch_init[p] < 1) { + tccp->prch[it_res] = 1; + } else { + tccp->prch[it_res] = (OPJ_UINT32)opj_int_floorlog2(parameters->prch_init[p]); } - } - for (i = 0; i < image->numcomps; i++) { - opj_tccp_t *tccp = &tcp->tccps[i]; + } else { + OPJ_INT32 res_spec = parameters->res_spec; + OPJ_INT32 size_prcw = 0; + OPJ_INT32 size_prch = 0; - tccp->csty = parameters->csty & 0x01; /* 0 => one precinct || 1 => custom precinct */ - tccp->numresolutions = (OPJ_UINT32)parameters->numresolution; - tccp->cblkw = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockw_init); - tccp->cblkh = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockh_init); - tccp->cblksty = (OPJ_UINT32)parameters->mode; - tccp->qmfbid = parameters->irreversible ? 0 : 1; - tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT; - tccp->numgbits = 2; + assert(res_spec > 0); /* issue 189 */ + size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); + size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); - if ((OPJ_INT32)i == parameters->roi_compno) { - tccp->roishift = parameters->roi_shift; + + if (size_prcw < 1) { + tccp->prcw[it_res] = 1; } else { - tccp->roishift = 0; + tccp->prcw[it_res] = (OPJ_UINT32)opj_int_floorlog2(size_prcw); } - if (parameters->csty & J2K_CCP_CSTY_PRT) { - OPJ_INT32 p = 0, it_res; - assert( tccp->numresolutions > 0 ); - for (it_res = (OPJ_INT32)tccp->numresolutions - 1; it_res >= 0; it_res--) { - if (p < parameters->res_spec) { - - if (parameters->prcw_init[p] < 1) { - tccp->prcw[it_res] = 1; - } else { - tccp->prcw[it_res] = (OPJ_UINT32)opj_int_floorlog2(parameters->prcw_init[p]); - } - - if (parameters->prch_init[p] < 1) { - tccp->prch[it_res] = 1; - }else { - tccp->prch[it_res] = (OPJ_UINT32)opj_int_floorlog2(parameters->prch_init[p]); - } - - } else { - OPJ_INT32 res_spec = parameters->res_spec; - OPJ_INT32 size_prcw = 0; - OPJ_INT32 size_prch = 0; - - assert(res_spec>0); /* issue 189 */ - size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); - size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); - - - if (size_prcw < 1) { - tccp->prcw[it_res] = 1; - } else { - tccp->prcw[it_res] = (OPJ_UINT32)opj_int_floorlog2(size_prcw); - } - - if (size_prch < 1) { - tccp->prch[it_res] = 1; - } else { - tccp->prch[it_res] = (OPJ_UINT32)opj_int_floorlog2(size_prch); - } - } - p++; - /*printf("\nsize precinct for level %d : %d,%d\n", it_res,tccp->prcw[it_res], tccp->prch[it_res]); */ - } /*end for*/ - } else { - for (j = 0; j < tccp->numresolutions; j++) { - tccp->prcw[j] = 15; - tccp->prch[j] = 15; - } - } - - opj_dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); + if (size_prch < 1) { + tccp->prch[it_res] = 1; + } else { + tccp->prch[it_res] = (OPJ_UINT32)opj_int_floorlog2(size_prch); + } + } + p++; + /*printf("\nsize precinct for level %d : %d,%d\n", it_res,tccp->prcw[it_res], tccp->prch[it_res]); */ + } /*end for*/ + } else { + for (j = 0; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 15; + tccp->prch[j] = 15; } - } + } - if (parameters->mct_data) { - opj_free(parameters->mct_data); - parameters->mct_data = 00; + opj_dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); } - return OPJ_TRUE; -} + } -static OPJ_BOOL opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) -{ - assert(cstr_index != 00); + if (parameters->mct_data) { + opj_free(parameters->mct_data); + parameters->mct_data = 00; + } + return OPJ_TRUE; +} - /* expand the list? */ - if ((cstr_index->marknum + 1) > cstr_index->maxmarknum) { - opj_marker_info_t *new_marker; - cstr_index->maxmarknum = (OPJ_UINT32)(100 + (OPJ_FLOAT32) cstr_index->maxmarknum); - new_marker = (opj_marker_info_t *) opj_realloc(cstr_index->marker, cstr_index->maxmarknum *sizeof(opj_marker_info_t)); - if (! new_marker) { - opj_free(cstr_index->marker); - cstr_index->marker = NULL; - cstr_index->maxmarknum = 0; - cstr_index->marknum = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); */ - return OPJ_FALSE; - } - cstr_index->marker = new_marker; +static OPJ_BOOL opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, + OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) +{ + assert(cstr_index != 00); + + /* expand the list? */ + if ((cstr_index->marknum + 1) > cstr_index->maxmarknum) { + opj_marker_info_t *new_marker; + cstr_index->maxmarknum = (OPJ_UINT32)(100 + (OPJ_FLOAT32) + cstr_index->maxmarknum); + new_marker = (opj_marker_info_t *) opj_realloc(cstr_index->marker, + cstr_index->maxmarknum * sizeof(opj_marker_info_t)); + if (! new_marker) { + opj_free(cstr_index->marker); + cstr_index->marker = NULL; + cstr_index->maxmarknum = 0; + cstr_index->marknum = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); */ + return OPJ_FALSE; } + cstr_index->marker = new_marker; + } - /* add the marker */ - cstr_index->marker[cstr_index->marknum].type = (OPJ_UINT16)type; - cstr_index->marker[cstr_index->marknum].pos = (OPJ_INT32)pos; - cstr_index->marker[cstr_index->marknum].len = (OPJ_INT32)len; - cstr_index->marknum++; - return OPJ_TRUE; + /* add the marker */ + cstr_index->marker[cstr_index->marknum].type = (OPJ_UINT16)type; + cstr_index->marker[cstr_index->marknum].pos = (OPJ_INT32)pos; + cstr_index->marker[cstr_index->marknum].len = (OPJ_INT32)len; + cstr_index->marknum++; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) -{ - assert(cstr_index != 00); - assert(cstr_index->tile_index != 00); - - /* expand the list? */ - if ((cstr_index->tile_index[tileno].marknum + 1) > cstr_index->tile_index[tileno].maxmarknum) { - opj_marker_info_t *new_marker; - cstr_index->tile_index[tileno].maxmarknum = (OPJ_UINT32)(100 + (OPJ_FLOAT32) cstr_index->tile_index[tileno].maxmarknum); - new_marker = (opj_marker_info_t *) opj_realloc( - cstr_index->tile_index[tileno].marker, - cstr_index->tile_index[tileno].maxmarknum *sizeof(opj_marker_info_t)); - if (! new_marker) { - opj_free(cstr_index->tile_index[tileno].marker); - cstr_index->tile_index[tileno].marker = NULL; - cstr_index->tile_index[tileno].maxmarknum = 0; - cstr_index->tile_index[tileno].marknum = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); */ - return OPJ_FALSE; - } - cstr_index->tile_index[tileno].marker = new_marker; +static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, + opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, + OPJ_UINT32 len) +{ + assert(cstr_index != 00); + assert(cstr_index->tile_index != 00); + + /* expand the list? */ + if ((cstr_index->tile_index[tileno].marknum + 1) > + cstr_index->tile_index[tileno].maxmarknum) { + opj_marker_info_t *new_marker; + cstr_index->tile_index[tileno].maxmarknum = (OPJ_UINT32)(100 + + (OPJ_FLOAT32) cstr_index->tile_index[tileno].maxmarknum); + new_marker = (opj_marker_info_t *) opj_realloc( + cstr_index->tile_index[tileno].marker, + cstr_index->tile_index[tileno].maxmarknum * sizeof(opj_marker_info_t)); + if (! new_marker) { + opj_free(cstr_index->tile_index[tileno].marker); + cstr_index->tile_index[tileno].marker = NULL; + cstr_index->tile_index[tileno].maxmarknum = 0; + cstr_index->tile_index[tileno].marknum = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); */ + return OPJ_FALSE; } + cstr_index->tile_index[tileno].marker = new_marker; + } - /* add the marker */ - cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].type = (OPJ_UINT16)type; - cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].pos = (OPJ_INT32)pos; - cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].len = (OPJ_INT32)len; - cstr_index->tile_index[tileno].marknum++; - - if (type == J2K_MS_SOT) { - OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno; + /* add the marker */ + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].type + = (OPJ_UINT16)type; + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].pos + = (OPJ_INT32)pos; + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].len + = (OPJ_INT32)len; + cstr_index->tile_index[tileno].marknum++; - if (cstr_index->tile_index[tileno].tp_index) - cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos; + if (type == J2K_MS_SOT) { + OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno; + if (cstr_index->tile_index[tileno].tp_index) { + cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos; } - return OPJ_TRUE; + + } + return OPJ_TRUE; } /* @@ -6729,7 +7465,7 @@ static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, opj_codestream_index_t * OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k, opj_stream_private_t *p_stream, opj_event_mgr_t * p_manager - ) + ) { (void)p_j2k; (void)p_stream; @@ -6737,2581 +7473,2892 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k, return OPJ_TRUE; } -OPJ_BOOL opj_j2k_read_header( opj_stream_private_t *p_stream, - opj_j2k_t* p_j2k, - opj_image_t** p_image, - opj_event_mgr_t* p_manager ) +OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, + opj_j2k_t* p_j2k, + opj_image_t** p_image, + opj_event_mgr_t* p_manager) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - /* create an empty image header */ - p_j2k->m_private_image = opj_image_create0(); - if (! p_j2k->m_private_image) { - return OPJ_FALSE; - } + /* create an empty image header */ + p_j2k->m_private_image = opj_image_create0(); + if (! p_j2k->m_private_image) { + return OPJ_FALSE; + } - /* customization of the validation */ - if (! opj_j2k_setup_decoding_validation(p_j2k, p_manager)) { - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; - return OPJ_FALSE; - } + /* customization of the validation */ + if (! opj_j2k_setup_decoding_validation(p_j2k, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } - /* validation of the parameters codec */ - if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream,p_manager)) { - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; - return OPJ_FALSE; - } + /* validation of the parameters codec */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } - /* customization of the encoding */ - if (! opj_j2k_setup_header_reading(p_j2k, p_manager)) { - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; - return OPJ_FALSE; - } + /* customization of the encoding */ + if (! opj_j2k_setup_header_reading(p_j2k, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } - /* read header */ - if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) { - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; - return OPJ_FALSE; - } + /* read header */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } - *p_image = opj_image_create0(); - if (! (*p_image)) { - return OPJ_FALSE; - } + *p_image = opj_image_create0(); + if (!(*p_image)) { + return OPJ_FALSE; + } - /* Copy codestream image information to the output image */ - opj_copy_image_header(p_j2k->m_private_image, *p_image); + /* Copy codestream image information to the output image */ + opj_copy_image_header(p_j2k->m_private_image, *p_image); /*Allocate and initialize some elements of codestrem index*/ - if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)){ - return OPJ_FALSE; - } - - return OPJ_TRUE; + if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_setup_header_reading (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_header_reading(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions*/ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_read_header_procedure, p_manager)) { - return OPJ_FALSE; - } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_read_header_procedure, p_manager)) { + return OPJ_FALSE; + } - /* DEVELOPER CORNER, add your custom procedures */ - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_copy_default_tcp_and_create_tcd, p_manager)) { - return OPJ_FALSE; - } - - return OPJ_TRUE; + /* DEVELOPER CORNER, add your custom procedures */ + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_copy_default_tcp_and_create_tcd, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_setup_decoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_decoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions*/ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); - if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list,(opj_procedure)opj_j2k_build_decoder, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list,(opj_procedure)opj_j2k_decoding_validation, p_manager)) { - return OPJ_FALSE; - } + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_build_decoder, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_decoding_validation, p_manager)) { + return OPJ_FALSE; + } - /* DEVELOPER CORNER, add your custom validation procedure */ - return OPJ_TRUE; + /* DEVELOPER CORNER, add your custom validation procedure */ + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_mct_validation ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_mct_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_BOOL l_is_valid = OPJ_TRUE; - OPJ_UINT32 i,j; + OPJ_BOOL l_is_valid = OPJ_TRUE; + OPJ_UINT32 i, j; - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - if ((p_j2k->m_cp.rsiz & 0x8200) == 0x8200) { - OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); - for (i=0;i<l_nb_tiles;++i) { - if (l_tcp->mct == 2) { - opj_tccp_t * l_tccp = l_tcp->tccps; - l_is_valid &= (l_tcp->m_mct_coding_matrix != 00); + if ((p_j2k->m_cp.rsiz & 0x8200) == 0x8200) { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; - for (j=0;j<p_j2k->m_private_image->numcomps;++j) { - l_is_valid &= ! (l_tccp->qmfbid & 1); - ++l_tccp; - } - } - ++l_tcp; + for (i = 0; i < l_nb_tiles; ++i) { + if (l_tcp->mct == 2) { + opj_tccp_t * l_tccp = l_tcp->tccps; + l_is_valid &= (l_tcp->m_mct_coding_matrix != 00); + + for (j = 0; j < p_j2k->m_private_image->numcomps; ++j) { + l_is_valid &= !(l_tccp->qmfbid & 1); + ++l_tccp; } + } + ++l_tcp; } + } - return l_is_valid; + return l_is_valid; } OPJ_BOOL opj_j2k_setup_mct_encoding(opj_tcp_t * p_tcp, opj_image_t * p_image) { - OPJ_UINT32 i; - OPJ_UINT32 l_indix = 1; - opj_mct_data_t * l_mct_deco_data = 00,* l_mct_offset_data = 00; - opj_simple_mcc_decorrelation_data_t * l_mcc_data; - OPJ_UINT32 l_mct_size,l_nb_elem; - OPJ_FLOAT32 * l_data, * l_current_data; - opj_tccp_t * l_tccp; - - /* preconditions */ - assert(p_tcp != 00); - - if (p_tcp->mct != 2) { - return OPJ_TRUE; - } - - if (p_tcp->m_mct_decoding_matrix) { - if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { - opj_mct_data_t *new_mct_records; - p_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + OPJ_UINT32 i; + OPJ_UINT32 l_indix = 1; + opj_mct_data_t * l_mct_deco_data = 00, * l_mct_offset_data = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_data; + OPJ_UINT32 l_mct_size, l_nb_elem; + OPJ_FLOAT32 * l_data, * l_current_data; + opj_tccp_t * l_tccp; - new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); - if (! new_mct_records) { - opj_free(p_tcp->m_mct_records); - p_tcp->m_mct_records = NULL; - p_tcp->m_nb_max_mct_records = 0; - p_tcp->m_nb_mct_records = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ - return OPJ_FALSE; - } - p_tcp->m_mct_records = new_mct_records; - l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + /* preconditions */ + assert(p_tcp != 00); - memset(l_mct_deco_data ,0,(p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); - } - l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + if (p_tcp->mct != 2) { + return OPJ_TRUE; + } - if (l_mct_deco_data->m_data) { - opj_free(l_mct_deco_data->m_data); - l_mct_deco_data->m_data = 00; - } + if (p_tcp->m_mct_decoding_matrix) { + if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { + opj_mct_data_t *new_mct_records; + p_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + + new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, + p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! new_mct_records) { + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = NULL; + p_tcp->m_nb_max_mct_records = 0; + p_tcp->m_nb_mct_records = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ + return OPJ_FALSE; + } + p_tcp->m_mct_records = new_mct_records; + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; - l_mct_deco_data->m_index = l_indix++; - l_mct_deco_data->m_array_type = MCT_TYPE_DECORRELATION; - l_mct_deco_data->m_element_type = MCT_TYPE_FLOAT; - l_nb_elem = p_image->numcomps * p_image->numcomps; - l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_deco_data->m_element_type]; - l_mct_deco_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size ); + memset(l_mct_deco_data, 0, + (p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof( + opj_mct_data_t)); + } + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; - if (! l_mct_deco_data->m_data) { - return OPJ_FALSE; - } + if (l_mct_deco_data->m_data) { + opj_free(l_mct_deco_data->m_data); + l_mct_deco_data->m_data = 00; + } - j2k_mct_write_functions_from_float[l_mct_deco_data->m_element_type](p_tcp->m_mct_decoding_matrix,l_mct_deco_data->m_data,l_nb_elem); + l_mct_deco_data->m_index = l_indix++; + l_mct_deco_data->m_array_type = MCT_TYPE_DECORRELATION; + l_mct_deco_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_deco_data->m_element_type]; + l_mct_deco_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size); - l_mct_deco_data->m_data_size = l_mct_size; - ++p_tcp->m_nb_mct_records; + if (! l_mct_deco_data->m_data) { + return OPJ_FALSE; } - if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { - opj_mct_data_t *new_mct_records; - p_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; - new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); - if (! new_mct_records) { - opj_free(p_tcp->m_mct_records); - p_tcp->m_mct_records = NULL; - p_tcp->m_nb_max_mct_records = 0; - p_tcp->m_nb_mct_records = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ - return OPJ_FALSE; - } - p_tcp->m_mct_records = new_mct_records; - l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + j2k_mct_write_functions_from_float[l_mct_deco_data->m_element_type]( + p_tcp->m_mct_decoding_matrix, l_mct_deco_data->m_data, l_nb_elem); - memset(l_mct_offset_data ,0,(p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + l_mct_deco_data->m_data_size = l_mct_size; + ++p_tcp->m_nb_mct_records; + } - if (l_mct_deco_data) { - l_mct_deco_data = l_mct_offset_data - 1; - } + if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { + opj_mct_data_t *new_mct_records; + p_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, + p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! new_mct_records) { + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = NULL; + p_tcp->m_nb_max_mct_records = 0; + p_tcp->m_nb_mct_records = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ + return OPJ_FALSE; } - + p_tcp->m_mct_records = new_mct_records; l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; - if (l_mct_offset_data->m_data) { - opj_free(l_mct_offset_data->m_data); - l_mct_offset_data->m_data = 00; + memset(l_mct_offset_data, 0, + (p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof( + opj_mct_data_t)); + + if (l_mct_deco_data) { + l_mct_deco_data = l_mct_offset_data - 1; } + } - l_mct_offset_data->m_index = l_indix++; - l_mct_offset_data->m_array_type = MCT_TYPE_OFFSET; - l_mct_offset_data->m_element_type = MCT_TYPE_FLOAT; - l_nb_elem = p_image->numcomps; - l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_offset_data->m_element_type]; - l_mct_offset_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size ); + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; - if (! l_mct_offset_data->m_data) { - return OPJ_FALSE; - } + if (l_mct_offset_data->m_data) { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + } - l_data = (OPJ_FLOAT32*)opj_malloc(l_nb_elem * sizeof(OPJ_FLOAT32)); - if (! l_data) { - opj_free(l_mct_offset_data->m_data); - l_mct_offset_data->m_data = 00; - return OPJ_FALSE; - } + l_mct_offset_data->m_index = l_indix++; + l_mct_offset_data->m_array_type = MCT_TYPE_OFFSET; + l_mct_offset_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_offset_data->m_element_type]; + l_mct_offset_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size); - l_tccp = p_tcp->tccps; - l_current_data = l_data; + if (! l_mct_offset_data->m_data) { + return OPJ_FALSE; + } - for (i=0;i<l_nb_elem;++i) { - *(l_current_data++) = (OPJ_FLOAT32) (l_tccp->m_dc_level_shift); - ++l_tccp; - } + l_data = (OPJ_FLOAT32*)opj_malloc(l_nb_elem * sizeof(OPJ_FLOAT32)); + if (! l_data) { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + return OPJ_FALSE; + } - j2k_mct_write_functions_from_float[l_mct_offset_data->m_element_type](l_data,l_mct_offset_data->m_data,l_nb_elem); + l_tccp = p_tcp->tccps; + l_current_data = l_data; - opj_free(l_data); + for (i = 0; i < l_nb_elem; ++i) { + *(l_current_data++) = (OPJ_FLOAT32)(l_tccp->m_dc_level_shift); + ++l_tccp; + } - l_mct_offset_data->m_data_size = l_mct_size; + j2k_mct_write_functions_from_float[l_mct_offset_data->m_element_type](l_data, + l_mct_offset_data->m_data, l_nb_elem); - ++p_tcp->m_nb_mct_records; + opj_free(l_data); - if (p_tcp->m_nb_mcc_records == p_tcp->m_nb_max_mcc_records) { - opj_simple_mcc_decorrelation_data_t *new_mcc_records; - p_tcp->m_nb_max_mcc_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; - new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc( - p_tcp->m_mcc_records, p_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t)); - if (! new_mcc_records) { - opj_free(p_tcp->m_mcc_records); - p_tcp->m_mcc_records = NULL; - p_tcp->m_nb_max_mcc_records = 0; - p_tcp->m_nb_mcc_records = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ - return OPJ_FALSE; - } - p_tcp->m_mcc_records = new_mcc_records; - l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; - memset(l_mcc_data ,0,(p_tcp->m_nb_max_mcc_records - p_tcp->m_nb_mcc_records) * sizeof(opj_simple_mcc_decorrelation_data_t)); + l_mct_offset_data->m_data_size = l_mct_size; - } + ++p_tcp->m_nb_mct_records; + if (p_tcp->m_nb_mcc_records == p_tcp->m_nb_max_mcc_records) { + opj_simple_mcc_decorrelation_data_t *new_mcc_records; + p_tcp->m_nb_max_mcc_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc( + p_tcp->m_mcc_records, p_tcp->m_nb_max_mcc_records * sizeof( + opj_simple_mcc_decorrelation_data_t)); + if (! new_mcc_records) { + opj_free(p_tcp->m_mcc_records); + p_tcp->m_mcc_records = NULL; + p_tcp->m_nb_max_mcc_records = 0; + p_tcp->m_nb_mcc_records = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ + return OPJ_FALSE; + } + p_tcp->m_mcc_records = new_mcc_records; l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; - l_mcc_data->m_decorrelation_array = l_mct_deco_data; - l_mcc_data->m_is_irreversible = 1; - l_mcc_data->m_nb_comps = p_image->numcomps; - l_mcc_data->m_index = l_indix++; - l_mcc_data->m_offset_array = l_mct_offset_data; - ++p_tcp->m_nb_mcc_records; + memset(l_mcc_data, 0, (p_tcp->m_nb_max_mcc_records - p_tcp->m_nb_mcc_records) * + sizeof(opj_simple_mcc_decorrelation_data_t)); - return OPJ_TRUE; + } + + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + l_mcc_data->m_decorrelation_array = l_mct_deco_data; + l_mcc_data->m_is_irreversible = 1; + l_mcc_data->m_nb_comps = p_image->numcomps; + l_mcc_data->m_index = l_indix++; + l_mcc_data->m_offset_array = l_mct_offset_data; + ++p_tcp->m_nb_mcc_records; + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_build_decoder (opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_build_decoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - /* add here initialization of cp - copy paste of setup_decoder */ - (void)p_j2k; - (void)p_stream; - (void)p_manager; - return OPJ_TRUE; + /* add here initialization of cp + copy paste of setup_decoder */ + (void)p_j2k; + (void)p_stream; + (void)p_manager; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_build_encoder (opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_build_encoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - /* add here initialization of cp - copy paste of setup_encoder */ - (void)p_j2k; - (void)p_stream; - (void)p_manager; - return OPJ_TRUE; + /* add here initialization of cp + copy paste of setup_encoder */ + (void)p_j2k; + (void)p_stream; + (void)p_manager; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_encoding_validation ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_encoding_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_BOOL l_is_valid = OPJ_TRUE; + OPJ_BOOL l_is_valid = OPJ_TRUE; - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - /* STATE checking */ - /* make sure the state is at 0 */ - l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NONE); + OPJ_UNUSED(p_stream); - /* POINTER validation */ - /* make sure a p_j2k codec is present */ - l_is_valid &= (p_j2k->m_procedure_list != 00); - /* make sure a validation list is present */ - l_is_valid &= (p_j2k->m_validation_list != 00); + /* STATE checking */ + /* make sure the state is at 0 */ + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NONE); - /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */ - /* 33 (32) would always fail the check below (if a cast to 64bits was done) */ - /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 32 ? */ - if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 32)) { - opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); - return OPJ_FALSE; - } + /* POINTER validation */ + /* make sure a p_j2k codec is present */ + l_is_valid &= (p_j2k->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (p_j2k->m_validation_list != 00); - if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { - opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); - return OPJ_FALSE; - } + /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */ + /* 33 (32) would always fail the check below (if a cast to 64bits was done) */ + /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 32 ? */ + if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || + (p_j2k->m_cp.tcps->tccps->numresolutions > 32)) { + opj_event_msg(p_manager, EVT_ERROR, + "Number of resolutions is too high in comparison to the size of tiles\n"); + return OPJ_FALSE; + } - if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { - opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); - return OPJ_FALSE; - } + if ((p_j2k->m_cp.tdx) < (OPJ_UINT32)(1 << + (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { + opj_event_msg(p_manager, EVT_ERROR, + "Number of resolutions is too high in comparison to the size of tiles\n"); + return OPJ_FALSE; + } + + if ((p_j2k->m_cp.tdy) < (OPJ_UINT32)(1 << + (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { + opj_event_msg(p_manager, EVT_ERROR, + "Number of resolutions is too high in comparison to the size of tiles\n"); + return OPJ_FALSE; + } - /* PARAMETER VALIDATION */ - return l_is_valid; + /* PARAMETER VALIDATION */ + return l_is_valid; } -static OPJ_BOOL opj_j2k_decoding_validation ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_decoding_validation(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - OPJ_BOOL l_is_valid = OPJ_TRUE; + OPJ_BOOL l_is_valid = OPJ_TRUE; - /* preconditions*/ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - /* STATE checking */ - /* make sure the state is at 0 */ + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); + + /* STATE checking */ + /* make sure the state is at 0 */ #ifdef TODO_MSD - l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE); + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE); #endif - l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == 0x0000); + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == 0x0000); - /* POINTER validation */ - /* make sure a p_j2k codec is present */ - /* make sure a procedure list is present */ - l_is_valid &= (p_j2k->m_procedure_list != 00); - /* make sure a validation list is present */ - l_is_valid &= (p_j2k->m_validation_list != 00); + /* POINTER validation */ + /* make sure a p_j2k codec is present */ + /* make sure a procedure list is present */ + l_is_valid &= (p_j2k->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (p_j2k->m_validation_list != 00); - /* PARAMETER VALIDATION */ - return l_is_valid; + /* PARAMETER VALIDATION */ + return l_is_valid; } -static OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_read_header_procedure(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 l_current_marker; - OPJ_UINT32 l_marker_size; - const opj_dec_memory_marker_handler_t * l_marker_handler = 00; - OPJ_BOOL l_has_siz = 0; - OPJ_BOOL l_has_cod = 0; - OPJ_BOOL l_has_qcd = 0; - - /* preconditions */ - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - /* We enter in the main header */ - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSOC; - - /* Try to read the SOC marker, the codestream must begin with SOC marker */ - if (! opj_j2k_read_soc(p_j2k,p_stream,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Expected a SOC marker \n"); - return OPJ_FALSE; - } - - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + OPJ_UINT32 l_current_marker; + OPJ_UINT32 l_marker_size; + const opj_dec_memory_marker_handler_t * l_marker_handler = 00; + OPJ_BOOL l_has_siz = 0; + OPJ_BOOL l_has_cod = 0; + OPJ_BOOL l_has_qcd = 0; - /* Read 2 bytes as the new marker ID */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - /* Try to read until the SOT is detected */ - while (l_current_marker != J2K_MS_SOT) { + /* We enter in the main header */ + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSOC; - /* Check if the current marker ID is valid */ - if (l_current_marker < 0xff00) { - opj_event_msg(p_manager, EVT_ERROR, "A marker ID was expected (0xff--) instead of %.8x\n", l_current_marker); - return OPJ_FALSE; - } + /* Try to read the SOC marker, the codestream must begin with SOC marker */ + if (! opj_j2k_read_soc(p_j2k, p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Expected a SOC marker \n"); + return OPJ_FALSE; + } - /* Get the marker handler from the marker ID */ - l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } - /* Manage case where marker is unknown */ - if (l_marker_handler->id == J2K_MS_UNK) { - if (! opj_j2k_read_unk(p_j2k, p_stream, &l_current_marker, p_manager)){ - opj_event_msg(p_manager, EVT_ERROR, "Unknow marker have been detected and generated error.\n"); - return OPJ_FALSE; - } + /* Read 2 bytes as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); - if (l_current_marker == J2K_MS_SOT) - break; /* SOT marker is detected main header is completely read */ - else /* Get the marker handler from the marker ID */ - l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); - } + /* Try to read until the SOT is detected */ + while (l_current_marker != J2K_MS_SOT) { - if (l_marker_handler->id == J2K_MS_SIZ) { - /* Mark required SIZ marker as found */ - l_has_siz = 1; - } - if (l_marker_handler->id == J2K_MS_COD) { - /* Mark required COD marker as found */ - l_has_cod = 1; - } - if (l_marker_handler->id == J2K_MS_QCD) { - /* Mark required QCD marker as found */ - l_has_qcd = 1; - } + /* Check if the current marker ID is valid */ + if (l_current_marker < 0xff00) { + opj_event_msg(p_manager, EVT_ERROR, + "A marker ID was expected (0xff--) instead of %.8x\n", l_current_marker); + return OPJ_FALSE; + } - /* Check if the marker is known and if it is the right place to find it */ - if (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) { - opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); - return OPJ_FALSE; - } + /* Get the marker handler from the marker ID */ + l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); - /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + /* Manage case where marker is unknown */ + if (l_marker_handler->id == J2K_MS_UNK) { + if (! opj_j2k_read_unk(p_j2k, p_stream, &l_current_marker, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Unknow marker have been detected and generated error.\n"); + return OPJ_FALSE; + } - /* read 2 bytes as the marker size */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); - if (l_marker_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid marker size\n"); - return OPJ_FALSE; - } - l_marker_size -= 2; /* Subtract the size of the marker ID already read */ - - /* Check if the marker size is compatible with the header data size */ - if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { - OPJ_BYTE *new_header_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size); - if (! new_header_data) { - opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); - p_j2k->m_specific_param.m_decoder.m_header_data = NULL; - p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read header\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data; - p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; - } + if (l_current_marker == J2K_MS_SOT) { + break; /* SOT marker is detected main header is completely read */ + } else { /* Get the marker handler from the marker ID */ + l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); + } + } - /* Try to read the rest of the marker segment from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != l_marker_size) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + if (l_marker_handler->id == J2K_MS_SIZ) { + /* Mark required SIZ marker as found */ + l_has_siz = 1; + } + if (l_marker_handler->id == J2K_MS_COD) { + /* Mark required COD marker as found */ + l_has_cod = 1; + } + if (l_marker_handler->id == J2K_MS_QCD) { + /* Mark required QCD marker as found */ + l_has_qcd = 1; + } - /* Read the marker segment with the correct marker handler */ - if (! (*(l_marker_handler->handler))(p_j2k,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Marker handler function failed to read the marker segment\n"); - return OPJ_FALSE; - } + /* Check if the marker is known and if it is the right place to find it */ + if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker is not compliant with its position\n"); + return OPJ_FALSE; + } - /* Add the marker to the codestream index*/ - if (OPJ_FALSE == opj_j2k_add_mhmarker( - p_j2k->cstr_index, - l_marker_handler->id, - (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, - l_marker_size + 4 )) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); - return OPJ_FALSE; - } + /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + /* read 2 bytes as the marker size */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker_size, + 2); + if (l_marker_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid marker size\n"); + return OPJ_FALSE; + } + l_marker_size -= 2; /* Subtract the size of the marker ID already read */ - /* read 2 bytes as the new marker ID */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); + /* Check if the marker size is compatible with the header data size */ + if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { + OPJ_BYTE *new_header_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size); + if (! new_header_data) { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = NULL; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read header\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data; + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; } - if (l_has_siz == 0) { - opj_event_msg(p_manager, EVT_ERROR, "required SIZ marker not found in main header\n"); + /* Try to read the rest of the marker segment from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, + p_manager) != l_marker_size) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } - if (l_has_cod == 0) { - opj_event_msg(p_manager, EVT_ERROR, "required COD marker not found in main header\n"); + + /* Read the marker segment with the correct marker handler */ + if (!(*(l_marker_handler->handler))(p_j2k, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker handler function failed to read the marker segment\n"); return OPJ_FALSE; } - if (l_has_qcd == 0) { - opj_event_msg(p_manager, EVT_ERROR, "required QCD marker not found in main header\n"); + + /* Add the marker to the codestream index*/ + if (OPJ_FALSE == opj_j2k_add_mhmarker( + p_j2k->cstr_index, + l_marker_handler->id, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, + l_marker_size + 4)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); return OPJ_FALSE; } - - if (! opj_j2k_merge_ppm(&(p_j2k->m_cp), p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPM data\n"); + + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } - opj_event_msg(p_manager, EVT_INFO, "Main header has been correctly decoded.\n"); + /* read 2 bytes as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + } + + if (l_has_siz == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "required SIZ marker not found in main header\n"); + return OPJ_FALSE; + } + if (l_has_cod == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "required COD marker not found in main header\n"); + return OPJ_FALSE; + } + if (l_has_qcd == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "required QCD marker not found in main header\n"); + return OPJ_FALSE; + } + + if (! opj_j2k_merge_ppm(&(p_j2k->m_cp), p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPM data\n"); + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_INFO, "Main header has been correctly decoded.\n"); - /* Position of the last element if the main header */ - p_j2k->cstr_index->main_head_end = (OPJ_UINT32) opj_stream_tell(p_stream) - 2; + /* Position of the last element if the main header */ + p_j2k->cstr_index->main_head_end = (OPJ_UINT32) opj_stream_tell(p_stream) - 2; - /* Next step: read a tile-part header */ - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + /* Next step: read a tile-part header */ + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_exec ( opj_j2k_t * p_j2k, - opj_procedure_list_t * p_procedure_list, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_exec(opj_j2k_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_BOOL (** l_procedure) (opj_j2k_t * ,opj_stream_private_t *,opj_event_mgr_t *) = 00; - OPJ_BOOL l_result = OPJ_TRUE; - OPJ_UINT32 l_nb_proc, i; + OPJ_BOOL(** l_procedure)(opj_j2k_t *, opj_stream_private_t *, + opj_event_mgr_t *) = 00; + OPJ_BOOL l_result = OPJ_TRUE; + OPJ_UINT32 l_nb_proc, i; - /* preconditions*/ - assert(p_procedure_list != 00); - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_procedure_list != 00); + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); - l_procedure = (OPJ_BOOL (**) (opj_j2k_t * ,opj_stream_private_t *,opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); + l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); + l_procedure = (OPJ_BOOL(**)(opj_j2k_t *, opj_stream_private_t *, + opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); - for (i=0;i<l_nb_proc;++i) { - l_result = l_result && ((*l_procedure) (p_j2k,p_stream,p_manager)); - ++l_procedure; - } + for (i = 0; i < l_nb_proc; ++i) { + l_result = l_result && ((*l_procedure)(p_j2k, p_stream, p_manager)); + ++l_procedure; + } - /* and clear the procedure list at the end.*/ - opj_procedure_list_clear(p_procedure_list); - return l_result; + /* and clear the procedure list at the end.*/ + opj_procedure_list_clear(p_procedure_list); + return l_result; } /* FIXME DOC*/ -static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - opj_tcp_t * l_tcp = 00; - opj_tcp_t * l_default_tcp = 00; - OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 i,j; - opj_tccp_t *l_current_tccp = 00; - OPJ_UINT32 l_tccp_size; - OPJ_UINT32 l_mct_size; - opj_image_t * l_image; - OPJ_UINT32 l_mcc_records_size,l_mct_records_size; - opj_mct_data_t * l_src_mct_rec, *l_dest_mct_rec; - opj_simple_mcc_decorrelation_data_t * l_src_mcc_rec, *l_dest_mcc_rec; - OPJ_UINT32 l_offset; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_private_image; - l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - l_tcp = p_j2k->m_cp.tcps; - l_tccp_size = l_image->numcomps * (OPJ_UINT32)sizeof(opj_tccp_t); - l_default_tcp = p_j2k->m_specific_param.m_decoder.m_default_tcp; - l_mct_size = l_image->numcomps * l_image->numcomps * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - - /* For each tile */ - for (i=0; i<l_nb_tiles; ++i) { - /* keep the tile-compo coding parameters pointer of the current tile coding parameters*/ - l_current_tccp = l_tcp->tccps; - /*Copy default coding parameters into the current tile coding parameters*/ - memcpy(l_tcp, l_default_tcp, sizeof(opj_tcp_t)); - /* Initialize some values of the current tile coding parameters*/ - l_tcp->cod = 0; - l_tcp->ppt = 0; - l_tcp->ppt_data = 00; - /* Remove memory not owned by this tile in case of early error return. */ - l_tcp->m_mct_decoding_matrix = 00; - l_tcp->m_nb_max_mct_records = 0; - l_tcp->m_mct_records = 00; - l_tcp->m_nb_max_mcc_records = 0; - l_tcp->m_mcc_records = 00; - /* Reconnect the tile-compo coding parameters pointer to the current tile coding parameters*/ - l_tcp->tccps = l_current_tccp; - - /* Get the mct_decoding_matrix of the dflt_tile_cp and copy them into the current tile cp*/ - if (l_default_tcp->m_mct_decoding_matrix) { - l_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); - if (! l_tcp->m_mct_decoding_matrix ) { - return OPJ_FALSE; - } - memcpy(l_tcp->m_mct_decoding_matrix,l_default_tcp->m_mct_decoding_matrix,l_mct_size); - } - - /* Get the mct_record of the dflt_tile_cp and copy them into the current tile cp*/ - l_mct_records_size = l_default_tcp->m_nb_max_mct_records * (OPJ_UINT32)sizeof(opj_mct_data_t); - l_tcp->m_mct_records = (opj_mct_data_t*)opj_malloc(l_mct_records_size); - if (! l_tcp->m_mct_records) { - return OPJ_FALSE; - } - memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records,l_mct_records_size); - - /* Copy the mct record data from dflt_tile_cp to the current tile*/ - l_src_mct_rec = l_default_tcp->m_mct_records; - l_dest_mct_rec = l_tcp->m_mct_records; +static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + opj_tcp_t * l_tcp = 00; + opj_tcp_t * l_default_tcp = 00; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 i, j; + opj_tccp_t *l_current_tccp = 00; + OPJ_UINT32 l_tccp_size; + OPJ_UINT32 l_mct_size; + opj_image_t * l_image; + OPJ_UINT32 l_mcc_records_size, l_mct_records_size; + opj_mct_data_t * l_src_mct_rec, *l_dest_mct_rec; + opj_simple_mcc_decorrelation_data_t * l_src_mcc_rec, *l_dest_mcc_rec; + OPJ_UINT32 l_offset; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + + l_image = p_j2k->m_private_image; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + l_tccp_size = l_image->numcomps * (OPJ_UINT32)sizeof(opj_tccp_t); + l_default_tcp = p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_mct_size = l_image->numcomps * l_image->numcomps * (OPJ_UINT32)sizeof( + OPJ_FLOAT32); + + /* For each tile */ + for (i = 0; i < l_nb_tiles; ++i) { + /* keep the tile-compo coding parameters pointer of the current tile coding parameters*/ + l_current_tccp = l_tcp->tccps; + /*Copy default coding parameters into the current tile coding parameters*/ + memcpy(l_tcp, l_default_tcp, sizeof(opj_tcp_t)); + /* Initialize some values of the current tile coding parameters*/ + l_tcp->cod = 0; + l_tcp->ppt = 0; + l_tcp->ppt_data = 00; + l_tcp->m_current_tile_part_number = -1; + /* Remove memory not owned by this tile in case of early error return. */ + l_tcp->m_mct_decoding_matrix = 00; + l_tcp->m_nb_max_mct_records = 0; + l_tcp->m_mct_records = 00; + l_tcp->m_nb_max_mcc_records = 0; + l_tcp->m_mcc_records = 00; + /* Reconnect the tile-compo coding parameters pointer to the current tile coding parameters*/ + l_tcp->tccps = l_current_tccp; + + /* Get the mct_decoding_matrix of the dflt_tile_cp and copy them into the current tile cp*/ + if (l_default_tcp->m_mct_decoding_matrix) { + l_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); + if (! l_tcp->m_mct_decoding_matrix) { + return OPJ_FALSE; + } + memcpy(l_tcp->m_mct_decoding_matrix, l_default_tcp->m_mct_decoding_matrix, + l_mct_size); + } - for (j=0;j<l_default_tcp->m_nb_mct_records;++j) { + /* Get the mct_record of the dflt_tile_cp and copy them into the current tile cp*/ + l_mct_records_size = l_default_tcp->m_nb_max_mct_records * (OPJ_UINT32)sizeof( + opj_mct_data_t); + l_tcp->m_mct_records = (opj_mct_data_t*)opj_malloc(l_mct_records_size); + if (! l_tcp->m_mct_records) { + return OPJ_FALSE; + } + memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records, l_mct_records_size); - if (l_src_mct_rec->m_data) { + /* Copy the mct record data from dflt_tile_cp to the current tile*/ + l_src_mct_rec = l_default_tcp->m_mct_records; + l_dest_mct_rec = l_tcp->m_mct_records; - l_dest_mct_rec->m_data = (OPJ_BYTE*) opj_malloc(l_src_mct_rec->m_data_size); - if(! l_dest_mct_rec->m_data) { - return OPJ_FALSE; - } - memcpy(l_dest_mct_rec->m_data,l_src_mct_rec->m_data,l_src_mct_rec->m_data_size); - } + for (j = 0; j < l_default_tcp->m_nb_mct_records; ++j) { - ++l_src_mct_rec; - ++l_dest_mct_rec; - /* Update with each pass to free exactly what has been allocated on early return. */ - l_tcp->m_nb_max_mct_records += 1; - } + if (l_src_mct_rec->m_data) { - /* Get the mcc_record of the dflt_tile_cp and copy them into the current tile cp*/ - l_mcc_records_size = l_default_tcp->m_nb_max_mcc_records * (OPJ_UINT32)sizeof(opj_simple_mcc_decorrelation_data_t); - l_tcp->m_mcc_records = (opj_simple_mcc_decorrelation_data_t*) opj_malloc(l_mcc_records_size); - if (! l_tcp->m_mcc_records) { - return OPJ_FALSE; + l_dest_mct_rec->m_data = (OPJ_BYTE*) opj_malloc(l_src_mct_rec->m_data_size); + if (! l_dest_mct_rec->m_data) { + return OPJ_FALSE; } - memcpy(l_tcp->m_mcc_records,l_default_tcp->m_mcc_records,l_mcc_records_size); - l_tcp->m_nb_max_mcc_records = l_default_tcp->m_nb_max_mcc_records; + memcpy(l_dest_mct_rec->m_data, l_src_mct_rec->m_data, + l_src_mct_rec->m_data_size); + } - /* Copy the mcc record data from dflt_tile_cp to the current tile*/ - l_src_mcc_rec = l_default_tcp->m_mcc_records; - l_dest_mcc_rec = l_tcp->m_mcc_records; + ++l_src_mct_rec; + ++l_dest_mct_rec; + /* Update with each pass to free exactly what has been allocated on early return. */ + l_tcp->m_nb_max_mct_records += 1; + } - for (j=0;j<l_default_tcp->m_nb_max_mcc_records;++j) { + /* Get the mcc_record of the dflt_tile_cp and copy them into the current tile cp*/ + l_mcc_records_size = l_default_tcp->m_nb_max_mcc_records * (OPJ_UINT32)sizeof( + opj_simple_mcc_decorrelation_data_t); + l_tcp->m_mcc_records = (opj_simple_mcc_decorrelation_data_t*) opj_malloc( + l_mcc_records_size); + if (! l_tcp->m_mcc_records) { + return OPJ_FALSE; + } + memcpy(l_tcp->m_mcc_records, l_default_tcp->m_mcc_records, l_mcc_records_size); + l_tcp->m_nb_max_mcc_records = l_default_tcp->m_nb_max_mcc_records; - if (l_src_mcc_rec->m_decorrelation_array) { - l_offset = (OPJ_UINT32)(l_src_mcc_rec->m_decorrelation_array - l_default_tcp->m_mct_records); - l_dest_mcc_rec->m_decorrelation_array = l_tcp->m_mct_records + l_offset; - } + /* Copy the mcc record data from dflt_tile_cp to the current tile*/ + l_src_mcc_rec = l_default_tcp->m_mcc_records; + l_dest_mcc_rec = l_tcp->m_mcc_records; - if (l_src_mcc_rec->m_offset_array) { - l_offset = (OPJ_UINT32)(l_src_mcc_rec->m_offset_array - l_default_tcp->m_mct_records); - l_dest_mcc_rec->m_offset_array = l_tcp->m_mct_records + l_offset; - } + for (j = 0; j < l_default_tcp->m_nb_max_mcc_records; ++j) { - ++l_src_mcc_rec; - ++l_dest_mcc_rec; - } + if (l_src_mcc_rec->m_decorrelation_array) { + l_offset = (OPJ_UINT32)(l_src_mcc_rec->m_decorrelation_array - + l_default_tcp->m_mct_records); + l_dest_mcc_rec->m_decorrelation_array = l_tcp->m_mct_records + l_offset; + } - /* Copy all the dflt_tile_compo_cp to the current tile cp */ - memcpy(l_current_tccp,l_default_tcp->tccps,l_tccp_size); + if (l_src_mcc_rec->m_offset_array) { + l_offset = (OPJ_UINT32)(l_src_mcc_rec->m_offset_array - + l_default_tcp->m_mct_records); + l_dest_mcc_rec->m_offset_array = l_tcp->m_mct_records + l_offset; + } - /* Move to next tile cp*/ - ++l_tcp; + ++l_src_mcc_rec; + ++l_dest_mcc_rec; } - /* Create the current tile decoder*/ - p_j2k->m_tcd = (opj_tcd_t*)opj_tcd_create(OPJ_TRUE); /* FIXME why a cast ? */ - if (! p_j2k->m_tcd ) { - return OPJ_FALSE; - } + /* Copy all the dflt_tile_compo_cp to the current tile cp */ + memcpy(l_current_tccp, l_default_tcp->tccps, l_tccp_size); - if ( !opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp)) ) { - opj_tcd_destroy(p_j2k->m_tcd); - p_j2k->m_tcd = 00; - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); - return OPJ_FALSE; - } + /* Move to next tile cp*/ + ++l_tcp; + } - return OPJ_TRUE; + /* Create the current tile decoder*/ + p_j2k->m_tcd = opj_tcd_create(OPJ_TRUE); + if (! p_j2k->m_tcd) { + return OPJ_FALSE; + } + + if (!opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp), p_j2k->m_tp)) { + opj_tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler (OPJ_UINT32 p_id) +static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler( + OPJ_UINT32 p_id) { - const opj_dec_memory_marker_handler_t *e; - for (e = j2k_memory_marker_handler_tab; e->id != 0; ++e) { - if (e->id == p_id) { - break; /* we find a handler corresponding to the marker ID*/ - } + const opj_dec_memory_marker_handler_t *e; + for (e = j2k_memory_marker_handler_tab; e->id != 0; ++e) { + if (e->id == p_id) { + break; /* we find a handler corresponding to the marker ID*/ } - return e; + } + return e; } -void opj_j2k_destroy (opj_j2k_t *p_j2k) +void opj_j2k_destroy(opj_j2k_t *p_j2k) { - if (p_j2k == 00) { - return; - } + if (p_j2k == 00) { + return; + } - if (p_j2k->m_is_decoder) { + if (p_j2k->m_is_decoder) { - if (p_j2k->m_specific_param.m_decoder.m_default_tcp != 00) { - opj_j2k_tcp_destroy(p_j2k->m_specific_param.m_decoder.m_default_tcp); - opj_free(p_j2k->m_specific_param.m_decoder.m_default_tcp); - p_j2k->m_specific_param.m_decoder.m_default_tcp = 00; - } + if (p_j2k->m_specific_param.m_decoder.m_default_tcp != 00) { + opj_j2k_tcp_destroy(p_j2k->m_specific_param.m_decoder.m_default_tcp); + opj_free(p_j2k->m_specific_param.m_decoder.m_default_tcp); + p_j2k->m_specific_param.m_decoder.m_default_tcp = 00; + } - if (p_j2k->m_specific_param.m_decoder.m_header_data != 00) { - opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); - p_j2k->m_specific_param.m_decoder.m_header_data = 00; - p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; - } + if (p_j2k->m_specific_param.m_decoder.m_header_data != 00) { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = 00; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; } - else { - if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); - p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 00; - } + opj_free(p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode); + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = 00; + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = 0; - if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { - opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 00; - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 00; - } + } else { - if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = 00; - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - } + if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 00; } - opj_tcd_destroy(p_j2k->m_tcd); - - opj_j2k_cp_destroy(&(p_j2k->m_cp)); - memset(&(p_j2k->m_cp),0,sizeof(opj_cp_t)); + if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { + opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 00; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 00; + } - opj_procedure_list_destroy(p_j2k->m_procedure_list); - p_j2k->m_procedure_list = 00; + if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = 00; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + } + } - opj_procedure_list_destroy(p_j2k->m_validation_list); - p_j2k->m_procedure_list = 00; + opj_tcd_destroy(p_j2k->m_tcd); - j2k_destroy_cstr_index(p_j2k->cstr_index); - p_j2k->cstr_index = NULL; + opj_j2k_cp_destroy(&(p_j2k->m_cp)); + memset(&(p_j2k->m_cp), 0, sizeof(opj_cp_t)); - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; + opj_procedure_list_destroy(p_j2k->m_procedure_list); + p_j2k->m_procedure_list = 00; - opj_image_destroy(p_j2k->m_output_image); - p_j2k->m_output_image = NULL; + opj_procedure_list_destroy(p_j2k->m_validation_list); + p_j2k->m_procedure_list = 00; - opj_free(p_j2k); -} + j2k_destroy_cstr_index(p_j2k->cstr_index); + p_j2k->cstr_index = NULL; -void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind) -{ - if (p_cstr_ind) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; - if (p_cstr_ind->marker) { - opj_free(p_cstr_ind->marker); - p_cstr_ind->marker = NULL; - } + opj_image_destroy(p_j2k->m_output_image); + p_j2k->m_output_image = NULL; - if (p_cstr_ind->tile_index) { - OPJ_UINT32 it_tile = 0; + opj_thread_pool_destroy(p_j2k->m_tp); + p_j2k->m_tp = NULL; - for (it_tile=0; it_tile < p_cstr_ind->nb_of_tiles; it_tile++) { + opj_free(p_j2k); +} - if(p_cstr_ind->tile_index[it_tile].packet_index) { - opj_free(p_cstr_ind->tile_index[it_tile].packet_index); - p_cstr_ind->tile_index[it_tile].packet_index = NULL; - } +void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind) +{ + if (p_cstr_ind) { - if(p_cstr_ind->tile_index[it_tile].tp_index){ - opj_free(p_cstr_ind->tile_index[it_tile].tp_index); - p_cstr_ind->tile_index[it_tile].tp_index = NULL; - } + if (p_cstr_ind->marker) { + opj_free(p_cstr_ind->marker); + p_cstr_ind->marker = NULL; + } - if(p_cstr_ind->tile_index[it_tile].marker){ - opj_free(p_cstr_ind->tile_index[it_tile].marker); - p_cstr_ind->tile_index[it_tile].marker = NULL; + if (p_cstr_ind->tile_index) { + OPJ_UINT32 it_tile = 0; - } - } + for (it_tile = 0; it_tile < p_cstr_ind->nb_of_tiles; it_tile++) { - opj_free( p_cstr_ind->tile_index); - p_cstr_ind->tile_index = NULL; + if (p_cstr_ind->tile_index[it_tile].packet_index) { + opj_free(p_cstr_ind->tile_index[it_tile].packet_index); + p_cstr_ind->tile_index[it_tile].packet_index = NULL; } - opj_free(p_cstr_ind); - } -} - -static void opj_j2k_tcp_destroy (opj_tcp_t *p_tcp) -{ - if (p_tcp == 00) { - return; - } - - if (p_tcp->ppt_markers != 00) { - OPJ_UINT32 i; - for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { - if (p_tcp->ppt_markers[i].m_data != NULL) { - opj_free(p_tcp->ppt_markers[i].m_data); - } - } - p_tcp->ppt_markers_count = 0U; - opj_free(p_tcp->ppt_markers); - p_tcp->ppt_markers = NULL; - } - - if (p_tcp->ppt_buffer != 00) { - opj_free(p_tcp->ppt_buffer); - p_tcp->ppt_buffer = 00; - } - - if (p_tcp->tccps != 00) { - opj_free(p_tcp->tccps); - p_tcp->tccps = 00; - } - - if (p_tcp->m_mct_coding_matrix != 00) { - opj_free(p_tcp->m_mct_coding_matrix); - p_tcp->m_mct_coding_matrix = 00; - } - - if (p_tcp->m_mct_decoding_matrix != 00) { - opj_free(p_tcp->m_mct_decoding_matrix); - p_tcp->m_mct_decoding_matrix = 00; - } - - if (p_tcp->m_mcc_records) { - opj_free(p_tcp->m_mcc_records); - p_tcp->m_mcc_records = 00; - p_tcp->m_nb_max_mcc_records = 0; - p_tcp->m_nb_mcc_records = 0; - } - - if (p_tcp->m_mct_records) { - opj_mct_data_t * l_mct_data = p_tcp->m_mct_records; - OPJ_UINT32 i; - - for (i=0;i<p_tcp->m_nb_mct_records;++i) { - if (l_mct_data->m_data) { - opj_free(l_mct_data->m_data); - l_mct_data->m_data = 00; - } - - ++l_mct_data; - } - - opj_free(p_tcp->m_mct_records); - p_tcp->m_mct_records = 00; - } - - if (p_tcp->mct_norms != 00) { - opj_free(p_tcp->mct_norms); - p_tcp->mct_norms = 00; - } - - opj_j2k_tcp_data_destroy(p_tcp); - -} - -static void opj_j2k_tcp_data_destroy (opj_tcp_t *p_tcp) -{ - if (p_tcp->m_data) { - opj_free(p_tcp->m_data); - p_tcp->m_data = NULL; - p_tcp->m_data_size = 0; - } -} - -static void opj_j2k_cp_destroy (opj_cp_t *p_cp) -{ - OPJ_UINT32 l_nb_tiles; - opj_tcp_t * l_current_tile = 00; - - if (p_cp == 00) - { - return; - } - if (p_cp->tcps != 00) - { - OPJ_UINT32 i; - l_current_tile = p_cp->tcps; - l_nb_tiles = p_cp->th * p_cp->tw; - - for (i = 0U; i < l_nb_tiles; ++i) - { - opj_j2k_tcp_destroy(l_current_tile); - ++l_current_tile; - } - opj_free(p_cp->tcps); - p_cp->tcps = 00; - } - if (p_cp->ppm_markers != 00) { - OPJ_UINT32 i; - for (i = 0U; i < p_cp->ppm_markers_count; ++i) { - if (p_cp->ppm_markers[i].m_data != NULL) { - opj_free(p_cp->ppm_markers[i].m_data); - } - } - p_cp->ppm_markers_count = 0U; - opj_free(p_cp->ppm_markers); - p_cp->ppm_markers = NULL; - } - opj_free(p_cp->ppm_buffer); - p_cp->ppm_buffer = 00; - p_cp->ppm_data = NULL; /* ppm_data belongs to the allocated buffer pointed by ppm_buffer */ - opj_free(p_cp->comment); - p_cp->comment = 00; - if (! p_cp->m_is_decoder) - { - opj_free(p_cp->m_specific_param.m_enc.m_matrice); - p_cp->m_specific_param.m_enc.m_matrice = 00; - } -} - -static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, opj_event_mgr_t * p_manager ) -{ - OPJ_BYTE l_header_data[10]; - OPJ_OFF_T l_stream_pos_backup; - OPJ_UINT32 l_current_marker; - OPJ_UINT32 l_marker_size; - OPJ_UINT32 l_tile_no, l_tot_len, l_current_part, l_num_parts; - - /* initialize to no correction needed */ - *p_correction_needed = OPJ_FALSE; - - l_stream_pos_backup = opj_stream_tell(p_stream); - if (l_stream_pos_backup == -1) { - /* let's do nothing */ - return OPJ_TRUE; - } - - for (;;) { - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,l_header_data, 2, p_manager) != 2) { - /* assume all is OK */ - if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { - return OPJ_FALSE; - } - return OPJ_TRUE; - } - - /* Read 2 bytes from buffer as the new marker ID */ - opj_read_bytes(l_header_data, &l_current_marker, 2); - - if (l_current_marker != J2K_MS_SOT) { - /* assume all is OK */ - if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { - return OPJ_FALSE; - } - return OPJ_TRUE; - } - - /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } - - /* Read 2 bytes from the buffer as the marker size */ - opj_read_bytes(l_header_data, &l_marker_size, 2); - - /* Check marker size for SOT Marker */ - if (l_marker_size != 10) { - opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n"); - return OPJ_FALSE; - } - l_marker_size -= 2; - - if (opj_stream_read_data(p_stream, l_header_data, l_marker_size, p_manager) != l_marker_size) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } - - if (! opj_j2k_get_sot_values(l_header_data, l_marker_size, &l_tile_no, &l_tot_len, &l_current_part, &l_num_parts, p_manager)) { - return OPJ_FALSE; - } - - if (l_tile_no == tile_no) { - /* we found what we were looking for */ - break; - } - - if ((l_tot_len == 0U) || (l_tot_len < 14U)) { - /* last SOT until EOC or invalid Psot value */ - /* assume all is OK */ - if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { - return OPJ_FALSE; - } - return OPJ_TRUE; - } - l_tot_len -= 12U; - /* look for next SOT marker */ - if (opj_stream_skip(p_stream, (OPJ_OFF_T)(l_tot_len), p_manager) != (OPJ_OFF_T)(l_tot_len)) { - /* assume all is OK */ - if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { - return OPJ_FALSE; - } - return OPJ_TRUE; - } - } - - /* check for correction */ - if (l_current_part == l_num_parts) { - *p_correction_needed = OPJ_TRUE; - } - - if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { - return OPJ_FALSE; - } - return OPJ_TRUE; -} - -OPJ_BOOL opj_j2k_read_tile_header( opj_j2k_t * p_j2k, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 l_current_marker = J2K_MS_SOT; - OPJ_UINT32 l_marker_size; - const opj_dec_memory_marker_handler_t * l_marker_handler = 00; - opj_tcp_t * l_tcp = NULL; - - /* preconditions */ - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - /* Reach the End Of Codestream ?*/ - if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC){ - l_current_marker = J2K_MS_EOC; - } - /* We need to encounter a SOT marker (a new tile-part header) */ - else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT){ - return OPJ_FALSE; - } - - /* Read into the codestream until reach the EOC or ! can_decode ??? FIXME */ - while ( (!p_j2k->m_specific_param.m_decoder.m_can_decode) && (l_current_marker != J2K_MS_EOC) ) { - - /* Try to read until the Start Of Data is detected */ - while (l_current_marker != J2K_MS_SOD) { - - if(opj_stream_get_number_byte_left(p_stream) == 0) - { - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; - break; - } + if (p_cstr_ind->tile_index[it_tile].tp_index) { + opj_free(p_cstr_ind->tile_index[it_tile].tp_index); + p_cstr_ind->tile_index[it_tile].tp_index = NULL; + } - /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + if (p_cstr_ind->tile_index[it_tile].marker) { + opj_free(p_cstr_ind->tile_index[it_tile].marker); + p_cstr_ind->tile_index[it_tile].marker = NULL; - /* Read 2 bytes from the buffer as the marker size */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); + } + } - /* Check marker size (does not include marker ID but includes marker size) */ - if (l_marker_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n"); - return OPJ_FALSE; - } + opj_free(p_cstr_ind->tile_index); + p_cstr_ind->tile_index = NULL; + } - /* cf. https://code.google.com/p/openjpeg/issues/detail?id=226 */ - if (l_current_marker == 0x8080 && opj_stream_get_number_byte_left(p_stream) == 0) { - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; - break; - } + opj_free(p_cstr_ind); + } +} - /* Why this condition? FIXME */ - if (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH){ - p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); - } - l_marker_size -= 2; /* Subtract the size of the marker ID already read */ +static void opj_j2k_tcp_destroy(opj_tcp_t *p_tcp) +{ + if (p_tcp == 00) { + return; + } - /* Get the marker handler from the marker ID */ - l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); + if (p_tcp->ppt_markers != 00) { + OPJ_UINT32 i; + for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { + if (p_tcp->ppt_markers[i].m_data != NULL) { + opj_free(p_tcp->ppt_markers[i].m_data); + } + } + p_tcp->ppt_markers_count = 0U; + opj_free(p_tcp->ppt_markers); + p_tcp->ppt_markers = NULL; + } - /* Check if the marker is known and if it is the right place to find it */ - if (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) { - opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); - return OPJ_FALSE; - } -/* FIXME manage case of unknown marker as in the main header ? */ - - /* Check if the marker size is compatible with the header data size */ - if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { - OPJ_BYTE *new_header_data = NULL; - /* If we are here, this means we consider this marker as known & we will read it */ - /* Check enough bytes left in stream before allocation */ - if ((OPJ_OFF_T)l_marker_size > opj_stream_get_number_byte_left(p_stream)) { - opj_event_msg(p_manager, EVT_ERROR, "Marker size inconsistent with stream length\n"); - return OPJ_FALSE; - } - new_header_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size); - if (! new_header_data) { - opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); - p_j2k->m_specific_param.m_decoder.m_header_data = NULL; - p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read header\n"); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data; - p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; - } + if (p_tcp->ppt_buffer != 00) { + opj_free(p_tcp->ppt_buffer); + p_tcp->ppt_buffer = 00; + } - /* Try to read the rest of the marker segment from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != l_marker_size) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + if (p_tcp->tccps != 00) { + opj_free(p_tcp->tccps); + p_tcp->tccps = 00; + } - if (!l_marker_handler->handler) { - /* See issue #175 */ - opj_event_msg(p_manager, EVT_ERROR, "Not sure how that happened.\n"); - return OPJ_FALSE; - } - /* Read the marker segment with the correct marker handler */ - if (! (*(l_marker_handler->handler))(p_j2k,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Fail to read the current marker segment (%#x)\n", l_current_marker); - return OPJ_FALSE; - } + if (p_tcp->m_mct_coding_matrix != 00) { + opj_free(p_tcp->m_mct_coding_matrix); + p_tcp->m_mct_coding_matrix = 00; + } - /* Add the marker to the codestream index*/ - if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number, - p_j2k->cstr_index, - l_marker_handler->id, - (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, - l_marker_size + 4 )) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); - return OPJ_FALSE; - } + if (p_tcp->m_mct_decoding_matrix != 00) { + opj_free(p_tcp->m_mct_decoding_matrix); + p_tcp->m_mct_decoding_matrix = 00; + } - /* Keep the position of the last SOT marker read */ - if ( l_marker_handler->id == J2K_MS_SOT ) { - OPJ_UINT32 sot_pos = (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4 ; - if (sot_pos > p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos) - { - p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = sot_pos; - } - } + if (p_tcp->m_mcc_records) { + opj_free(p_tcp->m_mcc_records); + p_tcp->m_mcc_records = 00; + p_tcp->m_nb_max_mcc_records = 0; + p_tcp->m_nb_mcc_records = 0; + } - if (p_j2k->m_specific_param.m_decoder.m_skip_data) { - /* Skip the rest of the tile part header*/ - if (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } - l_current_marker = J2K_MS_SOD; /* Normally we reached a SOD */ - } - else { - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } - /* Read 2 bytes from the buffer as the new marker ID */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - } - } - if(opj_stream_get_number_byte_left(p_stream) == 0 - && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) - break; + if (p_tcp->m_mct_records) { + opj_mct_data_t * l_mct_data = p_tcp->m_mct_records; + OPJ_UINT32 i; - /* If we didn't skip data before, we need to read the SOD marker*/ - if (! p_j2k->m_specific_param.m_decoder.m_skip_data) { - /* Try to read the SOD marker and skip data ? FIXME */ - if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) { - return OPJ_FALSE; - } - if (p_j2k->m_specific_param.m_decoder.m_can_decode && !p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked) { - /* Issue 254 */ - OPJ_BOOL l_correction_needed; - - p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; - if(!opj_j2k_need_nb_tile_parts_correction(p_stream, p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "opj_j2k_apply_nb_tile_parts_correction error\n"); - return OPJ_FALSE; - } - if (l_correction_needed) { - OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; - OPJ_UINT32 l_tile_no; - - p_j2k->m_specific_param.m_decoder.m_can_decode = 0; - p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction = 1; - /* correct tiles */ - for (l_tile_no = 0U; l_tile_no < l_nb_tiles; ++l_tile_no) { - if (p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts != 0U) { - p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts+=1; - } - } - opj_event_msg(p_manager, EVT_WARNING, "Non conformant codestream TPsot==TNsot.\n"); - } - } - if (! p_j2k->m_specific_param.m_decoder.m_can_decode){ - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } - - /* Read 2 bytes from buffer as the new marker ID */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - } - } - else { - /* Indicate we will try to read a new tile-part header*/ - p_j2k->m_specific_param.m_decoder.m_skip_data = 0; - p_j2k->m_specific_param.m_decoder.m_can_decode = 0; - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; - - /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ - if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + for (i = 0; i < p_tcp->m_nb_mct_records; ++i) { + if (l_mct_data->m_data) { + opj_free(l_mct_data->m_data); + l_mct_data->m_data = 00; + } - /* Read 2 bytes from buffer as the new marker ID */ - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - } + ++l_mct_data; } - /* Current marker is the EOC marker ?*/ - if (l_current_marker == J2K_MS_EOC) { - if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC ){ - p_j2k->m_current_tile_number = 0; - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC; - } - } + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = 00; + } - /* FIXME DOC ???*/ - if ( ! p_j2k->m_specific_param.m_decoder.m_can_decode) { - OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; + if (p_tcp->mct_norms != 00) { + opj_free(p_tcp->mct_norms); + p_tcp->mct_norms = 00; + } - while( (p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data == 00) ) { - ++p_j2k->m_current_tile_number; - ++l_tcp; - } + opj_j2k_tcp_data_destroy(p_tcp); - if (p_j2k->m_current_tile_number == l_nb_tiles) { - *p_go_on = OPJ_FALSE; - return OPJ_TRUE; - } - } +} - if (! opj_j2k_merge_ppt(p_j2k->m_cp.tcps + p_j2k->m_current_tile_number, p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPT data\n"); - return OPJ_FALSE; - } - /*FIXME ???*/ - if (! opj_tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); - return OPJ_FALSE; - } +static void opj_j2k_tcp_data_destroy(opj_tcp_t *p_tcp) +{ + if (p_tcp->m_data) { + opj_free(p_tcp->m_data); + p_tcp->m_data = NULL; + p_tcp->m_data_size = 0; + } +} + +static void opj_j2k_cp_destroy(opj_cp_t *p_cp) +{ + OPJ_UINT32 l_nb_tiles; + opj_tcp_t * l_current_tile = 00; - opj_event_msg(p_manager, EVT_INFO, "Header of tile %d / %d has been read.\n", - p_j2k->m_current_tile_number+1, (p_j2k->m_cp.th * p_j2k->m_cp.tw)); + if (p_cp == 00) { + return; + } + if (p_cp->tcps != 00) { + OPJ_UINT32 i; + l_current_tile = p_cp->tcps; + l_nb_tiles = p_cp->th * p_cp->tw; - *p_tile_index = p_j2k->m_current_tile_number; - *p_go_on = OPJ_TRUE; - *p_data_size = opj_tcd_get_decoded_tile_size(p_j2k->m_tcd); - if (*p_data_size == (OPJ_UINT32)-1) { - return OPJ_FALSE; + for (i = 0U; i < l_nb_tiles; ++i) { + opj_j2k_tcp_destroy(l_current_tile); + ++l_current_tile; + } + opj_free(p_cp->tcps); + p_cp->tcps = 00; + } + if (p_cp->ppm_markers != 00) { + OPJ_UINT32 i; + for (i = 0U; i < p_cp->ppm_markers_count; ++i) { + if (p_cp->ppm_markers[i].m_data != NULL) { + opj_free(p_cp->ppm_markers[i].m_data); + } } + p_cp->ppm_markers_count = 0U; + opj_free(p_cp->ppm_markers); + p_cp->ppm_markers = NULL; + } + opj_free(p_cp->ppm_buffer); + p_cp->ppm_buffer = 00; + p_cp->ppm_data = + NULL; /* ppm_data belongs to the allocated buffer pointed by ppm_buffer */ + opj_free(p_cp->comment); + p_cp->comment = 00; + if (! p_cp->m_is_decoder) { + opj_free(p_cp->m_specific_param.m_enc.m_matrice); + p_cp->m_specific_param.m_enc.m_matrice = 00; + } +} - *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; - *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; - *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; - *p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1; - *p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps; +static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t + *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_header_data[10]; + OPJ_OFF_T l_stream_pos_backup; + OPJ_UINT32 l_current_marker; + OPJ_UINT32 l_marker_size; + OPJ_UINT32 l_tile_no, l_tot_len, l_current_part, l_num_parts; - p_j2k->m_specific_param.m_decoder.m_state |= 0x0080;/* FIXME J2K_DEC_STATE_DATA;*/ + /* initialize to no correction needed */ + *p_correction_needed = OPJ_FALSE; + if (!opj_stream_has_seek(p_stream)) { + /* We can't do much in this case, seek is needed */ return OPJ_TRUE; -} - -OPJ_BOOL opj_j2k_decode_tile ( opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 l_current_marker; - OPJ_BYTE l_data [2]; - opj_tcp_t * l_tcp; + } - /* preconditions */ - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); + l_stream_pos_backup = opj_stream_tell(p_stream); + if (l_stream_pos_backup == -1) { + /* let's do nothing */ + return OPJ_TRUE; + } - if ( !(p_j2k->m_specific_param.m_decoder.m_state & 0x0080/*FIXME J2K_DEC_STATE_DATA*/) - || (p_tile_index != p_j2k->m_current_tile_number) ) { + for (;;) { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) { + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { return OPJ_FALSE; + } + return OPJ_TRUE; } - l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]); - if (! l_tcp->m_data) { - opj_j2k_tcp_destroy(l_tcp); - return OPJ_FALSE; - } + /* Read 2 bytes from buffer as the new marker ID */ + opj_read_bytes(l_header_data, &l_current_marker, 2); - if (! opj_tcd_decode_tile( p_j2k->m_tcd, - l_tcp->m_data, - l_tcp->m_data_size, - p_tile_index, - p_j2k->cstr_index, p_manager) ) { - opj_j2k_tcp_destroy(l_tcp); - p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/ - opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n"); + if (l_current_marker != J2K_MS_SOT) { + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { return OPJ_FALSE; + } + return OPJ_TRUE; } - if (! opj_tcd_update_tile_data(p_j2k->m_tcd,p_data,p_data_size)) { - return OPJ_FALSE; + /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; } - /* To avoid to destroy the tcp which can be useful when we try to decode a tile decoded before (cf j2k_random_tile_access) - * we destroy just the data which will be re-read in read_tile_header*/ - /*opj_j2k_tcp_destroy(l_tcp); - p_j2k->m_tcd->tcp = 0;*/ - opj_j2k_tcp_data_destroy(l_tcp); + /* Read 2 bytes from the buffer as the marker size */ + opj_read_bytes(l_header_data, &l_marker_size, 2); - p_j2k->m_specific_param.m_decoder.m_can_decode = 0; - p_j2k->m_specific_param.m_decoder.m_state &= (~ (0x0080u));/* FIXME J2K_DEC_STATE_DATA);*/ + /* Check marker size for SOT Marker */ + if (l_marker_size != 10) { + opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n"); + return OPJ_FALSE; + } + l_marker_size -= 2; - if(opj_stream_get_number_byte_left(p_stream) == 0 - && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC){ - return OPJ_TRUE; + if (opj_stream_read_data(p_stream, l_header_data, l_marker_size, + p_manager) != l_marker_size) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; } - if (p_j2k->m_specific_param.m_decoder.m_state != 0x0100){ /*FIXME J2K_DEC_STATE_EOC)*/ - if (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return OPJ_FALSE; - } + if (! opj_j2k_get_sot_values(l_header_data, l_marker_size, &l_tile_no, + &l_tot_len, &l_current_part, &l_num_parts, p_manager)) { + return OPJ_FALSE; + } - opj_read_bytes(l_data,&l_current_marker,2); + if (l_tile_no == tile_no) { + /* we found what we were looking for */ + break; + } - if (l_current_marker == J2K_MS_EOC) { - p_j2k->m_current_tile_number = 0; - p_j2k->m_specific_param.m_decoder.m_state = 0x0100;/*FIXME J2K_DEC_STATE_EOC;*/ - } - else if (l_current_marker != J2K_MS_SOT) - { - if(opj_stream_get_number_byte_left(p_stream) == 0) { - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; - opj_event_msg(p_manager, EVT_WARNING, "Stream does not end with EOC\n"); - return OPJ_TRUE; - } - opj_event_msg(p_manager, EVT_ERROR, "Stream too short, expected SOT\n"); - return OPJ_FALSE; - } + if (l_tot_len < 14U) { + /* last SOT until EOC or invalid Psot value */ + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; + } + l_tot_len -= 12U; + /* look for next SOT marker */ + if (opj_stream_skip(p_stream, (OPJ_OFF_T)(l_tot_len), + p_manager) != (OPJ_OFF_T)(l_tot_len)) { + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; } + } - return OPJ_TRUE; + /* check for correction */ + if (l_current_part == l_num_parts) { + *p_correction_needed = OPJ_TRUE; + } + + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image) +OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 i,j,k = 0; - OPJ_UINT32 l_width_src,l_height_src; - OPJ_UINT32 l_width_dest,l_height_dest; - OPJ_INT32 l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src; - OPJ_SIZE_T l_start_offset_src, l_line_offset_src, l_end_offset_src ; - OPJ_UINT32 l_start_x_dest , l_start_y_dest; - OPJ_UINT32 l_x0_dest, l_y0_dest, l_x1_dest, l_y1_dest; - OPJ_SIZE_T l_start_offset_dest, l_line_offset_dest; + OPJ_UINT32 l_current_marker = J2K_MS_SOT; + OPJ_UINT32 l_marker_size; + const opj_dec_memory_marker_handler_t * l_marker_handler = 00; + opj_tcp_t * l_tcp = NULL; - opj_image_comp_t * l_img_comp_src = 00; - opj_image_comp_t * l_img_comp_dest = 00; + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - opj_tcd_tilecomp_t * l_tilec = 00; - opj_image_t * l_image_src = 00; - OPJ_UINT32 l_size_comp, l_remaining; - OPJ_INT32 * l_dest_ptr; - opj_tcd_resolution_t* l_res= 00; + /* Reach the End Of Codestream ?*/ + if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC) { + l_current_marker = J2K_MS_EOC; + } + /* We need to encounter a SOT marker (a new tile-part header) */ + else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { + return OPJ_FALSE; + } - l_tilec = p_tcd->tcd_image->tiles->comps; - l_image_src = p_tcd->image; - l_img_comp_src = l_image_src->comps; + /* Read into the codestream until reach the EOC or ! can_decode ??? FIXME */ + while ((!p_j2k->m_specific_param.m_decoder.m_can_decode) && + (l_current_marker != J2K_MS_EOC)) { - l_img_comp_dest = p_output_image->comps; + /* Try to read until the Start Of Data is detected */ + while (l_current_marker != J2K_MS_SOD) { - for (i=0; i<l_image_src->numcomps; i++) { + if (opj_stream_get_number_byte_left(p_stream) == 0) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + break; + } - /* Allocate output component buffer if necessary */ - if (!l_img_comp_dest->data) { - OPJ_UINT32 width = l_img_comp_dest->w; - OPJ_UINT32 height = l_img_comp_dest->h; - const OPJ_UINT32 MAX_SIZE = UINT32_MAX / sizeof(OPJ_INT32); - if (height == 0 || width > MAX_SIZE / height) { - return OPJ_FALSE; - } - l_img_comp_dest->data = (OPJ_INT32*)opj_calloc(width * height, sizeof(OPJ_INT32)); - if (!l_img_comp_dest->data) { - return OPJ_FALSE; - } - } + /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } - /* Copy info from decoded comp image to output image */ - l_img_comp_dest->resno_decoded = l_img_comp_src->resno_decoded; + /* Read 2 bytes from the buffer as the marker size */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker_size, + 2); - /*-----*/ - /* Compute the precision of the output buffer */ - l_size_comp = l_img_comp_src->prec >> 3; /*(/ 8)*/ - l_remaining = l_img_comp_src->prec & 7; /* (%8) */ - l_res = l_tilec->resolutions + l_img_comp_src->resno_decoded; + /* Check marker size (does not include marker ID but includes marker size) */ + if (l_marker_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n"); + return OPJ_FALSE; + } - if (l_remaining) { - ++l_size_comp; - } + /* cf. https://code.google.com/p/openjpeg/issues/detail?id=226 */ + if (l_current_marker == 0x8080 && + opj_stream_get_number_byte_left(p_stream) == 0) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + break; + } - if (l_size_comp == 3) { - l_size_comp = 4; - } - /*-----*/ - - /* Current tile component size*/ - /*if (i == 0) { - fprintf(stdout, "SRC: l_res_x0=%d, l_res_x1=%d, l_res_y0=%d, l_res_y1=%d\n", - l_res->x0, l_res->x1, l_res->y0, l_res->y1); - }*/ - - l_width_src = (OPJ_UINT32)(l_res->x1 - l_res->x0); - l_height_src = (OPJ_UINT32)(l_res->y1 - l_res->y0); - - /* Border of the current output component*/ - l_x0_dest = opj_uint_ceildivpow2(l_img_comp_dest->x0, l_img_comp_dest->factor); - l_y0_dest = opj_uint_ceildivpow2(l_img_comp_dest->y0, l_img_comp_dest->factor); - l_x1_dest = l_x0_dest + l_img_comp_dest->w; /* can't overflow given that image->x1 is uint32 */ - l_y1_dest = l_y0_dest + l_img_comp_dest->h; - - /*if (i == 0) { - fprintf(stdout, "DEST: l_x0_dest=%d, l_x1_dest=%d, l_y0_dest=%d, l_y1_dest=%d (%d)\n", - l_x0_dest, l_x1_dest, l_y0_dest, l_y1_dest, l_img_comp_dest->factor ); - }*/ - - /*-----*/ - /* Compute the area (l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src) - * of the input buffer (decoded tile component) which will be move - * in the output buffer. Compute the area of the output buffer (l_start_x_dest, - * l_start_y_dest, l_width_dest, l_height_dest) which will be modified - * by this input area. - * */ - assert( l_res->x0 >= 0); - assert( l_res->x1 >= 0); - - /* Prevent bad casting to unsigned values in the subsequent lines. */ - if ( l_res->x0 < 0 || l_res->x1 < 0 || l_res->y0 < 0 || l_res->y1 < 0 ) { - return OPJ_FALSE; - } + /* Why this condition? FIXME */ + if (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH) { + p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); + } + l_marker_size -= 2; /* Subtract the size of the marker ID already read */ - if ( l_x0_dest < (OPJ_UINT32)l_res->x0 ) { - l_start_x_dest = (OPJ_UINT32)l_res->x0 - l_x0_dest; - l_offset_x0_src = 0; + /* Get the marker handler from the marker ID */ + l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); - if ( l_x1_dest >= (OPJ_UINT32)l_res->x1 ) { - l_width_dest = l_width_src; - l_offset_x1_src = 0; - } - else { - l_width_dest = l_x1_dest - (OPJ_UINT32)l_res->x0 ; - l_offset_x1_src = (OPJ_INT32)(l_width_src - l_width_dest); - } + /* Check if the marker is known and if it is the right place to find it */ + if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker is not compliant with its position\n"); + return OPJ_FALSE; + } + /* FIXME manage case of unknown marker as in the main header ? */ + + /* Check if the marker size is compatible with the header data size */ + if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { + OPJ_BYTE *new_header_data = NULL; + /* If we are here, this means we consider this marker as known & we will read it */ + /* Check enough bytes left in stream before allocation */ + if ((OPJ_OFF_T)l_marker_size > opj_stream_get_number_byte_left(p_stream)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker size inconsistent with stream length\n"); + return OPJ_FALSE; } - else { - l_start_x_dest = 0U; - l_offset_x0_src = (OPJ_INT32)l_x0_dest - l_res->x0; - - if ( l_x1_dest >= (OPJ_UINT32)l_res->x1 ) { - l_width_dest = l_width_src - (OPJ_UINT32)l_offset_x0_src; - l_offset_x1_src = 0; - } - else { - l_width_dest = l_img_comp_dest->w ; - l_offset_x1_src = l_res->x1 - (OPJ_INT32)l_x1_dest; - } + new_header_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size); + if (! new_header_data) { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = NULL; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read header\n"); + return OPJ_FALSE; } + p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data; + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; + } - if ( l_y0_dest < (OPJ_UINT32)l_res->y0 ) { - l_start_y_dest = (OPJ_UINT32)l_res->y0 - l_y0_dest; - l_offset_y0_src = 0; + /* Try to read the rest of the marker segment from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, + p_manager) != l_marker_size) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } - if ( l_y1_dest >= (OPJ_UINT32)l_res->y1 ) { - l_height_dest = l_height_src; - l_offset_y1_src = 0; - } - else { - l_height_dest = l_y1_dest - (OPJ_UINT32)l_res->y0 ; - l_offset_y1_src = (OPJ_INT32)(l_height_src - l_height_dest); - } + if (!l_marker_handler->handler) { + /* See issue #175 */ + opj_event_msg(p_manager, EVT_ERROR, "Not sure how that happened.\n"); + return OPJ_FALSE; + } + /* Read the marker segment with the correct marker handler */ + if (!(*(l_marker_handler->handler))(p_j2k, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Fail to read the current marker segment (%#x)\n", l_current_marker); + return OPJ_FALSE; + } + + /* Add the marker to the codestream index*/ + if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number, + p_j2k->cstr_index, + l_marker_handler->id, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, + l_marker_size + 4)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); + return OPJ_FALSE; + } + + /* Keep the position of the last SOT marker read */ + if (l_marker_handler->id == J2K_MS_SOT) { + OPJ_UINT32 sot_pos = (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4 + ; + if (sot_pos > p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos) { + p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = sot_pos; } - else { - l_start_y_dest = 0U; - l_offset_y0_src = (OPJ_INT32)l_y0_dest - l_res->y0; + } - if ( l_y1_dest >= (OPJ_UINT32)l_res->y1 ) { - l_height_dest = l_height_src - (OPJ_UINT32)l_offset_y0_src; - l_offset_y1_src = 0; - } - else { - l_height_dest = l_img_comp_dest->h ; - l_offset_y1_src = l_res->y1 - (OPJ_INT32)l_y1_dest; - } + if (p_j2k->m_specific_param.m_decoder.m_skip_data) { + /* Skip the rest of the tile part header*/ + if (opj_stream_skip(p_stream, p_j2k->m_specific_param.m_decoder.m_sot_length, + p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + l_current_marker = J2K_MS_SOD; /* Normally we reached a SOD */ + } else { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; } + /* Read 2 bytes from the buffer as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + } + } + if (opj_stream_get_number_byte_left(p_stream) == 0 + && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) { + break; + } - if( (l_offset_x0_src < 0 ) || (l_offset_y0_src < 0 ) || (l_offset_x1_src < 0 ) || (l_offset_y1_src < 0 ) ){ - return OPJ_FALSE; + /* If we didn't skip data before, we need to read the SOD marker*/ + if (! p_j2k->m_specific_param.m_decoder.m_skip_data) { + /* Try to read the SOD marker and skip data ? FIXME */ + if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) { + return OPJ_FALSE; + } + if (p_j2k->m_specific_param.m_decoder.m_can_decode && + !p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked) { + /* Issue 254 */ + OPJ_BOOL l_correction_needed; + + p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; + if (!opj_j2k_need_nb_tile_parts_correction(p_stream, + p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_apply_nb_tile_parts_correction error\n"); + return OPJ_FALSE; } - /* testcase 2977.pdf.asan.67.2198 */ - if ((OPJ_INT32)l_width_dest < 0 || (OPJ_INT32)l_height_dest < 0) { - return OPJ_FALSE; + if (l_correction_needed) { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + OPJ_UINT32 l_tile_no; + + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction = 1; + /* correct tiles */ + for (l_tile_no = 0U; l_tile_no < l_nb_tiles; ++l_tile_no) { + if (p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts != 0U) { + p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts += 1; + } + } + opj_event_msg(p_manager, EVT_WARNING, + "Non conformant codestream TPsot==TNsot.\n"); } - /*-----*/ - - /* Compute the input buffer offset */ - l_start_offset_src = (OPJ_SIZE_T)l_offset_x0_src + (OPJ_SIZE_T)l_offset_y0_src * (OPJ_SIZE_T)l_width_src; - l_line_offset_src = (OPJ_SIZE_T)l_offset_x1_src + (OPJ_SIZE_T)l_offset_x0_src; - l_end_offset_src = (OPJ_SIZE_T)l_offset_y1_src * (OPJ_SIZE_T)l_width_src - (OPJ_SIZE_T)l_offset_x0_src; - - /* Compute the output buffer offset */ - l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest * (OPJ_SIZE_T)l_img_comp_dest->w; - l_line_offset_dest = (OPJ_SIZE_T)l_img_comp_dest->w - (OPJ_SIZE_T)l_width_dest; - - /* Move the output buffer to the first place where we will write*/ - l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest; - - /*if (i == 0) { - fprintf(stdout, "COMPO[%d]:\n",i); - fprintf(stdout, "SRC: l_start_x_src=%d, l_start_y_src=%d, l_width_src=%d, l_height_src=%d\n" - "\t tile offset:%d, %d, %d, %d\n" - "\t buffer offset: %d; %d, %d\n", - l_res->x0, l_res->y0, l_width_src, l_height_src, - l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src, - l_start_offset_src, l_line_offset_src, l_end_offset_src); - - fprintf(stdout, "DEST: l_start_x_dest=%d, l_start_y_dest=%d, l_width_dest=%d, l_height_dest=%d\n" - "\t start offset: %d, line offset= %d\n", - l_start_x_dest, l_start_y_dest, l_width_dest, l_height_dest, l_start_offset_dest, l_line_offset_dest); - }*/ - - switch (l_size_comp) { - case 1: - { - OPJ_CHAR * l_src_ptr = (OPJ_CHAR*) p_data; - l_src_ptr += l_start_offset_src; /* Move to the first place where we will read*/ - - if (l_img_comp_src->sgnd) { - for (j = 0 ; j < l_height_dest ; ++j) { - for ( k = 0 ; k < l_width_dest ; ++k) { - *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++)); /* Copy only the data needed for the output image */ - } - - l_dest_ptr+= l_line_offset_dest; /* Move to the next place where we will write */ - l_src_ptr += l_line_offset_src ; /* Move to the next place where we will read */ - } - } - else { - for ( j = 0 ; j < l_height_dest ; ++j ) { - for ( k = 0 ; k < l_width_dest ; ++k) { - *(l_dest_ptr++) = (OPJ_INT32) ((*(l_src_ptr++))&0xff); - } - - l_dest_ptr+= l_line_offset_dest; - l_src_ptr += l_line_offset_src; - } - } - - l_src_ptr += l_end_offset_src; /* Move to the end of this component-part of the input buffer */ - p_data = (OPJ_BYTE*) l_src_ptr; /* Keep the current position for the next component-part */ - } - break; - case 2: - { - OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_data; - l_src_ptr += l_start_offset_src; - - if (l_img_comp_src->sgnd) { - for (j=0;j<l_height_dest;++j) { - for (k=0;k<l_width_dest;++k) { - *(l_dest_ptr++) = *(l_src_ptr++); - } - - l_dest_ptr+= l_line_offset_dest; - l_src_ptr += l_line_offset_src ; - } - } - else { - for (j=0;j<l_height_dest;++j) { - for (k=0;k<l_width_dest;++k) { - *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff; - } - - l_dest_ptr+= l_line_offset_dest; - l_src_ptr += l_line_offset_src ; - } - } - - l_src_ptr += l_end_offset_src; - p_data = (OPJ_BYTE*) l_src_ptr; - } - break; - case 4: - { - OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_data; - l_src_ptr += l_start_offset_src; - - for (j=0;j<l_height_dest;++j) { - for (k=0;k<l_width_dest;++k) { - *(l_dest_ptr++) = (*(l_src_ptr++)); - } - - l_dest_ptr+= l_line_offset_dest; - l_src_ptr += l_line_offset_src ; - } - - l_src_ptr += l_end_offset_src; - p_data = (OPJ_BYTE*) l_src_ptr; - } - break; + } + if (! p_j2k->m_specific_param.m_decoder.m_can_decode) { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; } - ++l_img_comp_dest; - ++l_img_comp_src; - ++l_tilec; + /* Read 2 bytes from buffer as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + } + } else { + /* Indicate we will try to read a new tile-part header*/ + p_j2k->m_specific_param.m_decoder.m_skip_data = 0; + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from buffer as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); } + } - return OPJ_TRUE; -} + /* Current marker is the EOC marker ?*/ + if (l_current_marker == J2K_MS_EOC) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC; + } -OPJ_BOOL opj_j2k_set_decode_area( opj_j2k_t *p_j2k, - opj_image_t* p_image, - OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, - opj_event_mgr_t * p_manager ) -{ - opj_cp_t * l_cp = &(p_j2k->m_cp); - opj_image_t * l_image = p_j2k->m_private_image; + /* FIXME DOC ???*/ + if (! p_j2k->m_specific_param.m_decoder.m_can_decode) { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; - OPJ_UINT32 it_comp; - OPJ_INT32 l_comp_x1, l_comp_y1; - opj_image_comp_t* l_img_comp = NULL; + while ((p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data == 00)) { + ++p_j2k->m_current_tile_number; + ++l_tcp; + } - /* Check if we are read the main header */ - if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { /* FIXME J2K_DEC_STATE_TPHSOT)*/ - opj_event_msg(p_manager, EVT_ERROR, "Need to decode the main header before begin to decode the remaining codestream"); - return OPJ_FALSE; + if (p_j2k->m_current_tile_number == l_nb_tiles) { + *p_go_on = OPJ_FALSE; + return OPJ_TRUE; } + } - if ( !p_start_x && !p_start_y && !p_end_x && !p_end_y){ - opj_event_msg(p_manager, EVT_INFO, "No decoded area parameters, set the decoded area to the whole image\n"); + if (! opj_j2k_merge_ppt(p_j2k->m_cp.tcps + p_j2k->m_current_tile_number, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPT data\n"); + return OPJ_FALSE; + } + /*FIXME ???*/ + if (! opj_tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } - p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; - p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + opj_event_msg(p_manager, EVT_INFO, "Header of tile %d / %d has been read.\n", + p_j2k->m_current_tile_number + 1, (p_j2k->m_cp.th * p_j2k->m_cp.tw)); - return OPJ_TRUE; + *p_tile_index = p_j2k->m_current_tile_number; + *p_go_on = OPJ_TRUE; + if (p_data_size) { + /* For internal use in j2k.c, we don't need this */ + /* This is just needed for folks using the opj_read_tile_header() / opj_decode_tile_data() combo */ + *p_data_size = opj_tcd_get_decoded_tile_size(p_j2k->m_tcd, OPJ_FALSE); + if (*p_data_size == UINT_MAX) { + return OPJ_FALSE; } + } + *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; + *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; + *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; + *p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1; + *p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps; - /* ----- */ - /* Check if the positions provided by the user are correct */ + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA; - /* Left */ - assert(p_start_x >= 0 ); - assert(p_start_y >= 0 ); + return OPJ_TRUE; +} - if ((OPJ_UINT32)p_start_x > l_image->x1 ) { - opj_event_msg(p_manager, EVT_ERROR, - "Left position of the decoded area (region_x0=%d) is outside the image area (Xsiz=%d).\n", - p_start_x, l_image->x1); - return OPJ_FALSE; - } - else if ((OPJ_UINT32)p_start_x < l_image->x0){ - opj_event_msg(p_manager, EVT_WARNING, - "Left position of the decoded area (region_x0=%d) is outside the image area (XOsiz=%d).\n", - p_start_x, l_image->x0); - p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; - p_image->x0 = l_image->x0; - } - else { - p_j2k->m_specific_param.m_decoder.m_start_tile_x = ((OPJ_UINT32)p_start_x - l_cp->tx0) / l_cp->tdx; - p_image->x0 = (OPJ_UINT32)p_start_x; - } +OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_current_marker; + OPJ_BYTE l_data [2]; + opj_tcp_t * l_tcp; + opj_image_t* l_image_for_bounds; - /* Up */ - if ((OPJ_UINT32)p_start_y > l_image->y1){ - opj_event_msg(p_manager, EVT_ERROR, - "Up position of the decoded area (region_y0=%d) is outside the image area (Ysiz=%d).\n", - p_start_y, l_image->y1); - return OPJ_FALSE; - } - else if ((OPJ_UINT32)p_start_y < l_image->y0){ - opj_event_msg(p_manager, EVT_WARNING, - "Up position of the decoded area (region_y0=%d) is outside the image area (YOsiz=%d).\n", - p_start_y, l_image->y0); - p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; - p_image->y0 = l_image->y0; - } - else { - p_j2k->m_specific_param.m_decoder.m_start_tile_y = ((OPJ_UINT32)p_start_y - l_cp->ty0) / l_cp->tdy; - p_image->y0 = (OPJ_UINT32)p_start_y; - } + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); - /* Right */ - assert((OPJ_UINT32)p_end_x > 0); - assert((OPJ_UINT32)p_end_y > 0); - if ((OPJ_UINT32)p_end_x < l_image->x0) { - opj_event_msg(p_manager, EVT_ERROR, - "Right position of the decoded area (region_x1=%d) is outside the image area (XOsiz=%d).\n", - p_end_x, l_image->x0); - return OPJ_FALSE; - } - else if ((OPJ_UINT32)p_end_x > l_image->x1) { - opj_event_msg(p_manager, EVT_WARNING, - "Right position of the decoded area (region_x1=%d) is outside the image area (Xsiz=%d).\n", - p_end_x, l_image->x1); - p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; - p_image->x1 = l_image->x1; + if (!(p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_DATA) + || (p_tile_index != p_j2k->m_current_tile_number)) { + return OPJ_FALSE; + } + + l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]); + if (! l_tcp->m_data) { + opj_j2k_tcp_destroy(l_tcp); + return OPJ_FALSE; + } + + /* When using the opj_read_tile_header / opj_decode_tile_data API */ + /* such as in test_tile_decoder, m_output_image is NULL, so fall back */ + /* to the full image dimension. This is a bit surprising that */ + /* opj_set_decode_area() is only used to determinte intersecting tiles, */ + /* but full tile decoding is done */ + l_image_for_bounds = p_j2k->m_output_image ? p_j2k->m_output_image : + p_j2k->m_private_image; + if (! opj_tcd_decode_tile(p_j2k->m_tcd, + l_image_for_bounds->x0, + l_image_for_bounds->y0, + l_image_for_bounds->x1, + l_image_for_bounds->y1, + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode, + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode, + l_tcp->m_data, + l_tcp->m_data_size, + p_tile_index, + p_j2k->cstr_index, p_manager)) { + opj_j2k_tcp_destroy(l_tcp); + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR; + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n"); + return OPJ_FALSE; + } + + /* p_data can be set to NULL when the call will take care of using */ + /* itself the TCD data. This is typically the case for whole single */ + /* tile decoding optimization. */ + if (p_data != NULL) { + if (! opj_tcd_update_tile_data(p_j2k->m_tcd, p_data, p_data_size)) { + return OPJ_FALSE; } - else { - p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv(p_end_x - (OPJ_INT32)l_cp->tx0, (OPJ_INT32)l_cp->tdx); - p_image->x1 = (OPJ_UINT32)p_end_x; + + /* To avoid to destroy the tcp which can be useful when we try to decode a tile decoded before (cf j2k_random_tile_access) + * we destroy just the data which will be re-read in read_tile_header*/ + /*opj_j2k_tcp_destroy(l_tcp); + p_j2k->m_tcd->tcp = 0;*/ + opj_j2k_tcp_data_destroy(l_tcp); + } + + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_state &= (~(OPJ_UINT32)J2K_STATE_DATA); + + if (opj_stream_get_number_byte_left(p_stream) == 0 + && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) { + return OPJ_TRUE; + } + + if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) { + if (opj_stream_read_data(p_stream, l_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; } - /* Bottom */ - if ((OPJ_UINT32)p_end_y < l_image->y0) { - opj_event_msg(p_manager, EVT_ERROR, - "Bottom position of the decoded area (region_y1=%d) is outside the image area (YOsiz=%d).\n", - p_end_y, l_image->y0); - return OPJ_FALSE; + opj_read_bytes(l_data, &l_current_marker, 2); + + if (l_current_marker == J2K_MS_EOC) { + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC; + } else if (l_current_marker != J2K_MS_SOT) { + if (opj_stream_get_number_byte_left(p_stream) == 0) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + opj_event_msg(p_manager, EVT_WARNING, "Stream does not end with EOC\n"); + return OPJ_TRUE; + } + opj_event_msg(p_manager, EVT_ERROR, "Stream too short, expected SOT\n"); + return OPJ_FALSE; } - if ((OPJ_UINT32)p_end_y > l_image->y1){ - opj_event_msg(p_manager, EVT_WARNING, - "Bottom position of the decoded area (region_y1=%d) is outside the image area (Ysiz=%d).\n", - p_end_y, l_image->y1); - p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; - p_image->y1 = l_image->y1; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, + opj_image_t* p_output_image) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_width_src, l_height_src; + OPJ_UINT32 l_width_dest, l_height_dest; + OPJ_INT32 l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src; + OPJ_SIZE_T l_start_offset_src; + OPJ_UINT32 l_start_x_dest, l_start_y_dest; + OPJ_UINT32 l_x0_dest, l_y0_dest, l_x1_dest, l_y1_dest; + OPJ_SIZE_T l_start_offset_dest; + + opj_image_comp_t * l_img_comp_src = 00; + opj_image_comp_t * l_img_comp_dest = 00; + + opj_tcd_tilecomp_t * l_tilec = 00; + opj_image_t * l_image_src = 00; + OPJ_INT32 * l_dest_ptr; + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_image_src = p_tcd->image; + l_img_comp_src = l_image_src->comps; + + l_img_comp_dest = p_output_image->comps; + + for (i = 0; i < l_image_src->numcomps; + i++, ++l_img_comp_dest, ++l_img_comp_src, ++l_tilec) { + OPJ_INT32 res_x0, res_x1, res_y0, res_y1; + OPJ_UINT32 src_data_stride; + const OPJ_INT32* p_src_data; + + /* Copy info from decoded comp image to output image */ + l_img_comp_dest->resno_decoded = l_img_comp_src->resno_decoded; + + if (p_tcd->whole_tile_decoding) { + opj_tcd_resolution_t* l_res = l_tilec->resolutions + + l_img_comp_src->resno_decoded; + res_x0 = l_res->x0; + res_y0 = l_res->y0; + res_x1 = l_res->x1; + res_y1 = l_res->y1; + src_data_stride = (OPJ_UINT32)( + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x1 - + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x0); + p_src_data = l_tilec->data; + } else { + opj_tcd_resolution_t* l_res = l_tilec->resolutions + + l_img_comp_src->resno_decoded; + res_x0 = (OPJ_INT32)l_res->win_x0; + res_y0 = (OPJ_INT32)l_res->win_y0; + res_x1 = (OPJ_INT32)l_res->win_x1; + res_y1 = (OPJ_INT32)l_res->win_y1; + src_data_stride = l_res->win_x1 - l_res->win_x0; + p_src_data = l_tilec->data_win; } - else{ - p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv(p_end_y - (OPJ_INT32)l_cp->ty0, (OPJ_INT32)l_cp->tdy); - p_image->y1 = (OPJ_UINT32)p_end_y; + + if (p_src_data == NULL) { + /* Happens for partial component decoding */ + continue; } - /* ----- */ - p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1; + l_width_src = (OPJ_UINT32)(res_x1 - res_x0); + l_height_src = (OPJ_UINT32)(res_y1 - res_y0); - l_img_comp = p_image->comps; - for (it_comp=0; it_comp < p_image->numcomps; ++it_comp) - { - OPJ_INT32 l_h,l_w; - l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); - l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); - l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); - l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); + /* Current tile component size*/ + /*if (i == 0) { + fprintf(stdout, "SRC: l_res_x0=%d, l_res_x1=%d, l_res_y0=%d, l_res_y1=%d\n", + res_x0, res_x1, res_y0, res_y1); + }*/ + - l_w = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor) - - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor); - if (l_w < 0){ - opj_event_msg(p_manager, EVT_ERROR, - "Size x of the decoded component image is incorrect (comp[%d].w=%d).\n", - it_comp, l_w); - return OPJ_FALSE; - } - l_img_comp->w = (OPJ_UINT32)l_w; + /* Border of the current output component*/ + l_x0_dest = opj_uint_ceildivpow2(l_img_comp_dest->x0, l_img_comp_dest->factor); + l_y0_dest = opj_uint_ceildivpow2(l_img_comp_dest->y0, l_img_comp_dest->factor); + l_x1_dest = l_x0_dest + + l_img_comp_dest->w; /* can't overflow given that image->x1 is uint32 */ + l_y1_dest = l_y0_dest + l_img_comp_dest->h; - l_h = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor) - - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor); - if (l_h < 0){ - opj_event_msg(p_manager, EVT_ERROR, - "Size y of the decoded component image is incorrect (comp[%d].h=%d).\n", - it_comp, l_h); - return OPJ_FALSE; - } - l_img_comp->h = (OPJ_UINT32)l_h; + /*if (i == 0) { + fprintf(stdout, "DEST: l_x0_dest=%d, l_x1_dest=%d, l_y0_dest=%d, l_y1_dest=%d (%d)\n", + l_x0_dest, l_x1_dest, l_y0_dest, l_y1_dest, l_img_comp_dest->factor ); + }*/ - l_img_comp++; + /*-----*/ + /* Compute the area (l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src) + * of the input buffer (decoded tile component) which will be move + * in the output buffer. Compute the area of the output buffer (l_start_x_dest, + * l_start_y_dest, l_width_dest, l_height_dest) which will be modified + * by this input area. + * */ + assert(res_x0 >= 0); + assert(res_x1 >= 0); + + /* Prevent bad casting to unsigned values in the subsequent lines. */ + if ( res_x0 < 0 || res_x1 < 0 || res_y0 < 0 || res_y1 < 0 ) { + return OPJ_FALSE; } - opj_event_msg( p_manager, EVT_INFO,"Setting decoding area to %d,%d,%d,%d\n", - p_image->x0, p_image->y0, p_image->x1, p_image->y1); + if (l_x0_dest < (OPJ_UINT32)res_x0) { + l_start_x_dest = (OPJ_UINT32)res_x0 - l_x0_dest; + l_offset_x0_src = 0; - return OPJ_TRUE; -} + if (l_x1_dest >= (OPJ_UINT32)res_x1) { + l_width_dest = l_width_src; + l_offset_x1_src = 0; + } else { + l_width_dest = l_x1_dest - (OPJ_UINT32)res_x0 ; + l_offset_x1_src = (OPJ_INT32)(l_width_src - l_width_dest); + } + } else { + l_start_x_dest = 0U; + l_offset_x0_src = (OPJ_INT32)l_x0_dest - res_x0; -opj_j2k_t* opj_j2k_create_decompress(void) -{ - opj_j2k_t *l_j2k = (opj_j2k_t*) opj_calloc(1,sizeof(opj_j2k_t)); - if (!l_j2k) { - return 00; + if (l_x1_dest >= (OPJ_UINT32)res_x1) { + l_width_dest = l_width_src - (OPJ_UINT32)l_offset_x0_src; + l_offset_x1_src = 0; + } else { + l_width_dest = l_img_comp_dest->w ; + l_offset_x1_src = res_x1 - (OPJ_INT32)l_x1_dest; + } } - l_j2k->m_is_decoder = 1; - l_j2k->m_cp.m_is_decoder = 1; + if (l_y0_dest < (OPJ_UINT32)res_y0) { + l_start_y_dest = (OPJ_UINT32)res_y0 - l_y0_dest; + l_offset_y0_src = 0; -#ifdef OPJ_DISABLE_TPSOT_FIX - l_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; -#endif + if (l_y1_dest >= (OPJ_UINT32)res_y1) { + l_height_dest = l_height_src; + l_offset_y1_src = 0; + } else { + l_height_dest = l_y1_dest - (OPJ_UINT32)res_y0 ; + l_offset_y1_src = (OPJ_INT32)(l_height_src - l_height_dest); + } + } else { + l_start_y_dest = 0U; + l_offset_y0_src = (OPJ_INT32)l_y0_dest - res_y0; - l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_calloc(1,sizeof(opj_tcp_t)); - if (!l_j2k->m_specific_param.m_decoder.m_default_tcp) { - opj_j2k_destroy(l_j2k); - return 00; + if (l_y1_dest >= (OPJ_UINT32)res_y1) { + l_height_dest = l_height_src - (OPJ_UINT32)l_offset_y0_src; + l_offset_y1_src = 0; + } else { + l_height_dest = l_img_comp_dest->h ; + l_offset_y1_src = res_y1 - (OPJ_INT32)l_y1_dest; + } } - l_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE *) opj_calloc(1,OPJ_J2K_DEFAULT_HEADER_SIZE); - if (! l_j2k->m_specific_param.m_decoder.m_header_data) { - opj_j2k_destroy(l_j2k); - return 00; + if ((l_offset_x0_src < 0) || (l_offset_y0_src < 0) || (l_offset_x1_src < 0) || + (l_offset_y1_src < 0)) { + return OPJ_FALSE; + } + /* testcase 2977.pdf.asan.67.2198 */ + if ((OPJ_INT32)l_width_dest < 0 || (OPJ_INT32)l_height_dest < 0) { + return OPJ_FALSE; } + /*-----*/ + + /* Compute the input buffer offset */ + l_start_offset_src = (OPJ_SIZE_T)l_offset_x0_src + (OPJ_SIZE_T)l_offset_y0_src + * (OPJ_SIZE_T)src_data_stride; + + /* Compute the output buffer offset */ + l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest + * (OPJ_SIZE_T)l_img_comp_dest->w; + + /* Allocate output component buffer if necessary */ + if (l_img_comp_dest->data == NULL && + l_start_offset_src == 0 && l_start_offset_dest == 0 && + src_data_stride == l_img_comp_dest->w && + l_width_dest == l_img_comp_dest->w && + l_height_dest == l_img_comp_dest->h) { + /* If the final image matches the tile buffer, then borrow it */ + /* directly to save a copy */ + if (p_tcd->whole_tile_decoding) { + l_img_comp_dest->data = l_tilec->data; + l_tilec->data = NULL; + } else { + l_img_comp_dest->data = l_tilec->data_win; + l_tilec->data_win = NULL; + } + continue; + } else if (l_img_comp_dest->data == NULL) { + OPJ_SIZE_T l_width = l_img_comp_dest->w; + OPJ_SIZE_T l_height = l_img_comp_dest->h; + + if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) || + l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) { + /* would overflow */ + return OPJ_FALSE; + } + l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height * + sizeof(OPJ_INT32)); + if (! l_img_comp_dest->data) { + return OPJ_FALSE; + } - l_j2k->m_specific_param.m_decoder.m_header_data_size = OPJ_J2K_DEFAULT_HEADER_SIZE; + if (l_img_comp_dest->w != l_width_dest || + l_img_comp_dest->h != l_height_dest) { + memset(l_img_comp_dest->data, 0, + (OPJ_SIZE_T)l_img_comp_dest->w * l_img_comp_dest->h * sizeof(OPJ_INT32)); + } + } - l_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = -1 ; + /* Move the output buffer to the first place where we will write*/ + l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest; - l_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = 0 ; + { + const OPJ_INT32 * l_src_ptr = p_src_data; + l_src_ptr += l_start_offset_src; - /* codestream index creation */ - l_j2k->cstr_index = opj_j2k_create_cstr_index(); - if (!l_j2k->cstr_index){ - opj_j2k_destroy(l_j2k); - return 00; + for (j = 0; j < l_height_dest; ++j) { + memcpy(l_dest_ptr, l_src_ptr, l_width_dest * sizeof(OPJ_INT32)); + l_dest_ptr += l_img_comp_dest->w; + l_src_ptr += src_data_stride; + } } - /* validation list creation */ - l_j2k->m_validation_list = opj_procedure_list_create(); - if (! l_j2k->m_validation_list) { - opj_j2k_destroy(l_j2k); - return 00; - } - /* execution list creation */ - l_j2k->m_procedure_list = opj_procedure_list_create(); - if (! l_j2k->m_procedure_list) { - opj_j2k_destroy(l_j2k); - return 00; - } + } - return l_j2k; + return OPJ_TRUE; } -static opj_codestream_index_t* opj_j2k_create_cstr_index(void) +static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image, + opj_event_mgr_t * p_manager) { - opj_codestream_index_t* cstr_index = (opj_codestream_index_t*) - opj_calloc(1,sizeof(opj_codestream_index_t)); - if (!cstr_index) - return NULL; + OPJ_UINT32 it_comp; + OPJ_INT32 l_comp_x1, l_comp_y1; + opj_image_comp_t* l_img_comp = NULL; - cstr_index->maxmarknum = 100; - cstr_index->marknum = 0; - cstr_index->marker = (opj_marker_info_t*) - opj_calloc(cstr_index->maxmarknum, sizeof(opj_marker_info_t)); - if (!cstr_index-> marker) { - opj_free(cstr_index); - return NULL; + l_img_comp = p_image->comps; + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); + + OPJ_INT32 l_1 = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor); + OPJ_INT32 l_2 = opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor); + if (l_1 < l_2) { + opj_event_msg(p_manager, EVT_ERROR, + "Size x of the decoded component image is incorrect (comp[%d].w<0).\n", + it_comp); + return OPJ_FALSE; } + l_img_comp->w = (OPJ_UINT32)(l_1-l_2); - cstr_index->tile_index = NULL; + l_1 = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor); + l_2 = opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor); + if (l_1 < l_2) { + opj_event_msg(p_manager, EVT_ERROR, + "Size y of the decoded component image is incorrect (comp[%d].h<0).\n", + it_comp); + return OPJ_FALSE; + } + l_img_comp->h = (OPJ_UINT32)(l_1-l_2); + + l_img_comp++; + } - return cstr_index; + return OPJ_TRUE; } -static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size ( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no ) +OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager) { - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; - - /* preconditions */ - assert(p_j2k != 00); + OPJ_UINT32 i; + OPJ_BOOL* already_mapped; - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_tile_no]; - l_tccp = &l_tcp->tccps[p_comp_no]; + if (p_j2k->m_private_image == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_read_header() should be called before " + "opj_set_decoded_components().\n"); + return OPJ_FALSE; + } - /* preconditions again */ - assert(p_tile_no < (l_cp->tw * l_cp->th)); - assert(p_comp_no < p_j2k->m_private_image->numcomps); + already_mapped = (OPJ_BOOL*) opj_calloc(sizeof(OPJ_BOOL), + p_j2k->m_private_image->numcomps); + if (already_mapped == NULL) { + return OPJ_FALSE; + } - if (l_tccp->csty & J2K_CCP_CSTY_PRT) { - return 5 + l_tccp->numresolutions; + for (i = 0; i < numcomps; i++) { + if (comps_indices[i] >= p_j2k->m_private_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid component index: %u\n", + comps_indices[i]); + opj_free(already_mapped); + return OPJ_FALSE; } - else { - return 5; + if (already_mapped[comps_indices[i]]) { + opj_event_msg(p_manager, EVT_ERROR, + "Component index %u used several times\n", + comps_indices[i]); + opj_free(already_mapped); + return OPJ_FALSE; + } + already_mapped[comps_indices[i]] = OPJ_TRUE; + } + opj_free(already_mapped); + + opj_free(p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode); + if (numcomps) { + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = + (OPJ_UINT32*) opj_malloc(numcomps * sizeof(OPJ_UINT32)); + if (p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode == NULL) { + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = 0; + return OPJ_FALSE; } + memcpy(p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode, + comps_indices, + numcomps * sizeof(OPJ_UINT32)); + } else { + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = NULL; + } + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = numcomps; + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_SPCod_SPCoc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager ) + +OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 i; - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_header_size != 00); - assert(p_manager != 00); - assert(p_data != 00); - - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_tile_no]; - l_tccp = &l_tcp->tccps[p_comp_no]; - - /* preconditions again */ - assert(p_tile_no < (l_cp->tw * l_cp->th)); - assert(p_comp_no <(p_j2k->m_private_image->numcomps)); - - if (*p_header_size < 5) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n"); - return OPJ_FALSE; - } + opj_cp_t * l_cp = &(p_j2k->m_cp); + opj_image_t * l_image = p_j2k->m_private_image; + OPJ_BOOL ret; + OPJ_UINT32 it_comp; - opj_write_bytes(p_data,l_tccp->numresolutions - 1, 1); /* SPcoc (D) */ - ++p_data; + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + p_j2k->m_cp.tcps[0].m_data != NULL) { + /* In the case of a single-tiled image whose codestream we have already */ + /* ingested, go on */ + } + /* Check if we are read the main header */ + else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { + opj_event_msg(p_manager, EVT_ERROR, + "Need to decode the main header before begin to decode the remaining codestream.\n"); + return OPJ_FALSE; + } - opj_write_bytes(p_data,l_tccp->cblkw - 2, 1); /* SPcoc (E) */ - ++p_data; + /* Update the comps[].factor member of the output image with the one */ + /* of m_reduce */ + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + p_image->comps[it_comp].factor = p_j2k->m_cp.m_specific_param.m_dec.m_reduce; + } - opj_write_bytes(p_data,l_tccp->cblkh - 2, 1); /* SPcoc (F) */ - ++p_data; + if (!p_start_x && !p_start_y && !p_end_x && !p_end_y) { + opj_event_msg(p_manager, EVT_INFO, + "No decoded area parameters, set the decoded area to the whole image\n"); - opj_write_bytes(p_data,l_tccp->cblksty, 1); /* SPcoc (G) */ - ++p_data; + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; - opj_write_bytes(p_data,l_tccp->qmfbid, 1); /* SPcoc (H) */ - ++p_data; + p_image->x0 = l_image->x0; + p_image->y0 = l_image->y0; + p_image->x1 = l_image->x1; + p_image->y1 = l_image->y1; - *p_header_size = *p_header_size - 5; + return opj_j2k_update_image_dimensions(p_image, p_manager); + } - if (l_tccp->csty & J2K_CCP_CSTY_PRT) { + /* ----- */ + /* Check if the positions provided by the user are correct */ - if (*p_header_size < l_tccp->numresolutions) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n"); - return OPJ_FALSE; - } + /* Left */ + if (p_start_x < 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Left position of the decoded area (region_x0=%d) should be >= 0.\n", + p_start_x); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_x > l_image->x1) { + opj_event_msg(p_manager, EVT_ERROR, + "Left position of the decoded area (region_x0=%d) is outside the image area (Xsiz=%d).\n", + p_start_x, l_image->x1); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_x < l_image->x0) { + opj_event_msg(p_manager, EVT_WARNING, + "Left position of the decoded area (region_x0=%d) is outside the image area (XOsiz=%d).\n", + p_start_x, l_image->x0); + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_image->x0 = l_image->x0; + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = ((OPJ_UINT32)p_start_x - + l_cp->tx0) / l_cp->tdx; + p_image->x0 = (OPJ_UINT32)p_start_x; + } - for (i = 0; i < l_tccp->numresolutions; ++i) { - opj_write_bytes(p_data,l_tccp->prcw[i] + (l_tccp->prch[i] << 4), 1); /* SPcoc (I_i) */ - ++p_data; - } + /* Up */ + if (p_start_y < 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Up position of the decoded area (region_y0=%d) should be >= 0.\n", + p_start_y); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_y > l_image->y1) { + opj_event_msg(p_manager, EVT_ERROR, + "Up position of the decoded area (region_y0=%d) is outside the image area (Ysiz=%d).\n", + p_start_y, l_image->y1); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_y < l_image->y0) { + opj_event_msg(p_manager, EVT_WARNING, + "Up position of the decoded area (region_y0=%d) is outside the image area (YOsiz=%d).\n", + p_start_y, l_image->y0); + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + p_image->y0 = l_image->y0; + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_y = ((OPJ_UINT32)p_start_y - + l_cp->ty0) / l_cp->tdy; + p_image->y0 = (OPJ_UINT32)p_start_y; + } - *p_header_size = *p_header_size - l_tccp->numresolutions; - } + /* Right */ + if (p_end_x <= 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Right position of the decoded area (region_x1=%d) should be > 0.\n", + p_end_x); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_end_x < l_image->x0) { + opj_event_msg(p_manager, EVT_ERROR, + "Right position of the decoded area (region_x1=%d) is outside the image area (XOsiz=%d).\n", + p_end_x, l_image->x0); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_end_x > l_image->x1) { + opj_event_msg(p_manager, EVT_WARNING, + "Right position of the decoded area (region_x1=%d) is outside the image area (Xsiz=%d).\n", + p_end_x, l_image->x1); + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_image->x1 = l_image->x1; + } else { + p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv( + p_end_x - (OPJ_INT32)l_cp->tx0, (OPJ_INT32)l_cp->tdx); + p_image->x1 = (OPJ_UINT32)p_end_x; + } - return OPJ_TRUE; -} + /* Bottom */ + if (p_end_y <= 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Bottom position of the decoded area (region_y1=%d) should be > 0.\n", + p_end_y); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_end_y < l_image->y0) { + opj_event_msg(p_manager, EVT_ERROR, + "Bottom position of the decoded area (region_y1=%d) is outside the image area (YOsiz=%d).\n", + p_end_y, l_image->y0); + return OPJ_FALSE; + } + if ((OPJ_UINT32)p_end_y > l_image->y1) { + opj_event_msg(p_manager, EVT_WARNING, + "Bottom position of the decoded area (region_y1=%d) is outside the image area (Ysiz=%d).\n", + p_end_y, l_image->y1); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + p_image->y1 = l_image->y1; + } else { + p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv( + p_end_y - (OPJ_INT32)l_cp->ty0, (OPJ_INT32)l_cp->tdy); + p_image->y1 = (OPJ_UINT32)p_end_y; + } + /* ----- */ -static OPJ_BOOL opj_j2k_read_SPCod_SPCoc( opj_j2k_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - opj_event_mgr_t * p_manager) -{ - OPJ_UINT32 i, l_tmp; - opj_cp_t *l_cp = NULL; - opj_tcp_t *l_tcp = NULL; - opj_tccp_t *l_tccp = NULL; - OPJ_BYTE * l_current_ptr = NULL; + p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_header_data != 00); + ret = opj_j2k_update_image_dimensions(p_image, p_manager); - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; + if (ret) { + opj_event_msg(p_manager, EVT_INFO, "Setting decoding area to %d,%d,%d,%d\n", + p_image->x0, p_image->y0, p_image->x1, p_image->y1); + } - /* precondition again */ - if (compno >= p_j2k->m_private_image->numcomps) { - return OPJ_FALSE; - } + return ret; +} - l_tccp = &l_tcp->tccps[compno]; - l_current_ptr = p_header_data; +opj_j2k_t* opj_j2k_create_decompress(void) +{ + opj_j2k_t *l_j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); + if (!l_j2k) { + return 00; + } - /* make sure room is sufficient */ - if (*p_header_size < 5) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); - return OPJ_FALSE; - } + l_j2k->m_is_decoder = 1; + l_j2k->m_cp.m_is_decoder = 1; + /* in the absence of JP2 boxes, consider different bit depth / sign */ + /* per component is allowed */ + l_j2k->m_cp.allow_different_bit_depth_sign = 1; - opj_read_bytes(l_current_ptr, &l_tccp->numresolutions ,1); /* SPcox (D) */ - ++l_tccp->numresolutions; /* tccp->numresolutions = read() + 1 */ - if (l_tccp->numresolutions > OPJ_J2K_MAXRLVLS) { - opj_event_msg(p_manager, EVT_ERROR, - "Invalid value for numresolutions : %d, max value is set in openjpeg.h at %d\n", - l_tccp->numresolutions, OPJ_J2K_MAXRLVLS); - return OPJ_FALSE; - } - ++l_current_ptr; +#ifdef OPJ_DISABLE_TPSOT_FIX + l_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; +#endif - /* If user wants to remove more resolutions than the codestream contains, return error */ - if (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) { - opj_event_msg(p_manager, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number " - "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); - p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/* FIXME J2K_DEC_STATE_ERR;*/ - return OPJ_FALSE; - } + l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_calloc(1, + sizeof(opj_tcp_t)); + if (!l_j2k->m_specific_param.m_decoder.m_default_tcp) { + opj_j2k_destroy(l_j2k); + return 00; + } - opj_read_bytes(l_current_ptr,&l_tccp->cblkw ,1); /* SPcoc (E) */ - ++l_current_ptr; - l_tccp->cblkw += 2; + l_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE *) opj_calloc(1, + OPJ_J2K_DEFAULT_HEADER_SIZE); + if (! l_j2k->m_specific_param.m_decoder.m_header_data) { + opj_j2k_destroy(l_j2k); + return 00; + } - opj_read_bytes(l_current_ptr,&l_tccp->cblkh ,1); /* SPcoc (F) */ - ++l_current_ptr; - l_tccp->cblkh += 2; + l_j2k->m_specific_param.m_decoder.m_header_data_size = + OPJ_J2K_DEFAULT_HEADER_SIZE; - if ((l_tccp->cblkw > 10) || (l_tccp->cblkh > 10) || ((l_tccp->cblkw + l_tccp->cblkh) > 12)) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element, Invalid cblkw/cblkh combination\n"); - return OPJ_FALSE; - } - + l_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = -1 ; - opj_read_bytes(l_current_ptr,&l_tccp->cblksty ,1); /* SPcoc (G) */ - ++l_current_ptr; + l_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = 0 ; - opj_read_bytes(l_current_ptr,&l_tccp->qmfbid ,1); /* SPcoc (H) */ - ++l_current_ptr; + /* codestream index creation */ + l_j2k->cstr_index = opj_j2k_create_cstr_index(); + if (!l_j2k->cstr_index) { + opj_j2k_destroy(l_j2k); + return 00; + } - *p_header_size = *p_header_size - 5; + /* validation list creation */ + l_j2k->m_validation_list = opj_procedure_list_create(); + if (! l_j2k->m_validation_list) { + opj_j2k_destroy(l_j2k); + return 00; + } - /* use custom precinct size ? */ - if (l_tccp->csty & J2K_CCP_CSTY_PRT) { - if (*p_header_size < l_tccp->numresolutions) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); - return OPJ_FALSE; - } + /* execution list creation */ + l_j2k->m_procedure_list = opj_procedure_list_create(); + if (! l_j2k->m_procedure_list) { + opj_j2k_destroy(l_j2k); + return 00; + } - for (i = 0; i < l_tccp->numresolutions; ++i) { - opj_read_bytes(l_current_ptr,&l_tmp ,1); /* SPcoc (I_i) */ - ++l_current_ptr; - /* Precinct exponent 0 is only allowed for lowest resolution level (Table A.21) */ - if ((i != 0) && (((l_tmp & 0xf) == 0) || ((l_tmp >> 4) == 0))) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct size\n"); - return OPJ_FALSE; - } - l_tccp->prcw[i] = l_tmp & 0xf; - l_tccp->prch[i] = l_tmp >> 4; - } + l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count()); + if (!l_j2k->m_tp) { + l_j2k->m_tp = opj_thread_pool_create(0); + } + if (!l_j2k->m_tp) { + opj_j2k_destroy(l_j2k); + return NULL; + } - *p_header_size = *p_header_size - l_tccp->numresolutions; - } - else { - /* set default size for the precinct width and height */ - for (i = 0; i < l_tccp->numresolutions; ++i) { - l_tccp->prcw[i] = 15; - l_tccp->prch[i] = 15; - } - } + return l_j2k; +} -#ifdef WIP_REMOVE_MSD - /* INDEX >> */ - if (p_j2k->cstr_info && compno == 0) { - OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32); +static opj_codestream_index_t* opj_j2k_create_cstr_index(void) +{ + opj_codestream_index_t* cstr_index = (opj_codestream_index_t*) + opj_calloc(1, sizeof(opj_codestream_index_t)); + if (!cstr_index) { + return NULL; + } - p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkh = l_tccp->cblkh; - p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkw = l_tccp->cblkw; - p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].numresolutions = l_tccp->numresolutions; - p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblksty = l_tccp->cblksty; - p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].qmfbid = l_tccp->qmfbid; + cstr_index->maxmarknum = 100; + cstr_index->marknum = 0; + cstr_index->marker = (opj_marker_info_t*) + opj_calloc(cstr_index->maxmarknum, sizeof(opj_marker_info_t)); + if (!cstr_index-> marker) { + opj_free(cstr_index); + return NULL; + } - memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdx,l_tccp->prcw, l_data_size); - memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdy,l_tccp->prch, l_data_size); - } - /* << INDEX */ -#endif + cstr_index->tile_index = NULL; - return OPJ_TRUE; + return cstr_index; } -static void opj_j2k_copy_tile_component_parameters( opj_j2k_t *p_j2k ) +static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no) { - /* loop */ - OPJ_UINT32 i; - opj_cp_t *l_cp = NULL; - opj_tcp_t *l_tcp = NULL; - opj_tccp_t *l_ref_tccp = NULL, *l_copied_tccp = NULL; - OPJ_UINT32 l_prc_size; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; - /* preconditions */ - assert(p_j2k != 00); + /* preconditions */ + assert(p_j2k != 00); - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? /* FIXME J2K_DEC_STATE_TPH*/ - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; - l_ref_tccp = &l_tcp->tccps[0]; - l_copied_tccp = l_ref_tccp + 1; - l_prc_size = l_ref_tccp->numresolutions * (OPJ_UINT32)sizeof(OPJ_UINT32); + /* preconditions again */ + assert(p_tile_no < (l_cp->tw * l_cp->th)); + assert(p_comp_no < p_j2k->m_private_image->numcomps); - for (i=1; i<p_j2k->m_private_image->numcomps; ++i) { - l_copied_tccp->numresolutions = l_ref_tccp->numresolutions; - l_copied_tccp->cblkw = l_ref_tccp->cblkw; - l_copied_tccp->cblkh = l_ref_tccp->cblkh; - l_copied_tccp->cblksty = l_ref_tccp->cblksty; - l_copied_tccp->qmfbid = l_ref_tccp->qmfbid; - memcpy(l_copied_tccp->prcw,l_ref_tccp->prcw,l_prc_size); - memcpy(l_copied_tccp->prch,l_ref_tccp->prch,l_prc_size); - ++l_copied_tccp; - } + if (l_tccp->csty & J2K_CCP_CSTY_PRT) { + return 5 + l_tccp->numresolutions; + } else { + return 5; + } } -static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no ) +static OPJ_BOOL opj_j2k_compare_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) { - OPJ_UINT32 l_num_bands; - - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; - - /* preconditions */ - assert(p_j2k != 00); + OPJ_UINT32 i; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_tccp0 = NULL; + opj_tccp_t *l_tccp1 = NULL; - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_tile_no]; - l_tccp = &l_tcp->tccps[p_comp_no]; + /* preconditions */ + assert(p_j2k != 00); - /* preconditions again */ - assert(p_tile_no < l_cp->tw * l_cp->th); - assert(p_comp_no < p_j2k->m_private_image->numcomps); + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp0 = &l_tcp->tccps[p_first_comp_no]; + l_tccp1 = &l_tcp->tccps[p_second_comp_no]; - l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (l_tccp->numresolutions * 3 - 2); + if (l_tccp0->numresolutions != l_tccp1->numresolutions) { + return OPJ_FALSE; + } + if (l_tccp0->cblkw != l_tccp1->cblkw) { + return OPJ_FALSE; + } + if (l_tccp0->cblkh != l_tccp1->cblkh) { + return OPJ_FALSE; + } + if (l_tccp0->cblksty != l_tccp1->cblksty) { + return OPJ_FALSE; + } + if (l_tccp0->qmfbid != l_tccp1->qmfbid) { + return OPJ_FALSE; + } + if ((l_tccp0->csty & J2K_CCP_CSTY_PRT) != (l_tccp1->csty & J2K_CCP_CSTY_PRT)) { + return OPJ_FALSE; + } - if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { - return 1 + l_num_bands; + for (i = 0U; i < l_tccp0->numresolutions; ++i) { + if (l_tccp0->prcw[i] != l_tccp1->prcw[i]) { + return OPJ_FALSE; } - else { - return 1 + 2*l_num_bands; + if (l_tccp0->prch[i] != l_tccp1->prch[i]) { + return OPJ_FALSE; } + } + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_SQcd_SQcc( opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 l_header_size; - OPJ_UINT32 l_band_no, l_num_bands; - OPJ_UINT32 l_expn,l_mant; - - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; + OPJ_UINT32 i; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_header_size != 00); + assert(p_manager != 00); + assert(p_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + /* preconditions again */ + assert(p_tile_no < (l_cp->tw * l_cp->th)); + assert(p_comp_no < (p_j2k->m_private_image->numcomps)); + + if (*p_header_size < 5) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n"); + return OPJ_FALSE; + } - /* preconditions */ - assert(p_j2k != 00); - assert(p_header_size != 00); - assert(p_manager != 00); - assert(p_data != 00); + opj_write_bytes(p_data, l_tccp->numresolutions - 1, 1); /* SPcoc (D) */ + ++p_data; - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_tile_no]; - l_tccp = &l_tcp->tccps[p_comp_no]; + opj_write_bytes(p_data, l_tccp->cblkw - 2, 1); /* SPcoc (E) */ + ++p_data; - /* preconditions again */ - assert(p_tile_no < l_cp->tw * l_cp->th); - assert(p_comp_no <p_j2k->m_private_image->numcomps); + opj_write_bytes(p_data, l_tccp->cblkh - 2, 1); /* SPcoc (F) */ + ++p_data; - l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (l_tccp->numresolutions * 3 - 2); + opj_write_bytes(p_data, l_tccp->cblksty, + 1); /* SPcoc (G) */ + ++p_data; - if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { - l_header_size = 1 + l_num_bands; + opj_write_bytes(p_data, l_tccp->qmfbid, + 1); /* SPcoc (H) */ + ++p_data; - if (*p_header_size < l_header_size) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n"); - return OPJ_FALSE; - } + *p_header_size = *p_header_size - 5; - opj_write_bytes(p_data,l_tccp->qntsty + (l_tccp->numgbits << 5), 1); /* Sqcx */ - ++p_data; + if (l_tccp->csty & J2K_CCP_CSTY_PRT) { - for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { - l_expn = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].expn; - opj_write_bytes(p_data, l_expn << 3, 1); /* SPqcx_i */ - ++p_data; - } + if (*p_header_size < l_tccp->numresolutions) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n"); + return OPJ_FALSE; } - else { - l_header_size = 1 + 2*l_num_bands; - - if (*p_header_size < l_header_size) { - opj_event_msg(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n"); - return OPJ_FALSE; - } - - opj_write_bytes(p_data,l_tccp->qntsty + (l_tccp->numgbits << 5), 1); /* Sqcx */ - ++p_data; - for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { - l_expn = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].expn; - l_mant = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].mant; - - opj_write_bytes(p_data, (l_expn << 11) + l_mant, 2); /* SPqcx_i */ - p_data += 2; - } + for (i = 0; i < l_tccp->numresolutions; ++i) { + opj_write_bytes(p_data, l_tccp->prcw[i] + (l_tccp->prch[i] << 4), + 1); /* SPcoc (I_i) */ + ++p_data; } - *p_header_size = *p_header_size - l_header_size; + *p_header_size = *p_header_size - l_tccp->numresolutions; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE* p_header_data, - OPJ_UINT32 * p_header_size, - opj_event_mgr_t * p_manager - ) -{ - /* loop*/ - OPJ_UINT32 l_band_no; - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_tccp = 00; - OPJ_BYTE * l_current_ptr = 00; - OPJ_UINT32 l_tmp, l_num_band; - - /* preconditions*/ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_header_data != 00); - - l_cp = &(p_j2k->m_cp); - /* come from tile part header or main header ?*/ - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? /*FIXME J2K_DEC_STATE_TPH*/ - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; - - /* precondition again*/ - if (p_comp_no >= p_j2k->m_private_image->numcomps) { - return OPJ_FALSE; - } +static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, l_tmp; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_tccp = NULL; + OPJ_BYTE * l_current_ptr = NULL; - l_tccp = &l_tcp->tccps[p_comp_no]; - l_current_ptr = p_header_data; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); - if (*p_header_size < 1) { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SQcd or SQcc element\n"); - return OPJ_FALSE; - } - *p_header_size -= 1; + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; - opj_read_bytes(l_current_ptr, &l_tmp ,1); /* Sqcx */ - ++l_current_ptr; + /* precondition again */ + if (compno >= p_j2k->m_private_image->numcomps) { + return OPJ_FALSE; + } - l_tccp->qntsty = l_tmp & 0x1f; - l_tccp->numgbits = l_tmp >> 5; - if (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { - l_num_band = 1; - } - else { - l_num_band = (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? - (*p_header_size) : - (*p_header_size) / 2; + assert(compno < p_j2k->m_private_image->numcomps); - if( l_num_band > OPJ_J2K_MAXBANDS ) { - opj_event_msg(p_manager, EVT_WARNING, "While reading CCP_QNTSTY element inside QCD or QCC marker segment, " - "number of subbands (%d) is greater to OPJ_J2K_MAXBANDS (%d). So we limit the number of elements stored to " - "OPJ_J2K_MAXBANDS (%d) and skip the rest. \n", l_num_band, OPJ_J2K_MAXBANDS, OPJ_J2K_MAXBANDS); - /*return OPJ_FALSE;*/ - } - } + l_tccp = &l_tcp->tccps[compno]; + l_current_ptr = p_header_data; -#ifdef USE_JPWL - if (l_cp->correct) { + /* make sure room is sufficient */ + if (*p_header_size < 5) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); + return OPJ_FALSE; + } - /* if JPWL is on, we check whether there are too many subbands */ - if (/*(l_num_band < 0) ||*/ (l_num_band >= OPJ_J2K_MAXBANDS)) { - opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: bad number of subbands in Sqcx (%d)\n", - l_num_band); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - /* we try to correct */ - l_num_band = 1; - opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n" - "- setting number of bands to %d => HYPOTHESIS!!!\n", - l_num_band); - }; + opj_read_bytes(l_current_ptr, &l_tccp->numresolutions, + 1); /* SPcox (D) */ + ++l_tccp->numresolutions; /* tccp->numresolutions = read() + 1 */ + if (l_tccp->numresolutions > OPJ_J2K_MAXRLVLS) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for numresolutions : %d, max value is set in openjpeg.h at %d\n", + l_tccp->numresolutions, OPJ_J2K_MAXRLVLS); + return OPJ_FALSE; + } + ++l_current_ptr; + + /* If user wants to remove more resolutions than the codestream contains, return error */ + if (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) { + opj_event_msg(p_manager, EVT_ERROR, + "Error decoding component %d.\nThe number of resolutions " + "to remove (%d) is greater or equal than the number " + "of resolutions of this component (%d)\nModify the cp_reduce parameter.\n\n", + compno, l_cp->m_specific_param.m_dec.m_reduce, l_tccp->numresolutions); + p_j2k->m_specific_param.m_decoder.m_state |= + 0x8000;/* FIXME J2K_DEC_STATE_ERR;*/ + return OPJ_FALSE; + } - }; -#endif /* USE_JPWL */ + opj_read_bytes(l_current_ptr, &l_tccp->cblkw, 1); /* SPcoc (E) */ + ++l_current_ptr; + l_tccp->cblkw += 2; - if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { - for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { - opj_read_bytes(l_current_ptr, &l_tmp ,1); /* SPqcx_i */ - ++l_current_ptr; - if (l_band_no < OPJ_J2K_MAXBANDS){ - l_tccp->stepsizes[l_band_no].expn = (OPJ_INT32)(l_tmp >> 3); - l_tccp->stepsizes[l_band_no].mant = 0; - } - } - *p_header_size = *p_header_size - l_num_band; - } - else { - for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { - opj_read_bytes(l_current_ptr, &l_tmp ,2); /* SPqcx_i */ - l_current_ptr+=2; - if (l_band_no < OPJ_J2K_MAXBANDS){ - l_tccp->stepsizes[l_band_no].expn = (OPJ_INT32)(l_tmp >> 11); - l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff; - } - } - *p_header_size = *p_header_size - 2*l_num_band; + opj_read_bytes(l_current_ptr, &l_tccp->cblkh, 1); /* SPcoc (F) */ + ++l_current_ptr; + l_tccp->cblkh += 2; + + if ((l_tccp->cblkw > 10) || (l_tccp->cblkh > 10) || + ((l_tccp->cblkw + l_tccp->cblkh) > 12)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading SPCod SPCoc element, Invalid cblkw/cblkh combination\n"); + return OPJ_FALSE; + } + + + opj_read_bytes(l_current_ptr, &l_tccp->cblksty, 1); /* SPcoc (G) */ + ++l_current_ptr; + if (l_tccp->cblksty & 0xC0U) { /* 2 msb are reserved, assume we can't read */ + opj_event_msg(p_manager, EVT_ERROR, + "Error reading SPCod SPCoc element, Invalid code-block style found\n"); + return OPJ_FALSE; + } + + opj_read_bytes(l_current_ptr, &l_tccp->qmfbid, 1); /* SPcoc (H) */ + ++l_current_ptr; + + *p_header_size = *p_header_size - 5; + + /* use custom precinct size ? */ + if (l_tccp->csty & J2K_CCP_CSTY_PRT) { + if (*p_header_size < l_tccp->numresolutions) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); + return OPJ_FALSE; } - /* Add Antonin : if scalar_derived -> compute other stepsizes */ - if (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { - for (l_band_no = 1; l_band_no < OPJ_J2K_MAXBANDS; l_band_no++) { - l_tccp->stepsizes[l_band_no].expn = - ((OPJ_INT32)(l_tccp->stepsizes[0].expn) - (OPJ_INT32)((l_band_no - 1) / 3) > 0) ? - (OPJ_INT32)(l_tccp->stepsizes[0].expn) - (OPJ_INT32)((l_band_no - 1) / 3) : 0; - l_tccp->stepsizes[l_band_no].mant = l_tccp->stepsizes[0].mant; - } + for (i = 0; i < l_tccp->numresolutions; ++i) { + opj_read_bytes(l_current_ptr, &l_tmp, 1); /* SPcoc (I_i) */ + ++l_current_ptr; + /* Precinct exponent 0 is only allowed for lowest resolution level (Table A.21) */ + if ((i != 0) && (((l_tmp & 0xf) == 0) || ((l_tmp >> 4) == 0))) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct size\n"); + return OPJ_FALSE; + } + l_tccp->prcw[i] = l_tmp & 0xf; + l_tccp->prch[i] = l_tmp >> 4; } - return OPJ_TRUE; + *p_header_size = *p_header_size - l_tccp->numresolutions; + } else { + /* set default size for the precinct width and height */ + for (i = 0; i < l_tccp->numresolutions; ++i) { + l_tccp->prcw[i] = 15; + l_tccp->prch[i] = 15; + } + } + +#ifdef WIP_REMOVE_MSD + /* INDEX >> */ + if (p_j2k->cstr_info && compno == 0) { + OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32); + + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkh = + l_tccp->cblkh; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkw = + l_tccp->cblkw; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].numresolutions + = l_tccp->numresolutions; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblksty = + l_tccp->cblksty; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].qmfbid = + l_tccp->qmfbid; + + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdx, l_tccp->prcw, + l_data_size); + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdy, l_tccp->prch, + l_data_size); + } + /* << INDEX */ +#endif + + return OPJ_TRUE; } -static void opj_j2k_copy_tile_quantization_parameters( opj_j2k_t *p_j2k ) +static void opj_j2k_copy_tile_component_parameters(opj_j2k_t *p_j2k) { - OPJ_UINT32 i; - opj_cp_t *l_cp = NULL; - opj_tcp_t *l_tcp = NULL; - opj_tccp_t *l_ref_tccp = NULL; - opj_tccp_t *l_copied_tccp = NULL; - OPJ_UINT32 l_size; + /* loop */ + OPJ_UINT32 i; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_ref_tccp = NULL, *l_copied_tccp = NULL; + OPJ_UINT32 l_prc_size; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) + ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + l_ref_tccp = &l_tcp->tccps[0]; + l_copied_tccp = l_ref_tccp + 1; + l_prc_size = l_ref_tccp->numresolutions * (OPJ_UINT32)sizeof(OPJ_UINT32); + + for (i = 1; i < p_j2k->m_private_image->numcomps; ++i) { + l_copied_tccp->numresolutions = l_ref_tccp->numresolutions; + l_copied_tccp->cblkw = l_ref_tccp->cblkw; + l_copied_tccp->cblkh = l_ref_tccp->cblkh; + l_copied_tccp->cblksty = l_ref_tccp->cblksty; + l_copied_tccp->qmfbid = l_ref_tccp->qmfbid; + memcpy(l_copied_tccp->prcw, l_ref_tccp->prcw, l_prc_size); + memcpy(l_copied_tccp->prch, l_ref_tccp->prch, l_prc_size); + ++l_copied_tccp; + } +} + +static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no) +{ + OPJ_UINT32 l_num_bands; - /* preconditions */ - assert(p_j2k != 00); + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; - l_cp = &(p_j2k->m_cp); - l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? - &l_cp->tcps[p_j2k->m_current_tile_number] : - p_j2k->m_specific_param.m_decoder.m_default_tcp; + /* preconditions */ + assert(p_j2k != 00); - l_ref_tccp = &l_tcp->tccps[0]; - l_copied_tccp = l_ref_tccp + 1; - l_size = OPJ_J2K_MAXBANDS * sizeof(opj_stepsize_t); + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; - for (i=1;i<p_j2k->m_private_image->numcomps;++i) { - l_copied_tccp->qntsty = l_ref_tccp->qntsty; - l_copied_tccp->numgbits = l_ref_tccp->numgbits; - memcpy(l_copied_tccp->stepsizes,l_ref_tccp->stepsizes,l_size); - ++l_copied_tccp; - } + /* preconditions again */ + assert(p_tile_no < l_cp->tw * l_cp->th); + assert(p_comp_no < p_j2k->m_private_image->numcomps); + + l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (l_tccp->numresolutions * 3 - 2); + + if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + return 1 + l_num_bands; + } else { + return 1 + 2 * l_num_bands; + } } -static void opj_j2k_dump_tile_info( opj_tcp_t * l_default_tile,OPJ_INT32 numcomps,FILE* out_stream) +static OPJ_BOOL opj_j2k_compare_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) { - if (l_default_tile) - { - OPJ_INT32 compno; - - fprintf(out_stream, "\t default tile {\n"); - fprintf(out_stream, "\t\t csty=%#x\n", l_default_tile->csty); - fprintf(out_stream, "\t\t prg=%#x\n", l_default_tile->prg); - fprintf(out_stream, "\t\t numlayers=%d\n", l_default_tile->numlayers); - fprintf(out_stream, "\t\t mct=%x\n", l_default_tile->mct); - - for (compno = 0; compno < numcomps; compno++) { - opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); - OPJ_UINT32 resno; - OPJ_INT32 bandno, numbands; - - /* coding style*/ - fprintf(out_stream, "\t\t comp %d {\n", compno); - fprintf(out_stream, "\t\t\t csty=%#x\n", l_tccp->csty); - fprintf(out_stream, "\t\t\t numresolutions=%d\n", l_tccp->numresolutions); - fprintf(out_stream, "\t\t\t cblkw=2^%d\n", l_tccp->cblkw); - fprintf(out_stream, "\t\t\t cblkh=2^%d\n", l_tccp->cblkh); - fprintf(out_stream, "\t\t\t cblksty=%#x\n", l_tccp->cblksty); - fprintf(out_stream, "\t\t\t qmfbid=%d\n", l_tccp->qmfbid); - - fprintf(out_stream, "\t\t\t preccintsize (w,h)="); - for (resno = 0; resno < l_tccp->numresolutions; resno++) { - fprintf(out_stream, "(%d,%d) ", l_tccp->prcw[resno], l_tccp->prch[resno]); - } - fprintf(out_stream, "\n"); - - /* quantization style*/ - fprintf(out_stream, "\t\t\t qntsty=%d\n", l_tccp->qntsty); - fprintf(out_stream, "\t\t\t numgbits=%d\n", l_tccp->numgbits); - fprintf(out_stream, "\t\t\t stepsizes (m,e)="); - numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (OPJ_INT32)l_tccp->numresolutions * 3 - 2; - for (bandno = 0; bandno < numbands; bandno++) { - fprintf(out_stream, "(%d,%d) ", l_tccp->stepsizes[bandno].mant, - l_tccp->stepsizes[bandno].expn); - } - fprintf(out_stream, "\n"); + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_tccp0 = NULL; + opj_tccp_t *l_tccp1 = NULL; + OPJ_UINT32 l_band_no, l_num_bands; + + /* preconditions */ + assert(p_j2k != 00); - /* RGN value*/ - fprintf(out_stream, "\t\t\t roishift=%d\n", l_tccp->roishift); + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp0 = &l_tcp->tccps[p_first_comp_no]; + l_tccp1 = &l_tcp->tccps[p_second_comp_no]; + + if (l_tccp0->qntsty != l_tccp1->qntsty) { + return OPJ_FALSE; + } + if (l_tccp0->numgbits != l_tccp1->numgbits) { + return OPJ_FALSE; + } + if (l_tccp0->qntsty == J2K_CCP_QNTSTY_SIQNT) { + l_num_bands = 1U; + } else { + l_num_bands = l_tccp0->numresolutions * 3U - 2U; + if (l_num_bands != (l_tccp1->numresolutions * 3U - 2U)) { + return OPJ_FALSE; + } + } - fprintf(out_stream, "\t\t }\n"); - } /*end of component of default tile*/ - fprintf(out_stream, "\t }\n"); /*end of default tile*/ + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + if (l_tccp0->stepsizes[l_band_no].expn != l_tccp1->stepsizes[l_band_no].expn) { + return OPJ_FALSE; + } + } + if (l_tccp0->qntsty != J2K_CCP_QNTSTY_NOQNT) { + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + if (l_tccp0->stepsizes[l_band_no].mant != l_tccp1->stepsizes[l_band_no].mant) { + return OPJ_FALSE; } + } + } + return OPJ_TRUE; } -void j2k_dump (opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream) + +static OPJ_BOOL opj_j2k_write_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager) { - /* Check if the flag is compatible with j2k file*/ - if ( (flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)){ - fprintf(out_stream, "Wrong flag\n"); - return; + OPJ_UINT32 l_header_size; + OPJ_UINT32 l_band_no, l_num_bands; + OPJ_UINT32 l_expn, l_mant; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_header_size != 00); + assert(p_manager != 00); + assert(p_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + /* preconditions again */ + assert(p_tile_no < l_cp->tw * l_cp->th); + assert(p_comp_no < p_j2k->m_private_image->numcomps); + + l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (l_tccp->numresolutions * 3 - 2); + + if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + l_header_size = 1 + l_num_bands; + + if (*p_header_size < l_header_size) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n"); + return OPJ_FALSE; } - /* Dump the image_header */ - if (flag & OPJ_IMG_INFO){ - if (p_j2k->m_private_image) - j2k_dump_image_header(p_j2k->m_private_image, 0, out_stream); + opj_write_bytes(p_data, l_tccp->qntsty + (l_tccp->numgbits << 5), + 1); /* Sqcx */ + ++p_data; + + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + l_expn = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].expn; + opj_write_bytes(p_data, l_expn << 3, 1); /* SPqcx_i */ + ++p_data; } + } else { + l_header_size = 1 + 2 * l_num_bands; - /* Dump the codestream info from main header */ - if (flag & OPJ_J2K_MH_INFO){ - opj_j2k_dump_MH_info(p_j2k, out_stream); + if (*p_header_size < l_header_size) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n"); + return OPJ_FALSE; } - /* Dump all tile/codestream info */ - if (flag & OPJ_J2K_TCH_INFO){ - OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - OPJ_UINT32 i; - opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; - for (i=0;i<l_nb_tiles;++i) { - opj_j2k_dump_tile_info( l_tcp,(OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream); - ++l_tcp; - } + + opj_write_bytes(p_data, l_tccp->qntsty + (l_tccp->numgbits << 5), + 1); /* Sqcx */ + ++p_data; + + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + l_expn = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].expn; + l_mant = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].mant; + + opj_write_bytes(p_data, (l_expn << 11) + l_mant, 2); /* SPqcx_i */ + p_data += 2; } + } + + *p_header_size = *p_header_size - l_header_size; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE* p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* loop*/ + OPJ_UINT32 l_band_no; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_BYTE * l_current_ptr = 00; + OPJ_UINT32 l_tmp, l_num_band; + + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_cp = &(p_j2k->m_cp); + /* come from tile part header or main header ?*/ + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) + ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + /* precondition again*/ + if (p_comp_no >= p_j2k->m_private_image->numcomps) { + return OPJ_FALSE; + } + + l_tccp = &l_tcp->tccps[p_comp_no]; + l_current_ptr = p_header_data; + + if (*p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SQcd or SQcc element\n"); + return OPJ_FALSE; + } + *p_header_size -= 1; + + opj_read_bytes(l_current_ptr, &l_tmp, 1); /* Sqcx */ + ++l_current_ptr; + + l_tccp->qntsty = l_tmp & 0x1f; + l_tccp->numgbits = l_tmp >> 5; + if (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { + l_num_band = 1; + } else { + l_num_band = (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? + (*p_header_size) : + (*p_header_size) / 2; + + if (l_num_band > OPJ_J2K_MAXBANDS) { + opj_event_msg(p_manager, EVT_WARNING, + "While reading CCP_QNTSTY element inside QCD or QCC marker segment, " + "number of subbands (%d) is greater to OPJ_J2K_MAXBANDS (%d). So we limit the number of elements stored to " + "OPJ_J2K_MAXBANDS (%d) and skip the rest. \n", l_num_band, OPJ_J2K_MAXBANDS, + OPJ_J2K_MAXBANDS); + /*return OPJ_FALSE;*/ + } + } + +#ifdef USE_JPWL + if (l_cp->correct) { + + /* if JPWL is on, we check whether there are too many subbands */ + if (/*(l_num_band < 0) ||*/ (l_num_band >= OPJ_J2K_MAXBANDS)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of subbands in Sqcx (%d)\n", + l_num_band); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + l_num_band = 1; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n" + "- setting number of bands to %d => HYPOTHESIS!!!\n", + l_num_band); + }; - /* Dump the codestream info of the current tile */ - if (flag & OPJ_J2K_TH_INFO){ + }; +#endif /* USE_JPWL */ + if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { + opj_read_bytes(l_current_ptr, &l_tmp, 1); /* SPqcx_i */ + ++l_current_ptr; + if (l_band_no < OPJ_J2K_MAXBANDS) { + l_tccp->stepsizes[l_band_no].expn = (OPJ_INT32)(l_tmp >> 3); + l_tccp->stepsizes[l_band_no].mant = 0; + } + } + *p_header_size = *p_header_size - l_num_band; + } else { + for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { + opj_read_bytes(l_current_ptr, &l_tmp, 2); /* SPqcx_i */ + l_current_ptr += 2; + if (l_band_no < OPJ_J2K_MAXBANDS) { + l_tccp->stepsizes[l_band_no].expn = (OPJ_INT32)(l_tmp >> 11); + l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff; + } } + *p_header_size = *p_header_size - 2 * l_num_band; + } - /* Dump the codestream index from main header */ - if (flag & OPJ_J2K_MH_IND){ - opj_j2k_dump_MH_index(p_j2k, out_stream); + /* Add Antonin : if scalar_derived -> compute other stepsizes */ + if (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { + for (l_band_no = 1; l_band_no < OPJ_J2K_MAXBANDS; l_band_no++) { + l_tccp->stepsizes[l_band_no].expn = + ((OPJ_INT32)(l_tccp->stepsizes[0].expn) - (OPJ_INT32)((l_band_no - 1) / 3) > 0) + ? + (OPJ_INT32)(l_tccp->stepsizes[0].expn) - (OPJ_INT32)((l_band_no - 1) / 3) : 0; + l_tccp->stepsizes[l_band_no].mant = l_tccp->stepsizes[0].mant; } + } + + return OPJ_TRUE; +} + +static void opj_j2k_copy_tile_quantization_parameters(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 i; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_ref_tccp = NULL; + opj_tccp_t *l_copied_tccp = NULL; + OPJ_UINT32 l_size; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + l_ref_tccp = &l_tcp->tccps[0]; + l_copied_tccp = l_ref_tccp + 1; + l_size = OPJ_J2K_MAXBANDS * sizeof(opj_stepsize_t); + + for (i = 1; i < p_j2k->m_private_image->numcomps; ++i) { + l_copied_tccp->qntsty = l_ref_tccp->qntsty; + l_copied_tccp->numgbits = l_ref_tccp->numgbits; + memcpy(l_copied_tccp->stepsizes, l_ref_tccp->stepsizes, l_size); + ++l_copied_tccp; + } +} + +static void opj_j2k_dump_tile_info(opj_tcp_t * l_default_tile, + OPJ_INT32 numcomps, FILE* out_stream) +{ + if (l_default_tile) { + OPJ_INT32 compno; + + fprintf(out_stream, "\t default tile {\n"); + fprintf(out_stream, "\t\t csty=%#x\n", l_default_tile->csty); + fprintf(out_stream, "\t\t prg=%#x\n", l_default_tile->prg); + fprintf(out_stream, "\t\t numlayers=%d\n", l_default_tile->numlayers); + fprintf(out_stream, "\t\t mct=%x\n", l_default_tile->mct); + + for (compno = 0; compno < numcomps; compno++) { + opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); + OPJ_UINT32 resno; + OPJ_INT32 bandno, numbands; + + /* coding style*/ + fprintf(out_stream, "\t\t comp %d {\n", compno); + fprintf(out_stream, "\t\t\t csty=%#x\n", l_tccp->csty); + fprintf(out_stream, "\t\t\t numresolutions=%d\n", l_tccp->numresolutions); + fprintf(out_stream, "\t\t\t cblkw=2^%d\n", l_tccp->cblkw); + fprintf(out_stream, "\t\t\t cblkh=2^%d\n", l_tccp->cblkh); + fprintf(out_stream, "\t\t\t cblksty=%#x\n", l_tccp->cblksty); + fprintf(out_stream, "\t\t\t qmfbid=%d\n", l_tccp->qmfbid); + + fprintf(out_stream, "\t\t\t preccintsize (w,h)="); + for (resno = 0; resno < l_tccp->numresolutions; resno++) { + fprintf(out_stream, "(%d,%d) ", l_tccp->prcw[resno], l_tccp->prch[resno]); + } + fprintf(out_stream, "\n"); + + /* quantization style*/ + fprintf(out_stream, "\t\t\t qntsty=%d\n", l_tccp->qntsty); + fprintf(out_stream, "\t\t\t numgbits=%d\n", l_tccp->numgbits); + fprintf(out_stream, "\t\t\t stepsizes (m,e)="); + numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (OPJ_INT32)l_tccp->numresolutions * 3 - 2; + for (bandno = 0; bandno < numbands; bandno++) { + fprintf(out_stream, "(%d,%d) ", l_tccp->stepsizes[bandno].mant, + l_tccp->stepsizes[bandno].expn); + } + fprintf(out_stream, "\n"); + + /* RGN value*/ + fprintf(out_stream, "\t\t\t roishift=%d\n", l_tccp->roishift); + + fprintf(out_stream, "\t\t }\n"); + } /*end of component of default tile*/ + fprintf(out_stream, "\t }\n"); /*end of default tile*/ + } +} + +void j2k_dump(opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream) +{ + /* Check if the flag is compatible with j2k file*/ + if ((flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)) { + fprintf(out_stream, "Wrong flag\n"); + return; + } - /* Dump the codestream index of the current tile */ - if (flag & OPJ_J2K_TH_IND){ + /* Dump the image_header */ + if (flag & OPJ_IMG_INFO) { + if (p_j2k->m_private_image) { + j2k_dump_image_header(p_j2k->m_private_image, 0, out_stream); + } + } + /* Dump the codestream info from main header */ + if (flag & OPJ_J2K_MH_INFO) { + if (p_j2k->m_private_image) { + opj_j2k_dump_MH_info(p_j2k, out_stream); + } + } + /* Dump all tile/codestream info */ + if (flag & OPJ_J2K_TCH_INFO) { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + OPJ_UINT32 i; + opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; + if (p_j2k->m_private_image) { + for (i = 0; i < l_nb_tiles; ++i) { + opj_j2k_dump_tile_info(l_tcp, (OPJ_INT32)p_j2k->m_private_image->numcomps, + out_stream); + ++l_tcp; + } } + } + + /* Dump the codestream info of the current tile */ + if (flag & OPJ_J2K_TH_INFO) { + + } + + /* Dump the codestream index from main header */ + if (flag & OPJ_J2K_MH_IND) { + opj_j2k_dump_MH_index(p_j2k, out_stream); + } + + /* Dump the codestream index of the current tile */ + if (flag & OPJ_J2K_TH_IND) { + + } } static void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream) { - opj_codestream_index_t* cstr_index = p_j2k->cstr_index; - OPJ_UINT32 it_marker, it_tile, it_tile_part; + opj_codestream_index_t* cstr_index = p_j2k->cstr_index; + OPJ_UINT32 it_marker, it_tile, it_tile_part; - fprintf(out_stream, "Codestream index from main header: {\n"); + fprintf(out_stream, "Codestream index from main header: {\n"); - fprintf(out_stream, "\t Main header start position=%" PRIi64 "\n" - "\t Main header end position=%" PRIi64 "\n", - cstr_index->main_head_start, cstr_index->main_head_end); + fprintf(out_stream, "\t Main header start position=%" PRIi64 "\n" + "\t Main header end position=%" PRIi64 "\n", + cstr_index->main_head_start, cstr_index->main_head_end); - fprintf(out_stream, "\t Marker list: {\n"); + fprintf(out_stream, "\t Marker list: {\n"); - if (cstr_index->marker){ - for (it_marker=0; it_marker < cstr_index->marknum ; it_marker++){ - fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", - cstr_index->marker[it_marker].type, - cstr_index->marker[it_marker].pos, - cstr_index->marker[it_marker].len ); - } + if (cstr_index->marker) { + for (it_marker = 0; it_marker < cstr_index->marknum ; it_marker++) { + fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", + cstr_index->marker[it_marker].type, + cstr_index->marker[it_marker].pos, + cstr_index->marker[it_marker].len); } + } - fprintf(out_stream, "\t }\n"); + fprintf(out_stream, "\t }\n"); - if (cstr_index->tile_index){ + if (cstr_index->tile_index) { /* Simple test to avoid to write empty information*/ OPJ_UINT32 l_acc_nb_of_tile_part = 0; - for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){ - l_acc_nb_of_tile_part += cstr_index->tile_index[it_tile].nb_tps; + for (it_tile = 0; it_tile < cstr_index->nb_of_tiles ; it_tile++) { + l_acc_nb_of_tile_part += cstr_index->tile_index[it_tile].nb_tps; } - if (l_acc_nb_of_tile_part) - { + if (l_acc_nb_of_tile_part) { fprintf(out_stream, "\t Tile index: {\n"); - for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){ - OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps; - - fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, nb_of_tile_part); - - if (cstr_index->tile_index[it_tile].tp_index){ - for (it_tile_part =0; it_tile_part < nb_of_tile_part; it_tile_part++){ - fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%" PRIi64 ", end_header=%" PRIi64 ", end_pos=%" PRIi64 ".\n", - it_tile_part, - cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos, - cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header, - cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos); - } - } - - if (cstr_index->tile_index[it_tile].marker){ - for (it_marker=0; it_marker < cstr_index->tile_index[it_tile].marknum ; it_marker++){ - fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", - cstr_index->tile_index[it_tile].marker[it_marker].type, - cstr_index->tile_index[it_tile].marker[it_marker].pos, - cstr_index->tile_index[it_tile].marker[it_marker].len ); - } - } + for (it_tile = 0; it_tile < cstr_index->nb_of_tiles ; it_tile++) { + OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps; + + fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, + nb_of_tile_part); + + if (cstr_index->tile_index[it_tile].tp_index) { + for (it_tile_part = 0; it_tile_part < nb_of_tile_part; it_tile_part++) { + fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%" PRIi64 ", end_header=%" + PRIi64 ", end_pos=%" PRIi64 ".\n", + it_tile_part, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos); } - fprintf(out_stream,"\t }\n"); - } + } + + if (cstr_index->tile_index[it_tile].marker) { + for (it_marker = 0; it_marker < cstr_index->tile_index[it_tile].marknum ; + it_marker++) { + fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", + cstr_index->tile_index[it_tile].marker[it_marker].type, + cstr_index->tile_index[it_tile].marker[it_marker].pos, + cstr_index->tile_index[it_tile].marker[it_marker].len); + } + } + } + fprintf(out_stream, "\t }\n"); } + } - fprintf(out_stream,"}\n"); + fprintf(out_stream, "}\n"); } @@ -9319,1523 +10366,1756 @@ static void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream) static void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream) { - fprintf(out_stream, "Codestream info from main header: {\n"); + fprintf(out_stream, "Codestream info from main header: {\n"); - fprintf(out_stream, "\t tx0=%d, ty0=%d\n", p_j2k->m_cp.tx0, p_j2k->m_cp.ty0); - fprintf(out_stream, "\t tdx=%d, tdy=%d\n", p_j2k->m_cp.tdx, p_j2k->m_cp.tdy); - fprintf(out_stream, "\t tw=%d, th=%d\n", p_j2k->m_cp.tw, p_j2k->m_cp.th); - opj_j2k_dump_tile_info(p_j2k->m_specific_param.m_decoder.m_default_tcp,(OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream); - fprintf(out_stream, "}\n"); + fprintf(out_stream, "\t tx0=%d, ty0=%d\n", p_j2k->m_cp.tx0, p_j2k->m_cp.ty0); + fprintf(out_stream, "\t tdx=%d, tdy=%d\n", p_j2k->m_cp.tdx, p_j2k->m_cp.tdy); + fprintf(out_stream, "\t tw=%d, th=%d\n", p_j2k->m_cp.tw, p_j2k->m_cp.th); + opj_j2k_dump_tile_info(p_j2k->m_specific_param.m_decoder.m_default_tcp, + (OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream); + fprintf(out_stream, "}\n"); } -void j2k_dump_image_header(opj_image_t* img_header, OPJ_BOOL dev_dump_flag, FILE* out_stream) +void j2k_dump_image_header(opj_image_t* img_header, OPJ_BOOL dev_dump_flag, + FILE* out_stream) { - char tab[2]; + char tab[2]; - if (dev_dump_flag){ - fprintf(stdout, "[DEV] Dump an image_header struct {\n"); - tab[0] = '\0'; - } - else { - fprintf(out_stream, "Image info {\n"); - tab[0] = '\t';tab[1] = '\0'; - } + if (dev_dump_flag) { + fprintf(stdout, "[DEV] Dump an image_header struct {\n"); + tab[0] = '\0'; + } else { + fprintf(out_stream, "Image info {\n"); + tab[0] = '\t'; + tab[1] = '\0'; + } - fprintf(out_stream, "%s x0=%d, y0=%d\n", tab, img_header->x0, img_header->y0); - fprintf(out_stream, "%s x1=%d, y1=%d\n", tab, img_header->x1, img_header->y1); - fprintf(out_stream, "%s numcomps=%d\n", tab, img_header->numcomps); + fprintf(out_stream, "%s x0=%d, y0=%d\n", tab, img_header->x0, img_header->y0); + fprintf(out_stream, "%s x1=%d, y1=%d\n", tab, img_header->x1, + img_header->y1); + fprintf(out_stream, "%s numcomps=%d\n", tab, img_header->numcomps); - if (img_header->comps){ - OPJ_UINT32 compno; - for (compno = 0; compno < img_header->numcomps; compno++) { - fprintf(out_stream, "%s\t component %d {\n", tab, compno); - j2k_dump_image_comp_header(&(img_header->comps[compno]), dev_dump_flag, out_stream); - fprintf(out_stream,"%s}\n",tab); - } + if (img_header->comps) { + OPJ_UINT32 compno; + for (compno = 0; compno < img_header->numcomps; compno++) { + fprintf(out_stream, "%s\t component %d {\n", tab, compno); + j2k_dump_image_comp_header(&(img_header->comps[compno]), dev_dump_flag, + out_stream); + fprintf(out_stream, "%s}\n", tab); } + } - fprintf(out_stream, "}\n"); + fprintf(out_stream, "}\n"); } -void j2k_dump_image_comp_header(opj_image_comp_t* comp_header, OPJ_BOOL dev_dump_flag, FILE* out_stream) +void j2k_dump_image_comp_header(opj_image_comp_t* comp_header, + OPJ_BOOL dev_dump_flag, FILE* out_stream) { - char tab[3]; + char tab[3]; - if (dev_dump_flag){ - fprintf(stdout, "[DEV] Dump an image_comp_header struct {\n"); - tab[0] = '\0'; - } else { - tab[0] = '\t';tab[1] = '\t';tab[2] = '\0'; - } + if (dev_dump_flag) { + fprintf(stdout, "[DEV] Dump an image_comp_header struct {\n"); + tab[0] = '\0'; + } else { + tab[0] = '\t'; + tab[1] = '\t'; + tab[2] = '\0'; + } - fprintf(out_stream, "%s dx=%d, dy=%d\n", tab, comp_header->dx, comp_header->dy); - fprintf(out_stream, "%s prec=%d\n", tab, comp_header->prec); - fprintf(out_stream, "%s sgnd=%d\n", tab, comp_header->sgnd); + fprintf(out_stream, "%s dx=%d, dy=%d\n", tab, comp_header->dx, comp_header->dy); + fprintf(out_stream, "%s prec=%d\n", tab, comp_header->prec); + fprintf(out_stream, "%s sgnd=%d\n", tab, comp_header->sgnd); - if (dev_dump_flag) - fprintf(out_stream, "}\n"); + if (dev_dump_flag) { + fprintf(out_stream, "}\n"); + } } opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k) { - OPJ_UINT32 compno; - OPJ_UINT32 numcomps = p_j2k->m_private_image->numcomps; - opj_tcp_t *l_default_tile; - opj_codestream_info_v2_t* cstr_info = (opj_codestream_info_v2_t*) opj_calloc(1,sizeof(opj_codestream_info_v2_t)); - if (!cstr_info) - return NULL; - - cstr_info->nbcomps = p_j2k->m_private_image->numcomps; - - cstr_info->tx0 = p_j2k->m_cp.tx0; - cstr_info->ty0 = p_j2k->m_cp.ty0; - cstr_info->tdx = p_j2k->m_cp.tdx; - cstr_info->tdy = p_j2k->m_cp.tdy; - cstr_info->tw = p_j2k->m_cp.tw; - cstr_info->th = p_j2k->m_cp.th; - - cstr_info->tile_info = NULL; /* Not fill from the main header*/ + OPJ_UINT32 compno; + OPJ_UINT32 numcomps = p_j2k->m_private_image->numcomps; + opj_tcp_t *l_default_tile; + opj_codestream_info_v2_t* cstr_info = (opj_codestream_info_v2_t*) opj_calloc(1, + sizeof(opj_codestream_info_v2_t)); + if (!cstr_info) { + return NULL; + } - l_default_tile = p_j2k->m_specific_param.m_decoder.m_default_tcp; + cstr_info->nbcomps = p_j2k->m_private_image->numcomps; - cstr_info->m_default_tile_info.csty = l_default_tile->csty; - cstr_info->m_default_tile_info.prg = l_default_tile->prg; - cstr_info->m_default_tile_info.numlayers = l_default_tile->numlayers; - cstr_info->m_default_tile_info.mct = l_default_tile->mct; + cstr_info->tx0 = p_j2k->m_cp.tx0; + cstr_info->ty0 = p_j2k->m_cp.ty0; + cstr_info->tdx = p_j2k->m_cp.tdx; + cstr_info->tdy = p_j2k->m_cp.tdy; + cstr_info->tw = p_j2k->m_cp.tw; + cstr_info->th = p_j2k->m_cp.th; - cstr_info->m_default_tile_info.tccp_info = (opj_tccp_info_t*) opj_calloc(cstr_info->nbcomps, sizeof(opj_tccp_info_t)); - if (!cstr_info->m_default_tile_info.tccp_info) - { - opj_destroy_cstr_info(&cstr_info); - return NULL; - } + cstr_info->tile_info = NULL; /* Not fill from the main header*/ - for (compno = 0; compno < numcomps; compno++) { - opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); - opj_tccp_info_t *l_tccp_info = &(cstr_info->m_default_tile_info.tccp_info[compno]); - OPJ_INT32 bandno, numbands; - - /* coding style*/ - l_tccp_info->csty = l_tccp->csty; - l_tccp_info->numresolutions = l_tccp->numresolutions; - l_tccp_info->cblkw = l_tccp->cblkw; - l_tccp_info->cblkh = l_tccp->cblkh; - l_tccp_info->cblksty = l_tccp->cblksty; - l_tccp_info->qmfbid = l_tccp->qmfbid; - if (l_tccp->numresolutions < OPJ_J2K_MAXRLVLS) - { - memcpy(l_tccp_info->prch, l_tccp->prch, l_tccp->numresolutions); - memcpy(l_tccp_info->prcw, l_tccp->prcw, l_tccp->numresolutions); - } + l_default_tile = p_j2k->m_specific_param.m_decoder.m_default_tcp; - /* quantization style*/ - l_tccp_info->qntsty = l_tccp->qntsty; - l_tccp_info->numgbits = l_tccp->numgbits; + cstr_info->m_default_tile_info.csty = l_default_tile->csty; + cstr_info->m_default_tile_info.prg = l_default_tile->prg; + cstr_info->m_default_tile_info.numlayers = l_default_tile->numlayers; + cstr_info->m_default_tile_info.mct = l_default_tile->mct; - numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (OPJ_INT32)l_tccp->numresolutions * 3 - 2; - if (numbands < OPJ_J2K_MAXBANDS) { - for (bandno = 0; bandno < numbands; bandno++) { - l_tccp_info->stepsizes_mant[bandno] = (OPJ_UINT32)l_tccp->stepsizes[bandno].mant; - l_tccp_info->stepsizes_expn[bandno] = (OPJ_UINT32)l_tccp->stepsizes[bandno].expn; - } - } + cstr_info->m_default_tile_info.tccp_info = (opj_tccp_info_t*) opj_calloc( + cstr_info->nbcomps, sizeof(opj_tccp_info_t)); + if (!cstr_info->m_default_tile_info.tccp_info) { + opj_destroy_cstr_info(&cstr_info); + return NULL; + } - /* RGN value*/ - l_tccp_info->roishift = l_tccp->roishift; + for (compno = 0; compno < numcomps; compno++) { + opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); + opj_tccp_info_t *l_tccp_info = & + (cstr_info->m_default_tile_info.tccp_info[compno]); + OPJ_INT32 bandno, numbands; + + /* coding style*/ + l_tccp_info->csty = l_tccp->csty; + l_tccp_info->numresolutions = l_tccp->numresolutions; + l_tccp_info->cblkw = l_tccp->cblkw; + l_tccp_info->cblkh = l_tccp->cblkh; + l_tccp_info->cblksty = l_tccp->cblksty; + l_tccp_info->qmfbid = l_tccp->qmfbid; + if (l_tccp->numresolutions < OPJ_J2K_MAXRLVLS) { + memcpy(l_tccp_info->prch, l_tccp->prch, l_tccp->numresolutions); + memcpy(l_tccp_info->prcw, l_tccp->prcw, l_tccp->numresolutions); + } + + /* quantization style*/ + l_tccp_info->qntsty = l_tccp->qntsty; + l_tccp_info->numgbits = l_tccp->numgbits; + + numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (OPJ_INT32)l_tccp->numresolutions * 3 - 2; + if (numbands < OPJ_J2K_MAXBANDS) { + for (bandno = 0; bandno < numbands; bandno++) { + l_tccp_info->stepsizes_mant[bandno] = (OPJ_UINT32) + l_tccp->stepsizes[bandno].mant; + l_tccp_info->stepsizes_expn[bandno] = (OPJ_UINT32) + l_tccp->stepsizes[bandno].expn; + } } - return cstr_info; + /* RGN value*/ + l_tccp_info->roishift = l_tccp->roishift; + } + + return cstr_info; } opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k) { - opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*) - opj_calloc(1,sizeof(opj_codestream_index_t)); - if (!l_cstr_index) - return NULL; + opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*) + opj_calloc(1, sizeof(opj_codestream_index_t)); + if (!l_cstr_index) { + return NULL; + } - l_cstr_index->main_head_start = p_j2k->cstr_index->main_head_start; - l_cstr_index->main_head_end = p_j2k->cstr_index->main_head_end; - l_cstr_index->codestream_size = p_j2k->cstr_index->codestream_size; + l_cstr_index->main_head_start = p_j2k->cstr_index->main_head_start; + l_cstr_index->main_head_end = p_j2k->cstr_index->main_head_end; + l_cstr_index->codestream_size = p_j2k->cstr_index->codestream_size; - l_cstr_index->marknum = p_j2k->cstr_index->marknum; - l_cstr_index->marker = (opj_marker_info_t*)opj_malloc(l_cstr_index->marknum*sizeof(opj_marker_info_t)); - if (!l_cstr_index->marker){ - opj_free( l_cstr_index); - return NULL; - } + l_cstr_index->marknum = p_j2k->cstr_index->marknum; + l_cstr_index->marker = (opj_marker_info_t*)opj_malloc(l_cstr_index->marknum * + sizeof(opj_marker_info_t)); + if (!l_cstr_index->marker) { + opj_free(l_cstr_index); + return NULL; + } - if (p_j2k->cstr_index->marker) - memcpy(l_cstr_index->marker, p_j2k->cstr_index->marker, l_cstr_index->marknum * sizeof(opj_marker_info_t) ); - else{ - opj_free(l_cstr_index->marker); - l_cstr_index->marker = NULL; - } + if (p_j2k->cstr_index->marker) { + memcpy(l_cstr_index->marker, p_j2k->cstr_index->marker, + l_cstr_index->marknum * sizeof(opj_marker_info_t)); + } else { + opj_free(l_cstr_index->marker); + l_cstr_index->marker = NULL; + } - l_cstr_index->nb_of_tiles = p_j2k->cstr_index->nb_of_tiles; - l_cstr_index->tile_index = (opj_tile_index_t*)opj_calloc(l_cstr_index->nb_of_tiles, sizeof(opj_tile_index_t) ); - if (!l_cstr_index->tile_index){ - opj_free( l_cstr_index->marker); - opj_free( l_cstr_index); - return NULL; - } + l_cstr_index->nb_of_tiles = p_j2k->cstr_index->nb_of_tiles; + l_cstr_index->tile_index = (opj_tile_index_t*)opj_calloc( + l_cstr_index->nb_of_tiles, sizeof(opj_tile_index_t)); + if (!l_cstr_index->tile_index) { + opj_free(l_cstr_index->marker); + opj_free(l_cstr_index); + return NULL; + } - if (!p_j2k->cstr_index->tile_index){ - opj_free(l_cstr_index->tile_index); - l_cstr_index->tile_index = NULL; - } - else { - OPJ_UINT32 it_tile = 0; - for (it_tile = 0; it_tile < l_cstr_index->nb_of_tiles; it_tile++ ){ + if (!p_j2k->cstr_index->tile_index) { + opj_free(l_cstr_index->tile_index); + l_cstr_index->tile_index = NULL; + } else { + OPJ_UINT32 it_tile = 0; + for (it_tile = 0; it_tile < l_cstr_index->nb_of_tiles; it_tile++) { - /* Tile Marker*/ - l_cstr_index->tile_index[it_tile].marknum = p_j2k->cstr_index->tile_index[it_tile].marknum; + /* Tile Marker*/ + l_cstr_index->tile_index[it_tile].marknum = + p_j2k->cstr_index->tile_index[it_tile].marknum; - l_cstr_index->tile_index[it_tile].marker = - (opj_marker_info_t*)opj_malloc(l_cstr_index->tile_index[it_tile].marknum*sizeof(opj_marker_info_t)); + l_cstr_index->tile_index[it_tile].marker = + (opj_marker_info_t*)opj_malloc(l_cstr_index->tile_index[it_tile].marknum * + sizeof(opj_marker_info_t)); - if (!l_cstr_index->tile_index[it_tile].marker) { - OPJ_UINT32 it_tile_free; + if (!l_cstr_index->tile_index[it_tile].marker) { + OPJ_UINT32 it_tile_free; - for (it_tile_free=0; it_tile_free < it_tile; it_tile_free++){ - opj_free(l_cstr_index->tile_index[it_tile_free].marker); - } + for (it_tile_free = 0; it_tile_free < it_tile; it_tile_free++) { + opj_free(l_cstr_index->tile_index[it_tile_free].marker); + } - opj_free( l_cstr_index->tile_index); - opj_free( l_cstr_index->marker); - opj_free( l_cstr_index); - return NULL; - } + opj_free(l_cstr_index->tile_index); + opj_free(l_cstr_index->marker); + opj_free(l_cstr_index); + return NULL; + } - if (p_j2k->cstr_index->tile_index[it_tile].marker) - memcpy( l_cstr_index->tile_index[it_tile].marker, - p_j2k->cstr_index->tile_index[it_tile].marker, - l_cstr_index->tile_index[it_tile].marknum * sizeof(opj_marker_info_t) ); - else{ - opj_free(l_cstr_index->tile_index[it_tile].marker); - l_cstr_index->tile_index[it_tile].marker = NULL; - } + if (p_j2k->cstr_index->tile_index[it_tile].marker) + memcpy(l_cstr_index->tile_index[it_tile].marker, + p_j2k->cstr_index->tile_index[it_tile].marker, + l_cstr_index->tile_index[it_tile].marknum * sizeof(opj_marker_info_t)); + else { + opj_free(l_cstr_index->tile_index[it_tile].marker); + l_cstr_index->tile_index[it_tile].marker = NULL; + } - /* Tile part index*/ - l_cstr_index->tile_index[it_tile].nb_tps = p_j2k->cstr_index->tile_index[it_tile].nb_tps; + /* Tile part index*/ + l_cstr_index->tile_index[it_tile].nb_tps = + p_j2k->cstr_index->tile_index[it_tile].nb_tps; - l_cstr_index->tile_index[it_tile].tp_index = - (opj_tp_index_t*)opj_malloc(l_cstr_index->tile_index[it_tile].nb_tps*sizeof(opj_tp_index_t)); + l_cstr_index->tile_index[it_tile].tp_index = + (opj_tp_index_t*)opj_malloc(l_cstr_index->tile_index[it_tile].nb_tps * sizeof( + opj_tp_index_t)); - if(!l_cstr_index->tile_index[it_tile].tp_index){ - OPJ_UINT32 it_tile_free; + if (!l_cstr_index->tile_index[it_tile].tp_index) { + OPJ_UINT32 it_tile_free; - for (it_tile_free=0; it_tile_free < it_tile; it_tile_free++){ - opj_free(l_cstr_index->tile_index[it_tile_free].marker); - opj_free(l_cstr_index->tile_index[it_tile_free].tp_index); - } + for (it_tile_free = 0; it_tile_free < it_tile; it_tile_free++) { + opj_free(l_cstr_index->tile_index[it_tile_free].marker); + opj_free(l_cstr_index->tile_index[it_tile_free].tp_index); + } - opj_free( l_cstr_index->tile_index); - opj_free( l_cstr_index->marker); - opj_free( l_cstr_index); - return NULL; - } + opj_free(l_cstr_index->tile_index); + opj_free(l_cstr_index->marker); + opj_free(l_cstr_index); + return NULL; + } - if (p_j2k->cstr_index->tile_index[it_tile].tp_index){ - memcpy( l_cstr_index->tile_index[it_tile].tp_index, - p_j2k->cstr_index->tile_index[it_tile].tp_index, - l_cstr_index->tile_index[it_tile].nb_tps * sizeof(opj_tp_index_t) ); - } - else{ - opj_free(l_cstr_index->tile_index[it_tile].tp_index); - l_cstr_index->tile_index[it_tile].tp_index = NULL; - } + if (p_j2k->cstr_index->tile_index[it_tile].tp_index) { + memcpy(l_cstr_index->tile_index[it_tile].tp_index, + p_j2k->cstr_index->tile_index[it_tile].tp_index, + l_cstr_index->tile_index[it_tile].nb_tps * sizeof(opj_tp_index_t)); + } else { + opj_free(l_cstr_index->tile_index[it_tile].tp_index); + l_cstr_index->tile_index[it_tile].tp_index = NULL; + } - /* Packet index (NOT USED)*/ - l_cstr_index->tile_index[it_tile].nb_packet = 0; - l_cstr_index->tile_index[it_tile].packet_index = NULL; + /* Packet index (NOT USED)*/ + l_cstr_index->tile_index[it_tile].nb_packet = 0; + l_cstr_index->tile_index[it_tile].packet_index = NULL; - } } + } - return l_cstr_index; + return l_cstr_index; } static OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k) { - OPJ_UINT32 it_tile=0; + OPJ_UINT32 it_tile = 0; - p_j2k->cstr_index->nb_of_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; - p_j2k->cstr_index->tile_index = (opj_tile_index_t*)opj_calloc(p_j2k->cstr_index->nb_of_tiles, sizeof(opj_tile_index_t)); - if (!p_j2k->cstr_index->tile_index) - return OPJ_FALSE; + p_j2k->cstr_index->nb_of_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + p_j2k->cstr_index->tile_index = (opj_tile_index_t*)opj_calloc( + p_j2k->cstr_index->nb_of_tiles, sizeof(opj_tile_index_t)); + if (!p_j2k->cstr_index->tile_index) { + return OPJ_FALSE; + } - for (it_tile=0; it_tile < p_j2k->cstr_index->nb_of_tiles; it_tile++){ - p_j2k->cstr_index->tile_index[it_tile].maxmarknum = 100; - p_j2k->cstr_index->tile_index[it_tile].marknum = 0; - p_j2k->cstr_index->tile_index[it_tile].marker = (opj_marker_info_t*) - opj_calloc(p_j2k->cstr_index->tile_index[it_tile].maxmarknum, sizeof(opj_marker_info_t)); - if (!p_j2k->cstr_index->tile_index[it_tile].marker) - return OPJ_FALSE; + for (it_tile = 0; it_tile < p_j2k->cstr_index->nb_of_tiles; it_tile++) { + p_j2k->cstr_index->tile_index[it_tile].maxmarknum = 100; + p_j2k->cstr_index->tile_index[it_tile].marknum = 0; + p_j2k->cstr_index->tile_index[it_tile].marker = (opj_marker_info_t*) + opj_calloc(p_j2k->cstr_index->tile_index[it_tile].maxmarknum, + sizeof(opj_marker_info_t)); + if (!p_j2k->cstr_index->tile_index[it_tile].marker) { + return OPJ_FALSE; } + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_decode_tiles ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager) -{ - OPJ_BOOL l_go_on = OPJ_TRUE; - OPJ_UINT32 l_current_tile_no; - OPJ_UINT32 l_data_size,l_max_data_size; - OPJ_INT32 l_tile_x0,l_tile_y0,l_tile_x1,l_tile_y1; - OPJ_UINT32 l_nb_comps; - OPJ_BYTE * l_current_data; - OPJ_UINT32 nr_tiles = 0; +static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL l_go_on = OPJ_TRUE; + OPJ_UINT32 l_current_tile_no; + OPJ_INT32 l_tile_x0, l_tile_y0, l_tile_x1, l_tile_y1; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 nr_tiles = 0; + + /* Particular case for whole single tile decoding */ + /* We can avoid allocating intermediate tile buffers */ + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + p_j2k->m_cp.tx0 == 0 && p_j2k->m_cp.ty0 == 0 && + p_j2k->m_output_image->x0 == 0 && + p_j2k->m_output_image->y0 == 0 && + p_j2k->m_output_image->x1 == p_j2k->m_cp.tdx && + p_j2k->m_output_image->y1 == p_j2k->m_cp.tdy) { + OPJ_UINT32 i; + if (! opj_j2k_read_tile_header(p_j2k, + &l_current_tile_no, + NULL, + &l_tile_x0, &l_tile_y0, + &l_tile_x1, &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) { + return OPJ_FALSE; + } + + if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile 1/1\n"); + return OPJ_FALSE; + } + + /* Transfer TCD data to output image data */ + for (i = 0; i < p_j2k->m_output_image->numcomps; i++) { + opj_image_data_free(p_j2k->m_output_image->comps[i].data); + p_j2k->m_output_image->comps[i].data = + p_j2k->m_tcd->tcd_image->tiles->comps[i].data; + p_j2k->m_output_image->comps[i].resno_decoded = + p_j2k->m_tcd->image->comps[i].resno_decoded; + p_j2k->m_tcd->tcd_image->tiles->comps[i].data = NULL; + } + + return OPJ_TRUE; + } - l_current_data = (OPJ_BYTE*)opj_malloc(1000); - if (! l_current_data) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tiles\n"); + for (;;) { + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + p_j2k->m_cp.tcps[0].m_data != NULL) { + l_current_tile_no = 0; + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA; + } else { + if (! opj_j2k_read_tile_header(p_j2k, + &l_current_tile_no, + NULL, + &l_tile_x0, &l_tile_y0, + &l_tile_x1, &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) { return OPJ_FALSE; + } + + if (! l_go_on) { + break; + } } - l_max_data_size = 1000; - - for (;;) { - if (! opj_j2k_read_tile_header( p_j2k, - &l_current_tile_no, - &l_data_size, - &l_tile_x0, &l_tile_y0, - &l_tile_x1, &l_tile_y1, - &l_nb_comps, - &l_go_on, - p_stream, - p_manager)) { - opj_free(l_current_data); - return OPJ_FALSE; - } - if (! l_go_on) { - break; - } + if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile %d/%d\n", + l_current_tile_no + 1, p_j2k->m_cp.th * p_j2k->m_cp.tw); + return OPJ_FALSE; + } - if (l_data_size > l_max_data_size) { - OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_data_size); - if (! l_new_current_data) { - opj_free(l_current_data); - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw); - return OPJ_FALSE; - } - l_current_data = l_new_current_data; - l_max_data_size = l_data_size; - } + opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", + l_current_tile_no + 1, p_j2k->m_cp.th * p_j2k->m_cp.tw); - if (! opj_j2k_decode_tile(p_j2k,l_current_tile_no,l_current_data,l_data_size,p_stream,p_manager)) { - opj_free(l_current_data); - opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile %d/%d\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw); - return OPJ_FALSE; - } - opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw); + if (! opj_j2k_update_image_data(p_j2k->m_tcd, + p_j2k->m_output_image)) { + return OPJ_FALSE; + } - if (! opj_j2k_update_image_data(p_j2k->m_tcd,l_current_data, p_j2k->m_output_image)) { - opj_free(l_current_data); - return OPJ_FALSE; - } - opj_event_msg(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no + 1); - - if(opj_stream_get_number_byte_left(p_stream) == 0 - && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) - break; - if(++nr_tiles == p_j2k->m_cp.th * p_j2k->m_cp.tw) - break; + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + !(p_j2k->m_output_image->x0 == p_j2k->m_private_image->x0 && + p_j2k->m_output_image->y0 == p_j2k->m_private_image->y0 && + p_j2k->m_output_image->x1 == p_j2k->m_private_image->x1 && + p_j2k->m_output_image->y1 == p_j2k->m_private_image->y1)) { + /* Keep current tcp data */ + } else { + opj_j2k_tcp_data_destroy(&p_j2k->m_cp.tcps[l_current_tile_no]); } - opj_free(l_current_data); + opj_event_msg(p_manager, EVT_INFO, + "Image data has been updated with tile %d.\n\n", l_current_tile_no + 1); - return OPJ_TRUE; + if (opj_stream_get_number_byte_left(p_stream) == 0 + && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) { + break; + } + if (++nr_tiles == p_j2k->m_cp.th * p_j2k->m_cp.tw) { + break; + } + } + + return OPJ_TRUE; } /** * Sets up the procedures to do on decoding data. Developpers wanting to extend the library can add their own reading procedures. */ -static OPJ_BOOL opj_j2k_setup_decoding (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_decoding(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions*/ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_tiles, p_manager)) { - return OPJ_FALSE; - } - /* DEVELOPER CORNER, add your custom procedures */ + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_decode_tiles, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ - return OPJ_TRUE; + return OPJ_TRUE; } /* * Read and decode one tile. */ -static OPJ_BOOL opj_j2k_decode_one_tile ( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager) -{ - OPJ_BOOL l_go_on = OPJ_TRUE; - OPJ_UINT32 l_current_tile_no; - OPJ_UINT32 l_tile_no_to_dec; - OPJ_UINT32 l_data_size,l_max_data_size; - OPJ_INT32 l_tile_x0,l_tile_y0,l_tile_x1,l_tile_y1; - OPJ_UINT32 l_nb_comps; - OPJ_BYTE * l_current_data; - - l_current_data = (OPJ_BYTE*)opj_malloc(1000); - if (! l_current_data) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode one tile\n"); - return OPJ_FALSE; - } - l_max_data_size = 1000; +static OPJ_BOOL opj_j2k_decode_one_tile(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL l_go_on = OPJ_TRUE; + OPJ_UINT32 l_current_tile_no; + OPJ_UINT32 l_tile_no_to_dec; + OPJ_INT32 l_tile_x0, l_tile_y0, l_tile_x1, l_tile_y1; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 i; - /*Allocate and initialize some elements of codestrem index if not already done*/ - if( !p_j2k->cstr_index->tile_index) - { - if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)){ - opj_free(l_current_data); - return OPJ_FALSE; - } + /*Allocate and initialize some elements of codestrem index if not already done*/ + if (!p_j2k->cstr_index->tile_index) { + if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { + return OPJ_FALSE; } - /* Move into the codestream to the first SOT used to decode the desired tile */ - l_tile_no_to_dec = (OPJ_UINT32)p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec; - if (p_j2k->cstr_index->tile_index) - if(p_j2k->cstr_index->tile_index->tp_index) - { - if ( ! p_j2k->cstr_index->tile_index[l_tile_no_to_dec].nb_tps) { - /* the index for this tile has not been built, - * so move to the last SOT read */ - if ( !(opj_stream_read_seek(p_stream, p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos+2, p_manager)) ){ - opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - } - else{ - if ( !(opj_stream_read_seek(p_stream, p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos+2, p_manager)) ) { - opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - } - /* Special case if we have previously read the EOC marker (if the previous tile getted is the last ) */ - if(p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC) - p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + } + /* Move into the codestream to the first SOT used to decode the desired tile */ + l_tile_no_to_dec = (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec; + if (p_j2k->cstr_index->tile_index) + if (p_j2k->cstr_index->tile_index->tp_index) { + if (! p_j2k->cstr_index->tile_index[l_tile_no_to_dec].nb_tps) { + /* the index for this tile has not been built, + * so move to the last SOT read */ + if (!(opj_stream_read_seek(p_stream, + p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos + 2, p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; } - - for (;;) { - if (! opj_j2k_read_tile_header( p_j2k, - &l_current_tile_no, - &l_data_size, - &l_tile_x0, &l_tile_y0, - &l_tile_x1, &l_tile_y1, - &l_nb_comps, - &l_go_on, - p_stream, - p_manager)) { - opj_free(l_current_data); - return OPJ_FALSE; + } else { + if (!(opj_stream_read_seek(p_stream, + p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos + 2, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; } + } + /* Special case if we have previously read the EOC marker (if the previous tile getted is the last ) */ + if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + } + } - if (! l_go_on) { - break; - } + /* Reset current tile part number for all tiles, and not only the one */ + /* of interest. */ + /* Not completely sure this is always correct but required for */ + /* ./build/bin/j2k_random_tile_access ./build/tests/tte1.j2k */ + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + for (i = 0; i < l_nb_tiles; ++i) { + p_j2k->m_cp.tcps[i].m_current_tile_part_number = -1; + } - if (l_data_size > l_max_data_size) { - OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_data_size); - if (! l_new_current_data) { - opj_free(l_current_data); - l_current_data = NULL; - /* TODO: LH: why tile numbering policy used in messages differs from - the one used in opj_j2k_decode_tiles() ? */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1); - return OPJ_FALSE; - } - l_current_data = l_new_current_data; - l_max_data_size = l_data_size; - } + for (;;) { + if (! opj_j2k_read_tile_header(p_j2k, + &l_current_tile_no, + NULL, + &l_tile_x0, &l_tile_y0, + &l_tile_x1, &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) { + return OPJ_FALSE; + } - if (! opj_j2k_decode_tile(p_j2k,l_current_tile_no,l_current_data,l_data_size,p_stream,p_manager)) { - opj_free(l_current_data); - return OPJ_FALSE; - } - opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1); + if (! l_go_on) { + break; + } - if (! opj_j2k_update_image_data(p_j2k->m_tcd,l_current_data, p_j2k->m_output_image)) { - opj_free(l_current_data); - return OPJ_FALSE; - } - opj_event_msg(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no); - - if(l_current_tile_no == l_tile_no_to_dec) - { - /* move into the codestream to the the first SOT (FIXME or not move?)*/ - if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) ) { - opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - break; - } - else { - opj_event_msg(p_manager, EVT_WARNING, "Tile read, decode and updated is not the desired (%d vs %d).\n", l_current_tile_no, l_tile_no_to_dec); - } + if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { + return OPJ_FALSE; + } + opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", + l_current_tile_no + 1, p_j2k->m_cp.th * p_j2k->m_cp.tw); + if (! opj_j2k_update_image_data(p_j2k->m_tcd, + p_j2k->m_output_image)) { + return OPJ_FALSE; } + opj_j2k_tcp_data_destroy(&p_j2k->m_cp.tcps[l_current_tile_no]); - opj_free(l_current_data); + opj_event_msg(p_manager, EVT_INFO, + "Image data has been updated with tile %d.\n\n", l_current_tile_no + 1); - return OPJ_TRUE; + if (l_current_tile_no == l_tile_no_to_dec) { + /* move into the codestream to the first SOT (FIXME or not move?)*/ + if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + break; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "Tile read, decoded and updated is not the desired one (%d vs %d).\n", + l_current_tile_no + 1, l_tile_no_to_dec + 1); + } + + } + + return OPJ_TRUE; } /** * Sets up the procedures to do on decoding one tile. Developpers wanting to extend the library can add their own reading procedures. */ -static OPJ_BOOL opj_j2k_setup_decoding_tile (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_decoding_tile(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions*/ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_one_tile, p_manager)) { - return OPJ_FALSE; - } - /* DEVELOPER CORNER, add your custom procedures */ + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_decode_one_tile, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k, - opj_stream_private_t * p_stream, - opj_image_t * p_image, - opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k, + opj_image_t * p_image) { - OPJ_UINT32 compno; + OPJ_UINT32 compno; - if (!p_image) - return OPJ_FALSE; - - p_j2k->m_output_image = opj_image_create0(); - if (! (p_j2k->m_output_image)) { - return OPJ_FALSE; + /* Move data and copy one information from codec to output image*/ + if (p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode > 0) { + opj_image_comp_t* newcomps = + (opj_image_comp_t*) opj_malloc( + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode * + sizeof(opj_image_comp_t)); + if (newcomps == NULL) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; } - opj_copy_image_header(p_image, p_j2k->m_output_image); - - /* customization of the decoding */ - opj_j2k_setup_decoding(p_j2k, p_manager); - - /* Decode the codestream */ - if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) { - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; - return OPJ_FALSE; + for (compno = 0; compno < p_image->numcomps; compno++) { + opj_image_data_free(p_image->comps[compno].data); + p_image->comps[compno].data = NULL; + } + for (compno = 0; + compno < p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode; compno++) { + OPJ_UINT32 src_compno = + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode[compno]; + memcpy(&(newcomps[compno]), + &(p_j2k->m_output_image->comps[src_compno]), + sizeof(opj_image_comp_t)); + newcomps[compno].resno_decoded = + p_j2k->m_output_image->comps[src_compno].resno_decoded; + newcomps[compno].data = p_j2k->m_output_image->comps[src_compno].data; + p_j2k->m_output_image->comps[src_compno].data = NULL; } - - /* Move data and copy one information from codec to output image*/ for (compno = 0; compno < p_image->numcomps; compno++) { - p_image->comps[compno].resno_decoded = p_j2k->m_output_image->comps[compno].resno_decoded; - p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data; + assert(p_j2k->m_output_image->comps[compno].data == NULL); + opj_image_data_free(p_j2k->m_output_image->comps[compno].data); + p_j2k->m_output_image->comps[compno].data = NULL; + } + p_image->numcomps = p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode; + opj_free(p_image->comps); + p_image->comps = newcomps; + } else { + for (compno = 0; compno < p_image->numcomps; compno++) { + p_image->comps[compno].resno_decoded = + p_j2k->m_output_image->comps[compno].resno_decoded; + opj_image_data_free(p_image->comps[compno].data); + p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data; #if 0 - char fn[256]; - sprintf( fn, "/tmp/%d.raw", compno ); - FILE *debug = fopen( fn, "wb" ); - fwrite( p_image->comps[compno].data, sizeof(OPJ_INT32), p_image->comps[compno].w * p_image->comps[compno].h, debug ); - fclose( debug ); + char fn[256]; + sprintf(fn, "/tmp/%d.raw", compno); + FILE *debug = fopen(fn, "wb"); + fwrite(p_image->comps[compno].data, sizeof(OPJ_INT32), + p_image->comps[compno].w * p_image->comps[compno].h, debug); + fclose(debug); #endif - p_j2k->m_output_image->comps[compno].data = NULL; + p_j2k->m_output_image->comps[compno].data = NULL; } - - return OPJ_TRUE; + } + return OPJ_TRUE; } -OPJ_BOOL opj_j2k_get_tile( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager, - OPJ_UINT32 tile_index ) +OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k, + opj_stream_private_t * p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 compno; - OPJ_UINT32 l_tile_x, l_tile_y; - opj_image_comp_t* l_img_comp; + if (!p_image) { + return OPJ_FALSE; + } - if (!p_image) { - opj_event_msg(p_manager, EVT_ERROR, "We need an image previously created.\n"); - return OPJ_FALSE; + /* Heuristics to detect sequence opj_read_header(), opj_set_decoded_resolution_factor() */ + /* and finally opj_decode_image() without manual setting of comps[].factor */ + /* We could potentially always execute it, if we don't allow people to do */ + /* opj_read_header(), modify x0,y0,x1,y1 of returned image an call opj_decode_image() */ + if (p_j2k->m_cp.m_specific_param.m_dec.m_reduce > 0 && + p_j2k->m_private_image != NULL && + p_j2k->m_private_image->numcomps > 0 && + p_j2k->m_private_image->comps[0].factor == + p_j2k->m_cp.m_specific_param.m_dec.m_reduce && + p_image->numcomps > 0 && + p_image->comps[0].factor == 0 && + /* Don't mess with image dimension if the user has allocated it */ + p_image->comps[0].data == NULL) { + OPJ_UINT32 it_comp; + + /* Update the comps[].factor member of the output image with the one */ + /* of m_reduce */ + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + p_image->comps[it_comp].factor = p_j2k->m_cp.m_specific_param.m_dec.m_reduce; + } + if (!opj_j2k_update_image_dimensions(p_image, p_manager)) { + return OPJ_FALSE; } + } - if ( /*(tile_index < 0) &&*/ (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) ){ - opj_event_msg(p_manager, EVT_ERROR, "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1); - return OPJ_FALSE; + if (p_j2k->m_output_image == NULL) { + p_j2k->m_output_image = opj_image_create0(); + if (!(p_j2k->m_output_image)) { + return OPJ_FALSE; } + } + opj_copy_image_header(p_image, p_j2k->m_output_image); - /* Compute the dimension of the desired tile*/ - l_tile_x = tile_index % p_j2k->m_cp.tw; - l_tile_y = tile_index / p_j2k->m_cp.tw; + /* customization of the decoding */ + if (!opj_j2k_setup_decoding(p_j2k, p_manager)) { + return OPJ_FALSE; + } - p_image->x0 = l_tile_x * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0; - if (p_image->x0 < p_j2k->m_private_image->x0) - p_image->x0 = p_j2k->m_private_image->x0; - p_image->x1 = (l_tile_x + 1) * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0; - if (p_image->x1 > p_j2k->m_private_image->x1) - p_image->x1 = p_j2k->m_private_image->x1; + /* Decode the codestream */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } - p_image->y0 = l_tile_y * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0; - if (p_image->y0 < p_j2k->m_private_image->y0) - p_image->y0 = p_j2k->m_private_image->y0; - p_image->y1 = (l_tile_y + 1) * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0; - if (p_image->y1 > p_j2k->m_private_image->y1) - p_image->y1 = p_j2k->m_private_image->y1; + /* Move data and copy one information from codec to output image*/ + return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image); +} - l_img_comp = p_image->comps; - for (compno=0; compno < p_image->numcomps; ++compno) - { - OPJ_INT32 l_comp_x1, l_comp_y1; +OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index) +{ + OPJ_UINT32 compno; + OPJ_UINT32 l_tile_x, l_tile_y; + opj_image_comp_t* l_img_comp; - l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; + if (!p_image) { + opj_event_msg(p_manager, EVT_ERROR, "We need an image previously created.\n"); + return OPJ_FALSE; + } - l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); - l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); - l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); - l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); + if (p_image->numcomps < p_j2k->m_private_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Image has less components than codestream.\n"); + return OPJ_FALSE; + } - l_img_comp->w = (OPJ_UINT32)(opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor) - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor)); - l_img_comp->h = (OPJ_UINT32)(opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor) - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor)); + if (/*(tile_index < 0) &&*/ (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th)) { + opj_event_msg(p_manager, EVT_ERROR, + "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, + (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1); + return OPJ_FALSE; + } - l_img_comp++; - } + /* Compute the dimension of the desired tile*/ + l_tile_x = tile_index % p_j2k->m_cp.tw; + l_tile_y = tile_index / p_j2k->m_cp.tw; - /* Destroy the previous output image*/ - if (p_j2k->m_output_image) - opj_image_destroy(p_j2k->m_output_image); + p_image->x0 = l_tile_x * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0; + if (p_image->x0 < p_j2k->m_private_image->x0) { + p_image->x0 = p_j2k->m_private_image->x0; + } + p_image->x1 = (l_tile_x + 1) * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0; + if (p_image->x1 > p_j2k->m_private_image->x1) { + p_image->x1 = p_j2k->m_private_image->x1; + } - /* Create the ouput image from the information previously computed*/ - p_j2k->m_output_image = opj_image_create0(); - if (! (p_j2k->m_output_image)) { - return OPJ_FALSE; - } - opj_copy_image_header(p_image, p_j2k->m_output_image); + p_image->y0 = l_tile_y * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0; + if (p_image->y0 < p_j2k->m_private_image->y0) { + p_image->y0 = p_j2k->m_private_image->y0; + } + p_image->y1 = (l_tile_y + 1) * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0; + if (p_image->y1 > p_j2k->m_private_image->y1) { + p_image->y1 = p_j2k->m_private_image->y1; + } + + l_img_comp = p_image->comps; + for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) { + OPJ_INT32 l_comp_x1, l_comp_y1; - p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = (OPJ_INT32)tile_index; + l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; - /* customization of the decoding */ - opj_j2k_setup_decoding_tile(p_j2k, p_manager); + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); - /* Decode the codestream */ - if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) { - opj_image_destroy(p_j2k->m_private_image); - p_j2k->m_private_image = NULL; - return OPJ_FALSE; + l_img_comp->w = (OPJ_UINT32)(opj_int_ceildivpow2(l_comp_x1, + (OPJ_INT32)l_img_comp->factor) - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, + (OPJ_INT32)l_img_comp->factor)); + l_img_comp->h = (OPJ_UINT32)(opj_int_ceildivpow2(l_comp_y1, + (OPJ_INT32)l_img_comp->factor) - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, + (OPJ_INT32)l_img_comp->factor)); + + l_img_comp++; + } + + if (p_image->numcomps > p_j2k->m_private_image->numcomps) { + /* Can happen when calling repeatdly opj_get_decoded_tile() on an + * image with a color palette, where color palette expansion is done + * later in jp2.c */ + for (compno = p_j2k->m_private_image->numcomps; compno < p_image->numcomps; + ++compno) { + opj_image_data_free(p_image->comps[compno].data); + p_image->comps[compno].data = NULL; } + p_image->numcomps = p_j2k->m_private_image->numcomps; + } - /* Move data and copy one information from codec to output image*/ - for (compno = 0; compno < p_image->numcomps; compno++) { - p_image->comps[compno].resno_decoded = p_j2k->m_output_image->comps[compno].resno_decoded; + /* Destroy the previous output image*/ + if (p_j2k->m_output_image) { + opj_image_destroy(p_j2k->m_output_image); + } - if (p_image->comps[compno].data) - opj_free(p_image->comps[compno].data); + /* Create the ouput image from the information previously computed*/ + p_j2k->m_output_image = opj_image_create0(); + if (!(p_j2k->m_output_image)) { + return OPJ_FALSE; + } + opj_copy_image_header(p_image, p_j2k->m_output_image); - p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data; + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = (OPJ_INT32)tile_index; - p_j2k->m_output_image->comps[compno].data = NULL; - } + /* customization of the decoding */ + if (!opj_j2k_setup_decoding_tile(p_j2k, p_manager)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + /* Decode the codestream */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + /* Move data and copy one information from codec to output image*/ + return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image); } OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, - OPJ_UINT32 res_factor, - opj_event_mgr_t * p_manager) -{ - OPJ_UINT32 it_comp; - - p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor; - - if (p_j2k->m_private_image) { - if (p_j2k->m_private_image->comps) { - if (p_j2k->m_specific_param.m_decoder.m_default_tcp) { - if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps) { - for (it_comp = 0 ; it_comp < p_j2k->m_private_image->numcomps; it_comp++) { - OPJ_UINT32 max_res = p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[it_comp].numresolutions; - if ( res_factor >= max_res){ - opj_event_msg(p_manager, EVT_ERROR, "Resolution factor is greater than the maximum resolution in the component.\n"); - return OPJ_FALSE; - } - p_j2k->m_private_image->comps[it_comp].factor = res_factor; - } - return OPJ_TRUE; - } + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 it_comp; + + p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor; + + if (p_j2k->m_private_image) { + if (p_j2k->m_private_image->comps) { + if (p_j2k->m_specific_param.m_decoder.m_default_tcp) { + if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps) { + for (it_comp = 0 ; it_comp < p_j2k->m_private_image->numcomps; it_comp++) { + OPJ_UINT32 max_res = + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[it_comp].numresolutions; + if (res_factor >= max_res) { + opj_event_msg(p_manager, EVT_ERROR, + "Resolution factor is greater than the maximum resolution in the component.\n"); + return OPJ_FALSE; } + p_j2k->m_private_image->comps[it_comp].factor = res_factor; + } + return OPJ_TRUE; } + } } + } - return OPJ_FALSE; + return OPJ_FALSE; } OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 i, j; - OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 l_max_tile_size = 0, l_current_tile_size; - OPJ_BYTE * l_current_data = 00; - opj_tcd_t* p_tcd = 00; - - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - p_tcd = p_j2k->m_tcd; - - l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - for (i=0;i<l_nb_tiles;++i) { - if (! opj_j2k_pre_write_tile(p_j2k,i,p_stream,p_manager)) { - if (l_current_data) { - opj_free(l_current_data); - } - return OPJ_FALSE; - } + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_nb_tiles; + OPJ_SIZE_T l_max_tile_size = 0, l_current_tile_size; + OPJ_BYTE * l_current_data = 00; + OPJ_BOOL l_reuse_data = OPJ_FALSE; + opj_tcd_t* p_tcd = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + p_tcd = p_j2k->m_tcd; + + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + if (l_nb_tiles == 1) { + l_reuse_data = OPJ_TRUE; +#ifdef __SSE__ + for (j = 0; j < p_j2k->m_tcd->image->numcomps; ++j) { + opj_image_comp_t * l_img_comp = p_tcd->image->comps + j; + if (((size_t)l_img_comp->data & 0xFU) != + 0U) { /* tile data shall be aligned on 16 bytes */ + l_reuse_data = OPJ_FALSE; + } + } +#endif + } + for (i = 0; i < l_nb_tiles; ++i) { + if (! opj_j2k_pre_write_tile(p_j2k, i, p_stream, p_manager)) { + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_FALSE; + } - /* if we only have one tile, then simply set tile component data equal to image component data */ - /* otherwise, allocate the data */ - for (j=0;j<p_j2k->m_tcd->image->numcomps;++j) { - opj_tcd_tilecomp_t* l_tilec = p_tcd->tcd_image->tiles->comps + j; - if (l_nb_tiles == 1) { - opj_image_comp_t * l_img_comp = p_tcd->image->comps + j; - l_tilec->data = l_img_comp->data; - l_tilec->ownsData = OPJ_FALSE; - } else { - if(! opj_alloc_tile_component_data(l_tilec)) { - opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data." ); - if (l_current_data) { - opj_free(l_current_data); - } - return OPJ_FALSE; - } - } + /* if we only have one tile, then simply set tile component data equal to image component data */ + /* otherwise, allocate the data */ + for (j = 0; j < p_j2k->m_tcd->image->numcomps; ++j) { + opj_tcd_tilecomp_t* l_tilec = p_tcd->tcd_image->tiles->comps + j; + if (l_reuse_data) { + opj_image_comp_t * l_img_comp = p_tcd->image->comps + j; + l_tilec->data = l_img_comp->data; + l_tilec->ownsData = OPJ_FALSE; + } else { + if (! opj_alloc_tile_component_data(l_tilec)) { + opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data."); + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_FALSE; } - l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd); - if (l_nb_tiles > 1) { - if (l_current_tile_size > l_max_tile_size) { - OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_current_tile_size); - if (! l_new_current_data) { - if (l_current_data) { - opj_free(l_current_data); - } - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to encode all tiles\n"); - return OPJ_FALSE; - } - l_current_data = l_new_current_data; - l_max_tile_size = l_current_tile_size; - } - - /* copy image data (32 bit) to l_current_data as contiguous, all-component, zero offset buffer */ - /* 32 bit components @ 8 bit precision get converted to 8 bit */ - /* 32 bit components @ 16 bit precision get converted to 16 bit */ - opj_j2k_get_tile_data(p_j2k->m_tcd,l_current_data); - - /* now copy this data into the tile component */ - if (! opj_tcd_copy_tile_data(p_j2k->m_tcd,l_current_data,l_current_tile_size)) { - opj_event_msg(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." ); - opj_free(l_current_data); - return OPJ_FALSE; - } + } + } + l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd); + if (!l_reuse_data) { + if (l_current_tile_size > l_max_tile_size) { + OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, + l_current_tile_size); + if (! l_new_current_data) { + if (l_current_data) { + opj_free(l_current_data); + } + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to encode all tiles\n"); + return OPJ_FALSE; } + l_current_data = l_new_current_data; + l_max_tile_size = l_current_tile_size; + } + if (l_current_data == NULL) { + /* Should not happen in practice, but will avoid Coverity to */ + /* complain about a null pointer dereference */ + assert(0); + return OPJ_FALSE; + } - if (! opj_j2k_post_write_tile (p_j2k,p_stream,p_manager)) { - if (l_current_data) { - opj_free(l_current_data); - } - return OPJ_FALSE; - } + /* copy image data (32 bit) to l_current_data as contiguous, all-component, zero offset buffer */ + /* 32 bit components @ 8 bit precision get converted to 8 bit */ + /* 32 bit components @ 16 bit precision get converted to 16 bit */ + opj_j2k_get_tile_data(p_j2k->m_tcd, l_current_data); + + /* now copy this data into the tile component */ + if (! opj_tcd_copy_tile_data(p_j2k->m_tcd, l_current_data, + l_current_tile_size)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size mismatch between tile data and sent data."); + opj_free(l_current_data); + return OPJ_FALSE; + } } - if (l_current_data) { + if (! opj_j2k_post_write_tile(p_j2k, p_stream, p_manager)) { + if (l_current_data) { opj_free(l_current_data); + } + return OPJ_FALSE; } - return OPJ_TRUE; + } + + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_TRUE; } -OPJ_BOOL opj_j2k_end_compress( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager) +OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - /* customization of the encoding */ - if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) { - return OPJ_FALSE; - } + /* customization of the encoding */ + if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) { + return OPJ_FALSE; + } - if (! opj_j2k_exec (p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) - { - return OPJ_FALSE; - } + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_image_t * p_image, - opj_event_mgr_t * p_manager) -{ - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - p_j2k->m_private_image = opj_image_create0(); - if (! p_j2k->m_private_image) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to allocate image header." ); - return OPJ_FALSE; - } - opj_copy_image_header(p_image, p_j2k->m_private_image); + opj_stream_private_t *p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); - /* TODO_MSD: Find a better way */ - if (p_image->comps) { - OPJ_UINT32 it_comp; - for (it_comp = 0 ; it_comp < p_image->numcomps; it_comp++) { - if (p_image->comps[it_comp].data) { - p_j2k->m_private_image->comps[it_comp].data =p_image->comps[it_comp].data; - p_image->comps[it_comp].data = NULL; + p_j2k->m_private_image = opj_image_create0(); + if (! p_j2k->m_private_image) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to allocate image header."); + return OPJ_FALSE; + } + opj_copy_image_header(p_image, p_j2k->m_private_image); - } - } - } + /* TODO_MSD: Find a better way */ + if (p_image->comps) { + OPJ_UINT32 it_comp; + for (it_comp = 0 ; it_comp < p_image->numcomps; it_comp++) { + if (p_image->comps[it_comp].data) { + p_j2k->m_private_image->comps[it_comp].data = p_image->comps[it_comp].data; + p_image->comps[it_comp].data = NULL; - /* customization of the validation */ - if (! opj_j2k_setup_encoding_validation (p_j2k, p_manager)) { - return OPJ_FALSE; + } } + } - /* validation of the parameters codec */ - if (! opj_j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) { - return OPJ_FALSE; - } + /* customization of the validation */ + if (! opj_j2k_setup_encoding_validation(p_j2k, p_manager)) { + return OPJ_FALSE; + } - /* customization of the encoding */ - if (! opj_j2k_setup_header_writing(p_j2k, p_manager)) { - return OPJ_FALSE; - } + /* validation of the parameters codec */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream, p_manager)) { + return OPJ_FALSE; + } - /* write header */ - if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) { - return OPJ_FALSE; - } + /* customization of the encoding */ + if (! opj_j2k_setup_header_writing(p_j2k, p_manager)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + /* write header */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_pre_write_tile ( opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_pre_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - (void)p_stream; - if (p_tile_index != p_j2k->m_current_tile_number) { - opj_event_msg(p_manager, EVT_ERROR, "The given tile index does not match." ); - return OPJ_FALSE; - } + (void)p_stream; + if (p_tile_index != p_j2k->m_current_tile_number) { + opj_event_msg(p_manager, EVT_ERROR, "The given tile index does not match."); + return OPJ_FALSE; + } - opj_event_msg(p_manager, EVT_INFO, "tile number %d / %d\n", p_j2k->m_current_tile_number + 1, p_j2k->m_cp.tw * p_j2k->m_cp.th); + opj_event_msg(p_manager, EVT_INFO, "tile number %d / %d\n", + p_j2k->m_current_tile_number + 1, p_j2k->m_cp.tw * p_j2k->m_cp.th); - p_j2k->m_specific_param.m_encoder.m_current_tile_part_number = 0; - p_j2k->m_tcd->cur_totnum_tp = p_j2k->m_cp.tcps[p_tile_index].m_nb_tile_parts; - p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number = 0; + p_j2k->m_tcd->cur_totnum_tp = p_j2k->m_cp.tcps[p_tile_index].m_nb_tile_parts; + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; - /* initialisation before tile encoding */ - if (! opj_tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, p_manager)) { - return OPJ_FALSE; - } + /* initialisation before tile encoding */ + if (! opj_tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, + p_manager)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } static void opj_get_tile_dimensions(opj_image_t * l_image, - opj_tcd_tilecomp_t * l_tilec, - opj_image_comp_t * l_img_comp, - OPJ_UINT32* l_size_comp, - OPJ_UINT32* l_width, - OPJ_UINT32* l_height, - OPJ_UINT32* l_offset_x, - OPJ_UINT32* l_offset_y, - OPJ_UINT32* l_image_width, - OPJ_UINT32* l_stride, - OPJ_UINT32* l_tile_offset) { - OPJ_UINT32 l_remaining; - *l_size_comp = l_img_comp->prec >> 3; /* (/8) */ - l_remaining = l_img_comp->prec & 7; /* (%8) */ - if (l_remaining) { - *l_size_comp += 1; - } - - if (*l_size_comp == 3) { - *l_size_comp = 4; - } - - *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); - *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); - *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx); - *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy); - *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 - (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx); - *l_stride = *l_image_width - *l_width; - *l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + ((OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width; -} - -static void opj_j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data) -{ - OPJ_UINT32 i,j,k = 0; - - for (i=0;i<p_tcd->image->numcomps;++i) { - opj_image_t * l_image = p_tcd->image; - OPJ_INT32 * l_src_ptr; - opj_tcd_tilecomp_t * l_tilec = p_tcd->tcd_image->tiles->comps + i; - opj_image_comp_t * l_img_comp = l_image->comps + i; - OPJ_UINT32 l_size_comp,l_width,l_height,l_offset_x,l_offset_y, l_image_width,l_stride,l_tile_offset; - - opj_get_tile_dimensions(l_image, - l_tilec, - l_img_comp, - &l_size_comp, - &l_width, - &l_height, - &l_offset_x, - &l_offset_y, - &l_image_width, - &l_stride, - &l_tile_offset); - - l_src_ptr = l_img_comp->data + l_tile_offset; - - switch (l_size_comp) { - case 1: - { - OPJ_CHAR * l_dest_ptr = (OPJ_CHAR*) p_data; - if (l_img_comp->sgnd) { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr) = (OPJ_CHAR) (*l_src_ptr); - ++l_dest_ptr; - ++l_src_ptr; - } - l_src_ptr += l_stride; - } - } - else { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr) = (OPJ_CHAR)((*l_src_ptr)&0xff); - ++l_dest_ptr; - ++l_src_ptr; - } - l_src_ptr += l_stride; - } - } - - p_data = (OPJ_BYTE*) l_dest_ptr; - } - break; - case 2: - { - OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_data; - if (l_img_comp->sgnd) { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (OPJ_INT16) (*(l_src_ptr++)); - } - l_src_ptr += l_stride; - } - } - else { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (OPJ_INT16)((*(l_src_ptr++)) & 0xffff); - } - l_src_ptr += l_stride; - } - } - - p_data = (OPJ_BYTE*) l_dest_ptr; - } - break; - case 4: - { - OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_data; - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = *(l_src_ptr++); - } - l_src_ptr += l_stride; - } - - p_data = (OPJ_BYTE*) l_dest_ptr; - } - break; + opj_tcd_tilecomp_t * l_tilec, + opj_image_comp_t * l_img_comp, + OPJ_UINT32* l_size_comp, + OPJ_UINT32* l_width, + OPJ_UINT32* l_height, + OPJ_UINT32* l_offset_x, + OPJ_UINT32* l_offset_y, + OPJ_UINT32* l_image_width, + OPJ_UINT32* l_stride, + OPJ_UINT32* l_tile_offset) +{ + OPJ_UINT32 l_remaining; + *l_size_comp = l_img_comp->prec >> 3; /* (/8) */ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + if (l_remaining) { + *l_size_comp += 1; + } + + if (*l_size_comp == 3) { + *l_size_comp = 4; + } + + *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); + *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); + *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx); + *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy); + *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 - + (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx); + *l_stride = *l_image_width - *l_width; + *l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + (( + OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width; +} + +static void opj_j2k_get_tile_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data) +{ + OPJ_UINT32 i, j, k = 0; + + for (i = 0; i < p_tcd->image->numcomps; ++i) { + opj_image_t * l_image = p_tcd->image; + OPJ_INT32 * l_src_ptr; + opj_tcd_tilecomp_t * l_tilec = p_tcd->tcd_image->tiles->comps + i; + opj_image_comp_t * l_img_comp = l_image->comps + i; + OPJ_UINT32 l_size_comp, l_width, l_height, l_offset_x, l_offset_y, + l_image_width, l_stride, l_tile_offset; + + opj_get_tile_dimensions(l_image, + l_tilec, + l_img_comp, + &l_size_comp, + &l_width, + &l_height, + &l_offset_x, + &l_offset_y, + &l_image_width, + &l_stride, + &l_tile_offset); + + l_src_ptr = l_img_comp->data + l_tile_offset; + + switch (l_size_comp) { + case 1: { + OPJ_CHAR * l_dest_ptr = (OPJ_CHAR*) p_data; + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr) = (OPJ_CHAR)(*l_src_ptr); + ++l_dest_ptr; + ++l_src_ptr; + } + l_src_ptr += l_stride; } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr) = (OPJ_CHAR)((*l_src_ptr) & 0xff); + ++l_dest_ptr; + ++l_src_ptr; + } + l_src_ptr += l_stride; + } + } + + p_data = (OPJ_BYTE*) l_dest_ptr; + } + break; + case 2: { + OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_data; + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_INT16)(*(l_src_ptr++)); + } + l_src_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_INT16)((*(l_src_ptr++)) & 0xffff); + } + l_src_ptr += l_stride; + } + } + + p_data = (OPJ_BYTE*) l_dest_ptr; + } + break; + case 4: { + OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_data; + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = *(l_src_ptr++); + } + l_src_ptr += l_stride; + } + + p_data = (OPJ_BYTE*) l_dest_ptr; + } + break; } + } } -static OPJ_BOOL opj_j2k_post_write_tile ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_j2k_post_write_tile(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - OPJ_UINT32 l_nb_bytes_written; - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_tile_size = 0; - OPJ_UINT32 l_available_data; + OPJ_UINT32 l_nb_bytes_written; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tile_size = 0; + OPJ_UINT32 l_available_data; - /* preconditions */ - assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + /* preconditions */ + assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); - l_tile_size = p_j2k->m_specific_param.m_encoder.m_encoded_tile_size; - l_available_data = l_tile_size; - l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data; + l_tile_size = p_j2k->m_specific_param.m_encoder.m_encoded_tile_size; + l_available_data = l_tile_size; + l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data; - l_nb_bytes_written = 0; - if (! opj_j2k_write_first_tile_part(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) { - return OPJ_FALSE; - } - l_current_data += l_nb_bytes_written; - l_available_data -= l_nb_bytes_written; + l_nb_bytes_written = 0; + if (! opj_j2k_write_first_tile_part(p_j2k, l_current_data, &l_nb_bytes_written, + l_available_data, p_stream, p_manager)) { + return OPJ_FALSE; + } + l_current_data += l_nb_bytes_written; + l_available_data -= l_nb_bytes_written; - l_nb_bytes_written = 0; - if (! opj_j2k_write_all_tile_parts(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) { - return OPJ_FALSE; - } + l_nb_bytes_written = 0; + if (! opj_j2k_write_all_tile_parts(p_j2k, l_current_data, &l_nb_bytes_written, + l_available_data, p_stream, p_manager)) { + return OPJ_FALSE; + } - l_available_data -= l_nb_bytes_written; - l_nb_bytes_written = l_tile_size - l_available_data; + l_available_data -= l_nb_bytes_written; + l_nb_bytes_written = l_tile_size - l_available_data; - if ( opj_stream_write_data( p_stream, - p_j2k->m_specific_param.m_encoder.m_encoded_tile_data, - l_nb_bytes_written,p_manager) != l_nb_bytes_written) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data, + l_nb_bytes_written, p_manager) != l_nb_bytes_written) { + return OPJ_FALSE; + } - ++p_j2k->m_current_tile_number; + ++p_j2k->m_current_tile_number; - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_setup_end_compress (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_end_compress(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); - /* DEVELOPER CORNER, insert your custom procedures */ - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_eoc, p_manager)) { - return OPJ_FALSE; - } + /* DEVELOPER CORNER, insert your custom procedures */ + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_eoc, p_manager)) { + return OPJ_FALSE; + } - if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) { - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_updated_tlm, p_manager)) { - return OPJ_FALSE; - } + if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_updated_tlm, p_manager)) { + return OPJ_FALSE; } + } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_epc, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_end_encoding, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_destroy_header_memory, p_manager)) { - return OPJ_FALSE; - } - return OPJ_TRUE; + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_epc, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_end_encoding, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_destroy_header_memory, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_setup_encoding_validation (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_encoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); - if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_build_encoder, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_encoding_validation, p_manager)) { - return OPJ_FALSE; - } + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_build_encoder, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_encoding_validation, p_manager)) { + return OPJ_FALSE; + } - /* DEVELOPER CORNER, add your custom validation procedure */ - if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_mct_validation, p_manager)) { - return OPJ_FALSE; - } - - return OPJ_TRUE; + /* DEVELOPER CORNER, add your custom validation procedure */ + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_mct_validation, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_setup_header_writing (opj_j2k_t *p_j2k, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_init_info, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_soc, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_siz, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_cod, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_qcd, p_manager)) { - return OPJ_FALSE; - } + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); - if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) { - /* No need for COC or QCC, QCD and COD are used - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_coc, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_all_qcc, p_manager)) { - return OPJ_FALSE; - } - */ - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_tlm, p_manager)) { - return OPJ_FALSE; - } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_init_info, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_soc, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_siz, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_cod, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_qcd, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_all_coc, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_all_qcc, p_manager)) { + return OPJ_FALSE; + } - if (p_j2k->m_cp.rsiz == OPJ_PROFILE_CINEMA_4K) { - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_poc, p_manager)) { - return OPJ_FALSE; - } - } + if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz)) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_tlm, p_manager)) { + return OPJ_FALSE; } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_regions, p_manager)) { + if (p_j2k->m_cp.rsiz == OPJ_PROFILE_CINEMA_4K) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_poc, p_manager)) { return OPJ_FALSE; + } } + } - if (p_j2k->m_cp.comment != 00) { - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_com, p_manager)) { - return OPJ_FALSE; - } - } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_regions, p_manager)) { + return OPJ_FALSE; + } - /* DEVELOPER CORNER, insert your custom procedures */ - if (p_j2k->m_cp.rsiz & OPJ_EXTENSION_MCT) { - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_mct_data_group, p_manager)) { - return OPJ_FALSE; - } + if (p_j2k->m_cp.comment != 00) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_com, p_manager)) { + return OPJ_FALSE; } - /* End of Developer Corner */ + } - if (p_j2k->cstr_index) { - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_get_end_header, p_manager)) { - return OPJ_FALSE; - } + /* DEVELOPER CORNER, insert your custom procedures */ + if (p_j2k->m_cp.rsiz & OPJ_EXTENSION_MCT) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_mct_data_group, p_manager)) { + return OPJ_FALSE; } + } + /* End of Developer Corner */ - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_create_tcd, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_update_rates, p_manager)) { - return OPJ_FALSE; + if (p_j2k->cstr_index) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_get_end_header, p_manager)) { + return OPJ_FALSE; } + } - return OPJ_TRUE; + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_create_tcd, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_update_rates, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_first_tile_part (opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 l_nb_bytes_written = 0; - OPJ_UINT32 l_current_nb_bytes_written; - OPJ_BYTE * l_begin_data = 00; + OPJ_UINT32 l_nb_bytes_written = 0; + OPJ_UINT32 l_current_nb_bytes_written; + OPJ_BYTE * l_begin_data = 00; - opj_tcd_t * l_tcd = 00; - opj_cp_t * l_cp = 00; + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; - l_tcd = p_j2k->m_tcd; - l_cp = &(p_j2k->m_cp); + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); - l_tcd->cur_pino = 0; + l_tcd->cur_pino = 0; - /*Get number of tile parts*/ - p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; + /*Get number of tile parts*/ + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; - /* INDEX >> */ - /* << INDEX */ + /* INDEX >> */ + /* << INDEX */ - l_current_nb_bytes_written = 0; - l_begin_data = p_data; - if (! opj_j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) - { - return OPJ_FALSE; - } + l_current_nb_bytes_written = 0; + l_begin_data = p_data; + if (! opj_j2k_write_sot(p_j2k, p_data, p_total_data_size, + &l_current_nb_bytes_written, p_stream, + p_manager)) { + return OPJ_FALSE; + } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; - if (!OPJ_IS_CINEMA(l_cp->rsiz)) { + if (!OPJ_IS_CINEMA(l_cp->rsiz)) { #if 0 - for (compno = 1; compno < p_j2k->m_private_image->numcomps; compno++) { - l_current_nb_bytes_written = 0; - opj_j2k_write_coc_in_memory(p_j2k,compno,p_data,&l_current_nb_bytes_written,p_manager); - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - - l_current_nb_bytes_written = 0; - opj_j2k_write_qcc_in_memory(p_j2k,compno,p_data,&l_current_nb_bytes_written,p_manager); - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - } + for (compno = 1; compno < p_j2k->m_private_image->numcomps; compno++) { + l_current_nb_bytes_written = 0; + opj_j2k_write_coc_in_memory(p_j2k, compno, p_data, &l_current_nb_bytes_written, + p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + + l_current_nb_bytes_written = 0; + opj_j2k_write_qcc_in_memory(p_j2k, compno, p_data, &l_current_nb_bytes_written, + p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + } #endif - - if (l_cp->tcps[p_j2k->m_current_tile_number].numpocs) { - l_current_nb_bytes_written = 0; - opj_j2k_write_poc_in_memory(p_j2k,p_data,&l_current_nb_bytes_written,p_manager); - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - } + if (l_cp->tcps[p_j2k->m_current_tile_number].numpocs) { + l_current_nb_bytes_written = 0; + opj_j2k_write_poc_in_memory(p_j2k, p_data, &l_current_nb_bytes_written, + p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; } + } - l_current_nb_bytes_written = 0; - if (! opj_j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) { - return OPJ_FALSE; - } + l_current_nb_bytes_written = 0; + if (! opj_j2k_write_sod(p_j2k, l_tcd, p_data, &l_current_nb_bytes_written, + p_total_data_size, p_stream, p_manager)) { + return OPJ_FALSE; + } - l_nb_bytes_written += l_current_nb_bytes_written; - * p_data_written = l_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + * p_data_written = l_nb_bytes_written; - /* Writing Psot in SOT marker */ - opj_write_bytes(l_begin_data + 6,l_nb_bytes_written,4); /* PSOT */ + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6, l_nb_bytes_written, + 4); /* PSOT */ - if (OPJ_IS_CINEMA(l_cp->rsiz)){ - opj_j2k_update_tlm(p_j2k,l_nb_bytes_written); - } + if (OPJ_IS_CINEMA(l_cp->rsiz)) { + opj_j2k_update_tlm(p_j2k, l_nb_bytes_written); + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_all_tile_parts( opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 tilepartno=0; - OPJ_UINT32 l_nb_bytes_written = 0; - OPJ_UINT32 l_current_nb_bytes_written; - OPJ_UINT32 l_part_tile_size; - OPJ_UINT32 tot_num_tp; - OPJ_UINT32 pino; - - OPJ_BYTE * l_begin_data; - opj_tcp_t *l_tcp = 00; - opj_tcd_t * l_tcd = 00; - opj_cp_t * l_cp = 00; - - l_tcd = p_j2k->m_tcd; - l_cp = &(p_j2k->m_cp); - l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; - - /*Get number of tile parts*/ - tot_num_tp = opj_j2k_get_num_tp(l_cp,0,p_j2k->m_current_tile_number); - - /* start writing remaining tile parts */ - ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; - for (tilepartno = 1; tilepartno < tot_num_tp ; ++tilepartno) { - p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; - l_current_nb_bytes_written = 0; - l_part_tile_size = 0; - l_begin_data = p_data; - - if (! opj_j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) { - return OPJ_FALSE; - } +static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 tilepartno = 0; + OPJ_UINT32 l_nb_bytes_written = 0; + OPJ_UINT32 l_current_nb_bytes_written; + OPJ_UINT32 l_part_tile_size; + OPJ_UINT32 tot_num_tp; + OPJ_UINT32 pino; + + OPJ_BYTE * l_begin_data; + opj_tcp_t *l_tcp = 00; + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; + + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); + l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; + + /*Get number of tile parts*/ + tot_num_tp = opj_j2k_get_num_tp(l_cp, 0, p_j2k->m_current_tile_number); + + /* start writing remaining tile parts */ + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + for (tilepartno = 1; tilepartno < tot_num_tp ; ++tilepartno) { + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; + l_current_nb_bytes_written = 0; + l_part_tile_size = 0; + l_begin_data = p_data; - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_current_nb_bytes_written; + if (! opj_j2k_write_sot(p_j2k, p_data, + p_total_data_size, + &l_current_nb_bytes_written, + p_stream, + p_manager)) { + return OPJ_FALSE; + } - l_current_nb_bytes_written = 0; - if (! opj_j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) { - return OPJ_FALSE; - } + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - l_nb_bytes_written += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_current_nb_bytes_written; + l_current_nb_bytes_written = 0; + if (! opj_j2k_write_sod(p_j2k, l_tcd, p_data, &l_current_nb_bytes_written, + p_total_data_size, p_stream, p_manager)) { + return OPJ_FALSE; + } - /* Writing Psot in SOT marker */ - opj_write_bytes(l_begin_data + 6,l_part_tile_size,4); /* PSOT */ + p_data += l_current_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; - if (OPJ_IS_CINEMA(l_cp->rsiz)) { - opj_j2k_update_tlm(p_j2k,l_part_tile_size); - } + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6, l_part_tile_size, + 4); /* PSOT */ - ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + if (OPJ_IS_CINEMA(l_cp->rsiz)) { + opj_j2k_update_tlm(p_j2k, l_part_tile_size); } - for (pino = 1; pino <= l_tcp->numpocs; ++pino) { - l_tcd->cur_pino = pino; + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + } - /*Get number of tile parts*/ - tot_num_tp = opj_j2k_get_num_tp(l_cp,pino,p_j2k->m_current_tile_number); - for (tilepartno = 0; tilepartno < tot_num_tp ; ++tilepartno) { - p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; - l_current_nb_bytes_written = 0; - l_part_tile_size = 0; - l_begin_data = p_data; + for (pino = 1; pino <= l_tcp->numpocs; ++pino) { + l_tcd->cur_pino = pino; - if (! opj_j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) { - return OPJ_FALSE; - } + /*Get number of tile parts*/ + tot_num_tp = opj_j2k_get_num_tp(l_cp, pino, p_j2k->m_current_tile_number); + for (tilepartno = 0; tilepartno < tot_num_tp ; ++tilepartno) { + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; + l_current_nb_bytes_written = 0; + l_part_tile_size = 0; + l_begin_data = p_data; + + if (! opj_j2k_write_sot(p_j2k, p_data, + p_total_data_size, + &l_current_nb_bytes_written, p_stream, + p_manager)) { + return OPJ_FALSE; + } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_current_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; - l_current_nb_bytes_written = 0; + l_current_nb_bytes_written = 0; - if (! opj_j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) { - return OPJ_FALSE; - } + if (! opj_j2k_write_sod(p_j2k, l_tcd, p_data, &l_current_nb_bytes_written, + p_total_data_size, p_stream, p_manager)) { + return OPJ_FALSE; + } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_current_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; - /* Writing Psot in SOT marker */ - opj_write_bytes(l_begin_data + 6,l_part_tile_size,4); /* PSOT */ + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6, l_part_tile_size, + 4); /* PSOT */ - if (OPJ_IS_CINEMA(l_cp->rsiz)) { - opj_j2k_update_tlm(p_j2k,l_part_tile_size); - } + if (OPJ_IS_CINEMA(l_cp->rsiz)) { + opj_j2k_update_tlm(p_j2k, l_part_tile_size); + } - ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; - } + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; } + } - *p_data_written = l_nb_bytes_written; + *p_data_written = l_nb_bytes_written; - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_write_updated_tlm( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_write_updated_tlm(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - OPJ_UINT32 l_tlm_size; - OPJ_OFF_T l_tlm_position, l_current_position; + OPJ_UINT32 l_tlm_size; + OPJ_OFF_T l_tlm_position, l_current_position; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - l_tlm_size = 5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts; - l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start; - l_current_position = opj_stream_tell(p_stream); + l_tlm_size = 5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts; + l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start; + l_current_position = opj_stream_tell(p_stream); - if (! opj_stream_seek(p_stream,l_tlm_position,p_manager)) { - return OPJ_FALSE; - } + if (! opj_stream_seek(p_stream, l_tlm_position, p_manager)) { + return OPJ_FALSE; + } - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer,l_tlm_size,p_manager) != l_tlm_size) { - return OPJ_FALSE; - } + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer, l_tlm_size, + p_manager) != l_tlm_size) { + return OPJ_FALSE; + } - if (! opj_stream_seek(p_stream,l_current_position,p_manager)) { - return OPJ_FALSE; - } + if (! opj_stream_seek(p_stream, l_current_position, p_manager)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_end_encoding( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_end_encoding(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - opj_tcd_destroy(p_j2k->m_tcd); - p_j2k->m_tcd = 00; + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); - if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { - opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 0; - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 0; - } + opj_tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; - if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); - p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 0; - } + if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { + opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 0; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 0; + } + + if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 0; + } - p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = 0; + p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = 0; - return OPJ_TRUE; + return OPJ_TRUE; } /** * Destroys the memory associated with the decoding of headers. */ -static OPJ_BOOL opj_j2k_destroy_header_memory ( opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - /* preconditions */ - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) { - opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); - p_j2k->m_specific_param.m_encoder.m_header_tile_data = 0; - } +static OPJ_BOOL opj_j2k_destroy_header_memory(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); + + if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = 0; + } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_j2k_init_info( opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ) +static OPJ_BOOL opj_j2k_init_info(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) { - opj_codestream_info_t * l_cstr_info = 00; + opj_codestream_info_t * l_cstr_info = 00; - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - (void)l_cstr_info; + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + (void)l_cstr_info; - /* TODO mergeV2: check this part which use cstr_info */ - /*l_cstr_info = p_j2k->cstr_info; + OPJ_UNUSED(p_stream); - if (l_cstr_info) { - OPJ_UINT32 compno; - l_cstr_info->tile = (opj_tile_info_t *) opj_malloc(p_j2k->m_cp.tw * p_j2k->m_cp.th * sizeof(opj_tile_info_t)); + /* TODO mergeV2: check this part which use cstr_info */ + /*l_cstr_info = p_j2k->cstr_info; - l_cstr_info->image_w = p_j2k->m_image->x1 - p_j2k->m_image->x0; - l_cstr_info->image_h = p_j2k->m_image->y1 - p_j2k->m_image->y0; + if (l_cstr_info) { + OPJ_UINT32 compno; + l_cstr_info->tile = (opj_tile_info_t *) opj_malloc(p_j2k->m_cp.tw * p_j2k->m_cp.th * sizeof(opj_tile_info_t)); - l_cstr_info->prog = (&p_j2k->m_cp.tcps[0])->prg; + l_cstr_info->image_w = p_j2k->m_image->x1 - p_j2k->m_image->x0; + l_cstr_info->image_h = p_j2k->m_image->y1 - p_j2k->m_image->y0; - l_cstr_info->tw = p_j2k->m_cp.tw; - l_cstr_info->th = p_j2k->m_cp.th; + l_cstr_info->prog = (&p_j2k->m_cp.tcps[0])->prg; - l_cstr_info->tile_x = p_j2k->m_cp.tdx;*/ /* new version parser */ - /*l_cstr_info->tile_y = p_j2k->m_cp.tdy;*/ /* new version parser */ - /*l_cstr_info->tile_Ox = p_j2k->m_cp.tx0;*/ /* new version parser */ - /*l_cstr_info->tile_Oy = p_j2k->m_cp.ty0;*/ /* new version parser */ + l_cstr_info->tw = p_j2k->m_cp.tw; + l_cstr_info->th = p_j2k->m_cp.th; - /*l_cstr_info->numcomps = p_j2k->m_image->numcomps; + l_cstr_info->tile_x = p_j2k->m_cp.tdx;*/ /* new version parser */ + /*l_cstr_info->tile_y = p_j2k->m_cp.tdy;*/ /* new version parser */ + /*l_cstr_info->tile_Ox = p_j2k->m_cp.tx0;*/ /* new version parser */ + /*l_cstr_info->tile_Oy = p_j2k->m_cp.ty0;*/ /* new version parser */ - l_cstr_info->numlayers = (&p_j2k->m_cp.tcps[0])->numlayers; + /*l_cstr_info->numcomps = p_j2k->m_image->numcomps; - l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(p_j2k->m_image->numcomps * sizeof(OPJ_INT32)); + l_cstr_info->numlayers = (&p_j2k->m_cp.tcps[0])->numlayers; - for (compno=0; compno < p_j2k->m_image->numcomps; compno++) { - l_cstr_info->numdecompos[compno] = (&p_j2k->m_cp.tcps[0])->tccps->numresolutions - 1; - } + l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(p_j2k->m_image->numcomps * sizeof(OPJ_INT32)); + + for (compno=0; compno < p_j2k->m_image->numcomps; compno++) { + l_cstr_info->numdecompos[compno] = (&p_j2k->m_cp.tcps[0])->tccps->numresolutions - 1; + } - l_cstr_info->D_max = 0.0; */ /* ADD Marcela */ + l_cstr_info->D_max = 0.0; */ /* ADD Marcela */ - /*l_cstr_info->main_head_start = opj_stream_tell(p_stream);*/ /* position of SOC */ + /*l_cstr_info->main_head_start = opj_stream_tell(p_stream);*/ /* position of SOC */ - /*l_cstr_info->maxmarknum = 100; - l_cstr_info->marker = (opj_marker_info_t *) opj_malloc(l_cstr_info->maxmarknum * sizeof(opj_marker_info_t)); - l_cstr_info->marknum = 0; - }*/ + /*l_cstr_info->maxmarknum = 100; + l_cstr_info->marker = (opj_marker_info_t *) opj_malloc(l_cstr_info->maxmarknum * sizeof(opj_marker_info_t)); + l_cstr_info->marknum = 0; + }*/ - return opj_j2k_calculate_tp(p_j2k,&(p_j2k->m_cp),&p_j2k->m_specific_param.m_encoder.m_total_tile_parts,p_j2k->m_private_image,p_manager); + return opj_j2k_calculate_tp(p_j2k, &(p_j2k->m_cp), + &p_j2k->m_specific_param.m_encoder.m_total_tile_parts, p_j2k->m_private_image, + p_manager); } /** - * Creates a tile-coder decoder. + * Creates a tile-coder encoder. * * @param p_stream the stream to write data to. * @param p_j2k J2K codec. * @param p_manager the user event manager. */ -static OPJ_BOOL opj_j2k_create_tcd( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - p_j2k->m_tcd = opj_tcd_create(OPJ_FALSE); + OPJ_UNUSED(p_stream); - if (! p_j2k->m_tcd) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n"); - return OPJ_FALSE; - } + p_j2k->m_tcd = opj_tcd_create(OPJ_FALSE); - if (!opj_tcd_init(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp)) { - opj_tcd_destroy(p_j2k->m_tcd); - p_j2k->m_tcd = 00; - return OPJ_FALSE; - } + if (! p_j2k->m_tcd) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + if (!opj_tcd_init(p_j2k->m_tcd, p_j2k->m_private_image, &p_j2k->m_cp, + p_j2k->m_tp)) { + opj_tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + return OPJ_FALSE; + } + + return OPJ_TRUE; } -OPJ_BOOL opj_j2k_write_tile (opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ) +OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) { - if (! opj_j2k_pre_write_tile(p_j2k,p_tile_index,p_stream,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error while opj_j2k_pre_write_tile with tile index = %d\n", p_tile_index); + if (! opj_j2k_pre_write_tile(p_j2k, p_tile_index, p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error while opj_j2k_pre_write_tile with tile index = %d\n", p_tile_index); + return OPJ_FALSE; + } else { + OPJ_UINT32 j; + /* Allocate data */ + for (j = 0; j < p_j2k->m_tcd->image->numcomps; ++j) { + opj_tcd_tilecomp_t* l_tilec = p_j2k->m_tcd->tcd_image->tiles->comps + j; + + if (! opj_alloc_tile_component_data(l_tilec)) { + opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data."); return OPJ_FALSE; + } } - else { - OPJ_UINT32 j; - /* Allocate data */ - for (j=0;j<p_j2k->m_tcd->image->numcomps;++j) { - opj_tcd_tilecomp_t* l_tilec = p_j2k->m_tcd->tcd_image->tiles->comps + j; - - if(! opj_alloc_tile_component_data(l_tilec)) { - opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data." ); - return OPJ_FALSE; - } - } - /* now copy data into the the tile component */ - if (! opj_tcd_copy_tile_data(p_j2k->m_tcd,p_data,p_data_size)) { - opj_event_msg(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." ); - return OPJ_FALSE; - } - if (! opj_j2k_post_write_tile(p_j2k,p_stream,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Error while opj_j2k_post_write_tile with tile index = %d\n", p_tile_index); - return OPJ_FALSE; - } + /* now copy data into the tile component */ + if (! opj_tcd_copy_tile_data(p_j2k->m_tcd, p_data, p_data_size)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size mismatch between tile data and sent data."); + return OPJ_FALSE; + } + if (! opj_j2k_post_write_tile(p_j2k, p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error while opj_j2k_post_write_tile with tile index = %d\n", p_tile_index); + return OPJ_FALSE; } + } - return OPJ_TRUE; + return OPJ_TRUE; } diff --git a/third_party/libopenjpeg20/j2k.h b/third_party/libopenjpeg20/j2k.h index 358e0739652c0b96481f6c23100c4768cef4c6a6..5d393c98130f27af8ee128175e504e580e4e4e13 100644 --- a/third_party/libopenjpeg20/j2k.h +++ b/third_party/libopenjpeg20/j2k.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,12 +8,12 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> - * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France * Copyright (c) 2012, CS Systemes d'Information, France * * All rights reserved. @@ -39,8 +39,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __J2K_H -#define __J2K_H +#ifndef OPJ_J2K_H +#define OPJ_J2K_H /** @file j2k.h @brief The JPEG-2000 Codestream Reader/Writer (J2K) @@ -65,43 +65,41 @@ The functions in J2K.C have for goal to read/write the several parts of the code #define J2K_CCP_QNTSTY_SIQNT 1 #define J2K_CCP_QNTSTY_SEQNT 2 -#define OPJ_J2K_DEFAULT_CBLK_DATA_SIZE 8192 - /* ----------------------------------------------------------------------- */ -#define J2K_MS_SOC 0xff4f /**< SOC marker value */ -#define J2K_MS_SOT 0xff90 /**< SOT marker value */ -#define J2K_MS_SOD 0xff93 /**< SOD marker value */ -#define J2K_MS_EOC 0xffd9 /**< EOC marker value */ -#define J2K_MS_SIZ 0xff51 /**< SIZ marker value */ -#define J2K_MS_COD 0xff52 /**< COD marker value */ -#define J2K_MS_COC 0xff53 /**< COC marker value */ -#define J2K_MS_RGN 0xff5e /**< RGN marker value */ -#define J2K_MS_QCD 0xff5c /**< QCD marker value */ -#define J2K_MS_QCC 0xff5d /**< QCC marker value */ -#define J2K_MS_POC 0xff5f /**< POC marker value */ -#define J2K_MS_TLM 0xff55 /**< TLM marker value */ -#define J2K_MS_PLM 0xff57 /**< PLM marker value */ -#define J2K_MS_PLT 0xff58 /**< PLT marker value */ -#define J2K_MS_PPM 0xff60 /**< PPM marker value */ -#define J2K_MS_PPT 0xff61 /**< PPT marker value */ -#define J2K_MS_SOP 0xff91 /**< SOP marker value */ -#define J2K_MS_EPH 0xff92 /**< EPH marker value */ -#define J2K_MS_CRG 0xff63 /**< CRG marker value */ -#define J2K_MS_COM 0xff64 /**< COM marker value */ -#define J2K_MS_CBD 0xff78 /**< CBD marker value */ -#define J2K_MS_MCC 0xff75 /**< MCC marker value */ -#define J2K_MS_MCT 0xff74 /**< MCT marker value */ -#define J2K_MS_MCO 0xff77 /**< MCO marker value */ - -#define J2K_MS_UNK 0 /**< UNKNOWN marker value */ +#define J2K_MS_SOC 0xff4f /**< SOC marker value */ +#define J2K_MS_SOT 0xff90 /**< SOT marker value */ +#define J2K_MS_SOD 0xff93 /**< SOD marker value */ +#define J2K_MS_EOC 0xffd9 /**< EOC marker value */ +#define J2K_MS_SIZ 0xff51 /**< SIZ marker value */ +#define J2K_MS_COD 0xff52 /**< COD marker value */ +#define J2K_MS_COC 0xff53 /**< COC marker value */ +#define J2K_MS_RGN 0xff5e /**< RGN marker value */ +#define J2K_MS_QCD 0xff5c /**< QCD marker value */ +#define J2K_MS_QCC 0xff5d /**< QCC marker value */ +#define J2K_MS_POC 0xff5f /**< POC marker value */ +#define J2K_MS_TLM 0xff55 /**< TLM marker value */ +#define J2K_MS_PLM 0xff57 /**< PLM marker value */ +#define J2K_MS_PLT 0xff58 /**< PLT marker value */ +#define J2K_MS_PPM 0xff60 /**< PPM marker value */ +#define J2K_MS_PPT 0xff61 /**< PPT marker value */ +#define J2K_MS_SOP 0xff91 /**< SOP marker value */ +#define J2K_MS_EPH 0xff92 /**< EPH marker value */ +#define J2K_MS_CRG 0xff63 /**< CRG marker value */ +#define J2K_MS_COM 0xff64 /**< COM marker value */ +#define J2K_MS_CBD 0xff78 /**< CBD marker value */ +#define J2K_MS_MCC 0xff75 /**< MCC marker value */ +#define J2K_MS_MCT 0xff74 /**< MCT marker value */ +#define J2K_MS_MCO 0xff77 /**< MCO marker value */ + +#define J2K_MS_UNK 0 /**< UNKNOWN marker value */ /* UniPG>> */ #ifdef USE_JPWL -#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ -#define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */ -#define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */ -#define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */ #endif /* USE_JPWL */ #ifdef USE_JPSEC #define J2K_MS_SEC 0xff65 /**< SEC marker value (Part 8: Secure JPEG 2000) */ @@ -109,6 +107,8 @@ The functions in J2K.C have for goal to read/write the several parts of the code #endif /* USE_JPSEC */ /* <<UniPG */ +#define J2K_MAX_POCS 32 /**< Maximum number of POCs */ + /* ----------------------------------------------------------------------- */ /** @@ -116,91 +116,89 @@ The functions in J2K.C have for goal to read/write the several parts of the code * These values may be combined with a | operator. * */ typedef enum J2K_STATUS { - J2K_STATE_NONE = 0x0000, /**< a SOC marker is expected */ - J2K_STATE_MHSOC = 0x0001, /**< a SOC marker is expected */ - J2K_STATE_MHSIZ = 0x0002, /**< a SIZ marker is expected */ - J2K_STATE_MH = 0x0004, /**< the decoding process is in the main header */ - J2K_STATE_TPHSOT = 0x0008, /**< the decoding process is in a tile part header and expects a SOT marker */ - J2K_STATE_TPH = 0x0010, /**< the decoding process is in a tile part header */ - J2K_STATE_MT = 0x0020, /**< the EOC marker has just been read */ - J2K_STATE_NEOC = 0x0040, /**< the decoding process must not expect a EOC marker because the codestream is truncated */ - - J2K_STATE_EOC = 0x0100, /**< the decoding process has encountered the EOC marker */ - J2K_STATE_ERR = 0x8000 /**< the decoding process has encountered an error (FIXME warning V1 = 0x0080)*/ + J2K_STATE_NONE = 0x0000, /**< a SOC marker is expected */ + J2K_STATE_MHSOC = 0x0001, /**< a SOC marker is expected */ + J2K_STATE_MHSIZ = 0x0002, /**< a SIZ marker is expected */ + J2K_STATE_MH = 0x0004, /**< the decoding process is in the main header */ + J2K_STATE_TPHSOT = 0x0008, /**< the decoding process is in a tile part header and expects a SOT marker */ + J2K_STATE_TPH = 0x0010, /**< the decoding process is in a tile part header */ + J2K_STATE_MT = 0x0020, /**< the EOC marker has just been read */ + J2K_STATE_NEOC = 0x0040, /**< the decoding process must not expect a EOC marker because the codestream is truncated */ + J2K_STATE_DATA = 0x0080, /**< a tile header has been successfully read and codestream is expected */ + + J2K_STATE_EOC = 0x0100, /**< the decoding process has encountered the EOC marker */ + J2K_STATE_ERR = 0x8000 /**< the decoding process has encountered an error (FIXME warning V1 = 0x0080)*/ } J2K_STATUS; /** * Type of elements storing in the MCT data */ -typedef enum MCT_ELEMENT_TYPE -{ - MCT_TYPE_INT16 = 0, /** MCT data is stored as signed shorts*/ - MCT_TYPE_INT32 = 1, /** MCT data is stored as signed integers*/ - MCT_TYPE_FLOAT = 2, /** MCT data is stored as floats*/ - MCT_TYPE_DOUBLE = 3 /** MCT data is stored as doubles*/ +typedef enum MCT_ELEMENT_TYPE { + MCT_TYPE_INT16 = 0, /** MCT data is stored as signed shorts*/ + MCT_TYPE_INT32 = 1, /** MCT data is stored as signed integers*/ + MCT_TYPE_FLOAT = 2, /** MCT data is stored as floats*/ + MCT_TYPE_DOUBLE = 3 /** MCT data is stored as doubles*/ } J2K_MCT_ELEMENT_TYPE; /** * Type of MCT array */ -typedef enum MCT_ARRAY_TYPE -{ - MCT_TYPE_DEPENDENCY = 0, - MCT_TYPE_DECORRELATION = 1, - MCT_TYPE_OFFSET = 2 +typedef enum MCT_ARRAY_TYPE { + MCT_TYPE_DEPENDENCY = 0, + MCT_TYPE_DECORRELATION = 1, + MCT_TYPE_OFFSET = 2 } J2K_MCT_ARRAY_TYPE; /* ----------------------------------------------------------------------- */ -/** -T2 encoding mode +/** +T2 encoding mode */ typedef enum T2_MODE { - THRESH_CALC = 0, /** Function called in Rate allocation process*/ - FINAL_PASS = 1 /** Function called in Tier 2 process*/ -}J2K_T2_MODE; + THRESH_CALC = 0, /** Function called in Rate allocation process*/ + FINAL_PASS = 1 /** Function called in Tier 2 process*/ +} J2K_T2_MODE; /** * Quantization stepsize */ typedef struct opj_stepsize { - /** exponent */ - OPJ_INT32 expn; - /** mantissa */ - OPJ_INT32 mant; + /** exponent */ + OPJ_INT32 expn; + /** mantissa */ + OPJ_INT32 mant; } opj_stepsize_t; /** Tile-component coding parameters */ -typedef struct opj_tccp -{ - /** coding style */ - OPJ_UINT32 csty; - /** number of resolutions */ - OPJ_UINT32 numresolutions; - /** code-blocks width */ - OPJ_UINT32 cblkw; - /** code-blocks height */ - OPJ_UINT32 cblkh; - /** code-block coding style */ - OPJ_UINT32 cblksty; - /** discrete wavelet transform identifier */ - OPJ_UINT32 qmfbid; - /** quantisation style */ - OPJ_UINT32 qntsty; - /** stepsizes used for quantization */ - opj_stepsize_t stepsizes[OPJ_J2K_MAXBANDS]; - /** number of guard bits */ - OPJ_UINT32 numgbits; - /** Region Of Interest shift */ - OPJ_INT32 roishift; - /** precinct width */ - OPJ_UINT32 prcw[OPJ_J2K_MAXRLVLS]; - /** precinct height */ - OPJ_UINT32 prch[OPJ_J2K_MAXRLVLS]; - /** the dc_level_shift **/ - OPJ_INT32 m_dc_level_shift; +typedef struct opj_tccp { + /** coding style */ + OPJ_UINT32 csty; + /** number of resolutions */ + OPJ_UINT32 numresolutions; + /** code-blocks width */ + OPJ_UINT32 cblkw; + /** code-blocks height */ + OPJ_UINT32 cblkh; + /** code-block coding style */ + OPJ_UINT32 cblksty; + /** discrete wavelet transform identifier */ + OPJ_UINT32 qmfbid; + /** quantisation style */ + OPJ_UINT32 qntsty; + /** stepsizes used for quantization */ + opj_stepsize_t stepsizes[OPJ_J2K_MAXBANDS]; + /** number of guard bits */ + OPJ_UINT32 numgbits; + /** Region Of Interest shift */ + OPJ_INT32 roishift; + /** precinct width */ + OPJ_UINT32 prcw[OPJ_J2K_MAXRLVLS]; + /** precinct height */ + OPJ_UINT32 prch[OPJ_J2K_MAXRLVLS]; + /** the dc_level_shift **/ + OPJ_INT32 m_dc_level_shift; } opj_tccp_t; @@ -209,33 +207,30 @@ opj_tccp_t; /** * FIXME DOC */ -typedef struct opj_mct_data -{ - J2K_MCT_ELEMENT_TYPE m_element_type; - J2K_MCT_ARRAY_TYPE m_array_type; - OPJ_UINT32 m_index; - OPJ_BYTE * m_data; - OPJ_UINT32 m_data_size; +typedef struct opj_mct_data { + J2K_MCT_ELEMENT_TYPE m_element_type; + J2K_MCT_ARRAY_TYPE m_array_type; + OPJ_UINT32 m_index; + OPJ_BYTE * m_data; + OPJ_UINT32 m_data_size; } opj_mct_data_t; /** * FIXME DOC */ -typedef struct opj_simple_mcc_decorrelation_data -{ - OPJ_UINT32 m_index; - OPJ_UINT32 m_nb_comps; - opj_mct_data_t * m_decorrelation_array; - opj_mct_data_t * m_offset_array; - OPJ_UINT32 m_is_irreversible : 1; +typedef struct opj_simple_mcc_decorrelation_data { + OPJ_UINT32 m_index; + OPJ_UINT32 m_nb_comps; + opj_mct_data_t * m_decorrelation_array; + opj_mct_data_t * m_offset_array; + OPJ_BITFIELD m_is_irreversible : 1; } opj_simple_mcc_decorrelation_data_t; -typedef struct opj_ppx_struct -{ - OPJ_BYTE* m_data; /* m_data == NULL => Zppx not read yet */ - OPJ_UINT32 m_data_size; +typedef struct opj_ppx_struct { + OPJ_BYTE* m_data; /* m_data == NULL => Zppx not read yet */ + OPJ_UINT32 m_data_size; } opj_ppx; /** @@ -243,106 +238,105 @@ Tile coding parameters : this structure is used to store coding/decoding parameters common to all tiles (information like COD, COC in main header) */ -typedef struct opj_tcp -{ - /** coding style */ - OPJ_UINT32 csty; - /** progression order */ - OPJ_PROG_ORDER prg; - /** number of layers */ - OPJ_UINT32 numlayers; - OPJ_UINT32 num_layers_to_decode; - /** multi-component transform identifier */ - OPJ_UINT32 mct; - /** rates of layers */ - OPJ_FLOAT32 rates[100]; - /** number of progression order changes */ - OPJ_UINT32 numpocs; - /** progression order changes */ - opj_poc_t pocs[32]; - - /** number of ppt markers (reserved size) */ - OPJ_UINT32 ppt_markers_count; - /** ppt markers data (table indexed by Zppt) */ - opj_ppx* ppt_markers; - - /** packet header store there for future use in t2_decode_packet */ - OPJ_BYTE *ppt_data; - /** used to keep a track of the allocated memory */ - OPJ_BYTE *ppt_buffer; - /** Number of bytes stored inside ppt_data*/ - OPJ_UINT32 ppt_data_size; - /** size of ppt_data*/ - OPJ_UINT32 ppt_len; - /** add fixed_quality */ - OPJ_FLOAT32 distoratio[100]; - /** tile-component coding parameters */ - opj_tccp_t *tccps; - /** number of tile parts for the tile. */ - OPJ_UINT32 m_nb_tile_parts; - /** data for the tile */ - OPJ_BYTE * m_data; - /** size of data */ - OPJ_UINT32 m_data_size; - /** encoding norms */ - OPJ_FLOAT64 * mct_norms; - /** the mct decoding matrix */ - OPJ_FLOAT32 * m_mct_decoding_matrix; - /** the mct coding matrix */ - OPJ_FLOAT32 * m_mct_coding_matrix; - /** mct records */ - opj_mct_data_t * m_mct_records; - /** the number of mct records. */ - OPJ_UINT32 m_nb_mct_records; - /** the max number of mct records. */ - OPJ_UINT32 m_nb_max_mct_records; - /** mcc records */ - opj_simple_mcc_decorrelation_data_t * m_mcc_records; - /** the number of mct records. */ - OPJ_UINT32 m_nb_mcc_records; - /** the max number of mct records. */ - OPJ_UINT32 m_nb_max_mcc_records; - - - /***** FLAGS *******/ - /** If cod == 1 --> there was a COD marker for the present tile */ - OPJ_UINT32 cod : 1; - /** If ppt == 1 --> there was a PPT marker for the present tile */ - OPJ_UINT32 ppt : 1; - /** indicates if a POC marker has been used O:NO, 1:YES */ - OPJ_UINT32 POC : 1; +typedef struct opj_tcp { + /** coding style */ + OPJ_UINT32 csty; + /** progression order */ + OPJ_PROG_ORDER prg; + /** number of layers */ + OPJ_UINT32 numlayers; + OPJ_UINT32 num_layers_to_decode; + /** multi-component transform identifier */ + OPJ_UINT32 mct; + /** rates of layers */ + OPJ_FLOAT32 rates[100]; + /** number of progression order changes */ + OPJ_UINT32 numpocs; + /** progression order changes */ + opj_poc_t pocs[J2K_MAX_POCS]; + + /** number of ppt markers (reserved size) */ + OPJ_UINT32 ppt_markers_count; + /** ppt markers data (table indexed by Zppt) */ + opj_ppx* ppt_markers; + + /** packet header store there for future use in t2_decode_packet */ + OPJ_BYTE *ppt_data; + /** used to keep a track of the allocated memory */ + OPJ_BYTE *ppt_buffer; + /** Number of bytes stored inside ppt_data*/ + OPJ_UINT32 ppt_data_size; + /** size of ppt_data*/ + OPJ_UINT32 ppt_len; + /** add fixed_quality */ + OPJ_FLOAT32 distoratio[100]; + /** tile-component coding parameters */ + opj_tccp_t *tccps; + /** current tile part number or -1 if first time into this tile */ + OPJ_INT32 m_current_tile_part_number; + /** number of tile parts for the tile. */ + OPJ_UINT32 m_nb_tile_parts; + /** data for the tile */ + OPJ_BYTE * m_data; + /** size of data */ + OPJ_UINT32 m_data_size; + /** encoding norms */ + OPJ_FLOAT64 * mct_norms; + /** the mct decoding matrix */ + OPJ_FLOAT32 * m_mct_decoding_matrix; + /** the mct coding matrix */ + OPJ_FLOAT32 * m_mct_coding_matrix; + /** mct records */ + opj_mct_data_t * m_mct_records; + /** the number of mct records. */ + OPJ_UINT32 m_nb_mct_records; + /** the max number of mct records. */ + OPJ_UINT32 m_nb_max_mct_records; + /** mcc records */ + opj_simple_mcc_decorrelation_data_t * m_mcc_records; + /** the number of mct records. */ + OPJ_UINT32 m_nb_mcc_records; + /** the max number of mct records. */ + OPJ_UINT32 m_nb_max_mcc_records; + + + /***** FLAGS *******/ + /** If cod == 1 --> there was a COD marker for the present tile */ + OPJ_BITFIELD cod : 1; + /** If ppt == 1 --> there was a PPT marker for the present tile */ + OPJ_BITFIELD ppt : 1; + /** indicates if a POC marker has been used O:NO, 1:YES */ + OPJ_BITFIELD POC : 1; } opj_tcp_t; -typedef struct opj_encoding_param -{ - /** Maximum rate for each component. If == 0, component size limitation is not considered */ - OPJ_UINT32 m_max_comp_size; - /** Position of tile part flag in progression order*/ - OPJ_INT32 m_tp_pos; - /** fixed layer */ - OPJ_INT32 *m_matrice; - /** Flag determining tile part generation*/ - OPJ_BYTE m_tp_flag; - /** allocation by rate/distortion */ - OPJ_UINT32 m_disto_alloc : 1; - /** allocation by fixed layer */ - OPJ_UINT32 m_fixed_alloc : 1; - /** add fixed_quality */ - OPJ_UINT32 m_fixed_quality : 1; - /** Enabling Tile part generation*/ - OPJ_UINT32 m_tp_on : 1; +typedef struct opj_encoding_param { + /** Maximum rate for each component. If == 0, component size limitation is not considered */ + OPJ_UINT32 m_max_comp_size; + /** Position of tile part flag in progression order*/ + OPJ_INT32 m_tp_pos; + /** fixed layer */ + OPJ_INT32 *m_matrice; + /** Flag determining tile part generation*/ + OPJ_BYTE m_tp_flag; + /** allocation by rate/distortion */ + OPJ_BITFIELD m_disto_alloc : 1; + /** allocation by fixed layer */ + OPJ_BITFIELD m_fixed_alloc : 1; + /** add fixed_quality */ + OPJ_BITFIELD m_fixed_quality : 1; + /** Enabling Tile part generation*/ + OPJ_BITFIELD m_tp_on : 1; } opj_encoding_param_t; -typedef struct opj_decoding_param -{ - /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */ - OPJ_UINT32 m_reduce; - /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ - OPJ_UINT32 m_layer; +typedef struct opj_decoding_param { + /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */ + OPJ_UINT32 m_reduce; + /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ + OPJ_UINT32 m_layer; } opj_decoding_param_t; @@ -350,199 +344,194 @@ opj_decoding_param_t; /** * Coding parameters */ -typedef struct opj_cp -{ - /** Size of the image in bits*/ - /*int img_size;*/ - /** Rsiz*/ +typedef struct opj_cp { + /** Size of the image in bits*/ + /*int img_size;*/ + /** Rsiz*/ OPJ_UINT16 rsiz; - /** XTOsiz */ - OPJ_UINT32 tx0; /* MSD see norm */ - /** YTOsiz */ - OPJ_UINT32 ty0; /* MSD see norm */ - /** XTsiz */ - OPJ_UINT32 tdx; - /** YTsiz */ - OPJ_UINT32 tdy; - /** comment */ - OPJ_CHAR *comment; - /** number of tiles in width */ - OPJ_UINT32 tw; - /** number of tiles in heigth */ - OPJ_UINT32 th; - - /** number of ppm markers (reserved size) */ - OPJ_UINT32 ppm_markers_count; - /** ppm markers data (table indexed by Zppm) */ - opj_ppx* ppm_markers; - - /** packet header store there for future use in t2_decode_packet */ - OPJ_BYTE *ppm_data; - /** size of the ppm_data*/ - OPJ_UINT32 ppm_len; - /** size of the ppm_data*/ - OPJ_UINT32 ppm_data_read; - - OPJ_BYTE *ppm_data_current; - - /** packet header storage original buffer */ - OPJ_BYTE *ppm_buffer; - /** pointer remaining on the first byte of the first header if ppm is used */ - OPJ_BYTE *ppm_data_first; - /** Number of bytes actually stored inside the ppm_data */ - OPJ_UINT32 ppm_data_size; - /** use in case of multiple marker PPM (number of info already store) */ - OPJ_INT32 ppm_store; - /** use in case of multiple marker PPM (case on non-finished previous info) */ - OPJ_INT32 ppm_previous; - - /** tile coding parameters */ - opj_tcp_t *tcps; - - union - { - opj_decoding_param_t m_dec; - opj_encoding_param_t m_enc; - } - m_specific_param; - - -/* UniPG>> */ + /** XTOsiz */ + OPJ_UINT32 tx0; /* MSD see norm */ + /** YTOsiz */ + OPJ_UINT32 ty0; /* MSD see norm */ + /** XTsiz */ + OPJ_UINT32 tdx; + /** YTsiz */ + OPJ_UINT32 tdy; + /** comment */ + OPJ_CHAR *comment; + /** number of tiles in width */ + OPJ_UINT32 tw; + /** number of tiles in height */ + OPJ_UINT32 th; + + /** number of ppm markers (reserved size) */ + OPJ_UINT32 ppm_markers_count; + /** ppm markers data (table indexed by Zppm) */ + opj_ppx* ppm_markers; + + /** packet header store there for future use in t2_decode_packet */ + OPJ_BYTE *ppm_data; + /** size of the ppm_data*/ + OPJ_UINT32 ppm_len; + /** size of the ppm_data*/ + OPJ_UINT32 ppm_data_read; + + OPJ_BYTE *ppm_data_current; + + /** packet header storage original buffer */ + OPJ_BYTE *ppm_buffer; + /** pointer remaining on the first byte of the first header if ppm is used */ + OPJ_BYTE *ppm_data_first; + /** Number of bytes actually stored inside the ppm_data */ + OPJ_UINT32 ppm_data_size; + /** use in case of multiple marker PPM (number of info already store) */ + OPJ_INT32 ppm_store; + /** use in case of multiple marker PPM (case on non-finished previous info) */ + OPJ_INT32 ppm_previous; + + /** tile coding parameters */ + opj_tcp_t *tcps; + + union { + opj_decoding_param_t m_dec; + opj_encoding_param_t m_enc; + } + m_specific_param; + + + /* UniPG>> */ #ifdef USE_JPWL - /** enables writing of EPC in MH, thus activating JPWL */ - OPJ_BOOL epc_on; - /** enables writing of EPB, in case of activated JPWL */ - OPJ_BOOL epb_on; - /** enables writing of ESD, in case of activated JPWL */ - OPJ_BOOL esd_on; - /** enables writing of informative techniques of ESD, in case of activated JPWL */ - OPJ_BOOL info_on; - /** enables writing of RED, in case of activated JPWL */ - OPJ_BOOL red_on; - /** error protection method for MH (0,1,16,32,37-128) */ - int hprot_MH; - /** tile number of header protection specification (>=0) */ - int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; - /** error protection methods for TPHs (0,1,16,32,37-128) */ - int hprot_TPH[JPWL_MAX_NO_TILESPECS]; - /** tile number of packet protection specification (>=0) */ - int pprot_tileno[JPWL_MAX_NO_PACKSPECS]; - /** packet number of packet protection specification (>=0) */ - int pprot_packno[JPWL_MAX_NO_PACKSPECS]; - /** error protection methods for packets (0,1,16,32,37-128) */ - int pprot[JPWL_MAX_NO_PACKSPECS]; - /** enables writing of ESD, (0/2/4 bytes) */ - int sens_size; - /** sensitivity addressing size (0=auto/2/4 bytes) */ - int sens_addr; - /** sensitivity range (0-3) */ - int sens_range; - /** sensitivity method for MH (-1,0-7) */ - int sens_MH; - /** tile number of sensitivity specification (>=0) */ - int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; - /** sensitivity methods for TPHs (-1,0-7) */ - int sens_TPH[JPWL_MAX_NO_TILESPECS]; - /** enables JPWL correction at the decoder */ - OPJ_BOOL correct; - /** expected number of components at the decoder */ - int exp_comps; - /** maximum number of tiles at the decoder */ - OPJ_UINT32 max_tiles; + /** enables writing of EPC in MH, thus activating JPWL */ + OPJ_BOOL epc_on; + /** enables writing of EPB, in case of activated JPWL */ + OPJ_BOOL epb_on; + /** enables writing of ESD, in case of activated JPWL */ + OPJ_BOOL esd_on; + /** enables writing of informative techniques of ESD, in case of activated JPWL */ + OPJ_BOOL info_on; + /** enables writing of RED, in case of activated JPWL */ + OPJ_BOOL red_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int hprot_MH; + /** tile number of header protection specification (>=0) */ + int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0/2/4 bytes) */ + int sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int sens_addr; + /** sensitivity range (0-3) */ + int sens_range; + /** sensitivity method for MH (-1,0-7) */ + int sens_MH; + /** tile number of sensitivity specification (>=0) */ + int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1,0-7) */ + int sens_TPH[JPWL_MAX_NO_TILESPECS]; + /** enables JPWL correction at the decoder */ + OPJ_BOOL correct; + /** expected number of components at the decoder */ + int exp_comps; + /** maximum number of tiles at the decoder */ + OPJ_UINT32 max_tiles; #endif /* USE_JPWL */ - /******** FLAGS *********/ - /** if ppm == 1 --> there was a PPM marker*/ - OPJ_UINT32 ppm : 1; - /** tells if the parameter is a coding or decoding one */ - OPJ_UINT32 m_is_decoder : 1; -/* <<UniPG */ + /******** FLAGS *********/ + /** if ppm == 1 --> there was a PPM marker*/ + OPJ_BITFIELD ppm : 1; + /** tells if the parameter is a coding or decoding one */ + OPJ_BITFIELD m_is_decoder : 1; + /** whether different bit depth or sign per component is allowed. Decoder only for ow */ + OPJ_BITFIELD allow_different_bit_depth_sign : 1; + /* <<UniPG */ } opj_cp_t; -typedef struct opj_j2k_dec -{ - /** locate in which part of the codestream the decoder is (main header, tile header, end) */ - OPJ_UINT32 m_state; - /** - * store decoding parameters common to all tiles (information like COD, COC in main header) - */ - opj_tcp_t *m_default_tcp; - OPJ_BYTE *m_header_data; - OPJ_UINT32 m_header_data_size; - /** to tell the tile part length */ - OPJ_UINT32 m_sot_length; - /** Only tiles index in the correct range will be decoded.*/ - OPJ_UINT32 m_start_tile_x; - OPJ_UINT32 m_start_tile_y; - OPJ_UINT32 m_end_tile_x; - OPJ_UINT32 m_end_tile_y; - /** - * Decoded area set by the user - */ - OPJ_UINT32 m_DA_x0; - OPJ_UINT32 m_DA_y0; - OPJ_UINT32 m_DA_x1; - OPJ_UINT32 m_DA_y1; - - /** Index of the tile to decode (used in get_tile) */ - OPJ_INT32 m_tile_ind_to_dec; - /** Position of the last SOT marker read */ - OPJ_OFF_T m_last_sot_read_pos; - - /** - * Indicate that the current tile-part is assume as the last tile part of the codestream. - * It is useful in the case of PSot is equal to zero. The sot length will be compute in the - * SOD reader function. FIXME NOT USED for the moment - */ - OPJ_BOOL m_last_tile_part; - /** to tell that a tile can be decoded. */ - OPJ_UINT32 m_can_decode : 1; - OPJ_UINT32 m_discard_tiles : 1; - OPJ_UINT32 m_skip_data : 1; - /** TNsot correction : see issue 254 **/ - OPJ_UINT32 m_nb_tile_parts_correction_checked : 1; - OPJ_UINT32 m_nb_tile_parts_correction : 1; +typedef struct opj_j2k_dec { + /** locate in which part of the codestream the decoder is (main header, tile header, end) */ + OPJ_UINT32 m_state; + /** + * store decoding parameters common to all tiles (information like COD, COC in main header) + */ + opj_tcp_t *m_default_tcp; + OPJ_BYTE *m_header_data; + OPJ_UINT32 m_header_data_size; + /** to tell the tile part length */ + OPJ_UINT32 m_sot_length; + /** Only tiles index in the correct range will be decoded.*/ + OPJ_UINT32 m_start_tile_x; + OPJ_UINT32 m_start_tile_y; + OPJ_UINT32 m_end_tile_x; + OPJ_UINT32 m_end_tile_y; + + /** Index of the tile to decode (used in get_tile) */ + OPJ_INT32 m_tile_ind_to_dec; + /** Position of the last SOT marker read */ + OPJ_OFF_T m_last_sot_read_pos; + + /** + * Indicate that the current tile-part is assume as the last tile part of the codestream. + * It is useful in the case of PSot is equal to zero. The sot length will be compute in the + * SOD reader function. FIXME NOT USED for the moment + */ + OPJ_BOOL m_last_tile_part; + + OPJ_UINT32 m_numcomps_to_decode; + OPJ_UINT32 *m_comps_indices_to_decode; + + /** to tell that a tile can be decoded. */ + OPJ_BITFIELD m_can_decode : 1; + OPJ_BITFIELD m_discard_tiles : 1; + OPJ_BITFIELD m_skip_data : 1; + /** TNsot correction : see issue 254 **/ + OPJ_BITFIELD m_nb_tile_parts_correction_checked : 1; + OPJ_BITFIELD m_nb_tile_parts_correction : 1; } opj_j2k_dec_t; -typedef struct opj_j2k_enc -{ - /** Tile part number, regardless of poc, for each new poc, tp is reset to 1*/ - OPJ_UINT32 m_current_poc_tile_part_number; /* tp_num */ +typedef struct opj_j2k_enc { + /** Tile part number, regardless of poc, for each new poc, tp is reset to 1*/ + OPJ_UINT32 m_current_poc_tile_part_number; /* tp_num */ - /** Tile part number currently coding, taking into account POC. m_current_tile_part_number holds the total number of tile parts while encoding the last tile part.*/ - OPJ_UINT32 m_current_tile_part_number; /*cur_tp_num */ + /** Tile part number currently coding, taking into account POC. m_current_tile_part_number holds the total number of tile parts while encoding the last tile part.*/ + OPJ_UINT32 m_current_tile_part_number; /*cur_tp_num */ - /** - locate the start position of the TLM marker - after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length. - */ + /** + locate the start position of the TLM marker + after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length. + */ OPJ_OFF_T m_tlm_start; - /** - * Stores the sizes of the tlm. - */ - OPJ_BYTE * m_tlm_sot_offsets_buffer; - /** - * The current offset of the tlm buffer. - */ - OPJ_BYTE * m_tlm_sot_offsets_current; + /** + * Stores the sizes of the tlm. + */ + OPJ_BYTE * m_tlm_sot_offsets_buffer; + /** + * The current offset of the tlm buffer. + */ + OPJ_BYTE * m_tlm_sot_offsets_current; - /** Total num of tile parts in whole image = num tiles* num tileparts in each tile*/ - /** used in TLMmarker*/ - OPJ_UINT32 m_total_tile_parts; /* totnum_tp */ + /** Total num of tile parts in whole image = num tiles* num tileparts in each tile*/ + /** used in TLMmarker*/ + OPJ_UINT32 m_total_tile_parts; /* totnum_tp */ - /* encoded data for a tile */ - OPJ_BYTE * m_encoded_tile_data; + /* encoded data for a tile */ + OPJ_BYTE * m_encoded_tile_data; - /* size of the encoded_data */ - OPJ_UINT32 m_encoded_tile_size; + /* size of the encoded_data */ + OPJ_UINT32 m_encoded_tile_size; - /* encoded data for a tile */ - OPJ_BYTE * m_header_tile_data; + /* encoded data for a tile */ + OPJ_BYTE * m_header_tile_data; - /* size of the encoded_data */ - OPJ_UINT32 m_header_tile_data_size; + /* size of the encoded_data */ + OPJ_UINT32 m_header_tile_data_size; } opj_j2k_enc_t; @@ -553,42 +542,51 @@ struct opj_tcd; /** JPEG-2000 codestream reader/writer */ -typedef struct opj_j2k -{ - /* J2K codestream is decoded*/ - OPJ_BOOL m_is_decoder; +typedef struct opj_j2k { + /* J2K codestream is decoded*/ + OPJ_BOOL m_is_decoder; + + /* FIXME DOC*/ + union { + opj_j2k_dec_t m_decoder; + opj_j2k_enc_t m_encoder; + } + m_specific_param; + + /** pointer to the internal/private encoded / decoded image */ + opj_image_t* m_private_image; - /* FIXME DOC*/ - union - { - opj_j2k_dec_t m_decoder; - opj_j2k_enc_t m_encoder; - } - m_specific_param; + /* pointer to the output image (decoded)*/ + opj_image_t* m_output_image; - /** pointer to the internal/private encoded / decoded image */ - opj_image_t* m_private_image; + /** Coding parameters */ + opj_cp_t m_cp; - /* pointer to the output image (decoded)*/ - opj_image_t* m_output_image; + /** the list of procedures to exec **/ + opj_procedure_list_t * m_procedure_list; - /** Coding parameters */ - opj_cp_t m_cp; + /** the list of validation procedures to follow to make sure the code is valid **/ + opj_procedure_list_t * m_validation_list; - /** the list of procedures to exec **/ - opj_procedure_list_t * m_procedure_list; + /** helper used to write the index file */ + opj_codestream_index_t *cstr_index; - /** the list of validation procedures to follow to make sure the code is valid **/ - opj_procedure_list_t * m_validation_list; + /** number of the tile currently concern by coding/decoding */ + OPJ_UINT32 m_current_tile_number; - /** helper used to write the index file */ - opj_codestream_index_t *cstr_index; + /** the current tile coder/decoder **/ + struct opj_tcd * m_tcd; - /** number of the tile curently concern by coding/decoding */ - OPJ_UINT32 m_current_tile_number; + /** Number of threads to use */ + int m_num_threads; - /** the current tile coder/decoder **/ - struct opj_tcd * m_tcd; + /** Thread pool */ + opj_thread_pool_t* m_tp; + + OPJ_UINT32 ihdr_w; + OPJ_UINT32 ihdr_h; + OPJ_UINT32 enumcs; + unsigned int dump_state; } opj_j2k_t; @@ -601,12 +599,14 @@ opj_j2k_t; /** Setup the decoder decoding parameters using user parameters. -Decoding parameters are returned in j2k->cp. +Decoding parameters are returned in j2k->cp. @param j2k J2K decompressor handle @param parameters decompression parameters */ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters); +OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads); + /** * Creates a J2K compression structure * @@ -615,15 +615,15 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters); opj_j2k_t* opj_j2k_create_compress(void); -OPJ_BOOL opj_j2k_setup_encoder( opj_j2k_t *p_j2k, - opj_cparameters_t *parameters, - opj_image_t *image, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager); /** Converts an enum type progression order to string type */ -char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); +const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); /* ----------------------------------------------------------------------- */ /*@}*/ @@ -648,87 +648,102 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k, * * @return true if the box is valid. */ -OPJ_BOOL opj_j2k_read_header( opj_stream_private_t *p_stream, - opj_j2k_t* p_j2k, - opj_image_t** p_image, - opj_event_mgr_t* p_manager ); +OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, + opj_j2k_t* p_j2k, + opj_image_t** p_image, + opj_event_mgr_t* p_manager); /** * Destroys a jpeg2000 codec. * - * @param p_j2k the jpeg20000 structure to destroy. + * @param p_j2k the jpeg20000 structure to destroy. */ -void opj_j2k_destroy (opj_j2k_t *p_j2k); +void opj_j2k_destroy(opj_j2k_t *p_j2k); /** * Destroys a codestream index structure. * - * @param p_cstr_ind the codestream index parameter to destroy. + * @param p_cstr_ind the codestream index parameter to destroy. */ -void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind); +void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind); /** * Decode tile data. - * @param p_j2k the jpeg2000 codec. - * @param p_tile_index + * @param p_j2k the jpeg2000 codec. + * @param p_tile_index * @param p_data FIXME DOC * @param p_data_size FIXME DOC - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. */ -OPJ_BOOL opj_j2k_decode_tile ( opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Reads a tile header. - * @param p_j2k the jpeg2000 codec. - * @param p_tile_index FIXME DOC - * @param p_data_size FIXME DOC - * @param p_tile_x0 FIXME DOC - * @param p_tile_y0 FIXME DOC - * @param p_tile_x1 FIXME DOC - * @param p_tile_y1 FIXME DOC - * @param p_nb_comps FIXME DOC - * @param p_go_on FIXME DOC - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. + * @param p_j2k the jpeg2000 codec. + * @param p_tile_index FIXME DOC + * @param p_data_size FIXME DOC + * @param p_tile_x0 FIXME DOC + * @param p_tile_y0 FIXME DOC + * @param p_tile_x1 FIXME DOC + * @param p_tile_y1 FIXME DOC + * @param p_nb_comps FIXME DOC + * @param p_go_on FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. */ -OPJ_BOOL opj_j2k_read_tile_header ( opj_j2k_t * p_j2k, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); - +OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + + +/** Sets the indices of the components to decode. + * + * @param p_j2k the jpeg2000 codec. + * @param numcomps Number of components to decode. + * @param comps_indices Array of num_compts indices (numbering starting at 0) + * corresponding to the components to decode. + * @param p_manager Event manager + * + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager); /** * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. * - * @param p_j2k the jpeg2000 codec. - * @param p_image FIXME DOC - * @param p_start_x the left position of the rectangle to decode (in image coordinates). - * @param p_start_y the up position of the rectangle to decode (in image coordinates). - * @param p_end_x the right position of the rectangle to decode (in image coordinates). - * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). - * @param p_manager the user event manager + * @param p_j2k the jpeg2000 codec. + * @param p_image FIXME DOC + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * @param p_manager the user event manager * - * @return true if the area could be set. + * @return true if the area could be set. */ -OPJ_BOOL opj_j2k_set_decode_area( opj_j2k_t *p_j2k, - opj_image_t* p_image, - OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager); /** * Creates a J2K decompression structure. @@ -741,48 +756,50 @@ opj_j2k_t* opj_j2k_create_decompress(void); /** * Dump some elements from the J2K decompression structure . * - *@param p_j2k the jpeg2000 codec. - *@param flag flag to describe what elments are dump. - *@param out_stream output stream where dump the elements. + *@param p_j2k the jpeg2000 codec. + *@param flag flag to describe what elements are dump. + *@param out_stream output stream where dump the elements. * */ -void j2k_dump (opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream); +void j2k_dump(opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream); /** * Dump an image header structure. * - *@param image the image header to dump. - *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function - *@param out_stream output stream where dump the elements. + *@param image the image header to dump. + *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function + *@param out_stream output stream where dump the elements. */ -void j2k_dump_image_header(opj_image_t* image, OPJ_BOOL dev_dump_flag, FILE* out_stream); +void j2k_dump_image_header(opj_image_t* image, OPJ_BOOL dev_dump_flag, + FILE* out_stream); /** * Dump a component image header structure. * - *@param comp the component image header to dump. - *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function - *@param out_stream output stream where dump the elements. + *@param comp the component image header to dump. + *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function + *@param out_stream output stream where dump the elements. */ -void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag, FILE* out_stream); +void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag, + FILE* out_stream); /** * Get the codestream info from a JPEG2000 codec. * - *@param p_j2k the component image header to dump. + *@param p_j2k the component image header to dump. * - *@return the codestream information extract from the jpg2000 codec + *@return the codestream information extract from the jpg2000 codec */ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k); /** * Get the codestream index from a JPEG2000 codec. * - *@param p_j2k the component image header to dump. + *@param p_j2k the component image header to dump. * - *@return the codestream index extract from the jpg2000 codec + *@return the codestream index extract from the jpg2000 codec */ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k); @@ -800,64 +817,64 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t *j2k, opj_event_mgr_t *p_manager); -OPJ_BOOL opj_j2k_get_tile( opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager, - OPJ_UINT32 tile_index ); +OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index); -OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, - OPJ_UINT32 res_factor, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager); /** * Writes a tile. - * @param p_j2k the jpeg2000 codec. + * @param p_j2k the jpeg2000 codec. * @param p_tile_index FIXME DOC * @param p_data FIXME DOC * @param p_data_size FIXME DOC - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. */ -OPJ_BOOL opj_j2k_write_tile ( opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Encodes an image into a JPEG-2000 codestream */ -OPJ_BOOL opj_j2k_encode( opj_j2k_t * p_j2k, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /** * Starts a compression scheme, i.e. validates the codec parameters, writes the header. * - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream object. - * @param p_image FIXME DOC - * @param p_manager the user event manager. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream object. + * @param p_image FIXME DOC + * @param p_manager the user event manager. * * @return true if the codec is valid. */ OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_image_t * p_image, - opj_event_mgr_t * p_manager); + opj_stream_private_t *p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager); /** * Ends the compression procedures and possibiliy add data to be read after the * codestream. */ -OPJ_BOOL opj_j2k_end_compress( opj_j2k_t *p_j2k, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); -OPJ_BOOL opj_j2k_setup_mct_encoding (opj_tcp_t * p_tcp, opj_image_t * p_image); +OPJ_BOOL opj_j2k_setup_mct_encoding(opj_tcp_t * p_tcp, opj_image_t * p_image); -#endif /* __J2K_H */ +#endif /* OPJ_J2K_H */ diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c index 8128d98e8f26f2d71df8412bcd55121f618a0245..2374d459fd3e17e091cb56d96737b37284c6d74e 100644 --- a/third_party/libopenjpeg20/jp2.c +++ b/third_party/libopenjpeg20/jp2.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,11 +8,11 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2010-2011, Kaori Hagihara - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -42,7 +42,9 @@ /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ /*@{*/ -#define OPJ_BOX_SIZE 1024 +#define OPJ_BOX_SIZE 1024 + +#define OPJ_UNUSED(x) (void)x /** @name Local static functions */ /*@{*/ @@ -52,130 +54,131 @@ /** * Reads a IHDR box - Image Header box * - * @param p_image_header_data pointer to actual data (already read from file) - * @param jp2 the jpeg2000 file codec. - * @param p_image_header_size the size of the image header - * @param p_manager the user event manager. + * @param p_image_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_image_header_size the size of the image header + * @param p_manager the user event manager. * - * @return true if the image header is valid, false else. + * @return true if the image header is valid, false else. */ -static OPJ_BOOL opj_jp2_read_ihdr( opj_jp2_t *jp2, - OPJ_BYTE *p_image_header_data, - OPJ_UINT32 p_image_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_ihdr(opj_jp2_t *jp2, + OPJ_BYTE *p_image_header_data, + OPJ_UINT32 p_image_header_size, + opj_event_mgr_t * p_manager); /** * Writes the Image Header box - Image Header box. * - * @param jp2 jpeg2000 file codec. - * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. * - * @return the data being copied. + * @return the data being copied. */ static OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written ); + OPJ_UINT32 * p_nb_bytes_written); /** * Writes the Bit per Component box. * - * @param jp2 jpeg2000 file codec. - * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. * - * @return the data being copied. + * @return the data being copied. */ -static OPJ_BYTE * opj_jp2_write_bpcc( opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written ); +static OPJ_BYTE * opj_jp2_write_bpcc(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); /** * Reads a Bit per Component box. * - * @param p_bpc_header_data pointer to actual data (already read from file) - * @param jp2 the jpeg2000 file codec. - * @param p_bpc_header_size the size of the bpc header - * @param p_manager the user event manager. + * @param p_bpc_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_bpc_header_size the size of the bpc header + * @param p_manager the user event manager. * - * @return true if the bpc header is valid, fale else. + * @return true if the bpc header is valid, false else. */ -static OPJ_BOOL opj_jp2_read_bpcc( opj_jp2_t *jp2, - OPJ_BYTE * p_bpc_header_data, - OPJ_UINT32 p_bpc_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_bpcc(opj_jp2_t *jp2, + OPJ_BYTE * p_bpc_header_data, + OPJ_UINT32 p_bpc_header_size, + opj_event_mgr_t * p_manager); -static OPJ_BOOL opj_jp2_read_cdef( opj_jp2_t * jp2, - OPJ_BYTE * p_cdef_header_data, - OPJ_UINT32 p_cdef_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_cdef(opj_jp2_t * jp2, + OPJ_BYTE * p_cdef_header_data, + OPJ_UINT32 p_cdef_header_size, + opj_event_mgr_t * p_manager); -static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, opj_event_mgr_t *); +static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, + opj_event_mgr_t *); /** * Writes the Channel Definition box. * - * @param jp2 jpeg2000 file codec. - * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. * - * @return the data being copied. + * @return the data being copied. */ -static OPJ_BYTE * opj_jp2_write_cdef( opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written ); +static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); /** * Writes the Colour Specification box. * - * @param jp2 jpeg2000 file codec. - * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. * - * @return the data being copied. + * @return the data being copied. */ -static OPJ_BYTE * opj_jp2_write_colr( opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written ); +static OPJ_BYTE * opj_jp2_write_colr(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); /** * Writes a FTYP box - File type box * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager the user event manager. + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. * - * @return true if writing was successful. + * @return true if writing was successful. */ -static OPJ_BOOL opj_jp2_write_ftyp( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /** * Reads a a FTYP box - File type box * - * @param p_header_data the data contained in the FTYP box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the FTYP box. - * @param p_manager the user event manager. + * @param p_header_data the data contained in the FTYP box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the FTYP box. + * @param p_manager the user event manager. * * @return true if the FTYP box is valid. */ -static OPJ_BOOL opj_jp2_read_ftyp( opj_jp2_t *jp2, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_ftyp(opj_jp2_t *jp2, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); -static OPJ_BOOL opj_jp2_skip_jp2c( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_skip_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); /** * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). * - * @param p_header_data the data contained in the file header box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the file header box. - * @param p_manager the user event manager. + * @param p_header_data the data contained in the file header box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the file header box. + * @param p_manager the user event manager. * * @return true if the JP2 Header box was successfully recognized. */ -static OPJ_BOOL opj_jp2_read_jp2h( opj_jp2_t *jp2, - OPJ_BYTE *p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_jp2h(opj_jp2_t *jp2, + OPJ_BYTE *p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); /** * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). @@ -187,61 +190,61 @@ static OPJ_BOOL opj_jp2_read_jp2h( opj_jp2_t *jp2, * @return true if writing was successful. */ static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager ); + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); /** * Writes the Jpeg2000 codestream Header box - JP2C Header box. This function must be called AFTER the coding has been done. * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. * * @return true if writing was successful. */ -static OPJ_BOOL opj_jp2_write_jp2c( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); #ifdef USE_JPIP /** * Write index Finder box * @param cio the stream to write to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. */ -static OPJ_BOOL opj_jpip_write_iptr( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jpip_write_iptr(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /** * Write index Finder box * @param cio the stream to write to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. */ static OPJ_BOOL opj_jpip_write_cidx(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /** * Write file Index (superbox) * @param cio the stream to write to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. */ static OPJ_BOOL opj_jpip_write_fidx(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); #endif /* USE_JPIP */ /** * Reads a jpeg2000 file signature box. * - * @param p_header_data the data contained in the signature box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the signature box. - * @param p_manager the user event manager. + * @param p_header_data the data contained in the signature box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the signature box. + * @param p_manager the user event manager. * * @return true if the file signature box is valid. */ @@ -254,21 +257,25 @@ static OPJ_BOOL opj_jp2_read_jp(opj_jp2_t *jp2, * Writes a jpeg2000 file signature box. * * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. + * @param jp2 the jpeg2000 file codec. * @param p_manager the user event manager. * * @return true if writing was successful. */ -static OPJ_BOOL opj_jp2_write_jp( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /** Apply collected palette data -@param color Collector for profile, cdef and pclr data -@param image +@param image Image. +@param color Collector for profile, cdef and pclr data. +@param p_manager the user event manager. +@return true in case of success */ -static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color); +static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + opj_jp2_color_t *color, + opj_event_mgr_t * p_manager); static void opj_jp2_free_pclr(opj_jp2_color_t *color); @@ -282,10 +289,10 @@ static void opj_jp2_free_pclr(opj_jp2_color_t *color); * * @return Returns true if successful, returns false otherwise */ -static OPJ_BOOL opj_jp2_read_pclr( opj_jp2_t *jp2, - OPJ_BYTE * p_pclr_header_data, - OPJ_UINT32 p_pclr_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_pclr(opj_jp2_t *jp2, + OPJ_BYTE * p_pclr_header_data, + OPJ_UINT32 p_pclr_header_size, + opj_event_mgr_t * p_manager); /** * Collect component mapping data @@ -298,25 +305,25 @@ static OPJ_BOOL opj_jp2_read_pclr( opj_jp2_t *jp2, * @return Returns true if successful, returns false otherwise */ -static OPJ_BOOL opj_jp2_read_cmap( opj_jp2_t * jp2, - OPJ_BYTE * p_cmap_header_data, - OPJ_UINT32 p_cmap_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_cmap(opj_jp2_t * jp2, + OPJ_BYTE * p_cmap_header_data, + OPJ_UINT32 p_cmap_header_size, + opj_event_mgr_t * p_manager); /** * Reads the Color Specification box. * - * @param p_colr_header_data pointer to actual data (already read from file) - * @param jp2 the jpeg2000 file codec. - * @param p_colr_header_size the size of the color header - * @param p_manager the user event manager. + * @param p_colr_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_colr_header_size the size of the color header + * @param p_manager the user event manager. * - * @return true if the bpc header is valid, fale else. + * @return true if the bpc header is valid, false else. */ -static OPJ_BOOL opj_jp2_read_colr( opj_jp2_t *jp2, - OPJ_BYTE * p_colr_header_data, - OPJ_UINT32 p_colr_header_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2, + OPJ_BYTE * p_colr_header_data, + OPJ_UINT32 p_colr_header_size, + opj_event_mgr_t * p_manager); /*@}*/ @@ -326,13 +333,15 @@ static OPJ_BOOL opj_jp2_read_colr( opj_jp2_t *jp2, * Sets up the procedures to do on writing header after the codestream. * Developpers wanting to extend the library can add their own writing procedures. */ -static OPJ_BOOL opj_jp2_setup_end_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_jp2_setup_end_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); /** * Sets up the procedures to do on reading header after the codestream. * Developpers wanting to extend the library can add their own writing procedures. */ -static OPJ_BOOL opj_jp2_setup_end_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_jp2_setup_end_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); /** * Reads a jpeg2000 file header structure. @@ -343,34 +352,34 @@ static OPJ_BOOL opj_jp2_setup_end_header_reading (opj_jp2_t *jp2, opj_event_mgr_ * * @return true if the box is valid. */ -static OPJ_BOOL opj_jp2_read_header_procedure( opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_header_procedure(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); /** - * Excutes the given procedures on the given codec. + * Executes the given procedures on the given codec. * - * @param p_procedure_list the list of procedures to execute - * @param jp2 the jpeg2000 file codec to execute the procedures on. - * @param stream the stream to execute the procedures on. - * @param p_manager the user manager. + * @param p_procedure_list the list of procedures to execute + * @param jp2 the jpeg2000 file codec to execute the procedures on. + * @param stream the stream to execute the procedures on. + * @param p_manager the user manager. * - * @return true if all the procedures were successfully executed. + * @return true if all the procedures were successfully executed. */ -static OPJ_BOOL opj_jp2_exec ( opj_jp2_t * jp2, - opj_procedure_list_t * p_procedure_list, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); /** * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. * - * @param cio the input stream to read data from. - * @param box the box structure to fill. - * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). - * @param p_manager user event manager. + * @param cio the input stream to read data from. + * @param box the box structure to fill. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_manager user event manager. * - * @return true if the box is recognized, false otherwise + * @return true if the box is recognized, false otherwise */ static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box, OPJ_UINT32 * p_number_bytes_read, @@ -378,445 +387,489 @@ static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box, opj_event_mgr_t * p_manager); /** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters * are valid. Developpers wanting to extend the library can add their own validation procedures. */ -static OPJ_BOOL opj_jp2_setup_encoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); /** * Sets up the procedures to do on writing header. Developpers wanting to extend the library can add their own writing procedures. */ -static OPJ_BOOL opj_jp2_setup_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_jp2_setup_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); -static OPJ_BOOL opj_jp2_default_validation ( opj_jp2_t * jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_default_validation(opj_jp2_t * jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /** * Finds the image execution function related to the given box id. * - * @param p_id the id of the handler to fetch. + * @param p_id the id of the handler to fetch. * - * @return the given handler or NULL if it could not be found. + * @return the given handler or NULL if it could not be found. */ -static const opj_jp2_header_handler_t * opj_jp2_img_find_handler (OPJ_UINT32 p_id); +static const opj_jp2_header_handler_t * opj_jp2_img_find_handler( + OPJ_UINT32 p_id); /** * Finds the execution function related to the given box id. * - * @param p_id the id of the handler to fetch. + * @param p_id the id of the handler to fetch. * - * @return the given handler or NULL if it could not be found. + * @return the given handler or NULL if it could not be found. */ -static const opj_jp2_header_handler_t * opj_jp2_find_handler (OPJ_UINT32 p_id ); +static const opj_jp2_header_handler_t * opj_jp2_find_handler(OPJ_UINT32 p_id); -static const opj_jp2_header_handler_t jp2_header [] = -{ - {JP2_JP,opj_jp2_read_jp}, - {JP2_FTYP,opj_jp2_read_ftyp}, - {JP2_JP2H,opj_jp2_read_jp2h} +static const opj_jp2_header_handler_t jp2_header [] = { + {JP2_JP, opj_jp2_read_jp}, + {JP2_FTYP, opj_jp2_read_ftyp}, + {JP2_JP2H, opj_jp2_read_jp2h} }; -static const opj_jp2_header_handler_t jp2_img_header [] = -{ - {JP2_IHDR,opj_jp2_read_ihdr}, - {JP2_COLR,opj_jp2_read_colr}, - {JP2_BPCC,opj_jp2_read_bpcc}, - {JP2_PCLR,opj_jp2_read_pclr}, - {JP2_CMAP,opj_jp2_read_cmap}, - {JP2_CDEF,opj_jp2_read_cdef} +static const opj_jp2_header_handler_t jp2_img_header [] = { + {JP2_IHDR, opj_jp2_read_ihdr}, + {JP2_COLR, opj_jp2_read_colr}, + {JP2_BPCC, opj_jp2_read_bpcc}, + {JP2_PCLR, opj_jp2_read_pclr}, + {JP2_CMAP, opj_jp2_read_cmap}, + {JP2_CDEF, opj_jp2_read_cdef} }; /** * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. Data is read from a character string * - * @param box the box structure to fill. - * @param p_data the character string to read data from. - * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). - * @param p_box_max_size the maximum number of bytes in the box. - * @param p_manager FIXME DOC + * @param box the box structure to fill. + * @param p_data the character string to read data from. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_box_max_size the maximum number of bytes in the box. + * @param p_manager FIXME DOC * - * @return true if the box is recognized, false otherwise + * @return true if the box is recognized, false otherwise */ -static OPJ_BOOL opj_jp2_read_boxhdr_char( opj_jp2_box_t *box, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_number_bytes_read, - OPJ_UINT32 p_box_max_size, - opj_event_mgr_t * p_manager ); +static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_number_bytes_read, + OPJ_UINT32 p_box_max_size, + opj_event_mgr_t * p_manager); /** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters * are valid. Developpers wanting to extend the library can add their own validation procedures. */ -static OPJ_BOOL opj_jp2_setup_decoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_jp2_setup_decoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); /** * Sets up the procedures to do on reading header. * Developpers wanting to extend the library can add their own writing procedures. */ -static OPJ_BOOL opj_jp2_setup_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager); +static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); /* ----------------------------------------------------------------------- */ static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box, - OPJ_UINT32 * p_number_bytes_read, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) + OPJ_UINT32 * p_number_bytes_read, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - /* read header from file */ - OPJ_BYTE l_data_header [8]; - - /* preconditions */ - assert(cio != 00); - assert(box != 00); - assert(p_number_bytes_read != 00); - assert(p_manager != 00); - - *p_number_bytes_read = (OPJ_UINT32)opj_stream_read_data(cio,l_data_header,8,p_manager); - if (*p_number_bytes_read != 8) { - return OPJ_FALSE; - } - - /* process read data */ - opj_read_bytes(l_data_header,&(box->length), 4); - opj_read_bytes(l_data_header+4,&(box->type), 4); - - if(box->length == 0)/* last box */ - { - const OPJ_OFF_T bleft = opj_stream_get_number_byte_left(cio); - box->length = (OPJ_UINT32)bleft; - assert( (OPJ_OFF_T)box->length == bleft ); - return OPJ_TRUE; + /* read header from file */ + OPJ_BYTE l_data_header [8]; + + /* preconditions */ + assert(cio != 00); + assert(box != 00); + assert(p_number_bytes_read != 00); + assert(p_manager != 00); + + *p_number_bytes_read = (OPJ_UINT32)opj_stream_read_data(cio, l_data_header, 8, + p_manager); + if (*p_number_bytes_read != 8) { + return OPJ_FALSE; + } + + /* process read data */ + opj_read_bytes(l_data_header, &(box->length), 4); + opj_read_bytes(l_data_header + 4, &(box->type), 4); + + if (box->length == 0) { /* last box */ + const OPJ_OFF_T bleft = opj_stream_get_number_byte_left(cio); + if (bleft > (OPJ_OFF_T)(0xFFFFFFFFU - 8U)) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + box->length = (OPJ_UINT32)bleft + 8U; + assert((OPJ_OFF_T)box->length == bleft + 8); + return OPJ_TRUE; } - /* do we have a "special very large box ?" */ - /* read then the XLBox */ - if (box->length == 1) { - OPJ_UINT32 l_xl_part_size; + /* do we have a "special very large box ?" */ + /* read then the XLBox */ + if (box->length == 1) { + OPJ_UINT32 l_xl_part_size; - OPJ_UINT32 l_nb_bytes_read = (OPJ_UINT32)opj_stream_read_data(cio,l_data_header,8,p_manager); - if (l_nb_bytes_read != 8) { - if (l_nb_bytes_read > 0) { - *p_number_bytes_read += l_nb_bytes_read; - } + OPJ_UINT32 l_nb_bytes_read = (OPJ_UINT32)opj_stream_read_data(cio, + l_data_header, 8, p_manager); + if (l_nb_bytes_read != 8) { + if (l_nb_bytes_read > 0) { + *p_number_bytes_read += l_nb_bytes_read; + } - return OPJ_FALSE; - } + return OPJ_FALSE; + } *p_number_bytes_read = 16; - opj_read_bytes(l_data_header,&l_xl_part_size, 4); - if (l_xl_part_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); - return OPJ_FALSE; - } - opj_read_bytes(l_data_header+4,&(box->length), 4); - } + opj_read_bytes(l_data_header, &l_xl_part_size, 4); + if (l_xl_part_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + opj_read_bytes(l_data_header + 4, &(box->length), 4); + } return OPJ_TRUE; } #if 0 -static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { - OPJ_UINT32 i; - opj_jp2_box_t box; - - box.init_pos = cio_tell(cio); - cio_skip(cio, 4); - cio_write(cio, JP2_URL, 4); /* DBTL */ - cio_write(cio, 0, 1); /* VERS */ - cio_write(cio, 0, 3); /* FLAG */ - - if(Idx_file) { - for (i = 0; i < strlen(Idx_file); i++) { - cio_write(cio, Idx_file[i], 1); - } - } - - box.length = cio_tell(cio) - box.init_pos; - cio_seek(cio, box.init_pos); - cio_write(cio, box.length, 4); /* L */ - cio_seek(cio, box.init_pos + box.length); +static void jp2_write_url(opj_cio_t *cio, char *Idx_file) +{ + OPJ_UINT32 i; + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_URL, 4); /* DBTL */ + cio_write(cio, 0, 1); /* VERS */ + cio_write(cio, 0, 3); /* FLAG */ + + if (Idx_file) { + for (i = 0; i < strlen(Idx_file); i++) { + cio_write(cio, Idx_file[i], 1); + } + } + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); } #endif -static OPJ_BOOL opj_jp2_read_ihdr( opj_jp2_t *jp2, - OPJ_BYTE *p_image_header_data, - OPJ_UINT32 p_image_header_size, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_jp2_read_ihdr(opj_jp2_t *jp2, + OPJ_BYTE *p_image_header_data, + OPJ_UINT32 p_image_header_size, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(p_image_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - if (p_image_header_size != 14) { - opj_event_msg(p_manager, EVT_ERROR, "Bad image header box (bad size)\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_image_header_data,&(jp2->h),4); /* HEIGHT */ - p_image_header_data += 4; - opj_read_bytes(p_image_header_data,&(jp2->w),4); /* WIDTH */ - p_image_header_data += 4; - opj_read_bytes(p_image_header_data,&(jp2->numcomps),2); /* NC */ - p_image_header_data += 2; - - /* allocate memory for components */ - opj_free(jp2->comps); - jp2->comps = (opj_jp2_comps_t*) opj_calloc(jp2->numcomps, sizeof(opj_jp2_comps_t)); - if (jp2->comps == 0) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle image header (ihdr)\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_image_header_data,&(jp2->bpc),1); /* BPC */ - ++ p_image_header_data; - - opj_read_bytes(p_image_header_data,&(jp2->C),1); /* C */ - ++ p_image_header_data; - - /* Should be equal to 7 cf. chapter about image header box of the norm */ - if (jp2->C != 7){ - opj_event_msg(p_manager, EVT_INFO, "JP2 IHDR box: compression type indicate that the file is not a conforming JP2 file (%d) \n", jp2->C); - } - - opj_read_bytes(p_image_header_data,&(jp2->UnkC),1); /* UnkC */ - ++ p_image_header_data; - opj_read_bytes(p_image_header_data,&(jp2->IPR),1); /* IPR */ - ++ p_image_header_data; - - return OPJ_TRUE; + /* preconditions */ + assert(p_image_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if (jp2->comps != NULL) { + opj_event_msg(p_manager, EVT_WARNING, + "Ignoring ihdr box. First ihdr box already read\n"); + return OPJ_TRUE; + } + + if (p_image_header_size != 14) { + opj_event_msg(p_manager, EVT_ERROR, "Bad image header box (bad size)\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_image_header_data, &(jp2->h), 4); /* HEIGHT */ + p_image_header_data += 4; + opj_read_bytes(p_image_header_data, &(jp2->w), 4); /* WIDTH */ + p_image_header_data += 4; + opj_read_bytes(p_image_header_data, &(jp2->numcomps), 2); /* NC */ + p_image_header_data += 2; + + if ((jp2->numcomps - 1U) >= + 16384U) { /* unsigned underflow is well defined: 1U <= jp2->numcomps <= 16384U */ + opj_event_msg(p_manager, EVT_ERROR, "Invalid number of components (ihdr)\n"); + return OPJ_FALSE; + } + + /* allocate memory for components */ + opj_free(jp2->comps); + jp2->comps = (opj_jp2_comps_t*) opj_calloc(jp2->numcomps, + sizeof(opj_jp2_comps_t)); + if (jp2->comps == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to handle image header (ihdr)\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_image_header_data, &(jp2->bpc), 1); /* BPC */ + ++ p_image_header_data; + + opj_read_bytes(p_image_header_data, &(jp2->C), 1); /* C */ + ++ p_image_header_data; + + /* Should be equal to 7 cf. chapter about image header box of the norm */ + if (jp2->C != 7) { + opj_event_msg(p_manager, EVT_INFO, + "JP2 IHDR box: compression type indicate that the file is not a conforming JP2 file (%d) \n", + jp2->C); + } + + opj_read_bytes(p_image_header_data, &(jp2->UnkC), 1); /* UnkC */ + ++ p_image_header_data; + opj_read_bytes(p_image_header_data, &(jp2->IPR), 1); /* IPR */ + ++ p_image_header_data; + + jp2->j2k->m_cp.allow_different_bit_depth_sign = (jp2->bpc == 255); + jp2->j2k->ihdr_w = jp2->w; + jp2->j2k->ihdr_h = jp2->h; + jp2->has_ihdr = 1; + + return OPJ_TRUE; } static OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written - ) + OPJ_UINT32 * p_nb_bytes_written + ) { - OPJ_BYTE * l_ihdr_data,* l_current_ihdr_ptr; - - /* preconditions */ - assert(jp2 != 00); - assert(p_nb_bytes_written != 00); - - /* default image header is 22 bytes wide */ - l_ihdr_data = (OPJ_BYTE *) opj_calloc(1,22); - if (l_ihdr_data == 00) { - return 00; - } - - l_current_ihdr_ptr = l_ihdr_data; - - opj_write_bytes(l_current_ihdr_ptr,22,4); /* write box size */ - l_current_ihdr_ptr+=4; - - opj_write_bytes(l_current_ihdr_ptr,JP2_IHDR, 4); /* IHDR */ - l_current_ihdr_ptr+=4; - - opj_write_bytes(l_current_ihdr_ptr,jp2->h, 4); /* HEIGHT */ - l_current_ihdr_ptr+=4; - - opj_write_bytes(l_current_ihdr_ptr, jp2->w, 4); /* WIDTH */ - l_current_ihdr_ptr+=4; - - opj_write_bytes(l_current_ihdr_ptr, jp2->numcomps, 2); /* NC */ - l_current_ihdr_ptr+=2; - - opj_write_bytes(l_current_ihdr_ptr, jp2->bpc, 1); /* BPC */ - ++l_current_ihdr_ptr; - - opj_write_bytes(l_current_ihdr_ptr, jp2->C, 1); /* C : Always 7 */ - ++l_current_ihdr_ptr; - - opj_write_bytes(l_current_ihdr_ptr, jp2->UnkC, 1); /* UnkC, colorspace unknown */ - ++l_current_ihdr_ptr; - - opj_write_bytes(l_current_ihdr_ptr, jp2->IPR, 1); /* IPR, no intellectual property */ - ++l_current_ihdr_ptr; - - *p_nb_bytes_written = 22; - - return l_ihdr_data; + OPJ_BYTE * l_ihdr_data, * l_current_ihdr_ptr; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + + /* default image header is 22 bytes wide */ + l_ihdr_data = (OPJ_BYTE *) opj_calloc(1, 22); + if (l_ihdr_data == 00) { + return 00; + } + + l_current_ihdr_ptr = l_ihdr_data; + + opj_write_bytes(l_current_ihdr_ptr, 22, 4); /* write box size */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, JP2_IHDR, 4); /* IHDR */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, jp2->h, 4); /* HEIGHT */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, jp2->w, 4); /* WIDTH */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, jp2->numcomps, 2); /* NC */ + l_current_ihdr_ptr += 2; + + opj_write_bytes(l_current_ihdr_ptr, jp2->bpc, 1); /* BPC */ + ++l_current_ihdr_ptr; + + opj_write_bytes(l_current_ihdr_ptr, jp2->C, 1); /* C : Always 7 */ + ++l_current_ihdr_ptr; + + opj_write_bytes(l_current_ihdr_ptr, jp2->UnkC, + 1); /* UnkC, colorspace unknown */ + ++l_current_ihdr_ptr; + + opj_write_bytes(l_current_ihdr_ptr, jp2->IPR, + 1); /* IPR, no intellectual property */ + ++l_current_ihdr_ptr; + + *p_nb_bytes_written = 22; + + return l_ihdr_data; } -static OPJ_BYTE * opj_jp2_write_bpcc( opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written - ) +static OPJ_BYTE * opj_jp2_write_bpcc(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written + ) { - OPJ_UINT32 i; - /* room for 8 bytes for box and 1 byte for each component */ - OPJ_UINT32 l_bpcc_size = 8 + jp2->numcomps; - OPJ_BYTE * l_bpcc_data,* l_current_bpcc_ptr; - - /* preconditions */ - assert(jp2 != 00); - assert(p_nb_bytes_written != 00); - - l_bpcc_data = (OPJ_BYTE *) opj_calloc(1,l_bpcc_size); - if (l_bpcc_data == 00) { - return 00; - } - - l_current_bpcc_ptr = l_bpcc_data; - - opj_write_bytes(l_current_bpcc_ptr,l_bpcc_size,4); /* write box size */ - l_current_bpcc_ptr += 4; - - opj_write_bytes(l_current_bpcc_ptr,JP2_BPCC,4); /* BPCC */ - l_current_bpcc_ptr += 4; - - for (i = 0; i < jp2->numcomps; ++i) { - opj_write_bytes(l_current_bpcc_ptr, jp2->comps[i].bpcc, 1); /* write each component information */ - ++l_current_bpcc_ptr; - } - - *p_nb_bytes_written = l_bpcc_size; - - return l_bpcc_data; + OPJ_UINT32 i; + /* room for 8 bytes for box and 1 byte for each component */ + OPJ_UINT32 l_bpcc_size; + OPJ_BYTE * l_bpcc_data, * l_current_bpcc_ptr; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + l_bpcc_size = 8 + jp2->numcomps; + + l_bpcc_data = (OPJ_BYTE *) opj_calloc(1, l_bpcc_size); + if (l_bpcc_data == 00) { + return 00; + } + + l_current_bpcc_ptr = l_bpcc_data; + + opj_write_bytes(l_current_bpcc_ptr, l_bpcc_size, + 4); /* write box size */ + l_current_bpcc_ptr += 4; + + opj_write_bytes(l_current_bpcc_ptr, JP2_BPCC, 4); /* BPCC */ + l_current_bpcc_ptr += 4; + + for (i = 0; i < jp2->numcomps; ++i) { + opj_write_bytes(l_current_bpcc_ptr, jp2->comps[i].bpcc, + 1); /* write each component information */ + ++l_current_bpcc_ptr; + } + + *p_nb_bytes_written = l_bpcc_size; + + return l_bpcc_data; } -static OPJ_BOOL opj_jp2_read_bpcc( opj_jp2_t *jp2, - OPJ_BYTE * p_bpc_header_data, - OPJ_UINT32 p_bpc_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_bpcc(opj_jp2_t *jp2, + OPJ_BYTE * p_bpc_header_data, + OPJ_UINT32 p_bpc_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 i; - - /* preconditions */ - assert(p_bpc_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - - if (jp2->bpc != 255 ){ - opj_event_msg(p_manager, EVT_WARNING, "A BPCC header box is available although BPC given by the IHDR box (%d) indicate components bit depth is constant\n",jp2->bpc); - } - - /* and length is relevant */ - if (p_bpc_header_size != jp2->numcomps) { - opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n"); - return OPJ_FALSE; - } - - /* read info for each component */ - for (i = 0; i < jp2->numcomps; ++i) { - opj_read_bytes(p_bpc_header_data,&jp2->comps[i].bpcc ,1); /* read each BPCC component */ - ++p_bpc_header_data; - } - - return OPJ_TRUE; + OPJ_UINT32 i; + + /* preconditions */ + assert(p_bpc_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + + if (jp2->bpc != 255) { + opj_event_msg(p_manager, EVT_WARNING, + "A BPCC header box is available although BPC given by the IHDR box (%d) indicate components bit depth is constant\n", + jp2->bpc); + } + + /* and length is relevant */ + if (p_bpc_header_size != jp2->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n"); + return OPJ_FALSE; + } + + /* read info for each component */ + for (i = 0; i < jp2->numcomps; ++i) { + opj_read_bytes(p_bpc_header_data, &jp2->comps[i].bpcc, + 1); /* read each BPCC component */ + ++p_bpc_header_data; + } + + return OPJ_TRUE; } -static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, OPJ_UINT32 * p_nb_bytes_written) +static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written) { - /* room for 8 bytes for box, 2 for n */ - OPJ_UINT32 l_cdef_size = 10; - OPJ_BYTE * l_cdef_data,* l_current_cdef_ptr; - OPJ_UINT32 l_value; - OPJ_UINT16 i; - - /* preconditions */ - assert(jp2 != 00); - assert(p_nb_bytes_written != 00); - assert(jp2->color.jp2_cdef != 00); - assert(jp2->color.jp2_cdef->info != 00); - assert(jp2->color.jp2_cdef->n > 0U); - - l_cdef_size += 6U * jp2->color.jp2_cdef->n; - - l_cdef_data = (OPJ_BYTE *) opj_malloc(l_cdef_size); - if (l_cdef_data == 00) { - return 00; - } - - l_current_cdef_ptr = l_cdef_data; - - opj_write_bytes(l_current_cdef_ptr,l_cdef_size,4); /* write box size */ - l_current_cdef_ptr += 4; - - opj_write_bytes(l_current_cdef_ptr,JP2_CDEF,4); /* BPCC */ - l_current_cdef_ptr += 4; - - l_value = jp2->color.jp2_cdef->n; - opj_write_bytes(l_current_cdef_ptr,l_value,2); /* N */ - l_current_cdef_ptr += 2; - - for (i = 0U; i < jp2->color.jp2_cdef->n; ++i) { - l_value = jp2->color.jp2_cdef->info[i].cn; - opj_write_bytes(l_current_cdef_ptr,l_value,2); /* Cni */ - l_current_cdef_ptr += 2; - l_value = jp2->color.jp2_cdef->info[i].typ; - opj_write_bytes(l_current_cdef_ptr,l_value,2); /* Typi */ - l_current_cdef_ptr += 2; - l_value = jp2->color.jp2_cdef->info[i].asoc; - opj_write_bytes(l_current_cdef_ptr,l_value,2); /* Asoci */ - l_current_cdef_ptr += 2; - } - *p_nb_bytes_written = l_cdef_size; - - return l_cdef_data; + /* room for 8 bytes for box, 2 for n */ + OPJ_UINT32 l_cdef_size = 10; + OPJ_BYTE * l_cdef_data, * l_current_cdef_ptr; + OPJ_UINT32 l_value; + OPJ_UINT16 i; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + assert(jp2->color.jp2_cdef != 00); + assert(jp2->color.jp2_cdef->info != 00); + assert(jp2->color.jp2_cdef->n > 0U); + + l_cdef_size += 6U * jp2->color.jp2_cdef->n; + + l_cdef_data = (OPJ_BYTE *) opj_malloc(l_cdef_size); + if (l_cdef_data == 00) { + return 00; + } + + l_current_cdef_ptr = l_cdef_data; + + opj_write_bytes(l_current_cdef_ptr, l_cdef_size, 4); /* write box size */ + l_current_cdef_ptr += 4; + + opj_write_bytes(l_current_cdef_ptr, JP2_CDEF, 4); /* BPCC */ + l_current_cdef_ptr += 4; + + l_value = jp2->color.jp2_cdef->n; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* N */ + l_current_cdef_ptr += 2; + + for (i = 0U; i < jp2->color.jp2_cdef->n; ++i) { + l_value = jp2->color.jp2_cdef->info[i].cn; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* Cni */ + l_current_cdef_ptr += 2; + l_value = jp2->color.jp2_cdef->info[i].typ; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* Typi */ + l_current_cdef_ptr += 2; + l_value = jp2->color.jp2_cdef->info[i].asoc; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* Asoci */ + l_current_cdef_ptr += 2; + } + *p_nb_bytes_written = l_cdef_size; + + return l_cdef_data; } -static OPJ_BYTE * opj_jp2_write_colr( opj_jp2_t *jp2, - OPJ_UINT32 * p_nb_bytes_written - ) +static OPJ_BYTE * opj_jp2_write_colr(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written + ) { - /* room for 8 bytes for box 3 for common data and variable upon profile*/ - OPJ_UINT32 l_colr_size = 11; - OPJ_BYTE * l_colr_data,* l_current_colr_ptr; + /* room for 8 bytes for box 3 for common data and variable upon profile*/ + OPJ_UINT32 l_colr_size = 11; + OPJ_BYTE * l_colr_data, * l_current_colr_ptr; - /* preconditions */ - assert(jp2 != 00); - assert(p_nb_bytes_written != 00); + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); assert(jp2->meth == 1 || jp2->meth == 2); - switch (jp2->meth) { - case 1 : - l_colr_size += 4; /* EnumCS */ - break; - case 2 : - assert(jp2->color.icc_profile_len); /* ICC profile */ - l_colr_size += jp2->color.icc_profile_len; - break; - default : - return 00; - } - - l_colr_data = (OPJ_BYTE *) opj_calloc(1,l_colr_size); - if (l_colr_data == 00) { - return 00; - } - - l_current_colr_ptr = l_colr_data; - - opj_write_bytes(l_current_colr_ptr,l_colr_size,4); /* write box size */ - l_current_colr_ptr += 4; - - opj_write_bytes(l_current_colr_ptr,JP2_COLR,4); /* BPCC */ - l_current_colr_ptr += 4; - - opj_write_bytes(l_current_colr_ptr, jp2->meth,1); /* METH */ - ++l_current_colr_ptr; - - opj_write_bytes(l_current_colr_ptr, jp2->precedence,1); /* PRECEDENCE */ - ++l_current_colr_ptr; - - opj_write_bytes(l_current_colr_ptr, jp2->approx,1); /* APPROX */ - ++l_current_colr_ptr; - - if (jp2->meth == 1) { /* Meth value is restricted to 1 or 2 (Table I.9 of part 1) */ - opj_write_bytes(l_current_colr_ptr, jp2->enumcs,4); } /* EnumCS */ + switch (jp2->meth) { + case 1 : + l_colr_size += 4; /* EnumCS */ + break; + case 2 : + assert(jp2->color.icc_profile_len); /* ICC profile */ + l_colr_size += jp2->color.icc_profile_len; + break; + default : + return 00; + } + + l_colr_data = (OPJ_BYTE *) opj_calloc(1, l_colr_size); + if (l_colr_data == 00) { + return 00; + } + + l_current_colr_ptr = l_colr_data; + + opj_write_bytes(l_current_colr_ptr, l_colr_size, + 4); /* write box size */ + l_current_colr_ptr += 4; + + opj_write_bytes(l_current_colr_ptr, JP2_COLR, 4); /* BPCC */ + l_current_colr_ptr += 4; + + opj_write_bytes(l_current_colr_ptr, jp2->meth, 1); /* METH */ + ++l_current_colr_ptr; + + opj_write_bytes(l_current_colr_ptr, jp2->precedence, 1); /* PRECEDENCE */ + ++l_current_colr_ptr; + + opj_write_bytes(l_current_colr_ptr, jp2->approx, 1); /* APPROX */ + ++l_current_colr_ptr; + + if (jp2->meth == + 1) { /* Meth value is restricted to 1 or 2 (Table I.9 of part 1) */ + opj_write_bytes(l_current_colr_ptr, jp2->enumcs, 4); + } /* EnumCS */ else { if (jp2->meth == 2) { /* ICC profile */ OPJ_UINT32 i; - for(i = 0; i < jp2->color.icc_profile_len; ++i) { + for (i = 0; i < jp2->color.icc_profile_len; ++i) { opj_write_bytes(l_current_colr_ptr, jp2->color.icc_profile_buf[i], 1); ++l_current_colr_ptr; } } - } + } + + *p_nb_bytes_written = l_colr_size; - *p_nb_bytes_written = l_colr_size; - - return l_colr_data; + return l_colr_data; } static void opj_jp2_free_pclr(opj_jp2_color_t *color) @@ -825,1521 +878,1671 @@ static void opj_jp2_free_pclr(opj_jp2_color_t *color) opj_free(color->jp2_pclr->channel_size); opj_free(color->jp2_pclr->entries); - if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap); + if (color->jp2_pclr->cmap) { + opj_free(color->jp2_pclr->cmap); + } - opj_free(color->jp2_pclr); color->jp2_pclr = NULL; + opj_free(color->jp2_pclr); + color->jp2_pclr = NULL; } -static OPJ_BOOL opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, opj_event_mgr_t *p_manager) +static OPJ_BOOL opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, + opj_event_mgr_t *p_manager) { - OPJ_UINT16 i; - - /* testcase 4149.pdf.SIGSEGV.cf7.3501 */ - if (color->jp2_cdef) { - opj_jp2_cdef_info_t *info = color->jp2_cdef->info; - OPJ_UINT16 n = color->jp2_cdef->n; - OPJ_UINT32 nr_channels = image->numcomps; /* FIXME image->numcomps == jp2->numcomps before color is applied ??? */ - - /* cdef applies to cmap channels if any */ - if (color->jp2_pclr && color->jp2_pclr->cmap) { - nr_channels = (OPJ_UINT32)color->jp2_pclr->nr_channels; - } - - for (i = 0; i < n; i++) { - if (info[i].cn >= nr_channels) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].cn, nr_channels); - return OPJ_FALSE; - } - if (info[i].asoc == 65535U) continue; - - if (info[i].asoc > 0 && (OPJ_UINT32)(info[i].asoc - 1) >= nr_channels) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].asoc - 1, nr_channels); - return OPJ_FALSE; - } - } - - /* issue 397 */ - /* ISO 15444-1 states that if cdef is present, it shall contain a complete list of channel definitions. */ - while (nr_channels > 0) - { - for(i = 0; i < n; ++i) { - if ((OPJ_UINT32)info[i].cn == (nr_channels - 1U)) { - break; - } - } - if (i == n) { - opj_event_msg(p_manager, EVT_ERROR, "Incomplete channel definitions.\n"); - return OPJ_FALSE; - } - --nr_channels; - } - } - - /* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and - 66ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725.pdf */ - if (color->jp2_pclr && color->jp2_pclr->cmap) { - OPJ_UINT16 nr_channels = color->jp2_pclr->nr_channels; - opj_jp2_cmap_comp_t *cmap = color->jp2_pclr->cmap; - OPJ_BOOL *pcol_usage, is_sane = OPJ_TRUE; - - /* verify that all original components match an existing one */ - for (i = 0; i < nr_channels; i++) { - if (cmap[i].cmp >= image->numcomps) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", cmap[i].cmp, image->numcomps); - is_sane = OPJ_FALSE; - } - } - - pcol_usage = opj_calloc(nr_channels, sizeof(OPJ_BOOL)); - if (!pcol_usage) { - opj_event_msg(p_manager, EVT_ERROR, "Unexpected OOM.\n"); - return OPJ_FALSE; - } - /* verify that no component is targeted more than once */ - for (i = 0; i < nr_channels; i++) { - if (cmap[i].mtyp != 0 && cmap[i].mtyp != 1) { - opj_event_msg(p_manager, EVT_ERROR, "Unexpected MTYP value.\n"); - opj_free(pcol_usage); - return OPJ_FALSE; - } - OPJ_UINT16 pcol = cmap[i].pcol; - if (pcol >= nr_channels) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid component/palette index for direct mapping %d.\n", pcol); - is_sane = OPJ_FALSE; - } - else if (pcol_usage[pcol] && cmap[i].mtyp != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Component %d is mapped twice.\n", pcol); - is_sane = OPJ_FALSE; - } - else if (cmap[i].mtyp == 0 && cmap[i].pcol != 0) { - /* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then - * the value of this field shall be 0. */ - opj_event_msg(p_manager, EVT_ERROR, "Direct use at #%d however pcol=%d.\n", i, pcol); - is_sane = OPJ_FALSE; - } - else - pcol_usage[pcol] = OPJ_TRUE; - } - /* verify that all components are targeted at least once */ - for (i = 0; i < nr_channels; i++) { - if (!pcol_usage[i] && cmap[i].mtyp != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Component %d doesn't have a mapping.\n", i); - is_sane = OPJ_FALSE; - } - } - /* Issue 235/447 weird cmap */ - if (1 && is_sane && (image->numcomps==1U)) { - for (i = 0; i < nr_channels; i++) { - if (!pcol_usage[i]) { - is_sane = 0U; - opj_event_msg(p_manager, EVT_WARNING, "Component mapping seems wrong. Trying to correct.\n", i); - break; - } - } - if (!is_sane) { - is_sane = OPJ_TRUE; - for (i = 0; i < nr_channels; i++) { - cmap[i].mtyp = 1U; - cmap[i].pcol = (OPJ_BYTE) i; - } - } - } - opj_free(pcol_usage); - if (!is_sane) { - return OPJ_FALSE; - } - } - - return OPJ_TRUE; + OPJ_UINT16 i; + + /* testcase 4149.pdf.SIGSEGV.cf7.3501 */ + if (color->jp2_cdef) { + opj_jp2_cdef_info_t *info = color->jp2_cdef->info; + OPJ_UINT16 n = color->jp2_cdef->n; + OPJ_UINT32 nr_channels = + image->numcomps; /* FIXME image->numcomps == jp2->numcomps before color is applied ??? */ + + /* cdef applies to cmap channels if any */ + if (color->jp2_pclr && color->jp2_pclr->cmap) { + nr_channels = (OPJ_UINT32)color->jp2_pclr->nr_channels; + } + + for (i = 0; i < n; i++) { + if (info[i].cn >= nr_channels) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", + info[i].cn, nr_channels); + return OPJ_FALSE; + } + if (info[i].asoc == 65535U) { + continue; + } + + if (info[i].asoc > 0 && (OPJ_UINT32)(info[i].asoc - 1) >= nr_channels) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", + info[i].asoc - 1, nr_channels); + return OPJ_FALSE; + } + } + + /* issue 397 */ + /* ISO 15444-1 states that if cdef is present, it shall contain a complete list of channel definitions. */ + while (nr_channels > 0) { + for (i = 0; i < n; ++i) { + if ((OPJ_UINT32)info[i].cn == (nr_channels - 1U)) { + break; + } + } + if (i == n) { + opj_event_msg(p_manager, EVT_ERROR, "Incomplete channel definitions.\n"); + return OPJ_FALSE; + } + --nr_channels; + } + } + + /* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and + 66ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725.pdf */ + if (color->jp2_pclr && color->jp2_pclr->cmap) { + OPJ_UINT16 nr_channels = color->jp2_pclr->nr_channels; + opj_jp2_cmap_comp_t *cmap = color->jp2_pclr->cmap; + OPJ_BOOL *pcol_usage, is_sane = OPJ_TRUE; + + /* verify that all original components match an existing one */ + for (i = 0; i < nr_channels; i++) { + if (cmap[i].cmp >= image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", + cmap[i].cmp, image->numcomps); + is_sane = OPJ_FALSE; + } + } + + pcol_usage = (OPJ_BOOL *) opj_calloc(nr_channels, sizeof(OPJ_BOOL)); + if (!pcol_usage) { + opj_event_msg(p_manager, EVT_ERROR, "Unexpected OOM.\n"); + return OPJ_FALSE; + } + /* verify that no component is targeted more than once */ + for (i = 0; i < nr_channels; i++) { + OPJ_BYTE mtyp = cmap[i].mtyp; + OPJ_BYTE pcol = cmap[i].pcol; + /* See ISO 15444-1 Table I.14 – MTYPi field values */ + if (mtyp != 0 && mtyp != 1) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cmap[%d].mtyp = %d.\n", i, + mtyp); + is_sane = OPJ_FALSE; + } else if (pcol >= nr_channels) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid component/palette index for direct mapping %d.\n", pcol); + is_sane = OPJ_FALSE; + } else if (pcol_usage[pcol] && mtyp == 1) { + opj_event_msg(p_manager, EVT_ERROR, "Component %d is mapped twice.\n", pcol); + is_sane = OPJ_FALSE; + } else if (mtyp == 0 && pcol != 0) { + /* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then + * the value of this field shall be 0. */ + opj_event_msg(p_manager, EVT_ERROR, "Direct use at #%d however pcol=%d.\n", i, + pcol); + is_sane = OPJ_FALSE; + } else if (mtyp == 1 && pcol != i) { + /* OpenJPEG implementation limitation. See assert(i == pcol); */ + /* in opj_jp2_apply_pclr() */ + opj_event_msg(p_manager, EVT_ERROR, + "Implementation limitation: for palette mapping, " + "pcol[%d] should be equal to %d, but is equal " + "to %d.\n", i, i, pcol); + is_sane = OPJ_FALSE; + } else { + pcol_usage[pcol] = OPJ_TRUE; + } + } + /* verify that all components are targeted at least once */ + for (i = 0; i < nr_channels; i++) { + if (!pcol_usage[i] && cmap[i].mtyp != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Component %d doesn't have a mapping.\n", + i); + is_sane = OPJ_FALSE; + } + } + /* Issue 235/447 weird cmap */ + if (1 && is_sane && (image->numcomps == 1U)) { + for (i = 0; i < nr_channels; i++) { + if (!pcol_usage[i]) { + is_sane = 0U; + opj_event_msg(p_manager, EVT_WARNING, + "Component mapping seems wrong. Trying to correct.\n", i); + break; + } + } + if (!is_sane) { + is_sane = OPJ_TRUE; + for (i = 0; i < nr_channels; i++) { + cmap[i].mtyp = 1U; + cmap[i].pcol = (OPJ_BYTE) i; + } + } + } + opj_free(pcol_usage); + if (!is_sane) { + return OPJ_FALSE; + } + } + + return OPJ_TRUE; } /* file9.jp2 */ -static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color) +static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + opj_jp2_color_t *color, + opj_event_mgr_t * p_manager) { - opj_image_comp_t *old_comps, *new_comps; - OPJ_BYTE *channel_size, *channel_sign; - OPJ_UINT32 *entries; - opj_jp2_cmap_comp_t *cmap; - OPJ_INT32 *src, *dst; - OPJ_UINT32 j, max; - OPJ_UINT16 i, nr_channels, cmp, pcol; - OPJ_INT32 k, top_k; - - channel_size = color->jp2_pclr->channel_size; - channel_sign = color->jp2_pclr->channel_sign; - entries = color->jp2_pclr->entries; - cmap = color->jp2_pclr->cmap; - nr_channels = color->jp2_pclr->nr_channels; - - old_comps = image->comps; - /* Overflow check: prevent integer overflow */ - for (i = 0; i < nr_channels; ++i) { - cmp = cmap[i].cmp; - if (old_comps[cmp].h == 0 || old_comps[cmp].w > ((OPJ_UINT32)-1) / sizeof(OPJ_INT32) / old_comps[cmp].h) { - return; - } - } - - new_comps = (opj_image_comp_t*) - opj_malloc(nr_channels * sizeof(opj_image_comp_t)); - if (!new_comps) { - /* FIXME no error code for opj_jp2_apply_pclr */ - /* FIXME event manager error callback */ - return; - } - for(i = 0; i < nr_channels; ++i) { - pcol = cmap[i].pcol; cmp = cmap[i].cmp; - - /* Direct use */ - if(cmap[i].mtyp == 0){ - assert( pcol == 0 ); - new_comps[i] = old_comps[cmp]; - } else { - assert( i == pcol ); // probably wrong? - new_comps[i] = old_comps[cmp]; - } - - /* Palette mapping: */ - new_comps[i].data = (OPJ_INT32*) - opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(OPJ_INT32)); - if (!new_comps[i].data) { - opj_free(new_comps); - new_comps = NULL; - /* FIXME no error code for opj_jp2_apply_pclr */ - /* FIXME event manager error callback */ - return; - } - new_comps[i].prec = channel_size[i]; - new_comps[i].sgnd = channel_sign[i]; - } - - top_k = color->jp2_pclr->nr_entries - 1; - - for(i = 0; i < nr_channels; ++i) { - /* Palette mapping: */ - cmp = cmap[i].cmp; pcol = cmap[i].pcol; - src = old_comps[cmp].data; - dst = new_comps[i].data; - max = new_comps[i].w * new_comps[i].h; - - /* Prevent null pointer access */ - if (!src || !dst) { - for (j = 0; j < nr_channels; ++j) { - opj_free(new_comps[j].data); - } - opj_free(new_comps); - new_comps = NULL; - return; - } - - /* Direct use: */ - if(cmap[i].mtyp == 0) { - assert( cmp == 0 ); // probably wrong. - for(j = 0; j < max; ++j) { - dst[j] = src[j]; + opj_image_comp_t *old_comps, *new_comps; + OPJ_BYTE *channel_size, *channel_sign; + OPJ_UINT32 *entries; + opj_jp2_cmap_comp_t *cmap; + OPJ_INT32 *src, *dst; + OPJ_UINT32 j, max; + OPJ_UINT16 i, nr_channels, cmp, pcol; + OPJ_INT32 k, top_k; + + channel_size = color->jp2_pclr->channel_size; + channel_sign = color->jp2_pclr->channel_sign; + entries = color->jp2_pclr->entries; + cmap = color->jp2_pclr->cmap; + nr_channels = color->jp2_pclr->nr_channels; + + for (i = 0; i < nr_channels; ++i) { + /* Palette mapping: */ + cmp = cmap[i].cmp; + if (image->comps[cmp].data == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "image->comps[%d].data == NULL in opj_jp2_apply_pclr().\n", i); + return OPJ_FALSE; + } + } + + old_comps = image->comps; + /* Overflow check: prevent integer overflow */ + for (i = 0; i < nr_channels; ++i) { + cmp = cmap[i].cmp; + if (old_comps[cmp].h == 0 || old_comps[cmp].w > ((OPJ_UINT32)-1) / sizeof(OPJ_INT32) / old_comps[cmp].h) { + return OPJ_FALSE; } } - else { - assert( i == pcol ); // probably wrong? - for(j = 0; j < max; ++j) { - /* The index */ - if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; - /* The colour */ - dst[j] = (OPJ_INT32)entries[k * nr_channels + pcol]; + new_comps = (opj_image_comp_t*) + opj_malloc(nr_channels * sizeof(opj_image_comp_t)); + if (!new_comps) { + opj_event_msg(p_manager, EVT_ERROR, + "Memory allocation failure in opj_jp2_apply_pclr().\n"); + return OPJ_FALSE; + } + for (i = 0; i < nr_channels; ++i) { + pcol = cmap[i].pcol; + cmp = cmap[i].cmp; + + /* Direct use */ + if (cmap[i].mtyp == 0) { + assert(pcol == 0); + new_comps[i] = old_comps[cmp]; + } else { + assert( i == pcol ); // probably wrong? + new_comps[i] = old_comps[cmp]; + } + + /* Palette mapping: */ + new_comps[i].data = (OPJ_INT32*) + opj_image_data_alloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(OPJ_INT32)); + if (!new_comps[i].data) { + while (i > 0) { + -- i; + opj_image_data_free(new_comps[i].data); + } + opj_free(new_comps); + opj_event_msg(p_manager, EVT_ERROR, + "Memory allocation failure in opj_jp2_apply_pclr().\n"); + return OPJ_FALSE; } + new_comps[i].prec = channel_size[i]; + new_comps[i].sgnd = channel_sign[i]; } - } - max = image->numcomps; - for(i = 0; i < max; ++i) { - if(old_comps[i].data) opj_free(old_comps[i].data); - } + top_k = color->jp2_pclr->nr_entries - 1; + + for (i = 0; i < nr_channels; ++i) { + /* Palette mapping: */ + cmp = cmap[i].cmp; + pcol = cmap[i].pcol; + src = old_comps[cmp].data; + dst = new_comps[i].data; + max = new_comps[i].w * new_comps[i].h; + + /* Prevent null pointer access */ + if (!src || !dst) { + for (j = 0; j < nr_channels; ++j) { + opj_image_data_free(new_comps[j].data); + } + opj_free(new_comps); + new_comps = NULL; + return OPJ_FALSE; + } + + /* Direct use: */ + if (cmap[i].mtyp == 0) { + assert( cmp == 0 ); // probably wrong. + for (j = 0; j < max; ++j) { + dst[j] = src[j]; + } + } else { + assert( i == pcol ); // probably wrong? + for (j = 0; j < max; ++j) { + /* The index */ + if ((k = src[j]) < 0) { + k = 0; + } else if (k > top_k) { + k = top_k; + } + + /* The colour */ + dst[j] = (OPJ_INT32)entries[k * nr_channels + pcol]; + } + } + } - opj_free(old_comps); - image->comps = new_comps; - image->numcomps = nr_channels; + max = image->numcomps; + for (i = 0; i < max; ++i) { + if (old_comps[i].data) { + opj_image_data_free(old_comps[i].data); + } + } - opj_jp2_free_pclr(color); + opj_free(old_comps); + image->comps = new_comps; + image->numcomps = nr_channels; + return OPJ_TRUE; }/* apply_pclr() */ -static OPJ_BOOL opj_jp2_read_pclr( opj_jp2_t *jp2, - OPJ_BYTE * p_pclr_header_data, - OPJ_UINT32 p_pclr_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_pclr(opj_jp2_t *jp2, + OPJ_BYTE * p_pclr_header_data, + OPJ_UINT32 p_pclr_header_size, + opj_event_mgr_t * p_manager + ) { - opj_jp2_pclr_t *jp2_pclr; - OPJ_BYTE *channel_size, *channel_sign; - OPJ_UINT32 *entries; - OPJ_UINT16 nr_entries,nr_channels; - OPJ_UINT16 i, j; - OPJ_UINT32 l_value; - OPJ_BYTE *orig_header_data = p_pclr_header_data; - - /* preconditions */ - assert(p_pclr_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); + opj_jp2_pclr_t *jp2_pclr; + OPJ_BYTE *channel_size, *channel_sign; + OPJ_UINT32 *entries; + OPJ_UINT16 nr_entries, nr_channels; + OPJ_UINT16 i, j; + OPJ_UINT32 l_value; + OPJ_BYTE *orig_header_data = p_pclr_header_data; + + /* preconditions */ + assert(p_pclr_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); (void)p_pclr_header_size; - if(jp2->color.jp2_pclr) - return OPJ_FALSE; - - if (p_pclr_header_size < 3) - return OPJ_FALSE; - - opj_read_bytes(p_pclr_header_data, &l_value , 2); /* NE */ - p_pclr_header_data += 2; - nr_entries = (OPJ_UINT16) l_value; - if ((nr_entries == 0U) || (nr_entries > 1024U)) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid PCLR box. Reports %d entries\n", (int)nr_entries); - return OPJ_FALSE; - } - - opj_read_bytes(p_pclr_header_data, &l_value , 1); /* NPC */ - ++p_pclr_header_data; - nr_channels = (OPJ_UINT16) l_value; - if (nr_channels == 0U) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid PCLR box. Reports 0 palette columns\n"); - return OPJ_FALSE; - } - - if (p_pclr_header_size < 3 + (OPJ_UINT32)nr_channels) - return OPJ_FALSE; - - entries = (OPJ_UINT32*) opj_malloc((size_t)nr_channels * nr_entries * sizeof(OPJ_UINT32)); - if (!entries) - return OPJ_FALSE; - channel_size = (OPJ_BYTE*) opj_malloc(nr_channels); - if (!channel_size) - { + if (jp2->color.jp2_pclr) { + return OPJ_FALSE; + } + + if (p_pclr_header_size < 3) { + return OPJ_FALSE; + } + + opj_read_bytes(p_pclr_header_data, &l_value, 2); /* NE */ + p_pclr_header_data += 2; + nr_entries = (OPJ_UINT16) l_value; + if ((nr_entries == 0U) || (nr_entries > 1024U)) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid PCLR box. Reports %d entries\n", + (int)nr_entries); + return OPJ_FALSE; + } + + opj_read_bytes(p_pclr_header_data, &l_value, 1); /* NPC */ + ++p_pclr_header_data; + nr_channels = (OPJ_UINT16) l_value; + if (nr_channels == 0U) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid PCLR box. Reports 0 palette columns\n"); + return OPJ_FALSE; + } + + if (p_pclr_header_size < 3 + (OPJ_UINT32)nr_channels) { + return OPJ_FALSE; + } + + entries = (OPJ_UINT32*) opj_malloc((size_t)nr_channels * nr_entries * sizeof( + OPJ_UINT32)); + if (!entries) { + return OPJ_FALSE; + } + channel_size = (OPJ_BYTE*) opj_malloc(nr_channels); + if (!channel_size) { opj_free(entries); return OPJ_FALSE; } - channel_sign = (OPJ_BYTE*) opj_malloc(nr_channels); - if (!channel_sign) - { + channel_sign = (OPJ_BYTE*) opj_malloc(nr_channels); + if (!channel_sign) { opj_free(entries); opj_free(channel_size); return OPJ_FALSE; - } + } - jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); - if (!jp2_pclr) - { + jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); + if (!jp2_pclr) { opj_free(entries); opj_free(channel_size); opj_free(channel_sign); return OPJ_FALSE; } - jp2_pclr->channel_sign = channel_sign; - jp2_pclr->channel_size = channel_size; - jp2_pclr->entries = entries; - jp2_pclr->nr_entries = nr_entries; - jp2_pclr->nr_channels = (OPJ_BYTE) l_value; - jp2_pclr->cmap = NULL; + jp2_pclr->channel_sign = channel_sign; + jp2_pclr->channel_size = channel_size; + jp2_pclr->entries = entries; + jp2_pclr->nr_entries = nr_entries; + jp2_pclr->nr_channels = (OPJ_BYTE) l_value; + jp2_pclr->cmap = NULL; - jp2->color.jp2_pclr = jp2_pclr; + jp2->color.jp2_pclr = jp2_pclr; - for(i = 0; i < nr_channels; ++i) { - opj_read_bytes(p_pclr_header_data, &l_value , 1); /* Bi */ - ++p_pclr_header_data; + for (i = 0; i < nr_channels; ++i) { + opj_read_bytes(p_pclr_header_data, &l_value, 1); /* Bi */ + ++p_pclr_header_data; - channel_size[i] = (OPJ_BYTE)((l_value & 0x7f) + 1); - channel_sign[i] = (l_value & 0x80) ? 1 : 0; - } + channel_size[i] = (OPJ_BYTE)((l_value & 0x7f) + 1); + channel_sign[i] = (l_value & 0x80) ? 1 : 0; + } - for(j = 0; j < nr_entries; ++j) { - for(i = 0; i < nr_channels; ++i) { - OPJ_UINT32 bytes_to_read = (OPJ_UINT32)((channel_size[i]+7)>>3); + for (j = 0; j < nr_entries; ++j) { + for (i = 0; i < nr_channels; ++i) { + OPJ_UINT32 bytes_to_read = (OPJ_UINT32)((channel_size[i] + 7) >> 3); - if (bytes_to_read > sizeof(OPJ_UINT32)) - bytes_to_read = sizeof(OPJ_UINT32); - if ((ptrdiff_t)p_pclr_header_size < (ptrdiff_t)(p_pclr_header_data - orig_header_data) + (ptrdiff_t)bytes_to_read) - return OPJ_FALSE; + if (bytes_to_read > sizeof(OPJ_UINT32)) { + bytes_to_read = sizeof(OPJ_UINT32); + } + if ((ptrdiff_t)p_pclr_header_size < (ptrdiff_t)(p_pclr_header_data - + orig_header_data) + (ptrdiff_t)bytes_to_read) { + return OPJ_FALSE; + } - opj_read_bytes(p_pclr_header_data, &l_value , bytes_to_read); /* Cji */ - p_pclr_header_data += bytes_to_read; - *entries = (OPJ_UINT32) l_value; - entries++; - } - } + opj_read_bytes(p_pclr_header_data, &l_value, bytes_to_read); /* Cji */ + p_pclr_header_data += bytes_to_read; + *entries = (OPJ_UINT32) l_value; + entries++; + } + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_read_cmap( opj_jp2_t * jp2, - OPJ_BYTE * p_cmap_header_data, - OPJ_UINT32 p_cmap_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_cmap(opj_jp2_t * jp2, + OPJ_BYTE * p_cmap_header_data, + OPJ_UINT32 p_cmap_header_size, + opj_event_mgr_t * p_manager + ) { - opj_jp2_cmap_comp_t *cmap; - OPJ_BYTE i, nr_channels; - OPJ_UINT32 l_value; - - /* preconditions */ - assert(jp2 != 00); - assert(p_cmap_header_data != 00); - assert(p_manager != 00); + opj_jp2_cmap_comp_t *cmap; + OPJ_BYTE i, nr_channels; + OPJ_UINT32 l_value; + + /* preconditions */ + assert(jp2 != 00); + assert(p_cmap_header_data != 00); + assert(p_manager != 00); (void)p_cmap_header_size; - /* Need nr_channels: */ - if(jp2->color.jp2_pclr == NULL) { - opj_event_msg(p_manager, EVT_ERROR, "Need to read a PCLR box before the CMAP box.\n"); - return OPJ_FALSE; - } + /* Need nr_channels: */ + if (jp2->color.jp2_pclr == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "Need to read a PCLR box before the CMAP box.\n"); + return OPJ_FALSE; + } - /* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box - * inside a JP2 Header box' : - */ - if(jp2->color.jp2_pclr->cmap) { - opj_event_msg(p_manager, EVT_ERROR, "Only one CMAP box is allowed.\n"); - return OPJ_FALSE; - } + /* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box + * inside a JP2 Header box' : + */ + if (jp2->color.jp2_pclr->cmap) { + opj_event_msg(p_manager, EVT_ERROR, "Only one CMAP box is allowed.\n"); + return OPJ_FALSE; + } - nr_channels = jp2->color.jp2_pclr->nr_channels; - if (p_cmap_header_size < (OPJ_UINT32)nr_channels * 4) { - opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CMAP box.\n"); - return OPJ_FALSE; - } + nr_channels = jp2->color.jp2_pclr->nr_channels; + if (p_cmap_header_size < (OPJ_UINT32)nr_channels * 4) { + opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CMAP box.\n"); + return OPJ_FALSE; + } - cmap = (opj_jp2_cmap_comp_t*) opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t)); - if (!cmap) + cmap = (opj_jp2_cmap_comp_t*) opj_malloc(nr_channels * sizeof( + opj_jp2_cmap_comp_t)); + if (!cmap) { return OPJ_FALSE; + } - for(i = 0; i < nr_channels; ++i) { - opj_read_bytes_BE(p_cmap_header_data, &l_value, 2); /* CMP^i */ - p_cmap_header_data +=2; - cmap[i].cmp = (OPJ_UINT16) l_value; + for (i = 0; i < nr_channels; ++i) { + opj_read_bytes_BE(p_cmap_header_data, &l_value, 2); /* CMP^i */ + p_cmap_header_data += 2; + cmap[i].cmp = (OPJ_UINT16) l_value; - opj_read_bytes(p_cmap_header_data, &l_value, 1); /* MTYP^i */ - ++p_cmap_header_data; - cmap[i].mtyp = (OPJ_BYTE) l_value; + opj_read_bytes(p_cmap_header_data, &l_value, 1); /* MTYP^i */ + ++p_cmap_header_data; + cmap[i].mtyp = (OPJ_BYTE) l_value; - opj_read_bytes(p_cmap_header_data, &l_value, 1); /* PCOL^i */ - ++p_cmap_header_data; - cmap[i].pcol = (OPJ_BYTE) l_value; - } + opj_read_bytes(p_cmap_header_data, &l_value, 1); /* PCOL^i */ + ++p_cmap_header_data; + cmap[i].pcol = (OPJ_BYTE) l_value; + } - jp2->color.jp2_pclr->cmap = cmap; + jp2->color.jp2_pclr->cmap = cmap; - return OPJ_TRUE; + return OPJ_TRUE; } -static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, opj_event_mgr_t *manager) +static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, + opj_event_mgr_t *manager) { - opj_jp2_cdef_info_t *info; - OPJ_UINT16 i, n, cn, asoc, acn; - - info = color->jp2_cdef->info; - n = color->jp2_cdef->n; - - for(i = 0; i < n; ++i) - { - /* WATCH: acn = asoc - 1 ! */ - asoc = info[i].asoc; - cn = info[i].cn; - - if( cn >= image->numcomps) - { - opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: cn=%d, numcomps=%d\n", cn, image->numcomps); - continue; - } - if(asoc == 0 || asoc == 65535) - { - image->comps[cn].alpha = info[i].typ; - continue; - } - - acn = (OPJ_UINT16)(asoc - 1); - if( acn >= image->numcomps ) - { - opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: acn=%d, numcomps=%d\n", acn, image->numcomps); - continue; - } - - /* Swap only if color channel */ - if((cn != acn) && (info[i].typ == 0)) - { - opj_image_comp_t saved; - OPJ_UINT16 j; - - memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); - memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); - memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); - - /* Swap channels in following channel definitions, don't bother with j <= i that are already processed */ - for (j = (OPJ_UINT16)(i + 1U); j < n ; ++j) - { - if (info[j].cn == cn) { - info[j].cn = acn; - } - else if (info[j].cn == acn) { - info[j].cn = cn; - } - /* asoc is related to color index. Do not update. */ - } - } - - image->comps[cn].alpha = info[i].typ; - } - - if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); - - opj_free(color->jp2_cdef); color->jp2_cdef = NULL; - -}/* jp2_apply_cdef() */ + opj_jp2_cdef_info_t *info; + OPJ_UINT16 i, n, cn, asoc, acn; -static OPJ_BOOL opj_jp2_read_cdef( opj_jp2_t * jp2, - OPJ_BYTE * p_cdef_header_data, - OPJ_UINT32 p_cdef_header_size, - opj_event_mgr_t * p_manager - ) -{ - opj_jp2_cdef_info_t *cdef_info; - OPJ_UINT16 i; - OPJ_UINT32 l_value; - - /* preconditions */ - assert(jp2 != 00); - assert(p_cdef_header_data != 00); - assert(p_manager != 00); - (void)p_cdef_header_size; + info = color->jp2_cdef->info; + n = color->jp2_cdef->n; - /* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box - * inside a JP2 Header box.'*/ - if(jp2->color.jp2_cdef) return OPJ_FALSE; - - if (p_cdef_header_size < 2) { - opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_cdef_header_data,&l_value ,2); /* N */ - p_cdef_header_data+= 2; - - if ( (OPJ_UINT16)l_value == 0){ /* szukw000: FIXME */ - opj_event_msg(p_manager, EVT_ERROR, "Number of channel description is equal to zero in CDEF box.\n"); - return OPJ_FALSE; - } - - if (p_cdef_header_size < 2 + (OPJ_UINT32)(OPJ_UINT16)l_value * 6) { - opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n"); - return OPJ_FALSE; - } - - cdef_info = (opj_jp2_cdef_info_t*) opj_malloc(l_value * sizeof(opj_jp2_cdef_info_t)); - if (!cdef_info) - return OPJ_FALSE; - - jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); - if(!jp2->color.jp2_cdef) - { - opj_free(cdef_info); - return OPJ_FALSE; - } - jp2->color.jp2_cdef->info = cdef_info; - jp2->color.jp2_cdef->n = (OPJ_UINT16) l_value; - - for(i = 0; i < jp2->color.jp2_cdef->n; ++i) { - opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Cn^i */ - p_cdef_header_data +=2; - cdef_info[i].cn = (OPJ_UINT16) l_value; - - opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Typ^i */ - p_cdef_header_data +=2; - cdef_info[i].typ = (OPJ_UINT16) l_value; - - opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Asoc^i */ - p_cdef_header_data +=2; - cdef_info[i].asoc = (OPJ_UINT16) l_value; - } - - return OPJ_TRUE; -} + for (i = 0; i < n; ++i) { + /* WATCH: acn = asoc - 1 ! */ + asoc = info[i].asoc; + cn = info[i].cn; -static OPJ_BOOL opj_jp2_read_colr( opj_jp2_t *jp2, - OPJ_BYTE * p_colr_header_data, - OPJ_UINT32 p_colr_header_size, - opj_event_mgr_t * p_manager - ) -{ - OPJ_UINT32 l_value; - - /* preconditions */ - assert(jp2 != 00); - assert(p_colr_header_data != 00); - assert(p_manager != 00); - - if (p_colr_header_size < 3) { - opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size)\n"); - return OPJ_FALSE; - } - - /* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour - * Specification boxes after the first.' - */ - if(jp2->color.jp2_has_colr) { - opj_event_msg(p_manager, EVT_INFO, "A conforming JP2 reader shall ignore all Colour Specification boxes after the first, so we ignore this one.\n"); - p_colr_header_data += p_colr_header_size; - return OPJ_TRUE; - } - - opj_read_bytes(p_colr_header_data,&jp2->meth ,1); /* METH */ - ++p_colr_header_data; - - opj_read_bytes(p_colr_header_data,&jp2->precedence ,1); /* PRECEDENCE */ - ++p_colr_header_data; - - opj_read_bytes(p_colr_header_data,&jp2->approx ,1); /* APPROX */ - ++p_colr_header_data; - - if (jp2->meth == 1) { - if (p_colr_header_size < 7) { - opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size: %d)\n", p_colr_header_size); - return OPJ_FALSE; - } - if ((p_colr_header_size > 7) && (jp2->enumcs != 14)) { /* handled below for CIELab) */ - /* testcase Altona_Technical_v20_x4.pdf */ - opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (bad size: %d)\n", p_colr_header_size); - } - - opj_read_bytes(p_colr_header_data,&jp2->enumcs ,4); /* EnumCS */ - - p_colr_header_data += 4; - - if(jp2->enumcs == 14)/* CIELab */ - { - OPJ_UINT32 *cielab; - OPJ_UINT32 rl, ol, ra, oa, rb, ob, il; - - cielab = (OPJ_UINT32*)opj_malloc(9 * sizeof(OPJ_UINT32)); - cielab[0] = 14; /* enumcs */ - - /* default values */ - rl = ra = rb = ol = oa = ob = 0; - il = 0x00443530; /* D50 */ - cielab[1] = 0x44454600;/* DEF */ - - if(p_colr_header_size == 35) - { - opj_read_bytes(p_colr_header_data, &rl, 4); - p_colr_header_data += 4; - opj_read_bytes(p_colr_header_data, &ol, 4); - p_colr_header_data += 4; - opj_read_bytes(p_colr_header_data, &ra, 4); - p_colr_header_data += 4; - opj_read_bytes(p_colr_header_data, &oa, 4); - p_colr_header_data += 4; - opj_read_bytes(p_colr_header_data, &rb, 4); - p_colr_header_data += 4; - opj_read_bytes(p_colr_header_data, &ob, 4); - p_colr_header_data += 4; - opj_read_bytes(p_colr_header_data, &il, 4); - p_colr_header_data += 4; - - cielab[1] = 0; - } - else if(p_colr_header_size != 7) - { - opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (CIELab, bad size: %d)\n", p_colr_header_size); - } - cielab[2] = rl; cielab[4] = ra; cielab[6] = rb; - cielab[3] = ol; cielab[5] = oa; cielab[7] = ob; - cielab[8] = il; - - jp2->color.icc_profile_buf = (OPJ_BYTE*)cielab; - jp2->color.icc_profile_len = 0; - } - jp2->color.jp2_has_colr = 1; - } - else if (jp2->meth == 2) { - /* ICC profile */ - OPJ_INT32 it_icc_value = 0; - OPJ_INT32 icc_len = (OPJ_INT32)p_colr_header_size - 3; - - jp2->color.icc_profile_len = (OPJ_UINT32)icc_len; - jp2->color.icc_profile_buf = (OPJ_BYTE*) opj_calloc(1,(size_t)icc_len); - if (!jp2->color.icc_profile_buf) - { - jp2->color.icc_profile_len = 0; - return OPJ_FALSE; - } - - for (it_icc_value = 0; it_icc_value < icc_len; ++it_icc_value) - { - opj_read_bytes(p_colr_header_data,&l_value,1); /* icc values */ - ++p_colr_header_data; - jp2->color.icc_profile_buf[it_icc_value] = (OPJ_BYTE) l_value; - } - - jp2->color.jp2_has_colr = 1; - } - else if (jp2->meth > 2) - { - /* ISO/IEC 15444-1:2004 (E), Table I.9 Legal METH values: - conforming JP2 reader shall ignore the entire Colour Specification box.*/ - opj_event_msg(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), " - "so we will ignore the entire Colour Specification box. \n", jp2->meth); - } - return OPJ_TRUE; -} + if (cn >= image->numcomps) { + opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: cn=%d, numcomps=%d\n", + cn, image->numcomps); + continue; + } + if (asoc == 0 || asoc == 65535) { + image->comps[cn].alpha = info[i].typ; + continue; + } -OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, - opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager) -{ - if (!p_image) - return OPJ_FALSE; - - /* J2K decoding */ - if( ! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager) ) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n"); - return OPJ_FALSE; - } - - if (!jp2->ignore_pclr_cmap_cdef){ - if (!opj_jp2_check_color(p_image, &(jp2->color), p_manager)) { - return OPJ_FALSE; - } - - /* Set Image Color Space */ - if (jp2->enumcs == 16) - p_image->color_space = OPJ_CLRSPC_SRGB; - else if (jp2->enumcs == 17) - p_image->color_space = OPJ_CLRSPC_GRAY; - else if (jp2->enumcs == 18) - p_image->color_space = OPJ_CLRSPC_SYCC; - else if (jp2->enumcs == 24) - p_image->color_space = OPJ_CLRSPC_EYCC; - else if (jp2->enumcs == 12) - p_image->color_space = OPJ_CLRSPC_CMYK; - else - p_image->color_space = OPJ_CLRSPC_UNKNOWN; - - if(jp2->color.jp2_pclr) { - /* Part 1, I.5.3.4: Either both or none : */ - if( !jp2->color.jp2_pclr->cmap) - opj_jp2_free_pclr(&(jp2->color)); - else if (p_image->pdfium_use_colorspace) - opj_jp2_apply_pclr(p_image, &(jp2->color)); - } - - /* Apply the color space if needed */ - if(jp2->color.jp2_cdef) { - opj_jp2_apply_cdef(p_image, &(jp2->color), p_manager); - } - - if(jp2->color.icc_profile_buf) { - p_image->icc_profile_buf = jp2->color.icc_profile_buf; - p_image->icc_profile_len = jp2->color.icc_profile_len; - jp2->color.icc_profile_buf = NULL; - } - } - - return OPJ_TRUE; -} + acn = (OPJ_UINT16)(asoc - 1); + if (acn >= image->numcomps) { + opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: acn=%d, numcomps=%d\n", + acn, image->numcomps); + continue; + } -static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager - ) -{ - opj_jp2_img_header_writer_handler_t l_writers [4]; - opj_jp2_img_header_writer_handler_t * l_current_writer; - - OPJ_INT32 i, l_nb_pass; - /* size of data for super box*/ - OPJ_UINT32 l_jp2h_size = 8; - OPJ_BOOL l_result = OPJ_TRUE; - - /* to store the data of the super box */ - OPJ_BYTE l_jp2h_data [8]; - - /* preconditions */ - assert(stream != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - memset(l_writers,0,sizeof(l_writers)); - - if (jp2->bpc == 255) { - l_nb_pass = 3; - l_writers[0].handler = opj_jp2_write_ihdr; - l_writers[1].handler = opj_jp2_write_bpcc; - l_writers[2].handler = opj_jp2_write_colr; - } - else { - l_nb_pass = 2; - l_writers[0].handler = opj_jp2_write_ihdr; - l_writers[1].handler = opj_jp2_write_colr; - } - - if (jp2->color.jp2_cdef != NULL) { - l_writers[l_nb_pass].handler = opj_jp2_write_cdef; - l_nb_pass++; - } - - /* write box header */ - /* write JP2H type */ - opj_write_bytes(l_jp2h_data+4,JP2_JP2H,4); - - l_current_writer = l_writers; - for (i=0;i<l_nb_pass;++i) { - l_current_writer->m_data = l_current_writer->handler(jp2,&(l_current_writer->m_size)); - if (l_current_writer->m_data == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to hold JP2 Header data\n"); - l_result = OPJ_FALSE; - break; - } - - l_jp2h_size += l_current_writer->m_size; - ++l_current_writer; - } - - if (! l_result) { - l_current_writer = l_writers; - for (i=0;i<l_nb_pass;++i) { - if (l_current_writer->m_data != 00) { - opj_free(l_current_writer->m_data ); - } - ++l_current_writer; - } - - return OPJ_FALSE; - } - - /* write super box size */ - opj_write_bytes(l_jp2h_data,l_jp2h_size,4); - - /* write super box data on stream */ - if (opj_stream_write_data(stream,l_jp2h_data,8,p_manager) != 8) { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while writing JP2 Header box\n"); - l_result = OPJ_FALSE; - } - - if (l_result) { - l_current_writer = l_writers; - for (i=0;i<l_nb_pass;++i) { - if (opj_stream_write_data(stream,l_current_writer->m_data,l_current_writer->m_size,p_manager) != l_current_writer->m_size) { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while writing JP2 Header box\n"); - l_result = OPJ_FALSE; - break; - } - ++l_current_writer; - } - } - - l_current_writer = l_writers; - - /* cleanup */ - for (i=0;i<l_nb_pass;++i) { - if (l_current_writer->m_data != 00) { - opj_free(l_current_writer->m_data ); - } - ++l_current_writer; - } - - return l_result; -} + /* Swap only if color channel */ + if ((cn != acn) && (info[i].typ == 0)) { + opj_image_comp_t saved; + OPJ_UINT16 j; + + memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); + + /* Swap channels in following channel definitions, don't bother with j <= i that are already processed */ + for (j = (OPJ_UINT16)(i + 1U); j < n ; ++j) { + if (info[j].cn == cn) { + info[j].cn = acn; + } else if (info[j].cn == acn) { + info[j].cn = cn; + } + /* asoc is related to color index. Do not update. */ + } + } -static OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) -{ - OPJ_UINT32 i; - OPJ_UINT32 l_ftyp_size = 16 + 4 * jp2->numcl; - OPJ_BYTE * l_ftyp_data, * l_current_data_ptr; - OPJ_BOOL l_result; - - /* preconditions */ - assert(cio != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - l_ftyp_data = (OPJ_BYTE *) opj_calloc(1,l_ftyp_size); - - if (l_ftyp_data == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle ftyp data\n"); - return OPJ_FALSE; - } - - l_current_data_ptr = l_ftyp_data; - - opj_write_bytes(l_current_data_ptr, l_ftyp_size,4); /* box size */ - l_current_data_ptr += 4; - - opj_write_bytes(l_current_data_ptr, JP2_FTYP,4); /* FTYP */ - l_current_data_ptr += 4; - - opj_write_bytes(l_current_data_ptr, jp2->brand,4); /* BR */ - l_current_data_ptr += 4; - - opj_write_bytes(l_current_data_ptr, jp2->minversion,4); /* MinV */ - l_current_data_ptr += 4; - - for (i = 0; i < jp2->numcl; i++) { - opj_write_bytes(l_current_data_ptr, jp2->cl[i],4); /* CL */ - } - - l_result = (opj_stream_write_data(cio,l_ftyp_data,l_ftyp_size,p_manager) == l_ftyp_size); - if (! l_result) - { - opj_event_msg(p_manager, EVT_ERROR, "Error while writing ftyp data to stream\n"); - } - - opj_free(l_ftyp_data); - - return l_result; -} + image->comps[cn].alpha = info[i].typ; + } -static OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) -{ - OPJ_OFF_T j2k_codestream_exit; - OPJ_BYTE l_data_header [8]; - - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - assert(opj_stream_has_seek(cio)); - - j2k_codestream_exit = opj_stream_tell(cio); - opj_write_bytes(l_data_header, - (OPJ_UINT32) (j2k_codestream_exit - jp2->j2k_codestream_offset), - 4); /* size of codestream */ - opj_write_bytes(l_data_header + 4,JP2_JP2C,4); /* JP2C */ - - if (! opj_stream_seek(cio,jp2->j2k_codestream_offset,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } - - if (opj_stream_write_data(cio,l_data_header,8,p_manager) != 8) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } - - if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } - - return OPJ_TRUE; -} + if (color->jp2_cdef->info) { + opj_free(color->jp2_cdef->info); + } -static OPJ_BOOL opj_jp2_write_jp( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) -{ - /* 12 bytes will be read */ - OPJ_BYTE l_signature_data [12]; - - /* preconditions */ - assert(cio != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - /* write box length */ - opj_write_bytes(l_signature_data,12,4); - /* writes box type */ - opj_write_bytes(l_signature_data+4,JP2_JP,4); - /* writes magic number*/ - opj_write_bytes(l_signature_data+8,0x0d0a870a,4); - - if (opj_stream_write_data(cio,l_signature_data,12,p_manager) != 12) { - return OPJ_FALSE; - } - - return OPJ_TRUE; -} + opj_free(color->jp2_cdef); + color->jp2_cdef = NULL; -/* ----------------------------------------------------------------------- */ -/* JP2 decoder interface */ -/* ----------------------------------------------------------------------- */ +}/* jp2_apply_cdef() */ -void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) +static OPJ_BOOL opj_jp2_read_cdef(opj_jp2_t * jp2, + OPJ_BYTE * p_cdef_header_data, + OPJ_UINT32 p_cdef_header_size, + opj_event_mgr_t * p_manager + ) { - /* setup the J2K codec */ - opj_j2k_setup_decoder(jp2->j2k, parameters); + opj_jp2_cdef_info_t *cdef_info; + OPJ_UINT16 i; + OPJ_UINT32 l_value; + + /* preconditions */ + assert(jp2 != 00); + assert(p_cdef_header_data != 00); + assert(p_manager != 00); + (void)p_cdef_header_size; - /* further JP2 initializations go here */ - jp2->color.jp2_has_colr = 0; - jp2->comps = NULL; - jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; -} + /* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box + * inside a JP2 Header box.'*/ + if (jp2->color.jp2_cdef) { + return OPJ_FALSE; + } -/* ----------------------------------------------------------------------- */ -/* JP2 encoder interface */ -/* ----------------------------------------------------------------------- */ + if (p_cdef_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n"); + return OPJ_FALSE; + } -OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2, - opj_cparameters_t *parameters, - opj_image_t *image, - opj_event_mgr_t * p_manager) -{ - OPJ_UINT32 i; - OPJ_UINT32 depth_0; - OPJ_UINT32 sign; - OPJ_UINT32 alpha_count; - OPJ_UINT32 color_channels = 0U; - OPJ_UINT32 alpha_channel = 0U; - - - if(!jp2 || !parameters || !image) - return OPJ_FALSE; - - /* setup the J2K codec */ - /* ------------------- */ - - /* Check if number of components respects standard */ - if (image->numcomps < 1 || image->numcomps > 16384) { - opj_event_msg(p_manager, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n"); - return OPJ_FALSE; - } - - if (opj_j2k_setup_encoder(jp2->j2k, parameters, image, p_manager ) == OPJ_FALSE) { - return OPJ_FALSE; - } - - /* setup the JP2 codec */ - /* ------------------- */ - - /* Profile box */ - - jp2->brand = JP2_JP2; /* BR */ - jp2->minversion = 0; /* MinV */ - jp2->numcl = 1; - jp2->cl = (OPJ_UINT32*) opj_malloc(jp2->numcl * sizeof(OPJ_UINT32)); - if (!jp2->cl){ - jp2->cl = NULL; - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory when setup the JP2 encoder\n"); - return OPJ_FALSE; - } - jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ - - /* Image Header box */ - - jp2->numcomps = image->numcomps; /* NC */ - jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); - if (!jp2->comps) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory when setup the JP2 encoder\n"); - /* Memory of jp2->cl will be freed by opj_jp2_destroy */ - return OPJ_FALSE; - } - - jp2->h = image->y1 - image->y0; /* HEIGHT */ - jp2->w = image->x1 - image->x0; /* WIDTH */ - /* BPC */ - depth_0 = image->comps[0].prec - 1; - sign = image->comps[0].sgnd; - jp2->bpc = depth_0 + (sign << 7); - for (i = 1; i < image->numcomps; i++) { - OPJ_UINT32 depth = image->comps[i].prec - 1; - sign = image->comps[i].sgnd; - if (depth_0 != depth) - jp2->bpc = 255; - } - jp2->C = 7; /* C : Always 7 */ - jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ - jp2->IPR = 0; /* IPR, no intellectual property */ - - /* BitsPerComponent box */ - for (i = 0; i < image->numcomps; i++) { - jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); - } - - /* Colour Specification box */ - if(image->icc_profile_len) { - jp2->meth = 2; - jp2->enumcs = 0; - } - else { - jp2->meth = 1; - if (image->color_space == 1) - jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */ - else if (image->color_space == 2) - jp2->enumcs = 17; /* greyscale */ - else if (image->color_space == 3) - jp2->enumcs = 18; /* YUV */ - } - - /* Channel Definition box */ - /* FIXME not provided by parameters */ - /* We try to do what we can... */ - alpha_count = 0U; - for (i = 0; i < image->numcomps; i++) { - if (image->comps[i].alpha != 0) { - alpha_count++; - alpha_channel = i; - } - } - if (alpha_count == 1U) { /* no way to deal with more than 1 alpha channel */ - switch (jp2->enumcs) { - case 16: - case 18: - color_channels = 3; - break; - case 17: - color_channels = 1; - break; - default: - alpha_count = 0U; - break; - } - if (alpha_count == 0U) { - opj_event_msg(p_manager, EVT_WARNING, "Alpha channel specified but unknown enumcs. No cdef box will be created.\n"); - } else if (image->numcomps < (color_channels+1)) { - opj_event_msg(p_manager, EVT_WARNING, "Alpha channel specified but not enough image components for an automatic cdef box creation.\n"); - alpha_count = 0U; - } else if ((OPJ_UINT32)alpha_channel < color_channels) { - opj_event_msg(p_manager, EVT_WARNING, "Alpha channel position conflicts with color channel. No cdef box will be created.\n"); - alpha_count = 0U; - } - } else if (alpha_count > 1) { - opj_event_msg(p_manager, EVT_WARNING, "Multiple alpha channels specified. No cdef box will be created.\n"); - } - if (alpha_count == 1U) { /* if here, we know what we can do */ - jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); - if(!jp2->color.jp2_cdef) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup the JP2 encoder\n"); - return OPJ_FALSE; - } - /* no memset needed, all values will be overwritten except if jp2->color.jp2_cdef->info allocation fails, */ - /* in which case jp2->color.jp2_cdef->info will be NULL => valid for destruction */ - jp2->color.jp2_cdef->info = (opj_jp2_cdef_info_t*) opj_malloc(image->numcomps * sizeof(opj_jp2_cdef_info_t)); - if (!jp2->color.jp2_cdef->info) { - /* memory will be freed by opj_jp2_destroy */ - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup the JP2 encoder\n"); - return OPJ_FALSE; - } - jp2->color.jp2_cdef->n = (OPJ_UINT16) image->numcomps; /* cast is valid : image->numcomps [1,16384] */ - for (i = 0U; i < color_channels; i++) { - jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16)i; /* cast is valid : image->numcomps [1,16384] */ - jp2->color.jp2_cdef->info[i].typ = 0U; - jp2->color.jp2_cdef->info[i].asoc = (OPJ_UINT16)(i+1U); /* No overflow + cast is valid : image->numcomps [1,16384] */ - } - for (; i < image->numcomps; i++) { - if (image->comps[i].alpha != 0) { /* we'll be here exactly once */ - jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16)i; /* cast is valid : image->numcomps [1,16384] */ - jp2->color.jp2_cdef->info[i].typ = 1U; /* Opacity channel */ - jp2->color.jp2_cdef->info[i].asoc = 0U; /* Apply alpha channel to the whole image */ - } else { - /* Unknown channel */ - jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16)i; /* cast is valid : image->numcomps [1,16384] */ - jp2->color.jp2_cdef->info[i].typ = 65535U; - jp2->color.jp2_cdef->info[i].asoc = 65535U; - } - } - } - - jp2->precedence = 0; /* PRECEDENCE */ - jp2->approx = 0; /* APPROX */ - - jp2->jpip_on = parameters->jpip_on; - - return OPJ_TRUE; + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* N */ + p_cdef_header_data += 2; + + if ((OPJ_UINT16)l_value == 0) { /* szukw000: FIXME */ + opj_event_msg(p_manager, EVT_ERROR, + "Number of channel description is equal to zero in CDEF box.\n"); + return OPJ_FALSE; + } + + if (p_cdef_header_size < 2 + (OPJ_UINT32)(OPJ_UINT16)l_value * 6) { + opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n"); + return OPJ_FALSE; + } + + cdef_info = (opj_jp2_cdef_info_t*) opj_malloc(l_value * sizeof( + opj_jp2_cdef_info_t)); + if (!cdef_info) { + return OPJ_FALSE; + } + + jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); + if (!jp2->color.jp2_cdef) { + opj_free(cdef_info); + return OPJ_FALSE; + } + jp2->color.jp2_cdef->info = cdef_info; + jp2->color.jp2_cdef->n = (OPJ_UINT16) l_value; + + for (i = 0; i < jp2->color.jp2_cdef->n; ++i) { + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Cn^i */ + p_cdef_header_data += 2; + cdef_info[i].cn = (OPJ_UINT16) l_value; + + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Typ^i */ + p_cdef_header_data += 2; + cdef_info[i].typ = (OPJ_UINT16) l_value; + + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Asoc^i */ + p_cdef_header_data += 2; + cdef_info[i].asoc = (OPJ_UINT16) l_value; + } + + return OPJ_TRUE; } -OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2, + OPJ_BYTE * p_colr_header_data, + OPJ_UINT32 p_colr_header_size, + opj_event_mgr_t * p_manager + ) { - return opj_j2k_encode(jp2->j2k, stream, p_manager); + OPJ_UINT32 l_value; + + /* preconditions */ + assert(jp2 != 00); + assert(p_colr_header_data != 00); + assert(p_manager != 00); + + if (p_colr_header_size < 3) { + opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size)\n"); + return OPJ_FALSE; + } + + /* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour + * Specification boxes after the first.' + */ + if (jp2->color.jp2_has_colr) { + opj_event_msg(p_manager, EVT_INFO, + "A conforming JP2 reader shall ignore all Colour Specification boxes after the first, so we ignore this one.\n"); + p_colr_header_data += p_colr_header_size; + return OPJ_TRUE; + } + + opj_read_bytes(p_colr_header_data, &jp2->meth, 1); /* METH */ + ++p_colr_header_data; + + opj_read_bytes(p_colr_header_data, &jp2->precedence, 1); /* PRECEDENCE */ + ++p_colr_header_data; + + opj_read_bytes(p_colr_header_data, &jp2->approx, 1); /* APPROX */ + ++p_colr_header_data; + + if (jp2->meth == 1) { + if (p_colr_header_size < 7) { + opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size: %d)\n", + p_colr_header_size); + return OPJ_FALSE; + } + if ((p_colr_header_size > 7) && + (jp2->enumcs != 14)) { /* handled below for CIELab) */ + /* testcase Altona_Technical_v20_x4.pdf */ + opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (bad size: %d)\n", + p_colr_header_size); + } + + opj_read_bytes(p_colr_header_data, &jp2->enumcs, 4); /* EnumCS */ + + p_colr_header_data += 4; + + if (jp2->enumcs == 14) { /* CIELab */ + OPJ_UINT32 *cielab; + OPJ_UINT32 rl, ol, ra, oa, rb, ob, il; + + cielab = (OPJ_UINT32*)opj_malloc(9 * sizeof(OPJ_UINT32)); + if (cielab == NULL) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for cielab\n"); + return OPJ_FALSE; + } + cielab[0] = 14; /* enumcs */ + + /* default values */ + rl = ra = rb = ol = oa = ob = 0; + il = 0x00443530; /* D50 */ + cielab[1] = 0x44454600;/* DEF */ + + if (p_colr_header_size == 35) { + opj_read_bytes(p_colr_header_data, &rl, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &ol, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &ra, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &oa, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &rb, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &ob, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &il, 4); + p_colr_header_data += 4; + + cielab[1] = 0; + } else if (p_colr_header_size != 7) { + opj_event_msg(p_manager, EVT_WARNING, + "Bad COLR header box (CIELab, bad size: %d)\n", p_colr_header_size); + } + cielab[2] = rl; + cielab[4] = ra; + cielab[6] = rb; + cielab[3] = ol; + cielab[5] = oa; + cielab[7] = ob; + cielab[8] = il; + + jp2->color.icc_profile_buf = (OPJ_BYTE*)cielab; + jp2->color.icc_profile_len = 0; + } + jp2->color.jp2_has_colr = 1; + } else if (jp2->meth == 2) { + /* ICC profile */ + OPJ_INT32 it_icc_value = 0; + OPJ_INT32 icc_len = (OPJ_INT32)p_colr_header_size - 3; + + jp2->color.icc_profile_len = (OPJ_UINT32)icc_len; + jp2->color.icc_profile_buf = (OPJ_BYTE*) opj_calloc(1, (size_t)icc_len); + if (!jp2->color.icc_profile_buf) { + jp2->color.icc_profile_len = 0; + return OPJ_FALSE; + } + + for (it_icc_value = 0; it_icc_value < icc_len; ++it_icc_value) { + opj_read_bytes(p_colr_header_data, &l_value, 1); /* icc values */ + ++p_colr_header_data; + jp2->color.icc_profile_buf[it_icc_value] = (OPJ_BYTE) l_value; + } + + jp2->color.jp2_has_colr = 1; + } else if (jp2->meth > 2) { + /* ISO/IEC 15444-1:2004 (E), Table I.9 Legal METH values: + conforming JP2 reader shall ignore the entire Colour Specification box.*/ + opj_event_msg(p_manager, EVT_INFO, + "COLR BOX meth value is not a regular value (%d), " + "so we will ignore the entire Colour Specification box. \n", jp2->meth); + } + if (jp2->color.jp2_has_colr) { + jp2->j2k->enumcs = jp2->enumcs; + } + return OPJ_TRUE; } -OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) +OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - - /* customization of the end encoding */ - if (! opj_jp2_setup_end_header_reading(jp2, p_manager)) { - return OPJ_FALSE; - } - - /* write header */ - if (! opj_jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) { - return OPJ_FALSE; - } - - return opj_j2k_end_decompress(jp2->j2k, cio, p_manager); + if (!p_image) { + return OPJ_FALSE; + } + + /* J2K decoding */ + if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Failed to decode the codestream in the JP2 file\n"); + return OPJ_FALSE; + } + + if (jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) { + /* Bypass all JP2 component transforms */ + return OPJ_TRUE; + } + + if (!jp2->ignore_pclr_cmap_cdef) { + if (!opj_jp2_check_color(p_image, &(jp2->color), p_manager)) { + return OPJ_FALSE; + } + + /* Set Image Color Space */ + if (jp2->enumcs == 16) { + p_image->color_space = OPJ_CLRSPC_SRGB; + } else if (jp2->enumcs == 17) { + p_image->color_space = OPJ_CLRSPC_GRAY; + } else if (jp2->enumcs == 18) { + p_image->color_space = OPJ_CLRSPC_SYCC; + } else if (jp2->enumcs == 24) { + p_image->color_space = OPJ_CLRSPC_EYCC; + } else if (jp2->enumcs == 12) { + p_image->color_space = OPJ_CLRSPC_CMYK; + } else { + p_image->color_space = OPJ_CLRSPC_UNKNOWN; + } + + if (jp2->color.jp2_pclr) { + /* Part 1, I.5.3.4: Either both or none : */ + if (!jp2->color.jp2_pclr->cmap) { + opj_jp2_free_pclr(&(jp2->color)); + } else if (p_image->pdfium_use_colorspace) { + if (!opj_jp2_apply_pclr(p_image, &(jp2->color), p_manager)) { + return OPJ_FALSE; + } + } + } + + /* Apply the color space if needed */ + if (jp2->color.jp2_cdef) { + opj_jp2_apply_cdef(p_image, &(jp2->color), p_manager); + } + + if (jp2->color.icc_profile_buf) { + p_image->icc_profile_buf = jp2->color.icc_profile_buf; + p_image->icc_profile_len = jp2->color.icc_profile_len; + jp2->color.icc_profile_buf = NULL; + } + } + + return OPJ_TRUE; } -OPJ_BOOL opj_jp2_end_compress( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_img_header_writer_handler_t l_writers [4]; + opj_jp2_img_header_writer_handler_t * l_current_writer; + + OPJ_INT32 i, l_nb_pass; + /* size of data for super box*/ + OPJ_UINT32 l_jp2h_size = 8; + OPJ_BOOL l_result = OPJ_TRUE; + + /* to store the data of the super box */ + OPJ_BYTE l_jp2h_data [8]; + + /* preconditions */ + assert(stream != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + memset(l_writers, 0, sizeof(l_writers)); + + if (jp2->bpc == 255) { + l_nb_pass = 3; + l_writers[0].handler = opj_jp2_write_ihdr; + l_writers[1].handler = opj_jp2_write_bpcc; + l_writers[2].handler = opj_jp2_write_colr; + } else { + l_nb_pass = 2; + l_writers[0].handler = opj_jp2_write_ihdr; + l_writers[1].handler = opj_jp2_write_colr; + } + + if (jp2->color.jp2_cdef != NULL) { + l_writers[l_nb_pass].handler = opj_jp2_write_cdef; + l_nb_pass++; + } + + /* write box header */ + /* write JP2H type */ + opj_write_bytes(l_jp2h_data + 4, JP2_JP2H, 4); + + l_current_writer = l_writers; + for (i = 0; i < l_nb_pass; ++i) { + l_current_writer->m_data = l_current_writer->handler(jp2, + &(l_current_writer->m_size)); + if (l_current_writer->m_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to hold JP2 Header data\n"); + l_result = OPJ_FALSE; + break; + } + + l_jp2h_size += l_current_writer->m_size; + ++l_current_writer; + } + + if (! l_result) { + l_current_writer = l_writers; + for (i = 0; i < l_nb_pass; ++i) { + if (l_current_writer->m_data != 00) { + opj_free(l_current_writer->m_data); + } + ++l_current_writer; + } + + return OPJ_FALSE; + } + + /* write super box size */ + opj_write_bytes(l_jp2h_data, l_jp2h_size, 4); + + /* write super box data on stream */ + if (opj_stream_write_data(stream, l_jp2h_data, 8, p_manager) != 8) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while writing JP2 Header box\n"); + l_result = OPJ_FALSE; + } + + if (l_result) { + l_current_writer = l_writers; + for (i = 0; i < l_nb_pass; ++i) { + if (opj_stream_write_data(stream, l_current_writer->m_data, + l_current_writer->m_size, p_manager) != l_current_writer->m_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while writing JP2 Header box\n"); + l_result = OPJ_FALSE; + break; + } + ++l_current_writer; + } + } + + l_current_writer = l_writers; + + /* cleanup */ + for (i = 0; i < l_nb_pass; ++i) { + if (l_current_writer->m_data != 00) { + opj_free(l_current_writer->m_data); + } + ++l_current_writer; + } + + return l_result; +} + +static OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - - /* customization of the end encoding */ - if (! opj_jp2_setup_end_header_writing(jp2, p_manager)) { - return OPJ_FALSE; - } - - if (! opj_j2k_end_compress(jp2->j2k,cio,p_manager)) { - return OPJ_FALSE; - } - - /* write header */ - return opj_jp2_exec(jp2,jp2->m_procedure_list,cio,p_manager); + OPJ_UINT32 i; + OPJ_UINT32 l_ftyp_size; + OPJ_BYTE * l_ftyp_data, * l_current_data_ptr; + OPJ_BOOL l_result; + + /* preconditions */ + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + l_ftyp_size = 16 + 4 * jp2->numcl; + + l_ftyp_data = (OPJ_BYTE *) opj_calloc(1, l_ftyp_size); + + if (l_ftyp_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle ftyp data\n"); + return OPJ_FALSE; + } + + l_current_data_ptr = l_ftyp_data; + + opj_write_bytes(l_current_data_ptr, l_ftyp_size, 4); /* box size */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, JP2_FTYP, 4); /* FTYP */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, jp2->brand, 4); /* BR */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, jp2->minversion, 4); /* MinV */ + l_current_data_ptr += 4; + + for (i = 0; i < jp2->numcl; i++) { + opj_write_bytes(l_current_data_ptr, jp2->cl[i], 4); /* CL */ + } + + l_result = (opj_stream_write_data(cio, l_ftyp_data, l_ftyp_size, + p_manager) == l_ftyp_size); + if (! l_result) { + opj_event_msg(p_manager, EVT_ERROR, + "Error while writing ftyp data to stream\n"); + } + + opj_free(l_ftyp_data); + + return l_result; } -static OPJ_BOOL opj_jp2_setup_end_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(p_manager != 00); + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [8]; + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header, + (OPJ_UINT32)(j2k_codestream_exit - jp2->j2k_codestream_offset), + 4); /* size of codestream */ + opj_write_bytes(l_data_header + 4, JP2_JP2C, + 4); /* JP2C */ -#ifdef USE_JPIP - if( jp2->jpip_on ) { - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_iptr, p_manager)) { - return OPJ_FALSE; - } - } -#endif - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2c, p_manager)) { - return OPJ_FALSE; - } - /* DEVELOPER CORNER, add your custom procedures */ -#ifdef USE_JPIP - if( jp2->jpip_on ) - { - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_cidx, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_write_fidx, p_manager)) { - return OPJ_FALSE; - } - } -#endif - return OPJ_TRUE; + if (! opj_stream_seek(cio, jp2->j2k_codestream_offset, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (opj_stream_write_data(cio, l_data_header, 8, p_manager) != 8) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_setup_end_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(p_manager != 00); - - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure, p_manager)) { - return OPJ_FALSE; - } - /* DEVELOPER CORNER, add your custom procedures */ - - return OPJ_TRUE; + /* 12 bytes will be read */ + OPJ_BYTE l_signature_data [12]; + + /* preconditions */ + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + OPJ_UNUSED(jp2); + + /* write box length */ + opj_write_bytes(l_signature_data, 12, 4); + /* writes box type */ + opj_write_bytes(l_signature_data + 4, JP2_JP, 4); + /* writes magic number*/ + opj_write_bytes(l_signature_data + 8, 0x0d0a870a, 4); + + if (opj_stream_write_data(cio, l_signature_data, 12, p_manager) != 12) { + return OPJ_FALSE; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_default_validation ( opj_jp2_t * jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) +/* ----------------------------------------------------------------------- */ +/* JP2 decoder interface */ +/* ----------------------------------------------------------------------- */ + +void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) +{ + /* setup the J2K codec */ + opj_j2k_setup_decoder(jp2->j2k, parameters); + + /* further JP2 initializations go here */ + jp2->color.jp2_has_colr = 0; + jp2->comps = NULL; + jp2->ignore_pclr_cmap_cdef = parameters->flags & + OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; +} + +OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads) +{ + return opj_j2k_set_threads(jp2->j2k, num_threads); +} + +/* ----------------------------------------------------------------------- */ +/* JP2 encoder interface */ +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i; + OPJ_UINT32 depth_0; + OPJ_UINT32 sign; + OPJ_UINT32 alpha_count; + OPJ_UINT32 color_channels = 0U; + OPJ_UINT32 alpha_channel = 0U; + + + if (!jp2 || !parameters || !image) { + return OPJ_FALSE; + } + + /* setup the J2K codec */ + /* ------------------- */ + + /* Check if number of components respects standard */ + if (image->numcomps < 1 || image->numcomps > 16384) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of components specified while setting up JP2 encoder\n"); + return OPJ_FALSE; + } + + if (opj_j2k_setup_encoder(jp2->j2k, parameters, image, + p_manager) == OPJ_FALSE) { + return OPJ_FALSE; + } + + /* setup the JP2 codec */ + /* ------------------- */ + + /* Profile box */ + + jp2->brand = JP2_JP2; /* BR */ + jp2->minversion = 0; /* MinV */ + jp2->numcl = 1; + jp2->cl = (OPJ_UINT32*) opj_malloc(jp2->numcl * sizeof(OPJ_UINT32)); + if (!jp2->cl) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory when setup the JP2 encoder\n"); + return OPJ_FALSE; + } + jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ + + /* Image Header box */ + + jp2->numcomps = image->numcomps; /* NC */ + jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof( + opj_jp2_comps_t)); + if (!jp2->comps) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory when setup the JP2 encoder\n"); + /* Memory of jp2->cl will be freed by opj_jp2_destroy */ + return OPJ_FALSE; + } + + jp2->h = image->y1 - image->y0; /* HEIGHT */ + jp2->w = image->x1 - image->x0; /* WIDTH */ + /* BPC */ + depth_0 = image->comps[0].prec - 1; + sign = image->comps[0].sgnd; + jp2->bpc = depth_0 + (sign << 7); + for (i = 1; i < image->numcomps; i++) { + OPJ_UINT32 depth = image->comps[i].prec - 1; + sign = image->comps[i].sgnd; + if (depth_0 != depth) { + jp2->bpc = 255; + } + } + jp2->C = 7; /* C : Always 7 */ + jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ + jp2->IPR = 0; /* IPR, no intellectual property */ + + /* BitsPerComponent box */ + for (i = 0; i < image->numcomps; i++) { + jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); + } + + /* Colour Specification box */ + if (image->icc_profile_len) { + jp2->meth = 2; + jp2->enumcs = 0; + } else { + jp2->meth = 1; + if (image->color_space == 1) { + jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */ + } else if (image->color_space == 2) { + jp2->enumcs = 17; /* greyscale */ + } else if (image->color_space == 3) { + jp2->enumcs = 18; /* YUV */ + } + } + + /* Channel Definition box */ + /* FIXME not provided by parameters */ + /* We try to do what we can... */ + alpha_count = 0U; + for (i = 0; i < image->numcomps; i++) { + if (image->comps[i].alpha != 0) { + alpha_count++; + alpha_channel = i; + } + } + if (alpha_count == 1U) { /* no way to deal with more than 1 alpha channel */ + switch (jp2->enumcs) { + case 16: + case 18: + color_channels = 3; + break; + case 17: + color_channels = 1; + break; + default: + alpha_count = 0U; + break; + } + if (alpha_count == 0U) { + opj_event_msg(p_manager, EVT_WARNING, + "Alpha channel specified but unknown enumcs. No cdef box will be created.\n"); + } else if (image->numcomps < (color_channels + 1)) { + opj_event_msg(p_manager, EVT_WARNING, + "Alpha channel specified but not enough image components for an automatic cdef box creation.\n"); + alpha_count = 0U; + } else if ((OPJ_UINT32)alpha_channel < color_channels) { + opj_event_msg(p_manager, EVT_WARNING, + "Alpha channel position conflicts with color channel. No cdef box will be created.\n"); + alpha_count = 0U; + } + } else if (alpha_count > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Multiple alpha channels specified. No cdef box will be created.\n"); + } + if (alpha_count == 1U) { /* if here, we know what we can do */ + jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); + if (!jp2->color.jp2_cdef) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to setup the JP2 encoder\n"); + return OPJ_FALSE; + } + /* no memset needed, all values will be overwritten except if jp2->color.jp2_cdef->info allocation fails, */ + /* in which case jp2->color.jp2_cdef->info will be NULL => valid for destruction */ + jp2->color.jp2_cdef->info = (opj_jp2_cdef_info_t*) opj_malloc( + image->numcomps * sizeof(opj_jp2_cdef_info_t)); + if (!jp2->color.jp2_cdef->info) { + /* memory will be freed by opj_jp2_destroy */ + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to setup the JP2 encoder\n"); + return OPJ_FALSE; + } + jp2->color.jp2_cdef->n = (OPJ_UINT16) + image->numcomps; /* cast is valid : image->numcomps [1,16384] */ + for (i = 0U; i < color_channels; i++) { + jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16) + i; /* cast is valid : image->numcomps [1,16384] */ + jp2->color.jp2_cdef->info[i].typ = 0U; + jp2->color.jp2_cdef->info[i].asoc = (OPJ_UINT16)(i + + 1U); /* No overflow + cast is valid : image->numcomps [1,16384] */ + } + for (; i < image->numcomps; i++) { + if (image->comps[i].alpha != 0) { /* we'll be here exactly once */ + jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16) + i; /* cast is valid : image->numcomps [1,16384] */ + jp2->color.jp2_cdef->info[i].typ = 1U; /* Opacity channel */ + jp2->color.jp2_cdef->info[i].asoc = + 0U; /* Apply alpha channel to the whole image */ + } else { + /* Unknown channel */ + jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16) + i; /* cast is valid : image->numcomps [1,16384] */ + jp2->color.jp2_cdef->info[i].typ = 65535U; + jp2->color.jp2_cdef->info[i].asoc = 65535U; + } + } + } + + jp2->precedence = 0; /* PRECEDENCE */ + jp2->approx = 0; /* APPROX */ + + jp2->jpip_on = parameters->jpip_on; + + return OPJ_TRUE; +} + +OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager) +{ + return opj_j2k_encode(jp2->j2k, stream, p_manager); +} + +OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + /* customization of the end encoding */ + if (! opj_jp2_setup_end_header_reading(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* write header */ + if (! opj_jp2_exec(jp2, jp2->m_procedure_list, cio, p_manager)) { + return OPJ_FALSE; + } + + return opj_j2k_end_decompress(jp2->j2k, cio, p_manager); +} + +OPJ_BOOL opj_jp2_end_compress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) { - OPJ_BOOL l_is_valid = OPJ_TRUE; - OPJ_UINT32 i; + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); + /* customization of the end encoding */ + if (! opj_jp2_setup_end_header_writing(jp2, p_manager)) { + return OPJ_FALSE; + } - /* JPEG2000 codec validation */ + if (! opj_j2k_end_compress(jp2->j2k, cio, p_manager)) { + return OPJ_FALSE; + } - /* STATE checking */ - /* make sure the state is at 0 */ - l_is_valid &= (jp2->jp2_state == JP2_STATE_NONE); + /* write header */ + return opj_jp2_exec(jp2, jp2->m_procedure_list, cio, p_manager); +} - /* make sure not reading a jp2h ???? WEIRD */ - l_is_valid &= (jp2->jp2_img_state == JP2_IMG_STATE_NONE); +static OPJ_BOOL opj_jp2_setup_end_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); - /* POINTER validation */ - /* make sure a j2k codec is present */ - l_is_valid &= (jp2->j2k != 00); +#ifdef USE_JPIP + if (jp2->jpip_on) { + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_write_iptr, p_manager)) { + return OPJ_FALSE; + } + } +#endif + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_jp2c, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ +#ifdef USE_JPIP + if (jp2->jpip_on) { + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_write_cidx, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_write_fidx, p_manager)) { + return OPJ_FALSE; + } + } +#endif + return OPJ_TRUE; +} - /* make sure a procedure list is present */ - l_is_valid &= (jp2->m_procedure_list != 00); +static OPJ_BOOL opj_jp2_setup_end_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); - /* make sure a validation list is present */ - l_is_valid &= (jp2->m_validation_list != 00); + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_read_header_procedure, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ - /* PARAMETER VALIDATION */ - /* number of components */ - l_is_valid &= (jp2->numcl > 0); - /* width */ - l_is_valid &= (jp2->h > 0); - /* height */ - l_is_valid &= (jp2->w > 0); - /* precision */ - for (i = 0; i < jp2->numcomps; ++i) { - l_is_valid &= ((jp2->comps[i].bpcc & 0x7FU) < 38U); /* 0 is valid, ignore sign for check */ - } + return OPJ_TRUE; +} - /* METH */ - l_is_valid &= ((jp2->meth > 0) && (jp2->meth < 3)); +static OPJ_BOOL opj_jp2_default_validation(opj_jp2_t * jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + OPJ_BOOL l_is_valid = OPJ_TRUE; + OPJ_UINT32 i; + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_manager); + + /* JPEG2000 codec validation */ + + /* STATE checking */ + /* make sure the state is at 0 */ + l_is_valid &= (jp2->jp2_state == JP2_STATE_NONE); + + /* make sure not reading a jp2h ???? WEIRD */ + l_is_valid &= (jp2->jp2_img_state == JP2_IMG_STATE_NONE); + + /* POINTER validation */ + /* make sure a j2k codec is present */ + l_is_valid &= (jp2->j2k != 00); + + /* make sure a procedure list is present */ + l_is_valid &= (jp2->m_procedure_list != 00); + + /* make sure a validation list is present */ + l_is_valid &= (jp2->m_validation_list != 00); + + /* PARAMETER VALIDATION */ + /* number of components */ + l_is_valid &= (jp2->numcl > 0); + /* width */ + l_is_valid &= (jp2->h > 0); + /* height */ + l_is_valid &= (jp2->w > 0); + /* precision */ + for (i = 0; i < jp2->numcomps; ++i) { + l_is_valid &= ((jp2->comps[i].bpcc & 0x7FU) < + 38U); /* 0 is valid, ignore sign for check */ + } - /* stream validation */ - /* back and forth is needed */ - l_is_valid &= opj_stream_has_seek(cio); + /* METH */ + l_is_valid &= ((jp2->meth > 0) && (jp2->meth < 3)); - return l_is_valid; + /* stream validation */ + /* back and forth is needed */ + l_is_valid &= opj_stream_has_seek(cio); + + return l_is_valid; } -static OPJ_BOOL opj_jp2_read_header_procedure( opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_header_procedure(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager + ) { - opj_jp2_box_t box; - OPJ_UINT32 l_nb_bytes_read; - const opj_jp2_header_handler_t * l_current_handler; - const opj_jp2_header_handler_t * l_current_handler_misplaced; - OPJ_UINT32 l_last_data_size = OPJ_BOX_SIZE; - OPJ_UINT32 l_current_data_size; - OPJ_BYTE * l_current_data = 00; - - /* preconditions */ - assert(stream != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - l_current_data = (OPJ_BYTE*)opj_calloc(1,l_last_data_size); - - if (l_current_data == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle jpeg2000 file header\n"); - return OPJ_FALSE; - } - - while (opj_jp2_read_boxhdr(&box,&l_nb_bytes_read,stream,p_manager)) { - /* is it the codestream box ? */ - if (box.type == JP2_JP2C) { - if (jp2->jp2_state & JP2_STATE_HEADER) { - jp2->jp2_state |= JP2_STATE_CODESTREAM; - opj_free(l_current_data); - return OPJ_TRUE; - } - else { - opj_event_msg(p_manager, EVT_ERROR, "bad placed jpeg codestream\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - } - else if (box.length == 0) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - /* testcase 1851.pdf.SIGSEGV.ce9.948 */ + opj_jp2_box_t box; + OPJ_UINT32 l_nb_bytes_read; + const opj_jp2_header_handler_t * l_current_handler; + const opj_jp2_header_handler_t * l_current_handler_misplaced; + OPJ_UINT32 l_last_data_size = OPJ_BOX_SIZE; + OPJ_UINT32 l_current_data_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(stream != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + l_current_data = (OPJ_BYTE*)opj_calloc(1, l_last_data_size); + + if (l_current_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to handle jpeg2000 file header\n"); + return OPJ_FALSE; + } + + while (opj_jp2_read_boxhdr(&box, &l_nb_bytes_read, stream, p_manager)) { + /* is it the codestream box ? */ + if (box.type == JP2_JP2C) { + if (jp2->jp2_state & JP2_STATE_HEADER) { + jp2->jp2_state |= JP2_STATE_CODESTREAM; + opj_free(l_current_data); + return OPJ_TRUE; + } else { + opj_event_msg(p_manager, EVT_ERROR, "bad placed jpeg codestream\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + } else if (box.length == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + /* testcase 1851.pdf.SIGSEGV.ce9.948 */ else if (box.length < l_nb_bytes_read) { - opj_event_msg(p_manager, EVT_ERROR, "invalid box size %d (%x)\n", box.length, box.type); - opj_free(l_current_data); - return OPJ_FALSE; - } - - l_current_handler = opj_jp2_find_handler(box.type); - l_current_handler_misplaced = opj_jp2_img_find_handler(box.type); - l_current_data_size = box.length - l_nb_bytes_read; - - if ((l_current_handler != 00) || (l_current_handler_misplaced != 00)) { - if (l_current_handler == 00) { - opj_event_msg(p_manager, EVT_WARNING, "Found a misplaced '%c%c%c%c' box outside jp2h box\n", (OPJ_BYTE)(box.type>>24), (OPJ_BYTE)(box.type>>16), (OPJ_BYTE)(box.type>>8), (OPJ_BYTE)(box.type>>0)); - if (jp2->jp2_state & JP2_STATE_HEADER) { - /* read anyway, we already have jp2h */ - l_current_handler = l_current_handler_misplaced; - } else { - opj_event_msg(p_manager, EVT_WARNING, "JPEG2000 Header box not read yet, '%c%c%c%c' box will be ignored\n", (OPJ_BYTE)(box.type>>24), (OPJ_BYTE)(box.type>>16), (OPJ_BYTE)(box.type>>8), (OPJ_BYTE)(box.type>>0)); - jp2->jp2_state |= JP2_STATE_UNKNOWN; - if (opj_stream_skip(stream,l_current_data_size,p_manager) != l_current_data_size) { - opj_event_msg(p_manager, EVT_ERROR, "Problem with skipping JPEG2000 box, stream error\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - continue; - } - } - if ((OPJ_OFF_T)l_current_data_size > opj_stream_get_number_byte_left(stream)) { - /* do not even try to malloc if we can't read */ - opj_event_msg(p_manager, EVT_ERROR, "Invalid box size %d for box '%c%c%c%c'. Need %d bytes, %d bytes remaining \n", box.length, (OPJ_BYTE)(box.type>>24), (OPJ_BYTE)(box.type>>16), (OPJ_BYTE)(box.type>>8), (OPJ_BYTE)(box.type>>0), l_current_data_size, (OPJ_UINT32)opj_stream_get_number_byte_left(stream)); - opj_free(l_current_data); - return OPJ_FALSE; - } - if (l_current_data_size > l_last_data_size) { - OPJ_BYTE* new_current_data = (OPJ_BYTE*)opj_realloc(l_current_data,l_current_data_size); - if (!new_current_data) { - opj_free(l_current_data); - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle jpeg2000 box\n"); - return OPJ_FALSE; - } + opj_event_msg(p_manager, EVT_ERROR, "invalid box size %d (%x)\n", box.length, + box.type); + opj_free(l_current_data); + return OPJ_FALSE; + } + + l_current_handler = opj_jp2_find_handler(box.type); + l_current_handler_misplaced = opj_jp2_img_find_handler(box.type); + l_current_data_size = box.length - l_nb_bytes_read; + + if ((l_current_handler != 00) || (l_current_handler_misplaced != 00)) { + if (l_current_handler == 00) { + opj_event_msg(p_manager, EVT_WARNING, + "Found a misplaced '%c%c%c%c' box outside jp2h box\n", + (OPJ_BYTE)(box.type >> 24), (OPJ_BYTE)(box.type >> 16), + (OPJ_BYTE)(box.type >> 8), (OPJ_BYTE)(box.type >> 0)); + if (jp2->jp2_state & JP2_STATE_HEADER) { + /* read anyway, we already have jp2h */ + l_current_handler = l_current_handler_misplaced; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG2000 Header box not read yet, '%c%c%c%c' box will be ignored\n", + (OPJ_BYTE)(box.type >> 24), (OPJ_BYTE)(box.type >> 16), + (OPJ_BYTE)(box.type >> 8), (OPJ_BYTE)(box.type >> 0)); + jp2->jp2_state |= JP2_STATE_UNKNOWN; + if (opj_stream_skip(stream, l_current_data_size, + p_manager) != l_current_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + continue; + } + } + if ((OPJ_OFF_T)l_current_data_size > opj_stream_get_number_byte_left(stream)) { + /* do not even try to malloc if we can't read */ + opj_event_msg(p_manager, EVT_ERROR, + "Invalid box size %d for box '%c%c%c%c'. Need %d bytes, %d bytes remaining \n", + box.length, (OPJ_BYTE)(box.type >> 24), (OPJ_BYTE)(box.type >> 16), + (OPJ_BYTE)(box.type >> 8), (OPJ_BYTE)(box.type >> 0), l_current_data_size, + (OPJ_UINT32)opj_stream_get_number_byte_left(stream)); + opj_free(l_current_data); + return OPJ_FALSE; + } + if (l_current_data_size > l_last_data_size) { + OPJ_BYTE* new_current_data = (OPJ_BYTE*)opj_realloc(l_current_data, + l_current_data_size); + if (!new_current_data) { + opj_free(l_current_data); + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to handle jpeg2000 box\n"); + return OPJ_FALSE; + } l_current_data = new_current_data; - l_last_data_size = l_current_data_size; - } - - l_nb_bytes_read = (OPJ_UINT32)opj_stream_read_data(stream,l_current_data,l_current_data_size,p_manager); - if (l_nb_bytes_read != l_current_data_size) { - opj_event_msg(p_manager, EVT_ERROR, "Problem with reading JPEG2000 box, stream error\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - - if (! l_current_handler->handler(jp2,l_current_data,l_current_data_size,p_manager)) { - opj_free(l_current_data); - return OPJ_FALSE; - } - } - else { + l_last_data_size = l_current_data_size; + } + + l_nb_bytes_read = (OPJ_UINT32)opj_stream_read_data(stream, l_current_data, + l_current_data_size, p_manager); + if (l_nb_bytes_read != l_current_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with reading JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + + if (! l_current_handler->handler(jp2, l_current_data, l_current_data_size, + p_manager)) { + opj_free(l_current_data); + return OPJ_FALSE; + } + } else { if (!(jp2->jp2_state & JP2_STATE_SIGNATURE)) { - opj_event_msg(p_manager, EVT_ERROR, "Malformed JP2 file format: first box must be JPEG 2000 signature box\n"); + opj_event_msg(p_manager, EVT_ERROR, + "Malformed JP2 file format: first box must be JPEG 2000 signature box\n"); opj_free(l_current_data); return OPJ_FALSE; } if (!(jp2->jp2_state & JP2_STATE_FILE_TYPE)) { - opj_event_msg(p_manager, EVT_ERROR, "Malformed JP2 file format: second box must be file type box\n"); + opj_event_msg(p_manager, EVT_ERROR, + "Malformed JP2 file format: second box must be file type box\n"); opj_free(l_current_data); return OPJ_FALSE; } - jp2->jp2_state |= JP2_STATE_UNKNOWN; - if (opj_stream_skip(stream,l_current_data_size,p_manager) != l_current_data_size) { - opj_event_msg(p_manager, EVT_ERROR, "Problem with skipping JPEG2000 box, stream error\n"); - opj_free(l_current_data); - return OPJ_FALSE; - } - } - } - - opj_free(l_current_data); - - return OPJ_TRUE; + jp2->jp2_state |= JP2_STATE_UNKNOWN; + if (opj_stream_skip(stream, l_current_data_size, + p_manager) != l_current_data_size) { + if (jp2->jp2_state & JP2_STATE_CODESTREAM) { + /* If we already read the codestream, do not error out */ + /* Needed for data/input/nonregression/issue254.jp2 */ + opj_event_msg(p_manager, EVT_WARNING, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_TRUE; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + } + } + } + + opj_free(l_current_data); + + return OPJ_TRUE; } /** - * Excutes the given procedures on the given codec. + * Executes the given procedures on the given codec. * - * @param p_procedure_list the list of procedures to execute - * @param jp2 the jpeg2000 file codec to execute the procedures on. - * @param stream the stream to execute the procedures on. - * @param p_manager the user manager. + * @param p_procedure_list the list of procedures to execute + * @param jp2 the jpeg2000 file codec to execute the procedures on. + * @param stream the stream to execute the procedures on. + * @param p_manager the user manager. * - * @return true if all the procedures were successfully executed. + * @return true if all the procedures were successfully executed. */ -static OPJ_BOOL opj_jp2_exec ( opj_jp2_t * jp2, - opj_procedure_list_t * p_procedure_list, +static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager + ) + +{ + OPJ_BOOL(** l_procedure)(opj_jp2_t * jp2, opj_stream_private_t *, + opj_event_mgr_t *) = 00; + OPJ_BOOL l_result = OPJ_TRUE; + OPJ_UINT32 l_nb_proc, i; + + /* preconditions */ + assert(p_procedure_list != 00); + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); + + l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); + l_procedure = (OPJ_BOOL(**)(opj_jp2_t * jp2, opj_stream_private_t *, + opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); + + for (i = 0; i < l_nb_proc; ++i) { + l_result = l_result && (*l_procedure)(jp2, stream, p_manager); + ++l_procedure; + } + + /* and clear the procedure list at the end. */ + opj_procedure_list_clear(p_procedure_list); + return l_result; +} + +OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2, opj_stream_private_t *stream, + opj_image_t * p_image, opj_event_mgr_t * p_manager - ) + ) +{ + /* preconditions */ + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); + + /* customization of the validation */ + if (! opj_jp2_setup_encoding_validation(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* validation of the parameters codec */ + if (! opj_jp2_exec(jp2, jp2->m_validation_list, stream, p_manager)) { + return OPJ_FALSE; + } + + /* customization of the encoding */ + if (! opj_jp2_setup_header_writing(jp2, p_manager)) { + return OPJ_FALSE; + } -{ - OPJ_BOOL (** l_procedure) (opj_jp2_t * jp2, opj_stream_private_t *, opj_event_mgr_t *) = 00; - OPJ_BOOL l_result = OPJ_TRUE; - OPJ_UINT32 l_nb_proc, i; - - /* preconditions */ - assert(p_procedure_list != 00); - assert(jp2 != 00); - assert(stream != 00); - assert(p_manager != 00); - - l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); - l_procedure = (OPJ_BOOL (**) (opj_jp2_t * jp2, opj_stream_private_t *, opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); - - for (i=0;i<l_nb_proc;++i) { - l_result = l_result && (*l_procedure) (jp2,stream,p_manager); - ++l_procedure; - } - - /* and clear the procedure list at the end. */ - opj_procedure_list_clear(p_procedure_list); - return l_result; -} + /* write header */ + if (! opj_jp2_exec(jp2, jp2->m_procedure_list, stream, p_manager)) { + return OPJ_FALSE; + } -OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_image_t * p_image, - opj_event_mgr_t * p_manager - ) -{ - /* preconditions */ - assert(jp2 != 00); - assert(stream != 00); - assert(p_manager != 00); - - /* customization of the validation */ - if (! opj_jp2_setup_encoding_validation (jp2, p_manager)) { - return OPJ_FALSE; - } - - /* validation of the parameters codec */ - if (! opj_jp2_exec(jp2,jp2->m_validation_list,stream,p_manager)) { - return OPJ_FALSE; - } - - /* customization of the encoding */ - if (! opj_jp2_setup_header_writing(jp2, p_manager)) { - return OPJ_FALSE; - } - - /* write header */ - if (! opj_jp2_exec (jp2,jp2->m_procedure_list,stream,p_manager)) { - return OPJ_FALSE; - } - - return opj_j2k_start_compress(jp2->j2k,stream,p_image,p_manager); + return opj_j2k_start_compress(jp2->j2k, stream, p_image, p_manager); } -static const opj_jp2_header_handler_t * opj_jp2_find_handler (OPJ_UINT32 p_id) +static const opj_jp2_header_handler_t * opj_jp2_find_handler(OPJ_UINT32 p_id) { - OPJ_UINT32 i, l_handler_size = sizeof(jp2_header) / sizeof(opj_jp2_header_handler_t); - - for (i=0;i<l_handler_size;++i) { - if (jp2_header[i].id == p_id) { - return &jp2_header[i]; - } - } - return NULL; + OPJ_UINT32 i, l_handler_size = sizeof(jp2_header) / sizeof( + opj_jp2_header_handler_t); + + for (i = 0; i < l_handler_size; ++i) { + if (jp2_header[i].id == p_id) { + return &jp2_header[i]; + } + } + return NULL; } /** * Finds the image execution function related to the given box id. * - * @param p_id the id of the handler to fetch. + * @param p_id the id of the handler to fetch. * - * @return the given handler or 00 if it could not be found. + * @return the given handler or 00 if it could not be found. */ -static const opj_jp2_header_handler_t * opj_jp2_img_find_handler (OPJ_UINT32 p_id) +static const opj_jp2_header_handler_t * opj_jp2_img_find_handler( + OPJ_UINT32 p_id) { - OPJ_UINT32 i, l_handler_size = sizeof(jp2_img_header) / sizeof(opj_jp2_header_handler_t); - for (i=0;i<l_handler_size;++i) - { - if (jp2_img_header[i].id == p_id) { - return &jp2_img_header[i]; - } - } - - return NULL; + OPJ_UINT32 i, l_handler_size = sizeof(jp2_img_header) / sizeof( + opj_jp2_header_handler_t); + for (i = 0; i < l_handler_size; ++i) { + if (jp2_img_header[i].id == p_id) { + return &jp2_img_header[i]; + } + } + + return NULL; } /** * Reads a jpeg2000 file signature box. * - * @param p_header_data the data contained in the signature box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the signature box. - * @param p_manager the user event manager. + * @param p_header_data the data contained in the signature box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the signature box. + * @param p_manager the user event manager. * * @return true if the file signature box is valid. */ @@ -2347,578 +2550,634 @@ static OPJ_BOOL opj_jp2_read_jp(opj_jp2_t *jp2, OPJ_BYTE * p_header_data, OPJ_UINT32 p_header_size, opj_event_mgr_t * p_manager - ) + ) { - OPJ_UINT32 l_magic_number; - - /* preconditions */ - assert(p_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - if (jp2->jp2_state != JP2_STATE_NONE) { - opj_event_msg(p_manager, EVT_ERROR, "The signature box must be the first box in the file.\n"); - return OPJ_FALSE; - } - - /* assure length of data is correct (4 -> magic number) */ - if (p_header_size != 4) { - opj_event_msg(p_manager, EVT_ERROR, "Error with JP signature Box size\n"); - return OPJ_FALSE; - } - - /* rearrange data */ - opj_read_bytes(p_header_data,&l_magic_number,4); - if (l_magic_number != 0x0d0a870a ) { - opj_event_msg(p_manager, EVT_ERROR, "Error with JP Signature : bad magic number\n"); - return OPJ_FALSE; - } - - jp2->jp2_state |= JP2_STATE_SIGNATURE; - - return OPJ_TRUE; + OPJ_UINT32 l_magic_number; + + /* preconditions */ + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if (jp2->jp2_state != JP2_STATE_NONE) { + opj_event_msg(p_manager, EVT_ERROR, + "The signature box must be the first box in the file.\n"); + return OPJ_FALSE; + } + + /* assure length of data is correct (4 -> magic number) */ + if (p_header_size != 4) { + opj_event_msg(p_manager, EVT_ERROR, "Error with JP signature Box size\n"); + return OPJ_FALSE; + } + + /* rearrange data */ + opj_read_bytes(p_header_data, &l_magic_number, 4); + if (l_magic_number != 0x0d0a870a) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with JP Signature : bad magic number\n"); + return OPJ_FALSE; + } + + jp2->jp2_state |= JP2_STATE_SIGNATURE; + + return OPJ_TRUE; } /** * Reads a a FTYP box - File type box * - * @param p_header_data the data contained in the FTYP box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the FTYP box. - * @param p_manager the user event manager. + * @param p_header_data the data contained in the FTYP box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the FTYP box. + * @param p_manager the user event manager. * * @return true if the FTYP box is valid. */ -static OPJ_BOOL opj_jp2_read_ftyp( opj_jp2_t *jp2, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_ftyp(opj_jp2_t *jp2, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 i, l_remaining_bytes; - - /* preconditions */ - assert(p_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - if (jp2->jp2_state != JP2_STATE_SIGNATURE) { - opj_event_msg(p_manager, EVT_ERROR, "The ftyp box must be the second box in the file.\n"); - return OPJ_FALSE; - } - - /* assure length of data is correct */ - if (p_header_size < 8) { - opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_header_data,&jp2->brand,4); /* BR */ - p_header_data += 4; - - opj_read_bytes(p_header_data,&jp2->minversion,4); /* MinV */ - p_header_data += 4; - - l_remaining_bytes = p_header_size - 8; - - /* the number of remaining bytes should be a multiple of 4 */ - if ((l_remaining_bytes & 0x3) != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); - return OPJ_FALSE; - } - - /* div by 4 */ - jp2->numcl = l_remaining_bytes >> 2; - if (jp2->numcl) { - jp2->cl = (OPJ_UINT32 *) opj_calloc(jp2->numcl, sizeof(OPJ_UINT32)); - if (jp2->cl == 00) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory with FTYP Box\n"); - return OPJ_FALSE; - } - } - - for (i = 0; i < jp2->numcl; ++i) - { - opj_read_bytes(p_header_data,&jp2->cl[i],4); /* CLi */ - p_header_data += 4; - } - - jp2->jp2_state |= JP2_STATE_FILE_TYPE; - - return OPJ_TRUE; + OPJ_UINT32 i, l_remaining_bytes; + + /* preconditions */ + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if (jp2->jp2_state != JP2_STATE_SIGNATURE) { + opj_event_msg(p_manager, EVT_ERROR, + "The ftyp box must be the second box in the file.\n"); + return OPJ_FALSE; + } + + /* assure length of data is correct */ + if (p_header_size < 8) { + opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &jp2->brand, 4); /* BR */ + p_header_data += 4; + + opj_read_bytes(p_header_data, &jp2->minversion, 4); /* MinV */ + p_header_data += 4; + + l_remaining_bytes = p_header_size - 8; + + /* the number of remaining bytes should be a multiple of 4 */ + if ((l_remaining_bytes & 0x3) != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); + return OPJ_FALSE; + } + + /* div by 4 */ + jp2->numcl = l_remaining_bytes >> 2; + if (jp2->numcl) { + jp2->cl = (OPJ_UINT32 *) opj_calloc(jp2->numcl, sizeof(OPJ_UINT32)); + if (jp2->cl == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory with FTYP Box\n"); + return OPJ_FALSE; + } + } + + for (i = 0; i < jp2->numcl; ++i) { + opj_read_bytes(p_header_data, &jp2->cl[i], 4); /* CLi */ + p_header_data += 4; + } + + jp2->jp2_state |= JP2_STATE_FILE_TYPE; + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_skip_jp2c( opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_jp2_skip_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(stream != 00); - assert(p_manager != 00); + /* preconditions */ + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); - jp2->j2k_codestream_offset = opj_stream_tell(stream); + jp2->j2k_codestream_offset = opj_stream_tell(stream); - if (opj_stream_skip(stream,8,p_manager) != 8) { - return OPJ_FALSE; - } + if (opj_stream_skip(stream, 8, p_manager) != 8) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_jpip_skip_iptr( opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager ) +static OPJ_BOOL opj_jpip_skip_iptr(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(stream != 00); - assert(p_manager != 00); + /* preconditions */ + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); - jp2->jpip_iptr_offset = opj_stream_tell(stream); + jp2->jpip_iptr_offset = opj_stream_tell(stream); - if (opj_stream_skip(stream,24,p_manager) != 24) { - return OPJ_FALSE; - } + if (opj_stream_skip(stream, 24, p_manager) != 24) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /** * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). * - * @param p_header_data the data contained in the file header box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the file header box. - * @param p_manager the user event manager. + * @param p_header_data the data contained in the file header box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the file header box. + * @param p_manager the user event manager. * * @return true if the JP2 Header box was successfully recognized. */ -static OPJ_BOOL opj_jp2_read_jp2h( opj_jp2_t *jp2, - OPJ_BYTE *p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_jp2h(opj_jp2_t *jp2, + OPJ_BYTE *p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_box_size=0, l_current_data_size = 0; - opj_jp2_box_t box; - const opj_jp2_header_handler_t * l_current_handler; - OPJ_BOOL l_has_ihdr = 0; - - /* preconditions */ - assert(p_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - /* make sure the box is well placed */ - if ((jp2->jp2_state & JP2_STATE_FILE_TYPE) != JP2_STATE_FILE_TYPE ) { - opj_event_msg(p_manager, EVT_ERROR, "The box must be the first box in the file.\n"); - return OPJ_FALSE; - } - - jp2->jp2_img_state = JP2_IMG_STATE_NONE; - - /* iterate while remaining data */ - while (p_header_size > 0) { - - if (! opj_jp2_read_boxhdr_char(&box,p_header_data,&l_box_size,p_header_size, p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box\n"); - return OPJ_FALSE; - } - - if (box.length > p_header_size) { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box: box length is inconsistent.\n"); - return OPJ_FALSE; - } - - l_current_handler = opj_jp2_img_find_handler(box.type); - l_current_data_size = box.length - l_box_size; - p_header_data += l_box_size; - - if (l_current_handler != 00) { - if (! l_current_handler->handler(jp2,p_header_data,l_current_data_size,p_manager)) { - return OPJ_FALSE; - } - } - else { - jp2->jp2_img_state |= JP2_IMG_STATE_UNKNOWN; - } - - if (box.type == JP2_IHDR) { - l_has_ihdr = 1; - } - - p_header_data += l_current_data_size; - p_header_size -= box.length; - } - - if (l_has_ihdr == 0) { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box: no 'ihdr' box.\n"); - return OPJ_FALSE; - } - - jp2->jp2_state |= JP2_STATE_HEADER; - - return OPJ_TRUE; + OPJ_UINT32 l_box_size = 0, l_current_data_size = 0; + opj_jp2_box_t box; + const opj_jp2_header_handler_t * l_current_handler; + OPJ_BOOL l_has_ihdr = 0; + + /* preconditions */ + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + /* make sure the box is well placed */ + if ((jp2->jp2_state & JP2_STATE_FILE_TYPE) != JP2_STATE_FILE_TYPE) { + opj_event_msg(p_manager, EVT_ERROR, + "The box must be the first box in the file.\n"); + return OPJ_FALSE; + } + + jp2->jp2_img_state = JP2_IMG_STATE_NONE; + + /* iterate while remaining data */ + while (p_header_size > 0) { + + if (! opj_jp2_read_boxhdr_char(&box, p_header_data, &l_box_size, p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while reading JP2 Header box\n"); + return OPJ_FALSE; + } + + if (box.length > p_header_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while reading JP2 Header box: box length is inconsistent.\n"); + return OPJ_FALSE; + } + + l_current_handler = opj_jp2_img_find_handler(box.type); + l_current_data_size = box.length - l_box_size; + p_header_data += l_box_size; + + if (l_current_handler != 00) { + if (! l_current_handler->handler(jp2, p_header_data, l_current_data_size, + p_manager)) { + return OPJ_FALSE; + } + } else { + jp2->jp2_img_state |= JP2_IMG_STATE_UNKNOWN; + } + + if (box.type == JP2_IHDR) { + l_has_ihdr = 1; + } + + p_header_data += l_current_data_size; + p_header_size -= box.length; + } + + if (l_has_ihdr == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while reading JP2 Header box: no 'ihdr' box.\n"); + return OPJ_FALSE; + } + + jp2->jp2_state |= JP2_STATE_HEADER; + jp2->has_jp2h = 1; + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_read_boxhdr_char( opj_jp2_box_t *box, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_number_bytes_read, - OPJ_UINT32 p_box_max_size, - opj_event_mgr_t * p_manager - ) +static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_number_bytes_read, + OPJ_UINT32 p_box_max_size, + opj_event_mgr_t * p_manager + ) { - OPJ_UINT32 l_value; - - /* preconditions */ - assert(p_data != 00); - assert(box != 00); - assert(p_number_bytes_read != 00); - assert(p_manager != 00); - - if (p_box_max_size < 8) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of less than 8 bytes\n"); - return OPJ_FALSE; - } - - /* process read data */ - opj_read_bytes(p_data, &l_value, 4); - p_data += 4; - box->length = (OPJ_UINT32)(l_value); - - opj_read_bytes(p_data, &l_value, 4); - p_data += 4; - box->type = (OPJ_UINT32)(l_value); - - *p_number_bytes_read = 8; - - /* do we have a "special very large box ?" */ - /* read then the XLBox */ - if (box->length == 1) { - OPJ_UINT32 l_xl_part_size; - - if (p_box_max_size < 16) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle XL box of less than 16 bytes\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_data,&l_xl_part_size, 4); - p_data += 4; - *p_number_bytes_read += 4; - - if (l_xl_part_size != 0) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); - return OPJ_FALSE; - } - - opj_read_bytes(p_data, &l_value, 4); - *p_number_bytes_read += 4; - box->length = (OPJ_UINT32)(l_value); - - if (box->length == 0) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); - return OPJ_FALSE; - } - } - else if (box->length == 0) { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); - return OPJ_FALSE; - } - if (box->length < *p_number_bytes_read) { - opj_event_msg(p_manager, EVT_ERROR, "Box length is inconsistent.\n"); - return OPJ_FALSE; - } - return OPJ_TRUE; + OPJ_UINT32 l_value; + + /* preconditions */ + assert(p_data != 00); + assert(box != 00); + assert(p_number_bytes_read != 00); + assert(p_manager != 00); + + if (p_box_max_size < 8) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of less than 8 bytes\n"); + return OPJ_FALSE; + } + + /* process read data */ + opj_read_bytes(p_data, &l_value, 4); + p_data += 4; + box->length = (OPJ_UINT32)(l_value); + + opj_read_bytes(p_data, &l_value, 4); + p_data += 4; + box->type = (OPJ_UINT32)(l_value); + + *p_number_bytes_read = 8; + + /* do we have a "special very large box ?" */ + /* read then the XLBox */ + if (box->length == 1) { + OPJ_UINT32 l_xl_part_size; + + if (p_box_max_size < 16) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle XL box of less than 16 bytes\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_data, &l_xl_part_size, 4); + p_data += 4; + *p_number_bytes_read += 4; + + if (l_xl_part_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_data, &l_value, 4); + *p_number_bytes_read += 4; + box->length = (OPJ_UINT32)(l_value); + + if (box->length == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return OPJ_FALSE; + } + } else if (box->length == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return OPJ_FALSE; + } + if (box->length < *p_number_bytes_read) { + opj_event_msg(p_manager, EVT_ERROR, "Box length is inconsistent.\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; } -OPJ_BOOL opj_jp2_read_header( opj_stream_private_t *p_stream, - opj_jp2_t *jp2, - opj_image_t ** p_image, - opj_event_mgr_t * p_manager - ) +OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, + opj_jp2_t *jp2, + opj_image_t ** p_image, + opj_event_mgr_t * p_manager + ) { - /* preconditions */ - assert(jp2 != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - /* customization of the validation */ - if (! opj_jp2_setup_decoding_validation (jp2, p_manager)) { - return OPJ_FALSE; - } - - /* customization of the encoding */ - if (! opj_jp2_setup_header_reading(jp2, p_manager)) { - return OPJ_FALSE; - } - - /* validation of the parameters codec */ - if (! opj_jp2_exec(jp2,jp2->m_validation_list,p_stream,p_manager)) { - return OPJ_FALSE; - } - - /* read header */ - if (! opj_jp2_exec (jp2,jp2->m_procedure_list,p_stream,p_manager)) { - return OPJ_FALSE; - } - - return opj_j2k_read_header( p_stream, - jp2->j2k, - p_image, - p_manager); + /* preconditions */ + assert(jp2 != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + /* customization of the validation */ + if (! opj_jp2_setup_decoding_validation(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* customization of the encoding */ + if (! opj_jp2_setup_header_reading(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* validation of the parameters codec */ + if (! opj_jp2_exec(jp2, jp2->m_validation_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + + /* read header */ + if (! opj_jp2_exec(jp2, jp2->m_procedure_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + if (jp2->has_jp2h == 0) { + opj_event_msg(p_manager, EVT_ERROR, "JP2H box missing. Required.\n"); + return OPJ_FALSE; + } + if (jp2->has_ihdr == 0) { + opj_event_msg(p_manager, EVT_ERROR, "IHDR box_missing. Required.\n"); + return OPJ_FALSE; + } + + return opj_j2k_read_header(p_stream, + jp2->j2k, + p_image, + p_manager); } -static OPJ_BOOL opj_jp2_setup_encoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(p_manager != 00); - - if (! opj_procedure_list_add_procedure(jp2->m_validation_list, (opj_procedure)opj_jp2_default_validation, p_manager)) { - return OPJ_FALSE; - } - /* DEVELOPER CORNER, add your custom validation procedure */ - - return OPJ_TRUE; + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_validation_list, + (opj_procedure)opj_jp2_default_validation, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom validation procedure */ + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_setup_decoding_validation (opj_jp2_t *jp2, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_setup_decoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(p_manager != 00); - - /* DEVELOPER CORNER, add your custom validation procedure */ - - return OPJ_TRUE; + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + OPJ_UNUSED(jp2); + OPJ_UNUSED(p_manager); + + /* DEVELOPER CORNER, add your custom validation procedure */ + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_setup_header_writing (opj_jp2_t *jp2, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_setup_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(p_manager != 00); - - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_ftyp, p_manager)) { - return OPJ_FALSE; - } - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2h, p_manager)) { - return OPJ_FALSE; - } - if( jp2->jpip_on ) { - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jpip_skip_iptr, p_manager)) { - return OPJ_FALSE; - } - } - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_skip_jp2c,p_manager)) { - return OPJ_FALSE; - } - - /* DEVELOPER CORNER, insert your custom procedures */ - - return OPJ_TRUE; + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_jp, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_ftyp, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_jp2h, p_manager)) { + return OPJ_FALSE; + } + if (jp2->jpip_on) { + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_skip_iptr, p_manager)) { + return OPJ_FALSE; + } + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_skip_jp2c, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, insert your custom procedures */ + + return OPJ_TRUE; } -static OPJ_BOOL opj_jp2_setup_header_reading (opj_jp2_t *jp2, opj_event_mgr_t * p_manager) +static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) { - /* preconditions */ - assert(jp2 != 00); - assert(p_manager != 00); - - if (! opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure, p_manager)) { - return OPJ_FALSE; - } - - /* DEVELOPER CORNER, add your custom procedures */ - - return OPJ_TRUE; + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_read_header_procedure, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, add your custom procedures */ + + return OPJ_TRUE; } -OPJ_BOOL opj_jp2_read_tile_header ( opj_jp2_t * p_jp2, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - return opj_j2k_read_tile_header(p_jp2->j2k, - p_tile_index, - p_data_size, - p_tile_x0, p_tile_y0, - p_tile_x1, p_tile_y1, - p_nb_comps, - p_go_on, - p_stream, - p_manager); + return opj_j2k_read_tile_header(p_jp2->j2k, + p_tile_index, + p_data_size, + p_tile_x0, p_tile_y0, + p_tile_x1, p_tile_y1, + p_nb_comps, + p_go_on, + p_stream, + p_manager); } -OPJ_BOOL opj_jp2_write_tile ( opj_jp2_t *p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - return opj_j2k_write_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager); + return opj_j2k_write_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size, + p_stream, p_manager); } -OPJ_BOOL opj_jp2_decode_tile ( opj_jp2_t * p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) { - return opj_j2k_decode_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager); + return opj_j2k_decode_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size, + p_stream, p_manager); } void opj_jp2_destroy(opj_jp2_t *jp2) { - if (jp2) { - /* destroy the J2K codec */ - opj_j2k_destroy(jp2->j2k); - jp2->j2k = 00; - - if (jp2->comps) { - opj_free(jp2->comps); - jp2->comps = 00; - } - - if (jp2->cl) { - opj_free(jp2->cl); - jp2->cl = 00; - } - - if (jp2->color.icc_profile_buf) { - opj_free(jp2->color.icc_profile_buf); - jp2->color.icc_profile_buf = 00; - } - - if (jp2->color.jp2_cdef) { - if (jp2->color.jp2_cdef->info) { - opj_free(jp2->color.jp2_cdef->info); - jp2->color.jp2_cdef->info = NULL; - } - - opj_free(jp2->color.jp2_cdef); - jp2->color.jp2_cdef = 00; - } - - if (jp2->color.jp2_pclr) { - if (jp2->color.jp2_pclr->cmap) { - opj_free(jp2->color.jp2_pclr->cmap); - jp2->color.jp2_pclr->cmap = NULL; - } - if (jp2->color.jp2_pclr->channel_sign) { - opj_free(jp2->color.jp2_pclr->channel_sign); - jp2->color.jp2_pclr->channel_sign = NULL; - } - if (jp2->color.jp2_pclr->channel_size) { - opj_free(jp2->color.jp2_pclr->channel_size); - jp2->color.jp2_pclr->channel_size = NULL; - } - if (jp2->color.jp2_pclr->entries) { - opj_free(jp2->color.jp2_pclr->entries); - jp2->color.jp2_pclr->entries = NULL; - } - - opj_free(jp2->color.jp2_pclr); - jp2->color.jp2_pclr = 00; - } - - if (jp2->m_validation_list) { - opj_procedure_list_destroy(jp2->m_validation_list); - jp2->m_validation_list = 00; - } - - if (jp2->m_procedure_list) { - opj_procedure_list_destroy(jp2->m_procedure_list); - jp2->m_procedure_list = 00; - } - - opj_free(jp2); - } + if (jp2) { + /* destroy the J2K codec */ + opj_j2k_destroy(jp2->j2k); + jp2->j2k = 00; + + if (jp2->comps) { + opj_free(jp2->comps); + jp2->comps = 00; + } + + if (jp2->cl) { + opj_free(jp2->cl); + jp2->cl = 00; + } + + if (jp2->color.icc_profile_buf) { + opj_free(jp2->color.icc_profile_buf); + jp2->color.icc_profile_buf = 00; + } + + if (jp2->color.jp2_cdef) { + if (jp2->color.jp2_cdef->info) { + opj_free(jp2->color.jp2_cdef->info); + jp2->color.jp2_cdef->info = NULL; + } + + opj_free(jp2->color.jp2_cdef); + jp2->color.jp2_cdef = 00; + } + + if (jp2->color.jp2_pclr) { + if (jp2->color.jp2_pclr->cmap) { + opj_free(jp2->color.jp2_pclr->cmap); + jp2->color.jp2_pclr->cmap = NULL; + } + if (jp2->color.jp2_pclr->channel_sign) { + opj_free(jp2->color.jp2_pclr->channel_sign); + jp2->color.jp2_pclr->channel_sign = NULL; + } + if (jp2->color.jp2_pclr->channel_size) { + opj_free(jp2->color.jp2_pclr->channel_size); + jp2->color.jp2_pclr->channel_size = NULL; + } + if (jp2->color.jp2_pclr->entries) { + opj_free(jp2->color.jp2_pclr->entries); + jp2->color.jp2_pclr->entries = NULL; + } + + opj_free(jp2->color.jp2_pclr); + jp2->color.jp2_pclr = 00; + } + + if (jp2->m_validation_list) { + opj_procedure_list_destroy(jp2->m_validation_list); + jp2->m_validation_list = 00; + } + + if (jp2->m_procedure_list) { + opj_procedure_list_destroy(jp2->m_procedure_list); + jp2->m_procedure_list = 00; + } + + opj_free(jp2); + } +} + +OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *p_jp2, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager) +{ + return opj_j2k_set_decoded_components(p_jp2->j2k, + numcomps, comps_indices, + p_manager); } -OPJ_BOOL opj_jp2_set_decode_area( opj_jp2_t *p_jp2, - opj_image_t* p_image, - OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, - opj_event_mgr_t * p_manager - ) +OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager + ) { - return opj_j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, p_end_x, p_end_y, p_manager); + return opj_j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, + p_end_x, p_end_y, p_manager); } -OPJ_BOOL opj_jp2_get_tile( opj_jp2_t *p_jp2, - opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager, - OPJ_UINT32 tile_index - ) +OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index + ) { - if (!p_image) - return OPJ_FALSE; - - opj_event_msg(p_manager, EVT_WARNING, "JP2 box which are after the codestream will not be read by this function.\n"); - - if (! opj_j2k_get_tile(p_jp2->j2k, p_stream, p_image, p_manager, tile_index) ){ - opj_event_msg(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n"); - return OPJ_FALSE; - } - - if (!opj_jp2_check_color(p_image, &(p_jp2->color), p_manager)) { - return OPJ_FALSE; - } - - /* Set Image Color Space */ - if (p_jp2->enumcs == 16) - p_image->color_space = OPJ_CLRSPC_SRGB; - else if (p_jp2->enumcs == 17) - p_image->color_space = OPJ_CLRSPC_GRAY; - else if (p_jp2->enumcs == 18) - p_image->color_space = OPJ_CLRSPC_SYCC; - else if (p_jp2->enumcs == 24) - p_image->color_space = OPJ_CLRSPC_EYCC; - else if (p_jp2->enumcs == 12) - p_image->color_space = OPJ_CLRSPC_CMYK; - else - p_image->color_space = OPJ_CLRSPC_UNKNOWN; - - if(p_jp2->color.jp2_pclr) { - /* Part 1, I.5.3.4: Either both or none : */ - if( !p_jp2->color.jp2_pclr->cmap) - opj_jp2_free_pclr(&(p_jp2->color)); - else - opj_jp2_apply_pclr(p_image, &(p_jp2->color)); - } - - /* Apply the color space if needed */ - if(p_jp2->color.jp2_cdef) { - opj_jp2_apply_cdef(p_image, &(p_jp2->color), p_manager); - } - - if(p_jp2->color.icc_profile_buf) { - p_image->icc_profile_buf = p_jp2->color.icc_profile_buf; - p_image->icc_profile_len = p_jp2->color.icc_profile_len; - p_jp2->color.icc_profile_buf = NULL; - } - - return OPJ_TRUE; + if (!p_image) { + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_WARNING, + "JP2 box which are after the codestream will not be read by this function.\n"); + + if (! opj_j2k_get_tile(p_jp2->j2k, p_stream, p_image, p_manager, tile_index)) { + opj_event_msg(p_manager, EVT_ERROR, + "Failed to decode the codestream in the JP2 file\n"); + return OPJ_FALSE; + } + + if (p_jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) { + /* Bypass all JP2 component transforms */ + return OPJ_TRUE; + } + + if (!opj_jp2_check_color(p_image, &(p_jp2->color), p_manager)) { + return OPJ_FALSE; + } + + /* Set Image Color Space */ + if (p_jp2->enumcs == 16) { + p_image->color_space = OPJ_CLRSPC_SRGB; + } else if (p_jp2->enumcs == 17) { + p_image->color_space = OPJ_CLRSPC_GRAY; + } else if (p_jp2->enumcs == 18) { + p_image->color_space = OPJ_CLRSPC_SYCC; + } else if (p_jp2->enumcs == 24) { + p_image->color_space = OPJ_CLRSPC_EYCC; + } else if (p_jp2->enumcs == 12) { + p_image->color_space = OPJ_CLRSPC_CMYK; + } else { + p_image->color_space = OPJ_CLRSPC_UNKNOWN; + } + + if (p_jp2->color.jp2_pclr) { + /* Part 1, I.5.3.4: Either both or none : */ + if (!p_jp2->color.jp2_pclr->cmap) { + opj_jp2_free_pclr(&(p_jp2->color)); + } else { + if (!opj_jp2_apply_pclr(p_image, &(p_jp2->color), p_manager)) { + return OPJ_FALSE; + } + } + } + + /* Apply the color space if needed */ + if (p_jp2->color.jp2_cdef) { + opj_jp2_apply_cdef(p_image, &(p_jp2->color), p_manager); + } + + if (p_jp2->color.icc_profile_buf) { + p_image->icc_profile_buf = p_jp2->color.icc_profile_buf; + p_image->icc_profile_len = p_jp2->color.icc_profile_len; + p_jp2->color.icc_profile_buf = NULL; + } + + return OPJ_TRUE; } /* ----------------------------------------------------------------------- */ @@ -2927,251 +3186,259 @@ OPJ_BOOL opj_jp2_get_tile( opj_jp2_t *p_jp2, opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder) { - opj_jp2_t *jp2 = (opj_jp2_t*)opj_calloc(1,sizeof(opj_jp2_t)); - if (jp2) { - - /* create the J2K codec */ - if (! p_is_decoder) { - jp2->j2k = opj_j2k_create_compress(); - } - else { - jp2->j2k = opj_j2k_create_decompress(); - } - - if (jp2->j2k == 00) { - opj_jp2_destroy(jp2); - return 00; - } - - /* Color structure */ - jp2->color.icc_profile_buf = NULL; - jp2->color.icc_profile_len = 0; - jp2->color.jp2_cdef = NULL; - jp2->color.jp2_pclr = NULL; - jp2->color.jp2_has_colr = 0; - - /* validation list creation */ - jp2->m_validation_list = opj_procedure_list_create(); - if (! jp2->m_validation_list) { - opj_jp2_destroy(jp2); - return 00; - } - - /* execution list creation */ - jp2->m_procedure_list = opj_procedure_list_create(); - if (! jp2->m_procedure_list) { - opj_jp2_destroy(jp2); - return 00; - } - } - - return jp2; + opj_jp2_t *jp2 = (opj_jp2_t*)opj_calloc(1, sizeof(opj_jp2_t)); + if (jp2) { + + /* create the J2K codec */ + if (! p_is_decoder) { + jp2->j2k = opj_j2k_create_compress(); + } else { + jp2->j2k = opj_j2k_create_decompress(); + } + + if (jp2->j2k == 00) { + opj_jp2_destroy(jp2); + return 00; + } + + /* Color structure */ + jp2->color.icc_profile_buf = NULL; + jp2->color.icc_profile_len = 0; + jp2->color.jp2_cdef = NULL; + jp2->color.jp2_pclr = NULL; + jp2->color.jp2_has_colr = 0; + + /* validation list creation */ + jp2->m_validation_list = opj_procedure_list_create(); + if (! jp2->m_validation_list) { + opj_jp2_destroy(jp2); + return 00; + } + + /* execution list creation */ + jp2->m_procedure_list = opj_procedure_list_create(); + if (! jp2->m_procedure_list) { + opj_jp2_destroy(jp2); + return 00; + } + } + + return jp2; } void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream) { - /* preconditions */ - assert(p_jp2 != 00); + /* preconditions */ + assert(p_jp2 != 00); - j2k_dump(p_jp2->j2k, - flag, - out_stream); + j2k_dump(p_jp2->j2k, + flag, + out_stream); } opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2) { - return j2k_get_cstr_index(p_jp2->j2k); + return j2k_get_cstr_index(p_jp2->j2k); } opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2) { - return j2k_get_cstr_info(p_jp2->j2k); + return j2k_get_cstr_info(p_jp2->j2k); } OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2, - OPJ_UINT32 res_factor, - opj_event_mgr_t * p_manager) + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager) { - return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager); + return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager); } /* JPIP specific */ #ifdef USE_JPIP static OPJ_BOOL opj_jpip_write_iptr(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - OPJ_OFF_T j2k_codestream_exit; - OPJ_BYTE l_data_header [24]; - - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - assert(opj_stream_has_seek(cio)); - - j2k_codestream_exit = opj_stream_tell(cio); - opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ - opj_write_bytes(l_data_header + 4,JPIP_IPTR,4); /* IPTR */ + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [24]; + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ + opj_write_bytes(l_data_header + 4, JPIP_IPTR, + 4); /* IPTR */ #if 0 - opj_write_bytes(l_data_header + 4 + 4, 0, 8); /* offset */ - opj_write_bytes(l_data_header + 8 + 8, 0, 8); /* length */ + opj_write_bytes(l_data_header + 4 + 4, 0, 8); /* offset */ + opj_write_bytes(l_data_header + 8 + 8, 0, 8); /* length */ #else - opj_write_double(l_data_header + 4 + 4, 0); /* offset */ - opj_write_double(l_data_header + 8 + 8, 0); /* length */ + opj_write_double(l_data_header + 4 + 4, 0); /* offset */ + opj_write_double(l_data_header + 8 + 8, 0); /* length */ #endif - if (! opj_stream_seek(cio,jp2->jpip_iptr_offset,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } + if (! opj_stream_seek(cio, jp2->jpip_iptr_offset, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } - if (opj_stream_write_data(cio,l_data_header,24,p_manager) != 24) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } + if (opj_stream_write_data(cio, l_data_header, 24, p_manager) != 24) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } - if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } static OPJ_BOOL opj_jpip_write_fidx(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - OPJ_OFF_T j2k_codestream_exit; - OPJ_BYTE l_data_header [24]; - - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - assert(opj_stream_has_seek(cio)); - - opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ - opj_write_bytes(l_data_header + 4,JPIP_FIDX,4); /* IPTR */ - opj_write_double(l_data_header + 4 + 4, 0); /* offset */ - opj_write_double(l_data_header + 8 + 8, 0); /* length */ - - if (opj_stream_write_data(cio,l_data_header,24,p_manager) != 24) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } - - j2k_codestream_exit = opj_stream_tell(cio); - if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } - - return OPJ_TRUE; + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [24]; + + OPJ_UNUSED(jp2); + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ + opj_write_bytes(l_data_header + 4, JPIP_FIDX, + 4); /* IPTR */ + opj_write_double(l_data_header + 4 + 4, 0); /* offset */ + opj_write_double(l_data_header + 8 + 8, 0); /* length */ + + if (opj_stream_write_data(cio, l_data_header, 24, p_manager) != 24) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + j2k_codestream_exit = opj_stream_tell(cio); + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; } static OPJ_BOOL opj_jpip_write_cidx(opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - OPJ_OFF_T j2k_codestream_exit; - OPJ_BYTE l_data_header [24]; - - /* preconditions */ - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - assert(opj_stream_has_seek(cio)); - - j2k_codestream_exit = opj_stream_tell(cio); - opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ - opj_write_bytes(l_data_header + 4,JPIP_CIDX,4); /* IPTR */ + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [24]; + + OPJ_UNUSED(jp2); + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ + opj_write_bytes(l_data_header + 4, JPIP_CIDX, + 4); /* IPTR */ #if 0 - opj_write_bytes(l_data_header + 4 + 4, 0, 8); /* offset */ - opj_write_bytes(l_data_header + 8 + 8, 0, 8); /* length */ + opj_write_bytes(l_data_header + 4 + 4, 0, 8); /* offset */ + opj_write_bytes(l_data_header + 8 + 8, 0, 8); /* length */ #else - opj_write_double(l_data_header + 4 + 4, 0); /* offset */ - opj_write_double(l_data_header + 8 + 8, 0); /* length */ + opj_write_double(l_data_header + 4 + 4, 0); /* offset */ + opj_write_double(l_data_header + 8 + 8, 0); /* length */ #endif - if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } - if (opj_stream_write_data(cio,l_data_header,24,p_manager) != 24) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } + if (opj_stream_write_data(cio, l_data_header, 24, p_manager) != 24) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } - j2k_codestream_exit = opj_stream_tell(cio); - if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) { - opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); - return OPJ_FALSE; - } + j2k_codestream_exit = opj_stream_tell(cio); + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } #if 0 -static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) +static void write_prxy(int offset_jp2c, int length_jp2c, int offset_idx, + int length_idx, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - OPJ_BYTE l_data_header [8]; - OPJ_OFF_T len, lenp; - - lenp = opj_stream_tell(cio); - opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ - opj_write_bytes(l_data_header,JPIP_PRXY,4); /* IPTR */ - opj_stream_write_data(cio,l_data_header,4,p_manager); - - opj_write_bytes( l_data_header, offset_jp2c, 8); /* OOFF */ - opj_stream_write_data(cio,l_data_header,8,p_manager); - opj_write_bytes( l_data_header, length_jp2c, 4); /* OBH part 1 */ - opj_write_bytes( l_data_header+4, JP2_JP2C, 4); /* OBH part 2 */ - opj_stream_write_data(cio,l_data_header,8,p_manager); - - opj_write_bytes( l_data_header, 1, 1);/* NI */ - opj_stream_write_data(cio,l_data_header,1,p_manager); - - opj_write_bytes( l_data_header, offset_idx, 8); /* IOFF */ - opj_stream_write_data(cio,l_data_header,8,p_manager); - opj_write_bytes( l_data_header, length_idx, 4); /* IBH part 1 */ - opj_write_bytes( l_data_header+4, JPIP_CIDX, 4); /* IBH part 2 */ - opj_stream_write_data(cio,l_data_header,8,p_manager); - - len = opj_stream_tell(cio)-lenp; - opj_stream_skip(cio, lenp, p_manager); - opj_write_bytes(l_data_header,len,4);/* L */ - opj_stream_write_data(cio,l_data_header,4,p_manager); - opj_stream_seek(cio, lenp+len,p_manager); + OPJ_BYTE l_data_header [8]; + OPJ_OFF_T len, lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_PRXY, 4); /* IPTR */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_bytes(l_data_header, offset_jp2c, 8); /* OOFF */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + opj_write_bytes(l_data_header, length_jp2c, 4); /* OBH part 1 */ + opj_write_bytes(l_data_header + 4, JP2_JP2C, 4); /* OBH part 2 */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + + opj_write_bytes(l_data_header, 1, 1); /* NI */ + opj_stream_write_data(cio, l_data_header, 1, p_manager); + + opj_write_bytes(l_data_header, offset_idx, 8); /* IOFF */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + opj_write_bytes(l_data_header, length_idx, 4); /* IBH part 1 */ + opj_write_bytes(l_data_header + 4, JPIP_CIDX, 4); /* IBH part 2 */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + + len = opj_stream_tell(cio) - lenp; + opj_stream_skip(cio, lenp, p_manager); + opj_write_bytes(l_data_header, len, 4); /* L */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_stream_seek(cio, lenp + len, p_manager); } #endif #if 0 -static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_stream_private_t *cio, - opj_event_mgr_t * p_manager ) +static int write_fidx(int offset_jp2c, int length_jp2c, int offset_idx, + int length_idx, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) { - OPJ_BYTE l_data_header [4]; - OPJ_OFF_T len, lenp; + OPJ_BYTE l_data_header [4]; + OPJ_OFF_T len, lenp; - lenp = opj_stream_tell(cio); - opj_stream_skip(cio, 4, p_manager); - opj_write_bytes(l_data_header,JPIP_FIDX,4); /* FIDX */ - opj_stream_write_data(cio,l_data_header,4,p_manager); + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); + opj_write_bytes(l_data_header, JPIP_FIDX, 4); /* FIDX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); - write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio,p_manager); + write_prxy(offset_jp2c, length_jp2c, offset_idx, length_idx, cio, p_manager); - len = opj_stream_tell(cio)-lenp; - opj_stream_skip(cio, lenp, p_manager); - opj_write_bytes(l_data_header,len,4);/* L */ - opj_stream_write_data(cio,l_data_header,4,p_manager); - opj_stream_seek(cio, lenp+len,p_manager); + len = opj_stream_tell(cio) - lenp; + opj_stream_skip(cio, lenp, p_manager); + opj_write_bytes(l_data_header, len, 4); /* L */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_stream_seek(cio, lenp + len, p_manager); - return len; + return len; } #endif #endif /* USE_JPIP */ diff --git a/third_party/libopenjpeg20/jp2.h b/third_party/libopenjpeg20/jp2.h index 94138832ac329b5edf01478ea96c4e0c61c5c214..34abd5118e3740a02c5692ee92aba3f1a7004431 100644 --- a/third_party/libopenjpeg20/jp2.h +++ b/third_party/libopenjpeg20/jp2.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2002-2003, Yannick Verschueren * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -33,8 +33,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __JP2_H -#define __JP2_H +#ifndef OPJ_JP2_H +#define OPJ_JP2_H /** @file jp2.h @brief The JPEG-2000 file format Reader/Writer (JP2) @@ -70,56 +70,50 @@ /* ----------------------------------------------------------------------- */ -typedef enum -{ - JP2_STATE_NONE = 0x0, - JP2_STATE_SIGNATURE = 0x1, - JP2_STATE_FILE_TYPE = 0x2, - JP2_STATE_HEADER = 0x4, - JP2_STATE_CODESTREAM = 0x8, - JP2_STATE_END_CODESTREAM = 0x10, - JP2_STATE_UNKNOWN = 0x7fffffff /* ISO C restricts enumerator values to range of 'int' */ +typedef enum { + JP2_STATE_NONE = 0x0, + JP2_STATE_SIGNATURE = 0x1, + JP2_STATE_FILE_TYPE = 0x2, + JP2_STATE_HEADER = 0x4, + JP2_STATE_CODESTREAM = 0x8, + JP2_STATE_END_CODESTREAM = 0x10, + JP2_STATE_UNKNOWN = 0x7fffffff /* ISO C restricts enumerator values to range of 'int' */ } JP2_STATE; -typedef enum -{ - JP2_IMG_STATE_NONE = 0x0, - JP2_IMG_STATE_UNKNOWN = 0x7fffffff +typedef enum { + JP2_IMG_STATE_NONE = 0x0, + JP2_IMG_STATE_UNKNOWN = 0x7fffffff } JP2_IMG_STATE; -/** +/** Channel description: channel index, type, association */ -typedef struct opj_jp2_cdef_info -{ +typedef struct opj_jp2_cdef_info { OPJ_UINT16 cn, typ, asoc; } opj_jp2_cdef_info_t; -/** +/** Channel descriptions and number of descriptions */ -typedef struct opj_jp2_cdef -{ +typedef struct opj_jp2_cdef { opj_jp2_cdef_info_t *info; OPJ_UINT16 n; } opj_jp2_cdef_t; -/** +/** Component mappings: channel index, mapping type, palette index */ -typedef struct opj_jp2_cmap_comp -{ +typedef struct opj_jp2_cmap_comp { OPJ_UINT16 cmp; OPJ_BYTE mtyp, pcol; } opj_jp2_cmap_comp_t; -/** +/** Palette data: table entries, palette columns */ -typedef struct opj_jp2_pclr -{ +typedef struct opj_jp2_pclr { OPJ_UINT32 *entries; OPJ_BYTE *channel_sign; OPJ_BYTE *channel_size; @@ -128,11 +122,10 @@ typedef struct opj_jp2_pclr OPJ_BYTE nr_channels; } opj_jp2_pclr_t; -/** -Collector for ICC profile, palette, component mapping, channel description +/** +Collector for ICC profile, palette, component mapping, channel description */ -typedef struct opj_jp2_color -{ +typedef struct opj_jp2_color { OPJ_BYTE *icc_profile_buf; OPJ_UINT32 icc_profile_len; @@ -141,60 +134,61 @@ typedef struct opj_jp2_color OPJ_BYTE jp2_has_colr; } opj_jp2_color_t; -/** +/** JP2 component */ typedef struct opj_jp2_comps { - OPJ_UINT32 depth; - OPJ_UINT32 sgnd; - OPJ_UINT32 bpcc; + OPJ_UINT32 depth; + OPJ_UINT32 sgnd; + OPJ_UINT32 bpcc; } opj_jp2_comps_t; /** JPEG-2000 file format reader/writer */ -typedef struct opj_jp2 -{ - /** handle to the J2K codec */ - opj_j2k_t *j2k; - /** list of validation procedures */ - struct opj_procedure_list * m_validation_list; - /** list of execution procedures */ - struct opj_procedure_list * m_procedure_list; - - /* width of image */ - OPJ_UINT32 w; - /* height of image */ - OPJ_UINT32 h; - /* number of components in the image */ - OPJ_UINT32 numcomps; - OPJ_UINT32 bpc; - OPJ_UINT32 C; - OPJ_UINT32 UnkC; - OPJ_UINT32 IPR; - OPJ_UINT32 meth; - OPJ_UINT32 approx; - OPJ_UINT32 enumcs; - OPJ_UINT32 precedence; - OPJ_UINT32 brand; - OPJ_UINT32 minversion; - OPJ_UINT32 numcl; - OPJ_UINT32 *cl; - opj_jp2_comps_t *comps; - /* FIXME: The following two variables are used to save offset - as we write out a JP2 file to disk. This mecanism is not flexible - as codec writers will need to extand those fields as new part - of the standard are implemented. - */ +typedef struct opj_jp2 { + /** handle to the J2K codec */ + opj_j2k_t *j2k; + /** list of validation procedures */ + struct opj_procedure_list * m_validation_list; + /** list of execution procedures */ + struct opj_procedure_list * m_procedure_list; + + /* width of image */ + OPJ_UINT32 w; + /* height of image */ + OPJ_UINT32 h; + /* number of components in the image */ + OPJ_UINT32 numcomps; + OPJ_UINT32 bpc; + OPJ_UINT32 C; + OPJ_UINT32 UnkC; + OPJ_UINT32 IPR; + OPJ_UINT32 meth; + OPJ_UINT32 approx; + OPJ_UINT32 enumcs; + OPJ_UINT32 precedence; + OPJ_UINT32 brand; + OPJ_UINT32 minversion; + OPJ_UINT32 numcl; + OPJ_UINT32 *cl; + opj_jp2_comps_t *comps; + /* FIXME: The following two variables are used to save offset + as we write out a JP2 file to disk. This mechanism is not flexible + as codec writers will need to extand those fields as new part + of the standard are implemented. + */ OPJ_OFF_T j2k_codestream_offset; OPJ_OFF_T jpip_iptr_offset; - OPJ_BOOL jpip_on; - OPJ_UINT32 jp2_state; - OPJ_UINT32 jp2_img_state; + OPJ_BOOL jpip_on; + OPJ_UINT32 jp2_state; + OPJ_UINT32 jp2_img_state; + + opj_jp2_color_t color; - opj_jp2_color_t color; - OPJ_BOOL ignore_pclr_cmap_cdef; + OPJ_BYTE has_jp2h; + OPJ_BYTE has_ihdr; } opj_jp2_t; @@ -207,28 +201,26 @@ typedef struct opj_jp2_box { OPJ_INT32 init_pos; } opj_jp2_box_t; -typedef struct opj_jp2_header_handler -{ - /* marker value */ - OPJ_UINT32 id; - /* action linked to the marker */ - OPJ_BOOL (*handler) ( opj_jp2_t *jp2, - OPJ_BYTE *p_header_data, - OPJ_UINT32 p_header_size, - opj_event_mgr_t * p_manager); +typedef struct opj_jp2_header_handler { + /* marker value */ + OPJ_UINT32 id; + /* action linked to the marker */ + OPJ_BOOL(*handler)(opj_jp2_t *jp2, + OPJ_BYTE *p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); } opj_jp2_header_handler_t; -typedef struct opj_jp2_img_header_writer_handler -{ - /* action to perform */ - OPJ_BYTE* (*handler) (opj_jp2_t *jp2, OPJ_UINT32 * p_data_size); - /* result of the action : data */ - OPJ_BYTE* m_data; - /* size of data */ - OPJ_UINT32 m_size; -} +typedef struct opj_jp2_img_header_writer_handler { + /* action to perform */ + OPJ_BYTE* (*handler)(opj_jp2_t *jp2, OPJ_UINT32 * p_data_size); + /* result of the action : data */ + OPJ_BYTE* m_data; + /* size of data */ + OPJ_UINT32 m_size; +} opj_jp2_img_header_writer_handler_t; /** @name Exported functions */ @@ -243,6 +235,14 @@ Decoding parameters are returned in jp2->j2k->cp. */ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters); +/** Allocates worker threads for the compressor/decompressor. + * + * @param jp2 JP2 decompressor handle + * @param num_threads Number of threads. + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads); + /** * Decode an image from a JPEG-2000 file stream * @param jp2 JP2 decompressor handle @@ -254,12 +254,12 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters); */ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager); + opj_image_t* p_image, + opj_event_mgr_t * p_manager); /** - * Setup the encoder parameters using the current image and using user parameters. - * Coding parameters are returned in jp2->j2k->cp. + * Setup the encoder parameters using the current image and using user parameters. + * Coding parameters are returned in jp2->j2k->cp. * * @param jp2 JP2 compressor handle * @param parameters compression parameters @@ -267,10 +267,10 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, * @param p_manager FIXME DOC * @return OPJ_TRUE if successful, OPJ_FALSE otherwise */ -OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2, - opj_cparameters_t *parameters, - opj_image_t *image, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager); /** Encode an image into a JPEG-2000 file stream @@ -279,9 +279,9 @@ Encode an image into a JPEG-2000 file stream @param p_manager event manager @return Returns true if successful, returns false otherwise */ -OPJ_BOOL opj_jp2_encode( opj_jp2_t *jp2, - opj_stream_private_t *stream, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); /** @@ -304,9 +304,9 @@ OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2, * Ends the compression procedures and possibiliy add data to be read after the * codestream. */ -OPJ_BOOL opj_jp2_end_compress( opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_jp2_end_compress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); /* ----------------------------------------------------------------------- */ @@ -314,7 +314,7 @@ OPJ_BOOL opj_jp2_end_compress( opj_jp2_t *jp2, * Ends the decompression procedures and possibiliy add data to be read after the * codestream. */ -OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, +OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, opj_stream_private_t *cio, opj_event_mgr_t * p_manager); @@ -328,10 +328,25 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, * * @return true if the box is valid. */ -OPJ_BOOL opj_jp2_read_header( opj_stream_private_t *p_stream, - opj_jp2_t *jp2, - opj_image_t ** p_image, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, + opj_jp2_t *jp2, + opj_image_t ** p_image, + opj_event_mgr_t * p_manager); + +/** Sets the indices of the components to decode. + * + * @param jp2 JP2 decompressor handle + * @param numcomps Number of components to decode. + * @param comps_indices Array of num_compts indices (numbering starting at 0) + * corresponding to the components to decode. + * @param p_manager Event manager; + * + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *jp2, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager); /** * Reads a tile header. @@ -347,17 +362,17 @@ OPJ_BOOL opj_jp2_read_header( opj_stream_private_t *p_stream, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -OPJ_BOOL opj_jp2_read_tile_header ( opj_jp2_t * p_jp2, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Writes a tile. @@ -369,12 +384,12 @@ OPJ_BOOL opj_jp2_read_tile_header ( opj_jp2_t * p_jp2, * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -OPJ_BOOL opj_jp2_write_tile ( opj_jp2_t *p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Decode tile data. @@ -387,19 +402,19 @@ OPJ_BOOL opj_jp2_write_tile ( opj_jp2_t *p_jp2, * * @return FIXME DOC */ -OPJ_BOOL opj_jp2_decode_tile ( opj_jp2_t * p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Creates a jpeg2000 file decompressor. * * @return an empty jpeg2000 file codec. */ -opj_jp2_t* opj_jp2_create (OPJ_BOOL p_is_decoder); +opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder); /** Destroy a JP2 decompressor handle @@ -421,28 +436,28 @@ void opj_jp2_destroy(opj_jp2_t *jp2); * * @return true if the area could be set. */ -OPJ_BOOL opj_jp2_set_decode_area( opj_jp2_t *p_jp2, - opj_image_t* p_image, - OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, - opj_event_mgr_t * p_manager ); - - /** - * - */ -OPJ_BOOL opj_jp2_get_tile( opj_jp2_t *p_jp2, - opj_stream_private_t *p_stream, - opj_image_t* p_image, - opj_event_mgr_t * p_manager, - OPJ_UINT32 tile_index ); +OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager); + +/** +* +*/ +OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index); /** - * + * */ -OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2, - OPJ_UINT32 res_factor, - opj_event_mgr_t * p_manager); +OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager); /* TODO MSD: clean these 3 functions */ @@ -450,11 +465,11 @@ OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2, * Dump some elements from the JP2 decompression structure . * *@param p_jp2 the jp2 codec. - *@param flag flag to describe what elments are dump. + *@param flag flag to describe what elements are dump. *@param out_stream output stream where dump the elements. * */ -void jp2_dump (opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream); +void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream); /** * Get the codestream info from a JPEG2000 codec. @@ -479,5 +494,5 @@ opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2); /*@}*/ -#endif /* __JP2_H */ +#endif /* OPJ_JP2_H */ diff --git a/third_party/libopenjpeg20/mct.c b/third_party/libopenjpeg20/mct.c index 7731c15ddb131e51023576ec89f2660783bc0c38..81ec223d85a755807ddbba281c3dfc4e14a21a78 100644 --- a/third_party/libopenjpeg20/mct.c +++ b/third_party/libopenjpeg20/mct.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,10 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -62,14 +62,14 @@ static const OPJ_FLOAT64 opj_mct_norms[3] = { 1.732, .8292, .8292 }; /* </summary> */ static const OPJ_FLOAT64 opj_mct_norms_real[3] = { 1.732, 1.805, 1.573 }; -const OPJ_FLOAT64 * opj_mct_get_mct_norms () +const OPJ_FLOAT64 * opj_mct_get_mct_norms() { - return opj_mct_norms; + return opj_mct_norms; } -const OPJ_FLOAT64 * opj_mct_get_mct_norms_real () +const OPJ_FLOAT64 * opj_mct_get_mct_norms_real() { - return opj_mct_norms_real; + return opj_mct_norms_real; } /* <summary> */ @@ -77,63 +77,67 @@ const OPJ_FLOAT64 * opj_mct_get_mct_norms_real () /* </summary> */ #ifdef USE_SSE2 void opj_mct_encode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_SIZE_T i; - const OPJ_SIZE_T len = n; - - for(i = 0; i < (len & ~3U); i += 4) { - __m128i y, u, v; - __m128i r = _mm_load_si128((const __m128i *)&(c0[i])); - __m128i g = _mm_load_si128((const __m128i *)&(c1[i])); - __m128i b = _mm_load_si128((const __m128i *)&(c2[i])); - y = _mm_add_epi32(g, g); - y = _mm_add_epi32(y, b); - y = _mm_add_epi32(y, r); - y = _mm_srai_epi32(y, 2); - u = _mm_sub_epi32(b, g); - v = _mm_sub_epi32(r, g); - _mm_store_si128((__m128i *)&(c0[i]), y); - _mm_store_si128((__m128i *)&(c1[i]), u); - _mm_store_si128((__m128i *)&(c2[i]), v); - } - - for(; i < len; ++i) { - OPJ_INT32 r = c0[i]; - OPJ_INT32 g = c1[i]; - OPJ_INT32 b = c2[i]; - OPJ_INT32 y = (r + (g * 2) + b) >> 2; - OPJ_INT32 u = b - g; - OPJ_INT32 v = r - g; - c0[i] = y; - c1[i] = u; - c2[i] = v; - } + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + /* buffer are aligned on 16 bytes */ + assert(((size_t)c0 & 0xf) == 0); + assert(((size_t)c1 & 0xf) == 0); + assert(((size_t)c2 & 0xf) == 0); + + for (i = 0; i < (len & ~3U); i += 4) { + __m128i y, u, v; + __m128i r = _mm_load_si128((const __m128i *) & (c0[i])); + __m128i g = _mm_load_si128((const __m128i *) & (c1[i])); + __m128i b = _mm_load_si128((const __m128i *) & (c2[i])); + y = _mm_add_epi32(g, g); + y = _mm_add_epi32(y, b); + y = _mm_add_epi32(y, r); + y = _mm_srai_epi32(y, 2); + u = _mm_sub_epi32(b, g); + v = _mm_sub_epi32(r, g); + _mm_store_si128((__m128i *) & (c0[i]), y); + _mm_store_si128((__m128i *) & (c1[i]), u); + _mm_store_si128((__m128i *) & (c2[i]), v); + } + + for (; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = (r + (g * 2) + b) >> 2; + OPJ_INT32 u = b - g; + OPJ_INT32 v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } } #else void opj_mct_encode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_SIZE_T i; - const OPJ_SIZE_T len = n; - - for(i = 0; i < len; ++i) { - OPJ_INT32 r = c0[i]; - OPJ_INT32 g = c1[i]; - OPJ_INT32 b = c2[i]; - OPJ_INT32 y = (r + (g * 2) + b) >> 2; - OPJ_INT32 u = b - g; - OPJ_INT32 v = r - g; - c0[i] = y; - c1[i] = u; - c2[i] = v; - } + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for (i = 0; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = (r + (g * 2) + b) >> 2; + OPJ_INT32 u = b - g; + OPJ_INT32 v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } } #endif @@ -142,66 +146,67 @@ void opj_mct_encode( /* </summary> */ #ifdef USE_SSE2 void opj_mct_decode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_SIZE_T i; - const OPJ_SIZE_T len = n; - - for(i = 0; i < (len & ~3U); i += 4) { - __m128i r, g, b; - __m128i y = _mm_load_si128((const __m128i *)&(c0[i])); - __m128i u = _mm_load_si128((const __m128i *)&(c1[i])); - __m128i v = _mm_load_si128((const __m128i *)&(c2[i])); - g = y; - g = _mm_sub_epi32(g, _mm_srai_epi32(_mm_add_epi32(u, v), 2)); - r = _mm_add_epi32(v, g); - b = _mm_add_epi32(u, g); - _mm_store_si128((__m128i *)&(c0[i]), r); - _mm_store_si128((__m128i *)&(c1[i]), g); - _mm_store_si128((__m128i *)&(c2[i]), b); - } - for (; i < len; ++i) { - OPJ_INT32 y = c0[i]; - OPJ_INT32 u = c1[i]; - OPJ_INT32 v = c2[i]; - OPJ_INT32 g = y - ((u + v) >> 2); - OPJ_INT32 r = v + g; - OPJ_INT32 b = u + g; - c0[i] = r; - c1[i] = g; - c2[i] = b; - } + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for (i = 0; i < (len & ~3U); i += 4) { + __m128i r, g, b; + __m128i y = _mm_load_si128((const __m128i *) & (c0[i])); + __m128i u = _mm_load_si128((const __m128i *) & (c1[i])); + __m128i v = _mm_load_si128((const __m128i *) & (c2[i])); + g = y; + g = _mm_sub_epi32(g, _mm_srai_epi32(_mm_add_epi32(u, v), 2)); + r = _mm_add_epi32(v, g); + b = _mm_add_epi32(u, g); + _mm_store_si128((__m128i *) & (c0[i]), r); + _mm_store_si128((__m128i *) & (c1[i]), g); + _mm_store_si128((__m128i *) & (c2[i]), b); + } + for (; i < len; ++i) { + OPJ_INT32 y = c0[i]; + OPJ_INT32 u = c1[i]; + OPJ_INT32 v = c2[i]; + OPJ_INT32 g = y - ((u + v) >> 2); + OPJ_INT32 r = v + g; + OPJ_INT32 b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } } #else void opj_mct_decode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_UINT32 i; - for (i = 0; i < n; ++i) { - OPJ_INT32 y = c0[i]; - OPJ_INT32 u = c1[i]; - OPJ_INT32 v = c2[i]; - OPJ_INT32 g = y - ((u + v) >> 2); - OPJ_INT32 r = v + g; - OPJ_INT32 b = u + g; - c0[i] = r; - c1[i] = g; - c2[i] = b; - } + OPJ_UINT32 i; + for (i = 0; i < n; ++i) { + OPJ_INT32 y = c0[i]; + OPJ_INT32 u = c1[i]; + OPJ_INT32 v = c2[i]; + OPJ_INT32 g = y - ((u + v) >> 2); + OPJ_INT32 r = v + g; + OPJ_INT32 b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } } #endif /* <summary> */ /* Get norm of basis function of reversible MCT. */ /* </summary> */ -OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) { - return opj_mct_norms[compno]; +OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) +{ + return opj_mct_norms[compno]; } /* <summary> */ @@ -209,164 +214,171 @@ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) { /* </summary> */ #ifdef USE_SSE4 void opj_mct_encode_real( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_SIZE_T i; - const OPJ_SIZE_T len = n; - - const __m128i ry = _mm_set1_epi32(2449); - const __m128i gy = _mm_set1_epi32(4809); - const __m128i by = _mm_set1_epi32(934); - const __m128i ru = _mm_set1_epi32(1382); - const __m128i gu = _mm_set1_epi32(2714); - /* const __m128i bu = _mm_set1_epi32(4096); */ - /* const __m128i rv = _mm_set1_epi32(4096); */ - const __m128i gv = _mm_set1_epi32(3430); - const __m128i bv = _mm_set1_epi32(666); - const __m128i mulround = _mm_shuffle_epi32(_mm_cvtsi32_si128(4096), _MM_SHUFFLE(1, 0, 1, 0)); - - for(i = 0; i < (len & ~3U); i += 4) { - __m128i lo, hi; - __m128i y, u, v; - __m128i r = _mm_load_si128((const __m128i *)&(c0[i])); - __m128i g = _mm_load_si128((const __m128i *)&(c1[i])); - __m128i b = _mm_load_si128((const __m128i *)&(c2[i])); - - lo = r; - hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, ry); - hi = _mm_mul_epi32(hi, ry); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - y = _mm_blend_epi16(lo, hi, 0xCC); - - lo = g; - hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, gy); - hi = _mm_mul_epi32(hi, gy); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); - - lo = b; - hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, by); - hi = _mm_mul_epi32(hi, by); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); - _mm_store_si128((__m128i *)&(c0[i]), y); - - /*lo = b; - hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, mulround); - hi = _mm_mul_epi32(hi, mulround);*/ - lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 2, 0))); - hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 3, 1))); - lo = _mm_slli_epi64(lo, 12); - hi = _mm_slli_epi64(hi, 12); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - u = _mm_blend_epi16(lo, hi, 0xCC); - - lo = r; - hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, ru); - hi = _mm_mul_epi32(hi, ru); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); - - lo = g; - hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, gu); - hi = _mm_mul_epi32(hi, gu); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); - _mm_store_si128((__m128i *)&(c1[i]), u); - - /*lo = r; - hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, mulround); - hi = _mm_mul_epi32(hi, mulround);*/ - lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 2, 0))); - hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 3, 1))); - lo = _mm_slli_epi64(lo, 12); - hi = _mm_slli_epi64(hi, 12); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - v = _mm_blend_epi16(lo, hi, 0xCC); - - lo = g; - hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, gv); - hi = _mm_mul_epi32(hi, gv); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); - - lo = b; - hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); - lo = _mm_mul_epi32(lo, bv); - hi = _mm_mul_epi32(hi, bv); - lo = _mm_add_epi64(lo, mulround); - hi = _mm_add_epi64(hi, mulround); - lo = _mm_srli_epi64(lo, 13); - hi = _mm_slli_epi64(hi, 32-13); - v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); - _mm_store_si128((__m128i *)&(c2[i]), v); - } - for(; i < len; ++i) { - OPJ_INT32 r = c0[i]; - OPJ_INT32 g = c1[i]; - OPJ_INT32 b = c2[i]; - OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g, 4809) + opj_int_fix_mul(b, 934); - OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g, 2714) + opj_int_fix_mul(b, 4096); - OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g, 3430) - opj_int_fix_mul(b, 666); - c0[i] = y; - c1[i] = u; - c2[i] = v; - } + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + const __m128i ry = _mm_set1_epi32(2449); + const __m128i gy = _mm_set1_epi32(4809); + const __m128i by = _mm_set1_epi32(934); + const __m128i ru = _mm_set1_epi32(1382); + const __m128i gu = _mm_set1_epi32(2714); + /* const __m128i bu = _mm_set1_epi32(4096); */ + /* const __m128i rv = _mm_set1_epi32(4096); */ + const __m128i gv = _mm_set1_epi32(3430); + const __m128i bv = _mm_set1_epi32(666); + const __m128i mulround = _mm_shuffle_epi32(_mm_cvtsi32_si128(4096), + _MM_SHUFFLE(1, 0, 1, 0)); + + for (i = 0; i < (len & ~3U); i += 4) { + __m128i lo, hi; + __m128i y, u, v; + __m128i r = _mm_load_si128((const __m128i *) & (c0[i])); + __m128i g = _mm_load_si128((const __m128i *) & (c1[i])); + __m128i b = _mm_load_si128((const __m128i *) & (c2[i])); + + lo = r; + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, ry); + hi = _mm_mul_epi32(hi, ry); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + y = _mm_blend_epi16(lo, hi, 0xCC); + + lo = g; + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, gy); + hi = _mm_mul_epi32(hi, gy); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); + + lo = b; + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, by); + hi = _mm_mul_epi32(hi, by); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + y = _mm_add_epi32(y, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i *) & (c0[i]), y); + + /*lo = b; + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, mulround); + hi = _mm_mul_epi32(hi, mulround);*/ + lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 2, 0))); + hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(b, _MM_SHUFFLE(3, 2, 3, 1))); + lo = _mm_slli_epi64(lo, 12); + hi = _mm_slli_epi64(hi, 12); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + u = _mm_blend_epi16(lo, hi, 0xCC); + + lo = r; + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, ru); + hi = _mm_mul_epi32(hi, ru); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); + + lo = g; + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, gu); + hi = _mm_mul_epi32(hi, gu); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + u = _mm_sub_epi32(u, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i *) & (c1[i]), u); + + /*lo = r; + hi = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, mulround); + hi = _mm_mul_epi32(hi, mulround);*/ + lo = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 2, 0))); + hi = _mm_cvtepi32_epi64(_mm_shuffle_epi32(r, _MM_SHUFFLE(3, 2, 3, 1))); + lo = _mm_slli_epi64(lo, 12); + hi = _mm_slli_epi64(hi, 12); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + v = _mm_blend_epi16(lo, hi, 0xCC); + + lo = g; + hi = _mm_shuffle_epi32(g, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, gv); + hi = _mm_mul_epi32(hi, gv); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); + + lo = b; + hi = _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 1, 1)); + lo = _mm_mul_epi32(lo, bv); + hi = _mm_mul_epi32(hi, bv); + lo = _mm_add_epi64(lo, mulround); + hi = _mm_add_epi64(hi, mulround); + lo = _mm_srli_epi64(lo, 13); + hi = _mm_slli_epi64(hi, 32 - 13); + v = _mm_sub_epi32(v, _mm_blend_epi16(lo, hi, 0xCC)); + _mm_store_si128((__m128i *) & (c2[i]), v); + } + for (; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g, + 4809) + opj_int_fix_mul(b, 934); + OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g, + 2714) + opj_int_fix_mul(b, 4096); + OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g, + 3430) - opj_int_fix_mul(b, 666); + c0[i] = y; + c1[i] = u; + c2[i] = v; + } } #else void opj_mct_encode_real( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_UINT32 i; - for(i = 0; i < n; ++i) { - OPJ_INT32 r = c0[i]; - OPJ_INT32 g = c1[i]; - OPJ_INT32 b = c2[i]; - OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g, 4809) + opj_int_fix_mul(b, 934); - OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g, 2714) + opj_int_fix_mul(b, 4096); - OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g, 3430) - opj_int_fix_mul(b, 666); - c0[i] = y; - c1[i] = u; - c2[i] = v; - } + OPJ_UINT32 i; + for (i = 0; i < n; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = opj_int_fix_mul(r, 2449) + opj_int_fix_mul(g, + 4809) + opj_int_fix_mul(b, 934); + OPJ_INT32 u = -opj_int_fix_mul(r, 1382) - opj_int_fix_mul(g, + 2714) + opj_int_fix_mul(b, 4096); + OPJ_INT32 v = opj_int_fix_mul(r, 4096) - opj_int_fix_mul(g, + 3430) - opj_int_fix_mul(b, 666); + c0[i] = y; + c1[i] = u; + c2[i] = v; + } } #endif @@ -374,183 +386,185 @@ void opj_mct_encode_real( /* Inverse irreversible MCT. */ /* </summary> */ void opj_mct_decode_real( - OPJ_FLOAT32* restrict c0, - OPJ_FLOAT32* restrict c1, - OPJ_FLOAT32* restrict c2, - OPJ_UINT32 n) + OPJ_FLOAT32* OPJ_RESTRICT c0, + OPJ_FLOAT32* OPJ_RESTRICT c1, + OPJ_FLOAT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) { - OPJ_UINT32 i; + OPJ_UINT32 i; #ifdef USE_SSE - __m128 vrv, vgu, vgv, vbu; - vrv = _mm_set1_ps(1.402f); - vgu = _mm_set1_ps(0.34413f); - vgv = _mm_set1_ps(0.71414f); - vbu = _mm_set1_ps(1.772f); - for (i = 0; i < (n >> 3); ++i) { - __m128 vy, vu, vv; - __m128 vr, vg, vb; - - vy = _mm_load_ps(c0); - vu = _mm_load_ps(c1); - vv = _mm_load_ps(c2); - vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); - vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); - vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); - _mm_store_ps(c0, vr); - _mm_store_ps(c1, vg); - _mm_store_ps(c2, vb); - c0 += 4; - c1 += 4; - c2 += 4; - - vy = _mm_load_ps(c0); - vu = _mm_load_ps(c1); - vv = _mm_load_ps(c2); - vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); - vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); - vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); - _mm_store_ps(c0, vr); - _mm_store_ps(c1, vg); - _mm_store_ps(c2, vb); - c0 += 4; - c1 += 4; - c2 += 4; - } - n &= 7; + __m128 vrv, vgu, vgv, vbu; + vrv = _mm_set1_ps(1.402f); + vgu = _mm_set1_ps(0.34413f); + vgv = _mm_set1_ps(0.71414f); + vbu = _mm_set1_ps(1.772f); + for (i = 0; i < (n >> 3); ++i) { + __m128 vy, vu, vv; + __m128 vr, vg, vb; + + vy = _mm_load_ps(c0); + vu = _mm_load_ps(c1); + vv = _mm_load_ps(c2); + vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); + vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); + vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); + _mm_store_ps(c0, vr); + _mm_store_ps(c1, vg); + _mm_store_ps(c2, vb); + c0 += 4; + c1 += 4; + c2 += 4; + + vy = _mm_load_ps(c0); + vu = _mm_load_ps(c1); + vv = _mm_load_ps(c2); + vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); + vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); + vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); + _mm_store_ps(c0, vr); + _mm_store_ps(c1, vg); + _mm_store_ps(c2, vb); + c0 += 4; + c1 += 4; + c2 += 4; + } + n &= 7; #endif - for(i = 0; i < n; ++i) { - OPJ_FLOAT32 y = c0[i]; - OPJ_FLOAT32 u = c1[i]; - OPJ_FLOAT32 v = c2[i]; - OPJ_FLOAT32 r = y + (v * 1.402f); - OPJ_FLOAT32 g = y - (u * 0.34413f) - (v * (0.71414f)); - OPJ_FLOAT32 b = y + (u * 1.772f); - c0[i] = r; - c1[i] = g; - c2[i] = b; - } + for (i = 0; i < n; ++i) { + OPJ_FLOAT32 y = c0[i]; + OPJ_FLOAT32 u = c1[i]; + OPJ_FLOAT32 v = c2[i]; + OPJ_FLOAT32 r = y + (v * 1.402f); + OPJ_FLOAT32 g = y - (u * 0.34413f) - (v * (0.71414f)); + OPJ_FLOAT32 b = y + (u * 1.772f); + c0[i] = r; + c1[i] = g; + c2[i] = b; + } } /* <summary> */ /* Get norm of basis function of irreversible MCT. */ /* </summary> */ -OPJ_FLOAT64 opj_mct_getnorm_real(OPJ_UINT32 compno) { - return opj_mct_norms_real[compno]; +OPJ_FLOAT64 opj_mct_getnorm_real(OPJ_UINT32 compno) +{ + return opj_mct_norms_real[compno]; } OPJ_BOOL opj_mct_encode_custom( - OPJ_BYTE * pCodingdata, - OPJ_UINT32 n, - OPJ_BYTE ** pData, - OPJ_UINT32 pNbComp, - OPJ_UINT32 isSigned) + OPJ_BYTE * pCodingdata, + OPJ_SIZE_T n, + OPJ_BYTE ** pData, + OPJ_UINT32 pNbComp, + OPJ_UINT32 isSigned) { - OPJ_FLOAT32 * lMct = (OPJ_FLOAT32 *) pCodingdata; - OPJ_UINT32 i; - OPJ_UINT32 j; - OPJ_UINT32 k; - OPJ_UINT32 lNbMatCoeff = pNbComp * pNbComp; - OPJ_INT32 * lCurrentData = 00; - OPJ_INT32 * lCurrentMatrix = 00; - OPJ_INT32 ** lData = (OPJ_INT32 **) pData; - OPJ_UINT32 lMultiplicator = 1 << 13; - OPJ_INT32 * lMctPtr; + OPJ_FLOAT32 * lMct = (OPJ_FLOAT32 *) pCodingdata; + OPJ_SIZE_T i; + OPJ_UINT32 j; + OPJ_UINT32 k; + OPJ_UINT32 lNbMatCoeff = pNbComp * pNbComp; + OPJ_INT32 * lCurrentData = 00; + OPJ_INT32 * lCurrentMatrix = 00; + OPJ_INT32 ** lData = (OPJ_INT32 **) pData; + OPJ_UINT32 lMultiplicator = 1 << 13; + OPJ_INT32 * lMctPtr; OPJ_ARG_NOT_USED(isSigned); - lCurrentData = (OPJ_INT32 *) opj_malloc((pNbComp + lNbMatCoeff) * sizeof(OPJ_INT32)); - if (! lCurrentData) { - return OPJ_FALSE; - } + lCurrentData = (OPJ_INT32 *) opj_malloc((pNbComp + lNbMatCoeff) * sizeof( + OPJ_INT32)); + if (! lCurrentData) { + return OPJ_FALSE; + } - lCurrentMatrix = lCurrentData + pNbComp; + lCurrentMatrix = lCurrentData + pNbComp; - for (i =0;i<lNbMatCoeff;++i) { - lCurrentMatrix[i] = (OPJ_INT32) (*(lMct++) * (OPJ_FLOAT32)lMultiplicator); - } + for (i = 0; i < lNbMatCoeff; ++i) { + lCurrentMatrix[i] = (OPJ_INT32)(*(lMct++) * (OPJ_FLOAT32)lMultiplicator); + } - for (i = 0; i < n; ++i) { - lMctPtr = lCurrentMatrix; - for (j=0;j<pNbComp;++j) { - lCurrentData[j] = (*(lData[j])); - } + for (i = 0; i < n; ++i) { + lMctPtr = lCurrentMatrix; + for (j = 0; j < pNbComp; ++j) { + lCurrentData[j] = (*(lData[j])); + } - for (j=0;j<pNbComp;++j) { - *(lData[j]) = 0; - for (k=0;k<pNbComp;++k) { - *(lData[j]) += opj_int_fix_mul(*lMctPtr, lCurrentData[k]); - ++lMctPtr; - } + for (j = 0; j < pNbComp; ++j) { + *(lData[j]) = 0; + for (k = 0; k < pNbComp; ++k) { + *(lData[j]) += opj_int_fix_mul(*lMctPtr, lCurrentData[k]); + ++lMctPtr; + } - ++lData[j]; - } - } + ++lData[j]; + } + } - opj_free(lCurrentData); + opj_free(lCurrentData); - return OPJ_TRUE; + return OPJ_TRUE; } OPJ_BOOL opj_mct_decode_custom( - OPJ_BYTE * pDecodingData, - OPJ_UINT32 n, - OPJ_BYTE ** pData, - OPJ_UINT32 pNbComp, - OPJ_UINT32 isSigned) + OPJ_BYTE * pDecodingData, + OPJ_SIZE_T n, + OPJ_BYTE ** pData, + OPJ_UINT32 pNbComp, + OPJ_UINT32 isSigned) { - OPJ_FLOAT32 * lMct; - OPJ_UINT32 i; - OPJ_UINT32 j; - OPJ_UINT32 k; + OPJ_FLOAT32 * lMct; + OPJ_SIZE_T i; + OPJ_UINT32 j; + OPJ_UINT32 k; - OPJ_FLOAT32 * lCurrentData = 00; - OPJ_FLOAT32 * lCurrentResult = 00; - OPJ_FLOAT32 ** lData = (OPJ_FLOAT32 **) pData; + OPJ_FLOAT32 * lCurrentData = 00; + OPJ_FLOAT32 * lCurrentResult = 00; + OPJ_FLOAT32 ** lData = (OPJ_FLOAT32 **) pData; OPJ_ARG_NOT_USED(isSigned); - lCurrentData = (OPJ_FLOAT32 *) opj_malloc (2 * pNbComp * sizeof(OPJ_FLOAT32)); - if (! lCurrentData) { - return OPJ_FALSE; - } - lCurrentResult = lCurrentData + pNbComp; - - for (i = 0; i < n; ++i) { - lMct = (OPJ_FLOAT32 *) pDecodingData; - for (j=0;j<pNbComp;++j) { - lCurrentData[j] = (OPJ_FLOAT32) (*(lData[j])); - } - for (j=0;j<pNbComp;++j) { - lCurrentResult[j] = 0; - for (k=0;k<pNbComp;++k) { - lCurrentResult[j] += *(lMct++) * lCurrentData[k]; - } - *(lData[j]++) = (OPJ_FLOAT32) (lCurrentResult[j]); - } - } - opj_free(lCurrentData); - return OPJ_TRUE; + lCurrentData = (OPJ_FLOAT32 *) opj_malloc(2 * pNbComp * sizeof(OPJ_FLOAT32)); + if (! lCurrentData) { + return OPJ_FALSE; + } + lCurrentResult = lCurrentData + pNbComp; + + for (i = 0; i < n; ++i) { + lMct = (OPJ_FLOAT32 *) pDecodingData; + for (j = 0; j < pNbComp; ++j) { + lCurrentData[j] = (OPJ_FLOAT32)(*(lData[j])); + } + for (j = 0; j < pNbComp; ++j) { + lCurrentResult[j] = 0; + for (k = 0; k < pNbComp; ++k) { + lCurrentResult[j] += *(lMct++) * lCurrentData[k]; + } + *(lData[j]++) = (OPJ_FLOAT32)(lCurrentResult[j]); + } + } + opj_free(lCurrentData); + return OPJ_TRUE; } -void opj_calculate_norms( OPJ_FLOAT64 * pNorms, - OPJ_UINT32 pNbComps, - OPJ_FLOAT32 * pMatrix) +void opj_calculate_norms(OPJ_FLOAT64 * pNorms, + OPJ_UINT32 pNbComps, + OPJ_FLOAT32 * pMatrix) { - OPJ_UINT32 i,j,lIndex; - OPJ_FLOAT32 lCurrentValue; - OPJ_FLOAT64 * lNorms = (OPJ_FLOAT64 *) pNorms; - OPJ_FLOAT32 * lMatrix = (OPJ_FLOAT32 *) pMatrix; - - for (i=0;i<pNbComps;++i) { - lNorms[i] = 0; - lIndex = i; - - for (j=0;j<pNbComps;++j) { - lCurrentValue = lMatrix[lIndex]; - lIndex += pNbComps; - lNorms[i] += lCurrentValue * lCurrentValue; - } - lNorms[i] = sqrt(lNorms[i]); - } + OPJ_UINT32 i, j, lIndex; + OPJ_FLOAT32 lCurrentValue; + OPJ_FLOAT64 * lNorms = (OPJ_FLOAT64 *) pNorms; + OPJ_FLOAT32 * lMatrix = (OPJ_FLOAT32 *) pMatrix; + + for (i = 0; i < pNbComps; ++i) { + lNorms[i] = 0; + lIndex = i; + + for (j = 0; j < pNbComps; ++j) { + lCurrentValue = lMatrix[lIndex]; + lIndex += pNbComps; + lNorms[i] += lCurrentValue * lCurrentValue; + } + lNorms[i] = sqrt(lNorms[i]); + } } diff --git a/third_party/libopenjpeg20/mct.h b/third_party/libopenjpeg20/mct.h index 1c1f4d0c4da94cbdbef8280ddacedb2aced8d568..2e37ce7333f85083d683e510e2107b92b73f5d06 100644 --- a/third_party/libopenjpeg20/mct.h +++ b/third_party/libopenjpeg20/mct.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,10 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -37,8 +37,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __MCT_H -#define __MCT_H +#ifndef OPJ_MCT_H +#define OPJ_MCT_H /** @file mct.h @brief Implementation of a multi-component transforms (MCT) @@ -60,7 +60,8 @@ Apply a reversible multi-component transform to an image @param c2 Samples blue component @param n Number of samples for each component */ -void opj_mct_encode(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 n); +void opj_mct_encode(OPJ_INT32* OPJ_RESTRICT c0, OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); /** Apply a reversible multi-component inverse transform to an image @param c0 Samples for luminance component @@ -68,11 +69,12 @@ Apply a reversible multi-component inverse transform to an image @param c2 Samples for blue chrominance component @param n Number of samples for each component */ -void opj_mct_decode(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 n); +void opj_mct_decode(OPJ_INT32* OPJ_RESTRICT c0, OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); /** Get norm of the basis function used for the reversible multi-component transform @param compno Number of the component (0->Y, 1->U, 2->V) -@return +@return */ OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno); @@ -83,7 +85,8 @@ Apply an irreversible multi-component transform to an image @param c2 Samples blue component @param n Number of samples for each component */ -void opj_mct_encode_real(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 n); +void opj_mct_encode_real(OPJ_INT32* OPJ_RESTRICT c0, OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); /** Apply an irreversible multi-component inverse transform to an image @param c0 Samples for luminance component @@ -91,11 +94,12 @@ Apply an irreversible multi-component inverse transform to an image @param c2 Samples for blue chrominance component @param n Number of samples for each component */ -void opj_mct_decode_real(OPJ_FLOAT32* c0, OPJ_FLOAT32* c1, OPJ_FLOAT32* c2, OPJ_UINT32 n); +void opj_mct_decode_real(OPJ_FLOAT32* OPJ_RESTRICT c0, + OPJ_FLOAT32* OPJ_RESTRICT c1, OPJ_FLOAT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); /** Get norm of the basis function used for the irreversible multi-component transform @param compno Number of the component (0->Y, 1->U, 2->V) -@return +@return */ OPJ_FLOAT64 opj_mct_getnorm_real(OPJ_UINT32 compno); @@ -109,11 +113,11 @@ FIXME DOC @return OPJ_FALSE if function encounter a problem, OPJ_TRUE otherwise */ OPJ_BOOL opj_mct_encode_custom( - OPJ_BYTE * p_coding_data, - OPJ_UINT32 n, - OPJ_BYTE ** p_data, - OPJ_UINT32 p_nb_comp, - OPJ_UINT32 is_signed); + OPJ_BYTE * p_coding_data, + OPJ_SIZE_T n, + OPJ_BYTE ** p_data, + OPJ_UINT32 p_nb_comp, + OPJ_UINT32 is_signed); /** FIXME DOC @param pDecodingData MCT data @@ -124,32 +128,32 @@ FIXME DOC @return OPJ_FALSE if function encounter a problem, OPJ_TRUE otherwise */ OPJ_BOOL opj_mct_decode_custom( - OPJ_BYTE * pDecodingData, - OPJ_UINT32 n, - OPJ_BYTE ** pData, - OPJ_UINT32 pNbComp, - OPJ_UINT32 isSigned); + OPJ_BYTE * pDecodingData, + OPJ_SIZE_T n, + OPJ_BYTE ** pData, + OPJ_UINT32 pNbComp, + OPJ_UINT32 isSigned); /** FIXME DOC @param pNorms MCT data @param p_nb_comps size of components @param pMatrix components -@return +@return */ -void opj_calculate_norms( OPJ_FLOAT64 * pNorms, - OPJ_UINT32 p_nb_comps, - OPJ_FLOAT32 * pMatrix); +void opj_calculate_norms(OPJ_FLOAT64 * pNorms, + OPJ_UINT32 p_nb_comps, + OPJ_FLOAT32 * pMatrix); /** -FIXME DOC +FIXME DOC */ -const OPJ_FLOAT64 * opj_mct_get_mct_norms (void); +const OPJ_FLOAT64 * opj_mct_get_mct_norms(void); /** -FIXME DOC +FIXME DOC */ -const OPJ_FLOAT64 * opj_mct_get_mct_norms_real (void); +const OPJ_FLOAT64 * opj_mct_get_mct_norms_real(void); /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ -#endif /* __MCT_H */ +#endif /* OPJ_MCT_H */ diff --git a/third_party/libopenjpeg20/mqc.c b/third_party/libopenjpeg20/mqc.c index 7e0f5637bf80470f18f13ef8d8ef10a62ca29879..6299b171d8788ffb32bd13c36027eb3f10b6983a 100644 --- a/third_party/libopenjpeg20/mqc.c +++ b/third_party/libopenjpeg20/mqc.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> @@ -38,6 +38,8 @@ #include "opj_includes.h" +#include <assert.h> + /** @defgroup MQC MQC - Implementation of an MQ-Coder */ /*@{*/ @@ -70,28 +72,6 @@ Fill mqc->c with 1's for flushing @param mqc MQC handle */ static void opj_mqc_setbits(opj_mqc_t *mqc); -/** -FIXME DOC -@param mqc MQC handle -@return -*/ -static INLINE OPJ_INT32 opj_mqc_mpsexchange(opj_mqc_t *const mqc); -/** -FIXME DOC -@param mqc MQC handle -@return -*/ -static INLINE OPJ_INT32 opj_mqc_lpsexchange(opj_mqc_t *const mqc); -/** -Input a byte -@param mqc MQC handle -*/ -static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc); -/** -Renormalize mqc->a and mqc->c while decoding -@param mqc MQC handle -*/ -static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc); /*@}*/ /*@}*/ @@ -99,516 +79,482 @@ static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc); /* <summary> */ /* This array defines all the possible states for a context. */ /* </summary> */ -static opj_mqc_state_t mqc_states[47 * 2] = { - {0x5601, 0, &mqc_states[2], &mqc_states[3]}, - {0x5601, 1, &mqc_states[3], &mqc_states[2]}, - {0x3401, 0, &mqc_states[4], &mqc_states[12]}, - {0x3401, 1, &mqc_states[5], &mqc_states[13]}, - {0x1801, 0, &mqc_states[6], &mqc_states[18]}, - {0x1801, 1, &mqc_states[7], &mqc_states[19]}, - {0x0ac1, 0, &mqc_states[8], &mqc_states[24]}, - {0x0ac1, 1, &mqc_states[9], &mqc_states[25]}, - {0x0521, 0, &mqc_states[10], &mqc_states[58]}, - {0x0521, 1, &mqc_states[11], &mqc_states[59]}, - {0x0221, 0, &mqc_states[76], &mqc_states[66]}, - {0x0221, 1, &mqc_states[77], &mqc_states[67]}, - {0x5601, 0, &mqc_states[14], &mqc_states[13]}, - {0x5601, 1, &mqc_states[15], &mqc_states[12]}, - {0x5401, 0, &mqc_states[16], &mqc_states[28]}, - {0x5401, 1, &mqc_states[17], &mqc_states[29]}, - {0x4801, 0, &mqc_states[18], &mqc_states[28]}, - {0x4801, 1, &mqc_states[19], &mqc_states[29]}, - {0x3801, 0, &mqc_states[20], &mqc_states[28]}, - {0x3801, 1, &mqc_states[21], &mqc_states[29]}, - {0x3001, 0, &mqc_states[22], &mqc_states[34]}, - {0x3001, 1, &mqc_states[23], &mqc_states[35]}, - {0x2401, 0, &mqc_states[24], &mqc_states[36]}, - {0x2401, 1, &mqc_states[25], &mqc_states[37]}, - {0x1c01, 0, &mqc_states[26], &mqc_states[40]}, - {0x1c01, 1, &mqc_states[27], &mqc_states[41]}, - {0x1601, 0, &mqc_states[58], &mqc_states[42]}, - {0x1601, 1, &mqc_states[59], &mqc_states[43]}, - {0x5601, 0, &mqc_states[30], &mqc_states[29]}, - {0x5601, 1, &mqc_states[31], &mqc_states[28]}, - {0x5401, 0, &mqc_states[32], &mqc_states[28]}, - {0x5401, 1, &mqc_states[33], &mqc_states[29]}, - {0x5101, 0, &mqc_states[34], &mqc_states[30]}, - {0x5101, 1, &mqc_states[35], &mqc_states[31]}, - {0x4801, 0, &mqc_states[36], &mqc_states[32]}, - {0x4801, 1, &mqc_states[37], &mqc_states[33]}, - {0x3801, 0, &mqc_states[38], &mqc_states[34]}, - {0x3801, 1, &mqc_states[39], &mqc_states[35]}, - {0x3401, 0, &mqc_states[40], &mqc_states[36]}, - {0x3401, 1, &mqc_states[41], &mqc_states[37]}, - {0x3001, 0, &mqc_states[42], &mqc_states[38]}, - {0x3001, 1, &mqc_states[43], &mqc_states[39]}, - {0x2801, 0, &mqc_states[44], &mqc_states[38]}, - {0x2801, 1, &mqc_states[45], &mqc_states[39]}, - {0x2401, 0, &mqc_states[46], &mqc_states[40]}, - {0x2401, 1, &mqc_states[47], &mqc_states[41]}, - {0x2201, 0, &mqc_states[48], &mqc_states[42]}, - {0x2201, 1, &mqc_states[49], &mqc_states[43]}, - {0x1c01, 0, &mqc_states[50], &mqc_states[44]}, - {0x1c01, 1, &mqc_states[51], &mqc_states[45]}, - {0x1801, 0, &mqc_states[52], &mqc_states[46]}, - {0x1801, 1, &mqc_states[53], &mqc_states[47]}, - {0x1601, 0, &mqc_states[54], &mqc_states[48]}, - {0x1601, 1, &mqc_states[55], &mqc_states[49]}, - {0x1401, 0, &mqc_states[56], &mqc_states[50]}, - {0x1401, 1, &mqc_states[57], &mqc_states[51]}, - {0x1201, 0, &mqc_states[58], &mqc_states[52]}, - {0x1201, 1, &mqc_states[59], &mqc_states[53]}, - {0x1101, 0, &mqc_states[60], &mqc_states[54]}, - {0x1101, 1, &mqc_states[61], &mqc_states[55]}, - {0x0ac1, 0, &mqc_states[62], &mqc_states[56]}, - {0x0ac1, 1, &mqc_states[63], &mqc_states[57]}, - {0x09c1, 0, &mqc_states[64], &mqc_states[58]}, - {0x09c1, 1, &mqc_states[65], &mqc_states[59]}, - {0x08a1, 0, &mqc_states[66], &mqc_states[60]}, - {0x08a1, 1, &mqc_states[67], &mqc_states[61]}, - {0x0521, 0, &mqc_states[68], &mqc_states[62]}, - {0x0521, 1, &mqc_states[69], &mqc_states[63]}, - {0x0441, 0, &mqc_states[70], &mqc_states[64]}, - {0x0441, 1, &mqc_states[71], &mqc_states[65]}, - {0x02a1, 0, &mqc_states[72], &mqc_states[66]}, - {0x02a1, 1, &mqc_states[73], &mqc_states[67]}, - {0x0221, 0, &mqc_states[74], &mqc_states[68]}, - {0x0221, 1, &mqc_states[75], &mqc_states[69]}, - {0x0141, 0, &mqc_states[76], &mqc_states[70]}, - {0x0141, 1, &mqc_states[77], &mqc_states[71]}, - {0x0111, 0, &mqc_states[78], &mqc_states[72]}, - {0x0111, 1, &mqc_states[79], &mqc_states[73]}, - {0x0085, 0, &mqc_states[80], &mqc_states[74]}, - {0x0085, 1, &mqc_states[81], &mqc_states[75]}, - {0x0049, 0, &mqc_states[82], &mqc_states[76]}, - {0x0049, 1, &mqc_states[83], &mqc_states[77]}, - {0x0025, 0, &mqc_states[84], &mqc_states[78]}, - {0x0025, 1, &mqc_states[85], &mqc_states[79]}, - {0x0015, 0, &mqc_states[86], &mqc_states[80]}, - {0x0015, 1, &mqc_states[87], &mqc_states[81]}, - {0x0009, 0, &mqc_states[88], &mqc_states[82]}, - {0x0009, 1, &mqc_states[89], &mqc_states[83]}, - {0x0005, 0, &mqc_states[90], &mqc_states[84]}, - {0x0005, 1, &mqc_states[91], &mqc_states[85]}, - {0x0001, 0, &mqc_states[90], &mqc_states[86]}, - {0x0001, 1, &mqc_states[91], &mqc_states[87]}, - {0x5601, 0, &mqc_states[92], &mqc_states[92]}, - {0x5601, 1, &mqc_states[93], &mqc_states[93]}, +static const opj_mqc_state_t mqc_states[47 * 2] = { + {0x5601, 0, &mqc_states[2], &mqc_states[3]}, + {0x5601, 1, &mqc_states[3], &mqc_states[2]}, + {0x3401, 0, &mqc_states[4], &mqc_states[12]}, + {0x3401, 1, &mqc_states[5], &mqc_states[13]}, + {0x1801, 0, &mqc_states[6], &mqc_states[18]}, + {0x1801, 1, &mqc_states[7], &mqc_states[19]}, + {0x0ac1, 0, &mqc_states[8], &mqc_states[24]}, + {0x0ac1, 1, &mqc_states[9], &mqc_states[25]}, + {0x0521, 0, &mqc_states[10], &mqc_states[58]}, + {0x0521, 1, &mqc_states[11], &mqc_states[59]}, + {0x0221, 0, &mqc_states[76], &mqc_states[66]}, + {0x0221, 1, &mqc_states[77], &mqc_states[67]}, + {0x5601, 0, &mqc_states[14], &mqc_states[13]}, + {0x5601, 1, &mqc_states[15], &mqc_states[12]}, + {0x5401, 0, &mqc_states[16], &mqc_states[28]}, + {0x5401, 1, &mqc_states[17], &mqc_states[29]}, + {0x4801, 0, &mqc_states[18], &mqc_states[28]}, + {0x4801, 1, &mqc_states[19], &mqc_states[29]}, + {0x3801, 0, &mqc_states[20], &mqc_states[28]}, + {0x3801, 1, &mqc_states[21], &mqc_states[29]}, + {0x3001, 0, &mqc_states[22], &mqc_states[34]}, + {0x3001, 1, &mqc_states[23], &mqc_states[35]}, + {0x2401, 0, &mqc_states[24], &mqc_states[36]}, + {0x2401, 1, &mqc_states[25], &mqc_states[37]}, + {0x1c01, 0, &mqc_states[26], &mqc_states[40]}, + {0x1c01, 1, &mqc_states[27], &mqc_states[41]}, + {0x1601, 0, &mqc_states[58], &mqc_states[42]}, + {0x1601, 1, &mqc_states[59], &mqc_states[43]}, + {0x5601, 0, &mqc_states[30], &mqc_states[29]}, + {0x5601, 1, &mqc_states[31], &mqc_states[28]}, + {0x5401, 0, &mqc_states[32], &mqc_states[28]}, + {0x5401, 1, &mqc_states[33], &mqc_states[29]}, + {0x5101, 0, &mqc_states[34], &mqc_states[30]}, + {0x5101, 1, &mqc_states[35], &mqc_states[31]}, + {0x4801, 0, &mqc_states[36], &mqc_states[32]}, + {0x4801, 1, &mqc_states[37], &mqc_states[33]}, + {0x3801, 0, &mqc_states[38], &mqc_states[34]}, + {0x3801, 1, &mqc_states[39], &mqc_states[35]}, + {0x3401, 0, &mqc_states[40], &mqc_states[36]}, + {0x3401, 1, &mqc_states[41], &mqc_states[37]}, + {0x3001, 0, &mqc_states[42], &mqc_states[38]}, + {0x3001, 1, &mqc_states[43], &mqc_states[39]}, + {0x2801, 0, &mqc_states[44], &mqc_states[38]}, + {0x2801, 1, &mqc_states[45], &mqc_states[39]}, + {0x2401, 0, &mqc_states[46], &mqc_states[40]}, + {0x2401, 1, &mqc_states[47], &mqc_states[41]}, + {0x2201, 0, &mqc_states[48], &mqc_states[42]}, + {0x2201, 1, &mqc_states[49], &mqc_states[43]}, + {0x1c01, 0, &mqc_states[50], &mqc_states[44]}, + {0x1c01, 1, &mqc_states[51], &mqc_states[45]}, + {0x1801, 0, &mqc_states[52], &mqc_states[46]}, + {0x1801, 1, &mqc_states[53], &mqc_states[47]}, + {0x1601, 0, &mqc_states[54], &mqc_states[48]}, + {0x1601, 1, &mqc_states[55], &mqc_states[49]}, + {0x1401, 0, &mqc_states[56], &mqc_states[50]}, + {0x1401, 1, &mqc_states[57], &mqc_states[51]}, + {0x1201, 0, &mqc_states[58], &mqc_states[52]}, + {0x1201, 1, &mqc_states[59], &mqc_states[53]}, + {0x1101, 0, &mqc_states[60], &mqc_states[54]}, + {0x1101, 1, &mqc_states[61], &mqc_states[55]}, + {0x0ac1, 0, &mqc_states[62], &mqc_states[56]}, + {0x0ac1, 1, &mqc_states[63], &mqc_states[57]}, + {0x09c1, 0, &mqc_states[64], &mqc_states[58]}, + {0x09c1, 1, &mqc_states[65], &mqc_states[59]}, + {0x08a1, 0, &mqc_states[66], &mqc_states[60]}, + {0x08a1, 1, &mqc_states[67], &mqc_states[61]}, + {0x0521, 0, &mqc_states[68], &mqc_states[62]}, + {0x0521, 1, &mqc_states[69], &mqc_states[63]}, + {0x0441, 0, &mqc_states[70], &mqc_states[64]}, + {0x0441, 1, &mqc_states[71], &mqc_states[65]}, + {0x02a1, 0, &mqc_states[72], &mqc_states[66]}, + {0x02a1, 1, &mqc_states[73], &mqc_states[67]}, + {0x0221, 0, &mqc_states[74], &mqc_states[68]}, + {0x0221, 1, &mqc_states[75], &mqc_states[69]}, + {0x0141, 0, &mqc_states[76], &mqc_states[70]}, + {0x0141, 1, &mqc_states[77], &mqc_states[71]}, + {0x0111, 0, &mqc_states[78], &mqc_states[72]}, + {0x0111, 1, &mqc_states[79], &mqc_states[73]}, + {0x0085, 0, &mqc_states[80], &mqc_states[74]}, + {0x0085, 1, &mqc_states[81], &mqc_states[75]}, + {0x0049, 0, &mqc_states[82], &mqc_states[76]}, + {0x0049, 1, &mqc_states[83], &mqc_states[77]}, + {0x0025, 0, &mqc_states[84], &mqc_states[78]}, + {0x0025, 1, &mqc_states[85], &mqc_states[79]}, + {0x0015, 0, &mqc_states[86], &mqc_states[80]}, + {0x0015, 1, &mqc_states[87], &mqc_states[81]}, + {0x0009, 0, &mqc_states[88], &mqc_states[82]}, + {0x0009, 1, &mqc_states[89], &mqc_states[83]}, + {0x0005, 0, &mqc_states[90], &mqc_states[84]}, + {0x0005, 1, &mqc_states[91], &mqc_states[85]}, + {0x0001, 0, &mqc_states[90], &mqc_states[86]}, + {0x0001, 1, &mqc_states[91], &mqc_states[87]}, + {0x5601, 0, &mqc_states[92], &mqc_states[92]}, + {0x5601, 1, &mqc_states[93], &mqc_states[93]}, }; -/* +/* ========================================================== local functions ========================================================== */ -static void opj_mqc_byteout(opj_mqc_t *mqc) { - if (*mqc->bp == 0xff) { - mqc->bp++; - *mqc->bp = (OPJ_BYTE)(mqc->c >> 20); - mqc->c &= 0xfffff; - mqc->ct = 7; - } else { - if ((mqc->c & 0x8000000) == 0) { /* ((mqc->c&0x8000000)==0) CHANGE */ - mqc->bp++; - *mqc->bp = (OPJ_BYTE)(mqc->c >> 19); - mqc->c &= 0x7ffff; - mqc->ct = 8; - } else { - (*mqc->bp)++; - if (*mqc->bp == 0xff) { - mqc->c &= 0x7ffffff; - mqc->bp++; - *mqc->bp = (OPJ_BYTE)(mqc->c >> 20); - mqc->c &= 0xfffff; - mqc->ct = 7; - } else { - mqc->bp++; - *mqc->bp = (OPJ_BYTE)(mqc->c >> 19); - mqc->c &= 0x7ffff; - mqc->ct = 8; - } - } - } -} - -static void opj_mqc_renorme(opj_mqc_t *mqc) { - do { - mqc->a <<= 1; - mqc->c <<= 1; - mqc->ct--; - if (mqc->ct == 0) { - opj_mqc_byteout(mqc); - } - } while ((mqc->a & 0x8000) == 0); -} - -static void opj_mqc_codemps(opj_mqc_t *mqc) { - mqc->a -= (*mqc->curctx)->qeval; - if ((mqc->a & 0x8000) == 0) { - if (mqc->a < (*mqc->curctx)->qeval) { - mqc->a = (*mqc->curctx)->qeval; - } else { - mqc->c += (*mqc->curctx)->qeval; - } - *mqc->curctx = (*mqc->curctx)->nmps; - opj_mqc_renorme(mqc); - } else { - mqc->c += (*mqc->curctx)->qeval; - } -} - -static void opj_mqc_codelps(opj_mqc_t *mqc) { - mqc->a -= (*mqc->curctx)->qeval; - if (mqc->a < (*mqc->curctx)->qeval) { - mqc->c += (*mqc->curctx)->qeval; - } else { - mqc->a = (*mqc->curctx)->qeval; - } - *mqc->curctx = (*mqc->curctx)->nlps; - opj_mqc_renorme(mqc); -} - -static void opj_mqc_setbits(opj_mqc_t *mqc) { - OPJ_UINT32 tempc = mqc->c + mqc->a; - mqc->c |= 0xffff; - if (mqc->c >= tempc) { - mqc->c -= 0x8000; - } +static void opj_mqc_byteout(opj_mqc_t *mqc) +{ + /* bp is initialized to start - 1 in opj_mqc_init_enc() */ + /* but this is safe, see opj_tcd_code_block_enc_allocate_data() */ + assert(mqc->bp >= mqc->start - 1); + if (*mqc->bp == 0xff) { + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 20); + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + if ((mqc->c & 0x8000000) == 0) { + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 19); + mqc->c &= 0x7ffff; + mqc->ct = 8; + } else { + (*mqc->bp)++; + if (*mqc->bp == 0xff) { + mqc->c &= 0x7ffffff; + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 20); + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 19); + mqc->c &= 0x7ffff; + mqc->ct = 8; + } + } + } } -static INLINE OPJ_INT32 opj_mqc_mpsexchange(opj_mqc_t *const mqc) { - OPJ_INT32 d; - if (mqc->a < (*mqc->curctx)->qeval) { - d = (OPJ_INT32)(1 - (*mqc->curctx)->mps); - *mqc->curctx = (*mqc->curctx)->nlps; - } else { - d = (OPJ_INT32)(*mqc->curctx)->mps; - *mqc->curctx = (*mqc->curctx)->nmps; - } - - return d; +static void opj_mqc_renorme(opj_mqc_t *mqc) +{ + do { + mqc->a <<= 1; + mqc->c <<= 1; + mqc->ct--; + if (mqc->ct == 0) { + opj_mqc_byteout(mqc); + } + } while ((mqc->a & 0x8000) == 0); } -static INLINE OPJ_INT32 opj_mqc_lpsexchange(opj_mqc_t *const mqc) { - OPJ_INT32 d; - if (mqc->a < (*mqc->curctx)->qeval) { - mqc->a = (*mqc->curctx)->qeval; - d = (OPJ_INT32)(*mqc->curctx)->mps; - *mqc->curctx = (*mqc->curctx)->nmps; - } else { - mqc->a = (*mqc->curctx)->qeval; - d = (OPJ_INT32)(1 - (*mqc->curctx)->mps); - *mqc->curctx = (*mqc->curctx)->nlps; - } - - return d; +static void opj_mqc_codemps(opj_mqc_t *mqc) +{ + mqc->a -= (*mqc->curctx)->qeval; + if ((mqc->a & 0x8000) == 0) { + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->a = (*mqc->curctx)->qeval; + } else { + mqc->c += (*mqc->curctx)->qeval; + } + *mqc->curctx = (*mqc->curctx)->nmps; + opj_mqc_renorme(mqc); + } else { + mqc->c += (*mqc->curctx)->qeval; + } } -#ifdef MQC_PERF_OPT -static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) { - unsigned int i = *((unsigned int *) mqc->bp); - mqc->c += i & 0xffff00; - mqc->ct = i & 0x0f; - mqc->bp += (i >> 2) & 0x04; +static void opj_mqc_codelps(opj_mqc_t *mqc) +{ + mqc->a -= (*mqc->curctx)->qeval; + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->c += (*mqc->curctx)->qeval; + } else { + mqc->a = (*mqc->curctx)->qeval; + } + *mqc->curctx = (*mqc->curctx)->nlps; + opj_mqc_renorme(mqc); } -#else -static void opj_mqc_bytein(opj_mqc_t *const mqc) { - if (mqc->bp != mqc->end) { - OPJ_UINT32 c; - if (mqc->bp + 1 != mqc->end) { - c = *(mqc->bp + 1); - } else { - c = 0xff; - } - if (*mqc->bp == 0xff) { - if (c > 0x8f) { - mqc->c += 0xff00; - mqc->ct = 8; - } else { - mqc->bp++; - mqc->c += c << 9; - mqc->ct = 7; - } - } else { - mqc->bp++; - mqc->c += c << 8; - mqc->ct = 8; - } - } else { - mqc->c += 0xff00; - mqc->ct = 8; - } -} -#endif -static INLINE void opj_mqc_renormd(opj_mqc_t *const mqc) { - do { - if (mqc->ct == 0) { - opj_mqc_bytein(mqc); - } - mqc->a <<= 1; - mqc->c <<= 1; - mqc->ct--; - } while (mqc->a < 0x8000); +static void opj_mqc_setbits(opj_mqc_t *mqc) +{ + OPJ_UINT32 tempc = mqc->c + mqc->a; + mqc->c |= 0xffff; + if (mqc->c >= tempc) { + mqc->c -= 0x8000; + } } -/* +/* ========================================================== MQ-Coder interface ========================================================== */ -opj_mqc_t* opj_mqc_create(void) { - opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t)); -#ifdef MQC_PERF_OPT - if (mqc) { - mqc->buffer = NULL; - } +OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc) +{ + const ptrdiff_t diff = mqc->bp - mqc->start; +#if 0 + assert(diff <= 0xffffffff && diff >= 0); /* UINT32_MAX */ #endif - return mqc; + return (OPJ_UINT32)diff; } -void opj_mqc_destroy(opj_mqc_t *mqc) { - if(mqc) { -#ifdef MQC_PERF_OPT - if (mqc->buffer) { - opj_free(mqc->buffer); - } -#endif - opj_free(mqc); - } +void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) +{ + /* To avoid the curctx pointer to be dangling, but not strictly */ + /* required as the current context is always set before encoding */ + opj_mqc_setcurctx(mqc, 0); + + /* As specified in Figure C.10 - Initialization of the encoder */ + /* (C.2.8 Initialization of the encoder (INITENC)) */ + mqc->a = 0x8000; + mqc->c = 0; + /* Yes, we point before the start of the buffer, but this is safe */ + /* given opj_tcd_code_block_enc_allocate_data() */ + mqc->bp = bp - 1; + mqc->ct = 12; + /* At this point we should test *(mqc->bp) against 0xFF, but this is not */ + /* necessary, as this is only used at the beginning of the code block */ + /* and our initial fake byte is set at 0 */ + assert(*(mqc->bp) != 0xff); + + mqc->start = bp; + mqc->end_of_byte_stream_counter = 0; } -OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc) { - const ptrdiff_t diff = mqc->bp - mqc->start; -#if 0 - assert( diff <= 0xffffffff && diff >= 0 ); /* UINT32_MAX */ -#endif - return (OPJ_UINT32)diff; +void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) +{ + if ((*mqc->curctx)->mps == d) { + opj_mqc_codemps(mqc); + } else { + opj_mqc_codelps(mqc); + } } -void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) { - /* TODO MSD: need to take a look to the v2 version */ - opj_mqc_setcurctx(mqc, 0); - mqc->a = 0x8000; - mqc->c = 0; - mqc->bp = bp - 1; - mqc->ct = 12; - if (*mqc->bp == 0xff) { - mqc->ct = 13; - } - mqc->start = bp; +void opj_mqc_flush(opj_mqc_t *mqc) +{ + /* C.2.9 Termination of coding (FLUSH) */ + /* Figure C.11 – FLUSH procedure */ + opj_mqc_setbits(mqc); + mqc->c <<= mqc->ct; + opj_mqc_byteout(mqc); + mqc->c <<= mqc->ct; + opj_mqc_byteout(mqc); + + /* It is forbidden that a coding pass ends with 0xff */ + if (*mqc->bp != 0xff) { + /* Advance pointer so that opj_mqc_numbytes() returns a valid value */ + mqc->bp++; + } } -void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) { - if ((*mqc->curctx)->mps == d) { - opj_mqc_codemps(mqc); - } else { - opj_mqc_codelps(mqc); - } +#define BYPASS_CT_INIT 0xDEADBEEF + +void opj_mqc_bypass_init_enc(opj_mqc_t *mqc) +{ + /* This function is normally called after at least one opj_mqc_flush() */ + /* which will have advance mqc->bp by at least 2 bytes beyond its */ + /* initial position */ + assert(mqc->bp >= mqc->start); + mqc->c = 0; + /* in theory we should initialize to 8, but use this special value */ + /* as a hint that opj_mqc_bypass_enc() has never been called, so */ + /* as to avoid the 0xff 0x7f elimination trick in opj_mqc_bypass_flush_enc() */ + /* to trigger when we don't have output any bit during this bypass sequence */ + /* Any value > 8 will do */ + mqc->ct = BYPASS_CT_INIT; + /* Given that we are called after opj_mqc_flush(), the previous byte */ + /* cannot be 0xff. */ + assert(mqc->bp[-1] != 0xff); } -void opj_mqc_flush(opj_mqc_t *mqc) { - opj_mqc_setbits(mqc); - mqc->c <<= mqc->ct; - opj_mqc_byteout(mqc); - mqc->c <<= mqc->ct; - opj_mqc_byteout(mqc); - - if (*mqc->bp != 0xff) { - mqc->bp++; - } +void opj_mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d) +{ + if (mqc->ct == BYPASS_CT_INIT) { + mqc->ct = 8; + } + mqc->ct--; + mqc->c = mqc->c + (d << mqc->ct); + if (mqc->ct == 0) { + *mqc->bp = (OPJ_BYTE)mqc->c; + mqc->ct = 8; + /* If the previous byte was 0xff, make sure that the next msb is 0 */ + if (*mqc->bp == 0xff) { + mqc->ct = 7; + } + mqc->bp++; + mqc->c = 0; + } } -void opj_mqc_bypass_init_enc(opj_mqc_t *mqc) { - mqc->c = 0; - mqc->ct = 8; - /*if (*mqc->bp == 0xff) { - mqc->ct = 7; - } */ +OPJ_UINT32 opj_mqc_bypass_get_extra_bytes(opj_mqc_t *mqc, OPJ_BOOL erterm) +{ + return (mqc->ct < 7 || + (mqc->ct == 7 && (erterm || mqc->bp[-1] != 0xff))) ? 1 : 0; } -void opj_mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d) { - mqc->ct--; - mqc->c = mqc->c + (d << mqc->ct); - if (mqc->ct == 0) { - mqc->bp++; - *mqc->bp = (OPJ_BYTE)mqc->c; - mqc->ct = 8; - if (*mqc->bp == 0xff) { - mqc->ct = 7; - } - mqc->c = 0; - } +void opj_mqc_bypass_flush_enc(opj_mqc_t *mqc, OPJ_BOOL erterm) +{ + /* Is there any bit remaining to be flushed ? */ + /* If the last output byte is 0xff, we can discard it, unless */ + /* erterm is required (I'm not completely sure why in erterm */ + /* we must output 0xff 0x2a if the last byte was 0xff instead of */ + /* discarding it, but Kakadu requires it when decoding */ + /* in -fussy mode) */ + if (mqc->ct < 7 || (mqc->ct == 7 && (erterm || mqc->bp[-1] != 0xff))) { + OPJ_BYTE bit_value = 0; + /* If so, fill the remaining lsbs with an alternating sequence of */ + /* 0,1,... */ + /* Note: it seems the standard only requires that for a ERTERM flush */ + /* and doesn't specify what to do for a regular BYPASS flush */ + while (mqc->ct > 0) { + mqc->ct--; + mqc->c += (OPJ_UINT32)(bit_value << mqc->ct); + bit_value = (OPJ_BYTE)(1U - bit_value); + } + *mqc->bp = (OPJ_BYTE)mqc->c; + /* Advance pointer so that opj_mqc_numbytes() returns a valid value */ + mqc->bp++; + } else if (mqc->ct == 7 && mqc->bp[-1] == 0xff) { + /* Discard last 0xff */ + assert(!erterm); + mqc->bp --; + } else if (mqc->ct == 8 && !erterm && + mqc->bp[-1] == 0x7f && mqc->bp[-2] == 0xff) { + /* Tiny optimization: discard terminating 0xff 0x7f since it is */ + /* interpreted as 0xff 0x7f [0xff 0xff] by the decoder, and given */ + /* the bit stuffing, in fact as 0xff 0xff [0xff ..] */ + /* Happens once on opj_compress -i ../MAPA.tif -o MAPA.j2k -M 1 */ + mqc->bp -= 2; + } + + assert(mqc->bp[-1] != 0xff); } -OPJ_UINT32 opj_mqc_bypass_flush_enc(opj_mqc_t *mqc) { - OPJ_BYTE bit_padding; - - bit_padding = 0; - - if (mqc->ct != 0) { - while (mqc->ct > 0) { - mqc->ct--; - mqc->c += (OPJ_UINT32)(bit_padding << mqc->ct); - bit_padding = (bit_padding + 1) & 0x01; - } - mqc->bp++; - *mqc->bp = (OPJ_BYTE)mqc->c; - mqc->ct = 8; - mqc->c = 0; - } - - return 1; +void opj_mqc_reset_enc(opj_mqc_t *mqc) +{ + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); } -void opj_mqc_reset_enc(opj_mqc_t *mqc) { - opj_mqc_resetstates(mqc); - opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); +#ifdef notdef +OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc) +{ + OPJ_UINT32 correction = 1; + + /* <flush part> */ + OPJ_INT32 n = (OPJ_INT32)(27 - 15 - mqc->ct); + mqc->c <<= mqc->ct; + while (n > 0) { + opj_mqc_byteout(mqc); + n -= (OPJ_INT32)mqc->ct; + mqc->c <<= mqc->ct; + } + opj_mqc_byteout(mqc); + + return correction; } +#endif -OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc) { - OPJ_UINT32 correction = 1; - - /* <flush part> */ - OPJ_INT32 n = (OPJ_INT32)(27 - 15 - mqc->ct); - mqc->c <<= mqc->ct; - while (n > 0) { - opj_mqc_byteout(mqc); - n -= (OPJ_INT32)mqc->ct; - mqc->c <<= mqc->ct; - } - opj_mqc_byteout(mqc); - - return correction; +void opj_mqc_restart_init_enc(opj_mqc_t *mqc) +{ + /* <Re-init part> */ + + /* As specified in Figure C.10 - Initialization of the encoder */ + /* (C.2.8 Initialization of the encoder (INITENC)) */ + mqc->a = 0x8000; + mqc->c = 0; + mqc->ct = 12; + /* This function is normally called after at least one opj_mqc_flush() */ + /* which will have advance mqc->bp by at least 2 bytes beyond its */ + /* initial position */ + mqc->bp --; + assert(mqc->bp >= mqc->start - 1); + assert(*mqc->bp != 0xff); + if (*mqc->bp == 0xff) { + mqc->ct = 13; + } } -void opj_mqc_restart_init_enc(opj_mqc_t *mqc) { - /* <Re-init part> */ - opj_mqc_setcurctx(mqc, 0); - mqc->a = 0x8000; - mqc->c = 0; - mqc->ct = 12; - mqc->bp--; - if (*mqc->bp == 0xff) { - mqc->ct = 13; - } +void opj_mqc_erterm_enc(opj_mqc_t *mqc) +{ + OPJ_INT32 k = (OPJ_INT32)(11 - mqc->ct + 1); + + while (k > 0) { + mqc->c <<= mqc->ct; + mqc->ct = 0; + opj_mqc_byteout(mqc); + k -= (OPJ_INT32)mqc->ct; + } + + if (*mqc->bp != 0xff) { + opj_mqc_byteout(mqc); + } } -void opj_mqc_erterm_enc(opj_mqc_t *mqc) { - OPJ_INT32 k = (OPJ_INT32)(11 - mqc->ct + 1); - - while (k > 0) { - mqc->c <<= mqc->ct; - mqc->ct = 0; - opj_mqc_byteout(mqc); - k -= (OPJ_INT32)mqc->ct; - } - - if (*mqc->bp != 0xff) { - opj_mqc_byteout(mqc); - } +void opj_mqc_segmark_enc(opj_mqc_t *mqc) +{ + OPJ_UINT32 i; + opj_mqc_setcurctx(mqc, 18); + + for (i = 1; i < 5; i++) { + opj_mqc_encode(mqc, i % 2); + } } -void opj_mqc_segmark_enc(opj_mqc_t *mqc) { - OPJ_UINT32 i; - opj_mqc_setcurctx(mqc, 18); - - for (i = 1; i < 5; i++) { - opj_mqc_encode(mqc, i % 2); - } +static void opj_mqc_init_dec_common(opj_mqc_t *mqc, + OPJ_BYTE *bp, + OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes) +{ + (void)extra_writable_bytes; + + assert(extra_writable_bytes >= OPJ_COMMON_CBLK_DATA_EXTRA); + mqc->start = bp; + mqc->end = bp + len; + /* Insert an artificial 0xFF 0xFF marker at end of the code block */ + /* data so that the bytein routines stop on it. This saves us comparing */ + /* the bp and end pointers */ + /* But before inserting it, backup th bytes we will overwrite */ + memcpy(mqc->backup, mqc->end, OPJ_COMMON_CBLK_DATA_EXTRA); + mqc->end[0] = 0xFF; + mqc->end[1] = 0xFF; + mqc->bp = bp; +} +void opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes) +{ + /* Implements ISO 15444-1 C.3.5 Initialization of the decoder (INITDEC) */ + /* Note: alternate "J.1 - Initialization of the software-conventions */ + /* decoder" has been tried, but does */ + /* not bring any improvement. */ + /* See https://github.com/uclouvain/openjpeg/issues/921 */ + opj_mqc_init_dec_common(mqc, bp, len, extra_writable_bytes); + opj_mqc_setcurctx(mqc, 0); + mqc->end_of_byte_stream_counter = 0; + if (len == 0) { + mqc->c = 0xff << 16; + } else { + mqc->c = (OPJ_UINT32)(*mqc->bp << 16); + } + + opj_mqc_bytein(mqc); + mqc->c <<= 7; + mqc->ct -= 7; + mqc->a = 0x8000; } -OPJ_BOOL opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len) { - opj_mqc_setcurctx(mqc, 0); - mqc->start = bp; - mqc->end = bp + len; - mqc->bp = bp; - if (len==0) mqc->c = 0xff << 16; - else mqc->c = (OPJ_UINT32)(*mqc->bp << 16); - -#ifdef MQC_PERF_OPT /* TODO_MSD: check this option and put in experimental */ - { - OPJ_UINT32 c; - OPJ_UINT32 *ip; - OPJ_BYTE *end = mqc->end - 1; - void* new_buffer = opj_realloc(mqc->buffer, (len + 1) * sizeof(OPJ_UINT32)); - if (! new_buffer) { - opj_free(mqc->buffer); - mqc->buffer = NULL; - return OPJ_FALSE; - } - mqc->buffer = new_buffer; - - ip = (OPJ_UINT32 *) mqc->buffer; - - while (bp < end) { - c = *(bp + 1); - if (*bp == 0xff) { - if (c > 0x8f) { - break; - } else { - *ip = 0x00000017 | (c << 9); - } - } else { - *ip = 0x00000018 | (c << 8); - } - bp++; - ip++; - } - - /* Handle last byte of data */ - c = 0xff; - if (*bp == 0xff) { - *ip = 0x0000ff18; - } else { - bp++; - *ip = 0x00000018 | (c << 8); - } - ip++; - - *ip = 0x0000ff08; - mqc->bp = mqc->buffer; - } -#endif - opj_mqc_bytein(mqc); - mqc->c <<= 7; - mqc->ct -= 7; - mqc->a = 0x8000; - return OPJ_TRUE; + +void opj_mqc_raw_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes) +{ + opj_mqc_init_dec_common(mqc, bp, len, extra_writable_bytes); + mqc->c = 0; + mqc->ct = 0; } -OPJ_INT32 opj_mqc_decode(opj_mqc_t *const mqc) { - OPJ_INT32 d; - mqc->a -= (*mqc->curctx)->qeval; - if ((mqc->c >> 16) < (*mqc->curctx)->qeval) { - d = opj_mqc_lpsexchange(mqc); - opj_mqc_renormd(mqc); - } else { - mqc->c -= (*mqc->curctx)->qeval << 16; - if ((mqc->a & 0x8000) == 0) { - d = opj_mqc_mpsexchange(mqc); - opj_mqc_renormd(mqc); - } else { - d = (OPJ_INT32)(*mqc->curctx)->mps; - } - } - - return d; + +void opq_mqc_finish_dec(opj_mqc_t *mqc) +{ + /* Restore the bytes overwritten by opj_mqc_init_dec_common() */ + memcpy(mqc->end, mqc->backup, OPJ_COMMON_CBLK_DATA_EXTRA); } -void opj_mqc_resetstates(opj_mqc_t *mqc) { - OPJ_UINT32 i; - for (i = 0; i < MQC_NUMCTXS; i++) { - mqc->ctxs[i] = mqc_states; - } +void opj_mqc_resetstates(opj_mqc_t *mqc) +{ + OPJ_UINT32 i; + for (i = 0; i < MQC_NUMCTXS; i++) { + mqc->ctxs[i] = mqc_states; + } } -void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, OPJ_INT32 prob) { - mqc->ctxs[ctxno] = &mqc_states[msb + (OPJ_UINT32)(prob << 1)]; +void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, + OPJ_INT32 prob) +{ + mqc->ctxs[ctxno] = &mqc_states[msb + (OPJ_UINT32)(prob << 1)]; } diff --git a/third_party/libopenjpeg20/mqc.h b/third_party/libopenjpeg20/mqc.h index 69a2d4602992c36b7983ee2a59287fa31a421522..69a2a79dc06d68b1a973e9aac915d13c6b0f566f 100644 --- a/third_party/libopenjpeg20/mqc.h +++ b/third_party/libopenjpeg20/mqc.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> @@ -36,8 +36,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __MQC_H -#define __MQC_H +#ifndef OPJ_MQC_H +#define OPJ_MQC_H + +#include "opj_common.h" + /** @file mqc.h @brief Implementation of an MQ-Coder (MQC) @@ -53,14 +56,14 @@ in MQC.C are used by some function in T1.C. This struct defines the state of a context. */ typedef struct opj_mqc_state { - /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */ - OPJ_UINT32 qeval; - /** the Most Probable Symbol (0 or 1) */ - OPJ_UINT32 mps; - /** next state if the next encoded symbol is the MPS */ - struct opj_mqc_state *nmps; - /** next state if the next encoded symbol is the LPS */ - struct opj_mqc_state *nlps; + /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */ + OPJ_UINT32 qeval; + /** the Most Probable Symbol (0 or 1) */ + OPJ_UINT32 mps; + /** next state if the next encoded symbol is the MPS */ + const struct opj_mqc_state *nmps; + /** next state if the next encoded symbol is the LPS */ + const struct opj_mqc_state *nlps; } opj_mqc_state_t; #define MQC_NUMCTXS 19 @@ -69,32 +72,36 @@ typedef struct opj_mqc_state { MQ coder */ typedef struct opj_mqc { - OPJ_UINT32 c; - OPJ_UINT32 a; - OPJ_UINT32 ct; - OPJ_BYTE *bp; - OPJ_BYTE *start; - OPJ_BYTE *end; - opj_mqc_state_t *ctxs[MQC_NUMCTXS]; - opj_mqc_state_t **curctx; -#ifdef MQC_PERF_OPT - unsigned char *buffer; -#endif + /** temporary buffer where bits are coded or decoded */ + OPJ_UINT32 c; + /** only used by MQ decoder */ + OPJ_UINT32 a; + /** number of bits already read or free to write */ + OPJ_UINT32 ct; + /* only used by decoder, to count the number of times a terminating 0xFF >0x8F marker is read */ + OPJ_UINT32 end_of_byte_stream_counter; + /** pointer to the current position in the buffer */ + OPJ_BYTE *bp; + /** pointer to the start of the buffer */ + OPJ_BYTE *start; + /** pointer to the end of the buffer */ + OPJ_BYTE *end; + /** Array of contexts */ + const opj_mqc_state_t *ctxs[MQC_NUMCTXS]; + /** Active context */ + const opj_mqc_state_t **curctx; + /* lut_ctxno_zc shifted by (1 << 9) * bandno */ + const OPJ_BYTE* lut_ctxno_zc_orient; + /** Original value of the 2 bytes at end[0] and end[1] */ + OPJ_BYTE backup[OPJ_COMMON_CBLK_DATA_EXTRA]; } opj_mqc_t; +#include "mqc_inl.h" + /** @name Exported functions */ /*@{*/ /* ----------------------------------------------------------------------- */ -/** -Create a new MQC handle -@return Returns a new MQC handle if successful, returns NULL otherwise -*/ -opj_mqc_t* opj_mqc_create(void); -/** -Destroy a previously created MQC handle -@param mqc MQC handle to destroy -*/ -void opj_mqc_destroy(opj_mqc_t *mqc); + /** Return the number of bytes written/read since initialisation @param mqc MQC handle @@ -102,7 +109,7 @@ Return the number of bytes written/read since initialisation */ OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc); /** -Reset the states of all the context of the coder/decoder +Reset the states of all the context of the coder/decoder (each context is set to a state where 0 and 1 are more or less equiprobable) @param mqc MQC handle */ @@ -114,7 +121,8 @@ Set the state of a particular context @param msb The MSB of the new state of the context @param prob Number that identifies the probability of the symbols for the new state of the context */ -void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, OPJ_INT32 prob); +void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, + OPJ_INT32 prob); /** Initialize the encoder @param mqc MQC handle @@ -126,7 +134,7 @@ Set the current context used for coding/decoding @param mqc MQC handle @param ctxno Number that identifies the context */ -#define opj_mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] +#define opj_mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] /** Encode a symbol using the MQ-coder @param mqc MQC handle @@ -139,38 +147,47 @@ Flush the encoder, so that all remaining data is written */ void opj_mqc_flush(opj_mqc_t *mqc); /** -BYPASS mode switch, initialization operation. -JPEG 2000 p 505. -<h2>Not fully implemented and tested !!</h2> +BYPASS mode switch, initialization operation. +JPEG 2000 p 505. @param mqc MQC handle */ void opj_mqc_bypass_init_enc(opj_mqc_t *mqc); + +/** Return number of extra bytes to add to opj_mqc_numbytes() for the² + size of a non-terminating BYPASS pass +@param mqc MQC handle +@param erterm 1 if ERTERM is enabled, 0 otherwise +*/ +OPJ_UINT32 opj_mqc_bypass_get_extra_bytes(opj_mqc_t *mqc, OPJ_BOOL erterm); + /** -BYPASS mode switch, coding operation. -JPEG 2000 p 505. -<h2>Not fully implemented and tested !!</h2> +BYPASS mode switch, coding operation. +JPEG 2000 p 505. @param mqc MQC handle @param d The symbol to be encoded (0 or 1) */ void opj_mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d); /** BYPASS mode switch, flush operation -<h2>Not fully implemented and tested !!</h2> @param mqc MQC handle -@return Returns 1 (always) +@param erterm 1 if ERTERM is enabled, 0 otherwise */ -OPJ_UINT32 opj_mqc_bypass_flush_enc(opj_mqc_t *mqc); +void opj_mqc_bypass_flush_enc(opj_mqc_t *mqc, OPJ_BOOL erterm); /** RESET mode switch @param mqc MQC handle */ void opj_mqc_reset_enc(opj_mqc_t *mqc); + +#ifdef notdef /** RESTART mode switch (TERMALL) @param mqc MQC handle @return Returns 1 (always) */ OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc); +#endif + /** RESTART mode switch (TERMALL) reinitialisation @param mqc MQC handle @@ -186,22 +203,69 @@ SEGMARK mode switch (SEGSYM) @param mqc MQC handle */ void opj_mqc_segmark_enc(opj_mqc_t *mqc); + /** -Initialize the decoder +Initialize the decoder for MQ decoding. + +opj_mqc_finish_dec() must be absolutely called after finishing the decoding +passes, so as to restore the bytes temporarily overwritten. + +@param mqc MQC handle +@param bp Pointer to the start of the buffer from which the bytes will be read + Note that OPJ_COMMON_CBLK_DATA_EXTRA bytes at the end of the buffer + will be temporarily overwritten with an artificial 0xFF 0xFF marker. + (they will be backuped in the mqc structure to be restored later) + So bp must be at least len + OPJ_COMMON_CBLK_DATA_EXTRA large, and + writable. +@param len Length of the input buffer +@param extra_writable_bytes Indicate how many bytes after len are writable. + This is to indicate your consent that bp must be + large enough. +*/ +void opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes); + +/** +Initialize the decoder for RAW decoding. + +opj_mqc_finish_dec() must be absolutely called after finishing the decoding +passes, so as to restore the bytes temporarily overwritten. + @param mqc MQC handle @param bp Pointer to the start of the buffer from which the bytes will be read + Note that OPJ_COMMON_CBLK_DATA_EXTRA bytes at the end of the buffer + will be temporarily overwritten with an artificial 0xFF 0xFF marker. + (they will be backuped in the mqc structure to be restored later) + So bp must be at least len + OPJ_COMMON_CBLK_DATA_EXTRA large, and + writable. @param len Length of the input buffer +@param extra_writable_bytes Indicate how many bytes after len are writable. + This is to indicate your consent that bp must be + large enough. */ -OPJ_BOOL opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len); +void opj_mqc_raw_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes); + + +/** +Terminate RAW/MQC decoding + +This restores the bytes temporarily overwritten by opj_mqc_init_dec()/ +opj_mqc_raw_init_dec() + +@param mqc MQC handle +*/ +void opq_mqc_finish_dec(opj_mqc_t *mqc); + /** Decode a symbol @param mqc MQC handle @return Returns the decoded symbol (0 or 1) */ -OPJ_INT32 opj_mqc_decode(opj_mqc_t * const mqc); +/*static INLINE OPJ_UINT32 opj_mqc_decode(opj_mqc_t * const mqc);*/ /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ -#endif /* __MQC_H */ +#endif /* OPJ_MQC_H */ diff --git a/third_party/libopenjpeg20/mqc_inl.h b/third_party/libopenjpeg20/mqc_inl.h new file mode 100644 index 0000000000000000000000000000000000000000..310a3287fd918dce3ab66e49e9f4e2706ccfa2de --- /dev/null +++ b/third_party/libopenjpeg20/mqc_inl.h @@ -0,0 +1,196 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OPJ_MQC_INL_H +#define OPJ_MQC_INL_H + +/* For internal use of opj_mqc_decode_macro() */ +#define opj_mqc_mpsexchange_macro(d, curctx, a) \ +{ \ + if (a < (*curctx)->qeval) { \ + d = !((*curctx)->mps); \ + *curctx = (*curctx)->nlps; \ + } else { \ + d = (*curctx)->mps; \ + *curctx = (*curctx)->nmps; \ + } \ +} + +/* For internal use of opj_mqc_decode_macro() */ +#define opj_mqc_lpsexchange_macro(d, curctx, a) \ +{ \ + if (a < (*curctx)->qeval) { \ + a = (*curctx)->qeval; \ + d = (*curctx)->mps; \ + *curctx = (*curctx)->nmps; \ + } else { \ + a = (*curctx)->qeval; \ + d = !((*curctx)->mps); \ + *curctx = (*curctx)->nlps; \ + } \ +} + + +/** +Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) +*/ +static INLINE OPJ_UINT32 opj_mqc_raw_decode(opj_mqc_t *mqc) +{ + OPJ_UINT32 d; + if (mqc->ct == 0) { + /* Given opj_mqc_raw_init_dec() we know that at some point we will */ + /* have a 0xFF 0xFF artificial marker */ + if (mqc->c == 0xff) { + if (*mqc->bp > 0x8f) { + mqc->c = 0xff; + mqc->ct = 8; + } else { + mqc->c = *mqc->bp; + mqc->bp ++; + mqc->ct = 7; + } + } else { + mqc->c = *mqc->bp; + mqc->bp ++; + mqc->ct = 8; + } + } + mqc->ct--; + d = ((OPJ_UINT32)mqc->c >> mqc->ct) & 0x01U; + + return d; +} + + +#define opj_mqc_bytein_macro(mqc, c, ct) \ +{ \ + OPJ_UINT32 l_c; \ + /* Given opj_mqc_init_dec() we know that at some point we will */ \ + /* have a 0xFF 0xFF artificial marker */ \ + l_c = *(mqc->bp + 1); \ + if (*mqc->bp == 0xff) { \ + if (l_c > 0x8f) { \ + c += 0xff00; \ + ct = 8; \ + mqc->end_of_byte_stream_counter ++; \ + } else { \ + mqc->bp++; \ + c += l_c << 9; \ + ct = 7; \ + } \ + } else { \ + mqc->bp++; \ + c += l_c << 8; \ + ct = 8; \ + } \ +} + +/* For internal use of opj_mqc_decode_macro() */ +#define opj_mqc_renormd_macro(mqc, a, c, ct) \ +{ \ + do { \ + if (ct == 0) { \ + opj_mqc_bytein_macro(mqc, c, ct); \ + } \ + a <<= 1; \ + c <<= 1; \ + ct--; \ + } while (a < 0x8000); \ +} + +#define opj_mqc_decode_macro(d, mqc, curctx, a, c, ct) \ +{ \ + /* Implements ISO 15444-1 C.3.2 Decoding a decision (DECODE) */ \ + /* Note: alternate "J.2 - Decoding an MPS or an LPS in the */ \ + /* software-conventions decoder" has been tried, but does not bring any */ \ + /* improvement. See https://github.com/uclouvain/openjpeg/issues/921 */ \ + a -= (*curctx)->qeval; \ + if ((c >> 16) < (*curctx)->qeval) { \ + opj_mqc_lpsexchange_macro(d, curctx, a); \ + opj_mqc_renormd_macro(mqc, a, c, ct); \ + } else { \ + c -= (*curctx)->qeval << 16; \ + if ((a & 0x8000) == 0) { \ + opj_mqc_mpsexchange_macro(d, curctx, a); \ + opj_mqc_renormd_macro(mqc, a, c, ct); \ + } else { \ + d = (*curctx)->mps; \ + } \ + } \ +} + +#define DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct) \ + register const opj_mqc_state_t **curctx = mqc->curctx; \ + register OPJ_UINT32 c = mqc->c; \ + register OPJ_UINT32 a = mqc->a; \ + register OPJ_UINT32 ct = mqc->ct + +#define UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct) \ + mqc->curctx = curctx; \ + mqc->c = c; \ + mqc->a = a; \ + mqc->ct = ct; + +/** +Input a byte +@param mqc MQC handle +*/ +static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) +{ + opj_mqc_bytein_macro(mqc, mqc->c, mqc->ct); +} + +/** +Renormalize mqc->a and mqc->c while decoding +@param mqc MQC handle +*/ +#define opj_mqc_renormd(mqc) \ + opj_mqc_renormd_macro(mqc, mqc->a, mqc->c, mqc->ct) + +/** +Decode a symbol +@param d OPJ_UINT32 value where to store the decoded symbol +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) in d +*/ +#define opj_mqc_decode(d, mqc) \ + opj_mqc_decode_macro(d, mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct) + +#endif /* OPJ_MQC_INL_H */ diff --git a/third_party/libopenjpeg20/openjpeg.c b/third_party/libopenjpeg20/openjpeg.c index 5114cc1086d368ec4714c85aabd29e29e39ee8cc..7b12303423b7ad79cf50b6f259a682dcdab25bb4 100644 --- a/third_party/libopenjpeg20/openjpeg.c +++ b/third_party/libopenjpeg20/openjpeg.c @@ -1,11 +1,11 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -41,110 +41,113 @@ /* ---------------------------------------------------------------------- */ /* Functions to set the message handlers */ -OPJ_BOOL OPJ_CALLCONV opj_set_info_handler( opj_codec_t * p_codec, - opj_msg_callback p_callback, - void * p_user_data) -{ - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - if(! l_codec){ - return OPJ_FALSE; - } - - l_codec->m_event_mgr.info_handler = p_callback; - l_codec->m_event_mgr.m_info_data = p_user_data; - - return OPJ_TRUE; -} - -OPJ_BOOL OPJ_CALLCONV opj_set_warning_handler( opj_codec_t * p_codec, - opj_msg_callback p_callback, - void * p_user_data) -{ - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - if (! l_codec) { - return OPJ_FALSE; - } - - l_codec->m_event_mgr.warning_handler = p_callback; - l_codec->m_event_mgr.m_warning_data = p_user_data; - - return OPJ_TRUE; -} - -OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, - opj_msg_callback p_callback, - void * p_user_data) -{ - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - if (! l_codec) { - return OPJ_FALSE; - } - - l_codec->m_event_mgr.error_handler = p_callback; - l_codec->m_event_mgr.m_error_data = p_user_data; - - return OPJ_TRUE; +OPJ_BOOL OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (! l_codec) { + return OPJ_FALSE; + } + + l_codec->m_event_mgr.info_handler = p_callback; + l_codec->m_event_mgr.m_info_data = p_user_data; + + return OPJ_TRUE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_warning_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (! l_codec) { + return OPJ_FALSE; + } + + l_codec->m_event_mgr.warning_handler = p_callback; + l_codec->m_event_mgr.m_warning_data = p_user_data; + + return OPJ_TRUE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (! l_codec) { + return OPJ_FALSE; + } + + l_codec->m_event_mgr.error_handler = p_callback; + l_codec->m_event_mgr.m_error_data = p_user_data; + + return OPJ_TRUE; } /* ---------------------------------------------------------------------- */ -static OPJ_SIZE_T opj_read_from_file (void * p_buffer, OPJ_SIZE_T p_nb_bytes, FILE * p_file) +static OPJ_SIZE_T opj_read_from_file(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + FILE * p_file) { - OPJ_SIZE_T l_nb_read = fread(p_buffer,1,p_nb_bytes,p_file); - return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1; + OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, p_file); + return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1; } -static OPJ_UINT64 opj_get_data_length_from_file (FILE * p_file) +static OPJ_UINT64 opj_get_data_length_from_file(FILE * p_file) { - OPJ_OFF_T file_length = 0; + OPJ_OFF_T file_length = 0; - OPJ_FSEEK(p_file, 0, SEEK_END); - file_length = (OPJ_OFF_T)OPJ_FTELL(p_file); - OPJ_FSEEK(p_file, 0, SEEK_SET); + OPJ_FSEEK(p_file, 0, SEEK_END); + file_length = (OPJ_OFF_T)OPJ_FTELL(p_file); + OPJ_FSEEK(p_file, 0, SEEK_SET); - return (OPJ_UINT64)file_length; + return (OPJ_UINT64)file_length; } -static OPJ_SIZE_T opj_write_from_file (void * p_buffer, OPJ_SIZE_T p_nb_bytes, FILE * p_file) +static OPJ_SIZE_T opj_write_from_file(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + FILE * p_file) { - return fwrite(p_buffer,1,p_nb_bytes,p_file); + return fwrite(p_buffer, 1, p_nb_bytes, p_file); } -static OPJ_OFF_T opj_skip_from_file (OPJ_OFF_T p_nb_bytes, FILE * p_user_data) +static OPJ_OFF_T opj_skip_from_file(OPJ_OFF_T p_nb_bytes, FILE * p_user_data) { - if (OPJ_FSEEK(p_user_data,p_nb_bytes,SEEK_CUR)) { - return -1; - } + if (OPJ_FSEEK(p_user_data, p_nb_bytes, SEEK_CUR)) { + return -1; + } - return p_nb_bytes; + return p_nb_bytes; } -static OPJ_BOOL opj_seek_from_file (OPJ_OFF_T p_nb_bytes, FILE * p_user_data) +static OPJ_BOOL opj_seek_from_file(OPJ_OFF_T p_nb_bytes, FILE * p_user_data) { - if (OPJ_FSEEK(p_user_data,p_nb_bytes,SEEK_SET)) { - return OPJ_FALSE; - } + if (OPJ_FSEEK(p_user_data, p_nb_bytes, SEEK_SET)) { + return OPJ_FALSE; + } - return OPJ_TRUE; + return OPJ_TRUE; } /* ---------------------------------------------------------------------- */ #ifdef _WIN32 #ifndef OPJ_STATIC BOOL APIENTRY -DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - - OPJ_ARG_NOT_USED(lpReserved); - OPJ_ARG_NOT_USED(hModule); +DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH : - break; - case DLL_PROCESS_DETACH : - break; - case DLL_THREAD_ATTACH : - case DLL_THREAD_DETACH : - break; + OPJ_ARG_NOT_USED(lpReserved); + OPJ_ARG_NOT_USED(hModule); + + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH : + break; + case DLL_PROCESS_DETACH : + break; + case DLL_THREAD_ATTACH : + case DLL_THREAD_DETACH : + break; } return TRUE; @@ -154,7 +157,8 @@ DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { /* ---------------------------------------------------------------------- */ -const char* OPJ_CALLCONV opj_version(void) { +const char* OPJ_CALLCONV opj_version(void) +{ return OPJ_PACKAGE_VERSION; } @@ -163,373 +167,445 @@ const char* OPJ_CALLCONV opj_version(void) { opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) { - opj_codec_private_t *l_codec = 00; - - l_codec = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t)); - if (!l_codec){ - return 00; - } - - l_codec->is_decompressor = 1; - - switch (p_format) { - case OPJ_CODEC_J2K: - l_codec->opj_dump_codec = (void (*) (void*, OPJ_INT32, FILE*)) j2k_dump; - - l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*) (void*) ) j2k_get_cstr_info; - - l_codec->opj_get_codec_index = (opj_codestream_index_t* (*) (void*) ) j2k_get_cstr_index; - - l_codec->m_codec_data.m_decompression.opj_decode = - (OPJ_BOOL (*) ( void *, - struct opj_stream_private *, - opj_image_t*, struct opj_event_mgr * )) opj_j2k_decode; - - l_codec->m_codec_data.m_decompression.opj_end_decompress = - (OPJ_BOOL (*) ( void *, - struct opj_stream_private *, - struct opj_event_mgr *)) opj_j2k_end_decompress; - - l_codec->m_codec_data.m_decompression.opj_read_header = - (OPJ_BOOL (*) ( struct opj_stream_private *, - void *, - opj_image_t **, - struct opj_event_mgr * )) opj_j2k_read_header; - - l_codec->m_codec_data.m_decompression.opj_destroy = - (void (*) (void *))opj_j2k_destroy; - - l_codec->m_codec_data.m_decompression.opj_setup_decoder = - (void (*) (void * , opj_dparameters_t * )) opj_j2k_setup_decoder; - - l_codec->m_codec_data.m_decompression.opj_read_tile_header = - (OPJ_BOOL (*) ( void *, - OPJ_UINT32*, - OPJ_UINT32*, - OPJ_INT32*, OPJ_INT32*, - OPJ_INT32*, OPJ_INT32*, - OPJ_UINT32*, - OPJ_BOOL*, - struct opj_stream_private *, - struct opj_event_mgr * )) opj_j2k_read_tile_header; - - l_codec->m_codec_data.m_decompression.opj_decode_tile_data = - (OPJ_BOOL (*) ( void *, - OPJ_UINT32, - OPJ_BYTE*, - OPJ_UINT32, - struct opj_stream_private *, - struct opj_event_mgr *)) opj_j2k_decode_tile; - - l_codec->m_codec_data.m_decompression.opj_set_decode_area = - (OPJ_BOOL (*) ( void *, - opj_image_t*, - OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, - struct opj_event_mgr *)) opj_j2k_set_decode_area; - - l_codec->m_codec_data.m_decompression.opj_get_decoded_tile = - (OPJ_BOOL (*) ( void *p_codec, - opj_stream_private_t *p_cio, - opj_image_t *p_image, - struct opj_event_mgr * p_manager, - OPJ_UINT32 tile_index)) opj_j2k_get_tile; - - l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor = - (OPJ_BOOL (*) ( void * p_codec, - OPJ_UINT32 res_factor, - struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_resolution_factor; - - l_codec->m_codec = opj_j2k_create_decompress(); - - if (! l_codec->m_codec) { - opj_free(l_codec); - return NULL; - } - - break; - - case OPJ_CODEC_JP2: - /* get a JP2 decoder handle */ - l_codec->opj_dump_codec = (void (*) (void*, OPJ_INT32, FILE*)) jp2_dump; - - l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*) (void*) ) jp2_get_cstr_info; - - l_codec->opj_get_codec_index = (opj_codestream_index_t* (*) (void*) ) jp2_get_cstr_index; - - l_codec->m_codec_data.m_decompression.opj_decode = - (OPJ_BOOL (*) ( void *, - struct opj_stream_private *, - opj_image_t*, - struct opj_event_mgr * )) opj_jp2_decode; - - l_codec->m_codec_data.m_decompression.opj_end_decompress = - (OPJ_BOOL (*) ( void *, - struct opj_stream_private *, - struct opj_event_mgr *)) opj_jp2_end_decompress; - - l_codec->m_codec_data.m_decompression.opj_read_header = - (OPJ_BOOL (*) ( struct opj_stream_private *, - void *, - opj_image_t **, - struct opj_event_mgr * )) opj_jp2_read_header; - - l_codec->m_codec_data.m_decompression.opj_read_tile_header = - (OPJ_BOOL (*) ( void *, - OPJ_UINT32*, - OPJ_UINT32*, - OPJ_INT32*, - OPJ_INT32*, - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_UINT32 * , - OPJ_BOOL *, - struct opj_stream_private *, - struct opj_event_mgr * )) opj_jp2_read_tile_header; - - l_codec->m_codec_data.m_decompression.opj_decode_tile_data = - (OPJ_BOOL (*) ( void *, - OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32, - struct opj_stream_private *, - struct opj_event_mgr * )) opj_jp2_decode_tile; - - l_codec->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))opj_jp2_destroy; - - l_codec->m_codec_data.m_decompression.opj_setup_decoder = - (void (*) (void * ,opj_dparameters_t * )) opj_jp2_setup_decoder; - - l_codec->m_codec_data.m_decompression.opj_set_decode_area = - (OPJ_BOOL (*) ( void *, - opj_image_t*, - OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, - struct opj_event_mgr * )) opj_jp2_set_decode_area; - - l_codec->m_codec_data.m_decompression.opj_get_decoded_tile = - (OPJ_BOOL (*) ( void *p_codec, - opj_stream_private_t *p_cio, - opj_image_t *p_image, - struct opj_event_mgr * p_manager, - OPJ_UINT32 tile_index)) opj_jp2_get_tile; - - l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor = - (OPJ_BOOL (*) ( void * p_codec, - OPJ_UINT32 res_factor, - opj_event_mgr_t * p_manager)) opj_jp2_set_decoded_resolution_factor; - - l_codec->m_codec = opj_jp2_create(OPJ_TRUE); - - if (! l_codec->m_codec) { - opj_free(l_codec); - return 00; - } - - break; - case OPJ_CODEC_UNKNOWN: - case OPJ_CODEC_JPT: - default: - opj_free(l_codec); - return 00; - } - - opj_set_default_event_handler(&(l_codec->m_event_mgr)); - return (opj_codec_t*) l_codec; -} - -void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters) { - if(parameters) { - memset(parameters, 0, sizeof(opj_dparameters_t)); - /* default decoding parameters */ - parameters->cp_layer = 0; - parameters->cp_reduce = 0; - - parameters->decod_format = -1; - parameters->cod_format = -1; - parameters->flags = 0; -/* UniPG>> */ + opj_codec_private_t *l_codec = 00; + + l_codec = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t)); + if (!l_codec) { + return 00; + } + + l_codec->is_decompressor = 1; + + switch (p_format) { + case OPJ_CODEC_J2K: + l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) j2k_dump; + + l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)( + void*)) j2k_get_cstr_info; + + l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)( + void*)) j2k_get_cstr_index; + + l_codec->m_codec_data.m_decompression.opj_decode = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + opj_image_t*, struct opj_event_mgr *)) opj_j2k_decode; + + l_codec->m_codec_data.m_decompression.opj_end_decompress = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_end_decompress; + + l_codec->m_codec_data.m_decompression.opj_read_header = + (OPJ_BOOL(*)(struct opj_stream_private *, + void *, + opj_image_t **, + struct opj_event_mgr *)) opj_j2k_read_header; + + l_codec->m_codec_data.m_decompression.opj_destroy = + (void (*)(void *))opj_j2k_destroy; + + l_codec->m_codec_data.m_decompression.opj_setup_decoder = + (void (*)(void *, opj_dparameters_t *)) opj_j2k_setup_decoder; + + l_codec->m_codec_data.m_decompression.opj_read_tile_header = + (OPJ_BOOL(*)(void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32*, OPJ_INT32*, + OPJ_INT32*, OPJ_INT32*, + OPJ_UINT32*, + OPJ_BOOL*, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_read_tile_header; + + l_codec->m_codec_data.m_decompression.opj_decode_tile_data = + (OPJ_BOOL(*)(void *, + OPJ_UINT32, + OPJ_BYTE*, + OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_decode_tile; + + l_codec->m_codec_data.m_decompression.opj_set_decode_area = + (OPJ_BOOL(*)(void *, + opj_image_t*, + OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, + struct opj_event_mgr *)) opj_j2k_set_decode_area; + + l_codec->m_codec_data.m_decompression.opj_get_decoded_tile = + (OPJ_BOOL(*)(void *p_codec, + opj_stream_private_t *p_cio, + opj_image_t *p_image, + struct opj_event_mgr * p_manager, + OPJ_UINT32 tile_index)) opj_j2k_get_tile; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 res_factor, + struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_resolution_factor; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_components = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32 * comps_indices, + struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_components; + + l_codec->opj_set_threads = + (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_j2k_set_threads; + + l_codec->m_codec = opj_j2k_create_decompress(); + + if (! l_codec->m_codec) { + opj_free(l_codec); + return NULL; + } + + break; + + case OPJ_CODEC_JP2: + /* get a JP2 decoder handle */ + l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) jp2_dump; + + l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)( + void*)) jp2_get_cstr_info; + + l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)( + void*)) jp2_get_cstr_index; + + l_codec->m_codec_data.m_decompression.opj_decode = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + opj_image_t*, + struct opj_event_mgr *)) opj_jp2_decode; + + l_codec->m_codec_data.m_decompression.opj_end_decompress = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_end_decompress; + + l_codec->m_codec_data.m_decompression.opj_read_header = + (OPJ_BOOL(*)(struct opj_stream_private *, + void *, + opj_image_t **, + struct opj_event_mgr *)) opj_jp2_read_header; + + l_codec->m_codec_data.m_decompression.opj_read_tile_header = + (OPJ_BOOL(*)(void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32*, + OPJ_INT32*, + OPJ_INT32 *, + OPJ_INT32 *, + OPJ_UINT32 *, + OPJ_BOOL *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_read_tile_header; + + l_codec->m_codec_data.m_decompression.opj_decode_tile_data = + (OPJ_BOOL(*)(void *, + OPJ_UINT32, OPJ_BYTE*, OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_decode_tile; + + l_codec->m_codec_data.m_decompression.opj_destroy = (void (*)( + void *))opj_jp2_destroy; + + l_codec->m_codec_data.m_decompression.opj_setup_decoder = + (void (*)(void *, opj_dparameters_t *)) opj_jp2_setup_decoder; + + l_codec->m_codec_data.m_decompression.opj_set_decode_area = + (OPJ_BOOL(*)(void *, + opj_image_t*, + OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, + struct opj_event_mgr *)) opj_jp2_set_decode_area; + + l_codec->m_codec_data.m_decompression.opj_get_decoded_tile = + (OPJ_BOOL(*)(void *p_codec, + opj_stream_private_t *p_cio, + opj_image_t *p_image, + struct opj_event_mgr * p_manager, + OPJ_UINT32 tile_index)) opj_jp2_get_tile; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager)) opj_jp2_set_decoded_resolution_factor; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_components = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32 * comps_indices, + struct opj_event_mgr * p_manager)) opj_jp2_set_decoded_components; + + l_codec->opj_set_threads = + (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_jp2_set_threads; + + l_codec->m_codec = opj_jp2_create(OPJ_TRUE); + + if (! l_codec->m_codec) { + opj_free(l_codec); + return 00; + } + + break; + case OPJ_CODEC_UNKNOWN: + case OPJ_CODEC_JPT: + default: + opj_free(l_codec); + return 00; + } + + opj_set_default_event_handler(&(l_codec->m_event_mgr)); + return (opj_codec_t*) l_codec; +} + +void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t + *parameters) +{ + if (parameters) { + memset(parameters, 0, sizeof(opj_dparameters_t)); + /* default decoding parameters */ + parameters->cp_layer = 0; + parameters->cp_reduce = 0; + + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->flags = 0; + /* UniPG>> */ #ifdef USE_JPWL - parameters->jpwl_correct = OPJ_FALSE; - parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; - parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; + parameters->jpwl_correct = OPJ_FALSE; + parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; + parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; #endif /* USE_JPWL */ -/* <<UniPG */ - } + /* <<UniPG */ + } +} + + +OPJ_BOOL OPJ_CALLCONV opj_codec_set_threads(opj_codec_t *p_codec, + int num_threads) +{ + if (p_codec && (num_threads >= 0)) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + return l_codec->opj_set_threads(l_codec->m_codec, (OPJ_UINT32)num_threads); + } + return OPJ_FALSE; } OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec, - opj_dparameters_t *parameters - ) -{ - if (p_codec && parameters) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - - if (! l_codec->is_decompressor) { - opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, - "Codec provided to the opj_setup_decoder function is not a decompressor handler.\n"); - return OPJ_FALSE; - } - - l_codec->m_codec_data.m_decompression.opj_setup_decoder(l_codec->m_codec, - parameters); - return OPJ_TRUE; - } - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_read_header ( opj_stream_t *p_stream, - opj_codec_t *p_codec, - opj_image_t **p_image ) -{ - if (p_codec && p_stream) { - opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - - if(! l_codec->is_decompressor) { - opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, - "Codec provided to the opj_read_header function is not a decompressor handler.\n"); - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_read_header( l_stream, - l_codec->m_codec, - p_image, - &(l_codec->m_event_mgr) ); - } - - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_decode( opj_codec_t *p_codec, - opj_stream_t *p_stream, - opj_image_t* p_image) -{ - if (p_codec && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_decode(l_codec->m_codec, - l_stream, - p_image, - &(l_codec->m_event_mgr) ); - } - - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec, - opj_image_t* p_image, - OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, OPJ_INT32 p_end_y - ) -{ - if (p_codec) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - - if (! l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_set_decode_area( l_codec->m_codec, - p_image, - p_start_x, p_start_y, - p_end_x, p_end_y, - &(l_codec->m_event_mgr) ); - } - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_read_tile_header( opj_codec_t *p_codec, - opj_stream_t * p_stream, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_should_go_on) -{ - if (p_codec && p_stream && p_data_size && p_tile_index) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_read_tile_header( l_codec->m_codec, - p_tile_index, - p_data_size, - p_tile_x0, p_tile_y0, - p_tile_x1, p_tile_y1, - p_nb_comps, - p_should_go_on, - l_stream, - &(l_codec->m_event_mgr)); - } - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_decode_tile_data( opj_codec_t *p_codec, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_t *p_stream - ) -{ - if (p_codec && p_data && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_decode_tile_data( l_codec->m_codec, - p_tile_index, - p_data, - p_data_size, - l_stream, - &(l_codec->m_event_mgr) ); - } - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_get_decoded_tile( opj_codec_t *p_codec, - opj_stream_t *p_stream, - opj_image_t *p_image, - OPJ_UINT32 tile_index) -{ - if (p_codec && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_get_decoded_tile( l_codec->m_codec, - l_stream, - p_image, - &(l_codec->m_event_mgr), - tile_index); - } - - return OPJ_FALSE; -} - -OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, - OPJ_UINT32 res_factor ) -{ - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - - if ( !l_codec ){ - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor(l_codec->m_codec, - res_factor, - &(l_codec->m_event_mgr) ); + opj_dparameters_t *parameters + ) +{ + if (p_codec && parameters) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_setup_decoder function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + l_codec->m_codec_data.m_decompression.opj_setup_decoder(l_codec->m_codec, + parameters); + return OPJ_TRUE; + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, + opj_codec_t *p_codec, + opj_image_t **p_image) +{ + if (p_codec && p_stream) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_read_header function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_read_header(l_stream, + l_codec->m_codec, + p_image, + &(l_codec->m_event_mgr)); + } + + return OPJ_FALSE; +} + + +OPJ_BOOL OPJ_CALLCONV opj_set_decoded_components(opj_codec_t *p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + OPJ_BOOL apply_color_transforms) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_set_decoded_components function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + if (apply_color_transforms) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "apply_color_transforms = OPJ_TRUE is not supported.\n"); + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_set_decoded_components( + l_codec->m_codec, + numcomps, + comps_indices, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_decode(opj_codec_t *p_codec, + opj_stream_t *p_stream, + opj_image_t* p_image) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_decode(l_codec->m_codec, + l_stream, + p_image, + &(l_codec->m_event_mgr)); + } + + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_decode_area(opj_codec_t *p_codec, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y + ) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_set_decode_area( + l_codec->m_codec, + p_image, + p_start_x, p_start_y, + p_end_x, p_end_y, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_read_tile_header(opj_codec_t *p_codec, + opj_stream_t * p_stream, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_should_go_on) +{ + if (p_codec && p_stream && p_data_size && p_tile_index) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_read_tile_header( + l_codec->m_codec, + p_tile_index, + p_data_size, + p_tile_x0, p_tile_y0, + p_tile_x1, p_tile_y1, + p_nb_comps, + p_should_go_on, + l_stream, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_decode_tile_data(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream + ) +{ + if (p_codec && p_data && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_decode_tile_data( + l_codec->m_codec, + p_tile_index, + p_data, + p_data_size, + l_stream, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_get_decoded_tile(opj_codec_t *p_codec, + opj_stream_t *p_stream, + opj_image_t *p_image, + OPJ_UINT32 tile_index) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_get_decoded_tile( + l_codec->m_codec, + l_stream, + p_image, + &(l_codec->m_event_mgr), + tile_index); + } + + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, + OPJ_UINT32 res_factor) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (!l_codec) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor( + l_codec->m_codec, + res_factor, + &(l_codec->m_event_mgr)); } /* ---------------------------------------------------------------------- */ @@ -537,395 +613,403 @@ OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) { - opj_codec_private_t *l_codec = 00; - - l_codec = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t)); - if (!l_codec) { - return 00; - } - - l_codec->is_decompressor = 0; - - switch(p_format) { - case OPJ_CODEC_J2K: - l_codec->m_codec_data.m_compression.opj_encode = (OPJ_BOOL (*) (void *, - struct opj_stream_private *, - struct opj_event_mgr * )) opj_j2k_encode; - - l_codec->m_codec_data.m_compression.opj_end_compress = (OPJ_BOOL (*) ( void *, - struct opj_stream_private *, - struct opj_event_mgr *)) opj_j2k_end_compress; - - l_codec->m_codec_data.m_compression.opj_start_compress = (OPJ_BOOL (*) (void *, - struct opj_stream_private *, - struct opj_image * , - struct opj_event_mgr *)) opj_j2k_start_compress; - - l_codec->m_codec_data.m_compression.opj_write_tile = (OPJ_BOOL (*) (void *, - OPJ_UINT32, - OPJ_BYTE*, - OPJ_UINT32, - struct opj_stream_private *, - struct opj_event_mgr *) ) opj_j2k_write_tile; - - l_codec->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) opj_j2k_destroy; - - l_codec->m_codec_data.m_compression.opj_setup_encoder = (OPJ_BOOL (*) ( void *, - opj_cparameters_t *, - struct opj_image *, - struct opj_event_mgr * )) opj_j2k_setup_encoder; - - l_codec->m_codec = opj_j2k_create_compress(); - if (! l_codec->m_codec) { - opj_free(l_codec); - return 00; - } - - break; - - case OPJ_CODEC_JP2: - /* get a JP2 decoder handle */ - l_codec->m_codec_data.m_compression.opj_encode = (OPJ_BOOL (*) (void *, - struct opj_stream_private *, - struct opj_event_mgr * )) opj_jp2_encode; - - l_codec->m_codec_data.m_compression.opj_end_compress = (OPJ_BOOL (*) ( void *, - struct opj_stream_private *, - struct opj_event_mgr *)) opj_jp2_end_compress; - - l_codec->m_codec_data.m_compression.opj_start_compress = (OPJ_BOOL (*) (void *, - struct opj_stream_private *, - struct opj_image * , - struct opj_event_mgr *)) opj_jp2_start_compress; - - l_codec->m_codec_data.m_compression.opj_write_tile = (OPJ_BOOL (*) (void *, - OPJ_UINT32, - OPJ_BYTE*, - OPJ_UINT32, - struct opj_stream_private *, - struct opj_event_mgr *)) opj_jp2_write_tile; - - l_codec->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) opj_jp2_destroy; - - l_codec->m_codec_data.m_compression.opj_setup_encoder = (OPJ_BOOL (*) ( void *, - opj_cparameters_t *, - struct opj_image *, - struct opj_event_mgr * )) opj_jp2_setup_encoder; - - l_codec->m_codec = opj_jp2_create(OPJ_FALSE); - if (! l_codec->m_codec) { - opj_free(l_codec); - return 00; - } - - break; - - case OPJ_CODEC_UNKNOWN: - case OPJ_CODEC_JPT: - default: - opj_free(l_codec); - return 00; - } - - opj_set_default_event_handler(&(l_codec->m_event_mgr)); - return (opj_codec_t*) l_codec; -} - -void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters) { - if(parameters) { - memset(parameters, 0, sizeof(opj_cparameters_t)); - /* default coding parameters */ + opj_codec_private_t *l_codec = 00; + + l_codec = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t)); + if (!l_codec) { + return 00; + } + + l_codec->is_decompressor = 0; + + switch (p_format) { + case OPJ_CODEC_J2K: + l_codec->m_codec_data.m_compression.opj_encode = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_encode; + + l_codec->m_codec_data.m_compression.opj_end_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_end_compress; + + l_codec->m_codec_data.m_compression.opj_start_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_image *, + struct opj_event_mgr *)) opj_j2k_start_compress; + + l_codec->m_codec_data.m_compression.opj_write_tile = (OPJ_BOOL(*)(void *, + OPJ_UINT32, + OPJ_BYTE*, + OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_write_tile; + + l_codec->m_codec_data.m_compression.opj_destroy = (void (*)( + void *)) opj_j2k_destroy; + + l_codec->m_codec_data.m_compression.opj_setup_encoder = (OPJ_BOOL(*)(void *, + opj_cparameters_t *, + struct opj_image *, + struct opj_event_mgr *)) opj_j2k_setup_encoder; + + l_codec->m_codec = opj_j2k_create_compress(); + if (! l_codec->m_codec) { + opj_free(l_codec); + return 00; + } + + break; + + case OPJ_CODEC_JP2: + /* get a JP2 decoder handle */ + l_codec->m_codec_data.m_compression.opj_encode = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_encode; + + l_codec->m_codec_data.m_compression.opj_end_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_end_compress; + + l_codec->m_codec_data.m_compression.opj_start_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_image *, + struct opj_event_mgr *)) opj_jp2_start_compress; + + l_codec->m_codec_data.m_compression.opj_write_tile = (OPJ_BOOL(*)(void *, + OPJ_UINT32, + OPJ_BYTE*, + OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_write_tile; + + l_codec->m_codec_data.m_compression.opj_destroy = (void (*)( + void *)) opj_jp2_destroy; + + l_codec->m_codec_data.m_compression.opj_setup_encoder = (OPJ_BOOL(*)(void *, + opj_cparameters_t *, + struct opj_image *, + struct opj_event_mgr *)) opj_jp2_setup_encoder; + + l_codec->m_codec = opj_jp2_create(OPJ_FALSE); + if (! l_codec->m_codec) { + opj_free(l_codec); + return 00; + } + + break; + + case OPJ_CODEC_UNKNOWN: + case OPJ_CODEC_JPT: + default: + opj_free(l_codec); + return 00; + } + + opj_set_default_event_handler(&(l_codec->m_event_mgr)); + return (opj_codec_t*) l_codec; +} + +void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t + *parameters) +{ + if (parameters) { + memset(parameters, 0, sizeof(opj_cparameters_t)); + /* default coding parameters */ parameters->cp_cinema = OPJ_OFF; /* DEPRECATED */ parameters->rsiz = OPJ_PROFILE_NONE; - parameters->max_comp_size = 0; - parameters->numresolution = 6; + parameters->max_comp_size = 0; + parameters->numresolution = 6; parameters->cp_rsiz = OPJ_STD_RSIZ; /* DEPRECATED */ - parameters->cblockw_init = 64; - parameters->cblockh_init = 64; - parameters->prog_order = OPJ_LRCP; - parameters->roi_compno = -1; /* no ROI */ - parameters->subsampling_dx = 1; - parameters->subsampling_dy = 1; - parameters->tp_on = 0; - parameters->decod_format = -1; - parameters->cod_format = -1; - parameters->tcp_rates[0] = 0; - parameters->tcp_numlayers = 0; - parameters->cp_disto_alloc = 0; - parameters->cp_fixed_alloc = 0; - parameters->cp_fixed_quality = 0; - parameters->jpip_on = OPJ_FALSE; -/* UniPG>> */ + parameters->cblockw_init = 64; + parameters->cblockh_init = 64; + parameters->prog_order = OPJ_LRCP; + parameters->roi_compno = -1; /* no ROI */ + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; + parameters->tp_on = 0; + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->tcp_rates[0] = 0; + parameters->tcp_numlayers = 0; + parameters->cp_disto_alloc = 0; + parameters->cp_fixed_alloc = 0; + parameters->cp_fixed_quality = 0; + parameters->jpip_on = OPJ_FALSE; + /* UniPG>> */ #ifdef USE_JPWL - parameters->jpwl_epc_on = OPJ_FALSE; - parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */ - { - int i; - for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { - parameters->jpwl_hprot_TPH_tileno[i] = -1; /* unassigned */ - parameters->jpwl_hprot_TPH[i] = 0; /* absent */ - } - }; - { - int i; - for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { - parameters->jpwl_pprot_tileno[i] = -1; /* unassigned */ - parameters->jpwl_pprot_packno[i] = -1; /* unassigned */ - parameters->jpwl_pprot[i] = 0; /* absent */ - } - }; - parameters->jpwl_sens_size = 0; /* 0 means no ESD */ - parameters->jpwl_sens_addr = 0; /* 0 means auto */ - parameters->jpwl_sens_range = 0; /* 0 means packet */ - parameters->jpwl_sens_MH = -1; /* -1 means unassigned */ - { - int i; - for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { - parameters->jpwl_sens_TPH_tileno[i] = -1; /* unassigned */ - parameters->jpwl_sens_TPH[i] = -1; /* absent */ - } - }; + parameters->jpwl_epc_on = OPJ_FALSE; + parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_hprot_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_hprot_TPH[i] = 0; /* absent */ + } + }; + { + int i; + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + parameters->jpwl_pprot_tileno[i] = -1; /* unassigned */ + parameters->jpwl_pprot_packno[i] = -1; /* unassigned */ + parameters->jpwl_pprot[i] = 0; /* absent */ + } + }; + parameters->jpwl_sens_size = 0; /* 0 means no ESD */ + parameters->jpwl_sens_addr = 0; /* 0 means auto */ + parameters->jpwl_sens_range = 0; /* 0 means packet */ + parameters->jpwl_sens_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_sens_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_sens_TPH[i] = -1; /* absent */ + } + }; #endif /* USE_JPWL */ -/* <<UniPG */ - } + /* <<UniPG */ + } } -OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec, - opj_cparameters_t *parameters, - opj_image_t *p_image) +OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec, + opj_cparameters_t *parameters, + opj_image_t *p_image) { - if (p_codec && parameters && p_image) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - - if (! l_codec->is_decompressor) { - return l_codec->m_codec_data.m_compression.opj_setup_encoder( l_codec->m_codec, - parameters, - p_image, - &(l_codec->m_event_mgr) ); - } - } + if (p_codec && parameters && p_image) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_setup_encoder(l_codec->m_codec, + parameters, + p_image, + &(l_codec->m_event_mgr)); + } + } - return OPJ_FALSE; + return OPJ_FALSE; } -OPJ_BOOL OPJ_CALLCONV opj_start_compress ( opj_codec_t *p_codec, - opj_image_t * p_image, - opj_stream_t *p_stream) +OPJ_BOOL OPJ_CALLCONV opj_start_compress(opj_codec_t *p_codec, + opj_image_t * p_image, + opj_stream_t *p_stream) { - if (p_codec && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return l_codec->m_codec_data.m_compression.opj_start_compress( l_codec->m_codec, - l_stream, - p_image, - &(l_codec->m_event_mgr)); - } - } + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_start_compress(l_codec->m_codec, + l_stream, + p_image, + &(l_codec->m_event_mgr)); + } + } - return OPJ_FALSE; + return OPJ_FALSE; } OPJ_BOOL OPJ_CALLCONV opj_encode(opj_codec_t *p_info, opj_stream_t *p_stream) { - if (p_info && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return l_codec->m_codec_data.m_compression.opj_encode( l_codec->m_codec, - l_stream, - &(l_codec->m_event_mgr)); - } - } + if (p_info && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_encode(l_codec->m_codec, + l_stream, + &(l_codec->m_event_mgr)); + } + } - return OPJ_FALSE; + return OPJ_FALSE; } -OPJ_BOOL OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec, - opj_stream_t *p_stream) +OPJ_BOOL OPJ_CALLCONV opj_end_compress(opj_codec_t *p_codec, + opj_stream_t *p_stream) { - if (p_codec && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec, - l_stream, - &(l_codec->m_event_mgr)); - } - } - return OPJ_FALSE; + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec, + l_stream, + &(l_codec->m_event_mgr)); + } + } + return OPJ_FALSE; } -OPJ_BOOL OPJ_CALLCONV opj_end_decompress ( opj_codec_t *p_codec, - opj_stream_t *p_stream) +OPJ_BOOL OPJ_CALLCONV opj_end_decompress(opj_codec_t *p_codec, + opj_stream_t *p_stream) { - if (p_codec && p_stream) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (! l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_decompression.opj_end_decompress(l_codec->m_codec, - l_stream, - &(l_codec->m_event_mgr) ); - } + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_end_decompress( + l_codec->m_codec, + l_stream, + &(l_codec->m_event_mgr)); + } - return OPJ_FALSE; + return OPJ_FALSE; } OPJ_BOOL OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters, OPJ_FLOAT32 * pEncodingMatrix, - OPJ_INT32 * p_dc_shift,OPJ_UINT32 pNbComp) + OPJ_INT32 * p_dc_shift, OPJ_UINT32 pNbComp) { - OPJ_UINT32 l_matrix_size = pNbComp * pNbComp * (OPJ_UINT32)sizeof(OPJ_FLOAT32); - OPJ_UINT32 l_dc_shift_size = pNbComp * (OPJ_UINT32)sizeof(OPJ_INT32); - OPJ_UINT32 l_mct_total_size = l_matrix_size + l_dc_shift_size; + OPJ_UINT32 l_matrix_size = pNbComp * pNbComp * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + OPJ_UINT32 l_dc_shift_size = pNbComp * (OPJ_UINT32)sizeof(OPJ_INT32); + OPJ_UINT32 l_mct_total_size = l_matrix_size + l_dc_shift_size; - /* add MCT capability */ + /* add MCT capability */ if (OPJ_IS_PART2(parameters->rsiz)) { parameters->rsiz |= OPJ_EXTENSION_MCT; } else { parameters->rsiz = ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_MCT)); } - parameters->irreversible = 1; + parameters->irreversible = 1; - /* use array based MCT */ - parameters->tcp_mct = 2; - parameters->mct_data = opj_malloc(l_mct_total_size); - if (! parameters->mct_data) { - return OPJ_FALSE; - } + /* use array based MCT */ + parameters->tcp_mct = 2; + parameters->mct_data = opj_malloc(l_mct_total_size); + if (! parameters->mct_data) { + return OPJ_FALSE; + } - memcpy(parameters->mct_data,pEncodingMatrix,l_matrix_size); - memcpy(((OPJ_BYTE *) parameters->mct_data) + l_matrix_size,p_dc_shift,l_dc_shift_size); + memcpy(parameters->mct_data, pEncodingMatrix, l_matrix_size); + memcpy(((OPJ_BYTE *) parameters->mct_data) + l_matrix_size, p_dc_shift, + l_dc_shift_size); - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_BOOL OPJ_CALLCONV opj_write_tile ( opj_codec_t *p_codec, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_t *p_stream ) +OPJ_BOOL OPJ_CALLCONV opj_write_tile(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream) { - if (p_codec && p_stream && p_data) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; - - if (l_codec->is_decompressor) { - return OPJ_FALSE; - } - - return l_codec->m_codec_data.m_compression.opj_write_tile( l_codec->m_codec, - p_tile_index, - p_data, - p_data_size, - l_stream, - &(l_codec->m_event_mgr) ); - } + if (p_codec && p_stream && p_data) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_compression.opj_write_tile(l_codec->m_codec, + p_tile_index, + p_data, + p_data_size, + l_stream, + &(l_codec->m_event_mgr)); + } - return OPJ_FALSE; + return OPJ_FALSE; } /* ---------------------------------------------------------------------- */ void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_codec) { - if (p_codec) { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - if (l_codec->is_decompressor) { - l_codec->m_codec_data.m_decompression.opj_destroy(l_codec->m_codec); - } - else { - l_codec->m_codec_data.m_compression.opj_destroy(l_codec->m_codec); - } + if (l_codec->is_decompressor) { + l_codec->m_codec_data.m_decompression.opj_destroy(l_codec->m_codec); + } else { + l_codec->m_codec_data.m_compression.opj_destroy(l_codec->m_codec); + } - l_codec->m_codec = 00; - opj_free(l_codec); - } + l_codec->m_codec = 00; + opj_free(l_codec); + } } /* ---------------------------------------------------------------------- */ -void OPJ_CALLCONV opj_dump_codec( opj_codec_t *p_codec, - OPJ_INT32 info_flag, - FILE* output_stream) +void OPJ_CALLCONV opj_dump_codec(opj_codec_t *p_codec, + OPJ_INT32 info_flag, + FILE* output_stream) { - if (p_codec) { - opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + if (p_codec) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; - l_codec->opj_dump_codec(l_codec->m_codec, info_flag, output_stream); - return; - } + l_codec->opj_dump_codec(l_codec->m_codec, info_flag, output_stream); + return; + } - /* TODO return error */ - /* fprintf(stderr, "[ERROR] Input parameter of the dump_codec function are incorrect.\n"); */ - return; + /* TODO return error */ + /* fprintf(stderr, "[ERROR] Input parameter of the dump_codec function are incorrect.\n"); */ + return; } opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info(opj_codec_t *p_codec) { - if (p_codec) { - opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + if (p_codec) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; - return l_codec->opj_get_codec_info(l_codec->m_codec); - } + return l_codec->opj_get_codec_info(l_codec->m_codec); + } - return NULL; + return NULL; } -void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t **cstr_info) { - if (cstr_info) { +void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t **cstr_info) +{ + if (cstr_info) { - if ((*cstr_info)->m_default_tile_info.tccp_info){ - opj_free((*cstr_info)->m_default_tile_info.tccp_info); - } + if ((*cstr_info)->m_default_tile_info.tccp_info) { + opj_free((*cstr_info)->m_default_tile_info.tccp_info); + } - if ((*cstr_info)->tile_info){ - /* FIXME not used for the moment*/ - } + if ((*cstr_info)->tile_info) { + /* FIXME not used for the moment*/ + } - opj_free((*cstr_info)); - (*cstr_info) = NULL; - } + opj_free((*cstr_info)); + (*cstr_info) = NULL; + } } opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index(opj_codec_t *p_codec) { - if (p_codec) { - opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + if (p_codec) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; - return l_codec->opj_get_codec_index(l_codec->m_codec); - } + return l_codec->opj_get_codec_index(l_codec->m_codec); + } - return NULL; + return NULL; } void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index) { - if (*p_cstr_index){ - j2k_destroy_cstr_index(*p_cstr_index); - (*p_cstr_index) = NULL; - } + if (*p_cstr_index) { + j2k_destroy_cstr_index(*p_cstr_index); + (*p_cstr_index) = NULL; + } } -opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (const char *fname, OPJ_BOOL p_is_read_stream) +opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream( + const char *fname, OPJ_BOOL p_is_read_stream) { - return opj_stream_create_file_stream(fname, OPJ_J2K_STREAM_CHUNK_SIZE, p_is_read_stream); + return opj_stream_create_file_stream(fname, OPJ_J2K_STREAM_CHUNK_SIZE, + p_is_read_stream); } -opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream ( - const char *fname, - OPJ_SIZE_T p_size, - OPJ_BOOL p_is_read_stream) +opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream( + const char *fname, + OPJ_SIZE_T p_size, + OPJ_BOOL p_is_read_stream) { opj_stream_t* l_stream = 00; FILE *p_file; @@ -934,27 +1018,48 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream ( if (! fname) { return NULL; } - - if(p_is_read_stream) mode = "rb"; else mode = "wb"; + + if (p_is_read_stream) { + mode = "rb"; + } else { + mode = "wb"; + } p_file = fopen(fname, mode); if (! p_file) { - return NULL; + return NULL; } - l_stream = opj_stream_create(p_size,p_is_read_stream); + l_stream = opj_stream_create(p_size, p_is_read_stream); if (! l_stream) { fclose(p_file); return NULL; } - opj_stream_set_user_data(l_stream, p_file, (opj_stream_free_user_data_fn) fclose); - opj_stream_set_user_data_length(l_stream, opj_get_data_length_from_file(p_file)); + opj_stream_set_user_data(l_stream, p_file, + (opj_stream_free_user_data_fn) fclose); + opj_stream_set_user_data_length(l_stream, + opj_get_data_length_from_file(p_file)); opj_stream_set_read_function(l_stream, (opj_stream_read_fn) opj_read_from_file); - opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_file); + opj_stream_set_write_function(l_stream, + (opj_stream_write_fn) opj_write_from_file); opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_file); opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn) opj_seek_from_file); return l_stream; } + + +void* OPJ_CALLCONV opj_image_data_alloc(OPJ_SIZE_T size) +{ + void* ret = opj_aligned_malloc(size); + /* printf("opj_image_data_alloc %p\n", ret); */ + return ret; +} + +void OPJ_CALLCONV opj_image_data_free(void* ptr) +{ + /* printf("opj_image_data_free %p\n", ptr); */ + opj_aligned_free(ptr); +} diff --git a/third_party/libopenjpeg20/openjpeg.h b/third_party/libopenjpeg20/openjpeg.h index e571672236bb4c8cb190bfc099f7bfce2692fbf7..c119e8f89739cedbb5ec02053ae1fd5801de8b55 100644 --- a/third_party/libopenjpeg20/openjpeg.h +++ b/third_party/libopenjpeg20/openjpeg.h @@ -1,110 +1,110 @@ - /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third - * party and contributor rights, including patent rights, and no such rights - * are granted under this license. - * - * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2014, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux - * Copyright (c) 2003-2014, Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2006-2007, Parvatha Elangovan - * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> - * Copyright (c) 2010-2011, Kaori Hagihara - * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France - * Copyright (c) 2012, CS Systemes d'Information, France - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* +* The copyright in this software is being made available under the 2-clauses +* BSD License, included below. This software may be subject to other third +* party and contributor rights, including patent rights, and no such rights +* are granted under this license. +* +* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium +* Copyright (c) 2002-2014, Professor Benoit Macq +* Copyright (c) 2001-2003, David Janssens +* Copyright (c) 2002-2003, Yannick Verschueren +* Copyright (c) 2003-2007, Francois-Olivier Devaux +* Copyright (c) 2003-2014, Antonin Descampe +* Copyright (c) 2005, Herve Drolon, FreeImage Team +* Copyright (c) 2006-2007, Parvatha Elangovan +* Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> +* Copyright (c) 2010-2011, Kaori Hagihara +* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France +* Copyright (c) 2012, CS Systemes d'Information, France +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ #ifndef OPENJPEG_H #define OPENJPEG_H -/* +/* ========================================================== Compiler directives ========================================================== */ /* -The inline keyword is supported by C99 but not by C90. -Most compilers implement their own version of this keyword ... +The inline keyword is supported by C99 but not by C90. +Most compilers implement their own version of this keyword ... */ #ifndef INLINE - #if defined(_MSC_VER) - #define INLINE __forceinline - #elif defined(__GNUC__) - #define INLINE __inline__ - #elif defined(__MWERKS__) - #define INLINE inline - #else - /* add other compilers here ... */ - #define INLINE - #endif /* defined(<Compiler>) */ +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(__MWERKS__) +#define INLINE inline +#else +/* add other compilers here ... */ +#define INLINE +#endif /* defined(<Compiler>) */ #endif /* INLINE */ /* deprecated attribute */ #ifdef __GNUC__ - #define OPJ_DEPRECATED(func) func __attribute__ ((deprecated)) +#define OPJ_DEPRECATED(func) func __attribute__ ((deprecated)) #elif defined(_MSC_VER) - #define OPJ_DEPRECATED(func) __declspec(deprecated) func +#define OPJ_DEPRECATED(func) __declspec(deprecated) func #else - #pragma message("WARNING: You need to implement DEPRECATED for this compiler") - #define OPJ_DEPRECATED(func) func +#pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define OPJ_DEPRECATED(func) func #endif #if defined(OPJ_STATIC) || !defined(_WIN32) /* http://gcc.gnu.org/wiki/Visibility */ -# if __GNUC__ >= 4 -# if defined(OPJ_STATIC) /* static library uses "hidden" */ -# define OPJ_API __attribute__ ((visibility ("hidden"))) -# else -# define OPJ_API __attribute__ ((visibility ("default"))) -# endif -# define OPJ_LOCAL __attribute__ ((visibility ("hidden"))) -# else -# define OPJ_API -# define OPJ_LOCAL -# endif -# define OPJ_CALLCONV +# if __GNUC__ >= 4 +# if defined(OPJ_STATIC) /* static library uses "hidden" */ +# define OPJ_API __attribute__ ((visibility ("hidden"))) +# else +# define OPJ_API __attribute__ ((visibility ("default"))) +# endif +# define OPJ_LOCAL __attribute__ ((visibility ("hidden"))) +# else +# define OPJ_API +# define OPJ_LOCAL +# endif +# define OPJ_CALLCONV #else -# define OPJ_CALLCONV __stdcall +# define OPJ_CALLCONV __stdcall /* -The following ifdef block is the standard way of creating macros which make exporting +The following ifdef block is the standard way of creating macros which make exporting from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS symbol defined on the command line. this symbol should not be defined on any project -that uses this DLL. This way any other project whose source files include this file see +that uses this DLL. This way any other project whose source files include this file see OPJ_API functions as being imported from a DLL, whereas this DLL sees symbols defined with this macro as being exported. */ -# if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) -# define OPJ_API __declspec(dllexport) -# else -# define OPJ_API __declspec(dllimport) -# endif /* OPJ_EXPORTS */ +# if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) +# define OPJ_API __declspec(dllexport) +# else +# define OPJ_API __declspec(dllimport) +# endif /* OPJ_EXPORTS */ #endif /* !OPJ_STATIC || !_WIN32 */ typedef int OPJ_BOOL; @@ -135,7 +135,7 @@ typedef size_t OPJ_SIZE_T; /* Avoid compile-time warning because parameter is not used */ #define OPJ_ARG_NOT_USED(x) (void)(x) -/* +/* ========================================================== Useful constant definitions ========================================================== @@ -143,19 +143,19 @@ typedef size_t OPJ_SIZE_T; #define OPJ_PATH_LEN 4096 /**< Maximum allowed size for filenames */ -#define OPJ_J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ -#define OPJ_J2K_MAXBANDS (3*OPJ_J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ +#define OPJ_J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ +#define OPJ_J2K_MAXBANDS (3*OPJ_J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ -#define OPJ_J2K_DEFAULT_NB_SEGS 10 -#define OPJ_J2K_STREAM_CHUNK_SIZE 0x100000 /** 1 mega by default */ -#define OPJ_J2K_DEFAULT_HEADER_SIZE 1000 -#define OPJ_J2K_MCC_DEFAULT_NB_RECORDS 10 -#define OPJ_J2K_MCT_DEFAULT_NB_RECORDS 10 +#define OPJ_J2K_DEFAULT_NB_SEGS 10 +#define OPJ_J2K_STREAM_CHUNK_SIZE 0x100000 /** 1 mega by default */ +#define OPJ_J2K_DEFAULT_HEADER_SIZE 1000 +#define OPJ_J2K_MCC_DEFAULT_NB_RECORDS 10 +#define OPJ_J2K_MCT_DEFAULT_NB_RECORDS 10 /* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ -#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */ -#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */ -#define JPWL_MAX_NO_MARKERS 512 /**< Maximum number of JPWL markers: increase at your will */ +#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_MARKERS 512 /**< Maximum number of JPWL markers: increase at your will */ #define JPWL_PRIVATEINDEX_NAME "jpwl_index_privatefilename" /**< index file name used when JPWL is on */ #define JPWL_EXPECTED_COMPONENTS 3 /**< Expect this number of components, so you'll find better the first EPB */ #define JPWL_MAXIMUM_TILES 8192 /**< Expect this maximum number of tiles, to avoid some crashes */ @@ -167,19 +167,19 @@ typedef size_t OPJ_SIZE_T; * EXPERIMENTAL FOR THE MOMENT * Supported options about file information used only in j2k_dump */ -#define OPJ_IMG_INFO 1 /**< Basic image information provided to the user */ -#define OPJ_J2K_MH_INFO 2 /**< Codestream information based only on the main header */ -#define OPJ_J2K_TH_INFO 4 /**< Tile information based on the current tile header */ -#define OPJ_J2K_TCH_INFO 8 /**< Tile/Component information of all tiles */ -#define OPJ_J2K_MH_IND 16 /**< Codestream index based only on the main header */ -#define OPJ_J2K_TH_IND 32 /**< Tile index based on the current tile */ -/*FIXME #define OPJ_J2K_CSTR_IND 48*/ /**< */ -#define OPJ_JP2_INFO 128 /**< JP2 file information */ -#define OPJ_JP2_IND 256 /**< JP2 file index */ +#define OPJ_IMG_INFO 1 /**< Basic image information provided to the user */ +#define OPJ_J2K_MH_INFO 2 /**< Codestream information based only on the main header */ +#define OPJ_J2K_TH_INFO 4 /**< Tile information based on the current tile header */ +#define OPJ_J2K_TCH_INFO 8 /**< Tile/Component information of all tiles */ +#define OPJ_J2K_MH_IND 16 /**< Codestream index based only on the main header */ +#define OPJ_J2K_TH_IND 32 /**< Tile index based on the current tile */ +/*FIXME #define OPJ_J2K_CSTR_IND 48*/ /**< */ +#define OPJ_JP2_INFO 128 /**< JP2 file information */ +#define OPJ_JP2_IND 256 /**< JP2 file index */ /** * JPEG 2000 Profiles, see Table A.10 from 15444-1 (updated in various AMD) - * These values help chosing the RSIZ value for the J2K codestream. + * These values help choosing the RSIZ value for the J2K codestream. * The RSIZ value triggers various encoding options, as detailed in Table A.10. * If OPJ_PROFILE_PART2 is chosen, it has to be combined with one or more extensions * described hereunder. @@ -228,12 +228,12 @@ typedef size_t OPJ_SIZE_T; /** * JPEG 2000 codestream and component size limits in cinema profiles * */ -#define OPJ_CINEMA_24_CS 1302083 /** Maximum codestream length for 24fps */ +#define OPJ_CINEMA_24_CS 1302083 /** Maximum codestream length for 24fps */ #define OPJ_CINEMA_48_CS 651041 /** Maximum codestream length for 48fps */ #define OPJ_CINEMA_24_COMP 1041666 /** Maximum size per color component for 2K & 4K @ 24fps */ -#define OPJ_CINEMA_48_COMP 520833 /** Maximum size per color component for 2K @ 48fps */ +#define OPJ_CINEMA_48_COMP 520833 /** Maximum size per color component for 2K @ 48fps */ -/* +/* ========================================================== enum definitions ========================================================== @@ -244,9 +244,9 @@ typedef size_t OPJ_SIZE_T; * Rsiz Capabilities * */ typedef enum RSIZ_CAPABILITIES { - OPJ_STD_RSIZ = 0, /** Standard JPEG2000 profile*/ - OPJ_CINEMA2K = 3, /** Profile name for a 2K image*/ - OPJ_CINEMA4K = 4, /** Profile name for a 4K image*/ + OPJ_STD_RSIZ = 0, /** Standard JPEG2000 profile*/ + OPJ_CINEMA2K = 3, /** Profile name for a 2K image*/ + OPJ_CINEMA4K = 4, /** Profile name for a 4K image*/ OPJ_MCT = 0x8100 } OPJ_RSIZ_CAPABILITIES; @@ -255,33 +255,33 @@ typedef enum RSIZ_CAPABILITIES { * Digital cinema operation mode * */ typedef enum CINEMA_MODE { - OPJ_OFF = 0, /** Not Digital Cinema*/ - OPJ_CINEMA2K_24 = 1, /** 2K Digital Cinema at 24 fps*/ - OPJ_CINEMA2K_48 = 2, /** 2K Digital Cinema at 48 fps*/ - OPJ_CINEMA4K_24 = 3 /** 4K Digital Cinema at 24 fps*/ -}OPJ_CINEMA_MODE; + OPJ_OFF = 0, /** Not Digital Cinema*/ + OPJ_CINEMA2K_24 = 1, /** 2K Digital Cinema at 24 fps*/ + OPJ_CINEMA2K_48 = 2, /** 2K Digital Cinema at 48 fps*/ + OPJ_CINEMA4K_24 = 3 /** 4K Digital Cinema at 24 fps*/ +} OPJ_CINEMA_MODE; -/** +/** * Progression order * */ typedef enum PROG_ORDER { - OPJ_PROG_UNKNOWN = -1, /**< place-holder */ - OPJ_LRCP = 0, /**< layer-resolution-component-precinct order */ - OPJ_RLCP = 1, /**< resolution-layer-component-precinct order */ - OPJ_RPCL = 2, /**< resolution-precinct-component-layer order */ - OPJ_PCRL = 3, /**< precinct-component-resolution-layer order */ - OPJ_CPRL = 4 /**< component-precinct-resolution-layer order */ + OPJ_PROG_UNKNOWN = -1, /**< place-holder */ + OPJ_LRCP = 0, /**< layer-resolution-component-precinct order */ + OPJ_RLCP = 1, /**< resolution-layer-component-precinct order */ + OPJ_RPCL = 2, /**< resolution-precinct-component-layer order */ + OPJ_PCRL = 3, /**< precinct-component-resolution-layer order */ + OPJ_CPRL = 4 /**< component-precinct-resolution-layer order */ } OPJ_PROG_ORDER; /** * Supported image color spaces */ typedef enum COLOR_SPACE { - OPJ_CLRSPC_UNKNOWN = -1, /**< not supported by the library */ - OPJ_CLRSPC_UNSPECIFIED = 0, /**< not specified in the codestream */ - OPJ_CLRSPC_SRGB = 1, /**< sRGB */ - OPJ_CLRSPC_GRAY = 2, /**< grayscale */ - OPJ_CLRSPC_SYCC = 3, /**< YUV */ + OPJ_CLRSPC_UNKNOWN = -1, /**< not supported by the library */ + OPJ_CLRSPC_UNSPECIFIED = 0, /**< not specified in the codestream */ + OPJ_CLRSPC_SRGB = 1, /**< sRGB */ + OPJ_CLRSPC_GRAY = 2, /**< grayscale */ + OPJ_CLRSPC_SYCC = 3, /**< YUV */ OPJ_CLRSPC_EYCC = 4, /**< e-YCC */ OPJ_CLRSPC_CMYK = 5 /**< CMYK */ } OPJ_COLOR_SPACE; @@ -290,16 +290,16 @@ typedef enum COLOR_SPACE { * Supported codec */ typedef enum CODEC_FORMAT { - OPJ_CODEC_UNKNOWN = -1, /**< place-holder */ - OPJ_CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */ - OPJ_CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */ - OPJ_CODEC_JP2 = 2, /**< JP2 file format : read/write */ - OPJ_CODEC_JPP = 3, /**< JPP-stream (JPEG 2000, JPIP) : to be coded */ - OPJ_CODEC_JPX = 4 /**< JPX file format (JPEG 2000 Part-2) : to be coded */ + OPJ_CODEC_UNKNOWN = -1, /**< place-holder */ + OPJ_CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */ + OPJ_CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */ + OPJ_CODEC_JP2 = 2, /**< JP2 file format : read/write */ + OPJ_CODEC_JPP = 3, /**< JPP-stream (JPEG 2000, JPIP) : to be coded */ + OPJ_CODEC_JPX = 4 /**< JPX file format (JPEG 2000 Part-2) : to be coded */ } OPJ_CODEC_FORMAT; -/* +/* ========================================================== event manager typedef definitions ========================================================== @@ -308,11 +308,11 @@ typedef enum CODEC_FORMAT { /** * Callback function prototype for events * @param msg Event message - * @param client_data Client object where will be return the event message + * @param client_data Client object where will be return the event message * */ -typedef void (*opj_msg_callback) (const char *msg, void *client_data); +typedef void (*opj_msg_callback)(const char *msg, void *client_data); -/* +/* ========================================================== codec typedef definitions ========================================================== @@ -320,147 +320,150 @@ typedef void (*opj_msg_callback) (const char *msg, void *client_data); /** * Progression order changes - * + * */ typedef struct opj_poc { - /** Resolution num start, Component num start, given by POC */ - OPJ_UINT32 resno0, compno0; - /** Layer num end,Resolution num end, Component num end, given by POC */ - OPJ_UINT32 layno1, resno1, compno1; - /** Layer num start,Precinct num start, Precinct num end */ - OPJ_UINT32 layno0, precno0, precno1; - /** Progression order enum*/ - OPJ_PROG_ORDER prg1,prg; - /** Progression order string*/ - OPJ_CHAR progorder[5]; - /** Tile number */ - OPJ_UINT32 tile; - /** Start and end values for Tile width and height*/ - OPJ_INT32 tx0,tx1,ty0,ty1; - /** Start value, initialised in pi_initialise_encode*/ - OPJ_UINT32 layS, resS, compS, prcS; - /** End value, initialised in pi_initialise_encode */ - OPJ_UINT32 layE, resE, compE, prcE; - /** Start and end values of Tile width and height, initialised in pi_initialise_encode*/ - OPJ_UINT32 txS,txE,tyS,tyE,dx,dy; - /** Temporary values for Tile parts, initialised in pi_create_encode */ - OPJ_UINT32 lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t; + /** Resolution num start, Component num start, given by POC */ + OPJ_UINT32 resno0, compno0; + /** Layer num end,Resolution num end, Component num end, given by POC */ + OPJ_UINT32 layno1, resno1, compno1; + /** Layer num start,Precinct num start, Precinct num end */ + OPJ_UINT32 layno0, precno0, precno1; + /** Progression order enum*/ + OPJ_PROG_ORDER prg1, prg; + /** Progression order string*/ + OPJ_CHAR progorder[5]; + /** Tile number */ + OPJ_UINT32 tile; + /** Start and end values for Tile width and height*/ + OPJ_INT32 tx0, tx1, ty0, ty1; + /** Start value, initialised in pi_initialise_encode*/ + OPJ_UINT32 layS, resS, compS, prcS; + /** End value, initialised in pi_initialise_encode */ + OPJ_UINT32 layE, resE, compE, prcE; + /** Start and end values of Tile width and height, initialised in pi_initialise_encode*/ + OPJ_UINT32 txS, txE, tyS, tyE, dx, dy; + /** Temporary values for Tile parts, initialised in pi_create_encode */ + OPJ_UINT32 lay_t, res_t, comp_t, prc_t, tx0_t, ty0_t; } opj_poc_t; /** * Compression parameters * */ typedef struct opj_cparameters { - /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ - OPJ_BOOL tile_size_on; - /** XTOsiz */ - int cp_tx0; - /** YTOsiz */ - int cp_ty0; - /** XTsiz */ - int cp_tdx; - /** YTsiz */ - int cp_tdy; - /** allocation by rate/distortion */ - int cp_disto_alloc; - /** allocation by fixed layer */ - int cp_fixed_alloc; - /** add fixed_quality */ - int cp_fixed_quality; - /** fixed layer */ - int *cp_matrice; - /** comment for coding */ - char *cp_comment; - /** csty : coding style */ - int csty; - /** progression order (default OPJ_LRCP) */ - OPJ_PROG_ORDER prog_order; - /** progression order changes */ - opj_poc_t POC[32]; - /** number of progression order changes (POC), default to 0 */ - OPJ_UINT32 numpocs; - /** number of layers */ - int tcp_numlayers; - /** rates of layers - might be subsequently limited by the max_cs_size field */ - float tcp_rates[100]; - /** different psnr for successive layers */ - float tcp_distoratio[100]; - /** number of resolutions */ - int numresolution; - /** initial code block width, default to 64 */ - int cblockw_init; - /** initial code block height, default to 64 */ - int cblockh_init; - /** mode switch (cblk_style) */ - int mode; - /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */ - int irreversible; - /** region of interest: affected component in [0..3], -1 means no ROI */ - int roi_compno; - /** region of interest: upshift value */ - int roi_shift; - /* number of precinct size specifications */ - int res_spec; - /** initial precinct width */ - int prcw_init[OPJ_J2K_MAXRLVLS]; - /** initial precinct height */ - int prch_init[OPJ_J2K_MAXRLVLS]; - - /**@name command line encoder parameters (not used inside the library) */ - /*@{*/ - /** input file name */ - char infile[OPJ_PATH_LEN]; - /** output file name */ - char outfile[OPJ_PATH_LEN]; - /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */ - int index_on; - /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */ - char index[OPJ_PATH_LEN]; - /** subimage encoding: origin image offset in x direction */ - int image_offset_x0; - /** subimage encoding: origin image offset in y direction */ - int image_offset_y0; - /** subsampling value for dx */ - int subsampling_dx; - /** subsampling value for dy */ - int subsampling_dy; - /** input file format 0: PGX, 1: PxM, 2: BMP 3:TIF*/ - int decod_format; - /** output file format 0: J2K, 1: JP2, 2: JPT */ - int cod_format; - /*@}*/ - -/* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ - /**@name JPWL encoding parameters */ - /*@{*/ - /** enables writing of EPC in MH, thus activating JPWL */ - OPJ_BOOL jpwl_epc_on; - /** error protection method for MH (0,1,16,32,37-128) */ - int jpwl_hprot_MH; - /** tile number of header protection specification (>=0) */ - int jpwl_hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; - /** error protection methods for TPHs (0,1,16,32,37-128) */ - int jpwl_hprot_TPH[JPWL_MAX_NO_TILESPECS]; - /** tile number of packet protection specification (>=0) */ - int jpwl_pprot_tileno[JPWL_MAX_NO_PACKSPECS]; - /** packet number of packet protection specification (>=0) */ - int jpwl_pprot_packno[JPWL_MAX_NO_PACKSPECS]; - /** error protection methods for packets (0,1,16,32,37-128) */ - int jpwl_pprot[JPWL_MAX_NO_PACKSPECS]; - /** enables writing of ESD, (0=no/1/2 bytes) */ - int jpwl_sens_size; - /** sensitivity addressing size (0=auto/2/4 bytes) */ - int jpwl_sens_addr; - /** sensitivity range (0-3) */ - int jpwl_sens_range; - /** sensitivity method for MH (-1=no,0-7) */ - int jpwl_sens_MH; - /** tile number of sensitivity specification (>=0) */ - int jpwl_sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; - /** sensitivity methods for TPHs (-1=no,0-7) */ - int jpwl_sens_TPH[JPWL_MAX_NO_TILESPECS]; - /*@}*/ -/* <<UniPG */ + /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ + OPJ_BOOL tile_size_on; + /** XTOsiz */ + int cp_tx0; + /** YTOsiz */ + int cp_ty0; + /** XTsiz */ + int cp_tdx; + /** YTsiz */ + int cp_tdy; + /** allocation by rate/distortion */ + int cp_disto_alloc; + /** allocation by fixed layer */ + int cp_fixed_alloc; + /** add fixed_quality */ + int cp_fixed_quality; + /** fixed layer */ + int *cp_matrice; + /** comment for coding */ + char *cp_comment; + /** csty : coding style */ + int csty; + /** progression order (default OPJ_LRCP) */ + OPJ_PROG_ORDER prog_order; + /** progression order changes */ + opj_poc_t POC[32]; + /** number of progression order changes (POC), default to 0 */ + OPJ_UINT32 numpocs; + /** number of layers */ + int tcp_numlayers; + /** rates of layers - might be subsequently limited by the max_cs_size field. + * Should be decreasing. 1 can be + * used as last value to indicate the last layer is lossless. */ + float tcp_rates[100]; + /** different psnr for successive layers. Should be increasing. 0 can be + * used as last value to indicate the last layer is lossless. */ + float tcp_distoratio[100]; + /** number of resolutions */ + int numresolution; + /** initial code block width, default to 64 */ + int cblockw_init; + /** initial code block height, default to 64 */ + int cblockh_init; + /** mode switch (cblk_style) */ + int mode; + /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */ + int irreversible; + /** region of interest: affected component in [0..3], -1 means no ROI */ + int roi_compno; + /** region of interest: upshift value */ + int roi_shift; + /* number of precinct size specifications */ + int res_spec; + /** initial precinct width */ + int prcw_init[OPJ_J2K_MAXRLVLS]; + /** initial precinct height */ + int prch_init[OPJ_J2K_MAXRLVLS]; + + /**@name command line encoder parameters (not used inside the library) */ + /*@{*/ + /** input file name */ + char infile[OPJ_PATH_LEN]; + /** output file name */ + char outfile[OPJ_PATH_LEN]; + /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */ + int index_on; + /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */ + char index[OPJ_PATH_LEN]; + /** subimage encoding: origin image offset in x direction */ + int image_offset_x0; + /** subimage encoding: origin image offset in y direction */ + int image_offset_y0; + /** subsampling value for dx */ + int subsampling_dx; + /** subsampling value for dy */ + int subsampling_dy; + /** input file format 0: PGX, 1: PxM, 2: BMP 3:TIF*/ + int decod_format; + /** output file format 0: J2K, 1: JP2, 2: JPT */ + int cod_format; + /*@}*/ + + /* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ + /**@name JPWL encoding parameters */ + /*@{*/ + /** enables writing of EPC in MH, thus activating JPWL */ + OPJ_BOOL jpwl_epc_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int jpwl_hprot_MH; + /** tile number of header protection specification (>=0) */ + int jpwl_hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int jpwl_hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int jpwl_pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int jpwl_pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int jpwl_pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0=no/1/2 bytes) */ + int jpwl_sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int jpwl_sens_addr; + /** sensitivity range (0-3) */ + int jpwl_sens_range; + /** sensitivity method for MH (-1=no,0-7) */ + int jpwl_sens_MH; + /** tile number of sensitivity specification (>=0) */ + int jpwl_sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1=no,0-7) */ + int jpwl_sens_TPH[JPWL_MAX_NO_TILESPECS]; + /*@}*/ + /* <<UniPG */ /** * DEPRECATED: use RSIZ, OPJ_PROFILE_* and MAX_COMP_SIZE instead @@ -471,23 +474,23 @@ typedef struct opj_cparameters { * Maximum size (in bytes) for each component. * If == 0, component size limitation is not considered * */ - int max_comp_size; + int max_comp_size; /** * DEPRECATED: use RSIZ, OPJ_PROFILE_* and OPJ_EXTENSION_* instead * Profile name * */ OPJ_RSIZ_CAPABILITIES cp_rsiz; - /** Tile part generation*/ - char tp_on; - /** Flag for Tile part generation*/ - char tp_flag; - /** MCT (multiple component transform) */ - char tcp_mct; - /** Enable JPIP indexing*/ - OPJ_BOOL jpip_on; - /** Naive implementation of MCT restricted to a single reversible array based + /** Tile part generation*/ + char tp_on; + /** Flag for Tile part generation*/ + char tp_flag; + /** MCT (multiple component transform) */ + char tcp_mct; + /** Enable JPIP indexing*/ + OPJ_BOOL jpip_on; + /** Naive implementation of MCT restricted to a single reversible array based encoding without offset concerning all the components. */ - void * mct_data; + void * mct_data; /** * Maximum size (in bytes) for the whole codestream. * If == 0, codestream size limitation is not considered @@ -498,72 +501,73 @@ typedef struct opj_cparameters { /** RSIZ value To be used to combine OPJ_PROFILE_*, OPJ_EXTENSION_* and (sub)levels values. */ OPJ_UINT16 rsiz; -} opj_cparameters_t; +} opj_cparameters_t; -#define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG 0x0001 +#define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG 0x0001 +#define OPJ_DPARAMETERS_DUMP_FLAG 0x0002 /** * Decompression parameters * */ typedef struct opj_dparameters { - /** - Set the number of highest resolution levels to be discarded. - The image resolution is effectively divided by 2 to the power of the number of discarded levels. - The reduce factor is limited by the smallest total number of decomposition levels among tiles. - if != 0, then original dimension divided by 2^(reduce); - if == 0 or not used, image is decoded to the full resolution - */ - OPJ_UINT32 cp_reduce; - /** - Set the maximum number of quality layers to decode. - If there are less quality layers than the specified number, all the quality layers are decoded. - if != 0, then only the first "layer" layers are decoded; - if == 0 or not used, all the quality layers are decoded - */ - OPJ_UINT32 cp_layer; - - /**@name command line decoder parameters (not used inside the library) */ - /*@{*/ - /** input file name */ - char infile[OPJ_PATH_LEN]; - /** output file name */ - char outfile[OPJ_PATH_LEN]; - /** input file format 0: J2K, 1: JP2, 2: JPT */ - int decod_format; - /** output file format 0: PGX, 1: PxM, 2: BMP */ - int cod_format; - - /** Decoding area left boundary */ - OPJ_UINT32 DA_x0; - /** Decoding area right boundary */ - OPJ_UINT32 DA_x1; - /** Decoding area up boundary */ - OPJ_UINT32 DA_y0; - /** Decoding area bottom boundary */ - OPJ_UINT32 DA_y1; - /** Verbose mode */ - OPJ_BOOL m_verbose; - - /** tile number ot the decoded tile*/ - OPJ_UINT32 tile_index; - /** Nb of tile to decode */ - OPJ_UINT32 nb_tile_to_decode; - - /*@}*/ - -/* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ - /**@name JPWL decoding parameters */ - /*@{*/ - /** activates the JPWL correction capabilities */ - OPJ_BOOL jpwl_correct; - /** expected number of components */ - int jpwl_exp_comps; - /** maximum number of tiles */ - int jpwl_max_tiles; - /*@}*/ -/* <<UniPG */ - - unsigned int flags; + /** + Set the number of highest resolution levels to be discarded. + The image resolution is effectively divided by 2 to the power of the number of discarded levels. + The reduce factor is limited by the smallest total number of decomposition levels among tiles. + if != 0, then original dimension divided by 2^(reduce); + if == 0 or not used, image is decoded to the full resolution + */ + OPJ_UINT32 cp_reduce; + /** + Set the maximum number of quality layers to decode. + If there are less quality layers than the specified number, all the quality layers are decoded. + if != 0, then only the first "layer" layers are decoded; + if == 0 or not used, all the quality layers are decoded + */ + OPJ_UINT32 cp_layer; + + /**@name command line decoder parameters (not used inside the library) */ + /*@{*/ + /** input file name */ + char infile[OPJ_PATH_LEN]; + /** output file name */ + char outfile[OPJ_PATH_LEN]; + /** input file format 0: J2K, 1: JP2, 2: JPT */ + int decod_format; + /** output file format 0: PGX, 1: PxM, 2: BMP */ + int cod_format; + + /** Decoding area left boundary */ + OPJ_UINT32 DA_x0; + /** Decoding area right boundary */ + OPJ_UINT32 DA_x1; + /** Decoding area up boundary */ + OPJ_UINT32 DA_y0; + /** Decoding area bottom boundary */ + OPJ_UINT32 DA_y1; + /** Verbose mode */ + OPJ_BOOL m_verbose; + + /** tile number ot the decoded tile*/ + OPJ_UINT32 tile_index; + /** Nb of tile to decode */ + OPJ_UINT32 nb_tile_to_decode; + + /*@}*/ + + /* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ + /**@name JPWL decoding parameters */ + /*@{*/ + /** activates the JPWL correction capabilities */ + OPJ_BOOL jpwl_correct; + /** expected number of components */ + int jpwl_exp_comps; + /** maximum number of tiles */ + int jpwl_max_tiles; + /*@}*/ + /* <<UniPG */ + + unsigned int flags; } opj_dparameters_t; @@ -573,7 +577,7 @@ typedef struct opj_dparameters { * */ typedef void * opj_codec_t; -/* +/* ========================================================== I/O stream typedef definitions ========================================================== @@ -583,41 +587,45 @@ typedef void * opj_codec_t; * Stream open flags. * */ /** The stream was opened for reading. */ -#define OPJ_STREAM_READ OPJ_TRUE +#define OPJ_STREAM_READ OPJ_TRUE /** The stream was opened for writing. */ #define OPJ_STREAM_WRITE OPJ_FALSE /* * Callback function prototype for read function */ -typedef OPJ_SIZE_T (* opj_stream_read_fn) (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) ; +typedef OPJ_SIZE_T(* opj_stream_read_fn)(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) ; /* * Callback function prototype for write function */ -typedef OPJ_SIZE_T (* opj_stream_write_fn) (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) ; +typedef OPJ_SIZE_T(* opj_stream_write_fn)(void * p_buffer, + OPJ_SIZE_T p_nb_bytes, void * p_user_data) ; /* * Callback function prototype for skip function */ -typedef OPJ_OFF_T (* opj_stream_skip_fn) (OPJ_OFF_T p_nb_bytes, void * p_user_data) ; +typedef OPJ_OFF_T(* opj_stream_skip_fn)(OPJ_OFF_T p_nb_bytes, + void * p_user_data) ; /* * Callback function prototype for seek function */ -typedef OPJ_BOOL (* opj_stream_seek_fn) (OPJ_OFF_T p_nb_bytes, void * p_user_data) ; +typedef OPJ_BOOL(* opj_stream_seek_fn)(OPJ_OFF_T p_nb_bytes, + void * p_user_data) ; /* * Callback function prototype for free user data function */ -typedef void (* opj_stream_free_user_data_fn) (void * p_user_data) ; +typedef void (* opj_stream_free_user_data_fn)(void * p_user_data) ; /* * JPEG2000 Stream. */ typedef void * opj_stream_t; -/* +/* ========================================================== image typedef definitions ========================================================== @@ -627,59 +635,60 @@ typedef void * opj_stream_t; * Defines a single image component * */ typedef struct opj_image_comp { - /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */ - OPJ_UINT32 dx; - /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */ - OPJ_UINT32 dy; - /** data width */ - OPJ_UINT32 w; - /** data height */ - OPJ_UINT32 h; - /** x component offset compared to the whole image */ - OPJ_UINT32 x0; - /** y component offset compared to the whole image */ - OPJ_UINT32 y0; - /** precision */ - OPJ_UINT32 prec; - /** image depth in bits */ - OPJ_UINT32 bpp; - /** signed (1) / unsigned (0) */ - OPJ_UINT32 sgnd; - /** number of decoded resolution */ - OPJ_UINT32 resno_decoded; - /** number of division by 2 of the out image compared to the original size of image */ - OPJ_UINT32 factor; - /** image component data */ - OPJ_INT32 *data; - /** alpha channel */ - OPJ_UINT16 alpha; + /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */ + OPJ_UINT32 dx; + /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */ + OPJ_UINT32 dy; + /** data width */ + OPJ_UINT32 w; + /** data height */ + OPJ_UINT32 h; + /** x component offset compared to the whole image */ + OPJ_UINT32 x0; + /** y component offset compared to the whole image */ + OPJ_UINT32 y0; + /** precision */ + OPJ_UINT32 prec; + /** image depth in bits */ + OPJ_UINT32 bpp; + /** signed (1) / unsigned (0) */ + OPJ_UINT32 sgnd; + /** number of decoded resolution */ + OPJ_UINT32 resno_decoded; + /** number of division by 2 of the out image compared to the original size of image */ + OPJ_UINT32 factor; + /** image component data */ + OPJ_INT32 *data; + /** alpha channel */ + OPJ_UINT16 alpha; } opj_image_comp_t; -/** +/** * Defines image data and characteristics * */ typedef struct opj_image { - /** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */ - OPJ_UINT32 x0; - /** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */ - OPJ_UINT32 y0; - /** Xsiz: width of the reference grid */ - OPJ_UINT32 x1; - /** Ysiz: height of the reference grid */ - OPJ_UINT32 y1; - /** number of components in the image */ - OPJ_UINT32 numcomps; - /** color space: sRGB, Greyscale or YUV */ - OPJ_COLOR_SPACE color_space; - /** image components */ - opj_image_comp_t *comps; - /** 'restricted' ICC profile */ - OPJ_BYTE *icc_profile_buf; - /** size of ICC profile */ - OPJ_UINT32 icc_profile_len; - - /** Whether to apply PCLR or not */ - OPJ_BOOL pdfium_use_colorspace; + /** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */ + OPJ_UINT32 x0; + /** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */ + OPJ_UINT32 y0; + /** Xsiz: width of the reference grid */ + OPJ_UINT32 x1; + /** Ysiz: height of the reference grid */ + OPJ_UINT32 y1; + /** number of components in the image */ + OPJ_UINT32 numcomps; + /** color space: sRGB, Greyscale or YUV */ + OPJ_COLOR_SPACE color_space; + /** image components */ + opj_image_comp_t *comps; + /** 'restricted' ICC profile */ + OPJ_BYTE *icc_profile_buf; + /** size of ICC profile */ + OPJ_UINT32 icc_profile_len; + + + /** Whether to apply PCLR or not */ + OPJ_BOOL pdfium_use_colorspace; } opj_image_t; @@ -687,28 +696,28 @@ typedef struct opj_image { * Component parameters structure used by the opj_image_create function * */ typedef struct opj_image_comptparm { - /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */ - OPJ_UINT32 dx; - /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */ - OPJ_UINT32 dy; - /** data width */ - OPJ_UINT32 w; - /** data height */ - OPJ_UINT32 h; - /** x component offset compared to the whole image */ - OPJ_UINT32 x0; - /** y component offset compared to the whole image */ - OPJ_UINT32 y0; - /** precision */ - OPJ_UINT32 prec; - /** image depth in bits */ - OPJ_UINT32 bpp; - /** signed (1) / unsigned (0) */ - OPJ_UINT32 sgnd; + /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */ + OPJ_UINT32 dx; + /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */ + OPJ_UINT32 dy; + /** data width */ + OPJ_UINT32 w; + /** data height */ + OPJ_UINT32 h; + /** x component offset compared to the whole image */ + OPJ_UINT32 x0; + /** y component offset compared to the whole image */ + OPJ_UINT32 y0; + /** precision */ + OPJ_UINT32 prec; + /** image depth in bits */ + OPJ_UINT32 bpp; + /** signed (1) / unsigned (0) */ + OPJ_UINT32 sgnd; } opj_image_cmptparm_t; -/* +/* ========================================================== Information on the JPEG 2000 codestream ========================================================== @@ -719,14 +728,14 @@ typedef struct opj_image_comptparm { * Index structure : Information concerning a packet inside tile * */ typedef struct opj_packet_info { - /** packet start position (including SOP marker if it exists) */ - OPJ_OFF_T start_pos; - /** end of packet header position (including EPH marker if it exists)*/ - OPJ_OFF_T end_ph_pos; - /** packet end position */ - OPJ_OFF_T end_pos; - /** packet distorsion */ - double disto; + /** packet start position (including SOP marker if it exists) */ + OPJ_OFF_T start_pos; + /** end of packet header position (including EPH marker if it exists)*/ + OPJ_OFF_T end_ph_pos; + /** packet end position */ + OPJ_OFF_T end_pos; + /** packet distorsion */ + double disto; } opj_packet_info_t; @@ -735,12 +744,12 @@ typedef struct opj_packet_info { * Marker structure * */ typedef struct opj_marker_info { - /** marker type */ - unsigned short int type; - /** position in codestream */ - OPJ_OFF_T pos; - /** length, marker val included */ - int len; + /** marker type */ + unsigned short int type; + /** position in codestream */ + OPJ_OFF_T pos; + /** length, marker val included */ + int len; } opj_marker_info_t; /* <<UniPG */ @@ -748,108 +757,108 @@ typedef struct opj_marker_info { * Index structure : Information concerning tile-parts */ typedef struct opj_tp_info { - /** start position of tile part */ - int tp_start_pos; - /** end position of tile part header */ - int tp_end_header; - /** end position of tile part */ - int tp_end_pos; - /** start packet of tile part */ - int tp_start_pack; - /** number of packets of tile part */ - int tp_numpacks; + /** start position of tile part */ + int tp_start_pos; + /** end position of tile part header */ + int tp_end_header; + /** end position of tile part */ + int tp_end_pos; + /** start packet of tile part */ + int tp_start_pack; + /** number of packets of tile part */ + int tp_numpacks; } opj_tp_info_t; /** * Index structure : information regarding tiles */ typedef struct opj_tile_info { - /** value of thresh for each layer by tile cfr. Marcela */ - double *thresh; - /** number of tile */ - int tileno; - /** start position */ - int start_pos; - /** end position of the header */ - int end_header; - /** end position */ - int end_pos; - /** precinct number for each resolution level (width) */ - int pw[33]; - /** precinct number for each resolution level (height) */ - int ph[33]; - /** precinct size (in power of 2), in X for each resolution level */ - int pdx[33]; - /** precinct size (in power of 2), in Y for each resolution level */ - int pdy[33]; - /** information concerning packets inside tile */ - opj_packet_info_t *packet; - /** add fixed_quality */ - int numpix; - /** add fixed_quality */ - double distotile; - /** number of markers */ - int marknum; - /** list of markers */ - opj_marker_info_t *marker; - /** actual size of markers array */ - int maxmarknum; - /** number of tile parts */ - int num_tps; - /** information concerning tile parts */ - opj_tp_info_t *tp; + /** value of thresh for each layer by tile cfr. Marcela */ + double *thresh; + /** number of tile */ + int tileno; + /** start position */ + int start_pos; + /** end position of the header */ + int end_header; + /** end position */ + int end_pos; + /** precinct number for each resolution level (width) */ + int pw[33]; + /** precinct number for each resolution level (height) */ + int ph[33]; + /** precinct size (in power of 2), in X for each resolution level */ + int pdx[33]; + /** precinct size (in power of 2), in Y for each resolution level */ + int pdy[33]; + /** information concerning packets inside tile */ + opj_packet_info_t *packet; + /** add fixed_quality */ + int numpix; + /** add fixed_quality */ + double distotile; + /** number of markers */ + int marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + int maxmarknum; + /** number of tile parts */ + int num_tps; + /** information concerning tile parts */ + opj_tp_info_t *tp; } opj_tile_info_t; /** * Index structure of the codestream */ typedef struct opj_codestream_info { - /** maximum distortion reduction on the whole image (add for Marcela) */ - double D_max; - /** packet number */ - int packno; - /** writing the packet in the index with t2_encode_packets */ - int index_write; - /** image width */ - int image_w; - /** image height */ - int image_h; - /** progression order */ - OPJ_PROG_ORDER prog; - /** tile size in x */ - int tile_x; - /** tile size in y */ - int tile_y; - /** */ - int tile_Ox; - /** */ - int tile_Oy; - /** number of tiles in X */ - int tw; - /** number of tiles in Y */ - int th; - /** component numbers */ - int numcomps; - /** number of layer */ - int numlayers; - /** number of decomposition for each component */ - int *numdecompos; -/* UniPG>> */ - /** number of markers */ - int marknum; - /** list of markers */ - opj_marker_info_t *marker; - /** actual size of markers array */ - int maxmarknum; -/* <<UniPG */ - /** main header position */ - int main_head_start; - /** main header position */ - int main_head_end; - /** codestream's size */ - int codestream_size; - /** information regarding tiles inside image */ - opj_tile_info_t *tile; + /** maximum distortion reduction on the whole image (add for Marcela) */ + double D_max; + /** packet number */ + int packno; + /** writing the packet in the index with t2_encode_packets */ + int index_write; + /** image width */ + int image_w; + /** image height */ + int image_h; + /** progression order */ + OPJ_PROG_ORDER prog; + /** tile size in x */ + int tile_x; + /** tile size in y */ + int tile_y; + /** */ + int tile_Ox; + /** */ + int tile_Oy; + /** number of tiles in X */ + int tw; + /** number of tiles in Y */ + int th; + /** component numbers */ + int numcomps; + /** number of layer */ + int numlayers; + /** number of decomposition for each component */ + int *numdecompos; + /* UniPG>> */ + /** number of markers */ + int marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + int maxmarknum; + /* <<UniPG */ + /** main header position */ + int main_head_start; + /** main header position */ + int main_head_end; + /** codestream's size */ + int codestream_size; + /** information regarding tiles inside image */ + opj_tile_info_t *tile; } opj_codestream_info_t; /* <----------------------------------------------------------- */ @@ -858,36 +867,35 @@ typedef struct opj_codestream_info { /** * Tile-component coding parameters information */ -typedef struct opj_tccp_info -{ - /** component index */ - OPJ_UINT32 compno; - /** coding style */ - OPJ_UINT32 csty; - /** number of resolutions */ - OPJ_UINT32 numresolutions; - /** code-blocks width */ - OPJ_UINT32 cblkw; - /** code-blocks height */ - OPJ_UINT32 cblkh; - /** code-block coding style */ - OPJ_UINT32 cblksty; - /** discrete wavelet transform identifier */ - OPJ_UINT32 qmfbid; - /** quantisation style */ - OPJ_UINT32 qntsty; - /** stepsizes used for quantization */ - OPJ_UINT32 stepsizes_mant[OPJ_J2K_MAXBANDS]; - /** stepsizes used for quantization */ - OPJ_UINT32 stepsizes_expn[OPJ_J2K_MAXBANDS]; - /** number of guard bits */ - OPJ_UINT32 numgbits; - /** Region Of Interest shift */ - OPJ_INT32 roishift; - /** precinct width */ - OPJ_UINT32 prcw[OPJ_J2K_MAXRLVLS]; - /** precinct height */ - OPJ_UINT32 prch[OPJ_J2K_MAXRLVLS]; +typedef struct opj_tccp_info { + /** component index */ + OPJ_UINT32 compno; + /** coding style */ + OPJ_UINT32 csty; + /** number of resolutions */ + OPJ_UINT32 numresolutions; + /** log2 of code-blocks width */ + OPJ_UINT32 cblkw; + /** log2 of code-blocks height */ + OPJ_UINT32 cblkh; + /** code-block coding style */ + OPJ_UINT32 cblksty; + /** discrete wavelet transform identifier: 0 = 9-7 irreversible, 1 = 5-3 reversible */ + OPJ_UINT32 qmfbid; + /** quantisation style */ + OPJ_UINT32 qntsty; + /** stepsizes used for quantization */ + OPJ_UINT32 stepsizes_mant[OPJ_J2K_MAXBANDS]; + /** stepsizes used for quantization */ + OPJ_UINT32 stepsizes_expn[OPJ_J2K_MAXBANDS]; + /** number of guard bits */ + OPJ_UINT32 numgbits; + /** Region Of Interest shift */ + OPJ_INT32 roishift; + /** precinct width */ + OPJ_UINT32 prcw[OPJ_J2K_MAXRLVLS]; + /** precinct height */ + OPJ_UINT32 prch[OPJ_J2K_MAXRLVLS]; } opj_tccp_info_t; @@ -896,19 +904,19 @@ opj_tccp_info_t; */ typedef struct opj_tile_v2_info { - /** number (index) of tile */ - int tileno; - /** coding style */ - OPJ_UINT32 csty; - /** progression order */ - OPJ_PROG_ORDER prg; - /** number of layers */ - OPJ_UINT32 numlayers; - /** multi-component transform identifier */ - OPJ_UINT32 mct; + /** number (index) of tile */ + int tileno; + /** coding style */ + OPJ_UINT32 csty; + /** progression order */ + OPJ_PROG_ORDER prg; + /** number of layers */ + OPJ_UINT32 numlayers; + /** multi-component transform identifier */ + OPJ_UINT32 mct; - /** information concerning tile component parameters*/ - opj_tccp_info_t *tccp_info; + /** information concerning tile component parameters*/ + opj_tccp_info_t *tccp_info; } opj_tile_info_v2_t; @@ -916,28 +924,28 @@ typedef struct opj_tile_v2_info { * Information structure about the codestream (FIXME should be expand and enhance) */ typedef struct opj_codestream_info_v2 { - /* Tile info */ - /** tile origin in x = XTOsiz */ - OPJ_UINT32 tx0; - /** tile origin in y = YTOsiz */ - OPJ_UINT32 ty0; - /** tile size in x = XTsiz */ - OPJ_UINT32 tdx; - /** tile size in y = YTsiz */ - OPJ_UINT32 tdy; - /** number of tiles in X */ - OPJ_UINT32 tw; - /** number of tiles in Y */ - OPJ_UINT32 th; - - /** number of components*/ - OPJ_UINT32 nbcomps; - - /** Default information regarding tiles inside image */ - opj_tile_info_v2_t m_default_tile_info; - - /** information regarding tiles inside image */ - opj_tile_info_v2_t *tile_info; /* FIXME not used for the moment */ + /* Tile info */ + /** tile origin in x = XTOsiz */ + OPJ_UINT32 tx0; + /** tile origin in y = YTOsiz */ + OPJ_UINT32 ty0; + /** tile size in x = XTsiz */ + OPJ_UINT32 tdx; + /** tile size in y = YTsiz */ + OPJ_UINT32 tdy; + /** number of tiles in X */ + OPJ_UINT32 tw; + /** number of tiles in Y */ + OPJ_UINT32 th; + + /** number of components*/ + OPJ_UINT32 nbcomps; + + /** Default information regarding tiles inside image */ + opj_tile_info_v2_t m_default_tile_info; + + /** information regarding tiles inside image */ + opj_tile_info_v2_t *tile_info; /* FIXME not used for the moment */ } opj_codestream_info_v2_t; @@ -946,12 +954,12 @@ typedef struct opj_codestream_info_v2 { * Index structure about a tile part */ typedef struct opj_tp_index { - /** start position */ - OPJ_OFF_T start_pos; - /** end position of the header */ - OPJ_OFF_T end_header; - /** end position */ - OPJ_OFF_T end_pos; + /** start position */ + OPJ_OFF_T start_pos; + /** end position of the header */ + OPJ_OFF_T end_header; + /** end position */ + OPJ_OFF_T end_pos; } opj_tp_index_t; @@ -959,31 +967,31 @@ typedef struct opj_tp_index { * Index structure about a tile */ typedef struct opj_tile_index { - /** tile index */ - OPJ_UINT32 tileno; - - /** number of tile parts */ - OPJ_UINT32 nb_tps; - /** current nb of tile part (allocated)*/ - OPJ_UINT32 current_nb_tps; - /** current tile-part index */ - OPJ_UINT32 current_tpsno; - /** information concerning tile parts */ - opj_tp_index_t *tp_index; - - /* UniPG>> */ /* NOT USED FOR THE MOMENT IN THE V2 VERSION */ - /** number of markers */ - OPJ_UINT32 marknum; - /** list of markers */ - opj_marker_info_t *marker; - /** actual size of markers array */ - OPJ_UINT32 maxmarknum; - /* <<UniPG */ - - /** packet number */ - OPJ_UINT32 nb_packet; - /** information concerning packets inside tile */ - opj_packet_info_t *packet_index; + /** tile index */ + OPJ_UINT32 tileno; + + /** number of tile parts */ + OPJ_UINT32 nb_tps; + /** current nb of tile part (allocated)*/ + OPJ_UINT32 current_nb_tps; + /** current tile-part index */ + OPJ_UINT32 current_tpsno; + /** information concerning tile parts */ + opj_tp_index_t *tp_index; + + /* UniPG>> */ /* NOT USED FOR THE MOMENT IN THE V2 VERSION */ + /** number of markers */ + OPJ_UINT32 marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + OPJ_UINT32 maxmarknum; + /* <<UniPG */ + + /** packet number */ + OPJ_UINT32 nb_packet; + /** information concerning packets inside tile */ + opj_packet_info_t *packet_index; } opj_tile_index_t; @@ -991,29 +999,29 @@ typedef struct opj_tile_index { * Index structure of the codestream (FIXME should be expand and enhance) */ typedef struct opj_codestream_index { - /** main header start position (SOC position) */ - OPJ_OFF_T main_head_start; - /** main header end position (first SOT position) */ - OPJ_OFF_T main_head_end; - - /** codestream's size */ - OPJ_UINT64 codestream_size; - -/* UniPG>> */ /* NOT USED FOR THE MOMENT IN THE V2 VERSION */ - /** number of markers */ - OPJ_UINT32 marknum; - /** list of markers */ - opj_marker_info_t *marker; - /** actual size of markers array */ - OPJ_UINT32 maxmarknum; -/* <<UniPG */ - - /** */ - OPJ_UINT32 nb_of_tiles; - /** */ - opj_tile_index_t *tile_index; /* FIXME not used for the moment */ - -}opj_codestream_index_t; + /** main header start position (SOC position) */ + OPJ_OFF_T main_head_start; + /** main header end position (first SOT position) */ + OPJ_OFF_T main_head_end; + + /** codestream's size */ + OPJ_UINT64 codestream_size; + + /* UniPG>> */ /* NOT USED FOR THE MOMENT IN THE V2 VERSION */ + /** number of markers */ + OPJ_UINT32 marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + OPJ_UINT32 maxmarknum; + /* <<UniPG */ + + /** */ + OPJ_UINT32 nb_of_tiles; + /** */ + opj_tile_index_t *tile_index; /* FIXME not used for the moment */ + +} opj_codestream_index_t; /* -----------------------------------------------------------> */ /* @@ -1027,8 +1035,8 @@ typedef struct opj_codestream_index { * EXPERIMENTAL FOR THE MOMENT */ typedef struct opj_jp2_metadata { - /** */ - OPJ_INT32 not_used; + /** */ + OPJ_INT32 not_used; } opj_jp2_metadata_t; @@ -1037,8 +1045,8 @@ typedef struct opj_jp2_metadata { * EXPERIMENTAL FOR THE MOMENT */ typedef struct opj_jp2_index { - /** */ - OPJ_INT32 not_used; + /** */ + OPJ_INT32 not_used; } opj_jp2_index_t; @@ -1048,7 +1056,7 @@ extern "C" { #endif -/* +/* ========================================================== openjpeg version ========================================================== @@ -1057,7 +1065,7 @@ extern "C" { /* Get the version of the openjpeg library*/ OPJ_API const char * OPJ_CALLCONV opj_version(void); -/* +/* ========================================================== image functions definitions ========================================================== @@ -1071,7 +1079,8 @@ OPJ_API const char * OPJ_CALLCONV opj_version(void); * @param clrspc image color space * @return returns a new image structure if successful, returns NULL otherwise * */ -OPJ_API opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); +OPJ_API opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); /** * Deallocate any resources associated with an image @@ -1083,15 +1092,37 @@ OPJ_API void OPJ_CALLCONV opj_image_destroy(opj_image_t *image); /** * Creates an image without allocating memory for the image (used in the new version of the library). * - * @param numcmpts the number of components - * @param cmptparms the components parameters - * @param clrspc the image color space + * @param numcmpts the number of components + * @param cmptparms the components parameters + * @param clrspc the image color space * - * @return a new image structure if successful, NULL otherwise. + * @return a new image structure if successful, NULL otherwise. */ -OPJ_API opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); +OPJ_API opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); -/* +/** + * Allocator for opj_image_t->comps[].data + * To be paired with opj_image_data_free. + * + * @param size number of bytes to allocate + * + * @return a new pointer if successful, NULL otherwise. + * @since 2.2.0 +*/ +OPJ_API void* OPJ_CALLCONV opj_image_data_alloc(OPJ_SIZE_T size); + +/** + * Destructor for opj_image_t->comps[].data + * To be paired with opj_image_data_alloc. + * + * @param ptr Pointer to free + * + * @since 2.2.0 +*/ +OPJ_API void OPJ_CALLCONV opj_image_data_free(void* ptr); + +/* ========================================================== stream functions definitions ========================================================== @@ -1100,65 +1131,72 @@ OPJ_API opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, opj /** * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream. * - * @param p_is_input if set to true then the stream will be an input stream, an output stream else. + * @param p_is_input if set to true then the stream will be an input stream, an output stream else. * - * @return a stream object. + * @return a stream object. */ -OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_default_create(OPJ_BOOL p_is_input); +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_default_create( + OPJ_BOOL p_is_input); /** * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream. * - * @param p_buffer_size FIXME DOC - * @param p_is_input if set to true then the stream will be an input stream, an output stream else. + * @param p_buffer_size FIXME DOC + * @param p_is_input if set to true then the stream will be an input stream, an output stream else. * - * @return a stream object. + * @return a stream object. */ -OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size, OPJ_BOOL p_is_input); +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size, + OPJ_BOOL p_is_input); /** * Destroys a stream created by opj_create_stream. This function does NOT close the abstract stream. If needed the user must * close its own implementation of the stream. * - * @param p_stream the stream to destroy. + * @param p_stream the stream to destroy. */ OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream); - + /** * Sets the given function to be used as a read function. - * @param p_stream the stream to modify - * @param p_function the function to use a read function. + * @param p_stream the stream to modify + * @param p_function the function to use a read function. */ -OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function); +OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, + opj_stream_read_fn p_function); /** * Sets the given function to be used as a write function. - * @param p_stream the stream to modify - * @param p_function the function to use a write function. + * @param p_stream the stream to modify + * @param p_function the function to use a write function. */ -OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function); +OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, + opj_stream_write_fn p_function); /** * Sets the given function to be used as a skip function. - * @param p_stream the stream to modify - * @param p_function the function to use a skip function. + * @param p_stream the stream to modify + * @param p_function the function to use a skip function. */ -OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function); +OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, + opj_stream_skip_fn p_function); /** * Sets the given function to be used as a seek function, the stream is then seekable. - * @param p_stream the stream to modify - * @param p_function the function to use a skip function. + * @param p_stream the stream to modify + * @param p_function the function to use a skip function. */ -OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function); +OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, + opj_stream_seek_fn p_function); /** * Sets the given data to be used as a user data for the stream. - * @param p_stream the stream to modify - * @param p_data the data to set. - * @param p_function the function to free p_data when opj_stream_destroy() is called. + * @param p_stream the stream to modify + * @param p_data the data to set. + * @param p_function the function to free p_data when opj_stream_destroy() is called. */ -OPJ_API void OPJ_CALLCONV opj_stream_set_user_data (opj_stream_t* p_stream, void * p_data, opj_stream_free_user_data_fn p_function); +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, + void * p_data, opj_stream_free_user_data_fn p_function); /** * Sets the length of the user data for the stream. @@ -1166,25 +1204,28 @@ OPJ_API void OPJ_CALLCONV opj_stream_set_user_data (opj_stream_t* p_stream, void * @param p_stream the stream to modify * @param data_length length of the user_data. */ -OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT64 data_length); +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length( + opj_stream_t* p_stream, OPJ_UINT64 data_length); /** * Create a stream from a file identified with its filename with default parameters (helper function) * @param fname the filename of the file to stream * @param p_is_read_stream whether the stream is a read stream (true) or not (false) */ -OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (const char *fname, OPJ_BOOL p_is_read_stream); - +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream( + const char *fname, OPJ_BOOL p_is_read_stream); + /** Create a stream from a file identified with its filename with a specific buffer size * @param fname the filename of the file to stream * @param p_buffer_size size of the chunk used to stream * @param p_is_read_stream whether the stream is a read stream (true) or not (false) */ -OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (const char *fname, - OPJ_SIZE_T p_buffer_size, - OPJ_BOOL p_is_read_stream); - -/* +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream( + const char *fname, + OPJ_SIZE_T p_buffer_size, + OPJ_BOOL p_is_read_stream); + +/* ========================================================== event manager functions definitions ========================================================== @@ -1195,9 +1236,9 @@ OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (const char *fn * @param p_callback the callback function which will be used * @param p_user_data client object where will be returned the message */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, - opj_msg_callback p_callback, - void * p_user_data); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data); /** * Set the warning handler use by openjpeg. * @param p_codec the codec previously initialise @@ -1205,19 +1246,19 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, * @param p_user_data client object where will be returned the message */ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_warning_handler(opj_codec_t * p_codec, - opj_msg_callback p_callback, - void * p_user_data); + opj_msg_callback p_callback, + void * p_user_data); /** * Set the error handler use by openjpeg. * @param p_codec the codec previously initialise * @param p_callback the callback function which will be used * @param p_user_data client object where will be returned the message */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, - opj_msg_callback p_callback, - void * p_user_data); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data); -/* +/* ========================================================== codec functions definitions ========================================================== @@ -1225,189 +1266,254 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, /** * Creates a J2K/JP2 decompression structure - * @param format Decoder to select + * @param format Decoder to select * * @return Returns a handle to a decompressor if successful, returns NULL otherwise * */ -OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format); +OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_decompress( + OPJ_CODEC_FORMAT format); /** * Destroy a decompressor handle * - * @param p_codec decompressor handle to destroy + * @param p_codec decompressor handle to destroy */ OPJ_API void OPJ_CALLCONV opj_destroy_codec(opj_codec_t * p_codec); /** * Read after the codestream if necessary - * @param p_codec the JPEG2000 codec to read. - * @param p_stream the JPEG2000 stream. + * @param p_codec the JPEG2000 codec to read. + * @param p_stream the JPEG2000 stream. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_end_decompress ( opj_codec_t *p_codec, - opj_stream_t *p_stream); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_end_decompress(opj_codec_t *p_codec, + opj_stream_t *p_stream); /** * Set decoding parameters to default values * @param parameters Decompression parameters */ -OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters); +OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters( + opj_dparameters_t *parameters); /** * Setup the decoder with decompression parameters provided by the user and with the message handler * provided by the user. * - * @param p_codec decompressor handler - * @param parameters decompression parameters + * @param p_codec decompressor handler + * @param parameters decompression parameters * - * @return true if the decoder is correctly set + * @return true if the decoder is correctly set */ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec, - opj_dparameters_t *parameters ); + opj_dparameters_t *parameters); + +/** + * Allocates worker threads for the compressor/decompressor. + * + * By default, only the main thread is used. If this function is not used, + * but the OPJ_NUM_THREADS environment variable is set, its value will be + * used to initialize the number of threads. The value can be either an integer + * number, or "ALL_CPUS". If OPJ_NUM_THREADS is set and this function is called, + * this function will override the behaviour of the environment variable. + * + * Note: currently only has effect on the decompressor. + * + * @param p_codec decompressor handler + * @param num_threads number of threads. + * + * @return OPJ_TRUE if the decoder is correctly set + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_codec_set_threads(opj_codec_t *p_codec, + int num_threads); /** * Decodes an image header. * - * @param p_stream the jpeg2000 stream. - * @param p_codec the jpeg2000 codec to read. - * @param p_image the image structure initialized with the characteristics of encoded image. + * @param p_stream the jpeg2000 stream. + * @param p_codec the jpeg2000 codec to read. + * @param p_image the image structure initialized with the characteristics of encoded image. * - * @return true if the main header of the codestream and the JP2 header is correctly read. + * @return true if the main header of the codestream and the JP2 header is correctly read. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_header ( opj_stream_t *p_stream, - opj_codec_t *p_codec, - opj_image_t **p_image); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, + opj_codec_t *p_codec, + opj_image_t **p_image); + + +/** Restrict the number of components to decode. + * + * This function should be called after opj_read_header(). + * + * This function enables to restrict the set of decoded components to the + * specified indices. + * Note that the current implementation (apply_color_transforms == OPJ_FALSE) + * is such that neither the multi-component transform at codestream level, + * nor JP2 channel transformations will be applied. + * Consequently the indices are relative to the codestream. + * + * Note: opj_decode_tile_data() should not be used together with opj_set_decoded_components(). + * + * @param p_codec the jpeg2000 codec to read. + * @param numcomps Size of the comps_indices array. + * @param comps_indices Array of numcomps values representing the indices + * of the components to decode (relative to the + * codestream, starting at 0) + * @param apply_color_transforms Whether multi-component transform at codestream level + * or JP2 channel transformations should be applied. + * Currently this parameter should be set to OPJ_FALSE. + * Setting it to OPJ_TRUE will result in an error. + * + * @return OPJ_TRUE in case of success. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decoded_components(opj_codec_t *p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + OPJ_BOOL apply_color_transforms); /** * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. * - * @param p_codec the jpeg2000 codec. - * @param p_image the decoded image previously setted by opj_read_header - * @param p_start_x the left position of the rectangle to decode (in image coordinates). - * @param p_end_x the right position of the rectangle to decode (in image coordinates). - * @param p_start_y the up position of the rectangle to decode (in image coordinates). - * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * The coordinates passed to this function should be expressed in the reference grid, + * that is to say at the highest resolution level, even if requesting the image at lower + * resolution levels. + * + * Generally opj_set_decode_area() should be followed by opj_decode(), and the + * codec cannot be re-used. + * In the particular case of an image made of a single tile, several sequences of + * calls to opoj_set_decode_area() and opj_decode() are allowed, and will bring + * performance improvements when reading an image by chunks. * - * @return true if the area could be set. + * @param p_codec the jpeg2000 codec. + * @param p_image the decoded image previously setted by opj_read_header + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * + * @return true if the area could be set. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec, - opj_image_t* p_image, - OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, OPJ_INT32 p_end_y ); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decode_area(opj_codec_t *p_codec, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y); /** * Decode an image from a JPEG-2000 codestream * - * @param p_decompressor decompressor handle - * @param p_stream Input buffer stream - * @param p_image the decoded image - * @return true if success, otherwise false + * @param p_decompressor decompressor handle + * @param p_stream Input buffer stream + * @param p_image the decoded image + * @return true if success, otherwise false * */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decode( opj_codec_t *p_decompressor, - opj_stream_t *p_stream, - opj_image_t *p_image); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decode(opj_codec_t *p_decompressor, + opj_stream_t *p_stream, + opj_image_t *p_image); /** * Get the decoded tile from the codec * - * @param p_codec the jpeg2000 codec. - * @param p_stream input streamm - * @param p_image output image - * @param tile_index index of the tile which will be decode + * @param p_codec the jpeg2000 codec. + * @param p_stream input streamm + * @param p_image output image + * @param tile_index index of the tile which will be decode * - * @return true if success, otherwise false + * @return true if success, otherwise false */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_get_decoded_tile( opj_codec_t *p_codec, - opj_stream_t *p_stream, - opj_image_t *p_image, - OPJ_UINT32 tile_index); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_get_decoded_tile(opj_codec_t *p_codec, + opj_stream_t *p_stream, + opj_image_t *p_image, + OPJ_UINT32 tile_index); /** * Set the resolution factor of the decoded image - * @param p_codec the jpeg2000 codec. - * @param res_factor resolution factor to set + * @param p_codec the jpeg2000 codec. + * @param res_factor resolution factor to set * - * @return true if success, otherwise false + * @return true if success, otherwise false */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, OPJ_UINT32 res_factor); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor( + opj_codec_t *p_codec, OPJ_UINT32 res_factor); /** * Writes a tile with the given data. * - * @param p_codec the jpeg2000 codec. - * @param p_tile_index the index of the tile to write. At the moment, the tiles must be written from 0 to n-1 in sequence. - * @param p_data pointer to the data to write. Data is arranged in sequence, data_comp0, then data_comp1, then ... NO INTERLEAVING should be set. - * @param p_data_size this value os used to make sure the data being written is correct. The size must be equal to the sum for each component of + * @param p_codec the jpeg2000 codec. + * @param p_tile_index the index of the tile to write. At the moment, the tiles must be written from 0 to n-1 in sequence. + * @param p_data pointer to the data to write. Data is arranged in sequence, data_comp0, then data_comp1, then ... NO INTERLEAVING should be set. + * @param p_data_size this value os used to make sure the data being written is correct. The size must be equal to the sum for each component of * tile_width * tile_height * component_size. component_size can be 1,2 or 4 bytes, depending on the precision of the given component. - * @param p_stream the stream to write data to. + * @param p_stream the stream to write data to. * - * @return true if the data could be written. + * @return true if the data could be written. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_write_tile ( opj_codec_t *p_codec, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_t *p_stream ); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_write_tile(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream); /** * Reads a tile header. This function is compulsory and allows one to know the size of the tile that will be decoded. * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. * - * @param p_codec the jpeg2000 codec. - * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. - * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case - * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same - * as depicted in opj_write_tile. - * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). - * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). - * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). - * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). - * @param p_nb_comps pointer to a value that will hold the number of components in the tile. - * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the - * codestream is over at the time of the call, the value will be set to false. The user should then stop - * the decoding. - * @param p_stream the stream to decode. - * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. - * returning false may be the result of a shortage of memory or an internal error. + * @param p_codec the jpeg2000 codec. + * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. + * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case + * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same + * as depicted in opj_write_tile. + * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). + * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). + * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). + * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). + * @param p_nb_comps pointer to a value that will hold the number of components in the tile. + * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the + * codestream is over at the time of the call, the value will be set to false. The user should then stop + * the decoding. + * @param p_stream the stream to decode. + * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. + * returning false may be the result of a shortage of memory or an internal error. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_tile_header( opj_codec_t *p_codec, - opj_stream_t * p_stream, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_should_go_on ); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_tile_header(opj_codec_t *p_codec, + opj_stream_t * p_stream, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_should_go_on); /** * Reads a tile data. This function is compulsory and allows one to decode tile data. opj_read_tile_header should be called before. * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. * - * @param p_codec the jpeg2000 codec. - * @param p_tile_index the index of the tile being decoded, this should be the value set by opj_read_tile_header. - * @param p_data pointer to a memory block that will hold the decoded data. - * @param p_data_size size of p_data. p_data_size should be bigger or equal to the value set by opj_read_tile_header. - * @param p_stream the stream to decode. + * Note: opj_decode_tile_data() should not be used together with opj_set_decoded_components(). + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index the index of the tile being decoded, this should be the value set by opj_read_tile_header. + * @param p_data pointer to a memory block that will hold the decoded data. + * @param p_data_size size of p_data. p_data_size should be bigger or equal to the value set by opj_read_tile_header. + * @param p_stream the stream to decode. * - * @return true if the data could be decoded. + * @return true if the data could be decoded. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decode_tile_data( opj_codec_t *p_codec, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_t *p_stream ); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decode_tile_data(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream); /* COMPRESSION FUNCTIONS*/ /** * Creates a J2K/JP2 compression structure - * @param format Coder to select - * @return Returns a handle to a compressor if successful, returns NULL otherwise + * @param format Coder to select + * @return Returns a handle to a compressor if successful, returns NULL otherwise */ OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format); /** -Set encoding parameters to default values, that means : +Set encoding parameters to default values, that means : <ul> <li>Lossless <li>1 tile @@ -1427,45 +1533,46 @@ Set encoding parameters to default values, that means : </ul> @param parameters Compression parameters */ -OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters); +OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters( + opj_cparameters_t *parameters); /** * Setup the encoder parameters using the current image and using user parameters. - * @param p_codec Compressor handle - * @param parameters Compression parameters - * @param image Input filled image + * @param p_codec Compressor handle + * @param parameters Compression parameters + * @param image Input filled image */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec, - opj_cparameters_t *parameters, - opj_image_t *image); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec, + opj_cparameters_t *parameters, + opj_image_t *image); /** * Start to compress the current image. - * @param p_codec Compressor handle - * @param image Input filled image - * @param p_stream Input stgream + * @param p_codec Compressor handle + * @param p_image Input filled image + * @param p_stream Input stgream */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_start_compress ( opj_codec_t *p_codec, - opj_image_t * p_image, - opj_stream_t *p_stream); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_start_compress(opj_codec_t *p_codec, + opj_image_t * p_image, + opj_stream_t *p_stream); /** * End to compress the current image. - * @param p_codec Compressor handle - * @param p_stream Input stgream + * @param p_codec Compressor handle + * @param p_stream Input stgream */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec, - opj_stream_t *p_stream); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_end_compress(opj_codec_t *p_codec, + opj_stream_t *p_stream); /** * Encode an image into a JPEG-2000 codestream - * @param p_codec compressor handle - * @param p_stream Output buffer stream + * @param p_codec compressor handle + * @param p_stream Output buffer stream * - * @return Returns true if successful, returns false otherwise + * @return Returns true if successful, returns false otherwise */ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_encode(opj_codec_t *p_codec, - opj_stream_t *p_stream); + opj_stream_t *p_stream); /* ========================================================== codec output functions definitions @@ -1477,60 +1584,65 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_encode(opj_codec_t *p_codec, Destroy Codestream information after compression or decompression @param cstr_info Codestream information structure */ -OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t **cstr_info); +OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t + **cstr_info); /** * Dump the codec information into the output stream * - * @param p_codec the jpeg2000 codec. - * @param info_flag type of information dump. - * @param output_stream output stream where dump the informations get from the codec. + * @param p_codec the jpeg2000 codec. + * @param info_flag type of information dump. + * @param output_stream output stream where dump the information gotten from the codec. * */ -OPJ_API void OPJ_CALLCONV opj_dump_codec( opj_codec_t *p_codec, - OPJ_INT32 info_flag, - FILE* output_stream); +OPJ_API void OPJ_CALLCONV opj_dump_codec(opj_codec_t *p_codec, + OPJ_INT32 info_flag, + FILE* output_stream); /** * Get the codestream information from the codec * - * @param p_codec the jpeg2000 codec. + * @param p_codec the jpeg2000 codec. * - * @return a pointer to a codestream information structure. + * @return a pointer to a codestream information structure. * */ -OPJ_API opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info(opj_codec_t *p_codec); +OPJ_API opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info( + opj_codec_t *p_codec); /** * Get the codestream index from the codec * - * @param p_codec the jpeg2000 codec. + * @param p_codec the jpeg2000 codec. * - * @return a pointer to a codestream index structure. + * @return a pointer to a codestream index structure. * */ -OPJ_API opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index(opj_codec_t *p_codec); +OPJ_API opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index( + opj_codec_t *p_codec); -OPJ_API void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index); +OPJ_API void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t + **p_cstr_index); /** * Get the JP2 file information from the codec FIXME * - * @param p_codec the jpeg2000 codec. + * @param p_codec the jpeg2000 codec. * - * @return a pointer to a JP2 metadata structure. + * @return a pointer to a JP2 metadata structure. * */ -OPJ_API opj_jp2_metadata_t* OPJ_CALLCONV opj_get_jp2_metadata(opj_codec_t *p_codec); +OPJ_API opj_jp2_metadata_t* OPJ_CALLCONV opj_get_jp2_metadata( + opj_codec_t *p_codec); /** * Get the JP2 file index from the codec FIXME * - * @param p_codec the jpeg2000 codec. + * @param p_codec the jpeg2000 codec. * - * @return a pointer to a JP2 index structure. + * @return a pointer to a JP2 index structure. * */ OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec); @@ -1545,18 +1657,31 @@ OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec); /** * Sets the MCT matrix to use. * - * @param parameters the parameters to change. - * @param pEncodingMatrix the encoding matrix. - * @param p_dc_shift the dc shift coefficients to use. - * @param pNbComp the number of components of the image. + * @param parameters the parameters to change. + * @param pEncodingMatrix the encoding matrix. + * @param p_dc_shift the dc shift coefficients to use. + * @param pNbComp the number of components of the image. * - * @return true if the parameters could be set. + * @return true if the parameters could be set. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters, + OPJ_FLOAT32 * pEncodingMatrix, + OPJ_INT32 * p_dc_shift, + OPJ_UINT32 pNbComp); + +/* +========================================================== + Thread functions +========================================================== +*/ + +/** Returns if the library is built with thread support. + * OPJ_TRUE if mutex, condition, thread, thread pool are available. */ -OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_MCT( opj_cparameters_t *parameters, - OPJ_FLOAT32 * pEncodingMatrix, - OPJ_INT32 * p_dc_shift, - OPJ_UINT32 pNbComp); +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void); +/** Return the number of virtual CPUs */ +OPJ_API int OPJ_CALLCONV opj_get_num_cpus(void); #ifdef __cplusplus diff --git a/third_party/libopenjpeg20/opj_clock.c b/third_party/libopenjpeg20/opj_clock.c index 0df99ef04defd84f5b442a074c42f4794e67c3fb..24f79a9ae7568e573eef2dae4bb2c738258a30a3 100644 --- a/third_party/libopenjpeg20/opj_clock.c +++ b/third_party/libopenjpeg20/opj_clock.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -29,6 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "opj_includes.h" + #ifdef _WIN32 #include <windows.h> #else @@ -36,29 +38,30 @@ #include <sys/resource.h> #include <sys/times.h> #endif /* _WIN32 */ -#include "opj_includes.h" -OPJ_FLOAT64 opj_clock(void) { +OPJ_FLOAT64 opj_clock(void) +{ #ifdef _WIN32 - /* _WIN32: use QueryPerformance (very accurate) */ - LARGE_INTEGER freq , t ; + /* _WIN32: use QueryPerformance (very accurate) */ + LARGE_INTEGER freq, t ; /* freq is the clock speed of the CPU */ QueryPerformanceFrequency(&freq) ; - /* cout << "freq = " << ((double) freq.QuadPart) << endl; */ + /* cout << "freq = " << ((double) freq.QuadPart) << endl; */ /* t is the high resolution performance counter (see MSDN) */ - QueryPerformanceCounter ( & t ) ; - return ( t.QuadPart /(OPJ_FLOAT64) freq.QuadPart ) ; + QueryPerformanceCounter(& t) ; + return ((OPJ_FLOAT64) t.QuadPart / (OPJ_FLOAT64) freq.QuadPart) ; #else - /* Unix or Linux: use resource usage */ + /* Unix or Linux: use resource usage */ struct rusage t; OPJ_FLOAT64 procTime; /* (1) Get the rusage data structure at this moment (man getrusage) */ - getrusage(0,&t); + getrusage(0, &t); /* (2) What is the elapsed time ? - CPU time = User time + System time */ - /* (2a) Get the seconds */ + /* (2a) Get the seconds */ procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec); /* (2b) More precisely! Get the microseconds part ! */ - return ( procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ; + return (procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) * + 1e-6) ; #endif } diff --git a/third_party/libopenjpeg20/opj_clock.h b/third_party/libopenjpeg20/opj_clock.h index 6f5168b5728a6e05808bdac1bfb0c7ccbb52d414..76366f53b501706c77eb790e76c2b5cc68c527bf 100644 --- a/third_party/libopenjpeg20/opj_clock.h +++ b/third_party/libopenjpeg20/opj_clock.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -28,8 +28,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __OPJ_CLOCK_H -#define __OPJ_CLOCK_H +#ifndef OPJ_CLOCK_H +#define OPJ_CLOCK_H /** @file opj_clock.h @brief Internal function for timing @@ -55,5 +55,5 @@ OPJ_FLOAT64 opj_clock(void); /*@}*/ -#endif /* __OPJ_CLOCK_H */ +#endif /* OPJ_CLOCK_H */ diff --git a/third_party/libopenjpeg20/opj_codec.h b/third_party/libopenjpeg20/opj_codec.h index 6bd791fa7a62c69167cf57a15b1a40964e988f40..b962b121633e1fb10c65a8b2bee5b5d99c8cdee3 100644 --- a/third_party/libopenjpeg20/opj_codec.h +++ b/third_party/libopenjpeg20/opj_codec.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -29,8 +29,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __OPJ_CODEC_H -#define __OPJ_CODEC_H +#ifndef OPJ_CODEC_H +#define OPJ_CODEC_H /** @file opj_codec.h */ @@ -39,113 +39,115 @@ /** * Main codec handler used for compression or decompression. */ -typedef struct opj_codec_private -{ +typedef struct opj_codec_private { /** FIXME DOC */ - union - { + union { /** * Decompression handler. */ - struct opj_decompression - { + struct opj_decompression { /** Main header reading function handler */ - OPJ_BOOL (*opj_read_header) ( struct opj_stream_private * cio, - void * p_codec, - opj_image_t **p_image, - struct opj_event_mgr * p_manager); + OPJ_BOOL(*opj_read_header)(struct opj_stream_private * cio, + void * p_codec, + opj_image_t **p_image, + struct opj_event_mgr * p_manager); /** Decoding function */ - OPJ_BOOL (*opj_decode) ( void * p_codec, - struct opj_stream_private * p_cio, - opj_image_t * p_image, - struct opj_event_mgr * p_manager); + OPJ_BOOL(*opj_decode)(void * p_codec, + struct opj_stream_private * p_cio, + opj_image_t * p_image, + struct opj_event_mgr * p_manager); /** FIXME DOC */ - OPJ_BOOL (*opj_read_tile_header)( void * p_codec, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - OPJ_BOOL * p_should_go_on, - struct opj_stream_private * p_cio, - struct opj_event_mgr * p_manager); + OPJ_BOOL(*opj_read_tile_header)(void * p_codec, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_should_go_on, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); /** FIXME DOC */ - OPJ_BOOL (*opj_decode_tile_data)( void * p_codec, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private * p_cio, - struct opj_event_mgr * p_manager); + OPJ_BOOL(*opj_decode_tile_data)(void * p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); /** Reading function used after codestream if necessary */ - OPJ_BOOL (* opj_end_decompress) ( void *p_codec, - struct opj_stream_private * cio, - struct opj_event_mgr * p_manager); + OPJ_BOOL(* opj_end_decompress)(void *p_codec, + struct opj_stream_private * cio, + struct opj_event_mgr * p_manager); /** Codec destroy function handler */ - void (*opj_destroy) (void * p_codec); + void (*opj_destroy)(void * p_codec); /** Setup decoder function handler */ - void (*opj_setup_decoder) ( void * p_codec, opj_dparameters_t * p_param); + void (*opj_setup_decoder)(void * p_codec, opj_dparameters_t * p_param); /** Set decode area function handler */ - OPJ_BOOL (*opj_set_decode_area) ( void * p_codec, - opj_image_t * p_image, - OPJ_INT32 p_start_x, - OPJ_INT32 p_end_x, - OPJ_INT32 p_start_y, - OPJ_INT32 p_end_y, - struct opj_event_mgr * p_manager); + OPJ_BOOL(*opj_set_decode_area)(void * p_codec, + opj_image_t * p_image, + OPJ_INT32 p_start_x, + OPJ_INT32 p_end_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager); /** Get tile function */ - OPJ_BOOL (*opj_get_decoded_tile) ( void *p_codec, - opj_stream_private_t * p_cio, - opj_image_t *p_image, - struct opj_event_mgr * p_manager, - OPJ_UINT32 tile_index); + OPJ_BOOL(*opj_get_decoded_tile)(void *p_codec, + opj_stream_private_t * p_cio, + opj_image_t *p_image, + struct opj_event_mgr * p_manager, + OPJ_UINT32 tile_index); /** Set the decoded resolution factor */ - OPJ_BOOL (*opj_set_decoded_resolution_factor) ( void * p_codec, - OPJ_UINT32 res_factor, - opj_event_mgr_t * p_manager); + OPJ_BOOL(*opj_set_decoded_resolution_factor)(void * p_codec, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager); + + /** Set the decoded components */ + OPJ_BOOL(*opj_set_decoded_components)(void * p_codec, + OPJ_UINT32 num_comps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager); } m_decompression; /** * Compression handler. FIXME DOC */ - struct opj_compression - { - OPJ_BOOL (* opj_start_compress) ( void *p_codec, - struct opj_stream_private * cio, - struct opj_image * p_image, - struct opj_event_mgr * p_manager); - - OPJ_BOOL (* opj_encode) ( void * p_codec, - struct opj_stream_private *p_cio, - struct opj_event_mgr * p_manager); - - OPJ_BOOL (* opj_write_tile) ( void * p_codec, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private * p_cio, + struct opj_compression { + OPJ_BOOL(* opj_start_compress)(void *p_codec, + struct opj_stream_private * cio, + struct opj_image * p_image, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_encode)(void * p_codec, + struct opj_stream_private *p_cio, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_write_tile)(void * p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_end_compress)(void * p_codec, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); + + void (* opj_destroy)(void * p_codec); + + OPJ_BOOL(* opj_setup_encoder)(void * p_codec, + opj_cparameters_t * p_param, + struct opj_image * p_image, struct opj_event_mgr * p_manager); - - OPJ_BOOL (* opj_end_compress) ( void * p_codec, - struct opj_stream_private * p_cio, - struct opj_event_mgr * p_manager); - - void (* opj_destroy) (void * p_codec); - - OPJ_BOOL (* opj_setup_encoder) ( void * p_codec, - opj_cparameters_t * p_param, - struct opj_image * p_image, - struct opj_event_mgr * p_manager); } m_compression; } m_codec_data; /** FIXME DOC*/ @@ -154,12 +156,16 @@ typedef struct opj_codec_private opj_event_mgr_t m_event_mgr; /** Flag to indicate if the codec is used to decode or encode*/ OPJ_BOOL is_decompressor; - void (*opj_dump_codec) (void * p_codec, OPJ_INT32 info_flag, FILE* output_stream); + void (*opj_dump_codec)(void * p_codec, OPJ_INT32 info_flag, + FILE* output_stream); opj_codestream_info_v2_t* (*opj_get_codec_info)(void* p_codec); opj_codestream_index_t* (*opj_get_codec_index)(void* p_codec); + + /** Set number of threads */ + OPJ_BOOL(*opj_set_threads)(void * p_codec, OPJ_UINT32 num_threads); } opj_codec_private_t; -#endif /* __OPJ_CODEC_H */ +#endif /* OPJ_CODEC_H */ diff --git a/third_party/libopenjpeg20/opj_common.h b/third_party/libopenjpeg20/opj_common.h new file mode 100644 index 0000000000000000000000000000000000000000..a051339154b69e295bddf24a0ca539cf7f773df8 --- /dev/null +++ b/third_party/libopenjpeg20/opj_common.h @@ -0,0 +1,41 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OPJ_COMMMON_H +#define OPJ_COMMMON_H + +/* + ========================================================== + Common constants shared among several modules + ========================================================== +*/ +#define OPJ_COMMON_CBLK_DATA_EXTRA 2 /**< Margin for a fake FFFF marker */ + +#endif /* OPJ_COMMMON_H */ diff --git a/third_party/libopenjpeg20/opj_config.h b/third_party/libopenjpeg20/opj_config.h index 37bc9ba3c31e27e1d06ec5ddaa680a1c84415edf..738454143917802da5b52153a352a0f8bf6d5666 100644 --- a/third_party/libopenjpeg20/opj_config.h +++ b/third_party/libopenjpeg20/opj_config.h @@ -12,5 +12,5 @@ /* Version number. */ #define OPJ_VERSION_MAJOR 2 -#define OPJ_VERSION_MINOR 1 +#define OPJ_VERSION_MINOR 3 #define OPJ_VERSION_BUILD 0 diff --git a/third_party/libopenjpeg20/opj_config_private.h b/third_party/libopenjpeg20/opj_config_private.h index 7d7e3ea463db7b3ef3354cf7db796a28b40a75ad..81b449d2e2ee4342f375282a1c517bb294fdf266 100644 --- a/third_party/libopenjpeg20/opj_config_private.h +++ b/third_party/libopenjpeg20/opj_config_private.h @@ -7,7 +7,7 @@ /* create opj_config_private.h for CMake */ #define OPJ_HAVE_INTTYPES_H 1 -#define OPJ_PACKAGE_VERSION "2.1.0" +#define OPJ_PACKAGE_VERSION "2.3.0" /* Not used by openjp2*/ /*#define HAVE_MEMORY_H 1*/ diff --git a/third_party/libopenjpeg20/opj_includes.h b/third_party/libopenjpeg20/opj_includes.h index 5add09188e958419af326391d79508e6366f6ddc..0a8628c96b3043f2d1635f32dca2be7b08340881 100644 --- a/third_party/libopenjpeg20/opj_includes.h +++ b/third_party/libopenjpeg20/opj_includes.h @@ -1,11 +1,11 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -54,6 +54,7 @@ #include <stdarg.h> #include <ctype.h> #include <assert.h> +#include <limits.h> /* Use fseeko() and ftello() if they are available since they use @@ -70,11 +71,11 @@ #if defined(WIN32) && !defined(Windows95) && !defined(__BORLANDC__) && \ !(defined(_MSC_VER) && _MSC_VER < 1400) && \ !(defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x800) - /* - Windows '95 and Borland C do not support _lseeki64 - Visual Studio does not support _fseeki64 and _ftelli64 until the 2005 release. - Without these interfaces, files over 2GB in size are not supported for Windows. - */ +/* + Windows '95 and Borland C do not support _lseeki64 + Visual Studio does not support _fseeki64 and _ftelli64 until the 2005 release. + Without these interfaces, files over 2GB in size are not supported for Windows. +*/ # define OPJ_FSEEK(stream,offset,whence) _fseeki64(stream,/* __int64 */ offset,whence) # define OPJ_FSTAT(fildes,stat_buff) _fstati64(fildes,/* struct _stati64 */ stat_buff) # define OPJ_FTELL(stream) /* __int64 */ _ftelli64(stream) @@ -103,69 +104,120 @@ */ /* Are restricted pointers available? (C99) */ -#if (__STDC_VERSION__ != 199901L) - /* Not a C99 compiler */ - #ifdef __GNUC__ - #define restrict __restrict__ - #else - #define restrict /* restrict */ - #endif +#if (__STDC_VERSION__ >= 199901L) +#define OPJ_RESTRICT restrict +#else +/* Not a C99 compiler */ +#if defined(__GNUC__) +#define OPJ_RESTRICT __restrict__ + +/* + vc14 (2015) outputs wrong results. + Need to check OPJ_RESTRICT usage (or a bug in vc14) + #elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define OPJ_RESTRICT __restrict +*/ +#else +#define OPJ_RESTRICT /* restrict */ +#endif #endif +#ifdef __has_attribute +#if __has_attribute(no_sanitize) +#define OPJ_NOSANITIZE(kind) __attribute__((no_sanitize(kind))) +#endif +#endif +#ifndef OPJ_NOSANITIZE +#define OPJ_NOSANITIZE(kind) +#endif /* MSVC before 2013 and Borland C do not have lrintf */ #if defined(_MSC_VER) #include <intrin.h> -static INLINE long opj_lrintf(float f){ +static INLINE long opj_lrintf(float f) +{ #ifdef _M_X64 - return _mm_cvt_ss2si(_mm_load_ss(&f)); + return _mm_cvt_ss2si(_mm_load_ss(&f)); - /* commented out line breaks many tests */ - /* return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); */ + /* commented out line breaks many tests */ + /* return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); */ #elif defined(_M_IX86) int i; - _asm{ + _asm{ fld f fistp i }; - + return i; -#else - return (long)((f>0.0f) ? (f + 0.5f) : (f - 0.5f)); +#else + return (long)((f>0.0f) ? (f + 0.5f) : (f - 0.5f)); #endif } #elif defined(__BORLANDC__) -static INLINE long opj_lrintf(float f) { +static INLINE long opj_lrintf(float f) +{ #ifdef _M_X64 - return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); + return (long)((f > 0.0f) ? (f + 0.5f) : (f - 0.5f)); #else - int i; + int i; - _asm { - fld f - fistp i - }; + _asm { + fld f + fistp i + }; - return i; + return i; #endif } #else -static INLINE long opj_lrintf(float f) { - return lrintf(f); +static INLINE long opj_lrintf(float f) +{ + return lrintf(f); } #endif #if defined(_MSC_VER) && (_MSC_VER < 1400) - #define vsnprintf _vsnprintf +#define vsnprintf _vsnprintf #endif /* MSVC x86 is really bad at doing int64 = int32 * int32 on its own. Use intrinsic. */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) -# include <intrin.h> -# pragma intrinsic(__emul) +# include <intrin.h> +# pragma intrinsic(__emul) +#endif + +/* Apparently Visual Studio doesn't define __SSE__ / __SSE2__ macros */ +#if defined(_M_X64) +/* Intel 64bit support SSE and SSE2 */ +# ifndef __SSE__ +# define __SSE__ 1 +# endif +# ifndef __SSE2__ +# define __SSE2__ 1 +# endif +#endif + +/* For x86, test the value of the _M_IX86_FP macro. */ +/* See https://msdn.microsoft.com/en-us/library/b0084kay.aspx */ +#if defined(_M_IX86_FP) +# if _M_IX86_FP >= 1 +# ifndef __SSE__ +# define __SSE__ 1 +# endif +# endif +# if _M_IX86_FP >= 2 +# ifndef __SSE2__ +# define __SSE2__ 1 +# endif +# endif #endif +/* Type to use for bit-fields in internal headers */ +typedef unsigned int OPJ_BITFIELD; + +#define OPJ_UNUSED(x) (void)x + #include "opj_inttypes.h" #include "opj_clock.h" #include "opj_malloc.h" @@ -174,13 +226,15 @@ static INLINE long opj_lrintf(float f) { #include "bio.h" #include "cio.h" +#include "thread.h" +#include "tls_keys.h" + #include "image.h" #include "invert.h" #include "j2k.h" #include "jp2.h" #include "mqc.h" -#include "raw.h" #include "bio.h" #include "pi.h" @@ -191,6 +245,7 @@ static INLINE long opj_lrintf(float f) { #include "t2.h" #include "mct.h" #include "opj_intmath.h" +#include "sparse_array.h" #ifdef USE_JPIP #include "cidx_manager.h" diff --git a/third_party/libopenjpeg20/opj_intmath.h b/third_party/libopenjpeg20/opj_intmath.h index 3f7934c470cbbf3bec7e9fab5488df7f8de74018..ad13597661319d8eda186143e3fb7b2c0019bdd3 100644 --- a/third_party/libopenjpeg20/opj_intmath.h +++ b/third_party/libopenjpeg20/opj_intmath.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. @@ -34,8 +34,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __INT_H -#define __INT_H +#ifndef OPJ_INTMATH_H +#define OPJ_INTMATH_H /** @file opj_intmath.h @brief Implementation of operations on integers (INT) @@ -53,41 +53,76 @@ The functions in OPJ_INTMATH.H have for goal to realize operations on integers. Get the minimum of two integers @return Returns a if a < b else b */ -static INLINE OPJ_INT32 opj_int_min(OPJ_INT32 a, OPJ_INT32 b) { - return a < b ? a : b; +static INLINE OPJ_INT32 opj_int_min(OPJ_INT32 a, OPJ_INT32 b) +{ + return a < b ? a : b; } /** Get the minimum of two integers @return Returns a if a < b else b */ -static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b) { - return a < b ? a : b; +static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return a < b ? a : b; } /** Get the maximum of two integers @return Returns a if a > b else b */ -static INLINE OPJ_INT32 opj_int_max(OPJ_INT32 a, OPJ_INT32 b) { - return (a > b) ? a : b; +static INLINE OPJ_INT32 opj_int_max(OPJ_INT32 a, OPJ_INT32 b) +{ + return (a > b) ? a : b; } /** Get the maximum of two integers @return Returns a if a > b else b */ -static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b) { - return (a > b) ? a : b; +static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return (a > b) ? a : b; } /** Get the saturated sum of two unsigned integers @return Returns saturated sum of a+b */ -static INLINE OPJ_UINT32 opj_uint_adds(OPJ_UINT32 a, OPJ_UINT32 b) { - OPJ_UINT64 sum = (OPJ_UINT64)a + (OPJ_UINT64)b; - return (OPJ_UINT32)(-(OPJ_INT32)(sum >> 32)) | (OPJ_UINT32)sum; +static INLINE OPJ_UINT32 opj_uint_adds(OPJ_UINT32 a, OPJ_UINT32 b) +{ + OPJ_UINT64 sum = (OPJ_UINT64)a + (OPJ_UINT64)b; + return (OPJ_UINT32)(-(OPJ_INT32)(sum >> 32)) | (OPJ_UINT32)sum; +} + +/** + Get the saturated difference of two unsigned integers + @return Returns saturated sum of a-b + */ +static INLINE OPJ_UINT32 opj_uint_subs(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return (a >= b) ? a - b : 0; +} + +/** +Clamp an integer inside an interval +@return +<ul> +<li>Returns a if (min < a < max) +<li>Returns max if (a > max) +<li>Returns min if (a < min) +</ul> +*/ +static INLINE OPJ_INT32 opj_int_clamp(OPJ_INT32 a, OPJ_INT32 min, + OPJ_INT32 max) +{ + if (a < min) { + return min; + } + if (a > max) { + return max; + } + return a; } /** @@ -96,93 +131,106 @@ Clamp an integer inside an interval <ul> <li>Returns a if (min < a < max) <li>Returns max if (a > max) -<li>Returns min if (a < min) +<li>Returns min if (a < min) </ul> */ -static INLINE OPJ_INT32 opj_int_clamp(OPJ_INT32 a, OPJ_INT32 min, OPJ_INT32 max) { - if (a < min) - return min; - if (a > max) - return max; - return a; +static INLINE OPJ_INT64 opj_int64_clamp(OPJ_INT64 a, OPJ_INT64 min, + OPJ_INT64 max) +{ + if (a < min) { + return min; + } + if (a > max) { + return max; + } + return a; } + /** @return Get absolute value of integer */ -static INLINE OPJ_INT32 opj_int_abs(OPJ_INT32 a) { - return a < 0 ? -a : a; +static INLINE OPJ_INT32 opj_int_abs(OPJ_INT32 a) +{ + return a < 0 ? -a : a; } /** Divide an integer and round upwards @return Returns a divided by b */ -static INLINE OPJ_INT32 opj_int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) { - assert(b); - return (a + b - 1) / b; +static INLINE OPJ_INT32 opj_int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) +{ + assert(b); + return (OPJ_INT32)(((OPJ_INT64)a + b - 1) / b); } /** Divide an integer and round upwards @return Returns a divided by b */ -static INLINE OPJ_UINT32 opj_uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) { - assert(b); - return (a + b - 1) / b; +static INLINE OPJ_UINT32 opj_uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) +{ + assert(b); + return (a + b - 1) / b; } /** Divide an integer by a power of 2 and round upwards @return Returns a divided by 2^b */ -static INLINE OPJ_INT32 opj_int_ceildivpow2(OPJ_INT32 a, OPJ_INT32 b) { - return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b); +static INLINE OPJ_INT32 opj_int_ceildivpow2(OPJ_INT32 a, OPJ_INT32 b) +{ + return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b); } /** Divide a 64bits integer by a power of 2 and round upwards @return Returns a divided by 2^b */ -static INLINE OPJ_INT32 opj_int64_ceildivpow2(OPJ_INT64 a, OPJ_INT32 b) { - return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b); +static INLINE OPJ_INT32 opj_int64_ceildivpow2(OPJ_INT64 a, OPJ_INT32 b) +{ + return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b); } /** Divide an integer by a power of 2 and round upwards @return Returns a divided by 2^b */ -static INLINE OPJ_UINT32 opj_uint_ceildivpow2(OPJ_UINT32 a, OPJ_UINT32 b) { - return (OPJ_UINT32)((a + ((OPJ_UINT64)1U << b) - 1U) >> b); +static INLINE OPJ_UINT32 opj_uint_ceildivpow2(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return (OPJ_UINT32)((a + ((OPJ_UINT64)1U << b) - 1U) >> b); } /** Divide an integer by a power of 2 and round downwards @return Returns a divided by 2^b */ -static INLINE OPJ_INT32 opj_int_floordivpow2(OPJ_INT32 a, OPJ_INT32 b) { - return a >> b; +static INLINE OPJ_INT32 opj_int_floordivpow2(OPJ_INT32 a, OPJ_INT32 b) +{ + return a >> b; } /** Get logarithm of an integer and round downwards @return Returns log2(a) */ -static INLINE OPJ_INT32 opj_int_floorlog2(OPJ_INT32 a) { - OPJ_INT32 l; - for (l = 0; a > 1; l++) { - a >>= 1; - } - return l; +static INLINE OPJ_INT32 opj_int_floorlog2(OPJ_INT32 a) +{ + OPJ_INT32 l; + for (l = 0; a > 1; l++) { + a >>= 1; + } + return l; } /** Get logarithm of an integer and round downwards @return Returns log2(a) */ -static INLINE OPJ_UINT32 opj_uint_floorlog2(OPJ_UINT32 a) { - OPJ_UINT32 l; - for (l = 0; a > 1; ++l) - { - a >>= 1; - } - return l; +static INLINE OPJ_UINT32 opj_uint_floorlog2(OPJ_UINT32 a) +{ + OPJ_UINT32 l; + for (l = 0; a > 1; ++l) { + a >>= 1; + } + return l; } /** @@ -191,28 +239,31 @@ Multiply two fixed-precision rational numbers. @param b @return Returns a * b */ -static INLINE OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) { +static INLINE OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) +{ #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) - OPJ_INT64 temp = __emul(a, b); + OPJ_INT64 temp = __emul(a, b); #else - OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; #endif - temp += 4096; - assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF); - assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1)); - return (OPJ_INT32) (temp >> 13); + temp += 4096; + assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF); + assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1)); + return (OPJ_INT32)(temp >> 13); } -static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) { +static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) +{ #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) - OPJ_INT64 temp = __emul(a, b); + OPJ_INT64 temp = __emul(a, b); #else - OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; #endif - temp += 4096; - assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) <= (OPJ_INT64)0x7FFFFFFF); - assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1)); - return (OPJ_INT32) (temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) ; + temp += 4096; + assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) <= (OPJ_INT64)0x7FFFFFFF); + assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) >= (-(OPJ_INT64)0x7FFFFFFF - + (OPJ_INT64)1)); + return (OPJ_INT32)(temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) ; } /* ----------------------------------------------------------------------- */ @@ -220,4 +271,4 @@ static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) { /*@}*/ -#endif +#endif /* OPJ_INTMATH_H */ diff --git a/third_party/libopenjpeg20/opj_inttypes.h b/third_party/libopenjpeg20/opj_inttypes.h index e74aed6a17e004949efcbca8d17bfe73ae37542d..2c9749a178baf3c869e5d0516e946c93a3148873 100644 --- a/third_party/libopenjpeg20/opj_inttypes.h +++ b/third_party/libopenjpeg20/opj_inttypes.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * diff --git a/third_party/libopenjpeg20/opj_malloc.h b/third_party/libopenjpeg20/opj_malloc.h index 517707f94cf8c24ab82e747676ad663717570b97..79b3a64102ac641478431011b413cb2bc4ae7897 100644 --- a/third_party/libopenjpeg20/opj_malloc.h +++ b/third_party/libopenjpeg20/opj_malloc.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -29,8 +29,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __OPJ_MALLOC_H -#define __OPJ_MALLOC_H +#ifndef OPJ_MALLOC_H +#define OPJ_MALLOC_H /** @file opj_malloc.h @brief Internal functions @@ -63,8 +63,8 @@ void * OPJ_CALLCONV opj_malloc(size_t size); /** Allocate a memory block with elements initialized to 0 -@param num Blocks to allocate -@param size Bytes per block to allocate +@param numOfElements Blocks to allocate +@param sizeOfElements Bytes per block to allocate @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available */ #ifdef ALLOC_PERF_OPT @@ -85,64 +85,79 @@ Allocate memory aligned to a 16 byte boundary */ /* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ #ifdef _WIN32 - /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ - #ifdef __GNUC__ - #include <mm_malloc.h> - #define HAVE_MM_MALLOC - #else /* MSVC, Intel C++ */ - #include <malloc.h> - #ifdef _mm_malloc - #define HAVE_MM_MALLOC - #endif - #endif + /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ + #ifdef __GNUC__ + #include <mm_malloc.h> + #define HAVE_MM_MALLOC + #else /* MSVC, Intel C++ */ + #include <malloc.h> + #ifdef _mm_malloc + #define HAVE_MM_MALLOC + #endif + #endif #else /* Not _WIN32 */ - #if defined(__sun) - #define HAVE_MEMALIGN + #if defined(__sun) + #define HAVE_MEMALIGN #elif defined(__FreeBSD__) #define HAVE_POSIX_MEMALIGN - /* Linux x86_64 and OSX always align allocations to 16 bytes */ - #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX) - #define HAVE_MEMALIGN - #include <malloc.h> - #endif + /* Linux x86_64 and OSX always align allocations to 16 bytes */ + #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX) + #define HAVE_MEMALIGN + #include <malloc.h> + #endif #endif #define opj_aligned_malloc(size) malloc(size) +#define opj_aligned_32_malloc(size) malloc(size) #define opj_aligned_free(m) free(m) #ifdef HAVE_MM_MALLOC - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) _mm_malloc(size, 16) - #undef opj_aligned_free - #define opj_aligned_free(m) _mm_free(m) + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) _mm_malloc((size), 16) + #undef opj_aligned_32_malloc + #define opj_aligned_32_malloc(size) _mm_malloc((size), 32) + #undef opj_aligned_free + #define opj_aligned_free(m) _mm_free(m) #endif #ifdef HAVE_MEMALIGN - extern void* memalign(size_t, size_t); - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) memalign(16, (size)) - #undef opj_aligned_free - #define opj_aligned_free(m) free(m) + extern void* memalign(size_t, size_t); + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) memalign(16, (size)) + #undef opj_aligned_32_malloc + #define opj_aligned_32_malloc(size) memalign(32, (size)) + #undef opj_aligned_free + #define opj_aligned_free(m) free(m) #endif #ifdef HAVE_POSIX_MEMALIGN - #undef opj_aligned_malloc - extern int posix_memalign(void**, size_t, size_t); - - static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ - void* mem = NULL; - posix_memalign(&mem, 16, size); - return mem; - } - #undef opj_aligned_free - #define opj_aligned_free(m) free(m) + #undef opj_aligned_malloc + extern int posix_memalign(void**, size_t, size_t); + + static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ + void* mem = NULL; + posix_memalign(&mem, 16, size); + return mem; + } + + #undef opj_aligned_32_malloc + static INLINE void* __attribute__ ((malloc)) opj_aligned_32_malloc(size_t size){ + void* mem = NULL; + posix_memalign(&mem, 32, size); + return mem; + } + + #undef opj_aligned_free + #define opj_aligned_free(m) free(m) #endif #ifdef ALLOC_PERF_OPT - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) opj_malloc(size) - #undef opj_aligned_free - #define opj_aligned_free(m) opj_free(m) + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) opj_malloc(size) + #undef opj_aligned_32_malloc + #define opj_aligned_32_malloc(size) opj_malloc(size) + #undef opj_aligned_free + #define opj_aligned_free(m) opj_free(m) #endif /** @@ -172,7 +187,7 @@ void OPJ_CALLCONV opj_free(void * m); #define opj_free(m) free(m) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(OPJ_SKIP_POISON) #pragma GCC poison malloc calloc realloc free #endif @@ -181,5 +196,5 @@ void OPJ_CALLCONV opj_free(void * m); /*@}*/ -#endif /* __OPJ_MALLOC_H */ +#endif /* OPJ_MALLOC_H */ diff --git a/third_party/libopenjpeg20/opj_stdint.h b/third_party/libopenjpeg20/opj_stdint.h index b8556a19383480da99651bb2d44a5c678920cfad..f26c921c2538cb8bc6280efddfea32948f3e70d8 100644 --- a/third_party/libopenjpeg20/opj_stdint.h +++ b/third_party/libopenjpeg20/opj_stdint.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c index 9097e31a0ee8808cec207292a176e08ce445509e..256fe37a1b3f0767facf2b03c56ac59f6b894153 100644 --- a/third_party/libopenjpeg20/pi.c +++ b/third_party/libopenjpeg20/pi.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan @@ -36,7 +36,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <limits.h> #include "opj_includes.h" /** @defgroup PI PI - Implementation of a packet iterator */ @@ -79,68 +78,68 @@ static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi); /** * Updates the coding parameters if the encoding is used with Progression order changes and final (or cinema parameters are used). * - * @param p_cp the coding parameters to modify - * @param p_tileno the tile index being concerned. - * @param p_tx0 X0 parameter for the tile - * @param p_tx1 X1 parameter for the tile - * @param p_ty0 Y0 parameter for the tile - * @param p_ty1 Y1 parameter for the tile - * @param p_max_prec the maximum precision for all the bands of the tile - * @param p_max_res the maximum number of resolutions for all the poc inside the tile. - * @param p_dx_min the minimum dx of all the components of all the resolutions for the tile. - * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile. + * @param p_cp the coding parameters to modify + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile. */ -static void opj_pi_update_encode_poc_and_final ( opj_cp_t *p_cp, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 p_ty1, - OPJ_UINT32 p_max_prec, - OPJ_UINT32 p_max_res, - OPJ_UINT32 p_dx_min, - OPJ_UINT32 p_dy_min); +static void opj_pi_update_encode_poc_and_final(opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min); /** * Updates the coding parameters if the encoding is not used with Progression order changes and final (and cinema parameters are used). * - * @param p_cp the coding parameters to modify - * @param p_num_comps the number of components - * @param p_tileno the tile index being concerned. - * @param p_tx0 X0 parameter for the tile - * @param p_tx1 X1 parameter for the tile - * @param p_ty0 Y0 parameter for the tile - * @param p_ty1 Y1 parameter for the tile - * @param p_max_prec the maximum precision for all the bands of the tile - * @param p_max_res the maximum number of resolutions for all the poc inside the tile. - * @param p_dx_min the minimum dx of all the components of all the resolutions for the tile. - * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile. + * @param p_cp the coding parameters to modify + * @param p_num_comps the number of components + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile. */ -static void opj_pi_update_encode_not_poc ( opj_cp_t *p_cp, - OPJ_UINT32 p_num_comps, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 p_ty1, - OPJ_UINT32 p_max_prec, - OPJ_UINT32 p_max_res, - OPJ_UINT32 p_dx_min, - OPJ_UINT32 p_dy_min); +static void opj_pi_update_encode_not_poc(opj_cp_t *p_cp, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min); /** * Gets the encoding parameters needed to update the coding parameters and all the pocs. - * - * @param p_image the image being encoded. - * @param p_cp the coding parameters. - * @param tileno the tile index of the tile being encoded. - * @param p_tx0 pointer that will hold the X0 parameter for the tile - * @param p_tx1 pointer that will hold the X1 parameter for the tile - * @param p_ty0 pointer that will hold the Y0 parameter for the tile - * @param p_ty1 pointer that will hold the Y1 parameter for the tile - * @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile - * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. - * @param p_dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. - * @param p_dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min pointer that will hold the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min pointer that will hold the minimum dy of all the components of all the resolutions for the tile. */ static void opj_get_encoding_parameters(const opj_image_t *p_image, const opj_cp_t *p_cp, @@ -152,7 +151,7 @@ static void opj_get_encoding_parameters(const opj_image_t *p_image, OPJ_UINT32 * p_dx_min, OPJ_UINT32 * p_dy_min, OPJ_UINT32 * p_max_prec, - OPJ_UINT32 * p_max_res ); + OPJ_UINT32 * p_max_res); /** * Gets the encoding parameters needed to update the coding parameters and all the pocs. @@ -161,65 +160,65 @@ static void opj_get_encoding_parameters(const opj_image_t *p_image, * to an area of size 4 * max_res. The data is stored inside this area with the following pattern : * dx_compi_res0 , dy_compi_res0 , w_compi_res0, h_compi_res0 , dx_compi_res1 , dy_compi_res1 , w_compi_res1, h_compi_res1 , ... * - * @param p_image the image being encoded. - * @param p_cp the coding parameters. - * @param tileno the tile index of the tile being encoded. - * @param p_tx0 pointer that will hold the X0 parameter for the tile - * @param p_tx1 pointer that will hold the X1 parameter for the tile - * @param p_ty0 pointer that will hold the Y0 parameter for the tile - * @param p_ty1 pointer that will hold the Y1 parameter for the tile - * @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile - * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. - * @param p_dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. - * @param p_dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. - * @param p_resolutions pointer to an area corresponding to the one described above. + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min pointer that will hold the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min pointer that will hold the minimum dy of all the components of all the resolutions for the tile. + * @param p_resolutions pointer to an area corresponding to the one described above. */ static void opj_get_all_encoding_parameters(const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 tileno, - OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * p_ty1, - OPJ_UINT32 * p_dx_min, - OPJ_UINT32 * p_dy_min, - OPJ_UINT32 * p_max_prec, - OPJ_UINT32 * p_max_res, - OPJ_UINT32 ** p_resolutions ); + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_INT32 * p_tx0, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res, + OPJ_UINT32 ** p_resolutions); /** * Allocates memory for a packet iterator. Data and data sizes are set by this operation. * No other data is set. The include section of the packet iterator is not allocated. - * - * @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant. - * @param p_cp the coding parameters. - * @param tileno the index of the tile from which creating the packet iterator. + * + * @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant. + * @param p_cp the coding parameters. + * @param tileno the index of the tile from which creating the packet iterator. */ -static opj_pi_iterator_t * opj_pi_create( const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 tileno ); +static opj_pi_iterator_t * opj_pi_create(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno); /** * FIXME DOC */ -static void opj_pi_update_decode_not_poc (opj_pi_iterator_t * p_pi, - opj_tcp_t * p_tcp, - OPJ_UINT32 p_max_precision, - OPJ_UINT32 p_max_res); +static void opj_pi_update_decode_not_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res); /** * FIXME DOC */ -static void opj_pi_update_decode_poc ( opj_pi_iterator_t * p_pi, - opj_tcp_t * p_tcp, - OPJ_UINT32 p_max_precision, - OPJ_UINT32 p_max_res); +static void opj_pi_update_decode_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res); /** * FIXME DOC */ -static OPJ_BOOL opj_pi_check_next_level( OPJ_INT32 pos, - opj_cp_t *cp, - OPJ_UINT32 tileno, - OPJ_UINT32 pino, - const OPJ_CHAR *prog); +static OPJ_BOOL opj_pi_check_next_level(OPJ_INT32 pos, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + const OPJ_CHAR *prog); /*@}*/ @@ -231,928 +230,1124 @@ static OPJ_BOOL opj_pi_check_next_level( OPJ_INT32 pos, ========================================================== */ -static OPJ_BOOL opj_pi_next_lrcp(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = NULL; - opj_pi_resolution_t *res = NULL; - OPJ_UINT32 index = 0; - - if (!pi->first) { - comp = &pi->comps[pi->compno]; - res = &comp->resolutions[pi->resno]; - goto LABEL_SKIP; - } else { - pi->first = 0; - } - - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; - pi->resno++) { - for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { - comp = &pi->comps[pi->compno]; - if (pi->resno >= comp->numresolutions) { - continue; - } - res = &comp->resolutions[pi->resno]; - if (!pi->tp_on){ - pi->poc.precno1 = res->pw * res->ph; - } - for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { - pi->include[index] = 1; - return OPJ_TRUE; - } -LABEL_SKIP:; - } - } - } - } - - return OPJ_FALSE; +static void opj_pi_emit_error(opj_pi_iterator_t * pi, const char* msg) +{ + (void)pi; + (void)msg; } -static OPJ_BOOL opj_pi_next_rlcp(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = NULL; - opj_pi_resolution_t *res = NULL; - OPJ_UINT32 index = 0; - - if (!pi->first) { - comp = &pi->comps[pi->compno]; - res = &comp->resolutions[pi->resno]; - goto LABEL_SKIP; - } else { - pi->first = 0; - } - - for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { - comp = &pi->comps[pi->compno]; - if (pi->resno >= comp->numresolutions) { - continue; - } - res = &comp->resolutions[pi->resno]; - if(!pi->tp_on){ - pi->poc.precno1 = res->pw * res->ph; - } - for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { - pi->include[index] = 1; - return OPJ_TRUE; - } -LABEL_SKIP:; - } - } - } - } - - return OPJ_FALSE; +static OPJ_BOOL opj_pi_next_lrcp(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; + pi->resno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if (!pi->tp_on) { + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + /* Avoids index out of bounds access with */ + /* id_000098,sig_11,src_005411,op_havoc,rep_2 of */ + /* https://github.com/uclouvain/openjpeg/issues/938 */ + /* Not sure if this is the most clever fix. Perhaps */ + /* include should be resized when a POC arises, or */ + /* the POC should be rejected */ + if (index >= pi->include_size) { + opj_pi_emit_error(pi, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + + return OPJ_FALSE; } -static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = NULL; - opj_pi_resolution_t *res = NULL; - OPJ_UINT32 index = 0; - - if (!pi->first) { - goto LABEL_SKIP; - } else { - OPJ_UINT32 compno, resno; - pi->first = 0; - pi->dx = 0; - pi->dy = 0; - for (compno = 0; compno < pi->numcomps; compno++) { - comp = &pi->comps[compno]; - for (resno = 0; resno < comp->numresolutions; resno++) { - OPJ_UINT32 dx, dy; - res = &comp->resolutions[resno]; - dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); - dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); - pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); - pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); - } - } - } -if (!pi->tp_on){ - pi->poc.ty0 = pi->ty0; - pi->poc.tx0 = pi->tx0; - pi->poc.ty1 = pi->ty1; - pi->poc.tx1 = pi->tx1; - } - for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { - for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += (OPJ_INT32)(pi->dy - (OPJ_UINT32)(pi->y % (OPJ_INT32)pi->dy))) { - for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += (OPJ_INT32)(pi->dx - (OPJ_UINT32)(pi->x % (OPJ_INT32)pi->dx))) { - for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { - OPJ_UINT32 levelno; - OPJ_INT32 trx0, try0; - OPJ_INT32 trx1, try1; - OPJ_UINT32 rpx, rpy; - OPJ_INT32 prci, prcj; - comp = &pi->comps[pi->compno]; - if (pi->resno >= comp->numresolutions) { - continue; - } - res = &comp->resolutions[pi->resno]; - levelno = comp->numresolutions - 1 - pi->resno; - trx0 = opj_int_ceildiv(pi->tx0, (OPJ_INT32)(comp->dx << levelno)); - try0 = opj_int_ceildiv(pi->ty0, (OPJ_INT32)(comp->dy << levelno)); - trx1 = opj_int_ceildiv(pi->tx1, (OPJ_INT32)(comp->dx << levelno)); - try1 = opj_int_ceildiv(pi->ty1, (OPJ_INT32)(comp->dy << levelno)); - rpx = res->pdx + levelno; - rpy = res->pdy + levelno; - if (!((pi->y % (OPJ_INT32)(comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ - continue; - } - if (!((pi->x % (OPJ_INT32)(comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ - continue; - } - - if ((res->pw==0)||(res->ph==0)) continue; - - if ((trx0==trx1)||(try0==try1)) continue; - - prci = opj_int_floordivpow2(opj_int_ceildiv(pi->x, (OPJ_INT32)(comp->dx << levelno)), (OPJ_INT32)res->pdx) - - opj_int_floordivpow2(trx0, (OPJ_INT32)res->pdx); - prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) - - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); - pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); - if (pi->precno >= res->pw * res->ph) { - return OPJ_FALSE; - } - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { - pi->include[index] = 1; - return OPJ_TRUE; - } -LABEL_SKIP:; - } - } - } - } - } - - return OPJ_FALSE; +static OPJ_BOOL opj_pi_next_rlcp(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if (!pi->tp_on) { + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_pi_emit_error(pi, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + + return OPJ_FALSE; } -static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = NULL; - opj_pi_resolution_t *res = NULL; - OPJ_UINT32 index = 0; - - if (!pi->first) { - comp = &pi->comps[pi->compno]; - goto LABEL_SKIP; - } else { - OPJ_UINT32 compno, resno; - pi->first = 0; - pi->dx = 0; - pi->dy = 0; - for (compno = 0; compno < pi->numcomps; compno++) { - comp = &pi->comps[compno]; - for (resno = 0; resno < comp->numresolutions; resno++) { - OPJ_UINT32 dx, dy; - res = &comp->resolutions[resno]; - dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); - dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); - pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); - pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); - } - } - } - if (!pi->tp_on){ - pi->poc.ty0 = pi->ty0; - pi->poc.tx0 = pi->tx0; - pi->poc.ty1 = pi->ty1; - pi->poc.tx1 = pi->tx1; - } - for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += (OPJ_INT32)(pi->dy - (OPJ_UINT32)(pi->y % (OPJ_INT32)pi->dy))) { - for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += (OPJ_INT32)(pi->dx - (OPJ_UINT32)(pi->x % (OPJ_INT32)pi->dx))) { - for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { - comp = &pi->comps[pi->compno]; - for (pi->resno = pi->poc.resno0; pi->resno < opj_uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { - OPJ_UINT32 levelno; - OPJ_INT32 trx0, try0; - OPJ_INT32 trx1, try1; - OPJ_UINT32 rpx, rpy; - OPJ_INT32 prci, prcj; - res = &comp->resolutions[pi->resno]; - levelno = comp->numresolutions - 1 - pi->resno; - trx0 = opj_int_ceildiv(pi->tx0, (OPJ_INT32)(comp->dx << levelno)); - try0 = opj_int_ceildiv(pi->ty0, (OPJ_INT32)(comp->dy << levelno)); - trx1 = opj_int_ceildiv(pi->tx1, (OPJ_INT32)(comp->dx << levelno)); - try1 = opj_int_ceildiv(pi->ty1, (OPJ_INT32)(comp->dy << levelno)); - rpx = res->pdx + levelno; - rpy = res->pdy + levelno; - if (!((pi->y % (OPJ_INT32)(comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ - continue; - } - if (!((pi->x % (OPJ_INT32)(comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ - continue; - } - - if ((res->pw==0)||(res->ph==0)) continue; - - if ((trx0==trx1)||(try0==try1)) continue; - - prci = opj_int_floordivpow2(opj_int_ceildiv(pi->x, (OPJ_INT32)(comp->dx << levelno)), (OPJ_INT32)res->pdx) - - opj_int_floordivpow2(trx0, (OPJ_INT32)res->pdx); - prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) - - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); - pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); - if (pi->precno >= res->pw * res->ph) { - return OPJ_FALSE; - } - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { - pi->include[index] = 1; - return OPJ_TRUE; - } -LABEL_SKIP:; - } - } - } - } - } - - return OPJ_FALSE; +static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (!pi->first) { + goto LABEL_SKIP; + } else { + OPJ_UINT32 compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + if (res->pdx + comp->numresolutions - 1 - resno < 32 && + comp->dx <= UINT_MAX / (1u << (res->pdx + comp->numresolutions - 1 - resno))) { + dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); + } + if (res->pdy + comp->numresolutions - 1 - resno < 32 && + comp->dy <= UINT_MAX / (1u << (res->pdy + comp->numresolutions - 1 - resno))) { + dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); + } + } + } + if (pi->dx == 0 || pi->dy == 0) { + return OPJ_FALSE; + } + } + if (!pi->tp_on) { + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; + pi->y += (OPJ_INT32)(pi->dy - (OPJ_UINT32)(pi->y % (OPJ_INT32)pi->dy))) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; + pi->x += (OPJ_INT32)(pi->dx - (OPJ_UINT32)(pi->x % (OPJ_INT32)pi->dx))) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + OPJ_UINT32 levelno; + OPJ_INT32 trx0, try0; + OPJ_INT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_INT32 prci, prcj; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + /* Avoids division by zero */ + /* Relates to id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */ + /* of https://github.com/uclouvain/openjpeg/issues/938 */ + if (levelno >= 32 || + ((comp->dx << levelno) >> levelno) != comp->dx || + ((comp->dy << levelno) >> levelno) != comp->dy) { + continue; + } + if ((comp->dx << levelno) > INT_MAX || + (comp->dy << levelno) > INT_MAX) { + continue; + } + trx0 = opj_int_ceildiv(pi->tx0, (OPJ_INT32)(comp->dx << levelno)); + try0 = opj_int_ceildiv(pi->ty0, (OPJ_INT32)(comp->dy << levelno)); + trx1 = opj_int_ceildiv(pi->tx1, (OPJ_INT32)(comp->dx << levelno)); + try1 = opj_int_ceildiv(pi->ty1, (OPJ_INT32)(comp->dy << levelno)); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + + /* To avoid divisions by zero / undefined behaviour on shift */ + /* in below tests */ + /* Fixes reading id:000026,sig:08,src:002419,op:int32,pos:60,val:+32 */ + /* of https://github.com/uclouvain/openjpeg/issues/938 */ + if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || + rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + continue; + } + + /* See ISO-15441. B.12.1.3 Resolution level-position-component-layer progression */ + if (!((pi->y % (OPJ_INT32)(comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && + ((try0 << levelno) % (1 << rpy))))) { + continue; + } + if (!((pi->x % (OPJ_INT32)(comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && + ((trx0 << levelno) % (1 << rpx))))) { + continue; + } + + if ((res->pw == 0) || (res->ph == 0)) { + continue; + } + + if ((trx0 == trx1) || (try0 == try1)) { + continue; + } + + prci = opj_int_floordivpow2(opj_int_ceildiv(pi->x, + (OPJ_INT32)(comp->dx << levelno)), (OPJ_INT32)res->pdx) + - opj_int_floordivpow2(trx0, (OPJ_INT32)res->pdx); + prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, + (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) + - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); + if (pi->precno >= res->pw * res->ph) { + return OPJ_FALSE; + } + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_pi_emit_error(pi, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + } + + return OPJ_FALSE; } -static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = NULL; - opj_pi_resolution_t *res = NULL; - OPJ_UINT32 index = 0; - - if (!pi->first) { - comp = &pi->comps[pi->compno]; - goto LABEL_SKIP; - } else { - pi->first = 0; - } - - for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { - OPJ_UINT32 resno; - comp = &pi->comps[pi->compno]; - pi->dx = 0; - pi->dy = 0; - for (resno = 0; resno < comp->numresolutions; resno++) { - OPJ_UINT32 dx, dy; - res = &comp->resolutions[resno]; - dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); - dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); - pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); - pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); - } - if (!pi->tp_on){ - pi->poc.ty0 = pi->ty0; - pi->poc.tx0 = pi->tx0; - pi->poc.ty1 = pi->ty1; - pi->poc.tx1 = pi->tx1; - } - for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += (OPJ_INT32)(pi->dy - (OPJ_UINT32)(pi->y % (OPJ_INT32)pi->dy))) { - for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += (OPJ_INT32)(pi->dx - (OPJ_UINT32)(pi->x % (OPJ_INT32)pi->dx))) { - for (pi->resno = pi->poc.resno0; pi->resno < opj_uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { - OPJ_UINT32 levelno; - OPJ_INT32 trx0, try0; - OPJ_INT32 trx1, try1; - OPJ_UINT32 rpx, rpy; - OPJ_INT32 prci, prcj; - res = &comp->resolutions[pi->resno]; - levelno = comp->numresolutions - 1 - pi->resno; - trx0 = opj_int_ceildiv(pi->tx0, (OPJ_INT32)(comp->dx << levelno)); - try0 = opj_int_ceildiv(pi->ty0, (OPJ_INT32)(comp->dy << levelno)); - trx1 = opj_int_ceildiv(pi->tx1, (OPJ_INT32)(comp->dx << levelno)); - try1 = opj_int_ceildiv(pi->ty1, (OPJ_INT32)(comp->dy << levelno)); - rpx = res->pdx + levelno; - rpy = res->pdy + levelno; - if (!((pi->y % (OPJ_INT32)(comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ - continue; - } - if (!((pi->x % (OPJ_INT32)(comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ - continue; - } - - if ((res->pw==0)||(res->ph==0)) continue; - - if ((trx0==trx1)||(try0==try1)) continue; - - prci = opj_int_floordivpow2(opj_int_ceildiv(pi->x, (OPJ_INT32)(comp->dx << levelno)), (OPJ_INT32)res->pdx) - - opj_int_floordivpow2(trx0, (OPJ_INT32)res->pdx); - prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) - - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); - pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); - if (pi->precno >= res->pw * res->ph) { - return OPJ_FALSE; - } - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[index]) { - pi->include[index] = 1; - return OPJ_TRUE; - } -LABEL_SKIP:; - } - } - } - } - } - - return OPJ_FALSE; +static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + OPJ_UINT32 compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + if (res->pdx + comp->numresolutions - 1 - resno < 32 && + comp->dx <= UINT_MAX / (1u << (res->pdx + comp->numresolutions - 1 - resno))) { + dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); + } + if (res->pdy + comp->numresolutions - 1 - resno < 32 && + comp->dy <= UINT_MAX / (1u << (res->pdy + comp->numresolutions - 1 - resno))) { + dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); + } + } + } + if (pi->dx == 0 || pi->dy == 0) { + return OPJ_FALSE; + } + } + if (!pi->tp_on) { + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; + pi->y += (OPJ_INT32)(pi->dy - (OPJ_UINT32)(pi->y % (OPJ_INT32)pi->dy))) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; + pi->x += (OPJ_INT32)(pi->dx - (OPJ_UINT32)(pi->x % (OPJ_INT32)pi->dx))) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + for (pi->resno = pi->poc.resno0; + pi->resno < opj_uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + OPJ_UINT32 levelno; + OPJ_INT32 trx0, try0; + OPJ_INT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_INT32 prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + /* Avoids division by zero */ + /* Relates to id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */ + /* of https://github.com/uclouvain/openjpeg/issues/938 */ + if (levelno >= 32 || + ((comp->dx << levelno) >> levelno) != comp->dx || + ((comp->dy << levelno) >> levelno) != comp->dy) { + continue; + } + if ((comp->dx << levelno) > INT_MAX || + (comp->dy << levelno) > INT_MAX) { + continue; + } + trx0 = opj_int_ceildiv(pi->tx0, (OPJ_INT32)(comp->dx << levelno)); + try0 = opj_int_ceildiv(pi->ty0, (OPJ_INT32)(comp->dy << levelno)); + trx1 = opj_int_ceildiv(pi->tx1, (OPJ_INT32)(comp->dx << levelno)); + try1 = opj_int_ceildiv(pi->ty1, (OPJ_INT32)(comp->dy << levelno)); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + + /* To avoid divisions by zero / undefined behaviour on shift */ + /* in below tests */ + /* Relates to id:000019,sig:08,src:001098,op:flip1,pos:49 */ + /* of https://github.com/uclouvain/openjpeg/issues/938 */ + if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || + rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + continue; + } + + /* See ISO-15441. B.12.1.4 Position-component-resolution level-layer progression */ + if (!((pi->y % (OPJ_INT32)(comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && + ((try0 << levelno) % (1 << rpy))))) { + continue; + } + if (!((pi->x % (OPJ_INT32)(comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && + ((trx0 << levelno) % (1 << rpx))))) { + continue; + } + + if ((res->pw == 0) || (res->ph == 0)) { + continue; + } + + if ((trx0 == trx1) || (try0 == try1)) { + continue; + } + + prci = opj_int_floordivpow2(opj_int_ceildiv(pi->x, + (OPJ_INT32)(comp->dx << levelno)), (OPJ_INT32)res->pdx) + - opj_int_floordivpow2(trx0, (OPJ_INT32)res->pdx); + prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, + (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) + - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); + if (pi->precno >= res->pw * res->ph) { + return OPJ_FALSE; + } + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_pi_emit_error(pi, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + } + + return OPJ_FALSE; } -static void opj_get_encoding_parameters( const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 p_tileno, - OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * p_ty1, - OPJ_UINT32 * p_dx_min, - OPJ_UINT32 * p_dy_min, - OPJ_UINT32 * p_max_prec, - OPJ_UINT32 * p_max_res ) +static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) { - /* loop */ - OPJ_UINT32 compno, resno; - /* pointers */ - const opj_tcp_t *l_tcp = 00; - const opj_tccp_t * l_tccp = 00; - const opj_image_comp_t * l_img_comp = 00; - - /* position in x and y of tile */ - OPJ_UINT32 p, q; - - /* preconditions */ - assert(p_cp != 00); - assert(p_image != 00); - assert(p_tileno < p_cp->tw * p_cp->th); - - /* initializations */ - l_tcp = &p_cp->tcps [p_tileno]; - l_img_comp = p_image->comps; - l_tccp = l_tcp->tccps; - - /* here calculation of tx0, tx1, ty0, ty1, maxprec, dx and dy */ - p = p_tileno % p_cp->tw; - q = p_tileno / p_cp->tw; - - /* find extent of tile */ - *p_tx0 = opj_int_max((OPJ_INT32)(p_cp->tx0 + p * p_cp->tdx), (OPJ_INT32)p_image->x0); - *p_tx1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + (p + 1) * p_cp->tdx), (OPJ_INT32)p_image->x1); - *p_ty0 = opj_int_max((OPJ_INT32)(p_cp->ty0 + q * p_cp->tdy), (OPJ_INT32)p_image->y0); - *p_ty1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + (q + 1) * p_cp->tdy), (OPJ_INT32)p_image->y1); - - /* max precision is 0 (can only grow) */ - *p_max_prec = 0; - *p_max_res = 0; - - /* take the largest value for dx_min and dy_min */ - *p_dx_min = 0x7fffffff; - *p_dy_min = 0x7fffffff; - - for (compno = 0; compno < p_image->numcomps; ++compno) { - /* arithmetic variables to calculate */ - OPJ_UINT32 l_level_no; - OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; - OPJ_INT32 l_px0, l_py0, l_px1, py1; - OPJ_UINT32 l_pdx, l_pdy; - OPJ_UINT32 l_pw, l_ph; - OPJ_UINT32 l_product; - OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; - - l_tcx0 = opj_int_ceildiv(*p_tx0, (OPJ_INT32)l_img_comp->dx); - l_tcy0 = opj_int_ceildiv(*p_ty0, (OPJ_INT32)l_img_comp->dy); - l_tcx1 = opj_int_ceildiv(*p_tx1, (OPJ_INT32)l_img_comp->dx); - l_tcy1 = opj_int_ceildiv(*p_ty1, (OPJ_INT32)l_img_comp->dy); - - if (l_tccp->numresolutions > *p_max_res) { - *p_max_res = l_tccp->numresolutions; - } - - /* use custom size for precincts */ - for (resno = 0; resno < l_tccp->numresolutions; ++resno) { - OPJ_UINT32 l_dx, l_dy; - - /* precinct width and height */ - l_pdx = l_tccp->prcw[resno]; - l_pdy = l_tccp->prch[resno]; - - l_dx = l_img_comp->dx * (1u << (l_pdx + l_tccp->numresolutions - 1 - resno)); - l_dy = l_img_comp->dy * (1u << (l_pdy + l_tccp->numresolutions - 1 - resno)); - - /* take the minimum size for dx for each comp and resolution */ - *p_dx_min = opj_uint_min(*p_dx_min, l_dx); - *p_dy_min = opj_uint_min(*p_dy_min, l_dy); - - /* various calculations of extents */ - l_level_no = l_tccp->numresolutions - 1 - resno; - - l_rx0 = opj_int_ceildivpow2(l_tcx0, (OPJ_INT32)l_level_no); - l_ry0 = opj_int_ceildivpow2(l_tcy0, (OPJ_INT32)l_level_no); - l_rx1 = opj_int_ceildivpow2(l_tcx1, (OPJ_INT32)l_level_no); - l_ry1 = opj_int_ceildivpow2(l_tcy1, (OPJ_INT32)l_level_no); - - l_px0 = opj_int_floordivpow2(l_rx0, (OPJ_INT32)l_pdx) << l_pdx; - l_py0 = opj_int_floordivpow2(l_ry0, (OPJ_INT32)l_pdy) << l_pdy; - l_px1 = opj_int_ceildivpow2(l_rx1, (OPJ_INT32)l_pdx) << l_pdx; - - py1 = opj_int_ceildivpow2(l_ry1, (OPJ_INT32)l_pdy) << l_pdy; - - l_pw = (l_rx0==l_rx1)?0:(OPJ_UINT32)((l_px1 - l_px0) >> l_pdx); - l_ph = (l_ry0==l_ry1)?0:(OPJ_UINT32)((py1 - l_py0) >> l_pdy); - - l_product = l_pw * l_ph; - - /* update precision */ - if (l_product > *p_max_prec) { - *p_max_prec = l_product; - } - } - ++l_img_comp; - ++l_tccp; - } + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + OPJ_UINT32 resno; + comp = &pi->comps[pi->compno]; + pi->dx = 0; + pi->dy = 0; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + if (res->pdx + comp->numresolutions - 1 - resno < 32 && + comp->dx <= UINT_MAX / (1u << (res->pdx + comp->numresolutions - 1 - resno))) { + dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); + } + if (res->pdy + comp->numresolutions - 1 - resno < 32 && + comp->dy <= UINT_MAX / (1u << (res->pdy + comp->numresolutions - 1 - resno))) { + dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); + } + } + if (pi->dx == 0 || pi->dy == 0) { + return OPJ_FALSE; + } + if (!pi->tp_on) { + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; + pi->y += (OPJ_INT32)(pi->dy - (OPJ_UINT32)(pi->y % (OPJ_INT32)pi->dy))) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; + pi->x += (OPJ_INT32)(pi->dx - (OPJ_UINT32)(pi->x % (OPJ_INT32)pi->dx))) { + for (pi->resno = pi->poc.resno0; + pi->resno < opj_uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + OPJ_UINT32 levelno; + OPJ_INT32 trx0, try0; + OPJ_INT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_INT32 prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + /* Avoids division by zero on id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */ + /* of https://github.com/uclouvain/openjpeg/issues/938 */ + if (levelno >= 32 || + ((comp->dx << levelno) >> levelno) != comp->dx || + ((comp->dy << levelno) >> levelno) != comp->dy) { + continue; + } + if ((comp->dx << levelno) > INT_MAX || + (comp->dy << levelno) > INT_MAX) { + continue; + } + trx0 = opj_int_ceildiv(pi->tx0, (OPJ_INT32)(comp->dx << levelno)); + try0 = opj_int_ceildiv(pi->ty0, (OPJ_INT32)(comp->dy << levelno)); + trx1 = opj_int_ceildiv(pi->tx1, (OPJ_INT32)(comp->dx << levelno)); + try1 = opj_int_ceildiv(pi->ty1, (OPJ_INT32)(comp->dy << levelno)); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + + /* To avoid divisions by zero / undefined behaviour on shift */ + /* in below tests */ + /* Fixes reading id:000019,sig:08,src:001098,op:flip1,pos:49 */ + /* of https://github.com/uclouvain/openjpeg/issues/938 */ + if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || + rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + continue; + } + + /* See ISO-15441. B.12.1.5 Component-position-resolution level-layer progression */ + if (!((pi->y % (OPJ_INT32)(comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && + ((try0 << levelno) % (1 << rpy))))) { + continue; + } + if (!((pi->x % (OPJ_INT32)(comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && + ((trx0 << levelno) % (1 << rpx))))) { + continue; + } + + if ((res->pw == 0) || (res->ph == 0)) { + continue; + } + + if ((trx0 == trx1) || (try0 == try1)) { + continue; + } + + prci = opj_int_floordivpow2(opj_int_ceildiv(pi->x, + (OPJ_INT32)(comp->dx << levelno)), (OPJ_INT32)res->pdx) + - opj_int_floordivpow2(trx0, (OPJ_INT32)res->pdx); + prcj = opj_int_floordivpow2(opj_int_ceildiv(pi->y, + (OPJ_INT32)(comp->dy << levelno)), (OPJ_INT32)res->pdy) + - opj_int_floordivpow2(try0, (OPJ_INT32)res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * (OPJ_INT32)res->pw); + if (pi->precno >= res->pw * res->ph) { + return OPJ_FALSE; + } + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_pi_emit_error(pi, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + } + + return OPJ_FALSE; } - -static void opj_get_all_encoding_parameters( const opj_image_t *p_image, +static void opj_get_encoding_parameters(const opj_image_t *p_image, const opj_cp_t *p_cp, - OPJ_UINT32 tileno, + OPJ_UINT32 p_tileno, OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * p_ty1, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, OPJ_UINT32 * p_dx_min, OPJ_UINT32 * p_dy_min, OPJ_UINT32 * p_max_prec, - OPJ_UINT32 * p_max_res, - OPJ_UINT32 ** p_resolutions ) + OPJ_UINT32 * p_max_res) { - /* loop*/ - OPJ_UINT32 compno, resno; - - /* pointers*/ - const opj_tcp_t *tcp = 00; - const opj_tccp_t * l_tccp = 00; - const opj_image_comp_t * l_img_comp = 00; - - /* to store l_dx, l_dy, w and h for each resolution and component.*/ - OPJ_UINT32 * lResolutionPtr; - - /* position in x and y of tile*/ - OPJ_UINT32 p, q; - - /* non-corrected (in regard to image offset) tile offset */ - OPJ_UINT32 l_tx0, l_ty0; - - /* preconditions in debug*/ - assert(p_cp != 00); - assert(p_image != 00); - assert(tileno < p_cp->tw * p_cp->th); - - /* initializations*/ - tcp = &p_cp->tcps [tileno]; - l_tccp = tcp->tccps; - l_img_comp = p_image->comps; - - /* position in x and y of tile*/ - p = tileno % p_cp->tw; - q = tileno / p_cp->tw; - - /* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */ - l_tx0 = p_cp->tx0 + p * p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */ - *p_tx0 = (OPJ_INT32)opj_uint_max(l_tx0, p_image->x0); - *p_tx1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1); - l_ty0 = p_cp->ty0 + q * p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */ - *p_ty0 = (OPJ_INT32)opj_uint_max(l_ty0, p_image->y0); - *p_ty1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1); - - /* max precision and resolution is 0 (can only grow)*/ - *p_max_prec = 0; - *p_max_res = 0; - - /* take the largest value for dx_min and dy_min*/ - *p_dx_min = 0x7fffffff; - *p_dy_min = 0x7fffffff; - - for (compno = 0; compno < p_image->numcomps; ++compno) { - /* aritmetic variables to calculate*/ - OPJ_UINT32 l_level_no; - OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; - OPJ_INT32 l_px0, l_py0, l_px1, py1; - OPJ_UINT32 l_product; - OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; - OPJ_UINT32 l_pdx, l_pdy , l_pw , l_ph; - - lResolutionPtr = p_resolutions[compno]; - - l_tcx0 = opj_int_ceildiv(*p_tx0, (OPJ_INT32)l_img_comp->dx); - l_tcy0 = opj_int_ceildiv(*p_ty0, (OPJ_INT32)l_img_comp->dy); - l_tcx1 = opj_int_ceildiv(*p_tx1, (OPJ_INT32)l_img_comp->dx); - l_tcy1 = opj_int_ceildiv(*p_ty1, (OPJ_INT32)l_img_comp->dy); - - if (l_tccp->numresolutions > *p_max_res) { - *p_max_res = l_tccp->numresolutions; - } - - /* use custom size for precincts*/ - l_level_no = l_tccp->numresolutions - 1; - for (resno = 0; resno < l_tccp->numresolutions; ++resno) { - OPJ_UINT32 l_dx, l_dy; - - /* precinct width and height*/ - l_pdx = l_tccp->prcw[resno]; - l_pdy = l_tccp->prch[resno]; - *lResolutionPtr++ = l_pdx; - *lResolutionPtr++ = l_pdy; - l_dx = l_img_comp->dx * (1u << (l_pdx + l_level_no)); - l_dy = l_img_comp->dy * (1u << (l_pdy + l_level_no)); - /* take the minimum size for l_dx for each comp and resolution*/ - *p_dx_min = (OPJ_UINT32)opj_int_min((OPJ_INT32)*p_dx_min, (OPJ_INT32)l_dx); - *p_dy_min = (OPJ_UINT32)opj_int_min((OPJ_INT32)*p_dy_min, (OPJ_INT32)l_dy); - - /* various calculations of extents*/ - l_rx0 = opj_int_ceildivpow2(l_tcx0, (OPJ_INT32)l_level_no); - l_ry0 = opj_int_ceildivpow2(l_tcy0, (OPJ_INT32)l_level_no); - l_rx1 = opj_int_ceildivpow2(l_tcx1, (OPJ_INT32)l_level_no); - l_ry1 = opj_int_ceildivpow2(l_tcy1, (OPJ_INT32)l_level_no); - l_px0 = opj_int_floordivpow2(l_rx0, (OPJ_INT32)l_pdx) << l_pdx; - l_py0 = opj_int_floordivpow2(l_ry0, (OPJ_INT32)l_pdy) << l_pdy; - l_px1 = opj_int_ceildivpow2(l_rx1, (OPJ_INT32)l_pdx) << l_pdx; - py1 = opj_int_ceildivpow2(l_ry1, (OPJ_INT32)l_pdy) << l_pdy; - l_pw = (l_rx0==l_rx1)?0:(OPJ_UINT32)((l_px1 - l_px0) >> l_pdx); - l_ph = (l_ry0==l_ry1)?0:(OPJ_UINT32)((py1 - l_py0) >> l_pdy); - *lResolutionPtr++ = l_pw; - *lResolutionPtr++ = l_ph; - l_product = l_pw * l_ph; - + /* loop */ + OPJ_UINT32 compno, resno; + /* pointers */ + const opj_tcp_t *l_tcp = 00; + const opj_tccp_t * l_tccp = 00; + const opj_image_comp_t * l_img_comp = 00; + + /* position in x and y of tile */ + OPJ_UINT32 p, q; + + /* preconditions */ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + /* initializations */ + l_tcp = &p_cp->tcps [p_tileno]; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + /* here calculation of tx0, tx1, ty0, ty1, maxprec, dx and dy */ + p = p_tileno % p_cp->tw; + q = p_tileno / p_cp->tw; + + /* find extent of tile */ + *p_tx0 = opj_int_max((OPJ_INT32)(p_cp->tx0 + p * p_cp->tdx), + (OPJ_INT32)p_image->x0); + *p_tx1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + (p + 1) * p_cp->tdx), + (OPJ_INT32)p_image->x1); + *p_ty0 = opj_int_max((OPJ_INT32)(p_cp->ty0 + q * p_cp->tdy), + (OPJ_INT32)p_image->y0); + *p_ty1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + (q + 1) * p_cp->tdy), + (OPJ_INT32)p_image->y1); + + /* max precision is 0 (can only grow) */ + *p_max_prec = 0; + *p_max_res = 0; + + /* take the largest value for dx_min and dy_min */ + *p_dx_min = 0x7fffffff; + *p_dy_min = 0x7fffffff; + + for (compno = 0; compno < p_image->numcomps; ++compno) { + /* arithmetic variables to calculate */ + OPJ_UINT32 l_level_no; + OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; + OPJ_INT32 l_px0, l_py0, l_px1, py1; + OPJ_UINT32 l_pdx, l_pdy; + OPJ_UINT32 l_pw, l_ph; + OPJ_UINT32 l_product; + OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; + + l_tcx0 = opj_int_ceildiv(*p_tx0, (OPJ_INT32)l_img_comp->dx); + l_tcy0 = opj_int_ceildiv(*p_ty0, (OPJ_INT32)l_img_comp->dy); + l_tcx1 = opj_int_ceildiv(*p_tx1, (OPJ_INT32)l_img_comp->dx); + l_tcy1 = opj_int_ceildiv(*p_ty1, (OPJ_INT32)l_img_comp->dy); + + if (l_tccp->numresolutions > *p_max_res) { + *p_max_res = l_tccp->numresolutions; + } + + /* use custom size for precincts */ + for (resno = 0; resno < l_tccp->numresolutions; ++resno) { + OPJ_UINT32 l_dx, l_dy; + + /* precinct width and height */ + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + + l_dx = l_img_comp->dx * (1u << (l_pdx + l_tccp->numresolutions - 1 - resno)); + l_dy = l_img_comp->dy * (1u << (l_pdy + l_tccp->numresolutions - 1 - resno)); + + /* take the minimum size for dx for each comp and resolution */ + *p_dx_min = opj_uint_min(*p_dx_min, l_dx); + *p_dy_min = opj_uint_min(*p_dy_min, l_dy); + + /* various calculations of extents */ + l_level_no = l_tccp->numresolutions - 1 - resno; + + l_rx0 = opj_int_ceildivpow2(l_tcx0, (OPJ_INT32)l_level_no); + l_ry0 = opj_int_ceildivpow2(l_tcy0, (OPJ_INT32)l_level_no); + l_rx1 = opj_int_ceildivpow2(l_tcx1, (OPJ_INT32)l_level_no); + l_ry1 = opj_int_ceildivpow2(l_tcy1, (OPJ_INT32)l_level_no); + + l_px0 = opj_int_floordivpow2(l_rx0, (OPJ_INT32)l_pdx) << l_pdx; + l_py0 = opj_int_floordivpow2(l_ry0, (OPJ_INT32)l_pdy) << l_pdy; + l_px1 = opj_int_ceildivpow2(l_rx1, (OPJ_INT32)l_pdx) << l_pdx; + + py1 = opj_int_ceildivpow2(l_ry1, (OPJ_INT32)l_pdy) << l_pdy; + + l_pw = (l_rx0 == l_rx1) ? 0 : (OPJ_UINT32)((l_px1 - l_px0) >> l_pdx); + l_ph = (l_ry0 == l_ry1) ? 0 : (OPJ_UINT32)((py1 - l_py0) >> l_pdy); + + l_product = l_pw * l_ph; + + /* update precision */ + if (l_product > *p_max_prec) { + *p_max_prec = l_product; + } + } + ++l_img_comp; + ++l_tccp; + } +} + + +static void opj_get_all_encoding_parameters(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_INT32 * p_tx0, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res, + OPJ_UINT32 ** p_resolutions) +{ + /* loop*/ + OPJ_UINT32 compno, resno; + + /* pointers*/ + const opj_tcp_t *tcp = 00; + const opj_tccp_t * l_tccp = 00; + const opj_image_comp_t * l_img_comp = 00; + + /* to store l_dx, l_dy, w and h for each resolution and component.*/ + OPJ_UINT32 * lResolutionPtr; + + /* position in x and y of tile*/ + OPJ_UINT32 p, q; + + /* non-corrected (in regard to image offset) tile offset */ + OPJ_UINT32 l_tx0, l_ty0; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_image != 00); + assert(tileno < p_cp->tw * p_cp->th); + + /* initializations*/ + tcp = &p_cp->tcps [tileno]; + l_tccp = tcp->tccps; + l_img_comp = p_image->comps; + + /* position in x and y of tile*/ + p = tileno % p_cp->tw; + q = tileno / p_cp->tw; + + /* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */ + l_tx0 = p_cp->tx0 + p * + p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */ + *p_tx0 = (OPJ_INT32)opj_uint_max(l_tx0, p_image->x0); + *p_tx1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1); + l_ty0 = p_cp->ty0 + q * + p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */ + *p_ty0 = (OPJ_INT32)opj_uint_max(l_ty0, p_image->y0); + *p_ty1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1); + + /* max precision and resolution is 0 (can only grow)*/ + *p_max_prec = 0; + *p_max_res = 0; + + /* take the largest value for dx_min and dy_min*/ + *p_dx_min = 0x7fffffff; + *p_dy_min = 0x7fffffff; + + for (compno = 0; compno < p_image->numcomps; ++compno) { + /* aritmetic variables to calculate*/ + OPJ_UINT32 l_level_no; + OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; + OPJ_INT32 l_px0, l_py0, l_px1, py1; + OPJ_UINT32 l_product; + OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; + OPJ_UINT32 l_pdx, l_pdy, l_pw, l_ph; + + lResolutionPtr = p_resolutions[compno]; + + l_tcx0 = opj_int_ceildiv(*p_tx0, (OPJ_INT32)l_img_comp->dx); + l_tcy0 = opj_int_ceildiv(*p_ty0, (OPJ_INT32)l_img_comp->dy); + l_tcx1 = opj_int_ceildiv(*p_tx1, (OPJ_INT32)l_img_comp->dx); + l_tcy1 = opj_int_ceildiv(*p_ty1, (OPJ_INT32)l_img_comp->dy); + + if (l_tccp->numresolutions > *p_max_res) { + *p_max_res = l_tccp->numresolutions; + } + + /* use custom size for precincts*/ + l_level_no = l_tccp->numresolutions; + for (resno = 0; resno < l_tccp->numresolutions; ++resno) { + OPJ_UINT32 l_dx, l_dy; + + --l_level_no; + + /* precinct width and height*/ + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + *lResolutionPtr++ = l_pdx; + *lResolutionPtr++ = l_pdy; + if (l_pdx + l_level_no < 32 && + l_img_comp->dx <= UINT_MAX / (1u << (l_pdx + l_level_no))) { + l_dx = l_img_comp->dx * (1u << (l_pdx + l_level_no)); + /* take the minimum size for l_dx for each comp and resolution*/ + *p_dx_min = (OPJ_UINT32)opj_int_min((OPJ_INT32) * p_dx_min, (OPJ_INT32)l_dx); + } + if (l_pdy + l_level_no < 32 && + l_img_comp->dy <= UINT_MAX / (1u << (l_pdy + l_level_no))) { + l_dy = l_img_comp->dy * (1u << (l_pdy + l_level_no)); + *p_dy_min = (OPJ_UINT32)opj_int_min((OPJ_INT32) * p_dy_min, (OPJ_INT32)l_dy); + } + + /* various calculations of extents*/ + l_rx0 = opj_int_ceildivpow2(l_tcx0, (OPJ_INT32)l_level_no); + l_ry0 = opj_int_ceildivpow2(l_tcy0, (OPJ_INT32)l_level_no); + l_rx1 = opj_int_ceildivpow2(l_tcx1, (OPJ_INT32)l_level_no); + l_ry1 = opj_int_ceildivpow2(l_tcy1, (OPJ_INT32)l_level_no); + l_px0 = opj_int_floordivpow2(l_rx0, (OPJ_INT32)l_pdx) << l_pdx; + l_py0 = opj_int_floordivpow2(l_ry0, (OPJ_INT32)l_pdy) << l_pdy; + l_px1 = opj_int_ceildivpow2(l_rx1, (OPJ_INT32)l_pdx) << l_pdx; + py1 = opj_int_ceildivpow2(l_ry1, (OPJ_INT32)l_pdy) << l_pdy; + l_pw = (l_rx0 == l_rx1) ? 0 : (OPJ_UINT32)((l_px1 - l_px0) >> l_pdx); + l_ph = (l_ry0 == l_ry1) ? 0 : (OPJ_UINT32)((py1 - l_py0) >> l_pdy); + *lResolutionPtr++ = l_pw; + *lResolutionPtr++ = l_ph; + l_product = l_pw * l_ph; + /* update precision*/ - if (l_product > *p_max_prec) { - *p_max_prec = l_product; - } - - --l_level_no; - } - ++l_tccp; - ++l_img_comp; - } + if (l_product > *p_max_prec) { + *p_max_prec = l_product; + } + + } + ++l_tccp; + ++l_img_comp; + } } -static opj_pi_iterator_t * opj_pi_create( const opj_image_t *image, - const opj_cp_t *cp, - OPJ_UINT32 tileno ) +static opj_pi_iterator_t * opj_pi_create(const opj_image_t *image, + const opj_cp_t *cp, + OPJ_UINT32 tileno) { - /* loop*/ - OPJ_UINT32 pino, compno; - /* number of poc in the p_pi*/ - OPJ_UINT32 l_poc_bound; - - /* pointers to tile coding parameters and components.*/ - opj_pi_iterator_t *l_pi = 00; - opj_tcp_t *tcp = 00; - const opj_tccp_t *tccp = 00; - - /* current packet iterator being allocated*/ - opj_pi_iterator_t *l_current_pi = 00; - - /* preconditions in debug*/ - assert(cp != 00); - assert(image != 00); - assert(tileno < cp->tw * cp->th); - - /* initializations*/ - tcp = &cp->tcps[tileno]; - l_poc_bound = tcp->numpocs+1; - - /* memory allocations*/ - l_pi = (opj_pi_iterator_t*) opj_calloc((l_poc_bound), sizeof(opj_pi_iterator_t)); - if (!l_pi) { - return NULL; - } - - l_current_pi = l_pi; - for (pino = 0; pino < l_poc_bound ; ++pino) { - - l_current_pi->comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t)); - if (! l_current_pi->comps) { - opj_pi_destroy(l_pi, l_poc_bound); - return NULL; - } - - l_current_pi->numcomps = image->numcomps; - - for (compno = 0; compno < image->numcomps; ++compno) { - opj_pi_comp_t *comp = &l_current_pi->comps[compno]; - - tccp = &tcp->tccps[compno]; - - comp->resolutions = (opj_pi_resolution_t*) opj_calloc(tccp->numresolutions, sizeof(opj_pi_resolution_t)); - if (!comp->resolutions) { - opj_pi_destroy(l_pi, l_poc_bound); - return 00; - } - - comp->numresolutions = tccp->numresolutions; - } - ++l_current_pi; - } - return l_pi; + /* loop*/ + OPJ_UINT32 pino, compno; + /* number of poc in the p_pi*/ + OPJ_UINT32 l_poc_bound; + + /* pointers to tile coding parameters and components.*/ + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *tcp = 00; + const opj_tccp_t *tccp = 00; + + /* current packet iterator being allocated*/ + opj_pi_iterator_t *l_current_pi = 00; + + /* preconditions in debug*/ + assert(cp != 00); + assert(image != 00); + assert(tileno < cp->tw * cp->th); + + /* initializations*/ + tcp = &cp->tcps[tileno]; + l_poc_bound = tcp->numpocs + 1; + + /* memory allocations*/ + l_pi = (opj_pi_iterator_t*) opj_calloc((l_poc_bound), + sizeof(opj_pi_iterator_t)); + if (!l_pi) { + return NULL; + } + + l_current_pi = l_pi; + for (pino = 0; pino < l_poc_bound ; ++pino) { + + l_current_pi->comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, + sizeof(opj_pi_comp_t)); + if (! l_current_pi->comps) { + opj_pi_destroy(l_pi, l_poc_bound); + return NULL; + } + + l_current_pi->numcomps = image->numcomps; + + for (compno = 0; compno < image->numcomps; ++compno) { + opj_pi_comp_t *comp = &l_current_pi->comps[compno]; + + tccp = &tcp->tccps[compno]; + + comp->resolutions = (opj_pi_resolution_t*) opj_calloc(tccp->numresolutions, + sizeof(opj_pi_resolution_t)); + if (!comp->resolutions) { + opj_pi_destroy(l_pi, l_poc_bound); + return 00; + } + + comp->numresolutions = tccp->numresolutions; + } + ++l_current_pi; + } + return l_pi; } -static void opj_pi_update_encode_poc_and_final ( opj_cp_t *p_cp, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 p_ty1, - OPJ_UINT32 p_max_prec, - OPJ_UINT32 p_max_res, - OPJ_UINT32 p_dx_min, - OPJ_UINT32 p_dy_min) +static void opj_pi_update_encode_poc_and_final(opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min) { - /* loop*/ - OPJ_UINT32 pino; - /* tile coding parameter*/ - opj_tcp_t *l_tcp = 00; - /* current poc being updated*/ - opj_poc_t * l_current_poc = 00; + /* loop*/ + OPJ_UINT32 pino; + /* tile coding parameter*/ + opj_tcp_t *l_tcp = 00; + /* current poc being updated*/ + opj_poc_t * l_current_poc = 00; - /* number of pocs*/ - OPJ_UINT32 l_poc_bound; + /* number of pocs*/ + OPJ_UINT32 l_poc_bound; OPJ_ARG_NOT_USED(p_max_res); - /* preconditions in debug*/ - assert(p_cp != 00); - assert(p_tileno < p_cp->tw * p_cp->th); - - /* initializations*/ - l_tcp = &p_cp->tcps [p_tileno]; - /* number of iterations in the loop */ - l_poc_bound = l_tcp->numpocs+1; - - /* start at first element, and to make sure the compiler will not make a calculation each time in the loop - store a pointer to the current element to modify rather than l_tcp->pocs[i]*/ - l_current_poc = l_tcp->pocs; - - l_current_poc->compS = l_current_poc->compno0; - l_current_poc->compE = l_current_poc->compno1; - l_current_poc->resS = l_current_poc->resno0; - l_current_poc->resE = l_current_poc->resno1; - l_current_poc->layE = l_current_poc->layno1; - - /* special treatment for the first element*/ - l_current_poc->layS = 0; - l_current_poc->prg = l_current_poc->prg1; - l_current_poc->prcS = 0; - - l_current_poc->prcE = p_max_prec; - l_current_poc->txS = (OPJ_UINT32)p_tx0; - l_current_poc->txE = (OPJ_UINT32)p_tx1; - l_current_poc->tyS = (OPJ_UINT32)p_ty0; - l_current_poc->tyE = (OPJ_UINT32)p_ty1; - l_current_poc->dx = p_dx_min; - l_current_poc->dy = p_dy_min; - - ++ l_current_poc; - for (pino = 1;pino < l_poc_bound ; ++pino) { - l_current_poc->compS = l_current_poc->compno0; - l_current_poc->compE= l_current_poc->compno1; - l_current_poc->resS = l_current_poc->resno0; - l_current_poc->resE = l_current_poc->resno1; - l_current_poc->layE = l_current_poc->layno1; - l_current_poc->prg = l_current_poc->prg1; - l_current_poc->prcS = 0; - /* special treatment here different from the first element*/ - l_current_poc->layS = (l_current_poc->layE > (l_current_poc-1)->layE) ? l_current_poc->layE : 0; - - l_current_poc->prcE = p_max_prec; - l_current_poc->txS = (OPJ_UINT32)p_tx0; - l_current_poc->txE = (OPJ_UINT32)p_tx1; - l_current_poc->tyS = (OPJ_UINT32)p_ty0; - l_current_poc->tyE = (OPJ_UINT32)p_ty1; - l_current_poc->dx = p_dx_min; - l_current_poc->dy = p_dy_min; - ++ l_current_poc; - } + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + /* initializations*/ + l_tcp = &p_cp->tcps [p_tileno]; + /* number of iterations in the loop */ + l_poc_bound = l_tcp->numpocs + 1; + + /* start at first element, and to make sure the compiler will not make a calculation each time in the loop + store a pointer to the current element to modify rather than l_tcp->pocs[i]*/ + l_current_poc = l_tcp->pocs; + + l_current_poc->compS = l_current_poc->compno0; + l_current_poc->compE = l_current_poc->compno1; + l_current_poc->resS = l_current_poc->resno0; + l_current_poc->resE = l_current_poc->resno1; + l_current_poc->layE = l_current_poc->layno1; + + /* special treatment for the first element*/ + l_current_poc->layS = 0; + l_current_poc->prg = l_current_poc->prg1; + l_current_poc->prcS = 0; + + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = (OPJ_UINT32)p_tx0; + l_current_poc->txE = (OPJ_UINT32)p_tx1; + l_current_poc->tyS = (OPJ_UINT32)p_ty0; + l_current_poc->tyE = (OPJ_UINT32)p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + + ++ l_current_poc; + for (pino = 1; pino < l_poc_bound ; ++pino) { + l_current_poc->compS = l_current_poc->compno0; + l_current_poc->compE = l_current_poc->compno1; + l_current_poc->resS = l_current_poc->resno0; + l_current_poc->resE = l_current_poc->resno1; + l_current_poc->layE = l_current_poc->layno1; + l_current_poc->prg = l_current_poc->prg1; + l_current_poc->prcS = 0; + /* special treatment here different from the first element*/ + l_current_poc->layS = (l_current_poc->layE > (l_current_poc - 1)->layE) ? + l_current_poc->layE : 0; + + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = (OPJ_UINT32)p_tx0; + l_current_poc->txE = (OPJ_UINT32)p_tx1; + l_current_poc->tyS = (OPJ_UINT32)p_ty0; + l_current_poc->tyE = (OPJ_UINT32)p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + ++ l_current_poc; + } } -static void opj_pi_update_encode_not_poc ( opj_cp_t *p_cp, - OPJ_UINT32 p_num_comps, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 p_ty1, - OPJ_UINT32 p_max_prec, - OPJ_UINT32 p_max_res, - OPJ_UINT32 p_dx_min, - OPJ_UINT32 p_dy_min) +static void opj_pi_update_encode_not_poc(opj_cp_t *p_cp, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min) { - /* loop*/ - OPJ_UINT32 pino; - /* tile coding parameter*/ - opj_tcp_t *l_tcp = 00; - /* current poc being updated*/ - opj_poc_t * l_current_poc = 00; - /* number of pocs*/ - OPJ_UINT32 l_poc_bound; - - /* preconditions in debug*/ - assert(p_cp != 00); - assert(p_tileno < p_cp->tw * p_cp->th); - - /* initializations*/ - l_tcp = &p_cp->tcps [p_tileno]; - - /* number of iterations in the loop */ - l_poc_bound = l_tcp->numpocs+1; - - /* start at first element, and to make sure the compiler will not make a calculation each time in the loop - store a pointer to the current element to modify rather than l_tcp->pocs[i]*/ - l_current_poc = l_tcp->pocs; - - for (pino = 0; pino < l_poc_bound ; ++pino) { - l_current_poc->compS = 0; - l_current_poc->compE = p_num_comps;/*p_image->numcomps;*/ - l_current_poc->resS = 0; - l_current_poc->resE = p_max_res; - l_current_poc->layS = 0; - l_current_poc->layE = l_tcp->numlayers; - l_current_poc->prg = l_tcp->prg; - l_current_poc->prcS = 0; - l_current_poc->prcE = p_max_prec; - l_current_poc->txS = (OPJ_UINT32)p_tx0; - l_current_poc->txE = (OPJ_UINT32)p_tx1; - l_current_poc->tyS = (OPJ_UINT32)p_ty0; - l_current_poc->tyE = (OPJ_UINT32)p_ty1; - l_current_poc->dx = p_dx_min; - l_current_poc->dy = p_dy_min; - ++ l_current_poc; - } + /* loop*/ + OPJ_UINT32 pino; + /* tile coding parameter*/ + opj_tcp_t *l_tcp = 00; + /* current poc being updated*/ + opj_poc_t * l_current_poc = 00; + /* number of pocs*/ + OPJ_UINT32 l_poc_bound; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + /* initializations*/ + l_tcp = &p_cp->tcps [p_tileno]; + + /* number of iterations in the loop */ + l_poc_bound = l_tcp->numpocs + 1; + + /* start at first element, and to make sure the compiler will not make a calculation each time in the loop + store a pointer to the current element to modify rather than l_tcp->pocs[i]*/ + l_current_poc = l_tcp->pocs; + + for (pino = 0; pino < l_poc_bound ; ++pino) { + l_current_poc->compS = 0; + l_current_poc->compE = p_num_comps;/*p_image->numcomps;*/ + l_current_poc->resS = 0; + l_current_poc->resE = p_max_res; + l_current_poc->layS = 0; + l_current_poc->layE = l_tcp->numlayers; + l_current_poc->prg = l_tcp->prg; + l_current_poc->prcS = 0; + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = (OPJ_UINT32)p_tx0; + l_current_poc->txE = (OPJ_UINT32)p_tx1; + l_current_poc->tyS = (OPJ_UINT32)p_ty0; + l_current_poc->tyE = (OPJ_UINT32)p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + ++ l_current_poc; + } } -static void opj_pi_update_decode_poc (opj_pi_iterator_t * p_pi, - opj_tcp_t * p_tcp, - OPJ_UINT32 p_max_precision, - OPJ_UINT32 p_max_res) +static void opj_pi_update_decode_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res) { - /* loop*/ - OPJ_UINT32 pino; + /* loop*/ + OPJ_UINT32 pino; - /* encoding prameters to set*/ - OPJ_UINT32 l_bound; + /* encoding prameters to set*/ + OPJ_UINT32 l_bound; - opj_pi_iterator_t * l_current_pi = 00; - opj_poc_t* l_current_poc = 0; + opj_pi_iterator_t * l_current_pi = 00; + opj_poc_t* l_current_poc = 0; OPJ_ARG_NOT_USED(p_max_res); - /* preconditions in debug*/ - assert(p_pi != 00); - assert(p_tcp != 00); - - /* initializations*/ - l_bound = p_tcp->numpocs+1; - l_current_pi = p_pi; - l_current_poc = p_tcp->pocs; - - for (pino = 0;pino<l_bound;++pino) { - l_current_pi->poc.prg = l_current_poc->prg; /* Progression Order #0 */ - l_current_pi->first = 1; - - l_current_pi->poc.resno0 = l_current_poc->resno0; /* Resolution Level Index #0 (Start) */ - l_current_pi->poc.compno0 = l_current_poc->compno0; /* Component Index #0 (Start) */ - l_current_pi->poc.layno0 = 0; - l_current_pi->poc.precno0 = 0; - l_current_pi->poc.resno1 = l_current_poc->resno1; /* Resolution Level Index #0 (End) */ - l_current_pi->poc.compno1 = l_current_poc->compno1; /* Component Index #0 (End) */ - l_current_pi->poc.layno1 = opj_uint_min(l_current_poc->layno1, p_tcp->numlayers); /* Layer Index #0 (End) */ - l_current_pi->poc.precno1 = p_max_precision; - ++l_current_pi; - ++l_current_poc; - } + /* preconditions in debug*/ + assert(p_pi != 00); + assert(p_tcp != 00); + + /* initializations*/ + l_bound = p_tcp->numpocs + 1; + l_current_pi = p_pi; + l_current_poc = p_tcp->pocs; + + for (pino = 0; pino < l_bound; ++pino) { + l_current_pi->poc.prg = l_current_poc->prg; /* Progression Order #0 */ + l_current_pi->first = 1; + + l_current_pi->poc.resno0 = + l_current_poc->resno0; /* Resolution Level Index #0 (Start) */ + l_current_pi->poc.compno0 = + l_current_poc->compno0; /* Component Index #0 (Start) */ + l_current_pi->poc.layno0 = 0; + l_current_pi->poc.precno0 = 0; + l_current_pi->poc.resno1 = + l_current_poc->resno1; /* Resolution Level Index #0 (End) */ + l_current_pi->poc.compno1 = + l_current_poc->compno1; /* Component Index #0 (End) */ + l_current_pi->poc.layno1 = opj_uint_min(l_current_poc->layno1, + p_tcp->numlayers); /* Layer Index #0 (End) */ + l_current_pi->poc.precno1 = p_max_precision; + ++l_current_pi; + ++l_current_poc; + } } -static void opj_pi_update_decode_not_poc (opj_pi_iterator_t * p_pi, - opj_tcp_t * p_tcp, - OPJ_UINT32 p_max_precision, - OPJ_UINT32 p_max_res) +static void opj_pi_update_decode_not_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res) { - /* loop*/ - OPJ_UINT32 pino; - - /* encoding prameters to set*/ - OPJ_UINT32 l_bound; - - opj_pi_iterator_t * l_current_pi = 00; - /* preconditions in debug*/ - assert(p_tcp != 00); - assert(p_pi != 00); - - /* initializations*/ - l_bound = p_tcp->numpocs+1; - l_current_pi = p_pi; - - for (pino = 0;pino<l_bound;++pino) { - l_current_pi->poc.prg = p_tcp->prg; - l_current_pi->first = 1; - l_current_pi->poc.resno0 = 0; - l_current_pi->poc.compno0 = 0; - l_current_pi->poc.layno0 = 0; - l_current_pi->poc.precno0 = 0; - l_current_pi->poc.resno1 = p_max_res; - l_current_pi->poc.compno1 = l_current_pi->numcomps; - l_current_pi->poc.layno1 = p_tcp->numlayers; - l_current_pi->poc.precno1 = p_max_precision; - ++l_current_pi; - } + /* loop*/ + OPJ_UINT32 pino; + + /* encoding prameters to set*/ + OPJ_UINT32 l_bound; + + opj_pi_iterator_t * l_current_pi = 00; + /* preconditions in debug*/ + assert(p_tcp != 00); + assert(p_pi != 00); + + /* initializations*/ + l_bound = p_tcp->numpocs + 1; + l_current_pi = p_pi; + + for (pino = 0; pino < l_bound; ++pino) { + l_current_pi->poc.prg = p_tcp->prg; + l_current_pi->first = 1; + l_current_pi->poc.resno0 = 0; + l_current_pi->poc.compno0 = 0; + l_current_pi->poc.layno0 = 0; + l_current_pi->poc.precno0 = 0; + l_current_pi->poc.resno1 = p_max_res; + l_current_pi->poc.compno1 = l_current_pi->numcomps; + l_current_pi->poc.layno1 = p_tcp->numlayers; + l_current_pi->poc.precno1 = p_max_precision; + ++l_current_pi; + } } -static OPJ_BOOL opj_pi_check_next_level( OPJ_INT32 pos, - opj_cp_t *cp, - OPJ_UINT32 tileno, - OPJ_UINT32 pino, - const OPJ_CHAR *prog) +static OPJ_BOOL opj_pi_check_next_level(OPJ_INT32 pos, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + const OPJ_CHAR *prog) { - OPJ_INT32 i; - opj_tcp_t *tcps =&cp->tcps[tileno]; - opj_poc_t *tcp = &tcps->pocs[pino]; - - if(pos>=0){ - for(i=pos;pos>=0;i--){ - switch(prog[i]){ - case 'R': - if(tcp->res_t==tcp->resE){ - if(opj_pi_check_next_level(pos-1,cp,tileno,pino,prog)){ - return OPJ_TRUE; - }else{ - return OPJ_FALSE; - } - }else{ - return OPJ_TRUE; - } - break; - case 'C': - if(tcp->comp_t==tcp->compE){ - if(opj_pi_check_next_level(pos-1,cp,tileno,pino,prog)){ - return OPJ_TRUE; - }else{ - return OPJ_FALSE; - } - }else{ - return OPJ_TRUE; - } - break; - case 'L': - if(tcp->lay_t==tcp->layE){ - if(opj_pi_check_next_level(pos-1,cp,tileno,pino,prog)){ - return OPJ_TRUE; - }else{ - return OPJ_FALSE; - } - }else{ - return OPJ_TRUE; - } - break; - case 'P': - switch(tcp->prg){ - case OPJ_LRCP: /* fall through */ - case OPJ_RLCP: - if(tcp->prc_t == tcp->prcE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - return OPJ_TRUE; - }else{ - return OPJ_FALSE; - } - }else{ - return OPJ_TRUE; - } - break; - default: - if(tcp->tx0_t == tcp->txE){ - /*TY*/ - if(tcp->ty0_t == tcp->tyE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - return OPJ_TRUE; - }else{ - return OPJ_FALSE; - } - }else{ - return OPJ_TRUE; - }/*TY*/ - }else{ - return OPJ_TRUE; - } - break; - }/*end case P*/ - }/*end switch*/ - }/*end for*/ - }/*end if*/ - return OPJ_FALSE; + OPJ_INT32 i; + opj_tcp_t *tcps = &cp->tcps[tileno]; + opj_poc_t *tcp = &tcps->pocs[pino]; + + if (pos >= 0) { + for (i = pos; pos >= 0; i--) { + switch (prog[i]) { + case 'R': + if (tcp->res_t == tcp->resE) { + if (opj_pi_check_next_level(pos - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + case 'C': + if (tcp->comp_t == tcp->compE) { + if (opj_pi_check_next_level(pos - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + case 'L': + if (tcp->lay_t == tcp->layE) { + if (opj_pi_check_next_level(pos - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: /* fall through */ + case OPJ_RLCP: + if (tcp->prc_t == tcp->prcE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + default: + if (tcp->tx0_t == tcp->txE) { + /*TY*/ + if (tcp->ty0_t == tcp->tyE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + }/*TY*/ + } else { + return OPJ_TRUE; + } + break; + }/*end case P*/ + }/*end switch*/ + }/*end for*/ + }/*end if*/ + return OPJ_FALSE; } @@ -1162,732 +1357,739 @@ static OPJ_BOOL opj_pi_check_next_level( OPJ_INT32 pos, ========================================================== */ opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image, - opj_cp_t *p_cp, - OPJ_UINT32 p_tile_no) + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no) { - /* loop */ - OPJ_UINT32 pino; - OPJ_UINT32 compno, resno; - - /* to store w, h, dx and dy fro all components and resolutions */ - OPJ_UINT32 * l_tmp_data; - OPJ_UINT32 ** l_tmp_ptr; - - /* encoding prameters to set */ - OPJ_UINT32 l_max_res; - OPJ_UINT32 l_max_prec; - OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; - OPJ_UINT32 l_dx_min,l_dy_min; - OPJ_UINT32 l_bound; - OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ; - OPJ_UINT32 l_data_stride; - - /* pointers */ - opj_pi_iterator_t *l_pi = 00; - opj_tcp_t *l_tcp = 00; - const opj_tccp_t *l_tccp = 00; - opj_pi_comp_t *l_current_comp = 00; - opj_image_comp_t * l_img_comp = 00; - opj_pi_iterator_t * l_current_pi = 00; - OPJ_UINT32 * l_encoding_value_ptr = 00; - - /* preconditions in debug */ - assert(p_cp != 00); - assert(p_image != 00); - assert(p_tile_no < p_cp->tw * p_cp->th); - - /* initializations */ - l_tcp = &p_cp->tcps[p_tile_no]; - l_bound = l_tcp->numpocs+1; - - l_data_stride = 4 * OPJ_J2K_MAXRLVLS; - l_tmp_data = (OPJ_UINT32*)opj_malloc( - l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32)); - if - (! l_tmp_data) - { - return 00; - } - l_tmp_ptr = (OPJ_UINT32**)opj_malloc( - p_image->numcomps * sizeof(OPJ_UINT32 *)); - if - (! l_tmp_ptr) - { - opj_free(l_tmp_data); - return 00; - } - - /* memory allocation for pi */ - l_pi = opj_pi_create(p_image, p_cp, p_tile_no); - if (!l_pi) { - opj_free(l_tmp_data); - opj_free(l_tmp_ptr); - return 00; - } - - l_encoding_value_ptr = l_tmp_data; - /* update pointer array */ - for - (compno = 0; compno < p_image->numcomps; ++compno) - { - l_tmp_ptr[compno] = l_encoding_value_ptr; - l_encoding_value_ptr += l_data_stride; - } - /* get encoding parameters */ - opj_get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr); - - /* step calculations */ - l_step_p = 1; - l_step_c = l_max_prec * l_step_p; - l_step_r = p_image->numcomps * l_step_c; - l_step_l = l_max_res * l_step_r; - - /* set values for first packet iterator */ - l_current_pi = l_pi; - - /* memory allocation for include */ - l_current_pi->include = 00; - if - (l_step_l && l_tcp->numlayers < UINT_MAX / l_step_l - 1) - { - l_current_pi->include = (OPJ_INT16*)opj_calloc((l_tcp->numlayers + 1) * l_step_l, sizeof(OPJ_INT16)); - } - - if - (!l_current_pi->include) - { - opj_free(l_tmp_data); - opj_free(l_tmp_ptr); - opj_pi_destroy(l_pi, l_bound); - return 00; - } - - /* special treatment for the first packet iterator */ - l_current_comp = l_current_pi->comps; - l_img_comp = p_image->comps; - l_tccp = l_tcp->tccps; - - l_current_pi->tx0 = l_tx0; - l_current_pi->ty0 = l_ty0; - l_current_pi->tx1 = l_tx1; - l_current_pi->ty1 = l_ty1; - - /*l_current_pi->dx = l_img_comp->dx;*/ - /*l_current_pi->dy = l_img_comp->dy;*/ - - l_current_pi->step_p = l_step_p; - l_current_pi->step_c = l_step_c; - l_current_pi->step_r = l_step_r; - l_current_pi->step_l = l_step_l; - - /* allocation for components and number of components has already been calculated by opj_pi_create */ - for - (compno = 0; compno < l_current_pi->numcomps; ++compno) - { - opj_pi_resolution_t *l_res = l_current_comp->resolutions; - l_encoding_value_ptr = l_tmp_ptr[compno]; - - l_current_comp->dx = l_img_comp->dx; - l_current_comp->dy = l_img_comp->dy; - /* resolutions have already been initialized */ - for - (resno = 0; resno < l_current_comp->numresolutions; resno++) - { - l_res->pdx = *(l_encoding_value_ptr++); - l_res->pdy = *(l_encoding_value_ptr++); - l_res->pw = *(l_encoding_value_ptr++); - l_res->ph = *(l_encoding_value_ptr++); - ++l_res; - } - ++l_current_comp; - ++l_img_comp; - ++l_tccp; - } - ++l_current_pi; - - for (pino = 1 ; pino<l_bound ; ++pino ) - { - l_current_comp = l_current_pi->comps; - l_img_comp = p_image->comps; - l_tccp = l_tcp->tccps; - - l_current_pi->tx0 = l_tx0; - l_current_pi->ty0 = l_ty0; - l_current_pi->tx1 = l_tx1; - l_current_pi->ty1 = l_ty1; - /*l_current_pi->dx = l_dx_min;*/ - /*l_current_pi->dy = l_dy_min;*/ - l_current_pi->step_p = l_step_p; - l_current_pi->step_c = l_step_c; - l_current_pi->step_r = l_step_r; - l_current_pi->step_l = l_step_l; - - /* allocation for components and number of components has already been calculated by opj_pi_create */ - for - (compno = 0; compno < l_current_pi->numcomps; ++compno) - { - opj_pi_resolution_t *l_res = l_current_comp->resolutions; - l_encoding_value_ptr = l_tmp_ptr[compno]; - - l_current_comp->dx = l_img_comp->dx; - l_current_comp->dy = l_img_comp->dy; - /* resolutions have already been initialized */ - for - (resno = 0; resno < l_current_comp->numresolutions; resno++) - { - l_res->pdx = *(l_encoding_value_ptr++); - l_res->pdy = *(l_encoding_value_ptr++); - l_res->pw = *(l_encoding_value_ptr++); - l_res->ph = *(l_encoding_value_ptr++); - ++l_res; - } - ++l_current_comp; - ++l_img_comp; - ++l_tccp; - } - /* special treatment*/ - l_current_pi->include = (l_current_pi-1)->include; - ++l_current_pi; - } - opj_free(l_tmp_data); - l_tmp_data = 00; - opj_free(l_tmp_ptr); - l_tmp_ptr = 00; - if - (l_tcp->POC) - { - opj_pi_update_decode_poc (l_pi,l_tcp,l_max_prec,l_max_res); - } - else - { - opj_pi_update_decode_not_poc(l_pi,l_tcp,l_max_prec,l_max_res); - } - return l_pi; + OPJ_UINT32 numcomps = p_image->numcomps; + + /* loop */ + OPJ_UINT32 pino; + OPJ_UINT32 compno, resno; + + /* to store w, h, dx and dy fro all components and resolutions */ + OPJ_UINT32 * l_tmp_data; + OPJ_UINT32 ** l_tmp_ptr; + + /* encoding prameters to set */ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_INT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + OPJ_UINT32 l_bound; + OPJ_UINT32 l_step_p, l_step_c, l_step_r, l_step_l ; + OPJ_UINT32 l_data_stride; + + /* pointers */ + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *l_tcp = 00; + const opj_tccp_t *l_tccp = 00; + opj_pi_comp_t *l_current_comp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_pi_iterator_t * l_current_pi = 00; + OPJ_UINT32 * l_encoding_value_ptr = 00; + + /* preconditions in debug */ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + /* initializations */ + l_tcp = &p_cp->tcps[p_tile_no]; + l_bound = l_tcp->numpocs + 1; + + l_data_stride = 4 * OPJ_J2K_MAXRLVLS; + l_tmp_data = (OPJ_UINT32*)opj_malloc( + l_data_stride * numcomps * sizeof(OPJ_UINT32)); + if + (! l_tmp_data) { + return 00; + } + l_tmp_ptr = (OPJ_UINT32**)opj_malloc( + numcomps * sizeof(OPJ_UINT32 *)); + if + (! l_tmp_ptr) { + opj_free(l_tmp_data); + return 00; + } + + /* memory allocation for pi */ + l_pi = opj_pi_create(p_image, p_cp, p_tile_no); + if (!l_pi) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + return 00; + } + + l_encoding_value_ptr = l_tmp_data; + /* update pointer array */ + for + (compno = 0; compno < numcomps; ++compno) { + l_tmp_ptr[compno] = l_encoding_value_ptr; + l_encoding_value_ptr += l_data_stride; + } + /* get encoding parameters */ + opj_get_all_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, + &l_ty0, &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res, l_tmp_ptr); + + /* step calculations */ + l_step_p = 1; + l_step_c = l_max_prec * l_step_p; + l_step_r = numcomps * l_step_c; + l_step_l = l_max_res * l_step_r; + + /* set values for first packet iterator */ + l_current_pi = l_pi; + + /* memory allocation for include */ + /* prevent an integer overflow issue */ + /* 0 < l_tcp->numlayers < 65536 c.f. opj_j2k_read_cod in j2k.c */ + l_current_pi->include = 00; + if (l_step_l <= (UINT_MAX / (l_tcp->numlayers + 1U))) { + l_current_pi->include_size = (l_tcp->numlayers + 1U) * l_step_l; + l_current_pi->include = (OPJ_INT16*) opj_calloc( + l_current_pi->include_size, sizeof(OPJ_INT16)); + } + + if (!l_current_pi->include) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + opj_pi_destroy(l_pi, l_bound); + return 00; + } + + /* special treatment for the first packet iterator */ + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + + /*l_current_pi->dx = l_img_comp->dx;*/ + /*l_current_pi->dy = l_img_comp->dy;*/ + + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for + (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + ++l_current_pi; + + for (pino = 1 ; pino < l_bound ; ++pino) { + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + /*l_current_pi->dx = l_dx_min;*/ + /*l_current_pi->dy = l_dy_min;*/ + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for + (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + /* special treatment*/ + l_current_pi->include = (l_current_pi - 1)->include; + l_current_pi->include_size = (l_current_pi - 1)->include_size; + ++l_current_pi; + } + opj_free(l_tmp_data); + l_tmp_data = 00; + opj_free(l_tmp_ptr); + l_tmp_ptr = 00; + if + (l_tcp->POC) { + opj_pi_update_decode_poc(l_pi, l_tcp, l_max_prec, l_max_res); + } else { + opj_pi_update_decode_not_poc(l_pi, l_tcp, l_max_prec, l_max_res); + } + return l_pi; } opj_pi_iterator_t *opj_pi_initialise_encode(const opj_image_t *p_image, - opj_cp_t *p_cp, - OPJ_UINT32 p_tile_no, - J2K_T2_MODE p_t2_mode ) + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no, + J2K_T2_MODE p_t2_mode) { - /* loop*/ - OPJ_UINT32 pino; - OPJ_UINT32 compno, resno; - - /* to store w, h, dx and dy fro all components and resolutions*/ - OPJ_UINT32 * l_tmp_data; - OPJ_UINT32 ** l_tmp_ptr; - - /* encoding prameters to set*/ - OPJ_UINT32 l_max_res; - OPJ_UINT32 l_max_prec; - OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; - OPJ_UINT32 l_dx_min,l_dy_min; - OPJ_UINT32 l_bound; - OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ; - OPJ_UINT32 l_data_stride; - - /* pointers*/ - opj_pi_iterator_t *l_pi = 00; - opj_tcp_t *l_tcp = 00; - const opj_tccp_t *l_tccp = 00; - opj_pi_comp_t *l_current_comp = 00; - opj_image_comp_t * l_img_comp = 00; - opj_pi_iterator_t * l_current_pi = 00; - OPJ_UINT32 * l_encoding_value_ptr = 00; - - /* preconditions in debug*/ - assert(p_cp != 00); - assert(p_image != 00); - assert(p_tile_no < p_cp->tw * p_cp->th); - - /* initializations*/ - l_tcp = &p_cp->tcps[p_tile_no]; - l_bound = l_tcp->numpocs+1; - - l_data_stride = 4 * OPJ_J2K_MAXRLVLS; - l_tmp_data = (OPJ_UINT32*)opj_malloc( - l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32)); - if (! l_tmp_data) { - return 00; - } - - l_tmp_ptr = (OPJ_UINT32**)opj_malloc( - p_image->numcomps * sizeof(OPJ_UINT32 *)); - if (! l_tmp_ptr) { - opj_free(l_tmp_data); - return 00; - } - - /* memory allocation for pi*/ - l_pi = opj_pi_create(p_image,p_cp,p_tile_no); - if (!l_pi) { - opj_free(l_tmp_data); - opj_free(l_tmp_ptr); - return 00; - } - - l_encoding_value_ptr = l_tmp_data; - /* update pointer array*/ - for (compno = 0; compno < p_image->numcomps; ++compno) { - l_tmp_ptr[compno] = l_encoding_value_ptr; - l_encoding_value_ptr += l_data_stride; - } - - /* get encoding parameters*/ - opj_get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr); - - /* step calculations*/ - l_step_p = 1; - l_step_c = l_max_prec * l_step_p; - l_step_r = p_image->numcomps * l_step_c; - l_step_l = l_max_res * l_step_r; - - /* set values for first packet iterator*/ - l_pi->tp_on = (OPJ_BYTE)p_cp->m_specific_param.m_enc.m_tp_on; - l_current_pi = l_pi; - - /* memory allocation for include*/ - l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16)); - if (!l_current_pi->include) { - opj_free(l_tmp_data); - opj_free(l_tmp_ptr); - opj_pi_destroy(l_pi, l_bound); - return 00; - } - - /* special treatment for the first packet iterator*/ - l_current_comp = l_current_pi->comps; - l_img_comp = p_image->comps; - l_tccp = l_tcp->tccps; - l_current_pi->tx0 = l_tx0; - l_current_pi->ty0 = l_ty0; - l_current_pi->tx1 = l_tx1; - l_current_pi->ty1 = l_ty1; - l_current_pi->dx = l_dx_min; - l_current_pi->dy = l_dy_min; - l_current_pi->step_p = l_step_p; - l_current_pi->step_c = l_step_c; - l_current_pi->step_r = l_step_r; - l_current_pi->step_l = l_step_l; - - /* allocation for components and number of components has already been calculated by opj_pi_create */ - for (compno = 0; compno < l_current_pi->numcomps; ++compno) { - opj_pi_resolution_t *l_res = l_current_comp->resolutions; - l_encoding_value_ptr = l_tmp_ptr[compno]; - - l_current_comp->dx = l_img_comp->dx; - l_current_comp->dy = l_img_comp->dy; - - /* resolutions have already been initialized */ - for (resno = 0; resno < l_current_comp->numresolutions; resno++) { - l_res->pdx = *(l_encoding_value_ptr++); - l_res->pdy = *(l_encoding_value_ptr++); - l_res->pw = *(l_encoding_value_ptr++); - l_res->ph = *(l_encoding_value_ptr++); - ++l_res; - } - - ++l_current_comp; - ++l_img_comp; - ++l_tccp; - } - ++l_current_pi; - - for (pino = 1 ; pino<l_bound ; ++pino ) { - l_current_comp = l_current_pi->comps; - l_img_comp = p_image->comps; - l_tccp = l_tcp->tccps; - - l_current_pi->tx0 = l_tx0; - l_current_pi->ty0 = l_ty0; - l_current_pi->tx1 = l_tx1; - l_current_pi->ty1 = l_ty1; - l_current_pi->dx = l_dx_min; - l_current_pi->dy = l_dy_min; - l_current_pi->step_p = l_step_p; - l_current_pi->step_c = l_step_c; - l_current_pi->step_r = l_step_r; - l_current_pi->step_l = l_step_l; - - /* allocation for components and number of components has already been calculated by opj_pi_create */ - for (compno = 0; compno < l_current_pi->numcomps; ++compno) { - opj_pi_resolution_t *l_res = l_current_comp->resolutions; - l_encoding_value_ptr = l_tmp_ptr[compno]; - - l_current_comp->dx = l_img_comp->dx; - l_current_comp->dy = l_img_comp->dy; - /* resolutions have already been initialized */ - for (resno = 0; resno < l_current_comp->numresolutions; resno++) { - l_res->pdx = *(l_encoding_value_ptr++); - l_res->pdy = *(l_encoding_value_ptr++); - l_res->pw = *(l_encoding_value_ptr++); - l_res->ph = *(l_encoding_value_ptr++); - ++l_res; - } - ++l_current_comp; - ++l_img_comp; - ++l_tccp; - } - - /* special treatment*/ - l_current_pi->include = (l_current_pi-1)->include; - ++l_current_pi; - } - - opj_free(l_tmp_data); - l_tmp_data = 00; - opj_free(l_tmp_ptr); - l_tmp_ptr = 00; + OPJ_UINT32 numcomps = p_image->numcomps; + + /* loop*/ + OPJ_UINT32 pino; + OPJ_UINT32 compno, resno; + + /* to store w, h, dx and dy fro all components and resolutions*/ + OPJ_UINT32 * l_tmp_data; + OPJ_UINT32 ** l_tmp_ptr; + + /* encoding prameters to set*/ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_INT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + OPJ_UINT32 l_bound; + OPJ_UINT32 l_step_p, l_step_c, l_step_r, l_step_l ; + OPJ_UINT32 l_data_stride; + + /* pointers*/ + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *l_tcp = 00; + const opj_tccp_t *l_tccp = 00; + opj_pi_comp_t *l_current_comp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_pi_iterator_t * l_current_pi = 00; + OPJ_UINT32 * l_encoding_value_ptr = 00; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + /* initializations*/ + l_tcp = &p_cp->tcps[p_tile_no]; + l_bound = l_tcp->numpocs + 1; + + l_data_stride = 4 * OPJ_J2K_MAXRLVLS; + l_tmp_data = (OPJ_UINT32*)opj_malloc( + l_data_stride * numcomps * sizeof(OPJ_UINT32)); + if (! l_tmp_data) { + return 00; + } + + l_tmp_ptr = (OPJ_UINT32**)opj_malloc( + numcomps * sizeof(OPJ_UINT32 *)); + if (! l_tmp_ptr) { + opj_free(l_tmp_data); + return 00; + } + + /* memory allocation for pi*/ + l_pi = opj_pi_create(p_image, p_cp, p_tile_no); + if (!l_pi) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + return 00; + } + + l_encoding_value_ptr = l_tmp_data; + /* update pointer array*/ + for (compno = 0; compno < numcomps; ++compno) { + l_tmp_ptr[compno] = l_encoding_value_ptr; + l_encoding_value_ptr += l_data_stride; + } + + /* get encoding parameters*/ + opj_get_all_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, + &l_ty0, &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res, l_tmp_ptr); + + /* step calculations*/ + l_step_p = 1; + l_step_c = l_max_prec * l_step_p; + l_step_r = numcomps * l_step_c; + l_step_l = l_max_res * l_step_r; + + /* set values for first packet iterator*/ + l_pi->tp_on = (OPJ_BYTE)p_cp->m_specific_param.m_enc.m_tp_on; + l_current_pi = l_pi; + + /* memory allocation for include*/ + l_current_pi->include_size = l_tcp->numlayers * l_step_l; + l_current_pi->include = (OPJ_INT16*) opj_calloc(l_current_pi->include_size, + sizeof(OPJ_INT16)); + if (!l_current_pi->include) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + opj_pi_destroy(l_pi, l_bound); + return 00; + } + + /* special treatment for the first packet iterator*/ + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + l_current_pi->dx = l_dx_min; + l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + + /* resolutions have already been initialized */ + for (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + ++l_current_pi; + + for (pino = 1 ; pino < l_bound ; ++pino) { + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + l_current_pi->dx = l_dx_min; + l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + + /* special treatment*/ + l_current_pi->include = (l_current_pi - 1)->include; + l_current_pi->include_size = (l_current_pi - 1)->include_size; + ++l_current_pi; + } + + opj_free(l_tmp_data); + l_tmp_data = 00; + opj_free(l_tmp_ptr); + l_tmp_ptr = 00; if (l_tcp->POC && (OPJ_IS_CINEMA(p_cp->rsiz) || p_t2_mode == FINAL_PASS)) { - opj_pi_update_encode_poc_and_final(p_cp,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); - } - else { - opj_pi_update_encode_not_poc(p_cp,p_image->numcomps,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); - } - - return l_pi; + opj_pi_update_encode_poc_and_final(p_cp, p_tile_no, l_tx0, l_tx1, l_ty0, l_ty1, + l_max_prec, l_max_res, l_dx_min, l_dy_min); + } else { + opj_pi_update_encode_not_poc(p_cp, numcomps, p_tile_no, l_tx0, l_tx1, + l_ty0, l_ty1, l_max_prec, l_max_res, l_dx_min, l_dy_min); + } + + return l_pi; } -void opj_pi_create_encode( opj_pi_iterator_t *pi, - opj_cp_t *cp, - OPJ_UINT32 tileno, - OPJ_UINT32 pino, - OPJ_UINT32 tpnum, - OPJ_INT32 tppos, - J2K_T2_MODE t2_mode) +void opj_pi_create_encode(opj_pi_iterator_t *pi, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + J2K_T2_MODE t2_mode) { - const OPJ_CHAR *prog; - OPJ_INT32 i; - OPJ_UINT32 incr_top=1,resetX=0; - opj_tcp_t *tcps =&cp->tcps[tileno]; - opj_poc_t *tcp= &tcps->pocs[pino]; - - prog = opj_j2k_convert_progression_order(tcp->prg); - - pi[pino].first = 1; - pi[pino].poc.prg = tcp->prg; - - if(!(cp->m_specific_param.m_enc.m_tp_on && ((!OPJ_IS_CINEMA(cp->rsiz) && (t2_mode == FINAL_PASS)) || OPJ_IS_CINEMA(cp->rsiz)))){ - pi[pino].poc.resno0 = tcp->resS; - pi[pino].poc.resno1 = tcp->resE; - pi[pino].poc.compno0 = tcp->compS; - pi[pino].poc.compno1 = tcp->compE; - pi[pino].poc.layno0 = tcp->layS; - pi[pino].poc.layno1 = tcp->layE; - pi[pino].poc.precno0 = tcp->prcS; - pi[pino].poc.precno1 = tcp->prcE; - pi[pino].poc.tx0 = (OPJ_INT32)tcp->txS; - pi[pino].poc.ty0 = (OPJ_INT32)tcp->tyS; - pi[pino].poc.tx1 = (OPJ_INT32)tcp->txE; - pi[pino].poc.ty1 = (OPJ_INT32)tcp->tyE; - }else { - for(i=tppos+1;i<4;i++){ - switch(prog[i]){ - case 'R': - pi[pino].poc.resno0 = tcp->resS; - pi[pino].poc.resno1 = tcp->resE; - break; - case 'C': - pi[pino].poc.compno0 = tcp->compS; - pi[pino].poc.compno1 = tcp->compE; - break; - case 'L': - pi[pino].poc.layno0 = tcp->layS; - pi[pino].poc.layno1 = tcp->layE; - break; - case 'P': - switch(tcp->prg){ - case OPJ_LRCP: - case OPJ_RLCP: - pi[pino].poc.precno0 = tcp->prcS; - pi[pino].poc.precno1 = tcp->prcE; - break; - default: - pi[pino].poc.tx0 = (OPJ_INT32)tcp->txS; - pi[pino].poc.ty0 = (OPJ_INT32)tcp->tyS; - pi[pino].poc.tx1 = (OPJ_INT32)tcp->txE; - pi[pino].poc.ty1 = (OPJ_INT32)tcp->tyE; - break; - } - break; - } - } - - if(tpnum==0){ - for(i=tppos;i>=0;i--){ - switch(prog[i]){ - case 'C': - tcp->comp_t = tcp->compS; - pi[pino].poc.compno0 = tcp->comp_t; - pi[pino].poc.compno1 = tcp->comp_t+1; - tcp->comp_t+=1; - break; - case 'R': - tcp->res_t = tcp->resS; - pi[pino].poc.resno0 = tcp->res_t; - pi[pino].poc.resno1 = tcp->res_t+1; - tcp->res_t+=1; - break; - case 'L': - tcp->lay_t = tcp->layS; - pi[pino].poc.layno0 = tcp->lay_t; - pi[pino].poc.layno1 = tcp->lay_t+1; - tcp->lay_t+=1; - break; - case 'P': - switch(tcp->prg){ - case OPJ_LRCP: - case OPJ_RLCP: - tcp->prc_t = tcp->prcS; - pi[pino].poc.precno0 = tcp->prc_t; - pi[pino].poc.precno1 = tcp->prc_t+1; - tcp->prc_t+=1; - break; - default: - tcp->tx0_t = tcp->txS; - tcp->ty0_t = tcp->tyS; - pi[pino].poc.tx0 = (OPJ_INT32)tcp->tx0_t; - pi[pino].poc.tx1 = (OPJ_INT32)(tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx)); - pi[pino].poc.ty0 = (OPJ_INT32)tcp->ty0_t; - pi[pino].poc.ty1 = (OPJ_INT32)(tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy)); - tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; - tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; - break; - } - break; - } - } - incr_top=1; - }else{ - for(i=tppos;i>=0;i--){ - switch(prog[i]){ - case 'C': - pi[pino].poc.compno0 = tcp->comp_t-1; - pi[pino].poc.compno1 = tcp->comp_t; - break; - case 'R': - pi[pino].poc.resno0 = tcp->res_t-1; - pi[pino].poc.resno1 = tcp->res_t; - break; - case 'L': - pi[pino].poc.layno0 = tcp->lay_t-1; - pi[pino].poc.layno1 = tcp->lay_t; - break; - case 'P': - switch(tcp->prg){ - case OPJ_LRCP: - case OPJ_RLCP: - pi[pino].poc.precno0 = tcp->prc_t-1; - pi[pino].poc.precno1 = tcp->prc_t; - break; - default: - pi[pino].poc.tx0 = (OPJ_INT32)(tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx)); - pi[pino].poc.tx1 = (OPJ_INT32)tcp->tx0_t ; - pi[pino].poc.ty0 = (OPJ_INT32)(tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy)); - pi[pino].poc.ty1 = (OPJ_INT32)tcp->ty0_t ; - break; - } - break; - } - if(incr_top==1){ - switch(prog[i]){ - case 'R': - if(tcp->res_t==tcp->resE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - tcp->res_t = tcp->resS; - pi[pino].poc.resno0 = tcp->res_t; - pi[pino].poc.resno1 = tcp->res_t+1; - tcp->res_t+=1; - incr_top=1; - }else{ - incr_top=0; - } - }else{ - pi[pino].poc.resno0 = tcp->res_t; - pi[pino].poc.resno1 = tcp->res_t+1; - tcp->res_t+=1; - incr_top=0; - } - break; - case 'C': - if(tcp->comp_t ==tcp->compE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - tcp->comp_t = tcp->compS; - pi[pino].poc.compno0 = tcp->comp_t; - pi[pino].poc.compno1 = tcp->comp_t+1; - tcp->comp_t+=1; - incr_top=1; - }else{ - incr_top=0; - } - }else{ - pi[pino].poc.compno0 = tcp->comp_t; - pi[pino].poc.compno1 = tcp->comp_t+1; - tcp->comp_t+=1; - incr_top=0; - } - break; - case 'L': - if(tcp->lay_t == tcp->layE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - tcp->lay_t = tcp->layS; - pi[pino].poc.layno0 = tcp->lay_t; - pi[pino].poc.layno1 = tcp->lay_t+1; - tcp->lay_t+=1; - incr_top=1; - }else{ - incr_top=0; - } - }else{ - pi[pino].poc.layno0 = tcp->lay_t; - pi[pino].poc.layno1 = tcp->lay_t+1; - tcp->lay_t+=1; - incr_top=0; - } - break; - case 'P': - switch(tcp->prg){ - case OPJ_LRCP: - case OPJ_RLCP: - if(tcp->prc_t == tcp->prcE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - tcp->prc_t = tcp->prcS; - pi[pino].poc.precno0 = tcp->prc_t; - pi[pino].poc.precno1 = tcp->prc_t+1; - tcp->prc_t+=1; - incr_top=1; - }else{ - incr_top=0; - } - }else{ - pi[pino].poc.precno0 = tcp->prc_t; - pi[pino].poc.precno1 = tcp->prc_t+1; - tcp->prc_t+=1; - incr_top=0; - } - break; - default: - if(tcp->tx0_t >= tcp->txE){ - if(tcp->ty0_t >= tcp->tyE){ - if(opj_pi_check_next_level(i-1,cp,tileno,pino,prog)){ - tcp->ty0_t = tcp->tyS; - pi[pino].poc.ty0 = (OPJ_INT32)tcp->ty0_t; - pi[pino].poc.ty1 = (OPJ_INT32)(tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy)); - tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; - incr_top=1;resetX=1; - }else{ - incr_top=0;resetX=0; - } - }else{ - pi[pino].poc.ty0 = (OPJ_INT32)tcp->ty0_t; - pi[pino].poc.ty1 = (OPJ_INT32)(tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy)); - tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; - incr_top=0;resetX=1; - } - if(resetX==1){ - tcp->tx0_t = tcp->txS; - pi[pino].poc.tx0 = (OPJ_INT32)tcp->tx0_t; - pi[pino].poc.tx1 = (OPJ_INT32)(tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx)); - tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; - } - }else{ - pi[pino].poc.tx0 = (OPJ_INT32)tcp->tx0_t; - pi[pino].poc.tx1 = (OPJ_INT32)(tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx)); - tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; - incr_top=0; - } - break; - } - break; - } - } - } - } - } + const OPJ_CHAR *prog; + OPJ_INT32 i; + OPJ_UINT32 incr_top = 1, resetX = 0; + opj_tcp_t *tcps = &cp->tcps[tileno]; + opj_poc_t *tcp = &tcps->pocs[pino]; + + prog = opj_j2k_convert_progression_order(tcp->prg); + + pi[pino].first = 1; + pi[pino].poc.prg = tcp->prg; + + if (!(cp->m_specific_param.m_enc.m_tp_on && ((!OPJ_IS_CINEMA(cp->rsiz) && + (t2_mode == FINAL_PASS)) || OPJ_IS_CINEMA(cp->rsiz)))) { + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + pi[pino].poc.tx0 = (OPJ_INT32)tcp->txS; + pi[pino].poc.ty0 = (OPJ_INT32)tcp->tyS; + pi[pino].poc.tx1 = (OPJ_INT32)tcp->txE; + pi[pino].poc.ty1 = (OPJ_INT32)tcp->tyE; + } else { + for (i = tppos + 1; i < 4; i++) { + switch (prog[i]) { + case 'R': + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + break; + case 'C': + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + break; + case 'L': + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + break; + default: + pi[pino].poc.tx0 = (OPJ_INT32)tcp->txS; + pi[pino].poc.ty0 = (OPJ_INT32)tcp->tyS; + pi[pino].poc.tx1 = (OPJ_INT32)tcp->txE; + pi[pino].poc.ty1 = (OPJ_INT32)tcp->tyE; + break; + } + break; + } + } + + if (tpnum == 0) { + for (i = tppos; i >= 0; i--) { + switch (prog[i]) { + case 'C': + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t + 1; + tcp->comp_t += 1; + break; + case 'R': + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t + 1; + tcp->res_t += 1; + break; + case 'L': + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t + 1; + tcp->lay_t += 1; + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t + 1; + tcp->prc_t += 1; + break; + default: + tcp->tx0_t = tcp->txS; + tcp->ty0_t = tcp->tyS; + pi[pino].poc.tx0 = (OPJ_INT32)tcp->tx0_t; + pi[pino].poc.tx1 = (OPJ_INT32)(tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx)); + pi[pino].poc.ty0 = (OPJ_INT32)tcp->ty0_t; + pi[pino].poc.ty1 = (OPJ_INT32)(tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy)); + tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; + tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; + break; + } + break; + } + } + incr_top = 1; + } else { + for (i = tppos; i >= 0; i--) { + switch (prog[i]) { + case 'C': + pi[pino].poc.compno0 = tcp->comp_t - 1; + pi[pino].poc.compno1 = tcp->comp_t; + break; + case 'R': + pi[pino].poc.resno0 = tcp->res_t - 1; + pi[pino].poc.resno1 = tcp->res_t; + break; + case 'L': + pi[pino].poc.layno0 = tcp->lay_t - 1; + pi[pino].poc.layno1 = tcp->lay_t; + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + pi[pino].poc.precno0 = tcp->prc_t - 1; + pi[pino].poc.precno1 = tcp->prc_t; + break; + default: + pi[pino].poc.tx0 = (OPJ_INT32)(tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx)); + pi[pino].poc.tx1 = (OPJ_INT32)tcp->tx0_t ; + pi[pino].poc.ty0 = (OPJ_INT32)(tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy)); + pi[pino].poc.ty1 = (OPJ_INT32)tcp->ty0_t ; + break; + } + break; + } + if (incr_top == 1) { + switch (prog[i]) { + case 'R': + if (tcp->res_t == tcp->resE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t + 1; + tcp->res_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t + 1; + tcp->res_t += 1; + incr_top = 0; + } + break; + case 'C': + if (tcp->comp_t == tcp->compE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t + 1; + tcp->comp_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t + 1; + tcp->comp_t += 1; + incr_top = 0; + } + break; + case 'L': + if (tcp->lay_t == tcp->layE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t + 1; + tcp->lay_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t + 1; + tcp->lay_t += 1; + incr_top = 0; + } + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + if (tcp->prc_t == tcp->prcE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t + 1; + tcp->prc_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t + 1; + tcp->prc_t += 1; + incr_top = 0; + } + break; + default: + if (tcp->tx0_t >= tcp->txE) { + if (tcp->ty0_t >= tcp->tyE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->ty0_t = tcp->tyS; + pi[pino].poc.ty0 = (OPJ_INT32)tcp->ty0_t; + pi[pino].poc.ty1 = (OPJ_INT32)(tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy)); + tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; + incr_top = 1; + resetX = 1; + } else { + incr_top = 0; + resetX = 0; + } + } else { + pi[pino].poc.ty0 = (OPJ_INT32)tcp->ty0_t; + pi[pino].poc.ty1 = (OPJ_INT32)(tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy)); + tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; + incr_top = 0; + resetX = 1; + } + if (resetX == 1) { + tcp->tx0_t = tcp->txS; + pi[pino].poc.tx0 = (OPJ_INT32)tcp->tx0_t; + pi[pino].poc.tx1 = (OPJ_INT32)(tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx)); + tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; + } + } else { + pi[pino].poc.tx0 = (OPJ_INT32)tcp->tx0_t; + pi[pino].poc.tx1 = (OPJ_INT32)(tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx)); + tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; + incr_top = 0; + } + break; + } + break; + } + } + } + } + } } void opj_pi_destroy(opj_pi_iterator_t *p_pi, OPJ_UINT32 p_nb_elements) { - OPJ_UINT32 compno, pino; - opj_pi_iterator_t *l_current_pi = p_pi; + OPJ_UINT32 compno, pino; + opj_pi_iterator_t *l_current_pi = p_pi; if (p_pi) { - if (p_pi->include) { - opj_free(p_pi->include); - p_pi->include = 00; - } - for (pino = 0; pino < p_nb_elements; ++pino){ - if(l_current_pi->comps) { - opj_pi_comp_t *l_current_component = l_current_pi->comps; - for (compno = 0; compno < l_current_pi->numcomps; compno++){ - if(l_current_component->resolutions) { - opj_free(l_current_component->resolutions); - l_current_component->resolutions = 00; - } - - ++l_current_component; - } - opj_free(l_current_pi->comps); - l_current_pi->comps = 0; - } - ++l_current_pi; - } - opj_free(p_pi); - } + if (p_pi->include) { + opj_free(p_pi->include); + p_pi->include = 00; + } + for (pino = 0; pino < p_nb_elements; ++pino) { + if (l_current_pi->comps) { + opj_pi_comp_t *l_current_component = l_current_pi->comps; + for (compno = 0; compno < l_current_pi->numcomps; compno++) { + if (l_current_component->resolutions) { + opj_free(l_current_component->resolutions); + l_current_component->resolutions = 00; + } + + ++l_current_component; + } + opj_free(l_current_pi->comps); + l_current_pi->comps = 0; + } + ++l_current_pi; + } + opj_free(p_pi); + } } -void opj_pi_update_encoding_parameters( const opj_image_t *p_image, - opj_cp_t *p_cp, - OPJ_UINT32 p_tile_no ) +void opj_pi_update_encoding_parameters(const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no) { - /* encoding parameters to set */ - OPJ_UINT32 l_max_res; - OPJ_UINT32 l_max_prec; - OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; - OPJ_UINT32 l_dx_min,l_dy_min; - - /* pointers */ - opj_tcp_t *l_tcp = 00; - - /* preconditions */ - assert(p_cp != 00); - assert(p_image != 00); - assert(p_tile_no < p_cp->tw * p_cp->th); - - l_tcp = &(p_cp->tcps[p_tile_no]); - - /* get encoding parameters */ - opj_get_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res); - - if (l_tcp->POC) { - opj_pi_update_encode_poc_and_final(p_cp,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); - } - else { - opj_pi_update_encode_not_poc(p_cp,p_image->numcomps,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); - } + /* encoding parameters to set */ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_INT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + + /* pointers */ + opj_tcp_t *l_tcp = 00; + + /* preconditions */ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + l_tcp = &(p_cp->tcps[p_tile_no]); + + /* get encoding parameters */ + opj_get_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, &l_ty0, + &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res); + + if (l_tcp->POC) { + opj_pi_update_encode_poc_and_final(p_cp, p_tile_no, l_tx0, l_tx1, l_ty0, l_ty1, + l_max_prec, l_max_res, l_dx_min, l_dy_min); + } else { + opj_pi_update_encode_not_poc(p_cp, p_image->numcomps, p_tile_no, l_tx0, l_tx1, + l_ty0, l_ty1, l_max_prec, l_max_res, l_dx_min, l_dy_min); + } } -OPJ_BOOL opj_pi_next(opj_pi_iterator_t * pi) { - switch (pi->poc.prg) { - case OPJ_LRCP: - return opj_pi_next_lrcp(pi); - case OPJ_RLCP: - return opj_pi_next_rlcp(pi); - case OPJ_RPCL: - return opj_pi_next_rpcl(pi); - case OPJ_PCRL: - return opj_pi_next_pcrl(pi); - case OPJ_CPRL: - return opj_pi_next_cprl(pi); - case OPJ_PROG_UNKNOWN: - return OPJ_FALSE; - } - - return OPJ_FALSE; +OPJ_BOOL opj_pi_next(opj_pi_iterator_t * pi) +{ + switch (pi->poc.prg) { + case OPJ_LRCP: + return opj_pi_next_lrcp(pi); + case OPJ_RLCP: + return opj_pi_next_rlcp(pi); + case OPJ_RPCL: + return opj_pi_next_rpcl(pi); + case OPJ_PCRL: + return opj_pi_next_pcrl(pi); + case OPJ_CPRL: + return opj_pi_next_cprl(pi); + case OPJ_PROG_UNKNOWN: + return OPJ_FALSE; + } + + return OPJ_FALSE; } diff --git a/third_party/libopenjpeg20/pi.h b/third_party/libopenjpeg20/pi.h index 265d5b1e24c90ced9293b4db60d1562edf2a9508..8c0dc25c19dd962bf9e76994609a37ee41fc0cca 100644 --- a/third_party/libopenjpeg20/pi.h +++ b/third_party/libopenjpeg20/pi.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. @@ -35,8 +35,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __PI_H -#define __PI_H +#ifndef OPJ_PI_H +#define OPJ_PI_H /** @file pi.h @brief Implementation of a packet iterator (PI) @@ -53,58 +53,60 @@ by some function in T2.C. FIXME DOC */ typedef struct opj_pi_resolution { - OPJ_UINT32 pdx, pdy; - OPJ_UINT32 pw, ph; + OPJ_UINT32 pdx, pdy; + OPJ_UINT32 pw, ph; } opj_pi_resolution_t; /** FIXME DOC */ typedef struct opj_pi_comp { - OPJ_UINT32 dx, dy; - /** number of resolution levels */ - OPJ_UINT32 numresolutions; - opj_pi_resolution_t *resolutions; + OPJ_UINT32 dx, dy; + /** number of resolution levels */ + OPJ_UINT32 numresolutions; + opj_pi_resolution_t *resolutions; } opj_pi_comp_t; /** Packet iterator */ typedef struct opj_pi_iterator { - /** Enabling Tile part generation*/ - OPJ_BYTE tp_on; - /** precise if the packet has been already used (useful for progression order change) */ - OPJ_INT16 *include; - /** layer step used to localize the packet in the include vector */ - OPJ_UINT32 step_l; - /** resolution step used to localize the packet in the include vector */ - OPJ_UINT32 step_r; - /** component step used to localize the packet in the include vector */ - OPJ_UINT32 step_c; - /** precinct step used to localize the packet in the include vector */ - OPJ_UINT32 step_p; - /** component that identify the packet */ - OPJ_UINT32 compno; - /** resolution that identify the packet */ - OPJ_UINT32 resno; - /** precinct that identify the packet */ - OPJ_UINT32 precno; - /** layer that identify the packet */ - OPJ_UINT32 layno; - /** 0 if the first packet */ - OPJ_BOOL first; - /** progression order change information */ - opj_poc_t poc; - /** number of components in the image */ - OPJ_UINT32 numcomps; - /** Components*/ - opj_pi_comp_t *comps; - /** FIXME DOC*/ - OPJ_INT32 tx0, ty0, tx1, ty1; - /** FIXME DOC*/ - OPJ_INT32 x, y; - /** FIXME DOC*/ - OPJ_UINT32 dx, dy; + /** Enabling Tile part generation*/ + OPJ_BYTE tp_on; + /** precise if the packet has been already used (useful for progression order change) */ + OPJ_INT16 *include; + /** Number of elements in include array */ + OPJ_UINT32 include_size; + /** layer step used to localize the packet in the include vector */ + OPJ_UINT32 step_l; + /** resolution step used to localize the packet in the include vector */ + OPJ_UINT32 step_r; + /** component step used to localize the packet in the include vector */ + OPJ_UINT32 step_c; + /** precinct step used to localize the packet in the include vector */ + OPJ_UINT32 step_p; + /** component that identify the packet */ + OPJ_UINT32 compno; + /** resolution that identify the packet */ + OPJ_UINT32 resno; + /** precinct that identify the packet */ + OPJ_UINT32 precno; + /** layer that identify the packet */ + OPJ_UINT32 layno; + /** 0 if the first packet */ + OPJ_BOOL first; + /** progression order change information */ + opj_poc_t poc; + /** number of components in the image */ + OPJ_UINT32 numcomps; + /** Components*/ + opj_pi_comp_t *comps; + /** FIXME DOC*/ + OPJ_INT32 tx0, ty0, tx1, ty1; + /** FIXME DOC*/ + OPJ_INT32 x, y; + /** FIXME DOC*/ + OPJ_UINT32 dx, dy; } opj_pi_iterator_t; /** @name Exported functions */ @@ -113,28 +115,28 @@ typedef struct opj_pi_iterator { /** * Creates a packet iterator for encoding. * - * @param image the image being encoded. - * @param cp the coding parameters. - * @param tileno index of the tile being encoded. - * @param t2_mode the type of pass for generating the packet iterator + * @param image the image being encoded. + * @param cp the coding parameters. + * @param tileno index of the tile being encoded. + * @param t2_mode the type of pass for generating the packet iterator * - * @return a list of packet iterator that points to the first packet of the tile (not true). + * @return a list of packet iterator that points to the first packet of the tile (not true). */ opj_pi_iterator_t *opj_pi_initialise_encode(const opj_image_t *image, - opj_cp_t *cp, - OPJ_UINT32 tileno, - J2K_T2_MODE t2_mode); + opj_cp_t *cp, + OPJ_UINT32 tileno, + J2K_T2_MODE t2_mode); /** * Updates the encoding parameters of the codec. * - * @param p_image the image being encoded. - * @param p_cp the coding parameters. - * @param p_tile_no index of the tile being encoded. + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tile_no index of the tile being encoded. */ -void opj_pi_update_encoding_parameters( const opj_image_t *p_image, - opj_cp_t *p_cp, - OPJ_UINT32 p_tile_no ); +void opj_pi_update_encoding_parameters(const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no); /** Modify the packet iterator for enabling tile part generation @@ -146,13 +148,13 @@ Modify the packet iterator for enabling tile part generation @param tppos The position of the tile part flag in the progression order @param t2_mode FIXME DOC */ -void opj_pi_create_encode( opj_pi_iterator_t *pi, - opj_cp_t *cp, - OPJ_UINT32 tileno, - OPJ_UINT32 pino, - OPJ_UINT32 tpnum, - OPJ_INT32 tppos, - J2K_T2_MODE t2_mode); +void opj_pi_create_encode(opj_pi_iterator_t *pi, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + J2K_T2_MODE t2_mode); /** Create a packet iterator for Decoder @@ -162,14 +164,14 @@ Create a packet iterator for Decoder @return Returns a packet iterator that points to the first packet of the tile @see opj_pi_destroy */ -opj_pi_iterator_t *opj_pi_create_decode(opj_image_t * image, +opj_pi_iterator_t *opj_pi_create_decode(opj_image_t * image, opj_cp_t * cp, OPJ_UINT32 tileno); /** * Destroys a packet iterator array. * - * @param p_pi the packet iterator array to destroy. - * @param p_nb_elements the number of elements in the array. + * @param p_pi the packet iterator array to destroy. + * @param p_nb_elements the number of elements in the array. */ void opj_pi_destroy(opj_pi_iterator_t *p_pi, OPJ_UINT32 p_nb_elements); @@ -185,4 +187,4 @@ OPJ_BOOL opj_pi_next(opj_pi_iterator_t * pi); /*@}*/ -#endif /* __PI_H */ +#endif /* OPJ_PI_H */ diff --git a/third_party/libopenjpeg20/raw.c b/third_party/libopenjpeg20/raw.c deleted file mode 100644 index 2498761c423f3ac00deca3093e2a458113237805..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/raw.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third - * party and contributor rights, including patent rights, and no such rights - * are granted under this license. - * - * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2014, Professor Benoit Macq - * Copyright (c) 2003-2007, Francois-Olivier Devaux - * Copyright (c) 2003-2014, Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "opj_includes.h" - -/* -========================================================== - local functions -========================================================== -*/ - - -/* -========================================================== - RAW encoding interface -========================================================== -*/ - -opj_raw_t* opj_raw_create(void) { - opj_raw_t *raw = (opj_raw_t*)opj_malloc(sizeof(opj_raw_t)); - return raw; -} - -void opj_raw_destroy(opj_raw_t *raw) { - if(raw) { - opj_free(raw); - } -} - -OPJ_UINT32 opj_raw_numbytes(opj_raw_t *raw) { - const ptrdiff_t diff = raw->bp - raw->start; - assert( diff <= (ptrdiff_t)0xffffffff && diff >= 0 ); /* UINT32_MAX */ - return (OPJ_UINT32)diff; -} - -void opj_raw_init_dec(opj_raw_t *raw, OPJ_BYTE *bp, OPJ_UINT32 len) { - raw->start = bp; - raw->lenmax = len; - raw->len = 0; - raw->c = 0; - raw->ct = 0; -} - -OPJ_UINT32 opj_raw_decode(opj_raw_t *raw) { - OPJ_UINT32 d; - if (raw->ct == 0) { - raw->ct = 8; - if (raw->len == raw->lenmax) { - raw->c = 0xff; - } else { - if (raw->c == 0xff) { - raw->ct = 7; - } - raw->c = *(raw->start + raw->len); - raw->len++; - } - } - raw->ct--; - d = (raw->c >> raw->ct) & 0x01; - - return d; -} - diff --git a/third_party/libopenjpeg20/raw.h b/third_party/libopenjpeg20/raw.h deleted file mode 100644 index 572c666176efa9da3f6912f1737b365821783d0a..0000000000000000000000000000000000000000 --- a/third_party/libopenjpeg20/raw.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third - * party and contributor rights, including patent rights, and no such rights - * are granted under this license. - * - * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2014, Professor Benoit Macq - * Copyright (c) 2003-2007, Francois-Olivier Devaux - * Copyright (c) 2003-2014, Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __RAW_H -#define __RAW_H -/** -@file raw.h -@brief Implementation of operations for raw encoding (RAW) - -The functions in RAW.C have for goal to realize the operation of raw encoding linked -with the corresponding mode switch. -*/ - -/** @defgroup RAW RAW - Implementation of operations for raw encoding */ -/*@{*/ - -/** -RAW encoding operations -*/ -typedef struct opj_raw { - /** temporary buffer where bits are coded or decoded */ - OPJ_BYTE c; - /** number of bits already read or free to write */ - OPJ_UINT32 ct; - /** maximum length to decode */ - OPJ_UINT32 lenmax; - /** length decoded */ - OPJ_UINT32 len; - /** pointer to the current position in the buffer */ - OPJ_BYTE *bp; - /** pointer to the start of the buffer */ - OPJ_BYTE *start; - /** pointer to the end of the buffer */ - OPJ_BYTE *end; -} opj_raw_t; - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** -Create a new RAW handle -@return Returns a new RAW handle if successful, returns NULL otherwise -*/ -opj_raw_t* opj_raw_create(void); -/** -Destroy a previously created RAW handle -@param raw RAW handle to destroy -*/ -void opj_raw_destroy(opj_raw_t *raw); -/** -Return the number of bytes written/read since initialisation -@param raw RAW handle to destroy -@return Returns the number of bytes already encoded -*/ -OPJ_UINT32 opj_raw_numbytes(opj_raw_t *raw); -/** -Initialize the decoder -@param raw RAW handle -@param bp Pointer to the start of the buffer from which the bytes will be read -@param len Length of the input buffer -*/ -void opj_raw_init_dec(opj_raw_t *raw, OPJ_BYTE *bp, OPJ_UINT32 len); -/** -Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN -@param raw RAW handle -@return Returns the decoded symbol (0 or 1) -*/ -OPJ_UINT32 opj_raw_decode(opj_raw_t *raw); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __RAW_H */ diff --git a/third_party/libopenjpeg20/sparse_array.c b/third_party/libopenjpeg20/sparse_array.c new file mode 100644 index 0000000000000000000000000000000000000000..73192924eddcef37e24e6138faef09f4b62bd73a --- /dev/null +++ b/third_party/libopenjpeg20/sparse_array.c @@ -0,0 +1,346 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2017, IntoPix SA <contact@intopix.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opj_includes.h" + + +struct opj_sparse_array_int32 { + OPJ_UINT32 width; + OPJ_UINT32 height; + OPJ_UINT32 block_width; + OPJ_UINT32 block_height; + OPJ_UINT32 block_count_hor; + OPJ_UINT32 block_count_ver; + OPJ_INT32** data_blocks; +}; + +opj_sparse_array_int32_t* opj_sparse_array_int32_create(OPJ_UINT32 width, + OPJ_UINT32 height, + OPJ_UINT32 block_width, + OPJ_UINT32 block_height) +{ + opj_sparse_array_int32_t* sa; + + if (width == 0 || height == 0 || block_width == 0 || block_height == 0) { + return NULL; + } + if (block_width > ((OPJ_UINT32)~0U) / block_height / sizeof(OPJ_INT32)) { + return NULL; + } + + sa = (opj_sparse_array_int32_t*) opj_calloc(1, + sizeof(opj_sparse_array_int32_t)); + sa->width = width; + sa->height = height; + sa->block_width = block_width; + sa->block_height = block_height; + sa->block_count_hor = opj_uint_ceildiv(width, block_width); + sa->block_count_ver = opj_uint_ceildiv(height, block_height); + if (sa->block_count_hor > ((OPJ_UINT32)~0U) / sa->block_count_ver) { + opj_free(sa); + return NULL; + } + sa->data_blocks = (OPJ_INT32**) opj_calloc(sizeof(OPJ_INT32*), + sa->block_count_hor * sa->block_count_ver); + if (sa->data_blocks == NULL) { + opj_free(sa); + return NULL; + } + + return sa; +} + +void opj_sparse_array_int32_free(opj_sparse_array_int32_t* sa) +{ + if (sa) { + OPJ_UINT32 i; + for (i = 0; i < sa->block_count_hor * sa->block_count_ver; i++) { + if (sa->data_blocks[i]) { + opj_free(sa->data_blocks[i]); + } + } + opj_free(sa->data_blocks); + opj_free(sa); + } +} + +OPJ_BOOL opj_sparse_array_is_region_valid(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1) +{ + return !(x0 >= sa->width || x1 <= x0 || x1 > sa->width || + y0 >= sa->height || y1 <= y0 || y1 > sa->height); +} + +static OPJ_BOOL opj_sparse_array_int32_read_or_write( + const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + OPJ_INT32* buf, + OPJ_UINT32 buf_col_stride, + OPJ_UINT32 buf_line_stride, + OPJ_BOOL forgiving, + OPJ_BOOL is_read_op) +{ + OPJ_UINT32 y, block_y; + OPJ_UINT32 y_incr = 0; + const OPJ_UINT32 block_width = sa->block_width; + + if (!opj_sparse_array_is_region_valid(sa, x0, y0, x1, y1)) { + return forgiving; + } + + block_y = y0 / sa->block_height; + for (y = y0; y < y1; block_y ++, y += y_incr) { + OPJ_UINT32 x, block_x; + OPJ_UINT32 x_incr = 0; + OPJ_UINT32 block_y_offset; + y_incr = (y == y0) ? sa->block_height - (y0 % sa->block_height) : + sa->block_height; + block_y_offset = sa->block_height - y_incr; + y_incr = opj_uint_min(y_incr, y1 - y); + block_x = x0 / block_width; + for (x = x0; x < x1; block_x ++, x += x_incr) { + OPJ_UINT32 j; + OPJ_UINT32 block_x_offset; + OPJ_INT32* src_block; + x_incr = (x == x0) ? block_width - (x0 % block_width) : block_width; + block_x_offset = block_width - x_incr; + x_incr = opj_uint_min(x_incr, x1 - x); + src_block = sa->data_blocks[block_y * sa->block_count_hor + block_x]; + if (is_read_op) { + if (src_block == NULL) { + if (buf_col_stride == 1) { + OPJ_INT32* dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + (x - x0) * buf_col_stride; + for (j = 0; j < y_incr; j++) { + memset(dest_ptr, 0, sizeof(OPJ_INT32) * x_incr); + dest_ptr += buf_line_stride; + } + } else { + OPJ_INT32* dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + (x - x0) * buf_col_stride; + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = 0; + } + dest_ptr += buf_line_stride; + } + } + } else { + const OPJ_INT32* OPJ_RESTRICT src_ptr = src_block + block_y_offset * + (OPJ_SIZE_T)block_width + block_x_offset; + if (buf_col_stride == 1) { + OPJ_INT32* OPJ_RESTRICT dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + + (x - x0) * buf_col_stride; + if (x_incr == 4) { + /* Same code as general branch, but the compiler */ + /* can have an efficient memcpy() */ + (void)(x_incr); /* trick to silent cppcheck duplicateBranch warning */ + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } else { + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } + } else { + OPJ_INT32* OPJ_RESTRICT dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + + (x - x0) * buf_col_stride; + if (x_incr == 1) { + for (j = 0; j < y_incr; j++) { + *dest_ptr = *src_ptr; + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } else if (y_incr == 1 && buf_col_stride == 2) { + OPJ_UINT32 k; + for (k = 0; k < (x_incr & ~3U); k += 4) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + dest_ptr[(k + 1) * buf_col_stride] = src_ptr[k + 1]; + dest_ptr[(k + 2) * buf_col_stride] = src_ptr[k + 2]; + dest_ptr[(k + 3) * buf_col_stride] = src_ptr[k + 3]; + } + for (; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + } + } else if (x_incr >= 8 && buf_col_stride == 8) { + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < (x_incr & ~3U); k += 4) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + dest_ptr[(k + 1) * buf_col_stride] = src_ptr[k + 1]; + dest_ptr[(k + 2) * buf_col_stride] = src_ptr[k + 2]; + dest_ptr[(k + 3) * buf_col_stride] = src_ptr[k + 3]; + } + for (; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + } + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } else { + /* General case */ + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + } + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } + } + } + } else { + if (src_block == NULL) { + src_block = (OPJ_INT32*) opj_calloc(1, + sa->block_width * sa->block_height * sizeof(OPJ_INT32)); + if (src_block == NULL) { + return OPJ_FALSE; + } + sa->data_blocks[block_y * sa->block_count_hor + block_x] = src_block; + } + + if (buf_col_stride == 1) { + OPJ_INT32* OPJ_RESTRICT dest_ptr = src_block + block_y_offset * + (OPJ_SIZE_T)block_width + block_x_offset; + const OPJ_INT32* OPJ_RESTRICT src_ptr = buf + (y - y0) * + (OPJ_SIZE_T)buf_line_stride + (x - x0) * buf_col_stride; + if (x_incr == 4) { + /* Same code as general branch, but the compiler */ + /* can have an efficient memcpy() */ + (void)(x_incr); /* trick to silent cppcheck duplicateBranch warning */ + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += block_width; + src_ptr += buf_line_stride; + } + } else { + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += block_width; + src_ptr += buf_line_stride; + } + } + } else { + OPJ_INT32* OPJ_RESTRICT dest_ptr = src_block + block_y_offset * + (OPJ_SIZE_T)block_width + block_x_offset; + const OPJ_INT32* OPJ_RESTRICT src_ptr = buf + (y - y0) * + (OPJ_SIZE_T)buf_line_stride + (x - x0) * buf_col_stride; + if (x_incr == 1) { + for (j = 0; j < y_incr; j++) { + *dest_ptr = *src_ptr; + src_ptr += buf_line_stride; + dest_ptr += block_width; + } + } else if (x_incr >= 8 && buf_col_stride == 8) { + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < (x_incr & ~3U); k += 4) { + dest_ptr[k] = src_ptr[k * buf_col_stride]; + dest_ptr[k + 1] = src_ptr[(k + 1) * buf_col_stride]; + dest_ptr[k + 2] = src_ptr[(k + 2) * buf_col_stride]; + dest_ptr[k + 3] = src_ptr[(k + 3) * buf_col_stride]; + } + for (; k < x_incr; k++) { + dest_ptr[k] = src_ptr[k * buf_col_stride]; + } + src_ptr += buf_line_stride; + dest_ptr += block_width; + } + } else { + /* General case */ + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < x_incr; k++) { + dest_ptr[k] = src_ptr[k * buf_col_stride]; + } + src_ptr += buf_line_stride; + dest_ptr += block_width; + } + } + } + } + } + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_sparse_array_int32_read(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + OPJ_INT32* dest, + OPJ_UINT32 dest_col_stride, + OPJ_UINT32 dest_line_stride, + OPJ_BOOL forgiving) +{ + return opj_sparse_array_int32_read_or_write( + (opj_sparse_array_int32_t*)sa, x0, y0, x1, y1, + dest, + dest_col_stride, + dest_line_stride, + forgiving, + OPJ_TRUE); +} + +OPJ_BOOL opj_sparse_array_int32_write(opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + const OPJ_INT32* src, + OPJ_UINT32 src_col_stride, + OPJ_UINT32 src_line_stride, + OPJ_BOOL forgiving) +{ + return opj_sparse_array_int32_read_or_write(sa, x0, y0, x1, y1, + (OPJ_INT32*)src, + src_col_stride, + src_line_stride, + forgiving, + OPJ_FALSE); +} diff --git a/third_party/libopenjpeg20/sparse_array.h b/third_party/libopenjpeg20/sparse_array.h new file mode 100644 index 0000000000000000000000000000000000000000..fd927eaa0b68bb3ec5ccb3a131e8ea90cf453f34 --- /dev/null +++ b/third_party/libopenjpeg20/sparse_array.h @@ -0,0 +1,141 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2017, IntoPix SA <contact@intopix.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opj_includes.h" + +#ifndef OPJ_SPARSE_ARRAY_H +#define OPJ_SPARSE_ARRAY_H +/** +@file sparse_array.h +@brief Sparse array management + +The functions in this file manage sparse arrays. Sparse arrays are arrays with +potential big dimensions, but with very few samples actually set. Such sparse +arrays require allocating a low amount of memory, by just allocating memory +for blocks of the array that are set. The minimum memory allocation unit is a +a block. There is a trade-off to pick up an appropriate dimension for blocks. +If it is too big, and pixels set are far from each other, too much memory will +be used. If blocks are too small, the book-keeping costs of blocks will raise. +*/ + +/** @defgroup SPARSE_ARRAY SPARSE ARRAYS - Sparse arrays */ +/*@{*/ + +/** Opaque type for sparse arrays that contain int32 values */ +typedef struct opj_sparse_array_int32 opj_sparse_array_int32_t; + +/** Creates a new sparse array. + * @param width total width of the array. + * @param height total height of the array + * @param block_width width of a block. + * @param block_height height of a block. + * @return a new sparse array instance, or NULL in case of failure. + */ +opj_sparse_array_int32_t* opj_sparse_array_int32_create(OPJ_UINT32 width, + OPJ_UINT32 height, + OPJ_UINT32 block_width, + OPJ_UINT32 block_height); + +/** Frees a sparse array. + * @param sa sparse array instance. + */ +void opj_sparse_array_int32_free(opj_sparse_array_int32_t* sa); + +/** Returns whether region bounds are valid (non empty and within array bounds) + * @param sa sparse array instance. + * @param x0 left x coordinate of the region. + * @param y0 top x coordinate of the region. + * @param x1 right x coordinate (not included) of the region. Must be greater than x0. + * @param y1 bottom y coordinate (not included) of the region. Must be greater than y0. + * @return OPJ_TRUE or OPJ_FALSE. + */ +OPJ_BOOL opj_sparse_array_is_region_valid(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1); + +/** Read the content of a rectangular region of the sparse array into a + * user buffer. + * + * Regions not written with opj_sparse_array_int32_write() are read as 0. + * + * @param sa sparse array instance. + * @param x0 left x coordinate of the region to read in the sparse array. + * @param y0 top x coordinate of the region to read in the sparse array. + * @param x1 right x coordinate (not included) of the region to read in the sparse array. Must be greater than x0. + * @param y1 bottom y coordinate (not included) of the region to read in the sparse array. Must be greater than y0. + * @param dest user buffer to fill. Must be at least sizeof(int32) * ( (y1 - y0 - 1) * dest_line_stride + (x1 - x0 - 1) * dest_col_stride + 1) bytes large. + * @param dest_col_stride spacing (in elements, not in bytes) in x dimension between consecutive elements of the user buffer. + * @param dest_line_stride spacing (in elements, not in bytes) in y dimension between consecutive elements of the user buffer. + * @param forgiving if set to TRUE and the region is invalid, OPJ_TRUE will still be returned. + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_sparse_array_int32_read(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + OPJ_INT32* dest, + OPJ_UINT32 dest_col_stride, + OPJ_UINT32 dest_line_stride, + OPJ_BOOL forgiving); + + +/** Write the content of a rectangular region into the sparse array from a + * user buffer. + * + * Blocks intersecting the region are allocated, if not already done. + * + * @param sa sparse array instance. + * @param x0 left x coordinate of the region to write into the sparse array. + * @param y0 top x coordinate of the region to write into the sparse array. + * @param x1 right x coordinate (not included) of the region to write into the sparse array. Must be greater than x0. + * @param y1 bottom y coordinate (not included) of the region to write into the sparse array. Must be greater than y0. + * @param src user buffer to fill. Must be at least sizeof(int32) * ( (y1 - y0 - 1) * src_line_stride + (x1 - x0 - 1) * src_col_stride + 1) bytes large. + * @param src_col_stride spacing (in elements, not in bytes) in x dimension between consecutive elements of the user buffer. + * @param src_line_stride spacing (in elements, not in bytes) in y dimension between consecutive elements of the user buffer. + * @param forgiving if set to TRUE and the region is invalid, OPJ_TRUE will still be returned. + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_sparse_array_int32_write(opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + const OPJ_INT32* src, + OPJ_UINT32 src_col_stride, + OPJ_UINT32 src_line_stride, + OPJ_BOOL forgiving); + +/*@}*/ + +#endif /* OPJ_SPARSE_ARRAY_H */ diff --git a/third_party/libopenjpeg20/t1.c b/third_party/libopenjpeg20/t1.c index 1ad850c77e85960232b7cad0c6793fccc0191a07..76744380f766c26ebf6ee7b4941d7f3214f495e1 100644 --- a/third_party/libopenjpeg20/t1.c +++ b/third_party/libopenjpeg20/t1.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,12 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com> + * Copyright (c) 2012, Carl Hetherington + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,250 +38,157 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define OPJ_SKIP_POISON #include "opj_includes.h" + +#ifdef __SSE__ +#include <xmmintrin.h> +#endif +#ifdef __SSE2__ +#include <emmintrin.h> +#endif + +#if defined(__GNUC__) +#pragma GCC poison malloc calloc realloc free +#endif + #include "t1_luts.h" /** @defgroup T1 T1 - Implementation of the tier-1 coding */ /*@{*/ +#define T1_FLAGS(x, y) (t1->flags[x + 1 + ((y / 4) + 1) * (t1->w+2)]) + +#define opj_t1_setcurctx(curctx, ctxno) curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] + /** @name Local static functions */ /*@{*/ -static INLINE OPJ_BYTE opj_t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient); -static OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 f); +static INLINE OPJ_BYTE opj_t1_getctxno_zc(opj_mqc_t *mqc, OPJ_UINT32 f); static INLINE OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f); -static OPJ_BYTE opj_t1_getspb(OPJ_UINT32 f); static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos); static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos); -static void opj_t1_updateflags(opj_flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride); -/** -Encode significant pass -*/ -static void opj_t1_enc_sigpass_step(opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc); +static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci, + OPJ_UINT32 s, OPJ_UINT32 stride, + OPJ_UINT32 vsc); + /** Decode significant pass */ -#if 0 -static void opj_t1_dec_sigpass_step(opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 oneplushalf, - OPJ_BYTE type, - OPJ_UINT32 vsc); -#endif static INLINE void opj_t1_dec_sigpass_step_raw( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf, - OPJ_INT32 vsc); + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 vsc, + OPJ_UINT32 row); static INLINE void opj_t1_dec_sigpass_step_mqc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf); -static INLINE void opj_t1_dec_sigpass_step_mqc_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf, - OPJ_INT32 vsc); - + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 row, + OPJ_UINT32 flags_stride, + OPJ_UINT32 vsc); /** Encode significant pass */ -static void opj_t1_enc_sigpass( opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty); +static void opj_t1_enc_sigpass(opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty); /** Decode significant pass */ static void opj_t1_dec_sigpass_raw( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient, - OPJ_INT32 cblksty); -static void opj_t1_dec_sigpass_mqc( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient); -static void opj_t1_dec_sigpass_mqc_vsc( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient); - - + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty); /** Encode refinement pass */ -static void opj_t1_enc_refpass_step(opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc); - - -/** -Encode refinement pass -*/ -static void opj_t1_enc_refpass( opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty); +static void opj_t1_enc_refpass(opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type); /** Decode refinement pass */ static void opj_t1_dec_refpass_raw( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 cblksty); -static void opj_t1_dec_refpass_mqc( - opj_t1_t *t1, - OPJ_INT32 bpno); -static void opj_t1_dec_refpass_mqc_vsc( - opj_t1_t *t1, - OPJ_INT32 bpno); + opj_t1_t *t1, + OPJ_INT32 bpno); /** Decode refinement pass */ -#if 0 -static void opj_t1_dec_refpass_step(opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_BYTE type, - OPJ_UINT32 vsc); -#endif static INLINE void opj_t1_dec_refpass_step_raw( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_INT32 vsc); + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 row); static INLINE void opj_t1_dec_refpass_step_mqc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf); -static INLINE void opj_t1_dec_refpass_step_mqc_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_INT32 vsc); - + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 row); -/** -Encode clean-up pass -*/ -static void opj_t1_enc_clnpass_step( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_UINT32 partial, - OPJ_UINT32 vsc); /** Decode clean-up pass */ -static void opj_t1_dec_clnpass_step_partial( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf); + static void opj_t1_dec_clnpass_step( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf); -static void opj_t1_dec_clnpass_step_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf, - OPJ_INT32 partial, - OPJ_INT32 vsc); + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 row, + OPJ_UINT32 vsc); + /** Encode clean-up pass */ static void opj_t1_enc_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_UINT32 cblksty); -/** -Decode clean-up pass -*/ -static void opj_t1_dec_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient, - OPJ_INT32 cblksty); + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_UINT32 cblksty); static OPJ_FLOAT64 opj_t1_getwmsedec( - OPJ_INT32 nmsedec, - OPJ_UINT32 compno, - OPJ_UINT32 level, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_UINT32 qmfbid, - OPJ_FLOAT64 stepsize, - OPJ_UINT32 numcomps, - const OPJ_FLOAT64 * mct_norms, - OPJ_UINT32 mct_numcomps); - -static void opj_t1_encode_cblk( opj_t1_t *t1, - opj_tcd_cblk_enc_t* cblk, - OPJ_UINT32 orient, - OPJ_UINT32 compno, - OPJ_UINT32 level, - OPJ_UINT32 qmfbid, - OPJ_FLOAT64 stepsize, - OPJ_UINT32 cblksty, - OPJ_UINT32 numcomps, - opj_tcd_tile_t * tile, - const OPJ_FLOAT64 * mct_norms, - OPJ_UINT32 mct_numcomps); + OPJ_INT32 nmsedec, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); + +static void opj_t1_encode_cblk(opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 cblksty, + OPJ_UINT32 numcomps, + opj_tcd_tile_t * tile, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); /** Decode 1 code-block @@ -288,16 +197,22 @@ Decode 1 code-block @param orient @param roishift Region of interest shifting value @param cblksty Code-block style +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked */ -static OPJ_BOOL opj_t1_decode_cblk( opj_t1_t *t1, - opj_tcd_cblk_dec_t* cblk, - OPJ_UINT32 orient, - OPJ_UINT32 roishift, - OPJ_UINT32 cblksty); - -static OPJ_BOOL opj_t1_allocate_buffers( opj_t1_t *t1, - OPJ_UINT32 w, - OPJ_UINT32 h); +static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); + +static OPJ_BOOL opj_t1_allocate_buffers(opj_t1_t *t1, + OPJ_UINT32 w, + OPJ_UINT32 h); /*@}*/ @@ -305,907 +220,1310 @@ static OPJ_BOOL opj_t1_allocate_buffers( opj_t1_t *t1, /* ----------------------------------------------------------------------- */ -static OPJ_BYTE opj_t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) { - return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)]; +static INLINE OPJ_BYTE opj_t1_getctxno_zc(opj_mqc_t *mqc, OPJ_UINT32 f) +{ + return mqc->lut_ctxno_zc_orient[(f & T1_SIGMA_NEIGHBOURS)]; } -static OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 f) { - return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +static INLINE OPJ_UINT32 opj_t1_getctxtno_sc_or_spb_index(OPJ_UINT32 fX, + OPJ_UINT32 pfX, + OPJ_UINT32 nfX, + OPJ_UINT32 ci) +{ + /* + 0 pfX T1_CHI_THIS T1_LUT_SGN_W + 1 tfX T1_SIGMA_1 T1_LUT_SIG_N + 2 nfX T1_CHI_THIS T1_LUT_SGN_E + 3 tfX T1_SIGMA_3 T1_LUT_SIG_W + 4 fX T1_CHI_(THIS - 1) T1_LUT_SGN_N + 5 tfX T1_SIGMA_5 T1_LUT_SIG_E + 6 fX T1_CHI_(THIS + 1) T1_LUT_SGN_S + 7 tfX T1_SIGMA_7 T1_LUT_SIG_S + */ + + OPJ_UINT32 lu = (fX >> (ci * 3U)) & (T1_SIGMA_1 | T1_SIGMA_3 | T1_SIGMA_5 | + T1_SIGMA_7); + + lu |= (pfX >> (T1_CHI_THIS_I + (ci * 3U))) & (1U << 0); + lu |= (nfX >> (T1_CHI_THIS_I - 2U + (ci * 3U))) & (1U << 2); + if (ci == 0U) { + lu |= (fX >> (T1_CHI_0_I - 4U)) & (1U << 4); + } else { + lu |= (fX >> (T1_CHI_1_I - 4U + ((ci - 1U) * 3U))) & (1U << 4); + } + lu |= (fX >> (T1_CHI_2_I - 6U + (ci * 3U))) & (1U << 6); + return lu; } -static OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f) { - OPJ_UINT32 tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG; - OPJ_UINT32 tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1; - return (tmp2); +static INLINE OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 lu) +{ + return lut_ctxno_sc[lu]; } -static OPJ_BYTE opj_t1_getspb(OPJ_UINT32 f) { - return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +static INLINE OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f) +{ + OPJ_UINT32 tmp = (f & T1_SIGMA_NEIGHBOURS) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG; + OPJ_UINT32 tmp2 = (f & T1_MU_0) ? T1_CTXNO_MAG + 2 : tmp; + return tmp2; } -static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) { - if (bitpos > 0) { - return lut_nmsedec_sig[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)]; - } - - return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +static INLINE OPJ_BYTE opj_t1_getspb(OPJ_UINT32 lu) +{ + return lut_spb[lu]; } -static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) { - if (bitpos > 0) { - return lut_nmsedec_ref[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)]; - } +static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) +{ + if (bitpos > 0) { + return lut_nmsedec_sig[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } - return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; + return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; } -static void opj_t1_updateflags(opj_flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride) { - opj_flag_t *np = flagsp - stride; - opj_flag_t *sp = flagsp + stride; +static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) +{ + if (bitpos > 0) { + return lut_nmsedec_ref[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } - static const opj_flag_t mod[] = { - T1_SIG_S, T1_SIG_S|T1_SGN_S, - T1_SIG_E, T1_SIG_E|T1_SGN_E, - T1_SIG_W, T1_SIG_W|T1_SGN_W, - T1_SIG_N, T1_SIG_N|T1_SGN_N - }; + return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} - np[-1] |= T1_SIG_SE; - np[0] |= mod[s]; - np[1] |= T1_SIG_SW; +#define opj_t1_update_flags_macro(flags, flagsp, ci, s, stride, vsc) \ +{ \ + /* east */ \ + flagsp[-1] |= T1_SIGMA_5 << (3U * ci); \ + \ + /* mark target as significant */ \ + flags |= ((s << T1_CHI_1_I) | T1_SIGMA_4) << (3U * ci); \ + \ + /* west */ \ + flagsp[1] |= T1_SIGMA_3 << (3U * ci); \ + \ + /* north-west, north, north-east */ \ + if (ci == 0U && !(vsc)) { \ + opj_flag_t* north = flagsp - (stride); \ + *north |= (s << T1_CHI_5_I) | T1_SIGMA_16; \ + north[-1] |= T1_SIGMA_17; \ + north[1] |= T1_SIGMA_15; \ + } \ + \ + /* south-west, south, south-east */ \ + if (ci == 3U) { \ + opj_flag_t* south = flagsp + (stride); \ + *south |= (s << T1_CHI_0_I) | T1_SIGMA_1; \ + south[-1] |= T1_SIGMA_2; \ + south[1] |= T1_SIGMA_0; \ + } \ +} - flagsp[-1] |= mod[s+2]; - flagsp[0] |= T1_SIG; - flagsp[1] |= mod[s+4]; - sp[-1] |= T1_SIG_NE; - sp[0] |= mod[s+6]; - sp[1] |= T1_SIG_NW; +static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci, + OPJ_UINT32 s, OPJ_UINT32 stride, + OPJ_UINT32 vsc) +{ + opj_t1_update_flags_macro(*flagsp, flagsp, ci, s, stride, vsc); } -static void opj_t1_enc_sigpass_step( opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc - ) +/** +Encode significant pass +*/ +static INLINE void opj_t1_enc_sigpass_step(opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 ci, + OPJ_UINT32 vsc) { - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? (OPJ_UINT32)((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (OPJ_UINT32)(*flagsp); - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - v = opj_int_abs(*datap) & one ? 1 : 0; - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc(flag, orient)); /* ESSAI */ - if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ - opj_mqc_bypass_enc(mqc, (OPJ_UINT32)v); - } else { - opj_mqc_encode(mqc, (OPJ_UINT32)v); - } - if (v) { - v = *datap < 0 ? 1 : 0; - *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno)); - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag)); /* ESSAI */ - if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ - opj_mqc_bypass_enc(mqc, (OPJ_UINT32)v); - } else { - opj_mqc_encode(mqc, (OPJ_UINT32)(v ^ opj_t1_getspb((OPJ_UINT32)flag))); - } - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - *flagsp |= T1_VISIT; - } -} + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + OPJ_UINT32 const flags = *flagsp; + + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); + v = (opj_int_abs(*datap) & one) ? 1 : 0; +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " ctxt1=%d\n", ctxt1); +#endif + opj_mqc_setcurctx(mqc, ctxt1); + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + opj_mqc_bypass_enc(mqc, v); + } else { + opj_mqc_encode(mqc, v); + } + if (v) { + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( + *flagsp, + flagsp[-1], flagsp[1], + ci); + OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); + v = *datap < 0 ? 1U : 0U; + *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), + (OPJ_UINT32)bpno); +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " ctxt2=%d\n", ctxt2); +#endif + opj_mqc_setcurctx(mqc, ctxt2); + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + opj_mqc_bypass_enc(mqc, v); + } else { + OPJ_UINT32 spb = opj_t1_getspb(lu); +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " spb=%d\n", spb); +#endif + opj_mqc_encode(mqc, v ^ spb); + } + opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); + } + *flagsp |= T1_PI_THIS << (ci * 3U); + } +} static INLINE void opj_t1_dec_sigpass_step_raw( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf, - OPJ_INT32 vsc) + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 vsc, + OPJ_UINT32 ci) { - OPJ_INT32 v, flag; - opj_raw_t *raw = t1->raw; /* RAW component */ - OPJ_ARG_NOT_USED(orient); - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - if (opj_raw_decode(raw)) { - v = (OPJ_INT32)opj_raw_decode(raw); /* ESSAI */ - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - *flagsp |= T1_VISIT; + OPJ_UINT32 v; + opj_mqc_t *mqc = &(t1->mqc); /* RAW component */ + + OPJ_UINT32 const flags = *flagsp; + + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { + if (opj_mqc_raw_decode(mqc)) { + v = opj_mqc_raw_decode(mqc); + *datap = v ? -oneplushalf : oneplushalf; + opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); } -} + *flagsp |= T1_PI_THIS << (ci * 3U); + } +} + +#define opj_t1_dec_sigpass_step_mqc_macro(flags, flagsp, flags_stride, data, \ + data_stride, ci, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc) \ +{ \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && \ + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt1); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if (v) { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + flags, \ + flagsp[-1], flagsp[1], \ + ci); \ + OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); \ + OPJ_UINT32 spb = opj_t1_getspb(lu); \ + opj_t1_setcurctx(curctx, ctxt2); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + v = v ^ spb; \ + data[ci*data_stride] = v ? -oneplushalf : oneplushalf; \ + opj_t1_update_flags_macro(flags, flagsp, ci, v, flags_stride, vsc); \ + } \ + flags |= T1_PI_THIS << (ci * 3U); \ + } \ +} static INLINE void opj_t1_dec_sigpass_step_mqc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf) + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 ci, + OPJ_UINT32 flags_stride, + OPJ_UINT32 vsc) { - OPJ_INT32 v, flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = *flagsp; - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc((OPJ_UINT32)flag, (OPJ_UINT32)orient)); - if (opj_mqc_decode(mqc)) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc((OPJ_UINT32)flag)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb((OPJ_UINT32)flag); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - *flagsp |= T1_VISIT; + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + opj_t1_dec_sigpass_step_mqc_macro(*flagsp, flagsp, flags_stride, datap, + 0, ci, mqc, mqc->curctx, + v, mqc->a, mqc->c, mqc->ct, oneplushalf, vsc); +} + +static void opj_t1_enc_sigpass(opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty + ) +{ + OPJ_UINT32 i, k; + OPJ_INT32 const one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + opj_flag_t* f = &T1_FLAGS(0, 0); + OPJ_UINT32 const extra = 2; + + *nmsedec = 0; +#ifdef DEBUG_ENC_SIG + fprintf(stderr, "enc_sigpass: bpno=%d\n", bpno); +#endif + for (k = 0; k < (t1->h & ~3U); k += 4) { +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i) { +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " i=%d\n", i); +#endif + if (*f == 0U) { + /* Nothing to do for any of the 4 data points */ + f++; + continue; + } + opj_t1_enc_sigpass_step( + t1, + f, + &t1->data[((k + 0) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 0, cblksty & J2K_CCP_CBLKSTY_VSC); + opj_t1_enc_sigpass_step( + t1, + f, + &t1->data[((k + 1) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 1, 0); + opj_t1_enc_sigpass_step( + t1, + f, + &t1->data[((k + 2) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 2, 0); + opj_t1_enc_sigpass_step( + t1, + f, + &t1->data[((k + 3) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 3, 0); + ++f; + } + f += extra; + } + + if (k < t1->h) { + OPJ_UINT32 j; +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i) { +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " i=%d\n", i); +#endif + if (*f == 0U) { + /* Nothing to do for any of the 4 data points */ + f++; + continue; + } + for (j = k; j < t1->h; ++j) { + opj_t1_enc_sigpass_step( + t1, + f, + &t1->data[(j * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + j - k, + (j == k && (cblksty & J2K_CCP_CBLKSTY_VSC) != 0)); + } + ++f; } -} /* VSC and BYPASS by Antonin */ - -static INLINE void opj_t1_dec_sigpass_step_mqc_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf, - OPJ_INT32 vsc) + } +} + +static void opj_t1_dec_sigpass_raw( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) { - OPJ_INT32 v, flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc((OPJ_UINT32)flag, (OPJ_UINT32)orient)); - if (opj_mqc_decode(mqc)) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc((OPJ_UINT32)flag)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb((OPJ_UINT32)flag); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - *flagsp |= T1_VISIT; + OPJ_INT32 one, half, oneplushalf; + OPJ_UINT32 i, j, k; + OPJ_INT32 *data = t1->data; + opj_flag_t *flagsp = &T1_FLAGS(0, 0); + const OPJ_UINT32 l_w = t1->w; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + + for (k = 0; k < (t1->h & ~3U); k += 4, flagsp += 2, data += 3 * l_w) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + opj_flag_t flags = *flagsp; + if (flags != 0) { + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data, + oneplushalf, + cblksty & J2K_CCP_CBLKSTY_VSC, /* vsc */ + 0U); + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + l_w, + oneplushalf, + OPJ_FALSE, /* vsc */ + 1U); + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + 2 * l_w, + oneplushalf, + OPJ_FALSE, /* vsc */ + 2U); + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + 3 * l_w, + oneplushalf, + OPJ_FALSE, /* vsc */ + 3U); + } + } + } + if (k < t1->h) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + for (j = 0; j < t1->h - k; ++j) { + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + j * l_w, + oneplushalf, + cblksty & J2K_CCP_CBLKSTY_VSC, /* vsc */ + j); + } } -} /* VSC and BYPASS by Antonin */ + } +} +#define opj_t1_dec_sigpass_mqc_internal(t1, bpno, vsc, w, h, flags_stride) \ +{ \ + OPJ_INT32 one, half, oneplushalf; \ + OPJ_UINT32 i, j, k; \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[(flags_stride) + 1]; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + register OPJ_UINT32 v; \ + one = 1 << bpno; \ + half = one >> 1; \ + oneplushalf = one | half; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if( flags != 0 ) { \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, v, a, c, ct, oneplushalf, vsc); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + *flagsp = flags; \ + } \ + } \ + } \ + UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_sigpass_step_mqc(t1, flagsp, \ + data + j * l_w, oneplushalf, j, flags_stride, vsc); \ + } \ + } \ + } \ +} +static void opj_t1_dec_sigpass_mqc_64x64_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_FALSE, 64, 64, 66); +} -static void opj_t1_enc_sigpass(opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty - ) +static void opj_t1_dec_sigpass_mqc_64x64_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_UINT32 i, j, k, vsc; - OPJ_INT32 one; - - *nmsedec = 0; - one = 1 << (bpno + T1_NMSEDEC_FRACBITS); - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - opj_t1_enc_sigpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->data_stride) + i], - orient, - bpno, - one, - nmsedec, - type, - vsc); - } - } - } + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_TRUE, 64, 64, 66); } -static void opj_t1_dec_sigpass_raw( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient, - OPJ_INT32 cblksty) +static void opj_t1_dec_sigpass_mqc_generic_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_INT32 one, half, oneplushalf, vsc; - OPJ_UINT32 i, j, k; - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - opj_t1_dec_sigpass_step_raw( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - oneplushalf, - vsc); - } - } - } -} /* VSC and BYPASS by Antonin */ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_FALSE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_sigpass_mqc_generic_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_TRUE, t1->w, t1->h, + t1->w + 2U); +} static void opj_t1_dec_sigpass_mqc( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient) + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) { - OPJ_INT32 one, half, oneplushalf; - OPJ_UINT32 i, j, k; - OPJ_INT32 *data1 = t1->data; - opj_flag_t *flags1 = &t1->flags[1]; - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - for (k = 0; k < (t1->h & ~3u); k += 4) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_flag_t *flags2 = flags1 + i; - flags2 += t1->flags_stride; - opj_t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - } - data1 += t1->w << 2; - flags1 += t1->flags_stride << 2; + if (t1->w == 64 && t1->h == 64) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_sigpass_mqc_64x64_vsc(t1, bpno); + } else { + opj_t1_dec_sigpass_mqc_64x64_novsc(t1, bpno); } - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_flag_t *flags2 = flags1 + i; - for (j = k; j < t1->h; ++j) { - flags2 += t1->flags_stride; - opj_t1_dec_sigpass_step_mqc(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - } + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_sigpass_mqc_generic_vsc(t1, bpno); + } else { + opj_t1_dec_sigpass_mqc_generic_novsc(t1, bpno); } -} /* VSC and BYPASS by Antonin */ + } +} -static void opj_t1_dec_sigpass_mqc_vsc( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient) +/** +Encode refinement pass step +*/ +static INLINE void opj_t1_enc_refpass_step(opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 ci) { - OPJ_INT32 one, half, oneplushalf, vsc; - OPJ_UINT32 i, j, k; - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = (j == k + 3 || j == t1->h - 1) ? 1 : 0; - opj_t1_dec_sigpass_step_mqc_vsc( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - oneplushalf, - vsc); - } - } - } -} /* VSC and BYPASS by Antonin */ + OPJ_UINT32 v; + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + OPJ_UINT32 const shift_flags = + (*flagsp >> (ci * 3U)); -static void opj_t1_enc_refpass_step( opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc) -{ - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? (OPJ_UINT32)((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (OPJ_UINT32)(*flagsp); - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - *nmsedec += opj_t1_getnmsedec_ref((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno)); - v = opj_int_abs(*datap) & one ? 1 : 0; - opj_mqc_setcurctx(mqc, opj_t1_getctxno_mag(flag)); /* ESSAI */ - if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ - opj_mqc_bypass_enc(mqc, (OPJ_UINT32)v); - } else { - opj_mqc_encode(mqc, (OPJ_UINT32)v); - } - *flagsp |= T1_REFINE; - } + if ((shift_flags & (T1_SIGMA_THIS | T1_PI_THIS)) == T1_SIGMA_THIS) { + OPJ_UINT32 ctxt = opj_t1_getctxno_mag(shift_flags); + *nmsedec += opj_t1_getnmsedec_ref((OPJ_UINT32)opj_int_abs(*datap), + (OPJ_UINT32)bpno); + v = (opj_int_abs(*datap) & one) ? 1 : 0; +#ifdef DEBUG_ENC_REF + fprintf(stderr, " ctxt=%d\n", ctxt); +#endif + opj_mqc_setcurctx(mqc, ctxt); + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + opj_mqc_bypass_enc(mqc, v); + } else { + opj_mqc_encode(mqc, v); + } + *flagsp |= T1_MU_THIS << (ci * 3U); + } } + static INLINE void opj_t1_dec_refpass_step_raw( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_INT32 vsc) + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 ci) { - OPJ_INT32 v, t, flag; - - opj_raw_t *raw = t1->raw; /* RAW component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - v = (OPJ_INT32)opj_raw_decode(raw); - t = v ? poshalf : neghalf; - *datap += *datap < 0 ? -t : t; - *flagsp |= T1_REFINE; - } -} /* VSC and BYPASS by Antonin */ + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* RAW component */ + + if ((*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == + (T1_SIGMA_THIS << (ci * 3U))) { + v = opj_mqc_raw_decode(mqc); + *datap += (v ^ (*datap < 0)) ? poshalf : -poshalf; + *flagsp |= T1_MU_THIS << (ci * 3U); + } +} + +#define opj_t1_dec_refpass_step_mqc_macro(flags, data, data_stride, ci, \ + mqc, curctx, v, a, c, ct, poshalf) \ +{ \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == \ + (T1_SIGMA_THIS << (ci * 3U))) { \ + OPJ_UINT32 ctxt = opj_t1_getctxno_mag(flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + data[ci*data_stride] += (v ^ (data[ci*data_stride] < 0)) ? poshalf : -poshalf; \ + flags |= T1_MU_THIS << (ci * 3U); \ + } \ +} static INLINE void opj_t1_dec_refpass_step_mqc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf) -{ - OPJ_INT32 v, t, flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = *flagsp; - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_mag((OPJ_UINT32)flag)); /* ESSAI */ - v = opj_mqc_decode(mqc); - t = v ? poshalf : neghalf; - *datap += *datap < 0 ? -t : t; - *flagsp |= T1_REFINE; - } -} /* VSC and BYPASS by Antonin */ - -static INLINE void opj_t1_dec_refpass_step_mqc_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_INT32 vsc) + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 ci) { - OPJ_INT32 v, t, flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_mag((OPJ_UINT32)flag)); /* ESSAI */ - v = opj_mqc_decode(mqc); - t = v ? poshalf : neghalf; - *datap += *datap < 0 ? -t : t; - *flagsp |= T1_REFINE; - } -} /* VSC and BYPASS by Antonin */ + OPJ_UINT32 v; + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + opj_t1_dec_refpass_step_mqc_macro(*flagsp, datap, 0, ci, + mqc, mqc->curctx, v, mqc->a, mqc->c, + mqc->ct, poshalf); +} static void opj_t1_enc_refpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty) + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type) { - OPJ_UINT32 i, j, k, vsc; - OPJ_INT32 one; - - *nmsedec = 0; - one = 1 << (bpno + T1_NMSEDEC_FRACBITS); - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - opj_t1_enc_refpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->data_stride) + i], - bpno, - one, - nmsedec, - type, - vsc); - } - } - } + OPJ_UINT32 i, k; + const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + opj_flag_t* f = &T1_FLAGS(0, 0); + const OPJ_UINT32 extra = 2U; + + *nmsedec = 0; +#ifdef DEBUG_ENC_REF + fprintf(stderr, "enc_refpass: bpno=%d\n", bpno); +#endif + for (k = 0; k < (t1->h & ~3U); k += 4) { +#ifdef DEBUG_ENC_REF + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i) { +#ifdef DEBUG_ENC_REF + fprintf(stderr, " i=%d\n", i); +#endif + if ((*f & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) { + /* none significant */ + f++; + continue; + } + if ((*f & (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) == + (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) { + /* all processed by sigpass */ + f++; + continue; + } + + opj_t1_enc_refpass_step( + t1, + f, + &t1->data[((k + 0) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 0); + opj_t1_enc_refpass_step( + t1, + f, + &t1->data[((k + 1) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 1); + opj_t1_enc_refpass_step( + t1, + f, + &t1->data[((k + 2) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 2); + opj_t1_enc_refpass_step( + t1, + f, + &t1->data[((k + 3) * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + 3); + ++f; + } + f += extra; + } + + if (k < t1->h) { + OPJ_UINT32 j; +#ifdef DEBUG_ENC_REF + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i) { +#ifdef DEBUG_ENC_REF + fprintf(stderr, " i=%d\n", i); +#endif + if ((*f & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) { + /* none significant */ + f++; + continue; + } + for (j = k; j < t1->h; ++j) { + opj_t1_enc_refpass_step( + t1, + f, + &t1->data[(j * t1->data_stride) + i], + bpno, + one, + nmsedec, + type, + j - k); + } + ++f; + } + } } + static void opj_t1_dec_refpass_raw( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 cblksty) + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_INT32 one, poshalf, neghalf; - OPJ_UINT32 i, j, k; - OPJ_INT32 vsc; - one = 1 << bpno; - poshalf = one >> 1; - neghalf = bpno > 0 ? -poshalf : -1; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - opj_t1_dec_refpass_step_raw( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - poshalf, - neghalf, - vsc); - } - } + OPJ_INT32 one, poshalf; + OPJ_UINT32 i, j, k; + OPJ_INT32 *data = t1->data; + opj_flag_t *flagsp = &T1_FLAGS(0, 0); + const OPJ_UINT32 l_w = t1->w; + one = 1 << bpno; + poshalf = one >> 1; + for (k = 0; k < (t1->h & ~3U); k += 4, flagsp += 2, data += 3 * l_w) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + opj_flag_t flags = *flagsp; + if (flags != 0) { + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data, + poshalf, + 0U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + l_w, + poshalf, + 1U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + 2 * l_w, + poshalf, + 2U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + 3 * l_w, + poshalf, + 3U); + } + } + } + if (k < t1->h) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + for (j = 0; j < t1->h - k; ++j) { + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + j * l_w, + poshalf, + j); + } } -} /* VSC and BYPASS by Antonin */ + } +} + +#define opj_t1_dec_refpass_mqc_internal(t1, bpno, w, h, flags_stride) \ +{ \ + OPJ_INT32 one, poshalf; \ + OPJ_UINT32 i, j, k; \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + register OPJ_UINT32 v; \ + one = 1 << bpno; \ + poshalf = one >> 1; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if( flags != 0 ) { \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 0, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 1, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 2, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 3, \ + mqc, curctx, v, a, c, ct, poshalf); \ + *flagsp = flags; \ + } \ + } \ + } \ + UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_refpass_step_mqc(t1, flagsp, data + j * l_w, poshalf, j); \ + } \ + } \ + } \ +} + +static void opj_t1_dec_refpass_mqc_64x64( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_refpass_mqc_internal(t1, bpno, 64, 64, 66); +} + +static void opj_t1_dec_refpass_mqc_generic( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_refpass_mqc_internal(t1, bpno, t1->w, t1->h, t1->w + 2U); +} static void opj_t1_dec_refpass_mqc( - opj_t1_t *t1, - OPJ_INT32 bpno) + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_INT32 one, poshalf, neghalf; - OPJ_UINT32 i, j, k; - OPJ_INT32 *data1 = t1->data; - opj_flag_t *flags1 = &t1->flags[1]; - one = 1 << bpno; - poshalf = one >> 1; - neghalf = bpno > 0 ? -poshalf : -1; - for (k = 0; k < (t1->h & ~3u); k += 4) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_flag_t *flags2 = flags1 + i; - flags2 += t1->flags_stride; - opj_t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); - data2 += t1->w; - } - data1 += t1->w << 2; - flags1 += t1->flags_stride << 2; + if (t1->w == 64 && t1->h == 64) { + opj_t1_dec_refpass_mqc_64x64(t1, bpno); + } else { + opj_t1_dec_refpass_mqc_generic(t1, bpno); + } +} + +/** +Encode clean-up pass step +*/ +static void opj_t1_enc_clnpass_step( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_UINT32 agg, + OPJ_UINT32 runlen, + OPJ_UINT32 lim, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 v; + OPJ_UINT32 ci; + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + + const OPJ_UINT32 check = (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13 | + T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); + + if ((*flagsp & check) == check) { + if (runlen == 0) { + *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); + } else if (runlen == 1) { + *flagsp &= ~(T1_PI_1 | T1_PI_2 | T1_PI_3); + } else if (runlen == 2) { + *flagsp &= ~(T1_PI_2 | T1_PI_3); + } else if (runlen == 3) { + *flagsp &= ~(T1_PI_3); } - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_flag_t *flags2 = flags1 + i; - for (j = k; j < t1->h; ++j) { - flags2 += t1->flags_stride; - opj_t1_dec_refpass_step_mqc(t1, flags2, data2, poshalf, neghalf); - data2 += t1->w; - } + return; + } + + for (ci = runlen; ci < lim; ++ci) { + OPJ_UINT32 vsc; + opj_flag_t flags; + OPJ_UINT32 ctxt1; + + flags = *flagsp; + + if ((agg != 0) && (ci == runlen)) { + goto LABEL_PARTIAL; + } + + if (!(flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) { + ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); +#ifdef DEBUG_ENC_CLN + printf(" ctxt1=%d\n", ctxt1); +#endif + opj_mqc_setcurctx(mqc, ctxt1); + v = (opj_int_abs(*datap) & one) ? 1 : 0; + opj_mqc_encode(mqc, v); + if (v) { + OPJ_UINT32 ctxt2, spb; + OPJ_UINT32 lu; +LABEL_PARTIAL: + lu = opj_t1_getctxtno_sc_or_spb_index( + *flagsp, + flagsp[-1], flagsp[1], + ci); + *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), + (OPJ_UINT32)bpno); + ctxt2 = opj_t1_getctxno_sc(lu); +#ifdef DEBUG_ENC_CLN + printf(" ctxt2=%d\n", ctxt2); +#endif + opj_mqc_setcurctx(mqc, ctxt2); + + v = *datap < 0 ? 1U : 0U; + spb = opj_t1_getspb(lu); +#ifdef DEBUG_ENC_CLN + printf(" spb=%d\n", spb); +#endif + opj_mqc_encode(mqc, v ^ spb); + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (ci == 0)) ? 1 : 0; + opj_t1_update_flags(flagsp, ci, v, t1->w + 2U, vsc); + } } -} /* VSC and BYPASS by Antonin */ + *flagsp &= ~(T1_PI_THIS << (3U * ci)); + datap += t1->data_stride; + } +} -static void opj_t1_dec_refpass_mqc_vsc( - opj_t1_t *t1, - OPJ_INT32 bpno) +#define opj_t1_dec_clnpass_step_macro(check_flags, partial, \ + flags, flagsp, flags_stride, data, \ + data_stride, ci, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc) \ +{ \ + if ( !check_flags || !(flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) {\ + do { \ + if( !partial ) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt1); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if( !v ) \ + break; \ + } \ + { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + flags, flagsp[-1], flagsp[1], \ + ci); \ + opj_t1_setcurctx(curctx, opj_t1_getctxno_sc(lu)); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + v = v ^ opj_t1_getspb(lu); \ + data[ci*data_stride] = v ? -oneplushalf : oneplushalf; \ + opj_t1_update_flags_macro(flags, flagsp, ci, v, flags_stride, vsc); \ + } \ + } while(0); \ + } \ +} + +static void opj_t1_dec_clnpass_step( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 ci, + OPJ_UINT32 vsc) { - OPJ_INT32 one, poshalf, neghalf; - OPJ_UINT32 i, j, k; - OPJ_INT32 vsc; - one = 1 << bpno; - poshalf = one >> 1; - neghalf = bpno > 0 ? -poshalf : -1; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((j == k + 3 || j == t1->h - 1)) ? 1 : 0; - opj_t1_dec_refpass_step_mqc_vsc( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - poshalf, - neghalf, - vsc); - } + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, + *flagsp, flagsp, t1->w + 2U, datap, + 0, ci, mqc, mqc->curctx, + v, mqc->a, mqc->c, mqc->ct, oneplushalf, vsc); +} + +static void opj_t1_enc_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, k; + const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + OPJ_UINT32 agg, runlen; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + + *nmsedec = 0; +#ifdef DEBUG_ENC_CLN + printf("enc_clnpass: bpno=%d\n", bpno); +#endif + for (k = 0; k < (t1->h & ~3U); k += 4) { +#ifdef DEBUG_ENC_CLN + printf(" k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i) { +#ifdef DEBUG_ENC_CLN + printf(" i=%d\n", i); +#endif + agg = !(T1_FLAGS(i, k)); +#ifdef DEBUG_ENC_CLN + printf(" agg=%d\n", agg); +#endif + if (agg) { + for (runlen = 0; runlen < 4; ++runlen) { + if (opj_int_abs(t1->data[((k + runlen)*t1->data_stride) + i]) & one) { + break; + } + } + opj_mqc_setcurctx(mqc, T1_CTXNO_AGG); + opj_mqc_encode(mqc, runlen != 4); + if (runlen == 4) { + continue; } + opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); + opj_mqc_encode(mqc, runlen >> 1); + opj_mqc_encode(mqc, runlen & 1); + } else { + runlen = 0; + } + opj_t1_enc_clnpass_step( + t1, + &T1_FLAGS(i, k), + &t1->data[((k + runlen) * t1->data_stride) + i], + bpno, + one, + nmsedec, + agg, + runlen, + 4U, + cblksty); + } + } + if (k < t1->h) { + agg = 0; + runlen = 0; +#ifdef DEBUG_ENC_CLN + printf(" k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i) { +#ifdef DEBUG_ENC_CLN + printf(" i=%d\n", i); + printf(" agg=%d\n", agg); +#endif + opj_t1_enc_clnpass_step( + t1, + &T1_FLAGS(i, k), + &t1->data[((k + runlen) * t1->data_stride) + i], + bpno, + one, + nmsedec, + agg, + runlen, + t1->h - k, + cblksty); } -} /* VSC and BYPASS by Antonin */ + } +} +#define opj_t1_dec_clnpass_internal(t1, bpno, vsc, w, h, flags_stride) \ +{ \ + OPJ_INT32 one, half, oneplushalf; \ + OPJ_UINT32 runlen; \ + OPJ_UINT32 i, j, k; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + register OPJ_UINT32 v; \ + one = 1 << bpno; \ + half = one >> 1; \ + oneplushalf = one | half; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if (flags == 0) { \ + OPJ_UINT32 partial = OPJ_TRUE; \ + opj_t1_setcurctx(curctx, T1_CTXNO_AGG); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if (!v) { \ + continue; \ + } \ + opj_t1_setcurctx(curctx, T1_CTXNO_UNI); \ + opj_mqc_decode_macro(runlen, mqc, curctx, a, c, ct); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + runlen = (runlen << 1) | v; \ + switch(runlen) { \ + case 0: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, OPJ_TRUE,\ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 1: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 2: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 3: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + break; \ + } \ + } else { \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + } \ + *flagsp = flags & ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + } \ + } \ + UPLOAD_MQC_VARIABLES(mqc, curctx, c, a, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_clnpass_step(t1, flagsp, data + j * l_w, oneplushalf, j, vsc); \ + } \ + *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + } \ + } \ +} -static void opj_t1_enc_clnpass_step( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_UINT32 partial, - OPJ_UINT32 vsc) +static void opj_t1_dec_clnpass_check_segsym(opj_t1_t *t1, OPJ_INT32 cblksty) { - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? (OPJ_UINT32)((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (OPJ_UINT32)(*flagsp); - if (partial) { - goto LABEL_PARTIAL; - } - if (!(*flagsp & (T1_SIG | T1_VISIT))) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc(flag, orient)); - v = opj_int_abs(*datap) & one ? 1 : 0; - opj_mqc_encode(mqc, (OPJ_UINT32)v); - if (v) { -LABEL_PARTIAL: - *nmsedec += opj_t1_getnmsedec_sig((OPJ_UINT32)opj_int_abs(*datap), (OPJ_UINT32)(bpno)); - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag)); - v = *datap < 0 ? 1 : 0; - opj_mqc_encode(mqc, (OPJ_UINT32)(v ^ opj_t1_getspb((OPJ_UINT32)flag))); - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - } - *flagsp &= ~T1_VISIT; + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) { + opj_mqc_t* mqc = &(t1->mqc); + OPJ_UINT32 v, v2; + opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); + opj_mqc_decode(v, mqc); + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + /* + if (v!=0xa) { + opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); + } + */ + } } -static void opj_t1_dec_clnpass_step_partial( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf) +static void opj_t1_dec_clnpass_64x64_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_INT32 v, flag; - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - OPJ_ARG_NOT_USED(orient); - - flag = *flagsp; - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc((OPJ_UINT32)flag)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb((OPJ_UINT32)flag); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - *flagsp &= ~T1_VISIT; -} /* VSC and BYPASS by Antonin */ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_FALSE, 64, 64, 66); +} -static void opj_t1_dec_clnpass_step( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf) +static void opj_t1_dec_clnpass_64x64_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_INT32 v, flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = *flagsp; - if (!(flag & (T1_SIG | T1_VISIT))) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc((OPJ_UINT32)flag, (OPJ_UINT32)orient)); - if (opj_mqc_decode(mqc)) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc((OPJ_UINT32)flag)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb((OPJ_UINT32)flag); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - } - *flagsp &= ~T1_VISIT; -} /* VSC and BYPASS by Antonin */ - -static void opj_t1_dec_clnpass_step_vsc( - opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 orient, - OPJ_INT32 oneplushalf, - OPJ_INT32 partial, - OPJ_INT32 vsc) + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_TRUE, 64, 64, 66); +} + +static void opj_t1_dec_clnpass_generic_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_INT32 v, flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if (partial) { - goto LABEL_PARTIAL; - } - if (!(flag & (T1_SIG | T1_VISIT))) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc((OPJ_UINT32)flag, (OPJ_UINT32)orient)); - if (opj_mqc_decode(mqc)) { -LABEL_PARTIAL: - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc((OPJ_UINT32)flag)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb((OPJ_UINT32)flag); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, (OPJ_UINT32)v, t1->flags_stride); - } - } - *flagsp &= ~T1_VISIT; + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_FALSE, t1->w, t1->h, + t1->w + 2U); } -static void opj_t1_enc_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_UINT32 cblksty) +static void opj_t1_dec_clnpass_generic_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) { - OPJ_UINT32 i, j, k; - OPJ_INT32 one; - OPJ_UINT32 agg, runlen, vsc; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - *nmsedec = 0; - one = 1 << (bpno + T1_NMSEDEC_FRACBITS); - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - if (k + 3 < t1->h) { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || (MACRO_t1_flags(1 + k + 3,1 + i) - & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } else { - agg = !((MACRO_t1_flags(1 + k,1 + i) | - MACRO_t1_flags(1 + k + 1,1 + i) | - MACRO_t1_flags(1 + k + 2,1 + i) | - MACRO_t1_flags(1 + k + 3,1 + i)) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } - } else { - agg = 0; - } - if (agg) { - for (runlen = 0; runlen < 4; ++runlen) { - if (opj_int_abs(t1->data[((k + runlen)*t1->data_stride) + i]) & one) - break; - } - opj_mqc_setcurctx(mqc, T1_CTXNO_AGG); - opj_mqc_encode(mqc, runlen != 4); - if (runlen == 4) { - continue; - } - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); - opj_mqc_encode(mqc, runlen >> 1); - opj_mqc_encode(mqc, runlen & 1); - } else { - runlen = 0; - } - for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - opj_t1_enc_clnpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->data_stride) + i], - orient, - bpno, - one, - nmsedec, - agg && (j == k + runlen), - vsc); - } - } - } + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_TRUE, t1->w, t1->h, + t1->w + 2U); } static void opj_t1_dec_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 orient, - OPJ_INT32 cblksty) + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) { - OPJ_INT32 one, half, oneplushalf, agg, runlen, vsc; - OPJ_UINT32 i, j, k; - OPJ_INT32 segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - if (k + 3 < t1->h) { - agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || (MACRO_t1_flags(1 + k + 3,1 + i) - & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } else { - agg = 0; - } - if (agg) { - opj_mqc_setcurctx(mqc, T1_CTXNO_AGG); - if (!opj_mqc_decode(mqc)) { - continue; - } - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); - runlen = opj_mqc_decode(mqc); - runlen = (runlen << 1) | opj_mqc_decode(mqc); - } else { - runlen = 0; - } - for (j = k + (OPJ_UINT32)runlen; j < k + 4 && j < t1->h; ++j) { - vsc = (j == k + 3 || j == t1->h - 1) ? 1 : 0; - opj_t1_dec_clnpass_step_vsc( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - oneplushalf, - agg && (j == k + (OPJ_UINT32)runlen), - vsc); - } - } - } - } else { - OPJ_INT32 *data1 = t1->data; - opj_flag_t *flags1 = &t1->flags[1]; - for (k = 0; k < (t1->h & ~3u); k += 4) { - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_flag_t *flags2 = flags1 + i; - agg = !((MACRO_t1_flags(1 + k, 1 + i) | - MACRO_t1_flags(1 + k + 1, 1 + i) | - MACRO_t1_flags(1 + k + 2, 1 + i) | - MACRO_t1_flags(1 + k + 3, 1 + i)) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - if (agg) { - opj_mqc_setcurctx(mqc, T1_CTXNO_AGG); - if (!opj_mqc_decode(mqc)) { - continue; - } - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); - runlen = opj_mqc_decode(mqc); - runlen = (runlen << 1) | opj_mqc_decode(mqc); - flags2 += (OPJ_UINT32)runlen * t1->flags_stride; - data2 += (OPJ_UINT32)runlen * t1->w; - for (j = (OPJ_UINT32)runlen; j < 4 && j < t1->h; ++j) { - flags2 += t1->flags_stride; - if (agg && (j == (OPJ_UINT32)runlen)) { - opj_t1_dec_clnpass_step_partial(t1, flags2, data2, orient, oneplushalf); - } else { - opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); - } - data2 += t1->w; - } - } else { - flags2 += t1->flags_stride; - opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - flags2 += t1->flags_stride; - opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - } - } - data1 += t1->w << 2; - flags1 += t1->flags_stride << 2; - } - for (i = 0; i < t1->w; ++i) { - OPJ_INT32 *data2 = data1 + i; - opj_flag_t *flags2 = flags1 + i; - for (j = k; j < t1->h; ++j) { - flags2 += t1->flags_stride; - opj_t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf); - data2 += t1->w; - } - } - } - - if (segsym) { - OPJ_INT32 v = 0; - opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); - v = opj_mqc_decode(mqc); - v = (v << 1) | opj_mqc_decode(mqc); - v = (v << 1) | opj_mqc_decode(mqc); - v = (v << 1) | opj_mqc_decode(mqc); - /* - if (v!=0xa) { - opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); - } - */ - } -} /* VSC and BYPASS by Antonin */ + if (t1->w == 64 && t1->h == 64) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_clnpass_64x64_vsc(t1, bpno); + } else { + opj_t1_dec_clnpass_64x64_novsc(t1, bpno); + } + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_clnpass_generic_vsc(t1, bpno); + } else { + opj_t1_dec_clnpass_generic_novsc(t1, bpno); + } + } + opj_t1_dec_clnpass_check_segsym(t1, cblksty); +} /** mod fixed_quality */ static OPJ_FLOAT64 opj_t1_getwmsedec( - OPJ_INT32 nmsedec, - OPJ_UINT32 compno, - OPJ_UINT32 level, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_UINT32 qmfbid, - OPJ_FLOAT64 stepsize, - OPJ_UINT32 numcomps, - const OPJ_FLOAT64 * mct_norms, - OPJ_UINT32 mct_numcomps) + OPJ_INT32 nmsedec, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps) { - OPJ_FLOAT64 w1 = 1, w2, wmsedec; - OPJ_ARG_NOT_USED(numcomps); + OPJ_FLOAT64 w1 = 1, w2, wmsedec; + OPJ_ARG_NOT_USED(numcomps); - if (mct_norms && (compno < mct_numcomps)) { - w1 = mct_norms[compno]; - } + if (mct_norms && (compno < mct_numcomps)) { + w1 = mct_norms[compno]; + } - if (qmfbid == 1) { - w2 = opj_dwt_getnorm(level, orient); - } else { /* if (qmfbid == 0) */ - w2 = opj_dwt_getnorm_real(level, orient); - } + if (qmfbid == 1) { + w2 = opj_dwt_getnorm(level, orient); + } else { /* if (qmfbid == 0) */ + w2 = opj_dwt_getnorm_real(level, orient); + } - wmsedec = w1 * w2 * stepsize * (1 << bpno); - wmsedec *= wmsedec * nmsedec / 8192.0; + wmsedec = w1 * w2 * stepsize * (1 << bpno); + wmsedec *= wmsedec * nmsedec / 8192.0; - return wmsedec; + return wmsedec; } static OPJ_BOOL opj_t1_allocate_buffers( - opj_t1_t *t1, - OPJ_UINT32 w, - OPJ_UINT32 h) + opj_t1_t *t1, + OPJ_UINT32 w, + OPJ_UINT32 h) { - OPJ_UINT32 datasize=w * h; - OPJ_UINT32 flagssize; - - /* encoder uses tile buffer, so no need to allocate */ - if (!t1->encoder) { - if(datasize > t1->datasize){ - opj_aligned_free(t1->data); - if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_INT32) < datasize) { - return OPJ_FALSE; - } - t1->data = (OPJ_INT32*) opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); - if(!t1->data){ - /* FIXME event manager error callback */ - return OPJ_FALSE; - } - t1->datasize=datasize; - } - memset(t1->data,0,datasize * sizeof(OPJ_INT32)); - } - t1->flags_stride=w+2; - flagssize=t1->flags_stride * (h+2); - - if(flagssize > t1->flagssize){ - opj_aligned_free(t1->flags); - if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(opj_flag_t) < flagssize) { - return OPJ_FALSE; - } - t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof(opj_flag_t)); - if(!t1->flags){ - /* FIXME event manager error callback */ - return OPJ_FALSE; - } - t1->flagssize=flagssize; - } - memset(t1->flags,0,flagssize * sizeof(opj_flag_t)); - - t1->w=w; - t1->h=h; - - return OPJ_TRUE; + OPJ_UINT32 flagssize; + OPJ_UINT32 flags_stride; + + /* No risk of overflow. Prior checks ensure those assert are met */ + /* They are per the specification */ + assert(w <= 1024); + assert(h <= 1024); + assert(w * h <= 4096); + + /* encoder uses tile buffer, so no need to allocate */ + if (!t1->encoder) { + OPJ_UINT32 datasize = w * h; + + if (datasize > t1->datasize) { + opj_aligned_free(t1->data); + t1->data = (OPJ_INT32*) opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); + if (!t1->data) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + t1->datasize = datasize; + } + /* memset first arg is declared to never be null by gcc */ + if (t1->data != NULL) { + memset(t1->data, 0, datasize * sizeof(OPJ_INT32)); + } + } + + flags_stride = w + 2U; /* can't be 0U */ + + flagssize = (h + 3U) / 4U + 2U; + + flagssize *= flags_stride; + { + opj_flag_t* p; + OPJ_UINT32 x; + OPJ_UINT32 flags_height = (h + 3U) / 4U; + + if (flagssize > t1->flagssize) { + + opj_aligned_free(t1->flags); + t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof( + opj_flag_t)); + if (!t1->flags) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + t1->flagssize = flagssize; + + memset(t1->flags, 0, flagssize * sizeof(opj_flag_t)); + + p = &t1->flags[0]; + for (x = 0; x < flags_stride; ++x) { + /* magic value to hopefully stop any passes being interested in this entry */ + *p++ = (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); + } + + p = &t1->flags[((flags_height + 1) * flags_stride)]; + for (x = 0; x < flags_stride; ++x) { + /* magic value to hopefully stop any passes being interested in this entry */ + *p++ = (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); + } + + if (h % 4) { + OPJ_UINT32 v = 0; + p = &t1->flags[((flags_height) * flags_stride)]; + if (h % 4 == 1) { + v |= T1_PI_1 | T1_PI_2 | T1_PI_3; + } else if (h % 4 == 2) { + v |= T1_PI_2 | T1_PI_3; + } else if (h % 4 == 3) { + v |= T1_PI_3; + } + for (x = 0; x < flags_stride; ++x) { + *p++ = v; + } + } + } + + t1->w = w; + t1->h = h; + + return OPJ_TRUE; } /* ----------------------------------------------------------------------- */ @@ -1218,28 +1536,16 @@ static OPJ_BOOL opj_t1_allocate_buffers( */ opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder) { - opj_t1_t *l_t1 = 00; - - l_t1 = (opj_t1_t*) opj_calloc(1,sizeof(opj_t1_t)); - if (!l_t1) { - return 00; - } - - /* create MQC and RAW handles */ - l_t1->mqc = opj_mqc_create(); - if (! l_t1->mqc) { - opj_t1_destroy(l_t1); - return 00; - } - - l_t1->raw = opj_raw_create(); - if (! l_t1->raw) { - opj_t1_destroy(l_t1); - return 00; - } - l_t1->encoder = isEncoder; - - return l_t1; + opj_t1_t *l_t1 = 00; + + l_t1 = (opj_t1_t*) opj_calloc(1, sizeof(opj_t1_t)); + if (!l_t1) { + return 00; + } + + l_t1->encoder = isEncoder; + + return l_t1; } @@ -1250,521 +1556,864 @@ opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder) */ void opj_t1_destroy(opj_t1_t *p_t1) { - if (! p_t1) { - return; - } - - /* destroy MQC and RAW handles */ - opj_mqc_destroy(p_t1->mqc); - p_t1->mqc = 00; - opj_raw_destroy(p_t1->raw); - p_t1->raw = 00; - - /* encoder uses tile buffer, so no need to free */ - if (!p_t1->encoder && p_t1->data) { - opj_aligned_free(p_t1->data); - p_t1->data = 00; - } - - if (p_t1->flags) { - opj_aligned_free(p_t1->flags); - p_t1->flags = 00; - } - - opj_free(p_t1); + if (! p_t1) { + return; + } + + /* encoder uses tile buffer, so no need to free */ + if (!p_t1->encoder && p_t1->data) { + opj_aligned_free(p_t1->data); + p_t1->data = 00; + } + + if (p_t1->flags) { + opj_aligned_free(p_t1->flags); + p_t1->flags = 00; + } + + opj_free(p_t1->cblkdatabuffer); + + opj_free(p_t1); +} + +typedef struct { + OPJ_BOOL whole_tile_decoding; + OPJ_UINT32 resno; + opj_tcd_cblk_dec_t* cblk; + opj_tcd_band_t* band; + opj_tcd_tilecomp_t* tilec; + opj_tccp_t* tccp; + OPJ_BOOL mustuse_cblkdatabuffer; + volatile OPJ_BOOL* pret; + opj_event_mgr_t *p_manager; + opj_mutex_t* p_manager_mutex; + OPJ_BOOL check_pterm; +} opj_t1_cblk_decode_processing_job_t; + +static void opj_t1_destroy_wrapper(void* t1) +{ + opj_t1_destroy((opj_t1_t*) t1); } -OPJ_BOOL opj_t1_decode_cblks( opj_t1_t* t1, - opj_tcd_tilecomp_t* tilec, - opj_tccp_t* tccp - ) +static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) { - OPJ_UINT32 resno, bandno, precno, cblkno; - OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0); - - for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) { - opj_tcd_resolution_t* res = &tilec->resolutions[resno]; - - for (bandno = 0; bandno < res->numbands; ++bandno) { - opj_tcd_band_t* restrict band = &res->bands[bandno]; - - for (precno = 0; precno < res->pw * res->ph; ++precno) { - opj_tcd_precinct_t* precinct = &band->precincts[precno]; - - for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { - opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; - OPJ_INT32* restrict datap; - OPJ_UINT32 cblk_w, cblk_h; - OPJ_INT32 x, y; - OPJ_UINT32 i, j; - - if (OPJ_FALSE == opj_t1_decode_cblk( - t1, - cblk, - band->bandno, - (OPJ_UINT32)tccp->roishift, - tccp->cblksty)) { - return OPJ_FALSE; + opj_tcd_cblk_dec_t* cblk; + opj_tcd_band_t* band; + opj_tcd_tilecomp_t* tilec; + opj_tccp_t* tccp; + OPJ_INT32* OPJ_RESTRICT datap; + OPJ_UINT32 cblk_w, cblk_h; + OPJ_INT32 x, y; + OPJ_UINT32 i, j; + opj_t1_cblk_decode_processing_job_t* job; + opj_t1_t* t1; + OPJ_UINT32 resno; + OPJ_UINT32 tile_w; + + job = (opj_t1_cblk_decode_processing_job_t*) user_data; + + cblk = job->cblk; + + if (!job->whole_tile_decoding) { + cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + + cblk->decoded_data = (OPJ_INT32*)opj_aligned_malloc(cblk_w * cblk_h * sizeof( + OPJ_INT32)); + if (cblk->decoded_data == NULL) { + if (job->p_manager_mutex) { + opj_mutex_lock(job->p_manager_mutex); + } + opj_event_msg(job->p_manager, EVT_ERROR, + "Cannot allocate cblk->decoded_data\n"); + if (job->p_manager_mutex) { + opj_mutex_unlock(job->p_manager_mutex); + } + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + /* Zero-init required */ + memset(cblk->decoded_data, 0, cblk_w * cblk_h * sizeof(OPJ_INT32)); + } else if (cblk->decoded_data) { + /* Not sure if that code path can happen, but better be */ + /* safe than sorry */ + opj_aligned_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + + resno = job->resno; + band = job->band; + tilec = job->tilec; + tccp = job->tccp; + tile_w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - 1].x1 + - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); + + if (!*(job->pret)) { + opj_free(job); + return; + } + + t1 = (opj_t1_t*) opj_tls_get(tls, OPJ_TLS_KEY_T1); + if (t1 == NULL) { + t1 = opj_t1_create(OPJ_FALSE); + opj_tls_set(tls, OPJ_TLS_KEY_T1, t1, opj_t1_destroy_wrapper); + } + t1->mustuse_cblkdatabuffer = job->mustuse_cblkdatabuffer; + + if (OPJ_FALSE == opj_t1_decode_cblk( + t1, + cblk, + band->bandno, + (OPJ_UINT32)tccp->roishift, + tccp->cblksty, + job->p_manager, + job->p_manager_mutex, + job->check_pterm)) { + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + datap = cblk->decoded_data ? cblk->decoded_data : t1->data; + cblk_w = t1->w; + cblk_h = t1->h; + + if (tccp->roishift) { + if (tccp->roishift >= 31) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + datap[(j * cblk_w) + i] = 0; + } + } + } else { + OPJ_INT32 thresh = 1 << tccp->roishift; + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 val = datap[(j * cblk_w) + i]; + OPJ_INT32 mag = abs(val); + if (mag >= thresh) { + mag >>= tccp->roishift; + datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; } + } + } + } + } + + /* Both can be non NULL if for example decoding a full tile and then */ + /* partially a tile. In which case partial decoding should be the */ + /* priority */ + assert((cblk->decoded_data != NULL) || (tilec->data != NULL)); + + if (cblk->decoded_data) { + OPJ_UINT32 cblk_size = cblk_w * cblk_h; + if (tccp->qmfbid == 1) { + for (i = 0; i < cblk_size; ++i) { + datap[i] /= 2; + } + } else { /* if (tccp->qmfbid == 0) */ + i = 0; +#ifdef __SSE2__ + { + const __m128 xmm_stepsize = _mm_set1_ps(band->stepsize); + for (; i < (cblk_size & ~15U); i += 16) { + __m128 xmm0_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 0))); + __m128 xmm1_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 4))); + __m128 xmm2_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 8))); + __m128 xmm3_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 12))); + _mm_store_ps((float*)(datap + 0), _mm_mul_ps(xmm0_data, xmm_stepsize)); + _mm_store_ps((float*)(datap + 4), _mm_mul_ps(xmm1_data, xmm_stepsize)); + _mm_store_ps((float*)(datap + 8), _mm_mul_ps(xmm2_data, xmm_stepsize)); + _mm_store_ps((float*)(datap + 12), _mm_mul_ps(xmm3_data, xmm_stepsize)); + datap += 16; + } + } +#endif + for (; i < cblk_size; ++i) { + OPJ_FLOAT32 tmp = ((OPJ_FLOAT32)(*datap)) * band->stepsize; + memcpy(datap, &tmp, sizeof(tmp)); + datap++; + } + } + } else if (tccp->qmfbid == 1) { + OPJ_INT32* OPJ_RESTRICT tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + + (OPJ_SIZE_T)x]; + for (j = 0; j < cblk_h; ++j) { + i = 0; + for (; i < (cblk_w & ~(OPJ_UINT32)3U); i += 4U) { + OPJ_INT32 tmp0 = datap[(j * cblk_w) + i + 0U]; + OPJ_INT32 tmp1 = datap[(j * cblk_w) + i + 1U]; + OPJ_INT32 tmp2 = datap[(j * cblk_w) + i + 2U]; + OPJ_INT32 tmp3 = datap[(j * cblk_w) + i + 3U]; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 0U] = tmp0 / 2; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 1U] = tmp1 / 2; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 2U] = tmp2 / 2; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 3U] = tmp3 / 2; + } + for (; i < cblk_w; ++i) { + OPJ_INT32 tmp = datap[(j * cblk_w) + i]; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i] = tmp / 2; + } + } + } else { /* if (tccp->qmfbid == 0) */ + OPJ_FLOAT32* OPJ_RESTRICT tiledp = (OPJ_FLOAT32*) &tilec->data[(OPJ_SIZE_T)y * + tile_w + (OPJ_SIZE_T)x]; + for (j = 0; j < cblk_h; ++j) { + OPJ_FLOAT32* OPJ_RESTRICT tiledp2 = tiledp; + for (i = 0; i < cblk_w; ++i) { + OPJ_FLOAT32 tmp = (OPJ_FLOAT32) * datap * band->stepsize; + *tiledp2 = tmp; + datap++; + tiledp2++; + } + tiledp += tile_w; + } + } - x = cblk->x0 - band->x0; - y = cblk->y0 - band->y0; - if (band->bandno & 1) { - opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; - x += pres->x1 - pres->x0; - } - if (band->bandno & 2) { - opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; - y += pres->y1 - pres->y0; - } - - datap=t1->data; - cblk_w = t1->w; - cblk_h = t1->h; - - if (tccp->roishift) { - OPJ_INT32 thresh = 1 << tccp->roishift; - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 val = datap[(j * cblk_w) + i]; - OPJ_INT32 mag = abs(val); - if (mag >= thresh) { - mag >>= tccp->roishift; - datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; - } - } - } - } - if (tccp->qmfbid == 1) { - OPJ_INT32* restrict tiledp = &tilec->data[(OPJ_UINT32)y * tile_w + (OPJ_UINT32)x]; - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 tmp = datap[(j * cblk_w) + i]; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i] = tmp/2; - } - } - } else { /* if (tccp->qmfbid == 0) */ - OPJ_FLOAT32* restrict tiledp = (OPJ_FLOAT32*) &tilec->data[(OPJ_UINT32)y * tile_w + (OPJ_UINT32)x]; - for (j = 0; j < cblk_h; ++j) { - OPJ_FLOAT32* restrict tiledp2 = tiledp; - for (i = 0; i < cblk_w; ++i) { - OPJ_FLOAT32 tmp = (OPJ_FLOAT32)*datap * band->stepsize; - *tiledp2 = tmp; - datap++; - tiledp2++; - } - tiledp += tile_w; - } - } - } /* cblkno */ - } /* precno */ - } /* bandno */ - } /* resno */ - return OPJ_TRUE; + opj_free(job); } -static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, - opj_tcd_cblk_dec_t* cblk, - OPJ_UINT32 orient, - OPJ_UINT32 roishift, - OPJ_UINT32 cblksty) +void opj_t1_decode_cblks(opj_tcd_t* tcd, + volatile OPJ_BOOL* pret, + opj_tcd_tilecomp_t* tilec, + opj_tccp_t* tccp, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm + ) { - opj_raw_t *raw = t1->raw; /* RAW component */ - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - OPJ_INT32 bpno_plus_one; - OPJ_UINT32 passtype; - OPJ_UINT32 segno, passno; - OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */ - - if(!opj_t1_allocate_buffers( - t1, - (OPJ_UINT32)(cblk->x1 - cblk->x0), - (OPJ_UINT32)(cblk->y1 - cblk->y0))) - { - return OPJ_FALSE; - } - - bpno_plus_one = (OPJ_INT32)(roishift + cblk->numbps); - passtype = 2; - - opj_mqc_resetstates(mqc); - opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - - for (segno = 0; segno < cblk->real_num_segs; ++segno) { - opj_tcd_seg_t *seg = &cblk->segs[segno]; - - /* BYPASS mode */ - type = ((bpno_plus_one <= ((OPJ_INT32) (cblk->numbps)) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */ - if(seg->data == 00){ - continue; - } - if (type == T1_TYPE_RAW) { - opj_raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len); - } else { - if (OPJ_FALSE == opj_mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len)) { - return OPJ_FALSE; - } - } + opj_thread_pool_t* tp = tcd->thread_pool; + OPJ_UINT32 resno, bandno, precno, cblkno; - for (passno = 0; (passno < seg->real_num_passes) && (bpno_plus_one >= 1); ++passno) { - switch (passtype) { - case 0: - if (type == T1_TYPE_RAW) { - opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)orient, (OPJ_INT32)cblksty); - } else { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - opj_t1_dec_sigpass_mqc_vsc(t1, bpno_plus_one, (OPJ_INT32)orient); - } else { - opj_t1_dec_sigpass_mqc(t1, bpno_plus_one, (OPJ_INT32)orient); +#ifdef DEBUG_VERBOSE + OPJ_UINT32 codeblocks_decoded = 0; + printf("Enter opj_t1_decode_cblks()\n"); +#endif + + for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) { + opj_tcd_resolution_t* res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t* precinct = &band->precincts[precno]; + + if (!opj_tcd_is_subband_area_of_interest(tcd, + tilec->compno, + resno, + band->bandno, + (OPJ_UINT32)precinct->x0, + (OPJ_UINT32)precinct->y0, + (OPJ_UINT32)precinct->x1, + (OPJ_UINT32)precinct->y1)) { + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + if (cblk->decoded_data) { +#ifdef DEBUG_VERBOSE + printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + opj_aligned_free(cblk->decoded_data); + cblk->decoded_data = NULL; } } - break; - case 1: - if (type == T1_TYPE_RAW) { - opj_t1_dec_refpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty); - } else { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - opj_t1_dec_refpass_mqc_vsc(t1, bpno_plus_one); - } else { - opj_t1_dec_refpass_mqc(t1, bpno_plus_one); + continue; + } + + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + opj_t1_cblk_decode_processing_job_t* job; + + if (!opj_tcd_is_subband_area_of_interest(tcd, + tilec->compno, + resno, + band->bandno, + (OPJ_UINT32)cblk->x0, + (OPJ_UINT32)cblk->y0, + (OPJ_UINT32)cblk->x1, + (OPJ_UINT32)cblk->y1)) { + if (cblk->decoded_data) { +#ifdef DEBUG_VERBOSE + printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + opj_aligned_free(cblk->decoded_data); + cblk->decoded_data = NULL; } + continue; } - break; - case 2: - opj_t1_dec_clnpass(t1, bpno_plus_one, (OPJ_INT32)orient, (OPJ_INT32)cblksty); - break; + + if (!tcd->whole_tile_decoding) { + OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + if (cblk->decoded_data != NULL) { +#ifdef DEBUG_VERBOSE + printf("Reusing codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + continue; + } + if (cblk_w == 0 || cblk_h == 0) { + continue; + } +#ifdef DEBUG_VERBOSE + printf("Decoding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + } + + job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1, + sizeof(opj_t1_cblk_decode_processing_job_t)); + if (!job) { + *pret = OPJ_FALSE; + return; + } + job->whole_tile_decoding = tcd->whole_tile_decoding; + job->resno = resno; + job->cblk = cblk; + job->band = band; + job->tilec = tilec; + job->tccp = tccp; + job->pret = pret; + job->p_manager_mutex = p_manager_mutex; + job->p_manager = p_manager; + job->check_pterm = check_pterm; + job->mustuse_cblkdatabuffer = opj_thread_pool_get_thread_count(tp) > 1; + opj_thread_pool_submit_job(tp, opj_t1_clbl_decode_processor, job); +#ifdef DEBUG_VERBOSE + codeblocks_decoded ++; +#endif + if (!(*pret)) { + return; + } + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + +#ifdef DEBUG_VERBOSE + printf("Leave opj_t1_decode_cblks(). Number decoded: %d\n", codeblocks_decoded); +#endif + return; +} + + +static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm) +{ + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + + OPJ_INT32 bpno_plus_one; + OPJ_UINT32 passtype; + OPJ_UINT32 segno, passno; + OPJ_BYTE* cblkdata = NULL; + OPJ_UINT32 cblkdataindex = 0; + OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */ + OPJ_INT32* original_t1_data = NULL; + + mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9); + + if (!opj_t1_allocate_buffers( + t1, + (OPJ_UINT32)(cblk->x1 - cblk->x0), + (OPJ_UINT32)(cblk->y1 - cblk->y0))) { + return OPJ_FALSE; + } + + bpno_plus_one = (OPJ_INT32)(roishift + cblk->numbps); + if (bpno_plus_one >= 31) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "opj_t1_decode_cblk(): unsupported bpno_plus_one = %d >= 31\n", + bpno_plus_one); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + passtype = 2; + + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + + /* Even if we have a single chunk, in multi-threaded decoding */ + /* the insertion of our synthetic marker might potentially override */ + /* valid codestream of other codeblocks decoded in parallel. */ + if (cblk->numchunks > 1 || t1->mustuse_cblkdatabuffer) { + OPJ_UINT32 i; + OPJ_UINT32 cblk_len; + + /* Compute whole codeblock length from chunk lengths */ + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + cblk_len += cblk->chunks[i].len; + } + + /* Allocate temporary memory if needed */ + if (cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA > t1->cblkdatabuffersize) { + cblkdata = (OPJ_BYTE*)opj_realloc(t1->cblkdatabuffer, + cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA); + if (cblkdata == NULL) { + return OPJ_FALSE; + } + t1->cblkdatabuffer = cblkdata; + memset(t1->cblkdatabuffer + cblk_len, 0, OPJ_COMMON_CBLK_DATA_EXTRA); + t1->cblkdatabuffersize = cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA; + } + + /* Concatenate all chunks */ + cblkdata = t1->cblkdatabuffer; + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + memcpy(cblkdata + cblk_len, cblk->chunks[i].data, cblk->chunks[i].len); + cblk_len += cblk->chunks[i].len; + } + } else if (cblk->numchunks == 1) { + cblkdata = cblk->chunks[0].data; + } else { + /* Not sure if that can happen in practice, but avoid Coverity to */ + /* think we will dereference a null cblkdta pointer */ + return OPJ_TRUE; + } + + /* For subtile decoding, directly decode in the decoded_data buffer of */ + /* the code-block. Hack t1->data to point to it, and restore it later */ + if (cblk->decoded_data) { + original_t1_data = t1->data; + t1->data = cblk->decoded_data; + } + + for (segno = 0; segno < cblk->real_num_segs; ++segno) { + opj_tcd_seg_t *seg = &cblk->segs[segno]; + + /* BYPASS mode */ + type = ((bpno_plus_one <= ((OPJ_INT32)(cblk->numbps)) - 4) && (passtype < 2) && + (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + if (type == T1_TYPE_RAW) { + opj_mqc_raw_init_dec(mqc, cblkdata + cblkdataindex, seg->len, + OPJ_COMMON_CBLK_DATA_EXTRA); + } else { + opj_mqc_init_dec(mqc, cblkdata + cblkdataindex, seg->len, + OPJ_COMMON_CBLK_DATA_EXTRA); + } + cblkdataindex += seg->len; + + for (passno = 0; (passno < seg->real_num_passes) && + (bpno_plus_one >= 1); ++passno) { + switch (passtype) { + case 0: + if (type == T1_TYPE_RAW) { + opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty); + } else { + opj_t1_dec_sigpass_mqc(t1, bpno_plus_one, (OPJ_INT32)cblksty); + } + break; + case 1: + if (type == T1_TYPE_RAW) { + opj_t1_dec_refpass_raw(t1, bpno_plus_one); + } else { + opj_t1_dec_refpass_mqc(t1, bpno_plus_one); + } + break; + case 2: + opj_t1_dec_clnpass(t1, bpno_plus_one, (OPJ_INT32)cblksty); + break; + } + + if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + } + if (++passtype == 3) { + passtype = 0; + bpno_plus_one--; + } + } + + opq_mqc_finish_dec(mqc); + } + + if (check_pterm) { + if (mqc->bp + 2 < mqc->end) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "PTERM check failure: %d remaining bytes in code block (%d used / %d)\n", + (int)(mqc->end - mqc->bp) - 2, + (int)(mqc->bp - mqc->start), + (int)(mqc->end - mqc->start)); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); } + } else if (mqc->end_of_byte_stream_counter > 2) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "PTERM check failure: %d synthetized 0xFF markers read\n", + mqc->end_of_byte_stream_counter); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + } + } + + /* Restore original t1->data is needed */ + if (cblk->decoded_data) { + t1->data = original_t1_data; + } - if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { - opj_mqc_resetstates(mqc); - opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - } - if (++passtype == 3) { - passtype = 0; - bpno_plus_one--; - } - } - } return OPJ_TRUE; } -OPJ_BOOL opj_t1_encode_cblks( opj_t1_t *t1, - opj_tcd_tile_t *tile, - opj_tcp_t *tcp, - const OPJ_FLOAT64 * mct_norms, - OPJ_UINT32 mct_numcomps - ) +OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps + ) { - OPJ_UINT32 compno, resno, bandno, precno, cblkno; - - tile->distotile = 0; /* fixed_quality */ - - for (compno = 0; compno < tile->numcomps; ++compno) { - opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; - opj_tccp_t* tccp = &tcp->tccps[compno]; - OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0); - - for (resno = 0; resno < tilec->numresolutions; ++resno) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - - for (bandno = 0; bandno < res->numbands; ++bandno) { - opj_tcd_band_t* restrict band = &res->bands[bandno]; - OPJ_INT32 bandconst = 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192)); - - for (precno = 0; precno < res->pw * res->ph; ++precno) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; - - for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) { - opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; - OPJ_INT32* restrict tiledp; - OPJ_UINT32 cblk_w; - OPJ_UINT32 cblk_h; - OPJ_UINT32 i, j, tileIndex=0, tileLineAdvance; - - OPJ_INT32 x = cblk->x0 - band->x0; - OPJ_INT32 y = cblk->y0 - band->y0; - if (band->bandno & 1) { - opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; - x += pres->x1 - pres->x0; - } - if (band->bandno & 2) { - opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; - y += pres->y1 - pres->y0; - } - - if(!opj_t1_allocate_buffers( - t1, - (OPJ_UINT32)(cblk->x1 - cblk->x0), - (OPJ_UINT32)(cblk->y1 - cblk->y0))) - { - return OPJ_FALSE; - } - - cblk_w = t1->w; - cblk_h = t1->h; - tileLineAdvance = tile_w - cblk_w; - - tiledp=&tilec->data[(OPJ_UINT32)y * tile_w + (OPJ_UINT32)x]; - t1->data = tiledp; - t1->data_stride = tile_w; - if (tccp->qmfbid == 1) { - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - tiledp[tileIndex] <<= T1_NMSEDEC_FRACBITS; - tileIndex++; - } - tileIndex += tileLineAdvance; - } - } else { /* if (tccp->qmfbid == 0) */ - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 tmp = tiledp[tileIndex]; - tiledp[tileIndex] = - opj_int_fix_mul_t1( - tmp, - bandconst); - tileIndex++; - } - tileIndex += tileLineAdvance; - } - } - - opj_t1_encode_cblk( - t1, - cblk, - band->bandno, - compno, - tilec->numresolutions - 1 - resno, - tccp->qmfbid, - band->stepsize, - tccp->cblksty, - tile->numcomps, - tile, - mct_norms, - mct_numcomps); - - } /* cblkno */ - } /* precno */ - } /* bandno */ - } /* resno */ - } /* compno */ - return OPJ_TRUE; + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + + tile->distotile = 0; /* fixed_quality */ + + for (compno = 0; compno < tile->numcomps; ++compno) { + opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; + opj_tccp_t* tccp = &tcp->tccps[compno]; + OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0); + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; + OPJ_INT32 bandconst; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + bandconst = 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192)); + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + OPJ_INT32* OPJ_RESTRICT tiledp; + OPJ_UINT32 cblk_w; + OPJ_UINT32 cblk_h; + OPJ_UINT32 i, j, tileLineAdvance; + OPJ_SIZE_T tileIndex = 0; + + OPJ_INT32 x = cblk->x0 - band->x0; + OPJ_INT32 y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + if (!opj_t1_allocate_buffers( + t1, + (OPJ_UINT32)(cblk->x1 - cblk->x0), + (OPJ_UINT32)(cblk->y1 - cblk->y0))) { + return OPJ_FALSE; + } + + cblk_w = t1->w; + cblk_h = t1->h; + tileLineAdvance = tile_w - cblk_w; + + tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + (OPJ_SIZE_T)x]; + t1->data = tiledp; + t1->data_stride = tile_w; + if (tccp->qmfbid == 1) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + tiledp[tileIndex] *= (1 << T1_NMSEDEC_FRACBITS); + tileIndex++; + } + tileIndex += tileLineAdvance; + } + } else { /* if (tccp->qmfbid == 0) */ + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 tmp = tiledp[tileIndex]; + tiledp[tileIndex] = + opj_int_fix_mul_t1( + tmp, + bandconst); + tileIndex++; + } + tileIndex += tileLineAdvance; + } + } + + opj_t1_encode_cblk( + t1, + cblk, + band->bandno, + compno, + tilec->numresolutions - 1 - resno, + tccp->qmfbid, + band->stepsize, + tccp->cblksty, + tile->numcomps, + tile, + mct_norms, + mct_numcomps); + + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + return OPJ_TRUE; } -/** mod fixed_quality */ -static void opj_t1_encode_cblk(opj_t1_t *t1, - opj_tcd_cblk_enc_t* cblk, - OPJ_UINT32 orient, - OPJ_UINT32 compno, - OPJ_UINT32 level, - OPJ_UINT32 qmfbid, - OPJ_FLOAT64 stepsize, - OPJ_UINT32 cblksty, - OPJ_UINT32 numcomps, - opj_tcd_tile_t * tile, - const OPJ_FLOAT64 * mct_norms, - OPJ_UINT32 mct_numcomps) +/* Returns whether the pass (bpno, passtype) is terminated */ +static int opj_t1_enc_is_term_pass(opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 cblksty, + OPJ_INT32 bpno, + OPJ_UINT32 passtype) { - OPJ_FLOAT64 cumwmsedec = 0.0; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - OPJ_UINT32 passno; - OPJ_INT32 bpno; - OPJ_UINT32 passtype; - OPJ_INT32 nmsedec = 0; - OPJ_INT32 max; - OPJ_UINT32 i, j; - OPJ_BYTE type = T1_TYPE_MQ; - OPJ_FLOAT64 tempwmsedec; - - max = 0; - for (i = 0; i < t1->w; ++i) { - for (j = 0; j < t1->h; ++j) { - OPJ_INT32 tmp = abs(t1->data[i + j*t1->data_stride]); - max = opj_int_max(max, tmp); - } - } - - cblk->numbps = max ? (OPJ_UINT32)((opj_int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS) : 0; - - bpno = (OPJ_INT32)(cblk->numbps - 1); - passtype = 2; - - opj_mqc_resetstates(mqc); - opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - opj_mqc_init_enc(mqc, cblk->data); - - for (passno = 0; bpno >= 0; ++passno) { - opj_tcd_pass_t *pass = &cblk->passes[passno]; - OPJ_UINT32 correction = 3; - type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - - switch (passtype) { - case 0: - opj_t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty); - break; - case 1: - opj_t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty); - break; - case 2: - opj_t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty); - /* code switch SEGMARK (i.e. SEGSYM) */ - if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) - opj_mqc_segmark_enc(mqc); - break; - } - - /* fixed_quality */ - tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms, mct_numcomps) ; - cumwmsedec += tempwmsedec; - tile->distotile += tempwmsedec; - - /* Code switch "RESTART" (i.e. TERMALL) */ - if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) { - if (type == T1_TYPE_RAW) { - opj_mqc_flush(mqc); - correction = 1; - /* correction = mqc_bypass_flush_enc(); */ - } else { /* correction = mqc_restart_enc(); */ - opj_mqc_flush(mqc); - correction = 1; - } - pass->term = 1; - } else { - if (((bpno < ((OPJ_INT32) (cblk->numbps) - 4) && (passtype > 0)) - || ((bpno == ((OPJ_INT32)cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) { - if (type == T1_TYPE_RAW) { - opj_mqc_flush(mqc); - correction = 1; - /* correction = mqc_bypass_flush_enc(); */ - } else { /* correction = mqc_restart_enc(); */ - opj_mqc_flush(mqc); - correction = 1; - } - pass->term = 1; - } else { - pass->term = 0; - } - } - - if (++passtype == 3) { - passtype = 0; - bpno--; - } - - if (pass->term && bpno > 0) { - type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - if (type == T1_TYPE_RAW) - opj_mqc_bypass_init_enc(mqc); - else - opj_mqc_restart_init_enc(mqc); - } - - pass->distortiondec = cumwmsedec; - pass->rate = opj_mqc_numbytes(mqc) + correction; /* FIXME */ - - /* Code-switch "RESET" */ - if (cblksty & J2K_CCP_CBLKSTY_RESET) - opj_mqc_reset_enc(mqc); - } - - /* Code switch "ERTERM" (i.e. PTERM) */ - if (cblksty & J2K_CCP_CBLKSTY_PTERM) - opj_mqc_erterm_enc(mqc); - else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY)) - opj_mqc_flush(mqc); - - cblk->totalpasses = passno; - - for (passno = 0; passno<cblk->totalpasses; passno++) { - opj_tcd_pass_t *pass = &cblk->passes[passno]; - if (pass->rate > opj_mqc_numbytes(mqc)) - pass->rate = opj_mqc_numbytes(mqc); - /*Preventing generation of FF as last data byte of a pass*/ - if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){ - pass->rate--; - } - pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); - } + /* Is it the last cleanup pass ? */ + if (passtype == 2 && bpno == 0) { + return OPJ_TRUE; + } + + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + return OPJ_TRUE; + } + + if ((cblksty & J2K_CCP_CBLKSTY_LAZY)) { + /* For bypass arithmetic bypass, terminate the 4th cleanup pass */ + if ((bpno == ((OPJ_INT32)cblk->numbps - 4)) && (passtype == 2)) { + return OPJ_TRUE; + } + /* and beyond terminate all the magnitude refinement passes (in raw) */ + /* and cleanup passes (in MQC) */ + if ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype > 0)) { + return OPJ_TRUE; + } + } + + return OPJ_FALSE; } -#if 0 -static void opj_t1_dec_refpass_step( opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_BYTE type, - OPJ_UINT32 vsc) + +/** mod fixed_quality */ +static void opj_t1_encode_cblk(opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 cblksty, + OPJ_UINT32 numcomps, + opj_tcd_tile_t * tile, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps) { - OPJ_INT32 t; - OPJ_UINT32 v,flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - opj_raw_t *raw = t1->raw; /* RAW component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_mag(flag)); /* ESSAI */ - if (type == T1_TYPE_RAW) { - v = opj_raw_decode(raw); - } else { - v = opj_mqc_decode(mqc); - } - t = v ? poshalf : neghalf; - *datap += *datap < 0 ? -t : t; - *flagsp |= T1_REFINE; - } -} /* VSC and BYPASS by Antonin */ + OPJ_FLOAT64 cumwmsedec = 0.0; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + + OPJ_UINT32 passno; + OPJ_INT32 bpno; + OPJ_UINT32 passtype; + OPJ_INT32 nmsedec = 0; + OPJ_INT32 max; + OPJ_UINT32 i, j; + OPJ_BYTE type = T1_TYPE_MQ; + OPJ_FLOAT64 tempwmsedec; + +#ifdef EXTRA_DEBUG + printf("encode_cblk(x=%d,y=%d,x1=%d,y1=%d,orient=%d,compno=%d,level=%d\n", + cblk->x0, cblk->y0, cblk->x1, cblk->y1, orient, compno, level); #endif + mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9); + max = 0; + for (i = 0; i < t1->w; ++i) { + for (j = 0; j < t1->h; ++j) { + OPJ_INT32 tmp = abs(t1->data[i + j * t1->data_stride]); + max = opj_int_max(max, tmp); + } + } + + cblk->numbps = max ? (OPJ_UINT32)((opj_int_floorlog2(max) + 1) - + T1_NMSEDEC_FRACBITS) : 0; + if (cblk->numbps == 0) { + cblk->totalpasses = 0; + return; + } + + bpno = (OPJ_INT32)(cblk->numbps - 1); + passtype = 2; + + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + opj_mqc_init_enc(mqc, cblk->data); + + for (passno = 0; bpno >= 0; ++passno) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + type = ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype < 2) && + (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + /* If the previous pass was terminating, we need to reset the encoder */ + if (passno > 0 && cblk->passes[passno - 1].term) { + if (type == T1_TYPE_RAW) { + opj_mqc_bypass_init_enc(mqc); + } else { + opj_mqc_restart_init_enc(mqc); + } + } -#if 0 -static void opj_t1_dec_sigpass_step( opj_t1_t *t1, - opj_flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 oneplushalf, - OPJ_BYTE type, - OPJ_UINT32 vsc) -{ - OPJ_UINT32 v, flag; - - opj_raw_t *raw = t1->raw; /* RAW component */ - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - if (type == T1_TYPE_RAW) { - if (opj_raw_decode(raw)) { - v = opj_raw_decode(raw); /* ESSAI */ - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, v, t1->flags_stride); - } - } else { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_zc(flag, orient)); - if (opj_mqc_decode(mqc)) { - opj_mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag)); - v = opj_mqc_decode(mqc) ^ opj_t1_getspb(flag); - *datap = v ? -oneplushalf : oneplushalf; - opj_t1_updateflags(flagsp, v, t1->flags_stride); - } - } - *flagsp |= T1_VISIT; - } -} /* VSC and BYPASS by Antonin */ + switch (passtype) { + case 0: + opj_t1_enc_sigpass(t1, bpno, &nmsedec, type, cblksty); + break; + case 1: + opj_t1_enc_refpass(t1, bpno, &nmsedec, type); + break; + case 2: + opj_t1_enc_clnpass(t1, bpno, &nmsedec, cblksty); + /* code switch SEGMARK (i.e. SEGSYM) */ + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) { + opj_mqc_segmark_enc(mqc); + } + break; + } + + /* fixed_quality */ + tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, + stepsize, numcomps, mct_norms, mct_numcomps) ; + cumwmsedec += tempwmsedec; + tile->distotile += tempwmsedec; + pass->distortiondec = cumwmsedec; + + if (opj_t1_enc_is_term_pass(cblk, cblksty, bpno, passtype)) { + /* If it is a terminated pass, terminate it */ + if (type == T1_TYPE_RAW) { + opj_mqc_bypass_flush_enc(mqc, cblksty & J2K_CCP_CBLKSTY_PTERM); + } else { + if (cblksty & J2K_CCP_CBLKSTY_PTERM) { + opj_mqc_erterm_enc(mqc); + } else { + opj_mqc_flush(mqc); + } + } + pass->term = 1; + pass->rate = opj_mqc_numbytes(mqc); + } else { + /* Non terminated pass */ + OPJ_UINT32 rate_extra_bytes; + if (type == T1_TYPE_RAW) { + rate_extra_bytes = opj_mqc_bypass_get_extra_bytes( + mqc, (cblksty & J2K_CCP_CBLKSTY_PTERM)); + } else { + rate_extra_bytes = 3; + } + pass->term = 0; + pass->rate = opj_mqc_numbytes(mqc) + rate_extra_bytes; + } + + if (++passtype == 3) { + passtype = 0; + bpno--; + } + + /* Code-switch "RESET" */ + if (cblksty & J2K_CCP_CBLKSTY_RESET) { + opj_mqc_reset_enc(mqc); + } + } + + cblk->totalpasses = passno; + + if (cblk->totalpasses) { + /* Make sure that pass rates are increasing */ + OPJ_UINT32 last_pass_rate = opj_mqc_numbytes(mqc); + for (passno = cblk->totalpasses; passno > 0;) { + opj_tcd_pass_t *pass = &cblk->passes[--passno]; + if (pass->rate > last_pass_rate) { + pass->rate = last_pass_rate; + } else { + last_pass_rate = pass->rate; + } + } + } + + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + + /* Prevent generation of FF as last data byte of a pass*/ + /* For terminating passes, the flushing procedure ensured this already */ + assert(pass->rate > 0); + if (cblk->data[pass->rate - 1] == 0xFF) { + pass->rate--; + } + pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); + } + +#ifdef EXTRA_DEBUG + printf(" len=%d\n", (cblk->totalpasses) ? opj_mqc_numbytes(mqc) : 0); + + /* Check that there not 0xff >=0x90 sequences */ + if (cblk->totalpasses) { + OPJ_UINT32 i; + OPJ_UINT32 len = opj_mqc_numbytes(mqc); + for (i = 1; i < len; ++i) { + if (cblk->data[i - 1] == 0xff && cblk->data[i] >= 0x90) { + printf("0xff %02x at offset %d\n", cblk->data[i], i - 1); + abort(); + } + } + } #endif +} diff --git a/third_party/libopenjpeg20/t1.h b/third_party/libopenjpeg20/t1.h index 3bc0ad9ea7fbc3bb85ae95e87938239b22bb0a27..171dfb0a7ae57e5f874f74c6967d80b628b6316e 100644 --- a/third_party/libopenjpeg20/t1.h +++ b/third_party/libopenjpeg20/t1.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,9 +8,11 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2012, Carl Hetherington + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,8 +36,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __T1_H -#define __T1_H +#ifndef OPJ_T1_H +#define OPJ_T1_H /** @file t1.h @brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1) @@ -50,71 +52,163 @@ in T1.C are used by some function in TCD.C. /* ----------------------------------------------------------------------- */ #define T1_NMSEDEC_BITS 7 -#define T1_SIG_NE 0x0001 /**< Context orientation : North-East direction */ -#define T1_SIG_SE 0x0002 /**< Context orientation : South-East direction */ -#define T1_SIG_SW 0x0004 /**< Context orientation : South-West direction */ -#define T1_SIG_NW 0x0008 /**< Context orientation : North-West direction */ -#define T1_SIG_N 0x0010 /**< Context orientation : North direction */ -#define T1_SIG_E 0x0020 /**< Context orientation : East direction */ -#define T1_SIG_S 0x0040 /**< Context orientation : South direction */ -#define T1_SIG_W 0x0080 /**< Context orientation : West direction */ -#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW) -#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W) - -#define T1_SGN_N 0x0100 -#define T1_SGN_E 0x0200 -#define T1_SGN_S 0x0400 -#define T1_SGN_W 0x0800 -#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W) - -#define T1_SIG 0x1000 -#define T1_REFINE 0x2000 -#define T1_VISIT 0x4000 - -#define T1_NUMCTXS_ZC 9 -#define T1_NUMCTXS_SC 5 +#define T1_NUMCTXS_ZC 9 +#define T1_NUMCTXS_SC 5 #define T1_NUMCTXS_MAG 3 #define T1_NUMCTXS_AGG 1 #define T1_NUMCTXS_UNI 1 -#define T1_CTXNO_ZC 0 -#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC) +#define T1_CTXNO_ZC 0 +#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC) #define T1_CTXNO_MAG (T1_CTXNO_SC+T1_NUMCTXS_SC) #define T1_CTXNO_AGG (T1_CTXNO_MAG+T1_NUMCTXS_MAG) #define T1_CTXNO_UNI (T1_CTXNO_AGG+T1_NUMCTXS_AGG) -#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI) +#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI) #define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1) -#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */ -#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/ +#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */ +#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/ + +/* BEGINNING of flags that apply to opj_flag_t */ +/** We hold the state of individual data points for the T1 encoder using + * a single 32-bit flags word to hold the state of 4 data points. This corresponds + * to the 4-point-high columns that the data is processed in. + * + * These \#defines declare the layout of a 32-bit flags word. + * + * This is currently done for encoding only. + * The values must NOT be changed, otherwise this is going to break a lot of + * assumptions. + */ + +/* SIGMA: significance state (3 cols x 6 rows) + * CHI: state for negative sample value (1 col x 6 rows) + * MU: state for visited in refinement pass (1 col x 4 rows) + * PI: state for visited in significance pass (1 col * 4 rows) + */ + +#define T1_SIGMA_0 (1U << 0) +#define T1_SIGMA_1 (1U << 1) +#define T1_SIGMA_2 (1U << 2) +#define T1_SIGMA_3 (1U << 3) +#define T1_SIGMA_4 (1U << 4) +#define T1_SIGMA_5 (1U << 5) +#define T1_SIGMA_6 (1U << 6) +#define T1_SIGMA_7 (1U << 7) +#define T1_SIGMA_8 (1U << 8) +#define T1_SIGMA_9 (1U << 9) +#define T1_SIGMA_10 (1U << 10) +#define T1_SIGMA_11 (1U << 11) +#define T1_SIGMA_12 (1U << 12) +#define T1_SIGMA_13 (1U << 13) +#define T1_SIGMA_14 (1U << 14) +#define T1_SIGMA_15 (1U << 15) +#define T1_SIGMA_16 (1U << 16) +#define T1_SIGMA_17 (1U << 17) + +#define T1_CHI_0 (1U << 18) +#define T1_CHI_0_I 18 +#define T1_CHI_1 (1U << 19) +#define T1_CHI_1_I 19 +#define T1_MU_0 (1U << 20) +#define T1_PI_0 (1U << 21) +#define T1_CHI_2 (1U << 22) +#define T1_CHI_2_I 22 +#define T1_MU_1 (1U << 23) +#define T1_PI_1 (1U << 24) +#define T1_CHI_3 (1U << 25) +#define T1_MU_2 (1U << 26) +#define T1_PI_2 (1U << 27) +#define T1_CHI_4 (1U << 28) +#define T1_MU_3 (1U << 29) +#define T1_PI_3 (1U << 30) +#define T1_CHI_5 (1U << 31) +#define T1_CHI_5_I 31 + +/** As an example, the bits T1_SIGMA_3, T1_SIGMA_4 and T1_SIGMA_5 + * indicate the significance state of the west neighbour of data point zero + * of our four, the point itself, and its east neighbour respectively. + * Many of the bits are arranged so that given a flags word, you can + * look at the values for the data point 0, then shift the flags + * word right by 3 bits and look at the same bit positions to see the + * values for data point 1. + * + * The \#defines below help a bit with this; say you have a flags word + * f, you can do things like + * + * (f & T1_SIGMA_THIS) + * + * to see the significance bit of data point 0, then do + * + * ((f >> 3) & T1_SIGMA_THIS) + * + * to see the significance bit of data point 1. + */ + +#define T1_SIGMA_NW T1_SIGMA_0 +#define T1_SIGMA_N T1_SIGMA_1 +#define T1_SIGMA_NE T1_SIGMA_2 +#define T1_SIGMA_W T1_SIGMA_3 +#define T1_SIGMA_THIS T1_SIGMA_4 +#define T1_SIGMA_E T1_SIGMA_5 +#define T1_SIGMA_SW T1_SIGMA_6 +#define T1_SIGMA_S T1_SIGMA_7 +#define T1_SIGMA_SE T1_SIGMA_8 +#define T1_SIGMA_NEIGHBOURS (T1_SIGMA_NW | T1_SIGMA_N | T1_SIGMA_NE | T1_SIGMA_W | T1_SIGMA_E | T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE) + +#define T1_CHI_THIS T1_CHI_1 +#define T1_CHI_THIS_I T1_CHI_1_I +#define T1_MU_THIS T1_MU_0 +#define T1_PI_THIS T1_PI_0 +#define T1_CHI_S T1_CHI_2 + +#define T1_LUT_SGN_W (1U << 0) +#define T1_LUT_SIG_N (1U << 1) +#define T1_LUT_SGN_E (1U << 2) +#define T1_LUT_SIG_W (1U << 3) +#define T1_LUT_SGN_N (1U << 4) +#define T1_LUT_SIG_E (1U << 5) +#define T1_LUT_SGN_S (1U << 6) +#define T1_LUT_SIG_S (1U << 7) +/* END of flags that apply to opj_flag_t */ /* ----------------------------------------------------------------------- */ -typedef OPJ_INT16 opj_flag_t; +/** Flags for 4 consecutive rows of a column */ +typedef OPJ_UINT32 opj_flag_t; /** Tier-1 coding (coding of code-block coefficients) */ typedef struct opj_t1 { - /** MQC component */ - opj_mqc_t *mqc; - /** RAW component */ - opj_raw_t *raw; - - OPJ_INT32 *data; - opj_flag_t *flags; - OPJ_UINT32 w; - OPJ_UINT32 h; - OPJ_UINT32 datasize; - OPJ_UINT32 flagssize; - OPJ_UINT32 flags_stride; - OPJ_UINT32 data_stride; - OPJ_BOOL encoder; -} opj_t1_t; + /** MQC component */ + opj_mqc_t mqc; + + OPJ_INT32 *data; + /** Flags used by decoder and encoder. + * Such that flags[1+0] is for state of col=0,row=0..3, + flags[1+1] for col=1, row=0..3, flags[1+flags_stride] for col=0,row=4..7, ... + This array avoids too much cache trashing when processing by 4 vertical samples + as done in the various decoding steps. */ + opj_flag_t *flags; -#define MACRO_t1_flags(x,y) t1->flags[((x)*(t1->flags_stride))+(y)] + OPJ_UINT32 w; + OPJ_UINT32 h; + OPJ_UINT32 datasize; + OPJ_UINT32 flagssize; + OPJ_UINT32 data_stride; + OPJ_BOOL encoder; + + /* Thre 3 variables below are only used by the decoder */ + /* set to TRUE in multithreaded context */ + OPJ_BOOL mustuse_cblkdatabuffer; + /* Temporary buffer to concatenate all chunks of a codebock */ + OPJ_BYTE *cblkdatabuffer; + /* Maximum size available in cblkdatabuffer */ + OPJ_UINT32 cblkdatabuffersize; +} opj_t1_t; /** @name Exported functions */ /*@{*/ @@ -128,21 +222,29 @@ Encode the code-blocks of a tile @param mct_norms FIXME DOC @param mct_numcomps Number of components used for MCT */ -OPJ_BOOL opj_t1_encode_cblks( opj_t1_t *t1, - opj_tcd_tile_t *tile, - opj_tcp_t *tcp, - const OPJ_FLOAT64 * mct_norms, - OPJ_UINT32 mct_numcomps); +OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); /** Decode the code-blocks of a tile -@param t1 T1 handle +@param tcd TCD handle +@param pret Pointer to return value @param tilec The tile to decode @param tccp Tile coding parameters +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked */ -OPJ_BOOL opj_t1_decode_cblks( opj_t1_t* t1, - opj_tcd_tilecomp_t* tilec, - opj_tccp_t* tccp); +void opj_t1_decode_cblks(opj_tcd_t* tcd, + volatile OPJ_BOOL* pret, + opj_tcd_tilecomp_t* tilec, + opj_tccp_t* tccp, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); @@ -164,4 +266,4 @@ void opj_t1_destroy(opj_t1_t *p_t1); /*@}*/ -#endif /* __T1_H */ +#endif /* OPJ_T1_H */ diff --git a/third_party/libopenjpeg20/t1_generate_luts.c b/third_party/libopenjpeg20/t1_generate_luts.c index 1997d39977a42befce3b740bc36a77213cca9d11..9ad6f200307afe1cf221137132a6c52d078991f1 100644 --- a/third_party/libopenjpeg20/t1_generate_luts.c +++ b/third_party/libopenjpeg20/t1_generate_luts.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,11 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com> + * Copyright (c) 2012, Carl Hetherington * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,245 +39,273 @@ #include "opj_includes.h" -static int t1_init_ctxno_zc(int f, int orient) { - int h, v, d, n, t, hv; - n = 0; - h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0); - v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0); - d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 0); +static int t1_init_ctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) +{ + int h, v, d, n, t, hv; + n = 0; + h = ((f & T1_SIGMA_3) != 0) + ((f & T1_SIGMA_5) != 0); + v = ((f & T1_SIGMA_1) != 0) + ((f & T1_SIGMA_7) != 0); + d = ((f & T1_SIGMA_0) != 0) + ((f & T1_SIGMA_2) != 0) + (( + f & T1_SIGMA_8) != 0) + ((f & T1_SIGMA_6) != 0); - switch (orient) { - case 2: - t = h; - h = v; - v = t; - case 0: - case 1: - if (!h) { - if (!v) { - if (!d) - n = 0; - else if (d == 1) - n = 1; - else - n = 2; - } else if (v == 1) { - n = 3; - } else { - n = 4; - } - } else if (h == 1) { - if (!v) { - if (!d) - n = 5; - else - n = 6; - } else { - n = 7; - } - } else - n = 8; - break; - case 3: - hv = h + v; - if (!d) { - if (!hv) { - n = 0; - } else if (hv == 1) { - n = 1; - } else { - n = 2; - } - } else if (d == 1) { - if (!hv) { - n = 3; - } else if (hv == 1) { - n = 4; - } else { - n = 5; - } - } else if (d == 2) { - if (!hv) { - n = 6; - } else { - n = 7; - } - } else { - n = 8; - } - break; - } + switch (orient) { + case 2: + t = h; + h = v; + v = t; + case 0: + case 1: + if (!h) { + if (!v) { + if (!d) { + n = 0; + } else if (d == 1) { + n = 1; + } else { + n = 2; + } + } else if (v == 1) { + n = 3; + } else { + n = 4; + } + } else if (h == 1) { + if (!v) { + if (!d) { + n = 5; + } else { + n = 6; + } + } else { + n = 7; + } + } else { + n = 8; + } + break; + case 3: + hv = h + v; + if (!d) { + if (!hv) { + n = 0; + } else if (hv == 1) { + n = 1; + } else { + n = 2; + } + } else if (d == 1) { + if (!hv) { + n = 3; + } else if (hv == 1) { + n = 4; + } else { + n = 5; + } + } else if (d == 2) { + if (!hv) { + n = 6; + } else { + n = 7; + } + } else { + n = 8; + } + break; + } - return (T1_CTXNO_ZC + n); + return (T1_CTXNO_ZC + n); } -static int t1_init_ctxno_sc(int f) { - int hc, vc, n; - n = 0; +static int t1_init_ctxno_sc(OPJ_UINT32 f) +{ + int hc, vc, n; + n = 0; - hc = opj_int_min(((f & (T1_SIG_E | T1_SGN_E)) == - T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), - 1) - opj_int_min(((f & (T1_SIG_E | T1_SGN_E)) == - (T1_SIG_E | T1_SGN_E)) + - ((f & (T1_SIG_W | T1_SGN_W)) == - (T1_SIG_W | T1_SGN_W)), 1); + hc = opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + T1_LUT_SIG_E) + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == T1_LUT_SIG_W), + 1) - opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + (T1_LUT_SIG_E | T1_LUT_SGN_E)) + + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == + (T1_LUT_SIG_W | T1_LUT_SGN_W)), 1); - vc = opj_int_min(((f & (T1_SIG_N | T1_SGN_N)) == - T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), - 1) - opj_int_min(((f & (T1_SIG_N | T1_SGN_N)) == - (T1_SIG_N | T1_SGN_N)) + - ((f & (T1_SIG_S | T1_SGN_S)) == - (T1_SIG_S | T1_SGN_S)), 1); + vc = opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + T1_LUT_SIG_N) + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == T1_LUT_SIG_S), + 1) - opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + (T1_LUT_SIG_N | T1_LUT_SGN_N)) + + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == + (T1_LUT_SIG_S | T1_LUT_SGN_S)), 1); - if (hc < 0) { - hc = -hc; - vc = -vc; - } - if (!hc) { - if (vc == -1) - n = 1; - else if (!vc) - n = 0; - else - n = 1; - } else if (hc == 1) { - if (vc == -1) - n = 2; - else if (!vc) - n = 3; - else - n = 4; - } + if (hc < 0) { + hc = -hc; + vc = -vc; + } + if (!hc) { + if (vc == -1) { + n = 1; + } else if (!vc) { + n = 0; + } else { + n = 1; + } + } else if (hc == 1) { + if (vc == -1) { + n = 2; + } else if (!vc) { + n = 3; + } else { + n = 4; + } + } - return (T1_CTXNO_SC + n); + return (T1_CTXNO_SC + n); } -static int t1_init_spb(int f) { - int hc, vc, n; +static int t1_init_spb(OPJ_UINT32 f) +{ + int hc, vc, n; - hc = opj_int_min(((f & (T1_SIG_E | T1_SGN_E)) == - T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), - 1) - opj_int_min(((f & (T1_SIG_E | T1_SGN_E)) == - (T1_SIG_E | T1_SGN_E)) + - ((f & (T1_SIG_W | T1_SGN_W)) == - (T1_SIG_W | T1_SGN_W)), 1); + hc = opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + T1_LUT_SIG_E) + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == T1_LUT_SIG_W), + 1) - opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + (T1_LUT_SIG_E | T1_LUT_SGN_E)) + + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == + (T1_LUT_SIG_W | T1_LUT_SGN_W)), 1); - vc = opj_int_min(((f & (T1_SIG_N | T1_SGN_N)) == - T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), - 1) - opj_int_min(((f & (T1_SIG_N | T1_SGN_N)) == - (T1_SIG_N | T1_SGN_N)) + - ((f & (T1_SIG_S | T1_SGN_S)) == - (T1_SIG_S | T1_SGN_S)), 1); + vc = opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + T1_LUT_SIG_N) + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == T1_LUT_SIG_S), + 1) - opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + (T1_LUT_SIG_N | T1_LUT_SGN_N)) + + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == + (T1_LUT_SIG_S | T1_LUT_SGN_S)), 1); - if (!hc && !vc) - n = 0; - else - n = (!(hc > 0 || (!hc && vc > 0))); + if (!hc && !vc) { + n = 0; + } else { + n = (!(hc > 0 || (!hc && vc > 0))); + } - return n; + return n; } -static void dump_array16(int array[],int size){ - int i; - --size; - for (i = 0; i < size; ++i) { - printf("0x%04x, ", array[i]); - if(!((i+1)&0x7)) - printf("\n "); - } - printf("0x%04x\n};\n\n", array[size]); +static void dump_array16(int array[], int size) +{ + int i; + --size; + for (i = 0; i < size; ++i) { + printf("0x%04x,", array[i]); + if (!((i + 1) & 0x7)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("0x%04x\n};\n\n", array[size]); } int main(int argc, char **argv) { - int i, j; - double u, v, t; + unsigned int i, j; + double u, v, t; - int lut_ctxno_zc[1024]; - int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS]; - int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS]; - int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS]; - int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS]; - (void)argc; (void)argv; + int lut_ctxno_zc[2048]; + int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS]; + (void)argc; + (void)argv; - printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); + printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); - /* lut_ctxno_zc */ - for (j = 0; j < 4; ++j) { - for (i = 0; i < 256; ++i) { - int orient = j; - if (orient == 2) { - orient = 1; - } else if (orient == 1) { - orient = 2; - } - lut_ctxno_zc[(orient << 8) | i] = t1_init_ctxno_zc(i, j); - } - } + /* lut_ctxno_zc */ + for (j = 0; j < 4; ++j) { + for (i = 0; i < 512; ++i) { + OPJ_UINT32 orient = j; + if (orient == 2) { + orient = 1; + } else if (orient == 1) { + orient = 2; + } + lut_ctxno_zc[(orient << 9) | i] = t1_init_ctxno_zc(i, j); + } + } - printf("static OPJ_BYTE lut_ctxno_zc[1024] = {\n "); - for (i = 0; i < 1023; ++i) { - printf("%i, ", lut_ctxno_zc[i]); - if(!((i+1)&0x1f)) - printf("\n "); - } - printf("%i\n};\n\n", lut_ctxno_zc[1023]); + printf("static const OPJ_BYTE lut_ctxno_zc[2048] = {\n "); + for (i = 0; i < 2047; ++i) { + printf("%i,", lut_ctxno_zc[i]); + if (!((i + 1) & 0x1f)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("%i\n};\n\n", lut_ctxno_zc[2047]); - /* lut_ctxno_sc */ - printf("static OPJ_BYTE lut_ctxno_sc[256] = {\n "); - for (i = 0; i < 255; ++i) { - printf("0x%x, ", t1_init_ctxno_sc(i << 4)); - if(!((i+1)&0xf)) - printf("\n "); - } - printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4)); + /* lut_ctxno_sc */ + printf("static const OPJ_BYTE lut_ctxno_sc[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("0x%x,", t1_init_ctxno_sc(i)); + if (!((i + 1) & 0xf)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("0x%x\n};\n\n", t1_init_ctxno_sc(255)); - /* lut_spb */ - printf("static OPJ_BYTE lut_spb[256] = {\n "); - for (i = 0; i < 255; ++i) { - printf("%i, ", t1_init_spb(i << 4)); - if(!((i+1)&0x1f)) - printf("\n "); - } - printf("%i\n};\n\n", t1_init_spb(255 << 4)); + /* lut_spb */ + printf("static const OPJ_BYTE lut_spb[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("%i,", t1_init_spb(i)); + if (!((i + 1) & 0x1f)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("%i\n};\n\n", t1_init_spb(255)); - /* FIXME FIXME FIXME */ - /* fprintf(stdout,"nmsedec luts:\n"); */ - for (i = 0; i < (1 << T1_NMSEDEC_BITS); ++i) { - t = i / pow(2, T1_NMSEDEC_FRACBITS); - u = t; - v = t - 1.5; - lut_nmsedec_sig[i] = - opj_int_max(0, - (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - lut_nmsedec_sig0[i] = - opj_int_max(0, - (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - u = t - 1.0; - if (i & (1 << (T1_NMSEDEC_BITS - 1))) { - v = t - 1.5; - } else { - v = t - 0.5; - } - lut_nmsedec_ref[i] = - opj_int_max(0, - (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - lut_nmsedec_ref0[i] = - opj_int_max(0, - (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - } + /* FIXME FIXME FIXME */ + /* fprintf(stdout,"nmsedec luts:\n"); */ + for (i = 0U; i < (1U << T1_NMSEDEC_BITS); ++i) { + t = i / pow(2, T1_NMSEDEC_FRACBITS); + u = t; + v = t - 1.5; + lut_nmsedec_sig[i] = + opj_int_max(0, + (int)(floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_sig0[i] = + opj_int_max(0, + (int)(floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + u = t - 1.0; + if (i & (1 << (T1_NMSEDEC_BITS - 1))) { + v = t - 1.5; + } else { + v = t - 0.5; + } + lut_nmsedec_ref[i] = + opj_int_max(0, + (int)(floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_ref0[i] = + opj_int_max(0, + (int)(floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + } - printf("static OPJ_INT16 lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(lut_nmsedec_sig, 1 << T1_NMSEDEC_BITS); + printf("static const OPJ_INT16 lut_nmsedec_sig[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_sig, 1U << T1_NMSEDEC_BITS); - printf("static OPJ_INT16 lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(lut_nmsedec_sig0, 1 << T1_NMSEDEC_BITS); + printf("static const OPJ_INT16 lut_nmsedec_sig0[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_sig0, 1U << T1_NMSEDEC_BITS); - printf("static OPJ_INT16 lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(lut_nmsedec_ref, 1 << T1_NMSEDEC_BITS); + printf("static const OPJ_INT16 lut_nmsedec_ref[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_ref, 1U << T1_NMSEDEC_BITS); - printf("static OPJ_INT16 lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(lut_nmsedec_ref0, 1 << T1_NMSEDEC_BITS); + printf("static const OPJ_INT16 lut_nmsedec_ref0[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_ref0, 1U << T1_NMSEDEC_BITS); - return 0; + return 0; } diff --git a/third_party/libopenjpeg20/t1_luts.h b/third_party/libopenjpeg20/t1_luts.h index 37776b65a161bb7417f54290028aeb456eaf28f7..1a5e7844f761b602f0a61f1205ba9d96d0e0a94d 100644 --- a/third_party/libopenjpeg20/t1_luts.h +++ b/third_party/libopenjpeg20/t1_luts.h @@ -1,143 +1,175 @@ /* This file was automatically generated by t1_generate_luts.c */ -static OPJ_BYTE lut_ctxno_zc[1024] = { - 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 3, 3, 6, 3, 6, 6, 8, 3, 6, 6, 8, 6, 8, 8, 8, 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, - 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8 +static const OPJ_BYTE lut_ctxno_zc[2048] = { + 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, + 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 5, 6, 1, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 0, 1, 5, 6, 1, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 5, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 5, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 2, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 2, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, + 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 3, 1, 4, 3, 6, 4, 7, 1, 4, 2, 5, 4, 7, 5, 7, 0, 3, 1, 4, 3, 6, 4, 7, 1, 4, 2, 5, 4, 7, 5, 7, + 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, + 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, + 2, 5, 2, 5, 5, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 6, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 6, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, + 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, + 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8 }; -static OPJ_BYTE lut_ctxno_sc[256] = { - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd +static const OPJ_BYTE lut_ctxno_sc[256] = { + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xd, 0xb, 0xc, 0xc, 0xd, 0xb, + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xb, 0xd, 0xc, 0xc, 0xb, 0xd, + 0xc, 0xc, 0xd, 0xd, 0xc, 0xc, 0xb, 0xb, 0xc, 0x9, 0xd, 0xa, 0x9, 0xc, 0xa, 0xb, + 0xc, 0xc, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xc, 0x9, 0xb, 0xa, 0x9, 0xc, 0xa, 0xd, + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xd, 0xb, 0xc, 0xc, 0xd, 0xb, + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xb, 0xd, 0xc, 0xc, 0xb, 0xd, + 0xc, 0xc, 0xd, 0xd, 0xc, 0xc, 0xb, 0xb, 0xc, 0x9, 0xd, 0xa, 0x9, 0xc, 0xa, 0xb, + 0xc, 0xc, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xc, 0x9, 0xb, 0xa, 0x9, 0xc, 0xa, 0xd, + 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xd, 0xb, 0xd, 0xb, 0xd, 0xb, 0xd, 0xb, + 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xd, 0xb, 0xc, 0xc, 0xd, 0xb, 0xc, 0xc, + 0xd, 0xd, 0xd, 0xd, 0xb, 0xb, 0xb, 0xb, 0xd, 0xa, 0xd, 0xa, 0xa, 0xb, 0xa, 0xb, + 0xd, 0xd, 0xc, 0xc, 0xb, 0xb, 0xc, 0xc, 0xd, 0xa, 0xc, 0x9, 0xa, 0xb, 0x9, 0xc, + 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xb, 0xd, 0xc, 0xc, 0xb, 0xd, 0xc, 0xc, + 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xb, 0xd, 0xb, 0xd, 0xb, 0xd, 0xb, 0xd, + 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xc, 0xc, 0xb, 0xa, 0xc, 0x9, 0xa, 0xd, 0x9, 0xc, + 0xb, 0xb, 0xb, 0xb, 0xd, 0xd, 0xd, 0xd, 0xb, 0xa, 0xb, 0xa, 0xa, 0xd, 0xa, 0xd }; -static OPJ_BYTE lut_spb[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, - 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +static const OPJ_BYTE lut_spb[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, + 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 }; -static OPJ_INT16 lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0180, 0x0300, 0x0480, 0x0600, 0x0780, 0x0900, 0x0a80, - 0x0c00, 0x0d80, 0x0f00, 0x1080, 0x1200, 0x1380, 0x1500, 0x1680, - 0x1800, 0x1980, 0x1b00, 0x1c80, 0x1e00, 0x1f80, 0x2100, 0x2280, - 0x2400, 0x2580, 0x2700, 0x2880, 0x2a00, 0x2b80, 0x2d00, 0x2e80, - 0x3000, 0x3180, 0x3300, 0x3480, 0x3600, 0x3780, 0x3900, 0x3a80, - 0x3c00, 0x3d80, 0x3f00, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, - 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5100, 0x5280, - 0x5400, 0x5580, 0x5700, 0x5880, 0x5a00, 0x5b80, 0x5d00, 0x5e80, - 0x6000, 0x6180, 0x6300, 0x6480, 0x6600, 0x6780, 0x6900, 0x6a80, - 0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680 +static const OPJ_INT16 lut_nmsedec_sig[1U << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0180, 0x0300, 0x0480, 0x0600, 0x0780, 0x0900, 0x0a80, + 0x0c00, 0x0d80, 0x0f00, 0x1080, 0x1200, 0x1380, 0x1500, 0x1680, + 0x1800, 0x1980, 0x1b00, 0x1c80, 0x1e00, 0x1f80, 0x2100, 0x2280, + 0x2400, 0x2580, 0x2700, 0x2880, 0x2a00, 0x2b80, 0x2d00, 0x2e80, + 0x3000, 0x3180, 0x3300, 0x3480, 0x3600, 0x3780, 0x3900, 0x3a80, + 0x3c00, 0x3d80, 0x3f00, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5100, 0x5280, + 0x5400, 0x5580, 0x5700, 0x5880, 0x5a00, 0x5b80, 0x5d00, 0x5e80, + 0x6000, 0x6180, 0x6300, 0x6480, 0x6600, 0x6780, 0x6900, 0x6a80, + 0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680 }; -static OPJ_INT16 lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, - 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, - 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, - 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, - 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, - 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, - 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, - 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00, - 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2680, 0x2780, - 0x2880, 0x2980, 0x2b00, 0x2c00, 0x2d00, 0x2e80, 0x2f80, 0x3100, - 0x3200, 0x3380, 0x3480, 0x3600, 0x3700, 0x3880, 0x3a00, 0x3b00, - 0x3c80, 0x3e00, 0x3f80, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, - 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5180, 0x5300, - 0x5480, 0x5600, 0x5800, 0x5980, 0x5b00, 0x5d00, 0x5e80, 0x6080, - 0x6200, 0x6400, 0x6580, 0x6780, 0x6900, 0x6b00, 0x6d00, 0x6e80, - 0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00 +static const OPJ_INT16 lut_nmsedec_sig0[1U << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00, + 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2680, 0x2780, + 0x2880, 0x2980, 0x2b00, 0x2c00, 0x2d00, 0x2e80, 0x2f80, 0x3100, + 0x3200, 0x3380, 0x3480, 0x3600, 0x3700, 0x3880, 0x3a00, 0x3b00, + 0x3c80, 0x3e00, 0x3f80, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5180, 0x5300, + 0x5480, 0x5600, 0x5800, 0x5980, 0x5b00, 0x5d00, 0x5e80, 0x6080, + 0x6200, 0x6400, 0x6580, 0x6780, 0x6900, 0x6b00, 0x6d00, 0x6e80, + 0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00 }; -static OPJ_INT16 lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = { - 0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480, - 0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080, - 0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80, - 0x0c00, 0x0b80, 0x0b00, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, - 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0500, 0x0480, - 0x0400, 0x0380, 0x0300, 0x0280, 0x0200, 0x0180, 0x0100, 0x0080, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, - 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, - 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80, - 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80, - 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, - 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780 +static const OPJ_INT16 lut_nmsedec_ref[1U << T1_NMSEDEC_BITS] = { + 0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480, + 0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080, + 0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80, + 0x0c00, 0x0b80, 0x0b00, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0500, 0x0480, + 0x0400, 0x0380, 0x0300, 0x0280, 0x0200, 0x0180, 0x0100, 0x0080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80, + 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80, + 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, + 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780 }; -static OPJ_INT16 lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = { - 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980, - 0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300, - 0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00, - 0x0c80, 0x0c00, 0x0b80, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, - 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0580, 0x0500, - 0x0480, 0x0400, 0x0400, 0x0380, 0x0300, 0x0300, 0x0280, 0x0280, - 0x0200, 0x0200, 0x0180, 0x0180, 0x0100, 0x0100, 0x0100, 0x0080, - 0x0080, 0x0080, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, - 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, - 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, - 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, - 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, - 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, - 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, - 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00 +static const OPJ_INT16 lut_nmsedec_ref0[1U << T1_NMSEDEC_BITS] = { + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980, + 0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300, + 0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00, + 0x0c80, 0x0c00, 0x0b80, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0580, 0x0500, + 0x0480, 0x0400, 0x0400, 0x0380, 0x0300, 0x0300, 0x0280, 0x0280, + 0x0200, 0x0200, 0x0180, 0x0180, 0x0100, 0x0100, 0x0100, 0x0080, + 0x0080, 0x0080, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00 }; diff --git a/third_party/libopenjpeg20/t2.c b/third_party/libopenjpeg20/t2.c index 5af1a69aae23dce7368f2ccaee0d339a4ebdae15..6f956d1c7f6f988d243a86f64c34f2e8020c7f5e 100644 --- a/third_party/libopenjpeg20/t2.c +++ b/third_party/libopenjpeg20/t2.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,11 +8,12 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +39,8 @@ */ #include "opj_includes.h" +#include "opj_common.h" + /** @defgroup T2 T2 - Implementation of a tier-2 coding */ /*@{*/ @@ -47,7 +50,7 @@ static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n); -static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio); +static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio); /** Variable length code for signalling delta Zil (truncation point) @param bio Bit Input/Output component @@ -66,16 +69,20 @@ Encode a packet of a tile to a destination buffer @param p_data_written FIXME DOC @param len Length of the destination buffer @param cstr_info Codestream information structure +@param p_t2_mode If == THRESH_CALC In Threshold calculation ,If == FINAL_PASS Final pass +@param p_manager the user event manager @return */ -static OPJ_BOOL opj_t2_encode_packet( OPJ_UINT32 tileno, - opj_tcd_tile_t *tile, - opj_tcp_t *tcp, - opj_pi_iterator_t *pi, - OPJ_BYTE *dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 len, - opj_codestream_info_t *cstr_info); +static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t *p_manager); /** Decode a packet of a tile from a source buffer @@ -87,39 +94,40 @@ Decode a packet of a tile from a source buffer @param data_read FIXME DOC @param max_length FIXME DOC @param pack_info Packet information +@param p_manager the user event manager @return FIXME DOC */ -static OPJ_BOOL opj_t2_decode_packet( opj_t2_t* t2, - opj_tcd_tile_t *tile, - opj_tcp_t *tcp, - opj_pi_iterator_t *pi, - OPJ_BYTE *src, - OPJ_UINT32 * data_read, - OPJ_UINT32 max_length, - opj_packet_info_t *pack_info, - opj_event_mgr_t *p_manager); - -static OPJ_BOOL opj_t2_skip_packet( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_tcp_t *p_tcp, - opj_pi_iterator_t *p_pi, - OPJ_BYTE *p_src, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *p_pack_info, - opj_event_mgr_t *p_manager); - -static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_tcp_t *p_tcp, - opj_pi_iterator_t *p_pi, - OPJ_BOOL * p_is_data_present, - OPJ_BYTE *p_src_data, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *p_pack_info, - opj_event_mgr_t *p_manager); +static OPJ_BOOL opj_t2_decode_packet(opj_t2_t* t2, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *src, + OPJ_UINT32 * data_read, + OPJ_UINT32 max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_t2_skip_packet(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BOOL * p_is_data_present, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager); static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, opj_tcd_tile_t *p_tile, @@ -144,10 +152,10 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2, @param cblksty @param first */ -static OPJ_BOOL opj_t2_init_seg( opj_tcd_cblk_dec_t* cblk, - OPJ_UINT32 index, - OPJ_UINT32 cblksty, - OPJ_UINT32 first); +static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 index, + OPJ_UINT32 cblksty, + OPJ_UINT32 first); /*@}*/ @@ -156,179 +164,197 @@ static OPJ_BOOL opj_t2_init_seg( opj_tcd_cblk_dec_t* cblk, /* ----------------------------------------------------------------------- */ /* #define RESTART 0x04 */ -static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n) { - while (--n >= 0) { - opj_bio_write(bio, 1, 1); - } - opj_bio_write(bio, 0, 1); +static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n) +{ + while (--n >= 0) { + opj_bio_write(bio, 1, 1); + } + opj_bio_write(bio, 0, 1); } static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio) { OPJ_UINT32 n = 0; while (opj_bio_read(bio, 1)) { - ++n; + ++n; } return n; } -static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) { - if (n == 1) { - opj_bio_write(bio, 0, 1); - } else if (n == 2) { - opj_bio_write(bio, 2, 2); - } else if (n <= 5) { - opj_bio_write(bio, 0xc | (n - 3), 4); - } else if (n <= 36) { - opj_bio_write(bio, 0x1e0 | (n - 6), 9); - } else if (n <= 164) { - opj_bio_write(bio, 0xff80 | (n - 37), 16); - } +static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) +{ + if (n == 1) { + opj_bio_write(bio, 0, 1); + } else if (n == 2) { + opj_bio_write(bio, 2, 2); + } else if (n <= 5) { + opj_bio_write(bio, 0xc | (n - 3), 4); + } else if (n <= 36) { + opj_bio_write(bio, 0x1e0 | (n - 6), 9); + } else if (n <= 164) { + opj_bio_write(bio, 0xff80 | (n - 37), 16); + } } -static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio) { - OPJ_UINT32 n; - if (!opj_bio_read(bio, 1)) - return 1; - if (!opj_bio_read(bio, 1)) - return 2; - if ((n = opj_bio_read(bio, 2)) != 3) - return (3 + n); - if ((n = opj_bio_read(bio, 5)) != 31) - return (6 + n); - return (37 + opj_bio_read(bio, 7)); +static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio) +{ + OPJ_UINT32 n; + if (!opj_bio_read(bio, 1)) { + return 1; + } + if (!opj_bio_read(bio, 1)) { + return 2; + } + if ((n = opj_bio_read(bio, 2)) != 3) { + return (3 + n); + } + if ((n = opj_bio_read(bio, 5)) != 31) { + return (6 + n); + } + return (37 + opj_bio_read(bio, 7)); } /* ----------------------------------------------------------------------- */ -OPJ_BOOL opj_t2_encode_packets( opj_t2_t* p_t2, - OPJ_UINT32 p_tile_no, - opj_tcd_tile_t *p_tile, - OPJ_UINT32 p_maxlayers, - OPJ_BYTE *p_dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_max_len, - opj_codestream_info_t *cstr_info, - OPJ_UINT32 p_tp_num, - OPJ_INT32 p_tp_pos, - OPJ_UINT32 p_pino, - J2K_T2_MODE p_t2_mode) +OPJ_BOOL opj_t2_encode_packets(opj_t2_t* p_t2, + OPJ_UINT32 p_tile_no, + opj_tcd_tile_t *p_tile, + OPJ_UINT32 p_maxlayers, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_len, + opj_codestream_info_t *cstr_info, + OPJ_UINT32 p_tp_num, + OPJ_INT32 p_tp_pos, + OPJ_UINT32 p_pino, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t *p_manager) { - OPJ_BYTE *l_current_data = p_dest; - OPJ_UINT32 l_nb_bytes = 0; - OPJ_UINT32 compno; - OPJ_UINT32 poc; - opj_pi_iterator_t *l_pi = 00; - opj_pi_iterator_t *l_current_pi = 00; - opj_image_t *l_image = p_t2->image; - opj_cp_t *l_cp = p_t2->cp; - opj_tcp_t *l_tcp = &l_cp->tcps[p_tile_no]; - OPJ_UINT32 pocno = (l_cp->rsiz == OPJ_PROFILE_CINEMA_4K)? 2: 1; - OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? l_image->numcomps : 1; - OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; - - l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode); - if (!l_pi) { - return OPJ_FALSE; - } - - * p_data_written = 0; - - if (p_t2_mode == THRESH_CALC ){ /* Calculating threshold */ - l_current_pi = l_pi; + OPJ_BYTE *l_current_data = p_dest; + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 compno; + OPJ_UINT32 poc; + opj_pi_iterator_t *l_pi = 00; + opj_pi_iterator_t *l_current_pi = 00; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_tcp_t *l_tcp = &l_cp->tcps[p_tile_no]; + OPJ_UINT32 pocno = (l_cp->rsiz == OPJ_PROFILE_CINEMA_4K) ? 2 : 1; + OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? + l_image->numcomps : 1; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + + l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode); + if (!l_pi) { + return OPJ_FALSE; + } - for (compno = 0; compno < l_max_comp; ++compno) { - OPJ_UINT32 l_comp_len = 0; - l_current_pi = l_pi; + * p_data_written = 0; - for (poc = 0; poc < pocno ; ++poc) { - OPJ_UINT32 l_tp_num = compno; + if (p_t2_mode == THRESH_CALC) { /* Calculating threshold */ + l_current_pi = l_pi; - /* TODO MSD : check why this function cannot fail (cf. v1) */ - opj_pi_create_encode(l_pi, l_cp,p_tile_no,poc,l_tp_num,p_tp_pos,p_t2_mode); + for (compno = 0; compno < l_max_comp; ++compno) { + OPJ_UINT32 l_comp_len = 0; + l_current_pi = l_pi; - if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { - /* TODO ADE : add an error */ - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } - while (opj_pi_next(l_current_pi)) { - if (l_current_pi->layno < p_maxlayers) { - l_nb_bytes = 0; + for (poc = 0; poc < pocno ; ++poc) { + OPJ_UINT32 l_tp_num = compno; - if (! opj_t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) { - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } + /* TODO MSD : check why this function cannot fail (cf. v1) */ + opj_pi_create_encode(l_pi, l_cp, p_tile_no, poc, l_tp_num, p_tp_pos, p_t2_mode); - l_comp_len += l_nb_bytes; - l_current_data += l_nb_bytes; - p_max_len -= l_nb_bytes; + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { + /* TODO ADE : add an error */ + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + while (opj_pi_next(l_current_pi)) { + if (l_current_pi->layno < p_maxlayers) { + l_nb_bytes = 0; + + if (! opj_t2_encode_packet(p_tile_no, p_tile, l_tcp, l_current_pi, + l_current_data, &l_nb_bytes, + p_max_len, cstr_info, + p_t2_mode, + p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } - * p_data_written += l_nb_bytes; - } - } + l_comp_len += l_nb_bytes; + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; - if (l_cp->m_specific_param.m_enc.m_max_comp_size) { - if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) { - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } - } + * p_data_written += l_nb_bytes; + } + } - ++l_current_pi; - } + if (l_cp->m_specific_param.m_enc.m_max_comp_size) { + if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } } + + ++l_current_pi; + } + } + } else { /* t2_mode == FINAL_PASS */ + opj_pi_create_encode(l_pi, l_cp, p_tile_no, p_pino, p_tp_num, p_tp_pos, + p_t2_mode); + + l_current_pi = &l_pi[p_pino]; + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { + /* TODO ADE : add an error */ + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; } - else { /* t2_mode == FINAL_PASS */ - opj_pi_create_encode(l_pi, l_cp,p_tile_no,p_pino,p_tp_num,p_tp_pos,p_t2_mode); + while (opj_pi_next(l_current_pi)) { + if (l_current_pi->layno < p_maxlayers) { + l_nb_bytes = 0; - l_current_pi = &l_pi[p_pino]; - if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { - /* TODO ADE : add an error */ + if (! opj_t2_encode_packet(p_tile_no, p_tile, l_tcp, l_current_pi, + l_current_data, &l_nb_bytes, p_max_len, + cstr_info, p_t2_mode, p_manager)) { opj_pi_destroy(l_pi, l_nb_pocs); return OPJ_FALSE; } - while (opj_pi_next(l_current_pi)) { - if (l_current_pi->layno < p_maxlayers) { - l_nb_bytes=0; - - if (! opj_t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) { - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } - - l_current_data += l_nb_bytes; - p_max_len -= l_nb_bytes; - - * p_data_written += l_nb_bytes; - - /* INDEX >> */ - if(cstr_info) { - if(cstr_info->index_write) { - opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no]; - opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; - if (!cstr_info->packno) { - info_PK->start_pos = info_TL->end_header + 1; - } else { - info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; - } - info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1; - info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance - to start of packet is incremented by value of start of packet*/ - } - cstr_info->packno++; - } - /* << INDEX */ - ++p_tile->packno; + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; + + * p_data_written += l_nb_bytes; + + /* INDEX >> */ + if (cstr_info) { + if (cstr_info->index_write) { + opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; + if (!cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else { + info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC) && + info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - + 1].end_pos + 1; } + info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1; + info_PK->end_ph_pos += info_PK->start_pos - + 1; /* End of packet header which now only represents the distance + to start of packet is incremented by value of start of packet*/ + } + + cstr_info->packno++; } + /* << INDEX */ + ++p_tile->packno; + } } + } - opj_pi_destroy(l_pi, l_nb_pocs); + opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_TRUE; + return OPJ_TRUE; } /* see issue 80 */ @@ -338,154 +364,208 @@ OPJ_BOOL opj_t2_encode_packets( opj_t2_t* p_t2, /* issue 290 */ static void opj_null_jas_fprintf(FILE* file, const char * format, ...) { - (void)file; - (void)format; + (void)file; + (void)format; } #define JAS_FPRINTF opj_null_jas_fprintf #endif -OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2, - OPJ_UINT32 p_tile_no, - opj_tcd_tile_t *p_tile, - OPJ_BYTE *p_src, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_len, - opj_codestream_index_t *p_cstr_index, - opj_event_mgr_t *p_manager) +OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd, + opj_t2_t *p_t2, + OPJ_UINT32 p_tile_no, + opj_tcd_tile_t *p_tile, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_len, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager) { - OPJ_BYTE *l_current_data = p_src; - opj_pi_iterator_t *l_pi = 00; - OPJ_UINT32 pino; - opj_image_t *l_image = p_t2->image; - opj_cp_t *l_cp = p_t2->cp; - opj_tcp_t *l_tcp = &(p_t2->cp->tcps[p_tile_no]); - OPJ_UINT32 l_nb_bytes_read; - OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; - opj_pi_iterator_t *l_current_pi = 00; + OPJ_BYTE *l_current_data = p_src; + opj_pi_iterator_t *l_pi = 00; + OPJ_UINT32 pino; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_tcp_t *l_tcp = &(p_t2->cp->tcps[p_tile_no]); + OPJ_UINT32 l_nb_bytes_read; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + opj_pi_iterator_t *l_current_pi = 00; #ifdef TODO_MSD - OPJ_UINT32 curtp = 0; - OPJ_UINT32 tp_start_packno; -#endif - opj_packet_info_t *l_pack_info = 00; - opj_image_comp_t* l_img_comp = 00; + OPJ_UINT32 curtp = 0; + OPJ_UINT32 tp_start_packno; +#endif + opj_packet_info_t *l_pack_info = 00; + opj_image_comp_t* l_img_comp = 00; - OPJ_ARG_NOT_USED(p_cstr_index); + OPJ_ARG_NOT_USED(p_cstr_index); #ifdef TODO_MSD - if (p_cstr_index) { - l_pack_info = p_cstr_index->tile_index[p_tile_no].packet; - } + if (p_cstr_index) { + l_pack_info = p_cstr_index->tile_index[p_tile_no].packet; + } #endif - /* create a packet iterator */ - l_pi = opj_pi_create_decode(l_image, l_cp, p_tile_no); - if (!l_pi) { - return OPJ_FALSE; - } + /* create a packet iterator */ + l_pi = opj_pi_create_decode(l_image, l_cp, p_tile_no); + if (!l_pi) { + return OPJ_FALSE; + } - l_current_pi = l_pi; + l_current_pi = l_pi; - for (pino = 0; pino <= l_tcp->numpocs; ++pino) { + for (pino = 0; pino <= l_tcp->numpocs; ++pino) { - /* if the resolution needed is too low, one dim of the tilec could be equal to zero - * and no packets are used to decode this resolution and - * l_current_pi->resno is always >= p_tile->comps[l_current_pi->compno].minimum_num_resolutions - * and no l_img_comp->resno_decoded are computed - */ - OPJ_BOOL* first_pass_failed = NULL; - - if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { - /* TODO ADE : add an error */ - opj_pi_destroy(l_pi, l_nb_pocs); - return OPJ_FALSE; - } - - first_pass_failed = (OPJ_BOOL*)opj_malloc(l_image->numcomps * sizeof(OPJ_BOOL)); - if (!first_pass_failed) - { - opj_pi_destroy(l_pi,l_nb_pocs); - return OPJ_FALSE; - } - memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL)); + /* if the resolution needed is too low, one dim of the tilec could be equal to zero + * and no packets are used to decode this resolution and + * l_current_pi->resno is always >= p_tile->comps[l_current_pi->compno].minimum_num_resolutions + * and no l_img_comp->resno_decoded are computed + */ + OPJ_BOOL* first_pass_failed = NULL; - while (opj_pi_next(l_current_pi)) { - JAS_FPRINTF( stderr, "packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n", - l_current_pi->poc.prg1, l_current_pi->compno, l_current_pi->resno, l_current_pi->precno, l_current_pi->layno ); + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { + /* TODO ADE : add an error */ + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } - if (l_tcp->num_layers_to_decode > l_current_pi->layno - && l_current_pi->resno < p_tile->comps[l_current_pi->compno].minimum_num_resolutions) { - l_nb_bytes_read = 0; + first_pass_failed = (OPJ_BOOL*)opj_malloc(l_image->numcomps * sizeof(OPJ_BOOL)); + if (!first_pass_failed) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL)); + + while (opj_pi_next(l_current_pi)) { + OPJ_BOOL skip_packet = OPJ_FALSE; + JAS_FPRINTF(stderr, + "packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n", + l_current_pi->poc.prg1, l_current_pi->compno, l_current_pi->resno, + l_current_pi->precno, l_current_pi->layno); + + /* If the packet layer is greater or equal than the maximum */ + /* number of layers, skip the packet */ + if (l_current_pi->layno >= l_tcp->num_layers_to_decode) { + skip_packet = OPJ_TRUE; + } + /* If the packet resolution number is greater than the minimum */ + /* number of resolution allowed, skip the packet */ + else if (l_current_pi->resno >= + p_tile->comps[l_current_pi->compno].minimum_num_resolutions) { + skip_packet = OPJ_TRUE; + } else { + /* If no precincts of any band intersects the area of interest, */ + /* skip the packet */ + OPJ_UINT32 bandno; + opj_tcd_tilecomp_t *tilec = &p_tile->comps[l_current_pi->compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[l_current_pi->resno]; + + skip_packet = OPJ_TRUE; + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* band = &res->bands[bandno]; + opj_tcd_precinct_t* prec = &band->precincts[l_current_pi->precno]; + + if (opj_tcd_is_subband_area_of_interest(tcd, + l_current_pi->compno, + l_current_pi->resno, + band->bandno, + (OPJ_UINT32)prec->x0, + (OPJ_UINT32)prec->y0, + (OPJ_UINT32)prec->x1, + (OPJ_UINT32)prec->y1)) { + skip_packet = OPJ_FALSE; + break; + } + } + /* + printf("packet cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d -> %s\n", + l_current_pi->compno, l_current_pi->resno, + l_current_pi->precno, l_current_pi->layno, skip_packet ? "skipped" : "kept"); + */ + } + + if (!skip_packet) { + l_nb_bytes_read = 0; - first_pass_failed[l_current_pi->compno] = OPJ_FALSE; + first_pass_failed[l_current_pi->compno] = OPJ_FALSE; - if (! opj_t2_decode_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info, p_manager)) { - opj_pi_destroy(l_pi,l_nb_pocs); - opj_free(first_pass_failed); - return OPJ_FALSE; - } + if (! opj_t2_decode_packet(p_t2, p_tile, l_tcp, l_current_pi, l_current_data, + &l_nb_bytes_read, p_max_len, l_pack_info, p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + opj_free(first_pass_failed); + return OPJ_FALSE; + } - l_img_comp = &(l_image->comps[l_current_pi->compno]); - l_img_comp->resno_decoded = opj_uint_max(l_current_pi->resno, l_img_comp->resno_decoded); - } - else { - l_nb_bytes_read = 0; - if (! opj_t2_skip_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info, p_manager)) { - opj_pi_destroy(l_pi,l_nb_pocs); - opj_free(first_pass_failed); - return OPJ_FALSE; - } - } + l_img_comp = &(l_image->comps[l_current_pi->compno]); + l_img_comp->resno_decoded = opj_uint_max(l_current_pi->resno, + l_img_comp->resno_decoded); + } else { + l_nb_bytes_read = 0; + if (! opj_t2_skip_packet(p_t2, p_tile, l_tcp, l_current_pi, l_current_data, + &l_nb_bytes_read, p_max_len, l_pack_info, p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + opj_free(first_pass_failed); + return OPJ_FALSE; + } + } - if (first_pass_failed[l_current_pi->compno]) { - l_img_comp = &(l_image->comps[l_current_pi->compno]); - if (l_img_comp->resno_decoded == 0) - l_img_comp->resno_decoded = p_tile->comps[l_current_pi->compno].minimum_num_resolutions - 1; - } + if (first_pass_failed[l_current_pi->compno]) { + l_img_comp = &(l_image->comps[l_current_pi->compno]); + if (l_img_comp->resno_decoded == 0) { + l_img_comp->resno_decoded = + p_tile->comps[l_current_pi->compno].minimum_num_resolutions - 1; + } + } - l_current_data += l_nb_bytes_read; - p_max_len -= l_nb_bytes_read; + l_current_data += l_nb_bytes_read; + p_max_len -= l_nb_bytes_read; - /* INDEX >> */ + /* INDEX >> */ #ifdef TODO_MSD - if(p_cstr_info) { - opj_tile_info_v2_t *info_TL = &p_cstr_info->tile[p_tile_no]; - opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno]; - tp_start_packno = 0; - if (!p_cstr_info->packno) { - info_PK->start_pos = info_TL->end_header + 1; - } else if (info_TL->packet[p_cstr_info->packno-1].end_pos >= (OPJ_INT32)p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_pos){ /* New tile part */ - info_TL->tp[curtp].tp_numpacks = p_cstr_info->packno - tp_start_packno; /* Number of packets in previous tile-part */ - tp_start_packno = p_cstr_info->packno; - curtp++; - info_PK->start_pos = p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_header+1; - } else { - info_PK->start_pos = (l_cp->m_specific_param.m_enc.m_tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[p_cstr_info->packno - 1].end_pos + 1; - } - info_PK->end_pos = info_PK->start_pos + l_nb_bytes_read - 1; - info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance */ - ++p_cstr_info->packno; - } -#endif - /* << INDEX */ + if (p_cstr_info) { + opj_tile_info_v2_t *info_TL = &p_cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno]; + tp_start_packno = 0; + if (!p_cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else if (info_TL->packet[p_cstr_info->packno - 1].end_pos >= + (OPJ_INT32) + p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_pos) { /* New tile part */ + info_TL->tp[curtp].tp_numpacks = p_cstr_info->packno - + tp_start_packno; /* Number of packets in previous tile-part */ + tp_start_packno = p_cstr_info->packno; + curtp++; + info_PK->start_pos = p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_header + 1; + } else { + info_PK->start_pos = (l_cp->m_specific_param.m_enc.m_tp_on && + info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[p_cstr_info->packno - + 1].end_pos + 1; } - ++l_current_pi; - - opj_free(first_pass_failed); + info_PK->end_pos = info_PK->start_pos + l_nb_bytes_read - 1; + info_PK->end_ph_pos += info_PK->start_pos - + 1; /* End of packet header which now only represents the distance */ + ++p_cstr_info->packno; + } +#endif + /* << INDEX */ } - /* INDEX >> */ + ++l_current_pi; + + opj_free(first_pass_failed); + } + /* INDEX >> */ #ifdef TODO_MSD - if - (p_cstr_info) { - p_cstr_info->tile[p_tile_no].tp[curtp].tp_numpacks = p_cstr_info->packno - tp_start_packno; /* Number of packets in last tile-part */ - } + if + (p_cstr_info) { + p_cstr_info->tile[p_tile_no].tp[curtp].tp_numpacks = p_cstr_info->packno - + tp_start_packno; /* Number of packets in last tile-part */ + } #endif - /* << INDEX */ + /* << INDEX */ - /* don't forget to release pi */ - opj_pi_destroy(l_pi,l_nb_pocs); - *p_data_read = (OPJ_UINT32)(l_current_data - p_src); - return OPJ_TRUE; + /* don't forget to release pi */ + opj_pi_destroy(l_pi, l_nb_pocs); + *p_data_read = (OPJ_UINT32)(l_current_data - p_src); + return OPJ_TRUE; } /* ----------------------------------------------------------------------- */ @@ -499,883 +579,985 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2, */ opj_t2_t* opj_t2_create(opj_image_t *p_image, opj_cp_t *p_cp) { - /* create the t2 structure */ - opj_t2_t *l_t2 = (opj_t2_t*)opj_calloc(1,sizeof(opj_t2_t)); - if (!l_t2) { - return NULL; - } + /* create the t2 structure */ + opj_t2_t *l_t2 = (opj_t2_t*)opj_calloc(1, sizeof(opj_t2_t)); + if (!l_t2) { + return NULL; + } - l_t2->image = p_image; - l_t2->cp = p_cp; + l_t2->image = p_image; + l_t2->cp = p_cp; - return l_t2; + return l_t2; } -void opj_t2_destroy(opj_t2_t *t2) { - if(t2) { - opj_free(t2); - } +void opj_t2_destroy(opj_t2_t *t2) +{ + if (t2) { + opj_free(t2); + } } -static OPJ_BOOL opj_t2_decode_packet( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_tcp_t *p_tcp, - opj_pi_iterator_t *p_pi, - OPJ_BYTE *p_src, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *p_pack_info, - opj_event_mgr_t *p_manager) +static OPJ_BOOL opj_t2_decode_packet(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager) { - OPJ_BOOL l_read_data; - OPJ_UINT32 l_nb_bytes_read = 0; - OPJ_UINT32 l_nb_total_bytes_read = 0; + OPJ_BOOL l_read_data; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_nb_total_bytes_read = 0; - *p_data_read = 0; + *p_data_read = 0; - if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) { - return OPJ_FALSE; - } + if (! opj_t2_read_packet_header(p_t2, p_tile, p_tcp, p_pi, &l_read_data, p_src, + &l_nb_bytes_read, p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; + } - p_src += l_nb_bytes_read; - l_nb_total_bytes_read += l_nb_bytes_read; - p_max_length -= l_nb_bytes_read; + p_src += l_nb_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + p_max_length -= l_nb_bytes_read; - /* we should read data for the packet */ - if (l_read_data) { - l_nb_bytes_read = 0; + /* we should read data for the packet */ + if (l_read_data) { + l_nb_bytes_read = 0; - if (! opj_t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) { - return OPJ_FALSE; - } - - l_nb_total_bytes_read += l_nb_bytes_read; + if (! opj_t2_read_packet_data(p_t2, p_tile, p_pi, p_src, &l_nb_bytes_read, + p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; } - *p_data_read = l_nb_total_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + } + + *p_data_read = l_nb_total_bytes_read; - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_t2_encode_packet( OPJ_UINT32 tileno, - opj_tcd_tile_t * tile, - opj_tcp_t * tcp, - opj_pi_iterator_t *pi, - OPJ_BYTE *dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 length, - opj_codestream_info_t *cstr_info) +static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, + opj_tcd_tile_t * tile, + opj_tcp_t * tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 length, + opj_codestream_info_t *cstr_info, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t *p_manager) { - OPJ_UINT32 bandno, cblkno; - OPJ_BYTE* c = dest; - OPJ_UINT32 l_nb_bytes; - OPJ_UINT32 compno = pi->compno; /* component value */ - OPJ_UINT32 resno = pi->resno; /* resolution level value */ - OPJ_UINT32 precno = pi->precno; /* precinct value */ - OPJ_UINT32 layno = pi->layno; /* quality layer value */ - OPJ_UINT32 l_nb_blocks; - opj_tcd_band_t *band = 00; - opj_tcd_cblk_enc_t* cblk = 00; - opj_tcd_pass_t *pass = 00; - - opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - - opj_bio_t *bio = 00; /* BIO component */ - - /* <SOP 0xff91> */ - if (tcp->csty & J2K_CP_CSTY_SOP) { - c[0] = 255; - c[1] = 145; - c[2] = 0; - c[3] = 4; + OPJ_UINT32 bandno, cblkno; + OPJ_BYTE* c = dest; + OPJ_UINT32 l_nb_bytes; + OPJ_UINT32 compno = pi->compno; /* component value */ + OPJ_UINT32 resno = pi->resno; /* resolution level value */ + OPJ_UINT32 precno = pi->precno; /* precinct value */ + OPJ_UINT32 layno = pi->layno; /* quality layer value */ + OPJ_UINT32 l_nb_blocks; + opj_tcd_band_t *band = 00; + opj_tcd_cblk_enc_t* cblk = 00; + opj_tcd_pass_t *pass = 00; + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + opj_bio_t *bio = 00; /* BIO component */ + OPJ_BOOL packet_empty = OPJ_TRUE; + + /* <SOP 0xff91> */ + if (tcp->csty & J2K_CP_CSTY_SOP) { + if (length < 6) { + if (p_t2_mode == FINAL_PASS) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): only %u bytes remaining in " + "output buffer. %u needed.\n", + length, 6); + } + return OPJ_FALSE; + } + c[0] = 255; + c[1] = 145; + c[2] = 0; + c[3] = 4; #if 0 - c[4] = (tile->packno % 65536) / 256; - c[5] = (tile->packno % 65536) % 256; + c[4] = (tile->packno % 65536) / 256; + c[5] = (tile->packno % 65536) % 256; #else - c[4] = (tile->packno >> 8) & 0xff; /* packno is uint32_t */ - c[5] = tile->packno & 0xff; + c[4] = (tile->packno >> 8) & 0xff; /* packno is uint32_t */ + c[5] = tile->packno & 0xff; #endif - c += 6; - length -= 6; - } - /* </SOP> */ + c += 6; + length -= 6; + } + /* </SOP> */ - if (!layno) { - band = res->bands; + if (!layno) { + band = res->bands; - for(bandno = 0; bandno < res->numbands; ++bandno) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (bandno = 0; bandno < res->numbands; ++bandno, ++band) { + opj_tcd_precinct_t *prc; - opj_tgt_reset(prc->incltree); - opj_tgt_reset(prc->imsbtree); + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } - l_nb_blocks = prc->cw * prc->ch; - for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { - cblk = &prc->cblks.enc[cblkno]; + prc = &band->precincts[precno]; + opj_tgt_reset(prc->incltree); + opj_tgt_reset(prc->imsbtree); - cblk->numpasses = 0; - opj_tgt_setvalue(prc->imsbtree, cblkno, band->numbps - (OPJ_INT32)cblk->numbps); - } - ++band; - } + l_nb_blocks = prc->cw * prc->ch; + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + cblk = &prc->cblks.enc[cblkno]; + + cblk->numpasses = 0; + opj_tgt_setvalue(prc->imsbtree, cblkno, band->numbps - (OPJ_INT32)cblk->numbps); + } } + } - bio = opj_bio_create(); - if (!bio) { - /* FIXME event manager error callback */ - return OPJ_FALSE; + bio = opj_bio_create(); + if (!bio) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + opj_bio_init_enc(bio, c, length); + + /* Check if the packet is empty */ + /* Note: we could also skip that step and always write a packet header */ + band = res->bands; + for (bandno = 0; bandno < res->numbands; ++bandno, ++band) { + opj_tcd_precinct_t *prc; + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; } - opj_bio_init_enc(bio, c, length); - opj_bio_write(bio, 1, 1); /* Empty header bit */ - /* Writing Packet header */ - band = res->bands; - for (bandno = 0; bandno < res->numbands; ++bandno) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; + prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + for (cblkno = 0; cblkno < l_nb_blocks; cblkno++, ++cblk) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + /* if cblk not included, go to the next cblk */ + if (!layer->numpasses) { + continue; + } + packet_empty = OPJ_FALSE; + break; + } + if (!packet_empty) { + break; + } + } - l_nb_blocks = prc->cw * prc->ch; - cblk = prc->cblks.enc; + opj_bio_write(bio, packet_empty ? 0 : 1, 1); /* Empty header bit */ - for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { - opj_tcd_layer_t *layer = &cblk->layers[layno]; - if (!cblk->numpasses && layer->numpasses) { - opj_tgt_setvalue(prc->incltree, cblkno, (OPJ_INT32)layno); - } + /* Writing Packet header */ + band = res->bands; + for (bandno = 0; !packet_empty && + bandno < res->numbands; ++bandno, ++band) { + opj_tcd_precinct_t *prc; - ++cblk; - } + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } - cblk = prc->cblks.enc; - for (cblkno = 0; cblkno < l_nb_blocks; cblkno++) { - opj_tcd_layer_t *layer = &cblk->layers[layno]; - OPJ_UINT32 increment = 0; - OPJ_UINT32 nump = 0; - OPJ_UINT32 len = 0, passno; - OPJ_UINT32 l_nb_passes; - - /* cblk inclusion bits */ - if (!cblk->numpasses) { - opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1)); - } else { - opj_bio_write(bio, layer->numpasses != 0, 1); - } + prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; - /* if cblk not included, go to the next cblk */ - if (!layer->numpasses) { - ++cblk; - continue; - } + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; - /* if first instance of cblk --> zero bit-planes information */ - if (!cblk->numpasses) { - cblk->numlenbits = 3; - opj_tgt_encode(bio, prc->imsbtree, cblkno, 999); - } + if (!cblk->numpasses && layer->numpasses) { + opj_tgt_setvalue(prc->incltree, cblkno, (OPJ_INT32)layno); + } + + ++cblk; + } - /* number of coding passes included */ - opj_t2_putnumpasses(bio, layer->numpasses); - l_nb_passes = cblk->numpasses + layer->numpasses; - pass = cblk->passes + cblk->numpasses; + cblk = prc->cblks.enc; + for (cblkno = 0; cblkno < l_nb_blocks; cblkno++) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 increment = 0; + OPJ_UINT32 nump = 0; + OPJ_UINT32 len = 0, passno; + OPJ_UINT32 l_nb_passes; + + /* cblk inclusion bits */ + if (!cblk->numpasses) { + opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1)); + } else { + opj_bio_write(bio, layer->numpasses != 0, 1); + } + + /* if cblk not included, go to the next cblk */ + if (!layer->numpasses) { + ++cblk; + continue; + } + + /* if first instance of cblk --> zero bit-planes information */ + if (!cblk->numpasses) { + cblk->numlenbits = 3; + opj_tgt_encode(bio, prc->imsbtree, cblkno, 999); + } + + /* number of coding passes included */ + opj_t2_putnumpasses(bio, layer->numpasses); + l_nb_passes = cblk->numpasses + layer->numpasses; + pass = cblk->passes + cblk->numpasses; + + /* computation of the increase of the length indicator and insertion in the header */ + for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { + ++nump; + len += pass->len; + + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + increment = (OPJ_UINT32)opj_int_max((OPJ_INT32)increment, + opj_int_floorlog2((OPJ_INT32)len) + 1 + - ((OPJ_INT32)cblk->numlenbits + opj_int_floorlog2((OPJ_INT32)nump))); + len = 0; + nump = 0; + } - /* computation of the increase of the length indicator and insertion in the header */ - for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { - ++nump; - len += pass->len; + ++pass; + } + opj_t2_putcommacode(bio, (OPJ_INT32)increment); - if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { - increment = (OPJ_UINT32)opj_int_max((OPJ_INT32)increment, opj_int_floorlog2((OPJ_INT32)len) + 1 - - ((OPJ_INT32)cblk->numlenbits + opj_int_floorlog2((OPJ_INT32)nump))); - len = 0; - nump = 0; - } + /* computation of the new Length indicator */ + cblk->numlenbits += increment; - ++pass; - } - opj_t2_putcommacode(bio, (OPJ_INT32)increment); - - /* computation of the new Length indicator */ - cblk->numlenbits += increment; - - pass = cblk->passes + cblk->numpasses; - /* insertion of the codeword segment length */ - for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { - nump++; - len += pass->len; - - if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { - opj_bio_write(bio, (OPJ_UINT32)len, cblk->numlenbits + (OPJ_UINT32)opj_int_floorlog2((OPJ_INT32)nump)); - len = 0; - nump = 0; - } - ++pass; - } + pass = cblk->passes + cblk->numpasses; + /* insertion of the codeword segment length */ + for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { + nump++; + len += pass->len; - ++cblk; + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + opj_bio_write(bio, (OPJ_UINT32)len, + cblk->numlenbits + (OPJ_UINT32)opj_int_floorlog2((OPJ_INT32)nump)); + len = 0; + nump = 0; } + ++pass; + } - ++band; - } - - if (!opj_bio_flush(bio)) { - opj_bio_destroy(bio); - return OPJ_FALSE; /* modified to eliminate longjmp !! */ + ++cblk; } + } - l_nb_bytes = (OPJ_UINT32)opj_bio_numbytes(bio); - c += l_nb_bytes; - length -= l_nb_bytes; - + if (!opj_bio_flush(bio)) { opj_bio_destroy(bio); + return OPJ_FALSE; /* modified to eliminate longjmp !! */ + } - /* <EPH 0xff92> */ - if (tcp->csty & J2K_CP_CSTY_EPH) { - c[0] = 255; - c[1] = 146; - c += 2; - length -= 2; + l_nb_bytes = (OPJ_UINT32)opj_bio_numbytes(bio); + c += l_nb_bytes; + length -= l_nb_bytes; + + opj_bio_destroy(bio); + + /* <EPH 0xff92> */ + if (tcp->csty & J2K_CP_CSTY_EPH) { + if (length < 2) { + if (p_t2_mode == FINAL_PASS) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): only %u bytes remaining in " + "output buffer. %u needed.\n", + length, 2); + } + return OPJ_FALSE; } - /* </EPH> */ + c[0] = 255; + c[1] = 146; + c += 2; + length -= 2; + } + /* </EPH> */ + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + Will be updated later by incrementing with packet start value*/ + if (cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->end_ph_pos = (OPJ_INT32)(c - dest); + } + /* INDEX >> */ - /* << INDEX */ - /* End of packet header position. Currently only represents the distance to start of packet - Will be updated later by incrementing with packet start value*/ - if(cstr_info && cstr_info->index_write) { - opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; - info_PK->end_ph_pos = (OPJ_INT32)(c - dest); - } - /* INDEX >> */ + /* Writing the packet body */ + band = res->bands; + for (bandno = 0; !packet_empty && bandno < res->numbands; bandno++, ++band) { + opj_tcd_precinct_t *prc; - /* Writing the packet body */ - band = res->bands; - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } - l_nb_blocks = prc->cw * prc->ch; - cblk = prc->cblks.enc; + prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; - for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { - opj_tcd_layer_t *layer = &cblk->layers[layno]; + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; - if (!layer->numpasses) { - ++cblk; - continue; - } + if (!layer->numpasses) { + ++cblk; + continue; + } - if (layer->len > length) { - return OPJ_FALSE; - } + if (layer->len > length) { + if (p_t2_mode == FINAL_PASS) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): only %u bytes remaining in " + "output buffer. %u needed.\n", + length, layer->len); + } + return OPJ_FALSE; + } - memcpy(c, layer->data, layer->len); - cblk->numpasses += layer->numpasses; - c += layer->len; - length -= layer->len; - - /* << INDEX */ - if(cstr_info && cstr_info->index_write) { - opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; - info_PK->disto += layer->disto; - if (cstr_info->D_max < info_PK->disto) { - cstr_info->D_max = info_PK->disto; - } - } + memcpy(c, layer->data, layer->len); + cblk->numpasses += layer->numpasses; + c += layer->len; + length -= layer->len; - ++cblk; - /* INDEX >> */ + /* << INDEX */ + if (cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->disto += layer->disto; + if (cstr_info->D_max < info_PK->disto) { + cstr_info->D_max = info_PK->disto; } - ++band; + } + + ++cblk; + /* INDEX >> */ } + } - assert( c >= dest ); - * p_data_written += (OPJ_UINT32)(c - dest); + assert(c >= dest); + * p_data_written += (OPJ_UINT32)(c - dest); - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_t2_skip_packet( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_tcp_t *p_tcp, - opj_pi_iterator_t *p_pi, - OPJ_BYTE *p_src, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *p_pack_info, - opj_event_mgr_t *p_manager) +static OPJ_BOOL opj_t2_skip_packet(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager) { - OPJ_BOOL l_read_data; - OPJ_UINT32 l_nb_bytes_read = 0; - OPJ_UINT32 l_nb_total_bytes_read = 0; + OPJ_BOOL l_read_data; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_nb_total_bytes_read = 0; - *p_data_read = 0; + *p_data_read = 0; - if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) { - return OPJ_FALSE; - } - - p_src += l_nb_bytes_read; - l_nb_total_bytes_read += l_nb_bytes_read; - p_max_length -= l_nb_bytes_read; + if (! opj_t2_read_packet_header(p_t2, p_tile, p_tcp, p_pi, &l_read_data, p_src, + &l_nb_bytes_read, p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; + } - /* we should read data for the packet */ - if (l_read_data) { - l_nb_bytes_read = 0; + p_src += l_nb_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + p_max_length -= l_nb_bytes_read; - if (! opj_t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info, p_manager)) { - return OPJ_FALSE; - } + /* we should read data for the packet */ + if (l_read_data) { + l_nb_bytes_read = 0; - l_nb_total_bytes_read += l_nb_bytes_read; + if (! opj_t2_skip_packet_data(p_t2, p_tile, p_pi, &l_nb_bytes_read, + p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; } - *p_data_read = l_nb_total_bytes_read; - return OPJ_TRUE; + l_nb_total_bytes_read += l_nb_bytes_read; + } + *p_data_read = l_nb_total_bytes_read; + + return OPJ_TRUE; } -static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_tcp_t *p_tcp, - opj_pi_iterator_t *p_pi, - OPJ_BOOL * p_is_data_present, - OPJ_BYTE *p_src_data, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *p_pack_info, - opj_event_mgr_t *p_manager) +static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BOOL * p_is_data_present, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager) { - /* loop */ - OPJ_UINT32 bandno, cblkno; - OPJ_UINT32 l_nb_code_blocks; - OPJ_UINT32 l_remaining_length; - OPJ_UINT32 l_header_length; - OPJ_UINT32 * l_modified_length_ptr = 00; - OPJ_BYTE *l_current_data = p_src_data; - opj_cp_t *l_cp = p_t2->cp; - opj_bio_t *l_bio = 00; /* BIO component */ - opj_tcd_band_t *l_band = 00; - opj_tcd_cblk_dec_t* l_cblk = 00; - opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; - - OPJ_BYTE *l_header_data = 00; - OPJ_BYTE **l_header_data_start = 00; - - OPJ_UINT32 l_present; - - if (p_pi->layno == 0) { - l_band = l_res->bands; - - /* reset tagtrees */ - for (bandno = 0; bandno < l_res->numbands; ++bandno) { - opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; - - if ( ! ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) ) { - opj_tgt_reset(l_prc->incltree); - opj_tgt_reset(l_prc->imsbtree); - l_cblk = l_prc->cblks.dec; - - l_nb_code_blocks = l_prc->cw * l_prc->ch; - for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { - l_cblk->numsegs = 0; - l_cblk->real_num_segs = 0; - ++l_cblk; - } - } + /* loop */ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + OPJ_UINT32 l_remaining_length; + OPJ_UINT32 l_header_length; + OPJ_UINT32 * l_modified_length_ptr = 00; + OPJ_BYTE *l_current_data = p_src_data; + opj_cp_t *l_cp = p_t2->cp; + opj_bio_t *l_bio = 00; /* BIO component */ + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = + &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + OPJ_BYTE *l_header_data = 00; + OPJ_BYTE **l_header_data_start = 00; + + OPJ_UINT32 l_present; + + if (p_pi->layno == 0) { + l_band = l_res->bands; - ++l_band; + /* reset tagtrees */ + for (bandno = 0; bandno < l_res->numbands; ++bandno) { + if (!opj_tcd_is_band_empty(l_band)) { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + if (!(p_pi->precno < (l_band->precincts_data_size / sizeof( + opj_tcd_precinct_t)))) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct\n"); + return OPJ_FALSE; } - } - /* SOP markers */ - if (p_tcp->csty & J2K_CP_CSTY_SOP) { - if (p_max_length < 6) { - opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected SOP marker\n"); - } else if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) { - opj_event_msg(p_manager, EVT_WARNING, "Expected SOP marker\n"); - } else { - l_current_data += 6; + opj_tgt_reset(l_prc->incltree); + opj_tgt_reset(l_prc->imsbtree); + l_cblk = l_prc->cblks.dec; + + l_nb_code_blocks = l_prc->cw * l_prc->ch; + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + l_cblk->numsegs = 0; + l_cblk->real_num_segs = 0; + ++l_cblk; } + } - /** TODO : check the Nsop value */ + ++l_band; } + } - /* - When the marker PPT/PPM is used the packet header are store in PPT/PPM marker - This part deal with this caracteristic - step 1: Read packet header in the saved structure - step 2: Return to codestream for decoding - */ + /* SOP markers */ - l_bio = opj_bio_create(); - if (! l_bio) { - return OPJ_FALSE; + if (p_tcp->csty & J2K_CP_CSTY_SOP) { + if (p_max_length < 6) { + opj_event_msg(p_manager, EVT_WARNING, + "Not enough space for expected SOP marker\n"); + } else if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) { + opj_event_msg(p_manager, EVT_WARNING, "Expected SOP marker\n"); + } else { + l_current_data += 6; } - if (l_cp->ppm == 1) { /* PPM */ - l_header_data_start = &l_cp->ppm_data; - l_header_data = *l_header_data_start; - l_modified_length_ptr = &(l_cp->ppm_len); - - } - else if (p_tcp->ppt == 1) { /* PPT */ - l_header_data_start = &(p_tcp->ppt_data); - l_header_data = *l_header_data_start; - l_modified_length_ptr = &(p_tcp->ppt_len); - } - else { /* Normal Case */ - l_header_data_start = &(l_current_data); - l_header_data = *l_header_data_start; - l_remaining_length = (OPJ_UINT32)(p_src_data+p_max_length-l_header_data); - l_modified_length_ptr = &(l_remaining_length); - } + /** TODO : check the Nsop value */ + } - opj_bio_init_dec(l_bio, l_header_data,*l_modified_length_ptr); - - l_present = opj_bio_read(l_bio, 1); - JAS_FPRINTF(stderr, "present=%d \n", l_present ); - if (!l_present) { - /* TODO MSD: no test to control the output of this function*/ - opj_bio_inalign(l_bio); - l_header_data += opj_bio_numbytes(l_bio); - opj_bio_destroy(l_bio); - - /* EPH markers */ - if (p_tcp->csty & J2K_CP_CSTY_EPH) { - if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - *l_header_data_start)) < 2U) { - opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected EPH marker\n"); - } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { - opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); - } else { - l_header_data += 2; - } - } + /* + When the marker PPT/PPM is used the packet header are store in PPT/PPM marker + This part deal with this caracteristic + step 1: Read packet header in the saved structure + step 2: Return to codestream for decoding + */ - l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); - *l_modified_length_ptr -= l_header_length; - *l_header_data_start += l_header_length; + l_bio = opj_bio_create(); + if (! l_bio) { + return OPJ_FALSE; + } - /* << INDEX */ - /* End of packet header position. Currently only represents the distance to start of packet - Will be updated later by incrementing with packet start value */ - if (p_pack_info) { - p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); - } - /* INDEX >> */ + if (l_cp->ppm == 1) { /* PPM */ + l_header_data_start = &l_cp->ppm_data; + l_header_data = *l_header_data_start; + l_modified_length_ptr = &(l_cp->ppm_len); + + } else if (p_tcp->ppt == 1) { /* PPT */ + l_header_data_start = &(p_tcp->ppt_data); + l_header_data = *l_header_data_start; + l_modified_length_ptr = &(p_tcp->ppt_len); + } else { /* Normal Case */ + l_header_data_start = &(l_current_data); + l_header_data = *l_header_data_start; + l_remaining_length = (OPJ_UINT32)(p_src_data + p_max_length - l_header_data); + l_modified_length_ptr = &(l_remaining_length); + } - * p_is_data_present = OPJ_FALSE; - *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data); - return OPJ_TRUE; - } + opj_bio_init_dec(l_bio, l_header_data, *l_modified_length_ptr); - l_band = l_res->bands; - for (bandno = 0; bandno < l_res->numbands; ++bandno) { - opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]); + l_present = opj_bio_read(l_bio, 1); + JAS_FPRINTF(stderr, "present=%d \n", l_present); + if (!l_present) { + /* TODO MSD: no test to control the output of this function*/ + opj_bio_inalign(l_bio); + l_header_data += opj_bio_numbytes(l_bio); + opj_bio_destroy(l_bio); - if ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) { - ++l_band; - continue; - } + /* EPH markers */ + if (p_tcp->csty & J2K_CP_CSTY_EPH) { + if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - + *l_header_data_start)) < 2U) { + opj_event_msg(p_manager, EVT_WARNING, + "Not enough space for expected EPH marker\n"); + } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); + } else { + l_header_data += 2; + } + } - l_nb_code_blocks = l_prc->cw * l_prc->ch; - l_cblk = l_prc->cblks.dec; - for (cblkno = 0; cblkno < l_nb_code_blocks; cblkno++) { - OPJ_UINT32 l_included,l_increment, l_segno; - OPJ_INT32 n; - - /* if cblk not yet included before --> inclusion tagtree */ - if (!l_cblk->numsegs) { - l_included = opj_tgt_decode(l_bio, l_prc->incltree, cblkno, (OPJ_INT32)(p_pi->layno + 1)); - /* else one bit */ - } - else { - l_included = opj_bio_read(l_bio, 1); - } + l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); + *l_modified_length_ptr -= l_header_length; + *l_header_data_start += l_header_length; - /* if cblk not included */ - if (!l_included) { - l_cblk->numnewpasses = 0; - ++l_cblk; - JAS_FPRINTF(stderr, "included=%d \n", l_included); - continue; - } + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + Will be updated later by incrementing with packet start value */ + if (p_pack_info) { + p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); + } + /* INDEX >> */ - /* if cblk not yet included --> zero-bitplane tagtree */ - if (!l_cblk->numsegs) { - OPJ_UINT32 i = 0; + * p_is_data_present = OPJ_FALSE; + *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data); + return OPJ_TRUE; + } - while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) { - ++i; - } + l_band = l_res->bands; + for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band) { + opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]); - l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i; - l_cblk->numlenbits = 3; - } + if (opj_tcd_is_band_empty(l_band)) { + continue; + } - /* number of coding passes */ - l_cblk->numnewpasses = opj_t2_getnumpasses(l_bio); - l_increment = opj_t2_getcommacode(l_bio); + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + for (cblkno = 0; cblkno < l_nb_code_blocks; cblkno++) { + OPJ_UINT32 l_included, l_increment, l_segno; + OPJ_INT32 n; + + /* if cblk not yet included before --> inclusion tagtree */ + if (!l_cblk->numsegs) { + l_included = opj_tgt_decode(l_bio, l_prc->incltree, cblkno, + (OPJ_INT32)(p_pi->layno + 1)); + /* else one bit */ + } else { + l_included = opj_bio_read(l_bio, 1); + } + + /* if cblk not included */ + if (!l_included) { + l_cblk->numnewpasses = 0; + ++l_cblk; + JAS_FPRINTF(stderr, "included=%d \n", l_included); + continue; + } + + /* if cblk not yet included --> zero-bitplane tagtree */ + if (!l_cblk->numsegs) { + OPJ_UINT32 i = 0; + + while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) { + ++i; + } - /* length indicator increment */ - l_cblk->numlenbits += l_increment; - l_segno = 0; + l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i; + l_cblk->numlenbits = 3; + } - if (!l_cblk->numsegs) { - if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) { - opj_bio_destroy(l_bio); - return OPJ_FALSE; - } - } - else { - l_segno = l_cblk->numsegs - 1; - if (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) { - ++l_segno; - if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { - opj_bio_destroy(l_bio); - return OPJ_FALSE; - } - } - } - n = (OPJ_INT32)l_cblk->numnewpasses; + /* number of coding passes */ + l_cblk->numnewpasses = opj_t2_getnumpasses(l_bio); + l_increment = opj_t2_getcommacode(l_bio); - do { - l_cblk->segs[l_segno].numnewpasses = (OPJ_UINT32)opj_int_min((OPJ_INT32)(l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses), n); - l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, l_cblk->numlenbits + opj_uint_floorlog2(l_cblk->segs[l_segno].numnewpasses)); - JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n", l_included, l_cblk->segs[l_segno].numnewpasses, l_increment, l_cblk->segs[l_segno].newlen ); + /* length indicator increment */ + l_cblk->numlenbits += l_increment; + l_segno = 0; - n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses; - if (n > 0) { - ++l_segno; + if (!l_cblk->numsegs) { + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + } else { + l_segno = l_cblk->numsegs - 1; + if (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) { + ++l_segno; + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + } + } + n = (OPJ_INT32)l_cblk->numnewpasses; + + do { + OPJ_UINT32 bit_number; + l_cblk->segs[l_segno].numnewpasses = (OPJ_UINT32)opj_int_min((OPJ_INT32)( + l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses), n); + bit_number = l_cblk->numlenbits + opj_uint_floorlog2( + l_cblk->segs[l_segno].numnewpasses); + if (bit_number > 32) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid bit number %d in opj_t2_read_packet_header()\n", + bit_number); + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, bit_number); + JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n", + l_included, l_cblk->segs[l_segno].numnewpasses, l_increment, + l_cblk->segs[l_segno].newlen); - if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { - opj_bio_destroy(l_bio); - return OPJ_FALSE; - } - } - } while (n > 0); + n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses; + if (n > 0) { + ++l_segno; - ++l_cblk; + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } } + } while (n > 0); - ++l_band; - } - - if (!opj_bio_inalign(l_bio)) { - opj_bio_destroy(l_bio); - return OPJ_FALSE; + ++l_cblk; } + } - l_header_data += opj_bio_numbytes(l_bio); + if (!opj_bio_inalign(l_bio)) { opj_bio_destroy(l_bio); + return OPJ_FALSE; + } - /* EPH markers */ - if (p_tcp->csty & J2K_CP_CSTY_EPH) { - if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - *l_header_data_start)) < 2U) { - opj_event_msg(p_manager, EVT_WARNING, "Not enough space for expected EPH marker\n"); - } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { - opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); - } else { - l_header_data += 2; - } + l_header_data += opj_bio_numbytes(l_bio); + opj_bio_destroy(l_bio); + + /* EPH markers */ + if (p_tcp->csty & J2K_CP_CSTY_EPH) { + if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - + *l_header_data_start)) < 2U) { + opj_event_msg(p_manager, EVT_WARNING, + "Not enough space for expected EPH marker\n"); + } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); + } else { + l_header_data += 2; } + } - l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); - JAS_FPRINTF( stderr, "hdrlen=%d \n", l_header_length ); - JAS_FPRINTF( stderr, "packet body\n"); - *l_modified_length_ptr -= l_header_length; - *l_header_data_start += l_header_length; - - /* << INDEX */ - /* End of packet header position. Currently only represents the distance to start of packet - Will be updated later by incrementing with packet start value */ - if (p_pack_info) { - p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); - } - /* INDEX >> */ + l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); + JAS_FPRINTF(stderr, "hdrlen=%d \n", l_header_length); + JAS_FPRINTF(stderr, "packet body\n"); + *l_modified_length_ptr -= l_header_length; + *l_header_data_start += l_header_length; + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + Will be updated later by incrementing with packet start value */ + if (p_pack_info) { + p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); + } + /* INDEX >> */ - *p_is_data_present = OPJ_TRUE; - *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data); + *p_is_data_present = OPJ_TRUE; + *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data); - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_t2_read_packet_data( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_pi_iterator_t *p_pi, - OPJ_BYTE *p_src_data, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *pack_info, - opj_event_mgr_t* p_manager) +static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t* p_manager) { - OPJ_UINT32 bandno, cblkno; - OPJ_UINT32 l_nb_code_blocks; - OPJ_BYTE *l_current_data = p_src_data; - opj_tcd_band_t *l_band = 00; - opj_tcd_cblk_dec_t* l_cblk = 00; - opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + OPJ_BYTE *l_current_data = p_src_data; + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = + &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + OPJ_ARG_NOT_USED(p_t2); + OPJ_ARG_NOT_USED(pack_info); + + l_band = l_res->bands; + for (bandno = 0; bandno < l_res->numbands; ++bandno) { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + + if ((l_band->x1 - l_band->x0 == 0) || (l_band->y1 - l_band->y0 == 0)) { + ++l_band; + continue; + } - OPJ_ARG_NOT_USED(p_t2); - OPJ_ARG_NOT_USED(pack_info); + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; - l_band = l_res->bands; - for (bandno = 0; bandno < l_res->numbands; ++bandno) { - opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + opj_tcd_seg_t *l_seg = 00; + + if (!l_cblk->numnewpasses) { + /* nothing to do */ + ++l_cblk; + continue; + } + + if (!l_cblk->numsegs) { + l_seg = l_cblk->segs; + ++l_cblk->numsegs; + } else { + l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; - if ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) { - ++l_band; - continue; + if (l_seg->numpasses == l_seg->maxpasses) { + ++l_seg; + ++l_cblk->numsegs; + } + } + + do { + /* Check possible overflow (on l_current_data only, assumes input args already checked) then size */ + if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) < + (OPJ_SIZE_T)l_current_data) || + (l_current_data + l_seg->newlen > p_src_data + p_max_length)) { + opj_event_msg(p_manager, EVT_ERROR, + "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, + p_pi->compno); + return OPJ_FALSE; } - l_nb_code_blocks = l_prc->cw * l_prc->ch; - l_cblk = l_prc->cblks.dec; +#ifdef USE_JPWL + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((l_cblk->len + l_seg->newlen) > 8192) { + opj_event_msg(p_manager, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + l_seg->newlen = 8192 - l_cblk->len; + opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n", + l_seg->newlen); + break; + }; - for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { - opj_tcd_seg_t *l_seg = 00; +#endif /* USE_JPWL */ - if (!l_cblk->numnewpasses) { - /* nothing to do */ - ++l_cblk; - continue; - } + if (l_cblk->numchunks == l_cblk->numchunksalloc) { + OPJ_UINT32 l_numchunksalloc = l_cblk->numchunksalloc * 2 + 1; + opj_tcd_seg_data_chunk_t* l_chunks = + (opj_tcd_seg_data_chunk_t*)opj_realloc(l_cblk->chunks, + l_numchunksalloc * sizeof(opj_tcd_seg_data_chunk_t)); + if (l_chunks == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "cannot allocate opj_tcd_seg_data_chunk_t* array"); + return OPJ_FALSE; + } + l_cblk->chunks = l_chunks; + l_cblk->numchunksalloc = l_numchunksalloc; + } - if (!l_cblk->numsegs) { - l_seg = l_cblk->segs; - ++l_cblk->numsegs; - l_cblk->data_current_size = 0; - } - else { - l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; + l_cblk->chunks[l_cblk->numchunks].data = l_current_data; + l_cblk->chunks[l_cblk->numchunks].len = l_seg->newlen; + l_cblk->numchunks ++; - if (l_seg->numpasses == l_seg->maxpasses) { - ++l_seg; - ++l_cblk->numsegs; - } - } + l_current_data += l_seg->newlen; + l_seg->len += l_seg->newlen; + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; - do { - /* Check possible overflow (on l_current_data only, assumes input args already checked) then size */ - if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) < (OPJ_SIZE_T)l_current_data) || (l_current_data + l_seg->newlen > p_src_data + p_max_length)) { - opj_event_msg(p_manager, EVT_ERROR, "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); - return OPJ_FALSE; - } + l_seg->real_num_passes = l_seg->numpasses; -#ifdef USE_JPWL - /* we need here a j2k handle to verify if making a check to - the validity of cblocks parameters is selected from user (-W) */ - - /* let's check that we are not exceeding */ - if ((l_cblk->len + l_seg->newlen) > 8192) { - opj_event_msg(p_manager, EVT_WARNING, - "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return OPJ_FALSE; - } - l_seg->newlen = 8192 - l_cblk->len; - opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n", l_seg->newlen); - break; - }; + if (l_cblk->numnewpasses > 0) { + ++l_seg; + ++l_cblk->numsegs; + } + } while (l_cblk->numnewpasses > 0); -#endif /* USE_JPWL */ - /* Check possible overflow on size */ - if ((l_cblk->data_current_size + l_seg->newlen) < l_cblk->data_current_size) { - opj_event_msg(p_manager, EVT_ERROR, "read: segment too long (%d) with current size (%d > %d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, l_cblk->data_current_size, 0xFFFFFFFF - l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); - return OPJ_FALSE; - } - /* Check if the cblk->data have allocated enough memory */ - if ((l_cblk->data_current_size + l_seg->newlen) > l_cblk->data_max_size) { - OPJ_BYTE* new_cblk_data = (OPJ_BYTE*) opj_realloc(l_cblk->data, l_cblk->data_current_size + l_seg->newlen); - if(! new_cblk_data) { - opj_free(l_cblk->data); - l_cblk->data = NULL; - l_cblk->data_max_size = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to realloc code block cata!\n"); */ - return OPJ_FALSE; - } - l_cblk->data_max_size = l_cblk->data_current_size + l_seg->newlen; - l_cblk->data = new_cblk_data; - } - - memcpy(l_cblk->data + l_cblk->data_current_size, l_current_data, l_seg->newlen); - - if (l_seg->numpasses == 0) { - l_seg->data = &l_cblk->data; - l_seg->dataindex = l_cblk->data_current_size; - } - - l_current_data += l_seg->newlen; - l_seg->numpasses += l_seg->numnewpasses; - l_cblk->numnewpasses -= l_seg->numnewpasses; - - l_seg->real_num_passes = l_seg->numpasses; - l_cblk->data_current_size += l_seg->newlen; - l_seg->len += l_seg->newlen; - - if (l_cblk->numnewpasses > 0) { - ++l_seg; - ++l_cblk->numsegs; - } - } while (l_cblk->numnewpasses > 0); - - l_cblk->real_num_segs = l_cblk->numsegs; - ++l_cblk; - } /* next code_block */ - - ++l_band; - } + l_cblk->real_num_segs = l_cblk->numsegs; + ++l_cblk; + } /* next code_block */ - *(p_data_read) = (OPJ_UINT32)(l_current_data - p_src_data); + ++l_band; + } + *(p_data_read) = (OPJ_UINT32)(l_current_data - p_src_data); - return OPJ_TRUE; + + return OPJ_TRUE; } -static OPJ_BOOL opj_t2_skip_packet_data( opj_t2_t* p_t2, - opj_tcd_tile_t *p_tile, - opj_pi_iterator_t *p_pi, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_length, - opj_packet_info_t *pack_info, - opj_event_mgr_t *p_manager) +static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t *p_manager) { - OPJ_UINT32 bandno, cblkno; - OPJ_UINT32 l_nb_code_blocks; - opj_tcd_band_t *l_band = 00; - opj_tcd_cblk_dec_t* l_cblk = 00; - opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; - - OPJ_ARG_NOT_USED(p_t2); - OPJ_ARG_NOT_USED(pack_info); + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = + &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; - *p_data_read = 0; - l_band = l_res->bands; + OPJ_ARG_NOT_USED(p_t2); + OPJ_ARG_NOT_USED(pack_info); - for (bandno = 0; bandno < l_res->numbands; ++bandno) { - opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + *p_data_read = 0; + l_band = l_res->bands; - if ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) { - ++l_band; - continue; - } + for (bandno = 0; bandno < l_res->numbands; ++bandno) { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; - l_nb_code_blocks = l_prc->cw * l_prc->ch; - l_cblk = l_prc->cblks.dec; + if ((l_band->x1 - l_band->x0 == 0) || (l_band->y1 - l_band->y0 == 0)) { + ++l_band; + continue; + } - for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { - opj_tcd_seg_t *l_seg = 00; + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; - if (!l_cblk->numnewpasses) { - /* nothing to do */ - ++l_cblk; - continue; - } + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + opj_tcd_seg_t *l_seg = 00; - if (!l_cblk->numsegs) { - l_seg = l_cblk->segs; - ++l_cblk->numsegs; - l_cblk->data_current_size = 0; - } - else { - l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; + if (!l_cblk->numnewpasses) { + /* nothing to do */ + ++l_cblk; + continue; + } - if (l_seg->numpasses == l_seg->maxpasses) { - ++l_seg; - ++l_cblk->numsegs; - } - } + if (!l_cblk->numsegs) { + l_seg = l_cblk->segs; + ++l_cblk->numsegs; + } else { + l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; - do { - /* Check possible overflow then size */ - if (((*p_data_read + l_seg->newlen) < (*p_data_read)) || ((*p_data_read + l_seg->newlen) > p_max_length)) { - opj_event_msg(p_manager, EVT_ERROR, "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); - return OPJ_FALSE; - } + if (l_seg->numpasses == l_seg->maxpasses) { + ++l_seg; + ++l_cblk->numsegs; + } + } + + do { + /* Check possible overflow then size */ + if (((*p_data_read + l_seg->newlen) < (*p_data_read)) || + ((*p_data_read + l_seg->newlen) > p_max_length)) { + opj_event_msg(p_manager, EVT_ERROR, + "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, + p_pi->compno); + return OPJ_FALSE; + } #ifdef USE_JPWL - /* we need here a j2k handle to verify if making a check to - the validity of cblocks parameters is selected from user (-W) */ - - /* let's check that we are not exceeding */ - if ((l_cblk->len + l_seg->newlen) > 8192) { - opj_event_msg(p_manager, EVT_WARNING, - "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); - if (!JPWL_ASSUME) { - opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); - return -999; - } - l_seg->newlen = 8192 - l_cblk->len; - opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n", l_seg->newlen); - break; - }; + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((l_cblk->len + l_seg->newlen) > 8192) { + opj_event_msg(p_manager, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return -999; + } + l_seg->newlen = 8192 - l_cblk->len; + opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n", + l_seg->newlen); + break; + }; #endif /* USE_JPWL */ - JAS_FPRINTF(stderr, "p_data_read (%d) newlen (%d) \n", *p_data_read, l_seg->newlen ); - *(p_data_read) += l_seg->newlen; - - l_seg->numpasses += l_seg->numnewpasses; - l_cblk->numnewpasses -= l_seg->numnewpasses; - if (l_cblk->numnewpasses > 0) - { - ++l_seg; - ++l_cblk->numsegs; - } - } while (l_cblk->numnewpasses > 0); - - ++l_cblk; + JAS_FPRINTF(stderr, "p_data_read (%d) newlen (%d) \n", *p_data_read, + l_seg->newlen); + *(p_data_read) += l_seg->newlen; + + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; + if (l_cblk->numnewpasses > 0) { + ++l_seg; + ++l_cblk->numsegs; } + } while (l_cblk->numnewpasses > 0); - ++l_band; + ++l_cblk; } - return OPJ_TRUE; + ++l_band; + } + + return OPJ_TRUE; } -OPJ_BOOL opj_t2_init_seg( opj_tcd_cblk_dec_t* cblk, - OPJ_UINT32 index, - OPJ_UINT32 cblksty, - OPJ_UINT32 first) +static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 index, + OPJ_UINT32 cblksty, + OPJ_UINT32 first) { - opj_tcd_seg_t* seg = 00; - OPJ_UINT32 l_nb_segs = index + 1; - - if (l_nb_segs > cblk->m_current_max_segs) { - opj_tcd_seg_t* new_segs; - cblk->m_current_max_segs += OPJ_J2K_DEFAULT_NB_SEGS; - - new_segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, cblk->m_current_max_segs * sizeof(opj_tcd_seg_t)); - if(! new_segs) { - opj_free(cblk->segs); - cblk->segs = NULL; - cblk->m_current_max_segs = 0; - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to initialize segment %d\n", l_nb_segs); */ - return OPJ_FALSE; - } - cblk->segs = new_segs; + opj_tcd_seg_t* seg = 00; + OPJ_UINT32 l_nb_segs = index + 1; + + if (l_nb_segs > cblk->m_current_max_segs) { + opj_tcd_seg_t* new_segs; + OPJ_UINT32 l_m_current_max_segs = cblk->m_current_max_segs + + OPJ_J2K_DEFAULT_NB_SEGS; + + new_segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, + l_m_current_max_segs * sizeof(opj_tcd_seg_t)); + if (! new_segs) { + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to initialize segment %d\n", l_nb_segs); */ + return OPJ_FALSE; } + cblk->segs = new_segs; + memset(new_segs + cblk->m_current_max_segs, + 0, OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t)); + cblk->m_current_max_segs = l_m_current_max_segs; + } - seg = &cblk->segs[index]; - memset(seg,0,sizeof(opj_tcd_seg_t)); + seg = &cblk->segs[index]; + opj_tcd_reinit_segment(seg); - if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { - seg->maxpasses = 1; - } - else if (cblksty & J2K_CCP_CBLKSTY_LAZY) { - if (first) { - seg->maxpasses = 10; - } else { - seg->maxpasses = (((seg - 1)->maxpasses == 1) || ((seg - 1)->maxpasses == 10)) ? 2 : 1; - } + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + seg->maxpasses = 1; + } else if (cblksty & J2K_CCP_CBLKSTY_LAZY) { + if (first) { + seg->maxpasses = 10; } else { - seg->maxpasses = 109; + seg->maxpasses = (((seg - 1)->maxpasses == 1) || + ((seg - 1)->maxpasses == 10)) ? 2 : 1; } + } else { + /* See paragraph "B.10.6 Number of coding passes" of the standard. + * Probably that 109 must be interpreted a (Mb-1)*3 + 1 with Mb=37, + * Mb being the maximum number of bit-planes available for the + * representation of coefficients in the sub-band */ + seg->maxpasses = 109; + } - return OPJ_TRUE; + return OPJ_TRUE; } diff --git a/third_party/libopenjpeg20/t2.h b/third_party/libopenjpeg20/t2.h index 3b652eeab547f83fc172507b709d688242fb17b0..66500b1699334d7752f9ad86eec672379028105b 100644 --- a/third_party/libopenjpeg20/t2.h +++ b/third_party/libopenjpeg20/t2.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,11 +8,12 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,8 +37,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __T2_H -#define __T2_H +#ifndef OPJ_T2_H +#define OPJ_T2_H /** @file t2.h @brief Implementation of a tier-2 coding (packetization of code-block data) (T2) @@ -52,10 +53,10 @@ Tier-2 coding */ typedef struct opj_t2 { - /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */ - opj_image_t *image; - /** pointer to the image coding parameters */ - opj_cp_t *cp; + /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */ + opj_image_t *image; + /** pointer to the image coding parameters */ + opj_cp_t *cp; } opj_t2_t; /** @name Exported functions */ @@ -75,23 +76,26 @@ Encode the packets of a tile to a destination buffer @param tpnum Tile part number of the current tile @param tppos The position of the tile part flag in the progression order @param pino FIXME DOC -@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass +@param t2_mode If == THRESH_CALC In Threshold calculation ,If == FINAL_PASS Final pass +@param p_manager the user event manager */ -OPJ_BOOL opj_t2_encode_packets( opj_t2_t* t2, - OPJ_UINT32 tileno, - opj_tcd_tile_t *tile, - OPJ_UINT32 maxlayers, - OPJ_BYTE *dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 len, - opj_codestream_info_t *cstr_info, - OPJ_UINT32 tpnum, - OPJ_INT32 tppos, - OPJ_UINT32 pino, - J2K_T2_MODE t2_mode); +OPJ_BOOL opj_t2_encode_packets(opj_t2_t* t2, + OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + OPJ_UINT32 maxlayers, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + OPJ_UINT32 pino, + J2K_T2_MODE t2_mode, + opj_event_mgr_t *p_manager); /** Decode the packets of a tile from a source buffer +@param tcd TCD handle @param t2 T2 handle @param tileno number that identifies the tile for which to decode the packets @param tile tile for which to decode the packets @@ -99,24 +103,26 @@ Decode the packets of a tile from a source buffer @param p_data_read the source buffer @param len length of the source buffer @param cstr_info FIXME DOC +@param p_manager the user event manager @return FIXME DOC */ -OPJ_BOOL opj_t2_decode_packets( opj_t2_t *t2, - OPJ_UINT32 tileno, - opj_tcd_tile_t *tile, - OPJ_BYTE *src, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 len, - opj_codestream_index_t *cstr_info, - opj_event_mgr_t *p_manager); +OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd, + opj_t2_t *t2, + OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + OPJ_BYTE *src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 len, + opj_codestream_index_t *cstr_info, + opj_event_mgr_t *p_manager); /** * Creates a Tier 2 handle * - * @param p_image Source or destination image - * @param p_cp Image coding parameters. - * @return a new T2 handle if successful, NULL otherwise. + * @param p_image Source or destination image + * @param p_cp Image coding parameters. + * @return a new T2 handle if successful, NULL otherwise. */ opj_t2_t* opj_t2_create(opj_image_t *p_image, opj_cp_t *p_cp); @@ -131,4 +137,4 @@ void opj_t2_destroy(opj_t2_t *t2); /*@}*/ -#endif /* __T2_H */ +#endif /* OPJ_T2_H */ diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c index 06eee4ebd5600c53f53a814e23a66d8804b910fa..7298fa39345b7801b40fa70b2d6c595472458164 100644 --- a/third_party/libopenjpeg20/tcd.c +++ b/third_party/libopenjpeg20/tcd.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,12 +8,13 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,100 +40,108 @@ */ #include "opj_includes.h" +#include "opj_common.h" /* ----------------------------------------------------------------------- */ /* TODO MSD: */ -#ifdef TODO_MSD -void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) { - int tileno, compno, resno, bandno, precno;/*, cblkno;*/ - - fprintf(fd, "image {\n"); - fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n", - img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, tcd->image->y1); - - for (tileno = 0; tileno < img->th * img->tw; tileno++) { - opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno]; - fprintf(fd, " tile {\n"); - fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n", - tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps); - for (compno = 0; compno < tile->numcomps; compno++) { - opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; - fprintf(fd, " tilec {\n"); +#ifdef TODO_MSD +void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) +{ + int tileno, compno, resno, bandno, precno;/*, cblkno;*/ + + fprintf(fd, "image {\n"); + fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n", + img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, + tcd->image->y1); + + for (tileno = 0; tileno < img->th * img->tw; tileno++) { + opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno]; + fprintf(fd, " tile {\n"); + fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n", + tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + fprintf(fd, " tilec {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n", + tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions); + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + fprintf(fd, "\n res {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n", + res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands); + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + fprintf(fd, " band {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n", + band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps); + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + fprintf(fd, " prec {\n"); fprintf(fd, - " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n", - tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions); - for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - fprintf(fd, "\n res {\n"); + " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n", + prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch); + /* + for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) { + opj_tcd_cblk_t *cblk = &prec->cblks[cblkno]; + fprintf(fd, " cblk {\n"); fprintf(fd, - " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n", - res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands); - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; - fprintf(fd, " band {\n"); - fprintf(fd, - " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n", - band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps); - for (precno = 0; precno < res->pw * res->ph; precno++) { - opj_tcd_precinct_t *prec = &band->precincts[precno]; - fprintf(fd, " prec {\n"); - fprintf(fd, - " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n", - prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch); - /* - for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) { - opj_tcd_cblk_t *cblk = &prec->cblks[cblkno]; - fprintf(fd, " cblk {\n"); - fprintf(fd, - " x0=%d, y0=%d, x1=%d, y1=%d\n", - cblk->x0, cblk->y0, cblk->x1, cblk->y1); - fprintf(fd, " }\n"); - } - */ - fprintf(fd, " }\n"); - } - fprintf(fd, " }\n"); - } - fprintf(fd, " }\n"); + " x0=%d, y0=%d, x1=%d, y1=%d\n", + cblk->x0, cblk->y0, cblk->x1, cblk->y1); + fprintf(fd, " }\n"); } - fprintf(fd, " }\n"); + */ + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); } - fprintf(fd, " }\n"); + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); } - fprintf(fd, "}\n"); + fprintf(fd, " }\n"); + } + fprintf(fd, "}\n"); } #endif /** * Initializes tile coding/decoding */ -static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager); +static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, + opj_event_mgr_t* manager); /** * Allocates memory for a decoding code block. */ -static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block); +static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t * + p_code_block); /** * Deallocates the decoding data of the given precinct. */ -static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct); +static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct); /** * Allocates memory for an encoding code block (but not data). */ -static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block); +static OPJ_BOOL opj_tcd_code_block_enc_allocate(opj_tcd_cblk_enc_t * + p_code_block); /** * Allocates data for an encoding code block */ -static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block); +static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * + p_code_block); /** * Deallocates the encoding data of the given precinct. */ -static void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct); +static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct); /** @@ -142,40 +151,48 @@ Free the memory allocated for encoding static void opj_tcd_free_tile(opj_tcd_t *tcd); -static OPJ_BOOL opj_tcd_t2_decode ( opj_tcd_t *p_tcd, - OPJ_BYTE * p_src_data, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_src_size, - opj_codestream_index_t *p_cstr_index, - opj_event_mgr_t *p_manager); +static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_src_size, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd); -static OPJ_BOOL opj_tcd_t1_decode (opj_tcd_t *p_tcd); +static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, + opj_event_mgr_t *p_manager); -static OPJ_BOOL opj_tcd_dwt_decode (opj_tcd_t *p_tcd); +static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd); -static OPJ_BOOL opj_tcd_mct_decode (opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager); -static OPJ_BOOL opj_tcd_dc_level_shift_decode (opj_tcd_t *p_tcd); +static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd); +static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd); -static OPJ_BOOL opj_tcd_dc_level_shift_encode ( opj_tcd_t *p_tcd ); +static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd); -static OPJ_BOOL opj_tcd_mct_encode ( opj_tcd_t *p_tcd ); +static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd); -static OPJ_BOOL opj_tcd_dwt_encode ( opj_tcd_t *p_tcd ); +static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager); -static OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd ); +static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager); -static OPJ_BOOL opj_tcd_t2_encode ( opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info ); -static OPJ_BOOL opj_tcd_rate_allocate_encode( opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest_data, - OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info ); +static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *tcd, + OPJ_UINT32 compno); /* ----------------------------------------------------------------------- */ @@ -184,1307 +201,1625 @@ Create a new TCD handle */ opj_tcd_t* opj_tcd_create(OPJ_BOOL p_is_decoder) { - opj_tcd_t *l_tcd = 00; + opj_tcd_t *l_tcd = 00; - /* create the tcd structure */ - l_tcd = (opj_tcd_t*) opj_calloc(1,sizeof(opj_tcd_t)); - if (!l_tcd) { - return 00; - } + /* create the tcd structure */ + l_tcd = (opj_tcd_t*) opj_calloc(1, sizeof(opj_tcd_t)); + if (!l_tcd) { + return 00; + } - l_tcd->m_is_decoder = p_is_decoder ? 1 : 0; + l_tcd->m_is_decoder = p_is_decoder ? 1 : 0; - l_tcd->tcd_image = (opj_tcd_image_t*)opj_calloc(1,sizeof(opj_tcd_image_t)); - if (!l_tcd->tcd_image) { - opj_free(l_tcd); - return 00; - } + l_tcd->tcd_image = (opj_tcd_image_t*)opj_calloc(1, sizeof(opj_tcd_image_t)); + if (!l_tcd->tcd_image) { + opj_free(l_tcd); + return 00; + } - return l_tcd; + return l_tcd; } /* ----------------------------------------------------------------------- */ -void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) { - OPJ_UINT32 layno; +void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) +{ + OPJ_UINT32 layno; - for (layno = 0; layno < tcd->tcp->numlayers; layno++) { - opj_tcd_makelayer_fixed(tcd, layno, 1); - } + for (layno = 0; layno < tcd->tcp->numlayers; layno++) { + opj_tcd_makelayer_fixed(tcd, layno, 1); + } } -void opj_tcd_makelayer( opj_tcd_t *tcd, - OPJ_UINT32 layno, - OPJ_FLOAT64 thresh, - OPJ_UINT32 final) +void opj_tcd_makelayer(opj_tcd_t *tcd, + OPJ_UINT32 layno, + OPJ_FLOAT64 thresh, + OPJ_UINT32 final) { - OPJ_UINT32 compno, resno, bandno, precno, cblkno; - OPJ_UINT32 passno; - - opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; - - tcd_tile->distolayer[layno] = 0; /* fixed_quality */ - - for (compno = 0; compno < tcd_tile->numcomps; compno++) { - opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; - - for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; - - for (precno = 0; precno < res->pw * res->ph; precno++) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; - - for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { - opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; - opj_tcd_layer_t *layer = &cblk->layers[layno]; - OPJ_UINT32 n; - - if (layno == 0) { - cblk->numpassesinlayers = 0; - } - - n = cblk->numpassesinlayers; - - for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { - OPJ_UINT32 dr; - OPJ_FLOAT64 dd; - opj_tcd_pass_t *pass = &cblk->passes[passno]; - - if (n == 0) { - dr = pass->rate; - dd = pass->distortiondec; - } else { - dr = pass->rate - cblk->passes[n - 1].rate; - dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; - } - - if (!dr) { - if (dd != 0) - n = passno + 1; - continue; - } - if (thresh - (dd / dr) < DBL_EPSILON) /* do not rely on float equality, check with DBL_EPSILON margin */ - n = passno + 1; - } - - layer->numpasses = n - cblk->numpassesinlayers; - - if (!layer->numpasses) { - layer->disto = 0; - continue; - } - - if (cblk->numpassesinlayers == 0) { - layer->len = cblk->passes[n - 1].rate; - layer->data = cblk->data; - layer->disto = cblk->passes[n - 1].distortiondec; - } else { - layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; - layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; - layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec; - } - - tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */ - - if (final) - cblk->numpassesinlayers = n; - } - } - } + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + OPJ_UINT32 passno; + + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + + tcd_tile->distolayer[layno] = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; } - } -} -void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final) { - OPJ_UINT32 compno, resno, bandno, precno, cblkno; - OPJ_INT32 value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */ - OPJ_INT32 matrice[10][10][3]; - OPJ_UINT32 i, j, k; - - opj_cp_t *cp = tcd->cp; - opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; - opj_tcp_t *tcd_tcp = tcd->tcp; - - for (compno = 0; compno < tcd_tile->numcomps; compno++) { - opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; - - for (i = 0; i < tcd_tcp->numlayers; i++) { - for (j = 0; j < tilec->numresolutions; j++) { - for (k = 0; k < 3; k++) { - matrice[i][j][k] = - (OPJ_INT32) ((OPJ_FLOAT32)cp->m_specific_param.m_enc.m_matrice[i * tilec->numresolutions * 3 + j * 3 + k] - * (OPJ_FLOAT32) (tcd->image->comps[compno].prec / 16.0)); - } + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 n; + + if (layno == 0) { + cblk->numpassesinlayers = 0; } - } - for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; - - for (precno = 0; precno < res->pw * res->ph; precno++) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; - - for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { - opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; - opj_tcd_layer_t *layer = &cblk->layers[layno]; - OPJ_UINT32 n; - OPJ_INT32 imsb = (OPJ_INT32)(tcd->image->comps[compno].prec - cblk->numbps); /* number of bit-plan equal to zero */ - - /* Correction of the matrix of coefficient to include the IMSB information */ - if (layno == 0) { - value = matrice[layno][resno][bandno]; - if (imsb >= value) { - value = 0; - } else { - value -= imsb; - } - } else { - value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno]; - if (imsb >= matrice[layno - 1][resno][bandno]) { - value -= (imsb - matrice[layno - 1][resno][bandno]); - if (value < 0) { - value = 0; - } - } - } - - if (layno == 0) { - cblk->numpassesinlayers = 0; - } - - n = cblk->numpassesinlayers; - if (cblk->numpassesinlayers == 0) { - if (value != 0) { - n = 3 * (OPJ_UINT32)value - 2 + cblk->numpassesinlayers; - } else { - n = cblk->numpassesinlayers; - } - } else { - n = 3 * (OPJ_UINT32)value + cblk->numpassesinlayers; - } - - layer->numpasses = n - cblk->numpassesinlayers; - - if (!layer->numpasses) - continue; - - if (cblk->numpassesinlayers == 0) { - layer->len = cblk->passes[n - 1].rate; - layer->data = cblk->data; - } else { - layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; - layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; - } - - if (final) - cblk->numpassesinlayers = n; - } + n = cblk->numpassesinlayers; + + if (thresh < 0) { + /* Special value to indicate to use all passes */ + n = cblk->totalpasses; + } else { + for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { + OPJ_UINT32 dr; + OPJ_FLOAT64 dd; + opj_tcd_pass_t *pass = &cblk->passes[passno]; + + if (n == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[n - 1].rate; + dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; } + + if (!dr) { + if (dd != 0) { + n = passno + 1; + } + continue; + } + if (thresh - (dd / dr) < + DBL_EPSILON) { /* do not rely on float equality, check with DBL_EPSILON margin */ + n = passno + 1; + } + } } + + layer->numpasses = n - cblk->numpassesinlayers; + + if (!layer->numpasses) { + layer->disto = 0; + continue; + } + + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + layer->disto = cblk->passes[n - 1].distortiondec; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - + 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->disto = cblk->passes[n - 1].distortiondec - + cblk->passes[cblk->numpassesinlayers - 1].distortiondec; + } + + tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */ + + if (final) { + cblk->numpassesinlayers = n; + } + } } + } } + } } -OPJ_BOOL opj_tcd_rateallocate( opj_tcd_t *tcd, - OPJ_BYTE *dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 len, - opj_codestream_info_t *cstr_info) +void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, + OPJ_UINT32 final) { - OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno; - OPJ_UINT32 passno; - OPJ_FLOAT64 min, max; - OPJ_FLOAT64 cumdisto[100]; /* fixed_quality */ - const OPJ_FLOAT64 K = 1; /* 1.1; fixed_quality */ - OPJ_FLOAT64 maxSE = 0; - - opj_cp_t *cp = tcd->cp; - opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; - opj_tcp_t *tcd_tcp = tcd->tcp; - - min = DBL_MAX; - max = 0; - - tcd_tile->numpix = 0; /* fixed_quality */ - - for (compno = 0; compno < tcd_tile->numcomps; compno++) { - opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; - tilec->numpix = 0; - - for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; - - for (precno = 0; precno < res->pw * res->ph; precno++) { - opj_tcd_precinct_t *prc = &band->precincts[precno]; - - for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { - opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; - - for (passno = 0; passno < cblk->totalpasses; passno++) { - opj_tcd_pass_t *pass = &cblk->passes[passno]; - OPJ_INT32 dr; - OPJ_FLOAT64 dd, rdslope; - - if (passno == 0) { - dr = (OPJ_INT32)pass->rate; - dd = pass->distortiondec; - } else { - dr = (OPJ_INT32)(pass->rate - cblk->passes[passno - 1].rate); - dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec; - } - - if (dr == 0) { - continue; - } - - rdslope = dd / dr; - if (rdslope < min) { - min = rdslope; - } - - if (rdslope > max) { - max = rdslope; - } - } /* passno */ - - /* fixed_quality */ - tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); - tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); - } /* cbklno */ - } /* precno */ - } /* bandno */ - } /* resno */ - - maxSE += (((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0) - * ((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) -1.0)) - * ((OPJ_FLOAT64)(tilec->numpix)); - } /* compno */ - - /* index file */ - if(cstr_info) { - opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno]; - tile_info->numpix = tcd_tile->numpix; - tile_info->distotile = tcd_tile->distotile; - tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof(OPJ_FLOAT64)); - if (!tile_info->thresh) { - /* FIXME event manager error callback */ - return OPJ_FALSE; + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + OPJ_INT32 value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */ + OPJ_INT32 matrice[10][10][3]; + OPJ_UINT32 i, j, k; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + opj_tcp_t *tcd_tcp = tcd->tcp; + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + + for (i = 0; i < tcd_tcp->numlayers; i++) { + for (j = 0; j < tilec->numresolutions; j++) { + for (k = 0; k < 3; k++) { + matrice[i][j][k] = + (OPJ_INT32)((OPJ_FLOAT32)cp->m_specific_param.m_enc.m_matrice[i * + tilec->numresolutions * 3 + j * 3 + k] + * (OPJ_FLOAT32)(tcd->image->comps[compno].prec / 16.0)); } + } } - for (layno = 0; layno < tcd_tcp->numlayers; layno++) { - OPJ_FLOAT64 lo = min; - OPJ_FLOAT64 hi = max; - OPJ_BOOL success = OPJ_FALSE; - OPJ_UINT32 maxlen = tcd_tcp->rates[layno] ? opj_uint_min(((OPJ_UINT32) ceil(tcd_tcp->rates[layno])), len) : len; - OPJ_FLOAT64 goodthresh = 0; - OPJ_FLOAT64 stable_thresh = 0; - OPJ_UINT32 i; - OPJ_FLOAT64 distotarget; /* fixed_quality */ - - /* fixed_quality */ - distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10, tcd_tcp->distoratio[layno] / 10)); - - /* Don't try to find an optimal threshold but rather take everything not included yet, if - -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0) - -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0) - ==> possible to have some lossy layers and the last layer for sure lossless */ - if ( ((cp->m_specific_param.m_enc.m_disto_alloc==1) && (tcd_tcp->rates[layno]>0)) || ((cp->m_specific_param.m_enc.m_fixed_quality==1) && (tcd_tcp->distoratio[layno]>0))) { - opj_t2_t*t2 = opj_t2_create(tcd->image, cp); - OPJ_FLOAT64 thresh = 0; - - if (t2 == 00) { - return OPJ_FALSE; - } + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - for (i = 0; i < 128; ++i) { - OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */ - - thresh = (lo + hi) / 2; - - opj_tcd_makelayer(tcd, layno, thresh, 0); - - if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ - if(OPJ_IS_CINEMA(cp->rsiz)){ - if (! opj_t2_encode_packets(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) { - - lo = thresh; - continue; - } - else { - distoachieved = layno == 0 ? - tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; - - if (distoachieved < distotarget) { - hi=thresh; - stable_thresh = thresh; - continue; - }else{ - lo=thresh; - } - } - }else{ - distoachieved = (layno == 0) ? - tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); - - if (distoachieved < distotarget) { - hi = thresh; - stable_thresh = thresh; - continue; - } - lo = thresh; - } - } else { - if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) - { - /* TODO: what to do with l ??? seek / tell ??? */ - /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ - lo = thresh; - continue; - } - - hi = thresh; - stable_thresh = thresh; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 n; + OPJ_INT32 imsb = (OPJ_INT32)(tcd->image->comps[compno].prec - + cblk->numbps); /* number of bit-plan equal to zero */ + + /* Correction of the matrix of coefficient to include the IMSB information */ + if (layno == 0) { + value = matrice[layno][resno][bandno]; + if (imsb >= value) { + value = 0; + } else { + value -= imsb; + } + } else { + value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno]; + if (imsb >= matrice[layno - 1][resno][bandno]) { + value -= (imsb - matrice[layno - 1][resno][bandno]); + if (value < 0) { + value = 0; } + } } - success = OPJ_TRUE; - goodthresh = stable_thresh == 0? thresh : stable_thresh; + if (layno == 0) { + cblk->numpassesinlayers = 0; + } - opj_t2_destroy(t2); - } else { - success = OPJ_TRUE; - goodthresh = min; - } + n = cblk->numpassesinlayers; + if (cblk->numpassesinlayers == 0) { + if (value != 0) { + n = 3 * (OPJ_UINT32)value - 2 + cblk->numpassesinlayers; + } else { + n = cblk->numpassesinlayers; + } + } else { + n = 3 * (OPJ_UINT32)value + cblk->numpassesinlayers; + } - if (!success) { - return OPJ_FALSE; - } + layer->numpasses = n - cblk->numpassesinlayers; - if(cstr_info) { /* Threshold for Marcela Index */ - cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh; - } + if (!layer->numpasses) { + continue; + } - opj_tcd_makelayer(tcd, layno, goodthresh, 1); + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - + 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + } - /* fixed_quality */ - cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + if (final) { + cblk->numpassesinlayers = n; + } + } + } + } } - - return OPJ_TRUE; + } } -OPJ_BOOL opj_tcd_init( opj_tcd_t *p_tcd, - opj_image_t * p_image, - opj_cp_t * p_cp ) +OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + opj_event_mgr_t *p_manager) { - p_tcd->image = p_image; - p_tcd->cp = p_cp; + OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno; + OPJ_UINT32 passno; + OPJ_FLOAT64 min, max; + OPJ_FLOAT64 cumdisto[100]; /* fixed_quality */ + const OPJ_FLOAT64 K = 1; /* 1.1; fixed_quality */ + OPJ_FLOAT64 maxSE = 0; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + opj_tcp_t *tcd_tcp = tcd->tcp; - p_tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(1,sizeof(opj_tcd_tile_t)); - if (! p_tcd->tcd_image->tiles) { + min = DBL_MAX; + max = 0; + + tcd_tile->numpix = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + tilec->numpix = 0; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + OPJ_INT32 dr; + OPJ_FLOAT64 dd, rdslope; + + if (passno == 0) { + dr = (OPJ_INT32)pass->rate; + dd = pass->distortiondec; + } else { + dr = (OPJ_INT32)(pass->rate - cblk->passes[passno - 1].rate); + dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec; + } + + if (dr == 0) { + continue; + } + + rdslope = dd / dr; + if (rdslope < min) { + min = rdslope; + } + + if (rdslope > max) { + max = rdslope; + } + } /* passno */ + + /* fixed_quality */ + tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + } /* cbklno */ + } /* precno */ + } /* bandno */ + } /* resno */ + + maxSE += (((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0) + * ((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0)) + * ((OPJ_FLOAT64)(tilec->numpix)); + } /* compno */ + + /* index file */ + if (cstr_info) { + opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno]; + tile_info->numpix = tcd_tile->numpix; + tile_info->distotile = tcd_tile->distotile; + tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof( + OPJ_FLOAT64)); + if (!tile_info->thresh) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + + for (layno = 0; layno < tcd_tcp->numlayers; layno++) { + OPJ_FLOAT64 lo = min; + OPJ_FLOAT64 hi = max; + OPJ_UINT32 maxlen = tcd_tcp->rates[layno] > 0.0f ? opj_uint_min((( + OPJ_UINT32) ceil(tcd_tcp->rates[layno])), len) : len; + OPJ_FLOAT64 goodthresh = 0; + OPJ_FLOAT64 stable_thresh = 0; + OPJ_UINT32 i; + OPJ_FLOAT64 distotarget; /* fixed_quality */ + + /* fixed_quality */ + distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10, + tcd_tcp->distoratio[layno] / 10)); + + /* Don't try to find an optimal threshold but rather take everything not included yet, if + -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0) + -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0) + ==> possible to have some lossy layers and the last layer for sure lossless */ + if (((cp->m_specific_param.m_enc.m_disto_alloc == 1) && + (tcd_tcp->rates[layno] > 0.0f)) || + ((cp->m_specific_param.m_enc.m_fixed_quality == 1) && + (tcd_tcp->distoratio[layno] > 0.0))) { + opj_t2_t*t2 = opj_t2_create(tcd->image, cp); + OPJ_FLOAT64 thresh = 0; + + if (t2 == 00) { return OPJ_FALSE; + } + + for (i = 0; i < 128; ++i) { + OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */ + + thresh = (lo + hi) / 2; + + opj_tcd_makelayer(tcd, layno, thresh, 0); + + if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ + if (OPJ_IS_CINEMA(cp->rsiz)) { + if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, + p_data_written, maxlen, cstr_info, tcd->cur_tp_num, tcd->tp_pos, tcd->cur_pino, + THRESH_CALC, p_manager)) { + + lo = thresh; + continue; + } else { + distoachieved = layno == 0 ? + tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; + + if (distoachieved < distotarget) { + hi = thresh; + stable_thresh = thresh; + continue; + } else { + lo = thresh; + } + } + } else { + distoachieved = (layno == 0) ? + tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + + if (distoachieved < distotarget) { + hi = thresh; + stable_thresh = thresh; + continue; + } + lo = thresh; + } + } else { + if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, + p_data_written, maxlen, cstr_info, tcd->cur_tp_num, tcd->tp_pos, tcd->cur_pino, + THRESH_CALC, p_manager)) { + /* TODO: what to do with l ??? seek / tell ??? */ + /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ + lo = thresh; + continue; + } + + hi = thresh; + stable_thresh = thresh; + } + } + + goodthresh = stable_thresh == 0 ? thresh : stable_thresh; + + opj_t2_destroy(t2); + } else { + /* Special value to indicate to use all passes */ + goodthresh = -1; } - p_tcd->tcd_image->tiles->comps = (opj_tcd_tilecomp_t *) opj_calloc(p_image->numcomps,sizeof(opj_tcd_tilecomp_t)); - if (! p_tcd->tcd_image->tiles->comps ) { - return OPJ_FALSE; + if (cstr_info) { /* Threshold for Marcela Index */ + cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh; } - p_tcd->tcd_image->tiles->numcomps = p_image->numcomps; - p_tcd->tp_pos = p_cp->m_specific_param.m_enc.m_tp_pos; + opj_tcd_makelayer(tcd, layno, goodthresh, 1); - return OPJ_TRUE; + /* fixed_quality */ + cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : + (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_init(opj_tcd_t *p_tcd, + opj_image_t * p_image, + opj_cp_t * p_cp, + opj_thread_pool_t* p_tp) +{ + p_tcd->image = p_image; + p_tcd->cp = p_cp; + + p_tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(1, + sizeof(opj_tcd_tile_t)); + if (! p_tcd->tcd_image->tiles) { + return OPJ_FALSE; + } + + p_tcd->tcd_image->tiles->comps = (opj_tcd_tilecomp_t *) opj_calloc( + p_image->numcomps, sizeof(opj_tcd_tilecomp_t)); + if (! p_tcd->tcd_image->tiles->comps) { + return OPJ_FALSE; + } + + p_tcd->tcd_image->tiles->numcomps = p_image->numcomps; + p_tcd->tp_pos = p_cp->m_specific_param.m_enc.m_tp_pos; + p_tcd->thread_pool = p_tp; + + return OPJ_TRUE; } /** Destroy a previously created TCD handle */ -void opj_tcd_destroy(opj_tcd_t *tcd) { - if (tcd) { - opj_tcd_free_tile(tcd); +void opj_tcd_destroy(opj_tcd_t *tcd) +{ + if (tcd) { + opj_tcd_free_tile(tcd); - if (tcd->tcd_image) { - opj_free(tcd->tcd_image); - tcd->tcd_image = 00; - } - opj_free(tcd); + if (tcd->tcd_image) { + opj_free(tcd->tcd_image); + tcd->tcd_image = 00; } + + opj_free(tcd->used_component); + + opj_free(tcd); + } } OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec) { - if ((l_tilec->data == 00) || ((l_tilec->data_size_needed > l_tilec->data_size) && (l_tilec->ownsData == OPJ_FALSE))) { - l_tilec->data = (OPJ_INT32 *) opj_malloc(l_tilec->data_size_needed); - if (! l_tilec->data ) { - return OPJ_FALSE; - } - /*fprintf(stderr, "tAllocate data of tilec (int): %d x OPJ_UINT32n",l_data_size);*/ - l_tilec->data_size = l_tilec->data_size_needed; - l_tilec->ownsData = OPJ_TRUE; - } - else if (l_tilec->data_size_needed > l_tilec->data_size) { - OPJ_INT32 * new_data = (OPJ_INT32 *) opj_realloc(l_tilec->data, l_tilec->data_size_needed); - /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle tile datan"); */ - /* fprintf(stderr, "Not enough memory to handle tile data"); */ - if (! new_data) { - opj_free(l_tilec->data); - l_tilec->data = NULL; - l_tilec->data_size = 0; - l_tilec->data_size_needed = 0; - l_tilec->ownsData = OPJ_FALSE; - return OPJ_FALSE; - } - l_tilec->data = new_data; - /*fprintf(stderr, "tReallocate data of tilec (int): from %d to %d x OPJ_UINT32n", l_tilec->data_size, l_data_size);*/ - l_tilec->data_size = l_tilec->data_size_needed; - l_tilec->ownsData = OPJ_TRUE; - } - return OPJ_TRUE; + if ((l_tilec->data == 00) || + ((l_tilec->data_size_needed > l_tilec->data_size) && + (l_tilec->ownsData == OPJ_FALSE))) { + l_tilec->data = (OPJ_INT32 *) opj_image_data_alloc(l_tilec->data_size_needed); + if (!l_tilec->data && l_tilec->data_size_needed != 0) { + return OPJ_FALSE; + } + /*fprintf(stderr, "tAllocate data of tilec (int): %d x OPJ_UINT32n",l_data_size);*/ + l_tilec->data_size = l_tilec->data_size_needed; + l_tilec->ownsData = OPJ_TRUE; + } else if (l_tilec->data_size_needed > l_tilec->data_size) { + /* We don't need to keep old data */ + opj_image_data_free(l_tilec->data); + l_tilec->data = (OPJ_INT32 *) opj_image_data_alloc(l_tilec->data_size_needed); + if (! l_tilec->data) { + l_tilec->data_size = 0; + l_tilec->data_size_needed = 0; + l_tilec->ownsData = OPJ_FALSE; + return OPJ_FALSE; + } + /*fprintf(stderr, "tReallocate data of tilec (int): from %d to %d x OPJ_UINT32n", l_tilec->data_size, l_data_size);*/ + l_tilec->data_size = l_tilec->data_size_needed; + l_tilec->ownsData = OPJ_TRUE; + } + return OPJ_TRUE; } /* ----------------------------------------------------------------------- */ -static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager) +static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, + opj_event_mgr_t* manager) { - OPJ_UINT32 (*l_gain_ptr)(OPJ_UINT32) = 00; - OPJ_UINT32 compno, resno, bandno, precno, cblkno; - opj_tcp_t * l_tcp = 00; - opj_cp_t * l_cp = 00; - opj_tcd_tile_t * l_tile = 00; - opj_tccp_t *l_tccp = 00; - opj_tcd_tilecomp_t *l_tilec = 00; - opj_image_comp_t * l_image_comp = 00; - opj_tcd_resolution_t *l_res = 00; - opj_tcd_band_t *l_band = 00; - opj_stepsize_t * l_step_size = 00; - opj_tcd_precinct_t *l_current_precinct = 00; - opj_image_t *l_image = 00; - OPJ_UINT32 p,q; - OPJ_UINT32 l_level_no; - OPJ_UINT32 l_pdx, l_pdy; - OPJ_UINT32 l_gain; - OPJ_INT32 l_x0b, l_y0b; - OPJ_UINT32 l_tx0, l_ty0; - /* extent of precincts , top left, bottom right**/ - OPJ_INT32 l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end, l_br_prc_y_end; - /* number of precinct for a resolution */ - OPJ_UINT32 l_nb_precincts; - /* room needed to store l_nb_precinct precinct for a resolution */ - OPJ_UINT32 l_nb_precinct_size; - /* number of code blocks for a precinct*/ - OPJ_UINT32 l_nb_code_blocks; - /* room needed to store l_nb_code_blocks code blocks for a precinct*/ - OPJ_UINT32 l_nb_code_blocks_size; - /* size of data for a tile */ - OPJ_UINT32 l_data_size; - - l_cp = p_tcd->cp; - l_tcp = &(l_cp->tcps[p_tile_no]); - l_tile = p_tcd->tcd_image->tiles; - l_tccp = l_tcp->tccps; - l_tilec = l_tile->comps; - l_image = p_tcd->image; - l_image_comp = p_tcd->image->comps; - - p = p_tile_no % l_cp->tw; /* tile coordinates */ - q = p_tile_no / l_cp->tw; - /*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/ - - /* 4 borders of the tile rescale on the image if necessary */ - l_tx0 = l_cp->tx0 + p * l_cp->tdx; /* can't be greater than l_image->x1 so won't overflow */ - l_tile->x0 = (OPJ_INT32)opj_uint_max(l_tx0, l_image->x0); - l_tile->x1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, l_cp->tdx), l_image->x1); - if (l_tile->x0 < 0 || l_tile->x1 < 0) { - return OPJ_FALSE; - } - - l_ty0 = l_cp->ty0 + q * l_cp->tdy; /* can't be greater than l_image->y1 so won't overflow */ - l_tile->y0 = (OPJ_INT32)opj_uint_max(l_ty0, l_image->y0); - l_tile->y1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, l_cp->tdy), l_image->y1); - if (l_tile->y0 < 0 || l_tile->y1 < 0) { - return OPJ_FALSE; - } - - /* testcase 1888.pdf.asan.35.988 */ - if (l_tccp->numresolutions == 0) { - opj_event_msg(manager, EVT_ERROR, "tiles require at least one resolution\n"); - return OPJ_FALSE; - } - /*fprintf(stderr, "Tile border = %d,%d,%d,%d\n", l_tile->x0, l_tile->y0,l_tile->x1,l_tile->y1);*/ - - /*tile->numcomps = image->numcomps; */ - for (compno = 0; compno < l_tile->numcomps; ++compno) { - /*fprintf(stderr, "compno = %d/%d\n", compno, l_tile->numcomps);*/ - l_image_comp->resno_decoded = 0; - /* border of each l_tile component (global) */ - l_tilec->x0 = opj_int_ceildiv(l_tile->x0, (OPJ_INT32)l_image_comp->dx); - l_tilec->y0 = opj_int_ceildiv(l_tile->y0, (OPJ_INT32)l_image_comp->dy); - l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx); - l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy); - /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ - if (l_tilec->x0 >= l_tilec->x1 || l_tilec->y0 >= l_tilec->y1) { - opj_event_msg(manager, EVT_ERROR, "Invalid tile data\n"); - return OPJ_FALSE; - } - /* compute l_data_size with overflow check */ - l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); - if ((((OPJ_UINT32)-1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0)) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); - return OPJ_FALSE; - } - l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); - - if ((((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); - return OPJ_FALSE; - } - l_data_size = l_data_size * (OPJ_UINT32)sizeof(OPJ_UINT32); - l_tilec->numresolutions = l_tccp->numresolutions; - if (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce) { - l_tilec->minimum_num_resolutions = 1; - } - else { - l_tilec->minimum_num_resolutions = l_tccp->numresolutions - l_cp->m_specific_param.m_dec.m_reduce; - } - - l_tilec->data_size_needed = l_data_size; - if (p_tcd->m_is_decoder && !opj_alloc_tile_component_data(l_tilec)) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n"); - return OPJ_FALSE; - } - - l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof(opj_tcd_resolution_t); - - if (l_tilec->resolutions == 00) { - l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size); - if (! l_tilec->resolutions ) { - return OPJ_FALSE; - } - /*fprintf(stderr, "\tAllocate resolutions of tilec (opj_tcd_resolution_t): %d\n",l_data_size);*/ - l_tilec->resolutions_size = l_data_size; - memset(l_tilec->resolutions,0,l_data_size); - } - else if (l_data_size > l_tilec->resolutions_size) { - opj_tcd_resolution_t* new_resolutions = (opj_tcd_resolution_t *) opj_realloc(l_tilec->resolutions, l_data_size); - if (! new_resolutions) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile resolutions\n"); - opj_free(l_tilec->resolutions); - l_tilec->resolutions = NULL; - l_tilec->resolutions_size = 0; - return OPJ_FALSE; - } - l_tilec->resolutions = new_resolutions; - /*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %d x OPJ_UINT32\n", l_tilec->resolutions_size, l_data_size);*/ - memset(((OPJ_BYTE*) l_tilec->resolutions)+l_tilec->resolutions_size,0,l_data_size - l_tilec->resolutions_size); - l_tilec->resolutions_size = l_data_size; - } - - l_level_no = l_tilec->numresolutions - 1; - l_res = l_tilec->resolutions; - l_step_size = l_tccp->stepsizes; - if (l_tccp->qmfbid == 0) { - l_gain_ptr = &opj_dwt_getgain_real; - } - else { - l_gain_ptr = &opj_dwt_getgain; - } - /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/ - - for (resno = 0; resno < l_tilec->numresolutions; ++resno) { - /*fprintf(stderr, "\t\tresno = %d/%d\n", resno, l_tilec->numresolutions);*/ - OPJ_INT32 tlcbgxstart, tlcbgystart /*, brcbgxend, brcbgyend*/; - OPJ_UINT32 cbgwidthexpn, cbgheightexpn; - OPJ_UINT32 cblkwidthexpn, cblkheightexpn; - - /* border for each resolution level (global) */ - l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); - l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); - l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); - l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); - /*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/ - /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ - l_pdx = l_tccp->prcw[resno]; - l_pdy = l_tccp->prch[resno]; - /*fprintf(stderr, "\t\t\tpdx=%d, pdy=%d\n", l_pdx, l_pdy);*/ - /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ - l_tl_prc_x_start = opj_int_floordivpow2(l_res->x0, (OPJ_INT32)l_pdx) << l_pdx; - l_tl_prc_y_start = opj_int_floordivpow2(l_res->y0, (OPJ_INT32)l_pdy) << l_pdy; - l_br_prc_x_end = opj_int_ceildivpow2(l_res->x1, (OPJ_INT32)l_pdx) << l_pdx; - l_br_prc_y_end = opj_int_ceildivpow2(l_res->y1, (OPJ_INT32)l_pdy) << l_pdy; - /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/ - - l_res->pw = (l_res->x0 == l_res->x1) ? 0 : (OPJ_UINT32)((l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx); - l_res->ph = (l_res->y0 == l_res->y1) ? 0 : (OPJ_UINT32)((l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy); - /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ - - if (l_res->pw && ((OPJ_UINT32)-1) / l_res->pw < l_res->ph) { - return OPJ_FALSE; - } - l_nb_precincts = l_res->pw * l_res->ph; - - if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t) < l_nb_precincts) { - return OPJ_FALSE; - } - l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t); - if (resno == 0) { - tlcbgxstart = l_tl_prc_x_start; - tlcbgystart = l_tl_prc_y_start; - /*brcbgxend = l_br_prc_x_end;*/ - /* brcbgyend = l_br_prc_y_end;*/ - cbgwidthexpn = l_pdx; - cbgheightexpn = l_pdy; - l_res->numbands = 1; - } - else { - tlcbgxstart = opj_int_ceildivpow2(l_tl_prc_x_start, 1); - tlcbgystart = opj_int_ceildivpow2(l_tl_prc_y_start, 1); - /*brcbgxend = opj_int_ceildivpow2(l_br_prc_x_end, 1);*/ - /*brcbgyend = opj_int_ceildivpow2(l_br_prc_y_end, 1);*/ - cbgwidthexpn = l_pdx - 1; - cbgheightexpn = l_pdy - 1; - l_res->numbands = 3; - } - - cblkwidthexpn = opj_uint_min(l_tccp->cblkw, cbgwidthexpn); - cblkheightexpn = opj_uint_min(l_tccp->cblkh, cbgheightexpn); - l_band = l_res->bands; - - for (bandno = 0; bandno < l_res->numbands; ++bandno) { - OPJ_INT32 numbps; - /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/ - - if (resno == 0) { - l_band->bandno = 0 ; - l_band->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); - l_band->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); - l_band->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); - l_band->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); - } - else { - l_band->bandno = bandno + 1; - /* x0b = 1 if bandno = 1 or 3 */ - l_x0b = l_band->bandno&1; - /* y0b = 1 if bandno = 2 or 3 */ - l_y0b = (OPJ_INT32)((l_band->bandno)>>1); - /* l_band border (global) */ - l_band->x0 = opj_int64_ceildivpow2(l_tilec->x0 - ((OPJ_INT64)l_x0b << l_level_no), (OPJ_INT32)(l_level_no + 1)); - l_band->y0 = opj_int64_ceildivpow2(l_tilec->y0 - ((OPJ_INT64)l_y0b << l_level_no), (OPJ_INT32)(l_level_no + 1)); - l_band->x1 = opj_int64_ceildivpow2(l_tilec->x1 - ((OPJ_INT64)l_x0b << l_level_no), (OPJ_INT32)(l_level_no + 1)); - l_band->y1 = opj_int64_ceildivpow2(l_tilec->y1 - ((OPJ_INT64)l_y0b << l_level_no), (OPJ_INT32)(l_level_no + 1)); - } - - /** avoid an if with storing function pointer */ - l_gain = (*l_gain_ptr) (l_band->bandno); - numbps = (OPJ_INT32)(l_image_comp->prec + l_gain); - l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, (OPJ_INT32) (numbps - l_step_size->expn)))) * fraction; - l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits - 1; /* WHY -1 ? */ - - if (! l_band->precincts) { - l_band->precincts = (opj_tcd_precinct_t *) opj_malloc( /*3 * */ l_nb_precinct_size); - if (! l_band->precincts) { - return OPJ_FALSE; - } - /*fprintf(stderr, "\t\t\t\tAllocate precincts of a band (opj_tcd_precinct_t): %d\n",l_nb_precinct_size); */ - memset(l_band->precincts,0,l_nb_precinct_size); - l_band->precincts_data_size = l_nb_precinct_size; - } - else if (l_band->precincts_data_size < l_nb_precinct_size) { - - opj_tcd_precinct_t * new_precincts = (opj_tcd_precinct_t *) opj_realloc(l_band->precincts,/*3 * */ l_nb_precinct_size); - if (! new_precincts) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory to handle band precints\n"); - opj_free(l_band->precincts); - l_band->precincts = NULL; - l_band->precincts_data_size = 0; - return OPJ_FALSE; - } - l_band->precincts = new_precincts; - /*fprintf(stderr, "\t\t\t\tReallocate precincts of a band (opj_tcd_precinct_t): from %d to %d\n",l_band->precincts_data_size, l_nb_precinct_size);*/ - memset(((OPJ_BYTE *) l_band->precincts) + l_band->precincts_data_size,0,l_nb_precinct_size - l_band->precincts_data_size); - l_band->precincts_data_size = l_nb_precinct_size; - } - - l_current_precinct = l_band->precincts; - for (precno = 0; precno < l_nb_precincts; ++precno) { - OPJ_INT32 tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; - OPJ_INT32 cbgxstart = tlcbgxstart + (OPJ_INT32)(precno % l_res->pw) * (1 << cbgwidthexpn); - OPJ_INT32 cbgystart = tlcbgystart + (OPJ_INT32)(precno / l_res->pw) * (1 << cbgheightexpn); - OPJ_INT32 cbgxend = cbgxstart + (1 << cbgwidthexpn); - OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn); - /*fprintf(stderr, "\t precno=%d; bandno=%d, resno=%d; compno=%d\n", precno, bandno , resno, compno);*/ - /*fprintf(stderr, "\t tlcbgxstart(=%d) + (precno(=%d) percent res->pw(=%d)) * (1 << cbgwidthexpn(=%d)) \n",tlcbgxstart,precno,l_res->pw,cbgwidthexpn);*/ - - /* precinct size (global) */ - /*fprintf(stderr, "\t cbgxstart=%d, l_band->x0 = %d \n",cbgxstart, l_band->x0);*/ - - l_current_precinct->x0 = opj_int_max(cbgxstart, l_band->x0); - l_current_precinct->y0 = opj_int_max(cbgystart, l_band->y0); - l_current_precinct->x1 = opj_int_min(cbgxend, l_band->x1); - l_current_precinct->y1 = opj_int_min(cbgyend, l_band->y1); - /*fprintf(stderr, "\t prc_x0=%d; prc_y0=%d, prc_x1=%d; prc_y1=%d\n",l_current_precinct->x0, l_current_precinct->y0 ,l_current_precinct->x1, l_current_precinct->y1);*/ - - tlcblkxstart = opj_int_floordivpow2(l_current_precinct->x0, (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; - /*fprintf(stderr, "\t tlcblkxstart =%d\n",tlcblkxstart );*/ - tlcblkystart = opj_int_floordivpow2(l_current_precinct->y0, (OPJ_INT32)cblkheightexpn) << cblkheightexpn; - /*fprintf(stderr, "\t tlcblkystart =%d\n",tlcblkystart );*/ - brcblkxend = opj_int_ceildivpow2(l_current_precinct->x1, (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; - /*fprintf(stderr, "\t brcblkxend =%d\n",brcblkxend );*/ - brcblkyend = opj_int_ceildivpow2(l_current_precinct->y1, (OPJ_INT32)cblkheightexpn) << cblkheightexpn; - /*fprintf(stderr, "\t brcblkyend =%d\n",brcblkyend );*/ - l_current_precinct->cw = (OPJ_UINT32)((brcblkxend - tlcblkxstart) >> cblkwidthexpn); - l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> cblkheightexpn); - - if (l_current_precinct->cw && ((OPJ_UINT32)-1) / l_current_precinct->cw < l_current_precinct->ch) { - return OPJ_FALSE; - } - l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; - /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ - - if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof_block < l_nb_code_blocks) { - return OPJ_FALSE; - } - l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; - - if (! l_current_precinct->cblks.blocks) { - l_current_precinct->cblks.blocks = opj_malloc(l_nb_code_blocks_size); - if (! l_current_precinct->cblks.blocks ) { - return OPJ_FALSE; - } - /*fprintf(stderr, "\t\t\t\tAllocate cblks of a precinct (opj_tcd_cblk_dec_t): %d\n",l_nb_code_blocks_size);*/ - - memset(l_current_precinct->cblks.blocks,0,l_nb_code_blocks_size); - - l_current_precinct->block_size = l_nb_code_blocks_size; - } - else if (l_nb_code_blocks_size > l_current_precinct->block_size) { - void *new_blocks = opj_realloc(l_current_precinct->cblks.blocks, l_nb_code_blocks_size); - if (! new_blocks) { - opj_free(l_current_precinct->cblks.blocks); - l_current_precinct->cblks.blocks = NULL; - l_current_precinct->block_size = 0; - opj_event_msg(manager, EVT_ERROR, "Not enough memory for current precinct codeblock element\n"); - return OPJ_FALSE; - } - l_current_precinct->cblks.blocks = new_blocks; - /*fprintf(stderr, "\t\t\t\tReallocate cblks of a precinct (opj_tcd_cblk_dec_t): from %d to %d\n",l_current_precinct->block_size, l_nb_code_blocks_size); */ - - memset(((OPJ_BYTE *) l_current_precinct->cblks.blocks) + l_current_precinct->block_size - ,0 - ,l_nb_code_blocks_size - l_current_precinct->block_size); - - l_current_precinct->block_size = l_nb_code_blocks_size; - } - - if (! l_current_precinct->incltree) { - l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw, l_current_precinct->ch, manager); - } - else{ - l_current_precinct->incltree = opj_tgt_init(l_current_precinct->incltree, l_current_precinct->cw, l_current_precinct->ch, manager); - } - - if (! l_current_precinct->incltree) { - opj_event_msg(manager, EVT_WARNING, "No incltree created.\n"); - /*return OPJ_FALSE;*/ - } - - if (! l_current_precinct->imsbtree) { - l_current_precinct->imsbtree = opj_tgt_create(l_current_precinct->cw, l_current_precinct->ch, manager); - } - else { - l_current_precinct->imsbtree = opj_tgt_init(l_current_precinct->imsbtree, l_current_precinct->cw, l_current_precinct->ch, manager); - } - - if (! l_current_precinct->imsbtree) { - opj_event_msg(manager, EVT_WARNING, "No imsbtree created.\n"); - /*return OPJ_FALSE;*/ - } - - for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { - OPJ_INT32 cblkxstart = tlcblkxstart + (OPJ_INT32)(cblkno % l_current_precinct->cw) * (1 << cblkwidthexpn); - OPJ_INT32 cblkystart = tlcblkystart + (OPJ_INT32)(cblkno / l_current_precinct->cw) * (1 << cblkheightexpn); - OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn); - OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn); - - if (isEncoder) { - opj_tcd_cblk_enc_t* l_code_block = l_current_precinct->cblks.enc + cblkno; - - if (! opj_tcd_code_block_enc_allocate(l_code_block)) { - return OPJ_FALSE; - } - /* code-block size (global) */ - l_code_block->x0 = opj_int_max(cblkxstart, l_current_precinct->x0); - l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); - l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); - l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); - - if (! opj_tcd_code_block_enc_allocate_data(l_code_block)) { - return OPJ_FALSE; - } - } else { - opj_tcd_cblk_dec_t* l_code_block = l_current_precinct->cblks.dec + cblkno; - - if (! opj_tcd_code_block_dec_allocate(l_code_block)) { - return OPJ_FALSE; - } - /* code-block size (global) */ - l_code_block->x0 = opj_int_max(cblkxstart, l_current_precinct->x0); - l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); - l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); - l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); - } - } - ++l_current_precinct; - } /* precno */ - ++l_band; - ++l_step_size; - } /* bandno */ - ++l_res; - --l_level_no; - } /* resno */ - ++l_tccp; - ++l_tilec; - ++l_image_comp; - } /* compno */ - return OPJ_TRUE; + OPJ_UINT32(*l_gain_ptr)(OPJ_UINT32) = 00; + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + opj_tcp_t * l_tcp = 00; + opj_cp_t * l_cp = 00; + opj_tcd_tile_t * l_tile = 00; + opj_tccp_t *l_tccp = 00; + opj_tcd_tilecomp_t *l_tilec = 00; + opj_image_comp_t * l_image_comp = 00; + opj_tcd_resolution_t *l_res = 00; + opj_tcd_band_t *l_band = 00; + opj_stepsize_t * l_step_size = 00; + opj_tcd_precinct_t *l_current_precinct = 00; + opj_image_t *l_image = 00; + OPJ_UINT32 p, q; + OPJ_UINT32 l_level_no; + OPJ_UINT32 l_pdx, l_pdy; + OPJ_UINT32 l_gain; + OPJ_INT32 l_x0b, l_y0b; + OPJ_UINT32 l_tx0, l_ty0; + /* extent of precincts , top left, bottom right**/ + OPJ_INT32 l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end, l_br_prc_y_end; + /* number of precinct for a resolution */ + OPJ_UINT32 l_nb_precincts; + /* room needed to store l_nb_precinct precinct for a resolution */ + OPJ_UINT32 l_nb_precinct_size; + /* number of code blocks for a precinct*/ + OPJ_UINT32 l_nb_code_blocks; + /* room needed to store l_nb_code_blocks code blocks for a precinct*/ + OPJ_UINT32 l_nb_code_blocks_size; + /* size of data for a tile */ + OPJ_UINT32 l_data_size; + + l_cp = p_tcd->cp; + l_tcp = &(l_cp->tcps[p_tile_no]); + l_tile = p_tcd->tcd_image->tiles; + l_tccp = l_tcp->tccps; + l_tilec = l_tile->comps; + l_image = p_tcd->image; + l_image_comp = p_tcd->image->comps; + + p = p_tile_no % l_cp->tw; /* tile coordinates */ + q = p_tile_no / l_cp->tw; + /*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/ + + /* 4 borders of the tile rescale on the image if necessary */ + l_tx0 = l_cp->tx0 + p * + l_cp->tdx; /* can't be greater than l_image->x1 so won't overflow */ + l_tile->x0 = (OPJ_INT32)opj_uint_max(l_tx0, l_image->x0); + l_tile->x1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, l_cp->tdx), + l_image->x1); + /* all those OPJ_UINT32 are casted to OPJ_INT32, let's do some sanity check */ + if ((l_tile->x0 < 0) || (l_tile->x1 <= l_tile->x0)) { + opj_event_msg(manager, EVT_ERROR, "Tile X coordinates are not supported\n"); + return OPJ_FALSE; + } + l_ty0 = l_cp->ty0 + q * + l_cp->tdy; /* can't be greater than l_image->y1 so won't overflow */ + l_tile->y0 = (OPJ_INT32)opj_uint_max(l_ty0, l_image->y0); + l_tile->y1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, l_cp->tdy), + l_image->y1); + /* all those OPJ_UINT32 are casted to OPJ_INT32, let's do some sanity check */ + if ((l_tile->y0 < 0) || (l_tile->y1 <= l_tile->y0)) { + opj_event_msg(manager, EVT_ERROR, "Tile Y coordinates are not supported\n"); + return OPJ_FALSE; + } + + + /* testcase 1888.pdf.asan.35.988 */ + if (l_tccp->numresolutions == 0) { + opj_event_msg(manager, EVT_ERROR, "tiles require at least one resolution\n"); + return OPJ_FALSE; + } + /*fprintf(stderr, "Tile border = %d,%d,%d,%d\n", l_tile->x0, l_tile->y0,l_tile->x1,l_tile->y1);*/ + + /*tile->numcomps = image->numcomps; */ + for (compno = 0; compno < l_tile->numcomps; ++compno) { + /*fprintf(stderr, "compno = %d/%d\n", compno, l_tile->numcomps);*/ + l_image_comp->resno_decoded = 0; + /* border of each l_tile component (global) */ + l_tilec->x0 = opj_int_ceildiv(l_tile->x0, (OPJ_INT32)l_image_comp->dx); + l_tilec->y0 = opj_int_ceildiv(l_tile->y0, (OPJ_INT32)l_image_comp->dy); + l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx); + l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy); + l_tilec->compno = compno; + /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ + + l_tilec->numresolutions = l_tccp->numresolutions; + if (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce) { + l_tilec->minimum_num_resolutions = 1; + } else { + l_tilec->minimum_num_resolutions = l_tccp->numresolutions - + l_cp->m_specific_param.m_dec.m_reduce; + } + + if (isEncoder) { + OPJ_SIZE_T l_tile_data_size; + + if (l_tilec->x0 >= l_tilec->x1 || l_tilec->y0 >= l_tilec->y1) { + opj_event_msg(manager, EVT_ERROR, "Invalid tile data\n"); + return OPJ_FALSE; + } + + /* compute l_data_size with overflow check */ + OPJ_SIZE_T w = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0); + OPJ_SIZE_T h = (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); + + /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ + if (h > 0 && w > SIZE_MAX / h) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_tile_data_size = w * h; + + if (SIZE_MAX / sizeof(OPJ_UINT32) < l_tile_data_size) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_tile_data_size = l_tile_data_size * sizeof(OPJ_UINT32); + + l_tilec->data_size_needed = l_tile_data_size; + } + + l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof( + opj_tcd_resolution_t); + + opj_image_data_free(l_tilec->data_win); + l_tilec->data_win = NULL; + l_tilec->win_x0 = 0; + l_tilec->win_y0 = 0; + l_tilec->win_x1 = 0; + l_tilec->win_y1 = 0; + + if (l_tilec->resolutions == 00) { + l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size); + if (! l_tilec->resolutions) { + return OPJ_FALSE; + } + /*fprintf(stderr, "\tAllocate resolutions of tilec (opj_tcd_resolution_t): %d\n",l_data_size);*/ + l_tilec->resolutions_size = l_data_size; + memset(l_tilec->resolutions, 0, l_data_size); + } else if (l_data_size > l_tilec->resolutions_size) { + opj_tcd_resolution_t* new_resolutions = (opj_tcd_resolution_t *) opj_realloc( + l_tilec->resolutions, l_data_size); + if (! new_resolutions) { + opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile resolutions\n"); + opj_free(l_tilec->resolutions); + l_tilec->resolutions = NULL; + l_tilec->resolutions_size = 0; + return OPJ_FALSE; + } + l_tilec->resolutions = new_resolutions; + /*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %d x OPJ_UINT32\n", l_tilec->resolutions_size, l_data_size);*/ + memset(((OPJ_BYTE*) l_tilec->resolutions) + l_tilec->resolutions_size, 0, + l_data_size - l_tilec->resolutions_size); + l_tilec->resolutions_size = l_data_size; + } + + l_level_no = l_tilec->numresolutions; + l_res = l_tilec->resolutions; + l_step_size = l_tccp->stepsizes; + if (l_tccp->qmfbid == 0) { + l_gain_ptr = &opj_dwt_getgain_real; + } else { + l_gain_ptr = &opj_dwt_getgain; + } + /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/ + + for (resno = 0; resno < l_tilec->numresolutions; ++resno) { + /*fprintf(stderr, "\t\tresno = %d/%d\n", resno, l_tilec->numresolutions);*/ + OPJ_INT32 tlcbgxstart, tlcbgystart /*, brcbgxend, brcbgyend*/; + OPJ_UINT32 cbgwidthexpn, cbgheightexpn; + OPJ_UINT32 cblkwidthexpn, cblkheightexpn; + + --l_level_no; + + /* border for each resolution level (global) */ + l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); + l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); + l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); + l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); + + /*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/ + /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + /*fprintf(stderr, "\t\t\tpdx=%d, pdy=%d\n", l_pdx, l_pdy);*/ + /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + l_tl_prc_x_start = opj_int_floordivpow2(l_res->x0, (OPJ_INT32)l_pdx) << l_pdx; + l_tl_prc_y_start = opj_int_floordivpow2(l_res->y0, (OPJ_INT32)l_pdy) << l_pdy; + l_br_prc_x_end = opj_int_ceildivpow2(l_res->x1, (OPJ_INT32)l_pdx) << l_pdx; + l_br_prc_y_end = opj_int_ceildivpow2(l_res->y1, (OPJ_INT32)l_pdy) << l_pdy; + /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/ + + l_res->pw = (l_res->x0 == l_res->x1) ? 0U : (OPJ_UINT32)(( + l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx); + l_res->ph = (l_res->y0 == l_res->y1) ? 0U : (OPJ_UINT32)(( + l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy); + /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ + + if ((l_res->pw != 0U) && ((((OPJ_UINT32) - 1) / l_res->pw) < l_res->ph)) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_nb_precincts = l_res->pw * l_res->ph; + + if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t)) < + l_nb_precincts) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t); + + if (resno == 0) { + tlcbgxstart = l_tl_prc_x_start; + tlcbgystart = l_tl_prc_y_start; + /*brcbgxend = l_br_prc_x_end;*/ + /* brcbgyend = l_br_prc_y_end;*/ + cbgwidthexpn = l_pdx; + cbgheightexpn = l_pdy; + l_res->numbands = 1; + } else { + tlcbgxstart = opj_int_ceildivpow2(l_tl_prc_x_start, 1); + tlcbgystart = opj_int_ceildivpow2(l_tl_prc_y_start, 1); + /*brcbgxend = opj_int_ceildivpow2(l_br_prc_x_end, 1);*/ + /*brcbgyend = opj_int_ceildivpow2(l_br_prc_y_end, 1);*/ + cbgwidthexpn = l_pdx - 1; + cbgheightexpn = l_pdy - 1; + l_res->numbands = 3; + } + + cblkwidthexpn = opj_uint_min(l_tccp->cblkw, cbgwidthexpn); + cblkheightexpn = opj_uint_min(l_tccp->cblkh, cbgheightexpn); + l_band = l_res->bands; + + for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band, ++l_step_size) { + OPJ_INT32 numbps; + /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/ + + if (resno == 0) { + l_band->bandno = 0 ; + l_band->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); + l_band->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); + l_band->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); + l_band->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); + } else { + l_band->bandno = bandno + 1; + /* x0b = 1 if bandno = 1 or 3 */ + l_x0b = l_band->bandno & 1; + /* y0b = 1 if bandno = 2 or 3 */ + l_y0b = (OPJ_INT32)((l_band->bandno) >> 1); + /* l_band border (global) */ + l_band->x0 = opj_int64_ceildivpow2(l_tilec->x0 - ((OPJ_INT64)l_x0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + l_band->y0 = opj_int64_ceildivpow2(l_tilec->y0 - ((OPJ_INT64)l_y0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + l_band->x1 = opj_int64_ceildivpow2(l_tilec->x1 - ((OPJ_INT64)l_x0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + l_band->y1 = opj_int64_ceildivpow2(l_tilec->y1 - ((OPJ_INT64)l_y0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + } + + if (isEncoder) { + /* Skip empty bands */ + if (opj_tcd_is_band_empty(l_band)) { + /* Do not zero l_band->precints to avoid leaks */ + /* but make sure we don't use it later, since */ + /* it will point to precincts of previous bands... */ + continue; + } + } + + /** avoid an if with storing function pointer */ + l_gain = (*l_gain_ptr)(l_band->bandno); + numbps = (OPJ_INT32)(l_image_comp->prec + l_gain); + l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, + (OPJ_INT32)(numbps - l_step_size->expn)))) * fraction; + /* Mb value of Equation E-2 in "E.1 Inverse quantization + * procedure" of the standard */ + l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits - + 1; + + if (!l_band->precincts && (l_nb_precincts > 0U)) { + l_band->precincts = (opj_tcd_precinct_t *) opj_malloc(/*3 * */ + l_nb_precinct_size); + if (! l_band->precincts) { + opj_event_msg(manager, EVT_ERROR, + "Not enough memory to handle band precints\n"); + return OPJ_FALSE; + } + /*fprintf(stderr, "\t\t\t\tAllocate precincts of a band (opj_tcd_precinct_t): %d\n",l_nb_precinct_size); */ + memset(l_band->precincts, 0, l_nb_precinct_size); + l_band->precincts_data_size = l_nb_precinct_size; + } else if (l_band->precincts_data_size < l_nb_precinct_size) { + + opj_tcd_precinct_t * new_precincts = (opj_tcd_precinct_t *) opj_realloc( + l_band->precincts,/*3 * */ l_nb_precinct_size); + if (! new_precincts) { + opj_event_msg(manager, EVT_ERROR, + "Not enough memory to handle band precints\n"); + opj_free(l_band->precincts); + l_band->precincts = NULL; + l_band->precincts_data_size = 0; + return OPJ_FALSE; + } + l_band->precincts = new_precincts; + /*fprintf(stderr, "\t\t\t\tReallocate precincts of a band (opj_tcd_precinct_t): from %d to %d\n",l_band->precincts_data_size, l_nb_precinct_size);*/ + memset(((OPJ_BYTE *) l_band->precincts) + l_band->precincts_data_size, 0, + l_nb_precinct_size - l_band->precincts_data_size); + l_band->precincts_data_size = l_nb_precinct_size; + } + + l_current_precinct = l_band->precincts; + for (precno = 0; precno < l_nb_precincts; ++precno) { + OPJ_INT32 tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; + OPJ_INT32 cbgxstart = tlcbgxstart + (OPJ_INT32)(precno % l_res->pw) * + (1 << cbgwidthexpn); + OPJ_INT32 cbgystart = tlcbgystart + (OPJ_INT32)(precno / l_res->pw) * + (1 << cbgheightexpn); + OPJ_INT32 cbgxend = cbgxstart + (1 << cbgwidthexpn); + OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn); + /*fprintf(stderr, "\t precno=%d; bandno=%d, resno=%d; compno=%d\n", precno, bandno , resno, compno);*/ + /*fprintf(stderr, "\t tlcbgxstart(=%d) + (precno(=%d) percent res->pw(=%d)) * (1 << cbgwidthexpn(=%d)) \n",tlcbgxstart,precno,l_res->pw,cbgwidthexpn);*/ + + /* precinct size (global) */ + /*fprintf(stderr, "\t cbgxstart=%d, l_band->x0 = %d \n",cbgxstart, l_band->x0);*/ + + l_current_precinct->x0 = opj_int_max(cbgxstart, l_band->x0); + l_current_precinct->y0 = opj_int_max(cbgystart, l_band->y0); + l_current_precinct->x1 = opj_int_min(cbgxend, l_band->x1); + l_current_precinct->y1 = opj_int_min(cbgyend, l_band->y1); + /*fprintf(stderr, "\t prc_x0=%d; prc_y0=%d, prc_x1=%d; prc_y1=%d\n",l_current_precinct->x0, l_current_precinct->y0 ,l_current_precinct->x1, l_current_precinct->y1);*/ + + tlcblkxstart = opj_int_floordivpow2(l_current_precinct->x0, + (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; + /*fprintf(stderr, "\t tlcblkxstart =%d\n",tlcblkxstart );*/ + tlcblkystart = opj_int_floordivpow2(l_current_precinct->y0, + (OPJ_INT32)cblkheightexpn) << cblkheightexpn; + /*fprintf(stderr, "\t tlcblkystart =%d\n",tlcblkystart );*/ + brcblkxend = opj_int_ceildivpow2(l_current_precinct->x1, + (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; + /*fprintf(stderr, "\t brcblkxend =%d\n",brcblkxend );*/ + brcblkyend = opj_int_ceildivpow2(l_current_precinct->y1, + (OPJ_INT32)cblkheightexpn) << cblkheightexpn; + /*fprintf(stderr, "\t brcblkyend =%d\n",brcblkyend );*/ + l_current_precinct->cw = (OPJ_UINT32)((brcblkxend - tlcblkxstart) >> + cblkwidthexpn); + l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> + cblkheightexpn); + if (l_current_precinct->cw && ((OPJ_UINT32)-1) / l_current_precinct->cw < l_current_precinct->ch) { + return OPJ_FALSE; + } + l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; + /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ + + if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof_block < l_nb_code_blocks) { + return OPJ_FALSE; + } + l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; + + if (!l_current_precinct->cblks.blocks && (l_nb_code_blocks > 0U)) { + l_current_precinct->cblks.blocks = opj_malloc(l_nb_code_blocks_size); + if (! l_current_precinct->cblks.blocks) { + return OPJ_FALSE; + } + /*fprintf(stderr, "\t\t\t\tAllocate cblks of a precinct (opj_tcd_cblk_dec_t): %d\n",l_nb_code_blocks_size);*/ + + memset(l_current_precinct->cblks.blocks, 0, l_nb_code_blocks_size); + + l_current_precinct->block_size = l_nb_code_blocks_size; + } else if (l_nb_code_blocks_size > l_current_precinct->block_size) { + void *new_blocks = opj_realloc(l_current_precinct->cblks.blocks, + l_nb_code_blocks_size); + if (! new_blocks) { + opj_free(l_current_precinct->cblks.blocks); + l_current_precinct->cblks.blocks = NULL; + l_current_precinct->block_size = 0; + opj_event_msg(manager, EVT_ERROR, + "Not enough memory for current precinct codeblock element\n"); + return OPJ_FALSE; + } + l_current_precinct->cblks.blocks = new_blocks; + /*fprintf(stderr, "\t\t\t\tReallocate cblks of a precinct (opj_tcd_cblk_dec_t): from %d to %d\n",l_current_precinct->block_size, l_nb_code_blocks_size); */ + + memset(((OPJ_BYTE *) l_current_precinct->cblks.blocks) + + l_current_precinct->block_size + , 0 + , l_nb_code_blocks_size - l_current_precinct->block_size); + + l_current_precinct->block_size = l_nb_code_blocks_size; + } + + if (! l_current_precinct->incltree) { + l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw, + l_current_precinct->ch, manager); + } else { + l_current_precinct->incltree = opj_tgt_init(l_current_precinct->incltree, + l_current_precinct->cw, l_current_precinct->ch, manager); + } + + if (! l_current_precinct->imsbtree) { + l_current_precinct->imsbtree = opj_tgt_create(l_current_precinct->cw, + l_current_precinct->ch, manager); + } else { + l_current_precinct->imsbtree = opj_tgt_init(l_current_precinct->imsbtree, + l_current_precinct->cw, l_current_precinct->ch, manager); + } + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + OPJ_INT32 cblkxstart = tlcblkxstart + (OPJ_INT32)(cblkno % + l_current_precinct->cw) * (1 << cblkwidthexpn); + OPJ_INT32 cblkystart = tlcblkystart + (OPJ_INT32)(cblkno / + l_current_precinct->cw) * (1 << cblkheightexpn); + OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn); + OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn); + + if (isEncoder) { + opj_tcd_cblk_enc_t* l_code_block = l_current_precinct->cblks.enc + cblkno; + + if (! opj_tcd_code_block_enc_allocate(l_code_block)) { + return OPJ_FALSE; + } + /* code-block size (global) */ + l_code_block->x0 = opj_int_max(cblkxstart, l_current_precinct->x0); + l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); + l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); + l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); + + if (! opj_tcd_code_block_enc_allocate_data(l_code_block)) { + return OPJ_FALSE; + } + } else { + opj_tcd_cblk_dec_t* l_code_block = l_current_precinct->cblks.dec + cblkno; + + if (! opj_tcd_code_block_dec_allocate(l_code_block)) { + return OPJ_FALSE; + } + /* code-block size (global) */ + l_code_block->x0 = opj_int_max(cblkxstart, l_current_precinct->x0); + l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); + l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); + l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); + } + } + ++l_current_precinct; + } /* precno */ + } /* bandno */ + ++l_res; + } /* resno */ + ++l_tccp; + ++l_tilec; + ++l_image_comp; + } /* compno */ + return OPJ_TRUE; } -OPJ_BOOL opj_tcd_init_encode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager) +OPJ_BOOL opj_tcd_init_encode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + opj_event_mgr_t* p_manager) { - return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, 1.0F, sizeof(opj_tcd_cblk_enc_t), p_manager); + return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, 1.0F, + sizeof(opj_tcd_cblk_enc_t), p_manager); } -OPJ_BOOL opj_tcd_init_decode_tile (opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager) +OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + opj_event_mgr_t* p_manager) { - return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, 0.5F, sizeof(opj_tcd_cblk_dec_t), p_manager); + return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, 0.5F, + sizeof(opj_tcd_cblk_dec_t), p_manager); } /** * Allocates memory for an encoding code block (but not data memory). */ -static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block) +static OPJ_BOOL opj_tcd_code_block_enc_allocate(opj_tcd_cblk_enc_t * + p_code_block) { - if (! p_code_block->layers) { - /* no memset since data */ - p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); - if (! p_code_block->layers) { - return OPJ_FALSE; - } - } - if (! p_code_block->passes) { - p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); - if (! p_code_block->passes) { - return OPJ_FALSE; - } - } - return OPJ_TRUE; + if (! p_code_block->layers) { + /* no memset since data */ + p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, + sizeof(opj_tcd_layer_t)); + if (! p_code_block->layers) { + return OPJ_FALSE; + } + } + if (! p_code_block->passes) { + p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, + sizeof(opj_tcd_pass_t)); + if (! p_code_block->passes) { + return OPJ_FALSE; + } + } + return OPJ_TRUE; } /** * Allocates data memory for an encoding code block. */ -static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block) +static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * + p_code_block) +{ + OPJ_UINT32 l_data_size; + + /* +1 is needed for https://github.com/uclouvain/openjpeg/issues/835 */ + /* and actually +2 required for https://github.com/uclouvain/openjpeg/issues/982 */ + /* TODO: is there a theoretical upper-bound for the compressed code */ + /* block size ? */ + l_data_size = 2 + (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * + (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32)); + + if (l_data_size > p_code_block->data_size) { + if (p_code_block->data) { + /* We refer to data - 1 since below we incremented it */ + opj_free(p_code_block->data - 1); + } + p_code_block->data = (OPJ_BYTE*) opj_malloc(l_data_size + 1); + if (! p_code_block->data) { + p_code_block->data_size = 0U; + return OPJ_FALSE; + } + p_code_block->data_size = l_data_size; + + /* We reserve the initial byte as a fake byte to a non-FF value */ + /* and increment the data pointer, so that opj_mqc_init_enc() */ + /* can do bp = data - 1, and opj_mqc_byteout() can safely dereference */ + /* it. */ + p_code_block->data[0] = 0; + p_code_block->data += 1; /*why +1 ?*/ + } + return OPJ_TRUE; +} + + +void opj_tcd_reinit_segment(opj_tcd_seg_t* seg) { - OPJ_UINT32 l_data_size; - - l_data_size = (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32)); - - if (l_data_size > p_code_block->data_size) { - if (p_code_block->data) { - opj_free(p_code_block->data - 1); /* again, why -1 */ - } - p_code_block->data = (OPJ_BYTE*) opj_malloc(l_data_size+1); - if(! p_code_block->data) { - p_code_block->data_size = 0U; - return OPJ_FALSE; - } - p_code_block->data_size = l_data_size; - - p_code_block->data[0] = 0; - p_code_block->data+=1; /*why +1 ?*/ - } - return OPJ_TRUE; + memset(seg, 0, sizeof(opj_tcd_seg_t)); } /** * Allocates memory for a decoding code block. */ -static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block) +static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t * + p_code_block) { - if (! p_code_block->data) { + if (! p_code_block->segs) { - p_code_block->data = (OPJ_BYTE*) opj_malloc(OPJ_J2K_DEFAULT_CBLK_DATA_SIZE); - if (! p_code_block->data) { - return OPJ_FALSE; - } - p_code_block->data_max_size = OPJ_J2K_DEFAULT_CBLK_DATA_SIZE; - /*fprintf(stderr, "Allocate 8192 elements of code_block->data\n");*/ + p_code_block->segs = (opj_tcd_seg_t *) opj_calloc(OPJ_J2K_DEFAULT_NB_SEGS, + sizeof(opj_tcd_seg_t)); + if (! p_code_block->segs) { + return OPJ_FALSE; + } + /*fprintf(stderr, "Allocate %d elements of code_block->data\n", OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/ + + p_code_block->m_current_max_segs = OPJ_J2K_DEFAULT_NB_SEGS; + /*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/ + } else { + /* sanitize */ + opj_tcd_seg_t * l_segs = p_code_block->segs; + OPJ_UINT32 l_current_max_segs = p_code_block->m_current_max_segs; + opj_tcd_seg_data_chunk_t* l_chunks = p_code_block->chunks; + OPJ_UINT32 l_numchunksalloc = p_code_block->numchunksalloc; + OPJ_UINT32 i; - p_code_block->segs = (opj_tcd_seg_t *) opj_calloc(OPJ_J2K_DEFAULT_NB_SEGS,sizeof(opj_tcd_seg_t)); - if (! p_code_block->segs) { - return OPJ_FALSE; - } - /*fprintf(stderr, "Allocate %d elements of code_block->data\n", OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/ + opj_aligned_free(p_code_block->decoded_data); + p_code_block->decoded_data = 00; - p_code_block->m_current_max_segs = OPJ_J2K_DEFAULT_NB_SEGS; - /*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/ - } else { - /* sanitize */ - OPJ_BYTE* l_data = p_code_block->data; - OPJ_UINT32 l_data_max_size = p_code_block->data_max_size; - opj_tcd_seg_t * l_segs = p_code_block->segs; - OPJ_UINT32 l_current_max_segs = p_code_block->m_current_max_segs; - - memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t)); - p_code_block->data = l_data; - p_code_block->data_max_size = l_data_max_size; - p_code_block->segs = l_segs; - p_code_block->m_current_max_segs = l_current_max_segs; - } + memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t)); + p_code_block->segs = l_segs; + p_code_block->m_current_max_segs = l_current_max_segs; + for (i = 0; i < l_current_max_segs; ++i) { + opj_tcd_reinit_segment(&l_segs[i]); + } + p_code_block->chunks = l_chunks; + p_code_block->numchunksalloc = l_numchunksalloc; + } - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_UINT32 opj_tcd_get_decoded_tile_size ( opj_tcd_t *p_tcd ) +OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd, + OPJ_BOOL take_into_account_partial_decoding) { - OPJ_UINT32 i; - OPJ_UINT32 l_data_size = 0; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_tilecomp_t * l_tile_comp = 00; - opj_tcd_resolution_t * l_res = 00; - OPJ_UINT32 l_size_comp, l_remaining; - OPJ_UINT32 l_temp; - - l_tile_comp = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; - - for (i=0;i<p_tcd->image->numcomps;++i) { - l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ - l_remaining = l_img_comp->prec & 7; /* (%8) */ - - if(l_remaining) { - ++l_size_comp; - } - - if (l_size_comp == 3) { - l_size_comp = 4; - } - - l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; - l_temp = (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0)); /* x1*y1 can't overflow */ + OPJ_UINT32 i; + OPJ_UINT32 l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tcd_resolution_t * l_res = 00; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_UINT32 l_temp; + + l_tile_comp = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + + for (i = 0; i < p_tcd->image->numcomps; ++i) { + OPJ_UINT32 w, h; + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + + if (l_remaining) { + ++l_size_comp; + } - if (l_size_comp && ((OPJ_UINT32)-1) / l_size_comp < l_temp) { - return (OPJ_UINT32)-1; - } - l_temp *= l_size_comp; + if (l_size_comp == 3) { + l_size_comp = 4; + } - if (l_temp > ((OPJ_UINT32)-1) - l_data_size) { - return (OPJ_UINT32)-1; - } - l_data_size += l_temp; + l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; + if (take_into_account_partial_decoding && !p_tcd->whole_tile_decoding) { + w = l_res->win_x1 - l_res->win_x0; + h = l_res->win_y1 - l_res->win_y0; + } else { + w = (OPJ_UINT32)(l_res->x1 - l_res->x0); + h = (OPJ_UINT32)(l_res->y1 - l_res->y0); + } + if (h > 0 && UINT_MAX / w < h) { + return UINT_MAX; + } + l_temp = w * h; + if (l_size_comp && UINT_MAX / l_size_comp < l_temp) { + return UINT_MAX; + } + l_temp *= l_size_comp; - ++l_img_comp; - ++l_tile_comp; + if (l_temp > UINT_MAX - l_data_size) { + return UINT_MAX; } + l_data_size += l_temp; + ++l_img_comp; + ++l_tile_comp; + } - return l_data_size; + return l_data_size; } -OPJ_BOOL opj_tcd_encode_tile( opj_tcd_t *p_tcd, - OPJ_UINT32 p_tile_no, - OPJ_BYTE *p_dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_max_length, - opj_codestream_info_t *p_cstr_info) +OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_length, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager) { - if (p_tcd->cur_tp_num == 0) { - - p_tcd->tcd_tileno = p_tile_no; - p_tcd->tcp = &p_tcd->cp->tcps[p_tile_no]; + if (p_tcd->cur_tp_num == 0) { - /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ - if(p_cstr_info) { - OPJ_UINT32 l_num_packs = 0; - OPJ_UINT32 i; - opj_tcd_tilecomp_t *l_tilec_idx = &p_tcd->tcd_image->tiles->comps[0]; /* based on component 0 */ - opj_tccp_t *l_tccp = p_tcd->tcp->tccps; /* based on component 0 */ - - for (i = 0; i < l_tilec_idx->numresolutions; i++) { - opj_tcd_resolution_t *l_res_idx = &l_tilec_idx->resolutions[i]; - - p_cstr_info->tile[p_tile_no].pw[i] = (int)l_res_idx->pw; - p_cstr_info->tile[p_tile_no].ph[i] = (int)l_res_idx->ph; - - l_num_packs += l_res_idx->pw * l_res_idx->ph; - p_cstr_info->tile[p_tile_no].pdx[i] = (int)l_tccp->prcw[i]; - p_cstr_info->tile[p_tile_no].pdy[i] = (int)l_tccp->prch[i]; - } - p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc((size_t)p_cstr_info->numcomps * (size_t)p_cstr_info->numlayers * l_num_packs, sizeof(opj_packet_info_t)); - if (!p_cstr_info->tile[p_tile_no].packet) { - /* FIXME event manager error callback */ - return OPJ_FALSE; - } - } - /* << INDEX */ - - /* FIXME _ProfStart(PGROUP_DC_SHIFT); */ - /*---------------TILE-------------------*/ - if (! opj_tcd_dc_level_shift_encode(p_tcd)) { - return OPJ_FALSE; - } - /* FIXME _ProfStop(PGROUP_DC_SHIFT); */ - - /* FIXME _ProfStart(PGROUP_MCT); */ - if (! opj_tcd_mct_encode(p_tcd)) { - return OPJ_FALSE; - } - /* FIXME _ProfStop(PGROUP_MCT); */ + p_tcd->tcd_tileno = p_tile_no; + p_tcd->tcp = &p_tcd->cp->tcps[p_tile_no]; - /* FIXME _ProfStart(PGROUP_DWT); */ - if (! opj_tcd_dwt_encode(p_tcd)) { - return OPJ_FALSE; - } - /* FIXME _ProfStop(PGROUP_DWT); */ + /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ + if (p_cstr_info) { + OPJ_UINT32 l_num_packs = 0; + OPJ_UINT32 i; + opj_tcd_tilecomp_t *l_tilec_idx = + &p_tcd->tcd_image->tiles->comps[0]; /* based on component 0 */ + opj_tccp_t *l_tccp = p_tcd->tcp->tccps; /* based on component 0 */ + + for (i = 0; i < l_tilec_idx->numresolutions; i++) { + opj_tcd_resolution_t *l_res_idx = &l_tilec_idx->resolutions[i]; + + p_cstr_info->tile[p_tile_no].pw[i] = (int)l_res_idx->pw; + p_cstr_info->tile[p_tile_no].ph[i] = (int)l_res_idx->ph; + + l_num_packs += l_res_idx->pw * l_res_idx->ph; + p_cstr_info->tile[p_tile_no].pdx[i] = (int)l_tccp->prcw[i]; + p_cstr_info->tile[p_tile_no].pdy[i] = (int)l_tccp->prch[i]; + } + p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc(( + OPJ_SIZE_T)p_cstr_info->numcomps * (OPJ_SIZE_T)p_cstr_info->numlayers * + l_num_packs, + sizeof(opj_packet_info_t)); + if (!p_cstr_info->tile[p_tile_no].packet) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + /* << INDEX */ - /* FIXME _ProfStart(PGROUP_T1); */ - if (! opj_tcd_t1_encode(p_tcd)) { - return OPJ_FALSE; - } - /* FIXME _ProfStop(PGROUP_T1); */ + /* FIXME _ProfStart(PGROUP_DC_SHIFT); */ + /*---------------TILE-------------------*/ + if (! opj_tcd_dc_level_shift_encode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DC_SHIFT); */ - /* FIXME _ProfStart(PGROUP_RATE); */ - if (! opj_tcd_rate_allocate_encode(p_tcd,p_dest,p_max_length,p_cstr_info)) { - return OPJ_FALSE; - } - /* FIXME _ProfStop(PGROUP_RATE); */ + /* FIXME _ProfStart(PGROUP_MCT); */ + if (! opj_tcd_mct_encode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_MCT); */ + /* FIXME _ProfStart(PGROUP_DWT); */ + if (! opj_tcd_dwt_encode(p_tcd)) { + return OPJ_FALSE; } - /*--------------TIER2------------------*/ + /* FIXME _ProfStop(PGROUP_DWT); */ - /* INDEX */ - if (p_cstr_info) { - p_cstr_info->index_write = 1; + /* FIXME _ProfStart(PGROUP_T1); */ + if (! opj_tcd_t1_encode(p_tcd)) { + return OPJ_FALSE; } - /* FIXME _ProfStart(PGROUP_T2); */ + /* FIXME _ProfStop(PGROUP_T1); */ - if (! opj_tcd_t2_encode(p_tcd,p_dest,p_data_written,p_max_length,p_cstr_info)) { - return OPJ_FALSE; + /* FIXME _ProfStart(PGROUP_RATE); */ + if (! opj_tcd_rate_allocate_encode(p_tcd, p_dest, p_max_length, + p_cstr_info, p_manager)) { + return OPJ_FALSE; } - /* FIXME _ProfStop(PGROUP_T2); */ + /* FIXME _ProfStop(PGROUP_RATE); */ - /*---------------CLEAN-------------------*/ + } + /*--------------TIER2------------------*/ - return OPJ_TRUE; + /* INDEX */ + if (p_cstr_info) { + p_cstr_info->index_write = 1; + } + /* FIXME _ProfStart(PGROUP_T2); */ + + if (! opj_tcd_t2_encode(p_tcd, p_dest, p_data_written, p_max_length, + p_cstr_info, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T2); */ + + /*---------------CLEAN-------------------*/ + + return OPJ_TRUE; } -OPJ_BOOL opj_tcd_decode_tile( opj_tcd_t *p_tcd, - OPJ_BYTE *p_src, - OPJ_UINT32 p_max_length, - OPJ_UINT32 p_tile_no, - opj_codestream_index_t *p_cstr_index, - opj_event_mgr_t *p_manager - ) +OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 win_x0, + OPJ_UINT32 win_y0, + OPJ_UINT32 win_x1, + OPJ_UINT32 win_y1, + OPJ_UINT32 numcomps_to_decode, + const OPJ_UINT32 *comps_indices, + OPJ_BYTE *p_src, + OPJ_UINT32 p_max_length, + OPJ_UINT32 p_tile_no, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager + ) { - OPJ_UINT32 l_data_read; - p_tcd->tcd_tileno = p_tile_no; - p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]); - -#ifdef TODO_MSD /* FIXME */ - /* INDEX >> */ - if(p_cstr_info) { - OPJ_UINT32 resno, compno, numprec = 0; - for (compno = 0; compno < (OPJ_UINT32) p_cstr_info->numcomps; compno++) { - opj_tcp_t *tcp = &p_tcd->cp->tcps[0]; - opj_tccp_t *tccp = &tcp->tccps[compno]; - opj_tcd_tilecomp_t *tilec_idx = &p_tcd->tcd_image->tiles->comps[compno]; - for (resno = 0; resno < tilec_idx->numresolutions; resno++) { - opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[resno]; - p_cstr_info->tile[p_tile_no].pw[resno] = res_idx->pw; - p_cstr_info->tile[p_tile_no].ph[resno] = res_idx->ph; - numprec += res_idx->pw * res_idx->ph; - p_cstr_info->tile[p_tile_no].pdx[resno] = tccp->prcw[resno]; - p_cstr_info->tile[p_tile_no].pdy[resno] = tccp->prch[resno]; - } - } - p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t *) opj_malloc(p_cstr_info->numlayers * numprec * sizeof(opj_packet_info_t)); - p_cstr_info->packno = 0; + OPJ_UINT32 l_data_read; + OPJ_UINT32 compno; + + p_tcd->tcd_tileno = p_tile_no; + p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]); + p_tcd->win_x0 = win_x0; + p_tcd->win_y0 = win_y0; + p_tcd->win_x1 = win_x1; + p_tcd->win_y1 = win_y1; + p_tcd->whole_tile_decoding = OPJ_TRUE; + + opj_free(p_tcd->used_component); + p_tcd->used_component = NULL; + + if (numcomps_to_decode) { + OPJ_BOOL* used_component = (OPJ_BOOL*) opj_calloc(sizeof(OPJ_BOOL), + p_tcd->image->numcomps); + if (used_component == NULL) { + return OPJ_FALSE; + } + for (compno = 0; compno < numcomps_to_decode; compno++) { + used_component[ comps_indices[compno] ] = OPJ_TRUE; } - /* << INDEX */ -#endif - /*--------------TIER2------------------*/ - /* FIXME _ProfStart(PGROUP_T2); */ - l_data_read = 0; - if (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index, p_manager)) - { - return OPJ_FALSE; + p_tcd->used_component = used_component; + } + + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; } - /* FIXME _ProfStop(PGROUP_T2); */ - /*------------------TIER1-----------------*/ + if (!opj_tcd_is_whole_tilecomp_decoding(p_tcd, compno)) { + p_tcd->whole_tile_decoding = OPJ_FALSE; + break; + } + } + + if (p_tcd->whole_tile_decoding) { + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_tcd_resolution_t *l_res = & + (tilec->resolutions[tilec->minimum_num_resolutions - 1]); + OPJ_SIZE_T l_data_size; + + /* compute l_data_size with overflow check */ + OPJ_SIZE_T res_w = (OPJ_SIZE_T)(l_res->x1 - l_res->x0); + OPJ_SIZE_T res_h = (OPJ_SIZE_T)(l_res->y1 - l_res->y0); + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ + if (res_h > 0 && res_w > SIZE_MAX / res_h) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size = res_w * res_h; - /* FIXME _ProfStart(PGROUP_T1); */ - if - (! opj_tcd_t1_decode(p_tcd)) - { + if (SIZE_MAX / sizeof(OPJ_UINT32) < l_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); return OPJ_FALSE; - } - /* FIXME _ProfStop(PGROUP_T1); */ + } + l_data_size *= sizeof(OPJ_UINT32); - /*----------------DWT---------------------*/ + tilec->data_size_needed = l_data_size; - /* FIXME _ProfStart(PGROUP_DWT); */ - if - (! opj_tcd_dwt_decode(p_tcd)) - { + if (!opj_alloc_tile_component_data(tilec)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); return OPJ_FALSE; + } } - /* FIXME _ProfStop(PGROUP_DWT); */ - - /*----------------MCT-------------------*/ - /* FIXME _ProfStart(PGROUP_MCT); */ - if - (! opj_tcd_mct_decode(p_tcd, p_manager)) - { + } else { + /* Compute restricted tile-component and tile-resolution coordinates */ + /* of the window of interest, but defer the memory allocation until */ + /* we know the resno_decoded */ + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + OPJ_UINT32 resno; + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + tilec->win_x0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx)); + tilec->win_y0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy)); + tilec->win_x1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx)); + tilec->win_y1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy)); + if (tilec->win_x1 < tilec->win_x0 || + tilec->win_y1 < tilec->win_y0) { + /* We should not normally go there. The circumstance is when */ + /* the tile coordinates do not intersect the area of interest */ + /* Upper level logic should not even try to decode that tile */ + opj_event_msg(p_manager, EVT_ERROR, + "Invalid tilec->win_xxx values\n"); return OPJ_FALSE; + } + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = tilec->resolutions + resno; + res->win_x0 = opj_uint_ceildivpow2(tilec->win_x0, + tilec->numresolutions - 1 - resno); + res->win_y0 = opj_uint_ceildivpow2(tilec->win_y0, + tilec->numresolutions - 1 - resno); + res->win_x1 = opj_uint_ceildivpow2(tilec->win_x1, + tilec->numresolutions - 1 - resno); + res->win_y1 = opj_uint_ceildivpow2(tilec->win_y1, + tilec->numresolutions - 1 - resno); + } } - /* FIXME _ProfStop(PGROUP_MCT); */ + } - /* FIXME _ProfStart(PGROUP_DC_SHIFT); */ - if - (! opj_tcd_dc_level_shift_decode(p_tcd)) - { - return OPJ_FALSE; +#ifdef TODO_MSD /* FIXME */ + /* INDEX >> */ + if (p_cstr_info) { + OPJ_UINT32 resno, compno, numprec = 0; + for (compno = 0; compno < (OPJ_UINT32) p_cstr_info->numcomps; compno++) { + opj_tcp_t *tcp = &p_tcd->cp->tcps[0]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_tcd_tilecomp_t *tilec_idx = &p_tcd->tcd_image->tiles->comps[compno]; + for (resno = 0; resno < tilec_idx->numresolutions; resno++) { + opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[resno]; + p_cstr_info->tile[p_tile_no].pw[resno] = res_idx->pw; + p_cstr_info->tile[p_tile_no].ph[resno] = res_idx->ph; + numprec += res_idx->pw * res_idx->ph; + p_cstr_info->tile[p_tile_no].pdx[resno] = tccp->prcw[resno]; + p_cstr_info->tile[p_tile_no].pdy[resno] = tccp->prch[resno]; + } } - /* FIXME _ProfStop(PGROUP_DC_SHIFT); */ + p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t *) opj_malloc( + p_cstr_info->numlayers * numprec * sizeof(opj_packet_info_t)); + p_cstr_info->packno = 0; + } + /* << INDEX */ +#endif + /*--------------TIER2------------------*/ + /* FIXME _ProfStart(PGROUP_T2); */ + l_data_read = 0; + if (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index, + p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T2); */ + + /*------------------TIER1-----------------*/ + + /* FIXME _ProfStart(PGROUP_T1); */ + if (! opj_tcd_t1_decode(p_tcd, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T1); */ + + + /* For subtile decoding, now we know the resno_decoded, we can allocate */ + /* the tile data buffer */ + if (!p_tcd->whole_tile_decoding) { + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + opj_tcd_resolution_t *res = tilec->resolutions + image_comp->resno_decoded; + OPJ_SIZE_T w = res->win_x1 - res->win_x0; + OPJ_SIZE_T h = res->win_y1 - res->win_y0; + OPJ_SIZE_T l_data_size; + + opj_image_data_free(tilec->data_win); + tilec->data_win = NULL; + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + if (w > 0 && h > 0) { + if (w > SIZE_MAX / h) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size = w * h; + if (l_data_size > SIZE_MAX / sizeof(OPJ_INT32)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size *= sizeof(OPJ_INT32); - /*---------------TILE-------------------*/ - return OPJ_TRUE; + tilec->data_win = (OPJ_INT32*) opj_image_data_alloc(l_data_size); + if (tilec->data_win == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + } + } + } + + /*----------------DWT---------------------*/ + + /* FIXME _ProfStart(PGROUP_DWT); */ + if + (! opj_tcd_dwt_decode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DWT); */ + + /*----------------MCT-------------------*/ + /* FIXME _ProfStart(PGROUP_MCT); */ + if + (! opj_tcd_mct_decode(p_tcd, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_MCT); */ + + /* FIXME _ProfStart(PGROUP_DC_SHIFT); */ + if + (! opj_tcd_dc_level_shift_decode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DC_SHIFT); */ + + + /*---------------TILE-------------------*/ + return OPJ_TRUE; } -OPJ_BOOL opj_tcd_update_tile_data ( opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest, - OPJ_UINT32 p_dest_length - ) +OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest, + OPJ_UINT32 p_dest_length + ) { - OPJ_UINT32 i,j,k,l_data_size = 0; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_tilecomp_t * l_tilec = 00; - opj_tcd_resolution_t * l_res; - OPJ_UINT32 l_size_comp, l_remaining; - OPJ_UINT32 l_stride, l_width,l_height; - - l_data_size = opj_tcd_get_decoded_tile_size(p_tcd); - if (l_data_size == (OPJ_UINT32)-1 || l_data_size > p_dest_length) { - return OPJ_FALSE; + OPJ_UINT32 i, j, k, l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + opj_tcd_resolution_t * l_res; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_UINT32 l_stride, l_width, l_height; + + l_data_size = opj_tcd_get_decoded_tile_size(p_tcd, OPJ_TRUE); + if (l_data_size == UINT_MAX || l_data_size > p_dest_length) { + return OPJ_FALSE; + } + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + + for (i = 0; i < p_tcd->image->numcomps; ++i) { + const OPJ_INT32* l_src_data; + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_res = l_tilec->resolutions + l_img_comp->resno_decoded; + if (p_tcd->whole_tile_decoding) { + l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); + l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); + l_stride = (OPJ_UINT32)(l_tilec->resolutions[l_tilec->minimum_num_resolutions - + 1].x1 - + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x0) - l_width; + l_src_data = l_tilec->data; + } else { + l_width = l_res->win_x1 - l_res->win_x0; + l_height = l_res->win_y1 - l_res->win_y0; + l_stride = 0; + l_src_data = l_tilec->data_win; } - l_tilec = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; + if (l_remaining) { + ++l_size_comp; + } - for (i=0;i<p_tcd->image->numcomps;++i) { - l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ - l_remaining = l_img_comp->prec & 7; /* (%8) */ - l_res = l_tilec->resolutions + l_img_comp->resno_decoded; - l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); - l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); - l_stride = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0) - l_width; + if (l_size_comp == 3) { + l_size_comp = 4; + } - if (l_remaining) { - ++l_size_comp; + switch (l_size_comp) { + case 1: { + OPJ_CHAR * l_dest_ptr = (OPJ_CHAR *) p_dest; + const OPJ_INT32 * l_src_ptr = l_src_data; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_CHAR)(*(l_src_ptr++)); + } + l_src_ptr += l_stride; } - - if (l_size_comp == 3) { - l_size_comp = 4; + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_CHAR)((*(l_src_ptr++)) & 0xff); + } + l_src_ptr += l_stride; } + } - switch (l_size_comp) - { - case 1: - { - OPJ_CHAR * l_dest_ptr = (OPJ_CHAR *) p_dest; - const OPJ_INT32 * l_src_ptr = l_tilec->data; - - if (l_img_comp->sgnd) { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (OPJ_CHAR) (*(l_src_ptr++)); - } - l_src_ptr += l_stride; - } - } - else { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (OPJ_CHAR) ((*(l_src_ptr++))&0xff); - } - l_src_ptr += l_stride; - } - } - - p_dest = (OPJ_BYTE *)l_dest_ptr; - } - break; - case 2: - { - const OPJ_INT32 * l_src_ptr = l_tilec->data; - OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest; - - if (l_img_comp->sgnd) { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (OPJ_INT16) (*(l_src_ptr++)); - } - l_src_ptr += l_stride; - } - } - else { - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (OPJ_INT16) ((*(l_src_ptr++))&0xffff); - } - l_src_ptr += l_stride; - } - } - - p_dest = (OPJ_BYTE*) l_dest_ptr; - } - break; - case 4: - { - OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest; - OPJ_INT32 * l_src_ptr = l_tilec->data; - - for (j=0;j<l_height;++j) { - for (k=0;k<l_width;++k) { - *(l_dest_ptr++) = (*(l_src_ptr++)); - } - l_src_ptr += l_stride; - } - - p_dest = (OPJ_BYTE*) l_dest_ptr; - } - break; + p_dest = (OPJ_BYTE *)l_dest_ptr; + } + break; + case 2: { + const OPJ_INT32 * l_src_ptr = l_src_data; + OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + OPJ_INT16 val = (OPJ_INT16)(*(l_src_ptr++)); + memcpy(l_dest_ptr, &val, sizeof(val)); + l_dest_ptr ++; + } + l_src_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + OPJ_INT16 val = (OPJ_INT16)((*(l_src_ptr++)) & 0xffff); + memcpy(l_dest_ptr, &val, sizeof(val)); + l_dest_ptr ++; + } + l_src_ptr += l_stride; } + } - ++l_img_comp; - ++l_tilec; + p_dest = (OPJ_BYTE*) l_dest_ptr; + } + break; + case 4: { + OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest; + const OPJ_INT32 * l_src_ptr = l_src_data; + + for (j = 0; j < l_height; ++j) { + memcpy(l_dest_ptr, l_src_ptr, l_width * sizeof(OPJ_INT32)); + l_dest_ptr += l_width; + l_src_ptr += l_width + l_stride; + } + + p_dest = (OPJ_BYTE*) l_dest_ptr; + } + break; } - return OPJ_TRUE; + ++l_img_comp; + ++l_tilec; + } + + return OPJ_TRUE; } @@ -1492,331 +1827,432 @@ OPJ_BOOL opj_tcd_update_tile_data ( opj_tcd_t *p_tcd, static void opj_tcd_free_tile(opj_tcd_t *p_tcd) { - OPJ_UINT32 compno, resno, bandno, precno; - opj_tcd_tile_t *l_tile = 00; - opj_tcd_tilecomp_t *l_tile_comp = 00; - opj_tcd_resolution_t *l_res = 00; - opj_tcd_band_t *l_band = 00; - opj_tcd_precinct_t *l_precinct = 00; - OPJ_UINT32 l_nb_resolutions, l_nb_precincts; - void (* l_tcd_code_block_deallocate) (opj_tcd_precinct_t *) = 00; + OPJ_UINT32 compno, resno, bandno, precno; + opj_tcd_tile_t *l_tile = 00; + opj_tcd_tilecomp_t *l_tile_comp = 00; + opj_tcd_resolution_t *l_res = 00; + opj_tcd_band_t *l_band = 00; + opj_tcd_precinct_t *l_precinct = 00; + OPJ_UINT32 l_nb_resolutions, l_nb_precincts; + void (* l_tcd_code_block_deallocate)(opj_tcd_precinct_t *) = 00; + + if (! p_tcd) { + return; + } + + if (! p_tcd->tcd_image) { + return; + } + + if (p_tcd->m_is_decoder) { + l_tcd_code_block_deallocate = opj_tcd_code_block_dec_deallocate; + } else { + l_tcd_code_block_deallocate = opj_tcd_code_block_enc_deallocate; + } + + l_tile = p_tcd->tcd_image->tiles; + if (! l_tile) { + return; + } + + l_tile_comp = l_tile->comps; + + for (compno = 0; compno < l_tile->numcomps; ++compno) { + l_res = l_tile_comp->resolutions; + if (l_res) { + + l_nb_resolutions = l_tile_comp->resolutions_size / (OPJ_UINT32)sizeof( + opj_tcd_resolution_t); + for (resno = 0; resno < l_nb_resolutions; ++resno) { + l_band = l_res->bands; + for (bandno = 0; bandno < 3; ++bandno) { + l_precinct = l_band->precincts; + if (l_precinct) { + + l_nb_precincts = l_band->precincts_data_size / (OPJ_UINT32)sizeof( + opj_tcd_precinct_t); + for (precno = 0; precno < l_nb_precincts; ++precno) { + opj_tgt_destroy(l_precinct->incltree); + l_precinct->incltree = 00; + opj_tgt_destroy(l_precinct->imsbtree); + l_precinct->imsbtree = 00; + (*l_tcd_code_block_deallocate)(l_precinct); + ++l_precinct; + } - if (! p_tcd) { - return; - } + opj_free(l_band->precincts); + l_band->precincts = 00; + } + ++l_band; + } /* for (resno */ + ++l_res; + } - if (! p_tcd->tcd_image) { - return; + opj_free(l_tile_comp->resolutions); + l_tile_comp->resolutions = 00; } - if (p_tcd->m_is_decoder) { - l_tcd_code_block_deallocate = opj_tcd_code_block_dec_deallocate; - } - else { - l_tcd_code_block_deallocate = opj_tcd_code_block_enc_deallocate; + if (l_tile_comp->ownsData && l_tile_comp->data) { + opj_image_data_free(l_tile_comp->data); + l_tile_comp->data = 00; + l_tile_comp->ownsData = 0; + l_tile_comp->data_size = 0; + l_tile_comp->data_size_needed = 0; } - l_tile = p_tcd->tcd_image->tiles; - if (! l_tile) { - return; - } + opj_image_data_free(l_tile_comp->data_win); - l_tile_comp = l_tile->comps; + ++l_tile_comp; + } - for (compno = 0; compno < l_tile->numcomps; ++compno) { - l_res = l_tile_comp->resolutions; - if (l_res) { + opj_free(l_tile->comps); + l_tile->comps = 00; + opj_free(p_tcd->tcd_image->tiles); + p_tcd->tcd_image->tiles = 00; +} - l_nb_resolutions = l_tile_comp->resolutions_size / sizeof(opj_tcd_resolution_t); - for (resno = 0; resno < l_nb_resolutions; ++resno) { - l_band = l_res->bands; - for (bandno = 0; bandno < 3; ++bandno) { - l_precinct = l_band->precincts; - if (l_precinct) { - l_nb_precincts = l_band->precincts_data_size / sizeof(opj_tcd_precinct_t); - for (precno = 0; precno < l_nb_precincts; ++precno) { - opj_tgt_destroy(l_precinct->incltree); - l_precinct->incltree = 00; - opj_tgt_destroy(l_precinct->imsbtree); - l_precinct->imsbtree = 00; - (*l_tcd_code_block_deallocate) (l_precinct); - ++l_precinct; - } +static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_src_size, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager + ) +{ + opj_t2_t * l_t2; + + l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp); + if (l_t2 == 00) { + return OPJ_FALSE; + } + + if (! opj_t2_decode_packets( + p_tcd, + l_t2, + p_tcd->tcd_tileno, + p_tcd->tcd_image->tiles, + p_src_data, + p_data_read, + p_max_src_size, + p_cstr_index, + p_manager)) { + opj_t2_destroy(l_t2); + return OPJ_FALSE; + } - opj_free(l_band->precincts); - l_band->precincts = 00; - } - ++l_band; - } /* for (resno */ - ++l_res; - } + opj_t2_destroy(l_t2); - opj_free(l_tile_comp->resolutions); - l_tile_comp->resolutions = 00; - } + /*---------------CLEAN-------------------*/ + return OPJ_TRUE; +} - if (l_tile_comp->ownsData && l_tile_comp->data) { - opj_free(l_tile_comp->data); - l_tile_comp->data = 00; - l_tile_comp->ownsData = 0; - l_tile_comp->data_size = 0; - l_tile_comp->data_size_needed = 0; - } - ++l_tile_comp; +static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 compno; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + volatile OPJ_BOOL ret = OPJ_TRUE; + OPJ_BOOL check_pterm = OPJ_FALSE; + opj_mutex_t* p_manager_mutex = NULL; + + p_manager_mutex = opj_mutex_create(); + + /* Only enable PTERM check if we decode all layers */ + if (p_tcd->tcp->num_layers_to_decode == p_tcd->tcp->numlayers && + (l_tccp->cblksty & J2K_CCP_CBLKSTY_PTERM) != 0) { + check_pterm = OPJ_TRUE; + } + + for (compno = 0; compno < l_tile->numcomps; + ++compno, ++l_tile_comp, ++l_tccp) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; } - opj_free(l_tile->comps); - l_tile->comps = 00; - opj_free(p_tcd->tcd_image->tiles); - p_tcd->tcd_image->tiles = 00; + opj_t1_decode_cblks(p_tcd, &ret, l_tile_comp, l_tccp, + p_manager, p_manager_mutex, check_pterm); + if (!ret) { + break; + } + } + + opj_thread_pool_wait_completion(p_tcd->thread_pool, 0); + if (p_manager_mutex) { + opj_mutex_destroy(p_manager_mutex); + } + return ret; } -static OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd, - OPJ_BYTE * p_src_data, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_src_size, - opj_codestream_index_t *p_cstr_index, - opj_event_mgr_t *p_manager - ) +static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd) { - opj_t2_t * l_t2; - - l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp); - if (l_t2 == 00) { - return OPJ_FALSE; + OPJ_UINT32 compno; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + opj_image_comp_t * l_img_comp = p_tcd->image->comps; + + for (compno = 0; compno < l_tile->numcomps; + compno++, ++l_tile_comp, ++l_img_comp, ++l_tccp) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; } - if (! opj_t2_decode_packets( - l_t2, - p_tcd->tcd_tileno, - p_tcd->tcd_image->tiles, - p_src_data, - p_data_read, - p_max_src_size, - p_cstr_index, - p_manager)) { - opj_t2_destroy(l_t2); + if (l_tccp->qmfbid == 1) { + if (! opj_dwt_decode(p_tcd, l_tile_comp, + l_img_comp->resno_decoded + 1)) { + return OPJ_FALSE; + } + } else { + if (! opj_dwt_decode_real(p_tcd, l_tile_comp, + l_img_comp->resno_decoded + 1)) { return OPJ_FALSE; + } } - opj_t2_destroy(l_t2); + } - /*---------------CLEAN-------------------*/ - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd ) +static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) { - OPJ_UINT32 compno; - opj_t1_t * l_t1; - opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; - opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps; - opj_tccp_t * l_tccp = p_tcd->tcp->tccps; - + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcp_t * l_tcp = p_tcd->tcp; + opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; + OPJ_UINT32 l_samples, i; - l_t1 = opj_t1_create(OPJ_FALSE); - if (l_t1 == 00) { + if (l_tcp->mct == 0 || p_tcd->used_component != NULL) { + return OPJ_TRUE; + } + + if (p_tcd->whole_tile_decoding) { + opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + + /* A bit inefficient: we process more data than needed if */ + /* resno_decoded < l_tile_comp->minimum_num_resolutions-1, */ + /* but we would need to take into account a stride then */ + l_samples = (OPJ_UINT32)((res_comp0->x1 - res_comp0->x0) * + (res_comp0->y1 - res_comp0->y0)); + if (l_tile->numcomps >= 3) { + if (l_tile_comp->minimum_num_resolutions != + l_tile->comps[1].minimum_num_resolutions || + l_tile_comp->minimum_num_resolutions != + l_tile->comps[2].minimum_num_resolutions) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); return OPJ_FALSE; + } } - - for (compno = 0; compno < l_tile->numcomps; ++compno) { - /* The +3 is headroom required by the vectorized DWT */ - if (OPJ_FALSE == opj_t1_decode_cblks(l_t1, l_tile_comp, l_tccp)) { - opj_t1_destroy(l_t1); - return OPJ_FALSE; - } - ++l_tile_comp; - ++l_tccp; + if (l_tile->numcomps >= 3) { + opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + /* testcase 1336.pdf.asan.47.376 */ + if (p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[1].resno_decoded || + p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[2].resno_decoded || + (OPJ_SIZE_T)(res_comp1->x1 - res_comp1->x0) * + (OPJ_SIZE_T)(res_comp1->y1 - res_comp1->y0) != l_samples || + (OPJ_SIZE_T)(res_comp2->x1 - res_comp2->x0) * + (OPJ_SIZE_T)(res_comp2->y1 - res_comp2->y0) != l_samples) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + } else { + opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions + + p_tcd->image->comps[0].resno_decoded; + + l_samples = (res_comp0->win_x1 - res_comp0->win_x0) * + (res_comp0->win_y1 - res_comp0->win_y0); + if (l_tile->numcomps >= 3) { + opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions + + p_tcd->image->comps[1].resno_decoded; + opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions + + p_tcd->image->comps[2].resno_decoded; + /* testcase 1336.pdf.asan.47.376 */ + if (p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[1].resno_decoded || + p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[2].resno_decoded || + (OPJ_SIZE_T)(res_comp1->win_x1 - res_comp1->win_x0) * + (OPJ_SIZE_T)(res_comp1->win_y1 - res_comp1->win_y0) != l_samples || + (OPJ_SIZE_T)(res_comp2->win_x1 - res_comp2->win_x0) * + (OPJ_SIZE_T)(res_comp2->win_y1 - res_comp2->win_y0) != l_samples) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } } + } - opj_t1_destroy(l_t1); + if (l_tile->numcomps >= 3) { + if (l_tcp->mct == 2) { + OPJ_BYTE ** l_data; - return OPJ_TRUE; -} + if (! l_tcp->m_mct_decoding_matrix) { + return OPJ_TRUE; + } + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps * sizeof(OPJ_BYTE*)); + if (! l_data) { + return OPJ_FALSE; + } -static OPJ_BOOL opj_tcd_dwt_decode ( opj_tcd_t *p_tcd ) -{ - OPJ_UINT32 compno; - opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; - opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; - opj_tccp_t * l_tccp = p_tcd->tcp->tccps; - opj_image_comp_t * l_img_comp = p_tcd->image->comps; - - for (compno = 0; compno < l_tile->numcomps; compno++) { - /* - if (tcd->cp->reduce != 0) { - tcd->image->comps[compno].resno_decoded = - tile->comps[compno].numresolutions - tcd->cp->reduce - 1; - if (tcd->image->comps[compno].resno_decoded < 0) - { - return false; - } + for (i = 0; i < l_tile->numcomps; ++i) { + if (p_tcd->whole_tile_decoding) { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + } else { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data_win; } - numres2decode = tcd->image->comps[compno].resno_decoded + 1; - if(numres2decode > 0){ - */ + ++l_tile_comp; + } + + if (! opj_mct_decode_custom(/* MCT data */ + (OPJ_BYTE*) l_tcp->m_mct_decoding_matrix, + /* size of components */ + l_samples, + /* components */ + l_data, + /* nb of components (i.e. size of pData) */ + l_tile->numcomps, + /* tells if the data is signed */ + p_tcd->image->comps->sgnd)) { + opj_free(l_data); + return OPJ_FALSE; + } - if (l_tccp->qmfbid == 1) { - if (! opj_dwt_decode(l_tile_comp, l_img_comp->resno_decoded+1)) { - return OPJ_FALSE; - } + opj_free(l_data); + } else { + if (l_tcp->tccps->qmfbid == 1) { + if (p_tcd->whole_tile_decoding) { + opj_mct_decode(l_tile->comps[0].data, + l_tile->comps[1].data, + l_tile->comps[2].data, + l_samples); + } else { + opj_mct_decode(l_tile->comps[0].data_win, + l_tile->comps[1].data_win, + l_tile->comps[2].data_win, + l_samples); } - else { - if (! opj_dwt_decode_real(l_tile_comp, l_img_comp->resno_decoded+1)) { - return OPJ_FALSE; - } + } else { + if (p_tcd->whole_tile_decoding) { + opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data, + (OPJ_FLOAT32*)l_tile->comps[1].data, + (OPJ_FLOAT32*)l_tile->comps[2].data, + l_samples); + } else { + opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data_win, + (OPJ_FLOAT32*)l_tile->comps[1].data_win, + (OPJ_FLOAT32*)l_tile->comps[2].data_win, + l_samples); } - - ++l_tile_comp; - ++l_img_comp; - ++l_tccp; + } } + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n", + l_tile->numcomps); + } - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_mct_decode ( opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) -{ - opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; - opj_tcp_t * l_tcp = p_tcd->tcp; - opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; - OPJ_UINT32 l_samples,i; - - if (! l_tcp->mct) { - return OPJ_TRUE; - } - - l_samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0)); - - if (l_tile->numcomps >= 3 ){ - /* testcase 1336.pdf.asan.47.376 */ - if ((l_tile->comps[0].x1 - l_tile->comps[0].x0) * (l_tile->comps[0].y1 - l_tile->comps[0].y0) < (OPJ_INT32)l_samples || - (l_tile->comps[1].x1 - l_tile->comps[1].x0) * (l_tile->comps[1].y1 - l_tile->comps[1].y0) < (OPJ_INT32)l_samples || - (l_tile->comps[2].x1 - l_tile->comps[2].x0) * (l_tile->comps[2].y1 - l_tile->comps[2].y0) < (OPJ_INT32)l_samples) { - opj_event_msg(p_manager, EVT_ERROR, "Tiles don't all have the same dimension. Skip the MCT step.\n"); - return OPJ_FALSE; - } - else if (l_tcp->mct == 2) { - OPJ_BYTE ** l_data; - - if (! l_tcp->m_mct_decoding_matrix) { - return OPJ_TRUE; - } - - l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); - if (! l_data) { - return OPJ_FALSE; - } - for (i=0;i<l_tile->numcomps;++i) { - l_data[i] = (OPJ_BYTE*) l_tile_comp->data; - ++l_tile_comp; - } - - if (! opj_mct_decode_custom(/* MCT data */ - (OPJ_BYTE*) l_tcp->m_mct_decoding_matrix, - /* size of components */ - l_samples, - /* components */ - l_data, - /* nb of components (i.e. size of pData) */ - l_tile->numcomps, - /* tells if the data is signed */ - p_tcd->image->comps->sgnd)) { - opj_free(l_data); - return OPJ_FALSE; - } - opj_free(l_data); - } - else { - if (l_tcp->tccps->qmfbid == 1) { - opj_mct_decode( l_tile->comps[0].data, - l_tile->comps[1].data, - l_tile->comps[2].data, - l_samples); - } - else { - opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data, - (OPJ_FLOAT32*)l_tile->comps[1].data, - (OPJ_FLOAT32*)l_tile->comps[2].data, - l_samples); - } - } - } - else { - opj_event_msg(p_manager, EVT_ERROR, "Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",l_tile->numcomps); +static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tccp_t * l_tccp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_resolution_t* l_res = 00; + opj_tcd_tile_t * l_tile; + OPJ_UINT32 l_width, l_height, i, j; + OPJ_INT32 * l_current_ptr; + OPJ_INT32 l_min, l_max; + OPJ_UINT32 l_stride; + + l_tile = p_tcd->tcd_image->tiles; + l_tile_comp = l_tile->comps; + l_tccp = p_tcd->tcp->tccps; + l_img_comp = p_tcd->image->comps; + + for (compno = 0; compno < l_tile->numcomps; + compno++, ++l_img_comp, ++l_tccp, ++l_tile_comp) { + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; } - return OPJ_TRUE; -} + l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded; + if (!p_tcd->whole_tile_decoding) { + l_width = l_res->win_x1 - l_res->win_x0; + l_height = l_res->win_y1 - l_res->win_y0; + l_stride = 0; + l_current_ptr = l_tile_comp->data_win; + } else { + l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); + l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); + l_stride = (OPJ_UINT32)( + l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x1 - + l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x0) + - l_width; + l_current_ptr = l_tile_comp->data; + + assert(l_height == 0 || + l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/ + } -static OPJ_BOOL opj_tcd_dc_level_shift_decode ( opj_tcd_t *p_tcd ) -{ - OPJ_UINT32 compno; - opj_tcd_tilecomp_t * l_tile_comp = 00; - opj_tccp_t * l_tccp = 00; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_resolution_t* l_res = 00; - opj_tcd_tile_t * l_tile; - OPJ_UINT32 l_width,l_height,i,j; - OPJ_INT32 * l_current_ptr; - OPJ_INT32 l_min, l_max; - OPJ_UINT32 l_stride; - - l_tile = p_tcd->tcd_image->tiles; - l_tile_comp = l_tile->comps; - l_tccp = p_tcd->tcp->tccps; - l_img_comp = p_tcd->image->comps; - - for (compno = 0; compno < l_tile->numcomps; compno++) { - l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded; - l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); - l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); - l_stride = (OPJ_UINT32)(l_tile_comp->x1 - l_tile_comp->x0) - l_width; - - assert(l_height == 0 || l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/ - - if (l_img_comp->sgnd) { - l_min = -(1 << (l_img_comp->prec - 1)); - l_max = (1 << (l_img_comp->prec - 1)) - 1; - } - else { + if (l_img_comp->sgnd) { + l_min = -(1 << (l_img_comp->prec - 1)); + l_max = (1 << (l_img_comp->prec - 1)) - 1; + } else { l_min = 0; - l_max = (1 << l_img_comp->prec) - 1; - } + l_max = (OPJ_INT32)((1U << l_img_comp->prec) - 1); + } - l_current_ptr = l_tile_comp->data; - if (l_tccp->qmfbid == 1) { - for (j=0;j<l_height;++j) { - for (i = 0; i < l_width; ++i) { - *l_current_ptr = opj_int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min, l_max); - ++l_current_ptr; - } - l_current_ptr += l_stride; - } + if (l_tccp->qmfbid == 1) { + for (j = 0; j < l_height; ++j) { + for (i = 0; i < l_width; ++i) { + /* TODO: do addition on int64 ? */ + *l_current_ptr = opj_int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min, + l_max); + ++l_current_ptr; } - else { - for (j=0;j<l_height;++j) { - for (i = 0; i < l_width; ++i) { - OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr); - *l_current_ptr = opj_int_clamp((OPJ_INT32)opj_lrintf(l_value) + l_tccp->m_dc_level_shift, l_min, l_max); ; - ++l_current_ptr; - } - l_current_ptr += l_stride; - } + l_current_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (i = 0; i < l_width; ++i) { + OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr); + if (l_value > INT_MAX) { + *l_current_ptr = l_max; + } else if (l_value < INT_MIN) { + *l_current_ptr = l_min; + } else { + /* Do addition on int64 to avoid overflows */ + OPJ_INT64 l_value_int = (OPJ_INT64)opj_lrintf(l_value); + *l_current_ptr = (OPJ_INT32)opj_int64_clamp( + l_value_int + l_tccp->m_dc_level_shift, l_min, l_max); + } + ++l_current_ptr; } - - ++l_img_comp; - ++l_tccp; - ++l_tile_comp; + l_current_ptr += l_stride; + } } + } - return OPJ_TRUE; + return OPJ_TRUE; } @@ -1824,415 +2260,550 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode ( opj_tcd_t *p_tcd ) /** * Deallocates the encoding data of the given precinct. */ -static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct) +static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct) { - OPJ_UINT32 cblkno , l_nb_code_blocks; + OPJ_UINT32 cblkno, l_nb_code_blocks; - opj_tcd_cblk_dec_t * l_code_block = p_precinct->cblks.dec; - if (l_code_block) { - /*fprintf(stderr,"deallocate codeblock:{\n");*/ - /*fprintf(stderr,"\t x0=%d, y0=%d, x1=%d, y1=%d\n",l_code_block->x0, l_code_block->y0, l_code_block->x1, l_code_block->y1);*/ - /*fprintf(stderr,"\t numbps=%d, numlenbits=%d, len=%d, numnewpasses=%d, real_num_segs=%d, m_current_max_segs=%d\n ", - l_code_block->numbps, l_code_block->numlenbits, l_code_block->len, l_code_block->numnewpasses, l_code_block->real_num_segs, l_code_block->m_current_max_segs );*/ + opj_tcd_cblk_dec_t * l_code_block = p_precinct->cblks.dec; + if (l_code_block) { + /*fprintf(stderr,"deallocate codeblock:{\n");*/ + /*fprintf(stderr,"\t x0=%d, y0=%d, x1=%d, y1=%d\n",l_code_block->x0, l_code_block->y0, l_code_block->x1, l_code_block->y1);*/ + /*fprintf(stderr,"\t numbps=%d, numlenbits=%d, len=%d, numnewpasses=%d, real_num_segs=%d, m_current_max_segs=%d\n ", + l_code_block->numbps, l_code_block->numlenbits, l_code_block->len, l_code_block->numnewpasses, l_code_block->real_num_segs, l_code_block->m_current_max_segs );*/ - l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_dec_t); - /*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/ + l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof( + opj_tcd_cblk_dec_t); + /*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/ - for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { - if (l_code_block->data) { - opj_free(l_code_block->data); - l_code_block->data = 00; - } + if (l_code_block->segs) { + opj_free(l_code_block->segs); + l_code_block->segs = 00; + } - if (l_code_block->segs) { - opj_free(l_code_block->segs ); - l_code_block->segs = 00; - } + if (l_code_block->chunks) { + opj_free(l_code_block->chunks); + l_code_block->chunks = 00; + } - ++l_code_block; - } + opj_aligned_free(l_code_block->decoded_data); + l_code_block->decoded_data = NULL; - opj_free(p_precinct->cblks.dec); - p_precinct->cblks.dec = 00; + ++l_code_block; } + + opj_free(p_precinct->cblks.dec); + p_precinct->cblks.dec = 00; + } } /** * Deallocates the encoding data of the given precinct. */ -static void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct) -{ - OPJ_UINT32 cblkno , l_nb_code_blocks; - - opj_tcd_cblk_enc_t * l_code_block = p_precinct->cblks.enc; - if (l_code_block) { - l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_enc_t); - - for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { - if (l_code_block->data) { - opj_free(l_code_block->data - 1); - l_code_block->data = 00; - } - - if (l_code_block->layers) { - opj_free(l_code_block->layers ); - l_code_block->layers = 00; - } +static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct) +{ + OPJ_UINT32 cblkno, l_nb_code_blocks; + + opj_tcd_cblk_enc_t * l_code_block = p_precinct->cblks.enc; + if (l_code_block) { + l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof( + opj_tcd_cblk_enc_t); + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + if (l_code_block->data) { + /* We refer to data - 1 since below we incremented it */ + /* in opj_tcd_code_block_enc_allocate_data() */ + opj_free(l_code_block->data - 1); + l_code_block->data = 00; + } + + if (l_code_block->layers) { + opj_free(l_code_block->layers); + l_code_block->layers = 00; + } + + if (l_code_block->passes) { + opj_free(l_code_block->passes); + l_code_block->passes = 00; + } + ++l_code_block; + } - if (l_code_block->passes) { - opj_free(l_code_block->passes ); - l_code_block->passes = 00; - } - ++l_code_block; - } + opj_free(p_precinct->cblks.enc); - opj_free(p_precinct->cblks.enc); - - p_precinct->cblks.enc = 00; - } + p_precinct->cblks.enc = 00; + } } -OPJ_UINT32 opj_tcd_get_encoded_tile_size ( opj_tcd_t *p_tcd ) +OPJ_SIZE_T opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd) { - OPJ_UINT32 i,l_data_size = 0; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_tilecomp_t * l_tilec = 00; - OPJ_UINT32 l_size_comp, l_remaining; - - l_tilec = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; - for (i=0;i<p_tcd->image->numcomps;++i) { - l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ - l_remaining = l_img_comp->prec & 7; /* (%8) */ - - if (l_remaining) { - ++l_size_comp; - } - - if (l_size_comp == 3) { - l_size_comp = 4; - } + OPJ_UINT32 i; + OPJ_SIZE_T l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + OPJ_UINT32 l_size_comp, l_remaining; + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for (i = 0; i < p_tcd->image->numcomps; ++i) { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + + if (l_remaining) { + ++l_size_comp; + } - l_data_size += l_size_comp * (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0)); - ++l_img_comp; - ++l_tilec; + if (l_size_comp == 3) { + l_size_comp = 4; } - return l_data_size; + l_data_size += l_size_comp * ((OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) * + (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0)); + ++l_img_comp; + ++l_tilec; + } + + return l_data_size; } - -static OPJ_BOOL opj_tcd_dc_level_shift_encode ( opj_tcd_t *p_tcd ) -{ - OPJ_UINT32 compno; - opj_tcd_tilecomp_t * l_tile_comp = 00; - opj_tccp_t * l_tccp = 00; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_tile_t * l_tile; - OPJ_UINT32 l_nb_elem,i; - OPJ_INT32 * l_current_ptr; - - l_tile = p_tcd->tcd_image->tiles; - l_tile_comp = l_tile->comps; - l_tccp = p_tcd->tcp->tccps; - l_img_comp = p_tcd->image->comps; - - for (compno = 0; compno < l_tile->numcomps; compno++) { - l_current_ptr = l_tile_comp->data; - l_nb_elem = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0)); - - if (l_tccp->qmfbid == 1) { - for (i = 0; i < l_nb_elem; ++i) { - *l_current_ptr -= l_tccp->m_dc_level_shift ; - ++l_current_ptr; - } - } - else { - for (i = 0; i < l_nb_elem; ++i) { - *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) << 11 ; - ++l_current_ptr; - } - } - ++l_img_comp; - ++l_tccp; - ++l_tile_comp; +static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tccp_t * l_tccp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tile_t * l_tile; + OPJ_SIZE_T l_nb_elem, i; + OPJ_INT32 * l_current_ptr; + + l_tile = p_tcd->tcd_image->tiles; + l_tile_comp = l_tile->comps; + l_tccp = p_tcd->tcp->tccps; + l_img_comp = p_tcd->image->comps; + + for (compno = 0; compno < l_tile->numcomps; compno++) { + l_current_ptr = l_tile_comp->data; + l_nb_elem = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) * + (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0); + + if (l_tccp->qmfbid == 1) { + for (i = 0; i < l_nb_elem; ++i) { + *l_current_ptr -= l_tccp->m_dc_level_shift ; + ++l_current_ptr; + } + } else { + for (i = 0; i < l_nb_elem; ++i) { + *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) * (1 << 11); + ++l_current_ptr; + } } - return OPJ_TRUE; + ++l_img_comp; + ++l_tccp; + ++l_tile_comp; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_mct_encode ( opj_tcd_t *p_tcd ) +static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd) { - opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; - opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; - OPJ_UINT32 samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0)); - OPJ_UINT32 i; - OPJ_BYTE ** l_data = 00; - opj_tcp_t * l_tcp = p_tcd->tcp; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; + OPJ_SIZE_T samples = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) * + (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0); + OPJ_UINT32 i; + OPJ_BYTE ** l_data = 00; + opj_tcp_t * l_tcp = p_tcd->tcp; + + if (!p_tcd->tcp->mct) { + return OPJ_TRUE; + } - if(!p_tcd->tcp->mct) { - return OPJ_TRUE; + if (p_tcd->tcp->mct == 2) { + if (! p_tcd->tcp->m_mct_coding_matrix) { + return OPJ_TRUE; } - if (p_tcd->tcp->mct == 2) { - if (! p_tcd->tcp->m_mct_coding_matrix) { - return OPJ_TRUE; - } - - l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); - if (! l_data) { - return OPJ_FALSE; - } + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps * sizeof(OPJ_BYTE*)); + if (! l_data) { + return OPJ_FALSE; + } - for (i=0;i<l_tile->numcomps;++i) { - l_data[i] = (OPJ_BYTE*) l_tile_comp->data; - ++l_tile_comp; - } + for (i = 0; i < l_tile->numcomps; ++i) { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + ++l_tile_comp; + } - if (! opj_mct_encode_custom(/* MCT data */ - (OPJ_BYTE*) p_tcd->tcp->m_mct_coding_matrix, - /* size of components */ - samples, - /* components */ - l_data, - /* nb of components (i.e. size of pData) */ - l_tile->numcomps, - /* tells if the data is signed */ - p_tcd->image->comps->sgnd) ) - { + if (! opj_mct_encode_custom(/* MCT data */ + (OPJ_BYTE*) p_tcd->tcp->m_mct_coding_matrix, + /* size of components */ + samples, + /* components */ + l_data, + /* nb of components (i.e. size of pData) */ + l_tile->numcomps, + /* tells if the data is signed */ + p_tcd->image->comps->sgnd)) { opj_free(l_data); - return OPJ_FALSE; - } - - opj_free(l_data); - } - else if (l_tcp->tccps->qmfbid == 0) { - opj_mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); - } - else { - opj_mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); + return OPJ_FALSE; } - return OPJ_TRUE; + opj_free(l_data); + } else if (l_tcp->tccps->qmfbid == 0) { + opj_mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data, + l_tile->comps[2].data, samples); + } else { + opj_mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, + l_tile->comps[2].data, samples); + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_dwt_encode ( opj_tcd_t *p_tcd ) +static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd) { - opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; - opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; - opj_tccp_t * l_tccp = p_tcd->tcp->tccps; - OPJ_UINT32 compno; - - for (compno = 0; compno < l_tile->numcomps; ++compno) { - if (l_tccp->qmfbid == 1) { - if (! opj_dwt_encode(l_tile_comp)) { - return OPJ_FALSE; - } - } - else if (l_tccp->qmfbid == 0) { - if (! opj_dwt_encode_real(l_tile_comp)) { - return OPJ_FALSE; - } - } - - ++l_tile_comp; - ++l_tccp; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + OPJ_UINT32 compno; + + for (compno = 0; compno < l_tile->numcomps; ++compno) { + if (l_tccp->qmfbid == 1) { + if (! opj_dwt_encode(l_tile_comp)) { + return OPJ_FALSE; + } + } else if (l_tccp->qmfbid == 0) { + if (! opj_dwt_encode_real(l_tile_comp)) { + return OPJ_FALSE; + } } - return OPJ_TRUE; + ++l_tile_comp; + ++l_tccp; + } + + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd ) +static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd) { - opj_t1_t * l_t1; - const OPJ_FLOAT64 * l_mct_norms; - OPJ_UINT32 l_mct_numcomps = 0U; - opj_tcp_t * l_tcp = p_tcd->tcp; - - l_t1 = opj_t1_create(OPJ_TRUE); - if (l_t1 == 00) { - return OPJ_FALSE; - } - - if (l_tcp->mct == 1) { - l_mct_numcomps = 3U; - /* irreversible encoding */ - if (l_tcp->tccps->qmfbid == 0) { - l_mct_norms = opj_mct_get_mct_norms_real(); - } - else { - l_mct_norms = opj_mct_get_mct_norms(); - } - } - else { - l_mct_numcomps = p_tcd->image->numcomps; - l_mct_norms = (const OPJ_FLOAT64 *) (l_tcp->mct_norms); + opj_t1_t * l_t1; + const OPJ_FLOAT64 * l_mct_norms; + OPJ_UINT32 l_mct_numcomps = 0U; + opj_tcp_t * l_tcp = p_tcd->tcp; + + l_t1 = opj_t1_create(OPJ_TRUE); + if (l_t1 == 00) { + return OPJ_FALSE; + } + + if (l_tcp->mct == 1) { + l_mct_numcomps = 3U; + /* irreversible encoding */ + if (l_tcp->tccps->qmfbid == 0) { + l_mct_norms = opj_mct_get_mct_norms_real(); + } else { + l_mct_norms = opj_mct_get_mct_norms(); } + } else { + l_mct_numcomps = p_tcd->image->numcomps; + l_mct_norms = (const OPJ_FLOAT64 *)(l_tcp->mct_norms); + } - if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms, l_mct_numcomps)) { + if (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles, l_tcp, l_mct_norms, + l_mct_numcomps)) { opj_t1_destroy(l_t1); - return OPJ_FALSE; - } + return OPJ_FALSE; + } - opj_t1_destroy(l_t1); + opj_t1_destroy(l_t1); - return OPJ_TRUE; + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_t2_encode (opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info ) +static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager) { - opj_t2_t * l_t2; - - l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp); - if (l_t2 == 00) { - return OPJ_FALSE; - } - - if (! opj_t2_encode_packets( - l_t2, - p_tcd->tcd_tileno, - p_tcd->tcd_image->tiles, - p_tcd->tcp->numlayers, - p_dest_data, - p_data_written, - p_max_dest_size, - p_cstr_info, - p_tcd->tp_num, - p_tcd->tp_pos, - p_tcd->cur_pino, - FINAL_PASS)) - { - opj_t2_destroy(l_t2); - return OPJ_FALSE; - } - + opj_t2_t * l_t2; + + l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp); + if (l_t2 == 00) { + return OPJ_FALSE; + } + + if (! opj_t2_encode_packets( + l_t2, + p_tcd->tcd_tileno, + p_tcd->tcd_image->tiles, + p_tcd->tcp->numlayers, + p_dest_data, + p_data_written, + p_max_dest_size, + p_cstr_info, + p_tcd->tp_num, + p_tcd->tp_pos, + p_tcd->cur_pino, + FINAL_PASS, + p_manager)) { opj_t2_destroy(l_t2); + return OPJ_FALSE; + } - /*---------------CLEAN-------------------*/ - return OPJ_TRUE; + opj_t2_destroy(l_t2); + + /*---------------CLEAN-------------------*/ + return OPJ_TRUE; } -static OPJ_BOOL opj_tcd_rate_allocate_encode( opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest_data, - OPJ_UINT32 p_max_dest_size, - opj_codestream_info_t *p_cstr_info ) +static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager) { - opj_cp_t * l_cp = p_tcd->cp; - OPJ_UINT32 l_nb_written = 0; - - if (p_cstr_info) { - p_cstr_info->index_write = 0; - } - - if (l_cp->m_specific_param.m_enc.m_disto_alloc|| l_cp->m_specific_param.m_enc.m_fixed_quality) { - /* fixed_quality */ - /* Normal Rate/distortion allocation */ - if (! opj_tcd_rateallocate(p_tcd, p_dest_data,&l_nb_written, p_max_dest_size, p_cstr_info)) { - return OPJ_FALSE; - } - } - else { - /* Fixed layer allocation */ - opj_tcd_rateallocate_fixed(p_tcd); + opj_cp_t * l_cp = p_tcd->cp; + OPJ_UINT32 l_nb_written = 0; + + if (p_cstr_info) { + p_cstr_info->index_write = 0; + } + + if (l_cp->m_specific_param.m_enc.m_disto_alloc || + l_cp->m_specific_param.m_enc.m_fixed_quality) { + /* fixed_quality */ + /* Normal Rate/distortion allocation */ + if (! opj_tcd_rateallocate(p_tcd, p_dest_data, &l_nb_written, p_max_dest_size, + p_cstr_info, p_manager)) { + return OPJ_FALSE; } + } else { + /* Fixed layer allocation */ + opj_tcd_rateallocate_fixed(p_tcd); + } - return OPJ_TRUE; + return OPJ_TRUE; } -OPJ_BOOL opj_tcd_copy_tile_data ( opj_tcd_t *p_tcd, - OPJ_BYTE * p_src, - OPJ_UINT32 p_src_length ) +OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src, + OPJ_SIZE_T p_src_length) { - OPJ_UINT32 i,j,l_data_size = 0; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_tilecomp_t * l_tilec = 00; - OPJ_UINT32 l_size_comp, l_remaining; - OPJ_UINT32 l_nb_elem; - - l_data_size = opj_tcd_get_encoded_tile_size(p_tcd); - if (l_data_size != p_src_length) { - return OPJ_FALSE; + OPJ_UINT32 i; + OPJ_SIZE_T j; + OPJ_SIZE_T l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_SIZE_T l_nb_elem; + + l_data_size = opj_tcd_get_encoded_tile_size(p_tcd); + if (l_data_size != p_src_length) { + return OPJ_FALSE; + } + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for (i = 0; i < p_tcd->image->numcomps; ++i) { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_nb_elem = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) * + (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); + + if (l_remaining) { + ++l_size_comp; } - l_tilec = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; - for (i=0;i<p_tcd->image->numcomps;++i) { - l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ - l_remaining = l_img_comp->prec & 7; /* (%8) */ - l_nb_elem = (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0)); + if (l_size_comp == 3) { + l_size_comp = 4; + } - if (l_remaining) { - ++l_size_comp; - } + switch (l_size_comp) { + case 1: { + OPJ_CHAR * l_src_ptr = (OPJ_CHAR *) p_src; + OPJ_INT32 * l_dest_ptr = l_tilec->data; - if (l_size_comp == 3) { - l_size_comp = 4; + if (l_img_comp->sgnd) { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (OPJ_INT32)(*(l_src_ptr++)); } + } else { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (*(l_src_ptr++)) & 0xff; + } + } - switch (l_size_comp) { - case 1: - { - OPJ_CHAR * l_src_ptr = (OPJ_CHAR *) p_src; - OPJ_INT32 * l_dest_ptr = l_tilec->data; - - if (l_img_comp->sgnd) { - for (j=0;j<l_nb_elem;++j) { - *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++)); - } - } - else { - for (j=0;j<l_nb_elem;++j) { - *(l_dest_ptr++) = (*(l_src_ptr++))&0xff; - } - } - - p_src = (OPJ_BYTE*) l_src_ptr; - } - break; - case 2: - { - OPJ_INT32 * l_dest_ptr = l_tilec->data; - OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src; - - if (l_img_comp->sgnd) { - for (j=0;j<l_nb_elem;++j) { - *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++)); - } - } - else { - for (j=0;j<l_nb_elem;++j) { - *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff; - } - } - - p_src = (OPJ_BYTE*) l_src_ptr; - } - break; - case 4: - { - OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_src; - OPJ_INT32 * l_dest_ptr = l_tilec->data; + p_src = (OPJ_BYTE*) l_src_ptr; + } + break; + case 2: { + OPJ_INT32 * l_dest_ptr = l_tilec->data; + OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (OPJ_INT32)(*(l_src_ptr++)); + } + } else { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (*(l_src_ptr++)) & 0xffff; + } + } - for (j=0;j<l_nb_elem;++j) { - *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++)); - } + p_src = (OPJ_BYTE*) l_src_ptr; + } + break; + case 4: { + OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_src; + OPJ_INT32 * l_dest_ptr = l_tilec->data; - p_src = (OPJ_BYTE*) l_src_ptr; - } - break; - } + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (OPJ_INT32)(*(l_src_ptr++)); + } - ++l_img_comp; - ++l_tilec; + p_src = (OPJ_BYTE*) l_src_ptr; + } + break; } - return OPJ_TRUE; + ++l_img_comp; + ++l_tilec; + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band) +{ + return (band->x1 - band->x0 == 0) || (band->y1 - band->y0 == 0); +} + +OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd, + OPJ_UINT32 compno, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 band_x0, + OPJ_UINT32 band_y0, + OPJ_UINT32 band_x1, + OPJ_UINT32 band_y1) +{ + /* Note: those values for filter_margin are in part the result of */ + /* experimentation. The value 2 for QMFBID=1 (5x3 filter) can be linked */ + /* to the maximum left/right extension given in tables F.2 and F.3 of the */ + /* standard. The value 3 for QMFBID=0 (9x7 filter) is more suspicious, */ + /* since F.2 and F.3 would lead to 4 instead, so the current 3 might be */ + /* needed to be bumped to 4, in case inconsistencies are found while */ + /* decoding parts of irreversible coded images. */ + /* See opj_dwt_decode_partial_53 and opj_dwt_decode_partial_97 as well */ + OPJ_UINT32 filter_margin = (tcd->tcp->tccps[compno].qmfbid == 1) ? 2 : 3; + opj_tcd_tilecomp_t *tilec = &(tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(tcd->image->comps[compno]); + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 tcx0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(tcd->win_x0, image_comp->dx)); + OPJ_UINT32 tcy0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(tcd->win_y0, image_comp->dy)); + OPJ_UINT32 tcx1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(tcd->win_x1, image_comp->dx)); + OPJ_UINT32 tcy1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(tcd->win_y1, image_comp->dy)); + /* Compute number of decomposition for this band. See table F-1 */ + OPJ_UINT32 nb = (resno == 0) ? + tilec->numresolutions - 1 : + tilec->numresolutions - resno; + /* Map above tile-based coordinates to sub-band-based coordinates per */ + /* equation B-15 of the standard */ + OPJ_UINT32 x0b = bandno & 1; + OPJ_UINT32 y0b = bandno >> 1; + OPJ_UINT32 tbx0 = (nb == 0) ? tcx0 : + (tcx0 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx0 - (1U << (nb - 1)) * x0b, nb); + OPJ_UINT32 tby0 = (nb == 0) ? tcy0 : + (tcy0 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy0 - (1U << (nb - 1)) * y0b, nb); + OPJ_UINT32 tbx1 = (nb == 0) ? tcx1 : + (tcx1 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx1 - (1U << (nb - 1)) * x0b, nb); + OPJ_UINT32 tby1 = (nb == 0) ? tcy1 : + (tcy1 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy1 - (1U << (nb - 1)) * y0b, nb); + OPJ_BOOL intersects; + + if (tbx0 < filter_margin) { + tbx0 = 0; + } else { + tbx0 -= filter_margin; + } + if (tby0 < filter_margin) { + tby0 = 0; + } else { + tby0 -= filter_margin; + } + tbx1 = opj_uint_adds(tbx1, filter_margin); + tby1 = opj_uint_adds(tby1, filter_margin); + + intersects = band_x0 < tbx1 && band_y0 < tby1 && band_x1 > tbx0 && + band_y1 > tby0; + +#ifdef DEBUG_VERBOSE + printf("compno=%u resno=%u nb=%u bandno=%u x0b=%u y0b=%u band=%u,%u,%u,%u tb=%u,%u,%u,%u -> %u\n", + compno, resno, nb, bandno, x0b, y0b, + band_x0, band_y0, band_x1, band_y1, + tbx0, tby0, tbx1, tby1, intersects); +#endif + return intersects; +} + +/** Returns whether a tile componenent is fully decoded, taking into account + * p_tcd->win_* members. + * + * @param p_tcd TCD handle. + * @param compno Component number + * @return OPJ_TRUE whether the tile componenent is fully decoded + */ +static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *p_tcd, + OPJ_UINT32 compno) +{ + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 tcx0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx)); + OPJ_UINT32 tcy0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy)); + OPJ_UINT32 tcx1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx)); + OPJ_UINT32 tcy1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy)); + + OPJ_UINT32 shift = tilec->numresolutions - tilec->minimum_num_resolutions; + /* Tolerate small margin within the reduced resolution factor to consider if */ + /* the whole tile path must be taken */ + return (tcx0 >= (OPJ_UINT32)tilec->x0 && + tcy0 >= (OPJ_UINT32)tilec->y0 && + tcx1 <= (OPJ_UINT32)tilec->x1 && + tcy1 <= (OPJ_UINT32)tilec->y1 && + (shift >= 32 || + (((tcx0 - (OPJ_UINT32)tilec->x0) >> shift) == 0 && + ((tcy0 - (OPJ_UINT32)tilec->y0) >> shift) == 0 && + (((OPJ_UINT32)tilec->x1 - tcx1) >> shift) == 0 && + (((OPJ_UINT32)tilec->y1 - tcy1) >> shift) == 0))); } diff --git a/third_party/libopenjpeg20/tcd.h b/third_party/libopenjpeg20/tcd.h index 07f8379afd48cf307051fe2f7cb2fb0ac282d849..e3214c1d982ad9b4ce57d17d007d6bd562883fe2 100644 --- a/third_party/libopenjpeg20/tcd.h +++ b/third_party/libopenjpeg20/tcd.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,11 +8,12 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA <support@intopix.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,8 +37,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __TCD_H -#define __TCD_H +#ifndef OPJ_TCD_H +#define OPJ_TCD_H /** @file tcd.h @brief Implementation of a tile coder/decoder (TCD) @@ -49,124 +50,175 @@ each other. The functions in TCD.C are used by other functions in J2K.C. /** @defgroup TCD TCD - Implementation of a tile coder/decoder */ /*@{*/ -/** -FIXME DOC -*/ -typedef struct opj_tcd_seg { - OPJ_BYTE ** data; - OPJ_UINT32 dataindex; - OPJ_UINT32 numpasses; - OPJ_UINT32 real_num_passes; - OPJ_UINT32 len; - OPJ_UINT32 maxpasses; - OPJ_UINT32 numnewpasses; - OPJ_UINT32 newlen; -} opj_tcd_seg_t; /** FIXME DOC */ typedef struct opj_tcd_pass { - OPJ_UINT32 rate; - OPJ_FLOAT64 distortiondec; - OPJ_UINT32 len; - OPJ_UINT32 term : 1; + OPJ_UINT32 rate; + OPJ_FLOAT64 distortiondec; + OPJ_UINT32 len; + OPJ_BITFIELD term : 1; } opj_tcd_pass_t; /** FIXME DOC */ typedef struct opj_tcd_layer { - OPJ_UINT32 numpasses; /* Number of passes in the layer */ - OPJ_UINT32 len; /* len of information */ - OPJ_FLOAT64 disto; /* add for index (Cfr. Marcela) */ - OPJ_BYTE *data; /* data */ + OPJ_UINT32 numpasses; /* Number of passes in the layer */ + OPJ_UINT32 len; /* len of information */ + OPJ_FLOAT64 disto; /* add for index (Cfr. Marcela) */ + OPJ_BYTE *data; /* data */ } opj_tcd_layer_t; /** FIXME DOC */ typedef struct opj_tcd_cblk_enc { - OPJ_BYTE* data; /* Data */ - opj_tcd_layer_t* layers; /* layer information */ - opj_tcd_pass_t* passes; /* information about the passes */ - OPJ_INT32 x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 numbps; - OPJ_UINT32 numlenbits; - OPJ_UINT32 data_size; /* Size of allocated data buffer */ - OPJ_UINT32 numpasses; /* number of pass already done for the code-blocks */ - OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */ - OPJ_UINT32 totalpasses; /* total number of passes */ + OPJ_BYTE* data; /* Data */ + opj_tcd_layer_t* layers; /* layer information */ + opj_tcd_pass_t* passes; /* information about the passes */ + OPJ_INT32 x0, y0, x1, + y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 numbps; + OPJ_UINT32 numlenbits; + OPJ_UINT32 data_size; /* Size of allocated data buffer */ + OPJ_UINT32 + numpasses; /* number of pass already done for the code-blocks */ + OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */ + OPJ_UINT32 totalpasses; /* total number of passes */ } opj_tcd_cblk_enc_t; +/** Chunk of codestream data that is part of a code block */ +typedef struct opj_tcd_seg_data_chunk { + /* Point to tilepart buffer. We don't make a copy ! + So the tilepart buffer must be kept alive + as long as we need to decode the codeblocks */ + OPJ_BYTE * data; + OPJ_UINT32 len; /* Usable length of data */ +} opj_tcd_seg_data_chunk_t; + +/** Segment of a code-block. + * A segment represent a number of consecutive coding passes, without termination + * of MQC or RAW between them. */ +typedef struct opj_tcd_seg { + OPJ_UINT32 len; /* Size of data related to this segment */ + /* Number of passes decoded. Including those that we skip */ + OPJ_UINT32 numpasses; + /* Number of passes actually to be decoded. To be used for code-block decoding */ + OPJ_UINT32 real_num_passes; + /* Maximum number of passes for this segment */ + OPJ_UINT32 maxpasses; + /* Number of new passes for current packed. Transitory value */ + OPJ_UINT32 numnewpasses; + /* Codestream length for this segment for current packed. Transitory value */ + OPJ_UINT32 newlen; +} opj_tcd_seg_t; + +/** Code-block for decoding */ typedef struct opj_tcd_cblk_dec { - OPJ_BYTE * data; /* Data */ - opj_tcd_seg_t* segs; /* segments information */ - OPJ_INT32 x0, y0, x1, y1; /* position of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 numbps; - OPJ_UINT32 numlenbits; - OPJ_UINT32 data_max_size; /* Size of allocated data buffer */ - OPJ_UINT32 data_current_size; /* Size of used data buffer */ - OPJ_UINT32 numnewpasses; /* number of pass added to the code-blocks */ - OPJ_UINT32 numsegs; /* number of segments */ - OPJ_UINT32 real_num_segs; - OPJ_UINT32 m_current_max_segs; + opj_tcd_seg_t* segs; /* segments information */ + opj_tcd_seg_data_chunk_t* chunks; /* Array of chunks */ + /* position of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + OPJ_UINT32 numbps; + /* number of bits for len, for the current packet. Transitory value */ + OPJ_UINT32 numlenbits; + /* number of pass added to the code-blocks, for the current packet. Transitory value */ + OPJ_UINT32 numnewpasses; + /* number of segments, including those of packet we skip */ + OPJ_UINT32 numsegs; + /* number of segments, to be used for code block decoding */ + OPJ_UINT32 real_num_segs; + OPJ_UINT32 m_current_max_segs; /* allocated number of segs[] items */ + OPJ_UINT32 numchunks; /* Number of valid chunks items */ + OPJ_UINT32 numchunksalloc; /* Number of chunks item allocated */ + /* Decoded code-block. Only used for subtile decoding. Otherwise tilec->data is directly updated */ + OPJ_INT32* decoded_data; } opj_tcd_cblk_dec_t; -/** -FIXME DOC -*/ +/** Precinct structure */ typedef struct opj_tcd_precinct { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 cw, ch; /* number of precinct in width and height */ - union{ /* code-blocks information */ - opj_tcd_cblk_enc_t* enc; - opj_tcd_cblk_dec_t* dec; - void* blocks; - } cblks; - OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */ - opj_tgt_tree_t *incltree; /* inclusion tree */ - opj_tgt_tree_t *imsbtree; /* IMSB tree */ + /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + OPJ_UINT32 cw, ch; /* number of code-blocks, in width and height */ + union { /* code-blocks information */ + opj_tcd_cblk_enc_t* enc; + opj_tcd_cblk_dec_t* dec; + void* blocks; + } cblks; + OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */ + opj_tgt_tree_t *incltree; /* inclusion tree */ + opj_tgt_tree_t *imsbtree; /* IMSB tree */ } opj_tcd_precinct_t; -/** -FIXME DOC -*/ +/** Sub-band structure */ typedef struct opj_tcd_band { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 bandno; - opj_tcd_precinct_t *precincts; /* precinct information */ - OPJ_UINT32 precincts_data_size; /* size of data taken by precincts */ - OPJ_INT32 numbps; - OPJ_FLOAT32 stepsize; + /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* band number: for lowest resolution level (0=LL), otherwise (1=HL, 2=LH, 3=HH) */ + OPJ_UINT32 bandno; + /* precinct information */ + opj_tcd_precinct_t *precincts; + /* size of data taken by precincts */ + OPJ_UINT32 precincts_data_size; + OPJ_INT32 numbps; + OPJ_FLOAT32 stepsize; } opj_tcd_band_t; -/** -FIXME DOC -*/ +/** Tile-component resolution structure */ typedef struct opj_tcd_resolution { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 pw, ph; - OPJ_UINT32 numbands; /* number sub-band for the resolution level */ - opj_tcd_band_t bands[3]; /* subband information */ + /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* number of precincts, in width and height, for this resolution level */ + OPJ_UINT32 pw, ph; + /* number of sub-bands for the resolution level (1 for lowest resolution level, 3 otherwise) */ + OPJ_UINT32 numbands; + /* subband information */ + opj_tcd_band_t bands[3]; + + /* dimension of the resolution limited to window of interest. Only valid if tcd->whole_tile_decoding is set */ + OPJ_UINT32 win_x0; + OPJ_UINT32 win_y0; + OPJ_UINT32 win_x1; + OPJ_UINT32 win_y1; } opj_tcd_resolution_t; -/** -FIXME DOC -*/ -typedef struct opj_tcd_tilecomp -{ - OPJ_INT32 x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 numresolutions; /* number of resolutions level */ - OPJ_UINT32 minimum_num_resolutions; /* number of resolutions level to decode (at max)*/ - opj_tcd_resolution_t *resolutions; /* resolutions information */ - OPJ_UINT32 resolutions_size; /* size of data for resolutions (in bytes) */ - OPJ_INT32 *data; /* data of the component */ - OPJ_BOOL ownsData; /* if true, then need to free after usage, otherwise do not free */ - OPJ_UINT32 data_size_needed; /* we may either need to allocate this amount of data, or re-use image data and ignore this value */ - OPJ_UINT32 data_size; /* size of the data of the component */ - OPJ_INT32 numpix; /* add fixed_quality */ +/** Tile-component structure */ +typedef struct opj_tcd_tilecomp { + /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* component number */ + OPJ_UINT32 compno; + /* number of resolutions level */ + OPJ_UINT32 numresolutions; + /* number of resolutions level to decode (at max)*/ + OPJ_UINT32 minimum_num_resolutions; + /* resolutions information */ + opj_tcd_resolution_t *resolutions; + /* size of data for resolutions (in bytes) */ + OPJ_UINT32 resolutions_size; + + /* data of the component. For decoding, only valid if tcd->whole_tile_decoding is set (so exclusive of data_win member) */ + OPJ_INT32 *data; + /* if true, then need to free after usage, otherwise do not free */ + OPJ_BOOL ownsData; + /* we may either need to allocate this amount of data, or re-use image data and ignore this value */ + size_t data_size_needed; + /* size of the data of the component */ + size_t data_size; + + /** data of the component limited to window of interest. Only valid for decoding and if tcd->whole_tile_decoding is NOT set (so exclusive of data member) */ + OPJ_INT32 *data_win; + /* dimension of the component limited to window of interest. Only valid for decoding and if tcd->whole_tile_decoding is NOT set */ + OPJ_UINT32 win_x0; + OPJ_UINT32 win_y0; + OPJ_UINT32 win_x1; + OPJ_UINT32 win_y1; + + /* add fixed_quality */ + OPJ_INT32 numpix; } opj_tcd_tilecomp_t; @@ -174,21 +226,21 @@ typedef struct opj_tcd_tilecomp FIXME DOC */ typedef struct opj_tcd_tile { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 numcomps; /* number of components in tile */ - opj_tcd_tilecomp_t *comps; /* Components information */ - OPJ_INT32 numpix; /* add fixed_quality */ - OPJ_FLOAT64 distotile; /* add fixed_quality */ - OPJ_FLOAT64 distolayer[100]; /* add fixed_quality */ - OPJ_UINT32 packno; /* packet number */ + /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + OPJ_UINT32 numcomps; /* number of components in tile */ + opj_tcd_tilecomp_t *comps; /* Components information */ + OPJ_INT32 numpix; /* add fixed_quality */ + OPJ_FLOAT64 distotile; /* add fixed_quality */ + OPJ_FLOAT64 distolayer[100]; /* add fixed_quality */ + OPJ_UINT32 packno; /* packet number */ } opj_tcd_tile_t; /** FIXME DOC */ -typedef struct opj_tcd_image -{ - opj_tcd_tile_t *tiles; /* Tiles information */ +typedef struct opj_tcd_image { + opj_tcd_tile_t *tiles; /* Tiles information */ } opj_tcd_image_t; @@ -196,30 +248,40 @@ opj_tcd_image_t; /** Tile coder/decoder */ -typedef struct opj_tcd -{ - /** Position of the tilepart flag in Progression order*/ - OPJ_INT32 tp_pos; - /** Tile part number*/ - OPJ_UINT32 tp_num; - /** Current tile part number*/ - OPJ_UINT32 cur_tp_num; - /** Total number of tileparts of the current tile*/ - OPJ_UINT32 cur_totnum_tp; - /** Current Packet iterator number */ - OPJ_UINT32 cur_pino; - /** info on each image tile */ - opj_tcd_image_t *tcd_image; - /** image header */ - opj_image_t *image; - /** coding parameters */ - opj_cp_t *cp; - /** coding/decoding parameters common to all tiles */ - opj_tcp_t *tcp; - /** current encoded/decoded tile */ - OPJ_UINT32 tcd_tileno; - /** tell if the tcd is a decoder. */ - OPJ_UINT32 m_is_decoder : 1; +typedef struct opj_tcd { + /** Position of the tilepart flag in Progression order*/ + OPJ_INT32 tp_pos; + /** Tile part number*/ + OPJ_UINT32 tp_num; + /** Current tile part number*/ + OPJ_UINT32 cur_tp_num; + /** Total number of tileparts of the current tile*/ + OPJ_UINT32 cur_totnum_tp; + /** Current Packet iterator number */ + OPJ_UINT32 cur_pino; + /** info on each image tile */ + opj_tcd_image_t *tcd_image; + /** image header */ + opj_image_t *image; + /** coding parameters */ + opj_cp_t *cp; + /** coding/decoding parameters common to all tiles */ + opj_tcp_t *tcp; + /** current encoded/decoded tile */ + OPJ_UINT32 tcd_tileno; + /** tell if the tcd is a decoder. */ + OPJ_BITFIELD m_is_decoder : 1; + /** Thread pool */ + opj_thread_pool_t* thread_pool; + /** Coordinates of the window of interest, in grid reference space */ + OPJ_UINT32 win_x0; + OPJ_UINT32 win_y0; + OPJ_UINT32 win_x1; + OPJ_UINT32 win_y1; + /** Only valid for decoding. Whether the whole tile is decoded, or just the region in win_x0/win_y0/win_x1/win_y1 */ + OPJ_BOOL whole_tile_decoding; + /* Array of size image->numcomps indicating if a component must be decoded. NULL if all components must be decoded */ + OPJ_BOOL* used_component; } opj_tcd_t; /** @name Exported functions */ @@ -229,7 +291,7 @@ typedef struct opj_tcd /** Dump the content of a tcd structure */ -/*void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);*/ /* TODO MSD shoul use the new v2 structures */ +/*void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);*/ /* TODO MSD shoul use the new v2 structures */ /** Create a new TCD handle @@ -246,113 +308,135 @@ void opj_tcd_destroy(opj_tcd_t *tcd); /** * Initialize the tile coder and may reuse some memory. - * @param p_tcd TCD handle. - * @param p_image raw image. - * @param p_cp coding parameters. + * @param p_tcd TCD handle. + * @param p_image raw image. + * @param p_cp coding parameters. + * @param p_tp thread pool * * @return true if the encoding values could be set (false otherwise). */ -OPJ_BOOL opj_tcd_init( opj_tcd_t *p_tcd, - opj_image_t * p_image, - opj_cp_t * p_cp ); +OPJ_BOOL opj_tcd_init(opj_tcd_t *p_tcd, + opj_image_t * p_image, + opj_cp_t * p_cp, + opj_thread_pool_t* p_tp); /** * Allocates memory for decoding a specific tile. * - * @param p_tcd the tile decoder. - * @param p_tile_no the index of the tile received in sequence. This not necessarily lead to the + * @param p_tcd the tile decoder. + * @param p_tile_no the index of the tile received in sequence. This not necessarily lead to the * tile at index p_tile_no. * @param p_manager the event manager. * - * @return true if the remaining data is sufficient. + * @return true if the remaining data is sufficient. */ -OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager); +OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + opj_event_mgr_t* p_manager); -void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final); +void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, + OPJ_UINT32 final); void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd); -void opj_tcd_makelayer( opj_tcd_t *tcd, - OPJ_UINT32 layno, - OPJ_FLOAT64 thresh, - OPJ_UINT32 final); +void opj_tcd_makelayer(opj_tcd_t *tcd, + OPJ_UINT32 layno, + OPJ_FLOAT64 thresh, + OPJ_UINT32 final); -OPJ_BOOL opj_tcd_rateallocate( opj_tcd_t *tcd, - OPJ_BYTE *dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 len, - opj_codestream_info_t *cstr_info); +OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + opj_event_mgr_t *p_manager); /** * Gets the maximum tile size that will be taken by the tile once decoded. */ -OPJ_UINT32 opj_tcd_get_decoded_tile_size (opj_tcd_t *p_tcd ); +OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd, + OPJ_BOOL take_into_account_partial_decoding); /** * Encodes a tile from the raw image into the given buffer. - * @param p_tcd Tile Coder handle - * @param p_tile_no Index of the tile to encode. - * @param p_dest Destination buffer - * @param p_data_written pointer to an int that is incremented by the number of bytes really written on p_dest - * @param p_len Maximum length of the destination buffer - * @param p_cstr_info Codestream information structure + * @param p_tcd Tile Coder handle + * @param p_tile_no Index of the tile to encode. + * @param p_dest Destination buffer + * @param p_data_written pointer to an int that is incremented by the number of bytes really written on p_dest + * @param p_len Maximum length of the destination buffer + * @param p_cstr_info Codestream information structure + * @param p_manager the user event manager * @return true if the coding is successful. */ -OPJ_BOOL opj_tcd_encode_tile( opj_tcd_t *p_tcd, - OPJ_UINT32 p_tile_no, - OPJ_BYTE *p_dest, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_len, - struct opj_codestream_info *p_cstr_info); +OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_len, + struct opj_codestream_info *p_cstr_info, + opj_event_mgr_t *p_manager); /** Decode a tile from a buffer into a raw image @param tcd TCD handle +@param win_x0 Upper left x of region to decode (in grid coordinates) +@param win_y0 Upper left y of region to decode (in grid coordinates) +@param win_x1 Lower right x of region to decode (in grid coordinates) +@param win_y1 Lower right y of region to decode (in grid coordinates) +@param numcomps_to_decode Size of the comps_indices array, or 0 if decoding all components. +@param comps_indices Array of numcomps values representing the indices + of the components to decode (relative to the + codestream, starting at 0). Or NULL if decoding all components. @param src Source buffer @param len Length of source buffer @param tileno Number that identifies one of the tiles to be decoded @param cstr_info FIXME DOC @param manager the event manager. */ -OPJ_BOOL opj_tcd_decode_tile( opj_tcd_t *tcd, - OPJ_BYTE *src, - OPJ_UINT32 len, - OPJ_UINT32 tileno, - opj_codestream_index_t *cstr_info, - opj_event_mgr_t *manager); +OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *tcd, + OPJ_UINT32 win_x0, + OPJ_UINT32 win_y0, + OPJ_UINT32 win_x1, + OPJ_UINT32 win_y1, + OPJ_UINT32 numcomps_to_decode, + const OPJ_UINT32 *comps_indices, + OPJ_BYTE *src, + OPJ_UINT32 len, + OPJ_UINT32 tileno, + opj_codestream_index_t *cstr_info, + opj_event_mgr_t *manager); /** * Copies tile data from the system onto the given memory block. */ -OPJ_BOOL opj_tcd_update_tile_data ( opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest, - OPJ_UINT32 p_dest_length ); +OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest, + OPJ_UINT32 p_dest_length); /** * */ -OPJ_UINT32 opj_tcd_get_encoded_tile_size ( opj_tcd_t *p_tcd ); +OPJ_SIZE_T opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd); /** * Initialize the tile coder and may reuse some meory. * - * @param p_tcd TCD handle. - * @param p_tile_no current tile index to encode. + * @param p_tcd TCD handle. + * @param p_tile_no current tile index to encode. * @param p_manager the event manager. * * @return true if the encoding values could be set (false otherwise). */ -OPJ_BOOL opj_tcd_init_encode_tile ( opj_tcd_t *p_tcd, - OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager ); +OPJ_BOOL opj_tcd_init_encode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager); /** * Copies tile data from the given memory block onto the system. */ -OPJ_BOOL opj_tcd_copy_tile_data (opj_tcd_t *p_tcd, - OPJ_BYTE * p_src, - OPJ_UINT32 p_src_length ); +OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src, + OPJ_SIZE_T p_src_length); /** * Allocates tile component data @@ -361,9 +445,42 @@ OPJ_BOOL opj_tcd_copy_tile_data (opj_tcd_t *p_tcd, */ OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec); +/** Returns whether a sub-band is empty (i.e. whether it has a null area) + * @param band Sub-band handle. + * @return OPJ_TRUE whether the sub-band is empty. + */ +OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band); + +/** Reinitialize a segment */ +void opj_tcd_reinit_segment(opj_tcd_seg_t* seg); + + +/** Returns whether a sub-band region contributes to the area of interest + * tcd->win_x0,tcd->win_y0,tcd->win_x1,tcd->win_y1. + * + * @param tcd TCD handle. + * @param compno Component number + * @param resno Resolution number + * @param bandno Band number (*not* band index, ie 0, 1, 2 or 3) + * @param x0 Upper left x in subband coordinates + * @param y0 Upper left y in subband coordinates + * @param x1 Lower right x in subband coordinates + * @param y1 Lower right y in subband coordinates + * @return OPJ_TRUE whether the sub-band region contributs to the area of + * interest. + */ +OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd, + OPJ_UINT32 compno, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1); + /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ -#endif /* __TCD_H */ +#endif /* OPJ_TCD_H */ diff --git a/third_party/libopenjpeg20/tgt.c b/third_party/libopenjpeg20/tgt.c index 5e34aa91298c6e2e49394c460ec9dc197f9116a9..0cbad12c42ef5e187f9553c12fffb33f8add009d 100644 --- a/third_party/libopenjpeg20/tgt.c +++ b/third_party/libopenjpeg20/tgt.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,10 +8,10 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -39,87 +39,90 @@ #include "opj_includes.h" -/* +/* ========================================================== Tag-tree coder interface ========================================================== */ -opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, opj_event_mgr_t *manager) { - OPJ_INT32 nplh[32]; - OPJ_INT32 nplv[32]; - opj_tgt_node_t *node = 00; - opj_tgt_node_t *l_parent_node = 00; - opj_tgt_node_t *l_parent_node0 = 00; - opj_tgt_tree_t *tree = 00; - OPJ_UINT32 i; - OPJ_INT32 j,k; - OPJ_UINT32 numlvls; - OPJ_UINT32 n; - - tree = (opj_tgt_tree_t *) opj_calloc(1,sizeof(opj_tgt_tree_t)); - if(!tree) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory to create Tag-tree\n"); - return 00; - } +opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, + opj_event_mgr_t *p_manager) +{ + OPJ_INT32 nplh[32]; + OPJ_INT32 nplv[32]; + opj_tgt_node_t *node = 00; + opj_tgt_node_t *l_parent_node = 00; + opj_tgt_node_t *l_parent_node0 = 00; + opj_tgt_tree_t *tree = 00; + OPJ_UINT32 i; + OPJ_INT32 j, k; + OPJ_UINT32 numlvls; + OPJ_UINT32 n; - tree->numleafsh = numleafsh; - tree->numleafsv = numleafsv; + tree = (opj_tgt_tree_t *) opj_calloc(1, sizeof(opj_tgt_tree_t)); + if (!tree) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tag-tree\n"); + return 00; + } - numlvls = 0; - nplh[0] = (OPJ_INT32)numleafsh; - nplv[0] = (OPJ_INT32)numleafsv; - tree->numnodes = 0; - do { - n = (OPJ_UINT32)(nplh[numlvls] * nplv[numlvls]); - nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2; - nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2; - tree->numnodes += n; - ++numlvls; - } while (n > 1); + tree->numleafsh = numleafsh; + tree->numleafsv = numleafsv; - /* ADD */ - if (tree->numnodes == 0) { - opj_free(tree); - opj_event_msg(manager, EVT_WARNING, "tgt_create tree->numnodes == 0, no tree created.\n"); - return 00; - } + numlvls = 0; + nplh[0] = (OPJ_INT32)numleafsh; + nplv[0] = (OPJ_INT32)numleafsv; + tree->numnodes = 0; + do { + n = (OPJ_UINT32)(nplh[numlvls] * nplv[numlvls]); + nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2; + nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2; + tree->numnodes += n; + ++numlvls; + } while (n > 1); - tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t)); - if(!tree->nodes) { - opj_event_msg(manager, EVT_ERROR, "Not enough memory to create Tag-tree nodes\n"); - opj_free(tree); - return 00; - } - tree->nodes_size = tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t); + /* ADD */ + if (tree->numnodes == 0) { + opj_free(tree); + return 00; + } - node = tree->nodes; - l_parent_node = &tree->nodes[tree->numleafsh * tree->numleafsv]; - l_parent_node0 = l_parent_node; + tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, + sizeof(opj_tgt_node_t)); + if (!tree->nodes) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to create Tag-tree nodes\n"); + opj_free(tree); + return 00; + } + tree->nodes_size = tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t); + + node = tree->nodes; + l_parent_node = &tree->nodes[tree->numleafsh * tree->numleafsv]; + l_parent_node0 = l_parent_node; - for (i = 0; i < numlvls - 1; ++i) { - for (j = 0; j < nplv[i]; ++j) { - k = nplh[i]; - while (--k >= 0) { - node->parent = l_parent_node; - ++node; - if (--k >= 0) { - node->parent = l_parent_node; - ++node; - } - ++l_parent_node; - } - if ((j & 1) || j == nplv[i] - 1) { - l_parent_node0 = l_parent_node; - } else { - l_parent_node = l_parent_node0; - l_parent_node0 += nplh[i]; - } + for (i = 0; i < numlvls - 1; ++i) { + for (j = 0; j < nplv[i]; ++j) { + k = nplh[i]; + while (--k >= 0) { + node->parent = l_parent_node; + ++node; + if (--k >= 0) { + node->parent = l_parent_node; + ++node; } + ++l_parent_node; + } + if ((j & 1) || j == nplv[i] - 1) { + l_parent_node0 = l_parent_node; + } else { + l_parent_node = l_parent_node0; + l_parent_node0 += nplh[i]; + } } - node->parent = 0; - opj_tgt_reset(tree); - return tree; + } + node->parent = 0; + opj_tgt_reset(tree); + return tree; } /** @@ -130,206 +133,212 @@ opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, opj_e * @param p_num_leafs_v the height of the array of leafs of the tree * @return a new tag-tree if successful, NULL otherwise */ -opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v, opj_event_mgr_t *p_manager) +opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree, OPJ_UINT32 p_num_leafs_h, + OPJ_UINT32 p_num_leafs_v, opj_event_mgr_t *p_manager) { - OPJ_INT32 l_nplh[32]; - OPJ_INT32 l_nplv[32]; - opj_tgt_node_t *l_node = 00; - opj_tgt_node_t *l_parent_node = 00; - opj_tgt_node_t *l_parent_node0 = 00; - OPJ_UINT32 i; - OPJ_INT32 j,k; - OPJ_UINT32 l_num_levels; - OPJ_UINT32 n; - OPJ_UINT32 l_node_size; - - if (! p_tree){ - return 00; + OPJ_INT32 l_nplh[32]; + OPJ_INT32 l_nplv[32]; + opj_tgt_node_t *l_node = 00; + opj_tgt_node_t *l_parent_node = 00; + opj_tgt_node_t *l_parent_node0 = 00; + OPJ_UINT32 i; + OPJ_INT32 j, k; + OPJ_UINT32 l_num_levels; + OPJ_UINT32 n; + OPJ_UINT32 l_node_size; + + if (! p_tree) { + return 00; + } + + if ((p_tree->numleafsh != p_num_leafs_h) || + (p_tree->numleafsv != p_num_leafs_v)) { + p_tree->numleafsh = p_num_leafs_h; + p_tree->numleafsv = p_num_leafs_v; + + l_num_levels = 0; + l_nplh[0] = (OPJ_INT32)p_num_leafs_h; + l_nplv[0] = (OPJ_INT32)p_num_leafs_v; + p_tree->numnodes = 0; + do { + n = (OPJ_UINT32)(l_nplh[l_num_levels] * l_nplv[l_num_levels]); + l_nplh[l_num_levels + 1] = (l_nplh[l_num_levels] + 1) / 2; + l_nplv[l_num_levels + 1] = (l_nplv[l_num_levels] + 1) / 2; + p_tree->numnodes += n; + ++l_num_levels; + } while (n > 1); + + /* ADD */ + if (p_tree->numnodes == 0) { + opj_tgt_destroy(p_tree); + return 00; } + l_node_size = p_tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t); - if ((p_tree->numleafsh != p_num_leafs_h) || (p_tree->numleafsv != p_num_leafs_v)) { - p_tree->numleafsh = p_num_leafs_h; - p_tree->numleafsv = p_num_leafs_v; - - l_num_levels = 0; - l_nplh[0] = (OPJ_INT32)p_num_leafs_h; - l_nplv[0] = (OPJ_INT32)p_num_leafs_v; - p_tree->numnodes = 0; - do - { - n = (OPJ_UINT32)(l_nplh[l_num_levels] * l_nplv[l_num_levels]); - l_nplh[l_num_levels + 1] = (l_nplh[l_num_levels] + 1) / 2; - l_nplv[l_num_levels + 1] = (l_nplv[l_num_levels] + 1) / 2; - p_tree->numnodes += n; - ++l_num_levels; - } - while (n > 1); + if (l_node_size > p_tree->nodes_size) { + opj_tgt_node_t* new_nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, + l_node_size); + if (! new_nodes) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to reinitialize the tag tree\n"); + opj_tgt_destroy(p_tree); + return 00; + } + p_tree->nodes = new_nodes; + memset(((char *) p_tree->nodes) + p_tree->nodes_size, 0, + l_node_size - p_tree->nodes_size); + p_tree->nodes_size = l_node_size; + } + l_node = p_tree->nodes; + l_parent_node = &p_tree->nodes[p_tree->numleafsh * p_tree->numleafsv]; + l_parent_node0 = l_parent_node; - /* ADD */ - if (p_tree->numnodes == 0) { - opj_tgt_destroy(p_tree); - return 00; - } - l_node_size = p_tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t); - - if (l_node_size > p_tree->nodes_size) { - opj_tgt_node_t* new_nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size); - if (! new_nodes) { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to reinitialize the tag tree\n"); - opj_tgt_destroy(p_tree); - return 00; - } - p_tree->nodes = new_nodes; - memset(((char *) p_tree->nodes) + p_tree->nodes_size, 0 , l_node_size - p_tree->nodes_size); - p_tree->nodes_size = l_node_size; + for (i = 0; i < l_num_levels - 1; ++i) { + for (j = 0; j < l_nplv[i]; ++j) { + k = l_nplh[i]; + while (--k >= 0) { + l_node->parent = l_parent_node; + ++l_node; + if (--k >= 0) { + l_node->parent = l_parent_node; + ++l_node; + } + ++l_parent_node; } - l_node = p_tree->nodes; - l_parent_node = &p_tree->nodes[p_tree->numleafsh * p_tree->numleafsv]; - l_parent_node0 = l_parent_node; - - for (i = 0; i < l_num_levels - 1; ++i) { - for (j = 0; j < l_nplv[i]; ++j) { - k = l_nplh[i]; - while (--k >= 0) { - l_node->parent = l_parent_node; - ++l_node; - if (--k >= 0) { - l_node->parent = l_parent_node; - ++l_node; - } - ++l_parent_node; - } - if ((j & 1) || j == l_nplv[i] - 1) - { - l_parent_node0 = l_parent_node; - } - else - { - l_parent_node = l_parent_node0; - l_parent_node0 += l_nplh[i]; - } - } + if ((j & 1) || j == l_nplv[i] - 1) { + l_parent_node0 = l_parent_node; + } else { + l_parent_node = l_parent_node0; + l_parent_node0 += l_nplh[i]; } - l_node->parent = 0; + } } - opj_tgt_reset(p_tree); + l_node->parent = 0; + } + opj_tgt_reset(p_tree); - return p_tree; + return p_tree; } void opj_tgt_destroy(opj_tgt_tree_t *p_tree) { - if (! p_tree) { - return; - } + if (! p_tree) { + return; + } - if (p_tree->nodes) { - opj_free(p_tree->nodes); - p_tree->nodes = 00; - } - opj_free(p_tree); + if (p_tree->nodes) { + opj_free(p_tree->nodes); + p_tree->nodes = 00; + } + opj_free(p_tree); } -void opj_tgt_reset(opj_tgt_tree_t *p_tree) { - OPJ_UINT32 i; - opj_tgt_node_t * l_current_node = 00;; +void opj_tgt_reset(opj_tgt_tree_t *p_tree) +{ + OPJ_UINT32 i; + opj_tgt_node_t * l_current_node = 00;; - if (! p_tree) { - return; - } + if (! p_tree) { + return; + } - l_current_node = p_tree->nodes; - for (i = 0; i < p_tree->numnodes; ++i) - { - l_current_node->value = 999; - l_current_node->low = 0; - l_current_node->known = 0; - ++l_current_node; - } + l_current_node = p_tree->nodes; + for (i = 0; i < p_tree->numnodes; ++i) { + l_current_node->value = 999; + l_current_node->low = 0; + l_current_node->known = 0; + ++l_current_node; + } } -void opj_tgt_setvalue(opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 value) { - opj_tgt_node_t *node; - node = &tree->nodes[leafno]; - while (node && node->value > value) { - node->value = value; - node = node->parent; - } +void opj_tgt_setvalue(opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 value) +{ + opj_tgt_node_t *node; + node = &tree->nodes[leafno]; + while (node && node->value > value) { + node->value = value; + node = node->parent; + } } -void opj_tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold) { - opj_tgt_node_t *stk[31]; - opj_tgt_node_t **stkptr; - opj_tgt_node_t *node; - OPJ_INT32 low; - - stkptr = stk; - node = &tree->nodes[leafno]; - while (node->parent) { - *stkptr++ = node; - node = node->parent; +void opj_tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, + OPJ_INT32 threshold) +{ + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + OPJ_INT32 low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; } - - low = 0; - for (;;) { - if (low > node->low) { - node->low = low; - } else { - low = node->low; - } - - while (low < threshold) { - if (low >= node->value) { - if (!node->known) { - opj_bio_write(bio, 1, 1); - node->known = 1; - } - break; - } - opj_bio_write(bio, 0, 1); - ++low; + + while (low < threshold) { + if (low >= node->value) { + if (!node->known) { + opj_bio_write(bio, 1, 1); + node->known = 1; } - - node->low = low; - if (stkptr == stk) - break; - node = *--stkptr; + break; + } + opj_bio_write(bio, 0, 1); + ++low; + } + + node->low = low; + if (stkptr == stk) { + break; } + node = *--stkptr; + } } -OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold) { - opj_tgt_node_t *stk[31]; - opj_tgt_node_t **stkptr; - opj_tgt_node_t *node; - OPJ_INT32 low; - - stkptr = stk; - node = &tree->nodes[leafno]; - while (node->parent) { - *stkptr++ = node; - node = node->parent; +OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, OPJ_INT32 threshold) +{ + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + OPJ_INT32 low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; } - - low = 0; - for (;;) { - if (low > node->low) { - node->low = low; - } else { - low = node->low; - } - while (low < threshold && low < node->value) { - if (opj_bio_read(bio, 1)) { - node->value = low; - } else { - ++low; - } - } - node->low = low; - if (stkptr == stk) { - break; - } - node = *--stkptr; + while (low < threshold && low < node->value) { + if (opj_bio_read(bio, 1)) { + node->value = low; + } else { + ++low; + } + } + node->low = low; + if (stkptr == stk) { + break; } - - return (node->value < threshold) ? 1 : 0; + node = *--stkptr; + } + + return (node->value < threshold) ? 1 : 0; } diff --git a/third_party/libopenjpeg20/tgt.h b/third_party/libopenjpeg20/tgt.h index 102238052ac3b121642b3f4c87a40377a3d39065..9818208b82075922ebd5007d4cab18f587efb122 100644 --- a/third_party/libopenjpeg20/tgt.h +++ b/third_party/libopenjpeg20/tgt.h @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,11 +8,11 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr> - * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France * Copyright (c) 2012, CS Systemes d'Information, France * All rights reserved. * @@ -38,8 +38,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __TGT_H -#define __TGT_H +#ifndef OPJ_TGT_H +#define OPJ_TGT_H /** @file tgt.h @brief Implementation of a tag-tree coder (TGT) @@ -64,13 +64,12 @@ typedef struct opj_tgt_node { /** Tag tree */ -typedef struct opj_tgt_tree -{ - OPJ_UINT32 numleafsh; - OPJ_UINT32 numleafsv; - OPJ_UINT32 numnodes; - opj_tgt_node_t *nodes; - OPJ_UINT32 nodes_size; /* maximum size taken by nodes */ +typedef struct opj_tgt_tree { + OPJ_UINT32 numleafsh; + OPJ_UINT32 numleafsv; + OPJ_UINT32 numnodes; + opj_tgt_node_t *nodes; + OPJ_UINT32 nodes_size; /* maximum size taken by nodes */ } opj_tgt_tree_t; @@ -81,21 +80,23 @@ typedef struct opj_tgt_tree Create a tag-tree @param numleafsh Width of the array of leafs of the tree @param numleafsv Height of the array of leafs of the tree +@param p_manager the event manager @return Returns a new tag-tree if successful, returns NULL otherwise */ -opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, opj_event_mgr_t *manager); +opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, + opj_event_mgr_t *p_manager); /** * Reinitialises a tag-tree from an exixting one. * - * @param p_tree the tree to reinitialize. - * @param p_num_leafs_h the width of the array of leafs of the tree - * @param p_num_leafs_v the height of the array of leafs of the tree + * @param p_tree the tree to reinitialize. + * @param p_num_leafs_h the width of the array of leafs of the tree + * @param p_num_leafs_v the height of the array of leafs of the tree * @param p_manager the event manager - * @return a new tag-tree if successful, NULL otherwise + * @return a new tag-tree if successful, NULL otherwise */ -opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree, - OPJ_UINT32 p_num_leafs_h, +opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree, + OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v, opj_event_mgr_t *p_manager); /** Destroy a tag-tree, liberating memory @@ -113,8 +114,8 @@ Set the value of a leaf of a tag-tree @param leafno Number that identifies the leaf to modify @param value New value of the leaf */ -void opj_tgt_setvalue(opj_tgt_tree_t *tree, - OPJ_UINT32 leafno, +void opj_tgt_setvalue(opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, OPJ_INT32 value); /** Encode the value of a leaf of the tag-tree up to a given threshold @@ -123,9 +124,9 @@ Encode the value of a leaf of the tag-tree up to a given threshold @param leafno Number that identifies the leaf to encode @param threshold Threshold to use when encoding value of the leaf */ -void opj_tgt_encode(opj_bio_t *bio, - opj_tgt_tree_t *tree, - OPJ_UINT32 leafno, +void opj_tgt_encode(opj_bio_t *bio, + opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, OPJ_INT32 threshold); /** Decode the value of a leaf of the tag-tree up to a given threshold @@ -135,13 +136,13 @@ Decode the value of a leaf of the tag-tree up to a given threshold @param threshold Threshold to use when decoding value of the leaf @return Returns 1 if the node's value < threshold, returns 0 otherwise */ -OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, - opj_tgt_tree_t *tree, - OPJ_UINT32 leafno, +OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, + opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, OPJ_INT32 threshold); /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ -#endif /* __TGT_H */ +#endif /* OPJ_TGT_H */ diff --git a/third_party/libopenjpeg20/thread.c b/third_party/libopenjpeg20/thread.c new file mode 100644 index 0000000000000000000000000000000000000000..af33c2c8062ffefd404a6c523c58522bce2389f5 --- /dev/null +++ b/third_party/libopenjpeg20/thread.c @@ -0,0 +1,952 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2016, Even Rouault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <assert.h> + +#ifdef MUTEX_win32 + +/* Some versions of x86_64-w64-mingw32-gc -m32 resolve InterlockedCompareExchange() */ +/* as __sync_val_compare_and_swap_4 but fails to link it. As this protects against */ +/* a rather unlikely race, skip it */ +#if !(defined(__MINGW32__) && defined(__i386__)) +#define HAVE_INTERLOCKED_COMPARE_EXCHANGE 1 +#endif + +#include <windows.h> +#include <process.h> + +#include "opj_includes.h" + +OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void) +{ + return OPJ_TRUE; +} + +int OPJ_CALLCONV opj_get_num_cpus(void) +{ + SYSTEM_INFO info; + DWORD dwNum; + GetSystemInfo(&info); + dwNum = info.dwNumberOfProcessors; + if (dwNum < 1) { + return 1; + } + return (int)dwNum; +} + +struct opj_mutex_t { + CRITICAL_SECTION cs; +}; + +opj_mutex_t* opj_mutex_create(void) +{ + opj_mutex_t* mutex = (opj_mutex_t*) opj_malloc(sizeof(opj_mutex_t)); + if (!mutex) { + return NULL; + } + InitializeCriticalSectionAndSpinCount(&(mutex->cs), 4000); + return mutex; +} + +void opj_mutex_lock(opj_mutex_t* mutex) +{ + EnterCriticalSection(&(mutex->cs)); +} + +void opj_mutex_unlock(opj_mutex_t* mutex) +{ + LeaveCriticalSection(&(mutex->cs)); +} + +void opj_mutex_destroy(opj_mutex_t* mutex) +{ + if (!mutex) { + return; + } + DeleteCriticalSection(&(mutex->cs)); + opj_free(mutex); +} + +struct opj_cond_waiter_list_t { + HANDLE hEvent; + struct opj_cond_waiter_list_t* next; +}; +typedef struct opj_cond_waiter_list_t opj_cond_waiter_list_t; + +struct opj_cond_t { + opj_mutex_t *internal_mutex; + opj_cond_waiter_list_t *waiter_list; +}; + +static DWORD TLSKey = 0; +static volatile LONG inTLSLockedSection = 0; +static volatile int TLSKeyInit = OPJ_FALSE; + +opj_cond_t* opj_cond_create(void) +{ + opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t)); + if (!cond) { + return NULL; + } + + /* Make sure that the TLS key is allocated in a thread-safe way */ + /* We cannot use a global mutex/critical section since its creation itself would not be */ + /* thread-safe, so use InterlockedCompareExchange trick */ + while (OPJ_TRUE) { + +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + if (InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0) +#endif + { + if (!TLSKeyInit) { + TLSKey = TlsAlloc(); + TLSKeyInit = OPJ_TRUE; + } +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + InterlockedCompareExchange(&inTLSLockedSection, 0, 1); +#endif + break; + } + } + + if (TLSKey == TLS_OUT_OF_INDEXES) { + opj_free(cond); + return NULL; + } + cond->internal_mutex = opj_mutex_create(); + if (cond->internal_mutex == NULL) { + opj_free(cond); + return NULL; + } + cond->waiter_list = NULL; + return cond; +} + +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) +{ + opj_cond_waiter_list_t* item; + HANDLE hEvent = (HANDLE) TlsGetValue(TLSKey); + if (hEvent == NULL) { + hEvent = CreateEvent(NULL, /* security attributes */ + 0, /* manual reset = no */ + 0, /* initial state = unsignaled */ + NULL /* no name */); + assert(hEvent); + + TlsSetValue(TLSKey, hEvent); + } + + /* Insert the waiter into the waiter list of the condition */ + opj_mutex_lock(cond->internal_mutex); + + item = (opj_cond_waiter_list_t*)opj_malloc(sizeof(opj_cond_waiter_list_t)); + assert(item != NULL); + + item->hEvent = hEvent; + item->next = cond->waiter_list; + + cond->waiter_list = item; + + opj_mutex_unlock(cond->internal_mutex); + + /* Release the client mutex before waiting for the event being signaled */ + opj_mutex_unlock(mutex); + + /* Ideally we would check that we do not get WAIT_FAILED but it is hard */ + /* to report a failure. */ + WaitForSingleObject(hEvent, INFINITE); + + /* Reacquire the client mutex */ + opj_mutex_lock(mutex); +} + +void opj_cond_signal(opj_cond_t* cond) +{ + opj_cond_waiter_list_t* psIter; + + /* Signal the first registered event, and remove it from the list */ + opj_mutex_lock(cond->internal_mutex); + + psIter = cond->waiter_list; + if (psIter != NULL) { + SetEvent(psIter->hEvent); + cond->waiter_list = psIter->next; + opj_free(psIter); + } + + opj_mutex_unlock(cond->internal_mutex); +} + +void opj_cond_destroy(opj_cond_t* cond) +{ + if (!cond) { + return; + } + opj_mutex_destroy(cond->internal_mutex); + assert(cond->waiter_list == NULL); + opj_free(cond); +} + +struct opj_thread_t { + opj_thread_fn thread_fn; + void* user_data; + HANDLE hThread; +}; + +unsigned int __stdcall opj_thread_callback_adapter(void *info) +{ + opj_thread_t* thread = (opj_thread_t*) info; + HANDLE hEvent = NULL; + + thread->thread_fn(thread->user_data); + + /* Free the handle possible allocated by a cond */ + while (OPJ_TRUE) { + /* Make sure TLSKey is not being created just at that moment... */ +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + if (InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0) +#endif + { + if (TLSKeyInit) { + hEvent = (HANDLE) TlsGetValue(TLSKey); + } +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + InterlockedCompareExchange(&inTLSLockedSection, 0, 1); +#endif + break; + } + } + if (hEvent) { + CloseHandle(hEvent); + } + + return 0; +} + +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data) +{ + opj_thread_t* thread; + + assert(thread_fn); + + thread = (opj_thread_t*) opj_malloc(sizeof(opj_thread_t)); + if (!thread) { + return NULL; + } + thread->thread_fn = thread_fn; + thread->user_data = user_data; + + thread->hThread = (HANDLE)_beginthreadex(NULL, 0, + opj_thread_callback_adapter, thread, 0, NULL); + + if (thread->hThread == NULL) { + opj_free(thread); + return NULL; + } + return thread; +} + +void opj_thread_join(opj_thread_t* thread) +{ + WaitForSingleObject(thread->hThread, INFINITE); + CloseHandle(thread->hThread); + + opj_free(thread); +} + +#elif MUTEX_pthread + +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> + +/* Moved after all system includes, and in particular pthread.h, so as to */ +/* avoid poisoning issuing with malloc() use in pthread.h with ulibc (#1013) */ +#include "opj_includes.h" + +OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void) +{ + return OPJ_TRUE; +} + +int OPJ_CALLCONV opj_get_num_cpus(void) +{ +#ifdef _SC_NPROCESSORS_ONLN + return (int)sysconf(_SC_NPROCESSORS_ONLN); +#else + return 1; +#endif +} + +struct opj_mutex_t { + pthread_mutex_t mutex; +}; + +opj_mutex_t* opj_mutex_create(void) +{ + opj_mutex_t* mutex = (opj_mutex_t*) opj_calloc(1U, sizeof(opj_mutex_t)); + if (mutex != NULL) { + if (pthread_mutex_init(&mutex->mutex, NULL) != 0) { + opj_free(mutex); + mutex = NULL; + } + } + return mutex; +} + +void opj_mutex_lock(opj_mutex_t* mutex) +{ + pthread_mutex_lock(&(mutex->mutex)); +} + +void opj_mutex_unlock(opj_mutex_t* mutex) +{ + pthread_mutex_unlock(&(mutex->mutex)); +} + +void opj_mutex_destroy(opj_mutex_t* mutex) +{ + if (!mutex) { + return; + } + pthread_mutex_destroy(&(mutex->mutex)); + opj_free(mutex); +} + +struct opj_cond_t { + pthread_cond_t cond; +}; + +opj_cond_t* opj_cond_create(void) +{ + opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t)); + if (!cond) { + return NULL; + } + if (pthread_cond_init(&(cond->cond), NULL) != 0) { + opj_free(cond); + return NULL; + } + return cond; +} + +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) +{ + pthread_cond_wait(&(cond->cond), &(mutex->mutex)); +} + +void opj_cond_signal(opj_cond_t* cond) +{ + int ret = pthread_cond_signal(&(cond->cond)); + (void)ret; + assert(ret == 0); +} + +void opj_cond_destroy(opj_cond_t* cond) +{ + if (!cond) { + return; + } + pthread_cond_destroy(&(cond->cond)); + opj_free(cond); +} + + +struct opj_thread_t { + opj_thread_fn thread_fn; + void* user_data; + pthread_t thread; +}; + +static void* opj_thread_callback_adapter(void* info) +{ + opj_thread_t* thread = (opj_thread_t*) info; + thread->thread_fn(thread->user_data); + return NULL; +} + +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data) +{ + pthread_attr_t attr; + opj_thread_t* thread; + + assert(thread_fn); + + thread = (opj_thread_t*) opj_malloc(sizeof(opj_thread_t)); + if (!thread) { + return NULL; + } + thread->thread_fn = thread_fn; + thread->user_data = user_data; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + if (pthread_create(&(thread->thread), &attr, + opj_thread_callback_adapter, (void *) thread) != 0) { + opj_free(thread); + return NULL; + } + return thread; +} + +void opj_thread_join(opj_thread_t* thread) +{ + void* status; + pthread_join(thread->thread, &status); + + opj_free(thread); +} + +#else +/* Stub implementation */ + +#include "opj_includes.h" + +OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void) +{ + return OPJ_FALSE; +} + +int OPJ_CALLCONV opj_get_num_cpus(void) +{ + return 1; +} + +opj_mutex_t* opj_mutex_create(void) +{ + return NULL; +} + +void opj_mutex_lock(opj_mutex_t* mutex) +{ + (void) mutex; +} + +void opj_mutex_unlock(opj_mutex_t* mutex) +{ + (void) mutex; +} + +void opj_mutex_destroy(opj_mutex_t* mutex) +{ + (void) mutex; +} + +opj_cond_t* opj_cond_create(void) +{ + return NULL; +} + +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) +{ + (void) cond; + (void) mutex; +} + +void opj_cond_signal(opj_cond_t* cond) +{ + (void) cond; +} + +void opj_cond_destroy(opj_cond_t* cond) +{ + (void) cond; +} + +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data) +{ + (void) thread_fn; + (void) user_data; + return NULL; +} + +void opj_thread_join(opj_thread_t* thread) +{ + (void) thread; +} + +#endif + +typedef struct { + int key; + void* value; + opj_tls_free_func opj_free_func; +} opj_tls_key_val_t; + +struct opj_tls_t { + opj_tls_key_val_t* key_val; + int key_val_count; +}; + +static opj_tls_t* opj_tls_new(void) +{ + return (opj_tls_t*) opj_calloc(1, sizeof(opj_tls_t)); +} + +static void opj_tls_destroy(opj_tls_t* tls) +{ + int i; + if (!tls) { + return; + } + for (i = 0; i < tls->key_val_count; i++) { + if (tls->key_val[i].opj_free_func) { + tls->key_val[i].opj_free_func(tls->key_val[i].value); + } + } + opj_free(tls->key_val); + opj_free(tls); +} + +void* opj_tls_get(opj_tls_t* tls, int key) +{ + int i; + for (i = 0; i < tls->key_val_count; i++) { + if (tls->key_val[i].key == key) { + return tls->key_val[i].value; + } + } + return NULL; +} + +OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value, + opj_tls_free_func opj_free_func) +{ + opj_tls_key_val_t* new_key_val; + int i; + + if (tls->key_val_count == INT_MAX) { + return OPJ_FALSE; + } + for (i = 0; i < tls->key_val_count; i++) { + if (tls->key_val[i].key == key) { + if (tls->key_val[i].opj_free_func) { + tls->key_val[i].opj_free_func(tls->key_val[i].value); + } + tls->key_val[i].value = value; + tls->key_val[i].opj_free_func = opj_free_func; + return OPJ_TRUE; + } + } + new_key_val = (opj_tls_key_val_t*) opj_realloc(tls->key_val, + ((size_t)tls->key_val_count + 1U) * sizeof(opj_tls_key_val_t)); + if (!new_key_val) { + return OPJ_FALSE; + } + tls->key_val = new_key_val; + new_key_val[tls->key_val_count].key = key; + new_key_val[tls->key_val_count].value = value; + new_key_val[tls->key_val_count].opj_free_func = opj_free_func; + tls->key_val_count ++; + return OPJ_TRUE; +} + + +typedef struct { + opj_job_fn job_fn; + void *user_data; +} opj_worker_thread_job_t; + +typedef struct { + opj_thread_pool_t *tp; + opj_thread_t *thread; + int marked_as_waiting; + + opj_mutex_t *mutex; + opj_cond_t *cond; +} opj_worker_thread_t; + +typedef enum { + OPJWTS_OK, + OPJWTS_STOP, + OPJWTS_ERROR +} opj_worker_thread_state; + +struct opj_job_list_t { + opj_worker_thread_job_t* job; + struct opj_job_list_t* next; +}; +typedef struct opj_job_list_t opj_job_list_t; + +struct opj_worker_thread_list_t { + opj_worker_thread_t* worker_thread; + struct opj_worker_thread_list_t* next; +}; +typedef struct opj_worker_thread_list_t opj_worker_thread_list_t; + +struct opj_thread_pool_t { + opj_worker_thread_t* worker_threads; + int worker_threads_count; + opj_cond_t* cond; + opj_mutex_t* mutex; + volatile opj_worker_thread_state state; + opj_job_list_t* job_queue; + volatile int pending_jobs_count; + opj_worker_thread_list_t* waiting_worker_thread_list; + int waiting_worker_thread_count; + opj_tls_t* tls; + int signaling_threshold; +}; + +static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads); +static opj_worker_thread_job_t* opj_thread_pool_get_next_job( + opj_thread_pool_t* tp, + opj_worker_thread_t* worker_thread, + OPJ_BOOL signal_job_finished); + +opj_thread_pool_t* opj_thread_pool_create(int num_threads) +{ + opj_thread_pool_t* tp; + + tp = (opj_thread_pool_t*) opj_calloc(1, sizeof(opj_thread_pool_t)); + if (!tp) { + return NULL; + } + tp->state = OPJWTS_OK; + + if (num_threads <= 0) { + tp->tls = opj_tls_new(); + if (!tp->tls) { + opj_free(tp); + tp = NULL; + } + return tp; + } + + tp->mutex = opj_mutex_create(); + if (!tp->mutex) { + opj_free(tp); + return NULL; + } + if (!opj_thread_pool_setup(tp, num_threads)) { + opj_thread_pool_destroy(tp); + return NULL; + } + return tp; +} + +static void opj_worker_thread_function(void* user_data) +{ + opj_worker_thread_t* worker_thread; + opj_thread_pool_t* tp; + opj_tls_t* tls; + OPJ_BOOL job_finished = OPJ_FALSE; + + worker_thread = (opj_worker_thread_t*) user_data; + tp = worker_thread->tp; + tls = opj_tls_new(); + + while (OPJ_TRUE) { + opj_worker_thread_job_t* job = opj_thread_pool_get_next_job(tp, worker_thread, + job_finished); + if (job == NULL) { + break; + } + + if (job->job_fn) { + job->job_fn(job->user_data, tls); + } + opj_free(job); + job_finished = OPJ_TRUE; + } + + opj_tls_destroy(tls); +} + +static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads) +{ + int i; + OPJ_BOOL bRet = OPJ_TRUE; + + assert(num_threads > 0); + + tp->cond = opj_cond_create(); + if (tp->cond == NULL) { + return OPJ_FALSE; + } + + tp->worker_threads = (opj_worker_thread_t*) opj_calloc((size_t)num_threads, + sizeof(opj_worker_thread_t)); + if (tp->worker_threads == NULL) { + return OPJ_FALSE; + } + tp->worker_threads_count = num_threads; + + for (i = 0; i < num_threads; i++) { + tp->worker_threads[i].tp = tp; + + tp->worker_threads[i].mutex = opj_mutex_create(); + if (tp->worker_threads[i].mutex == NULL) { + tp->worker_threads_count = i; + bRet = OPJ_FALSE; + break; + } + + tp->worker_threads[i].cond = opj_cond_create(); + if (tp->worker_threads[i].cond == NULL) { + opj_mutex_destroy(tp->worker_threads[i].mutex); + tp->worker_threads_count = i; + bRet = OPJ_FALSE; + break; + } + + tp->worker_threads[i].marked_as_waiting = OPJ_FALSE; + + tp->worker_threads[i].thread = opj_thread_create(opj_worker_thread_function, + &(tp->worker_threads[i])); + if (tp->worker_threads[i].thread == NULL) { + tp->worker_threads_count = i; + bRet = OPJ_FALSE; + break; + } + } + + /* Wait all threads to be started */ + /* printf("waiting for all threads to be started\n"); */ + opj_mutex_lock(tp->mutex); + while (tp->waiting_worker_thread_count < num_threads) { + opj_cond_wait(tp->cond, tp->mutex); + } + opj_mutex_unlock(tp->mutex); + /* printf("all threads started\n"); */ + + if (tp->state == OPJWTS_ERROR) { + bRet = OPJ_FALSE; + } + + return bRet; +} + +/* +void opj_waiting() +{ + printf("waiting!\n"); +} +*/ + +static opj_worker_thread_job_t* opj_thread_pool_get_next_job( + opj_thread_pool_t* tp, + opj_worker_thread_t* worker_thread, + OPJ_BOOL signal_job_finished) +{ + while (OPJ_TRUE) { + opj_job_list_t* top_job_iter; + + opj_mutex_lock(tp->mutex); + + if (signal_job_finished) { + signal_job_finished = OPJ_FALSE; + tp->pending_jobs_count --; + /*printf("tp=%p, remaining jobs: %d\n", tp, tp->pending_jobs_count);*/ + if (tp->pending_jobs_count <= tp->signaling_threshold) { + opj_cond_signal(tp->cond); + } + } + + if (tp->state == OPJWTS_STOP) { + opj_mutex_unlock(tp->mutex); + return NULL; + } + top_job_iter = tp->job_queue; + if (top_job_iter) { + opj_worker_thread_job_t* job; + tp->job_queue = top_job_iter->next; + + job = top_job_iter->job; + opj_mutex_unlock(tp->mutex); + opj_free(top_job_iter); + return job; + } + + /* opj_waiting(); */ + if (!worker_thread->marked_as_waiting) { + opj_worker_thread_list_t* item; + + worker_thread->marked_as_waiting = OPJ_TRUE; + tp->waiting_worker_thread_count ++; + assert(tp->waiting_worker_thread_count <= tp->worker_threads_count); + + item = (opj_worker_thread_list_t*) opj_malloc(sizeof(opj_worker_thread_list_t)); + if (item == NULL) { + tp->state = OPJWTS_ERROR; + opj_cond_signal(tp->cond); + + opj_mutex_unlock(tp->mutex); + return NULL; + } + + item->worker_thread = worker_thread; + item->next = tp->waiting_worker_thread_list; + tp->waiting_worker_thread_list = item; + } + + /* printf("signaling that worker thread is ready\n"); */ + opj_cond_signal(tp->cond); + + opj_mutex_lock(worker_thread->mutex); + opj_mutex_unlock(tp->mutex); + + /* printf("waiting for job\n"); */ + opj_cond_wait(worker_thread->cond, worker_thread->mutex); + + opj_mutex_unlock(worker_thread->mutex); + /* printf("got job\n"); */ + } +} + +OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp, + opj_job_fn job_fn, + void* user_data) +{ + opj_worker_thread_job_t* job; + opj_job_list_t* item; + + if (tp->mutex == NULL) { + job_fn(user_data, tp->tls); + return OPJ_TRUE; + } + + job = (opj_worker_thread_job_t*)opj_malloc(sizeof(opj_worker_thread_job_t)); + if (job == NULL) { + return OPJ_FALSE; + } + job->job_fn = job_fn; + job->user_data = user_data; + + item = (opj_job_list_t*) opj_malloc(sizeof(opj_job_list_t)); + if (item == NULL) { + opj_free(job); + return OPJ_FALSE; + } + item->job = job; + + opj_mutex_lock(tp->mutex); + + tp->signaling_threshold = 100 * tp->worker_threads_count; + while (tp->pending_jobs_count > tp->signaling_threshold) { + /* printf("%d jobs enqueued. Waiting\n", tp->pending_jobs_count); */ + opj_cond_wait(tp->cond, tp->mutex); + /* printf("...%d jobs enqueued.\n", tp->pending_jobs_count); */ + } + + item->next = tp->job_queue; + tp->job_queue = item; + tp->pending_jobs_count ++; + + if (tp->waiting_worker_thread_list) { + opj_worker_thread_t* worker_thread; + opj_worker_thread_list_t* next; + opj_worker_thread_list_t* to_opj_free; + + worker_thread = tp->waiting_worker_thread_list->worker_thread; + + assert(worker_thread->marked_as_waiting); + worker_thread->marked_as_waiting = OPJ_FALSE; + + next = tp->waiting_worker_thread_list->next; + to_opj_free = tp->waiting_worker_thread_list; + tp->waiting_worker_thread_list = next; + tp->waiting_worker_thread_count --; + + opj_mutex_lock(worker_thread->mutex); + opj_mutex_unlock(tp->mutex); + opj_cond_signal(worker_thread->cond); + opj_mutex_unlock(worker_thread->mutex); + + opj_free(to_opj_free); + } else { + opj_mutex_unlock(tp->mutex); + } + + return OPJ_TRUE; +} + +void opj_thread_pool_wait_completion(opj_thread_pool_t* tp, + int max_remaining_jobs) +{ + if (tp->mutex == NULL) { + return; + } + + if (max_remaining_jobs < 0) { + max_remaining_jobs = 0; + } + opj_mutex_lock(tp->mutex); + tp->signaling_threshold = max_remaining_jobs; + while (tp->pending_jobs_count > max_remaining_jobs) { + /*printf("tp=%p, jobs before wait = %d, max_remaining_jobs = %d\n", tp, tp->pending_jobs_count, max_remaining_jobs);*/ + opj_cond_wait(tp->cond, tp->mutex); + /*printf("tp=%p, jobs after wait = %d\n", tp, tp->pending_jobs_count);*/ + } + opj_mutex_unlock(tp->mutex); +} + +int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp) +{ + return tp->worker_threads_count; +} + +void opj_thread_pool_destroy(opj_thread_pool_t* tp) +{ + if (!tp) { + return; + } + if (tp->cond) { + int i; + opj_thread_pool_wait_completion(tp, 0); + + opj_mutex_lock(tp->mutex); + tp->state = OPJWTS_STOP; + opj_mutex_unlock(tp->mutex); + + for (i = 0; i < tp->worker_threads_count; i++) { + opj_mutex_lock(tp->worker_threads[i].mutex); + opj_cond_signal(tp->worker_threads[i].cond); + opj_mutex_unlock(tp->worker_threads[i].mutex); + opj_thread_join(tp->worker_threads[i].thread); + opj_cond_destroy(tp->worker_threads[i].cond); + opj_mutex_destroy(tp->worker_threads[i].mutex); + } + + opj_free(tp->worker_threads); + + while (tp->waiting_worker_thread_list != NULL) { + opj_worker_thread_list_t* next = tp->waiting_worker_thread_list->next; + opj_free(tp->waiting_worker_thread_list); + tp->waiting_worker_thread_list = next; + } + + opj_cond_destroy(tp->cond); + } + opj_mutex_destroy(tp->mutex); + opj_tls_destroy(tp->tls); + opj_free(tp); +} diff --git a/third_party/libopenjpeg20/thread.h b/third_party/libopenjpeg20/thread.h new file mode 100644 index 0000000000000000000000000000000000000000..c89e19b4a6afabfd7e2e8d07b56fa7acd34b1b1d --- /dev/null +++ b/third_party/libopenjpeg20/thread.h @@ -0,0 +1,256 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2016, Even Rouault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THREAD_H +#define THREAD_H + +#include "openjpeg.h" + +/** +@file thread.h +@brief Thread API + +The functions in thread.c have for goal to manage mutex, conditions, thread +creation and thread pools that accept jobs. +*/ + +/** @defgroup THREAD THREAD - Mutex, conditions, threads and thread pools */ +/*@{*/ + +/** @name Mutex */ +/*@{*/ + +/** Opaque type for a mutex */ +typedef struct opj_mutex_t opj_mutex_t; + +/** Creates a mutex. + * @return the mutex or NULL in case of error (can for example happen if the library + * is built without thread support) + */ +opj_mutex_t* opj_mutex_create(void); + +/** Lock/acquire the mutex. + * @param mutex the mutex to acquire. + */ +void opj_mutex_lock(opj_mutex_t* mutex); + +/** Unlock/release the mutex. + * @param mutex the mutex to release. + */ +void opj_mutex_unlock(opj_mutex_t* mutex); + +/** Destroy a mutex + * @param mutex the mutex to destroy. + */ +void opj_mutex_destroy(opj_mutex_t* mutex); + +/*@}*/ + +/** @name Condition */ +/*@{*/ + +/** Opaque type for a condition */ +typedef struct opj_cond_t opj_cond_t; + +/** Creates a condition. + * @return the condition or NULL in case of error (can for example happen if the library + * is built without thread support) + */ +opj_cond_t* opj_cond_create(void); + +/** Wait for the condition to be signaled. + * The semantics is the same as the POSIX pthread_cond_wait. + * The provided mutex *must* be acquired before calling this function, and + * released afterwards. + * The mutex will be released by this function while it must wait for the condition + * and reacquired afterwards. + * In some particular situations, the function might return even if the condition is not signaled + * with opj_cond_signal(), hence the need to check with an application level + * mechanism. + * + * Waiting thread : + * \code + * opj_mutex_lock(mutex); + * while( !some_application_level_condition ) + * { + * opj_cond_wait(cond, mutex); + * } + * opj_mutex_unlock(mutex); + * \endcode + * + * Signaling thread : + * \code + * opj_mutex_lock(mutex); + * some_application_level_condition = TRUE; + * opj_cond_signal(cond); + * opj_mutex_unlock(mutex); + * \endcode + * + * @param cond the condition to wait. + * @param mutex the mutex (in acquired state before calling this function) + */ +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex); + +/** Signal waiting threads on a condition. + * One of the thread waiting with opj_cond_wait() will be waken up. + * It is strongly advised that this call is done with the mutex that is used + * by opj_cond_wait(), in a acquired state. + * @param cond the condition to signal. + */ +void opj_cond_signal(opj_cond_t* cond); + +/** Destroy a condition + * @param cond the condition to destroy. + */ +void opj_cond_destroy(opj_cond_t* cond); + +/*@}*/ + +/** @name Thread */ +/*@{*/ + +/** Opaque type for a thread handle */ +typedef struct opj_thread_t opj_thread_t; + +/** User function to execute in a thread + * @param user_data user data provided with opj_thread_create() + */ +typedef void (*opj_thread_fn)(void* user_data); + +/** Creates a new thread. + * @param thread_fn Function to run in the new thread. + * @param user_data user data provided to the thread function. Might be NULL. + * @return a thread handle or NULL in case of failure (can for example happen if the library + * is built without thread support) + */ +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data); + +/** Wait for a thread to be finished and release associated resources to the + * thread handle. + * @param thread the thread to wait for being finished. + */ +void opj_thread_join(opj_thread_t* thread); + +/*@}*/ + +/** @name Thread local storage */ +/*@{*/ +/** Opaque type for a thread local storage */ +typedef struct opj_tls_t opj_tls_t; + +/** Get a thread local value corresponding to the provided key. + * @param tls thread local storage handle + * @param key key whose value to retrieve. + * @return value associated with the key, or NULL is missing. + */ +void* opj_tls_get(opj_tls_t* tls, int key); + +/** Type of the function used to free a TLS value */ +typedef void (*opj_tls_free_func)(void* value); + +/** Set a thread local value corresponding to the provided key. + * @param tls thread local storage handle + * @param key key whose value to set. + * @param value value to set (may be NULL). + * @param free_func function to call currently installed value. + * @return OPJ_TRUE if successful. + */ +OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value, + opj_tls_free_func free_func); + +/*@}*/ + +/** @name Thread pool */ +/*@{*/ + +/** Opaque type for a thread pool */ +typedef struct opj_thread_pool_t opj_thread_pool_t; + +/** Create a new thread pool. + * num_thread must nominally be >= 1 to create a real thread pool. If num_threads + * is negative or null, then a dummy thread pool will be created. All functions + * operating on the thread pool will work, but job submission will be run + * synchronously in the calling thread. + * + * @param num_threads the number of threads to allocate for this thread pool. + * @return a thread pool handle, or NULL in case of failure (can for example happen if the library + * is built without thread support) + */ +opj_thread_pool_t* opj_thread_pool_create(int num_threads); + +/** User function to execute in a thread + * @param user_data user data provided with opj_thread_create() + * @param tls handle to thread local storage + */ +typedef void (*opj_job_fn)(void* user_data, opj_tls_t* tls); + + +/** Submit a new job to be run by one of the thread in the thread pool. + * The job ( thread_fn, user_data ) will be added in the queue of jobs managed + * by the thread pool, and run by the first thread that is no longer busy. + * + * @param tp the thread pool handle. + * @param job_fn Function to run. Must not be NULL. + * @param user_data User data provided to thread_fn. + * @return OPJ_TRUE if the job was successfully submitted. + */ +OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp, opj_job_fn job_fn, + void* user_data); + +/** Wait that no more than max_remaining_jobs jobs are remaining in the queue of + * the thread pool. The aim of this function is to avoid submitting too many + * jobs while the thread pool cannot cope fast enough with them, which would + * result potentially in out-of-memory situations with too many job descriptions + * being queued. + * + * @param tp the thread pool handle + * @param max_remaining_jobs maximum number of jobs allowed to be queued without waiting. + */ +void opj_thread_pool_wait_completion(opj_thread_pool_t* tp, + int max_remaining_jobs); + +/** Return the number of threads associated with the thread pool. + * + * @param tp the thread pool handle. + * @return number of threads associated with the thread pool. + */ +int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp); + +/** Destroy a thread pool. + * @param tp the thread pool handle. + */ +void opj_thread_pool_destroy(opj_thread_pool_t* tp); + +/*@}*/ + +/*@}*/ + +#endif /* THREAD_H */ diff --git a/third_party/libopenjpeg20/tls_keys.h b/third_party/libopenjpeg20/tls_keys.h new file mode 100644 index 0000000000000000000000000000000000000000..23f847541845803136fb2c5ae6bc83da9a463c8b --- /dev/null +++ b/third_party/libopenjpeg20/tls_keys.h @@ -0,0 +1,37 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2016, Even Rouault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OPJ_TLS_KEYS_H +#define OPJ_TLS_KEYS_H + +#define OPJ_TLS_KEY_T1 0 + +#endif /* OPJ_TLS_KEY_H */ diff --git a/third_party/libpng16/0000-build-config.patch b/third_party/libpng16/0000-build-config.patch index 7b7b158f32570899b241991a583b23e09ee50ed3..325b58fe025f844d3d9ead8d9716584f59a8da0a 100644 --- a/third_party/libpng16/0000-build-config.patch +++ b/third_party/libpng16/0000-build-config.patch @@ -5,8 +5,8 @@ diff a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c #include "pngpriv.h" -+void* FXMEM_DefaultAlloc(int byte_size, int); -+void FXMEM_DefaultFree(void* pointer, int); ++void* FXMEM_DefaultAlloc(size_t byte_size); ++void FXMEM_DefaultFree(void* pointer); + #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) /* Free a png_struct */ @@ -16,7 +16,7 @@ diff a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c else #endif - return malloc((size_t)size); /* checked for truncation above */ -+ return FXMEM_DefaultAlloc((int)size, 0); ++ return FXMEM_DefaultAlloc(size); } else @@ -25,19 +25,7 @@ diff a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c #endif /* USER_MEM */ - free(ptr); -+ FXMEM_DefaultFree(ptr, 0); ++ FXMEM_DefaultFree(ptr); } #ifdef PNG_USER_MEM_SUPPORTED -diff a/third_party/libpng16/pngstruct.h b/third_party/libpng16/pngstruct.h ---- a/third_party/libpng16/pngstruct.h -+++ b/third_party/libpng16/pngstruct.h -@@ -27,7 +27,7 @@ - /* We must ensure that zlib uses 'const' in declarations. */ - # define ZLIB_CONST - #endif --#include "zlib.h" -+#include "third_party/zlib_v128/zlib.h" - #ifdef const - /* zlib.h sometimes #defines const to nothing, undo this. */ - # undef const diff --git a/third_party/libpng16/0004-invalid-icc.patch b/third_party/libpng16/0004-invalid-icc.patch new file mode 100644 index 0000000000000000000000000000000000000000..0052c8e0f71d0a7847debb974181d884322de9b6 --- /dev/null +++ b/third_party/libpng16/0004-invalid-icc.patch @@ -0,0 +1,81 @@ +diff --git a/png.c b/png.c +index 35e14f63d..01d8d9bae 100644 +--- a/png.c ++++ b/png.c +@@ -1931,8 +1931,8 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, + static const png_byte D50_nCIEXYZ[12] = + { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; + +-int /* PRIVATE */ +-png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, ++static int /* bool */ ++icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) + { + if (profile_length < 132) +@@ -1942,6 +1942,40 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + return 1; + } + ++#ifdef PNG_READ_iCCP_SUPPORTED ++int /* PRIVATE */ ++png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, ++ png_const_charp name, png_uint_32 profile_length) ++{ ++ if (!icc_check_length(png_ptr, colorspace, name, profile_length)) ++ return 0; ++ ++ /* This needs to be here because the 'normal' check is in ++ * png_decompress_chunk, yet this happens after the attempt to ++ * png_malloc_base the required data. We only need this on read; on write ++ * the caller supplies the profile buffer so libpng doesn't allocate it. See ++ * the call to icc_check_length below (the write case). ++ */ ++# ifdef PNG_SET_USER_LIMITS_SUPPORTED ++ else if (png_ptr->user_chunk_malloc_max > 0 && ++ png_ptr->user_chunk_malloc_max < profile_length) ++ return png_icc_profile_error(png_ptr, colorspace, name, profile_length, ++ "exceeds application limits"); ++# elif PNG_USER_CHUNK_MALLOC_MAX > 0 ++ else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) ++ return png_icc_profile_error(png_ptr, colorspace, name, profile_length, ++ "exceeds libpng limits"); ++# else /* !SET_USER_LIMITS */ ++ /* This will get compiled out on all 32-bit and better systems. */ ++ else if (PNG_SIZE_MAX < profile_length) ++ return png_icc_profile_error(png_ptr, colorspace, name, profile_length, ++ "exceeds system limits"); ++# endif /* !SET_USER_LIMITS */ ++ ++ return 1; ++} ++#endif /* READ_iCCP */ ++ + int /* PRIVATE */ + png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, +@@ -2379,7 +2413,7 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, + if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) + return 0; + +- if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && ++ if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && + png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, + color_type) != 0 && + png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, +diff --git a/pngpriv.h b/pngpriv.h +index 9ea023fea..633671352 100644 +--- a/pngpriv.h ++++ b/pngpriv.h +@@ -1541,9 +1541,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, + /* The 'name' is used for information only */ + + /* Routines for checking parts of an ICC profile. */ ++#ifdef PNG_READ_iCCP_SUPPORTED + PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length), PNG_EMPTY); ++#endif /* READ_iCCP */ + PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, diff --git a/third_party/libpng16/README.pdfium b/third_party/libpng16/README.pdfium index 47af52f8b6876bb9452c829f688a13e860d03313..faa59590c85efbe2474bdf19df459365d92d7022 100644 --- a/third_party/libpng16/README.pdfium +++ b/third_party/libpng16/README.pdfium @@ -18,3 +18,4 @@ pngprefix.h: manually-created redefinitions to avoid conflicts with Chromium. 0000-build-config.patch: Local build configuration changes. 0002-static-png-gt.patch: Unconditionally use static png_gt() in png.c to avoid compilation warning. 0003-check-errors-in-set-pcal.patch: Backported github.com/glennrp/libpng/pull/135 +0004-invalid-icc.patch: Fix for large allocation for invalid ICC https://github.com/glennrp/libpng/commit/92a7c79db2c962d04006b35e2603ba9d5ce75541 diff --git a/third_party/libpng16/png.c b/third_party/libpng16/png.c index 35e14f63d8fffcb5dda0a2993b593c5e810e2d91..01d8d9bae6eabc705554b3ea36ee82ab82062b56 100644 --- a/third_party/libpng16/png.c +++ b/third_party/libpng16/png.c @@ -1931,8 +1931,8 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, static const png_byte D50_nCIEXYZ[12] = { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; -int /* PRIVATE */ -png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, +static int /* bool */ +icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length) { if (profile_length < 132) @@ -1942,6 +1942,40 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, return 1; } +#ifdef PNG_READ_iCCP_SUPPORTED +int /* PRIVATE */ +png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) +{ + if (!icc_check_length(png_ptr, colorspace, name, profile_length)) + return 0; + + /* This needs to be here because the 'normal' check is in + * png_decompress_chunk, yet this happens after the attempt to + * png_malloc_base the required data. We only need this on read; on write + * the caller supplies the profile buffer so libpng doesn't allocate it. See + * the call to icc_check_length below (the write case). + */ +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + else if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds application limits"); +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds libpng limits"); +# else /* !SET_USER_LIMITS */ + /* This will get compiled out on all 32-bit and better systems. */ + else if (PNG_SIZE_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds system limits"); +# endif /* !SET_USER_LIMITS */ + + return 1; +} +#endif /* READ_iCCP */ + int /* PRIVATE */ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, @@ -2379,7 +2413,7 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; - if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && + if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, color_type) != 0 && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, diff --git a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c index b5507134fb492c8522e8948940774340bcf5890c..cf815a6f8881f57c4a8422705099838564f368d1 100644 --- a/third_party/libpng16/pngmem.c +++ b/third_party/libpng16/pngmem.c @@ -19,8 +19,8 @@ #include "pngpriv.h" -void* FXMEM_DefaultAlloc(int byte_size, int); -void FXMEM_DefaultFree(void* pointer, int); +void* FXMEM_DefaultAlloc(size_t byte_size); +void FXMEM_DefaultFree(void* pointer); #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) /* Free a png_struct */ @@ -95,7 +95,7 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), else #endif - return FXMEM_DefaultAlloc((int)size, 0); + return FXMEM_DefaultAlloc(size); } else @@ -252,7 +252,7 @@ png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) return; #endif /* USER_MEM */ - FXMEM_DefaultFree(ptr, 0); + FXMEM_DefaultFree(ptr); } #ifdef PNG_USER_MEM_SUPPORTED diff --git a/third_party/libpng16/pngpriv.h b/third_party/libpng16/pngpriv.h index 9ea023fea7bea2c449e6b22e4108095aa390c4ef..63367135267f0c6e81d4d0062d83bc4eb6fb6b33 100644 --- a/third_party/libpng16/pngpriv.h +++ b/third_party/libpng16/pngpriv.h @@ -1541,9 +1541,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, /* The 'name' is used for information only */ /* Routines for checking parts of an ICC profile. */ +#ifdef PNG_READ_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length), PNG_EMPTY); +#endif /* READ_iCCP */ PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, diff --git a/third_party/libpng16/pngstruct.h b/third_party/libpng16/pngstruct.h index 0b372de4c616df5911e2882b8e045bcd6e8acb58..c1f35edef5c15c5d65a866abbe3620ff48080bb3 100644 --- a/third_party/libpng16/pngstruct.h +++ b/third_party/libpng16/pngstruct.h @@ -27,7 +27,7 @@ /* We must ensure that zlib uses 'const' in declarations. */ # define ZLIB_CONST #endif -#include "third_party/zlib_v128/zlib.h" +#include "zlib.h" #ifdef const /* zlib.h sometimes #defines const to nothing, undo this. */ # undef const diff --git a/third_party/libtiff/0000-build-config.patch b/third_party/libtiff/0000-build-config.patch index 64e86e60ad4a6d75b8009d465e81b57180e7a891..2989607412dcbe50ff4784a83043a73cf0507e7d 100644 --- a/third_party/libtiff/0000-build-config.patch +++ b/third_party/libtiff/0000-build-config.patch @@ -65,34 +65,10 @@ diff a/third_party/libtiff/tif_ojpeg.c b/third_party/libtiff/tif_ojpeg.c typedef struct jpeg_error_mgr jpeg_error_mgr; typedef struct jpeg_common_struct jpeg_common_struct; -diff a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c ---- a/third_party/libtiff/tif_pixarlog.c -+++ b/third_party/libtiff/tif_pixarlog.c -@@ -90,7 +90,7 @@ - */ - - #include "tif_predict.h" --#include "zlib.h" -+#include "../zlib_v128/zlib.h" - - #include <stdio.h> - #include <stdlib.h> -diff a/third_party/libtiff/tif_zip.c b/third_party/libtiff/tif_zip.c ---- a/third_party/libtiff/tif_zip.c -+++ b/third_party/libtiff/tif_zip.c -@@ -47,7 +47,7 @@ - * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz. - */ - #include "tif_predict.h" --#include "zlib.h" -+#include "../zlib_v128/zlib.h" - - #include <stdio.h> - diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h --- /dev/null +++ b/third_party/libtiff/tiffconf.h -@@ -0,0 +1,248 @@ +@@ -0,0 +1,239 @@ +/* libtiff/tiffconf.h. Generated by configure. */ +/* + Configuration defines for installed libtiff. @@ -102,23 +78,13 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + -+#include "core/include/fxcrt/fx_system.h" ++#include "core/fxcrt/fx_system.h" + +//NOTE: The tiff codec requires an ANSI C compiler environment for building and -+// presumes an ANSI C environment for use. -+ -+/* Define to 1 if you have the <fcntl.h> header file. */ -+/* Define to 1 if you have the <sys/types.h> header file. */ -+#if _FX_OS_ == _FX_WIN32_MOBILE_ -+# define O_RDONLY 0x0000 /* open for reading only */ -+# define O_WRONLY 0x0001 /* open for writing only */ -+# define O_RDWR 0x0002 /* open for reading and writing */ -+# define O_CREAT 0x0100 /* create and open file */ -+# define O_TRUNC 0x0200 /* open and truncate */ -+#else ++// presumes an ANSI C environment for use. ++ +# define HAVE_SYS_TYPES_H 1 +# define HAVE_FCNTL_H 1 -+#endif + +/* Compatibility stuff. */ + @@ -134,21 +100,23 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +//fx_system.h already include the string.h in ANSIC + +/* Define to 1 if you have the <search.h> header file. */ -+/*#define HAVE_SEARCH_H 1 */ ++#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ && _MSC_VER >= 1900 ++// search.h is always available in VS 2015 and above, and may be ++// available in earlier versions. ++#define HAVE_SEARCH_H 1 ++#endif + ++static const size_t sizeOfInt = sizeof(int); +/* The size of a `int', as computed by sizeof. */ -+/* According typedef int int32_t; in the fx_system.h*/ -+#define SIZEOF_INT 4 ++#define SIZEOF_INT sizeOfInt + -+/* Sunliang.Liu 20110325. We should config the correct long size for tif -+ fax4decode optimize in tif_fax3.c -- Linux64 decode issue. -+ TESTDOC: Bug #23661 - z1.tif. */ -+#if _FX_CPU_ == _FX_WIN64_ || _FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ ++static const size_t sizeOfULong = sizeof(unsigned long); +/* The size of `unsigned long', as computed by sizeof. */ -+#define SIZEOF_UNSIGNED_LONG 8 -+#else -+#define SIZEOF_UNSIGNED_LONG 4 -+#endif ++#define SIZEOF_UNSIGNED_LONG sizeOfULong ++ ++static const size_t sizeOfVoidP = sizeof(void*); ++/* The size of void* as computed by sizeof. */ ++#define SIZEOF_VOIDP sizeOfVoidP + +/* Signed 8-bit type */ +#define TIFF_INT8_T signed char @@ -174,7 +142,7 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +/* Unsigned 32-bit type formatter */ +#define TIFF_UINT32_FORMAT "%u" + -+#ifdef _MSC_VER // windows ++#ifdef _MSC_VER // windows + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%I64d" @@ -188,9 +156,9 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + -+#else // linux/unix ++#else // linux/unix + -+#if 0 //_FX_CPU_ == _FX_X64_ // linux/unix 64 ++#if 0 //_FX_CPU_ == _FX_X64_ // linux/unix 64 + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%ld" @@ -201,7 +169,7 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +/* Signed 64-bit type */ +#define TIFF_INT64_T signed long + -+#else // linux/unix 32 ++#else // linux/unix 32 + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%lld" @@ -212,7 +180,7 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +/* Signed 64-bit type */ +#define TIFF_INT64_T signed long long + -+#endif // end _FX_CPU_ ++#endif // end _FX_CPU_ + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned long long @@ -295,7 +263,7 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ -+#define OJPEG_SUPPORT 1 ++#define OJPEG_SUPPORT 1 + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 diff --git a/third_party/libtiff/0001-build-config.patch b/third_party/libtiff/0001-build-config.patch deleted file mode 100644 index c393154658d38b17068720a2cf45af43af3f4838..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0001-build-config.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h -index bcc0bc5..ca749da 100644 ---- a/third_party/libtiff/tiffconf.h -+++ b/third_party/libtiff/tiffconf.h -@@ -39,7 +39,11 @@ - //fx_system.h already include the string.h in ANSIC - - /* Define to 1 if you have the <search.h> header file. */ --/*#define HAVE_SEARCH_H 1 */ -+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER >= 1900 -+// search.h is always available in VS 2015 and above, and may be -+// available in earlier versions. -+#define HAVE_SEARCH_H 1 -+#endif - - /* The size of a `int', as computed by sizeof. */ - /* According typedef int int32_t; in the fx_system.h*/ diff --git a/third_party/libtiff/0002-CVE-2015-8665-8683.patch b/third_party/libtiff/0002-CVE-2015-8665-8683.patch deleted file mode 100644 index 0d740e229d421c8e45e21689c6403a2456612249..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0002-CVE-2015-8665-8683.patch +++ /dev/null @@ -1,114 +0,0 @@ -From f94a29a822f5528d2334592760fbb7938f15eb55 Mon Sep 17 00:00:00 2001 -From: erouault <erouault> -Date: Sat, 26 Dec 2015 17:32:03 +0000 -Subject: [PATCH] * libtiff/tif_getimage.c: fix out-of-bound reads in - TIFFRGBAImage interface in case of unsupported values of - SamplesPerPixel/ExtraSamples for LogLUV / CIELab. Add explicit call to - TIFFRGBAImageOK() in TIFFRGBAImageBegin(). Fix CVE-2015-8665 reported by - limingxing and CVE-2015-8683 reported by zzf of Alibaba. - ---- - ChangeLog | 8 ++++++++ - libtiff/tif_getimage.c | 35 ++++++++++++++++++++++------------- - 2 files changed, 30 insertions(+), 13 deletions(-) - -Index: tiff-4.0.3/libtiff/tif_getimage.c -=================================================================== ---- tiff-4.0.3.orig/libtiff/tif_getimage.c 2016-03-23 10:13:42.728371661 -0400 -+++ tiff-4.0.3/libtiff/tif_getimage.c 2016-03-23 10:13:42.724371614 -0400 -@@ -182,20 +182,22 @@ - "Planarconfiguration", td->td_planarconfig); - return (0); - } -- if( td->td_samplesperpixel != 3 ) -+ if( td->td_samplesperpixel != 3 || colorchannels != 3 ) - { - sprintf(emsg, -- "Sorry, can not handle image with %s=%d", -- "Samples/pixel", td->td_samplesperpixel); -+ "Sorry, can not handle image with %s=%d, %s=%d", -+ "Samples/pixel", td->td_samplesperpixel, -+ "colorchannels", colorchannels); - return 0; - } - break; - case PHOTOMETRIC_CIELAB: -- if( td->td_samplesperpixel != 3 || td->td_bitspersample != 8 ) -+ if( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 ) - { - sprintf(emsg, -- "Sorry, can not handle image with %s=%d and %s=%d", -+ "Sorry, can not handle image with %s=%d, %s=%d and %s=%d", - "Samples/pixel", td->td_samplesperpixel, -+ "colorchannels", colorchannels, - "Bits/sample", td->td_bitspersample); - return 0; - } -@@ -255,6 +257,9 @@ - int colorchannels; - uint16 *red_orig, *green_orig, *blue_orig; - int n_color; -+ -+ if( !TIFFRGBAImageOK(tif, emsg) ) -+ return 0; - - /* Initialize to normal values */ - img->row_offset = 0; -@@ -2470,29 +2475,33 @@ - case PHOTOMETRIC_RGB: - switch (img->bitspersample) { - case 8: -- if (img->alpha == EXTRASAMPLE_ASSOCALPHA) -+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA && -+ img->samplesperpixel >= 4) - img->put.contig = putRGBAAcontig8bittile; -- else if (img->alpha == EXTRASAMPLE_UNASSALPHA) -+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA && -+ img->samplesperpixel >= 4) - { - if (BuildMapUaToAa(img)) - img->put.contig = putRGBUAcontig8bittile; - } -- else -+ else if( img->samplesperpixel >= 3 ) - img->put.contig = putRGBcontig8bittile; - break; - case 16: -- if (img->alpha == EXTRASAMPLE_ASSOCALPHA) -+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA && -+ img->samplesperpixel >=4 ) - { - if (BuildMapBitdepth16To8(img)) - img->put.contig = putRGBAAcontig16bittile; - } -- else if (img->alpha == EXTRASAMPLE_UNASSALPHA) -+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA && -+ img->samplesperpixel >=4 ) - { - if (BuildMapBitdepth16To8(img) && - BuildMapUaToAa(img)) - img->put.contig = putRGBUAcontig16bittile; - } -- else -+ else if( img->samplesperpixel >=3 ) - { - if (BuildMapBitdepth16To8(img)) - img->put.contig = putRGBcontig16bittile; -@@ -2501,7 +2510,7 @@ - } - break; - case PHOTOMETRIC_SEPARATED: -- if (buildMap(img)) { -+ if (img->samplesperpixel >=4 && buildMap(img)) { - if (img->bitspersample == 8) { - if (!img->Map) - img->put.contig = putRGBcontig8bitCMYKtile; -@@ -2597,7 +2606,7 @@ - } - break; - case PHOTOMETRIC_CIELAB: -- if (buildMap(img)) { -+ if (img->samplesperpixel == 3 && buildMap(img)) { - if (img->bitspersample == 8) - img->put.contig = initCIELabConversion(img); - break; diff --git a/third_party/libtiff/0003-CVE-2015-8781-8782-8783.patch b/third_party/libtiff/0003-CVE-2015-8781-8782-8783.patch deleted file mode 100644 index c4ed67dfc8ed81c7946bfd1c5d39e8b8ce0f3483..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0003-CVE-2015-8781-8782-8783.patch +++ /dev/null @@ -1,172 +0,0 @@ -From aaab5c3c9d2a2c6984f23ccbc79702610439bc65 Mon Sep 17 00:00:00 2001 -From: erouault <erouault> -Date: Sun, 27 Dec 2015 16:25:11 +0000 -Subject: [PATCH] * libtiff/tif_luv.c: fix potential out-of-bound writes in - decode functions in non debug builds by replacing assert()s by regular if - checks (bugzilla #2522). Fix potential out-of-bound reads in case of short - input data. - ---- - ChangeLog | 7 +++++++ - libtiff/tif_luv.c | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- - 2 files changed, 51 insertions(+), 11 deletions(-) - -Index: tiff-4.0.3/libtiff/tif_luv.c -=================================================================== ---- tiff-4.0.3.orig/libtiff/tif_luv.c 2016-03-23 10:13:56.868540963 -0400 -+++ tiff-4.0.3/libtiff/tif_luv.c 2016-03-23 10:13:56.864540914 -0400 -@@ -202,7 +202,11 @@ - if (sp->user_datafmt == SGILOGDATAFMT_16BIT) - tp = (int16*) op; - else { -- assert(sp->tbuflen >= npixels); -+ if(sp->tbuflen < npixels) { -+ TIFFErrorExt(tif->tif_clientdata, module, -+ "Translation buffer too short"); -+ return (0); -+ } - tp = (int16*) sp->tbuf; - } - _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); -@@ -211,9 +215,11 @@ - cc = tif->tif_rawcc; - /* get each byte string */ - for (shft = 2*8; (shft -= 8) >= 0; ) { -- for (i = 0; i < npixels && cc > 0; ) -+ for (i = 0; i < npixels && cc > 0; ) { - if (*bp >= 128) { /* run */ -- rc = *bp++ + (2-128); /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ -+ if( cc < 2 ) -+ break; -+ rc = *bp++ + (2-128); - b = (int16)(*bp++ << shft); - cc -= 2; - while (rc-- && i < npixels) -@@ -223,6 +229,7 @@ - while (--cc && rc-- && i < npixels) - tp[i++] |= (int16)*bp++ << shft; - } -+ } - if (i != npixels) { - #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, -@@ -268,13 +275,17 @@ - if (sp->user_datafmt == SGILOGDATAFMT_RAW) - tp = (uint32 *)op; - else { -- assert(sp->tbuflen >= npixels); -+ if(sp->tbuflen < npixels) { -+ TIFFErrorExt(tif->tif_clientdata, module, -+ "Translation buffer too short"); -+ return (0); -+ } - tp = (uint32 *) sp->tbuf; - } - /* copy to array of uint32 */ - bp = (unsigned char*) tif->tif_rawcp; - cc = tif->tif_rawcc; -- for (i = 0; i < npixels && cc > 0; i++) { -+ for (i = 0; i < npixels && cc >= 3; i++) { - tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; - bp += 3; - cc -= 3; -@@ -325,7 +336,11 @@ - if (sp->user_datafmt == SGILOGDATAFMT_RAW) - tp = (uint32*) op; - else { -- assert(sp->tbuflen >= npixels); -+ if(sp->tbuflen < npixels) { -+ TIFFErrorExt(tif->tif_clientdata, module, -+ "Translation buffer too short"); -+ return (0); -+ } - tp = (uint32*) sp->tbuf; - } - _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); -@@ -334,11 +349,13 @@ - cc = tif->tif_rawcc; - /* get each byte string */ - for (shft = 4*8; (shft -= 8) >= 0; ) { -- for (i = 0; i < npixels && cc > 0; ) -+ for (i = 0; i < npixels && cc > 0; ) { - if (*bp >= 128) { /* run */ -+ if( cc < 2 ) -+ break; - rc = *bp++ + (2-128); - b = (uint32)*bp++ << shft; -- cc -= 2; /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ -+ cc -= 2; - while (rc-- && i < npixels) - tp[i++] |= b; - } else { /* non-run */ -@@ -346,6 +363,7 @@ - while (--cc && rc-- && i < npixels) - tp[i++] |= (uint32)*bp++ << shft; - } -+ } - if (i != npixels) { - #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, -@@ -407,6 +425,7 @@ - static int - LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) - { -+ static const char module[] = "LogL16Encode"; - LogLuvState* sp = EncoderState(tif); - int shft; - tmsize_t i; -@@ -427,7 +446,11 @@ - tp = (int16*) bp; - else { - tp = (int16*) sp->tbuf; -- assert(sp->tbuflen >= npixels); -+ if(sp->tbuflen < npixels) { -+ TIFFErrorExt(tif->tif_clientdata, module, -+ "Translation buffer too short"); -+ return (0); -+ } - (*sp->tfunc)(sp, bp, npixels); - } - /* compress each byte string */ -@@ -500,6 +523,7 @@ - static int - LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) - { -+ static const char module[] = "LogLuvEncode24"; - LogLuvState* sp = EncoderState(tif); - tmsize_t i; - tmsize_t npixels; -@@ -515,7 +539,11 @@ - tp = (uint32*) bp; - else { - tp = (uint32*) sp->tbuf; -- assert(sp->tbuflen >= npixels); -+ if(sp->tbuflen < npixels) { -+ TIFFErrorExt(tif->tif_clientdata, module, -+ "Translation buffer too short"); -+ return (0); -+ } - (*sp->tfunc)(sp, bp, npixels); - } - /* write out encoded pixels */ -@@ -547,6 +575,7 @@ - static int - LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) - { -+ static const char module[] = "LogLuvEncode32"; - LogLuvState* sp = EncoderState(tif); - int shft; - tmsize_t i; -@@ -568,7 +597,11 @@ - tp = (uint32*) bp; - else { - tp = (uint32*) sp->tbuf; -- assert(sp->tbuflen >= npixels); -+ if(sp->tbuflen < npixels) { -+ TIFFErrorExt(tif->tif_clientdata, module, -+ "Translation buffer too short"); -+ return (0); -+ } - (*sp->tfunc)(sp, bp, npixels); - } - /* compress each byte string */ diff --git a/third_party/libtiff/0004-CVE-2015-8784.patch b/third_party/libtiff/0004-CVE-2015-8784.patch deleted file mode 100644 index e4415de6c1a919fb9259e799b69c64ca69ade152..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0004-CVE-2015-8784.patch +++ /dev/null @@ -1,50 +0,0 @@ -From b18012dae552f85dcc5c57d3bf4e997a15b1cc1c Mon Sep 17 00:00:00 2001 -From: erouault <erouault> -Date: Sun, 27 Dec 2015 16:55:20 +0000 -Subject: [PATCH] * libtiff/tif_next.c: fix potential out-of-bound write in - NeXTDecode() triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif - (bugzilla #2508) - ---- - ChangeLog | 6 ++++++ - libtiff/tif_next.c | 10 ++++++++-- - 2 files changed, 14 insertions(+), 2 deletions(-) - -diff --git a/libtiff/tif_next.c b/libtiff/tif_next.c -index dd669cc..0a5b635 100644 ---- a/libtiff/tif_next.c -+++ b/libtiff/tif_next.c -@@ -37,7 +37,7 @@ - case 0: op[0] = (unsigned char) ((v) << 6); break; \ - case 1: op[0] |= (v) << 4; break; \ - case 2: op[0] |= (v) << 2; break; \ -- case 3: *op++ |= (v); break; \ -+ case 3: *op++ |= (v); op_offset++; break; \ - } \ - } - -@@ -106,6 +106,7 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) - uint32 imagewidth = tif->tif_dir.td_imagewidth; - if( isTiled(tif) ) - imagewidth = tif->tif_dir.td_tilewidth; -+ tmsize_t op_offset = 0; - - /* - * The scanline is composed of a sequence of constant -@@ -122,10 +123,15 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) - * bounds, potentially resulting in a security - * issue. - */ -- while (n-- > 0 && npixels < imagewidth) -+ while (n-- > 0 && npixels < imagewidth && op_offset < scanline) - SETPIXEL(op, grey); - if (npixels >= imagewidth) - break; -+ if (op_offset >= scanline ) { -+ TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld", -+ (long) tif->tif_row); -+ return (0); -+ } - if (cc == 0) - goto bad; - n = *bp++, cc--; diff --git a/third_party/libtiff/0005-Leak-TIFFFetchStripThing.patch b/third_party/libtiff/0005-Leak-TIFFFetchStripThing.patch deleted file mode 100644 index 0f9b16873f302de7e7b06b9f943ce2240bc0b6e1..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0005-Leak-TIFFFetchStripThing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c -index a0dc68b..5ef3264 100644 ---- a/third_party/libtiff/tif_dirread.c -+++ b/third_party/libtiff/tif_dirread.c -@@ -5372,6 +5372,8 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp) - static const char module[] = "TIFFFetchStripThing"; - enum TIFFReadDirEntryErr err; - uint64* data; -+ _TIFFfree(*lpp); -+ *lpp = 0; - err=TIFFReadDirEntryLong8Array(tif,dir,&data); - if (err!=TIFFReadDirEntryErrOk) - { diff --git a/third_party/libtiff/0006-HeapBufferOverflow-ChopUpSingleUncompressedStrip.patch b/third_party/libtiff/0006-HeapBufferOverflow-ChopUpSingleUncompressedStrip.patch index 583f068c95525ef0b29a23bb768eab3d75f78581..5d44fb1cbc4722116f5b5c9547afd394ae0900b5 100644 --- a/third_party/libtiff/0006-HeapBufferOverflow-ChopUpSingleUncompressedStrip.patch +++ b/third_party/libtiff/0006-HeapBufferOverflow-ChopUpSingleUncompressedStrip.patch @@ -1,9 +1,9 @@ -diff --git a/core/fxcodec/codec/fx_codec_tiff.cpp b/core/fxcodec/codec/fx_codec_tiff.cpp +diff --git a/core/fxcodec/codec/ccodec_tiffmodule.cpp b/core/fxcodec/codec/ccodec_tiffmodule.cpp index 09cfea4..20fda63 100644 ---- a/core/fxcodec/codec/fx_codec_tiff.cpp -+++ b/core/fxcodec/codec/fx_codec_tiff.cpp +--- a/core/fxcodec/codec/ccodec_tiffmodule.cpp ++++ b/core/fxcodec/codec/ccodec_tiffmodule.cpp @@ -79,6 +79,10 @@ int _TIFFmemcmp(const void* ptr1, const void* ptr2, tmsize_t size) { - return FXSYS_memcmp(ptr1, ptr2, (size_t)size); + return memcmp(ptr1, ptr2, (size_t)size); } +int _TIFFIfMultiplicationOverflow(tmsize_t op1, tmsize_t op2) { diff --git a/third_party/libtiff/0007-uninitialized-value.patch b/third_party/libtiff/0007-uninitialized-value.patch deleted file mode 100644 index f6e9806181c2247369197b2c6b574fe5fd6ca70e..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0007-uninitialized-value.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c -index 5ef3264..bc41021 100644 ---- a/third_party/libtiff/tif_dirread.c -+++ b/third_party/libtiff/tif_dirread.c -@@ -4443,7 +4443,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, - static const char module[] = "TIFFFetchDirectory"; - - void* origdir; -- uint16 dircount16; -+ uint16 dircount16 = 0; - uint32 dirsize; - TIFFDirEntry* dir; - uint8* ma; diff --git a/third_party/libtiff/0009-HeapBufferOverflow-PixarLogDecode.patch b/third_party/libtiff/0009-HeapBufferOverflow-PixarLogDecode.patch deleted file mode 100644 index 57dbe2efb7209cfaee9721d60c8de8ac52e17b5a..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0009-HeapBufferOverflow-PixarLogDecode.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c -index b93b4c7..0674fa4 100644 ---- a/third_party/libtiff/tif_pixarlog.c -+++ b/third_party/libtiff/tif_pixarlog.c -@@ -457,6 +457,7 @@ horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op, - typedef struct { - TIFFPredictorState predict; - z_stream stream; -+ tmsize_t tbuf_size; /* only set/used on reading for now */ - uint16 *tbuf; - uint16 stride; - int state; -@@ -692,6 +693,7 @@ PixarLogSetupDecode(TIFF* tif) - sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); - if (sp->tbuf == NULL) - return (0); -+ sp->tbuf_size = tbuf_size; - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) - sp->user_datafmt = PixarLogGuessDataFmt(td); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { -@@ -781,6 +783,12 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } -+ /* Check that we will not fill more than what was allocated */ -+ if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size) -+ { -+ TIFFErrorExt(tif->tif_clientdata, module, "sp->stream.avail_out > sp->tbuf_size"); -+ return (0); -+ } - do { - int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); - if (state == Z_STREAM_END) { diff --git a/third_party/libtiff/0010-fix-leak-imagebegin.patch b/third_party/libtiff/0010-fix-leak-imagebegin.patch deleted file mode 100644 index 41aaf91a38533cde468cb43ef5199d7f4137868e..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0010-fix-leak-imagebegin.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c -index 8523793..97fa94d 100644 ---- a/third_party/libtiff/tif_getimage.c -+++ b/third_party/libtiff/tif_getimage.c -@@ -478,10 +478,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) - return 1; - - fail_return: -- _TIFFfree( img->redcmap ); -- _TIFFfree( img->greencmap ); -- _TIFFfree( img->bluecmap ); -- img->redcmap = img->greencmap = img->bluecmap = NULL; -+ TIFFRGBAImageEnd(img); - return 0; - } diff --git a/third_party/libtiff/0011-fix-leak-imagebegin2.patch b/third_party/libtiff/0011-fix-leak-imagebegin2.patch deleted file mode 100644 index 91f82c939e35bca9ba85d14f327842deb6ac3923..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0011-fix-leak-imagebegin2.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c -index 97fa94d..1cf6ac6 100644 ---- a/third_party/libtiff/tif_getimage.c -+++ b/third_party/libtiff/tif_getimage.c -@@ -267,6 +267,13 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) - img->redcmap = NULL; - img->greencmap = NULL; - img->bluecmap = NULL; -+ img->Map = NULL; -+ img->BWmap = NULL; -+ img->PALmap = NULL; -+ img->ycbcr = NULL; -+ img->cielab = NULL; -+ img->UaToAa = NULL; -+ img->Bitdepth16To8 = NULL; - img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */ - - img->tif = tif; -@@ -452,13 +459,6 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) - photoTag, img->photometric); - goto fail_return; - } -- img->Map = NULL; -- img->BWmap = NULL; -- img->PALmap = NULL; -- img->ycbcr = NULL; -- img->cielab = NULL; -- img->UaToAa = NULL; -- img->Bitdepth16To8 = NULL; - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); - TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); -@@ -478,7 +478,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) - return 1; - - fail_return: -- TIFFRGBAImageEnd(img); -+ TIFFRGBAImageEnd( img ); - return 0; - } - \ No newline at end of file diff --git a/third_party/libtiff/0012-initialize-tif-rawdata.patch b/third_party/libtiff/0012-initialize-tif-rawdata.patch deleted file mode 100644 index 2543b89eb01a72ec3f22395c41eac449deb8f26a..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0012-initialize-tif-rawdata.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/third_party/libtiff/tif_read.c b/third_party/libtiff/tif_read.c -index 5cb419bd4..548b1f5ea 100644 ---- a/third_party/libtiff/tif_read.c -+++ b/third_party/libtiff/tif_read.c -@@ -936,6 +936,9 @@ TIFFReadBufferSetup(TIFF* tif, void* bp, tmsize_t size) - return (0); - } - tif->tif_rawdata = (uint8*) _TIFFmalloc(tif->tif_rawdatasize); -+ if (tif->tif_rawdata) -+ memset(tif->tif_rawdata, 0, tif->tif_rawdatasize); -+ - tif->tif_flags |= TIFF_MYBUFFER; - } - if (tif->tif_rawdata == NULL) { diff --git a/third_party/libtiff/0013-validate-refblackwhite.patch b/third_party/libtiff/0013-validate-refblackwhite.patch deleted file mode 100644 index a314fbdc3f1bb09b7dc821acd2e376932ad499bf..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0013-validate-refblackwhite.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/third_party/libtiff/tif_dir.c b/third_party/libtiff/tif_dir.c -index 73212c02d..16ce3d3ce 100644 ---- a/third_party/libtiff/tif_dir.c -+++ b/third_party/libtiff/tif_dir.c -@@ -426,6 +426,14 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) - case TIFFTAG_REFERENCEBLACKWHITE: - /* XXX should check for null range */ - _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); -+ for (int i = 0; i < 6; i++) { -+ if (isnan(td->td_refblackwhite[i])) { -+ if (i % 2 == 0) -+ td->td_refblackwhite[i] = 0; -+ else -+ td->td_refblackwhite[i] = pow(2, td->td_bitspersample) - 1; -+ } -+ } - break; - case TIFFTAG_INKNAMES: - v = (uint16) va_arg(ap, uint16_vap); diff --git a/third_party/libtiff/0014-cast-to-unsigned-in-putagreytile.patch b/third_party/libtiff/0014-cast-to-unsigned-in-putagreytile.patch deleted file mode 100644 index 00336b188c5c95323c4cea1c8ff7a75dbd41fbbf..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0014-cast-to-unsigned-in-putagreytile.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c -index 1cf6ac6b4..2861cdd1e 100644 ---- a/third_party/libtiff/tif_getimage.c -+++ b/third_party/libtiff/tif_getimage.c -@@ -1281,7 +1281,7 @@ DECLAREContigPutFunc(putagreytile) - while (h-- > 0) { - for (x = w; x-- > 0;) - { -- *cp++ = BWmap[*pp][0] & (*(pp+1) << 24 | ~A1); -+ *cp++ = BWmap[*pp][0] & ((uint32)*(pp+1) << 24 | ~A1); - pp += samplesperpixel; - } - cp += toskew; diff --git a/third_party/libtiff/0015-fix-leaks-in-tif_ojpeg.patch b/third_party/libtiff/0015-fix-leaks-in-tif_ojpeg.patch deleted file mode 100644 index e9d3a408bfef490f1433e50b754dd61170b8afd7..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0015-fix-leaks-in-tif_ojpeg.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/third_party/libtiff/tif_ojpeg.c b/third_party/libtiff/tif_ojpeg.c -index cc5449cd6..f69b00148 100644 ---- a/third_party/libtiff/tif_ojpeg.c -+++ b/third_party/libtiff/tif_ojpeg.c -@@ -1790,7 +1790,10 @@ OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif) - TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); - if (p!=64) -+ { -+ _TIFFfree(ob); - return(0); -+ } - sp->qtable[m]=ob; - sp->sof_tq[m]=m; - } -@@ -1854,7 +1857,10 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) - rb[sizeof(uint32)+5+n]=o[n]; - p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); - if (p!=q) -+ { -+ _TIFFfree(rb); - return(0); -+ } - sp->dctable[m]=rb; - sp->sos_tda[m]=(m<<4); - } -@@ -1918,7 +1924,10 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) - rb[sizeof(uint32)+5+n]=o[n]; - p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); - if (p!=q) -+ { -+ _TIFFfree(rb); - return(0); -+ } - sp->actable[m]=rb; - sp->sos_tda[m]=(sp->sos_tda[m]|m); - } diff --git a/third_party/libtiff/0016-fix-leak-in-pixarlogsetupdecode.patch b/third_party/libtiff/0016-fix-leak-in-pixarlogsetupdecode.patch deleted file mode 100644 index c49e676c3485d37511c1d825c4f6c5424c0dc494..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0016-fix-leak-in-pixarlogsetupdecode.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c -index 29535d31e..80006d5b1 100644 ---- a/third_party/libtiff/tif_pixarlog.c -+++ b/third_party/libtiff/tif_pixarlog.c -@@ -697,6 +697,9 @@ PixarLogSetupDecode(TIFF* tif) - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) - sp->user_datafmt = PixarLogGuessDataFmt(td); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { -+ _TIFFfree(sp->tbuf); -+ sp->tbuf = NULL; -+ sp->tbuf_size = 0; - TIFFErrorExt(tif->tif_clientdata, module, - "PixarLog compression can't handle bits depth/data format combination (depth: %d)", - td->td_bitspersample); -@@ -704,6 +707,9 @@ PixarLogSetupDecode(TIFF* tif) - } - - if (inflateInit(&sp->stream) != Z_OK) { -+ _TIFFfree(sp->tbuf); -+ sp->tbuf = NULL; -+ sp->tbuf_size = 0; - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); - return (0); - } else { diff --git a/third_party/libtiff/0017-safe_skews_in_gtTileContig.patch b/third_party/libtiff/0017-safe_skews_in_gtTileContig.patch index 10c5077392d4f2fccb11b7a6125d6ae18130719e..ad6d33daeec445d72f405008172c228d62acb93f 100644 --- a/third_party/libtiff/0017-safe_skews_in_gtTileContig.patch +++ b/third_party/libtiff/0017-safe_skews_in_gtTileContig.patch @@ -1,5 +1,5 @@ diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c -index 2861cdd1e..5ed1b7a37 100644 +index 84cc1d1a7..82e19164e 100644 --- a/third_party/libtiff/tif_getimage.c +++ b/third_party/libtiff/tif_getimage.c @@ -31,6 +31,7 @@ @@ -10,7 +10,7 @@ index 2861cdd1e..5ed1b7a37 100644 static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32); static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); -@@ -612,6 +613,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +@@ -629,6 +628,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 tw, th; unsigned char* buf; int32 fromskew, toskew; @@ -18,22 +18,23 @@ index 2861cdd1e..5ed1b7a37 100644 uint32 nrow; int ret = 1, flip; uint32 this_tw, tocol; -@@ -631,19 +633,37 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +@@ -649,19 +647,37 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) flip = setorientation(img); if (flip & FLIP_VERTICALLY) { - y = h - 1; -- toskew = -(int32)(tw + w); -+ safeskew = 0; -+ safeskew -= tw; -+ safeskew -= w; + y = h - 1; +- toskew = -(int32)(tw + w); ++ safeskew = 0; ++ safeskew -= tw; ++ safeskew -= w; } else { - y = 0; -- toskew = -(int32)(tw - w); -+ safeskew = 0; -+ safeskew -= tw; -+ safeskew +=w; + y = 0; +- toskew = -(int32)(tw - w); ++ safeskew = 0; ++ safeskew -= tw; ++ safeskew +=w; } + + if(safeskew > INT_MAX || safeskew < INT_MIN){ + _TIFFfree(buf); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); @@ -41,9 +42,8 @@ index 2861cdd1e..5ed1b7a37 100644 + } + toskew = safeskew; + - /* - * Leftmost tile is clipped on left side if col_offset > 0. + * Leftmost tile is clipped on left side if col_offset > 0. */ leftmost_fromskew = img->col_offset % tw; leftmost_tw = tw - leftmost_fromskew; @@ -59,30 +59,30 @@ index 2861cdd1e..5ed1b7a37 100644 for (row = 0; row < h; row += nrow) { rowstoread = th - (row + img->row_offset) % th; -@@ -668,9 +688,24 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) - /* - * Rightmost tile is clipped on right side. - */ -- fromskew = tw - (w - tocol); -+ safeskew = tw; -+ safeskew -= w; -+ safeskew += tocol; -+ if(safeskew > INT_MAX || safeskew < INT_MIN){ -+ _TIFFfree(buf); -+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); -+ return (0); -+ } -+ fromskew = safeskew; - this_tw = tw - fromskew; -- this_toskew = toskew + fromskew; -+ safeskew = toskew; -+ safeskew += fromskew; -+ if(safeskew > INT_MAX || safeskew < INT_MIN){ -+ _TIFFfree(buf); -+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); -+ return (0); -+ } -+ this_toskew = safeskew; - } - (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos); - tocol += this_tw; +@@ -704,9 +684,24 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + /* + * Rightmost tile is clipped on right side. + */ +- fromskew = tw - (w - tocol); ++ safeskew = tw; ++ safeskew -= w; ++ safeskew += tocol; ++ if(safeskew > INT_MAX || safeskew < INT_MIN){ ++ _TIFFfree(buf); ++ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); ++ return (0); ++ } ++ fromskew = safeskew; + this_tw = tw - fromskew; +- this_toskew = toskew + fromskew; ++ safeskew = toskew; ++ safeskew += fromskew; ++ if(safeskew > INT_MAX || safeskew < INT_MIN){ ++ _TIFFfree(buf); ++ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); ++ return (0); ++ } ++ this_toskew = safeskew; + } + (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos); + tocol += this_tw; diff --git a/third_party/libtiff/0018-fix-leak-in-PredictorSetupDecode.patch b/third_party/libtiff/0018-fix-leak-in-PredictorSetupDecode.patch deleted file mode 100644 index a18df77409698963e78c119116db8e1cc44db5c8..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0018-fix-leak-in-PredictorSetupDecode.patch +++ /dev/null @@ -1,39 +0,0 @@ -diff --git a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c -index 80006d5b1..29535d31e 100644 ---- a/third_party/libtiff/tif_pixarlog.c -+++ b/third_party/libtiff/tif_pixarlog.c -@@ -697,9 +697,6 @@ PixarLogSetupDecode(TIFF* tif) - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) - sp->user_datafmt = PixarLogGuessDataFmt(td); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { -- _TIFFfree(sp->tbuf); -- sp->tbuf = NULL; -- sp->tbuf_size = 0; - TIFFErrorExt(tif->tif_clientdata, module, - "PixarLog compression can't handle bits depth/data format combination (depth: %d)", - td->td_bitspersample); -@@ -707,9 +704,6 @@ PixarLogSetupDecode(TIFF* tif) - } - - if (inflateInit(&sp->stream) != Z_OK) { -- _TIFFfree(sp->tbuf); -- sp->tbuf = NULL; -- sp->tbuf_size = 0; - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); - return (0); - } else { -diff --git a/third_party/libtiff/tif_predict.c b/third_party/libtiff/tif_predict.c -index 1388dde59..8975672ae 100644 ---- a/third_party/libtiff/tif_predict.c -+++ b/third_party/libtiff/tif_predict.c -@@ -109,7 +109,10 @@ PredictorSetupDecode(TIFF* tif) - TIFFDirectory* td = &tif->tif_dir; - - if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) -+ { -+ (*tif->tif_cleanup)(tif); - return 0; -+ } - - if (sp->predictor == 2) { - switch (td->td_bitspersample) { diff --git a/third_party/libtiff/0019-fix-invalid-reads-TIFFFetchNormalTag.patch b/third_party/libtiff/0019-fix-invalid-reads-TIFFFetchNormalTag.patch deleted file mode 100644 index 9ebb7ef8db98ece6d26b6bd05862d8c378cb3bb6..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0019-fix-invalid-reads-TIFFFetchNormalTag.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c -index bc4102184..0e3f8ccd4 100644 ---- a/third_party/libtiff/tif_dirread.c -+++ b/third_party/libtiff/tif_dirread.c -@@ -4983,6 +4983,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) - if (err==TIFFReadDirEntryErrOk) - { - int m; -+ if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) -+ { -+ TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); -+ data[dp->tdir_count-1] = '\0'; -+ } - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); -@@ -5155,6 +5160,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) - if (err==TIFFReadDirEntryErrOk) - { - int m; -+ if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) -+ { -+ TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); -+ data[dp->tdir_count-1] = '\0'; -+ } - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); diff --git a/third_party/libtiff/0020-unreasonable-td-bitspersample.patch b/third_party/libtiff/0020-unreasonable-td-bitspersample.patch deleted file mode 100644 index 1ad5e34e3c2a76a60a8dcf1fce0bfe16c66dbd44..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0020-unreasonable-td-bitspersample.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c -index 0e3f8ccd4..e0403aef3 100644 ---- a/third_party/libtiff/tif_dirread.c -+++ b/third_party/libtiff/tif_dirread.c -@@ -3754,6 +3754,17 @@ TIFFReadDirectory(TIFF* tif) - fip ? fip->field_name : "unknown tagname"); - continue; - } -+ /* ColorMap or TransferFunction for high bit */ -+ /* depths do not make much sense and could be */ -+ /* used as a denial of service vector */ -+ if (tif->tif_dir.td_bitspersample > 24) -+ { -+ TIFFWarningExt(tif->tif_clientdata,module, -+ "Ignoring %s because BitsPerSample=%d>24", -+ fip ? fip->field_name : "unknown tagname", -+ tif->tif_dir.td_bitspersample); -+ continue; -+ } - countpersample=(1L<<tif->tif_dir.td_bitspersample); - if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) - { diff --git a/third_party/libtiff/0021-fix-leaks-ojpegreaderinfosectables.patch b/third_party/libtiff/0021-fix-leaks-ojpegreaderinfosectables.patch deleted file mode 100644 index e3b4bd8964037337970289bbda8bb07c158c5d7c..0000000000000000000000000000000000000000 --- a/third_party/libtiff/0021-fix-leaks-ojpegreaderinfosectables.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/third_party/libtiff/tif_ojpeg.c b/third_party/libtiff/tif_ojpeg.c -index f69b00148..276d562df 100644 ---- a/third_party/libtiff/tif_ojpeg.c -+++ b/third_party/libtiff/tif_ojpeg.c -@@ -1794,6 +1794,8 @@ OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif) - _TIFFfree(ob); - return(0); - } -+ if (sp->qtable[m]!=0) -+ _TIFFfree(sp->qtable[m]); - sp->qtable[m]=ob; - sp->sof_tq[m]=m; - } -@@ -1861,6 +1863,8 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) - _TIFFfree(rb); - return(0); - } -+ if (sp->dctable[m]!=0) -+ _TIFFfree(sp->dctable[m]); - sp->dctable[m]=rb; - sp->sos_tda[m]=(m<<4); - } -@@ -1928,6 +1932,8 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) - _TIFFfree(rb); - return(0); - } -+ if (sp->actable[m]) -+ _TIFFfree(sp->actable[m]); - sp->actable[m]=rb; - sp->sos_tda[m]=(sp->sos_tda[m]|m); - } diff --git a/third_party/libtiff/0025-upstream-OOM-gtTileContig.patch b/third_party/libtiff/0025-upstream-OOM-gtTileContig.patch new file mode 100644 index 0000000000000000000000000000000000000000..d4d3d7028fc5901a1a6590ec9f76ad15611e6dfc --- /dev/null +++ b/third_party/libtiff/0025-upstream-OOM-gtTileContig.patch @@ -0,0 +1,460 @@ +diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c +index 53c938a89..03c9a81fb 100644 +--- a/third_party/libtiff/tif_getimage.c ++++ b/third_party/libtiff/tif_getimage.c +@@ -627,7 +627,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + uint32 col, row, y, rowstoread; + tmsize_t pos; + uint32 tw, th; +- unsigned char* buf; ++ unsigned char* buf = NULL; + int32 fromskew, toskew; + int64 safeskew; + uint32 nrow; +@@ -636,13 +636,14 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + int32 this_toskew, leftmost_toskew; + int32 leftmost_fromskew; + uint32 leftmost_tw; ++ tmsize_t bufsize; + +- buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); +- if (buf == 0) { +- TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); +- return (0); ++ bufsize = TIFFTileSize(tif); ++ if (bufsize == 0) { ++ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); ++ return (0); + } +- _TIFFmemset(buf, 0, TIFFTileSize(tif)); ++ + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + +@@ -691,8 +692,9 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + col = img->col_offset; + while (tocol < w) + { +- if (TIFFReadTile(tif, buf, col, +- row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr) ++ if (_TIFFReadTileAndAllocBuffer(tif, (void**) &buf, bufsize, col, ++ row+img->row_offset, 0, 0)==(tmsize_t)(-1) && ++ (buf == NULL || img->stoponerr)) + { + ret = 0; + break; +@@ -772,11 +774,11 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + uint32 col, row, y, rowstoread; + tmsize_t pos; + uint32 tw, th; +- unsigned char* buf; +- unsigned char* p0; +- unsigned char* p1; +- unsigned char* p2; +- unsigned char* pa; ++ unsigned char* buf = NULL; ++ unsigned char* p0 = NULL; ++ unsigned char* p1 = NULL; ++ unsigned char* p2 = NULL; ++ unsigned char* pa = NULL; + tmsize_t tilesize; + tmsize_t bufsize; + int32 fromskew, toskew; +@@ -795,16 +797,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate"); + return (0); + } +- buf = (unsigned char*) _TIFFmalloc(bufsize); +- if (buf == 0) { +- TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); +- return (0); +- } +- _TIFFmemset(buf, 0, bufsize); +- p0 = buf; +- p1 = p0 + tilesize; +- p2 = p1 + tilesize; +- pa = (alpha?(p2+tilesize):NULL); ++ + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + +@@ -824,7 +817,6 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_PALETTE: + colorchannels = 1; +- p2 = p1 = p0; + break; + + default: +@@ -849,7 +841,30 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + col = img->col_offset; + while (tocol < w) + { +- if (TIFFReadTile(tif, p0, col, ++ if( buf == NULL ) ++ { ++ if (_TIFFReadTileAndAllocBuffer( ++ tif, (void**) &buf, bufsize, col, ++ row+img->row_offset,0,0)==(tmsize_t)(-1) ++ && (buf == NULL || img->stoponerr)) ++ { ++ ret = 0; ++ break; ++ } ++ p0 = buf; ++ if( colorchannels == 1 ) ++ { ++ p2 = p1 = p0; ++ pa = (alpha?(p0+3*tilesize):NULL); ++ } ++ else ++ { ++ p1 = p0 + tilesize; ++ p2 = p1 + tilesize; ++ pa = (alpha?(p2+tilesize):NULL); ++ } ++ } ++ else if (TIFFReadTile(tif, p0, col, + row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr) + { + ret = 0; +@@ -940,13 +955,14 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + tileContigRoutine put = img->put.contig; + uint32 row, y, nrow, nrowsub, rowstoread; + tmsize_t pos; +- unsigned char* buf; ++ unsigned char* buf = NULL; + uint32 rowsperstrip; + uint16 subsamplinghor,subsamplingver; + uint32 imagewidth = img->width; + tmsize_t scanline; + int32 fromskew, toskew; + int ret = 1, flip; ++ tmsize_t maxstripsize; + + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); + if( subsamplingver == 0 ) { +@@ -954,12 +970,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + return (0); + } + +- buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); +- if (buf == 0) { +- TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); +- return (0); +- } +- _TIFFmemset(buf, 0, TIFFStripSize(tif)); ++ maxstripsize = TIFFStripSize(tif); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { +@@ -981,11 +992,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + nrowsub = nrow; + if ((nrowsub%subsamplingver)!=0) + nrowsub+=subsamplingver-nrowsub%subsamplingver; +- if (TIFFReadEncodedStrip(tif, ++ if (_TIFFReadEncodedStripAndAllocBuffer(tif, + TIFFComputeStrip(tif,row+img->row_offset, 0), +- buf, ++ (void**)(&buf), ++ maxstripsize, + ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) +- && img->stoponerr) ++ && (buf == NULL || img->stoponerr)) + { + ret = 0; + break; +@@ -1029,8 +1041,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + { + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; +- unsigned char *buf; +- unsigned char *p0, *p1, *p2, *pa; ++ unsigned char *buf = NULL; ++ unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL; + uint32 row, y, nrow, rowstoread; + tmsize_t pos; + tmsize_t scanline; +@@ -1049,15 +1061,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate"); + return (0); + } +- p0 = buf = (unsigned char *)_TIFFmalloc(bufsize); +- if (buf == 0) { +- TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); +- return (0); +- } +- _TIFFmemset(buf, 0, bufsize); +- p1 = p0 + stripsize; +- p2 = p1 + stripsize; +- pa = (alpha?(p2+stripsize):NULL); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { +@@ -1075,7 +1078,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_PALETTE: + colorchannels = 1; +- p2 = p1 = p0; + break; + + default: +@@ -1091,7 +1093,31 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + offset_row = row + img->row_offset; +- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), ++ if( buf == NULL ) ++ { ++ if (_TIFFReadEncodedStripAndAllocBuffer( ++ tif, TIFFComputeStrip(tif, offset_row, 0), ++ (void**) &buf, bufsize, ++ ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) ++ && (buf == NULL || img->stoponerr)) ++ { ++ ret = 0; ++ break; ++ } ++ p0 = buf; ++ if( colorchannels == 1 ) ++ { ++ p2 = p1 = p0; ++ pa = (alpha?(p0+3*stripsize):NULL); ++ } ++ else ++ { ++ p1 = p0 + stripsize; ++ p2 = p1 + stripsize; ++ pa = (alpha?(p2+stripsize):NULL); ++ } ++ } ++ else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), + p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) + && img->stoponerr) + { +diff --git a/third_party/libtiff/tif_read.c b/third_party/libtiff/tif_read.c +index cc4f5d2f6..ad0a778c0 100644 +--- a/third_party/libtiff/tif_read.c ++++ b/third_party/libtiff/tif_read.c +@@ -442,18 +442,17 @@ TIFFReadScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) + } + + /* +- * Read a strip of data and decompress the specified +- * amount into the user-supplied buffer. ++ * Calculate the strip size according to the number of ++ * rows in the strip (check for truncated last strip on any ++ * of the separations). + */ +-tmsize_t +-TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) ++static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF* tif, uint32 strip, uint16* pplane) + { + static const char module[] = "TIFFReadEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + uint32 rowsperstrip; + uint32 stripsperplane; + uint32 stripinplane; +- uint16 plane; + uint32 rows; + tmsize_t stripsize; + if (!TIFFCheckRead(tif,0)) +@@ -465,23 +464,37 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) + (unsigned long)td->td_nstrips); + return((tmsize_t)(-1)); + } +- /* +- * Calculate the strip size according to the number of +- * rows in the strip (check for truncated last strip on any +- * of the separations). +- */ ++ + rowsperstrip=td->td_rowsperstrip; + if (rowsperstrip>td->td_imagelength) + rowsperstrip=td->td_imagelength; + stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); + stripinplane=(strip%stripsperplane); +- plane=(uint16)(strip/stripsperplane); ++ if( pplane ) *pplane=(uint16)(strip/stripsperplane); + rows=td->td_imagelength-stripinplane*rowsperstrip; + if (rows>rowsperstrip) + rows=rowsperstrip; + stripsize=TIFFVStripSize(tif,rows); + if (stripsize==0) + return((tmsize_t)(-1)); ++ return stripsize; ++} ++ ++/* ++ * Read a strip of data and decompress the specified ++ * amount into the user-supplied buffer. ++ */ ++tmsize_t ++TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) ++{ ++ static const char module[] = "TIFFReadEncodedStrip"; ++ TIFFDirectory *td = &tif->tif_dir; ++ tmsize_t stripsize; ++ uint16 plane; ++ ++ stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); ++ if (stripsize==((tmsize_t)(-1))) ++ return((tmsize_t)(-1)); + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE && +@@ -510,6 +523,50 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) + return(stripsize); + } + ++/* Variant of TIFFReadEncodedStrip() that does ++ * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillStrip() has ++ * suceeded. This avoid excessive memory allocation in case of truncated ++ * file. ++ * * calls regular TIFFReadEncodedStrip() if *buf != NULL ++ */ ++tmsize_t ++_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, ++ void **buf, tmsize_t bufsizetoalloc, ++ tmsize_t size_to_read) ++{ ++ tmsize_t this_stripsize; ++ uint16 plane; ++ ++ if( *buf != NULL ) ++ { ++ return TIFFReadEncodedStrip(tif, strip, *buf, size_to_read); ++ } ++ ++ this_stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); ++ if (this_stripsize==((tmsize_t)(-1))) ++ return((tmsize_t)(-1)); ++ ++ if ((size_to_read!=(tmsize_t)(-1))&&(size_to_read<this_stripsize)) ++ this_stripsize=size_to_read; ++ if (!TIFFFillStrip(tif,strip)) ++ return((tmsize_t)(-1)); ++ ++ *buf = _TIFFmalloc(bufsizetoalloc); ++ if (*buf == NULL) { ++ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); ++ return((tmsize_t)(-1)); ++ } ++ _TIFFmemset(*buf, 0, bufsizetoalloc); ++ ++ if ((*tif->tif_decodestrip)(tif,*buf,this_stripsize,plane)<=0) ++ return((tmsize_t)(-1)); ++ (*tif->tif_postdecode)(tif,*buf,this_stripsize); ++ return(this_stripsize); ++ ++ ++} ++ ++ + static tmsize_t + TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, + const char* module) +@@ -939,6 +996,78 @@ TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) + return ((tmsize_t)(-1)); + } + ++/* Variant of TIFFReadTile() that does ++ * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has ++ * suceeded. This avoid excessive memory allocation in case of truncated ++ * file. ++ * * calls regular TIFFReadEncodedTile() if *buf != NULL ++ */ ++tmsize_t ++_TIFFReadTileAndAllocBuffer(TIFF* tif, ++ void **buf, tmsize_t bufsizetoalloc, ++ uint32 x, uint32 y, uint32 z, uint16 s) ++{ ++ if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) ++ return ((tmsize_t)(-1)); ++ return (_TIFFReadEncodedTileAndAllocBuffer(tif, ++ TIFFComputeTile(tif, x, y, z, s), ++ buf, bufsizetoalloc, ++ (tmsize_t)(-1))); ++} ++ ++/* Variant of TIFFReadEncodedTile() that does ++ * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has ++ * suceeded. This avoid excessive memory allocation in case of truncated ++ * file. ++ * * calls regular TIFFReadEncodedTile() if *buf != NULL ++ */ ++tmsize_t ++_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, ++ void **buf, tmsize_t bufsizetoalloc, ++ tmsize_t size_to_read) ++{ ++ static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; ++ TIFFDirectory *td = &tif->tif_dir; ++ tmsize_t tilesize = tif->tif_tilesize; ++ ++ if( *buf != NULL ) ++ { ++ return TIFFReadEncodedTile(tif, tile, *buf, size_to_read); ++ } ++ ++ if (!TIFFCheckRead(tif, 1)) ++ return ((tmsize_t)(-1)); ++ if (tile >= td->td_nstrips) { ++ TIFFErrorExt(tif->tif_clientdata, module, ++ "%lu: Tile out of range, max %lu", ++ (unsigned long) tile, (unsigned long) td->td_nstrips); ++ return ((tmsize_t)(-1)); ++ } ++ ++ if (!TIFFFillTile(tif,tile)) ++ return((tmsize_t)(-1)); ++ ++ *buf = _TIFFmalloc(bufsizetoalloc); ++ if (*buf == NULL) { ++ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), ++ "No space for tile buffer"); ++ return((tmsize_t)(-1)); ++ } ++ _TIFFmemset(*buf, 0, bufsizetoalloc); ++ ++ if (size_to_read == (tmsize_t)(-1)) ++ size_to_read = tilesize; ++ else if (size_to_read > tilesize) ++ size_to_read = tilesize; ++ if( (*tif->tif_decodetile)(tif, ++ (uint8*) *buf, size_to_read, (uint16)(tile/td->td_stripsperimage))) { ++ (*tif->tif_postdecode)(tif, (uint8*) *buf, size_to_read); ++ return (size_to_read); ++ } else ++ return ((tmsize_t)(-1)); ++} ++ ++ + static tmsize_t + TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) + { +diff --git a/third_party/libtiff/tiffiop.h b/third_party/libtiff/tiffiop.h +index 7e415c750..6fb47de5b 100644 +--- a/third_party/libtiff/tiffiop.h ++++ b/third_party/libtiff/tiffiop.h +@@ -364,6 +364,20 @@ extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); + extern double _TIFFUInt64ToDouble(uint64); + extern float _TIFFUInt64ToFloat(uint64); + ++extern tmsize_t ++_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, ++ void **buf, tmsize_t bufsizetoalloc, ++ tmsize_t size_to_read); ++extern tmsize_t ++_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, ++ void **buf, tmsize_t bufsizetoalloc, ++ tmsize_t size_to_read); ++extern tmsize_t ++_TIFFReadTileAndAllocBuffer(TIFF* tif, ++ void **buf, tmsize_t bufsizetoalloc, ++ uint32 x, uint32 y, uint32 z, uint16 s); ++ ++ + extern int TIFFInitDumpMode(TIFF*, int); + #ifdef PACKBITS_SUPPORT + extern int TIFFInitPackBits(TIFF*, int); diff --git a/third_party/libtiff/0026-upstream-null-dereference.patch b/third_party/libtiff/0026-upstream-null-dereference.patch new file mode 100644 index 0000000000000000000000000000000000000000..052645ff8a7ba8f7df5715217a1cc7c05f122ad4 --- /dev/null +++ b/third_party/libtiff/0026-upstream-null-dereference.patch @@ -0,0 +1,22 @@ +diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c +index 03c9a81fb..d37f729c4 100644 +--- a/third_party/libtiff/tif_getimage.c ++++ b/third_party/libtiff/tif_getimage.c +@@ -681,7 +681,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + return (0); + } + leftmost_toskew = safeskew; +- for (row = 0; row < h; row += nrow) ++ for (row = 0; ret != 0 && row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); +@@ -830,7 +830,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) + leftmost_fromskew = img->col_offset % tw; + leftmost_tw = tw - leftmost_fromskew; + leftmost_toskew = toskew + leftmost_fromskew; +- for (row = 0; row < h; row += nrow) ++ for (row = 0; ret != 0 && row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); diff --git a/third_party/libtiff/0027-build-config.patch b/third_party/libtiff/0027-build-config.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec1a205574f5309c4798d0650541943b6ddff6cb --- /dev/null +++ b/third_party/libtiff/0027-build-config.patch @@ -0,0 +1,40 @@ +diff --git a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h +index 2a88cb75f..4d2d7c9d9 100644 +--- a/third_party/libtiff/tiffconf.h ++++ b/third_party/libtiff/tiffconf.h +@@ -35,17 +35,26 @@ + #define HAVE_SEARCH_H 1 + #endif + +-static const size_t sizeOfInt = sizeof(int); +-/* The size of a `int', as computed by sizeof. */ +-#define SIZEOF_INT sizeOfInt +- +-static const size_t sizeOfULong = sizeof(unsigned long); ++/* The size of a `int'. */ ++/* According typedef int int32_t; in the fx_system.h*/ ++#define SIZEOF_INT 4 ++ ++/* Sunliang.Liu 20110325. We should config the correct long size for tif ++ fax4decode optimize in tif_fax3.c -- Linux64 decode issue. ++ TESTDOC: Bug #23661 - z1.tif. */ ++#if _FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ + /* The size of `unsigned long', as computed by sizeof. */ +-#define SIZEOF_UNSIGNED_LONG sizeOfULong ++#define SIZEOF_UNSIGNED_LONG 8 ++#else ++#define SIZEOF_UNSIGNED_LONG 4 ++#endif + +-static const size_t sizeOfVoidP = sizeof(void*); +-/* The size of void* as computed by sizeof. */ +-#define SIZEOF_VOIDP sizeOfVoidP ++/* The size of void*. */ ++#ifdef __LP64__ ++#define SIZEOF_VOIDP 8 ++#else ++#define SIZEOF_VOIDP 4 ++#endif + + /* Signed 8-bit type */ + #define TIFF_INT8_T signed char diff --git a/third_party/libtiff/0028-nstrips-OOM.patch b/third_party/libtiff/0028-nstrips-OOM.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6db66ee8863e8921dc7a90245f5566a7ce91c43 --- /dev/null +++ b/third_party/libtiff/0028-nstrips-OOM.patch @@ -0,0 +1,26 @@ +diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c +index 772ebaf7d..ab938eac9 100644 +--- a/third_party/libtiff/tif_dirread.c ++++ b/third_party/libtiff/tif_dirread.c +@@ -41,6 +41,7 @@ + + #include "tiffiop.h" + #include <float.h> ++#include <limits.h> + + #define IGNORE 0 /* tag placeholder used below */ + #define FAILED_FII ((uint32) -1) +@@ -3638,6 +3639,13 @@ TIFFReadDirectory(TIFF* tif) + isTiled(tif) ? "tiles" : "strips"); + goto bad; + } ++ if (tif->tif_dir.td_nstrips > INT_MAX) { ++ TIFFErrorExt(tif->tif_clientdata, module, ++ "Cannot handle %u number of %s", ++ tif->tif_dir.td_nstrips, ++ isTiled(tif) ? "tiles" : "strips"); ++ goto bad; ++ } + tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips; + if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE) + tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel; diff --git a/third_party/libtiff/README.pdfium b/third_party/libtiff/README.pdfium index e4436d21fdc2f52fbc9863c70bdde61710812596..a370a49ce767582a2d034a324d5851ef5e06c1a6 100644 --- a/third_party/libtiff/README.pdfium +++ b/third_party/libtiff/README.pdfium @@ -1,6 +1,6 @@ Name: LibTIFF -URL: http://www.remotesensing.org/libtiff/ -Version: 4.0.6 +URL: http://www.simplesystems.org/libtiff/ +Version: 4.0.8 Security Critical: yes License: BSD @@ -11,23 +11,10 @@ Local Modifications: 0000-build-config.patch: Local build configuration changes. 0001-build-config.patch: Enable HAVE_SEARCH_H in tiffconf.h for VS 2015 -0002-CVE-2015-8665-8683.patch: Security fixes -0003-CVE-2015-8781-8782-8783.patch: Security fixes -0004-CVE-2015-8784.patch: Security fixes -0005-Leak-TIFFFetchStripThing.patch: Fix a memory leak 0006-HeapBufferOverflow-ChopUpSingleUncompressedStrip.patch: Fix a heap buffer overflow -0007-uninitialized-value.patch: Fix potentially uninitialized dircount value 0008-HeapBufferOverflow-ChopUpSingleUncompressedStrip.patch: Fix a heap buffer overflow -0009-HeapBufferOverflow-PixarLogDecode.patch: Fix a heap buffer overflow -0010-fix-leak-imagebegin: Fix a leak when TIFFRGBAImageBegin fails -0011-fix-leak-imagebegin2: Apply upstream fix related to our previous patch -0012-initialize-tif-rawdata.patch: Initialize tif_rawdata to guard against unitialized access -0013-validate-refblackwhite.patch: Make sure the refblackwhite values aren't nan. -0014-cast-to-unsigned-in-putagreytile.patch: casting to avoid undefined shifts. -0015-fix-leaks-in-tif_ojpeg.patch: fix direct leaks in tif_ojpeg.c methods -0016-fix-leak-in-pixarlogsetupdecode.patch: Free sp->tbuf if setup fails 0017-safe_skews_in_gtTileContig.patch: return error if to/from skews overflow from int32. -0018-fix-leak-in-PredictorSetupDecode.patch: call tif->tif_cleanup if the setup fails. -0019-fix-invalid-reads-TIFFFetchNormalTag.patch: upstream security fix in tif_dirread. -0020-unreasonable-td-bitspersample.patch: upstream patch ignoring large td_bitspersample. -0021-fix-leaks-ojpegreaderinfosectables.patch: more direct leak fixes in tif_ojpeg.c. +0025-upstream-OOM-gtTileContig: allocates the decoded buffer only after a first successful TIFFFillStrip. +0026-upstream-null-dereference: properly evit when stoponerr is set and avoid null dereferences. +0027-build-config.patch: #define variables so their value can be used by #if. +0028-nstrips-OOM.patch: return error for excess number of tiles/strips. diff --git a/third_party/libtiff/tif_aux.c b/third_party/libtiff/tif_aux.c index bc4ea0192815137f2d55031e70fbd0ee2d130d9e..74532c8c6fbe207993aff6b312bcb0c8c33fcd4e 100644 --- a/third_party/libtiff/tif_aux.c +++ b/third_party/libtiff/tif_aux.c @@ -1,4 +1,4 @@ -/* $Id: tif_aux.c,v 1.26 2010-07-01 15:33:28 dron Exp $ */ +/* $Id: tif_aux.c,v 1.29 2016-11-11 20:45:53 erouault Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler @@ -100,7 +100,8 @@ TIFFDefaultTransferFunction(TIFFDirectory* td) n = ((tmsize_t)1)<<td->td_bitspersample; nbytes = n * sizeof (uint16); - if (!(tf[0] = (uint16 *)_TIFFmalloc(nbytes))) + tf[0] = (uint16 *)_TIFFmalloc(nbytes); + if (tf[0] == NULL) return 0; tf[0][0] = 0; for (i = 1; i < n; i++) { @@ -109,10 +110,12 @@ TIFFDefaultTransferFunction(TIFFDirectory* td) } if (td->td_samplesperpixel - td->td_extrasamples > 1) { - if (!(tf[1] = (uint16 *)_TIFFmalloc(nbytes))) + tf[1] = (uint16 *)_TIFFmalloc(nbytes); + if(tf[1] == NULL) goto bad; _TIFFmemcpy(tf[1], tf[0], nbytes); - if (!(tf[2] = (uint16 *)_TIFFmalloc(nbytes))) + tf[2] = (uint16 *)_TIFFmalloc(nbytes); + if (tf[2] == NULL) goto bad; _TIFFmemcpy(tf[2], tf[0], nbytes); } @@ -134,7 +137,8 @@ TIFFDefaultRefBlackWhite(TIFFDirectory* td) { int i; - if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)))) + td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)); + if (td->td_refblackwhite == NULL) return 0; if (td->td_photometric == PHOTOMETRIC_YCBCR) { /* @@ -163,7 +167,7 @@ TIFFDefaultRefBlackWhite(TIFFDirectory* td) * value if the tag is not present in the directory. * * NB: We use the value in the directory, rather than - * explcit values so that defaults exist only one + * explicit values so that defaults exist only one * place in the library -- in TIFFDefaultDirectory. */ int @@ -208,11 +212,18 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap) *va_arg(ap, uint16 *) = td->td_resolutionunit; return (1); case TIFFTAG_PREDICTOR: - { - TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data; - *va_arg(ap, uint16*) = (uint16) sp->predictor; - return 1; - } + { + TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data; + if( sp == NULL ) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot get \"Predictor\" tag as plugin is not configured"); + *va_arg(ap, uint16*) = 0; + return 0; + } + *va_arg(ap, uint16*) = (uint16) sp->predictor; + return 1; + } case TIFFTAG_DOTRANGE: *va_arg(ap, uint16 *) = 0; *va_arg(ap, uint16 *) = (1<<td->td_bitspersample)-1; diff --git a/third_party/libtiff/tif_close.c b/third_party/libtiff/tif_close.c index 13d2bab5ce956e85c0154bda4fcdecd79e8ebd53..a0cb661311fa43ab011de1c8217cdcdbad9724c6 100644 --- a/third_party/libtiff/tif_close.c +++ b/third_party/libtiff/tif_close.c @@ -1,4 +1,4 @@ -/* $Id: tif_close.c,v 1.19 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Id: tif_close.c,v 1.21 2016-01-23 21:20:34 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -36,7 +36,7 @@ /** * Auxiliary function to free the TIFF structure. Given structure will be - * completetly freed, so you should save opened file handle and pointer + * completely freed, so you should save opened file handle and pointer * to the close procedure in external variables before calling * _TIFFCleanup(), if you will need these ones to close the file. * @@ -62,11 +62,11 @@ TIFFCleanup(TIFF* tif) */ while( tif->tif_clientinfo ) { - TIFFClientInfoLink *link = tif->tif_clientinfo; + TIFFClientInfoLink *psLink = tif->tif_clientinfo; - tif->tif_clientinfo = link->next; - _TIFFfree( link->name ); - _TIFFfree( link ); + tif->tif_clientinfo = psLink->next; + _TIFFfree( psLink->name ); + _TIFFfree( psLink ); } if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER)) diff --git a/third_party/libtiff/tif_color.c b/third_party/libtiff/tif_color.c index be4850ce6b106a03171f629cd85600a2c05a1c84..8b8418c30118fece1892ed5413ca5a937bee6418 100644 --- a/third_party/libtiff/tif_color.c +++ b/third_party/libtiff/tif_color.c @@ -1,4 +1,4 @@ -/* $Id: tif_color.c,v 1.19 2010-12-14 02:22:42 faxguy Exp $ */ +/* $Id: tif_color.c,v 1.23 2017-05-13 18:17:34 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -126,37 +126,37 @@ TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, const TIFFDisplay *display, float *refWhite) { int i; - double gamma; + double dfGamma; cielab->range = CIELABTORGB_TABLE_RANGE; _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); /* Red */ - gamma = 1.0 / cielab->display.d_gammaR ; + dfGamma = 1.0 / cielab->display.d_gammaR ; cielab->rstep = (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; for(i = 0; i <= cielab->range; i++) { cielab->Yr2r[i] = cielab->display.d_Vrwr - * ((float)pow((double)i / cielab->range, gamma)); + * ((float)pow((double)i / cielab->range, dfGamma)); } /* Green */ - gamma = 1.0 / cielab->display.d_gammaG ; + dfGamma = 1.0 / cielab->display.d_gammaG ; cielab->gstep = (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; for(i = 0; i <= cielab->range; i++) { cielab->Yg2g[i] = cielab->display.d_Vrwg - * ((float)pow((double)i / cielab->range, gamma)); + * ((float)pow((double)i / cielab->range, dfGamma)); } /* Blue */ - gamma = 1.0 / cielab->display.d_gammaB ; + dfGamma = 1.0 / cielab->display.d_gammaB ; cielab->bstep = (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; for(i = 0; i <= cielab->range; i++) { cielab->Yb2b[i] = cielab->display.d_Vrwb - * ((float)pow((double)i / cielab->range, gamma)); + * ((float)pow((double)i / cielab->range, dfGamma)); } /* Init reference white point */ @@ -175,7 +175,7 @@ TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, #define SHIFT 16 #define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5)) #define ONE_HALF ((int32)(1<<(SHIFT-1))) -#define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1)) +#define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)!=0) ? ((RW)-(RB)) : 1)) #define CLAMP(f,min,max) ((f)<(min)?(min):(f)>(max)?(max):(f)) #define HICLAMP(f,max) ((f)>(max)?(max):(f)) @@ -186,7 +186,9 @@ TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, int32 i; /* XXX: Only 8-bit YCbCr input supported for now */ - Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255); + Y = HICLAMP(Y, 255); + Cb = CLAMP(Cb, 0, 255); + Cr = CLAMP(Cr, 0, 255); i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; *r = CLAMP(i, 0, 255); @@ -197,6 +199,23 @@ TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, *b = CLAMP(i, 0, 255); } +/* Clamp function for sanitization purposes. Normally clamping should not */ +/* occur for well behaved chroma and refBlackWhite coefficients */ +static float CLAMPw(float v, float vmin, float vmax) +{ + if( v < vmin ) + { + /* printf("%f clamped to %f\n", v, vmin); */ + return vmin; + } + if( v > vmax ) + { + /* printf("%f clamped to %f\n", v, vmax); */ + return vmax; + } + return v; +} + /* * Initialize the YCbCr->RGB conversion tables. The conversion * is done according to the 6.0 spec: @@ -236,10 +255,10 @@ TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; ycbcr->Y_tab = ycbcr->Cb_g_tab + 256; - { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); - float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); - float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); - float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); + { float f1 = 2-2*LumaRed; int32 D1 = FIX(CLAMP(f1,0.0F,2.0F)); + float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(CLAMP(f2,0.0F,2.0F)); + float f3 = 2-2*LumaBlue; int32 D3 = FIX(CLAMP(f3,0.0F,2.0F)); + float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(CLAMP(f4,0.0F,2.0F)); int x; #undef LumaBlue @@ -254,17 +273,20 @@ TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) * constructing tables indexed by the raw pixel data. */ for (i = 0, x = -128; i < 256; i++, x++) { - int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F, - refBlackWhite[5] - 128.0F, 127); - int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F, - refBlackWhite[3] - 128.0F, 127); + int32 Cr = (int32)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F, + refBlackWhite[5] - 128.0F, 127), + -128.0F * 64, 128.0F * 64); + int32 Cb = (int32)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F, + refBlackWhite[3] - 128.0F, 127), + -128.0F * 64, 128.0F * 64); ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT); ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT); ycbcr->Cr_g_tab[i] = D2*Cr; ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF; ycbcr->Y_tab[i] = - (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255); + (int32)CLAMPw(Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255), + -128.0F * 64, 128.0F * 64); } } diff --git a/third_party/libtiff/tif_compress.c b/third_party/libtiff/tif_compress.c index 20e72fd0731f5664e734de168d06819950407fb2..b571d19545f266d798ef65e05061201b0a0186ef 100644 --- a/third_party/libtiff/tif_compress.c +++ b/third_party/libtiff/tif_compress.c @@ -1,4 +1,4 @@ -/* $Id: tif_compress.c,v 1.22 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Id: tif_compress.c,v 1.25 2016-10-25 20:04:22 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -82,10 +82,10 @@ TIFFNoDecode(TIFF* tif, const char* method) TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Compression scheme %u %s decoding is not implemented", tif->tif_dir.td_compression, method); - return (-1); + return (0); } -int +static int _TIFFNoFixupTags(TIFF* tif) { (void) tif; @@ -227,7 +227,7 @@ TIFFUnRegisterCODEC(TIFFCodec* c) codec_t* cd; codec_t** pcd; - for (pcd = ®isteredCODECS; (cd = *pcd); pcd = &cd->next) + for (pcd = ®isteredCODECS; (cd = *pcd) != NULL; pcd = &cd->next) if (cd->info == c) { *pcd = cd->next; _TIFFfree(cd); diff --git a/third_party/libtiff/tif_dir.c b/third_party/libtiff/tif_dir.c index 16ce3d3cee1387c7017b7ad2ed97ea3c67212f4d..a88394917aa169a6c602bb6a8092939cb49f8d59 100644 --- a/third_party/libtiff/tif_dir.c +++ b/third_party/libtiff/tif_dir.c @@ -1,4 +1,4 @@ -/* $Id: tif_dir.c,v 1.121 2015-05-31 23:11:43 bfriesen Exp $ */ +/* $Id: tif_dir.c,v 1.130 2017-05-17 21:54:05 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -31,6 +31,7 @@ * (and also some miscellaneous stuff) */ #include "tiffiop.h" +#include <float.h> /* * These are used in the backwards compatibility code... @@ -43,8 +44,10 @@ static void setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size) { - if (*vpp) - _TIFFfree(*vpp), *vpp = 0; + if (*vpp) { + _TIFFfree(*vpp); + *vpp = 0; + } if (vp) { tmsize_t bytes = (tmsize_t)(nmemb * elem_size); if (elem_size && bytes / elem_size == nmemb) @@ -57,13 +60,13 @@ void _TIFFsetByteArray(void** vpp, void* vp, uint32 n) { setByteArray(vpp, vp, n, 1); } void _TIFFsetString(char** cpp, char* cp) { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); } -void _TIFFsetNString(char** cpp, char* cp, uint32 n) +static void _TIFFsetNString(char** cpp, char* cp, uint32 n) { setByteArray((void**) cpp, (void*) cp, n, 1); } void _TIFFsetShortArray(uint16** wpp, uint16* wp, uint32 n) { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); } void _TIFFsetLongArray(uint32** lpp, uint32* lp, uint32 n) { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); } -void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n) +static void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n) { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint64)); } void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n) { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); } @@ -152,6 +155,15 @@ bad: return (0); } +static float TIFFClampDoubleToFloat( double val ) +{ + if( val > FLT_MAX ) + return FLT_MAX; + if( val < -FLT_MAX ) + return -FLT_MAX; + return (float)val; +} + static int _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) { @@ -170,7 +182,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) * We want to force the custom code to be used for custom * fields even if the tag happens to match a well known * one - important for reinterpreted handling of standard - * tag values in custom directories (ie. EXIF) + * tag values in custom directories (i.e. EXIF) */ if (fip->field_bit == FIELD_CUSTOM) { standard_tag = 0; @@ -254,6 +266,28 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) v = (uint16) va_arg(ap, uint16_vap); if (v == 0) goto badvalue; + if( v != td->td_samplesperpixel ) + { + /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */ + if( td->td_sminsamplevalue != NULL ) + { + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag value is changing, " + "but SMinSampleValue tag was read with a different value. Cancelling it"); + TIFFClrFieldBit(tif,FIELD_SMINSAMPLEVALUE); + _TIFFfree(td->td_sminsamplevalue); + td->td_sminsamplevalue = NULL; + } + if( td->td_smaxsamplevalue != NULL ) + { + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag value is changing, " + "but SMaxSampleValue tag was read with a different value. Cancelling it"); + TIFFClrFieldBit(tif,FIELD_SMAXSAMPLEVALUE); + _TIFFfree(td->td_smaxsamplevalue); + td->td_smaxsamplevalue = NULL; + } + } td->td_samplesperpixel = (uint16) v; break; case TIFFTAG_ROWSPERSTRIP: @@ -288,13 +322,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) dblval = va_arg(ap, double); if( dblval < 0 ) goto badvaluedouble; - td->td_xresolution = (float) dblval; + td->td_xresolution = TIFFClampDoubleToFloat( dblval ); break; case TIFFTAG_YRESOLUTION: dblval = va_arg(ap, double); if( dblval < 0 ) goto badvaluedouble; - td->td_yresolution = (float) dblval; + td->td_yresolution = TIFFClampDoubleToFloat( dblval ); break; case TIFFTAG_PLANARCONFIG: v = (uint16) va_arg(ap, uint16_vap); @@ -303,10 +337,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) td->td_planarconfig = (uint16) v; break; case TIFFTAG_XPOSITION: - td->td_xposition = (float) va_arg(ap, double); + td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); break; case TIFFTAG_YPOSITION: - td->td_yposition = (float) va_arg(ap, double); + td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); break; case TIFFTAG_RESOLUTIONUNIT: v = (uint16) va_arg(ap, uint16_vap); @@ -402,7 +436,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) if ((tif->tif_flags & TIFF_INSUBIFD) == 0) { td->td_nsubifd = (uint16) va_arg(ap, uint16_vap); _TIFFsetLong8Array(&td->td_subifd, (uint64*) va_arg(ap, uint64*), - (long) td->td_nsubifd); + (uint32) td->td_nsubifd); } else { TIFFErrorExt(tif->tif_clientdata, module, "%s: Sorry, cannot nest SubIFDs", @@ -421,19 +455,11 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1; for (i = 0; i < v; i++) _TIFFsetShortArray(&td->td_transferfunction[i], - va_arg(ap, uint16*), 1L<<td->td_bitspersample); + va_arg(ap, uint16*), 1U<<td->td_bitspersample); break; case TIFFTAG_REFERENCEBLACKWHITE: /* XXX should check for null range */ _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); - for (int i = 0; i < 6; i++) { - if (isnan(td->td_refblackwhite[i])) { - if (i % 2 == 0) - td->td_refblackwhite[i] = 0; - else - td->td_refblackwhite[i] = pow(2, td->td_bitspersample) - 1; - } - } break; case TIFFTAG_INKNAMES: v = (uint16) va_arg(ap, uint16_vap); @@ -587,10 +613,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) handled this way ... likely best if we move it into the directory structure with an explicit field in libtiff 4.1 and assign it a FIELD_ value */ - uint16 v[2]; - v[0] = (uint16)va_arg(ap, int); - v[1] = (uint16)va_arg(ap, int); - _TIFFmemcpy(tv->value, &v, 4); + uint16 v2[2]; + v2[0] = (uint16)va_arg(ap, int); + v2[1] = (uint16)va_arg(ap, int); + _TIFFmemcpy(tv->value, &v2, 4); } else if (fip->field_passcount @@ -608,66 +634,66 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) case TIFF_BYTE: case TIFF_UNDEFINED: { - uint8 v = (uint8)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); + uint8 v2 = (uint8)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_SBYTE: { - int8 v = (int8)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); + int8 v2 = (int8)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_SHORT: { - uint16 v = (uint16)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); + uint16 v2 = (uint16)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_SSHORT: { - int16 v = (int16)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); + int16 v2 = (int16)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_LONG: case TIFF_IFD: { - uint32 v = va_arg(ap, uint32); - _TIFFmemcpy(val, &v, tv_size); + uint32 v2 = va_arg(ap, uint32); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_SLONG: { - int32 v = va_arg(ap, int32); - _TIFFmemcpy(val, &v, tv_size); + int32 v2 = va_arg(ap, int32); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_LONG8: case TIFF_IFD8: { - uint64 v = va_arg(ap, uint64); - _TIFFmemcpy(val, &v, tv_size); + uint64 v2 = va_arg(ap, uint64); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_SLONG8: { - int64 v = va_arg(ap, int64); - _TIFFmemcpy(val, &v, tv_size); + int64 v2 = va_arg(ap, int64); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_RATIONAL: case TIFF_SRATIONAL: case TIFF_FLOAT: { - float v = (float)va_arg(ap, double); - _TIFFmemcpy(val, &v, tv_size); + float v2 = TIFFClampDoubleToFloat(va_arg(ap, double)); + _TIFFmemcpy(val, &v2, tv_size); } break; case TIFF_DOUBLE: { - double v = va_arg(ap, double); - _TIFFmemcpy(val, &v, tv_size); + double v2 = va_arg(ap, double); + _TIFFmemcpy(val, &v2, tv_size); } break; default: @@ -680,9 +706,9 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) } } if (status) { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); - if (fip) - TIFFSetFieldBit(tif, fip->field_bit); + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); + if (fip2) + TIFFSetFieldBit(tif, fip2->field_bit); tif->tif_flags |= TIFF_DIRTYDIRECT; } @@ -691,31 +717,31 @@ end: return (status); badvalue: { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); TIFFErrorExt(tif->tif_clientdata, module, "%s: Bad value %u for \"%s\" tag", tif->tif_name, v, - fip ? fip->field_name : "Unknown"); + fip2 ? fip2->field_name : "Unknown"); va_end(ap); } return (0); badvalue32: { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); TIFFErrorExt(tif->tif_clientdata, module, "%s: Bad value %u for \"%s\" tag", tif->tif_name, v32, - fip ? fip->field_name : "Unknown"); + fip2 ? fip2->field_name : "Unknown"); va_end(ap); } return (0); badvaluedouble: { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); TIFFErrorExt(tif->tif_clientdata, module, "%s: Bad value %f for \"%s\" tag", tif->tif_name, dblval, - fip ? fip->field_name : "Unknown"); + fip2 ? fip2->field_name : "Unknown"); va_end(ap); } return (0); @@ -838,11 +864,37 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) if( fip == NULL ) /* cannot happen since TIFFGetField() already checks it */ return 0; + if( tag == TIFFTAG_NUMBEROFINKS ) + { + int i; + for (i = 0; i < td->td_customValueCount; i++) { + uint16 val; + TIFFTagValue *tv = td->td_customValues + i; + if (tv->info->field_tag != tag) + continue; + val = *(uint16 *)tv->value; + /* Truncate to SamplesPerPixel, since the */ + /* setting code for INKNAMES assume that there are SamplesPerPixel */ + /* inknames. */ + /* Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599 */ + if( val > td->td_samplesperpixel ) + { + TIFFWarningExt(tif->tif_clientdata,"_TIFFVGetField", + "Truncating NumberOfInks from %u to %u", + val, td->td_samplesperpixel); + val = td->td_samplesperpixel; + } + *va_arg(ap, uint16*) = val; + return 1; + } + return 0; + } + /* * We want to force the custom code to be used for custom * fields even if the tag happens to match a well known * one - important for reinterpreted handling of standard - * tag values in custom directories (ie. EXIF) + * tag values in custom directories (i.e. EXIF) */ if (fip->field_bit == FIELD_CUSTOM) { standard_tag = 0; @@ -893,7 +945,7 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) *va_arg(ap, double**) = td->td_sminsamplevalue; else { - /* libtiff historially treats this as a single value. */ + /* libtiff historically treats this as a single value. */ uint16 i; double v = td->td_sminsamplevalue[0]; for (i=1; i < td->td_samplesperpixel; ++i) @@ -907,7 +959,7 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) *va_arg(ap, double**) = td->td_smaxsamplevalue; else { - /* libtiff historially treats this as a single value. */ + /* libtiff historically treats this as a single value. */ uint16 i; double v = td->td_smaxsamplevalue[0]; for (i=1; i < td->td_samplesperpixel; ++i) diff --git a/third_party/libtiff/tif_dirinfo.c b/third_party/libtiff/tif_dirinfo.c index 7db4bdb95c71e0f98f65e056f308077a5daba434..23ad0020559f531caf852a424b8cec29c0fafc4d 100644 --- a/third_party/libtiff/tif_dirinfo.c +++ b/third_party/libtiff/tif_dirinfo.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirinfo.c,v 1.121 2014-05-07 01:58:46 bfriesen Exp $ */ +/* $Id: tif_dirinfo.c,v 1.126 2016-11-18 02:52:13 bfriesen Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -38,14 +38,22 @@ * NOTE: The second field (field_readcount) and third field (field_writecount) * sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3) * and TIFF_SPP (-2). The macros should be used but would throw off - * the formatting of the code, so please interprete the -1, -2 and -3 + * the formatting of the code, so please interpret the -1, -2 and -3 * values accordingly. */ -static TIFFFieldArray tiffFieldArray; -static TIFFFieldArray exifFieldArray; - -static TIFFField +/* const object should be initialized */ +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4132 ) +#endif +static const TIFFFieldArray tiffFieldArray; +static const TIFFFieldArray exifFieldArray; +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +static const TIFFField tiffFields[] = { { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "SubfileType", NULL }, { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "OldSubfileType", NULL }, @@ -95,7 +103,7 @@ tiffFields[] = { { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileLength", NULL }, { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "TileOffsets", NULL }, { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "TileByteCounts", NULL }, - { TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", &tiffFieldArray }, + { TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", (TIFFFieldArray*) &tiffFieldArray }, { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InkSet", NULL }, { TIFFTAG_INKNAMES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_C16_ASCII, TIFF_SETGET_UNDEFINED, FIELD_INKNAMES, 1, 1, "InkNames", NULL }, { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NumberOfInks", NULL }, @@ -134,7 +142,7 @@ tiffFields[] = { /* end Pixar tags */ { TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_LONG, 0, TIFF_SETGET_C32_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "RichTIFFIPTC", NULL }, { TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "Photoshop", NULL }, - { TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "EXIFIFDOffset", &exifFieldArray }, + { TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "EXIFIFDOffset", (TIFFFieldArray*) &exifFieldArray }, { TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ICC Profile", NULL }, { TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "GPSIFDOffset", NULL }, { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL }, @@ -211,7 +219,7 @@ tiffFields[] = { /* begin pseudo tags */ }; -static TIFFField +static const TIFFField exifFields[] = { { EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureTime", NULL }, { EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FNumber", NULL }, @@ -271,13 +279,13 @@ exifFields[] = { { EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageUniqueID", NULL } }; -static TIFFFieldArray -tiffFieldArray = { tfiatImage, 0, TIFFArrayCount(tiffFields), tiffFields }; -static TIFFFieldArray -exifFieldArray = { tfiatExif, 0, TIFFArrayCount(exifFields), exifFields }; +static const TIFFFieldArray +tiffFieldArray = { tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField*) tiffFields }; +static const TIFFFieldArray +exifFieldArray = { tfiatExif, 0, TIFFArrayCount(exifFields), (TIFFField*) exifFields }; /* - * We have our own local lfind() equivelent to avoid subtle differences + * We have our own local lfind() equivalent to avoid subtle differences * in types passed to lfind() on different systems. */ @@ -521,7 +529,7 @@ TIFFFindField(TIFF* tif, uint32 tag, TIFFDataType dt) return tif->tif_foundfield = (ret ? *ret : NULL); } -const TIFFField* +static const TIFFField* _TIFFFindFieldByName(TIFF* tif, const char *field_name, TIFFDataType dt) { TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL}; @@ -713,7 +721,7 @@ _TIFFCreateAnonField(TIFF *tif, uint32 tag, TIFFDataType field_type) * note that this name is a special sign to TIFFClose() and * _TIFFSetupFields() to free the field */ - snprintf(fld->field_name, 32, "Tag %d", (int) tag); + (void) snprintf(fld->field_name, 32, "Tag %d", (int) tag); return fld; } diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c index e0403aef31436e3ce723da91d38dba2430f45e56..ab938eac9da5b98a8fd4aa0bf708273e0c0ada72 100644 --- a/third_party/libtiff/tif_dirread.c +++ b/third_party/libtiff/tif_dirread.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirread.c,v 1.191 2015-09-05 20:31:41 bfriesen Exp $ */ +/* $Id: tif_dirread.c,v 1.208 2017-04-27 15:46:22 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -40,6 +40,8 @@ */ #include "tiffiop.h" +#include <float.h> +#include <limits.h> #define IGNORE 0 /* tag placeholder used below */ #define FAILED_FII ((uint32) -1) @@ -166,6 +168,8 @@ static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); static void ChopUpSingleUncompressedStrip(TIFF*); static uint64 TIFFReadUInt64(const uint8 *value); +static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ); + typedef union _UInt64Aligned_t { double d; @@ -2404,7 +2408,14 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray(TIFF* tif, TIFFDirEnt ma=(double*)origdata; mb=data; for (n=0; n<count; n++) - *mb++=(float)(*ma++); + { + double val = *ma++; + if( val > FLT_MAX ) + val = FLT_MAX; + else if( val < -FLT_MAX ) + val = -FLT_MAX; + *mb++=(float)val; + } } break; } @@ -2870,7 +2881,10 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational(TIFF* tif, TIFFD m.l = direntry->tdir_offset.toff_long8; if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfLong(m.i,2); - if (m.i[0]==0) + /* Not completely sure what we should do when m.i[1]==0, but some */ + /* sanitizers do not like division by 0.0: */ + /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */ + if (m.i[0]==0 || m.i[1]==0) *value=0.0; else *value=(double)m.i[0]/(double)m.i[1]; @@ -2898,7 +2912,10 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational(TIFF* tif, TIFF m.l=direntry->tdir_offset.toff_long8; if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfLong(m.i,2); - if ((int32)m.i[0]==0) + /* Not completely sure what we should do when m.i[1]==0, but some */ + /* sanitizers do not like division by 0.0: */ + /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */ + if ((int32)m.i[0]==0 || m.i[1]==0) *value=0.0; else *value=(double)((int32)m.i[0])/(double)m.i[1]; @@ -3457,12 +3474,12 @@ TIFFReadDirectory(TIFF* tif) * the fields to check type and tag information, * and to extract info required to size data * structures. A second pass is made afterwards - * to read in everthing not taken in the first pass. + * to read in everything not taken in the first pass. * But we must process the Compression tag first * in order to merge in codec-private tag definitions (otherwise * we may get complaints about unknown tags). However, the * Compression tag may be dependent on the SamplesPerPixel - * tag value because older TIFF specs permited Compression + * tag value because older TIFF specs permitted Compression * to be written as a SamplesPerPixel-count tag entry. * Thus if we don't first figure out the correct SamplesPerPixel * tag value then we may end up ignoring the Compression tag @@ -3622,10 +3639,18 @@ TIFFReadDirectory(TIFF* tif) isTiled(tif) ? "tiles" : "strips"); goto bad; } + if (tif->tif_dir.td_nstrips > INT_MAX) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot handle %u number of %s", + tif->tif_dir.td_nstrips, + isTiled(tif) ? "tiles" : "strips"); + goto bad; + } tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips; if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE) tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel; if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { +#ifdef OJPEG_SUPPORT if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) && (isTiled(tif)==0) && (tif->tif_dir.td_nstrips==1)) { @@ -3638,7 +3663,9 @@ TIFFReadDirectory(TIFF* tif) * JpegInterchangeFormat stream. */ TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); - } else { + } else +#endif + { MissingRequired(tif, isTiled(tif) ? "TileOffsets" : "StripOffsets"); goto bad; @@ -3663,7 +3690,7 @@ TIFFReadDirectory(TIFF* tif) * DataType and SampleFormat tags are supposed to be * written as one value/sample, but some vendors * incorrectly write one value only -- so we accept - * that as well (yech). Other vendors write correct + * that as well (yuck). Other vendors write correct * value for NumberOfSamples, but incorrect one for * BitsPerSample and friends, and we will read this * too. @@ -3690,7 +3717,7 @@ TIFFReadDirectory(TIFF* tif) case TIFFTAG_SMAXSAMPLEVALUE: { - double *data; + double *data = NULL; enum TIFFReadDirEntryErr err; uint32 saved_flags; int m; @@ -3719,6 +3746,14 @@ TIFFReadDirectory(TIFF* tif) _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry), dp, sizeof(TIFFDirEntry) ); #else + if( tif->tif_dir.td_stripoffset != NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "tif->tif_dir.td_stripoffset is " + "already allocated. Likely duplicated " + "StripOffsets/TileOffsets tag"); + goto bad; + } if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset)) goto bad; #endif @@ -3729,7 +3764,15 @@ TIFFReadDirectory(TIFF* tif) _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry), dp, sizeof(TIFFDirEntry) ); #else - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount)) + if( tif->tif_dir.td_stripbytecount != NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "tif->tif_dir.td_stripbytecount is " + "already allocated. Likely duplicated " + "StripByteCounts/TileByteCounts tag"); + goto bad; + } + if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount)) goto bad; #endif break; @@ -3741,7 +3784,7 @@ TIFFReadDirectory(TIFF* tif) uint32 countrequired; uint32 incrementpersample; uint16* value=NULL; - /* It would be dangerous to instanciate those tag values */ + /* It would be dangerous to instantiate those tag values */ /* since if td_bitspersample has not yet been read (due to */ /* unordered tags), it could be read afterwards with a */ /* values greater than the default one (1), which may cause */ @@ -3759,13 +3802,14 @@ TIFFReadDirectory(TIFF* tif) /* used as a denial of service vector */ if (tif->tif_dir.td_bitspersample > 24) { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); TIFFWarningExt(tif->tif_clientdata,module, "Ignoring %s because BitsPerSample=%d>24", fip ? fip->field_name : "unknown tagname", tif->tif_dir.td_bitspersample); continue; } - countpersample=(1L<<tif->tif_dir.td_bitspersample); + countpersample=(1U<<tif->tif_dir.td_bitspersample); if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) { countrequired=countpersample; @@ -4153,7 +4197,7 @@ TIFFReadDirectoryFindFieldInfo(TIFF* tif, uint16 tagid, uint32* fii) } /* - * Read custom directory from the arbitarry offset. + * Read custom directory from the arbitrary offset. * The code is very similar to TIFFReadDirectory(). */ int @@ -4280,8 +4324,9 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) TIFFDirectory *td = &tif->tif_dir; uint32 strip; - if( !_TIFFFillStriles( tif ) ) - return -1; + /* Do not try to load stripbytecount as we will compute it */ + if( !_TIFFFillStrilesInternal( tif, 0 ) ) + return -1; if (td->td_stripbytecount) _TIFFfree(td->td_stripbytecount); @@ -4303,7 +4348,7 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) /* calculate amount of space used by indirect values */ for (dp = dir, n = dircount; n > 0; n--, dp++) { - uint32 typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type); + uint32 typewidth; uint64 datasize; typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type); if (typewidth == 0) { @@ -4393,7 +4438,7 @@ TIFFCheckDirOffset(TIFF* tif, uint64 diroff) tif->tif_dirnumber++; - if (tif->tif_dirnumber > tif->tif_dirlistsize) { + if (tif->tif_dirlist == NULL || tif->tif_dirnumber > tif->tif_dirlistsize) { uint64* new_dirlist; /* @@ -4454,7 +4499,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, static const char module[] = "TIFFFetchDirectory"; void* origdir; - uint16 dircount16 = 0; + uint16 dircount16; uint32 dirsize; TIFFDirEntry* dir; uint8* ma; @@ -4583,7 +4628,6 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, } else { - tmsize_t m; uint64 dircount64; m=off+sizeof(uint64); if ((m<off)||(m<(tmsize_t)sizeof(uint64))||(m>tif->tif_size)) { @@ -4994,7 +5038,7 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) if (err==TIFFReadDirEntryErrOk) { int m; - if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) + if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) { TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); data[dp->tdir_count-1] = '\0'; @@ -5171,7 +5215,7 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) if (err==TIFFReadDirEntryErrOk) { int m; - if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) + if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) { TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); data[dp->tdir_count-1] = '\0'; @@ -5393,8 +5437,6 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp) static const char module[] = "TIFFFetchStripThing"; enum TIFFReadDirEntryErr err; uint64* data; - _TIFFfree(*lpp); - *lpp = 0; err=TIFFReadDirEntryLong8Array(tif,dir,&data); if (err!=TIFFReadDirEntryErrOk) { @@ -5498,8 +5540,7 @@ ChopUpSingleUncompressedStrip(TIFF* tif) uint64 rowblockbytes; uint64 stripbytes; uint32 strip; - uint64 nstrips64; - uint32 nstrips32; + uint32 nstrips; uint32 rowsperstrip; uint64* newcounts; uint64* newoffsets; @@ -5530,18 +5571,17 @@ ChopUpSingleUncompressedStrip(TIFF* tif) return; /* - * never increase the number of strips in an image + * never increase the number of rows per strip */ if (rowsperstrip >= td->td_rowsperstrip) return; - nstrips64 = TIFFhowmany_64(bytecount, stripbytes); - if ((nstrips64==0)||(nstrips64>0xFFFFFFFF)) /* something is wonky, do nothing. */ - return; - nstrips32 = (uint32)nstrips64; + nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); + if( nstrips == 0 ) + return; - newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64), + newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), "for chopped \"StripByteCounts\" array"); - newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64), + newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), "for chopped \"StripOffsets\" array"); if (newcounts == NULL || newoffsets == NULL) { /* @@ -5558,18 +5598,18 @@ ChopUpSingleUncompressedStrip(TIFF* tif) * Fill the strip information arrays with new bytecounts and offsets * that reflect the broken-up format. */ - for (strip = 0; strip < nstrips32; strip++) { + for (strip = 0; strip < nstrips; strip++) { if (stripbytes > bytecount) stripbytes = bytecount; newcounts[strip] = stripbytes; - newoffsets[strip] = offset; + newoffsets[strip] = stripbytes ? offset : 0; offset += stripbytes; bytecount -= stripbytes; } /* * Replace old single strip info with multi-strip info. */ - td->td_stripsperimage = td->td_nstrips = nstrips32; + td->td_stripsperimage = td->td_nstrips = nstrips; TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); _TIFFfree(td->td_stripbytecount); @@ -5580,6 +5620,11 @@ ChopUpSingleUncompressedStrip(TIFF* tif) } int _TIFFFillStriles( TIFF *tif ) +{ + return _TIFFFillStrilesInternal( tif, 1 ); +} + +static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ) { #if defined(DEFER_STRILE_LOAD) register TIFFDirectory *td = &tif->tif_dir; @@ -5597,7 +5642,8 @@ int _TIFFFillStriles( TIFF *tif ) return_value = 0; } - if (!TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), + if (loadStripByteCount && + !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), td->td_nstrips,&td->td_stripbytecount)) { return_value = 0; @@ -5622,6 +5668,7 @@ int _TIFFFillStriles( TIFF *tif ) return return_value; #else /* !defined(DEFER_STRILE_LOAD) */ (void) tif; + (void) loadStripByteCount; return 1; #endif } diff --git a/third_party/libtiff/tif_dirwrite.c b/third_party/libtiff/tif_dirwrite.c index a0fd8dc2f62215ba623a67e0f9623b5371b4ec25..f7339685130d1482b2ef7ff6c33c7876c80d03ba 100644 --- a/third_party/libtiff/tif_dirwrite.c +++ b/third_party/libtiff/tif_dirwrite.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirwrite.c,v 1.78 2015-05-31 00:38:46 bfriesen Exp $ */ +/* $Id: tif_dirwrite.c,v 1.85 2017-01-11 16:09:02 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -30,6 +30,7 @@ * Directory Write Support Routines. */ #include "tiffiop.h" +#include <float.h> #ifdef HAVE_IEEEFP #define TIFFCvtNativeToIEEEFloat(tif, n, fp) @@ -542,8 +543,20 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) { if (!isTiled(tif)) { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) - goto bad; + /* td_stripoffset might be NULL in an odd OJPEG case. See + * tif_dirread.c around line 3634. + * XXX: OJPEG hack. + * If a) compression is OJPEG, b) it's not a tiled TIFF, + * and c) the number of strips is 1, + * then we tolerate the absence of stripoffsets tag, + * because, presumably, all required data is in the + * JpegInterchangeFormat stream. + * We can get here when using tiffset on such a file. + * See http://bugzilla.maptools.org/show_bug.cgi?id=2500 + */ + if (tif->tif_dir.td_stripoffset != NULL && + !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) + goto bad; } else { @@ -645,7 +658,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) assert(o->field_passcount==0); TIFFGetField(tif,o->field_tag,&pb); pa=(uint32)(strlen(pb)); - if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,o->field_tag,pa,pb)) + if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,(uint16)o->field_tag,pa,pb)) goto bad; } break; @@ -656,7 +669,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) assert(o->field_readcount==1); assert(o->field_passcount==0); TIFFGetField(tif,o->field_tag,&p); - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,o->field_tag,p)) + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,(uint16)o->field_tag,p)) goto bad; } break; @@ -667,7 +680,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) assert(o->field_readcount==1); assert(o->field_passcount==0); TIFFGetField(tif,o->field_tag,&p); - if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,o->field_tag,p)) + if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,(uint16)o->field_tag,p)) goto bad; } break; @@ -679,7 +692,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) assert(o->field_readcount==TIFF_VARIABLE2); assert(o->field_passcount==1); TIFFGetField(tif,o->field_tag,&pa,&pb); - if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,o->field_tag,pa,pb)) + if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,(uint16)o->field_tag,pa,pb)) goto bad; } break; @@ -693,70 +706,72 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) } for (m=0; m<(uint32)(tif->tif_dir.td_customValueCount); m++) { + uint16 tag = (uint16)tif->tif_dir.td_customValues[m].info->field_tag; + uint32 count = tif->tif_dir.td_customValues[m].count; switch (tif->tif_dir.td_customValues[m].info->field_type) { case TIFF_ASCII: - if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_UNDEFINED: - if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_BYTE: - if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SBYTE: - if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SHORT: - if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SSHORT: - if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_LONG: - if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SLONG: - if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_LONG8: - if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SLONG8: - if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_RATIONAL: - if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SRATIONAL: - if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_FLOAT: - if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_DOUBLE: - if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_IFD: - if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_IFD8: - if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) + if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; default: @@ -778,7 +793,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) goto bad; } else - tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~1); + tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~((toff_t)1)); if (pdiroff!=NULL) *pdiroff=tif->tif_diroff; if (!(tif->tif_flags&TIFF_BIGTIFF)) @@ -828,7 +843,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) uint32 nTmp; TIFFDirEntry* o; n=dirmem; - *(uint16*)n=ndir; + *(uint16*)n=(uint16)ndir; if (tif->tif_flags&TIFF_SWAB) TIFFSwabShort((uint16*)n); n+=2; @@ -925,6 +940,69 @@ bad: return(0); } +static float TIFFClampDoubleToFloat( double val ) +{ + if( val > FLT_MAX ) + return FLT_MAX; + if( val < -FLT_MAX ) + return -FLT_MAX; + return (float)val; +} + +static int8 TIFFClampDoubleToInt8( double val ) +{ + if( val > 127 ) + return 127; + if( val < -128 || val != val ) + return -128; + return (int8)val; +} + +static int16 TIFFClampDoubleToInt16( double val ) +{ + if( val > 32767 ) + return 32767; + if( val < -32768 || val != val ) + return -32768; + return (int16)val; +} + +static int32 TIFFClampDoubleToInt32( double val ) +{ + if( val > 0x7FFFFFFF ) + return 0x7FFFFFFF; + if( val < -0x7FFFFFFF-1 || val != val ) + return -0x7FFFFFFF-1; + return (int32)val; +} + +static uint8 TIFFClampDoubleToUInt8( double val ) +{ + if( val < 0 ) + return 0; + if( val > 255 || val != val ) + return 255; + return (uint8)val; +} + +static uint16 TIFFClampDoubleToUInt16( double val ) +{ + if( val < 0 ) + return 0; + if( val > 65535 || val != val ) + return 65535; + return (uint16)val; +} + +static uint32 TIFFClampDoubleToUInt32( double val ) +{ + if( val < 0 ) + return 0; + if( val > 0xFFFFFFFFU || val != val ) + return 0xFFFFFFFFU; + return (uint32)val; +} + static int TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) { @@ -945,7 +1023,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di if (tif->tif_dir.td_bitspersample<=32) { for (i = 0; i < count; ++i) - ((float*)conv)[i] = (float)value[i]; + ((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]); ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); } else @@ -957,19 +1035,19 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di if (tif->tif_dir.td_bitspersample<=8) { for (i = 0; i < count; ++i) - ((int8*)conv)[i] = (int8)value[i]; + ((int8*)conv)[i] = TIFFClampDoubleToInt8(value[i]); ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv); } else if (tif->tif_dir.td_bitspersample<=16) { for (i = 0; i < count; ++i) - ((int16*)conv)[i] = (int16)value[i]; + ((int16*)conv)[i] = TIFFClampDoubleToInt16(value[i]); ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv); } else { for (i = 0; i < count; ++i) - ((int32*)conv)[i] = (int32)value[i]; + ((int32*)conv)[i] = TIFFClampDoubleToInt32(value[i]); ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv); } break; @@ -977,19 +1055,19 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di if (tif->tif_dir.td_bitspersample<=8) { for (i = 0; i < count; ++i) - ((uint8*)conv)[i] = (uint8)value[i]; + ((uint8*)conv)[i] = TIFFClampDoubleToUInt8(value[i]); ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv); } else if (tif->tif_dir.td_bitspersample<=16) { for (i = 0; i < count; ++i) - ((uint16*)conv)[i] = (uint16)value[i]; + ((uint16*)conv)[i] = TIFFClampDoubleToUInt16(value[i]); ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv); } else { for (i = 0; i < count; ++i) - ((uint32*)conv)[i] = (uint32)value[i]; + ((uint32*)conv)[i] = TIFFClampDoubleToUInt32(value[i]); ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv); } break; @@ -2080,15 +2158,25 @@ TIFFWriteDirectoryTagCheckedSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* d static int TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { + static const char module[] = "TIFFWriteDirectoryTagCheckedRational"; uint32 m[2]; - assert(value>=0.0); assert(sizeof(uint32)==4); - if (value<=0.0) + if( value < 0 ) + { + TIFFErrorExt(tif->tif_clientdata,module,"Negative value is illegal"); + return 0; + } + else if( value != value ) + { + TIFFErrorExt(tif->tif_clientdata,module,"Not-a-number value is illegal"); + return 0; + } + else if (value==0.0) { m[0]=0; m[1]=1; } - else if (value==(double)(uint32)value) + else if (value <= 0xFFFFFFFFU && value==(double)(uint32)value) { m[0]=(uint32)value; m[1]=1; @@ -2129,25 +2217,26 @@ TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* } for (na=value, nb=m, nc=0; nc<count; na++, nb+=2, nc++) { - if (*na<=0.0) + if (*na<=0.0 || *na != *na) { nb[0]=0; nb[1]=1; } - else if (*na==(float)(uint32)(*na)) + else if (*na >= 0 && *na <= (float)0xFFFFFFFFU && + *na==(float)(uint32)(*na)) { nb[0]=(uint32)(*na); nb[1]=1; } else if (*na<1.0) { - nb[0]=(uint32)((*na)*0xFFFFFFFF); + nb[0]=(uint32)((double)(*na)*0xFFFFFFFF); nb[1]=0xFFFFFFFF; } else { nb[0]=0xFFFFFFFF; - nb[1]=(uint32)(0xFFFFFFFF/(*na)); + nb[1]=(uint32)((double)0xFFFFFFFF/(*na)); } } if (tif->tif_flags&TIFF_SWAB) @@ -2184,13 +2273,13 @@ TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry } else if (*na>-1.0) { - nb[0]=-(int32)((-*na)*0x7FFFFFFF); + nb[0]=-(int32)((double)(-*na)*0x7FFFFFFF); nb[1]=0x7FFFFFFF; } else { nb[0]=-0x7FFFFFFF; - nb[1]=(int32)(0x7FFFFFFF/(-*na)); + nb[1]=(int32)((double)0x7FFFFFFF/(-*na)); } } else @@ -2202,13 +2291,13 @@ TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry } else if (*na<1.0) { - nb[0]=(int32)((*na)*0x7FFFFFFF); + nb[0]=(int32)((double)(*na)*0x7FFFFFFF); nb[1]=0x7FFFFFFF; } else { nb[0]=0x7FFFFFFF; - nb[1]=(int32)(0x7FFFFFFF/(*na)); + nb[1]=(int32)((double)0x7FFFFFFF/(*na)); } } } @@ -2368,7 +2457,7 @@ TIFFLinkDirectory(TIFF* tif) { static const char module[] = "TIFFLinkDirectory"; - tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) &~ 1; + tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) & (~((toff_t)1)); /* * Handle SubIFDs diff --git a/third_party/libtiff/tif_dumpmode.c b/third_party/libtiff/tif_dumpmode.c index a94cf0b34a92c41378bc5916e7d3fc84813f1ea9..a6a94c04d5664cce9a4e61471447fbd44d2aec90 100644 --- a/third_party/libtiff/tif_dumpmode.c +++ b/third_party/libtiff/tif_dumpmode.c @@ -1,4 +1,4 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.14 2011-04-02 20:54:09 bfriesen Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.15 2015-12-12 18:04:26 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -66,7 +66,7 @@ DumpModeEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) cc -= n; if (tif->tif_rawcc >= tif->tif_rawdatasize && !TIFFFlushData1(tif)) - return (-1); + return (0); } return (1); } diff --git a/third_party/libtiff/tif_extension.c b/third_party/libtiff/tif_extension.c index 10afd4162c157271ca9d08de73795a1155a27775..39fab4c7ba8e2869c5426d35fbd8268ba70cd16a 100644 --- a/third_party/libtiff/tif_extension.c +++ b/third_party/libtiff/tif_extension.c @@ -1,4 +1,4 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.7 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.8 2015-12-06 11:13:43 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -66,13 +66,13 @@ TIFFTagMethods *TIFFAccessTagMethods( TIFF *tif ) void *TIFFGetClientInfo( TIFF *tif, const char *name ) { - TIFFClientInfoLink *link = tif->tif_clientinfo; + TIFFClientInfoLink *psLink = tif->tif_clientinfo; - while( link != NULL && strcmp(link->name,name) != 0 ) - link = link->next; + while( psLink != NULL && strcmp(psLink->name,name) != 0 ) + psLink = psLink->next; - if( link != NULL ) - return link->data; + if( psLink != NULL ) + return psLink->data; else return NULL; } @@ -80,18 +80,18 @@ void *TIFFGetClientInfo( TIFF *tif, const char *name ) void TIFFSetClientInfo( TIFF *tif, void *data, const char *name ) { - TIFFClientInfoLink *link = tif->tif_clientinfo; + TIFFClientInfoLink *psLink = tif->tif_clientinfo; /* ** Do we have an existing link with this name? If so, just ** set it. */ - while( link != NULL && strcmp(link->name,name) != 0 ) - link = link->next; + while( psLink != NULL && strcmp(psLink->name,name) != 0 ) + psLink = psLink->next; - if( link != NULL ) + if( psLink != NULL ) { - link->data = data; + psLink->data = data; return; } @@ -99,15 +99,15 @@ void TIFFSetClientInfo( TIFF *tif, void *data, const char *name ) ** Create a new link. */ - link = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink)); - assert (link != NULL); - link->next = tif->tif_clientinfo; - link->name = (char *) _TIFFmalloc((tmsize_t)(strlen(name)+1)); - assert (link->name != NULL); - strcpy(link->name, name); - link->data = data; + psLink = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink)); + assert (psLink != NULL); + psLink->next = tif->tif_clientinfo; + psLink->name = (char *) _TIFFmalloc((tmsize_t)(strlen(name)+1)); + assert (psLink->name != NULL); + strcpy(psLink->name, name); + psLink->data = data; - tif->tif_clientinfo = link; + tif->tif_clientinfo = psLink; } /* * Local Variables: diff --git a/third_party/libtiff/tif_fax3.c b/third_party/libtiff/tif_fax3.c index bbe72555bee33318396b54d9d7f1e741f92d2a48..087cedddc11059ae3eec1f279514082d9736baf0 100644 --- a/third_party/libtiff/tif_fax3.c +++ b/third_party/libtiff/tif_fax3.c @@ -1,4 +1,4 @@ -/* $Id: tif_fax3.c,v 1.75 2015-08-30 20:49:55 erouault Exp $ */ +/* $Id: tif_fax3.c,v 1.80 2017-04-27 19:50:01 erouault Exp $ */ /* * Copyright (c) 1990-1997 Sam Leffler @@ -329,34 +329,64 @@ Fax3Decode2D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) #if SIZEOF_UNSIGNED_LONG == 8 # define FILL(n, cp) \ switch (n) { \ - case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\ - case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\ - case 9: (cp)[8] = 0xff; case 8: (cp)[7] = 0xff; case 7: (cp)[6] = 0xff;\ - case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; case 4: (cp)[3] = 0xff;\ - case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ - case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + case 15:(cp)[14] = 0xff; /*-fallthrough*/ \ + case 14:(cp)[13] = 0xff; /*-fallthrough*/ \ + case 13:(cp)[12] = 0xff; /*-fallthrough*/ \ + case 12:(cp)[11] = 0xff; /*-fallthrough*/ \ + case 11:(cp)[10] = 0xff; /*-fallthrough*/ \ + case 10: (cp)[9] = 0xff; /*-fallthrough*/ \ + case 9: (cp)[8] = 0xff; /*-fallthrough*/ \ + case 8: (cp)[7] = 0xff; /*-fallthrough*/ \ + case 7: (cp)[6] = 0xff; /*-fallthrough*/ \ + case 6: (cp)[5] = 0xff; /*-fallthrough*/ \ + case 5: (cp)[4] = 0xff; /*-fallthrough*/ \ + case 4: (cp)[3] = 0xff; /*-fallthrough*/ \ + case 3: (cp)[2] = 0xff; /*-fallthrough*/ \ + case 2: (cp)[1] = 0xff; /*-fallthrough*/ \ + case 1: (cp)[0] = 0xff; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } # define ZERO(n, cp) \ switch (n) { \ - case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0; \ - case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0; \ - case 9: (cp)[8] = 0; case 8: (cp)[7] = 0; case 7: (cp)[6] = 0; \ - case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; case 4: (cp)[3] = 0; \ - case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ - case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + case 15:(cp)[14] = 0; /*-fallthrough*/ \ + case 14:(cp)[13] = 0; /*-fallthrough*/ \ + case 13:(cp)[12] = 0; /*-fallthrough*/ \ + case 12:(cp)[11] = 0; /*-fallthrough*/ \ + case 11:(cp)[10] = 0; /*-fallthrough*/ \ + case 10: (cp)[9] = 0; /*-fallthrough*/ \ + case 9: (cp)[8] = 0; /*-fallthrough*/ \ + case 8: (cp)[7] = 0; /*-fallthrough*/ \ + case 7: (cp)[6] = 0; /*-fallthrough*/ \ + case 6: (cp)[5] = 0; /*-fallthrough*/ \ + case 5: (cp)[4] = 0; /*-fallthrough*/ \ + case 4: (cp)[3] = 0; /*-fallthrough*/ \ + case 3: (cp)[2] = 0; /*-fallthrough*/ \ + case 2: (cp)[1] = 0; /*-fallthrough*/ \ + case 1: (cp)[0] = 0; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } #else # define FILL(n, cp) \ switch (n) { \ - case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \ - case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ - case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + case 7: (cp)[6] = 0xff; /*-fallthrough*/ \ + case 6: (cp)[5] = 0xff; /*-fallthrough*/ \ + case 5: (cp)[4] = 0xff; /*-fallthrough*/ \ + case 4: (cp)[3] = 0xff; /*-fallthrough*/ \ + case 3: (cp)[2] = 0xff; /*-fallthrough*/ \ + case 2: (cp)[1] = 0xff; /*-fallthrough*/ \ + case 1: (cp)[0] = 0xff; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } # define ZERO(n, cp) \ switch (n) { \ - case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; \ - case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ - case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + case 7: (cp)[6] = 0; /*-fallthrough*/ \ + case 6: (cp)[5] = 0; /*-fallthrough*/ \ + case 5: (cp)[4] = 0; /*-fallthrough*/ \ + case 4: (cp)[3] = 0; /*-fallthrough*/ \ + case 3: (cp)[2] = 0; /*-fallthrough*/ \ + case 2: (cp)[1] = 0; /*-fallthrough*/ \ + case 1: (cp)[0] = 0; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } #endif @@ -644,7 +674,8 @@ putspan(TIFF* tif, int32 span, const tableentry* tab) while (span >= 2624) { const tableentry* te = &tab[63 + (2560>>6)]; - code = te->code, length = te->length; + code = te->code; + length = te->length; #ifdef FAX3_DEBUG DEBUG_PRINT("MakeUp", te->runlen); #endif @@ -654,14 +685,16 @@ putspan(TIFF* tif, int32 span, const tableentry* tab) if (span >= 64) { const tableentry* te = &tab[63 + (span>>6)]; assert(te->runlen == 64*(span>>6)); - code = te->code, length = te->length; + code = te->code; + length = te->length; #ifdef FAX3_DEBUG DEBUG_PRINT("MakeUp", te->runlen); #endif _PutBits(tif, code, length); span -= te->runlen; } - code = tab[span].code, length = tab[span].length; + code = tab[span].code; + length = tab[span].length; #ifdef FAX3_DEBUG DEBUG_PRINT(" Term", tab[span].runlen); #endif @@ -697,14 +730,16 @@ Fax3PutEOL(TIFF* tif) align = sp->bit + (8 - align); else align = sp->bit - align; - code = 0; tparm=align; _PutBits(tif, 0, tparm); } } - code = EOL, length = 12; - if (is2DEncoding(sp)) - code = (code<<1) | (sp->tag == G3_1D), length++; + code = EOL; + length = 12; + if (is2DEncoding(sp)) { + code = (code<<1) | (sp->tag == G3_1D); + length++; + } _PutBits(tif, code, length); sp->data = data; @@ -815,7 +850,7 @@ find0span(unsigned char* bp, int32 bs, int32 be) /* * Check partial byte on lhs. */ - if (bits > 0 && (n = (bs & 7))) { + if (bits > 0 && (n = (bs & 7)) != 0) { span = zeroruns[(*bp << n) & 0xff]; if (span > 8-n) /* table value too generous */ span = 8-n; @@ -835,12 +870,14 @@ find0span(unsigned char* bp, int32 bs, int32 be) while (!isAligned(bp, long)) { if (*bp != 0x00) return (span + zeroruns[*bp]); - span += 8, bits -= 8; + span += 8; + bits -= 8; bp++; } lp = (long*) bp; while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) { - span += 8*sizeof (long), bits -= 8*sizeof (long); + span += 8*sizeof (long); + bits -= 8*sizeof (long); lp++; } bp = (unsigned char*) lp; @@ -851,7 +888,8 @@ find0span(unsigned char* bp, int32 bs, int32 be) while (bits >= 8) { if (*bp != 0x00) /* end of run */ return (span + zeroruns[*bp]); - span += 8, bits -= 8; + span += 8; + bits -= 8; bp++; } /* @@ -874,7 +912,7 @@ find1span(unsigned char* bp, int32 bs, int32 be) /* * Check partial byte on lhs. */ - if (bits > 0 && (n = (bs & 7))) { + if (bits > 0 && (n = (bs & 7)) != 0) { span = oneruns[(*bp << n) & 0xff]; if (span > 8-n) /* table value too generous */ span = 8-n; @@ -894,12 +932,14 @@ find1span(unsigned char* bp, int32 bs, int32 be) while (!isAligned(bp, long)) { if (*bp != 0xff) return (span + oneruns[*bp]); - span += 8, bits -= 8; + span += 8; + bits -= 8; bp++; } lp = (long*) bp; while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) { - span += 8*sizeof (long), bits -= 8*sizeof (long); + span += 8*sizeof (long); + bits -= 8*sizeof (long); lp++; } bp = (unsigned char*) lp; @@ -910,7 +950,8 @@ find1span(unsigned char* bp, int32 bs, int32 be) while (bits >= 8) { if (*bp != 0xff) /* end of run */ return (span + oneruns[*bp]); - span += 8, bits -= 8; + span += 8; + bits -= 8; bp++; } /* @@ -1088,14 +1129,16 @@ Fax3PostEncode(TIFF* tif) static void Fax3Close(TIFF* tif) { - if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0) { + if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0 && tif->tif_rawcp) { Fax3CodecState* sp = EncoderState(tif); unsigned int code = EOL; unsigned int length = 12; int i; - if (is2DEncoding(sp)) - code = (code<<1) | (sp->tag == G3_1D), length++; + if (is2DEncoding(sp)) { + code = (code<<1) | (sp->tag == G3_1D); + length++; + } for (i = 0; i < 6; i++) Fax3PutBits(tif, code, length); Fax3FlushBits(tif, sp); @@ -1182,7 +1225,7 @@ Fax3VSetField(TIFF* tif, uint32 tag, va_list ap) return (*sp->vsetparent)(tif, tag, ap); } - if ((fip = TIFFFieldWithTag(tif, tag))) + if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) TIFFSetFieldBit(tif, fip->field_bit); else return 0; @@ -1241,10 +1284,14 @@ Fax3PrintDir(TIFF* tif, FILE* fd, long flags) } else { fprintf(fd, " Group 3 Options:"); - if (sp->groupoptions & GROUP3OPT_2DENCODING) - fprintf(fd, "%s2-d encoding", sep), sep = "+"; - if (sp->groupoptions & GROUP3OPT_FILLBITS) - fprintf(fd, "%sEOL padding", sep), sep = "+"; + if (sp->groupoptions & GROUP3OPT_2DENCODING) { + fprintf(fd, "%s2-d encoding", sep); + sep = "+"; + } + if (sp->groupoptions & GROUP3OPT_FILLBITS) { + fprintf(fd, "%sEOL padding", sep); + sep = "+"; + } if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED) fprintf(fd, "%suncompressed data", sep); } @@ -1304,6 +1351,7 @@ InitCCITTFax3(TIFF* tif) "No space for state block"); return (0); } + _TIFFmemset(tif->tif_data, 0, sizeof (Fax3CodecState)); sp = Fax3State(tif); sp->rw_mode = tif->tif_mode; diff --git a/third_party/libtiff/tif_fax3.h b/third_party/libtiff/tif_fax3.h index b0f46c9a43f065ae346f6ba8622777e96f28b780..8a435059c7b3c95c2aa944fb61c3932fbbeb5f75 100644 --- a/third_party/libtiff/tif_fax3.h +++ b/third_party/libtiff/tif_fax3.h @@ -1,4 +1,4 @@ -/* $Id: tif_fax3.h,v 1.9 2011-03-10 20:23:07 fwarmerdam Exp $ */ +/* $Id: tif_fax3.h,v 1.13 2016-12-14 18:36:27 faxguy Exp $ */ /* * Copyright (c) 1990-1997 Sam Leffler @@ -39,7 +39,7 @@ /* * To override the default routine used to image decoded - * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC. + * spans one can use the pseudo tag TIFFTAG_FAXFILLFUNC. * The routine must have the type signature given below; * for example: * @@ -81,10 +81,12 @@ extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32); #define S_MakeUp 11 #define S_EOL 12 +/* WARNING: do not change the layout of this structure as the HylaFAX software */ +/* really depends on it. See http://bugzilla.maptools.org/show_bug.cgi?id=2636 */ typedef struct { /* state table entry */ unsigned char State; /* see above */ unsigned char Width; /* width of code in bits */ - uint32 Param; /* unsigned 32-bit run length in bits */ + uint32 Param; /* unsigned 32-bit run length in bits (holds on 16 bit actually, but cannot be changed. See above warning) */ } TIFFFaxTabEnt; extern const TIFFFaxTabEnt TIFFFaxMainTable[]; diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c index 5ed1b7a370ad5f5b472f39aad449e91678fd6813..d37f729c4617a04b06ec16838e4622f77800e09a 100644 --- a/third_party/libtiff/tif_getimage.c +++ b/third_party/libtiff/tif_getimage.c @@ -1,4 +1,4 @@ -/* $Id: tif_getimage.c,v 1.90 2015-06-17 01:34:08 bfriesen Exp $ */ +/* $Id: tif_getimage.c,v 1.106 2017-05-20 11:29:02 erouault Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler @@ -96,6 +96,10 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) td->td_bitspersample); return (0); } + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP) { + sprintf(emsg, "Sorry, can not handle images with IEEE floating-point samples"); + return (0); + } colorchannels = td->td_samplesperpixel - td->td_extrasamples; if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { switch (colorchannels) { @@ -183,27 +187,25 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) "Planarconfiguration", td->td_planarconfig); return (0); } - if( td->td_samplesperpixel != 3 || colorchannels != 3 ) - { - sprintf(emsg, - "Sorry, can not handle image with %s=%d, %s=%d", - "Samples/pixel", td->td_samplesperpixel, - "colorchannels", colorchannels); - return 0; - } + if ( td->td_samplesperpixel != 3 || colorchannels != 3 ) { + sprintf(emsg, + "Sorry, can not handle image with %s=%d, %s=%d", + "Samples/pixel", td->td_samplesperpixel, + "colorchannels", colorchannels); + return 0; + } break; case PHOTOMETRIC_CIELAB: - if( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 ) - { - sprintf(emsg, - "Sorry, can not handle image with %s=%d, %s=%d and %s=%d", - "Samples/pixel", td->td_samplesperpixel, - "colorchannels", colorchannels, - "Bits/sample", td->td_bitspersample); - return 0; - } + if ( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 ) { + sprintf(emsg, + "Sorry, can not handle image with %s=%d, %s=%d and %s=%d", + "Samples/pixel", td->td_samplesperpixel, + "colorchannels", colorchannels, + "Bits/sample", td->td_bitspersample); + return 0; + } break; - default: + default: sprintf(emsg, "Sorry, can not handle image with %s=%d", photoTag, photometric); return (0); @@ -214,20 +216,34 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) void TIFFRGBAImageEnd(TIFFRGBAImage* img) { - if (img->Map) - _TIFFfree(img->Map), img->Map = NULL; - if (img->BWmap) - _TIFFfree(img->BWmap), img->BWmap = NULL; - if (img->PALmap) - _TIFFfree(img->PALmap), img->PALmap = NULL; - if (img->ycbcr) - _TIFFfree(img->ycbcr), img->ycbcr = NULL; - if (img->cielab) - _TIFFfree(img->cielab), img->cielab = NULL; - if (img->UaToAa) - _TIFFfree(img->UaToAa), img->UaToAa = NULL; - if (img->Bitdepth16To8) - _TIFFfree(img->Bitdepth16To8), img->Bitdepth16To8 = NULL; + if (img->Map) { + _TIFFfree(img->Map); + img->Map = NULL; + } + if (img->BWmap) { + _TIFFfree(img->BWmap); + img->BWmap = NULL; + } + if (img->PALmap) { + _TIFFfree(img->PALmap); + img->PALmap = NULL; + } + if (img->ycbcr) { + _TIFFfree(img->ycbcr); + img->ycbcr = NULL; + } + if (img->cielab) { + _TIFFfree(img->cielab); + img->cielab = NULL; + } + if (img->UaToAa) { + _TIFFfree(img->UaToAa); + img->UaToAa = NULL; + } + if (img->Bitdepth16To8) { + _TIFFfree(img->Bitdepth16To8); + img->Bitdepth16To8 = NULL; + } if( img->redcmap ) { _TIFFfree( img->redcmap ); @@ -351,7 +367,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) } /* copy the colormaps so we can modify them */ - n_color = (1L << img->bitspersample); + n_color = (1U << img->bitspersample); img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); @@ -364,7 +380,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 ); _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 ); - /* fall thru... */ + /* fall through... */ case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: if (planarconfig == PLANARCONFIG_CONTIG @@ -512,7 +528,7 @@ TIFFReadRGBAImageOriented(TIFF* tif, int ok; if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) { - img.req_orientation = orientation; + img.req_orientation = (uint16)orientation; /* XXX verify rwidth and rheight against width and height */ ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, rwidth, img.height); @@ -611,7 +627,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 col, row, y, rowstoread; tmsize_t pos; uint32 tw, th; - unsigned char* buf; + unsigned char* buf = NULL; int32 fromskew, toskew; int64 safeskew; uint32 nrow; @@ -620,13 +636,14 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) int32 this_toskew, leftmost_toskew; int32 leftmost_fromskew; uint32 leftmost_tw; + tmsize_t bufsize; - buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); - return (0); + bufsize = TIFFTileSize(tif); + if (bufsize == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); + return (0); } - _TIFFmemset(buf, 0, TIFFTileSize(tif)); + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); @@ -643,14 +660,14 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) safeskew -= tw; safeskew +=w; } + if(safeskew > INT_MAX || safeskew < INT_MIN){ - _TIFFfree(buf); - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); - return (0); + _TIFFfree(buf); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); + return (0); } toskew = safeskew; - /* * Leftmost tile is clipped on left side if col_offset > 0. */ @@ -659,12 +676,12 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) safeskew = toskew; safeskew += leftmost_fromskew; if(safeskew > INT_MAX || safeskew < INT_MIN){ - _TIFFfree(buf); - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); - return (0); + _TIFFfree(buf); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); + return (0); } leftmost_toskew = safeskew; - for (row = 0; row < h; row += nrow) + for (row = 0; ret != 0 && row < h; row += nrow) { rowstoread = th - (row + img->row_offset) % th; nrow = (row + rowstoread > h ? h - row : rowstoread); @@ -675,8 +692,9 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) col = img->col_offset; while (tocol < w) { - if (TIFFReadTile(tif, buf, col, - row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr) + if (_TIFFReadTileAndAllocBuffer(tif, (void**) &buf, bufsize, col, + row+img->row_offset, 0, 0)==(tmsize_t)(-1) && + (buf == NULL || img->stoponerr)) { ret = 0; break; @@ -692,18 +710,18 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) safeskew -= w; safeskew += tocol; if(safeskew > INT_MAX || safeskew < INT_MIN){ - _TIFFfree(buf); - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); - return (0); + _TIFFfree(buf); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); + return (0); } fromskew = safeskew; this_tw = tw - fromskew; safeskew = toskew; safeskew += fromskew; if(safeskew > INT_MAX || safeskew < INT_MIN){ - _TIFFfree(buf); - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); - return (0); + _TIFFfree(buf); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "Invalid skew"); + return (0); } this_toskew = safeskew; } @@ -718,7 +736,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) this_toskew = toskew; } - y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow); } _TIFFfree(buf); @@ -733,7 +751,8 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 temp = *left; *left = *right; *right = temp; - left++, right--; + left++; + right--; } } } @@ -755,18 +774,18 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 col, row, y, rowstoread; tmsize_t pos; uint32 tw, th; - unsigned char* buf; - unsigned char* p0; - unsigned char* p1; - unsigned char* p2; - unsigned char* pa; + unsigned char* buf = NULL; + unsigned char* p0 = NULL; + unsigned char* p1 = NULL; + unsigned char* p2 = NULL; + unsigned char* pa = NULL; tmsize_t tilesize; tmsize_t bufsize; int32 fromskew, toskew; int alpha = img->alpha; uint32 nrow; int ret = 1, flip; - int colorchannels; + uint16 colorchannels; uint32 this_tw, tocol; int32 this_toskew, leftmost_toskew; int32 leftmost_fromskew; @@ -778,16 +797,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate"); return (0); } - buf = (unsigned char*) _TIFFmalloc(bufsize); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); - return (0); - } - _TIFFmemset(buf, 0, bufsize); - p0 = buf; - p1 = p0 + tilesize; - p2 = p1 + tilesize; - pa = (alpha?(p2+tilesize):NULL); + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); @@ -807,7 +817,6 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_PALETTE: colorchannels = 1; - p2 = p1 = p0; break; default: @@ -821,7 +830,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) leftmost_fromskew = img->col_offset % tw; leftmost_tw = tw - leftmost_fromskew; leftmost_toskew = toskew + leftmost_fromskew; - for (row = 0; row < h; row += nrow) + for (row = 0; ret != 0 && row < h; row += nrow) { rowstoread = th - (row + img->row_offset) % th; nrow = (row + rowstoread > h ? h - row : rowstoread); @@ -832,7 +841,30 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) col = img->col_offset; while (tocol < w) { - if (TIFFReadTile(tif, p0, col, + if( buf == NULL ) + { + if (_TIFFReadTileAndAllocBuffer( + tif, (void**) &buf, bufsize, col, + row+img->row_offset,0,0)==(tmsize_t)(-1) + && (buf == NULL || img->stoponerr)) + { + ret = 0; + break; + } + p0 = buf; + if( colorchannels == 1 ) + { + p2 = p1 = p0; + pa = (alpha?(p0+3*tilesize):NULL); + } + else + { + p1 = p0 + tilesize; + p2 = p1 + tilesize; + pa = (alpha?(p2+tilesize):NULL); + } + } + else if (TIFFReadTile(tif, p0, col, row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr) { ret = 0; @@ -886,7 +918,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) this_toskew = toskew; } - y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow); + y += ((flip & FLIP_VERTICALLY) ?-(int32) nrow : (int32) nrow); } if (flip & FLIP_HORIZONTALLY) { @@ -900,7 +932,8 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 temp = *left; *left = *right; *right = temp; - left++, right--; + left++; + right--; } } } @@ -922,13 +955,14 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) tileContigRoutine put = img->put.contig; uint32 row, y, nrow, nrowsub, rowstoread; tmsize_t pos; - unsigned char* buf; + unsigned char* buf = NULL; uint32 rowsperstrip; uint16 subsamplinghor,subsamplingver; uint32 imagewidth = img->width; tmsize_t scanline; int32 fromskew, toskew; int ret = 1, flip; + tmsize_t maxstripsize; TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); if( subsamplingver == 0 ) { @@ -936,12 +970,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) return (0); } - buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); - return (0); - } - _TIFFmemset(buf, 0, TIFFStripSize(tif)); + maxstripsize = TIFFStripSize(tif); flip = setorientation(img); if (flip & FLIP_VERTICALLY) { @@ -963,11 +992,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) nrowsub = nrow; if ((nrowsub%subsamplingver)!=0) nrowsub+=subsamplingver-nrowsub%subsamplingver; - if (TIFFReadEncodedStrip(tif, + if (_TIFFReadEncodedStripAndAllocBuffer(tif, TIFFComputeStrip(tif,row+img->row_offset, 0), - buf, + (void**)(&buf), + maxstripsize, ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) - && img->stoponerr) + && (buf == NULL || img->stoponerr)) { ret = 0; break; @@ -976,7 +1006,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) pos = ((row + img->row_offset) % rowsperstrip) * scanline + \ ((tmsize_t) img->col_offset * img->samplesperpixel); (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); - y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow); } if (flip & FLIP_HORIZONTALLY) { @@ -990,7 +1020,8 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 temp = *left; *left = *right; *right = temp; - left++, right--; + left++; + right--; } } } @@ -1010,8 +1041,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { TIFF* tif = img->tif; tileSeparateRoutine put = img->put.separate; - unsigned char *buf; - unsigned char *p0, *p1, *p2, *pa; + unsigned char *buf = NULL; + unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL; uint32 row, y, nrow, rowstoread; tmsize_t pos; tmsize_t scanline; @@ -1021,7 +1052,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) tmsize_t bufsize; int32 fromskew, toskew; int alpha = img->alpha; - int ret = 1, flip, colorchannels; + int ret = 1, flip; + uint16 colorchannels; stripsize = TIFFStripSize(tif); bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize); @@ -1029,15 +1061,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate"); return (0); } - p0 = buf = (unsigned char *)_TIFFmalloc(bufsize); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); - return (0); - } - _TIFFmemset(buf, 0, bufsize); - p1 = p0 + stripsize; - p2 = p1 + stripsize; - pa = (alpha?(p2+stripsize):NULL); flip = setorientation(img); if (flip & FLIP_VERTICALLY) { @@ -1055,7 +1078,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_PALETTE: colorchannels = 1; - p2 = p1 = p0; break; default: @@ -1071,7 +1093,31 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; nrow = (row + rowstoread > h ? h - row : rowstoread); offset_row = row + img->row_offset; - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), + if( buf == NULL ) + { + if (_TIFFReadEncodedStripAndAllocBuffer( + tif, TIFFComputeStrip(tif, offset_row, 0), + (void**) &buf, bufsize, + ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) + && (buf == NULL || img->stoponerr)) + { + ret = 0; + break; + } + p0 = buf; + if( colorchannels == 1 ) + { + p2 = p1 = p0; + pa = (alpha?(p0+3*stripsize):NULL); + } + else + { + p1 = p0 + stripsize; + p2 = p1 + stripsize; + pa = (alpha?(p2+stripsize):NULL); + } + } + else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) && img->stoponerr) { @@ -1109,7 +1155,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) ((tmsize_t) img->col_offset * img->samplesperpixel); (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); - y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow); } if (flip & FLIP_HORIZONTALLY) { @@ -1123,7 +1169,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 temp = *left; *left = *right; *right = temp; - left++, right--; + left++; + right--; } } } @@ -1147,11 +1194,15 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) #define REPEAT2(op) op; op #define CASE8(x,op) \ switch (x) { \ - case 7: op; case 6: op; case 5: op; \ - case 4: op; case 3: op; case 2: op; \ + case 7: op; /*-fallthrough*/ \ + case 6: op; /*-fallthrough*/ \ + case 5: op; /*-fallthrough*/ \ + case 4: op; /*-fallthrough*/ \ + case 3: op; /*-fallthrough*/ \ + case 2: op; /*-fallthrough*/ \ case 1: op; \ } -#define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } +#define CASE4(x,op) switch (x) { case 3: op; /*-fallthrough*/ case 2: op; /*-fallthrough*/ case 1: op; } #define NOP #define UNROLL8(w, op1, op2) { \ @@ -1451,7 +1502,7 @@ DECLAREContigPutFunc(putRGBUAcontig8bittile) uint8* m; for (x = w; x-- > 0;) { a = pp[3]; - m = img->UaToAa+(a<<8); + m = img->UaToAa+((size_t) a<<8); r = m[pp[0]]; g = m[pp[1]]; b = m[pp[2]]; @@ -1522,7 +1573,7 @@ DECLAREContigPutFunc(putRGBUAcontig16bittile) uint8* m; for (x = w; x-- > 0;) { a = img->Bitdepth16To8[wp[3]]; - m = img->UaToAa+(a<<8); + m = img->UaToAa+((size_t) a<<8); r = m[img->Bitdepth16To8[wp[0]]]; g = m[img->Bitdepth16To8[wp[1]]]; b = m[img->Bitdepth16To8[wp[2]]]; @@ -1653,7 +1704,7 @@ DECLARESepPutFunc(putRGBUAseparate8bittile) uint8* m; for (x = w; x-- > 0;) { av = *a++; - m = img->UaToAa+(av<<8); + m = img->UaToAa+((size_t) av<<8); rv = m[*r++]; gv = m[*g++]; bv = m[*b++]; @@ -1715,15 +1766,15 @@ DECLARESepPutFunc(putRGBUAseparate16bittile) uint16 *wa = (uint16*) a; (void) img; (void) y; while (h-- > 0) { - uint32 r,g,b,a; + uint32 r2,g2,b2,a2; uint8* m; for (x = w; x-- > 0;) { - a = img->Bitdepth16To8[*wa++]; - m = img->UaToAa+(a<<8); - r = m[img->Bitdepth16To8[*wr++]]; - g = m[img->Bitdepth16To8[*wg++]]; - b = m[img->Bitdepth16To8[*wb++]]; - *cp++ = PACK4(r,g,b,a); + a2 = img->Bitdepth16To8[*wa++]; + m = img->UaToAa+((size_t) a2<<8); + r2 = m[img->Bitdepth16To8[*wr++]]; + g2 = m[img->Bitdepth16To8[*wg++]]; + b2 = m[img->Bitdepth16To8[*wb++]]; + *cp++ = PACK4(r2,g2,b2,a2); } SKEW4(wr, wg, wb, wa, fromskew); cp += toskew; @@ -1878,10 +1929,16 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) YCbCrtoRGB(cp3[2], pp[14]); YCbCrtoRGB(cp3[3], pp[15]); - cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + cp += 4; + cp1 += 4; + cp2 += 4; + cp3 += 4; pp += 18; } while (--x); - cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + cp += incr; + cp1 += incr; + cp2 += incr; + cp3 += incr; pp += fromskew; } } else { @@ -1932,7 +1989,10 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) if (h <= 4) break; h -= 4; - cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + cp += incr; + cp1 += incr; + cp2 += incr; + cp3 += incr; pp += fromskew; } } @@ -1964,10 +2024,12 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) YCbCrtoRGB(cp1[2], pp[6]); YCbCrtoRGB(cp1[3], pp[7]); - cp += 4, cp1 += 4; + cp += 4; + cp1 += 4; pp += 10; } while (--x); - cp += incr, cp1 += incr; + cp += incr; + cp1 += incr; pp += fromskew; } } else { @@ -2010,7 +2072,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) if (h <= 2) break; h -= 2; - cp += incr, cp1 += incr; + cp += incr; + cp1 += incr; pp += fromskew; } } @@ -2045,9 +2108,9 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) int32 Cr = pp[5]; switch( (w&3) ) { - case 3: YCbCrtoRGB(cp [2], pp[2]); - case 2: YCbCrtoRGB(cp [1], pp[1]); - case 1: YCbCrtoRGB(cp [0], pp[0]); + case 3: YCbCrtoRGB(cp [2], pp[2]); /*-fallthrough*/ + case 2: YCbCrtoRGB(cp [1], pp[1]); /*-fallthrough*/ + case 1: YCbCrtoRGB(cp [0], pp[0]); /*-fallthrough*/ case 0: break; } @@ -2237,6 +2300,11 @@ DECLARESepPutFunc(putseparate8bitYCbCr11tile) } #undef YCbCrtoRGB +static int isInRefBlackWhiteRange(float f) +{ + return f >= (float)(-0x7FFFFFFF + 128) && f <= (float)0x7FFFFFFF; +} + static int initYCbCrConversion(TIFFRGBAImage* img) { @@ -2261,6 +2329,31 @@ initYCbCrConversion(TIFFRGBAImage* img) TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma); TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE, &refBlackWhite); + + /* Do some validation to avoid later issues. Detect NaN for now */ + /* and also if lumaGreen is zero since we divide by it later */ + if( luma[0] != luma[0] || + luma[1] != luma[1] || + luma[1] == 0.0 || + luma[2] != luma[2] ) + { + TIFFErrorExt(img->tif->tif_clientdata, module, + "Invalid values for YCbCrCoefficients tag"); + return (0); + } + + if( !isInRefBlackWhiteRange(refBlackWhite[0]) || + !isInRefBlackWhiteRange(refBlackWhite[1]) || + !isInRefBlackWhiteRange(refBlackWhite[2]) || + !isInRefBlackWhiteRange(refBlackWhite[3]) || + !isInRefBlackWhiteRange(refBlackWhite[4]) || + !isInRefBlackWhiteRange(refBlackWhite[5]) ) + { + TIFFErrorExt(img->tif->tif_clientdata, module, + "Invalid values for ReferenceBlackWhite tag"); + return (0); + } + if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0) return(0); return (1); @@ -2399,7 +2492,8 @@ setupMap(TIFFRGBAImage* img) if (!makebwmap(img)) return (0); /* no longer need Map, free it */ - _TIFFfree(img->Map), img->Map = NULL; + _TIFFfree(img->Map); + img->Map = NULL; } return (1); } @@ -2507,7 +2601,7 @@ buildMap(TIFFRGBAImage* img) case PHOTOMETRIC_SEPARATED: if (img->bitspersample == 8) break; - /* fall thru... */ + /* fall through... */ case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: if (!setupMap(img)) @@ -2777,7 +2871,7 @@ BuildMapUaToAa(TIFFRGBAImage* img) for (na=0; na<256; na++) { for (nv=0; nv<256; nv++) - *m++=(nv*na+127)/255; + *m++=(uint8)((nv*na+127)/255); } return(1); } @@ -2797,7 +2891,7 @@ BuildMapBitdepth16To8(TIFFRGBAImage* img) } m=img->Bitdepth16To8; for (n=0; n<65536; n++) - *m++=(n+128)/257; + *m++=(uint8)((n+128)/257); return(1); } @@ -2813,6 +2907,13 @@ BuildMapBitdepth16To8(TIFFRGBAImage* img) int TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) +{ + return TIFFReadRGBAStripExt(tif, row, raster, 0 ); +} + +int +TIFFReadRGBAStripExt(TIFF* tif, uint32 row, uint32 * raster, int stop_on_error) + { char emsg[1024] = ""; TIFFRGBAImage img; @@ -2834,7 +2935,7 @@ TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) return (0); } - if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) { img.row_offset = row; img.col_offset = 0; @@ -2864,6 +2965,13 @@ TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) int TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) +{ + return TIFFReadRGBATileExt(tif, col, row, raster, 0 ); +} + + +int +TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop_on_error ) { char emsg[1024] = ""; TIFFRGBAImage img; @@ -2899,7 +3007,7 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) */ if (!TIFFRGBAImageOK(tif, emsg) - || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + || !TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); return( 0 ); } diff --git a/third_party/libtiff/tif_jpeg.c b/third_party/libtiff/tif_jpeg.c index 66599092994de5eed9fa23bbd544010faeabced1..df06e03fab22ccf99b7a38272b0846eb97b83deb 100644 --- a/third_party/libtiff/tif_jpeg.c +++ b/third_party/libtiff/tif_jpeg.c @@ -1,4 +1,4 @@ -/* $Id: tif_jpeg.c,v 1.119 2015-08-15 20:13:07 bfriesen Exp $ */ +/* $Id: tif_jpeg.c,v 1.127 2017-01-31 13:02:27 erouault Exp $ */ /* * Copyright (c) 1994-1997 Sam Leffler @@ -58,7 +58,7 @@ int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode ); Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is not defined. Unfortunately, the MinGW and Borland compilers include a typedef for INT32, which causes a conflict. MSVC does not include - a conficting typedef given the headers which are included. + a conflicting typedef given the headers which are included. */ #if defined(__BORLANDC__) || defined(__MINGW32__) # define XMD_H 1 @@ -705,9 +705,11 @@ static int JPEGFixupTags(TIFF* tif) { #ifdef CHECK_JPEG_YCBCR_SUBSAMPLING + JPEGState* sp = JState(tif); if ((tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR)&& (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&& - (tif->tif_dir.td_samplesperpixel==3)) + (tif->tif_dir.td_samplesperpixel==3) && + !sp->ycbcrsampling_fetched) JPEGFixupTagsSubsampling(tif); #endif @@ -945,7 +947,7 @@ JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* data, uint16 s else { uint16 m; - m=skiplength-data->bufferbytesleft; + m=(uint16)(skiplength-data->bufferbytesleft); if (m<=data->filebytesleft) { data->bufferbytesleft=0; @@ -1291,7 +1293,7 @@ JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) if( line_work_buf != NULL ) { /* - * In the MK1 case, we aways read into a 16bit + * In the MK1 case, we always read into a 16bit * buffer, and then pack down to 12bit or 8bit. * In 6B case we only read into 16 bit buffer * for 12bit data, which we need to repack. @@ -1311,10 +1313,10 @@ JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) ((unsigned char *) buf) + iPair * 3; JSAMPLE *in_ptr = line_work_buf + iPair * 2; - out_ptr[0] = (in_ptr[0] & 0xff0) >> 4; - out_ptr[1] = ((in_ptr[0] & 0xf) << 4) - | ((in_ptr[1] & 0xf00) >> 8); - out_ptr[2] = ((in_ptr[1] & 0xff) >> 0); + out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); + out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) + | ((in_ptr[1] & 0xf00) >> 8)); + out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); } } else if( sp->cinfo.d.data_precision == 8 ) @@ -1375,7 +1377,7 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) (void) s; /* data is expected to be read in multiples of a scanline */ - if ( (nrows = sp->cinfo.d.image_height) ) { + if ( (nrows = sp->cinfo.d.image_height) != 0 ) { /* Cb,Cr both have sampling factors 1, so this is correct */ JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; @@ -1475,10 +1477,10 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3; JSAMPLE *in_ptr = (JSAMPLE *) (tmpbuf + iPair * 2); - out_ptr[0] = (in_ptr[0] & 0xff0) >> 4; - out_ptr[1] = ((in_ptr[0] & 0xf) << 4) - | ((in_ptr[1] & 0xf00) >> 8); - out_ptr[2] = ((in_ptr[1] & 0xff) >> 0); + out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); + out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) + | ((in_ptr[1] & 0xf00) >> 8)); + out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); } } } @@ -1634,6 +1636,20 @@ JPEGSetupEncode(TIFF* tif) case PHOTOMETRIC_YCBCR: sp->h_sampling = td->td_ycbcrsubsampling[0]; sp->v_sampling = td->td_ycbcrsubsampling[1]; + if( sp->h_sampling == 0 || sp->v_sampling == 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalig horizontal/vertical sampling value"); + return (0); + } + if( td->td_bitspersample > 16 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "BitsPerSample %d not allowed for JPEG", + td->td_bitspersample); + return (0); + } + /* * A ReferenceBlackWhite field *must* be present since the * default value is inappropriate for YCbCr. Fill in the @@ -1901,7 +1917,7 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) if( sp->cinfo.c.data_precision == 12 ) { - line16_count = (sp->bytesperline * 2) / 3; + line16_count = (int)((sp->bytesperline * 2) / 3); line16 = (short *) _TIFFmalloc(sizeof(short) * line16_count); if (!line16) { @@ -2146,8 +2162,7 @@ JPEGVSetField(TIFF* tif, uint32 tag, va_list ap) /* XXX */ return (0); } - _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), - (long) v32); + _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), v32); sp->jpegtables_length = v32; TIFFSetFieldBit(tif, FIELD_JPEGTABLES); break; @@ -2176,7 +2191,7 @@ JPEGVSetField(TIFF* tif, uint32 tag, va_list ap) return (*sp->vsetparent)(tif, tag, ap); } - if ((fip = TIFFFieldWithTag(tif, tag))) { + if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) { TIFFSetFieldBit(tif, fip->field_bit); } else { return (0); @@ -2300,6 +2315,15 @@ static int JPEGInitializeLibJPEG( TIFF * tif, int decompress ) } else { if (!TIFFjpeg_create_compress(sp)) return (0); +#ifndef TIFF_JPEG_MAX_MEMORY_TO_USE +#define TIFF_JPEG_MAX_MEMORY_TO_USE (10 * 1024 * 1024) +#endif + /* Increase the max memory usable. This helps when creating files */ + /* with "big" tile, without using libjpeg temporary files. */ + /* For example a 512x512 tile with 3 bands */ + /* requires 1.5 MB which is above libjpeg 1MB default */ + if( sp->cinfo.c.mem->max_memory_to_use < TIFF_JPEG_MAX_MEMORY_TO_USE ) + sp->cinfo.c.mem->max_memory_to_use = TIFF_JPEG_MAX_MEMORY_TO_USE; } sp->cinfo_initialized = TRUE; diff --git a/third_party/libtiff/tif_luv.c b/third_party/libtiff/tif_luv.c index 01f39c0d636ede8c2ede35d4a547350ea8b593e7..59d0a74cc6bdab1d6bd9ff26ae7a85771e597dbc 100644 --- a/third_party/libtiff/tif_luv.c +++ b/third_party/libtiff/tif_luv.c @@ -1,4 +1,4 @@ -/* $Id: tif_luv.c,v 1.40 2015-06-21 01:09:09 bfriesen Exp $ */ +/* $Id: tif_luv.c,v 1.47 2017-05-14 10:17:27 erouault Exp $ */ /* * Copyright (c) 1997 Greg Ward Larson @@ -158,6 +158,7 @@ typedef struct logLuvState LogLuvState; struct logLuvState { + int encoder_state; /* 1 if encoder correctly initialized */ int user_datafmt; /* user data format */ int encode_meth; /* encoding method */ int pixel_size; /* bytes per pixel */ @@ -401,8 +402,10 @@ LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) return 0; assert(cc%rowlen == 0); - while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) - bp += rowlen, cc -= rowlen; + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) { + bp += rowlen; + cc -= rowlen; + } return (cc == 0); } @@ -420,8 +423,10 @@ LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) return 0; assert(cc%rowlen == 0); - while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) - bp += rowlen, cc -= rowlen; + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) { + bp += rowlen; + cc -= rowlen; + } return (cc == 0); } @@ -468,7 +473,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } @@ -500,7 +505,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } @@ -560,7 +565,7 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } @@ -619,7 +624,7 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } @@ -651,7 +656,7 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } @@ -687,8 +692,10 @@ LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) return 0; assert(cc%rowlen == 0); - while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) - bp += rowlen, cc -= rowlen; + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) { + bp += rowlen; + cc -= rowlen; + } return (cc == 0); } @@ -705,8 +712,10 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) return 0; assert(cc%rowlen == 0); - while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) - bp += rowlen, cc -= rowlen; + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) { + bp += rowlen; + cc -= rowlen; + } return (cc == 0); } @@ -1255,15 +1264,16 @@ LogL16GuessDataFmt(TIFFDirectory *td) return (SGILOGDATAFMT_UNKNOWN); } + +#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) +#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) + static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2) { - tmsize_t bytes = m1 * m2; - - if (m1 && bytes / m1 != m2) - bytes = 0; - - return bytes; + if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) + return 0; + return m1 * m2; } static int @@ -1276,6 +1286,14 @@ LogL16InitState(TIFF* tif) assert(sp != NULL); assert(td->td_photometric == PHOTOMETRIC_LOGL); + if( td->td_samplesperpixel != 1 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sorry, can not handle LogL image with %s=%d", + "Samples/pixel", td->td_samplesperpixel); + return 0; + } + /* for some reason, we can't do this in TIFFInitLogL16 */ if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) sp->user_datafmt = LogL16GuessDataFmt(td); @@ -1296,8 +1314,10 @@ LogL16InitState(TIFF* tif) } if( isTiled(tif) ) sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength); - else + else if( td->td_rowsperstrip != (uint32)-1 ) sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip); + else + sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength); if (multiply_ms(sp->tbuflen, sizeof (int16)) == 0 || (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) { TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer"); @@ -1536,6 +1556,7 @@ LogLuvSetupEncode(TIFF* tif) td->td_photometric, "must be either LogLUV or LogL"); break; } + sp->encoder_state = 1; return (1); notsupported: TIFFErrorExt(tif->tif_clientdata, module, @@ -1547,19 +1568,27 @@ notsupported: static void LogLuvClose(TIFF* tif) { + LogLuvState* sp = (LogLuvState*) tif->tif_data; TIFFDirectory *td = &tif->tif_dir; + assert(sp != 0); /* * For consistency, we always want to write out the same * bitspersample and sampleformat for our TIFF file, * regardless of the data format being used by the application. * Since this routine is called after tags have been set but * before they have been recorded in the file, we reset them here. + * Note: this is really a nasty approach. See PixarLogClose */ - td->td_samplesperpixel = - (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; - td->td_bitspersample = 16; - td->td_sampleformat = SAMPLEFORMAT_INT; + if( sp->encoder_state ) + { + /* See PixarLogClose. Might avoid issues with tags whose size depends + * on those below, but not completely sure this is enough. */ + td->td_samplesperpixel = + (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; + td->td_bitspersample = 16; + td->td_sampleformat = SAMPLEFORMAT_INT; + } } static void @@ -1598,17 +1627,21 @@ LogLuvVSetField(TIFF* tif, uint32 tag, va_list ap) */ switch (sp->user_datafmt) { case SGILOGDATAFMT_FLOAT: - bps = 32, fmt = SAMPLEFORMAT_IEEEFP; + bps = 32; + fmt = SAMPLEFORMAT_IEEEFP; break; case SGILOGDATAFMT_16BIT: - bps = 16, fmt = SAMPLEFORMAT_INT; + bps = 16; + fmt = SAMPLEFORMAT_INT; break; case SGILOGDATAFMT_RAW: - bps = 32, fmt = SAMPLEFORMAT_UINT; + bps = 32; + fmt = SAMPLEFORMAT_UINT; TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); break; case SGILOGDATAFMT_8BIT: - bps = 8, fmt = SAMPLEFORMAT_UINT; + bps = 8; + fmt = SAMPLEFORMAT_UINT; break; default: TIFFErrorExt(tif->tif_clientdata, tif->tif_name, diff --git a/third_party/libtiff/tif_lzw.c b/third_party/libtiff/tif_lzw.c index 9b76dd03b3919ca24df4e994fdd35c349085ae16..5f1acf83da014ccdbd6538a5257e8f13d2e6dd1d 100644 --- a/third_party/libtiff/tif_lzw.c +++ b/third_party/libtiff/tif_lzw.c @@ -1,4 +1,4 @@ -/* $Id: tif_lzw.c,v 1.49 2015-08-30 21:07:44 erouault Exp $ */ +/* $Id: tif_lzw.c,v 1.55 2017-05-17 09:38:58 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -240,8 +240,8 @@ LZWSetupDecode(TIFF* tif) */ code = 255; do { - sp->dec_codetab[code].value = code; - sp->dec_codetab[code].firstchar = code; + sp->dec_codetab[code].value = (unsigned char)code; + sp->dec_codetab[code].firstchar = (unsigned char)code; sp->dec_codetab[code].length = 1; sp->dec_codetab[code].next = NULL; } while (code--); @@ -318,7 +318,7 @@ LZWPreDecode(TIFF* tif, uint16 s) sp->dec_restart = 0; sp->dec_nbitsmask = MAXCODE(BITS_MIN); #ifdef LZW_CHECKEOS - sp->dec_bitsleft = ((uint64)tif->tif_rawcc) << 3; + sp->dec_bitsleft = 0; #endif sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; /* @@ -411,19 +411,23 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) /* * Residue satisfies only part of the decode request. */ - op += residue, occ -= residue; + op += residue; + occ -= residue; tp = op; do { int t; --tp; t = codep->value; codep = codep->next; - *tp = t; + *tp = (char)t; } while (--residue && codep); sp->dec_restart = 0; } bp = (unsigned char *)tif->tif_rawcp; +#ifdef LZW_CHECKEOS + sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3); +#endif nbits = sp->lzw_nbits; nextdata = sp->lzw_nextdata; nextbits = sp->lzw_nextbits; @@ -454,7 +458,8 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) tif->tif_row); return (0); } - *op++ = (char)code, occ--; + *op++ = (char)code; + occ--; oldcodep = sp->dec_codetab + code; continue; } @@ -532,18 +537,22 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) --tp; t = codep->value; codep = codep->next; - *tp = t; + *tp = (char)t; } while (codep && tp > op); if (codep) { codeLoop(tif, module); break; } assert(occ >= len); - op += len, occ -= len; - } else - *op++ = (char)code, occ--; + op += len; + occ -= len; + } else { + *op++ = (char)code; + occ--; + } } + tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp ); tif->tif_rawcp = (uint8*) bp; sp->lzw_nbits = (unsigned short) nbits; sp->lzw_nextdata = nextdata; @@ -635,7 +644,8 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) /* * Residue satisfies only part of the decode request. */ - op += residue, occ -= residue; + op += residue; + occ -= residue; tp = op; do { *--tp = codep->value; @@ -675,7 +685,8 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) tif->tif_row); return (0); } - *op++ = code, occ--; + *op++ = (char)code; + occ--; oldcodep = sp->dec_codetab + code; continue; } @@ -741,17 +752,20 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) break; } assert(occ >= codep->length); - op += codep->length, occ -= codep->length; + op += codep->length; + occ -= codep->length; tp = op; do { *--tp = codep->value; } while( (codep = codep->next) != NULL ); - } else - *op++ = code, occ--; + } else { + *op++ = (char)code; + occ--; + } } tif->tif_rawcp = (uint8*) bp; - sp->lzw_nbits = nbits; + sp->lzw_nbits = (unsigned short)nbits; sp->lzw_nextdata = nextdata; sp->lzw_nextbits = nextbits; sp->dec_nbitsmask = nbitsmask; @@ -900,7 +914,7 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) nbits = sp->lzw_nbits; op = tif->tif_rawcp; limit = sp->enc_rawlimit; - ent = sp->enc_oldcode; + ent = (hcode_t)sp->enc_oldcode; if (ent == (hcode_t) -1 && cc > 0) { /* @@ -936,7 +950,7 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) disp = 1; do { /* - * Avoid pointer arithmetic 'cuz of + * Avoid pointer arithmetic because of * wraparound problems with segments. */ if ((h -= disp) < 0) @@ -959,12 +973,13 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) */ if (op > limit) { tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); - TIFFFlushData1(tif); + if( !TIFFFlushData1(tif) ) + return 0; op = tif->tif_rawdata; } PutNextCode(op, ent); - ent = c; - hp->code = free_ent++; + ent = (hcode_t)c; + hp->code = (hcode_t)(free_ent++); hp->hash = fcode; if (free_ent == CODE_MAX-1) { /* table is full, emit clear code and reset */ @@ -1021,9 +1036,9 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) sp->enc_oldcode = ent; sp->lzw_nextdata = nextdata; sp->lzw_nextbits = nextbits; - sp->lzw_free_ent = free_ent; - sp->lzw_maxcode = maxcode; - sp->lzw_nbits = nbits; + sp->lzw_free_ent = (unsigned short)free_ent; + sp->lzw_maxcode = (unsigned short)maxcode; + sp->lzw_nbits = (unsigned short)nbits; tif->tif_rawcp = op; return (1); } @@ -1044,12 +1059,32 @@ LZWPostEncode(TIFF* tif) if (op > sp->enc_rawlimit) { tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); - TIFFFlushData1(tif); + if( !TIFFFlushData1(tif) ) + return 0; op = tif->tif_rawdata; } if (sp->enc_oldcode != (hcode_t) -1) { + int free_ent = sp->lzw_free_ent; + PutNextCode(op, sp->enc_oldcode); sp->enc_oldcode = (hcode_t) -1; + free_ent ++; + + if (free_ent == CODE_MAX-1) { + /* table is full, emit clear code and reset */ + outcount = 0; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + } else { + /* + * If the next entry is going to be too big for + * the code size, then increase it, if possible. + */ + if (free_ent > sp->lzw_maxcode) { + nbits++; + assert(nbits <= BITS_MAX); + } + } } PutNextCode(op, CODE_EOI); /* Explicit 0xff masking to make icc -check=conversions happy */ diff --git a/third_party/libtiff/tif_next.c b/third_party/libtiff/tif_next.c index b2076a0b01755bf976ddc31b6f5df3629c28fc05..08211788acb8d2df76bdf1d3ce38363172b59174 100644 --- a/third_party/libtiff/tif_next.c +++ b/third_party/libtiff/tif_next.c @@ -1,4 +1,4 @@ -/* $Id: tif_next.c,v 1.16 2014-12-29 12:09:11 erouault Exp $ */ +/* $Id: tif_next.c,v 1.19 2016-09-04 21:32:56 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -72,7 +72,8 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) return (0); } for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline) { - n = *bp++, cc--; + n = *bp++; + cc--; switch (n) { case LITERALROW: /* @@ -103,10 +104,10 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) } default: { uint32 npixels = 0, grey; + tmsize_t op_offset = 0; uint32 imagewidth = tif->tif_dir.td_imagewidth; if( isTiled(tif) ) imagewidth = tif->tif_dir.td_tilewidth; - tmsize_t op_offset = 0; /* * The scanline is composed of a sequence of constant @@ -134,7 +135,8 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) } if (cc == 0) goto bad; - n = *bp++, cc--; + n = *bp++; + cc--; } break; } diff --git a/third_party/libtiff/tif_ojpeg.c b/third_party/libtiff/tif_ojpeg.c index 276d562dfbe743fa161b56e565351597672c6ca1..60e4eca91908b1596053acfdbdb0f50d60fbcea8 100644 --- a/third_party/libtiff/tif_ojpeg.c +++ b/third_party/libtiff/tif_ojpeg.c @@ -1,4 +1,4 @@ -/* $Id: tif_ojpeg.c,v 1.60 2015-05-31 00:38:46 bfriesen Exp $ */ +/* $Id: tif_ojpeg.c,v 1.69 2017-04-27 17:29:26 erouault Exp $ */ /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0 specification is now totally obsolete and deprecated for new applications and @@ -75,7 +75,7 @@ OJPEGSubsamplingCorrect, making no note of any other data, reporting no warnings or errors, up to the point where either these values are read, or it's clear they aren't there. This means that some of the data is read twice, but we feel speed - in correcting these values is important enough to warrant this sacrifice. Allthough + in correcting these values is important enough to warrant this sacrifice. Although there is currently no define or other configuration mechanism to disable this behaviour, the actual header scanning is build to robustly respond with error report if it should encounter an uncorrected mismatch of subsampling values. See @@ -84,7 +84,7 @@ The restart interval and restart markers are the most tricky part... The restart interval can be specified in a tag. It can also be set inside the input JPEG stream. It can be used inside the input JPEG stream. If reading from strile data, we've - consistenly discovered the need to insert restart markers in between the different + consistently discovered the need to insert restart markers in between the different striles, as is also probably the most likely interpretation of the original TIFF 6.0 specification. With all this setting of interval, and actual use of markers that is not predictable at the time of valid JPEG header assembly, the restart thing may turn @@ -113,7 +113,7 @@ planarconfig is not separate (vast majority). We may one day use that to build converters to JPEG, and/or to new-style JPEG compression inside TIFF. - A dissadvantage is the lack of random access to the individual striles. This is the + A disadvantage is the lack of random access to the individual striles. This is the reason for much of the complicated restart-and-position stuff inside OJPEGPreDecode. Applications would do well accessing all striles in order, as this will result in a single sequential scan of the input stream, and no restarting of LibJpeg decoding @@ -135,7 +135,7 @@ * The default mode, without JPEG_ENCAP_EXTERNAL, implements the call encapsulators * here, internally, with normal longjump. * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent is - * conviniently available, but still it may be worthwhile to use _setjmp or sigsetjmp + * conveniently available, but still it may be worthwhile to use _setjmp or sigsetjmp * in place of plain setjmp. These macros will make it easier. It is useless * to fiddle with these if you define JPEG_ENCAP_EXTERNAL. * OJPEG_BUFFER: Define the size of the desired buffer here. Should be small enough so as to guarantee @@ -200,7 +200,7 @@ static const TIFFField ojpegFields[] = { Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is not defined. Unfortunately, the MinGW and Borland compilers include a typedef for INT32, which causes a conflict. MSVC does not include - a conficting typedef given the headers which are included. + a conflicting typedef given the headers which are included. */ #if defined(__BORLANDC__) || defined(__MINGW32__) # define XMD_H 1 @@ -253,6 +253,7 @@ typedef enum { typedef struct { TIFF* tif; + int decoder_ok; #ifndef LIBJPEG_ENCAP_EXTERNAL JMP_BUF exit_jmpbuf; #endif @@ -731,6 +732,7 @@ OJPEGPreDecode(TIFF* tif, uint16 s) } sp->write_curstrile++; } + sp->decoder_ok = 1; return(1); } @@ -793,8 +795,14 @@ OJPEGPreDecodeSkipScanlines(TIFF* tif) static int OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { + static const char module[]="OJPEGDecode"; OJPEGState* sp=(OJPEGState*)tif->tif_data; (void)s; + if( !sp->decoder_ok ) + { + TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized"); + return 0; + } if (sp->libjpeg_jpeg_query_style==0) { if (OJPEGDecodeRaw(tif,buf,cc)==0) @@ -1090,7 +1098,7 @@ OJPEGReadHeaderInfo(TIFF* tif) TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); return(0); } - sp->restart_interval=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8)); + sp->restart_interval=(uint16)(((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8))); } if (OJPEGReadHeaderInfoSec(tif)==0) return(0); @@ -1112,7 +1120,7 @@ OJPEGReadSecondarySos(TIFF* tif, uint16 s) assert(s<3); assert(sp->sos_end[0].log!=0); assert(sp->sos_end[s].log==0); - sp->plane_sample_offset=s-1; + sp->plane_sample_offset=(uint8)(s-1); while(sp->sos_end[sp->plane_sample_offset].log==0) sp->plane_sample_offset--; sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source; @@ -1390,7 +1398,8 @@ OJPEGReadHeaderInfoSec(TIFF* tif) static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif) { - /* this could easilly cause trouble in some cases... but no such cases have occured sofar */ + /* This could easily cause trouble in some cases... but no such cases have + occurred so far */ static const char module[]="OJPEGReadHeaderInfoSecStreamDri"; OJPEGState* sp=(OJPEGState*)tif->tif_data; uint16 m; @@ -1788,12 +1797,12 @@ OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif) ob[sizeof(uint32)+3]=67; ob[sizeof(uint32)+4]=m; TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); + p=(uint32)TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); if (p!=64) - { - _TIFFfree(ob); + { + _TIFFfree(ob); return(0); - } + } if (sp->qtable[m]!=0) _TIFFfree(sp->qtable[m]); sp->qtable[m]=ob; @@ -1836,7 +1845,7 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) } } TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,o,16); + p=(uint32)TIFFReadFile(tif,o,16); if (p!=16) return(0); q=0; @@ -1852,17 +1861,17 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) *(uint32*)rb=ra; rb[sizeof(uint32)]=255; rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; - rb[sizeof(uint32)+2]=((19+q)>>8); + rb[sizeof(uint32)+2]=(uint8)((19+q)>>8); rb[sizeof(uint32)+3]=((19+q)&255); rb[sizeof(uint32)+4]=m; for (n=0; n<16; n++) rb[sizeof(uint32)+5+n]=o[n]; - p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); + p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); if (p!=q) - { - _TIFFfree(rb); + { + _TIFFfree(rb); return(0); - } + } if (sp->dctable[m]!=0) _TIFFfree(sp->dctable[m]); sp->dctable[m]=rb; @@ -1905,7 +1914,7 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) } } TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,o,16); + p=(uint32)TIFFReadFile(tif,o,16); if (p!=16) return(0); q=0; @@ -1921,18 +1930,18 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) *(uint32*)rb=ra; rb[sizeof(uint32)]=255; rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; - rb[sizeof(uint32)+2]=((19+q)>>8); + rb[sizeof(uint32)+2]=(uint8)((19+q)>>8); rb[sizeof(uint32)+3]=((19+q)&255); rb[sizeof(uint32)+4]=(16|m); for (n=0; n<16; n++) rb[sizeof(uint32)+5+n]=o[n]; - p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); + p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); if (p!=q) - { - _TIFFfree(rb); + { + _TIFFfree(rb); return(0); - } - if (sp->actable[m]) + } + if (sp->actable[m]!=0) _TIFFfree(sp->actable[m]); sp->actable[m]=rb; sp->sos_tda[m]=(sp->sos_tda[m]|m); @@ -2293,10 +2302,10 @@ OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len) /* P */ sp->out_buffer[4]=8; /* Y */ - sp->out_buffer[5]=(sp->sof_y>>8); + sp->out_buffer[5]=(uint8)(sp->sof_y>>8); sp->out_buffer[6]=(sp->sof_y&255); /* X */ - sp->out_buffer[7]=(sp->sof_x>>8); + sp->out_buffer[7]=(uint8)(sp->sof_x>>8); sp->out_buffer[8]=(sp->sof_x&255); /* Nf */ sp->out_buffer[9]=sp->samples_per_pixel_per_plane; @@ -2409,7 +2418,12 @@ OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len) static int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_create_decompress(cinfo); + return 1; + } } #endif @@ -2417,7 +2431,12 @@ jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) static int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_read_header(cinfo,require_image); + return 1; + } } #endif @@ -2425,7 +2444,12 @@ jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 requ static int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_start_decompress(cinfo); + return 1; + } } #endif @@ -2433,7 +2457,12 @@ jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) static int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_read_scanlines(cinfo,scanlines,max_lines); + return 1; + } } #endif @@ -2441,7 +2470,12 @@ jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* s static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_read_raw_data(cinfo,data,max_lines); + return 1; + } } #endif @@ -2503,6 +2537,10 @@ OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_b jpeg_encap_unwind(tif); } +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) /* unreachable code */ +#endif static boolean OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired) { @@ -2512,6 +2550,9 @@ OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desi jpeg_encap_unwind(tif); return(0); } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo) diff --git a/third_party/libtiff/tif_open.c b/third_party/libtiff/tif_open.c index 8c88328cf28d995d568c497b4cfb35f5ccb1c73c..a7279e1ea057c9249d65880a787bdf663f358bb4 100644 --- a/third_party/libtiff/tif_open.c +++ b/third_party/libtiff/tif_open.c @@ -1,4 +1,4 @@ -/* $Id: tif_open.c,v 1.46 2010-12-06 16:54:54 faxguy Exp $ */ +/* $Id: tif_open.c,v 1.48 2016-11-20 22:29:47 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -168,7 +168,7 @@ TIFFClientOpen( * The following flags may be used to control intrinsic library * behaviour that may or may not be desirable (usually for * compatibility with some application that claims to support - * TIFF but only supports some braindead idea of what the + * TIFF but only supports some brain dead idea of what the * vendor thinks TIFF is): * * 'l' use little-endian byte order for creating a file @@ -198,8 +198,8 @@ TIFFClientOpen( * The 'L', 'B', and 'H' flags are intended for applications * that can optimize operations on data by using a particular * bit order. By default the library returns data in MSB2LSB - * bit order for compatibiltiy with older versions of this - * library. Returning data in the bit order of the native cpu + * bit order for compatibility with older versions of this + * library. Returning data in the bit order of the native CPU * makes the most sense but also requires applications to check * the value of the FillOrder tag; something they probably do * not do right now. @@ -279,10 +279,10 @@ TIFFClientOpen( * Setup header and write. */ #ifdef WORDS_BIGENDIAN - tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB + tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; #else - tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB + tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; #endif if (!(tif->tif_flags&TIFF_BIGTIFF)) diff --git a/third_party/libtiff/tif_packbits.c b/third_party/libtiff/tif_packbits.c index 9e77190131e97b00a35d272403a251c896116740..18904b01370d6e2ce09512f4b777071de058596a 100644 --- a/third_party/libtiff/tif_packbits.c +++ b/third_party/libtiff/tif_packbits.c @@ -1,4 +1,4 @@ -/* $Id: tif_packbits.c,v 1.22 2012-06-20 05:25:33 fwarmerdam Exp $ */ +/* $Id: tif_packbits.c,v 1.26 2017-05-14 02:26:07 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -38,7 +38,8 @@ PackBitsPreEncode(TIFF* tif, uint16 s) { (void) s; - if (!(tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t)))) + tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t)); + if (tif->tif_data == NULL) return (0); /* * Calculate the scanline/tile-width size in bytes. @@ -81,7 +82,9 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) /* * Find the longest string of identical bytes. */ - b = *bp++, cc--, n = 1; + b = *bp++; + cc--; + n = 1; for (; cc > 0 && b == *bp; cc--, bp++) n++; again: @@ -96,7 +99,7 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) slop = (long)(op - lastliteral); tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp); if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; while (slop-- > 0) *op++ = *lastliteral++; @@ -104,7 +107,7 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) } else { tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp); if (!TIFFFlushData1(tif)) - return (-1); + return (0); op = tif->tif_rawcp; } } @@ -222,7 +225,8 @@ PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) bp = (char*) tif->tif_rawcp; cc = tif->tif_rawcc; while (cc > 0 && occ > 0) { - n = (long) *bp++, cc--; + n = (long) *bp++; + cc--; /* * Watch out for compilers that * don't sign extend chars... @@ -240,8 +244,15 @@ PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) (unsigned long) ((tmsize_t)n - occ)); n = (long)occ; } + if( cc == 0 ) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Terminating PackBitsDecode due to lack of data."); + break; + } occ -= n; - b = *bp++, cc--; + b = *bp++; + cc--; while (n-- > 0) *op++ = (uint8) b; } else { /* copy next n+1 bytes literally */ diff --git a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c index 29535d31ee1d8fb7dc6bf91086a84299148e912e..f2263950e1773b97051c6cde25223e087dd1d171 100644 --- a/third_party/libtiff/tif_pixarlog.c +++ b/third_party/libtiff/tif_pixarlog.c @@ -1,4 +1,4 @@ -/* $Id: tif_pixarlog.c,v 1.39 2012-12-10 17:27:13 tgl Exp $ */ +/* $Id: tif_pixarlog.c,v 1.53 2017-05-17 09:53:06 erouault Exp $ */ /* * Copyright (c) 1996-1997 Sam Leffler @@ -45,15 +45,15 @@ * input is assumed to be unsigned linear color values that represent * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to * be the normal linear color range, in addition over 1 values are - * accepted up to a value of about 25.0 to encode "hot" hightlights and such. + * accepted up to a value of about 25.0 to encode "hot" highlights and such. * The encoding is lossless for 8-bit values, slightly lossy for the * other bit depths. The actual color precision should be better * than the human eye can perceive with extra room to allow for * error introduced by further image computation. As with any quantized * color format, it is possible to perform image calculations which * expose the quantization error. This format should certainly be less - * susceptable to such errors than standard 8-bit encodings, but more - * susceptable than straight 16-bit or 32-bit encodings. + * susceptible to such errors than standard 8-bit encodings, but more + * susceptible than straight 16-bit or 32-bit encodings. * * On reading the internal format is converted to the desired output format. * The program can request which format it desires by setting the internal @@ -90,7 +90,7 @@ */ #include "tif_predict.h" -#include "../zlib_v128/zlib.h" +#include "zlib.h" #include <stdio.h> #include <stdlib.h> @@ -296,33 +296,35 @@ horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op, static void horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op) { - register unsigned int cr, cg, cb, ca, mask; + register unsigned int cr, cg, cb, ca, mask; if (n >= stride) { mask = CODE_MASK; if (stride == 3) { - op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2]; + op[0] = wp[0]; op[1] = wp[1]; op[2] = wp[2]; + cr = wp[0]; cg = wp[1]; cb = wp[2]; n -= 3; while (n > 0) { wp += 3; op += 3; n -= 3; - op[0] = (cr += wp[0]) & mask; - op[1] = (cg += wp[1]) & mask; - op[2] = (cb += wp[2]) & mask; + op[0] = (uint16)((cr += wp[0]) & mask); + op[1] = (uint16)((cg += wp[1]) & mask); + op[2] = (uint16)((cb += wp[2]) & mask); } } else if (stride == 4) { - op[0] = cr = wp[0]; op[1] = cg = wp[1]; - op[2] = cb = wp[2]; op[3] = ca = wp[3]; + op[0] = wp[0]; op[1] = wp[1]; + op[2] = wp[2]; op[3] = wp[3]; + cr = wp[0]; cg = wp[1]; cb = wp[2]; ca = wp[3]; n -= 4; while (n > 0) { wp += 4; op += 4; n -= 4; - op[0] = (cr += wp[0]) & mask; - op[1] = (cg += wp[1]) & mask; - op[2] = (cb += wp[2]) & mask; - op[3] = (ca += wp[3]) & mask; + op[0] = (uint16)((cr += wp[0]) & mask); + op[1] = (uint16)((cg += wp[1]) & mask); + op[2] = (uint16)((cb += wp[2]) & mask); + op[3] = (uint16)((ca += wp[3]) & mask); } } else { REPEAT(stride, *op = *wp&mask; wp++; op++) @@ -557,7 +559,7 @@ PixarLogMakeTables(PixarLogState *sp) for (i = 0; i < lt2size; i++) { if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1]) j++; - FromLT2[i] = j; + FromLT2[i] = (uint16)j; } /* @@ -569,14 +571,14 @@ PixarLogMakeTables(PixarLogState *sp) for (i = 0; i < 16384; i++) { while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1]) j++; - From14[i] = j; + From14[i] = (uint16)j; } j = 0; for (i = 0; i < 256; i++) { while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1]) j++; - From8[i] = j; + From8[i] = (uint16)j; } Fltsize = (float)(lt2size/2); @@ -634,29 +636,27 @@ PixarLogGuessDataFmt(TIFFDirectory *td) return guess; } +#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) +#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) + static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2) { - tmsize_t bytes = m1 * m2; - - if (m1 && bytes / m1 != m2) - bytes = 0; - - return bytes; + if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) + return 0; + return m1 * m2; } static tmsize_t add_ms(tmsize_t m1, tmsize_t m2) { - tmsize_t bytes = m1 + m2; - /* if either input is zero, assume overflow already occurred */ if (m1 == 0 || m2 == 0) - bytes = 0; - else if (bytes <= m1 || bytes <= m2) - bytes = 0; + return 0; + else if (m1 > TIFF_TMSIZE_T_MAX - m2) + return 0; - return bytes; + return m1 + m2; } static int @@ -676,6 +676,12 @@ PixarLogSetupDecode(TIFF* tif) assert(sp != NULL); + /* This function can possibly be called several times by */ + /* PredictorSetupDecode() if this function succeeds but */ + /* PredictorSetup() fails */ + if( (sp->state & PLSTATE_INIT) != 0 ) + return 1; + /* Make sure no byte swapping happens on the data * after decompression. */ tif->tif_postdecode = _TIFFNoPostDecode; @@ -697,6 +703,9 @@ PixarLogSetupDecode(TIFF* tif) if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) sp->user_datafmt = PixarLogGuessDataFmt(td); if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + _TIFFfree(sp->tbuf); + sp->tbuf = NULL; + sp->tbuf_size = 0; TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle bits depth/data format combination (depth: %d)", td->td_bitspersample); @@ -704,7 +713,10 @@ PixarLogSetupDecode(TIFF* tif) } if (inflateInit(&sp->stream) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); + _TIFFfree(sp->tbuf); + sp->tbuf = NULL; + sp->tbuf_size = 0; + TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)"); return (0); } else { sp->state |= PLSTATE_INIT; @@ -727,7 +739,7 @@ PixarLogPreDecode(TIFF* tif, uint16 s) assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ + appropriately even before we simplify it */ sp->stream.avail_in = (uInt) tif->tif_rawcc; if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) { @@ -772,11 +784,15 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) (void) s; assert(sp != NULL); + + sp->stream.next_in = tif->tif_rawcp; + sp->stream.avail_in = (uInt) tif->tif_rawcc; + sp->stream.next_out = (unsigned char *) sp->tbuf; assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ + appropriately even before we simplify it */ sp->stream.avail_out = (uInt) (nsamples * sizeof(uint16)); if (sp->stream.avail_out != nsamples * sizeof(uint16)) { @@ -797,14 +813,14 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) if (state == Z_DATA_ERROR) { TIFFErrorExt(tif->tif_clientdata, module, "Decoding error at scanline %lu, %s", - (unsigned long) tif->tif_row, sp->stream.msg); + (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); if (inflateSync(&sp->stream) != Z_OK) return (0); continue; } if (state != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); + sp->stream.msg ? sp->stream.msg : "(null)"); return (0); } } while (sp->stream.avail_out > 0); @@ -817,6 +833,9 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) return (0); } + tif->tif_rawcp = sp->stream.next_in; + tif->tif_rawcc = sp->stream.avail_in; + up = sp->tbuf; /* Swap bytes in the data if from a different endian machine. */ if (tif->tif_flags & TIFF_SWAB) @@ -906,7 +925,7 @@ PixarLogSetupEncode(TIFF* tif) } if (deflateInit(&sp->stream, sp->quality) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); + TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)"); return (0); } else { sp->state |= PLSTATE_INIT; @@ -929,8 +948,8 @@ PixarLogPreEncode(TIFF* tif, uint16 s) assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_out = tif->tif_rawdatasize; + appropriately even before we simplify it */ + sp->stream.avail_out = (uInt)tif->tif_rawdatasize; if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); @@ -961,9 +980,9 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) n -= 3; wp += 3; ip += 3; - r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + r1 = (int32) CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = (int32) CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = (int32) CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; } } else if (stride == 4) { r2 = wp[0] = (uint16) CLAMP(ip[0]); @@ -975,23 +994,20 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) n -= 4; wp += 4; ip += 4; - r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; - a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; + r1 = (int32) CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = (int32) CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = (int32) CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; + a1 = (int32) CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1; } } else { - ip += n - 1; /* point to last one */ - wp += n - 1; /* point to last one */ - n -= stride; - while (n > 0) { - REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--) + REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp++; ip++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[0] = (uint16)(((int32)CLAMP(ip[0])-(int32)CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; + } } } } @@ -1016,9 +1032,9 @@ horizontalDifference16(unsigned short *ip, int n, int stride, n -= 3; wp += 3; ip += 3; - r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + r1 = CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; } } else if (stride == 4) { r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); @@ -1028,23 +1044,20 @@ horizontalDifference16(unsigned short *ip, int n, int stride, n -= 4; wp += 4; ip += 4; - r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; - a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; + r1 = CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; + a1 = CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1; } } else { - ip += n - 1; /* point to last one */ - wp += n - 1; /* point to last one */ + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++) n -= stride; while (n > 0) { - REPEAT(stride, wp[0] = CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + REPEAT(stride, + wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; + } } } } @@ -1067,9 +1080,9 @@ horizontalDifference8(unsigned char *ip, int n, int stride, n -= 3; while (n > 0) { n -= 3; - r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1; + r1 = CLAMP(ip[3]); wp[3] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[4]); wp[4] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[5]); wp[5] = (uint16)((b1-b2) & mask); b2 = b1; wp += 3; ip += 3; } @@ -1079,26 +1092,23 @@ horizontalDifference8(unsigned char *ip, int n, int stride, n -= 4; while (n > 0) { n -= 4; - r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1; - a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1; + r1 = CLAMP(ip[4]); wp[4] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[5]); wp[5] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[6]); wp[6] = (uint16)((b1-b2) & mask); b2 = b1; + a1 = CLAMP(ip[7]); wp[7] = (uint16)((a1-a2) & mask); a2 = a1; wp += 4; ip += 4; } } else { - wp += n + stride - 1; /* point to last one */ - ip += n + stride - 1; /* point to last one */ - n -= stride; - while (n > 0) { - REPEAT(stride, wp[0] = CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) - } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; + } + } } } @@ -1139,6 +1149,13 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) } llen = sp->stride * td->td_imagewidth; + /* Check against the number of elements (of size uint16) of sp->tbuf */ + if( n > (tmsize_t)(td->td_rowsperstrip * llen) ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Too many input bytes provided"); + return 0; + } for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) { switch (sp->user_datafmt) { @@ -1169,7 +1186,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ + appropriately even before we simplify it */ sp->stream.avail_in = (uInt) (n * sizeof(uint16)); if ((sp->stream.avail_in / sizeof(uint16)) != (uInt) n) { @@ -1181,7 +1198,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) do { if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s", - sp->stream.msg); + sp->stream.msg ? sp->stream.msg : "(null)"); return (0); } if (sp->stream.avail_out == 0) { @@ -1223,7 +1240,7 @@ PixarLogPostEncode(TIFF* tif) break; default: TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); + sp->stream.msg ? sp->stream.msg : "(null)"); return (0); } } while (state != Z_STREAM_END); @@ -1233,9 +1250,11 @@ PixarLogPostEncode(TIFF* tif) static void PixarLogClose(TIFF* tif) { + PixarLogState* sp = (PixarLogState*) tif->tif_data; TIFFDirectory *td = &tif->tif_dir; - /* In a really sneaky (and really incorrect, and untruthfull, and + assert(sp != 0); + /* In a really sneaky (and really incorrect, and untruthful, and * troublesome, and error-prone) maneuver that completely goes against * the spirit of TIFF, and breaks TIFF, on close, we covertly * modify both bitspersample and sampleformat in the directory to @@ -1243,8 +1262,19 @@ PixarLogClose(TIFF* tif) * readers that don't know about PixarLog, or how to set * the PIXARLOGDATFMT pseudo-tag. */ - td->td_bitspersample = 8; - td->td_sampleformat = SAMPLEFORMAT_UINT; + + if (sp->state&PLSTATE_INIT) { + /* We test the state to avoid an issue such as in + * http://bugzilla.maptools.org/show_bug.cgi?id=2604 + * What appends in that case is that the bitspersample is 1 and + * a TransferFunction is set. The size of the TransferFunction + * depends on 1<<bitspersample. So if we increase it, an access + * out of the buffer will happen at directory flushing. + * Another option would be to clear those targs. + */ + td->td_bitspersample = 8; + td->td_sampleformat = SAMPLEFORMAT_UINT; + } } static void @@ -1293,7 +1323,7 @@ PixarLogVSetField(TIFF* tif, uint32 tag, va_list ap) if (deflateParams(&sp->stream, sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); + sp->stream.msg ? sp->stream.msg : "(null)"); return (0); } } diff --git a/third_party/libtiff/tif_predict.c b/third_party/libtiff/tif_predict.c index 8975672aec9cdf1b3fdc4e325ddc1f2288232b86..7a60a39edfdfd983115c81f1aeb8596624ba95e4 100644 --- a/third_party/libtiff/tif_predict.c +++ b/third_party/libtiff/tif_predict.c @@ -1,4 +1,4 @@ -/* $Id: tif_predict.c,v 1.35 2015-08-31 15:05:57 erouault Exp $ */ +/* $Id: tif_predict.c,v 1.43 2017-05-10 15:21:16 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -34,18 +34,18 @@ #define PredictorState(tif) ((TIFFPredictorState*) (tif)->tif_data) -static void horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc); -static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc); +static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc); static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s); static int PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s); static int PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s); @@ -80,6 +80,15 @@ PredictorSetup(TIFF* tif) td->td_sampleformat); return 0; } + if (td->td_bitspersample != 16 + && td->td_bitspersample != 24 + && td->td_bitspersample != 32 + && td->td_bitspersample != 64) { /* Should 64 be allowed? */ + TIFFErrorExt(tif->tif_clientdata, module, + "Floating point \"Predictor\" not supported with %d-bit samples", + td->td_bitspersample); + return 0; + } break; default: TIFFErrorExt(tif->tif_clientdata, module, @@ -108,11 +117,11 @@ PredictorSetupDecode(TIFF* tif) TIFFPredictorState* sp = PredictorState(tif); TIFFDirectory* td = &tif->tif_dir; + /* Note: when PredictorSetup() fails, the effets of setupdecode() */ + /* will not be "cancelled" so setupdecode() might be robust to */ + /* be called several times. */ if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) - { - (*tif->tif_cleanup)(tif); return 0; - } if (sp->predictor == 2) { switch (td->td_bitspersample) { @@ -177,7 +186,7 @@ PredictorSetupDecode(TIFF* tif) } /* * Allocate buffer to keep the decoded bytes before - * rearranging in the ight order + * rearranging in the right order */ } @@ -216,7 +225,7 @@ PredictorSetupEncode(TIFF* tif) /* * If the data is horizontally differenced 16-bit data that * requires byte-swapping, then it must be byte swapped after - * the differenciation step. We do this with a special-purpose + * the differentiation step. We do this with a special-purpose * routine and override the normal post decoding logic that * the library setup when the directory was read. */ @@ -253,11 +262,12 @@ PredictorSetupEncode(TIFF* tif) #define REPEAT4(n, op) \ switch (n) { \ - default: { tmsize_t i; for (i = n-4; i > 0; i--) { op; } } \ - case 4: op; \ - case 3: op; \ - case 2: op; \ - case 1: op; \ + default: { \ + tmsize_t i; for (i = n-4; i > 0; i--) { op; } } /*-fallthrough*/ \ + case 4: op; /*-fallthrough*/ \ + case 3: op; /*-fallthrough*/ \ + case 2: op; /*-fallthrough*/ \ + case 1: op; /*-fallthrough*/ \ case 0: ; \ } @@ -267,13 +277,19 @@ PredictorSetupEncode(TIFF* tif) /* - when storing into the byte stream, we explicitly mask with 0xff so */ /* as to make icc -check=conversions happy (not necessary by the standard) */ -static void +static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc) { tmsize_t stride = PredictorState(tif)->stride; unsigned char* cp = (unsigned char*) cp0; - assert((cc%stride)==0); + if((cc%stride)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horAcc8", + "%s", "(cc%stride)!=0"); + return 0; + } + if (cc > stride) { /* * Pipeline the most common cases. @@ -315,26 +331,32 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc) } while (cc>0); } } + return 1; } -static void +static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc) { uint16* wp = (uint16*) cp0; tmsize_t wc = cc / 2; TIFFSwabArrayOfShort(wp, wc); - horAcc16(tif, cp0, cc); + return horAcc16(tif, cp0, cc); } -static void +static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc) { tmsize_t stride = PredictorState(tif)->stride; uint16* wp = (uint16*) cp0; tmsize_t wc = cc / 2; - assert((cc%(2*stride))==0); + if((cc%(2*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horAcc16", + "%s", "cc%(2*stride))!=0"); + return 0; + } if (wc > stride) { wc -= stride; @@ -343,26 +365,32 @@ horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc) wc -= stride; } while (wc > 0); } + return 1; } -static void +static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc) { uint32* wp = (uint32*) cp0; tmsize_t wc = cc / 4; TIFFSwabArrayOfLong(wp, wc); - horAcc32(tif, cp0, cc); + return horAcc32(tif, cp0, cc); } -static void +static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc) { tmsize_t stride = PredictorState(tif)->stride; uint32* wp = (uint32*) cp0; tmsize_t wc = cc / 4; - assert((cc%(4*stride))==0); + if((cc%(4*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horAcc32", + "%s", "cc%(4*stride))!=0"); + return 0; + } if (wc > stride) { wc -= stride; @@ -371,12 +399,13 @@ horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc) wc -= stride; } while (wc > 0); } + return 1; } /* * Floating point predictor accumulation routine. */ -static void +static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc) { tmsize_t stride = PredictorState(tif)->stride; @@ -384,12 +413,18 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc) tmsize_t wc = cc / bps; tmsize_t count = cc; uint8 *cp = (uint8 *) cp0; - uint8 *tmp = (uint8 *)_TIFFmalloc(cc); + uint8 *tmp; - assert((cc%(bps*stride))==0); + if(cc%(bps*stride)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "fpAcc", + "%s", "cc%(bps*stride))!=0"); + return 0; + } + tmp = (uint8 *)_TIFFmalloc(cc); if (!tmp) - return; + return 0; while (count > stride) { REPEAT4(stride, cp[stride] = @@ -411,6 +446,7 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc) } } _TIFFfree(tmp); + return 1; } /* @@ -426,8 +462,7 @@ PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) assert(sp->decodepfunc != NULL); if ((*sp->decoderow)(tif, op0, occ0, s)) { - (*sp->decodepfunc)(tif, op0, occ0); - return 1; + return (*sp->decodepfunc)(tif, op0, occ0); } else return 0; } @@ -450,10 +485,16 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) if ((*sp->decodetile)(tif, op0, occ0, s)) { tmsize_t rowsize = sp->rowsize; assert(rowsize > 0); - assert((occ0%rowsize)==0); + if((occ0%rowsize) !=0) + { + TIFFErrorExt(tif->tif_clientdata, "PredictorDecodeTile", + "%s", "occ0%rowsize != 0"); + return 0; + } assert(sp->decodepfunc != NULL); while (occ0 > 0) { - (*sp->decodepfunc)(tif, op0, rowsize); + if( !(*sp->decodepfunc)(tif, op0, rowsize) ) + return 0; occ0 -= rowsize; op0 += rowsize; } @@ -462,14 +503,19 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) return 0; } -static void +static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc) { TIFFPredictorState* sp = PredictorState(tif); tmsize_t stride = sp->stride; unsigned char* cp = (unsigned char*) cp0; - assert((cc%stride)==0); + if((cc%stride)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horDiff8", + "%s", "(cc%stride)!=0"); + return 0; + } if (cc > stride) { cc -= stride; @@ -507,9 +553,10 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc) } while ((cc -= stride) > 0); } } + return 1; } -static void +static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) { TIFFPredictorState* sp = PredictorState(tif); @@ -517,7 +564,12 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) uint16 *wp = (uint16*) cp0; tmsize_t wc = cc/2; - assert((cc%(2*stride))==0); + if((cc%(2*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horDiff8", + "%s", "(cc%(2*stride))!=0"); + return 0; + } if (wc > stride) { wc -= stride; @@ -527,20 +579,23 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) wc -= stride; } while (wc > 0); } + return 1; } -static void +static int swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) { uint16* wp = (uint16*) cp0; tmsize_t wc = cc / 2; - horDiff16(tif, cp0, cc); + if( !horDiff16(tif, cp0, cc) ) + return 0; TIFFSwabArrayOfShort(wp, wc); + return 1; } -static void +static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) { TIFFPredictorState* sp = PredictorState(tif); @@ -548,7 +603,12 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) uint32 *wp = (uint32*) cp0; tmsize_t wc = cc/4; - assert((cc%(4*stride))==0); + if((cc%(4*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horDiff32", + "%s", "(cc%(4*stride))!=0"); + return 0; + } if (wc > stride) { wc -= stride; @@ -558,23 +618,26 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) wc -= stride; } while (wc > 0); } + return 1; } -static void +static int swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) { uint32* wp = (uint32*) cp0; tmsize_t wc = cc / 4; - horDiff32(tif, cp0, cc); + if( !horDiff32(tif, cp0, cc) ) + return 0; TIFFSwabArrayOfLong(wp, wc); + return 1; } /* * Floating point predictor differencing routine. */ -static void +static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc) { tmsize_t stride = PredictorState(tif)->stride; @@ -582,12 +645,18 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc) tmsize_t wc = cc / bps; tmsize_t count; uint8 *cp = (uint8 *) cp0; - uint8 *tmp = (uint8 *)_TIFFmalloc(cc); + uint8 *tmp; - assert((cc%(bps*stride))==0); + if((cc%(bps*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "fpDiff", + "%s", "(cc%(bps*stride))!=0"); + return 0; + } + tmp = (uint8 *)_TIFFmalloc(cc); if (!tmp) - return; + return 0; _TIFFmemcpy(tmp, cp0, cc); for (count = 0; count < wc; count++) { @@ -607,6 +676,7 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc) cp += cc - stride - 1; for (count = cc; count > stride; count -= stride) REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--) + return 1; } static int @@ -619,7 +689,8 @@ PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) assert(sp->encoderow != NULL); /* XXX horizontal differencing alters user's data XXX */ - (*sp->encodepfunc)(tif, bp, cc); + if( !(*sp->encodepfunc)(tif, bp, cc) ) + return 0; return (*sp->encoderow)(tif, bp, cc, s); } @@ -654,7 +725,13 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s) rowsize = sp->rowsize; assert(rowsize > 0); - assert((cc0%rowsize)==0); + if((cc0%rowsize)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "PredictorEncodeTile", + "%s", "(cc0%rowsize)!=0"); + _TIFFfree( working_copy ); + return 0; + } while (cc > 0) { (*sp->encodepfunc)(tif, bp, rowsize); cc -= rowsize; @@ -703,7 +780,7 @@ PredictorVGetField(TIFF* tif, uint32 tag, va_list ap) switch (tag) { case TIFFTAG_PREDICTOR: - *va_arg(ap, uint16*) = sp->predictor; + *va_arg(ap, uint16*) = (uint16)sp->predictor; break; default: return (*sp->vgetparent)(tif, tag, ap); @@ -724,7 +801,7 @@ PredictorPrintDir(TIFF* tif, FILE* fd, long flags) case 2: fprintf(fd, "horizontal differencing "); break; case 3: fprintf(fd, "floating point predictor "); break; } - fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor); + fprintf(fd, "%d (0x%x)\n", sp->predictor, sp->predictor); } if (sp->printdir) (*sp->printdir)(tif, fd, flags); diff --git a/third_party/libtiff/tif_predict.h b/third_party/libtiff/tif_predict.h index dc7144c69e6b3bac385d188bdcc7c0c6c3c2cafe..6c68e21acbb5c6e4f64b67073c6455be3816890d 100644 --- a/third_party/libtiff/tif_predict.h +++ b/third_party/libtiff/tif_predict.h @@ -1,4 +1,4 @@ -/* $Id: tif_predict.h,v 1.8 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Id: tif_predict.h,v 1.9 2016-10-31 17:24:26 erouault Exp $ */ /* * Copyright (c) 1995-1997 Sam Leffler @@ -30,6 +30,8 @@ * ``Library-private'' Support for the Predictor Tag */ +typedef int (*TIFFEncodeDecodeMethod)(TIFF* tif, uint8* buf, tmsize_t size); + /* * Codecs that want to support the Predictor tag must place * this structure first in their private state block so that @@ -43,12 +45,12 @@ typedef struct { TIFFCodeMethod encoderow; /* parent codec encode/decode row */ TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */ TIFFCodeMethod encodetile; /* parent codec encode/decode tile */ - TIFFPostMethod encodepfunc; /* horizontal differencer */ + TIFFEncodeDecodeMethod encodepfunc; /* horizontal differencer */ TIFFCodeMethod decoderow; /* parent codec encode/decode row */ TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */ TIFFCodeMethod decodetile; /* parent codec encode/decode tile */ - TIFFPostMethod decodepfunc; /* horizontal accumulator */ + TIFFEncodeDecodeMethod decodepfunc; /* horizontal accumulator */ TIFFVGetMethod vgetparent; /* super-class method */ TIFFVSetMethod vsetparent; /* super-class method */ diff --git a/third_party/libtiff/tif_print.c b/third_party/libtiff/tif_print.c index 7b1a4222a3bcb3252e3c79d67bf1820e921473b6..24d4b98a6822c608c5e1591783e2e64c4311a558 100644 --- a/third_party/libtiff/tif_print.c +++ b/third_party/libtiff/tif_print.c @@ -1,4 +1,4 @@ -/* $Id: tif_print.c,v 1.62 2015-08-19 02:31:04 bfriesen Exp $ */ +/* $Id: tif_print.c,v 1.65 2016-11-20 22:31:22 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -37,7 +37,7 @@ static void _TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars); -static const char *photoNames[] = { +static const char * const photoNames[] = { "min-is-white", /* PHOTOMETRIC_MINISWHITE */ "min-is-black", /* PHOTOMETRIC_MINISBLACK */ "RGB color", /* PHOTOMETRIC_RGB */ @@ -52,7 +52,7 @@ static const char *photoNames[] = { }; #define NPHOTONAMES (sizeof (photoNames) / sizeof (photoNames[0])) -static const char *orientNames[] = { +static const char * const orientNames[] = { "0 (0x0)", "row 0 top, col 0 lhs", /* ORIENTATION_TOPLEFT */ "row 0 top, col 0 rhs", /* ORIENTATION_TOPRIGHT */ @@ -237,7 +237,6 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) { TIFFDirectory *td = &tif->tif_dir; char *sep; - uint16 i; long l, n; #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) @@ -263,7 +262,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) if (td->td_subfiletype & FILETYPE_MASK) fprintf(fd, "%stransparency mask", sep); fprintf(fd, " (%lu = 0x%lx)\n", - (long) td->td_subfiletype, (long) td->td_subfiletype); + (unsigned long) td->td_subfiletype, (long) td->td_subfiletype); } if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { fprintf(fd, " Image Width: %lu Image Length: %lu", @@ -365,6 +364,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) } } if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { + uint16 i; fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); sep = ""; for (i = 0; i < td->td_extrasamples; i++) { @@ -389,6 +389,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) } if (TIFFFieldSet(tif,FIELD_INKNAMES)) { char* cp; + uint16 i; fprintf(fd, " Ink Names: "); i = td->td_samplesperpixel; sep = ""; @@ -481,6 +482,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) { + int i; int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1; fprintf(fd, " SMin Sample Value:"); for (i = 0; i < count; ++i) @@ -488,6 +490,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) { + int i; int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1; fprintf(fd, " SMax Sample Value:"); for (i = 0; i < count; ++i) @@ -518,7 +521,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) - fprintf(fd, " %5lu: %5u %5u %5u\n", + fprintf(fd, " %5ld: %5u %5u %5u\n", l, td->td_colormap[0][l], td->td_colormap[1][l], @@ -527,6 +530,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { + int i; fprintf(fd, " Reference Black/White:\n"); for (i = 0; i < 3; i++) fprintf(fd, " %2d: %5g %5g\n", i, @@ -539,7 +543,8 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) { - fprintf(fd, " %2lu: %5u", + uint16 i; + fprintf(fd, " %2ld: %5u", l, td->td_transferfunction[0][l]); for (i = 1; i < td->td_samplesperpixel; i++) fprintf(fd, " %5u", @@ -550,6 +555,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) { + uint16 i; fprintf(fd, " SubIFD Offsets:"); for (i = 0; i < td->td_nsubifd; i++) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) @@ -655,7 +661,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) uint32 s; fprintf(fd, " %lu %s:\n", - (long) td->td_nstrips, + (unsigned long) td->td_nstrips, isTiled(tif) ? "Tiles" : "Strips"); for (s = 0; s < td->td_nstrips; s++) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) diff --git a/third_party/libtiff/tif_read.c b/third_party/libtiff/tif_read.c index 548b1f5ea673631c8b718e2cfe4dc200d77dc4fb..ad0a778c0f591b0d995926474453dcba0711bf54 100644 --- a/third_party/libtiff/tif_read.c +++ b/third_party/libtiff/tif_read.c @@ -1,4 +1,4 @@ -/* $Id: tif_read.c,v 1.45 2015-06-07 22:35:40 bfriesen Exp $ */ +/* $Id: tif_read.c,v 1.59 2017-05-13 15:34:06 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -31,6 +31,9 @@ #include "tiffiop.h" #include <stdio.h> +#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) +#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) + int TIFFFillStrip(TIFF* tif, uint32 strip); int TIFFFillTile(TIFF* tif, uint32 tile); static int TIFFStartStrip(TIFF* tif, uint32 strip); @@ -38,10 +41,127 @@ static int TIFFStartTile(TIFF* tif, uint32 tile); static int TIFFCheckRead(TIFF*, int); static tmsize_t TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,const char* module); +static tmsize_t +TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module); #define NOSTRIP ((uint32)(-1)) /* undefined state */ #define NOTILE ((uint32)(-1)) /* undefined state */ +#define INITIAL_THRESHOLD (1024 * 1024) +#define THRESHOLD_MULTIPLIER 10 +#define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) + +/* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset' + * Returns 1 in case of success, 0 otherwise. */ +static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, + tmsize_t rawdata_offset, + int is_strip, uint32 strip_or_tile, + const char* module ) +{ +#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 + tmsize_t threshold = INITIAL_THRESHOLD; +#endif + tmsize_t already_read = 0; + + /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ + /* so as to avoid allocating too much memory in case the file is too */ + /* short. We could ask for the file size, but this might be */ + /* expensive with some I/O layers (think of reading a gzipped file) */ + /* Restrict to 64 bit processes, so as to avoid reallocs() */ + /* on 32 bit processes where virtual memory is scarce. */ + while( already_read < size ) + { + tmsize_t bytes_read; + tmsize_t to_read = size - already_read; +#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 + if( to_read >= threshold && threshold < MAX_THRESHOLD && + already_read + to_read + rawdata_offset > tif->tif_rawdatasize ) + { + to_read = threshold; + threshold *= THRESHOLD_MULTIPLIER; + } +#endif + if (already_read + to_read + rawdata_offset > tif->tif_rawdatasize) { + uint8* new_rawdata; + assert((tif->tif_flags & TIFF_MYBUFFER) != 0); + tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64( + (uint64)already_read + to_read + rawdata_offset, 1024); + if (tif->tif_rawdatasize==0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid buffer size"); + return 0; + } + new_rawdata = (uint8*) _TIFFrealloc( + tif->tif_rawdata, tif->tif_rawdatasize); + if( new_rawdata == 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for data buffer at scanline %lu", + (unsigned long) tif->tif_row); + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = 0; + tif->tif_rawdatasize = 0; + return 0; + } + tif->tif_rawdata = new_rawdata; + } + + bytes_read = TIFFReadFile(tif, + tif->tif_rawdata + rawdata_offset + already_read, to_read); + already_read += bytes_read; + if (bytes_read != to_read) { + memset( tif->tif_rawdata + rawdata_offset + already_read, 0, + tif->tif_rawdatasize - rawdata_offset - already_read ); +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + if( is_strip ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu; got %I64u bytes, " + "expected %I64u", + (unsigned long) tif->tif_row, + (unsigned __int64) already_read, + (unsigned __int64) size); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at row %lu, col %lu, tile %lu; " + "got %I64u bytes, expected %I64u", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) strip_or_tile, + (unsigned __int64) already_read, + (unsigned __int64) size); + } +#else + if( is_strip ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu; got %llu bytes, " + "expected %llu", + (unsigned long) tif->tif_row, + (unsigned long long) already_read, + (unsigned long long) size); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at row %lu, col %lu, tile %lu; " + "got %llu bytes, expected %llu", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) strip_or_tile, + (unsigned long long) already_read, + (unsigned long long) size); + } +#endif + return 0; + } + } + return 1; +} + + static int TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) { @@ -49,7 +169,8 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) register TIFFDirectory *td = &tif->tif_dir; tmsize_t unused_data; uint64 read_offset; - tmsize_t cc, to_read; + tmsize_t to_read; + tmsize_t read_ahead_mod; /* tmsize_t bytecountm; */ if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) @@ -62,7 +183,14 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) */ /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ - if (read_ahead*2 > tif->tif_rawdatasize) { + + /* Not completely sure where the * 2 comes from, but probably for */ + /* an exponentional growth strategy of tif_rawdatasize */ + if( read_ahead < TIFF_TMSIZE_T_MAX / 2 ) + read_ahead_mod = read_ahead * 2; + else + read_ahead_mod = read_ahead; + if (read_ahead_mod > tif->tif_rawdatasize) { assert( restart ); tif->tif_curstrip = NOSTRIP; @@ -72,8 +200,6 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) (unsigned long) strip); return (0); } - if (!TIFFReadBufferSetup(tif, 0, read_ahead*2)) - return (0); } if( restart ) @@ -113,7 +239,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) /* ** How much do we want to read? */ - to_read = tif->tif_rawdatasize - unused_data; + if( read_ahead_mod > tif->tif_rawdatasize ) + to_read = read_ahead_mod - unused_data; + else + to_read = tif->tif_rawdatasize - unused_data; if( (uint64) to_read > td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { @@ -122,25 +251,14 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) } assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); - cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read); - - if (cc != to_read) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu; got %I64u bytes, expected %I64u", - (unsigned long) tif->tif_row, - (unsigned __int64) cc, - (unsigned __int64) to_read); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu; got %llu bytes, expected %llu", - (unsigned long) tif->tif_row, - (unsigned long long) cc, - (unsigned long long) to_read); -#endif + if( !TIFFReadAndRealloc( tif, to_read, unused_data, + 1, /* is_strip */ + 0, /* strip_or_tile */ + module) ) + { return 0; } - + tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; @@ -159,7 +277,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) if( restart ) return TIFFStartStrip(tif, strip); else + { + tif->tif_rawcc = tif->tif_rawdataloaded; return 1; + } } /* @@ -214,7 +335,18 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) if( !whole_strip ) { - read_ahead = tif->tif_scanlinesize * 16 + 5000; + /* 16 is for YCbCr mode where we may need to read 16 */ + /* lines at a time to get a decompressed line, and 5000 */ + /* is some constant value, for example for JPEG tables */ + if( tif->tif_scanlinesize < TIFF_TMSIZE_T_MAX / 16 && + tif->tif_scanlinesize * 16 < TIFF_TMSIZE_T_MAX - 5000 ) + { + read_ahead = tif->tif_scanlinesize * 16 + 5000; + } + else + { + read_ahead = tif->tif_scanlinesize; + } } /* @@ -310,18 +442,17 @@ TIFFReadScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) } /* - * Read a strip of data and decompress the specified - * amount into the user-supplied buffer. + * Calculate the strip size according to the number of + * rows in the strip (check for truncated last strip on any + * of the separations). */ -tmsize_t -TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) +static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF* tif, uint32 strip, uint16* pplane) { static const char module[] = "TIFFReadEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; uint32 rowsperstrip; uint32 stripsperplane; uint32 stripinplane; - uint16 plane; uint32 rows; tmsize_t stripsize; if (!TIFFCheckRead(tif,0)) @@ -333,23 +464,55 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) (unsigned long)td->td_nstrips); return((tmsize_t)(-1)); } - /* - * Calculate the strip size according to the number of - * rows in the strip (check for truncated last strip on any - * of the separations). - */ + rowsperstrip=td->td_rowsperstrip; if (rowsperstrip>td->td_imagelength) rowsperstrip=td->td_imagelength; - stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip); + stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); stripinplane=(strip%stripsperplane); - plane=(strip/stripsperplane); + if( pplane ) *pplane=(uint16)(strip/stripsperplane); rows=td->td_imagelength-stripinplane*rowsperstrip; if (rows>rowsperstrip) rows=rowsperstrip; stripsize=TIFFVStripSize(tif,rows); if (stripsize==0) return((tmsize_t)(-1)); + return stripsize; +} + +/* + * Read a strip of data and decompress the specified + * amount into the user-supplied buffer. + */ +tmsize_t +TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) +{ + static const char module[] = "TIFFReadEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + tmsize_t stripsize; + uint16 plane; + + stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); + if (stripsize==((tmsize_t)(-1))) + return((tmsize_t)(-1)); + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE && + size!=(tmsize_t)(-1) && size >= stripsize && + !isMapped(tif) && + ((tif->tif_flags&TIFF_NOREADRAW)==0) ) + { + if (TIFFReadRawStrip1(tif, strip, buf, stripsize, module) != stripsize) + return ((tmsize_t)(-1)); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(buf,stripsize); + + (*tif->tif_postdecode)(tif,buf,stripsize); + return (stripsize); + } + if ((size!=(tmsize_t)(-1))&&(size<stripsize)) stripsize=size; if (!TIFFFillStrip(tif,strip)) @@ -360,6 +523,50 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) return(stripsize); } +/* Variant of TIFFReadEncodedStrip() that does + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillStrip() has + * suceeded. This avoid excessive memory allocation in case of truncated + * file. + * * calls regular TIFFReadEncodedStrip() if *buf != NULL + */ +tmsize_t +_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read) +{ + tmsize_t this_stripsize; + uint16 plane; + + if( *buf != NULL ) + { + return TIFFReadEncodedStrip(tif, strip, *buf, size_to_read); + } + + this_stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); + if (this_stripsize==((tmsize_t)(-1))) + return((tmsize_t)(-1)); + + if ((size_to_read!=(tmsize_t)(-1))&&(size_to_read<this_stripsize)) + this_stripsize=size_to_read; + if (!TIFFFillStrip(tif,strip)) + return((tmsize_t)(-1)); + + *buf = _TIFFmalloc(bufsizetoalloc); + if (*buf == NULL) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); + return((tmsize_t)(-1)); + } + _TIFFmemset(*buf, 0, bufsizetoalloc); + + if ((*tif->tif_decodestrip)(tif,*buf,this_stripsize,plane)<=0) + return((tmsize_t)(-1)); + (*tif->tif_postdecode)(tif,*buf,this_stripsize); + return(this_stripsize); + + +} + + static tmsize_t TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, const char* module) @@ -397,16 +604,25 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, return ((tmsize_t)(-1)); } } else { - tmsize_t ma,mb; + tmsize_t ma = 0; tmsize_t n; - ma=(tmsize_t)td->td_stripoffset[strip]; - mb=ma+size; - if (((uint64)ma!=td->td_stripoffset[strip])||(ma>tif->tif_size)) - n=0; - else if ((mb<ma)||(mb<size)||(mb>tif->tif_size)) - n=tif->tif_size-ma; - else - n=size; + if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)|| + ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size)) + { + n=0; + } + else if( ma > TIFF_TMSIZE_T_MAX - size ) + { + n=0; + } + else + { + tmsize_t mb=ma+size; + if (mb>tif->tif_size) + n=tif->tif_size-ma; + else + n=size; + } if (n!=size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, @@ -431,6 +647,43 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, return (size); } +static tmsize_t +TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip, + tmsize_t size, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + assert( !isMapped(tif) ); + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + + if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) { + if( is_strip ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at scanline %lu, strip %lu", + (unsigned long) tif->tif_row, + (unsigned long) strip_or_tile); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at row %lu, col %lu, tile %lu", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) strip_or_tile); + } + return ((tmsize_t)(-1)); + } + + if( !TIFFReadAndRealloc( tif, size, 0, is_strip, + strip_or_tile, module ) ) + { + return ((tmsize_t)(-1)); + } + + return (size); +} + /* * Read a strip of data from the file. */ @@ -492,9 +745,9 @@ TIFFFillStrip(TIFF* tif, uint32 strip) static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; + if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[strip]; @@ -512,6 +765,39 @@ TIFFFillStrip(TIFF* tif, uint32 strip) #endif return (0); } + + /* To avoid excessive memory allocations: */ + /* Byte count should normally not be larger than a number of */ + /* times the uncompressed size plus some margin */ + if( bytecount > 1024 * 1024 ) + { + /* 10 and 4096 are just values that could be adjusted. */ + /* Hopefully they are safe enough for all codecs */ + tmsize_t stripsize = TIFFStripSize(tif); + if( stripsize != 0 && + (bytecount - 4096) / 10 > (uint64)stripsize ) + { + uint64 newbytecount = (uint64)stripsize * 10 + 4096; + if( (int64)newbytecount >= 0 ) + { +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFWarningExt(tif->tif_clientdata, module, + "Too large strip byte count %I64u, strip %lu. Limiting to %I64u", + (unsigned __int64) bytecount, + (unsigned long) strip, + (unsigned __int64) newbytecount); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Too large strip byte count %llu, strip %lu. Limiting to %llu", + (unsigned long long) bytecount, + (unsigned long) strip, + (unsigned long long) newbytecount); +#endif + bytecount = newbytecount; + } + } + } + if (isMapped(tif) && (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { @@ -601,17 +887,36 @@ TIFFFillStrip(TIFF* tif, uint32 strip) (unsigned long) strip); return (0); } - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) - return (0); } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curstrip = NOSTRIP; - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + tif->tif_flags &= ~TIFF_BUFFERMMAP; + } + + if( isMapped(tif) ) + { + if (bytecountm > tif->tif_rawdatasize && + !TIFFReadBufferSetup(tif, 0, bytecountm)) + { return (0); + } + if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, + bytecountm, module) != bytecountm) + { + return (0); + } + } + else + { + if (TIFFReadRawStripOrTile2(tif, strip, 1, + bytecountm, module) != bytecountm) + { + return (0); + } } - if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, - bytecountm, module) != bytecountm) - return (0); + tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; @@ -661,6 +966,24 @@ TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tmsize_t)(-1)); } + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE && + size!=(tmsize_t)(-1) && size >= tilesize && + !isMapped(tif) && + ((tif->tif_flags&TIFF_NOREADRAW)==0) ) + { + if (TIFFReadRawTile1(tif, tile, buf, tilesize, module) != tilesize) + return ((tmsize_t)(-1)); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(buf,tilesize); + + (*tif->tif_postdecode)(tif,buf,tilesize); + return (tilesize); + } + if (size == (tmsize_t)(-1)) size = tilesize; else if (size > tilesize) @@ -673,6 +996,78 @@ TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) return ((tmsize_t)(-1)); } +/* Variant of TIFFReadTile() that does + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has + * suceeded. This avoid excessive memory allocation in case of truncated + * file. + * * calls regular TIFFReadEncodedTile() if *buf != NULL + */ +tmsize_t +_TIFFReadTileAndAllocBuffer(TIFF* tif, + void **buf, tmsize_t bufsizetoalloc, + uint32 x, uint32 y, uint32 z, uint16 s) +{ + if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) + return ((tmsize_t)(-1)); + return (_TIFFReadEncodedTileAndAllocBuffer(tif, + TIFFComputeTile(tif, x, y, z, s), + buf, bufsizetoalloc, + (tmsize_t)(-1))); +} + +/* Variant of TIFFReadEncodedTile() that does + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has + * suceeded. This avoid excessive memory allocation in case of truncated + * file. + * * calls regular TIFFReadEncodedTile() if *buf != NULL + */ +tmsize_t +_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read) +{ + static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; + TIFFDirectory *td = &tif->tif_dir; + tmsize_t tilesize = tif->tif_tilesize; + + if( *buf != NULL ) + { + return TIFFReadEncodedTile(tif, tile, *buf, size_to_read); + } + + if (!TIFFCheckRead(tif, 1)) + return ((tmsize_t)(-1)); + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Tile out of range, max %lu", + (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tmsize_t)(-1)); + } + + if (!TIFFFillTile(tif,tile)) + return((tmsize_t)(-1)); + + *buf = _TIFFmalloc(bufsizetoalloc); + if (*buf == NULL) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "No space for tile buffer"); + return((tmsize_t)(-1)); + } + _TIFFmemset(*buf, 0, bufsizetoalloc); + + if (size_to_read == (tmsize_t)(-1)) + size_to_read = tilesize; + else if (size_to_read > tilesize) + size_to_read = tilesize; + if( (*tif->tif_decodetile)(tif, + (uint8*) *buf, size_to_read, (uint16)(tile/td->td_stripsperimage))) { + (*tif->tif_postdecode)(tif, (uint8*) *buf, size_to_read); + return (size_to_read); + } else + return ((tmsize_t)(-1)); +} + + static tmsize_t TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) { @@ -717,7 +1112,7 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m tmsize_t n; ma=(tmsize_t)td->td_stripoffset[tile]; mb=ma+size; - if (((uint64)ma!=td->td_stripoffset[tile])||(ma>tif->tif_size)) + if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size)) n=0; else if ((mb<ma)||(mb<size)||(mb>tif->tif_size)) n=tif->tif_size-ma; @@ -795,9 +1190,9 @@ TIFFFillTile(TIFF* tif, uint32 tile) static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; + if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[tile]; @@ -876,18 +1271,36 @@ TIFFFillTile(TIFF* tif, uint32 tile) (unsigned long) tile); return (0); } - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) - return (0); } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curtile = NOTILE; - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + tif->tif_flags &= ~TIFF_BUFFERMMAP; + } + + if( isMapped(tif) ) + { + if (bytecountm > tif->tif_rawdatasize && + !TIFFReadBufferSetup(tif, 0, bytecountm)) + { + return (0); + } + if (TIFFReadRawTile1(tif, tile, tif->tif_rawdata, + bytecountm, module) != bytecountm) + { return (0); + } + } + else + { + if (TIFFReadRawStripOrTile2(tif, tile, 0, + bytecountm, module) != bytecountm) + { + return (0); + } } - if (TIFFReadRawTile1(tif, tile, tif->tif_rawdata, - bytecountm, module) != bytecountm) - return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; @@ -935,10 +1348,9 @@ TIFFReadBufferSetup(TIFF* tif, void* bp, tmsize_t size) "Invalid buffer size"); return (0); } - tif->tif_rawdata = (uint8*) _TIFFmalloc(tif->tif_rawdatasize); - if (tif->tif_rawdata) - memset(tif->tif_rawdata, 0, tif->tif_rawdatasize); - + /* Initialize to zero to avoid uninitialized buffers in case of */ + /* short reads (http://bugzilla.maptools.org/show_bug.cgi?id=2651) */ + tif->tif_rawdata = (uint8*) _TIFFcalloc(1, tif->tif_rawdatasize); tif->tif_flags |= TIFF_MYBUFFER; } if (tif->tif_rawdata == NULL) { @@ -960,8 +1372,8 @@ TIFFStartStrip(TIFF* tif, uint32 strip) { TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupdecode)(tif)) @@ -980,7 +1392,10 @@ TIFFStartStrip(TIFF* tif, uint32 strip) else { tif->tif_rawcp = tif->tif_rawdata; - tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; + if( tif->tif_rawdataloaded > 0 ) + tif->tif_rawcc = tif->tif_rawdataloaded; + else + tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; } return ((*tif->tif_predecode)(tif, (uint16)(strip / td->td_stripsperimage))); diff --git a/third_party/libtiff/tif_strip.c b/third_party/libtiff/tif_strip.c index 6cac71dd928a3ff3bfcc4d1f1843ca694dc19a3a..6e9f2ef6ddf269f69b22b80497e1d9ce1f6a3912 100644 --- a/third_party/libtiff/tif_strip.c +++ b/third_party/libtiff/tif_strip.c @@ -1,4 +1,4 @@ -/* $Id: tif_strip.c,v 1.36 2015-06-07 22:35:40 bfriesen Exp $ */ +/* $Id: tif_strip.c,v 1.38 2016-12-03 11:02:15 erouault Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler diff --git a/third_party/libtiff/tif_swab.c b/third_party/libtiff/tif_swab.c index f37e33f1c9925113b9a9cc1b87feba6d07bca064..211dc576eb26decbaeda5b431642744410de1924 100644 --- a/third_party/libtiff/tif_swab.c +++ b/third_party/libtiff/tif_swab.c @@ -1,4 +1,4 @@ -/* $Id: tif_swab.c,v 1.13 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Id: tif_swab.c,v 1.14 2016-09-04 21:32:56 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -296,8 +296,10 @@ TIFFReverseBits(uint8* cp, tmsize_t n) cp[7] = TIFFBitRevTable[cp[7]]; cp += 8; } - while (n-- > 0) - *cp = TIFFBitRevTable[*cp], cp++; + while (n-- > 0) { + *cp = TIFFBitRevTable[*cp]; + cp++; + } } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/third_party/libtiff/tif_thunder.c b/third_party/libtiff/tif_thunder.c index 390891c98bde1a07c593e6560f754826f656f11a..183199de76e46adbf9a57e1aa83b521deaa693b4 100644 --- a/third_party/libtiff/tif_thunder.c +++ b/third_party/libtiff/tif_thunder.c @@ -1,4 +1,4 @@ -/* $Id: tif_thunder.c,v 1.12 2011-04-02 20:54:09 bfriesen Exp $ */ +/* $Id: tif_thunder.c,v 1.13 2016-09-04 21:32:56 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -100,7 +100,8 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels) while (cc > 0 && npixels < maxpixels) { int n, delta; - n = *bp++, cc--; + n = *bp++; + cc--; switch (n & THUNDER_CODE) { case THUNDER_RUN: /* pixel run */ /* diff --git a/third_party/libtiff/tif_write.c b/third_party/libtiff/tif_write.c index 7996c31e08a07630c3be3497d6a783f584b1a2f5..4c216ec200ae2e356ec31fafc69ae6f049c60682 100644 --- a/third_party/libtiff/tif_write.c +++ b/third_party/libtiff/tif_write.c @@ -1,4 +1,4 @@ -/* $Id: tif_write.c,v 1.42 2015-06-07 23:00:23 bfriesen Exp $ */ +/* $Id: tif_write.c,v 1.46 2016-12-03 21:57:44 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -258,6 +258,23 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) tif->tif_rawcp = tif->tif_rawdata; tif->tif_flags &= ~TIFF_POSTENCODE; + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE ) + { + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (uint8*) data, cc ); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((uint8*) data, cc); + + if (cc > 0 && + !TIFFAppendToStrip(tif, strip, (uint8*) data, cc)) + return ((tmsize_t) -1); + return (cc); + } + sample = (uint16)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t) -1); @@ -266,7 +283,7 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) - return (0); + return ((tmsize_t) -1); if (!(*tif->tif_postencode)(tif)) return ((tmsize_t) -1); if (!isFillOrder(tif, td->td_fillorder) && @@ -431,9 +448,7 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_flags &= ~TIFF_POSTENCODE; - sample = (uint16)(tile/td->td_stripsperimage); - if (!(*tif->tif_preencode)(tif, sample)) - return ((tmsize_t)(-1)); + /* * Clamp write amount to the tile size. This is mostly * done so that callers can pass in some large number @@ -442,22 +457,41 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) if ( cc < 1 || cc > tif->tif_tilesize) cc = tif->tif_tilesize; + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE ) + { /* swab if needed - note that source buffer will be altered */ - tif->tif_postdecode( tif, (uint8*) data, cc ); - - if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) - return (0); - if (!(*tif->tif_postencode)(tif)) - return ((tmsize_t)(-1)); - if (!isFillOrder(tif, td->td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); - if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, - tif->tif_rawdata, tif->tif_rawcc)) - return ((tmsize_t)(-1)); - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; - return (cc); + tif->tif_postdecode( tif, (uint8*) data, cc ); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((uint8*) data, cc); + + if (cc > 0 && + !TIFFAppendToStrip(tif, tile, (uint8*) data, cc)) + return ((tmsize_t) -1); + return (cc); + } + + sample = (uint16)(tile/td->td_stripsperimage); + if (!(*tif->tif_preencode)(tif, sample)) + return ((tmsize_t)(-1)); + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (uint8*) data, cc ); + + if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) + return ((tmsize_t) -1); + if (!(*tif->tif_postencode)(tif)) + return ((tmsize_t)(-1)); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); + if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, + tif->tif_rawdata, tif->tif_rawcc)) + return ((tmsize_t)(-1)); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (cc); } /* @@ -764,7 +798,14 @@ TIFFFlushData1(TIFF* tif) if (!TIFFAppendToStrip(tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, tif->tif_rawdata, tif->tif_rawcc)) + { + /* We update those variables even in case of error since there's */ + /* code that doesn't really check the return code of this */ + /* function */ + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; return (0); + } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; } diff --git a/third_party/libtiff/tif_zip.c b/third_party/libtiff/tif_zip.c index b3ac9b956e1197fe3f6e0221b1dda53c1eff4784..42943fbb14f5d3c9ed850adfc018a51922a56581 100644 --- a/third_party/libtiff/tif_zip.c +++ b/third_party/libtiff/tif_zip.c @@ -1,4 +1,4 @@ -/* $Id: tif_zip.c,v 1.33 2014-12-25 18:29:11 erouault Exp $ */ +/* $Id: tif_zip.c,v 1.37 2017-05-10 15:21:16 erouault Exp $ */ /* * Copyright (c) 1995-1997 Sam Leffler @@ -47,7 +47,7 @@ * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz. */ #include "tif_predict.h" -#include "../zlib_v128/zlib.h" +#include "zlib.h" #include <stdio.h> @@ -107,7 +107,11 @@ ZIPSetupDecode(TIFF* tif) sp->state = 0; } - if (inflateInit(&sp->stream) != Z_OK) { + /* This function can possibly be called several times by */ + /* PredictorSetupDecode() if this function succeeds but */ + /* PredictorSetup() fails */ + if ((sp->state & ZSTATE_INIT_DECODE) == 0 && + inflateInit(&sp->stream) != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "%s", SAFE_MSG(sp)); return (0); } else { @@ -135,7 +139,7 @@ ZIPPreDecode(TIFF* tif, uint16 s) assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ + appropriately even before we simplify it */ sp->stream.avail_in = (uInt) tif->tif_rawcc; if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) { @@ -162,7 +166,7 @@ ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ + appropriately even before we simplify it */ sp->stream.avail_out = (uInt) occ; if ((tmsize_t)sp->stream.avail_out != occ) { @@ -239,8 +243,8 @@ ZIPPreEncode(TIFF* tif, uint16 s) assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_out = tif->tif_rawdatasize; + appropriately even before we simplify it */ + sp->stream.avail_out = (uInt)tif->tif_rawdatasize; if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); @@ -266,7 +270,7 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ + appropriately even before we simplify it */ sp->stream.avail_in = (uInt) cc; if ((tmsize_t)sp->stream.avail_in != cc) { @@ -460,7 +464,7 @@ bad: "No space for ZIP state block"); return (0); } -#endif /* ZIP_SUPORT */ +#endif /* ZIP_SUPPORT */ /* vim: set ts=8 sts=8 sw=8 noet: */ /* diff --git a/third_party/libtiff/tiff.h b/third_party/libtiff/tiff.h index bc46acd02b351ba75908bbd12da87929482d5322..fb39634c4b6a0a757678c2f7555948a0b78b6f67 100644 --- a/third_party/libtiff/tiff.h +++ b/third_party/libtiff/tiff.h @@ -1,4 +1,4 @@ -/* $Id: tiff.h,v 1.69 2014-04-02 17:23:06 fwarmerdam Exp $ */ +/* $Id: tiff.h,v 1.70 2016-01-23 21:20:34 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -279,7 +279,7 @@ typedef enum { #define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */ #define TIFFTAG_WHITEPOINT 318 /* image white point */ #define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ -#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ +#define TIFFTAG_COLORMAP 320 /* RGB map for palette image */ #define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ #define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */ #define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */ @@ -358,7 +358,7 @@ typedef enum { #define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ #define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ #define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ -#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ +#define TIFFTAG_JPEGQTABLES 519 /* !Q matrix offsets */ #define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ #define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ #define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ diff --git a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h index 26de163aba30c9e3c4e78a784c9cc07db903cbad..50e458faf40359ba2b8a6cf738c00b4a0143e475 100644 --- a/third_party/libtiff/tiffconf.h +++ b/third_party/libtiff/tiffconf.h @@ -12,18 +12,8 @@ //NOTE: The tiff codec requires an ANSI C compiler environment for building and // presumes an ANSI C environment for use. -/* Define to 1 if you have the <fcntl.h> header file. */ -/* Define to 1 if you have the <sys/types.h> header file. */ -#if _FX_OS_ == _FX_WIN32_MOBILE_ -# define O_RDONLY 0x0000 /* open for reading only */ -# define O_WRONLY 0x0001 /* open for writing only */ -# define O_RDWR 0x0002 /* open for reading and writing */ -# define O_CREAT 0x0100 /* create and open file */ -# define O_TRUNC 0x0200 /* open and truncate */ -#else # define HAVE_SYS_TYPES_H 1 # define HAVE_FCNTL_H 1 -#endif /* Compatibility stuff. */ @@ -39,26 +29,33 @@ //fx_system.h already include the string.h in ANSIC /* Define to 1 if you have the <search.h> header file. */ -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER >= 1900 +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ && _MSC_VER >= 1900 // search.h is always available in VS 2015 and above, and may be // available in earlier versions. #define HAVE_SEARCH_H 1 #endif -/* The size of a `int', as computed by sizeof. */ -/* According typedef int int32_t; in the fx_system.h*/ +/* The size of a `int'. */ +/* According typedef int int32_t; in the fx_system.h*/ #define SIZEOF_INT 4 /* Sunliang.Liu 20110325. We should config the correct long size for tif fax4decode optimize in tif_fax3.c -- Linux64 decode issue. TESTDOC: Bug #23661 - z1.tif. */ -#if _FX_CPU_ == _FX_WIN64_ || _FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ +#if _FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ /* The size of `unsigned long', as computed by sizeof. */ #define SIZEOF_UNSIGNED_LONG 8 #else #define SIZEOF_UNSIGNED_LONG 4 #endif +/* The size of void*. */ +#ifdef __LP64__ +#define SIZEOF_VOIDP 8 +#else +#define SIZEOF_VOIDP 4 +#endif + /* Signed 8-bit type */ #define TIFF_INT8_T signed char diff --git a/third_party/libtiff/tiffio.h b/third_party/libtiff/tiffio.h index 056aed22f7b454eddf507a01e05c21a54d59721c..f1d2fdc1640fc5ea9760a498566c5772390d2d20 100644 --- a/third_party/libtiff/tiffio.h +++ b/third_party/libtiff/tiffio.h @@ -1,4 +1,4 @@ -/* $Id: tiffio.h,v 1.91 2012-07-29 15:45:29 tgl Exp $ */ +/* $Id: tiffio.h,v 1.94 2017-01-11 19:02:49 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -208,7 +208,7 @@ struct _TIFFRGBAImage { uint16 orientation; /* image orientation */ uint16 req_orientation; /* requested orientation */ uint16 photometric; /* image photometric interp */ - uint16* redcmap; /* colormap pallete */ + uint16* redcmap; /* colormap palette */ uint16* greencmap; uint16* bluecmap; /* get image data routine */ @@ -225,7 +225,7 @@ struct _TIFFRGBAImage { TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ - uint8* UaToAa; /* Unassociated alpha to associated alpha convertion LUT */ + uint8* UaToAa; /* Unassociated alpha to associated alpha conversion LUT */ uint8* Bitdepth16To8; /* LUT for conversion from 16bit to 8bit values */ int row_offset; @@ -293,6 +293,7 @@ extern TIFFCodec* TIFFGetConfiguredCODECs(void); */ extern void* _TIFFmalloc(tmsize_t s); +extern void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz); extern void* _TIFFrealloc(void* p, tmsize_t s); extern void _TIFFmemset(void* p, int v, tmsize_t c); extern void _TIFFmemcpy(void* d, const void* s, tmsize_t c); @@ -431,6 +432,8 @@ extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int); extern int TIFFReadRGBAStrip(TIFF*, uint32, uint32 * ); extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); +extern int TIFFReadRGBAStripExt(TIFF*, uint32, uint32 *, int stop_on_error ); +extern int TIFFReadRGBATileExt(TIFF*, uint32, uint32, uint32 *, int stop_on_error ); extern int TIFFRGBAImageOK(TIFF*, char [1024]); extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); diff --git a/third_party/libtiff/tiffiop.h b/third_party/libtiff/tiffiop.h index f4b2ea480a69f9648c483697eead84cf54437c45..6fb47de5b2c3ed610a9609c1df97a0ffab7ec39d 100644 --- a/third_party/libtiff/tiffiop.h +++ b/third_party/libtiff/tiffiop.h @@ -1,4 +1,4 @@ -/* $Id: tiffiop.h,v 1.87 2015-08-23 17:49:01 bfriesen Exp $ */ +/* $Id: tiffiop.h,v 1.90 2016-12-02 21:56:56 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -85,7 +85,7 @@ typedef struct client_info { /* * Typedefs for ``method pointers'' used internally. - * these are depriciated and provided only for backwards compatibility + * these are deprecated and provided only for backwards compatibility. */ typedef unsigned char tidataval_t; /* internal image data value type */ typedef tidataval_t* tidata_t; /* reference to internal image data */ @@ -104,33 +104,33 @@ struct tiff { int tif_fd; /* open file descriptor */ int tif_mode; /* open mode (O_*) */ uint32 tif_flags; - #define TIFF_FILLORDER 0x00003 /* natural bit fill order for machine */ - #define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */ - #define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */ - #define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */ - #define TIFF_CODERSETUP 0x00020 /* encoder/decoder setup done */ - #define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */ - #define TIFF_SWAB 0x00080 /* byte swap file information */ - #define TIFF_NOBITREV 0x00100 /* inhibit bit reversal logic */ - #define TIFF_MYBUFFER 0x00200 /* my raw data buffer; free on close */ - #define TIFF_ISTILED 0x00400 /* file is tile, not strip- based */ - #define TIFF_MAPPED 0x00800 /* file is mapped into memory */ - #define TIFF_POSTENCODE 0x01000 /* need call to postencode routine */ - #define TIFF_INSUBIFD 0x02000 /* currently writing a subifd */ - #define TIFF_UPSAMPLED 0x04000 /* library is doing data up-sampling */ - #define TIFF_STRIPCHOP 0x08000 /* enable strip chopping support */ - #define TIFF_HEADERONLY 0x10000 /* read header only, do not process the first directory */ - #define TIFF_NOREADRAW 0x20000 /* skip reading of raw uncompressed image data */ - #define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */ - #define TIFF_BIGTIFF 0x80000 /* read/write bigtiff */ - #define TIFF_BUF4WRITE 0x100000 /* rawcc bytes are for writing */ - #define TIFF_DIRTYSTRIP 0x200000 /* stripoffsets/stripbytecount dirty*/ - #define TIFF_PERSAMPLE 0x400000 /* get/set per sample tags as arrays */ - #define TIFF_BUFFERMMAP 0x800000 /* read buffer (tif_rawdata) points into mmap() memory */ + #define TIFF_FILLORDER 0x00003U /* natural bit fill order for machine */ + #define TIFF_DIRTYHEADER 0x00004U /* header must be written on close */ + #define TIFF_DIRTYDIRECT 0x00008U /* current directory must be written */ + #define TIFF_BUFFERSETUP 0x00010U /* data buffers setup */ + #define TIFF_CODERSETUP 0x00020U /* encoder/decoder setup done */ + #define TIFF_BEENWRITING 0x00040U /* written 1+ scanlines to file */ + #define TIFF_SWAB 0x00080U /* byte swap file information */ + #define TIFF_NOBITREV 0x00100U /* inhibit bit reversal logic */ + #define TIFF_MYBUFFER 0x00200U /* my raw data buffer; free on close */ + #define TIFF_ISTILED 0x00400U /* file is tile, not strip- based */ + #define TIFF_MAPPED 0x00800U /* file is mapped into memory */ + #define TIFF_POSTENCODE 0x01000U /* need call to postencode routine */ + #define TIFF_INSUBIFD 0x02000U /* currently writing a subifd */ + #define TIFF_UPSAMPLED 0x04000U /* library is doing data up-sampling */ + #define TIFF_STRIPCHOP 0x08000U /* enable strip chopping support */ + #define TIFF_HEADERONLY 0x10000U /* read header only, do not process the first directory */ + #define TIFF_NOREADRAW 0x20000U /* skip reading of raw uncompressed image data */ + #define TIFF_INCUSTOMIFD 0x40000U /* currently writing a custom IFD */ + #define TIFF_BIGTIFF 0x80000U /* read/write bigtiff */ + #define TIFF_BUF4WRITE 0x100000U /* rawcc bytes are for writing */ + #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/ + #define TIFF_PERSAMPLE 0x400000U /* get/set per sample tags as arrays */ + #define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */ uint64 tif_diroff; /* file offset of current directory */ uint64 tif_nextdiroff; /* file offset of following directory */ uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */ - uint16 tif_dirlistsize; /* number of entires in offset list */ + uint16 tif_dirlistsize; /* number of entries in offset list */ uint16 tif_dirnumber; /* number of already seen directories */ TIFFDirectory tif_dir; /* internal rep of current directory */ TIFFDirectory tif_customdir; /* custom IFDs are separated from the main ones */ @@ -249,6 +249,10 @@ struct tiff { #define TIFFhowmany_32(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \ ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ 0U) +/* Variant of TIFFhowmany_32() that doesn't return 0 if x close to MAXUINT. */ +/* Caution: TIFFhowmany_32_maxuint_compat(x,y)*y might overflow */ +#define TIFFhowmany_32_maxuint_compat(x, y) \ + (((uint32)(x) / (uint32)(y)) + ((((uint32)(x) % (uint32)(y)) != 0) ? 1 : 0)) #define TIFFhowmany8_32(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) #define TIFFroundup_32(x, y) (TIFFhowmany_32(x,y)*(y)) #define TIFFhowmany_64(x, y) ((((uint64)(x))+(((uint64)(y))-1))/((uint64)(y))) @@ -360,6 +364,20 @@ extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); extern double _TIFFUInt64ToDouble(uint64); extern float _TIFFUInt64ToFloat(uint64); +extern tmsize_t +_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read); +extern tmsize_t +_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read); +extern tmsize_t +_TIFFReadTileAndAllocBuffer(TIFF* tif, + void **buf, tmsize_t bufsizetoalloc, + uint32 x, uint32 y, uint32 z, uint16 s); + + extern int TIFFInitDumpMode(TIFF*, int); #ifdef PACKBITS_SUPPORT extern int TIFFInitPackBits(TIFF*, int); diff --git a/third_party/libtiff/tiffvers.h b/third_party/libtiff/tiffvers.h index e965814b3d64ca3c057b65069eab1989570c8c08..890e433d8a03444c4c954da447f0baa3361f61dc 100644 --- a/third_party/libtiff/tiffvers.h +++ b/third_party/libtiff/tiffvers.h @@ -1,4 +1,4 @@ -#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.6\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.8\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." /* * This define can be used in code that requires * compilation-related definitions specific to a @@ -6,4 +6,4 @@ * version checking should be done based on the * string returned by TIFFGetVersion. */ -#define TIFFLIB_VERSION 20150912 +#define TIFFLIB_VERSION 20170521 diff --git a/third_party/libtiff/uvcode.h b/third_party/libtiff/uvcode.h index 50f11d7e0aeccdbcdaa16f701d19f48a13681da3..6286cfbb0c17c207c12c31890471535cfc6928b5 100644 --- a/third_party/libtiff/uvcode.h +++ b/third_party/libtiff/uvcode.h @@ -3,7 +3,7 @@ #define UV_NDIVS 16289 #define UV_VSTART (float)0.016940 #define UV_NVS 163 -static struct { +static const struct { float ustart; short nus, ncum; } uv_row[UV_NVS] = { diff --git a/third_party/pdfiumagg23.bp b/third_party/pdfiumagg23.bp deleted file mode 100644 index 960e594dda2c075f87f10a837fe53aa9eeb4fb00..0000000000000000000000000000000000000000 --- a/third_party/pdfiumagg23.bp +++ /dev/null @@ -1,19 +0,0 @@ -cc_library_static { - name: "libpdfiumagg23", - defaults: ["pdfium-defaults"], - - cflags: [ - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-unused-parameter", - "-Wno-unused-function", - ], - - srcs: [ - "agg23/agg_curves.cpp", - "agg23/agg_path_storage.cpp", - "agg23/agg_rasterizer_scanline_aa.cpp", - "agg23/agg_vcgen_dash.cpp", - "agg23/agg_vcgen_stroke.cpp", - ], -} diff --git a/third_party/pdfiumbigint.bp b/third_party/pdfiumbigint.bp index 536b1155eaccd042d664c2bef76ee389e14f33f3..fbd92a9a12296305012916cdcdfaab5d213e3b22 100644 --- a/third_party/pdfiumbigint.bp +++ b/third_party/pdfiumbigint.bp @@ -1,6 +1,6 @@ cc_library_static { name: "libpdfiumbigint", - defaults: ["pdfium-defaults"], + defaults: ["pdfium-third-party"], srcs: [ "bigint/BigInteger.cc", diff --git a/third_party/pdfiumfx_agg.bp b/third_party/pdfiumfx_agg.bp new file mode 100644 index 0000000000000000000000000000000000000000..f55fa6715ea08f948df9192bca476961577f2963 --- /dev/null +++ b/third_party/pdfiumfx_agg.bp @@ -0,0 +1,20 @@ +cc_library_static { + name: "libpdfiumfx_agg", + defaults: ["pdfium-third-party"], + + cflags: [ + "-Wno-unused-function" + ], + + static_libs: [ + "libpdfiumfxcrt", + ], + + srcs: [ + "agg23/agg_curves.cpp", + "agg23/agg_path_storage.cpp", + "agg23/agg_rasterizer_scanline_aa.cpp", + "agg23/agg_vcgen_dash.cpp", + "agg23/agg_vcgen_stroke.cpp", + ], +} diff --git a/third_party/pdfiumfx_libopenjpeg.bp b/third_party/pdfiumfx_libopenjpeg.bp new file mode 100644 index 0000000000000000000000000000000000000000..46b594ddbfcbc5fbb1a721d48abdee469df0532c --- /dev/null +++ b/third_party/pdfiumfx_libopenjpeg.bp @@ -0,0 +1,27 @@ +cc_library_static { + name: "libpdfiumfx_libopenjpeg", + defaults: ["pdfium-third-party"], + + srcs: [ + "libopenjpeg20/bio.c", + "libopenjpeg20/cio.c", + "libopenjpeg20/dwt.c", + "libopenjpeg20/event.c", + "libopenjpeg20/function_list.c", + "libopenjpeg20/image.c", + "libopenjpeg20/invert.c", + "libopenjpeg20/j2k.c", + "libopenjpeg20/jp2.c", + "libopenjpeg20/mct.c", + "libopenjpeg20/mqc.c", + "libopenjpeg20/openjpeg.c", + "libopenjpeg20/opj_clock.c", + "libopenjpeg20/pi.c", + "libopenjpeg20/sparse_array.c", + "libopenjpeg20/t1.c", + "libopenjpeg20/t2.c", + "libopenjpeg20/tcd.c", + "libopenjpeg20/tgt.c", + "libopenjpeg20/thread.c", + ], +} diff --git a/third_party/pdfiumjpeg.bp b/third_party/pdfiumjpeg.bp deleted file mode 100644 index 9113e7ab0073ecea757644ece568be2adc65b56f..0000000000000000000000000000000000000000 --- a/third_party/pdfiumjpeg.bp +++ /dev/null @@ -1,54 +0,0 @@ -cc_library_static { - name: "libpdfiumjpeg", - defaults: ["pdfium-defaults"], - - cflags: [ - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-shift-negative-value", - "-Wno-unused-parameter", - ], - - srcs: [ - "libjpeg/fpdfapi_jcapimin.c", - "libjpeg/fpdfapi_jcapistd.c", - "libjpeg/fpdfapi_jccoefct.c", - "libjpeg/fpdfapi_jccolor.c", - "libjpeg/fpdfapi_jcdctmgr.c", - "libjpeg/fpdfapi_jchuff.c", - "libjpeg/fpdfapi_jcinit.c", - "libjpeg/fpdfapi_jcmainct.c", - "libjpeg/fpdfapi_jcmarker.c", - "libjpeg/fpdfapi_jcmaster.c", - "libjpeg/fpdfapi_jcomapi.c", - "libjpeg/fpdfapi_jcparam.c", - "libjpeg/fpdfapi_jcphuff.c", - "libjpeg/fpdfapi_jcprepct.c", - "libjpeg/fpdfapi_jcsample.c", - "libjpeg/fpdfapi_jctrans.c", - "libjpeg/fpdfapi_jdapimin.c", - "libjpeg/fpdfapi_jdapistd.c", - "libjpeg/fpdfapi_jdcoefct.c", - "libjpeg/fpdfapi_jdcolor.c", - "libjpeg/fpdfapi_jddctmgr.c", - "libjpeg/fpdfapi_jdhuff.c", - "libjpeg/fpdfapi_jdinput.c", - "libjpeg/fpdfapi_jdmainct.c", - "libjpeg/fpdfapi_jdmarker.c", - "libjpeg/fpdfapi_jdmaster.c", - "libjpeg/fpdfapi_jdmerge.c", - "libjpeg/fpdfapi_jdphuff.c", - "libjpeg/fpdfapi_jdpostct.c", - "libjpeg/fpdfapi_jdsample.c", - "libjpeg/fpdfapi_jdtrans.c", - "libjpeg/fpdfapi_jerror.c", - "libjpeg/fpdfapi_jfdctfst.c", - "libjpeg/fpdfapi_jfdctint.c", - "libjpeg/fpdfapi_jidctfst.c", - "libjpeg/fpdfapi_jidctint.c", - "libjpeg/fpdfapi_jidctred.c", - "libjpeg/fpdfapi_jmemmgr.c", - "libjpeg/fpdfapi_jmemnobs.c", - "libjpeg/fpdfapi_jutils.c", - ], -} diff --git a/third_party/pdfiumlcms.bp b/third_party/pdfiumlcms.bp deleted file mode 100644 index 2eab7eb7d725bd73a15e4b31f1a2fe4e00056c4d..0000000000000000000000000000000000000000 --- a/third_party/pdfiumlcms.bp +++ /dev/null @@ -1,40 +0,0 @@ -cc_library_static { - name: "libpdfiumlcms", - defaults: ["pdfium-defaults"], - - cflags: [ - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-unused-parameter", - "-Wno-missing-braces", - "-Wno-unused-function", - ], - - srcs: [ - "lcms2-2.6/src/cmscam02.c", - "lcms2-2.6/src/cmscgats.c", - "lcms2-2.6/src/cmscnvrt.c", - "lcms2-2.6/src/cmserr.c", - "lcms2-2.6/src/cmsgamma.c", - "lcms2-2.6/src/cmsgmt.c", - "lcms2-2.6/src/cmshalf.c", - "lcms2-2.6/src/cmsintrp.c", - "lcms2-2.6/src/cmsio0.c", - "lcms2-2.6/src/cmsio1.c", - "lcms2-2.6/src/cmslut.c", - "lcms2-2.6/src/cmsmd5.c", - "lcms2-2.6/src/cmsmtrx.c", - "lcms2-2.6/src/cmsnamed.c", - "lcms2-2.6/src/cmsopt.c", - "lcms2-2.6/src/cmspack.c", - "lcms2-2.6/src/cmspcs.c", - "lcms2-2.6/src/cmsplugin.c", - "lcms2-2.6/src/cmsps2.c", - "lcms2-2.6/src/cmssamp.c", - "lcms2-2.6/src/cmssm.c", - "lcms2-2.6/src/cmstypes.c", - "lcms2-2.6/src/cmsvirt.c", - "lcms2-2.6/src/cmswtpnt.c", - "lcms2-2.6/src/cmsxform.c", - ], -} diff --git a/third_party/pdfiumlcms2.bp b/third_party/pdfiumlcms2.bp new file mode 100644 index 0000000000000000000000000000000000000000..d55287bfd3eb8dd3caea55cec1fc7829f85216de --- /dev/null +++ b/third_party/pdfiumlcms2.bp @@ -0,0 +1,37 @@ +cc_library_static { + name: "libpdfiumlcms2", + defaults: ["pdfium-third-party"], + + cflags: [ + "-Wno-missing-braces", + ], + + srcs: [ + "lcms/src/cmsalpha.c", + "lcms/src/cmscam02.c", + "lcms/src/cmscgats.c", + "lcms/src/cmscnvrt.c", + "lcms/src/cmserr.c", + "lcms/src/cmsgamma.c", + "lcms/src/cmsgmt.c", + "lcms/src/cmshalf.c", + "lcms/src/cmsintrp.c", + "lcms/src/cmsio0.c", + "lcms/src/cmsio1.c", + "lcms/src/cmslut.c", + "lcms/src/cmsmd5.c", + "lcms/src/cmsmtrx.c", + "lcms/src/cmsnamed.c", + "lcms/src/cmsopt.c", + "lcms/src/cmspack.c", + "lcms/src/cmspcs.c", + "lcms/src/cmsplugin.c", + "lcms/src/cmsps2.c", + "lcms/src/cmssamp.c", + "lcms/src/cmssm.c", + "lcms/src/cmstypes.c", + "lcms/src/cmsvirt.c", + "lcms/src/cmswtpnt.c", + "lcms/src/cmsxform.c", + ], +} diff --git a/third_party/pdfiumopenjpeg.bp b/third_party/pdfiumopenjpeg.bp deleted file mode 100644 index 076306fe22bca1df85daa013308fa8fb7bd39614..0000000000000000000000000000000000000000 --- a/third_party/pdfiumopenjpeg.bp +++ /dev/null @@ -1,33 +0,0 @@ -cc_library_static { - name: "libpdfiumopenjpeg", - defaults: ["pdfium-defaults"], - - cflags: [ - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-sign-compare", - "-Wno-unused-parameter", - ], - - srcs: [ - "libopenjpeg20/bio.c", - "libopenjpeg20/cio.c", - "libopenjpeg20/dwt.c", - "libopenjpeg20/event.c", - "libopenjpeg20/function_list.c", - "libopenjpeg20/image.c", - "libopenjpeg20/invert.c", - "libopenjpeg20/j2k.c", - "libopenjpeg20/jp2.c", - "libopenjpeg20/mct.c", - "libopenjpeg20/mqc.c", - "libopenjpeg20/openjpeg.c", - "libopenjpeg20/opj_clock.c", - "libopenjpeg20/pi.c", - "libopenjpeg20/raw.c", - "libopenjpeg20/t1.c", - "libopenjpeg20/t2.c", - "libopenjpeg20/tcd.c", - "libopenjpeg20/tgt.c", - ], -} diff --git a/third_party/pdfiumpdfiumbase.bp b/third_party/pdfiumpdfiumbase.bp new file mode 100644 index 0000000000000000000000000000000000000000..fc72eeb5b24190b4ccd79b1199f0fdd58a2656b9 --- /dev/null +++ b/third_party/pdfiumpdfiumbase.bp @@ -0,0 +1,11 @@ +cc_library_static { + name: "libpdfiumpdfiumbase", + defaults: ["pdfium-third-party"], + + srcs: [ + "base/allocator/partition_allocator/address_space_randomization.cc", + "base/allocator/partition_allocator/page_allocator.cc", + "base/allocator/partition_allocator/partition_alloc.cc", + "base/allocator/partition_allocator/spin_lock.cc", + ], +} diff --git a/third_party/pdfiumzlib.bp b/third_party/pdfiumzlib.bp deleted file mode 100644 index efd60c32fb03e95219943b828c1ad1a79fc5f2b2..0000000000000000000000000000000000000000 --- a/third_party/pdfiumzlib.bp +++ /dev/null @@ -1,29 +0,0 @@ -cc_library_static { - name: "libpdfiumzlib", - defaults: ["pdfium-defaults"], - - cflags: [ - // Mask some warnings. These are benign, but we probably want to fix them - // upstream at some point. - "-Wno-shift-negative-value", - "-Wno-unused-parameter", - ], - - srcs: [ - "zlib_v128/adler32.c", - "zlib_v128/compress.c", - "zlib_v128/crc32.c", - "zlib_v128/deflate.c", - "zlib_v128/gzclose.c", - "zlib_v128/gzlib.c", - "zlib_v128/gzread.c", - "zlib_v128/gzwrite.c", - "zlib_v128/infback.c", - "zlib_v128/inffast.c", - "zlib_v128/inflate.c", - "zlib_v128/inftrees.c", - "zlib_v128/trees.c", - "zlib_v128/uncompr.c", - "zlib_v128/zutil.c", - ], -} diff --git a/third_party/pymock/OWNERS b/third_party/pymock/OWNERS deleted file mode 100644 index 994656037670e33d7694d607bed375459e22a0a2..0000000000000000000000000000000000000000 --- a/third_party/pymock/OWNERS +++ /dev/null @@ -1 +0,0 @@ -sbc@chromium.org diff --git a/third_party/yasm/BUILD.gn b/third_party/yasm/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..94dbf9131ce77738fa6ab035a547f0de846ed30b --- /dev/null +++ b/third_party/yasm/BUILD.gn @@ -0,0 +1,569 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# The yasm build process creates a slew of small C subprograms that +# dynamically generate files at various point in the build process. This makes +# the build integration moderately complex. +# +# There are three classes of dynamically generated files: +# 1) C source files that should be included in the build (eg., lc3bid.c) +# 2) C source files that are #included by static C sources (eg., license.c) +# 3) Intermediate files that are used as input by other subprograms to +# further generate files in category #1 or #2. (eg., version.mac) +# +# This structure is represented with the following targets: +# 1) yasm -- Sources, flags for the main yasm executable. Also has most of +# of the actions and rules that invoke the subprograms. +# 2) yasm_config -- General build configuration including setting a +# inputs listing the checked in version of files +# generated by manually running configure. These manually +# generated files are used by all binaries. +# 3) yasm_utils -- Object files with memory management and hashing utilities +# shared between yasm and the genperf subprogram. +# 4) genmacro, genmodule, etc. -- One executable target for each subprogram. +# 5) generate_license, generate_module, etc. -- Actions that invoke programs +# built in #4 to generate .c files. +# 6) compile_gperf, compile_re2c, etc. -- Actions that invoke programs that +# turn intermediate files into .c files. + +import("//build/config/compiler/compiler.gni") + +configs_to_delete = [] +configs_to_add = [] +if (is_debug) { + configs_to_delete += [ + # Build with full optimizations even on debug configurations, because some + # yasm build steps (highbd_sad4d_sse2.asm) can take ~33 seconds or more in + # debug component builds on Windows. Enabling compiler optimizations saves + # ~5 seconds. + "//build/config/compiler:default_optimization", + + # Don't define _DEBUG. Modest savings, but good for consistency. + "//build/config:debug", + ] + configs_to_add += [ + "//build/config:release", + "//build/config/compiler:optimize_max", + ] + if (is_win) { + # This switches to using the release CRT. On debug component builds of + # highbd_sad4d_sse2.asm on Windows this saves about 15 s. + configs_to_delete += [ "//build/config/win:default_crt" ] + configs_to_add += [ "//build/config/win:release_crt" ] + } +} + +if (current_toolchain == host_toolchain) { + # Various files referenced by multiple targets. yasm_gen_include_dir was moved + # from $target_gen_dir/include to avoid conflicts with x86insn_gas.c and + # x86insn_nasm.c. These files were previously generated during the build but + # are now shipped pre-generated by yasm. + yasm_gen_include_dir = "$target_gen_dir/gen_include" + config_makefile = "source/config/Makefile" + version_file = "version.mac" + + import("//build/compiled_action.gni") + + config("yasm_config") { + include_dirs = [ + "source/config/$host_os", + "source/patched-yasm", + ] + defines = [ "HAVE_CONFIG_H" ] + if (is_posix) { + cflags = [ "-std=gnu99" ] + } + } + + executable("genmacro") { + sources = [ + "source/patched-yasm/tools/genmacro/genmacro.c", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + ] + deps = [ + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + executable("genmodule") { + sources = [ + "source/patched-yasm/libyasm/genmodule.c", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + ] + deps = [ + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + executable("genperf") { + sources = [ + "source/patched-yasm/tools/genperf/genperf.c", + "source/patched-yasm/tools/genperf/perfect.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + ] + + # Must be compatible with yasm_utils/yasm + configs -= configs_to_delete + configs += configs_to_add + + deps = [ + ":yasm_utils", + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + # Used by both yasm and genperf binaries. + static_library("yasm_utils") { + sources = [ + "source/patched-yasm/libyasm/phash.c", + "source/patched-yasm/libyasm/xmalloc.c", + "source/patched-yasm/libyasm/xstrdup.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + ] + + # Must be compatible with yasm + configs -= configs_to_delete + configs += configs_to_add + } + + executable("genstring") { + sources = [ + "source/patched-yasm/genstring.c", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + ] + deps = [ + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + executable("genversion") { + sources = [ + "source/patched-yasm/modules/preprocs/nasm/genversion.c", + ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + ] + deps = [ + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + config("re2c_warnings") { + # re2c is missing CLOSEVOP from one switch. + if (is_clang) { + cflags = [ + # re2c is missing CLOSEVOP from one switch. + "-Wno-switch", + + # re2c contains many static functions in headers (because it's + # a C library predating C99.) + "-Wno-unused-function", + ] + } + } + + executable("re2c") { + sources = [ + "source/patched-yasm/tools/re2c/actions.c", + "source/patched-yasm/tools/re2c/code.c", + "source/patched-yasm/tools/re2c/dfa.c", + "source/patched-yasm/tools/re2c/main.c", + "source/patched-yasm/tools/re2c/mbo_getopt.c", + "source/patched-yasm/tools/re2c/parser.c", + "source/patched-yasm/tools/re2c/scanner.c", + "source/patched-yasm/tools/re2c/substr.c", + "source/patched-yasm/tools/re2c/translate.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + + # Must be after no_chromium_code for warning flags to be ordered + # correctly. + ":re2c_warnings", + ] + deps = [ + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + config("yasm_warnings") { + if (is_clang) { + cflags = [ + # reg3264type in x86expr.c is unused. + "-Wno-unused-local-typedef", + ] + } else if (is_linux) { + cflags = [ + # dosexe_objfmt_output ignores the return value of ftruncate. + "-Wno-unused-result", + ] + } + } + + executable("yasm") { + sources = [ + "source/patched-yasm/frontends/yasm/yasm-options.c", + "source/patched-yasm/frontends/yasm/yasm.c", + "source/patched-yasm/libyasm/assocdat.c", + "source/patched-yasm/libyasm/bc-align.c", + "source/patched-yasm/libyasm/bc-data.c", + "source/patched-yasm/libyasm/bc-incbin.c", + "source/patched-yasm/libyasm/bc-org.c", + "source/patched-yasm/libyasm/bc-reserve.c", + "source/patched-yasm/libyasm/bitvect.c", + "source/patched-yasm/libyasm/bytecode.c", + "source/patched-yasm/libyasm/errwarn.c", + "source/patched-yasm/libyasm/expr.c", + "source/patched-yasm/libyasm/file.c", + "source/patched-yasm/libyasm/floatnum.c", + "source/patched-yasm/libyasm/hamt.c", + "source/patched-yasm/libyasm/insn.c", + "source/patched-yasm/libyasm/intnum.c", + "source/patched-yasm/libyasm/inttree.c", + "source/patched-yasm/libyasm/linemap.c", + "source/patched-yasm/libyasm/md5.c", + "source/patched-yasm/libyasm/mergesort.c", + "source/patched-yasm/libyasm/section.c", + "source/patched-yasm/libyasm/strcasecmp.c", + "source/patched-yasm/libyasm/strsep.c", + "source/patched-yasm/libyasm/symrec.c", + "source/patched-yasm/libyasm/valparam.c", + "source/patched-yasm/libyasm/value.c", + "source/patched-yasm/modules/arch/lc3b/lc3barch.c", + "source/patched-yasm/modules/arch/lc3b/lc3bbc.c", + "source/patched-yasm/modules/arch/x86/x86arch.c", + "source/patched-yasm/modules/arch/x86/x86bc.c", + "source/patched-yasm/modules/arch/x86/x86expr.c", + "source/patched-yasm/modules/arch/x86/x86id.c", + "source/patched-yasm/modules/dbgfmts/codeview/cv-dbgfmt.c", + "source/patched-yasm/modules/dbgfmts/codeview/cv-symline.c", + "source/patched-yasm/modules/dbgfmts/codeview/cv-type.c", + "source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c", + "source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c", + "source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-info.c", + "source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-line.c", + "source/patched-yasm/modules/dbgfmts/null/null-dbgfmt.c", + "source/patched-yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c", + "source/patched-yasm/modules/listfmts/nasm/nasm-listfmt.c", + "source/patched-yasm/modules/objfmts/bin/bin-objfmt.c", + "source/patched-yasm/modules/objfmts/coff/coff-objfmt.c", + "source/patched-yasm/modules/objfmts/coff/win64-except.c", + "source/patched-yasm/modules/objfmts/dbg/dbg-objfmt.c", + "source/patched-yasm/modules/objfmts/elf/elf-objfmt.c", + "source/patched-yasm/modules/objfmts/elf/elf-x86-amd64.c", + "source/patched-yasm/modules/objfmts/elf/elf-x86-x32.c", + "source/patched-yasm/modules/objfmts/elf/elf-x86-x86.c", + "source/patched-yasm/modules/objfmts/elf/elf.c", + "source/patched-yasm/modules/objfmts/macho/macho-objfmt.c", + "source/patched-yasm/modules/objfmts/rdf/rdf-objfmt.c", + "source/patched-yasm/modules/objfmts/xdf/xdf-objfmt.c", + "source/patched-yasm/modules/parsers/gas/gas-parse-intel.c", + "source/patched-yasm/modules/parsers/gas/gas-parse.c", + "source/patched-yasm/modules/parsers/gas/gas-parser.c", + "source/patched-yasm/modules/parsers/nasm/nasm-parse.c", + "source/patched-yasm/modules/parsers/nasm/nasm-parser.c", + "source/patched-yasm/modules/preprocs/cpp/cpp-preproc.c", + "source/patched-yasm/modules/preprocs/gas/gas-eval.c", + "source/patched-yasm/modules/preprocs/gas/gas-preproc.c", + "source/patched-yasm/modules/preprocs/nasm/nasm-eval.c", + "source/patched-yasm/modules/preprocs/nasm/nasm-pp.c", + "source/patched-yasm/modules/preprocs/nasm/nasm-preproc.c", + "source/patched-yasm/modules/preprocs/nasm/nasmlib.c", + "source/patched-yasm/modules/preprocs/raw/raw-preproc.c", + + # Files generated by compile_gperf + "$target_gen_dir/x86cpu.c", + "$target_gen_dir/x86regtmod.c", + + # Files generated by compile_re2c + "$target_gen_dir/gas-token.c", + "$target_gen_dir/nasm-token.c", + + # File generated by compile_re2c_lc3b + "$target_gen_dir/lc3bid.c", + + # File generated by generate_module + "$target_gen_dir/module.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":yasm_config", + "//build/config/compiler:no_chromium_code", + "//build/config/compiler:no_incompatible_pointer_warnings", + + # Must be after no_chromium_code for warning flags to be ordered + # correctly. + ":yasm_warnings", + ] + + # Disable WPO for yasm: crbug.com/604808 + if (is_official_build && full_wpo_on_official) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_no_wpo" ] + } else { + configs -= configs_to_delete + configs += configs_to_add + } + + # Yasm generates a bunch of .c files which its source file #include. These + # are placed in |yasm_gen_include_dir|. + include_dirs = [ yasm_gen_include_dir ] + + if (!is_win) { + cflags = [ + "-std=c89", + "-pedantic", + ] + } + + # TODO(ajwong): This should take most of the generated output as + # inputs. + deps = [ + ":compile_gperf", + ":compile_gperf_for_include", + ":compile_nasm_macros", + ":compile_nasm_version", + ":compile_re2c", + ":compile_re2c_lc3b", + ":compile_win64_gas", + ":compile_win64_nasm", + ":generate_license", + ":generate_module", + ":generate_version", + ":yasm_utils", + "//build/config:exe_and_shlib_deps", + + # Default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + + compiled_action_foreach("compile_gperf") { + tool = ":genperf" + sources = [ + "source/patched-yasm/modules/arch/x86/x86cpu.gperf", + "source/patched-yasm/modules/arch/x86/x86regtmod.gperf", + ] + + outputs = [ + "$target_gen_dir/{{source_name_part}}.c", + ] + args = [ + "{{source}}", + rebase_path(target_gen_dir, root_build_dir) + "/{{source_name_part}}.c", + ] + } + + # This differs from |compile_gperf| in where it places it output files. + compiled_action_foreach("compile_gperf_for_include") { + tool = ":genperf" + sources = [ + # Make sure the generated gperf files in $target_gen_dir are synced with + # the outputs for the related generate_*_insn actions in the + # generate_files target below. + # + # The output for these two are #included by + # source/patched-yasm/modules/arch/x86/x86id.c + "source/patched-yasm/x86insn_gas.gperf", + "source/patched-yasm/x86insn_nasm.gperf", + ] + + outputs = [ + "$yasm_gen_include_dir/{{source_name_part}}.c", + ] + args = [ + "{{source}}", + rebase_path(yasm_gen_include_dir, root_build_dir) + + "/{{source_name_part}}.c", + ] + } + + template("compile_macro") { + compiled_action(target_name) { + tool = ":genmacro" + + # Output #included by source/patched-yasm/frontends/yasm/yasm.c. + inputs = invoker.sources + outputs = invoker.outputs + args = [ + rebase_path(outputs[0], root_build_dir), + invoker.macro_varname, + rebase_path(inputs[0], root_build_dir), + ] + if (defined(invoker.deps)) { + deps = invoker.deps + } + } + } + + compile_macro("compile_nasm_macros") { + # Output #included by + # source/patched-yasm/modules/preprocs/nasm/nasm-parser.c + sources = [ + "source/patched-yasm/modules/parsers/nasm/nasm-std.mac", + ] + outputs = [ + "$yasm_gen_include_dir/nasm-macros.c", + ] + macro_varname = "nasm_standard_mac" + } + + compile_macro("compile_nasm_version") { + # Output #included by + # source/patched-yasm/modules/preprocs/nasm/nasm-preproc.c + sources = [ + "$target_gen_dir/$version_file", + ] + outputs = [ + "$yasm_gen_include_dir/nasm-version.c", + ] + macro_varname = "nasm_version_mac" + deps = [ + ":generate_version", + ] + } + + compile_macro("compile_win64_gas") { + # Output #included by source/patched-yasm/frontends/yasm/yasm.c. + sources = [ + "source/patched-yasm/modules/objfmts/coff/win64-gas.mac", + ] + outputs = [ + "$yasm_gen_include_dir/win64-gas.c", + ] + macro_varname = "win64_gas_stdmac" + } + + compile_macro("compile_win64_nasm") { + # Output #included by source/patched-yasm/frontends/yasm/yasm.c. + sources = [ + "source/patched-yasm/modules/objfmts/coff/win64-nasm.mac", + ] + outputs = [ + "$yasm_gen_include_dir/win64-nasm.c", + ] + macro_varname = "win64_nasm_stdmac" + } + + compiled_action_foreach("compile_re2c") { + tool = ":re2c" + sources = [ + "source/patched-yasm/modules/parsers/gas/gas-token.re", + "source/patched-yasm/modules/parsers/nasm/nasm-token.re", + ] + outputs = [ + "$target_gen_dir/{{source_name_part}}.c", + ] + args = [ + "-b", + "-o", + rebase_path(target_gen_dir, root_build_dir) + "/{{source_name_part}}.c", + "{{source}}", + ] + } + + # This call doesn't fit into the re2c template above. + compiled_action("compile_re2c_lc3b") { + tool = ":re2c" + inputs = [ + "source/patched-yasm/modules/arch/lc3b/lc3bid.re", + ] + outputs = [ + "$target_gen_dir/lc3bid.c", + ] + args = [ + "-s", + "-o", + rebase_path(outputs[0], root_build_dir), + rebase_path(inputs[0], root_build_dir), + ] + } + + compiled_action("generate_license") { + tool = ":genstring" + + # Output #included by source/patched-yasm/frontends/yasm/yasm.c. + inputs = [ + "source/patched-yasm/COPYING", + ] + outputs = [ + "$yasm_gen_include_dir/license.c", + ] + args = [ + "license_msg", + rebase_path(outputs[0], root_build_dir), + rebase_path(inputs[0], root_build_dir), + ] + } + + compiled_action("generate_module") { + tool = ":genmodule" + inputs = [ + "source/patched-yasm/libyasm/module.in", + config_makefile, + ] + outputs = [ + "$target_gen_dir/module.c", + ] + args = [ + rebase_path(inputs[0], root_build_dir), + rebase_path(config_makefile, root_build_dir), + rebase_path(outputs[0], root_build_dir), + ] + } + + compiled_action("generate_version") { + tool = ":genversion" + outputs = [ + "$target_gen_dir/$version_file", + ] + args = [ rebase_path(outputs[0], root_build_dir) ] + } +} diff --git a/third_party/yasm/CHROMIUM.diff b/third_party/yasm/CHROMIUM.diff new file mode 100644 index 0000000000000000000000000000000000000000..8f036f214d6868431cfd03ef0ec4382f0bf8056c --- /dev/null +++ b/third_party/yasm/CHROMIUM.diff @@ -0,0 +1,81 @@ +diff --git a/frontends/tasm/tasm.c b/frontends/tasm/tasm.c +index 58954b6..568f478 100644 +--- a/frontends/tasm/tasm.c ++++ b/frontends/tasm/tasm.c +@@ -228,7 +228,6 @@ static opt_option options[] = + /* version message */ + /*@observer@*/ static const char *version_msg[] = { + PACKAGE_STRING, +- "Compiled on " __DATE__ ".", + "Copyright (c) 2001-2010 Peter Johnson and other Yasm developers.", + "Run yasm --license for licensing overview and summary." + }; +diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c +index ff4c59e..015ae8d 100644 +--- a/frontends/yasm/yasm.c ++++ b/frontends/yasm/yasm.c +@@ -217,7 +217,6 @@ static opt_option options[] = + /* version message */ + /*@observer@*/ static const char *version_msg[] = { + PACKAGE_STRING, +- "Compiled on " __DATE__ ".", + "Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.", + "Run yasm --license for licensing overview and summary." + }; +diff --git a/libyasm/genmodule.c b/libyasm/genmodule.c +index 867d93a..027e2fe 100644 +--- a/libyasm/genmodule.c ++++ b/libyasm/genmodule.c +@@ -58,9 +58,14 @@ main(int argc, char *argv[]) + include *inc; + int isam = 0; + int linecont = 0; +- +- if (argc != 3) { +- fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]>\n", argv[0]); ++ char *outfile; ++ ++ if (argc == 3) { ++ outfile = OUTPUT; ++ } else if (argc == 4) { ++ outfile = argv[3]; ++ } else { ++ fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]> [<outfile>]\n", argv[0]); + return EXIT_FAILURE; + } + +@@ -167,10 +172,10 @@ keepgoing: + fclose(in); + } + +- out = fopen(OUTPUT, "wt"); ++ out = fopen(outfile, "wt"); + + if (!out) { +- fprintf(stderr, "Could not open `%s'.\n", OUTPUT); ++ fprintf(stderr, "Could not open `%s'.\n", outfile); + return EXIT_FAILURE; + } + +@@ -181,7 +186,7 @@ keepgoing: + if (!in) { + fprintf(stderr, "Could not open `%s'.\n", argv[1]); + fclose(out); +- remove(OUTPUT); ++ remove(outfile); + return EXIT_FAILURE; + } + +diff --git a/tools/genperf/perfect.c b/tools/genperf/perfect.c +index a9a14c0..e45f9c5 100644 +--- a/tools/genperf/perfect.c ++++ b/tools/genperf/perfect.c +@@ -563,7 +563,7 @@ static int perfect( + if (!augment(tabb, tabh, tabq, blen, scramble, smax, &tabb[i], nkeys, + i+1, form)) + { +- fprintf(stderr, "fail to map group of size %ld for tab size %ld\n", j, blen); ++ /* Do not print an error. The caller may retry with a larger table. */ + return FALSE; + } + diff --git a/third_party/yasm/README.pdfium b/third_party/yasm/README.pdfium new file mode 100644 index 0000000000000000000000000000000000000000..41da312adb7665ac0c098aa7b60e0a781df8b98c --- /dev/null +++ b/third_party/yasm/README.pdfium @@ -0,0 +1,126 @@ +Name: yasm +URL: http://www.tortall.net/projects/yasm/ +Version: 1.3.0 +License: 2-clause or 3-clause BSD licensed, with the exception of bitvect, which is triple-licensed under the Artistic license, GPL, and LGPL +License File: source/patched-yasm/COPYING +License Android Compatible: yes +Security Critical: no + +Source: http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz +SHA-512: 572d3b45568b10f58e48f1188c2d6bcbdd16429c8afaccc8c6d37859b45635e1 + 06885d679e41d0bee78c23822108c7ae75aa7475eed5ba58057e0a6fe1b68645 + +With these patches applied: +* CHROMIUM.diff: Combined patch from Chromium. + See Chromium's third_party/yasm/README.chromium for details. + + +See also the BUILD.gn file for a description of the yasm build process. + +Instructions for recreating the BUILD.gn file. + 1) Update yasm and re-apply the patches. + + 2) Make a copy of source in a different directory (e.g., /tmp/yasm_build) and + run configure. Using another directory will keep the source tree clean. An + out-of-tree build does not appear to work reliably as of yasm 1.3.0. + + 3) Next, capture all the output from a build of yasm. We will use the build + log as a reference for BUILD.gn. + + make yasm > yasm_build_log 2> yasm_build_err + + 4) Check yasm_build_err to see if there are any anomalies beyond yasm's + compiler warnings. + + 5) Grab the generated libyasm-stdint.h and config.h and put into the correct + platform location. + + src/third_party/yasm/source/config/[platform] + + For android platform, copy the files generated for linux, but make sure + that ENABLE_NLS is not defined to allow mac host compiles to work. For + ios, copy the files from mac. For win, copy the libyasm-stdint.h from + linux and fix up config.h. + + Find the YASM_MODULES line in the generated Makefile and update + src/third_party/yasm/source/config/Makefile. It is needed by the + "genmodule" subprogram as input for creating the available modules list. + + 6) Make sure all the subprograms are represented in BUILD.gn. + + grep -w gcc yasm_build_log | + grep -v ' -DHAVE_CONFIG_H ' + + The yasm build creates a bunch of subprograms that in-turn generate + more .c files in the build. Luckily the commands to generate the + subprogram do not have -DHAVE_CONFIG_H as a cflag. + + From this list, make sure all the subprograms that are build have + appropriate targets in the BUILD.gn. + + You will notice, when you get to the next step, that there are some + .c source files that are compiled both for yasm, and for genperf. + + Those should go into the yasm_utils target so that they can be shared by + the genperf and yasm targets. Find the files used by genperf by appending + + | grep 'gp-' + + to the command above. Then grep for them without the 'gp-' prefix to see if + they are used in yasm as well. + + 7) Find all the source files used to build yasm proper. + + grep -w gcc yasm_build_log | + grep ' -DHAVE_CONFIG_H ' | + sed -e 's/[&\\]*$//' | # Remove any trailing '&&'s and '\'s. + awk '{print $NF }' | + sed -e "s/'\.\/'\`//" | # Removes some garbage from the build line. + sort -u | + sed -e 's/\(.*\)/ "source\/patched-yasm\/\1",/' + + Reversing the -DHAVE_CONFIG_H filter from the command above should + list the compile lines for yasm proper. + + This should get you close, but you will need to manually examine this + list. However, some of the built products are still included in the + command above. Generally, if the source file is in the root directory, + it's a generated file. Also remove the sources in the yasm_utils target. + + Inspect the current BUILD.gn for a list of the subprograms and their + outputs. + + Update the sources list in the yasm target accordingly. Read step #9 + as well if you update the source list to avoid problems. + + 8) Update the actions for each of the subprograms. + + Here is the real fun. For each subprogram created, you will need to + update the actions and rules in BUILD.gn that invoke the subprogram to + generate the files needed by the rest of the build. + + I don't have any good succinct instructions for this. Grep the build + log for each subprogram invocation (eg., "./genversion"), look at + its command inputs and output, then verify our BUILD.gn does something + similar. + + The good news is things likely only link or compile if this is done + right so you'll know if there is a problem. + + Again, refer to the existing BUILD.gn for a guide to how the generated + files are used. + + Here are a few gotchas: + 1) genmodule, by default, writes module.c into the current + directory. This does not play nicely with gn. We have a patch + to allow specifying a specific output file. + + 2) Most of the generated files, even though they are .c files, are + #included by other files in the build. Make sure they end up + in yasm_gen_include_dir. + + 3) Some of the genperf output is #included while others need to be + compiled directly. That is why there are 2 different rules for + .gperf files in two targets. + + 9) If all that's is finished, attempt to build....and cross your fingers. diff --git a/third_party/yasm/run_yasm.py b/third_party/yasm/run_yasm.py new file mode 100644 index 0000000000000000000000000000000000000000..cbd79ccea177250abb74080b6b2f3b7e3ac779c5 --- /dev/null +++ b/third_party/yasm/run_yasm.py @@ -0,0 +1,51 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""A wrapper to run yasm. + +Its main job is to provide a Python wrapper for GN integration, and to write +the makefile-style output yasm generates in stdout to a .d file for dependency +management of .inc files. + +Run with: + python run_yasm.py <yasm_binary_path> <all other yasm args> + +Note that <all other yasm args> must include an explicit output file (-o). This +script will append a ".d" to this and write the dependencies there. This script +will add "-M" to cause yasm to write the deps to stdout, so you don't need to +specify that. +""" + +import argparse +import sys +import subprocess + +# Extract the output file name from the yasm command line so we can generate a +# .d file with the same base name. +parser = argparse.ArgumentParser() +parser.add_argument("-o", dest="objfile") +options, _ = parser.parse_known_args() + +objfile = options.objfile +depfile = objfile + '.d' + +# Assemble. +result_code = subprocess.call(sys.argv[1:]) +if result_code != 0: + sys.exit(result_code) + +# Now generate the .d file listing the dependencies. The -M option makes yasm +# write the Makefile-style dependencies to stdout, but it seems that inhibits +# generating any compiled output so we need to do this in a separate pass. +# However, outputting deps seems faster than actually assembling, and yasm is +# so fast anyway this is not a big deal. +# +# This guarantees proper dependency management for assembly files. Otherwise, +# we would have to require people to manually specify the .inc files they +# depend on in the build file, which will surely be wrong or out-of-date in +# some cases. +deps = subprocess.check_output(sys.argv[1:] + ['-M']) +with open(depfile, "wb") as f: + f.write(deps) + diff --git a/third_party/yasm/source/config/Makefile b/third_party/yasm/source/config/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..59dc34d5996c79d8ba3b3acfd233aa8029c5a754 --- /dev/null +++ b/third_party/yasm/source/config/Makefile @@ -0,0 +1,9 @@ +# The YASM_MODULES line below is extracted from the Makefile generated by the +# configure script. +YASM_MODULES = arch_x86 arch_lc3b listfmt_nasm parser_gas parser_gnu \ + parser_nasm parser_tasm preproc_nasm preproc_tasm preproc_raw \ + preproc_cpp preproc_gas dbgfmt_cv8 dbgfmt_dwarf2 dbgfmt_null \ + dbgfmt_stabs objfmt_dbg objfmt_bin objfmt_dosexe objfmt_elf \ + objfmt_elf32 objfmt_elf64 objfmt_elfx32 objfmt_coff \ + objfmt_macho objfmt_macho32 objfmt_macho64 objfmt_rdf \ + objfmt_win32 objfmt_win64 objfmt_x64 objfmt_xdf diff --git a/third_party/yasm/source/config/android/config.h b/third_party/yasm/source/config/android/config.h new file mode 100644 index 0000000000000000000000000000000000000000..d1b5ab43231b23825e5f205de1c27c2c0ee1b2d7 --- /dev/null +++ b/third_party/yasm/source/config/android/config.h @@ -0,0 +1,173 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Command name to run C preprocessor */ +#define CPP_PROG "cc -E" + +/* */ +/* #undef ENABLE_NLS */ + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* */ +/* #undef HAVE_CATGETS */ + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the <direct.h> header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the GNU C Library */ +#define HAVE_GNU_C_LIBRARY 1 + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* */ +/* #undef HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mergesort' function. */ +/* #undef HAVE_MERGESORT */ + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `toascii' function. */ +#define HAVE_TOASCII 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +/* #undef HAVE__STRICMP */ + +/* Name of package */ +#define PACKAGE "yasm" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-yasm@tortall.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "yasm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yasm 1.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "yasm" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.0" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void*', as computed by sizeof. */ +/* #undef SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.0" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ diff --git a/third_party/yasm/source/config/android/libyasm-stdint.h b/third_party/yasm/source/config/android/libyasm-stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..b9ce696dde94a7084eaac734b98cb125d4625dbc --- /dev/null +++ b/third_party/yasm/source/config/android/libyasm-stdint.h @@ -0,0 +1,9 @@ +#ifndef _YASM_LIBYASM_STDINT_H +#define _YASM_LIBYASM_STDINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "yasm 1.3.0" +/* generated using gcc -std=gnu99 */ +#define _STDINT_HAVE_STDINT_H 1 +#include <stdint.h> +#endif +#endif diff --git a/third_party/yasm/source/config/ios/config.h b/third_party/yasm/source/config/ios/config.h new file mode 100644 index 0000000000000000000000000000000000000000..01695d6eac883d98166bbecc32cdd616eef62757 --- /dev/null +++ b/third_party/yasm/source/config/ios/config.h @@ -0,0 +1,173 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Command name to run C preprocessor */ +#define CPP_PROG "cc -E" + +/* */ +/* #undef ENABLE_NLS */ + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* */ +/* #undef HAVE_CATGETS */ + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +#define HAVE_CFLOCALECOPYCURRENT 1 + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +#define HAVE_CFPREFERENCESCOPYAPPVALUE 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +/* #undef HAVE_DCGETTEXT */ + +/* Define to 1 if you have the <direct.h> header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* */ +/* #undef HAVE_GETTEXT */ + +/* Define to 1 if you have the GNU C Library */ +/* #undef HAVE_GNU_C_LIBRARY */ + +/* Define if you have the iconv() function and it works. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* */ +/* #undef HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mergesort' function. */ +#define HAVE_MERGESORT 1 + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `toascii' function. */ +#define HAVE_TOASCII 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +/* #undef HAVE__STRICMP */ + +/* Name of package */ +#define PACKAGE "yasm" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-yasm@tortall.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "yasm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yasm 1.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "yasm" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.0" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void*', as computed by sizeof. */ +/* #undef SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.0" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ diff --git a/third_party/yasm/source/config/ios/libyasm-stdint.h b/third_party/yasm/source/config/ios/libyasm-stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..5780da8b6405c1a4ae3c3b03fe1e0b8ae4a4617c --- /dev/null +++ b/third_party/yasm/source/config/ios/libyasm-stdint.h @@ -0,0 +1,9 @@ +#ifndef _YASM_LIBYASM_STDINT_H +#define _YASM_LIBYASM_STDINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "yasm 1.3.0" +/* generated using gcc */ +#define _STDINT_HAVE_STDINT_H 1 +#include <stdint.h> +#endif +#endif diff --git a/third_party/yasm/source/config/linux/config.h b/third_party/yasm/source/config/linux/config.h new file mode 100644 index 0000000000000000000000000000000000000000..6ca1f6a017b3dda959a8a7e4518efc34ce181da6 --- /dev/null +++ b/third_party/yasm/source/config/linux/config.h @@ -0,0 +1,173 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Command name to run C preprocessor */ +#define CPP_PROG "cc -E" + +/* */ +#define ENABLE_NLS 1 + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* */ +/* #undef HAVE_CATGETS */ + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the <direct.h> header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the GNU C Library */ +#define HAVE_GNU_C_LIBRARY 1 + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* */ +/* #undef HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mergesort' function. */ +/* #undef HAVE_MERGESORT */ + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `toascii' function. */ +#define HAVE_TOASCII 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +/* #undef HAVE__STRICMP */ + +/* Name of package */ +#define PACKAGE "yasm" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-yasm@tortall.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "yasm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yasm 1.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "yasm" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.0" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void*', as computed by sizeof. */ +/* #undef SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.0" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ diff --git a/third_party/yasm/source/config/linux/libyasm-stdint.h b/third_party/yasm/source/config/linux/libyasm-stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..b9ce696dde94a7084eaac734b98cb125d4625dbc --- /dev/null +++ b/third_party/yasm/source/config/linux/libyasm-stdint.h @@ -0,0 +1,9 @@ +#ifndef _YASM_LIBYASM_STDINT_H +#define _YASM_LIBYASM_STDINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "yasm 1.3.0" +/* generated using gcc -std=gnu99 */ +#define _STDINT_HAVE_STDINT_H 1 +#include <stdint.h> +#endif +#endif diff --git a/third_party/yasm/source/config/mac/config.h b/third_party/yasm/source/config/mac/config.h new file mode 100644 index 0000000000000000000000000000000000000000..01695d6eac883d98166bbecc32cdd616eef62757 --- /dev/null +++ b/third_party/yasm/source/config/mac/config.h @@ -0,0 +1,173 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Command name to run C preprocessor */ +#define CPP_PROG "cc -E" + +/* */ +/* #undef ENABLE_NLS */ + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* */ +/* #undef HAVE_CATGETS */ + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +#define HAVE_CFLOCALECOPYCURRENT 1 + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +#define HAVE_CFPREFERENCESCOPYAPPVALUE 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +/* #undef HAVE_DCGETTEXT */ + +/* Define to 1 if you have the <direct.h> header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* */ +/* #undef HAVE_GETTEXT */ + +/* Define to 1 if you have the GNU C Library */ +/* #undef HAVE_GNU_C_LIBRARY */ + +/* Define if you have the iconv() function and it works. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* */ +/* #undef HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mergesort' function. */ +#define HAVE_MERGESORT 1 + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `toascii' function. */ +#define HAVE_TOASCII 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +/* #undef HAVE__STRICMP */ + +/* Name of package */ +#define PACKAGE "yasm" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-yasm@tortall.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "yasm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yasm 1.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "yasm" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.0" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void*', as computed by sizeof. */ +/* #undef SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.0" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ diff --git a/third_party/yasm/source/config/mac/libyasm-stdint.h b/third_party/yasm/source/config/mac/libyasm-stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..5780da8b6405c1a4ae3c3b03fe1e0b8ae4a4617c --- /dev/null +++ b/third_party/yasm/source/config/mac/libyasm-stdint.h @@ -0,0 +1,9 @@ +#ifndef _YASM_LIBYASM_STDINT_H +#define _YASM_LIBYASM_STDINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "yasm 1.3.0" +/* generated using gcc */ +#define _STDINT_HAVE_STDINT_H 1 +#include <stdint.h> +#endif +#endif diff --git a/third_party/yasm/source/config/openbsd/config.h b/third_party/yasm/source/config/openbsd/config.h new file mode 100644 index 0000000000000000000000000000000000000000..4f742881c825fd0e8ab1a15b07b0d9873cf1d517 --- /dev/null +++ b/third_party/yasm/source/config/openbsd/config.h @@ -0,0 +1,165 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Command name to run C preprocessor */ +#define CPP_PROG "cc -E" + +/* */ +/* #undef ENABLE_NLS */ + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* */ +/* #undef HAVE_CATGETS */ + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +/* #undef HAVE_DCGETTEXT */ + +/* Define to 1 if you have the <direct.h> header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* */ +/* #undef HAVE_GETTEXT */ + +/* Define to 1 if you have the GNU C Library */ +/* #undef HAVE_GNU_C_LIBRARY */ + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* */ +/* #undef HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mergesort' function. */ +#define HAVE_MERGESORT 1 + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `toascii' function. */ +#define HAVE_TOASCII 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +/* #undef HAVE__STRICMP */ + +/* Name of package */ +#define PACKAGE "yasm" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-yasm@tortall.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "yasm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yasm 1.2.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "yasm" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.0" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void*', as computed by sizeof. */ +/* #undef SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.2.0" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ diff --git a/third_party/yasm/source/config/openbsd/libyasm-stdint.h b/third_party/yasm/source/config/openbsd/libyasm-stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..b875214c8943684d71ca7ea83e36e3f5d6f29855 --- /dev/null +++ b/third_party/yasm/source/config/openbsd/libyasm-stdint.h @@ -0,0 +1,9 @@ +#ifndef _YASM_LIBYASM_STDINT_H +#define _YASM_LIBYASM_STDINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "yasm 1.1.0" +/* generated using gcc -std=gnu99 */ +#define _STDINT_HAVE_STDINT_H 1 +#include <stdint.h> +#endif +#endif diff --git a/third_party/yasm/source/config/win/config.h b/third_party/yasm/source/config/win/config.h new file mode 100644 index 0000000000000000000000000000000000000000..12c081d0f8d2b00490592aad7d4f4cbf38aa75bf --- /dev/null +++ b/third_party/yasm/source/config/win/config.h @@ -0,0 +1,173 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Command name to run C preprocessor */ +#define CPP_PROG "cc -E" + +/* */ +/* #undef ENABLE_NLS */ + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* */ +/* #undef HAVE_CATGETS */ + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue i + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the <direct.h> header file. */ +#define HAVE_DIRECT_H 1 + +/* Define to 1 if you have the `ftruncate' function. */ +/* #undef HAVE_FTRUNCATE */ + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the GNU C Library */ +/* #undef HAVE_GNU_C_LIBRARY */ + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* */ +/* #undef HAVE_LC_MESSAGES */ + +/* Define to 1 if you have the <libgen.h> header file. */ +/* #undef HAVE_LIBGEN_H */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mergesort' function. */ +/* #undef HAVE_MERGESORT */ + +/* Define to 1 if you have the `popen' function. */ +/* #undef HAVE_POPEN */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strcasecmp' function. */ +/* #undef HAVE_STRCASECMP */ + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strsep' function. */ +/* #undef HAVE_STRSEP */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `toascii' function. */ +#define HAVE_TOASCII 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +/* #undef HAVE__STRICMP */ + +/* Name of package */ +#define PACKAGE "yasm" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-yasm@tortall.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "yasm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "yasm 1.3.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "yasm" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.0" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void*', as computed by sizeof. */ +/* #undef SIZEOF_VOIDP */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.0" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ diff --git a/third_party/yasm/source/config/win/libyasm-stdint.h b/third_party/yasm/source/config/win/libyasm-stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..b9ce696dde94a7084eaac734b98cb125d4625dbc --- /dev/null +++ b/third_party/yasm/source/config/win/libyasm-stdint.h @@ -0,0 +1,9 @@ +#ifndef _YASM_LIBYASM_STDINT_H +#define _YASM_LIBYASM_STDINT_H 1 +#ifndef _GENERATED_STDINT_H +#define _GENERATED_STDINT_H "yasm 1.3.0" +/* generated using gcc -std=gnu99 */ +#define _STDINT_HAVE_STDINT_H 1 +#include <stdint.h> +#endif +#endif diff --git a/third_party/yasm/yasm_assemble.gni b/third_party/yasm/yasm_assemble.gni new file mode 100644 index 0000000000000000000000000000000000000000..73d554856bad2735edb31462d430e92da79bda01 --- /dev/null +++ b/third_party/yasm/yasm_assemble.gni @@ -0,0 +1,196 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This provides the yasm_assemble() template which uses YASM to assemble +# assembly files. +# +# Files to be assembled with YASM should have an extension of .asm. +# +# Parameters +# +# yasm_flags (optional) +# [list of strings] Pass additional flags into YASM. These are appended +# to the command line. Note that the target machine type and system is +# already set up based on the current toolchain so you don't need to +# specify these things (see below). +# +# Example: yasm_flags = [ "--force-strict" ] +# +# include_dirs (optional) +# [list of dir names] List of additional include dirs. Note that the +# source root and the root generated file dir is always added, just like +# our C++ build sets up. +# +# Example: include_dirs = [ "//some/other/path", target_gen_dir ] +# +# defines (optional) +# [list of strings] List of defines, as with the native code defines. +# +# Example: defines = [ "FOO", "BAR=1" ] +# +# inputs, deps, visibility (optional) +# These have the same meaning as in an action. +# +# Example +# +# yasm_assemble("my_yasm_target") { +# sources = [ +# "ultra_optimized_awesome.asm", +# ] +# include_dirs = [ "assembly_include" ] +# } + +if (is_mac || is_ios) { + if (current_cpu == "x86") { + _yasm_flags = [ + "-fmacho32", + "-m", + "x86", + ] + } else if (current_cpu == "x64") { + _yasm_flags = [ + "-fmacho64", + "-m", + "amd64", + ] + } +} else if (is_posix) { + if (current_cpu == "x86") { + _yasm_flags = [ + "-felf32", + "-m", + "x86", + ] + } else if (current_cpu == "x64") { + _yasm_flags = [ + "-DPIC", + "-felf64", + "-m", + "amd64", + ] + } +} else if (is_win) { + if (current_cpu == "x86") { + _yasm_flags = [ + "-DPREFIX", + "-fwin32", + "-m", + "x86", + ] + } else if (current_cpu == "x64") { + _yasm_flags = [ + "-fwin64", + "-m", + "amd64", + ] + } +} + +if (is_win) { + asm_obj_extension = "obj" +} else { + asm_obj_extension = "o" +} + +template("yasm_assemble") { + assert(defined(invoker.sources), "Need sources defined for $target_name") + + # Only depend on YASM on x86 systems. Force compilation of .asm files for + # ARM to fail. + assert(current_cpu == "x86" || current_cpu == "x64") + + action_name = "${target_name}_action" + source_set_name = target_name + + action_foreach(action_name) { + # Only the source set can depend on this. + visibility = [ ":$source_set_name" ] + + script = "//third_party/yasm/run_yasm.py" + sources = invoker.sources + + if (defined(invoker.inputs)) { + inputs = invoker.inputs + } + + # Executable (first in the args). The binary might be in the root build dir + # (no cross-compiling) or in a toolchain-specific subdirectory of that + # (when cross-compiling). + yasm_label = "//third_party/yasm($host_toolchain)" + args = [ "./" + # Force current dir. + rebase_path(get_label_info(yasm_label, "root_out_dir") + "/yasm", + root_build_dir) ] + + # Deps. + deps = [ + yasm_label, + ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + # Flags. + args += _yasm_flags + if (defined(invoker.yasm_flags)) { + args += invoker.yasm_flags + } + + # User defined include dirs go first. + if (defined(invoker.include_dirs)) { + foreach(include, invoker.include_dirs) { + args += [ "-I" + rebase_path(include, root_build_dir) ] + } + } + + # Default yasm include dirs. Make it match the native build (source root and + # root generated code directory). + # This goes to the end of include list. + args += [ + "-I.", + + # Using "//." will produce a relative path "../.." which looks better than + # "../../" which will result from using "//" as the base (although both + # work). This is because rebase_path will terminate the result in a + # slash if the input ends in a slash. + "-I" + rebase_path("//.", root_build_dir), + "-I" + rebase_path(root_gen_dir, root_build_dir), + ] + + # Extra defines. + if (defined(invoker.defines)) { + foreach(def, invoker.defines) { + args += [ "-D$def" ] + } + } + + # Output file. + outputs = [ + "$target_out_dir/$source_set_name/{{source_name_part}}.o", + ] + args += [ + "-o", + rebase_path(outputs[0], root_build_dir), + "{{source}}", + ] + + # The wrapper script run_yasm will write the depfile to the same name as + # the output but with .d appended (like gcc will). + depfile = outputs[0] + ".d" + } + + # Gather the .o files into a linkable thing. This doesn't actually link + # anything (a source set just compiles files to link later), but will pass + # the object files generated by the action up the dependency chain. + static_library(source_set_name) { + if (defined(invoker.visibility)) { + visibility = invoker.visibility + } + + sources = get_target_outputs(":$action_name") + + deps = [ + ":$action_name", + ] + } +} diff --git a/third_party/zlib_v128/adler32.c b/third_party/zlib_v128/adler32.c deleted file mode 100644 index 82a84ceed2b963ffae793abd7efa58d3a0eb03c4..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/adler32.c +++ /dev/null @@ -1,179 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -#define local static - -local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - -#define BASE 65521 /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware -- - try it both ways to see which is faster */ -#ifdef NO_DIVIDE -/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 - (thank you to John Reiser for pointing this out) */ -# define CHOP(a) \ - do { \ - unsigned long tmp = a >> 16; \ - a &= 0xffffUL; \ - a += (tmp << 4) - tmp; \ - } while (0) -# define MOD28(a) \ - do { \ - CHOP(a); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD(a) \ - do { \ - CHOP(a); \ - MOD28(a); \ - } while (0) -# define MOD63(a) \ - do { /* this assumes a is not negative */ \ - z_off64_t tmp = a >> 32; \ - a &= 0xffffffffL; \ - a += (tmp << 8) - (tmp << 5) + tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD28(a) a %= BASE -# define MOD63(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32( - uLong adler, - const Bytef *buf, - uInt len) -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -local uLong adler32_combine_( - uLong adler1, - uLong adler2, - z_off64_t len2) -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* for negative len, return invalid adler32 as a clue for debugging */ - if (len2 < 0) - return 0xffffffffUL; - - /* the derivation of this formula is left as an exercise for the reader */ - MOD63(len2); /* assumes len2 >= 0 */ - rem = (unsigned)len2; - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 >= BASE) sum1 -= BASE; - if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 >= BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine( - uLong adler1, - uLong adler2, - z_off_t len2) -{ - return adler32_combine_(adler1, adler2, len2); -} - -uLong ZEXPORT adler32_combine64( - uLong adler1, - uLong adler2, - z_off64_t len2) -{ - return adler32_combine_(adler1, adler2, len2); -} diff --git a/third_party/zlib_v128/compress.c b/third_party/zlib_v128/compress.c deleted file mode 100644 index 0314fbc61a3232b836927318087cf3ef14a887af..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/compress.c +++ /dev/null @@ -1,80 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2 ( - Bytef *dest, - uLongf *destLen, - const Bytef *source, - uLong sourceLen, - int level) -{ - z_stream stream; - int err; - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =========================================================================== - */ -int ZEXPORT compress ( - Bytef *dest, - uLongf *destLen, - const Bytef *source, - uLong sourceLen) -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -uLong ZEXPORT compressBound ( - uLong sourceLen) -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13; -} diff --git a/third_party/zlib_v128/crc32.c b/third_party/zlib_v128/crc32.c deleted file mode 100644 index f0072c94bf9494a463f782d5caefab2be6bf10c6..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/crc32.c +++ /dev/null @@ -1,425 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id$ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - - DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. - */ - -#ifdef MAKECRCH -# include <stdio.h> -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -#define local static - -/* Definitions for doing the crc four data bytes at a time. */ -#if !defined(NOBYFOUR) && defined(Z_U4) -# define BYFOUR -#endif -#ifdef BYFOUR - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); -# define TBLS 8 -#else -# define TBLS 1 -#endif /* BYFOUR */ - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); - - -#ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local z_crc_t FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); -#ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *)); -#endif /* MAKECRCH */ -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - z_crc_t c; - int n, k; - z_crc_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (z_crc_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (z_crc_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } - -#ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const z_crc_t FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH -local void write_table( - FILE *out, - const z_crc_t FAR *table) -{ - int n; - - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} -#endif /* MAKECRCH */ - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - return (const z_crc_t FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -unsigned long ZEXPORT crc32( - unsigned long crc, - const unsigned char FAR *buf, - uInt len) -{ - if (buf == Z_NULL) return 0UL; - -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - z_crc_t endian; - - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -#ifdef BYFOUR - -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little( - unsigned long crc, - const unsigned char FAR *buf, - unsigned len) -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = (z_crc_t)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big( - unsigned long crc, - const unsigned char FAR *buf, - unsigned len) -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = ZSWAP32((z_crc_t)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf4++; - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(ZSWAP32(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times( - unsigned long *mat, - unsigned long vec) -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square( - unsigned long *square, - unsigned long *mat) -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -local uLong crc32_combine_( - uLong crc1, - uLong crc2, - z_off64_t len2) -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine( - uLong crc1, - uLong crc2, - z_off_t len2) -{ - return crc32_combine_(crc1, crc2, len2); -} - -uLong ZEXPORT crc32_combine64( - uLong crc1, - uLong crc2, - z_off64_t len2) -{ - return crc32_combine_(crc1, crc2, len2); -} diff --git a/third_party/zlib_v128/crc32.h b/third_party/zlib_v128/crc32.h deleted file mode 100644 index 9e0c7781025148380d130d6f7b6e590117ad3a8c..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/crc32.h +++ /dev/null @@ -1,441 +0,0 @@ -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const z_crc_t FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; diff --git a/third_party/zlib_v128/deflate.c b/third_party/zlib_v128/deflate.c deleted file mode 100644 index 1afe233c9aea8c341a37bf7adf55cf4383bb5797..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/deflate.c +++ /dev/null @@ -1,1966 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id$ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -#ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -#ifdef FASTEST -local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ -#else -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -#endif - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - -/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_( - z_streamp strm, - int level, - const char *version, - int stream_size) -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_( - z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy, - const char *version, - int stream_size) -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } -#ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } -#endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->high_water = 0; /* nothing written to s->window yet */ - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary ( - z_streamp strm, - const Bytef *dictionary, - uInt dictLength) -{ - deflate_state *s; - uInt str, n; - int wrap; - unsigned avail; - z_const unsigned char *next; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) - return Z_STREAM_ERROR; - s = strm->state; - wrap = s->wrap; - if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) - return Z_STREAM_ERROR; - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap == 1) - strm->adler = adler32(strm->adler, dictionary, dictLength); - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s->w_size) { - if (wrap == 0) { /* already empty otherwise */ - CLEAR_HASH(s); - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - dictionary += dictLength - s->w_size; /* use the tail */ - dictLength = s->w_size; - } - - /* insert dictionary into window and hash */ - avail = strm->avail_in; - next = strm->next_in; - strm->avail_in = dictLength; - strm->next_in = (z_const Bytef *)dictionary; - fill_window(s); - while (s->lookahead >= MIN_MATCH) { - str = s->strstart; - n = s->lookahead - (MIN_MATCH-1); - do { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - } while (--n); - s->strstart = str; - s->lookahead = MIN_MATCH-1; - fill_window(s); - } - s->strstart += s->lookahead; - s->block_start = (long)s->strstart; - s->insert = s->lookahead; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - strm->next_in = next; - strm->avail_in = avail; - s->wrap = wrap; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateResetKeep ( - z_streamp strm) -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = -#ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : -#endif - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset ( - z_streamp strm) -{ - int ret; - - ret = deflateResetKeep(strm); - if (ret == Z_OK) - lm_init(strm->state); - return ret; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) - z_streamp strm; - gz_headerp head; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePending ( - z_streamp strm, - unsigned *pending, - int *bits) -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (pending != Z_NULL) - *pending = strm->state->pending; - if (bits != Z_NULL) - *bits = strm->state->bi_valid; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) - z_streamp strm; - int bits; - int value; -{ - deflate_state *s; - int put; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) - return Z_BUF_ERROR; - do { - put = Buf_size - s->bi_valid; - if (put > bits) - put = bits; - s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); - s->bi_valid += put; - _tr_flush_bits(s); - value >>= put; - bits -= put; - } while (bits); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams( - z_streamp strm, - int level, - int strategy) -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); - if (err == Z_BUF_ERROR && s->pending == 0) - err = Z_OK; - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune( - z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain) -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; - s->nice_match = nice_length; - s->max_chain_length = max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. - */ -uLong ZEXPORT deflateBound( - z_streamp strm, - uLong sourceLen) -{ - deflate_state *s; - uLong complen, wraplen; - Bytef *str; - - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; - - /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) - return complen + 6; - - /* compute wrapper length */ - s = strm->state; - switch (s->wrap) { - case 0: /* raw deflate */ - wraplen = 0; - break; - case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); - break; - case 2: /* gzip wrapper */ - wraplen = 18; - if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ - if (s->gzhead->extra != Z_NULL) - wraplen += 2 + s->gzhead->extra_len; - str = s->gzhead->name; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - str = s->gzhead->comment; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - if (s->gzhead->hcrc) - wraplen += 2; - } - break; - default: /* for compiler happiness */ - wraplen = 6; - } - - /* if not default parameters, return conservative bound */ - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; - - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13 - 6 + wraplen; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB ( - deflate_state *s, - uInt b) -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending( - z_streamp strm) -{ - unsigned len; - deflate_state *s = strm->state; - - _tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) { - s->pending_out = s->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate ( - z_streamp strm, - int flush) -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - if (s->lookahead == 0) { - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else -#endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd ( - z_streamp strm) -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy ( - z_streamp dest, - z_streamp source) -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif /* MAXSEG_64K */ -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf( - z_streamp strm, - Bytef *buf, - unsigned size) -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } -#endif - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init ( - deflate_state *s) -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif -} - -#ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match( - deflate_state *s, - IPos cur_match) /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} -#endif /* ASMV */ - -#else /* FASTEST */ - -/* --------------------------------------------------------------------------- - * Optimized version for FASTEST only - */ -local uInt longest_match( - deflate_state *s, - IPos cur_match) /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#endif /* FASTEST */ - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match( - deflate_state *s, - IPos start, IPos match, - int length) -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window( - deflate_state *s) -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - UPDATE_HASH(s, s->ins_h, s->window[str + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - while (s->insert) { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, last) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (last)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, last) { \ - FLUSH_BLOCK_ONLY(s, last); \ - if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored( - deflate_state *s, - int flush) -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if ((long)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast( - deflate_state *s, - int flush) -{ - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -#ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow( - deflate_state *s, - int flush) -{ - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -#if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) -#endif - )) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} -#endif /* FASTEST */ - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -local block_state deflate_rle( - deflate_state *s, - int flush) -{ - int bflush; /* set if current block must be flushed */ - uInt prev; /* byte at distance one to match */ - Bytef *scan, *strend; /* scan goes up to strend for length of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s->match_length = 0; - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); - if (s->match_length > s->lookahead) - s->match_length = s->lookahead; - } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, s->match_length); - - _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - s->strstart += s->match_length; - s->match_length = 0; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -local block_state deflate_huff( - deflate_state *s, - int flush) -{ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s->match_length = 0; - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/third_party/zlib_v128/deflate.h b/third_party/zlib_v128/deflate.h deleted file mode 100644 index ce0299edd19168b97e38667479bd1b5e769a63d0..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/deflate.h +++ /dev/null @@ -1,346 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define Buf_size 16 -/* size of bit buffer in bi_buf */ - -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* can only be DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - uInt insert; /* bytes at end of window left to insert */ - -#ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - ulg high_water; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -#define WIN_INIT MAX_MATCH -/* Number of bytes after end of data in window to initialize in order to avoid - memory checker errors from longest match routines */ - - /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch ZLIB_INTERNAL _length_code[]; - extern uch ZLIB_INTERNAL _dist_code[]; -#else - extern const uch ZLIB_INTERNAL _length_code[]; - extern const uch ZLIB_INTERNAL _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif /* DEFLATE_H */ diff --git a/third_party/zlib_v128/gzclose.c b/third_party/zlib_v128/gzclose.c deleted file mode 100644 index 0f010b84c88c06fec096fa273f9b9681c2235517..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/gzclose.c +++ /dev/null @@ -1,25 +0,0 @@ -/* gzclose.c -- zlib gzclose() function - * Copyright (C) 2004, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* gzclose() is in a separate file so that it is linked in only if it is used. - That way the other gzclose functions can be used instead to avoid linking in - unneeded compression or decompression routines. */ -int ZEXPORT gzclose( - gzFile file) -{ -#ifndef NO_GZCOMPRESS - gz_statep state; - - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); -#else - return gzclose_r(file); -#endif -} diff --git a/third_party/zlib_v128/gzguts.h b/third_party/zlib_v128/gzguts.h deleted file mode 100644 index e2c3b67eedefac214db5770135c74648054177f2..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/gzguts.h +++ /dev/null @@ -1,217 +0,0 @@ -/* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef _LARGEFILE64_SOURCE -# ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE 1 -# endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif -#endif - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include <stdio.h> -#include "zlib.h" -#ifdef STDC -# include <string.h> -# include <stdlib.h> -# include <limits.h> -#endif -#include <fcntl.h> - -#ifdef _WIN32 -# include <stddef.h> -#else -# include <unistd.h> -#endif - -#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) -# include <io.h> -#endif - -#ifdef WINAPI_FAMILY -# define open _open -# define read _read -# define write _write -# define close _close -#endif - -#ifdef NO_DEFLATE /* for compatibility with old definition */ -# define NO_GZCOMPRESS -#endif - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS -/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 -/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -# ifdef VMS -# define NO_vsnprintf -# endif -# ifdef __OS400__ -# define NO_vsnprintf -# endif -# ifdef __MVS__ -# define NO_vsnprintf -# endif -#endif - -/* unlike snprintf (which is required in C99, yet still not supported by - Microsoft more than a decade later!), _snprintf does not guarantee null - termination of the result -- however this is only used in gzlib.c where - the result is assured to fit in the space provided */ -#ifdef _MSC_VER -# define snprintf _snprintf -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -/* gz* functions always use library allocation functions */ -#ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); -#endif - -extern void* FXMEM_DefaultAlloc(size_t, int); -extern void FXMEM_DefaultFree(void*, int); - -#define malloc(size) FXMEM_DefaultAlloc(size, 0) -#define free(ptr) FXMEM_DefaultFree(ptr, 0) - -/* get errno and strerror definition */ -#if defined UNDER_CE -# include <windows.h> -# define zstrerror() gz_strwinerror((DWORD)GetLastError()) -#else -# ifndef NO_STRERROR -# include <errno.h> -# define zstrerror() strerror(errno) -# else -# define zstrerror() "stdio error (consult errno)" -# endif -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); -#endif - -/* default memLevel */ -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - -/* default i/o buffer size -- double this for output when reading (this and - twice this must be able to fit in an unsigned type) */ -#define GZBUFSIZE 8192 - -/* gzip modes, also provide a little integrity check on the passed structure */ -#define GZ_NONE 0 -#define GZ_READ 7247 -#define GZ_WRITE 31153 -#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ - -/* values for gz_state how */ -#define LOOK 0 /* look for a gzip header */ -#define COPY 1 /* copy input directly */ -#define GZIP 2 /* decompress a gzip stream */ - -/* internal gzip file state data structure */ -typedef struct { - /* exposed contents for gzgetc() macro */ - struct gzFile_s x; /* "x" for exposed */ - /* x.have: number of bytes available at x.next */ - /* x.next: next output data to deliver or write */ - /* x.pos: current position in uncompressed data */ - /* used for both reading and writing */ - int mode; /* see gzip modes above */ - int fd; /* file descriptor */ - char *path; /* path or fd for error messages */ - unsigned size; /* buffer size, zero if not allocated yet */ - unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ - unsigned char *out; /* output buffer (double-sized when reading) */ - int direct; /* 0 if processing gzip, 1 if transparent */ - /* just for reading */ - int how; /* 0: get header, 1: copy, 2: decompress */ - z_off64_t start; /* where the gzip data started, for rewinding */ - int eof; /* true if end of input file reached */ - int past; /* true if read requested past end */ - /* just for writing */ - int level; /* compression level */ - int strategy; /* compression strategy */ - /* seek request */ - z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ - /* error information */ - int err; /* error code */ - char *msg; /* error message */ - /* zlib inflate or deflate stream */ - z_stream strm; /* stream structure in-place (not a pointer) */ -} gz_state; -typedef gz_state FAR *gz_statep; - -/* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); -#if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); -#endif - -/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t - value -- needed when comparing unsigned to z_off64_t, which is signed - (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif diff --git a/third_party/zlib_v128/gzlib.c b/third_party/zlib_v128/gzlib.c deleted file mode 100644 index 68b176478d24ae93727d0a6584b792e5dd21b30e..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/gzlib.c +++ /dev/null @@ -1,634 +0,0 @@ -/* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -#if defined(_WIN32) && !defined(__BORLANDC__) -# define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define LSEEK lseek64 -#else -# define LSEEK lseek -#endif -#endif - -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const void *, int, const char *)); - -#if defined UNDER_CE - -/* Map the Windows error number in ERROR to a locale-dependent error message - string and return a pointer to it. Typically, the values for ERROR come - from GetLastError. - - The string pointed to shall not be modified by the application, but may be - overwritten by a subsequent call to gz_strwinerror - - The gz_strwinerror function does not change the current setting of - GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror ( - DWORD error) -{ - static char buf[1024]; - - wchar_t *msgbuf; - DWORD lasterr = GetLastError(); - DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - error, - 0, /* Default language */ - (LPVOID)&msgbuf, - 0, - NULL); - if (chars != 0) { - /* If there is an \r\n appended, zap it. */ - if (chars >= 2 - && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { - chars -= 2; - msgbuf[chars] = 0; - } - - if (chars > sizeof (buf) - 1) { - chars = sizeof (buf) - 1; - msgbuf[chars] = 0; - } - - wcstombs(buf, msgbuf, chars + 1); - LocalFree(msgbuf); - } - else { - sprintf(buf, "unknown win32 error (%ld)", error); - } - - SetLastError(lasterr); - return buf; -} - -#endif /* UNDER_CE */ - -/* Reset gzip file state */ -local void gz_reset( - gz_statep state) -{ - state->x.have = 0; /* no output data available */ - if (state->mode == GZ_READ) { /* for reading ... */ - state->eof = 0; /* not at end of file */ - state->past = 0; /* have not read past end yet */ - state->how = LOOK; /* look for gzip header */ - } - state->seek = 0; /* no seek request pending */ - gz_error(state, Z_OK, NULL); /* clear error */ - state->x.pos = 0; /* no uncompressed data yet */ - state->strm.avail_in = 0; /* no input data yet */ -} - -/* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open( - const void *path, - int fd, - const char *mode) -{ - gz_statep state; - size_t len; - int oflag; -#ifdef O_CLOEXEC - int cloexec = 0; -#endif -#ifdef O_EXCL - int exclusive = 0; -#endif - - /* check input */ - if (path == NULL) - return NULL; - - /* allocate gzFile structure to return */ - state = (gz_statep)malloc(sizeof(gz_state)); - if (state == NULL) - return NULL; - state->size = 0; /* no buffers allocated yet */ - state->want = GZBUFSIZE; /* requested buffer size */ - state->msg = NULL; /* no error message yet */ - - /* interpret mode */ - state->mode = GZ_NONE; - state->level = Z_DEFAULT_COMPRESSION; - state->strategy = Z_DEFAULT_STRATEGY; - state->direct = 0; - while (*mode) { - if (*mode >= '0' && *mode <= '9') - state->level = *mode - '0'; - else - switch (*mode) { - case 'r': - state->mode = GZ_READ; - break; -#ifndef NO_GZCOMPRESS - case 'w': - state->mode = GZ_WRITE; - break; - case 'a': - state->mode = GZ_APPEND; - break; -#endif - case '+': /* can't read and write at the same time */ - free(state); - return NULL; - case 'b': /* ignore -- will request binary anyway */ - break; -#ifdef O_CLOEXEC - case 'e': - cloexec = 1; - break; -#endif -#ifdef O_EXCL - case 'x': - exclusive = 1; - break; -#endif - case 'f': - state->strategy = Z_FILTERED; - break; - case 'h': - state->strategy = Z_HUFFMAN_ONLY; - break; - case 'R': - state->strategy = Z_RLE; - break; - case 'F': - state->strategy = Z_FIXED; - break; - case 'T': - state->direct = 1; - break; - default: /* could consider as an error, but just ignore */ - ; - } - mode++; - } - - /* must provide an "r", "w", or "a" */ - if (state->mode == GZ_NONE) { - free(state); - return NULL; - } - - /* can't force transparent read */ - if (state->mode == GZ_READ) { - if (state->direct) { - free(state); - return NULL; - } - state->direct = 1; /* for empty file */ - } - - /* save the path name for error messages */ -#ifdef _WIN32 - if (fd == -2) { - len = wcstombs(NULL, path, 0); - if (len == (size_t)-1) - len = 0; - } - else -#endif - len = strlen((const char *)path); - state->path = (char *)malloc(len + 1); - if (state->path == NULL) { - free(state); - return NULL; - } -#ifdef _WIN32 - if (fd == -2) - if (len) - wcstombs(state->path, path, len + 1); - else - *(state->path) = 0; - else -#endif -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->path, len + 1, "%s", (const char *)path); -#else - strcpy(state->path, path); -#endif - - /* compute the flags for open() */ - oflag = -#ifdef O_LARGEFILE - O_LARGEFILE | -#endif -#ifdef O_BINARY - O_BINARY | -#endif -#ifdef O_CLOEXEC - (cloexec ? O_CLOEXEC : 0) | -#endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | -#ifdef O_EXCL - (exclusive ? O_EXCL : 0) | -#endif - (state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))); - - /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( -#ifdef _WIN32 - fd == -2 ? _wopen(path, oflag, 0666) : -#endif - open((const char *)path, oflag, 0666)); - if (state->fd == -1) { - free(state->path); - free(state); - return NULL; - } - if (state->mode == GZ_APPEND) - state->mode = GZ_WRITE; /* simplify later checks */ - - /* save the current position for rewinding (only if reading) */ - if (state->mode == GZ_READ) { - state->start = LSEEK(state->fd, 0, SEEK_CUR); - if (state->start == -1) state->start = 0; - } - - /* initialize stream */ - gz_reset(state); - - /* return stream */ - return (gzFile)state; -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen( - const char *path, - const char *mode) -{ - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64( - const char *path, - const char *mode) -{ - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen( - int fd, - const char *mode) -{ - char *path; /* identifier for error messages */ - gzFile gz; - - if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) - return NULL; -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */ -#else - sprintf(path, "<fd:%d>", fd); /* for debugging */ -#endif - gz = gz_open(path, fd, mode); - free(path); - return gz; -} - -/* -- see zlib.h -- */ -#ifdef _WIN32 -gzFile ZEXPORT gzopen_w( - const wchar_t *path, - const char *mode) -{ - return gz_open(path, -2, mode); -} -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzbuffer( - gzFile file, - unsigned size) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* make sure we haven't already allocated memory */ - if (state->size != 0) - return -1; - - /* check and set requested size */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ - state->want = size; - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzrewind( - gzFile file) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* back up and start over */ - if (LSEEK(state->fd, state->start, SEEK_SET) == -1) - return -1; - gz_reset(state); - return 0; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64( - gzFile file, - z_off64_t offset, - int whence) -{ - unsigned n; - z_off64_t ret; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* check that there's no error */ - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* can only seek from start or relative to current position */ - if (whence != SEEK_SET && whence != SEEK_CUR) - return -1; - - /* normalize offset to a SEEK_CUR specification */ - if (whence == SEEK_SET) - offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; - - /* if within raw area while reading, just go there */ - if (state->mode == GZ_READ && state->how == COPY && - state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); - if (ret == -1) - return -1; - state->x.have = 0; - state->eof = 0; - state->past = 0; - state->seek = 0; - gz_error(state, Z_OK, NULL); - state->strm.avail_in = 0; - state->x.pos += offset; - return state->x.pos; - } - - /* calculate skip amount, rewinding if needed for back seek when reading */ - if (offset < 0) { - if (state->mode != GZ_READ) /* writing -- can't go backwards */ - return -1; - offset += state->x.pos; - if (offset < 0) /* before start of file! */ - return -1; - if (gzrewind(file) == -1) /* rewind, then skip to offset */ - return -1; - } - - /* if reading, skip what's in output buffer (one less gzgetc() check) */ - if (state->mode == GZ_READ) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? - (unsigned)offset : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - offset -= n; - } - - /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } - return state->x.pos + offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek( - gzFile file, - z_off_t offset, - int whence) -{ - z_off64_t ret; - - ret = gzseek64(file, (z_off64_t)offset, whence); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64( - gzFile file) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gztell( - gzFile file) -{ - z_off64_t ret; - - ret = gztell64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64( - gzFile file) -{ - z_off64_t offset; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* compute and return effective offset in file */ - offset = LSEEK(state->fd, 0, SEEK_CUR); - if (offset == -1) - return -1; - if (state->mode == GZ_READ) /* reading */ - offset -= state->strm.avail_in; /* don't count buffered input */ - return offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset( - gzFile file) -{ - z_off64_t ret; - - ret = gzoffset64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzeof( - gzFile file) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return 0; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return 0; - - /* return end-of-file state */ - return state->mode == GZ_READ ? state->past : 0; -} - -/* -- see zlib.h -- */ -const char * ZEXPORT gzerror( - gzFile file, - int *errnum) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return NULL; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return NULL; - - /* return error information */ - if (errnum != NULL) - *errnum = state->err; - return state->err == Z_MEM_ERROR ? "out of memory" : - (state->msg == NULL ? "" : state->msg); -} - -/* -- see zlib.h -- */ -void ZEXPORT gzclearerr( - gzFile file) -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return; - - /* clear error and end-of-file */ - if (state->mode == GZ_READ) { - state->eof = 0; - state->past = 0; - } - gz_error(state, Z_OK, NULL); -} - -/* Create an error message in allocated memory and set state->err and - state->msg accordingly. Free any previous error message already there. Do - not try to free or allocate space if the error is Z_MEM_ERROR (out of - memory). Simply save the error message as a static string. If there is an - allocation failure constructing the error message, then convert the error to - out of memory. */ -void ZLIB_INTERNAL gz_error( - gz_statep state, - int err, - const char *msg) -{ - /* free previously allocated message and clear */ - if (state->msg != NULL) { - if (state->err != Z_MEM_ERROR) - free(state->msg); - state->msg = NULL; - } - - /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ - if (err != Z_OK && err != Z_BUF_ERROR) - state->x.have = 0; - - /* set error code, and if no message, then done */ - state->err = err; - if (msg == NULL) - return; - - /* for an out of memory error, return literal string when requested */ - if (err == Z_MEM_ERROR) - return; - - /* construct error message with path */ - if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == - NULL) { - state->err = Z_MEM_ERROR; - return; - } -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, - "%s%s%s", state->path, ": ", msg); -#else - strcpy(state->msg, state->path); - strcat(state->msg, ": "); - strcat(state->msg, msg); -#endif - return; -} - -#ifndef INT_MAX -/* portably return maximum value for an int (when limits.h presumed not - available) -- we need to do this to cover cases where 2's complement not - used, since C standard permits 1's complement and sign-bit representations, - otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ - unsigned p, q; - - p = 1; - do { - q = p; - p <<= 1; - p++; - } while (p > q); - return q >> 1; -} -#endif diff --git a/third_party/zlib_v128/gzread.c b/third_party/zlib_v128/gzread.c deleted file mode 100644 index f162a32f102e08a1aa163cba1af4286dd57d6ac7..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/gzread.c +++ /dev/null @@ -1,594 +0,0 @@ -/* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_look OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_fetch OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); - -/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from - state->fd, and update state->eof, state->err, and state->msg as appropriate. - This function needs to loop on read(), since read() is not guaranteed to - read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load( - gz_statep state, - unsigned char *buf, - unsigned len, - unsigned *have) -{ - int ret; - - *have = 0; - do { - ret = read(state->fd, buf + *have, len - *have); - if (ret <= 0) - break; - *have += ret; - } while (*have < len); - if (ret < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (ret == 0) - state->eof = 1; - return 0; -} - -/* Load up input buffer and set eof flag if last data loaded -- return -1 on - error, 0 otherwise. Note that the eof flag is set when the end of the input - file is reached, even though there may be unused data in the buffer. Once - that data has been used, no more attempts will be made to read the file. - If strm->avail_in != 0, then the current data is moved to the beginning of - the input buffer, and then the remainder of the buffer is loaded with the - available data from the input file. */ -local int gz_avail( - gz_statep state) -{ - unsigned got; - z_streamp strm = &(state->strm); - - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - if (state->eof == 0) { - if (strm->avail_in) { /* copy what's there to the start */ - unsigned char *p = state->in; - unsigned const char *q = strm->next_in; - unsigned n = strm->avail_in; - do { - *p++ = *q++; - } while (--n); - } - if (gz_load(state, state->in + strm->avail_in, - state->size - strm->avail_in, &got) == -1) - return -1; - strm->avail_in += got; - strm->next_in = state->in; - } - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. - If this is the first time in, allocate required memory. state->how will be - left unchanged if there is no more input data available, will be set to COPY - if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression. If direct copying, then leftover input - data from the input buffer will be copied to the output buffer. In that - case, all further file reads will be directly to either the output buffer or - a user buffer. If decompressing, the inflate state will be initialized. - gz_look() will return 0 on success or -1 on failure. */ -local int gz_look( - gz_statep state) -{ - z_streamp strm = &(state->strm); - - /* allocate read buffers and inflate memory */ - if (state->size == 0) { - /* allocate buffers */ - state->in = (unsigned char *)malloc(state->want); - state->out = (unsigned char *)malloc(state->want << 1); - if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - state->size = state->want; - - /* allocate inflate memory */ - state->strm.zalloc = Z_NULL; - state->strm.zfree = Z_NULL; - state->strm.opaque = Z_NULL; - state->strm.avail_in = 0; - state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ - free(state->out); - free(state->in); - state->size = 0; - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* get at least the magic bytes in the input buffer */ - if (strm->avail_in < 2) { - if (gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) - return 0; - } - - /* look for gzip magic bytes -- if there, do gzip decoding (note: there is - a logical dilemma here when considering the case of a partially written - gzip file, to wit, if a single 31 byte is written, then we cannot tell - whether this is a single-byte file, or just a partially written gzip - file -- for here we assume that if a gzip file is being written, then - the header will be written in a single operation, so that reading a - single byte is sufficient indication that it is not a gzip file) */ - if (strm->avail_in > 1 && - strm->next_in[0] == 31 && strm->next_in[1] == 139) { - inflateReset(strm); - state->how = GZIP; - state->direct = 0; - return 0; - } - - /* no gzip header -- if we were decoding gzip before, then this is trailing - garbage. Ignore the trailing garbage and finish. */ - if (state->direct == 0) { - strm->avail_in = 0; - state->eof = 1; - state->x.have = 0; - return 0; - } - - /* doing raw i/o, copy any leftover input to output -- this assumes that - the output buffer is larger than the input buffer, which also assures - space for gzungetc() */ - state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } - state->how = COPY; - state->direct = 1; - return 0; -} - -/* Decompress from input to the provided next_out and avail_out in the state. - On return, state->x.have and state->x.next point to the just decompressed - data. If the gzip stream completes, state->how is reset to LOOK to look for - the next gzip stream or raw data, once state->x.have is depleted. Returns 0 - on success, -1 on failure. */ -local int gz_decomp( - gz_statep state) -{ - int ret = Z_OK; - unsigned had; - z_streamp strm = &(state->strm); - - /* fill output buffer up to end of deflate stream */ - had = strm->avail_out; - do { - /* get more input for inflate() */ - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) { - gz_error(state, Z_BUF_ERROR, "unexpected end of file"); - break; - } - - /* decompress and handle errors */ - ret = inflate(strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { - gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); - return -1; - } - if (ret == Z_MEM_ERROR) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ - gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); - return -1; - } - } while (strm->avail_out && ret != Z_STREAM_END); - - /* update available output */ - state->x.have = had - strm->avail_out; - state->x.next = strm->next_out - state->x.have; - - /* if the gzip stream completed successfully, look for another */ - if (ret == Z_STREAM_END) - state->how = LOOK; - - /* good decompression */ - return 0; -} - -/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. - Data is either copied from the input file or decompressed from the input - file depending on state->how. If state->how is LOOK, then a gzip header is - looked for to determine whether to copy or decompress. Returns -1 on error, - otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the - end of the input file has been reached and all data has been processed. */ -local int gz_fetch( - gz_statep state) -{ - z_streamp strm = &(state->strm); - - do { - switch(state->how) { - case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ - if (gz_look(state) == -1) - return -1; - if (state->how == LOOK) - return 0; - break; - case COPY: /* -> COPY */ - if (gz_load(state, state->out, state->size << 1, &(state->x.have)) - == -1) - return -1; - state->x.next = state->out; - return 0; - case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } - } while (state->x.have == 0 && (!state->eof || strm->avail_in)); - return 0; -} - -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip( - gz_statep state, - z_off64_t len) -{ - unsigned n; - - /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) - /* skip over whatever is in output buffer */ - if (state->x.have) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? - (unsigned)len : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - len -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) - break; - - /* need more data to skip -- load up output buffer */ - else { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - } - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzread( - gzFile file, - voidp buf, - unsigned len) -{ - unsigned got, n; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return -1; - } - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* get len bytes to buf, or less than len if at the end */ - got = 0; - do { - /* first just try copying data from the output buffer */ - if (state->x.have) { - n = state->x.have > len ? len : state->x.have; - memcpy(buf, state->x.next, n); - state->x.next += n; - state->x.have -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) { - state->past = 1; /* tried to read past end */ - break; - } - - /* need output data -- for small len or new stream load up our output - buffer */ - else if (state->how == LOOK || len < (state->size << 1)) { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - continue; /* no progress yet -- go back to copy above */ - /* the copy above assures that we will leave with space in the - output buffer, allowing at least one gzungetc() to succeed */ - } - - /* large len -- read directly into user buffer */ - else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, len, &n) == -1) - return -1; - } - - /* large len -- decompress directly into user buffer */ - else { /* state->how == GZIP */ - strm->avail_out = len; - strm->next_out = (unsigned char *)buf; - if (gz_decomp(state) == -1) - return -1; - n = state->x.have; - state->x.have = 0; - } - - /* update progress */ - len -= n; - buf = (char *)buf + n; - got += n; - state->x.pos += n; - } while (len); - - /* return number of bytes read into user buffer (will fit in int) */ - return (int)got; -} - -/* -- see zlib.h -- */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -#else -# undef gzgetc -#endif -int ZEXPORT gzgetc( - gzFile file) -{ - int ret; - unsigned char buf[1]; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* try output buffer (no need to check for skip request) */ - if (state->x.have) { - state->x.have--; - state->x.pos++; - return *(state->x.next)++; - } - - /* nothing there -- try gzread() */ - ret = gzread(file, buf, 1); - return ret < 1 ? -1 : buf[0]; -} - -int ZEXPORT gzgetc_( -gzFile file) -{ - return gzgetc(file); -} - -/* -- see zlib.h -- */ -int ZEXPORT gzungetc( - int c, - gzFile file) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* can't push EOF */ - if (c < 0) - return -1; - - /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->x.have == 0) { - state->x.have = 1; - state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = c; - state->x.pos--; - state->past = 0; - return c; - } - - /* if no room, give up (must have already done a gzungetc()) */ - if (state->x.have == (state->size << 1)) { - gz_error(state, Z_DATA_ERROR, "out of room to push characters"); - return -1; - } - - /* slide output data if needed and insert byte before existing data */ - if (state->x.next == state->out) { - unsigned char *src = state->out + state->x.have; - unsigned char *dest = state->out + (state->size << 1); - while (src > state->out) - *--dest = *--src; - state->x.next = dest; - } - state->x.have++; - state->x.next--; - state->x.next[0] = c; - state->x.pos--; - state->past = 0; - return c; -} - -/* -- see zlib.h -- */ -char * ZEXPORT gzgets( - gzFile file, - char *buf, - int len) -{ - unsigned left, n; - char *str; - unsigned char *eol; - gz_statep state; - - /* check parameters and get internal structure */ - if (file == NULL || buf == NULL || len < 1) - return NULL; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return NULL; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } - - /* copy output bytes up to new line or len - 1, whichever comes first -- - append a terminating zero to the string (we don't check for a zero in - the contents, let the user worry about that) */ - str = buf; - left = (unsigned)len - 1; - if (left) do { - /* assure that something is in the output buffer */ - if (state->x.have == 0 && gz_fetch(state) == -1) - return NULL; /* error */ - if (state->x.have == 0) { /* end of file */ - state->past = 1; /* read past end */ - break; /* return what we have */ - } - - /* look for end-of-line in current output buffer */ - n = state->x.have > left ? left : state->x.have; - eol = (unsigned char *)memchr(state->x.next, '\n', n); - if (eol != NULL) - n = (unsigned)(eol - state->x.next) + 1; - - /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->x.next, n); - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - left -= n; - buf += n; - } while (left && eol == NULL); - - /* return terminated string, or if nothing, end of file */ - if (buf == str) - return NULL; - buf[0] = 0; - return str; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzdirect( - gzFile file) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* if the state is not known, but we can find out, then do so (this is - mainly for right after a gzopen() or gzdopen()) */ - if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) - (void)gz_look(state); - - /* return 1 if transparent, 0 if processing a gzip stream */ - return state->direct; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_r( - gzFile file) -{ - int ret, err; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're reading */ - if (state->mode != GZ_READ) - return Z_STREAM_ERROR; - - /* free memory and close file */ - if (state->size) { - inflateEnd(&(state->strm)); - free(state->out); - free(state->in); - } - err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; - gz_error(state, Z_OK, NULL); - free(state->path); - ret = close(state->fd); - free(state); - return ret ? Z_ERRNO : err; -} diff --git a/third_party/zlib_v128/gzwrite.c b/third_party/zlib_v128/gzwrite.c deleted file mode 100644 index 161070866fd3aee2e9a25574998af81689c0561e..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/gzwrite.c +++ /dev/null @@ -1,576 +0,0 @@ -/* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); - -/* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on failure or 0 on success. */ -local int gz_init( - gz_statep state) -{ - int ret; - z_streamp strm = &(state->strm); - - /* allocate input buffer */ - state->in = (unsigned char *)malloc(state->want); - if (state->in == NULL) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* only need output buffer and deflate state if compressing */ - if (!state->direct) { - /* allocate output buffer */ - state->out = (unsigned char *)malloc(state->want); - if (state->out == NULL) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); - if (ret != Z_OK) { - free(state->out); - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* mark state as initialized */ - state->size = state->want; - - /* initialize write buffer if compressing */ - if (!state->direct) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = strm->next_out; - } - return 0; -} - -/* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file, otherwise 0. - flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. If gz->direct - is true, then simply write to the output file without compressing, and - ignore flush. */ -local int gz_comp( - gz_statep state, - int flush) -{ - int ret, got; - unsigned have; - z_streamp strm = &(state->strm); - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return -1; - - /* write directly if requested */ - if (state->direct) { - got = write(state->fd, strm->next_in, strm->avail_in); - if (got < 0 || (unsigned)got != strm->avail_in) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - strm->avail_in = 0; - return 0; - } - - /* run deflate() on provided input until it produces no more output */ - ret = Z_OK; - do { - /* write out current buffer contents if full, or if flushing, but if - doing Z_FINISH then don't write until we get to Z_STREAM_END */ - if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && - (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = write(state->fd, state->x.next, have)) < 0 || - (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (strm->avail_out == 0) { - strm->avail_out = state->size; - strm->next_out = state->out; - } - state->x.next = strm->next_out; - } - - /* compress */ - have = strm->avail_out; - ret = deflate(strm, flush); - if (ret == Z_STREAM_ERROR) { - gz_error(state, Z_STREAM_ERROR, - "internal error: deflate stream corrupt"); - return -1; - } - have -= strm->avail_out; - } while (have); - - /* if that completed a deflate stream, allow another to start */ - if (flush == Z_FINISH) - deflateReset(strm); - - /* all done, no errors */ - return 0; -} - -/* Compress len zeros to output. Return -1 on error, 0 on success. */ -local int gz_zero( - gz_statep state, - z_off64_t len) -{ - int first; - unsigned n; - z_streamp strm = &(state->strm); - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - - /* compress len zeros (len guaranteed > 0) */ - first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? - (unsigned)len : state->size; - if (first) { - memset(state->in, 0, n); - first = 0; - } - strm->avail_in = n; - strm->next_in = state->in; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - len -= n; - } - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzwrite( - gzFile file, - voidpc buf, - unsigned len) -{ - unsigned put = len; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* for small len, copy to input buffer, otherwise compress directly */ - if (len < state->size) { - /* copy to input buffer, compress when full */ - do { - unsigned have, copy; - - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - copy = state->size - have; - if (copy > len) - copy = len; - memcpy(state->in + have, buf, copy); - strm->avail_in += copy; - state->x.pos += copy; - buf = (const char *)buf + copy; - len -= copy; - if (len && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } while (len); - } - else { - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* directly compress user buffer to file */ - strm->avail_in = len; - strm->next_in = (z_const Bytef *)buf; - state->x.pos += len; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } - - /* input was all buffered or compressed (put will fit in int) */ - return (int)put; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputc( - gzFile file, - int c) -{ - unsigned have; - unsigned char buf[1]; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* try writing to input buffer for speed (state->size == 0 if buffer not - initialized) */ - if (state->size) { - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - if (have < state->size) { - state->in[have] = c; - strm->avail_in++; - state->x.pos++; - return c & 0xff; - } - } - - /* no room in buffer or not initialized, use gz_write() */ - buf[0] = c; - if (gzwrite(file, buf, 1) != 1) - return -1; - return c & 0xff; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputs( - gzFile file, - const char *str) -{ - int ret; - unsigned len; - - /* write string */ - len = (unsigned)strlen(str); - ret = gzwrite(file, str, len); - return ret == 0 && len != 0 ? -1 : ret; -} - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -#include <stdarg.h> - -/* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) -{ - int size, len; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf((char *)(state->in), format, va); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; -# else - len = vsprintf((char *)(state->in), format, va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf((char *)(state->in), size, format, va); - len = strlen((char *)(state->in)); -# else - len = vsnprintf((char *)(state->in), size, format, va); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) - return 0; - - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; - state->x.pos += len; - return len; -} - -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) -{ - va_list va; - int ret; - - va_start(va, format); - ret = gzvprintf(file, format, va); - va_end(va); - return ret; -} - -#else /* !STDC && !Z_HAVE_STDARG_H */ - -/* -- see zlib.h -- */ -int ZEXPORTVA gzprintf ( - gzFile file, - const char *format, - int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, - int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20) -{ - int size, len; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that can really pass pointer in ints */ - if (sizeof(int) != sizeof(void *)) - return 0; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; -# else - len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen((char *)(state->in)); -# else - len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, - a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, - a19, a20); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) - return 0; - - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; - state->x.pos += len; - return len; -} - -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzflush( - gzFile file, - int flush) -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* check flush parameter */ - if (flush < 0 || flush > Z_FINISH) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* compress remaining data with requested flush */ - gz_comp(state, flush); - return state->err; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzsetparams( - gzFile file, - int level, - int strategy) -{ - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* if no change is requested, then do nothing */ - if (level == state->level && strategy == state->strategy) - return Z_OK; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* change compression parameters for subsequent input */ - if (state->size) { - /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) - return state->err; - deflateParams(strm, level, strategy); - } - state->level = level; - state->strategy = strategy; - return Z_OK; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_w( - gzFile file) -{ - int ret = Z_OK; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're writing */ - if (state->mode != GZ_WRITE) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - ret = state->err; - } - - /* flush, free memory, and close file */ - if (gz_comp(state, Z_FINISH) == -1) - ret = state->err; - if (state->size) { - if (!state->direct) { - (void)deflateEnd(&(state->strm)); - free(state->out); - } - free(state->in); - } - gz_error(state, Z_OK, NULL); - free(state->path); - if (close(state->fd) == -1) - ret = Z_ERRNO; - free(state); - return ret; -} diff --git a/third_party/zlib_v128/infback.c b/third_party/zlib_v128/infback.c deleted file mode 100644 index 157bbd64e96427b00c6da12adc79f5b69f4412e7..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/infback.c +++ /dev/null @@ -1,640 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2011 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_( -z_streamp strm, -int windowBits, -unsigned char FAR *window, -const char *version, -int stream_size) -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->wnext = 0; - state->whave = 0; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables( -struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack( -z_streamp strm, -in_func in, -void FAR *in_desc, -out_func out, -void FAR *out_desc) -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - state->length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd( -z_streamp strm) -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/third_party/zlib_v128/inffast.c b/third_party/zlib_v128/inffast.c deleted file mode 100644 index 3fcffae4981b19ba4cb498076ab6d0ad2d4876c3..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inffast.c +++ /dev/null @@ -1,340 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ -#else -# define OFF 1 -# define PUP(a) *++(a) -#endif - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void ZLIB_INTERNAL inflate_fast( -z_streamp strm, -unsigned start) /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *in; /* local strm->next_in */ - z_const unsigned char FAR *last; /* have enough input while in < last */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code here; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; - last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - here = lcode[hold & lmask]; - dolen: - op = (unsigned)(here.bits); - hold >>= op; - bits -= op; - op = (unsigned)(here.op); - if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - PUP(out) = (unsigned char)(here.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(here.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - here = dcode[hold & dmask]; - dodist: - op = (unsigned)(here.bits); - hold >>= op; - bits -= op; - op = (unsigned)(here.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - strm->msg = - (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - PUP(out) = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - PUP(out) = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - PUP(out) = PUP(from); - } while (--len); - continue; - } -#endif - } - from = window - OFF; - if (wnext == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = window - OFF; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } while (len > 2); - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and wnext == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/third_party/zlib_v128/inffast.h b/third_party/zlib_v128/inffast.h deleted file mode 100644 index e5c1aa4ca8cd5244423680865609c71ab68f9ab6..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/third_party/zlib_v128/inffixed.h b/third_party/zlib_v128/inffixed.h deleted file mode 100644 index d6283277694802ce7938f537f12990d6eead4924..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* WARNING: this file should *not* be used by applications. - It is part of the implementation of this library and is - subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/third_party/zlib_v128/inflate.c b/third_party/zlib_v128/inflate.c deleted file mode 100644 index bc5e448daf18c0971911cda71d110be0fe460ca4..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inflate.c +++ /dev/null @@ -1,1513 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common wnext == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, - unsigned copy)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, - unsigned len)); - -int ZEXPORT inflateResetKeep( -z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - if (state->wrap) /* to support ill-conceived Java test suite */ - strm->adler = state->wrap & 1; - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - state->sane = 1; - state->back = -1; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflateReset( -z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; - return inflateResetKeep(strm); -} - -int ZEXPORT inflateReset2( -z_streamp strm, -int windowBits) -{ - int wrap; - struct inflate_state FAR *state; - - /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; -#ifdef GUNZIP - if (windowBits < 48) - windowBits &= 15; -#endif - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) - return Z_STREAM_ERROR; - if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { - ZFREE(strm, state->window); - state->window = Z_NULL; - } - - /* update state and reset the rest of it */ - state->wrap = wrap; - state->wbits = (unsigned)windowBits; - return inflateReset(strm); -} - -int ZEXPORT inflateInit2_( -z_streamp strm, -int windowBits, -const char *version, -int stream_size) -{ - int ret; - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->window = Z_NULL; - ret = inflateReset2(strm, windowBits); - if (ret != Z_OK) { - ZFREE(strm, state); - strm->state = Z_NULL; - } - return ret; -} - -int ZEXPORT inflateInit_( -z_streamp strm, -const char *version, -int stream_size) -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -int ZEXPORT inflatePrime( -z_streamp strm, -int bits, -int value) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits < 0) { - state->hold = 0; - state->bits = 0; - return Z_OK; - } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables( -struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include <stdio.h> - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, - state.lencode[low].bits, state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow( -z_streamp strm, -const Bytef *end, -unsigned copy) -{ - struct inflate_state FAR *state; - unsigned dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->wnext = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { - zmemcpy(state->window, end - state->wsize, state->wsize); - state->wnext = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->wnext; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, end - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, end - copy, copy); - state->wnext = copy; - state->whave = state->wsize; - } - else { - state->wnext += dist; - if (state->wnext == state->wsize) state->wnext = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate( -z_streamp strm, -int flush) -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (state->wbits == 0) - state->wbits = len; - else if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = ZSWAP32(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN_; /* decode codes */ - if (flush == Z_TREES) { - DROPBITS(2); - goto inf_leave; - } - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY_; - if (flush == Z_TREES) goto inf_leave; - case COPY_: - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (const code FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN_; - if (flush == Z_TREES) goto inf_leave; - case LEN_: - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - if (state->mode == TYPE) - state->back = -1; - break; - } - state->back = 0; - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - state->length = (unsigned)here.val; - if ((int)(here.op) == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - state->mode = LIT; - break; - } - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->back = -1; - state->mode = TYPE; - break; - } - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(here.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->was = state->length; - state->mode = DIST; - case DIST: - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - state->extra = (unsigned)(here.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->whave) { - if (state->sane) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - Trace((stderr, "inflate.c too far\n")); - copy -= state->whave; - if (copy > state->length) copy = state->length; - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = 0; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; -#endif - } - if (copy > state->wnext) { - copy -= state->wnext; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->wnext - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if (( -#ifdef GUNZIP - state->flags ? hold : -#endif - ZSWAP32(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (out != strm->avail_out && state->mode < BAD && - (state->mode < CHECK || flush != Z_FINISH))) - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (state->wrap && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0) + - (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd( -z_streamp strm) -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateGetDictionary( -z_streamp strm, -Bytef *dictionary, -uInt *dictLength) -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* copy dictionary */ - if (state->whave && dictionary != Z_NULL) { - zmemcpy(dictionary, state->window + state->wnext, - state->whave - state->wnext); - zmemcpy(dictionary + state->whave - state->wnext, - state->window, state->wnext); - } - if (dictLength != Z_NULL) - *dictLength = state->whave; - return Z_OK; -} - -int ZEXPORT inflateSetDictionary( -z_streamp strm, -const Bytef *dictionary, -uInt dictLength) -{ - struct inflate_state FAR *state; - unsigned long dictid; - int ret; - - dictid = 0; - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary identifier */ - if (state->mode == DICT) { - dictid = adler32(0L, Z_NULL, 0); - dictid = adler32(dictid, dictionary, dictLength); - if (dictid != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); - if (ret) { - state->mode = MEM; - return Z_MEM_ERROR; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader( -z_streamp strm, -gz_headerp head) -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch( -unsigned FAR *have, -const unsigned char FAR *buf, -unsigned len) -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync( -z_streamp strm) -{ - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint( -z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy( -z_streamp dest, -z_streamp source) -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} - -int ZEXPORT inflateUndermine( -z_streamp strm, -int subvert) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - return Z_OK; -#else - state->sane = 1; - return Z_DATA_ERROR; -#endif -} - -long ZEXPORT inflateMark( -z_streamp strm) -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; - state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + - (state->mode == COPY ? state->length : - (state->mode == MATCH ? state->was - state->length : 0)); -} diff --git a/third_party/zlib_v128/inflate.h b/third_party/zlib_v128/inflate.h deleted file mode 100644 index 95f4986d400223bad542e5b34a7e6284a039425e..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inflate.h +++ /dev/null @@ -1,122 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY_, /* i/o: same as COPY below, but only first time in */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN_, /* i: same as LEN below, but only first time in */ - LEN, /* i: waiting for length/lit/eob code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to BAD or MEM on error -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) or (raw) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> - HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - (raw) -> TYPEDO - Read deflate blocks: - TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK - STORED -> COPY_ -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN_ - LEN_ -> LEN - Read deflate codes in fixed or dynamic block: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* state maintained between inflate() calls. Approximately 10K bytes. */ -struct inflate_state { - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ - int sane; /* if false, allow invalid distance too far */ - int back; /* bits back of last unprocessed length/lit */ - unsigned was; /* initial length of match */ -}; diff --git a/third_party/zlib_v128/inftrees.c b/third_party/zlib_v128/inftrees.c deleted file mode 100644 index 05ba1324f4f0454acb073b4775aadf81f9bd8f9b..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inftrees.c +++ /dev/null @@ -1,306 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2013 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int ZLIB_INTERNAL inflate_table( -codetype type, -unsigned short FAR *lens, -unsigned codes, -code FAR * FAR *table, -unsigned FAR *bits, -unsigned short FAR *work) -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code here; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)1; - here.val = (unsigned short)0; - *(*table)++ = here; /* make a table to force an error */ - *(*table)++ = here; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - here.op = (unsigned char)0; - here.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; - } - else { - here.op = (unsigned char)(32 + 64); /* end of block */ - here.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = here; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff != 0) { - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - next[huff] = here; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/third_party/zlib_v128/inftrees.h b/third_party/zlib_v128/inftrees.h deleted file mode 100644 index baa53a0b1a199ce6ea4c3f99d0306502ab4fab2c..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/inftrees.h +++ /dev/null @@ -1,62 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1444, which is the sum of 852 for literal/length codes and 592 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in inflate.c and infback.c. If the root table size is - changed, then these maximum sizes would be need to be recalculated and - updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 592 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/third_party/zlib_v128/trees.c b/third_party/zlib_v128/trees.c deleted file mode 100644 index e1fd952046af4e51b57ea0169791de97cc412bd1..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/trees.c +++ /dev/null @@ -1,1226 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2012 Jean-loup Gailly - * detect_data_type() function provided freely by Cosmin Truta, 2006 - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef DEBUG -# include <ctype.h> -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, const ct_data *ltree, - const ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits( - deflate_state *s, - int value, /* value to send */ - int length) /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (ush)value << s->bi_valid; - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= (ush)value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (ush)val << s->bi_valid;\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (ush)(value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG */ - - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ -#ifdef NO_INIT_GLOBAL_POINTERS - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; -#endif - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1<<extra_lbits[code]); n++) { - _length_code[length++] = (uch)code; - } - } - Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length-1] = (uch)code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<<extra_dbits[code]); n++) { - _dist_code[dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include <stdio.h> -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, - "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void ZLIB_INTERNAL _tr_init( - deflate_state *s) -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block( - deflate_state *s) -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap( - deflate_state *s, - ct_data *tree, /* the tree to restore */ - int k) /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen( - deflate_state *s, - tree_desc *desc) /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes ( - ct_data *tree, /* the tree to decorate */ - int max_code, /* largest code with non zero frequency */ - ushf *bl_count) /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, - "inconsistent bit counts"); - Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -local void build_tree( - deflate_state *s, - tree_desc *desc) /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree ( - deflate_state *s, - ct_data *tree, /* the tree to be scanned */ - int max_code) /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree ( - deflate_state *s, - ct_data *tree, /* the tree to be scanned */ - int max_code) /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree( - deflate_state *s) -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees( - deflate_state *s, - int lcodes, int dcodes, int blcodes) /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void ZLIB_INTERNAL _tr_stored_block( - deflate_state *s, - charf *buf, /* input block */ - ulg stored_len, /* length of input block */ - int last) /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) - */ -void ZLIB_INTERNAL _tr_flush_bits( - deflate_state *s) -{ - bi_flush(s); -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -void ZLIB_INTERNAL _tr_align( - deflate_state *s) -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void ZLIB_INTERNAL _tr_flush_block( - deflate_state *s, - charf *buf, /* input block, or NULL if too old */ - ulg stored_len, /* length of input block */ - int last) /* one if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (s->strm->data_type == Z_UNKNOWN) - s->strm->data_type = detect_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (const ct_data *)static_ltree, - (const ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (const ct_data *)s->dyn_ltree, - (const ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int ZLIB_INTERNAL _tr_tally ( - deflate_state *s, - unsigned dist, /* distance of matched string */ - unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block( - deflate_state *s, - const ct_data *ltree, /* literal tree */ - const ct_data *dtree) /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type( - deflate_state *s) -{ - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long black_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("white-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse( - unsigned code, /* the value to invert */ - int len) /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush( - deflate_state *s) -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup( - deflate_state *s) -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block( - deflate_state *s, - charf *buf, /* the input data */ - unsigned len, /* its length */ - int header) /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/third_party/zlib_v128/trees.h b/third_party/zlib_v128/trees.h deleted file mode 100644 index 8a09b5803aa6862a134e2bab8d2ca2fa092e5d8d..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/trees.h +++ /dev/null @@ -1,129 +0,0 @@ -/* GENERATED FILE */ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/third_party/zlib_v128/uncompr.c b/third_party/zlib_v128/uncompr.c deleted file mode 100644 index d3cb8fe1835424d6917cebd6d4c05d1a0aefc0a0..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/uncompr.c +++ /dev/null @@ -1,59 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ -int ZEXPORT uncompress ( - Bytef *dest, - uLongf *destLen, - const Bytef *source, - uLong sourceLen) -{ - z_stream stream; - int err; - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} diff --git a/third_party/zlib_v128/zconf.h b/third_party/zlib_v128/zconf.h deleted file mode 100644 index 5708a377e040c2c7b2e5f8c1c0be53d13282b093..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/zconf.h +++ /dev/null @@ -1,519 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include <windows.h> - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include <limits.h> -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#if 0 /* Sunliang.Liu 20100908 sync the config to the old revision, otherwise, evc compile failed. */ -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif -#endif /* 0 */ - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#if 0 /* Sunliang.Liu 20100908 sync the config to the old revision, otherwise, evc compile failed. */ -#ifdef STDC -# ifndef Z_SOLO -# include <sys/types.h> /* for off_t */ -# endif -#endif -#endif /* 0 */ - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include <stdarg.h> /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include <stddef.h> /* for wchar_t */ -# endif -#endif - -#if 0 /* Sunliang.Liu 20100908 sync the config to the old revision, otherwise, evc compile failed. */ -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif -#endif /* 0 */ - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -#if 0 /* Sunliang.Liu 20100908 sync the config to the old revision, otherwise, evc compile failed. */ -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include <unixio.h> /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif /* 0 */ -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/third_party/zlib_v128/zlib.h b/third_party/zlib_v128/zlib.h deleted file mode 100644 index 2d5812acf11a263a41b8deafc3bc4a6bb7543d28..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/zlib.h +++ /dev/null @@ -1,1839 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 - - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 - (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif - -#define deflate_copyright FPDFAPI_deflate_copyright -#define adler32 FPDFAPI_adler32 -#define compress2 FPDFAPI_compress2 -#define compress FPDFAPI_compress -#define compressBound FPDFAPI_compressBound -#define get_crc_table FPDFAPI_get_crc_table -#define crc32 FPDFAPI_crc32 -#define deflateInit_ FPDFAPI_deflateInit_ -#define deflateInit2_ FPDFAPI_deflateInit2_ -#define deflateSetDictionary FPDFAPI_deflateSetDictionary -#define deflateReset FPDFAPI_deflateReset -#define deflatePending FPDFAPI_deflatePending -#define deflatePrime FPDFAPI_deflatePrime -#define deflateParams FPDFAPI_deflateParams -#define deflateBound FPDFAPI_deflateBound -#define deflateSetHeader FPDFAPI_deflateSetHeader -#define deflateTune FPDFAPI_deflateTune -#define deflate FPDFAPI_deflate -#define deflateEnd FPDFAPI_deflateEnd -#define deflateCopy FPDFAPI_deflateCopy -#define inflateBackInit_ FPDFAPI_inflateBackInit_ -#define inflateBack FPDFAPI_inflateBack -#define inflateBackEnd FPDFAPI_inflateBackEnd -#define inflateReset FPDFAPI_inflateReset -#define inflateInit2_ FPDFAPI_inflateInit2_ -#define inflateInit_ FPDFAPI_inflateInit_ -#define inflate FPDFAPI_inflate -#define inflateEnd FPDFAPI_inflateEnd -#define inflateSetDictionary FPDFAPI_inflateSetDictionary -#define inflateSync FPDFAPI_inflateSync -#define inflateSyncPoint FPDFAPI_inflateSyncPoint -#define inflateCopy FPDFAPI_inflateCopy -#define uncompress FPDFAPI_uncompress -#define zlibVersion FPDFAPI_zlibVersion -#define zlibCompileFlags FPDFAPI_zlibCompileFlags -#define zError FPDFAPI_zError -#define z_errmsg FPDFAPI_z_errmsg -#define zcfree FPDFAPI_zcfree -#define zcalloc FPDFAPI_zcalloc -#define inflate_fast FPDFAPI_inflate_fast -#define inflate_table FPDFAPI_inflate_table -#define inflate_copyright FPDFAPI_inflate_copyright -#define _length_code FPDFAPI_length_code -#define _tr_flush_block FPDFAPI_tr_flush_block -#define _dist_code FPDFAPI_dist_code -#define _tr_stored_block FPDFAPI_tr_stored_block -#define _tr_init FPDFAPI_tr_init -#define _tr_align FPDFAPI_tr_align -#define _tr_tally FPDFAPI_tr_tally -#define _tr_flush_bits FPDFAPI_tr_flush_bits -#define adler32_combine FPDFAPI_adler32_combine -#define inflatePrime FPDFAPI_inflatePrime -#define inflateGetDictionary FPDFAPI_inflateGetDictionary -#define inflateGetHeader FPDFAPI_inflateGetHeader -#define crc32_combine FPDFAPI_crc32_combine -#define inflateReset2 FPDFAPI_inflateReset2 -#define inflateUndermine FPDFAPI_inflateUndermine -#define inflateMark FPDFAPI_inflateMark -#define adler32_combine64 FPDFAPI_adler32_combine64 -#define inflateResetKeep FPDFAPI_inflateResetKeep -#define deflateResetKeep FPDFAPI_deflateResetKeep - -#include "zconf.h" - -/* Sunliang.Liu 20100908 sync the config to the old revision. NO_GZIP */ -#define NO_GZIP /* XYQ */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.8" -#define ZLIB_VERNUM 0x1280 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 8 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - z_const Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total number of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total number of bytes output so far */ - - z_const char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this if - the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers - returned by zalloc for objects of exactly 65536 bytes *must* have their - offset normalized to zero. The default allocation function provided by this - library ensures this (see zutil.c). To reduce memory requirements and avoid - any allocation of 64K objects, at the expense of compression ratio, compile - the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all of the uncompressed data for the - operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not - required to perform an inflation in one step. However it may be used to - inform inflate that a faster approach can be used for the single inflate() - call. Z_FINISH also informs inflate to not maintain a sliding window if the - stream completes, which reduces inflate's memory footprint. If the stream - does not complete, either because not all of the stream is provided or not - enough output space is provided, then a sliding window will be allocated and - inflate() can be called again to continue the operation as if Z_NO_FLUSH had - been used. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The - compressor and decompressor must use exactly the same dictionary (see - inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). deflateSetDictionary does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are Z_NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. The application must insure that the dictionary - that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); -/* - Returns the sliding dictionary being maintained by inflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If inflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. - - inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurrences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible full flush point has been found, - Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point - has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above or -1 << 16 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is potentially more efficient than - inflate() for file i/o applications, in that it avoids copying between the - output and the sliding window by simply making the window itself the output - buffer. inflate() can be faster on modern CPUs when used with large - buffers. inflateBack() trusts the application to not change the output - buffer passed by the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - -#ifndef Z_SOLO - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) 'T' will - request transparent writing or appending with no compression and not using - the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. The addition of - "x" when writing will create the file exclusively, which fails if the file - already exists. On systems that support it, the addition of "e" when - reading or writing will set the flag to close the file on an execve() call. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - -#endif /* !Z_SOLO */ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) - -#ifndef Z_SOLO - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -# define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) -#else -# define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) -#endif - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) -# ifdef Z_PREFIX_SET -# define z_gzopen z_gzopen64 -# define z_gzseek z_gzseek64 -# define z_gztell z_gztell64 -# define z_gzoffset z_gzoffset64 -# define z_adler32_combine z_adler32_combine64 -# define z_crc32_combine z_crc32_combine64 -# else -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# undef adler32_combine -# undef crc32_combine -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# endif -# ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN off64_t ZEXPORT gzseek64 OF((gzFile, off64_t, int)); - ZEXTERN off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off64_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -#else /* Z_SOLO */ - - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - -#endif /* !Z_SOLO */ - -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if defined(_WIN32) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); -# endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/third_party/zlib_v128/zutil.c b/third_party/zlib_v128/zutil.c deleted file mode 100644 index 5fa007964d5b84e00cdb07000adbfe0d280e87d7..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/zutil.c +++ /dev/null @@ -1,341 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" -#ifndef Z_SOLO -# include "gzguts.h" -#endif - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -z_const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch ((int)(sizeof(uInt))) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch ((int)(sizeof(uLong))) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch ((int)(sizeof(voidpf))) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch ((int)(sizeof(z_off_t))) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#ifdef DEBUG - -# ifndef verbose -# define verbose 0 -# endif -int ZLIB_INTERNAL z_verbose = verbose; - -void ZLIB_INTERNAL z_error ( - char *m) -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError( - int err) -{ - return ERR_MSG(err); -} - -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - /* does not exist on WCE. XYQ: and we don't need it! */ - /*int errno = 0;*/ -#endif - -#ifndef HAVE_MEMCPY - -void ZLIB_INTERNAL zmemcpy( - Bytef* dest, - const Bytef* source, - uInt len) -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int ZLIB_INTERNAL zmemcmp( - const Bytef* s1, - const Bytef* s2, - uInt len) -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void ZLIB_INTERNAL zmemzero( - Bytef* dest, - uInt len) -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#if 0 -#ifndef Z_SOLO - -#ifdef SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} - -#endif /* __TURBOC__ */ - - -#ifdef M_I86 -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - if (opaque) items += size - size; /* make compiler happy */ - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); -} - -void ZLIB_INTERNAL zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ - -#endif /* !Z_SOLO */ -#endif /* 0 */ - -extern void* FXMEM_DefaultAlloc(size_t, int); -extern void FXMEM_DefaultFree(void*, int); - -/* XYQ 2007-1-19 */ -voidpf zcalloc(voidpf opaque, unsigned items, unsigned size) -{ - return FXMEM_DefaultAlloc(items * size, 0); -} - -void zcfree(voidpf opaque, voidpf ptr) -{ - FXMEM_DefaultFree(ptr, 0); -} diff --git a/third_party/zlib_v128/zutil.h b/third_party/zlib_v128/zutil.h deleted file mode 100644 index c3b10e109b6f6d45dbbbe028bc2a32d0124d0482..0000000000000000000000000000000000000000 --- a/third_party/zlib_v128/zutil.h +++ /dev/null @@ -1,255 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#include "core/fxcrt/fx_system.h" - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include "zlib.h" - -#if defined(STDC) && !defined(Z_SOLO) -# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) -# include <stddef.h> -# endif -# include <string.h> -# include <stdlib.h> -#endif - -#ifdef Z_SOLO - typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# define OS_CODE 0x00 -# ifndef Z_SOLO -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include <alloc.h> -# endif -# else /* MSC or DJGPP */ -# include <malloc.h> -# endif -# endif -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - FXSYS_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -# if defined(M_I86) && !defined(Z_SOLO) -# include <malloc.h> -# endif -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# ifndef Z_SOLO -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include <unix.h> /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -# endif -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#endif - -#if defined(__BORLANDC__) && !defined(MSDOS) - #pragma warn -8004 - #pragma warn -8008 - #pragma warn -8066 -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && \ - (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) FXSYS_fopen((name), (mode)) -#endif - - /* functions */ - -#if defined(pyr) || defined(Z_SOLO) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy FXSYS_memcpy -# define zmemcmp FXSYS_memcmp -# define zmemzero(dest, len) FXSYS_memset(dest, 0, len) -# endif -#else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include <stdio.h> - extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) FXSYS_fprintf x ;} -# define Tracev(x) {if (z_verbose>0) FXSYS_fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) FXSYS_fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) FXSYS_fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) FXSYS_fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -#ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); -#endif - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -/* Reverse the bytes in a 32-bit value */ -#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -#endif /* ZUTIL_H */ diff --git a/tools/drmemory/DrMemory-Windows-sfx.exe b/tools/drmemory/DrMemory-Windows-sfx.exe deleted file mode 100644 index cd3992b84e16d5057f1c07711939ed34888442d5..0000000000000000000000000000000000000000 Binary files a/tools/drmemory/DrMemory-Windows-sfx.exe and /dev/null differ diff --git a/xfa/DEPS b/xfa/DEPS index 4aad7ef9581eaa1c673eda1ece76ede932c1a4a7..2dd4ef3f547b8dd7cb3e68666d67465d78aa4d26 100644 --- a/xfa/DEPS +++ b/xfa/DEPS @@ -1,6 +1,5 @@ include_rules = [ - '+core/fpdfapi/parser', - '+core/fxcrt', - '+core/fxge', + '+core', + '+fxbarcode', '+third_party/bigint' ] diff --git a/xfa/README.md b/xfa/README.md new file mode 100644 index 0000000000000000000000000000000000000000..07460a62c073b318855f91f62485e1cd085a95e2 --- /dev/null +++ b/xfa/README.md @@ -0,0 +1,4 @@ +XFA stands for XML Forms Architecture. + +https://en.wikipedia.org/wiki/XFA + diff --git a/xfa/fde/cfde_data.h b/xfa/fde/cfde_data.h new file mode 100644 index 0000000000000000000000000000000000000000..d4ca63d071da35ad9526bbc81435e75e0fdf29ea --- /dev/null +++ b/xfa/fde/cfde_data.h @@ -0,0 +1,46 @@ +// Copyright 2018 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FDE_CFDE_DATA_H_ +#define XFA_FDE_CFDE_DATA_H_ + +#include "core/fxcrt/fx_coordinates.h" + +enum class FDE_TextAlignment : uint8_t { + kTopLeft = 0, + kCenterLeft, + kCenter, + kCenterRight +}; + +struct FDE_TextStyle { + FDE_TextStyle() + : single_line_(false), line_wrap_(false), last_line_height_(false) {} + ~FDE_TextStyle() {} + + void Reset() { + single_line_ = false; + line_wrap_ = false; + last_line_height_ = false; + } + + bool single_line_; + bool line_wrap_; + bool last_line_height_; +}; + +struct FDE_TTOPIECE { + FDE_TTOPIECE(); + FDE_TTOPIECE(const FDE_TTOPIECE& that); + ~FDE_TTOPIECE(); + + int32_t iStartChar; + int32_t iChars; + uint32_t dwCharStyles; + CFX_RectF rtPiece; +}; + +#endif // XFA_FDE_CFDE_DATA_H_ diff --git a/xfa/fde/cfde_path.cpp b/xfa/fde/cfde_path.cpp deleted file mode 100644 index 5e6cf5cf56cc605b9779e2210c33864f7ab705f0..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_path.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_path.h" - -#include "third_party/base/stl_util.h" -#include "xfa/fde/fde_object.h" - -void CFDE_Path::CloseFigure() { - m_Path.ClosePath(); -} - -bool CFDE_Path::FigureClosed() const { - const std::vector<FX_PATHPOINT>& points = m_Path.GetPoints(); - return points.empty() ? true : points.back().m_CloseFigure; -} - -void CFDE_Path::MoveTo(const CFX_PointF& point) { - m_Path.AppendPoint(point, FXPT_TYPE::MoveTo, false); -} - -void CFDE_Path::LineTo(const CFX_PointF& point) { - m_Path.AppendPoint(point, FXPT_TYPE::LineTo, false); -} - -void CFDE_Path::BezierTo(const CFX_PointF& p1, - const CFX_PointF& p2, - const CFX_PointF& p3) { - m_Path.AppendPoint(p1, FXPT_TYPE::BezierTo, false); - m_Path.AppendPoint(p2, FXPT_TYPE::BezierTo, false); - m_Path.AppendPoint(p3, FXPT_TYPE::BezierTo, false); -} - -void CFDE_Path::ArcTo(bool bStart, - const CFX_RectF& rect, - FX_FLOAT startAngle, - FX_FLOAT endAngle) { - FX_FLOAT rx = rect.width / 2; - FX_FLOAT ry = rect.height / 2; - FX_FLOAT cx = rect.left + rx; - FX_FLOAT cy = rect.top + ry; - FX_FLOAT alpha = - FXSYS_atan2(rx * FXSYS_sin(startAngle), ry * FXSYS_cos(startAngle)); - FX_FLOAT beta = - FXSYS_atan2(rx * FXSYS_sin(endAngle), ry * FXSYS_cos(endAngle)); - if (FXSYS_fabs(beta - alpha) > FX_PI) { - if (beta > alpha) - beta -= 2 * FX_PI; - else - alpha -= 2 * FX_PI; - } - - FX_FLOAT half_delta = (beta - alpha) / 2; - FX_FLOAT bcp = 4.0f / 3 * (1 - FXSYS_cos(half_delta)) / FXSYS_sin(half_delta); - FX_FLOAT sin_alpha = FXSYS_sin(alpha); - FX_FLOAT sin_beta = FXSYS_sin(beta); - FX_FLOAT cos_alpha = FXSYS_cos(alpha); - FX_FLOAT cos_beta = FXSYS_cos(beta); - if (bStart) - MoveTo(CFX_PointF(cx + rx * cos_alpha, cy + ry * sin_alpha)); - - BezierTo(CFX_PointF(cx + rx * (cos_alpha - bcp * sin_alpha), - cy + ry * (sin_alpha + bcp * cos_alpha)), - CFX_PointF(cx + rx * (cos_beta + bcp * sin_beta), - cy + ry * (sin_beta - bcp * cos_beta)), - CFX_PointF(cx + rx * cos_beta, cy + ry * sin_beta)); -} - -void CFDE_Path::AddBezier(const std::vector<CFX_PointF>& points) { - if (points.size() != 4) - return; - - MoveTo(points[0]); - BezierTo(points[1], points[2], points[3]); -} - -void CFDE_Path::AddBeziers(const std::vector<CFX_PointF>& points) { - int32_t iCount = points.size(); - if (iCount < 4) - return; - - const CFX_PointF* p = points.data(); - const CFX_PointF* pEnd = p + iCount; - MoveTo(p[0]); - for (++p; p <= pEnd - 3; p += 3) - BezierTo(p[0], p[1], p[2]); -} - -void CFDE_Path::GetCurveTangents(const std::vector<CFX_PointF>& points, - std::vector<CFX_PointF>* tangents, - bool bClosed, - FX_FLOAT fTension) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(points); - tangents->resize(iCount); - if (iCount < 3) - return; - - FX_FLOAT fCoefficient = fTension / 3.0f; - const CFX_PointF* pPoints = points.data(); - CFX_PointF* pTangents = tangents->data(); - for (int32_t i = 0; i < iCount; ++i) { - int32_t r = i + 1; - int32_t s = i - 1; - if (r >= iCount) - r = bClosed ? (r - iCount) : (iCount - 1); - if (s < 0) - s = bClosed ? (s + iCount) : 0; - - pTangents[i].x += (fCoefficient * (pPoints[r].x - pPoints[s].x)); - pTangents[i].y += (fCoefficient * (pPoints[r].y - pPoints[s].y)); - } -} - -void CFDE_Path::AddCurve(const std::vector<CFX_PointF>& points, - bool bClosed, - FX_FLOAT fTension) { - int32_t iLast = pdfium::CollectionSize<int32_t>(points) - 1; - if (iLast < 1) - return; - - std::vector<CFX_PointF> tangents; - GetCurveTangents(points, &tangents, bClosed, fTension); - const CFX_PointF* pPoints = points.data(); - CFX_PointF* pTangents = tangents.data(); - MoveTo(pPoints[0]); - for (int32_t i = 0; i < iLast; ++i) { - BezierTo(CFX_PointF(pPoints[i].x + pTangents[i].x, - pPoints[i].y + pTangents[i].y), - CFX_PointF(pPoints[i + 1].x - pTangents[i + 1].x, - pPoints[i + 1].y - pTangents[i + 1].y), - CFX_PointF(pPoints[i + 1].x, pPoints[i + 1].y)); - } - if (bClosed) { - BezierTo(CFX_PointF(pPoints[iLast].x + pTangents[iLast].x, - pPoints[iLast].y + pTangents[iLast].y), - CFX_PointF(pPoints[0].x - pTangents[0].x, - pPoints[0].y - pTangents[0].y), - CFX_PointF(pPoints[0].x, pPoints[0].y)); - CloseFigure(); - } -} - -void CFDE_Path::AddEllipse(const CFX_RectF& rect) { - FX_FLOAT fStartAngle = 0; - FX_FLOAT fEndAngle = FX_PI / 2; - for (int32_t i = 0; i < 4; ++i) { - ArcTo(i == 0, rect, fStartAngle, fEndAngle); - fStartAngle += FX_PI / 2; - fEndAngle += FX_PI / 2; - } - CloseFigure(); -} - -void CFDE_Path::AddLine(const CFX_PointF& pt1, const CFX_PointF& pt2) { - std::vector<FX_PATHPOINT>& points = m_Path.GetPoints(); - if (points.empty() || FXSYS_fabs(points.back().m_Point.x - pt1.x) > 0.001 || - FXSYS_fabs(points.back().m_Point.y - pt1.y) > 0.001) { - MoveTo(pt1); - } - LineTo(pt2); -} - -void CFDE_Path::AddPath(const CFDE_Path* pSrc, bool bConnect) { - if (!pSrc) - return; - - if (pSrc->m_Path.GetPoints().empty()) - return; - if (bConnect) - LineTo(pSrc->m_Path.GetPoint(0)); - - m_Path.Append(&pSrc->m_Path, nullptr); -} - -void CFDE_Path::AddPolygon(const std::vector<CFX_PointF>& points) { - size_t iCount = points.size(); - if (iCount < 2) - return; - - AddLines(points); - const CFX_PointF* p = points.data(); - if (FXSYS_fabs(p[0].x - p[iCount - 1].x) < 0.01f || - FXSYS_fabs(p[0].y - p[iCount - 1].y) < 0.01f) { - LineTo(p[0]); - } - CloseFigure(); -} - -void CFDE_Path::AddLines(const std::vector<CFX_PointF>& points) { - size_t iCount = points.size(); - if (iCount < 2) - return; - - const CFX_PointF* p = points.data(); - const CFX_PointF* pEnd = p + iCount; - MoveTo(p[0]); - for (++p; p < pEnd; ++p) - LineTo(*p); -} - -void CFDE_Path::AddRectangle(const CFX_RectF& rect) { - MoveTo(rect.TopLeft()); - LineTo(rect.TopRight()); - LineTo(rect.BottomRight()); - LineTo(rect.BottomLeft()); - CloseFigure(); -} - -CFX_RectF CFDE_Path::GetBBox() const { - CFX_FloatRect rect = m_Path.GetBoundingBox(); - CFX_RectF bbox = CFX_RectF(rect.left, rect.top, rect.Width(), rect.Height()); - bbox.Normalize(); - return bbox; -} - -CFX_RectF CFDE_Path::GetBBox(FX_FLOAT fLineWidth, FX_FLOAT fMiterLimit) const { - CFX_FloatRect rect = m_Path.GetBoundingBox(fLineWidth, fMiterLimit); - CFX_RectF bbox = CFX_RectF(rect.left, rect.top, rect.Width(), rect.Height()); - bbox.Normalize(); - return bbox; -} diff --git a/xfa/fde/cfde_path.h b/xfa/fde/cfde_path.h deleted file mode 100644 index 99ff4d36803210c97384a771e05e21efd88c9a95..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_path.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_PATH_H_ -#define XFA_FDE_CFDE_PATH_H_ - -#include <vector> - -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" - -class CFDE_Path { - public: - void CloseFigure(); - - void AddBezier(const std::vector<CFX_PointF>& points); - void AddBeziers(const std::vector<CFX_PointF>& points); - void AddCurve(const std::vector<CFX_PointF>& points, - bool bClosed, - FX_FLOAT fTension = 0.5f); - void AddEllipse(const CFX_RectF& rect); - void AddLines(const std::vector<CFX_PointF>& points); - void AddLine(const CFX_PointF& pt1, const CFX_PointF& pt2); - void AddPath(const CFDE_Path* pSrc, bool bConnect); - void AddPolygon(const std::vector<CFX_PointF>& points); - void AddRectangle(const CFX_RectF& rect); - - CFX_RectF GetBBox() const; - CFX_RectF GetBBox(FX_FLOAT fLineWidth, FX_FLOAT fMiterLimit) const; - - bool FigureClosed() const; - void BezierTo(const CFX_PointF& p1, - const CFX_PointF& p2, - const CFX_PointF& p3); - void ArcTo(bool bStart, - const CFX_RectF& rect, - FX_FLOAT startAngle, - FX_FLOAT endAngle); - void MoveTo(const CFX_PointF& p); - void LineTo(const CFX_PointF& p); - - void GetCurveTangents(const std::vector<CFX_PointF>& points, - std::vector<CFX_PointF>* tangents, - bool bClosed, - FX_FLOAT fTension) const; - CFX_PathData m_Path; -}; - -#endif // XFA_FDE_CFDE_PATH_H_ diff --git a/xfa/fde/cfde_texteditengine.cpp b/xfa/fde/cfde_texteditengine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d085a8d1477d90387611a0a113043d31056fd7c1 --- /dev/null +++ b/xfa/fde/cfde_texteditengine.cpp @@ -0,0 +1,1218 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fde/cfde_texteditengine.h" + +#include <algorithm> +#include <limits> + +#include "xfa/fde/cfde_textout.h" +#include "xfa/fde/cfde_wordbreak_data.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +namespace { + +constexpr size_t kMaxEditOperations = 128; +constexpr size_t kGapSize = 128; +constexpr size_t kPageWidthMax = 0xffff; + +class InsertOperation : public CFDE_TextEditEngine::Operation { + public: + InsertOperation(CFDE_TextEditEngine* engine, + size_t start_idx, + const WideString& added_text) + : engine_(engine), start_idx_(start_idx), added_text_(added_text) {} + + ~InsertOperation() override {} + + void Redo() const override { + engine_->Insert(start_idx_, added_text_, + CFDE_TextEditEngine::RecordOperation::kSkipRecord); + } + + void Undo() const override { + engine_->Delete(start_idx_, added_text_.GetLength(), + CFDE_TextEditEngine::RecordOperation::kSkipRecord); + } + + private: + UnownedPtr<CFDE_TextEditEngine> engine_; + size_t start_idx_; + WideString added_text_; +}; + +class DeleteOperation : public CFDE_TextEditEngine::Operation { + public: + DeleteOperation(CFDE_TextEditEngine* engine, + size_t start_idx, + const WideString& removed_text) + : engine_(engine), start_idx_(start_idx), removed_text_(removed_text) {} + + ~DeleteOperation() override {} + + void Redo() const override { + engine_->Delete(start_idx_, removed_text_.GetLength(), + CFDE_TextEditEngine::RecordOperation::kSkipRecord); + } + + void Undo() const override { + engine_->Insert(start_idx_, removed_text_, + CFDE_TextEditEngine::RecordOperation::kSkipRecord); + } + + private: + UnownedPtr<CFDE_TextEditEngine> engine_; + size_t start_idx_; + WideString removed_text_; +}; + +class ReplaceOperation : public CFDE_TextEditEngine::Operation { + public: + ReplaceOperation(CFDE_TextEditEngine* engine, + size_t start_idx, + const WideString& removed_text, + const WideString& added_text) + : insert_op_(engine, start_idx, added_text), + delete_op_(engine, start_idx, removed_text) {} + + ~ReplaceOperation() override {} + + void Redo() const override { + delete_op_.Redo(); + insert_op_.Redo(); + } + + void Undo() const override { + insert_op_.Undo(); + delete_op_.Undo(); + } + + private: + InsertOperation insert_op_; + DeleteOperation delete_op_; +}; + +bool CheckStateChangeForWordBreak(WordBreakProperty from, + WordBreakProperty to) { + ASSERT(static_cast<int>(from) < 13); + + return !!(gs_FX_WordBreak_Table[static_cast<int>(from)] & + static_cast<uint16_t>(1 << static_cast<int>(to))); +} + +WordBreakProperty GetWordBreakProperty(wchar_t wcCodePoint) { + uint8_t dwProperty = gs_FX_WordBreak_CodePointProperties[wcCodePoint >> 1]; + return static_cast<WordBreakProperty>((wcCodePoint & 1) ? (dwProperty & 0x0F) + : (dwProperty >> 4)); +} + +int GetBreakFlagsFor(WordBreakProperty current, WordBreakProperty next) { + if (current == WordBreakProperty::kMidLetter) { + if (next == WordBreakProperty::kALetter) + return 1; + } else if (current == WordBreakProperty::kMidNum) { + if (next == WordBreakProperty::kNumeric) + return 2; + } else if (current == WordBreakProperty::kMidNumLet) { + if (next == WordBreakProperty::kALetter) + return 1; + if (next == WordBreakProperty::kNumeric) + return 2; + } + return 0; +} + +bool BreakFlagsChanged(int flags, WordBreakProperty previous) { + return (flags != 1 || previous != WordBreakProperty::kALetter) && + (flags != 2 || previous != WordBreakProperty::kNumeric); +} + +} // namespace + +CFDE_TextEditEngine::CFDE_TextEditEngine() + : font_color_(0xff000000), + font_size_(10.0f), + line_spacing_(10.0f), + text_length_(0), + gap_position_(0), + gap_size_(kGapSize), + available_width_(kPageWidthMax), + character_limit_(std::numeric_limits<size_t>::max()), + visible_line_count_(1), + next_operation_index_to_undo_(kMaxEditOperations - 1), + next_operation_index_to_insert_(0), + max_edit_operations_(kMaxEditOperations), + character_alignment_(CFX_TxtLineAlignment_Left), + has_character_limit_(false), + is_comb_text_(false), + is_dirty_(false), + validation_enabled_(false), + is_multiline_(false), + is_linewrap_enabled_(false), + limit_horizontal_area_(false), + limit_vertical_area_(false), + password_mode_(false), + password_alias_(L'*'), + has_selection_(false), + selection_({0, 0}) { + content_.resize(gap_size_); + operation_buffer_.resize(max_edit_operations_); + + text_break_.SetFontSize(font_size_); + text_break_.SetLineBreakTolerance(2.0f); + text_break_.SetTabWidth(36); +} + +CFDE_TextEditEngine::~CFDE_TextEditEngine() {} + +void CFDE_TextEditEngine::Clear() { + text_length_ = 0; + gap_position_ = 0; + gap_size_ = kGapSize; + + content_.clear(); + content_.resize(gap_size_); + + ClearSelection(); + ClearOperationRecords(); +} + +void CFDE_TextEditEngine::SetMaxEditOperationsForTesting(size_t max) { + max_edit_operations_ = max; + operation_buffer_.resize(max); + + ClearOperationRecords(); +} + +void CFDE_TextEditEngine::AdjustGap(size_t idx, size_t length) { + static const size_t char_size = sizeof(WideString::CharType); + + // Move the gap, if necessary. + if (idx < gap_position_) { + memmove(content_.data() + idx + gap_size_, content_.data() + idx, + (gap_position_ - idx) * char_size); + gap_position_ = idx; + } else if (idx > gap_position_) { + memmove(content_.data() + gap_position_, + content_.data() + gap_position_ + gap_size_, + (idx - gap_position_) * char_size); + gap_position_ = idx; + } + + // If the gap is too small, make it bigger. + if (length >= gap_size_) { + size_t new_gap_size = length + kGapSize; + content_.resize(text_length_ + new_gap_size); + + memmove(content_.data() + gap_position_ + new_gap_size, + content_.data() + gap_position_ + gap_size_, + (text_length_ - gap_position_) * char_size); + + gap_size_ = new_gap_size; + } +} + +size_t CFDE_TextEditEngine::CountCharsExceedingSize(const WideString& text, + size_t num_to_check) { + if (!limit_horizontal_area_ && !limit_vertical_area_) + return 0; + + auto text_out = pdfium::MakeUnique<CFDE_TextOut>(); + text_out->SetLineSpace(line_spacing_); + text_out->SetFont(font_); + text_out->SetFontSize(font_size_); + + FDE_TextStyle style; + style.single_line_ = !is_multiline_; + + CFX_RectF text_rect; + if (is_linewrap_enabled_) { + style.line_wrap_ = true; + text_rect.width = available_width_; + } else { + text_rect.width = kPageWidthMax; + } + text_out->SetStyles(style); + + size_t length = text.GetLength(); + WideStringView temp(text.c_str(), length); + + float vertical_height = line_spacing_ * visible_line_count_; + size_t chars_exceeding_size = 0; + // TODO(dsinclair): Can this get changed to a binary search? + for (size_t i = 0; i < num_to_check; i++) { + // This does a lot of string copying .... + // TODO(dsinclair): make CalcLogicSize take a WideStringC instead. + text_out->CalcLogicSize(WideString(temp), text_rect); + + if (limit_horizontal_area_ && text_rect.width <= available_width_) + break; + if (limit_vertical_area_ && text_rect.height <= vertical_height) + break; + + --length; + temp = temp.Mid(0, length); + ++chars_exceeding_size; + } + + return chars_exceeding_size; +} + +void CFDE_TextEditEngine::Insert(size_t idx, + const WideString& text, + RecordOperation add_operation) { + if (idx > text_length_) + idx = text_length_; + + size_t length = text.GetLength(); + if (length == 0) + return; + + // If we're going to be too big we insert what we can and notify the + // delegate we've filled the text after the insert is done. + bool exceeded_limit = false; + if (has_character_limit_ && text_length_ + length > character_limit_) { + exceeded_limit = true; + length = character_limit_ - text_length_; + } + + AdjustGap(idx, length); + + if (validation_enabled_ || limit_horizontal_area_ || limit_vertical_area_) { + WideString str; + if (gap_position_ > 0) + str += WideStringView(content_.data(), gap_position_); + + str += text; + + if (text_length_ - gap_position_ > 0) { + str += WideStringView(content_.data() + gap_position_ + gap_size_, + text_length_ - gap_position_); + } + + if (validation_enabled_ && delegate_ && !delegate_->OnValidate(str)) { + // TODO(dsinclair): Notify delegate of validation failure? + return; + } + + // Check if we've limited the horizontal/vertical area, and if so determine + // how many of our characters would be outside the area. + size_t chars_exceeding = CountCharsExceedingSize(str, length); + if (chars_exceeding > 0) { + // If none of the characters will fit, notify and exit. + if (chars_exceeding == length) { + if (delegate_) + delegate_->NotifyTextFull(); + return; + } + + // Some, but not all, chars will fit, insert them and then notify + // we're full. + exceeded_limit = true; + length -= chars_exceeding; + } + } + + if (add_operation == RecordOperation::kInsertRecord) { + AddOperationRecord( + pdfium::MakeUnique<InsertOperation>(this, gap_position_, text)); + } + + WideString previous_text; + if (delegate_) + previous_text = GetText(); + + // Copy the new text into the gap. + static const size_t char_size = sizeof(WideString::CharType); + memcpy(content_.data() + gap_position_, text.c_str(), length * char_size); + gap_position_ += length; + gap_size_ -= length; + text_length_ += length; + + is_dirty_ = true; + + // Inserting text resets the selection. + ClearSelection(); + + if (delegate_) { + if (exceeded_limit) + delegate_->NotifyTextFull(); + + delegate_->OnTextChanged(previous_text); + } +} + +void CFDE_TextEditEngine::AddOperationRecord(std::unique_ptr<Operation> op) { + size_t last_insert_position = next_operation_index_to_insert_ == 0 + ? max_edit_operations_ - 1 + : next_operation_index_to_insert_ - 1; + + // If our undo record is not the last thing we inserted then we need to + // remove all the undo records between our insert position and the undo marker + // and make that our new insert position. + if (next_operation_index_to_undo_ != last_insert_position) { + if (next_operation_index_to_undo_ > last_insert_position) { + // Our Undo position is ahead of us, which means we need to clear out the + // head of the queue. + while (last_insert_position != 0) { + operation_buffer_[last_insert_position].reset(); + --last_insert_position; + } + operation_buffer_[0].reset(); + + // Moving this will let us then clear out the end, setting the undo + // position to before the insert position. + last_insert_position = max_edit_operations_ - 1; + } + + // Clear out the vector from undo position to our set insert position. + while (next_operation_index_to_undo_ != last_insert_position) { + operation_buffer_[last_insert_position].reset(); + --last_insert_position; + } + } + + // We're now pointing at the next thing we want to Undo, so insert at the + // next position in the queue. + ++last_insert_position; + if (last_insert_position >= max_edit_operations_) + last_insert_position = 0; + + operation_buffer_[last_insert_position] = std::move(op); + next_operation_index_to_insert_ = + (last_insert_position + 1) % max_edit_operations_; + next_operation_index_to_undo_ = last_insert_position; +} + +void CFDE_TextEditEngine::ClearOperationRecords() { + for (auto& record : operation_buffer_) + record.reset(); + + next_operation_index_to_undo_ = max_edit_operations_ - 1; + next_operation_index_to_insert_ = 0; +} + +size_t CFDE_TextEditEngine::GetIndexBefore(size_t pos) { + int32_t bidi_level; + CFX_RectF rect; + // Possible |Layout| triggered by |GetCharacterInfo|. + std::tie(bidi_level, rect) = GetCharacterInfo(pos); + return FX_IsOdd(bidi_level) ? GetIndexRight(pos) : GetIndexLeft(pos); +} + +size_t CFDE_TextEditEngine::GetIndexLeft(size_t pos) const { + if (pos == 0) + return 0; + --pos; + + wchar_t ch = GetChar(pos); + while (pos != 0) { + // We want to be on the location just before the \r or \n + ch = GetChar(pos - 1); + if (ch != '\r' && ch != '\n') + break; + + --pos; + } + return pos; +} + +size_t CFDE_TextEditEngine::GetIndexRight(size_t pos) const { + if (pos >= text_length_) + return text_length_; + ++pos; + + wchar_t ch = GetChar(pos); + // We want to be on the location after the \r\n. + while (pos < text_length_ && (ch == '\r' || ch == '\n')) { + ++pos; + ch = GetChar(pos); + } + + return pos; +} + +size_t CFDE_TextEditEngine::GetIndexUp(size_t pos) const { + size_t line_start = GetIndexAtStartOfLine(pos); + if (line_start == 0) + return pos; + + // Determine how far along the line we were. + size_t dist = pos - line_start; + + // Move to the end of the preceding line. + wchar_t ch; + do { + --line_start; + ch = GetChar(line_start); + } while (line_start != 0 && (ch == '\r' || ch == '\n')); + + if (line_start == 0) + return dist; + + // Get the start of the line prior to the current line. + size_t prior_start = GetIndexAtStartOfLine(line_start); + + // Prior line is shorter then next line, and we're past the end of that line + // return the end of line. + if (prior_start + dist > line_start) + return GetIndexAtEndOfLine(line_start); + + return prior_start + dist; +} + +size_t CFDE_TextEditEngine::GetIndexDown(size_t pos) const { + size_t line_end = GetIndexAtEndOfLine(pos); + if (line_end == text_length_) + return pos; + + wchar_t ch; + do { + ++line_end; + ch = GetChar(line_end); + } while (line_end < text_length_ && (ch == '\r' || ch == '\n')); + + if (line_end == text_length_) + return line_end; + + // Determine how far along the line we are. + size_t dist = pos - GetIndexAtStartOfLine(pos); + + // Check if next line is shorter then current line. If so, return end + // of next line. + size_t next_line_end = GetIndexAtEndOfLine(line_end); + if (line_end + dist > next_line_end) + return next_line_end; + + return line_end + dist; +} + +size_t CFDE_TextEditEngine::GetIndexAtStartOfLine(size_t pos) const { + if (pos == 0) + return 0; + + wchar_t ch = GetChar(pos); + // What to do. + if (ch == '\r' || ch == '\n') + return pos; + + do { + // We want to be on the location just after the \r\n + ch = GetChar(pos - 1); + if (ch == '\r' || ch == '\n') + break; + + --pos; + } while (pos > 0); + + return pos; +} + +size_t CFDE_TextEditEngine::GetIndexAtEndOfLine(size_t pos) const { + if (pos >= text_length_) + return text_length_; + + wchar_t ch = GetChar(pos); + // Not quite sure which way to go here? + if (ch == '\r' || ch == '\n') + return pos; + + // We want to be on the location of the first \r or \n. + do { + ++pos; + ch = GetChar(pos); + } while (pos < text_length_ && (ch != '\r' && ch != '\n')); + + return pos; +} + +void CFDE_TextEditEngine::LimitHorizontalScroll(bool val) { + ClearOperationRecords(); + limit_horizontal_area_ = val; +} + +void CFDE_TextEditEngine::LimitVerticalScroll(bool val) { + ClearOperationRecords(); + limit_vertical_area_ = val; +} + +bool CFDE_TextEditEngine::CanUndo() const { + return operation_buffer_[next_operation_index_to_undo_] != nullptr && + next_operation_index_to_undo_ != next_operation_index_to_insert_; +} + +bool CFDE_TextEditEngine::CanRedo() const { + size_t idx = (next_operation_index_to_undo_ + 1) % max_edit_operations_; + return idx != next_operation_index_to_insert_ && + operation_buffer_[idx] != nullptr; +} + +bool CFDE_TextEditEngine::Redo() { + if (!CanRedo()) + return false; + + next_operation_index_to_undo_ = + (next_operation_index_to_undo_ + 1) % max_edit_operations_; + operation_buffer_[next_operation_index_to_undo_]->Redo(); + return true; +} + +bool CFDE_TextEditEngine::Undo() { + if (!CanUndo()) + return false; + + operation_buffer_[next_operation_index_to_undo_]->Undo(); + next_operation_index_to_undo_ = next_operation_index_to_undo_ == 0 + ? max_edit_operations_ - 1 + : next_operation_index_to_undo_ - 1; + return true; +} + +void CFDE_TextEditEngine::Layout() { + if (!is_dirty_) + return; + + is_dirty_ = false; + RebuildPieces(); +} + +CFX_RectF CFDE_TextEditEngine::GetContentsBoundingBox() { + // Layout if necessary. + Layout(); + return contents_bounding_box_; +} + +void CFDE_TextEditEngine::SetAvailableWidth(size_t width) { + if (width == available_width_) + return; + + ClearOperationRecords(); + + available_width_ = width; + if (is_linewrap_enabled_) + text_break_.SetLineWidth(width); + if (is_comb_text_) + SetCombTextWidth(); + + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetHasCharacterLimit(bool limit) { + if (has_character_limit_ == limit) + return; + + has_character_limit_ = limit; + if (is_comb_text_) + SetCombTextWidth(); + + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetCharacterLimit(size_t limit) { + if (character_limit_ == limit) + return; + + ClearOperationRecords(); + + character_limit_ = limit; + if (is_comb_text_) + SetCombTextWidth(); + + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetFont(RetainPtr<CFGAS_GEFont> font) { + if (font_ == font) + return; + + font_ = font; + text_break_.SetFont(font_); + is_dirty_ = true; +} + +RetainPtr<CFGAS_GEFont> CFDE_TextEditEngine::GetFont() const { + return font_; +} + +void CFDE_TextEditEngine::SetFontSize(float size) { + if (font_size_ == size) + return; + + font_size_ = size; + text_break_.SetFontSize(font_size_); + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetTabWidth(float width) { + int32_t old_tab_width = text_break_.GetTabWidth(); + text_break_.SetTabWidth(width); + if (old_tab_width == text_break_.GetTabWidth()) + return; + + is_dirty_ = true; +} + +float CFDE_TextEditEngine::GetFontAscent() const { + return (static_cast<float>(font_->GetAscent()) * font_size_) / 1000; +} + +void CFDE_TextEditEngine::SetAlignment(uint32_t alignment) { + if (alignment == character_alignment_) + return; + + character_alignment_ = alignment; + text_break_.SetAlignment(alignment); + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetVisibleLineCount(size_t count) { + if (visible_line_count_ == count) + return; + + visible_line_count_ = std::max(static_cast<size_t>(1), count); + is_dirty_ = true; +} + +void CFDE_TextEditEngine::EnableMultiLine(bool val) { + if (is_multiline_ == val) + return; + + is_multiline_ = true; + + uint32_t style = text_break_.GetLayoutStyles(); + if (is_multiline_) + style &= ~FX_LAYOUTSTYLE_SingleLine; + else + style |= FX_LAYOUTSTYLE_SingleLine; + text_break_.SetLayoutStyles(style); + is_dirty_ = true; +} + +void CFDE_TextEditEngine::EnableLineWrap(bool val) { + if (is_linewrap_enabled_ == val) + return; + + is_linewrap_enabled_ = val; + text_break_.SetLineWidth(is_linewrap_enabled_ ? available_width_ + : kPageWidthMax); + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetCombText(bool enable) { + if (is_comb_text_ == enable) + return; + + is_comb_text_ = enable; + + uint32_t style = text_break_.GetLayoutStyles(); + if (enable) { + style |= FX_LAYOUTSTYLE_CombText; + SetCombTextWidth(); + } else { + style &= ~FX_LAYOUTSTYLE_CombText; + } + text_break_.SetLayoutStyles(style); + is_dirty_ = true; +} + +void CFDE_TextEditEngine::SetCombTextWidth() { + size_t width = available_width_; + if (has_character_limit_) + width /= character_limit_; + + text_break_.SetCombWidth(width); +} + +void CFDE_TextEditEngine::SelectAll() { + if (text_length_ == 0) + return; + + has_selection_ = true; + selection_.start_idx = 0; + selection_.count = text_length_; +} + +void CFDE_TextEditEngine::ClearSelection() { + has_selection_ = false; + selection_.start_idx = 0; + selection_.count = 0; +} + +void CFDE_TextEditEngine::SetSelection(size_t start_idx, size_t count) { + if (count == 0) { + ClearSelection(); + return; + } + + if (start_idx > text_length_) + return; + if (start_idx + count > text_length_) + count = text_length_ - start_idx; + + has_selection_ = true; + selection_.start_idx = start_idx; + selection_.count = count; +} + +WideString CFDE_TextEditEngine::GetSelectedText() const { + if (!has_selection_) + return L""; + + WideString text; + if (selection_.start_idx < gap_position_) { + // Fully on left of gap. + if (selection_.start_idx + selection_.count < gap_position_) { + text += WideStringView(content_.data() + selection_.start_idx, + selection_.count); + return text; + } + + // Pre-gap text + text += WideStringView(content_.data() + selection_.start_idx, + gap_position_ - selection_.start_idx); + + if (selection_.count - (gap_position_ - selection_.start_idx) > 0) { + // Post-gap text + text += WideStringView( + content_.data() + gap_position_ + gap_size_, + selection_.count - (gap_position_ - selection_.start_idx)); + } + + return text; + } + + // Fully right of gap + text += WideStringView(content_.data() + gap_size_ + selection_.start_idx, + selection_.count); + return text; +} + +WideString CFDE_TextEditEngine::DeleteSelectedText( + RecordOperation add_operation) { + if (!has_selection_) + return L""; + + return Delete(selection_.start_idx, selection_.count, add_operation); +} + +WideString CFDE_TextEditEngine::Delete(size_t start_idx, + size_t length, + RecordOperation add_operation) { + if (start_idx >= text_length_) + return L""; + + length = std::min(length, text_length_ - start_idx); + AdjustGap(start_idx + length, 0); + + WideString ret; + ret += WideStringView(content_.data() + start_idx, length); + + if (add_operation == RecordOperation::kInsertRecord) { + AddOperationRecord( + pdfium::MakeUnique<DeleteOperation>(this, start_idx, ret)); + } + + WideString previous_text = GetText(); + + gap_position_ = start_idx; + gap_size_ += length; + + text_length_ -= length; + ClearSelection(); + + if (delegate_) + delegate_->OnTextChanged(previous_text); + + return ret; +} + +void CFDE_TextEditEngine::ReplaceSelectedText(const WideString& rep) { + size_t start_idx = selection_.start_idx; + + WideString txt = DeleteSelectedText(RecordOperation::kSkipRecord); + Insert(gap_position_, rep, RecordOperation::kSkipRecord); + + AddOperationRecord( + pdfium::MakeUnique<ReplaceOperation>(this, start_idx, txt, rep)); +} + +WideString CFDE_TextEditEngine::GetText() const { + WideString str; + if (gap_position_ > 0) + str += WideStringView(content_.data(), gap_position_); + if (text_length_ - gap_position_ > 0) { + str += WideStringView(content_.data() + gap_position_ + gap_size_, + text_length_ - gap_position_); + } + return str; +} + +size_t CFDE_TextEditEngine::GetLength() const { + return text_length_; +} + +wchar_t CFDE_TextEditEngine::GetChar(size_t idx) const { + if (idx >= text_length_) + return L'\0'; + if (password_mode_) + return password_alias_; + + return idx < gap_position_ + ? content_[idx] + : content_[gap_position_ + gap_size_ + (idx - gap_position_)]; +} + +size_t CFDE_TextEditEngine::GetWidthOfChar(size_t idx) { + // Recalculate the widths if necessary. + Layout(); + return idx < char_widths_.size() ? char_widths_[idx] : 0; +} + +size_t CFDE_TextEditEngine::GetIndexForPoint(const CFX_PointF& point) { + // Recalculate the widths if necessary. + Layout(); + + auto start_it = text_piece_info_.begin(); + for (; start_it < text_piece_info_.end(); ++start_it) { + if (start_it->rtPiece.top <= point.y && + point.y < start_it->rtPiece.bottom()) + break; + } + // We didn't find the point before getting to the end of the text, return + // end of text. + if (start_it == text_piece_info_.end()) + return text_length_; + + auto end_it = start_it; + for (; end_it < text_piece_info_.end(); ++end_it) { + // We've moved past where the point should be and didn't find anything. + // Return the start of the current piece as the location. + if (end_it->rtPiece.bottom() <= point.y || point.y < end_it->rtPiece.top) + break; + } + // Make sure the end iterator is pointing to our text pieces. + if (end_it == text_piece_info_.end()) + --end_it; + + size_t start_it_idx = start_it->nStart; + for (; start_it <= end_it; ++start_it) { + if (!start_it->rtPiece.Contains(point)) + continue; + + std::vector<CFX_RectF> rects = GetCharRects(*start_it); + for (size_t i = 0; i < rects.size(); ++i) { + if (!rects[i].Contains(point)) + continue; + size_t pos = start_it->nStart + i; + if (pos >= text_length_) + return text_length_; + + wchar_t wch = GetChar(pos); + if (wch == L'\n' || wch == L'\r') { + if (wch == L'\n' && pos > 0 && GetChar(pos - 1) == L'\r') + --pos; + return pos; + } + + // TODO(dsinclair): Old code had a before flag set based on bidi? + return pos; + } + } + + if (start_it == text_piece_info_.end()) + return start_it_idx; + if (start_it == end_it) + return start_it->nStart; + + // We didn't find the point before going over all of the pieces, we want to + // return the start of the piece after the point. + return end_it->nStart; +} + +std::vector<CFX_RectF> CFDE_TextEditEngine::GetCharRects( + const FDE_TEXTEDITPIECE& piece) { + if (piece.nCount < 1) + return std::vector<CFX_RectF>(); + + FX_TXTRUN tr; + tr.pEdtEngine = this; + tr.pIdentity = &piece; + tr.iLength = piece.nCount; + tr.pFont = font_; + tr.fFontSize = font_size_; + tr.dwStyles = text_break_.GetLayoutStyles(); + tr.dwCharStyles = piece.dwCharStyles; + tr.pRect = &piece.rtPiece; + return text_break_.GetCharRects(&tr, false); +} + +std::vector<FXTEXT_CHARPOS> CFDE_TextEditEngine::GetDisplayPos( + const FDE_TEXTEDITPIECE& piece) { + if (piece.nCount < 1) + return std::vector<FXTEXT_CHARPOS>(); + + FX_TXTRUN tr; + tr.pEdtEngine = this; + tr.pIdentity = &piece; + tr.iLength = piece.nCount; + tr.pFont = font_; + tr.fFontSize = font_size_; + tr.dwStyles = text_break_.GetLayoutStyles(); + tr.dwCharStyles = piece.dwCharStyles; + tr.pRect = &piece.rtPiece; + + std::vector<FXTEXT_CHARPOS> data(text_break_.GetDisplayPos(&tr, nullptr)); + text_break_.GetDisplayPos(&tr, data.data()); + return data; +} + +void CFDE_TextEditEngine::RebuildPieces() { + text_break_.EndBreak(CFX_BreakType::Paragraph); + text_break_.ClearBreakPieces(); + + char_widths_.clear(); + text_piece_info_.clear(); + + // Must have a font set in order to break the text. + if (text_length_ == 0 || !font_) + return; + + bool initialized_bounding_box = false; + contents_bounding_box_ = CFX_RectF(); + size_t current_piece_start = 0; + float current_line_start = 0; + + auto iter = pdfium::MakeUnique<CFDE_TextEditEngine::Iterator>(this); + while (!iter->IsEOF(false)) { + iter->Next(false); + + CFX_BreakType break_status = text_break_.AppendChar( + password_mode_ ? password_alias_ : iter->GetChar()); + if (iter->IsEOF(false) && CFX_BreakTypeNoneOrPiece(break_status)) + break_status = text_break_.EndBreak(CFX_BreakType::Paragraph); + + if (CFX_BreakTypeNoneOrPiece(break_status)) + continue; + int32_t piece_count = text_break_.CountBreakPieces(); + for (int32_t i = 0; i < piece_count; ++i) { + const CFX_BreakPiece* piece = text_break_.GetBreakPieceUnstable(i); + + FDE_TEXTEDITPIECE txtEdtPiece; + memset(&txtEdtPiece, 0, sizeof(FDE_TEXTEDITPIECE)); + + txtEdtPiece.nBidiLevel = piece->m_iBidiLevel; + txtEdtPiece.nCount = piece->GetLength(); + txtEdtPiece.nStart = current_piece_start; + txtEdtPiece.dwCharStyles = piece->m_dwCharStyles; + if (FX_IsOdd(piece->m_iBidiLevel)) + txtEdtPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; + + txtEdtPiece.rtPiece.left = piece->m_iStartPos / 20000.0f; + txtEdtPiece.rtPiece.top = current_line_start; + txtEdtPiece.rtPiece.width = piece->m_iWidth / 20000.0f; + txtEdtPiece.rtPiece.height = line_spacing_; + text_piece_info_.push_back(txtEdtPiece); + + if (initialized_bounding_box) { + contents_bounding_box_.Union(txtEdtPiece.rtPiece); + } else { + contents_bounding_box_ = txtEdtPiece.rtPiece; + initialized_bounding_box = true; + } + + current_piece_start += txtEdtPiece.nCount; + for (int32_t k = 0; k < txtEdtPiece.nCount; ++k) + char_widths_.push_back(piece->GetChar(k)->m_iCharWidth); + } + + current_line_start += line_spacing_; + text_break_.ClearBreakPieces(); + } + + float delta = 0.0; + bool bounds_smaller = contents_bounding_box_.width < available_width_; + if (IsAlignedRight() && bounds_smaller) { + delta = available_width_ - contents_bounding_box_.width; + } else if (IsAlignedCenter() && bounds_smaller) { + // TODO(dsinclair): Old code used CombText here and set the space to + // something unrelated to the available width .... Figure out if this is + // needed and what it should do. + // if (is_comb_text_) { + // } else { + delta = (available_width_ - contents_bounding_box_.width) / 2.0f; + // } + } + + if (delta != 0.0) { + float offset = delta - contents_bounding_box_.left; + for (auto& info : text_piece_info_) + info.rtPiece.Offset(offset, 0.0f); + contents_bounding_box_.Offset(offset, 0.0f); + } + + // Shrink the last piece down to the font_size. + contents_bounding_box_.height -= line_spacing_ - font_size_; + text_piece_info_.back().rtPiece.height = font_size_; +} + +std::pair<int32_t, CFX_RectF> CFDE_TextEditEngine::GetCharacterInfo( + int32_t start_idx) { + ASSERT(start_idx >= 0); + ASSERT(static_cast<size_t>(start_idx) <= text_length_); + + // Make sure the current available data is fresh. + Layout(); + + auto it = text_piece_info_.begin(); + for (; it != text_piece_info_.end(); ++it) { + if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount) + break; + } + if (it == text_piece_info_.end()) { + NOTREACHED(); + return {0, CFX_RectF()}; + } + + return {it->nBidiLevel, GetCharRects(*it)[start_idx - it->nStart]}; +} + +std::vector<CFX_RectF> CFDE_TextEditEngine::GetCharacterRectsInRange( + int32_t start_idx, + int32_t count) { + // Make sure the current available data is fresh. + Layout(); + + auto it = text_piece_info_.begin(); + for (; it != text_piece_info_.end(); ++it) { + if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount) + break; + } + if (it == text_piece_info_.end()) + return std::vector<CFX_RectF>(); + + int32_t end_idx = start_idx + count - 1; + std::vector<CFX_RectF> rects; + while (it != text_piece_info_.end()) { + // If we end inside the current piece, extract what we need and we're done. + if (it->nStart <= end_idx && end_idx < it->nStart + it->nCount) { + std::vector<CFX_RectF> arr = GetCharRects(*it); + CFX_RectF piece = arr[0]; + piece.Union(arr[end_idx - it->nStart]); + rects.push_back(piece); + break; + } + rects.push_back(it->rtPiece); + ++it; + } + + return rects; +} + +std::pair<size_t, size_t> CFDE_TextEditEngine::BoundsForWordAt( + size_t idx) const { + if (idx > text_length_) + return {0, 0}; + + CFDE_TextEditEngine::Iterator iter(this); + iter.SetAt(idx); + + size_t start_idx = iter.FindNextBreakPos(true); + size_t end_idx = iter.FindNextBreakPos(false); + return {start_idx, end_idx - start_idx + 1}; +} + +CFDE_TextEditEngine::Iterator::Iterator(const CFDE_TextEditEngine* engine) + : engine_(engine), current_position_(-1) {} + +CFDE_TextEditEngine::Iterator::~Iterator() {} + +void CFDE_TextEditEngine::Iterator::Next(bool bPrev) { + if (bPrev && current_position_ == -1) + return; + if (!bPrev && current_position_ > -1 && + static_cast<size_t>(current_position_) == engine_->GetLength()) { + return; + } + + if (bPrev) + --current_position_; + else + ++current_position_; +} + +wchar_t CFDE_TextEditEngine::Iterator::GetChar() const { + return engine_->GetChar(current_position_); +} + +void CFDE_TextEditEngine::Iterator::SetAt(size_t nIndex) { + if (static_cast<size_t>(nIndex) >= engine_->GetLength()) + current_position_ = engine_->GetLength(); + else + current_position_ = nIndex; +} + +bool CFDE_TextEditEngine::Iterator::IsEOF(bool bPrev) const { + return bPrev ? current_position_ == -1 + : current_position_ > -1 && + static_cast<size_t>(current_position_) == + engine_->GetLength(); +} + +size_t CFDE_TextEditEngine::Iterator::FindNextBreakPos(bool bPrev) { + if (IsEOF(bPrev)) + return current_position_ > -1 ? current_position_ : 0; + + WordBreakProperty ePreType = WordBreakProperty::kNone; + if (!IsEOF(!bPrev)) { + Next(!bPrev); + ePreType = GetWordBreakProperty(GetChar()); + Next(bPrev); + } + + WordBreakProperty eCurType = GetWordBreakProperty(GetChar()); + bool bFirst = true; + while (!IsEOF(bPrev)) { + Next(bPrev); + + WordBreakProperty eNextType = GetWordBreakProperty(GetChar()); + bool wBreak = CheckStateChangeForWordBreak(eCurType, eNextType); + if (wBreak) { + if (IsEOF(bPrev)) { + Next(!bPrev); + break; + } + if (bFirst) { + int32_t nFlags = GetBreakFlagsFor(eCurType, eNextType); + if (nFlags > 0) { + if (BreakFlagsChanged(nFlags, ePreType)) { + Next(!bPrev); + break; + } + Next(bPrev); + wBreak = false; + } + } + if (wBreak) { + int32_t nFlags = GetBreakFlagsFor(eNextType, eCurType); + if (nFlags <= 0) { + Next(!bPrev); + break; + } + + Next(bPrev); + eNextType = GetWordBreakProperty(GetChar()); + if (BreakFlagsChanged(nFlags, eNextType)) { + Next(!bPrev); + Next(!bPrev); + break; + } + } + } + eCurType = eNextType; + bFirst = false; + } + return current_position_ > -1 ? current_position_ : 0; +} diff --git a/xfa/fde/cfde_texteditengine.h b/xfa/fde/cfde_texteditengine.h new file mode 100644 index 0000000000000000000000000000000000000000..58f77edf31cb27ff665c332a89b216289bd5fd37 --- /dev/null +++ b/xfa/fde/cfde_texteditengine.h @@ -0,0 +1,239 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FDE_CFDE_TEXTEDITENGINE_H_ +#define XFA_FDE_CFDE_TEXTEDITENGINE_H_ + +#include <memory> +#include <utility> +#include <vector> + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/fx_dib.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" + +class CFGAS_GEFont; + +struct FDE_TEXTEDITPIECE { + FDE_TEXTEDITPIECE(); + FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that); + ~FDE_TEXTEDITPIECE(); + + CFX_RectF rtPiece; + int32_t nStart = 0; + int32_t nCount = 0; + int32_t nBidiLevel = 0; + uint32_t dwCharStyles = 0; +}; + +inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE() = default; +inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that) = + default; +inline FDE_TEXTEDITPIECE::~FDE_TEXTEDITPIECE() = default; + +class CFDE_TextEditEngine { + public: + class Iterator { + public: + explicit Iterator(const CFDE_TextEditEngine* engine); + ~Iterator(); + + void Next(bool bPrev); + wchar_t GetChar() const; + void SetAt(size_t nIndex); + size_t FindNextBreakPos(bool bPrev); + bool IsEOF(bool bPrev) const; + + private: + UnownedPtr<const CFDE_TextEditEngine> engine_; + int32_t current_position_; + }; + + class Operation { + public: + virtual ~Operation() = default; + virtual void Redo() const = 0; + virtual void Undo() const = 0; + }; + + class Delegate { + public: + virtual ~Delegate() = default; + virtual void NotifyTextFull() = 0; + virtual void OnCaretChanged() = 0; + virtual void OnTextChanged(const WideString& prevText) = 0; + virtual void OnSelChanged() = 0; + virtual bool OnValidate(const WideString& wsText) = 0; + virtual void SetScrollOffset(float fScrollOffset) = 0; + }; + + enum class RecordOperation { + kInsertRecord, + kSkipRecord, + }; + + CFDE_TextEditEngine(); + ~CFDE_TextEditEngine(); + + void SetDelegate(Delegate* delegate) { delegate_ = delegate; } + void Clear(); + + void Insert(size_t idx, + const WideString& text, + RecordOperation add_operation = RecordOperation::kInsertRecord); + WideString Delete( + size_t start_idx, + size_t length, + RecordOperation add_operation = RecordOperation::kInsertRecord); + WideString GetText() const; + size_t GetLength() const; + + // Non-const so we can force a layout. + CFX_RectF GetContentsBoundingBox(); + void SetAvailableWidth(size_t width); + + void SetFont(RetainPtr<CFGAS_GEFont> font); + RetainPtr<CFGAS_GEFont> GetFont() const; + void SetFontSize(float size); + float GetFontSize() const { return font_size_; } + void SetFontColor(FX_ARGB color) { font_color_ = color; } + FX_ARGB GetFontColor() const { return font_color_; } + float GetFontAscent() const; + + void SetAlignment(uint32_t alignment); + float GetLineSpace() const { return line_spacing_; } + void SetLineSpace(float space) { line_spacing_ = space; } + void SetAliasChar(wchar_t alias) { password_alias_ = alias; } + void SetHasCharacterLimit(bool limit); + void SetCharacterLimit(size_t limit); + void SetCombText(bool enable); + void SetTabWidth(float width); + void SetVisibleLineCount(size_t lines); + + void EnableValidation(bool val) { validation_enabled_ = val; } + void EnablePasswordMode(bool val) { password_mode_ = val; } + void EnableMultiLine(bool val); + void EnableLineWrap(bool val); + void LimitHorizontalScroll(bool val); + void LimitVerticalScroll(bool val); + + bool CanUndo() const; + bool CanRedo() const; + bool Redo(); + bool Undo(); + void ClearOperationRecords(); + + // This is not const it can trigger a |Layout|. + size_t GetIndexBefore(size_t pos); + size_t GetIndexLeft(size_t pos) const; + size_t GetIndexRight(size_t pos) const; + size_t GetIndexUp(size_t pos) const; + size_t GetIndexDown(size_t pos) const; + size_t GetIndexAtStartOfLine(size_t pos) const; + size_t GetIndexAtEndOfLine(size_t pos) const; + + void SelectAll(); + void SetSelection(size_t start_idx, size_t count); + void ClearSelection(); + bool HasSelection() const { return has_selection_; } + // Returns <start_idx, count> of the selection. + std::pair<size_t, size_t> GetSelection() const { + return {selection_.start_idx, selection_.count}; + } + WideString GetSelectedText() const; + WideString DeleteSelectedText( + RecordOperation add_operation = RecordOperation::kInsertRecord); + void ReplaceSelectedText(const WideString& str); + + void Layout(); + + wchar_t GetChar(size_t idx) const; + // Non-const so we can force a Layout() if needed. + size_t GetWidthOfChar(size_t idx); + // Non-const so we can force a Layout() if needed. + size_t GetIndexForPoint(const CFX_PointF& point); + // <start_idx, count> + std::pair<size_t, size_t> BoundsForWordAt(size_t idx) const; + + // Returns <bidi level, character rect> + std::pair<int32_t, CFX_RectF> GetCharacterInfo(int32_t start_idx); + std::vector<CFX_RectF> GetCharacterRectsInRange(int32_t start_idx, + int32_t count); + + CFX_TxtBreak* GetTextBreak() { return &text_break_; } + + const std::vector<FDE_TEXTEDITPIECE>& GetTextPieces() { + // Force a layout if needed. + Layout(); + return text_piece_info_; + } + + std::vector<FXTEXT_CHARPOS> GetDisplayPos(const FDE_TEXTEDITPIECE& info); + + void SetMaxEditOperationsForTesting(size_t max); + + private: + void SetCombTextWidth(); + void AdjustGap(size_t idx, size_t length); + void RebuildPieces(); + size_t CountCharsExceedingSize(const WideString& str, size_t num_to_check); + void AddOperationRecord(std::unique_ptr<Operation> op); + + bool IsAlignedRight() const { + return !!(character_alignment_ & CFX_TxtLineAlignment_Left); + } + + bool IsAlignedCenter() const { + return !!(character_alignment_ & CFX_TxtLineAlignment_Center); + } + std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE& piece); + + struct Selection { + size_t start_idx; + size_t count; + }; + + CFX_RectF contents_bounding_box_; + UnownedPtr<Delegate> delegate_; + std::vector<FDE_TEXTEDITPIECE> text_piece_info_; + std::vector<size_t> char_widths_; + CFX_TxtBreak text_break_; + RetainPtr<CFGAS_GEFont> font_; + FX_ARGB font_color_; + float font_size_; + float line_spacing_; + std::vector<WideString::CharType> content_; + size_t text_length_; + size_t gap_position_; + size_t gap_size_; + size_t available_width_; + size_t character_limit_; + size_t visible_line_count_; + // Ring buffer of edit operations + std::vector<std::unique_ptr<Operation>> operation_buffer_; + // Next edit operation to undo. + size_t next_operation_index_to_undo_; + // Next index to insert an edit operation into. + size_t next_operation_index_to_insert_; + size_t max_edit_operations_; + uint32_t character_alignment_; + bool has_character_limit_; + bool is_comb_text_; + bool is_dirty_; + bool validation_enabled_; + bool is_multiline_; + bool is_linewrap_enabled_; + bool limit_horizontal_area_; + bool limit_vertical_area_; + bool password_mode_; + wchar_t password_alias_; + bool has_selection_; + Selection selection_; +}; + +#endif // XFA_FDE_CFDE_TEXTEDITENGINE_H_ diff --git a/xfa/fde/cfde_texteditengine_unittest.cpp b/xfa/fde/cfde_texteditengine_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..522e61a01175fc78256eb984808f0d4cd7cf735c --- /dev/null +++ b/xfa/fde/cfde_texteditengine_unittest.cpp @@ -0,0 +1,697 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fde/cfde_texteditengine.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +class CFDE_TextEditEngineTest : public testing::Test { + public: + class Delegate : public CFDE_TextEditEngine::Delegate { + public: + void Reset() { + text_is_full = false; + fail_validation = false; + } + + void NotifyTextFull() override { text_is_full = true; } + + void OnCaretChanged() override {} + void OnTextChanged(const WideString& prevText) override {} + void OnSelChanged() override {} + bool OnValidate(const WideString& wsText) override { + return !fail_validation; + } + void SetScrollOffset(float fScrollOffset) override {} + + bool fail_validation = false; + bool text_is_full = false; + }; + + CFDE_TextEditEngineTest() {} + ~CFDE_TextEditEngineTest() override {} + + void SetUp() override { + font_ = + CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0, GetGlobalFontManager()); + ASSERT(font_.Get() != nullptr); + + engine_ = pdfium::MakeUnique<CFDE_TextEditEngine>(); + engine_->SetFont(font_); + engine_->SetFontSize(12.0f); + } + + void TearDown() override { engine_.reset(); } + + CFDE_TextEditEngine* engine() const { return engine_.get(); } + + private: + RetainPtr<CFGAS_GEFont> font_; + std::unique_ptr<CFDE_TextEditEngine> engine_; +}; + +TEST_F(CFDE_TextEditEngineTest, Insert) { + EXPECT_STREQ(L"", engine()->GetText().c_str()); + + engine()->Insert(0, L""); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + EXPECT_EQ(0U, engine()->GetLength()); + + engine()->Insert(0, L"Hello"); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + EXPECT_EQ(5U, engine()->GetLength()); + + engine()->Insert(5, L" World"); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + EXPECT_EQ(11U, engine()->GetLength()); + + engine()->Insert(5, L" New"); + EXPECT_STREQ(L"Hello New World", engine()->GetText().c_str()); + + engine()->Insert(100, L" Cat"); + EXPECT_STREQ(L"Hello New World Cat", engine()->GetText().c_str()); + + engine()->Clear(); + + engine()->SetHasCharacterLimit(true); + engine()->SetCharacterLimit(5); + engine()->Insert(0, L"Hello"); + + // No delegate + engine()->Insert(5, L" World"); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + + engine()->SetCharacterLimit(8); + engine()->Insert(5, L" World"); + EXPECT_STREQ(L"Hello Wo", engine()->GetText().c_str()); + + engine()->Clear(); + + // With Delegate + auto delegate = pdfium::MakeUnique<CFDE_TextEditEngineTest::Delegate>(); + engine()->SetDelegate(delegate.get()); + + engine()->SetCharacterLimit(5); + engine()->Insert(0, L"Hello"); + + // Insert when full. + engine()->Insert(5, L" World"); + EXPECT_TRUE(delegate->text_is_full); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + delegate->Reset(); + + engine()->SetCharacterLimit(8); + engine()->Insert(5, L" World"); + EXPECT_TRUE(delegate->text_is_full); + EXPECT_STREQ(L"Hello Wo", engine()->GetText().c_str()); + delegate->Reset(); + engine()->SetHasCharacterLimit(false); + + engine()->Clear(); + engine()->Insert(0, L"Hello"); + + // Insert Invalid text + delegate->fail_validation = true; + engine()->EnableValidation(true); + engine()->Insert(5, L" World"); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + + delegate->fail_validation = false; + engine()->Insert(5, L" World"); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + engine()->EnableValidation(false); + + engine()->Clear(); + + engine()->Insert(0, L"Hello\nWorld"); + EXPECT_FALSE(delegate->text_is_full); + EXPECT_STREQ(L"Hello\nWorld", engine()->GetText().c_str()); + delegate->Reset(); + engine()->Clear(); + + // Insert with limited area and over-fill + engine()->LimitHorizontalScroll(true); + engine()->SetAvailableWidth(60.0f); // Fits 'Hello Wo'. + engine()->Insert(0, L"Hello"); + EXPECT_FALSE(delegate->text_is_full); + engine()->Insert(5, L" World"); + EXPECT_TRUE(delegate->text_is_full); + EXPECT_STREQ(L"Hello Wo", engine()->GetText().c_str()); + engine()->LimitHorizontalScroll(false); + + delegate->Reset(); + engine()->Clear(); + + engine()->SetLineSpace(12.0f); + engine()->LimitVerticalScroll(true); + // Default is one line of text. + engine()->Insert(0, L"Hello"); + EXPECT_FALSE(delegate->text_is_full); + engine()->Insert(5, L" Wo\nrld"); + EXPECT_TRUE(delegate->text_is_full); + EXPECT_STREQ(L"Hello Wo\n", engine()->GetText().c_str()); + engine()->LimitVerticalScroll(false); + + engine()->SetDelegate(nullptr); +} + +TEST_F(CFDE_TextEditEngineTest, Delete) { + EXPECT_STREQ(L"", engine()->Delete(0, 50).c_str()); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + + engine()->Insert(0, L"Hello World"); + EXPECT_STREQ(L" World", engine()->Delete(5, 6).c_str()); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello World"); + EXPECT_STREQ(L" ", engine()->Delete(5, 1).c_str()); + EXPECT_STREQ(L"HelloWorld", engine()->GetText().c_str()); + + EXPECT_STREQ(L"elloWorld", engine()->Delete(1, 50).c_str()); + EXPECT_STREQ(L"H", engine()->GetText().c_str()); +} + +TEST_F(CFDE_TextEditEngineTest, Clear) { + EXPECT_STREQ(L"", engine()->GetText().c_str()); + + engine()->Clear(); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + + engine()->Insert(0, L"Hello World"); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + + engine()->Clear(); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + EXPECT_EQ(0U, engine()->GetLength()); +} + +TEST_F(CFDE_TextEditEngineTest, GetChar) { + // Out of bounds. + EXPECT_EQ(L'\0', engine()->GetChar(0)); + + engine()->Insert(0, L"Hello World"); + EXPECT_EQ(L'H', engine()->GetChar(0)); + EXPECT_EQ(L'd', engine()->GetChar(engine()->GetLength() - 1)); + EXPECT_EQ(L' ', engine()->GetChar(5)); + + engine()->Insert(5, L" A"); + EXPECT_STREQ(L"Hello A World", engine()->GetText().c_str()); + EXPECT_EQ(L'W', engine()->GetChar(8)); + + engine()->EnablePasswordMode(true); + EXPECT_EQ(L'*', engine()->GetChar(8)); + + engine()->SetAliasChar(L'+'); + EXPECT_EQ(L'+', engine()->GetChar(8)); +} + +TEST_F(CFDE_TextEditEngineTest, GetWidthOfChar) { + // Out of Bounds. + EXPECT_EQ(0U, engine()->GetWidthOfChar(0)); + + engine()->Insert(0, L"Hello World"); + EXPECT_EQ(199920U, engine()->GetWidthOfChar(0)); + EXPECT_EQ(159840U, engine()->GetWidthOfChar(1)); + + engine()->Insert(0, L"\t"); + EXPECT_EQ(0U, engine()->GetWidthOfChar(0)); +} + +TEST_F(CFDE_TextEditEngineTest, GetDisplayPos) { + EXPECT_EQ(0U, engine()->GetDisplayPos(FDE_TEXTEDITPIECE()).size()); +} + +TEST_F(CFDE_TextEditEngineTest, Selection) { + EXPECT_FALSE(engine()->HasSelection()); + engine()->SelectAll(); + EXPECT_FALSE(engine()->HasSelection()); + + engine()->Insert(0, L"Hello World"); + EXPECT_STREQ(L"", engine()->DeleteSelectedText().c_str()); + + EXPECT_FALSE(engine()->HasSelection()); + engine()->SelectAll(); + EXPECT_TRUE(engine()->HasSelection()); + EXPECT_STREQ(L"Hello World", engine()->GetSelectedText().c_str()); + + engine()->ClearSelection(); + EXPECT_FALSE(engine()->HasSelection()); + EXPECT_STREQ(L"", engine()->GetSelectedText().c_str()); + + engine()->SelectAll(); + size_t start_idx; + size_t count; + std::tie(start_idx, count) = engine()->GetSelection(); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(11U, count); + + // Selection before gap. + EXPECT_STREQ(L"Hello World", engine()->GetSelectedText().c_str()); + EXPECT_TRUE(engine()->HasSelection()); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + + engine()->Insert(5, L" A"); + EXPECT_FALSE(engine()->HasSelection()); + EXPECT_STREQ(L"", engine()->GetSelectedText().c_str()); + + // Selection over the gap. + engine()->SelectAll(); + EXPECT_TRUE(engine()->HasSelection()); + EXPECT_STREQ(L"Hello A World", engine()->GetSelectedText().c_str()); + engine()->Clear(); + + engine()->Insert(0, L"Hello World"); + engine()->SelectAll(); + + EXPECT_STREQ(L"Hello World", engine()->DeleteSelectedText().c_str()); + EXPECT_FALSE(engine()->HasSelection()); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + + engine()->Insert(0, L"Hello World"); + engine()->SetSelection(5, 5); + EXPECT_STREQ(L" Worl", engine()->DeleteSelectedText().c_str()); + EXPECT_FALSE(engine()->HasSelection()); + EXPECT_STREQ(L"Hellod", engine()->GetText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello World"); + engine()->SelectAll(); + engine()->ReplaceSelectedText(L"Goodbye Everybody"); + EXPECT_FALSE(engine()->HasSelection()); + EXPECT_STREQ(L"Goodbye Everybody", engine()->GetText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello World"); + engine()->SetSelection(1, 4); + engine()->ReplaceSelectedText(L"i,"); + EXPECT_FALSE(engine()->HasSelection()); + EXPECT_STREQ(L"Hi, World", engine()->GetText().c_str()); + + // Selection fully after gap. + engine()->Clear(); + engine()->Insert(0, L"Hello"); + engine()->Insert(0, L"A "); + engine()->SetSelection(3, 6); + EXPECT_STREQ(L"ello", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello World"); + engine()->ClearSelection(); + engine()->DeleteSelectedText(); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); +} + +TEST_F(CFDE_TextEditEngineTest, UndoRedo) { + EXPECT_FALSE(engine()->CanUndo()); + EXPECT_FALSE(engine()->CanRedo()); + EXPECT_FALSE(engine()->Undo()); + EXPECT_FALSE(engine()->Redo()); + + engine()->Insert(0, L"Hello"); + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_FALSE(engine()->CanRedo()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + EXPECT_FALSE(engine()->CanUndo()); + EXPECT_TRUE(engine()->CanRedo()); + EXPECT_TRUE(engine()->Redo()); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_FALSE(engine()->CanRedo()); + + engine()->Clear(); + EXPECT_FALSE(engine()->CanUndo()); + EXPECT_FALSE(engine()->CanRedo()); + + engine()->Insert(0, L"Hello World"); + engine()->SelectAll(); + engine()->DeleteSelectedText(); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanRedo()); + EXPECT_TRUE(engine()->Redo()); + EXPECT_STREQ(L"", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_FALSE(engine()->CanRedo()); + + engine()->Insert(0, L"Hello World"); + engine()->SelectAll(); + engine()->ReplaceSelectedText(L"Goodbye Friend"); + EXPECT_STREQ(L"Goodbye Friend", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanRedo()); + EXPECT_TRUE(engine()->Redo()); + EXPECT_STREQ(L"Goodbye Friend", engine()->GetText().c_str()); + + engine()->Clear(); + engine()->SetMaxEditOperationsForTesting(3); + engine()->Insert(0, L"First "); + engine()->Insert(engine()->GetLength(), L"Second "); + engine()->Insert(engine()->GetLength(), L"Third"); + + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"First Second ", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->CanUndo()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_FALSE( + engine()->CanUndo()); // Can't undo First; undo buffer too small. + EXPECT_STREQ(L"First ", engine()->GetText().c_str()); + + EXPECT_TRUE(engine()->CanRedo()); + EXPECT_TRUE(engine()->Redo()); + EXPECT_TRUE(engine()->CanRedo()); + EXPECT_TRUE(engine()->Redo()); + EXPECT_FALSE(engine()->CanRedo()); + EXPECT_STREQ(L"First Second Third", engine()->GetText().c_str()); + + engine()->Clear(); + + engine()->SetMaxEditOperationsForTesting(4); + + // Go beyond the max operations limit. + engine()->Insert(0, L"H"); + engine()->Insert(1, L"e"); + engine()->Insert(2, L"l"); + engine()->Insert(3, L"l"); + engine()->Insert(4, L"o"); + engine()->Insert(5, L" World"); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + + // Do A, undo. Do B, undo. Redo should cause B. + engine()->Delete(4, 3); + EXPECT_STREQ(L"Hellorld", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + engine()->Delete(5, 6); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->Redo()); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + + // Undo down to the limit. + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hello World", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hello", engine()->GetText().c_str()); + EXPECT_TRUE(engine()->Undo()); + EXPECT_STREQ(L"Hell", engine()->GetText().c_str()); + EXPECT_FALSE(engine()->Undo()); + EXPECT_STREQ(L"Hell", engine()->GetText().c_str()); +} + +TEST_F(CFDE_TextEditEngineTest, GetIndexForPoint) { + engine()->SetFontSize(10.0f); + engine()->Insert(0, L"Hello World"); + EXPECT_EQ(0U, engine()->GetIndexForPoint({0.0f, 0.0f})); + EXPECT_EQ(11U, engine()->GetIndexForPoint({999999.0f, 9999999.0f})); + EXPECT_EQ(1U, engine()->GetIndexForPoint({10.0f, 5.0f})); +} + +TEST_F(CFDE_TextEditEngineTest, BoundsForWordAt) { + size_t start_idx; + size_t count; + + std::tie(start_idx, count) = engine()->BoundsForWordAt(100); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(0U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(0); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(5U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"Hello", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello World"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(100); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(0U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(0); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(5U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"Hello", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(1); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(5U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"Hello", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(4); + EXPECT_EQ(0U, start_idx); + EXPECT_EQ(5U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"Hello", engine()->GetSelectedText().c_str()); + + // Select the space + std::tie(start_idx, count) = engine()->BoundsForWordAt(5); + EXPECT_EQ(5U, start_idx); + EXPECT_EQ(1U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L" ", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(6); + EXPECT_EQ(6U, start_idx); + EXPECT_EQ(5U, count); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"123 456 789"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(5); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"456", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"123def789"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(5); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"123def789", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"abc456ghi"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(5); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"abc456ghi", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"hello, world"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(0); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"hello", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"hello, world"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(5); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L",", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"np-complete"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(6); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"complete", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"(123) 456-7890"); + std::tie(start_idx, count) = engine()->BoundsForWordAt(0); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"(", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(1); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"123", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(7); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"456", engine()->GetSelectedText().c_str()); + + std::tie(start_idx, count) = engine()->BoundsForWordAt(11); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(L"7890", engine()->GetSelectedText().c_str()); + + // Tests from: + // http://unicode.org/Public/UNIDATA/auxiliary/WordBreakTest.html#samples + struct bounds { + size_t start; + size_t end; + }; + struct { + const wchar_t* str; + std::vector<const wchar_t*> results; + } tests[] = { + // {L"\r\na\n\u0308", {L"\r\n", L"a", L"\n", L"\u0308"}}, + // {L"a\u0308", {L"a\u0308"}}, + // {L" \u200d\u0646", {L" \u200d", L"\u0646"}}, + // {L"\u0646\u200d ", {L"\u0646\u200d", L" "}}, + {L"AAA", {L"AAA"}}, + {L"A:A", {L"A:A"}}, + {L"A::A", {L"A", L":", L":", L"A"}}, + // {L"\u05d0'", {L"\u05d0'"}}, + // {L"\u05d0\"\u05d0", {L"\u05d0\"\u05d0"}}, + {L"A00A", {L"A00A"}}, + {L"0,0", {L"0,0"}}, + {L"0,,0", {L"0", L",", L",", L"0"}}, + {L"\u3031\u3031", {L"\u3031\u3031"}}, + {L"A_0_\u3031_", {L"A_0_\u3031_"}}, + {L"A__A", {L"A__A"}}, + // {L"\u200d\u2640", {L"\u200d\u2640"}}, + // {L"a\u0308\u200b\u0308b", {L"a\u0308\u200b\u0308b"}}, + }; + + for (auto t : tests) { + engine()->Clear(); + engine()->Insert(0, t.str); + + size_t idx = 0; + for (const auto* res : t.results) { + std::tie(start_idx, count) = engine()->BoundsForWordAt(idx); + engine()->SetSelection(start_idx, count); + EXPECT_STREQ(res, engine()->GetSelectedText().c_str()) + << "Input: '" << t.str << "'"; + idx += count; + } + } +} + +TEST_F(CFDE_TextEditEngineTest, CursorMovement) { + engine()->Clear(); + engine()->Insert(0, L"Hello"); + + EXPECT_EQ(0U, engine()->GetIndexLeft(0)); + EXPECT_EQ(5U, engine()->GetIndexRight(5)); + EXPECT_EQ(2U, engine()->GetIndexUp(2)); + EXPECT_EQ(2U, engine()->GetIndexDown(2)); + EXPECT_EQ(1U, engine()->GetIndexLeft(2)); + EXPECT_EQ(1U, engine()->GetIndexBefore(2)); + EXPECT_EQ(3U, engine()->GetIndexRight(2)); + EXPECT_EQ(0U, engine()->GetIndexAtStartOfLine(2)); + EXPECT_EQ(5U, engine()->GetIndexAtEndOfLine(2)); + + engine()->Clear(); + engine()->Insert(0, L"The book is \"مدخل إلى C++\""); + EXPECT_EQ(2U, engine()->GetIndexBefore(3)); // Before is to left. + EXPECT_EQ(16U, engine()->GetIndexBefore(15)); // Before is to right. + EXPECT_EQ(22U, engine()->GetIndexBefore(23)); // Before is to left. + + engine()->Clear(); + engine()->Insert(0, L"Hello\r\nWorld\r\nTest"); + // Move to end of Hello from start of World. + engine()->SetSelection(engine()->GetIndexBefore(7U), 7); + EXPECT_STREQ(L"\r\nWorld", engine()->GetSelectedText().c_str()); + + // Second letter in Hello from second letter in World. + engine()->SetSelection(engine()->GetIndexUp(8U), 2); + EXPECT_STREQ(L"el", engine()->GetSelectedText().c_str()); + + // Second letter in World from second letter in Test. + engine()->SetSelection(engine()->GetIndexUp(15U), 2); + EXPECT_STREQ(L"or", engine()->GetSelectedText().c_str()); + + // Second letter in World from second letter in Hello. + engine()->SetSelection(engine()->GetIndexDown(1U), 2); + EXPECT_STREQ(L"or", engine()->GetSelectedText().c_str()); + + // Second letter in Test from second letter in World. + engine()->SetSelection(engine()->GetIndexDown(8U), 2); + EXPECT_STREQ(L"es", engine()->GetSelectedText().c_str()); + + size_t start_idx = engine()->GetIndexAtStartOfLine(8U); + size_t end_idx = engine()->GetIndexAtEndOfLine(8U); + engine()->SetSelection(start_idx, end_idx - start_idx); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); + + // Move past \r\n to before W. + engine()->SetSelection(engine()->GetIndexRight(5U), 5); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Short\nAnd a very long line"); + engine()->SetSelection(engine()->GetIndexUp(14U), 11); + EXPECT_STREQ(L"\nAnd a very", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"A Very long line\nShort"); + EXPECT_EQ(engine()->GetLength(), engine()->GetIndexDown(8U)); + + engine()->Clear(); + engine()->Insert(0, L"Hello\rWorld\rTest"); + // Move to end of Hello from start of World. + engine()->SetSelection(engine()->GetIndexBefore(6U), 6); + EXPECT_STREQ(L"\rWorld", engine()->GetSelectedText().c_str()); + + // Second letter in Hello from second letter in World. + engine()->SetSelection(engine()->GetIndexUp(7U), 2); + EXPECT_STREQ(L"el", engine()->GetSelectedText().c_str()); + + // Second letter in World from second letter in Test. + engine()->SetSelection(engine()->GetIndexUp(13U), 2); + EXPECT_STREQ(L"or", engine()->GetSelectedText().c_str()); + + // Second letter in World from second letter in Hello. + engine()->SetSelection(engine()->GetIndexDown(1U), 2); + EXPECT_STREQ(L"or", engine()->GetSelectedText().c_str()); + + // Second letter in Test from second letter in World. + engine()->SetSelection(engine()->GetIndexDown(7U), 2); + EXPECT_STREQ(L"es", engine()->GetSelectedText().c_str()); + + start_idx = engine()->GetIndexAtStartOfLine(7U); + end_idx = engine()->GetIndexAtEndOfLine(7U); + engine()->SetSelection(start_idx, end_idx - start_idx); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); + + // Move past \r to before W. + engine()->SetSelection(engine()->GetIndexRight(5U), 5); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); + + engine()->Clear(); + engine()->Insert(0, L"Hello\nWorld\nTest"); + // Move to end of Hello from start of World. + engine()->SetSelection(engine()->GetIndexBefore(6U), 6); + EXPECT_STREQ(L"\nWorld", engine()->GetSelectedText().c_str()); + + // Second letter in Hello from second letter in World. + engine()->SetSelection(engine()->GetIndexUp(7U), 2); + EXPECT_STREQ(L"el", engine()->GetSelectedText().c_str()); + + // Second letter in World from second letter in Test. + engine()->SetSelection(engine()->GetIndexUp(13U), 2); + EXPECT_STREQ(L"or", engine()->GetSelectedText().c_str()); + + // Second letter in World from second letter in Hello. + engine()->SetSelection(engine()->GetIndexDown(1U), 2); + EXPECT_STREQ(L"or", engine()->GetSelectedText().c_str()); + + // Second letter in Test from second letter in World. + engine()->SetSelection(engine()->GetIndexDown(7U), 2); + EXPECT_STREQ(L"es", engine()->GetSelectedText().c_str()); + + start_idx = engine()->GetIndexAtStartOfLine(7U); + end_idx = engine()->GetIndexAtEndOfLine(7U); + engine()->SetSelection(start_idx, end_idx - start_idx); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); + + // Move past \r to before W. + engine()->SetSelection(engine()->GetIndexRight(5U), 5); + EXPECT_STREQ(L"World", engine()->GetSelectedText().c_str()); +} diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19e7ae69343085e5c40e0957b63f46fb889699a4 --- /dev/null +++ b/xfa/fde/cfde_textout.cpp @@ -0,0 +1,569 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fde/cfde_textout.h" + +#include <algorithm> +#include <utility> + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/cfx_font.h" +#include "core/fxge/cfx_pathdata.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" + +namespace { + +bool TextAlignmentVerticallyCentered(const FDE_TextAlignment align) { + return align == FDE_TextAlignment::kCenterLeft || + align == FDE_TextAlignment::kCenter || + align == FDE_TextAlignment::kCenterRight; +} + +bool IsTextAlignmentTop(const FDE_TextAlignment align) { + return align == FDE_TextAlignment::kTopLeft; +} + +} // namespace + +// static +bool CFDE_TextOut::DrawString(CFX_RenderDevice* device, + FX_ARGB color, + const RetainPtr<CFGAS_GEFont>& pFont, + FXTEXT_CHARPOS* pCharPos, + int32_t iCount, + float fFontSize, + const CFX_Matrix* pMatrix) { + ASSERT(pFont && pCharPos && iCount > 0); + + CFX_Font* pFxFont = pFont->GetDevFont(); + if (FontStyleIsItalic(pFont->GetFontStyles()) && !pFxFont->IsItalic()) { + for (int32_t i = 0; i < iCount; ++i) { + static const float mc = 0.267949f; + float* pAM = pCharPos->m_AdjustMatrix; + pAM[2] = mc * pAM[0] + pAM[2]; + pAM[3] = mc * pAM[1] + pAM[3]; + ++pCharPos; + } + } + +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + uint32_t dwFontStyle = pFont->GetFontStyles(); + CFX_Font FxFont; + auto SubstFxFont = pdfium::MakeUnique<CFX_SubstFont>(); + SubstFxFont->m_Weight = FontStyleIsBold(dwFontStyle) ? 700 : 400; + SubstFxFont->m_ItalicAngle = FontStyleIsItalic(dwFontStyle) ? -12 : 0; + SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight; + SubstFxFont->m_bItalicCJK = FontStyleIsItalic(dwFontStyle); + FxFont.SetSubstFont(std::move(SubstFxFont)); +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + + RetainPtr<CFGAS_GEFont> pCurFont; + FXTEXT_CHARPOS* pCurCP = nullptr; + int32_t iCurCount = 0; + for (int32_t i = 0; i < iCount; ++i) { + RetainPtr<CFGAS_GEFont> pSTFont = + pFont->GetSubstFont(static_cast<int32_t>(pCharPos->m_GlyphIndex)); + pCharPos->m_GlyphIndex &= 0x00FFFFFF; + pCharPos->m_bFontStyle = false; + if (pCurFont != pSTFont) { + if (pCurFont) { + pFxFont = pCurFont->GetDevFont(); + + CFX_Font* font; +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + FxFont.SetFace(pFxFont->GetFace()); + font = &FxFont; +#else + font = pFxFont; +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + + device->DrawNormalText(iCurCount, pCurCP, font, -fFontSize, pMatrix, + color, FXTEXT_CLEARTYPE); + } + pCurFont = pSTFont; + pCurCP = pCharPos; + iCurCount = 1; + } else { + ++iCurCount; + } + ++pCharPos; + } + + bool bRet = true; + if (pCurFont && iCurCount) { + pFxFont = pCurFont->GetDevFont(); + CFX_Font* font; +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + FxFont.SetFace(pFxFont->GetFace()); + font = &FxFont; +#else + font = pFxFont; +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + + bRet = device->DrawNormalText(iCurCount, pCurCP, font, -fFontSize, pMatrix, + color, FXTEXT_CLEARTYPE); + } + +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + FxFont.SetFace(nullptr); +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + + return bRet; +} + +FDE_TTOPIECE::FDE_TTOPIECE() = default; + +FDE_TTOPIECE::FDE_TTOPIECE(const FDE_TTOPIECE& that) = default; + +FDE_TTOPIECE::~FDE_TTOPIECE() = default; + +CFDE_TextOut::CFDE_TextOut() + : m_pTxtBreak(pdfium::MakeUnique<CFX_TxtBreak>()), + m_pFont(nullptr), + m_fFontSize(12.0f), + m_fLineSpace(m_fFontSize), + m_fLinePos(0.0f), + m_fTolerance(0.0f), + m_iAlignment(FDE_TextAlignment::kTopLeft), + m_TxtColor(0xFF000000), + m_dwTxtBkStyles(0), + m_ttoLines(5), + m_iCurLine(0), + m_iCurPiece(0), + m_iTotalLines(0) {} + +CFDE_TextOut::~CFDE_TextOut() {} + +void CFDE_TextOut::SetFont(const RetainPtr<CFGAS_GEFont>& pFont) { + ASSERT(pFont); + m_pFont = pFont; + m_pTxtBreak->SetFont(pFont); +} + +void CFDE_TextOut::SetFontSize(float fFontSize) { + ASSERT(fFontSize > 0); + m_fFontSize = fFontSize; + m_pTxtBreak->SetFontSize(fFontSize); +} + +void CFDE_TextOut::SetStyles(const FDE_TextStyle& dwStyles) { + m_Styles = dwStyles; + + m_dwTxtBkStyles = 0; + if (m_Styles.single_line_) + m_dwTxtBkStyles |= FX_LAYOUTSTYLE_SingleLine; + + m_pTxtBreak->SetLayoutStyles(m_dwTxtBkStyles); +} + +void CFDE_TextOut::SetAlignment(FDE_TextAlignment iAlignment) { + m_iAlignment = iAlignment; + + int32_t txtBreakAlignment = 0; + switch (m_iAlignment) { + case FDE_TextAlignment::kCenter: + txtBreakAlignment = CFX_TxtLineAlignment_Center; + break; + case FDE_TextAlignment::kCenterRight: + txtBreakAlignment = CFX_TxtLineAlignment_Right; + break; + case FDE_TextAlignment::kCenterLeft: + case FDE_TextAlignment::kTopLeft: + txtBreakAlignment = CFX_TxtLineAlignment_Left; + break; + } + m_pTxtBreak->SetAlignment(txtBreakAlignment); +} + +void CFDE_TextOut::SetLineSpace(float fLineSpace) { + ASSERT(fLineSpace > 1.0f); + m_fLineSpace = fLineSpace; +} + +void CFDE_TextOut::SetLineBreakTolerance(float fTolerance) { + m_fTolerance = fTolerance; + m_pTxtBreak->SetLineBreakTolerance(m_fTolerance); +} + +void CFDE_TextOut::CalcLogicSize(const WideString& str, CFX_SizeF& size) { + CFX_RectF rtText(0.0f, 0.0f, size.width, size.height); + CalcLogicSize(str, rtText); + size = rtText.Size(); +} + +void CFDE_TextOut::CalcLogicSize(const WideString& str, CFX_RectF& rect) { + if (str.IsEmpty()) { + rect.width = 0.0f; + rect.height = 0.0f; + return; + } + + ASSERT(m_pFont && m_fFontSize >= 1.0f); + + if (!m_Styles.single_line_) { + if (rect.Width() < 1.0f) + rect.width = m_fFontSize * 1000.0f; + + m_pTxtBreak->SetLineWidth(rect.Width()); + } + + m_iTotalLines = 0; + float fWidth = 0.0f; + float fHeight = 0.0f; + float fStartPos = rect.right(); + CFX_BreakType dwBreakStatus = CFX_BreakType::None; + bool break_char_is_set = false; + for (const wchar_t& wch : str) { + if (!break_char_is_set && (wch == L'\n' || wch == L'\r')) { + break_char_is_set = true; + m_pTxtBreak->SetParagraphBreakChar(wch); + } + dwBreakStatus = m_pTxtBreak->AppendChar(wch); + if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) + RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight); + } + + dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph); + if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) + RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight); + + m_pTxtBreak->Reset(); + float fInc = rect.Height() - fHeight; + if (TextAlignmentVerticallyCentered(m_iAlignment)) + fInc /= 2.0f; + else if (IsTextAlignmentTop(m_iAlignment)) + fInc = 0.0f; + + rect.left += fStartPos; + rect.top += fInc; + rect.width = std::min(fWidth, rect.Width()); + rect.height = fHeight; + if (m_Styles.last_line_height_) + rect.height -= m_fLineSpace - m_fFontSize; +} + +bool CFDE_TextOut::RetrieveLineWidth(CFX_BreakType dwBreakStatus, + float& fStartPos, + float& fWidth, + float& fHeight) { + if (CFX_BreakTypeNoneOrPiece(dwBreakStatus)) + return false; + + float fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; + float fLineWidth = 0.0f; + for (int32_t i = 0; i < m_pTxtBreak->CountBreakPieces(); i++) { + const CFX_BreakPiece* pPiece = m_pTxtBreak->GetBreakPieceUnstable(i); + fLineWidth += static_cast<float>(pPiece->m_iWidth) / 20000.0f; + fStartPos = + std::min(fStartPos, static_cast<float>(pPiece->m_iStartPos) / 20000.0f); + } + m_pTxtBreak->ClearBreakPieces(); + + if (dwBreakStatus == CFX_BreakType::Paragraph) + m_pTxtBreak->Reset(); + if (!m_Styles.line_wrap_ && dwBreakStatus == CFX_BreakType::Line) { + fWidth += fLineWidth; + } else { + fWidth = std::max(fWidth, fLineWidth); + fHeight += fLineStep; + } + ++m_iTotalLines; + return true; +} + +void CFDE_TextOut::DrawLogicText(CFX_RenderDevice* device, + const WideStringView& str, + const CFX_RectF& rect) { + ASSERT(m_pFont && m_fFontSize >= 1.0f); + + if (str.IsEmpty()) + return; + if (rect.width < m_fFontSize || rect.height < m_fFontSize) + return; + + float fLineWidth = rect.width; + m_pTxtBreak->SetLineWidth(fLineWidth); + m_ttoLines.clear(); + m_wsText.clear(); + + LoadText(WideString(str), rect); + Reload(rect); + DoAlignment(rect); + + if (!device || m_ttoLines.empty()) + return; + + CFX_RectF rtClip = m_Matrix.TransformRect(CFX_RectF()); + device->SaveState(); + if (rtClip.Width() > 0.0f && rtClip.Height() > 0.0f) + device->SetClip_Rect(rtClip); + + for (auto& line : m_ttoLines) { + int32_t iPieces = line.GetSize(); + for (int32_t j = 0; j < iPieces; j++) { + FDE_TTOPIECE* pPiece = line.GetPtrAt(j); + if (!pPiece) + continue; + + int32_t iCount = GetDisplayPos(pPiece); + if (iCount > 0) { + CFDE_TextOut::DrawString(device, m_TxtColor, m_pFont, m_CharPos.data(), + iCount, m_fFontSize, &m_Matrix); + } + } + } + device->RestoreState(false); +} + +void CFDE_TextOut::LoadText(const WideString& str, const CFX_RectF& rect) { + ASSERT(!str.IsEmpty()); + + m_wsText = str; + + if (pdfium::CollectionSize<size_t>(m_CharWidths) < str.GetLength()) + m_CharWidths.resize(str.GetLength(), 0); + + float fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; + float fLineStop = rect.bottom(); + m_fLinePos = rect.top; + int32_t iStartChar = 0; + int32_t iPieceWidths = 0; + CFX_BreakType dwBreakStatus; + bool bRet = false; + for (const auto& wch : str) { + dwBreakStatus = m_pTxtBreak->AppendChar(wch); + if (CFX_BreakTypeNoneOrPiece(dwBreakStatus)) + continue; + + bool bEndofLine = + RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, false, rect); + if (bEndofLine && + (m_Styles.line_wrap_ || dwBreakStatus == CFX_BreakType::Paragraph || + dwBreakStatus == CFX_BreakType::Page)) { + iPieceWidths = 0; + ++m_iCurLine; + m_fLinePos += fLineStep; + } + if (m_fLinePos + fLineStep > fLineStop) { + int32_t iCurLine = bEndofLine ? m_iCurLine - 1 : m_iCurLine; + m_ttoLines[iCurLine].SetNewReload(true); + bRet = true; + break; + } + } + + dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph); + if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus) && !bRet) + RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, false, rect); + + m_pTxtBreak->ClearBreakPieces(); + m_pTxtBreak->Reset(); +} + +bool CFDE_TextOut::RetrievePieces(CFX_BreakType dwBreakStatus, + int32_t& iStartChar, + int32_t& iPieceWidths, + bool bReload, + const CFX_RectF& rect) { + float fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; + bool bNeedReload = false; + int32_t iLineWidth = FXSYS_round(rect.Width() * 20000.0f); + int32_t iCount = m_pTxtBreak->CountBreakPieces(); + for (int32_t i = 0; i < iCount; i++) { + const CFX_BreakPiece* pPiece = m_pTxtBreak->GetBreakPieceUnstable(i); + int32_t iPieceChars = pPiece->GetLength(); + int32_t iChar = iStartChar; + int32_t iWidth = 0; + int32_t j = 0; + for (; j < iPieceChars; j++) { + const CFX_Char* pTC = pPiece->GetChar(j); + int32_t iCurCharWidth = pTC->m_iCharWidth > 0 ? pTC->m_iCharWidth : 0; + if (m_Styles.single_line_ || !m_Styles.line_wrap_) { + if (iLineWidth - iPieceWidths - iWidth < iCurCharWidth) { + bNeedReload = true; + break; + } + } + iWidth += iCurCharWidth; + m_CharWidths[iChar++] = iCurCharWidth; + } + + if (j == 0 && !bReload) { + m_ttoLines[m_iCurLine].SetNewReload(true); + } else if (j > 0) { + FDE_TTOPIECE ttoPiece; + ttoPiece.iStartChar = iStartChar; + ttoPiece.iChars = j; + ttoPiece.dwCharStyles = pPiece->m_dwCharStyles; + ttoPiece.rtPiece = CFX_RectF( + rect.left + static_cast<float>(pPiece->m_iStartPos) / 20000.0f, + m_fLinePos, iWidth / 20000.0f, fLineStep); + + if (FX_IsOdd(pPiece->m_iBidiLevel)) + ttoPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; + + AppendPiece(ttoPiece, bNeedReload, (bReload && i == iCount - 1)); + } + iStartChar += iPieceChars; + iPieceWidths += iWidth; + } + m_pTxtBreak->ClearBreakPieces(); + + return m_Styles.single_line_ || m_Styles.line_wrap_ || bNeedReload || + dwBreakStatus == CFX_BreakType::Paragraph; +} + +void CFDE_TextOut::AppendPiece(const FDE_TTOPIECE& ttoPiece, + bool bNeedReload, + bool bEnd) { + if (m_iCurLine >= pdfium::CollectionSize<int32_t>(m_ttoLines)) { + CFDE_TTOLine ttoLine; + ttoLine.SetNewReload(bNeedReload); + + m_iCurPiece = ttoLine.AddPiece(m_iCurPiece, ttoPiece); + m_ttoLines.push_back(ttoLine); + m_iCurLine = pdfium::CollectionSize<int32_t>(m_ttoLines) - 1; + } else { + CFDE_TTOLine* pLine = &m_ttoLines[m_iCurLine]; + pLine->SetNewReload(bNeedReload); + + m_iCurPiece = pLine->AddPiece(m_iCurPiece, ttoPiece); + if (bEnd) { + int32_t iPieces = pLine->GetSize(); + if (m_iCurPiece < iPieces) + pLine->RemoveLast(iPieces - m_iCurPiece - 1); + } + } + if (!bEnd && bNeedReload) + m_iCurPiece = 0; +} + +void CFDE_TextOut::Reload(const CFX_RectF& rect) { + int i = 0; + for (auto& line : m_ttoLines) { + if (line.GetNewReload()) { + m_iCurLine = i; + m_iCurPiece = 0; + ReloadLinePiece(&line, rect); + } + ++i; + } +} + +void CFDE_TextOut::ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect) { + const wchar_t* pwsStr = m_wsText.c_str(); + int32_t iPieceWidths = 0; + + FDE_TTOPIECE* pPiece = pLine->GetPtrAt(0); + int32_t iStartChar = pPiece->iStartChar; + int32_t iPieceCount = pLine->GetSize(); + int32_t iPieceIndex = 0; + CFX_BreakType dwBreakStatus = CFX_BreakType::None; + m_fLinePos = pPiece->rtPiece.top; + while (iPieceIndex < iPieceCount) { + int32_t iStar = iStartChar; + int32_t iEnd = pPiece->iChars + iStar; + while (iStar < iEnd) { + dwBreakStatus = m_pTxtBreak->AppendChar(*(pwsStr + iStar)); + if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) + RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, true, rect); + + ++iStar; + } + ++iPieceIndex; + pPiece = pLine->GetPtrAt(iPieceIndex); + } + + dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph); + if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) + RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, true, rect); + + m_pTxtBreak->Reset(); +} + +void CFDE_TextOut::DoAlignment(const CFX_RectF& rect) { + if (m_ttoLines.empty()) + return; + + FDE_TTOPIECE* pFirstPiece = m_ttoLines.back().GetPtrAt(0); + if (!pFirstPiece) + return; + + float fInc = rect.bottom() - pFirstPiece->rtPiece.bottom(); + if (TextAlignmentVerticallyCentered(m_iAlignment)) + fInc /= 2.0f; + else if (IsTextAlignmentTop(m_iAlignment)) + fInc = 0.0f; + + if (fInc < 1.0f) + return; + + for (auto& line : m_ttoLines) { + int32_t iPieces = line.GetSize(); + for (int32_t j = 0; j < iPieces; j++) + line.GetPtrAt(j)->rtPiece.top += fInc; + } +} + +int32_t CFDE_TextOut::GetDisplayPos(FDE_TTOPIECE* pPiece) { + ASSERT(pPiece->iChars >= 0); + + if (pdfium::CollectionSize<int32_t>(m_CharPos) < pPiece->iChars) + m_CharPos.resize(pPiece->iChars, FXTEXT_CHARPOS()); + + FX_TXTRUN tr; + tr.wsStr = m_wsText + pPiece->iStartChar; + tr.pWidths = &m_CharWidths[pPiece->iStartChar]; + tr.iLength = pPiece->iChars; + tr.pFont = m_pFont; + tr.fFontSize = m_fFontSize; + tr.dwStyles = m_dwTxtBkStyles; + tr.dwCharStyles = pPiece->dwCharStyles; + tr.pRect = &pPiece->rtPiece; + + return m_pTxtBreak->GetDisplayPos(&tr, m_CharPos.data()); +} + +CFDE_TextOut::CFDE_TTOLine::CFDE_TTOLine() : m_bNewReload(false) {} + +CFDE_TextOut::CFDE_TTOLine::CFDE_TTOLine(const CFDE_TTOLine& ttoLine) + : m_pieces(5) { + m_bNewReload = ttoLine.m_bNewReload; + m_pieces = ttoLine.m_pieces; +} + +CFDE_TextOut::CFDE_TTOLine::~CFDE_TTOLine() {} + +int32_t CFDE_TextOut::CFDE_TTOLine::AddPiece(int32_t index, + const FDE_TTOPIECE& ttoPiece) { + if (index >= pdfium::CollectionSize<int32_t>(m_pieces)) { + m_pieces.push_back(ttoPiece); + return pdfium::CollectionSize<int32_t>(m_pieces); + } + m_pieces[index] = ttoPiece; + return index; +} + +int32_t CFDE_TextOut::CFDE_TTOLine::GetSize() const { + return pdfium::CollectionSize<int32_t>(m_pieces); +} + +FDE_TTOPIECE* CFDE_TextOut::CFDE_TTOLine::GetPtrAt(int32_t index) { + return pdfium::IndexInBounds(m_pieces, index) ? &m_pieces[index] : nullptr; +} + +void CFDE_TextOut::CFDE_TTOLine::RemoveLast(int32_t icount) { + if (icount < 0) + return; + m_pieces.erase( + m_pieces.end() - + std::min(icount, pdfium::CollectionSize<int32_t>(m_pieces)), + m_pieces.end()); +} diff --git a/xfa/fde/cfde_textout.h b/xfa/fde/cfde_textout.h new file mode 100644 index 0000000000000000000000000000000000000000..6b6878e07c55fb7b7c97633b2c5e4f387cf02758 --- /dev/null +++ b/xfa/fde/cfde_textout.h @@ -0,0 +1,110 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FDE_CFDE_TEXTOUT_H_ +#define XFA_FDE_CFDE_TEXTOUT_H_ + +#include <deque> +#include <memory> +#include <vector> + +#include "core/fxcrt/cfx_char.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/fx_dib.h" +#include "xfa/fde/cfde_data.h" + +class CFDE_RenderDevice; +class CFGAS_GEFont; +class CFX_RenderDevice; +class CFX_TxtBreak; + +class CFDE_TextOut { + public: + static bool DrawString(CFX_RenderDevice* device, + FX_ARGB color, + const RetainPtr<CFGAS_GEFont>& pFont, + FXTEXT_CHARPOS* pCharPos, + int32_t iCount, + float fFontSize, + const CFX_Matrix* pMatrix); + + CFDE_TextOut(); + ~CFDE_TextOut(); + + void SetFont(const RetainPtr<CFGAS_GEFont>& pFont); + void SetFontSize(float fFontSize); + void SetTextColor(FX_ARGB color) { m_TxtColor = color; } + void SetStyles(const FDE_TextStyle& dwStyles); + void SetAlignment(FDE_TextAlignment iAlignment); + void SetLineSpace(float fLineSpace); + void SetMatrix(const CFX_Matrix& matrix) { m_Matrix = matrix; } + void SetLineBreakTolerance(float fTolerance); + + void CalcLogicSize(const WideString& str, CFX_SizeF& size); + void CalcLogicSize(const WideString& str, CFX_RectF& rect); + void DrawLogicText(CFX_RenderDevice* device, + const WideStringView& str, + const CFX_RectF& rect); + int32_t GetTotalLines() const { return m_iTotalLines; } + + private: + class CFDE_TTOLine { + public: + CFDE_TTOLine(); + CFDE_TTOLine(const CFDE_TTOLine& ttoLine); + ~CFDE_TTOLine(); + + bool GetNewReload() const { return m_bNewReload; } + void SetNewReload(bool reload) { m_bNewReload = reload; } + int32_t AddPiece(int32_t index, const FDE_TTOPIECE& ttoPiece); + int32_t GetSize() const; + FDE_TTOPIECE* GetPtrAt(int32_t index); + void RemoveLast(int32_t iCount); + + private: + bool m_bNewReload; + std::deque<FDE_TTOPIECE> m_pieces; + }; + + bool RetrieveLineWidth(CFX_BreakType dwBreakStatus, + float& fStartPos, + float& fWidth, + float& fHeight); + void LoadText(const WideString& str, const CFX_RectF& rect); + + void Reload(const CFX_RectF& rect); + void ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect); + bool RetrievePieces(CFX_BreakType dwBreakStatus, + int32_t& iStartChar, + int32_t& iPieceWidths, + bool bReload, + const CFX_RectF& rect); + void AppendPiece(const FDE_TTOPIECE& ttoPiece, bool bNeedReload, bool bEnd); + void DoAlignment(const CFX_RectF& rect); + int32_t GetDisplayPos(FDE_TTOPIECE* pPiece); + + std::unique_ptr<CFX_TxtBreak> m_pTxtBreak; + RetainPtr<CFGAS_GEFont> m_pFont; + float m_fFontSize; + float m_fLineSpace; + float m_fLinePos; + float m_fTolerance; + FDE_TextAlignment m_iAlignment; + FDE_TextStyle m_Styles; + std::vector<int32_t> m_CharWidths; + FX_ARGB m_TxtColor; + uint32_t m_dwTxtBkStyles; + WideString m_wsText; + CFX_Matrix m_Matrix; + std::deque<CFDE_TTOLine> m_ttoLines; + int32_t m_iCurLine; + int32_t m_iCurPiece; + int32_t m_iTotalLines; + std::vector<FXTEXT_CHARPOS> m_CharPos; +}; + +#endif // XFA_FDE_CFDE_TEXTOUT_H_ diff --git a/xfa/fde/cfde_txtedtbuf.cpp b/xfa/fde/cfde_txtedtbuf.cpp deleted file mode 100644 index 1c2e0d1f3ffa958b5942016e8f13cfc55de8b6bb..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtbuf.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedtbuf.h" - -#include <algorithm> -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -const int kDefaultChunkSize = 1024; - -} // namespace - -CFDE_TxtEdtBuf::CFDE_TxtEdtBuf() : m_chunkSize(kDefaultChunkSize), m_nTotal(0) { - m_chunks.push_back(NewChunk()); -} - -CFDE_TxtEdtBuf::~CFDE_TxtEdtBuf() {} - -int32_t CFDE_TxtEdtBuf::GetChunkSize() const { - return m_chunkSize; -} - -int32_t CFDE_TxtEdtBuf::GetTextLength() const { - return m_nTotal; -} - -void CFDE_TxtEdtBuf::SetText(const CFX_WideString& wsText) { - ASSERT(!wsText.IsEmpty()); - - Clear(false); - int32_t nTextLength = wsText.GetLength(); - int32_t nNeedCount = - ((nTextLength - 1) / GetChunkSize() + 1) - m_chunks.size(); - int32_t i = 0; - for (i = 0; i < nNeedCount; i++) - m_chunks.push_back(NewChunk()); - - int32_t nTotalCount = m_chunks.size(); - const FX_WCHAR* lpSrcBuf = wsText.c_str(); - int32_t nLeave = nTextLength; - int32_t nCopyedLength = GetChunkSize(); - for (i = 0; i < nTotalCount && nLeave > 0; i++) { - if (nLeave < nCopyedLength) { - nCopyedLength = nLeave; - } - - ChunkHeader* chunk = m_chunks[i].get(); - FXSYS_memcpy(chunk->wChars.get(), lpSrcBuf, - nCopyedLength * sizeof(FX_WCHAR)); - nLeave -= nCopyedLength; - lpSrcBuf += nCopyedLength; - chunk->nUsed = nCopyedLength; - } - m_nTotal = nTextLength; -} - -CFX_WideString CFDE_TxtEdtBuf::GetText() const { - return GetRange(0, m_nTotal); -} - -FX_WCHAR CFDE_TxtEdtBuf::GetCharByIndex(int32_t nIndex) const { - ASSERT(nIndex >= 0 && nIndex < GetTextLength()); - - ChunkHeader* pChunkHeader = nullptr; - int32_t nTotal = 0; - for (const auto& chunk : m_chunks) { - pChunkHeader = chunk.get(); - nTotal += pChunkHeader->nUsed; - if (nTotal > nIndex) - break; - } - ASSERT(pChunkHeader); - - FX_WCHAR* buf = pChunkHeader->wChars.get(); - return buf[pChunkHeader->nUsed - (nTotal - nIndex)]; -} - -CFX_WideString CFDE_TxtEdtBuf::GetRange(int32_t nBegin, int32_t nLength) const { - if (nLength == 0 || GetTextLength() == 0) - return CFX_WideString(); - - ASSERT(nBegin >= 0 && nLength > 0 && nBegin < GetTextLength() && - nBegin + nLength <= GetTextLength()); - - int32_t chunkIndex = 0; - int32_t charIndex = 0; - std::tie(chunkIndex, charIndex) = Index2CP(nBegin); - - int32_t nLeave = nLength; - int32_t nCount = m_chunks.size(); - - CFX_WideString wsText; - FX_WCHAR* lpDstBuf = wsText.GetBuffer(nLength); - int32_t nChunkIndex = chunkIndex; - - ChunkHeader* chunkHeader = m_chunks[nChunkIndex].get(); - int32_t nCopyLength = chunkHeader->nUsed - charIndex; - FX_WCHAR* lpSrcBuf = chunkHeader->wChars.get() + charIndex; - while (nLeave > 0) { - if (nLeave <= nCopyLength) { - nCopyLength = nLeave; - } - FXSYS_memcpy(lpDstBuf, lpSrcBuf, nCopyLength * sizeof(FX_WCHAR)); - nChunkIndex++; - if (nChunkIndex >= nCount) { - break; - } - chunkHeader = m_chunks[nChunkIndex].get(); - lpSrcBuf = chunkHeader->wChars.get(); - nLeave -= nCopyLength; - lpDstBuf += nCopyLength; - nCopyLength = chunkHeader->nUsed; - } - wsText.ReleaseBuffer(); - - return wsText; -} - -void CFDE_TxtEdtBuf::Insert(int32_t nPos, - const FX_WCHAR* lpText, - int32_t nLength) { - ASSERT(nPos >= 0 && nPos <= m_nTotal); - ASSERT(nLength > 0); - - int32_t chunkIndex = 0; - int32_t charIndex = 0; - std::tie(chunkIndex, charIndex) = Index2CP(nPos); - - int32_t nLengthTemp = nLength; - if (charIndex != 0) { - auto newChunk = NewChunk(); - - ChunkHeader* chunk = m_chunks[chunkIndex].get(); - int32_t nCopy = chunk->nUsed - charIndex; - - FXSYS_memcpy(newChunk->wChars.get(), chunk->wChars.get() + charIndex, - nCopy * sizeof(FX_WCHAR)); - chunk->nUsed -= nCopy; - chunkIndex++; - - newChunk->nUsed = nCopy; - m_chunks.insert(m_chunks.begin() + chunkIndex, std::move(newChunk)); - charIndex = 0; - } - - if (chunkIndex != 0) { - ChunkHeader* chunk = m_chunks[chunkIndex - 1].get(); - if (chunk->nUsed != GetChunkSize()) { - chunkIndex--; - int32_t nFree = GetChunkSize() - chunk->nUsed; - int32_t nCopy = std::min(nLengthTemp, nFree); - FXSYS_memcpy(chunk->wChars.get() + chunk->nUsed, lpText, - nCopy * sizeof(FX_WCHAR)); - lpText += nCopy; - nLengthTemp -= nCopy; - chunk->nUsed += nCopy; - chunkIndex++; - } - } - - while (nLengthTemp > 0) { - auto chunk = NewChunk(); - - int32_t nCopy = std::min(nLengthTemp, GetChunkSize()); - FXSYS_memcpy(chunk->wChars.get(), lpText, nCopy * sizeof(FX_WCHAR)); - lpText += nCopy; - nLengthTemp -= nCopy; - chunk->nUsed = nCopy; - m_chunks.insert(m_chunks.begin() + chunkIndex, std::move(chunk)); - chunkIndex++; - } - m_nTotal += nLength; -} - -void CFDE_TxtEdtBuf::Delete(int32_t nIndex, int32_t nLength) { - ASSERT(nLength > 0 && nIndex >= 0 && nIndex + nLength <= m_nTotal); - - int32_t endChunkIndex = 0; - int32_t endCharIndex = 0; - std::tie(endChunkIndex, endCharIndex) = Index2CP(nIndex + nLength - 1); - m_nTotal -= nLength; - - ChunkHeader* chunk = m_chunks[endChunkIndex].get(); - int32_t nFirstPart = endCharIndex + 1; - int32_t nMovePart = chunk->nUsed - nFirstPart; - if (nMovePart != 0) { - int32_t nDelete = std::min(nFirstPart, nLength); - FXSYS_memmove(chunk->wChars.get() + nFirstPart - nDelete, - chunk->wChars.get() + nFirstPart, - nMovePart * sizeof(FX_WCHAR)); - chunk->nUsed -= nDelete; - nLength -= nDelete; - endChunkIndex--; - } - - while (nLength > 0) { - ChunkHeader* curChunk = m_chunks[endChunkIndex].get(); - int32_t nDeleted = std::min(curChunk->nUsed, nLength); - curChunk->nUsed -= nDeleted; - if (curChunk->nUsed == 0) - m_chunks.erase(m_chunks.begin() + endChunkIndex); - - nLength -= nDeleted; - endChunkIndex--; - } -} - -void CFDE_TxtEdtBuf::Clear(bool bRelease) { - if (bRelease) { - m_chunks.clear(); - } else { - size_t i = 0; - while (i < m_chunks.size()) - m_chunks[i++]->nUsed = 0; - } - m_nTotal = 0; -} - -void CFDE_TxtEdtBuf::SetChunkSizeForTesting(size_t size) { - ASSERT(size > 0); - - m_chunkSize = size; - m_chunks.clear(); - m_chunks.push_back(NewChunk()); -} - -std::tuple<int32_t, int32_t> CFDE_TxtEdtBuf::Index2CP(int32_t nIndex) const { - ASSERT(nIndex <= GetTextLength()); - - if (nIndex == m_nTotal) { - return std::tuple<int32_t, int32_t>(m_chunks.size() - 1, - m_chunks.back()->nUsed); - } - - int32_t chunkIndex = 0; - int32_t nTotal = 0; - for (auto& chunk : m_chunks) { - nTotal += chunk->nUsed; - if (nTotal > nIndex) - break; - chunkIndex++; - } - - int32_t charIndex = m_chunks[chunkIndex]->nUsed - (nTotal - nIndex); - return std::tuple<int32_t, int32_t>(chunkIndex, charIndex); -} - -std::unique_ptr<CFDE_TxtEdtBuf::ChunkHeader> CFDE_TxtEdtBuf::NewChunk() { - auto chunk = pdfium::MakeUnique<ChunkHeader>(); - chunk->wChars.reset(FX_Alloc(FX_WCHAR, GetChunkSize())); - chunk->nUsed = 0; - return chunk; -} - -CFDE_TxtEdtBuf::ChunkHeader::ChunkHeader() {} - -CFDE_TxtEdtBuf::ChunkHeader::~ChunkHeader() {} - -CFDE_TxtEdtBuf::Iterator::Iterator(CFDE_TxtEdtBuf* pBuf, FX_WCHAR wcAlias) - : m_pBuf(pBuf), - m_nCurChunk(0), - m_nCurIndex(0), - m_nIndex(0), - m_Alias(wcAlias) { - ASSERT(m_pBuf); -} - -CFDE_TxtEdtBuf::Iterator::~Iterator() {} - -bool CFDE_TxtEdtBuf::Iterator::Next(bool bPrev) { - if (bPrev) { - if (m_nIndex == 0) - return false; - - ASSERT(m_nCurChunk < pdfium::CollectionSize<int32_t>(m_pBuf->m_chunks)); - - ChunkHeader* chunk = nullptr; - if (m_nCurIndex > 0) { - m_nCurIndex--; - } else { - while (m_nCurChunk > 0) { - --m_nCurChunk; - chunk = m_pBuf->m_chunks[m_nCurChunk].get(); - if (chunk->nUsed > 0) { - m_nCurIndex = chunk->nUsed - 1; - break; - } - } - } - ASSERT(m_nCurChunk >= 0); - m_nIndex--; - return true; - } else { - if (m_nIndex >= (m_pBuf->m_nTotal - 1)) - return false; - - ASSERT(m_nCurChunk < pdfium::CollectionSize<int32_t>(m_pBuf->m_chunks)); - if (m_pBuf->m_chunks[m_nCurChunk]->nUsed != (m_nCurIndex + 1)) { - m_nCurIndex++; - } else { - int32_t nEnd = m_pBuf->m_chunks.size() - 1; - while (m_nCurChunk < nEnd) { - m_nCurChunk++; - ChunkHeader* chunkTemp = m_pBuf->m_chunks[m_nCurChunk].get(); - if (chunkTemp->nUsed > 0) { - m_nCurIndex = 0; - break; - } - } - } - m_nIndex++; - return true; - } -} - -void CFDE_TxtEdtBuf::Iterator::SetAt(int32_t nIndex) { - ASSERT(nIndex >= 0 && nIndex < m_pBuf->m_nTotal); - - std::tie(m_nCurChunk, m_nCurIndex) = m_pBuf->Index2CP(nIndex); - m_nIndex = nIndex; -} - -int32_t CFDE_TxtEdtBuf::Iterator::GetAt() const { - return m_nIndex; -} - -FX_WCHAR CFDE_TxtEdtBuf::Iterator::GetChar() { - ASSERT(m_nIndex >= 0 && m_nIndex < m_pBuf->m_nTotal); - if (m_Alias == 0 || m_nIndex == (m_pBuf->m_nTotal - 1)) { - FX_WCHAR* buf = m_pBuf->m_chunks[m_nCurChunk]->wChars.get(); - return buf[m_nCurIndex]; - } - return m_Alias; -} - -bool CFDE_TxtEdtBuf::Iterator::IsEOF(bool bTail) const { - return bTail ? m_nIndex == (m_pBuf->GetTextLength() - 2) : m_nIndex == 0; -} - -IFX_CharIter* CFDE_TxtEdtBuf::Iterator::Clone() { - CFDE_TxtEdtBuf::Iterator* pIter = new CFDE_TxtEdtBuf::Iterator(m_pBuf); - pIter->m_nCurChunk = m_nCurChunk; - pIter->m_nCurIndex = m_nCurIndex; - pIter->m_nIndex = m_nIndex; - pIter->m_Alias = m_Alias; - return pIter; -} diff --git a/xfa/fde/cfde_txtedtbuf.h b/xfa/fde/cfde_txtedtbuf.h deleted file mode 100644 index 9eeee5632efc8ac1b29c29b3cdc09ba3a2301cf2..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtbuf.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTBUF_H_ -#define XFA_FDE_CFDE_TXTEDTBUF_H_ - -#include <memory> -#include <tuple> -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/ifx_chariter.h" - -class IFX_Pause; - -class CFDE_TxtEdtBuf { - public: - class Iterator : public IFX_CharIter { - public: - explicit Iterator(CFDE_TxtEdtBuf* pBuf, FX_WCHAR wcAlias = 0); - ~Iterator() override; - - bool Next(bool bPrev = false) override; - FX_WCHAR GetChar() override; - - void SetAt(int32_t nIndex) override; - int32_t GetAt() const override; - - bool IsEOF(bool bTail = true) const override; - IFX_CharIter* Clone() override; - - private: - CFDE_TxtEdtBuf* m_pBuf; - int32_t m_nCurChunk; - int32_t m_nCurIndex; - int32_t m_nIndex; - FX_WCHAR m_Alias; - }; - - CFDE_TxtEdtBuf(); - ~CFDE_TxtEdtBuf(); - - int32_t GetChunkSize() const; - int32_t GetTextLength() const; - - void SetText(const CFX_WideString& wsText); - CFX_WideString GetText() const; - - FX_WCHAR GetCharByIndex(int32_t nIndex) const; - CFX_WideString GetRange(int32_t nBegin, int32_t nCount) const; - - void Insert(int32_t nPos, const FX_WCHAR* lpText, int32_t nLength); - void Delete(int32_t nIndex, int32_t nLength); - void Clear(bool bRelease); - - private: - friend class Iterator; - friend class CFDE_TxtEdtBufTest; - - class ChunkHeader { - public: - ChunkHeader(); - ~ChunkHeader(); - - int32_t nUsed; - std::unique_ptr<FX_WCHAR, FxFreeDeleter> wChars; - }; - - void SetChunkSizeForTesting(size_t size); - std::tuple<int32_t, int32_t> Index2CP(int32_t nIndex) const; - std::unique_ptr<ChunkHeader> NewChunk(); - - size_t m_chunkSize; - int32_t m_nTotal; - std::vector<std::unique_ptr<ChunkHeader>> m_chunks; -}; - -#endif // XFA_FDE_CFDE_TXTEDTBUF_H_ diff --git a/xfa/fde/cfde_txtedtbuf_unittest.cpp b/xfa/fde/cfde_txtedtbuf_unittest.cpp deleted file mode 100644 index 9c564093e5896648387a0ce388369eee824ea543..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtbuf_unittest.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "xfa/fde/cfde_txtedtbuf.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/test_support.h" -#include "third_party/base/ptr_util.h" - -class CFDE_TxtEdtBufTest : public testing::Test { - public: - void SetUp() override { - buf_ = pdfium::MakeUnique<CFDE_TxtEdtBuf>(); - buf_->SetChunkSizeForTesting(5); - } - size_t ChunkCount() const { return buf_->m_chunks.size(); } - - std::unique_ptr<CFDE_TxtEdtBuf> buf_; -}; - -TEST_F(CFDE_TxtEdtBufTest, SetTextLessThenChunkSize) { - buf_->SetText(L"Hi"); - EXPECT_EQ(1UL, ChunkCount()); - EXPECT_EQ(2, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(2, res.GetLength()); - EXPECT_EQ(L"Hi", res); -} - -TEST_F(CFDE_TxtEdtBufTest, InsertAppendChunk) { - buf_->SetText(L"Hi"); - - CFX_WideString end = L" World"; - buf_->Insert(2, end.c_str(), end.GetLength()); - EXPECT_EQ(3UL, ChunkCount()); - EXPECT_EQ(8, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(8, res.GetLength()); - EXPECT_EQ(L"Hi World", res); -} - -TEST_F(CFDE_TxtEdtBufTest, InsertPrependChunk) { - buf_->SetText(L"Hi"); - - CFX_WideString end = L"World "; - buf_->Insert(0, end.c_str(), end.GetLength()); - EXPECT_EQ(3UL, ChunkCount()); - EXPECT_EQ(8, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"World Hi", res); - EXPECT_EQ(8, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, InsertBetweenChunks) { - buf_->SetText(L"Hello World"); - EXPECT_EQ(3UL, ChunkCount()); - - CFX_WideString inst = L"there "; - buf_->Insert(6, inst.c_str(), inst.GetLength()); - EXPECT_EQ(5UL, ChunkCount()); - EXPECT_EQ(17, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"Hello there World", res); - EXPECT_EQ(17, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, SetText) { - buf_->SetText(L"Hello World"); - EXPECT_EQ(11, buf_->GetTextLength()); - - buf_->SetText(L"Hi"); - // Don't remove chunks on setting shorter text. - EXPECT_EQ(3UL, ChunkCount()); - EXPECT_EQ(2, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"Hi", res); - EXPECT_EQ(2, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, DeleteMiddleText) { - buf_->SetText(L"Hello there World"); - buf_->Delete(6, 6); - EXPECT_EQ(4UL, ChunkCount()); - EXPECT_EQ(11, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"Hello World", res); - EXPECT_EQ(11, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, DeleteEndText) { - buf_->SetText(L"Hello World"); - buf_->Delete(5, 6); - EXPECT_EQ(1UL, ChunkCount()); - EXPECT_EQ(5, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"Hello", res); - EXPECT_EQ(5, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, DeleteStartText) { - buf_->SetText(L"Hello World"); - buf_->Delete(0, 6); - EXPECT_EQ(2UL, ChunkCount()); - EXPECT_EQ(5, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"World", res); - EXPECT_EQ(5, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, DeleteAllText) { - buf_->SetText(L"Hello World"); - buf_->Delete(0, 11); - EXPECT_EQ(0UL, ChunkCount()); - EXPECT_EQ(0, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"", res); - EXPECT_EQ(0, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, ClearWithRelease) { - buf_->SetText(L"Hello World"); - buf_->Clear(true); - EXPECT_EQ(0UL, ChunkCount()); - EXPECT_EQ(0, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"", res); - EXPECT_EQ(0, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, ClearWithoutRelease) { - buf_->SetText(L"Hello World"); - buf_->Clear(false); - EXPECT_EQ(3UL, ChunkCount()); - EXPECT_EQ(0, buf_->GetTextLength()); - - CFX_WideString res = buf_->GetText(); - EXPECT_EQ(L"", res); - EXPECT_EQ(0, res.GetLength()); -} - -TEST_F(CFDE_TxtEdtBufTest, GetCharByIndex) { - buf_->SetText(L"Hello world"); - EXPECT_EQ(L"e", CFX_WideString(buf_->GetCharByIndex(1))); - EXPECT_EQ(L"o", CFX_WideString(buf_->GetCharByIndex(7))); -} - -TEST_F(CFDE_TxtEdtBufTest, GetRange) { - buf_->SetText(L"Hello World"); - EXPECT_EQ(L"", buf_->GetRange(1, 0)); - EXPECT_EQ(L"ello", buf_->GetRange(1, 4)); - EXPECT_EQ(L"lo Wo", buf_->GetRange(3, 5)); -} - -#ifndef NDEBUG -using CFDE_TxtEdtBufTestDeathTest = CFDE_TxtEdtBufTest; - -TEST_F(CFDE_TxtEdtBufTestDeathTest, InsertBadIndexes) { - CFX_WideString inst = L"there "; - - buf_->SetText(L"Hi"); - EXPECT_DEATH(buf_->Insert(-4, inst.c_str(), inst.GetLength()), "Assertion"); - EXPECT_DEATH(buf_->Insert(9999, inst.c_str(), inst.GetLength()), "Assertion"); - EXPECT_DEATH(buf_->Insert(1, inst.c_str(), -6), "Assertion"); -} - -TEST_F(CFDE_TxtEdtBufTestDeathTest, DeleteWithBadIdx) { - buf_->SetText(L"Hi"); - EXPECT_DEATH(buf_->Delete(-10, 4), "Assertion"); - EXPECT_DEATH(buf_->Delete(1, -5), "Assertion"); - EXPECT_DEATH(buf_->Delete(5, 1), "Assertion"); - EXPECT_DEATH(buf_->Delete(0, 10000), "Assertion"); -} - -TEST_F(CFDE_TxtEdtBufTestDeathTest, GetCharByIndex) { - buf_->SetText(L"Hi"); - EXPECT_DEATH(buf_->GetCharByIndex(-1), "Assertion"); - EXPECT_DEATH(buf_->GetCharByIndex(100), "Assertion"); -} - -TEST_F(CFDE_TxtEdtBufTestDeathTest, GetRange) { - buf_->SetText(L"Hi"); - EXPECT_DEATH(buf_->GetRange(1, -1), "Assertion"); - EXPECT_DEATH(buf_->GetRange(-1, 1), "Assertion"); - EXPECT_DEATH(buf_->GetRange(10, 1), "Assertion"); - EXPECT_DEATH(buf_->GetRange(1, 100), "Assertion"); -} - -#endif // NDEBUG diff --git a/xfa/fde/cfde_txtedtdorecord_deleterange.cpp b/xfa/fde/cfde_txtedtdorecord_deleterange.cpp deleted file mode 100644 index df6387e08425d95ddecaec59eb706c404fd3d366..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtdorecord_deleterange.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedtdorecord_deleterange.h" - -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fwl/cfwl_edit.h" - -CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange( - CFDE_TxtEdtEngine* pEngine, - int32_t nIndex, - int32_t nCaret, - const CFX_WideString& wsRange, - bool bSel) - : m_pEngine(pEngine), - m_bSel(bSel), - m_nIndex(nIndex), - m_nCaret(nCaret), - m_wsRange(wsRange) { - ASSERT(pEngine); -} - -CFDE_TxtEdtDoRecord_DeleteRange::~CFDE_TxtEdtDoRecord_DeleteRange() {} - -bool CFDE_TxtEdtDoRecord_DeleteRange::Undo() const { - if (m_pEngine->IsSelect()) - m_pEngine->ClearSelection(); - - m_pEngine->Inner_Insert(m_nIndex, m_wsRange.c_str(), m_wsRange.GetLength()); - if (m_bSel) - m_pEngine->AddSelRange(m_nIndex, m_wsRange.GetLength()); - - FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; - m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; - m_pEngine->m_ChangeInfo.wsDelete = m_wsRange; - Param.pEventSink->OnTextChanged(m_pEngine->m_ChangeInfo); - m_pEngine->SetCaretPos(m_nCaret, true); - return true; -} - -bool CFDE_TxtEdtDoRecord_DeleteRange::Redo() const { - m_pEngine->Inner_DeleteRange(m_nIndex, m_wsRange.GetLength()); - if (m_bSel) - m_pEngine->RemoveSelRange(m_nIndex, m_wsRange.GetLength()); - - FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; - m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; - m_pEngine->m_ChangeInfo.wsDelete = m_wsRange; - Param.pEventSink->OnTextChanged(m_pEngine->m_ChangeInfo); - m_pEngine->SetCaretPos(m_nIndex, true); - return true; -} diff --git a/xfa/fde/cfde_txtedtdorecord_deleterange.h b/xfa/fde/cfde_txtedtdorecord_deleterange.h deleted file mode 100644 index f7d79559403cdb7ec1c5e1a6fc2a64a1dfc0f319..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtdorecord_deleterange.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTDORECORD_DELETERANGE_H_ -#define XFA_FDE_CFDE_TXTEDTDORECORD_DELETERANGE_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/ifde_txtedtdorecord.h" - -class CFDE_TxtEdtEngine; - -class CFDE_TxtEdtDoRecord_DeleteRange : public IFDE_TxtEdtDoRecord { - public: - CFDE_TxtEdtDoRecord_DeleteRange(CFDE_TxtEdtEngine* pEngine, - int32_t nIndex, - int32_t nCaret, - const CFX_WideString& wsRange, - bool bSel = false); - ~CFDE_TxtEdtDoRecord_DeleteRange() override; - - bool Undo() const override; - bool Redo() const override; - - private: - CFDE_TxtEdtEngine* m_pEngine; - bool m_bSel; - int32_t m_nIndex; - int32_t m_nCaret; - CFX_WideString m_wsRange; -}; - -#endif // XFA_FDE_CFDE_TXTEDTDORECORD_DELETERANGE_H_ diff --git a/xfa/fde/cfde_txtedtdorecord_insert.cpp b/xfa/fde/cfde_txtedtdorecord_insert.cpp deleted file mode 100644 index b80b15dff68c50bd9add611d562313d1fd9b6bf3..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtdorecord_insert.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedtdorecord_insert.h" - -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fwl/cfwl_edit.h" - -CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert( - CFDE_TxtEdtEngine* pEngine, - int32_t nCaret, - const FX_WCHAR* lpText, - int32_t nLength) - : m_pEngine(pEngine), m_nCaret(nCaret) { - ASSERT(pEngine); - FX_WCHAR* lpBuffer = m_wsInsert.GetBuffer(nLength); - FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR)); - m_wsInsert.ReleaseBuffer(); -} - -CFDE_TxtEdtDoRecord_Insert::~CFDE_TxtEdtDoRecord_Insert() {} - -bool CFDE_TxtEdtDoRecord_Insert::Undo() const { - if (m_pEngine->IsSelect()) - m_pEngine->ClearSelection(); - - m_pEngine->Inner_DeleteRange(m_nCaret, m_wsInsert.GetLength()); - FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; - m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; - m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert; - Param.pEventSink->OnTextChanged(m_pEngine->m_ChangeInfo); - m_pEngine->SetCaretPos(m_nCaret, true); - return true; -} - -bool CFDE_TxtEdtDoRecord_Insert::Redo() const { - m_pEngine->Inner_Insert(m_nCaret, m_wsInsert.c_str(), m_wsInsert.GetLength()); - FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; - m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; - m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert; - Param.pEventSink->OnTextChanged(m_pEngine->m_ChangeInfo); - m_pEngine->SetCaretPos(m_nCaret, false); - return true; -} diff --git a/xfa/fde/cfde_txtedtdorecord_insert.h b/xfa/fde/cfde_txtedtdorecord_insert.h deleted file mode 100644 index e80453e9e3c662ba8e1304cd350c05691523866a..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtdorecord_insert.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTDORECORD_INSERT_H_ -#define XFA_FDE_CFDE_TXTEDTDORECORD_INSERT_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/ifde_txtedtdorecord.h" - -class CFDE_TxtEdtEngine; - -class CFDE_TxtEdtDoRecord_Insert : public IFDE_TxtEdtDoRecord { - public: - CFDE_TxtEdtDoRecord_Insert(CFDE_TxtEdtEngine* pEngine, - int32_t nCaret, - const FX_WCHAR* lpText, - int32_t nLength); - ~CFDE_TxtEdtDoRecord_Insert() override; - - bool Undo() const override; - bool Redo() const override; - - private: - CFDE_TxtEdtEngine* m_pEngine; - int32_t m_nCaret; - CFX_WideString m_wsInsert; -}; - -#endif // XFA_FDE_CFDE_TXTEDTDORECORD_INSERT_H_ diff --git a/xfa/fde/cfde_txtedtengine.cpp b/xfa/fde/cfde_txtedtengine.cpp deleted file mode 100644 index a61f6ab4d904aa701d633bba4cd15ad31bd2b719..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtengine.cpp +++ /dev/null @@ -1,1480 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedtengine.h" - -#include <algorithm> - -#include "third_party/base/ptr_util.h" -#include "xfa/fde/cfde_txtedtbuf.h" -#include "xfa/fde/cfde_txtedtdorecord_deleterange.h" -#include "xfa/fde/cfde_txtedtdorecord_insert.h" -#include "xfa/fde/cfde_txtedtpage.h" -#include "xfa/fde/cfde_txtedtparag.h" -#include "xfa/fde/ifx_chariter.h" -#include "xfa/fde/tto/fde_textout.h" -#include "xfa/fgas/layout/fgas_textbreak.h" -#include "xfa/fwl/cfwl_edit.h" - -namespace { - -const uint32_t kPageWidthMax = 0xffff; -const uint32_t kUnicodeParagraphSeparator = 0x2029; - -} // namespace - -FDE_TXTEDTPARAMS::FDE_TXTEDTPARAMS() - : fPlateWidth(0), - fPlateHeight(0), - nLineCount(0), - dwLayoutStyles(0), - dwAlignment(0), - dwMode(0), - fFontSize(10.0f), - dwFontColor(0xff000000), - fLineSpace(10.0f), - fTabWidth(36), - bTabEquidistant(false), - wDefChar(0xFEFF), - wLineBreakChar('\n'), - nCharRotation(0), - nLineEnd(0), - nHorzScale(100), - fCharSpace(0), - pEventSink(nullptr) {} - -FDE_TXTEDTPARAMS::~FDE_TXTEDTPARAMS() {} - -FDE_TXTEDT_TEXTCHANGE_INFO::FDE_TXTEDT_TEXTCHANGE_INFO() {} - -FDE_TXTEDT_TEXTCHANGE_INFO::~FDE_TXTEDT_TEXTCHANGE_INFO() {} - -CFDE_TxtEdtEngine::CFDE_TxtEdtEngine() - : m_pTxtBuf(new CFDE_TxtEdtBuf()), - m_nPageLineCount(20), - m_nLineCount(0), - m_nAnchorPos(-1), - m_nLayoutPos(0), - m_fCaretPosReserve(0.0), - m_nCaret(0), - m_bBefore(true), - m_nCaretPage(0), - m_dwFindFlags(0), - m_bLock(false), - m_nLimit(0), - m_wcAliasChar(L'*'), - m_nFirstLineEnd(FDE_TXTEDIT_LINEEND_Auto), - m_bAutoLineEnd(true), - m_wLineEnd(kUnicodeParagraphSeparator) { - m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto); -} - -CFDE_TxtEdtEngine::~CFDE_TxtEdtEngine() { - RemoveAllParags(); - RemoveAllPages(); - m_Param.pEventSink = nullptr; - ClearSelection(); -} - -void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS& params) { - if (!m_pTextBreak) - m_pTextBreak = pdfium::MakeUnique<CFX_TxtBreak>(FX_TXTBREAKPOLICY_None); - - m_Param = params; - m_wLineEnd = params.wLineBreakChar; - m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto); - UpdateTxtBreak(); -} - -FDE_TXTEDTPARAMS* CFDE_TxtEdtEngine::GetEditParams() { - return &m_Param; -} - -int32_t CFDE_TxtEdtEngine::CountPages() const { - if (m_nLineCount == 0) { - return 0; - } - return ((m_nLineCount - 1) / m_nPageLineCount) + 1; -} - -IFDE_TxtEdtPage* CFDE_TxtEdtEngine::GetPage(int32_t nIndex) { - if (m_PagePtrArray.GetSize() <= nIndex) { - return nullptr; - } - return m_PagePtrArray[nIndex]; -} - -void CFDE_TxtEdtEngine::SetTextByStream( - const CFX_RetainPtr<IFGAS_Stream>& pStream) { - ResetEngine(); - int32_t nIndex = 0; - if (pStream && pStream->GetLength()) { - int32_t nStreamLength = pStream->GetLength(); - bool bValid = true; - if (m_nLimit > 0 && nStreamLength > m_nLimit) { - bValid = false; - } - bool bPreIsCR = false; - if (bValid) { - uint8_t bom[4]; - int32_t nPos = pStream->GetBOM(bom); - pStream->Seek(FX_STREAMSEEK_Begin, nPos); - int32_t nPlateSize = std::min(nStreamLength, m_pTxtBuf->GetChunkSize()); - FX_WCHAR* lpwstr = FX_Alloc(FX_WCHAR, nPlateSize); - bool bEos = false; - while (!bEos) { - int32_t nRead = pStream->ReadString(lpwstr, nPlateSize, bEos); - bPreIsCR = ReplaceParagEnd(lpwstr, nRead, bPreIsCR); - m_pTxtBuf->Insert(nIndex, lpwstr, nRead); - nIndex += nRead; - } - FX_Free(lpwstr); - } - } - m_pTxtBuf->Insert(nIndex, &m_wLineEnd, 1); - RebuildParagraphs(); -} - -void CFDE_TxtEdtEngine::SetText(const CFX_WideString& wsText) { - ResetEngine(); - int32_t nLength = wsText.GetLength(); - if (nLength > 0) { - CFX_WideString wsTemp; - FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength); - FXSYS_memcpy(lpBuffer, wsText.c_str(), nLength * sizeof(FX_WCHAR)); - ReplaceParagEnd(lpBuffer, nLength, false); - wsTemp.ReleaseBuffer(nLength); - if (m_nLimit > 0 && nLength > m_nLimit) { - wsTemp.Delete(m_nLimit, nLength - m_nLimit); - nLength = m_nLimit; - } - m_pTxtBuf->SetText(wsTemp); - } - m_pTxtBuf->Insert(nLength, &m_wLineEnd, 1); - RebuildParagraphs(); -} - -int32_t CFDE_TxtEdtEngine::GetTextLength() const { - return GetTextBufLength(); -} - -CFX_WideString CFDE_TxtEdtEngine::GetText(int32_t nStart, - int32_t nCount) const { - int32_t nTextBufLength = GetTextBufLength(); - if (nCount == -1) - nCount = nTextBufLength - nStart; - - CFX_WideString wsText = m_pTxtBuf->GetRange(nStart, nCount); - RecoverParagEnd(wsText); - return wsText; -} - -void CFDE_TxtEdtEngine::ClearText() { - DeleteRange(0, -1); -} - -int32_t CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret) const { - rtCaret = m_rtCaret; - return m_nCaret; -} - -int32_t CFDE_TxtEdtEngine::GetCaretPos() const { - if (IsLocked()) { - return 0; - } - return m_nCaret + (m_bBefore ? 0 : 1); -} - -int32_t CFDE_TxtEdtEngine::SetCaretPos(int32_t nIndex, bool bBefore) { - if (IsLocked()) { - return 0; - } - ASSERT(nIndex >= 0 && nIndex <= GetTextBufLength()); - if (m_PagePtrArray.GetSize() <= m_nCaretPage) { - return 0; - } - m_bBefore = bBefore; - m_nCaret = nIndex; - MovePage2Char(m_nCaret); - GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore); - if (!m_bBefore) { - m_nCaret++; - m_bBefore = true; - } - m_fCaretPosReserve = m_rtCaret.left; - m_Param.pEventSink->OnCaretChanged(); - m_nAnchorPos = -1; - return m_nCaret; -} - -int32_t CFDE_TxtEdtEngine::MoveCaretPos(FDE_TXTEDTMOVECARET eMoveCaret, - bool bShift, - bool bCtrl) { - if (IsLocked()) { - return 0; - } - if (m_PagePtrArray.GetSize() <= m_nCaretPage) { - return 0; - } - bool bSelChange = false; - if (IsSelect()) { - ClearSelection(); - bSelChange = true; - } - if (bShift) { - if (m_nAnchorPos == -1) { - m_nAnchorPos = m_nCaret; - } - } else { - m_nAnchorPos = -1; - } - - switch (eMoveCaret) { - case MC_Left: { - bool bBefore = true; - int32_t nIndex = MoveBackward(bBefore); - if (nIndex >= 0) { - UpdateCaretRect(nIndex, bBefore); - } - break; - } - case MC_Right: { - bool bBefore = true; - int32_t nIndex = MoveForward(bBefore); - if (nIndex >= 0) { - UpdateCaretRect(nIndex, bBefore); - } - break; - } - case MC_Up: { - CFX_PointF ptCaret; - if (MoveUp(ptCaret)) { - UpdateCaretIndex(ptCaret); - } - break; - } - case MC_Down: { - CFX_PointF ptCaret; - if (MoveDown(ptCaret)) { - UpdateCaretIndex(ptCaret); - } - break; - } - case MC_WordBackward: - break; - case MC_WordForward: - break; - case MC_LineStart: - MoveLineStart(); - break; - case MC_LineEnd: - MoveLineEnd(); - break; - case MC_ParagStart: - MoveParagStart(); - break; - case MC_ParagEnd: - MoveParagEnd(); - break; - case MC_PageDown: - break; - case MC_PageUp: - break; - case MC_Home: - MoveHome(); - break; - case MC_End: - MoveEnd(); - break; - default: - break; - } - if (bShift && m_nAnchorPos != -1 && (m_nAnchorPos != m_nCaret)) { - AddSelRange(std::min(m_nAnchorPos, m_nCaret), - FXSYS_abs(m_nAnchorPos - m_nCaret)); - m_Param.pEventSink->OnSelChanged(); - } - if (bSelChange) - m_Param.pEventSink->OnSelChanged(); - - return m_nCaret; -} - -void CFDE_TxtEdtEngine::Lock() { - m_bLock = true; -} - -void CFDE_TxtEdtEngine::Unlock() { - m_bLock = false; -} - -bool CFDE_TxtEdtEngine::IsLocked() const { - return m_bLock; -} - -int32_t CFDE_TxtEdtEngine::Insert(int32_t nStart, - const FX_WCHAR* lpText, - int32_t nLength) { - if (IsLocked()) { - return FDE_TXTEDT_MODIFY_RET_F_Locked; - } - CFX_WideString wsTemp; - FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength); - FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR)); - ReplaceParagEnd(lpBuffer, nLength, false); - wsTemp.ReleaseBuffer(nLength); - bool bPart = false; - if (m_nLimit > 0) { - int32_t nTotalLength = GetTextBufLength(); - int32_t nCount = m_SelRangePtrArr.GetSize(); - for (int32_t i = 0; i < nCount; i++) { - FDE_TXTEDTSELRANGE* lpSelRange = m_SelRangePtrArr.GetAt(i); - nTotalLength -= lpSelRange->nCount; - } - int32_t nExpectLength = nTotalLength + nLength; - if (nTotalLength == m_nLimit) { - return FDE_TXTEDT_MODIFY_RET_F_Full; - } - if (nExpectLength > m_nLimit) { - nLength -= (nExpectLength - m_nLimit); - bPart = true; - } - } - if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || - (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) { - int32_t nTemp = nLength; - if (m_Param.dwMode & FDE_TEXTEDITMODE_Password) { - while (nLength > 0) { - CFX_WideString wsText = GetPreInsertText(m_nCaret, lpBuffer, nLength); - int32_t nTotal = wsText.GetLength(); - FX_WCHAR* lpBuf = wsText.GetBuffer(nTotal); - for (int32_t i = 0; i < nTotal; i++) { - lpBuf[i] = m_wcAliasChar; - } - wsText.ReleaseBuffer(nTotal); - if (IsFitArea(wsText)) { - break; - } - nLength--; - } - } else { - while (nLength > 0) { - CFX_WideString wsText = GetPreInsertText(m_nCaret, lpBuffer, nLength); - if (IsFitArea(wsText)) { - break; - } - nLength--; - } - } - if (nLength == 0) { - return FDE_TXTEDT_MODIFY_RET_F_Full; - } - if (nLength < nTemp) { - bPart = true; - } - } - if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { - CFX_WideString wsText = GetPreInsertText(m_nCaret, lpBuffer, nLength); - if (!m_Param.pEventSink->OnValidate(wsText)) - return FDE_TXTEDT_MODIFY_RET_F_Invalidate; - } - if (IsSelect()) { - DeleteSelect(); - } - m_Param.pEventSink->OnAddDoRecord( - pdfium::MakeUnique<CFDE_TxtEdtDoRecord_Insert>(this, m_nCaret, lpBuffer, - nLength)); - - m_ChangeInfo.wsPrevText = GetText(0, -1); - Inner_Insert(m_nCaret, lpBuffer, nLength); - m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; - m_ChangeInfo.wsInsert = CFX_WideString(lpBuffer, nLength); - nStart = m_nCaret; - nStart += nLength; - FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1); - bool bBefore = true; - if (wChar != L'\n' && wChar != L'\r') { - nStart--; - bBefore = false; - } - SetCaretPos(nStart, bBefore); - m_Param.pEventSink->OnTextChanged(m_ChangeInfo); - return bPart ? FDE_TXTEDT_MODIFY_RET_S_Part : FDE_TXTEDT_MODIFY_RET_S_Normal; -} - -int32_t CFDE_TxtEdtEngine::Delete(int32_t nStart, bool bBackspace) { - if (IsLocked()) { - return FDE_TXTEDT_MODIFY_RET_F_Locked; - } - if (IsSelect()) { - DeleteSelect(); - return FDE_TXTEDT_MODIFY_RET_S_Normal; - } - - int32_t nCount = 1; - if (bBackspace) { - if (nStart == 0) { - return FDE_TXTEDT_MODIFY_RET_F_Boundary; - } - if (nStart > 2 && m_pTxtBuf->GetCharByIndex(nStart - 1) == L'\n' && - m_pTxtBuf->GetCharByIndex(nStart - 2) == L'\r') { - nStart--; - nCount++; - } - nStart--; - } else { - if (nStart == GetTextBufLength()) { - return FDE_TXTEDT_MODIFY_RET_F_Full; - } - if ((nStart + 1 < GetTextBufLength()) && - (m_pTxtBuf->GetCharByIndex(nStart) == L'\r') && - (m_pTxtBuf->GetCharByIndex(nStart + 1) == L'\n')) { - nCount++; - } - } - if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { - CFX_WideString wsText = GetPreDeleteText(nStart, nCount); - if (!m_Param.pEventSink->OnValidate(wsText)) - return FDE_TXTEDT_MODIFY_RET_F_Invalidate; - } - CFX_WideString wsRange = m_pTxtBuf->GetRange(nStart, nCount); - m_Param.pEventSink->OnAddDoRecord( - pdfium::MakeUnique<CFDE_TxtEdtDoRecord_DeleteRange>(this, nStart, - m_nCaret, wsRange)); - - m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; - m_ChangeInfo.wsDelete = GetText(nStart, nCount); - Inner_DeleteRange(nStart, nCount); - SetCaretPos(nStart + ((!bBackspace && nStart > 0) ? -1 : 0), - (bBackspace || nStart == 0)); - m_Param.pEventSink->OnTextChanged(m_ChangeInfo); - return FDE_TXTEDT_MODIFY_RET_S_Normal; -} - -int32_t CFDE_TxtEdtEngine::DeleteRange(int32_t nStart, int32_t nCount) { - if (IsLocked()) - return FDE_TXTEDT_MODIFY_RET_F_Locked; - if (nCount == -1) - nCount = GetTextBufLength(); - if (nCount == 0) - return FDE_TXTEDT_MODIFY_RET_S_Normal; - if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { - CFX_WideString wsText = GetPreDeleteText(nStart, nCount); - if (!m_Param.pEventSink->OnValidate(wsText)) - return FDE_TXTEDT_MODIFY_RET_F_Invalidate; - } - DeleteRange_DoRecord(nStart, nCount); - m_Param.pEventSink->OnTextChanged(m_ChangeInfo); - SetCaretPos(nStart, true); - return FDE_TXTEDT_MODIFY_RET_S_Normal; -} - -int32_t CFDE_TxtEdtEngine::Replace(int32_t nStart, - int32_t nLength, - const CFX_WideString& wsReplace) { - if (IsLocked()) - return FDE_TXTEDT_MODIFY_RET_F_Locked; - if (nStart < 0 || (nStart + nLength > GetTextBufLength())) - return FDE_TXTEDT_MODIFY_RET_F_Boundary; - if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { - CFX_WideString wsText = GetPreReplaceText( - nStart, nLength, wsReplace.c_str(), wsReplace.GetLength()); - if (!m_Param.pEventSink->OnValidate(wsText)) - return FDE_TXTEDT_MODIFY_RET_F_Invalidate; - } - if (IsSelect()) - ClearSelection(); - - m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Replace; - m_ChangeInfo.wsDelete = GetText(nStart, nLength); - if (nLength > 0) - Inner_DeleteRange(nStart, nLength); - - int32_t nTextLength = wsReplace.GetLength(); - if (nTextLength > 0) - Inner_Insert(nStart, wsReplace.c_str(), nTextLength); - - m_ChangeInfo.wsInsert = CFX_WideString(wsReplace.c_str(), nTextLength); - nStart += nTextLength; - FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1); - bool bBefore = true; - if (wChar != L'\n' && wChar != L'\r') { - nStart--; - bBefore = false; - } - SetCaretPos(nStart, bBefore); - m_Param.pEventSink->OnPageUnload(m_nCaretPage); - m_Param.pEventSink->OnPageLoad(m_nCaretPage); - m_Param.pEventSink->OnTextChanged(m_ChangeInfo); - return FDE_TXTEDT_MODIFY_RET_S_Normal; -} - -void CFDE_TxtEdtEngine::SetLimit(int32_t nLimit) { - m_nLimit = nLimit; -} - -void CFDE_TxtEdtEngine::SetAliasChar(FX_WCHAR wcAlias) { - m_wcAliasChar = wcAlias; -} - -void CFDE_TxtEdtEngine::RemoveSelRange(int32_t nStart, int32_t nCount) { - FDE_TXTEDTSELRANGE* lpTemp = nullptr; - int32_t nRangeCount = m_SelRangePtrArr.GetSize(); - int32_t i = 0; - for (i = 0; i < nRangeCount; i++) { - lpTemp = m_SelRangePtrArr[i]; - if (lpTemp->nStart == nStart && lpTemp->nCount == nCount) { - delete lpTemp; - m_SelRangePtrArr.RemoveAt(i); - return; - } - } -} - -void CFDE_TxtEdtEngine::AddSelRange(int32_t nStart, int32_t nCount) { - if (nCount == -1) { - nCount = GetTextLength() - nStart; - } - int32_t nSize = m_SelRangePtrArr.GetSize(); - if (nSize <= 0) { - FDE_TXTEDTSELRANGE* lpSelRange = new FDE_TXTEDTSELRANGE; - lpSelRange->nStart = nStart; - lpSelRange->nCount = nCount; - m_SelRangePtrArr.Add(lpSelRange); - m_Param.pEventSink->OnSelChanged(); - return; - } - FDE_TXTEDTSELRANGE* lpTemp = nullptr; - lpTemp = m_SelRangePtrArr[nSize - 1]; - if (nStart >= lpTemp->nStart + lpTemp->nCount) { - FDE_TXTEDTSELRANGE* lpSelRange = new FDE_TXTEDTSELRANGE; - lpSelRange->nStart = nStart; - lpSelRange->nCount = nCount; - m_SelRangePtrArr.Add(lpSelRange); - m_Param.pEventSink->OnSelChanged(); - return; - } - int32_t nEnd = nStart + nCount - 1; - bool bBegin = false; - int32_t nRangeBgn = 0; - int32_t nRangeCnt = 0; - for (int32_t i = 0; i < nSize; i++) { - lpTemp = m_SelRangePtrArr[i]; - int32_t nTempBgn = lpTemp->nStart; - int32_t nTempEnd = nTempBgn + lpTemp->nCount - 1; - if (bBegin) { - if (nEnd < nTempBgn) { - break; - } else if (nStart >= nTempBgn && nStart <= nTempEnd) { - nRangeCnt++; - break; - } - nRangeCnt++; - } else { - if (nStart <= nTempEnd) { - nRangeBgn = i; - if (nEnd < nTempBgn) { - break; - } - nRangeCnt = 1; - bBegin = true; - } - } - } - if (nRangeCnt == 0) { - FDE_TXTEDTSELRANGE* lpSelRange = new FDE_TXTEDTSELRANGE; - lpSelRange->nStart = nStart; - lpSelRange->nCount = nCount; - m_SelRangePtrArr.InsertAt(nRangeBgn, lpSelRange); - } else { - lpTemp = m_SelRangePtrArr[nRangeBgn]; - lpTemp->nStart = nStart; - lpTemp->nCount = nCount; - nRangeCnt--; - nRangeBgn++; - while (nRangeCnt--) { - delete m_SelRangePtrArr[nRangeBgn]; - m_SelRangePtrArr.RemoveAt(nRangeBgn); - } - } - m_Param.pEventSink->OnSelChanged(); -} - -int32_t CFDE_TxtEdtEngine::CountSelRanges() const { - return m_SelRangePtrArr.GetSize(); -} - -int32_t CFDE_TxtEdtEngine::GetSelRange(int32_t nIndex, int32_t* nStart) const { - if (nStart) - *nStart = m_SelRangePtrArr[nIndex]->nStart; - return m_SelRangePtrArr[nIndex]->nCount; -} - -void CFDE_TxtEdtEngine::ClearSelection() { - int32_t nCount = m_SelRangePtrArr.GetSize(); - for (int i = 0; i < nCount; ++i) - delete m_SelRangePtrArr[i]; - m_SelRangePtrArr.RemoveAll(); - if (nCount && m_Param.pEventSink) - m_Param.pEventSink->OnSelChanged(); -} - -bool CFDE_TxtEdtEngine::Redo(const IFDE_TxtEdtDoRecord* pDoRecord) { - if (IsLocked()) - return false; - return pDoRecord->Redo(); -} - -bool CFDE_TxtEdtEngine::Undo(const IFDE_TxtEdtDoRecord* pDoRecord) { - if (IsLocked()) - return false; - return pDoRecord->Undo(); -} - -int32_t CFDE_TxtEdtEngine::StartLayout() { - Lock(); - RemoveAllPages(); - m_nLayoutPos = 0; - m_nLineCount = 0; - return 0; -} - -int32_t CFDE_TxtEdtEngine::DoLayout(IFX_Pause* pPause) { - int32_t nCount = m_ParagPtrArray.GetSize(); - CFDE_TxtEdtParag* pParag = nullptr; - int32_t nLineCount = 0; - for (; m_nLayoutPos < nCount; m_nLayoutPos++) { - pParag = m_ParagPtrArray[m_nLayoutPos]; - pParag->CalcLines(); - nLineCount += pParag->GetLineCount(); - if (nLineCount > m_nPageLineCount && pPause && pPause->NeedToPauseNow()) { - m_nLineCount += nLineCount; - return (++m_nLayoutPos * 100) / nCount; - } - } - m_nLineCount += nLineCount; - return 100; -} - -void CFDE_TxtEdtEngine::EndLayout() { - UpdatePages(); - int32_t nLength = GetTextLength(); - if (m_nCaret > nLength) - m_nCaret = nLength; - - int32_t nIndex = m_nCaret; - if (!m_bBefore) - nIndex--; - - m_rtCaret = CFX_RectF(0, 0, 1, m_Param.fFontSize); - Unlock(); -} - -CFDE_TxtEdtBuf* CFDE_TxtEdtEngine::GetTextBuf() const { - return m_pTxtBuf.get(); -} - -int32_t CFDE_TxtEdtEngine::GetTextBufLength() const { - return m_pTxtBuf->GetTextLength() - 1; -} - -CFX_TxtBreak* CFDE_TxtEdtEngine::GetTextBreak() const { - return m_pTextBreak.get(); -} - -int32_t CFDE_TxtEdtEngine::GetLineCount() const { - return m_nLineCount; -} - -int32_t CFDE_TxtEdtEngine::GetPageLineCount() const { - return m_nPageLineCount; -} - -int32_t CFDE_TxtEdtEngine::CountParags() const { - return m_ParagPtrArray.GetSize(); -} - -CFDE_TxtEdtParag* CFDE_TxtEdtEngine::GetParag(int32_t nParagIndex) const { - return m_ParagPtrArray[nParagIndex]; -} - -IFX_CharIter* CFDE_TxtEdtEngine::CreateCharIter() { - if (!m_pTxtBuf) - return nullptr; - return new CFDE_TxtEdtBuf::Iterator(m_pTxtBuf.get()); -} - -int32_t CFDE_TxtEdtEngine::Line2Parag(int32_t nStartParag, - int32_t nStartLineofParag, - int32_t nLineIndex, - int32_t& nStartLine) const { - int32_t nLineTotal = nStartLineofParag; - int32_t nCount = m_ParagPtrArray.GetSize(); - CFDE_TxtEdtParag* pParag = nullptr; - int32_t i = nStartParag; - for (; i < nCount; i++) { - pParag = m_ParagPtrArray[i]; - nLineTotal += pParag->GetLineCount(); - if (nLineTotal > nLineIndex) { - break; - } - } - nStartLine = nLineTotal - pParag->GetLineCount(); - return i; -} - -CFX_WideString CFDE_TxtEdtEngine::GetPreDeleteText(int32_t nIndex, - int32_t nLength) { - CFX_WideString wsText = GetText(0, GetTextBufLength()); - wsText.Delete(nIndex, nLength); - return wsText; -} - -CFX_WideString CFDE_TxtEdtEngine::GetPreInsertText(int32_t nIndex, - const FX_WCHAR* lpText, - int32_t nLength) { - CFX_WideString wsText = GetText(0, GetTextBufLength()); - int32_t nSelIndex = 0; - int32_t nSelLength = 0; - int32_t nSelCount = CountSelRanges(); - while (nSelCount--) { - nSelLength = GetSelRange(nSelCount, &nSelIndex); - wsText.Delete(nSelIndex, nSelLength); - nIndex = nSelIndex; - } - CFX_WideString wsTemp; - int32_t nOldLength = wsText.GetLength(); - const FX_WCHAR* pOldBuffer = wsText.c_str(); - FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nOldLength + nLength); - FXSYS_memcpy(lpBuffer, pOldBuffer, (nIndex) * sizeof(FX_WCHAR)); - FXSYS_memcpy(lpBuffer + nIndex, lpText, nLength * sizeof(FX_WCHAR)); - FXSYS_memcpy(lpBuffer + nIndex + nLength, pOldBuffer + nIndex, - (nOldLength - nIndex) * sizeof(FX_WCHAR)); - wsTemp.ReleaseBuffer(nOldLength + nLength); - wsText = wsTemp; - return wsText; -} - -CFX_WideString CFDE_TxtEdtEngine::GetPreReplaceText(int32_t nIndex, - int32_t nOriginLength, - const FX_WCHAR* lpText, - int32_t nLength) { - CFX_WideString wsText = GetText(0, GetTextBufLength()); - int32_t nSelIndex = 0; - int32_t nSelLength = 0; - int32_t nSelCount = CountSelRanges(); - while (nSelCount--) { - nSelLength = GetSelRange(nSelCount, &nSelIndex); - wsText.Delete(nSelIndex, nSelLength); - } - wsText.Delete(nIndex, nOriginLength); - int32_t i = 0; - for (i = 0; i < nLength; i++) - wsText.Insert(nIndex++, lpText[i]); - - return wsText; -} - -void CFDE_TxtEdtEngine::Inner_Insert(int32_t nStart, - const FX_WCHAR* lpText, - int32_t nLength) { - ASSERT(nLength > 0); - FDE_TXTEDTPARAGPOS ParagPos; - TextPos2ParagPos(nStart, ParagPos); - m_Param.pEventSink->OnPageUnload(m_nCaretPage); - int32_t nParagCount = m_ParagPtrArray.GetSize(); - int32_t i = 0; - for (i = ParagPos.nParagIndex + 1; i < nParagCount; i++) - m_ParagPtrArray[i]->IncrementStartIndex(nLength); - - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; - int32_t nReserveLineCount = pParag->GetLineCount(); - int32_t nReserveCharStart = pParag->GetStartIndex(); - int32_t nLeavePart = ParagPos.nCharIndex; - int32_t nCutPart = pParag->GetTextLength() - ParagPos.nCharIndex; - int32_t nTextStart = 0; - FX_WCHAR wCurChar = L' '; - const FX_WCHAR* lpPos = lpText; - bool bFirst = true; - int32_t nParagIndex = ParagPos.nParagIndex; - for (i = 0; i < nLength; i++, lpPos++) { - wCurChar = *lpPos; - if (wCurChar == m_wLineEnd) { - if (bFirst) { - pParag->SetTextLength(nLeavePart + (i - nTextStart + 1)); - pParag->SetLineCount(-1); - nReserveCharStart += pParag->GetTextLength(); - bFirst = false; - } else { - pParag = new CFDE_TxtEdtParag(this); - pParag->SetLineCount(-1); - pParag->SetTextLength(i - nTextStart + 1); - pParag->SetStartIndex(nReserveCharStart); - m_ParagPtrArray.InsertAt(++nParagIndex, pParag); - nReserveCharStart += pParag->GetTextLength(); - } - nTextStart = i + 1; - } - } - if (bFirst) { - pParag->IncrementTextLength(nLength); - pParag->SetLineCount(-1); - bFirst = false; - } else { - pParag = new CFDE_TxtEdtParag(this); - pParag->SetLineCount(-1); - pParag->SetTextLength(nLength - nTextStart + nCutPart); - pParag->SetStartIndex(nReserveCharStart); - m_ParagPtrArray.InsertAt(++nParagIndex, pParag); - } - m_pTxtBuf->Insert(nStart, lpText, nLength); - int32_t nTotalLineCount = 0; - for (i = ParagPos.nParagIndex; i <= nParagIndex; i++) { - pParag = m_ParagPtrArray[i]; - pParag->CalcLines(); - nTotalLineCount += pParag->GetLineCount(); - } - m_nLineCount += nTotalLineCount - nReserveLineCount; - m_Param.pEventSink->OnPageLoad(m_nCaretPage); - UpdatePages(); -} - -void CFDE_TxtEdtEngine::Inner_DeleteRange(int32_t nStart, int32_t nCount) { - if (nCount == -1) { - nCount = m_pTxtBuf->GetTextLength() - nStart; - } - int32_t nEnd = nStart + nCount - 1; - ASSERT(nStart >= 0 && nEnd < m_pTxtBuf->GetTextLength()); - m_Param.pEventSink->OnPageUnload(m_nCaretPage); - FDE_TXTEDTPARAGPOS ParagPosBgn, ParagPosEnd; - TextPos2ParagPos(nStart, ParagPosBgn); - TextPos2ParagPos(nEnd, ParagPosEnd); - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPosEnd.nParagIndex]; - bool bLastParag = false; - if (ParagPosEnd.nCharIndex == pParag->GetTextLength() - 1) { - if (ParagPosEnd.nParagIndex < m_ParagPtrArray.GetSize() - 1) { - ParagPosEnd.nParagIndex++; - } else { - bLastParag = true; - } - } - int32_t nTotalLineCount = 0; - int32_t nTotalCharCount = 0; - int32_t i = 0; - for (i = ParagPosBgn.nParagIndex; i <= ParagPosEnd.nParagIndex; i++) { - CFDE_TxtEdtParag* pTextParag = m_ParagPtrArray[i]; - pTextParag->CalcLines(); - nTotalLineCount += pTextParag->GetLineCount(); - nTotalCharCount += pTextParag->GetTextLength(); - } - m_pTxtBuf->Delete(nStart, nCount); - int32_t nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag) - ? ParagPosBgn.nParagIndex - : (ParagPosBgn.nParagIndex + 1); - for (i = nNextParagIndex; i <= ParagPosEnd.nParagIndex; i++) { - delete m_ParagPtrArray[nNextParagIndex]; - m_ParagPtrArray.RemoveAt(nNextParagIndex); - } - if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) { - pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex]; - pParag->SetTextLength(nTotalCharCount - nCount); - pParag->CalcLines(); - nTotalLineCount -= pParag->GetTextLength(); - } - int32_t nParagCount = m_ParagPtrArray.GetSize(); - for (i = nNextParagIndex; i < nParagCount; i++) - m_ParagPtrArray[i]->DecrementStartIndex(nCount); - - m_nLineCount -= nTotalLineCount; - UpdatePages(); - int32_t nPageCount = CountPages(); - if (m_nCaretPage >= nPageCount) { - m_nCaretPage = nPageCount - 1; - } - m_Param.pEventSink->OnPageLoad(m_nCaretPage); -} - -void CFDE_TxtEdtEngine::DeleteRange_DoRecord(int32_t nStart, - int32_t nCount, - bool bSel) { - ASSERT(nStart >= 0); - if (nCount == -1) { - nCount = GetTextLength() - nStart; - } - ASSERT((nStart + nCount) <= m_pTxtBuf->GetTextLength()); - - CFX_WideString wsRange = m_pTxtBuf->GetRange(nStart, nCount); - m_Param.pEventSink->OnAddDoRecord( - pdfium::MakeUnique<CFDE_TxtEdtDoRecord_DeleteRange>( - this, nStart, m_nCaret, wsRange, bSel)); - - m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; - m_ChangeInfo.wsDelete = GetText(nStart, nCount); - Inner_DeleteRange(nStart, nCount); -} - -void CFDE_TxtEdtEngine::ResetEngine() { - RemoveAllPages(); - RemoveAllParags(); - ClearSelection(); - m_nCaret = 0; - m_pTxtBuf->Clear(false); - m_nCaret = 0; -} - -void CFDE_TxtEdtEngine::RebuildParagraphs() { - RemoveAllParags(); - FX_WCHAR wChar = L' '; - int32_t nParagStart = 0; - int32_t nIndex = 0; - std::unique_ptr<IFX_CharIter> pIter( - new CFDE_TxtEdtBuf::Iterator(m_pTxtBuf.get())); - pIter->SetAt(0); - do { - wChar = pIter->GetChar(); - nIndex = pIter->GetAt(); - if (wChar == m_wLineEnd) { - CFDE_TxtEdtParag* pParag = new CFDE_TxtEdtParag(this); - pParag->SetStartIndex(nParagStart); - pParag->SetTextLength(nIndex - nParagStart + 1); - pParag->SetLineCount(-1); - m_ParagPtrArray.Add(pParag); - nParagStart = nIndex + 1; - } - } while (pIter->Next()); -} - -void CFDE_TxtEdtEngine::RemoveAllParags() { - for (int32_t i = 0; i < m_ParagPtrArray.GetSize(); ++i) - delete m_ParagPtrArray[i]; - m_ParagPtrArray.RemoveAll(); -} - -void CFDE_TxtEdtEngine::RemoveAllPages() { - for (int32_t i = 0; i < m_PagePtrArray.GetSize(); i++) - delete m_PagePtrArray[i]; - m_PagePtrArray.RemoveAll(); -} - -void CFDE_TxtEdtEngine::UpdateParags() { - int32_t nCount = m_ParagPtrArray.GetSize(); - if (nCount == 0) { - return; - } - CFDE_TxtEdtParag* pParag = nullptr; - int32_t nLineCount = 0; - int32_t i = 0; - for (i = 0; i < nCount; i++) { - pParag = m_ParagPtrArray[i]; - if (pParag->GetLineCount() == -1) - pParag->CalcLines(); - - nLineCount += pParag->GetLineCount(); - } - m_nLineCount = nLineCount; -} - -void CFDE_TxtEdtEngine::UpdatePages() { - if (m_nLineCount == 0) - return; - - int32_t nPageCount = (m_nLineCount - 1) / (m_nPageLineCount) + 1; - int32_t nSize = m_PagePtrArray.GetSize(); - if (nSize == nPageCount) - return; - - if (nSize > nPageCount) { - for (int32_t i = nSize - 1; i >= nPageCount; i--) { - delete m_PagePtrArray[i]; - m_PagePtrArray.RemoveAt(i); - } - return; - } - if (nSize < nPageCount) { - for (int32_t i = nSize; i < nPageCount; i++) - m_PagePtrArray.Add(IFDE_TxtEdtPage::Create(this, i)); - return; - } -} - -void CFDE_TxtEdtEngine::UpdateTxtBreak() { - uint32_t dwStyle = m_pTextBreak->GetLayoutStyles(); - if (m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines) { - dwStyle &= ~FX_TXTLAYOUTSTYLE_SingleLine; - } else { - dwStyle |= FX_TXTLAYOUTSTYLE_SingleLine; - } - dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalLayout; - dwStyle &= ~FX_TXTLAYOUTSTYLE_ReverseLine; - dwStyle &= ~FX_TXTLAYOUTSTYLE_RTLReadingOrder; - - if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) { - dwStyle |= FX_TXTLAYOUTSTYLE_CombText; - } else { - dwStyle &= ~FX_TXTLAYOUTSTYLE_CombText; - } - - dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalChars; - dwStyle &= ~FX_TXTLAYOUTSTYLE_ExpandTab; - dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicContext; - dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicShapes; - - m_pTextBreak->SetLayoutStyles(dwStyle); - uint32_t dwAligment = 0; - if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Justified) { - dwAligment |= FX_TXTLINEALIGNMENT_Justified; - } - if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Center) { - dwAligment |= FX_TXTLINEALIGNMENT_Center; - } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Right) { - dwAligment |= FX_TXTLINEALIGNMENT_Right; - } - m_pTextBreak->SetAlignment(dwAligment); - - if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { - m_pTextBreak->SetLineWidth(m_Param.fPlateWidth); - } else { - m_pTextBreak->SetLineWidth(kPageWidthMax); - } - - m_nPageLineCount = m_Param.nLineCount; - if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) { - FX_FLOAT fCombWidth = m_Param.fPlateWidth; - if (m_nLimit > 0) { - fCombWidth /= m_nLimit; - } - m_pTextBreak->SetCombWidth(fCombWidth); - } - m_pTextBreak->SetFont(m_Param.pFont); - m_pTextBreak->SetFontSize(m_Param.fFontSize); - m_pTextBreak->SetTabWidth(m_Param.fTabWidth, m_Param.bTabEquidistant); - m_pTextBreak->SetDefaultChar(m_Param.wDefChar); - m_pTextBreak->SetParagraphBreakChar(m_Param.wLineBreakChar); - m_pTextBreak->SetCharRotation(m_Param.nCharRotation); - m_pTextBreak->SetLineBreakTolerance(m_Param.fFontSize * 0.2f); - m_pTextBreak->SetHorizontalScale(m_Param.nHorzScale); - m_pTextBreak->SetCharSpace(m_Param.fCharSpace); -} - -bool CFDE_TxtEdtEngine::ReplaceParagEnd(FX_WCHAR*& lpText, - int32_t& nLength, - bool bPreIsCR) { - for (int32_t i = 0; i < nLength; i++) { - FX_WCHAR wc = lpText[i]; - switch (wc) { - case L'\r': { - lpText[i] = m_wLineEnd; - bPreIsCR = true; - } break; - case L'\n': { - if (bPreIsCR == true) { - int32_t nNext = i + 1; - if (nNext < nLength) { - FXSYS_memmove(lpText + i, lpText + nNext, - (nLength - nNext) * sizeof(FX_WCHAR)); - } - i--; - nLength--; - bPreIsCR = false; - if (m_bAutoLineEnd) { - m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CRLF; - m_bAutoLineEnd = false; - } - } else { - lpText[i] = m_wLineEnd; - if (m_bAutoLineEnd) { - m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_LF; - m_bAutoLineEnd = false; - } - } - } break; - default: { - if (bPreIsCR && m_bAutoLineEnd) { - m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CR; - m_bAutoLineEnd = false; - } - bPreIsCR = false; - } break; - } - } - return bPreIsCR; -} - -void CFDE_TxtEdtEngine::RecoverParagEnd(CFX_WideString& wsText) const { - FX_WCHAR wc = (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CR) ? L'\n' : L'\r'; - if (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CRLF) { - CFX_ArrayTemplate<int32_t> PosArr; - int32_t nLength = wsText.GetLength(); - int32_t i = 0; - FX_WCHAR* lpPos = const_cast<FX_WCHAR*>(wsText.c_str()); - for (i = 0; i < nLength; i++, lpPos++) { - if (*lpPos == m_wLineEnd) { - *lpPos = wc; - PosArr.Add(i); - } - } - const FX_WCHAR* lpSrcBuf = wsText.c_str(); - CFX_WideString wsTemp; - int32_t nCount = PosArr.GetSize(); - FX_WCHAR* lpDstBuf = wsTemp.GetBuffer(nLength + nCount); - int32_t nDstPos = 0; - int32_t nSrcPos = 0; - for (i = 0; i < nCount; i++) { - int32_t nPos = PosArr[i]; - int32_t nCopyLen = nPos - nSrcPos + 1; - FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, - nCopyLen * sizeof(FX_WCHAR)); - nDstPos += nCopyLen; - nSrcPos += nCopyLen; - lpDstBuf[nDstPos] = L'\n'; - nDstPos++; - } - if (nSrcPos < nLength) { - FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, - (nLength - nSrcPos) * sizeof(FX_WCHAR)); - } - wsTemp.ReleaseBuffer(nLength + nCount); - wsText = wsTemp; - } else { - int32_t nLength = wsText.GetLength(); - FX_WCHAR* lpBuf = const_cast<FX_WCHAR*>(wsText.c_str()); - for (int32_t i = 0; i < nLength; i++, lpBuf++) { - if (*lpBuf == m_wLineEnd) - *lpBuf = wc; - } - } -} - -int32_t CFDE_TxtEdtEngine::MovePage2Char(int32_t nIndex) { - ASSERT(nIndex >= 0); - ASSERT(nIndex <= m_pTxtBuf->GetTextLength()); - if (m_nCaretPage >= 0) { - IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; - m_Param.pEventSink->OnPageLoad(m_nCaretPage); - int32_t nPageCharStart = pPage->GetCharStart(); - int32_t nPageCharCount = pPage->GetCharCount(); - if (nIndex >= nPageCharStart && nIndex < nPageCharStart + nPageCharCount) { - m_Param.pEventSink->OnPageUnload(m_nCaretPage); - return m_nCaretPage; - } - m_Param.pEventSink->OnPageUnload(m_nCaretPage); - } - CFDE_TxtEdtParag* pParag = nullptr; - int32_t nLineCount = 0; - int32_t nParagCount = m_ParagPtrArray.GetSize(); - int32_t i = 0; - for (i = 0; i < nParagCount; i++) { - pParag = m_ParagPtrArray[i]; - if (pParag->GetStartIndex() <= nIndex && - nIndex < (pParag->GetStartIndex() + pParag->GetTextLength())) { - break; - } - nLineCount += pParag->GetLineCount(); - } - pParag->LoadParag(); - int32_t nLineStart = -1; - int32_t nLineCharCount = -1; - for (i = 0; i < pParag->GetLineCount(); i++) { - pParag->GetLineRange(i, nLineStart, nLineCharCount); - if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount)) - break; - } - ASSERT(i < pParag->GetLineCount()); - nLineCount += (i + 1); - m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1; - pParag->UnloadParag(); - return m_nCaretPage; -} - -void CFDE_TxtEdtEngine::TextPos2ParagPos(int32_t nIndex, - FDE_TXTEDTPARAGPOS& ParagPos) const { - ASSERT(nIndex >= 0 && nIndex < m_pTxtBuf->GetTextLength()); - int32_t nCount = m_ParagPtrArray.GetSize(); - int32_t nBgn = 0; - int32_t nMid = 0; - int32_t nEnd = nCount - 1; - while (nEnd > nBgn) { - nMid = (nBgn + nEnd) / 2; - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nMid]; - if (nIndex < pParag->GetStartIndex()) - nEnd = nMid - 1; - else if (nIndex >= (pParag->GetStartIndex() + pParag->GetTextLength())) - nBgn = nMid + 1; - else - break; - } - if (nBgn == nEnd) - nMid = nBgn; - - ASSERT(nIndex >= m_ParagPtrArray[nMid]->GetStartIndex() && - (nIndex < m_ParagPtrArray[nMid]->GetStartIndex() + - m_ParagPtrArray[nMid]->GetTextLength())); - ParagPos.nParagIndex = nMid; - ParagPos.nCharIndex = nIndex - m_ParagPtrArray[nMid]->GetStartIndex(); -} - -int32_t CFDE_TxtEdtEngine::MoveForward(bool& bBefore) { - if (m_nCaret == m_pTxtBuf->GetTextLength() - 1) - return -1; - - int32_t nCaret = m_nCaret; - if ((nCaret + 1 < m_pTxtBuf->GetTextLength()) && - (m_pTxtBuf->GetCharByIndex(nCaret) == L'\r') && - (m_pTxtBuf->GetCharByIndex(nCaret + 1) == L'\n')) { - nCaret++; - } - nCaret++; - bBefore = true; - return nCaret; -} - -int32_t CFDE_TxtEdtEngine::MoveBackward(bool& bBefore) { - if (m_nCaret == 0) - return false; - - int32_t nCaret = m_nCaret; - if (nCaret > 2 && m_pTxtBuf->GetCharByIndex(nCaret - 1) == L'\n' && - m_pTxtBuf->GetCharByIndex(nCaret - 2) == L'\r') { - nCaret--; - } - nCaret--; - bBefore = true; - return nCaret; -} - -bool CFDE_TxtEdtEngine::MoveUp(CFX_PointF& ptCaret) { - IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage); - const CFX_RectF& rtContent = pPage->GetContentsBox(); - ptCaret.x = m_fCaretPosReserve; - ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 - m_Param.fLineSpace; - if (ptCaret.y < rtContent.top) { - if (m_nCaretPage == 0) { - return false; - } - ptCaret.y -= rtContent.top; - m_nCaretPage--; - IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); - ptCaret.y += pCurPage->GetContentsBox().bottom(); - } - - return true; -} - -bool CFDE_TxtEdtEngine::MoveDown(CFX_PointF& ptCaret) { - IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage); - const CFX_RectF& rtContent = pPage->GetContentsBox(); - ptCaret.x = m_fCaretPosReserve; - ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 + m_Param.fLineSpace; - if (ptCaret.y >= rtContent.bottom()) { - if (m_nCaretPage == CountPages() - 1) { - return false; - } - ptCaret.y -= rtContent.bottom(); - m_nCaretPage++; - IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); - ptCaret.y += pCurPage->GetContentsBox().top; - } - return true; -} - -bool CFDE_TxtEdtEngine::MoveLineStart() { - int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; - FDE_TXTEDTPARAGPOS ParagPos; - TextPos2ParagPos(nIndex, ParagPos); - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; - pParag->LoadParag(); - int32_t nLineCount = pParag->GetLineCount(); - int32_t i = 0; - int32_t nStart = 0; - int32_t nCount = 0; - for (; i < nLineCount; i++) { - pParag->GetLineRange(i, nStart, nCount); - if (nIndex >= nStart && nIndex < nStart + nCount) { - break; - } - } - UpdateCaretRect(nStart, true); - pParag->UnloadParag(); - return true; -} - -bool CFDE_TxtEdtEngine::MoveLineEnd() { - int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; - FDE_TXTEDTPARAGPOS ParagPos; - TextPos2ParagPos(nIndex, ParagPos); - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; - pParag->LoadParag(); - int32_t nLineCount = pParag->GetLineCount(); - int32_t i = 0; - int32_t nStart = 0; - int32_t nCount = 0; - for (; i < nLineCount; i++) { - pParag->GetLineRange(i, nStart, nCount); - if (nIndex >= nStart && nIndex < nStart + nCount) { - break; - } - } - nIndex = nStart + nCount - 1; - ASSERT(nIndex <= GetTextBufLength()); - FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex); - bool bBefore = false; - if (nIndex <= GetTextBufLength()) { - if (wChar == L'\r') { - bBefore = true; - } else if (wChar == L'\n' && nIndex > nStart) { - bBefore = true; - nIndex--; - wChar = m_pTxtBuf->GetCharByIndex(nIndex); - if (wChar != L'\r') { - nIndex++; - } - } - } - UpdateCaretRect(nIndex, bBefore); - pParag->UnloadParag(); - return true; -} - -bool CFDE_TxtEdtEngine::MoveParagStart() { - int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; - FDE_TXTEDTPARAGPOS ParagPos; - TextPos2ParagPos(nIndex, ParagPos); - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; - UpdateCaretRect(pParag->GetStartIndex(), true); - return true; -} - -bool CFDE_TxtEdtEngine::MoveParagEnd() { - int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; - FDE_TXTEDTPARAGPOS ParagPos; - TextPos2ParagPos(nIndex, ParagPos); - CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; - nIndex = pParag->GetStartIndex() + pParag->GetTextLength() - 1; - FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex); - if (wChar == L'\n' && nIndex > 0) { - nIndex--; - wChar = m_pTxtBuf->GetCharByIndex(nIndex); - if (wChar != L'\r') { - nIndex++; - } - } - UpdateCaretRect(nIndex, true); - return true; -} - -bool CFDE_TxtEdtEngine::MoveHome() { - UpdateCaretRect(0, true); - return true; -} - -bool CFDE_TxtEdtEngine::MoveEnd() { - UpdateCaretRect(GetTextBufLength(), true); - return true; -} - -bool CFDE_TxtEdtEngine::IsFitArea(CFX_WideString& wsText) { - std::unique_ptr<CFDE_TextOut> pTextOut(new CFDE_TextOut); - pTextOut->SetLineSpace(m_Param.fLineSpace); - pTextOut->SetFont(m_Param.pFont); - pTextOut->SetFontSize(m_Param.fFontSize); - uint32_t dwStyle = 0; - if (!(m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines)) - dwStyle |= FDE_TTOSTYLE_SingleLine; - - CFX_RectF rcText; - if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { - dwStyle |= FDE_TTOSTYLE_LineWrap; - rcText.width = m_Param.fPlateWidth; - } else { - rcText.width = 65535; - } - pTextOut->SetStyles(dwStyle); - wsText += L"\n"; - pTextOut->CalcLogicSize(wsText.c_str(), wsText.GetLength(), rcText); - wsText.Delete(wsText.GetLength() - 1); - if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz) && - (rcText.width > m_Param.fPlateWidth)) { - return false; - } - if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) && - (rcText.height > m_Param.fLineSpace * m_Param.nLineCount)) { - return false; - } - return true; -} - -void CFDE_TxtEdtEngine::UpdateCaretRect(int32_t nIndex, bool bBefore) { - MovePage2Char(nIndex); - GetCaretRect(m_rtCaret, m_nCaretPage, nIndex, bBefore); - m_nCaret = nIndex; - m_bBefore = bBefore; - if (!m_bBefore) { - m_nCaret++; - m_bBefore = true; - } - m_fCaretPosReserve = m_rtCaret.left; - m_Param.pEventSink->OnCaretChanged(); -} - -void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret, - int32_t nPageIndex, - int32_t nCaret, - bool bBefore) { - IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; - m_Param.pEventSink->OnPageLoad(m_nCaretPage); - bool bCombText = !!(m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText); - int32_t nIndexInpage = nCaret - pPage->GetCharStart(); - if (bBefore && bCombText && nIndexInpage > 0) { - nIndexInpage--; - bBefore = false; - } - int32_t nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText); - if ((!FX_IsOdd(nBIDILevel) && !bBefore) || - (FX_IsOdd(nBIDILevel) && bBefore)) { - rtCaret.Offset(rtCaret.width - 1.0f, 0); - } - if (rtCaret.width == 0 && rtCaret.left > 1.0f) - rtCaret.left -= 1.0f; - - rtCaret.width = 1.0f; - - m_Param.pEventSink->OnPageUnload(m_nCaretPage); -} - -void CFDE_TxtEdtEngine::UpdateCaretIndex(const CFX_PointF& ptCaret) { - IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; - m_Param.pEventSink->OnPageLoad(m_nCaretPage); - m_nCaret = pPage->GetCharIndex(ptCaret, m_bBefore); - GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore); - if (!m_bBefore) { - m_nCaret++; - m_bBefore = true; - } - m_Param.pEventSink->OnCaretChanged(); - m_Param.pEventSink->OnPageUnload(m_nCaretPage); -} - -bool CFDE_TxtEdtEngine::IsSelect() { - return m_SelRangePtrArr.GetSize() > 0; -} - -void CFDE_TxtEdtEngine::DeleteSelect() { - int32_t nCountRange = CountSelRanges(); - if (nCountRange > 0) { - int32_t nSelStart = 0; - while (nCountRange > 0) { - int32_t nSelCount = GetSelRange(--nCountRange, &nSelStart); - delete m_SelRangePtrArr[nCountRange]; - m_SelRangePtrArr.RemoveAt(nCountRange); - DeleteRange_DoRecord(nSelStart, nSelCount, true); - } - ClearSelection(); - m_Param.pEventSink->OnTextChanged(m_ChangeInfo); - m_Param.pEventSink->OnSelChanged(); - SetCaretPos(nSelStart, true); - return; - } -} diff --git a/xfa/fde/cfde_txtedtengine.h b/xfa/fde/cfde_txtedtengine.h deleted file mode 100644 index 6918d6305f00e64ebc9356299e3543b0eba072ba..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtengine.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTENGINE_H_ -#define XFA_FDE_CFDE_TXTEDTENGINE_H_ - -#include <memory> - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "xfa/fde/ifde_txtedtengine.h" - -class CFDE_TxtEdtBuf; -class CFDE_TxtEdtParag; -class CFX_TxtBreak; -class IFDE_TxtEdtDoRecord; -class IFX_CharIter; - -class CFDE_TxtEdtEngine { - public: - CFDE_TxtEdtEngine(); - ~CFDE_TxtEdtEngine(); - - void SetEditParams(const FDE_TXTEDTPARAMS& params); - FDE_TXTEDTPARAMS* GetEditParams(); - - int32_t CountPages() const; - IFDE_TxtEdtPage* GetPage(int32_t nIndex); - - void SetTextByStream(const CFX_RetainPtr<IFGAS_Stream>& pStream); - void SetText(const CFX_WideString& wsText); - int32_t GetTextLength() const; - CFX_WideString GetText(int32_t nStart, int32_t nCount) const; - void ClearText(); - - int32_t GetCaretRect(CFX_RectF& rtCaret) const; - int32_t GetCaretPos() const; - int32_t SetCaretPos(int32_t nIndex, bool bBefore); - int32_t MoveCaretPos(FDE_TXTEDTMOVECARET eMoveCaret, - bool bShift = false, - bool bCtrl = false); - void Lock(); - void Unlock(); - bool IsLocked() const; - - int32_t Insert(int32_t nStart, const FX_WCHAR* lpText, int32_t nLength); - int32_t Delete(int32_t nStart, bool bBackspace = false); - int32_t DeleteRange(int32_t nStart, int32_t nCount = -1); - int32_t Replace(int32_t nStart, - int32_t nLength, - const CFX_WideString& wsReplace); - - void SetLimit(int32_t nLimit); - void SetAliasChar(FX_WCHAR wcAlias); - - void RemoveSelRange(int32_t nStart, int32_t nCount); - - void AddSelRange(int32_t nStart, int32_t nCount); - int32_t CountSelRanges() const; - int32_t GetSelRange(int32_t nIndex, int32_t* nStart) const; - void ClearSelection(); - - bool Redo(const IFDE_TxtEdtDoRecord* pRecord); - bool Undo(const IFDE_TxtEdtDoRecord* pRecord); - - int32_t StartLayout(); - int32_t DoLayout(IFX_Pause* pPause); - void EndLayout(); - - int32_t CountParags() const; - CFDE_TxtEdtParag* GetParag(int32_t nParagIndex) const; - IFX_CharIter* CreateCharIter(); - CFDE_TxtEdtBuf* GetTextBuf() const; - int32_t GetTextBufLength() const; - CFX_TxtBreak* GetTextBreak() const; - int32_t GetLineCount() const; - int32_t GetPageLineCount() const; - - int32_t Line2Parag(int32_t nStartParag, - int32_t nStartLineofParag, - int32_t nLineIndex, - int32_t& nStartLine) const; - FX_WCHAR GetAliasChar() const { return m_wcAliasChar; } - - private: - friend class CFDE_TxtEdtDoRecord_Insert; - friend class CFDE_TxtEdtDoRecord_DeleteRange; - friend class CFDE_TxtEdtPage; - - struct FDE_TXTEDTSELRANGE { - int32_t nStart; - int32_t nCount; - }; - - struct FDE_TXTEDTPARAGPOS { - int32_t nParagIndex; - int32_t nCharIndex; - }; - - void Inner_Insert(int32_t nStart, const FX_WCHAR* lpText, int32_t nLength); - CFX_WideString GetPreDeleteText(int32_t nIndex, int32_t nLength); - CFX_WideString GetPreInsertText(int32_t nIndex, - const FX_WCHAR* lpText, - int32_t nLength); - CFX_WideString GetPreReplaceText(int32_t nIndex, - int32_t nOriginLength, - const FX_WCHAR* lpText, - int32_t nLength); - - void Inner_DeleteRange(int32_t nStart, int32_t nCount = -1); - void DeleteRange_DoRecord(int32_t nStart, int32_t nCount, bool bSel = false); - void ResetEngine(); - void RebuildParagraphs(); - void RemoveAllParags(); - void RemoveAllPages(); - void UpdateParags(); - void UpdatePages(); - void UpdateTxtBreak(); - - bool ReplaceParagEnd(FX_WCHAR*& lpText, - int32_t& nLength, - bool bPreIsCR = false); - void RecoverParagEnd(CFX_WideString& wsText) const; - int32_t MovePage2Char(int32_t nIndex); - void TextPos2ParagPos(int32_t nIndex, FDE_TXTEDTPARAGPOS& ParagPos) const; - int32_t MoveForward(bool& bBefore); - int32_t MoveBackward(bool& bBefore); - bool MoveUp(CFX_PointF& ptCaret); - bool MoveDown(CFX_PointF& ptCaret); - bool MoveLineStart(); - bool MoveLineEnd(); - bool MoveParagStart(); - bool MoveParagEnd(); - bool MoveHome(); - bool MoveEnd(); - bool IsFitArea(CFX_WideString& wsText); - void UpdateCaretRect(int32_t nIndex, bool bBefore = true); - void GetCaretRect(CFX_RectF& rtCaret, - int32_t nPageIndex, - int32_t nCaret, - bool bBefore = true); - void UpdateCaretIndex(const CFX_PointF& ptCaret); - - bool IsSelect(); - void DeleteSelect(); - - std::unique_ptr<CFDE_TxtEdtBuf> m_pTxtBuf; - std::unique_ptr<CFX_TxtBreak> m_pTextBreak; - FDE_TXTEDTPARAMS m_Param; - CFX_ArrayTemplate<IFDE_TxtEdtPage*> m_PagePtrArray; - CFX_ArrayTemplate<CFDE_TxtEdtParag*> m_ParagPtrArray; - CFX_ArrayTemplate<FDE_TXTEDTSELRANGE*> m_SelRangePtrArr; - int32_t m_nPageLineCount; - int32_t m_nLineCount; - int32_t m_nAnchorPos; - int32_t m_nLayoutPos; - FX_FLOAT m_fCaretPosReserve; - int32_t m_nCaret; - bool m_bBefore; - int32_t m_nCaretPage; - CFX_RectF m_rtCaret; - uint32_t m_dwFindFlags; - bool m_bLock; - int32_t m_nLimit; - FX_WCHAR m_wcAliasChar; - int32_t m_nFirstLineEnd; - bool m_bAutoLineEnd; - FX_WCHAR m_wLineEnd; - FDE_TXTEDT_TEXTCHANGE_INFO m_ChangeInfo; -}; - -#endif // XFA_FDE_CFDE_TXTEDTENGINE_H_ diff --git a/xfa/fde/cfde_txtedtpage.cpp b/xfa/fde/cfde_txtedtpage.cpp deleted file mode 100644 index 8b58b2b443516c101dc5d8a4bbf5fda69ec6902c..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtpage.cpp +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedtpage.h" - -#include <algorithm> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/cfde_txtedtbuf.h" -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/cfde_txtedtparag.h" -#include "xfa/fde/cfde_txtedttextset.h" -#include "xfa/fde/cfx_wordbreak.h" -#include "xfa/fde/ifde_txtedtengine.h" -#include "xfa/fde/ifde_txtedtpage.h" - -namespace { - -const double kTolerance = 0.1f; - -} // namespace - -IFDE_TxtEdtPage* IFDE_TxtEdtPage::Create(CFDE_TxtEdtEngine* pEngine, - int32_t nIndex) { - return new CFDE_TxtEdtPage(pEngine, nIndex); -} - -CFDE_TxtEdtPage::CFDE_TxtEdtPage(CFDE_TxtEdtEngine* pEngine, int32_t nPageIndex) - : m_pEditEngine(pEngine), - m_pBgnParag(nullptr), - m_pEndParag(nullptr), - m_nRefCount(0), - m_nPageStart(-1), - m_nCharCount(0), - m_nPageIndex(nPageIndex), - m_bLoaded(false) { -} - -CFDE_TxtEdtPage::~CFDE_TxtEdtPage() {} - -CFDE_TxtEdtEngine* CFDE_TxtEdtPage::GetEngine() const { - return m_pEditEngine; -} - -FDE_VISUALOBJTYPE CFDE_TxtEdtPage::GetType() { - return FDE_VISUALOBJ_Text; -} - -CFX_RectF CFDE_TxtEdtPage::GetRect(const FDE_TEXTEDITPIECE& hVisualObj) { - return CFX_RectF(); -} - -int32_t CFDE_TxtEdtPage::GetCharRect(int32_t nIndex, - CFX_RectF& rect, - bool bBBox) const { - ASSERT(m_nRefCount > 0); - ASSERT(nIndex >= 0 && nIndex < m_nCharCount); - if (m_nRefCount < 1) - return 0; - - for (const auto& piece : m_Pieces) { - if (nIndex >= piece.nStart && nIndex < piece.nStart + piece.nCount) { - std::vector<CFX_RectF> rectArr = m_pTextSet->GetCharRects(&piece, bBBox); - rect = rectArr[nIndex - piece.nStart]; - return piece.nBidiLevel; - } - } - ASSERT(0); - return 0; -} - -int32_t CFDE_TxtEdtPage::GetCharIndex(const CFX_PointF& fPoint, bool& bBefore) { - CFX_PointF ptF = fPoint; - NormalizePt2Rect(ptF, m_rtPageContents, kTolerance); - int32_t nCount = pdfium::CollectionSize<int32_t>(m_Pieces); - CFX_RectF rtLine; - int32_t nBgn = 0; - int32_t nEnd = 0; - bool bInLine = false; - int32_t i = 0; - for (i = 0; i < nCount; i++) { - const FDE_TEXTEDITPIECE* pPiece = &m_Pieces[i]; - if (!bInLine && - (pPiece->rtPiece.top <= ptF.y && pPiece->rtPiece.bottom() > ptF.y)) { - nBgn = nEnd = i; - rtLine = pPiece->rtPiece; - bInLine = true; - } else if (bInLine) { - if (pPiece->rtPiece.bottom() <= ptF.y || pPiece->rtPiece.top > ptF.y) { - nEnd = i - 1; - break; - } else { - rtLine.Union(pPiece->rtPiece); - } - } - } - NormalizePt2Rect(ptF, rtLine, kTolerance); - int32_t nCaret = 0; - FDE_TEXTEDITPIECE* pPiece = nullptr; - for (i = nBgn; i <= nEnd; i++) { - pPiece = &m_Pieces[i]; - nCaret = m_nPageStart + pPiece->nStart; - if (pPiece->rtPiece.Contains(ptF)) { - std::vector<CFX_RectF> rectArr = m_pTextSet->GetCharRects(pPiece, false); - int32_t nRtCount = pdfium::CollectionSize<int32_t>(rectArr); - for (int32_t j = 0; j < nRtCount; j++) { - if (rectArr[j].Contains(ptF)) { - nCaret = m_nPageStart + pPiece->nStart + j; - if (nCaret >= m_pEditEngine->GetTextBufLength()) { - bBefore = true; - return m_pEditEngine->GetTextBufLength(); - } - FX_WCHAR wChar = m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret); - if (wChar == L'\n' || wChar == L'\r') { - if (wChar == L'\n') { - if (m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret - 1) == - L'\r') { - nCaret--; - } - } - bBefore = true; - return nCaret; - } - if (ptF.x > ((rectArr[j].left + rectArr[j].right()) / 2)) { - bBefore = FX_IsOdd(pPiece->nBidiLevel); - } else { - bBefore = !FX_IsOdd(pPiece->nBidiLevel); - } - return nCaret; - } - } - } - } - bBefore = true; - return nCaret; -} - -int32_t CFDE_TxtEdtPage::GetCharStart() const { - return m_nPageStart; -} - -int32_t CFDE_TxtEdtPage::GetCharCount() const { - return m_nCharCount; -} - -int32_t CFDE_TxtEdtPage::GetDisplayPos(const CFX_RectF& rtClip, - FXTEXT_CHARPOS*& pCharPos, - CFX_RectF* pBBox) const { - pCharPos = FX_Alloc(FXTEXT_CHARPOS, m_nCharCount); - int32_t nCharPosCount = 0; - FXTEXT_CHARPOS* pos = pCharPos; - for (const auto& piece : m_Pieces) { - if (!rtClip.IntersectWith(m_pTextSet->GetRect(piece))) - continue; - - int32_t nCount = m_pTextSet->GetDisplayPos(piece, pos, false); - nCharPosCount += nCount; - pos += nCount; - } - if ((nCharPosCount * 5) < (m_nCharCount << 2)) { - FXTEXT_CHARPOS* pTemp = FX_Alloc(FXTEXT_CHARPOS, nCharPosCount); - FXSYS_memcpy(pTemp, pCharPos, sizeof(FXTEXT_CHARPOS) * nCharPosCount); - FX_Free(pCharPos); - pCharPos = pTemp; - } - return nCharPosCount; -} - -void CFDE_TxtEdtPage::CalcRangeRectArray( - int32_t nStart, - int32_t nCount, - std::vector<CFX_RectF>* pRectFArr) const { - int32_t nEnd = nStart + nCount - 1; - bool bInRange = false; - for (const auto& piece : m_Pieces) { - if (!bInRange) { - if (nStart >= piece.nStart && nStart < piece.nStart + piece.nCount) { - int32_t nRangeEnd = piece.nCount - 1; - bool bEnd = false; - if (nEnd >= piece.nStart && nEnd < piece.nStart + piece.nCount) { - nRangeEnd = nEnd - piece.nStart; - bEnd = true; - } - std::vector<CFX_RectF> rcArr = m_pTextSet->GetCharRects(&piece, false); - CFX_RectF rectPiece = rcArr[nStart - piece.nStart]; - rectPiece.Union(rcArr[nRangeEnd]); - pRectFArr->push_back(rectPiece); - if (bEnd) - return; - - bInRange = true; - } - } else { - if (nEnd >= piece.nStart && nEnd < piece.nStart + piece.nCount) { - std::vector<CFX_RectF> rcArr = m_pTextSet->GetCharRects(&piece, false); - CFX_RectF rectPiece = rcArr[0]; - rectPiece.Union(rcArr[nEnd - piece.nStart]); - pRectFArr->push_back(rectPiece); - return; - } - pRectFArr->push_back(piece.rtPiece); - } - } -} - -int32_t CFDE_TxtEdtPage::SelectWord(const CFX_PointF& fPoint, int32_t& nCount) { - if (m_nRefCount < 0) { - return -1; - } - CFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf(); - bool bBefore; - int32_t nIndex = GetCharIndex(fPoint, bBefore); - if (nIndex == m_pEditEngine->GetTextBufLength()) { - nIndex = m_pEditEngine->GetTextBufLength() - 1; - } - if (nIndex < 0) { - return -1; - } - std::unique_ptr<CFX_WordBreak> pIter(new CFX_WordBreak); - pIter->Attach(new CFDE_TxtEdtBuf::Iterator(pBuf)); - pIter->SetAt(nIndex); - nCount = pIter->GetWordLength(); - return pIter->GetWordPos(); -} - -bool CFDE_TxtEdtPage::IsLoaded(const CFX_RectF* pClipBox) { - return m_bLoaded; -} - -int32_t CFDE_TxtEdtPage::LoadPage(const CFX_RectF* pClipBox, - IFX_Pause* pPause) { - if (m_nRefCount > 0) { - m_nRefCount++; - return m_nRefCount; - } - CFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf(); - const FDE_TXTEDTPARAMS* pParams = m_pEditEngine->GetEditParams(); - FX_WCHAR wcAlias = 0; - if (pParams->dwMode & FDE_TEXTEDITMODE_Password) { - wcAlias = m_pEditEngine->GetAliasChar(); - } - m_pIter.reset(new CFDE_TxtEdtBuf::Iterator(static_cast<CFDE_TxtEdtBuf*>(pBuf), - wcAlias)); - CFX_TxtBreak* pBreak = m_pEditEngine->GetTextBreak(); - pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - pBreak->ClearBreakPieces(); - int32_t nPageLineCount = m_pEditEngine->GetPageLineCount(); - int32_t nStartLine = nPageLineCount * m_nPageIndex; - int32_t nEndLine = std::min((nStartLine + nPageLineCount - 1), - (m_pEditEngine->GetLineCount() - 1)); - int32_t nPageStart, nPageEnd, nTemp, nBgnParag, nStartLineInParag, nEndParag, - nEndLineInParag; - nBgnParag = m_pEditEngine->Line2Parag(0, 0, nStartLine, nStartLineInParag); - m_pBgnParag = - static_cast<CFDE_TxtEdtParag*>(m_pEditEngine->GetParag(nBgnParag)); - m_pBgnParag->LoadParag(); - m_pBgnParag->GetLineRange(nStartLine - nStartLineInParag, nPageStart, nTemp); - nEndParag = m_pEditEngine->Line2Parag(nBgnParag, nStartLineInParag, nEndLine, - nEndLineInParag); - m_pEndParag = - static_cast<CFDE_TxtEdtParag*>(m_pEditEngine->GetParag(nEndParag)); - m_pEndParag->LoadParag(); - m_pEndParag->GetLineRange(nEndLine - nEndLineInParag, nPageEnd, nTemp); - nPageEnd += (nTemp - 1); - - FX_FLOAT fLineStart = 0.0f; - FX_FLOAT fLineStep = pParams->fLineSpace; - FX_FLOAT fLinePos = fLineStart; - if (!m_pTextSet) - m_pTextSet = pdfium::MakeUnique<CFDE_TxtEdtTextSet>(this); - - m_Pieces.clear(); - uint32_t dwBreakStatus = FX_TXTBREAK_None; - int32_t nPieceStart = 0; - - m_CharWidths.resize(nPageEnd - nPageStart + 1, 0); - pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - pBreak->ClearBreakPieces(); - m_nPageStart = nPageStart; - m_nCharCount = nPageEnd - nPageStart + 1; - bool bReload = false; - FX_FLOAT fDefCharWidth = 0; - std::unique_ptr<IFX_CharIter> pIter(m_pIter->Clone()); - pIter->SetAt(nPageStart); - m_pIter->SetAt(nPageStart); - bool bFirstPiece = true; - do { - if (bReload) { - dwBreakStatus = pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - } else { - FX_WCHAR wAppend = pIter->GetChar(); - dwBreakStatus = pBreak->AppendChar(wAppend); - } - if (pIter->GetAt() == nPageEnd && dwBreakStatus < FX_TXTBREAK_LineBreak) { - dwBreakStatus = pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - } - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - int32_t nPieceCount = pBreak->CountBreakPieces(); - for (int32_t j = 0; j < nPieceCount; j++) { - const CFX_TxtPiece* pPiece = pBreak->GetBreakPiece(j); - FDE_TEXTEDITPIECE TxtEdtPiece; - FXSYS_memset(&TxtEdtPiece, 0, sizeof(FDE_TEXTEDITPIECE)); - TxtEdtPiece.nBidiLevel = pPiece->m_iBidiLevel; - TxtEdtPiece.nCount = pPiece->GetLength(); - TxtEdtPiece.nStart = nPieceStart; - TxtEdtPiece.dwCharStyles = pPiece->m_dwCharStyles; - if (FX_IsOdd(pPiece->m_iBidiLevel)) { - TxtEdtPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; - } - FX_FLOAT fParaBreakWidth = 0.0f; - if (pPiece->m_dwStatus > FX_TXTBREAK_PieceBreak) { - FX_WCHAR wRtChar = pParams->wLineBreakChar; - if (TxtEdtPiece.nCount >= 2) { - FX_WCHAR wChar = pBuf->GetCharByIndex( - m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1); - FX_WCHAR wCharPre = pBuf->GetCharByIndex( - m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 2); - if (wChar == wRtChar) { - fParaBreakWidth += fDefCharWidth; - } - if (wCharPre == wRtChar) { - fParaBreakWidth += fDefCharWidth; - } - } else if (TxtEdtPiece.nCount >= 1) { - FX_WCHAR wChar = pBuf->GetCharByIndex( - m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1); - if (wChar == wRtChar) { - fParaBreakWidth += fDefCharWidth; - } - } - } - - TxtEdtPiece.rtPiece.left = (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; - TxtEdtPiece.rtPiece.top = fLinePos; - TxtEdtPiece.rtPiece.width = - (FX_FLOAT)pPiece->m_iWidth / 20000.0f + fParaBreakWidth; - TxtEdtPiece.rtPiece.height = pParams->fLineSpace; - - if (bFirstPiece) { - m_rtPageContents = TxtEdtPiece.rtPiece; - bFirstPiece = false; - } else { - m_rtPageContents.Union(TxtEdtPiece.rtPiece); - } - nPieceStart += TxtEdtPiece.nCount; - m_Pieces.push_back(TxtEdtPiece); - for (int32_t k = 0; k < TxtEdtPiece.nCount; k++) { - CFX_Char* ptc = pPiece->GetCharPtr(k); - m_CharWidths[TxtEdtPiece.nStart + k] = ptc->m_iCharWidth; - } - } - fLinePos += fLineStep; - pBreak->ClearBreakPieces(); - } - if (pIter->GetAt() == nPageEnd && dwBreakStatus == FX_TXTBREAK_LineBreak) { - bReload = true; - pIter->Next(true); - } - } while (pIter->Next(false) && (pIter->GetAt() <= nPageEnd)); - if (m_rtPageContents.left != 0) { - FX_FLOAT fDelta = 0.0f; - if (m_rtPageContents.width < pParams->fPlateWidth) { - if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Right) { - fDelta = pParams->fPlateWidth - m_rtPageContents.width; - } else if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Center) { - if ((pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) && - m_nCharCount > 1) { - int32_t nCount = m_nCharCount - 1; - int32_t n = (m_pEditEngine->m_nLimit - nCount) / 2; - fDelta = (m_rtPageContents.width / nCount) * n; - } else { - fDelta = (pParams->fPlateWidth - m_rtPageContents.width) / 2; - } - } - } - FX_FLOAT fOffset = m_rtPageContents.left - fDelta; - for (auto& piece : m_Pieces) - piece.rtPiece.Offset(-fOffset, 0.0f); - - m_rtPageContents.Offset(-fOffset, 0.0f); - } - if (m_pEditEngine->GetEditParams()->dwLayoutStyles & - FDE_TEXTEDITLAYOUT_LastLineHeight) { - m_rtPageContents.height -= pParams->fLineSpace - pParams->fFontSize; - m_Pieces.back().rtPiece.height = pParams->fFontSize; - } - m_nRefCount = 1; - m_bLoaded = true; - return 0; -} - -void CFDE_TxtEdtPage::UnloadPage(const CFX_RectF* pClipBox) { - ASSERT(m_nRefCount > 0); - m_nRefCount--; - if (m_nRefCount != 0) - return; - - m_Pieces.clear(); - m_pTextSet.reset(); - m_CharWidths.clear(); - if (m_pBgnParag) { - m_pBgnParag->UnloadParag(); - m_pBgnParag = nullptr; - } - if (m_pEndParag) { - m_pEndParag->UnloadParag(); - m_pEndParag = nullptr; - } - m_pIter.reset(); -} - -const CFX_RectF& CFDE_TxtEdtPage::GetContentsBox() { - return m_rtPageContents; -} - -FX_POSITION CFDE_TxtEdtPage::GetFirstPosition() { - if (m_Pieces.empty()) - return nullptr; - return (FX_POSITION)1; -} - -FDE_TEXTEDITPIECE* CFDE_TxtEdtPage::GetNext(FX_POSITION& pos, - IFDE_VisualSet*& pVisualSet) { - if (!m_pTextSet) { - pos = nullptr; - return nullptr; - } - int32_t nPos = (int32_t)(uintptr_t)pos; - pVisualSet = m_pTextSet.get(); - if (nPos + 1 > pdfium::CollectionSize<int32_t>(m_Pieces)) - pos = nullptr; - else - pos = (FX_POSITION)(uintptr_t)(nPos + 1); - - return &m_Pieces[nPos - 1]; -} - -FX_WCHAR CFDE_TxtEdtPage::GetChar(const FDE_TEXTEDITPIECE* pIdentity, - int32_t index) const { - int32_t nIndex = m_nPageStart + pIdentity->nStart + index; - if (nIndex != m_pIter->GetAt()) - m_pIter->SetAt(nIndex); - - FX_WCHAR wChar = m_pIter->GetChar(); - m_pIter->Next(); - return wChar; -} - -int32_t CFDE_TxtEdtPage::GetWidth(const FDE_TEXTEDITPIECE* pIdentity, - int32_t index) const { - int32_t nWidth = m_CharWidths[pIdentity->nStart + index]; - return nWidth; -} - -void CFDE_TxtEdtPage::NormalizePt2Rect(CFX_PointF& ptF, - const CFX_RectF& rtF, - FX_FLOAT fTolerance) const { - if (rtF.Contains(ptF)) - return; - if (ptF.x < rtF.left) - ptF.x = rtF.left; - else if (ptF.x >= rtF.right()) - ptF.x = rtF.right() - fTolerance; - - if (ptF.y < rtF.top) - ptF.y = rtF.top; - else if (ptF.y >= rtF.bottom()) - ptF.y = rtF.bottom() - fTolerance; -} diff --git a/xfa/fde/cfde_txtedtpage.h b/xfa/fde/cfde_txtedtpage.h deleted file mode 100644 index 63ec7e7cf36d4d7488acc83be58e90bc02f761d4..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtpage.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTPAGE_H_ -#define XFA_FDE_CFDE_TXTEDTPAGE_H_ - -#include <deque> -#include <memory> -#include <vector> - -#include "xfa/fde/ifde_txtedtpage.h" -#include "xfa/fde/ifx_chariter.h" - -class CFDE_TxtEdtEngine; -class CFDE_TxtEdtParag; -class CFDE_TxtEdtTextSet; - -class CFDE_TxtEdtPage : public IFDE_TxtEdtPage { - public: - CFDE_TxtEdtPage(CFDE_TxtEdtEngine* pEngine, int32_t nLineIndex); - ~CFDE_TxtEdtPage() override; - - // IFDE_TxtEditPage: - CFDE_TxtEdtEngine* GetEngine() const override; - int32_t GetCharRect(int32_t nIndex, - CFX_RectF& rect, - bool bBBox = false) const override; - int32_t GetCharIndex(const CFX_PointF& fPoint, bool& bBefore) override; - void CalcRangeRectArray(int32_t nStart, - int32_t nCount, - std::vector<CFX_RectF>* RectFArr) const override; - int32_t SelectWord(const CFX_PointF& fPoint, int32_t& nCount) override; - int32_t GetCharStart() const override; - int32_t GetCharCount() const override; - int32_t GetDisplayPos(const CFX_RectF& rtClip, - FXTEXT_CHARPOS*& pCharPos, - CFX_RectF* pBBox) const override; - bool IsLoaded(const CFX_RectF* pClipBox) override; - int32_t LoadPage(const CFX_RectF* pClipBox, IFX_Pause* pPause) override; - void UnloadPage(const CFX_RectF* pClipBox) override; - const CFX_RectF& GetContentsBox() override; - - // IFDE_VisualSet: - FDE_VISUALOBJTYPE GetType() override; - CFX_RectF GetRect(const FDE_TEXTEDITPIECE& pPiece) override; - - // IFDE_CanvasSet: - FX_POSITION GetFirstPosition() override; - FDE_TEXTEDITPIECE* GetNext(FX_POSITION& pos, - IFDE_VisualSet*& pVisualSet) override; - - // IFX_TxtAccess: - FX_WCHAR GetChar(const FDE_TEXTEDITPIECE* pIdentity, - int32_t index) const override; - int32_t GetWidth(const FDE_TEXTEDITPIECE* pIdentity, - int32_t index) const override; - - private: - void NormalizePt2Rect(CFX_PointF& ptF, - const CFX_RectF& rtF, - FX_FLOAT fTolerance) const; - - std::unique_ptr<IFX_CharIter> m_pIter; - std::unique_ptr<CFDE_TxtEdtTextSet> m_pTextSet; - CFDE_TxtEdtEngine* const m_pEditEngine; - std::deque<FDE_TEXTEDITPIECE> m_Pieces; - CFDE_TxtEdtParag* m_pBgnParag; - CFDE_TxtEdtParag* m_pEndParag; - int32_t m_nRefCount; - int32_t m_nPageStart; - int32_t m_nCharCount; - int32_t m_nPageIndex; - bool m_bLoaded; - CFX_RectF m_rtPage; - CFX_RectF m_rtPageMargin; - CFX_RectF m_rtPageContents; - CFX_RectF m_rtPageCanvas; - std::vector<int32_t> m_CharWidths; -}; - -#endif // XFA_FDE_CFDE_TXTEDTPAGE_H_ diff --git a/xfa/fde/cfde_txtedtparag.cpp b/xfa/fde/cfde_txtedtparag.cpp deleted file mode 100644 index f9f88bfb5d14071419d220d65a032c5782b52876..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtparag.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedtparag.h" - -#include <memory> - -#include "xfa/fde/cfde_txtedtbuf.h" -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/ifde_txtedtengine.h" -#include "xfa/fde/ifx_chariter.h" -#include "xfa/fgas/layout/fgas_textbreak.h" - -CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine) - : m_nCharStart(0), - m_nCharCount(0), - m_nLineCount(0), - m_lpData(nullptr), - m_pEngine(pEngine) { - ASSERT(m_pEngine); -} - -CFDE_TxtEdtParag::~CFDE_TxtEdtParag() { - if (m_lpData) - FX_Free(m_lpData); -} - -void CFDE_TxtEdtParag::LoadParag() { - if (m_lpData) { - m_lpData[0]++; - return; - } - CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak(); - CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf(); - const FDE_TXTEDTPARAMS* pParam = m_pEngine->GetEditParams(); - FX_WCHAR wcAlias = 0; - if (pParam->dwMode & FDE_TEXTEDITMODE_Password) { - wcAlias = m_pEngine->GetAliasChar(); - } - std::unique_ptr<IFX_CharIter> pIter(new CFDE_TxtEdtBuf::Iterator( - static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), wcAlias)); - pIter->SetAt(m_nCharStart); - int32_t nEndIndex = m_nCharStart + m_nCharCount; - CFX_ArrayTemplate<int32_t> LineBaseArr; - bool bReload = false; - uint32_t dwBreakStatus = FX_TXTBREAK_None; - do { - if (bReload) { - dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - } else { - FX_WCHAR wAppend = pIter->GetChar(); - dwBreakStatus = pTxtBreak->AppendChar(wAppend); - } - if (pIter->GetAt() + 1 == nEndIndex && - dwBreakStatus < FX_TXTBREAK_LineBreak) { - dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - } - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - int32_t nCount = pTxtBreak->CountBreakPieces(); - int32_t nTotal = 0; - for (int32_t j = 0; j < nCount; j++) { - const CFX_TxtPiece* Piece = pTxtBreak->GetBreakPiece(j); - nTotal += Piece->GetLength(); - } - LineBaseArr.Add(nTotal); - pTxtBreak->ClearBreakPieces(); - } - if ((pIter->GetAt() + 1 == nEndIndex) && - (dwBreakStatus == FX_TXTBREAK_LineBreak)) { - bReload = true; - pIter->Next(true); - } - } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex)); - pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - pTxtBreak->ClearBreakPieces(); - int32_t nLineCount = LineBaseArr.GetSize(); - m_nLineCount = nLineCount; - if (m_lpData) { - m_lpData = FX_Realloc(int32_t, m_lpData, nLineCount + 1); - } else { - m_lpData = FX_Alloc(int32_t, nLineCount + 1); - } - int32_t* pIntArr = m_lpData; - pIntArr[0] = 1; - m_nLineCount = nLineCount; - pIntArr++; - for (int32_t j = 0; j < nLineCount; j++, pIntArr++) { - *pIntArr = LineBaseArr[j]; - } - LineBaseArr.RemoveAll(); -} - -void CFDE_TxtEdtParag::UnloadParag() { - m_lpData[0]--; - ASSERT(m_lpData[0] >= 0); - if (m_lpData[0] == 0) { - FX_Free(m_lpData); - m_lpData = nullptr; - } -} - -void CFDE_TxtEdtParag::CalcLines() { - CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak(); - CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf(); - int32_t nCount = 0; - uint32_t dwBreakStatus = FX_TXTBREAK_None; - int32_t nEndIndex = m_nCharStart + m_nCharCount; - std::unique_ptr<IFX_CharIter> pIter( - new CFDE_TxtEdtBuf::Iterator(static_cast<CFDE_TxtEdtBuf*>(pTxtBuf))); - pIter->SetAt(m_nCharStart); - bool bReload = false; - do { - if (bReload) { - dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - } else { - FX_WCHAR wAppend = pIter->GetChar(); - dwBreakStatus = pTxtBreak->AppendChar(wAppend); - } - if (pIter->GetAt() + 1 == nEndIndex && - dwBreakStatus < FX_TXTBREAK_LineBreak) { - dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - } - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - nCount++; - pTxtBreak->ClearBreakPieces(); - } - if ((pIter->GetAt() + 1 == nEndIndex) && - (dwBreakStatus == FX_TXTBREAK_LineBreak)) { - bReload = true; - pIter->Next(true); - } - } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex)); - pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - pTxtBreak->ClearBreakPieces(); - m_nLineCount = nCount; -} - -void CFDE_TxtEdtParag::GetLineRange(int32_t nLineIndex, - int32_t& nStart, - int32_t& nCount) const { - int32_t* pLineBaseArr = m_lpData; - ASSERT(nLineIndex < m_nLineCount); - nStart = m_nCharStart; - pLineBaseArr++; - for (int32_t i = 0; i < nLineIndex; i++) { - nStart += *pLineBaseArr; - pLineBaseArr++; - } - nCount = *pLineBaseArr; -} diff --git a/xfa/fde/cfde_txtedtparag.h b/xfa/fde/cfde_txtedtparag.h deleted file mode 100644 index 4521f3be0ceecf1f541f8f1fbef281510d35eff9..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedtparag.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTPARAG_H_ -#define XFA_FDE_CFDE_TXTEDTPARAG_H_ - -#include <stdint.h> - -class CFDE_TxtEdtEngine; - -class CFDE_TxtEdtParag { - public: - explicit CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine); - ~CFDE_TxtEdtParag(); - - int32_t GetTextLength() const { return m_nCharCount; } - int32_t GetStartIndex() const { return m_nCharStart; } - int32_t GetLineCount() const { return m_nLineCount; } - - void SetTextLength(int32_t len) { m_nCharCount = len; } - void IncrementTextLength(int32_t len) { m_nCharCount += len; } - void SetStartIndex(int32_t idx) { m_nCharStart = idx; } - void IncrementStartIndex(int32_t val) { m_nCharStart += val; } - void DecrementStartIndex(int32_t val) { m_nCharStart -= val; } - void SetLineCount(int32_t count) { m_nLineCount = count; } - - void GetLineRange(int32_t nLineIndex, int32_t& nStart, int32_t& nCount) const; - void LoadParag(); - void UnloadParag(); - void CalcLines(); - - private: - int32_t m_nCharStart; - int32_t m_nCharCount; - int32_t m_nLineCount; - int32_t* m_lpData; - CFDE_TxtEdtEngine* m_pEngine; -}; - -#endif // XFA_FDE_CFDE_TXTEDTPARAG_H_ diff --git a/xfa/fde/cfde_txtedttextset.cpp b/xfa/fde/cfde_txtedttextset.cpp deleted file mode 100644 index 8d32f75ff394decabeba2b8c6987e5c244d110b7..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedttextset.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfde_txtedttextset.h" - -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/cfde_txtedtpage.h" -#include "xfa/fgas/font/cfgas_gefont.h" - -CFDE_TxtEdtTextSet::CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage) - : m_pPage(pPage) {} - -CFDE_TxtEdtTextSet::~CFDE_TxtEdtTextSet() {} - -FDE_VISUALOBJTYPE CFDE_TxtEdtTextSet::GetType() { - return FDE_VISUALOBJ_Text; -} - -CFX_RectF CFDE_TxtEdtTextSet::GetRect(const FDE_TEXTEDITPIECE& pPiece) { - return pPiece.rtPiece; -} - -int32_t CFDE_TxtEdtTextSet::GetString(FDE_TEXTEDITPIECE* pPiece, - CFX_WideString& wsText) { - FX_WCHAR* pBuffer = wsText.GetBuffer(pPiece->nCount); - for (int32_t i = 0; i < pPiece->nCount; i++) - pBuffer[i] = m_pPage->GetChar(pPiece, i); - - wsText.ReleaseBuffer(pPiece->nCount); - return pPiece->nCount; -} - -CFX_RetainPtr<CFGAS_GEFont> CFDE_TxtEdtTextSet::GetFont() { - return m_pPage->GetEngine()->GetEditParams()->pFont; -} - -FX_FLOAT CFDE_TxtEdtTextSet::GetFontSize() { - return m_pPage->GetEngine()->GetEditParams()->fFontSize; -} - -FX_ARGB CFDE_TxtEdtTextSet::GetFontColor() { - return m_pPage->GetEngine()->GetEditParams()->dwFontColor; -} - -int32_t CFDE_TxtEdtTextSet::GetDisplayPos(const FDE_TEXTEDITPIECE& piece, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode, - CFX_WideString* pWSForms) { - int32_t nLength = piece.nCount; - if (nLength < 1) - return 0; - - CFDE_TxtEdtEngine* pEngine = - static_cast<CFDE_TxtEdtEngine*>(m_pPage->GetEngine()); - const FDE_TXTEDTPARAMS* pTextParams = pEngine->GetEditParams(); - CFX_TxtBreak* pBreak = pEngine->GetTextBreak(); - uint32_t dwLayoutStyle = pBreak->GetLayoutStyles(); - FX_TXTRUN tr; - tr.pAccess = m_pPage; - tr.pIdentity = &piece; - tr.iLength = nLength; - tr.pFont = pTextParams->pFont; - tr.fFontSize = pTextParams->fFontSize; - tr.dwStyles = dwLayoutStyle; - tr.iCharRotation = pTextParams->nCharRotation; - tr.dwCharStyles = piece.dwCharStyles; - tr.pRect = &piece.rtPiece; - tr.wLineBreakChar = pTextParams->wLineBreakChar; - return pBreak->GetDisplayPos(&tr, pCharPos, bCharCode, pWSForms); -} - -std::vector<CFX_RectF> CFDE_TxtEdtTextSet::GetCharRects( - const FDE_TEXTEDITPIECE* pPiece, - bool bBBox) { - if (!pPiece || pPiece->nCount < 1) - return std::vector<CFX_RectF>(); - - auto pEngine = static_cast<CFDE_TxtEdtEngine*>(m_pPage->GetEngine()); - const FDE_TXTEDTPARAMS* pTextParams = pEngine->GetEditParams(); - uint32_t dwLayoutStyle = pEngine->GetTextBreak()->GetLayoutStyles(); - FX_TXTRUN tr; - tr.pAccess = m_pPage; - tr.pIdentity = pPiece; - tr.iLength = pPiece->nCount; - tr.pFont = pTextParams->pFont; - tr.fFontSize = pTextParams->fFontSize; - tr.dwStyles = dwLayoutStyle; - tr.iCharRotation = pTextParams->nCharRotation; - tr.dwCharStyles = pPiece->dwCharStyles; - tr.pRect = &pPiece->rtPiece; - tr.wLineBreakChar = pTextParams->wLineBreakChar; - return pEngine->GetTextBreak()->GetCharRects(&tr, bBBox); -} diff --git a/xfa/fde/cfde_txtedttextset.h b/xfa/fde/cfde_txtedttextset.h deleted file mode 100644 index 8ab65787931b6100a1c6ff6e8a554358f8d54b64..0000000000000000000000000000000000000000 --- a/xfa/fde/cfde_txtedttextset.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFDE_TXTEDTTEXTSET_H_ -#define XFA_FDE_CFDE_TXTEDTTEXTSET_H_ - -#include <vector> - -#include "xfa/fde/fde_visualset.h" - -class CFDE_TxtEdtPage; - -class CFDE_TxtEdtTextSet : public IFDE_TextSet { - public: - explicit CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage); - ~CFDE_TxtEdtTextSet() override; - - // IFDE_VisualSet - FDE_VISUALOBJTYPE GetType() override; - CFX_RectF GetRect(const FDE_TEXTEDITPIECE& hVisualObj) override; - - // IFDE_TextSet - int32_t GetString(FDE_TEXTEDITPIECE* pPiece, CFX_WideString& wsText) override; - CFX_RetainPtr<CFGAS_GEFont> GetFont() override; - FX_FLOAT GetFontSize() override; - FX_ARGB GetFontColor() override; - int32_t GetDisplayPos(const FDE_TEXTEDITPIECE& pPiece, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode = false, - CFX_WideString* pWSForms = nullptr) override; - std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE* pPiece, - bool bBBox) override; - - private: - CFDE_TxtEdtPage* const m_pPage; -}; - -#endif // XFA_FDE_CFDE_TXTEDTTEXTSET_H_ diff --git a/xfa/fde/cfde_wordbreak_data.cpp b/xfa/fde/cfde_wordbreak_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c4864be690d5ab24a45792709c0755df7107e12 --- /dev/null +++ b/xfa/fde/cfde_wordbreak_data.cpp @@ -0,0 +1,2849 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fde/cfde_wordbreak_data.h" + +namespace { + +enum WordBreakValue : uint16_t { + kWordBreakValueNone = 1 << 0, + kWordBreakValueCR = 1 << 1, + kWordBreakValueLF = 1 << 2, + kWordBreakValueNewLine = 1 << 3, + kWordBreakValueExtend = 1 << 4, + kWordBreakValueFormat = 1 << 5, + kWordBreakValueKataKana = 1 << 6, + kWordBreakValueALetter = 1 << 7, + kWordBreakValueMidLetter = 1 << 8, + kWordBreakValueMidNum = 1 << 9, + kWordBreakValueMidNumLet = 1 << 10, + kWordBreakValueNumeric = 1 << 11, + kWordBreakValueExtendNumLet = 1 << 12, +}; + +static_assert(kWordBreakValueNone == + (1 << static_cast<int>(WordBreakProperty::kNone)), + "WordBreakValue must match"); +static_assert(kWordBreakValueCR == + (1 << static_cast<int>(WordBreakProperty::kCR)), + "WordBreakValue must match"); +static_assert(kWordBreakValueLF == + (1 << static_cast<int>(WordBreakProperty::kLF)), + "WordBreakValue must match"); +static_assert(kWordBreakValueNewLine == + (1 << static_cast<int>(WordBreakProperty::kNewLine)), + "WordBreakValue must match"); +static_assert(kWordBreakValueExtend == + (1 << static_cast<int>(WordBreakProperty::kExtend)), + "WordBreakValue must match"); +static_assert(kWordBreakValueFormat == + (1 << static_cast<int>(WordBreakProperty::kFormat)), + "WordBreakValue must match"); +static_assert(kWordBreakValueKataKana == + (1 << static_cast<int>(WordBreakProperty::kKataKana)), + "WordBreakValue must match"); +static_assert(kWordBreakValueALetter == + (1 << static_cast<int>(WordBreakProperty::kALetter)), + "WordBreakValue must match"); +static_assert(kWordBreakValueMidLetter == + (1 << static_cast<int>(WordBreakProperty::kMidLetter)), + "WordBreakValue must match"); +static_assert(kWordBreakValueMidNum == + (1 << static_cast<int>(WordBreakProperty::kMidNum)), + "WordBreakValue must match"); +static_assert(kWordBreakValueMidNumLet == + (1 << static_cast<int>(WordBreakProperty::kMidNumLet)), + "WordBreakValue must match"); +static_assert(kWordBreakValueNumeric == + (1 << static_cast<int>(WordBreakProperty::kNumeric)), + "WordBreakValue must match"); +static_assert(kWordBreakValueExtendNumLet == + (1 << static_cast<int>(WordBreakProperty::kExtendNumLet)), + "WordBreakValue must match"); + +} // namespace + +const uint16_t gs_FX_WordBreak_Table[] = { + // WordBreakProperty::kNone + 0xFFFF, + + // WordBreakProperty::kCR + static_cast<uint16_t>(~(kWordBreakValueLF | kWordBreakValueCR)), + + // WordBreakProperty::kLF + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakProperty::kNewLine + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakProperty::kExtend + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakPropery:: kFormat + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakProperty::kKataKana + static_cast<uint16_t>(~(kWordBreakValueLF | kWordBreakValueKataKana | + kWordBreakValueExtendNumLet)), + + // WordBreakProperty::kALetter + static_cast<uint16_t>(~(kWordBreakValueLF | kWordBreakValueALetter | + kWordBreakValueNumeric | + kWordBreakValueExtendNumLet)), + + // WordBreakProperty::kMidLetter + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakProperty::kMidNum + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakProperty::kMidNumLet + static_cast<uint16_t>(~(kWordBreakValueLF)), + + // WordBreakProperty::kNumeric + static_cast<uint16_t>(~(kWordBreakValueLF | kWordBreakValueALetter | + kWordBreakValueNumeric | + kWordBreakValueExtendNumLet)), + + // WordBreakProperty::kExtendNumLet + static_cast<uint16_t>(~(kWordBreakValueLF | kWordBreakValueKataKana | + kWordBreakValueALetter | kWordBreakValueNumeric | + kWordBreakValueExtendNumLet)), +}; + +const uint8_t gs_FX_WordBreak_CodePointProperties[(0xFFFF - 1) / 2 + 1] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x90, 0xA0, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x89, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x0C, + 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x05, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x70, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x70, 0x00, + 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x77, 0x77, 0x70, 0x77, + 0x00, 0x77, 0x77, 0x90, 0x00, 0x00, 0x00, 0x78, 0x77, 0x70, 0x70, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x04, 0x44, 0x44, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, + 0x07, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x04, 0x04, 0x40, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x70, 0x00, 0x00, 0x77, 0x77, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x40, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x0B, 0x90, 0x77, 0x47, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x44, + 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x47, 0x74, 0x40, 0x44, 0x44, 0x77, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x77, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x74, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x07, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, 0x77, 0x00, + 0x90, 0x70, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x44, 0x44, 0x74, 0x44, 0x44, 0x44, 0x44, 0x74, 0x44, + 0x74, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x40, 0x74, 0x44, 0x44, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x07, 0x70, 0x00, 0x00, + 0x07, 0x77, 0x77, 0x77, 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x07, + 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x77, 0x77, 0x77, 0x70, 0x70, 0x00, 0x77, 0x77, 0x00, 0x47, 0x44, + 0x44, 0x44, 0x40, 0x04, 0x40, 0x04, 0x44, 0x70, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x77, 0x07, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x07, 0x77, + 0x77, 0x70, 0x00, 0x07, 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x07, 0x70, + 0x77, 0x00, 0x40, 0x44, 0x44, 0x40, 0x00, 0x04, 0x40, 0x04, 0x44, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x77, 0x70, 0x70, 0x00, 0x00, 0x00, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0x44, 0x77, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x77, 0x07, 0x77, 0x07, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, + 0x70, 0x77, 0x07, 0x77, 0x77, 0x00, 0x47, 0x44, 0x44, 0x44, 0x44, 0x04, + 0x44, 0x04, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x07, + 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x07, 0x77, 0x77, 0x00, 0x47, 0x44, + 0x44, 0x44, 0x40, 0x04, 0x40, 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x00, 0x00, 0x77, 0x07, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x07, 0x77, + 0x77, 0x70, 0x00, 0x77, 0x70, 0x77, 0x77, 0x00, 0x07, 0x70, 0x70, 0x77, + 0x00, 0x07, 0x70, 0x00, 0x77, 0x70, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x44, 0x44, 0x40, 0x00, 0x44, 0x40, 0x44, 0x44, 0x00, + 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x07, 0x77, 0x77, 0x00, 0x07, 0x44, 0x44, 0x44, 0x40, 0x44, + 0x40, 0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x40, 0x77, 0x00, 0x00, 0x00, + 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x77, + 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x77, 0x77, 0x00, 0x47, 0x44, + 0x44, 0x44, 0x40, 0x44, 0x40, 0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x40, + 0x00, 0x00, 0x00, 0x70, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x07, 0x77, + 0x77, 0x77, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x07, 0x44, 0x44, 0x44, 0x40, 0x44, 0x40, 0x44, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x77, 0x44, 0x00, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, + 0x00, 0x44, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, + 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x07, 0x00, 0x77, 0x77, 0x77, 0x70, + 0x00, 0x40, 0x00, 0x04, 0x44, 0x44, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x40, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x44, 0x44, + 0x44, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x44, 0x77, 0x77, 0x77, 0x77, + 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x04, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x44, 0x77, 0x77, 0x00, 0x00, + 0x44, 0x44, 0x44, 0x44, 0x04, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x40, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x40, 0x44, 0x40, 0x04, + 0x44, 0x44, 0x44, 0x00, 0x04, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x04, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x44, 0x44, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x70, 0x70, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x70, 0x70, 0x77, 0x77, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x70, + 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x70, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x77, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, + 0x77, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, + 0x70, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x74, 0x70, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, + 0x44, 0x44, 0x44, 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x04, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x44, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x47, 0x77, + 0x77, 0x77, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, + 0x44, 0x40, 0x00, 0x77, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x07, 0x77, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x47, 0x77, 0x74, 0x77, 0x77, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x07, 0x07, 0x07, 0x07, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x70, 0x00, 0x77, 0x70, 0x77, + 0x77, 0x77, 0x70, 0x00, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x77, 0x70, 0x77, + 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x55, + 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x08, + 0x33, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, + 0xC0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0x00, 0x00, 0x55, 0x55, 0x55, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x07, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x00, + 0x07, 0x77, 0x77, 0x00, 0x00, 0x00, 0x70, 0x70, 0x70, 0x77, 0x77, 0x07, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x00, 0x00, 0x07, 0x77, + 0x77, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, + 0x00, 0x07, 0x77, 0x74, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x70, + 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, + 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, + 0x77, 0x77, 0x77, 0x70, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, + 0x06, 0x66, 0x66, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x46, 0x60, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x66, 0x66, 0x00, 0x00, 0x07, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x07, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x70, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x74, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x44, 0x07, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, + 0x77, 0x47, 0x77, 0x47, 0x77, 0x74, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x77, 0x77, 0x77, 0x00, 0x07, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, + 0x44, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x74, 0x77, 0x77, 0x77, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x44, 0x40, 0x04, + 0x40, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, 0x40, 0x44, 0x00, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x07, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x77, 0x77, 0x00, 0x00, 0x07, 0x47, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x70, 0x70, + 0x77, 0x07, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x90, 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xCC, 0x90, 0xA0, 0x98, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x05, + 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x89, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x0C, 0x07, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x44, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, + 0x00, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, + 0x00, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x00, 0x00, +}; diff --git a/xfa/fde/cfde_wordbreak_data.h b/xfa/fde/cfde_wordbreak_data.h new file mode 100644 index 0000000000000000000000000000000000000000..28e26cc4fe851eb3df712932fae32a518ee331eb --- /dev/null +++ b/xfa/fde/cfde_wordbreak_data.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FDE_CFDE_WORDBREAK_DATA_H_ +#define XFA_FDE_CFDE_WORDBREAK_DATA_H_ + +#include <stdint.h> + +enum class WordBreakProperty : uint8_t { + kNone = 0, + kCR, + kLF, + kNewLine, + kExtend, + kFormat, + kKataKana, + kALetter, + kMidLetter, + kMidNum, + kMidNumLet, + kNumeric, + kExtendNumLet, +}; + +extern const uint16_t gs_FX_WordBreak_Table[]; +extern const uint8_t gs_FX_WordBreak_CodePointProperties[]; + +#endif // XFA_FDE_CFDE_WORDBREAK_DATA_H_ diff --git a/xfa/fde/cfx_chariter.cpp b/xfa/fde/cfx_chariter.cpp deleted file mode 100644 index 568ecd6cf0d85bd49458f573377789fbdccf21a3..0000000000000000000000000000000000000000 --- a/xfa/fde/cfx_chariter.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfx_chariter.h" - -CFX_CharIter::CFX_CharIter(const CFX_WideString& wsText) - : m_wsText(wsText), m_nIndex(0) { - ASSERT(!wsText.IsEmpty()); -} - -CFX_CharIter::~CFX_CharIter() {} - -bool CFX_CharIter::Next(bool bPrev) { - if (bPrev) { - if (m_nIndex <= 0) - return false; - m_nIndex--; - } else { - if (m_nIndex + 1 >= m_wsText.GetLength()) - return false; - m_nIndex++; - } - return true; -} - -FX_WCHAR CFX_CharIter::GetChar() { - return m_wsText.GetAt(m_nIndex); -} - -void CFX_CharIter::SetAt(int32_t nIndex) { - if (nIndex < 0 || nIndex >= m_wsText.GetLength()) - return; - m_nIndex = nIndex; -} - -int32_t CFX_CharIter::GetAt() const { - return m_nIndex; -} - -bool CFX_CharIter::IsEOF(bool bTail) const { - return bTail ? (m_nIndex + 1 == m_wsText.GetLength()) : (m_nIndex == 0); -} - -IFX_CharIter* CFX_CharIter::Clone() { - CFX_CharIter* pIter = new CFX_CharIter(m_wsText); - pIter->m_nIndex = m_nIndex; - return pIter; -} diff --git a/xfa/fde/cfx_chariter.h b/xfa/fde/cfx_chariter.h deleted file mode 100644 index d122af21f1997f8e119a13a724f659469c786024..0000000000000000000000000000000000000000 --- a/xfa/fde/cfx_chariter.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFX_CHARITER_H_ -#define XFA_FDE_CFX_CHARITER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/ifx_chariter.h" - -class CFX_CharIter : public IFX_CharIter { - public: - explicit CFX_CharIter(const CFX_WideString& wsText); - ~CFX_CharIter() override; - - bool Next(bool bPrev = false) override; - FX_WCHAR GetChar() override; - void SetAt(int32_t nIndex) override; - int32_t GetAt() const override; - bool IsEOF(bool bTail = true) const override; - IFX_CharIter* Clone() override; - - private: - const CFX_WideString& m_wsText; - int32_t m_nIndex; -}; - -#endif // XFA_FDE_CFX_CHARITER_H_ diff --git a/xfa/fde/cfx_wordbreak.cpp b/xfa/fde/cfx_wordbreak.cpp deleted file mode 100644 index 2d37ba1707e9d2fb2ff00355879002d515511bbf..0000000000000000000000000000000000000000 --- a/xfa/fde/cfx_wordbreak.cpp +++ /dev/null @@ -1,2946 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/cfx_wordbreak.h" - -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "xfa/fde/cfx_chariter.h" - -namespace { - -enum FX_WordBreakProp { - FX_WordBreakProp_None = 0, - FX_WordBreakProp_CR, - FX_WordBreakProp_LF, - FX_WordBreakProp_NewLine, - FX_WordBreakProp_Extend, - FX_WordBreakProp_Format, - FX_WordBreakProp_KataKana, - FX_WordBreakProp_ALetter, - FX_WordBreakProp_MidLetter, - FX_WordBreakProp_MidNum, - FX_WordBreakProp_MidNumLet, - FX_WordBreakProp_Numberic, - FX_WordBreakProp_ExtendNumLet, -}; - -const uint16_t gs_FX_WordBreak_Table[16] = { - 0xFFFF, 0xFFF9, 0xFFFB, 0xFFFB, 0xFFFB, 0xFFFB, 0xEFBB, 0xE77B, - 0xFFFB, 0xFFFB, 0xFFFB, 0xE77B, 0xE73B, 0xFFFB, 0xFFFB, 0xFFFB, -}; - -const uint8_t gs_FX_WordBreak_CodePointProperties[(0xFFFF - 1) / 2 + 1] = - // NOLINTNEXTLINE - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x90, 0xA0, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x89, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x0C, - 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0x05, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x70, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x70, 0x00, - 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x77, 0x77, 0x70, 0x77, - 0x00, 0x77, 0x77, 0x90, 0x00, 0x00, 0x00, 0x78, 0x77, 0x70, 0x70, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x04, 0x44, 0x44, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, - 0x07, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x04, 0x04, 0x40, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x70, 0x00, 0x00, 0x77, 0x77, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x40, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x0B, 0x90, 0x77, 0x47, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x44, - 0x44, 0x44, 0x45, 0x44, 0x44, 0x44, 0x47, 0x74, 0x40, 0x44, 0x44, 0x77, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x77, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x74, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x07, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, 0x77, 0x00, - 0x90, 0x70, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x44, 0x44, 0x74, 0x44, 0x44, 0x44, 0x44, 0x74, 0x44, - 0x74, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x40, 0x74, 0x44, 0x44, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x07, 0x70, 0x00, 0x00, - 0x07, 0x77, 0x77, 0x77, 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x07, - 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x70, 0x77, 0x77, 0x77, 0x70, 0x70, 0x00, 0x77, 0x77, 0x00, 0x47, 0x44, - 0x44, 0x44, 0x40, 0x04, 0x40, 0x04, 0x44, 0x70, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x77, 0x07, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, - 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x07, 0x77, - 0x77, 0x70, 0x00, 0x07, 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x07, 0x70, - 0x77, 0x00, 0x40, 0x44, 0x44, 0x40, 0x00, 0x04, 0x40, 0x04, 0x44, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x07, 0x77, 0x70, 0x70, 0x00, 0x00, 0x00, 0xBB, - 0xBB, 0xBB, 0xBB, 0xBB, 0x44, 0x77, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x77, 0x07, 0x77, 0x07, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, - 0x70, 0x77, 0x07, 0x77, 0x77, 0x00, 0x47, 0x44, 0x44, 0x44, 0x44, 0x04, - 0x44, 0x04, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x07, - 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x07, 0x77, 0x77, 0x00, 0x47, 0x44, - 0x44, 0x44, 0x40, 0x04, 0x40, 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x00, 0x00, 0x77, 0x07, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x07, 0x77, - 0x77, 0x70, 0x00, 0x77, 0x70, 0x77, 0x77, 0x00, 0x07, 0x70, 0x70, 0x77, - 0x00, 0x07, 0x70, 0x00, 0x77, 0x70, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x00, 0x00, 0x44, 0x44, 0x40, 0x00, 0x44, 0x40, 0x44, 0x44, 0x00, - 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, - 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x07, 0x77, 0x77, 0x00, 0x07, 0x44, 0x44, 0x44, 0x40, 0x44, - 0x40, 0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x40, 0x77, 0x00, 0x00, 0x00, - 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x07, 0x77, 0x77, 0x77, 0x70, 0x77, - 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x77, 0x77, 0x00, 0x47, 0x44, - 0x44, 0x44, 0x40, 0x44, 0x40, 0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x40, - 0x00, 0x00, 0x00, 0x70, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x07, 0x77, - 0x77, 0x77, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x00, 0x07, 0x44, 0x44, 0x44, 0x40, 0x44, 0x40, 0x44, 0x44, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x77, 0x44, 0x00, 0xBB, - 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, - 0x00, 0x44, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, - 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x07, 0x00, 0x77, 0x77, 0x77, 0x70, - 0x00, 0x40, 0x00, 0x04, 0x44, 0x44, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x40, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x44, 0x44, - 0x44, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x44, 0x77, 0x77, 0x77, 0x77, - 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x04, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x44, 0x77, 0x77, 0x00, 0x00, - 0x44, 0x44, 0x44, 0x44, 0x04, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x40, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x40, 0x44, 0x40, 0x04, - 0x44, 0x44, 0x44, 0x00, 0x04, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x04, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x44, 0x44, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x70, 0x70, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x70, 0x70, 0x77, 0x77, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x70, - 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x70, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x70, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x77, 0x70, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, - 0x77, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, - 0x70, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x74, 0x70, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, - 0x44, 0x44, 0x44, 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x04, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x44, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x47, 0x77, - 0x77, 0x77, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x47, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, - 0x44, 0x40, 0x00, 0x77, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x07, 0x77, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x47, 0x77, 0x74, 0x77, 0x77, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x07, 0x07, 0x07, 0x07, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x70, 0x00, 0x77, 0x70, 0x77, - 0x77, 0x77, 0x70, 0x00, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x77, 0x70, 0x77, - 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x55, - 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x08, - 0x33, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, - 0xC0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0x00, 0x00, 0x55, 0x55, 0x55, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0x00, 0x07, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x07, 0x00, - 0x07, 0x77, 0x77, 0x00, 0x00, 0x00, 0x70, 0x70, 0x70, 0x77, 0x77, 0x07, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x00, 0x00, 0x07, 0x77, - 0x77, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, - 0x00, 0x07, 0x77, 0x74, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x70, - 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, - 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x70, - 0x77, 0x77, 0x77, 0x70, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, - 0x06, 0x66, 0x66, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x46, 0x60, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x66, 0x66, 0x00, 0x00, 0x07, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x07, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x70, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x74, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x44, 0x07, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x70, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x77, - 0x77, 0x47, 0x77, 0x47, 0x77, 0x74, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x77, 0x77, 0x77, 0x00, 0x07, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x44, 0x44, 0x44, 0x44, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, - 0x44, 0x44, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x74, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x74, 0x77, 0x77, 0x77, 0x77, 0x44, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, - 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x44, 0x40, 0x04, - 0x40, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x74, 0x44, 0x44, 0x44, 0x40, 0x44, 0x00, - 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x07, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x77, 0x77, 0x00, 0x00, 0x07, 0x47, 0x77, 0x77, 0x77, 0x77, - 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x77, 0x77, 0x70, 0x70, - 0x77, 0x07, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x90, 0x08, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xCC, 0x90, 0xA0, 0x98, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x77, 0x70, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x05, - 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x89, 0x00, 0x00, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x0C, 0x07, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x44, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x70, - 0x00, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, - 0x00, 0x77, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x00, 0x00, -}; - -FX_WordBreakProp GetWordBreakProperty(FX_WCHAR wcCodePoint) { - uint32_t dwProperty = - (uint32_t)gs_FX_WordBreak_CodePointProperties[wcCodePoint >> 1]; - return (FX_WordBreakProp)(((wcCodePoint)&1) ? (dwProperty & 0x0F) - : (dwProperty >> 4)); -} - -} // namespace - -CFX_WordBreak::CFX_WordBreak() {} - -CFX_WordBreak::~CFX_WordBreak() {} - -void CFX_WordBreak::Attach(IFX_CharIter* pIter) { - ASSERT(pIter); - m_pCurIter.reset(pIter); -} - -void CFX_WordBreak::Attach(const CFX_WideString& wsText) { - m_pCurIter = pdfium::MakeUnique<CFX_CharIter>(wsText); -} - -bool CFX_WordBreak::Next(bool bPrev) { - std::unique_ptr<IFX_CharIter> pIter( - (bPrev ? m_pPreIter : m_pCurIter)->Clone()); - if (pIter->IsEOF(!bPrev)) - return false; - - pIter->Next(bPrev); - if (!FindNextBreakPos(pIter.get(), bPrev, true)) - return false; - - if (bPrev) { - m_pCurIter = std::move(m_pPreIter); - m_pCurIter->Next(true); - m_pPreIter = std::move(pIter); - } else { - m_pPreIter = std::move(m_pCurIter); - m_pPreIter->Next(); - m_pCurIter = std::move(pIter); - } - return true; -} - -void CFX_WordBreak::SetAt(int32_t nIndex) { - m_pPreIter.reset(); - m_pCurIter->SetAt(nIndex); - FindNextBreakPos(m_pCurIter.get(), true, false); - m_pPreIter = std::move(m_pCurIter); - m_pCurIter.reset(m_pPreIter->Clone()); - FindNextBreakPos(m_pCurIter.get(), false, false); -} - -int32_t CFX_WordBreak::GetWordPos() const { - return m_pPreIter->GetAt(); -} - -int32_t CFX_WordBreak::GetWordLength() const { - return m_pCurIter->GetAt() - m_pPreIter->GetAt() + 1; -} - -void CFX_WordBreak::GetWord(CFX_WideString& wsWord) const { - int32_t nWordLength = GetWordLength(); - if (nWordLength <= 0) { - return; - } - FX_WCHAR* lpBuf = wsWord.GetBuffer(nWordLength); - std::unique_ptr<IFX_CharIter> pTempIter(m_pPreIter->Clone()); - int32_t i = 0; - while (pTempIter->GetAt() <= m_pCurIter->GetAt()) { - lpBuf[i++] = pTempIter->GetChar(); - if (!pTempIter->Next()) - break; - } - wsWord.ReleaseBuffer(nWordLength); -} - -bool CFX_WordBreak::IsEOF(bool bTail) const { - return m_pCurIter->IsEOF(bTail); -} - -bool CFX_WordBreak::FindNextBreakPos(IFX_CharIter* pIter, - bool bPrev, - bool bFromNext) { - FX_WordBreakProp ePreType = FX_WordBreakProp_None; - FX_WordBreakProp eCurType = FX_WordBreakProp_None; - FX_WordBreakProp eNextType = FX_WordBreakProp_None; - if (pIter->IsEOF(!bPrev)) { - return true; - } - if (!(bFromNext || pIter->IsEOF(bPrev))) { - pIter->Next(!bPrev); - ePreType = GetWordBreakProperty(pIter->GetChar()); - pIter->Next(bPrev); - } - eCurType = GetWordBreakProperty(pIter->GetChar()); - bool bFirst = true; - do { - pIter->Next(bPrev); - eNextType = GetWordBreakProperty(pIter->GetChar()); - uint16_t wBreak = - gs_FX_WordBreak_Table[eCurType] & ((uint16_t)(1 << eNextType)); - if (wBreak) { - if (pIter->IsEOF(!bPrev)) { - pIter->Next(!bPrev); - return true; - } - if (bFirst) { - int32_t nFlags = 0; - if (eCurType == FX_WordBreakProp_MidLetter) { - if (eNextType == FX_WordBreakProp_ALetter) { - nFlags = 1; - } - } else if (eCurType == FX_WordBreakProp_MidNum) { - if (eNextType == FX_WordBreakProp_Numberic) { - nFlags = 2; - } - } else if (eCurType == FX_WordBreakProp_MidNumLet) { - if (eNextType == FX_WordBreakProp_ALetter) { - nFlags = 1; - } else if (eNextType == FX_WordBreakProp_Numberic) { - nFlags = 2; - } - } - if (nFlags > 0) { - ASSERT(nFlags <= 2); - if (!((nFlags == 1 && ePreType == FX_WordBreakProp_ALetter) || - (nFlags == 2 && ePreType == FX_WordBreakProp_Numberic))) { - pIter->Next(!bPrev); - return true; - } - pIter->Next(bPrev); - wBreak = false; - } - bFirst = false; - } - if (wBreak) { - int32_t nFlags = 0; - if (eNextType == FX_WordBreakProp_MidLetter) { - if (eCurType == FX_WordBreakProp_ALetter) { - nFlags = 1; - } - } else if (eNextType == FX_WordBreakProp_MidNum) { - if (eCurType == FX_WordBreakProp_Numberic) { - nFlags = 2; - } - } else if (eNextType == FX_WordBreakProp_MidNumLet) { - if (eCurType == FX_WordBreakProp_ALetter) { - nFlags = 1; - } else if (eCurType == FX_WordBreakProp_Numberic) { - nFlags = 2; - } - } - if (nFlags <= 0) { - pIter->Next(!bPrev); - return true; - } - ASSERT(nFlags <= 2); - pIter->Next(bPrev); - eNextType = (FX_WordBreakProp)GetWordBreakProperty(pIter->GetChar()); - if (!((nFlags == 1 && eNextType == FX_WordBreakProp_ALetter) || - (nFlags == 2 && eNextType == FX_WordBreakProp_Numberic))) { - pIter->Next(!bPrev); - pIter->Next(!bPrev); - return true; - } - } - } - ePreType = eCurType; - eCurType = eNextType; - bFirst = false; - } while (!pIter->IsEOF(!bPrev)); - return true; -} diff --git a/xfa/fde/cfx_wordbreak.h b/xfa/fde/cfx_wordbreak.h deleted file mode 100644 index 9df6eda1f590de3c2e6ccccbf1a176517f035169..0000000000000000000000000000000000000000 --- a/xfa/fde/cfx_wordbreak.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CFX_WORDBREAK_H_ -#define XFA_FDE_CFX_WORDBREAK_H_ - -#include <memory> - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" - -class IFX_CharIter; - -class CFX_WordBreak { - public: - CFX_WordBreak(); - ~CFX_WordBreak(); - - void Attach(IFX_CharIter* pIter); - void Attach(const CFX_WideString& wsText); - bool Next(bool bPrev); - void SetAt(int32_t nIndex); - int32_t GetWordPos() const; - int32_t GetWordLength() const; - void GetWord(CFX_WideString& wsWord) const; - bool IsEOF(bool bTail) const; - - protected: - bool FindNextBreakPos(IFX_CharIter* pIter, bool bPrev, bool bFromNext = true); - - private: - std::unique_ptr<IFX_CharIter> m_pPreIter; - std::unique_ptr<IFX_CharIter> m_pCurIter; -}; - -#endif // XFA_FDE_CFX_WORDBREAK_H_ diff --git a/xfa/fde/css/cfde_csscolorvalue.cpp b/xfa/fde/css/cfde_csscolorvalue.cpp deleted file mode 100644 index 015355136c918c0539b644255e66bfceb2531869..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csscolorvalue.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_csscolorvalue.h" - -CFDE_CSSColorValue::CFDE_CSSColorValue(FX_ARGB value) - : CFDE_CSSValue(FDE_CSSPrimitiveType::RGB), value_(value) {} - -CFDE_CSSColorValue::~CFDE_CSSColorValue() {} diff --git a/xfa/fde/css/cfde_csscolorvalue.h b/xfa/fde/css/cfde_csscolorvalue.h deleted file mode 100644 index 1d0441ad2a570df05452526d1cb861cf24573e7a..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csscolorvalue.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSCOLORVALUE_H_ -#define XFA_FDE_CSS_CFDE_CSSCOLORVALUE_H_ - -#include "xfa/fde/css/cfde_cssvalue.h" - -class CFDE_CSSColorValue : public CFDE_CSSValue { - public: - explicit CFDE_CSSColorValue(FX_ARGB color); - ~CFDE_CSSColorValue() override; - - FX_ARGB Value() const { return value_; } - - private: - FX_ARGB value_; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSCOLORVALUE_H_ diff --git a/xfa/fde/css/cfde_csscomputedstyle.cpp b/xfa/fde/css/cfde_csscomputedstyle.cpp deleted file mode 100644 index 01872d18fc4b8c23bb276acb163d67b22e2ed929..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csscomputedstyle.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_csscomputedstyle.h" - -#include "third_party/base/stl_util.h" -#include "xfa/fde/css/cfde_cssstringvalue.h" -#include "xfa/fde/css/cfde_cssvaluelist.h" - -CFDE_CSSComputedStyle::CFDE_CSSComputedStyle() {} - -CFDE_CSSComputedStyle::~CFDE_CSSComputedStyle() {} - -bool CFDE_CSSComputedStyle::GetCustomStyle(const CFX_WideString& wsName, - CFX_WideString& wsValue) const { - for (auto iter = m_CustomProperties.rbegin(); - iter != m_CustomProperties.rend(); iter++) { - if (wsName == iter->name()) { - wsValue = iter->value(); - return true; - } - } - return false; -} - -int32_t CFDE_CSSComputedStyle::CountFontFamilies() const { - return m_InheritedData.m_pFontFamily - ? m_InheritedData.m_pFontFamily->CountValues() - : 0; -} - -const CFX_WideString CFDE_CSSComputedStyle::GetFontFamily(int32_t index) const { - return m_InheritedData.m_pFontFamily->GetValue(index) - .As<CFDE_CSSStringValue>() - ->Value(); -} - -uint16_t CFDE_CSSComputedStyle::GetFontWeight() const { - return m_InheritedData.m_wFontWeight; -} - -FDE_CSSFontVariant CFDE_CSSComputedStyle::GetFontVariant() const { - return m_InheritedData.m_eFontVariant; -} - -FDE_CSSFontStyle CFDE_CSSComputedStyle::GetFontStyle() const { - return m_InheritedData.m_eFontStyle; -} - -FX_FLOAT CFDE_CSSComputedStyle::GetFontSize() const { - return m_InheritedData.m_fFontSize; -} - -FX_ARGB CFDE_CSSComputedStyle::GetColor() const { - return m_InheritedData.m_dwFontColor; -} - -void CFDE_CSSComputedStyle::SetFontWeight(uint16_t wFontWeight) { - m_InheritedData.m_wFontWeight = wFontWeight; -} - -void CFDE_CSSComputedStyle::SetFontVariant(FDE_CSSFontVariant eFontVariant) { - m_InheritedData.m_eFontVariant = eFontVariant; -} - -void CFDE_CSSComputedStyle::SetFontStyle(FDE_CSSFontStyle eFontStyle) { - m_InheritedData.m_eFontStyle = eFontStyle; -} - -void CFDE_CSSComputedStyle::SetFontSize(FX_FLOAT fFontSize) { - m_InheritedData.m_fFontSize = fFontSize; -} - -void CFDE_CSSComputedStyle::SetColor(FX_ARGB dwFontColor) { - m_InheritedData.m_dwFontColor = dwFontColor; -} - -const FDE_CSSRect* CFDE_CSSComputedStyle::GetBorderWidth() const { - return m_NonInheritedData.m_bHasBorder ? &(m_NonInheritedData.m_BorderWidth) - : nullptr; -} - -const FDE_CSSRect* CFDE_CSSComputedStyle::GetMarginWidth() const { - return m_NonInheritedData.m_bHasMargin ? &(m_NonInheritedData.m_MarginWidth) - : nullptr; -} - -const FDE_CSSRect* CFDE_CSSComputedStyle::GetPaddingWidth() const { - return m_NonInheritedData.m_bHasPadding ? &(m_NonInheritedData.m_PaddingWidth) - : nullptr; -} - -void CFDE_CSSComputedStyle::SetMarginWidth(const FDE_CSSRect& rect) { - m_NonInheritedData.m_MarginWidth = rect; - m_NonInheritedData.m_bHasMargin = true; -} - -void CFDE_CSSComputedStyle::SetPaddingWidth(const FDE_CSSRect& rect) { - m_NonInheritedData.m_PaddingWidth = rect; - m_NonInheritedData.m_bHasPadding = true; -} - -FDE_CSSDisplay CFDE_CSSComputedStyle::GetDisplay() const { - return m_NonInheritedData.m_eDisplay; -} - -FX_FLOAT CFDE_CSSComputedStyle::GetLineHeight() const { - return m_InheritedData.m_fLineHeight; -} - -const FDE_CSSLength& CFDE_CSSComputedStyle::GetTextIndent() const { - return m_InheritedData.m_TextIndent; -} - -FDE_CSSTextAlign CFDE_CSSComputedStyle::GetTextAlign() const { - return m_InheritedData.m_eTextAlign; -} - -FDE_CSSVerticalAlign CFDE_CSSComputedStyle::GetVerticalAlign() const { - return m_NonInheritedData.m_eVerticalAlign; -} - -FX_FLOAT CFDE_CSSComputedStyle::GetNumberVerticalAlign() const { - return m_NonInheritedData.m_fVerticalAlign; -} - -uint32_t CFDE_CSSComputedStyle::GetTextDecoration() const { - return m_NonInheritedData.m_dwTextDecoration; -} - -const FDE_CSSLength& CFDE_CSSComputedStyle::GetLetterSpacing() const { - return m_InheritedData.m_LetterSpacing; -} - -void CFDE_CSSComputedStyle::SetLineHeight(FX_FLOAT fLineHeight) { - m_InheritedData.m_fLineHeight = fLineHeight; -} - -void CFDE_CSSComputedStyle::SetTextIndent(const FDE_CSSLength& textIndent) { - m_InheritedData.m_TextIndent = textIndent; -} - -void CFDE_CSSComputedStyle::SetTextAlign(FDE_CSSTextAlign eTextAlign) { - m_InheritedData.m_eTextAlign = eTextAlign; -} - -void CFDE_CSSComputedStyle::SetNumberVerticalAlign(FX_FLOAT fAlign) { - m_NonInheritedData.m_eVerticalAlign = FDE_CSSVerticalAlign::Number, - m_NonInheritedData.m_fVerticalAlign = fAlign; -} - -void CFDE_CSSComputedStyle::SetTextDecoration(uint32_t dwTextDecoration) { - m_NonInheritedData.m_dwTextDecoration = dwTextDecoration; -} - -void CFDE_CSSComputedStyle::SetLetterSpacing( - const FDE_CSSLength& letterSpacing) { - m_InheritedData.m_LetterSpacing = letterSpacing; -} - -void CFDE_CSSComputedStyle::AddCustomStyle(const CFDE_CSSCustomProperty& prop) { - // Force the property to be copied so we aren't dependent on the lifetime - // of whatever currently owns it. - m_CustomProperties.push_back(prop); -} - -CFDE_CSSComputedStyle::InheritedData::InheritedData() - : m_LetterSpacing(FDE_CSSLengthUnit::Normal), - m_WordSpacing(FDE_CSSLengthUnit::Normal), - m_TextIndent(FDE_CSSLengthUnit::Point, 0), - m_pFontFamily(nullptr), - m_fFontSize(12.0f), - m_fLineHeight(14.0f), - m_dwFontColor(0xFF000000), - m_wFontWeight(400), - m_eFontVariant(FDE_CSSFontVariant::Normal), - m_eFontStyle(FDE_CSSFontStyle::Normal), - m_eTextAlign(FDE_CSSTextAlign::Left) {} - -CFDE_CSSComputedStyle::InheritedData::~InheritedData() {} - -CFDE_CSSComputedStyle::NonInheritedData::NonInheritedData() - : m_MarginWidth(FDE_CSSLengthUnit::Point, 0), - m_BorderWidth(FDE_CSSLengthUnit::Point, 0), - m_PaddingWidth(FDE_CSSLengthUnit::Point, 0), - m_fVerticalAlign(0.0f), - m_eDisplay(FDE_CSSDisplay::Inline), - m_eVerticalAlign(FDE_CSSVerticalAlign::Baseline), - m_dwTextDecoration(0), - m_bHasMargin(false), - m_bHasBorder(false), - m_bHasPadding(false) {} diff --git a/xfa/fde/css/cfde_csscomputedstyle.h b/xfa/fde/css/cfde_csscomputedstyle.h deleted file mode 100644 index bba4ccbcd447e5dc63caf71132f5c192cb350e0e..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csscomputedstyle.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSCOMPUTEDSTYLE_H_ -#define XFA_FDE_CSS_CFDE_CSSCOMPUTEDSTYLE_H_ - -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_string.h" -#include "xfa/fde/css/cfde_csscustomproperty.h" -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSValueList; - -class CFDE_CSSComputedStyle : public CFX_Retainable { - public: - class InheritedData { - public: - InheritedData(); - ~InheritedData(); - - FDE_CSSLength m_LetterSpacing; - FDE_CSSLength m_WordSpacing; - FDE_CSSLength m_TextIndent; - CFX_RetainPtr<CFDE_CSSValueList> m_pFontFamily; - FX_FLOAT m_fFontSize; - FX_FLOAT m_fLineHeight; - FX_ARGB m_dwFontColor; - uint16_t m_wFontWeight; - FDE_CSSFontVariant m_eFontVariant; - FDE_CSSFontStyle m_eFontStyle; - FDE_CSSTextAlign m_eTextAlign; - }; - - class NonInheritedData { - public: - NonInheritedData(); - - FDE_CSSRect m_MarginWidth; - FDE_CSSRect m_BorderWidth; - FDE_CSSRect m_PaddingWidth; - FDE_CSSLength m_Top; - FDE_CSSLength m_Bottom; - FDE_CSSLength m_Left; - FDE_CSSLength m_Right; - FX_FLOAT m_fVerticalAlign; - FDE_CSSDisplay m_eDisplay; - FDE_CSSVerticalAlign m_eVerticalAlign; - uint8_t m_dwTextDecoration; - bool m_bHasMargin; - bool m_bHasBorder; - bool m_bHasPadding; - }; - - int32_t CountFontFamilies() const; - const CFX_WideString GetFontFamily(int32_t index) const; - uint16_t GetFontWeight() const; - FDE_CSSFontVariant GetFontVariant() const; - FDE_CSSFontStyle GetFontStyle() const; - FX_FLOAT GetFontSize() const; - FX_ARGB GetColor() const; - void SetFontWeight(uint16_t wFontWeight); - void SetFontVariant(FDE_CSSFontVariant eFontVariant); - void SetFontStyle(FDE_CSSFontStyle eFontStyle); - void SetFontSize(FX_FLOAT fFontSize); - void SetColor(FX_ARGB dwFontColor); - - const FDE_CSSRect* GetBorderWidth() const; - const FDE_CSSRect* GetMarginWidth() const; - const FDE_CSSRect* GetPaddingWidth() const; - void SetMarginWidth(const FDE_CSSRect& rect); - void SetPaddingWidth(const FDE_CSSRect& rect); - - FDE_CSSDisplay GetDisplay() const; - - FX_FLOAT GetLineHeight() const; - const FDE_CSSLength& GetTextIndent() const; - FDE_CSSTextAlign GetTextAlign() const; - FDE_CSSVerticalAlign GetVerticalAlign() const; - FX_FLOAT GetNumberVerticalAlign() const; - uint32_t GetTextDecoration() const; - const FDE_CSSLength& GetLetterSpacing() const; - void SetLineHeight(FX_FLOAT fLineHeight); - void SetTextIndent(const FDE_CSSLength& textIndent); - void SetTextAlign(FDE_CSSTextAlign eTextAlign); - void SetNumberVerticalAlign(FX_FLOAT fAlign); - void SetTextDecoration(uint32_t dwTextDecoration); - void SetLetterSpacing(const FDE_CSSLength& letterSpacing); - void AddCustomStyle(const CFDE_CSSCustomProperty& prop); - - bool GetCustomStyle(const CFX_WideString& wsName, - CFX_WideString& wsValue) const; - - InheritedData m_InheritedData; - NonInheritedData m_NonInheritedData; - - private: - template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - CFDE_CSSComputedStyle(); - ~CFDE_CSSComputedStyle() override; - - std::vector<CFDE_CSSCustomProperty> m_CustomProperties; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSCOMPUTEDSTYLE_H_ diff --git a/xfa/fde/css/cfde_csscustomproperty.cpp b/xfa/fde/css/cfde_csscustomproperty.cpp deleted file mode 100644 index 92b288eb4f7bc3e64765fa43b3043b5911ac2fd0..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csscustomproperty.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "xfa/fde/css/cfde_csscustomproperty.h" - -CFDE_CSSCustomProperty::CFDE_CSSCustomProperty(const CFX_WideString& name, - const CFX_WideString& value) - : name_(name), value_(value) {} - -CFDE_CSSCustomProperty::CFDE_CSSCustomProperty( - const CFDE_CSSCustomProperty& prop) - : name_(prop.name_), value_(prop.value_) {} - -CFDE_CSSCustomProperty::~CFDE_CSSCustomProperty() {} diff --git a/xfa/fde/css/cfde_csscustomproperty.h b/xfa/fde/css/cfde_csscustomproperty.h deleted file mode 100644 index 6970d49cbb91591dd2ab4ca8a5a8bc6b9abc8529..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csscustomproperty.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSCUSTOMPROPERTY_H_ -#define XFA_FDE_CSS_CFDE_CSSCUSTOMPROPERTY_H_ - -#include "core/fxcrt/fx_string.h" - -class CFDE_CSSCustomProperty { - public: - CFDE_CSSCustomProperty(const CFX_WideString& name, - const CFX_WideString& value); - CFDE_CSSCustomProperty(const CFDE_CSSCustomProperty& prop); - ~CFDE_CSSCustomProperty(); - - CFX_WideString name() const { return name_; } - CFX_WideString value() const { return value_; } - - private: - CFX_WideString name_; - CFX_WideString value_; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSCUSTOMPROPERTY_H_ diff --git a/xfa/fde/css/cfde_cssdeclaration.cpp b/xfa/fde/css/cfde_cssdeclaration.cpp deleted file mode 100644 index 3c776ca77155a2816f36016f80b091e6b0cd9f12..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssdeclaration.cpp +++ /dev/null @@ -1,639 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssdeclaration.h" - -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fde/css/cfde_csscolorvalue.h" -#include "xfa/fde/css/cfde_csscustomproperty.h" -#include "xfa/fde/css/cfde_cssenumvalue.h" -#include "xfa/fde/css/cfde_cssnumbervalue.h" -#include "xfa/fde/css/cfde_csspropertyholder.h" -#include "xfa/fde/css/cfde_cssstringvalue.h" -#include "xfa/fde/css/cfde_cssvaluelist.h" -#include "xfa/fde/css/cfde_cssvaluelistparser.h" - -namespace { - -uint8_t Hex2Dec(uint8_t hexHigh, uint8_t hexLow) { - return (FXSYS_toHexDigit(hexHigh) << 4) + FXSYS_toHexDigit(hexLow); -} - -bool ParseCSSNumber(const FX_WCHAR* pszValue, - int32_t iValueLen, - FX_FLOAT& fValue, - FDE_CSSNumberType& eUnit) { - ASSERT(pszValue && iValueLen > 0); - int32_t iUsedLen = 0; - fValue = FXSYS_wcstof(pszValue, iValueLen, &iUsedLen); - if (iUsedLen <= 0) - return false; - - iValueLen -= iUsedLen; - pszValue += iUsedLen; - eUnit = FDE_CSSNumberType::Number; - if (iValueLen >= 1 && *pszValue == '%') { - eUnit = FDE_CSSNumberType::Percent; - } else if (iValueLen == 2) { - const FDE_CSSLengthUnitTable* pUnit = - FDE_GetCSSLengthUnitByName(CFX_WideStringC(pszValue, 2)); - if (pUnit) - eUnit = pUnit->wValue; - } - return true; -} - -} // namespace - -// static -bool CFDE_CSSDeclaration::ParseCSSString(const FX_WCHAR* pszValue, - int32_t iValueLen, - int32_t* iOffset, - int32_t* iLength) { - ASSERT(pszValue && iValueLen > 0); - *iOffset = 0; - *iLength = iValueLen; - if (iValueLen >= 2) { - FX_WCHAR first = pszValue[0], last = pszValue[iValueLen - 1]; - if ((first == '\"' && last == '\"') || (first == '\'' && last == '\'')) { - *iOffset = 1; - *iLength -= 2; - } - } - return iValueLen > 0; -} - -// static. -bool CFDE_CSSDeclaration::ParseCSSColor(const FX_WCHAR* pszValue, - int32_t iValueLen, - FX_ARGB* dwColor) { - ASSERT(pszValue && iValueLen > 0); - ASSERT(dwColor); - - if (*pszValue == '#') { - switch (iValueLen) { - case 4: { - uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[1]); - uint8_t green = Hex2Dec((uint8_t)pszValue[2], (uint8_t)pszValue[2]); - uint8_t blue = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[3]); - *dwColor = ArgbEncode(255, red, green, blue); - return true; - } - case 7: { - uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[2]); - uint8_t green = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[4]); - uint8_t blue = Hex2Dec((uint8_t)pszValue[5], (uint8_t)pszValue[6]); - *dwColor = ArgbEncode(255, red, green, blue); - return true; - } - default: - return false; - } - } - - if (iValueLen >= 10) { - if (pszValue[iValueLen - 1] != ')' || FXSYS_wcsnicmp(L"rgb(", pszValue, 4)) - return false; - - uint8_t rgb[3] = {0}; - FX_FLOAT fValue; - FDE_CSSPrimitiveType eType; - CFDE_CSSValueListParser list(pszValue + 4, iValueLen - 5, ','); - for (int32_t i = 0; i < 3; ++i) { - if (!list.NextValue(eType, pszValue, iValueLen)) - return false; - if (eType != FDE_CSSPrimitiveType::Number) - return false; - FDE_CSSNumberType eNumType; - if (!ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) - return false; - - rgb[i] = eNumType == FDE_CSSNumberType::Percent - ? FXSYS_round(fValue * 2.55f) - : FXSYS_round(fValue); - } - *dwColor = ArgbEncode(255, rgb[0], rgb[1], rgb[2]); - return true; - } - - const FDE_CSSCOLORTABLE* pColor = - FDE_GetCSSColorByName(CFX_WideStringC(pszValue, iValueLen)); - if (!pColor) - return false; - - *dwColor = pColor->dwValue; - return true; -} - -CFDE_CSSDeclaration::CFDE_CSSDeclaration() {} - -CFDE_CSSDeclaration::~CFDE_CSSDeclaration() {} - -CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::GetProperty( - FDE_CSSProperty eProperty, - bool* bImportant) const { - for (const auto& p : properties_) { - if (p->eProperty == eProperty) { - *bImportant = p->bImportant; - return p->pValue; - } - } - return nullptr; -} - -void CFDE_CSSDeclaration::AddPropertyHolder(FDE_CSSProperty eProperty, - CFX_RetainPtr<CFDE_CSSValue> pValue, - bool bImportant) { - auto pHolder = pdfium::MakeUnique<CFDE_CSSPropertyHolder>(); - pHolder->bImportant = bImportant; - pHolder->eProperty = eProperty; - pHolder->pValue = pValue; - properties_.push_back(std::move(pHolder)); -} - -void CFDE_CSSDeclaration::AddProperty(const FDE_CSSPropertyTable* pTable, - const CFX_WideStringC& value) { - ASSERT(!value.IsEmpty()); - - const FX_WCHAR* pszValue = value.c_str(); - int32_t iValueLen = value.GetLength(); - - bool bImportant = false; - if (iValueLen >= 10 && pszValue[iValueLen - 10] == '!' && - FXSYS_wcsnicmp(L"important", pszValue + iValueLen - 9, 9) == 0) { - if ((iValueLen -= 10) == 0) - return; - - bImportant = true; - } - const uint32_t dwType = pTable->dwType; - switch (dwType & 0x0F) { - case FDE_CSSVALUETYPE_Primitive: { - static const uint32_t g_ValueGuessOrder[] = { - FDE_CSSVALUETYPE_MaybeNumber, FDE_CSSVALUETYPE_MaybeEnum, - FDE_CSSVALUETYPE_MaybeColor, FDE_CSSVALUETYPE_MaybeString, - }; - static const int32_t g_ValueGuessCount = - sizeof(g_ValueGuessOrder) / sizeof(uint32_t); - for (int32_t i = 0; i < g_ValueGuessCount; ++i) { - const uint32_t dwMatch = dwType & g_ValueGuessOrder[i]; - if (dwMatch == 0) { - continue; - } - CFX_RetainPtr<CFDE_CSSValue> pCSSValue; - switch (dwMatch) { - case FDE_CSSVALUETYPE_MaybeNumber: - pCSSValue = ParseNumber(pszValue, iValueLen); - break; - case FDE_CSSVALUETYPE_MaybeEnum: - pCSSValue = ParseEnum(pszValue, iValueLen); - break; - case FDE_CSSVALUETYPE_MaybeColor: - pCSSValue = ParseColor(pszValue, iValueLen); - break; - case FDE_CSSVALUETYPE_MaybeString: - pCSSValue = ParseString(pszValue, iValueLen); - break; - default: - break; - } - if (pCSSValue) { - AddPropertyHolder(pTable->eName, pCSSValue, bImportant); - return; - } - if (FDE_IsOnlyValue(dwType, g_ValueGuessOrder[i])) - return; - } - break; - } - case FDE_CSSVALUETYPE_Shorthand: { - CFX_RetainPtr<CFDE_CSSValue> pWidth; - switch (pTable->eName) { - case FDE_CSSProperty::Font: - ParseFontProperty(pszValue, iValueLen, bImportant); - return; - case FDE_CSSProperty::Border: - if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { - AddPropertyHolder(FDE_CSSProperty::BorderLeftWidth, pWidth, - bImportant); - AddPropertyHolder(FDE_CSSProperty::BorderTopWidth, pWidth, - bImportant); - AddPropertyHolder(FDE_CSSProperty::BorderRightWidth, pWidth, - bImportant); - AddPropertyHolder(FDE_CSSProperty::BorderBottomWidth, pWidth, - bImportant); - return; - } - break; - case FDE_CSSProperty::BorderLeft: - if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { - AddPropertyHolder(FDE_CSSProperty::BorderLeftWidth, pWidth, - bImportant); - return; - } - break; - case FDE_CSSProperty::BorderTop: - if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { - AddPropertyHolder(FDE_CSSProperty::BorderTopWidth, pWidth, - bImportant); - return; - } - break; - case FDE_CSSProperty::BorderRight: - if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { - AddPropertyHolder(FDE_CSSProperty::BorderRightWidth, pWidth, - bImportant); - return; - } - break; - case FDE_CSSProperty::BorderBottom: - if (ParseBorderProperty(pszValue, iValueLen, pWidth)) { - AddPropertyHolder(FDE_CSSProperty::BorderBottomWidth, pWidth, - bImportant); - return; - } - break; - default: - break; - } - } break; - case FDE_CSSVALUETYPE_List: - ParseValueListProperty(pTable, pszValue, iValueLen, bImportant); - return; - default: - ASSERT(false); - break; - } -} - -void CFDE_CSSDeclaration::AddProperty(const CFX_WideString& prop, - const CFX_WideString& value) { - custom_properties_.push_back( - pdfium::MakeUnique<CFDE_CSSCustomProperty>(prop, value)); -} - -CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseNumber( - const FX_WCHAR* pszValue, - int32_t iValueLen) { - FX_FLOAT fValue; - FDE_CSSNumberType eUnit; - if (!ParseCSSNumber(pszValue, iValueLen, fValue, eUnit)) - return nullptr; - return pdfium::MakeRetain<CFDE_CSSNumberValue>(eUnit, fValue); -} - -CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseEnum( - const FX_WCHAR* pszValue, - int32_t iValueLen) { - const FDE_CSSPropertyValueTable* pValue = - FDE_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); - return pValue ? pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName) - : nullptr; -} - -CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseColor( - const FX_WCHAR* pszValue, - int32_t iValueLen) { - FX_ARGB dwColor; - if (!ParseCSSColor(pszValue, iValueLen, &dwColor)) - return nullptr; - return pdfium::MakeRetain<CFDE_CSSColorValue>(dwColor); -} - -CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSDeclaration::ParseString( - const FX_WCHAR* pszValue, - int32_t iValueLen) { - int32_t iOffset; - if (!ParseCSSString(pszValue, iValueLen, &iOffset, &iValueLen)) - return nullptr; - - if (iValueLen <= 0) - return nullptr; - - return pdfium::MakeRetain<CFDE_CSSStringValue>( - CFX_WideString(pszValue + iOffset, iValueLen)); -} - -void CFDE_CSSDeclaration::ParseValueListProperty( - const FDE_CSSPropertyTable* pTable, - const FX_WCHAR* pszValue, - int32_t iValueLen, - bool bImportant) { - FX_WCHAR separator = - (pTable->eName == FDE_CSSProperty::FontFamily) ? ',' : ' '; - CFDE_CSSValueListParser parser(pszValue, iValueLen, separator); - - const uint32_t dwType = pTable->dwType; - FDE_CSSPrimitiveType eType; - std::vector<CFX_RetainPtr<CFDE_CSSValue>> list; - while (parser.NextValue(eType, pszValue, iValueLen)) { - switch (eType) { - case FDE_CSSPrimitiveType::Number: - if (dwType & FDE_CSSVALUETYPE_MaybeNumber) { - FX_FLOAT fValue; - FDE_CSSNumberType eNumType; - if (ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) - list.push_back( - pdfium::MakeRetain<CFDE_CSSNumberValue>(eNumType, fValue)); - } - break; - case FDE_CSSPrimitiveType::String: - if (dwType & FDE_CSSVALUETYPE_MaybeColor) { - FX_ARGB dwColor; - if (ParseCSSColor(pszValue, iValueLen, &dwColor)) { - list.push_back(pdfium::MakeRetain<CFDE_CSSColorValue>(dwColor)); - continue; - } - } - if (dwType & FDE_CSSVALUETYPE_MaybeEnum) { - const FDE_CSSPropertyValueTable* pValue = - FDE_GetCSSPropertyValueByName( - CFX_WideStringC(pszValue, iValueLen)); - if (pValue) { - list.push_back( - pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName)); - continue; - } - } - if (dwType & FDE_CSSVALUETYPE_MaybeString) { - list.push_back(pdfium::MakeRetain<CFDE_CSSStringValue>( - CFX_WideString(pszValue, iValueLen))); - } - break; - case FDE_CSSPrimitiveType::RGB: - if (dwType & FDE_CSSVALUETYPE_MaybeColor) { - FX_ARGB dwColor; - if (ParseCSSColor(pszValue, iValueLen, &dwColor)) { - list.push_back(pdfium::MakeRetain<CFDE_CSSColorValue>(dwColor)); - } - } - break; - default: - break; - } - } - if (list.empty()) - return; - - switch (pTable->eName) { - case FDE_CSSProperty::BorderWidth: - Add4ValuesProperty(list, bImportant, FDE_CSSProperty::BorderLeftWidth, - FDE_CSSProperty::BorderTopWidth, - FDE_CSSProperty::BorderRightWidth, - FDE_CSSProperty::BorderBottomWidth); - return; - case FDE_CSSProperty::Margin: - Add4ValuesProperty(list, bImportant, FDE_CSSProperty::MarginLeft, - FDE_CSSProperty::MarginTop, - FDE_CSSProperty::MarginRight, - FDE_CSSProperty::MarginBottom); - return; - case FDE_CSSProperty::Padding: - Add4ValuesProperty(list, bImportant, FDE_CSSProperty::PaddingLeft, - FDE_CSSProperty::PaddingTop, - FDE_CSSProperty::PaddingRight, - FDE_CSSProperty::PaddingBottom); - return; - default: { - auto pList = pdfium::MakeRetain<CFDE_CSSValueList>(list); - AddPropertyHolder(pTable->eName, pList, bImportant); - return; - } - } -} - -void CFDE_CSSDeclaration::Add4ValuesProperty( - const std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list, - bool bImportant, - FDE_CSSProperty eLeft, - FDE_CSSProperty eTop, - FDE_CSSProperty eRight, - FDE_CSSProperty eBottom) { - switch (list.size()) { - case 1: - AddPropertyHolder(eLeft, list[0], bImportant); - AddPropertyHolder(eTop, list[0], bImportant); - AddPropertyHolder(eRight, list[0], bImportant); - AddPropertyHolder(eBottom, list[0], bImportant); - return; - case 2: - AddPropertyHolder(eLeft, list[1], bImportant); - AddPropertyHolder(eTop, list[0], bImportant); - AddPropertyHolder(eRight, list[1], bImportant); - AddPropertyHolder(eBottom, list[0], bImportant); - return; - case 3: - AddPropertyHolder(eLeft, list[1], bImportant); - AddPropertyHolder(eTop, list[0], bImportant); - AddPropertyHolder(eRight, list[1], bImportant); - AddPropertyHolder(eBottom, list[2], bImportant); - return; - case 4: - AddPropertyHolder(eLeft, list[3], bImportant); - AddPropertyHolder(eTop, list[0], bImportant); - AddPropertyHolder(eRight, list[1], bImportant); - AddPropertyHolder(eBottom, list[2], bImportant); - return; - default: - break; - } -} - -bool CFDE_CSSDeclaration::ParseBorderProperty( - const FX_WCHAR* pszValue, - int32_t iValueLen, - CFX_RetainPtr<CFDE_CSSValue>& pWidth) const { - pWidth.Reset(nullptr); - - CFDE_CSSValueListParser parser(pszValue, iValueLen, ' '); - FDE_CSSPrimitiveType eType; - while (parser.NextValue(eType, pszValue, iValueLen)) { - switch (eType) { - case FDE_CSSPrimitiveType::Number: { - if (pWidth) - continue; - - FX_FLOAT fValue; - FDE_CSSNumberType eNumType; - if (ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) - pWidth = pdfium::MakeRetain<CFDE_CSSNumberValue>(eNumType, fValue); - break; - } - case FDE_CSSPrimitiveType::String: { - const FDE_CSSCOLORTABLE* pColorItem = - FDE_GetCSSColorByName(CFX_WideStringC(pszValue, iValueLen)); - if (pColorItem) - continue; - - const FDE_CSSPropertyValueTable* pValue = - FDE_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); - if (!pValue) - continue; - - switch (pValue->eName) { - case FDE_CSSPropertyValue::Thin: - case FDE_CSSPropertyValue::Thick: - case FDE_CSSPropertyValue::Medium: - if (!pWidth) - pWidth = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - break; - default: - break; - } - break; - } - default: - break; - } - } - if (!pWidth) - pWidth = pdfium::MakeRetain<CFDE_CSSNumberValue>(FDE_CSSNumberType::Number, - 0.0f); - - return true; -} - -void CFDE_CSSDeclaration::ParseFontProperty(const FX_WCHAR* pszValue, - int32_t iValueLen, - bool bImportant) { - CFDE_CSSValueListParser parser(pszValue, iValueLen, '/'); - CFX_RetainPtr<CFDE_CSSValue> pStyle; - CFX_RetainPtr<CFDE_CSSValue> pVariant; - CFX_RetainPtr<CFDE_CSSValue> pWeight; - CFX_RetainPtr<CFDE_CSSValue> pFontSize; - CFX_RetainPtr<CFDE_CSSValue> pLineHeight; - std::vector<CFX_RetainPtr<CFDE_CSSValue>> familyList; - FDE_CSSPrimitiveType eType; - while (parser.NextValue(eType, pszValue, iValueLen)) { - switch (eType) { - case FDE_CSSPrimitiveType::String: { - const FDE_CSSPropertyValueTable* pValue = - FDE_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); - if (pValue) { - switch (pValue->eName) { - case FDE_CSSPropertyValue::XxSmall: - case FDE_CSSPropertyValue::XSmall: - case FDE_CSSPropertyValue::Small: - case FDE_CSSPropertyValue::Medium: - case FDE_CSSPropertyValue::Large: - case FDE_CSSPropertyValue::XLarge: - case FDE_CSSPropertyValue::XxLarge: - case FDE_CSSPropertyValue::Smaller: - case FDE_CSSPropertyValue::Larger: - if (!pFontSize) - pFontSize = - pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - continue; - case FDE_CSSPropertyValue::Bold: - case FDE_CSSPropertyValue::Bolder: - case FDE_CSSPropertyValue::Lighter: - if (!pWeight) - pWeight = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - continue; - case FDE_CSSPropertyValue::Italic: - case FDE_CSSPropertyValue::Oblique: - if (!pStyle) - pStyle = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - continue; - case FDE_CSSPropertyValue::SmallCaps: - if (!pVariant) - pVariant = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - continue; - case FDE_CSSPropertyValue::Normal: - if (!pStyle) - pStyle = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - else if (!pVariant) - pVariant = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - else if (!pWeight) - pWeight = pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - else if (!pFontSize) - pFontSize = - pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - else if (!pLineHeight) - pLineHeight = - pdfium::MakeRetain<CFDE_CSSEnumValue>(pValue->eName); - continue; - default: - break; - } - } - if (pFontSize) { - familyList.push_back(pdfium::MakeRetain<CFDE_CSSStringValue>( - CFX_WideString(pszValue, iValueLen))); - } - parser.m_Separator = ','; - break; - } - case FDE_CSSPrimitiveType::Number: { - FX_FLOAT fValue; - FDE_CSSNumberType eNumType; - if (!ParseCSSNumber(pszValue, iValueLen, fValue, eNumType)) - break; - if (eType == FDE_CSSPrimitiveType::Number) { - switch ((int32_t)fValue) { - case 100: - case 200: - case 300: - case 400: - case 500: - case 600: - case 700: - case 800: - case 900: - if (!pWeight) - pWeight = pdfium::MakeRetain<CFDE_CSSNumberValue>( - FDE_CSSNumberType::Number, fValue); - continue; - } - } - if (!pFontSize) - pFontSize = pdfium::MakeRetain<CFDE_CSSNumberValue>(eNumType, fValue); - else if (!pLineHeight) - pLineHeight = - pdfium::MakeRetain<CFDE_CSSNumberValue>(eNumType, fValue); - break; - } - default: - break; - } - } - - if (!pStyle) { - pStyle = - pdfium::MakeRetain<CFDE_CSSEnumValue>(FDE_CSSPropertyValue::Normal); - } - if (!pVariant) { - pVariant = - pdfium::MakeRetain<CFDE_CSSEnumValue>(FDE_CSSPropertyValue::Normal); - } - if (!pWeight) { - pWeight = - pdfium::MakeRetain<CFDE_CSSEnumValue>(FDE_CSSPropertyValue::Normal); - } - if (!pFontSize) { - pFontSize = - pdfium::MakeRetain<CFDE_CSSEnumValue>(FDE_CSSPropertyValue::Medium); - } - if (!pLineHeight) { - pLineHeight = - pdfium::MakeRetain<CFDE_CSSEnumValue>(FDE_CSSPropertyValue::Normal); - } - - AddPropertyHolder(FDE_CSSProperty::FontStyle, pStyle, bImportant); - AddPropertyHolder(FDE_CSSProperty::FontVariant, pVariant, bImportant); - AddPropertyHolder(FDE_CSSProperty::FontWeight, pWeight, bImportant); - AddPropertyHolder(FDE_CSSProperty::FontSize, pFontSize, bImportant); - AddPropertyHolder(FDE_CSSProperty::LineHeight, pLineHeight, bImportant); - if (!familyList.empty()) { - auto pList = pdfium::MakeRetain<CFDE_CSSValueList>(familyList); - AddPropertyHolder(FDE_CSSProperty::FontFamily, pList, bImportant); - } -} - -size_t CFDE_CSSDeclaration::PropertyCountForTesting() const { - return properties_.size(); -} diff --git a/xfa/fde/css/cfde_cssdeclaration.h b/xfa/fde/css/cfde_cssdeclaration.h deleted file mode 100644 index eb287308f8bb286be2d59360b7403b936362dcf0..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssdeclaration.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSDECLARATION_H_ -#define XFA_FDE_CSS_CFDE_CSSDECLARATION_H_ - -#include <memory> -#include <utility> -#include <vector> - -#include "xfa/fde/css/fde_cssdatatable.h" - -class CFDE_CSSPropertyHolder; -class CFDE_CSSCustomProperty; - -class CFDE_CSSDeclaration { - public: - using const_prop_iterator = - std::vector<std::unique_ptr<CFDE_CSSPropertyHolder>>::const_iterator; - using const_custom_iterator = - std::vector<std::unique_ptr<CFDE_CSSCustomProperty>>::const_iterator; - - static bool ParseCSSString(const FX_WCHAR* pszValue, - int32_t iValueLen, - int32_t* iOffset, - int32_t* iLength); - static bool ParseCSSColor(const FX_WCHAR* pszValue, - int32_t iValueLen, - FX_ARGB* dwColor); - - CFDE_CSSDeclaration(); - ~CFDE_CSSDeclaration(); - - CFX_RetainPtr<CFDE_CSSValue> GetProperty(FDE_CSSProperty eProperty, - bool* bImportant) const; - - const_prop_iterator begin() const { return properties_.begin(); } - const_prop_iterator end() const { return properties_.end(); } - - const_custom_iterator custom_begin() const { - return custom_properties_.begin(); - } - const_custom_iterator custom_end() const { return custom_properties_.end(); } - - bool empty() const { return properties_.empty(); } - - void AddProperty(const FDE_CSSPropertyTable* pTable, - const CFX_WideStringC& value); - void AddProperty(const CFX_WideString& prop, const CFX_WideString& value); - - size_t PropertyCountForTesting() const; - - FX_ARGB ParseColorForTest(const FX_WCHAR* pszValue, - int32_t iValueLen, - FX_ARGB* dwColor) const; - - private: - void ParseFontProperty(const FX_WCHAR* pszValue, - int32_t iValueLen, - bool bImportant); - bool ParseBorderProperty(const FX_WCHAR* pszValue, - int32_t iValueLen, - CFX_RetainPtr<CFDE_CSSValue>& pWidth) const; - void ParseValueListProperty(const FDE_CSSPropertyTable* pTable, - const FX_WCHAR* pszValue, - int32_t iValueLen, - bool bImportant); - void Add4ValuesProperty(const std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list, - bool bImportant, - FDE_CSSProperty eLeft, - FDE_CSSProperty eTop, - FDE_CSSProperty eRight, - FDE_CSSProperty eBottom); - CFX_RetainPtr<CFDE_CSSValue> ParseNumber(const FX_WCHAR* pszValue, - int32_t iValueLen); - CFX_RetainPtr<CFDE_CSSValue> ParseEnum(const FX_WCHAR* pszValue, - int32_t iValueLen); - CFX_RetainPtr<CFDE_CSSValue> ParseColor(const FX_WCHAR* pszValue, - int32_t iValueLen); - CFX_RetainPtr<CFDE_CSSValue> ParseString(const FX_WCHAR* pszValue, - int32_t iValueLen); - void AddPropertyHolder(FDE_CSSProperty eProperty, - CFX_RetainPtr<CFDE_CSSValue> pValue, - bool bImportant); - - std::vector<std::unique_ptr<CFDE_CSSPropertyHolder>> properties_; - std::vector<std::unique_ptr<CFDE_CSSCustomProperty>> custom_properties_; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSDECLARATION_H_ diff --git a/xfa/fde/css/cfde_cssdeclaration_unittest.cpp b/xfa/fde/css/cfde_cssdeclaration_unittest.cpp deleted file mode 100644 index 48a3c72c39b0da14472e2ceccd2ac9bad416ea89..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssdeclaration_unittest.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "xfa/fde/css/cfde_cssdeclaration.h" - -#include "testing/gtest/include/gtest/gtest.h" - -TEST(CFDE_CSSDecalration, HexEncodingParsing) { - FX_ARGB color; - - // Length value invalid. - EXPECT_FALSE(CFDE_CSSDeclaration::ParseCSSColor(L"#000", 3, &color)); - EXPECT_FALSE(CFDE_CSSDeclaration::ParseCSSColor(L"#000000", 5, &color)); - EXPECT_FALSE(CFDE_CSSDeclaration::ParseCSSColor(L"#000000", 8, &color)); - - // Invalid characters - EXPECT_TRUE(CFDE_CSSDeclaration::ParseCSSColor(L"#zxytlm", 7, &color)); - EXPECT_EQ(0, FXARGB_R(color)); - EXPECT_EQ(0, FXARGB_G(color)); - EXPECT_EQ(0, FXARGB_B(color)); - - EXPECT_TRUE(CFDE_CSSDeclaration::ParseCSSColor(L"#000", 4, &color)); - EXPECT_EQ(0, FXARGB_R(color)); - EXPECT_EQ(0, FXARGB_G(color)); - EXPECT_EQ(0, FXARGB_B(color)); - - EXPECT_TRUE(CFDE_CSSDeclaration::ParseCSSColor(L"#FFF", 4, &color)); - EXPECT_EQ(255, FXARGB_R(color)); - EXPECT_EQ(255, FXARGB_G(color)); - EXPECT_EQ(255, FXARGB_B(color)); - - EXPECT_TRUE(CFDE_CSSDeclaration::ParseCSSColor(L"#F0F0F0", 7, &color)); - EXPECT_EQ(240, FXARGB_R(color)); - EXPECT_EQ(240, FXARGB_G(color)); - EXPECT_EQ(240, FXARGB_B(color)); - - // Upper and lower case characters. - EXPECT_TRUE(CFDE_CSSDeclaration::ParseCSSColor(L"#1b2F3c", 7, &color)); - EXPECT_EQ(27, FXARGB_R(color)); - EXPECT_EQ(47, FXARGB_G(color)); - EXPECT_EQ(60, FXARGB_B(color)); -} - -TEST(CFDE_CSSDecalration, RGBEncodingParsing) { - FX_ARGB color; - - // Invalid input for rgb() syntax. - EXPECT_FALSE(CFDE_CSSDeclaration::ParseCSSColor(L"blahblahblah", 11, &color)); - - EXPECT_TRUE(CFDE_CSSDeclaration::ParseCSSColor(L"rgb(0, 0, 0)", 12, &color)); - EXPECT_EQ(0, FXARGB_R(color)); - EXPECT_EQ(0, FXARGB_G(color)); - EXPECT_EQ(0, FXARGB_B(color)); - - EXPECT_TRUE( - CFDE_CSSDeclaration::ParseCSSColor(L"rgb(128,255,48)", 15, &color)); - EXPECT_EQ(128, FXARGB_R(color)); - EXPECT_EQ(255, FXARGB_G(color)); - EXPECT_EQ(48, FXARGB_B(color)); -} diff --git a/xfa/fde/css/cfde_cssenumvalue.cpp b/xfa/fde/css/cfde_cssenumvalue.cpp deleted file mode 100644 index c6b9d3ff73585a41b589d5953cf6ddebe9e61d75..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssenumvalue.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssenumvalue.h" - -CFDE_CSSEnumValue::CFDE_CSSEnumValue(FDE_CSSPropertyValue value) - : CFDE_CSSValue(FDE_CSSPrimitiveType::Enum), value_(value) {} - -CFDE_CSSEnumValue::~CFDE_CSSEnumValue() {} diff --git a/xfa/fde/css/cfde_cssenumvalue.h b/xfa/fde/css/cfde_cssenumvalue.h deleted file mode 100644 index 9fb1b69ef55de6385bea197e635b6f45ca25313d..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssenumvalue.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSENUMVALUE_H_ -#define XFA_FDE_CSS_CFDE_CSSENUMVALUE_H_ - -#include "xfa/fde/css/cfde_cssvalue.h" - -class CFDE_CSSEnumValue : public CFDE_CSSValue { - public: - explicit CFDE_CSSEnumValue(FDE_CSSPropertyValue value); - ~CFDE_CSSEnumValue() override; - - FDE_CSSPropertyValue Value() const { return value_; } - - private: - FDE_CSSPropertyValue value_; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSENUMVALUE_H_ diff --git a/xfa/fde/css/cfde_cssnumbervalue.cpp b/xfa/fde/css/cfde_cssnumbervalue.cpp deleted file mode 100644 index 71566ca5a3d24c7430a162f6961ef0f4d489a8af..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssnumbervalue.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssnumbervalue.h" - -CFDE_CSSNumberValue::CFDE_CSSNumberValue(FDE_CSSNumberType type, FX_FLOAT value) - : CFDE_CSSValue(FDE_CSSPrimitiveType::Number), type_(type), value_(value) { - if (type_ == FDE_CSSNumberType::Number && FXSYS_fabs(value_) < 0.001f) - value_ = 0.0f; -} - -CFDE_CSSNumberValue::~CFDE_CSSNumberValue() {} - -FX_FLOAT CFDE_CSSNumberValue::Apply(FX_FLOAT percentBase) const { - switch (type_) { - case FDE_CSSNumberType::Pixels: - case FDE_CSSNumberType::Number: - return value_ * 72 / 96; - case FDE_CSSNumberType::EMS: - case FDE_CSSNumberType::EXS: - return value_ * percentBase; - case FDE_CSSNumberType::Percent: - return value_ * percentBase / 100.0f; - case FDE_CSSNumberType::CentiMeters: - return value_ * 28.3464f; - case FDE_CSSNumberType::MilliMeters: - return value_ * 2.8346f; - case FDE_CSSNumberType::Inches: - return value_ * 72.0f; - case FDE_CSSNumberType::Picas: - return value_ / 12.0f; - case FDE_CSSNumberType::Points: - return value_; - } - return value_; -} diff --git a/xfa/fde/css/cfde_cssnumbervalue.h b/xfa/fde/css/cfde_cssnumbervalue.h deleted file mode 100644 index 29e562e1e3588142418938135c2f2d56e9a98404..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssnumbervalue.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSNUMBERVALUE_H_ -#define XFA_FDE_CSS_CFDE_CSSNUMBERVALUE_H_ - -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/css/cfde_cssvalue.h" - -enum class FDE_CSSNumberType { - Number, - Percent, - EMS, - EXS, - Pixels, - CentiMeters, - MilliMeters, - Inches, - Points, - Picas, -}; - -class CFDE_CSSNumberValue : public CFDE_CSSValue { - public: - CFDE_CSSNumberValue(FDE_CSSNumberType type, FX_FLOAT value); - ~CFDE_CSSNumberValue() override; - - FX_FLOAT Value() const { return value_; } - FDE_CSSNumberType Kind() const { return type_; } - - FX_FLOAT Apply(FX_FLOAT percentBase) const; - - private: - FDE_CSSNumberType type_; - FX_FLOAT value_; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSNUMBERVALUE_H_ diff --git a/xfa/fde/css/cfde_csspropertyholder.cpp b/xfa/fde/css/cfde_csspropertyholder.cpp deleted file mode 100644 index 9f47c8f08b724c3afb5945b9131b86e0efb487d7..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csspropertyholder.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_csspropertyholder.h" - -CFDE_CSSPropertyHolder::CFDE_CSSPropertyHolder() {} - -CFDE_CSSPropertyHolder::~CFDE_CSSPropertyHolder() {} diff --git a/xfa/fde/css/cfde_csspropertyholder.h b/xfa/fde/css/cfde_csspropertyholder.h deleted file mode 100644 index 7f8526d92e645beab8f47d3887d5597ebeb39f8d..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csspropertyholder.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSPROPERTYHOLDER_H_ -#define XFA_FDE_CSS_CFDE_CSSPROPERTYHOLDER_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "xfa/fde/css/cfde_cssvalue.h" -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSPropertyHolder { - public: - CFDE_CSSPropertyHolder(); - ~CFDE_CSSPropertyHolder(); - - FDE_CSSProperty eProperty; - bool bImportant; - CFX_RetainPtr<CFDE_CSSValue> pValue; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSPROPERTYHOLDER_H_ diff --git a/xfa/fde/css/cfde_cssrulecollection.cpp b/xfa/fde/css/cfde_cssrulecollection.cpp deleted file mode 100644 index e31865113788602c7c6dfa4d9b56cf9995cc5016..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssrulecollection.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssrulecollection.h" - -#include <algorithm> -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/cfde_cssselector.h" -#include "xfa/fde/css/cfde_cssstylerule.h" -#include "xfa/fde/css/cfde_cssstylesheet.h" -#include "xfa/fde/css/cfde_csssyntaxparser.h" - -CFDE_CSSRuleCollection::CFDE_CSSRuleCollection() : m_iSelectors(0) {} - -CFDE_CSSRuleCollection::~CFDE_CSSRuleCollection() { - Clear(); -} - -void CFDE_CSSRuleCollection::Clear() { - m_TagRules.clear(); - m_iSelectors = 0; -} - -const std::vector<std::unique_ptr<CFDE_CSSRuleCollection::Data>>* -CFDE_CSSRuleCollection::GetTagRuleData(const CFX_WideString& tagname) const { - auto it = m_TagRules.find(FX_HashCode_GetW(tagname.c_str(), true)); - return it != m_TagRules.end() ? &it->second : nullptr; -} - -void CFDE_CSSRuleCollection::AddRulesFrom(const CFDE_CSSStyleSheet* sheet, - CFGAS_FontMgr* pFontMgr) { - int32_t iRules = sheet->CountRules(); - for (int32_t j = 0; j < iRules; j++) - AddRulesFrom(sheet, sheet->GetRule(j), pFontMgr); -} - -void CFDE_CSSRuleCollection::AddRulesFrom(const CFDE_CSSStyleSheet* pStyleSheet, - CFDE_CSSStyleRule* pStyleRule, - CFGAS_FontMgr* pFontMgr) { - CFDE_CSSDeclaration* pDeclaration = pStyleRule->GetDeclaration(); - int32_t iSelectors = pStyleRule->CountSelectorLists(); - for (int32_t i = 0; i < iSelectors; ++i) { - CFDE_CSSSelector* pSelector = pStyleRule->GetSelectorList(i); - m_TagRules[pSelector->GetNameHash()].push_back( - pdfium::MakeUnique<Data>(pSelector, pDeclaration)); - m_iSelectors++; - } -} - -CFDE_CSSRuleCollection::Data::Data(CFDE_CSSSelector* pSel, - CFDE_CSSDeclaration* pDecl) - : pSelector(pSel), pDeclaration(pDecl) {} diff --git a/xfa/fde/css/cfde_cssrulecollection.h b/xfa/fde/css/cfde_cssrulecollection.h deleted file mode 100644 index 5d49922fcda3acb71e3d0c323616295714ae0fb4..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssrulecollection.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSRULECOLLECTION_H_ -#define XFA_FDE_CSS_CFDE_CSSRULECOLLECTION_H_ - -#include <map> -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_basic.h" - -class CFDE_CSSDeclaration; -class CFDE_CSSSelector; -class CFDE_CSSStyleRule; -class CFDE_CSSStyleSheet; -class CFGAS_FontMgr; - -class CFDE_CSSRuleCollection { - public: - class Data { - public: - Data(CFDE_CSSSelector* pSel, CFDE_CSSDeclaration* pDecl); - - CFDE_CSSSelector* const pSelector; - CFDE_CSSDeclaration* const pDeclaration; - }; - - CFDE_CSSRuleCollection(); - ~CFDE_CSSRuleCollection(); - - void AddRulesFrom(const CFDE_CSSStyleSheet* sheet, CFGAS_FontMgr* pFontMgr); - void Clear(); - int32_t CountSelectors() const { return m_iSelectors; } - - const std::vector<std::unique_ptr<Data>>* GetTagRuleData( - const CFX_WideString& tagname) const; - - private: - void AddRulesFrom(const CFDE_CSSStyleSheet* pStyleSheet, - CFDE_CSSStyleRule* pRule, - CFGAS_FontMgr* pFontMgr); - - std::map<uint32_t, std::vector<std::unique_ptr<Data>>> m_TagRules; - int32_t m_iSelectors; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSRULECOLLECTION_H_ diff --git a/xfa/fde/css/cfde_cssselector.cpp b/xfa/fde/css/cfde_cssselector.cpp deleted file mode 100644 index 03580236f525252cbda3da2869990fe5d8a7f009..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssselector.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssselector.h" - -#include <utility> - -#include "third_party/base/ptr_util.h" - -namespace { - -bool IsCSSChar(FX_WCHAR wch) { - return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z'); -} - -int32_t GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { - const FX_WCHAR* pStart = psz; - while (psz < pEnd) { - FX_WCHAR wch = *psz; - if (IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' || - wch == '-') { - ++psz; - } else { - break; - } - } - return psz - pStart; -} - -} // namespace - -CFDE_CSSSelector::CFDE_CSSSelector(FDE_CSSSelectorType eType, - const FX_WCHAR* psz, - int32_t iLen, - bool bIgnoreCase) - : m_eType(eType), - m_dwHash(FX_HashCode_GetW(CFX_WideStringC(psz, iLen), bIgnoreCase)) {} - -CFDE_CSSSelector::~CFDE_CSSSelector() {} - -FDE_CSSSelectorType CFDE_CSSSelector::GetType() const { - return m_eType; -} - -uint32_t CFDE_CSSSelector::GetNameHash() const { - return m_dwHash; -} - -CFDE_CSSSelector* CFDE_CSSSelector::GetNextSelector() const { - return m_pNext.get(); -} - -// static. -std::unique_ptr<CFDE_CSSSelector> CFDE_CSSSelector::FromString( - const CFX_WideStringC& str) { - ASSERT(!str.IsEmpty()); - - const FX_WCHAR* psz = str.c_str(); - const FX_WCHAR* pStart = psz; - const FX_WCHAR* pEnd = psz + str.GetLength(); - for (; psz < pEnd; ++psz) { - switch (*psz) { - case '>': - case '[': - case '+': - return nullptr; - } - } - - std::unique_ptr<CFDE_CSSSelector> pFirst = nullptr; - for (psz = pStart; psz < pEnd;) { - FX_WCHAR wch = *psz; - if (IsCSSChar(wch) || wch == '*') { - int32_t iNameLen = wch == '*' ? 1 : GetCSSNameLen(psz, pEnd); - auto p = pdfium::MakeUnique<CFDE_CSSSelector>( - FDE_CSSSelectorType::Element, psz, iNameLen, true); - if (pFirst) { - pFirst->SetType(FDE_CSSSelectorType::Descendant); - p->SetNext(std::move(pFirst)); - } - pFirst = std::move(p); - psz += iNameLen; - } else if (wch == ' ') { - psz++; - } else { - return nullptr; - } - } - return pFirst; -} diff --git a/xfa/fde/css/cfde_cssselector.h b/xfa/fde/css/cfde_cssselector.h deleted file mode 100644 index d585b3f368e723dc3bf4c1aabb7bca39c0782699..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssselector.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSSELECTOR_H_ -#define XFA_FDE_CSS_CFDE_CSSSELECTOR_H_ - -#include <memory> -#include <utility> - -#include "core/fxcrt/fx_string.h" -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSSelector { - public: - static std::unique_ptr<CFDE_CSSSelector> FromString( - const CFX_WideStringC& str); - - CFDE_CSSSelector(FDE_CSSSelectorType eType, - const FX_WCHAR* psz, - int32_t iLen, - bool bIgnoreCase); - ~CFDE_CSSSelector(); - - FDE_CSSSelectorType GetType() const; - uint32_t GetNameHash() const; - CFDE_CSSSelector* GetNextSelector() const; - - void SetNext(std::unique_ptr<CFDE_CSSSelector> pNext) { - m_pNext = std::move(pNext); - } - - private: - void SetType(FDE_CSSSelectorType eType) { m_eType = eType; } - - FDE_CSSSelectorType m_eType; - uint32_t m_dwHash; - std::unique_ptr<CFDE_CSSSelector> m_pNext; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSSELECTOR_H_ diff --git a/xfa/fde/css/cfde_cssstringvalue.cpp b/xfa/fde/css/cfde_cssstringvalue.cpp deleted file mode 100644 index deb9be3dc0af85c593a0097b1371d458d6b3f00c..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstringvalue.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssstringvalue.h" - -CFDE_CSSStringValue::CFDE_CSSStringValue(const CFX_WideString& value) - : CFDE_CSSValue(FDE_CSSPrimitiveType::String), value_(value) {} - -CFDE_CSSStringValue::~CFDE_CSSStringValue() {} diff --git a/xfa/fde/css/cfde_cssstringvalue.h b/xfa/fde/css/cfde_cssstringvalue.h deleted file mode 100644 index 33328cf52bd2a57a204b3ad37ac702e1bbccea03..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstringvalue.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSSTRINGVALUE_H_ -#define XFA_FDE_CSS_CFDE_CSSSTRINGVALUE_H_ - -#include "xfa/fde/css/cfde_cssvalue.h" - -class CFDE_CSSStringValue : public CFDE_CSSValue { - public: - explicit CFDE_CSSStringValue(const CFX_WideString& value); - ~CFDE_CSSStringValue() override; - - const CFX_WideString Value() const { return value_; } - - private: - const CFX_WideString value_; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSSTRINGVALUE_H_ diff --git a/xfa/fde/css/cfde_cssstylerule.cpp b/xfa/fde/css/cfde_cssstylerule.cpp deleted file mode 100644 index 04f6cfff089473cc537fbfe5752608a9d466afbd..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstylerule.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssstylerule.h" - -CFDE_CSSStyleRule::CFDE_CSSStyleRule() {} - -CFDE_CSSStyleRule::~CFDE_CSSStyleRule() {} - -size_t CFDE_CSSStyleRule::CountSelectorLists() const { - return m_ppSelector.size(); -} - -CFDE_CSSSelector* CFDE_CSSStyleRule::GetSelectorList(int32_t index) const { - return m_ppSelector[index].get(); -} - -CFDE_CSSDeclaration* CFDE_CSSStyleRule::GetDeclaration() { - return &m_Declaration; -} - -void CFDE_CSSStyleRule::SetSelector( - std::vector<std::unique_ptr<CFDE_CSSSelector>>* list) { - ASSERT(m_ppSelector.empty()); - - m_ppSelector.swap(*list); -} diff --git a/xfa/fde/css/cfde_cssstylerule.h b/xfa/fde/css/cfde_cssstylerule.h deleted file mode 100644 index 075ab8d4781550e8fd47eea86e586be2684045aa..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstylerule.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSSTYLERULE_H_ -#define XFA_FDE_CSS_CFDE_CSSSTYLERULE_H_ - -#include <memory> -#include <vector> - -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/cfde_cssselector.h" - -class CFDE_CSSStyleRule { - public: - CFDE_CSSStyleRule(); - ~CFDE_CSSStyleRule(); - - size_t CountSelectorLists() const; - CFDE_CSSSelector* GetSelectorList(int32_t index) const; - CFDE_CSSDeclaration* GetDeclaration(); - - void SetSelector(std::vector<std::unique_ptr<CFDE_CSSSelector>>* list); - - private: - CFDE_CSSDeclaration m_Declaration; - std::vector<std::unique_ptr<CFDE_CSSSelector>> m_ppSelector; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSSTYLERULE_H_ diff --git a/xfa/fde/css/cfde_cssstyleselector.cpp b/xfa/fde/css/cfde_cssstyleselector.cpp deleted file mode 100644 index 5a7aa1b7ff0196f82bb0058cbec33d7711f84394..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstyleselector.cpp +++ /dev/null @@ -1,602 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssstyleselector.h" - -#include <algorithm> -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "xfa/fde/css/cfde_csscolorvalue.h" -#include "xfa/fde/css/cfde_csscomputedstyle.h" -#include "xfa/fde/css/cfde_csscustomproperty.h" -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/cfde_cssenumvalue.h" -#include "xfa/fde/css/cfde_csspropertyholder.h" -#include "xfa/fde/css/cfde_cssselector.h" -#include "xfa/fde/css/cfde_cssstylesheet.h" -#include "xfa/fde/css/cfde_csssyntaxparser.h" -#include "xfa/fde/css/cfde_cssvaluelist.h" -#include "xfa/fxfa/app/cxfa_csstagprovider.h" - -CFDE_CSSStyleSelector::CFDE_CSSStyleSelector(CFGAS_FontMgr* pFontMgr) - : m_pFontMgr(pFontMgr), m_fDefFontSize(12.0f) {} - -CFDE_CSSStyleSelector::~CFDE_CSSStyleSelector() {} - -void CFDE_CSSStyleSelector::SetDefFontSize(FX_FLOAT fFontSize) { - ASSERT(fFontSize > 0); - m_fDefFontSize = fFontSize; -} - -CFX_RetainPtr<CFDE_CSSComputedStyle> CFDE_CSSStyleSelector::CreateComputedStyle( - CFDE_CSSComputedStyle* pParentStyle) { - auto pStyle = pdfium::MakeRetain<CFDE_CSSComputedStyle>(); - if (pParentStyle) - pStyle->m_InheritedData = pParentStyle->m_InheritedData; - return pStyle; -} - -void CFDE_CSSStyleSelector::SetUAStyleSheet( - std::unique_ptr<CFDE_CSSStyleSheet> pSheet) { - m_UAStyles = std::move(pSheet); -} - -void CFDE_CSSStyleSelector::UpdateStyleIndex() { - m_UARules.Clear(); - m_UARules.AddRulesFrom(m_UAStyles.get(), m_pFontMgr); -} - -std::vector<const CFDE_CSSDeclaration*> -CFDE_CSSStyleSelector::MatchDeclarations(const CFX_WideString& tagname) { - std::vector<const CFDE_CSSDeclaration*> matchedDecls; - if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty()) - return matchedDecls; - - auto rules = m_UARules.GetTagRuleData(tagname); - if (!rules) - return matchedDecls; - - for (const auto& d : *rules) { - if (MatchSelector(tagname, d->pSelector)) - matchedDecls.push_back(d->pDeclaration); - } - return matchedDecls; -} - -bool CFDE_CSSStyleSelector::MatchSelector(const CFX_WideString& tagname, - CFDE_CSSSelector* pSel) { - // TODO(dsinclair): The code only supports a single level of selector at this - // point. None of the code using selectors required the complexity so lets - // just say we don't support them to simplify the code for now. - if (!pSel || pSel->GetNextSelector() || - pSel->GetType() == FDE_CSSSelectorType::Descendant) { - return false; - } - return pSel->GetNameHash() == FX_HashCode_GetW(tagname.c_str(), true); -} - -void CFDE_CSSStyleSelector::ComputeStyle( - const std::vector<const CFDE_CSSDeclaration*>& declArray, - const CFX_WideString& styleString, - const CFX_WideString& alignString, - CFDE_CSSComputedStyle* pDest) { - std::unique_ptr<CFDE_CSSDeclaration> pDecl; - if (!styleString.IsEmpty() || !alignString.IsEmpty()) { - pDecl = pdfium::MakeUnique<CFDE_CSSDeclaration>(); - - if (!styleString.IsEmpty()) - AppendInlineStyle(pDecl.get(), styleString); - if (!alignString.IsEmpty()) { - pDecl->AddProperty(FDE_GetCSSPropertyByEnum(FDE_CSSProperty::TextAlign), - alignString.AsStringC()); - } - } - ApplyDeclarations(declArray, pDecl.get(), pDest); -} - -void CFDE_CSSStyleSelector::ApplyDeclarations( - const std::vector<const CFDE_CSSDeclaration*>& declArray, - const CFDE_CSSDeclaration* extraDecl, - CFDE_CSSComputedStyle* pComputedStyle) { - std::vector<const CFDE_CSSPropertyHolder*> importants; - std::vector<const CFDE_CSSPropertyHolder*> normals; - std::vector<const CFDE_CSSCustomProperty*> customs; - - for (auto& decl : declArray) - ExtractValues(decl, &importants, &normals, &customs); - - if (extraDecl) - ExtractValues(extraDecl, &importants, &normals, &customs); - - for (auto& prop : normals) - ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle); - - for (auto& prop : customs) - pComputedStyle->AddCustomStyle(*prop); - - for (auto& prop : importants) - ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle); -} - -void CFDE_CSSStyleSelector::ExtractValues( - const CFDE_CSSDeclaration* decl, - std::vector<const CFDE_CSSPropertyHolder*>* importants, - std::vector<const CFDE_CSSPropertyHolder*>* normals, - std::vector<const CFDE_CSSCustomProperty*>* custom) { - for (const auto& holder : *decl) { - if (holder->bImportant) - importants->push_back(holder.get()); - else - normals->push_back(holder.get()); - } - for (auto it = decl->custom_begin(); it != decl->custom_end(); it++) - custom->push_back(it->get()); -} - -void CFDE_CSSStyleSelector::AppendInlineStyle(CFDE_CSSDeclaration* pDecl, - const CFX_WideString& style) { - ASSERT(pDecl && !style.IsEmpty()); - - auto pSyntax = pdfium::MakeUnique<CFDE_CSSSyntaxParser>(); - if (!pSyntax->Init(style.c_str(), style.GetLength(), 32, true)) - return; - - int32_t iLen2 = 0; - const FDE_CSSPropertyTable* table = nullptr; - CFX_WideString wsName; - while (1) { - FDE_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse(); - if (eStatus == FDE_CSSSyntaxStatus::PropertyName) { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); - table = FDE_GetCSSPropertyByName(strValue); - if (!table) - wsName = CFX_WideString(strValue); - } else if (eStatus == FDE_CSSSyntaxStatus::PropertyValue) { - if (table || iLen2 > 0) { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); - if (!strValue.IsEmpty()) { - if (table) - pDecl->AddProperty(table, strValue); - else if (iLen2 > 0) - pDecl->AddProperty(wsName, CFX_WideString(strValue)); - } - } - } else { - break; - } - } -} - -void CFDE_CSSStyleSelector::ApplyProperty( - FDE_CSSProperty eProperty, - const CFX_RetainPtr<CFDE_CSSValue>& pValue, - CFDE_CSSComputedStyle* pComputedStyle) { - if (pValue->GetType() != FDE_CSSPrimitiveType::List) { - FDE_CSSPrimitiveType eType = pValue->GetType(); - switch (eProperty) { - case FDE_CSSProperty::Display: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_NonInheritedData.m_eDisplay = - ToDisplay(pValue.As<CFDE_CSSEnumValue>()->Value()); - } - break; - case FDE_CSSProperty::FontSize: { - FX_FLOAT& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize; - if (eType == FDE_CSSPrimitiveType::Number) { - fFontSize = pValue.As<CFDE_CSSNumberValue>()->Apply(fFontSize); - } else if (eType == FDE_CSSPrimitiveType::Enum) { - fFontSize = - ToFontSize(pValue.As<CFDE_CSSEnumValue>()->Value(), fFontSize); - } - } break; - case FDE_CSSProperty::LineHeight: - if (eType == FDE_CSSPrimitiveType::Number) { - CFX_RetainPtr<CFDE_CSSNumberValue> v = - pValue.As<CFDE_CSSNumberValue>(); - if (v->Kind() == FDE_CSSNumberType::Number) { - pComputedStyle->m_InheritedData.m_fLineHeight = - v->Value() * pComputedStyle->m_InheritedData.m_fFontSize; - } else { - pComputedStyle->m_InheritedData.m_fLineHeight = - v->Apply(pComputedStyle->m_InheritedData.m_fFontSize); - } - } - break; - case FDE_CSSProperty::TextAlign: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_InheritedData.m_eTextAlign = - ToTextAlign(pValue.As<CFDE_CSSEnumValue>()->Value()); - } - break; - case FDE_CSSProperty::TextIndent: - SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent, - eType, pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - break; - case FDE_CSSProperty::FontWeight: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_InheritedData.m_wFontWeight = - ToFontWeight(pValue.As<CFDE_CSSEnumValue>()->Value()); - } else if (eType == FDE_CSSPrimitiveType::Number) { - int32_t iValue = - (int32_t)pValue.As<CFDE_CSSNumberValue>()->Value() / 100; - if (iValue >= 1 && iValue <= 9) { - pComputedStyle->m_InheritedData.m_wFontWeight = iValue * 100; - } - } - break; - case FDE_CSSProperty::FontStyle: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_InheritedData.m_eFontStyle = - ToFontStyle(pValue.As<CFDE_CSSEnumValue>()->Value()); - } - break; - case FDE_CSSProperty::Color: - if (eType == FDE_CSSPrimitiveType::RGB) { - pComputedStyle->m_InheritedData.m_dwFontColor = - pValue.As<CFDE_CSSColorValue>()->Value(); - } - break; - case FDE_CSSProperty::MarginLeft: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_MarginWidth.left, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasMargin = true; - } - break; - case FDE_CSSProperty::MarginTop: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_MarginWidth.top, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasMargin = true; - } - break; - case FDE_CSSProperty::MarginRight: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_MarginWidth.right, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasMargin = true; - } - break; - case FDE_CSSProperty::MarginBottom: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_MarginWidth.bottom, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasMargin = true; - } - break; - case FDE_CSSProperty::PaddingLeft: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_PaddingWidth.left, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasPadding = true; - } - break; - case FDE_CSSProperty::PaddingTop: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_PaddingWidth.top, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasPadding = true; - } - break; - case FDE_CSSProperty::PaddingRight: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_PaddingWidth.right, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasPadding = true; - } - break; - case FDE_CSSProperty::PaddingBottom: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_PaddingWidth.bottom, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasPadding = true; - } - break; - case FDE_CSSProperty::BorderLeftWidth: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_BorderWidth.left, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasBorder = true; - } - break; - case FDE_CSSProperty::BorderTopWidth: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_BorderWidth.top, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasBorder = true; - } - break; - case FDE_CSSProperty::BorderRightWidth: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_BorderWidth.right, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasBorder = true; - } - break; - case FDE_CSSProperty::BorderBottomWidth: - if (SetLengthWithPercent( - pComputedStyle->m_NonInheritedData.m_BorderWidth.bottom, eType, - pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { - pComputedStyle->m_NonInheritedData.m_bHasBorder = true; - } - break; - case FDE_CSSProperty::VerticalAlign: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_NonInheritedData.m_eVerticalAlign = - ToVerticalAlign(pValue.As<CFDE_CSSEnumValue>()->Value()); - } else if (eType == FDE_CSSPrimitiveType::Number) { - pComputedStyle->m_NonInheritedData.m_eVerticalAlign = - FDE_CSSVerticalAlign::Number; - pComputedStyle->m_NonInheritedData.m_fVerticalAlign = - pValue.As<CFDE_CSSNumberValue>()->Apply( - pComputedStyle->m_InheritedData.m_fFontSize); - } - break; - case FDE_CSSProperty::FontVariant: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_InheritedData.m_eFontVariant = - ToFontVariant(pValue.As<CFDE_CSSEnumValue>()->Value()); - } - break; - case FDE_CSSProperty::LetterSpacing: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_InheritedData.m_LetterSpacing.Set( - FDE_CSSLengthUnit::Normal); - } else if (eType == FDE_CSSPrimitiveType::Number) { - if (pValue.As<CFDE_CSSNumberValue>()->Kind() == - FDE_CSSNumberType::Percent) { - break; - } - - SetLengthWithPercent(pComputedStyle->m_InheritedData.m_LetterSpacing, - eType, pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - } - break; - case FDE_CSSProperty::WordSpacing: - if (eType == FDE_CSSPrimitiveType::Enum) { - pComputedStyle->m_InheritedData.m_WordSpacing.Set( - FDE_CSSLengthUnit::Normal); - } else if (eType == FDE_CSSPrimitiveType::Number) { - if (pValue.As<CFDE_CSSNumberValue>()->Kind() == - FDE_CSSNumberType::Percent) { - break; - } - SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing, - eType, pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - } - break; - case FDE_CSSProperty::Top: - SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Top, eType, - pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - break; - case FDE_CSSProperty::Bottom: - SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Bottom, eType, - pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - break; - case FDE_CSSProperty::Left: - SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Left, eType, - pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - break; - case FDE_CSSProperty::Right: - SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Right, eType, - pValue, - pComputedStyle->m_InheritedData.m_fFontSize); - break; - default: - break; - } - } else if (pValue->GetType() == FDE_CSSPrimitiveType::List) { - CFX_RetainPtr<CFDE_CSSValueList> pList = pValue.As<CFDE_CSSValueList>(); - int32_t iCount = pList->CountValues(); - if (iCount > 0) { - switch (eProperty) { - case FDE_CSSProperty::FontFamily: - pComputedStyle->m_InheritedData.m_pFontFamily = pList; - break; - case FDE_CSSProperty::TextDecoration: - pComputedStyle->m_NonInheritedData.m_dwTextDecoration = - ToTextDecoration(pList); - break; - default: - break; - } - } - } else { - ASSERT(false); - } -} - -FDE_CSSDisplay CFDE_CSSStyleSelector::ToDisplay(FDE_CSSPropertyValue eValue) { - switch (eValue) { - case FDE_CSSPropertyValue::Block: - return FDE_CSSDisplay::Block; - case FDE_CSSPropertyValue::None: - return FDE_CSSDisplay::None; - case FDE_CSSPropertyValue::ListItem: - return FDE_CSSDisplay::ListItem; - case FDE_CSSPropertyValue::InlineTable: - return FDE_CSSDisplay::InlineTable; - case FDE_CSSPropertyValue::InlineBlock: - return FDE_CSSDisplay::InlineBlock; - case FDE_CSSPropertyValue::Inline: - default: - return FDE_CSSDisplay::Inline; - } -} - -FDE_CSSTextAlign CFDE_CSSStyleSelector::ToTextAlign( - FDE_CSSPropertyValue eValue) { - switch (eValue) { - case FDE_CSSPropertyValue::Center: - return FDE_CSSTextAlign::Center; - case FDE_CSSPropertyValue::Right: - return FDE_CSSTextAlign::Right; - case FDE_CSSPropertyValue::Justify: - return FDE_CSSTextAlign::Justify; - case FDE_CSSPropertyValue::Left: - default: - return FDE_CSSTextAlign::Left; - } -} - -uint16_t CFDE_CSSStyleSelector::ToFontWeight(FDE_CSSPropertyValue eValue) { - switch (eValue) { - case FDE_CSSPropertyValue::Bold: - return 700; - case FDE_CSSPropertyValue::Bolder: - return 900; - case FDE_CSSPropertyValue::Lighter: - return 200; - case FDE_CSSPropertyValue::Normal: - default: - return 400; - } -} - -FDE_CSSFontStyle CFDE_CSSStyleSelector::ToFontStyle( - FDE_CSSPropertyValue eValue) { - switch (eValue) { - case FDE_CSSPropertyValue::Italic: - case FDE_CSSPropertyValue::Oblique: - return FDE_CSSFontStyle::Italic; - default: - return FDE_CSSFontStyle::Normal; - } -} - -bool CFDE_CSSStyleSelector::SetLengthWithPercent( - FDE_CSSLength& width, - FDE_CSSPrimitiveType eType, - const CFX_RetainPtr<CFDE_CSSValue>& pValue, - FX_FLOAT fFontSize) { - if (eType == FDE_CSSPrimitiveType::Number) { - CFX_RetainPtr<CFDE_CSSNumberValue> v = pValue.As<CFDE_CSSNumberValue>(); - if (v->Kind() == FDE_CSSNumberType::Percent) { - width.Set(FDE_CSSLengthUnit::Percent, - pValue.As<CFDE_CSSNumberValue>()->Value() / 100.0f); - return width.NonZero(); - } - - FX_FLOAT fValue = v->Apply(fFontSize); - width.Set(FDE_CSSLengthUnit::Point, fValue); - return width.NonZero(); - } else if (eType == FDE_CSSPrimitiveType::Enum) { - switch (pValue.As<CFDE_CSSEnumValue>()->Value()) { - case FDE_CSSPropertyValue::Auto: - width.Set(FDE_CSSLengthUnit::Auto); - return true; - case FDE_CSSPropertyValue::None: - width.Set(FDE_CSSLengthUnit::None); - return true; - case FDE_CSSPropertyValue::Thin: - width.Set(FDE_CSSLengthUnit::Point, 2); - return true; - case FDE_CSSPropertyValue::Medium: - width.Set(FDE_CSSLengthUnit::Point, 3); - return true; - case FDE_CSSPropertyValue::Thick: - width.Set(FDE_CSSLengthUnit::Point, 4); - return true; - default: - return false; - } - } - return false; -} - -FX_FLOAT CFDE_CSSStyleSelector::ToFontSize(FDE_CSSPropertyValue eValue, - FX_FLOAT fCurFontSize) { - switch (eValue) { - case FDE_CSSPropertyValue::XxSmall: - return m_fDefFontSize / 1.2f / 1.2f / 1.2f; - case FDE_CSSPropertyValue::XSmall: - return m_fDefFontSize / 1.2f / 1.2f; - case FDE_CSSPropertyValue::Small: - return m_fDefFontSize / 1.2f; - case FDE_CSSPropertyValue::Medium: - return m_fDefFontSize; - case FDE_CSSPropertyValue::Large: - return m_fDefFontSize * 1.2f; - case FDE_CSSPropertyValue::XLarge: - return m_fDefFontSize * 1.2f * 1.2f; - case FDE_CSSPropertyValue::XxLarge: - return m_fDefFontSize * 1.2f * 1.2f * 1.2f; - case FDE_CSSPropertyValue::Larger: - return fCurFontSize * 1.2f; - case FDE_CSSPropertyValue::Smaller: - return fCurFontSize / 1.2f; - default: - return fCurFontSize; - } -} - -FDE_CSSVerticalAlign CFDE_CSSStyleSelector::ToVerticalAlign( - FDE_CSSPropertyValue eValue) { - switch (eValue) { - case FDE_CSSPropertyValue::Middle: - return FDE_CSSVerticalAlign::Middle; - case FDE_CSSPropertyValue::Bottom: - return FDE_CSSVerticalAlign::Bottom; - case FDE_CSSPropertyValue::Super: - return FDE_CSSVerticalAlign::Super; - case FDE_CSSPropertyValue::Sub: - return FDE_CSSVerticalAlign::Sub; - case FDE_CSSPropertyValue::Top: - return FDE_CSSVerticalAlign::Top; - case FDE_CSSPropertyValue::TextTop: - return FDE_CSSVerticalAlign::TextTop; - case FDE_CSSPropertyValue::TextBottom: - return FDE_CSSVerticalAlign::TextBottom; - case FDE_CSSPropertyValue::Baseline: - default: - return FDE_CSSVerticalAlign::Baseline; - } -} - -uint32_t CFDE_CSSStyleSelector::ToTextDecoration( - const CFX_RetainPtr<CFDE_CSSValueList>& pValue) { - uint32_t dwDecoration = 0; - for (int32_t i = pValue->CountValues() - 1; i >= 0; --i) { - const CFX_RetainPtr<CFDE_CSSValue> pVal = pValue->GetValue(i); - if (pVal->GetType() != FDE_CSSPrimitiveType::Enum) - continue; - - switch (pVal.As<CFDE_CSSEnumValue>()->Value()) { - case FDE_CSSPropertyValue::Underline: - dwDecoration |= FDE_CSSTEXTDECORATION_Underline; - break; - case FDE_CSSPropertyValue::LineThrough: - dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough; - break; - case FDE_CSSPropertyValue::Overline: - dwDecoration |= FDE_CSSTEXTDECORATION_Overline; - break; - case FDE_CSSPropertyValue::Blink: - dwDecoration |= FDE_CSSTEXTDECORATION_Blink; - break; - case FDE_CSSPropertyValue::Double: - dwDecoration |= FDE_CSSTEXTDECORATION_Double; - break; - default: - break; - } - } - return dwDecoration; -} - -FDE_CSSFontVariant CFDE_CSSStyleSelector::ToFontVariant( - FDE_CSSPropertyValue eValue) { - return eValue == FDE_CSSPropertyValue::SmallCaps - ? FDE_CSSFontVariant::SmallCaps - : FDE_CSSFontVariant::Normal; -} diff --git a/xfa/fde/css/cfde_cssstyleselector.h b/xfa/fde/css/cfde_cssstyleselector.h deleted file mode 100644 index c7b6b4164a212f81c11373019f57dac99ed67a0e..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstyleselector.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSSTYLESELECTOR_H_ -#define XFA_FDE_CSS_CFDE_CSSSTYLESELECTOR_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/css/cfde_cssrulecollection.h" -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSComputedStyle; -class CFDE_CSSCustomProperty; -class CFDE_CSSDeclaration; -class CFDE_CSSPropertyHolder; -class CFDE_CSSSelector; -class CFDE_CSSStyleSheet; -class CFDE_CSSValue; -class CFDE_CSSValueList; -class CFGAS_FontMgr; - -class CFDE_CSSStyleSelector { - public: - explicit CFDE_CSSStyleSelector(CFGAS_FontMgr* pFontMgr); - ~CFDE_CSSStyleSelector(); - - void SetDefFontSize(FX_FLOAT fFontSize); - void SetUAStyleSheet(std::unique_ptr<CFDE_CSSStyleSheet> pSheet); - void UpdateStyleIndex(); - - CFX_RetainPtr<CFDE_CSSComputedStyle> CreateComputedStyle( - CFDE_CSSComputedStyle* pParentStyle); - - // Note, the dest style has to be an out param because the CXFA_TextParser - // adds non-inherited data from the parent style. Attempting to copy - // internally will fail as you'll lose the non-inherited data. - void ComputeStyle(const std::vector<const CFDE_CSSDeclaration*>& declArray, - const CFX_WideString& styleString, - const CFX_WideString& alignString, - CFDE_CSSComputedStyle* pDestStyle); - - std::vector<const CFDE_CSSDeclaration*> MatchDeclarations( - const CFX_WideString& tagname); - - private: - bool MatchSelector(const CFX_WideString& tagname, CFDE_CSSSelector* pSel); - - void AppendInlineStyle(CFDE_CSSDeclaration* pDecl, - const CFX_WideString& style); - void ApplyDeclarations( - const std::vector<const CFDE_CSSDeclaration*>& declArray, - const CFDE_CSSDeclaration* extraDecl, - CFDE_CSSComputedStyle* pDestStyle); - void ApplyProperty(FDE_CSSProperty eProperty, - const CFX_RetainPtr<CFDE_CSSValue>& pValue, - CFDE_CSSComputedStyle* pComputedStyle); - void ExtractValues(const CFDE_CSSDeclaration* decl, - std::vector<const CFDE_CSSPropertyHolder*>* importants, - std::vector<const CFDE_CSSPropertyHolder*>* normals, - std::vector<const CFDE_CSSCustomProperty*>* custom); - - bool SetLengthWithPercent(FDE_CSSLength& width, - FDE_CSSPrimitiveType eType, - const CFX_RetainPtr<CFDE_CSSValue>& pValue, - FX_FLOAT fFontSize); - FX_FLOAT ToFontSize(FDE_CSSPropertyValue eValue, FX_FLOAT fCurFontSize); - FDE_CSSDisplay ToDisplay(FDE_CSSPropertyValue eValue); - FDE_CSSTextAlign ToTextAlign(FDE_CSSPropertyValue eValue); - uint16_t ToFontWeight(FDE_CSSPropertyValue eValue); - FDE_CSSFontStyle ToFontStyle(FDE_CSSPropertyValue eValue); - FDE_CSSVerticalAlign ToVerticalAlign(FDE_CSSPropertyValue eValue); - uint32_t ToTextDecoration(const CFX_RetainPtr<CFDE_CSSValueList>& pList); - FDE_CSSFontVariant ToFontVariant(FDE_CSSPropertyValue eValue); - - CFGAS_FontMgr* const m_pFontMgr; - FX_FLOAT m_fDefFontSize; - std::unique_ptr<CFDE_CSSStyleSheet> m_UAStyles; - CFDE_CSSRuleCollection m_UARules; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSSTYLESELECTOR_H_ diff --git a/xfa/fde/css/cfde_cssstylesheet.cpp b/xfa/fde/css/cfde_cssstylesheet.cpp deleted file mode 100644 index c8bf70ec23169a20c16a641bb06ef0d93786d59d..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstylesheet.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssstylesheet.h" - -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/cfde_cssstylerule.h" -#include "xfa/fde/css/fde_cssdatatable.h" -#include "xfa/fgas/crt/fgas_codepage.h" - -CFDE_CSSStyleSheet::CFDE_CSSStyleSheet() {} - -CFDE_CSSStyleSheet::~CFDE_CSSStyleSheet() { - Reset(); -} - -void CFDE_CSSStyleSheet::Reset() { - m_RuleArray.clear(); - m_StringCache.clear(); -} - -int32_t CFDE_CSSStyleSheet::CountRules() const { - return pdfium::CollectionSize<int32_t>(m_RuleArray); -} - -CFDE_CSSStyleRule* CFDE_CSSStyleSheet::GetRule(int32_t index) const { - return m_RuleArray[index].get(); -} - -bool CFDE_CSSStyleSheet::LoadBuffer(const FX_WCHAR* pBuffer, int32_t iBufSize) { - ASSERT(pBuffer && iBufSize > 0); - - auto pSyntax = pdfium::MakeUnique<CFDE_CSSSyntaxParser>(); - if (!pSyntax->Init(pBuffer, iBufSize)) - return false; - - Reset(); - FDE_CSSSyntaxStatus eStatus; - do { - switch (eStatus = pSyntax->DoSyntaxParse()) { - case FDE_CSSSyntaxStatus::StyleRule: - eStatus = LoadStyleRule(pSyntax.get(), &m_RuleArray); - break; - default: - break; - } - } while (eStatus >= FDE_CSSSyntaxStatus::None); - - m_StringCache.clear(); - return eStatus != FDE_CSSSyntaxStatus::Error; -} - -FDE_CSSSyntaxStatus CFDE_CSSStyleSheet::LoadStyleRule( - CFDE_CSSSyntaxParser* pSyntax, - std::vector<std::unique_ptr<CFDE_CSSStyleRule>>* ruleArray) { - std::vector<std::unique_ptr<CFDE_CSSSelector>> selectors; - - CFDE_CSSStyleRule* pStyleRule = nullptr; - int32_t iValueLen = 0; - const FDE_CSSPropertyTable* propertyTable = nullptr; - CFX_WideString wsName; - while (1) { - switch (pSyntax->DoSyntaxParse()) { - case FDE_CSSSyntaxStatus::Selector: { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); - auto pSelector = CFDE_CSSSelector::FromString(strValue); - if (pSelector) - selectors.push_back(std::move(pSelector)); - break; - } - case FDE_CSSSyntaxStatus::PropertyName: { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); - propertyTable = FDE_GetCSSPropertyByName(strValue); - if (!propertyTable) - wsName = CFX_WideString(strValue); - break; - } - case FDE_CSSSyntaxStatus::PropertyValue: { - if (propertyTable || iValueLen > 0) { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); - auto decl = pStyleRule->GetDeclaration(); - if (!strValue.IsEmpty()) { - if (propertyTable) { - decl->AddProperty(propertyTable, strValue); - } else { - decl->AddProperty(wsName, CFX_WideString(strValue)); - } - } - } - break; - } - case FDE_CSSSyntaxStatus::DeclOpen: { - if (!pStyleRule && !selectors.empty()) { - auto rule = pdfium::MakeUnique<CFDE_CSSStyleRule>(); - pStyleRule = rule.get(); - pStyleRule->SetSelector(&selectors); - ruleArray->push_back(std::move(rule)); - } else { - SkipRuleSet(pSyntax); - return FDE_CSSSyntaxStatus::None; - } - break; - } - case FDE_CSSSyntaxStatus::DeclClose: { - if (pStyleRule && pStyleRule->GetDeclaration()->empty()) { - ruleArray->pop_back(); - pStyleRule = nullptr; - } - return FDE_CSSSyntaxStatus::None; - } - case FDE_CSSSyntaxStatus::EOS: - return FDE_CSSSyntaxStatus::EOS; - case FDE_CSSSyntaxStatus::Error: - default: - return FDE_CSSSyntaxStatus::Error; - } - } -} - -void CFDE_CSSStyleSheet::SkipRuleSet(CFDE_CSSSyntaxParser* pSyntax) { - while (1) { - switch (pSyntax->DoSyntaxParse()) { - case FDE_CSSSyntaxStatus::Selector: - case FDE_CSSSyntaxStatus::DeclOpen: - case FDE_CSSSyntaxStatus::PropertyName: - case FDE_CSSSyntaxStatus::PropertyValue: - break; - case FDE_CSSSyntaxStatus::DeclClose: - case FDE_CSSSyntaxStatus::EOS: - case FDE_CSSSyntaxStatus::Error: - default: - return; - } - } -} diff --git a/xfa/fde/css/cfde_cssstylesheet.h b/xfa/fde/css/cfde_cssstylesheet.h deleted file mode 100644 index 4de377219c5ed109919aab9c48d3a6d52c5760d0..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstylesheet.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSSTYLESHEET_H_ -#define XFA_FDE_CSS_CFDE_CSSSTYLESHEET_H_ - -#include <memory> -#include <unordered_map> -#include <vector> - -#include "core/fxcrt/fx_string.h" -#include "xfa/fde/css/cfde_csssyntaxparser.h" - -class CFDE_CSSStyleRule; - -class CFDE_CSSStyleSheet { - public: - CFDE_CSSStyleSheet(); - ~CFDE_CSSStyleSheet(); - - bool LoadBuffer(const FX_WCHAR* pBuffer, int32_t iBufSize); - - int32_t CountRules() const; - CFDE_CSSStyleRule* GetRule(int32_t index) const; - - private: - void Reset(); - FDE_CSSSyntaxStatus LoadStyleRule( - CFDE_CSSSyntaxParser* pSyntax, - std::vector<std::unique_ptr<CFDE_CSSStyleRule>>* ruleArray); - void SkipRuleSet(CFDE_CSSSyntaxParser* pSyntax); - - std::vector<std::unique_ptr<CFDE_CSSStyleRule>> m_RuleArray; - std::unordered_map<uint32_t, FX_WCHAR*> m_StringCache; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSSTYLESHEET_H_ diff --git a/xfa/fde/css/cfde_cssstylesheet_unittest.cpp b/xfa/fde/css/cfde_cssstylesheet_unittest.cpp deleted file mode 100644 index fa73a7a9ba70433e6a3853dd5ae6eab811424d0c..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssstylesheet_unittest.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssstylesheet.h" - -#include <memory> -#include <vector> - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/cfde_cssenumvalue.h" -#include "xfa/fde/css/cfde_cssnumbervalue.h" -#include "xfa/fde/css/cfde_cssstylerule.h" -#include "xfa/fde/css/cfde_cssvaluelist.h" - -class CFDE_CSSStyleSheetTest : public testing::Test { - public: - void SetUp() override { - sheet_ = pdfium::MakeUnique<CFDE_CSSStyleSheet>(); - decl_ = nullptr; - } - - void TearDown() override { decl_ = nullptr; } - - void LoadAndVerifyDecl(const FX_WCHAR* buf, - const std::vector<CFX_WideString>& selectors, - size_t decl_count) { - ASSERT(sheet_); - - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(sheet_->CountRules(), 1); - - CFDE_CSSStyleRule* style = sheet_->GetRule(0); - EXPECT_EQ(selectors.size(), style->CountSelectorLists()); - - for (size_t i = 0; i < selectors.size(); i++) { - uint32_t hash = FX_HashCode_GetW(selectors[i].AsStringC(), true); - EXPECT_EQ(hash, style->GetSelectorList(i)->GetNameHash()); - } - - decl_ = style->GetDeclaration(); - EXPECT_EQ(decl_->PropertyCountForTesting(), decl_count); - } - - void VerifyFloat(FDE_CSSProperty prop, float val, FDE_CSSNumberType type) { - ASSERT(decl_); - - bool important; - CFX_RetainPtr<CFDE_CSSValue> v = decl_->GetProperty(prop, &important); - EXPECT_EQ(v->GetType(), FDE_CSSPrimitiveType::Number); - EXPECT_EQ(v.As<CFDE_CSSNumberValue>()->Kind(), type); - EXPECT_EQ(v.As<CFDE_CSSNumberValue>()->Value(), val); - } - - void VerifyEnum(FDE_CSSProperty prop, FDE_CSSPropertyValue val) { - ASSERT(decl_); - - bool important; - CFX_RetainPtr<CFDE_CSSValue> v = decl_->GetProperty(prop, &important); - EXPECT_EQ(v->GetType(), FDE_CSSPrimitiveType::Enum); - EXPECT_EQ(v.As<CFDE_CSSEnumValue>()->Value(), val); - } - - void VerifyList(FDE_CSSProperty prop, - std::vector<FDE_CSSPropertyValue> values) { - ASSERT(decl_); - - bool important; - CFX_RetainPtr<CFDE_CSSValueList> list = - decl_->GetProperty(prop, &important).As<CFDE_CSSValueList>(); - EXPECT_EQ(list->CountValues(), pdfium::CollectionSize<int32_t>(values)); - - for (size_t i = 0; i < values.size(); i++) { - CFX_RetainPtr<CFDE_CSSValue> val = list->GetValue(i); - EXPECT_EQ(val->GetType(), FDE_CSSPrimitiveType::Enum); - EXPECT_EQ(val.As<CFDE_CSSEnumValue>()->Value(), values[i]); - } - } - - std::unique_ptr<CFDE_CSSStyleSheet> sheet_; - CFDE_CSSDeclaration* decl_; -}; - -TEST_F(CFDE_CSSStyleSheetTest, ParseMultipleSelectors) { - const FX_WCHAR* buf = - L"a { border: 10px; }\nb { text-decoration: underline; }"; - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(2, sheet_->CountRules()); - - CFDE_CSSStyleRule* style = sheet_->GetRule(0); - EXPECT_EQ(1UL, style->CountSelectorLists()); - - bool found_selector = false; - uint32_t hash = FX_HashCode_GetW(L"a", true); - for (size_t i = 0; i < style->CountSelectorLists(); i++) { - if (style->GetSelectorList(i)->GetNameHash() == hash) { - found_selector = true; - break; - } - } - EXPECT_TRUE(found_selector); - - decl_ = style->GetDeclaration(); - EXPECT_EQ(4UL, decl_->PropertyCountForTesting()); - - VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 10.0, - FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderRightWidth, 10.0, - FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderTopWidth, 10.0, FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 10.0, - FDE_CSSNumberType::Pixels); - - style = sheet_->GetRule(1); - EXPECT_EQ(1UL, style->CountSelectorLists()); - - found_selector = false; - hash = FX_HashCode_GetW(L"b", true); - for (size_t i = 0; i < style->CountSelectorLists(); i++) { - if (style->GetSelectorList(i)->GetNameHash() == hash) { - found_selector = true; - break; - } - } - EXPECT_TRUE(found_selector); - - decl_ = style->GetDeclaration(); - EXPECT_EQ(1UL, decl_->PropertyCountForTesting()); - VerifyList(FDE_CSSProperty::TextDecoration, - {FDE_CSSPropertyValue::Underline}); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseChildSelectors) { - const FX_WCHAR* buf = L"a b c { border: 10px; }"; - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(1, sheet_->CountRules()); - - CFDE_CSSStyleRule* style = sheet_->GetRule(0); - EXPECT_EQ(1UL, style->CountSelectorLists()); - - auto sel = style->GetSelectorList(0); - EXPECT_TRUE(sel != nullptr); - EXPECT_EQ(FX_HashCode_GetW(L"c", true), sel->GetNameHash()); - - sel = sel->GetNextSelector(); - EXPECT_TRUE(sel != nullptr); - EXPECT_EQ(FX_HashCode_GetW(L"b", true), sel->GetNameHash()); - - sel = sel->GetNextSelector(); - EXPECT_TRUE(sel != nullptr); - EXPECT_EQ(FX_HashCode_GetW(L"a", true), sel->GetNameHash()); - - sel = sel->GetNextSelector(); - EXPECT_TRUE(sel == nullptr); - - decl_ = style->GetDeclaration(); - EXPECT_EQ(4UL, decl_->PropertyCountForTesting()); - - VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 10.0, - FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderRightWidth, 10.0, - FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderTopWidth, 10.0, FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 10.0, - FDE_CSSNumberType::Pixels); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseUnhandledSelectors) { - const FX_WCHAR* buf = L"a > b { padding: 0; }"; - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(0, sheet_->CountRules()); - - buf = L"a[first] { padding: 0; }"; - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(0, sheet_->CountRules()); - - buf = L"a+b { padding: 0; }"; - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(0, sheet_->CountRules()); - - buf = L"a ^ b { padding: 0; }"; - EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf))); - EXPECT_EQ(0, sheet_->CountRules()); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseMultipleSelectorsCombined) { - LoadAndVerifyDecl(L"a, b, c { border: 5px; }", {L"a", L"b", L"c"}, 4); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorder) { - LoadAndVerifyDecl(L"a { border: 5px; }", {L"a"}, 4); - VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 5.0, FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderRightWidth, 5.0, - FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderTopWidth, 5.0, FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 5.0, - FDE_CSSNumberType::Pixels); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorderFull) { - LoadAndVerifyDecl(L"a { border: 5px solid red; }", {L"a"}, 4); - VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 5.0, FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderRightWidth, 5.0, - FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderTopWidth, 5.0, FDE_CSSNumberType::Pixels); - VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 5.0, - FDE_CSSNumberType::Pixels); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorderLeft) { - LoadAndVerifyDecl(L"a { border-left: 2.5pc; }", {L"a"}, 1); - VerifyFloat(FDE_CSSProperty::BorderLeftWidth, 2.5, FDE_CSSNumberType::Picas); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorderLeftThick) { - LoadAndVerifyDecl(L"a { border-left: thick; }", {L"a"}, 1); - VerifyEnum(FDE_CSSProperty::BorderLeftWidth, FDE_CSSPropertyValue::Thick); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorderRight) { - LoadAndVerifyDecl(L"a { border-right: 2.5pc; }", {L"a"}, 1); - VerifyFloat(FDE_CSSProperty::BorderRightWidth, 2.5, FDE_CSSNumberType::Picas); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorderTop) { - LoadAndVerifyDecl(L"a { border-top: 2.5pc; }", {L"a"}, 1); - VerifyFloat(FDE_CSSProperty::BorderTopWidth, 2.5, FDE_CSSNumberType::Picas); -} - -TEST_F(CFDE_CSSStyleSheetTest, ParseBorderBottom) { - LoadAndVerifyDecl(L"a { border-bottom: 2.5pc; }", {L"a"}, 1); - VerifyFloat(FDE_CSSProperty::BorderBottomWidth, 2.5, - FDE_CSSNumberType::Picas); -} diff --git a/xfa/fde/css/cfde_csssyntaxparser.cpp b/xfa/fde/css/cfde_csssyntaxparser.cpp deleted file mode 100644 index 2f7bcce9d7f427b322b9ab11f9f4608b7473845d..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csssyntaxparser.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_csssyntaxparser.h" - -#include <algorithm> - -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/fde_cssdatatable.h" -#include "xfa/fgas/crt/fgas_codepage.h" - -namespace { - -bool IsSelectorStart(FX_WCHAR wch) { - return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') || - (wch >= 'A' && wch <= 'Z'); -} - -} // namespace - -CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser() - : m_iTextDataLen(0), - m_dwCheck((uint32_t)-1), - m_eMode(FDE_CSSSyntaxMode::RuleSet), - m_eStatus(FDE_CSSSyntaxStatus::None) {} - -CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() { - m_TextData.Reset(); - m_TextPlane.Reset(); -} - -bool CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer, - int32_t iBufferSize, - int32_t iTextDatSize, - bool bOnlyDeclaration) { - ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0); - Reset(bOnlyDeclaration); - if (!m_TextData.EstimateSize(iTextDatSize)) - return false; - return m_TextPlane.AttachBuffer(pBuffer, iBufferSize); -} - -void CFDE_CSSSyntaxParser::Reset(bool bOnlyDeclaration) { - m_TextPlane.Reset(); - m_TextData.Reset(); - m_iTextDataLen = 0; - m_dwCheck = (uint32_t)-1; - m_eStatus = FDE_CSSSyntaxStatus::None; - m_eMode = bOnlyDeclaration ? FDE_CSSSyntaxMode::PropertyName - : FDE_CSSSyntaxMode::RuleSet; -} - -FDE_CSSSyntaxStatus CFDE_CSSSyntaxParser::DoSyntaxParse() { - while (m_eStatus >= FDE_CSSSyntaxStatus::None) { - if (m_TextPlane.IsEOF()) { - if (m_eMode == FDE_CSSSyntaxMode::PropertyValue && - m_TextData.GetLength() > 0) { - SaveTextData(); - m_eStatus = FDE_CSSSyntaxStatus::PropertyValue; - return m_eStatus; - } - m_eStatus = FDE_CSSSyntaxStatus::EOS; - return m_eStatus; - } - FX_WCHAR wch; - while (!m_TextPlane.IsEOF()) { - wch = m_TextPlane.GetChar(); - switch (m_eMode) { - case FDE_CSSSyntaxMode::RuleSet: - switch (wch) { - case '}': - m_TextPlane.MoveNext(); - if (RestoreMode()) - return FDE_CSSSyntaxStatus::DeclClose; - - m_eStatus = FDE_CSSSyntaxStatus::Error; - return m_eStatus; - case '/': - if (m_TextPlane.GetNextChar() == '*') { - m_ModeStack.push(m_eMode); - SwitchMode(FDE_CSSSyntaxMode::Comment); - break; - } - default: - if (wch <= ' ') { - m_TextPlane.MoveNext(); - } else if (IsSelectorStart(wch)) { - SwitchMode(FDE_CSSSyntaxMode::Selector); - return FDE_CSSSyntaxStatus::StyleRule; - } else { - m_eStatus = FDE_CSSSyntaxStatus::Error; - return m_eStatus; - } - break; - } - break; - case FDE_CSSSyntaxMode::Selector: - switch (wch) { - case ',': - m_TextPlane.MoveNext(); - SwitchMode(FDE_CSSSyntaxMode::Selector); - if (m_iTextDataLen > 0) - return FDE_CSSSyntaxStatus::Selector; - break; - case '{': - if (m_TextData.GetLength() > 0) { - SaveTextData(); - return FDE_CSSSyntaxStatus::Selector; - } - m_TextPlane.MoveNext(); - m_ModeStack.push(FDE_CSSSyntaxMode::RuleSet); - SwitchMode(FDE_CSSSyntaxMode::PropertyName); - return FDE_CSSSyntaxStatus::DeclOpen; - case '/': - if (m_TextPlane.GetNextChar() == '*') { - if (SwitchToComment() > 0) - return FDE_CSSSyntaxStatus::Selector; - break; - } - default: - AppendChar(wch); - break; - } - break; - case FDE_CSSSyntaxMode::PropertyName: - switch (wch) { - case ':': - m_TextPlane.MoveNext(); - SwitchMode(FDE_CSSSyntaxMode::PropertyValue); - return FDE_CSSSyntaxStatus::PropertyName; - case '}': - m_TextPlane.MoveNext(); - if (RestoreMode()) - return FDE_CSSSyntaxStatus::DeclClose; - - m_eStatus = FDE_CSSSyntaxStatus::Error; - return m_eStatus; - case '/': - if (m_TextPlane.GetNextChar() == '*') { - if (SwitchToComment() > 0) - return FDE_CSSSyntaxStatus::PropertyName; - break; - } - default: - AppendChar(wch); - break; - } - break; - case FDE_CSSSyntaxMode::PropertyValue: - switch (wch) { - case ';': - m_TextPlane.MoveNext(); - case '}': - SwitchMode(FDE_CSSSyntaxMode::PropertyName); - return FDE_CSSSyntaxStatus::PropertyValue; - case '/': - if (m_TextPlane.GetNextChar() == '*') { - if (SwitchToComment() > 0) - return FDE_CSSSyntaxStatus::PropertyValue; - break; - } - default: - AppendChar(wch); - break; - } - break; - case FDE_CSSSyntaxMode::Comment: - if (wch == '/' && m_TextData.GetLength() > 0 && - m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') { - RestoreMode(); - } else { - m_TextData.AppendChar(wch); - } - m_TextPlane.MoveNext(); - break; - case FDE_CSSSyntaxMode::UnknownRule: - if (wch == ';') - SwitchMode(FDE_CSSSyntaxMode::RuleSet); - m_TextPlane.MoveNext(); - break; - default: - ASSERT(false); - break; - } - } - } - return m_eStatus; -} - -bool CFDE_CSSSyntaxParser::IsImportEnabled() const { - if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) - return false; - if (m_ModeStack.size() > 1) - return false; - return true; -} - -bool CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) { - m_TextPlane.MoveNext(); - if (m_TextData.GetLength() > 0 || wch > ' ') { - m_TextData.AppendChar(wch); - return true; - } - return false; -} - -int32_t CFDE_CSSSyntaxParser::SaveTextData() { - m_iTextDataLen = m_TextData.TrimEnd(); - m_TextData.Clear(); - return m_iTextDataLen; -} - -void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSyntaxMode eMode) { - m_eMode = eMode; - SaveTextData(); -} - -int32_t CFDE_CSSSyntaxParser::SwitchToComment() { - int32_t iLength = m_TextData.GetLength(); - m_ModeStack.push(m_eMode); - SwitchMode(FDE_CSSSyntaxMode::Comment); - return iLength; -} - -bool CFDE_CSSSyntaxParser::RestoreMode() { - if (m_ModeStack.empty()) - return false; - - SwitchMode(m_ModeStack.top()); - m_ModeStack.pop(); - return true; -} - -CFX_WideStringC CFDE_CSSSyntaxParser::GetCurrentString() const { - return CFX_WideStringC(m_TextData.GetBuffer(), m_iTextDataLen); -} diff --git a/xfa/fde/css/cfde_csssyntaxparser.h b/xfa/fde/css/cfde_csssyntaxparser.h deleted file mode 100644 index b583b98b15ff94a65feb400f6a316c8e0fe0747a..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csssyntaxparser.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSSYNTAXPARSER_H_ -#define XFA_FDE_CSS_CFDE_CSSSYNTAXPARSER_H_ - -#include <stack> - -#include "xfa/fde/css/cfde_csstextbuf.h" - -#define FDE_CSSSYNTAXCHECK_AllowCharset 1 -#define FDE_CSSSYNTAXCHECK_AllowImport 2 - -enum class FDE_CSSSyntaxMode { - RuleSet, - Comment, - UnknownRule, - Selector, - PropertyName, - PropertyValue, -}; - -enum class FDE_CSSSyntaxStatus : uint8_t { - Error, - EOS, - None, - StyleRule, - Selector, - DeclOpen, - DeclClose, - PropertyName, - PropertyValue, -}; - -class CFDE_CSSSyntaxParser { - public: - CFDE_CSSSyntaxParser(); - ~CFDE_CSSSyntaxParser(); - - bool Init(const FX_WCHAR* pBuffer, - int32_t iBufferSize, - int32_t iTextDatSize = 32, - bool bOnlyDeclaration = false); - FDE_CSSSyntaxStatus DoSyntaxParse(); - CFX_WideStringC GetCurrentString() const; - - protected: - void Reset(bool bOnlyDeclaration); - void SwitchMode(FDE_CSSSyntaxMode eMode); - int32_t SwitchToComment(); - - bool RestoreMode(); - bool AppendChar(FX_WCHAR wch); - int32_t SaveTextData(); - bool IsCharsetEnabled() const { - return (m_dwCheck & FDE_CSSSYNTAXCHECK_AllowCharset) != 0; - } - void DisableCharset() { m_dwCheck = FDE_CSSSYNTAXCHECK_AllowImport; } - bool IsImportEnabled() const; - void DisableImport() { m_dwCheck = 0; } - - CFDE_CSSTextBuf m_TextData; - CFDE_CSSTextBuf m_TextPlane; - int32_t m_iTextDataLen; - uint32_t m_dwCheck; - FDE_CSSSyntaxMode m_eMode; - FDE_CSSSyntaxStatus m_eStatus; - std::stack<FDE_CSSSyntaxMode> m_ModeStack; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSSYNTAXPARSER_H_ diff --git a/xfa/fde/css/cfde_csstextbuf.cpp b/xfa/fde/css/cfde_csstextbuf.cpp deleted file mode 100644 index 83b2899f1989a84be3789074cc454bb9880c3967..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csstextbuf.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_csstextbuf.h" - -#include <algorithm> - -CFDE_CSSTextBuf::CFDE_CSSTextBuf() - : m_bExtBuf(false), - m_pBuffer(nullptr), - m_iBufLen(0), - m_iDatLen(0), - m_iDatPos(0) {} - -CFDE_CSSTextBuf::~CFDE_CSSTextBuf() { - Reset(); -} - -void CFDE_CSSTextBuf::Reset() { - if (!m_bExtBuf) { - FX_Free(m_pBuffer); - m_pBuffer = nullptr; - } - m_iDatPos = m_iDatLen = m_iBufLen; -} - -bool CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, int32_t iBufLen) { - Reset(); - m_pBuffer = const_cast<FX_WCHAR*>(pBuffer); - m_iDatLen = m_iBufLen = iBufLen; - return m_bExtBuf = true; -} - -bool CFDE_CSSTextBuf::EstimateSize(int32_t iAllocSize) { - ASSERT(iAllocSize > 0); - Clear(); - m_bExtBuf = false; - return ExpandBuf(iAllocSize); -} - -int32_t CFDE_CSSTextBuf::LoadFromStream( - const CFX_RetainPtr<IFGAS_Stream>& pTxtStream, - int32_t iStreamOffset, - int32_t iMaxChars, - bool& bEOS) { - ASSERT(iStreamOffset >= 0 && iMaxChars > 0); - Clear(); - m_bExtBuf = false; - if (!ExpandBuf(iMaxChars)) - return 0; - - if (pTxtStream->GetPosition() != iStreamOffset) - pTxtStream->Seek(FX_STREAMSEEK_Begin, iStreamOffset); - - m_iDatLen = pTxtStream->ReadString(m_pBuffer, iMaxChars, bEOS); - return m_iDatLen; -} - -bool CFDE_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) { - if (m_bExtBuf) - return false; - if (!m_pBuffer) - m_pBuffer = FX_Alloc(FX_WCHAR, iDesiredSize); - else if (m_iBufLen != iDesiredSize) - m_pBuffer = FX_Realloc(FX_WCHAR, m_pBuffer, iDesiredSize); - else - return true; - - if (!m_pBuffer) { - m_iBufLen = 0; - return false; - } - m_iBufLen = iDesiredSize; - return true; -} - -void CFDE_CSSTextBuf::Subtract(int32_t iStart, int32_t iLength) { - ASSERT(iStart >= 0 && iLength >= 0); - - iLength = std::max(std::min(iLength, m_iDatLen - iStart), 0); - FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR)); - m_iDatLen = iLength; -} diff --git a/xfa/fde/css/cfde_csstextbuf.h b/xfa/fde/css/cfde_csstextbuf.h deleted file mode 100644 index df151e02d8189356a08170513e9efab85c47628a..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_csstextbuf.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSTEXTBUF_H_ -#define XFA_FDE_CSS_CFDE_CSSTEXTBUF_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fgas/crt/fgas_stream.h" - -class CFDE_CSSTextBuf { - public: - CFDE_CSSTextBuf(); - ~CFDE_CSSTextBuf(); - - bool AttachBuffer(const FX_WCHAR* pBuffer, int32_t iBufLen); - bool EstimateSize(int32_t iAllocSize); - int32_t LoadFromStream(const CFX_RetainPtr<IFGAS_Stream>& pTxtStream, - int32_t iStreamOffset, - int32_t iMaxChars, - bool& bEOS); - bool AppendChar(FX_WCHAR wch) { - if (m_iDatLen >= m_iBufLen && !ExpandBuf(m_iBufLen * 2)) - return false; - m_pBuffer[m_iDatLen++] = wch; - return true; - } - - void Clear() { m_iDatPos = m_iDatLen = 0; } - void Reset(); - - int32_t TrimEnd() { - while (m_iDatLen > 0 && m_pBuffer[m_iDatLen - 1] <= ' ') - --m_iDatLen; - AppendChar(0); - return --m_iDatLen; - } - - void Subtract(int32_t iStart, int32_t iLength); - bool IsEOF() const { return m_iDatPos >= m_iDatLen; } - - FX_WCHAR GetAt(int32_t index) const { return m_pBuffer[index]; } - FX_WCHAR GetChar() const { return m_pBuffer[m_iDatPos]; } - FX_WCHAR GetNextChar() const { - return (m_iDatPos + 1 >= m_iDatLen) ? 0 : m_pBuffer[m_iDatPos + 1]; - } - - void MoveNext() { m_iDatPos++; } - - int32_t GetLength() const { return m_iDatLen; } - const FX_WCHAR* GetBuffer() const { return m_pBuffer; } - - protected: - bool ExpandBuf(int32_t iDesiredSize); - bool m_bExtBuf; - FX_WCHAR* m_pBuffer; - int32_t m_iBufLen; - int32_t m_iDatLen; - int32_t m_iDatPos; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSTEXTBUF_H_ diff --git a/xfa/fde/css/cfde_cssvalue.cpp b/xfa/fde/css/cfde_cssvalue.cpp deleted file mode 100644 index ef7029f9a5d5dcc9a0a16390102d798c00bcbe0f..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvalue.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssvalue.h" - -CFDE_CSSValue::CFDE_CSSValue(FDE_CSSPrimitiveType type) : m_value(type) {} diff --git a/xfa/fde/css/cfde_cssvalue.h b/xfa/fde/css/cfde_cssvalue.h deleted file mode 100644 index 71d254bbeaca21fdd821c3f0955d5526007f6aae..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvalue.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSVALUE_H_ -#define XFA_FDE_CSS_CFDE_CSSVALUE_H_ - -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSValue : public CFX_Retainable { - public: - FDE_CSSPrimitiveType GetType() const { return m_value; } - - protected: - explicit CFDE_CSSValue(FDE_CSSPrimitiveType type); - - private: - FDE_CSSPrimitiveType m_value; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSVALUE_H_ diff --git a/xfa/fde/css/cfde_cssvaluelist.cpp b/xfa/fde/css/cfde_cssvaluelist.cpp deleted file mode 100644 index 737ffcb04555e7423815b79f239f26be8a5e90f8..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvaluelist.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssvaluelist.h" - -#include <utility> - -#include "xfa/fde/css/fde_css.h" - -CFDE_CSSValueList::CFDE_CSSValueList( - std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list) - : CFDE_CSSValue(FDE_CSSPrimitiveType::List), m_ppList(std::move(list)) {} - -CFDE_CSSValueList::~CFDE_CSSValueList() {} - -int32_t CFDE_CSSValueList::CountValues() const { - return m_ppList.size(); -} - -CFX_RetainPtr<CFDE_CSSValue> CFDE_CSSValueList::GetValue(int32_t index) const { - return m_ppList[index]; -} diff --git a/xfa/fde/css/cfde_cssvaluelist.h b/xfa/fde/css/cfde_cssvaluelist.h deleted file mode 100644 index a47f8a3250d17bb03258adf1b123013eaed0a3be..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvaluelist.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSVALUELIST_H_ -#define XFA_FDE_CSS_CFDE_CSSVALUELIST_H_ - -#include <vector> - -#include "xfa/fde/css/cfde_cssvalue.h" - -class CFDE_CSSValueList : public CFDE_CSSValue { - public: - explicit CFDE_CSSValueList(std::vector<CFX_RetainPtr<CFDE_CSSValue>>& list); - ~CFDE_CSSValueList() override; - - int32_t CountValues() const; - CFX_RetainPtr<CFDE_CSSValue> GetValue(int32_t index) const; - - protected: - std::vector<CFX_RetainPtr<CFDE_CSSValue>> m_ppList; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSVALUELIST_H_ diff --git a/xfa/fde/css/cfde_cssvaluelistparser.cpp b/xfa/fde/css/cfde_cssvaluelistparser.cpp deleted file mode 100644 index 42c32968654e1a48d941efc5ee5d4f76cae877f3..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvaluelistparser.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssvaluelistparser.h" - -CFDE_CSSValueListParser::CFDE_CSSValueListParser(const FX_WCHAR* psz, - int32_t iLen, - FX_WCHAR separator) - : m_Separator(separator), m_pCur(psz), m_pEnd(psz + iLen) { - ASSERT(psz && iLen > 0); -} - -bool CFDE_CSSValueListParser::NextValue(FDE_CSSPrimitiveType& eType, - const FX_WCHAR*& pStart, - int32_t& iLength) { - while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator)) - ++m_pCur; - - if (m_pCur >= m_pEnd) - return false; - - eType = FDE_CSSPrimitiveType::Unknown; - pStart = m_pCur; - iLength = 0; - FX_WCHAR wch = *m_pCur; - if (wch == '#') { - iLength = SkipTo(' ', false, false); - if (iLength == 4 || iLength == 7) - eType = FDE_CSSPrimitiveType::RGB; - } else if ((wch >= '0' && wch <= '9') || wch == '.' || wch == '-' || - wch == '+') { - while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator)) - ++m_pCur; - - iLength = m_pCur - pStart; - eType = FDE_CSSPrimitiveType::Number; - } else if (wch == '\"' || wch == '\'') { - pStart++; - m_pCur++; - iLength = SkipTo(wch, false, false); - m_pCur++; - eType = FDE_CSSPrimitiveType::String; - } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') { - if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) { - iLength = SkipTo(')', false, false) + 1; - m_pCur++; - eType = FDE_CSSPrimitiveType::RGB; - } - } else { - iLength = SkipTo(m_Separator, true, true); - eType = FDE_CSSPrimitiveType::String; - } - return m_pCur <= m_pEnd && iLength > 0; -} - -int32_t CFDE_CSSValueListParser::SkipTo(FX_WCHAR wch, - bool breakOnSpace, - bool matchBrackets) { - const FX_WCHAR* pStart = m_pCur; - int32_t bracketCount = 0; - while (m_pCur < m_pEnd && *m_pCur != wch) { - if (breakOnSpace && *m_pCur <= ' ') - break; - if (!matchBrackets) { - m_pCur++; - continue; - } - - if (*m_pCur == '(') - bracketCount++; - else if (*m_pCur == ')') - bracketCount--; - - m_pCur++; - } - - while (bracketCount > 0 && m_pCur < m_pEnd) { - if (*m_pCur == ')') - bracketCount--; - m_pCur++; - } - return m_pCur - pStart; -} diff --git a/xfa/fde/css/cfde_cssvaluelistparser.h b/xfa/fde/css/cfde_cssvaluelistparser.h deleted file mode 100644 index 734aed8a520a8d862cf2b49b3d0f3528f38ca1fd..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvaluelistparser.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_CFDE_CSSVALUELISTPARSER_H_ -#define XFA_FDE_CSS_CFDE_CSSVALUELISTPARSER_H_ - -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSValueListParser { - public: - CFDE_CSSValueListParser(const FX_WCHAR* psz, - int32_t iLen, - FX_WCHAR separator); - - bool NextValue(FDE_CSSPrimitiveType& eType, - const FX_WCHAR*& pStart, - int32_t& iLength); - - FX_WCHAR m_Separator; - - private: - int32_t SkipTo(FX_WCHAR wch, bool breakOnSpace, bool matchBrackets); - - const FX_WCHAR* m_pCur; - const FX_WCHAR* m_pEnd; -}; - -#endif // XFA_FDE_CSS_CFDE_CSSVALUELISTPARSER_H_ diff --git a/xfa/fde/css/cfde_cssvaluelistparser_unittest.cpp b/xfa/fde/css/cfde_cssvaluelistparser_unittest.cpp deleted file mode 100644 index 71bb807f3d178b823ab9fc91f4ce2ca69a444f1a..0000000000000000000000000000000000000000 --- a/xfa/fde/css/cfde_cssvaluelistparser_unittest.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/cfde_cssvaluelistparser.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/ptr_util.h" - -TEST(CFDE_CSSValueListParser, rgb_short) { - FDE_CSSPrimitiveType type; - const FX_WCHAR* start; - int32_t len; - - auto parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"#abc", 4, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"#abc", CFX_WideString(start, len)); - EXPECT_FALSE(parser->NextValue(type, start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"#abcdef", 7, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"#abcdef", CFX_WideString(start, len)); - EXPECT_FALSE(parser->NextValue(type, start, len)); - - parser = - pdfium::MakeUnique<CFDE_CSSValueListParser>(L"rgb(1, 255, 4)", 14, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"rgb(1, 255, 4)", CFX_WideString(start, len)); - - parser = - pdfium::MakeUnique<CFDE_CSSValueListParser>(L"#abcdefghij", 11, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Unknown, type); - EXPECT_EQ(L"#abcdefghij", CFX_WideString(start, len)); - EXPECT_FALSE(parser->NextValue(type, start, len)); -} - -TEST(CFDE_CSSValueListParser, number_parsing) { - FDE_CSSPrimitiveType type; - const FX_WCHAR* start; - int32_t len; - - auto parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"1234", 4, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"1234", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"-1234", 5, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"-1234", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"+1234", 5, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"+1234", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L".1234", 5, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L".1234", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"4321.1234", 9, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"4321.1234", CFX_WideString(start, len)); - - // TODO(dsinclair): These should probably fail but currently don't. - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"4321.12.34", 10, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"4321.12.34", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"43a1.12.34", 10, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"43a1.12.34", CFX_WideString(start, len)); -} - -TEST(CFDE_CSSValueListParser, string_parsing) { - FDE_CSSPrimitiveType type; - const FX_WCHAR* start; - int32_t len; - - auto parser = - pdfium::MakeUnique<CFDE_CSSValueListParser>(L"'string'", 8, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::String, type); - EXPECT_EQ(L"string", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"\"another string\"", - 16, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::String, type); - EXPECT_EQ(L"another string", CFX_WideString(start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>(L"standalone", 10, L' '); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::String, type); - EXPECT_EQ(L"standalone", CFX_WideString(start, len)); -} - -TEST(CFDE_CSSValueListParser, multiparsing) { - FDE_CSSPrimitiveType type; - const FX_WCHAR* start; - int32_t len; - - auto parser = - pdfium::MakeUnique<CFDE_CSSValueListParser>(L"1, 2, 3", 7, L','); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"1", CFX_WideString(start, len)); - - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"2", CFX_WideString(start, len)); - - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"3", CFX_WideString(start, len)); - - EXPECT_FALSE(parser->NextValue(type, start, len)); - - parser = pdfium::MakeUnique<CFDE_CSSValueListParser>( - L"'str', rgb(1, 2, 3), 4", 22, L','); - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::String, type); - EXPECT_EQ(L"str", CFX_WideString(start, len)); - - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"rgb(1, 2, 3)", CFX_WideString(start, len)); - - EXPECT_TRUE(parser->NextValue(type, start, len)); - EXPECT_EQ(FDE_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"4", CFX_WideString(start, len)); -} diff --git a/xfa/fde/css/fde_css.h b/xfa/fde/css/fde_css.h deleted file mode 100644 index 6c2629f5ec32d6a71d9693e96b7a3fcad7cf1fed..0000000000000000000000000000000000000000 --- a/xfa/fde/css/fde_css.h +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_FDE_CSS_H_ -#define XFA_FDE_CSS_FDE_CSS_H_ - -#include "core/fxge/fx_dib.h" -#include "xfa/fgas/crt/fgas_stream.h" -#include "xfa/fgas/crt/fgas_utils.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" - -enum FDE_CSSVALUETYPE { - FDE_CSSVALUETYPE_Primitive = 1 << 0, - FDE_CSSVALUETYPE_List = 1 << 1, - FDE_CSSVALUETYPE_Shorthand = 1 << 2, - // Note the values below this comment must be > 0x0F so we can mask the above. - FDE_CSSVALUETYPE_MaybeNumber = 1 << 4, - FDE_CSSVALUETYPE_MaybeEnum = 1 << 5, - FDE_CSSVALUETYPE_MaybeString = 1 << 7, - FDE_CSSVALUETYPE_MaybeColor = 1 << 8 -}; - -enum class FDE_CSSPrimitiveType : uint8_t { - Unknown = 0, - Number, - String, - RGB, - Enum, - Function, - List, -}; - -enum class FDE_CSSPropertyValue : uint8_t { - Bolder = 0, - None, - Dot, - Sub, - Top, - Right, - Normal, - Auto, - Text, - XSmall, - Thin, - Small, - Bottom, - Underline, - Double, - Lighter, - Oblique, - Super, - Center, - XxLarge, - Smaller, - Baseline, - Thick, - Justify, - Middle, - Medium, - ListItem, - XxSmall, - Bold, - SmallCaps, - Inline, - Overline, - TextBottom, - Larger, - InlineTable, - InlineBlock, - Blink, - Block, - Italic, - LineThrough, - XLarge, - Large, - Left, - TextTop, - LAST_MARKER -}; - -enum class FDE_CSSProperty : uint8_t { - BorderLeft = 0, - Top, - Margin, - TextIndent, - Right, - PaddingLeft, - MarginLeft, - Border, - BorderTop, - Bottom, - PaddingRight, - BorderBottom, - FontFamily, - FontWeight, - Color, - LetterSpacing, - TextAlign, - BorderRightWidth, - VerticalAlign, - PaddingTop, - FontVariant, - BorderWidth, - BorderBottomWidth, - BorderRight, - FontSize, - BorderSpacing, - FontStyle, - Font, - LineHeight, - MarginRight, - BorderLeftWidth, - Display, - PaddingBottom, - BorderTopWidth, - WordSpacing, - Left, - TextDecoration, - Padding, - MarginBottom, - MarginTop, - LAST_MARKER -}; - -enum class FDE_CSSSelectorType : uint8_t { Element = 0, Descendant }; - -enum class FDE_CSSLengthUnit : uint8_t { - Auto, - None, - Normal, - Point, - Percent, -}; - -enum class FDE_CSSDisplay : uint8_t { - None, - ListItem, - Block, - Inline, - InlineBlock, - InlineTable, -}; - -enum class FDE_CSSFontStyle : uint8_t { - Normal, - Italic, -}; - -enum class FDE_CSSTextAlign : uint8_t { - Left, - Right, - Center, - Justify, - JustifyAll, -}; - -enum class FDE_CSSVerticalAlign : uint8_t { - Baseline, - Sub, - Super, - Top, - TextTop, - Middle, - Bottom, - TextBottom, - Number, -}; - -enum class FDE_CSSFontVariant : uint8_t { - Normal, - SmallCaps, -}; - -enum FDE_CSSTEXTDECORATION { - FDE_CSSTEXTDECORATION_None = 0, - FDE_CSSTEXTDECORATION_Underline = 1 << 0, - FDE_CSSTEXTDECORATION_Overline = 1 << 1, - FDE_CSSTEXTDECORATION_LineThrough = 1 << 2, - FDE_CSSTEXTDECORATION_Blink = 1 << 3, - FDE_CSSTEXTDECORATION_Double = 1 << 4, -}; - -class FDE_CSSLength { - public: - FDE_CSSLength() {} - - explicit FDE_CSSLength(FDE_CSSLengthUnit eUnit) : m_unit(eUnit) {} - - FDE_CSSLength(FDE_CSSLengthUnit eUnit, FX_FLOAT fValue) - : m_unit(eUnit), m_fValue(fValue) {} - - FDE_CSSLength& Set(FDE_CSSLengthUnit eUnit) { - m_unit = eUnit; - return *this; - } - - FDE_CSSLength& Set(FDE_CSSLengthUnit eUnit, FX_FLOAT fValue) { - m_unit = eUnit; - m_fValue = fValue; - return *this; - } - - FDE_CSSLengthUnit GetUnit() const { return m_unit; } - - FX_FLOAT GetValue() const { return m_fValue; } - bool NonZero() const { return static_cast<int>(m_fValue) != 0; } - - private: - FDE_CSSLengthUnit m_unit; - FX_FLOAT m_fValue; -}; - -class FDE_CSSRect { - public: - FDE_CSSRect() {} - - FDE_CSSRect(FDE_CSSLengthUnit eUnit, FX_FLOAT val) - : left(eUnit, val), - top(eUnit, val), - right(eUnit, val), - bottom(eUnit, val) {} - - FDE_CSSRect& Set(FDE_CSSLengthUnit eUnit) { - left.Set(eUnit); - top.Set(eUnit); - right.Set(eUnit); - bottom.Set(eUnit); - return *this; - } - FDE_CSSRect& Set(FDE_CSSLengthUnit eUnit, FX_FLOAT fValue) { - left.Set(eUnit, fValue); - top.Set(eUnit, fValue); - right.Set(eUnit, fValue); - bottom.Set(eUnit, fValue); - return *this; - } - - FDE_CSSLength left, top, right, bottom; -}; - -#endif // XFA_FDE_CSS_FDE_CSS_H_ diff --git a/xfa/fde/css/fde_cssdatatable.cpp b/xfa/fde/css/fde_cssdatatable.cpp deleted file mode 100644 index d61c610fe9bae8d3d992dc9af5e3b569688a515f..0000000000000000000000000000000000000000 --- a/xfa/fde/css/fde_cssdatatable.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/css/fde_cssdatatable.h" - -#include <utility> - -#include "core/fxcrt/fx_ext.h" -#include "xfa/fde/css/cfde_cssstyleselector.h" -#include "xfa/fde/css/cfde_cssvaluelistparser.h" -#include "xfa/fgas/crt/fgas_codepage.h" - -static const FDE_CSSPropertyTable g_FDE_CSSProperties[] = { - {FDE_CSSProperty::BorderLeft, L"border-left", 0x04080036, - FDE_CSSVALUETYPE_Shorthand}, - {FDE_CSSProperty::Top, L"top", 0x0BEDAF33, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::Margin, L"margin", 0x0CB016BE, - FDE_CSSVALUETYPE_List | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::TextIndent, L"text-indent", 0x169ADB74, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::Right, L"right", 0x193ADE3E, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::PaddingLeft, L"padding-left", 0x228CF02F, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::MarginLeft, L"margin-left", 0x297C5656, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber | - FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::Border, L"border", 0x2A23349E, - FDE_CSSVALUETYPE_Shorthand}, - {FDE_CSSProperty::BorderTop, L"border-top", 0x2B866ADE, - FDE_CSSVALUETYPE_Shorthand}, - {FDE_CSSProperty::Bottom, L"bottom", 0x399F02B5, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::PaddingRight, L"padding-right", 0x3F616AC2, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::BorderBottom, L"border-bottom", 0x452CE780, - FDE_CSSVALUETYPE_Shorthand}, - {FDE_CSSProperty::FontFamily, L"font-family", 0x574686E6, - FDE_CSSVALUETYPE_List | FDE_CSSVALUETYPE_MaybeString}, - {FDE_CSSProperty::FontWeight, L"font-weight", 0x6692F60C, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::Color, L"color", 0x6E67921F, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeColor}, - {FDE_CSSProperty::LetterSpacing, L"letter-spacing", 0x70536102, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::TextAlign, L"text-align", 0x7553F1BD, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::BorderRightWidth, L"border-right-width", 0x8F5A6036, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::VerticalAlign, L"vertical-align", 0x934A87D2, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::PaddingTop, L"padding-top", 0x959D22B7, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::FontVariant, L"font-variant", 0x9C785779, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::BorderWidth, L"border-width", 0xA8DE4FEB, - FDE_CSSVALUETYPE_List | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::BorderBottomWidth, L"border-bottom-width", 0xAE41204D, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::BorderRight, L"border-right", 0xB78E9EA9, - FDE_CSSVALUETYPE_Shorthand}, - {FDE_CSSProperty::FontSize, L"font-size", 0xB93956DF, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::BorderSpacing, L"border-spacing", 0xC72030F0, - FDE_CSSVALUETYPE_List | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::FontStyle, L"font-style", 0xCB1950F5, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::Font, L"font", 0xCD308B77, FDE_CSSVALUETYPE_Shorthand}, - {FDE_CSSProperty::LineHeight, L"line-height", 0xCFCACE2E, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::MarginRight, L"margin-right", 0xD13C58C9, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber | - FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::BorderLeftWidth, L"border-left-width", 0xD1E93D83, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::Display, L"display", 0xD4224C36, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::PaddingBottom, L"padding-bottom", 0xE555B3B9, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::BorderTopWidth, L"border-top-width", 0xED2CB62B, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::WordSpacing, L"word-spacing", 0xEDA63BAE, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::Left, L"left", 0xF5AD782B, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeEnum | - FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::TextDecoration, L"text-decoration", 0xF7C634BA, - FDE_CSSVALUETYPE_List | FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::Padding, L"padding", 0xF8C373F7, - FDE_CSSVALUETYPE_List | FDE_CSSVALUETYPE_MaybeNumber}, - {FDE_CSSProperty::MarginBottom, L"margin-bottom", 0xF93485A0, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber | - FDE_CSSVALUETYPE_MaybeEnum}, - {FDE_CSSProperty::MarginTop, L"margin-top", 0xFE51DCFE, - FDE_CSSVALUETYPE_Primitive | FDE_CSSVALUETYPE_MaybeNumber | - FDE_CSSVALUETYPE_MaybeEnum}, -}; -const int32_t g_iCSSPropertyCount = - sizeof(g_FDE_CSSProperties) / sizeof(FDE_CSSPropertyTable); -static_assert(g_iCSSPropertyCount == - static_cast<int32_t>(FDE_CSSProperty::LAST_MARKER), - "Property table differs in size from property enum"); - -static const FDE_CSSPropertyValueTable g_FDE_CSSPropertyValues[] = { - {FDE_CSSPropertyValue::Bolder, L"bolder", 0x009F1058}, - {FDE_CSSPropertyValue::None, L"none", 0x048B6670}, - {FDE_CSSPropertyValue::Dot, L"dot", 0x0A48CB27}, - {FDE_CSSPropertyValue::Sub, L"sub", 0x0BD37FAA}, - {FDE_CSSPropertyValue::Top, L"top", 0x0BEDAF33}, - {FDE_CSSPropertyValue::Right, L"right", 0x193ADE3E}, - {FDE_CSSPropertyValue::Normal, L"normal", 0x247CF3E9}, - {FDE_CSSPropertyValue::Auto, L"auto", 0x2B35B6D9}, - {FDE_CSSPropertyValue::Text, L"text", 0x2D08AF85}, - {FDE_CSSPropertyValue::XSmall, L"x-small", 0x2D2FCAFE}, - {FDE_CSSPropertyValue::Thin, L"thin", 0x2D574D53}, - {FDE_CSSPropertyValue::Small, L"small", 0x316A3739}, - {FDE_CSSPropertyValue::Bottom, L"bottom", 0x399F02B5}, - {FDE_CSSPropertyValue::Underline, L"underline", 0x3A0273A6}, - {FDE_CSSPropertyValue::Double, L"double", 0x3D98515B}, - {FDE_CSSPropertyValue::Lighter, L"lighter", 0x45BEB7AF}, - {FDE_CSSPropertyValue::Oblique, L"oblique", 0x53EBDDB1}, - {FDE_CSSPropertyValue::Super, L"super", 0x6A4F842F}, - {FDE_CSSPropertyValue::Center, L"center", 0x6C51AFC1}, - {FDE_CSSPropertyValue::XxLarge, L"xx-large", 0x70BB1508}, - {FDE_CSSPropertyValue::Smaller, L"smaller", 0x849769F0}, - {FDE_CSSPropertyValue::Baseline, L"baseline", 0x87436BA3}, - {FDE_CSSPropertyValue::Thick, L"thick", 0x8CC35EB3}, - {FDE_CSSPropertyValue::Justify, L"justify", 0x8D269CAE}, - {FDE_CSSPropertyValue::Middle, L"middle", 0x947FA00F}, - {FDE_CSSPropertyValue::Medium, L"medium", 0xA084A381}, - {FDE_CSSPropertyValue::ListItem, L"list-item", 0xA32382B8}, - {FDE_CSSPropertyValue::XxSmall, L"xx-small", 0xADE1FC76}, - {FDE_CSSPropertyValue::Bold, L"bold", 0xB18313A1}, - {FDE_CSSPropertyValue::SmallCaps, L"small-caps", 0xB299428D}, - {FDE_CSSPropertyValue::Inline, L"inline", 0xC02D649F}, - {FDE_CSSPropertyValue::Overline, L"overline", 0xC0EC9FA4}, - {FDE_CSSPropertyValue::TextBottom, L"text-bottom", 0xC7D08D87}, - {FDE_CSSPropertyValue::Larger, L"larger", 0xCD3C409D}, - {FDE_CSSPropertyValue::InlineTable, L"inline-table", 0xD131F494}, - {FDE_CSSPropertyValue::InlineBlock, L"inline-block", 0xD26A8BD7}, - {FDE_CSSPropertyValue::Blink, L"blink", 0xDC36E390}, - {FDE_CSSPropertyValue::Block, L"block", 0xDCD480AB}, - {FDE_CSSPropertyValue::Italic, L"italic", 0xE31D5396}, - {FDE_CSSPropertyValue::LineThrough, L"line-through", 0xE4C5A276}, - {FDE_CSSPropertyValue::XLarge, L"x-large", 0xF008E390}, - {FDE_CSSPropertyValue::Large, L"large", 0xF4434FCB}, - {FDE_CSSPropertyValue::Left, L"left", 0xF5AD782B}, - {FDE_CSSPropertyValue::TextTop, L"text-top", 0xFCB58D45}, -}; -const int32_t g_iCSSPropertyValueCount = - sizeof(g_FDE_CSSPropertyValues) / sizeof(FDE_CSSPropertyValueTable); -static_assert(g_iCSSPropertyValueCount == - static_cast<int32_t>(FDE_CSSPropertyValue::LAST_MARKER), - "Property value table differs in size from property value enum"); - -static const FDE_CSSLengthUnitTable g_FDE_CSSLengthUnits[] = { - {0x0672, FDE_CSSNumberType::EMS}, - {0x067D, FDE_CSSNumberType::EXS}, - {0x1AF7, FDE_CSSNumberType::Inches}, - {0x2F7A, FDE_CSSNumberType::MilliMeters}, - {0x3ED3, FDE_CSSNumberType::Picas}, - {0x3EE4, FDE_CSSNumberType::Points}, - {0x3EE8, FDE_CSSNumberType::Pixels}, - {0xFC30, FDE_CSSNumberType::CentiMeters}, -}; - -static const FDE_CSSCOLORTABLE g_FDE_CSSColors[] = { - {0x031B47FE, 0xff000080}, {0x0BB8DF5B, 0xffff0000}, - {0x0D82A78C, 0xff800000}, {0x2ACC82E8, 0xff00ffff}, - {0x2D083986, 0xff008080}, {0x4A6A6195, 0xffc0c0c0}, - {0x546A8EF3, 0xff808080}, {0x65C9169C, 0xffffa500}, - {0x8422BB61, 0xffffffff}, {0x9271A558, 0xff800080}, - {0xA65A3EE3, 0xffff00ff}, {0xB1345708, 0xff0000ff}, - {0xB6D2CF1F, 0xff808000}, {0xD19B5E1C, 0xffffff00}, - {0xDB64391D, 0xff000000}, {0xF616D507, 0xff00ff00}, - {0xF6EFFF31, 0xff008000}, -}; - -const FDE_CSSPropertyTable* FDE_GetCSSPropertyByName( - const CFX_WideStringC& wsName) { - ASSERT(!wsName.IsEmpty()); - uint32_t dwHash = FX_HashCode_GetW(wsName, true); - int32_t iEnd = g_iCSSPropertyCount; - int32_t iMid, iStart = 0; - uint32_t dwMid; - do { - iMid = (iStart + iEnd) / 2; - dwMid = g_FDE_CSSProperties[iMid].dwHash; - if (dwHash == dwMid) { - return g_FDE_CSSProperties + iMid; - } else if (dwHash > dwMid) { - iStart = iMid + 1; - } else { - iEnd = iMid - 1; - } - } while (iStart <= iEnd); - return nullptr; -} - -const FDE_CSSPropertyTable* FDE_GetCSSPropertyByEnum(FDE_CSSProperty eName) { - return g_FDE_CSSProperties + static_cast<int>(eName); -} - -const FDE_CSSPropertyValueTable* FDE_GetCSSPropertyValueByName( - const CFX_WideStringC& wsName) { - ASSERT(!wsName.IsEmpty()); - uint32_t dwHash = FX_HashCode_GetW(wsName, true); - int32_t iEnd = g_iCSSPropertyValueCount; - int32_t iMid, iStart = 0; - uint32_t dwMid; - do { - iMid = (iStart + iEnd) / 2; - dwMid = g_FDE_CSSPropertyValues[iMid].dwHash; - if (dwHash == dwMid) { - return g_FDE_CSSPropertyValues + iMid; - } else if (dwHash > dwMid) { - iStart = iMid + 1; - } else { - iEnd = iMid - 1; - } - } while (iStart <= iEnd); - return nullptr; -} - -const FDE_CSSLengthUnitTable* FDE_GetCSSLengthUnitByName( - const CFX_WideStringC& wsName) { - ASSERT(!wsName.IsEmpty()); - uint16_t wHash = FX_HashCode_GetW(wsName, true); - int32_t iEnd = - sizeof(g_FDE_CSSLengthUnits) / sizeof(FDE_CSSLengthUnitTable) - 1; - int32_t iMid, iStart = 0; - uint16_t wMid; - do { - iMid = (iStart + iEnd) / 2; - wMid = g_FDE_CSSLengthUnits[iMid].wHash; - if (wHash == wMid) { - return g_FDE_CSSLengthUnits + iMid; - } else if (wHash > wMid) { - iStart = iMid + 1; - } else { - iEnd = iMid - 1; - } - } while (iStart <= iEnd); - return nullptr; -} - -const FDE_CSSCOLORTABLE* FDE_GetCSSColorByName(const CFX_WideStringC& wsName) { - ASSERT(!wsName.IsEmpty()); - uint32_t dwHash = FX_HashCode_GetW(wsName, true); - int32_t iEnd = sizeof(g_FDE_CSSColors) / sizeof(FDE_CSSCOLORTABLE) - 1; - int32_t iMid, iStart = 0; - uint32_t dwMid; - do { - iMid = (iStart + iEnd) / 2; - dwMid = g_FDE_CSSColors[iMid].dwHash; - if (dwHash == dwMid) { - return g_FDE_CSSColors + iMid; - } else if (dwHash > dwMid) { - iStart = iMid + 1; - } else { - iEnd = iMid - 1; - } - } while (iStart <= iEnd); - return nullptr; -} diff --git a/xfa/fde/css/fde_cssdatatable.h b/xfa/fde/css/fde_cssdatatable.h deleted file mode 100644 index afb0b8502d7be17f5acf4a9aac61301a72784c9b..0000000000000000000000000000000000000000 --- a/xfa/fde/css/fde_cssdatatable.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_CSS_FDE_CSSDATATABLE_H_ -#define XFA_FDE_CSS_FDE_CSSDATATABLE_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/css/cfde_cssnumbervalue.h" -#include "xfa/fde/css/cfde_cssvalue.h" -#include "xfa/fde/css/fde_css.h" - -#define FDE_IsOnlyValue(type, enum) \ - (((type) & ~(enum)) == FDE_CSSVALUETYPE_Primitive) - -struct FDE_CSSPropertyTable { - FDE_CSSProperty eName; - const FX_WCHAR* pszName; - uint32_t dwHash; - uint32_t dwType; -}; - -struct FDE_CSSPropertyValueTable { - FDE_CSSPropertyValue eName; - const FX_WCHAR* pszName; - uint32_t dwHash; -}; - -struct FDE_CSSLengthUnitTable { - uint16_t wHash; - FDE_CSSNumberType wValue; -}; - -struct FDE_CSSCOLORTABLE { - uint32_t dwHash; - FX_ARGB dwValue; -}; - -const FDE_CSSPropertyTable* FDE_GetCSSPropertyByName( - const CFX_WideStringC& wsName); -const FDE_CSSPropertyTable* FDE_GetCSSPropertyByEnum(FDE_CSSProperty eName); - -const FDE_CSSPropertyValueTable* FDE_GetCSSPropertyValueByName( - const CFX_WideStringC& wsName); - -const FDE_CSSLengthUnitTable* FDE_GetCSSLengthUnitByName( - const CFX_WideStringC& wsName); - -const FDE_CSSCOLORTABLE* FDE_GetCSSColorByName(const CFX_WideStringC& wsName); - -#endif // XFA_FDE_CSS_FDE_CSSDATATABLE_H_ diff --git a/xfa/fde/fde_gedevice.cpp b/xfa/fde/fde_gedevice.cpp deleted file mode 100644 index db05f7624168cf86cd8c6807e3f2dd475c566f36..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_gedevice.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/fde_gedevice.h" - -#include <algorithm> -#include <memory> - -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/cfx_substfont.h" -#include "xfa/fde/cfde_path.h" -#include "xfa/fde/fde_object.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" -#include "xfa/fgas/font/cfgas_gefont.h" - -CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice, - bool bOwnerDevice) - : m_pDevice(pDevice), m_bOwnerDevice(bOwnerDevice), m_iCharCount(0) { - ASSERT(pDevice); - - FX_RECT rt = m_pDevice->GetClipBox(); - m_rtClip = CFX_RectF( - static_cast<FX_FLOAT>(rt.left), static_cast<FX_FLOAT>(rt.top), - static_cast<FX_FLOAT>(rt.Width()), static_cast<FX_FLOAT>(rt.Height())); -} - -CFDE_RenderDevice::~CFDE_RenderDevice() { - if (m_bOwnerDevice) - delete m_pDevice; -} - -int32_t CFDE_RenderDevice::GetWidth() const { - return m_pDevice->GetWidth(); -} - -int32_t CFDE_RenderDevice::GetHeight() const { - return m_pDevice->GetHeight(); -} - -void CFDE_RenderDevice::SaveState() { - m_pDevice->SaveState(); -} - -void CFDE_RenderDevice::RestoreState() { - m_pDevice->RestoreState(false); - const FX_RECT& rt = m_pDevice->GetClipBox(); - m_rtClip = CFX_RectF( - static_cast<FX_FLOAT>(rt.left), static_cast<FX_FLOAT>(rt.top), - static_cast<FX_FLOAT>(rt.Width()), static_cast<FX_FLOAT>(rt.Height())); -} - -bool CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) { - m_rtClip = rtClip; - return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left), - (int32_t)FXSYS_floor(rtClip.top), - (int32_t)FXSYS_ceil(rtClip.right()), - (int32_t)FXSYS_ceil(rtClip.bottom()))); -} - -const CFX_RectF& CFDE_RenderDevice::GetClipRect() { - return m_rtClip; -} - -bool CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) { - return false; -} - -CFDE_Path* CFDE_RenderDevice::GetClipPath() const { - return nullptr; -} - -FX_FLOAT CFDE_RenderDevice::GetDpiX() const { - return 96; -} - -FX_FLOAT CFDE_RenderDevice::GetDpiY() const { - return 96; -} - -bool CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib, - const CFX_RectF* pSrcRect, - const CFX_RectF& dstRect, - const CFX_Matrix* pImgMatrix, - const CFX_Matrix* pDevMatrix) { - CFX_RectF srcRect; - if (pSrcRect) { - srcRect = *pSrcRect; - } else { - srcRect = CFX_RectF(0, 0, static_cast<FX_FLOAT>(pDib->GetWidth()), - static_cast<FX_FLOAT>(pDib->GetHeight())); - } - - if (srcRect.IsEmpty()) - return false; - - CFX_Matrix dib2fxdev; - if (pImgMatrix) { - dib2fxdev = *pImgMatrix; - } else { - dib2fxdev.SetIdentity(); - } - dib2fxdev.a = dstRect.width; - dib2fxdev.d = -dstRect.height; - dib2fxdev.e = dstRect.left; - dib2fxdev.f = dstRect.bottom(); - if (pDevMatrix) { - dib2fxdev.Concat(*pDevMatrix); - } - void* handle = nullptr; - m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0, - handle); - while (m_pDevice->ContinueDIBits(handle, nullptr)) { - } - m_pDevice->CancelDIBits(handle); - return !!handle; -} - -bool CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush, - const CFX_RetainPtr<CFGAS_GEFont>& pFont, - const FXTEXT_CHARPOS* pCharPos, - int32_t iCount, - FX_FLOAT fFontSize, - const CFX_Matrix* pMatrix) { - ASSERT(pBrush && pFont && pCharPos && iCount > 0); - CFX_Font* pFxFont = pFont->GetDevFont(); - FX_ARGB argb = pBrush->GetColor(); - if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 && - !pFxFont->IsItalic()) { - FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos; - FX_FLOAT* pAM; - for (int32_t i = 0; i < iCount; ++i) { - static const FX_FLOAT mc = 0.267949f; - pAM = pCP->m_AdjustMatrix; - pAM[2] = mc * pAM[0] + pAM[2]; - pAM[3] = mc * pAM[1] + pAM[3]; - pCP++; - } - } - FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos; - CFX_RetainPtr<CFGAS_GEFont> pCurFont; - CFX_RetainPtr<CFGAS_GEFont> pSTFont; - FXTEXT_CHARPOS* pCurCP = nullptr; - int32_t iCurCount = 0; - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - uint32_t dwFontStyle = pFont->GetFontStyles(); - CFX_Font FxFont; - CFX_SubstFont* SubstFxFont = new CFX_SubstFont(); - FxFont.SetSubstFont(std::unique_ptr<CFX_SubstFont>(SubstFxFont)); - SubstFxFont->m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400; - SubstFxFont->m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0; - SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight; - SubstFxFont->m_bItalicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic); -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - - for (int32_t i = 0; i < iCount; ++i) { - pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex); - pCP->m_GlyphIndex &= 0x00FFFFFF; - pCP->m_bFontStyle = false; - if (pCurFont != pSTFont) { - if (pCurFont) { - pFxFont = pCurFont->GetDevFont(); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - FxFont.SetFace(pFxFont->GetFace()); - m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize, - pMatrix, argb, FXTEXT_CLEARTYPE); -#else - m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize, - pMatrix, argb, FXTEXT_CLEARTYPE); -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - } - pCurFont = pSTFont; - pCurCP = pCP; - iCurCount = 1; - } else { - iCurCount++; - } - pCP++; - } - if (pCurFont && iCurCount) { - pFxFont = pCurFont->GetDevFont(); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - FxFont.SetFace(pFxFont->GetFace()); - bool bRet = - m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize, - pMatrix, argb, FXTEXT_CLEARTYPE); - FxFont.SetFace(nullptr); - return bRet; -#else - return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize, - pMatrix, argb, FXTEXT_CLEARTYPE); -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - } - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - FxFont.SetFace(nullptr); -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - - return true; -} - -bool CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_PointF& pt1, - const CFX_PointF& pt2, - const CFX_PointF& pt3, - const CFX_PointF& pt4, - const CFX_Matrix* pMatrix) { - std::vector<CFX_PointF> points; - points.push_back(pt1); - points.push_back(pt2); - points.push_back(pt3); - points.push_back(pt4); - CFDE_Path path; - path.AddBezier(points); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const std::vector<CFX_PointF>& points, - bool bClosed, - FX_FLOAT fTension, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddCurve(points, bClosed, fTension); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddEllipse(rect); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const std::vector<CFX_PointF>& points, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddLines(points); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_PointF& pt1, - const CFX_PointF& pt2, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddLine(pt1, pt2); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFDE_Path* pPath, - const CFX_Matrix* pMatrix) { - CFDE_Path* pGePath = (CFDE_Path*)pPath; - if (!pGePath) - return false; - - CFX_GraphStateData graphState; - if (!CreatePen(pPen, fPenWidth, graphState)) { - return false; - } - return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix, - &graphState, 0, pPen->GetColor(), 0); -} - -bool CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const std::vector<CFX_PointF>& points, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddPolygon(points); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddRectangle(rect); - return DrawPath(pPen, fPenWidth, &path, pMatrix); -} - -bool CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush, - const std::vector<CFX_PointF>& points, - FX_FLOAT fTension, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddCurve(points, true, fTension); - return FillPath(pBrush, &path, pMatrix); -} - -bool CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddEllipse(rect); - return FillPath(pBrush, &path, pMatrix); -} - -bool CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush, - const std::vector<CFX_PointF>& points, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddPolygon(points); - return FillPath(pBrush, &path, pMatrix); -} - -bool CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix) { - CFDE_Path path; - path.AddRectangle(rect); - return FillPath(pBrush, &path, pMatrix); -} - -bool CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - CFX_GraphStateData& graphState) { - if (!pPen) - return false; - - graphState.m_LineCap = CFX_GraphStateData::LineCapButt; - graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter; - graphState.m_LineWidth = fPenWidth; - graphState.m_MiterLimit = 10; - graphState.m_DashPhase = 0; - return true; -} - -bool CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush, - const CFDE_Path* pPath, - const CFX_Matrix* pMatrix) { - CFDE_Path* pGePath = (CFDE_Path*)pPath; - if (!pGePath) - return false; - if (!pBrush) - return false; - return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr, - pBrush->GetColor(), 0, FXFILL_WINDING); -} - diff --git a/xfa/fde/fde_gedevice.h b/xfa/fde/fde_gedevice.h deleted file mode 100644 index 7c772cfd0385512205b9923dd6b03dfc0335e9af..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_gedevice.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_FDE_GEDEVICE_H_ -#define XFA_FDE_FDE_GEDEVICE_H_ - -#include <vector> - -#include "core/fxge/cfx_renderdevice.h" -#include "xfa/fgas/font/cfgas_gefont.h" - -class CFDE_Brush; -class CFDE_Path; -class CFDE_Pen; -class CFX_GraphStateData; - -class CFDE_RenderDevice { - public: - CFDE_RenderDevice(CFX_RenderDevice* pDevice, bool bOwnerDevice); - ~CFDE_RenderDevice(); - - int32_t GetWidth() const; - int32_t GetHeight() const; - void SaveState(); - void RestoreState(); - bool SetClipPath(const CFDE_Path* pClip); - CFDE_Path* GetClipPath() const; - bool SetClipRect(const CFX_RectF& rtClip); - const CFX_RectF& GetClipRect(); - - FX_FLOAT GetDpiX() const; - FX_FLOAT GetDpiY() const; - - bool DrawImage(CFX_DIBSource* pDib, - const CFX_RectF* pSrcRect, - const CFX_RectF& dstRect, - const CFX_Matrix* pImgMatrix = nullptr, - const CFX_Matrix* pDevMatrix = nullptr); - bool DrawString(CFDE_Brush* pBrush, - const CFX_RetainPtr<CFGAS_GEFont>& pFont, - const FXTEXT_CHARPOS* pCharPos, - int32_t iCount, - FX_FLOAT fFontSize, - const CFX_Matrix* pMatrix = nullptr); - bool DrawBezier(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_PointF& pt1, - const CFX_PointF& pt2, - const CFX_PointF& pt3, - const CFX_PointF& pt4, - const CFX_Matrix* pMatrix = nullptr); - bool DrawCurve(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const std::vector<CFX_PointF>& points, - bool bClosed, - FX_FLOAT fTension = 0.5f, - const CFX_Matrix* pMatrix = nullptr); - bool DrawEllipse(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix = nullptr); - bool DrawLines(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const std::vector<CFX_PointF>& points, - const CFX_Matrix* pMatrix = nullptr); - bool DrawLine(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_PointF& pt1, - const CFX_PointF& pt2, - const CFX_Matrix* pMatrix = nullptr); - bool DrawPath(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFDE_Path* pPath, - const CFX_Matrix* pMatrix = nullptr); - bool DrawPolygon(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const std::vector<CFX_PointF>& points, - const CFX_Matrix* pMatrix = nullptr); - bool DrawRectangle(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix = nullptr); - bool FillClosedCurve(CFDE_Brush* pBrush, - const std::vector<CFX_PointF>& points, - FX_FLOAT fTension = 0.5f, - const CFX_Matrix* pMatrix = nullptr); - bool FillEllipse(CFDE_Brush* pBrush, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix = nullptr); - bool FillPath(CFDE_Brush* pBrush, - const CFDE_Path* pPath, - const CFX_Matrix* pMatrix = nullptr); - bool FillPolygon(CFDE_Brush* pBrush, - const std::vector<CFX_PointF>& points, - const CFX_Matrix* pMatrix = nullptr); - bool FillRectangle(CFDE_Brush* pBrush, - const CFX_RectF& rect, - const CFX_Matrix* pMatrix = nullptr); - - bool DrawSolidString(CFDE_Brush* pBrush, - const CFX_RetainPtr<CFGAS_GEFont>& pFont, - const FXTEXT_CHARPOS* pCharPos, - int32_t iCount, - FX_FLOAT fFontSize, - const CFX_Matrix* pMatrix); - bool DrawStringPath(CFDE_Brush* pBrush, - const CFX_RetainPtr<CFGAS_GEFont>& pFont, - const FXTEXT_CHARPOS* pCharPos, - int32_t iCount, - FX_FLOAT fFontSize, - const CFX_Matrix* pMatrix); - - protected: - bool CreatePen(CFDE_Pen* pPen, - FX_FLOAT fPenWidth, - CFX_GraphStateData& graphState); - - CFX_RenderDevice* const m_pDevice; - CFX_RectF m_rtClip; - bool m_bOwnerDevice; - int32_t m_iCharCount; -}; - -#endif // XFA_FDE_FDE_GEDEVICE_H_ diff --git a/xfa/fde/fde_iterator.cpp b/xfa/fde/fde_iterator.cpp deleted file mode 100644 index 9ca02da6a0babcfe2845134f5d5c1e7919f6373f..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_iterator.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/fde_iterator.h" - -#include "xfa/fgas/crt/fgas_utils.h" - -CFDE_VisualSetIterator::CFDE_VisualSetIterator() - : m_dwFilter(0), m_CanvasStack(100) {} - -CFDE_VisualSetIterator::~CFDE_VisualSetIterator() { - m_CanvasStack.RemoveAll(false); -} - -bool CFDE_VisualSetIterator::AttachCanvas(IFDE_CanvasSet* pCanvas) { - ASSERT(pCanvas); - - m_CanvasStack.RemoveAll(false); - FDE_CANVASITEM canvas; - canvas.hCanvas = nullptr; - canvas.pCanvas = pCanvas; - canvas.hPos = pCanvas->GetFirstPosition(); - if (!canvas.hPos) - return false; - - return m_CanvasStack.Push(canvas) == 0; -} - -bool CFDE_VisualSetIterator::FilterObjects(uint32_t dwObjects) { - if (m_CanvasStack.GetSize() == 0) - return false; - - while (m_CanvasStack.GetSize() > 1) - m_CanvasStack.Pop(); - - m_dwFilter = dwObjects; - - FDE_CANVASITEM* pCanvas = m_CanvasStack.GetTopElement(); - ASSERT(pCanvas && pCanvas->pCanvas); - - pCanvas->hPos = pCanvas->pCanvas->GetFirstPosition(); - return !!pCanvas->hPos; -} - -void CFDE_VisualSetIterator::Reset() { - FilterObjects(m_dwFilter); -} - -FDE_TEXTEDITPIECE* CFDE_VisualSetIterator::GetNext( - IFDE_VisualSet*& pVisualSet, - FDE_TEXTEDITPIECE** phCanvasObj, - IFDE_CanvasSet** ppCanvasSet) { - while (m_CanvasStack.GetSize() > 0) { - FDE_CANVASITEM* pCanvas = m_CanvasStack.GetTopElement(); - ASSERT(pCanvas && pCanvas->pCanvas); - - if (!pCanvas->hPos) { - if (m_CanvasStack.GetSize() == 1) - break; - - m_CanvasStack.Pop(); - continue; - } - do { - FDE_TEXTEDITPIECE* pObj = - pCanvas->pCanvas->GetNext(pCanvas->hPos, pVisualSet); - ASSERT(pObj); - - FDE_VISUALOBJTYPE eType = pVisualSet->GetType(); - if (eType == FDE_VISUALOBJ_Canvas) { - FDE_CANVASITEM canvas; - canvas.hCanvas = pObj; - canvas.pCanvas = static_cast<IFDE_CanvasSet*>(pVisualSet); - canvas.hPos = canvas.pCanvas->GetFirstPosition(); - m_CanvasStack.Push(canvas); - break; - } - uint32_t dwObj = (uint32_t)eType; - if ((m_dwFilter & dwObj) != 0) { - if (ppCanvasSet) - *ppCanvasSet = pCanvas->pCanvas; - if (phCanvasObj) - *phCanvasObj = pCanvas->hCanvas; - return pObj; - } - } while (pCanvas->hPos); - } - if (ppCanvasSet) - *ppCanvasSet = nullptr; - if (phCanvasObj) - *phCanvasObj = nullptr; - - pVisualSet = nullptr; - return nullptr; -} diff --git a/xfa/fde/fde_iterator.h b/xfa/fde/fde_iterator.h deleted file mode 100644 index 45659ce87cf6d702b845319c6c80244def87855c..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_iterator.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_FDE_ITERATOR_H_ -#define XFA_FDE_FDE_ITERATOR_H_ - -#include "xfa/fde/fde_visualset.h" -#include "xfa/fgas/crt/fgas_utils.h" - -struct FDE_CANVASITEM { - IFDE_CanvasSet* pCanvas; - FDE_TEXTEDITPIECE* hCanvas; - FX_POSITION hPos; -}; - -class CFDE_VisualSetIterator { - public: - CFDE_VisualSetIterator(); - ~CFDE_VisualSetIterator(); - - bool AttachCanvas(IFDE_CanvasSet* pCanvas); - bool FilterObjects(uint32_t dwObjects = 0xFFFFFFFF); - - void Reset(); - FDE_TEXTEDITPIECE* GetNext(IFDE_VisualSet*& pVisualSet, - FDE_TEXTEDITPIECE** phCanvasObj = nullptr, - IFDE_CanvasSet** ppCanvasSet = nullptr); - - protected: - uint32_t m_dwFilter; - CFX_StackTemplate<FDE_CANVASITEM> m_CanvasStack; -}; - -#endif // XFA_FDE_FDE_ITERATOR_H_ diff --git a/xfa/fde/fde_object.h b/xfa/fde/fde_object.h deleted file mode 100644 index 5c66b202b66d1907a57eb47e410ec80c7b26a579..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_object.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_FDE_OBJECT_H_ -#define XFA_FDE_FDE_OBJECT_H_ - -#include <cstdint> - -#include "core/fxge/fx_dib.h" - -class CFDE_Brush { - public: - CFDE_Brush() : m_Color(0xFF000000) {} - - FX_ARGB GetColor() const { return m_Color; } - void SetColor(FX_ARGB color) { m_Color = color; } - - private: - FX_ARGB m_Color; -}; - -class CFDE_Pen { - public: - CFDE_Pen() : m_Color(0) {} - ~CFDE_Pen() {} - - FX_ARGB GetColor() const { return m_Color; } - void SetColor(FX_ARGB color) { m_Color = color; } - - private: - FX_ARGB m_Color; -}; - -#endif // XFA_FDE_FDE_OBJECT_H_ diff --git a/xfa/fde/fde_render.cpp b/xfa/fde/fde_render.cpp deleted file mode 100644 index b6a8f7edd0e32e14fd9545fcaeeb2b05799e7c39..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_render.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/fde_render.h" - -#include "third_party/base/ptr_util.h" -#include "xfa/fde/fde_gedevice.h" -#include "xfa/fde/fde_object.h" - -#define FDE_PATHRENDER_Stroke 1 -#define FDE_PATHRENDER_Fill 2 - -CFDE_RenderContext::CFDE_RenderContext() - : m_eStatus(FDE_RENDERSTATUS_Reset), - m_pRenderDevice(nullptr), - m_Transform() { - m_Transform.SetIdentity(); -} - -CFDE_RenderContext::~CFDE_RenderContext() { - StopRender(); -} - -bool CFDE_RenderContext::StartRender(CFDE_RenderDevice* pRenderDevice, - IFDE_CanvasSet* pCanvasSet, - const CFX_Matrix& tmDoc2Device) { - if (m_pRenderDevice) - return false; - if (!pRenderDevice) - return false; - if (!pCanvasSet) - return false; - - m_eStatus = FDE_RENDERSTATUS_Paused; - m_pRenderDevice = pRenderDevice; - m_Transform = tmDoc2Device; - if (!m_pIterator) - m_pIterator = pdfium::MakeUnique<CFDE_VisualSetIterator>(); - - return m_pIterator->AttachCanvas(pCanvasSet) && m_pIterator->FilterObjects(); -} - -FDE_RENDERSTATUS CFDE_RenderContext::DoRender(IFX_Pause* pPause) { - if (!m_pRenderDevice) - return FDE_RENDERSTATUS_Failed; - if (!m_pIterator) - return FDE_RENDERSTATUS_Failed; - - FDE_RENDERSTATUS eStatus = FDE_RENDERSTATUS_Paused; - CFX_Matrix rm; - rm.SetReverse(m_Transform); - CFX_RectF rtDocClip = m_pRenderDevice->GetClipRect(); - if (rtDocClip.IsEmpty()) { - rtDocClip.left = rtDocClip.top = 0; - rtDocClip.width = (FX_FLOAT)m_pRenderDevice->GetWidth(); - rtDocClip.height = (FX_FLOAT)m_pRenderDevice->GetHeight(); - } - rm.TransformRect(rtDocClip); - IFDE_VisualSet* pVisualSet; - FDE_TEXTEDITPIECE* pPiece; - int32_t iCount = 0; - while (true) { - pPiece = m_pIterator->GetNext(pVisualSet); - if (!pPiece || !pVisualSet) { - eStatus = FDE_RENDERSTATUS_Done; - break; - } - if (!rtDocClip.IntersectWith(pVisualSet->GetRect(*pPiece))) - continue; - - switch (pVisualSet->GetType()) { - case FDE_VISUALOBJ_Text: - RenderText(static_cast<IFDE_TextSet*>(pVisualSet), pPiece); - iCount += 5; - break; - case FDE_VISUALOBJ_Canvas: - ASSERT(false); - break; - default: - break; - } - if (iCount >= 100 && pPause && pPause->NeedToPauseNow()) { - eStatus = FDE_RENDERSTATUS_Paused; - break; - } - } - return m_eStatus = eStatus; -} - -void CFDE_RenderContext::StopRender() { - m_eStatus = FDE_RENDERSTATUS_Reset; - m_pRenderDevice = nullptr; - m_Transform.SetIdentity(); - m_pIterator.reset(); - m_pBrush.reset(); - m_CharPos.clear(); -} - -void CFDE_RenderContext::RenderText(IFDE_TextSet* pTextSet, - FDE_TEXTEDITPIECE* pText) { - ASSERT(m_pRenderDevice); - ASSERT(pTextSet && pText); - - CFX_RetainPtr<CFGAS_GEFont> pFont = pTextSet->GetFont(); - if (!pFont) - return; - - int32_t iCount = pTextSet->GetDisplayPos(*pText, nullptr, false); - if (iCount < 1) - return; - - if (!m_pBrush) - m_pBrush = pdfium::MakeUnique<CFDE_Brush>(); - - if (m_CharPos.size() < static_cast<size_t>(iCount)) - m_CharPos.resize(iCount, FXTEXT_CHARPOS()); - - iCount = pTextSet->GetDisplayPos(*pText, m_CharPos.data(), false); - FX_FLOAT fFontSize = pTextSet->GetFontSize(); - FX_ARGB dwColor = pTextSet->GetFontColor(); - m_pBrush->SetColor(dwColor); - m_pRenderDevice->DrawString(m_pBrush.get(), pFont, m_CharPos.data(), iCount, - fFontSize, &m_Transform); -} - diff --git a/xfa/fde/fde_render.h b/xfa/fde/fde_render.h deleted file mode 100644 index a24d6b54964e77cd56ab9116cb2b1ced0c070ab3..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_render.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_FDE_RENDER_H_ -#define XFA_FDE_FDE_RENDER_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_coordinates.h" -#include "xfa/fde/fde_gedevice.h" -#include "xfa/fde/fde_iterator.h" -#include "xfa/fde/fde_visualset.h" - -class CFDE_RenderDevice; - -enum FDE_RENDERSTATUS { - FDE_RENDERSTATUS_Reset = 0, - FDE_RENDERSTATUS_Paused, - FDE_RENDERSTATUS_Done, - FDE_RENDERSTATUS_Failed, -}; - -class CFDE_RenderContext { - public: - CFDE_RenderContext(); - ~CFDE_RenderContext(); - - bool StartRender(CFDE_RenderDevice* pRenderDevice, - IFDE_CanvasSet* pCanvasSet, - const CFX_Matrix& tmDoc2Device); - FDE_RENDERSTATUS GetStatus() const { return m_eStatus; } - FDE_RENDERSTATUS DoRender(IFX_Pause* pPause = nullptr); - void StopRender(); - void RenderText(IFDE_TextSet* pTextSet, FDE_TEXTEDITPIECE* pText); - - protected: - FDE_RENDERSTATUS m_eStatus; - CFDE_RenderDevice* m_pRenderDevice; - CFX_Matrix m_Transform; - std::vector<FXTEXT_CHARPOS> m_CharPos; - std::unique_ptr<CFDE_Brush> m_pBrush; - std::unique_ptr<CFDE_VisualSetIterator> m_pIterator; -}; - -#endif // XFA_FDE_FDE_RENDER_H_ diff --git a/xfa/fde/fde_visualset.h b/xfa/fde/fde_visualset.h deleted file mode 100644 index 5cf02cde9cac3a0d108eba099da352f6c8069fab..0000000000000000000000000000000000000000 --- a/xfa/fde/fde_visualset.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_FDE_VISUALSET_H_ -#define XFA_FDE_FDE_VISUALSET_H_ - -#include <vector> - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fde/cfde_path.h" -#include "xfa/fde/fde_object.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" - -class FXTEXT_CHARPOS; - -enum FDE_VISUALOBJTYPE { - FDE_VISUALOBJ_Canvas = 0x00, - FDE_VISUALOBJ_Text = 0x01 -}; - -struct FDE_TEXTEDITPIECE { - FDE_TEXTEDITPIECE(); - FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that); - ~FDE_TEXTEDITPIECE(); - - int32_t nStart; - int32_t nCount; - int32_t nBidiLevel; - CFX_RectF rtPiece; - uint32_t dwCharStyles; -}; -inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE() = default; -inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that) = - default; -inline FDE_TEXTEDITPIECE::~FDE_TEXTEDITPIECE() = default; - -class IFDE_VisualSet { - public: - virtual ~IFDE_VisualSet() {} - virtual FDE_VISUALOBJTYPE GetType() = 0; - virtual CFX_RectF GetRect(const FDE_TEXTEDITPIECE& hVisualObj) = 0; -}; - -class IFDE_CanvasSet : public IFDE_VisualSet { - public: - virtual FX_POSITION GetFirstPosition() = 0; - virtual FDE_TEXTEDITPIECE* GetNext(FX_POSITION& pos, - IFDE_VisualSet*& pVisualSet) = 0; -}; - -class IFDE_TextSet : public IFDE_VisualSet { - public: - virtual int32_t GetString(FDE_TEXTEDITPIECE* hText, - CFX_WideString& wsText) = 0; - virtual CFX_RetainPtr<CFGAS_GEFont> GetFont() = 0; - virtual FX_FLOAT GetFontSize() = 0; - virtual FX_ARGB GetFontColor() = 0; - virtual int32_t GetDisplayPos(const FDE_TEXTEDITPIECE& hText, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode = false, - CFX_WideString* pWSForms = nullptr) = 0; - virtual std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE* hText, - bool bbox) = 0; -}; - -#endif // XFA_FDE_FDE_VISUALSET_H_ diff --git a/xfa/fde/ifde_txtedtdorecord.h b/xfa/fde/ifde_txtedtdorecord.h deleted file mode 100644 index b6a4100d9944a0a1c6965bebecd3bf008bb89639..0000000000000000000000000000000000000000 --- a/xfa/fde/ifde_txtedtdorecord.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_IFDE_TXTEDTDORECORD_H_ -#define XFA_FDE_IFDE_TXTEDTDORECORD_H_ - -#include "core/fxcrt/fx_system.h" - -class IFDE_TxtEdtDoRecord { - public: - virtual ~IFDE_TxtEdtDoRecord() {} - - virtual bool Redo() const = 0; - virtual bool Undo() const = 0; -}; - -#endif // XFA_FDE_IFDE_TXTEDTDORECORD_H_ diff --git a/xfa/fde/ifde_txtedtengine.h b/xfa/fde/ifde_txtedtengine.h deleted file mode 100644 index 6940a8c7d684a10fa9810530dde9e712d05fe66c..0000000000000000000000000000000000000000 --- a/xfa/fde/ifde_txtedtengine.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_IFDE_TXTEDTENGINE_H_ -#define XFA_FDE_IFDE_TXTEDTENGINE_H_ - -#include "core/fxge/fx_dib.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" - -class CFDE_TxtEdtEngine; -class IFDE_TxtEdtPage; -class CFWL_Edit; - -#define FDE_TEXTEDITMODE_MultiLines (1L << 0) -#define FDE_TEXTEDITMODE_AutoLineWrap (1L << 1) -#define FDE_TEXTEDITMODE_ReadOnly (1L << 2) -#define FDE_TEXTEDITMODE_LimitArea_Vert (1L << 3) -#define FDE_TEXTEDITMODE_LimitArea_Horz (1L << 4) -#define FDE_TEXTEDITMODE_Validate (1L << 8) -#define FDE_TEXTEDITMODE_Password (1L << 9) - -#define FDE_TEXTEDITALIGN_Left 0 -#define FDE_TEXTEDITALIGN_Center (1L << 0) -#define FDE_TEXTEDITALIGN_Right (2L << 0) -#define FDE_TEXTEDITALIGN_Normal (1L << 3) -#define FDE_TEXTEDITALIGN_Justified (1L << 4) - -#define FDE_TEXTEDITLAYOUT_CombText (1L << 4) -#define FDE_TEXTEDITLAYOUT_LastLineHeight (1L << 8) - -enum FDE_TXTEDTMOVECARET { - MC_MoveNone = 0, - MC_Left, - MC_Right, - MC_Up, - MC_Down, - MC_WordBackward, - MC_WordForward, - MC_LineStart, - MC_LineEnd, - MC_ParagStart, - MC_ParagEnd, - MC_PageUp, - MC_PageDown, - MC_Home, - MC_End, -}; - -enum FDE_TXTEDT_MODIFY_RET { - FDE_TXTEDT_MODIFY_RET_F_Tab = -6, - FDE_TXTEDT_MODIFY_RET_F_Locked = -5, - FDE_TXTEDT_MODIFY_RET_F_Invalidate = -4, - FDE_TXTEDT_MODIFY_RET_F_Boundary = -3, - FDE_TXTEDT_MODIFY_RET_F_Full = -2, - FDE_TXTEDT_MODIFY_RET_F_Normal = -1, - FDE_TXTEDT_MODIFY_RET_S_Normal = 0, - FDE_TXTEDT_MODIFY_RET_S_Full = 1, - FDE_TXTEDT_MODIFY_RET_S_Part = 2, - FDE_TXTEDT_MODIFY_RET_S_Empty = 3, - FDE_TXTEDT_MODIFY_RET_T_Tab = 4, -}; - -enum FDE_TXTEDIT_LINEEND { - FDE_TXTEDIT_LINEEND_Auto, - FDE_TXTEDIT_LINEEND_CRLF, - FDE_TXTEDIT_LINEEND_CR, - FDE_TXTEDIT_LINEEND_LF, -}; - -struct FDE_TXTEDTPARAMS { - FDE_TXTEDTPARAMS(); - ~FDE_TXTEDTPARAMS(); - - FX_FLOAT fPlateWidth; - FX_FLOAT fPlateHeight; - int32_t nLineCount; - uint32_t dwLayoutStyles; - uint32_t dwAlignment; - uint32_t dwMode; - CFX_RetainPtr<CFGAS_GEFont> pFont; - FX_FLOAT fFontSize; - FX_ARGB dwFontColor; - FX_FLOAT fLineSpace; - FX_FLOAT fTabWidth; - bool bTabEquidistant; - FX_WCHAR wDefChar; - FX_WCHAR wLineBreakChar; - int32_t nCharRotation; - int32_t nLineEnd; - int32_t nHorzScale; - FX_FLOAT fCharSpace; - CFWL_Edit* pEventSink; -}; - -enum FDE_TXTEDT_TEXTCHANGE_TYPE { - FDE_TXTEDT_TEXTCHANGE_TYPE_Insert = 0, - FDE_TXTEDT_TEXTCHANGE_TYPE_Delete, - FDE_TXTEDT_TEXTCHANGE_TYPE_Replace, -}; - -struct FDE_TXTEDT_TEXTCHANGE_INFO { - FDE_TXTEDT_TEXTCHANGE_INFO(); - ~FDE_TXTEDT_TEXTCHANGE_INFO(); - - int32_t nChangeType; - CFX_WideString wsInsert; - CFX_WideString wsDelete; - CFX_WideString wsPrevText; -}; - -#endif // XFA_FDE_IFDE_TXTEDTENGINE_H_ diff --git a/xfa/fde/ifde_txtedtpage.h b/xfa/fde/ifde_txtedtpage.h deleted file mode 100644 index 0ab3897b3cf5f11bb3f3ea02186ec7e0355c6ce0..0000000000000000000000000000000000000000 --- a/xfa/fde/ifde_txtedtpage.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_IFDE_TXTEDTPAGE_H_ -#define XFA_FDE_IFDE_TXTEDTPAGE_H_ - -#include <vector> - -#include "xfa/fde/fde_visualset.h" -#include "xfa/fgas/layout/fgas_textbreak.h" - -class CFDE_TxtEdtEngine; - -class IFDE_TxtEdtPage : public IFDE_CanvasSet, public IFX_TxtAccess { - public: - static IFDE_TxtEdtPage* Create(CFDE_TxtEdtEngine* pEngine, int32_t nIndex); - ~IFDE_TxtEdtPage() override {} - - virtual CFDE_TxtEdtEngine* GetEngine() const = 0; - virtual int32_t GetCharRect(int32_t nIndex, - CFX_RectF& rect, - bool bBBox = false) const = 0; - virtual int32_t GetCharIndex(const CFX_PointF& fPoint, bool& bBefore) = 0; - virtual void CalcRangeRectArray(int32_t nStart, - int32_t nCount, - std::vector<CFX_RectF>* RectFArr) const = 0; - virtual int32_t SelectWord(const CFX_PointF& fPoint, int32_t& nCount) = 0; - virtual int32_t GetCharStart() const = 0; - virtual int32_t GetCharCount() const = 0; - - virtual int32_t GetDisplayPos(const CFX_RectF& rtClip, - FXTEXT_CHARPOS*& pCharPos, - CFX_RectF* pBBox) const = 0; - virtual bool IsLoaded(const CFX_RectF* pClipBox) = 0; - virtual int32_t LoadPage(const CFX_RectF* pClipBox, IFX_Pause* pPause) = 0; - virtual void UnloadPage(const CFX_RectF* pClipBox) = 0; - virtual const CFX_RectF& GetContentsBox() = 0; -}; - -#endif // XFA_FDE_IFDE_TXTEDTPAGE_H_ diff --git a/xfa/fde/ifx_chariter.h b/xfa/fde/ifx_chariter.h deleted file mode 100644 index c967efd4d60a154e36e03e4eaebd90c1c8f8a507..0000000000000000000000000000000000000000 --- a/xfa/fde/ifx_chariter.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_IFX_CHARITER_H_ -#define XFA_FDE_IFX_CHARITER_H_ - -#include "core/fxcrt/fx_system.h" - -class IFX_CharIter { - public: - virtual ~IFX_CharIter() {} - - virtual bool Next(bool bPrev = false) = 0; - virtual FX_WCHAR GetChar() = 0; - virtual void SetAt(int32_t nIndex) = 0; - virtual int32_t GetAt() const = 0; - virtual bool IsEOF(bool bTail = true) const = 0; - virtual IFX_CharIter* Clone() = 0; -}; - -#endif // XFA_FDE_IFX_CHARITER_H_ diff --git a/xfa/fde/tto/fde_textout.cpp b/xfa/fde/tto/fde_textout.cpp deleted file mode 100644 index 421876b48d41714bdb710cc0eea85fea1ae0f307..0000000000000000000000000000000000000000 --- a/xfa/fde/tto/fde_textout.cpp +++ /dev/null @@ -1,876 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/tto/fde_textout.h" - -#include <algorithm> - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/cfde_path.h" -#include "xfa/fde/fde_gedevice.h" -#include "xfa/fde/fde_object.h" -#include "xfa/fgas/crt/fgas_utils.h" -#include "xfa/fgas/layout/fgas_textbreak.h" - -FDE_TTOPIECE::FDE_TTOPIECE() = default; -FDE_TTOPIECE::FDE_TTOPIECE(const FDE_TTOPIECE& that) = default; -FDE_TTOPIECE::~FDE_TTOPIECE() = default; - -CFDE_TextOut::CFDE_TextOut() - : m_pTxtBreak(new CFX_TxtBreak(FX_TXTBREAKPOLICY_None)), - m_pFont(nullptr), - m_fFontSize(12.0f), - m_fLineSpace(m_fFontSize), - m_fLinePos(0.0f), - m_fTolerance(0.0f), - m_iAlignment(0), - m_iTxtBkAlignment(0), - m_wParagraphBkChar(L'\n'), - m_TxtColor(0xFF000000), - m_dwStyles(0), - m_dwTxtBkStyles(0), - m_bElliChanged(false), - m_iEllipsisWidth(0), - m_ttoLines(5), - m_iCurLine(0), - m_iCurPiece(0), - m_iTotalLines(0) { - m_Matrix.SetIdentity(); - m_rtClip.Reset(); - m_rtLogicClip.Reset(); -} - -CFDE_TextOut::~CFDE_TextOut() {} - -void CFDE_TextOut::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) { - ASSERT(pFont); - m_pFont = pFont; - m_pTxtBreak->SetFont(pFont); -} - -void CFDE_TextOut::SetFontSize(FX_FLOAT fFontSize) { - ASSERT(fFontSize > 0); - m_fFontSize = fFontSize; - m_pTxtBreak->SetFontSize(fFontSize); -} - -void CFDE_TextOut::SetTextColor(FX_ARGB color) { - m_TxtColor = color; -} - -void CFDE_TextOut::SetStyles(uint32_t dwStyles) { - m_dwStyles = dwStyles; - m_dwTxtBkStyles = 0; - if (dwStyles & FDE_TTOSTYLE_SingleLine) { - m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_SingleLine; - } - if (dwStyles & FDE_TTOSTYLE_ExpandTab) { - m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_ExpandTab; - } - if (dwStyles & FDE_TTOSTYLE_ArabicShapes) { - m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_ArabicShapes; - } - if (dwStyles & FDE_TTOSTYLE_ArabicContext) { - m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_ArabicContext; - } - if (dwStyles & FDE_TTOSTYLE_VerticalLayout) { - m_dwTxtBkStyles |= - (FX_TXTLAYOUTSTYLE_VerticalChars | FX_TXTLAYOUTSTYLE_VerticalLayout); - } - m_pTxtBreak->SetLayoutStyles(m_dwTxtBkStyles); -} - -void CFDE_TextOut::SetTabWidth(FX_FLOAT fTabWidth) { - ASSERT(fTabWidth > 1.0f); - m_pTxtBreak->SetTabWidth(fTabWidth, false); -} - -void CFDE_TextOut::SetEllipsisString(const CFX_WideString& wsEllipsis) { - m_bElliChanged = true; - m_wsEllipsis = wsEllipsis; -} - -void CFDE_TextOut::SetParagraphBreakChar(FX_WCHAR wch) { - m_wParagraphBkChar = wch; - m_pTxtBreak->SetParagraphBreakChar(wch); -} - -void CFDE_TextOut::SetAlignment(int32_t iAlignment) { - m_iAlignment = iAlignment; - switch (m_iAlignment) { - case FDE_TTOALIGNMENT_TopCenter: - case FDE_TTOALIGNMENT_Center: - case FDE_TTOALIGNMENT_BottomCenter: - m_iTxtBkAlignment = FX_TXTLINEALIGNMENT_Center; - break; - case FDE_TTOALIGNMENT_TopRight: - case FDE_TTOALIGNMENT_CenterRight: - case FDE_TTOALIGNMENT_BottomRight: - m_iTxtBkAlignment = FX_TXTLINEALIGNMENT_Right; - break; - default: - m_iTxtBkAlignment = FX_TXTLINEALIGNMENT_Left; - break; - } - m_pTxtBreak->SetAlignment(m_iTxtBkAlignment); -} - -void CFDE_TextOut::SetLineSpace(FX_FLOAT fLineSpace) { - ASSERT(fLineSpace > 1.0f); - m_fLineSpace = fLineSpace; -} - -void CFDE_TextOut::SetDIBitmap(CFX_DIBitmap* pDIB) { - ASSERT(pDIB); - - m_pRenderDevice.reset(); - CFX_FxgeDevice* device = new CFX_FxgeDevice; - device->Attach(pDIB, false, nullptr, false); - m_pRenderDevice = pdfium::MakeUnique<CFDE_RenderDevice>(device, false); -} - -void CFDE_TextOut::SetRenderDevice(CFX_RenderDevice* pDevice) { - ASSERT(pDevice); - m_pRenderDevice = pdfium::MakeUnique<CFDE_RenderDevice>(pDevice, false); -} - -void CFDE_TextOut::SetClipRect(const CFX_Rect& rtClip) { - m_rtClip = rtClip.As<FX_FLOAT>(); -} - -void CFDE_TextOut::SetClipRect(const CFX_RectF& rtClip) { - m_rtClip = rtClip; -} - -void CFDE_TextOut::SetLogicClipRect(const CFX_RectF& rtClip) { - m_rtLogicClip = rtClip; -} - -void CFDE_TextOut::SetMatrix(const CFX_Matrix& matrix) { - m_Matrix = matrix; -} - -void CFDE_TextOut::SetLineBreakTolerance(FX_FLOAT fTolerance) { - m_fTolerance = fTolerance; - m_pTxtBreak->SetLineBreakTolerance(m_fTolerance); -} - -int32_t CFDE_TextOut::GetTotalLines() { - return m_iTotalLines; -} - -void CFDE_TextOut::CalcLogicSize(const FX_WCHAR* pwsStr, - int32_t iLength, - CFX_SizeF& size) { - CFX_RectF rtText(0.0f, 0.0f, size.width, size.height); - CalcLogicSize(pwsStr, iLength, rtText); - size = rtText.Size(); -} - -void CFDE_TextOut::CalcLogicSize(const FX_WCHAR* pwsStr, - int32_t iLength, - CFX_RectF& rect) { - if (!pwsStr || iLength < 1) { - rect.width = 0.0f; - rect.height = 0.0f; - } else { - CalcTextSize(pwsStr, iLength, rect); - } -} - -void CFDE_TextOut::CalcTextSize(const FX_WCHAR* pwsStr, - int32_t iLength, - CFX_RectF& rect) { - ASSERT(m_pFont && m_fFontSize >= 1.0f); - SetLineWidth(rect); - m_iTotalLines = 0; - const FX_WCHAR* pStr = pwsStr; - bool bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey); - bool bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); - FX_FLOAT fWidth = 0.0f; - FX_FLOAT fHeight = 0.0f; - FX_FLOAT fStartPos = bVertical ? rect.bottom() : rect.right(); - uint32_t dwBreakStatus = 0; - FX_WCHAR wPreChar = 0; - FX_WCHAR wch; - FX_WCHAR wBreak = 0; - while (iLength-- > 0) { - wch = *pStr++; - if (wBreak == 0 && (wch == L'\n' || wch == L'\r')) { - wBreak = wch; - m_pTxtBreak->SetParagraphBreakChar(wch); - } - if (bHotKey && wch == L'&' && wPreChar != L'&') { - wPreChar = wch; - continue; - } - dwBreakStatus = m_pTxtBreak->AppendChar(wch); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight); - } - wPreChar = 0; - } - dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight); - } - m_pTxtBreak->Reset(); - FX_FLOAT fInc = rect.Height() - fHeight; - if (bVertical) { - fInc = rect.Width() - fHeight; - } - if (m_iAlignment >= FDE_TTOALIGNMENT_CenterLeft && - m_iAlignment < FDE_TTOALIGNMENT_BottomLeft) { - fInc /= 2.0f; - } else if (m_iAlignment < FDE_TTOALIGNMENT_CenterLeft) { - fInc = 0.0f; - } - if (bVertical) { - rect.top += fStartPos; - rect.left += fInc; - rect.width = fHeight; - rect.height = std::min(fWidth, rect.Height()); - } else { - rect.left += fStartPos; - rect.top += fInc; - rect.width = std::min(fWidth, rect.Width()); - rect.height = fHeight; - if (m_dwStyles & FDE_TTOSTYLE_LastLineHeight) { - rect.height -= m_fLineSpace - m_fFontSize; - } - } -} - -void CFDE_TextOut::SetLineWidth(CFX_RectF& rect) { - if ((m_dwStyles & FDE_TTOSTYLE_SingleLine) == 0) { - FX_FLOAT fLineWidth = 0.0f; - if (m_dwStyles & FDE_TTOSTYLE_VerticalLayout) { - if (rect.Height() < 1.0f) { - rect.height = m_fFontSize * 1000.0f; - } - fLineWidth = rect.Height(); - } else { - if (rect.Width() < 1.0f) { - rect.width = m_fFontSize * 1000.0f; - } - fLineWidth = rect.Width(); - } - m_pTxtBreak->SetLineWidth(fLineWidth); - } -} - -bool CFDE_TextOut::RetrieveLineWidth(uint32_t dwBreakStatus, - FX_FLOAT& fStartPos, - FX_FLOAT& fWidth, - FX_FLOAT& fHeight) { - if (dwBreakStatus <= FX_TXTBREAK_PieceBreak) { - return false; - } - FX_FLOAT fLineStep = - (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; - bool bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); - FX_FLOAT fLineWidth = 0.0f; - int32_t iCount = m_pTxtBreak->CountBreakPieces(); - for (int32_t i = 0; i < iCount; i++) { - const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); - fLineWidth += (FX_FLOAT)pPiece->m_iWidth / 20000.0f; - fStartPos = std::min(fStartPos, (FX_FLOAT)pPiece->m_iStartPos / 20000.0f); - } - m_pTxtBreak->ClearBreakPieces(); - if (dwBreakStatus == FX_TXTBREAK_ParagraphBreak) { - m_pTxtBreak->Reset(); - } - if (!bLineWrap && dwBreakStatus == FX_TXTBREAK_LineBreak) { - fWidth += fLineWidth; - } else { - fWidth = std::max(fWidth, fLineWidth); - fHeight += fLineStep; - } - m_iTotalLines++; - return true; -} - -void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - int32_t x, - int32_t y) { - CFX_RectF rtText(static_cast<FX_FLOAT>(x), static_cast<FX_FLOAT>(y), - m_fFontSize * 1000.0f, m_fFontSize * 1000.0f); - DrawText(pwsStr, iLength, rtText); -} - -void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - FX_FLOAT x, - FX_FLOAT y) { - DrawText(pwsStr, iLength, - CFX_RectF(x, y, m_fFontSize * 1000.0f, m_fFontSize * 1000.0f)); -} - -void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_Rect& rect) { - DrawText(pwsStr, iLength, rect.As<FX_FLOAT>()); -} - -void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_RectF& rect) { - CFX_RectF rtText(rect.left, rect.top, rect.width, rect.height); - CFX_Matrix rm; - rm.SetReverse(m_Matrix); - rm.TransformRect(rtText); - DrawText(pwsStr, iLength, rtText, m_rtClip); -} - -void CFDE_TextOut::DrawLogicText(const FX_WCHAR* pwsStr, - int32_t iLength, - FX_FLOAT x, - FX_FLOAT y) { - CFX_RectF rtText(x, y, m_fFontSize * 1000.0f, m_fFontSize * 1000.0f); - DrawLogicText(pwsStr, iLength, rtText); -} - -void CFDE_TextOut::DrawLogicText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_RectF& rect) { - CFX_RectF rtClip(m_rtLogicClip.left, m_rtLogicClip.top, m_rtLogicClip.width, - m_rtLogicClip.height); - m_Matrix.TransformRect(rtClip); - DrawText(pwsStr, iLength, rect, rtClip); -} - -void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_RectF& rect, - const CFX_RectF& rtClip) { - ASSERT(m_pFont && m_fFontSize >= 1.0f); - if (!pwsStr || iLength < 1) - return; - - if (rect.width < m_fFontSize || rect.height < m_fFontSize) { - return; - } - FX_FLOAT fLineWidth = rect.width; - if (m_dwStyles & FDE_TTOSTYLE_VerticalLayout) { - fLineWidth = rect.height; - } - m_pTxtBreak->SetLineWidth(fLineWidth); - m_ttoLines.clear(); - m_wsText.clear(); - LoadText(pwsStr, iLength, rect); - if (m_dwStyles & FDE_TTOSTYLE_Ellipsis) { - ReplaceWidthEllipsis(); - } - Reload(rect); - DoAlignment(rect); - OnDraw(rtClip); -} - -void CFDE_TextOut::ExpandBuffer(int32_t iSize, int32_t iType) { - ASSERT(iSize >= 0); - size_t size = iSize; - switch (iType) { - case 0: - if (m_CharWidths.size() < size) - m_CharWidths.resize(size, 0); - break; - case 1: - if (m_EllCharWidths.size() < size) - m_EllCharWidths.resize(size, 0); - break; - case 2: - if (m_CharPos.size() < size) - m_CharPos.resize(size, FXTEXT_CHARPOS()); - break; - } -} - -void CFDE_TextOut::LoadEllipsis() { - if (!m_bElliChanged) { - return; - } - m_bElliChanged = false; - m_iEllipsisWidth = 0; - int32_t iLength = m_wsEllipsis.GetLength(); - if (iLength < 1) { - return; - } - ExpandBuffer(iLength, 1); - const FX_WCHAR* pStr = m_wsEllipsis.c_str(); - uint32_t dwBreakStatus; - FX_WCHAR wch; - while (iLength-- > 0) { - wch = *pStr++; - dwBreakStatus = m_pTxtBreak->AppendChar(wch); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) - RetrieveEllPieces(&m_EllCharWidths); - } - dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) - RetrieveEllPieces(&m_EllCharWidths); - m_pTxtBreak->Reset(); -} - -void CFDE_TextOut::RetrieveEllPieces(std::vector<int32_t>* pCharWidths) { - int32_t iCount = m_pTxtBreak->CountBreakPieces(); - int32_t iCharIndex = 0; - for (int32_t i = 0; i < iCount; i++) { - const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); - int32_t iPieceChars = pPiece->GetLength(); - for (int32_t j = 0; j < iPieceChars; j++) { - CFX_Char* pTC = pPiece->GetCharPtr(j); - (*pCharWidths)[iCharIndex] = std::max(pTC->m_iCharWidth, 0); - m_iEllipsisWidth += (*pCharWidths)[iCharIndex]; - iCharIndex++; - } - } - m_pTxtBreak->ClearBreakPieces(); -} - -void CFDE_TextOut::LoadText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_RectF& rect) { - FX_WCHAR* pStr = m_wsText.GetBuffer(iLength); - int32_t iTxtLength = iLength; - ExpandBuffer(iTxtLength, 0); - bool bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey); - bool bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); - bool bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); - FX_FLOAT fLineStep = - (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; - FX_FLOAT fLineStop = bVertical ? rect.left : rect.bottom(); - m_fLinePos = bVertical ? rect.right() : rect.top; - if (bVertical) { - fLineStep = -fLineStep; - } - m_hotKeys.RemoveAll(); - int32_t iStartChar = 0; - int32_t iChars = 0; - int32_t iPieceWidths = 0; - uint32_t dwBreakStatus; - FX_WCHAR wch; - bool bRet = false; - while (iTxtLength-- > 0) { - wch = *pwsStr++; - if (bHotKey && wch == L'&' && *(pStr - 1) != L'&') { - if (iTxtLength > 0) - m_hotKeys.Add(iChars); - continue; - } - *pStr++ = wch; - iChars++; - dwBreakStatus = m_pTxtBreak->AppendChar(wch); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - bool bEndofLine = - RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, false, rect); - if (bEndofLine && (bLineWrap || (dwBreakStatus > FX_TXTBREAK_LineBreak && - !bLineWrap))) { - iPieceWidths = 0; - m_iCurLine++; - m_fLinePos += fLineStep; - } - if ((bVertical && m_fLinePos + fLineStep < fLineStop) || - (!bVertical && m_fLinePos + fLineStep > fLineStop)) { - int32_t iCurLine = bEndofLine ? m_iCurLine - 1 : m_iCurLine; - m_ttoLines[iCurLine].SetNewReload(true); - bRet = true; - break; - } - } - } - dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak && !bRet) { - RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, false, rect); - } - m_pTxtBreak->ClearBreakPieces(); - m_pTxtBreak->Reset(); - m_wsText.ReleaseBuffer(iLength); -} - -bool CFDE_TextOut::RetriecePieces(uint32_t dwBreakStatus, - int32_t& iStartChar, - int32_t& iPieceWidths, - bool bReload, - const CFX_RectF& rect) { - bool bSingleLine = !!(m_dwStyles & FDE_TTOSTYLE_SingleLine); - bool bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); - bool bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); - FX_FLOAT fLineStep = - (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; - if (bVertical) { - fLineStep = -fLineStep; - } - CFX_Char* pTC = nullptr; - bool bNeedReload = false; - FX_FLOAT fLineWidth = bVertical ? rect.Height() : rect.Width(); - int32_t iLineWidth = FXSYS_round(fLineWidth * 20000.0f); - int32_t iCount = m_pTxtBreak->CountBreakPieces(); - for (int32_t i = 0; i < iCount; i++) { - const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); - int32_t iPieceChars = pPiece->GetLength(); - int32_t iChar = iStartChar; - int32_t iWidth = 0; - int32_t j = 0; - for (; j < iPieceChars; j++) { - pTC = pPiece->GetCharPtr(j); - int32_t iCurCharWidth = pTC->m_iCharWidth > 0 ? pTC->m_iCharWidth : 0; - if (bSingleLine || !bLineWrap) { - if (iLineWidth - iPieceWidths - iWidth < iCurCharWidth) { - bNeedReload = true; - break; - } - } - iWidth += iCurCharWidth; - m_CharWidths[iChar++] = iCurCharWidth; - } - if (j == 0 && !bReload) { - m_ttoLines[m_iCurLine].SetNewReload(true); - } else if (j > 0) { - CFX_RectF rtPiece; - if (bVertical) { - rtPiece.left = m_fLinePos; - rtPiece.top = rect.top + (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; - rtPiece.width = fLineStep; - rtPiece.height = iWidth / 20000.0f; - } else { - rtPiece.left = rect.left + (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; - rtPiece.top = m_fLinePos; - rtPiece.width = iWidth / 20000.0f; - rtPiece.height = fLineStep; - } - FDE_TTOPIECE ttoPiece; - ttoPiece.iStartChar = iStartChar; - ttoPiece.iChars = j; - ttoPiece.rtPiece = rtPiece; - ttoPiece.dwCharStyles = pPiece->m_dwCharStyles; - if (FX_IsOdd(pPiece->m_iBidiLevel)) { - ttoPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; - } - AppendPiece(ttoPiece, bNeedReload, (bReload && i == iCount - 1)); - } - iStartChar += iPieceChars; - iPieceWidths += iWidth; - } - m_pTxtBreak->ClearBreakPieces(); - bool bRet = bSingleLine || bLineWrap || (!bLineWrap && bNeedReload) || - dwBreakStatus == FX_TXTBREAK_ParagraphBreak; - return bRet; -} - -void CFDE_TextOut::AppendPiece(const FDE_TTOPIECE& ttoPiece, - bool bNeedReload, - bool bEnd) { - if (m_iCurLine >= pdfium::CollectionSize<int32_t>(m_ttoLines)) { - CFDE_TTOLine ttoLine; - ttoLine.SetNewReload(bNeedReload); - m_iCurPiece = ttoLine.AddPiece(m_iCurPiece, ttoPiece); - m_ttoLines.push_back(ttoLine); - m_iCurLine = pdfium::CollectionSize<int32_t>(m_ttoLines) - 1; - } else { - CFDE_TTOLine* pLine = &m_ttoLines[m_iCurLine]; - pLine->SetNewReload(bNeedReload); - m_iCurPiece = pLine->AddPiece(m_iCurPiece, ttoPiece); - if (bEnd) { - int32_t iPieces = pLine->GetSize(); - if (m_iCurPiece < iPieces) { - pLine->RemoveLast(iPieces - m_iCurPiece - 1); - } - } - } - if (!bEnd && bNeedReload) - m_iCurPiece = 0; -} - -void CFDE_TextOut::ReplaceWidthEllipsis() { - LoadEllipsis(); - int32_t iLength = m_wsEllipsis.GetLength(); - if (iLength < 1) - return; - - for (auto& line : m_ttoLines) { - if (!line.GetNewReload()) - continue; - - int32_t iEllipsisCharIndex = iLength - 1; - int32_t iCharWidth = 0; - int32_t iCharCount = 0; - int32_t iPiece = line.GetSize(); - while (iPiece-- > 0) { - FDE_TTOPIECE* pPiece = line.GetPtrAt(iPiece); - if (!pPiece) - break; - - for (int32_t j = pPiece->iChars - 1; j >= 0; j--) { - if (iEllipsisCharIndex < 0) - break; - - int32_t index = pPiece->iStartChar + j; - iCharWidth += m_CharWidths[index]; - iCharCount++; - if (iCharCount <= iLength) { - m_wsText.SetAt(index, m_wsEllipsis.GetAt(iEllipsisCharIndex)); - m_CharWidths[index] = m_EllCharWidths[iEllipsisCharIndex]; - } else if (iCharWidth <= m_iEllipsisWidth) { - m_wsText.SetAt(index, 0); - m_CharWidths[index] = 0; - } - iEllipsisCharIndex--; - } - if (iEllipsisCharIndex < 0) - break; - } - } -} - -void CFDE_TextOut::Reload(const CFX_RectF& rect) { - int i = 0; - for (auto& line : m_ttoLines) { - if (line.GetNewReload()) { - m_iCurLine = i; - m_iCurPiece = 0; - ReloadLinePiece(&line, rect); - } - ++i; - } -} - -void CFDE_TextOut::ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect) { - const FX_WCHAR* pwsStr = m_wsText.c_str(); - bool bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); - int32_t iPieceWidths = 0; - FDE_TTOPIECE* pPiece = pLine->GetPtrAt(0); - int32_t iStartChar = pPiece->iStartChar; - m_fLinePos = bVertical ? pPiece->rtPiece.left : pPiece->rtPiece.top; - int32_t iPieceCount = pLine->GetSize(); - int32_t iPieceIndex = 0; - uint32_t dwBreakStatus = 0; - FX_WCHAR wch; - while (iPieceIndex < iPieceCount) { - int32_t iStar = iStartChar; - int32_t iEnd = pPiece->iChars + iStar; - while (iStar < iEnd) { - wch = *(pwsStr + iStar); - dwBreakStatus = m_pTxtBreak->AppendChar(wch); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, true, rect); - } - iStar++; - } - iPieceIndex++; - pPiece = pLine->GetPtrAt(iPieceIndex); - } - dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); - if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { - RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, true, rect); - } - m_pTxtBreak->Reset(); -} - -void CFDE_TextOut::DoAlignment(const CFX_RectF& rect) { - if (m_ttoLines.empty()) - return; - - bool bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); - FX_FLOAT fLineStopS = bVertical ? rect.right() : rect.bottom(); - FDE_TTOPIECE* pFirstPiece = m_ttoLines.back().GetPtrAt(0); - if (!pFirstPiece) - return; - - FX_FLOAT fLineStopD = - bVertical ? pFirstPiece->rtPiece.right() : pFirstPiece->rtPiece.bottom(); - FX_FLOAT fInc = fLineStopS - fLineStopD; - if (m_iAlignment >= FDE_TTOALIGNMENT_CenterLeft && - m_iAlignment < FDE_TTOALIGNMENT_BottomLeft) { - fInc /= 2.0f; - } else if (m_iAlignment < FDE_TTOALIGNMENT_CenterLeft) { - fInc = 0.0f; - } - if (fInc < 1.0f) - return; - for (auto& line : m_ttoLines) { - int32_t iPieces = line.GetSize(); - for (int32_t j = 0; j < iPieces; j++) { - FDE_TTOPIECE* pPiece = line.GetPtrAt(j); - if (bVertical) - pPiece->rtPiece.left += fInc; - else - pPiece->rtPiece.top += fInc; - } - } -} - -void CFDE_TextOut::OnDraw(const CFX_RectF& rtClip) { - if (!m_pRenderDevice || m_ttoLines.empty()) - return; - - auto pBrush = pdfium::MakeUnique<CFDE_Brush>(); - pBrush->SetColor(m_TxtColor); - m_pRenderDevice->SaveState(); - if (rtClip.Width() > 0.0f && rtClip.Height() > 0.0f) - m_pRenderDevice->SetClipRect(rtClip); - - auto pPen = pdfium::MakeUnique<CFDE_Pen>(); - pPen->SetColor(m_TxtColor); - - for (auto& line : m_ttoLines) { - int32_t iPieces = line.GetSize(); - for (int32_t j = 0; j < iPieces; j++) { - FDE_TTOPIECE* pPiece = line.GetPtrAt(j); - if (!pPiece) - continue; - - int32_t iCount = GetDisplayPos(pPiece); - if (iCount > 0) { - m_pRenderDevice->DrawString(pBrush.get(), m_pFont, m_CharPos.data(), - iCount, m_fFontSize, &m_Matrix); - } - DrawLine(pPiece, pPen.get()); - } - } - m_pRenderDevice->RestoreState(); -} - -int32_t CFDE_TextOut::GetDisplayPos(FDE_TTOPIECE* pPiece) { - FX_TXTRUN tr = ToTextRun(pPiece); - ExpandBuffer(tr.iLength, 2); - return m_pTxtBreak->GetDisplayPos(&tr, m_CharPos.data()); -} - -int32_t CFDE_TextOut::GetCharRects(const FDE_TTOPIECE* pPiece) { - FX_TXTRUN tr = ToTextRun(pPiece); - m_rectArray = m_pTxtBreak->GetCharRects(&tr); - return pdfium::CollectionSize<int32_t>(m_rectArray); -} - -FX_TXTRUN CFDE_TextOut::ToTextRun(const FDE_TTOPIECE* pPiece) { - FX_TXTRUN tr; - tr.wsStr = m_wsText + pPiece->iStartChar; - tr.pWidths = &m_CharWidths[pPiece->iStartChar]; - tr.iLength = pPiece->iChars; - tr.pFont = m_pFont; - tr.fFontSize = m_fFontSize; - tr.dwStyles = m_dwTxtBkStyles; - tr.dwCharStyles = pPiece->dwCharStyles; - tr.wLineBreakChar = m_wParagraphBkChar; - tr.pRect = &pPiece->rtPiece; - return tr; -} - -void CFDE_TextOut::DrawLine(const FDE_TTOPIECE* pPiece, CFDE_Pen* pPen) { - bool bUnderLine = !!(m_dwStyles & FDE_TTOSTYLE_Underline); - bool bStrikeOut = !!(m_dwStyles & FDE_TTOSTYLE_Strikeout); - bool bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey); - bool bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); - if (!bUnderLine && !bStrikeOut && !bHotKey) - return; - - std::unique_ptr<CFDE_Path> pPath(new CFDE_Path); - int32_t iLineCount = 0; - CFX_RectF rtText = pPiece->rtPiece; - CFX_PointF pt1, pt2; - if (bUnderLine) { - if (bVertical) { - pt1.x = rtText.left; - pt1.y = rtText.top; - pt2.x = rtText.left; - pt2.y = rtText.bottom(); - } else { - pt1.x = rtText.left; - pt1.y = rtText.bottom(); - pt2.x = rtText.right(); - pt2.y = rtText.bottom(); - } - pPath->AddLine(pt1, pt2); - iLineCount++; - } - if (bStrikeOut) { - if (bVertical) { - pt1.x = rtText.left + rtText.width * 2.0f / 5.0f; - pt1.y = rtText.top; - pt2.x = pt1.x; - pt2.y = rtText.bottom(); - } else { - pt1.x = rtText.left; - pt1.y = rtText.bottom() - rtText.height * 2.0f / 5.0f; - pt2.x = rtText.right(); - pt2.y = pt1.y; - } - pPath->AddLine(pt1, pt2); - iLineCount++; - } - if (bHotKey) { - int32_t iHotKeys = m_hotKeys.GetSize(); - int32_t iCount = GetCharRects(pPiece); - if (iCount > 0) { - for (int32_t i = 0; i < iHotKeys; i++) { - int32_t iCharIndex = m_hotKeys.GetAt(i); - if (iCharIndex >= pPiece->iStartChar && - iCharIndex < pPiece->iStartChar + pPiece->iChars) { - CFX_RectF rect = m_rectArray[iCharIndex - pPiece->iStartChar]; - if (bVertical) { - pt1.x = rect.left; - pt1.y = rect.top; - pt2.x = rect.left; - pt2.y = rect.bottom(); - } else { - pt1.x = rect.left; - pt1.y = rect.bottom(); - pt2.x = rect.right(); - pt2.y = rect.bottom(); - } - pPath->AddLine(pt1, pt2); - iLineCount++; - } - } - } - } - if (iLineCount > 0) - m_pRenderDevice->DrawPath(pPen, 1, pPath.get(), &m_Matrix); -} - -CFDE_TTOLine::CFDE_TTOLine() : m_bNewReload(false) {} - -CFDE_TTOLine::CFDE_TTOLine(const CFDE_TTOLine& ttoLine) : m_pieces(5) { - m_bNewReload = ttoLine.m_bNewReload; - m_pieces = ttoLine.m_pieces; -} - -CFDE_TTOLine::~CFDE_TTOLine() {} - -int32_t CFDE_TTOLine::AddPiece(int32_t index, const FDE_TTOPIECE& ttoPiece) { - if (index >= pdfium::CollectionSize<int32_t>(m_pieces)) { - m_pieces.push_back(ttoPiece); - return pdfium::CollectionSize<int32_t>(m_pieces); - } - m_pieces[index] = ttoPiece; - return index; -} - -int32_t CFDE_TTOLine::GetSize() const { - return pdfium::CollectionSize<int32_t>(m_pieces); -} - -FDE_TTOPIECE* CFDE_TTOLine::GetPtrAt(int32_t index) { - if (index < 0 || index >= pdfium::CollectionSize<int32_t>(m_pieces)) - return nullptr; - - return &m_pieces[index]; -} - -void CFDE_TTOLine::RemoveLast(int32_t icount) { - if (icount < 0) - return; - icount = std::min(icount, pdfium::CollectionSize<int32_t>(m_pieces)); - m_pieces.erase(m_pieces.end() - icount, m_pieces.end()); -} - -void CFDE_TTOLine::RemoveAll() { - m_pieces.clear(); -} diff --git a/xfa/fde/tto/fde_textout.h b/xfa/fde/tto/fde_textout.h deleted file mode 100644 index 04d656776e631c864f16296f583d429b8c9e6508..0000000000000000000000000000000000000000 --- a/xfa/fde/tto/fde_textout.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_TTO_FDE_TEXTOUT_H_ -#define XFA_FDE_TTO_FDE_TEXTOUT_H_ - -#include <deque> -#include <memory> -#include <vector> - -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fde/fde_object.h" -#include "xfa/fgas/crt/fgas_utils.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" - -#define FDE_TTOSTYLE_Underline 0x0001 -#define FDE_TTOSTYLE_Strikeout 0x0002 -#define FDE_TTOSTYLE_VerticalLayout 0x0004 -#define FDE_TTOSTYLE_SingleLine 0x0010 -#define FDE_TTOSTYLE_ExpandTab 0x0020 -#define FDE_TTOSTYLE_HotKey 0x0040 -#define FDE_TTOSTYLE_Ellipsis 0x0080 -#define FDE_TTOSTYLE_LineWrap 0x0100 -#define FDE_TTOSTYLE_ArabicShapes 0x0200 -#define FDE_TTOSTYLE_ArabicContext 0x0800 -#define FDE_TTOSTYLE_LastLineHeight 0x1000 -#define FDE_TTOALIGNMENT_TopLeft 0 -#define FDE_TTOALIGNMENT_TopCenter 1 -#define FDE_TTOALIGNMENT_TopRight 2 -#define FDE_TTOALIGNMENT_TopAuto 3 -#define FDE_TTOALIGNMENT_CenterLeft 4 -#define FDE_TTOALIGNMENT_Center 5 -#define FDE_TTOALIGNMENT_CenterRight 6 -#define FDE_TTOALIGNMENT_CenterAuto 7 -#define FDE_TTOALIGNMENT_BottomLeft 8 -#define FDE_TTOALIGNMENT_BottomCenter 9 -#define FDE_TTOALIGNMENT_BottomRight 10 -#define FDE_TTOALIGNMENT_BottomAuto 11 - -class CFDE_RenderDevice; -class CFX_RenderDevice; -class CFX_TxtBreak; -struct FX_TXTRUN; - -struct FDE_TTOPIECE { - FDE_TTOPIECE(); - FDE_TTOPIECE(const FDE_TTOPIECE& that); - ~FDE_TTOPIECE(); - - int32_t iStartChar; - int32_t iChars; - uint32_t dwCharStyles; - CFX_RectF rtPiece; -}; - -class CFDE_TTOLine { - public: - CFDE_TTOLine(); - CFDE_TTOLine(const CFDE_TTOLine& ttoLine); - ~CFDE_TTOLine(); - - bool GetNewReload() const { return m_bNewReload; } - void SetNewReload(bool reload) { m_bNewReload = reload; } - int32_t AddPiece(int32_t index, const FDE_TTOPIECE& ttoPiece); - int32_t GetSize() const; - FDE_TTOPIECE* GetPtrAt(int32_t index); - void RemoveLast(int32_t iCount); - void RemoveAll(); - - private: - bool m_bNewReload; - std::deque<FDE_TTOPIECE> m_pieces; -}; - -class CFDE_TextOut { - public: - CFDE_TextOut(); - ~CFDE_TextOut(); - - void SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont); - void SetFontSize(FX_FLOAT fFontSize); - void SetTextColor(FX_ARGB color); - void SetStyles(uint32_t dwStyles); - void SetTabWidth(FX_FLOAT fTabWidth); - void SetEllipsisString(const CFX_WideString& wsEllipsis); - void SetParagraphBreakChar(FX_WCHAR wch); - void SetAlignment(int32_t iAlignment); - void SetLineSpace(FX_FLOAT fLineSpace); - void SetDIBitmap(CFX_DIBitmap* pDIB); - void SetRenderDevice(CFX_RenderDevice* pDevice); - void SetClipRect(const CFX_Rect& rtClip); - void SetClipRect(const CFX_RectF& rtClip); - void SetMatrix(const CFX_Matrix& matrix); - void SetLineBreakTolerance(FX_FLOAT fTolerance); - - void DrawText(const FX_WCHAR* pwsStr, int32_t iLength, int32_t x, int32_t y); - void DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - FX_FLOAT x, - FX_FLOAT y); - void DrawText(const FX_WCHAR* pwsStr, int32_t iLength, const CFX_Rect& rect); - void DrawText(const FX_WCHAR* pwsStr, int32_t iLength, const CFX_RectF& rect); - - void SetLogicClipRect(const CFX_RectF& rtClip); - void CalcLogicSize(const FX_WCHAR* pwsStr, int32_t iLength, CFX_SizeF& size); - void CalcLogicSize(const FX_WCHAR* pwsStr, int32_t iLength, CFX_RectF& rect); - void DrawLogicText(const FX_WCHAR* pwsStr, - int32_t iLength, - FX_FLOAT x, - FX_FLOAT y); - void DrawLogicText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_RectF& rect); - int32_t GetTotalLines(); - - protected: - void CalcTextSize(const FX_WCHAR* pwsStr, int32_t iLength, CFX_RectF& rect); - bool RetrieveLineWidth(uint32_t dwBreakStatus, - FX_FLOAT& fStartPos, - FX_FLOAT& fWidth, - FX_FLOAT& fHeight); - void SetLineWidth(CFX_RectF& rect); - void DrawText(const FX_WCHAR* pwsStr, - int32_t iLength, - const CFX_RectF& rect, - const CFX_RectF& rtClip); - void LoadText(const FX_WCHAR* pwsStr, int32_t iLength, const CFX_RectF& rect); - void LoadEllipsis(); - void ExpandBuffer(int32_t iSize, int32_t iType); - void RetrieveEllPieces(std::vector<int32_t>* pCharWidths); - - void Reload(const CFX_RectF& rect); - void ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect); - bool RetriecePieces(uint32_t dwBreakStatus, - int32_t& iStartChar, - int32_t& iPieceWidths, - bool bReload, - const CFX_RectF& rect); - void AppendPiece(const FDE_TTOPIECE& ttoPiece, bool bNeedReload, bool bEnd); - void ReplaceWidthEllipsis(); - void DoAlignment(const CFX_RectF& rect); - void OnDraw(const CFX_RectF& rtClip); - int32_t GetDisplayPos(FDE_TTOPIECE* pPiece); - int32_t GetCharRects(const FDE_TTOPIECE* pPiece); - - FX_TXTRUN ToTextRun(const FDE_TTOPIECE* pPiece); - void DrawLine(const FDE_TTOPIECE* pPiece, CFDE_Pen* pPen); - - std::unique_ptr<CFX_TxtBreak> m_pTxtBreak; - CFX_RetainPtr<CFGAS_GEFont> m_pFont; - FX_FLOAT m_fFontSize; - FX_FLOAT m_fLineSpace; - FX_FLOAT m_fLinePos; - FX_FLOAT m_fTolerance; - int32_t m_iAlignment; - int32_t m_iTxtBkAlignment; - std::vector<int32_t> m_CharWidths; - std::vector<int32_t> m_EllCharWidths; - FX_WCHAR m_wParagraphBkChar; - FX_ARGB m_TxtColor; - uint32_t m_dwStyles; - uint32_t m_dwTxtBkStyles; - CFX_WideString m_wsEllipsis; - bool m_bElliChanged; - int32_t m_iEllipsisWidth; - CFX_WideString m_wsText; - CFX_RectF m_rtClip; - CFX_RectF m_rtLogicClip; - CFX_Matrix m_Matrix; - std::deque<CFDE_TTOLine> m_ttoLines; - int32_t m_iCurLine; - int32_t m_iCurPiece; - int32_t m_iTotalLines; - std::vector<FXTEXT_CHARPOS> m_CharPos; - std::unique_ptr<CFDE_RenderDevice> m_pRenderDevice; - CFX_ArrayTemplate<int32_t> m_hotKeys; - std::vector<CFX_RectF> m_rectArray; -}; - -#endif // XFA_FDE_TTO_FDE_TEXTOUT_H_ diff --git a/xfa/fde/xml/cfx_saxreader.cpp b/xfa/fde/xml/cfx_saxreader.cpp deleted file mode 100644 index 458bed52d6caf598bb6534d2631a7f0f6a084a2a..0000000000000000000000000000000000000000 --- a/xfa/fde/xml/cfx_saxreader.cpp +++ /dev/null @@ -1,739 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/xml/cfx_saxreader.h" - -#include <algorithm> -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "xfa/fxfa/xfa_checksum.h" - -enum class CFX_SaxMode { - Text = 0, - NodeStart, - DeclOrComment, - DeclNode, - Comment, - CommentContent, - TagName, - TagAttributeName, - TagAttributeEqual, - TagAttributeValue, - TagMaybeClose, - TagClose, - TagEnd, - TargetData, - MAX -}; - -class CFX_SAXCommentContext { - public: - CFX_SAXCommentContext() : m_iHeaderCount(0), m_iTailCount(0) {} - int32_t m_iHeaderCount; - int32_t m_iTailCount; -}; - -namespace { - -const uint32_t kSaxFileBufSize = 32768; - -typedef void (CFX_SAXReader::*FX_SAXReader_LPFParse)(); -static const FX_SAXReader_LPFParse - g_FX_SAXReader_LPFParse[static_cast<int>(CFX_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, -}; - -} // namespace - -CFX_SAXFile::CFX_SAXFile() - : m_dwStart(0), - m_dwEnd(0), - m_dwCur(0), - m_pBuf(nullptr), - m_dwBufSize(0), - m_dwBufIndex(0) {} - -CFX_SAXFile::~CFX_SAXFile() {} - -bool CFX_SAXFile::StartFile(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile, - uint32_t dwStart, - uint32_t dwLen) { - ASSERT(!m_pFile && pFile); - uint32_t dwSize = pFile->GetSize(); - if (dwStart >= dwSize) - return false; - - if (dwLen == static_cast<uint32_t>(-1) || dwStart + dwLen > dwSize) - dwLen = dwSize - dwStart; - - if (dwLen == 0) - return false; - - m_dwBufSize = std::min(dwLen, kSaxFileBufSize); - m_pBuf = FX_Alloc(uint8_t, m_dwBufSize); - 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; -} - -bool CFX_SAXFile::ReadNextBlock() { - ASSERT(m_pFile); - uint32_t dwSize = m_dwEnd - m_dwCur; - if (dwSize == 0) { - return false; - } - m_dwBufSize = std::min(dwSize, kSaxFileBufSize); - 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 = nullptr; - } - m_pFile = nullptr; -} - -CFX_SAXReader::CFX_SAXReader() - : m_File(), - m_pHandler(nullptr), - m_iState(-1), - m_dwItemID(0), - m_iDataSize(256), - m_iNameSize(256), - m_dwParseMode(0), - m_pCommentContext(nullptr) { - m_pszData = FX_Alloc(uint8_t, m_iDataSize); - m_pszName = FX_Alloc(uint8_t, m_iNameSize); -} -CFX_SAXReader::~CFX_SAXReader() { - Reset(); - if (m_pszData) { - FX_Free(m_pszData); - m_pszData = nullptr; - } - if (m_pszName) { - FX_Free(m_pszName); - m_pszName = nullptr; - } -} - -void CFX_SAXReader::Reset() { - m_File.Reset(); - while (!m_Stack.empty()) - m_Stack.pop(); - - m_dwItemID = 0; - m_SkipStack.RemoveAll(); - m_SkipChar = 0; - m_iDataLength = 0; - m_iEntityStart = -1; - m_iNameLength = 0; - m_iDataPos = 0; - delete m_pCommentContext; - m_pCommentContext = nullptr; -} - -void CFX_SAXReader::Push() { - std::unique_ptr<CFX_SAXItem> pNew = - pdfium::MakeUnique<CFX_SAXItem>(++m_dwItemID); - if (!m_Stack.empty()) - pNew->m_bSkip = m_Stack.top()->m_bSkip; - m_Stack.push(std::move(pNew)); -} - -void CFX_SAXReader::Pop() { - if (!m_Stack.empty()) - m_Stack.pop(); -} - -CFX_SAXItem* CFX_SAXReader::GetCurrentItem() const { - return m_Stack.empty() ? nullptr : m_Stack.top().get(); -} - -void CFX_SAXReader::AppendData(uint8_t ch) { - ReallocDataBuffer(); - m_pszData[m_iDataPos++] = ch; -} - -void CFX_SAXReader::AppendName(uint8_t 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 = (uint8_t*)FX_Realloc(uint8_t, 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 = (uint8_t*)FX_Realloc(uint8_t, m_pszName, m_iNameSize); -} - -bool CFX_SAXReader::SkipSpace(uint8_t ch) { - return (m_dwParseMode & CFX_SaxParseMode_NotSkipSpace) == 0 && ch < 0x21; -} - -int32_t CFX_SAXReader::StartParse( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFile, - uint32_t dwStart, - uint32_t dwLen, - uint32_t dwParseMode) { - m_iState = -1; - Reset(); - if (!m_File.StartFile(pFile, dwStart, dwLen)) - return -1; - - m_iState = 0; - m_eMode = CFX_SaxMode::Text; - m_ePrevMode = CFX_SaxMode::Text; - m_bCharData = false; - m_dwDataOffset = 0; - m_dwParseMode = dwParseMode; - m_Stack.emplace(new CFX_SAXItem(++m_dwItemID)); - return 0; -} - -int32_t 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) { - uint32_t& index = m_File.m_dwBufIndex; - uint32_t size = m_File.m_dwBufSize; - const uint8_t* pBuf = m_File.m_pBuf; - while (index < size) { - m_CurByte = pBuf[index]; - (this->*g_FX_SAXReader_LPFParse[static_cast<int>(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(uint8_t ch) { - ReallocDataBuffer(); - m_pszData[m_iDataPos] = ch; - if (m_iEntityStart > -1 && ch == ';') { - int32_t iSaveEntityStart = m_iEntityStart; - CFX_ByteString csEntity(m_pszData + m_iEntityStart + 1, - m_iDataPos - m_iEntityStart - 1); - int32_t iLen = csEntity.GetLength(); - if (iLen > 0) { - if (csEntity[0] == '#') { - if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_sharp) == 0) { - ch = 0; - uint8_t w; - if (iLen > 1 && csEntity[1] == 'x') { - for (int32_t 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 (int32_t 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 & CFX_SaxParseMode_NotConvert_amp) == 0) { - m_pszData[m_iEntityStart++] = '&'; - } - } else if (csEntity.Compare("lt") == 0) { - if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_lt) == 0) { - m_pszData[m_iEntityStart++] = '<'; - } - } else if (csEntity.Compare("gt") == 0) { - if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_gt) == 0) { - m_pszData[m_iEntityStart++] = '>'; - } - } else if (csEntity.Compare("apos") == 0) { - if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_apos) == 0) { - m_pszData[m_iEntityStart++] = '\''; - } - } else if (csEntity.Compare("quot") == 0) { - if ((m_dwParseMode & CFX_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 = CFX_SaxMode::NodeStart; - return; - } - if (m_iDataPos < 1 && SkipSpace(m_CurByte)) { - return; - } - ParseChar(m_CurByte); -} - -void CFX_SAXReader::ParseNodeStart() { - if (m_CurByte == '?') { - GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Instruction; - m_eMode = CFX_SaxMode::TagName; - return; - } - if (m_CurByte == '!') { - m_eMode = CFX_SaxMode::DeclOrComment; - return; - } - if (m_CurByte == '/') { - m_eMode = CFX_SaxMode::TagEnd; - return; - } - if (m_CurByte == '>') { - Pop(); - m_eMode = CFX_SaxMode::Text; - return; - } - if (m_CurByte > 0x20) { - m_dwDataOffset = m_File.m_dwBufIndex; - GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Tag; - m_eMode = CFX_SaxMode::TagName; - AppendData(m_CurByte); - } -} - -void CFX_SAXReader::ParseDeclOrComment() { - if (m_CurByte == '-') { - m_eMode = CFX_SaxMode::Comment; - GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Comment; - if (!m_pCommentContext) - m_pCommentContext = new CFX_SAXCommentContext; - - m_pCommentContext->m_iHeaderCount = 1; - m_pCommentContext->m_iTailCount = 0; - } else { - m_eMode = CFX_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 = CFX_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 = CFX_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 = CFX_SaxMode::TagAttributeName; - } else if (m_CurByte == '/' || m_CurByte == '?') { - m_ePrevMode = m_eMode; - m_eMode = CFX_SaxMode::TagMaybeClose; - } else { - if (m_pHandler) { - NotifyBreak(); - } - m_eMode = CFX_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 == '=' ? CFX_SaxMode::TagAttributeValue - : CFX_SaxMode::TagAttributeEqual; - return; - } - if (m_CurByte == '/' || m_CurByte == '>' || m_CurByte == '?') { - if (m_CurByte == '/' || m_CurByte == '?') { - m_ePrevMode = m_eMode; - m_eMode = CFX_SaxMode::TagMaybeClose; - } else { - if (m_pHandler) { - NotifyBreak(); - } - m_eMode = CFX_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 = CFX_SaxMode::TagAttributeValue; - return; - } - if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) { - m_iDataPos = m_iNameLength; - AppendName(0x20); - m_eMode = CFX_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 = CFX_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 (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) { - m_iNameLength = m_iDataPos; - m_iDataPos = 0; - if (m_pHandler) { - NotifyTargetData(); - } - } - ParseTagClose(); - m_eMode = CFX_SaxMode::Text; - } else if (m_ePrevMode == CFX_SaxMode::TagName) { - AppendData('/'); - m_eMode = CFX_SaxMode::TagName; - m_ePrevMode = CFX_SaxMode::Text; - ParseTagName(); - } else if (m_ePrevMode == CFX_SaxMode::TagAttributeName) { - AppendName('/'); - m_eMode = CFX_SaxMode::TagAttributeName; - m_ePrevMode = CFX_SaxMode::Text; - ParseTagAttributeName(); - } else if (m_ePrevMode == CFX_SaxMode::TargetData) { - AppendName('?'); - m_eMode = CFX_SaxMode::TargetData; - m_ePrevMode = CFX_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 = CFX_SaxMode::Text; - } else { - ParseChar(m_CurByte); - } -} -void CFX_SAXReader::ParseTargetData() { - if (m_CurByte == '?') { - m_ePrevMode = m_eMode; - m_eMode = CFX_SaxMode::TagMaybeClose; - } else { - AppendName(m_CurByte); - } -} -void CFX_SAXReader::SkipNode() { - int32_t iLen = m_SkipStack.GetSize(); - if (m_SkipChar == '\'' || m_SkipChar == '\"') { - if (m_CurByte != m_SkipChar) { - return; - } - iLen--; - 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(uint8_t)) == 0 && - FXSYS_memcmp(m_pszData + m_iDataLength - 2, "]]", - 2 * sizeof(uint8_t)) == 0) { - Pop(); - m_iDataLength -= 9; - m_dwDataOffset += 7; - FXSYS_memmove(m_pszData, m_pszData + 7, - m_iDataLength * sizeof(uint8_t)); - m_bCharData = true; - if (m_pHandler) { - NotifyData(); - } - m_bCharData = false; - } else { - Pop(); - } - m_eMode = CFX_SaxMode::Text; - } - } - break; - } - if (iLen > 0) { - ParseChar(m_CurByte); - } -} - -void CFX_SAXReader::NotifyData() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (!pItem) - return; - - if (pItem->m_eNode == CFX_SAXItem::Type::Tag) - m_pHandler->OnTagData( - pItem->m_pNode, - m_bCharData ? CFX_SAXItem::Type::CharData : CFX_SAXItem::Type::Text, - CFX_ByteStringC(m_pszData, m_iDataLength), - m_File.m_dwCur + m_dwDataOffset); -} - -void CFX_SAXReader::NotifyEnter() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (pItem->m_eNode == CFX_SAXItem::Type::Tag || - pItem->m_eNode == CFX_SAXItem::Type::Instruction) { - pItem->m_pNode = m_pHandler->OnTagEnter( - CFX_ByteStringC(m_pszData, m_iDataLength), pItem->m_eNode, m_dwNodePos); - } -} - -void CFX_SAXReader::NotifyAttribute() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (pItem->m_eNode == CFX_SAXItem::Type::Tag || - pItem->m_eNode == CFX_SAXItem::Type::Instruction) { - m_pHandler->OnTagAttribute(pItem->m_pNode, - CFX_ByteStringC(m_pszName, m_iNameLength), - CFX_ByteStringC(m_pszData, m_iDataLength)); - } -} - -void CFX_SAXReader::NotifyBreak() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (pItem->m_eNode == CFX_SAXItem::Type::Tag) - m_pHandler->OnTagBreak(pItem->m_pNode); -} - -void CFX_SAXReader::NotifyClose() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (pItem->m_eNode == CFX_SAXItem::Type::Tag || - pItem->m_eNode == CFX_SAXItem::Type::Instruction) { - m_pHandler->OnTagClose(pItem->m_pNode, m_dwNodePos); - } -} - -void CFX_SAXReader::NotifyEnd() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (!pItem || pItem->m_eNode != CFX_SAXItem::Type::Tag) - return; - - m_pHandler->OnTagEnd(pItem->m_pNode, - CFX_ByteStringC(m_pszData, m_iDataLength), m_dwNodePos); -} - -void CFX_SAXReader::NotifyTargetData() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (pItem->m_eNode == CFX_SAXItem::Type::Instruction) { - m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode, - CFX_ByteStringC(m_pszName, m_iNameLength), - m_dwNodePos); - } else if (pItem->m_eNode == CFX_SAXItem::Type::Comment) { - m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode, - CFX_ByteStringC(m_pszData, m_iDataLength), - m_dwNodePos); - } -} - -void CFX_SAXReader::SkipCurrentNode() { - CFX_SAXItem* pItem = GetCurrentItem(); - if (!pItem) - return; - - pItem->m_bSkip = true; -} - -void CFX_SAXReader::SetHandler(CXFA_SAXReaderHandler* pHandler) { - m_pHandler = pHandler; -} diff --git a/xfa/fde/xml/cfx_saxreader.h b/xfa/fde/xml/cfx_saxreader.h deleted file mode 100644 index 129399d88d94dffe5025314a22891fd80a916546..0000000000000000000000000000000000000000 --- a/xfa/fde/xml/cfx_saxreader.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_XML_CFX_SAXREADER_H_ -#define XFA_FDE_XML_CFX_SAXREADER_H_ - -#include <memory> -#include <stack> - -#include "core/fxcrt/fx_basic.h" - -class CXFA_SAXContext; - -class CFX_SAXItem { - public: - enum class Type { - Unknown = 0, - Instruction, - Declaration, - Comment, - Tag, - Text, - CharData, - }; - - explicit CFX_SAXItem(uint32_t id) - : m_pNode(nullptr), m_eNode(Type::Unknown), m_dwID(id), m_bSkip(false) {} - - CXFA_SAXContext* m_pNode; - Type m_eNode; - const uint32_t m_dwID; - bool m_bSkip; -}; - -class CFX_SAXFile { - public: - CFX_SAXFile(); - ~CFX_SAXFile(); - - bool StartFile(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile, - uint32_t dwStart, - uint32_t dwLen); - bool ReadNextBlock(); - void Reset(); - - CFX_RetainPtr<IFX_SeekableReadStream> m_pFile; - uint32_t m_dwStart; - uint32_t m_dwEnd; - uint32_t m_dwCur; - uint8_t* m_pBuf; - uint32_t m_dwBufSize; - uint32_t m_dwBufIndex; -}; - -class CFX_SAXCommentContext; -enum class CFX_SaxMode; - -enum CFX_SaxParseMode { - CFX_SaxParseMode_NotConvert_amp = 1 << 0, - CFX_SaxParseMode_NotConvert_lt = 1 << 1, - CFX_SaxParseMode_NotConvert_gt = 1 << 2, - CFX_SaxParseMode_NotConvert_apos = 1 << 3, - CFX_SaxParseMode_NotConvert_quot = 1 << 4, - CFX_SaxParseMode_NotConvert_sharp = 1 << 5, - CFX_SaxParseMode_NotSkipSpace = 1 << 6 -}; - -class CXFA_SAXReaderHandler; - -class CFX_SAXReader { - public: - CFX_SAXReader(); - ~CFX_SAXReader(); - - int32_t StartParse(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile, - uint32_t dwStart = 0, - uint32_t dwLen = -1, - uint32_t dwParseMode = 0); - int32_t ContinueParse(IFX_Pause* pPause = nullptr); - void SkipCurrentNode(); - void SetHandler(CXFA_SAXReaderHandler* pHandler); - void AppendData(uint8_t ch); - void AppendName(uint8_t 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(); - - private: - void Reset(); - void Push(); - void Pop(); - CFX_SAXItem* GetCurrentItem() const; - bool SkipSpace(uint8_t ch); - void SkipNode(); - void NotifyData(); - void NotifyEnter(); - void NotifyAttribute(); - void NotifyBreak(); - void NotifyClose(); - void NotifyEnd(); - void NotifyTargetData(); - void ReallocDataBuffer(); - void ReallocNameBuffer(); - void ParseChar(uint8_t ch); - - CFX_SAXFile m_File; - CXFA_SAXReaderHandler* m_pHandler; - int32_t m_iState; - std::stack<std::unique_ptr<CFX_SAXItem>> m_Stack; - uint32_t m_dwItemID; - CFX_SaxMode m_eMode; - CFX_SaxMode m_ePrevMode; - bool m_bCharData; - uint8_t m_CurByte; - uint32_t m_dwDataOffset; - CFX_ArrayTemplate<uint8_t> m_SkipStack; - uint8_t m_SkipChar; - uint32_t m_dwNodePos; - uint8_t* m_pszData; - int32_t m_iDataSize; - int32_t m_iDataLength; - int32_t m_iEntityStart; - int32_t m_iDataPos; - uint8_t* m_pszName; - int32_t m_iNameSize; - int32_t m_iNameLength; - uint32_t m_dwParseMode; - CFX_SAXCommentContext* m_pCommentContext; -}; - -#endif // XFA_FDE_XML_CFX_SAXREADER_H_ diff --git a/xfa/fde/xml/fde_xml.h b/xfa/fde/xml/fde_xml.h deleted file mode 100644 index e773b3085111c7cd09ac9dcc45149794cc565bbb..0000000000000000000000000000000000000000 --- a/xfa/fde/xml/fde_xml.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_XML_FDE_XML_H_ -#define XFA_FDE_XML_FDE_XML_H_ - -#include "core/fxcrt/fx_system.h" - -enum class FDE_XmlSyntaxResult { - None, - InstructionOpen, - InstructionClose, - ElementOpen, - ElementBreak, - ElementClose, - TargetName, - TagName, - AttriName, - AttriValue, - Text, - CData, - TargetData, - Error, - EndOfString -}; - -enum FDE_XMLNODETYPE { - FDE_XMLNODE_Unknown = 0, - FDE_XMLNODE_Instruction, - FDE_XMLNODE_Element, - FDE_XMLNODE_Text, - FDE_XMLNODE_CharData, -}; - -struct FDE_XMLNODE { - int32_t iNodeNum; - FDE_XMLNODETYPE eNodeType; -}; - -bool FDE_IsXMLValidChar(FX_WCHAR ch); - -#endif // XFA_FDE_XML_FDE_XML_H_ diff --git a/xfa/fde/xml/fde_xml_imp.cpp b/xfa/fde/xml/fde_xml_imp.cpp deleted file mode 100644 index 5ce274bbdbcfa60d0d8b1f9f4ea209e1cf3959ac..0000000000000000000000000000000000000000 --- a/xfa/fde/xml/fde_xml_imp.cpp +++ /dev/null @@ -1,1897 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fde/xml/fde_xml_imp.h" - -#include <algorithm> -#include <utility> - -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_safe_types.h" -#include "third_party/base/stl_util.h" -#include "xfa/fgas/crt/fgas_codepage.h" - -namespace { - -const uint32_t kMaxCharRange = 0x10ffff; - -const uint16_t g_XMLValidCharRange[][2] = {{0x09, 0x09}, - {0x0A, 0x0A}, - {0x0D, 0x0D}, - {0x20, 0xD7FF}, - {0xE000, 0xFFFD}}; - -bool FDE_IsXMLWhiteSpace(FX_WCHAR ch) { - return ch == L' ' || ch == 0x0A || ch == 0x0D || ch == 0x09; -} - -struct FDE_XMLNAMECHAR { - uint16_t wStart; - uint16_t wEnd; - bool bStartChar; -}; - -const FDE_XMLNAMECHAR g_XMLNameChars[] = { - {L'-', L'.', false}, {L'0', L'9', false}, {L':', L':', false}, - {L'A', L'Z', true}, {L'_', L'_', true}, {L'a', L'z', true}, - {0xB7, 0xB7, false}, {0xC0, 0xD6, true}, {0xD8, 0xF6, true}, - {0xF8, 0x02FF, true}, {0x0300, 0x036F, false}, {0x0370, 0x037D, true}, - {0x037F, 0x1FFF, true}, {0x200C, 0x200D, true}, {0x203F, 0x2040, false}, - {0x2070, 0x218F, true}, {0x2C00, 0x2FEF, true}, {0x3001, 0xD7FF, true}, - {0xF900, 0xFDCF, true}, {0xFDF0, 0xFFFD, true}, -}; - -bool FDE_IsXMLNameChar(FX_WCHAR ch, bool bFirstChar) { - int32_t iStart = 0; - int32_t iEnd = FX_ArraySize(g_XMLNameChars) - 1; - while (iStart <= iEnd) { - int32_t iMid = (iStart + iEnd) / 2; - if (ch < g_XMLNameChars[iMid].wStart) { - iEnd = iMid - 1; - } else if (ch > g_XMLNameChars[iMid].wEnd) { - iStart = iMid + 1; - } else { - return bFirstChar ? g_XMLNameChars[iMid].bStartChar : true; - } - } - return false; -} - -} // namespace - -bool FDE_IsXMLValidChar(FX_WCHAR ch) { - int32_t iStart = 0; - int32_t iEnd = FX_ArraySize(g_XMLValidCharRange) - 1; - while (iStart <= iEnd) { - int32_t iMid = (iStart + iEnd) / 2; - if (ch < g_XMLValidCharRange[iMid][0]) { - iEnd = iMid - 1; - } else if (ch > g_XMLValidCharRange[iMid][1]) { - iStart = iMid + 1; - } else { - return true; - } - } - return false; -} - -CFDE_XMLNode::CFDE_XMLNode() - : m_pParent(nullptr), - m_pChild(nullptr), - m_pPrior(nullptr), - m_pNext(nullptr) {} - -FDE_XMLNODETYPE CFDE_XMLNode::GetType() const { - return FDE_XMLNODE_Unknown; -} - -CFDE_XMLNode::~CFDE_XMLNode() { - DeleteChildren(); -} - -void CFDE_XMLNode::DeleteChildren() { - CFDE_XMLNode* pChild = m_pChild; - while (pChild) { - CFDE_XMLNode* pNext = pChild->m_pNext; - delete pChild; - pChild = pNext; - } - m_pChild = nullptr; -} - -int32_t CFDE_XMLNode::CountChildNodes() const { - int32_t iCount = 0; - CFDE_XMLNode* pChild = m_pChild; - while (pChild) { - iCount++; - pChild = pChild->m_pNext; - } - return iCount; -} - -CFDE_XMLNode* CFDE_XMLNode::GetChildNode(int32_t index) const { - CFDE_XMLNode* pChild = m_pChild; - while (pChild) { - if (index == 0) { - return pChild; - } - index--; - pChild = pChild->m_pNext; - } - return nullptr; -} - -int32_t CFDE_XMLNode::GetChildNodeIndex(CFDE_XMLNode* pNode) const { - int32_t index = 0; - CFDE_XMLNode* pChild = m_pChild; - while (pChild) { - if (pChild == pNode) { - return index; - } - index++; - pChild = pChild->m_pNext; - } - return -1; -} - -CFDE_XMLNode* CFDE_XMLNode::GetPath(const FX_WCHAR* pPath, - int32_t iLength, - bool bQualifiedName) const { - ASSERT(pPath); - if (iLength < 0) { - iLength = FXSYS_wcslen(pPath); - } - if (iLength == 0) { - return nullptr; - } - CFX_WideString csPath; - const FX_WCHAR* pStart = pPath; - const FX_WCHAR* pEnd = pPath + iLength; - FX_WCHAR ch; - while (pStart < pEnd) { - ch = *pStart++; - if (ch == L'/') { - break; - } else { - csPath += ch; - } - } - iLength -= pStart - pPath; - CFDE_XMLNode* pFind = nullptr; - if (csPath.GetLength() < 1) { - pFind = GetNodeItem(CFDE_XMLNode::Root); - } else if (csPath.Compare(L"..") == 0) { - pFind = m_pParent; - } else if (csPath.Compare(L".") == 0) { - pFind = (CFDE_XMLNode*)this; - } else { - CFX_WideString wsTag; - CFDE_XMLNode* pNode = m_pChild; - while (pNode) { - if (pNode->GetType() == FDE_XMLNODE_Element) { - if (bQualifiedName) { - ((CFDE_XMLElement*)pNode)->GetTagName(wsTag); - } else { - ((CFDE_XMLElement*)pNode)->GetLocalTagName(wsTag); - } - if (wsTag.Compare(csPath) == 0) { - if (iLength < 1) { - pFind = pNode; - } else { - pFind = pNode->GetPath(pStart, iLength, bQualifiedName); - } - if (pFind) - return pFind; - } - } - pNode = pNode->m_pNext; - } - } - if (!pFind || iLength < 1) - return pFind; - return pFind->GetPath(pStart, iLength, bQualifiedName); -} - -int32_t CFDE_XMLNode::InsertChildNode(CFDE_XMLNode* pNode, int32_t index) { - pNode->m_pParent = this; - if (!m_pChild) { - m_pChild = pNode; - pNode->m_pPrior = nullptr; - pNode->m_pNext = nullptr; - return 0; - } - if (index == 0) { - pNode->m_pNext = m_pChild; - pNode->m_pPrior = nullptr; - m_pChild->m_pPrior = pNode; - m_pChild = pNode; - return 0; - } - int32_t iCount = 0; - CFDE_XMLNode* pFind = m_pChild; - while (++iCount != index && pFind->m_pNext) { - pFind = pFind->m_pNext; - } - pNode->m_pPrior = pFind; - pNode->m_pNext = pFind->m_pNext; - if (pFind->m_pNext) - pFind->m_pNext->m_pPrior = pNode; - pFind->m_pNext = pNode; - return iCount; -} - -void CFDE_XMLNode::RemoveChildNode(CFDE_XMLNode* pNode) { - ASSERT(m_pChild && pNode); - if (m_pChild == pNode) { - m_pChild = pNode->m_pNext; - } else { - pNode->m_pPrior->m_pNext = pNode->m_pNext; - } - if (pNode->m_pNext) - pNode->m_pNext->m_pPrior = pNode->m_pPrior; - pNode->m_pParent = nullptr; - pNode->m_pNext = nullptr; - pNode->m_pPrior = nullptr; -} - -CFDE_XMLNode* CFDE_XMLNode::GetNodeItem(CFDE_XMLNode::NodeItem eItem) const { - switch (eItem) { - case CFDE_XMLNode::Root: { - CFDE_XMLNode* pParent = (CFDE_XMLNode*)this; - while (pParent->m_pParent) { - pParent = pParent->m_pParent; - } - return pParent; - } - case CFDE_XMLNode::Parent: - return m_pParent; - case CFDE_XMLNode::FirstSibling: { - CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; - while (pItem->m_pPrior) { - pItem = pItem->m_pPrior; - } - return pItem == (CFDE_XMLNode*)this ? nullptr : pItem; - } - case CFDE_XMLNode::PriorSibling: - return m_pPrior; - case CFDE_XMLNode::NextSibling: - return m_pNext; - case CFDE_XMLNode::LastSibling: { - CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; - while (pItem->m_pNext) - pItem = pItem->m_pNext; - return pItem == (CFDE_XMLNode*)this ? nullptr : pItem; - } - case CFDE_XMLNode::FirstNeighbor: { - CFDE_XMLNode* pParent = (CFDE_XMLNode*)this; - while (pParent->m_pParent) - pParent = pParent->m_pParent; - return pParent == (CFDE_XMLNode*)this ? nullptr : pParent; - } - case CFDE_XMLNode::PriorNeighbor: { - if (!m_pPrior) - return m_pParent; - - CFDE_XMLNode* pItem = m_pPrior; - while (pItem->m_pChild) { - pItem = pItem->m_pChild; - while (pItem->m_pNext) - pItem = pItem->m_pNext; - } - return pItem; - } - case CFDE_XMLNode::NextNeighbor: { - if (m_pChild) - return m_pChild; - if (m_pNext) - return m_pNext; - CFDE_XMLNode* pItem = m_pParent; - while (pItem) { - if (pItem->m_pNext) - return pItem->m_pNext; - pItem = pItem->m_pParent; - } - return nullptr; - } - case CFDE_XMLNode::LastNeighbor: { - CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; - while (pItem->m_pParent) { - pItem = pItem->m_pParent; - } - while (true) { - while (pItem->m_pNext) - pItem = pItem->m_pNext; - if (!pItem->m_pChild) - break; - pItem = pItem->m_pChild; - } - return pItem == (CFDE_XMLNode*)this ? nullptr : pItem; - } - case CFDE_XMLNode::FirstChild: - return m_pChild; - case CFDE_XMLNode::LastChild: { - if (!m_pChild) - return nullptr; - - CFDE_XMLNode* pChild = m_pChild; - while (pChild->m_pNext) - pChild = pChild->m_pNext; - return pChild; - } - default: - break; - } - return nullptr; -} - -int32_t CFDE_XMLNode::GetNodeLevel() const { - int32_t iLevel = 0; - const CFDE_XMLNode* pItem = m_pParent; - while (pItem) { - iLevel++; - pItem = pItem->m_pParent; - } - return iLevel; -} - -bool CFDE_XMLNode::InsertNodeItem(CFDE_XMLNode::NodeItem eItem, - CFDE_XMLNode* pNode) { - switch (eItem) { - case CFDE_XMLNode::NextSibling: { - pNode->m_pParent = m_pParent; - pNode->m_pNext = m_pNext; - pNode->m_pPrior = this; - if (m_pNext) { - m_pNext->m_pPrior = pNode; - } - m_pNext = pNode; - return true; - } - case CFDE_XMLNode::PriorSibling: { - pNode->m_pParent = m_pParent; - pNode->m_pNext = this; - pNode->m_pPrior = m_pPrior; - if (m_pPrior) { - m_pPrior->m_pNext = pNode; - } else if (m_pParent) { - m_pParent->m_pChild = pNode; - } - m_pPrior = pNode; - return true; - } - default: - return false; - } -} - -CFDE_XMLNode* CFDE_XMLNode::RemoveNodeItem(CFDE_XMLNode::NodeItem eItem) { - CFDE_XMLNode* pNode = nullptr; - switch (eItem) { - case CFDE_XMLNode::NextSibling: - if (m_pNext) { - pNode = m_pNext; - m_pNext = pNode->m_pNext; - if (m_pNext) { - m_pNext->m_pPrior = this; - } - pNode->m_pParent = nullptr; - pNode->m_pNext = nullptr; - pNode->m_pPrior = nullptr; - } - break; - default: - break; - } - return pNode; -} - -CFDE_XMLNode* CFDE_XMLNode::Clone(bool bRecursive) { - return nullptr; -} - -void CFDE_XMLNode::SaveXMLNode(const CFX_RetainPtr<IFGAS_Stream>& pXMLStream) { - CFDE_XMLNode* pNode = (CFDE_XMLNode*)this; - switch (pNode->GetType()) { - case FDE_XMLNODE_Instruction: { - CFX_WideString ws; - CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode; - if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) { - ws = L"<?xml version=\"1.0\" encoding=\""; - uint16_t wCodePage = pXMLStream->GetCodePage(); - if (wCodePage == FX_CODEPAGE_UTF16LE) { - ws += L"UTF-16"; - } else if (wCodePage == FX_CODEPAGE_UTF16BE) { - ws += L"UTF-16be"; - } else { - ws += L"UTF-8"; - } - ws += L"\"?>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } else { - ws.Format(L"<?%s", pInstruction->m_wsTarget.c_str()); - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - std::vector<CFX_WideString>& attributes = pInstruction->m_Attributes; - int32_t i; - int32_t iCount = pdfium::CollectionSize<int32_t>(attributes); - CFX_WideString wsValue; - for (i = 0; i < iCount; i += 2) { - ws = L" "; - ws += attributes[i]; - ws += L"=\""; - wsValue = attributes[i + 1]; - wsValue.Replace(L"&", L"&"); - wsValue.Replace(L"<", L"<"); - wsValue.Replace(L">", L">"); - wsValue.Replace(L"\'", L"'"); - wsValue.Replace(L"\"", L"""); - ws += wsValue; - ws += L"\""; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - std::vector<CFX_WideString>& targetdata = pInstruction->m_TargetData; - iCount = pdfium::CollectionSize<int32_t>(targetdata); - for (i = 0; i < iCount; i++) { - ws = L" \""; - ws += targetdata[i]; - ws += L"\""; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - ws = L"?>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - } break; - case FDE_XMLNODE_Element: { - CFX_WideString ws; - ws = L"<"; - ws += ((CFDE_XMLElement*)pNode)->m_wsTag; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - std::vector<CFX_WideString>& attributes = - static_cast<CFDE_XMLElement*>(pNode)->m_Attributes; - int32_t iCount = pdfium::CollectionSize<int32_t>(attributes); - CFX_WideString wsValue; - for (int32_t i = 0; i < iCount; i += 2) { - ws = L" "; - ws += attributes[i]; - ws += L"=\""; - wsValue = attributes[i + 1]; - wsValue.Replace(L"&", L"&"); - wsValue.Replace(L"<", L"<"); - wsValue.Replace(L">", L">"); - wsValue.Replace(L"\'", L"'"); - wsValue.Replace(L"\"", L"""); - ws += wsValue; - ws += L"\""; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - if (pNode->m_pChild) { - ws = L"\n>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - CFDE_XMLNode* pChild = pNode->m_pChild; - while (pChild) { - pChild->SaveXMLNode(pXMLStream); - pChild = pChild->m_pNext; - } - ws = L"</"; - ws += ((CFDE_XMLElement*)pNode)->m_wsTag; - ws += L"\n>"; - } else { - ws = L"\n/>"; - } - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } break; - case FDE_XMLNODE_Text: { - CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText; - ws.Replace(L"&", L"&"); - ws.Replace(L"<", L"<"); - ws.Replace(L">", L">"); - ws.Replace(L"\'", L"'"); - ws.Replace(L"\"", L"""); - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } break; - case FDE_XMLNODE_CharData: { - CFX_WideString ws = L"<![CDATA["; - ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData; - ws += L"]]>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } break; - case FDE_XMLNODE_Unknown: - break; - default: - break; - } -} - -void CFDE_XMLNode::CloneChildren(CFDE_XMLNode* pClone) { - if (!m_pChild) { - return; - } - CFDE_XMLNode* pNext = m_pChild; - CFDE_XMLNode* pCloneNext = pNext->Clone(true); - pClone->InsertChildNode(pCloneNext); - pNext = pNext->m_pNext; - while (pNext) { - CFDE_XMLNode* pChild = pNext->Clone(true); - pCloneNext->InsertNodeItem(CFDE_XMLNode::NextSibling, pChild); - pCloneNext = pChild; - pNext = pNext->m_pNext; - } -} - -CFDE_XMLInstruction::CFDE_XMLInstruction(const CFX_WideString& wsTarget) - : m_wsTarget(wsTarget) { - ASSERT(m_wsTarget.GetLength() > 0); -} - -FDE_XMLNODETYPE CFDE_XMLInstruction::GetType() const { - return FDE_XMLNODE_Instruction; -} - -CFDE_XMLNode* CFDE_XMLInstruction::Clone(bool bRecursive) { - CFDE_XMLInstruction* pClone = new CFDE_XMLInstruction(m_wsTarget); - if (!pClone) - return nullptr; - - pClone->m_Attributes = m_Attributes; - pClone->m_TargetData = m_TargetData; - if (bRecursive) - CloneChildren(pClone); - - return pClone; -} - -int32_t CFDE_XMLInstruction::CountAttributes() const { - return pdfium::CollectionSize<int32_t>(m_Attributes) / 2; -} - -bool CFDE_XMLInstruction::GetAttribute(int32_t index, - CFX_WideString& wsAttriName, - CFX_WideString& wsAttriValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - ASSERT(index > -1 && index < iCount / 2); - for (int32_t i = 0; i < iCount; i += 2) { - if (index == 0) { - wsAttriName = m_Attributes[i]; - wsAttriValue = m_Attributes[i + 1]; - return true; - } - index--; - } - return false; -} - -bool CFDE_XMLInstruction::HasAttribute(const FX_WCHAR* pwsAttriName) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - return true; - } - } - return false; -} - -void CFDE_XMLInstruction::GetString(const FX_WCHAR* pwsAttriName, - CFX_WideString& wsAttriValue, - const FX_WCHAR* pwsDefValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - wsAttriValue = m_Attributes[i + 1]; - return; - } - } - wsAttriValue = pwsDefValue; -} - -void CFDE_XMLInstruction::SetString(const CFX_WideString& wsAttriName, - const CFX_WideString& wsAttriValue) { - ASSERT(wsAttriName.GetLength() > 0); - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(wsAttriName) == 0) { - m_Attributes[i] = wsAttriName; - m_Attributes[i + 1] = wsAttriValue; - return; - } - } - m_Attributes.push_back(wsAttriName); - m_Attributes.push_back(wsAttriValue); -} - -int32_t CFDE_XMLInstruction::GetInteger(const FX_WCHAR* pwsAttriName, - int32_t iDefValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - return FXSYS_wtoi(m_Attributes[i + 1].c_str()); - } - } - return iDefValue; -} - -void CFDE_XMLInstruction::SetInteger(const FX_WCHAR* pwsAttriName, - int32_t iAttriValue) { - CFX_WideString wsValue; - wsValue.Format(L"%d", iAttriValue); - SetString(pwsAttriName, wsValue); -} - -FX_FLOAT CFDE_XMLInstruction::GetFloat(const FX_WCHAR* pwsAttriName, - FX_FLOAT fDefValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - return FXSYS_wcstof(m_Attributes[i + 1].c_str(), -1, nullptr); - } - } - return fDefValue; -} - -void CFDE_XMLInstruction::SetFloat(const FX_WCHAR* pwsAttriName, - FX_FLOAT fAttriValue) { - CFX_WideString wsValue; - wsValue.Format(L"%f", fAttriValue); - SetString(pwsAttriName, wsValue); -} - -void CFDE_XMLInstruction::RemoveAttribute(const FX_WCHAR* pwsAttriName) { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - m_Attributes.erase(m_Attributes.begin() + i, - m_Attributes.begin() + i + 2); - return; - } - } -} - -int32_t CFDE_XMLInstruction::CountData() const { - return pdfium::CollectionSize<int32_t>(m_TargetData); -} - -bool CFDE_XMLInstruction::GetData(int32_t index, CFX_WideString& wsData) const { - if (index < 0 || index >= pdfium::CollectionSize<int32_t>(m_TargetData)) - return false; - - wsData = m_TargetData[index]; - return true; -} - -void CFDE_XMLInstruction::AppendData(const CFX_WideString& wsData) { - m_TargetData.push_back(wsData); -} - -void CFDE_XMLInstruction::RemoveData(int32_t index) { - if (index < 0 || index >= pdfium::CollectionSize<int32_t>(m_TargetData)) - return; - - m_TargetData.erase(m_TargetData.begin() + index); -} - -CFDE_XMLInstruction::~CFDE_XMLInstruction() {} - -CFDE_XMLElement::CFDE_XMLElement(const CFX_WideString& wsTag) - : CFDE_XMLNode(), m_wsTag(wsTag), m_Attributes() { - ASSERT(m_wsTag.GetLength() > 0); -} - -CFDE_XMLElement::~CFDE_XMLElement() {} - -FDE_XMLNODETYPE CFDE_XMLElement::GetType() const { - return FDE_XMLNODE_Element; -} - -CFDE_XMLNode* CFDE_XMLElement::Clone(bool bRecursive) { - CFDE_XMLElement* pClone = new CFDE_XMLElement(m_wsTag); - if (!pClone) - return nullptr; - - pClone->m_Attributes = m_Attributes; - if (bRecursive) { - CloneChildren(pClone); - } else { - CFX_WideString wsText; - CFDE_XMLNode* pChild = m_pChild; - while (pChild) { - switch (pChild->GetType()) { - case FDE_XMLNODE_Text: - wsText += ((CFDE_XMLText*)pChild)->m_wsText; - break; - default: - break; - } - pChild = pChild->m_pNext; - } - pClone->SetTextData(wsText); - } - return pClone; -} - -void CFDE_XMLElement::GetTagName(CFX_WideString& wsTag) const { - wsTag = m_wsTag; -} - -void CFDE_XMLElement::GetLocalTagName(CFX_WideString& wsTag) const { - FX_STRSIZE iFind = m_wsTag.Find(L':', 0); - if (iFind < 0) { - wsTag = m_wsTag; - } else { - wsTag = m_wsTag.Right(m_wsTag.GetLength() - iFind - 1); - } -} - -void CFDE_XMLElement::GetNamespacePrefix(CFX_WideString& wsPrefix) const { - FX_STRSIZE iFind = m_wsTag.Find(L':', 0); - if (iFind < 0) { - wsPrefix.clear(); - } else { - wsPrefix = m_wsTag.Left(iFind); - } -} - -void CFDE_XMLElement::GetNamespaceURI(CFX_WideString& wsNamespace) const { - CFX_WideString wsAttri(L"xmlns"), wsPrefix; - GetNamespacePrefix(wsPrefix); - if (wsPrefix.GetLength() > 0) { - wsAttri += L":"; - wsAttri += wsPrefix; - } - wsNamespace.clear(); - CFDE_XMLNode* pNode = (CFDE_XMLNode*)this; - while (pNode) { - if (pNode->GetType() != FDE_XMLNODE_Element) { - break; - } - CFDE_XMLElement* pElement = (CFDE_XMLElement*)pNode; - if (!pElement->HasAttribute(wsAttri.c_str())) { - pNode = pNode->GetNodeItem(CFDE_XMLNode::Parent); - continue; - } - pElement->GetString(wsAttri.c_str(), wsNamespace); - break; - } -} - -int32_t CFDE_XMLElement::CountAttributes() const { - return pdfium::CollectionSize<int32_t>(m_Attributes) / 2; -} - -bool CFDE_XMLElement::GetAttribute(int32_t index, - CFX_WideString& wsAttriName, - CFX_WideString& wsAttriValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - ASSERT(index > -1 && index < iCount / 2); - for (int32_t i = 0; i < iCount; i += 2) { - if (index == 0) { - wsAttriName = m_Attributes[i]; - wsAttriValue = m_Attributes[i + 1]; - return true; - } - index--; - } - return false; -} - -bool CFDE_XMLElement::HasAttribute(const FX_WCHAR* pwsAttriName) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) - return true; - } - return false; -} - -void CFDE_XMLElement::GetString(const FX_WCHAR* pwsAttriName, - CFX_WideString& wsAttriValue, - const FX_WCHAR* pwsDefValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - wsAttriValue = m_Attributes[i + 1]; - return; - } - } - wsAttriValue = pwsDefValue; -} - -void CFDE_XMLElement::SetString(const CFX_WideString& wsAttriName, - const CFX_WideString& wsAttriValue) { - ASSERT(wsAttriName.GetLength() > 0); - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(wsAttriName) == 0) { - m_Attributes[i] = wsAttriName; - m_Attributes[i + 1] = wsAttriValue; - return; - } - } - m_Attributes.push_back(wsAttriName); - m_Attributes.push_back(wsAttriValue); -} - -int32_t CFDE_XMLElement::GetInteger(const FX_WCHAR* pwsAttriName, - int32_t iDefValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - return FXSYS_wtoi(m_Attributes[i + 1].c_str()); - } - } - return iDefValue; -} - -void CFDE_XMLElement::SetInteger(const FX_WCHAR* pwsAttriName, - int32_t iAttriValue) { - CFX_WideString wsValue; - wsValue.Format(L"%d", iAttriValue); - SetString(pwsAttriName, wsValue); -} - -FX_FLOAT CFDE_XMLElement::GetFloat(const FX_WCHAR* pwsAttriName, - FX_FLOAT fDefValue) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - return FXSYS_wcstof(m_Attributes[i + 1].c_str(), -1, nullptr); - } - } - return fDefValue; -} - -void CFDE_XMLElement::SetFloat(const FX_WCHAR* pwsAttriName, - FX_FLOAT fAttriValue) { - CFX_WideString wsValue; - wsValue.Format(L"%f", fAttriValue); - SetString(pwsAttriName, wsValue); -} - -void CFDE_XMLElement::RemoveAttribute(const FX_WCHAR* pwsAttriName) { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Attributes); - for (int32_t i = 0; i < iCount; i += 2) { - if (m_Attributes[i].Compare(pwsAttriName) == 0) { - m_Attributes.erase(m_Attributes.begin() + i, - m_Attributes.begin() + i + 2); - return; - } - } -} - -void CFDE_XMLElement::GetTextData(CFX_WideString& wsText) const { - CFX_WideTextBuf buffer; - CFDE_XMLNode* pChild = m_pChild; - while (pChild) { - switch (pChild->GetType()) { - case FDE_XMLNODE_Text: - buffer << ((CFDE_XMLText*)pChild)->m_wsText; - break; - case FDE_XMLNODE_CharData: - buffer << ((CFDE_XMLCharData*)pChild)->m_wsCharData; - break; - default: - break; - } - pChild = pChild->m_pNext; - } - wsText = buffer.AsStringC(); -} - -void CFDE_XMLElement::SetTextData(const CFX_WideString& wsText) { - if (wsText.GetLength() < 1) { - return; - } - InsertChildNode(new CFDE_XMLText(wsText)); -} - -CFDE_XMLText::CFDE_XMLText(const CFX_WideString& wsText) - : CFDE_XMLNode(), m_wsText(wsText) {} - -FDE_XMLNODETYPE CFDE_XMLText::GetType() const { - return FDE_XMLNODE_Text; -} - -CFDE_XMLNode* CFDE_XMLText::Clone(bool bRecursive) { - CFDE_XMLText* pClone = new CFDE_XMLText(m_wsText); - return pClone; -} - -CFDE_XMLText::~CFDE_XMLText() {} - -CFDE_XMLCharData::CFDE_XMLCharData(const CFX_WideString& wsCData) - : CFDE_XMLDeclaration(), m_wsCharData(wsCData) {} - -FDE_XMLNODETYPE CFDE_XMLCharData::GetType() const { - return FDE_XMLNODE_CharData; -} - -CFDE_XMLNode* CFDE_XMLCharData::Clone(bool bRecursive) { - CFDE_XMLCharData* pClone = new CFDE_XMLCharData(m_wsCharData); - return pClone; -} - -CFDE_XMLCharData::~CFDE_XMLCharData() {} - -CFDE_XMLDoc::CFDE_XMLDoc() : m_pRoot(nullptr) { - Reset(true); - CFDE_XMLInstruction* pXML = new CFDE_XMLInstruction(L"xml"); - m_pRoot->InsertChildNode(pXML); -} - -CFDE_XMLDoc::~CFDE_XMLDoc() { - Reset(false); -} - -void CFDE_XMLDoc::Reset(bool bInitRoot) { - m_iStatus = 0; - m_pStream = nullptr; - if (bInitRoot) { - if (m_pRoot) - m_pRoot->DeleteChildren(); - else - m_pRoot = new CFDE_XMLNode; - } else { - delete m_pRoot; - m_pRoot = nullptr; - } - ReleaseParser(); -} - -void CFDE_XMLDoc::ReleaseParser() { - m_pXMLParser.reset(); -} - -bool CFDE_XMLDoc::LoadXML(std::unique_ptr<IFDE_XMLParser> pXMLParser) { - if (!pXMLParser) - return false; - - Reset(true); - m_pXMLParser = std::move(pXMLParser); - return true; -} - -int32_t CFDE_XMLDoc::DoLoad(IFX_Pause* pPause) { - if (m_iStatus < 100) - m_iStatus = m_pXMLParser->DoParser(pPause); - - return m_iStatus; -} - -void CFDE_XMLDoc::CloseXML() { - ReleaseParser(); -} - -void CFDE_XMLDoc::SaveXMLNode(const CFX_RetainPtr<IFGAS_Stream>& pXMLStream, - CFDE_XMLNode* pINode) { - CFDE_XMLNode* pNode = (CFDE_XMLNode*)pINode; - switch (pNode->GetType()) { - case FDE_XMLNODE_Instruction: { - CFX_WideString ws; - CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode; - if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) { - ws = L"<?xml version=\"1.0\" encoding=\""; - uint16_t wCodePage = pXMLStream->GetCodePage(); - if (wCodePage == FX_CODEPAGE_UTF16LE) { - ws += L"UTF-16"; - } else if (wCodePage == FX_CODEPAGE_UTF16BE) { - ws += L"UTF-16be"; - } else { - ws += L"UTF-8"; - } - ws += L"\"?>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } else { - ws.Format(L"<?%s", pInstruction->m_wsTarget.c_str()); - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - std::vector<CFX_WideString>& attributes = pInstruction->m_Attributes; - int32_t i; - int32_t iCount = pdfium::CollectionSize<int32_t>(attributes); - CFX_WideString wsValue; - for (i = 0; i < iCount; i += 2) { - ws = L" "; - ws += attributes[i]; - ws += L"=\""; - wsValue = attributes[i + 1]; - wsValue.Replace(L"&", L"&"); - wsValue.Replace(L"<", L"<"); - wsValue.Replace(L">", L">"); - wsValue.Replace(L"\'", L"'"); - wsValue.Replace(L"\"", L"""); - ws += wsValue; - ws += L"\""; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - std::vector<CFX_WideString>& targetdata = pInstruction->m_TargetData; - iCount = pdfium::CollectionSize<int32_t>(targetdata); - for (i = 0; i < iCount; i++) { - ws = L" \""; - ws += targetdata[i]; - ws += L"\""; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - ws = L"?>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - } break; - case FDE_XMLNODE_Element: { - CFX_WideString ws; - ws = L"<"; - ws += ((CFDE_XMLElement*)pNode)->m_wsTag; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - std::vector<CFX_WideString>& attributes = - static_cast<CFDE_XMLElement*>(pNode)->m_Attributes; - int32_t iCount = pdfium::CollectionSize<int32_t>(attributes); - CFX_WideString wsValue; - for (int32_t i = 0; i < iCount; i += 2) { - ws = L" "; - ws += attributes[i]; - ws += L"=\""; - wsValue = attributes[i + 1]; - wsValue.Replace(L"&", L"&"); - wsValue.Replace(L"<", L"<"); - wsValue.Replace(L">", L">"); - wsValue.Replace(L"\'", L"'"); - wsValue.Replace(L"\"", L"""); - ws += wsValue; - ws += L"\""; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } - if (pNode->m_pChild) { - ws = L"\n>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - CFDE_XMLNode* pChild = pNode->m_pChild; - while (pChild) { - SaveXMLNode(pXMLStream, static_cast<CFDE_XMLNode*>(pChild)); - pChild = pChild->m_pNext; - } - ws = L"</"; - ws += ((CFDE_XMLElement*)pNode)->m_wsTag; - ws += L"\n>"; - } else { - ws = L"\n/>"; - } - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } break; - case FDE_XMLNODE_Text: { - CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText; - ws.Replace(L"&", L"&"); - ws.Replace(L"<", L"<"); - ws.Replace(L">", L">"); - ws.Replace(L"\'", L"'"); - ws.Replace(L"\"", L"""); - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } break; - case FDE_XMLNODE_CharData: { - CFX_WideString ws = L"<![CDATA["; - ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData; - ws += L"]]>"; - pXMLStream->WriteString(ws.c_str(), ws.GetLength()); - } break; - case FDE_XMLNODE_Unknown: - break; - default: - break; - } -} - -void CFDE_XMLDoc::SaveXML(CFX_RetainPtr<IFGAS_Stream>& pXMLStream, - bool bSaveBOM) { - if (!pXMLStream || pXMLStream == m_pStream) { - m_pStream->Seek(FX_STREAMSEEK_Begin, 0); - pXMLStream = m_pStream; - } - ASSERT((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Text) != 0); - ASSERT((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Write) != 0); - uint16_t wCodePage = pXMLStream->GetCodePage(); - if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && - wCodePage != FX_CODEPAGE_UTF8) { - wCodePage = FX_CODEPAGE_UTF8; - pXMLStream->SetCodePage(wCodePage); - } - if (bSaveBOM) { - pXMLStream->WriteString(L"\xFEFF", 1); - } - CFDE_XMLNode* pNode = m_pRoot->m_pChild; - while (pNode) { - SaveXMLNode(pXMLStream, static_cast<CFDE_XMLNode*>(pNode)); - pNode = pNode->m_pNext; - } - if (pXMLStream == m_pStream) { - int32_t iPos = pXMLStream->GetPosition(); - pXMLStream->SetLength(iPos); - } -} - -CFDE_BlockBuffer::CFDE_BlockBuffer(int32_t iAllocStep) - : m_iDataLength(0), - m_iBufferSize(0), - m_iAllocStep(iAllocStep), - m_iStartPosition(0) {} - -CFDE_BlockBuffer::~CFDE_BlockBuffer() { - ClearBuffer(); -} - -FX_WCHAR* CFDE_BlockBuffer::GetAvailableBlock(int32_t& iIndexInBlock) { - iIndexInBlock = 0; - if (!m_BlockArray.GetSize()) { - return nullptr; - } - int32_t iRealIndex = m_iStartPosition + m_iDataLength; - if (iRealIndex == m_iBufferSize) { - FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep); - m_BlockArray.Add(pBlock); - m_iBufferSize += m_iAllocStep; - return pBlock; - } - iIndexInBlock = iRealIndex % m_iAllocStep; - return m_BlockArray[iRealIndex / m_iAllocStep]; -} - -bool CFDE_BlockBuffer::InitBuffer(int32_t iBufferSize) { - ClearBuffer(); - int32_t iNumOfBlock = (iBufferSize - 1) / m_iAllocStep + 1; - for (int32_t i = 0; i < iNumOfBlock; i++) { - m_BlockArray.Add(FX_Alloc(FX_WCHAR, m_iAllocStep)); - } - m_iBufferSize = iNumOfBlock * m_iAllocStep; - return true; -} - -void CFDE_BlockBuffer::SetTextChar(int32_t iIndex, FX_WCHAR ch) { - if (iIndex < 0) { - return; - } - int32_t iRealIndex = m_iStartPosition + iIndex; - int32_t iBlockIndex = iRealIndex / m_iAllocStep; - int32_t iInnerIndex = iRealIndex % m_iAllocStep; - int32_t iBlockSize = m_BlockArray.GetSize(); - if (iBlockIndex >= iBlockSize) { - int32_t iNewBlocks = iBlockIndex - iBlockSize + 1; - do { - FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep); - m_BlockArray.Add(pBlock); - m_iBufferSize += m_iAllocStep; - } while (--iNewBlocks); - } - FX_WCHAR* pTextData = m_BlockArray[iBlockIndex]; - *(pTextData + iInnerIndex) = ch; - if (m_iDataLength <= iIndex) { - m_iDataLength = iIndex + 1; - } -} - -int32_t CFDE_BlockBuffer::DeleteTextChars(int32_t iCount, bool bDirection) { - if (iCount <= 0) { - return m_iDataLength; - } - if (iCount >= m_iDataLength) { - Reset(false); - return 0; - } - if (bDirection) { - m_iStartPosition += iCount; - m_iDataLength -= iCount; - } else { - m_iDataLength -= iCount; - } - return m_iDataLength; -} - -void CFDE_BlockBuffer::GetTextData(CFX_WideString& wsTextData, - int32_t iStart, - int32_t iLength) const { - wsTextData.clear(); - int32_t iMaybeDataLength = m_iBufferSize - 1 - m_iStartPosition; - if (iStart < 0 || iStart > iMaybeDataLength) { - return; - } - if (iLength == -1 || iLength > iMaybeDataLength) { - iLength = iMaybeDataLength; - } - if (iLength <= 0) { - return; - } - FX_WCHAR* pBuf = wsTextData.GetBuffer(iLength); - if (!pBuf) { - return; - } - int32_t iStartBlockIndex = 0; - int32_t iStartInnerIndex = 0; - TextDataIndex2BufIndex(iStart, iStartBlockIndex, iStartInnerIndex); - int32_t iEndBlockIndex = 0; - int32_t iEndInnerIndex = 0; - TextDataIndex2BufIndex(iStart + iLength, iEndBlockIndex, iEndInnerIndex); - int32_t iPointer = 0; - for (int32_t i = iStartBlockIndex; i <= iEndBlockIndex; i++) { - int32_t iBufferPointer = 0; - int32_t iCopyLength = m_iAllocStep; - if (i == iStartBlockIndex) { - iCopyLength -= iStartInnerIndex; - iBufferPointer = iStartInnerIndex; - } - if (i == iEndBlockIndex) { - iCopyLength -= ((m_iAllocStep - 1) - iEndInnerIndex); - } - FX_WCHAR* pBlockBuf = m_BlockArray[i]; - FXSYS_memcpy(pBuf + iPointer, pBlockBuf + iBufferPointer, - iCopyLength * sizeof(FX_WCHAR)); - iPointer += iCopyLength; - } - wsTextData.ReleaseBuffer(iLength); -} - -void CFDE_BlockBuffer::TextDataIndex2BufIndex(const int32_t iIndex, - int32_t& iBlockIndex, - int32_t& iInnerIndex) const { - ASSERT(iIndex >= 0); - int32_t iRealIndex = m_iStartPosition + iIndex; - iBlockIndex = iRealIndex / m_iAllocStep; - iInnerIndex = iRealIndex % m_iAllocStep; -} - -void CFDE_BlockBuffer::ClearBuffer() { - m_iBufferSize = 0; - int32_t iSize = m_BlockArray.GetSize(); - for (int32_t i = 0; i < iSize; i++) { - FX_Free(m_BlockArray[i]); - } - m_BlockArray.RemoveAll(); -} - -CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser() - : m_pStream(nullptr), - m_iXMLPlaneSize(-1), - m_iCurrentPos(0), - m_iCurrentNodeNum(-1), - m_iLastNodeNum(-1), - m_iParsedChars(0), - m_iParsedBytes(0), - m_pBuffer(nullptr), - m_iBufferChars(0), - m_bEOS(false), - m_pStart(nullptr), - m_pEnd(nullptr), - m_XMLNodeStack(16), - m_iAllocStep(m_BlockBuffer.GetAllocStep()), - m_iDataLength(m_BlockBuffer.GetDataLengthRef()), - m_pCurrentBlock(nullptr), - m_iIndexInBlock(0), - m_iTextDataLength(0), - m_syntaxParserResult(FDE_XmlSyntaxResult::None), - m_syntaxParserState(FDE_XmlSyntaxState::Text), - m_wQuotationMark(0), - m_iEntityStart(-1), - m_SkipStack(16) { - m_CurNode.iNodeNum = -1; - m_CurNode.eNodeType = FDE_XMLNODE_Unknown; -} - -void CFDE_XMLSyntaxParser::Init(const CFX_RetainPtr<IFGAS_Stream>& pStream, - int32_t iXMLPlaneSize, - int32_t iTextDataSize) { - ASSERT(!m_pStream && !m_pBuffer); - ASSERT(pStream && iXMLPlaneSize > 0); - int32_t iStreamLength = pStream->GetLength(); - ASSERT(iStreamLength > 0); - m_pStream = pStream; - m_iXMLPlaneSize = std::min(iXMLPlaneSize, iStreamLength); - uint8_t bom[4]; - m_iCurrentPos = m_pStream->GetBOM(bom); - ASSERT(!m_pBuffer); - - FX_SAFE_INT32 alloc_size_safe = m_iXMLPlaneSize; - alloc_size_safe += 1; // For NUL. - if (!alloc_size_safe.IsValid() || alloc_size_safe.ValueOrDie() <= 0) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return; - } - - m_pBuffer = FX_Alloc( - FX_WCHAR, pdfium::base::ValueOrDieForType<size_t>(alloc_size_safe)); - m_pStart = m_pEnd = m_pBuffer; - ASSERT(!m_BlockBuffer.IsInitialized()); - m_BlockBuffer.InitBuffer(); - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_iParsedBytes = m_iParsedChars = 0; - m_iBufferChars = 0; -} - -FDE_XmlSyntaxResult CFDE_XMLSyntaxParser::DoSyntaxParse() { - if (m_syntaxParserResult == FDE_XmlSyntaxResult::Error || - m_syntaxParserResult == FDE_XmlSyntaxResult::EndOfString) { - return m_syntaxParserResult; - } - ASSERT(m_pStream && m_pBuffer && m_BlockBuffer.IsInitialized()); - int32_t iStreamLength = m_pStream->GetLength(); - int32_t iPos; - - FDE_XmlSyntaxResult syntaxParserResult = FDE_XmlSyntaxResult::None; - while (true) { - if (m_pStart >= m_pEnd) { - if (m_bEOS || m_iCurrentPos >= iStreamLength) { - m_syntaxParserResult = FDE_XmlSyntaxResult::EndOfString; - return m_syntaxParserResult; - } - m_iParsedChars += (m_pEnd - m_pBuffer); - m_iParsedBytes = m_iCurrentPos; - if (m_pStream->GetPosition() != m_iCurrentPos) { - m_pStream->Seek(FX_STREAMSEEK_Begin, m_iCurrentPos); - } - m_iBufferChars = - m_pStream->ReadString(m_pBuffer, m_iXMLPlaneSize, m_bEOS); - iPos = m_pStream->GetPosition(); - if (m_iBufferChars < 1) { - m_iCurrentPos = iStreamLength; - m_syntaxParserResult = FDE_XmlSyntaxResult::EndOfString; - return m_syntaxParserResult; - } - m_iCurrentPos = iPos; - m_pStart = m_pBuffer; - m_pEnd = m_pBuffer + m_iBufferChars; - } - - while (m_pStart < m_pEnd) { - FX_WCHAR ch = *m_pStart; - switch (m_syntaxParserState) { - case FDE_XmlSyntaxState::Text: - if (ch == L'<') { - if (m_iDataLength > 0) { - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_iEntityStart = -1; - syntaxParserResult = FDE_XmlSyntaxResult::Text; - } else { - m_pStart++; - m_syntaxParserState = FDE_XmlSyntaxState::Node; - } - } else { - ParseTextChar(ch); - } - break; - case FDE_XmlSyntaxState::Node: - if (ch == L'!') { - m_pStart++; - m_syntaxParserState = FDE_XmlSyntaxState::SkipCommentOrDecl; - } else if (ch == L'/') { - m_pStart++; - m_syntaxParserState = FDE_XmlSyntaxState::CloseElement; - } else if (ch == L'?') { - m_iLastNodeNum++; - m_iCurrentNodeNum = m_iLastNodeNum; - m_CurNode.iNodeNum = m_iLastNodeNum; - m_CurNode.eNodeType = FDE_XMLNODE_Instruction; - m_XMLNodeStack.Push(m_CurNode); - m_pStart++; - m_syntaxParserState = FDE_XmlSyntaxState::Target; - syntaxParserResult = FDE_XmlSyntaxResult::InstructionOpen; - } else { - m_iLastNodeNum++; - m_iCurrentNodeNum = m_iLastNodeNum; - m_CurNode.iNodeNum = m_iLastNodeNum; - m_CurNode.eNodeType = FDE_XMLNODE_Element; - m_XMLNodeStack.Push(m_CurNode); - m_syntaxParserState = FDE_XmlSyntaxState::Tag; - syntaxParserResult = FDE_XmlSyntaxResult::ElementOpen; - } - break; - case FDE_XmlSyntaxState::Target: - case FDE_XmlSyntaxState::Tag: - if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) { - if (m_iDataLength < 1) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } else { - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (m_syntaxParserState != FDE_XmlSyntaxState::Target) { - syntaxParserResult = FDE_XmlSyntaxResult::TagName; - } else { - syntaxParserResult = FDE_XmlSyntaxResult::TargetName; - } - m_syntaxParserState = FDE_XmlSyntaxState::AttriName; - } - } else { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return FDE_XmlSyntaxResult::Error; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - m_pStart++; - } - break; - case FDE_XmlSyntaxState::AttriName: - if (m_iDataLength < 1 && FDE_IsXMLWhiteSpace(ch)) { - m_pStart++; - break; - } - if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) { - if (m_iDataLength < 1) { - if (m_CurNode.eNodeType == FDE_XMLNODE_Element) { - if (ch == L'>' || ch == L'/') { - m_syntaxParserState = FDE_XmlSyntaxState::BreakElement; - break; - } - } else if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) { - if (ch == L'?') { - m_syntaxParserState = FDE_XmlSyntaxState::CloseInstruction; - m_pStart++; - } else { - m_syntaxParserState = FDE_XmlSyntaxState::TargetData; - } - break; - } - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } else { - if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) { - if (ch != '=' && !FDE_IsXMLWhiteSpace(ch)) { - m_syntaxParserState = FDE_XmlSyntaxState::TargetData; - break; - } - } - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_syntaxParserState = FDE_XmlSyntaxState::AttriEqualSign; - syntaxParserResult = FDE_XmlSyntaxResult::AttriName; - } - } else { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return FDE_XmlSyntaxResult::Error; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - m_pStart++; - } - break; - case FDE_XmlSyntaxState::AttriEqualSign: - if (FDE_IsXMLWhiteSpace(ch)) { - m_pStart++; - break; - } - if (ch != L'=') { - if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) { - m_syntaxParserState = FDE_XmlSyntaxState::TargetData; - break; - } - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } else { - m_syntaxParserState = FDE_XmlSyntaxState::AttriQuotation; - m_pStart++; - } - break; - case FDE_XmlSyntaxState::AttriQuotation: - if (FDE_IsXMLWhiteSpace(ch)) { - m_pStart++; - break; - } - if (ch != L'\"' && ch != L'\'') { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } else { - m_wQuotationMark = ch; - m_syntaxParserState = FDE_XmlSyntaxState::AttriValue; - m_pStart++; - } - break; - case FDE_XmlSyntaxState::AttriValue: - if (ch == m_wQuotationMark) { - if (m_iEntityStart > -1) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } - m_iTextDataLength = m_iDataLength; - m_wQuotationMark = 0; - m_BlockBuffer.Reset(); - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_pStart++; - m_syntaxParserState = FDE_XmlSyntaxState::AttriName; - syntaxParserResult = FDE_XmlSyntaxResult::AttriValue; - } else { - ParseTextChar(ch); - } - break; - case FDE_XmlSyntaxState::CloseInstruction: - if (ch != L'>') { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return FDE_XmlSyntaxResult::Error; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - m_syntaxParserState = FDE_XmlSyntaxState::TargetData; - } else if (m_iDataLength > 0) { - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - syntaxParserResult = FDE_XmlSyntaxResult::TargetData; - } else { - m_pStart++; - FDE_XMLNODE* pXMLNode = m_XMLNodeStack.GetTopElement(); - if (!pXMLNode) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } - m_XMLNodeStack.Pop(); - pXMLNode = m_XMLNodeStack.GetTopElement(); - if (pXMLNode) { - m_CurNode = *pXMLNode; - } else { - m_CurNode.iNodeNum = -1; - m_CurNode.eNodeType = FDE_XMLNODE_Unknown; - } - m_iCurrentNodeNum = m_CurNode.iNodeNum; - m_BlockBuffer.Reset(); - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_syntaxParserState = FDE_XmlSyntaxState::Text; - syntaxParserResult = FDE_XmlSyntaxResult::InstructionClose; - } - break; - case FDE_XmlSyntaxState::BreakElement: - if (ch == L'>') { - m_syntaxParserState = FDE_XmlSyntaxState::Text; - syntaxParserResult = FDE_XmlSyntaxResult::ElementBreak; - } else if (ch == L'/') { - m_syntaxParserState = FDE_XmlSyntaxState::CloseElement; - } else { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } - m_pStart++; - break; - case FDE_XmlSyntaxState::CloseElement: - if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) { - if (ch == L'>') { - FDE_XMLNODE* pXMLNode = m_XMLNodeStack.GetTopElement(); - if (!pXMLNode) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } - m_XMLNodeStack.Pop(); - pXMLNode = m_XMLNodeStack.GetTopElement(); - if (pXMLNode) { - m_CurNode = *pXMLNode; - } else { - m_CurNode.iNodeNum = -1; - m_CurNode.eNodeType = FDE_XMLNODE_Unknown; - } - m_iCurrentNodeNum = m_CurNode.iNodeNum; - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_syntaxParserState = FDE_XmlSyntaxState::Text; - syntaxParserResult = FDE_XmlSyntaxResult::ElementClose; - } else if (!FDE_IsXMLWhiteSpace(ch)) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } - } else { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return FDE_XmlSyntaxResult::Error; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - } - m_pStart++; - break; - case FDE_XmlSyntaxState::SkipCommentOrDecl: - if (FXSYS_wcsnicmp(m_pStart, L"--", 2) == 0) { - m_pStart += 2; - m_syntaxParserState = FDE_XmlSyntaxState::SkipComment; - } else if (FXSYS_wcsnicmp(m_pStart, L"[CDATA[", 7) == 0) { - m_pStart += 7; - m_syntaxParserState = FDE_XmlSyntaxState::SkipCData; - } else { - m_syntaxParserState = FDE_XmlSyntaxState::SkipDeclNode; - m_SkipChar = L'>'; - m_SkipStack.Push(L'>'); - } - break; - case FDE_XmlSyntaxState::SkipCData: { - if (FXSYS_wcsnicmp(m_pStart, L"]]>", 3) == 0) { - m_pStart += 3; - syntaxParserResult = FDE_XmlSyntaxResult::CData; - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_syntaxParserState = FDE_XmlSyntaxState::Text; - } else { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) - return FDE_XmlSyntaxResult::Error; - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - m_pStart++; - } - break; - } - case FDE_XmlSyntaxState::SkipDeclNode: - if (m_SkipChar == L'\'' || m_SkipChar == L'\"') { - m_pStart++; - if (ch != m_SkipChar) - break; - - m_SkipStack.Pop(); - uint32_t* pDWord = m_SkipStack.GetTopElement(); - if (!pDWord) - m_syntaxParserState = FDE_XmlSyntaxState::Text; - else - m_SkipChar = (FX_WCHAR)*pDWord; - } else { - switch (ch) { - case L'<': - m_SkipChar = L'>'; - m_SkipStack.Push(L'>'); - break; - case L'[': - m_SkipChar = L']'; - m_SkipStack.Push(L']'); - break; - case L'(': - m_SkipChar = L')'; - m_SkipStack.Push(L')'); - break; - case L'\'': - m_SkipChar = L'\''; - m_SkipStack.Push(L'\''); - break; - case L'\"': - m_SkipChar = L'\"'; - m_SkipStack.Push(L'\"'); - break; - default: - if (ch == m_SkipChar) { - m_SkipStack.Pop(); - uint32_t* pDWord = m_SkipStack.GetTopElement(); - if (!pDWord) { - if (m_iDataLength >= 9) { - CFX_WideString wsHeader; - m_BlockBuffer.GetTextData(wsHeader, 0, 7); - } - m_iTextDataLength = m_iDataLength; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_syntaxParserState = FDE_XmlSyntaxState::Text; - } else { - m_SkipChar = static_cast<FX_WCHAR>(*pDWord); - } - } - break; - } - if (m_SkipStack.GetSize() > 0) { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return FDE_XmlSyntaxResult::Error; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - } - m_pStart++; - } - break; - case FDE_XmlSyntaxState::SkipComment: - if (FXSYS_wcsnicmp(m_pStart, L"-->", 3) == 0) { - m_pStart += 2; - m_syntaxParserState = FDE_XmlSyntaxState::Text; - } - - m_pStart++; - break; - case FDE_XmlSyntaxState::TargetData: - if (FDE_IsXMLWhiteSpace(ch)) { - if (m_iDataLength < 1) { - m_pStart++; - break; - } else if (m_wQuotationMark == 0) { - m_iTextDataLength = m_iDataLength; - m_wQuotationMark = 0; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_pStart++; - syntaxParserResult = FDE_XmlSyntaxResult::TargetData; - break; - } - } - if (ch == '?') { - m_syntaxParserState = FDE_XmlSyntaxState::CloseInstruction; - m_pStart++; - } else if (ch == '\"') { - if (m_wQuotationMark == 0) { - m_wQuotationMark = ch; - m_pStart++; - } else if (ch == m_wQuotationMark) { - m_iTextDataLength = m_iDataLength; - m_wQuotationMark = 0; - m_BlockBuffer.Reset(); - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_pStart++; - syntaxParserResult = FDE_XmlSyntaxResult::TargetData; - } else { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - return m_syntaxParserResult; - } - } else { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = - m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return FDE_XmlSyntaxResult::Error; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = ch; - m_iDataLength++; - m_pStart++; - } - break; - default: - break; - } - if (syntaxParserResult != FDE_XmlSyntaxResult::None) - return syntaxParserResult; - } - } - return FDE_XmlSyntaxResult::Text; -} - -CFDE_XMLSyntaxParser::~CFDE_XMLSyntaxParser() { - m_pCurrentBlock = nullptr; - FX_Free(m_pBuffer); -} - -int32_t CFDE_XMLSyntaxParser::GetStatus() const { - if (!m_pStream) - return -1; - - int32_t iStreamLength = m_pStream->GetLength(); - if (iStreamLength < 1) - return 100; - - if (m_syntaxParserResult == FDE_XmlSyntaxResult::Error) - return -1; - - if (m_syntaxParserResult == FDE_XmlSyntaxResult::EndOfString) - return 100; - return m_iParsedBytes * 100 / iStreamLength; -} - -static int32_t FX_GetUTF8EncodeLength(const FX_WCHAR* pSrc, int32_t iSrcLen) { - uint32_t unicode = 0; - int32_t iDstNum = 0; - while (iSrcLen-- > 0) { - unicode = *pSrc++; - int nbytes = 0; - if ((uint32_t)unicode < 0x80) { - nbytes = 1; - } else if ((uint32_t)unicode < 0x800) { - nbytes = 2; - } else if ((uint32_t)unicode < 0x10000) { - nbytes = 3; - } else if ((uint32_t)unicode < 0x200000) { - nbytes = 4; - } else if ((uint32_t)unicode < 0x4000000) { - nbytes = 5; - } else { - nbytes = 6; - } - iDstNum += nbytes; - } - return iDstNum; -} - -FX_FILESIZE CFDE_XMLSyntaxParser::GetCurrentBinaryPos() const { - if (!m_pStream) - return 0; - - int32_t nSrcLen = m_pStart - m_pBuffer; - int32_t nDstLen = FX_GetUTF8EncodeLength(m_pBuffer, nSrcLen); - return m_iParsedBytes + nDstLen; -} - -void CFDE_XMLSyntaxParser::ParseTextChar(FX_WCHAR character) { - if (m_iIndexInBlock == m_iAllocStep) { - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - if (!m_pCurrentBlock) { - return; - } - } - m_pCurrentBlock[m_iIndexInBlock++] = character; - m_iDataLength++; - if (m_iEntityStart > -1 && character == L';') { - CFX_WideString csEntity; - m_BlockBuffer.GetTextData(csEntity, m_iEntityStart + 1, - (m_iDataLength - 1) - m_iEntityStart - 1); - int32_t iLen = csEntity.GetLength(); - if (iLen > 0) { - if (csEntity[0] == L'#') { - uint32_t ch = 0; - FX_WCHAR w; - if (iLen > 1 && csEntity[1] == L'x') { - for (int32_t i = 2; i < iLen; i++) { - w = csEntity[i]; - if (w >= L'0' && w <= L'9') { - ch = (ch << 4) + w - L'0'; - } else if (w >= L'A' && w <= L'F') { - ch = (ch << 4) + w - 55; - } else if (w >= L'a' && w <= L'f') { - ch = (ch << 4) + w - 87; - } else { - break; - } - } - } else { - for (int32_t i = 1; i < iLen; i++) { - w = csEntity[i]; - if (w < L'0' || w > L'9') - break; - ch = ch * 10 + w - L'0'; - } - } - if (ch > kMaxCharRange) - ch = ' '; - - character = static_cast<FX_WCHAR>(ch); - if (character != 0) { - m_BlockBuffer.SetTextChar(m_iEntityStart, character); - m_iEntityStart++; - } - } else { - if (csEntity.Compare(L"amp") == 0) { - m_BlockBuffer.SetTextChar(m_iEntityStart, L'&'); - m_iEntityStart++; - } else if (csEntity.Compare(L"lt") == 0) { - m_BlockBuffer.SetTextChar(m_iEntityStart, L'<'); - m_iEntityStart++; - } else if (csEntity.Compare(L"gt") == 0) { - m_BlockBuffer.SetTextChar(m_iEntityStart, L'>'); - m_iEntityStart++; - } else if (csEntity.Compare(L"apos") == 0) { - m_BlockBuffer.SetTextChar(m_iEntityStart, L'\''); - m_iEntityStart++; - } else if (csEntity.Compare(L"quot") == 0) { - m_BlockBuffer.SetTextChar(m_iEntityStart, L'\"'); - m_iEntityStart++; - } - } - } - m_BlockBuffer.DeleteTextChars(m_iDataLength - m_iEntityStart, false); - m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); - m_iEntityStart = -1; - } else { - if (m_iEntityStart < 0 && character == L'&') { - m_iEntityStart = m_iDataLength - 1; - } - } - m_pStart++; -} diff --git a/xfa/fde/xml/fde_xml_imp.h b/xfa/fde/xml/fde_xml_imp.h deleted file mode 100644 index 41e84bad17bcb9a51d14e1cff88893b9681b24ac..0000000000000000000000000000000000000000 --- a/xfa/fde/xml/fde_xml_imp.h +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FDE_XML_FDE_XML_IMP_H_ -#define XFA_FDE_XML_FDE_XML_IMP_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/xml/fde_xml.h" -#include "xfa/fgas/crt/fgas_stream.h" -#include "xfa/fgas/crt/fgas_utils.h" - -class CFDE_BlockBuffer; -class CFDE_XMLInstruction; -class CFDE_XMLElement; -class CFDE_XMLText; -class CFDE_XMLDoc; -class CFDE_XMLDOMParser; -class CFDE_XMLSyntaxParser; -class IFDE_XMLParser; - -class CFDE_XMLNode { - public: - enum NodeItem { - Root = 0, - Parent, - FirstSibling, - PriorSibling, - NextSibling, - LastSibling, - FirstNeighbor, - PriorNeighbor, - NextNeighbor, - LastNeighbor, - FirstChild, - LastChild - }; - - CFDE_XMLNode(); - virtual ~CFDE_XMLNode(); - - virtual FDE_XMLNODETYPE GetType() const; - virtual CFDE_XMLNode* Clone(bool bRecursive); - - int32_t CountChildNodes() const; - CFDE_XMLNode* GetChildNode(int32_t index) const; - int32_t GetChildNodeIndex(CFDE_XMLNode* pNode) const; - int32_t InsertChildNode(CFDE_XMLNode* pNode, int32_t index = -1); - void RemoveChildNode(CFDE_XMLNode* pNode); - void DeleteChildren(); - void CloneChildren(CFDE_XMLNode* pClone); - - CFDE_XMLNode* GetPath(const FX_WCHAR* pPath, - int32_t iLength = -1, - bool bQualifiedName = true) const; - - int32_t GetNodeLevel() const; - CFDE_XMLNode* GetNodeItem(CFDE_XMLNode::NodeItem eItem) const; - bool InsertNodeItem(CFDE_XMLNode::NodeItem eItem, CFDE_XMLNode* pNode); - CFDE_XMLNode* RemoveNodeItem(CFDE_XMLNode::NodeItem eItem); - - void SaveXMLNode(const CFX_RetainPtr<IFGAS_Stream>& pXMLStream); - - CFDE_XMLNode* m_pParent; - CFDE_XMLNode* m_pChild; - CFDE_XMLNode* m_pPrior; - CFDE_XMLNode* m_pNext; -}; - -class CFDE_XMLInstruction : public CFDE_XMLNode { - public: - explicit CFDE_XMLInstruction(const CFX_WideString& wsTarget); - ~CFDE_XMLInstruction() override; - - // CFDE_XMLNode - FDE_XMLNODETYPE GetType() const override; - CFDE_XMLNode* Clone(bool bRecursive) override; - - void GetTargetName(CFX_WideString& wsTarget) const { wsTarget = m_wsTarget; } - int32_t CountAttributes() const; - bool GetAttribute(int32_t index, - CFX_WideString& wsAttriName, - CFX_WideString& wsAttriValue) const; - bool HasAttribute(const FX_WCHAR* pwsAttriName) const; - void GetString(const FX_WCHAR* pwsAttriName, - CFX_WideString& wsAttriValue, - const FX_WCHAR* pwsDefValue = nullptr) const; - void SetString(const CFX_WideString& wsAttriName, - const CFX_WideString& wsAttriValue); - int32_t GetInteger(const FX_WCHAR* pwsAttriName, int32_t iDefValue = 0) const; - void SetInteger(const FX_WCHAR* pwsAttriName, int32_t iAttriValue); - FX_FLOAT GetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fDefValue = 0) const; - void SetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fAttriValue); - void RemoveAttribute(const FX_WCHAR* pwsAttriName); - int32_t CountData() const; - bool GetData(int32_t index, CFX_WideString& wsData) const; - void AppendData(const CFX_WideString& wsData); - void RemoveData(int32_t index); - - CFX_WideString m_wsTarget; - std::vector<CFX_WideString> m_Attributes; - std::vector<CFX_WideString> m_TargetData; -}; - -class CFDE_XMLElement : public CFDE_XMLNode { - public: - explicit CFDE_XMLElement(const CFX_WideString& wsTag); - ~CFDE_XMLElement() override; - - // CFDE_XMLNode - FDE_XMLNODETYPE GetType() const override; - CFDE_XMLNode* Clone(bool bRecursive) override; - - void GetTagName(CFX_WideString& wsTag) const; - void GetLocalTagName(CFX_WideString& wsTag) const; - - void GetNamespacePrefix(CFX_WideString& wsPrefix) const; - void GetNamespaceURI(CFX_WideString& wsNamespace) const; - - int32_t CountAttributes() const; - bool GetAttribute(int32_t index, - CFX_WideString& wsAttriName, - CFX_WideString& wsAttriValue) const; - bool HasAttribute(const FX_WCHAR* pwsAttriName) const; - void RemoveAttribute(const FX_WCHAR* pwsAttriName); - - void GetString(const FX_WCHAR* pwsAttriName, - CFX_WideString& wsAttriValue, - const FX_WCHAR* pwsDefValue = nullptr) const; - void SetString(const CFX_WideString& wsAttriName, - const CFX_WideString& wsAttriValue); - - int32_t GetInteger(const FX_WCHAR* pwsAttriName, int32_t iDefValue = 0) const; - void SetInteger(const FX_WCHAR* pwsAttriName, int32_t iAttriValue); - - FX_FLOAT GetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fDefValue = 0) const; - void SetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fAttriValue); - - void GetTextData(CFX_WideString& wsText) const; - void SetTextData(const CFX_WideString& wsText); - - CFX_WideString m_wsTag; - std::vector<CFX_WideString> m_Attributes; -}; - -class CFDE_XMLText : public CFDE_XMLNode { - public: - explicit CFDE_XMLText(const CFX_WideString& wsText); - ~CFDE_XMLText() override; - - // CFDE_XMLNode - FDE_XMLNODETYPE GetType() const override; - CFDE_XMLNode* Clone(bool bRecursive) override; - - void GetText(CFX_WideString& wsText) const { wsText = m_wsText; } - void SetText(const CFX_WideString& wsText) { m_wsText = wsText; } - - CFX_WideString m_wsText; -}; - -class CFDE_XMLDeclaration : public CFDE_XMLNode { - public: - CFDE_XMLDeclaration() {} - ~CFDE_XMLDeclaration() override {} -}; - -class CFDE_XMLCharData : public CFDE_XMLDeclaration { - public: - explicit CFDE_XMLCharData(const CFX_WideString& wsCData); - ~CFDE_XMLCharData() override; - - FDE_XMLNODETYPE GetType() const override; - CFDE_XMLNode* Clone(bool bRecursive) override; - - void GetCharData(CFX_WideString& wsCharData) const { - wsCharData = m_wsCharData; - } - void SetCharData(const CFX_WideString& wsCData) { m_wsCharData = wsCData; } - - CFX_WideString m_wsCharData; -}; - -class CFDE_XMLDoc { - public: - CFDE_XMLDoc(); - ~CFDE_XMLDoc(); - - bool LoadXML(std::unique_ptr<IFDE_XMLParser> pXMLParser); - int32_t DoLoad(IFX_Pause* pPause = nullptr); - void CloseXML(); - CFDE_XMLNode* GetRoot() const { return m_pRoot; } - void SaveXML(CFX_RetainPtr<IFGAS_Stream>& pXMLStream, bool bSaveBOM = true); - void SaveXMLNode(const CFX_RetainPtr<IFGAS_Stream>& pXMLStream, - CFDE_XMLNode* pNode); - - protected: - void Reset(bool bInitRoot); - void ReleaseParser(); - - CFX_RetainPtr<IFGAS_Stream> m_pStream; - int32_t m_iStatus; - CFDE_XMLNode* m_pRoot; - std::unique_ptr<IFDE_XMLParser> m_pXMLParser; -}; - -class IFDE_XMLParser { - public: - virtual ~IFDE_XMLParser() {} - virtual int32_t DoParser(IFX_Pause* pPause) = 0; -}; - -class CFDE_BlockBuffer { - public: - explicit CFDE_BlockBuffer(int32_t iAllocStep = 1024 * 1024); - ~CFDE_BlockBuffer(); - - bool InitBuffer(int32_t iBufferSize = 1024 * 1024); - bool IsInitialized() { return m_iBufferSize / m_iAllocStep >= 1; } - FX_WCHAR* GetAvailableBlock(int32_t& iIndexInBlock); - inline int32_t GetAllocStep() const { return m_iAllocStep; } - inline int32_t& GetDataLengthRef() { return m_iDataLength; } - inline void Reset(bool bReserveData = true) { - if (!bReserveData) { - m_iStartPosition = 0; - } - m_iDataLength = 0; - } - void SetTextChar(int32_t iIndex, FX_WCHAR ch); - int32_t DeleteTextChars(int32_t iCount, bool bDirection = true); - void GetTextData(CFX_WideString& wsTextData, - int32_t iStart = 0, - int32_t iLength = -1) const; - - protected: - inline void TextDataIndex2BufIndex(const int32_t iIndex, - int32_t& iBlockIndex, - int32_t& iInnerIndex) const; - void ClearBuffer(); - - CFX_ArrayTemplate<FX_WCHAR*> m_BlockArray; - int32_t m_iDataLength; - int32_t m_iBufferSize; - int32_t m_iAllocStep; - int32_t m_iStartPosition; -}; - -class CFDE_XMLSyntaxParser { - public: - CFDE_XMLSyntaxParser(); - ~CFDE_XMLSyntaxParser(); - - void Init(const CFX_RetainPtr<IFGAS_Stream>& pStream, - int32_t iXMLPlaneSize, - int32_t iTextDataSize = 256); - - FDE_XmlSyntaxResult DoSyntaxParse(); - - int32_t GetStatus() const; - int32_t GetCurrentPos() const { - return m_iParsedChars + (m_pStart - m_pBuffer); - } - FX_FILESIZE GetCurrentBinaryPos() const; - int32_t GetCurrentNodeNumber() const { return m_iCurrentNodeNum; } - int32_t GetLastNodeNumber() const { return m_iLastNodeNum; } - - void GetTargetName(CFX_WideString& wsTarget) const { - m_BlockBuffer.GetTextData(wsTarget, 0, m_iTextDataLength); - } - void GetTagName(CFX_WideString& wsTag) const { - m_BlockBuffer.GetTextData(wsTag, 0, m_iTextDataLength); - } - void GetAttributeName(CFX_WideString& wsAttriName) const { - m_BlockBuffer.GetTextData(wsAttriName, 0, m_iTextDataLength); - } - void GetAttributeValue(CFX_WideString& wsAttriValue) const { - m_BlockBuffer.GetTextData(wsAttriValue, 0, m_iTextDataLength); - } - void GetTextData(CFX_WideString& wsText) const { - m_BlockBuffer.GetTextData(wsText, 0, m_iTextDataLength); - } - void GetTargetData(CFX_WideString& wsData) const { - m_BlockBuffer.GetTextData(wsData, 0, m_iTextDataLength); - } - - protected: - enum class FDE_XmlSyntaxState { - Text, - Node, - Target, - Tag, - AttriName, - AttriEqualSign, - AttriQuotation, - AttriValue, - Entity, - EntityDecimal, - EntityHex, - CloseInstruction, - BreakElement, - CloseElement, - SkipDeclNode, - DeclCharData, - SkipComment, - SkipCommentOrDecl, - SkipCData, - TargetData - }; - - void ParseTextChar(FX_WCHAR ch); - - CFX_RetainPtr<IFGAS_Stream> m_pStream; - int32_t m_iXMLPlaneSize; - int32_t m_iCurrentPos; - int32_t m_iCurrentNodeNum; - int32_t m_iLastNodeNum; - int32_t m_iParsedChars; - int32_t m_iParsedBytes; - FX_WCHAR* m_pBuffer; - int32_t m_iBufferChars; - bool m_bEOS; - FX_WCHAR* m_pStart; - FX_WCHAR* m_pEnd; - FDE_XMLNODE m_CurNode; - CFX_StackTemplate<FDE_XMLNODE> m_XMLNodeStack; - CFDE_BlockBuffer m_BlockBuffer; - int32_t m_iAllocStep; - int32_t& m_iDataLength; - FX_WCHAR* m_pCurrentBlock; - int32_t m_iIndexInBlock; - int32_t m_iTextDataLength; - FDE_XmlSyntaxResult m_syntaxParserResult; - FDE_XmlSyntaxState m_syntaxParserState; - FX_WCHAR m_wQuotationMark; - int32_t m_iEntityStart; - CFX_StackTemplate<uint32_t> m_SkipStack; - FX_WCHAR m_SkipChar; -}; - -#endif // XFA_FDE_XML_FDE_XML_IMP_H_ diff --git a/xfa/fde/xml/fde_xml_imp_unittest.cpp b/xfa/fde/xml/fde_xml_imp_unittest.cpp deleted file mode 100644 index 6db1b1905af93cdd99c7d5926711f5096ca50479..0000000000000000000000000000000000000000 --- a/xfa/fde/xml/fde_xml_imp_unittest.cpp +++ /dev/null @@ -1,632 +0,0 @@ -// Copyright 2016 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. - -#include "xfa/fde/xml/fde_xml_imp.h" - -#include <memory> - -#include "testing/gtest/include/gtest/gtest.h" -#include "xfa/fgas/crt/fgas_stream.h" - -TEST(CFDE_XMLSyntaxParser, CData) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <![CDATA[\n" - L" if (a[1] < 3)\n" - L" app.alert(\"Tclams\");\n" - L" ]]>\n" - L"</script>"; - - const FX_WCHAR* cdata = - L"\n" - L" if (a[1] < 3)\n" - L" app.alert(\"Tclams\");\n" - L" "; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::CData, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(cdata, data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, CDataWithInnerScript) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <![CDATA[\n" - L" if (a[1] < 3)\n" - L" app.alert(\"Tclams\");\n" - L" </script>\n" - L" ]]>\n" - L"</script>"; - - const FX_WCHAR* cdata = - L"\n" - L" if (a[1] < 3)\n" - L" app.alert(\"Tclams\");\n" - L" </script>\n" - L" "; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::CData, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(cdata, data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, ArrowBangArrow) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <!>\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, ArrowBangBracketArrow) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <![>\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - // Parser walks to end of input. - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, IncompleteCData) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <![CDATA>\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - // Parser walks to end of input. - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, UnClosedCData) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <![CDATA[\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - // Parser walks to end of input. - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, EmptyCData) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <![CDATA[]]>\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::CData, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, Comment) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <!-- A Comment -->\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, IncorrectCommentStart) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <!- A Comment -->\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, CommentEmpty) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <!---->\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, CommentThreeDash) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <!--->\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, CommentTwoDash) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">\n" - L" <!-->\n" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"\n ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, Entities) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">" - L"B" - L"T" - L"H" - L"ꭈ" - L"�" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L"BTH\xab48", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, EntityOverflowHex) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">" - L"�" - L"�" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L" ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} - -TEST(CFDE_XMLSyntaxParser, EntityOverflowDecimal) { - const FX_WCHAR* input = - L"<script contentType=\"application/x-javascript\">" - L"�" - L"�" - L"</script>"; - - // We * sizeof(FX_WCHAR) because we pass in the uint8_t, not the FX_WCHAR. - size_t len = FXSYS_wcslen(input) * sizeof(FX_WCHAR); - CFX_RetainPtr<IFGAS_Stream> stream = IFGAS_Stream::CreateStream( - reinterpret_cast<uint8_t*>(const_cast<FX_WCHAR*>(input)), len, 0); - CFDE_XMLSyntaxParser parser; - parser.Init(stream, 256); - EXPECT_EQ(FDE_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); - - CFX_WideString data; - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::AttriName, parser.DoSyntaxParse()); - parser.GetAttributeName(data); - EXPECT_EQ(L"contentType", data); - EXPECT_EQ(FDE_XmlSyntaxResult::AttriValue, parser.DoSyntaxParse()); - parser.GetAttributeValue(data); - EXPECT_EQ(L"application/x-javascript", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementBreak, parser.DoSyntaxParse()); - EXPECT_EQ(FDE_XmlSyntaxResult::Text, parser.DoSyntaxParse()); - parser.GetTextData(data); - EXPECT_EQ(L" ", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::ElementClose, parser.DoSyntaxParse()); - parser.GetTagName(data); - EXPECT_EQ(L"script", data); - - EXPECT_EQ(FDE_XmlSyntaxResult::EndOfString, parser.DoSyntaxParse()); -} diff --git a/xfa/fgas/README.md b/xfa/fgas/README.md new file mode 100644 index 0000000000000000000000000000000000000000..fb277e33c833ef92eba9338cef9aedef9bee9ff9 --- /dev/null +++ b/xfa/fgas/README.md @@ -0,0 +1 @@ +xfa/fgas contains utility classes used by XFA. diff --git a/xfa/fgas/crt/cfgas_formatstring.cpp b/xfa/fgas/crt/cfgas_formatstring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8f6eeefca387064606887c89639e48f1ec6269a --- /dev/null +++ b/xfa/fgas/crt/cfgas_formatstring.cpp @@ -0,0 +1,2345 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/crt/cfgas_formatstring.h" + +#include <algorithm> +#include <vector> + +#include "core/fxcrt/cfx_decimal.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cxml_element.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 + +#define FX_NUMSTYLE_Percent 0x01 +#define FX_NUMSTYLE_Exponent 0x02 +#define FX_NUMSTYLE_DotVorv 0x04 + +namespace { + +struct FX_LOCALESUBCATEGORYINFO { + uint32_t uHash; + const wchar_t* pName; + int32_t eSubCategory; +}; + +const FX_LOCALESUBCATEGORYINFO g_FXLocaleDateTimeSubCatData[] = { + {0x14da2125, L"default", FX_LOCALEDATETIMESUBCATEGORY_Default}, + {0x9041d4b0, L"short", FX_LOCALEDATETIMESUBCATEGORY_Short}, + {0xa084a381, L"medium", FX_LOCALEDATETIMESUBCATEGORY_Medium}, + {0xcdce56b3, L"full", FX_LOCALEDATETIMESUBCATEGORY_Full}, + {0xf6b4afb0, L"long", FX_LOCALEDATETIMESUBCATEGORY_Long}, +}; +const int32_t g_iFXLocaleDateTimeSubCatCount = + sizeof(g_FXLocaleDateTimeSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO); + +const FX_LOCALESUBCATEGORYINFO g_FXLocaleNumSubCatData[] = { + {0x46f95531, L"percent", FX_LOCALENUMPATTERN_Percent}, + {0x4c4e8acb, L"currency", FX_LOCALENUMPATTERN_Currency}, + {0x54034c2f, L"decimal", FX_LOCALENUMPATTERN_Decimal}, + {0x7568e6ae, L"integer", FX_LOCALENUMPATTERN_Integer}, +}; +const int32_t g_iFXLocaleNumSubCatCount = + sizeof(g_FXLocaleNumSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO); + +struct FX_LOCALETIMEZONEINFO { + const wchar_t* name; + int16_t iHour; + int16_t iMinute; +}; + +const FX_LOCALETIMEZONEINFO g_FXLocaleTimeZoneData[] = { + {L"CDT", -5, 0}, {L"CST", -6, 0}, {L"EDT", -4, 0}, {L"EST", -5, 0}, + {L"MDT", -6, 0}, {L"MST", -7, 0}, {L"PDT", -7, 0}, {L"PST", -8, 0}, +}; + +const wchar_t gs_wsTimeSymbols[] = L"hHkKMSFAzZ"; +const wchar_t gs_wsDateSymbols[] = L"DJMEeGgYwW"; +const wchar_t gs_wsConstChars[] = L",-:/. "; + +int32_t ParseTimeZone(const wchar_t* pStr, int32_t iLen, FX_TIMEZONE* tz) { + tz->tzHour = 0; + tz->tzMinute = 0; + if (iLen < 0) + return 0; + + int32_t iStart = 1; + int32_t iEnd = iStart + 2; + while (iStart < iLen && iStart < iEnd) + tz->tzHour = tz->tzHour * 10 + FXSYS_DecimalCharToInt(pStr[iStart++]); + + if (iStart < iLen && pStr[iStart] == ':') + iStart++; + + iEnd = iStart + 2; + while (iStart < iLen && iStart < iEnd) + tz->tzMinute = tz->tzMinute * 10 + FXSYS_DecimalCharToInt(pStr[iStart++]); + + if (pStr[0] == '-') + tz->tzHour = -tz->tzHour; + + return iStart; +} + +int32_t ConvertHex(int32_t iKeyValue, wchar_t ch) { + if (FXSYS_isHexDigit(ch)) + return iKeyValue * 16 + FXSYS_HexCharToInt(ch); + return iKeyValue; +} + +WideString GetLiteralText(const wchar_t* pStrPattern, + int32_t* iPattern, + int32_t iLenPattern) { + WideString wsOutput; + if (pStrPattern[*iPattern] != '\'') + return wsOutput; + + (*iPattern)++; + int32_t iQuote = 1; + while (*iPattern < iLenPattern) { + if (pStrPattern[*iPattern] == '\'') { + iQuote++; + if ((*iPattern + 1 >= iLenPattern) || + ((pStrPattern[*iPattern + 1] != '\'') && (iQuote % 2 == 0))) { + break; + } + iQuote++; + (*iPattern)++; + } else if (pStrPattern[*iPattern] == '\\' && + (*iPattern + 1 < iLenPattern) && + pStrPattern[*iPattern + 1] == 'u') { + int32_t iKeyValue = 0; + *iPattern += 2; + int32_t i = 0; + while (*iPattern < iLenPattern && i++ < 4) { + wchar_t ch = pStrPattern[(*iPattern)++]; + iKeyValue = ConvertHex(iKeyValue, ch); + } + if (iKeyValue != 0) + wsOutput += static_cast<wchar_t>(iKeyValue & 0x0000FFFF); + + continue; + } + wsOutput += pStrPattern[(*iPattern)++]; + } + return wsOutput; +} + +WideString GetLiteralTextReverse(const wchar_t* pStrPattern, + int32_t* iPattern) { + WideString wsOutput; + if (pStrPattern[*iPattern] != '\'') + return wsOutput; + + (*iPattern)--; + int32_t iQuote = 1; + while (*iPattern >= 0) { + if (pStrPattern[*iPattern] == '\'') { + iQuote++; + if (*iPattern - 1 >= 0 || + ((pStrPattern[*iPattern - 1] != '\'') && (iQuote % 2 == 0))) { + break; + } + iQuote++; + (*iPattern)--; + } else if (pStrPattern[*iPattern] == '\\' && + pStrPattern[*iPattern + 1] == 'u') { + (*iPattern)--; + int32_t iKeyValue = 0; + int32_t iLen = wsOutput.GetLength(); + int32_t i = 1; + for (; i < iLen && i < 5; i++) { + wchar_t ch = wsOutput[i]; + iKeyValue = ConvertHex(iKeyValue, ch); + } + if (iKeyValue != 0) { + wsOutput.Delete(0, i); + wsOutput = (wchar_t)(iKeyValue & 0x0000FFFF) + wsOutput; + } + continue; + } + wsOutput = pStrPattern[(*iPattern)--] + wsOutput; + } + return wsOutput; +} + +bool GetNumericDotIndex(const WideString& wsNum, + const WideString& wsDotSymbol, + int32_t* iDotIndex) { + int32_t ccf = 0; + int32_t iLenf = wsNum.GetLength(); + const wchar_t* pStr = wsNum.c_str(); + int32_t iLenDot = wsDotSymbol.GetLength(); + while (ccf < iLenf) { + if (pStr[ccf] == '\'') { + GetLiteralText(pStr, &ccf, iLenf); + } else if (ccf + iLenDot <= iLenf && + !wcsncmp(pStr + ccf, wsDotSymbol.c_str(), iLenDot)) { + *iDotIndex = ccf; + return true; + } + ccf++; + } + auto result = wsNum.Find('.'); + *iDotIndex = result.value_or(iLenf); + return result.has_value(); +} + +bool ExtractCountDigits(const wchar_t* str, + int len, + int count, + int* cc, + uint32_t* value) { + for (int i = count; i > 0; --i) { + if (*cc >= len) + return false; + if (!FXSYS_isDecimalDigit(str[*cc])) + return false; + *value = *value * 10 + FXSYS_DecimalCharToInt(str[(*cc)++]); + } + return true; +} + +bool ExtractCountDigitsWithOptional(const wchar_t* str, + int len, + int count, + int* cc, + uint32_t* value) { + if (!ExtractCountDigits(str, len, count, cc, value)) + return false; + ExtractCountDigits(str, len, 1, cc, value); + return true; +} + +bool ParseLocaleDate(const WideString& wsDate, + const WideString& wsDatePattern, + IFX_Locale* pLocale, + CFX_DateTime* datetime, + int32_t* cc) { + uint32_t year = 1900; + uint32_t month = 1; + uint32_t day = 1; + int32_t ccf = 0; + const wchar_t* str = wsDate.c_str(); + int32_t len = wsDate.GetLength(); + const wchar_t* strf = wsDatePattern.c_str(); + int32_t lenf = wsDatePattern.GetLength(); + WideStringView wsDateSymbols(gs_wsDateSymbols); + while (*cc < len && ccf < lenf) { + if (strf[ccf] == '\'') { + WideString wsLiteral = GetLiteralText(strf, &ccf, lenf); + int32_t iLiteralLen = wsLiteral.GetLength(); + if (*cc + iLiteralLen > len || + wcsncmp(str + *cc, wsLiteral.c_str(), iLiteralLen)) { + return false; + } + *cc += iLiteralLen; + ccf++; + continue; + } + if (!wsDateSymbols.Contains(strf[ccf])) { + if (strf[ccf] != str[*cc]) + return false; + (*cc)++; + ccf++; + continue; + } + + WideString symbol; + symbol.Reserve(4); + symbol += strf[ccf++]; + while (ccf < lenf && strf[ccf] == symbol[0]) + symbol += strf[ccf++]; + + if (symbol == L"D" || symbol == L"DD") { + day = 0; + if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &day)) + return false; + } else if (symbol == L"J") { + uint32_t val = 0; + ExtractCountDigits(str, len, 3, cc, &val); + } else if (symbol == L"M" || symbol == L"MM") { + month = 0; + if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &month)) + return false; + } else if (symbol == L"MMM" || symbol == L"MMMM") { + for (uint16_t i = 0; i < 12; i++) { + WideString wsMonthName = pLocale->GetMonthName(i, symbol == L"MMM"); + if (wsMonthName.IsEmpty()) + continue; + if (!wcsncmp(wsMonthName.c_str(), str + *cc, wsMonthName.GetLength())) { + *cc += wsMonthName.GetLength(); + month = i + 1; + break; + } + } + } else if (symbol == L"EEE" || symbol == L"EEEE") { + for (uint16_t i = 0; i < 7; i++) { + WideString wsDayName = pLocale->GetDayName(i, symbol == L"EEE"); + if (wsDayName.IsEmpty()) + continue; + if (!wcsncmp(wsDayName.c_str(), str + *cc, wsDayName.GetLength())) { + *cc += wsDayName.GetLength(); + break; + } + } + } else if (symbol == L"YY" || symbol == L"YYYY") { + if (*cc + pdfium::base::checked_cast<int32_t>(symbol.GetLength()) > len) + return false; + + year = 0; + if (!ExtractCountDigits(str, len, symbol.GetLength(), cc, &year)) + return false; + if (symbol == L"YY") { + if (year <= 29) + year += 2000; + else + year += 1900; + } + } else if (symbol == L"G") { + *cc += 2; + } else if (symbol == L"JJJ" || symbol == L"E" || symbol == L"e" || + symbol == L"w" || symbol == L"WW") { + *cc += symbol.GetLength(); + } + } + if (*cc < len) + return false; + + datetime->SetDate(year, month, day); + return !!(*cc); +} + +void ResolveZone(FX_TIMEZONE tzDiff, + IFX_Locale* pLocale, + uint32_t* wHour, + uint32_t* wMinute) { + int32_t iMinuteDiff = *wHour * 60 + *wMinute; + FX_TIMEZONE tzLocale = pLocale->GetTimeZone(); + iMinuteDiff += tzLocale.tzHour * 60 + + (tzLocale.tzHour < 0 ? -tzLocale.tzMinute : tzLocale.tzMinute); + iMinuteDiff -= tzDiff.tzHour * 60 + + (tzDiff.tzHour < 0 ? -tzDiff.tzMinute : tzDiff.tzMinute); + + iMinuteDiff %= 1440; + if (iMinuteDiff < 0) + iMinuteDiff += 1440; + + *wHour = iMinuteDiff / 60; + *wMinute = iMinuteDiff % 60; +} + +bool ParseLocaleTime(const WideString& wsTime, + const WideString& wsTimePattern, + IFX_Locale* pLocale, + CFX_DateTime* datetime, + int32_t* cc) { + uint32_t hour = 0; + uint32_t minute = 0; + uint32_t second = 0; + uint32_t millisecond = 0; + int32_t ccf = 0; + const wchar_t* str = wsTime.c_str(); + int len = wsTime.GetLength(); + const wchar_t* strf = wsTimePattern.c_str(); + int lenf = wsTimePattern.GetLength(); + bool bHasA = false; + bool bPM = false; + WideStringView wsTimeSymbols(gs_wsTimeSymbols); + while (*cc < len && ccf < lenf) { + if (strf[ccf] == '\'') { + WideString wsLiteral = GetLiteralText(strf, &ccf, lenf); + int32_t iLiteralLen = wsLiteral.GetLength(); + if (*cc + iLiteralLen > len || + wcsncmp(str + *cc, wsLiteral.c_str(), iLiteralLen)) { + return false; + } + *cc += iLiteralLen; + ccf++; + continue; + } + if (!wsTimeSymbols.Contains(strf[ccf])) { + if (strf[ccf] != str[*cc]) + return false; + (*cc)++; + ccf++; + continue; + } + + WideString symbol; + symbol.Reserve(4); + symbol += strf[ccf++]; + while (ccf < lenf && strf[ccf] == symbol[0]) + symbol += strf[ccf++]; + + if (symbol == L"k" || symbol == L"K" || symbol == L"h" || symbol == L"H") { + hour = 0; + if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &hour)) + return false; + if (symbol == L"K" && hour == 24) + hour = 0; + } else if (symbol == L"kk" || symbol == L"KK" || symbol == L"hh" || + symbol == L"HH") { + hour = 0; + if (!ExtractCountDigits(str, len, 2, cc, &hour)) + return false; + if (symbol == L"KK" && hour == 24) + hour = 0; + } else if (symbol == L"M") { + minute = 0; + if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &minute)) + return false; + } else if (symbol == L"MM") { + minute = 0; + if (!ExtractCountDigits(str, len, 2, cc, &minute)) + return false; + } else if (symbol == L"S") { + second = 0; + if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &second)) + return false; + } else if (symbol == L"SS") { + second = 0; + if (!ExtractCountDigits(str, len, 2, cc, &second)) + return false; + } else if (symbol == L"FFF") { + millisecond = 0; + if (!ExtractCountDigits(str, len, 3, cc, &millisecond)) + return false; + } else if (symbol == L"A") { + WideString wsAM = pLocale->GetMeridiemName(true); + WideString wsPM = pLocale->GetMeridiemName(false); + if ((*cc + pdfium::base::checked_cast<int32_t>(wsAM.GetLength()) <= + len) && + (WideStringView(str + *cc, wsAM.GetLength()) == wsAM)) { + *cc += wsAM.GetLength(); + bHasA = true; + } else if ((*cc + pdfium::base::checked_cast<int32_t>(wsPM.GetLength()) <= + len) && + (WideStringView(str + *cc, wsPM.GetLength()) == wsPM)) { + *cc += wsPM.GetLength(); + bHasA = true; + bPM = true; + } + } else if (symbol == L"Z") { + if (*cc + 3 > len) + continue; + + WideString tz(str[(*cc)++]); + tz += str[(*cc)++]; + tz += str[(*cc)++]; + if (tz == L"GMT") { + FX_TIMEZONE tzDiff; + tzDiff.tzHour = 0; + tzDiff.tzMinute = 0; + if (*cc < len && (str[*cc] == '-' || str[*cc] == '+')) + *cc += ParseTimeZone(str + *cc, len - *cc, &tzDiff); + + ResolveZone(tzDiff, pLocale, &hour, &minute); + } else { + // Search the timezone list. There are only 8 of them, so linear scan. + for (size_t i = 0; i < FX_ArraySize(g_FXLocaleTimeZoneData); ++i) { + const FX_LOCALETIMEZONEINFO& info = g_FXLocaleTimeZoneData[i]; + if (tz != info.name) + continue; + + hour += info.iHour; + minute += info.iHour > 0 ? info.iMinute : -info.iMinute; + break; + } + } + } else if (symbol == L"z") { + if (str[*cc] != 'Z') { + FX_TIMEZONE tzDiff; + *cc += ParseTimeZone(str + *cc, len - *cc, &tzDiff); + ResolveZone(tzDiff, pLocale, &hour, &minute); + } else { + (*cc)++; + } + } + } + if (bHasA) { + if (bPM) { + hour += 12; + if (hour == 24) + hour = 12; + } else { + if (hour == 12) + hour = 0; + } + } + datetime->SetTime(hour, minute, second, millisecond); + return !!(*cc); +} + +int32_t GetNumTrailingLimit(const WideString& wsFormat, + int iDotPos, + bool* bTrimTailZeros) { + if (iDotPos < 0) + return 0; + + int32_t iCount = wsFormat.GetLength(); + int32_t iTreading = 0; + for (iDotPos++; iDotPos < iCount; iDotPos++) { + wchar_t wc = wsFormat[iDotPos]; + if (wc == L'z' || wc == L'9' || wc == 'Z') { + iTreading++; + *bTrimTailZeros = wc != L'9'; + } + } + return iTreading; +} + +bool IsLeapYear(uint32_t year) { + return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; +} + +bool MonthHas30Days(uint32_t month) { + return month == 4 || month == 6 || month == 9 || month == 11; +} + +bool MonthHas31Days(uint32_t month) { + return month != 2 && !MonthHas30Days(month); +} + +// |month| is 1-based. e.g. 1 means January. +uint16_t GetSolarMonthDays(uint16_t year, uint16_t month) { + if (month == 2) + return FX_IsLeapYear(year) ? 29 : 28; + + return MonthHas30Days(month) ? 30 : 31; +} + +uint16_t GetWeekDay(uint16_t year, uint16_t month, uint16_t day) { + static const uint16_t month_day[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; + uint16_t nDays = + (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400; + nDays += month_day[month - 1] + day; + if (FX_IsLeapYear(year) && month > 2) + nDays++; + return nDays % 7; +} + +uint16_t GetWeekOfMonth(uint16_t year, uint16_t month, uint16_t day) { + uint16_t week_day = GetWeekDay(year, month, 1); + uint16_t week_index = 0; + week_index += day / 7; + day = day % 7; + if (week_day + day > 7) + week_index++; + return week_index; +} + +uint16_t GetWeekOfYear(uint16_t year, uint16_t month, uint16_t day) { + uint16_t nDays = 0; + for (uint16_t i = 1; i < month; i++) + nDays += GetSolarMonthDays(year, i); + + nDays += day; + uint16_t week_day = GetWeekDay(year, 1, 1); + uint16_t week_index = 1; + week_index += nDays / 7; + nDays = nDays % 7; + if (week_day + nDays > 7) + week_index++; + return week_index; +} + +WideString NumToString(size_t fmt_size, int32_t value) { + return WideString::Format( + fmt_size == 1 ? L"%d" : fmt_size == 2 ? L"%02d" : L"%03d", value); +} + +WideString DateFormat(const WideString& wsDatePattern, + IFX_Locale* pLocale, + const CFX_DateTime& datetime) { + WideString wsResult; + int32_t year = datetime.GetYear(); + uint8_t month = datetime.GetMonth(); + uint8_t day = datetime.GetDay(); + int32_t ccf = 0; + const wchar_t* strf = wsDatePattern.c_str(); + int32_t lenf = wsDatePattern.GetLength(); + WideStringView wsDateSymbols(gs_wsDateSymbols); + while (ccf < lenf) { + if (strf[ccf] == '\'') { + wsResult += GetLiteralText(strf, &ccf, lenf); + ccf++; + continue; + } + if (!wsDateSymbols.Contains(strf[ccf])) { + wsResult += strf[ccf++]; + continue; + } + + WideString symbol; + symbol.Reserve(4); + symbol += strf[ccf++]; + while (ccf < lenf && strf[ccf] == symbol[0]) + symbol += strf[ccf++]; + + if (symbol == L"D" || symbol == L"DD") { + wsResult += NumToString(symbol.GetLength(), day); + } else if (symbol == L"J" || symbol == L"JJJ") { + uint16_t nDays = 0; + for (int i = 1; i < month; i++) + nDays += GetSolarMonthDays(year, i); + nDays += day; + wsResult += NumToString(symbol.GetLength(), nDays); + } else if (symbol == L"M" || symbol == L"MM") { + wsResult += NumToString(symbol.GetLength(), month); + } else if (symbol == L"MMM" || symbol == L"MMMM") { + wsResult += pLocale->GetMonthName(month - 1, symbol == L"MMM"); + } else if (symbol == L"E" || symbol == L"e") { + uint16_t wWeekDay = GetWeekDay(year, month, day); + wsResult += NumToString( + 1, symbol == L"E" ? wWeekDay + 1 : (wWeekDay ? wWeekDay : 7)); + } else if (symbol == L"EEE" || symbol == L"EEEE") { + wsResult += + pLocale->GetDayName(GetWeekDay(year, month, day), symbol == L"EEE"); + } else if (symbol == L"G") { + wsResult += pLocale->GetEraName(year > 0); + } else if (symbol == L"YY") { + wsResult += NumToString(2, year % 100); + } else if (symbol == L"YYYY") { + wsResult += NumToString(1, year); + } else if (symbol == L"w") { + wsResult += NumToString(1, GetWeekOfMonth(year, month, day)); + } else if (symbol == L"WW") { + wsResult += NumToString(2, GetWeekOfYear(year, month, day)); + } + } + return wsResult; +} + +WideString TimeFormat(const WideString& wsTimePattern, + IFX_Locale* pLocale, + const CFX_DateTime& datetime) { + WideString wsResult; + uint8_t hour = datetime.GetHour(); + uint8_t minute = datetime.GetMinute(); + uint8_t second = datetime.GetSecond(); + uint16_t millisecond = datetime.GetMillisecond(); + int32_t ccf = 0; + const wchar_t* strf = wsTimePattern.c_str(); + int32_t lenf = wsTimePattern.GetLength(); + uint16_t wHour = hour; + bool bPM = false; + if (wsTimePattern.Contains('A')) { + if (wHour >= 12) + bPM = true; + } + + WideStringView wsTimeSymbols(gs_wsTimeSymbols); + while (ccf < lenf) { + if (strf[ccf] == '\'') { + wsResult += GetLiteralText(strf, &ccf, lenf); + ccf++; + continue; + } + if (!wsTimeSymbols.Contains(strf[ccf])) { + wsResult += strf[ccf++]; + continue; + } + + WideString symbol; + symbol.Reserve(4); + symbol += strf[ccf++]; + while (ccf < lenf && strf[ccf] == symbol[0]) + symbol += strf[ccf++]; + + if (symbol == L"h" || symbol == L"hh") { + if (wHour > 12) + wHour -= 12; + wsResult += NumToString(symbol.GetLength(), wHour == 0 ? 12 : wHour); + } else if (symbol == L"K" || symbol == L"KK") { + wsResult += NumToString(symbol.GetLength(), wHour == 0 ? 24 : wHour); + } else if (symbol == L"k" || symbol == L"kk") { + if (wHour > 12) + wHour -= 12; + wsResult += NumToString(symbol.GetLength(), wHour); + } else if (symbol == L"H" || symbol == L"HH") { + wsResult += NumToString(symbol.GetLength(), wHour); + } else if (symbol == L"M" || symbol == L"MM") { + wsResult += NumToString(symbol.GetLength(), minute); + } else if (symbol == L"S" || symbol == L"SS") { + wsResult += NumToString(symbol.GetLength(), second); + } else if (symbol == L"FFF") { + wsResult += NumToString(3, millisecond); + } else if (symbol == L"A") { + wsResult += pLocale->GetMeridiemName(!bPM); + } else if (symbol == L"Z" || symbol == L"z") { + if (symbol == L"Z") + wsResult += L"GMT"; + + FX_TIMEZONE tz = pLocale->GetTimeZone(); + if (tz.tzHour != 0 || tz.tzMinute != 0) { + wsResult += tz.tzHour < 0 ? L"-" : L"+"; + wsResult += + WideString::Format(L"%02d:%02d", abs(tz.tzHour), tz.tzMinute); + } + } + } + return wsResult; +} + +WideString FormatDateTimeInternal(const CFX_DateTime& dt, + const WideString& wsDatePattern, + const WideString& wsTimePattern, + bool bDateFirst, + IFX_Locale* pLocale) { + WideString wsDateOut; + if (!wsDatePattern.IsEmpty()) + wsDateOut = DateFormat(wsDatePattern, pLocale, dt); + + WideString wsTimeOut; + if (!wsTimePattern.IsEmpty()) + wsTimeOut = TimeFormat(wsTimePattern, pLocale, dt); + + return bDateFirst ? wsDateOut + wsTimeOut : wsTimeOut + wsDateOut; +} + +} // namespace + +bool FX_DateFromCanonical(const WideString& wsDate, CFX_DateTime* datetime) { + const wchar_t* str = wsDate.c_str(); + int len = wsDate.GetLength(); + if (len > 10) + return false; + + int cc = 0; + uint32_t year = 0; + if (!ExtractCountDigits(str, len, 4, &cc, &year)) + return false; + if (year < 1900) + return false; + if (cc >= len) { + datetime->SetDate(year, 1, 1); + return true; + } + + if (str[cc] == '-') + cc++; + + uint32_t month = 0; + if (!ExtractCountDigits(str, len, 2, &cc, &month)) + return false; + if (month > 12 || month < 1) + return false; + if (cc >= len) { + datetime->SetDate(year, month, 1); + return true; + } + + if (str[cc] == '-') + cc++; + + uint32_t day = 0; + if (!ExtractCountDigits(str, len, 2, &cc, &day)) + return false; + if (day < 1) + return false; + if ((MonthHas31Days(month) && day > 31) || + (MonthHas30Days(month) && day > 30)) { + return false; + } + if (month == 2 && day > (IsLeapYear(year) ? 29U : 28U)) + return false; + + datetime->SetDate(year, month, day); + return true; +} + +bool FX_TimeFromCanonical(const WideStringView& wsTime, + CFX_DateTime* datetime, + IFX_Locale* pLocale) { + if (wsTime.GetLength() == 0) + return false; + + const wchar_t* str = wsTime.unterminated_c_str(); + int len = wsTime.GetLength(); + + int cc = 0; + uint32_t hour = 0; + if (!ExtractCountDigits(str, len, 2, &cc, &hour)) + return false; + if (hour >= 24) + return false; + if (cc >= len) { + datetime->SetTime(hour, 0, 0, 0); + return true; + } + + if (str[cc] == ':') + cc++; + + uint32_t minute = 0; + if (!ExtractCountDigits(str, len, 2, &cc, &minute)) + return false; + if (minute >= 60) + return false; + + if (cc >= len) { + datetime->SetTime(hour, minute, 0, 0); + return true; + } + + if (str[cc] == ':') + cc++; + + uint32_t second = 0; + uint32_t millisecond = 0; + if (str[cc] != 'Z') { + if (!ExtractCountDigits(str, len, 2, &cc, &second)) + return false; + if (second >= 60) + return false; + if (cc < len && str[cc] == '.') { + cc++; + if (!ExtractCountDigits(str, len, 3, &cc, &millisecond)) + return false; + } + } + + // Skip until we find a + or - for the time zone. + while (cc < len) { + if (str[cc] == '+' || str[cc] == '-') + break; + ++cc; + } + + if (cc < len) { + FX_TIMEZONE tzDiff; + tzDiff.tzHour = 0; + tzDiff.tzMinute = 0; + if (str[cc] != 'Z') + cc += ParseTimeZone(str + cc, len - cc, &tzDiff); + + ResolveZone(tzDiff, pLocale, &hour, &minute); + } + + datetime->SetTime(hour, minute, second, millisecond); + return true; +} + +CFGAS_FormatString::CFGAS_FormatString(CXFA_LocaleMgr* pLocaleMgr) + : m_pLocaleMgr(pLocaleMgr) {} + +CFGAS_FormatString::~CFGAS_FormatString() {} + +void CFGAS_FormatString::SplitFormatString( + const WideString& wsFormatString, + std::vector<WideString>* wsPatterns) { + int32_t iStrLen = wsFormatString.GetLength(); + const wchar_t* pStr = wsFormatString.c_str(); + const wchar_t* pToken = pStr; + const wchar_t* pEnd = pStr + iStrLen; + bool iQuote = false; + while (true) { + if (pStr >= pEnd) { + wsPatterns->push_back(WideString(pToken, pStr - pToken)); + return; + } + if (*pStr == '\'') { + iQuote = !iQuote; + } else if (*pStr == L'|' && !iQuote) { + wsPatterns->push_back(WideString(pToken, pStr - pToken)); + pToken = pStr + 1; + } + pStr++; + } +} + +FX_LOCALECATEGORY CFGAS_FormatString::GetCategory(const WideString& wsPattern) { + FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown; + int32_t ccf = 0; + int32_t iLenf = wsPattern.GetLength(); + const wchar_t* pStr = wsPattern.c_str(); + bool bBraceOpen = false; + WideStringView wsConstChars(gs_wsConstChars); + while (ccf < iLenf) { + if (pStr[ccf] == '\'') { + GetLiteralText(pStr, &ccf, iLenf); + } else if (!bBraceOpen && !wsConstChars.Contains(pStr[ccf])) { + 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++; + } + + uint32_t dwHash = FX_HashCode_GetW(wsCategory.AsStringView(), false); + if (dwHash == FX_LOCALECATEGORY_DateTimeHash) + return FX_LOCALECATEGORY_DateTime; + if (dwHash == FX_LOCALECATEGORY_TextHash) + return FX_LOCALECATEGORY_Text; + if (dwHash == FX_LOCALECATEGORY_NumHash) + return FX_LOCALECATEGORY_Num; + if (dwHash == FX_LOCALECATEGORY_ZeroHash) + return FX_LOCALECATEGORY_Zero; + if (dwHash == FX_LOCALECATEGORY_NullHash) + return FX_LOCALECATEGORY_Null; + 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 (pStr[ccf] == '}') { + bBraceOpen = false; + } + ccf++; + } + return eCategory; +} + +WideString CFGAS_FormatString::GetTextFormat(const WideString& wsPattern, + const WideStringView& wsCategory) { + int32_t ccf = 0; + int32_t iLenf = wsPattern.GetLength(); + const wchar_t* pStr = wsPattern.c_str(); + bool bBrackOpen = false; + WideStringView wsConstChars(gs_wsConstChars); + WideString wsPurgePattern; + while (ccf < iLenf) { + if (pStr[ccf] == '\'') { + int32_t iCurChar = ccf; + GetLiteralText(pStr, &ccf, iLenf); + wsPurgePattern += WideStringView(pStr + iCurChar, ccf - iCurChar + 1); + } else if (!bBrackOpen && !wsConstChars.Contains(pStr[ccf])) { + 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++; + // Skip over the encoding name. + while (ccf < iLenf && pStr[ccf] != ')') + ccf++; + } else if (pStr[ccf] == '{') { + bBrackOpen = true; + break; + } + ccf++; + } + } else if (pStr[ccf] != '}') { + wsPurgePattern += pStr[ccf]; + } + ccf++; + } + if (!bBrackOpen) + wsPurgePattern = wsPattern; + + return wsPurgePattern; +} + +IFX_Locale* CFGAS_FormatString::GetNumericFormat(const WideString& wsPattern, + int32_t* iDotIndex, + uint32_t* dwStyle, + WideString* wsPurgePattern) { + *dwStyle = 0; + IFX_Locale* pLocale = nullptr; + int32_t ccf = 0; + int32_t iLenf = wsPattern.GetLength(); + const wchar_t* pStr = wsPattern.c_str(); + bool bFindDot = false; + bool bBrackOpen = false; + WideStringView wsConstChars(gs_wsConstChars); + while (ccf < iLenf) { + if (pStr[ccf] == '\'') { + int32_t iCurChar = ccf; + GetLiteralText(pStr, &ccf, iLenf); + *wsPurgePattern += WideStringView(pStr + iCurChar, ccf - iCurChar + 1); + } else if (!bBrackOpen && !wsConstChars.Contains(pStr[ccf])) { + WideString wsCategory(pStr[ccf]); + ccf++; + while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && + pStr[ccf] != '(') { + wsCategory += pStr[ccf]; + ccf++; + } + if (wsCategory != L"num") { + bBrackOpen = true; + ccf = 0; + continue; + } + while (ccf < iLenf) { + if (pStr[ccf] == '{') { + bBrackOpen = true; + break; + } + if (pStr[ccf] == '(') { + ccf++; + WideString wsLCID; + while (ccf < iLenf && pStr[ccf] != ')') + wsLCID += pStr[ccf++]; + + pLocale = m_pLocaleMgr->GetLocaleByName(wsLCID); + } else if (pStr[ccf] == '.') { + WideString wsSubCategory; + ccf++; + while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') + wsSubCategory += pStr[ccf++]; + + uint32_t dwSubHash = + FX_HashCode_GetW(wsSubCategory.AsStringView(), false); + FX_LOCALENUMSUBCATEGORY eSubCategory = FX_LOCALENUMPATTERN_Decimal; + for (int32_t i = 0; i < g_iFXLocaleNumSubCatCount; i++) { + if (g_FXLocaleNumSubCatData[i].uHash == dwSubHash) { + eSubCategory = (FX_LOCALENUMSUBCATEGORY)g_FXLocaleNumSubCatData[i] + .eSubCategory; + break; + } + } + if (!pLocale) + pLocale = m_pLocaleMgr->GetDefLocale(); + + ASSERT(pLocale); + + wsSubCategory = pLocale->GetNumPattern(eSubCategory); + auto result = wsSubCategory.Find('.'); + if (result.has_value() && result.value() != 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; +} + +bool CFGAS_FormatString::ParseText(const WideString& wsSrcText, + const WideString& wsPattern, + WideString* wsValue) { + wsValue->clear(); + if (wsSrcText.IsEmpty() || wsPattern.IsEmpty()) + return false; + + WideString wsTextFormat = GetTextFormat(wsPattern, L"text"); + if (wsTextFormat.IsEmpty()) + return false; + + int32_t iText = 0; + int32_t iPattern = 0; + const wchar_t* pStrText = wsSrcText.c_str(); + int32_t iLenText = wsSrcText.GetLength(); + const wchar_t* pStrPattern = wsTextFormat.c_str(); + int32_t iLenPattern = wsTextFormat.GetLength(); + while (iPattern < iLenPattern && iText < iLenText) { + switch (pStrPattern[iPattern]) { + case '\'': { + WideString wsLiteral = + GetLiteralText(pStrPattern, &iPattern, iLenPattern); + int32_t iLiteralLen = wsLiteral.GetLength(); + if (iText + iLiteralLen > iLenText || + wcsncmp(pStrText + iText, wsLiteral.c_str(), iLiteralLen)) { + *wsValue = wsSrcText; + return false; + } + iText += iLiteralLen; + iPattern++; + break; + } + case 'A': + if (FXSYS_iswalpha(pStrText[iText])) { + *wsValue += pStrText[iText]; + iText++; + } + iPattern++; + break; + case 'X': + *wsValue += pStrText[iText]; + iText++; + iPattern++; + break; + case 'O': + case '0': + if (FXSYS_isDecimalDigit(pStrText[iText]) || + FXSYS_iswalpha(pStrText[iText])) { + *wsValue += pStrText[iText]; + iText++; + } + iPattern++; + break; + case '9': + if (FXSYS_isDecimalDigit(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; +} + +bool CFGAS_FormatString::ParseNum(const WideString& wsSrcNum, + const WideString& wsPattern, + WideString* wsValue) { + wsValue->clear(); + if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) + return false; + + int32_t dot_index_f = -1; + uint32_t dwFormatStyle = 0; + WideString wsNumFormat; + IFX_Locale* pLocale = + GetNumericFormat(wsPattern, &dot_index_f, &dwFormatStyle, &wsNumFormat); + if (!pLocale || wsNumFormat.IsEmpty()) + return false; + + int32_t iExponent = 0; + WideString wsDotSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); + WideString wsGroupSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping); + int32_t iGroupLen = wsGroupSymbol.GetLength(); + WideString wsMinus = pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus); + int32_t iMinusLen = wsMinus.GetLength(); + const wchar_t* str = wsSrcNum.c_str(); + int len = wsSrcNum.GetLength(); + const wchar_t* strf = wsNumFormat.c_str(); + int lenf = wsNumFormat.GetLength(); + bool bHavePercentSymbol = false; + bool bNeg = false; + bool bReverseParse = false; + int32_t dot_index = 0; + + // If we're looking for a '.', 'V' or 'v' and the input string does not + // have a dot index for one of those, then we disable parsing the decimal. + if (!GetNumericDotIndex(wsSrcNum, wsDotSymbol, &dot_index) && + (dwFormatStyle & FX_NUMSTYLE_DotVorv)) + bReverseParse = true; + + // This parse is broken into two parts based on the '.' in the number + // (or 'V' or 'v'). |dot_index_f| is the location of the dot in the format and + // |dot_index| is the location of the dot in the number. + // + // This first while() starts at the '.' and walks backwards to the start of + // the number. The second while() walks from the dot forwards to the end of + // the decimal. + + int ccf = dot_index_f - 1; + int cc = dot_index - 1; + while (ccf >= 0 && cc >= 0) { + switch (strf[ccf]) { + case '\'': { + WideString wsLiteral = GetLiteralTextReverse(strf, &ccf); + int32_t iLiteralLen = wsLiteral.GetLength(); + cc -= iLiteralLen - 1; + if (cc < 0 || wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) + return false; + + cc--; + ccf--; + break; + } + case '9': + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + wsValue->InsertAtFront(str[cc]); + cc--; + ccf--; + break; + case 'z': + case 'Z': + if (strf[ccf] == 'z' || str[cc] != ' ') { + if (FXSYS_isDecimalDigit(str[cc])) { + wsValue->InsertAtFront(str[cc]); + cc--; + } + } else { + cc--; + } + ccf--; + break; + case 'S': + case 's': + if (str[cc] == '+' || (strf[ccf] == 'S' && str[cc] == ' ')) { + cc--; + } else { + cc -= iMinusLen - 1; + if (cc < 0 || wcsncmp(str + cc, wsMinus.c_str(), iMinusLen)) + return false; + + cc--; + bNeg = true; + } + ccf--; + break; + case 'E': { + bool bExpSign = false; + while (cc >= 0) { + if (str[cc] == 'E' || str[cc] == 'e') + break; + if (FXSYS_isDecimalDigit(str[cc])) { + iExponent = iExponent + FXSYS_DecimalCharToInt(str[cc]) * 10; + cc--; + continue; + } + if (str[cc] == '+') { + cc--; + continue; + } + if (cc - iMinusLen + 1 > 0 && !wcsncmp(str + (cc - iMinusLen + 1), + wsMinus.c_str(), iMinusLen)) { + bExpSign = true; + cc -= iMinusLen; + continue; + } + + return false; + } + cc--; + iExponent = bExpSign ? -iExponent : iExponent; + ccf--; + break; + } + case '$': { + WideString wsSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol); + int32_t iSymbolLen = wsSymbol.GetLength(); + cc -= iSymbolLen - 1; + if (cc < 0 || wcsncmp(str + cc, wsSymbol.c_str(), iSymbolLen)) + return false; + + cc--; + ccf--; + break; + } + case 'r': + case 'R': + if (ccf - 1 >= 0 && ((strf[ccf] == 'R' && strf[ccf - 1] == 'C') || + (strf[ccf] == 'r' && strf[ccf - 1] == 'c'))) { + if (strf[ccf] == 'R' && str[cc] == ' ') { + cc -= 2; + } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { + bNeg = true; + cc -= 2; + } + ccf -= 2; + } else { + ccf--; + } + break; + case 'b': + case 'B': + if (ccf - 1 >= 0 && ((strf[ccf] == 'B' && strf[ccf - 1] == 'D') || + (strf[ccf] == 'b' && strf[ccf - 1] == 'd'))) { + if (strf[ccf] == 'B' && str[cc] == ' ') { + cc -= 2; + } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { + bNeg = true; + cc -= 2; + } + ccf -= 2; + } else { + ccf--; + } + break; + case '%': { + WideString wsSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent); + int32_t iSysmbolLen = wsSymbol.GetLength(); + cc -= iSysmbolLen - 1; + if (cc < 0 || wcsncmp(str + cc, wsSymbol.c_str(), iSysmbolLen)) + return false; + + cc--; + ccf--; + bHavePercentSymbol = true; + break; + } + case '.': + case 'V': + case 'v': + case '8': + return false; + case ',': { + if (cc >= 0) { + cc -= iGroupLen - 1; + if (cc >= 0 && + wcsncmp(str + cc, wsGroupSymbol.c_str(), iGroupLen) == 0) { + cc--; + } else { + cc += iGroupLen - 1; + } + } + ccf--; + break; + } + case '(': + case ')': + if (str[cc] == strf[ccf]) + 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 '\'': { + WideString wsLiteral = GetLiteralText(strf, &ccf, lenf); + int32_t iLiteralLen = wsLiteral.GetLength(); + if (cc + iLiteralLen > len || + wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { + return false; + } + cc += iLiteralLen; + ccf++; + break; + } + case '9': + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + *wsValue += str[cc]; + cc++; + ccf++; + break; + case 'z': + case 'Z': + if (strf[ccf] == 'z' || str[cc] != ' ') { + if (FXSYS_isDecimalDigit(str[cc])) { + *wsValue += str[cc]; + cc++; + } + } else { + cc++; + } + ccf++; + break; + case 'S': + case 's': + if (str[cc] == '+' || (strf[ccf] == 'S' && str[cc] == ' ')) { + cc++; + } else { + if (cc + iMinusLen > len || + wcsncmp(str + cc, wsMinus.c_str(), iMinusLen)) { + return false; + } + bNeg = true; + cc += iMinusLen; + } + ccf++; + break; + case 'E': { + if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) + return false; + + bool bExpSign = false; + cc++; + if (cc < len) { + if (str[cc] == '+') { + cc++; + } else if (str[cc] == '-') { + bExpSign = true; + cc++; + } + } + while (cc < len) { + if (!FXSYS_isDecimalDigit(str[cc])) + break; + + iExponent = iExponent * 10 + FXSYS_DecimalCharToInt(str[cc]); + cc++; + } + iExponent = bExpSign ? -iExponent : iExponent; + ccf++; + break; + } + case '$': { + WideString wsSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol); + int32_t iSymbolLen = wsSymbol.GetLength(); + if (cc + iSymbolLen > len || + wcsncmp(str + cc, wsSymbol.c_str(), iSymbolLen)) { + return false; + } + cc += iSymbolLen; + ccf++; + break; + } + case 'c': + case 'C': + if (ccf + 1 < lenf && ((strf[ccf] == 'C' && strf[ccf + 1] == 'R') || + (strf[ccf] == 'c' && strf[ccf + 1] == 'r'))) { + if (strf[ccf] == 'C' && str[cc] == ' ') { + cc++; + } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') { + bNeg = true; + cc += 2; + } + ccf += 2; + } + break; + case 'd': + case 'D': + if (ccf + 1 < lenf && ((strf[ccf] == 'D' && strf[ccf + 1] == 'B') || + (strf[ccf] == 'd' && strf[ccf + 1] == 'b'))) { + if (strf[ccf] == 'D' && 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 '%': { + WideString wsSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent); + int32_t iSysmbolLen = wsSymbol.GetLength(); + if (cc + iSysmbolLen <= len && + !wcsncmp(str + cc, wsSymbol.c_str(), iSysmbolLen)) { + cc += iSysmbolLen; + } + ccf++; + bHavePercentSymbol = true; + } break; + case '8': { + while (ccf < lenf && strf[ccf] == '8') + ccf++; + + while (cc < len && FXSYS_isDecimalDigit(str[cc])) { + *wsValue += str[cc]; + cc++; + } + } break; + case ',': { + if (cc + iGroupLen <= len && + wcsncmp(str + cc, wsGroupSymbol.c_str(), iGroupLen) == 0) { + cc += iGroupLen; + } + ccf++; + break; + } + case '(': + case ')': + if (str[cc] == strf[ccf]) + 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->AsStringView()); + if (iExponent) { + decimal = decimal * + CFX_Decimal(FXSYS_pow(10, static_cast<float>(iExponent)), 3); + } + if (bHavePercentSymbol) + decimal = decimal / CFX_Decimal(100); + + *wsValue = decimal; + } + if (bNeg) + wsValue->InsertAtFront(L'-'); + + return true; +} + +FX_DATETIMETYPE CFGAS_FormatString::GetDateTimeFormat( + const WideString& wsPattern, + IFX_Locale** pLocale, + WideString* wsDatePattern, + WideString* wsTimePattern) { + *pLocale = nullptr; + WideString wsTempPattern; + FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown; + int32_t ccf = 0; + int32_t iLenf = wsPattern.GetLength(); + const wchar_t* pStr = wsPattern.c_str(); + int32_t iFindCategory = 0; + bool bBraceOpen = false; + WideStringView wsConstChars(gs_wsConstChars); + while (ccf < iLenf) { + if (pStr[ccf] == '\'') { + int32_t iCurChar = ccf; + GetLiteralText(pStr, &ccf, iLenf); + wsTempPattern += WideStringView(pStr + iCurChar, ccf - iCurChar + 1); + } else if (!bBraceOpen && iFindCategory != 3 && + !wsConstChars.Contains(pStr[ccf])) { + 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 == L"date") { + iFindCategory |= 1; + eCategory = FX_LOCALECATEGORY_Date; + if (iFindCategory & 2) + iFindCategory = 4; + } else if (!(iFindCategory & 2) && wsCategory == L"time") { + iFindCategory |= 2; + eCategory = FX_LOCALECATEGORY_Time; + } else if (wsCategory == L"datetime") { + iFindCategory = 3; + eCategory = FX_LOCALECATEGORY_DateTime; + } else { + continue; + } + while (ccf < iLenf) { + if (pStr[ccf] == '{') { + bBraceOpen = true; + break; + } + if (pStr[ccf] == '(') { + ccf++; + WideString wsLCID; + while (ccf < iLenf && pStr[ccf] != ')') + wsLCID += pStr[ccf++]; + + *pLocale = m_pLocaleMgr->GetLocaleByName(wsLCID); + } else if (pStr[ccf] == '.') { + WideString wsSubCategory; + ccf++; + while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') + wsSubCategory += pStr[ccf++]; + + uint32_t dwSubHash = + FX_HashCode_GetW(wsSubCategory.AsStringView(), false); + FX_LOCALEDATETIMESUBCATEGORY eSubCategory = + FX_LOCALEDATETIMESUBCATEGORY_Medium; + for (int32_t 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(); + ASSERT(*pLocale); + + switch (eCategory) { + case FX_LOCALECATEGORY_Date: + *wsDatePattern = + wsTempPattern + (*pLocale)->GetDatePattern(eSubCategory); + break; + case FX_LOCALECATEGORY_Time: + *wsTimePattern = + wsTempPattern + (*pLocale)->GetTimePattern(eSubCategory); + break; + case FX_LOCALECATEGORY_DateTime: + *wsDatePattern = + wsTempPattern + (*pLocale)->GetDatePattern(eSubCategory); + *wsTimePattern = (*pLocale)->GetTimePattern(eSubCategory); + break; + default: + break; + } + wsTempPattern.clear(); + 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.clear(); + } + } 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->clear(); + *wsDatePattern = wsPattern; + } + return (FX_DATETIMETYPE)iFindCategory; +} + +bool CFGAS_FormatString::ParseDateTime(const WideString& wsSrcDateTime, + const WideString& wsPattern, + FX_DATETIMETYPE eDateTimeType, + CFX_DateTime* dtValue) { + dtValue->Reset(); + if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) + return false; + + WideString wsDatePattern; + WideString wsTimePattern; + IFX_Locale* pLocale = nullptr; + 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) { + int32_t iStart = 0; + if (!ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, + &iStart)) { + return false; + } + if (!ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, + &iStart)) { + return false; + } + } else { + int32_t iStart = 0; + if ((eCategory & FX_DATETIMETYPE_Date) && + !ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, + &iStart)) { + return false; + } + if ((eCategory & FX_DATETIMETYPE_Time) && + !ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, + &iStart)) { + return false; + } + } + return true; +} + +bool CFGAS_FormatString::ParseZero(const WideString& wsSrcText, + const WideString& wsPattern) { + WideString wsTextFormat = GetTextFormat(wsPattern, L"zero"); + + int32_t iText = 0; + int32_t iPattern = 0; + const wchar_t* pStrText = wsSrcText.c_str(); + int32_t iLenText = wsSrcText.GetLength(); + const wchar_t* pStrPattern = wsTextFormat.c_str(); + int32_t iLenPattern = wsTextFormat.GetLength(); + while (iPattern < iLenPattern && iText < iLenText) { + if (pStrPattern[iPattern] == '\'') { + WideString wsLiteral = + GetLiteralText(pStrPattern, &iPattern, iLenPattern); + int32_t iLiteralLen = wsLiteral.GetLength(); + if (iText + iLiteralLen > iLenText || + wcsncmp(pStrText + iText, wsLiteral.c_str(), iLiteralLen)) { + return false; + } + iText += iLiteralLen; + iPattern++; + continue; + } + if (pStrPattern[iPattern] != pStrText[iText]) + return false; + + iText++; + iPattern++; + } + return iPattern == iLenPattern && iText == iLenText; +} + +bool CFGAS_FormatString::ParseNull(const WideString& wsSrcText, + const WideString& wsPattern) { + WideString wsTextFormat = GetTextFormat(wsPattern, L"null"); + + int32_t iText = 0; + int32_t iPattern = 0; + const wchar_t* pStrText = wsSrcText.c_str(); + int32_t iLenText = wsSrcText.GetLength(); + const wchar_t* pStrPattern = wsTextFormat.c_str(); + int32_t iLenPattern = wsTextFormat.GetLength(); + while (iPattern < iLenPattern && iText < iLenText) { + if (pStrPattern[iPattern] == '\'') { + WideString wsLiteral = + GetLiteralText(pStrPattern, &iPattern, iLenPattern); + int32_t iLiteralLen = wsLiteral.GetLength(); + if (iText + iLiteralLen > iLenText || + wcsncmp(pStrText + iText, wsLiteral.c_str(), iLiteralLen)) { + return false; + } + iText += iLiteralLen; + iPattern++; + continue; + } + if (pStrPattern[iPattern] != pStrText[iText]) + return false; + + iText++; + iPattern++; + } + return iPattern == iLenPattern && iText == iLenText; +} + +bool CFGAS_FormatString::FormatText(const WideString& wsSrcText, + const WideString& wsPattern, + WideString* wsOutput) { + if (wsPattern.IsEmpty()) + return false; + + int32_t iLenText = wsSrcText.GetLength(); + if (iLenText == 0) + return false; + + WideString wsTextFormat = GetTextFormat(wsPattern, L"text"); + + int32_t iText = 0; + int32_t iPattern = 0; + const wchar_t* pStrText = wsSrcText.c_str(); + const wchar_t* pStrPattern = wsTextFormat.c_str(); + int32_t iLenPattern = wsTextFormat.GetLength(); + while (iPattern < iLenPattern) { + switch (pStrPattern[iPattern]) { + case '\'': { + *wsOutput += GetLiteralText(pStrPattern, &iPattern, iLenPattern); + iPattern++; + break; + } + case 'A': + if (iText >= iLenText || !FXSYS_iswalpha(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 || (!FXSYS_isDecimalDigit(pStrText[iText]) && + !FXSYS_iswalpha(pStrText[iText]))) { + return false; + } + *wsOutput += pStrText[iText++]; + iPattern++; + break; + case '9': + if (iText >= iLenText || !FXSYS_isDecimalDigit(pStrText[iText])) + return false; + + *wsOutput += pStrText[iText++]; + iPattern++; + break; + default: + *wsOutput += pStrPattern[iPattern++]; + break; + } + } + return iText == iLenText; +} + +bool CFGAS_FormatString::FormatStrNum(const WideStringView& wsInputNum, + const WideString& wsPattern, + WideString* wsOutput) { + if (wsInputNum.IsEmpty() || wsPattern.IsEmpty()) + return false; + + int32_t dot_index_f = -1; + uint32_t dwNumStyle = 0; + WideString wsNumFormat; + IFX_Locale* pLocale = + GetNumericFormat(wsPattern, &dot_index_f, &dwNumStyle, &wsNumFormat); + if (!pLocale || wsNumFormat.IsEmpty()) + return false; + + int32_t cc = 0, ccf = 0; + const wchar_t* strf = wsNumFormat.c_str(); + int lenf = wsNumFormat.GetLength(); + WideString wsSrcNum(wsInputNum); + wsSrcNum.TrimLeft('0'); + if (wsSrcNum.IsEmpty() || wsSrcNum[0] == '.') + wsSrcNum.InsertAtFront('0'); + + CFX_Decimal decimal = CFX_Decimal(wsSrcNum.AsStringView()); + if (dwNumStyle & FX_NUMSTYLE_Percent) { + decimal = decimal * CFX_Decimal(100); + wsSrcNum = decimal; + } + + int32_t exponent = 0; + if (dwNumStyle & FX_NUMSTYLE_Exponent) { + int fixed_count = 0; + while (ccf < dot_index_f) { + switch (strf[ccf]) { + case '\'': + 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; + } + } + } + } + + bool bTrimTailZeros = false; + int32_t iTreading = + GetNumTrailingLimit(wsNumFormat, dot_index_f, &bTrimTailZeros); + int32_t scale = decimal.GetScale(); + if (iTreading < scale) { + decimal.SetScale(iTreading); + wsSrcNum = decimal; + } + if (bTrimTailZeros && scale > 0 && iTreading > 0) { + wsSrcNum.TrimRight(L"0"); + wsSrcNum.TrimRight(L"."); + } + + WideString wsGroupSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping); + bool bNeg = false; + if (wsSrcNum[0] == '-') { + bNeg = true; + wsSrcNum.Delete(0, 1); + } + + bool bAddNeg = false; + const wchar_t* str = wsSrcNum.c_str(); + int len = wsSrcNum.GetLength(); + auto dot_index = wsSrcNum.Find('.'); + if (!dot_index.has_value()) + dot_index = len; + + ccf = dot_index_f - 1; + cc = dot_index.value() - 1; + while (ccf >= 0) { + switch (strf[ccf]) { + case '9': + if (cc >= 0) { + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + wsOutput->InsertAtFront(str[cc]); + cc--; + } else { + wsOutput->InsertAtFront(L'0'); + } + ccf--; + break; + case 'z': + if (cc >= 0) { + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + if (str[0] != '0') + wsOutput->InsertAtFront(str[cc]); + + cc--; + } + ccf--; + break; + case 'Z': + if (cc >= 0) { + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + wsOutput->InsertAtFront(str[0] == '0' ? L' ' : str[cc]); + cc--; + } else { + wsOutput->InsertAtFront(L' '); + } + ccf--; + break; + case 'S': + if (bNeg) { + *wsOutput = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + *wsOutput; + bAddNeg = true; + } else { + wsOutput->InsertAtFront(L' '); + } + ccf--; + break; + case 's': + if (bNeg) { + *wsOutput = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + *wsOutput; + bAddNeg = true; + } + ccf--; + break; + case 'E': { + *wsOutput = WideString::Format(L"E%+d", exponent) + *wsOutput; + ccf--; + break; + } + case '$': { + *wsOutput = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol) + + *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') { + *wsOutput = bNeg ? L"CR" : 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') { + *wsOutput = bNeg ? L"DB" : L" " + *wsOutput; + ccf -= 2; + bAddNeg = true; + } + break; + case '%': { + *wsOutput = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent) + *wsOutput; + ccf--; + break; + } + case ',': + if (cc >= 0) + *wsOutput = wsGroupSymbol + *wsOutput; + + ccf--; + break; + case '(': + wsOutput->InsertAtFront(bNeg ? L'(' : L' '); + bAddNeg = true; + ccf--; + break; + case ')': + wsOutput->InsertAtFront(bNeg ? L')' : L' '); + ccf--; + break; + case '\'': + *wsOutput = GetLiteralTextReverse(strf, &ccf) + *wsOutput; + ccf--; + break; + default: + wsOutput->InsertAtFront(strf[ccf]); + ccf--; + } + } + + if (cc >= 0) { + int nPos = dot_index.value() % 3; + wsOutput->clear(); + for (int32_t i = 0; + i < pdfium::base::checked_cast<int32_t>(dot_index.value()); i++) { + if (i % 3 == nPos && i != 0) + *wsOutput += wsGroupSymbol; + *wsOutput += wsSrcNum[i]; + } + if (pdfium::base::checked_cast<int32_t>(dot_index.value()) < len) { + *wsOutput += pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); + *wsOutput += wsSrcNum.Right(len - dot_index.value() - 1); + } + if (bNeg) { + *wsOutput = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + *wsOutput; + } + return false; + } + if (dot_index_f == + pdfium::base::checked_cast<int32_t>(wsNumFormat.GetLength())) { + if (!bAddNeg && bNeg) { + *wsOutput = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + *wsOutput; + } + return true; + } + + WideString wsDotSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); + if (strf[dot_index_f] == 'V') { + *wsOutput += wsDotSymbol; + } else if (strf[dot_index_f] == '.') { + if (pdfium::base::checked_cast<int32_t>(dot_index.value()) < 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.value() + 1; + while (ccf < lenf) { + switch (strf[ccf]) { + case '\'': + *wsOutput += GetLiteralText(strf, &ccf, lenf); + ccf++; + break; + case '9': + if (cc < len) { + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + *wsOutput += str[cc]; + cc++; + } else { + *wsOutput += L'0'; + } + ccf++; + break; + case 'z': + if (cc < len) { + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + *wsOutput += str[cc]; + cc++; + } + ccf++; + break; + case 'Z': + if (cc < len) { + if (!FXSYS_isDecimalDigit(str[cc])) + return false; + + *wsOutput += str[cc]; + cc++; + } else { + *wsOutput += L'0'; + } + ccf++; + break; + case 'E': { + *wsOutput += WideString::Format(L"E%+d", exponent); + ccf++; + break; + } + case '$': + *wsOutput += + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol); + 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') { + *wsOutput += bNeg ? L"CR" : 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') { + *wsOutput += bNeg ? L"DB" : L" "; + ccf += 2; + bAddNeg = true; + } + break; + case '%': + *wsOutput += pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent); + ccf++; + break; + case '8': + while (ccf < lenf && strf[ccf] == '8') + ccf++; + while (cc < len && FXSYS_isDecimalDigit(str[cc])) { + *wsOutput += str[cc]; + cc++; + } + break; + case ',': + *wsOutput += wsGroupSymbol; + ccf++; + break; + case '(': + *wsOutput += bNeg ? '(' : ' '; + bAddNeg = true; + ccf++; + break; + case ')': + *wsOutput += bNeg ? ')' : ' '; + ccf++; + break; + default: + ccf++; + } + } + if (!bAddNeg && bNeg) { + *wsOutput = pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + + (*wsOutput)[0] + wsOutput->Right(wsOutput->GetLength() - 1); + } + return true; +} + +bool CFGAS_FormatString::FormatNum(const WideString& wsSrcNum, + const WideString& wsPattern, + WideString* wsOutput) { + if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) + return false; + return FormatStrNum(wsSrcNum.AsStringView(), wsPattern, wsOutput); +} + +bool CFGAS_FormatString::FormatDateTime(const WideString& wsSrcDateTime, + const WideString& wsPattern, + FX_DATETIMETYPE eDateTimeType, + WideString* wsOutput) { + if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) + return false; + + WideString wsDatePattern; + WideString wsTimePattern; + IFX_Locale* pLocale = nullptr; + 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.clear(); + } + eCategory = eDateTimeType; + } + if (eCategory == FX_DATETIMETYPE_Unknown) + return false; + + CFX_DateTime dt; + auto iT = wsSrcDateTime.Find(L"T"); + if (!iT.has_value()) { + if (eCategory == FX_DATETIMETYPE_Date && + FX_DateFromCanonical(wsSrcDateTime, &dt)) { + *wsOutput = FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, true, + pLocale); + return true; + } + if (eCategory == FX_DATETIMETYPE_Time && + FX_TimeFromCanonical(wsSrcDateTime.AsStringView(), &dt, pLocale)) { + *wsOutput = FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, true, + pLocale); + return true; + } + } else { + WideString wsSrcDate(wsSrcDateTime.c_str(), iT.value()); + WideStringView wsSrcTime(wsSrcDateTime.c_str() + iT.value() + 1, + wsSrcDateTime.GetLength() - iT.value() - 1); + if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty()) + return false; + if (FX_DateFromCanonical(wsSrcDate, &dt) && + FX_TimeFromCanonical(wsSrcTime, &dt, pLocale)) { + *wsOutput = FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, + eCategory != FX_DATETIMETYPE_TimeDate, + pLocale); + return true; + } + } + return false; +} + +bool CFGAS_FormatString::FormatZero(const WideString& wsPattern, + WideString* wsOutput) { + if (wsPattern.IsEmpty()) + return false; + + WideString wsTextFormat = GetTextFormat(wsPattern, L"zero"); + int32_t iPattern = 0; + const wchar_t* pStrPattern = wsTextFormat.c_str(); + int32_t iLenPattern = wsTextFormat.GetLength(); + while (iPattern < iLenPattern) { + if (pStrPattern[iPattern] == '\'') { + *wsOutput += GetLiteralText(pStrPattern, &iPattern, iLenPattern); + iPattern++; + } else { + *wsOutput += pStrPattern[iPattern++]; + } + } + return true; +} + +bool CFGAS_FormatString::FormatNull(const WideString& wsPattern, + WideString* wsOutput) { + if (wsPattern.IsEmpty()) + return false; + + WideString wsTextFormat = GetTextFormat(wsPattern, L"null"); + int32_t iPattern = 0; + const wchar_t* pStrPattern = wsTextFormat.c_str(); + int32_t iLenPattern = wsTextFormat.GetLength(); + while (iPattern < iLenPattern) { + if (pStrPattern[iPattern] == '\'') { + *wsOutput += GetLiteralText(pStrPattern, &iPattern, iLenPattern); + iPattern++; + continue; + } + *wsOutput += pStrPattern[iPattern++]; + } + return true; +} diff --git a/xfa/fgas/crt/cfgas_formatstring.h b/xfa/fgas/crt/cfgas_formatstring.h new file mode 100644 index 0000000000000000000000000000000000000000..5eae25dca5597ae81f12bf2d42f8de8714d412b0 --- /dev/null +++ b/xfa/fgas/crt/cfgas_formatstring.h @@ -0,0 +1,73 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_CRT_CFGAS_FORMATSTRING_H_ +#define XFA_FGAS_CRT_CFGAS_FORMATSTRING_H_ + +#include <vector> + +#include "core/fxcrt/ifx_locale.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" + +bool FX_DateFromCanonical(const WideString& wsDate, CFX_DateTime* datetime); +bool FX_TimeFromCanonical(const WideStringView& wsTime, + CFX_DateTime* datetime, + IFX_Locale* pLocale); + +class CFGAS_FormatString { + public: + explicit CFGAS_FormatString(CXFA_LocaleMgr* pLocaleMgr); + ~CFGAS_FormatString(); + + void SplitFormatString(const WideString& wsFormatString, + std::vector<WideString>* wsPatterns); + FX_LOCALECATEGORY GetCategory(const WideString& wsPattern); + + bool ParseText(const WideString& wsSrcText, + const WideString& wsPattern, + WideString* wsValue); + bool ParseNum(const WideString& wsSrcNum, + const WideString& wsPattern, + WideString* wsValue); + bool ParseDateTime(const WideString& wsSrcDateTime, + const WideString& wsPattern, + FX_DATETIMETYPE eDateTimeType, + CFX_DateTime* dtValue); + bool ParseZero(const WideString& wsSrcText, const WideString& wsPattern); + bool ParseNull(const WideString& wsSrcText, const WideString& wsPattern); + + bool FormatText(const WideString& wsSrcText, + const WideString& wsPattern, + WideString* wsOutput); + bool FormatNum(const WideString& wsSrcNum, + const WideString& wsPattern, + WideString* wsOutput); + bool FormatDateTime(const WideString& wsSrcDateTime, + const WideString& wsPattern, + FX_DATETIMETYPE eDateTimeType, + WideString* wsOutput); + bool FormatZero(const WideString& wsPattern, WideString* wsOutput); + bool FormatNull(const WideString& wsPattern, WideString* wsOutput); + + private: + WideString GetTextFormat(const WideString& wsPattern, + const WideStringView& wsCategory); + IFX_Locale* GetNumericFormat(const WideString& wsPattern, + int32_t* iDotIndex, + uint32_t* dwStyle, + WideString* wsPurgePattern); + bool FormatStrNum(const WideStringView& wsInputNum, + const WideString& wsPattern, + WideString* wsOutput); + FX_DATETIMETYPE GetDateTimeFormat(const WideString& wsPattern, + IFX_Locale** pLocale, + WideString* wsDatePattern, + WideString* wsTimePattern); + + CXFA_LocaleMgr* m_pLocaleMgr; +}; + +#endif // XFA_FGAS_CRT_CFGAS_FORMATSTRING_H_ diff --git a/xfa/fgas/crt/cfgas_formatstring_unittest.cpp b/xfa/fgas/crt/cfgas_formatstring_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51c001090ca8b08b8f1ecb4edfb76b9bcd4ab488 --- /dev/null +++ b/xfa/fgas/crt/cfgas_formatstring_unittest.cpp @@ -0,0 +1,661 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/crt/cfgas_formatstring.h" + +#include <time.h> + +#include <memory> + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" + +class CFGAS_FormatStringTest : public testing::Test { + public: + CFGAS_FormatStringTest() { + SetTZ("UTC"); + CPDF_ModuleMgr::Get()->Init(); + } + + ~CFGAS_FormatStringTest() override { CPDF_ModuleMgr::Get()->Destroy(); } + + void TearDown() override { + fmt_.reset(); + mgr_.reset(); + } + + void SetTZ(const char* tz) { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + _putenv_s("TZ", tz); + _tzset(); +#else + setenv("TZ", tz, 1); + tzset(); +#endif + } + + // Note, this re-creates the fmt on each call. If you need to multiple + // times store it locally. + CFGAS_FormatString* fmt(const WideString& locale) { + mgr_ = pdfium::MakeUnique<CXFA_LocaleMgr>(nullptr, locale); + fmt_ = pdfium::MakeUnique<CFGAS_FormatString>(mgr_.get()); + return fmt_.get(); + } + + protected: + std::unique_ptr<CXFA_LocaleMgr> mgr_; + std::unique_ptr<CFGAS_FormatString> fmt_; +}; + +// TODO(dsinclair): Looks like the formatter/parser does not handle the various +// 'g' flags. +TEST_F(CFGAS_FormatStringTest, DateFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = { + {L"en", L"2002-10-25", L"MMMM DD, YYYY", L"October 25, 2002"}, + // Note, this is in the doc as 5 but it's wrong and should be 3 by the + // example in the Picture Clause Reference section. + {L"en", L"20040722", L"'Week of the month is' w", + L"Week of the month is 3"}, + {L"en", L"20040722", L"e 'days after Sunday'", L"4 days after Sunday"}, + {L"en", L"20040722", L"YYYY-'W'WW-e", L"2004-W30-4"}, + {L"en", L"20040722", L"E 'days after Saturday'", + L"5 days after Saturday"}, + {L"en", L"2000-01-01", L"EEE, 'the' D 'of' MMMM, YYYY", + L"Sat, the 1 of January, 2000"}, + {L"en", L"2000-01-01", L"EEEE, 'the' D 'of' MMMM, YYYY", + L"Saturday, the 1 of January, 2000"}, + {L"en", L"19991202", L"MM/D/YY", L"12/2/99"}, + {L"en", L"19990110", L"MMM D, YYYY", L"Jan 10, 1999"}, + {L"en", L"19990202", L"J", L"33"}, + {L"en", L"19990202", L"JJJ", L"033"}, + {L"en", L"19991231", L"J", L"365"}, + {L"en", L"20001231", L"J", L"366"}, + {L"en", L"19990501", L"J", L"121"}, + {L"en", L"19990901", L"J", L"244"}, + {L"en", L"19990228", L"J", L"59"}, + {L"en", L"20000229", L"J", L"60"}, + {L"en", L"21000501", L"J", L"121"}, + {L"en", L"19990102", L"M", L"1"}, + {L"en", L"19990102", L"MMM", L"Jan"}, + {L"en", L"19990102", L"YYYY G", L"1999 AD"}, + // Week 01 of the year is the week containing Jan 04. + // {L"en", L"19990102", L"WW", L"00"}, -- Returns 01 incorrectly + // {L"en", L"19990104", L"WW", L"01"}, -- Returns 02 incorrectly + // The ?*+ should format as whitespace. + // {L"en", L"19990104", L"YYYY?*+MM", L"1999 01"}, + // {L"en", L"1999-07-16", L"date{DD/MM/YY} '('date{MMM DD, YYYY}')'", + // L"16/07/99 (Jul 16, 1999)"}, + {L"de_CH", L"20041030", L"D. MMMM YYYY", L"30. Oktober 2004"}, + {L"fr_CA", L"20041030", L"D MMMM YYYY", L"30 octobre 2004"}, + {L"en", L"2002-10-25", L"date(fr){DD MMMM, YYYY}", L"25 octobre, 2002"}, + {L"en", L"2002-10-25", L"date(es){EEEE, D 'de' MMMM 'de' YYYY}", + L"viernes, 25 de octubre de 2002"}, + // {L"en", L"2002-20-25", L"date.long(fr)()", L"25 octobre, 2002"}, + // {L"ja", L"2003-11-03", L"gY/M/D", L"H15/11/3"}, + // {L"ja", L"1989-01-08", L"ggY-M-D", L"\u5e731-1-8"}, + // {L"ja", L"1989-11-03", L"gggYY/MM/DD", L"\u5e73\u621089/11/03"}, + }; + // Note, none of the full width date symbols are listed here + // as they are not supported. In theory there are the full width versions + // of DDD, DDDD, MMM, MMMM, E, e, gg, YYY, YYYYY. + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->FormatDateTime(tests[i].input, tests[i].pattern, + FX_DATETIMETYPE_Date, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, TimeFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = {{L"en", L"01:01:11", L"h:M A", L"1:1 AM"}, + {L"en", L"13:01:11", L"h:M A", L"1:1 PM"}, + {L"en", L"01:01:11", L"hh:MM:SS A", L"01:01:11 AM"}, + {L"en", L"13:01:11", L"hh:MM:SS A", L"01:01:11 PM"}, + {L"en", L"01:01:11", L"hh:MM:SS A Z", L"01:01:11 AM GMT-02:00"}, + {L"en", L"01:01:11", L"hh:MM:SS A z", L"01:01:11 AM -02:00"}, + // {L"en", L"01:01:11", L"hh:MM:SS A zz", L"01:01:11 AM GMT"}, + // Should change ?*+ into ' ' when formatting. + // {L"en", L"01:01:11", L"hh:MM:SS?*+A", L"01:01:11 AM"}, + {L"en", L"12:01:01", L"k:MM:SS", L"12:01:01"}, + {L"en", L"14:01:01", L"k:MM:SS", L"2:01:01"}, + {L"en", L"12:01:11", L"kk:MM", L"12:01"}, + {L"en", L"14:01:11", L"kk:MM", L"02:01"}, + {L"en", L"12:01:11 +04:30", L"kk:MM", L"05:31"}, + {L"en", L"12:01:11", L"kk:MM A", L"12:01 PM"}, + {L"en", L"00:01:01", L"H:M:S", L"0:1:1"}, + {L"en", L"13:02:11", L"H:M:S", L"13:2:11"}, + {L"en", L"00:01:11.001", L"HH:M:S.FFF", L"00:1:11.001"}, + {L"en", L"13:02:11", L"HH:M", L"13:2"}, + {L"en", L"00:01:11", L"K:M", L"24:1"}, + {L"en", L"00:02:11", L"KK:M", L"24:2"}, + {L"en", L"11:11:11", L"HH:MM:SS 'o''clock' A Z", + L"11:11:11 o'clock AM GMT-02:00"}, + {L"en", L"14:30:59", L"h:MM A", L"2:30 PM"}, + {L"en", L"14:30:59", L"HH:MM:SS A Z", L"14:30:59 PM GMT-02:00"}}; + // Note, none of the full width time symbols are listed here + // as they are not supported. In theory there are the full + // width versions of kkk, kkkk, HHH, HHHH, KKK, KKKK, MMM, MMMM, + // SSS, SSSS plus 2 more that the spec apparently forgot to + // list the symbol. + + // The z modifier only appends if the TZ is outside of +0 + SetTZ("UTC+2"); + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->FormatDateTime(tests[i].input, tests[i].pattern, + FX_DATETIMETYPE_Time, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } + + SetTZ("UTC"); +} + +TEST_F(CFGAS_FormatStringTest, DateTimeFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = { + {L"en", L"1999-07-16T10:30Z", + L"'At' time{HH:MM Z} 'on' date{MMM DD, YYYY}", + L"At 10:30 GMT on Jul 16, 1999"}, + {L"en", L"1999-07-16T10:30", L"'At' time{HH:MM} 'on' date{MMM DD, YYYY}", + L"At 10:30 on Jul 16, 1999"}, + {L"en", L"1999-07-16T10:30Z", + L"time{'At' HH:MM Z} date{'on' MMM DD, YYYY}", + L"At 10:30 GMT on Jul 16, 1999"}, + {L"en", L"1999-07-16T10:30Z", + L"time{'At 'HH:MM Z}date{' on 'MMM DD, YYYY}", + L"At 10:30 GMT on Jul 16, 1999"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->FormatDateTime(tests[i].input, tests[i].pattern, + FX_DATETIMETYPE_TimeDate, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, DateParse) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + CFX_DateTime output; + } tests[] = { + {L"en", L"12/2/99", L"MM/D/YY", CFX_DateTime(1999, 12, 2, 0, 0, 0, 0)}, + {L"en", L"2/2/99", L"M/D/YY", CFX_DateTime(1999, 2, 2, 0, 0, 0, 0)}, + {L"en", L"2/2/10", L"M/D/YY", CFX_DateTime(2010, 2, 2, 0, 0, 0, 0)}, + {L"en", L"Jan 10, 1999", L"MMM D, YYYY", + CFX_DateTime(1999, 1, 10, 0, 0, 0, 0)}, + {L"en", L"Jan 10, 1999 AD", L"MMM D, YYYY G", + CFX_DateTime(1999, 1, 10, 0, 0, 0, 0)}, + // TODO(dsinclair): Should this be -2 instead of 2? + {L"en", L"Jan 10, 0002 BC", L"MMM D, YYYY G", + CFX_DateTime(2, 1, 10, 0, 0, 0, 0)}, + {L"en", L"October 25, 2002", L"MMMM DD, YYYY", + CFX_DateTime(2002, 10, 25, 0, 0, 0, 0)}, + // TODO(dsinclair): The J and JJJ are ignored during parsing when they + // could be turned back into a date. + {L"en", L"1999-33", L"YYYY-J", CFX_DateTime(1999, 1, 1, 0, 0, 0, 0)}, + {L"en", L"1999-033", L"YYYY-JJJ", CFX_DateTime(1999, 1, 1, 0, 0, 0, 0)}, + {L"de_CH", L"30. Oktober 2004", L"D. MMMM YYYY", + CFX_DateTime(2004, 10, 30, 0, 0, 0, 0)}, + {L"fr_CA", L"30 octobre 2004", L"D MMMM YYYY", + CFX_DateTime(2004, 10, 30, 0, 0, 0, 0)}, + {L"en", L"Saturday, the 1 of January, 2000", + L"EEEE, 'the' D 'of' MMMM, YYYY", CFX_DateTime(2000, 1, 1, 0, 0, 0, 0)}, + {L"en", L"Sat, the 1 of January, 2000", L"EEE, 'the' D 'of' MMMM, YYYY", + CFX_DateTime(2000, 1, 1, 0, 0, 0, 0)}, + {L"en", L"7, the 1 of January, 2000", // 7 == Saturday as 1 == Sunday + L"E, 'the' D 'of' MMMM, YYYY", CFX_DateTime(2000, 1, 1, 0, 0, 0, 0)}, + {L"en", L"6, the 1 of January, 2000", // 6 == Saturday as 1 == Monday + L"e, 'the' D 'of' MMMM, YYYY", CFX_DateTime(2000, 1, 1, 0, 0, 0, 0)}, + {L"en", L"2004-07-22 Week of the month is 3", + L"YYYY-MM-DD 'Week of the month is' w", + CFX_DateTime(2004, 7, 22, 0, 0, 0, 0)}, + {L"en", L"2004-07-22 Week of the year is 03", + L"YYYY-MM-DD 'Week of the year is' WW", + CFX_DateTime(2004, 7, 22, 0, 0, 0, 0)} + // {L"ja", L"H15/11/3", L"gY/M/D", CFX_DateTime(2003, 11, 3, 0, 0, 0, 0)}, + // {L"ja", L"\u5e731-1-8", L"ggY-M-D", CFX_DateTime(1989, 1, 8, 0, 0, 0, + // 0)}, {L"ja", L"\u5e73\u621089/11/03", L"gggYY/MM/DD", + // CFX_DateTime(1989, 11, 3, 0, 0, 0, 0)}, + // {L"ja", L"u337b99/01/08", L"\u0067\u0067YY/MM/DD", + // CFX_DateTime(1999, 1, 8, 0, 0, 0, 0)} + }; + // Note, none of the full width date symbols are listed here as they are + // not supported. In theory there are the full width versions of DDD, + // DDDD, MMM, MMMM, E, e, gg, YYY, YYYYY. + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + CFX_DateTime result; + EXPECT_TRUE(fmt(tests[i].locale) + ->ParseDateTime(tests[i].input, tests[i].pattern, + FX_DATETIMETYPE_Date, &result)); + EXPECT_EQ(tests[i].output, result) << " TEST: " << i; + } +} + +// TODO(dsinclair): GetDateTimeFormat is broken and doesn't allow just returning +// a parsed Time. It will assume it's a Date. The method needs to be re-written. +// TEST_F(CFGAS_FormatStringTest, TimeParse) { +// struct { +// const wchar_t* locale; +// const wchar_t* input; +// const wchar_t* pattern; +// CFX_DateTime output; +// } tests[] = { +// {L"en", L"18:00", L"HH:MM", CFX_DateTime(0, 0, 0, 18, 0, 0, 0)}, +// {L"en", L"12.59 Uhr", L"H.MM 'Uhr'", CFX_DateTime(0, 0, 0, 12, 59, 0, +// 0)}, {L"en", L"1:05:10 PM PST", L"h:MM:SS A Z", +// CFX_DateTime(0, 0, 0, 17, 05, 10, 0)}}; +// // Note, none of the full width date symbols are listed here as they are +// // not supported. In theory there are the full width versions of kkk, +// // kkkk, HHH, HHHH, KKK, KKKK, MMM, MMMM, SSS, SSSS plus 2 more that the +// // spec apparently forgot to list the symbol. + +// for (size_t i = 0; i < FX_ArraySize(tests); ++i) { +// CFX_DateTime result; +// EXPECT_TRUE(fmt(tests[i].locale) +// ->ParseDateTime(tests[i].input, tests[i].pattern, +// FX_DATETIMETYPE_Time, &result)); +// EXPECT_EQ(tests[i].output, result) << " TEST: " << i; +// } +// } + +TEST_F(CFGAS_FormatStringTest, SplitFormatString) { + std::vector<WideString> results; + fmt(L"en")->SplitFormatString( + L"null{'No data'} | null{} | text{999*9999} | text{999*999*9999}", + &results); + EXPECT_EQ(4UL, results.size()); + + const wchar_t* patterns[] = {L"null{'No data'} ", L" null{} ", + L" text{999*9999} ", L" text{999*999*9999}"}; + + for (size_t i = 0; i < results.size(); ++i) { + EXPECT_STREQ(patterns[i], results[i].c_str()); + } +} + +TEST_F(CFGAS_FormatStringTest, NumParse) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = { + // {L"en", L"€100.00", L"num(en_GB){$z,zz9.99}", L"100"}, + // {L"en", L"1050", L"99V99", L"10.50"}, + // {L"en", L"3125", L"99V99", L"31.25"}, + {L"en", L"12.345e3", L"99.999E", L"12345.000000"}, + {L"en", L"12.345e+3", L"99.999E", L"12345.000000"}, + {L"en", L"12.345E-2", L"99.999E", L"0.123450"}, + // TODO(dsinclair): Returns 0.000? + // {L"en", L"12e-2", L"99E", L"0.12"}, + {L"en", L"150", L"z999", L"150"}, + {L"en", L"150.50$", L"zzz.zz$", L"150.50"}, + {L"en", L"0150", L"z999", L"0150"}, + {L"en", L"123CR", L"999cr", L"-123"}, + {L"en", L"123", L"999cr", L"123"}, + {L"en", L"123CR", L"999CR", L"-123"}, + {L"en", L"123 ", L"999CR", L"123"}, + {L"en", L"123DB", L"999db", L"-123"}, + {L"en", L"123", L"999db", L"123"}, + {L"en", L"123DB", L"999DB", L"-123"}, + {L"en", L"123 ", L"999DB", L"123"}, + {L"en", L"123.5CR", L"999.9cr", L"-123.5"}, + {L"en", L"123.5", L"999.9cr", L"123.5"}, + {L"en", L"123.5CR", L"999.9CR", L"-123.5"}, + // {L"en", L"123.5 ", L"999.9CR", L"123.5"}, + {L"en", L"123.5DB", L"999.9db", L"-123.5"}, + {L"en", L"123.5", L"999.9db", L"123.5"}, + {L"en", L"123.5DB", L"999.9DB", L"-123.5"}, + // {L"en", L"123.5 ", L"999.9DB", L"123.5"}, + {L"en", L"10.50", L"z,zz9.99", L"10.50"}, + {L"en", L"3,125.00", L"z,zz9.99", L"3125.00"}, + {L"en", L"$1,234.00", L"$z,zz9.99DB", L"1234.00"}, + // TODO(dsinclair): Comes out as 1234 instead of -1234. + // {L"en", L"$,1234.00DB", L"$z,zz9.99DB", L"-1234.00"}, + {L"en", L"1.234", L"zz9.zzz", L"1.234"}, + {L"en", L"1 text", L"num{z 'text'}", L"1"}, + {L"en", L"1.234 text", L"z.zzz 'text'", L"1.234"}, + {L"en", L" 1.234", L"ZZ9.ZZZ", L"1.234"}, + {L"en", L"12.345", L"zz9.zzz", L"12.345"}, + {L"en", L" 12.345", L"ZZ9.ZZZ", L"12.345"}, + {L"en", L"123.456", L"zz9.zzz", L"123.456"}, + {L"en", L"123.456", L"ZZ9.ZZZ", L"123.456"}, + {L"en", L"123.456-", L"ZZ9.ZZZS", L"-123.456"}, + {L"en", L"123.456+", L"ZZ9.ZZZS", L"123.456"}, + {L"en", L"123.456 ", L"ZZ9.ZZZS", L"123.456"}, + {L"en", L"123.456-", L"ZZ9.ZZZS", L"-123.456"}, + {L"en", L"123.456+", L"ZZ9.ZZZS", L"123.456"}, + {L"en", L"123", L"zz9.zzz", L"123"}, + {L"en", L"123.", L"ZZ9.ZZZ", L"123."}, + {L"en", L"123.", L"zz9.zzz", L"123."}, + {L"en", L"123.", L"ZZ9.ZZZ", L"123."}, + {L"en", L"123.0", L"zz9.zzz", L"123.0"}, + {L"en", L"123.0", L"ZZ9.ZZZ", L"123.0"}, + {L"en", L"123.000", L"zz9.zzz", L"123.000"}, + {L"en", L"123.000", L"ZZ9.ZZZ", L"123.000"}, + {L"en", L"12,345.67", L"zzz,zz9.88888888", L"12345.67"}, + {L"en", L"12,345.0000", L"zzz,zz9.88888888", L"12345.0000"}, + {L"en", L"12,345.6789", L"zzz,zz9.8", L"12345.6789"}, + {L"en", L"12,345.", L"zzz,zz9.8", L"12345."}, + {L"en", L"123,456.000", L"zzz,zz9.8888", L"123456.000"}, + {L"en", L"123,456.0", L"zzz,zz9.8888", L"123456.0"}, + {L"en", L"123,456", L"zzz,zz9.8888", L"123456"}, + {L"en", L"123,456", L"ZZZ,ZZ9.88", L"123456"}, + {L"en", L"12,345.67", L"zzz,zz9.88888888", L"12345.67"}, + {L"en", L"12,345.0000", L"zzz,zz9.88888888", L"12345.0000"}, + {L"en", L"12,345.6789", L"zzz,zz9.8", L"12345.6789"}, + {L"en", L"12,345.", L"zzz,zz9.8", L"12345."}, + // TODO(dsinclair): Parses to 0 + // {L"en", L"12%", L"zz9.%%", L".12"}, + {L"en", L"1,234.50%", L"zzz,zz9.99%%", L"12.345"}, + // {L"en", L"-00123", L"S999v99", L"-1.23"}, + {L"en", L" 001.23", L"S999V99", L"001.23"}, + // {L"en", L" 123.00", L"S999V99", L"123"}, + {L"en", L" 12.30", L"SZZ9.99", L"12.30"}, + {L"en", L"- 12.30", L"SZ99.99", L"-12.30"}, + {L"en", L"123.00", L"szz9.99", L"123.00"}, + {L"en", L"-123.00", L"szz9.99", L"-123.00"}, + // {L"en", L"$ 1,234.00 ", L"$ZZ,ZZ9.99CR", L"1234"}, + // {L"en", L"$ 1,234.00CR", L"$ZZ,ZZ9.99CR", L"-1234"}, + // {L"en", L"$1,23400", L"$z,zz9.99DB", L"1234"}, + {L"en", L"$1,234.00DB", L"$z,zz9.99DB", L"-1234.00"}, + {L"en", + L"1\xA0" + L"234", + L"num(fr){z,zzz}", L"1234"}, + // TODO(dsinclair): Parses to blank + // {L"en", L"1,234%", L"num.percent{}", L"12.34"}, + // {L"en", L"1\xA0" L"234%%", L"num(fr).percent{}", L"12.34"}, + // TODO(dsinclair): Parses to blank + // {L"en", L"1,234%", L"num{9,999%%}", L"12.34"}, + {L"fr", + L"123\xA0" + L"456", + L"zzz,zzz", L"123456"}, + {L"en", L"12%", L"zz%", L"0.12"}, + {L"en", L"(123", L"(zzz", L"-123"}, + {L"en", L"123)", L"zzz)", L"-123"}, + {L"en", L"(123)", L"(zzz)", L"-123"}, + {L"en", L"123 ", L"zzz)", L"123"}, + {L"en", L" 123", L"(zzz", L"123"}, + {L"en", L" 123 ", L"(zzz)", L"123"}, + {L"en", L"123.5(", L"zzz.z(", L"-123.5"}, + {L"en", L"123.5)", L"zzz.z)", L"-123.5"}, + {L"en", L"123.5 ", L"zzz.z)", L"123.5"}, + {L"en", L"123.5 ", L"zzz.z(", L"123.5"}, + {L"en", L"123.545,4", L"zzz.zzz,z", L"123.5454"}, + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->ParseNum(tests[i].input, tests[i].pattern, &result)) + << " TEST: " << i; + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, NumFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = { + {L"en", L"1.234", L"zz9.zzz", L"1.234"}, + {L"en", L"1", L"num{z 'text'}", L"1 text"}, + {L"en", L"1", L"num{'text' z}", L"text 1"}, + {L"en", L"1.234", L"ZZ9.ZZZ", L" 1.234"}, + {L"en", L"12.345", L"zz9.zzz", L"12.345"}, + {L"en", L"12.345", L"ZZ9.ZZZ", L" 12.345"}, + {L"en", L"123.456", L"zz9.zzz", L"123.456"}, + {L"en", L"123.456", L"ZZ9.ZZZ", L"123.456"}, + {L"en", L"123", L"zz9.zzz", L"123"}, + {L"en", L"123", L"ZZ9.ZZZ", L"123.000"}, + {L"en", L"123.", L"zz9.zzz", L"123."}, + {L"en", L"123.", L"ZZ9.ZZZ", L"123.000"}, + {L"en", L"123.0", L"zz9.zzz", L"123"}, + {L"en", L"123.0", L"ZZ9.ZZZ", L"123.000"}, + {L"en", L"123.000", L"zz9.zzz", L"123"}, + {L"en", L"123.000", L"ZZ9.ZZZ", L"123.000"}, + // {L"en", L"12345.67", L"zzz,zz9.88888888", L"12,345.67"}, + // {L"en", L"12345.0000", L"zzz,zz9.88888888", L"12,345.0000"}, + // {L"en", L"12345.6789", L"zzz,zz9.8", L"12,345.6789"}, + // {L"en", L"12345.", L"zzz,zz9.8", L"12,345"}, + // {L"en", L"123456.000", L"zzz,zz9.8888", L"123,456.000"}, + // {L"en", L"123456.0", L"zzz,zz9.8888", L"123,456.0"}, + {L"en", L"123456", L"zzz,zz9.8888", L"123,456"}, + {L"en", L"123456", L"ZZZ,ZZ9.88", L"123,456"}, + // {L"en", L"12345.67", L"zzz,zz9.88888888", L"12,345.67"}, + // {L"en", L"12345.0000", L"zzz,zz9.88888888", L"12,345.0000"}, + // {L"en", L"12345.6789", L"zzz,zz9.8", L"12,345.6789"}, + // {L"en", L"12345.", L"zzz,zz9.8", L"12,345"}, + // {L"en", L"12%%", L"zz9.%%", L"12%%"}, + // {L"en", L"1,234.5%%", L"zzz,zz9.99%%", L"1,234.50%%"}, + {L"en", L"-1.23", L"S999v99", L"-00123"}, + {L"en", L"1.23", L"S999V99", L" 001.23"}, + {L"en", L"123", L"S999V99", L" 123.00"}, + {L"en", L"12.3", L"SZZ9.99", L" 12.30"}, + {L"en", L"-12.3", L"SZ99.99", L"- 12.30"}, + {L"en", L"123", L"szz9.99", L"123.00"}, + {L"en", L"-123", L"szz9.99", L"-123.00"}, + // {L"en", L"1234", L"$ZZ,ZZ9.99CR", L"$ 1,234.00 "}, + // {L"en", L"-1234", L"$ZZ,ZZ9.99CR", L"$ 1,234.00CR"}, + // {L"en", L"1234", L"$z,zz9.99DB", L"$1,234.00"}, + {L"en", L"-1234", L"$z,zz9.99DB", L"$1,234.00DB"}, + {L"en", L"12345", L"99.999E", L"12.345E+3"}, + {L"en", L"12345", L"99999E", L"12345E+0"}, + {L"en", L".12345", L"99.999E", L"12.345E-2"}, + {L"en", L"12345", L"99,999", L"12,345"}, + {L"en", L"1234", L"num(fr){z,zzz}", + L"1\xA0" + L"234"}, + {L"en", L"12.34", L"num.percent{}", L"1,234%"}, + {L"en", L"12.34", L"num(fr).percent{}", + L"1\xA0" + L"234%"}, + // {L"en", L"12.34", L"num{9,999%%}", L"1,234%"}, + {L"en", L"-123", L"zzzCR", L"123CR"}, + {L"en", L"123", L"zzzCR", L"123 "}, + {L"en", L"-123", L"zzzcr", L"123CR"}, + {L"en", L"123", L"zzzcr", L"123"}, + {L"en", L"123", L"zzz$", L"123$"}, + {L"en", L"-123.5", L"zzz.zCR", L"123.5CR"}, + {L"en", L"123.5", L"zzz.zCR", L"123.5 "}, + {L"en", L"-123.5", L"zzz.zcr", L"123.5CR"}, + {L"en", L"123.5", L"zzz.zcr", L"123.5"}, + + {L"en", L"-123.5", L"999.9db", L"123.5db"}, + {L"en", L"123.5", L"999.9db", L"123.5"}, + {L"en", L"-123.5", L"999.9DB", L"123.5DB"}, + {L"en", L"123.5", L"999.9DB", L"123.5 "}, + + {L"en", L"-123", L"(zzz", L"(123"}, + // {L"en", L"-123", L"zzz)", L"123)"}, + {L"en", L"-123", L"(zzz)", L"(123)"}, + {L"en", L"123", L"zzz)", L"123 "}, + {L"en", L"123", L"(zzz", L" 123"}, + {L"en", L"123", L"(zzz)", L" 123 "}, + {L"en", L"-123.5", L"zzz.z(", L"123.5("}, + // {L"en", L"-123.5", L"zzz.z)", L"123.5)"}, + {L"en", L"123.5", L"zzz.z)", L"123.5 "}, + {L"en", L"123.5", L"zzz.z(", L"123.5 "}, + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->FormatNum(tests[i].input, tests[i].pattern, &result)) + << " TEST: " << i; + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, TextParse) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = {// TODO(dsinclair) Missing support for the global modifiers: + // ? - wildcard + // * - zero or more whitespace + // + - one or more whitespace + // {L"en", L"555-1212", L"text(th_TH){999*9999}", L"5551212"}, + {L"en", L"ABC-1234-5", L"AAA-9999-X", L"ABC12345"}, + {L"en", L"ABC-1234-D", L"AAA-9999-X", L"ABC1234D"}, + {L"en", L"A1C-1234-D", L"OOO-9999-X", L"A1C1234D"}, + {L"en", L"A1C-1234-D", L"000-9999-X", L"A1C1234D"}, + {L"en", L"A1C-1234-D text", L"000-9999-X 'text'", L"A1C1234D"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->ParseText(tests[i].input, tests[i].pattern, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, InvalidTextParse) { + // Input does not match mask. + WideString result; + EXPECT_FALSE(fmt(L"en")->ParseText(L"123-4567-8", L"AAA-9999-X", &result)); +} + +TEST_F(CFGAS_FormatStringTest, TextFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = { + {L"en", L"K1S5K2", L"A9A 9A9", L"K1S 5K2"}, + {L"en", L"K1S5K2", L"text(fr){A9A 9A9}", L"K1S 5K2"}, + {L"en", L"6135551212", L"'+1 ('9\u002399') '999-9999", + L"+1 (6#13) 555-1212"}, + {L"en", L"6135551212", L"999.999.9999", L"613.555.1212"}, + {L"en", L"6135551212", L"999\u0023999\u002A9999", L"613#555*1212"}, + {L"en", L"K1#5K2", L"00X OO9", L"K1# 5K2"}, + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale) + ->FormatText(tests[i].input, tests[i].pattern, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, NullParse) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + } tests[] = { + {L"en", L"", L"null{}"}, {L"en", L"No data", L"null{'No data'}"}, + }; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE( + fmt(tests[i].locale)->ParseNull(tests[i].input, tests[i].pattern)) + << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, NullFormat) { + struct { + const wchar_t* locale; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = {{L"en", L"null{'n/a'}", L"n/a"}, {L"en", L"null{}", L""}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE(fmt(tests[i].locale)->FormatNull(tests[i].pattern, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, ZeroParse) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + } tests[] = {{L"en", L"", L"zero{}"}, + {L"en", L"9", L"zero{9}"}, + {L"en", L"a", L"zero{'a'}"}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + EXPECT_TRUE( + fmt(tests[i].locale)->ParseZero(tests[i].input, tests[i].pattern)) + << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, ZeroFormat) { + struct { + const wchar_t* locale; + const wchar_t* input; + const wchar_t* pattern; + const wchar_t* output; + } tests[] = {// TODO(dsinclair): The zero format can take a number specifier + // which we don't take into account. + // {L"en", L"", L"zero {9}", L""}, + // {L"en", L"0", L"zero {9}", L"0"}, + // {L"en", L"0.0", L"zero{9}", L"0"}, + {L"en", L"0", L"zero{}", L""}}; + + for (size_t i = 0; i < FX_ArraySize(tests); ++i) { + WideString result; + EXPECT_TRUE( + fmt(tests[i].locale) + ->FormatZero(/* tests[i].input,*/ tests[i].pattern, &result)); + EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i; + } +} + +TEST_F(CFGAS_FormatStringTest, GetCategory) { + CFGAS_FormatString* f = fmt(L"en"); + + EXPECT_EQ(FX_LOCALECATEGORY_Unknown, f->GetCategory(L"'just text'")); + EXPECT_EQ(FX_LOCALECATEGORY_Null, f->GetCategory(L"null{}")); + EXPECT_EQ(FX_LOCALECATEGORY_Zero, f->GetCategory(L"zero{}")); + EXPECT_EQ(FX_LOCALECATEGORY_Num, f->GetCategory(L"num{}")); + EXPECT_EQ(FX_LOCALECATEGORY_Text, f->GetCategory(L"text{}")); + EXPECT_EQ(FX_LOCALECATEGORY_DateTime, f->GetCategory(L"datetime{}")); + EXPECT_EQ(FX_LOCALECATEGORY_Time, f->GetCategory(L"time{}")); + EXPECT_EQ(FX_LOCALECATEGORY_Date, f->GetCategory(L"date{}")); + EXPECT_EQ(FX_LOCALECATEGORY_DateTime, f->GetCategory(L"time{} date{}")); + EXPECT_EQ(FX_LOCALECATEGORY_DateTime, f->GetCategory(L"date{} time{}")); + EXPECT_EQ(FX_LOCALECATEGORY_Num, f->GetCategory(L"num(en_GB){}")); + EXPECT_EQ(FX_LOCALECATEGORY_Date, f->GetCategory(L"date.long{}")); +} diff --git a/xfa/fgas/crt/fgas_codepage.cpp b/xfa/fgas/crt/fgas_codepage.cpp deleted file mode 100644 index 36f87a36f3fddcf08805e10bed18bf9360e376db..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_codepage.cpp +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fx_ext.h" -#include "xfa/fgas/crt/fgas_codepage.h" -#include "xfa/fgas/crt/fgas_language.h" - -namespace { - -struct FX_STR2CPHASH { - uint32_t uHash; - uint16_t uCodePage; -}; - -struct FX_CHARSET_MAP { - uint16_t charset; - uint16_t codepage; -}; - -struct FX_LANG2CPMAP { - uint16_t wLanguage; - uint16_t wCodepage; -}; - -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}, -}; - -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}, -}; - -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}, -}; - -uint16_t GetCodePageFromStringA(const FX_CHAR* pStr, int32_t iLength) { - ASSERT(pStr); - if (iLength < 0) { - iLength = FXSYS_strlen(pStr); - } - if (iLength == 0) { - return 0xFFFF; - } - uint32_t uHash = FX_HashCode_GetA(CFX_ByteStringC(pStr, iLength), true); - int32_t iStart = 0; - int32_t iEnd = sizeof(g_FXCPHashTable) / sizeof(FX_STR2CPHASH) - 1; - ASSERT(iEnd >= 0); - do { - int32_t iMid = (iStart + iEnd) / 2; - const FX_STR2CPHASH& cp = g_FXCPHashTable[iMid]; - if (uHash == cp.uHash) { - return (uint16_t)cp.uCodePage; - } else if (uHash < cp.uHash) { - iEnd = iMid - 1; - } else { - iStart = iMid + 1; - } - } while (iStart <= iEnd); - return 0xFFFF; -} - -} // namespace - -uint16_t FX_GetCodePageFromCharset(uint8_t charset) { - int32_t iEnd = sizeof(g_FXCharset2CodePageTable) / sizeof(FX_CHARSET_MAP) - 1; - ASSERT(iEnd >= 0); - int32_t 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; -} - -uint16_t FX_GetDefCodePageByLanguage(uint16_t wLanguage) { - int32_t iEnd = sizeof(g_FXLang2CodepageTable) / sizeof(FX_LANG2CPMAP) - 1; - ASSERT(iEnd >= 0); - int32_t 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; -} - -uint16_t FX_GetCodePageFromStringW(const FX_WCHAR* pStr, int32_t iLength) { - if (iLength < 0) { - iLength = FXSYS_wcslen(pStr); - } - if (iLength == 0) { - return 0xFFFF; - } - CFX_ByteString csStr; - FX_CHAR* pBuf = csStr.GetBuffer(iLength + 1); - for (int32_t i = 0; i < iLength; ++i) { - *pBuf++ = (FX_CHAR)*pStr++; - } - csStr.ReleaseBuffer(iLength); - return GetCodePageFromStringA(csStr.c_str(), iLength); -} - -void FX_SwapByteOrder(FX_WCHAR* pStr, int32_t iLength) { - ASSERT(pStr); - if (iLength < 0) { - iLength = FXSYS_wcslen(pStr); - } - uint16_t wch; - if (sizeof(FX_WCHAR) > 2) { - while (iLength-- > 0) { - wch = (uint16_t)*pStr; - wch = (wch >> 8) | (wch << 8); - wch &= 0x00FF; - *pStr++ = wch; - } - } else { - while (iLength-- > 0) { - wch = (uint16_t)*pStr; - wch = (wch >> 8) | (wch << 8); - *pStr++ = wch; - } - } -} - -void FX_UTF16ToWChar(void* pBuffer, int32_t iLength) { - ASSERT(pBuffer && iLength > 0); - if (sizeof(FX_WCHAR) == 2) { - return; - } - uint16_t* pSrc = (uint16_t*)pBuffer; - FX_WCHAR* pDst = (FX_WCHAR*)pBuffer; - while (--iLength >= 0) { - pDst[iLength] = (FX_WCHAR)pSrc[iLength]; - } -} - -int32_t FX_DecodeString(uint16_t wCodePage, - const FX_CHAR* pSrc, - int32_t* pSrcLen, - FX_WCHAR* pDst, - int32_t* pDstLen, - bool bErrBreak) { - if (wCodePage == FX_CODEPAGE_UTF8) { - return FX_UTF8Decode(pSrc, pSrcLen, pDst, pDstLen); - } - return -1; -} -int32_t FX_UTF8Decode(const FX_CHAR* pSrc, - int32_t* pSrcLen, - FX_WCHAR* pDst, - int32_t* pDstLen) { - if (!pSrcLen || !pDstLen) { - return -1; - } - int32_t iSrcLen = *pSrcLen; - if (iSrcLen < 1) { - *pSrcLen = *pDstLen = 0; - return 1; - } - int32_t iDstLen = *pDstLen; - bool bValidDst = (pDst && iDstLen > 0); - uint32_t dwCode = 0; - int32_t iPending = 0; - int32_t iSrcNum = 0, iDstNum = 0; - int32_t k = 0; - int32_t iIndex = 0; - k = 1; - while (iIndex < iSrcLen) { - uint8_t byte = (uint8_t) * (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/fgas/crt/fgas_codepage.h b/xfa/fgas/crt/fgas_codepage.h deleted file mode 100644 index 780c20e23353072746a086e057101b84d7293fb8..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_codepage.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_CRT_FGAS_CODEPAGE_H_ -#define XFA_FGAS_CRT_FGAS_CODEPAGE_H_ - -#include "core/fxcrt/fx_basic.h" - -#define FX_CODEPAGE_DefANSI 0 -#define FX_CODEPAGE_DefOEM 1 -#define FX_CODEPAGE_DefMAC 2 -#define FX_CODEPAGE_Thread 3 -#define FX_CODEPAGE_Symbol 42 -#define FX_CODEPAGE_MSDOS_US 437 -#define FX_CODEPAGE_Arabic_ASMO708 708 -#define FX_CODEPAGE_Arabic_ASMO449Plus 709 -#define FX_CODEPAGE_Arabic_Transparent 710 -#define FX_CODEPAGE_Arabic_NafithaEnhanced 711 -#define FX_CODEPAGE_Arabic_TransparentASMO 720 -#define FX_CODEPAGE_MSDOS_Greek1 737 -#define FX_CODEPAGE_MSDOS_Baltic 775 -#define FX_CODEPAGE_MSWin31_WesternEuropean 819 -#define FX_CODEPAGE_MSDOS_WesternEuropean 850 -#define FX_CODEPAGE_MSDOS_EasternEuropean 852 -#define FX_CODEPAGE_MSDOS_Latin3 853 -#define FX_CODEPAGE_MSDOS_Cyrillic 855 -#define FX_CODEPAGE_MSDOS_Turkish 857 -#define FX_CODEPAGE_MSDOS_Latin1Euro 858 -#define FX_CODEPAGE_MSDOS_Portuguese 860 -#define FX_CODEPAGE_MSDOS_Icelandic 861 -#define FX_CODEPAGE_MSDOS_Hebrew 862 -#define FX_CODEPAGE_MSDOS_FrenchCanadian 863 -#define FX_CODEPAGE_MSDOS_Arabic 864 -#define FX_CODEPAGE_MSDOS_Norwegian 865 -#define FX_CODEPAGE_MSDOS_Russian 866 -#define FX_CODEPAGE_MSDOS_Greek2 869 -#define FX_CODEPAGE_MSDOS_Thai 874 -#define FX_CODEPAGE_MSDOS_KamenickyCS 895 -#define FX_CODEPAGE_ShiftJIS 932 -#define FX_CODEPAGE_ChineseSimplified 936 -#define FX_CODEPAGE_Korean 949 -#define FX_CODEPAGE_ChineseTraditional 950 -#define FX_CODEPAGE_UTF16LE 1200 -#define FX_CODEPAGE_UTF16BE 1201 -#define FX_CODEPAGE_MSWin_EasternEuropean 1250 -#define FX_CODEPAGE_MSWin_Cyrillic 1251 -#define FX_CODEPAGE_MSWin_WesternEuropean 1252 -#define FX_CODEPAGE_MSWin_Greek 1253 -#define FX_CODEPAGE_MSWin_Turkish 1254 -#define FX_CODEPAGE_MSWin_Hebrew 1255 -#define FX_CODEPAGE_MSWin_Arabic 1256 -#define FX_CODEPAGE_MSWin_Baltic 1257 -#define FX_CODEPAGE_MSWin_Vietnamese 1258 -#define FX_CODEPAGE_Johab 1361 -#define FX_CODEPAGE_MAC_Roman 10000 -#define FX_CODEPAGE_MAC_ShiftJIS 10001 -#define FX_CODEPAGE_MAC_ChineseTraditional 10002 -#define FX_CODEPAGE_MAC_Korean 10003 -#define FX_CODEPAGE_MAC_Arabic 10004 -#define FX_CODEPAGE_MAC_Hebrew 10005 -#define FX_CODEPAGE_MAC_Greek 10006 -#define FX_CODEPAGE_MAC_Cyrillic 10007 -#define FX_CODEPAGE_MAC_ChineseSimplified 10008 -#define FX_CODEPAGE_MAC_Thai 10021 -#define FX_CODEPAGE_MAC_EasternEuropean 10029 -#define FX_CODEPAGE_MAC_Turkish 10081 -#define FX_CODEPAGE_UTF32LE 12000 -#define FX_CODEPAGE_UTF32BE 12001 -#define FX_CODEPAGE_ISO8859_1 28591 -#define FX_CODEPAGE_ISO8859_2 28592 -#define FX_CODEPAGE_ISO8859_3 28593 -#define FX_CODEPAGE_ISO8859_4 28594 -#define FX_CODEPAGE_ISO8859_5 28595 -#define FX_CODEPAGE_ISO8859_6 28596 -#define FX_CODEPAGE_ISO8859_7 28597 -#define FX_CODEPAGE_ISO8859_8 28598 -#define FX_CODEPAGE_ISO8859_9 28599 -#define FX_CODEPAGE_ISO8859_10 28600 -#define FX_CODEPAGE_ISO8859_11 28601 -#define FX_CODEPAGE_ISO8859_12 28602 -#define FX_CODEPAGE_ISO8859_13 28603 -#define FX_CODEPAGE_ISO8859_14 28604 -#define FX_CODEPAGE_ISO8859_15 28605 -#define FX_CODEPAGE_ISO8859_16 28606 -#define FX_CODEPAGE_ISCII_Devanagari 57002 -#define FX_CODEPAGE_ISCII_Bengali 57003 -#define FX_CODEPAGE_ISCII_Tamil 57004 -#define FX_CODEPAGE_ISCII_Telugu 57005 -#define FX_CODEPAGE_ISCII_Assamese 57006 -#define FX_CODEPAGE_ISCII_Oriya 57007 -#define FX_CODEPAGE_ISCII_Kannada 57008 -#define FX_CODEPAGE_ISCII_Malayalam 57009 -#define FX_CODEPAGE_ISCII_Gujarati 57010 -#define FX_CODEPAGE_ISCII_Punjabi 57011 -#define FX_CODEPAGE_UTF7 65000 -#define FX_CODEPAGE_UTF8 65001 -#define FX_CHARSET_ANSI 0 -#define FX_CHARSET_Default 1 -#define FX_CHARSET_Symbol 2 -#define FX_CHARSET_MAC_Roman 77 -#define FX_CHARSET_MAC_ShiftJIS 78 -#define FX_CHARSET_MAC_Korean 79 -#define FX_CHARSET_MAC_ChineseSimplified 80 -#define FX_CHARSET_MAC_ChineseTriditional 81 -#define FX_CHARSET_MAC_Johab 82 -#define FX_CHARSET_MAC_Hebrew 83 -#define FX_CHARSET_MAC_Arabic 84 -#define FX_CHARSET_MAC_Greek 85 -#define FX_CHARSET_MAC_Turkish 86 -#define FX_CHARSET_MAC_Thai 87 -#define FX_CHARSET_MAC_EasternEuropean 88 -#define FX_CHARSET_MAC_Cyrillic 89 -#define FX_CHARSET_ShiftJIS 128 -#define FX_CHARSET_Korean 129 -#define FX_CHARSET_Johab 130 -#define FX_CHARSET_ChineseSimplified 134 -#define FX_CHARSET_ChineseTriditional 136 -#define FX_CHARSET_MSWin_Greek 161 -#define FX_CHARSET_MSWin_Turkish 162 -#define FX_CHARSET_MSWin_Vietnamese 163 -#define FX_CHARSET_MSWin_Hebrew 177 -#define FX_CHARSET_MSWin_Arabic 178 -#define FX_CHARSET_ArabicTraditional 179 -#define FX_CHARSET_ArabicUser 180 -#define FX_CHARSET_HebrewUser 181 -#define FX_CHARSET_MSWin_Baltic 186 -#define FX_CHARSET_MSWin_Cyrillic 204 -#define FX_CHARSET_Thai 222 -#define FX_CHARSET_MSWin_EasterEuropean 238 -#define FX_CHARSET_US 254 -#define FX_CHARSET_OEM 255 - -uint16_t FX_GetCodePageFromCharset(uint8_t charset); -uint16_t FX_GetCodePageFromStringW(const FX_WCHAR* pStr, int32_t iLength); -uint16_t FX_GetDefCodePageByLanguage(uint16_t wLanguage); -void FX_SwapByteOrder(FX_WCHAR* pStr, int32_t iLength); - -void FX_UTF16ToWChar(void* pBuffer, int32_t iLength); -int32_t FX_DecodeString(uint16_t wCodePage, - const FX_CHAR* pSrc, - int32_t* pSrcLen, - FX_WCHAR* pDst, - int32_t* pDstLen, - bool bErrBreak); -int32_t FX_UTF8Decode(const FX_CHAR* pSrc, - int32_t* pSrcLen, - FX_WCHAR* pDst, - int32_t* pDstLen); - -#endif // XFA_FGAS_CRT_FGAS_CODEPAGE_H_ diff --git a/xfa/fgas/crt/fgas_language.h b/xfa/fgas/crt/fgas_language.h deleted file mode 100644 index 21d68e68a106f3fde92c6db8f05aa3815832b07c..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_language.h +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_CRT_FGAS_LANGUAGE_H_ -#define XFA_FGAS_CRT_FGAS_LANGUAGE_H_ - -#define FX_LANG_Neutral 0x0000 -#define FX_LANG_Invariant 0x007f -#define FX_LANG_UserDefault 0x0400 -#define FX_LANG_SystemDefault 0x0800 -#define FX_LANG_Afrikaans_SouthAfrica 0x0436 -#define FX_LANG_Albanian_Albania 0x041c -#define FX_LANG_Alsatian_France 0x0484 -#define FX_LANG_Amharic_Ethiopia 0x045e -#define FX_LANG_Arabic_Algeria 0x1401 -#define FX_LANG_Arabic_Bahrain 0x3c01 -#define FX_LANG_Arabic_Egypt 0x0c01 -#define FX_LANG_Arabic_Iraq 0x0801 -#define FX_LANG_Arabic_Jordan 0x2c01 -#define FX_LANG_Arabic_Kuwait 0x3401 -#define FX_LANG_Arabic_Lebanon 0x3001 -#define FX_LANG_Arabic_Libya 0x1001 -#define FX_LANG_Arabic_Morocco 0x1801 -#define FX_LANG_Arabic_Oman 0x2001 -#define FX_LANG_Arabic_Qatar 0x4001 -#define FX_LANG_Arabic_SaudiArabia 0x0401 -#define FX_LANG_Arabic_Syria 0x2801 -#define FX_LANG_Arabic_Tunisia 0x1c01 -#define FX_LANG_Arabic_UAE 0x3801 -#define FX_LANG_Arabic_Yemen 0x2401 -#define FX_LANG_Armenian_Armenia 0x042b -#define FX_LANG_Assamese_India 0x044d -#define FX_LANG_Azerbaijan_Cyrillic 0x082c -#define FX_LANG_Azerbaijan_Latin 0x042c -#define FX_LANG_Bashkir_Russia 0x046d -#define FX_LANG_Basque_Basque 0x042d -#define FX_LANG_Belarusian_Belarus 0x0423 -#define FX_LANG_Bengali_Bangladesh 0x0845 -#define FX_LANG_Bengali_India 0x0445 -#define FX_LANG_Bosnia_Herzegovina 0x101a -#define FX_LANG_Bosnian_Cyrillic 0x201a -#define FX_LANG_Bosnian_Latin 0x141a -#define FX_LANG_Breton_France 0x047e -#define FX_LANG_Bulgarian_Bulgaria 0x0402 -#define FX_LANG_Burmese 0x0455 -#define FX_LANG_Catalan_Catalan 0x0403 -#define FX_LANG_Cherokee 0x045c -#define FX_LANG_Chinese_HongKong 0x0c04 -#define FX_LANG_Chinese_Macao 0x1404 -#define FX_LANG_Chinese_PRC 0x0804 -#define FX_LANG_Chinese_Singapore 0x1004 -#define FX_LANG_Chinese_Taiwan 0x0404 -#define FX_LANG_Corsican_France 0x0483 -#define FX_LANG_Croatian_Croatia 0x041a -#define FX_LANG_Croatian_Latin 0x101a -#define FX_LANG_CustomCurrent 0x0c00 -#define FX_LANG_CzechRepublic 0x0405 -#define FX_LANG_Danish_Denmark 0x0406 -#define FX_LANG_Dari_Afghanistan 0x048c -#define FX_LANG_Divehi_Maldives 0x0465 -#define FX_LANG_Dutch_Belgium 0x0813 -#define FX_LANG_Dutch_Netherlands 0x0413 -#define FX_LANG_Dutch_Preferred 0x0013 -#define FX_LANG_Dzongkha 0x0851 -#define FX_LANG_Edo 0x0466 -#define FX_LANG_English_Australia 0x0c09 -#define FX_LANG_English_Belize 0x2809 -#define FX_LANG_English_Canada 0x1009 -#define FX_LANG_English_Caribbean 0x2409 -#define FX_LANG_English_HongKong 0x3c09 -#define FX_LANG_English_India 0x4009 -#define FX_LANG_English_Indonesia 0x3809 -#define FX_LANG_English_Ireland 0x1809 -#define FX_LANG_English_Jamaica 0x2009 -#define FX_LANG_English_Malaysia 0x4409 -#define FX_LANG_English_NewZealand 0x1409 -#define FX_LANG_English_Philippines 0x3409 -#define FX_LANG_English_Singapore 0x4809 -#define FX_LANG_English_SouthAfrica 0x1c09 -#define FX_LANG_English_TrinidadTobago 0x2c09 -#define FX_LANG_English_UnitedKingdom 0x0809 -#define FX_LANG_English_UnitedStates 0x0409 -#define FX_LANG_English_Zimbabwe 0x3009 -#define FX_LANG_Estonian_Estonia 0x0425 -#define FX_LANG_Faroese_FaroeIslands 0x0438 -#define FX_LANG_Filipino_Philippines 0x0464 -#define FX_LANG_Finnish_Finland 0x040b -#define FX_LANG_French_Belgium 0x080c -#define FX_LANG_French_Cameroon 0x2c0c -#define FX_LANG_French_Canada 0x0c0c -#define FX_LANG_French_CongoDRC 0x240c -#define FX_LANG_French_CotedIvoire 0x300c -#define FX_LANG_French_France 0x040c -#define FX_LANG_French_Haiti 0x3c0c -#define FX_LANG_French_Luxembourg 0x140c -#define FX_LANG_French_Mali 0x340c -#define FX_LANG_French_Monaco 0x180c -#define FX_LANG_French_Morocco 0x380c -#define FX_LANG_French_Reunion 0x200c -#define FX_LANG_French_Senegal 0x280c -#define FX_LANG_French_Switzerland 0x100c -#define FX_LANG_French_WestIndies 0x1c0c -#define FX_LANG_Frisian_Netherlands 0x0462 -#define FX_LANG_Fulfulde 0x0467 -#define FX_LANG_Gaelic_Ireland 0x083c -#define FX_LANG_Gaelic_Scotland 0x043c -#define FX_LANG_Galician_Galician 0x0456 -#define FX_LANG_Georgian_Georgia 0x0437 -#define FX_LANG_German_Austria 0x0c07 -#define FX_LANG_German_Germany 0x0407 -#define FX_LANG_German_Liechtenstein 0x1407 -#define FX_LANG_German_Luxembourg 0x1007 -#define FX_LANG_German_Switzerland 0x0807 -#define FX_LANG_Greek_Greece 0x0408 -#define FX_LANG_Greenlandic_Greenland 0x046f -#define FX_LANG_Guarani 0x0474 -#define FX_LANG_Gujarati_India 0x0447 -#define FX_LANG_Hausa_LatinNigeria 0x0468 -#define FX_LANG_Hawaiian 0x0475 -#define FX_LANG_Hebrew_Israel 0x040d -#define FX_LANG_Hindi_India 0x0439 -#define FX_LANG_Hungarian_Hungary 0x040e -#define FX_LANG_Ibibio_Nigeria 0x0469 -#define FX_LANG_Icelandic_Iceland 0x040f -#define FX_LANG_Igbo_Nigeria 0x0470 -#define FX_LANG_Indonesian_Indonesia 0x0421 -#define FX_LANG_Inuktitut_LatinCanada 0x085d -#define FX_LANG_Inuktitut_SyllabicsCanada 0x045d -#define FX_LANG_IsiXhosa_SouthAfrica 0x0434 -#define FX_LANG_IsiZulu_SouthAfrica 0x0435 -#define FX_LANG_Italian_Italy 0x0410 -#define FX_LANG_Italian_Switzerland 0x0810 -#define FX_LANG_Japanese_Japan 0x0411 -#define FX_LANG_Kannada_India 0x044b -#define FX_LANG_Kanuri 0x0471 -#define FX_LANG_Kashmiri 0x0860 -#define FX_LANG_Kashmiri_Arabic 0x0460 -#define FX_LANG_Kazakh_Kazakhstan 0x043f -#define FX_LANG_Khmer_Cambodia 0x0453 -#define FX_LANG_Kiche_Guatemala 0x0486 -#define FX_LANG_Kinyarwanda_Rwanda 0x0487 -#define FX_LANG_Kiswahili_Kenya 0x0441 -#define FX_LANG_Konkani_India 0x0457 -#define FX_LANG_Korean_Korea 0x0412 -#define FX_LANG_Kyrgyz_Kyrgyzstan 0x0440 -#define FX_LANG_Lao_LaoPDR 0x0454 -#define FX_LANG_Latin 0x0476 -#define FX_LANG_Latvian_Latvia 0x0426 -#define FX_LANG_Lithuanian_Lithuania 0x0427 -#define FX_LANG_LithuanianTrad 0x0827 -#define FX_LANG_Lower Sorbian_Germany 0x082e -#define FX_LANG_Luxembourgish_Luxembourg 0x046e -#define FX_LANG_Macedonian 0x042f -#define FX_LANG_Malay_BruneiDarussalam 0x083e -#define FX_LANG_Malay_Malaysia 0x043e -#define FX_LANG_Malayalam_India 0x044c -#define FX_LANG_Maldivian 0x0465 -#define FX_LANG_Maltese_Malta 0x043a -#define FX_LANG_Manipuri 0x0458 -#define FX_LANG_Maori_NewZealand 0x0481 -#define FX_LANG_Mapudungun_Chile 0x047a -#define FX_LANG_Marathi_India 0x044e -#define FX_LANG_Mohawk_Mohawk 0x047c -#define FX_LANG_Mongolian_CyrillicMongolia 0x0450 -#define FX_LANG_Mongolian_TraditionalMongolian 0x0850 -#define FX_LANG_Nepali_India 0x0861 -#define FX_LANG_Nepali_Nepal 0x0461 -#define FX_LANG_Norwegian_Bokmal 0x0414 -#define FX_LANG_Norwegian_Nynorsk 0x0814 -#define FX_LANG_Occitan_France 0x0482 -#define FX_LANG_Oriya_India 0x0448 -#define FX_LANG_Oromo 0x0472 -#define FX_LANG_Papiamentu 0x0479 -#define FX_LANG_Pashto_Afghanistan 0x0463 -#define FX_LANG_Persian 0x0429 -#define FX_LANG_Polish_Poland 0x0415 -#define FX_LANG_Portuguese_Brazil 0x0416 -#define FX_LANG_Portuguese_Portugal 0x0816 -#define FX_LANG_Punjabi_India 0x0446 -#define FX_LANG_Punjabi_Pakistan 0x0846 -#define FX_LANG_Quechua_Bolivia 0x046b -#define FX_LANG_Quechua_Ecuador 0x086b -#define FX_LANG_Quechua_Peru 0x0c6b -#define FX_LANG_Romanian_Moldova 0x0818 -#define FX_LANG_Romanian_Romania 0x0418 -#define FX_LANG_Romansh_Switzerland 0x0417 -#define FX_LANG_Russian_Moldova 0x0819 -#define FX_LANG_Russian_Russia 0x0419 -#define FX_LANG_Sami_InariFinland 0x243b -#define FX_LANG_Sami_LuleNorway 0x103b -#define FX_LANG_Sami_LuleSweden 0x143b -#define FX_LANG_Sami_NorthernFinland 0x0c3b -#define FX_LANG_Sami_NorthernNorway 0x043b -#define FX_LANG_Sami_NorthernSweden 0x083b -#define FX_LANG_Sami_SkoltFinland 0x203b -#define FX_LANG_Sami_SouthernNorway 0x183b -#define FX_LANG_Sami_SouthernSweden 0x1c3b -#define FX_LANG_SanskritIndia 0x044f -#define FX_LANG_SerbianCyrillic_BosniaHerzegovina 0x1c1a -#define FX_LANG_SerbianCyrillic_Serbia 0x0c1a -#define FX_LANG_SerbianLatin_BosniaHerzegovina 0x181a -#define FX_LANG_SerbianLatin_Serbia 0x081a -#define FX_LANG_SesothoSaLeboa 0x046c -#define FX_LANG_Setswana_SouthAfrica 0x0432 -#define FX_LANG_Sindhi_Arabic 0x0859 -#define FX_LANG_Sindhi_Devanagari 0x0459 -#define FX_LANG_Sinhala_SriLanka 0x045b -#define FX_LANG_Slovak_Slovakia 0x041b -#define FX_LANG_Slovenian_Slovenia 0x0424 -#define FX_LANG_Somali 0x0477 -#define FX_LANG_Spanish_Argentina 0x2c0a -#define FX_LANG_Spanish_Bolivia 0x400a -#define FX_LANG_Spanish_Chile 0x340a -#define FX_LANG_Spanish_Colombia 0x240a -#define FX_LANG_Spanish_CostaRica 0x140a -#define FX_LANG_Spanish_DominicanRepublic 0x1c0a -#define FX_LANG_Spanish_Ecuador 0x300a -#define FX_LANG_Spanish_ElSalvador 0x440a -#define FX_LANG_Spanish_Guatemala 0x100a -#define FX_LANG_Spanish_Honduras 0x480a -#define FX_LANG_Spanish_Mexico 0x080a -#define FX_LANG_Spanish_Nicaragua 0x4c0a -#define FX_LANG_Spanish_Panama 0x180a -#define FX_LANG_Spanish_Paraguay 0x3c0a -#define FX_LANG_Spanish_Peru 0x280a -#define FX_LANG_Spanish_PuertoRico 0x500a -#define FX_LANG_Spanish_InternationalSort 0x0c0a -#define FX_LANG_Spanish_TraditionalSort 0x040a -#define FX_LANG_Spanish_UnitedStates 0x540a -#define FX_LANG_Spanish_Uruguay 0x380a -#define FX_LANG_Spanish_Venezuela 0x200a -#define FX_LANG_Sutu_SouthAfrica 0x0430 -#define FX_LANG_Swedish_Finland 0x081d -#define FX_LANG_Swedish_Sweden 0x041d -#define FX_LANG_Syriac_Syria 0x045a -#define FX_LANG_Tajik_CyrillicTajikistan 0x0428 -#define FX_LANG_Tamazight_ArabicMorocco 0x045f -#define FX_LANG_Tamazight_LatinAlgeria 0x085f -#define FX_LANG_Tamil_India 0x0449 -#define FX_LANG_Tatar_Russia 0x0444 -#define FX_LANG_Telugu_India 0x044a -#define FX_LANG_Thai_Thailand 0x041e -#define FX_LANG_TibetanPRC 0x0451 -#define FX_LANG_Tigrigna_Eritrea 0x0873 -#define FX_LANG_Tigrigna_Ethiopia 0x0473 -#define FX_LANG_Tsonga 0x0431 -#define FX_LANG_Turkish_Turkey 0x041f -#define FX_LANG_Turkmen_Turkmenistan 0x0442 -#define FX_LANG_UighurPRC 0x0480 -#define FX_LANG_Ukrainian_Ukraine 0x0422 -#define FX_LANG_UpperSorbian_Germany 0x042e -#define FX_LANG_Urdu_Pakistan 0x0420 -#define FX_LANG_Urdu_India 0x0820 -#define FX_LANG_Uzbek_CyrillicUzbekistan 0x0843 -#define FX_LANG_Uzbek_LatinUzbekistan 0x0443 -#define FX_LANG_Venda 0x0433 -#define FX_LANG_Vietnamese_Vietnam 0x042a -#define FX_LANG_Welsh_UnitedKingdom 0x0452 -#define FX_LANG_Wolof_Senegal 0x0488 -#define FX_LANG_Xhosa 0x0434 -#define FX_LANG_Yakut_Russia 0x0485 -#define FX_LANG_YiPRC 0x0478 -#define FX_LANG_Yiddish 0x043d -#define FX_LANG_Yoruba_Nigeria 0x046a - -#endif // XFA_FGAS_CRT_FGAS_LANGUAGE_H_ diff --git a/xfa/fgas/crt/fgas_stream.cpp b/xfa/fgas/crt/fgas_stream.cpp deleted file mode 100644 index 424b191cb8e1715697f9f812b133db080696d7cb..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_stream.cpp +++ /dev/null @@ -1,1483 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fgas/crt/fgas_stream.h" - -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \ - _FX_OS_ == _FX_WIN64_ -#include <io.h> -#endif - -#include <algorithm> -#include <memory> - -#include "third_party/base/ptr_util.h" -#include "xfa/fgas/crt/fgas_codepage.h" - -namespace { - -class IFGAS_StreamImp { - public: - virtual ~IFGAS_StreamImp() {} - - virtual int32_t GetLength() const = 0; - virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) = 0; - virtual int32_t GetPosition() = 0; - virtual bool IsEOF() const = 0; - virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) = 0; - virtual int32_t ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) = 0; - virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) = 0; - virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) = 0; - virtual void Flush() = 0; - virtual bool SetLength(int32_t iLength) = 0; - - protected: - IFGAS_StreamImp(); - - uint32_t GetAccessModes() const { return m_dwAccess; } - void SetAccessModes(uint32_t modes) { m_dwAccess = modes; } - - private: - uint32_t m_dwAccess; -}; - -class CFGAS_FileStreamImp : public IFGAS_StreamImp { - public: - CFGAS_FileStreamImp(); - ~CFGAS_FileStreamImp() override; - - bool LoadFile(const FX_WCHAR* pszSrcFileName, uint32_t dwAccess); - - // IFGAS_StreamImp: - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override; - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override; - void Flush() override; - bool SetLength(int32_t iLength) override; - - protected: - FXSYS_FILE* m_hFile; - int32_t m_iLength; -}; - -class CFGAS_BufferStreamImp : public IFGAS_StreamImp { - public: - CFGAS_BufferStreamImp(); - ~CFGAS_BufferStreamImp() override {} - - bool LoadBuffer(uint8_t* pData, int32_t iTotalSize, uint32_t dwAccess); - - // IFGAS_StreamImp: - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override; - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override; - void Flush() override {} - bool SetLength(int32_t iLength) override { return false; } - - protected: - uint8_t* m_pData; - int32_t m_iTotalSize; - int32_t m_iPosition; - int32_t m_iLength; -}; - -class CFGAS_FileReadStreamImp : public IFGAS_StreamImp { - public: - CFGAS_FileReadStreamImp(); - ~CFGAS_FileReadStreamImp() override {} - - bool LoadFileRead(const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead, - uint32_t dwAccess); - - // IFGAS_StreamImp: - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override { return m_iPosition; } - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override { - return 0; - } - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override { - return 0; - } - void Flush() override {} - bool SetLength(int32_t iLength) override { return false; } - - protected: - CFX_RetainPtr<IFX_SeekableReadStream> m_pFileRead; - int32_t m_iPosition; - int32_t m_iLength; -}; - -class CFGAS_BufferReadStreamImp : public IFGAS_StreamImp { - public: - CFGAS_BufferReadStreamImp(); - ~CFGAS_BufferReadStreamImp() override; - - bool LoadBufferRead(const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead, - int32_t iFileSize, - uint32_t dwAccess); - - // IFGAS_StreamImp: - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override { return m_iPosition; } - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override { - return 0; - } - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override { - return 0; - } - void Flush() override {} - bool SetLength(int32_t iLength) override { return false; } - - private: - CFX_RetainPtr<IFX_BufferedReadStream> m_pBufferRead; - int32_t m_iPosition; - int32_t m_iBufferSize; -}; - -class CFGAS_FileWriteStreamImp : public IFGAS_StreamImp { - public: - CFGAS_FileWriteStreamImp(); - ~CFGAS_FileWriteStreamImp() override {} - - bool LoadFileWrite(const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite, - uint32_t dwAccess); - - // IFGAS_StreamImp: - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override { return m_iPosition; } - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override { return 0; } - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override { - return 0; - } - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override; - void Flush() override; - bool SetLength(int32_t iLength) override { return false; } - - protected: - CFX_RetainPtr<IFX_SeekableWriteStream> m_pFileWrite; - int32_t m_iPosition; -}; - -enum FX_STREAMTYPE { - FX_SREAMTYPE_Unknown = 0, - FX_STREAMTYPE_File, - FX_STREAMTYPE_Buffer, - FX_STREAMTYPE_Stream, - FX_STREAMTYPE_BufferRead, -}; - -class CFGAS_Stream : public IFGAS_Stream { - public: - template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - bool LoadFile(const FX_WCHAR* pszSrcFileName, uint32_t dwAccess); - bool LoadBuffer(uint8_t* pData, int32_t iTotalSize, uint32_t dwAccess); - bool LoadFileRead(const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead, - uint32_t dwAccess); - bool LoadFileWrite(const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite, - uint32_t dwAccess); - bool LoadBufferRead(const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead, - int32_t iFileSize, - uint32_t dwAccess); - - // IFGAS_Stream - uint32_t GetAccessModes() const override; - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override; - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override; - void Flush() override; - bool SetLength(int32_t iLength) override; - int32_t GetBOM(uint8_t bom[4]) const override; - uint16_t GetCodePage() const override; - uint16_t SetCodePage(uint16_t wCodePage) override; - CFX_RetainPtr<IFGAS_Stream> CreateSharedStream(uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) override; - - protected: - CFGAS_Stream(); - ~CFGAS_Stream() override; - - FX_STREAMTYPE m_eStreamType; - IFGAS_StreamImp* m_pStreamImp; - uint32_t m_dwAccess; - int32_t m_iTotalSize; - int32_t m_iPosition; - int32_t m_iStart; - int32_t m_iLength; - int32_t m_iRefCount; -}; - -class CFGAS_TextStream : public IFGAS_Stream { - public: - template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - // IFGAS_Stream - uint32_t GetAccessModes() const override; - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override; - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override; - void Flush() override; - bool SetLength(int32_t iLength) override; - int32_t GetBOM(uint8_t bom[4]) const override; - uint16_t GetCodePage() const override; - uint16_t SetCodePage(uint16_t wCodePage) override; - CFX_RetainPtr<IFGAS_Stream> CreateSharedStream(uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) override; - - protected: - explicit CFGAS_TextStream(const CFX_RetainPtr<IFGAS_Stream>& pStream); - ~CFGAS_TextStream() override; - - void InitStream(); - - uint16_t m_wCodePage; - int32_t m_wBOMLength; - uint32_t m_dwBOM; - uint8_t* m_pBuf; - int32_t m_iBufSize; - CFX_RetainPtr<IFGAS_Stream> m_pStreamImp; -}; - -class CFGAS_FileRead : public IFX_SeekableReadStream { - public: - static CFX_RetainPtr<CFGAS_FileRead> Create( - const CFX_RetainPtr<IFGAS_Stream>& pStream); - - explicit CFGAS_FileRead(const CFX_RetainPtr<IFGAS_Stream>& pStream); - ~CFGAS_FileRead() override; - - // IFX_SeekableReadStream - FX_FILESIZE GetSize() override; - bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; - - protected: - CFX_RetainPtr<IFGAS_Stream> m_pStream; -}; - -int32_t FileLength(FXSYS_FILE* file) { - ASSERT(file); -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_ - return _filelength(_fileno(file)); -#else - int32_t iPos = FXSYS_ftell(file); - FXSYS_fseek(file, 0, FXSYS_SEEK_END); - int32_t iLen = FXSYS_ftell(file); - FXSYS_fseek(file, iPos, FXSYS_SEEK_SET); - return iLen; -#endif -} - -bool FileSetSize(FXSYS_FILE* file, int32_t size) { - ASSERT(file); -#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); - uint32_t dwPos = ::SetFilePointer(hFile, 0, 0, FILE_CURRENT); - ::SetFilePointer(hFile, size, 0, FILE_BEGIN); - bool bRet = ::SetEndOfFile(hFile); - ::SetFilePointer(hFile, (int32_t)dwPos, 0, FILE_BEGIN); - return bRet; -#else - return false; -#endif -} - -} // namespace - -// static -CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateStream( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead, - uint32_t dwAccess) { - auto pSR = pdfium::MakeRetain<CFGAS_Stream>(); - if (!pSR->LoadFileRead(pFileRead, dwAccess)) - return nullptr; - - if (dwAccess & FX_STREAMACCESS_Text) - return pdfium::MakeRetain<CFGAS_TextStream>(pSR); - - return pSR; -} - -// static -CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateStream( - const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite, - uint32_t dwAccess) { - auto pSR = pdfium::MakeRetain<CFGAS_Stream>(); - if (!pSR->LoadFileWrite(pFileWrite, dwAccess)) - return nullptr; - - if (dwAccess & FX_STREAMACCESS_Text) - return pdfium::MakeRetain<CFGAS_TextStream>(pSR); - - return pSR; -} - -// static -CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateStream(uint8_t* pData, - int32_t length, - uint32_t dwAccess) { - auto pSR = pdfium::MakeRetain<CFGAS_Stream>(); - if (!pSR->LoadBuffer(pData, length, dwAccess)) - return nullptr; - - if (dwAccess & FX_STREAMACCESS_Text) - return pdfium::MakeRetain<CFGAS_TextStream>(pSR); - - return pSR; -} - -IFGAS_StreamImp::IFGAS_StreamImp() : m_dwAccess(0) {} - -CFGAS_FileStreamImp::CFGAS_FileStreamImp() : m_hFile(nullptr), m_iLength(0) {} - -CFGAS_FileStreamImp::~CFGAS_FileStreamImp() { - if (m_hFile) - FXSYS_fclose(m_hFile); -} - -bool CFGAS_FileStreamImp::LoadFile(const FX_WCHAR* pszSrcFileName, - uint32_t dwAccess) { - ASSERT(!m_hFile); - ASSERT(pszSrcFileName && FXSYS_wcslen(pszSrcFileName) > 0); -#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \ - _FX_OS_ == _FX_WIN64_ - const FX_WCHAR* 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"; - } - m_hFile = FXSYS_wfopen(pszSrcFileName, wsMode); - - if (!m_hFile) { - if (dwAccess & FX_STREAMACCESS_Write) { - if (dwAccess & FX_STREAMACCESS_Create) - m_hFile = FXSYS_wfopen(pszSrcFileName, L"w+b"); - - if (!m_hFile) { - m_hFile = FXSYS_wfopen(pszSrcFileName, L"r+b"); - if (!m_hFile) - return false; - - if (dwAccess & FX_STREAMACCESS_Truncate) - FileSetSize(m_hFile, 0); - } - } else { - return false; - } - } -#else - const FX_CHAR* wsMode = "rb"; - 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"; - } - } - CFX_ByteString szFileName = CFX_ByteString::FromUnicode(pszSrcFileName); - m_hFile = FXSYS_fopen(szFileName.c_str(), wsMode); - if (!m_hFile) { - if (dwAccess & FX_STREAMACCESS_Write) { - if (dwAccess & FX_STREAMACCESS_Create) { - m_hFile = FXSYS_fopen(szFileName.c_str(), "w+b"); - } - if (!m_hFile) { - m_hFile = FXSYS_fopen(szFileName.c_str(), "r+b"); - if (!m_hFile) { - return false; - } - if (dwAccess & FX_STREAMACCESS_Truncate) { - FileSetSize(m_hFile, 0); - } - } - } else { - return false; - } - } -#endif - SetAccessModes(dwAccess); - if ((dwAccess & (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) == - (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) { - m_iLength = 0; - } else { - m_iLength = FileLength(m_hFile); - } - return true; -} -int32_t CFGAS_FileStreamImp::GetLength() const { - ASSERT(m_hFile); - return m_iLength; -} -int32_t CFGAS_FileStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) { - ASSERT(m_hFile); - FXSYS_fseek(m_hFile, iOffset, eSeek); - return FXSYS_ftell(m_hFile); -} -int32_t CFGAS_FileStreamImp::GetPosition() { - ASSERT(m_hFile); - return FXSYS_ftell(m_hFile); -} -bool CFGAS_FileStreamImp::IsEOF() const { - ASSERT(m_hFile); - return FXSYS_ftell(m_hFile) >= m_iLength; -} -int32_t CFGAS_FileStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) { - ASSERT(m_hFile); - ASSERT(pBuffer && iBufferSize > 0); - return FXSYS_fread(pBuffer, 1, iBufferSize, m_hFile); -} -int32_t CFGAS_FileStreamImp::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - ASSERT(m_hFile); - ASSERT(pStr && iMaxLength > 0); - if (m_iLength <= 0) { - return 0; - } - int32_t iPosition = FXSYS_ftell(m_hFile); - int32_t iLen = std::min((m_iLength - iPosition) / 2, iMaxLength); - if (iLen <= 0) { - return 0; - } - iLen = FXSYS_fread(pStr, 2, iLen, m_hFile); - int32_t 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; -} -int32_t CFGAS_FileStreamImp::WriteData(const uint8_t* pBuffer, - int32_t iBufferSize) { - ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0); - ASSERT(pBuffer && iBufferSize > 0); - int32_t iRet = FXSYS_fwrite(pBuffer, 1, iBufferSize, m_hFile); - if (iRet != 0) { - int32_t iPos = FXSYS_ftell(m_hFile); - if (iPos > m_iLength) { - m_iLength = iPos; - } - } - return iRet; -} -int32_t CFGAS_FileStreamImp::WriteString(const FX_WCHAR* pStr, - int32_t iLength) { - ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0); - ASSERT(pStr && iLength > 0); - int32_t iRet = FXSYS_fwrite(pStr, 2, iLength, m_hFile); - if (iRet != 0) { - int32_t iPos = FXSYS_ftell(m_hFile); - if (iPos > m_iLength) { - m_iLength = iPos; - } - } - return iRet; -} -void CFGAS_FileStreamImp::Flush() { - ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0); - FXSYS_fflush(m_hFile); -} -bool CFGAS_FileStreamImp::SetLength(int32_t iLength) { - ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0); - bool bRet = FileSetSize(m_hFile, iLength); - m_iLength = FileLength(m_hFile); - return bRet; -} - -CFGAS_FileReadStreamImp::CFGAS_FileReadStreamImp() - : m_pFileRead(nullptr), m_iPosition(0), m_iLength(0) {} - -bool CFGAS_FileReadStreamImp::LoadFileRead( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead, - uint32_t dwAccess) { - ASSERT(!m_pFileRead && pFileRead); - if (dwAccess & FX_STREAMACCESS_Write) - return false; - - m_pFileRead = pFileRead; - m_iLength = m_pFileRead->GetSize(); - return true; -} - -int32_t CFGAS_FileReadStreamImp::GetLength() const { - return m_iLength; -} -int32_t CFGAS_FileReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t 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; -} -bool CFGAS_FileReadStreamImp::IsEOF() const { - return m_iPosition >= m_iLength; -} -int32_t CFGAS_FileReadStreamImp::ReadData(uint8_t* pBuffer, - int32_t iBufferSize) { - ASSERT(m_pFileRead); - ASSERT(pBuffer && 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; -} -int32_t CFGAS_FileReadStreamImp::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - ASSERT(m_pFileRead); - ASSERT(pStr && iMaxLength > 0); - iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2; - if (iMaxLength <= 0) { - return 0; - } - int32_t i = 0; - while (i < iMaxLength && pStr[i] != L'\0') { - ++i; - } - bEOS = (m_iPosition >= m_iLength) || pStr[i] == L'\0'; - return i; -} - -CFGAS_BufferReadStreamImp::CFGAS_BufferReadStreamImp() - : m_iPosition(0), m_iBufferSize(0) {} - -CFGAS_BufferReadStreamImp::~CFGAS_BufferReadStreamImp() {} - -bool CFGAS_BufferReadStreamImp::LoadBufferRead( - const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead, - int32_t iFileSize, - uint32_t dwAccess) { - ASSERT(!m_pBufferRead && pBufferRead); - if (dwAccess & FX_STREAMACCESS_Write) - return false; - - 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; -} -int32_t CFGAS_BufferReadStreamImp::GetLength() const { - return m_iBufferSize; -} -int32_t CFGAS_BufferReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) { - int32_t 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; -} -bool CFGAS_BufferReadStreamImp::IsEOF() const { - return m_pBufferRead ? m_pBufferRead->IsEOF() : true; -} -int32_t CFGAS_BufferReadStreamImp::ReadData(uint8_t* pBuffer, - int32_t iBufferSize) { - ASSERT(m_pBufferRead); - ASSERT(pBuffer && iBufferSize > 0); - int32_t iLength = GetLength(); - if (m_iPosition >= iLength) { - return 0; - } - if (iBufferSize > iLength - m_iPosition) { - iBufferSize = iLength - m_iPosition; - } - uint32_t dwBlockOffset = m_pBufferRead->GetBlockOffset(); - uint32_t dwBlockSize = m_pBufferRead->GetBlockSize(); - if (m_iPosition < (int32_t)dwBlockOffset) { - if (!m_pBufferRead->ReadNextBlock(true)) { - return 0; - } - dwBlockOffset = m_pBufferRead->GetBlockOffset(); - dwBlockSize = m_pBufferRead->GetBlockSize(); - } - while (m_iPosition < (int32_t)dwBlockOffset || - m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) { - if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(false)) { - break; - } - dwBlockOffset = m_pBufferRead->GetBlockOffset(); - dwBlockSize = m_pBufferRead->GetBlockSize(); - } - if (m_iPosition < (int32_t)dwBlockOffset || - m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) { - return 0; - } - const uint8_t* pBufferTmp = m_pBufferRead->GetBlockBuffer(); - uint32_t dwOffsetTmp = m_iPosition - dwBlockOffset; - uint32_t dwCopySize = - std::min(iBufferSize, (int32_t)(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 = std::min((uint32_t)iBufferSize, dwBlockSize); - FXSYS_memcpy(pBuffer + dwOffsetTmp, pBufferTmp, dwCopySize); - dwOffsetTmp += dwCopySize; - iBufferSize -= dwCopySize; - } - m_iPosition += dwOffsetTmp; - return dwOffsetTmp; -} -int32_t CFGAS_BufferReadStreamImp::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - ASSERT(m_pBufferRead); - ASSERT(pStr && iMaxLength > 0); - iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2; - if (iMaxLength <= 0) { - return 0; - } - int32_t i = 0; - while (i < iMaxLength && pStr[i] != L'\0') { - ++i; - } - bEOS = (m_iPosition >= GetLength()) || pStr[i] == L'\0'; - return i; -} -CFGAS_FileWriteStreamImp::CFGAS_FileWriteStreamImp() - : m_pFileWrite(nullptr), m_iPosition(0) {} - -bool CFGAS_FileWriteStreamImp::LoadFileWrite( - const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite, - uint32_t dwAccess) { - ASSERT(!m_pFileWrite && pFileWrite); - if (dwAccess & FX_STREAMACCESS_Read) - return false; - - if (dwAccess & FX_STREAMACCESS_Append) - m_iPosition = pFileWrite->GetSize(); - - m_pFileWrite = pFileWrite; - return true; -} - -int32_t CFGAS_FileWriteStreamImp::GetLength() const { - if (!m_pFileWrite) - return 0; - - return (int32_t)m_pFileWrite->GetSize(); -} -int32_t CFGAS_FileWriteStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) { - int32_t 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; -} -bool CFGAS_FileWriteStreamImp::IsEOF() const { - return m_iPosition >= GetLength(); -} -int32_t CFGAS_FileWriteStreamImp::WriteData(const uint8_t* pBuffer, - int32_t iBufferSize) { - if (!m_pFileWrite) { - return 0; - } - if (m_pFileWrite->WriteBlock(pBuffer, m_iPosition, iBufferSize)) { - m_iPosition += iBufferSize; - } - return iBufferSize; -} -int32_t CFGAS_FileWriteStreamImp::WriteString(const FX_WCHAR* pStr, - int32_t iLength) { - return WriteData((const uint8_t*)pStr, iLength * sizeof(FX_WCHAR)); -} -void CFGAS_FileWriteStreamImp::Flush() { - if (m_pFileWrite) { - m_pFileWrite->Flush(); - } -} -CFGAS_BufferStreamImp::CFGAS_BufferStreamImp() - : m_pData(nullptr), m_iTotalSize(0), m_iPosition(0), m_iLength(0) {} - -bool CFGAS_BufferStreamImp::LoadBuffer(uint8_t* pData, - int32_t iTotalSize, - uint32_t dwAccess) { - ASSERT(!m_pData && pData && iTotalSize > 0); - SetAccessModes(dwAccess); - m_pData = pData; - m_iTotalSize = iTotalSize; - m_iPosition = 0; - m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iTotalSize; - return true; -} -int32_t CFGAS_BufferStreamImp::GetLength() const { - ASSERT(m_pData); - return m_iLength; -} -int32_t CFGAS_BufferStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) { - ASSERT(m_pData); - 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; -} -int32_t CFGAS_BufferStreamImp::GetPosition() { - ASSERT(m_pData); - return m_iPosition; -} -bool CFGAS_BufferStreamImp::IsEOF() const { - ASSERT(m_pData); - return m_iPosition >= m_iLength; -} -int32_t CFGAS_BufferStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) { - ASSERT(m_pData); - ASSERT(pBuffer && iBufferSize > 0); - int32_t iLen = std::min(m_iLength - m_iPosition, iBufferSize); - if (iLen <= 0) { - return 0; - } - FXSYS_memcpy(pBuffer, m_pData + m_iPosition, iLen); - m_iPosition += iLen; - return iLen; -} -int32_t CFGAS_BufferStreamImp::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - ASSERT(m_pData); - ASSERT(pStr && iMaxLength > 0); - int32_t iLen = std::min((m_iLength - m_iPosition) / 2, iMaxLength); - if (iLen <= 0) { - return 0; - } - const FX_WCHAR* pSrc = (const FX_WCHAR*)(FX_CHAR*)(m_pData + m_iPosition); - int32_t iCount = 0; - while (*pSrc && iCount < iLen) { - *pStr++ = *pSrc++; - iCount++; - } - m_iPosition += iCount * 2; - bEOS = (*pSrc == L'\0') || (m_iPosition >= m_iLength); - return iCount; -} -int32_t CFGAS_BufferStreamImp::WriteData(const uint8_t* pBuffer, - int32_t iBufferSize) { - ASSERT(m_pData && (GetAccessModes() & FX_STREAMACCESS_Write) != 0); - ASSERT(pBuffer && iBufferSize > 0); - int32_t iLen = std::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; -} -int32_t CFGAS_BufferStreamImp::WriteString(const FX_WCHAR* pStr, - int32_t iLength) { - ASSERT(m_pData && (GetAccessModes() & FX_STREAMACCESS_Write) != 0); - ASSERT(pStr && iLength > 0); - int32_t iLen = std::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; -} - -// static -CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateTextStream( - const CFX_RetainPtr<IFGAS_Stream>& pBaseStream) { - ASSERT(pBaseStream); - return pdfium::MakeRetain<CFGAS_TextStream>(pBaseStream); -} - -CFGAS_TextStream::CFGAS_TextStream(const CFX_RetainPtr<IFGAS_Stream>& pStream) - : m_wCodePage(FX_CODEPAGE_DefANSI), - m_wBOMLength(0), - m_dwBOM(0), - m_pBuf(nullptr), - m_iBufSize(0), - m_pStreamImp(pStream) { - ASSERT(m_pStreamImp); - InitStream(); -} - -CFGAS_TextStream::~CFGAS_TextStream() { - if (m_pBuf) - FX_Free(m_pBuf); -} - -void CFGAS_TextStream::InitStream() { - int32_t iPosition = m_pStreamImp->GetPosition(); - m_pStreamImp->Seek(FX_STREAMSEEK_Begin, 0); - m_pStreamImp->ReadData((uint8_t*)&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, std::max(m_wBOMLength, iPosition)); -} - -uint32_t CFGAS_TextStream::GetAccessModes() const { - return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text; -} - -int32_t CFGAS_TextStream::GetLength() const { - return m_pStreamImp->GetLength(); -} - -int32_t CFGAS_TextStream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) { - return m_pStreamImp->Seek(eSeek, iOffset); -} - -int32_t CFGAS_TextStream::GetPosition() { - return m_pStreamImp->GetPosition(); -} - -bool CFGAS_TextStream::IsEOF() const { - return m_pStreamImp->IsEOF(); -} - -int32_t CFGAS_TextStream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) { - return m_pStreamImp->ReadData(pBuffer, iBufferSize); -} - -int32_t CFGAS_TextStream::WriteData(const uint8_t* pBuffer, - int32_t iBufferSize) { - return m_pStreamImp->WriteData(pBuffer, iBufferSize); -} - -void CFGAS_TextStream::Flush() { - m_pStreamImp->Flush(); -} - -bool CFGAS_TextStream::SetLength(int32_t iLength) { - return m_pStreamImp->SetLength(iLength); -} - -uint16_t CFGAS_TextStream::GetCodePage() const { - return m_wCodePage; -} - -CFX_RetainPtr<IFGAS_Stream> CFGAS_TextStream::CreateSharedStream( - uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) { - CFX_RetainPtr<IFGAS_Stream> pSR = - m_pStreamImp->CreateSharedStream(dwAccess, iOffset, iLength); - if (!pSR) - return nullptr; - - if (dwAccess & FX_STREAMACCESS_Text) - return pdfium::MakeRetain<CFGAS_TextStream>(pSR); - - return pSR; -} - -int32_t CFGAS_TextStream::GetBOM(uint8_t bom[4]) const { - if (m_wBOMLength < 1) - return 0; - - *(uint32_t*)bom = m_dwBOM; - return m_wBOMLength; -} - -uint16_t CFGAS_TextStream::SetCodePage(uint16_t wCodePage) { - if (m_wBOMLength > 0) - return m_wCodePage; - - uint16_t v = m_wCodePage; - m_wCodePage = wCodePage; - return v; -} - -int32_t CFGAS_TextStream::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - ASSERT(pStr && iMaxLength > 0); - if (!m_pStreamImp) { - return -1; - } - int32_t iLen; - if (m_wCodePage == FX_CODEPAGE_UTF16LE || - m_wCodePage == FX_CODEPAGE_UTF16BE) { - int32_t iBytes = iMaxLength * 2; - iLen = m_pStreamImp->ReadData((uint8_t*)pStr, iBytes); - 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 { - int32_t pos = m_pStreamImp->GetPosition(); - int32_t iBytes = iMaxLength; - iBytes = std::min(iBytes, m_pStreamImp->GetLength() - pos); - if (iBytes > 0) { - if (!m_pBuf) { - m_pBuf = FX_Alloc(uint8_t, iBytes); - m_iBufSize = iBytes; - } else if (iBytes > m_iBufSize) { - m_pBuf = FX_Realloc(uint8_t, m_pBuf, iBytes); - m_iBufSize = iBytes; - } - iLen = m_pStreamImp->ReadData(m_pBuf, iBytes); - int32_t iSrc = iLen; - int32_t iDecode = FX_DecodeString(m_wCodePage, (const FX_CHAR*)m_pBuf, - &iSrc, pStr, &iMaxLength, true); - m_pStreamImp->Seek(FX_STREAMSEEK_Current, iSrc - iLen); - if (iDecode < 1) { - return -1; - } - } else { - iMaxLength = 0; - } - } - bEOS = m_pStreamImp->IsEOF(); - return iMaxLength; -} - -int32_t CFGAS_TextStream::WriteString(const FX_WCHAR* pStr, int32_t iLength) { - ASSERT(pStr && iLength > 0); - if ((m_pStreamImp->GetAccessModes() & FX_STREAMACCESS_Write) == 0) - return -1; - - if (m_wCodePage == FX_CODEPAGE_UTF8) { - int32_t len = iLength; - CFX_UTF8Encoder encoder; - while (len-- > 0) { - encoder.Input(*pStr++); - } - CFX_ByteStringC bsResult = encoder.GetResult(); - m_pStreamImp->WriteData((const uint8_t*)bsResult.c_str(), - bsResult.GetLength()); - } - return iLength; -} - -CFGAS_Stream::CFGAS_Stream() - : m_eStreamType(FX_SREAMTYPE_Unknown), - m_pStreamImp(nullptr), - m_dwAccess(0), - m_iTotalSize(0), - m_iPosition(0), - m_iStart(0), - m_iLength(0), - m_iRefCount(1) {} - -CFGAS_Stream::~CFGAS_Stream() { - if (m_eStreamType != FX_STREAMTYPE_Stream) - delete m_pStreamImp; -} - -bool CFGAS_Stream::LoadFile(const FX_WCHAR* pszSrcFileName, uint32_t dwAccess) { - if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp) - return false; - - if (!pszSrcFileName || FXSYS_wcslen(pszSrcFileName) < 1) - return false; - - std::unique_ptr<CFGAS_FileStreamImp> pImp(new CFGAS_FileStreamImp()); - if (!pImp->LoadFile(pszSrcFileName, dwAccess)) - return false; - - m_pStreamImp = pImp.release(); - m_eStreamType = FX_STREAMTYPE_File; - m_dwAccess = dwAccess; - m_iLength = m_pStreamImp->GetLength(); - return true; -} - -bool CFGAS_Stream::LoadFileRead( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead, - uint32_t dwAccess) { - if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp) - return false; - - if (!pFileRead) - return false; - - std::unique_ptr<CFGAS_FileReadStreamImp> pImp(new CFGAS_FileReadStreamImp()); - if (!pImp->LoadFileRead(pFileRead, dwAccess)) - return false; - - m_pStreamImp = pImp.release(); - m_eStreamType = FX_STREAMTYPE_File; - m_dwAccess = dwAccess; - m_iLength = m_pStreamImp->GetLength(); - return true; -} - -bool CFGAS_Stream::LoadFileWrite( - const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite, - uint32_t dwAccess) { - if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp) - return false; - - if (!pFileWrite) - return false; - - auto pImp = pdfium::MakeUnique<CFGAS_FileWriteStreamImp>(); - if (!pImp->LoadFileWrite(pFileWrite, dwAccess)) - return false; - - m_pStreamImp = pImp.release(); - m_eStreamType = FX_STREAMTYPE_File; - m_dwAccess = dwAccess; - m_iLength = m_pStreamImp->GetLength(); - return true; -} - -bool CFGAS_Stream::LoadBuffer(uint8_t* pData, - int32_t iTotalSize, - uint32_t dwAccess) { - if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp) - return false; - - if (!pData || iTotalSize < 1) - return false; - - std::unique_ptr<CFGAS_BufferStreamImp> pImp(new CFGAS_BufferStreamImp()); - if (!pImp->LoadBuffer(pData, iTotalSize, dwAccess)) - return false; - - m_pStreamImp = pImp.release(); - m_eStreamType = FX_STREAMTYPE_Buffer; - m_dwAccess = dwAccess; - m_iLength = m_pStreamImp->GetLength(); - return true; -} - -bool CFGAS_Stream::LoadBufferRead( - const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead, - int32_t iFileSize, - uint32_t dwAccess) { - if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp) - return false; - - if (!pBufferRead) - return false; - - auto pImp = pdfium::MakeUnique<CFGAS_BufferReadStreamImp>(); - if (!pImp->LoadBufferRead(pBufferRead, iFileSize, dwAccess)) - return false; - - m_pStreamImp = pImp.release(); - m_eStreamType = FX_STREAMTYPE_BufferRead; - m_dwAccess = dwAccess; - m_iLength = m_pStreamImp->GetLength(); - return true; -} - -uint32_t CFGAS_Stream::GetAccessModes() const { - return m_dwAccess; -} - -int32_t CFGAS_Stream::GetLength() const { - if (!m_pStreamImp) { - return -1; - } - if (m_eStreamType == FX_STREAMTYPE_File || - m_eStreamType == FX_STREAMTYPE_Buffer) { - return m_pStreamImp->GetLength(); - } - return m_iLength; -} -int32_t CFGAS_Stream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) { - if (!m_pStreamImp) { - return -1; - } - if (m_eStreamType == FX_STREAMTYPE_File || - m_eStreamType == FX_STREAMTYPE_Buffer) { - return m_iPosition = m_pStreamImp->Seek(eSeek, iOffset); - } - int32_t iEnd = m_iStart + m_iLength; - int32_t 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; -} -int32_t CFGAS_Stream::GetPosition() { - if (!m_pStreamImp) { - return -1; - } - if (m_eStreamType == FX_STREAMTYPE_File || - m_eStreamType == FX_STREAMTYPE_Buffer) { - return m_iPosition = m_pStreamImp->GetPosition(); - } - return m_iPosition - m_iStart; -} -bool CFGAS_Stream::IsEOF() const { - if (!m_pStreamImp) { - return true; - } - if (m_eStreamType == FX_STREAMTYPE_File || - m_eStreamType == FX_STREAMTYPE_Buffer) { - return m_pStreamImp->IsEOF(); - } - return m_iPosition >= m_iStart + m_iLength; -} -int32_t CFGAS_Stream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) { - ASSERT(pBuffer && iBufferSize > 0); - if (!m_pStreamImp) { - return -1; - } - int32_t iLen = std::min(m_iStart + m_iLength - m_iPosition, iBufferSize); - if (iLen <= 0) { - return 0; - } - 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(); - return iLen; -} -int32_t CFGAS_Stream::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - ASSERT(pStr && iMaxLength > 0); - if (!m_pStreamImp) { - return -1; - } - int32_t iEnd = m_iStart + m_iLength; - int32_t iLen = iEnd - m_iPosition; - iLen = std::min(iEnd / 2, iMaxLength); - if (iLen <= 0) { - return 0; - } - 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; - } - return iLen; -} - -int32_t CFGAS_Stream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) { - ASSERT(pBuffer && iBufferSize > 0); - if (!m_pStreamImp) { - return -1; - } - if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) { - return -1; - } - int32_t iLen = iBufferSize; - if (m_eStreamType == FX_STREAMTYPE_Stream) { - iLen = std::min(m_iStart + m_iTotalSize - m_iPosition, iBufferSize); - if (iLen <= 0) { - return 0; - } - } - int32_t 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; - } - return iLen; -} -int32_t CFGAS_Stream::WriteString(const FX_WCHAR* pStr, int32_t iLength) { - ASSERT(pStr && iLength > 0); - if (!m_pStreamImp) { - return -1; - } - if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) { - return -1; - } - int32_t iLen = iLength; - if (m_eStreamType == FX_STREAMTYPE_Stream) { - iLen = std::min((m_iStart + m_iTotalSize - m_iPosition) / 2, iLength); - if (iLen <= 0) { - return 0; - } - } - int32_t 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; - } - return iLen; -} -void CFGAS_Stream::Flush() { - if (!m_pStreamImp) { - return; - } - if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) { - return; - } - m_pStreamImp->Flush(); -} -bool CFGAS_Stream::SetLength(int32_t iLength) { - if (!m_pStreamImp) { - return false; - } - if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) { - return false; - } - return m_pStreamImp->SetLength(iLength); -} -int32_t CFGAS_Stream::GetBOM(uint8_t bom[4]) const { - if (!m_pStreamImp) { - return -1; - } - return 0; -} -uint16_t CFGAS_Stream::GetCodePage() const { -#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_ - return FX_CODEPAGE_UTF16LE; -#else - return FX_CODEPAGE_UTF16BE; -#endif -} -uint16_t CFGAS_Stream::SetCodePage(uint16_t wCodePage) { -#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_ - return FX_CODEPAGE_UTF16LE; -#else - return FX_CODEPAGE_UTF16BE; -#endif -} - -CFX_RetainPtr<IFGAS_Stream> CFGAS_Stream::CreateSharedStream(uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) { - ASSERT(iLength > 0); - if (!m_pStreamImp) - return nullptr; - - if ((m_dwAccess & FX_STREAMACCESS_Text) != 0 && - (dwAccess & FX_STREAMACCESS_Text) == 0) { - return nullptr; - } - if ((m_dwAccess & FX_STREAMACCESS_Write) == 0 && - (dwAccess & FX_STREAMACCESS_Write) != 0) { - return nullptr; - } - int32_t iStart = m_iStart + iOffset; - int32_t iTotal = m_iStart + m_iLength; - if (iStart < m_iStart || iStart >= iTotal) - return nullptr; - - int32_t iEnd = iStart + iLength; - if (iEnd < iStart || iEnd > iTotal) - return nullptr; - - auto pShared = pdfium::MakeRetain<CFGAS_Stream>(); - 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 IFGAS_Stream::CreateTextStream(pShared); - - return pShared; -} - -CFX_RetainPtr<IFX_SeekableReadStream> IFGAS_Stream::MakeSeekableReadStream() { - return CFGAS_FileRead::Create(CFX_RetainPtr<IFGAS_Stream>(this)); -} - -CFX_RetainPtr<CFGAS_FileRead> CFGAS_FileRead::Create( - const CFX_RetainPtr<IFGAS_Stream>& pStream) { - return pdfium::MakeRetain<CFGAS_FileRead>(pStream); -} - -CFGAS_FileRead::CFGAS_FileRead(const CFX_RetainPtr<IFGAS_Stream>& pStream) - : m_pStream(pStream) { - ASSERT(m_pStream); -} - -CFGAS_FileRead::~CFGAS_FileRead() {} - -FX_FILESIZE CFGAS_FileRead::GetSize() { - return (FX_FILESIZE)m_pStream->GetLength(); -} - -bool CFGAS_FileRead::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) { - m_pStream->Seek(FX_STREAMSEEK_Begin, (int32_t)offset); - int32_t iLen = m_pStream->ReadData((uint8_t*)buffer, (int32_t)size); - return iLen == (int32_t)size; -} diff --git a/xfa/fgas/crt/fgas_stream.h b/xfa/fgas/crt/fgas_stream.h deleted file mode 100644 index 79fda58d2a5db28b8a7705f8e3cd6d1fbf35f038..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_stream.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_CRT_FGAS_STREAM_H_ -#define XFA_FGAS_CRT_FGAS_STREAM_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_stream.h" -#include "core/fxcrt/fx_system.h" - -enum FX_STREAMACCESS { - FX_STREAMACCESS_Binary = 0x00, - FX_STREAMACCESS_Text = 0x01, - FX_STREAMACCESS_Read = 0x02, - FX_STREAMACCESS_Write = 0x04, - FX_STREAMACCESS_Truncate = 0x10, - FX_STREAMACCESS_Append = 0x20, - FX_STREAMACCESS_Create = 0x80, -}; - -enum FX_STREAMSEEK { - FX_STREAMSEEK_Begin = 0, - FX_STREAMSEEK_Current, - FX_STREAMSEEK_End, -}; - -class IFGAS_Stream : public CFX_Retainable { - public: - static CFX_RetainPtr<IFGAS_Stream> CreateStream( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead, - uint32_t dwAccess); - static CFX_RetainPtr<IFGAS_Stream> CreateStream( - const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite, - uint32_t dwAccess); - static CFX_RetainPtr<IFGAS_Stream> CreateStream(uint8_t* pData, - int32_t length, - uint32_t dwAccess); - static CFX_RetainPtr<IFGAS_Stream> CreateTextStream( - const CFX_RetainPtr<IFGAS_Stream>& pBaseStream); - - virtual CFX_RetainPtr<IFGAS_Stream> CreateSharedStream(uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) = 0; - - virtual uint32_t GetAccessModes() const = 0; - virtual int32_t GetLength() const = 0; - virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) = 0; - virtual int32_t GetPosition() = 0; - virtual bool IsEOF() const = 0; - virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) = 0; - virtual int32_t ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) = 0; - virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) = 0; - virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) = 0; - virtual void Flush() = 0; - virtual bool SetLength(int32_t iLength) = 0; - virtual int32_t GetBOM(uint8_t bom[4]) const = 0; - virtual uint16_t GetCodePage() const = 0; - virtual uint16_t SetCodePage(uint16_t wCodePage) = 0; - - CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(); -}; - - -#endif // XFA_FGAS_CRT_FGAS_STREAM_H_ diff --git a/xfa/fgas/crt/fgas_utils.cpp b/xfa/fgas/crt/fgas_utils.cpp deleted file mode 100644 index c09198f6e0ad1bae1ec346737a99ca57a1aaba13..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_utils.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fgas/crt/fgas_utils.h" - -#include <algorithm> - -#include "core/fxcrt/fx_basic.h" - -class FX_BASEARRAYDATA { - public: - FX_BASEARRAYDATA(int32_t growsize, int32_t blocksize); - ~FX_BASEARRAYDATA(); - - int32_t iGrowSize; - int32_t iBlockSize; - int32_t iTotalCount; - int32_t iBlockCount; - uint8_t* pBuffer; -}; - -FX_BASEARRAYDATA::FX_BASEARRAYDATA(int32_t growsize, int32_t blocksize) - : iGrowSize(growsize), - iBlockSize(blocksize), - iTotalCount(0), - iBlockCount(0), - pBuffer(nullptr) {} - -FX_BASEARRAYDATA::~FX_BASEARRAYDATA() { - FX_Free(pBuffer); -} - -CFX_BaseArray::CFX_BaseArray(int32_t iGrowSize, int32_t iBlockSize) { - ASSERT(iGrowSize > 0 && iBlockSize > 0); - m_pData = new FX_BASEARRAYDATA(iGrowSize, iBlockSize); -} -CFX_BaseArray::~CFX_BaseArray() { - RemoveAll(false); - delete m_pData; -} -int32_t CFX_BaseArray::GetSize() const { - return m_pData->iBlockCount; -} -int32_t CFX_BaseArray::GetBlockSize() const { - return m_pData->iBlockSize; -} -uint8_t* CFX_BaseArray::AddSpaceTo(int32_t index) { - ASSERT(index > -1); - uint8_t*& pBuffer = m_pData->pBuffer; - int32_t& iTotalCount = m_pData->iTotalCount; - int32_t iBlockSize = m_pData->iBlockSize; - if (index >= iTotalCount) { - int32_t iGrowSize = m_pData->iGrowSize; - iTotalCount = (index / iGrowSize + 1) * iGrowSize; - int32_t iNewSize = iTotalCount * iBlockSize; - if (!pBuffer) { - pBuffer = FX_Alloc(uint8_t, iNewSize); - } else { - pBuffer = FX_Realloc(uint8_t, pBuffer, iNewSize); - } - } - int32_t& iBlockCount = m_pData->iBlockCount; - if (index >= iBlockCount) { - iBlockCount = index + 1; - } - return pBuffer + index * iBlockSize; -} -uint8_t* CFX_BaseArray::GetAt(int32_t index) const { - ASSERT(index > -1 && index < m_pData->iBlockCount); - return m_pData->pBuffer + index * m_pData->iBlockSize; -} -uint8_t* CFX_BaseArray::GetBuffer() const { - return m_pData->pBuffer; -} -int32_t CFX_BaseArray::Append(const CFX_BaseArray& src, - int32_t iStart, - int32_t iCount) { - int32_t iBlockSize = m_pData->iBlockSize; - ASSERT(iBlockSize == src.m_pData->iBlockSize); - int32_t& iBlockCount = m_pData->iBlockCount; - int32_t iAdded = src.GetSize(); - ASSERT(iStart > -1 && iStart < iAdded); - if (iCount < 0) { - iCount = iAdded; - } - if (iStart + iCount > iAdded) { - iCount = iAdded - iStart; - } - if (iCount < 1) { - return 0; - } - uint8_t* pDst = m_pData->pBuffer + iBlockCount * iBlockSize; - AddSpaceTo(iBlockCount + iCount - 1); - FXSYS_memcpy(pDst, src.m_pData->pBuffer + iStart * iBlockSize, - iCount * iBlockSize); - return iCount; -} -int32_t CFX_BaseArray::Copy(const CFX_BaseArray& src, - int32_t iStart, - int32_t iCount) { - int32_t iBlockSize = m_pData->iBlockSize; - ASSERT(iBlockSize == src.m_pData->iBlockSize); - int32_t iCopied = src.GetSize(); - 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); - FXSYS_memcpy(m_pData->pBuffer, src.m_pData->pBuffer + iStart * iBlockSize, - iCount * iBlockSize); - return iCount; -} -int32_t CFX_BaseArray::RemoveLast(int32_t iCount) { - int32_t& iBlockCount = m_pData->iBlockCount; - if (iCount < 0 || iCount > iBlockCount) { - iCount = iBlockCount; - iBlockCount = 0; - } else { - iBlockCount -= iCount; - } - return iCount; -} -void CFX_BaseArray::RemoveAll(bool bLeaveMemory) { - if (!bLeaveMemory) { - uint8_t*& pBuffer = m_pData->pBuffer; - if (pBuffer) { - FX_Free(pBuffer); - pBuffer = nullptr; - } - m_pData->iTotalCount = 0; - } - m_pData->iBlockCount = 0; -} - -CFX_BaseMassArrayImp::CFX_BaseMassArrayImp(int32_t iChunkSize, - int32_t iBlockSize) - : m_iChunkSize(iChunkSize), - m_iBlockSize(iBlockSize), - m_iChunkCount(0), - m_iBlockCount(0), - m_pData(new CFX_ArrayTemplate<void*>()) { - ASSERT(m_iChunkSize > 0 && m_iBlockSize > 0); - m_pData->SetSize(16); -} -CFX_BaseMassArrayImp::~CFX_BaseMassArrayImp() { - RemoveAll(false); - delete m_pData; -} -uint8_t* CFX_BaseMassArrayImp::AddSpaceTo(int32_t index) { - ASSERT(index > -1); - uint8_t* pChunk; - if (index < m_iBlockCount) { - pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize); - } else { - int32_t iMemSize = m_iChunkSize * m_iBlockSize; - while (true) { - if (index < m_iChunkCount * m_iChunkSize) { - pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize); - break; - } else { - pChunk = FX_Alloc(uint8_t, iMemSize); - if (m_iChunkCount < m_pData->GetSize()) { - m_pData->SetAt(m_iChunkCount, pChunk); - } else { - m_pData->Add(pChunk); - } - m_iChunkCount++; - } - } - } - ASSERT(pChunk); - m_iBlockCount = index + 1; - return pChunk + (index % m_iChunkSize) * m_iBlockSize; -} -uint8_t* CFX_BaseMassArrayImp::GetAt(int32_t index) const { - ASSERT(index > -1 && index < m_iBlockCount); - uint8_t* pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize); - ASSERT(pChunk); - return pChunk + (index % m_iChunkSize) * m_iBlockSize; -} -int32_t CFX_BaseMassArrayImp::Append(const CFX_BaseMassArrayImp& src, - int32_t iStart, - int32_t iCount) { - ASSERT(m_iBlockSize == src.m_iBlockSize); - int32_t iAdded = src.m_iBlockCount; - ASSERT(iStart > -1 && iStart < iAdded); - if (iCount < 0) { - iCount = iAdded; - } - if (iStart + iCount > iAdded) { - iCount = iAdded - iStart; - } - if (iCount < 1) { - return m_iBlockCount; - } - int32_t iBlockCount = m_iBlockCount; - int32_t iTotal = m_iBlockCount + iCount; - AddSpaceTo(iTotal - 1); - Append(iBlockCount, src, iStart, iCount); - return m_iBlockCount; -} -int32_t CFX_BaseMassArrayImp::Copy(const CFX_BaseMassArrayImp& src, - int32_t iStart, - int32_t iCount) { - ASSERT(m_iBlockSize == src.m_iBlockSize); - int32_t iCopied = src.m_iBlockCount; - 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(int32_t iDstStart, - const CFX_BaseMassArrayImp& src, - int32_t iSrcStart, - int32_t iSrcCount) { - ASSERT(iDstStart > -1); - ASSERT(m_iBlockSize == src.m_iBlockSize); - ASSERT(src.m_iBlockCount > 0); - ASSERT(m_iBlockCount >= iDstStart + iSrcCount); - ASSERT(iSrcStart > -1); - ASSERT(iSrcStart < src.m_iBlockCount); - ASSERT(iSrcCount > 0); - ASSERT(iSrcStart + iSrcCount <= src.m_iBlockCount); - - int32_t iDstChunkIndex = iDstStart / m_iChunkSize; - int32_t iSrcChunkIndex = iSrcStart / src.m_iChunkSize; - uint8_t* pDstChunk = (uint8_t*)GetAt(iDstStart); - uint8_t* pSrcChunk = (uint8_t*)src.GetAt(iSrcStart); - int32_t iDstChunkSize = m_iChunkSize - (iDstStart % m_iChunkSize); - int32_t iSrcChunkSize = src.m_iChunkSize - (iSrcStart % src.m_iChunkSize); - int32_t iCopySize = - std::min(iSrcCount, std::min(iSrcChunkSize, iDstChunkSize)); - int32_t iCopyBytes = iCopySize * m_iBlockSize; - while (iSrcCount > 0) { - ASSERT(pDstChunk && pSrcChunk); - FXSYS_memcpy(pDstChunk, pSrcChunk, iCopyBytes); - iSrcCount -= iCopySize; - iSrcChunkSize -= iCopySize; - if (iSrcChunkSize < 1) { - iSrcChunkSize = src.m_iChunkSize; - iSrcChunkIndex++; - pSrcChunk = (uint8_t*)src.m_pData->GetAt(iSrcChunkIndex); - } else { - pSrcChunk += iCopyBytes; - } - iDstChunkSize -= iCopySize; - if (iDstChunkSize < 1) { - iDstChunkSize = m_iChunkSize; - iDstChunkIndex++; - pDstChunk = (uint8_t*)m_pData->GetAt(iDstChunkIndex); - } else { - pDstChunk += iCopyBytes; - } - iCopySize = std::min(iSrcCount, std::min(iSrcChunkSize, iDstChunkSize)); - iCopyBytes = iCopySize * m_iBlockSize; - } -} -int32_t CFX_BaseMassArrayImp::RemoveLast(int32_t iCount) { - if (iCount < 0 || iCount >= m_iBlockCount) { - m_iBlockCount = 0; - } else { - m_iBlockCount -= iCount; - } - return m_iBlockCount; -} -void CFX_BaseMassArrayImp::RemoveAll(bool bLeaveMemory) { - if (bLeaveMemory) { - m_iBlockCount = 0; - return; - } - for (int32_t i = 0; i < m_iChunkCount; i++) - FX_Free(m_pData->GetAt(i)); - - m_pData->RemoveAll(); - m_iChunkCount = 0; - m_iBlockCount = 0; -} - -struct FX_BASEDISCRETEARRAYDATA { - int32_t iBlockSize; - int32_t iChunkSize; - int32_t iChunkCount; - CFX_ArrayTemplate<uint8_t*> ChunkBuffer; -}; - -CFX_BaseDiscreteArray::CFX_BaseDiscreteArray(int32_t iChunkSize, - int32_t iBlockSize) { - ASSERT(iChunkSize > 0 && iBlockSize > 0); - FX_BASEDISCRETEARRAYDATA* pData = new FX_BASEDISCRETEARRAYDATA; - m_pData = pData; - pData->ChunkBuffer.SetSize(16); - pData->iChunkCount = 0; - pData->iChunkSize = iChunkSize; - pData->iBlockSize = iBlockSize; -} -CFX_BaseDiscreteArray::~CFX_BaseDiscreteArray() { - RemoveAll(); - delete static_cast<FX_BASEDISCRETEARRAYDATA*>(m_pData); -} -uint8_t* CFX_BaseDiscreteArray::AddSpaceTo(int32_t index) { - ASSERT(index > -1); - FX_BASEDISCRETEARRAYDATA* pData = (FX_BASEDISCRETEARRAYDATA*)m_pData; - int32_t& iChunkCount = pData->iChunkCount; - int32_t iChunkSize = pData->iChunkSize; - uint8_t* pChunk = nullptr; - int32_t iChunk = index / iChunkSize; - if (iChunk < iChunkCount) { - pChunk = pData->ChunkBuffer.GetAt(iChunk); - } - if (!pChunk) { - pChunk = FX_Alloc2D(uint8_t, iChunkSize, pData->iBlockSize); - FXSYS_memset(pChunk, 0, iChunkSize * pData->iBlockSize); - pData->ChunkBuffer.SetAtGrow(iChunk, pChunk); - if (iChunkCount <= iChunk) { - iChunkCount = iChunk + 1; - } - } - return pChunk + (index % iChunkSize) * pData->iBlockSize; -} -uint8_t* CFX_BaseDiscreteArray::GetAt(int32_t index) const { - ASSERT(index >= 0); - FX_BASEDISCRETEARRAYDATA* pData = (FX_BASEDISCRETEARRAYDATA*)m_pData; - int32_t iChunkSize = pData->iChunkSize; - int32_t iChunk = index / iChunkSize; - if (iChunk >= pData->iChunkCount) - return nullptr; - - uint8_t* pChunk = pData->ChunkBuffer.GetAt(iChunk); - if (!pChunk) - return nullptr; - - return pChunk + (index % iChunkSize) * pData->iBlockSize; -} -void CFX_BaseDiscreteArray::RemoveAll() { - FX_BASEDISCRETEARRAYDATA* pData = (FX_BASEDISCRETEARRAYDATA*)m_pData; - CFX_ArrayTemplate<uint8_t*>& ChunkBuffer = pData->ChunkBuffer; - int32_t& iChunkCount = pData->iChunkCount; - for (int32_t i = 0; i < iChunkCount; i++) - FX_Free(ChunkBuffer.GetAt(i)); - - ChunkBuffer.RemoveAll(); - iChunkCount = 0; -} -CFX_BaseStack::CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize) { - m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize); -} -CFX_BaseStack::~CFX_BaseStack() { - delete (CFX_BaseMassArrayImp*)m_pData; -} -uint8_t* CFX_BaseStack::Push() { - return m_pData->AddSpace(); -} -void CFX_BaseStack::Pop() { - int32_t& iBlockCount = m_pData->m_iBlockCount; - if (iBlockCount < 1) { - return; - } - iBlockCount--; -} -uint8_t* CFX_BaseStack::GetTopElement() const { - int32_t iSize = m_pData->m_iBlockCount; - if (iSize < 1) { - return nullptr; - } - return m_pData->GetAt(iSize - 1); -} -int32_t CFX_BaseStack::GetSize() const { - return m_pData->m_iBlockCount; -} -uint8_t* CFX_BaseStack::GetAt(int32_t index) const { - return m_pData->GetAt(index); -} -void CFX_BaseStack::RemoveAll(bool bLeaveMemory) { - m_pData->RemoveAll(bLeaveMemory); -} diff --git a/xfa/fgas/crt/fgas_utils.h b/xfa/fgas/crt/fgas_utils.h deleted file mode 100644 index 105920dc5518ba3591e321705731ca8008e18e0b..0000000000000000000000000000000000000000 --- a/xfa/fgas/crt/fgas_utils.h +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_CRT_FGAS_UTILS_H_ -#define XFA_FGAS_CRT_FGAS_UTILS_H_ - -#include "core/fxcrt/fx_coordinates.h" - -class FX_BASEARRAYDATA; - -class CFX_BaseArray { - protected: - CFX_BaseArray(int32_t iGrowSize, int32_t iBlockSize); - ~CFX_BaseArray(); - - int32_t GetSize() const; - int32_t GetBlockSize() const; - uint8_t* AddSpaceTo(int32_t index); - uint8_t* GetAt(int32_t index) const; - uint8_t* GetBuffer() const; - int32_t Append(const CFX_BaseArray& src, int32_t iStart, int32_t iCount); - int32_t Copy(const CFX_BaseArray& src, int32_t iStart, int32_t iCount); - int32_t RemoveLast(int32_t iCount); - void RemoveAll(bool bLeaveMemory); - - FX_BASEARRAYDATA* m_pData; -}; - -template <class baseType> -class CFX_BaseArrayTemplate : public CFX_BaseArray { - public: - explicit CFX_BaseArrayTemplate(int32_t iGrowSize) - : CFX_BaseArray(iGrowSize, sizeof(baseType)) {} - CFX_BaseArrayTemplate(int32_t iGrowSize, int32_t iBlockSize) - : CFX_BaseArray(iGrowSize, iBlockSize) {} - - int32_t GetSize() const { return CFX_BaseArray::GetSize(); } - int32_t GetBlockSize() const { return CFX_BaseArray::GetBlockSize(); } - baseType* AddSpace() { - return (baseType*)CFX_BaseArray::AddSpaceTo(CFX_BaseArray::GetSize()); - } - int32_t Add(const baseType& element) { - int32_t index = CFX_BaseArray::GetSize(); - *(baseType*)CFX_BaseArray::AddSpaceTo(index) = element; - return index; - } - baseType* GetBuffer() const { return (baseType*)CFX_BaseArray::GetBuffer(); } - baseType& GetAt(int32_t index) const { - return *(baseType*)CFX_BaseArray::GetAt(index); - } - baseType* GetPtrAt(int32_t index) const { - return (baseType*)CFX_BaseArray::GetAt(index); - } - void SetAt(int32_t index, const baseType& element) { - *(baseType*)CFX_BaseArray::GetAt(index) = element; - } - void SetAtGrow(int32_t index, const baseType& element) { - *(baseType*)CFX_BaseArray::AddSpaceTo(index) = element; - } - int32_t Append(const CFX_BaseArrayTemplate& src, - int32_t iStart, - int32_t iCount) { - return CFX_BaseArray::Append(src, iStart, iCount); - } - int32_t Copy(const CFX_BaseArrayTemplate& src, - int32_t iStart, - int32_t iCount) { - return CFX_BaseArray::Copy(src, iStart, iCount); - } - int32_t RemoveLast(int32_t iCount) { - return CFX_BaseArray::RemoveLast(iCount); - } - void RemoveAll(bool bLeaveMemory) { CFX_BaseArray::RemoveAll(bLeaveMemory); } -}; - -class CFX_BaseMassArrayImp { - public: - CFX_BaseMassArrayImp(int32_t iChunkSize, int32_t iBlockSize); - ~CFX_BaseMassArrayImp(); - - uint8_t* AddSpace() { return AddSpaceTo(m_iBlockCount); } - uint8_t* AddSpaceTo(int32_t index); - uint8_t* GetAt(int32_t index) const; - int32_t Append(const CFX_BaseMassArrayImp& src, - int32_t iStart, - int32_t iCount); - int32_t Copy(const CFX_BaseMassArrayImp& src, int32_t iStart, int32_t iCount); - int32_t RemoveLast(int32_t iCount); - void RemoveAll(bool bLeaveMemory); - - int32_t m_iChunkSize; - int32_t m_iBlockSize; - int32_t m_iChunkCount; - int32_t m_iBlockCount; - CFX_ArrayTemplate<void*>* m_pData; - - protected: - void Append(int32_t iDstStart, - const CFX_BaseMassArrayImp& src, - int32_t iSrcStart, - int32_t iSrcCount); -}; - -class CFX_BaseDiscreteArray { - protected: - CFX_BaseDiscreteArray(int32_t iChunkSize, int32_t iBlockSize); - ~CFX_BaseDiscreteArray(); - - uint8_t* AddSpaceTo(int32_t index); - uint8_t* GetAt(int32_t index) const; - void RemoveAll(); - void* m_pData; -}; - -template <class baseType> -class CFX_DiscreteArrayTemplate : public CFX_BaseDiscreteArray { - public: - explicit CFX_DiscreteArrayTemplate(int32_t iChunkSize) - : CFX_BaseDiscreteArray(iChunkSize, sizeof(baseType)) {} - - baseType& GetAt(int32_t index, const baseType& defValue) const { - baseType* p = (baseType*)CFX_BaseDiscreteArray::GetAt(index); - return p ? *p : (baseType&)defValue; - } - baseType* GetPtrAt(int32_t index) const { - return (baseType*)CFX_BaseDiscreteArray::GetAt(index); - } - void SetAtGrow(int32_t index, const baseType& element) { - *(baseType*)CFX_BaseDiscreteArray::AddSpaceTo(index) = element; - } - void RemoveAll() { CFX_BaseDiscreteArray::RemoveAll(); } -}; - -class CFX_BaseStack { - protected: - CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize); - ~CFX_BaseStack(); - - uint8_t* Push(); - void Pop(); - uint8_t* GetTopElement() const; - int32_t GetSize() const; - uint8_t* GetAt(int32_t index) const; - void RemoveAll(bool bLeaveMemory); - CFX_BaseMassArrayImp* m_pData; -}; - -template <class baseType> -class CFX_StackTemplate : public CFX_BaseStack { - public: - explicit CFX_StackTemplate(int32_t iChunkSize) - : CFX_BaseStack(iChunkSize, sizeof(baseType)) {} - - int32_t Push(const baseType& element) { - int32_t index = CFX_BaseStack::GetSize(); - *(baseType*)CFX_BaseStack::Push() = element; - return index; - } - void Pop() { CFX_BaseStack::Pop(); } - baseType* GetTopElement() const { - return (baseType*)CFX_BaseStack::GetTopElement(); - } - int32_t GetSize() const { return CFX_BaseStack::GetSize(); } - baseType* GetAt(int32_t index) const { - return (baseType*)CFX_BaseStack::GetAt(index); - } - void RemoveAll(bool bLeaveMemory) { CFX_BaseStack::RemoveAll(bLeaveMemory); } -}; - -#endif // XFA_FGAS_CRT_FGAS_UTILS_H_ diff --git a/xfa/fgas/font/DEPS b/xfa/fgas/font/DEPS deleted file mode 100644 index 2930dd036a45dda6297f57d61a9ec3e656690112..0000000000000000000000000000000000000000 --- a/xfa/fgas/font/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - '+third_party/freetype/include', -] diff --git a/xfa/fgas/font/cfgas_defaultfontmanager.cpp b/xfa/fgas/font/cfgas_defaultfontmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d0ff20583a084ac2ad1570a8264df6a01584708 --- /dev/null +++ b/xfa/fgas/font/cfgas_defaultfontmanager.cpp @@ -0,0 +1,70 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/font/cfgas_defaultfontmanager.h" + +#include "xfa/fgas/font/fgas_fontutils.h" + +CFGAS_DefaultFontManager::CFGAS_DefaultFontManager() {} + +CFGAS_DefaultFontManager::~CFGAS_DefaultFontManager() {} + +RetainPtr<CFGAS_GEFont> CFGAS_DefaultFontManager::GetFont( + CFGAS_FontMgr* pFontMgr, + const WideStringView& wsFontFamily, + uint32_t dwFontStyles) { + WideString wsFontName(wsFontFamily); + RetainPtr<CFGAS_GEFont> pFont = + pFontMgr->LoadFont(wsFontName.c_str(), dwFontStyles, 0xFFFF); + if (!pFont) { + const FGAS_FontInfo* pCurFont = + FGAS_FontInfoByFontName(wsFontName.AsStringView()); + if (pCurFont && pCurFont->pReplaceFont) { + uint32_t dwStyle = 0; + // TODO(dsinclair): Why doesn't this check the other flags? + if (FontStyleIsBold(dwFontStyles)) + dwStyle |= FXFONT_BOLD; + if (FontStyleIsItalic(dwFontStyles)) + dwStyle |= FXFONT_ITALIC; + + const wchar_t* pReplace = pCurFont->pReplaceFont; + int32_t iLength = wcslen(pReplace); + while (iLength > 0) { + const wchar_t* pNameText = pReplace; + while (*pNameText != L',' && iLength > 0) { + pNameText++; + iLength--; + } + WideString wsReplace = WideString(pReplace, pNameText - pReplace); + pFont = pFontMgr->LoadFont(wsReplace.c_str(), dwStyle, 0xFFFF); + if (pFont) + break; + + iLength--; + pNameText++; + pReplace = pNameText; + } + } + } + if (pFont) + m_CacheFonts.push_back(pFont); + return pFont; +} + +RetainPtr<CFGAS_GEFont> CFGAS_DefaultFontManager::GetDefaultFont( + CFGAS_FontMgr* pFontMgr, + const WideStringView& wsFontFamily, + uint32_t dwFontStyles) { + RetainPtr<CFGAS_GEFont> pFont = + pFontMgr->LoadFont(L"Arial Narrow", dwFontStyles, 0xFFFF); + if (!pFont) { + pFont = pFontMgr->LoadFont(static_cast<const wchar_t*>(nullptr), + dwFontStyles, 0xFFFF); + } + if (pFont) + m_CacheFonts.push_back(pFont); + return pFont; +} diff --git a/xfa/fgas/font/cfgas_defaultfontmanager.h b/xfa/fgas/font/cfgas_defaultfontmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..2afe9ebc543b04d7bd2b9f7fbae5a57f62b112b5 --- /dev/null +++ b/xfa/fgas/font/cfgas_defaultfontmanager.h @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_FONT_CFGAS_DEFAULTFONTMANAGER_H_ +#define XFA_FGAS_FONT_CFGAS_DEFAULTFONTMANAGER_H_ + +#include <vector> + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +class CFGAS_DefaultFontManager { + public: + CFGAS_DefaultFontManager(); + ~CFGAS_DefaultFontManager(); + + RetainPtr<CFGAS_GEFont> GetFont(CFGAS_FontMgr* pFontMgr, + const WideStringView& wsFontFamily, + uint32_t dwFontStyles); + RetainPtr<CFGAS_GEFont> GetDefaultFont(CFGAS_FontMgr* pFontMgr, + const WideStringView& wsFontFamily, + uint32_t dwFontStyles); + + private: + std::vector<RetainPtr<CFGAS_GEFont>> m_CacheFonts; +}; + +#endif // XFA_FGAS_FONT_CFGAS_DEFAULTFONTMANAGER_H_ diff --git a/xfa/fgas/font/cfgas_fontmgr.cpp b/xfa/fgas/font/cfgas_fontmgr.cpp index aa41318f5d293deff16a425d8d2ca262908aaa52..862e9299b53502d1381343c8d0aa4321d120fccb 100644 --- a/xfa/fgas/font/cfgas_fontmgr.cpp +++ b/xfa/fgas/font/cfgas_fontmgr.cpp @@ -10,40 +10,95 @@ #include <memory> #include <utility> -#include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/cfx_fontmapper.h" #include "core/fxge/cfx_fontmgr.h" #include "core/fxge/cfx_gemodule.h" +#include "core/fxge/fx_font.h" #include "core/fxge/ifx_systemfontinfo.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -#include "xfa/fgas/crt/fgas_codepage.h" #include "xfa/fgas/font/cfgas_gefont.h" #include "xfa/fgas/font/fgas_fontutils.h" -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ namespace { +struct FX_CHARSET_MAP { + uint16_t charset; + uint16_t codepage; +}; + +const FX_CHARSET_MAP g_FXCharset2CodePageTable[] = { + {FX_CHARSET_ANSI, FX_CODEPAGE_MSWin_WesternEuropean}, + {FX_CHARSET_Default, FX_CODEPAGE_DefANSI}, + {FX_CHARSET_Symbol, FX_CODEPAGE_Symbol}, + {FX_CHARSET_MAC_Roman, FX_CODEPAGE_MAC_Roman}, + {FX_CHARSET_MAC_ShiftJIS, FX_CODEPAGE_MAC_ShiftJIS}, + {FX_CHARSET_MAC_Korean, FX_CODEPAGE_MAC_Korean}, + {FX_CHARSET_MAC_ChineseSimplified, FX_CODEPAGE_MAC_ChineseSimplified}, + {FX_CHARSET_MAC_ChineseTraditional, FX_CODEPAGE_MAC_ChineseTraditional}, + {FX_CHARSET_MAC_Hebrew, FX_CODEPAGE_MAC_Hebrew}, + {FX_CHARSET_MAC_Arabic, FX_CODEPAGE_MAC_Arabic}, + {FX_CHARSET_MAC_Greek, FX_CODEPAGE_MAC_Greek}, + {FX_CHARSET_MAC_Turkish, FX_CODEPAGE_MAC_Turkish}, + {FX_CHARSET_MAC_Thai, FX_CODEPAGE_MAC_Thai}, + {FX_CHARSET_MAC_EasternEuropean, FX_CODEPAGE_MAC_EasternEuropean}, + {FX_CHARSET_MAC_Cyrillic, FX_CODEPAGE_MAC_Cyrillic}, + {FX_CHARSET_ShiftJIS, FX_CODEPAGE_ShiftJIS}, + {FX_CHARSET_Hangul, FX_CODEPAGE_Hangul}, + {FX_CHARSET_Johab, FX_CODEPAGE_Johab}, + {FX_CHARSET_ChineseSimplified, FX_CODEPAGE_ChineseSimplified}, + {FX_CHARSET_ChineseTraditional, FX_CODEPAGE_ChineseTraditional}, + {FX_CHARSET_MSWin_Greek, FX_CODEPAGE_MSWin_Greek}, + {FX_CHARSET_MSWin_Turkish, FX_CODEPAGE_MSWin_Turkish}, + {FX_CHARSET_MSWin_Vietnamese, FX_CODEPAGE_MSWin_Vietnamese}, + {FX_CHARSET_MSWin_Hebrew, FX_CODEPAGE_MSWin_Hebrew}, + {FX_CHARSET_MSWin_Arabic, FX_CODEPAGE_MSWin_Arabic}, + {FX_CHARSET_MSWin_Baltic, FX_CODEPAGE_MSWin_Baltic}, + {FX_CHARSET_MSWin_Cyrillic, FX_CODEPAGE_MSWin_Cyrillic}, + {FX_CHARSET_Thai, FX_CODEPAGE_MSDOS_Thai}, + {FX_CHARSET_MSWin_EasternEuropean, FX_CODEPAGE_MSWin_EasternEuropean}, + {FX_CHARSET_US, FX_CODEPAGE_MSDOS_US}, + {FX_CHARSET_OEM, FX_CODEPAGE_MSDOS_WesternEuropean}, +}; + +uint16_t GetCodePageFromCharset(uint8_t charset) { + int32_t iEnd = sizeof(g_FXCharset2CodePageTable) / sizeof(FX_CHARSET_MAP) - 1; + ASSERT(iEnd >= 0); + + int32_t iStart = 0, iMid; + do { + iMid = (iStart + iEnd) / 2; + const FX_CHARSET_MAP& cp = g_FXCharset2CodePageTable[iMid]; + if (charset == cp.charset) + return cp.codepage; + if (charset < cp.charset) + iEnd = iMid - 1; + else + iStart = iMid + 1; + } while (iStart <= iEnd); + return 0xFFFF; +} + int32_t GetSimilarityScore(FX_FONTDESCRIPTOR const* pFont, uint32_t dwFontStyles) { int32_t iValue = 0; - if ((dwFontStyles & FX_FONTSTYLE_Symbolic) == - (pFont->dwFontStyles & FX_FONTSTYLE_Symbolic)) { + if (FontStyleIsSymbolic(dwFontStyles) == + FontStyleIsSymbolic(pFont->dwFontStyles)) { iValue += 64; } - if ((dwFontStyles & FX_FONTSTYLE_FixedPitch) == - (pFont->dwFontStyles & FX_FONTSTYLE_FixedPitch)) { + if (FontStyleIsFixedPitch(dwFontStyles) == + FontStyleIsFixedPitch(pFont->dwFontStyles)) { iValue += 32; } - if ((dwFontStyles & FX_FONTSTYLE_Serif) == - (pFont->dwFontStyles & FX_FONTSTYLE_Serif)) { + if (FontStyleIsSerif(dwFontStyles) == FontStyleIsSerif(pFont->dwFontStyles)) iValue += 16; - } - if ((dwFontStyles & FX_FONTSTYLE_Script) == - (pFont->dwFontStyles & FX_FONTSTYLE_Script)) { + if (FontStyleIsScript(dwFontStyles) == FontStyleIsScript(pFont->dwFontStyles)) iValue += 8; - } return iValue; } @@ -52,12 +107,12 @@ const FX_FONTDESCRIPTOR* MatchDefaultFont( const std::deque<FX_FONTDESCRIPTOR>& fonts) { const FX_FONTDESCRIPTOR* pBestFont = nullptr; int32_t iBestSimilar = 0; - bool bMatchStyle = (pParams->dwMatchFlags & FX_FONTMATCHPARA_MatchStyle) > 0; for (const auto& font : fonts) { - if ((font.dwFontStyles & FX_FONTSTYLE_BoldItalic) == - FX_FONTSTYLE_BoldItalic) { + if (FontStyleIsBold(font.dwFontStyles) && + FontStyleIsItalic(font.dwFontStyles)) { continue; } + if (pParams->pwsFamily) { if (FXSYS_wcsicmp(pParams->pwsFamily, font.wsFontFace)) continue; @@ -67,7 +122,7 @@ const FX_FONTDESCRIPTOR* MatchDefaultFont( if (font.uCharSet == FX_CHARSET_Symbol) continue; if (pParams->wCodePage != 0xFFFF) { - if (FX_GetCodePageFromCharset(font.uCharSet) != pParams->wCodePage) + if (GetCodePageFromCharset(font.uCharSet) != pParams->wCodePage) continue; } else { if (pParams->dwUSB < 128) { @@ -77,7 +132,7 @@ const FX_FONTDESCRIPTOR* MatchDefaultFont( continue; } } - if (bMatchStyle) { + if (pParams->matchParagraphStyle) { if ((font.dwFontStyles & 0x0F) == (pParams->dwFontStyles & 0x0F)) return &font; continue; @@ -95,187 +150,85 @@ const FX_FONTDESCRIPTOR* MatchDefaultFont( return iBestSimilar < 1 ? nullptr : pBestFont; } -} // namespace - -std::unique_ptr<CFGAS_FontMgr> CFGAS_FontMgr::Create( - FX_LPEnumAllFonts pEnumerator) { - return pdfium::MakeUnique<CFGAS_FontMgr>(pEnumerator); -} - -CFGAS_FontMgr::CFGAS_FontMgr(FX_LPEnumAllFonts pEnumerator) - : m_pEnumerator(pEnumerator), m_FontFaces(100) { - if (m_pEnumerator) - m_pEnumerator(&m_FontFaces, nullptr, 0xFEFF); +uint32_t GetGdiFontStyles(const LOGFONTW& lf) { + uint32_t dwStyles = 0; + if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH) + dwStyles |= FXFONT_FIXED_PITCH; + uint8_t nFamilies = lf.lfPitchAndFamily & 0xF0; + if (nFamilies == FF_ROMAN) + dwStyles |= FXFONT_SERIF; + if (nFamilies == FF_SCRIPT) + dwStyles |= FXFONT_SCRIPT; + if (lf.lfCharSet == SYMBOL_CHARSET) + dwStyles |= FXFONT_SYMBOLIC; + return dwStyles; } -CFGAS_FontMgr::~CFGAS_FontMgr() {} - -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByCodePage( - uint16_t wCodePage, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily) { - uint32_t dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); - auto it = m_CPFonts.find(dwHash); - if (it != m_CPFonts.end()) { - return it->second ? LoadFont(it->second, dwFontStyles, wCodePage) : nullptr; - } - const FX_FONTDESCRIPTOR* pFD = - FindFont(pszFontFamily, dwFontStyles, true, wCodePage); - if (!pFD) - pFD = FindFont(nullptr, dwFontStyles, true, wCodePage); - if (!pFD) - pFD = FindFont(nullptr, dwFontStyles, false, wCodePage); - if (!pFD) - return nullptr; - - CFX_RetainPtr<CFGAS_GEFont> pFont = - CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); - if (!pFont) - return nullptr; - - m_Fonts.push_back(pFont); - m_CPFonts[dwHash] = pFont; - dwHash = FGAS_GetFontFamilyHash(pFD->wsFontFace, dwFontStyles, wCodePage); - m_FamilyFonts[dwHash] = pFont; - return LoadFont(pFont, dwFontStyles, wCodePage); +int32_t CALLBACK 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_FONTDESCRIPTOR* pFont = FX_Alloc(FX_FONTDESCRIPTOR, 1); + memset(pFont, 0, sizeof(FX_FONTDESCRIPTOR)); + pFont->uCharSet = lf.lfCharSet; + pFont->dwFontStyles = GetGdiFontStyles(lf); + FXSYS_wcsncpy(pFont->wsFontFace, (const wchar_t*)lf.lfFaceName, 31); + pFont->wsFontFace[31] = 0; + memcpy(&pFont->FontSignature, &lpntme->ntmFontSig, + sizeof(lpntme->ntmFontSig)); + reinterpret_cast<std::deque<FX_FONTDESCRIPTOR>*>(lParam)->push_back(*pFont); + FX_Free(pFont); + return 1; } -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicode( - FX_WCHAR wUnicode, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily) { - const FGAS_FONTUSB* pRet = FGAS_GetUnicodeBitField(wUnicode); - if (pRet->wBitField == 999) - return nullptr; - - uint32_t dwHash = - FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, pRet->wBitField); - auto it = m_UnicodeFonts.find(dwHash); - if (it != m_UnicodeFonts.end()) { - return it->second ? LoadFont(it->second, dwFontStyles, pRet->wCodePage) - : nullptr; - } - const FX_FONTDESCRIPTOR* pFD = - FindFont(pszFontFamily, dwFontStyles, false, pRet->wCodePage, - pRet->wBitField, wUnicode); - if (!pFD && pszFontFamily) { - pFD = FindFont(nullptr, dwFontStyles, false, pRet->wCodePage, - pRet->wBitField, wUnicode); +void EnumGdiFonts(std::deque<FX_FONTDESCRIPTOR>* fonts, + const wchar_t* pwsFaceName, + wchar_t wUnicode) { + HDC hDC = ::GetDC(nullptr); + LOGFONTW lfFind; + memset(&lfFind, 0, sizeof(lfFind)); + lfFind.lfCharSet = DEFAULT_CHARSET; + if (pwsFaceName) { + FXSYS_wcsncpy(lfFind.lfFaceName, pwsFaceName, 31); + lfFind.lfFaceName[31] = 0; } - if (!pFD) - return nullptr; - - uint16_t wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet); - const FX_WCHAR* pFontFace = pFD->wsFontFace; - CFX_RetainPtr<CFGAS_GEFont> pFont = - CFGAS_GEFont::LoadFont(pFontFace, dwFontStyles, wCodePage, this); - if (!pFont) - return nullptr; - - m_Fonts.push_back(pFont); - m_UnicodeFonts[dwHash] = pFont; - m_CPFonts[FGAS_GetFontHashCode(wCodePage, dwFontStyles)] = pFont; - m_FamilyFonts[FGAS_GetFontFamilyHash(pFontFace, dwFontStyles, wCodePage)] = - pFont; - return LoadFont(pFont, dwFontStyles, wCodePage); -} - -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( - const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage) { - CFX_RetainPtr<CFGAS_GEFont> pFont; - uint32_t dwHash = - FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, wCodePage); - auto it = m_FamilyFonts.find(dwHash); - if (it != m_FamilyFonts.end()) - return it->second ? LoadFont(it->second, dwFontStyles, wCodePage) : nullptr; - - const FX_FONTDESCRIPTOR* pFD = - FindFont(pszFontFamily, dwFontStyles, true, wCodePage); - if (!pFD) - pFD = FindFont(pszFontFamily, dwFontStyles, false, wCodePage); - if (!pFD) - return nullptr; - - if (wCodePage == 0xFFFF) - wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet); - - pFont = - CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); - if (!pFont) - return nullptr; - - m_Fonts.push_back(pFont); - m_FamilyFonts[dwHash] = pFont; - dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); - m_CPFonts[dwHash] = pFont; - return LoadFont(pFont, dwFontStyles, wCodePage); + EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind, (FONTENUMPROCW)GdiFontEnumProc, + (LPARAM)fonts, 0); + ::ReleaseDC(nullptr, hDC); } -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( - const CFX_RetainPtr<CFGAS_GEFont>& pSrcFont, - uint32_t dwFontStyles, - uint16_t wCodePage) { - if (pSrcFont->GetFontStyles() == dwFontStyles) - return pSrcFont; - - void* buffer[3] = {pSrcFont.Get(), (void*)(uintptr_t)dwFontStyles, - (void*)(uintptr_t)wCodePage}; - uint32_t dwHash = FX_HashCode_GetA( - CFX_ByteStringC((uint8_t*)buffer, sizeof(buffer)), false); - auto it = m_DeriveFonts.find(dwHash); - if (it != m_DeriveFonts.end() && it->second) - return it->second; - - CFX_RetainPtr<CFGAS_GEFont> pFont = pSrcFont->Derive(dwFontStyles, wCodePage); - if (!pFont) - return nullptr; +} // namespace - m_DeriveFonts[dwHash] = pFont; - auto iter = std::find(m_Fonts.begin(), m_Fonts.end(), pFont); - if (iter == m_Fonts.end()) - m_Fonts.push_back(pFont); - return pFont; +CFGAS_FontMgr::CFGAS_FontMgr() : m_pEnumerator(EnumGdiFonts), m_FontFaces(100) { + if (m_pEnumerator) + m_pEnumerator(&m_FontFaces, nullptr, 0xFEFF); } -void CFGAS_FontMgr::RemoveFont( - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>>* pFontMap, - const CFX_RetainPtr<CFGAS_GEFont>& pFont) { - auto iter = pFontMap->begin(); - while (iter != pFontMap->end()) { - auto old_iter = iter++; - if (old_iter->second == pFont) - pFontMap->erase(old_iter); - } -} +CFGAS_FontMgr::~CFGAS_FontMgr() {} -void CFGAS_FontMgr::RemoveFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) { - RemoveFont(&m_CPFonts, pFont); - RemoveFont(&m_FamilyFonts, pFont); - RemoveFont(&m_UnicodeFonts, pFont); - RemoveFont(&m_BufferFonts, pFont); - RemoveFont(&m_StreamFonts, pFont); - RemoveFont(&m_DeriveFonts, pFont); - auto it = std::find(m_Fonts.begin(), m_Fonts.end(), pFont); - if (it != m_Fonts.end()) - m_Fonts.erase(it); +bool CFGAS_FontMgr::EnumFonts() { + return true; } -const FX_FONTDESCRIPTOR* CFGAS_FontMgr::FindFont(const FX_WCHAR* pszFontFamily, +const FX_FONTDESCRIPTOR* CFGAS_FontMgr::FindFont(const wchar_t* pszFontFamily, uint32_t dwFontStyles, - uint32_t dwMatchFlags, + bool matchParagraphStyle, uint16_t wCodePage, uint32_t dwUSB, - FX_WCHAR wUnicode) { + wchar_t wUnicode) { FX_FONTMATCHPARAMS params; - FXSYS_memset(¶ms, 0, sizeof(params)); + memset(¶ms, 0, sizeof(params)); params.dwUSB = dwUSB; params.wUnicode = wUnicode; params.wCodePage = wCodePage; params.pwsFamily = pszFontFamily; params.dwFontStyles = dwFontStyles; - params.dwMatchFlags = dwMatchFlags; + params.matchParagraphStyle = matchParagraphStyle; const FX_FONTDESCRIPTOR* pDesc = MatchDefaultFont(¶ms, m_FontFaces); if (pDesc) return pDesc; @@ -298,105 +251,95 @@ const FX_FONTDESCRIPTOR* CFGAS_FontMgr::FindFont(const FX_WCHAR* pszFontFamily, return &m_FontFaces.back(); } -uint32_t FX_GetGdiFontStyles(const LOGFONTW& lf) { - uint32_t dwStyles = 0; - if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH) - dwStyles |= FX_FONTSTYLE_FixedPitch; - uint8_t 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 int32_t 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_FONTDESCRIPTOR* pFont = FX_Alloc(FX_FONTDESCRIPTOR, 1); - FXSYS_memset(pFont, 0, sizeof(FX_FONTDESCRIPTOR)); - pFont->uCharSet = lf.lfCharSet; - pFont->dwFontStyles = FX_GetGdiFontStyles(lf); - FXSYS_wcsncpy(pFont->wsFontFace, (const FX_WCHAR*)lf.lfFaceName, 31); - pFont->wsFontFace[31] = 0; - FXSYS_memcpy(&pFont->FontSignature, &lpntme->ntmFontSig, - sizeof(lpntme->ntmFontSig)); - reinterpret_cast<std::deque<FX_FONTDESCRIPTOR>*>(lParam)->push_back(*pFont); - FX_Free(pFont); - return 1; -} - -static void FX_EnumGdiFonts(std::deque<FX_FONTDESCRIPTOR>* fonts, - const FX_WCHAR* pwsFaceName, - FX_WCHAR wUnicode) { - HDC hDC = ::GetDC(nullptr); - LOGFONTW lfFind; - FXSYS_memset(&lfFind, 0, sizeof(lfFind)); - lfFind.lfCharSet = DEFAULT_CHARSET; - if (pwsFaceName) { - FXSYS_wcsncpy(lfFind.lfFaceName, pwsFaceName, 31); - lfFind.lfFaceName[31] = 0; - } - EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind, - (FONTENUMPROCW)FX_GdiFontEnumProc, (LPARAM)fonts, 0); - ::ReleaseDC(nullptr, hDC); -} - -FX_LPEnumAllFonts FX_GetDefFontEnumerator() { - return FX_EnumGdiFonts; -} - -#else // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ namespace { -const FX_CHAR* g_FontFolders[] = { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ +constexpr const char* g_FontFolders[] = { +#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ "/usr/share/fonts", "/usr/share/X11/fonts/Type1", "/usr/share/X11/fonts/TTF", "/usr/local/share/fonts", -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ "~/Library/Fonts", "/Library/Fonts", "/System/Library/Fonts", -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ +#elif _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ "/system/fonts", #endif }; -struct FX_BitCodePage { - uint16_t wBit; - uint16_t wCodePage; -}; - -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}, -}; +const uint16_t g_CodePages[] = {FX_CODEPAGE_MSWin_WesternEuropean, + FX_CODEPAGE_MSWin_EasternEuropean, + FX_CODEPAGE_MSWin_Cyrillic, + FX_CODEPAGE_MSWin_Greek, + FX_CODEPAGE_MSWin_Turkish, + FX_CODEPAGE_MSWin_Hebrew, + FX_CODEPAGE_MSWin_Arabic, + FX_CODEPAGE_MSWin_Baltic, + FX_CODEPAGE_MSWin_Vietnamese, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_MSDOS_Thai, + FX_CODEPAGE_ShiftJIS, + FX_CODEPAGE_ChineseSimplified, + FX_CODEPAGE_Hangul, + FX_CODEPAGE_ChineseTraditional, + FX_CODEPAGE_Johab, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_DefANSI, + FX_CODEPAGE_MSDOS_Greek2, + FX_CODEPAGE_MSDOS_Russian, + FX_CODEPAGE_MSDOS_Norwegian, + FX_CODEPAGE_MSDOS_Arabic, + FX_CODEPAGE_MSDOS_FrenchCanadian, + FX_CODEPAGE_MSDOS_Hebrew, + FX_CODEPAGE_MSDOS_Icelandic, + FX_CODEPAGE_MSDOS_Portuguese, + FX_CODEPAGE_MSDOS_Turkish, + FX_CODEPAGE_MSDOS_Cyrillic, + FX_CODEPAGE_MSDOS_EasternEuropean, + FX_CODEPAGE_MSDOS_Baltic, + FX_CODEPAGE_MSDOS_Greek1, + FX_CODEPAGE_Arabic_ASMO708, + FX_CODEPAGE_MSDOS_WesternEuropean, + FX_CODEPAGE_MSDOS_US}; uint16_t FX_GetCodePageBit(uint16_t wCodePage) { - for (size_t i = 0; i < FX_ArraySize(g_Bit2CodePage); ++i) { - if (g_Bit2CodePage[i].wCodePage == wCodePage) - return g_Bit2CodePage[i].wBit; + for (size_t i = 0; i < FX_ArraySize(g_CodePages); ++i) { + if (g_CodePages[i] == wCodePage) + return static_cast<uint16_t>(i); } return static_cast<uint16_t>(-1); } -uint16_t FX_GetUnicodeBit(FX_WCHAR wcUnicode) { +uint16_t FX_GetUnicodeBit(wchar_t wcUnicode) { const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wcUnicode); return x ? x->wBitField : 999; } @@ -416,7 +359,7 @@ struct FX_BIT2CHARSET { const FX_BIT2CHARSET g_FX_Bit2Charset[4][16] = { {{1 << 0, FX_CHARSET_ANSI}, - {1 << 1, FX_CHARSET_MSWin_EasterEuropean}, + {1 << 1, FX_CHARSET_MSWin_EasternEuropean}, {1 << 2, FX_CHARSET_MSWin_Cyrillic}, {1 << 3, FX_CHARSET_MSWin_Greek}, {1 << 4, FX_CHARSET_MSWin_Turkish}, @@ -434,8 +377,8 @@ const FX_BIT2CHARSET g_FX_Bit2Charset[4][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 << 3, FX_CHARSET_Hangul}, + {1 << 4, FX_CHARSET_ChineseTraditional}, {1 << 5, FX_CHARSET_Johab}, {1 << 6, FX_CHARSET_Default}, {1 << 7, FX_CHARSET_Default}, @@ -480,6 +423,29 @@ const FX_BIT2CHARSET g_FX_Bit2Charset[4][16] = { {1 << 14, FX_CHARSET_Default}, {1 << 15, FX_CHARSET_US}}}; +constexpr wchar_t kFolderSeparator = L'/'; + +extern "C" { + +unsigned long ftStreamRead(FXFT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count) { + if (count == 0) + return 0; + + IFX_SeekableReadStream* pFile = + static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer); + if (!pFile->ReadBlock(buffer, offset, count)) + return 0; + + return count; +} + +void ftStreamClose(FXFT_Stream stream) {} + +}; // extern "C" + } // namespace CFX_FontDescriptor::CFX_FontDescriptor() @@ -494,22 +460,22 @@ CFX_FontSourceEnum_File::CFX_FontSourceEnum_File() { CFX_FontSourceEnum_File::~CFX_FontSourceEnum_File() {} -CFX_ByteString CFX_FontSourceEnum_File::GetNextFile() { +ByteString CFX_FontSourceEnum_File::GetNextFile() { FX_FileHandle* pCurHandle = !m_FolderQueue.empty() ? m_FolderQueue.back().pFileHandle : nullptr; if (!pCurHandle) { if (m_FolderPaths.empty()) return ""; pCurHandle = FX_OpenFolder(m_FolderPaths.back().c_str()); - FX_HandleParentPath hpp; + HandleParentPath hpp; hpp.pFileHandle = pCurHandle; hpp.bsParentPath = m_FolderPaths.back(); m_FolderQueue.push_back(hpp); } - CFX_ByteString bsName; + ByteString bsName; bool bFolder; - CFX_ByteString bsFolderSeparator = - CFX_ByteString::FromUnicode(CFX_WideString(FX_GetFolderSeparator())); + ByteString bsFolderSeparator = + ByteString::FromUnicode(WideString(kFolderSeparator)); while (true) { if (!FX_GetNextFile(pCurHandle, &bsName, &bFolder)) { FX_CloseFolder(pCurHandle); @@ -526,7 +492,7 @@ CFX_ByteString CFX_FontSourceEnum_File::GetNextFile() { if (bsName == "." || bsName == "..") continue; if (bFolder) { - FX_HandleParentPath hpp; + HandleParentPath hpp; hpp.bsParentPath = m_FolderQueue.back().bsParentPath + bsFolderSeparator + bsName; hpp.pFileHandle = FX_OpenFolder(hpp.bsParentPath.c_str()); @@ -542,35 +508,25 @@ CFX_ByteString CFX_FontSourceEnum_File::GetNextFile() { return bsName; } -FX_POSITION CFX_FontSourceEnum_File::GetStartPosition() { - m_wsNext = GetNextFile().UTF8Decode(); - if (m_wsNext.GetLength() == 0) - return (FX_POSITION)0; - return (FX_POSITION)-1; -} - -CFX_RetainPtr<IFX_FileAccess> CFX_FontSourceEnum_File::GetNext( - FX_POSITION& pos) { - CFX_RetainPtr<IFX_FileAccess> pAccess = - IFX_FileAccess::CreateDefault(m_wsNext.AsStringC()); +bool CFX_FontSourceEnum_File::HasStartPosition() { m_wsNext = GetNextFile().UTF8Decode(); - pos = m_wsNext.GetLength() != 0 ? pAccess.Get() : nullptr; - return pAccess; + return m_wsNext.GetLength() != 0; } -std::unique_ptr<CFGAS_FontMgr> CFGAS_FontMgr::Create( - CFX_FontSourceEnum_File* pFontEnum) { - if (!pFontEnum) - return nullptr; +// <next exists, stream for next> +std::pair<bool, RetainPtr<IFX_SeekableStream>> +CFX_FontSourceEnum_File::GetNext() { + if (m_wsNext.GetLength() == 0) + return {false, nullptr}; - auto pFontMgr = pdfium::MakeUnique<CFGAS_FontMgr>(pFontEnum); - if (!pFontMgr->EnumFonts()) - return nullptr; - return pFontMgr; + auto stream = IFX_SeekableStream::CreateFromFilename(m_wsNext.c_str(), + FX_FILEMODE_ReadOnly); + m_wsNext = GetNextFile().UTF8Decode(); + return {true, stream}; } -CFGAS_FontMgr::CFGAS_FontMgr(CFX_FontSourceEnum_File* pFontEnum) - : m_pFontSource(pFontEnum) {} +CFGAS_FontMgr::CFGAS_FontMgr() + : m_pFontSource(pdfium::MakeUnique<CFX_FontSourceEnum_File>()) {} CFGAS_FontMgr::~CFGAS_FontMgr() {} @@ -586,13 +542,13 @@ bool CFGAS_FontMgr::EnumFontsFromFontMapper() { pSystemFontInfo->EnumFontList(pFontMapper); for (int32_t i = 0; i < pFontMapper->GetFaceSize(); ++i) { - CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = + RetainPtr<IFX_SeekableReadStream> pFontStream = CreateFontStream(pFontMapper, pSystemFontInfo, i); if (!pFontStream) continue; - CFX_WideString wsFaceName = - CFX_WideString::FromLocal(pFontMapper->GetFaceName(i).c_str()); + WideString wsFaceName = + WideString::FromLocal(pFontMapper->GetFaceName(i).c_str()); RegisterFaces(pFontStream, &wsFaceName); } return !m_InstalledFonts.empty(); @@ -600,13 +556,16 @@ bool CFGAS_FontMgr::EnumFontsFromFontMapper() { bool CFGAS_FontMgr::EnumFontsFromFiles() { CFX_GEModule::Get()->GetFontMgr()->InitFTLibrary(); - FX_POSITION pos = m_pFontSource->GetStartPosition(); - while (pos) { - CFX_RetainPtr<IFX_FileAccess> pFontSource = m_pFontSource->GetNext(pos); - CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = - pFontSource->CreateFileStream(FX_FILEMODE_ReadOnly); - if (pFontStream) - RegisterFaces(pFontStream, nullptr); + if (!m_pFontSource->HasStartPosition()) + return !m_InstalledFonts.empty(); + + bool has_next; + RetainPtr<IFX_SeekableStream> stream; + std::tie(has_next, stream) = m_pFontSource->GetNext(); + while (has_next) { + if (stream) + RegisterFaces(stream, nullptr); + std::tie(has_next, stream) = m_pFontSource->GetNext(); } return !m_InstalledFonts.empty(); } @@ -615,99 +574,9 @@ bool CFGAS_FontMgr::EnumFonts() { return EnumFontsFromFontMapper() || EnumFontsFromFiles(); } -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( - const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage) { - return GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily); -} - -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByCodePage( - uint16_t wCodePage, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily) { - CFX_ByteString bsHash; - bsHash.Format("%d, %d", wCodePage, dwFontStyles); - bsHash += FX_UTF8Encode(CFX_WideStringC(pszFontFamily)); - uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false); - std::vector<CFX_RetainPtr<CFGAS_GEFont>>* pFontArray = &m_Hash2Fonts[dwHash]; - if (!pFontArray->empty()) - return (*pFontArray)[0]; - - std::vector<CFX_FontDescriptorInfo>* sortedFontInfos = - m_Hash2CandidateList[dwHash].get(); - if (!sortedFontInfos) { - auto pNewFonts = pdfium::MakeUnique<std::vector<CFX_FontDescriptorInfo>>(); - sortedFontInfos = pNewFonts.get(); - MatchFonts(sortedFontInfos, wCodePage, dwFontStyles, - CFX_WideString(pszFontFamily), 0); - m_Hash2CandidateList[dwHash] = std::move(pNewFonts); - } - if (sortedFontInfos->empty()) - return nullptr; - - CFX_FontDescriptor* pDesc = (*sortedFontInfos)[0].pFont; - CFX_RetainPtr<CFGAS_GEFont> pFont = - LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); - if (!pFont) - return nullptr; - - pFont->SetLogicalFontStyle(dwFontStyles); - pFontArray->push_back(pFont); - return pFont; -} - -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicode( - FX_WCHAR wUnicode, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily) { - if (pdfium::ContainsKey(m_FailedUnicodesSet, wUnicode)) - return nullptr; - - const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode); - uint16_t wCodePage = x ? x->wCodePage : 0xFFFF; - uint16_t wBitField = x ? x->wBitField : 0x03E7; - CFX_ByteString bsHash; - if (wCodePage == 0xFFFF) - bsHash.Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles); - else - bsHash.Format("%d, %d", wCodePage, dwFontStyles); - bsHash += FX_UTF8Encode(CFX_WideStringC(pszFontFamily)); - uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false); - std::vector<CFX_RetainPtr<CFGAS_GEFont>>* pFonts = &m_Hash2Fonts[dwHash]; - for (size_t i = 0; i < pFonts->size(); ++i) { - if (VerifyUnicode((*pFonts)[i], wUnicode)) - return (*pFonts)[i]; - } - std::vector<CFX_FontDescriptorInfo>* sortedFontInfos = - m_Hash2CandidateList[dwHash].get(); - if (!sortedFontInfos) { - auto pNewFonts = pdfium::MakeUnique<std::vector<CFX_FontDescriptorInfo>>(); - sortedFontInfos = pNewFonts.get(); - MatchFonts(sortedFontInfos, wCodePage, dwFontStyles, - CFX_WideString(pszFontFamily), wUnicode); - m_Hash2CandidateList[dwHash] = std::move(pNewFonts); - } - for (const auto& info : *sortedFontInfos) { - CFX_FontDescriptor* pDesc = info.pFont; - if (!VerifyUnicode(pDesc, wUnicode)) - continue; - CFX_RetainPtr<CFGAS_GEFont> pFont = - LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); - if (!pFont) - continue; - pFont->SetLogicalFontStyle(dwFontStyles); - pFonts->push_back(pFont); - return pFont; - } - if (!pszFontFamily) - m_FailedUnicodesSet.insert(wUnicode); - return nullptr; -} - bool CFGAS_FontMgr::VerifyUnicode(CFX_FontDescriptor* pDesc, - FX_WCHAR wcUnicode) { - CFX_RetainPtr<IFX_SeekableReadStream> pFileRead = + wchar_t wcUnicode) { + RetainPtr<IFX_SeekableReadStream> pFileRead = CreateFontStream(pDesc->m_wsFaceName.UTF8Encode()); if (!pFileRead) return false; @@ -725,27 +594,9 @@ bool CFGAS_FontMgr::VerifyUnicode(CFX_FontDescriptor* pDesc, return !retCharmap && retIndex; } -bool CFGAS_FontMgr::VerifyUnicode(const CFX_RetainPtr<CFGAS_GEFont>& pFont, - FX_WCHAR wcUnicode) { - if (!pFont) - return false; - - FXFT_Face pFace = pFont->GetDevFont()->GetFace(); - FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace); - if (FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE) != 0) - return false; - - if (FXFT_Get_Char_Index(pFace, wcUnicode) == 0) { - FXFT_Set_Charmap(pFace, charmap); - return false; - } - return true; -} - -CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( - const CFX_WideString& wsFaceName, - int32_t iFaceIndex, - int32_t* pFaceCount) { +RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont(const WideString& wsFaceName, + int32_t iFaceIndex, + int32_t* pFaceCount) { CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper(); if (!pFontMapper) @@ -755,7 +606,7 @@ CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( if (!pSystemFontInfo) return nullptr; - CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = + RetainPtr<IFX_SeekableReadStream> pFontStream = CreateFontStream(wsFaceName.UTF8Encode()); if (!pFontStream) return nullptr; @@ -764,7 +615,7 @@ CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) return nullptr; - CFX_RetainPtr<CFGAS_GEFont> pFont = + RetainPtr<CFGAS_GEFont> pFont = CFGAS_GEFont::LoadFont(std::move(pInternalFont), this); if (!pFont) return nullptr; @@ -775,29 +626,8 @@ CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( 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_SeekableReadStream* pFile = - static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer); - if (!pFile->ReadBlock(buffer, offset, count)) - return 0; - - return count; -} - -void _ftStreamClose(FXFT_Stream stream) {} - -}; // extern "C" - FXFT_Face CFGAS_FontMgr::LoadFace( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFontStream, + const RetainPtr<IFX_SeekableReadStream>& pFontStream, int32_t iFaceIndex) { if (!pFontStream) return nullptr; @@ -809,23 +639,28 @@ FXFT_Face CFGAS_FontMgr::LoadFace( if (!library) return nullptr; - FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1); - FXSYS_memset(ftStream, 0, sizeof(FXFT_StreamRec)); + // TODO(palmer): This memory will be freed with |ft_free| (which is |free|). + // Ultimately, we want to change this to: + // FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1); + // https://bugs.chromium.org/p/pdfium/issues/detail?id=690 + FXFT_Stream ftStream = + static_cast<FXFT_Stream>(ft_scalloc(sizeof(FXFT_StreamRec), 1)); + memset(ftStream, 0, sizeof(FXFT_StreamRec)); ftStream->base = nullptr; ftStream->descriptor.pointer = static_cast<void*>(pFontStream.Get()); ftStream->pos = 0; ftStream->size = static_cast<unsigned long>(pFontStream->GetSize()); - ftStream->read = _ftStreamRead; - ftStream->close = _ftStreamClose; + ftStream->read = ftStreamRead; + ftStream->close = ftStreamClose; FXFT_Open_Args ftArgs; - FXSYS_memset(&ftArgs, 0, sizeof(FXFT_Open_Args)); + memset(&ftArgs, 0, sizeof(FXFT_Open_Args)); ftArgs.flags |= FT_OPEN_STREAM; ftArgs.stream = ftStream; FXFT_Face pFace = nullptr; if (FXFT_Open_Face(library, &ftArgs, iFaceIndex, &pFace)) { - FX_Free(ftStream); + ft_sfree(ftStream); return nullptr; } @@ -833,14 +668,12 @@ FXFT_Face CFGAS_FontMgr::LoadFace( return pFace; } -CFX_RetainPtr<IFX_SeekableReadStream> CFGAS_FontMgr::CreateFontStream( +RetainPtr<IFX_SeekableReadStream> CFGAS_FontMgr::CreateFontStream( CFX_FontMapper* pFontMapper, IFX_SystemFontInfo* pSystemFontInfo, uint32_t index) { - int iExact = 0; - void* hFont = - pSystemFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, - pFontMapper->GetFaceName(index).c_str(), iExact); + void* hFont = pSystemFontInfo->MapFont( + 0, 0, FX_CHARSET_Default, 0, pFontMapper->GetFaceName(index).c_str()); if (!hFont) return nullptr; @@ -851,11 +684,11 @@ CFX_RetainPtr<IFX_SeekableReadStream> CFGAS_FontMgr::CreateFontStream( uint8_t* pBuffer = FX_Alloc(uint8_t, dwFileSize + 1); dwFileSize = pSystemFontInfo->GetFontData(hFont, 0, pBuffer, dwFileSize); - return IFX_MemoryStream::Create(pBuffer, dwFileSize, true); + return pdfium::MakeRetain<CFX_MemoryStream>(pBuffer, dwFileSize, true); } -CFX_RetainPtr<IFX_SeekableReadStream> CFGAS_FontMgr::CreateFontStream( - const CFX_ByteString& bsFaceName) { +RetainPtr<IFX_SeekableReadStream> CFGAS_FontMgr::CreateFontStream( + const ByteString& bsFaceName) { CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper(); if (!pFontMapper) @@ -877,8 +710,8 @@ void CFGAS_FontMgr::MatchFonts( std::vector<CFX_FontDescriptorInfo>* pMatchedFonts, uint16_t wCodePage, uint32_t dwFontStyles, - const CFX_WideString& FontName, - FX_WCHAR wcUnicode) { + const WideString& FontName, + wchar_t wcUnicode) { pMatchedFonts->clear(); for (const auto& pFont : m_InstalledFonts) { int32_t nPenalty = @@ -895,8 +728,8 @@ void CFGAS_FontMgr::MatchFonts( int32_t CFGAS_FontMgr::CalcPenalty(CFX_FontDescriptor* pInstalled, uint16_t wCodePage, uint32_t dwFontStyles, - const CFX_WideString& FontName, - FX_WCHAR wcUnicode) { + const WideString& FontName, + wchar_t wcUnicode) { int32_t nPenalty = 30000; if (FontName.GetLength() != 0) { if (FontName != pInstalled->m_wsFaceName) { @@ -928,20 +761,20 @@ int32_t CFGAS_FontMgr::CalcPenalty(CFX_FontDescriptor* pInstalled, } } uint32_t dwStyleMask = pInstalled->m_dwFontStyles ^ dwFontStyles; - if (dwStyleMask & FX_FONTSTYLE_Bold) + if (FontStyleIsBold(dwStyleMask)) nPenalty += 4500; - if (dwStyleMask & FX_FONTSTYLE_FixedPitch) + if (FontStyleIsFixedPitch(dwStyleMask)) nPenalty += 10000; - if (dwStyleMask & FX_FONTSTYLE_Italic) + if (FontStyleIsItalic(dwStyleMask)) nPenalty += 10000; - if (dwStyleMask & FX_FONTSTYLE_Serif) + if (FontStyleIsSerif(dwStyleMask)) nPenalty += 500; - if (dwStyleMask & FX_FONTSTYLE_Symbolic) + if (FontStyleIsSymbolic(dwStyleMask)) nPenalty += 0xFFFF; if (nPenalty >= 0xFFFF) return 0xFFFF; - uint16_t wBit = (wCodePage == 0 || wCodePage == 0xFFFF) + uint16_t wBit = (wCodePage == FX_CODEPAGE_DefANSI || wCodePage == 0xFFFF) ? static_cast<uint16_t>(-1) : FX_GetCodePageBit(wCodePage); if (wBit != static_cast<uint16_t>(-1)) { @@ -963,35 +796,13 @@ int32_t CFGAS_FontMgr::CalcPenalty(CFX_FontDescriptor* pInstalled, return nPenalty; } -void CFGAS_FontMgr::RemoveFont(const CFX_RetainPtr<CFGAS_GEFont>& pEFont) { - if (!pEFont) - return; - - m_IFXFont2FileRead.erase(pEFont); - - auto iter = m_Hash2Fonts.begin(); - while (iter != m_Hash2Fonts.end()) { - auto old_iter = iter++; - bool all_empty = true; - for (size_t i = 0; i < old_iter->second.size(); i++) { - if (old_iter->second[i] == pEFont) - old_iter->second[i].Reset(); - else if (old_iter->second[i]) - all_empty = false; - } - if (all_empty) - m_Hash2Fonts.erase(old_iter); - } -} - -void CFGAS_FontMgr::RegisterFace(FXFT_Face pFace, - const CFX_WideString* pFaceName) { +void CFGAS_FontMgr::RegisterFace(FXFT_Face pFace, const WideString* pFaceName) { if ((pFace->face_flags & FT_FACE_FLAG_SCALABLE) == 0) return; auto pFont = pdfium::MakeUnique<CFX_FontDescriptor>(); - 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 |= FXFT_Is_Face_Bold(pFace) ? FXFONT_BOLD : 0; + pFont->m_dwFontStyles |= FXFT_Is_Face_Italic(pFace) ? FXFONT_ITALIC : 0; pFont->m_dwFontStyles |= GetFlags(pFace); std::vector<uint16_t> charsets = GetCharsets(pFace); @@ -1009,18 +820,17 @@ void CFGAS_FontMgr::RegisterFace(FXFT_Face pFace, table.clear(); } GetNames(table.empty() ? nullptr : table.data(), pFont->m_wsFamilyNames); - pFont->m_wsFamilyNames.push_back( - CFX_ByteString(pFace->family_name).UTF8Decode()); + pFont->m_wsFamilyNames.push_back(ByteString(pFace->family_name).UTF8Decode()); pFont->m_wsFaceName = pFaceName ? *pFaceName - : CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(pFace)); + : WideString::FromLocal(FXFT_Get_Postscript_Name(pFace)); pFont->m_nFaceIndex = pFace->face_index; m_InstalledFonts.push_back(std::move(pFont)); } void CFGAS_FontMgr::RegisterFaces( - const CFX_RetainPtr<IFX_SeekableReadStream>& pFontStream, - const CFX_WideString* pFaceName) { + const RetainPtr<IFX_SeekableReadStream>& pFontStream, + const WideString* pFaceName) { int32_t index = 0; int32_t num_faces = 0; do { @@ -1040,28 +850,28 @@ void CFGAS_FontMgr::RegisterFaces( uint32_t CFGAS_FontMgr::GetFlags(FXFT_Face pFace) { uint32_t flag = 0; if (FT_IS_FIXED_WIDTH(pFace)) - flag |= FX_FONTSTYLE_FixedPitch; + flag |= FXFONT_FIXED_PITCH; 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; + flag |= FXFONT_SYMBOLIC; if (pOS2->panose[0] == 2) { uint8_t uSerif = pOS2->panose[1]; if ((uSerif > 1 && uSerif < 10) || uSerif > 13) - flag |= FX_FONTSTYLE_Serif; + flag |= FXFONT_SERIF; } return flag; } void CFGAS_FontMgr::GetNames(const uint8_t* name_table, - std::vector<CFX_WideString>& Names) { + std::vector<WideString>& Names) { if (!name_table) return; uint8_t* lpTable = (uint8_t*)name_table; - CFX_WideString wsFamily; + WideString wsFamily; uint8_t* sp = lpTable + 2; uint8_t* lpNameRecord = lpTable + 6; uint16_t nNameCount = GetUInt16(sp); @@ -1077,14 +887,14 @@ void CFGAS_FontMgr::GetNames(const uint8_t* name_table, wsFamily.clear(); if (nPlatformID != 1) { for (uint16_t k = 0; k < nNameLength / 2; k++) { - FX_WCHAR wcTemp = GetUInt16(lpStr + nNameOffset + k * 2); + wchar_t wcTemp = GetUInt16(lpStr + nNameOffset + k * 2); wsFamily += wcTemp; } Names.push_back(wsFamily); continue; } for (uint16_t k = 0; k < nNameLength; k++) { - FX_WCHAR wcTemp = GetUInt8(lpStr + nNameOffset + k); + wchar_t wcTemp = GetUInt8(lpStr + nNameOffset + k); wsFamily += wcTemp; } Names.push_back(wsFamily); @@ -1129,11 +939,205 @@ void CFGAS_FontMgr::GetUSBCSB(FXFT_Face pFace, uint32_t* USB, uint32_t* CSB) { CSB[1] = pOS2->ulCodePageRange2; } -int32_t CFGAS_FontMgr::IsPartName(const CFX_WideString& Name1, - const CFX_WideString& Name2) { - if (Name1.Find(Name2.c_str()) != -1) +int32_t CFGAS_FontMgr::IsPartName(const WideString& Name1, + const WideString& Name2) { + if (Name1.Contains(Name2.c_str())) return 1; return 0; } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + +RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByCodePage( + uint16_t wCodePage, + uint32_t dwFontStyles, + const wchar_t* pszFontFamily) { + ByteString bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles); + bsHash += FX_UTF8Encode(WideStringView(pszFontFamily)); + uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringView(), false); + std::vector<RetainPtr<CFGAS_GEFont>>* pFontArray = &m_Hash2Fonts[dwHash]; + if (!pFontArray->empty()) + return (*pFontArray)[0]; + +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const FX_FONTDESCRIPTOR* pFD = + FindFont(pszFontFamily, dwFontStyles, true, wCodePage, 999, 0); + if (!pFD) + pFD = FindFont(nullptr, dwFontStyles, true, wCodePage, 999, 0); + if (!pFD) + pFD = FindFont(nullptr, dwFontStyles, false, wCodePage, 999, 0); + if (!pFD) + return nullptr; + + RetainPtr<CFGAS_GEFont> pFont = + CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + std::vector<CFX_FontDescriptorInfo>* sortedFontInfos = + m_Hash2CandidateList[dwHash].get(); + if (!sortedFontInfos) { + auto pNewFonts = pdfium::MakeUnique<std::vector<CFX_FontDescriptorInfo>>(); + sortedFontInfos = pNewFonts.get(); + MatchFonts(sortedFontInfos, wCodePage, dwFontStyles, + WideString(pszFontFamily), 0); + m_Hash2CandidateList[dwHash] = std::move(pNewFonts); + } + if (sortedFontInfos->empty()) + return nullptr; + + CFX_FontDescriptor* pDesc = (*sortedFontInfos)[0].pFont; + RetainPtr<CFGAS_GEFont> pFont = + LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + + if (!pFont) + return nullptr; + + pFont->SetLogicalFontStyle(dwFontStyles); + pFontArray->push_back(pFont); + return pFont; +} + +RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicode( + wchar_t wUnicode, + uint32_t dwFontStyles, + const wchar_t* pszFontFamily) { +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + if (pdfium::ContainsKey(m_FailedUnicodesSet, wUnicode)) + return nullptr; +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + + const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode); + uint16_t wCodePage = x ? x->wCodePage : 0xFFFF; + uint16_t wBitField = x ? x->wBitField : 0x03E7; + ByteString bsHash; + if (wCodePage == 0xFFFF) { + bsHash = + ByteString::Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles); + } else { + bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles); + } + bsHash += FX_UTF8Encode(WideStringView(pszFontFamily)); + uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringView(), false); + std::vector<RetainPtr<CFGAS_GEFont>>* pFonts = &m_Hash2Fonts[dwHash]; + for (size_t i = 0; i < pFonts->size(); ++i) { + if (VerifyUnicode((*pFonts)[i], wUnicode)) + return (*pFonts)[i]; + } +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const FX_FONTDESCRIPTOR* pFD = FindFont(pszFontFamily, dwFontStyles, false, + wCodePage, wBitField, wUnicode); + if (!pFD && pszFontFamily) { + pFD = + FindFont(nullptr, dwFontStyles, false, wCodePage, wBitField, wUnicode); + } + if (!pFD) + return nullptr; + + uint16_t newCodePage = GetCodePageFromCharset(pFD->uCharSet); + const wchar_t* pFontFace = pFD->wsFontFace; + RetainPtr<CFGAS_GEFont> pFont = + CFGAS_GEFont::LoadFont(pFontFace, dwFontStyles, newCodePage, this); + if (!pFont) + return nullptr; + + pFont->SetLogicalFontStyle(dwFontStyles); + pFonts->push_back(pFont); + return pFont; +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + std::vector<CFX_FontDescriptorInfo>* sortedFontInfos = + m_Hash2CandidateList[dwHash].get(); + if (!sortedFontInfos) { + auto pNewFonts = pdfium::MakeUnique<std::vector<CFX_FontDescriptorInfo>>(); + sortedFontInfos = pNewFonts.get(); + MatchFonts(sortedFontInfos, wCodePage, dwFontStyles, + WideString(pszFontFamily), wUnicode); + m_Hash2CandidateList[dwHash] = std::move(pNewFonts); + } + for (const auto& info : *sortedFontInfos) { + CFX_FontDescriptor* pDesc = info.pFont; + if (!VerifyUnicode(pDesc, wUnicode)) + continue; + RetainPtr<CFGAS_GEFont> pFont = + LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); + if (!pFont) + continue; + pFont->SetLogicalFontStyle(dwFontStyles); + pFonts->push_back(pFont); + return pFont; + } + if (!pszFontFamily) + m_FailedUnicodesSet.insert(wUnicode); + return nullptr; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +} + +bool CFGAS_FontMgr::VerifyUnicode(const RetainPtr<CFGAS_GEFont>& pFont, + wchar_t wcUnicode) { + if (!pFont) + return false; + + FXFT_Face pFace = pFont->GetDevFont()->GetFace(); + FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace); + if (FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE) != 0) + return false; + + if (FXFT_Get_Char_Index(pFace, wcUnicode) == 0) { + FXFT_Set_Charmap(pFace, charmap); + return false; + } + return true; +} + +RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont(const wchar_t* pszFontFamily, + uint32_t dwFontStyles, + uint16_t wCodePage) { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + ByteString bsHash = ByteString::Format("%d, %d", wCodePage, dwFontStyles); + bsHash += FX_UTF8Encode(WideStringView(pszFontFamily)); + uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringView(), false); + std::vector<RetainPtr<CFGAS_GEFont>>* pFontArray = &m_Hash2Fonts[dwHash]; + if (!pFontArray->empty()) + return (*pFontArray)[0]; + + const FX_FONTDESCRIPTOR* pFD = + FindFont(pszFontFamily, dwFontStyles, true, wCodePage, 999, 0); + if (!pFD) + pFD = FindFont(pszFontFamily, dwFontStyles, false, wCodePage, 999, 0); + if (!pFD) + return nullptr; + + RetainPtr<CFGAS_GEFont> pFont = + CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); + if (!pFont) + return nullptr; + + pFont->SetLogicalFontStyle(dwFontStyles); + pFontArray->push_back(pFont); + return pFont; +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + return GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +} + +void CFGAS_FontMgr::RemoveFont(const RetainPtr<CFGAS_GEFont>& pEFont) { + if (!pEFont) + return; + +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + m_IFXFont2FileRead.erase(pEFont); +#endif // _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ + + auto iter = m_Hash2Fonts.begin(); + while (iter != m_Hash2Fonts.end()) { + auto old_iter = iter++; + bool all_empty = true; + for (size_t i = 0; i < old_iter->second.size(); i++) { + if (old_iter->second[i] == pEFont) + old_iter->second[i].Reset(); + else if (old_iter->second[i]) + all_empty = false; + } + if (all_empty) + m_Hash2Fonts.erase(old_iter); + } +} diff --git a/xfa/fgas/font/cfgas_fontmgr.h b/xfa/fgas/font/cfgas_fontmgr.h index dffdb8a665b051f8be45b02631f57963e26856f6..445b318a26b061d214b7dc8c766e595079094720 100644 --- a/xfa/fgas/font/cfgas_fontmgr.h +++ b/xfa/fgas/font/cfgas_fontmgr.h @@ -11,44 +11,28 @@ #include <map> #include <memory> #include <set> +#include <utility> #include <vector> -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_ext.h" -#include "core/fxge/cfx_fontmapper.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/observable.h" +#include "core/fxcrt/retain_ptr.h" #include "core/fxge/fx_freetype.h" #include "core/fxge/ifx_systemfontinfo.h" -#include "third_party/freetype/include/freetype/fttypes.h" -#include "xfa/fgas/crt/fgas_stream.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#include "xfa/fgas/crt/fgas_utils.h" -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - -#define FX_FONTSTYLE_Normal 0x00 -#define FX_FONTSTYLE_FixedPitch 0x01 -#define FX_FONTSTYLE_Serif 0x02 -#define FX_FONTSTYLE_Symbolic 0x04 -#define FX_FONTSTYLE_Script 0x08 -#define FX_FONTSTYLE_Italic 0x40 -#define FX_FONTSTYLE_Bold 0x40000 -#define FX_FONTSTYLE_BoldItalic (FX_FONTSTYLE_Bold | FX_FONTSTYLE_Italic) -#define FX_FONTSTYLE_ExactMatch 0x80000000 +#include "xfa/fgas/font/cfgas_pdffontmgr.h" -class CFX_FontSourceEnum_File; -class CXFA_PDFFontMgr; -class CFGAS_FontMgr; class CFGAS_GEFont; +class CFX_FontMapper; +class CFX_FontSourceEnum_File; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#define FX_FONTMATCHPARA_MatchStyle 0x01 - +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ struct FX_FONTMATCHPARAMS { - const FX_WCHAR* pwsFamily; + const wchar_t* pwsFamily; uint32_t dwFontStyles; uint32_t dwUSB; - uint32_t dwMatchFlags; - FX_WCHAR wUnicode; + bool matchParagraphStyle; + wchar_t wUnicode; uint16_t wCodePage; }; @@ -65,7 +49,7 @@ inline bool operator==(const FX_FONTSIGNATURE& left, } struct FX_FONTDESCRIPTOR { - FX_WCHAR wsFontFace[32]; + wchar_t wsFontFace[32]; uint32_t dwFontStyles; uint8_t uCharSet; FX_FONTSIGNATURE FontSignature; @@ -76,67 +60,23 @@ inline bool operator==(const FX_FONTDESCRIPTOR& left, return left.uCharSet == right.uCharSet && left.dwFontStyles == right.dwFontStyles && left.FontSignature == right.FontSignature && - FXSYS_wcscmp(left.wsFontFace, right.wsFontFace) == 0; + wcscmp(left.wsFontFace, right.wsFontFace) == 0; } typedef void (*FX_LPEnumAllFonts)(std::deque<FX_FONTDESCRIPTOR>* fonts, - const FX_WCHAR* pwsFaceName, - FX_WCHAR wUnicode); - -FX_LPEnumAllFonts FX_GetDefFontEnumerator(); - -class CFGAS_FontMgr { - public: - static std::unique_ptr<CFGAS_FontMgr> Create(FX_LPEnumAllFonts pEnumerator); - - explicit CFGAS_FontMgr(FX_LPEnumAllFonts pEnumerator); - ~CFGAS_FontMgr(); + const wchar_t* pwsFaceName, + wchar_t wUnicode); - CFX_RetainPtr<CFGAS_GEFont> GetFontByCodePage(uint16_t wCodePage, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily); - CFX_RetainPtr<CFGAS_GEFont> GetFontByUnicode(FX_WCHAR wUnicode, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily); - CFX_RetainPtr<CFGAS_GEFont> LoadFont(const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage); - void RemoveFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont); - - private: - CFX_RetainPtr<CFGAS_GEFont> LoadFont( - const CFX_RetainPtr<CFGAS_GEFont>& pSrcFont, - uint32_t dwFontStyles, - uint16_t wCodePage); - void RemoveFont(std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>>* pFontMap, - const CFX_RetainPtr<CFGAS_GEFont>& pFont); - const FX_FONTDESCRIPTOR* FindFont(const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint32_t dwMatchFlags, - uint16_t wCodePage, - uint32_t dwUSB = 999, - FX_WCHAR wUnicode = 0); - - FX_LPEnumAllFonts m_pEnumerator; - std::deque<FX_FONTDESCRIPTOR> m_FontFaces; - std::vector<CFX_RetainPtr<CFGAS_GEFont>> m_Fonts; - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>> m_CPFonts; - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>> m_FamilyFonts; - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>> m_UnicodeFonts; - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>> m_BufferFonts; - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>> m_StreamFonts; - std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>> m_DeriveFonts; -}; +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ -#else // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ class CFX_FontDescriptor { public: CFX_FontDescriptor(); ~CFX_FontDescriptor(); int32_t m_nFaceIndex; - CFX_WideString m_wsFaceName; - std::vector<CFX_WideString> m_wsFamilyNames; + WideString m_wsFaceName; + std::vector<WideString> m_wsFamilyNames; uint32_t m_dwFontStyles; uint32_t m_dwUsb[4]; uint32_t m_dwCsb[2]; @@ -158,97 +98,109 @@ class CFX_FontDescriptorInfo { } }; -struct FX_HandleParentPath { - FX_HandleParentPath() {} - FX_HandleParentPath(const FX_HandleParentPath& x) { - pFileHandle = x.pFileHandle; - bsParentPath = x.bsParentPath; - } - FX_FileHandle* pFileHandle; - CFX_ByteString bsParentPath; -}; - class CFX_FontSourceEnum_File { public: CFX_FontSourceEnum_File(); ~CFX_FontSourceEnum_File(); - FX_POSITION GetStartPosition(); - CFX_RetainPtr<IFX_FileAccess> GetNext(FX_POSITION& pos); + bool HasStartPosition(); + std::pair<bool, RetainPtr<IFX_SeekableStream>> GetNext(); private: - CFX_ByteString GetNextFile(); - - CFX_WideString m_wsNext; - std::vector<FX_HandleParentPath> m_FolderQueue; - std::vector<CFX_ByteString> m_FolderPaths; + struct HandleParentPath { + HandleParentPath() = default; + HandleParentPath(const HandleParentPath& x) { + pFileHandle = x.pFileHandle; + bsParentPath = x.bsParentPath; + } + FX_FileHandle* pFileHandle; + ByteString bsParentPath; + }; + + ByteString GetNextFile(); + + WideString m_wsNext; + std::vector<HandleParentPath> m_FolderQueue; + std::vector<ByteString> m_FolderPaths; }; -class CFGAS_FontMgr { - public: - static std::unique_ptr<CFGAS_FontMgr> Create( - CFX_FontSourceEnum_File* pFontEnum); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ - explicit CFGAS_FontMgr(CFX_FontSourceEnum_File* pFontEnum); +class CFGAS_FontMgr : public Observable<CFGAS_FontMgr> { + public: + CFGAS_FontMgr(); ~CFGAS_FontMgr(); - CFX_RetainPtr<CFGAS_GEFont> GetFontByCodePage(uint16_t wCodePage, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily); - CFX_RetainPtr<CFGAS_GEFont> GetFontByUnicode(FX_WCHAR wUnicode, - uint32_t dwFontStyles, - const FX_WCHAR* pszFontFamily); - CFX_RetainPtr<CFGAS_GEFont> LoadFont(const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage); - void RemoveFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont); + RetainPtr<CFGAS_GEFont> GetFontByCodePage(uint16_t wCodePage, + uint32_t dwFontStyles, + const wchar_t* pszFontFamily); + RetainPtr<CFGAS_GEFont> GetFontByUnicode(wchar_t wUnicode, + uint32_t dwFontStyles, + const wchar_t* pszFontFamily); + RetainPtr<CFGAS_GEFont> LoadFont(const wchar_t* pszFontFamily, + uint32_t dwFontStyles, + uint16_t wCodePage); + void RemoveFont(const RetainPtr<CFGAS_GEFont>& pFont); - private: bool EnumFonts(); + + private: +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + const FX_FONTDESCRIPTOR* FindFont(const wchar_t* pszFontFamily, + uint32_t dwFontStyles, + bool matchParagraphStyle, + uint16_t wCodePage, + uint32_t dwUSB, + wchar_t wUnicode); + + FX_LPEnumAllFonts m_pEnumerator; + std::deque<FX_FONTDESCRIPTOR> m_FontFaces; +#else // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ bool EnumFontsFromFontMapper(); bool EnumFontsFromFiles(); - void RegisterFace(FXFT_Face pFace, const CFX_WideString* pFaceName); - void RegisterFaces(const CFX_RetainPtr<IFX_SeekableReadStream>& pFontStream, - const CFX_WideString* pFaceName); - void GetNames(const uint8_t* name_table, std::vector<CFX_WideString>& Names); + void RegisterFace(FXFT_Face pFace, const WideString* pFaceName); + void RegisterFaces(const RetainPtr<IFX_SeekableReadStream>& pFontStream, + const WideString* pFaceName); + void GetNames(const uint8_t* name_table, std::vector<WideString>& Names); std::vector<uint16_t> GetCharsets(FXFT_Face pFace) const; void GetUSBCSB(FXFT_Face pFace, uint32_t* USB, uint32_t* CSB); uint32_t GetFlags(FXFT_Face pFace); - bool VerifyUnicode(CFX_FontDescriptor* pDesc, FX_WCHAR wcUnicode); - bool VerifyUnicode(const CFX_RetainPtr<CFGAS_GEFont>& pFont, - FX_WCHAR wcUnicode); - int32_t IsPartName(const CFX_WideString& Name1, const CFX_WideString& Name2); + bool VerifyUnicode(CFX_FontDescriptor* pDesc, wchar_t wcUnicode); + int32_t IsPartName(const WideString& Name1, const WideString& Name2); void MatchFonts(std::vector<CFX_FontDescriptorInfo>* MatchedFonts, uint16_t wCodePage, uint32_t dwFontStyles, - const CFX_WideString& FontName, - FX_WCHAR wcUnicode = 0xFFFE); + const WideString& FontName, + wchar_t wcUnicode = 0xFFFE); int32_t CalcPenalty(CFX_FontDescriptor* pInstalled, uint16_t wCodePage, uint32_t dwFontStyles, - const CFX_WideString& FontName, - FX_WCHAR wcUnicode = 0xFFFE); - CFX_RetainPtr<CFGAS_GEFont> LoadFont(const CFX_WideString& wsFaceName, - int32_t iFaceIndex, - int32_t* pFaceCount); - FXFT_Face LoadFace(const CFX_RetainPtr<IFX_SeekableReadStream>& pFontStream, + const WideString& FontName, + wchar_t wcUnicode = 0xFFFE); + RetainPtr<CFGAS_GEFont> LoadFont(const WideString& wsFaceName, + int32_t iFaceIndex, + int32_t* pFaceCount); + FXFT_Face LoadFace(const RetainPtr<IFX_SeekableReadStream>& pFontStream, int32_t iFaceIndex); - CFX_RetainPtr<IFX_SeekableReadStream> CreateFontStream( + RetainPtr<IFX_SeekableReadStream> CreateFontStream( CFX_FontMapper* pFontMapper, IFX_SystemFontInfo* pSystemFontInfo, uint32_t index); - CFX_RetainPtr<IFX_SeekableReadStream> CreateFontStream( - const CFX_ByteString& bsFaceName); + RetainPtr<IFX_SeekableReadStream> CreateFontStream( + const ByteString& bsFaceName); - CFX_FontSourceEnum_File* const m_pFontSource; + std::unique_ptr<CFX_FontSourceEnum_File> m_pFontSource; std::vector<std::unique_ptr<CFX_FontDescriptor>> m_InstalledFonts; std::map<uint32_t, std::unique_ptr<std::vector<CFX_FontDescriptorInfo>>> m_Hash2CandidateList; - std::map<uint32_t, std::vector<CFX_RetainPtr<CFGAS_GEFont>>> m_Hash2Fonts; - std::map<CFX_RetainPtr<CFGAS_GEFont>, CFX_RetainPtr<IFX_SeekableReadStream>> + std::map<RetainPtr<CFGAS_GEFont>, RetainPtr<IFX_SeekableReadStream>> m_IFXFont2FileRead; - std::set<FX_WCHAR> m_FailedUnicodesSet; + std::set<wchar_t> m_FailedUnicodesSet; +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + + bool VerifyUnicode(const RetainPtr<CFGAS_GEFont>& pFont, wchar_t wcUnicode); + + std::map<uint32_t, std::vector<RetainPtr<CFGAS_GEFont>>> m_Hash2Fonts; }; -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ #endif // XFA_FGAS_FONT_CFGAS_FONTMGR_H_ diff --git a/xfa/fgas/font/cfgas_gefont.cpp b/xfa/fgas/font/cfgas_gefont.cpp index a57962d084bba951e9cc949bf0a1f34879ca194b..83b7ad68d73566df9e9351530adcf62a9172de5d 100644 --- a/xfa/fgas/font/cfgas_gefont.cpp +++ b/xfa/fgas/font/cfgas_gefont.cpp @@ -9,21 +9,20 @@ #include <memory> #include <utility> +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_font.h" #include "core/fxge/cfx_substfont.h" #include "core/fxge/cfx_unicodeencoding.h" #include "core/fxge/cfx_unicodeencodingex.h" #include "third_party/base/ptr_util.h" -#include "xfa/fgas/crt/fgas_codepage.h" #include "xfa/fgas/font/fgas_fontutils.h" -#include "xfa/fxfa/xfa_fontmgr.h" // static -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont( - const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage, - CFGAS_FontMgr* pFontMgr) { -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const wchar_t* pszFontFamily, + uint32_t dwFontStyles, + uint16_t wCodePage, + CFGAS_FontMgr* pFontMgr) { +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ if (!pFontMgr) return nullptr; @@ -37,8 +36,8 @@ CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont( } // static -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont, - CFGAS_FontMgr* pFontMgr) { +RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont, + CFGAS_FontMgr* pFontMgr) { auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr); if (!pFont->LoadFontInternal(pExternalFont)) return nullptr; @@ -46,7 +45,7 @@ CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont, } // static -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont( +RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont( std::unique_ptr<CFX_Font> pInternalFont, CFGAS_FontMgr* pFontMgr) { auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr); @@ -55,66 +54,13 @@ CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont( return pFont; } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -// static -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const uint8_t* pBuffer, - int32_t iLength, - CFGAS_FontMgr* pFontMgr) { - auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr); - if (pFont->LoadFontInternal(pBuffer, iLength)) - return nullptr; - return pFont; -} - -// static -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont( - const CFX_RetainPtr<IFGAS_Stream>& pFontStream, - CFGAS_FontMgr* pFontMgr, - bool bSaveStream) { - auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr); - if (!pFont->LoadFontInternal(pFontStream, bSaveStream)) - return nullptr; - return pFont; -} -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr) : -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - m_bUseLogFontStyle(false), - m_dwLogFontStyle(0), -#endif - m_pFont(nullptr), - m_pFontMgr(pFontMgr), - m_bExternalFont(false), - m_pProvider(nullptr) { -} - -CFGAS_GEFont::CFGAS_GEFont(const CFX_RetainPtr<CFGAS_GEFont>& src, - uint32_t dwFontStyles) - : -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ m_bUseLogFontStyle(false), m_dwLogFontStyle(0), -#endif m_pFont(nullptr), - m_pSrcFont(src), - m_pFontMgr(src->m_pFontMgr), m_bExternalFont(false), - m_pProvider(nullptr) { - ASSERT(m_pSrcFont->m_pFont); - m_pFont = new CFX_Font; - m_pFont->LoadClone(m_pSrcFont->m_pFont); - CFX_SubstFont* pSubst = m_pFont->GetSubstFont(); - if (!pSubst) { - pSubst = new CFX_SubstFont; - m_pFont->SetSubstFont(std::unique_ptr<CFX_SubstFont>(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(); + m_pFontMgr(pFontMgr) { } CFGAS_GEFont::~CFGAS_GEFont() { @@ -122,72 +68,33 @@ CFGAS_GEFont::~CFGAS_GEFont() { delete m_pFont; } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -bool CFGAS_GEFont::LoadFontInternal(const FX_WCHAR* pszFontFamily, +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +bool CFGAS_GEFont::LoadFontInternal(const wchar_t* pszFontFamily, uint32_t dwFontStyles, uint16_t wCodePage) { if (m_pFont) return false; - CFX_ByteString csFontFamily; + ByteString csFontFamily; if (pszFontFamily) - csFontFamily = CFX_ByteString::FromUnicode(pszFontFamily); - uint32_t 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; + csFontFamily = ByteString::FromUnicode(pszFontFamily); + int32_t iWeight = - (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL; + FontStyleIsBold(dwFontStyles) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL; m_pFont = new CFX_Font; - if ((dwFlags & FXFONT_ITALIC) && (dwFlags & FXFONT_BOLD)) + if (FontStyleIsItalic(dwFontStyles) && FontStyleIsBold(dwFontStyles)) csFontFamily += ",BoldItalic"; - else if (dwFlags & FXFONT_BOLD) + else if (FontStyleIsBold(dwFontStyles)) csFontFamily += ",Bold"; - else if (dwFlags & FXFONT_ITALIC) + else if (FontStyleIsItalic(dwFontStyles)) csFontFamily += ",Italic"; - m_pFont->LoadSubst(csFontFamily, true, dwFlags, iWeight, 0, wCodePage, false); - if (!m_pFont->GetFace()) - return false; - return InitFont(); -} - -bool CFGAS_GEFont::LoadFontInternal(const uint8_t* pBuffer, int32_t length) { - if (m_pFont) - return false; - - m_pFont = new CFX_Font; - if (!m_pFont->LoadEmbedded(pBuffer, length)) - return false; - return InitFont(); -} - -bool CFGAS_GEFont::LoadFontInternal( - const CFX_RetainPtr<IFGAS_Stream>& pFontStream, - bool bSaveStream) { - if (m_pFont || m_pFileRead || !pFontStream || pFontStream->GetLength() < 1) - return false; - if (bSaveStream) - m_pStream = pFontStream; - m_pFileRead = pFontStream->MakeSeekableReadStream(); - m_pFont = new CFX_Font; - if (!m_pFont->LoadFile(m_pFileRead)) { - m_pFileRead.Reset(); + m_pFont->LoadSubst(csFontFamily, true, dwFontStyles, iWeight, 0, wCodePage, + false); + if (!m_pFont->GetFace()) return false; - } return InitFont(); } -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ bool CFGAS_GEFont::LoadFontInternal(CFX_Font* pExternalFont) { if (m_pFont || !pExternalFont) @@ -211,121 +118,88 @@ bool CFGAS_GEFont::InitFont() { if (!m_pFont) return false; - if (!m_pFontEncoding) { - m_pFontEncoding.reset(FX_CreateFontEncodingEx(m_pFont)); - if (!m_pFontEncoding) - return false; - } - if (!m_pCharWidthMap) { - m_pCharWidthMap = - pdfium::MakeUnique<CFX_DiscreteArrayTemplate<uint16_t>>(1024); - } - return true; -} + if (m_pFontEncoding) + return true; -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::Derive(uint32_t dwFontStyles, - uint16_t wCodePage) { - CFX_RetainPtr<CFGAS_GEFont> pFont(this); - if (GetFontStyles() == dwFontStyles) - return pFont; - return pdfium::MakeRetain<CFGAS_GEFont>(pFont, dwFontStyles); + m_pFontEncoding = FX_CreateFontEncodingEx(m_pFont, FXFM_ENCODING_NONE); + return !!m_pFontEncoding; } -CFX_WideString CFGAS_GEFont::GetFamilyName() const { +WideString CFGAS_GEFont::GetFamilyName() const { if (!m_pFont->GetSubstFont() || m_pFont->GetSubstFont()->m_Family.GetLength() == 0) { - return CFX_WideString::FromLocal(m_pFont->GetFamilyName().AsStringC()); + return WideString::FromLocal(m_pFont->GetFamilyName().AsStringView()); } - return CFX_WideString::FromLocal( - m_pFont->GetSubstFont()->m_Family.AsStringC()); + return WideString::FromLocal( + m_pFont->GetSubstFont()->m_Family.AsStringView()); } uint32_t CFGAS_GEFont::GetFontStyles() const { ASSERT(m_pFont); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ if (m_bUseLogFontStyle) return m_dwLogFontStyle; -#endif uint32_t dwStyles = 0; auto* pSubstFont = m_pFont->GetSubstFont(); if (pSubstFont) { if (pSubstFont->m_Weight == FXFONT_FW_BOLD) - dwStyles |= FX_FONTSTYLE_Bold; - if (pSubstFont->m_SubstFlags & FXFONT_SUBST_ITALIC) - dwStyles |= FX_FONTSTYLE_Italic; + dwStyles |= FXFONT_BOLD; + if (pSubstFont->m_bFlagItalic) + dwStyles |= FXFONT_ITALIC; } else { if (m_pFont->IsBold()) - dwStyles |= FX_FONTSTYLE_Bold; + dwStyles |= FXFONT_BOLD; if (m_pFont->IsItalic()) - dwStyles |= FX_FONTSTYLE_Italic; + dwStyles |= FXFONT_ITALIC; } return dwStyles; } -bool CFGAS_GEFont::GetCharWidth(FX_WCHAR wUnicode, - int32_t& iWidth, - bool bCharCode) { - return GetCharWidthInternal(wUnicode, iWidth, true, bCharCode); -} - -bool CFGAS_GEFont::GetCharWidthInternal(FX_WCHAR wUnicode, - int32_t& iWidth, - bool bRecursive, - bool bCharCode) { - ASSERT(m_pCharWidthMap); - iWidth = m_pCharWidthMap->GetAt(wUnicode, 0); +bool CFGAS_GEFont::GetCharWidth(wchar_t wUnicode, int32_t& iWidth) { + auto it = m_CharWidthMap.find(wUnicode); + iWidth = it != m_CharWidthMap.end() ? it->second : 0; if (iWidth == 65535) return false; if (iWidth > 0) return true; - if (!m_pProvider || - !m_pProvider->GetCharWidth(CFX_RetainPtr<CFGAS_GEFont>(this), wUnicode, - bCharCode, &iWidth)) { - CFX_RetainPtr<CFGAS_GEFont> pFont; - int32_t iGlyph = GetGlyphIndex(wUnicode, true, &pFont, bCharCode); + if (!m_pProvider || !m_pProvider->GetCharWidth(RetainPtr<CFGAS_GEFont>(this), + wUnicode, &iWidth)) { + RetainPtr<CFGAS_GEFont> pFont; + int32_t iGlyph; + std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true); if (iGlyph != 0xFFFF && pFont) { if (pFont.Get() == this) { iWidth = m_pFont->GetGlyphWidth(iGlyph); if (iWidth < 0) iWidth = -1; - } else if (pFont->GetCharWidthInternal(wUnicode, iWidth, false, - bCharCode)) { + } else if (pFont->GetCharWidth(wUnicode, iWidth)) { return true; } } else { iWidth = -1; } } - m_pCharWidthMap->SetAtGrow(wUnicode, iWidth); + m_CharWidthMap[wUnicode] = iWidth; return iWidth > 0; } -bool CFGAS_GEFont::GetCharBBox(FX_WCHAR wUnicode, - CFX_Rect* bbox, - bool bCharCode) { - return GetCharBBoxInternal(wUnicode, bbox, true, bCharCode); -} - -bool CFGAS_GEFont::GetCharBBoxInternal(FX_WCHAR wUnicode, - CFX_Rect* bbox, - bool bRecursive, - bool bCharCode) { +bool CFGAS_GEFont::GetCharBBox(wchar_t wUnicode, CFX_Rect* bbox) { auto it = m_BBoxMap.find(wUnicode); if (it != m_BBoxMap.end()) { *bbox = it->second; return true; } - CFX_RetainPtr<CFGAS_GEFont> pFont; - int32_t iGlyph = GetGlyphIndex(wUnicode, true, &pFont, bCharCode); + RetainPtr<CFGAS_GEFont> pFont; + int32_t iGlyph; + std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true); if (!pFont || iGlyph == 0xFFFF) return false; if (pFont.Get() != this) - return pFont->GetCharBBoxInternal(wUnicode, bbox, false, bCharCode); + return pFont->GetCharBBox(wUnicode, bbox); FX_RECT rtBBox; if (!m_pFont->GetGlyphBBox(iGlyph, rtBBox)) @@ -349,64 +223,62 @@ bool CFGAS_GEFont::GetBBox(CFX_Rect* bbox) { return true; } -int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, bool bCharCode) { - return GetGlyphIndex(wUnicode, true, nullptr, bCharCode); +int32_t CFGAS_GEFont::GetGlyphIndex(wchar_t wUnicode) { + int32_t glyph; + RetainPtr<CFGAS_GEFont> font; + std::tie(glyph, font) = GetGlyphIndexAndFont(wUnicode, true); + return glyph; } -int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, - bool bRecursive, - CFX_RetainPtr<CFGAS_GEFont>* ppFont, - bool bCharCode) { +std::pair<int32_t, RetainPtr<CFGAS_GEFont>> CFGAS_GEFont::GetGlyphIndexAndFont( + wchar_t wUnicode, + bool bRecursive) { int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode); - if (iGlyphIndex > 0) { - if (ppFont) - ppFont->Reset(this); - return iGlyphIndex; - } + if (iGlyphIndex > 0) + return {iGlyphIndex, RetainPtr<CFGAS_GEFont>(this)}; + const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode); if (!pFontUSB) - return 0xFFFF; + return {0xFFFF, nullptr}; uint16_t wBitField = pFontUSB->wBitField; if (wBitField >= 128) - return 0xFFFF; + return {0xFFFF, nullptr}; auto it = m_FontMapper.find(wUnicode); if (it != m_FontMapper.end() && it->second && it->second.Get() != this) { - iGlyphIndex = - it->second->GetGlyphIndex(wUnicode, false, nullptr, bCharCode); + RetainPtr<CFGAS_GEFont> font; + std::tie(iGlyphIndex, font) = + it->second->GetGlyphIndexAndFont(wUnicode, false); if (iGlyphIndex != 0xFFFF) { for (size_t i = 0; i < m_SubstFonts.size(); ++i) { - if (m_SubstFonts[i] == it->second) { - if (ppFont) - *ppFont = it->second; - return (iGlyphIndex | ((i + 1) << 24)); - } + if (m_SubstFonts[i] == it->second) + return {(iGlyphIndex | ((i + 1) << 24)), it->second}; } } } if (!m_pFontMgr || !bRecursive) - return 0xFFFF; + return {0xFFFF, nullptr}; - CFX_WideString wsFamily = GetFamilyName(); - CFX_RetainPtr<CFGAS_GEFont> pFont = + WideString wsFamily = GetFamilyName(); + RetainPtr<CFGAS_GEFont> pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str()); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ if (!pFont) pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr); #endif if (!pFont || pFont.Get() == this) // Avoids direct cycles below. - return 0xFFFF; + return {0xFFFF, nullptr}; m_FontMapper[wUnicode] = pFont; m_SubstFonts.push_back(pFont); - iGlyphIndex = pFont->GetGlyphIndex(wUnicode, false, nullptr, bCharCode); + + RetainPtr<CFGAS_GEFont> font; + std::tie(iGlyphIndex, font) = pFont->GetGlyphIndexAndFont(wUnicode, false); if (iGlyphIndex == 0xFFFF) - return 0xFFFF; + return {0xFFFF, nullptr}; - if (ppFont) - *ppFont = pFont; - return (iGlyphIndex | (m_SubstFonts.size() << 24)); + return {(iGlyphIndex | (m_SubstFonts.size() << 24)), pFont}; } int32_t CFGAS_GEFont::GetAscent() const { @@ -417,9 +289,9 @@ int32_t CFGAS_GEFont::GetDescent() const { return m_pFont->GetDescent(); } -CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) { +RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) { iGlyphIndex = static_cast<uint32_t>(iGlyphIndex) >> 24; if (iGlyphIndex == 0) - return CFX_RetainPtr<CFGAS_GEFont>(this); + return RetainPtr<CFGAS_GEFont>(this); return m_SubstFonts[iGlyphIndex - 1]; } diff --git a/xfa/fgas/font/cfgas_gefont.h b/xfa/fgas/font/cfgas_gefont.h index 2201721a934577d25e3e0c585a63900f82472751..646562d9eecf82d545d323aeb9250613f48e6006 100644 --- a/xfa/fgas/font/cfgas_gefont.h +++ b/xfa/fgas/font/cfgas_gefont.h @@ -9,110 +9,89 @@ #include <map> #include <memory> +#include <utility> #include <vector> -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_memory.h" -#include "xfa/fgas/crt/fgas_utils.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" #include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_pdffontmgr.h" -#define FXFONT_SUBST_ITALIC 0x02 - -class CFGAS_FontMgr; class CFX_UnicodeEncoding; -class CXFA_PDFFontMgr; -class CFGAS_GEFont : public CFX_Retainable { +class CFGAS_GEFont : public Retainable { public: template <typename T> - friend class CFX_RetainPtr; + friend class RetainPtr; template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - static CFX_RetainPtr<CFGAS_GEFont> LoadFont(const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage, - CFGAS_FontMgr* pFontMgr); - static CFX_RetainPtr<CFGAS_GEFont> LoadFont(CFX_Font* pExternalFont, - CFGAS_FontMgr* pFontMgr); - static CFX_RetainPtr<CFGAS_GEFont> LoadFont( + friend RetainPtr<T> pdfium::MakeRetain(Args&&... args); + + static RetainPtr<CFGAS_GEFont> LoadFont(const wchar_t* pszFontFamily, + uint32_t dwFontStyles, + uint16_t wCodePage, + CFGAS_FontMgr* pFontMgr); + static RetainPtr<CFGAS_GEFont> LoadFont(CFX_Font* pExternalFont, + CFGAS_FontMgr* pFontMgr); + static RetainPtr<CFGAS_GEFont> LoadFont( std::unique_ptr<CFX_Font> pInternalFont, CFGAS_FontMgr* pFontMgr); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - static CFX_RetainPtr<CFGAS_GEFont> LoadFont(const uint8_t* pBuffer, - int32_t iLength, - CFGAS_FontMgr* pFontMgr); - static CFX_RetainPtr<CFGAS_GEFont> LoadFont( - const CFX_RetainPtr<IFGAS_Stream>& pFontStream, - CFGAS_FontMgr* pFontMgr, - bool bSaveStream); -#endif - - CFX_RetainPtr<CFGAS_GEFont> Derive(uint32_t dwFontStyles, - uint16_t wCodePage = 0); + uint32_t GetFontStyles() const; - bool GetCharWidth(FX_WCHAR wUnicode, int32_t& iWidth, bool bCharCode); - int32_t GetGlyphIndex(FX_WCHAR wUnicode, bool bCharCode = false); + bool GetCharWidth(wchar_t wUnicode, int32_t& iWidth); + int32_t GetGlyphIndex(wchar_t wUnicode); int32_t GetAscent() const; int32_t GetDescent() const; - bool GetCharBBox(FX_WCHAR wUnicode, CFX_Rect* bbox, bool bCharCode = false); + + bool GetCharBBox(wchar_t wUnicode, CFX_Rect* bbox); bool GetBBox(CFX_Rect* bbox); - CFX_RetainPtr<CFGAS_GEFont> GetSubstFont(int32_t iGlyphIndex); + + RetainPtr<CFGAS_GEFont> GetSubstFont(int32_t iGlyphIndex); CFX_Font* GetDevFont() const { return m_pFont; } - void SetFontProvider(CXFA_PDFFontMgr* pProvider) { m_pProvider = pProvider; } -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ + + void SetFontProvider(CFGAS_PDFFontMgr* pProvider) { + m_pProvider.Reset(pProvider); + } + void SetLogicalFontStyle(uint32_t dwLogFontStyle) { m_bUseLogFontStyle = true; m_dwLogFontStyle = dwLogFontStyle; } -#endif private: explicit CFGAS_GEFont(CFGAS_FontMgr* pFontMgr); - CFGAS_GEFont(const CFX_RetainPtr<CFGAS_GEFont>& src, uint32_t dwFontStyles); ~CFGAS_GEFont() override; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - bool LoadFontInternal(const FX_WCHAR* pszFontFamily, +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + bool LoadFontInternal(const wchar_t* pszFontFamily, uint32_t dwFontStyles, uint16_t wCodePage); bool LoadFontInternal(const uint8_t* pBuffer, int32_t length); - bool LoadFontInternal(const CFX_RetainPtr<IFGAS_Stream>& pFontStream, + bool LoadFontInternal(const RetainPtr<CFX_SeekableStreamProxy>& pFontStream, bool bSaveStream); -#endif - bool LoadFontInternal(CFX_Font* pExternalFont); +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ bool LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont); + bool LoadFontInternal(CFX_Font* pExternalFont); bool InitFont(); - bool GetCharBBoxInternal(FX_WCHAR wUnicode, - CFX_Rect* bbox, - bool bRecursive, - bool bCharCode = false); - bool GetCharWidthInternal(FX_WCHAR wUnicode, - int32_t& iWidth, - bool bRecursive, - bool bCharCode); - int32_t GetGlyphIndex(FX_WCHAR wUnicode, - bool bRecursive, - CFX_RetainPtr<CFGAS_GEFont>* ppFont, - bool bCharCode = false); - CFX_WideString GetFamilyName() const; - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ + std::pair<int32_t, RetainPtr<CFGAS_GEFont>> GetGlyphIndexAndFont( + wchar_t wUnicode, + bool bRecursive); + WideString GetFamilyName() const; + bool m_bUseLogFontStyle; uint32_t m_dwLogFontStyle; -#endif CFX_Font* m_pFont; - CFX_RetainPtr<CFGAS_GEFont> m_pSrcFont; // Only set by ctor, so no cycles. - CFGAS_FontMgr* const m_pFontMgr; bool m_bExternalFont; - CFX_RetainPtr<IFGAS_Stream> m_pStream; - CFX_RetainPtr<IFX_SeekableReadStream> m_pFileRead; + RetainPtr<CFGAS_GEFont> m_pSrcFont; // Only set by ctor, so no cycles. + CFGAS_FontMgr::ObservedPtr m_pFontMgr; + CFGAS_PDFFontMgr::ObservedPtr m_pProvider; + RetainPtr<CFX_SeekableStreamProxy> m_pStream; + RetainPtr<IFX_SeekableReadStream> m_pFileRead; std::unique_ptr<CFX_UnicodeEncoding> m_pFontEncoding; - std::unique_ptr<CFX_DiscreteArrayTemplate<uint16_t>> m_pCharWidthMap; - std::map<FX_WCHAR, CFX_Rect> m_BBoxMap; - CXFA_PDFFontMgr* m_pProvider; // not owned. - std::vector<CFX_RetainPtr<CFGAS_GEFont>> m_SubstFonts; - std::map<FX_WCHAR, CFX_RetainPtr<CFGAS_GEFont>> m_FontMapper; + std::map<wchar_t, int32_t> m_CharWidthMap; + std::map<wchar_t, CFX_Rect> m_BBoxMap; + std::vector<RetainPtr<CFGAS_GEFont>> m_SubstFonts; + std::map<wchar_t, RetainPtr<CFGAS_GEFont>> m_FontMapper; }; #endif // XFA_FGAS_FONT_CFGAS_GEFONT_H_ diff --git a/xfa/fgas/font/cfgas_pdffontmgr.cpp b/xfa/fgas/font/cfgas_pdffontmgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d34ac828472a5a6df660d587718dd0ff4797e34 --- /dev/null +++ b/xfa/fgas/font/cfgas_pdffontmgr.cpp @@ -0,0 +1,204 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/font/cfgas_pdffontmgr.h" + +#include <algorithm> + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +namespace { + +// The 5 names per entry are: PsName, Normal, Bold, Italic, BoldItalic. +const char* const g_XFAPDFFontName[][5] = { + {"Adobe PI Std", "AdobePIStd", "AdobePIStd", "AdobePIStd", "AdobePIStd"}, + {"Myriad Pro Light", "MyriadPro-Light", "MyriadPro-Semibold", + "MyriadPro-LightIt", "MyriadPro-SemiboldIt"}, +}; + +} // namespace + +CFGAS_PDFFontMgr::CFGAS_PDFFontMgr(CPDF_Document* pDoc, CFGAS_FontMgr* pFontMgr) + : m_pDoc(pDoc), m_pFontMgr(pFontMgr) { + ASSERT(pDoc); + ASSERT(pFontMgr); +} + +CFGAS_PDFFontMgr::~CFGAS_PDFFontMgr() {} + +RetainPtr<CFGAS_GEFont> CFGAS_PDFFontMgr::FindFont(const ByteString& strPsName, + bool bBold, + bool bItalic, + CPDF_Font** pDstPDFFont, + bool bStrictMatch) { + CPDF_Dictionary* pFontSetDict = + m_pDoc->GetRoot()->GetDictFor("AcroForm")->GetDictFor("DR"); + if (!pFontSetDict) + return nullptr; + + pFontSetDict = pFontSetDict->GetDictFor("Font"); + if (!pFontSetDict) + return nullptr; + + ByteString name = strPsName; + name.Remove(' '); + for (const auto& it : *pFontSetDict) { + const ByteString& key = it.first; + CPDF_Object* pObj = it.second.get(); + if (!PsNameMatchDRFontName(name.AsStringView(), bBold, bItalic, key, + bStrictMatch)) { + continue; + } + CPDF_Dictionary* pFontDict = ToDictionary(pObj->GetDirect()); + if (!pFontDict || pFontDict->GetStringFor("Type") != "Font") + return nullptr; + + CPDF_Font* pPDFFont = m_pDoc->LoadFont(pFontDict); + if (!pPDFFont) + return nullptr; + + if (!pPDFFont->IsEmbedded()) { + *pDstPDFFont = pPDFFont; + return nullptr; + } + return CFGAS_GEFont::LoadFont(pPDFFont->GetFont(), m_pFontMgr.Get()); + } + return nullptr; +} + +RetainPtr<CFGAS_GEFont> CFGAS_PDFFontMgr::GetFont( + const WideStringView& wsFontFamily, + uint32_t dwFontStyles, + CPDF_Font** pPDFFont, + bool bStrictMatch) { + uint32_t dwHashCode = FX_HashCode_GetW(wsFontFamily, false); + ByteString strKey = ByteString::Format("%u%u", dwHashCode, dwFontStyles); + auto it = m_FontMap.find(strKey); + if (it != m_FontMap.end()) + return it->second; + + ByteString bsPsName = ByteString::FromUnicode(WideString(wsFontFamily)); + bool bBold = FontStyleIsBold(dwFontStyles); + bool bItalic = FontStyleIsItalic(dwFontStyles); + ByteString strFontName = PsNameToFontName(bsPsName, bBold, bItalic); + RetainPtr<CFGAS_GEFont> pFont = + FindFont(strFontName, bBold, bItalic, pPDFFont, bStrictMatch); + if (pFont) + m_FontMap[strKey] = pFont; + + return pFont; +} + +ByteString CFGAS_PDFFontMgr::PsNameToFontName(const ByteString& strPsName, + bool bBold, + bool bItalic) { + for (size_t i = 0; i < FX_ArraySize(g_XFAPDFFontName); ++i) { + if (strPsName == g_XFAPDFFontName[i][0]) { + size_t index = 1; + if (bBold) + ++index; + if (bItalic) + index += 2; + return g_XFAPDFFontName[i][index]; + } + } + return strPsName; +} + +bool CFGAS_PDFFontMgr::PsNameMatchDRFontName(const ByteStringView& bsPsName, + bool bBold, + bool bItalic, + const ByteString& bsDRFontName, + bool bStrictMatch) { + ByteString bsDRName = bsDRFontName; + bsDRName.Remove('-'); + size_t iPsLen = bsPsName.GetLength(); + auto nIndex = bsDRName.Find(bsPsName); + if (nIndex.has_value() && !bStrictMatch) + return true; + + if (!nIndex.has_value() || nIndex.value() != 0) + return false; + + size_t iDifferLength = bsDRName.GetLength() - iPsLen; + if (iDifferLength > 1 || (bBold || bItalic)) { + auto iBoldIndex = bsDRName.Find("Bold"); + if (bBold != iBoldIndex.has_value()) + return false; + + if (iBoldIndex.has_value()) { + iDifferLength = std::min(iDifferLength - 4, + bsDRName.GetLength() - iBoldIndex.value() - 4); + } + bool bItalicFont = true; + if (bsDRName.Contains("Italic")) + iDifferLength -= 6; + else if (bsDRName.Contains("It")) + iDifferLength -= 2; + else if (bsDRName.Contains("Oblique")) + iDifferLength -= 7; + else + bItalicFont = false; + + if (bItalic != bItalicFont) + return false; + + if (iDifferLength > 1) { + ByteString bsDRTailer = bsDRName.Right(iDifferLength); + if (bsDRTailer == "MT" || bsDRTailer == "PSMT" || + bsDRTailer == "Regular" || bsDRTailer == "Reg") { + return true; + } + if (iBoldIndex.has_value() || bItalicFont) + return false; + + bool bMatch = false; + switch (bsPsName[iPsLen - 1]) { + case 'L': + if (bsDRName.Right(5) == "Light") + bMatch = true; + + break; + case 'R': + if (bsDRName.Right(7) == "Regular" || bsDRName.Right(3) == "Reg") + bMatch = true; + + break; + case 'M': + if (bsDRName.Right(5) == "Medium") + bMatch = true; + break; + default: + break; + } + return bMatch; + } + } + return true; +} + +bool CFGAS_PDFFontMgr::GetCharWidth(const RetainPtr<CFGAS_GEFont>& pFont, + wchar_t wUnicode, + int32_t* pWidth) { + if (wUnicode != 0x20) + return false; + + auto it = m_FDE2PDFFont.find(pFont); + if (it == m_FDE2PDFFont.end()) + return false; + + CPDF_Font* pPDFFont = it->second; + *pWidth = pPDFFont->GetCharWidthF(pPDFFont->CharCodeFromUnicode(wUnicode)); + return true; +} + +void CFGAS_PDFFontMgr::SetFont(const RetainPtr<CFGAS_GEFont>& pFont, + CPDF_Font* pPDFFont) { + m_FDE2PDFFont[pFont] = pPDFFont; +} diff --git a/xfa/fgas/font/cfgas_pdffontmgr.h b/xfa/fgas/font/cfgas_pdffontmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..a019990dad1daf68507b2de4a56b50c355abd151 --- /dev/null +++ b/xfa/fgas/font/cfgas_pdffontmgr.h @@ -0,0 +1,58 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_FONT_CFGAS_PDFFONTMGR_H_ +#define XFA_FGAS_FONT_CFGAS_PDFFONTMGR_H_ + +#include <map> + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/observable.h" +#include "core/fxcrt/retain_ptr.h" + +class CFGAS_FontMgr; +class CFGAS_GEFont; +class CPDF_Document; +class CPDF_Font; + +class CFGAS_PDFFontMgr : public Observable<CFGAS_PDFFontMgr> { + public: + explicit CFGAS_PDFFontMgr(CPDF_Document* pDoc, CFGAS_FontMgr* pFontMgr); + ~CFGAS_PDFFontMgr(); + + void SetFont(const RetainPtr<CFGAS_GEFont>& pFont, CPDF_Font* pPDFFont); + RetainPtr<CFGAS_GEFont> GetFont(const WideStringView& wsFontFamily, + uint32_t dwFontStyles, + CPDF_Font** pPDFFont, + bool bStrictMatch); + bool GetCharWidth(const RetainPtr<CFGAS_GEFont>& pFont, + wchar_t wUnicode, + int32_t* pWidth); + + private: + RetainPtr<CFGAS_GEFont> FindFont(const ByteString& strFamilyName, + bool bBold, + bool bItalic, + CPDF_Font** pPDFFont, + bool bStrictMatch); + ByteString PsNameToFontName(const ByteString& strPsName, + bool bBold, + bool bItalic); + bool PsNameMatchDRFontName(const ByteStringView& bsPsName, + bool bBold, + bool bItalic, + const ByteString& bsDRFontName, + bool bStrictMatch); + + UnownedPtr<CPDF_Document> const m_pDoc; + UnownedPtr<CFGAS_FontMgr> const m_pFontMgr; + std::map<RetainPtr<CFGAS_GEFont>, CPDF_Font*> m_FDE2PDFFont; + std::map<ByteString, RetainPtr<CFGAS_GEFont>> m_FontMap; +}; + +#endif // XFA_FGAS_FONT_CFGAS_PDFFONTMGR_H_ diff --git a/xfa/fgas/font/fgas_fontutils.cpp b/xfa/fgas/font/fgas_fontutils.cpp index e74056b53ed7435c07235fecdb96ce3244aa721b..2cf56ce7ca661bc842c526ce8d7a33ebfd9cada2 100644 --- a/xfa/fgas/font/fgas_fontutils.cpp +++ b/xfa/fgas/font/fgas_fontutils.cpp @@ -6,148 +6,1912 @@ #include "xfa/fgas/font/fgas_fontutils.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" #include "xfa/fgas/font/cfgas_fontmgr.h" -uint32_t FGAS_GetFontHashCode(uint16_t wCodePage, uint32_t dwFontStyles) { - uint32_t 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; -} -uint32_t FGAS_GetFontFamilyHash(const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t 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_GetW(wsFont.AsStringC(), false); -} -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}, +namespace { + +const FGAS_FONTUSB g_FXGdiFontUSBTable[] = { + {0x0000, 0x007F, 0, FX_CODEPAGE_MSWin_WesternEuropean}, + {0x0080, 0x00FF, 1, FX_CODEPAGE_MSWin_WesternEuropean}, + {0x0100, 0x017F, 2, FX_CODEPAGE_MSWin_EasternEuropean}, + {0x0180, 0x024F, 3, FX_CODEPAGE_MSWin_EasternEuropean}, + {0x0250, 0x02AF, 4, 0xFFFF}, + {0x02B0, 0x02FF, 5, 0xFFFF}, + {0x0300, 0x036F, 6, 0xFFFF}, + {0x0370, 0x03FF, 7, FX_CODEPAGE_MSWin_Greek}, + {0x0400, 0x04FF, 9, FX_CODEPAGE_MSWin_Cyrillic}, + {0x0500, 0x052F, 9, 0xFFFF}, + {0x0530, 0x058F, 10, 0xFFFF}, + {0x0590, 0x05FF, 11, FX_CODEPAGE_MSWin_Hebrew}, + {0x0600, 0x06FF, 13, FX_CODEPAGE_MSWin_Arabic}, + {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, FX_CODEPAGE_MSDOS_Thai}, + {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, FX_CODEPAGE_ChineseSimplified}, + {0x216C, 0x216F, 36, 0xFFFF}, + {0x2170, 0x2179, 36, FX_CODEPAGE_ChineseSimplified}, + {0x217A, 0x218F, 36, 0xFFFF}, + {0x2190, 0x2199, 37, FX_CODEPAGE_Hangul}, + {0x219A, 0x21FF, 37, 0xFFFF}, + {0x2200, 0x22FF, 38, 0xFFFF}, + {0x2300, 0x23FF, 39, 0xFFFF}, + {0x2400, 0x243F, 40, 0xFFFF}, + {0x2440, 0x245F, 41, 0xFFFF}, + {0x2460, 0x2473, 42, FX_CODEPAGE_ShiftJIS}, + {0x2474, 0x249B, 42, FX_CODEPAGE_ChineseSimplified}, + {0x249C, 0x24E9, 42, FX_CODEPAGE_Hangul}, + {0x24EA, 0x24FF, 42, 0xFFFF}, + {0x2500, 0x2573, 43, FX_CODEPAGE_ChineseSimplified}, + {0x2574, 0x257F, 43, 0xFFFF}, + {0x2580, 0x2580, 44, 0xFFFF}, + {0x2581, 0x258F, 44, FX_CODEPAGE_ChineseSimplified}, + {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, FX_CODEPAGE_ShiftJIS}, + {0x30A0, 0x30FF, 50, FX_CODEPAGE_ShiftJIS}, + {0x3100, 0x3129, 51, FX_CODEPAGE_ChineseSimplified}, + {0x312A, 0x312F, 51, 0xFFFF}, + {0x3130, 0x318F, 52, FX_CODEPAGE_Hangul}, + {0x3190, 0x319F, 59, 0xFFFF}, + {0x31A0, 0x31BF, 51, 0xFFFF}, + {0x31C0, 0x31EF, 61, 0xFFFF}, + {0x31F0, 0x31FF, 50, 0xFFFF}, + {0x3200, 0x321C, 54, FX_CODEPAGE_Hangul}, + {0x321D, 0x325F, 54, 0xFFFF}, + {0x3260, 0x327F, 54, FX_CODEPAGE_Hangul}, + {0x3280, 0x32FF, 54, 0xFFFF}, + {0x3300, 0x3387, 55, 0xFFFF}, + {0x3388, 0x33D0, 55, FX_CODEPAGE_Hangul}, + {0x33D1, 0x33FF, 55, 0xFFFF}, + {0x3400, 0x4DBF, 59, 0xFFFF}, + {0x4DC0, 0x4DFF, 99, 0xFFFF}, + {0x4E00, 0x9FA5, 59, FX_CODEPAGE_ChineseSimplified}, + {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, FX_CODEPAGE_Hangul}, + {0xD7B0, 0xD7FF, 999, 0xFFFF}, + {0xD800, 0xDB7F, 57, 0xFFFF}, + {0xDB80, 0xDBFF, 57, 0xFFFF}, + {0xDC00, 0xDFFF, 57, 0xFFFF}, + {0xE000, 0xE814, 60, 0xFFFF}, + {0xE815, 0xE864, 60, FX_CODEPAGE_ChineseSimplified}, + {0xE865, 0xF8FF, 60, 0xFFFF}, + {0xF900, 0xFA0B, 61, FX_CODEPAGE_Hangul}, + {0xFA0C, 0xFA0D, 61, FX_CODEPAGE_ChineseSimplified}, + {0xFA0E, 0xFA2D, 61, FX_CODEPAGE_ShiftJIS}, + {0xFA2E, 0xFAFF, 61, 0xFFFF}, + {0xFB00, 0xFB4F, 62, 0xFFFF}, + {0xFB50, 0xFDFF, 63, FX_CODEPAGE_MSWin_Arabic}, + {0xFE00, 0xFE0F, 91, 0xFFFF}, + {0xFE10, 0xFE1F, 65, 0xFFFF}, + {0xFE20, 0xFE2F, 64, 0xFFFF}, + {0xFE30, 0xFE4F, 65, 0xFFFF}, + {0xFE50, 0xFE6F, 66, 0xFFFF}, + {0xFE70, 0xFEFF, 67, FX_CODEPAGE_MSWin_Arabic}, + {0xFF00, 0xFF5F, 68, FX_CODEPAGE_ChineseSimplified}, + {0xFF60, 0xFF9F, 68, FX_CODEPAGE_ShiftJIS}, {0xFFA0, 0xFFEF, 68, 0xFFFF}, }; -const FGAS_FONTUSB* FGAS_GetUnicodeBitField(FX_WCHAR wUnicode) { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ +const FGAS_FontInfo g_XFAFontsMap[] = { + {0x01d5d33e, L"SimSun", L"Arial", 0, 936}, + {0x01e4f102, L"YouYuan", L"Arial", 1, 936}, + {0x030549dc, L"LiSu", L"Arial", 1, 936}, + {0x032edd44, L"Simhei", L"Arial", 1, 936}, + {0x03eac6fc, L"PoorRichard-Regular", L"Arial", 2, 1252}, + {0x03ed90e6, L"Nina", L"Arial", 0, 1252}, + {0x077b56b3, L"KingsoftPhoneticPlain", L"Arial", 0, 1252}, + {0x078ed524, L"MicrosoftSansSerif", L"Arial", 0, 1252}, + {0x089b18a9, L"Arial", L"Arial", 0, 1252}, + {0x0b2cad72, L"MonotypeCorsiva", L"Arial", 8, 1252}, + {0x0bb003e7, L"Kartika", L"Arial", 2, 1252}, + {0x0bb469df, L"VinerHandITC", L"Arial", 8, 1252}, + {0x0bc1a851, L"SegoeUI", L"Arial", 0, 1252}, + {0x0c112ebd, L"KozukaGothicPro-VIM", L"Arial", 0, 1252}, + {0x0cfcb9c1, L"AdobeThai", L"Kokila,Arial Narrow", 0, 847}, + {0x0e7de0f9, L"Playbill", L"Arial", 0, 1252}, + {0x0eff47c3, L"STHupo", L"Arial", 0, 936}, + {0x107ad374, L"Constantia", L"Arial", 2, 1252}, + {0x12194c2d, L"KunstlerScript", L"Arial", 8, 1252}, + {0x135ef6a1, L"MinionProSmBd", + L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252}, + {0x158c4049, L"Garamond", L"Arial", 2, 1252}, + {0x160ecb24, L"STZhongsong", L"Arial", 0, 936}, + {0x161ed07e, L"MSGothic", L"Arial", 1, 1252}, + {0x171d1ed1, L"SnapITC-Regular", L"Arial", 0, 1252}, + {0x18d1188f, L"Cambria", L"Arial", 2, 1252}, + {0x18eaf350, L"ArialUnicodeMS", L"Arial", 0, 936}, + {0x1a92d115, L"MingLiU", L"Arial", 1, 1252}, + {0x1cc217c6, L"TrebuchetMS", L"Arial", 0, 1252}, + {0x1d649596, L"BasemicTimes", L"Arial", 0, 1252}, + {0x1e34ee60, L"BellMT", L"Arial", 2, 1252}, + {0x1eb36945, L"CooperBlack", L"Arial", 2, 1252}, + {0x1ef7787d, L"BatangChe", L"Arial", 1, 1252}, + {0x20b3bd3a, L"BrushScriptMT", L"Arial", 8, 1252}, + {0x220877aa, L"Candara", L"Arial", 0, 1252}, + {0x22135007, L"FreestyleScript-Regular", L"Arial", 8, 1252}, + {0x251059c3, L"Chiller", L"Arial", 0, 1252}, + {0x25bed6dd, L"MSReferenceSansSerif", L"Arial", 0, 1252}, + {0x28154c81, L"Parchment-Regular", L"Arial", 8, 1252}, + {0x29711eb9, L"STLiti", L"Arial", 0, 936}, + {0x2b1993b4, L"Basemic", L"Arial", 0, 1252}, + {0x2b316339, L"NiagaraSolid-Reg", L"Arial", 0, 1252}, + {0x2c147529, L"FootlightMTLight", L"Arial", 0, 1252}, + {0x2c198928, L"HarlowSolid", L"Arial", 0, 1252}, + {0x2c6ac6b2, L"LucidaBright", L"Arial", 2, 1252}, + {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"Arial", 0, 1252}, + {0x2d5a47b0, L"STCaiyun", L"Arial", 0, 936}, + {0x2def26bf, L"BernardMT-Condensed", L"Arial", 0, 1252}, + {0x2fd8930b, L"KozukaMinchoPr6NR", L"Arial", 0, 1252}, + {0x3115525a, L"FangSong_GB2312", L"Arial", 0, 1252}, + {0x31327817, L"MyriadPro", + L"Calibri,Corbel,Candara,Cambria Math,Franklin Gothic Medium,Arial " + L"Narrow,Times New Roman", + 0, 1252}, + {0x32244975, L"Helvetica", L"Arial", 0, 1252}, + {0x32ac995c, L"Terminal", L"Arial", 0, 1252}, + {0x338d648a, L"NiagaraEngraved-Reg", L"Arial", 0, 1252}, + {0x33bb65f2, L"Sylfaen", L"Arial", 2, 1252}, + {0x3402c30e, L"MSPMincho", L"Arial", 2, 1252}, + {0x3412bf31, L"SimSun-PUA", L"Arial", 0, 936}, + {0x36eb39b9, L"BerlinSansFB", L"Arial", 0, 1252}, + {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, + {0x3864c4f6, L"HighTowerText", L"Arial", 2, 1252}, + {0x3a257d03, L"FangSong_GB2312", L"Arial", 0, 1252}, + {0x3cdae668, L"FreestyleScript", L"Arial", 8, 1252}, + {0x3d55aed7, L"Jokerman", L"Arial", 0, 1252}, + {0x3d5b4385, L"PMingLiU", L"Arial", 2, 1252}, + {0x3d9b7669, L"EstrangeloEdessa", L"Arial", 0, 1252}, + {0x3e532d74, L"FranklinGothicMedium", L"Arial", 0, 1252}, + {0x3e6aa32d, L"NSimSun", L"Arial", 1, 936}, + {0x3f6c36a8, L"Gautami", L"Arial", 0, 1252}, + {0x3ff32662, L"Chiller-Regular", L"Arial", 0, 1252}, + {0x409de312, L"ModernNo.20", L"Arial", 2, 1252}, + {0x41443c5e, L"Georgia", L"Arial", 2, 1252}, + {0x4160ade5, L"BellGothicStdBlack", + L"Arial,Arial Unicode MS,Book Antiqua,Dotum,Georgia", 0, 1252}, + {0x421976c4, L"Modern-Regular", L"Arial", 2, 1252}, + {0x422a7252, L"Stencil", L"Arial", 0, 1252}, + {0x42c8554f, L"Fixedsys", L"Arial", 0, 1252}, + {0x435cb41d, L"Roman", L"Arial", 0, 1252}, + {0x47882383, L"CourierNew", L"Arial", 1, 1252}, + {0x480a2338, L"BerlinSansFBDemi", L"Arial", 0, 1252}, + {0x480bf7a4, L"CourierStd", L"Courier New,Verdana", 0, 1252}, + {0x481ad6ed, L"VladimirScript", L"Arial", 8, 1252}, + {0x4911577a, L"YouYuan", L"Arial", 1, 936}, + {0x4a788d72, L"STXingkai", L"Arial", 0, 936}, + {0x4bf88566, L"SegoeCondensed", L"Arial", 0, 1252}, + {0x4ccf51a4, L"BerlinSansFB-Reg", L"Arial", 0, 1252}, + {0x4ea967ce, L"GulimChe", L"Arial", 1, 1252}, + {0x4f68bd79, L"LetterGothicStd", L"Courier New,Verdana", 0, 1252}, + {0x51a0d0e6, L"KozukaGothicPr6NM", L"Arial", 0, 1252}, + {0x531b3dea, L"BasemicSymbol", L"Arial", 0, 1252}, + {0x5333fd39, L"CalifornianFB-Reg", L"Arial", 2, 1252}, + {0x53561a54, L"FZYTK--GBK1-0", L"Arial", 0, 936}, + {0x55e0dde6, L"LucidaSansTypewriter", L"Arial", 0, 1252}, + {0x574d4d3d, L"AdobeArabic", L"Arial Narrow", 0, 1252}, + {0x5792e759, L"STKaiti", L"Arial", 0, 936}, + {0x5921978e, L"LucidaSansUnicode", L"Arial", 0, 1252}, + {0x594e2da4, L"Vrinda", L"Arial", 0, 1252}, + {0x59baa9a2, L"KaiTi_GB2312", L"Arial", 0, 1252}, + {0x5cfedf4f, L"BaskOldFace", L"Arial", 0, 1252}, + {0x5f97921c, L"AdobeMyungjoStdM", + L"Batang,Bookman Old Style,Consolas,STZhongsong", 0, 936}, + {0x5fefbfad, L"Batang", L"Arial", 2, 1252}, + {0x605342b9, L"DotumChe", L"Arial", 1, 1252}, + {0x608c5f9a, L"KaiTi_GB2312", L"Arial", 0, 936}, + {0x61efd0d1, L"MaturaMTScriptCapitals", L"Arial", 0, 1252}, + {0x626608a9, L"MVBoli", L"Arial", 0, 1252}, + {0x630501a3, L"SmallFonts", L"Arial", 0, 1252}, + {0x65d0e2a9, L"FZYTK--GBK1-0", L"Arial", 0, 936}, + {0x669f29e1, L"FZSTK--GBK1-0", L"Arial", 0, 936}, + {0x673a9e5f, L"Tunga", L"Arial", 0, 1252}, + {0x691aa4ce, L"NiagaraSolid", L"Arial", 0, 1252}, + {0x696259b7, L"Corbel", L"Arial", 0, 1252}, + {0x696ee9be, L"STXihei", L"Arial", 0, 936}, + {0x6c59cf69, L"Dotum", L"Arial", 0, 1252}, + {0x707fa561, L"Gungsuh", L"Arial", 2, 1252}, + {0x71416bb2, L"ZWAdobeF", L"Arial", 0, 1252}, + {0x71b41801, L"Verdana", L"Arial", 0, 1252}, + {0x73f25e4c, L"PalatinoLinotype", L"Arial", 0, 1252}, + {0x73f4d19f, L"NiagaraEngraved", L"Arial", 0, 1252}, + {0x74001694, L"MyriadProBlack", L"Book Antiqua,Constantia,Dotum,Georgia", 0, + 1252}, + {0x74b14d8f, L"Haettenschweiler", L"Arial", 0, 1252}, + {0x74cb44ee, L"NSimSun", L"Arial", 1, 936}, + {0x76b4d7ff, L"Shruti", L"Arial", 0, 1252}, + {0x788b3533, L"Webdings", L"Arial", 6, 42}, + {0x797dde99, L"MSSerif", L"Arial", 0, 1252}, + {0x7a0f9e9e, L"MSMincho", L"Arial", 1, 1252}, + {0x7b439caf, L"OldEnglishTextMT", L"Arial", 0, 1252}, + {0x8213a433, L"LucidaSans-Typewriter", L"Arial", 0, 1252}, + {0x82fec929, L"AdobeSongStdL", + L"Centaur,Calibri,STSong,Bell MT,Garamond,Times New Roman", 0, 936}, + {0x83581825, L"Modern", L"Arial", 0, 1252}, + {0x835a2823, L"Algerian", L"Arial", 0, 1252}, + {0x83dab9f5, L"Script", L"Arial", 0, 1252}, + {0x847b56da, L"Tahoma", L"Arial", 0, 1252}, + {0x8a783cb2, L"SimSun-PUA", L"Arial", 0, 1252}, + {0x8b5cac0e, L"Onyx", L"Arial", 0, 1252}, + {0x8c6a499e, L"Gulim", L"Arial", 0, 1252}, + {0x8e0af790, L"JuiceITC", L"Arial", 0, 1252}, + {0x8e8d43b2, L"Centaur", L"Arial", 2, 1252}, + {0x8ee4dcca, L"BookshelfSymbol7", L"Arial", 0, 1252}, + {0x90794800, L"BellGothicStdLight", L"Bell MT,Calibri,Times New Roman", 0, + 1252}, + {0x909b516a, L"Century", L"Arial", 2, 1252}, + {0x92ae370d, L"MSOutlook", L"Arial", 4, 42}, + {0x93c9fbf1, L"LucidaFax", L"Arial", 2, 1252}, + {0x9565085e, L"BookAntiqua", L"Arial", 2, 1252}, + {0x9856d95d, L"AdobeMingStdL", L"Arial,Arial Unicode MS,Cambria,BatangChe", + 0, 949}, + {0x9bbadd6b, L"ColonnaMT", L"Arial", 0, 1252}, + {0x9cbd16a4, L"ShowcardGothic-Reg", L"Arial", 0, 1252}, + {0x9d73008e, L"MSSansSerif", L"Arial", 0, 1252}, + {0xa0607db1, L"GungsuhChe", L"Arial", 1, 1252}, + {0xa0bcf6a1, L"LatinWide", L"Arial", 2, 1252}, + {0xa1429b36, L"Symbol", L"Arial", 6, 42}, + {0xa1fa5abc, L"Wingdings2", L"Arial", 6, 42}, + {0xa1fa5abd, L"Wingdings3", L"Arial", 6, 42}, + {0xa427bad4, L"InformalRoman-Regular", L"Arial", 8, 1252}, + {0xa8b92ece, L"FZSTK--GBK1-0", L"Arial", 0, 936}, + {0xa8d83ece, L"CalifornianFB", L"Arial", 2, 1252}, + {0xaa3e082c, L"Kingsoft-Phonetic", L"Arial", 0, 1252}, + {0xaa6bcabe, L"HarlowSolidItalic", L"Arial", 0, 1252}, + {0xade5337c, L"MSUIGothic", L"Arial", 0, 1252}, + {0xb08dd941, L"WideLatin", L"Arial", 2, 1252}, + {0xb207f05d, L"PoorRichard", L"Arial", 2, 1252}, + {0xb3bc492f, L"JuiceITC-Regular", L"Arial", 0, 1252}, + {0xb5545399, L"Marlett", L"Arial", 4, 42}, + {0xb5dd1ebb, L"BritannicBold", L"Arial", 0, 1252}, + {0xb699c1c5, L"LucidaCalligraphy-Italic", L"Arial", 0, 1252}, + {0xb725d629, L"TimesNewRoman", L"Arial", 2, 1252}, + {0xb7eaebeb, L"AdobeHeitiStdR", L"Batang,Century,Dotum", 0, 936}, + {0xbd29c486, L"BerlinSansFBDemi-Bold", L"Arial", 0, 1252}, + {0xbe8a8db4, L"BookshelfSymbolSeven", L"Arial", 0, 1252}, + {0xc16c0118, L"AdobeHebrew", L"Bell MT,Berlin Sans FB,Calibri", 0, 1252}, + {0xc318b0af, L"MyriadProLight", L"Calibri,STFangsong,Times New Roman", 0, + 1252}, + {0xc65e5659, L"CambriaMath", L"Arial", 2, 1252}, + {0xc75c8f05, L"LucidaConsole", L"Arial", 1, 1252}, + {0xca7c35d6, L"Calibri", L"Arial", 0, 1252}, + {0xcb053f53, L"MicrosoftYaHei", L"Arial", 0, 936}, + {0xcb7190f9, L"Magneto-Bold", L"Arial", 0, 1252}, + {0xcca00cc5, L"System", L"Arial", 0, 1252}, + {0xccad6f76, L"Jokerman-Regular", L"Arial", 0, 1252}, + {0xccc5818c, L"EuroSign", L"Arial", 0, 1252}, + {0xcf3d7234, L"LucidaHandwriting-Italic", L"Arial", 0, 1252}, + {0xcf7b8fdb, L"MinionPro", + L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252}, + {0xcfe5755f, L"Simhei", L"Arial", 1, 936}, + {0xd011f4ee, L"MSPGothic", L"Arial", 0, 1252}, + {0xd060e7ef, L"Vivaldi", L"Arial", 8, 1252}, + {0xd07edec1, L"FranklinGothic-Medium", L"Arial", 0, 1252}, + {0xd107243f, L"SimSun", L"Arial", 0, 936}, + {0xd1881562, L"ArialNarrow", L"Arial Narrow", 0, 1252}, + {0xd22b7dce, L"BodoniMTPosterCompressed", L"Arial", 0, 1252}, + {0xd22bfa60, L"ComicSansMS", L"Arial", 8, 1252}, + {0xd3bd0e35, L"Bauhaus93", L"Arial", 0, 1252}, + {0xd429ee7a, L"STFangsong", L"Arial", 0, 936}, + {0xd6679c12, L"BernardMTCondensed", L"Arial", 0, 1252}, + {0xd8e8a027, L"LucidaSans", L"Arial", 0, 1252}, + {0xd9fe7761, L"HighTowerText-Reg", L"Arial", 2, 1252}, + {0xda7e551e, L"STSong", L"Arial", 0, 936}, + {0xdaa6842d, L"STZhongsong", L"Arial", 0, 936}, + {0xdaaab93f, L"STFangsong", L"Arial", 0, 936}, + {0xdaeb0713, L"STSong", L"Arial", 0, 936}, + {0xdafedbef, L"STCaiyun", L"Arial", 0, 936}, + {0xdb00a3d9, L"Broadway", L"Arial", 0, 1252}, + {0xdb1f5ad4, L"STXinwei", L"Arial", 0, 936}, + {0xdb326e7f, L"STKaiti", L"Arial", 0, 936}, + {0xdb69595a, L"STHupo", L"Arial", 0, 936}, + {0xdba0082c, L"STXihei", L"Arial", 0, 936}, + {0xdbd0ab18, L"STXingkai", L"Arial", 0, 936}, + {0xdc1a7db1, L"STLiti", L"Arial", 0, 936}, + {0xdc33075f, L"KristenITC-Regular", L"Arial", 8, 1252}, + {0xdcc7009c, L"Harrington", L"Arial", 0, 1252}, + {0xdd712466, L"ArialBlack", L"Arial", 0, 1252}, + {0xdde87b3e, L"Impact", L"Arial", 0, 1252}, + {0xdf69fb32, L"SnapITC", L"Arial", 0, 1252}, + {0xdf8b25e8, L"CenturyGothic", L"Arial", 0, 1252}, + {0xe0f705c0, L"KristenITC", L"Arial", 8, 1252}, + {0xe1427573, L"Raavi", L"Arial", 0, 1252}, + {0xe2cea0cb, L"Magneto", L"Arial", 0, 1252}, + {0xe36a9e17, L"Ravie", L"Arial", 0, 1252}, + {0xe433f8e2, L"Parchment", L"Arial", 8, 1252}, + {0xe43dff4a, L"Wingdings", L"Arial", 4, 42}, + {0xe4e2c405, L"MTExtra", L"Arial", 6, 42}, + {0xe618cc35, L"InformalRoman", L"Arial", 8, 1252}, + {0xe6c27ffc, L"Mistral", L"Arial", 8, 1252}, + {0xe7ebf4b9, L"Courier", L"Courier New", 0, 1252}, + {0xe8bc4a9d, L"MSReferenceSpecialty", L"Arial", 0, 1252}, + {0xe90fb013, L"TempusSansITC", L"Arial", 0, 1252}, + {0xec637b42, L"Consolas", L"Verdana", 1, 1252}, + {0xed3a683b, L"STXinwei", L"Arial", 0, 936}, + {0xef264cd1, L"LucidaHandwriting", L"Arial", 0, 1252}, + {0xf086bca2, L"BaskervilleOldFace", L"Arial", 0, 1252}, + {0xf1028030, L"Mangal", L"Arial", 2, 1252}, + {0xf1da7eb9, L"ShowcardGothic", L"Arial", 0, 1252}, + {0xf210f06a, L"ArialMT", L"Arial", 0, 1252}, + {0xf477f16a, L"Latha", L"Arial", 0, 1252}, + {0xf616f3dd, L"LiSu", L"Arial", 1, 936}, + {0xfa479aa6, L"MicrosoftYaHei", L"Arial", 0, 936}, + {0xfcd19697, L"BookmanOldStyle", L"Arial", 0, 1252}, + {0xfe209a82, L"LucidaCalligraphy", L"Arial", 0, 1252}, + {0xfef135f8, L"AdobeHeitiStd-Regular", L"Batang,Century,Dotum", 0, 936}, +}; +#elif _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ +const FGAS_FontInfo g_XFAFontsMap[] = { + {0x01d5d33e, L"SimSun", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " + L"PL UMing TW MBE", + 0, 936}, + {0x01e4f102, L"YouYuan", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " + L"PL UMing TW MBE", + 1, 936}, + {0x030549dc, L"LiSu", + L"WenQuanYi Zen Hei,WenQuanYi Zen Hei Sharp,WenQuanYi Zen Hei " + L"Mono,WenQuanYi Micro Hei", + 1, 936}, + {0x032edd44, L"Simhei", + L"WenQuanYi Zen Hei,WenQuanYi Zen Hei Sharp,WenQuanYi Zen Hei " + L"Mono,WenQuanYi Micro Hei", + 1, 936}, + {0x03eac6fc, L"PoorRichard-Regular", L"Droid Sans Japanese,FreeSerif", 2, + 1252}, + {0x03ed90e6, L"Nina", L"FreeSerif", 0, 1252}, + {0x077b56b3, L"KingsoftPhoneticPlain", + L"Tibetan Machine Uni,LKLUG,Samyak Gujarati,Droid Sans Thai,Droid Sans " + L"Armenian,Untitled1,utkal,Lohit Oriya", + 0, 1252}, + {0x078ed524, L"MicrosoftSansSerif", + L"Droid Sans Japanese,FreeSerif,WenQuanYi Micro Hei", 0, 1252}, + {0x089b18a9, L"Arial", + L"Droid Sans Japanese,DejaVu Sans Condensed,FreeSerif,WenQuanYi Micro Hei", + 0, 1252}, + {0x0b2cad72, L"MonotypeCorsiva", L"Droid Sans Japanese,FreeSerif", 8, 1252}, + {0x0bb003e7, L"Kartika", + L"FreeSans,Liberation Sans,Liberation Sans Narrow,Nimbus Sans " + L"L,Garuda,FreeSerif,WenQuanYi Micro Hei", + 2, 1252}, + {0x0bb469df, L"VinerHandITC", + L"Droid Sans Japanese,Ubuntu,Liberation Sans,Liberation Serif", 8, 1252}, + {0x0bc1a851, L"SegoeUI", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, + {0x0c112ebd, L"KozukaGothicPro-VIM", L"FreeSerif", 0, 1252}, + {0x0cfcb9c1, L"AdobeThai", L"Droid Sans Japanese,Waree", 0, 847}, + {0x0e7de0f9, L"Playbill", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " + L"Sans Ethiopic,Droid Sans Japanese,FreeSerif", + 0, 1252}, + {0x0eff47c3, L"STHupo", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0x107ad374, L"Constantia", + L"Droid Sans Japanese,FreeSerif,WenQuanYi Micro Hei,Ubuntu", 2, 1252}, + {0x12194c2d, L"KunstlerScript", L"Droid Sans Japanese,Liberation Serif", 8, + 1252}, + {0x135ef6a1, L"MinionProSmBd", L"Liberation Serif", 0, 1252}, + {0x158c4049, L"Garamond", + L"Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 2, 1252}, + {0x160ecb24, L"STZhongsong", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x161ed07e, L"MSGothic", + L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,AR PL " + L"UMing CN,AR PL UMing HK,AR PL UMing TW", + 1, 1252}, + {0x171d1ed1, L"SnapITC-Regular", + L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans L,DejaVu Sans", 0, + 1252}, + {0x18d1188f, L"Cambria", L"Droid Sans Japanese,FreeSerif,FreeMono", 2, + 1252}, + {0x18eaf350, L"ArialUnicodeMS", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x1a92d115, L"MingLiU", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 1, 1252}, + {0x1cc217c6, L"TrebuchetMS", + L"Droid Sans Japanese,Liberation Serif,FreeSerif,Ubuntu", 0, 1252}, + {0x1d649596, L"BasemicTimes", + L"Liberation Serif,Times New Roman,Droid Sans Japanese,FreeSerif,Ubuntu", + 0, 1252}, + {0x1e34ee60, L"BellMT", + L"KacstQurn,Droid Sans Japanese,Ubuntu,Liberation Serif", 2, 1252}, + {0x1eb36945, L"CooperBlack", + L"KacstQurn,Droid Sans Japanese,FreeMono,Liberation Mono, WenQuanYi Micro " + L"Hei Mono", + 2, 1252}, + {0x1ef7787d, L"BatangChe", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing " + L"TW,WenQuanYi Zen Hei,WenQuanYi Micro Hei", + 1, 1252}, + {0x20b3bd3a, L"BrushScriptMT", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans " + L"Japanese,URW Chancery L,Liberation Sans", + 8, 1252}, + {0x220877aa, L"Candara", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, + {0x22135007, L"FreestyleScript-Regular", + L"KacstQurn,Droid Sans Japanese,Liberation Sans", 8, 1252}, + {0x251059c3, L"Chiller", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans " + L"Japanese,Liberation Sans", + 0, 1252}, + {0x25bed6dd, L"MSReferenceSansSerif", + L"DejaVu Sans Condensed,Ubuntu Condensed,Droid Sans Japanese,AR PL UKai " + L"HK", + 0, 1252}, + {0x28154c81, L"Parchment-Regular", L"Droid Sans Japanese,Liberation Sans", + 8, 1252}, + {0x29711eb9, L"STLiti", L"AR PL UKai HK", 0, 936}, + {0x2b1993b4, L"Basemic", + L"Liberation Serif,Droid Sans Japanese,Liberation Sans", 0, 1252}, + {0x2b316339, L"NiagaraSolid-Reg", L"Droid Sans Japanese,Liberation Sans", 0, + 1252}, + {0x2c147529, L"FootlightMTLight", + L"KacstQurn,Droid Sans Japanese,Liberation Sans", 0, 1252}, + {0x2c198928, L"HarlowSolid", + L"KacstQurn,Droid Sans Japanese,Liberation Sans", 0, 1252}, + {0x2c6ac6b2, L"LucidaBright", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " + L"Sans Japanese,Liberation Sans", + 2, 1252}, + {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"DejaVu Sans", 0, 1252}, + {0x2d5a47b0, L"STCaiyun", L"AR PL UKai HK", 0, 936}, + {0x2def26bf, L"BernardMT-Condensed", + L"KacstQurn,Droid Sans Japanese,DejaVu Serif", 0, 1252}, + {0x2fd8930b, L"KozukaMinchoPr6NR", L"DejaVu Serif", 0, 1252}, + {0x3115525a, L"FangSong_GB2312", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 1252}, + {0x31327817, L"MyriadPro", + L"Ubuntu Condensed,Droid Sans Japanese, FreeSerif", 0, 1252}, + {0x32244975, L"Helvetica", + L"Ubuntu,DejaVu Sans Condensed,Liberation Sans,Liberation Sans " + L"Narrow,Nimbus Sans L", + 0, 1252}, + {0x32ac995c, L"Terminal", L"DejaVu Serif", 0, 1252}, + {0x338d648a, L"NiagaraEngraved-Reg", L"Droid Sans Japanese,DejaVu Serif", 0, + 1252}, + {0x33bb65f2, L"Sylfaen", L"Droid Sans Japanese,DejaVu Sans", 2, 1252}, + {0x3402c30e, L"MSPMincho", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 2, + 1252}, + {0x3412bf31, L"SimSun-PUA", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing CN,AR PL UMing HK", 0, + 936}, + {0x36eb39b9, L"BerlinSansFB", + L"Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 0, 1252}, + {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, + {0x3864c4f6, L"HighTowerText", L"Droid Sans Japanese,DejaVu Serif", 2, + 1252}, + {0x3a257d03, L"FangSong_GB2312", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei", 0, 1252}, + {0x3c7d1d07, L"Garamond3LTStd", + L"Droid Sans Japanese,Ubuntu Condensed,DejaVu Sans Condensed,Liberation " + L"Serif,Ubuntu,FreeSerif", + 2, 1252}, + {0x3cdae668, L"FreestyleScript", + L"KacstQurn,Droid Sans Japanese,DejaVu Sans", 8, 1252}, + {0x3d55aed7, L"Jokerman", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, + {0x3d5b4385, L"PMingLiU", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 2, 1252}, + {0x3d9b7669, L"EstrangeloEdessa", L"Droid Sans Japanese,DejaVu Sans", 0, + 1252}, + {0x3e532d74, L"FranklinGothicMedium", L"Droid Sans Japanese,Ubuntu", 0, + 1252}, + {0x3e6aa32d, L"NSimSun", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 1, 936}, + {0x3f6c36a8, L"Gautami", + L"Droid Arabic Naskh,Droid Sans Ethiopic, mry_KacstQurn,Droid Sans " + L"Japanese,FreeSans", + 0, 1252}, + {0x3ff32662, L"Chiller-Regular", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,FreeSans", 0, 1252}, + {0x409de312, L"ModernNo.20", + L"KacstQurn,Droid Sans Japanese,Nimbus Sans L,Nimbus Sans L,FreeSans", 2, + 1252}, + {0x41443c5e, L"Georgia", L"Droid Sans Japanese,FreeSans", 2, 1252}, + {0x4160ade5, L"BellGothicStdBlack", L"FreeSans", 0, 1252}, + {0x421976c4, L"Modern-Regular", L"FreeSans", 2, 1252}, + {0x422a7252, L"Stencil", L"Droid Sans Japanese,FreeSans,Liberation Sans", 0, + 1252}, + {0x42c8554f, L"Fixedsys", L"FreeSerif", 0, 1252}, + {0x435cb41d, L"Roman", L"FreeSerif", 0, 1252}, + {0x47882383, L"CourierNew", + L"FreeMono,WenQuanYi Micro Hei Mono,AR PL UKai CN,AR PL UKai HK,AR PL " + L"UKai TW,AR PL UKai TW MBE,DejaVu Sans", + 1, 1252}, + {0x480a2338, L"BerlinSansFBDemi", L"Droid Sans Japanese,Liberation Serif", + 0, 1252}, + {0x480bf7a4, L"CourierStd", L"DejaVu Sans", 0, 1252}, + {0x481ad6ed, L"VladimirScript", L"Droid Sans Japanese,DejaVu Serif", 8, + 1252}, + {0x4911577a, L"YouYuan", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 1, + 936}, + {0x4a788d72, L"STXingkai", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0x4bf88566, L"SegoeCondensed", L"FreeSerif", 0, 1252}, + {0x4ccf51a4, L"BerlinSansFB-Reg", L"Droid Sans Japanese,Liberation Serif", + 0, 1252}, + {0x4ea967ce, L"GulimChe", + L"WenQuanYi Zen Hei Mono,AR PL UKai CN,AR PL UKai HK,AR PL UKai TW,AR PL " + L"UKai TW MBE", + 1, 1252}, + {0x4f68bd79, L"LetterGothicStd", + L"FreeMono,Liberation Mono,Andale Mono,WenQuanYi Micro Hei Mono", 0, 1252}, + {0x51a0d0e6, L"KozukaGothicPr6NM", L"FreeSerif", 0, 1252}, + {0x531b3dea, L"BasemicSymbol", L"FreeSerif", 0, 1252}, + {0x5333fd39, L"CalifornianFB-Reg", + L"Droid Sans Japanese,URW Chancery L,FreeSerif", 2, 1252}, + {0x53561a54, L"FZYTK--GBK1-0", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x55e0dde6, L"LucidaSansTypewriter", + L"Ubuntu Mono,DejaVu Sans Mono,Nimbus Mono L,Liberation Mono,Courier 10 " + L"Pitch,FreeMono", + 0, 1252}, + {0x574d4d3d, L"AdobeArabic", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, + {0x5792e759, L"STKaiti", L"WenQuanYi Micro Hei Mono", 0, 936}, + {0x5921978e, L"LucidaSansUnicode", L"Droid Sans Japanese,DejaVu Sans", 0, + 1252}, + {0x594e2da4, L"Vrinda", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Arabic " + L"Naskh,mry_KacstQurn,Droid Sans Japanese,FreeSans,FreeSerif", + 0, 1252}, + {0x59baa9a2, L"KaiTi_GB2312", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 1252}, + {0x5cfedf4f, L"BaskOldFace", + L"KacstQurn,Droid Sans Japanese,Ubuntu,Liberation Serif", 0, 1252}, + {0x5e16ac91, L"TrajanPro", + L"Nimbus Sans L,AR PL UMing HK,AR PL UKai HK,AR PL UMing TW,AR PL UMing " + L"TW MBE,DejaVu Sans,DejaVu Serif", + 0, 1252}, + {0x5f388196, L"ITCLegacySansStdMedium", + L"Liberation Serif,FreeSerif,FreeSans,Ubuntu", 0, 1252}, + {0x5f97921c, L"AdobeMyungjoStdM", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x5fefbfad, L"Batang", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 2, 1252}, + {0x605342b9, L"DotumChe", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 1, + 1252}, + {0x608c5f9a, L"KaiTi_GB2312", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x61efd0d1, L"MaturaMTScriptCapitals", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " + L"Sans Japanese,DejaVu Serif,DejaVu Sans", + 0, 1252}, + {0x626608a9, L"MVBoli", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " + L"Ethiopic,Droid Sans Japanese,DejaVu Sans", + 0, 1252}, + {0x630501a3, L"SmallFonts", L"DejaVu Serif", 0, 1252}, + {0x65d0e2a9, L"FZYTK--GBK1-0", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x669f29e1, L"FZSTK--GBK1-0", + L"AR PL UMing CN,AR PL UKai CN, AR PL UMing HK", 0, 936}, + {0x673a9e5f, L"Tunga", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " + L"Japanese,DejaVu Serif", + 0, 1252}, + {0x691aa4ce, L"NiagaraSolid", L"Droid Sans Japanese,DejaVu Serif", 0, 1252}, + {0x696259b7, L"Corbel", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, + {0x696ee9be, L"STXihei", L"WenQuanYi Micro Hei Mono", 0, 936}, + {0x6c59cf69, L"Dotum", L"WenQuanYi Zen Hei Mono", 0, 1252}, + {0x707fa561, L"Gungsuh", L"WenQuanYi Zen Hei Mono", 2, 1252}, + {0x71416bb2, L"ZWAdobeF", + L"KacstArt,KacstBookm,KacstDecorative,KacstDigital,KacstFarsi,KacstLetter," + L"KacstOffice,Dingbats,FreeSerif", + 0, 1252}, + {0x71b41801, L"Verdana", + L"DejaVu Sans Condensed,Ubuntu Condensed,Droid Sans Japanese,DejaVu Sans", + 0, 1252}, + {0x73f25e4c, L"PalatinoLinotype", L"Droid Sans Japanese,FreeSerif", 0, + 1252}, + {0x73f4d19f, L"NiagaraEngraved", L"Droid Sans Japanese,FreeSerif", 0, 1252}, + {0x74001694, L"MyriadProBlack", L"Droid Sans Japanese,AR PL UKai HK", 0, + 1252}, + {0x74b14d8f, L"Haettenschweiler", L"Droid Sans Japanese,DejaVu Serif", 0, + 1252}, + {0x74cb44ee, L"NSimSun", L"WenQuanYi Zen Hei Mono", 1, 936}, + {0x76b4d7ff, L"Shruti", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " + L"Japanese,FreeSans", + 0, 1252}, + {0x788b3533, L"Webdings", L"FreeSans", 6, 42}, + {0x797dde99, L"MSSerif", L"FreeSans", 0, 1252}, + {0x7a0f9e9e, L"MSMincho", + L"WenQuanYi Micro Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", + 1, 1252}, + {0x7b439caf, L"OldEnglishTextMT", + L"Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252}, + {0x8213a433, L"LucidaSans-Typewriter", + L"Ubuntu Mono,Liberation Mono,DejaVu Sans Mono", 0, 1252}, + {0x82fec929, L"AdobeSongStdL", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0x83581825, L"Modern", L"FreeSans", 0, 1252}, + {0x835a2823, L"Algerian", + L"KacstQurn,Droid Sans Japanese,FreeSans,Liberation Sans,Ubuntu", 0, 1252}, + {0x83dab9f5, L"Script", L"FreeSans", 0, 1252}, + {0x847b56da, L"Tahoma", + L"Droid Sans Japanese,DejaVu Sans Condensed,FreeSerif", 0, 1252}, + {0x8a783cb2, L"SimSun-PUA", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 1252}, + {0x8b5cac0e, L"Onyx", L"Droid Sans Japanese,Liberation Sans", 0, 1252}, + {0x8c6a499e, L"Gulim", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 1252}, + {0x8e0af790, L"JuiceITC", L"Droid Sans Japanese,Liberation Sans", 0, 1252}, + {0x8e8d43b2, L"Centaur", + L"KacstQurn,Droid Sans Japanese,Khmer OS,Khmer OS System", 2, 1252}, + {0x8ee4dcca, L"BookshelfSymbol7", L"Liberation Sans", 0, 1252}, + {0x90794800, L"BellGothicStdLight", L"Liberation Sans", 0, 1252}, + {0x909b516a, L"Century", + L"Droid Sans Japanese,Liberation Sans,Liberation Mono,Liberation Serif", 2, + 1252}, + {0x92ae370d, L"MSOutlook", L"Liberation Sans", 4, 42}, + {0x93c9fbf1, L"LucidaFax", + L"KacstQurn,Droid Arabic Naskh,Droid Sans " + L"Ethiopic,mry_KacstQurn,Liberation Sans", + 2, 1252}, + {0x9565085e, L"BookAntiqua", + L"Droid Sans Japanese,Liberation Sans,Liberation Serif", 2, 1252}, + {0x9856d95d, L"AdobeMingStdL", L"AR PL UMing HK", 0, 949}, + {0x9bbadd6b, L"ColonnaMT", + L"KacstQurn,Droid Sans Japanese,Khmer OS,Khmer OS System", 0, 1252}, + {0x9cbd16a4, L"ShowcardGothic-Reg", + L"Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252}, + {0x9d73008e, L"MSSansSerif", L"FreeSerif", 0, 1252}, + {0xa0607db1, L"GungsuhChe", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 1, 1252}, + {0xa0bcf6a1, L"LatinWide", L"FreeSerif", 2, 1252}, + {0xa1429b36, L"Symbol", L"FreeSerif", 6, 42}, + {0xa1fa5abc, L"Wingdings2", L"FreeSerif", 6, 42}, + {0xa1fa5abd, L"Wingdings3", L"FreeSerif", 6, 42}, + {0xa427bad4, L"InformalRoman-Regular", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " + L"Japanese,FreeSerif", + 8, 1252}, + {0xa8b92ece, L"FZSTK--GBK1-0", L"AR PL UMing CN", 0, 936}, + {0xa8d83ece, L"CalifornianFB", L"Droid Sans Japanese,FreeSerif", 2, 1252}, + {0xaa3e082c, L"Kingsoft-Phonetic", + L"Tibetan Machine Uni,LKLUG,Samyak Gujarati,Droid Sans " + L"Thai,utkal,Kedage,Mallige,AR PL UKai CN", + 0, 1252}, + {0xaa6bcabe, L"HarlowSolidItalic", + L"KacstQurn,Droid Sans Japanese,Liberation Serif", 0, 1252}, + {0xade5337c, L"MSUIGothic", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 1252}, + {0xb08dd941, L"WideLatin", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " + L"Sans Japanese,Liberation Serif", + 2, 1252}, + {0xb12765e0, L"ITCLegacySansStdBook", + L"AR PL UMing HK,AR PL UKai HK,FreeSerif,Ubuntu,FreeSans", 0, 1252}, + {0xb207f05d, L"PoorRichard", L"Droid Sans Japanese,Liberation Serif", 2, + 1252}, + {0xb3bc492f, L"JuiceITC-Regular", L"Droid Sans Japanese,Liberation Serif", + 0, 1252}, + {0xb5545399, L"Marlett", L"Liberation Serif", 4, 42}, + {0xb5dd1ebb, L"BritannicBold", + L"KacstQurn,Droid Arabic Naskh,Droid Sans " + L"Ethiopic,mry_KacstQurn,Liberation Serif", + 0, 1252}, + {0xb699c1c5, L"LucidaCalligraphy-Italic", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " + L"Sans Japanese,DejaVu Serif", + 0, 1252}, + {0xb725d629, L"TimesNewRoman", L"Droid Sans Japanese,Liberation Sans", 2, + 1252}, + {0xb7eaebeb, L"AdobeHeitiStdR", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0xbd29c486, L"BerlinSansFBDemi-Bold", L"Droid Sans Japanese,DejaVu Serif", + 0, 1252}, + {0xbe8a8db4, L"BookshelfSymbolSeven", L"DejaVu Sans", 0, 1252}, + {0xc16c0118, L"AdobeHebrew", L"Droid Sans Japanese,Ubuntu,Liberation Serif", + 0, 1252}, + {0xc318b0af, L"MyriadProLight", + L"Droid Sans Japanese,AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 1252}, + {0xc65e5659, L"CambriaMath", L"Droid Sans Japanese,FreeSerif,FreeMono", 2, + 1252}, + {0xc75c8f05, L"LucidaConsole", + L"Liberation Mono,DejaVu Sans Mono,FreeMono,WenQuanYi Micro Hei Mono", 1, + 1252}, + {0xca7c35d6, L"Calibri", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, + {0xcb053f53, L"MicrosoftYaHei", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0xcb7190f9, L"Magneto-Bold", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " + L"Japanese,DejaVu Serif", + 0, 1252}, + {0xcca00cc5, L"System", L"DejaVu Sans", 0, 1252}, + {0xccad6f76, L"Jokerman-Regular", L"Droid Sans Japanese,DejaVu Sans", 0, + 1252}, + {0xccc5818c, L"EuroSign", L"DejaVu Serif", 0, 1252}, + {0xcf3d7234, L"LucidaHandwriting-Italic", + L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans L,DejaVu Serif", 0, + 1252}, + {0xcf7b8fdb, L"MinionPro", L"DejaVu Sans", 0, 1252}, + {0xcfe5755f, L"Simhei", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 1, 936}, + {0xd011f4ee, L"MSPGothic", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 0, + 1252}, + {0xd060e7ef, L"Vivaldi", + L"KacstQurn,Droid Sans Japanese,Liberation Sans,Ubuntu", 8, 1252}, + {0xd07edec1, L"FranklinGothic-Medium", L"Droid Sans Japanese,Ubuntu", 0, + 1252}, + {0xd107243f, L"SimSun", L"WenQuanYi Zen Hei Mono", 0, 936}, + {0xd1881562, L"ArialNarrow", + L"Liberation Sans Narrow,Droid Sans Japanese,FreeSerif", 0, 1252}, + {0xd22b7dce, L"BodoniMTPosterCompressed", + L"Droid Sans Japanese,DejaVu Serif", 0, 1252}, + {0xd22bfa60, L"ComicSansMS", + L"Droid Sans Japanese,FreeMono,Liberation Mono", 8, 1252}, + {0xd3bd0e35, L"Bauhaus93", + L"KacstQurn,Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252}, + {0xd429ee7a, L"STFangsong", L"WenQuanYi Micro Hei Mono", 0, 936}, + {0xd6679c12, L"BernardMTCondensed", + L"KacstQurn,Droid Sans Japanese,Nimbus Sans L,URW Chancery " + L"L,KacstOne,Liberation Sans", + 0, 1252}, + {0xd8e8a027, L"LucidaSans", + L"Liberation Sans Narrow,Nimbus Sans L,KacstQurn,Droid Arabic Naskh,Droid " + L"Sans Ethiopic,DejaVu Serif Condensed,Liberation Mono,Ubuntu", + 0, 1252}, + {0xd9fe7761, L"HighTowerText-Reg", + L"Droid Sans Japanese,Ubuntu,Liberation Serif", 2, 1252}, + {0xda7e551e, L"STSong", L"WenQuanYi Micro Hei Mono", 0, 936}, + {0xdaa6842d, L"STZhongsong", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0xdaaab93f, L"STFangsong", + L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " + L"Hei,WenQuanYi Zen Hei Sharp", + 0, 936}, + {0xdaeb0713, L"STSong", + L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " + L"Hei,WenQuanYi Zen Hei Sharp", + 0, 936}, + {0xdafedbef, L"STCaiyun", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0xdb00a3d9, L"Broadway", + L"KacstQurn,Droid Sans Japanese,DejaVu Sans,FreeMono,Liberation Mono", 0, + 1252}, + {0xdb1f5ad4, L"STXinwei", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0xdb326e7f, L"STKaiti", + L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " + L"Hei,WenQuanYi Zen Hei Sharp", + 0, 936}, + {0xdb69595a, L"STHupo", + L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " + L"Hei,WenQuanYi Zen Hei Sharp", + 0, 936}, + {0xdba0082c, L"STXihei", + L" WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " + L"Hei,WenQuanYi Zen Hei Sharp", + 0, 936}, + {0xdbd0ab18, L"STXingkai", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0xdc1a7db1, L"STLiti", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0xdc33075f, L"KristenITC-Regular", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu Sans " + L"Condensed,Ubuntu,Liberation Sans", + 8, 1252}, + {0xdcc7009c, L"Harrington", + L"KacstQurn,Droid Sans Japanese,Liberation Serif,FreeSerif,Ubuntu", 0, + 1252}, + {0xdd712466, L"ArialBlack", + L"Droid Sans Japanese,DejaVu Sans,DejaVu Serif,FreeMono", 0, 1252}, + {0xdde87b3e, L"Impact", L"Droid Sans Japanese,DejaVu Serif", 0, 1252}, + {0xdf69fb32, L"SnapITC", + L"Liberation Sans Narrow,Ubuntu Condensed,DejaVu Sans,DejaVu " + L"Serif,FreeMono", + 0, 1252}, + {0xdf8b25e8, L"CenturyGothic", + L"Droid Sans Japanese,Liberation Mono,Liberation Sans,Liberation Serif", 0, + 1252}, + {0xe0f705c0, L"KristenITC", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu Sans " + L"Condensed,Ubuntu,Liberation Sans", + 8, 1252}, + {0xe1427573, L"Raavi", + L"Droid Arabic Naskh,Droid Sans " + L"Ethiopic,mry_KacstQurn,FreeSerif,Liberation Serif,Khmer OS", + 0, 1252}, + {0xe2cea0cb, L"Magneto", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu " + L"Serif,DejaVu Serif Condensed,DejaVu Sans", + 0, 1252}, + {0xe36a9e17, L"Ravie", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu " + L"Serif,DejaVu Sans,FreeMono", + 0, 1252}, + {0xe433f8e2, L"Parchment", L"Droid Sans Japanese,DejaVu Serif", 8, 1252}, + {0xe43dff4a, L"Wingdings", L"DejaVu Serif", 4, 42}, + {0xe4e2c405, L"MTExtra", L"DejaVu Serif", 6, 42}, + {0xe618cc35, L"InformalRoman", + L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " + L"Japanese,Nimbus Sans L,DejaVu Sans Condensed,Ubuntu,Liberation Sans", + 8, 1252}, + {0xe6c27ffc, L"Mistral", L"Droid Sans Japanese,DejaVu Serif", 8, 1252}, + {0xe7ebf4b9, L"Courier", L"DejaVu Sans,DejaVu Sans Condensed,FreeSerif", 0, + 1252}, + {0xe8bc4a9d, L"MSReferenceSpecialty", L"DejaVu Serif", 0, 1252}, + {0xe90fb013, L"TempusSansITC", + L"Droid Sans Japanese,Ubuntu,Liberation Serif,FreeSerif", 0, 1252}, + {0xec637b42, L"Consolas", + L"DejaVu Sans Condensed,AR PL UKai CN,AR PL UKai HK,AR PL UKai " + L"TW,FreeSerif,FreeSans", + 1, 1252}, + {0xed3a683b, L"STXinwei", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, + 936}, + {0xef264cd1, L"LucidaHandwriting", + L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans " + L"L,KacstQurn,Liberation Mono", + 0, 1252}, + {0xf086bca2, L"BaskervilleOldFace", + L"KacstQurn,Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 0, + 1252}, + {0xf1028030, L"Mangal", + L"FreeSans,TSCu_Paranar,Garuda,Liberation Sans,Liberation Sans " + L"Narrow,Nimbus Sans L", + 2, 1252}, + {0xf1da7eb9, L"ShowcardGothic", + L"Droid Sans Japanese,DejaVu Serif Condensed,DejaVu Sans " + L"Condensed,Liberation Sans,Ubuntu", + 0, 1252}, + {0xf210f06a, L"ArialMT", + L"Liberation Sans,Liberation Sans Narrow,FreeSans,Nimbus Sans L,Khmer OS " + L"System,Khmer OS", + 0, 1252}, + {0xf477f16a, L"Latha", + L"Liberation Sans Narrow,Nimbus Sans L,Droid Arabic " + L"Naskh,mry_KacstQurn,FreeSerif,Nimbus Sans L", + 0, 1252}, + {0xf616f3dd, L"LiSu", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " + L"PL UMing TW MBE", + 1, 936}, + {0xfa479aa6, L"MicrosoftYaHei", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, + {0xfcd19697, L"BookmanOldStyle", + L"Droid Sans Japanese,Liberation Mono,Liberation Sans,Liberation Serif", 0, + 1252}, + {0xfe209a82, L"LucidaCalligraphy", + L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " + L"Sans Japanese,DejaVu Serif,DejaVu Sans,FreeMono", + 0, 1252}, + {0xfef135f8, L"AdobeHeitiStd-Regular", + L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " + L"Sharp,WenQuanYi Micro Hei", + 0, 936}, +}; +#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ +const FGAS_FontInfo g_XFAFontsMap[] = { + {0x01d5d33e, L"SimSun", L"STHeiti,Heiti TC,STFangsong", 0, 936}, + {0x01e4f102, L"YouYuan", L"STHeiti,Heiti TC,STFangsong", 1, 936}, + {0x030549dc, L"LiSu", L"STHeiti,Heiti TC,STFangsong", 1, 936}, + {0x032edd44, L"Simhei", L"STHeiti,Heiti TC,STFangsong", 1, 936}, + {0x03eac6fc, L"PoorRichard-Regular", + L"Noteworthy,Avenir Next Condensed,Impact", 2, 1252}, + {0x03ed90e6, L"Nina", L"Microsoft Sans Serif", 0, 1252}, + {0x077b56b3, L"KingsoftPhoneticPlain", + L"LastResort,Apple " + L"Chancery,STIXVariants,STIXSizeOneSym,STIXSizeOneSym,Apple Braille", + 0, 1252}, + {0x078ed524, L"MicrosoftSansSerif", L"Songti SC,Apple Symbols", 0, 1252}, + {0x089b18a9, L"Arial", + L"Arial Unicode MS,Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x0b2cad72, L"MonotypeCorsiva", L"Arial Narrow,Impact", 8, 1252}, + {0x0bb003e7, L"Kartika", + L"Arial Unicode MS,Microsoft Sans Serif,Arial Narrow,Damascus", 2, 1252}, + {0x0bb469df, L"VinerHandITC", L"Comic Sans MS,Songti SC,STSong", 8, 1252}, + {0x0bc1a851, L"SegoeUI", L"Apple Symbols", 0, 1252}, + {0x0c112ebd, L"KozukaGothicPro-VIM", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0x0cfcb9c1, L"AdobeThai", L"Avenir Next Condensed Ultra Light", 0, 847}, + {0x0e7de0f9, L"Playbill", L"STIXNonUnicode", 0, 1252}, + {0x0eff47c3, L"STHupo", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, + {0x107ad374, L"Constantia", L"Arial Unicode MS,Palatino,Baskerville", 2, + 1252}, + {0x12194c2d, L"KunstlerScript", + L"Avenir Next Condensed Demi Bold,Arial Narrow", 8, 1252}, + {0x135ef6a1, L"MinionProSmBd", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x158c4049, L"Garamond", L"Impact,Arial Narrow", 2, 1252}, + {0x160ecb24, L"STZhongsong", L"STFangsong,Songti SC", 0, 936}, + {0x161ed07e, L"MSGothic", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing " + L"TW,Microsoft Sans Serif,Apple Symbols", + 1, 1252}, + {0x171d1ed1, L"SnapITC-Regular", L"STHeiti,Arial Black", 0, 1252}, + {0x18d1188f, L"Cambria", L"Arial Unicode MS", 2, 1252}, + {0x18eaf350, L"ArialUnicodeMS", L"Microsoft Sans Serif,Apple Symbols", 0, + 936}, + {0x1a92d115, L"MingLiU", L"Heiti SC,STHeiti", 1, 1252}, + {0x1cc217c6, L"TrebuchetMS", L"Damascus,Impact,Arial Narrow", 0, 1252}, + {0x1d649596, L"BasemicTimes", L"Liberation Serif,Impact,Arial Narrow", 0, + 1252}, + {0x1e34ee60, L"BellMT", + L"Papyrus,STIXNonUnicode,Microsoft Sans Serif,Avenir Light", 2, 1252}, + {0x1eb36945, L"CooperBlack", + L"Marion,STIXNonUnicode,Arial Rounded MT Bold,Lucida Grande", 2, 1252}, + {0x1ef7787d, L"BatangChe", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,,AR PL UMing HK,AR PL UMing TW,AR " + L"PL UMing TW MBE,Arial Unicode MS,Heiti TC", + 1, 1252}, + {0x20b3bd3a, L"BrushScriptMT", + L"STIXNonUnicode,Damascus,Arial Narrow,Avenir Next Condensed,Cochin", 8, + 1252}, + {0x220877aa, L"Candara", L"Cochin,Baskerville,Marion", 0, 1252}, + {0x22135007, L"FreestyleScript-Regular", + L"STIXNonUnicode,Nadeem,Zapf Dingbats", 8, 1252}, + {0x251059c3, L"Chiller", + L"Zapf Dingbats,Damascus,STIXNonUnicode,Papyrus,KufiStandardGK,Baghdad", 0, + 1252}, + {0x25bed6dd, L"MSReferenceSansSerif", + L"Tahoma,Apple Symbols,Apple LiGothic,Arial Unicode MS,Lucida " + L"Grande,Microsoft Sans Serif", + 0, 1252}, + {0x28154c81, L"Parchment-Regular", L"Microsoft Sans Serif,Apple Symbols", 8, + 1252}, + {0x29711eb9, L"STLiti", L"Kaiti SC,Songti SC", 0, 936}, + {0x2b1993b4, L"Basemic", L"Impact,Arial Narrow", 0, 1252}, + {0x2b316339, L"NiagaraSolid-Reg", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x2c147529, L"FootlightMTLight", + L"STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans,Noteworthy", 0, 1252}, + {0x2c198928, L"HarlowSolid", + L"Avenir Medium,Avenir Next Medium,Arial Unicode MS", 0, 1252}, + {0x2c6ac6b2, L"LucidaBright", + L"PT Sans Narrow,Papyrus,Damascus,STIXNonUnicode,Arial Rounded MT " + L"Bold,Comic Sans MS,Avenir Next", + 2, 1252}, + {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0x2d5a47b0, L"STCaiyun", L"Kaiti SC,Songti SC", 0, 936}, + {0x2def26bf, L"BernardMT-Condensed", + L"Impact,Avenir Next Condensed Demi Bold,American Typewriter", 0, 1252}, + {0x2fd8930b, L"KozukaMinchoPr6NR", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x3115525a, L"FangSong_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252}, + {0x31327817, L"MyriadPro", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x32244975, L"Helvetica", + L"Arial Narrow,Arial Unicode MS,Damascus,STIXNonUnicode", 0, 1252}, + {0x32ac995c, L"Terminal", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x338d648a, L"NiagaraEngraved-Reg", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0x33bb65f2, L"Sylfaen", L"Arial Unicode MS,Marion", 2, 1252}, + {0x3402c30e, L"MSPMincho", L"Arial Unicode MS,Apple SD Gothic Neo", 2, + 1252}, + {0x3412bf31, L"SimSun-PUA", L"STHeiti,Heiti TC,STFangsong", 0, 936}, + {0x36eb39b9, L"BerlinSansFB", L"American Typewriter,Impact", 0, 1252}, + {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, + {0x3864c4f6, L"HighTowerText", L"STIXGeneral,.Helvetica Neue Desk UI", 2, + 1252}, + {0x3a257d03, L"FangSong_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252}, + {0x3cdae668, L"FreestyleScript", L"Nadeem,Zapf Dingbats,STIXNonUnicode", 8, + 1252}, + {0x3d55aed7, L"Jokerman", + L"Papyrus,Lucida Grande,Heiti TC,American Typewriter", 0, 1252}, + {0x3d5b4385, L"PMingLiU", L"Heiti SC,STHeiti", 2, 1252}, + {0x3d9b7669, L"EstrangeloEdessa", L"American Typewriter,Marion", 0, 1252}, + {0x3e532d74, L"FranklinGothicMedium", L"Impact,Arial Narrow", 0, 1252}, + {0x3e6aa32d, L"NSimSun", L"STHeiti,STFangsong", 1, 936}, + {0x3f6c36a8, L"Gautami", + L"Damascus,STIXNonUnicode,STIXGeneral,American Typewriter", 0, 1252}, + {0x3ff32662, L"Chiller-Regular", L"Papyrus,KufiStandardGK,Baghdad", 0, + 1252}, + {0x409de312, L"ModernNo.20", L"Avenir Next Condensed,Impact", 2, 1252}, + {0x41443c5e, L"Georgia", L".Helvetica Neue Desk UI,Arial Unicode MS", 2, + 1252}, + {0x4160ade5, L"BellGothicStdBlack", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0x421976c4, L"Modern-Regular", L"Impact", 2, 1252}, + {0x422a7252, L"Stencil", L"STIXNonUnicode,Songti SC,Georgia,Baskerville", 0, + 1252}, + {0x42c8554f, L"Fixedsys", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x435cb41d, L"Roman", L"Arial Narrow", 0, 1252}, + {0x47882383, L"CourierNew", L"PCMyungjo,Osaka,Arial Unicode MS,Songti SC", + 1, 1252}, + {0x480a2338, L"BerlinSansFBDemi", + L"STIXNonUnicode,American Typewriter,Avenir Next Condensed Heavy", 0, + 1252}, + {0x480bf7a4, L"CourierStd", L"Courier New", 0, 1252}, + {0x481ad6ed, L"VladimirScript", + L"STIXNonUnicode,Avenir Next Condensed,Impact", 8, 1252}, + {0x4911577a, L"YouYuan", L"STHeiti,Heiti TC", 1, 936}, + {0x4a788d72, L"STXingkai", L"Kaiti SC,Songti SC", 0, 936}, + {0x4bf88566, L"SegoeCondensed", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x4ccf51a4, L"BerlinSansFB-Reg", + L"STIXNonUnicode,American Typewriter,Impact", 0, 1252}, + {0x4ea967ce, L"GulimChe", L"Arial Unicode MS,Heiti TC,STFangsong", 1, 1252}, + {0x4f68bd79, L"LetterGothicStd", + L"Courier New,Andale Mono,Ayuthaya,PCMyungjo,Osaka", 0, 1252}, + {0x51a0d0e6, L"KozukaGothicPr6NM", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x531b3dea, L"BasemicSymbol", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x5333fd39, L"CalifornianFB-Reg", + L"American Typewriter,Avenir Next Condensed,Impact", 2, 1252}, + {0x53561a54, L"FZYTK--GBK1-0", L"STFangsong,Songti SC,STSong", 0, 936}, + {0x55e0dde6, L"LucidaSansTypewriter", L"Menlo,Courier New,Andale Mono", 0, + 1252}, + {0x574d4d3d, L"AdobeArabic", L"Arial Narrow", 0, 1252}, + {0x5792e759, L"STKaiti", L"Songti SC,Arial Unicode MS", 0, 936}, + {0x5921978e, L"LucidaSansUnicode", L"Lucida Grande,Arial Unicode MS,Menlo", + 0, 1252}, + {0x594e2da4, L"Vrinda", L"Geeza Pro,Damascus,STIXGeneral,Gill Sans", 0, + 1252}, + {0x59baa9a2, L"KaiTi_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252}, + {0x5cfedf4f, L"BaskOldFace", + L"Avenir Next Condensed Heavy,PT Sans,Avenir Next Condensed", 0, 1252}, + {0x5e16ac91, L"TrajanPro", L"Arial Narrow,PT Sans Narrow,Damascus", 0, + 1252}, + {0x5f97921c, L"AdobeMyungjoStdM", + L"AppleMyungjo,AppleGothic,Arial Unicode MS", 0, 936}, + {0x5fefbfad, L"Batang", L"Arial Unicode MS,Songti SC", 2, 1252}, + {0x605342b9, L"DotumChe", L"Arial Unicode MS,Heiti TC", 1, 1252}, + {0x608c5f9a, L"KaiTi_GB2312", L"Hiragino Sans GB,STHeiti,Heiti TC", 0, 936}, + {0x61efd0d1, L"MaturaMTScriptCapitals", + L"Kokonor,Damascus,STIXNonUnicode,STHeiti,Arial Black,Avenir Next Heavy", + 0, 1252}, + {0x626608a9, L"MVBoli", + L"Apple Braille,Geeza Pro,Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x630501a3, L"SmallFonts", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x65d0e2a9, L"FZYTK--GBK1-0", L"STFangsong,Songti SC,STSong", 0, 936}, + {0x669f29e1, L"FZSTK--GBK1-0", L"STHeiti,Heiti TC", 0, 936}, + {0x673a9e5f, L"Tunga", + L"Damascus,STIXNonUnicode,Avenir Next Condensed,Avenir Next Condensed " + L"Ultra Light,Futura", + 0, 1252}, + {0x691aa4ce, L"NiagaraSolid", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x696259b7, L"Corbel", L"Cochin,Baskerville,Marion", 0, 1252}, + {0x696ee9be, L"STXihei", L"STHeiti,Heiti TC,Songti SC,Arial Unicode MS", 0, + 936}, + {0x6c59cf69, L"Dotum", L"Arial Unicode MS,Songti SC", 0, 1252}, + {0x707fa561, L"Gungsuh", L"Arial Unicode MS,Heiti TC", 2, 1252}, + {0x71416bb2, L"ZWAdobeF", + L"STIXSizeFourSym,STIXSizeThreeSym,STIXSizeTwoSym,STIXSizeOneSym", 0, + 1252}, + {0x71b41801, L"Verdana", + L"Tahoma,Marion,Apple Symbols,.Helvetica Neue Desk UI,Lucida " + L"Grande,Courier New", + 0, 1252}, + {0x73f25e4c, L"PalatinoLinotype", L"Palatino,Arial Unicode MS", 0, 1252}, + {0x73f4d19f, L"NiagaraEngraved", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x74001694, L"MyriadProBlack", L"Palatino,Baskerville,Marion,Cochin", 0, + 1252}, + {0x74b14d8f, L"Haettenschweiler", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x74cb44ee, L"NSimSun", L"STHeiti,Heiti TC,STFangsong", 1, 936}, + {0x76b4d7ff, L"Shruti", + L"Damascus,STIXNonUnicode,Arial Unicode MS,American Typewriter", 0, 1252}, + {0x788b3533, L"Webdings", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, + {0x797dde99, L"MSSerif", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x7a0f9e9e, L"MSMincho", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " + L"PL UMing TW MBE,Arial Unicode MS,Apple SD Gothic Neo", + 1, 1252}, + {0x7b439caf, L"OldEnglishTextMT", + L"STIXNonUnicode,Arial Unicode MS,Baskerville,Avenir Next Medium", 0, + 1252}, + {0x8213a433, L"LucidaSans-Typewriter", + L"Comic Sans MS,Avenir Next,Arial Rounded MT Bold", 0, 1252}, + {0x82fec929, L"AdobeSongStdL", L"Heiti TC,STHeiti", 0, 936}, + {0x83581825, L"Modern", L"Avenir Next Condensed,Impact", 0, 1252}, + {0x835a2823, L"Algerian", + L"STIXNonUnicode,Baskerville,Avenir Next Medium,American Typewriter", 0, + 1252}, + {0x83dab9f5, L"Script", L"Arial Narrow", 0, 1252}, + {0x847b56da, L"Tahoma", L"Songti SC,Apple Symbols", 0, 1252}, + {0x8a783cb2, L"SimSun-PUA", L"STHeiti,Heiti TC,STFangsong", 0, 1252}, + {0x8b5cac0e, L"Onyx", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0x8c6a499e, L"Gulim", L"Arial Unicode MS,Songti SC", 0, 1252}, + {0x8e0af790, L"JuiceITC", L"Nadeem,Al Bayan", 0, 1252}, + {0x8e8d43b2, L"Centaur", L"Avenir Next Condensed,Noteworthy,Impact", 2, + 1252}, + {0x8ee4dcca, L"BookshelfSymbol7", L"Microsoft Sans Serif,Apple Symbols", 0, + 1252}, + {0x90794800, L"BellGothicStdLight", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0x909b516a, L"Century", L"Damascus,Andale Mono,Songti SC,Arial Unicode MS", + 2, 1252}, + {0x92ae370d, L"MSOutlook", L"Microsoft Sans Serif,Apple Symbols", 4, 42}, + {0x93c9fbf1, L"LucidaFax", + L"PT Sans Narrow,Papyrus,Kokonor,Geeza Pro,Arial Rounded MT Bold,Lucida " + L"Grande,Futura", + 2, 1252}, + {0x9565085e, L"BookAntiqua", L"Palatino,Microsoft Sans Serif,Apple Symbols", + 2, 1252}, + {0x9856d95d, L"AdobeMingStdL", L"AHiragino Sans GB,Heiti TC,STHeiti", 0, + 949}, + {0x9bbadd6b, L"ColonnaMT", L"Noteworthy,Avenir Next Condensed,Impact", 0, + 1252}, + {0x9cbd16a4, L"ShowcardGothic-Reg", + L"Arial Unicode MS,Georgia,American Typewriter", 0, 1252}, + {0x9d73008e, L"MSSansSerif", L"Songti SC,Apple Symbols", 0, 1252}, + {0xa0607db1, L"GungsuhChe", + L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " + L"PL UMing TW MBE,Arial Unicode MS,Heiti TC,STFangsong", + 1, 1252}, + {0xa0bcf6a1, L"LatinWide", L"Zapfino,Arial Black,STHeiti", 2, 1252}, + {0xa1429b36, L"Symbol", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, + {0xa1fa5abc, L"Wingdings2", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, + {0xa1fa5abd, L"Wingdings3", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, + {0xa427bad4, L"InformalRoman-Regular", + L"STIXNonUnicode,Arial Narrow,Avenir Next Condensed Demi Bold", 8, 1252}, + {0xa8b92ece, L"FZSTK--GBK1-0", L"STHeiti,Heiti TC,STFangsong", 0, 936}, + {0xa8d83ece, L"CalifornianFB", + L"American Typewriter,Avenir Next Condensed,Impact", 2, 1252}, + {0xaa3e082c, L"Kingsoft-Phonetic", + L"STIXVariants,STIXSizeOneSym,Apple Braille", 0, 1252}, + {0xaa6bcabe, L"HarlowSolidItalic", + L"STIXNonUnicode,Avenir Medium,Avenir Next Medium,Arial Unicode MS", 0, + 1252}, + {0xade5337c, L"MSUIGothic", L"Arial Unicode MS,Apple SD Gothic Neo", 0, + 1252}, + {0xb08dd941, L"WideLatin", + L"Marion,Papyrus,Nanum Pen Script,Zapf Dingbats,Damascus,Zapfino,Arial " + L"Black,STHeiti", + 2, 1252}, + {0xb12765e0, L"ITCLegacySansStdBook", + L"LastResort,.Helvetica Neue Desk UI,Arial Unicode MS,Palatino", 0, 1252}, + {0xb207f05d, L"PoorRichard", L"Noteworthy,Avenir Next Condensed,Impact", 2, + 1252}, + {0xb3bc492f, L"JuiceITC-Regular", L"Nadeem,Al Bayan,STIXNonUnicode", 0, + 1252}, + {0xb5545399, L"Marlett", L"Microsoft Sans Serif,Apple Symbols", 4, 42}, + {0xb5dd1ebb, L"BritannicBold", + L"Damascus,STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans", 0, 1252}, + {0xb699c1c5, L"LucidaCalligraphy-Italic", L"STHeiti,Arial Black", 0, 1252}, + {0xb725d629, L"TimesNewRoman", L"Microsoft Sans Serif,Apple Symbols", 2, + 1252}, + {0xb7eaebeb, L"AdobeHeitiStdR", L"Heiti TC,STHeiti", 0, 936}, + {0xbd29c486, L"BerlinSansFBDemi-Bold", + L"American Typewriter,Avenir Next Condensed Heavy", 0, 1252}, + {0xbe8a8db4, L"BookshelfSymbolSeven", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0xc16c0118, L"AdobeHebrew", + L".Helvetica Neue Desk UI,Palatino,American Typewriter", 0, 1252}, + {0xc318b0af, L"MyriadProLight", L"Palatino,Baskerville,Marion", 0, 1252}, + {0xc65e5659, L"CambriaMath", L"Arial Unicode MS", 2, 1252}, + {0xc75c8f05, L"LucidaConsole", L"Courier New,Menlo,Andale Mono", 1, 1252}, + {0xca7c35d6, L"Calibri", L"Apple Symbols,HeadLineA", 0, 1252}, + {0xcb053f53, L"MicrosoftYaHei", L"Arial Unicode MS", 0, 936}, + {0xcb7190f9, L"Magneto-Bold", L"Lucida Grande", 0, 1252}, + {0xcca00cc5, L"System", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0xccad6f76, L"Jokerman-Regular", L"Lucida Grande", 0, 1252}, + {0xccc5818c, L"EuroSign", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0xcf3d7234, L"LucidaHandwriting-Italic", + L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0xcf7b8fdb, L"MinionPro", + L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252}, + {0xcfe5755f, L"Simhei", L"STHeiti,Heiti TC,STFangsong", 1, 936}, + {0xd011f4ee, L"MSPGothic", L"Arial Unicode MS,Apple SD Gothic Neo", 0, + 1252}, + {0xd060e7ef, L"Vivaldi", + L"STIXNonUnicode,Arial Unicode MS,Avenir Medium,Avenir Next Medium", 8, + 1252}, + {0xd07edec1, L"FranklinGothic-Medium", L"Impact,Arial Narrow", 0, 1252}, + {0xd107243f, L"SimSun", L"STHeiti,Heiti TC,STFangsong", 0, 936}, + {0xd1881562, L"ArialNarrow", L"PT Sans Narrow,Apple Symbols", 0, 1252}, + {0xd22b7dce, L"BodoniMTPosterCompressed", + L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, + {0xd22bfa60, L"ComicSansMS", + L"Damascus,Georgia,.Helvetica Neue Desk UI,Lucida Grande,Arial Unicode MS", + 8, 1252}, + {0xd3bd0e35, L"Bauhaus93", + L"STIXNonUnicode,Arial Unicode MS,Avenir Next,Avenir", 0, 1252}, + {0xd429ee7a, L"STFangsong", L"Songti SC,Arial Unicode MS", 0, 936}, + {0xd6679c12, L"BernardMTCondensed", + L"Impact,Avenir Next Condensed Demi Bold", 0, 1252}, + {0xd8e8a027, L"LucidaSans", + L"Arial Narrow,Khmer MN,Kokonor,Damascus,Microsoft Sans Serif,Apple " + L"Symbols", + 0, 1252}, + {0xd9fe7761, L"HighTowerText-Reg", + L"STIXGeneral,.Helvetica Neue Desk UI,Trebuchet MS", 2, 1252}, + {0xda7e551e, L"STSong", L"Arial Unicode MS", 0, 936}, + {0xdaa6842d, L"STZhongsong", L"STFangsong,Songti SC,STSong", 0, 936}, + {0xdaaab93f, L"STFangsong", L"Songti SC,Arial Unicode MS", 0, 936}, + {0xdaeb0713, L"STSong", L"Songti SC,Arial Unicode MS", 0, 936}, + {0xdafedbef, L"STCaiyun", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, + {0xdb00a3d9, L"Broadway", + L"Papyrus,STIXNonUnicode,Arial Black,Avenir Next Heavy,Heiti TC", 0, 1252}, + {0xdb1f5ad4, L"STXinwei", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, + {0xdb326e7f, L"STKaiti", L"Songti SC,Arial Unicode MS", 0, 936}, + {0xdb69595a, L"STHupo", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, + {0xdba0082c, L"STXihei", L"Songti SC,Arial Unicode MS", 0, 936}, + {0xdbd0ab18, L"STXingkai", L"Kaiti SC,Songti SC", 0, 936}, + {0xdc1a7db1, L"STLiti", L"Kaiti SC,Songti SC", 0, 936}, + {0xdc33075f, L"KristenITC-Regular", + L"STIXNonUnicode,Damascus,Songti SC,STSong", 8, 1252}, + {0xdcc7009c, L"Harrington", + L"STIXNonUnicode,Avenir Next Condensed Heavy,Noteworthy", 0, 1252}, + {0xdd712466, L"ArialBlack", L"Geeza Pro,Damascus,Songti SC,STSong", 0, + 1252}, + {0xdde87b3e, L"Impact", L"Arial Narrow,Marion", 0, 1252}, + {0xdf69fb32, L"SnapITC", + L"Arial Narrow,PT Sans Narrow,Marion,STHeiti,Arial Black", 0, 1252}, + {0xdf8b25e8, L"CenturyGothic", + L"Damascus,Andale Mono,Songti SC,Arial Unicode MS", 0, 1252}, + {0xe0f705c0, L"KristenITC", L"Songti SC,STSong", 8, 1252}, + {0xe1427573, L"Raavi", + L"Damascus,STIXNonUnicode,Marion,Papyrus,Avenir Next Condensed " + L"Heavy,American Typewriter", + 0, 1252}, + {0xe2cea0cb, L"Magneto", + L"STIXNonUnicode,Damascus,Geeza Pro,Lucida Grande,Georgia,Heiti TC", 0, + 1252}, + {0xe36a9e17, L"Ravie", L"STHeiti,Arial Black", 0, 1252}, + {0xe433f8e2, L"Parchment", L"Microsoft Sans Serif,Apple Symbols", 8, 1252}, + {0xe43dff4a, L"Wingdings", L"Microsoft Sans Serif,Apple Symbols", 4, 42}, + {0xe4e2c405, L"MTExtra", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, + {0xe618cc35, L"InformalRoman", L"Arial Narrow", 8, 1252}, + {0xe6c27ffc, L"Mistral", L"Apple Symbols", 8, 1252}, + {0xe7ebf4b9, L"Courier", L"Courier New", 0, 1252}, + {0xe8bc4a9d, L"MSReferenceSpecialty", L"Microsoft Sans Serif,Apple Symbols", + 0, 1252}, + {0xe90fb013, L"TempusSansITC", + L"STIXNonUnicode,Microsoft Sans Serif,Avenir Light", 0, 1252}, + {0xec637b42, L"Consolas", + L"AR PL UKai CN,AR PL UKai HK,AR PL UKai TW,AR PL UKai TW MBE,AR PL UMing " + L"CN,AR PL UMing HK,Microsoft Sans Serif,Tahoma", + 1, 1252}, + {0xed3a683b, L"STXinwei", L"Kaiti SC,Songti SC,", 0, 936}, + {0xef264cd1, L"LucidaHandwriting", + L"Arial Narrow,Avenir Next Condensed Demi Bold,Avenir Next " + L"Condensed,Avenir Next Condensed Medium,STHeiti,Arial Black", + 0, 1252}, + {0xf086bca2, L"BaskervilleOldFace", + L"STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans", 0, 1252}, + {0xf1028030, L"Mangal", + L"Arial Unicode MS,Microsoft Sans Serif,Arial Narrow,Tahoma", 2, 1252}, + {0xf1da7eb9, L"ShowcardGothic", + L"Papyrus,Arial Unicode MS,Georgia,American Typewriter", 0, 1252}, + {0xf210f06a, L"ArialMT", + L"Arial Unicode MS,Arial Narrow,STIXNonUnicode,Damascus,Avenir Next " + L"Condensed Demi Bold,Avenir Next Condensed Medium,Avenir Next Condensed", + 0, 1252}, + {0xf477f16a, L"Latha", + L"Arial Narrow,Damascus,STIXNonUnicode,American Typewriter", 0, 1252}, + {0xf616f3dd, L"LiSu", L"STHeiti,Heiti TC,STFangsong", 1, 936}, + {0xfa479aa6, L"MicrosoftYaHei", L"Arial Unicode MS", 0, 936}, + {0xfcd19697, L"BookmanOldStyle", + L"Geeza Pro,Damascus,Andale Mono,Songti SC,Arial Unicode MS", 0, 1252}, + {0xfe209a82, L"LucidaCalligraphy", + L"Kokonor,Damascus,STIXNonUnicode,STHeiti,Arial Black", 0, 1252}, + {0xfef135f8, L"AdobeHeitiStd-Regular", L"Heiti TC,STHeiti", 0, 936}, +}; +#elif _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_ +const FGAS_FontInfo g_XFAFontsMap[] = { + {0x01d5d33e, L"SimSun", L"Droid Sans Fallback", 0, 936}, + {0x01e4f102, L"YouYuan", L"Droid Sans Fallback", 1, 936}, + {0x030549dc, L"LiSu", L"Droid Sans Fallback", 1, 936}, + {0x032edd44, L"Simhei", L"Droid Sans Fallback", 1, 936}, + {0x03eac6fc, L"PoorRichard-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback,Droid Arabic " + L"Naskh,Droid Sans Ethiopic", + 2, 1252}, + {0x03ed90e6, L"Nina", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x077b56b3, L"KingsoftPhoneticPlain", + L"Droid Sans Thai,Droid Sans Armenian,Droid Arabic Naskh,Droid Sans " + L"Ethiopic,Droid Sans Fallback", + 0, 1252}, + {0x078ed524, L"MicrosoftSansSerif", L"Droid Sans Fallback", 0, 1252}, + {0x089b18a9, L"Arial", L"Droid Sans Fallback", 0, 1252}, + {0x0b2cad72, L"MonotypeCorsiva", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x0bb003e7, L"Kartika", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 2, 1252}, + {0x0bb469df, L"VinerHandITC", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x0bc1a851, L"SegoeUI", L"Droid Sans Fallback", 0, 1252}, + {0x0c112ebd, L"KozukaGothicPro-VIM", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x0cfcb9c1, L"AdobeThai", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 847}, + {0x0e7de0f9, L"Playbill", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 0, 1252}, + {0x0eff47c3, L"STHupo", L"Droid Sans Fallback", 0, 936}, + {0x107ad374, L"Constantia", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x12194c2d, L"KunstlerScript", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x135ef6a1, L"MinionProSmBd", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x158c4049, L"Garamond", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x160ecb24, L"STZhongsong", L"Droid Sans Fallback", 0, 936}, + {0x161ed07e, L"MSGothic", L"Droid Sans Fallback", 1, 1252}, + {0x171d1ed1, L"SnapITC-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x18d1188f, L"Cambria", L"Droid Sans Fallback", 2, 1252}, + {0x18eaf350, L"ArialUnicodeMS", L"Droid Sans Fallback", 0, 936}, + {0x1a92d115, L"MingLiU", L"Droid Sans Fallback", 1, 1252}, + {0x1cc217c6, L"TrebuchetMS", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x1d649596, L"BasemicTimes", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x1e34ee60, L"BellMT", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x1eb36945, L"CooperBlack", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x1ef7787d, L"BatangChe", L"Droid Sans Fallback", 1, 1252}, + {0x20b3bd3a, L"BrushScriptMT", L"Droid Arabic Naskh,Droid Sans Ethiopic", 8, + 1252}, + {0x220877aa, L"Candara", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x22135007, L"FreestyleScript-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x251059c3, L"Chiller", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 0, 1252}, + {0x25bed6dd, L"MSReferenceSansSerif", L"Droid Sans Fallback", 0, 1252}, + {0x28154c81, L"Parchment-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x29711eb9, L"STLiti", L"Droid Sans Fallback", 0, 936}, + {0x2b1993b4, L"Basemic", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x2b316339, L"NiagaraSolid-Reg", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x2c147529, L"FootlightMTLight", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x2c198928, L"HarlowSolid", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x2c6ac6b2, L"LucidaBright", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 2, 1252}, + {0x2c9f38e2, L"KozukaMinchoPro-VIR", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x2d5a47b0, L"STCaiyun", L"Droid Sans Fallback", 0, 936}, + {0x2def26bf, L"BernardMT-Condensed", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x2fd8930b, L"KozukaMinchoPr6NR", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x3115525a, L"FangSong_GB2312", L"Droid Sans Fallback", 0, 1252}, + {0x31327817, L"MyriadPro", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x32244975, L"Helvetica", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 0, 1252}, + {0x32ac995c, L"Terminal", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x338d648a, L"NiagaraEngraved-Reg", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x33bb65f2, L"Sylfaen", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x3402c30e, L"MSPMincho", L"Droid Sans Fallback", 2, 1252}, + {0x3412bf31, L"SimSun-PUA", L"Droid Sans Fallback", 0, 936}, + {0x36eb39b9, L"BerlinSansFB", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, + {0x3864c4f6, L"HighTowerText", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x3a257d03, L"FangSong_GB2312", L"Droid Sans Fallback", 0, 1252}, + {0x3cdae668, L"FreestyleScript", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x3d55aed7, L"Jokerman", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x3d5b4385, L"PMingLiU", L"Droid Sans Fallback", 2, 1252}, + {0x3d9b7669, L"EstrangeloEdessa", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x3e532d74, L"FranklinGothicMedium", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x3e6aa32d, L"NSimSun", L"Droid Sans Fallback", 1, 936}, + {0x3f6c36a8, L"Gautami", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono,Droid Sans Fallback", + 0, 1252}, + {0x3ff32662, L"Chiller-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x409de312, L"ModernNo.20", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x41443c5e, L"Georgia", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x4160ade5, L"BellGothicStdBlack", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x421976c4, L"Modern-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x422a7252, L"Stencil", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x42c8554f, L"Fixedsys", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x435cb41d, L"Roman", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x47882383, L"CourierNew", L"Droid Sans Fallback", 1, 1252}, + {0x480a2338, L"BerlinSansFBDemi", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x480bf7a4, L"CourierStd", L"Droid Sans Fallback", 0, 1252}, + {0x481ad6ed, L"VladimirScript", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0x4911577a, L"YouYuan", L"Droid Sans Fallback", 1, 936}, + {0x4a788d72, L"STXingkai", L"Droid Sans Fallback", 0, 936}, + {0x4bf88566, L"SegoeCondensed", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x4ccf51a4, L"BerlinSansFB-Reg", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x4ea967ce, L"GulimChe", L"Droid Sans Fallback", 1, 1252}, + {0x4f68bd79, L"LetterGothicStd", + L"Droid Sans Mono,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans " + L"Mono,Droid Serif,Droid Sans Fallback", + 0, 1252}, + {0x51a0d0e6, L"KozukaGothicPr6NM", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x531b3dea, L"BasemicSymbol", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x5333fd39, L"CalifornianFB-Reg", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x53561a54, L"FZYTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, + {0x55e0dde6, L"LucidaSansTypewriter", + L"Droid Sans Mono,Droid Arabic Naskh,Droid Sans Ethiopic", 0, 1252}, + {0x574d4d3d, L"AdobeArabic", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x5792e759, L"STKaiti", L"Droid Sans Fallback", 0, 936}, + {0x5921978e, L"LucidaSansUnicode", L"Droid Sans Fallback", 0, 1252}, + {0x594e2da4, L"Vrinda", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 0, 1252}, + {0x59baa9a2, L"KaiTi_GB2312", L"Droid Sans Fallback", 0, 1252}, + {0x5cfedf4f, L"BaskOldFace", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x5f97921c, L"AdobeMyungjoStdM", L"Droid Sans Fallback", 0, 936}, + {0x5fefbfad, L"Batang", L"Droid Sans Fallback", 2, 1252}, + {0x605342b9, L"DotumChe", L"Droid Sans Fallback", 1, 1252}, + {0x608c5f9a, L"KaiTi_GB2312", L"Droid Sans Fallback", 0, 936}, + {0x61efd0d1, L"MaturaMTScriptCapitals", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 0, 1252}, + {0x626608a9, L"MVBoli", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 0, 1252}, + {0x630501a3, L"SmallFonts", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x65d0e2a9, L"FZYTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, + {0x669f29e1, L"FZSTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, + {0x673a9e5f, L"Tunga", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono,Droid Sans Fallback", + 0, 1252}, + {0x691aa4ce, L"NiagaraSolid", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x696259b7, L"Corbel", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x696ee9be, L"STXihei", L"Droid Sans Fallback", 0, 936}, + {0x6c59cf69, L"Dotum", L"Droid Sans Fallback", 0, 1252}, + {0x707fa561, L"Gungsuh", L"Droid Sans Fallback", 2, 1252}, + {0x71416bb2, L"ZWAdobeF", + L"Droid Arabic Naskh,Droid Sans Armenian,Droid Sans Ethiopic,Droid Sans " + L"Georgian,Droid Sans Hebrew,Droid Sans Thai", + 0, 1252}, + {0x71b41801, L"Verdana", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x73f25e4c, L"PalatinoLinotype", L"Droid Sans Fallback", 0, 1252}, + {0x73f4d19f, L"NiagaraEngraved", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x74001694, L"MyriadProBlack", L"Book Antiqua,Constantia,Dotum,Georgia", 0, + 1252}, + {0x74b14d8f, L"Haettenschweiler", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x74cb44ee, L"NSimSun", L"Droid Sans Fallback", 1, 936}, + {0x76b4d7ff, L"Shruti", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 0, 1252}, + {0x788b3533, L"Webdings", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, + {0x797dde99, L"MSSerif", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x7a0f9e9e, L"MSMincho", L"Droid Sans Fallback", 1, 1252}, + {0x7b439caf, L"OldEnglishTextMT", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x8213a433, L"LucidaSans-Typewriter", + L"Droid Sans Mono,Droid Serif,Roboto,Droid Sans Fallback", 0, 1252}, + {0x82fec929, L"AdobeSongStdL", L"Droid Sans Fallback", 0, 936}, + {0x83581825, L"Modern", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x835a2823, L"Algerian", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x83dab9f5, L"Script", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x847b56da, L"Tahoma", L"Droid Sans Fallback", 0, 1252}, + {0x8a783cb2, L"SimSun-PUA", L"Droid Sans Fallback", 0, 1252}, + {0x8b5cac0e, L"Onyx", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x8c6a499e, L"Gulim", L"Droid Sans Fallback", 0, 1252}, + {0x8e0af790, L"JuiceITC", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x8e8d43b2, L"Centaur", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x8ee4dcca, L"BookshelfSymbol7", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x90794800, L"BellGothicStdLight", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x909b516a, L"Century", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x92ae370d, L"MSOutlook", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42}, + {0x93c9fbf1, L"LucidaFax", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 2, 1252}, + {0x9565085e, L"BookAntiqua", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0x9856d95d, L"AdobeMingStdL", L"Droid Sans Fallback", 0, 949}, + {0x9bbadd6b, L"ColonnaMT", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0x9cbd16a4, L"ShowcardGothic-Reg", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallbac", 0, 1252}, + {0x9d73008e, L"MSSansSerif", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xa0607db1, L"GungsuhChe", L"Droid Sans Fallback", 1, 1252}, + {0xa0bcf6a1, L"LatinWide", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0xa1429b36, L"Symbol", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, + {0xa1fa5abc, L"Wingdings2", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, + {0xa1fa5abd, L"Wingdings3", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, + {0xa427bad4, L"InformalRoman-Regular", + L"Droid Arabic Naskh,Droid Sans Ethiopic", 8, 1252}, + {0xa8b92ece, L"FZSTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, + {0xa8d83ece, L"CalifornianFB", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0xaa3e082c, L"Kingsoft-Phonetic", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xaa6bcabe, L"HarlowSolidItalic", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xade5337c, L"MSUIGothic", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xb08dd941, L"WideLatin", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 2, 1252}, + {0xb207f05d, L"PoorRichard", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0xb3bc492f, L"JuiceITC-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xb5545399, L"Marlett", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42}, + {0xb5dd1ebb, L"BritannicBold", L"Droid Arabic Naskh,Droid Sans Ethiopic", 0, + 1252}, + {0xb699c1c5, L"LucidaCalligraphy-Italic", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xb725d629, L"TimesNewRoman", L"Droid Sans Fallback", 2, 1252}, + {0xb7eaebeb, L"AdobeHeitiStdR", L"Droid Sans Fallback", 0, 936}, + {0xbd29c486, L"BerlinSansFBDemi-Bold", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xbe8a8db4, L"BookshelfSymbolSeven", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xc16c0118, L"AdobeHebrew", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback,Droid Arabic " + L"Naskh,Droid Sans Ethiopic", + 0, 1252}, + {0xc318b0af, L"MyriadProLight", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xc65e5659, L"CambriaMath", L"Droid Sans Fallback", 2, 1252}, + {0xc75c8f05, L"LucidaConsole", + L"Droid Sans Mono,Droid Serif,Roboto,Droid Sans Fallback", 1, 1252}, + {0xca7c35d6, L"Calibri", L"Droid Sans Fallback", 0, 1252}, + {0xcb053f53, L"MicrosoftYaHei", L"Droid Sans Fallback", 0, 936}, + {0xcb7190f9, L"Magneto-Bold", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xcca00cc5, L"System", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xccad6f76, L"Jokerman-Regular", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xccc5818c, L"EuroSign", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xcf3d7234, L"LucidaHandwriting-Italic", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xcf7b8fdb, L"MinionPro", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xcfe5755f, L"Simhei", L"Droid Sans Fallback", 1, 936}, + {0xd011f4ee, L"MSPGothic", L"Droid Sans Fallback", 0, 1252}, + {0xd060e7ef, L"Vivaldi", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0xd07edec1, L"FranklinGothic-Medium", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xd107243f, L"SimSun", L"Droid Sans Fallback", 0, 936}, + {0xd1881562, L"ArialNarrow", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xd22b7dce, L"BodoniMTPosterCompressed", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xd22bfa60, L"ComicSansMS", L"Droid Serif,Roboto,Droid Sans Fallback", 8, + 1252}, + {0xd3bd0e35, L"Bauhaus93", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xd429ee7a, L"STFangsong", L"Droid Sans Fallback", 0, 936}, + {0xd6679c12, L"BernardMTCondensed", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xd8e8a027, L"LucidaSans", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 0, 1252}, + {0xd9fe7761, L"HighTowerText-Reg", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, + {0xda7e551e, L"STSong", L"Droid Sans Fallback", 0, 936}, + {0xdaa6842d, L"STZhongsong", L"Droid Sans Fallback", 0, 936}, + {0xdaaab93f, L"STFangsong", L"Droid Sans Fallback", 0, 936}, + {0xdaeb0713, L"STSong", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 936}, + {0xdafedbef, L"STCaiyun", L"Droid Sans Fallback", 0, 936}, + {0xdb00a3d9, L"Broadway", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xdb1f5ad4, L"STXinwei", L"Droid Sans Fallback", 0, 936}, + {0xdb326e7f, L"STKaiti", L"Droid Sans Fallback", 0, 936}, + {0xdb69595a, L"STHupo", L"Droid Sans Fallback", 0, 936}, + {0xdba0082c, L"STXihei", L"Droid Sans Fallback", 0, 936}, + {0xdbd0ab18, L"STXingkai", L"Droid Sans Fallback", 0, 936}, + {0xdc1a7db1, L"STLiti", L"Droid Sans Fallback", 0, 936}, + {0xdc33075f, L"KristenITC-Regular", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 8, 1252}, + {0xdcc7009c, L"Harrington", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xdd712466, L"ArialBlack", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xdde87b3e, L"Impact", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xdf69fb32, L"SnapITC", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 0, 1252}, + {0xdf8b25e8, L"CenturyGothic", + L"Droid Serif,Roboto,Droid Serif,Droid Sans Mono", 0, 1252}, + {0xe0f705c0, L"KristenITC", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 8, 1252}, + {0xe1427573, L"Raavi", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 0, 1252}, + {0xe2cea0cb, L"Magneto", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 0, 1252}, + {0xe36a9e17, L"Ravie", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 0, 1252}, + {0xe433f8e2, L"Parchment", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0xe43dff4a, L"Wingdings", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42}, + {0xe4e2c405, L"MTExtra", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, + {0xe618cc35, L"InformalRoman", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 8, 1252}, + {0xe6c27ffc, L"Mistral", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, + {0xe7ebf4b9, L"Courier", L"Droid Sans Fallback", 0, 1252}, + {0xe8bc4a9d, L"MSReferenceSpecialty", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xe90fb013, L"TempusSansITC", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xec637b42, L"Consolas", L"Droid Sans Fallback", 1, 1252}, + {0xed3a683b, L"STXinwei", L"Droid Sans Fallback", 0, 936}, + {0xef264cd1, L"LucidaHandwriting", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 0, 1252}, + {0xf086bca2, L"BaskervilleOldFace", + L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xf1028030, L"Mangal", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 2, 1252}, + {0xf1da7eb9, L"ShowcardGothic", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallbac", 0, 1252}, + {0xf210f06a, L"ArialMT", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 0, 1252}, + {0xf477f16a, L"Latha", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " + L"Mono", + 0, 1252}, + {0xf616f3dd, L"LiSu", L"Droid Sans Fallback", 1, 936}, + {0xfa479aa6, L"MicrosoftYaHei", L"Droid Sans Fallback", 0, 936}, + {0xfcd19697, L"BookmanOldStyle", + L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, + {0xfe209a82, L"LucidaCalligraphy", + L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " + L"Mono", + 0, 1252}, + {0xfef135f8, L"AdobeHeitiStd-Regular", L"Droid Sans Fallback", 0, 936}, +}; +#endif + +} // namespace + +const FGAS_FONTUSB* FGAS_GetUnicodeBitField(wchar_t wUnicode) { int32_t iEnd = sizeof(g_FXGdiFontUSBTable) / sizeof(FGAS_FONTUSB) - 1; ASSERT(iEnd >= 0); - int32_t iStart = 0, iMid; + + int32_t iStart = 0; + int32_t iMid; do { iMid = (iStart + iEnd) / 2; const FGAS_FONTUSB& usb = g_FXGdiFontUSBTable[iMid]; - if (wUnicode < usb.wStartUnicode) { + if (wUnicode < usb.wStartUnicode) iEnd = iMid - 1; - } else if (wUnicode > usb.wEndUnicode) { + else if (wUnicode > usb.wEndUnicode) iStart = iMid + 1; - } else { + else return &usb; - } } while (iStart <= iEnd); return nullptr; } + +WideString FGAS_FontNameToEnglishName(const WideStringView& wsLocalName) { + uint32_t dwLocalNameHash = FX_HashCode_GetW(wsLocalName, true); + const FGAS_FontInfo* pEnd = g_XFAFontsMap + FX_ArraySize(g_XFAFontsMap); + const FGAS_FontInfo* pFontInfo = + std::lower_bound(g_XFAFontsMap, pEnd, dwLocalNameHash, + [](const FGAS_FontInfo& entry, uint32_t hash) { + return entry.dwFontNameHash < hash; + }); + if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwLocalNameHash) + return pFontInfo->pPsName; + return WideString(wsLocalName); +} + +const FGAS_FontInfo* FGAS_FontInfoByFontName(const WideStringView& wsFontName) { + WideString wsFontNameTemp(wsFontName); + wsFontNameTemp.Remove(L' '); + uint32_t dwCurFontNameHash = + FX_HashCode_GetW(wsFontNameTemp.AsStringView(), true); + const FGAS_FontInfo* pEnd = g_XFAFontsMap + FX_ArraySize(g_XFAFontsMap); + const FGAS_FontInfo* pFontInfo = + std::lower_bound(g_XFAFontsMap, pEnd, dwCurFontNameHash, + [](const FGAS_FontInfo& entry, uint32_t hash) { + return entry.dwFontNameHash < hash; + }); + if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwCurFontNameHash) + return pFontInfo; + return nullptr; +} diff --git a/xfa/fgas/font/fgas_fontutils.h b/xfa/fgas/font/fgas_fontutils.h index d7055ced9b4f7d8cf0c8371a8221002ede7ae5db..3bfd9394d6bc2d9d3669f14846909f970b38cbc5 100644 --- a/xfa/fgas/font/fgas_fontutils.h +++ b/xfa/fgas/font/fgas_fontutils.h @@ -7,7 +7,7 @@ #ifndef XFA_FGAS_FONT_FGAS_FONTUTILS_H_ #define XFA_FGAS_FONT_FGAS_FONTUTILS_H_ -#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/widestring.h" struct FGAS_FONTUSB { uint16_t wStartUnicode; @@ -16,10 +16,18 @@ struct FGAS_FONTUSB { uint16_t wCodePage; }; -uint32_t FGAS_GetFontHashCode(uint16_t wCodePage, uint32_t dwFontStyles); -uint32_t FGAS_GetFontFamilyHash(const FX_WCHAR* pszFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage); -const FGAS_FONTUSB* FGAS_GetUnicodeBitField(FX_WCHAR wUnicode); +const FGAS_FONTUSB* FGAS_GetUnicodeBitField(wchar_t wUnicode); + +struct FGAS_FontInfo { + uint32_t dwFontNameHash; + const wchar_t* pPsName; + const wchar_t* pReplaceFont; + uint16_t dwStyles; + uint16_t wCodePage; +}; + +WideString FGAS_FontNameToEnglishName(const WideStringView& wsLocalName); + +const FGAS_FontInfo* FGAS_FontInfoByFontName(const WideStringView& wsFontName); #endif // XFA_FGAS_FONT_FGAS_FONTUTILS_H_ diff --git a/xfa/fgas/layout/cfx_break.cpp b/xfa/fgas/layout/cfx_break.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f52a2d274952fa39df8c8ff4b651fabe2c7c450 --- /dev/null +++ b/xfa/fgas/layout/cfx_break.cpp @@ -0,0 +1,202 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_break.h" + +#include <algorithm> +#include <vector> + +#include "third_party/base/stl_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +namespace { + +const int kMinimumTabWidth = 160000; + +} // namespace + +CFX_Break::CFX_Break(uint32_t dwLayoutStyles) + : m_eCharType(FX_CHARTYPE_Unknown), + m_bSingleLine(false), + m_bCombText(false), + m_dwIdentity(0), + m_dwLayoutStyles(dwLayoutStyles), + m_iLineStart(0), + m_iLineWidth(2000000), + m_wParagraphBreakChar(L'\n'), + m_iFontSize(240), + m_iTabWidth(720000), + m_iHorizontalScale(100), + m_iVerticalScale(100), + m_iTolerance(0), + m_iCharSpace(0), + m_iDefChar(0), + m_wDefChar(0xFEFF), + m_pFont(nullptr), + m_pCurLine(nullptr), + m_iReadyLineIndex(-1) { + m_pCurLine = &m_Line[0]; +} + +CFX_Break::~CFX_Break() {} + +void CFX_Break::Reset() { + m_eCharType = FX_CHARTYPE_Unknown; + m_Line[0].Clear(); + m_Line[1].Clear(); +} + +void CFX_Break::SetLayoutStyles(uint32_t dwLayoutStyles) { + m_dwLayoutStyles = dwLayoutStyles; + m_bSingleLine = (m_dwLayoutStyles & FX_LAYOUTSTYLE_SingleLine) != 0; + m_bCombText = (m_dwLayoutStyles & FX_LAYOUTSTYLE_CombText) != 0; +} + +void CFX_Break::SetHorizontalScale(int32_t iScale) { + iScale = std::max(iScale, 0); + if (m_iHorizontalScale == iScale) + return; + + SetBreakStatus(); + m_iHorizontalScale = iScale; +} + +void CFX_Break::SetVerticalScale(int32_t iScale) { + if (iScale < 0) + iScale = 0; + if (m_iVerticalScale == iScale) + return; + + SetBreakStatus(); + m_iVerticalScale = iScale; +} + +void CFX_Break::SetFont(const RetainPtr<CFGAS_GEFont>& pFont) { + if (!pFont || pFont == m_pFont) + return; + + SetBreakStatus(); + m_pFont = pFont; + FontChanged(); +} + +void CFX_Break::SetFontSize(float fFontSize) { + int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); + if (m_iFontSize == iFontSize) + return; + + SetBreakStatus(); + m_iFontSize = iFontSize; + FontChanged(); +} + +void CFX_Break::SetBreakStatus() { + ++m_dwIdentity; + int32_t iCount = m_pCurLine->CountChars(); + if (iCount < 1) + return; + + CFX_Char* tc = m_pCurLine->GetChar(iCount - 1); + if (tc->m_dwStatus == CFX_BreakType::None) + tc->m_dwStatus = CFX_BreakType::Piece; +} + +FX_CHARTYPE CFX_Break::GetUnifiedCharType(FX_CHARTYPE chartype) const { + return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype; +} + +void CFX_Break::FontChanged() { + m_iDefChar = 0; + if (!m_pFont || m_wDefChar == 0xFEFF) + return; + + m_pFont->GetCharWidth(m_wDefChar, m_iDefChar); + m_iDefChar *= m_iFontSize; +} + +void CFX_Break::SetTabWidth(float fTabWidth) { + // Note, the use of max here was only done in the TxtBreak code. Leaving this + // in for the RTFBreak code for consistency. If we see issues with tab widths + // we may need to fix this. + m_iTabWidth = std::max(FXSYS_round(fTabWidth * 20000.0f), kMinimumTabWidth); +} + +void CFX_Break::SetDefaultChar(wchar_t wch) { + m_wDefChar = wch; + m_iDefChar = 0; + if (m_wDefChar == 0xFEFF || !m_pFont) + return; + + m_pFont->GetCharWidth(m_wDefChar, m_iDefChar); + if (m_iDefChar < 0) + m_iDefChar = 0; + else + m_iDefChar *= m_iFontSize; +} + +void CFX_Break::SetParagraphBreakChar(wchar_t wch) { + if (wch != L'\r' && wch != L'\n') + return; + m_wParagraphBreakChar = wch; +} + +void CFX_Break::SetLineBreakTolerance(float fTolerance) { + m_iTolerance = FXSYS_round(fTolerance * 20000.0f); +} + +void CFX_Break::SetCharSpace(float fCharSpace) { + m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f); +} + +void CFX_Break::SetLineBoundary(float fLineStart, float fLineEnd) { + if (fLineStart > fLineEnd) + return; + + m_iLineStart = FXSYS_round(fLineStart * 20000.0f); + m_iLineWidth = FXSYS_round(fLineEnd * 20000.0f); + m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iLineWidth); + m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iLineStart); +} + +CFX_Char* CFX_Break::GetLastChar(int32_t index, + bool bOmitChar, + bool bRichText) const { + std::vector<CFX_Char>& tca = m_pCurLine->m_LineChars; + if (!pdfium::IndexInBounds(tca, index)) + return nullptr; + + int32_t iStart = pdfium::CollectionSize<int32_t>(tca) - 1; + while (iStart > -1) { + CFX_Char* pTC = &tca[iStart--]; + if (((bRichText && pTC->m_iCharWidth < 0) || bOmitChar) && + pTC->GetCharType() == FX_CHARTYPE_Combination) { + continue; + } + if (--index < 0) + return pTC; + } + return nullptr; +} + +int32_t CFX_Break::CountBreakPieces() const { + return HasLine() ? pdfium::CollectionSize<int32_t>( + m_Line[m_iReadyLineIndex].m_LinePieces) + : 0; +} + +const CFX_BreakPiece* CFX_Break::GetBreakPieceUnstable(int32_t index) const { + if (!HasLine()) + return nullptr; + if (!pdfium::IndexInBounds(m_Line[m_iReadyLineIndex].m_LinePieces, index)) + return nullptr; + return &m_Line[m_iReadyLineIndex].m_LinePieces[index]; +} + +void CFX_Break::ClearBreakPieces() { + if (HasLine()) + m_Line[m_iReadyLineIndex].Clear(); + m_iReadyLineIndex = -1; +} diff --git a/xfa/fgas/layout/cfx_break.h b/xfa/fgas/layout/cfx_break.h new file mode 100644 index 0000000000000000000000000000000000000000..789220d9da14a9380e66c970f52a50184e46d08a --- /dev/null +++ b/xfa/fgas/layout/cfx_break.h @@ -0,0 +1,93 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_LAYOUT_CFX_BREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_BREAK_H_ + +#include <stdint.h> + +#include "core/fxcrt/retain_ptr.h" +#include "xfa/fgas/layout/cfx_breakline.h" + +class CFGAS_GEFont; + +struct FX_TPO { + bool operator<(const FX_TPO& that) const { return pos < that.pos; } + + int32_t index; + int32_t pos; +}; + +enum FX_LAYOUTSTYLE { + FX_LAYOUTSTYLE_None = 0, + FX_LAYOUTSTYLE_Pagination = 0x01, + FX_LAYOUTSTYLE_ExpandTab = 0x10, + FX_LAYOUTSTYLE_SingleLine = 0x200, + FX_LAYOUTSTYLE_CombText = 0x400 +}; + +class CFX_Break { + public: + virtual ~CFX_Break(); + + void Reset(); + + void SetLayoutStyles(uint32_t dwLayoutStyles); + uint32_t GetLayoutStyles() const { return m_dwLayoutStyles; } + + void SetFont(const RetainPtr<CFGAS_GEFont>& pFont); + void SetFontSize(float fFontSize); + void SetTabWidth(float fTabWidth); + int32_t GetTabWidth() const { return m_iTabWidth; } + + void SetHorizontalScale(int32_t iScale); + void SetVerticalScale(int32_t iScale); + void SetLineBreakTolerance(float fTolerance); + void SetLineBoundary(float fLineStart, float fLineEnd); + + void SetCharSpace(float fCharSpace); + void SetParagraphBreakChar(wchar_t wch); + void SetDefaultChar(wchar_t wch); + + int32_t CountBreakPieces() const; + const CFX_BreakPiece* GetBreakPieceUnstable(int32_t index) const; + void ClearBreakPieces(); + + CFX_Char* GetLastChar(int32_t index, bool bOmitChar, bool bRichText) const; + + protected: + explicit CFX_Break(uint32_t dwLayoutStyles); + + void SetBreakStatus(); + bool HasLine() const { return m_iReadyLineIndex >= 0; } + FX_CHARTYPE GetUnifiedCharType(FX_CHARTYPE dwType) const; + + FX_CHARTYPE m_eCharType; + bool m_bSingleLine; + bool m_bCombText; + uint32_t m_dwIdentity; + uint32_t m_dwLayoutStyles; + int32_t m_iLineStart; + int32_t m_iLineWidth; + wchar_t m_wParagraphBreakChar; + int32_t m_iFontSize; + int32_t m_iTabWidth; + int32_t m_iHorizontalScale; + int32_t m_iVerticalScale; + int32_t m_iTolerance; + int32_t m_iCharSpace; + int32_t m_iDefChar; + wchar_t m_wDefChar; + RetainPtr<CFGAS_GEFont> m_pFont; + CFX_BreakLine m_Line[2]; + CFX_BreakLine* m_pCurLine; + int8_t m_iReadyLineIndex; + + private: + void FontChanged(); +}; + +#endif // XFA_FGAS_LAYOUT_CFX_BREAK_H_ diff --git a/xfa/fgas/layout/cfx_breakline.cpp b/xfa/fgas/layout/cfx_breakline.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0788603ad0aef26849a24285a71905c21d3af7db --- /dev/null +++ b/xfa/fgas/layout/cfx_breakline.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_breakline.h" + +#include "third_party/base/stl_util.h" + +CFX_BreakLine::CFX_BreakLine() : m_iStart(0), m_iWidth(0), m_iArabicChars(0) {} + +CFX_BreakLine::~CFX_BreakLine() {} + +int32_t CFX_BreakLine::CountChars() const { + return pdfium::CollectionSize<int32_t>(m_LineChars); +} + +CFX_Char* CFX_BreakLine::GetChar(int32_t index) { + ASSERT(pdfium::IndexInBounds(m_LineChars, index)); + return &m_LineChars[index]; +} + +const CFX_Char* CFX_BreakLine::GetChar(int32_t index) const { + ASSERT(pdfium::IndexInBounds(m_LineChars, index)); + return &m_LineChars[index]; +} + +int32_t CFX_BreakLine::CountPieces() const { + return pdfium::CollectionSize<int32_t>(m_LinePieces); +} + +const CFX_BreakPiece* CFX_BreakLine::GetPiece(int32_t index) const { + ASSERT(index >= 0 && index < CountPieces()); + return &m_LinePieces[index]; +} + +int32_t CFX_BreakLine::GetLineEnd() const { + return m_iStart + m_iWidth; +} + +void CFX_BreakLine::Clear() { + m_LineChars.clear(); + m_LinePieces.clear(); + m_iWidth = 0; + m_iArabicChars = 0; +} diff --git a/xfa/fgas/layout/cfx_breakline.h b/xfa/fgas/layout/cfx_breakline.h new file mode 100644 index 0000000000000000000000000000000000000000..0b83ee6baa734f5a764b74680b2fdf19bb9e742b --- /dev/null +++ b/xfa/fgas/layout/cfx_breakline.h @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_LAYOUT_CFX_BREAKLINE_H_ +#define XFA_FGAS_LAYOUT_CFX_BREAKLINE_H_ + +#include <vector> + +#include "core/fxcrt/cfx_char.h" +#include "xfa/fgas/layout/cfx_breakpiece.h" + +class CFX_BreakLine { + public: + CFX_BreakLine(); + ~CFX_BreakLine(); + + int32_t CountChars() const; + CFX_Char* GetChar(int32_t index); + const CFX_Char* GetChar(int32_t index) const; + + int32_t CountPieces() const; + const CFX_BreakPiece* GetPiece(int32_t index) const; + + int32_t GetLineEnd() const; + + void Clear(); + + std::vector<CFX_Char> m_LineChars; + std::vector<CFX_BreakPiece> m_LinePieces; + int32_t m_iStart; + int32_t m_iWidth; + int32_t m_iArabicChars; +}; + +#endif // XFA_FGAS_LAYOUT_CFX_BREAKLINE_H_ diff --git a/xfa/fgas/layout/cfx_breakpiece.cpp b/xfa/fgas/layout/cfx_breakpiece.cpp new file mode 100644 index 0000000000000000000000000000000000000000..364c117e89036857f76d15a5ff581810b3b93455 --- /dev/null +++ b/xfa/fgas/layout/cfx_breakpiece.cpp @@ -0,0 +1,51 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_breakpiece.h" + +CFX_BreakPiece::CFX_BreakPiece() + : m_dwStatus(CFX_BreakType::Piece), + m_iStartPos(0), + m_iWidth(-1), + m_iStartChar(0), + m_iChars(0), + m_iBidiLevel(0), + m_iBidiPos(0), + m_iFontSize(0), + m_iHorizontalScale(100), + m_iVerticalScale(100), + m_dwIdentity(0), + m_dwCharStyles(0), + m_pChars(nullptr) {} + +CFX_BreakPiece::CFX_BreakPiece(const CFX_BreakPiece& other) = default; + +CFX_BreakPiece::~CFX_BreakPiece() = default; + +int32_t CFX_BreakPiece::GetEndPos() const { + return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth; +} + +CFX_Char* CFX_BreakPiece::GetChar(int32_t index) const { + ASSERT(index >= 0 && index < m_iChars && m_pChars); + return &(*m_pChars)[m_iStartChar + index]; +} + +WideString CFX_BreakPiece::GetString() const { + WideString ret; + ret.Reserve(m_iChars); + for (int32_t i = m_iStartChar; i < m_iStartChar + m_iChars; i++) + ret += static_cast<wchar_t>((*m_pChars)[i].char_code()); + return ret; +} + +std::vector<int32_t> CFX_BreakPiece::GetWidths() const { + std::vector<int32_t> ret; + ret.reserve(m_iChars); + for (int32_t i = m_iStartChar; i < m_iStartChar + m_iChars; i++) + ret.push_back((*m_pChars)[i].m_iCharWidth); + return ret; +} diff --git a/xfa/fgas/layout/cfx_breakpiece.h b/xfa/fgas/layout/cfx_breakpiece.h new file mode 100644 index 0000000000000000000000000000000000000000..5dbc0e77222170f4881bad1f864156acf8c8b20b --- /dev/null +++ b/xfa/fgas/layout/cfx_breakpiece.h @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_LAYOUT_CFX_BREAKPIECE_H_ +#define XFA_FGAS_LAYOUT_CFX_BREAKPIECE_H_ + +#include <vector> + +#include "core/fxcrt/cfx_char.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "xfa/fxfa/cxfa_textuserdata.h" + +class CFX_BreakPiece { + public: + CFX_BreakPiece(); + CFX_BreakPiece(const CFX_BreakPiece& other); + ~CFX_BreakPiece(); + + int32_t GetEndPos() const; + int32_t GetLength() const { return m_iChars; } + + CFX_Char* GetChar(int32_t index) const; + WideString GetString() const; + std::vector<int32_t> GetWidths() const; + + CFX_BreakType m_dwStatus; + int32_t m_iStartPos; + int32_t m_iWidth; + int32_t m_iStartChar; + int32_t m_iChars; + int32_t m_iBidiLevel; + int32_t m_iBidiPos; + int32_t m_iFontSize; + int32_t m_iHorizontalScale; + int32_t m_iVerticalScale; + uint32_t m_dwIdentity; + uint32_t m_dwCharStyles; + UnownedPtr<std::vector<CFX_Char>> m_pChars; + RetainPtr<CXFA_TextUserData> m_pUserData; +}; + +#endif // XFA_FGAS_LAYOUT_CFX_BREAKPIECE_H_ diff --git a/xfa/fgas/layout/cfx_linebreak.cpp b/xfa/fgas/layout/cfx_linebreak.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14352481bd6d294197470899b8b0132f2d1de6d3 --- /dev/null +++ b/xfa/fgas/layout/cfx_linebreak.cpp @@ -0,0 +1,268 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_linebreak.h" + +#include "core/fxcrt/fx_unicode.h" + +const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32] = { + {FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBPB, FX_LBPB, FX_LBPB, FX_LBCP, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBPB, FX_LBPB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBPB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBIB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBPB, + FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBPB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, + FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, + FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, + FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, + {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, + FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, +}; diff --git a/xfa/fgas/layout/cfx_linebreak.h b/xfa/fgas/layout/cfx_linebreak.h new file mode 100644 index 0000000000000000000000000000000000000000..8ba022e71e8d63f413f7db6ead620ee7f64dda91 --- /dev/null +++ b/xfa/fgas/layout/cfx_linebreak.h @@ -0,0 +1,32 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_LAYOUT_CFX_LINEBREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_LINEBREAK_H_ + +#include "core/fxcrt/fx_system.h" + +enum FX_LINEBREAKTYPE : uint8_t { + FX_LBT_UNKNOWN = 0x00, + FX_LBT_DIRECT_BRK = 0x1A, + FX_LBT_INDIRECT_BRK = 0x2B, + FX_LBT_COM_INDIRECT_BRK = 0x3C, + FX_LBT_COM_PROHIBITED_BRK = 0x4D, + FX_LBT_PROHIBITED_BRK = 0x5E, + FX_LBT_HANGUL_SPACE_BRK = 0x6F, +}; + +#define FX_LBUN FX_LBT_UNKNOWN +#define FX_LBDB FX_LBT_DIRECT_BRK +#define FX_LBIB FX_LBT_INDIRECT_BRK +#define FX_LBCB FX_LBT_COM_INDIRECT_BRK +#define FX_LBCP FX_LBT_COM_PROHIBITED_BRK +#define FX_LBPB FX_LBT_PROHIBITED_BRK +#define FX_LBHS FX_LBT_HANGUL_SPACE_BRK + +extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32]; + +#endif // XFA_FGAS_LAYOUT_CFX_LINEBREAK_H_ diff --git a/xfa/fgas/layout/cfx_rtfbreak.cpp b/xfa/fgas/layout/cfx_rtfbreak.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ef0ef2624bdedc4bf436ec652e696c185a959a9 --- /dev/null +++ b/xfa/fgas/layout/cfx_rtfbreak.cpp @@ -0,0 +1,789 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_rtfbreak.h" + +#include <algorithm> + +#include "core/fxcrt/fx_arabic.h" +#include "core/fxcrt/fx_bidi.h" +#include "core/fxge/cfx_renderdevice.h" +#include "third_party/base/stl_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/layout/cfx_linebreak.h" + +CFX_RTFBreak::CFX_RTFBreak(uint32_t dwLayoutStyles) + : CFX_Break(dwLayoutStyles), + m_bPagination(false), + m_iAlignment(CFX_RTFLineAlignment::Left) { + SetBreakStatus(); + m_bPagination = !!(m_dwLayoutStyles & FX_LAYOUTSTYLE_Pagination); +} + +CFX_RTFBreak::~CFX_RTFBreak() {} + +void CFX_RTFBreak::SetLineStartPos(float fLinePos) { + int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f); + iLinePos = std::min(iLinePos, m_iLineWidth); + iLinePos = std::max(iLinePos, m_iLineStart); + m_pCurLine->m_iStart = iLinePos; +} + +void CFX_RTFBreak::AddPositionedTab(float fTabPos) { + int32_t iTabPos = + std::min(FXSYS_round(fTabPos * 20000.0f) + m_iLineStart, m_iLineWidth); + auto it = std::lower_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), + iTabPos); + if (it != m_PositionedTabs.end() && *it == iTabPos) + return; + m_PositionedTabs.insert(it, iTabPos); +} + +void CFX_RTFBreak::SetUserData(const RetainPtr<CXFA_TextUserData>& pUserData) { + if (m_pUserData == pUserData) + return; + + SetBreakStatus(); + m_pUserData = pUserData; +} + +int32_t CFX_RTFBreak::GetLastPositionedTab() const { + return m_PositionedTabs.empty() ? m_iLineStart : m_PositionedTabs.back(); +} + +bool CFX_RTFBreak::GetPositionedTab(int32_t* iTabPos) const { + auto it = std::upper_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), + *iTabPos); + if (it == m_PositionedTabs.end()) + return false; + + *iTabPos = *it; + return true; +} + +CFX_BreakType CFX_RTFBreak::AppendChar(wchar_t wch) { + ASSERT(m_pFont && m_pCurLine); + + uint32_t dwProps = FX_GetUnicodeProperties(wch); + FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); + m_pCurLine->m_LineChars.emplace_back(wch, dwProps, m_iHorizontalScale, + m_iVerticalScale); + CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back(); + pCurChar->m_iFontSize = m_iFontSize; + pCurChar->m_dwIdentity = m_dwIdentity; + pCurChar->m_pUserData = m_pUserData; + + CFX_BreakType dwRet1 = CFX_BreakType::None; + if (chartype != FX_CHARTYPE_Combination && + GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && + m_eCharType != FX_CHARTYPE_Unknown && + m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance && + (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { + dwRet1 = EndBreak(CFX_BreakType::Line); + int32_t iCount = m_pCurLine->CountChars(); + if (iCount > 0) + pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; + } + + CFX_BreakType dwRet2 = CFX_BreakType::None; + switch (chartype) { + case FX_CHARTYPE_Tab: + AppendChar_Tab(pCurChar); + break; + case FX_CHARTYPE_Control: + dwRet2 = AppendChar_Control(pCurChar); + break; + case FX_CHARTYPE_Combination: + AppendChar_Combination(pCurChar); + break; + case FX_CHARTYPE_ArabicAlef: + case FX_CHARTYPE_ArabicSpecial: + case FX_CHARTYPE_ArabicDistortion: + case FX_CHARTYPE_ArabicNormal: + case FX_CHARTYPE_ArabicForm: + case FX_CHARTYPE_Arabic: + dwRet2 = AppendChar_Arabic(pCurChar); + break; + case FX_CHARTYPE_Unknown: + case FX_CHARTYPE_Space: + case FX_CHARTYPE_Numeric: + case FX_CHARTYPE_Normal: + default: + dwRet2 = AppendChar_Others(pCurChar); + break; + } + + m_eCharType = chartype; + return std::max(dwRet1, dwRet2); +} + +void CFX_RTFBreak::AppendChar_Combination(CFX_Char* pCurChar) { + int32_t iCharWidth = 0; + if (!m_pFont->GetCharWidth(pCurChar->char_code(), iCharWidth)) + iCharWidth = 0; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + CFX_Char* pLastChar = GetLastChar(0, false, true); + if (pLastChar && pLastChar->GetCharType() > FX_CHARTYPE_Combination) + iCharWidth = -iCharWidth; + else + m_eCharType = FX_CHARTYPE_Combination; + + pCurChar->m_iCharWidth = iCharWidth; + if (iCharWidth > 0) + m_pCurLine->m_iWidth += iCharWidth; +} + +void CFX_RTFBreak::AppendChar_Tab(CFX_Char* pCurChar) { + if (!(m_dwLayoutStyles & FX_LAYOUTSTYLE_ExpandTab)) + return; + + int32_t& iLineWidth = m_pCurLine->m_iWidth; + int32_t iCharWidth = iLineWidth; + if (GetPositionedTab(&iCharWidth)) + iCharWidth -= iLineWidth; + else + iCharWidth = m_iTabWidth * (iLineWidth / m_iTabWidth + 1) - iLineWidth; + + pCurChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; +} + +CFX_BreakType CFX_RTFBreak::AppendChar_Control(CFX_Char* pCurChar) { + CFX_BreakType dwRet2 = CFX_BreakType::None; + switch (pCurChar->char_code()) { + case L'\v': + case 0x2028: + dwRet2 = CFX_BreakType::Line; + break; + case L'\f': + dwRet2 = CFX_BreakType::Page; + break; + case 0x2029: + dwRet2 = CFX_BreakType::Paragraph; + break; + default: + if (pCurChar->char_code() == m_wParagraphBreakChar) + dwRet2 = CFX_BreakType::Paragraph; + break; + } + if (dwRet2 != CFX_BreakType::None) + dwRet2 = EndBreak(dwRet2); + + return dwRet2; +} + +CFX_BreakType CFX_RTFBreak::AppendChar_Arabic(CFX_Char* pCurChar) { + CFX_Char* pLastChar = nullptr; + int32_t iCharWidth = 0; + wchar_t wForm; + bool bAlef = false; + if (m_eCharType >= FX_CHARTYPE_ArabicAlef && + m_eCharType <= FX_CHARTYPE_ArabicDistortion) { + pLastChar = GetLastChar(1, false, true); + if (pLastChar) { + m_pCurLine->m_iWidth -= pLastChar->m_iCharWidth; + CFX_Char* pPrevChar = GetLastChar(2, false, true); + wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); + bAlef = (wForm == 0xFEFF && + pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); + if (!m_pFont->GetCharWidth(wForm, iCharWidth) && + !m_pFont->GetCharWidth(pLastChar->char_code(), iCharWidth)) { + iCharWidth = m_iDefChar; + } + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + pLastChar->m_iCharWidth = iCharWidth; + m_pCurLine->m_iWidth += iCharWidth; + iCharWidth = 0; + } + } + + wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, + nullptr); + if (!m_pFont->GetCharWidth(wForm, iCharWidth) && + !m_pFont->GetCharWidth(pCurChar->char_code(), iCharWidth)) { + iCharWidth = m_iDefChar; + } + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + pCurChar->m_iCharWidth = iCharWidth; + m_pCurLine->m_iWidth += iCharWidth; + m_pCurLine->m_iArabicChars++; + + if (m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) + return EndBreak(CFX_BreakType::Line); + return CFX_BreakType::None; +} + +CFX_BreakType CFX_RTFBreak::AppendChar_Others(CFX_Char* pCurChar) { + FX_CHARTYPE chartype = pCurChar->GetCharType(); + wchar_t wForm = pCurChar->char_code(); + int32_t iCharWidth = 0; + if (!m_pFont->GetCharWidth(wForm, iCharWidth)) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth *= m_iHorizontalScale / 100; + iCharWidth += m_iCharSpace; + + pCurChar->m_iCharWidth = iCharWidth; + m_pCurLine->m_iWidth += iCharWidth; + if (chartype != FX_CHARTYPE_Space && + m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) { + return EndBreak(CFX_BreakType::Line); + } + return CFX_BreakType::None; +} + +CFX_BreakType CFX_RTFBreak::EndBreak(CFX_BreakType dwStatus) { + ASSERT(dwStatus != CFX_BreakType::None); + + ++m_dwIdentity; + if (!m_pCurLine->m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus; + return m_pCurLine->m_LinePieces.back().m_dwStatus; + } + + if (HasLine()) { + if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus; + return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus; + } + return CFX_BreakType::None; + } + + int32_t iCount = m_pCurLine->CountChars(); + if (iCount < 1) + return CFX_BreakType::None; + + CFX_Char* tc = m_pCurLine->GetChar(iCount - 1); + tc->m_dwStatus = dwStatus; + if (dwStatus == CFX_BreakType::Piece) + return dwStatus; + + m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1; + CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex]; + bool bAllChars = m_iAlignment == CFX_RTFLineAlignment::Justified || + m_iAlignment == CFX_RTFLineAlignment::Distributed; + + if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) { + std::deque<FX_TPO> tpos; + EndBreak_BidiLine(&tpos, dwStatus); + if (!m_bPagination && m_iAlignment != CFX_RTFLineAlignment::Left) + EndBreak_Alignment(tpos, bAllChars, dwStatus); + } + m_pCurLine = pNextLine; + m_pCurLine->m_iStart = m_iLineStart; + + CFX_Char* pTC = GetLastChar(0, false, true); + m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; + return dwStatus; +} + +bool CFX_RTFBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine, + bool bAllChars, + CFX_BreakType dwStatus) { + bool bDone = false; + if (m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) { + const CFX_Char* tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1); + switch (tc->GetCharType()) { + case FX_CHARTYPE_Tab: + case FX_CHARTYPE_Control: + case FX_CHARTYPE_Space: + break; + default: + SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars); + bDone = true; + break; + } + } + + if (!m_bPagination) { + if (bAllChars && !bDone) { + int32_t endPos = m_pCurLine->GetLineEnd(); + GetBreakPos(m_pCurLine->m_LineChars, endPos, bAllChars, true); + } + return false; + } + + const CFX_Char* pCurChars = m_pCurLine->m_LineChars.data(); + CFX_BreakPiece tp; + tp.m_pChars = &m_pCurLine->m_LineChars; + bool bNew = true; + uint32_t dwIdentity = static_cast<uint32_t>(-1); + int32_t iLast = m_pCurLine->CountChars() - 1; + int32_t j = 0; + for (int32_t i = 0; i <= iLast;) { + const CFX_Char* pTC = pCurChars + i; + if (bNew) { + tp.m_iStartChar = i; + tp.m_iStartPos += tp.m_iWidth; + tp.m_iWidth = 0; + tp.m_dwStatus = pTC->m_dwStatus; + tp.m_iFontSize = pTC->m_iFontSize; + tp.m_iHorizontalScale = pTC->horizonal_scale(); + tp.m_iVerticalScale = pTC->vertical_scale(); + dwIdentity = pTC->m_dwIdentity; + tp.m_dwIdentity = dwIdentity; + tp.m_pUserData = pTC->m_pUserData.As<CXFA_TextUserData>(); + j = i; + bNew = false; + } + + if (i == iLast || pTC->m_dwStatus != CFX_BreakType::None || + pTC->m_dwIdentity != dwIdentity) { + tp.m_iChars = i - j; + if (pTC->m_dwIdentity == dwIdentity) { + tp.m_dwStatus = pTC->m_dwStatus; + tp.m_iWidth += pTC->m_iCharWidth; + tp.m_iChars += 1; + ++i; + } + m_pCurLine->m_LinePieces.push_back(tp); + bNew = true; + } else { + tp.m_iWidth += pTC->m_iCharWidth; + ++i; + } + } + return true; +} + +void CFX_RTFBreak::EndBreak_BidiLine(std::deque<FX_TPO>* tpos, + CFX_BreakType dwStatus) { + CFX_Char* pTC; + std::vector<CFX_Char>& chars = m_pCurLine->m_LineChars; + int32_t iCount = m_pCurLine->CountChars(); + if (!m_bPagination && m_pCurLine->m_iArabicChars > 0) { + ASSERT(iCount >= 0); + + size_t iBidiNum = 0; + for (size_t i = 0; i < static_cast<size_t>(iCount); ++i) { + pTC = &chars[i]; + pTC->m_iBidiPos = static_cast<int32_t>(i); + if (pTC->GetCharType() != FX_CHARTYPE_Control) + iBidiNum = i; + if (i == 0) + pTC->m_iBidiLevel = 1; + } + FX_BidiLine(&chars, iBidiNum + 1); + } else { + for (int32_t i = 0; i < iCount; ++i) { + pTC = &chars[i]; + pTC->m_iBidiLevel = 0; + pTC->m_iBidiPos = 0; + pTC->m_iBidiOrder = 0; + } + } + + CFX_BreakPiece tp; + tp.m_dwStatus = CFX_BreakType::Piece; + tp.m_iStartPos = m_pCurLine->m_iStart; + tp.m_pChars = &chars; + + int32_t iBidiLevel = -1; + int32_t iCharWidth; + FX_TPO tpo; + uint32_t dwIdentity = static_cast<uint32_t>(-1); + int32_t i = 0; + int32_t j = 0; + while (i < iCount) { + pTC = &chars[i]; + if (iBidiLevel < 0) { + iBidiLevel = pTC->m_iBidiLevel; + iCharWidth = pTC->m_iCharWidth; + tp.m_iWidth = iCharWidth < 1 ? 0 : iCharWidth; + tp.m_iBidiLevel = iBidiLevel; + tp.m_iBidiPos = pTC->m_iBidiOrder; + tp.m_iFontSize = pTC->m_iFontSize; + tp.m_iHorizontalScale = pTC->horizonal_scale(); + tp.m_iVerticalScale = pTC->vertical_scale(); + dwIdentity = pTC->m_dwIdentity; + tp.m_dwIdentity = dwIdentity; + tp.m_pUserData = pTC->m_pUserData.As<CXFA_TextUserData>(); + tp.m_dwStatus = CFX_BreakType::Piece; + ++i; + } else if (iBidiLevel != pTC->m_iBidiLevel || + pTC->m_dwIdentity != dwIdentity) { + tp.m_iChars = i - tp.m_iStartChar; + m_pCurLine->m_LinePieces.push_back(tp); + + tp.m_iStartPos += tp.m_iWidth; + tp.m_iStartChar = i; + tpo.index = j++; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(tpo); + iBidiLevel = -1; + } else { + iCharWidth = pTC->m_iCharWidth; + if (iCharWidth > 0) + tp.m_iWidth += iCharWidth; + ++i; + } + } + + if (i > tp.m_iStartChar) { + tp.m_dwStatus = dwStatus; + tp.m_iChars = i - tp.m_iStartChar; + m_pCurLine->m_LinePieces.push_back(tp); + + tpo.index = j; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(tpo); + } + + std::sort(tpos->begin(), tpos->end()); + int32_t iStartPos = m_pCurLine->m_iStart; + for (const auto& it : *tpos) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it.index]; + ttp.m_iStartPos = iStartPos; + iStartPos += ttp.m_iWidth; + } +} + +void CFX_RTFBreak::EndBreak_Alignment(const std::deque<FX_TPO>& tpos, + bool bAllChars, + CFX_BreakType dwStatus) { + int32_t iNetWidth = m_pCurLine->m_iWidth; + int32_t iGapChars = 0; + bool bFind = false; + for (auto it = tpos.rbegin(); it != tpos.rend(); it++) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index]; + if (!bFind) + iNetWidth = ttp.GetEndPos(); + + bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); + int32_t j = bArabic ? 0 : ttp.m_iChars - 1; + while (j > -1 && j < ttp.m_iChars) { + const CFX_Char* tc = ttp.GetChar(j); + if (tc->m_nBreakType == FX_LBT_DIRECT_BRK) + ++iGapChars; + + if (!bFind || !bAllChars) { + uint32_t dwCharType = tc->GetCharType(); + if (dwCharType == FX_CHARTYPE_Space || + dwCharType == FX_CHARTYPE_Control) { + if (!bFind) { + int32_t iCharWidth = tc->m_iCharWidth; + if (bAllChars && iCharWidth > 0) + iNetWidth -= iCharWidth; + } + } else { + bFind = true; + if (!bAllChars) + break; + } + } + j += bArabic ? 1 : -1; + } + if (!bAllChars && bFind) + break; + } + + int32_t iOffset = m_iLineWidth - iNetWidth; + if (iGapChars > 0 && (m_iAlignment == CFX_RTFLineAlignment::Distributed || + (m_iAlignment == CFX_RTFLineAlignment::Justified && + dwStatus != CFX_BreakType::Paragraph))) { + int32_t iStart = -1; + for (const auto& tpo : tpos) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; + if (iStart < 0) + iStart = ttp.m_iStartPos; + else + ttp.m_iStartPos = iStart; + + for (int32_t j = 0; j < ttp.m_iChars; ++j) { + CFX_Char* tc = ttp.GetChar(j); + if (tc->m_nBreakType != FX_LBT_DIRECT_BRK || tc->m_iCharWidth < 0) + continue; + + int32_t k = iOffset / iGapChars; + tc->m_iCharWidth += k; + ttp.m_iWidth += k; + iOffset -= k; + --iGapChars; + if (iGapChars < 1) + break; + } + iStart += ttp.m_iWidth; + } + } else if (m_iAlignment == CFX_RTFLineAlignment::Right || + m_iAlignment == CFX_RTFLineAlignment::Center) { + if (m_iAlignment == CFX_RTFLineAlignment::Center) + iOffset /= 2; + if (iOffset > 0) { + for (auto& ttp : m_pCurLine->m_LinePieces) + ttp.m_iStartPos += iOffset; + } + } +} + +int32_t CFX_RTFBreak::GetBreakPos(std::vector<CFX_Char>& tca, + int32_t& iEndPos, + bool bAllChars, + bool bOnlyBrk) { + int32_t iLength = pdfium::CollectionSize<int32_t>(tca) - 1; + if (iLength < 1) + return iLength; + + int32_t iBreak = -1; + int32_t iBreakPos = -1; + int32_t iIndirect = -1; + int32_t iIndirectPos = -1; + int32_t iLast = -1; + int32_t iLastPos = -1; + if (iEndPos <= m_iLineWidth) { + if (!bAllChars) + return iLength; + + iBreak = iLength; + iBreakPos = iEndPos; + } + + CFX_Char* pCharArray = tca.data(); + CFX_Char* pCur = pCharArray + iLength; + --iLength; + if (bAllChars) + pCur->m_nBreakType = FX_LBT_UNKNOWN; + + uint32_t nCodeProp = pCur->char_props(); + uint32_t nNext = nCodeProp & 0x003F; + int32_t iCharWidth = pCur->m_iCharWidth; + if (iCharWidth > 0) + iEndPos -= iCharWidth; + + while (iLength >= 0) { + pCur = pCharArray + iLength; + nCodeProp = pCur->char_props(); + uint32_t nCur = nCodeProp & 0x003F; + bool bNeedBreak = false; + FX_LINEBREAKTYPE eType; + if (nCur == kBreakPropertyTB) { + bNeedBreak = true; + eType = nNext == kBreakPropertyTB + ? FX_LBT_PROHIBITED_BRK + : gs_FX_LineBreak_PairTable[nCur][nNext]; + } else { + if (nCur == kBreakPropertySpace) + bNeedBreak = true; + + eType = nNext == kBreakPropertySpace + ? FX_LBT_PROHIBITED_BRK + : gs_FX_LineBreak_PairTable[nCur][nNext]; + } + if (bAllChars) + pCur->m_nBreakType = eType; + + if (!bOnlyBrk) { + iCharWidth = pCur->m_iCharWidth; + if (iEndPos <= m_iLineWidth || bNeedBreak) { + if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) { + iBreak = iLength; + iBreakPos = iEndPos; + if (!bAllChars) + return iLength; + } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) { + iIndirect = iLength; + iIndirectPos = iEndPos; + } + if (iLast < 0) { + iLast = iLength; + iLastPos = iEndPos; + } + } + if (iCharWidth > 0) + iEndPos -= iCharWidth; + } + nNext = nCodeProp & 0x003F; + --iLength; + } + if (bOnlyBrk) + return 0; + + if (iBreak > -1) { + iEndPos = iBreakPos; + return iBreak; + } + if (iIndirect > -1) { + iEndPos = iIndirectPos; + return iIndirect; + } + if (iLast > -1) { + iEndPos = iLastPos; + return iLast; + } + return 0; +} + +void CFX_RTFBreak::SplitTextLine(CFX_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars) { + ASSERT(pCurLine && pNextLine); + int32_t iCount = pCurLine->CountChars(); + if (iCount < 2) + return; + + int32_t iEndPos = pCurLine->GetLineEnd(); + std::vector<CFX_Char>& curChars = pCurLine->m_LineChars; + int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); + if (iCharPos < 0) + iCharPos = 0; + + ++iCharPos; + if (iCharPos >= iCount) { + pNextLine->Clear(); + curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; + return; + } + + pNextLine->m_LineChars = + std::vector<CFX_Char>(curChars.begin() + iCharPos, curChars.end()); + curChars.erase(curChars.begin() + iCharPos, curChars.end()); + pNextLine->m_iStart = pCurLine->m_iStart; + pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos; + pCurLine->m_iWidth = iEndPos; + curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; + + for (size_t i = 0; i < pNextLine->m_LineChars.size(); ++i) { + if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { + pCurLine->m_iArabicChars--; + pNextLine->m_iArabicChars++; + } + pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None; + } +} + +int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode) const { + if (!pText || pText->iLength < 1) + return 0; + + ASSERT(pText->pFont && pText->pRect); + + RetainPtr<CFGAS_GEFont> pFont = pText->pFont; + CFX_RectF rtText(*pText->pRect); + bool bRTLPiece = FX_IsOdd(pText->iBidiLevel); + float fFontSize = pText->fFontSize; + int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); + int32_t iAscent = pFont->GetAscent(); + int32_t iDescent = pFont->GetDescent(); + int32_t iMaxHeight = iAscent - iDescent; + float fFontHeight = fFontSize; + float fAscent = fFontHeight * static_cast<float>(iAscent) / + static_cast<float>(iMaxHeight); + wchar_t wPrev = 0xFEFF; + wchar_t wNext; + float fX = rtText.left; + int32_t iHorScale = pText->iHorizontalScale; + int32_t iVerScale = pText->iVerticalScale; + if (bRTLPiece) + fX = rtText.right(); + + float fY = rtText.top + fAscent; + int32_t iCount = 0; + for (int32_t i = 0; i < pText->iLength; ++i) { + wchar_t wch = pText->pStr[i]; + int32_t iWidth = pText->pWidths[i]; + uint32_t dwProps = FX_GetUnicodeProperties(wch); + uint32_t dwCharType = (dwProps & FX_CHARTYPEBITSMASK); + if (iWidth == 0) { + if (dwCharType == FX_CHARTYPE_ArabicAlef) + wPrev = 0xFEFF; + continue; + } + + int32_t iCharWidth = abs(iWidth); + bool bEmptyChar = + (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control); + if (!bEmptyChar) + ++iCount; + + if (pCharPos) { + iCharWidth /= iFontSize; + wchar_t wForm = wch; + if (dwCharType >= FX_CHARTYPE_ArabicAlef) { + if (i + 1 < pText->iLength) { + wNext = pText->pStr[i + 1]; + if (pText->pWidths[i + 1] < 0 && i + 2 < pText->iLength) + wNext = pText->pStr[i + 2]; + } else { + wNext = 0xFEFF; + } + wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); + } else if (bRTLPiece) { + wForm = FX_GetMirrorChar(wch, dwProps); + } + dwProps = FX_GetUnicodeProperties(wForm); + + if (!bEmptyChar) { + if (bCharCode) { + pCharPos->m_GlyphIndex = wch; + } else { + pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm); + if (pCharPos->m_GlyphIndex == 0xFFFF) + pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch); + } +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; +#endif + pCharPos->m_FontCharWidth = iCharWidth; + } + + float fCharWidth = fFontSize * iCharWidth / 1000.0f; + if (bRTLPiece && dwCharType != FX_CHARTYPE_Combination) + fX -= fCharWidth; + + if (!bEmptyChar) + pCharPos->m_Origin = CFX_PointF(fX, fY); + if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) + fX += fCharWidth; + + if (!bEmptyChar) { + pCharPos->m_bGlyphAdjust = true; + pCharPos->m_AdjustMatrix[0] = -1; + pCharPos->m_AdjustMatrix[1] = 0; + pCharPos->m_AdjustMatrix[2] = 0; + pCharPos->m_AdjustMatrix[3] = 1; + pCharPos->m_Origin.y += fAscent * iVerScale / 100.0f; + pCharPos->m_Origin.y -= fAscent; + + if (iHorScale != 100 || iVerScale != 100) { + pCharPos->m_AdjustMatrix[0] = + pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f; + pCharPos->m_AdjustMatrix[1] = + pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f; + pCharPos->m_AdjustMatrix[2] = + pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f; + pCharPos->m_AdjustMatrix[3] = + pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f; + } + ++pCharPos; + } + } + if (iWidth > 0) + wPrev = wch; + } + return iCount; +} + +FX_RTFTEXTOBJ::FX_RTFTEXTOBJ() + : pFont(nullptr), + pRect(nullptr), + wLineBreakChar(L'\n'), + fFontSize(12.0f), + iLength(0), + iBidiLevel(0), + iHorizontalScale(100), + iVerticalScale(100) {} + +FX_RTFTEXTOBJ::~FX_RTFTEXTOBJ() {} diff --git a/xfa/fgas/layout/cfx_rtfbreak.h b/xfa/fgas/layout/cfx_rtfbreak.h new file mode 100644 index 0000000000000000000000000000000000000000..67052d23adf791f70d7310684c144116b97b346f --- /dev/null +++ b/xfa/fgas/layout/cfx_rtfbreak.h @@ -0,0 +1,98 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_LAYOUT_CFX_RTFBREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_RTFBREAK_H_ + +#include <deque> +#include <vector> + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_unicode.h" +#include "core/fxcrt/retain_ptr.h" +#include "xfa/fgas/layout/cfx_break.h" +#include "xfa/fxfa/cxfa_textuserdata.h" + +class CFGAS_GEFont; +class FXTEXT_CHARPOS; + +enum class CFX_RTFLineAlignment { + Left = 0, + Center, + Right, + Justified, + Distributed +}; + +struct FX_RTFTEXTOBJ { + FX_RTFTEXTOBJ(); + ~FX_RTFTEXTOBJ(); + + WideString pStr; + std::vector<int32_t> pWidths; + RetainPtr<CFGAS_GEFont> pFont; + const CFX_RectF* pRect; + wchar_t wLineBreakChar; + float fFontSize; + int32_t iLength; + int32_t iBidiLevel; + int32_t iHorizontalScale; + int32_t iVerticalScale; +}; + +class CFX_RTFBreak : public CFX_Break { + public: + explicit CFX_RTFBreak(uint32_t dwLayoutStyles); + ~CFX_RTFBreak() override; + + void SetLineStartPos(float fLinePos); + + void SetAlignment(CFX_RTFLineAlignment align) { m_iAlignment = align; } + void SetUserData(const RetainPtr<CXFA_TextUserData>& pUserData); + + void AddPositionedTab(float fTabPos); + + CFX_BreakType EndBreak(CFX_BreakType dwStatus); + + int32_t GetDisplayPos(const FX_RTFTEXTOBJ* pText, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode) const; + + CFX_BreakType AppendChar(wchar_t wch); + + CFX_BreakLine* GetCurrentLineForTesting() const { return m_pCurLine; } + + private: + void AppendChar_Combination(CFX_Char* pCurChar); + void AppendChar_Tab(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Control(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Arabic(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Others(CFX_Char* pCurChar); + int32_t GetLastPositionedTab() const; + bool GetPositionedTab(int32_t* iTabPos) const; + + int32_t GetBreakPos(std::vector<CFX_Char>& tca, + int32_t& iEndPos, + bool bAllChars, + bool bOnlyBrk); + void SplitTextLine(CFX_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars); + bool EndBreak_SplitLine(CFX_BreakLine* pNextLine, + bool bAllChars, + CFX_BreakType dwStatus); + void EndBreak_BidiLine(std::deque<FX_TPO>* tpos, CFX_BreakType dwStatus); + void EndBreak_Alignment(const std::deque<FX_TPO>& tpos, + bool bAllChars, + CFX_BreakType dwStatus); + + bool m_bPagination; + std::vector<int32_t> m_PositionedTabs; + CFX_RTFLineAlignment m_iAlignment; + RetainPtr<CXFA_TextUserData> m_pUserData; +}; + +#endif // XFA_FGAS_LAYOUT_CFX_RTFBREAK_H_ diff --git a/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f24631315e79b1157e436cc4ae62ed1c0abadcc --- /dev/null +++ b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp @@ -0,0 +1,74 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_rtfbreak.h" + +#include <memory> + +#include "core/fxge/cfx_gemodule.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +class CFX_RTFBreakTest : public testing::Test { + public: + void SetUp() override { + font_ = + CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0, GetGlobalFontManager()); + ASSERT(font_.Get() != nullptr); + } + + std::unique_ptr<CFX_RTFBreak> CreateBreak(int32_t args) { + auto b = pdfium::MakeUnique<CFX_RTFBreak>(args); + b->SetFont(font_); + return b; + } + + private: + RetainPtr<CFGAS_GEFont> font_; +}; + +// As soon as you get one of the control characters the break is complete +// and must be consumed before you get any more characters .... + +TEST_F(CFX_RTFBreakTest, AddChars) { + auto b = CreateBreak(FX_LAYOUTSTYLE_ExpandTab); + + WideString str(L"Input String."); + for (const auto& c : str) + EXPECT_EQ(CFX_BreakType::None, b->AppendChar(c)); + + EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(L'\n')); + ASSERT_EQ(1, b->CountBreakPieces()); + EXPECT_EQ(str + L"\n", b->GetBreakPieceUnstable(0)->GetString()); + + b->ClearBreakPieces(); + b->Reset(); + EXPECT_EQ(0, b->GetCurrentLineForTesting()->GetLineEnd()); + + str = L"Second str."; + for (const auto& c : str) + EXPECT_EQ(CFX_BreakType::None, b->AppendChar(c)); + + // Force the end of the break at the end of the string. + b->EndBreak(CFX_BreakType::Paragraph); + ASSERT_EQ(1, b->CountBreakPieces()); + EXPECT_EQ(str, b->GetBreakPieceUnstable(0)->GetString()); +} + +TEST_F(CFX_RTFBreakTest, ControlCharacters) { + auto b = CreateBreak(FX_LAYOUTSTYLE_ExpandTab); + EXPECT_EQ(CFX_BreakType::Line, b->AppendChar(L'\v')); + EXPECT_EQ(CFX_BreakType::Page, b->AppendChar(L'\f')); + // 0x2029 is the Paragraph Separator unicode character. + EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(0x2029)); + EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(L'\n')); + + ASSERT_EQ(1, b->CountBreakPieces()); + EXPECT_EQ(L"\v", b->GetBreakPieceUnstable(0)->GetString()); +} diff --git a/xfa/fgas/layout/cfx_txtbreak.cpp b/xfa/fgas/layout/cfx_txtbreak.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b028c9baf68a48d0241574f37ecbc3c8c1aa11dd --- /dev/null +++ b/xfa/fgas/layout/cfx_txtbreak.cpp @@ -0,0 +1,998 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fgas/layout/cfx_txtbreak.h" + +#include <algorithm> + +#include "core/fxcrt/fx_arabic.h" +#include "core/fxcrt/fx_bidi.h" +#include "core/fxcrt/fx_memory.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fde/cfde_texteditengine.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/layout/cfx_linebreak.h" + +namespace { + +bool IsCtrlCode(wchar_t ch) { + uint32_t dwRet = (FX_GetUnicodeProperties(ch) & FX_CHARTYPEBITSMASK); + return dwRet == FX_CHARTYPE_Tab || dwRet == FX_CHARTYPE_Control; +} + +} // namespace + +CFX_TxtBreak::CFX_TxtBreak() + : CFX_Break(FX_LAYOUTSTYLE_None), + m_iAlignment(CFX_TxtLineAlignment_Left), + m_iCombWidth(360000) {} + +CFX_TxtBreak::~CFX_TxtBreak() {} + +void CFX_TxtBreak::SetLineWidth(float fLineWidth) { + m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f); + ASSERT(m_iLineWidth >= 20000); +} + +void CFX_TxtBreak::SetAlignment(int32_t iAlignment) { + ASSERT(iAlignment >= CFX_TxtLineAlignment_Left && + iAlignment <= CFX_TxtLineAlignment_Justified); + m_iAlignment = iAlignment; +} + +void CFX_TxtBreak::SetCombWidth(float fCombWidth) { + m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f); +} + +void CFX_TxtBreak::AppendChar_Combination(CFX_Char* pCurChar) { + wchar_t wch = pCurChar->char_code(); + wchar_t wForm; + int32_t iCharWidth = 0; + pCurChar->m_iCharWidth = -1; + if (m_bCombText) { + iCharWidth = m_iCombWidth; + } else { + wForm = wch; + CFX_Char* pLastChar = GetLastChar(0, false, false); + if (pLastChar && + (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) { + bool bShadda = false; + if (wch == 0x0651) { + wchar_t wLast = pLastChar->char_code(); + if (wLast >= 0x064C && wLast <= 0x0650) { + wForm = FX_GetArabicFromShaddaTable(wLast); + bShadda = true; + } + } else if (wch >= 0x064C && wch <= 0x0650) { + if (pLastChar->char_code() == 0x0651) { + wForm = FX_GetArabicFromShaddaTable(wch); + bShadda = true; + } + } + if (bShadda) { + pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; + pLastChar->m_iCharWidth = 0; + pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; + } + } + if (!m_pFont->GetCharWidth(wForm, iCharWidth)) + iCharWidth = 0; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + } + pCurChar->m_iCharWidth = -iCharWidth; +} + +void CFX_TxtBreak::AppendChar_Tab(CFX_Char* pCurChar) { + m_eCharType = FX_CHARTYPE_Tab; +} + +CFX_BreakType CFX_TxtBreak::AppendChar_Control(CFX_Char* pCurChar) { + m_eCharType = FX_CHARTYPE_Control; + CFX_BreakType dwRet = CFX_BreakType::None; + if (!m_bSingleLine) { + wchar_t wch = pCurChar->char_code(); + switch (wch) { + case L'\v': + case 0x2028: + dwRet = CFX_BreakType::Line; + break; + case L'\f': + dwRet = CFX_BreakType::Page; + break; + case 0x2029: + dwRet = CFX_BreakType::Paragraph; + break; + default: + if (wch == m_wParagraphBreakChar) + dwRet = CFX_BreakType::Paragraph; + break; + } + if (dwRet != CFX_BreakType::None) + dwRet = EndBreak(dwRet); + } + return dwRet; +} + +CFX_BreakType CFX_TxtBreak::AppendChar_Arabic(CFX_Char* pCurChar) { + FX_CHARTYPE chartype = pCurChar->GetCharType(); + int32_t& iLineWidth = m_pCurLine->m_iWidth; + wchar_t wForm; + int32_t iCharWidth = 0; + CFX_Char* pLastChar = nullptr; + bool bAlef = false; + if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef && + m_eCharType <= FX_CHARTYPE_ArabicDistortion) { + pLastChar = GetLastChar(1, true, false); + if (pLastChar) { + iCharWidth = pLastChar->m_iCharWidth; + if (iCharWidth > 0) + iLineWidth -= iCharWidth; + + CFX_Char* pPrevChar = GetLastChar(2, true, false); + wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); + bAlef = (wForm == 0xFEFF && + pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); + m_pFont->GetCharWidth(wForm, iCharWidth); + + if (wForm == 0xFEFF) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + pLastChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; + iCharWidth = 0; + } + } + + m_eCharType = chartype; + wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, + nullptr); + if (m_bCombText) { + iCharWidth = m_iCombWidth; + } else { + m_pFont->GetCharWidth(wForm, iCharWidth); + + if (wForm == 0xFEFF) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + } + pCurChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; + m_pCurLine->m_iArabicChars++; + if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) + return EndBreak(CFX_BreakType::Line); + return CFX_BreakType::None; +} + +CFX_BreakType CFX_TxtBreak::AppendChar_Others(CFX_Char* pCurChar) { + FX_CHARTYPE chartype = pCurChar->GetCharType(); + int32_t& iLineWidth = m_pCurLine->m_iWidth; + int32_t iCharWidth = 0; + m_eCharType = chartype; + wchar_t wch = pCurChar->char_code(); + wchar_t wForm = wch; + + if (m_bCombText) { + iCharWidth = m_iCombWidth; + } else { + if (!m_pFont->GetCharWidth(wForm, iCharWidth)) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + } + + iCharWidth += m_iCharSpace; + pCurChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; + if (!m_bSingleLine && chartype != FX_CHARTYPE_Space && + iLineWidth > m_iLineWidth + m_iTolerance) { + return EndBreak(CFX_BreakType::Line); + } + + return CFX_BreakType::None; +} + +CFX_BreakType CFX_TxtBreak::AppendChar(wchar_t wch) { + uint32_t dwProps = FX_GetUnicodeProperties(wch); + FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); + m_pCurLine->m_LineChars.emplace_back(wch, dwProps, m_iHorizontalScale, + m_iVerticalScale); + CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back(); + pCurChar->m_dwCharStyles = m_iAlignment | (1 << 8); + + CFX_BreakType dwRet1 = CFX_BreakType::None; + if (chartype != FX_CHARTYPE_Combination && + GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && + m_eCharType != FX_CHARTYPE_Unknown && + m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine && + (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { + dwRet1 = EndBreak(CFX_BreakType::Line); + int32_t iCount = m_pCurLine->CountChars(); + if (iCount > 0) + pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; + } + + CFX_BreakType dwRet2 = CFX_BreakType::None; + if (wch == m_wParagraphBreakChar) { + // This is handled in AppendChar_Control, but it seems like \n and \r + // don't get matched as control characters so we go into AppendChar_other + // and never detect the new paragraph ... + dwRet2 = CFX_BreakType::Paragraph; + } else { + switch (chartype) { + case FX_CHARTYPE_Tab: + AppendChar_Tab(pCurChar); + break; + case FX_CHARTYPE_Control: + dwRet2 = AppendChar_Control(pCurChar); + break; + case FX_CHARTYPE_Combination: + AppendChar_Combination(pCurChar); + break; + case FX_CHARTYPE_ArabicAlef: + case FX_CHARTYPE_ArabicSpecial: + case FX_CHARTYPE_ArabicDistortion: + case FX_CHARTYPE_ArabicNormal: + case FX_CHARTYPE_ArabicForm: + case FX_CHARTYPE_Arabic: + dwRet2 = AppendChar_Arabic(pCurChar); + break; + case FX_CHARTYPE_Unknown: + case FX_CHARTYPE_Space: + case FX_CHARTYPE_Numeric: + case FX_CHARTYPE_Normal: + default: + dwRet2 = AppendChar_Others(pCurChar); + break; + } + } + return std::max(dwRet1, dwRet2); +} + +bool CFX_TxtBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine, + bool bAllChars) { + int32_t iCount = m_pCurLine->CountChars(); + bool bDone = false; + CFX_Char* pTC; + if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) { + pTC = m_pCurLine->GetChar(iCount - 1); + switch (pTC->GetCharType()) { + case FX_CHARTYPE_Tab: + case FX_CHARTYPE_Control: + case FX_CHARTYPE_Space: + break; + default: + SplitTextLine(m_pCurLine, pNextLine, bAllChars); + bDone = true; + break; + } + } + + iCount = m_pCurLine->CountChars(); + CFX_BreakPiece tp; + if (bAllChars && !bDone) { + int32_t iEndPos = m_pCurLine->m_iWidth; + GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, true); + } + return false; +} + +void CFX_TxtBreak::EndBreak_BidiLine(std::deque<FX_TPO>* tpos, + CFX_BreakType dwStatus) { + CFX_BreakPiece tp; + FX_TPO tpo; + CFX_Char* pTC; + std::vector<CFX_Char>& chars = m_pCurLine->m_LineChars; + int32_t iCount = m_pCurLine->CountChars(); + bool bDone = m_pCurLine->m_iArabicChars > 0; + if (bDone) { + ASSERT(iCount >= 0); + + size_t iBidiNum = 0; + for (size_t i = 0; i < static_cast<size_t>(iCount); ++i) { + pTC = &chars[i]; + pTC->m_iBidiPos = static_cast<int32_t>(i); + if (pTC->GetCharType() != FX_CHARTYPE_Control) + iBidiNum = i; + if (i == 0) + pTC->m_iBidiLevel = 1; + } + FX_BidiLine(&chars, iBidiNum + 1); + } + + if (bDone) { + tp.m_dwStatus = CFX_BreakType::Piece; + tp.m_iStartPos = m_pCurLine->m_iStart; + tp.m_pChars = &m_pCurLine->m_LineChars; + int32_t iBidiLevel = -1; + int32_t iCharWidth; + int32_t i = 0; + int32_t j = -1; + while (i < iCount) { + pTC = &chars[i]; + if (iBidiLevel < 0) { + iBidiLevel = pTC->m_iBidiLevel; + tp.m_iWidth = 0; + tp.m_iBidiLevel = iBidiLevel; + tp.m_iBidiPos = pTC->m_iBidiOrder; + tp.m_dwCharStyles = pTC->m_dwCharStyles; + tp.m_iHorizontalScale = pTC->horizonal_scale(); + tp.m_iVerticalScale = pTC->vertical_scale(); + tp.m_dwStatus = CFX_BreakType::Piece; + } + if (iBidiLevel != pTC->m_iBidiLevel || + pTC->m_dwStatus != CFX_BreakType::None) { + if (iBidiLevel == pTC->m_iBidiLevel) { + tp.m_dwStatus = pTC->m_dwStatus; + iCharWidth = pTC->m_iCharWidth; + if (iCharWidth > 0) + tp.m_iWidth += iCharWidth; + + i++; + } + tp.m_iChars = i - tp.m_iStartChar; + m_pCurLine->m_LinePieces.push_back(tp); + tp.m_iStartPos += tp.m_iWidth; + tp.m_iStartChar = i; + tpo.index = ++j; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(tpo); + iBidiLevel = -1; + } else { + iCharWidth = pTC->m_iCharWidth; + if (iCharWidth > 0) + tp.m_iWidth += iCharWidth; + + i++; + } + } + if (i > tp.m_iStartChar) { + tp.m_dwStatus = dwStatus; + tp.m_iChars = i - tp.m_iStartChar; + m_pCurLine->m_LinePieces.push_back(tp); + tpo.index = ++j; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(tpo); + } + if (j > -1) { + if (j > 0) { + std::sort(tpos->begin(), tpos->end()); + int32_t iStartPos = 0; + for (i = 0; i <= j; i++) { + tpo = (*tpos)[i]; + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; + ttp.m_iStartPos = iStartPos; + iStartPos += ttp.m_iWidth; + } + } + m_pCurLine->m_LinePieces[j].m_dwStatus = dwStatus; + } + } else { + tp.m_dwStatus = dwStatus; + tp.m_iStartPos = m_pCurLine->m_iStart; + tp.m_iWidth = m_pCurLine->m_iWidth; + tp.m_iStartChar = 0; + tp.m_iChars = iCount; + tp.m_pChars = &m_pCurLine->m_LineChars; + pTC = &chars[0]; + tp.m_dwCharStyles = pTC->m_dwCharStyles; + tp.m_iHorizontalScale = pTC->horizonal_scale(); + tp.m_iVerticalScale = pTC->vertical_scale(); + m_pCurLine->m_LinePieces.push_back(tp); + tpos->push_back({0, 0}); + } +} + +void CFX_TxtBreak::EndBreak_Alignment(const std::deque<FX_TPO>& tpos, + bool bAllChars, + CFX_BreakType dwStatus) { + int32_t iNetWidth = m_pCurLine->m_iWidth; + int32_t iGapChars = 0; + bool bFind = false; + for (auto it = tpos.rbegin(); it != tpos.rend(); ++it) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index]; + if (!bFind) + iNetWidth = ttp.GetEndPos(); + + bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); + int32_t j = bArabic ? 0 : ttp.m_iChars - 1; + while (j > -1 && j < ttp.m_iChars) { + const CFX_Char* pTC = ttp.GetChar(j); + if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) + iGapChars++; + if (!bFind || !bAllChars) { + FX_CHARTYPE chartype = pTC->GetCharType(); + if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) { + if (!bFind && bAllChars && pTC->m_iCharWidth > 0) + iNetWidth -= pTC->m_iCharWidth; + } else { + bFind = true; + if (!bAllChars) + break; + } + } + j += bArabic ? 1 : -1; + } + if (!bAllChars && bFind) + break; + } + + int32_t iOffset = m_iLineWidth - iNetWidth; + if (iGapChars > 0 && m_iAlignment & CFX_TxtLineAlignment_Justified && + dwStatus != CFX_BreakType::Paragraph) { + int32_t iStart = -1; + for (auto& tpo : tpos) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; + if (iStart < -1) + iStart = ttp.m_iStartPos; + else + ttp.m_iStartPos = iStart; + + for (int32_t j = 0; j < ttp.m_iChars; j++) { + CFX_Char* pTC = ttp.GetChar(j); + if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) + continue; + + int32_t k = iOffset / iGapChars; + pTC->m_iCharWidth += k; + ttp.m_iWidth += k; + iOffset -= k; + iGapChars--; + if (iGapChars < 1) + break; + } + iStart += ttp.m_iWidth; + } + } else if (m_iAlignment & CFX_TxtLineAlignment_Center || + m_iAlignment & CFX_TxtLineAlignment_Right) { + if (m_iAlignment & CFX_TxtLineAlignment_Center && + !(m_iAlignment & CFX_TxtLineAlignment_Right)) { + iOffset /= 2; + } + if (iOffset > 0) { + for (auto& ttp : m_pCurLine->m_LinePieces) + ttp.m_iStartPos += iOffset; + } + } +} + +CFX_BreakType CFX_TxtBreak::EndBreak(CFX_BreakType dwStatus) { + ASSERT(dwStatus != CFX_BreakType::None); + + if (!m_pCurLine->m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus; + return m_pCurLine->m_LinePieces.back().m_dwStatus; + } + + if (HasLine()) { + if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus; + return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus; + } + return CFX_BreakType::None; + } + + int32_t iCount = m_pCurLine->CountChars(); + if (iCount < 1) + return CFX_BreakType::None; + + m_pCurLine->GetChar(iCount - 1)->m_dwStatus = dwStatus; + if (dwStatus == CFX_BreakType::Piece) + return dwStatus; + + m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1; + CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex]; + bool bAllChars = m_iAlignment > CFX_TxtLineAlignment_Right; + if (!EndBreak_SplitLine(pNextLine, bAllChars)) { + std::deque<FX_TPO> tpos; + EndBreak_BidiLine(&tpos, dwStatus); + if (m_iAlignment > CFX_TxtLineAlignment_Left) + EndBreak_Alignment(tpos, bAllChars, dwStatus); + } + + m_pCurLine = pNextLine; + CFX_Char* pTC = GetLastChar(0, false, false); + m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; + + return dwStatus; +} + +int32_t CFX_TxtBreak::GetBreakPos(std::vector<CFX_Char>& ca, + int32_t& iEndPos, + bool bAllChars, + bool bOnlyBrk) { + int32_t iLength = pdfium::CollectionSize<int32_t>(ca) - 1; + if (iLength < 1) + return iLength; + + int32_t iBreak = -1; + int32_t iBreakPos = -1; + int32_t iIndirect = -1; + int32_t iIndirectPos = -1; + int32_t iLast = -1; + int32_t iLastPos = -1; + if (m_bSingleLine || iEndPos <= m_iLineWidth) { + if (!bAllChars) + return iLength; + + iBreak = iLength; + iBreakPos = iEndPos; + } + + FX_LINEBREAKTYPE eType; + uint32_t nCodeProp; + uint32_t nCur; + uint32_t nNext; + CFX_Char* pCur = &ca[iLength--]; + if (bAllChars) + pCur->m_nBreakType = FX_LBT_UNKNOWN; + + nCodeProp = pCur->char_props(); + nNext = nCodeProp & 0x003F; + int32_t iCharWidth = pCur->m_iCharWidth; + if (iCharWidth > 0) + iEndPos -= iCharWidth; + + while (iLength >= 0) { + pCur = &ca[iLength]; + nCodeProp = pCur->char_props(); + nCur = nCodeProp & 0x003F; + if (nNext == kBreakPropertySpace) + eType = FX_LBT_PROHIBITED_BRK; + else + eType = gs_FX_LineBreak_PairTable[nCur][nNext]; + if (bAllChars) + pCur->m_nBreakType = static_cast<uint8_t>(eType); + if (!bOnlyBrk) { + if (m_bSingleLine || iEndPos <= m_iLineWidth || + nCur == kBreakPropertySpace) { + if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) { + iBreak = iLength; + iBreakPos = iEndPos; + if (!bAllChars) + return iLength; + } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) { + iIndirect = iLength; + iIndirectPos = iEndPos; + } + if (iLast < 0) { + iLast = iLength; + iLastPos = iEndPos; + } + } + iCharWidth = pCur->m_iCharWidth; + if (iCharWidth > 0) + iEndPos -= iCharWidth; + } + nNext = nCodeProp & 0x003F; + iLength--; + } + if (bOnlyBrk) + return 0; + if (iBreak > -1) { + iEndPos = iBreakPos; + return iBreak; + } + if (iIndirect > -1) { + iEndPos = iIndirectPos; + return iIndirect; + } + if (iLast > -1) { + iEndPos = iLastPos; + return iLast; + } + return 0; +} + +void CFX_TxtBreak::SplitTextLine(CFX_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars) { + ASSERT(pCurLine && pNextLine); + int32_t iCount = pCurLine->CountChars(); + if (iCount < 2) + return; + + int32_t iEndPos = pCurLine->m_iWidth; + std::vector<CFX_Char>& curChars = pCurLine->m_LineChars; + int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); + if (iCharPos < 0) + iCharPos = 0; + + iCharPos++; + if (iCharPos >= iCount) { + pNextLine->Clear(); + CFX_Char* pTC = &curChars[iCharPos - 1]; + pTC->m_nBreakType = FX_LBT_UNKNOWN; + return; + } + + pNextLine->m_LineChars = + std::vector<CFX_Char>(curChars.begin() + iCharPos, curChars.end()); + curChars.erase(curChars.begin() + iCharPos, curChars.end()); + pCurLine->m_iWidth = iEndPos; + CFX_Char* pTC = &curChars[iCharPos - 1]; + pTC->m_nBreakType = FX_LBT_UNKNOWN; + iCount = pdfium::CollectionSize<int>(pNextLine->m_LineChars); + int32_t iWidth = 0; + for (int32_t i = 0; i < iCount; i++) { + if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { + pCurLine->m_iArabicChars--; + pNextLine->m_iArabicChars++; + } + iWidth += std::max(0, pNextLine->m_LineChars[i].m_iCharWidth); + pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None; + } + pNextLine->m_iWidth = iWidth; +} + +struct FX_FORMCHAR { + uint16_t wch; + uint16_t wForm; + int32_t iWidth; +}; + +int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun, + FXTEXT_CHARPOS* pCharPos) const { + if (!pTxtRun || pTxtRun->iLength < 1) + return 0; + + CFDE_TextEditEngine* pEngine = pTxtRun->pEdtEngine; + const wchar_t* pStr = pTxtRun->wsStr.c_str(); + int32_t* pWidths = pTxtRun->pWidths; + int32_t iLength = pTxtRun->iLength - 1; + RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont; + uint32_t dwStyles = pTxtRun->dwStyles; + CFX_RectF rtText(*pTxtRun->pRect); + bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0; + float fFontSize = pTxtRun->fFontSize; + int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); + int32_t iAscent = pFont->GetAscent(); + int32_t iDescent = pFont->GetDescent(); + int32_t iMaxHeight = iAscent - iDescent; + float fFontHeight = fFontSize; + float fAscent = fFontHeight * (float)iAscent / (float)iMaxHeight; + float fX = rtText.left; + float fY; + float fCharWidth; + int32_t iHorScale = pTxtRun->iHorizontalScale; + int32_t iVerScale = pTxtRun->iVerticalScale; + bool bSkipSpace = pTxtRun->bSkipSpace; + FX_FORMCHAR formChars[3]; + float fYBase; + + if (bRTLPiece) + fX = rtText.right(); + + fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f; + fY = fYBase + fAscent; + + int32_t iCount = 0; + int32_t iNext = 0; + wchar_t wPrev = 0xFEFF; + wchar_t wNext = 0xFEFF; + wchar_t wForm = 0xFEFF; + wchar_t wLast = 0xFEFF; + bool bShadda = false; + bool bLam = false; + for (int32_t i = 0; i <= iLength; i++) { + int32_t iWidth; + wchar_t wch; + if (pEngine) { + wch = pEngine->GetChar(i); + iWidth = pEngine->GetWidthOfChar(i); + } else { + wch = *pStr++; + iWidth = *pWidths++; + } + + uint32_t dwProps = FX_GetUnicodeProperties(wch); + FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); + if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) { + wPrev = 0xFEFF; + wLast = wch; + continue; + } + + if (chartype >= FX_CHARTYPE_ArabicAlef) { + if (i < iLength) { + if (pEngine) { + iNext = i + 1; + while (iNext <= iLength) { + wNext = pEngine->GetChar(iNext); + dwProps = FX_GetUnicodeProperties(wNext); + if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination) + break; + + iNext++; + } + if (iNext > iLength) + wNext = 0xFEFF; + } else { + int32_t j = -1; + do { + j++; + if (i + j >= iLength) + break; + + wNext = pStr[j]; + dwProps = FX_GetUnicodeProperties(wNext); + } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination); + if (i + j >= iLength) + wNext = 0xFEFF; + } + } else { + wNext = 0xFEFF; + } + + wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); + bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647); + } else if (chartype == FX_CHARTYPE_Combination) { + wForm = wch; + if (wch >= 0x064C && wch <= 0x0651) { + if (bShadda) { + wForm = 0xFEFF; + bShadda = false; + } else { + wNext = 0xFEFF; + if (pEngine) { + iNext = i + 1; + if (iNext <= iLength) + wNext = pEngine->GetChar(iNext); + } else { + if (i < iLength) + wNext = *pStr; + } + if (wch == 0x0651) { + if (wNext >= 0x064C && wNext <= 0x0650) { + wForm = FX_GetArabicFromShaddaTable(wNext); + bShadda = true; + } + } else { + if (wNext == 0x0651) { + wForm = FX_GetArabicFromShaddaTable(wch); + bShadda = true; + } + } + } + } else { + bShadda = false; + } + } else if (chartype == FX_CHARTYPE_Numeric) { + wForm = wch; + } else if (wch == L'.') { + wForm = wch; + } else if (wch == L',') { + wForm = wch; + } else if (bRTLPiece) { + wForm = FX_GetMirrorChar(wch, dwProps); + } else { + wForm = wch; + } + if (chartype != FX_CHARTYPE_Combination) + bShadda = false; + if (chartype < FX_CHARTYPE_ArabicAlef) + bLam = false; + + dwProps = FX_GetUnicodeProperties(wForm); + bool bEmptyChar = + (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control); + if (wForm == 0xFEFF) + bEmptyChar = true; + + int32_t iForms = bLam ? 3 : 1; + iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms; + if (!pCharPos) { + if (iWidth > 0) + wPrev = wch; + wLast = wch; + continue; + } + + int32_t iCharWidth = iWidth; + if (iCharWidth < 0) + iCharWidth = -iCharWidth; + + iCharWidth /= iFontSize; + formChars[0].wch = wch; + formChars[0].wForm = wForm; + formChars[0].iWidth = iCharWidth; + if (bLam) { + formChars[1].wForm = 0x0651; + iCharWidth = 0; + pFont->GetCharWidth(0x0651, iCharWidth); + formChars[1].iWidth = iCharWidth; + formChars[2].wForm = 0x0670; + iCharWidth = 0; + pFont->GetCharWidth(0x0670, iCharWidth); + formChars[2].iWidth = iCharWidth; + } + + for (int32_t j = 0; j < iForms; j++) { + wForm = (wchar_t)formChars[j].wForm; + iCharWidth = formChars[j].iWidth; + if (j > 0) { + chartype = FX_CHARTYPE_Combination; + wch = wForm; + wLast = (wchar_t)formChars[j - 1].wForm; + } + if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { + pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm); +#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ + pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; +#endif + pCharPos->m_FontCharWidth = iCharWidth; + } + + fCharWidth = fFontSize * iCharWidth / 1000.0f; + if (bRTLPiece && chartype != FX_CHARTYPE_Combination) + fX -= fCharWidth; + + if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { + pCharPos->m_Origin = CFX_PointF(fX, fY); + + if ((dwStyles & FX_LAYOUTSTYLE_CombText) != 0) { + int32_t iFormWidth = iCharWidth; + pFont->GetCharWidth(wForm, iFormWidth); + float fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f; + pCharPos->m_Origin.x += fOffset; + } + + if (chartype == FX_CHARTYPE_Combination) { + CFX_Rect rtBBox; + if (pFont->GetCharBBox(wForm, &rtBBox)) { + pCharPos->m_Origin.y = + fYBase + fFontSize - + fFontSize * (float)rtBBox.height / (float)iMaxHeight; + } + if (wForm == wch && wLast != 0xFEFF) { + uint32_t dwLastProps = FX_GetUnicodeProperties(wLast); + if ((dwLastProps & FX_CHARTYPEBITSMASK) == + FX_CHARTYPE_Combination) { + CFX_Rect rtBox; + if (pFont->GetCharBBox(wLast, &rtBox)) + pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight; + } + } + } + } + if (!bRTLPiece && chartype != FX_CHARTYPE_Combination) + fX += fCharWidth; + + if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { + pCharPos->m_bGlyphAdjust = true; + pCharPos->m_AdjustMatrix[0] = -1; + pCharPos->m_AdjustMatrix[1] = 0; + pCharPos->m_AdjustMatrix[2] = 0; + pCharPos->m_AdjustMatrix[3] = 1; + + if (iHorScale != 100 || iVerScale != 100) { + pCharPos->m_AdjustMatrix[0] = + pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f; + pCharPos->m_AdjustMatrix[1] = + pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f; + pCharPos->m_AdjustMatrix[2] = + pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f; + pCharPos->m_AdjustMatrix[3] = + pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f; + } + pCharPos++; + } + } + if (iWidth > 0) + wPrev = static_cast<wchar_t>(formChars[0].wch); + wLast = wch; + } + return iCount; +} + +std::vector<CFX_RectF> CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun, + bool bCharBBox) const { + if (!pTxtRun || pTxtRun->iLength < 1) + return std::vector<CFX_RectF>(); + + CFDE_TextEditEngine* pEngine = pTxtRun->pEdtEngine; + const wchar_t* pStr = pTxtRun->wsStr.c_str(); + int32_t* pWidths = pTxtRun->pWidths; + int32_t iLength = pTxtRun->iLength; + CFX_RectF rect(*pTxtRun->pRect); + float fFontSize = pTxtRun->fFontSize; + int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); + float fScale = fFontSize / 1000.0f; + RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont; + if (!pFont) + bCharBBox = false; + + CFX_Rect bbox; + if (bCharBBox) + bCharBBox = pFont->GetBBox(&bbox); + + float fLeft = std::max(0.0f, bbox.left * fScale); + float fHeight = fabs(bbox.height * fScale); + bool bRTLPiece = !!(pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel); + bool bSingleLine = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_SingleLine); + bool bCombText = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_CombText); + wchar_t wch; + int32_t iCharSize; + float fCharSize; + float fStart = bRTLPiece ? rect.right() : rect.left; + + std::vector<CFX_RectF> rtArray(iLength); + for (int32_t i = 0; i < iLength; i++) { + if (pEngine) { + wch = pEngine->GetChar(i); + iCharSize = pEngine->GetWidthOfChar(i); + } else { + wch = *pStr++; + iCharSize = *pWidths++; + } + fCharSize = static_cast<float>(iCharSize) / 20000.0f; + bool bRet = (!bSingleLine && IsCtrlCode(wch)); + if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 || + wch == L'\n')) { + bRet = false; + } + if (bRet) { + iCharSize = iFontSize * 500; + fCharSize = fFontSize / 2.0f; + } + rect.left = fStart; + if (bRTLPiece) { + rect.left -= fCharSize; + fStart -= fCharSize; + } else { + fStart += fCharSize; + } + rect.width = fCharSize; + + if (bCharBBox && !bRet) { + int32_t iCharWidth = 1000; + pFont->GetCharWidth(wch, iCharWidth); + float fRTLeft = 0, fCharWidth = 0; + if (iCharWidth > 0) { + fCharWidth = iCharWidth * fScale; + fRTLeft = fLeft; + if (bCombText) + fRTLeft = (rect.width - fCharWidth) / 2.0f; + } + CFX_RectF rtBBoxF; + rtBBoxF.left = rect.left + fRTLeft; + rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f; + rtBBoxF.width = fCharWidth; + rtBBoxF.height = fHeight; + rtBBoxF.top = std::max(rtBBoxF.top, 0.0f); + rtArray[i] = rtBBoxF; + continue; + } + rtArray[i] = rect; + } + return rtArray; +} + +FX_TXTRUN::FX_TXTRUN() + : pEdtEngine(nullptr), + pIdentity(nullptr), + pWidths(nullptr), + iLength(0), + pFont(nullptr), + fFontSize(12), + dwStyles(0), + iHorizontalScale(100), + iVerticalScale(100), + dwCharStyles(0), + pRect(nullptr), + bSkipSpace(true) {} + +FX_TXTRUN::~FX_TXTRUN() {} + +FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default; diff --git a/xfa/fgas/layout/cfx_txtbreak.h b/xfa/fgas/layout/cfx_txtbreak.h new file mode 100644 index 0000000000000000000000000000000000000000..e6f8da03d21109f37bfaeb801efde2622c2be509 --- /dev/null +++ b/xfa/fgas/layout/cfx_txtbreak.h @@ -0,0 +1,98 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FGAS_LAYOUT_CFX_TXTBREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_TXTBREAK_H_ + +#include <deque> +#include <memory> +#include <vector> + +#include "core/fxcrt/cfx_char.h" +#include "core/fxge/cfx_renderdevice.h" +#include "third_party/base/stl_util.h" +#include "xfa/fgas/layout/cfx_break.h" + +class CFDE_TextEditEngine; +class CFGAS_GEFont; +struct FDE_TEXTEDITPIECE; + +#define FX_TXTCHARSTYLE_ArabicShadda 0x0020 +#define FX_TXTCHARSTYLE_OddBidiLevel 0x0040 + +enum CFX_TxtLineAlignment { + CFX_TxtLineAlignment_Left = 0, + CFX_TxtLineAlignment_Center = 1 << 0, + CFX_TxtLineAlignment_Right = 1 << 1, + CFX_TxtLineAlignment_Justified = 1 << 2 +}; + +inline bool CFX_BreakTypeNoneOrPiece(CFX_BreakType type) { + return type == CFX_BreakType::None || type == CFX_BreakType::Piece; +} + +struct FX_TXTRUN { + FX_TXTRUN(); + FX_TXTRUN(const FX_TXTRUN& other); + ~FX_TXTRUN(); + + CFDE_TextEditEngine* pEdtEngine; + const FDE_TEXTEDITPIECE* pIdentity; + WideString wsStr; + int32_t* pWidths; + int32_t iLength; + RetainPtr<CFGAS_GEFont> pFont; + float fFontSize; + uint32_t dwStyles; + int32_t iHorizontalScale; + int32_t iVerticalScale; + uint32_t dwCharStyles; + const CFX_RectF* pRect; + bool bSkipSpace; +}; + +class CFX_TxtBreak : public CFX_Break { + public: + CFX_TxtBreak(); + ~CFX_TxtBreak() override; + + void SetLineWidth(float fLineWidth); + void SetAlignment(int32_t iAlignment); + void SetCombWidth(float fCombWidth); + CFX_BreakType EndBreak(CFX_BreakType dwStatus); + + int32_t GetDisplayPos(const FX_TXTRUN* pTxtRun, + FXTEXT_CHARPOS* pCharPos) const; + std::vector<CFX_RectF> GetCharRects(const FX_TXTRUN* pTxtRun, + bool bCharBBox = false) const; + CFX_BreakType AppendChar(wchar_t wch); + + private: + void AppendChar_Combination(CFX_Char* pCurChar); + void AppendChar_Tab(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Control(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Arabic(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Others(CFX_Char* pCurChar); + + void ResetContextCharStyles(); + bool EndBreak_SplitLine(CFX_BreakLine* pNextLine, bool bAllChars); + void EndBreak_BidiLine(std::deque<FX_TPO>* tpos, CFX_BreakType dwStatus); + void EndBreak_Alignment(const std::deque<FX_TPO>& tpos, + bool bAllChars, + CFX_BreakType dwStatus); + int32_t GetBreakPos(std::vector<CFX_Char>& ca, + int32_t& iEndPos, + bool bAllChars = false, + bool bOnlyBrk = false); + void SplitTextLine(CFX_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars = false); + + int32_t m_iAlignment; + int32_t m_iCombWidth; +}; + +#endif // XFA_FGAS_LAYOUT_CFX_TXTBREAK_H_ diff --git a/xfa/fgas/layout/fgas_linebreak.cpp b/xfa/fgas/layout/fgas_linebreak.cpp deleted file mode 100644 index 2a9e3be522eb7bf61a9a65c842da351adeb124c9..0000000000000000000000000000000000000000 --- a/xfa/fgas/layout/fgas_linebreak.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fgas/layout/fgas_linebreak.h" - -#include "core/fxcrt/fx_ucd.h" - -const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32] = { - {FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBPB, FX_LBPB, FX_LBPB, FX_LBCP, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBPB, FX_LBPB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBPB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBIB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBPB, - FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBPB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, - FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, - FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, - FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, - {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, - FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN}, -}; diff --git a/xfa/fgas/layout/fgas_linebreak.h b/xfa/fgas/layout/fgas_linebreak.h deleted file mode 100644 index 99333dfa47c496b10695b5e63ce546618f487ba5..0000000000000000000000000000000000000000 --- a/xfa/fgas/layout/fgas_linebreak.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_LAYOUT_FGAS_LINEBREAK_H_ -#define XFA_FGAS_LAYOUT_FGAS_LINEBREAK_H_ - -#include "core/fxcrt/fx_system.h" -#include "xfa/fgas/crt/fgas_utils.h" - -enum FX_LINEBREAKTYPE : uint8_t { - FX_LBT_UNKNOWN = 0x00, - FX_LBT_DIRECT_BRK = 0x1A, - FX_LBT_INDIRECT_BRK = 0x2B, - FX_LBT_COM_INDIRECT_BRK = 0x3C, - FX_LBT_COM_PROHIBITED_BRK = 0x4D, - FX_LBT_PROHIBITED_BRK = 0x5E, - FX_LBT_HANGUL_SPACE_BRK = 0x6F, -}; - -#define FX_LBUN FX_LBT_UNKNOWN -#define FX_LBDB FX_LBT_DIRECT_BRK -#define FX_LBIB FX_LBT_INDIRECT_BRK -#define FX_LBCB FX_LBT_COM_INDIRECT_BRK -#define FX_LBCP FX_LBT_COM_PROHIBITED_BRK -#define FX_LBPB FX_LBT_PROHIBITED_BRK -#define FX_LBHS FX_LBT_HANGUL_SPACE_BRK - -extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32]; - -#endif // XFA_FGAS_LAYOUT_FGAS_LINEBREAK_H_ diff --git a/xfa/fgas/layout/fgas_rtfbreak.cpp b/xfa/fgas/layout/fgas_rtfbreak.cpp deleted file mode 100644 index 9a83be65ac370258293b997d6c5f6b9c32e76fa2..0000000000000000000000000000000000000000 --- a/xfa/fgas/layout/fgas_rtfbreak.cpp +++ /dev/null @@ -1,1031 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fgas/layout/fgas_rtfbreak.h" - -#include <algorithm> - -#include "core/fxcrt/fx_arabic.h" -#include "core/fxcrt/fx_arb.h" -#include "third_party/base/stl_util.h" -#include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fgas/layout/fgas_linebreak.h" - -namespace { - -typedef CFX_RTFBreakType (CFX_RTFBreak::*FX_RTFBreak_LPFAppendChar)( - CFX_RTFChar* pCurChar); -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, -}; - -} // namespace - -CFX_RTFBreak::CFX_RTFBreak(uint32_t dwLayoutStyles) - : m_iBoundaryStart(0), - m_iBoundaryEnd(2000000), - m_dwLayoutStyles(dwLayoutStyles), - m_bPagination(false), - m_pFont(nullptr), - m_iFontHeight(240), - m_iFontSize(240), - m_iTabWidth(720000), - m_wDefChar(0xFEFF), - m_iDefChar(0), - m_wLineBreakChar(L'\n'), - m_iHorizontalScale(100), - m_iVerticalScale(100), - m_iCharSpace(0), - m_iAlignment(CFX_RTFLineAlignment::Left), - m_pUserData(nullptr), - m_eCharType(FX_CHARTYPE_Unknown), - m_dwIdentity(0), - m_RTFLine1(), - m_RTFLine2(), - m_pCurLine(nullptr), - m_iReady(0), - m_iTolerance(0) { - m_pCurLine = &m_RTFLine1; - - SetBreakStatus(); - m_bPagination = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_Pagination) != 0; -} - -CFX_RTFBreak::~CFX_RTFBreak() { - Reset(); -} - -void CFX_RTFBreak::SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd) { - if (fLineStart > fLineEnd) - return; - - m_iBoundaryStart = FXSYS_round(fLineStart * 20000.0f); - m_iBoundaryEnd = FXSYS_round(fLineEnd * 20000.0f); - m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iBoundaryEnd); - m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iBoundaryStart); -} - -void CFX_RTFBreak::SetLineStartPos(FX_FLOAT fLinePos) { - int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f); - iLinePos = std::min(iLinePos, m_iBoundaryEnd); - iLinePos = std::max(iLinePos, m_iBoundaryStart); - m_pCurLine->m_iStart = iLinePos; -} - -void CFX_RTFBreak::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) { - if (!pFont || pFont == m_pFont) - return; - - SetBreakStatus(); - m_pFont = pFont; - FontChanged(); -} - -void CFX_RTFBreak::SetFontSize(FX_FLOAT fFontSize) { - int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); - if (m_iFontSize == iFontSize) - return; - - SetBreakStatus(); - m_iFontSize = iFontSize; - FontChanged(); -} - -void CFX_RTFBreak::FontChanged() { - m_iDefChar = 0; - if (!m_pFont) - return; - - m_iFontHeight = m_iFontSize; - if (m_wDefChar == 0xFEFF) - return; - - m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false); - m_iDefChar *= m_iFontSize; -} - -void CFX_RTFBreak::SetTabWidth(FX_FLOAT fTabWidth) { - m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f); -} - -void CFX_RTFBreak::AddPositionedTab(FX_FLOAT fTabPos) { - int32_t iTabPos = std::min(FXSYS_round(fTabPos * 20000.0f) + m_iBoundaryStart, - m_iBoundaryEnd); - auto it = std::lower_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), - iTabPos); - if (it != m_PositionedTabs.end() && *it == iTabPos) - return; - m_PositionedTabs.insert(it, iTabPos); -} - -void CFX_RTFBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) { - m_iTolerance = FXSYS_round(fTolerance * 20000.0f); -} - -void CFX_RTFBreak::SetHorizontalScale(int32_t iScale) { - if (iScale < 0) - iScale = 0; - if (m_iHorizontalScale == iScale) - return; - - SetBreakStatus(); - m_iHorizontalScale = iScale; -} - -void CFX_RTFBreak::SetVerticalScale(int32_t iScale) { - if (iScale < 0) - iScale = 0; - if (m_iVerticalScale == iScale) - return; - - SetBreakStatus(); - m_iVerticalScale = iScale; -} - -void CFX_RTFBreak::SetCharSpace(FX_FLOAT fCharSpace) { - m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f); -} - -void CFX_RTFBreak::SetUserData(const CFX_RetainPtr<CFX_Retainable>& pUserData) { - if (m_pUserData == pUserData) - return; - - SetBreakStatus(); - m_pUserData = pUserData; -} - -void CFX_RTFBreak::SetBreakStatus() { - m_dwIdentity++; - int32_t iCount = m_pCurLine->CountChars(); - if (iCount < 1) - return; - - CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1); - if (tc.m_dwStatus == CFX_RTFBreakType::None) - tc.m_dwStatus = CFX_RTFBreakType::Piece; -} - -CFX_RTFChar* CFX_RTFBreak::GetLastChar(int32_t index) const { - std::vector<CFX_RTFChar>& tca = m_pCurLine->m_LineChars; - int32_t iCount = pdfium::CollectionSize<int32_t>(tca); - if (index < 0 || index >= iCount) - return nullptr; - - int32_t iStart = iCount - 1; - while (iStart > -1) { - CFX_RTFChar* pTC = &tca[iStart--]; - if (pTC->m_iCharWidth >= 0 || - pTC->GetCharType() != FX_CHARTYPE_Combination) { - if (--index < 0) - return pTC; - } - } - return nullptr; -} - -const CFX_RTFLine* CFX_RTFBreak::GetRTFLine() const { - if (m_iReady == 1) - return &m_RTFLine1; - if (m_iReady == 2) - return &m_RTFLine2; - return nullptr; -} - -const CFX_RTFPieceArray* CFX_RTFBreak::GetRTFPieces() const { - const CFX_RTFLine* pRTFLine = GetRTFLine(); - return pRTFLine ? &pRTFLine->m_LinePieces : nullptr; -} - -inline FX_CHARTYPE CFX_RTFBreak::GetUnifiedCharType( - FX_CHARTYPE chartype) const { - return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype; -} - -int32_t CFX_RTFBreak::GetLastPositionedTab() const { - return m_PositionedTabs.empty() ? m_iBoundaryStart : m_PositionedTabs.back(); -} - -bool CFX_RTFBreak::GetPositionedTab(int32_t* iTabPos) const { - auto it = std::upper_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), - *iTabPos); - if (it == m_PositionedTabs.end()) - return false; - - *iTabPos = *it; - return true; -} - -CFX_RTFBreakType CFX_RTFBreak::AppendChar(FX_WCHAR wch) { - ASSERT(m_pFont && m_pCurLine); - - uint32_t dwProps = kTextLayoutCodeProperties[static_cast<uint16_t>(wch)]; - FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); - m_pCurLine->m_LineChars.emplace_back(); - - CFX_RTFChar* pCurChar = &m_pCurLine->m_LineChars.back(); - pCurChar->m_dwStatus = CFX_RTFBreakType::None; - pCurChar->m_wCharCode = wch; - pCurChar->m_dwCharProps = dwProps; - pCurChar->m_iFontSize = m_iFontSize; - pCurChar->m_iFontHeight = m_iFontHeight; - pCurChar->m_iHorizontalScale = m_iHorizontalScale; - pCurChar->m_iVerticalScale = m_iVerticalScale; - pCurChar->m_iCharWidth = 0; - pCurChar->m_dwIdentity = m_dwIdentity; - pCurChar->m_pUserData = m_pUserData; - - CFX_RTFBreakType dwRet1 = CFX_RTFBreakType::None; - if (chartype != FX_CHARTYPE_Combination && - GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && - m_eCharType != FX_CHARTYPE_Unknown && - m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance && - (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { - dwRet1 = EndBreak(CFX_RTFBreakType::Line); - int32_t iCount = m_pCurLine->CountChars(); - if (iCount > 0) - pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; - } - - CFX_RTFBreakType dwRet2 = - (this->*g_FX_RTFBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])( - pCurChar); - m_eCharType = chartype; - return std::max(dwRet1, dwRet2); -} - -CFX_RTFBreakType CFX_RTFBreak::AppendChar_Combination(CFX_RTFChar* pCurChar) { - int32_t iCharWidth = 0; - if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, false)) - iCharWidth = 0; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - CFX_RTFChar* pLastChar = GetLastChar(0); - if (pLastChar && pLastChar->GetCharType() > FX_CHARTYPE_Combination) - iCharWidth = -iCharWidth; - else - m_eCharType = FX_CHARTYPE_Combination; - - pCurChar->m_iCharWidth = iCharWidth; - if (iCharWidth > 0) - m_pCurLine->m_iWidth += iCharWidth; - - return CFX_RTFBreakType::None; -} - -CFX_RTFBreakType CFX_RTFBreak::AppendChar_Tab(CFX_RTFChar* pCurChar) { - if (!(m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ExpandTab)) - return CFX_RTFBreakType::None; - - int32_t& iLineWidth = m_pCurLine->m_iWidth; - int32_t iCharWidth = iLineWidth; - if (GetPositionedTab(&iCharWidth)) - iCharWidth -= iLineWidth; - else - iCharWidth = m_iTabWidth * (iLineWidth / m_iTabWidth + 1) - iLineWidth; - - pCurChar->m_iCharWidth = iCharWidth; - iLineWidth += iCharWidth; - return CFX_RTFBreakType::None; -} - -CFX_RTFBreakType CFX_RTFBreak::AppendChar_Control(CFX_RTFChar* pCurChar) { - CFX_RTFBreakType dwRet2 = CFX_RTFBreakType::None; - switch (pCurChar->m_wCharCode) { - case L'\v': - case 0x2028: - dwRet2 = CFX_RTFBreakType::Line; - break; - case L'\f': - dwRet2 = CFX_RTFBreakType::Page; - break; - case 0x2029: - dwRet2 = CFX_RTFBreakType::Paragraph; - break; - default: - if (pCurChar->m_wCharCode == m_wLineBreakChar) - dwRet2 = CFX_RTFBreakType::Paragraph; - break; - } - if (dwRet2 != CFX_RTFBreakType::None) - dwRet2 = EndBreak(dwRet2); - - return dwRet2; -} - -CFX_RTFBreakType CFX_RTFBreak::AppendChar_Arabic(CFX_RTFChar* pCurChar) { - CFX_RTFChar* pLastChar = nullptr; - int32_t iCharWidth = 0; - FX_WCHAR wForm; - bool bAlef = false; - if (m_eCharType >= FX_CHARTYPE_ArabicAlef && - m_eCharType <= FX_CHARTYPE_ArabicDistortion) { - pLastChar = GetLastChar(1); - if (pLastChar) { - m_pCurLine->m_iWidth -= pLastChar->m_iCharWidth; - CFX_RTFChar* pPrevChar = GetLastChar(2); - wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); - bAlef = (wForm == 0xFEFF && - pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false) && - !m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth, false)) { - iCharWidth = m_iDefChar; - } - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - pLastChar->m_iCharWidth = iCharWidth; - m_pCurLine->m_iWidth += iCharWidth; - iCharWidth = 0; - } - } - - wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, - nullptr); - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false) && - !m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, false)) { - iCharWidth = m_iDefChar; - } - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - pCurChar->m_iCharWidth = iCharWidth; - m_pCurLine->m_iWidth += iCharWidth; - m_pCurLine->m_iArabicChars++; - - if (m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) - return EndBreak(CFX_RTFBreakType::Line); - return CFX_RTFBreakType::None; -} - -CFX_RTFBreakType CFX_RTFBreak::AppendChar_Others(CFX_RTFChar* pCurChar) { - FX_CHARTYPE chartype = pCurChar->GetCharType(); - FX_WCHAR wForm = pCurChar->m_wCharCode; - int32_t iCharWidth = 0; - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) - iCharWidth = m_iDefChar; - - iCharWidth *= m_iFontSize; - iCharWidth *= m_iHorizontalScale / 100; - iCharWidth += m_iCharSpace; - - pCurChar->m_iCharWidth = iCharWidth; - m_pCurLine->m_iWidth += iCharWidth; - if (chartype != FX_CHARTYPE_Space && - m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) { - return EndBreak(CFX_RTFBreakType::Line); - } - return CFX_RTFBreakType::None; -} - -CFX_RTFBreakType CFX_RTFBreak::EndBreak(CFX_RTFBreakType dwStatus) { - ASSERT(dwStatus != CFX_RTFBreakType::None); - - m_dwIdentity++; - const CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces; - int32_t iCount = pCurPieces->GetSize(); - if (iCount > 0) { - CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount); - if (dwStatus != CFX_RTFBreakType::Piece) - pLastPiece->m_dwStatus = dwStatus; - else - dwStatus = pLastPiece->m_dwStatus; - return dwStatus; - } - - const CFX_RTFLine* pLastLine = GetRTFLine(); - if (pLastLine) { - pCurPieces = &pLastLine->m_LinePieces; - iCount = pCurPieces->GetSize(); - if (iCount-- > 0) { - CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(iCount); - if (dwStatus != CFX_RTFBreakType::Piece) - pLastPiece->m_dwStatus = dwStatus; - else - dwStatus = pLastPiece->m_dwStatus; - return dwStatus; - } - return CFX_RTFBreakType::None; - } - - iCount = m_pCurLine->CountChars(); - if (iCount < 1) - return CFX_RTFBreakType::None; - - CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1); - tc.m_dwStatus = dwStatus; - if (dwStatus == CFX_RTFBreakType::Piece) - return dwStatus; - - m_iReady = m_pCurLine == &m_RTFLine1 ? 1 : 2; - CFX_RTFLine* pNextLine = - m_pCurLine == &m_RTFLine1 ? &m_RTFLine2 : &m_RTFLine1; - bool bAllChars = m_iAlignment == CFX_RTFLineAlignment::Justified || - m_iAlignment == CFX_RTFLineAlignment::Distributed; - - if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) { - std::deque<FX_TPO> tpos; - EndBreak_BidiLine(&tpos, dwStatus); - if (!m_bPagination && m_iAlignment != CFX_RTFLineAlignment::Left) - EndBreak_Alignment(tpos, bAllChars, dwStatus); - } - m_pCurLine = pNextLine; - m_pCurLine->m_iStart = m_iBoundaryStart; - - CFX_RTFChar* pTC = GetLastChar(0); - m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; - return dwStatus; -} - -bool CFX_RTFBreak::EndBreak_SplitLine(CFX_RTFLine* pNextLine, - bool bAllChars, - CFX_RTFBreakType dwStatus) { - bool bDone = false; - if (m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) { - const CFX_RTFChar& tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1); - switch (tc.GetCharType()) { - case FX_CHARTYPE_Tab: - case FX_CHARTYPE_Control: - case FX_CHARTYPE_Space: - break; - default: - SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars); - bDone = true; - break; - } - } - - if (!m_bPagination && m_pCurLine->m_iMBCSChars <= 0) { - if (bAllChars && !bDone) { - int32_t endPos = m_pCurLine->GetLineEnd(); - GetBreakPos(m_pCurLine->m_LineChars, endPos, bAllChars, true); - } - return false; - } - - const CFX_RTFChar* pCurChars = m_pCurLine->m_LineChars.data(); - const CFX_RTFChar* pTC; - CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces; - CFX_RTFPiece tp; - tp.m_pChars = &m_pCurLine->m_LineChars; - bool bNew = true; - uint32_t dwIdentity = static_cast<uint32_t>(-1); - int32_t iLast = m_pCurLine->CountChars() - 1; - int32_t j = 0; - for (int32_t i = 0; i <= iLast;) { - pTC = pCurChars + i; - if (bNew) { - tp.m_iStartChar = i; - tp.m_iStartPos += tp.m_iWidth; - tp.m_iWidth = 0; - tp.m_dwStatus = pTC->m_dwStatus; - tp.m_iFontSize = pTC->m_iFontSize; - tp.m_iFontHeight = pTC->m_iFontHeight; - tp.m_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - dwIdentity = pTC->m_dwIdentity; - tp.m_dwIdentity = dwIdentity; - tp.m_pUserData = pTC->m_pUserData; - j = i; - bNew = false; - } - - if (i == iLast || pTC->m_dwStatus != CFX_RTFBreakType::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; -} - -void CFX_RTFBreak::EndBreak_BidiLine(std::deque<FX_TPO>* tpos, - CFX_RTFBreakType dwStatus) { - FX_TPO tpo; - CFX_RTFPiece tp; - CFX_RTFChar* pTC; - int32_t i; - int32_t j; - std::vector<CFX_RTFChar>& chars = m_pCurLine->m_LineChars; - int32_t iCount = m_pCurLine->CountChars(); - if (!m_bPagination && m_pCurLine->m_iArabicChars > 0) { - int32_t iBidiNum = 0; - for (i = 0; i < iCount; i++) { - pTC = &chars[i]; - pTC->m_iBidiPos = i; - if (pTC->GetCharType() != FX_CHARTYPE_Control) - iBidiNum = i; - if (i == 0) - pTC->m_iBidiLevel = 1; - } - FX_BidiLine(chars, iBidiNum + 1, 0); - } else { - for (i = 0; i < iCount; i++) { - pTC = &chars[i]; - pTC->m_iBidiLevel = 0; - pTC->m_iBidiPos = 0; - pTC->m_iBidiOrder = 0; - } - } - - tp.m_dwStatus = CFX_RTFBreakType::Piece; - tp.m_iStartPos = m_pCurLine->m_iStart; - tp.m_pChars = &chars; - CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces; - int32_t iBidiLevel = -1; - int32_t iCharWidth; - uint32_t dwIdentity = static_cast<uint32_t>(-1); - i = 0; - j = 0; - while (i < iCount) { - pTC = &chars[i]; - if (iBidiLevel < 0) { - iBidiLevel = pTC->m_iBidiLevel; - iCharWidth = pTC->m_iCharWidth; - tp.m_iWidth = iCharWidth < 1 ? 0 : iCharWidth; - tp.m_iBidiLevel = iBidiLevel; - tp.m_iBidiPos = pTC->m_iBidiOrder; - tp.m_iFontSize = pTC->m_iFontSize; - tp.m_iFontHeight = pTC->m_iFontHeight; - tp.m_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - dwIdentity = pTC->m_dwIdentity; - tp.m_dwIdentity = dwIdentity; - tp.m_pUserData = pTC->m_pUserData; - tp.m_dwStatus = CFX_RTFBreakType::Piece; - 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->push_back(tpo); - iBidiLevel = -1; - } else { - iCharWidth = pTC->m_iCharWidth; - if (iCharWidth > 0) - tp.m_iWidth += iCharWidth; - i++; - } - } - - if (i > tp.m_iStartChar) { - tp.m_dwStatus = dwStatus; - tp.m_iChars = i - tp.m_iStartChar; - pCurPieces->Add(tp); - tpo.index = j; - tpo.pos = tp.m_iBidiPos; - tpos->push_back(tpo); - } - - std::sort(tpos->begin(), tpos->end()); - int32_t iStartPos = m_pCurLine->m_iStart; - for (const auto& it : *tpos) { - CFX_RTFPiece& ttp = pCurPieces->GetAt(it.index); - ttp.m_iStartPos = iStartPos; - iStartPos += ttp.m_iWidth; - } -} - -void CFX_RTFBreak::EndBreak_Alignment(const std::deque<FX_TPO>& tpos, - bool bAllChars, - CFX_RTFBreakType dwStatus) { - CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces; - int32_t iNetWidth = m_pCurLine->m_iWidth; - int32_t iGapChars = 0; - int32_t iCharWidth; - int32_t iCount = pCurPieces->GetSize(); - bool bFind = false; - uint32_t dwCharType; - int32_t i; - int32_t j; - FX_TPO tpo; - for (i = iCount - 1; i > -1; i--) { - tpo = tpos[i]; - CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index); - if (!bFind) - iNetWidth = ttp.GetEndPos(); - - bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); - j = bArabic ? 0 : ttp.m_iChars - 1; - while (j > -1 && j < ttp.m_iChars) { - const CFX_RTFChar& tc = ttp.GetChar(j); - if (tc.m_nBreakType == FX_LBT_DIRECT_BRK) - iGapChars++; - - if (!bFind || !bAllChars) { - dwCharType = tc.GetCharType(); - if (dwCharType == FX_CHARTYPE_Space || - dwCharType == FX_CHARTYPE_Control) { - if (!bFind) { - iCharWidth = tc.m_iCharWidth; - if (bAllChars && iCharWidth > 0) - iNetWidth -= iCharWidth; - } - } else { - bFind = true; - if (!bAllChars) - break; - } - } - j += bArabic ? 1 : -1; - } - if (!bAllChars && bFind) - break; - } - - int32_t iOffset = m_iBoundaryEnd - iNetWidth; - if (iGapChars > 0 && (m_iAlignment == CFX_RTFLineAlignment::Distributed || - (m_iAlignment == CFX_RTFLineAlignment::Justified && - dwStatus != CFX_RTFBreakType::Paragraph))) { - int32_t iStart = -1; - for (i = 0; i < iCount; i++) { - tpo = tpos[i]; - CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index); - if (iStart < 0) - iStart = ttp.m_iStartPos; - else - ttp.m_iStartPos = iStart; - - 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; - - int32_t k = iOffset / iGapChars; - tc.m_iCharWidth += k; - ttp.m_iWidth += k; - iOffset -= k; - iGapChars--; - if (iGapChars < 1) - break; - } - iStart += ttp.m_iWidth; - } - } else if (m_iAlignment == CFX_RTFLineAlignment::Right || - m_iAlignment == CFX_RTFLineAlignment::Center) { - if (m_iAlignment == CFX_RTFLineAlignment::Center) - iOffset /= 2; - if (iOffset > 0) { - for (i = 0; i < iCount; i++) { - CFX_RTFPiece& ttp = pCurPieces->GetAt(i); - ttp.m_iStartPos += iOffset; - } - } - } -} - -int32_t CFX_RTFBreak::GetBreakPos(std::vector<CFX_RTFChar>& tca, - int32_t& iEndPos, - bool bAllChars, - bool bOnlyBrk) { - int32_t iLength = pdfium::CollectionSize<int32_t>(tca) - 1; - if (iLength < 1) - return iLength; - - int32_t iBreak = -1; - int32_t iBreakPos = -1; - int32_t iIndirect = -1; - int32_t iIndirectPos = -1; - int32_t iLast = -1; - int32_t iLastPos = -1; - if (iEndPos <= m_iBoundaryEnd) { - if (!bAllChars) - return iLength; - - iBreak = iLength; - iBreakPos = iEndPos; - } - - CFX_RTFChar* pCharArray = tca.data(); - CFX_RTFChar* pCur = pCharArray + iLength; - --iLength; - if (bAllChars) - pCur->m_nBreakType = FX_LBT_UNKNOWN; - - uint32_t nCodeProp = pCur->m_dwCharProps; - uint32_t nNext = nCodeProp & 0x003F; - int32_t iCharWidth = pCur->m_iCharWidth; - if (iCharWidth > 0) - iEndPos -= iCharWidth; - - while (iLength >= 0) { - pCur = pCharArray + iLength; - nCodeProp = pCur->m_dwCharProps; - uint32_t nCur = nCodeProp & 0x003F; - bool bNeedBreak = false; - FX_LINEBREAKTYPE eType; - if (nCur == FX_CBP_TB) { - bNeedBreak = true; - eType = nNext == FX_CBP_TB ? FX_LBT_PROHIBITED_BRK - : gs_FX_LineBreak_PairTable[nCur][nNext]; - } else { - if (nCur == FX_CBP_SP) - bNeedBreak = true; - - eType = nNext == FX_CBP_SP ? FX_LBT_PROHIBITED_BRK - : gs_FX_LineBreak_PairTable[nCur][nNext]; - } - if (bAllChars) - pCur->m_nBreakType = eType; - - if (!bOnlyBrk) { - iCharWidth = pCur->m_iCharWidth; - if (iEndPos <= m_iBoundaryEnd || 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, - bool bAllChars) { - ASSERT(pCurLine && pNextLine); - int32_t iCount = pCurLine->CountChars(); - if (iCount < 2) - return; - - int32_t iEndPos = pCurLine->GetLineEnd(); - std::vector<CFX_RTFChar>& curChars = pCurLine->m_LineChars; - int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); - if (iCharPos < 0) - iCharPos = 0; - - iCharPos++; - if (iCharPos >= iCount) { - pNextLine->RemoveAll(true); - CFX_Char* pTC = &curChars[iCharPos - 1]; - pTC->m_nBreakType = FX_LBT_UNKNOWN; - return; - } - - pNextLine->m_LineChars = - std::vector<CFX_RTFChar>(curChars.begin() + iCharPos, curChars.end()); - curChars.erase(curChars.begin() + iCharPos, curChars.end()); - pNextLine->m_iStart = pCurLine->m_iStart; - pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos; - pCurLine->m_iWidth = iEndPos; - curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; - - for (size_t i = 0; i < pNextLine->m_LineChars.size(); i++) { - if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { - pCurLine->m_iArabicChars--; - pNextLine->m_iArabicChars++; - } - pNextLine->m_LineChars[i].m_dwStatus = CFX_RTFBreakType::None; - } -} - -int32_t CFX_RTFBreak::CountBreakPieces() const { - const CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(); - return pRTFPieces ? pRTFPieces->GetSize() : 0; -} - -const CFX_RTFPiece* CFX_RTFBreak::GetBreakPiece(int32_t index) const { - const CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(); - if (!pRTFPieces) - return nullptr; - if (index < 0 || index >= pRTFPieces->GetSize()) - return nullptr; - return pRTFPieces->GetPtrAt(index); -} - -void CFX_RTFBreak::ClearBreakPieces() { - const CFX_RTFLine* pRTFLine = GetRTFLine(); - if (pRTFLine) - const_cast<CFX_RTFLine*>(pRTFLine)->RemoveAll(true); - m_iReady = 0; -} - -void CFX_RTFBreak::Reset() { - m_eCharType = FX_CHARTYPE_Unknown; - m_RTFLine1.RemoveAll(true); - m_RTFLine2.RemoveAll(true); -} - -int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode) const { - if (!pText || pText->iLength < 1) - return 0; - - ASSERT(pText->pFont && pText->pRect); - - CFX_RetainPtr<CFGAS_GEFont> pFont = pText->pFont; - CFX_RectF rtText(*pText->pRect); - bool bRTLPiece = FX_IsOdd(pText->iBidiLevel); - FX_FLOAT fFontSize = pText->fFontSize; - int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); - int32_t iAscent = pFont->GetAscent(); - int32_t iDescent = pFont->GetDescent(); - int32_t iMaxHeight = iAscent - iDescent; - FX_FLOAT fFontHeight = fFontSize; - FX_FLOAT fAscent = fFontHeight * static_cast<FX_FLOAT>(iAscent) / - static_cast<FX_FLOAT>(iMaxHeight); - FX_WCHAR wch; - FX_WCHAR wPrev = 0xFEFF; - FX_WCHAR wNext; - FX_WCHAR wForm; - int32_t iWidth; - int32_t iCharWidth; - int32_t iCharHeight; - FX_FLOAT fX = rtText.left; - FX_FLOAT fY = rtText.top; - FX_FLOAT fCharWidth; - FX_FLOAT fCharHeight; - int32_t iHorScale = pText->iHorizontalScale; - int32_t iVerScale = pText->iVerticalScale; - bool bEmptyChar; - uint32_t dwProps; - uint32_t dwCharType; - - if (bRTLPiece) - fX = rtText.right(); - - fY += fAscent; - int32_t iCount = 0; - for (int32_t i = 0; i < pText->iLength; i++) { - wch = pText->pStr[i]; - iWidth = pText->pWidths[i]; - dwProps = FX_GetUnicodeProperties(wch); - dwCharType = (dwProps & FX_CHARTYPEBITSMASK); - if (iWidth == 0) { - if (dwCharType == FX_CHARTYPE_ArabicAlef) - wPrev = 0xFEFF; - continue; - } - - iCharWidth = FXSYS_abs(iWidth); - bEmptyChar = - (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control); - if (!bEmptyChar) - iCount++; - - if (pCharPos) { - iCharWidth /= iFontSize; - wForm = wch; - if (dwCharType >= FX_CHARTYPE_ArabicAlef) { - if (i + 1 < pText->iLength) { - wNext = pText->pStr[i + 1]; - if (pText->pWidths[i + 1] < 0 && i + 2 < pText->iLength) - wNext = pText->pStr[i + 2]; - } else { - wNext = 0xFEFF; - } - wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); - } else if (bRTLPiece) { - wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, false); - } - dwProps = FX_GetUnicodeProperties(wForm); - - if (!bEmptyChar) { - if (bCharCode) { - pCharPos->m_GlyphIndex = wch; - } else { - pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, false); - if (pCharPos->m_GlyphIndex == 0xFFFF) - pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, false); - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; -#endif - pCharPos->m_FontCharWidth = iCharWidth; - } - iCharHeight = 1000; - - fCharWidth = fFontSize * iCharWidth / 1000.0f; - fCharHeight = fFontSize * iCharHeight / 1000.0f; - if (bRTLPiece && dwCharType != FX_CHARTYPE_Combination) - fX -= fCharWidth; - - if (!bEmptyChar) - pCharPos->m_Origin = CFX_PointF(fX, fY); - if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) - fX += fCharWidth; - - if (!bEmptyChar) { - pCharPos->m_bGlyphAdjust = true; - pCharPos->m_AdjustMatrix[0] = -1; - pCharPos->m_AdjustMatrix[1] = 0; - pCharPos->m_AdjustMatrix[2] = 0; - pCharPos->m_AdjustMatrix[3] = 1; - pCharPos->m_Origin.y += fAscent * iVerScale / 100.0f; - pCharPos->m_Origin.y -= fAscent; - - if (iHorScale != 100 || iVerScale != 100) { - pCharPos->m_AdjustMatrix[0] = - pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f; - pCharPos->m_AdjustMatrix[1] = - pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f; - pCharPos->m_AdjustMatrix[2] = - pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f; - pCharPos->m_AdjustMatrix[3] = - pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f; - } - pCharPos++; - } - } - if (iWidth > 0) - wPrev = wch; - } - return iCount; -} - -CFX_RTFPiece::CFX_RTFPiece() - : m_dwStatus(CFX_RTFBreakType::Piece), - m_iStartPos(0), - m_iWidth(-1), - m_iStartChar(0), - m_iChars(0), - m_iBidiLevel(0), - m_iBidiPos(0), - m_iFontSize(0), - m_iFontHeight(0), - m_iHorizontalScale(100), - m_iVerticalScale(100), - m_dwIdentity(0), - m_pChars(nullptr), - m_pUserData(nullptr) {} - -CFX_RTFPiece::~CFX_RTFPiece() { - Reset(); -} - -CFX_RTFLine::CFX_RTFLine() - : m_LinePieces(16), - m_iStart(0), - m_iWidth(0), - m_iArabicChars(0), - m_iMBCSChars(0) {} - -CFX_RTFLine::~CFX_RTFLine() { - RemoveAll(false); -} - -FX_RTFTEXTOBJ::FX_RTFTEXTOBJ() - : pFont(nullptr), - pRect(nullptr), - wLineBreakChar(L'\n'), - fFontSize(12.0f), - iLength(0), - iBidiLevel(0), - iHorizontalScale(100), - iVerticalScale(100) {} - -FX_RTFTEXTOBJ::~FX_RTFTEXTOBJ() {} diff --git a/xfa/fgas/layout/fgas_rtfbreak.h b/xfa/fgas/layout/fgas_rtfbreak.h deleted file mode 100644 index 4d999ec682aa3ffe0be18602217574b7a88ba7bd..0000000000000000000000000000000000000000 --- a/xfa/fgas/layout/fgas_rtfbreak.h +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_ -#define XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_ - -#include <deque> -#include <vector> - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_ucd.h" -#include "xfa/fgas/crt/fgas_utils.h" -#include "xfa/fgas/layout/fgas_textbreak.h" - -class CFGAS_GEFont; - -#define FX_RTFLAYOUTSTYLE_Pagination 0x01 -#define FX_RTFLAYOUTSTYLE_ExpandTab 0x10 - -enum class CFX_RTFLineAlignment { - Left = 0, - Center, - Right, - Justified, - Distributed -}; - -struct FX_RTFTEXTOBJ { - FX_RTFTEXTOBJ(); - ~FX_RTFTEXTOBJ(); - - CFX_WideString pStr; - std::vector<int32_t> pWidths; - CFX_RetainPtr<CFGAS_GEFont> pFont; - const CFX_RectF* pRect; - FX_WCHAR wLineBreakChar; - FX_FLOAT fFontSize; - int32_t iLength; - int32_t iBidiLevel; - int32_t iHorizontalScale; - int32_t iVerticalScale; -}; - -class CFX_RTFPiece { - public: - CFX_RTFPiece(); - ~CFX_RTFPiece(); - - int32_t GetEndPos() const { - return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth; - } - - CFX_RTFChar& GetChar(int32_t index) { - ASSERT(index > -1 && index < m_iChars && m_pChars); - return (*m_pChars)[m_iStartChar + index]; - } - - CFX_WideString GetString() const { - CFX_WideString ret; - ret.Reserve(m_iChars); - for (int32_t i = m_iStartChar; i < m_iStartChar + m_iChars; i++) - ret += static_cast<FX_WCHAR>((*m_pChars)[i].m_wCharCode); - return ret; - } - - std::vector<int32_t> GetWidths() const { - std::vector<int32_t> ret; - ret.reserve(m_iChars); - for (int32_t i = m_iStartChar; i < m_iStartChar + m_iChars; i++) - ret.push_back((*m_pChars)[i].m_iCharWidth); - return ret; - } - - void Reset() { - m_dwStatus = CFX_RTFBreakType::Piece; - if (m_iWidth > -1) - m_iStartPos += m_iWidth; - - m_iWidth = -1; - m_iStartChar += m_iChars; - m_iChars = 0; - m_iBidiLevel = 0; - m_iBidiPos = 0; - m_iHorizontalScale = 100; - m_iVerticalScale = 100; - } - - CFX_RTFBreakType m_dwStatus; - int32_t m_iStartPos; - int32_t m_iWidth; - int32_t m_iStartChar; - int32_t m_iChars; - int32_t m_iBidiLevel; - int32_t m_iBidiPos; - int32_t m_iFontSize; - int32_t m_iFontHeight; - int32_t m_iHorizontalScale; - int32_t m_iVerticalScale; - uint32_t m_dwIdentity; - std::vector<CFX_RTFChar>* m_pChars; // not owned. - CFX_RetainPtr<CFX_Retainable> m_pUserData; -}; - -typedef CFX_BaseArrayTemplate<CFX_RTFPiece> CFX_RTFPieceArray; - -class CFX_RTFLine { - public: - CFX_RTFLine(); - ~CFX_RTFLine(); - - int32_t CountChars() const { - return pdfium::CollectionSize<int32_t>(m_LineChars); - } - - CFX_RTFChar& GetChar(int32_t index) { - ASSERT(index >= 0 && index < pdfium::CollectionSize<int32_t>(m_LineChars)); - return m_LineChars[index]; - } - - int32_t GetLineEnd() const { return m_iStart + m_iWidth; } - void RemoveAll(bool bLeaveMemory) { - m_LineChars.clear(); - m_LinePieces.RemoveAll(bLeaveMemory); - m_iWidth = 0; - m_iArabicChars = 0; - m_iMBCSChars = 0; - } - - std::vector<CFX_RTFChar> m_LineChars; - CFX_RTFPieceArray m_LinePieces; - int32_t m_iStart; - int32_t m_iWidth; - int32_t m_iArabicChars; - int32_t m_iMBCSChars; -}; - -class CFX_RTFBreak { - public: - explicit CFX_RTFBreak(uint32_t dwLayoutStyles); - ~CFX_RTFBreak(); - - void SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd); - void SetLineStartPos(FX_FLOAT fLinePos); - void SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont); - void SetFontSize(FX_FLOAT fFontSize); - void SetTabWidth(FX_FLOAT fTabWidth); - void SetLineBreakTolerance(FX_FLOAT fTolerance); - void SetHorizontalScale(int32_t iScale); - void SetVerticalScale(int32_t iScale); - void SetCharSpace(FX_FLOAT fCharSpace); - void SetAlignment(CFX_RTFLineAlignment align) { m_iAlignment = align; } - void SetUserData(const CFX_RetainPtr<CFX_Retainable>& pUserData); - - void AddPositionedTab(FX_FLOAT fTabPos); - - CFX_RTFBreakType EndBreak(CFX_RTFBreakType dwStatus); - int32_t CountBreakPieces() const; - const CFX_RTFPiece* GetBreakPiece(int32_t index) const; - void ClearBreakPieces(); - - void Reset(); - - int32_t GetDisplayPos(const FX_RTFTEXTOBJ* pText, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode) const; - - CFX_RTFBreakType AppendChar(FX_WCHAR wch); - CFX_RTFBreakType AppendChar_Combination(CFX_RTFChar* pCurChar); - CFX_RTFBreakType AppendChar_Tab(CFX_RTFChar* pCurChar); - CFX_RTFBreakType AppendChar_Control(CFX_RTFChar* pCurChar); - CFX_RTFBreakType AppendChar_Arabic(CFX_RTFChar* pCurChar); - CFX_RTFBreakType AppendChar_Others(CFX_RTFChar* pCurChar); - - private: - void FontChanged(); - void SetBreakStatus(); - CFX_RTFChar* GetLastChar(int32_t index) const; - const CFX_RTFLine* GetRTFLine() const; - const CFX_RTFPieceArray* GetRTFPieces() const; - FX_CHARTYPE GetUnifiedCharType(FX_CHARTYPE chartype) const; - int32_t GetLastPositionedTab() const; - bool GetPositionedTab(int32_t* iTabPos) const; - - int32_t GetBreakPos(std::vector<CFX_RTFChar>& tca, - int32_t& iEndPos, - bool bAllChars, - bool bOnlyBrk); - void SplitTextLine(CFX_RTFLine* pCurLine, - CFX_RTFLine* pNextLine, - bool bAllChars); - bool EndBreak_SplitLine(CFX_RTFLine* pNextLine, - bool bAllChars, - CFX_RTFBreakType dwStatus); - void EndBreak_BidiLine(std::deque<FX_TPO>* tpos, CFX_RTFBreakType dwStatus); - void EndBreak_Alignment(const std::deque<FX_TPO>& tpos, - bool bAllChars, - CFX_RTFBreakType dwStatus); - - int32_t m_iBoundaryStart; - int32_t m_iBoundaryEnd; - uint32_t m_dwLayoutStyles; - bool m_bPagination; - CFX_RetainPtr<CFGAS_GEFont> m_pFont; - int32_t m_iFontHeight; - int32_t m_iFontSize; - int32_t m_iTabWidth; - std::vector<int32_t> m_PositionedTabs; - FX_WCHAR m_wDefChar; - int32_t m_iDefChar; - FX_WCHAR m_wLineBreakChar; - int32_t m_iHorizontalScale; - int32_t m_iVerticalScale; - int32_t m_iCharSpace; - CFX_RTFLineAlignment m_iAlignment; - CFX_RetainPtr<CFX_Retainable> m_pUserData; - FX_CHARTYPE m_eCharType; - uint32_t m_dwIdentity; - CFX_RTFLine m_RTFLine1; - CFX_RTFLine m_RTFLine2; - CFX_RTFLine* m_pCurLine; - int32_t m_iReady; - int32_t m_iTolerance; -}; - -#endif // XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_ diff --git a/xfa/fgas/layout/fgas_textbreak.cpp b/xfa/fgas/layout/fgas_textbreak.cpp deleted file mode 100644 index 8be72f2c7bfaf57ddb7a709689f6e4879a44b166..0000000000000000000000000000000000000000 --- a/xfa/fgas/layout/fgas_textbreak.cpp +++ /dev/null @@ -1,1668 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fgas/layout/fgas_textbreak.h" - -#include <algorithm> - -#include "core/fxcrt/fx_arabic.h" -#include "core/fxcrt/fx_arb.h" -#include "core/fxcrt/fx_memory.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fgas/layout/fgas_linebreak.h" - -namespace { - -typedef uint32_t (CFX_TxtBreak::*FX_TxtBreak_LPFAppendChar)( - CFX_TxtChar* pCurChar, - int32_t iRotation); -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, -}; - -} // namespace - -CFX_TxtBreak::CFX_TxtBreak(uint32_t dwPolicies) - : m_dwPolicies(dwPolicies), - 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(nullptr), - 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(nullptr), - m_eCharType(FX_CHARTYPE_Unknown), - m_bArabicNumber(false), - m_bArabicComma(false), - m_pCurLine(nullptr), - m_iReady(0), - m_iTolerance(0), - m_iHorScale(100), - m_iCharSpace(0) { - m_bPagination = (m_dwPolicies & FX_TXTBREAKPOLICY_Pagination) != 0; - int32_t iSize = m_bPagination ? sizeof(CFX_Char) : sizeof(CFX_TxtChar); - m_pTxtLine1 = pdfium::MakeUnique<CFX_TxtLine>(iSize); - m_pTxtLine2 = pdfium::MakeUnique<CFX_TxtLine>(iSize); - m_pCurLine = m_pTxtLine1.get(); - ResetArabicContext(); -} - -CFX_TxtBreak::~CFX_TxtBreak() { - Reset(); -} - -void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth) { - m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f); - ASSERT(m_iLineWidth >= 20000); -} - -void CFX_TxtBreak::SetLinePos(FX_FLOAT fLinePos) { - int32_t iLinePos = - std::min(std::max(FXSYS_round(fLinePos * 20000.0f), 0), m_iLineWidth); - m_pCurLine->m_iStart = iLinePos; - m_pCurLine->m_iWidth += iLinePos; -} - -void CFX_TxtBreak::SetLayoutStyles(uint32_t 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(const CFX_RetainPtr<CFGAS_GEFont>& pFont) { - if (!pFont || pFont == m_pFont) - return; - - SetBreakStatus(); - m_pFont = pFont; - FontChanged(); -} - -void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize) { - int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); - if (m_iFontSize == iFontSize) - return; - - SetBreakStatus(); - m_iFontSize = iFontSize; - FontChanged(); -} - -void CFX_TxtBreak::FontChanged() { - m_iDefChar = 0; - if (m_wDefChar == 0xFEFF || !m_pFont) - return; - - m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false); - m_iDefChar *= m_iFontSize; -} - -void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, 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) - return; - - m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false); - if (m_iDefChar < 0) - m_iDefChar = 0; - else - m_iDefChar *= m_iFontSize; -} - -void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch) { - if (wch != L'\r' && wch != L'\n') - return; - m_wParagBreakChar = wch; -} - -void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) { - m_iTolerance = FXSYS_round(fTolerance * 20000.0f); -} - -void CFX_TxtBreak::SetCharRotation(int32_t iCharRotation) { - if (iCharRotation < 0) - iCharRotation += (-iCharRotation / 4 + 1) * 4; - else if (iCharRotation > 3) - iCharRotation -= (iCharRotation / 4) * 4; - - if (m_iCharRotation == iCharRotation) - return; - - SetBreakStatus(); - m_iCharRotation = iCharRotation; - m_iRotation = m_iLineRotation + m_iCharRotation; - m_iRotation %= 4; -} - -void CFX_TxtBreak::SetAlignment(int32_t iAlignment) { - 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); -} - -void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth) { - m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f); -} - -void CFX_TxtBreak::SetUserData(void* pUserData) { - if (m_pUserData == pUserData) - return; - - SetBreakStatus(); - m_pUserData = pUserData; -} - -void CFX_TxtBreak::SetBreakStatus() { - if (m_bPagination) - return; - - int32_t iCount = m_pCurLine->CountChars(); - if (iCount < 1) - return; - - CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1); - if (pTC->m_dwStatus == 0) - pTC->m_dwStatus = FX_TXTBREAK_PieceBreak; -} - -void CFX_TxtBreak::SetHorizontalScale(int32_t iScale) { - if (iScale < 0) - iScale = 0; - if (iScale == m_iHorScale) - return; - - SetBreakStatus(); - m_iHorScale = iScale; -} - -void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace) { - m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f); -} - -static const int32_t gs_FX_TxtLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2}; - -int32_t CFX_TxtBreak::GetLineRotation(uint32_t dwStyles) const { - return gs_FX_TxtLineRotations[(dwStyles & 0x0E) >> 1]; -} - -CFX_TxtChar* CFX_TxtBreak::GetLastChar(int32_t index, bool bOmitChar) const { - std::vector<CFX_TxtChar>& ca = *m_pCurLine->m_pLineChars.get(); - int32_t iCount = pdfium::CollectionSize<int32_t>(ca); - if (index < 0 || index >= iCount) - return nullptr; - - int32_t iStart = iCount - 1; - while (iStart > -1) { - CFX_TxtChar* pTC = &ca[iStart--]; - if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination) - continue; - if (--index < 0) - return pTC; - } - return nullptr; -} - -CFX_TxtLine* CFX_TxtBreak::GetTxtLine() const { - if (m_iReady == 1) - return m_pTxtLine1.get(); - if (m_iReady == 2) - return m_pTxtLine2.get(); - return nullptr; -} - -CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces() const { - CFX_TxtLine* pTxtLine = GetTxtLine(); - return pTxtLine ? pTxtLine->m_pLinePieces.get() : nullptr; -} - -inline FX_CHARTYPE CFX_TxtBreak::GetUnifiedCharType( - FX_CHARTYPE chartype) const { - return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype; -} - -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_TxtChar* pCurChar, - uint32_t dwProps) { - if (!m_bPagination) { - pCurChar->m_dwStatus = 0; - pCurChar->m_pUserData = m_pUserData; - } - if (m_bArabicContext || m_bArabicShapes) { - int32_t iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS; - int32_t iArabicContext = - (iBidiCls == FX_BIDICLASS_R || iBidiCls == FX_BIDICLASS_AL) - ? 2 - : ((iBidiCls == FX_BIDICLASS_L || iBidiCls == FX_BIDICLASS_S) ? 0 - : 1); - if (iArabicContext != m_iArabicContext && iArabicContext != 1) { - m_iArabicContext = iArabicContext; - if (m_iCurArabicContext == 1) - m_iCurArabicContext = iArabicContext; - - ResetArabicContext(); - if (!m_bPagination) { - CFX_TxtChar* pLastChar = GetLastChar(1, false); - if (pLastChar && pLastChar->m_dwStatus < 1) - pLastChar->m_dwStatus = FX_TXTBREAK_PieceBreak; - } - } - } - pCurChar->m_dwCharStyles = m_dwContextCharStyles; -} - -uint32_t CFX_TxtBreak::AppendChar_Combination(CFX_TxtChar* pCurChar, - int32_t iRotation) { - FX_WCHAR wch = pCurChar->m_wCharCode; - FX_WCHAR wForm; - int32_t iCharWidth = 0; - 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) { - CFX_TxtChar* pLastChar = GetLastChar(0, false); - if (pLastChar && - (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) { - 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) { - pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; - pLastChar->m_iCharWidth = 0; - pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; - } - } - } - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) - iCharWidth = 0; - } - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorScale / 100; - } - pCurChar->m_iCharWidth = -iCharWidth; - return FX_TXTBREAK_None; -} - -uint32_t CFX_TxtBreak::AppendChar_Tab(CFX_TxtChar* pCurChar, - int32_t iRotation) { - m_eCharType = FX_CHARTYPE_Tab; - if ((m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ExpandTab) == 0) - return FX_TXTBREAK_None; - - int32_t& iLineWidth = m_pCurLine->m_iWidth; - int32_t iCharWidth; - if (m_bCombText) { - iCharWidth = m_iCombWidth; - } else { - if (m_bEquidistant) { - iCharWidth = iLineWidth; - iCharWidth = m_iTabWidth * (iCharWidth / m_iTabWidth + 1) - iCharWidth; - if (iCharWidth < FX_TXTBREAK_MinimumTabWidth) - iCharWidth += m_iTabWidth; - } else { - iCharWidth = m_iTabWidth; - } - } - - pCurChar->m_iCharWidth = iCharWidth; - iLineWidth += iCharWidth; - if (!m_bSingleLine && iLineWidth >= m_iLineWidth + m_iTolerance) - return EndBreak(FX_TXTBREAK_LineBreak); - - return FX_TXTBREAK_None; -} - -uint32_t CFX_TxtBreak::AppendChar_Control(CFX_TxtChar* pCurChar, - int32_t iRotation) { - m_eCharType = FX_CHARTYPE_Control; - uint32_t 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; -} - -uint32_t CFX_TxtBreak::AppendChar_Arabic(CFX_TxtChar* pCurChar, - int32_t iRotation) { - FX_CHARTYPE chartype = pCurChar->GetCharType(); - int32_t& iLineWidth = m_pCurLine->m_iWidth; - FX_WCHAR wForm; - int32_t iCharWidth = 0; - CFX_TxtChar* pLastChar = nullptr; - bool bAlef = false; - if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef && - m_eCharType <= FX_CHARTYPE_ArabicDistortion) { - pLastChar = GetLastChar(1); - if (pLastChar) { - iCharWidth = pLastChar->m_iCharWidth; - if (iCharWidth > 0) - iLineWidth -= iCharWidth; - - CFX_Char* pPrevChar = GetLastChar(2); - wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); - bAlef = (wForm == 0xFEFF && - pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); - int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation; - if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) - iLastRotation++; - if (m_bVertical != FX_IsOdd(iLastRotation)) - iCharWidth = 1000; - else - m_pFont->GetCharWidth(wForm, iCharWidth, false); - - if (wForm == 0xFEFF) - iCharWidth = m_iDefChar; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorScale / 100; - pLastChar->m_iCharWidth = iCharWidth; - iLineWidth += iCharWidth; - iCharWidth = 0; - } - } - - m_eCharType = chartype; - wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, - nullptr); - 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; -} - -uint32_t CFX_TxtBreak::AppendChar_Others(CFX_TxtChar* pCurChar, - int32_t iRotation) { - uint32_t dwProps = pCurChar->m_dwCharProps; - FX_CHARTYPE chartype = pCurChar->GetCharType(); - int32_t& iLineWidth = m_pCurLine->m_iWidth; - int32_t iCharWidth = 0; - m_eCharType = chartype; - FX_WCHAR wch = pCurChar->m_wCharCode; - FX_WCHAR wForm = wch; - if (chartype == 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; - bool bBreak = (chartype != 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; -} - -uint32_t CFX_TxtBreak::AppendChar(FX_WCHAR wch) { - uint32_t dwProps = kTextLayoutCodeProperties[static_cast<uint16_t>(wch)]; - FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); - m_pCurLine->m_pLineChars->emplace_back(); - - CFX_TxtChar* pCurChar = &m_pCurLine->m_pLineChars->back(); - pCurChar->m_wCharCode = static_cast<uint16_t>(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_iVerticalScale = 100; - pCurChar->m_dwStatus = 0; - pCurChar->m_iBidiClass = 0; - pCurChar->m_iBidiLevel = 0; - pCurChar->m_iBidiPos = 0; - pCurChar->m_iBidiOrder = 0; - pCurChar->m_pUserData = nullptr; - AppendChar_PageLoad(pCurChar, dwProps); - uint32_t dwRet1 = FX_TXTBREAK_None; - if (chartype != FX_CHARTYPE_Combination && - GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && - m_eCharType != FX_CHARTYPE_Unknown && - m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine && - (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { - dwRet1 = EndBreak(FX_TXTBREAK_LineBreak); - int32_t iCount = m_pCurLine->CountChars(); - if (iCount > 0) - pCurChar = &(*m_pCurLine->m_pLineChars)[iCount - 1]; - } - - int32_t iRotation = m_iRotation; - if (m_bVertical && (dwProps & 0x8000) != 0) - iRotation = (iRotation + 1) % 4; - - uint32_t dwRet2 = - (this->*g_FX_TxtBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])( - pCurChar, iRotation); - return std::max(dwRet1, dwRet2); -} - -void CFX_TxtBreak::EndBreak_UpdateArabicShapes() { - ASSERT(m_bArabicShapes); - int32_t iCount = m_pCurLine->CountChars(); - if (iCount < 2) - return; - - int32_t& iLineWidth = m_pCurLine->m_iWidth; - CFX_TxtChar* pCur = m_pCurLine->GetCharPtr(0); - bool bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0; - pCur = m_pCurLine->GetCharPtr(1); - FX_WCHAR wch, wForm; - bool bNextNum; - int32_t i = 1; - int32_t iCharWidth; - int32_t iRotation; - CFX_TxtChar* pNext; - do { - i++; - if (i < iCount) { - pNext = m_pCurLine->GetCharPtr(i); - bNextNum = (pNext->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0; - } else { - pNext = nullptr; - 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); -} - -bool CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine* pNextLine, - bool bAllChars, - uint32_t dwStatus) { - int32_t iCount = m_pCurLine->CountChars(); - bool bDone = false; - CFX_TxtChar* 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.get(); - 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.get(); - 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_iVerticalScale; - pCurPieces->Add(tp); - m_pCurLine = pNextLine; - m_eCharType = FX_CHARTYPE_Unknown; - return true; - } - if (bAllChars && !bDone) { - int32_t iEndPos = m_pCurLine->m_iWidth; - GetBreakPos(*m_pCurLine->m_pLineChars.get(), iEndPos, bAllChars, true); - } - return false; -} - -void CFX_TxtBreak::EndBreak_BidiLine(std::deque<FX_TPO>* tpos, - uint32_t dwStatus) { - CFX_TxtPiece tp; - FX_TPO tpo; - CFX_TxtChar* pTC; - int32_t i; - int32_t j; - std::vector<CFX_TxtChar>& chars = *m_pCurLine->m_pLineChars.get(); - int32_t iCount = m_pCurLine->CountChars(); - bool bDone = (m_pCurLine->m_iArabicChars > 0 || m_bCurRTL); - if (!m_bPagination && bDone) { - int32_t iBidiNum = 0; - for (i = 0; i < iCount; i++) { - pTC = &chars[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.get(); - 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.get(); - int32_t iBidiLevel = -1; - int32_t iCharWidth; - i = 0; - j = -1; - while (i < iCount) { - pTC = &chars[i]; - if (iBidiLevel < 0) { - iBidiLevel = pTC->m_iBidiLevel; - tp.m_iWidth = 0; - tp.m_iBidiLevel = iBidiLevel; - tp.m_iBidiPos = pTC->m_iBidiOrder; - tp.m_dwCharStyles = pTC->m_dwCharStyles; - tp.m_pUserData = pTC->m_pUserData; - tp.m_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - 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->push_back(tpo); - iBidiLevel = -1; - } else { - iCharWidth = pTC->m_iCharWidth; - if (iCharWidth > 0) - tp.m_iWidth += iCharWidth; - - i++; - } - } - if (i > tp.m_iStartChar) { - tp.m_dwStatus = dwStatus; - tp.m_iChars = i - tp.m_iStartChar; - pCurPieces->Add(tp); - tpo.index = ++j; - tpo.pos = tp.m_iBidiPos; - tpos->push_back(tpo); - } - if (j > -1) { - if (j > 0) { - std::sort(tpos->begin(), tpos->end()); - int32_t iStartPos = 0; - for (i = 0; i <= j; i++) { - tpo = (*tpos)[i]; - CFX_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.get(); - tp.m_pUserData = m_pUserData; - pTC = &chars[0]; - tp.m_dwCharStyles = pTC->m_dwCharStyles; - tp.m_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - pCurPieces->Add(tp); - tpos->push_back({0, 0}); - } -} - -void CFX_TxtBreak::EndBreak_Alignment(const std::deque<FX_TPO>& tpos, - bool bAllChars, - uint32_t dwStatus) { - int32_t iNetWidth = m_pCurLine->m_iWidth; - int32_t iGapChars = 0; - int32_t iCharWidth; - CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get(); - int32_t i; - int32_t j; - int32_t iCount = pCurPieces->GetSize(); - bool bFind = false; - FX_TPO tpo; - CFX_TxtChar* pTC; - FX_CHARTYPE chartype; - for (i = iCount - 1; i > -1; i--) { - tpo = tpos[i]; - CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index); - if (!bFind) - iNetWidth = ttp.GetEndPos(); - - 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) { - chartype = pTC->GetCharType(); - if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) { - if (!bFind) { - iCharWidth = pTC->m_iCharWidth; - if (bAllChars && iCharWidth > 0) - iNetWidth -= iCharWidth; - } - } else { - bFind = true; - if (!bAllChars) - break; - } - } - j += bArabic ? 1 : -1; - } - if (!bAllChars && bFind) - break; - } - - int32_t iOffset = m_iLineWidth - iNetWidth; - int32_t iLowerAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_LowerMask); - int32_t iHigherAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_HigherMask); - if (iGapChars > 0 && (iHigherAlignment == FX_TXTLINEALIGNMENT_Distributed || - (iHigherAlignment == FX_TXTLINEALIGNMENT_Justified && - dwStatus != FX_TXTBREAK_ParagraphBreak))) { - int32_t iStart = -1; - for (i = 0; i < iCount; i++) { - tpo = tpos[i]; - CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index); - if (iStart < -1) - iStart = ttp.m_iStartPos; - else - ttp.m_iStartPos = iStart; - - 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; - - int32_t k = iOffset / iGapChars; - pTC->m_iCharWidth += k; - ttp.m_iWidth += k; - iOffset -= k; - iGapChars--; - if (iGapChars < 1) - break; - } - iStart += ttp.m_iWidth; - } - } else if (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; - } - } - } -} - -uint32_t CFX_TxtBreak::EndBreak(uint32_t dwStatus) { - ASSERT(dwStatus >= FX_TXTBREAK_PieceBreak && - dwStatus <= FX_TXTBREAK_PageBreak); - CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get(); - int32_t iCount = pCurPieces->GetSize(); - if (iCount > 0) { - CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount); - if (dwStatus > FX_TXTBREAK_PieceBreak) - pLastPiece->m_dwStatus = dwStatus; - else - dwStatus = pLastPiece->m_dwStatus; - return dwStatus; - } else { - CFX_TxtLine* pLastLine = GetTxtLine(); - if (pLastLine) { - pCurPieces = pLastLine->m_pLinePieces.get(); - 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.get()) ? 1 : 2; - CFX_TxtLine* pNextLine = - (m_pCurLine == m_pTxtLine1.get()) ? m_pTxtLine2.get() : m_pTxtLine1.get(); - bool bAllChars = (m_iCurAlignment > FX_TXTLINEALIGNMENT_Right); - if (m_bArabicShapes) - EndBreak_UpdateArabicShapes(); - - if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) { - std::deque<FX_TPO> tpos; - EndBreak_BidiLine(&tpos, dwStatus); - if (!m_bPagination && m_iCurAlignment > FX_TXTLINEALIGNMENT_Left) - EndBreak_Alignment(tpos, bAllChars, dwStatus); - } - - m_pCurLine = pNextLine; - CFX_Char* pTC = GetLastChar(0, false); - m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; - if (dwStatus == FX_TXTBREAK_ParagraphBreak) { - m_iArabicContext = m_iCurArabicContext = 1; - ResetArabicContext(); - } - return dwStatus; -} - -int32_t CFX_TxtBreak::GetBreakPos(std::vector<CFX_TxtChar>& ca, - int32_t& iEndPos, - bool bAllChars, - bool bOnlyBrk) { - int32_t iLength = pdfium::CollectionSize<int32_t>(ca) - 1; - if (iLength < 1) - return iLength; - - int32_t iBreak = -1; - int32_t iBreakPos = -1; - int32_t iIndirect = -1; - int32_t iIndirectPos = -1; - int32_t iLast = -1; - int32_t iLastPos = -1; - if (m_bSingleLine || iEndPos <= m_iLineWidth) { - if (!bAllChars) - return iLength; - - iBreak = iLength; - iBreakPos = iEndPos; - } - - bool bSpaceBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0; - bool bNumberBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_NumberBreak) != 0; - FX_LINEBREAKTYPE eType; - uint32_t nCodeProp; - uint32_t nCur; - uint32_t nNext; - CFX_Char* pCur = &ca[iLength--]; - if (bAllChars) - pCur->m_nBreakType = FX_LBT_UNKNOWN; - - nCodeProp = pCur->m_dwCharProps; - nNext = nCodeProp & 0x003F; - int32_t iCharWidth = pCur->m_iCharWidth; - if (iCharWidth > 0) - iEndPos -= iCharWidth; - - while (iLength >= 0) { - pCur = &ca[iLength]; - nCodeProp = pCur->m_dwCharProps; - nCur = nCodeProp & 0x003F; - if (nCur == FX_CBP_SP) { - if (nNext == FX_CBP_SP) - eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK; - else - eType = gs_FX_LineBreak_PairTable[nCur][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 = gs_FX_LineBreak_PairTable[nCur][nNext]; - } - if (bAllChars) - pCur->m_nBreakType = static_cast<uint8_t>(eType); - if (!bOnlyBrk) { - if (m_bSingleLine || iEndPos <= m_iLineWidth || - (nCur == FX_CBP_SP && !bSpaceBreak)) { - if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) { - iBreak = iLength; - iBreakPos = iEndPos; - if (!bAllChars) - return iLength; - } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) { - iIndirect = iLength; - iIndirectPos = iEndPos; - } - if (iLast < 0) { - iLast = iLength; - iLastPos = iEndPos; - } - } - iCharWidth = pCur->m_iCharWidth; - if (iCharWidth > 0) - iEndPos -= iCharWidth; - } - nNext = nCodeProp & 0x003F; - iLength--; - } - if (bOnlyBrk) - return 0; - if (iBreak > -1) { - iEndPos = iBreakPos; - return iBreak; - } - if (iIndirect > -1) { - iEndPos = iIndirectPos; - return iIndirect; - } - if (iLast > -1) { - iEndPos = iLastPos; - return iLast; - } - return 0; -} - -void CFX_TxtBreak::SplitTextLine(CFX_TxtLine* pCurLine, - CFX_TxtLine* pNextLine, - bool bAllChars) { - ASSERT(pCurLine && pNextLine); - int32_t iCount = pCurLine->CountChars(); - if (iCount < 2) - return; - - int32_t iEndPos = pCurLine->m_iWidth; - std::vector<CFX_TxtChar>& curChars = *pCurLine->m_pLineChars; - int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); - if (iCharPos < 0) - iCharPos = 0; - - iCharPos++; - if (iCharPos >= iCount) { - pNextLine->RemoveAll(true); - CFX_Char* pTC = &curChars[iCharPos - 1]; - pTC->m_nBreakType = FX_LBT_UNKNOWN; - return; - } - - // m_pLineChars is a unique_ptr<vector>. Assign the ref into nextChars - // so we can change the m_pLineChars vector ... - std::vector<CFX_TxtChar>& nextChars = *pNextLine->m_pLineChars; - nextChars = - std::vector<CFX_TxtChar>(curChars.begin() + iCharPos, curChars.end()); - curChars.erase(curChars.begin() + iCharPos, curChars.end()); - pCurLine->m_iWidth = iEndPos; - CFX_TxtChar* pTC = &curChars[iCharPos - 1]; - pTC->m_nBreakType = FX_LBT_UNKNOWN; - iCount = pdfium::CollectionSize<int>(nextChars); - int32_t iWidth = 0; - for (int32_t i = 0; i < iCount; i++) { - if (nextChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { - pCurLine->m_iArabicChars--; - pNextLine->m_iArabicChars++; - } - int32_t iCharWidth = nextChars[i].m_iCharWidth; - if (iCharWidth > 0) - iWidth += iCharWidth; - if (m_bPagination) - continue; - - nextChars[i].m_dwStatus = 0; - } - pNextLine->m_iWidth = iWidth; -} - -int32_t CFX_TxtBreak::CountBreakPieces() const { - CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(); - return pTxtPieces ? pTxtPieces->GetSize() : 0; -} - -const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const { - CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(); - if (!pTxtPieces) - return nullptr; - if (index < 0 || index >= pTxtPieces->GetSize()) - return nullptr; - return pTxtPieces->GetPtrAt(index); -} - -void CFX_TxtBreak::ClearBreakPieces() { - CFX_TxtLine* pTxtLine = GetTxtLine(); - if (pTxtLine) - pTxtLine->RemoveAll(true); - m_iReady = 0; -} - -void CFX_TxtBreak::Reset() { - m_eCharType = FX_CHARTYPE_Unknown; - m_iArabicContext = 1; - m_iCurArabicContext = 1; - ResetArabicContext(); - m_pTxtLine1->RemoveAll(true); - m_pTxtLine2->RemoveAll(true); -} - -struct FX_FORMCHAR { - uint16_t wch; - uint16_t wForm; - int32_t iWidth; -}; - -int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode, - CFX_WideString* pWSForms) const { - if (!pTxtRun || pTxtRun->iLength < 1) - return 0; - - IFX_TxtAccess* pAccess = pTxtRun->pAccess; - const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity; - const FX_WCHAR* pStr = pTxtRun->wsStr.c_str(); - int32_t* pWidths = pTxtRun->pWidths; - int32_t iLength = pTxtRun->iLength - 1; - CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont; - uint32_t dwStyles = pTxtRun->dwStyles; - CFX_RectF rtText(*pTxtRun->pRect); - bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0; - bool bArabicNumber = - (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0; - bool bArabicComma = - (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0; - FX_FLOAT fFontSize = pTxtRun->fFontSize; - int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); - int32_t iAscent = pFont->GetAscent(); - int32_t iDescent = pFont->GetDescent(); - int32_t iMaxHeight = iAscent - iDescent; - FX_FLOAT fFontHeight = fFontSize; - FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight; - FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight; - bool bVerticalDoc = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0; - bool bVerticalChar = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0; - int32_t iRotation = GetLineRotation(dwStyles) + pTxtRun->iCharRotation; - FX_FLOAT fX = rtText.left; - FX_FLOAT fY; - FX_FLOAT fCharWidth; - FX_FLOAT fCharHeight; - int32_t iHorScale = pTxtRun->iHorizontalScale; - int32_t iVerScale = pTxtRun->iVerticalScale; - bool bSkipSpace = pTxtRun->bSkipSpace; - FX_FORMCHAR formChars[3]; - FX_FLOAT fYBase; - - if (bVerticalDoc) { - fX += (rtText.width - fFontSize) / 2.0f; - fYBase = bRTLPiece ? rtText.bottom() : rtText.top; - fY = fYBase; - } else { - if (bRTLPiece) - fX = rtText.right(); - - fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f; - fY = fYBase + fAscent; - } - - int32_t iCount = 0; - int32_t iNext = 0; - FX_WCHAR wPrev = 0xFEFF; - FX_WCHAR wNext = 0xFEFF; - FX_WCHAR wForm = 0xFEFF; - FX_WCHAR wLast = 0xFEFF; - bool bShadda = false; - bool bLam = false; - for (int32_t i = 0; i <= iLength; i++) { - int32_t iWidth; - FX_WCHAR wch; - if (pAccess) { - wch = pAccess->GetChar(pIdentity, i); - iWidth = pAccess->GetWidth(pIdentity, i); - } else { - wch = *pStr++; - iWidth = *pWidths++; - } - - uint32_t dwProps = FX_GetUnicodeProperties(wch); - FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); - if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) { - wPrev = 0xFEFF; - wLast = wch; - continue; - } - - if (chartype >= FX_CHARTYPE_ArabicAlef) { - if (i < iLength) { - if (pAccess) { - iNext = i + 1; - while (iNext <= iLength) { - wNext = pAccess->GetChar(pIdentity, iNext); - dwProps = FX_GetUnicodeProperties(wNext); - if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination) - break; - - iNext++; - } - if (iNext > iLength) - wNext = 0xFEFF; - } else { - int32_t j = -1; - do { - j++; - if (i + j >= iLength) - break; - - wNext = pStr[j]; - dwProps = FX_GetUnicodeProperties(wNext); - } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination); - if (i + j >= iLength) - wNext = 0xFEFF; - } - } else { - wNext = 0xFEFF; - } - - wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); - bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647); - } else if (chartype == FX_CHARTYPE_Combination) { - wForm = wch; - if (wch >= 0x064C && wch <= 0x0651) { - if (bShadda) { - wForm = 0xFEFF; - bShadda = false; - } else { - wNext = 0xFEFF; - if (pAccess) { - iNext = i + 1; - if (iNext <= iLength) - wNext = pAccess->GetChar(pIdentity, iNext); - } else { - if (i < iLength) - wNext = *pStr; - } - if (wch == 0x0651) { - if (wNext >= 0x064C && wNext <= 0x0650) { - wForm = FX_GetArabicFromShaddaTable(wNext); - bShadda = true; - } - } else { - if (wNext == 0x0651) { - wForm = FX_GetArabicFromShaddaTable(wch); - bShadda = true; - } - } - } - } else { - bShadda = false; - } - } else if (chartype == FX_CHARTYPE_Numeric) { - wForm = wch; - if (bArabicNumber) - wForm += 0x0630; - } else if (wch == L'.') { - wForm = wch; - if (bArabicNumber) { - wNext = 0xFEFF; - if (pAccess) { - 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 (chartype != FX_CHARTYPE_Combination) - bShadda = false; - if (chartype < FX_CHARTYPE_ArabicAlef) - bLam = false; - - dwProps = FX_GetUnicodeProperties(wForm); - int32_t iCharRotation = iRotation; - if (bVerticalChar && (dwProps & 0x8000) != 0) - iCharRotation++; - - iCharRotation %= 4; - bool bEmptyChar = - (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control); - if (wForm == 0xFEFF) - bEmptyChar = true; - - int32_t iForms = bLam ? 3 : 1; - iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms; - if (!pCharPos) { - if (iWidth > 0) - wPrev = wch; - wLast = wch; - continue; - } - - int32_t iCharWidth = iWidth; - if (iCharWidth < 0) - iCharWidth = -iCharWidth; - - iCharWidth /= iFontSize; - formChars[0].wch = wch; - formChars[0].wForm = wForm; - formChars[0].iWidth = iCharWidth; - if (bLam) { - formChars[1].wForm = 0x0651; - iCharWidth = 0; - pFont->GetCharWidth(0x0651, iCharWidth, false); - formChars[1].iWidth = iCharWidth; - formChars[2].wForm = 0x0670; - iCharWidth = 0; - pFont->GetCharWidth(0x0670, iCharWidth, false); - formChars[2].iWidth = iCharWidth; - } - - for (int32_t j = 0; j < iForms; j++) { - wForm = (FX_WCHAR)formChars[j].wForm; - iCharWidth = formChars[j].iWidth; - if (j > 0) { - chartype = 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); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; -#endif - pCharPos->m_FontCharWidth = iCharWidth; - if (pWSForms) - *pWSForms += wForm; - } - - int32_t iCharHeight; - if (bVerticalDoc) { - iCharHeight = iCharWidth; - iCharWidth = 1000; - } else { - iCharHeight = 1000; - } - - fCharWidth = fFontSize * iCharWidth / 1000.0f; - fCharHeight = fFontSize * iCharHeight / 1000.0f; - if (bRTLPiece && chartype != FX_CHARTYPE_Combination) { - if (bVerticalDoc) - fY -= fCharHeight; - else - fX -= fCharWidth; - } - if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { - pCharPos->m_Origin = CFX_PointF(fX, fY); - if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) { - int32_t iFormWidth = iCharWidth; - pFont->GetCharWidth(wForm, iFormWidth, false); - FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f; - if (bVerticalDoc) - pCharPos->m_Origin.y += fOffset; - else - pCharPos->m_Origin.x += fOffset; - } - - if (chartype == FX_CHARTYPE_Combination) { - CFX_Rect rtBBox; - if (pFont->GetCharBBox(wForm, &rtBBox, false)) { - pCharPos->m_Origin.y = - fYBase + fFontSize - - fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight; - } - if (wForm == wch && wLast != 0xFEFF) { - uint32_t dwLastProps = FX_GetUnicodeProperties(wLast); - if ((dwLastProps & FX_CHARTYPEBITSMASK) == - FX_CHARTYPE_Combination) { - CFX_Rect rtBox; - if (pFont->GetCharBBox(wLast, &rtBox, false)) - pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight; - } - } - } - CFX_PointF ptOffset; - if (bVerticalChar && (dwProps & 0x00010000) != 0) { - CFX_Rect rtBBox; - if (pFont->GetCharBBox(wForm, &rtBBox, false)) { - ptOffset.x = fFontSize * (850 - rtBBox.right()) / iMaxHeight; - ptOffset.y = fFontSize * (iAscent - rtBBox.top - 150) / iMaxHeight; - } - } - pCharPos->m_Origin.x += ptOffset.x; - pCharPos->m_Origin.y -= ptOffset.y; - } - if (!bRTLPiece && chartype != 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_Origin.y += 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_Origin.x -= 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_Origin.x += fCharWidth; - pCharPos->m_Origin.y += fAscent; - } else { - pCharPos->m_AdjustMatrix[0] = 0; - pCharPos->m_AdjustMatrix[1] = 1; - pCharPos->m_AdjustMatrix[2] = 1; - pCharPos->m_AdjustMatrix[3] = 0; - pCharPos->m_Origin.x += 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_Origin.x -= fDescent; - pCharPos->m_Origin.y -= 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_Origin.x += fCharWidth; - pCharPos->m_Origin.y -= fAscent; - } else { - pCharPos->m_AdjustMatrix[0] = 0; - pCharPos->m_AdjustMatrix[1] = 1; - pCharPos->m_AdjustMatrix[2] = 1; - pCharPos->m_AdjustMatrix[3] = 0; - pCharPos->m_Origin.x += 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 = static_cast<FX_WCHAR>(formChars[0].wch); - wLast = wch; - } - return iCount; -} - -std::vector<CFX_RectF> CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun, - bool bCharBBox) const { - if (!pTxtRun || pTxtRun->iLength < 1) - return std::vector<CFX_RectF>(); - - IFX_TxtAccess* pAccess = pTxtRun->pAccess; - const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity; - const FX_WCHAR* pStr = pTxtRun->wsStr.c_str(); - int32_t* pWidths = pTxtRun->pWidths; - int32_t iLength = pTxtRun->iLength; - CFX_RectF rect(*pTxtRun->pRect); - FX_FLOAT fFontSize = pTxtRun->fFontSize; - int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); - FX_FLOAT fScale = fFontSize / 1000.0f; - CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont; - if (!pFont) - bCharBBox = false; - - CFX_Rect bbox; - if (bCharBBox) - bCharBBox = pFont->GetBBox(&bbox); - - FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale); - FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale); - bool bRTLPiece = !!(pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel); - bool bVertical = !!(pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout); - bool bSingleLine = !!(pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine); - bool bCombText = !!(pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText); - FX_WCHAR wch; - FX_WCHAR wLineBreakChar = pTxtRun->wLineBreakChar; - int32_t iCharSize; - FX_FLOAT fCharSize; - FX_FLOAT fStart; - if (bVertical) - fStart = bRTLPiece ? rect.bottom() : rect.top; - else - fStart = bRTLPiece ? rect.right() : rect.left; - - std::vector<CFX_RectF> rtArray(iLength); - for (int32_t i = 0; i < iLength; i++) { - if (pAccess) { - wch = pAccess->GetChar(pIdentity, i); - iCharSize = pAccess->GetWidth(pIdentity, i); - } else { - wch = *pStr++; - iCharSize = *pWidths++; - } - fCharSize = static_cast<FX_FLOAT>(iCharSize) / 20000.0f; - bool bRet = (!bSingleLine && FX_IsCtrlCode(wch)); - if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 || - (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) { - bRet = false; - } - if (bRet) { - iCharSize = iFontSize * 500; - fCharSize = fFontSize / 2.0f; - } - if (bVertical) { - rect.top = fStart; - if (bRTLPiece) { - rect.top -= fCharSize; - fStart -= fCharSize; - } else { - fStart += fCharSize; - } - rect.height = fCharSize; - } else { - rect.left = fStart; - if (bRTLPiece) { - rect.left -= fCharSize; - fStart -= fCharSize; - } else { - fStart += fCharSize; - } - rect.width = fCharSize; - } - - if (bCharBBox && !bRet) { - int32_t iCharWidth = 1000; - pFont->GetCharWidth(wch, iCharWidth, false); - FX_FLOAT fRTLeft = 0, fCharWidth = 0; - if (iCharWidth > 0) { - fCharWidth = iCharWidth * fScale; - fRTLeft = fLeft; - if (bCombText) - fRTLeft = (rect.width - fCharWidth) / 2.0f; - } - CFX_RectF rtBBoxF; - if (bVertical) { - rtBBoxF.top = rect.left + fRTLeft; - rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f; - rtBBoxF.height = fCharWidth; - rtBBoxF.width = fHeight; - rtBBoxF.left = std::max(rtBBoxF.left, 0.0f); - } else { - rtBBoxF.left = rect.left + fRTLeft; - rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f; - rtBBoxF.width = fCharWidth; - rtBBoxF.height = fHeight; - rtBBoxF.top = std::max(rtBBoxF.top, 0.0f); - } - rtArray[i] = rtBBoxF; - continue; - } - rtArray[i] = rect; - } - return rtArray; -} - -FX_TXTRUN::FX_TXTRUN() - : pAccess(nullptr), - pIdentity(nullptr), - pWidths(nullptr), - iLength(0), - pFont(nullptr), - fFontSize(12), - dwStyles(0), - iHorizontalScale(100), - iVerticalScale(100), - iCharRotation(0), - dwCharStyles(0), - pRect(nullptr), - wLineBreakChar(L'\n'), - bSkipSpace(true) {} - -FX_TXTRUN::~FX_TXTRUN() {} - -FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default; - -CFX_TxtPiece::CFX_TxtPiece() - : m_dwStatus(FX_TXTBREAK_PieceBreak), - m_iStartPos(0), - m_iWidth(-1), - m_iStartChar(0), - m_iChars(0), - m_iBidiLevel(0), - m_iBidiPos(0), - m_iHorizontalScale(100), - m_iVerticalScale(100), - m_dwCharStyles(0), - m_pChars(nullptr), - m_pUserData(nullptr) {} - -CFX_TxtLine::CFX_TxtLine(int32_t iBlockSize) - : m_pLineChars(new std::vector<CFX_TxtChar>), - m_pLinePieces(new CFX_TxtPieceArray(16)), - m_iStart(0), - m_iWidth(0), - m_iArabicChars(0) {} - -CFX_TxtLine::~CFX_TxtLine() { - RemoveAll(); -} diff --git a/xfa/fgas/layout/fgas_textbreak.h b/xfa/fgas/layout/fgas_textbreak.h deleted file mode 100644 index 69ca835fadf790f1303d993da734e7ef0dfbfdb8..0000000000000000000000000000000000000000 --- a/xfa/fgas/layout/fgas_textbreak.h +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_ -#define XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_ - -#include <deque> -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_ucd.h" -#include "core/fxge/cfx_renderdevice.h" -#include "third_party/base/stl_util.h" -#include "xfa/fgas/crt/fgas_utils.h" - -class CFX_Char; -class CFGAS_GEFont; -class CFX_TxtChar; -class CFX_TxtPiece; -class IFX_TxtAccess; -struct FDE_TEXTEDITPIECE; - -#define FX_TXTBREAKPOLICY_None 0x00 -#define FX_TXTBREAKPOLICY_Pagination 0x01 -#define FX_TXTBREAKPOLICY_SpaceBreak 0x02 -#define FX_TXTBREAKPOLICY_NumberBreak 0x04 -#define FX_TXTBREAK_None 0x00 -#define FX_TXTBREAK_PieceBreak 0x01 -#define FX_TXTBREAK_LineBreak 0x02 -#define FX_TXTBREAK_ParagraphBreak 0x03 -#define FX_TXTBREAK_PageBreak 0x04 -#define FX_TXTBREAK_ControlChar 0x10 -#define FX_TXTBREAK_BreakChar 0x20 -#define FX_TXTBREAK_UnknownChar 0x40 -#define FX_TXTBREAK_RemoveChar 0x80 -#define FX_TXTLAYOUTSTYLE_MutipleFormat 0x0001 -#define FX_TXTLAYOUTSTYLE_VerticalLayout 0x0002 -#define FX_TXTLAYOUTSTYLE_VerticalChars 0x0004 -#define FX_TXTLAYOUTSTYLE_ReverseLine 0x0008 -#define FX_TXTLAYOUTSTYLE_ArabicContext 0x0010 -#define FX_TXTLAYOUTSTYLE_ArabicShapes 0x0020 -#define FX_TXTLAYOUTSTYLE_RTLReadingOrder 0x0040 -#define FX_TXTLAYOUTSTYLE_ExpandTab 0x0100 -#define FX_TXTLAYOUTSTYLE_SingleLine 0x0200 -#define FX_TXTLAYOUTSTYLE_CombText 0x0400 -#define FX_TXTCHARSTYLE_Alignment 0x000F -#define FX_TXTCHARSTYLE_ArabicNumber 0x0010 -#define FX_TXTCHARSTYLE_ArabicShadda 0x0020 -#define FX_TXTCHARSTYLE_OddBidiLevel 0x0040 -#define FX_TXTCHARSTYLE_RTLReadingOrder 0x0080 -#define FX_TXTCHARSTYLE_ArabicContext 0x0300 -#define FX_TXTCHARSTYLE_ArabicIndic 0x0400 -#define FX_TXTCHARSTYLE_ArabicComma 0x0800 -#define FX_TXTLINEALIGNMENT_Left 0 -#define FX_TXTLINEALIGNMENT_Center 1 -#define FX_TXTLINEALIGNMENT_Right 2 -#define FX_TXTLINEALIGNMENT_Justified (1 << 2) -#define FX_TXTLINEALIGNMENT_Distributed (2 << 2) -#define FX_TXTLINEALIGNMENT_JustifiedLeft \ - (FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Justified) -#define FX_TXTLINEALIGNMENT_JustifiedCenter \ - (FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Justified) -#define FX_TXTLINEALIGNMENT_JustifiedRight \ - (FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Justified) -#define FX_TXTLINEALIGNMENT_DistributedLeft \ - (FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Distributed) -#define FX_TXTLINEALIGNMENT_DistributedCenter \ - (FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Distributed) -#define FX_TXTLINEALIGNMENT_DistributedRight \ - (FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Distributed) -#define FX_TXTLINEALIGNMENT_LowerMask 0x03 -#define FX_TXTLINEALIGNMENT_HigherMask 0x0C -#define FX_TXTBREAK_MinimumTabWidth 160000 - -struct FX_TPO { - int32_t index; - int32_t pos; - - bool operator<(const FX_TPO& that) const { return pos < that.pos; } -}; - -class IFX_TxtAccess { - public: - virtual ~IFX_TxtAccess() {} - virtual FX_WCHAR GetChar(const FDE_TEXTEDITPIECE* pIdentity, - int32_t index) const = 0; - virtual int32_t GetWidth(const FDE_TEXTEDITPIECE* pIdentity, - int32_t index) const = 0; -}; - -struct FX_TXTRUN { - FX_TXTRUN(); - FX_TXTRUN(const FX_TXTRUN& other); - ~FX_TXTRUN(); - - IFX_TxtAccess* pAccess; - const FDE_TEXTEDITPIECE* pIdentity; - CFX_WideString wsStr; - int32_t* pWidths; - int32_t iLength; - CFX_RetainPtr<CFGAS_GEFont> pFont; - FX_FLOAT fFontSize; - uint32_t dwStyles; - int32_t iHorizontalScale; - int32_t iVerticalScale; - int32_t iCharRotation; - uint32_t dwCharStyles; - const CFX_RectF* pRect; - FX_WCHAR wLineBreakChar; - bool bSkipSpace; -}; - -class CFX_TxtPiece { - public: - CFX_TxtPiece(); - - int32_t GetEndPos() const { - return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth; - } - int32_t GetLength() const { return m_iChars; } - int32_t GetEndChar() const { return m_iStartChar + m_iChars; } - CFX_TxtChar* GetCharPtr(int32_t index) const { - ASSERT(index > -1 && index < m_iChars && m_pChars); - return &(*m_pChars)[m_iStartChar + index]; - } - void GetString(FX_WCHAR* pText) const { - ASSERT(pText); - int32_t iEndChar = m_iStartChar + m_iChars; - for (int32_t i = m_iStartChar; i < iEndChar; i++) - *pText++ = static_cast<FX_WCHAR>((*m_pChars)[i].m_wCharCode); - } - void GetString(CFX_WideString& wsText) const { - FX_WCHAR* pText = wsText.GetBuffer(m_iChars); - GetString(pText); - wsText.ReleaseBuffer(m_iChars); - } - void GetWidths(int32_t* pWidths) const { - ASSERT(pWidths); - int32_t iEndChar = m_iStartChar + m_iChars; - for (int32_t i = m_iStartChar; i < iEndChar; i++) - *pWidths++ = (*m_pChars)[i].m_iCharWidth; - } - - uint32_t m_dwStatus; - int32_t m_iStartPos; - int32_t m_iWidth; - int32_t m_iStartChar; - int32_t m_iChars; - int32_t m_iBidiLevel; - int32_t m_iBidiPos; - int32_t m_iHorizontalScale; - int32_t m_iVerticalScale; - uint32_t m_dwCharStyles; - std::vector<CFX_TxtChar>* m_pChars; - void* m_pUserData; -}; - -typedef CFX_BaseArrayTemplate<CFX_TxtPiece> CFX_TxtPieceArray; - -class CFX_TxtLine { - public: - explicit CFX_TxtLine(int32_t iBlockSize); - ~CFX_TxtLine(); - - int32_t CountChars() const { - return pdfium::CollectionSize<int32_t>(*m_pLineChars); - } - - CFX_TxtChar* GetCharPtr(int32_t index) const { - ASSERT(index >= 0 && - index < pdfium::CollectionSize<int32_t>(*m_pLineChars)); - return &(*m_pLineChars)[index]; - } - - int32_t CountPieces() const { return m_pLinePieces->GetSize(); } - CFX_TxtPiece* GetPiecePtr(int32_t index) const { - ASSERT(index > -1 && index < m_pLinePieces->GetSize()); - return m_pLinePieces->GetPtrAt(index); - } - - void GetString(CFX_WideString& wsStr) const { - int32_t iCount = pdfium::CollectionSize<int32_t>(*m_pLineChars); - FX_WCHAR* pBuf = wsStr.GetBuffer(iCount); - for (int32_t i = 0; i < iCount; i++) - *pBuf++ = static_cast<FX_WCHAR>((*m_pLineChars)[i].m_wCharCode); - wsStr.ReleaseBuffer(iCount); - } - - void RemoveAll(bool bLeaveMemory = false) { - m_pLineChars->clear(); - m_pLinePieces->RemoveAll(bLeaveMemory); - m_iWidth = 0; - m_iArabicChars = 0; - } - - std::unique_ptr<std::vector<CFX_TxtChar>> m_pLineChars; - std::unique_ptr<CFX_TxtPieceArray> m_pLinePieces; - int32_t m_iStart; - int32_t m_iWidth; - int32_t m_iArabicChars; -}; - -class CFX_TxtBreak { - public: - explicit CFX_TxtBreak(uint32_t dwPolicies); - ~CFX_TxtBreak(); - - void SetLineWidth(FX_FLOAT fLineWidth); - void SetLinePos(FX_FLOAT fLinePos); - uint32_t GetLayoutStyles() const { return m_dwLayoutStyles; } - void SetLayoutStyles(uint32_t dwLayoutStyles); - void SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont); - void SetFontSize(FX_FLOAT fFontSize); - void SetTabWidth(FX_FLOAT fTabWidth, bool bEquidistant); - void SetDefaultChar(FX_WCHAR wch); - void SetParagraphBreakChar(FX_WCHAR wch); - void SetLineBreakTolerance(FX_FLOAT fTolerance); - void SetHorizontalScale(int32_t iScale); - void SetCharRotation(int32_t iCharRotation); - void SetCharSpace(FX_FLOAT fCharSpace); - void SetAlignment(int32_t iAlignment); - void SetCombWidth(FX_FLOAT fCombWidth); - void SetUserData(void* pUserData); - uint32_t AppendChar(FX_WCHAR wch); - uint32_t EndBreak(uint32_t dwStatus = FX_TXTBREAK_PieceBreak); - int32_t CountBreakPieces() const; - const CFX_TxtPiece* GetBreakPiece(int32_t index) const; - void ClearBreakPieces(); - void Reset(); - int32_t GetDisplayPos(const FX_TXTRUN* pTxtRun, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode = false, - CFX_WideString* pWSForms = nullptr) const; - std::vector<CFX_RectF> GetCharRects(const FX_TXTRUN* pTxtRun, - bool bCharBBox = false) const; - void AppendChar_PageLoad(CFX_TxtChar* pCurChar, uint32_t dwProps); - uint32_t AppendChar_Combination(CFX_TxtChar* pCurChar, int32_t iRotation); - uint32_t AppendChar_Tab(CFX_TxtChar* pCurChar, int32_t iRotation); - uint32_t AppendChar_Control(CFX_TxtChar* pCurChar, int32_t iRotation); - uint32_t AppendChar_Arabic(CFX_TxtChar* pCurChar, int32_t iRotation); - uint32_t AppendChar_Others(CFX_TxtChar* pCurChar, int32_t iRotation); - - private: - void FontChanged(); - void SetBreakStatus(); - int32_t GetLineRotation(uint32_t dwStyles) const; - CFX_TxtChar* GetLastChar(int32_t index, bool bOmitChar = true) const; - CFX_TxtLine* GetTxtLine() const; - CFX_TxtPieceArray* GetTxtPieces() const; - FX_CHARTYPE GetUnifiedCharType(FX_CHARTYPE dwType) const; - void ResetArabicContext(); - void ResetContextCharStyles(); - void EndBreak_UpdateArabicShapes(); - bool EndBreak_SplitLine(CFX_TxtLine* pNextLine, - bool bAllChars, - uint32_t dwStatus); - void EndBreak_BidiLine(std::deque<FX_TPO>* tpos, uint32_t dwStatus); - void EndBreak_Alignment(const std::deque<FX_TPO>& tpos, - bool bAllChars, - uint32_t dwStatus); - int32_t GetBreakPos(std::vector<CFX_TxtChar>& ca, - int32_t& iEndPos, - bool bAllChars = false, - bool bOnlyBrk = false); - void SplitTextLine(CFX_TxtLine* pCurLine, - CFX_TxtLine* pNextLine, - bool bAllChars = false); - - uint32_t m_dwPolicies; - bool m_bPagination; - int32_t m_iLineWidth; - uint32_t m_dwLayoutStyles; - bool m_bVertical; - bool m_bArabicContext; - bool m_bArabicShapes; - bool m_bRTL; - bool m_bSingleLine; - bool m_bCombText; - int32_t m_iArabicContext; - int32_t m_iCurArabicContext; - CFX_RetainPtr<CFGAS_GEFont> m_pFont; - int32_t m_iFontSize; - bool m_bEquidistant; - int32_t m_iTabWidth; - FX_WCHAR m_wDefChar; - FX_WCHAR m_wParagBreakChar; - int32_t m_iDefChar; - int32_t m_iLineRotation; - int32_t m_iCharRotation; - int32_t m_iRotation; - int32_t m_iAlignment; - uint32_t m_dwContextCharStyles; - int32_t m_iCombWidth; - void* m_pUserData; - FX_CHARTYPE m_eCharType; - bool m_bCurRTL; - int32_t m_iCurAlignment; - bool m_bArabicNumber; - bool m_bArabicComma; - std::unique_ptr<CFX_TxtLine> m_pTxtLine1; - std::unique_ptr<CFX_TxtLine> m_pTxtLine2; - CFX_TxtLine* m_pCurLine; - int32_t m_iReady; - int32_t m_iTolerance; - int32_t m_iHorScale; - int32_t m_iCharSpace; -}; - -#endif // XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_ diff --git a/xfa/fgas/localization/fgas_datetime.cpp b/xfa/fgas/localization/fgas_datetime.cpp deleted file mode 100644 index 83000a4f205a76cdd231014f6637bd8d5f481b29..0000000000000000000000000000000000000000 --- a/xfa/fgas/localization/fgas_datetime.cpp +++ /dev/null @@ -1,550 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fx_system.h" -#include "xfa/fgas/localization/fgas_datetime.h" - -#if _FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_ANDROID_ || \ - _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ -#include <sys/time.h> -#include <time.h> -#endif - -const uint8_t g_FXDaysPerMonth[12] = {31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; -const uint8_t g_FXDaysPerLeapMonth[12] = {31, 29, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; -const int32_t g_FXDaysBeforeMonth[12] = {0, 31, 59, 90, 120, 151, - 181, 212, 243, 273, 304, 334}; -const int32_t g_FXDaysBeforeLeapMonth[12] = {0, 31, 60, 91, 121, 152, - 182, 213, 244, 274, 305, 335}; -const int32_t g_FXDaysPerYear = 365; -const int32_t g_FXDaysPerLeapYear = 366; -const int32_t g_FXDaysPer4Years = 1461; -const int32_t g_FXDaysPer100Years = 36524; -const int32_t g_FXDaysPer400Years = 146097; -const int64_t g_FXMillisecondsPerSecond = 1000; -const int64_t g_FXMillisecondsPerMinute = 60000; -const int64_t g_FXMillisecondsPerHour = 3600000; -const int64_t g_FXMillisecondsPerDay = 86400000; -bool FX_IsLeapYear(int32_t iYear) { - ASSERT(iYear != 0); - return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0; -} -int32_t FX_DaysInYear(int32_t iYear) { - ASSERT(iYear != 0); - return FX_IsLeapYear(iYear) ? g_FXDaysPerLeapYear : g_FXDaysPerYear; -} -uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth) { - ASSERT(iYear != 0); - ASSERT(iMonth >= 1 && iMonth <= 12); - const uint8_t* p = - FX_IsLeapYear(iYear) ? g_FXDaysPerLeapMonth : g_FXDaysPerMonth; - return p[iMonth - 1]; -} -static int32_t FX_DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) { - ASSERT(iYear != 0); - ASSERT(iMonth >= 1 && iMonth <= 12); - const int32_t* p = - FX_IsLeapYear(iYear) ? g_FXDaysBeforeLeapMonth : g_FXDaysBeforeMonth; - return p[iMonth - 1]; -} -static int64_t FX_DateToDays(int32_t iYear, - uint8_t iMonth, - uint8_t iDay, - bool bIncludeThisDay = false) { - ASSERT(iYear != 0); - ASSERT(iMonth >= 1 && iMonth <= 12); - ASSERT(iDay >= 1 && iDay <= FX_DaysInMonth(iYear, iMonth)); - int64_t iDays = FX_DaysBeforeMonthInYear(iYear, iMonth); - iDays += iDay; - if (!bIncludeThisDay) { - iDays--; - } - if (iYear > 0) { - iYear--; - } else { - iDays -= FX_DaysInYear(iYear); - iYear++; - } - return iDays + (int64_t)iYear * 365 + iYear / 4 - iYear / 100 + iYear / 400; -} -static void FX_DaysToDate(int64_t iDays, - int32_t& iYear, - uint8_t& iMonth, - uint8_t& iDay) { - bool bBC = iDays < 0; - if (bBC) { - iDays = -iDays; - } - iYear = 1; - iMonth = 1; - iDay = 1; - if (iDays >= g_FXDaysPer400Years) { - iYear += (int32_t)(iDays / g_FXDaysPer400Years * 400); - iDays %= g_FXDaysPer400Years; - } - if (iDays >= g_FXDaysPer100Years) { - if (iDays == g_FXDaysPer100Years * 4) { - iYear += 300; - iDays -= g_FXDaysPer100Years * 3; - } else { - iYear += (int32_t)(iDays / g_FXDaysPer100Years * 100); - iDays %= g_FXDaysPer100Years; - } - } - if (iDays >= g_FXDaysPer4Years) { - iYear += (int32_t)(iDays / g_FXDaysPer4Years * 4); - iDays %= g_FXDaysPer4Years; - } - while (true) { - int32_t iYearDays = FX_DaysInYear(iYear); - if (iDays < iYearDays) { - if (bBC) { - iYear = -iYear; - iDays = iYearDays - iDays; - } - break; - } - iYear++; - iDays -= iYearDays; - } - while (true) { - int32_t iMonthDays = FX_DaysInMonth(iYear, iMonth); - if (iDays < iMonthDays) { - break; - } - iMonth++; - iDays -= iMonthDays; - } - iDay += (uint8_t)iDays; -} - -struct FXUT_SYSTEMTIME { - uint16_t wYear; - uint16_t wMonth; - uint16_t wDayOfWeek; - uint16_t wDay; - uint16_t wHour; - uint16_t wMinute; - uint16_t wSecond; - uint16_t wMilliseconds; -}; - -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, nullptr); -#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, (uint8_t)utLocal.wMonth, (uint8_t)utLocal.wDay, - (uint8_t)utLocal.wHour, (uint8_t)utLocal.wMinute, - (uint8_t)utLocal.wSecond, (uint16_t)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, nullptr); -#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, (uint8_t)utLocal.wMonth, (uint8_t)utLocal.wDay, - (uint8_t)utLocal.wHour, (uint8_t)utLocal.wMinute, - (uint8_t)utLocal.wSecond, (uint16_t)utLocal.wMilliseconds); -} -void CFX_Unitime::Set(int32_t year, - uint8_t month, - uint8_t day, - uint8_t hour, - uint8_t minute, - uint8_t second, - uint16_t millisecond) { - ASSERT(hour <= 23); - ASSERT(minute <= 59); - ASSERT(second <= 59); - ASSERT(millisecond <= 999); - m_iUnitime = (int64_t)hour * g_FXMillisecondsPerHour + - (int64_t)minute * g_FXMillisecondsPerMinute + - (int64_t)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; -} -int32_t CFX_Unitime::GetYear() const { - int32_t iYear; - uint8_t iMonth, iDay; - FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay); - return iYear; -} -uint8_t CFX_Unitime::GetMonth() const { - int32_t iYear; - uint8_t iMonth, iDay; - FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay); - return iMonth; -} -uint8_t CFX_Unitime::GetDay() const { - int32_t iYear; - uint8_t iMonth, iDay; - FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay); - return iDay; -} -FX_WEEKDAY CFX_Unitime::GetDayOfWeek() const { - int32_t v = (int32_t)((m_iUnitime / g_FXMillisecondsPerDay + 1) % 7); - if (v < 0) { - v += 7; - } - return (FX_WEEKDAY)v; -} -uint16_t CFX_Unitime::GetDayOfYear() const { - int32_t iYear; - uint8_t iMonth, iDay; - FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay); - return FX_DaysBeforeMonthInYear(iYear, iMonth) + iDay; -} -int64_t CFX_Unitime::GetDayOfAD() const { - bool bBC = m_iUnitime < 0; - int64_t iDays = m_iUnitime / g_FXMillisecondsPerDay; - iDays += bBC ? -1 : 0; - if (bBC && (m_iUnitime % g_FXMillisecondsPerDay) == 0) { - iDays++; - } - return iDays; -} -uint8_t CFX_Unitime::GetHour() const { - int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerDay); - if (v < 0) { - v += g_FXMillisecondsPerDay; - } - return (uint8_t)(v / g_FXMillisecondsPerHour); -} -uint8_t CFX_Unitime::GetMinute() const { - int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerHour); - if (v < 0) { - v += g_FXMillisecondsPerHour; - } - return (uint8_t)(v / g_FXMillisecondsPerMinute); -} -uint8_t CFX_Unitime::GetSecond() const { - int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerMinute); - if (v < 0) { - v += g_FXMillisecondsPerMinute; - } - return (uint8_t)(v / g_FXMillisecondsPerSecond); -} -uint16_t CFX_Unitime::GetMillisecond() const { - int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerSecond); - if (v < 0) { - v += g_FXMillisecondsPerSecond; - } - return (uint16_t)v; -} -bool CFX_Unitime::AddYears(int32_t iYears) { - FX_UNITIME ut = m_iUnitime; - if (ut < 0) { - ut = -ut; - } - FX_UNITIME r = ut % g_FXMillisecondsPerDay; - int32_t iYear; - uint8_t 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; -} -bool CFX_Unitime::AddMonths(int32_t iMonths) { - bool b = iMonths > 0; - FX_UNITIME ut = m_iUnitime; - if (ut < 0) { - ut = -ut; - } - FX_UNITIME r = ut % g_FXMillisecondsPerDay; - int32_t iYear; - uint8_t 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, (uint8_t)iMonths, iDay, false) * - g_FXMillisecondsPerDay; - m_iUnitime += (iYear < 0) ? -r : r; - return true; -} -bool CFX_Unitime::AddDays(int32_t iDays) { - m_iUnitime += (int64_t)iDays * g_FXMillisecondsPerDay; - return true; -} -bool CFX_Unitime::AddHours(int32_t iHours) { - m_iUnitime += (int64_t)iHours * g_FXMillisecondsPerHour; - return true; -} -bool CFX_Unitime::AddMinutes(int32_t iMinutes) { - m_iUnitime += (int64_t)iMinutes * g_FXMillisecondsPerMinute; - return true; -} -bool CFX_Unitime::AddSeconds(int32_t iSeconds) { - m_iUnitime += ((int64_t)iSeconds) * g_FXMillisecondsPerSecond; - return true; -} -bool CFX_Unitime::AddMilliseconds(int32_t iMilliseconds) { - m_iUnitime += iMilliseconds; - return true; -} -bool CFX_DateTime::Set(int32_t year, - uint8_t month, - uint8_t day, - uint8_t hour, - uint8_t minute, - uint8_t second, - uint16_t 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; -} -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 = - (int64_t)m_DateTime.Date.sDate.day * g_FXMillisecondsPerHour + - (int64_t)m_DateTime.Time.sTime.minute * g_FXMillisecondsPerMinute + - (int64_t)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; -} -int32_t CFX_DateTime::GetYear() const { - return m_DateTime.Date.sDate.year; -} -uint8_t CFX_DateTime::GetMonth() const { - return m_DateTime.Date.sDate.month; -} -uint8_t CFX_DateTime::GetDay() const { - return m_DateTime.Date.sDate.day; -} -FX_WEEKDAY CFX_DateTime::GetDayOfWeek() const { - int32_t v = (int32_t)(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; -} -uint16_t CFX_DateTime::GetDayOfYear() const { - return FX_DaysBeforeMonthInYear(m_DateTime.Date.sDate.year, - m_DateTime.Date.sDate.month) + - m_DateTime.Date.sDate.day; -} -int64_t CFX_DateTime::GetDayOfAD() const { - return FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, - m_DateTime.Date.sDate.day, true); -} -uint8_t CFX_DateTime::GetHour() const { - return m_DateTime.Date.sDate.day; -} -uint8_t CFX_DateTime::GetMinute() const { - return m_DateTime.Time.sTime.minute; -} -uint8_t CFX_DateTime::GetSecond() const { - return m_DateTime.Time.sTime.second; -} -uint16_t CFX_DateTime::GetMillisecond() const { - return m_DateTime.Time.sTime.millisecond; -} -bool CFX_DateTime::AddYears(int32_t iYears) { - if (iYears == 0) { - return false; - } - int32_t 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; -} -bool CFX_DateTime::AddMonths(int32_t iMonths) { - if (iMonths == 0) { - return false; - } - 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 = (uint8_t)iMonths; - return true; -} -bool CFX_DateTime::AddDays(int32_t iDays) { - if (iDays == 0) { - return false; - } - int64_t v1 = - FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, - m_DateTime.Date.sDate.day, true); - int64_t 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; -} -bool CFX_DateTime::AddHours(int32_t iHours) { - if (iHours == 0) { - return false; - } - iHours += m_DateTime.Date.sDate.day; - int32_t iDays = iHours / 24; - iHours %= 24; - if (iHours < 0) { - iDays--, iHours += 24; - } - m_DateTime.Date.sDate.day = (uint8_t)iHours; - if (iDays != 0) { - AddDays(iDays); - } - return true; -} -bool CFX_DateTime::AddMinutes(int32_t iMinutes) { - if (iMinutes == 0) { - return false; - } - iMinutes += m_DateTime.Time.sTime.minute; - int32_t iHours = iMinutes / 60; - iMinutes %= 60; - if (iMinutes < 0) { - iHours--, iMinutes += 60; - } - m_DateTime.Time.sTime.minute = (uint8_t)iMinutes; - if (iHours != 0) { - AddHours(iHours); - } - return true; -} -bool CFX_DateTime::AddSeconds(int32_t iSeconds) { - if (iSeconds == 0) { - return false; - } - iSeconds += m_DateTime.Time.sTime.second; - int32_t iMinutes = iSeconds / 60; - iSeconds %= 60; - if (iSeconds < 0) { - iMinutes--, iSeconds += 60; - } - m_DateTime.Time.sTime.second = (uint8_t)iSeconds; - if (iMinutes != 0) { - AddMinutes(iMinutes); - } - return true; -} -bool CFX_DateTime::AddMilliseconds(int32_t iMilliseconds) { - if (iMilliseconds == 0) { - return false; - } - iMilliseconds += m_DateTime.Time.sTime.millisecond; - int32_t iSeconds = (int32_t)(iMilliseconds / g_FXMillisecondsPerSecond); - iMilliseconds %= g_FXMillisecondsPerSecond; - if (iMilliseconds < 0) { - iSeconds--, iMilliseconds += g_FXMillisecondsPerSecond; - } - m_DateTime.Time.sTime.millisecond = (uint16_t)iMilliseconds; - if (iSeconds != 0) { - AddSeconds(iSeconds); - } - return true; -} diff --git a/xfa/fgas/localization/fgas_datetime.h b/xfa/fgas/localization/fgas_datetime.h deleted file mode 100644 index d3ea9fa4a6a14df1fa8f456adf0012c447d664cf..0000000000000000000000000000000000000000 --- a/xfa/fgas/localization/fgas_datetime.h +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_LOCALIZATION_FGAS_DATETIME_H_ -#define XFA_FGAS_LOCALIZATION_FGAS_DATETIME_H_ - -#include "core/fxcrt/fx_system.h" - -class CFX_Unitime; -class CFX_DateTime; - -typedef int64_t FX_UNITIME; -enum FX_WEEKDAY { - FX_Sunday = 0, - FX_Monday, - FX_Tuesday, - FX_Wednesday, - FX_Thursday, - FX_Friday, - FX_Saturday, -}; - -bool FX_IsLeapYear(int32_t iYear); -int32_t FX_DaysInYear(int32_t iYear); -uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth); - -class CFX_Unitime { - public: - CFX_Unitime() { m_iUnitime = 0; } - explicit CFX_Unitime(FX_UNITIME iUnitime) { m_iUnitime = iUnitime; } - CFX_Unitime(const CFX_Unitime& unitime) { m_iUnitime = unitime.m_iUnitime; } - operator FX_UNITIME*() { return &m_iUnitime; } - operator FX_UNITIME const*() const { return &m_iUnitime; } - operator FX_UNITIME&() { return m_iUnitime; } - operator const FX_UNITIME&() const { return m_iUnitime; } - CFX_Unitime& operator=(const CFX_Unitime& t) { - m_iUnitime = t.m_iUnitime; - return *this; - } - CFX_Unitime& operator=(FX_UNITIME t) { - m_iUnitime = t; - return *this; - } - CFX_Unitime& operator+=(const CFX_Unitime& t) { - m_iUnitime += t.m_iUnitime; - return *this; - } - CFX_Unitime& operator+=(FX_UNITIME t) { - m_iUnitime += t; - return *this; - } - CFX_Unitime& operator-=(const CFX_Unitime& t) { - m_iUnitime -= t.m_iUnitime; - return *this; - } - CFX_Unitime& operator-=(FX_UNITIME t) { - m_iUnitime -= t; - return *this; - } - void Now(); - void SetGMTime(); - void Set(int32_t year, - uint8_t month, - uint8_t day, - uint8_t hour = 0, - uint8_t minute = 0, - uint8_t second = 0, - uint16_t millisecond = 0); - void Set(FX_UNITIME t); - int32_t GetYear() const; - uint8_t GetMonth() const; - uint8_t GetDay() const; - FX_WEEKDAY GetDayOfWeek() const; - uint16_t GetDayOfYear() const; - int64_t GetDayOfAD() const; - uint8_t GetHour() const; - uint8_t GetMinute() const; - uint8_t GetSecond() const; - uint16_t GetMillisecond() const; - bool AddYears(int32_t iYears); - bool AddMonths(int32_t iMonths); - bool AddDays(int32_t iDays); - bool AddHours(int32_t iHours); - bool AddMinutes(int32_t iMinutes); - bool AddSeconds(int32_t iSeconds); - bool AddMilliseconds(int32_t iMilliseconds); - friend CFX_Unitime operator+(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return CFX_Unitime(t1.m_iUnitime + t2.m_iUnitime); - } - friend CFX_Unitime operator+(const CFX_Unitime& t1, FX_UNITIME t2) { - return CFX_Unitime(t1.m_iUnitime + t2); - } - friend CFX_Unitime operator+(FX_UNITIME t1, const CFX_Unitime& t2) { - return CFX_Unitime(t1 + t2.m_iUnitime); - } - friend CFX_Unitime operator-(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return CFX_Unitime(t1.m_iUnitime + t2.m_iUnitime); - } - friend CFX_Unitime operator-(const CFX_Unitime& t1, FX_UNITIME t2) { - return CFX_Unitime(t1.m_iUnitime + t2); - } - friend CFX_Unitime operator-(FX_UNITIME t1, const CFX_Unitime& t2) { - return CFX_Unitime(t1 + t2.m_iUnitime); - } - friend bool operator==(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return t1.m_iUnitime == t2.m_iUnitime; - } - friend bool operator==(const CFX_Unitime& t1, FX_UNITIME t2) { - return t1.m_iUnitime == t2; - } - friend bool operator==(FX_UNITIME t1, const CFX_Unitime& t2) { - return t1 == t2.m_iUnitime; - } - friend bool operator!=(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return t1.m_iUnitime != t2.m_iUnitime; - } - friend bool operator!=(const CFX_Unitime& t1, FX_UNITIME t2) { - return t1.m_iUnitime != t2; - } - friend bool operator!=(FX_UNITIME t1, const CFX_Unitime& t2) { - return t1 != t2.m_iUnitime; - } - friend bool operator>(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return t1.m_iUnitime > t2.m_iUnitime; - } - friend bool operator>(const CFX_Unitime& t1, FX_UNITIME t2) { - return t1.m_iUnitime > t2; - } - friend bool operator>(FX_UNITIME t1, const CFX_Unitime& t2) { - return t1 > t2.m_iUnitime; - } - friend bool operator>=(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return t1.m_iUnitime >= t2.m_iUnitime; - } - friend bool operator>=(const CFX_Unitime& t1, FX_UNITIME t2) { - return t1.m_iUnitime >= t2; - } - friend bool operator>=(FX_UNITIME t1, const CFX_Unitime& t2) { - return t1 >= t2.m_iUnitime; - } - friend bool operator<(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return t1.m_iUnitime < t2.m_iUnitime; - } - friend bool operator<(const CFX_Unitime& t1, FX_UNITIME t2) { - return t1.m_iUnitime < t2; - } - friend bool operator<(FX_UNITIME t1, const CFX_Unitime& t2) { - return t1 < t2.m_iUnitime; - } - friend bool operator<=(const CFX_Unitime& t1, const CFX_Unitime& t2) { - return t1.m_iUnitime <= t2.m_iUnitime; - } - friend bool operator<=(const CFX_Unitime& t1, FX_UNITIME t2) { - return t1.m_iUnitime <= t2; - } - friend bool operator<=(FX_UNITIME t1, const CFX_Unitime& t2) { - return t1 <= t2.m_iUnitime; - } - - private: - FX_UNITIME m_iUnitime; -}; - -#if _FX_OS_ != _FX_ANDROID_ -#pragma pack(push, 1) -#endif -struct FX_DATE { - int32_t year; - uint8_t month; - uint8_t day; -}; - -struct FX_TIME { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint16_t millisecond; -}; - -struct FX_TIMEZONE { - int8_t tzHour; - uint8_t tzMinute; -}; - -struct FX_DATETIME { - union { - struct { - int32_t year; - uint8_t month; - uint8_t day; - } sDate; - FX_DATE aDate; - } Date; - union { - struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint16_t millisecond; - } sTime; - FX_TIME aTime; - } Time; -}; - -#if _FX_OS_ != _FX_ANDROID_ -#pragma pack(pop) -#endif - -class CFX_DateTime { - public: - CFX_DateTime() {} - explicit CFX_DateTime(const FX_DATETIME& dt) { m_DateTime = dt; } - CFX_DateTime(const CFX_DateTime& dt) { m_DateTime = dt.m_DateTime; } - virtual ~CFX_DateTime() {} - operator FX_DATETIME*() { return &m_DateTime; } - operator const FX_DATETIME*() const { return &m_DateTime; } - operator FX_DATETIME&() { return m_DateTime; } - operator const FX_DATETIME&() const { return m_DateTime; } - CFX_DateTime& operator=(const CFX_DateTime& dt) { - m_DateTime = dt.m_DateTime; - return *this; - } - CFX_DateTime& operator=(const FX_DATETIME& dt) { - m_DateTime = dt; - return *this; - } - CFX_DateTime& operator+=(const CFX_DateTime& dt) { - FromUnitime(ToUnitime() + dt.ToUnitime()); - return *this; - } - CFX_DateTime& operator+=(const FX_DATETIME& dt) { - FromUnitime(ToUnitime() + ((const CFX_DateTime&)dt).ToUnitime()); - return *this; - } - CFX_DateTime& operator-=(const CFX_DateTime& dt) { - FromUnitime(ToUnitime() - dt.ToUnitime()); - return *this; - } - CFX_DateTime& operator-=(const FX_DATETIME& dt) { - FromUnitime(ToUnitime() - ((const CFX_DateTime&)dt).ToUnitime()); - return *this; - } - virtual bool Set(int32_t year, - uint8_t month, - uint8_t day, - uint8_t hour = 0, - uint8_t minute = 0, - uint8_t second = 0, - uint16_t millisecond = 0); - virtual bool FromUnitime(FX_UNITIME t); - virtual FX_UNITIME ToUnitime() const; - virtual int32_t GetYear() const; - virtual uint8_t GetMonth() const; - virtual uint8_t GetDay() const; - virtual FX_WEEKDAY GetDayOfWeek() const; - virtual uint16_t GetDayOfYear() const; - virtual int64_t GetDayOfAD() const; - virtual uint8_t GetHour() const; - virtual uint8_t GetMinute() const; - virtual uint8_t GetSecond() const; - virtual uint16_t GetMillisecond() const; - virtual bool AddYears(int32_t iYears); - virtual bool AddMonths(int32_t iMonths); - virtual bool AddDays(int32_t iDays); - virtual bool AddHours(int32_t iHours); - virtual bool AddMinutes(int32_t iMinutes); - virtual bool AddSeconds(int32_t iSeconds); - virtual bool AddMilliseconds(int32_t iMilliseconds); - friend CFX_DateTime operator+(const CFX_DateTime& dt1, - const CFX_DateTime& dt2) { - CFX_DateTime dt; - dt.FromUnitime(dt1.ToUnitime() + dt2.ToUnitime()); - return dt; - } - friend CFX_DateTime operator+(const CFX_DateTime& dt1, - const FX_DATETIME& dt2) { - CFX_DateTime dt; - dt.FromUnitime(dt1.ToUnitime() + ((const CFX_DateTime&)dt2).ToUnitime()); - return dt; - } - friend CFX_DateTime operator+(const FX_DATETIME& dt1, - const CFX_DateTime& dt2) { - CFX_DateTime dt; - dt.FromUnitime(((const CFX_DateTime&)dt1).ToUnitime() + dt2.ToUnitime()); - return dt; - } - friend CFX_DateTime operator-(const CFX_DateTime& dt1, - const CFX_DateTime& dt2) { - CFX_DateTime dt; - dt.FromUnitime(dt1.ToUnitime() - dt2.ToUnitime()); - return dt; - } - friend CFX_DateTime operator-(const CFX_DateTime& dt1, - const FX_DATETIME& dt2) { - CFX_DateTime dt; - dt.FromUnitime(dt1.ToUnitime() - ((const CFX_DateTime&)dt2).ToUnitime()); - return dt; - } - friend CFX_DateTime operator-(const FX_DATETIME& dt1, - const CFX_DateTime& dt2) { - CFX_DateTime dt; - dt.FromUnitime(((const CFX_DateTime&)dt1).ToUnitime() - dt2.ToUnitime()); - return dt; - } - friend bool operator==(const CFX_DateTime& dt1, const CFX_DateTime& dt2) { - return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1), - static_cast<const FX_DATETIME*>(dt2), - sizeof(FX_DATETIME)) == 0; - } - friend bool operator==(const CFX_DateTime& dt1, const FX_DATETIME& dt2) { - return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1), &dt2, - sizeof(FX_DATETIME)) == 0; - } - friend bool operator==(const FX_DATETIME& dt1, const CFX_DateTime& dt2) { - return FXSYS_memcmp(&dt1, static_cast<const FX_DATETIME*>(dt2), - sizeof(FX_DATETIME)) == 0; - } - friend bool operator!=(const CFX_DateTime& dt1, const CFX_DateTime& dt2) { - return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1), - static_cast<const FX_DATETIME*>(dt2), - sizeof(FX_DATETIME)) != 0; - } - friend bool operator!=(const CFX_DateTime& dt1, const FX_DATETIME& dt2) { - return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1), &dt2, - sizeof(FX_DATETIME)) != 0; - } - friend bool operator!=(const FX_DATETIME& dt1, const CFX_DateTime& dt2) { - return FXSYS_memcmp(&dt1, static_cast<const FX_DATETIME*>(dt2), - sizeof(FX_DATETIME)) != 0; - } - friend bool operator>(const CFX_DateTime& dt1, const CFX_DateTime& dt2) { - return dt1.ToUnitime() > dt2.ToUnitime(); - } - friend bool operator>(const CFX_DateTime& dt1, const FX_DATETIME& dt2) { - return dt1.ToUnitime() > ((const CFX_DateTime&)dt2).ToUnitime(); - } - friend bool operator>(const FX_DATETIME& dt1, const CFX_DateTime& dt2) { - return ((const CFX_DateTime&)dt1).ToUnitime() > dt2.ToUnitime(); - } - friend bool operator>=(const CFX_DateTime& dt1, const CFX_DateTime& dt2) { - return dt1.ToUnitime() >= dt2.ToUnitime(); - } - friend bool operator>=(const CFX_DateTime& dt1, const FX_DATETIME& dt2) { - return dt1.ToUnitime() >= ((const CFX_DateTime&)dt2).ToUnitime(); - } - friend bool operator>=(const FX_DATETIME& dt1, const CFX_DateTime& dt2) { - return ((const CFX_DateTime&)dt1).ToUnitime() >= dt2.ToUnitime(); - } - friend bool operator<(const CFX_DateTime& dt1, const CFX_DateTime& dt2) { - return dt1.ToUnitime() < dt2.ToUnitime(); - } - friend bool operator<(const CFX_DateTime& dt1, const FX_DATETIME& dt2) { - return dt1.ToUnitime() < ((const CFX_DateTime&)dt2).ToUnitime(); - } - friend bool operator<(const FX_DATETIME& dt1, const CFX_DateTime& dt2) { - return ((const CFX_DateTime&)dt1).ToUnitime() < dt2.ToUnitime(); - } - friend bool operator<=(const CFX_DateTime& dt1, const CFX_DateTime& dt2) { - return dt1.ToUnitime() <= dt2.ToUnitime(); - } - friend bool operator<=(const CFX_DateTime& dt1, const FX_DATETIME& dt2) { - return dt1.ToUnitime() <= ((const CFX_DateTime&)dt2).ToUnitime(); - } - friend bool operator<=(const FX_DATETIME& dt1, const CFX_DateTime& dt2) { - return ((const CFX_DateTime&)dt1).ToUnitime() <= dt2.ToUnitime(); - } - - private: - FX_DATETIME m_DateTime; -}; - -#endif // XFA_FGAS_LOCALIZATION_FGAS_DATETIME_H_ diff --git a/xfa/fgas/localization/fgas_locale.cpp b/xfa/fgas/localization/fgas_locale.cpp deleted file mode 100644 index 7d538411f5296f5dd297ef47496d889bf8cd10b1..0000000000000000000000000000000000000000 --- a/xfa/fgas/localization/fgas_locale.cpp +++ /dev/null @@ -1,4766 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fgas/localization/fgas_locale.h" - -#include <algorithm> -#include <vector> - -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_xml.h" -#include "xfa/fgas/localization/fgas_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 - -struct FX_LOCALESUBCATEGORYINFO { - uint32_t uHash; - const FX_WCHAR* pName; - int32_t eSubCategory; -}; - -static const FX_LOCALESUBCATEGORYINFO g_FXLocaleDateTimeSubCatData[] = { - {0x14da2125, L"default", FX_LOCALEDATETIMESUBCATEGORY_Default}, - {0x9041d4b0, L"short", FX_LOCALEDATETIMESUBCATEGORY_Short}, - {0xa084a381, L"medium", FX_LOCALEDATETIMESUBCATEGORY_Medium}, - {0xcdce56b3, L"full", FX_LOCALEDATETIMESUBCATEGORY_Full}, - {0xf6b4afb0, L"long", FX_LOCALEDATETIMESUBCATEGORY_Long}, -}; -static const int32_t g_iFXLocaleDateTimeSubCatCount = - sizeof(g_FXLocaleDateTimeSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO); - -static const FX_LOCALESUBCATEGORYINFO g_FXLocaleNumSubCatData[] = { - {0x46f95531, L"percent", FX_LOCALENUMPATTERN_Percent}, - {0x4c4e8acb, L"currency", FX_LOCALENUMPATTERN_Currency}, - {0x54034c2f, L"decimal", FX_LOCALENUMPATTERN_Decimal}, - {0x7568e6ae, L"integer", FX_LOCALENUMPATTERN_Integer}, -}; -static const int32_t g_iFXLocaleNumSubCatCount = - sizeof(g_FXLocaleNumSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO); - -struct FX_LOCALETIMEZONEINFO { - uint32_t uHash; - int16_t iHour; - int16_t iMinute; -}; - -static const 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}, -}; - -static const FX_WCHAR gs_wsTimeSymbols[] = L"hHkKMSFAzZ"; -static const FX_WCHAR gs_wsDateSymbols[] = L"DJMEeGgYwW"; -static const FX_WCHAR gs_wsConstChars[] = L",-:/. "; - -static int32_t FX_ParseTimeZone(const FX_WCHAR* pStr, - int32_t iLen, - FX_TIMEZONE& tz) { - tz.tzHour = 0; - tz.tzMinute = 0; - if (iLen < 0) { - return 0; - } - int32_t iStart = 1; - int32_t 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; -} - -class CFX_LCNumeric { - public: - CFX_LCNumeric(); - CFX_LCNumeric(int64_t integral, - uint32_t fractional = 0, - int32_t exponent = 0); - explicit CFX_LCNumeric(FX_FLOAT dbRetValue); - explicit CFX_LCNumeric(double dbvalue); - explicit CFX_LCNumeric(CFX_WideString& wsNumeric); - - FX_FLOAT GetFloat() const; - double GetDouble() const; - CFX_WideString ToString() const; - CFX_WideString ToString(int32_t nTreading, bool bTrimTailZeros) const; - - int64_t m_Integral; - uint32_t m_Fractional; - int32_t m_Exponent; -}; - -static bool FX_WStringToNumeric(const CFX_WideString& wsValue, - CFX_LCNumeric& lcnum) { - lcnum.m_Integral = 0; - lcnum.m_Fractional = 0; - lcnum.m_Exponent = 0; - - if (wsValue.IsEmpty()) - return false; - - const int32_t nIntegralMaxLen = 17; - int32_t cc = 0; - bool bNegative = false; - bool bExpSign = false; - const FX_WCHAR* str = wsValue.c_str(); - int32_t len = wsValue.GetLength(); - while (cc < len && FXSYS_iswspace(str[cc])) - cc++; - - if (cc >= len) - return false; - - if (str[cc] == '+') { - cc++; - } else if (str[cc] == '-') { - bNegative = true; - cc++; - } - int32_t nIntegralLen = 0; - while (cc < len) { - if (str[cc] == '.') - break; - - if (!FXSYS_isDecimalDigit(str[cc])) { - if ((str[cc] == 'E' || str[cc] == 'e')) - break; - return false; - } - if (nIntegralLen < nIntegralMaxLen) { - lcnum.m_Integral = lcnum.m_Integral * 10 + str[cc] - '0'; - nIntegralLen++; - } - cc++; - } - - lcnum.m_Integral = bNegative ? -lcnum.m_Integral : lcnum.m_Integral; - if (cc < len && str[cc] == '.') { - int scale = 0; - double fraction = 0.0; - cc++; - while (cc < len) { - if (scale >= FXSYS_FractionalScaleCount()) { - while (cc < len) { - if (!FXSYS_isDecimalDigit(str[cc])) - break; - cc++; - } - } - if (!FXSYS_isDecimalDigit(str[cc])) { - if ((str[cc] == 'E' || str[cc] == 'e')) - break; - return false; - } - fraction += FXSYS_FractionalScale(scale, FXSYS_toDecimalDigit(str[cc])); - scale++; - cc++; - } - lcnum.m_Fractional = (uint32_t)(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 (FXSYS_isDecimalDigit(str[cc])) - return false; - lcnum.m_Exponent = lcnum.m_Exponent * 10 + str[cc] - '0'; - cc++; - } - lcnum.m_Exponent = bExpSign ? -lcnum.m_Exponent : lcnum.m_Exponent; - } - return true; -} - -CFX_LCNumeric::CFX_LCNumeric() { - m_Integral = 0; - m_Fractional = 0; - m_Exponent = 0; -} -CFX_LCNumeric::CFX_LCNumeric(int64_t integral, - uint32_t fractional, - int32_t exponent) { - m_Integral = integral; - m_Fractional = fractional; - m_Exponent = exponent; -} -CFX_LCNumeric::CFX_LCNumeric(FX_FLOAT dbRetValue) { - m_Integral = (int64_t)dbRetValue; - m_Fractional = (uint32_t)(((dbRetValue > 0) ? (dbRetValue - m_Integral) - : (m_Integral - dbRetValue)) * - 4294967296); - m_Exponent = 0; -} -CFX_LCNumeric::CFX_LCNumeric(double dbvalue) { - m_Integral = (int64_t)dbvalue; - m_Fractional = (uint32_t)( - ((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(int32_t nTreading, - bool bTrimTailZeros) const { - CFX_WideString wsFormat; - wsFormat.Format(L"%%.%df", nTreading); - CFX_WideString wsResult; - wsResult.Format(wsFormat.c_str(), GetDouble()); - if (bTrimTailZeros && nTreading > 0) { - wsResult.TrimRight(L"0"); - wsResult.TrimRight(L"."); - } - return wsResult; -} - -CFX_FormatString::CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, bool bUseLCID) - : m_pLocaleMgr(pLocaleMgr), m_bUseLCID(bUseLCID) {} - -CFX_FormatString::~CFX_FormatString() {} - -void CFX_FormatString::SplitFormatString( - const CFX_WideString& wsFormatString, - std::vector<CFX_WideString>& wsPatterns) { - int32_t iStrLen = wsFormatString.GetLength(); - const FX_WCHAR* pStr = wsFormatString.c_str(); - const FX_WCHAR* pToken = pStr; - const FX_WCHAR* pEnd = pStr + iStrLen; - bool iQuote = false; - while (true) { - if (pStr >= pEnd) { - wsPatterns.push_back(CFX_WideString(pToken, pStr - pToken)); - return; - } - if (*pStr == '\'') { - iQuote = !iQuote; - } else if (*pStr == L'|' && !iQuote) { - wsPatterns.push_back(CFX_WideString(pToken, pStr - pToken)); - pToken = pStr + 1; - } - pStr++; - } -} - -static CFX_WideString FX_GetLiteralText(const FX_WCHAR* pStrPattern, - int32_t& iPattern, - int32_t iLenPattern) { - CFX_WideString wsOutput; - if (pStrPattern[iPattern] != '\'') { - return wsOutput; - } - iPattern++; - int32_t 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') { - int32_t iKeyValue = 0; - iPattern += 2; - int32_t 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(const FX_WCHAR* pStrPattern, - int32_t& iPattern) { - CFX_WideString wsOutput; - if (pStrPattern[iPattern] != '\'') { - return wsOutput; - } - iPattern--; - int32_t iQuote = 1; - while (iPattern >= 0) { - if (pStrPattern[iPattern] == '\'') { - iQuote++; - if (iPattern - 1 >= 0 || - ((pStrPattern[iPattern - 1] != '\'') && (iQuote % 2 == 0))) { - break; - } - iQuote++; - iPattern--; - } else if (pStrPattern[iPattern] == '\\' && - pStrPattern[iPattern + 1] == 'u') { - iPattern--; - int32_t iKeyValue = 0; - int32_t iLen = wsOutput.GetLength(); - int32_t 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; - int32_t ccf = 0; - int32_t iLenf = wsPattern.GetLength(); - const FX_WCHAR* pStr = wsPattern.c_str(); - bool bBraceOpen = false; - CFX_WideStringC wsConstChars(gs_wsConstChars); - while (ccf < iLenf) { - if (pStr[ccf] == '\'') { - FX_GetLiteralText(pStr, ccf, iLenf); - } else if (!bBraceOpen && wsConstChars.Find(pStr[ccf]) == -1) { - 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++; - } - uint32_t dwHash = FX_HashCode_GetW(wsCategory.AsStringC(), false); - 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 uint16_t FX_WStringToLCID(const FX_WCHAR* pstrLCID) { - if (!pstrLCID) { - return 0; - } - wchar_t* pEnd; - return (uint16_t)wcstol((wchar_t*)pstrLCID, &pEnd, 16); -} -uint16_t CFX_FormatString::GetLCID(const CFX_WideString& wsPattern) { - return FX_WStringToLCID(GetLocaleName(wsPattern).c_str()); -} -CFX_WideString CFX_FormatString::GetLocaleName( - const CFX_WideString& wsPattern) { - int32_t ccf = 0; - int32_t iLenf = wsPattern.GetLength(); - const FX_WCHAR* pStr = wsPattern.c_str(); - 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, - const CFX_WideStringC& wsCategory, - CFX_WideString& wsPurgePattern) { - IFX_Locale* pLocale = nullptr; - int32_t ccf = 0; - int32_t iLenf = wsPattern.GetLength(); - const FX_WCHAR* pStr = wsPattern.c_str(); - bool bBrackOpen = false; - CFX_WideStringC wsConstChars(gs_wsConstChars); - while (ccf < iLenf) { - if (pStr[ccf] == '\'') { - int32_t iCurChar = ccf; - FX_GetLiteralText(pStr, ccf, iLenf); - wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1); - } else if (!bBrackOpen && wsConstChars.Find(pStr[ccf]) == -1) { - 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, - int32_t& iDotIndex, - uint32_t& dwStyle, - CFX_WideString& wsPurgePattern) { - dwStyle = 0; - IFX_Locale* pLocale = nullptr; - int32_t ccf = 0; - int32_t iLenf = wsPattern.GetLength(); - const FX_WCHAR* pStr = wsPattern.c_str(); - bool bFindDot = false; - bool bBrackOpen = false; - CFX_WideStringC wsConstChars(gs_wsConstChars); - while (ccf < iLenf) { - if (pStr[ccf] == '\'') { - int32_t iCurChar = ccf; - FX_GetLiteralText(pStr, ccf, iLenf); - wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1); - } else if (!bBrackOpen && wsConstChars.Find(pStr[ccf]) == -1) { - CFX_WideString wsCategory(pStr[ccf]); - ccf++; - while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && - pStr[ccf] != '(') { - wsCategory += pStr[ccf]; - ccf++; - } - if (wsCategory != 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++]; - } - uint32_t dwSubHash = - FX_HashCode_GetW(wsSubCategory.AsStringC(), false); - FX_LOCALENUMSUBCATEGORY eSubCategory = FX_LOCALENUMPATTERN_Decimal; - for (int32_t i = 0; i < g_iFXLocaleNumSubCatCount; i++) { - if (g_FXLocaleNumSubCatData[i].uHash == dwSubHash) { - eSubCategory = (FX_LOCALENUMSUBCATEGORY)g_FXLocaleNumSubCatData[i] - .eSubCategory; - break; - } - } - wsSubCategory.clear(); - if (!pLocale) { - pLocale = m_pLocaleMgr->GetDefLocale(); - } - ASSERT(pLocale); - 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 bool FX_GetNumericDotIndex(const CFX_WideString& wsNum, - const CFX_WideString& wsDotSymbol, - int32_t& iDotIndex) { - int32_t ccf = 0; - int32_t iLenf = wsNum.GetLength(); - const FX_WCHAR* pStr = wsNum.c_str(); - int32_t iLenDot = wsDotSymbol.GetLength(); - while (ccf < iLenf) { - if (pStr[ccf] == '\'') { - FX_GetLiteralText(pStr, ccf, iLenf); - } else if (ccf + iLenDot <= iLenf && - !FXSYS_wcsncmp(pStr + ccf, wsDotSymbol.c_str(), iLenDot)) { - iDotIndex = ccf; - return true; - } - ccf++; - } - iDotIndex = wsNum.Find('.'); - if (iDotIndex < 0) { - iDotIndex = iLenf; - return false; - } - return true; -} -bool CFX_FormatString::ParseText(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern, - CFX_WideString& wsValue) { - wsValue.clear(); - if (wsSrcText.IsEmpty() || wsPattern.IsEmpty()) { - return false; - } - CFX_WideString wsTextFormat; - GetTextFormat(wsPattern, L"text", wsTextFormat); - if (wsTextFormat.IsEmpty()) { - return false; - } - int32_t iText = 0, iPattern = 0; - const FX_WCHAR* pStrText = wsSrcText.c_str(); - int32_t iLenText = wsSrcText.GetLength(); - const FX_WCHAR* pStrPattern = wsTextFormat.c_str(); - int32_t iLenPattern = wsTextFormat.GetLength(); - while (iPattern < iLenPattern && iText < iLenText) { - switch (pStrPattern[iPattern]) { - case '\'': { - CFX_WideString wsLiteral = - FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (iText + iLiteralLen > iLenText || - FXSYS_wcsncmp(pStrText + iText, wsLiteral.c_str(), iLiteralLen)) { - wsValue = wsSrcText; - return false; - } - iText += iLiteralLen; - iPattern++; - break; - } - case 'A': - if (FXSYS_iswalpha(pStrText[iText])) { - wsValue += pStrText[iText]; - iText++; - } - iPattern++; - break; - case 'X': - wsValue += pStrText[iText]; - iText++; - iPattern++; - break; - case 'O': - case '0': - if (FXSYS_isDecimalDigit(pStrText[iText]) || - FXSYS_iswalpha(pStrText[iText])) { - wsValue += pStrText[iText]; - iText++; - } - iPattern++; - break; - case '9': - if (FXSYS_isDecimalDigit(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; -} -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; - } - int32_t dot_index_f = -1; - uint32_t dwFormatStyle = 0; - CFX_WideString wsNumFormat; - IFX_Locale* pLocale = - GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat); - if (!pLocale || wsNumFormat.IsEmpty()) { - return false; - } - int32_t iExponent = 0; - CFX_WideString wsDotSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol); - CFX_WideString wsGroupSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); - int32_t iGroupLen = wsGroupSymbol.GetLength(); - CFX_WideString wsMinus; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus); - int32_t iMinusLen = wsMinus.GetLength(); - int cc = 0, ccf = 0; - const FX_WCHAR* str = wsSrcNum.c_str(); - int len = wsSrcNum.GetLength(); - const FX_WCHAR* strf = wsNumFormat.c_str(); - int lenf = wsNumFormat.GetLength(); - double dbRetValue = 0; - double coeff = 1; - bool bHavePercentSymbol = false; - bool bNeg = false; - bool bReverseParse = false; - int32_t 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); - int32_t iLiteralLen = wsLiteral.GetLength(); - cc -= iLiteralLen - 1; - if (cc < 0 || - FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc--; - ccf--; - break; - } - case '9': - if (!FXSYS_isDecimalDigit(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, wsMinus.c_str(), 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, wsMinus.c_str(), iMinusLen)) { - return false; - } - cc--; - bNeg = true; - } - ccf--; - break; - case 'E': { - if (cc >= dot_index) { - return false; - } - bool bExpSign = false; - while (cc >= 0) { - if (str[cc] == 'E' || str[cc] == 'e') { - break; - } - if (FXSYS_isDecimalDigit(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), - wsMinus.c_str(), 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); - int32_t iSymbolLen = wsSymbol.GetLength(); - cc -= iSymbolLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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); - int32_t iSysmbolLen = wsSymbol.GetLength(); - cc -= iSysmbolLen - 1; - if (cc < 0 || - FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), iSysmbolLen)) { - return false; - } - cc--; - ccf--; - bHavePercentSymbol = true; - } break; - case '8': - while (ccf < lenf && strf[ccf] == '8') { - ccf++; - } - while (cc < len && FXSYS_isDecimalDigit(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, wsGroupSymbol.c_str(), 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); - int32_t iLiteralLen = wsLiteral.GetLength(); - cc -= iLiteralLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc--; - ccf--; - break; - } - case '9': - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - dbRetValue = dbRetValue + (str[cc] - '0') * coeff; - coeff *= 10; - cc--; - ccf--; - break; - case 'z': - if (FXSYS_isDecimalDigit(str[cc])) { - dbRetValue = dbRetValue + (str[cc] - '0') * coeff; - coeff *= 10; - cc--; - } - ccf--; - break; - case 'Z': - if (str[cc] != ' ') { - if (FXSYS_isDecimalDigit(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, wsMinus.c_str(), 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, wsMinus.c_str(), iMinusLen)) { - return false; - } - cc--; - bNeg = true; - } - ccf--; - break; - case 'E': { - if (cc >= dot_index) { - return false; - } - bool bExpSign = false; - while (cc >= 0) { - if (str[cc] == 'E' || str[cc] == 'e') { - break; - } - if (FXSYS_isDecimalDigit(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), wsMinus.c_str(), - 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); - int32_t iSymbolLen = wsSymbol.GetLength(); - cc -= iSymbolLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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); - int32_t iSysmbolLen = wsSymbol.GetLength(); - cc -= iSysmbolLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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, wsGroupSymbol.c_str(), 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); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (cc + iLiteralLen > len || - FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc += iLiteralLen; - ccf++; - break; - } - case '9': - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - { - dbRetValue = dbRetValue + (str[cc] - '0') * coeff; - coeff *= 0.1; - } - cc++; - ccf++; - break; - case 'z': - if (FXSYS_isDecimalDigit(str[cc])) { - dbRetValue = dbRetValue + (str[cc] - '0') * coeff; - coeff *= 0.1; - cc++; - } - ccf++; - break; - case 'Z': - if (str[cc] != ' ') { - if (FXSYS_isDecimalDigit(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, wsMinus.c_str(), iMinusLen)) { - return false; - } - bNeg = true; - cc += iMinusLen; - } - ccf++; - break; - case 's': - if (str[cc] == '+') { - cc++; - } else { - if (cc + iMinusLen > len || - FXSYS_wcsncmp(str + cc, wsMinus.c_str(), iMinusLen)) { - return false; - } - bNeg = true; - cc += iMinusLen; - } - ccf++; - break; - case 'E': { - if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) { - return false; - } - bool bExpSign = false; - cc++; - if (cc < len) { - if (str[cc] == '+') { - cc++; - } else if (str[cc] == '-') { - bExpSign = true; - cc++; - } - } - while (cc < len) { - if (!FXSYS_isDecimalDigit(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); - int32_t iSymbolLen = wsSymbol.GetLength(); - if (cc + iSymbolLen > len || - FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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); - int32_t iSysmbolLen = wsSymbol.GetLength(); - if (cc + iSysmbolLen <= len && - !FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), iSysmbolLen)) { - cc += iSysmbolLen; - } - ccf++; - bHavePercentSymbol = true; - } break; - case '8': { - while (ccf < lenf && strf[ccf] == '8') { - ccf++; - } - while (cc < len && FXSYS_isDecimalDigit(str[cc])) { - dbRetValue = (str[cc] - '0') * coeff + dbRetValue; - coeff *= 0.1; - cc++; - } - } break; - case ',': { - if (cc + iGroupLen <= len && - FXSYS_wcsncmp(str + cc, wsGroupSymbol.c_str(), 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; -} - -bool CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsValue) { - wsValue.clear(); - if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) { - return false; - } - int32_t dot_index_f = -1; - uint32_t dwFormatStyle = 0; - CFX_WideString wsNumFormat; - IFX_Locale* pLocale = - GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat); - if (!pLocale || wsNumFormat.IsEmpty()) { - return false; - } - int32_t iExponent = 0; - CFX_WideString wsDotSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol); - CFX_WideString wsGroupSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); - int32_t iGroupLen = wsGroupSymbol.GetLength(); - CFX_WideString wsMinus; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus); - int32_t iMinusLen = wsMinus.GetLength(); - int cc = 0, ccf = 0; - const FX_WCHAR* str = wsSrcNum.c_str(); - int len = wsSrcNum.GetLength(); - const FX_WCHAR* strf = wsNumFormat.c_str(); - int lenf = wsNumFormat.GetLength(); - bool bHavePercentSymbol = false; - bool bNeg = false; - bool bReverseParse = false; - int32_t 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); - int32_t iLiteralLen = wsLiteral.GetLength(); - cc -= iLiteralLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc--; - ccf--; - break; - } - case '9': - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - wsValue = str[cc] + wsValue; - cc--; - ccf--; - break; - case 'z': - if (FXSYS_isDecimalDigit(str[cc])) { - wsValue = str[cc] + wsValue; - cc--; - } - ccf--; - break; - case 'Z': - if (str[cc] != ' ') { - if (FXSYS_isDecimalDigit(str[cc])) { - wsValue = 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, wsMinus.c_str(), 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, wsMinus.c_str(), iMinusLen)) { - return false; - } - cc--; - bNeg = true; - } - ccf--; - break; - case 'E': { - if (cc >= dot_index) { - return false; - } - bool bExpSign = false; - while (cc >= 0) { - if (str[cc] == 'E' || str[cc] == 'e') { - break; - } - if (FXSYS_isDecimalDigit(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), wsMinus.c_str(), - 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); - int32_t iSymbolLen = wsSymbol.GetLength(); - cc -= iSymbolLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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); - int32_t iSysmbolLen = wsSymbol.GetLength(); - cc -= iSysmbolLen - 1; - if (cc < 0 || FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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, wsGroupSymbol.c_str(), 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); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (cc + iLiteralLen > len || - FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc += iLiteralLen; - ccf++; - break; - } - case '9': - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - { wsValue += str[cc]; } - cc++; - ccf++; - break; - case 'z': - if (FXSYS_isDecimalDigit(str[cc])) { - wsValue += str[cc]; - cc++; - } - ccf++; - break; - case 'Z': - if (str[cc] != ' ') { - if (FXSYS_isDecimalDigit(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, wsMinus.c_str(), iMinusLen)) { - return false; - } - bNeg = true; - cc += iMinusLen; - } - ccf++; - break; - case 's': - if (str[cc] == '+') { - cc++; - } else { - if (cc + iMinusLen > len || - FXSYS_wcsncmp(str + cc, wsMinus.c_str(), iMinusLen)) { - return false; - } - bNeg = true; - cc += iMinusLen; - } - ccf++; - break; - case 'E': { - if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) { - return false; - } - bool bExpSign = false; - cc++; - if (cc < len) { - if (str[cc] == '+') { - cc++; - } else if (str[cc] == '-') { - bExpSign = true; - cc++; - } - } - while (cc < len) { - if (!FXSYS_isDecimalDigit(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); - int32_t iSymbolLen = wsSymbol.GetLength(); - if (cc + iSymbolLen > len || - FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), 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); - int32_t iSysmbolLen = wsSymbol.GetLength(); - if (cc + iSysmbolLen <= len && - !FXSYS_wcsncmp(str + cc, wsSymbol.c_str(), iSysmbolLen)) { - cc += iSysmbolLen; - } - ccf++; - bHavePercentSymbol = true; - } break; - case '8': { - while (ccf < lenf && strf[ccf] == '8') { - ccf++; - } - while (cc < len && FXSYS_isDecimalDigit(str[cc])) { - wsValue += str[cc]; - cc++; - } - } break; - case ',': { - if (cc + iGroupLen <= len && - FXSYS_wcsncmp(str + cc, wsGroupSymbol.c_str(), 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.AsStringC()); - if (iExponent) { - decimal = decimal * CFX_Decimal(FXSYS_pow(10, (FX_FLOAT)iExponent)); - } - if (bHavePercentSymbol) { - decimal = decimal / CFX_Decimal(100); - } - wsValue = decimal; - } - if (bNeg) { - wsValue = L'-' + wsValue; - } - return true; -} -FX_DATETIMETYPE CFX_FormatString::GetDateTimeFormat( - const CFX_WideString& wsPattern, - IFX_Locale*& pLocale, - CFX_WideString& wsDatePattern, - CFX_WideString& wsTimePattern) { - pLocale = nullptr; - CFX_WideString wsTempPattern; - FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown; - int32_t ccf = 0; - int32_t iLenf = wsPattern.GetLength(); - const FX_WCHAR* pStr = wsPattern.c_str(); - int32_t iFindCategory = 0; - bool bBraceOpen = false; - CFX_WideStringC wsConstChars(gs_wsConstChars); - while (ccf < iLenf) { - if (pStr[ccf] == '\'') { - int32_t iCurChar = ccf; - FX_GetLiteralText(pStr, ccf, iLenf); - wsTempPattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1); - } else if (!bBraceOpen && iFindCategory != 3 && - wsConstChars.Find(pStr[ccf]) == -1) { - 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 == L"date") { - iFindCategory |= 1; - eCategory = FX_LOCALECATEGORY_Date; - if (iFindCategory & 2) { - iFindCategory = 4; - } - } else if (!(iFindCategory & 2) && wsCategory == L"time") { - iFindCategory |= 2; - eCategory = FX_LOCALECATEGORY_Time; - } else if (wsCategory == 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++]; - } - uint32_t dwSubHash = - FX_HashCode_GetW(wsSubCategory.AsStringC(), false); - FX_LOCALEDATETIMESUBCATEGORY eSubCategory = - FX_LOCALEDATETIMESUBCATEGORY_Medium; - for (int32_t 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(); - } - ASSERT(pLocale); - 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.clear(); - 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.clear(); - } - } 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.clear(); - wsDatePattern = wsPattern; - } - return (FX_DATETIMETYPE)iFindCategory; -} -static bool FX_ParseLocaleDate(const CFX_WideString& wsDate, - const CFX_WideString& wsDatePattern, - IFX_Locale* pLocale, - CFX_Unitime& datetime, - int32_t& cc) { - int32_t year = 1900; - int32_t month = 1; - int32_t day = 1; - int32_t ccf = 0; - const FX_WCHAR* str = wsDate.c_str(); - int32_t len = wsDate.GetLength(); - const FX_WCHAR* strf = wsDatePattern.c_str(); - int32_t lenf = wsDatePattern.GetLength(); - CFX_WideStringC wsDateSymbols(gs_wsDateSymbols); - while (cc < len && ccf < lenf) { - if (strf[ccf] == '\'') { - CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (cc + iLiteralLen > len || - FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc += iLiteralLen; - ccf++; - continue; - } else if (wsDateSymbols.Find(strf[ccf]) == -1) { - if (strf[ccf] != str[cc]) - return false; - cc++; - ccf++; - continue; - } - uint32_t dwSymbolNum = 1; - FX_WCHAR dwCharSymbol = strf[ccf++]; - while (ccf < lenf && strf[ccf] == dwCharSymbol) { - ccf++; - dwSymbolNum++; - } - uint32_t dwSymbol = (dwCharSymbol << 8) | (dwSymbolNum + '0'); - if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - day = str[cc++] - '0'; - if (cc < len && FXSYS_isDecimalDigit(str[cc])) { - day = day * 10 + str[cc++] - '0'; - } - } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) { - if (!FXSYS_isDecimalDigit(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 && FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - month = str[cc++] - '0'; - if (cc < len && FXSYS_isDecimalDigit(str[cc])) { - month = month * 10 + str[cc++] - '0'; - } - } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { - if (!FXSYS_isDecimalDigit(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; - uint16_t i = 0; - for (; i < 12; i++) { - pLocale->GetMonthName(i, wsMonthNameAbbr, true); - if (wsMonthNameAbbr.IsEmpty()) { - continue; - } - if (!FXSYS_wcsncmp(wsMonthNameAbbr.c_str(), 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; - uint16_t i = 0; - for (; i < 12; i++) { - pLocale->GetMonthName(i, wsMonthName, false); - if (wsMonthName.IsEmpty()) { - continue; - } - if (!FXSYS_wcsncmp(wsMonthName.c_str(), 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; - uint16_t i = 0; - for (; i < 7; i++) { - pLocale->GetDayName(i, wsDayNameAbbr, true); - if (wsDayNameAbbr.IsEmpty()) { - continue; - } - if (!FXSYS_wcsncmp(wsDayNameAbbr.c_str(), str + cc, - wsDayNameAbbr.GetLength())) { - break; - } - } - if (i < 12) { - cc += wsDayNameAbbr.GetLength(); - } - } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) { - CFX_WideString wsDayName; - int32_t i = 0; - for (; i < 7; i++) { - pLocale->GetDayName(i, wsDayName, false); - if (wsDayName == L"") { - continue; - } - if (!FXSYS_wcsncmp(wsDayName.c_str(), 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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - year = str[cc++] - '0'; - if (cc >= len || !FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(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; - } - } - if (cc < len) { - return false; - } - CFX_Unitime ut; - ut.Set(year, month, day); - datetime = datetime + ut; - return !!cc; -} - -static void FX_ResolveZone(uint8_t& wHour, - uint8_t& wMinute, - FX_TIMEZONE tzDiff, - IFX_Locale* pLocale) { - int32_t 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 bool FX_ParseLocaleTime(const CFX_WideString& wsTime, - const CFX_WideString& wsTimePattern, - IFX_Locale* pLocale, - CFX_Unitime& datetime, - int32_t& cc) { - uint8_t hour = 0; - uint8_t minute = 0; - uint8_t second = 0; - uint16_t millisecond = 0; - int32_t ccf = 0; - const FX_WCHAR* str = wsTime.c_str(); - int len = wsTime.GetLength(); - const FX_WCHAR* strf = wsTimePattern.c_str(); - int lenf = wsTimePattern.GetLength(); - bool bHasA = false; - bool bPM = false; - CFX_WideStringC wsTimeSymbols(gs_wsTimeSymbols); - while (cc < len && ccf < lenf) { - if (strf[ccf] == '\'') { - CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (cc + iLiteralLen > len || - FXSYS_wcsncmp(str + cc, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - cc += iLiteralLen; - ccf++; - continue; - } else if (wsTimeSymbols.Find(strf[ccf]) == -1) { - if (strf[ccf] != str[cc]) - return false; - cc++; - ccf++; - continue; - } - uint32_t dwSymbolNum = 1; - FX_WCHAR dwCharSymbol = strf[ccf++]; - while (ccf < lenf && strf[ccf] == dwCharSymbol) { - ccf++; - dwSymbolNum++; - } - uint32_t dwSymbol = (dwCharSymbol << 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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - hour = str[cc++] - '0'; - if (cc < len && FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - hour = str[cc++] - '0'; - if (cc >= len) { - return false; - } - if (!FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - minute = str[cc++] - '0'; - if (cc < len && FXSYS_isDecimalDigit(str[cc])) { - minute = minute * 10 + str[cc++] - '0'; - } - } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - minute = str[cc++] - '0'; - if (cc >= len) { - return false; - } - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - minute = minute * 10 + str[cc++] - '0'; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - second = str[cc++] - '0'; - if (cc < len && FXSYS_isDecimalDigit(str[cc])) { - second = second * 10 + str[cc++] - '0'; - } - } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - second = str[cc++] - '0'; - if (cc >= len) { - return false; - } - if (!FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(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; - } - uint32_t 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 { - const FX_LOCALETIMEZONEINFO* pEnd = - g_FXLocaleTimeZoneData + FX_ArraySize(g_FXLocaleTimeZoneData); - const FX_LOCALETIMEZONEINFO* pTimeZoneInfo = - std::lower_bound(g_FXLocaleTimeZoneData, pEnd, dwHash, - [](const FX_LOCALETIMEZONEINFO& info, - uint32_t hash) { return info.uHash < hash; }); - if (pTimeZoneInfo < pEnd && dwHash == pTimeZoneInfo->uHash) { - 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; -} - -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 = nullptr; - 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) { - int32_t iStart = 0; - if (!FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, - iStart)) { - return false; - } - if (!FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, - iStart)) { - return false; - } - } else { - int32_t 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; -} -bool CFX_FormatString::ParseZero(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern) { - CFX_WideString wsTextFormat; - GetTextFormat(wsPattern, L"zero", wsTextFormat); - int32_t iText = 0, iPattern = 0; - const FX_WCHAR* pStrText = wsSrcText.c_str(); - int32_t iLenText = wsSrcText.GetLength(); - const FX_WCHAR* pStrPattern = wsTextFormat.c_str(); - int32_t iLenPattern = wsTextFormat.GetLength(); - while (iPattern < iLenPattern && iText < iLenText) { - if (pStrPattern[iPattern] == '\'') { - CFX_WideString wsLiteral = - FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (iText + iLiteralLen > iLenText || - FXSYS_wcsncmp(pStrText + iText, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - iText += iLiteralLen; - iPattern++; - continue; - } else if (pStrPattern[iPattern] != pStrText[iText]) { - return false; - } else { - iText++; - iPattern++; - } - } - return iPattern == iLenPattern && iText == iLenText; -} -bool CFX_FormatString::ParseNull(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern) { - CFX_WideString wsTextFormat; - GetTextFormat(wsPattern, L"null", wsTextFormat); - int32_t iText = 0, iPattern = 0; - const FX_WCHAR* pStrText = wsSrcText.c_str(); - int32_t iLenText = wsSrcText.GetLength(); - const FX_WCHAR* pStrPattern = wsTextFormat.c_str(); - int32_t iLenPattern = wsTextFormat.GetLength(); - while (iPattern < iLenPattern && iText < iLenText) { - if (pStrPattern[iPattern] == '\'') { - CFX_WideString wsLiteral = - FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); - int32_t iLiteralLen = wsLiteral.GetLength(); - if (iText + iLiteralLen > iLenText || - FXSYS_wcsncmp(pStrText + iText, wsLiteral.c_str(), iLiteralLen)) { - return false; - } - iText += iLiteralLen; - iPattern++; - continue; - } else if (pStrPattern[iPattern] != pStrText[iText]) { - return false; - } else { - iText++; - iPattern++; - } - } - return iPattern == iLenPattern && iText == iLenText; -} -bool CFX_FormatString::FormatText(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput) { - if (wsPattern.IsEmpty()) { - return false; - } - int32_t iLenText = wsSrcText.GetLength(); - if (iLenText == 0) { - return false; - } - CFX_WideString wsTextFormat; - GetTextFormat(wsPattern, L"text", wsTextFormat); - int32_t iText = 0, iPattern = 0; - const FX_WCHAR* pStrText = wsSrcText.c_str(); - const FX_WCHAR* pStrPattern = wsTextFormat.c_str(); - int32_t iLenPattern = wsTextFormat.GetLength(); - while (iPattern < iLenPattern) { - switch (pStrPattern[iPattern]) { - case '\'': { - wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); - iPattern++; - break; - } - case 'A': - if (iText >= iLenText || !FXSYS_iswalpha(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 || (!FXSYS_isDecimalDigit(pStrText[iText]) && - !FXSYS_iswalpha(pStrText[iText]))) { - return false; - } - wsOutput += pStrText[iText++]; - iPattern++; - break; - case '9': - if (iText >= iLenText || !FXSYS_isDecimalDigit(pStrText[iText])) { - return false; - } - wsOutput += pStrText[iText++]; - iPattern++; - break; - default: - wsOutput += pStrPattern[iPattern++]; - break; - } - } - return iText == iLenText; -} -static int32_t FX_GetNumTrailingLimit(const CFX_WideString& wsFormat, - int iDotPos, - bool& bTrimTailZeros) { - if (iDotPos < 0) { - return 0; - } - int32_t iCount = wsFormat.GetLength(); - int32_t 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; -} -bool CFX_FormatString::FormatStrNum(const CFX_WideStringC& wsInputNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput) { - if (wsInputNum.IsEmpty() || wsPattern.IsEmpty()) { - return false; - } - int32_t dot_index_f = -1; - uint32_t dwNumStyle = 0; - CFX_WideString wsNumFormat; - IFX_Locale* pLocale = - GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat); - if (!pLocale || wsNumFormat.IsEmpty()) { - return false; - } - int32_t cc = 0, ccf = 0; - const FX_WCHAR* strf = wsNumFormat.c_str(); - 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.AsStringC()); - if (dwNumStyle & FX_NUMSTYLE_Percent) { - decimal = decimal * CFX_Decimal(100); - wsSrcNum = decimal; - } - int32_t 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; - } - } - } - } - bool bTrimTailZeros = false; - int32_t iTreading = - FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros); - int32_t scale = decimal.GetScale(); - if (iTreading < scale) { - decimal.SetScale(iTreading); - wsSrcNum = decimal; - } - if (bTrimTailZeros && scale > 0 && iTreading > 0) { - wsSrcNum.TrimRight(L"0"); - wsSrcNum.TrimRight(L"."); - } - CFX_WideString wsGroupSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); - bool bNeg = false; - if (wsSrcNum[0] == '-') { - bNeg = true; - wsSrcNum.Delete(0, 1); - } - bool bAddNeg = false; - const FX_WCHAR* str = wsSrcNum.c_str(); - 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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - wsOutput = str[cc] + wsOutput; - cc--; - } else { - wsOutput = L'0' + wsOutput; - } - ccf--; - break; - case 'z': - if (cc >= 0) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - if (str[0] != '0') { - wsOutput = str[cc] + wsOutput; - } - cc--; - } - ccf--; - break; - case 'Z': - if (cc >= 0) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - if (str[0] == '0') { - wsOutput = L' ' + wsOutput; - } else { - wsOutput = str[cc] + wsOutput; - } - cc--; - } else { - wsOutput = L' ' + wsOutput; - } - ccf--; - break; - case 'S': - if (bNeg) { - CFX_WideString wsMinusSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol); - wsOutput = wsMinusSymbol + wsOutput; - bAddNeg = true; - } else { - wsOutput = 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(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 = strf[ccf] + wsOutput; - ccf--; - } - } - if (cc >= 0) { - int nPos = dot_index % 3; - wsOutput.clear(); - for (int32_t 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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - wsOutput += str[cc]; - cc++; - } else { - wsOutput += L'0'; - } - ccf++; - break; - case 'z': - if (cc < len) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - wsOutput += str[cc]; - cc++; - } - ccf++; - break; - case 'Z': - if (cc < len) { - if (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - wsOutput += str[cc]; - cc++; - } else { - wsOutput += L'0'; - } - ccf++; - break; - case 'E': { - CFX_WideString wsExp; - wsExp.Format(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 && FXSYS_isDecimalDigit(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; -} -bool CFX_FormatString::FormatLCNumeric(CFX_LCNumeric& lcNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput) { - int32_t dot_index_f = -1; - uint32_t dwNumStyle = 0; - CFX_WideString wsNumFormat; - IFX_Locale* pLocale = - GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat); - if (!pLocale || wsNumFormat.IsEmpty()) { - return false; - } - int32_t cc = 0, ccf = 0; - const FX_WCHAR* strf = wsNumFormat.c_str(); - int lenf = wsNumFormat.GetLength(); - double dbOrgRaw = lcNum.GetDouble(); - double dbRetValue = dbOrgRaw; - if (dwNumStyle & FX_NUMSTYLE_Percent) { - dbRetValue *= 100; - } - int32_t 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); - } - bool bTrimTailZeros = false; - int32_t 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); - bool bNeg = false; - if (wsNumeric[0] == '-') { - bNeg = true; - wsNumeric.Delete(0, 1); - } - bool bAddNeg = false; - const FX_WCHAR* str = wsNumeric.c_str(); - 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 = str[cc] + wsOutput; - cc--; - } else { - wsOutput = L'0' + wsOutput; - } - ccf--; - break; - case 'z': - if (cc >= 0) { - if (lcNum.m_Integral != 0) { - wsOutput = str[cc] + wsOutput; - } - cc--; - } - ccf--; - break; - case 'Z': - if (cc >= 0) { - if (lcNum.m_Integral == 0) { - wsOutput = L' ' + wsOutput; - } else { - wsOutput = str[cc] + wsOutput; - } - cc--; - } else { - wsOutput = L' ' + wsOutput; - } - ccf--; - break; - case 'S': - if (bNeg) { - CFX_WideString wsMinusSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol); - wsOutput = wsMinusSymbol + wsOutput; - bAddNeg = true; - } else { - wsOutput = 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(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 = strf[ccf] + wsOutput; - ccf--; - } - } - if (cc >= 0) { - int nPos = dot_index % 3; - wsOutput.clear(); - for (int32_t 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(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 && FXSYS_isDecimalDigit(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; -} -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.AsStringC(), wsPattern, wsOutput); -} -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); -} -bool FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime& datetime) { - int32_t year = 1900; - int32_t month = 1; - int32_t day = 1; - uint16_t wYear = 0; - int cc_start = 0, cc = 0; - const FX_WCHAR* str = wsDate.c_str(); - int len = wsDate.GetLength(); - if (len > 10) { - return false; - } - while (cc < len && cc < 4) { - if (!FXSYS_isDecimalDigit(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; - uint8_t tmpM = 0; - while (cc < len && cc < cc_start + 2) { - if (!FXSYS_isDecimalDigit(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++; - } - uint8_t tmpD = 0; - cc_start = cc; - while (cc < len && cc < cc_start + 2) { - if (!FXSYS_isDecimalDigit(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; - } - 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; -} -bool FX_TimeFromCanonical(const CFX_WideStringC& wsTime, - CFX_Unitime& datetime, - IFX_Locale* pLocale) { - if (wsTime.GetLength() == 0) { - return false; - } - uint8_t hour = 0; - uint8_t minute = 0; - uint8_t second = 0; - uint16_t millisecond = 0; - int cc_start = 0, cc = cc_start; - const FX_WCHAR* str = wsTime.c_str(); - int len = wsTime.GetLength(); - while (cc < len && cc < 2) { - if (!FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(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 (!FXSYS_isDecimalDigit(str[cc])) { - return false; - } - millisecond = millisecond * 10 + str[cc++] - '0'; - } - if (cc < cc_start + 3) - 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 uint16_t FX_GetSolarMonthDays(uint16_t year, uint16_t month) { - if (month % 2) { - return 31; - } else if (month == 2) { - return FX_IsLeapYear(year) ? 29 : 28; - } - return 30; -} -static uint16_t FX_GetWeekDay(uint16_t year, uint16_t month, uint16_t day) { - uint16_t g_month_day[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; - uint16_t 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 uint16_t FX_GetWeekOfMonth(uint16_t year, uint16_t month, uint16_t day) { - uint16_t week_day = FX_GetWeekDay(year, month, 1); - uint16_t week_index = 0; - week_index += day / 7; - day = day % 7; - if (week_day + day > 7) { - week_index++; - } - return week_index; -} -static uint16_t FX_GetWeekOfYear(uint16_t year, uint16_t month, uint16_t day) { - uint16_t nDays = 0; - for (uint16_t i = 1; i < month; i++) { - nDays += FX_GetSolarMonthDays(year, i); - } - nDays += day; - uint16_t week_day = FX_GetWeekDay(year, 1, 1); - uint16_t week_index = 1; - week_index += nDays / 7; - nDays = nDays % 7; - if (week_day + nDays > 7) { - week_index++; - } - return week_index; -} -static bool FX_DateFormat(const CFX_WideString& wsDatePattern, - IFX_Locale* pLocale, - const CFX_Unitime& datetime, - CFX_WideString& wsResult) { - bool bRet = true; - int32_t year = datetime.GetYear(); - uint8_t month = datetime.GetMonth(); - uint8_t day = datetime.GetDay(); - int32_t ccf = 0; - const FX_WCHAR* strf = wsDatePattern.c_str(); - int32_t lenf = wsDatePattern.GetLength(); - CFX_WideStringC wsDateSymbols(gs_wsDateSymbols); - while (ccf < lenf) { - if (strf[ccf] == '\'') { - wsResult += FX_GetLiteralText(strf, ccf, lenf); - ccf++; - continue; - } else if (wsDateSymbols.Find(strf[ccf]) == -1) { - wsResult += strf[ccf++]; - continue; - } - uint32_t dwSymbolNum = 1; - FX_WCHAR dwCharSymbol = strf[ccf++]; - while (ccf < lenf && strf[ccf] == dwCharSymbol) { - ccf++; - dwSymbolNum++; - } - uint32_t dwSymbol = (dwCharSymbol << 8) | (dwSymbolNum + '0'); - if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) { - CFX_WideString wsDay; - wsDay.Format(L"%d", day); - wsResult += wsDay; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) { - CFX_WideString wsDay; - wsDay.Format(L"%02d", day); - wsResult += wsDay; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) { - uint16_t nDays = 0; - for (int i = 1; i < month; i++) { - nDays += FX_GetSolarMonthDays(year, i); - } - nDays += day; - CFX_WideString wsDays; - wsDays.Format(L"%d", nDays); - wsResult += wsDays; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) { - uint16_t nDays = 0; - for (int i = 1; i < month; i++) { - nDays += FX_GetSolarMonthDays(year, i); - } - nDays += day; - CFX_WideString wsDays; - wsDays.Format(L"%03d", nDays); - wsResult += wsDays; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) { - CFX_WideString wsMonth; - wsMonth.Format(L"%d", month); - wsResult += wsMonth; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { - CFX_WideString wsMonth; - wsMonth.Format(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')) { - uint16_t wWeekDay = FX_GetWeekDay(year, month, day); - CFX_WideString wsWeekDay; - wsWeekDay.Format(L"%d", wWeekDay + 1); - wsResult += wsWeekDay; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) { - uint16_t 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')) { - uint16_t 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')) { - uint16_t wWeekDay = FX_GetWeekDay(year, month, day); - CFX_WideString wsWeekDay; - wsWeekDay.Format(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(L"%02d", year % 100); - wsResult += wsYear; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) { - CFX_WideString wsYear; - wsYear.Format(L"%d", year); - wsResult += wsYear; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) { - uint16_t week_index = FX_GetWeekOfMonth(year, month, day); - CFX_WideString wsWeekInMonth; - wsWeekInMonth.Format(L"%d", week_index); - wsResult += wsWeekInMonth; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) { - uint16_t week_index = FX_GetWeekOfYear(year, month, day); - CFX_WideString wsWeekInYear; - wsWeekInYear.Format(L"%02d", week_index); - wsResult += wsWeekInYear; - } - } - return bRet; -} -static bool FX_TimeFormat(const CFX_WideString& wsTimePattern, - IFX_Locale* pLocale, - const CFX_Unitime& datetime, - CFX_WideString& wsResult) { - bool bGMT = false; - bool bRet = true; - uint8_t hour = datetime.GetHour(); - uint8_t minute = datetime.GetMinute(); - uint8_t second = datetime.GetSecond(); - uint16_t millisecond = datetime.GetMillisecond(); - int32_t ccf = 0; - const FX_WCHAR* strf = wsTimePattern.c_str(); - int32_t lenf = wsTimePattern.GetLength(); - uint16_t wHour = hour; - bool bPM = false; - if (wsTimePattern.Find('A') != -1) { - if (wHour >= 12) { - bPM = true; - } - } - CFX_WideStringC wsTimeSymbols(gs_wsTimeSymbols); - while (ccf < lenf) { - if (strf[ccf] == '\'') { - wsResult += FX_GetLiteralText(strf, ccf, lenf); - ccf++; - continue; - } else if (wsTimeSymbols.Find(strf[ccf]) == -1) { - wsResult += strf[ccf++]; - continue; - } - uint32_t dwSymbolNum = 1; - FX_WCHAR dwCharSymbol = strf[ccf++]; - while (ccf < lenf && strf[ccf] == dwCharSymbol) { - ccf++; - dwSymbolNum++; - } - uint32_t dwSymbol = (dwCharSymbol << 8) | (dwSymbolNum + '0'); - if (dwSymbol == FXBSTR_ID(0, 0, 'h', '1')) { - if (wHour > 12) { - wHour -= 12; - } - CFX_WideString wsHour; - wsHour.Format(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(L"%02d", wHour == 0 ? 12 : wHour); - wsResult += wsHour; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) { - CFX_WideString wsHour; - wsHour.Format(L"%d", wHour == 0 ? 24 : wHour); - wsResult += wsHour; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) { - CFX_WideString wsHour; - wsHour.Format(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(L"%d", wHour); - wsResult += wsHour; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '1')) { - CFX_WideString wsHour; - wsHour.Format(L"%d", wHour); - wsResult += wsHour; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2')) { - if (wHour > 12) { - wHour -= 12; - } - CFX_WideString wsHour; - wsHour.Format(L"%02d", wHour); - wsResult += wsHour; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '2')) { - CFX_WideString wsHour; - wsHour.Format(L"%02d", wHour); - wsResult += wsHour; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) { - CFX_WideString wsMinute; - wsMinute.Format(L"%d", minute); - wsResult += wsMinute; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { - CFX_WideString wsMinute; - wsMinute.Format(L"%02d", minute); - wsResult += wsMinute; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) { - CFX_WideString wsSecond; - wsSecond.Format(L"%d", second); - wsResult += wsSecond; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) { - CFX_WideString wsSecond; - wsSecond.Format(L"%02d", second); - wsResult += wsSecond; - } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) { - CFX_WideString wsMilliseconds; - wsMilliseconds.Format(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 += L"GMT"; - FX_TIMEZONE tz; - pLocale->GetTimeZone(&tz); - if (!bGMT && (tz.tzHour != 0 || tz.tzMinute != 0)) { - if (tz.tzHour < 0) { - wsResult += L"-"; - } else { - wsResult += L"+"; - } - CFX_WideString wsTimezone; - wsTimezone.Format(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 += L"-"; - } else { - wsResult += L"+"; - } - CFX_WideString wsTimezone; - wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute); - wsResult += wsTimezone; - } - } - } - return bRet; -} -static bool FX_FormatDateTime(const CFX_Unitime& dt, - const CFX_WideString& wsDatePattern, - const CFX_WideString& wsTimePattern, - bool bDateFirst, - IFX_Locale* pLocale, - CFX_WideString& wsOutput) { - 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; -} -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 = nullptr; - FX_DATETIMETYPE eCategory = - GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); - if (!pLocale || eCategory == FX_DATETIMETYPE_Unknown) { - return false; - } - CFX_Unitime dt(0); - int32_t 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.AsStringC(), dt, pLocale); - } - } else { - FX_DateFromCanonical(wsSrcDateTime.Left(iT), dt); - FX_TimeFromCanonical( - wsSrcDateTime.Right(wsSrcDateTime.GetLength() - iT - 1).AsStringC(), dt, - pLocale); - } - return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, - eCategory != FX_DATETIMETYPE_TimeDate, pLocale, - wsOutput); -} -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 = nullptr; - 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.clear(); - } - eCategory = eDateTimeType; - } - if (eCategory == FX_DATETIMETYPE_Unknown) { - return false; - } - CFX_Unitime dt(0); - int32_t 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.AsStringC(), dt, pLocale)) { - return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, true, pLocale, - wsOutput); - } - } else { - CFX_WideString wsSrcDate(wsSrcDateTime.c_str(), iT); - CFX_WideStringC wsSrcTime(wsSrcDateTime.c_str() + 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; -} -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 = nullptr; - FX_DATETIMETYPE eCategory = - GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); - if (!pLocale) { - return false; - } - return FX_FormatDateTime(dt, wsPattern, wsTimePattern, - eCategory != FX_DATETIMETYPE_TimeDate, pLocale, - wsOutput); -} -bool CFX_FormatString::FormatZero(const CFX_WideString& wsPattern, - CFX_WideString& wsOutput) { - if (wsPattern.IsEmpty()) { - return false; - } - CFX_WideString wsTextFormat; - GetTextFormat(wsPattern, L"zero", wsTextFormat); - int32_t iPattern = 0; - const FX_WCHAR* pStrPattern = wsTextFormat.c_str(); - int32_t iLenPattern = wsTextFormat.GetLength(); - while (iPattern < iLenPattern) { - if (pStrPattern[iPattern] == '\'') { - wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); - iPattern++; - continue; - } else { - wsOutput += pStrPattern[iPattern++]; - continue; - } - } - return true; -} -bool CFX_FormatString::FormatNull(const CFX_WideString& wsPattern, - CFX_WideString& wsOutput) { - if (wsPattern.IsEmpty()) { - return false; - } - CFX_WideString wsTextFormat; - GetTextFormat(wsPattern, L"null", wsTextFormat); - int32_t iPattern = 0; - const FX_WCHAR* pStrPattern = wsTextFormat.c_str(); - int32_t 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(const CFX_WideString& wsLocale) { - 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) \ - ((uint8_t)(((FLAGS) & ~FXMATH_DECIMAL_NEGMASK) >> 0x10)) -#define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x) >> 0x10 >> 0x10) -#define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x) << 0x10 << 0x10) -static inline uint8_t fxmath_decimal_helper_div10(uint64_t& phi, - uint64_t& pmid, - uint64_t& plo) { - uint8_t 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 uint8_t fxmath_decimal_helper_div10_any(uint64_t nums[], - uint8_t numcount) { - uint8_t 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(uint64_t& phi, - uint64_t& pmid, - uint64_t& plo) { - plo *= 0xA; - pmid = pmid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(plo); - plo = (uint32_t)plo; - phi = phi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(pmid); - pmid = (uint32_t)pmid; -} -static inline void fxmath_decimal_helper_mul10_any(uint64_t nums[], - uint8_t 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] = (uint32_t)nums[i - 1]; - } -} -static inline void fxmath_decimal_helper_normalize(uint64_t& phi, - uint64_t& pmid, - uint64_t& plo) { - phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid); - pmid = (uint32_t)pmid; - pmid += FXMATH_DECIMAL_RSHIFT32BIT(plo); - plo = (uint32_t)plo; - phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid); - pmid = (uint32_t)pmid; -} -static inline void fxmath_decimal_helper_normalize_any(uint64_t nums[], - uint8_t len) { - { - for (int i = len - 2; i > 0; i--) { - nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]); - nums[i] = (uint32_t)nums[i]; - } - } - { - for (int i = 0; i < len - 1; i++) { - nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]); - nums[i] = (uint32_t)nums[i]; - } - } -} -static inline int8_t fxmath_decimal_helper_raw_compare(uint32_t hi1, - uint32_t mid1, - uint32_t lo1, - uint32_t hi2, - uint32_t mid2, - uint32_t lo2) { - int8_t 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 int8_t fxmath_decimal_helper_raw_compare_any(uint64_t a[], - uint8_t al, - uint64_t b[], - uint8_t bl) { - int8_t retVal = 0; - for (int i = std::max(al - 1, bl - 1); i >= 0; i--) { - uint64_t 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(uint64_t a[], uint8_t al) { - for (int i = 0; i < al; i++) { - if (a[i]--) { - return; - } - } -} -static inline void fxmath_decimal_helper_inc_any(uint64_t a[], uint8_t al) { - for (int i = 0; i < al; i++) { - a[i]++; - if ((uint32_t)a[i] == a[i]) { - return; - } - a[i] = 0; - } -} -static inline void fxmath_decimal_helper_raw_mul(uint64_t a[], - uint8_t al, - uint64_t b[], - uint8_t bl, - uint64_t c[], - uint8_t 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++) { - uint64_t m = (uint64_t)a[i] * b[j]; - c[i + j] += (uint32_t)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] = (uint32_t)c[i]; - } - } - { - for (int i = 0; i < cl; i++) { - c[i] = (uint32_t)c[i]; - } - } -} -static inline void fxmath_decimal_helper_raw_div(uint64_t a[], - uint8_t al, - uint64_t b[], - uint8_t bl, - uint64_t c[], - uint8_t cl) { - int i; - for (i = 0; i < cl; i++) { - c[i] = 0; - } - uint64_t left[16] = {0}, right[16] = {0}; - left[0] = 0; - for (i = 0; i < al; i++) { - right[i] = a[i]; - } - uint64_t tmp[16]; - while (fxmath_decimal_helper_raw_compare_any(left, al, right, al) <= 0) { - uint64_t 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 < std::min(al, cl); i++) { - c[i] = cur[i]; - } - return; - } - } - for (i = 0; i < std::min(al, cl); i++) { - c[i] = left[i]; - } -} -static inline bool fxmath_decimal_helper_outofrange(uint64_t a[], - uint8_t al, - uint8_t goal) { - for (int i = goal; i < al; i++) { - if (a[i]) { - return true; - } - } - return false; -} -static inline void fxmath_decimal_helper_shrinkintorange(uint64_t a[], - uint8_t al, - uint8_t goal, - uint8_t& scale) { - 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(uint64_t& phi, - uint64_t& pmid, - uint64_t& plo, - uint8_t& scale, - uint8_t minscale = 0) { - while (scale > minscale) { - uint64_t 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(uint64_t val) { - m_uLo = (uint32_t)val; - m_uMid = (uint32_t)FXMATH_DECIMAL_RSHIFT32BIT(val); - m_uHi = 0; - m_uFlags = 0; -} -CFX_Decimal::CFX_Decimal(uint32_t val) { - m_uLo = (uint32_t)val; - m_uMid = m_uHi = 0; - m_uFlags = 0; -} -CFX_Decimal::CFX_Decimal(uint32_t lo, - uint32_t mid, - uint32_t hi, - bool neg, - uint8_t 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(int32_t val) { - if (val >= 0) { - *this = CFX_Decimal((uint32_t)val); - } else { - *this = CFX_Decimal((uint32_t)-val); - SetNegate(); - } -} -CFX_Decimal::CFX_Decimal(int64_t val) { - if (val >= 0) { - *this = CFX_Decimal((uint64_t)val); - } else { - *this = CFX_Decimal((uint64_t)-val); - SetNegate(); - } -} -CFX_Decimal::CFX_Decimal(FX_FLOAT val, uint8_t scale) { - FX_FLOAT newval = fabs(val); - uint64_t phi, pmid, plo; - plo = (uint64_t)newval; - pmid = (uint64_t)(newval / 1e32); - phi = (uint64_t)(newval / 1e64); - newval = FXSYS_fmod(newval, 1.0f); - for (uint8_t iter = 0; iter < scale; iter++) { - fxmath_decimal_helper_mul10(phi, pmid, plo); - newval *= 10; - plo += (uint64_t)newval; - newval = FXSYS_fmod(newval, 1.0f); - } - plo += FXSYS_round(newval); - fxmath_decimal_helper_normalize(phi, pmid, plo); - m_uHi = (uint32_t)phi; - m_uMid = (uint32_t)pmid; - m_uLo = (uint32_t)plo; - m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale); -} -CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) { - const FX_WCHAR* str = strObj.c_str(); - const FX_WCHAR* strBound = str + strObj.GetLength(); - bool pointmet = 0; - bool negmet = 0; - uint8_t 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((uint64_t)m_uMid * 0xA); - m_uMid = m_uMid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)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(const CFX_ByteStringC& strObj) { - *this = CFX_Decimal(CFX_WideString::FromLocal(strObj).AsStringC()); -} - -CFX_Decimal::operator CFX_WideString() const { - CFX_WideString retString; - CFX_WideString tmpbuf; - uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo; - while (phi || pmid || plo) { - tmpbuf += fxmath_decimal_helper_div10(phi, pmid, plo) + '0'; - } - uint8_t outputlen = (uint8_t)tmpbuf.GetLength(); - uint8_t scale = (uint8_t)FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); - while (scale >= outputlen) { - tmpbuf += '0'; - outputlen++; - } - if (FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero()) { - retString += '-'; - } - for (uint8_t 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); - int8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); - bool bNeg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags); - return (bNeg ? -1 : 1) * base * ::pow(10.0, -scale); -} -void CFX_Decimal::SetScale(uint8_t newscale) { - uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); - if (newscale > oldscale) { - uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo; - for (uint8_t iter = 0; iter < newscale - oldscale; iter++) { - fxmath_decimal_helper_mul10(phi, pmid, plo); - } - m_uHi = (uint32_t)phi; - m_uMid = (uint32_t)pmid; - m_uLo = (uint32_t)plo; - m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( - FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); - } else if (newscale < oldscale) { - uint64_t phi, pmid, plo; - phi = 0, pmid = 0, plo = 5; - { - for (uint8_t 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 (uint8_t iter = 0; iter < oldscale - newscale; iter++) { - fxmath_decimal_helper_div10(phi, pmid, plo); - } - } - m_uHi = (uint32_t)phi; - m_uMid = (uint32_t)pmid; - m_uLo = (uint32_t)plo; - m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( - FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); - } -} -uint8_t CFX_Decimal::GetScale() { - uint8_t 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(bool bFloor) { - uint64_t nums[3] = {m_uLo, m_uMid, m_uHi}; - 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 = (uint32_t)nums[2]; - m_uMid = (uint32_t)nums[1]; - m_uLo = (uint32_t)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) { - uint32_t 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; -} -int8_t CFX_Decimal::Compare(const CFX_Decimal& val) const { - CFX_Decimal lhs = *this, rhs = val; - int8_t retVal = 0; - if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != - FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) { - uint8_t scale = std::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, - bool isAdding) const { - CFX_Decimal lhs = *this, rhs = val; - if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != - FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) { - uint8_t scale = std::max(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags), - FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)); - lhs.SetScale(scale); - rhs.SetScale(scale); - } - if (!isAdding) { - rhs.SetNegate(); - } - if (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) == - FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags)) { - uint64_t 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 = (uint32_t)phi; - lhs.m_uMid = (uint32_t)pmid; - lhs.m_uLo = (uint32_t)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 { - uint64_t a[3] = {m_uLo, m_uMid, m_uHi}, - b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}; - uint64_t c[6]; - fxmath_decimal_helper_raw_mul(a, 3, b, 3, c, 6); - bool neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ - FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags); - uint8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) + - FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags); - fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale); - return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg, - scale); -} -CFX_Decimal CFX_Decimal::Divide(const CFX_Decimal& val) const { - if (!val.IsNotZero()) { - return CFX_Decimal(); - } - bool neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ - FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags); - uint64_t a[7] = {m_uLo, m_uMid, m_uHi}, - b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0}; - uint8_t 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); - } - uint8_t 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((uint32_t)c[0], (uint32_t)c[1], (uint32_t)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; -} -bool CFX_Decimal::operator==(const CFX_Decimal& val) const { - return Compare(val) == 0; -} -bool CFX_Decimal::operator<=(const CFX_Decimal& val) const { - return Compare(val) <= 0; -} -bool CFX_Decimal::operator>=(const CFX_Decimal& val) const { - return Compare(val) >= 0; -} -bool CFX_Decimal::operator!=(const CFX_Decimal& val) const { - return Compare(val) != 0; -} -bool CFX_Decimal::operator<(const CFX_Decimal& val) const { - return Compare(val) < 0; -} -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/fgas/localization/fgas_locale.h b/xfa/fgas/localization/fgas_locale.h deleted file mode 100644 index f15766d2dd2909af6c118c070b9071cf30872e6a..0000000000000000000000000000000000000000 --- a/xfa/fgas/localization/fgas_locale.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_LOCALIZATION_FGAS_LOCALE_H_ -#define XFA_FGAS_LOCALIZATION_FGAS_LOCALE_H_ - -#include <memory> - -#include "core/fxcrt/fx_xml.h" -#include "xfa/fgas/localization/fgas_datetime.h" - -class CFX_Unitime; - -enum FX_LOCALENUMSYMBOL { - FX_LOCALENUMSYMBOL_Decimal, - FX_LOCALENUMSYMBOL_Grouping, - FX_LOCALENUMSYMBOL_Percent, - FX_LOCALENUMSYMBOL_Minus, - FX_LOCALENUMSYMBOL_Zero, - FX_LOCALENUMSYMBOL_CurrencySymbol, - FX_LOCALENUMSYMBOL_CurrencyName, -}; -enum FX_LOCALEDATETIMESUBCATEGORY { - FX_LOCALEDATETIMESUBCATEGORY_Default, - FX_LOCALEDATETIMESUBCATEGORY_Short, - FX_LOCALEDATETIMESUBCATEGORY_Medium, - FX_LOCALEDATETIMESUBCATEGORY_Full, - FX_LOCALEDATETIMESUBCATEGORY_Long, -}; -enum FX_LOCALENUMSUBCATEGORY { - FX_LOCALENUMPATTERN_Percent, - FX_LOCALENUMPATTERN_Currency, - FX_LOCALENUMPATTERN_Decimal, - FX_LOCALENUMPATTERN_Integer, -}; -enum FX_LOCALECATEGORY { - FX_LOCALECATEGORY_Unknown, - FX_LOCALECATEGORY_Date, - FX_LOCALECATEGORY_Time, - FX_LOCALECATEGORY_DateTime, - FX_LOCALECATEGORY_Num, - FX_LOCALECATEGORY_Text, - FX_LOCALECATEGORY_Zero, - FX_LOCALECATEGORY_Null, -}; -enum FX_DATETIMETYPE { - FX_DATETIMETYPE_Unknown, - FX_DATETIMETYPE_Date, - FX_DATETIMETYPE_Time, - FX_DATETIMETYPE_DateTime, - FX_DATETIMETYPE_TimeDate, -}; - -class IFX_Locale { - public: - virtual ~IFX_Locale() {} - - virtual CFX_WideString GetName() const = 0; - virtual void GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, - CFX_WideString& wsNumSymbol) const = 0; - virtual void GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const = 0; - virtual void GetMonthName(int32_t nMonth, - CFX_WideString& wsMonthName, - bool bAbbr = true) const = 0; - virtual void GetDayName(int32_t nWeek, - CFX_WideString& wsDayName, - bool bAbbr = true) const = 0; - virtual void GetMeridiemName(CFX_WideString& wsMeridiemName, - bool bAM = true) const = 0; - virtual void GetTimeZone(FX_TIMEZONE* tz) const = 0; - virtual void GetEraName(CFX_WideString& wsEraName, bool bAD = true) const = 0; - virtual void GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const = 0; - virtual void GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const = 0; - virtual void GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, - CFX_WideString& wsPattern) const = 0; -}; - -class IFX_LocaleMgr { - public: - virtual ~IFX_LocaleMgr() {} - - virtual uint16_t GetDefLocaleID() const = 0; - virtual IFX_Locale* GetDefLocale() = 0; - virtual IFX_Locale* GetLocaleByName(const CFX_WideString& wsLocaleName) = 0; - - protected: - virtual std::unique_ptr<IFX_Locale> GetLocale(uint16_t lcid) = 0; -}; - -bool FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime& datetime); -bool FX_TimeFromCanonical(const CFX_WideStringC& wsTime, - CFX_Unitime& datetime, - IFX_Locale* pLocale); -class CFX_Decimal { - public: - CFX_Decimal(); - explicit CFX_Decimal(uint32_t val); - explicit CFX_Decimal(uint64_t val); - explicit CFX_Decimal(int32_t val); - explicit CFX_Decimal(int64_t val); - explicit CFX_Decimal(FX_FLOAT val, uint8_t scale = 3); - explicit CFX_Decimal(const CFX_WideStringC& str); - explicit CFX_Decimal(const CFX_ByteStringC& str); - operator CFX_WideString() const; - operator double() const; - bool operator==(const CFX_Decimal& val) const; - bool operator<=(const CFX_Decimal& val) const; - bool operator>=(const CFX_Decimal& val) const; - bool operator!=(const CFX_Decimal& val) const; - bool operator<(const CFX_Decimal& val) const; - bool operator>(const CFX_Decimal& val) const; - CFX_Decimal operator+(const CFX_Decimal& val) const; - CFX_Decimal operator-(const CFX_Decimal& val) const; - CFX_Decimal operator*(const CFX_Decimal& val) const; - CFX_Decimal operator/(const CFX_Decimal& val) const; - CFX_Decimal operator%(const CFX_Decimal& val) const; - void SetScale(uint8_t newScale); - uint8_t GetScale(); - void SetAbs(); - void SetNegate(); - void SetFloor(); - void SetCeiling(); - void SetTruncate(); - - protected: - CFX_Decimal(uint32_t hi, uint32_t mid, uint32_t lo, bool neg, uint8_t scale); - inline bool IsNotZero() const { return m_uHi || m_uMid || m_uLo; } - inline int8_t Compare(const CFX_Decimal& val) const; - inline void Swap(CFX_Decimal& val); - inline void FloorOrCeil(bool bFloor); - CFX_Decimal AddOrMinus(const CFX_Decimal& val, bool isAdding) const; - CFX_Decimal Multiply(const CFX_Decimal& val) const; - CFX_Decimal Divide(const CFX_Decimal& val) const; - CFX_Decimal Modulus(const CFX_Decimal& val) const; - uint32_t m_uFlags; - uint32_t m_uHi; - uint32_t m_uLo; - uint32_t m_uMid; -}; - -#endif // XFA_FGAS_LOCALIZATION_FGAS_LOCALE_H_ diff --git a/xfa/fgas/localization/fgas_localeimp.h b/xfa/fgas/localization/fgas_localeimp.h deleted file mode 100644 index a66921b61c09717b4d1e67b980b3210c4b21923b..0000000000000000000000000000000000000000 --- a/xfa/fgas/localization/fgas_localeimp.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FGAS_LOCALIZATION_FGAS_LOCALEIMP_H_ -#define XFA_FGAS_LOCALIZATION_FGAS_LOCALEIMP_H_ - -#include <vector> - -#include "xfa/fgas/localization/fgas_locale.h" - -class CFX_LCNumeric; - -class CFX_FormatString { - public: - CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, bool bUseLCID); - ~CFX_FormatString(); - - void SplitFormatString(const CFX_WideString& wsFormatString, - std::vector<CFX_WideString>& wsPatterns); - FX_LOCALECATEGORY GetCategory(const CFX_WideString& wsPattern); - uint16_t GetLCID(const CFX_WideString& wsPattern); - CFX_WideString GetLocaleName(const CFX_WideString& wsPattern); - bool ParseText(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern, - CFX_WideString& wsValue); - bool ParseNum(const CFX_WideString& wsSrcNum, - const CFX_WideString& wsPattern, - FX_FLOAT& fValue); - bool ParseNum(const CFX_WideString& wsSrcNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsValue); - bool ParseDateTime(const CFX_WideString& wsSrcDateTime, - const CFX_WideString& wsPattern, - FX_DATETIMETYPE eDateTimeType, - CFX_Unitime& dtValue); - bool ParseZero(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern); - bool ParseNull(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern); - bool FormatText(const CFX_WideString& wsSrcText, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput); - bool FormatNum(const CFX_WideString& wsSrcNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput); - bool FormatNum(FX_FLOAT fNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput); - bool FormatDateTime(const CFX_WideString& wsSrcDateTime, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput); - bool FormatDateTime(const CFX_WideString& wsSrcDateTime, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput, - FX_DATETIMETYPE eDateTimeType); - bool FormatDateTime(const CFX_Unitime& dt, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput); - bool FormatZero(const CFX_WideString& wsPattern, CFX_WideString& wsOutput); - bool FormatNull(const CFX_WideString& wsPattern, CFX_WideString& wsOutput); - - protected: - IFX_Locale* GetTextFormat(const CFX_WideString& wsPattern, - const CFX_WideStringC& wsCategory, - CFX_WideString& wsPurgePattern); - IFX_Locale* GetNumericFormat(const CFX_WideString& wsPattern, - int32_t& iDotIndex, - uint32_t& dwStyle, - CFX_WideString& wsPurgePattern); - bool FormatStrNum(const CFX_WideStringC& wsInputNum, - const CFX_WideString& wsPattern, - CFX_WideString& wsOutput); - 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(const CFX_WideString& wsLocale); - - IFX_LocaleMgr* m_pLocaleMgr; - bool m_bUseLCID; -}; - -#endif // XFA_FGAS_LOCALIZATION_FGAS_LOCALEIMP_H_ diff --git a/xfa/fwl/README.md b/xfa/fwl/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9285e8934595a78778a48e7721eb6b02d8f095fd --- /dev/null +++ b/xfa/fwl/README.md @@ -0,0 +1,58 @@ +xfa/fwl is a Widget Library for XFA Forms. + +CFWL_Widget is the base class that widget classes extend. The derived widget +classes are both controllers and renderers for each widget. The hierarchy is: + +* CFWL_Widget + * CFWL_Form + * CFWL_FormProxy + * CFWL_ComboBoxProxy + * CFWL_Caret + * CFWL_CheckBox + * CFWL_ComboBox + * CFWL_DateTimePicker + * CFWL_Edit + * CFWL_Barcode + * CFWL_ComboEdit + * CFWL_DateTimeEdit + * CFWL_ListBox + * CFWL_ComboList + * CFWL_MonthCalendar + * CFWL_PictureBox + * CFWL_PushButton + * CFWL_ScrollBar + * CFWL_SpinButton + +These CFWL widgets are instantiated by and closely related to the CXFA classes +in the xfa/fxfa directory. See xfa/fxfa/README.md. + +CFWL_Widget implements IFWL_WidgetDelegate through which it receives messages, +events and draw calls. + +Messages consist of user input for a widget to handle. Each type of message is +identified by an enum value in Message::Type and has its own class derived from +the base CFWL_Message. + +* CFWL_Message + * CFWL_MessageKey + * CFWL_MessageKillFocus + * CFWL_MessageMouse + * CFWL_MessageMouseWheel + * CFWL_MessageSetFocus + +Events are originated in the widgets and are then handled by other CFWL_Widget +and CXFA classes. + +* CFWL_Event + * CFWL_EventCheckWord + * CFWL_EventMouse + * CFWL_EventScroll + * CFWL_EventSelectChanged + * CFWL_EventTextChanged + * CFWL_EventValidate + +The widgets use IFWL_ThemeProvider for rendering everything, calling +DrawBackground() and DrawText() and passing many options in their parameters, +respectively of types CFWL_ThemeBackground and CFWL_ThemeText. See +xfa/fwl/theme/README.md. + diff --git a/xfa/fwl/cfwl_app.cpp b/xfa/fwl/cfwl_app.cpp index febc8a0fdf863555f5e06bfbb3acac07a548195a..58ca93de61414ed056456dd21adea7b524602b7f 100644 --- a/xfa/fwl/cfwl_app.cpp +++ b/xfa/fwl/cfwl_app.cpp @@ -10,7 +10,7 @@ #include "xfa/fwl/cfwl_notedriver.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/cfwl_widgetmgr.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" CFWL_App::CFWL_App(CXFA_FFApp* pAdapter) : m_pAdapterNative(pAdapter), diff --git a/xfa/fwl/cfwl_app.h b/xfa/fwl/cfwl_app.h index c2779e8a258424a513f66169b2d90a36dd3d9c53..ed47149a56f92b905c91e45b2ccce005c6c94f12 100644 --- a/xfa/fwl/cfwl_app.h +++ b/xfa/fwl/cfwl_app.h @@ -32,12 +32,12 @@ class CFWL_App { explicit CFWL_App(CXFA_FFApp* pAdapter); ~CFWL_App(); - CXFA_FFApp* GetAdapterNative() const { return m_pAdapterNative; } + CXFA_FFApp* GetAdapterNative() const { return m_pAdapterNative.Get(); } CFWL_WidgetMgr* GetWidgetMgr() const { return m_pWidgetMgr.get(); } CFWL_NoteDriver* GetNoteDriver() const { return m_pNoteDriver.get(); } private: - CXFA_FFApp* const m_pAdapterNative; + UnownedPtr<CXFA_FFApp> const m_pAdapterNative; std::unique_ptr<CFWL_WidgetMgr> m_pWidgetMgr; std::unique_ptr<CFWL_NoteDriver> m_pNoteDriver; }; diff --git a/xfa/fwl/cfwl_barcode.cpp b/xfa/fwl/cfwl_barcode.cpp index 0412b86958b1e24a70012f8e1f9f0fadacaf61fc..f5d6ea98b20bbea8865be597612be20e52825fc5 100644 --- a/xfa/fwl/cfwl_barcode.cpp +++ b/xfa/fwl/cfwl_barcode.cpp @@ -14,6 +14,7 @@ #include "xfa/fwl/cfwl_themepart.h" #include "xfa/fwl/cfx_barcode.h" #include "xfa/fwl/ifwl_themeprovider.h" +#include "xfa/fwl/theme/cfwl_utils.h" CFWL_Barcode::CFWL_Barcode(const CFWL_App* app) : CFWL_Edit(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr), @@ -35,8 +36,8 @@ void CFWL_Barcode::Update() { GenerateBarcodeImageCache(); } -void CFWL_Barcode::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_Barcode::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -49,15 +50,12 @@ void CFWL_Barcode::DrawWidget(CFX_Graphics* pGraphics, CFX_Matrix mt; mt.e = GetRTClient().left; mt.f = GetRTClient().top; - if (pMatrix) - mt.Concat(*pMatrix); + mt.Concat(matrix); - int32_t errorCode = 0; - m_pBarcodeEngine->RenderDevice(pGraphics->GetRenderDevice(), pMatrix, - errorCode); + m_pBarcodeEngine->RenderDevice(pGraphics->GetRenderDevice(), &matrix); return; } - CFWL_Edit::DrawWidget(pGraphics, pMatrix); + CFWL_Edit::DrawWidget(pGraphics, matrix); } void CFWL_Barcode::SetType(BC_TYPE type) { @@ -69,7 +67,7 @@ void CFWL_Barcode::SetType(BC_TYPE type) { m_dwStatus = XFA_BCS_NeedUpdate; } -void CFWL_Barcode::SetText(const CFX_WideString& wsText) { +void CFWL_Barcode::SetText(const WideString& wsText) { m_pBarcodeEngine.reset(); m_dwStatus = XFA_BCS_NeedUpdate; CFWL_Edit::SetText(wsText); @@ -131,17 +129,17 @@ void CFWL_Barcode::SetTextLocation(BC_TEXT_LOC location) { m_eTextLocation = location; } -void CFWL_Barcode::SetWideNarrowRatio(int32_t ratio) { +void CFWL_Barcode::SetWideNarrowRatio(int8_t ratio) { m_dwAttributeMask |= FWL_BCDATTRIBUTE_WIDENARROWRATIO; m_nWideNarrowRatio = ratio; } -void CFWL_Barcode::SetStartChar(FX_CHAR startChar) { +void CFWL_Barcode::SetStartChar(char startChar) { m_dwAttributeMask |= FWL_BCDATTRIBUTE_STARTCHAR; m_cStartChar = startChar; } -void CFWL_Barcode::SetEndChar(FX_CHAR endChar) { +void CFWL_Barcode::SetEndChar(char endChar) { m_dwAttributeMask |= FWL_BCDATTRIBUTE_ENDCHAR; m_cEndChar = endChar; } @@ -169,7 +167,7 @@ void CFWL_Barcode::GenerateBarcodeImageCache() { if (pTheme) { CFWL_ThemePart part; part.m_pWidget = this; - if (CFX_RetainPtr<CFGAS_GEFont> pFont = pTheme->GetFont(&part)) { + if (RetainPtr<CFGAS_GEFont> pFont = pTheme->GetFont(&part)) { if (CFX_Font* pCXFont = pFont->GetDevFont()) m_pBarcodeEngine->SetFont(pCXFont); } @@ -201,15 +199,12 @@ void CFWL_Barcode::GenerateBarcodeImageCache() { m_pBarcodeEngine->SetStartChar(m_cStartChar); if (m_dwAttributeMask & FWL_BCDATTRIBUTE_ENDCHAR) m_pBarcodeEngine->SetEndChar(m_cEndChar); - if (m_dwAttributeMask & FWL_BCDATTRIBUTE_VERSION) - m_pBarcodeEngine->SetVersion(0); if (m_dwAttributeMask & FWL_BCDATTRIBUTE_ECLEVEL) m_pBarcodeEngine->SetErrorCorrectionLevel(m_nECLevel); if (m_dwAttributeMask & FWL_BCDATTRIBUTE_TRUNCATED) m_pBarcodeEngine->SetTruncated(m_bTruncated); - int32_t errorCode = 0; - m_dwStatus = m_pBarcodeEngine->Encode(GetText().AsStringC(), true, errorCode) + m_dwStatus = m_pBarcodeEngine->Encode(GetText().AsStringView()) ? XFA_BCS_EncodeSuccess : 0; } @@ -218,7 +213,7 @@ void CFWL_Barcode::CreateBarcodeEngine() { if (m_pBarcodeEngine || m_type == BC_UNKNOWN) return; - std::unique_ptr<CFX_Barcode> pBarcode(new CFX_Barcode); + auto pBarcode = pdfium::MakeUnique<CFX_Barcode>(); if (pBarcode->Create(m_type)) m_pBarcodeEngine = std::move(pBarcode); } diff --git a/xfa/fwl/cfwl_barcode.h b/xfa/fwl/cfwl_barcode.h index 2e9799172b68d7f1151113cf5cc3bd46e8644de0..2fc79608b3fb5d08f7b84d57f4dae9d81389c567 100644 --- a/xfa/fwl/cfwl_barcode.h +++ b/xfa/fwl/cfwl_barcode.h @@ -9,10 +9,10 @@ #include <memory> +#include "fxbarcode/BC_Library.h" #include "xfa/fwl/cfwl_edit.h" #include "xfa/fwl/cfwl_scrollbar.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxbarcode/BC_Library.h" class CFWL_WidgetProperties; class CFX_Barcode; @@ -33,9 +33,8 @@ enum FWL_BCDAttribute { FWL_BCDATTRIBUTE_WIDENARROWRATIO = 1 << 7, FWL_BCDATTRIBUTE_STARTCHAR = 1 << 8, FWL_BCDATTRIBUTE_ENDCHAR = 1 << 9, - FWL_BCDATTRIBUTE_VERSION = 1 << 10, - FWL_BCDATTRIBUTE_ECLEVEL = 1 << 11, - FWL_BCDATTRIBUTE_TRUNCATED = 1 << 12 + FWL_BCDATTRIBUTE_ECLEVEL = 1 << 10, + FWL_BCDATTRIBUTE_TRUNCATED = 1 << 11, }; class CFWL_Barcode : public CFWL_Edit { @@ -46,11 +45,11 @@ class CFWL_Barcode : public CFWL_Edit { // CFWL_Widget FWL_Type GetClassID() const override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessEvent(CFWL_Event* pEvent) override; // CFWL_Edit - void SetText(const CFX_WideString& wsText) override; + void SetText(const WideString& wsText) override; void SetType(BC_TYPE type); bool IsProtectedType() const; @@ -62,9 +61,9 @@ class CFWL_Barcode : public CFWL_Edit { void SetCalChecksum(bool calChecksum); void SetPrintChecksum(bool printChecksum); void SetTextLocation(BC_TEXT_LOC location); - void SetWideNarrowRatio(int32_t ratio); - void SetStartChar(FX_CHAR startChar); - void SetEndChar(FX_CHAR endChar); + void SetWideNarrowRatio(int8_t ratio); + void SetStartChar(char startChar); + void SetEndChar(char endChar); void SetErrorCorrectionLevel(int32_t ecLevel); void SetTruncated(bool truncated); @@ -82,9 +81,9 @@ class CFWL_Barcode : public CFWL_Edit { bool m_bCalChecksum; bool m_bPrintChecksum; BC_TEXT_LOC m_eTextLocation; - int32_t m_nWideNarrowRatio; - FX_CHAR m_cStartChar; - FX_CHAR m_cEndChar; + int8_t m_nWideNarrowRatio; + char m_cStartChar; + char m_cEndChar; int32_t m_nECLevel; bool m_bTruncated; uint32_t m_dwAttributeMask; diff --git a/xfa/fwl/cfwl_caret.cpp b/xfa/fwl/cfwl_caret.cpp index da57cb408cf7e8399f64b41d757161b13cee33c2..cd85041d92ebae5b9c2dbba7c14dc177f116217b 100644 --- a/xfa/fwl/cfwl_caret.cpp +++ b/xfa/fwl/cfwl_caret.cpp @@ -19,15 +19,17 @@ namespace { const uint32_t kFrequency = 400; +constexpr int kStateHighlight = (1 << 0); + } // namespace CFWL_Caret::CFWL_Caret(const CFWL_App* app, std::unique_ptr<CFWL_WidgetProperties> properties, CFWL_Widget* pOuter) : CFWL_Widget(app, std::move(properties), pOuter), - m_pTimer(new CFWL_Caret::Timer(this)), + m_pTimer(pdfium::MakeUnique<CFWL_Caret::Timer>(this)), m_pTimerInfo(nullptr) { - SetStates(FWL_STATE_CAT_HightLight); + SetStates(kStateHighlight); } CFWL_Caret::~CFWL_Caret() { @@ -43,8 +45,8 @@ FWL_Type CFWL_Caret::GetClassID() const { void CFWL_Caret::Update() {} -void CFWL_Caret::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_Caret::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -52,7 +54,7 @@ void CFWL_Caret::DrawWidget(CFX_Graphics* pGraphics, if (!m_pProperties->m_pThemeProvider) return; - DrawCaretBK(pGraphics, m_pProperties->m_pThemeProvider, pMatrix); + DrawCaretBK(pGraphics, m_pProperties->m_pThemeProvider, &matrix); } void CFWL_Caret::ShowCaret() { @@ -70,10 +72,10 @@ void CFWL_Caret::HideCaret() { SetStates(FWL_WGTSTATE_Invisible); } -void CFWL_Caret::DrawCaretBK(CFX_Graphics* pGraphics, +void CFWL_Caret::DrawCaretBK(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { - if (!(m_pProperties->m_dwStates & FWL_STATE_CAT_HightLight)) + if (!(m_pProperties->m_dwStates & kStateHighlight)) return; CFWL_ThemeBackground param; @@ -89,19 +91,19 @@ void CFWL_Caret::DrawCaretBK(CFX_Graphics* pGraphics, void CFWL_Caret::OnProcessMessage(CFWL_Message* pMessage) {} -void CFWL_Caret::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_Caret::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } CFWL_Caret::Timer::Timer(CFWL_Caret* pCaret) : CFWL_Timer(pCaret) {} void CFWL_Caret::Timer::Run(CFWL_TimerInfo* pTimerInfo) { - CFWL_Caret* pCaret = static_cast<CFWL_Caret*>(m_pWidget); - if (!(pCaret->GetStates() & FWL_STATE_CAT_HightLight)) - pCaret->SetStates(FWL_STATE_CAT_HightLight); + CFWL_Caret* pCaret = static_cast<CFWL_Caret*>(m_pWidget.Get()); + if (!(pCaret->GetStates() & kStateHighlight)) + pCaret->SetStates(kStateHighlight); else - pCaret->RemoveStates(FWL_STATE_CAT_HightLight); + pCaret->RemoveStates(kStateHighlight); CFX_RectF rt = pCaret->GetWidgetRect(); pCaret->RepaintRect(CFX_RectF(0, 0, rt.width + 1, rt.height)); diff --git a/xfa/fwl/cfwl_caret.h b/xfa/fwl/cfwl_caret.h index e0c07d301a78a9decc118e1ad949ef1f7b1d8ad6..90d62d6e9b74558ebb0fd320b0d8bd01cb0195b1 100644 --- a/xfa/fwl/cfwl_caret.h +++ b/xfa/fwl/cfwl_caret.h @@ -11,13 +11,11 @@ #include "xfa/fwl/cfwl_timer.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxgraphics/cfx_color.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" class CFWL_WidgetProperties; class CFWL_Widget; -#define FWL_STATE_CAT_HightLight 1 - class CFWL_Caret : public CFWL_Widget { public: CFWL_Caret(const CFWL_App* app, @@ -27,10 +25,10 @@ class CFWL_Caret : public CFWL_Widget { // CFWL_Widget FWL_Type GetClassID() const override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; void Update() override; void ShowCaret(); @@ -46,12 +44,12 @@ class CFWL_Caret : public CFWL_Widget { }; friend class CFWL_Caret::Timer; - void DrawCaretBK(CFX_Graphics* pGraphics, + void DrawCaretBK(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); std::unique_ptr<CFWL_Caret::Timer> m_pTimer; - CFWL_TimerInfo* m_pTimerInfo; // not owned. + UnownedPtr<CFWL_TimerInfo> m_pTimerInfo; }; #endif // XFA_FWL_CFWL_CARET_H_ diff --git a/xfa/fwl/cfwl_checkbox.cpp b/xfa/fwl/cfwl_checkbox.cpp index 0102bc7cc42a6a228ce40727d42d062854343be8..42b6cadc8393d015468f961c0ec88abc9c152c28 100644 --- a/xfa/fwl/cfwl_checkbox.cpp +++ b/xfa/fwl/cfwl_checkbox.cpp @@ -12,7 +12,7 @@ #include <vector> #include "third_party/base/ptr_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_messagekey.h" @@ -31,10 +31,10 @@ const int kCaptionMargin = 5; CFWL_CheckBox::CFWL_CheckBox(const CFWL_App* app) : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr), - m_dwTTOStyles(FDE_TTOSTYLE_SingleLine), - m_iTTOAlign(FDE_TTOALIGNMENT_Center), + m_iTTOAlign(FDE_TextAlignment::kCenter), m_bBtnDown(false), m_fBoxHeight(16.0f) { + m_dwTTOStyles.single_line_ = true; m_rtClient.Reset(); m_rtBox.Reset(); m_rtCaption.Reset(); @@ -47,7 +47,7 @@ FWL_Type CFWL_CheckBox::GetClassID() const { return FWL_Type::CheckBox; } -void CFWL_CheckBox::SetBoxSize(FX_FLOAT fHeight) { +void CFWL_CheckBox::SetBoxSize(float fHeight) { m_fBoxHeight = fHeight; } @@ -61,8 +61,8 @@ void CFWL_CheckBox::Update() { Layout(); } -void CFWL_CheckBox::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_CheckBox::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -71,7 +71,7 @@ void CFWL_CheckBox::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; if (HasBorder()) { DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider, - pMatrix); + matrix); } int32_t dwStates = GetPartStates(); @@ -81,8 +81,7 @@ void CFWL_CheckBox::DrawWidget(CFX_Graphics* pGraphics, param.m_iPart = CFWL_Part::Background; param.m_dwStates = dwStates; param.m_pGraphics = pGraphics; - if (pMatrix) - param.m_matrix.Concat(*pMatrix); + param.m_matrix.Concat(matrix); param.m_rtPart = m_rtClient; if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) param.m_pData = &m_rtFocus; @@ -97,8 +96,7 @@ void CFWL_CheckBox::DrawWidget(CFX_Graphics* pGraphics, textParam.m_iPart = CFWL_Part::Caption; textParam.m_dwStates = dwStates; textParam.m_pGraphics = pGraphics; - if (pMatrix) - textParam.m_matrix.Concat(*pMatrix); + textParam.m_matrix.Concat(matrix); textParam.m_rtPart = m_rtCaption; textParam.m_wsText = L"Check box"; textParam.m_dwTTOStyles = m_dwTTOStyles; @@ -129,7 +127,7 @@ void CFWL_CheckBox::Layout() { FXSYS_round(m_pProperties->m_rtWidget.height); m_rtClient = GetClientRect(); - FX_FLOAT fTextLeft = m_rtClient.left + m_fBoxHeight; + float fTextLeft = m_rtClient.left + m_fBoxHeight; m_rtBox = CFX_RectF(m_rtClient.TopLeft(), m_fBoxHeight, m_fBoxHeight); m_rtCaption = CFX_RectF(fTextLeft, m_rtClient.top, m_rtClient.right() - fTextLeft, m_rtClient.height); @@ -170,9 +168,10 @@ uint32_t CFWL_CheckBox::GetPartStates() const { } void CFWL_CheckBox::UpdateTextOutStyles() { - m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft; - m_dwTTOStyles = 0; - m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine; + m_iTTOAlign = FDE_TextAlignment::kTopLeft; + + m_dwTTOStyles.Reset(); + m_dwTTOStyles.single_line_ = true; } void CFWL_CheckBox::NextStates() { @@ -184,7 +183,7 @@ void CFWL_CheckBox::NextStates() { if (!pWidgetMgr->IsFormDisabled()) { std::vector<CFWL_Widget*> radioarr = pWidgetMgr->GetSameGroupRadioButton(this); - for (const auto& pWidget : radioarr) { + for (auto* pWidget : radioarr) { CFWL_CheckBox* pCheckBox = static_cast<CFWL_CheckBox*>(pWidget); if (pCheckBox != this && pCheckBox->GetStates() & FWL_STATE_CKB_Checked) { @@ -266,9 +265,9 @@ void CFWL_CheckBox::OnProcessMessage(CFWL_Message* pMessage) { CFWL_Widget::OnProcessMessage(pMessage); } -void CFWL_CheckBox::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_CheckBox::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_CheckBox::OnFocusChanged(bool bSet) { diff --git a/xfa/fwl/cfwl_checkbox.h b/xfa/fwl/cfwl_checkbox.h index 6df7440894e76284cbe68883f2858b7cc5ac42e7..9ae6590b2f737a48f7f2c535f181a9dd25e6412a 100644 --- a/xfa/fwl/cfwl_checkbox.h +++ b/xfa/fwl/cfwl_checkbox.h @@ -41,13 +41,13 @@ class CFWL_CheckBox : public CFWL_Widget { // CFWL_Widget FWL_Type GetClassID() const override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; - void SetBoxSize(FX_FLOAT fHeight); + void SetBoxSize(float fHeight); private: void SetCheckState(int32_t iCheck); @@ -66,10 +66,10 @@ class CFWL_CheckBox : public CFWL_Widget { CFX_RectF m_rtBox; CFX_RectF m_rtCaption; CFX_RectF m_rtFocus; - uint32_t m_dwTTOStyles; - int32_t m_iTTOAlign; + FDE_TextStyle m_dwTTOStyles; + FDE_TextAlignment m_iTTOAlign; bool m_bBtnDown; - FX_FLOAT m_fBoxHeight; + float m_fBoxHeight; }; #endif // XFA_FWL_CFWL_CHECKBOX_H_ diff --git a/xfa/fwl/cfwl_combobox.cpp b/xfa/fwl/cfwl_combobox.cpp index 6083943f94e989ce6be766c1bf085df7d8767d5b..143d797fbda7b79b18602f2d1ccdba5ec76ea9d7 100644 --- a/xfa/fwl/cfwl_combobox.cpp +++ b/xfa/fwl/cfwl_combobox.cpp @@ -11,8 +11,8 @@ #include <utility> #include "third_party/base/ptr_util.h" -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_texteditengine.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_eventselectchanged.h" @@ -49,12 +49,12 @@ CFWL_ComboBox::CFWL_ComboBox(const CFWL_App* app) auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; prop->m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; - m_pListBox = - pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this); + m_pListBox = pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp.Get(), + std::move(prop), this); if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) { m_pEdit = pdfium::MakeUnique<CFWL_ComboEdit>( - m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this); + m_pOwnerApp.Get(), pdfium::MakeUnique<CFWL_WidgetProperties>(), this); m_pEdit->SetOuter(this); } if (m_pEdit) @@ -69,7 +69,7 @@ FWL_Type CFWL_ComboBox::GetClassID() const { return FWL_Type::ComboBox; } -void CFWL_ComboBox::AddString(const CFX_WideStringC& wsText) { +void CFWL_ComboBox::AddString(const WideStringView& wsText) { m_pListBox->AddString(wsText); } @@ -92,7 +92,8 @@ void CFWL_ComboBox::ModifyStylesEx(uint32_t dwStylesExAdded, bool bRemoveDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown); if (bAddDropDown && !m_pEdit) { m_pEdit = pdfium::MakeUnique<CFWL_ComboEdit>( - m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); + m_pOwnerApp.Get(), pdfium::MakeUnique<CFWL_WidgetProperties>(), + nullptr); m_pEdit->SetOuter(this); m_pEdit->SetParent(this); } else if (bRemoveDropDown && m_pEdit) { @@ -124,10 +125,10 @@ FWL_WidgetHit CFWL_ComboBox::HitTest(const CFX_PointF& point) { return CFWL_Widget::HitTest(point); } -void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_ComboBox::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (m_pWidgetMgr->IsFormDisabled()) { - DisForm_DrawWidget(pGraphics, pMatrix); + DisForm_DrawWidget(pGraphics, &matrix); return; } @@ -138,7 +139,7 @@ void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); if (!IsDropDownStyle()) { CFX_RectF rtTextBk(m_rtClient); @@ -148,8 +149,7 @@ void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics, param.m_pWidget = this; param.m_iPart = CFWL_Part::Background; param.m_pGraphics = pGraphics; - if (pMatrix) - param.m_matrix.Concat(*pMatrix); + param.m_matrix.Concat(matrix); param.m_rtPart = rtTextBk; if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { @@ -173,14 +173,14 @@ void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics, theme_text.m_iPart = CFWL_Part::Caption; theme_text.m_dwStates = m_iBtnState; theme_text.m_pGraphics = pGraphics; - theme_text.m_matrix.Concat(*pMatrix); + theme_text.m_matrix.Concat(matrix); theme_text.m_rtPart = rtTextBk; theme_text.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ? CFWL_PartState_Selected : CFWL_PartState_Normal; theme_text.m_wsText = hItem ? hItem->GetText() : L""; - theme_text.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; - theme_text.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + theme_text.m_dwTTOStyles.single_line_ = true; + theme_text.m_iTTOAlign = FDE_TextAlignment::kCenterLeft; pTheme->DrawText(&theme_text); } } @@ -192,7 +192,7 @@ void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics, ? CFWL_PartState_Disabled : m_iBtnState; param.m_pGraphics = pGraphics; - param.m_matrix.Concat(*pMatrix); + param.m_matrix.Concat(matrix); param.m_rtPart = m_rtBtn; pTheme->DrawBackground(¶m); } @@ -208,7 +208,7 @@ void CFWL_ComboBox::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { m_pEdit->SetThemeProvider(pThemeProvider); } -CFX_WideString CFWL_ComboBox::GetTextByIndex(int32_t iIndex) const { +WideString CFWL_ComboBox::GetTextByIndex(int32_t iIndex) const { CFWL_ListItem* pItem = static_cast<CFWL_ListItem*>( m_pListBox->GetItem(m_pListBox.get(), iIndex)); return pItem ? pItem->GetText() : L""; @@ -219,7 +219,7 @@ void CFWL_ComboBox::SetCurSel(int32_t iSel) { bool bClearSel = iSel < 0 || iSel >= iCount; if (IsDropDownStyle() && m_pEdit) { if (bClearSel) { - m_pEdit->SetText(CFX_WideString()); + m_pEdit->SetText(WideString()); } else { CFWL_ListItem* hItem = m_pListBox->GetItem(this, iSel); m_pEdit->SetText(hItem ? hItem->GetText() : L""); @@ -245,7 +245,7 @@ void CFWL_ComboBox::RemoveStates(uint32_t dwStates) { CFWL_Widget::RemoveStates(dwStates); } -void CFWL_ComboBox::SetEditText(const CFX_WideString& wsText) { +void CFWL_ComboBox::SetEditText(const WideString& wsText) { if (!m_pEdit) return; @@ -253,7 +253,7 @@ void CFWL_ComboBox::SetEditText(const CFX_WideString& wsText) { m_pEdit->Update(); } -CFX_WideString CFWL_ComboBox::GetEditText() const { +WideString CFWL_ComboBox::GetEditText() const { if (m_pEdit) return m_pEdit->GetText(); if (!m_pListBox) @@ -287,7 +287,7 @@ void CFWL_ComboBox::EditModifyStylesEx(uint32_t dwStylesExAdded, m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); } -void CFWL_ComboBox::DrawStretchHandler(CFX_Graphics* pGraphics, +void CFWL_ComboBox::DrawStretchHandler(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground param; param.m_pGraphics = pGraphics; @@ -348,7 +348,7 @@ void CFWL_ComboBox::ShowDropList(bool bActivate) { } void CFWL_ComboBox::MatchEditText() { - CFX_WideString wsText = m_pEdit->GetText(); + WideString wsText = m_pEdit->GetText(); int32_t iMatch = m_pListBox->MatchItem(wsText); if (iMatch != m_iCurSel) { m_pListBox->ChangeSelected(iMatch); @@ -376,7 +376,7 @@ void CFWL_ComboBox::Layout() { if (!theme) return; - FX_FLOAT fBtn = theme->GetScrollBarWidth(); + float fBtn = theme->GetScrollBarWidth(); m_rtBtn = CFX_RectF(m_rtClient.right() - fBtn, m_rtClient.top, fBtn, m_rtClient.height); if (!IsDropDownStyle() || !m_pEdit) @@ -496,8 +496,8 @@ void CFWL_ComboBox::InitProxyForm() { // TODO(dsinclair): Does this leak? I don't see a delete, but I'm not sure // if the SetParent call is going to transfer ownership. - m_pComboBoxProxy = new CFWL_ComboBoxProxy(this, m_pOwnerApp, std::move(prop), - m_pListBox.get()); + m_pComboBoxProxy = new CFWL_ComboBoxProxy(this, m_pOwnerApp.Get(), + std::move(prop), m_pListBox.get()); m_pListBox->SetParent(m_pComboBoxProxy); } @@ -510,8 +510,8 @@ void CFWL_ComboBox::DisForm_InitComboList() { prop->m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; prop->m_dwStates = FWL_WGTSTATE_Invisible; prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; - m_pListBox = - pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this); + m_pListBox = pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp.Get(), + std::move(prop), this); } void CFWL_ComboBox::DisForm_InitComboEdit() { @@ -522,8 +522,8 @@ void CFWL_ComboBox::DisForm_InitComboEdit() { prop->m_pParent = this; prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; - m_pEdit = - pdfium::MakeUnique<CFWL_ComboEdit>(m_pOwnerApp, std::move(prop), this); + m_pEdit = pdfium::MakeUnique<CFWL_ComboEdit>(m_pOwnerApp.Get(), + std::move(prop), this); m_pEdit->SetOuter(this); } @@ -543,13 +543,13 @@ void CFWL_ComboBox::DisForm_ShowDropList(bool bActivate) { ResetListItemAlignment(); pComboList->ChangeSelected(m_iCurSel); - FX_FLOAT fItemHeight = pComboList->CalcItemHeight(); - FX_FLOAT fBorder = GetBorderSize(true); - FX_FLOAT fPopupMin = 0.0f; + float fItemHeight = pComboList->CalcItemHeight(); + float fBorder = GetBorderSize(true); + float fPopupMin = 0.0f; if (iItems > 3) fPopupMin = fItemHeight * 3 + fBorder * 2; - FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2; + float fPopupMax = fItemHeight * iItems + fBorder * 2; CFX_RectF rtList(m_rtClient.left, 0, m_pProperties->m_rtWidget.width, 0); GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList); @@ -614,10 +614,10 @@ FWL_WidgetHit CFWL_ComboBox::DisForm_HitTest(const CFX_PointF& point) { return FWL_WidgetHit::Unknown; } -void CFWL_ComboBox::DisForm_DrawWidget(CFX_Graphics* pGraphics, +void CFWL_ComboBox::DisForm_DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix) { IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; - CFX_Matrix mtOrg(1, 0, 0, 1, 0, 0); + CFX_Matrix mtOrg; if (pMatrix) mtOrg = *pMatrix; @@ -638,13 +638,13 @@ void CFWL_ComboBox::DisForm_DrawWidget(CFX_Graphics* pGraphics, CFX_RectF rtEdit = m_pEdit->GetWidgetRect(); CFX_Matrix mt(1, 0, 0, 1, rtEdit.left, rtEdit.top); mt.Concat(mtOrg); - m_pEdit->DrawWidget(pGraphics, &mt); + m_pEdit->DrawWidget(pGraphics, mt); } if (m_pListBox && DisForm_IsDropListVisible()) { CFX_RectF rtList = m_pListBox->GetWidgetRect(); CFX_Matrix mt(1, 0, 0, 1, rtList.left, rtList.top); mt.Concat(mtOrg); - m_pListBox->DrawWidget(pGraphics, &mt); + m_pListBox->DrawWidget(pGraphics, mt); } } @@ -666,8 +666,8 @@ void CFWL_ComboBox::DisForm_Layout() { if (!theme) return; - FX_FLOAT borderWidth = 1; - FX_FLOAT fBtn = theme->GetScrollBarWidth(); + float borderWidth = 1; + float fBtn = theme->GetScrollBarWidth(); if (!(GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) { m_rtBtn = CFX_RectF(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth, @@ -755,9 +755,9 @@ void CFWL_ComboBox::OnProcessEvent(CFWL_Event* pEvent) { } } -void CFWL_ComboBox::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_ComboBox::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_ComboBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { @@ -861,7 +861,7 @@ void CFWL_ComboBox::DoSubCtrlKey(CFWL_MessageKey* pMsg) { int32_t iCurSel = m_iCurSel; bool bDropDown = IsDropDownStyle(); if (bDropDown && m_pEdit) { - CFX_WideString wsText = m_pEdit->GetText(); + WideString wsText = m_pEdit->GetText(); iCurSel = m_pListBox->MatchItem(wsText); if (iCurSel >= 0) { CFWL_ListItem* hItem = m_pListBox->GetItem(this, iCurSel); @@ -990,7 +990,7 @@ void CFWL_ComboBox::DisForm_OnKey(CFWL_MessageKey* pMsg) { bool bMatchEqual = false; int32_t iCurSel = m_iCurSel; if (m_pEdit) { - CFX_WideString wsText = m_pEdit->GetText(); + WideString wsText = m_pEdit->GetText(); iCurSel = pComboList->MatchItem(wsText); if (iCurSel >= 0) { CFWL_ListItem* item = m_pListBox->GetSelItem(iCurSel); diff --git a/xfa/fwl/cfwl_combobox.h b/xfa/fwl/cfwl_combobox.h index 168e203162df347e489e1fcc5ba1734ffe2eee85..a9dc63537307b9d5f92bd9eb1118efe342bb7c81 100644 --- a/xfa/fwl/cfwl_combobox.h +++ b/xfa/fwl/cfwl_combobox.h @@ -14,7 +14,7 @@ #include "xfa/fwl/cfwl_combolist.h" #include "xfa/fwl/cfwl_form.h" #include "xfa/fwl/cfwl_listbox.h" -#include "xfa/fxgraphics/cfx_graphics.h" +#include "xfa/fxgraphics/cxfa_graphics.h" class CFWL_WidgetProperties; class CFWL_ComboBox; @@ -52,23 +52,23 @@ class CFWL_ComboBox : public CFWL_Widget { void RemoveStates(uint32_t dwStates) override; void Update() override; FWL_WidgetHit HitTest(const CFX_PointF& point) override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override; void OnProcessMessage(CFWL_Message* pMessage) override; void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; - CFX_WideString GetTextByIndex(int32_t iIndex) const; + WideString GetTextByIndex(int32_t iIndex) const; int32_t GetCurSel() const { return m_iCurSel; } void SetCurSel(int32_t iSel); - void AddString(const CFX_WideStringC& wsText); + void AddString(const WideStringView& wsText); void RemoveAt(int32_t iIndex); void RemoveAll(); - void SetEditText(const CFX_WideString& wsText); - CFX_WideString GetEditText() const; + void SetEditText(const WideString& wsText); + WideString GetEditText() const; void OpenDropDownList(bool bActivate); @@ -76,26 +76,24 @@ class CFWL_ComboBox : public CFWL_Widget { bool EditCanRedo() const { return m_pEdit->CanRedo(); } bool EditUndo() { return m_pEdit->Undo(); } bool EditRedo() { return m_pEdit->Redo(); } - bool EditCanCopy() const { return m_pEdit->CountSelRanges() > 0; } + bool EditCanCopy() const { return m_pEdit->HasSelection(); } bool EditCanCut() const { if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) return false; return EditCanCopy(); } bool EditCanSelectAll() const { return m_pEdit->GetTextLength() > 0; } - bool EditCopy(CFX_WideString& wsCopy) const { return m_pEdit->Copy(wsCopy); } - bool EditCut(CFX_WideString& wsCut) { return m_pEdit->Cut(wsCut); } - bool EditPaste(const CFX_WideString& wsPaste) { - return m_pEdit->Paste(wsPaste); - } - void EditSelectAll() { m_pEdit->AddSelRange(0); } + Optional<WideString> EditCopy() const { return m_pEdit->Copy(); } + Optional<WideString> EditCut() { return m_pEdit->Cut(); } + bool EditPaste(const WideString& wsPaste) { return m_pEdit->Paste(wsPaste); } + void EditSelectAll() { m_pEdit->SelectAll(); } void EditDelete() { m_pEdit->ClearText(); } - void EditDeSelect() { m_pEdit->ClearSelections(); } + void EditDeSelect() { m_pEdit->ClearSelection(); } CFX_RectF GetBBox() const; void EditModifyStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved); - void DrawStretchHandler(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix); + void DrawStretchHandler(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix); bool IsDropListVisible() const { return m_pComboBoxProxy && !(m_pComboBoxProxy->GetStates() & FWL_WGTSTATE_Invisible); @@ -136,7 +134,7 @@ class CFWL_ComboBox : public CFWL_Widget { uint32_t dwStylesExRemoved); void DisForm_Update(); FWL_WidgetHit DisForm_HitTest(const CFX_PointF& point); - void DisForm_DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix); + void DisForm_DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix); CFX_RectF DisForm_GetBBox() const; void DisForm_Layout(); void DisForm_OnProcessMessage(CFWL_Message* pMessage); diff --git a/xfa/fwl/cfwl_comboboxproxy.cpp b/xfa/fwl/cfwl_comboboxproxy.cpp index 0e2779b5c9c9d5d1f54e5b9d096d39d3b14cc824..d1db1c01a83c9c662a6d893edb79f8cc1ab43b2f 100644 --- a/xfa/fwl/cfwl_comboboxproxy.cpp +++ b/xfa/fwl/cfwl_comboboxproxy.cpp @@ -58,9 +58,9 @@ void CFWL_ComboBoxProxy::OnProcessMessage(CFWL_Message* pMessage) { CFWL_Widget::OnProcessMessage(pMessage); } -void CFWL_ComboBoxProxy::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - m_pComboBox->DrawStretchHandler(pGraphics, pMatrix); +void CFWL_ComboBoxProxy::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + m_pComboBox->DrawStretchHandler(pGraphics, &matrix); } void CFWL_ComboBoxProxy::OnLButtonDown(CFWL_Message* pMessage) { diff --git a/xfa/fwl/cfwl_comboboxproxy.h b/xfa/fwl/cfwl_comboboxproxy.h index 4be14b9e6574b49ae37e3923ffe6d3bca45bbaa4..bb217078519952963adc3efaa6258a5546e155f6 100644 --- a/xfa/fwl/cfwl_comboboxproxy.h +++ b/xfa/fwl/cfwl_comboboxproxy.h @@ -23,8 +23,8 @@ class CFWL_ComboBoxProxy : public CFWL_FormProxy { // CFWL_FormProxy void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; void Reset() { m_bLButtonUpSelf = false; } diff --git a/xfa/fwl/cfwl_comboedit.cpp b/xfa/fwl/cfwl_comboedit.cpp index 22ad6bff32642b8f9de04a6f9c46c7038abaf567..4fa127745e8472a6745ffe0ab967bcf6cbd632ca 100644 --- a/xfa/fwl/cfwl_comboedit.cpp +++ b/xfa/fwl/cfwl_comboedit.cpp @@ -9,7 +9,7 @@ #include <memory> #include <utility> -#include "xfa/fde/cfde_txtedtengine.h" +#include "xfa/fde/cfde_texteditengine.h" #include "xfa/fwl/cfwl_combobox.h" #include "xfa/fwl/cfwl_messagemouse.h" @@ -22,14 +22,13 @@ CFWL_ComboEdit::CFWL_ComboEdit( } void CFWL_ComboEdit::ClearSelected() { - ClearSelections(); + ClearSelection(); RepaintRect(GetRTClient()); } void CFWL_ComboEdit::SetSelected() { FlagFocus(true); - GetTxtEdtEngine()->MoveCaretPos(MC_End); - AddSelRange(0); + SelectAll(); } void CFWL_ComboEdit::FlagFocus(bool bSet) { diff --git a/xfa/fwl/cfwl_combolist.cpp b/xfa/fwl/cfwl_combolist.cpp index 5b700a90deabfb0be33766e5f5ceee9bb4629b21..1180acf5c886853ca2e12378527d64900da2c72d 100644 --- a/xfa/fwl/cfwl_combolist.cpp +++ b/xfa/fwl/cfwl_combolist.cpp @@ -25,16 +25,16 @@ CFWL_ComboList::CFWL_ComboList( ASSERT(pOuter); } -int32_t CFWL_ComboList::MatchItem(const CFX_WideString& wsMatch) { +int32_t CFWL_ComboList::MatchItem(const WideString& wsMatch) { if (wsMatch.IsEmpty()) return -1; int32_t iCount = CountItems(this); for (int32_t i = 0; i < iCount; i++) { CFWL_ListItem* hItem = GetItem(this, i); - CFX_WideString wsText = hItem ? hItem->GetText() : L""; - FX_STRSIZE pos = wsText.Find(wsMatch.c_str()); - if (!pos) + WideString wsText = hItem ? hItem->GetText() : L""; + auto pos = wsText.Find(wsMatch.c_str()); + if (pos.has_value() && pos.value() == 0) return i; } return -1; diff --git a/xfa/fwl/cfwl_combolist.h b/xfa/fwl/cfwl_combolist.h index b7ba6b578034637b1b75f6ad8aaec0b7dc14a820..a4d513559e66f10f7279c65999ff027adc416099 100644 --- a/xfa/fwl/cfwl_combolist.h +++ b/xfa/fwl/cfwl_combolist.h @@ -22,7 +22,7 @@ class CFWL_ComboList : public CFWL_ListBox { // CFWL_ListBox. void OnProcessMessage(CFWL_Message* pMessage) override; - int32_t MatchItem(const CFX_WideString& wsMatch); + int32_t MatchItem(const WideString& wsMatch); void ChangeSelected(int32_t iSel); diff --git a/xfa/fwl/cfwl_datetimepicker.cpp b/xfa/fwl/cfwl_datetimepicker.cpp index a6ba65a3b212aad497aa1f7fab8486fdc282851a..f3da4543540685834a248347c32272f80f02d264 100644 --- a/xfa/fwl/cfwl_datetimepicker.cpp +++ b/xfa/fwl/cfwl_datetimepicker.cpp @@ -16,7 +16,6 @@ #include "xfa/fwl/cfwl_messagemouse.h" #include "xfa/fwl/cfwl_messagesetfocus.h" #include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_spinbutton.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/ifwl_themeprovider.h" @@ -40,8 +39,8 @@ CFWL_DateTimePicker::CFWL_DateTimePicker(const CFWL_App* app) monthProp->m_dwStates = FWL_WGTSTATE_Invisible; monthProp->m_pParent = this; monthProp->m_pThemeProvider = m_pProperties->m_pThemeProvider; - m_pMonthCal.reset( - new CFWL_MonthCalendar(m_pOwnerApp, std::move(monthProp), this)); + m_pMonthCal = pdfium::MakeUnique<CFWL_MonthCalendar>( + m_pOwnerApp.Get(), std::move(monthProp), this); m_pMonthCal->SetWidgetRect( CFX_RectF(0, 0, m_pMonthCal->GetAutosizedWidgetRect().Size())); @@ -50,7 +49,7 @@ CFWL_DateTimePicker::CFWL_DateTimePicker(const CFWL_App* app) editProp->m_pParent = this; editProp->m_pThemeProvider = m_pProperties->m_pThemeProvider; - m_pEdit = pdfium::MakeUnique<CFWL_DateTimeEdit>(m_pOwnerApp, + m_pEdit = pdfium::MakeUnique<CFWL_DateTimeEdit>(m_pOwnerApp.Get(), std::move(editProp), this); RegisterEventTarget(m_pMonthCal.get()); RegisterEventTarget(m_pEdit.get()); @@ -81,7 +80,7 @@ void CFWL_DateTimePicker::Update() { if (!theme) return; - FX_FLOAT fBtn = theme->GetScrollBarWidth(); + float fBtn = theme->GetScrollBarWidth(); m_rtBtn = CFX_RectF(m_rtClient.right() - fBtn, m_rtClient.top, fBtn - 1, m_rtClient.height - 1); @@ -114,8 +113,8 @@ FWL_WidgetHit CFWL_DateTimePicker::HitTest(const CFX_PointF& point) { return FWL_WidgetHit::Unknown; } -void CFWL_DateTimePicker::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_DateTimePicker::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -123,11 +122,11 @@ void CFWL_DateTimePicker::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); if (!m_rtBtn.IsEmpty()) - DrawDropDownButton(pGraphics, pTheme, pMatrix); + DrawDropDownButton(pGraphics, pTheme, &matrix); if (m_pWidgetMgr->IsFormDisabled()) { - DisForm_DrawWidget(pGraphics, pMatrix); + DisForm_DrawWidget(pGraphics, &matrix); return; } } @@ -161,7 +160,7 @@ void CFWL_DateTimePicker::SetCurSel(int32_t iYear, m_pMonthCal->SetSelect(iYear, iMonth, iDay); } -void CFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) { +void CFWL_DateTimePicker::SetEditText(const WideString& wsText) { if (!m_pEdit) return; @@ -172,7 +171,7 @@ void CFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) { DispatchEvent(&ev); } -CFX_WideString CFWL_DateTimePicker::GetEditText() const { +WideString CFWL_DateTimePicker::GetEditText() const { return m_pEdit ? m_pEdit->GetText() : L""; } @@ -195,7 +194,7 @@ void CFWL_DateTimePicker::ModifyEditStylesEx(uint32_t dwStylesExAdded, m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); } -void CFWL_DateTimePicker::DrawDropDownButton(CFX_Graphics* pGraphics, +void CFWL_DateTimePicker::DrawDropDownButton(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground param; @@ -209,17 +208,20 @@ void CFWL_DateTimePicker::DrawDropDownButton(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶m); } -void CFWL_DateTimePicker::FormatDateString(int32_t iYear, - int32_t iMonth, - int32_t iDay, - CFX_WideString& wsText) { +WideString CFWL_DateTimePicker::FormatDateString(int32_t iYear, + int32_t iMonth, + int32_t iDay) { if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat) == FWL_STYLEEXT_DTP_ShortDateFormat) { - wsText.Format(L"%d-%d-%d", iYear, iMonth, iDay); - } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) == - FWL_STYLEEXT_DTP_LongDateFormat) { - wsText.Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay); + return WideString::Format(L"%d-%d-%d", iYear, iMonth, iDay); } + + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) == + FWL_STYLEEXT_DTP_LongDateFormat) { + return WideString::Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay); + } + + return WideString(); } void CFWL_DateTimePicker::ShowMonthCalendar(bool bActivate) { @@ -308,8 +310,7 @@ void CFWL_DateTimePicker::ProcessSelChanged(int32_t iYear, m_iMonth = iMonth; m_iDay = iDay; - CFX_WideString wsText; - FormatDateString(m_iYear, m_iMonth, m_iDay, wsText); + WideString wsText = FormatDateString(m_iYear, m_iMonth, m_iDay); m_pEdit->SetText(wsText); m_pEdit->Update(); RepaintRect(m_rtClient); @@ -332,8 +333,8 @@ void CFWL_DateTimePicker::InitProxyForm() { prop->m_dwStates = FWL_WGTSTATE_Invisible; prop->m_pOwner = this; - m_pForm = pdfium::MakeUnique<CFWL_FormProxy>(m_pOwnerApp, std::move(prop), - m_pMonthCal.get()); + m_pForm = pdfium::MakeUnique<CFWL_FormProxy>( + m_pOwnerApp.Get(), std::move(prop), m_pMonthCal.get()); m_pMonthCal->SetParent(m_pForm.get()); } @@ -349,8 +350,8 @@ void CFWL_DateTimePicker::DisForm_ShowMonthCalendar(bool bActivate) { if (bActivate) { CFX_RectF rtMonthCal = m_pMonthCal->GetAutosizedWidgetRect(); - FX_FLOAT fPopupMin = rtMonthCal.height; - FX_FLOAT fPopupMax = rtMonthCal.height; + float fPopupMin = rtMonthCal.height; + float fPopupMax = rtMonthCal.height; CFX_RectF rtAnchor(m_pProperties->m_rtWidget); rtAnchor.width = rtMonthCal.width; rtMonthCal.left = m_rtClient.left; @@ -443,7 +444,7 @@ CFX_RectF CFWL_DateTimePicker::DisForm_GetBBox() const { return rect; } -void CFWL_DateTimePicker::DisForm_DrawWidget(CFX_Graphics* pGraphics, +void CFWL_DateTimePicker::DisForm_DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix) { if (!pGraphics) return; @@ -453,7 +454,7 @@ void CFWL_DateTimePicker::DisForm_DrawWidget(CFX_Graphics* pGraphics, CFX_Matrix mt(1, 0, 0, 1, rtEdit.left, rtEdit.top); if (pMatrix) mt.Concat(*pMatrix); - m_pEdit->DrawWidget(pGraphics, &mt); + m_pEdit->DrawWidget(pGraphics, mt); } if (!IsMonthCalendarVisible()) return; @@ -462,7 +463,7 @@ void CFWL_DateTimePicker::DisForm_DrawWidget(CFX_Graphics* pGraphics, CFX_Matrix mt(1, 0, 0, 1, rtMonth.left, rtMonth.top); if (pMatrix) mt.Concat(*pMatrix); - m_pMonthCal->DrawWidget(pGraphics, &mt); + m_pMonthCal->DrawWidget(pGraphics, mt); } void CFWL_DateTimePicker::OnProcessMessage(CFWL_Message* pMessage) { @@ -510,9 +511,9 @@ void CFWL_DateTimePicker::OnProcessMessage(CFWL_Message* pMessage) { CFWL_Widget::OnProcessMessage(pMessage); } -void CFWL_DateTimePicker::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_DateTimePicker::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_DateTimePicker::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { diff --git a/xfa/fwl/cfwl_datetimepicker.h b/xfa/fwl/cfwl_datetimepicker.h index 2935ee8b1c808b937ec7a26d42d8fb7546648296..6d536016ddb2db7d531c91377504c823167fd55e 100644 --- a/xfa/fwl/cfwl_datetimepicker.h +++ b/xfa/fwl/cfwl_datetimepicker.h @@ -8,6 +8,7 @@ #define XFA_FWL_CFWL_DATETIMEPICKER_H_ #include <memory> +#include <utility> #include "xfa/fwl/cfwl_datetimeedit.h" #include "xfa/fwl/cfwl_event.h" @@ -39,21 +40,22 @@ class CFWL_DateTimePicker : public CFWL_Widget { FWL_Type GetClassID() const override; void Update() override; FWL_WidgetHit HitTest(const CFX_PointF& point) override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void SetThemeProvider(IFWL_ThemeProvider* pTP) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; void GetCurSel(int32_t& iYear, int32_t& iMonth, int32_t& iDay); void SetCurSel(int32_t iYear, int32_t iMonth, int32_t iDay); - void SetEditText(const CFX_WideString& wsText); - CFX_WideString GetEditText() const; + void SetEditText(const WideString& wsText); + WideString GetEditText() const; - int32_t CountSelRanges() const { return m_pEdit->CountSelRanges(); } - int32_t GetSelRange(int32_t nIndex, int32_t* nStart) const { - return m_pEdit->GetSelRange(nIndex, nStart); + bool HasSelection() const { return m_pEdit->HasSelection(); } + // Returns <start, count> of the selection. + std::pair<size_t, size_t> GetSelection() const { + return m_pEdit->GetSelection(); } CFX_RectF GetBBox() const; @@ -67,13 +69,10 @@ class CFWL_DateTimePicker : public CFWL_Widget { CFWL_FormProxy* GetFormProxy() const { return m_pForm.get(); } private: - void DrawDropDownButton(CFX_Graphics* pGraphics, + void DrawDropDownButton(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void FormatDateString(int32_t iYear, - int32_t iMonth, - int32_t iDay, - CFX_WideString& wsText); + WideString FormatDateString(int32_t iYear, int32_t iMonth, int32_t iDay); void ResetEditAlignment(); void InitProxyForm(); void OnFocusChanged(CFWL_Message* pMsg, bool bSet); @@ -88,7 +87,7 @@ class CFWL_DateTimePicker : public CFWL_Widget { bool DisForm_IsNeedShowButton() const; void DisForm_Update(); CFX_RectF DisForm_GetBBox() const; - void DisForm_DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix); + void DisForm_DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix); void DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet); CFX_RectF m_rtBtn; @@ -101,7 +100,7 @@ class CFWL_DateTimePicker : public CFWL_Widget { std::unique_ptr<CFWL_DateTimeEdit> m_pEdit; std::unique_ptr<CFWL_MonthCalendar> m_pMonthCal; std::unique_ptr<CFWL_FormProxy> m_pForm; - FX_FLOAT m_fBtn; + float m_fBtn; }; #endif // XFA_FWL_CFWL_DATETIMEPICKER_H_ diff --git a/xfa/fwl/cfwl_edit.cpp b/xfa/fwl/cfwl_edit.cpp index d36e28ab56d62395d90121cff2c0505724982c48..960ec9967a4b4ceacea3422b51e234e2cd208fa7 100644 --- a/xfa/fwl/cfwl_edit.cpp +++ b/xfa/fwl/cfwl_edit.cpp @@ -13,10 +13,8 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/fde_gedevice.h" -#include "xfa/fde/fde_render.h" -#include "xfa/fde/ifde_txtedtpage.h" +#include "xfa/fde/cfde_texteditengine.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fgas/font/cfgas_gefont.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_caret.h" @@ -30,28 +28,35 @@ #include "xfa/fwl/cfwl_themepart.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fwl/theme/cfwl_utils.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxgraphics/cxfa_gepath.h" namespace { const int kEditMargin = 3; -bool FX_EDIT_ISLATINWORD(FX_WCHAR c) { +#if (_FX_OS_ == _FX_OS_MACOSX_) +constexpr int kEditingModifier = FWL_KEYFLAG_Command; +#else +constexpr int kEditingModifier = FWL_KEYFLAG_Ctrl; +#endif + +bool FxEditIsLatinWord(wchar_t c) { return c == 0x2D || (c <= 0x005A && c >= 0x0041) || (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) || c == 0x0027; } -void AddSquigglyPath(CFX_Path* pPathData, - FX_FLOAT fStartX, - FX_FLOAT fEndX, - FX_FLOAT fY, - FX_FLOAT fStep) { +void AddSquigglyPath(CXFA_GEPath* pPathData, + float fStartX, + float fEndX, + float fY, + float fStep) { pPathData->MoveTo(CFX_PointF(fStartX, fY)); int i = 1; - for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i) + for (float fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i) pPathData->LineTo(CFX_PointF(fx, fY + (i & 1) * fStep)); } @@ -65,24 +70,22 @@ CFWL_Edit::CFWL_Edit(const CFWL_App* app, m_fScrollOffsetX(0.0f), m_fScrollOffsetY(0.0f), m_bLButtonDown(false), - m_nSelStart(0), + m_CursorPosition(0), m_nLimit(-1), m_fFontSize(0), m_bSetRange(false), - m_iMax(0xFFFFFFF), - m_iCurRecord(-1), - m_iMaxRecord(128) { + m_iMax(0xFFFFFFF) { m_rtClient.Reset(); m_rtEngine.Reset(); m_rtStatic.Reset(); InitCaret(); + m_EdtEngine.SetDelegate(this); } CFWL_Edit::~CFWL_Edit() { if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) HideCaret(nullptr); - ClearRecord(); } FWL_Type CFWL_Edit::GetClassID() const { @@ -108,12 +111,14 @@ CFX_RectF CFWL_Edit::GetWidgetRect() { CFX_RectF CFWL_Edit::GetAutosizedWidgetRect() { CFX_RectF rect; - if (m_EdtEngine.GetTextLength() > 0) { - CFX_SizeF sz = CalcTextSize( - m_EdtEngine.GetText(0, -1), m_pProperties->m_pThemeProvider, + + if (m_EdtEngine.GetLength() > 0) { + CFX_SizeF size = CalcTextSize( + m_EdtEngine.GetText(), m_pProperties->m_pThemeProvider, !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine)); - rect = CFX_RectF(0, 0, sz); + rect = CFX_RectF(0, 0, size); } + InflateWidgetRect(rect); return rect; } @@ -158,52 +163,44 @@ FWL_WidgetHit CFWL_Edit::HitTest(const CFX_PointF& point) { return FWL_WidgetHit::Unknown; } -void CFWL_Edit::AddSpellCheckObj(CFX_Path& PathData, +void CFWL_Edit::AddSpellCheckObj(CXFA_GEPath& PathData, int32_t nStart, int32_t nCount, - FX_FLOAT fOffSetX, - FX_FLOAT fOffSetY) { - FX_FLOAT fStartX = 0.0f; - FX_FLOAT fEndX = 0.0f; - FX_FLOAT fY = 0.0f; - FX_FLOAT fStep = 0.0f; - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams(); - FX_FLOAT fAsent = static_cast<FX_FLOAT>(txtEdtParams->pFont->GetAscent()) * - txtEdtParams->fFontSize / 1000; - - std::vector<CFX_RectF> rectArray; - pPage->CalcRangeRectArray(nStart, nCount, &rectArray); - - for (const auto& rectText : rectArray) { - fY = rectText.top + fAsent + fOffSetY; - fStep = txtEdtParams->fFontSize / 16.0f; - fStartX = rectText.left + fOffSetX; - fEndX = fStartX + rectText.Width(); + float fOffSetX, + float fOffSetY) { + float fStep = m_EdtEngine.GetFontSize() / 16.0f; + float font_ascent = m_EdtEngine.GetFontAscent(); + + std::vector<CFX_RectF> rects = + m_EdtEngine.GetCharacterRectsInRange(nStart, nCount); + for (const auto& rect : rects) { + float fY = rect.top + font_ascent + fOffSetY; + float fStartX = rect.left + fOffSetX; + float fEndX = fStartX + rect.Width(); + AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep); } } -void CFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics, +void CFWL_Edit::DrawSpellCheck(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix) { pGraphics->SaveGraphState(); if (pMatrix) - pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix)); + pGraphics->ConcatMatrix(pMatrix); - CFX_Color crLine(0xFFFF0000); CFWL_EventCheckWord checkWordEvent(this); - CFX_ByteString sLatinWord; - CFX_Path pathSpell; + ByteString sLatinWord; + CXFA_GEPath pathSpell; int32_t nStart = 0; - FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; - FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; - CFX_WideString wsSpell = GetText(); + float fOffSetX = m_rtEngine.left - m_fScrollOffsetX; + float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + WideString wsSpell = GetText(); int32_t nContentLen = wsSpell.GetLength(); for (int i = 0; i < nContentLen; i++) { - if (FX_EDIT_ISLATINWORD(wsSpell[i])) { + if (FxEditIsLatinWord(wsSpell[i])) { if (sLatinWord.IsEmpty()) nStart = i; - sLatinWord += (FX_CHAR)wsSpell[i]; + sLatinWord += (char)wsSpell[i]; continue; } checkWordEvent.bsWord = sLatinWord; @@ -229,18 +226,18 @@ void CFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics, CFX_RectF rtClip = m_rtEngine; CFX_Matrix mt(1, 0, 0, 1, fOffSetX, fOffSetY); if (pMatrix) { - pMatrix->TransformRect(rtClip); + rtClip = pMatrix->TransformRect(rtClip); mt.Concat(*pMatrix); } pGraphics->SetClipRect(rtClip); - pGraphics->SetStrokeColor(&crLine); + pGraphics->SetStrokeColor(CXFA_GEColor(0xFFFF0000)); pGraphics->SetLineWidth(0); pGraphics->StrokePath(&pathSpell, nullptr); } pGraphics->RestoreGraphState(); } -void CFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { +void CFWL_Edit::DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -250,15 +247,15 @@ void CFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; if (!m_pWidgetMgr->IsFormDisabled()) - DrawTextBk(pGraphics, pTheme, pMatrix); - DrawContent(pGraphics, pTheme, pMatrix); + DrawTextBk(pGraphics, pTheme, &matrix); + DrawContent(pGraphics, pTheme, &matrix); if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) { - DrawSpellCheck(pGraphics, pMatrix); + DrawSpellCheck(pGraphics, &matrix); } if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); } void CFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { @@ -273,36 +270,37 @@ void CFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { m_pProperties->m_pThemeProvider = pThemeProvider; } -void CFWL_Edit::SetText(const CFX_WideString& wsText) { - m_EdtEngine.SetText(wsText); +void CFWL_Edit::SetText(const WideString& wsText) { + m_EdtEngine.Clear(); + m_EdtEngine.Insert(0, wsText); } int32_t CFWL_Edit::GetTextLength() const { - return m_EdtEngine.GetTextLength(); + return m_EdtEngine.GetLength(); } -CFX_WideString CFWL_Edit::GetText() const { - return m_EdtEngine.GetText(0, -1); +WideString CFWL_Edit::GetText() const { + return m_EdtEngine.GetText(); } void CFWL_Edit::ClearText() { - m_EdtEngine.ClearText(); + m_EdtEngine.Clear(); } -void CFWL_Edit::AddSelRange(int32_t nStart) { - m_EdtEngine.AddSelRange(nStart, -1); +void CFWL_Edit::SelectAll() { + m_EdtEngine.SelectAll(); } -int32_t CFWL_Edit::CountSelRanges() const { - return m_EdtEngine.CountSelRanges(); +bool CFWL_Edit::HasSelection() const { + return m_EdtEngine.HasSelection(); } -int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t* nStart) const { - return m_EdtEngine.GetSelRange(nIndex, nStart); +std::pair<size_t, size_t> CFWL_Edit::GetSelection() const { + return m_EdtEngine.GetSelection(); } -void CFWL_Edit::ClearSelections() { - m_EdtEngine.ClearSelection(); +void CFWL_Edit::ClearSelection() { + return m_EdtEngine.ClearSelection(); } int32_t CFWL_Edit::GetLimit() const { @@ -311,89 +309,67 @@ int32_t CFWL_Edit::GetLimit() const { void CFWL_Edit::SetLimit(int32_t nLimit) { m_nLimit = nLimit; - m_EdtEngine.SetLimit(nLimit); + + if (m_nLimit > 0) { + m_EdtEngine.SetHasCharacterLimit(true); + m_EdtEngine.SetCharacterLimit(nLimit); + } else { + m_EdtEngine.SetHasCharacterLimit(false); + } } -void CFWL_Edit::SetAliasChar(FX_WCHAR wAlias) { +void CFWL_Edit::SetAliasChar(wchar_t wAlias) { m_EdtEngine.SetAliasChar(wAlias); } -bool CFWL_Edit::Copy(CFX_WideString& wsCopy) { - int32_t nCount = m_EdtEngine.CountSelRanges(); - if (nCount == 0) - return false; +Optional<WideString> CFWL_Edit::Copy() { + if (!m_EdtEngine.HasSelection()) + return {}; - wsCopy.clear(); - int32_t nStart; - int32_t nLength; - for (int32_t i = 0; i < nCount; i++) { - nLength = m_EdtEngine.GetSelRange(i, &nStart); - wsCopy += m_EdtEngine.GetText(nStart, nLength); - } - return true; + return {m_EdtEngine.GetSelectedText()}; } -bool CFWL_Edit::Cut(CFX_WideString& wsCut) { - int32_t nCount = m_EdtEngine.CountSelRanges(); - if (nCount == 0) - return false; +Optional<WideString> CFWL_Edit::Cut() { + if (!m_EdtEngine.HasSelection()) + return {}; - wsCut.clear(); - CFX_WideString wsTemp; - int32_t nStart, nLength; - for (int32_t i = 0; i < nCount; i++) { - nLength = m_EdtEngine.GetSelRange(i, &nStart); - wsTemp = m_EdtEngine.GetText(nStart, nLength); - wsCut += wsTemp; - wsTemp.clear(); - } - m_EdtEngine.Delete(0); - return true; -} - -bool CFWL_Edit::Paste(const CFX_WideString& wsPaste) { - int32_t nCaret = m_EdtEngine.GetCaretPos(); - int32_t iError = - m_EdtEngine.Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength()); - if (iError < 0) { - ProcessInsertError(iError); - return false; - } - return true; + return {m_EdtEngine.DeleteSelectedText()}; } -bool CFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) { - return m_EdtEngine.Redo(pRecord); -} +bool CFWL_Edit::Paste(const WideString& wsPaste) { + if (m_EdtEngine.HasSelection()) + m_EdtEngine.ReplaceSelectedText(wsPaste); + else + m_EdtEngine.Insert(m_CursorPosition, wsPaste); -bool CFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) { - return m_EdtEngine.Undo(pRecord); + return true; } bool CFWL_Edit::Undo() { - if (!CanUndo()) - return false; - return Undo(m_DoRecords[m_iCurRecord--].get()); + return CanUndo() ? m_EdtEngine.Undo() : false; } bool CFWL_Edit::Redo() { - if (!CanRedo()) - return false; - return Redo(m_DoRecords[++m_iCurRecord].get()); + return CanRedo() ? m_EdtEngine.Redo() : false; } bool CFWL_Edit::CanUndo() { - return m_iCurRecord >= 0; + return m_EdtEngine.CanUndo(); } bool CFWL_Edit::CanRedo() { - return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; + return m_EdtEngine.CanRedo(); } void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) { m_pOuter = pOuter; } +void CFWL_Edit::NotifyTextFull() { + CFWL_Event evt(CFWL_Event::Type::TextFull, this); + DispatchEvent(&evt); +} + void CFWL_Edit::OnCaretChanged() { if (m_rtEngine.IsEmpty()) return; @@ -418,12 +394,12 @@ void CFWL_Edit::OnCaretChanged() { } } -void CFWL_Edit::OnTextChanged(const FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) { +void CFWL_Edit::OnTextChanged(const WideString& prevText) { if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask) UpdateVAlignment(); CFWL_EventTextChanged event(this); - event.wsPrevText = ChangeInfo.wsPrevText; + event.wsPrevText = prevText; DispatchEvent(&event); LayoutScrollBar(); @@ -434,29 +410,7 @@ void CFWL_Edit::OnSelChanged() { RepaintRect(GetClientRect()); } -bool CFWL_Edit::OnPageLoad(int32_t nPageIndex) { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex); - if (!pPage) - return false; - - pPage->LoadPage(nullptr, nullptr); - return true; -} - -bool CFWL_Edit::OnPageUnload(int32_t nPageIndex) { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex); - if (!pPage) - return false; - - pPage->UnloadPage(nullptr); - return true; -} - -void CFWL_Edit::OnAddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord) { - AddDoRecord(std::move(pRecord)); -} - -bool CFWL_Edit::OnValidate(const CFX_WideString& wsText) { +bool CFWL_Edit::OnValidate(const WideString& wsText) { CFWL_Widget* pDst = GetOuter(); if (!pDst) pDst = this; @@ -468,11 +422,11 @@ bool CFWL_Edit::OnValidate(const CFX_WideString& wsText) { return event.bValidate; } -void CFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) { +void CFWL_Edit::SetScrollOffset(float fScrollOffset) { m_fScrollOffsetY = fScrollOffset; } -void CFWL_Edit::DrawTextBk(CFX_Graphics* pGraphics, +void CFWL_Edit::DrawTextBk(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground param; @@ -504,49 +458,34 @@ void CFWL_Edit::DrawTextBk(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶m); } -void CFWL_Edit::DrawContent(CFX_Graphics* pGraphics, +void CFWL_Edit::DrawContent(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - pGraphics->SaveGraphState(); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) pGraphics->SaveGraphState(); CFX_RectF rtClip = m_rtEngine; - FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; - FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + float fOffSetX = m_rtEngine.left - m_fScrollOffsetX; + float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + CFX_Matrix mt(1, 0, 0, 1, fOffSetX, fOffSetY); if (pMatrix) { - pMatrix->TransformRect(rtClip); + rtClip = pMatrix->TransformRect(rtClip); mt.Concat(*pMatrix); } bool bShowSel = !!(m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); - int32_t nSelCount = m_EdtEngine.CountSelRanges(); - if (bShowSel && nSelCount > 0) { - int32_t nPageCharStart = pPage->GetCharStart(); - int32_t nPageCharCount = pPage->GetCharCount(); - int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1; - int32_t nCharCount; - int32_t nCharStart; - std::vector<CFX_RectF> rectArr; - for (int32_t i = 0; i < nSelCount; i++) { - nCharCount = m_EdtEngine.GetSelRange(i, &nCharStart); - int32_t nCharEnd = nCharStart + nCharCount - 1; - if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) - continue; - - int32_t nBgn = std::max(nCharStart, nPageCharStart); - int32_t nEnd = std::min(nCharEnd, nPageCharEnd); - pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1, - &rectArr); - } - - CFX_Path path; - for (auto& rect : rectArr) { + if (bShowSel && m_EdtEngine.HasSelection()) { + size_t sel_start; + size_t count; + std::tie(sel_start, count) = m_EdtEngine.GetSelection(); + std::vector<CFX_RectF> rects = + m_EdtEngine.GetCharacterRectsInRange(sel_start, count); + + CXFA_GEPath path; + for (auto& rect : rects) { rect.left += fOffSetX; rect.top += fOffSetY; path.AddRectangle(rect.left, rect.top, rect.width, rect.height); @@ -566,19 +505,15 @@ void CFWL_Edit::DrawContent(CFX_Graphics* pGraphics, if (!pRenderDev) return; - std::unique_ptr<CFDE_RenderDevice> pRenderDevice( - new CFDE_RenderDevice(pRenderDev, false)); - std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext); - pRenderDevice->SetClipRect(rtClip); - pRenderContext->StartRender(pRenderDevice.get(), pPage, mt); - pRenderContext->DoRender(nullptr); + RenderText(pRenderDev, rtClip, mt); if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { pGraphics->RestoreGraphState(); - CFX_Path path; + + CXFA_GEPath path; int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1; - FX_FLOAT fStep = m_rtEngine.width / iLimit; - FX_FLOAT fLeft = m_rtEngine.left + 1; + float fStep = m_rtEngine.width / iLimit; + float fLeft = m_rtEngine.left + 1; for (int32_t i = 1; i < iLimit; i++) { fLeft += fStep; path.AddLine(CFX_PointF(fLeft, m_rtClient.top), @@ -596,38 +531,68 @@ void CFWL_Edit::DrawContent(CFX_Graphics* pGraphics, pGraphics->RestoreGraphState(); } +void CFWL_Edit::RenderText(CFX_RenderDevice* pRenderDev, + const CFX_RectF& clipRect, + const CFX_Matrix& mt) { + ASSERT(pRenderDev); + + RetainPtr<CFGAS_GEFont> font = m_EdtEngine.GetFont(); + if (!font) + return; + + pRenderDev->SetClip_Rect(clipRect); + + CFX_RectF rtDocClip = clipRect; + if (rtDocClip.IsEmpty()) { + rtDocClip.left = 0; + rtDocClip.top = 0; + rtDocClip.width = static_cast<float>(pRenderDev->GetWidth()); + rtDocClip.height = static_cast<float>(pRenderDev->GetHeight()); + } + rtDocClip = mt.GetInverse().TransformRect(rtDocClip); + + for (const FDE_TEXTEDITPIECE& info : m_EdtEngine.GetTextPieces()) { + // If this character is outside the clip, skip it. + if (!rtDocClip.IntersectWith(info.rtPiece)) + continue; + + std::vector<FXTEXT_CHARPOS> char_pos = m_EdtEngine.GetDisplayPos(info); + if (char_pos.empty()) + continue; + + CFDE_TextOut::DrawString(pRenderDev, m_EdtEngine.GetFontColor(), font, + char_pos.data(), char_pos.size(), + m_EdtEngine.GetFontSize(), &mt); + } +} + void CFWL_Edit::UpdateEditEngine() { UpdateEditParams(); UpdateEditLayout(); - if (m_nLimit > -1) - m_EdtEngine.SetLimit(m_nLimit); } void CFWL_Edit::UpdateEditParams() { - FDE_TXTEDTPARAMS params; - params.nHorzScale = 100; - params.fPlateWidth = m_rtEngine.width; - params.fPlateHeight = m_rtEngine.height; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) - params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) - params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) - params.dwMode |= FDE_TEXTEDITMODE_Validate; - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) - params.dwMode |= FDE_TEXTEDITMODE_Password; + m_EdtEngine.SetAvailableWidth(m_rtEngine.width); + m_EdtEngine.SetCombText( + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)); + m_EdtEngine.EnableValidation( + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate)); + m_EdtEngine.EnablePasswordMode( + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password)); + + uint32_t alignment = 0; switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) { case FWL_STYLEEXT_EDT_HNear: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Left; + alignment |= CFX_TxtLineAlignment_Left; break; } case FWL_STYLEEXT_EDT_HCenter: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Center; + alignment |= CFX_TxtLineAlignment_Center; break; } case FWL_STYLEEXT_EDT_HFar: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Right; + alignment |= CFX_TxtLineAlignment_Right; break; } default: @@ -635,122 +600,99 @@ void CFWL_Edit::UpdateEditParams() { } switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) { case FWL_STYLEEXT_EDT_Justified: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Justified; + alignment |= CFX_TxtLineAlignment_Justified; break; } - default: { - params.dwAlignment |= FDE_TEXTEDITALIGN_Normal; + default: break; - } } + m_EdtEngine.SetAlignment(alignment); + + bool auto_hscroll = + !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll); if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { - params.dwMode |= FDE_TEXTEDITMODE_MultiLines; - if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) { - params.dwMode |= - FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz; - } - if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && - (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) { - params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert; - } else { - params.fPlateHeight = 0x00FFFFFF; - } - } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == - 0) { - params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz; - } - if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || - (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { - params.dwMode |= FDE_TEXTEDITMODE_ReadOnly; + m_EdtEngine.EnableMultiLine(true); + m_EdtEngine.EnableLineWrap(!auto_hscroll); + m_EdtEngine.LimitVerticalScroll( + (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0); + } else { + m_EdtEngine.EnableMultiLine(false); + m_EdtEngine.EnableLineWrap(false); + m_EdtEngine.LimitVerticalScroll(false); } + m_EdtEngine.LimitHorizontalScroll(!auto_hscroll); IFWL_ThemeProvider* theme = GetAvailableTheme(); CFWL_ThemePart part; part.m_pWidget = this; - m_fFontSize = theme ? theme->GetFontSize(&part) : FWLTHEME_CAPACITY_FontSize; - if (!theme) + if (!theme) { + m_fFontSize = FWLTHEME_CAPACITY_FontSize; return; + } + m_fFontSize = theme->GetFontSize(&part); - params.dwFontColor = theme->GetTextColor(&part); - params.fLineSpace = theme->GetLineHeight(&part); - - CFX_RetainPtr<CFGAS_GEFont> pFont = theme->GetFont(&part); + RetainPtr<CFGAS_GEFont> pFont = theme->GetFont(&part); if (!pFont) return; - params.pFont = pFont; - params.fFontSize = m_fFontSize; - params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace); - if (params.nLineCount <= 0) - params.nLineCount = 1; - params.fTabWidth = params.fFontSize * 1; - params.bTabEquidistant = true; - params.wLineBreakChar = L'\n'; - params.nCharRotation = 0; - params.pEventSink = this; - m_EdtEngine.SetEditParams(params); + m_EdtEngine.SetFont(pFont); + m_EdtEngine.SetFontColor(theme->GetTextColor(&part)); + m_EdtEngine.SetFontSize(m_fFontSize); + m_EdtEngine.SetLineSpace(theme->GetLineHeight(&part)); + m_EdtEngine.SetTabWidth(m_fFontSize); + m_EdtEngine.SetVisibleLineCount(m_rtEngine.height / + theme->GetLineHeight(&part)); } void CFWL_Edit::UpdateEditLayout() { - if (m_EdtEngine.GetTextLength() <= 0) - m_EdtEngine.SetTextByStream(nullptr); - - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (pPage) - pPage->UnloadPage(nullptr); - - m_EdtEngine.StartLayout(); - m_EdtEngine.DoLayout(nullptr); - m_EdtEngine.EndLayout(); - pPage = m_EdtEngine.GetPage(0); - if (pPage) - pPage->LoadPage(nullptr, nullptr); + m_EdtEngine.Layout(); } bool CFWL_Edit::UpdateOffset() { - CFX_RectF rtCaret; - m_EdtEngine.GetCaretRect(rtCaret); - FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; - FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + CFX_RectF rtCaret = m_rtCaret; + + float fOffSetX = m_rtEngine.left - m_fScrollOffsetX; + float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; rtCaret.Offset(fOffSetX, fOffSetY); - const CFX_RectF& rtEidt = m_rtEngine; - if (rtEidt.Contains(rtCaret)) { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return false; - CFX_RectF rtFDE = pPage->GetContentsBox(); - rtFDE.Offset(fOffSetX, fOffSetY); - if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) { - m_fScrollOffsetX += rtFDE.right() - rtEidt.right(); + const CFX_RectF& edit_bounds = m_rtEngine; + if (edit_bounds.Contains(rtCaret)) { + CFX_RectF contents_bounds = m_EdtEngine.GetContentsBoundingBox(); + contents_bounds.Offset(fOffSetX, fOffSetY); + if (contents_bounds.right() < edit_bounds.right() && m_fScrollOffsetX > 0) { + m_fScrollOffsetX += contents_bounds.right() - edit_bounds.right(); m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f); } - if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) { - m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom(); + if (contents_bounds.bottom() < edit_bounds.bottom() && + m_fScrollOffsetY > 0) { + m_fScrollOffsetY += contents_bounds.bottom() - edit_bounds.bottom(); m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f); } return false; } - FX_FLOAT offsetX = 0.0; - FX_FLOAT offsetY = 0.0; - if (rtCaret.left < rtEidt.left) - offsetX = rtCaret.left - rtEidt.left; - if (rtCaret.right() > rtEidt.right()) - offsetX = rtCaret.right() - rtEidt.right(); - if (rtCaret.top < rtEidt.top) - offsetY = rtCaret.top - rtEidt.top; - if (rtCaret.bottom() > rtEidt.bottom()) - offsetY = rtCaret.bottom() - rtEidt.bottom(); + float offsetX = 0.0; + float offsetY = 0.0; + if (rtCaret.left < edit_bounds.left) + offsetX = rtCaret.left - edit_bounds.left; + if (rtCaret.right() > edit_bounds.right()) + offsetX = rtCaret.right() - edit_bounds.right(); + if (rtCaret.top < edit_bounds.top) + offsetY = rtCaret.top - edit_bounds.top; + if (rtCaret.bottom() > edit_bounds.bottom()) + offsetY = rtCaret.bottom() - edit_bounds.bottom(); + m_fScrollOffsetX += offsetX; m_fScrollOffsetY += offsetY; if (m_fFontSize > m_rtEngine.height) m_fScrollOffsetY = 0; + return true; } -bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged) { +bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, float fPosChanged) { if (pScrollBar == m_pHorzScrollBar.get()) m_fScrollOffsetX += fPosChanged; else @@ -759,37 +701,29 @@ bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged) { } void CFWL_Edit::UpdateVAlignment() { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - - const CFX_RectF& rtFDE = pPage->GetContentsBox(); - FX_FLOAT fOffsetY = 0.0f; - FX_FLOAT fSpaceAbove = 0.0f; - FX_FLOAT fSpaceBelow = 0.0f; + float fSpaceAbove = 0.0f; + float fSpaceBelow = 0.0f; IFWL_ThemeProvider* theme = GetAvailableTheme(); if (theme) { CFWL_ThemePart part; part.m_pWidget = this; CFX_SizeF pSpace = theme->GetSpaceAboveBelow(&part); - fSpaceAbove = pSpace.width; - fSpaceBelow = pSpace.height; + fSpaceAbove = pSpace.width >= 0.1f ? pSpace.width : 0.0f; + fSpaceBelow = pSpace.height >= 0.1f ? pSpace.height : 0.0f; } - if (fSpaceAbove < 0.1f) - fSpaceAbove = 0; - if (fSpaceBelow < 0.1f) - fSpaceBelow = 0; + float fOffsetY = 0.0f; + CFX_RectF contents_bounds = m_EdtEngine.GetContentsBoundingBox(); if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) { - fOffsetY = (m_rtEngine.height - rtFDE.height) / 2; - if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 && + fOffsetY = (m_rtEngine.height - contents_bounds.height) / 2.0f; + if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2.0f && fSpaceAbove < fSpaceBelow) { return; } - fOffsetY += (fSpaceAbove - fSpaceBelow) / 2; + fOffsetY += (fSpaceAbove - fSpaceBelow) / 2.0f; } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) { - fOffsetY = (m_rtEngine.height - rtFDE.height); + fOffsetY = (m_rtEngine.height - contents_bounds.height); fOffsetY -= fSpaceBelow; } else { fOffsetY += fSpaceAbove; @@ -798,17 +732,14 @@ void CFWL_Edit::UpdateVAlignment() { } void CFWL_Edit::UpdateCaret() { - CFX_RectF rtFDE; - m_EdtEngine.GetCaretRect(rtFDE); - - rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX, - m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); - CFX_RectF rtCaret(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height); + CFX_RectF rtCaret = m_rtCaret; + rtCaret.Offset(m_rtEngine.left - m_fScrollOffsetX, + m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); CFX_RectF rtClient = GetClientRect(); rtCaret.Intersect(rtClient); if (rtCaret.left > rtClient.right()) { - FX_FLOAT right = rtCaret.right(); + float right = rtCaret.right(); rtCaret.left = rtClient.right() - 1; rtCaret.width = right - rtCaret.left; } @@ -829,20 +760,16 @@ CFWL_ScrollBar* CFWL_Edit::UpdateScroll() { if (!bShowHorz && !bShowVert) return nullptr; - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return nullptr; - - const CFX_RectF& rtFDE = pPage->GetContentsBox(); + CFX_RectF contents_bounds = m_EdtEngine.GetContentsBoundingBox(); CFWL_ScrollBar* pRepaint = nullptr; if (bShowHorz) { CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect(); - if (rtScroll.width < rtFDE.width) { + if (rtScroll.width < contents_bounds.width) { m_pHorzScrollBar->LockUpdate(); - FX_FLOAT fRange = rtFDE.width - rtScroll.width; + float fRange = contents_bounds.width - rtScroll.width; m_pHorzScrollBar->SetRange(0.0f, fRange); - FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetX, 0.0f), fRange); + float fPos = pdfium::clamp(m_fScrollOffsetX, 0.0f, fRange); m_pHorzScrollBar->SetPos(fPos); m_pHorzScrollBar->SetTrackPos(fPos); m_pHorzScrollBar->SetPageSize(rtScroll.width); @@ -863,13 +790,14 @@ CFWL_ScrollBar* CFWL_Edit::UpdateScroll() { if (bShowVert) { CFX_RectF rtScroll = m_pVertScrollBar->GetWidgetRect(); - if (rtScroll.height < rtFDE.height) { + if (rtScroll.height < contents_bounds.height) { m_pVertScrollBar->LockUpdate(); - FX_FLOAT fStep = m_EdtEngine.GetEditParams()->fLineSpace; - FX_FLOAT fRange = std::max(rtFDE.height - m_rtEngine.height, fStep); + float fStep = m_EdtEngine.GetLineSpace(); + float fRange = + std::max(contents_bounds.height - m_rtEngine.height, fStep); m_pVertScrollBar->SetRange(0.0f, fRange); - FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetY, 0.0f), fRange); + float fPos = pdfium::clamp(m_fScrollOffsetY, 0.0f, fRange); m_pVertScrollBar->SetPos(fPos); m_pVertScrollBar->SetTrackPos(fPos); m_pVertScrollBar->SetPageSize(rtScroll.height); @@ -891,41 +819,20 @@ CFWL_ScrollBar* CFWL_Edit::UpdateScroll() { } bool CFWL_Edit::IsShowScrollBar(bool bVert) { + if (!bVert) + return false; bool bShow = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == FWL_WGTSTATE_Focused : true; - if (bVert) { - return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) && - (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) && - IsContentHeightOverflow(); - } - return false; + return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) && + IsContentHeightOverflow(); } bool CFWL_Edit::IsContentHeightOverflow() { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return false; - return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f; -} - -int32_t CFWL_Edit::AddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord) { - int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords); - if (m_iCurRecord == nCount - 1) { - if (nCount == m_iMaxRecord) { - m_DoRecords.pop_front(); - m_iCurRecord--; - } - } else { - m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1, - m_DoRecords.end()); - } - - m_DoRecords.push_back(std::move(pRecord)); - m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; - return m_iCurRecord; + return m_EdtEngine.GetContentsBoundingBox().height > m_rtEngine.height + 1.0f; } void CFWL_Edit::Layout() { @@ -935,7 +842,7 @@ void CFWL_Edit::Layout() { if (!theme) return; - FX_FLOAT fWidth = theme->GetScrollBarWidth(); + float fWidth = theme->GetScrollBarWidth(); CFWL_ThemePart part; if (!m_pOuter) { part.m_pWidget = this; @@ -1005,7 +912,7 @@ void CFWL_Edit::LayoutScrollBar() { bool bShowHorzScrollbar = IsShowScrollBar(false); IFWL_ThemeProvider* theme = GetAvailableTheme(); - FX_FLOAT fWidth = theme ? theme->GetScrollBarWidth() : 0; + float fWidth = theme ? theme->GetScrollBarWidth() : 0; if (bShowVertScrollbar) { if (!m_pVertScrollBar) { InitVerticalScrollBar(); @@ -1066,8 +973,8 @@ void CFWL_Edit::InitVerticalScrollBar() { prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible; prop->m_pParent = this; prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; - m_pVertScrollBar = - pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this); + m_pVertScrollBar = pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp.Get(), + std::move(prop), this); } void CFWL_Edit::InitHorizontalScrollBar() { @@ -1079,8 +986,8 @@ void CFWL_Edit::InitHorizontalScrollBar() { prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible; prop->m_pParent = this; prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; - m_pHorzScrollBar = - pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this); + m_pHorzScrollBar = pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp.Get(), + std::move(prop), this); } void CFWL_Edit::ShowCaret(CFX_RectF* pRect) { @@ -1110,8 +1017,7 @@ void CFWL_Edit::ShowCaret(CFX_RectF* pRect) { if (!pDocEnvironment) return; - CFX_RectF rt(*pRect); - pXFAWidget->GetRotateMatrix().TransformRect(rt); + CFX_RectF rt = pXFAWidget->GetRotateMatrix().TransformRect(*pRect); pDocEnvironment->DisplayCaret(pXFAWidget, true, &rt); } @@ -1138,53 +1044,51 @@ void CFWL_Edit::HideCaret(CFX_RectF* pRect) { pDocEnvironment->DisplayCaret(pXFAWidget, false, pRect); } -bool CFWL_Edit::ValidateNumberChar(FX_WCHAR cNum) { +bool CFWL_Edit::ValidateNumberChar(wchar_t cNum) { if (!m_bSetRange) return true; - CFX_WideString wsText = m_EdtEngine.GetText(0, -1); - if (wsText.IsEmpty()) { - if (cNum == L'0') - return false; - return true; - } - - int32_t caretPos = m_EdtEngine.GetCaretPos(); - if (CountSelRanges() == 0) { - if (cNum == L'0' && caretPos == 0) - return false; + WideString wsText = m_EdtEngine.GetText(); + if (wsText.IsEmpty()) + return cNum != L'0'; - int32_t nLen = wsText.GetLength(); - CFX_WideString l = wsText.Mid(0, caretPos); - CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos); - CFX_WideString wsNew = l + cNum + r; - if (wsNew.GetInteger() <= m_iMax) - return true; + if (HasSelection()) + return wsText.GetInteger() <= m_iMax; + if (cNum == L'0' && m_CursorPosition == 0) return false; - } - if (wsText.GetInteger() <= m_iMax) - return true; - return false; + int32_t nLen = wsText.GetLength(); + WideString l = wsText.Left(m_CursorPosition); + WideString r = wsText.Right(nLen - m_CursorPosition); + WideString wsNew = l + cNum + r; + return wsNew.GetInteger() <= m_iMax; } void CFWL_Edit::InitCaret() { - if (!m_pCaret) - return; m_pCaret.reset(); + m_rtCaret = CFX_RectF(); } -void CFWL_Edit::ClearRecord() { - m_iCurRecord = -1; - m_DoRecords.clear(); +void CFWL_Edit::UpdateCursorRect() { + int32_t bidi_level = 0; + m_rtCaret = CFX_RectF(); + std::tie(bidi_level, m_rtCaret) = + m_EdtEngine.GetCharacterInfo(m_CursorPosition); + // TODO(dsinclair): This should handle bidi level ... + + if (m_rtCaret.width == 0 && m_rtCaret.left > 1.0f) + m_rtCaret.left -= 1.0f; + + m_rtCaret.width = 1.0f; } -void CFWL_Edit::ProcessInsertError(int32_t iError) { - if (iError != -2) +void CFWL_Edit::SetCursorPosition(size_t position) { + if (m_CursorPosition == position) return; - CFWL_Event textFullEvent(CFWL_Event::Type::TextFull, this); - DispatchEvent(&textFullEvent); + m_CursorPosition = position; + UpdateCursorRect(); + OnCaretChanged(); } void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { @@ -1208,13 +1112,13 @@ void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { OnLButtonUp(pMsg); break; case FWL_MouseCommand::LeftButtonDblClk: - OnButtonDblClk(pMsg); + OnButtonDoubleClick(pMsg); break; case FWL_MouseCommand::Move: OnMouseMove(pMsg); break; case FWL_MouseCommand::RightButtonDown: - DoButtonDown(pMsg); + DoRButtonDown(pMsg); break; default: break; @@ -1236,9 +1140,7 @@ void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { } void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) { - if (!pEvent) - return; - if (pEvent->GetType() != CFWL_Event::Type::Scroll) + if (!pEvent || pEvent->GetType() != CFWL_Event::Type::Scroll) return; CFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget; @@ -1250,25 +1152,16 @@ void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) { } } -void CFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_Edit::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } -void CFWL_Edit::DoButtonDown(CFWL_MessageMouse* pMsg) { +void CFWL_Edit::DoRButtonDown(CFWL_MessageMouse* pMsg) { if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) SetFocus(true); - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - - bool bBefore = true; - int32_t nIndex = pPage->GetCharIndex(DeviceToEngine(pMsg->m_pos), bBefore); - if (nIndex < 0) - nIndex = 0; - - m_EdtEngine.SetCaretPos(nIndex, bBefore); + m_CursorPosition = m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos)); } void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { @@ -1283,15 +1176,11 @@ void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; HideCaret(nullptr); - int32_t nSel = CountSelRanges(); - if (nSel > 0) { - ClearSelections(); + if (HasSelection()) { + ClearSelection(); bRepaint = true; } - m_EdtEngine.SetCaretPos(0, true); UpdateOffset(); - - ClearRecord(); } LayoutScrollBar(); @@ -1309,22 +1198,30 @@ void CFWL_Edit::OnLButtonDown(CFWL_MessageMouse* pMsg) { m_bLButtonDown = true; SetGrab(true); - DoButtonDown(pMsg); - int32_t nIndex = m_EdtEngine.GetCaretPos(); + + if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) + SetFocus(true); + bool bRepaint = false; - if (m_EdtEngine.CountSelRanges() > 0) { + if (m_EdtEngine.HasSelection()) { m_EdtEngine.ClearSelection(); bRepaint = true; } - if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) { - int32_t iStart = std::min(m_nSelStart, nIndex); - int32_t iEnd = std::max(m_nSelStart, nIndex); - m_EdtEngine.AddSelRange(iStart, iEnd - iStart); + size_t index_at_click = + m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos)); + + if (index_at_click != m_CursorPosition && + !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift)) { + size_t start = std::min(m_CursorPosition, index_at_click); + size_t end = std::max(m_CursorPosition, index_at_click); + + m_EdtEngine.SetSelection(start, end - start); bRepaint = true; } else { - m_nSelStart = nIndex; + m_CursorPosition = index_at_click; } + if (bRepaint) RepaintRect(m_rtEngine); } @@ -1334,98 +1231,102 @@ void CFWL_Edit::OnLButtonUp(CFWL_MessageMouse* pMsg) { SetGrab(false); } -void CFWL_Edit::OnButtonDblClk(CFWL_MessageMouse* pMsg) { - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) - return; - - int32_t nCount = 0; - int32_t nIndex = pPage->SelectWord(DeviceToEngine(pMsg->m_pos), nCount); - if (nIndex < 0) - return; +void CFWL_Edit::OnButtonDoubleClick(CFWL_MessageMouse* pMsg) { + size_t click_idx = m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos)); + size_t start_idx; + size_t count; + std::tie(start_idx, count) = m_EdtEngine.BoundsForWordAt(click_idx); - m_EdtEngine.AddSelRange(nIndex, nCount); - m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false); + m_EdtEngine.SetSelection(start_idx, count); + m_CursorPosition = start_idx + count; RepaintRect(m_rtEngine); } void CFWL_Edit::OnMouseMove(CFWL_MessageMouse* pMsg) { - if (m_nSelStart == -1 || !m_bLButtonDown) + bool shift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift); + if (!m_bLButtonDown || !shift) return; - IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); - if (!pPage) + size_t old_cursor_pos = m_CursorPosition; + SetCursorPosition(m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos))); + if (old_cursor_pos == m_CursorPosition) return; - bool bBefore = true; - int32_t nIndex = pPage->GetCharIndex(DeviceToEngine(pMsg->m_pos), bBefore); - m_EdtEngine.SetCaretPos(nIndex, bBefore); - nIndex = m_EdtEngine.GetCaretPos(); - m_EdtEngine.ClearSelection(); + size_t length = m_EdtEngine.GetLength(); + if (m_CursorPosition > length) + SetCursorPosition(length); - if (nIndex == m_nSelStart) - return; - - int32_t nLen = m_EdtEngine.GetTextLength(); - if (m_nSelStart >= nLen) - m_nSelStart = nLen; + size_t sel_start = 0; + size_t count = 0; + if (m_EdtEngine.HasSelection()) + std::tie(sel_start, count) = m_EdtEngine.GetSelection(); + else + sel_start = old_cursor_pos; - m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex), - FXSYS_abs(nIndex - m_nSelStart)); + size_t start_pos = std::min(sel_start, m_CursorPosition); + size_t end_pos = std::max(sel_start, m_CursorPosition); + m_EdtEngine.SetSelection(start_pos, end_pos - start_pos); } void CFWL_Edit::OnKeyDown(CFWL_MessageKey* pMsg) { - FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone; bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift); bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl); - uint32_t dwKeyCode = pMsg->m_dwKeyCode; - switch (dwKeyCode) { - case FWL_VKEY_Left: { - MoveCaret = MC_Left; + + size_t sel_start = m_CursorPosition; + if (m_EdtEngine.HasSelection()) { + size_t start_idx; + size_t count; + std::tie(start_idx, count) = m_EdtEngine.GetSelection(); + sel_start = start_idx; + } + + switch (pMsg->m_dwKeyCode) { + case FWL_VKEY_Left: + SetCursorPosition(m_EdtEngine.GetIndexLeft(m_CursorPosition)); break; - } - case FWL_VKEY_Right: { - MoveCaret = MC_Right; + case FWL_VKEY_Right: + SetCursorPosition(m_EdtEngine.GetIndexRight(m_CursorPosition)); break; - } - case FWL_VKEY_Up: { - MoveCaret = MC_Up; + case FWL_VKEY_Up: + SetCursorPosition(m_EdtEngine.GetIndexUp(m_CursorPosition)); break; - } - case FWL_VKEY_Down: { - MoveCaret = MC_Down; + case FWL_VKEY_Down: + SetCursorPosition(m_EdtEngine.GetIndexDown(m_CursorPosition)); break; - } - case FWL_VKEY_Home: { - MoveCaret = bCtrl ? MC_Home : MC_LineStart; + case FWL_VKEY_Home: + SetCursorPosition( + bCtrl ? 0 : m_EdtEngine.GetIndexAtStartOfLine(m_CursorPosition)); break; - } - case FWL_VKEY_End: { - MoveCaret = bCtrl ? MC_End : MC_LineEnd; - break; - } - case FWL_VKEY_Insert: + case FWL_VKEY_End: + SetCursorPosition( + bCtrl ? m_EdtEngine.GetLength() + : m_EdtEngine.GetIndexAtEndOfLine(m_CursorPosition)); break; case FWL_VKEY_Delete: { if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { break; } - int32_t nCaret = m_EdtEngine.GetCaretPos(); -#if (_FX_OS_ == _FX_MACOSX_) - m_EdtEngine.Delete(nCaret, true); -#else - m_EdtEngine.Delete(nCaret); -#endif + + if (m_CursorPosition > 0) { + SetCursorPosition(m_EdtEngine.GetIndexBefore(m_CursorPosition)); + m_EdtEngine.Delete(m_CursorPosition, 1); + } break; } + case FWL_VKEY_Insert: case FWL_VKEY_F2: case FWL_VKEY_Tab: default: break; } - if (MoveCaret != MC_MoveNone) - m_EdtEngine.MoveCaretPos(MoveCaret, bShift, bCtrl); + + // Update the selection. + if (bShift && sel_start != m_CursorPosition) { + m_EdtEngine.SetSelection(std::min(sel_start, m_CursorPosition), + std::max(sel_start, m_CursorPosition)); + RepaintRect(m_rtEngine); + } } void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) { @@ -1434,26 +1335,27 @@ void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) { return; } - int32_t iError = 0; - FX_WCHAR c = static_cast<FX_WCHAR>(pMsg->m_dwKeyCode); - int32_t nCaret = m_EdtEngine.GetCaretPos(); + wchar_t c = static_cast<wchar_t>(pMsg->m_dwKeyCode); switch (c) { case FWL_VKEY_Back: - m_EdtEngine.Delete(nCaret, true); + if (m_CursorPosition > 0) { + SetCursorPosition(m_EdtEngine.GetIndexBefore(m_CursorPosition)); + m_EdtEngine.Delete(m_CursorPosition, 1); + } break; case FWL_VKEY_NewLine: case FWL_VKEY_Escape: break; - case FWL_VKEY_Tab: { - iError = m_EdtEngine.Insert(nCaret, L"\t", 1); + case FWL_VKEY_Tab: + m_EdtEngine.Insert(m_CursorPosition, L"\t"); + SetCursorPosition(m_CursorPosition + 1); break; - } - case FWL_VKEY_Return: { + case FWL_VKEY_Return: if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) { - iError = m_EdtEngine.Insert(nCaret, L"\n", 1); + m_EdtEngine.Insert(m_CursorPosition, L"\n"); + SetCursorPosition(m_CursorPosition + 1); } break; - } default: { if (!m_pWidgetMgr->IsFormDisabled()) { if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) { @@ -1466,29 +1368,23 @@ void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) { break; } } -#if (_FX_OS_ == _FX_MACOSX_) - if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) -#else - if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) -#endif - { + if (pMsg->m_dwFlags & kEditingModifier) break; - } - iError = m_EdtEngine.Insert(nCaret, &c, 1); + + m_EdtEngine.Insert(m_CursorPosition, WideString(c)); + SetCursorPosition(m_CursorPosition + 1); break; } } - if (iError < 0) - ProcessInsertError(iError); } bool CFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar, CFWL_EventScroll::Code dwCode, - FX_FLOAT fPos) { + float fPos) { CFX_SizeF fs; pScrollBar->GetRange(&fs.width, &fs.height); - FX_FLOAT iCurPos = pScrollBar->GetPos(); - FX_FLOAT fStep = pScrollBar->GetStepSize(); + float iCurPos = pScrollBar->GetPos(); + float fStep = pScrollBar->GetStepSize(); switch (dwCode) { case CFWL_EventScroll::Code::Min: { fPos = fs.width; diff --git a/xfa/fwl/cfwl_edit.h b/xfa/fwl/cfwl_edit.h index 154e286331fbcd8dea5e46660a855e019b3137ed..9c667f5e1452e12a94ff1b16fd2ae3d7b466c17a 100644 --- a/xfa/fwl/cfwl_edit.h +++ b/xfa/fwl/cfwl_edit.h @@ -7,16 +7,15 @@ #ifndef XFA_FWL_CFWL_EDIT_H_ #define XFA_FWL_CFWL_EDIT_H_ -#include <deque> #include <memory> +#include <utility> #include <vector> -#include "xfa/fde/cfde_txtedtengine.h" -#include "xfa/fde/ifde_txtedtdorecord.h" +#include "xfa/fde/cfde_texteditengine.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_scrollbar.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gepath.h" #define FWL_STYLEEXT_EDT_ReadOnly (1L << 0) #define FWL_STYLEEXT_EDT_MultiLine (1L << 1) @@ -39,15 +38,13 @@ #define FWL_STYLEEXT_EDT_HAlignModeMask (3L << 22) #define FWL_STYLEEXT_EDT_ShowScrollbarFocus (1L << 25) #define FWL_STYLEEXT_EDT_OuterScrollbar (1L << 26) -#define FWL_STYLEEXT_EDT_LastLineHeight (1L << 27) -class IFDE_TxtEdtDoRecord; class CFWL_Edit; class CFWL_MessageMouse; class CFWL_WidgetProperties; class CFWL_Caret; -class CFWL_Edit : public CFWL_Widget { +class CFWL_Edit : public CFWL_Widget, public CFDE_TextEditEngine::Delegate { public: CFWL_Edit(const CFWL_App* app, std::unique_ptr<CFWL_WidgetProperties> properties, @@ -61,31 +58,31 @@ class CFWL_Edit : public CFWL_Widget { void Update() override; FWL_WidgetHit HitTest(const CFX_PointF& point) override; void SetStates(uint32_t dwStates) override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override; void OnProcessMessage(CFWL_Message* pMessage) override; void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; - virtual void SetText(const CFX_WideString& wsText); + virtual void SetText(const WideString& wsText); int32_t GetTextLength() const; - CFX_WideString GetText() const; + WideString GetText() const; void ClearText(); - void AddSelRange(int32_t nStart); - int32_t CountSelRanges() const; - int32_t GetSelRange(int32_t nIndex, int32_t* nStart) const; - void ClearSelections(); + void SelectAll(); + void ClearSelection(); + bool HasSelection() const; + // Returns <start, count> of the selection. + std::pair<size_t, size_t> GetSelection() const; + int32_t GetLimit() const; void SetLimit(int32_t nLimit); - void SetAliasChar(FX_WCHAR wAlias); - bool Copy(CFX_WideString& wsCopy); - bool Cut(CFX_WideString& wsCut); - bool Paste(const CFX_WideString& wsPaste); - bool Redo(const IFDE_TxtEdtDoRecord* pRecord); - bool Undo(const IFDE_TxtEdtDoRecord* pRecord); + void SetAliasChar(wchar_t wAlias); + Optional<WideString> Copy(); + Optional<WideString> Cut(); + bool Paste(const WideString& wsPaste); bool Undo(); bool Redo(); bool CanUndo(); @@ -93,35 +90,37 @@ class CFWL_Edit : public CFWL_Widget { void SetOuter(CFWL_Widget* pOuter); - void OnCaretChanged(); - void OnTextChanged(const FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo); - void OnSelChanged(); - bool OnPageLoad(int32_t nPageIndex); - bool OnPageUnload(int32_t nPageIndex); - void OnAddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord); - bool OnValidate(const CFX_WideString& wsText); - void SetScrollOffset(FX_FLOAT fScrollOffset); + // CFDE_TextEditEngine::Delegate + void NotifyTextFull() override; + void OnCaretChanged() override; + void OnTextChanged(const WideString& prevText) override; + void OnSelChanged() override; + bool OnValidate(const WideString& wsText) override; + void SetScrollOffset(float fScrollOffset) override; protected: void ShowCaret(CFX_RectF* pRect); void HideCaret(CFX_RectF* pRect); const CFX_RectF& GetRTClient() const { return m_rtClient; } - CFDE_TxtEdtEngine* GetTxtEdtEngine() { return &m_EdtEngine; } + CFDE_TextEditEngine* GetTxtEdtEngine() { return &m_EdtEngine; } private: - void DrawTextBk(CFX_Graphics* pGraphics, + void RenderText(CFX_RenderDevice* pRenderDev, + const CFX_RectF& clipRect, + const CFX_Matrix& mt); + void DrawTextBk(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawContent(CFX_Graphics* pGraphics, + void DrawContent(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawSpellCheck(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix); + void DrawSpellCheck(CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix); void UpdateEditEngine(); void UpdateEditParams(); void UpdateEditLayout(); bool UpdateOffset(); - bool UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged); + bool UpdateOffset(CFWL_ScrollBar* pScrollBar, float fPosChanged); void UpdateVAlignment(); void UpdateCaret(); CFWL_ScrollBar* UpdateScroll(); @@ -132,51 +131,48 @@ class CFWL_Edit : public CFWL_Widget { void InitHorizontalScrollBar(); void InitEngine(); void InitCaret(); - bool ValidateNumberChar(FX_WCHAR cNum); - void ClearRecord(); + bool ValidateNumberChar(wchar_t cNum); bool IsShowScrollBar(bool bVert); bool IsContentHeightOverflow(); - int32_t AddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord); - void ProcessInsertError(int32_t iError); - void AddSpellCheckObj(CFX_Path& PathData, + void AddSpellCheckObj(CXFA_GEPath& PathData, int32_t nStart, int32_t nCount, - FX_FLOAT fOffSetX, - FX_FLOAT fOffSetY); + float fOffSetX, + float fOffSetY); + void SetCursorPosition(size_t position); + void UpdateCursorRect(); - void DoButtonDown(CFWL_MessageMouse* pMsg); + void DoRButtonDown(CFWL_MessageMouse* pMsg); void OnFocusChanged(CFWL_Message* pMsg, bool bSet); void OnLButtonDown(CFWL_MessageMouse* pMsg); void OnLButtonUp(CFWL_MessageMouse* pMsg); - void OnButtonDblClk(CFWL_MessageMouse* pMsg); + void OnButtonDoubleClick(CFWL_MessageMouse* pMsg); void OnMouseMove(CFWL_MessageMouse* pMsg); void OnKeyDown(CFWL_MessageKey* pMsg); void OnChar(CFWL_MessageKey* pMsg); bool OnScroll(CFWL_ScrollBar* pScrollBar, CFWL_EventScroll::Code dwCode, - FX_FLOAT fPos); + float fPos); CFX_RectF m_rtClient; CFX_RectF m_rtEngine; CFX_RectF m_rtStatic; - FX_FLOAT m_fVAlignOffset; - FX_FLOAT m_fScrollOffsetX; - FX_FLOAT m_fScrollOffsetY; - CFDE_TxtEdtEngine m_EdtEngine; + CFX_RectF m_rtCaret; + float m_fVAlignOffset; + float m_fScrollOffsetX; + float m_fScrollOffsetY; + CFDE_TextEditEngine m_EdtEngine; bool m_bLButtonDown; - int32_t m_nSelStart; + size_t m_CursorPosition; int32_t m_nLimit; - FX_FLOAT m_fFontSize; + float m_fFontSize; bool m_bSetRange; int32_t m_iMax; std::unique_ptr<CFWL_ScrollBar> m_pVertScrollBar; std::unique_ptr<CFWL_ScrollBar> m_pHorzScrollBar; std::unique_ptr<CFWL_Caret> m_pCaret; - CFX_WideString m_wsCache; - CFX_WideString m_wsFont; - std::deque<std::unique_ptr<IFDE_TxtEdtDoRecord>> m_DoRecords; - int32_t m_iCurRecord; - int32_t m_iMaxRecord; + WideString m_wsCache; + WideString m_wsFont; }; #endif // XFA_FWL_CFWL_EDIT_H_ diff --git a/xfa/fwl/cfwl_edit_embeddertest.cpp b/xfa/fwl/cfwl_edit_embeddertest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59a4ca59474538b85716098a1a2fb25bf3e4860f --- /dev/null +++ b/xfa/fwl/cfwl_edit_embeddertest.cpp @@ -0,0 +1,79 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/widestring.h" +#include "public/fpdf_formfill.h" +#include "public/fpdf_fwlevent.h" +#include "testing/embedder_test.h" +#include "testing/embedder_test_timer_handling_delegate.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CFWLEditEmbeddertest : public EmbedderTest { + protected: + void SetUp() override { + EmbedderTest::SetUp(); + SetDelegate(&delegate_); + CreateAndInitializeFormPDF(); + } + + void TearDown() override { + UnloadPage(page()); + EmbedderTest::TearDown(); + } + + void CreateAndInitializeFormPDF() { + EXPECT_TRUE(OpenDocument("xfa/email_recommended.pdf")); + page_ = LoadPage(0); + ASSERT_TRUE(page_); + } + + FPDF_PAGE page() const { return page_; } + EmbedderTestTimerHandlingDelegate delegate() const { return delegate_; } + + private: + FPDF_PAGE page_; + EmbedderTestTimerHandlingDelegate delegate_; +}; + +TEST_F(CFWLEditEmbeddertest, Trivial) { + ASSERT_EQ(1u, delegate().GetAlerts().size()); + auto alert = delegate().GetAlerts()[0]; + EXPECT_STREQ(L"PDFium", alert.title.c_str()); + EXPECT_STREQ(L"The value you entered for Text Field is invalid.", + alert.message.c_str()); +} + +TEST_F(CFWLEditEmbeddertest, LeftClickMouseSelection) { + FORM_OnLButtonDown(form_handle(), page(), 0, 115, 58); + for (size_t i = 0; i < 10; ++i) + FORM_OnChar(form_handle(), page(), 'a' + i, 0); + + // Mouse selection + FORM_OnLButtonDown(form_handle(), page(), 0, 128, 58); + FORM_OnLButtonDown(form_handle(), page(), FWL_EVENTFLAG_ShiftKey, 152, 58); + + // 12 == (2 * strlen(defgh)) + 2 (for \0\0) + EXPECT_EQ(12UL, FORM_GetSelectedText(form_handle(), page(), nullptr, 0)); + + unsigned short buf[128]; + unsigned long len = FORM_GetSelectedText(form_handle(), page(), &buf, 128); + EXPECT_STREQ(L"defgh", WideString::FromUTF16LE(buf, len).c_str()); +} + +TEST_F(CFWLEditEmbeddertest, DragMouseSelection) { + FORM_OnLButtonDown(form_handle(), page(), 0, 115, 58); + for (size_t i = 0; i < 10; ++i) + FORM_OnChar(form_handle(), page(), 'a' + i, 0); + + // Mouse selection + FORM_OnLButtonDown(form_handle(), page(), 0, 128, 58); + FORM_OnMouseMove(form_handle(), page(), FWL_EVENTFLAG_ShiftKey, 152, 58); + + // 12 == (2 * strlen(defgh)) + 2 (for \0\0) + EXPECT_EQ(12UL, FORM_GetSelectedText(form_handle(), page(), nullptr, 0)); + + unsigned short buf[128]; + unsigned long len = FORM_GetSelectedText(form_handle(), page(), &buf, 128); + EXPECT_STREQ(L"defgh", WideString::FromUTF16LE(buf, len).c_str()); +} diff --git a/xfa/fwl/cfwl_event.h b/xfa/fwl/cfwl_event.h index e326ab32c8d0e9313f60ea7fc16ae8617c32cac1..01e3914b8bebb054e44fd72b868011c447ef9a1b 100644 --- a/xfa/fwl/cfwl_event.h +++ b/xfa/fwl/cfwl_event.h @@ -13,7 +13,7 @@ #include "xfa/fwl/cfwl_messagekey.h" #include "xfa/fwl/cfwl_messagemouse.h" -class CFX_Graphics; +class CXFA_Graphics; class CFWL_Widget; class CFWL_Event { diff --git a/xfa/fwl/cfwl_eventcheckword.h b/xfa/fwl/cfwl_eventcheckword.h index 3de1e75c248001de6c4fb157a601ab32e9f42c4e..fafe3d3278f342b2c6cdc16f5e108ca18b799800 100644 --- a/xfa/fwl/cfwl_eventcheckword.h +++ b/xfa/fwl/cfwl_eventcheckword.h @@ -14,7 +14,7 @@ class CFWL_EventCheckWord : public CFWL_Event { explicit CFWL_EventCheckWord(CFWL_Widget* pSrcTarget); ~CFWL_EventCheckWord() override; - CFX_ByteString bsWord; + ByteString bsWord; bool bCheckWord; }; diff --git a/xfa/fwl/cfwl_eventscroll.h b/xfa/fwl/cfwl_eventscroll.h index 2fdef9e7b1748b11a42ea55c5e6d9dd8d328d314..a13eeef02019787e11f13332dc4e267313f06602 100644 --- a/xfa/fwl/cfwl_eventscroll.h +++ b/xfa/fwl/cfwl_eventscroll.h @@ -28,7 +28,7 @@ class CFWL_EventScroll : public CFWL_Event { ~CFWL_EventScroll() override; Code m_iScrollCode; - FX_FLOAT m_fPos; + float m_fPos; }; #endif // XFA_FWL_CFWL_EVENTSCROLL_H_ diff --git a/xfa/fwl/cfwl_eventtarget.cpp b/xfa/fwl/cfwl_eventtarget.cpp index 55f8e1fc78f9f4673ca9f7b87584c2370fc6c9c4..8a3b78799b2aee8a61d9e195da45082e74776d6f 100644 --- a/xfa/fwl/cfwl_eventtarget.cpp +++ b/xfa/fwl/cfwl_eventtarget.cpp @@ -10,7 +10,7 @@ #include "xfa/fwl/ifwl_widgetdelegate.h" CFWL_EventTarget::CFWL_EventTarget(CFWL_Widget* pListener) - : m_pListener(pListener), m_bInvalid(false) {} + : m_pListener(pListener), m_bValid(true) {} CFWL_EventTarget::~CFWL_EventTarget() {} diff --git a/xfa/fwl/cfwl_eventtarget.h b/xfa/fwl/cfwl_eventtarget.h index 1bca97232c0cd97b86573c66cdc835f3a11a9036..b5a8bdbb9e062c77f2e33d736ef47483946e9234 100644 --- a/xfa/fwl/cfwl_eventtarget.h +++ b/xfa/fwl/cfwl_eventtarget.h @@ -9,7 +9,6 @@ #include <set> -#include "core/fxcrt/fx_basic.h" #include "xfa/fwl/cfwl_event.h" class CFWL_Event; @@ -23,13 +22,13 @@ class CFWL_EventTarget { void SetEventSource(CFWL_Widget* pSource); bool ProcessEvent(CFWL_Event* pEvent); - bool IsInvalid() const { return m_bInvalid; } - void FlagInvalid() { m_bInvalid = true; } + bool IsValid() const { return m_bValid; } + void FlagInvalid() { m_bValid = false; } private: std::set<CFWL_Widget*> m_widgets; CFWL_Widget* m_pListener; - bool m_bInvalid; + bool m_bValid; }; #endif // XFA_FWL_CFWL_EVENTTARGET_H_ diff --git a/xfa/fwl/cfwl_eventtextchanged.h b/xfa/fwl/cfwl_eventtextchanged.h index 8ae27627b54696c1002da5fcc88657c3d8e686ff..4494f080755e51796c7a3df30a18d6e7355bb6fe 100644 --- a/xfa/fwl/cfwl_eventtextchanged.h +++ b/xfa/fwl/cfwl_eventtextchanged.h @@ -14,7 +14,7 @@ class CFWL_EventTextChanged : public CFWL_Event { explicit CFWL_EventTextChanged(CFWL_Widget* pSrcTarget); ~CFWL_EventTextChanged() override; - CFX_WideString wsPrevText; + WideString wsPrevText; }; #endif // XFA_FWL_CFWL_EVENTTEXTCHANGED_H_ diff --git a/xfa/fwl/cfwl_eventvalidate.h b/xfa/fwl/cfwl_eventvalidate.h index 512161212a1f4c916361ed898037c0b5f3fddf26..b8feff11200c14336186a6a1ee1ff32964d0f8a7 100644 --- a/xfa/fwl/cfwl_eventvalidate.h +++ b/xfa/fwl/cfwl_eventvalidate.h @@ -14,7 +14,7 @@ class CFWL_EventValidate : public CFWL_Event { explicit CFWL_EventValidate(CFWL_Widget* pSrcTarget); ~CFWL_EventValidate() override; - CFX_WideString wsInsert; + WideString wsInsert; bool bValidate; }; diff --git a/xfa/fwl/cfwl_form.cpp b/xfa/fwl/cfwl_form.cpp index 5e956ade2d0a9e7c5399a173d63468a8ee047a37..d1c178322cef46c450b4bd37c36939e8efcf5bc9 100644 --- a/xfa/fwl/cfwl_form.cpp +++ b/xfa/fwl/cfwl_form.cpp @@ -9,7 +9,7 @@ #include <utility> #include "third_party/base/ptr_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_formproxy.h" @@ -21,7 +21,6 @@ #include "xfa/fwl/cfwl_themetext.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fwl/theme/cfwl_widgettp.h" CFWL_Form::CFWL_Form(const CFWL_App* app, std::unique_ptr<CFWL_WidgetProperties> properties, @@ -46,8 +45,8 @@ FWL_Type CFWL_Form::GetClassID() const { return FWL_Type::Form; } -bool CFWL_Form::IsInstance(const CFX_WideStringC& wsClass) const { - if (wsClass == CFX_WideStringC(FWL_CLASS_Form)) +bool CFWL_Form::IsInstance(const WideStringView& wsClass) const { + if (wsClass == WideStringView(FWL_CLASS_Form)) return true; return CFWL_Widget::IsInstance(wsClass); } @@ -75,7 +74,7 @@ FWL_WidgetHit CFWL_Form::HitTest(const CFX_PointF& point) { : FWL_WidgetHit::Client; } -void CFWL_Form::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { +void CFWL_Form::DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -84,7 +83,7 @@ void CFWL_Form::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; DrawBackground(pGraphics, pTheme); -#ifdef FWL_UseMacSystemBorder +#if _FX_OS_ == _FX_OS_MACOSX_ return; #endif CFWL_ThemeBackground param; @@ -92,8 +91,7 @@ void CFWL_Form::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { param.m_dwStates = CFWL_PartState_Normal; param.m_pGraphics = pGraphics; param.m_rtPart = m_rtRelative; - if (pMatrix) - param.m_matrix.Concat(*pMatrix); + param.m_matrix.Concat(matrix); if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) { param.m_iPart = CFWL_Part::Border; pTheme->DrawBackground(¶m); @@ -116,7 +114,7 @@ CFWL_Widget* CFWL_Form::DoModal() { RemoveStates(FWL_WGTSTATE_Invisible); pDriver->Run(); -#if _FX_OS_ != _FX_MACOSX_ +#if _FX_OS_ != _FX_OS_MACOSX_ pDriver->PopNoteLoop(); #endif @@ -128,7 +126,7 @@ void CFWL_Form::EndDoModal() { if (!m_pNoteLoop) return; -#if (_FX_OS_ == _FX_MACOSX_) +#if (_FX_OS_ == _FX_OS_MACOSX_) m_pNoteLoop->EndModalLoop(); const CFWL_App* pApp = GetOwnerApp(); if (!pApp) @@ -147,7 +145,7 @@ void CFWL_Form::EndDoModal() { #endif } -void CFWL_Form::DrawBackground(CFX_Graphics* pGraphics, +void CFWL_Form::DrawBackground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme) { CFWL_ThemeBackground param; param.m_pWidget = this; @@ -161,8 +159,8 @@ void CFWL_Form::DrawBackground(CFX_Graphics* pGraphics, CFX_RectF CFWL_Form::GetEdgeRect() { CFX_RectF rtEdge = m_rtRelative; if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) { - FX_FLOAT fCX = GetBorderSize(true); - FX_FLOAT fCY = GetBorderSize(false); + float fCX = GetBorderSize(true); + float fCY = GetBorderSize(false); rtEdge.Deflate(fCX, fCY, fCX, fCY); } return rtEdge; @@ -179,7 +177,7 @@ void CFWL_Form::SetWorkAreaRect() { void CFWL_Form::Layout() { m_rtRelative = GetRelativeRect(); -#ifndef FWL_UseMacSystemBorder +#if _FX_OS_ == _FX_OS_MACOSX_ IFWL_ThemeProvider* theme = GetAvailableTheme(); m_fCXBorder = theme ? theme->GetCXBorderSize() : 0.0f; m_fCYBorder = theme ? theme->GetCYBorderSize() : 0.0f; @@ -213,7 +211,7 @@ void CFWL_Form::UnRegisterForm() { } void CFWL_Form::OnProcessMessage(CFWL_Message* pMessage) { -#ifndef FWL_UseMacSystemBorder +#if _FX_OS_ == _FX_OS_MACOSX_ if (!pMessage) return; @@ -235,12 +233,12 @@ void CFWL_Form::OnProcessMessage(CFWL_Message* pMessage) { default: break; } -#endif // FWL_UseMacSystemBorder +#endif // _FX_OS_ == _FX_OS_MACOSX_ } -void CFWL_Form::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_Form::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_Form::OnLButtonDown(CFWL_MessageMouse* pMsg) { diff --git a/xfa/fwl/cfwl_form.h b/xfa/fwl/cfwl_form.h index 7202cb279b2b398a2271d0b952a09f643e35b353..cac1747385991a8930d9b1d77cfd35119c057fab 100644 --- a/xfa/fwl/cfwl_form.h +++ b/xfa/fwl/cfwl_form.h @@ -16,10 +16,6 @@ #define FWL_CLASS_Form L"FWL_FORM" #define FWL_CLASS_FormProxy L"FWL_FORMPROXY" -#if (_FX_OS_ == _FX_MACOSX_) -#define FWL_UseMacSystemBorder -#endif - class CFWL_MessageMouse; class CFWL_NoteLoop; class CFWL_Widget; @@ -34,14 +30,14 @@ class CFWL_Form : public CFWL_Widget { // CFWL_Widget FWL_Type GetClassID() const override; - bool IsInstance(const CFX_WideStringC& wsClass) const override; + bool IsInstance(const WideStringView& wsClass) const override; CFX_RectF GetClientRect() override; void Update() override; FWL_WidgetHit HitTest(const CFX_PointF& point) override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; CFWL_Widget* DoModal(); void EndDoModal(); @@ -50,7 +46,7 @@ class CFWL_Form : public CFWL_Widget { void SetSubFocus(CFWL_Widget* pWidget) { m_pSubFocus = pWidget; } private: - void DrawBackground(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme); + void DrawBackground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme); CFX_RectF GetEdgeRect(); void SetWorkAreaRect(); void Layout(); @@ -63,8 +59,8 @@ class CFWL_Form : public CFWL_Widget { CFX_RectF m_rtRelative; std::unique_ptr<CFWL_NoteLoop> m_pNoteLoop; CFWL_Widget* m_pSubFocus; - FX_FLOAT m_fCXBorder; - FX_FLOAT m_fCYBorder; + float m_fCXBorder; + float m_fCYBorder; }; #endif // XFA_FWL_CFWL_FORM_H_ diff --git a/xfa/fwl/cfwl_formproxy.cpp b/xfa/fwl/cfwl_formproxy.cpp index 776ba0ac6140e38769b536a24ab572b2c8de601d..d03c1488cd222b86900c2dd795a8bdeea0631e3f 100644 --- a/xfa/fwl/cfwl_formproxy.cpp +++ b/xfa/fwl/cfwl_formproxy.cpp @@ -24,16 +24,16 @@ FWL_Type CFWL_FormProxy::GetClassID() const { return FWL_Type::FormProxy; } -bool CFWL_FormProxy::IsInstance(const CFX_WideStringC& wsClass) const { - if (wsClass == CFX_WideStringC(FWL_CLASS_FormProxy)) +bool CFWL_FormProxy::IsInstance(const WideStringView& wsClass) const { + if (wsClass == WideStringView(FWL_CLASS_FormProxy)) return true; return CFWL_Form::IsInstance(wsClass); } void CFWL_FormProxy::Update() {} -void CFWL_FormProxy::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) {} +void CFWL_FormProxy::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) {} void CFWL_FormProxy::OnProcessMessage(CFWL_Message* pMessage) { m_pOuter->GetDelegate()->OnProcessMessage(pMessage); diff --git a/xfa/fwl/cfwl_formproxy.h b/xfa/fwl/cfwl_formproxy.h index 4ad70bf15c66368a31860128176034dedef031fc..498ff42a3e38feb1cf7f35d08c80f1ed5528eb6b 100644 --- a/xfa/fwl/cfwl_formproxy.h +++ b/xfa/fwl/cfwl_formproxy.h @@ -22,9 +22,9 @@ class CFWL_FormProxy : public CFWL_Form { // CFWL_Widget FWL_Type GetClassID() const override; - bool IsInstance(const CFX_WideStringC& wsClass) const override; + bool IsInstance(const WideStringView& wsClass) const override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; }; diff --git a/xfa/fwl/cfwl_listbox.cpp b/xfa/fwl/cfwl_listbox.cpp index 0b827099723526fb4a6e5a868a2cb2fba7c5004c..0ddb65bc1a0105266ae73879fb2a31349f633fff 100644 --- a/xfa/fwl/cfwl_listbox.cpp +++ b/xfa/fwl/cfwl_listbox.cpp @@ -12,7 +12,7 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_messagekey.h" #include "xfa/fwl/cfwl_messagemouse.h" @@ -32,8 +32,7 @@ CFWL_ListBox::CFWL_ListBox(const CFWL_App* app, std::unique_ptr<CFWL_WidgetProperties> properties, CFWL_Widget* pOuter) : CFWL_Widget(app, std::move(properties), pOuter), - m_dwTTOStyles(0), - m_iTTOAligns(0), + m_iTTOAligns(FDE_TextAlignment::kTopLeft), m_hAnchor(nullptr), m_fScorllBarWidth(0), m_bLButtonDown(false), @@ -57,20 +56,20 @@ void CFWL_ListBox::Update() { switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_AlignMask) { case FWL_STYLEEXT_LTB_LeftAlign: { - m_iTTOAligns = FDE_TTOALIGNMENT_CenterLeft; + m_iTTOAligns = FDE_TextAlignment::kCenterLeft; break; } case FWL_STYLEEXT_LTB_RightAlign: { - m_iTTOAligns = FDE_TTOALIGNMENT_CenterRight; + m_iTTOAligns = FDE_TextAlignment::kCenterRight; break; } case FWL_STYLEEXT_LTB_CenterAlign: default: { - m_iTTOAligns = FDE_TTOALIGNMENT_Center; + m_iTTOAligns = FDE_TextAlignment::kCenter; break; } } - m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine; + m_dwTTOStyles.single_line_ = true; m_fScorllBarWidth = GetScrollWidth(); CalcSize(false); } @@ -91,8 +90,8 @@ FWL_WidgetHit CFWL_ListBox::HitTest(const CFX_PointF& point) { return FWL_WidgetHit::Unknown; } -void CFWL_ListBox::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_ListBox::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -101,21 +100,19 @@ void CFWL_ListBox::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; pGraphics->SaveGraphState(); if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); CFX_RectF rtClip(m_rtConent); if (IsShowScrollBar(false)) rtClip.height -= m_fScorllBarWidth; if (IsShowScrollBar(true)) rtClip.width -= m_fScorllBarWidth; - if (pMatrix) - pMatrix->TransformRect(rtClip); - pGraphics->SetClipRect(rtClip); + pGraphics->SetClipRect(matrix.TransformRect(rtClip)); if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_NoBackground) == 0) - DrawBkground(pGraphics, pTheme, pMatrix); + DrawBkground(pGraphics, pTheme, &matrix); - DrawItems(pGraphics, pTheme, pMatrix); + DrawItems(pGraphics, pTheme, &matrix); pGraphics->RestoreGraphState(); } @@ -306,11 +303,11 @@ void CFWL_ListBox::SetFocusItem(CFWL_ListItem* pItem) { CFWL_ListItem* CFWL_ListBox::GetItemAtPoint(const CFX_PointF& point) { CFX_PointF pos = point - m_rtConent.TopLeft(); - FX_FLOAT fPosX = 0.0f; + float fPosX = 0.0f; if (m_pHorzScrollBar) fPosX = m_pHorzScrollBar->GetPos(); - FX_FLOAT fPosY = 0.0; + float fPosY = 0.0; if (m_pVertScrollBar) fPosY = m_pVertScrollBar->GetPos(); @@ -334,7 +331,7 @@ bool CFWL_ListBox::ScrollToVisible(CFWL_ListItem* pItem) { CFX_RectF rtItem = pItem ? pItem->GetRect() : CFX_RectF(); bool bScroll = false; - FX_FLOAT fPosY = m_pVertScrollBar->GetPos(); + float fPosY = m_pVertScrollBar->GetPos(); rtItem.Offset(0, -fPosY + m_rtConent.top); if (rtItem.top < m_rtConent.top) { fPosY += rtItem.top - m_rtConent.top; @@ -352,7 +349,7 @@ bool CFWL_ListBox::ScrollToVisible(CFWL_ListItem* pItem) { return true; } -void CFWL_ListBox::DrawBkground(CFX_Graphics* pGraphics, +void CFWL_ListBox::DrawBkground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { if (!pGraphics) @@ -375,14 +372,14 @@ void CFWL_ListBox::DrawBkground(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶m); } -void CFWL_ListBox::DrawItems(CFX_Graphics* pGraphics, +void CFWL_ListBox::DrawItems(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { - FX_FLOAT fPosX = 0.0f; + float fPosX = 0.0f; if (m_pHorzScrollBar) fPosX = m_pHorzScrollBar->GetPos(); - FX_FLOAT fPosY = 0.0f; + float fPosY = 0.0f; if (m_pVertScrollBar) fPosY = m_pVertScrollBar->GetPos(); @@ -408,7 +405,7 @@ void CFWL_ListBox::DrawItems(CFX_Graphics* pGraphics, } } -void CFWL_ListBox::DrawItem(CFX_Graphics* pGraphics, +void CFWL_ListBox::DrawItem(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, CFWL_ListItem* pItem, int32_t Index, @@ -447,7 +444,7 @@ void CFWL_ListBox::DrawItem(CFX_Graphics* pGraphics, if (!pItem) return; - CFX_WideString wsText = pItem->GetText(); + WideString wsText = pItem->GetText(); if (wsText.GetLength() <= 0) return; @@ -484,11 +481,10 @@ CFX_SizeF CFWL_ListBox::CalcSize(bool bAutoSize) { pUIMargin.height); } - FX_FLOAT fWidth = GetMaxTextWidth(); + float fWidth = GetMaxTextWidth(); fWidth += 2 * kItemTextMargin; if (!bAutoSize) { - FX_FLOAT fActualWidth = - m_rtClient.width - rtUIMargin.left - rtUIMargin.width; + float fActualWidth = m_rtClient.width - rtUIMargin.left - rtUIMargin.width; fWidth = std::max(fWidth, fActualWidth); } m_fItemHeight = CalcItemHeight(); @@ -502,7 +498,7 @@ CFX_SizeF CFWL_ListBox::CalcSize(bool bAutoSize) { if (bAutoSize) return fs; - FX_FLOAT iHeight = m_rtClient.height; + float iHeight = m_rtClient.height; bool bShowVertScr = false; bool bShowHorzScr = false; if (!bShowVertScr && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll)) @@ -527,8 +523,8 @@ CFX_SizeF CFWL_ListBox::CalcSize(bool bAutoSize) { m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10); m_pVertScrollBar->SetStepSize(m_fItemHeight); - FX_FLOAT fPos = - std::min(std::max(m_pVertScrollBar->GetPos(), 0.f), szRange.height); + float fPos = + pdfium::clamp(m_pVertScrollBar->GetPos(), 0.0f, szRange.height); m_pVertScrollBar->SetPos(fPos); m_pVertScrollBar->SetTrackPos(fPos); if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) == @@ -559,8 +555,8 @@ CFX_SizeF CFWL_ListBox::CalcSize(bool bAutoSize) { m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10); m_pHorzScrollBar->SetStepSize(fWidth / 10); - FX_FLOAT fPos = - std::min(std::max(m_pHorzScrollBar->GetPos(), 0.f), szRange.height); + float fPos = + pdfium::clamp(m_pHorzScrollBar->GetPos(), 0.0f, szRange.height); m_pHorzScrollBar->SetPos(fPos); m_pHorzScrollBar->SetTrackPos(fPos); if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) == @@ -584,8 +580,8 @@ CFX_SizeF CFWL_ListBox::CalcSize(bool bAutoSize) { void CFWL_ListBox::UpdateItemSize(CFWL_ListItem* pItem, CFX_SizeF& size, - FX_FLOAT fWidth, - FX_FLOAT fItemHeight, + float fWidth, + float fItemHeight, bool bAutoSize) const { if (!bAutoSize && pItem) { CFX_RectF rtItem(0, size.height, fWidth, fItemHeight); @@ -595,8 +591,8 @@ void CFWL_ListBox::UpdateItemSize(CFWL_ListItem* pItem, size.height += fItemHeight; } -FX_FLOAT CFWL_ListBox::GetMaxTextWidth() { - FX_FLOAT fRet = 0.0f; +float CFWL_ListBox::GetMaxTextWidth() { + float fRet = 0.0f; int32_t iCount = CountItems(this); for (int32_t i = 0; i < iCount; i++) { CFWL_ListItem* pItem = GetItem(this, i); @@ -610,12 +606,12 @@ FX_FLOAT CFWL_ListBox::GetMaxTextWidth() { return fRet; } -FX_FLOAT CFWL_ListBox::GetScrollWidth() { +float CFWL_ListBox::GetScrollWidth() { IFWL_ThemeProvider* theme = GetAvailableTheme(); return theme ? theme->GetScrollBarWidth() : 0.0f; } -FX_FLOAT CFWL_ListBox::CalcItemHeight() { +float CFWL_ListBox::CalcItemHeight() { IFWL_ThemeProvider* theme = GetAvailableTheme(); CFWL_ThemePart part; part.m_pWidget = this; @@ -631,8 +627,8 @@ void CFWL_ListBox::InitVerticalScrollBar() { prop->m_dwStates = FWL_WGTSTATE_Invisible; prop->m_pParent = this; prop->m_pThemeProvider = m_pScrollBarTP; - m_pVertScrollBar = - pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this); + m_pVertScrollBar = pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp.Get(), + std::move(prop), this); } void CFWL_ListBox::InitHorizontalScrollBar() { @@ -644,8 +640,8 @@ void CFWL_ListBox::InitHorizontalScrollBar() { prop->m_dwStates = FWL_WGTSTATE_Invisible; prop->m_pParent = this; prop->m_pThemeProvider = m_pScrollBarTP; - m_pHorzScrollBar = - pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this); + m_pHorzScrollBar = pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp.Get(), + std::move(prop), this); } bool CFWL_ListBox::IsShowScrollBar(bool bVert) { @@ -715,9 +711,9 @@ void CFWL_ListBox::OnProcessEvent(CFWL_Event* pEvent) { } } -void CFWL_ListBox::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_ListBox::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_ListBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { @@ -838,11 +834,11 @@ void CFWL_ListBox::OnVK(CFWL_ListItem* pItem, bool bShift, bool bCtrl) { bool CFWL_ListBox::OnScroll(CFWL_ScrollBar* pScrollBar, CFWL_EventScroll::Code dwCode, - FX_FLOAT fPos) { + float fPos) { CFX_SizeF fs; pScrollBar->GetRange(&fs.width, &fs.height); - FX_FLOAT iCurPos = pScrollBar->GetPos(); - FX_FLOAT fStep = pScrollBar->GetStepSize(); + float iCurPos = pScrollBar->GetPos(); + float fStep = pScrollBar->GetStepSize(); switch (dwCode) { case CFWL_EventScroll::Code::Min: { fPos = fs.width; @@ -911,9 +907,9 @@ int32_t CFWL_ListBox::GetItemIndex(CFWL_Widget* pWidget, CFWL_ListItem* pItem) { return it != m_ItemArray.end() ? it - m_ItemArray.begin() : -1; } -CFWL_ListItem* CFWL_ListBox::AddString(const CFX_WideStringC& wsAdd) { +CFWL_ListItem* CFWL_ListBox::AddString(const WideStringView& wsAdd) { m_ItemArray.emplace_back( - pdfium::MakeUnique<CFWL_ListItem>(CFX_WideString(wsAdd))); + pdfium::MakeUnique<CFWL_ListItem>(WideString(wsAdd))); return m_ItemArray.back().get(); } diff --git a/xfa/fwl/cfwl_listbox.h b/xfa/fwl/cfwl_listbox.h index caa4f509f82f4ab26a2866e2e85c5ceac3cb8a71..4a7818c38da0e1b3d44314e1ac3703243f44514c 100644 --- a/xfa/fwl/cfwl_listbox.h +++ b/xfa/fwl/cfwl_listbox.h @@ -42,18 +42,18 @@ class CFWL_ListBox : public CFWL_Widget { FWL_Type GetClassID() const override; void Update() override; FWL_WidgetHit HitTest(const CFX_PointF& point) override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override; void OnProcessMessage(CFWL_Message* pMessage) override; void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; int32_t CountItems(const CFWL_Widget* pWidget) const; CFWL_ListItem* GetItem(const CFWL_Widget* pWidget, int32_t nIndex) const; int32_t GetItemIndex(CFWL_Widget* pWidget, CFWL_ListItem* pItem); - CFWL_ListItem* AddString(const CFX_WideStringC& wsAdd); + CFWL_ListItem* AddString(const WideStringView& wsAdd); void RemoveAt(int32_t iIndex); void DeleteString(CFWL_ListItem* pItem); void DeleteAll(); @@ -63,8 +63,8 @@ class CFWL_ListBox : public CFWL_Widget { int32_t GetSelIndex(int32_t nIndex); void SetSelItem(CFWL_ListItem* hItem, bool bSelect); - FX_FLOAT GetItemHeight() const { return m_fItemHeight; } - FX_FLOAT CalcItemHeight(); + float GetItemHeight() const { return m_fItemHeight; } + float CalcItemHeight(); protected: CFWL_ListItem* GetListItem(CFWL_ListItem* hItem, uint32_t dwKeyCode); @@ -85,27 +85,27 @@ class CFWL_ListBox : public CFWL_Widget { void SelectAll(); CFWL_ListItem* GetFocusedItem(); void SetFocusItem(CFWL_ListItem* hItem); - void DrawBkground(CFX_Graphics* pGraphics, + void DrawBkground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawItems(CFX_Graphics* pGraphics, + void DrawItems(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawItem(CFX_Graphics* pGraphics, + void DrawItem(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, CFWL_ListItem* hItem, int32_t Index, const CFX_RectF& rtItem, const CFX_Matrix* pMatrix); - void DrawStatic(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme); + void DrawStatic(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme); CFX_SizeF CalcSize(bool bAutoSize); void UpdateItemSize(CFWL_ListItem* hItem, CFX_SizeF& size, - FX_FLOAT fWidth, - FX_FLOAT fHeight, + float fWidth, + float fHeight, bool bAutoSize) const; - FX_FLOAT GetMaxTextWidth(); - FX_FLOAT GetScrollWidth(); + float GetMaxTextWidth(); + float GetScrollWidth(); void OnFocusChanged(CFWL_Message* pMsg, bool bSet); void OnLButtonDown(CFWL_MessageMouse* pMsg); @@ -115,18 +115,18 @@ class CFWL_ListBox : public CFWL_Widget { void OnVK(CFWL_ListItem* hItem, bool bShift, bool bCtrl); bool OnScroll(CFWL_ScrollBar* pScrollBar, CFWL_EventScroll::Code dwCode, - FX_FLOAT fPos); + float fPos); CFX_RectF m_rtClient; CFX_RectF m_rtStatic; CFX_RectF m_rtConent; std::unique_ptr<CFWL_ScrollBar> m_pHorzScrollBar; std::unique_ptr<CFWL_ScrollBar> m_pVertScrollBar; - uint32_t m_dwTTOStyles; - int32_t m_iTTOAligns; + FDE_TextStyle m_dwTTOStyles; + FDE_TextAlignment m_iTTOAligns; CFWL_ListItem* m_hAnchor; - FX_FLOAT m_fItemHeight; - FX_FLOAT m_fScorllBarWidth; + float m_fItemHeight; + float m_fScorllBarWidth; bool m_bLButtonDown; IFWL_ThemeProvider* m_pScrollBarTP; std::vector<std::unique_ptr<CFWL_ListItem>> m_ItemArray; diff --git a/xfa/fwl/cfwl_listitem.cpp b/xfa/fwl/cfwl_listitem.cpp index a8ea8a645237234a4e07bc3246a0ee3eda5528b2..f8a7b753aa1b9817716a44deed0a0927b43ff89a 100644 --- a/xfa/fwl/cfwl_listitem.cpp +++ b/xfa/fwl/cfwl_listitem.cpp @@ -6,7 +6,7 @@ #include "xfa/fwl/cfwl_listitem.h" -CFWL_ListItem::CFWL_ListItem(const CFX_WideString& text) +CFWL_ListItem::CFWL_ListItem(const WideString& text) : m_dwStates(0), m_wsText(text) { m_rtItem.Reset(); } diff --git a/xfa/fwl/cfwl_listitem.h b/xfa/fwl/cfwl_listitem.h index aac67fcb51fd491afb9bf1a78b1f3d8de2fcfac4..62c3a98bd7d527579eaadd53586e73064dad0475 100644 --- a/xfa/fwl/cfwl_listitem.h +++ b/xfa/fwl/cfwl_listitem.h @@ -12,7 +12,7 @@ class CFWL_ListItem { public: - explicit CFWL_ListItem(const CFX_WideString& text); + explicit CFWL_ListItem(const WideString& text); ~CFWL_ListItem(); CFX_RectF GetRect() const { return m_rtItem; } @@ -21,12 +21,12 @@ class CFWL_ListItem { uint32_t GetStates() const { return m_dwStates; } void SetStates(uint32_t dwStates) { m_dwStates = dwStates; } - CFX_WideString GetText() const { return m_wsText; } + WideString GetText() const { return m_wsText; } private: CFX_RectF m_rtItem; uint32_t m_dwStates; - CFX_WideString m_wsText; + WideString m_wsText; }; #endif // XFA_FWL_CFWL_LISTITEM_H_ diff --git a/xfa/fwl/cfwl_message.h b/xfa/fwl/cfwl_message.h index 778e1e20797723b795dd7db3cc5493442536ad3c..99cf01b5b843cbff337b9c84d3619c45c66f5144 100644 --- a/xfa/fwl/cfwl_message.h +++ b/xfa/fwl/cfwl_message.h @@ -9,7 +9,6 @@ #include <memory> -#include "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" diff --git a/xfa/fwl/cfwl_monthcalendar.cpp b/xfa/fwl/cfwl_monthcalendar.cpp index 6882d709bfad6a789376c29d1657f4aad917e31d..08ed83f4f11c29d70343f98f56131a4bfefa8f96 100644 --- a/xfa/fwl/cfwl_monthcalendar.cpp +++ b/xfa/fwl/cfwl_monthcalendar.cpp @@ -12,7 +12,7 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_datetimepicker.h" #include "xfa/fwl/cfwl_formproxy.h" #include "xfa/fwl/cfwl_messagemouse.h" @@ -32,9 +32,9 @@ namespace { -CFX_WideString GetCapacityForDay(IFWL_ThemeProvider* pTheme, - CFWL_ThemePart& params, - uint32_t day) { +WideString GetCapacityForDay(IFWL_ThemeProvider* pTheme, + CFWL_ThemePart& params, + uint32_t day) { ASSERT(day < 7); if (day == 0) @@ -52,9 +52,9 @@ CFX_WideString GetCapacityForDay(IFWL_ThemeProvider* pTheme, return L"Sat"; } -CFX_WideString GetCapacityForMonth(IFWL_ThemeProvider* pTheme, - CFWL_ThemePart& params, - uint32_t month) { +WideString GetCapacityForMonth(IFWL_ThemeProvider* pTheme, + CFWL_ThemePart& params, + uint32_t month) { ASSERT(month < 12); if (month == 0) @@ -90,7 +90,6 @@ CFWL_MonthCalendar::CFWL_MonthCalendar( CFWL_Widget* pOuter) : CFWL_Widget(app, std::move(properties), pOuter), m_bInitialized(false), - m_pDateTime(new CFX_DateTime), m_iCurYear(2011), m_iCurMonth(1), m_iYear(2011), @@ -147,8 +146,8 @@ void CFWL_MonthCalendar::Update() { Layout(); } -void CFWL_MonthCalendar::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_MonthCalendar::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -156,20 +155,20 @@ void CFWL_MonthCalendar::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); - - DrawBackground(pGraphics, pTheme, pMatrix); - DrawHeadBK(pGraphics, pTheme, pMatrix); - DrawLButton(pGraphics, pTheme, pMatrix); - DrawRButton(pGraphics, pTheme, pMatrix); - DrawSeperator(pGraphics, pTheme, pMatrix); - DrawDatesInBK(pGraphics, pTheme, pMatrix); - DrawDatesInCircle(pGraphics, pTheme, pMatrix); - DrawCaption(pGraphics, pTheme, pMatrix); - DrawWeek(pGraphics, pTheme, pMatrix); - DrawDatesIn(pGraphics, pTheme, pMatrix); - DrawDatesOut(pGraphics, pTheme, pMatrix); - DrawToday(pGraphics, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); + + DrawBackground(pGraphics, pTheme, &matrix); + DrawHeadBK(pGraphics, pTheme, &matrix); + DrawLButton(pGraphics, pTheme, &matrix); + DrawRButton(pGraphics, pTheme, &matrix); + DrawSeperator(pGraphics, pTheme, &matrix); + DrawDatesInBK(pGraphics, pTheme, &matrix); + DrawDatesInCircle(pGraphics, pTheme, &matrix); + DrawCaption(pGraphics, pTheme, &matrix); + DrawWeek(pGraphics, pTheme, &matrix); + DrawDatesIn(pGraphics, pTheme, &matrix); + DrawDatesOut(pGraphics, pTheme, &matrix); + DrawToday(pGraphics, pTheme, &matrix); } void CFWL_MonthCalendar::SetSelect(int32_t iYear, @@ -179,7 +178,7 @@ void CFWL_MonthCalendar::SetSelect(int32_t iYear, AddSelDay(iDay); } -void CFWL_MonthCalendar::DrawBackground(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawBackground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground params; @@ -193,7 +192,7 @@ void CFWL_MonthCalendar::DrawBackground(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶ms); } -void CFWL_MonthCalendar::DrawHeadBK(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawHeadBK(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground params; @@ -207,7 +206,7 @@ void CFWL_MonthCalendar::DrawHeadBK(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶ms); } -void CFWL_MonthCalendar::DrawLButton(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawLButton(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground params; @@ -221,7 +220,7 @@ void CFWL_MonthCalendar::DrawLButton(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶ms); } -void CFWL_MonthCalendar::DrawRButton(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawRButton(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground params; @@ -235,7 +234,7 @@ void CFWL_MonthCalendar::DrawRButton(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶ms); } -void CFWL_MonthCalendar::DrawCaption(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawCaption(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeText textParam; @@ -248,14 +247,14 @@ void CFWL_MonthCalendar::DrawCaption(CFX_Graphics* pGraphics, CalcTextSize(textParam.m_wsText, m_pProperties->m_pThemeProvider, false); CalcHeadSize(); textParam.m_rtPart = m_rtHeadText; - textParam.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; - textParam.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + textParam.m_dwTTOStyles.single_line_ = true; + textParam.m_iTTOAlign = FDE_TextAlignment::kCenter; if (pMatrix) textParam.m_matrix.Concat(*pMatrix); pTheme->DrawText(&textParam); } -void CFWL_MonthCalendar::DrawSeperator(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawSeperator(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground params; @@ -269,7 +268,7 @@ void CFWL_MonthCalendar::DrawSeperator(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶ms); } -void CFWL_MonthCalendar::DrawDatesInBK(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawDatesInBK(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground params; @@ -299,7 +298,7 @@ void CFWL_MonthCalendar::DrawDatesInBK(CFX_Graphics* pGraphics, } } -void CFWL_MonthCalendar::DrawWeek(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawWeek(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeText params; @@ -307,7 +306,9 @@ void CFWL_MonthCalendar::DrawWeek(CFX_Graphics* pGraphics, params.m_iPart = CFWL_Part::Week; params.m_pGraphics = pGraphics; params.m_dwStates = CFWL_PartState_Normal; - params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + params.m_iTTOAlign = FDE_TextAlignment::kCenter; + params.m_dwTTOStyles.single_line_ = true; + CFX_RectF rtDayOfWeek; if (pMatrix) params.m_matrix.Concat(*pMatrix); @@ -319,12 +320,11 @@ void CFWL_MonthCalendar::DrawWeek(CFX_Graphics* pGraphics, params.m_rtPart = rtDayOfWeek; params.m_wsText = GetCapacityForDay(pTheme, params, i); - params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; pTheme->DrawText(¶ms); } } -void CFWL_MonthCalendar::DrawToday(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawToday(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeText params; @@ -332,20 +332,21 @@ void CFWL_MonthCalendar::DrawToday(CFX_Graphics* pGraphics, params.m_iPart = CFWL_Part::Today; params.m_pGraphics = pGraphics; params.m_dwStates = CFWL_PartState_Normal; - params.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + params.m_iTTOAlign = FDE_TextAlignment::kCenterLeft; params.m_wsText = L"Today" + GetTodayText(m_iYear, m_iMonth, m_iDay); m_szToday = CalcTextSize(params.m_wsText, m_pProperties->m_pThemeProvider, false); CalcTodaySize(); params.m_rtPart = m_rtToday; - params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + params.m_dwTTOStyles.single_line_ = true; + if (pMatrix) params.m_matrix.Concat(*pMatrix); pTheme->DrawText(¶ms); } -void CFWL_MonthCalendar::DrawDatesIn(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawDatesIn(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeText params; @@ -353,7 +354,7 @@ void CFWL_MonthCalendar::DrawDatesIn(CFX_Graphics* pGraphics, params.m_iPart = CFWL_Part::DatesIn; params.m_pGraphics = pGraphics; params.m_dwStates = CFWL_PartState_Normal; - params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + params.m_iTTOAlign = FDE_TextAlignment::kCenter; if (pMatrix) params.m_matrix.Concat(*pMatrix); @@ -365,12 +366,13 @@ void CFWL_MonthCalendar::DrawDatesIn(CFX_Graphics* pGraphics, params.m_dwStates = pDataInfo->dwStates; if (j + 1 == m_iHovered) params.m_dwStates |= CFWL_PartState_Hovered; - params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + + params.m_dwTTOStyles.single_line_ = true; pTheme->DrawText(¶ms); } } -void CFWL_MonthCalendar::DrawDatesOut(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawDatesOut(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeText params; @@ -378,13 +380,13 @@ void CFWL_MonthCalendar::DrawDatesOut(CFX_Graphics* pGraphics, params.m_iPart = CFWL_Part::DatesOut; params.m_pGraphics = pGraphics; params.m_dwStates = CFWL_PartState_Normal; - params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + params.m_iTTOAlign = FDE_TextAlignment::kCenter; if (pMatrix) params.m_matrix.Concat(*pMatrix); pTheme->DrawText(¶ms); } -void CFWL_MonthCalendar::DrawDatesInCircle(CFX_Graphics* pGraphics, +void CFWL_MonthCalendar::DrawDatesInCircle(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { if (m_iMonth != m_iCurMonth || m_iYear != m_iCurYear) @@ -415,8 +417,8 @@ CFX_SizeF CFWL_MonthCalendar::CalcSize() { CFWL_ThemePart params; params.m_pWidget = this; IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; - FX_FLOAT fMaxWeekW = 0.0f; - FX_FLOAT fMaxWeekH = 0.0f; + float fMaxWeekW = 0.0f; + float fMaxWeekH = 0.0f; for (uint32_t i = 0; i < 7; ++i) { CFX_SizeF sz = CalcTextSize(GetCapacityForDay(pTheme, params, i), @@ -425,25 +427,24 @@ CFX_SizeF CFWL_MonthCalendar::CalcSize() { fMaxWeekH = (fMaxWeekH >= sz.height) ? fMaxWeekH : sz.height; } - FX_FLOAT fDayMaxW = 0.0f; - FX_FLOAT fDayMaxH = 0.0f; + float fDayMaxW = 0.0f; + float fDayMaxH = 0.0f; for (int day = 10; day <= 31; day++) { - CFX_WideString wsDay; - wsDay.Format(L"%d", day); - CFX_SizeF sz = CalcTextSize(wsDay, m_pProperties->m_pThemeProvider, false); + CFX_SizeF sz = CalcTextSize(WideString::Format(L"%d", day), + m_pProperties->m_pThemeProvider, false); fDayMaxW = (fDayMaxW >= sz.width) ? fDayMaxW : sz.width; fDayMaxH = (fDayMaxH >= sz.height) ? fDayMaxH : sz.height; } - m_szCell.width = FX_FLOAT((fMaxWeekW >= fDayMaxW) ? (int)(fMaxWeekW + 0.5) - : (int)(fDayMaxW + 0.5)); + m_szCell.width = float((fMaxWeekW >= fDayMaxW) ? (int)(fMaxWeekW + 0.5) + : (int)(fDayMaxW + 0.5)); m_szCell.height = (fMaxWeekH >= fDayMaxH) ? fMaxWeekH : fDayMaxH; CFX_SizeF fs; fs.width = m_szCell.width * MONTHCAL_COLUMNS + MONTHCAL_HMARGIN * MONTHCAL_COLUMNS * 2 + MONTHCAL_HEADER_BTN_HMARGIN * 2; - FX_FLOAT fMonthMaxW = 0.0f; - FX_FLOAT fMonthMaxH = 0.0f; + float fMonthMaxW = 0.0f; + float fMonthMaxH = 0.0f; for (uint32_t i = 0; i < 12; ++i) { CFX_SizeF sz = CalcTextSize(GetCapacityForMonth(pTheme, params, i), @@ -460,7 +461,7 @@ CFX_SizeF CFWL_MonthCalendar::CalcSize() { m_szHead.width + MONTHCAL_HEADER_BTN_HMARGIN * 2 + m_szCell.width * 2; fs.width = std::max(fs.width, fMonthMaxW); - CFX_WideString wsToday = GetTodayText(m_iYear, m_iMonth, m_iDay); + WideString wsToday = GetTodayText(m_iYear, m_iMonth, m_iDay); m_wsToday = L"Today" + wsToday; m_szToday = CalcTextSize(wsToday, m_pProperties->m_pThemeProvider, false); m_szToday.height = (m_szToday.height >= m_szCell.height) ? m_szToday.height @@ -472,8 +473,8 @@ CFX_SizeF CFWL_MonthCalendar::CalcSize() { } void CFWL_MonthCalendar::CalcHeadSize() { - FX_FLOAT fHeadHMargin = (m_rtClient.width - m_szHead.width) / 2; - FX_FLOAT fHeadVMargin = (m_szCell.width - m_szHead.height) / 2; + float fHeadHMargin = (m_rtClient.width - m_szHead.width) / 2; + float fHeadVMargin = (m_szCell.width - m_szHead.height) / 2; m_rtHeadText = CFX_RectF(m_rtClient.left + fHeadHMargin, m_rtClient.top + MONTHCAL_HEADER_BTN_VMARGIN + MONTHCAL_VMARGIN + fHeadVMargin, @@ -527,8 +528,8 @@ void CFWL_MonthCalendar::Layout() { void CFWL_MonthCalendar::CalDateItem() { bool bNewWeek = false; int32_t iWeekOfMonth = 0; - FX_FLOAT fLeft = m_rtDates.left; - FX_FLOAT fTop = m_rtDates.top; + float fLeft = m_rtDates.left; + float fTop = m_rtDates.top; for (const auto& pDateInfo : m_arrDates) { if (bNewWeek) { iWeekOfMonth++; @@ -570,15 +571,13 @@ void CFWL_MonthCalendar::ClearDateItem() { } void CFWL_MonthCalendar::ResetDateItem() { - m_pDateTime->Set(m_iCurYear, m_iCurMonth, 1); int32_t iDays = FX_DaysInMonth(m_iCurYear, m_iCurMonth); - int32_t iDayOfWeek = m_pDateTime->GetDayOfWeek(); + int32_t iDayOfWeek = + CFX_DateTime(m_iCurYear, m_iCurMonth, 1, 0, 0, 0, 0).GetDayOfWeek(); for (int32_t i = 0; i < iDays; i++) { if (iDayOfWeek >= 7) iDayOfWeek = 0; - CFX_WideString wsDay; - wsDay.Format(L"%d", i + 1); uint32_t dwStates = 0; if (m_iYear == m_iCurYear && m_iMonth == m_iCurMonth && m_iDay == (i + 1)) dwStates |= FWL_ITEMSTATE_MCD_Flag; @@ -586,8 +585,8 @@ void CFWL_MonthCalendar::ResetDateItem() { dwStates |= FWL_ITEMSTATE_MCD_Selected; CFX_RectF rtDate; - m_arrDates.push_back(pdfium::MakeUnique<DATEINFO>(i + 1, iDayOfWeek, - dwStates, rtDate, wsDay)); + m_arrDates.push_back(pdfium::MakeUnique<DATEINFO>( + i + 1, iDayOfWeek, dwStates, rtDate, WideString::Format(L"%d", i + 1))); iDayOfWeek++; } } @@ -672,23 +671,19 @@ void CFWL_MonthCalendar::JumpToToday() { AddSelDay(m_iDay); } -CFX_WideString CFWL_MonthCalendar::GetHeadText(int32_t iYear, int32_t iMonth) { +WideString CFWL_MonthCalendar::GetHeadText(int32_t iYear, int32_t iMonth) { ASSERT(iMonth > 0 && iMonth < 13); - static const FX_WCHAR* const pMonth[] = { - L"January", L"February", L"March", L"April", - L"May", L"June", L"July", L"August", - L"September", L"October", L"November", L"December"}; - CFX_WideString wsHead; - wsHead.Format(L"%s, %d", pMonth[iMonth - 1], iYear); - return wsHead; + static const wchar_t* const pMonth[] = {L"January", L"February", L"March", + L"April", L"May", L"June", + L"July", L"August", L"September", + L"October", L"November", L"December"}; + return WideString::Format(L"%ls, %d", pMonth[iMonth - 1], iYear); } -CFX_WideString CFWL_MonthCalendar::GetTodayText(int32_t iYear, - int32_t iMonth, - int32_t iDay) { - CFX_WideString wsToday; - wsToday.Format(L", %d/%d/%d", iDay, iMonth, iYear); - return wsToday; +WideString CFWL_MonthCalendar::GetTodayText(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + return WideString::Format(L", %d/%d/%d", iDay, iMonth, iYear); } int32_t CFWL_MonthCalendar::GetDayAtPoint(const CFX_PointF& point) const { @@ -746,9 +741,9 @@ void CFWL_MonthCalendar::OnProcessMessage(CFWL_Message* pMessage) { CFWL_Widget::OnProcessMessage(pMessage); } -void CFWL_MonthCalendar::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_MonthCalendar::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_MonthCalendar::OnLButtonDown(CFWL_MessageMouse* pMsg) { @@ -891,7 +886,7 @@ CFWL_MonthCalendar::DATEINFO::DATEINFO(int32_t day, int32_t dayofweek, uint32_t dwSt, CFX_RectF rc, - CFX_WideString& wsday) + const WideString& wsday) : iDay(day), iDayOfWeek(dayofweek), dwStates(dwSt), diff --git a/xfa/fwl/cfwl_monthcalendar.h b/xfa/fwl/cfwl_monthcalendar.h index a110ee829708aaa52408f50d8a74c86cf9331a10..7b68600bbce25fd098042e1b678b2094e6c408fc 100644 --- a/xfa/fwl/cfwl_monthcalendar.h +++ b/xfa/fwl/cfwl_monthcalendar.h @@ -10,12 +10,11 @@ #include <memory> #include <vector> -#include "xfa/fgas/localization/fgas_datetime.h" +#include "core/fxcrt/cfx_datetime.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/cfwl_widgetproperties.h" -#define FWL_ITEMSTATE_MCD_Nomal 0 #define FWL_ITEMSTATE_MCD_Flag (1L << 0) #define FWL_ITEMSTATE_MCD_Selected (1L << 1) @@ -33,10 +32,10 @@ class CFWL_MonthCalendar : public CFWL_Widget { FWL_Type GetClassID() const override; CFX_RectF GetAutosizedWidgetRect() override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; void SetSelect(int32_t iYear, int32_t iMonth, int32_t iDay); @@ -80,50 +79,50 @@ class CFWL_MonthCalendar : public CFWL_Widget { int32_t dayofweek, uint32_t dwSt, CFX_RectF rc, - CFX_WideString& wsday); + const WideString& wsday); ~DATEINFO(); int32_t iDay; int32_t iDayOfWeek; uint32_t dwStates; CFX_RectF rect; - CFX_WideString wsDay; + WideString wsDay; }; - void DrawBackground(CFX_Graphics* pGraphics, + void DrawBackground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawHeadBK(CFX_Graphics* pGraphics, + void DrawHeadBK(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawLButton(CFX_Graphics* pGraphics, + void DrawLButton(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawRButton(CFX_Graphics* pGraphics, + void DrawRButton(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawCaption(CFX_Graphics* pGraphics, + void DrawCaption(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawSeperator(CFX_Graphics* pGraphics, + void DrawSeperator(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawDatesInBK(CFX_Graphics* pGraphics, + void DrawDatesInBK(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawWeek(CFX_Graphics* pGraphics, + void DrawWeek(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawToday(CFX_Graphics* pGraphics, + void DrawToday(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawDatesIn(CFX_Graphics* pGraphics, + void DrawDatesIn(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawDatesOut(CFX_Graphics* pGraphics, + void DrawDatesOut(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); - void DrawDatesInCircle(CFX_Graphics* pGraphics, + void DrawDatesInCircle(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); CFX_SizeF CalcSize(); @@ -141,8 +140,8 @@ class CFWL_MonthCalendar : public CFWL_Widget { void RemoveSelDay(); void AddSelDay(int32_t iDay); void JumpToToday(); - CFX_WideString GetHeadText(int32_t iYear, int32_t iMonth); - CFX_WideString GetTodayText(int32_t iYear, int32_t iMonth, int32_t iDay); + WideString GetHeadText(int32_t iYear, int32_t iMonth); + WideString GetTodayText(int32_t iYear, int32_t iMonth, int32_t iDay); int32_t GetDayAtPoint(const CFX_PointF& point) const; CFX_RectF GetDayRect(int32_t iDay); void OnLButtonDown(CFWL_MessageMouse* pMsg); @@ -163,9 +162,8 @@ class CFWL_MonthCalendar : public CFWL_Widget { CFX_RectF m_rtTodayFlag; CFX_RectF m_rtWeekNum; CFX_RectF m_rtWeekNumSep; - CFX_WideString m_wsHead; - CFX_WideString m_wsToday; - std::unique_ptr<CFX_DateTime> m_pDateTime; + WideString m_wsHead; + WideString m_wsToday; std::vector<std::unique_ptr<DATEINFO>> m_arrDates; int32_t m_iCurYear; int32_t m_iCurMonth; diff --git a/xfa/fwl/cfwl_notedriver.cpp b/xfa/fwl/cfwl_notedriver.cpp index 8feb0fb4e565617b115b49e1c0b6f2cff580844d..9a19f4b8a7b63292bfe54e341de192111ee6d59a 100644 --- a/xfa/fwl/cfwl_notedriver.cpp +++ b/xfa/fwl/cfwl_notedriver.cpp @@ -9,7 +9,7 @@ #include <algorithm> #include <utility> -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" #include "xfa/fwl/cfwl_app.h" @@ -31,18 +31,12 @@ CFWL_NoteDriver::CFWL_NoteDriver() PushNoteLoop(m_pNoteLoop.get()); } -CFWL_NoteDriver::~CFWL_NoteDriver() { - ClearEventTargets(true); -} +CFWL_NoteDriver::~CFWL_NoteDriver() {} void CFWL_NoteDriver::SendEvent(CFWL_Event* pNote) { - if (m_eventTargets.empty()) - return; - for (const auto& pair : m_eventTargets) { - CFWL_EventTarget* pEventTarget = pair.second; - if (pEventTarget && !pEventTarget->IsInvalid()) - pEventTarget->ProcessEvent(pNote); + if (pair.second->IsValid()) + pair.second->ProcessEvent(pNote); } } @@ -56,7 +50,7 @@ void CFWL_NoteDriver::RegisterEventTarget(CFWL_Widget* pListener, pListener->SetEventKey(key); } if (!m_eventTargets[key]) - m_eventTargets[key] = new CFWL_EventTarget(pListener); + m_eventTargets[key] = pdfium::MakeUnique<CFWL_EventTarget>(pListener); m_eventTargets[key]->SetEventSource(pEventSource); } @@ -112,15 +106,14 @@ bool CFWL_NoteDriver::SetFocus(CFWL_Widget* pFocus) { } void CFWL_NoteDriver::Run() { -#if (_FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_WIN32_DESKTOP_ || \ - _FX_OS_ == _FX_WIN64_) +#if _FX_OS_ == _FX_OS_LINUX_ || _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ for (;;) { CFWL_NoteLoop* pTopLoop = GetTopLoop(); if (!pTopLoop || !pTopLoop->ContinueModal()) break; UnqueueMessageAndProcess(pTopLoop); } -#endif +#endif // _FX_OS_ == _FX_OS_LINUX_ || _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ } void CFWL_NoteDriver::NotifyTargetHide(CFWL_Widget* pNoteTarget) { @@ -294,7 +287,7 @@ bool CFWL_NoteDriver::DoKillFocus(CFWL_Message* pMessage, bool CFWL_NoteDriver::DoKey(CFWL_Message* pMessage, CFWL_Widget* pMessageForm) { CFWL_MessageKey* pMsg = static_cast<CFWL_MessageKey*>(pMessage); -#if (_FX_OS_ != _FX_MACOSX_) +#if (_FX_OS_ != _FX_OS_MACOSX_) if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown && pMsg->m_dwKeyCode == FWL_VKEY_Tab) { CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr(); @@ -445,13 +438,11 @@ CFWL_Widget* CFWL_NoteDriver::GetMessageForm(CFWL_Widget* pDstTarget) { return pMessageForm; } -void CFWL_NoteDriver::ClearEventTargets(bool bRemoveAll) { +void CFWL_NoteDriver::ClearEventTargets() { auto it = m_eventTargets.begin(); while (it != m_eventTargets.end()) { auto old = it++; - if (old->second && (bRemoveAll || old->second->IsInvalid())) { - delete old->second; + if (!old->second->IsValid()) m_eventTargets.erase(old); - } } } diff --git a/xfa/fwl/cfwl_notedriver.h b/xfa/fwl/cfwl_notedriver.h index e177494ff144eee1d7066318036f1583c89c5922..0db482ecbc79d0657201de5a33d84beab784b4ab 100644 --- a/xfa/fwl/cfwl_notedriver.h +++ b/xfa/fwl/cfwl_notedriver.h @@ -8,13 +8,13 @@ #define XFA_FWL_CFWL_NOTEDRIVER_H_ #include <deque> +#include <map> #include <memory> -#include <unordered_map> #include <vector> #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxgraphics/cfx_graphics.h" +#include "xfa/fxgraphics/cxfa_graphics.h" class CFWL_EventTarget; class CFWL_NoteLoop; @@ -30,7 +30,7 @@ class CFWL_NoteDriver { void RegisterEventTarget(CFWL_Widget* pListener, CFWL_Widget* pEventSource); void UnregisterEventTarget(CFWL_Widget* pListener); - void ClearEventTargets(bool bRemoveAll); + void ClearEventTargets(); CFWL_NoteLoop* GetTopLoop() const; void PushNoteLoop(CFWL_NoteLoop* pNoteLoop); @@ -69,7 +69,7 @@ class CFWL_NoteDriver { std::vector<CFWL_Widget*> m_Forms; std::deque<std::unique_ptr<CFWL_Message>> m_NoteQueue; std::vector<CFWL_NoteLoop*> m_NoteLoopQueue; - std::unordered_map<uint32_t, CFWL_EventTarget*> m_eventTargets; + std::map<uint32_t, std::unique_ptr<CFWL_EventTarget>> m_eventTargets; CFWL_Widget* m_pHover; CFWL_Widget* m_pFocus; CFWL_Widget* m_pGrab; diff --git a/xfa/fwl/cfwl_picturebox.cpp b/xfa/fwl/cfwl_picturebox.cpp index 8c200e0494abb9248cf9049b18ffbf29933526c0..637de94e7ddb54308b9cbf437452b4351bf5cb54 100644 --- a/xfa/fwl/cfwl_picturebox.cpp +++ b/xfa/fwl/cfwl_picturebox.cpp @@ -32,8 +32,8 @@ void CFWL_PictureBox::Update() { m_rtClient = GetClientRect(); } -void CFWL_PictureBox::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_PictureBox::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -41,10 +41,10 @@ void CFWL_PictureBox::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = GetAvailableTheme(); if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); } -void CFWL_PictureBox::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_PictureBox::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } diff --git a/xfa/fwl/cfwl_picturebox.h b/xfa/fwl/cfwl_picturebox.h index 743ea1dc6da0676a5c5a8e30cab18a09f3a573ef..363db8a291c71ff66ba3704c5055fe442ed88a1d 100644 --- a/xfa/fwl/cfwl_picturebox.h +++ b/xfa/fwl/cfwl_picturebox.h @@ -23,9 +23,9 @@ class CFWL_PictureBox : public CFWL_Widget { // CFWL_Widget FWL_Type GetClassID() const override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; private: CFX_RectF m_rtClient; diff --git a/xfa/fwl/cfwl_pushbutton.cpp b/xfa/fwl/cfwl_pushbutton.cpp index fe4c3f621ac6e8f1c9cd5df28fa53215b970aa7e..a912108278644434b431dae1d591d4ea1155102f 100644 --- a/xfa/fwl/cfwl_pushbutton.cpp +++ b/xfa/fwl/cfwl_pushbutton.cpp @@ -10,7 +10,7 @@ #include <utility> #include "third_party/base/ptr_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_eventmouse.h" #include "xfa/fwl/cfwl_messagekey.h" @@ -22,9 +22,7 @@ CFWL_PushButton::CFWL_PushButton(const CFWL_App* app) : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr), - m_bBtnDown(false), - m_dwTTOStyles(FDE_TTOSTYLE_SingleLine), - m_iTTOAlign(FDE_TTOALIGNMENT_Center) {} + m_bBtnDown(false) {} CFWL_PushButton::~CFWL_PushButton() {} @@ -46,13 +44,12 @@ void CFWL_PushButton::Update() { if (!m_pProperties->m_pThemeProvider) m_pProperties->m_pThemeProvider = GetAvailableTheme(); - UpdateTextOutStyles(); m_rtClient = GetClientRect(); m_rtCaption = m_rtClient; } -void CFWL_PushButton::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_PushButton::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -60,12 +57,12 @@ void CFWL_PushButton::DrawWidget(CFX_Graphics* pGraphics, if (HasBorder()) { DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider, - pMatrix); + matrix); } - DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix); + DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, &matrix); } -void CFWL_PushButton::DrawBkground(CFX_Graphics* pGraphics, +void CFWL_PushButton::DrawBkground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground param; @@ -94,11 +91,6 @@ uint32_t CFWL_PushButton::GetPartStates() { return dwStates; } -void CFWL_PushButton::UpdateTextOutStyles() { - m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft; - m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; -} - void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) { if (!pMessage) return; @@ -144,9 +136,9 @@ void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) { CFWL_Widget::OnProcessMessage(pMessage); } -void CFWL_PushButton::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_PushButton::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_PushButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { diff --git a/xfa/fwl/cfwl_pushbutton.h b/xfa/fwl/cfwl_pushbutton.h index f7323eb46b048f7a5974f089ecfcd98250bcb6a4..5c509fb50377017375c56217c4056d01c6ac702d 100644 --- a/xfa/fwl/cfwl_pushbutton.h +++ b/xfa/fwl/cfwl_pushbutton.h @@ -28,13 +28,13 @@ class CFWL_PushButton : public CFWL_Widget { FWL_Type GetClassID() const override; void SetStates(uint32_t dwStates) override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; private: - void DrawBkground(CFX_Graphics* pGraphics, + void DrawBkground(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); uint32_t GetPartStates(); @@ -49,8 +49,6 @@ class CFWL_PushButton : public CFWL_Widget { CFX_RectF m_rtClient; CFX_RectF m_rtCaption; bool m_bBtnDown; - uint32_t m_dwTTOStyles; - int32_t m_iTTOAlign; }; #endif // XFA_FWL_CFWL_PUSHBUTTON_H_ diff --git a/xfa/fwl/cfwl_scrollbar.cpp b/xfa/fwl/cfwl_scrollbar.cpp index 1da2674550403c32b8d9c5280641a886d56be0c2..f723124e86bc3c2da9ee5c24f062b86277a89ff9 100644 --- a/xfa/fwl/cfwl_scrollbar.cpp +++ b/xfa/fwl/cfwl_scrollbar.cpp @@ -11,6 +11,7 @@ #include <utility> #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" #include "xfa/fwl/cfwl_messagemouse.h" #include "xfa/fwl/cfwl_messagemousewheel.h" #include "xfa/fwl/cfwl_notedriver.h" @@ -73,8 +74,8 @@ void CFWL_ScrollBar::Update() { Layout(); } -void CFWL_ScrollBar::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { +void CFWL_ScrollBar::DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pGraphics) return; if (!m_pProperties->m_pThemeProvider) @@ -82,28 +83,28 @@ void CFWL_ScrollBar::DrawWidget(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); - DrawTrack(pGraphics, pTheme, true, pMatrix); - DrawTrack(pGraphics, pTheme, false, pMatrix); - DrawArrowBtn(pGraphics, pTheme, true, pMatrix); - DrawArrowBtn(pGraphics, pTheme, false, pMatrix); - DrawThumb(pGraphics, pTheme, pMatrix); + DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix); + DrawTrack(pGraphics, pTheme, true, &matrix); + DrawTrack(pGraphics, pTheme, false, &matrix); + DrawArrowBtn(pGraphics, pTheme, true, &matrix); + DrawArrowBtn(pGraphics, pTheme, false, &matrix); + DrawThumb(pGraphics, pTheme, &matrix); } -void CFWL_ScrollBar::SetTrackPos(FX_FLOAT fTrackPos) { +void CFWL_ScrollBar::SetTrackPos(float fTrackPos) { m_fTrackPos = fTrackPos; m_rtThumb = CalcThumbButtonRect(m_rtThumb); m_rtMinTrack = CalcMinTrackRect(m_rtMinTrack); m_rtMaxTrack = CalcMaxTrackRect(m_rtMaxTrack); } -bool CFWL_ScrollBar::DoScroll(CFWL_EventScroll::Code dwCode, FX_FLOAT fPos) { +bool CFWL_ScrollBar::DoScroll(CFWL_EventScroll::Code dwCode, float fPos) { if (dwCode == CFWL_EventScroll::Code::None) return false; return OnScroll(dwCode, fPos); } -void CFWL_ScrollBar::DrawTrack(CFX_Graphics* pGraphics, +void CFWL_ScrollBar::DrawTrack(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, bool bLower, const CFX_Matrix* pMatrix) { @@ -119,7 +120,7 @@ void CFWL_ScrollBar::DrawTrack(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶m); } -void CFWL_ScrollBar::DrawArrowBtn(CFX_Graphics* pGraphics, +void CFWL_ScrollBar::DrawArrowBtn(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, bool bMinBtn, const CFX_Matrix* pMatrix) { @@ -136,7 +137,7 @@ void CFWL_ScrollBar::DrawArrowBtn(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶m); } -void CFWL_ScrollBar::DrawThumb(CFX_Graphics* pGraphics, +void CFWL_ScrollBar::DrawThumb(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { CFWL_ThemeBackground param; @@ -164,7 +165,7 @@ void CFWL_ScrollBar::Layout() { void CFWL_ScrollBar::CalcButtonLen() { m_fButtonLen = IsVertical() ? m_rtClient.width : m_rtClient.height; - FX_FLOAT fLength = IsVertical() ? m_rtClient.height : m_rtClient.width; + float fLength = IsVertical() ? m_rtClient.height : m_rtClient.width; if (fLength < m_fButtonLen * 2) { m_fButtonLen = fLength / 2; m_bMinSize = true; @@ -199,7 +200,7 @@ CFX_RectF CFWL_ScrollBar::CalcThumbButtonRect(const CFX_RectF& rtThumb) { return rect; } - FX_FLOAT fRange = m_fRangeMax - m_fRangeMin; + float fRange = m_fRangeMax - m_fRangeMin; if (fRange < 0) { if (IsVertical()) { return CFX_RectF(m_rtClient.left, m_rtMaxBtn.bottom(), m_rtClient.width, @@ -209,22 +210,21 @@ CFX_RectF CFWL_ScrollBar::CalcThumbButtonRect(const CFX_RectF& rtThumb) { } CFX_RectF rtClient = m_rtClient; - FX_FLOAT fLength = IsVertical() ? rtClient.height : rtClient.width; - FX_FLOAT fSize = m_fButtonLen; + float fLength = IsVertical() ? rtClient.height : rtClient.width; + float fSize = m_fButtonLen; fLength -= fSize * 2.0f; if (fLength < fSize) fLength = 0.0f; - FX_FLOAT fThumbSize = fLength * fLength / (fRange + fLength); + float fThumbSize = fLength * fLength / (fRange + fLength); fThumbSize = std::max(fThumbSize, kMinThumbSize); - FX_FLOAT fDiff = std::max(fLength - fThumbSize, 0.0f); - FX_FLOAT fTrackPos = - std::max(std::min(m_fTrackPos, m_fRangeMax), m_fRangeMin); + float fDiff = std::max(fLength - fThumbSize, 0.0f); + float fTrackPos = pdfium::clamp(m_fTrackPos, m_fRangeMin, m_fRangeMax); if (!fRange) return rect; - FX_FLOAT iPos = fSize + fDiff * (fTrackPos - m_fRangeMin) / fRange; + float iPos = fSize + fDiff * (fTrackPos - m_fRangeMin) / fRange; rect.left = rtClient.left; rect.top = rtClient.top; if (IsVertical()) { @@ -264,20 +264,20 @@ CFX_RectF CFWL_ScrollBar::CalcMaxTrackRect(const CFX_RectF& rtMaxRect) { return CFX_RectF(rtMaxRect.TopLeft(), 0, 0); if (IsVertical()) { - FX_FLOAT iy = (m_rtThumb.top + m_rtThumb.bottom()) / 2; + float iy = (m_rtThumb.top + m_rtThumb.bottom()) / 2; return CFX_RectF(m_rtClient.left, iy, m_rtClient.width, m_rtClient.bottom() - iy); } - FX_FLOAT ix = (m_rtThumb.left + m_rtThumb.right()) / 2; + float ix = (m_rtThumb.left + m_rtThumb.right()) / 2; return CFX_RectF(ix, m_rtClient.top, m_rtClient.height - ix, m_rtClient.height); } -FX_FLOAT CFWL_ScrollBar::GetTrackPointPos(const CFX_PointF& point) { +float CFWL_ScrollBar::GetTrackPointPos(const CFX_PointF& point) { CFX_PointF diff = point - m_cpTrackPoint; - FX_FLOAT fRange = m_fRangeMax - m_fRangeMin; - FX_FLOAT fPos; + float fRange = m_fRangeMax - m_fRangeMin; + float fPos; if (IsVertical()) { fPos = fRange * diff.y / @@ -288,7 +288,7 @@ FX_FLOAT CFWL_ScrollBar::GetTrackPointPos(const CFX_PointF& point) { } fPos += m_fLastTrackPos; - return std::min(std::max(fPos, m_fRangeMin), m_fRangeMax); + return pdfium::clamp(fPos, m_fRangeMin, m_fRangeMax); } bool CFWL_ScrollBar::SendEvent() { @@ -317,7 +317,7 @@ bool CFWL_ScrollBar::SendEvent() { return true; } -bool CFWL_ScrollBar::OnScroll(CFWL_EventScroll::Code dwCode, FX_FLOAT fPos) { +bool CFWL_ScrollBar::OnScroll(CFWL_EventScroll::Code dwCode, float fPos) { CFWL_EventScroll ev(this); ev.m_iScrollCode = dwCode; ev.m_fPos = fPos; @@ -355,9 +355,9 @@ void CFWL_ScrollBar::OnProcessMessage(CFWL_Message* pMessage) { } } -void CFWL_ScrollBar::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); +void CFWL_ScrollBar::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + DrawWidget(pGraphics, matrix); } void CFWL_ScrollBar::OnLButtonDown(const CFX_PointF& point) { @@ -485,8 +485,7 @@ void CFWL_ScrollBar::DoMouseHover(int32_t iItem, CFWL_ScrollBar::Timer::Timer(CFWL_ScrollBar* pToolTip) : CFWL_Timer(pToolTip) {} void CFWL_ScrollBar::Timer::Run(CFWL_TimerInfo* pTimerInfo) { - CFWL_ScrollBar* pButton = static_cast<CFWL_ScrollBar*>(m_pWidget); - + CFWL_ScrollBar* pButton = static_cast<CFWL_ScrollBar*>(m_pWidget.Get()); if (pButton->m_pTimerInfo) pButton->m_pTimerInfo->StopTimer(); diff --git a/xfa/fwl/cfwl_scrollbar.h b/xfa/fwl/cfwl_scrollbar.h index 6a67fa8687dc096d61744806d7f720973d0e73e2..b2523a6e150a6d31cc3f60634e0bbd543df78182 100644 --- a/xfa/fwl/cfwl_scrollbar.h +++ b/xfa/fwl/cfwl_scrollbar.h @@ -30,28 +30,28 @@ class CFWL_ScrollBar : public CFWL_Widget { // CFWL_Widget FWL_Type GetClassID() const override; void Update() override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; + void DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) override; void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; - void GetRange(FX_FLOAT* fMin, FX_FLOAT* fMax) const { + void GetRange(float* fMin, float* fMax) const { ASSERT(fMin); ASSERT(fMax); *fMin = m_fRangeMin; *fMax = m_fRangeMax; } - void SetRange(FX_FLOAT fMin, FX_FLOAT fMax) { + void SetRange(float fMin, float fMax) { m_fRangeMin = fMin; m_fRangeMax = fMax; } - FX_FLOAT GetPageSize() const { return m_fPageSize; } - void SetPageSize(FX_FLOAT fPageSize) { m_fPageSize = fPageSize; } - FX_FLOAT GetStepSize() const { return m_fStepSize; } - void SetStepSize(FX_FLOAT fStepSize) { m_fStepSize = fStepSize; } - FX_FLOAT GetPos() const { return m_fPos; } - void SetPos(FX_FLOAT fPos) { m_fPos = fPos; } - void SetTrackPos(FX_FLOAT fTrackPos); + float GetPageSize() const { return m_fPageSize; } + void SetPageSize(float fPageSize) { m_fPageSize = fPageSize; } + float GetStepSize() const { return m_fStepSize; } + void SetStepSize(float fStepSize) { m_fStepSize = fStepSize; } + float GetPos() const { return m_fPos; } + void SetPos(float fPos) { m_fPos = fPos; } + void SetTrackPos(float fTrackPos); private: class Timer : public CFWL_Timer { @@ -66,15 +66,15 @@ class CFWL_ScrollBar : public CFWL_Widget { bool IsVertical() const { return !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_SCB_Vert); } - void DrawTrack(CFX_Graphics* pGraphics, + void DrawTrack(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, bool bLower, const CFX_Matrix* pMatrix); - void DrawArrowBtn(CFX_Graphics* pGraphics, + void DrawArrowBtn(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, bool bMinBtn, const CFX_Matrix* pMatrix); - void DrawThumb(CFX_Graphics* pGraphics, + void DrawThumb(CXFA_Graphics* pGraphics, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); void Layout(); @@ -84,16 +84,16 @@ class CFWL_ScrollBar : public CFWL_Widget { CFX_RectF CalcThumbButtonRect(const CFX_RectF& rtThumbRect); CFX_RectF CalcMinTrackRect(const CFX_RectF& rtMinRect); CFX_RectF CalcMaxTrackRect(const CFX_RectF& rtMaxRect); - FX_FLOAT GetTrackPointPos(const CFX_PointF& point); + float GetTrackPointPos(const CFX_PointF& point); bool SendEvent(); - bool OnScroll(CFWL_EventScroll::Code dwCode, FX_FLOAT fPos); + bool OnScroll(CFWL_EventScroll::Code dwCode, float fPos); void OnLButtonDown(const CFX_PointF& point); void OnLButtonUp(const CFX_PointF& point); void OnMouseMove(const CFX_PointF& point); void OnMouseLeave(); void OnMouseWheel(const CFX_PointF& delta); - bool DoScroll(CFWL_EventScroll::Code dwCode, FX_FLOAT fPos); + bool DoScroll(CFWL_EventScroll::Code dwCode, float fPos); void DoMouseDown(int32_t iItem, const CFX_RectF& rtItem, int32_t& iState, @@ -110,22 +110,22 @@ class CFWL_ScrollBar : public CFWL_Widget { void DoMouseHover(int32_t iItem, const CFX_RectF& rtItem, int32_t& iState); CFWL_TimerInfo* m_pTimerInfo; - FX_FLOAT m_fRangeMin; - FX_FLOAT m_fRangeMax; - FX_FLOAT m_fPageSize; - FX_FLOAT m_fStepSize; - FX_FLOAT m_fPos; - FX_FLOAT m_fTrackPos; + float m_fRangeMin; + float m_fRangeMax; + float m_fPageSize; + float m_fStepSize; + float m_fPos; + float m_fTrackPos; int32_t m_iMinButtonState; int32_t m_iMaxButtonState; int32_t m_iThumbButtonState; int32_t m_iMinTrackState; int32_t m_iMaxTrackState; - FX_FLOAT m_fLastTrackPos; + float m_fLastTrackPos; CFX_PointF m_cpTrackPoint; int32_t m_iMouseWheel; bool m_bMouseDown; - FX_FLOAT m_fButtonLen; + float m_fButtonLen; bool m_bMinSize; CFX_RectF m_rtClient; CFX_RectF m_rtThumb; diff --git a/xfa/fwl/cfwl_spinbutton.cpp b/xfa/fwl/cfwl_spinbutton.cpp deleted file mode 100644 index 6e58b69baf9a7c6767799db8660aa4fe8b29b865..0000000000000000000000000000000000000000 --- a/xfa/fwl/cfwl_spinbutton.cpp +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fwl/cfwl_spinbutton.h" - -#include <memory> -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "xfa/fwl/cfwl_event.h" -#include "xfa/fwl/cfwl_messagekey.h" -#include "xfa/fwl/cfwl_messagemouse.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_themebackground.h" -#include "xfa/fwl/cfwl_timerinfo.h" -#include "xfa/fwl/cfwl_widgetproperties.h" -#include "xfa/fwl/ifwl_themeprovider.h" - -namespace { -const int kElapseTime = 200; - -} // namespace - -CFWL_SpinButton::CFWL_SpinButton( - const CFWL_App* app, - std::unique_ptr<CFWL_WidgetProperties> properties) - : CFWL_Widget(app, std::move(properties), nullptr), - m_dwUpState(CFWL_PartState_Normal), - m_dwDnState(CFWL_PartState_Normal), - m_iButtonIndex(0), - m_bLButtonDwn(false), - m_pTimerInfo(nullptr), - m_Timer(this) { - m_rtClient.Reset(); - m_rtUpButton.Reset(); - m_rtDnButton.Reset(); - m_pProperties->m_dwStyleExes |= FWL_STYLEEXE_SPB_Vert; -} - -CFWL_SpinButton::~CFWL_SpinButton() {} - -FWL_Type CFWL_SpinButton::GetClassID() const { - return FWL_Type::SpinButton; -} - -void CFWL_SpinButton::Update() { - if (IsLocked()) - return; - - m_rtClient = GetClientRect(); - if (m_pProperties->m_dwStyleExes & FWL_STYLEEXE_SPB_Vert) { - m_rtUpButton = CFX_RectF(m_rtClient.top, m_rtClient.left, m_rtClient.width, - m_rtClient.height / 2); - m_rtDnButton = - CFX_RectF(m_rtClient.left, m_rtClient.top + m_rtClient.height / 2, - m_rtClient.width, m_rtClient.height / 2); - } else { - m_rtUpButton = CFX_RectF(m_rtClient.TopLeft(), m_rtClient.width / 2, - m_rtClient.height); - m_rtDnButton = - CFX_RectF(m_rtClient.left + m_rtClient.width / 2, m_rtClient.top, - m_rtClient.width / 2, m_rtClient.height); - } -} - -FWL_WidgetHit CFWL_SpinButton::HitTest(const CFX_PointF& point) { - if (m_rtClient.Contains(point)) - return FWL_WidgetHit::Client; - if (HasBorder() && (m_rtClient.Contains(point))) - return FWL_WidgetHit::Border; - if (m_rtUpButton.Contains(point)) - return FWL_WidgetHit::UpButton; - if (m_rtDnButton.Contains(point)) - return FWL_WidgetHit::DownButton; - return FWL_WidgetHit::Unknown; -} - -void CFWL_SpinButton::DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - if (!pGraphics) - return; - - CFX_RectF rtClip(m_rtClient); - if (pMatrix) - pMatrix->TransformRect(rtClip); - - IFWL_ThemeProvider* pTheme = GetAvailableTheme(); - if (HasBorder()) - DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); - - DrawUpButton(pGraphics, pTheme, pMatrix); - DrawDownButton(pGraphics, pTheme, pMatrix); -} - -void CFWL_SpinButton::DisableButton() { - m_dwDnState = CFWL_PartState_Disabled; -} - -bool CFWL_SpinButton::IsUpButtonEnabled() { - return m_dwUpState != CFWL_PartState_Disabled; -} - -bool CFWL_SpinButton::IsDownButtonEnabled() { - return m_dwDnState != CFWL_PartState_Disabled; -} - -void CFWL_SpinButton::DrawUpButton(CFX_Graphics* pGraphics, - IFWL_ThemeProvider* pTheme, - const CFX_Matrix* pMatrix) { - CFWL_ThemeBackground params; - params.m_pWidget = this; - params.m_iPart = CFWL_Part::UpButton; - params.m_pGraphics = pGraphics; - params.m_dwStates = m_dwUpState + 1; - if (pMatrix) - params.m_matrix.Concat(*pMatrix); - - params.m_rtPart = m_rtUpButton; - pTheme->DrawBackground(¶ms); -} - -void CFWL_SpinButton::DrawDownButton(CFX_Graphics* pGraphics, - IFWL_ThemeProvider* pTheme, - const CFX_Matrix* pMatrix) { - CFWL_ThemeBackground params; - params.m_pWidget = this; - params.m_iPart = CFWL_Part::DownButton; - params.m_pGraphics = pGraphics; - params.m_dwStates = m_dwDnState + 1; - if (pMatrix) - params.m_matrix.Concat(*pMatrix); - - params.m_rtPart = m_rtDnButton; - pTheme->DrawBackground(¶ms); -} - -void CFWL_SpinButton::OnProcessMessage(CFWL_Message* pMessage) { - if (!pMessage) - return; - - switch (pMessage->GetType()) { - case CFWL_Message::Type::SetFocus: { - OnFocusChanged(pMessage, true); - break; - } - case CFWL_Message::Type::KillFocus: { - OnFocusChanged(pMessage, false); - break; - } - case CFWL_Message::Type::Mouse: { - CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage); - switch (pMsg->m_dwCmd) { - case FWL_MouseCommand::LeftButtonDown: - OnLButtonDown(pMsg); - break; - case FWL_MouseCommand::LeftButtonUp: - OnLButtonUp(pMsg); - break; - case FWL_MouseCommand::Move: - OnMouseMove(pMsg); - break; - case FWL_MouseCommand::Leave: - OnMouseLeave(pMsg); - break; - default: - break; - } - break; - } - case CFWL_Message::Type::Key: { - CFWL_MessageKey* pKey = static_cast<CFWL_MessageKey*>(pMessage); - if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown) - OnKeyDown(pKey); - break; - } - default: - break; - } - CFWL_Widget::OnProcessMessage(pMessage); -} - -void CFWL_SpinButton::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - DrawWidget(pGraphics, pMatrix); -} - -void CFWL_SpinButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { - if (bSet) - m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused); - else - m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused); - - RepaintRect(m_rtClient); -} - -void CFWL_SpinButton::OnLButtonDown(CFWL_MessageMouse* pMsg) { - m_bLButtonDwn = true; - SetGrab(true); - SetFocus(true); - - bool bUpPress = m_rtUpButton.Contains(pMsg->m_pos) && IsUpButtonEnabled(); - bool bDnPress = m_rtDnButton.Contains(pMsg->m_pos) && IsDownButtonEnabled(); - if (!bUpPress && !bDnPress) - return; - if (bUpPress) { - m_iButtonIndex = 0; - m_dwUpState = CFWL_PartState_Pressed; - } - if (bDnPress) { - m_iButtonIndex = 1; - m_dwDnState = CFWL_PartState_Pressed; - } - - CFWL_Event wmPosChanged(CFWL_Event::Type::Click, this); - DispatchEvent(&wmPosChanged); - - RepaintRect(bUpPress ? m_rtUpButton : m_rtDnButton); - m_pTimerInfo = m_Timer.StartTimer(kElapseTime, true); -} - -void CFWL_SpinButton::OnLButtonUp(CFWL_MessageMouse* pMsg) { - if (m_pProperties->m_dwStates & CFWL_PartState_Disabled) - return; - - m_bLButtonDwn = false; - SetGrab(false); - SetFocus(false); - if (m_pTimerInfo) { - m_pTimerInfo->StopTimer(); - m_pTimerInfo = nullptr; - } - bool bRepaint = false; - CFX_RectF rtInvalidate; - if (m_dwUpState == CFWL_PartState_Pressed && IsUpButtonEnabled()) { - m_dwUpState = CFWL_PartState_Normal; - bRepaint = true; - rtInvalidate = m_rtUpButton; - } else if (m_dwDnState == CFWL_PartState_Pressed && IsDownButtonEnabled()) { - m_dwDnState = CFWL_PartState_Normal; - bRepaint = true; - rtInvalidate = m_rtDnButton; - } - if (bRepaint) - RepaintRect(rtInvalidate); -} - -void CFWL_SpinButton::OnMouseMove(CFWL_MessageMouse* pMsg) { - if (m_bLButtonDwn) - return; - - bool bRepaint = false; - CFX_RectF rtInvlidate; - if (m_rtUpButton.Contains(pMsg->m_pos)) { - if (IsUpButtonEnabled()) { - if (m_dwUpState == CFWL_PartState_Hovered) { - m_dwUpState = CFWL_PartState_Hovered; - bRepaint = true; - rtInvlidate = m_rtUpButton; - } - if (m_dwDnState != CFWL_PartState_Normal && IsDownButtonEnabled()) { - m_dwDnState = CFWL_PartState_Normal; - if (bRepaint) - rtInvlidate.Union(m_rtDnButton); - else - rtInvlidate = m_rtDnButton; - - bRepaint = true; - } - } - if (!IsDownButtonEnabled()) - DisableButton(); - - } else if (m_rtDnButton.Contains(pMsg->m_pos)) { - if (IsDownButtonEnabled()) { - if (m_dwDnState != CFWL_PartState_Hovered) { - m_dwDnState = CFWL_PartState_Hovered; - bRepaint = true; - rtInvlidate = m_rtDnButton; - } - if (m_dwUpState != CFWL_PartState_Normal && IsUpButtonEnabled()) { - m_dwUpState = CFWL_PartState_Normal; - if (bRepaint) - rtInvlidate.Union(m_rtUpButton); - else - rtInvlidate = m_rtUpButton; - bRepaint = true; - } - } - } else if (m_dwUpState != CFWL_PartState_Normal || - m_dwDnState != CFWL_PartState_Normal) { - if (m_dwUpState != CFWL_PartState_Normal) { - m_dwUpState = CFWL_PartState_Normal; - bRepaint = true; - rtInvlidate = m_rtUpButton; - } - if (m_dwDnState != CFWL_PartState_Normal) { - m_dwDnState = CFWL_PartState_Normal; - if (bRepaint) - rtInvlidate.Union(m_rtDnButton); - else - rtInvlidate = m_rtDnButton; - - bRepaint = true; - } - } - if (bRepaint) - RepaintRect(rtInvlidate); -} - -void CFWL_SpinButton::OnMouseLeave(CFWL_MessageMouse* pMsg) { - if (!pMsg) - return; - if (m_dwUpState != CFWL_PartState_Normal && IsUpButtonEnabled()) - m_dwUpState = CFWL_PartState_Normal; - if (m_dwDnState != CFWL_PartState_Normal && IsDownButtonEnabled()) - m_dwDnState = CFWL_PartState_Normal; - - RepaintRect(m_rtClient); -} - -void CFWL_SpinButton::OnKeyDown(CFWL_MessageKey* pMsg) { - bool bUp = - pMsg->m_dwKeyCode == FWL_VKEY_Up || pMsg->m_dwKeyCode == FWL_VKEY_Left; - bool bDown = - pMsg->m_dwKeyCode == FWL_VKEY_Down || pMsg->m_dwKeyCode == FWL_VKEY_Right; - if (!bUp && !bDown) - return; - - bool bUpEnable = IsUpButtonEnabled(); - bool bDownEnable = IsDownButtonEnabled(); - if (!bUpEnable && !bDownEnable) - return; - - CFWL_Event wmPosChanged(CFWL_Event::Type::Click, this); - DispatchEvent(&wmPosChanged); - - RepaintRect(bUpEnable ? m_rtUpButton : m_rtDnButton); -} - -CFWL_SpinButton::Timer::Timer(CFWL_SpinButton* pToolTip) - : CFWL_Timer(pToolTip) {} - -void CFWL_SpinButton::Timer::Run(CFWL_TimerInfo* pTimerInfo) { - CFWL_SpinButton* pButton = static_cast<CFWL_SpinButton*>(m_pWidget); - - if (!pButton->m_pTimerInfo) - return; - - CFWL_Event wmPosChanged(CFWL_Event::Type::Click, pButton); - pButton->DispatchEvent(&wmPosChanged); -} diff --git a/xfa/fwl/cfwl_spinbutton.h b/xfa/fwl/cfwl_spinbutton.h deleted file mode 100644 index 3cda761f91de2bc32fd275be3cb1cc893d26080f..0000000000000000000000000000000000000000 --- a/xfa/fwl/cfwl_spinbutton.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FWL_CFWL_SPINBUTTON_H_ -#define XFA_FWL_CFWL_SPINBUTTON_H_ - -#include <memory> - -#include "xfa/fwl/cfwl_timer.h" -#include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxfa/cxfa_eventparam.h" - -#define FWL_STYLEEXE_SPB_Vert (1L << 0) - -class CFWL_MessageMouse; -class CFWL_WidgetProperties; - -class CFWL_SpinButton : public CFWL_Widget { - public: - CFWL_SpinButton(const CFWL_App* app, - std::unique_ptr<CFWL_WidgetProperties> properties); - ~CFWL_SpinButton() override; - - // CFWL_Widget - FWL_Type GetClassID() const override; - void Update() override; - FWL_WidgetHit HitTest(const CFX_PointF& point) override; - void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) override; - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; - - private: - class Timer : public CFWL_Timer { - public: - explicit Timer(CFWL_SpinButton* pToolTip); - ~Timer() override {} - - void Run(CFWL_TimerInfo* pTimerInfo) override; - }; - friend class CFWL_SpinButton::Timer; - - void DisableButton(); - bool IsUpButtonEnabled(); - bool IsDownButtonEnabled(); - void DrawUpButton(CFX_Graphics* pGraphics, - IFWL_ThemeProvider* pTheme, - const CFX_Matrix* pMatrix); - void DrawDownButton(CFX_Graphics* pGraphics, - IFWL_ThemeProvider* pTheme, - const CFX_Matrix* pMatrix); - void OnFocusChanged(CFWL_Message* pMsg, bool bSet); - void OnLButtonDown(CFWL_MessageMouse* pMsg); - void OnLButtonUp(CFWL_MessageMouse* pMsg); - void OnMouseMove(CFWL_MessageMouse* pMsg); - void OnMouseLeave(CFWL_MessageMouse* pMsg); - void OnKeyDown(CFWL_MessageKey* pMsg); - - CFX_RectF m_rtClient; - CFX_RectF m_rtUpButton; - CFX_RectF m_rtDnButton; - uint32_t m_dwUpState; - uint32_t m_dwDnState; - int32_t m_iButtonIndex; - bool m_bLButtonDwn; - CFWL_TimerInfo* m_pTimerInfo; - CFWL_SpinButton::Timer m_Timer; -}; - -#endif // XFA_FWL_CFWL_SPINBUTTON_H_ diff --git a/xfa/fwl/cfwl_themebackground.h b/xfa/fwl/cfwl_themebackground.h index 3f2048883011a749acb32f3192d0c8f0facfd867..85435aa524f385da1a930c4bc245e132b7b0e711 100644 --- a/xfa/fwl/cfwl_themebackground.h +++ b/xfa/fwl/cfwl_themebackground.h @@ -7,21 +7,23 @@ #ifndef XFA_FWL_CFWL_THEMEBACKGROUND_H_ #define XFA_FWL_CFWL_THEMEBACKGROUND_H_ -#include "core/fxge/fx_dib.h" #include "xfa/fwl/cfwl_themepart.h" -class CFX_DIBitmpa; -class CFX_Graphics; -class CFX_Path; +class CXFA_Graphics; +class CXFA_GEPath; class CFWL_ThemeBackground : public CFWL_ThemePart { public: - CFWL_ThemeBackground() - : m_pGraphics(nullptr), m_pImage(nullptr), m_pPath(nullptr) {} + CFWL_ThemeBackground(); + ~CFWL_ThemeBackground(); - CFX_Graphics* m_pGraphics; - CFX_DIBitmap* m_pImage; - CFX_Path* m_pPath; + CXFA_Graphics* m_pGraphics; + CXFA_GEPath* m_pPath; }; +inline CFWL_ThemeBackground::CFWL_ThemeBackground() + : m_pGraphics(nullptr), m_pPath(nullptr) {} + +inline CFWL_ThemeBackground::~CFWL_ThemeBackground() {} + #endif // XFA_FWL_CFWL_THEMEBACKGROUND_H_ diff --git a/xfa/fwl/cfwl_themetext.h b/xfa/fwl/cfwl_themetext.h index 6cbc465bf328b0e7f37b419ee44c52260054b1e6..91a3f385dfffcb19d41cbe351bfbc4ba43ff5889 100644 --- a/xfa/fwl/cfwl_themetext.h +++ b/xfa/fwl/cfwl_themetext.h @@ -15,10 +15,10 @@ class CFWL_ThemeText : public CFWL_ThemePart { public: CFWL_ThemeText() : m_pGraphics(nullptr) {} - CFX_WideString m_wsText; - uint32_t m_dwTTOStyles; - int32_t m_iTTOAlign; - CFX_Graphics* m_pGraphics; + WideString m_wsText; + FDE_TextStyle m_dwTTOStyles; + FDE_TextAlignment m_iTTOAlign; + CXFA_Graphics* m_pGraphics; }; #endif // XFA_FWL_CFWL_THEMETEXT_H_ diff --git a/xfa/fwl/cfwl_timer.cpp b/xfa/fwl/cfwl_timer.cpp index c7214a4f72d5651f4d97fd46dc38abf829f43053..2734e49d7867f1c999bbe92ea4b0416b9896da37 100644 --- a/xfa/fwl/cfwl_timer.cpp +++ b/xfa/fwl/cfwl_timer.cpp @@ -10,7 +10,11 @@ #include "xfa/fwl/cfwl_timerinfo.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/ifwl_adaptertimermgr.h" -#include "xfa/fxfa/xfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffapp.h" + +CFWL_Timer::CFWL_Timer(CFWL_Widget* parent) : m_pWidget(parent) {} + +CFWL_Timer::~CFWL_Timer() {} CFWL_TimerInfo* CFWL_Timer::StartTimer(uint32_t dwElapse, bool bImmediately) { const CFWL_App* pApp = m_pWidget->GetOwnerApp(); diff --git a/xfa/fwl/cfwl_timer.h b/xfa/fwl/cfwl_timer.h index 6c9079acfe570d44c06468b2557d73729e3f0e94..da1b4437e20de4ccf34bbedd6c34a575a617cfeb 100644 --- a/xfa/fwl/cfwl_timer.h +++ b/xfa/fwl/cfwl_timer.h @@ -8,20 +8,21 @@ #define XFA_FWL_CFWL_TIMER_H_ #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class CFWL_TimerInfo; class CFWL_Widget; class CFWL_Timer { public: - explicit CFWL_Timer(CFWL_Widget* parent) : m_pWidget(parent) {} - virtual ~CFWL_Timer() {} + explicit CFWL_Timer(CFWL_Widget* parent); + virtual ~CFWL_Timer(); virtual void Run(CFWL_TimerInfo* hTimer) = 0; CFWL_TimerInfo* StartTimer(uint32_t dwElapse, bool bImmediately); protected: - CFWL_Widget* m_pWidget; // Not owned. + UnownedPtr<CFWL_Widget> m_pWidget; }; #endif // XFA_FWL_CFWL_TIMER_H_ diff --git a/xfa/fwl/cfwl_timerinfo.cpp b/xfa/fwl/cfwl_timerinfo.cpp index 8c7aaebbbb762c623f272da43d9565709adcf6d2..ee4746af3fd773f6bc1b26dd28497d8d02d67cf6 100644 --- a/xfa/fwl/cfwl_timerinfo.cpp +++ b/xfa/fwl/cfwl_timerinfo.cpp @@ -8,6 +8,12 @@ #include "xfa/fwl/ifwl_adaptertimermgr.h" +CFWL_TimerInfo::CFWL_TimerInfo(IFWL_AdapterTimerMgr* mgr) : m_pMgr(mgr) { + ASSERT(mgr); +} + +CFWL_TimerInfo::~CFWL_TimerInfo() {} + void CFWL_TimerInfo::StopTimer() { m_pMgr->Stop(this); } diff --git a/xfa/fwl/cfwl_timerinfo.h b/xfa/fwl/cfwl_timerinfo.h index a47fede60f80079ca48bfab6a3e1f0683c761b4b..c58bcff9a931216ef20cca519a5ab8d2ca45b68b 100644 --- a/xfa/fwl/cfwl_timerinfo.h +++ b/xfa/fwl/cfwl_timerinfo.h @@ -8,20 +8,19 @@ #define XFA_FWL_CFWL_TIMERINFO_H_ #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" class IFWL_AdapterTimerMgr; class CFWL_TimerInfo { public: - explicit CFWL_TimerInfo(IFWL_AdapterTimerMgr* mgr) : m_pMgr(mgr) { - ASSERT(mgr); - } - virtual ~CFWL_TimerInfo() {} + explicit CFWL_TimerInfo(IFWL_AdapterTimerMgr* mgr); + virtual ~CFWL_TimerInfo(); void StopTimer(); private: - IFWL_AdapterTimerMgr* m_pMgr; // Not owned. + UnownedPtr<IFWL_AdapterTimerMgr> m_pMgr; }; #endif // XFA_FWL_CFWL_TIMERINFO_H_ diff --git a/xfa/fwl/cfwl_widget.cpp b/xfa/fwl/cfwl_widget.cpp index b5b8bf4c7d19fab52ce72ac0da76272d5164acb2..b9b04cf1f40651307137c62b111bdd12694abcb0 100644 --- a/xfa/fwl/cfwl_widget.cpp +++ b/xfa/fwl/cfwl_widget.cpp @@ -11,7 +11,7 @@ #include <vector> #include "third_party/base/stl_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_combobox.h" #include "xfa/fwl/cfwl_event.h" @@ -28,7 +28,7 @@ #include "xfa/fwl/cfwl_themetext.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxfa/xfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffapp.h" #define FWL_STYLEEXT_MNU_Vert (1L << 0) #define FWL_WGT_CalcHeight 2048 @@ -63,7 +63,7 @@ CFWL_Widget::~CFWL_Widget() { m_pWidgetMgr->RemoveWidget(this); } -bool CFWL_Widget::IsInstance(const CFX_WideStringC& wsClass) const { +bool CFWL_Widget::IsInstance(const WideStringView& wsClass) const { return false; } @@ -77,7 +77,7 @@ CFX_RectF CFWL_Widget::GetWidgetRect() { void CFWL_Widget::InflateWidgetRect(CFX_RectF& rect) { if (HasBorder()) { - FX_FLOAT fBorder = GetBorderSize(true); + float fBorder = GetBorderSize(true); rect.Inflate(fBorder, fBorder); } } @@ -197,9 +197,8 @@ CFX_PointF CFWL_Widget::TransformTo(CFWL_Widget* pWidget, if (!parent) return ret; - CFX_Matrix m; - m.SetReverse(pWidget->GetMatrix()); - return m.Transform(ret) - pWidget->GetWidgetRect().TopLeft(); + return pWidget->GetMatrix().GetInverse().Transform(ret) - + pWidget->GetWidgetRect().TopLeft(); } CFX_Matrix CFWL_Widget::GetMatrix() { @@ -269,14 +268,14 @@ CFX_RectF CFWL_Widget::GetEdgeRect() { CFX_RectF rtEdge(0, 0, m_pProperties->m_rtWidget.width, m_pProperties->m_rtWidget.height); if (HasBorder()) { - FX_FLOAT fCX = GetBorderSize(true); - FX_FLOAT fCY = GetBorderSize(false); + float fCX = GetBorderSize(true); + float fCY = GetBorderSize(false); rtEdge.Deflate(fCX, fCY); } return rtEdge; } -FX_FLOAT CFWL_Widget::GetBorderSize(bool bCX) { +float CFWL_Widget::GetBorderSize(bool bCX) { IFWL_ThemeProvider* theme = GetAvailableTheme(); if (!theme) return 0.0f; @@ -316,7 +315,7 @@ CFWL_Widget* CFWL_Widget::GetRootOuter() { return pRet; } -CFX_SizeF CFWL_Widget::CalcTextSize(const CFX_WideString& wsText, +CFX_SizeF CFWL_Widget::CalcTextSize(const WideString& wsText, IFWL_ThemeProvider* pTheme, bool bMultiLine) { if (!pTheme) @@ -325,20 +324,22 @@ CFX_SizeF CFWL_Widget::CalcTextSize(const CFX_WideString& wsText, CFWL_ThemeText calPart; calPart.m_pWidget = this; calPart.m_wsText = wsText; - calPart.m_dwTTOStyles = - bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine; - calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft; - FX_FLOAT fWidth = - bMultiLine ? FWL_WGT_CalcMultiLineDefWidth : FWL_WGT_CalcWidth; + if (bMultiLine) + calPart.m_dwTTOStyles.line_wrap_ = true; + else + calPart.m_dwTTOStyles.single_line_ = true; + + calPart.m_iTTOAlign = FDE_TextAlignment::kTopLeft; + float fWidth = bMultiLine ? FWL_WGT_CalcMultiLineDefWidth : FWL_WGT_CalcWidth; CFX_RectF rect(0, 0, fWidth, FWL_WGT_CalcHeight); pTheme->CalcTextRect(&calPart, rect); return CFX_SizeF(rect.width, rect.height); } -void CFWL_Widget::CalcTextRect(const CFX_WideString& wsText, +void CFWL_Widget::CalcTextRect(const WideString& wsText, IFWL_ThemeProvider* pTheme, - uint32_t dwTTOStyles, - int32_t iTTOAlign, + const FDE_TextStyle& dwTTOStyles, + FDE_TextAlignment iTTOAlign, CFX_RectF& rect) { CFWL_ThemeText calPart; calPart.m_pWidget = this; @@ -378,8 +379,8 @@ void CFWL_Widget::SetGrab(bool bSet) { pDriver->SetGrab(this, bSet); } -void CFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, +void CFWL_Widget::GetPopupPos(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) { if (GetClassID() == FWL_Type::ComboBox) { @@ -400,13 +401,13 @@ void CFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight, GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup); } -bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, +bool CFWL_Widget::GetPopupPosMenu(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) { if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) { bool bLeft = m_pProperties->m_rtWidget.left < 0; - FX_FLOAT fRight = rtAnchor.right() + rtPopup.width; + float fRight = rtAnchor.right() + rtPopup.width; CFX_PointF point = TransformTo(nullptr, CFX_PointF()); if (fRight + point.x > 0.0f || bLeft) { rtPopup = CFX_RectF(rtAnchor.left - rtPopup.width, rtAnchor.top, @@ -419,7 +420,7 @@ bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight, return true; } - FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height; + float fBottom = rtAnchor.bottom() + rtPopup.height; CFX_PointF point = TransformTo(nullptr, point); if (fBottom + point.y > 0.0f) { rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height, @@ -432,18 +433,18 @@ bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight, return true; } -bool CFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, +bool CFWL_Widget::GetPopupPosComboBox(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) { - FX_FLOAT fPopHeight = rtPopup.height; + float fPopHeight = rtPopup.height; if (rtPopup.height > fMaxHeight) fPopHeight = fMaxHeight; else if (rtPopup.height < fMinHeight) fPopHeight = fMinHeight; - FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width); - FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight; + float fWidth = std::max(rtAnchor.width, rtPopup.width); + float fBottom = rtAnchor.bottom() + fPopHeight; CFX_PointF point = TransformTo(nullptr, CFX_PointF()); if (fBottom + point.y > 0.0f) { rtPopup = @@ -456,8 +457,8 @@ bool CFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight, return true; } -bool CFWL_Widget::GetPopupPosGeneral(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, +bool CFWL_Widget::GetPopupPosGeneral(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) { CFX_PointF point = TransformTo(nullptr, CFX_PointF()); @@ -520,7 +521,7 @@ void CFWL_Widget::RepaintRect(const CFX_RectF& pRect) { m_pWidgetMgr->RepaintWidget(this, pRect); } -void CFWL_Widget::DrawBackground(CFX_Graphics* pGraphics, +void CFWL_Widget::DrawBackground(CXFA_Graphics* pGraphics, CFWL_Part iPartBk, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix) { @@ -534,16 +535,15 @@ void CFWL_Widget::DrawBackground(CFX_Graphics* pGraphics, pTheme->DrawBackground(¶m); } -void CFWL_Widget::DrawBorder(CFX_Graphics* pGraphics, +void CFWL_Widget::DrawBorder(CXFA_Graphics* pGraphics, CFWL_Part iPartBorder, IFWL_ThemeProvider* pTheme, - const CFX_Matrix* pMatrix) { + const CFX_Matrix& matrix) { CFWL_ThemeBackground param; param.m_pWidget = this; param.m_iPart = iPartBorder; param.m_pGraphics = pGraphics; - if (pMatrix) - param.m_matrix.Concat(*pMatrix, true); + param.m_matrix.Concat(matrix, true); param.m_rtPart = GetRelativeRect(); pTheme->DrawBackground(¶m); } @@ -612,5 +612,5 @@ void CFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) { void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {} -void CFWL_Widget::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) {} +void CFWL_Widget::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) {} diff --git a/xfa/fwl/cfwl_widget.h b/xfa/fwl/cfwl_widget.h index 2387b753e585692f5ae418b50128af12be376d0f..27cb458b9e6ba8542a3cd2bd59e48a3419e80756 100644 --- a/xfa/fwl/cfwl_widget.h +++ b/xfa/fwl/cfwl_widget.h @@ -6,16 +6,18 @@ #ifndef XFA_FWL_CFWL_WIDGET_H_ #define XFA_FWL_CFWL_WIDGET_H_ + #include <memory> #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/unowned_ptr.h" +#include "xfa/fde/cfde_data.h" #include "xfa/fwl/cfwl_event.h" #include "xfa/fwl/cfwl_themepart.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/fwl_widgethit.h" #include "xfa/fwl/ifwl_widgetdelegate.h" -#include "xfa/fwl/theme/cfwl_widgettp.h" enum class FWL_Type { Unknown = 0, @@ -51,7 +53,7 @@ class CFWL_Widget : public IFWL_WidgetDelegate { ~CFWL_Widget() override; virtual FWL_Type GetClassID() const = 0; - virtual bool IsInstance(const CFX_WideStringC& wsClass) const; + virtual bool IsInstance(const WideStringView& wsClass) const; virtual CFX_RectF GetAutosizedWidgetRect(); virtual CFX_RectF GetWidgetRect(); virtual CFX_RectF GetClientRect(); @@ -61,15 +63,15 @@ class CFWL_Widget : public IFWL_WidgetDelegate { virtual void RemoveStates(uint32_t dwStates); virtual void Update() = 0; virtual FWL_WidgetHit HitTest(const CFX_PointF& point); - virtual void DrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) = 0; + virtual void DrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) = 0; virtual void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider); // IFWL_WidgetDelegate. void OnProcessMessage(CFWL_Message* pMessage) override; void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; void InflateWidgetRect(CFX_RectF& rect); void SetWidgetRect(const CFX_RectF& rect); @@ -96,13 +98,13 @@ class CFWL_Widget : public IFWL_WidgetDelegate { void SetDelegate(IFWL_WidgetDelegate* delegate) { m_pDelegate = delegate; } IFWL_WidgetDelegate* GetDelegate() { - return m_pDelegate ? m_pDelegate : this; + return m_pDelegate ? m_pDelegate.Get() : this; } const IFWL_WidgetDelegate* GetDelegate() const { - return m_pDelegate ? m_pDelegate : this; + return m_pDelegate ? m_pDelegate.Get() : this; } - const CFWL_App* GetOwnerApp() const { return m_pOwnerApp; } + const CFWL_App* GetOwnerApp() const { return m_pOwnerApp.Get(); } uint32_t GetEventKey() const { return m_nEventKey; } void SetEventKey(uint32_t key) { m_nEventKey = key; } @@ -122,32 +124,32 @@ class CFWL_Widget : public IFWL_WidgetDelegate { bool IsLocked() const { return m_iLock > 0; } bool HasBorder() const; CFX_RectF GetEdgeRect(); - FX_FLOAT GetBorderSize(bool bCX); + float GetBorderSize(bool bCX); CFX_RectF GetRelativeRect(); IFWL_ThemeProvider* GetAvailableTheme(); - CFX_SizeF CalcTextSize(const CFX_WideString& wsText, + CFX_SizeF CalcTextSize(const WideString& wsText, IFWL_ThemeProvider* pTheme, bool bMultiLine); - void CalcTextRect(const CFX_WideString& wsText, + void CalcTextRect(const WideString& wsText, IFWL_ThemeProvider* pTheme, - uint32_t dwTTOStyles, - int32_t iTTOAlign, + const FDE_TextStyle& dwTTOStyles, + FDE_TextAlignment iTTOAlign, CFX_RectF& rect); void SetGrab(bool bSet); - void GetPopupPos(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, + void GetPopupPos(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup); void RegisterEventTarget(CFWL_Widget* pEventSource); void UnregisterEventTarget(); void DispatchEvent(CFWL_Event* pEvent); - void DrawBorder(CFX_Graphics* pGraphics, + void DrawBorder(CXFA_Graphics* pGraphics, CFWL_Part iPartBorder, IFWL_ThemeProvider* pTheme, - const CFX_Matrix* pMatrix); + const CFX_Matrix& pMatrix); - const CFWL_App* const m_pOwnerApp; - CFWL_WidgetMgr* const m_pWidgetMgr; + UnownedPtr<const CFWL_App> const m_pOwnerApp; + UnownedPtr<CFWL_WidgetMgr> const m_pWidgetMgr; std::unique_ptr<CFWL_WidgetProperties> m_pProperties; CFWL_Widget* m_pOuter; int32_t m_iLock; @@ -161,19 +163,19 @@ class CFWL_Widget : public IFWL_WidgetDelegate { bool IsPopup() const; bool IsChild() const; CFWL_Widget* GetRootOuter(); - bool GetPopupPosMenu(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, + bool GetPopupPosMenu(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup); - bool GetPopupPosComboBox(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, + bool GetPopupPosComboBox(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup); - bool GetPopupPosGeneral(FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, + bool GetPopupPosGeneral(float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup); - void DrawBackground(CFX_Graphics* pGraphics, + void DrawBackground(CXFA_Graphics* pGraphics, CFWL_Part iPartBk, IFWL_ThemeProvider* pTheme, const CFX_Matrix* pMatrix); @@ -182,7 +184,7 @@ class CFWL_Widget : public IFWL_WidgetDelegate { CXFA_FFWidget* m_pLayoutItem; uint32_t m_nEventKey; - IFWL_WidgetDelegate* m_pDelegate; // Not owned. + UnownedPtr<IFWL_WidgetDelegate> m_pDelegate; }; #endif // XFA_FWL_CFWL_WIDGET_H_ diff --git a/xfa/fwl/cfwl_widgetmgr.cpp b/xfa/fwl/cfwl_widgetmgr.cpp index 7c0fddd41938ba7ead2e119c07a2f92f253df845..3082b182ad8502454eb6c652b72f101a50fc6688 100644 --- a/xfa/fwl/cfwl_widgetmgr.cpp +++ b/xfa/fwl/cfwl_widgetmgr.cpp @@ -12,8 +12,8 @@ #include "xfa/fwl/cfwl_app.h" #include "xfa/fwl/cfwl_form.h" #include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/xfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" namespace { @@ -29,12 +29,13 @@ struct FWL_NEEDREPAINTHITDATA { } // namespace CFWL_WidgetMgr::CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative) - : m_dwCapability(0), m_pAdapter(pAdapterNative->GetWidgetMgr(this)) { + : m_dwCapability(FWL_WGTMGR_DisableForm), + m_pAdapter(pAdapterNative->GetFWLAdapterWidgetMgr()) { ASSERT(m_pAdapter); m_mapWidgetItem[nullptr] = pdfium::MakeUnique<Item>(); -#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ m_rtScreen.Reset(); -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ } CFWL_WidgetMgr::~CFWL_WidgetMgr() {} @@ -266,12 +267,7 @@ CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent, CFWL_Widget* child = GetLastChildWidget(parent); while (child) { if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) { - CFX_Matrix m; - m.SetIdentity(); - - CFX_Matrix matrixOnParent; - m.SetReverse(matrixOnParent); - pos = m.Transform(point); + pos = parent->GetMatrix().GetInverse().Transform(point); CFX_RectF bounds = child->GetWidgetRect(); if (bounds.Contains(pos)) { @@ -383,17 +379,13 @@ bool CFWL_WidgetMgr::IsAbleNative(CFWL_Widget* pWidget) const { } void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget, - FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, + float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) const { m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor, rtPopup); } -void CFWL_WidgetMgr::OnSetCapability(uint32_t dwCapability) { - m_dwCapability = dwCapability; -} - void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) { if (!pMessage) return; @@ -415,7 +407,7 @@ void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) { else pNoteDriver->QueueMessage(pMessage->Clone()); -#if (_FX_OS_ == _FX_MACOSX_) +#if (_FX_OS_ == _FX_OS_MACOSX_) CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop(); if (pTopLoop) pNoteDriver->UnqueueMessageAndProcess(pTopLoop); @@ -423,34 +415,36 @@ void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) { } void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget, - CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { + CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { if (!pWidget || !pGraphics) return; CFX_RectF clipCopy(0, 0, pWidget->GetWidgetRect().Size()); CFX_RectF clipBounds; -#if _FX_OS_ == _FX_MACOSX_ +#if _FX_OS_ == _FX_OS_MACOSX_ if (IsFormDisabled()) { -#endif // _FX_OS_ == _FX_MACOSX_ +#endif // _FX_OS_ == _FX_OS_MACOSX_ - pWidget->GetDelegate()->OnDrawWidget(pGraphics, pMatrix); + pWidget->GetDelegate()->OnDrawWidget(pGraphics, matrix); clipBounds = pGraphics->GetClipRect(); clipCopy = clipBounds; -#if _FX_OS_ == _FX_MACOSX_ +#if _FX_OS_ == _FX_OS_MACOSX_ } else { - clipBounds = CFX_RectF(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d); - const_cast<CFX_Matrix*>(pMatrix)->SetIdentity(); // FIXME: const cast. - pWidget->GetDelegate()->OnDrawWidget(pGraphics, pMatrix); + clipBounds = CFX_RectF(matrix.a, matrix.b, matrix.c, matrix.d); + // FIXME: const cast + CFX_Matrix* pMatrixHack = const_cast<CFX_Matrix*>(&matrix); + pMatrixHack->SetIdentity(); + pWidget->GetDelegate()->OnDrawWidget(pGraphics, *pMatrixHack); } -#endif // _FX_OS_ == _FX_MACOSX_ +#endif // _FX_OS_ == _FX_OS_MACOSX_ if (!IsFormDisabled()) clipBounds.Intersect(pWidget->GetClientRect()); if (!clipBounds.IsEmpty()) - DrawChild(pWidget, clipBounds, pGraphics, pMatrix); + DrawChild(pWidget, clipBounds, pGraphics, &matrix); GetWidgetMgrItem(pWidget)->iRedrawCounter = 0; ResetRedrawCounts(pWidget); @@ -458,7 +452,7 @@ void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget, void CFWL_WidgetMgr::DrawChild(CFWL_Widget* parent, const CFX_RectF& rtClip, - CFX_Graphics* pGraphics, + CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix) { if (!parent) return; @@ -497,7 +491,7 @@ void CFWL_WidgetMgr::DrawChild(CFWL_Widget* parent, if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate()) { if (IsFormDisabled() || IsNeedRepaint(child, &widgetMatrix, rtClip)) - pDelegate->OnDrawWidget(pGraphics, &widgetMatrix); + pDelegate->OnDrawWidget(pGraphics, widgetMatrix); } if (!bFormDisable) pGraphics->RestoreGraphState(); @@ -517,8 +511,8 @@ bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget, return true; } - CFX_RectF rtWidget(0, 0, pWidget->GetWidgetRect().Size()); - pMatrix->TransformRect(rtWidget); + CFX_RectF rtWidget = + pMatrix->TransformRect(CFX_RectF(0, 0, pWidget->GetWidgetRect().Size())); if (!rtWidget.IntersectWith(rtDirty)) return false; @@ -532,9 +526,9 @@ bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget, bool bOrginPtIntersectWidthChild = false; bool bOrginPtIntersectWidthDirty = rtDirty.Contains(rtWidget.TopLeft()); static FWL_NEEDREPAINTHITDATA hitPoint[kNeedRepaintHitPoints]; - FXSYS_memset(hitPoint, 0, sizeof(hitPoint)); - FX_FLOAT fxPiece = rtWidget.width / kNeedRepaintHitPiece; - FX_FLOAT fyPiece = rtWidget.height / kNeedRepaintHitPiece; + memset(hitPoint, 0, sizeof(hitPoint)); + float fxPiece = rtWidget.width / kNeedRepaintHitPiece; + float fyPiece = rtWidget.height / kNeedRepaintHitPiece; hitPoint[2].hitPoint.x = hitPoint[6].hitPoint.x = rtWidget.left; hitPoint[0].hitPoint.x = hitPoint[3].hitPoint.x = hitPoint[7].hitPoint.x = hitPoint[10].hitPoint.x = fxPiece + rtWidget.left; @@ -596,7 +590,7 @@ bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget, if (repaintPoint > 0) return true; - pMatrix->TransformRect(rtChilds); + rtChilds = pMatrix->TransformRect(rtChilds); if (rtChilds.Contains(rtDirty) || rtChilds.Contains(rtWidget)) return false; return true; @@ -612,10 +606,10 @@ CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget) pNext(nullptr), pWidget(widget), iRedrawCounter(0) -#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ , bOutsideChanged(false) -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ { } diff --git a/xfa/fwl/cfwl_widgetmgr.h b/xfa/fwl/cfwl_widgetmgr.h index 2d436bd8e298872ea6482192f3d101e5135af7db..153d0a903e691219d53d3b071aebe21de8e6509c 100644 --- a/xfa/fwl/cfwl_widgetmgr.h +++ b/xfa/fwl/cfwl_widgetmgr.h @@ -12,29 +12,26 @@ #include <vector> #include "core/fxcrt/fx_system.h" -#include "xfa/fwl/ifwl_widgetmgrdelegate.h" -#include "xfa/fxgraphics/cfx_graphics.h" +#include "xfa/fxgraphics/cxfa_graphics.h" #define FWL_WGTMGR_DisableForm 0x00000002 class CFWL_Message; class CXFA_FFApp; class CXFA_FWLAdapterWidgetMgr; -class CFX_Graphics; +class CXFA_Graphics; class CFX_Matrix; class CFWL_Widget; -class CFWL_WidgetMgr : public CFWL_WidgetMgrDelegate { +class CFWL_WidgetMgr { public: explicit CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative); ~CFWL_WidgetMgr(); - // CFWL_WidgetMgrDelegate - void OnSetCapability(uint32_t dwCapability) override; - void OnProcessMessageToForm(CFWL_Message* pMessage) override; + void OnProcessMessageToForm(CFWL_Message* pMessage); void OnDrawWidget(CFWL_Widget* pWidget, - CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) override; + CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix); CFWL_Widget* GetParentWidget(CFWL_Widget* pWidget) const; CFWL_Widget* GetOwnerWidget(CFWL_Widget* pWidget) const; @@ -64,8 +61,8 @@ class CFWL_WidgetMgr : public CFWL_WidgetMgrDelegate { } void GetAdapterPopupPos(CFWL_Widget* pWidget, - FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, + float fMinHeight, + float fMaxHeight, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) const; @@ -82,11 +79,11 @@ class CFWL_WidgetMgr : public CFWL_WidgetMgrDelegate { Item* pPrevious; Item* pNext; CFWL_Widget* const pWidget; - std::unique_ptr<CFX_Graphics> pOffscreen; + std::unique_ptr<CXFA_Graphics> pOffscreen; int32_t iRedrawCounter; -#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ bool bOutsideChanged; -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ }; CFWL_Widget* GetFirstSiblingWidget(CFWL_Widget* pWidget) const; @@ -103,11 +100,11 @@ class CFWL_WidgetMgr : public CFWL_WidgetMgrDelegate { void DrawChild(CFWL_Widget* pParent, const CFX_RectF& rtClip, - CFX_Graphics* pGraphics, + CXFA_Graphics* pGraphics, const CFX_Matrix* pMatrix); - CFX_Graphics* DrawWidgetBefore(CFWL_Widget* pWidget, - CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix); + CXFA_Graphics* DrawWidgetBefore(CFWL_Widget* pWidget, + CXFA_Graphics* pGraphics, + const CFX_Matrix* pMatrix); bool IsNeedRepaint(CFWL_Widget* pWidget, CFX_Matrix* pMatrix, const CFX_RectF& rtDirty); @@ -116,10 +113,10 @@ class CFWL_WidgetMgr : public CFWL_WidgetMgrDelegate { uint32_t m_dwCapability; std::map<CFWL_Widget*, std::unique_ptr<Item>> m_mapWidgetItem; - CXFA_FWLAdapterWidgetMgr* const m_pAdapter; -#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) + UnownedPtr<CXFA_FWLAdapterWidgetMgr> const m_pAdapter; +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ CFX_RectF m_rtScreen; -#endif +#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ }; #endif // XFA_FWL_CFWL_WIDGETMGR_H_ diff --git a/xfa/fwl/cfx_barcode.cpp b/xfa/fwl/cfx_barcode.cpp index 7af3aa18884e521c80ec196b2e75a97e22f010c3..9d667c67b92302438494292113cc206acaa28243 100644 --- a/xfa/fwl/cfx_barcode.cpp +++ b/xfa/fwl/cfx_barcode.cpp @@ -6,44 +6,47 @@ #include "xfa/fwl/cfx_barcode.h" -#include "xfa/fxbarcode/cbc_codabar.h" -#include "xfa/fxbarcode/cbc_code128.h" -#include "xfa/fxbarcode/cbc_code39.h" -#include "xfa/fxbarcode/cbc_codebase.h" -#include "xfa/fxbarcode/cbc_datamatrix.h" -#include "xfa/fxbarcode/cbc_ean13.h" -#include "xfa/fxbarcode/cbc_ean8.h" -#include "xfa/fxbarcode/cbc_pdf417i.h" -#include "xfa/fxbarcode/cbc_qrcode.h" -#include "xfa/fxbarcode/cbc_upca.h" -#include "xfa/fxbarcode/utils.h" +#include <memory> + +#include "fxbarcode/cbc_codabar.h" +#include "fxbarcode/cbc_code128.h" +#include "fxbarcode/cbc_code39.h" +#include "fxbarcode/cbc_codebase.h" +#include "fxbarcode/cbc_datamatrix.h" +#include "fxbarcode/cbc_ean13.h" +#include "fxbarcode/cbc_ean8.h" +#include "fxbarcode/cbc_pdf417i.h" +#include "fxbarcode/cbc_qrcode.h" +#include "fxbarcode/cbc_upca.h" +#include "fxbarcode/utils.h" +#include "third_party/base/ptr_util.h" namespace { -CBC_CodeBase* CreateBarCodeEngineObject(BC_TYPE type) { +std::unique_ptr<CBC_CodeBase> CreateBarCodeEngineObject(BC_TYPE type) { switch (type) { case BC_CODE39: - return new CBC_Code39(); + return pdfium::MakeUnique<CBC_Code39>(); case BC_CODABAR: - return new CBC_Codabar(); + return pdfium::MakeUnique<CBC_Codabar>(); case BC_CODE128: - return new CBC_Code128(BC_CODE128_B); + return pdfium::MakeUnique<CBC_Code128>(BC_CODE128_B); case BC_CODE128_B: - return new CBC_Code128(BC_CODE128_B); + return pdfium::MakeUnique<CBC_Code128>(BC_CODE128_B); case BC_CODE128_C: - return new CBC_Code128(BC_CODE128_C); + return pdfium::MakeUnique<CBC_Code128>(BC_CODE128_C); case BC_EAN8: - return new CBC_EAN8(); + return pdfium::MakeUnique<CBC_EAN8>(); case BC_UPCA: - return new CBC_UPCA(); + return pdfium::MakeUnique<CBC_UPCA>(); case BC_EAN13: - return new CBC_EAN13(); + return pdfium::MakeUnique<CBC_EAN13>(); case BC_QR_CODE: - return new CBC_QRCode(); + return pdfium::MakeUnique<CBC_QRCode>(); case BC_PDF417: - return new CBC_PDF417I(); + return pdfium::MakeUnique<CBC_PDF417I>(); case BC_DATAMATRIX: - return new CBC_DataMatrix(); + return pdfium::MakeUnique<CBC_DataMatrix>(); case BC_UNKNOWN: default: return nullptr; @@ -57,7 +60,7 @@ CFX_Barcode::CFX_Barcode() {} CFX_Barcode::~CFX_Barcode() {} bool CFX_Barcode::Create(BC_TYPE type) { - m_pBCEngine.reset(CreateBarCodeEngineObject(type)); + m_pBCEngine = CreateBarCodeEngineObject(type); return !!m_pBCEngine; } @@ -160,7 +163,7 @@ bool CFX_Barcode::SetFont(CFX_Font* pFont) { } } -bool CFX_Barcode::SetFontSize(FX_FLOAT size) { +bool CFX_Barcode::SetFontSize(float size) { switch (GetType()) { case BC_CODE39: case BC_CODABAR: @@ -219,8 +222,8 @@ bool CFX_Barcode::SetTextLocation(BC_TEXT_LOC location) { return m_pBCEngine && memptr ? (m_pBCEngine.get()->*memptr)(location) : false; } -bool CFX_Barcode::SetWideNarrowRatio(int32_t ratio) { - typedef bool (CBC_CodeBase::*memptrtype)(int32_t); +bool CFX_Barcode::SetWideNarrowRatio(int8_t ratio) { + typedef bool (CBC_CodeBase::*memptrtype)(int8_t); memptrtype memptr = nullptr; switch (GetType()) { case BC_CODE39: @@ -235,8 +238,8 @@ bool CFX_Barcode::SetWideNarrowRatio(int32_t ratio) { return m_pBCEngine && memptr ? (m_pBCEngine.get()->*memptr)(ratio) : false; } -bool CFX_Barcode::SetStartChar(FX_CHAR start) { - typedef bool (CBC_CodeBase::*memptrtype)(FX_CHAR); +bool CFX_Barcode::SetStartChar(char start) { + typedef bool (CBC_CodeBase::*memptrtype)(char); memptrtype memptr = nullptr; switch (GetType()) { case BC_CODABAR: @@ -248,8 +251,8 @@ bool CFX_Barcode::SetStartChar(FX_CHAR start) { return m_pBCEngine && memptr ? (m_pBCEngine.get()->*memptr)(start) : false; } -bool CFX_Barcode::SetEndChar(FX_CHAR end) { - typedef bool (CBC_CodeBase::*memptrtype)(FX_CHAR); +bool CFX_Barcode::SetEndChar(char end) { + typedef bool (CBC_CodeBase::*memptrtype)(char); memptrtype memptr = nullptr; switch (GetType()) { case BC_CODABAR: @@ -261,19 +264,6 @@ bool CFX_Barcode::SetEndChar(FX_CHAR end) { return m_pBCEngine && memptr ? (m_pBCEngine.get()->*memptr)(end) : false; } -bool CFX_Barcode::SetVersion(int32_t version) { - typedef bool (CBC_CodeBase::*memptrtype)(int32_t); - memptrtype memptr = nullptr; - switch (GetType()) { - case BC_QR_CODE: - memptr = (memptrtype)&CBC_QRCode::SetVersion; - break; - default: - break; - } - return m_pBCEngine && memptr ? (m_pBCEngine.get()->*memptr)(version) : false; -} - bool CFX_Barcode::SetErrorCorrectionLevel(int32_t level) { typedef bool (CBC_CodeBase::*memptrtype)(int32_t); memptrtype memptr = nullptr; @@ -289,6 +279,7 @@ bool CFX_Barcode::SetErrorCorrectionLevel(int32_t level) { } return m_pBCEngine && memptr ? (m_pBCEngine.get()->*memptr)(level) : false; } + bool CFX_Barcode::SetTruncated(bool truncated) { typedef void (CBC_CodeBase::*memptrtype)(bool); memptrtype memptr = nullptr; @@ -303,14 +294,11 @@ bool CFX_Barcode::SetTruncated(bool truncated) { : false; } -bool CFX_Barcode::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - return m_pBCEngine && m_pBCEngine->Encode(contents, isDevice, e); +bool CFX_Barcode::Encode(const WideStringView& contents) { + return m_pBCEngine && m_pBCEngine->Encode(contents); } bool CFX_Barcode::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - return m_pBCEngine && m_pBCEngine->RenderDevice(device, matrix, e); + const CFX_Matrix* matrix) { + return m_pBCEngine && m_pBCEngine->RenderDevice(device, matrix); } diff --git a/xfa/fwl/cfx_barcode.h b/xfa/fwl/cfx_barcode.h index f639977cfc13c0040154917198b6c4d2e7a954ff..eec4648e822a69ab4da5c63868806a16a69746ea 100644 --- a/xfa/fwl/cfx_barcode.h +++ b/xfa/fwl/cfx_barcode.h @@ -13,7 +13,7 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/fx_system.h" #include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/BC_Library.h" +#include "fxbarcode/BC_Library.h" class CBC_CodeBase; class CFX_Font; @@ -27,11 +27,9 @@ class CFX_Barcode { bool Create(BC_TYPE type); BC_TYPE GetType(); - bool Encode(const CFX_WideStringC& contents, bool isDevice, int32_t& e); + bool Encode(const WideStringView& contents); - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e); + bool RenderDevice(CFX_RenderDevice* device, const CFX_Matrix* matrix); bool SetCharEncoding(BC_CHAR_ENCODING encoding); @@ -46,15 +44,14 @@ class CFX_Barcode { bool SetCalChecksum(bool state); bool SetFont(CFX_Font* pFont); - bool SetFontSize(FX_FLOAT size); + bool SetFontSize(float size); bool SetFontColor(FX_ARGB color); bool SetTextLocation(BC_TEXT_LOC location); - bool SetWideNarrowRatio(int32_t ratio); - bool SetStartChar(FX_CHAR start); - bool SetEndChar(FX_CHAR end); - bool SetVersion(int32_t version); + bool SetWideNarrowRatio(int8_t ratio); + bool SetStartChar(char start); + bool SetEndChar(char end); bool SetErrorCorrectionLevel(int32_t level); bool SetTruncated(bool truncated); diff --git a/xfa/fwl/cfx_barcode_unittest.cpp b/xfa/fwl/cfx_barcode_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe8aee4709c67731b5257fced6702d57f6d21804 --- /dev/null +++ b/xfa/fwl/cfx_barcode_unittest.cpp @@ -0,0 +1,145 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fwl/cfx_barcode.h" + +#include <memory> +#include <string> +#include <utility> + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_renderdevice.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" + +class BarcodeTest : public testing::Test { + public: + void SetUp() override { + BC_Library_Init(); + barcode_ = pdfium::MakeUnique<CFX_Barcode>(); + + auto device = pdfium::MakeUnique<CFX_DefaultRenderDevice>(); + auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + if (bitmap->Create(640, 480, FXDIB_Rgb32)) + bitmap_ = bitmap; + ASSERT_TRUE(bitmap_); + ASSERT_TRUE(device->Attach(bitmap_, false, nullptr, false)); + device_ = std::move(device); + } + + void TearDown() override { + bitmap_.Reset(); + device_.reset(); + barcode_.reset(); + BC_Library_Destroy(); + } + + CFX_Barcode* barcode() const { return barcode_.get(); } + + bool Create(BC_TYPE type) { + if (!barcode_->Create(type)) + return false; + + barcode_->SetModuleHeight(300); + barcode_->SetModuleWidth(420); + barcode_->SetHeight(298); + barcode_->SetWidth(418); + return true; + } + + bool RenderDevice() { + return barcode_->RenderDevice(device_.get(), &matrix_); + } + + std::string BitmapChecksum() { + return GenerateMD5Base16(bitmap_->GetBuffer(), + bitmap_->GetPitch() * bitmap_->GetHeight()); + } + + protected: + CFX_Matrix matrix_; + std::unique_ptr<CFX_Barcode> barcode_; + std::unique_ptr<CFX_RenderDevice> device_; + RetainPtr<CFX_DIBitmap> bitmap_; +}; + +TEST_F(BarcodeTest, Code39) { + EXPECT_TRUE(Create(BC_CODE39)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("cd4cd3f36da38ff58d9f621827018903", BitmapChecksum()); +} + +TEST_F(BarcodeTest, CodaBar) { + EXPECT_TRUE(Create(BC_CODABAR)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("481189dc4f86eddb8c42343c9b8ef1dd", BitmapChecksum()); +} + +TEST_F(BarcodeTest, Code128) { + EXPECT_TRUE(Create(BC_CODE128)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("11b21c178a9fd866d8be196c2103b263", BitmapChecksum()); +} + +TEST_F(BarcodeTest, Code128_B) { + EXPECT_TRUE(Create(BC_CODE128_B)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("11b21c178a9fd866d8be196c2103b263", BitmapChecksum()); +} + +TEST_F(BarcodeTest, Code128_C) { + EXPECT_TRUE(Create(BC_CODE128_C)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("6284ec8503d5a948c9518108da33cdd3", BitmapChecksum()); +} + +TEST_F(BarcodeTest, Ean8) { + EXPECT_TRUE(Create(BC_EAN8)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("22d85bcb02d48f48813f02a1cc9cfe8c", BitmapChecksum()); +} + +TEST_F(BarcodeTest, UPCA) { + EXPECT_TRUE(Create(BC_UPCA)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("cce41fc30852744c44b3353059b568b4", BitmapChecksum()); +} + +TEST_F(BarcodeTest, Ean13) { + EXPECT_TRUE(Create(BC_EAN13)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("187091ec1fd1830fc4d41d40a923d4fb", BitmapChecksum()); +} + +TEST_F(BarcodeTest, Pdf417) { + EXPECT_TRUE(Create(BC_PDF417)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("2bdb9b39f20c5763da6a0d7c7b1f6933", BitmapChecksum()); +} + +TEST_F(BarcodeTest, DataMatrix) { + EXPECT_TRUE(Create(BC_DATAMATRIX)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("5e5cd9a680b86fcd4ffd53ed36e3c980", BitmapChecksum()); +} + +TEST_F(BarcodeTest, QrCode) { + EXPECT_TRUE(Create(BC_QR_CODE)); + EXPECT_TRUE(barcode()->Encode(L"clams")); + RenderDevice(); + EXPECT_EQ("4751c6e0f67749fabe24f787128decee", BitmapChecksum()); +} diff --git a/xfa/fwl/ifwl_themeprovider.h b/xfa/fwl/ifwl_themeprovider.h index 21a12a55f2a53605afb6cee0d8c050046527efe3..eba308597cda7809e6649cd3408d534d313593b7 100644 --- a/xfa/fwl/ifwl_themeprovider.h +++ b/xfa/fwl/ifwl_themeprovider.h @@ -8,8 +8,10 @@ #define XFA_FWL_IFWL_THEMEPROVIDER_H_ #include "core/fxcrt/fx_coordinates.h" -#include "xfa/fwl/theme/cfwl_widgettp.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/fx_dib.h" +class CFGAS_GEFont; class CFWL_ThemeBackground; class CFWL_ThemePart; class CFWL_ThemeText; @@ -26,8 +28,7 @@ class IFWL_ThemeProvider { virtual float GetCYBorderSize() const = 0; virtual CFX_RectF GetUIMargin(CFWL_ThemePart* pThemePart) const = 0; virtual float GetFontSize(CFWL_ThemePart* pThemePart) const = 0; - virtual CFX_RetainPtr<CFGAS_GEFont> GetFont( - CFWL_ThemePart* pThemePart) const = 0; + virtual RetainPtr<CFGAS_GEFont> GetFont(CFWL_ThemePart* pThemePart) const = 0; virtual float GetLineHeight(CFWL_ThemePart* pThemePart) const = 0; virtual float GetScrollBarWidth() const = 0; virtual FX_COLORREF GetTextColor(CFWL_ThemePart* pThemePart) const = 0; diff --git a/xfa/fwl/ifwl_widgetdelegate.h b/xfa/fwl/ifwl_widgetdelegate.h index a96f00dc9e960b73ed17175e05b20e64f943dd94..09bac9ab4e50393b373a7c45d50e35eafcdf837a 100644 --- a/xfa/fwl/ifwl_widgetdelegate.h +++ b/xfa/fwl/ifwl_widgetdelegate.h @@ -11,7 +11,7 @@ class CFWL_Event; class CFWL_Message; -class CFX_Graphics; +class CXFA_Graphics; class CFX_Matrix; class IFWL_WidgetDelegate { @@ -20,8 +20,8 @@ class IFWL_WidgetDelegate { virtual void OnProcessMessage(CFWL_Message* pMessage) = 0; virtual void OnProcessEvent(CFWL_Event* pEvent) = 0; - virtual void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) = 0; + virtual void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) = 0; }; #endif // XFA_FWL_IFWL_WIDGETDELEGATE_H_ diff --git a/xfa/fwl/ifwl_widgetmgrdelegate.h b/xfa/fwl/ifwl_widgetmgrdelegate.h deleted file mode 100644 index 9f0b5708b38e38dce64f4a9a9b19e31c0e9da264..0000000000000000000000000000000000000000 --- a/xfa/fwl/ifwl_widgetmgrdelegate.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FWL_IFWL_WIDGETMGRDELEGATE_H_ -#define XFA_FWL_IFWL_WIDGETMGRDELEGATE_H_ - -class CFWL_Message; -class CFX_Graphics; -class CFX_Matrix; -class CFWL_Widget; - -class CFWL_WidgetMgrDelegate { - public: - virtual void OnSetCapability(uint32_t dwCapability) = 0; - virtual void OnProcessMessageToForm(CFWL_Message* pMessage) = 0; - virtual void OnDrawWidget(CFWL_Widget* pWidget, - CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) = 0; -}; - -#endif // XFA_FWL_IFWL_WIDGETMGRDELEGATE_H_ diff --git a/xfa/fwl/theme/README.md b/xfa/fwl/theme/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7a69932929c99f84fcb98cb0c360144793d66d19 --- /dev/null +++ b/xfa/fwl/theme/README.md @@ -0,0 +1,29 @@ +xfa/fwl/theme contains code for rendering XFA widgets. + +TP stands for Theme Part. + +CFWL_WidgetTP contains much of the code common to more than one widget. + +The other CFWL_TP classes derive from it and know how to draw the pieces +specific to their respective widget. + +The inheritance hierarchy for this directory is: + +* CFWL_WidgetTP + * CFWL_BarcodeTP + * CFWL_CaretTP + * CFWL_CheckboxTP + * CFWL_ComboBowTP + * CFWL_DateTimePickerTP + * CFWL_EditTP + * CFWL_ListBoxTP + * CFWL_MonthCalendarTP + * CFWL_PictureBoxTP + * CFWL_PushButtonTP + * CFWL_ScrollBarTP + +All these widget TP classes are composed into CXFA_FWLTheme, which implements +IFWL_ThemeProvider (and is the only class that does). CXFA_FWLTheme receives +DrawBackground() calls from CFWL widgets to draw themselves and routes them to +the TP (Theme Part) corresponding to that widget. + diff --git a/xfa/fwl/theme/cfwl_carettp.cpp b/xfa/fwl/theme/cfwl_carettp.cpp index 4a04f869f4a0e0551aedeec56396aa18a0cb365c..973531958ac380368bd98c9b1831cc38cb824b7b 100644 --- a/xfa/fwl/theme/cfwl_carettp.cpp +++ b/xfa/fwl/theme/cfwl_carettp.cpp @@ -9,8 +9,8 @@ #include "xfa/fwl/cfwl_caret.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" CFWL_CaretTP::CFWL_CaretTP() {} CFWL_CaretTP::~CFWL_CaretTP() {} @@ -25,7 +25,7 @@ void CFWL_CaretTP::DrawBackground(CFWL_ThemeBackground* pParams) { return; DrawCaretBK(pParams->m_pGraphics, pParams->m_dwStates, - &(pParams->m_rtPart), (CFX_Color*)pParams->m_pData, + &(pParams->m_rtPart), (CXFA_GEColor*)pParams->m_pData, &(pParams->m_matrix)); break; } @@ -34,19 +34,18 @@ void CFWL_CaretTP::DrawBackground(CFWL_ThemeBackground* pParams) { } } -void CFWL_CaretTP::DrawCaretBK(CFX_Graphics* pGraphics, +void CFWL_CaretTP::DrawCaretBK(CXFA_Graphics* pGraphics, uint32_t dwStates, const CFX_RectF* pRect, - CFX_Color* crFill, + CXFA_GEColor* crFill, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rect = *pRect; path.AddRectangle(rect.left, rect.top, rect.width, rect.height); if (crFill) { - pGraphics->SetFillColor(crFill); + pGraphics->SetFillColor(*crFill); } else { - CFX_Color crFilltemp(ArgbEncode(255, 0, 0, 0)); - pGraphics->SetFillColor(&crFilltemp); + pGraphics->SetFillColor(CXFA_GEColor(ArgbEncode(255, 0, 0, 0))); } pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } diff --git a/xfa/fwl/theme/cfwl_carettp.h b/xfa/fwl/theme/cfwl_carettp.h index f7d44b7f8ed3554b62a1e58ebc1847a867ac7986..8b88feeda326ddbdbd4806021eca5bff27616fcb 100644 --- a/xfa/fwl/theme/cfwl_carettp.h +++ b/xfa/fwl/theme/cfwl_carettp.h @@ -18,10 +18,10 @@ class CFWL_CaretTP : public CFWL_WidgetTP { void DrawBackground(CFWL_ThemeBackground* pParams) override; protected: - void DrawCaretBK(CFX_Graphics* pGraphics, + void DrawCaretBK(CXFA_Graphics* pGraphics, uint32_t dwStates, const CFX_RectF* pRect, - CFX_Color* crFill, + CXFA_GEColor* crFill, CFX_Matrix* pMatrix = nullptr); }; diff --git a/xfa/fwl/theme/cfwl_checkboxtp.cpp b/xfa/fwl/theme/cfwl_checkboxtp.cpp index 1d185b4c3379e78bb3a99497bbdd3c5d4077bdf9..82fdc1a18a6f6f56af2834f617945df93dda8c3f 100644 --- a/xfa/fwl/theme/cfwl_checkboxtp.cpp +++ b/xfa/fwl/theme/cfwl_checkboxtp.cpp @@ -8,18 +8,25 @@ #include "core/fxge/cfx_pathdata.h" #include "third_party/base/ptr_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_checkbox.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_themetext.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" namespace { const int kSignPath = 100; +CFX_PointF ScaleBezierPoint(const CFX_PointF& point) { + CFX_PointF scaled_point(point); + scaled_point.x *= FX_BEZIER; + scaled_point.y *= FX_BEZIER; + return scaled_point; +} + } // namespace #define CHECKBOX_COLOR_BOXLT1 (ArgbEncode(255, 172, 168, 153)) @@ -56,7 +63,7 @@ void CFWL_CheckBoxTP::DrawText(CFWL_ThemeText* pParams) { CFWL_WidgetTP::DrawText(pParams); } -void CFWL_CheckBoxTP::DrawSignCheck(CFX_Graphics* pGraphics, +void CFWL_CheckBoxTP::DrawSignCheck(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix) { @@ -64,100 +71,94 @@ void CFWL_CheckBoxTP::DrawSignCheck(CFX_Graphics* pGraphics, InitCheckPath(pRtSign->width); CFX_Matrix mt; - mt.SetIdentity(); mt.Translate(pRtSign->left, pRtSign->top); mt.Concat(*pMatrix); - CFX_Color crFill(argbFill); pGraphics->SaveGraphState(); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(argbFill)); pGraphics->FillPath(m_pCheckPath.get(), FXFILL_WINDING, &mt); pGraphics->RestoreGraphState(); } -void CFWL_CheckBoxTP::DrawSignCircle(CFX_Graphics* pGraphics, +void CFWL_CheckBoxTP::DrawSignCircle(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; path.AddEllipse(*pRtSign); - CFX_Color crFill(argbFill); pGraphics->SaveGraphState(); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(argbFill)); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_CheckBoxTP::DrawSignCross(CFX_Graphics* pGraphics, +void CFWL_CheckBoxTP::DrawSignCross(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix) { - CFX_Path path; - FX_FLOAT fRight = pRtSign->right(); - FX_FLOAT fBottom = pRtSign->bottom(); + CXFA_GEPath path; + float fRight = pRtSign->right(); + float fBottom = pRtSign->bottom(); path.AddLine(pRtSign->TopLeft(), CFX_PointF(fRight, fBottom)); path.AddLine(CFX_PointF(pRtSign->left, fBottom), CFX_PointF(fRight, pRtSign->top)); - CFX_Color crFill(argbFill); pGraphics->SaveGraphState(); - pGraphics->SetStrokeColor(&crFill); + pGraphics->SetStrokeColor(CXFA_GEColor(argbFill)); pGraphics->SetLineWidth(1.0f); pGraphics->StrokePath(&path, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_CheckBoxTP::DrawSignDiamond(CFX_Graphics* pGraphics, +void CFWL_CheckBoxTP::DrawSignDiamond(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix) { - CFX_Path path; - FX_FLOAT fWidth = pRtSign->width; - FX_FLOAT fHeight = pRtSign->height; - FX_FLOAT fBottom = pRtSign->bottom(); + CXFA_GEPath path; + float fWidth = pRtSign->width; + float fHeight = pRtSign->height; + float fBottom = pRtSign->bottom(); path.MoveTo(CFX_PointF(pRtSign->left + fWidth / 2, pRtSign->top)); path.LineTo(CFX_PointF(pRtSign->left, pRtSign->top + fHeight / 2)); path.LineTo(CFX_PointF(pRtSign->left + fWidth / 2, fBottom)); path.LineTo(CFX_PointF(pRtSign->right(), pRtSign->top + fHeight / 2)); path.LineTo(CFX_PointF(pRtSign->left + fWidth / 2, pRtSign->top)); - CFX_Color crFill(argbFill); pGraphics->SaveGraphState(); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(argbFill)); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_CheckBoxTP::DrawSignSquare(CFX_Graphics* pGraphics, +void CFWL_CheckBoxTP::DrawSignSquare(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; path.AddRectangle(pRtSign->left, pRtSign->top, pRtSign->width, pRtSign->height); - CFX_Color crFill(argbFill); pGraphics->SaveGraphState(); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(argbFill)); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_CheckBoxTP::DrawSignStar(CFX_Graphics* pGraphics, +void CFWL_CheckBoxTP::DrawSignStar(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix) { - CFX_Path path; - FX_FLOAT fBottom = pRtSign->bottom(); - FX_FLOAT fRadius = - (pRtSign->top - fBottom) / (1 + static_cast<FX_FLOAT>(cos(FX_PI / 5.0f))); + CXFA_GEPath path; + float fBottom = pRtSign->bottom(); + float fRadius = + (pRtSign->top - fBottom) / (1 + static_cast<float>(cos(FX_PI / 5.0f))); CFX_PointF ptCenter((pRtSign->left + pRtSign->right()) / 2.0f, (pRtSign->top + fBottom) / 2.0f); CFX_PointF points[5]; - FX_FLOAT fAngel = FX_PI / 10.0f; + float fAngel = FX_PI / 10.0f; for (int32_t i = 0; i < 5; i++) { points[i] = - ptCenter + CFX_PointF(fRadius * static_cast<FX_FLOAT>(cos(fAngel)), - fRadius * static_cast<FX_FLOAT>(sin(fAngel))); + ptCenter + CFX_PointF(fRadius * static_cast<float>(cos(fAngel)), + fRadius * static_cast<float>(sin(fAngel))); fAngel += FX_PI * 2 / 5.0f; } @@ -170,10 +171,8 @@ void CFWL_CheckBoxTP::DrawSignStar(CFX_Graphics* pGraphics, path.LineTo(points[nNext]); } - - CFX_Color crFill(argbFill); pGraphics->SaveGraphState(); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(argbFill)); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pGraphics->RestoreGraphState(); } @@ -216,13 +215,13 @@ void CFWL_CheckBoxTP::SetThemeData() { m_pThemeData->clrSignNeutralPressed = ArgbEncode(255, 28, 134, 26); } -void CFWL_CheckBoxTP::InitCheckPath(FX_FLOAT fCheckLen) { +void CFWL_CheckBoxTP::InitCheckPath(float fCheckLen) { if (!m_pCheckPath) { - m_pCheckPath = pdfium::MakeUnique<CFX_Path>(); + m_pCheckPath = pdfium::MakeUnique<CXFA_GEPath>(); - FX_FLOAT fWidth = kSignPath; - FX_FLOAT fHeight = -kSignPath; - FX_FLOAT fBottom = kSignPath; + float fWidth = kSignPath; + float fHeight = -kSignPath; + float fBottom = kSignPath; CFX_PointF pt1(fWidth / 15.0f, fBottom + fHeight * 2 / 5.0f); CFX_PointF pt2(fWidth / 4.5f, fBottom + fHeight / 16.0f); CFX_PointF pt3(fWidth / 3.0f, fBottom); @@ -242,28 +241,28 @@ void CFWL_CheckBoxTP::InitCheckPath(FX_FLOAT fCheckLen) { CFX_PointF pt15(fWidth / 3.5f, fBottom + fHeight * 3.5f / 5.0f); m_pCheckPath->MoveTo(pt1); - CFX_PointF p1 = CFX_PointF(pt12.x - pt1.x, pt12.y - pt1.y) * FX_BEZIER; - CFX_PointF p2 = CFX_PointF(pt21.x - pt2.x, pt21.y - pt2.y) * FX_BEZIER; + CFX_PointF p1 = ScaleBezierPoint(pt12 - pt1); + CFX_PointF p2 = ScaleBezierPoint(pt21 - pt2); m_pCheckPath->BezierTo(pt1 + p1, pt2 + p2, pt2); - p1 = CFX_PointF(pt23.x - pt2.x, pt23.y - pt2.y) * FX_BEZIER; - p2 = CFX_PointF(pt32.x - pt3.x, pt32.y - pt3.y) * FX_BEZIER; + p1 = ScaleBezierPoint(pt23 - pt2); + p2 = ScaleBezierPoint(pt32 - pt3); m_pCheckPath->BezierTo(pt2 + p1, pt3 + p2, pt3); - p1 = CFX_PointF(pt34.x - pt3.x, pt34.y - pt3.y) * FX_BEZIER; - p2 = CFX_PointF(pt43.x - pt4.x, pt43.y - pt4.y) * FX_BEZIER; + p1 = ScaleBezierPoint(pt34 - pt3); + p2 = ScaleBezierPoint(pt43 - pt4); m_pCheckPath->BezierTo(pt3 + p1, pt4 + p2, pt4); - p1 = CFX_PointF(pt45.x - pt4.x, pt45.y - pt4.y) * FX_BEZIER; - p2 = CFX_PointF(pt54.x - pt5.x, pt54.y - pt5.y) * FX_BEZIER; + p1 = ScaleBezierPoint(pt45 - pt4); + p2 = ScaleBezierPoint(pt54 - pt5); m_pCheckPath->BezierTo(pt4 + p1, pt5 + p2, pt5); - p1 = CFX_PointF(pt51.x - pt5.x, pt51.y - pt5.y) * FX_BEZIER; - p2 = CFX_PointF(pt15.x - pt1.x, pt15.y - pt1.y) * FX_BEZIER; + p1 = ScaleBezierPoint(pt51 - pt5); + p2 = ScaleBezierPoint(pt15 - pt1); m_pCheckPath->BezierTo(pt5 + p1, pt1 + p2, pt1); - FX_FLOAT fScale = fCheckLen / kSignPath; - CFX_Matrix mt(1, 0, 0, 1, 0, 0); + float fScale = fCheckLen / kSignPath; + CFX_Matrix mt; mt.Scale(fScale, fScale); m_pCheckPath->TransformBy(mt); @@ -282,7 +281,7 @@ void CFWL_CheckBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { } void CFWL_CheckBoxTP::DrawCheckSign(CFWL_Widget* pWidget, - CFX_Graphics* pGraphics, + CXFA_Graphics* pGraphics, const CFX_RectF& pRtBox, int32_t iState, CFX_Matrix* pMatrix) { diff --git a/xfa/fwl/theme/cfwl_checkboxtp.h b/xfa/fwl/theme/cfwl_checkboxtp.h index 979b970b3934ecbefb968c6609a340eadc727f88..e373b382a87a93b36dab875a15e31a21475ab2f0 100644 --- a/xfa/fwl/theme/cfwl_checkboxtp.h +++ b/xfa/fwl/theme/cfwl_checkboxtp.h @@ -36,39 +36,39 @@ class CFWL_CheckBoxTP : public CFWL_WidgetTP { }; void DrawCheckSign(CFWL_Widget* pWidget, - CFX_Graphics* pGraphics, + CXFA_Graphics* pGraphics, const CFX_RectF& pRtBox, int32_t iState, CFX_Matrix* pMatrix); - void DrawSignCheck(CFX_Graphics* pGraphics, + void DrawSignCheck(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix); - void DrawSignCircle(CFX_Graphics* pGraphics, + void DrawSignCircle(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix); - void DrawSignCross(CFX_Graphics* pGraphics, + void DrawSignCross(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix); - void DrawSignDiamond(CFX_Graphics* pGraphics, + void DrawSignDiamond(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix); - void DrawSignSquare(CFX_Graphics* pGraphics, + void DrawSignSquare(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix); - void DrawSignStar(CFX_Graphics* pGraphics, + void DrawSignStar(CXFA_Graphics* pGraphics, const CFX_RectF* pRtSign, FX_ARGB argbFill, CFX_Matrix* pMatrix); - void InitCheckPath(FX_FLOAT fCheckLen); + void InitCheckPath(float fCheckLen); std::unique_ptr<CKBThemeData> m_pThemeData; - std::unique_ptr<CFX_Path> m_pCheckPath; + std::unique_ptr<CXFA_GEPath> m_pCheckPath; private: void SetThemeData(); diff --git a/xfa/fwl/theme/cfwl_comboboxtp.cpp b/xfa/fwl/theme/cfwl_comboboxtp.cpp index 53a6eae722fa9a93dfa02352bcf7f5333f79c50a..76953423e6f71c2a6981547d51fbe4925f869756 100644 --- a/xfa/fwl/theme/cfwl_comboboxtp.cpp +++ b/xfa/fwl/theme/cfwl_comboboxtp.cpp @@ -10,8 +10,8 @@ #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" CFWL_ComboBoxTP::CFWL_ComboBoxTP() {} @@ -27,7 +27,7 @@ void CFWL_ComboBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { break; } case CFWL_Part::Background: { - CFX_Path path; + CXFA_GEPath path; CFX_RectF& rect = pParams->m_rtPart; path.AddRectangle(rect.left, rect.top, rect.width, rect.height); FX_ARGB argb_color; @@ -42,8 +42,7 @@ void CFWL_ComboBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { argb_color = 0xFFFFFFFF; } pParams->m_pGraphics->SaveGraphState(); - CFX_Color cr(argb_color); - pParams->m_pGraphics->SetFillColor(&cr); + pParams->m_pGraphics->SetFillColor(CXFA_GEColor(argb_color)); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, &pParams->m_matrix); pParams->m_pGraphics->RestoreGraphState(); break; @@ -64,11 +63,11 @@ void CFWL_ComboBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { void CFWL_ComboBoxTP::DrawStrethHandler(CFWL_ThemeBackground* pParams, uint32_t dwStates, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; path.AddRectangle(pParams->m_rtPart.left, pParams->m_rtPart.top, pParams->m_rtPart.width - 1, pParams->m_rtPart.height); - CFX_Color cr(ArgbEncode(0xff, 0xff, 0, 0)); - pParams->m_pGraphics->SetFillColor(&cr); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(ArgbEncode(0xff, 0xff, 0, 0))); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, &pParams->m_matrix); } diff --git a/xfa/fwl/theme/cfwl_edittp.cpp b/xfa/fwl/theme/cfwl_edittp.cpp index 43160177d75aac15de1a62f8ffefb685c7df7bd2..599a4dda690653d7da7b10529dc04f787a3310ee 100644 --- a/xfa/fwl/theme/cfwl_edittp.cpp +++ b/xfa/fwl/theme/cfwl_edittp.cpp @@ -9,10 +9,12 @@ #include "xfa/fwl/cfwl_edit.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxfa/app/xfa_fwltheme.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fwltheme.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" CFWL_EditTP::CFWL_EditTP() {} @@ -21,17 +23,17 @@ CFWL_EditTP::~CFWL_EditTP() {} void CFWL_EditTP::DrawBackground(CFWL_ThemeBackground* pParams) { if (CFWL_Part::CombTextLine == pParams->m_iPart) { CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); + CXFA_Border* borderUI = pWidget->GetNode()->GetWidgetAcc()->GetUIBorder(); FX_ARGB cr = 0xFF000000; - FX_FLOAT fWidth = 1.0f; - if (CXFA_Border borderUI = pWidget->GetDataAcc()->GetUIBorder()) { - CXFA_Edge edge = borderUI.GetEdge(0); + float fWidth = 1.0f; + if (borderUI) { + CXFA_Edge* edge = borderUI->GetEdgeIfExists(0); if (edge) { - cr = edge.GetColor(); - fWidth = edge.GetThickness(); + cr = edge->GetColor(); + fWidth = edge->GetThickness(); } } - CFX_Color crLine(cr); - pParams->m_pGraphics->SetStrokeColor(&crLine); + pParams->m_pGraphics->SetStrokeColor(CXFA_GEColor(cr)); pParams->m_pGraphics->SetLineWidth(fWidth); pParams->m_pGraphics->StrokePath(pParams->m_pPath, &pParams->m_matrix); return; @@ -44,28 +46,27 @@ void CFWL_EditTP::DrawBackground(CFWL_ThemeBackground* pParams) { } case CFWL_Part::Background: { if (pParams->m_pPath) { - CFX_Graphics* pGraphics = pParams->m_pGraphics; + CXFA_Graphics* pGraphics = pParams->m_pGraphics; pGraphics->SaveGraphState(); - CFX_Color crSelected(FWLTHEME_COLOR_BKSelected); - pGraphics->SetFillColor(&crSelected); + pGraphics->SetFillColor(CXFA_GEColor(FWLTHEME_COLOR_BKSelected)); pGraphics->FillPath(pParams->m_pPath, FXFILL_WINDING, &pParams->m_matrix); pGraphics->RestoreGraphState(); } else { - CFX_Path path; + CXFA_GEPath path; path.AddRectangle(pParams->m_rtPart.left, pParams->m_rtPart.top, pParams->m_rtPart.width, pParams->m_rtPart.height); - CFX_Color cr(FWLTHEME_COLOR_Background); + CXFA_GEColor cr(FWLTHEME_COLOR_Background); if (!pParams->m_bStaticBackground) { if (pParams->m_dwStates & CFWL_PartState_Disabled) - cr.Set(FWLTHEME_COLOR_EDGERB1); + cr = CXFA_GEColor(FWLTHEME_COLOR_EDGERB1); else if (pParams->m_dwStates & CFWL_PartState_ReadOnly) - cr.Set(ArgbEncode(255, 236, 233, 216)); + cr = CXFA_GEColor(ArgbEncode(255, 236, 233, 216)); else - cr.Set(0xFFFFFFFF); + cr = CXFA_GEColor(0xFFFFFFFF); } pParams->m_pGraphics->SaveGraphState(); - pParams->m_pGraphics->SetFillColor(&cr); + pParams->m_pGraphics->SetFillColor(cr); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, &pParams->m_matrix); pParams->m_pGraphics->RestoreGraphState(); @@ -73,11 +74,8 @@ void CFWL_EditTP::DrawBackground(CFWL_ThemeBackground* pParams) { break; } case CFWL_Part::CombTextLine: { - FX_ARGB cr = 0xFF000000; - FX_FLOAT fWidth = 1.0f; - CFX_Color crLine(cr); - pParams->m_pGraphics->SetStrokeColor(&crLine); - pParams->m_pGraphics->SetLineWidth(fWidth); + pParams->m_pGraphics->SetStrokeColor(CXFA_GEColor(0xFF000000)); + pParams->m_pGraphics->SetLineWidth(1.0f); pParams->m_pGraphics->StrokePath(pParams->m_pPath, &pParams->m_matrix); break; } diff --git a/xfa/fwl/theme/cfwl_listboxtp.cpp b/xfa/fwl/theme/cfwl_listboxtp.cpp index 4e00420df53ba2bc7e463e3efd22a72c20724f12..6b8aa768a565848115ee451d5fbebfe16fa22fc2 100644 --- a/xfa/fwl/theme/cfwl_listboxtp.cpp +++ b/xfa/fwl/theme/cfwl_listboxtp.cpp @@ -9,8 +9,8 @@ #include "xfa/fwl/cfwl_listbox.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" CFWL_ListBoxTP::CFWL_ListBoxTP() {} @@ -39,11 +39,6 @@ void CFWL_ListBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { &pParams->m_rtPart, pParams->m_pData, &pParams->m_matrix); break; } - case CFWL_Part::Icon: { - pParams->m_pGraphics->StretchImage(pParams->m_pImage, pParams->m_rtPart, - &pParams->m_matrix); - break; - } case CFWL_Part::Check: { uint32_t color = 0xFF000000; if (pParams->m_dwStates == CFWL_PartState_Checked) { @@ -59,18 +54,17 @@ void CFWL_ListBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { } } -void CFWL_ListBoxTP::DrawListBoxItem(CFX_Graphics* pGraphics, +void CFWL_ListBoxTP::DrawListBoxItem(CXFA_Graphics* pGraphics, uint32_t dwStates, const CFX_RectF* prtItem, void* pData, CFX_Matrix* pMatrix) { if (dwStates & CFWL_PartState_Selected) { pGraphics->SaveGraphState(); - CFX_Color crFill(FWLTHEME_COLOR_BKSelected); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(FWLTHEME_COLOR_BKSelected)); CFX_RectF rt(*prtItem); - CFX_Path path; -#if (_FX_OS_ == _FX_MACOSX_) + CXFA_GEPath path; +#if (_FX_OS_ == _FX_OS_MACOSX_) path.AddRectangle(rt.left, rt.top, rt.width - 1, rt.height - 1); #else path.AddRectangle(rt.left, rt.top, rt.width, rt.height); diff --git a/xfa/fwl/theme/cfwl_listboxtp.h b/xfa/fwl/theme/cfwl_listboxtp.h index dcf5ec89bee44ab25201d9bda0558186af74b38c..5dc45af4fec0dcbe622a00fda157bae3eaad4ad2 100644 --- a/xfa/fwl/theme/cfwl_listboxtp.h +++ b/xfa/fwl/theme/cfwl_listboxtp.h @@ -18,7 +18,7 @@ class CFWL_ListBoxTP : public CFWL_WidgetTP { void DrawBackground(CFWL_ThemeBackground* pParams) override; protected: - void DrawListBoxItem(CFX_Graphics* pGraphics, + void DrawListBoxItem(CXFA_Graphics* pGraphics, uint32_t dwStates, const CFX_RectF* prtItem, void* pData = nullptr, diff --git a/xfa/fwl/theme/cfwl_monthcalendartp.cpp b/xfa/fwl/theme/cfwl_monthcalendartp.cpp index b14109d0136454ba0530fbbbe877bf7f451260a7..6bb3f186b71748fb102390f4e1da61316ac8da35 100644 --- a/xfa/fwl/theme/cfwl_monthcalendartp.cpp +++ b/xfa/fwl/theme/cfwl_monthcalendartp.cpp @@ -6,14 +6,14 @@ #include "xfa/fwl/theme/cfwl_monthcalendartp.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fwl/cfwl_monthcalendar.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_themetext.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" CFWL_MonthCalendarTP::CFWL_MonthCalendarTP() : m_pThemeData(new MCThemeData) { SetThemeData(); @@ -104,47 +104,42 @@ void CFWL_MonthCalendarTP::DrawText(CFWL_ThemeText* pParams) { void CFWL_MonthCalendarTP::DrawTotalBK(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtTotal(pParams->m_rtPart); path.AddRectangle(rtTotal.left, rtTotal.top, rtTotal.width, rtTotal.height); pParams->m_pGraphics->SaveGraphState(); - - CFX_Color clrBK(m_pThemeData->clrBK); - pParams->m_pGraphics->SetFillColor(&clrBK); + pParams->m_pGraphics->SetFillColor(CXFA_GEColor(m_pThemeData->clrBK)); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } void CFWL_MonthCalendarTP::DrawHeadBk(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtHead = pParams->m_rtPart; path.AddRectangle(rtHead.left, rtHead.top, rtHead.width, rtHead.height); pParams->m_pGraphics->SaveGraphState(); - - CFX_Color clrHeadBK(m_pThemeData->clrBK); - pParams->m_pGraphics->SetFillColor(&clrHeadBK); + pParams->m_pGraphics->SetFillColor(CXFA_GEColor(m_pThemeData->clrBK)); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } void CFWL_MonthCalendarTP::DrawLButton(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtLBtn = pParams->m_rtPart; path.AddRectangle(rtLBtn.left, rtLBtn.top, rtLBtn.width, rtLBtn.height); pParams->m_pGraphics->SaveGraphState(); - - CFX_Color clrLBtnEdge(ArgbEncode(0xff, 205, 219, 243)); - pParams->m_pGraphics->SetStrokeColor(&clrLBtnEdge); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(ArgbEncode(0xff, 205, 219, 243))); pParams->m_pGraphics->StrokePath(&path, pMatrix); if (pParams->m_dwStates & CFWL_PartState_Pressed) { - CFX_Color clrLBtnFill(ArgbEncode(0xff, 174, 198, 242)); - pParams->m_pGraphics->SetFillColor(&clrLBtnFill); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(ArgbEncode(0xff, 174, 198, 242))); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } else { - CFX_Color clrLBtnFill(ArgbEncode(0xff, 227, 235, 249)); - pParams->m_pGraphics->SetFillColor(&clrLBtnFill); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(ArgbEncode(0xff, 227, 235, 249))); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } @@ -156,29 +151,28 @@ void CFWL_MonthCalendarTP::DrawLButton(CFWL_ThemeBackground* pParams, path.LineTo(CFX_PointF(rtLBtn.left + rtLBtn.Width() / 3 * 2, rtLBtn.bottom() - rtLBtn.height / 4)); - CFX_Color clrFlag(ArgbEncode(0xff, 50, 104, 205)); - pParams->m_pGraphics->SetStrokeColor(&clrFlag); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(ArgbEncode(0xff, 50, 104, 205))); pParams->m_pGraphics->StrokePath(&path, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } void CFWL_MonthCalendarTP::DrawRButton(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtRBtn = pParams->m_rtPart; path.AddRectangle(rtRBtn.left, rtRBtn.top, rtRBtn.width, rtRBtn.height); pParams->m_pGraphics->SaveGraphState(); - - CFX_Color clrRBtnEdge(ArgbEncode(0xff, 205, 219, 243)); - pParams->m_pGraphics->SetStrokeColor(&clrRBtnEdge); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(ArgbEncode(0xff, 205, 219, 243))); pParams->m_pGraphics->StrokePath(&path, pMatrix); if (pParams->m_dwStates & CFWL_PartState_Pressed) { - CFX_Color clrRBtnFill(ArgbEncode(0xff, 174, 198, 242)); - pParams->m_pGraphics->SetFillColor(&clrRBtnFill); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(ArgbEncode(0xff, 174, 198, 242))); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } else { - CFX_Color clrRBtnFill(ArgbEncode(0xff, 227, 235, 249)); - pParams->m_pGraphics->SetFillColor(&clrRBtnFill); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(ArgbEncode(0xff, 227, 235, 249))); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } @@ -190,36 +184,34 @@ void CFWL_MonthCalendarTP::DrawRButton(CFWL_ThemeBackground* pParams, path.LineTo(CFX_PointF(rtRBtn.left + rtRBtn.Width() / 3, rtRBtn.bottom() - rtRBtn.height / 4)); - CFX_Color clrFlag(ArgbEncode(0xff, 50, 104, 205)); - pParams->m_pGraphics->SetStrokeColor(&clrFlag); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(ArgbEncode(0xff, 50, 104, 205))); pParams->m_pGraphics->StrokePath(&path, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } void CFWL_MonthCalendarTP::DrawHSeperator(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtHSep = pParams->m_rtPart; path.MoveTo(CFX_PointF(rtHSep.left, rtHSep.top + rtHSep.height / 2)); path.LineTo(CFX_PointF(rtHSep.right(), rtHSep.top + rtHSep.height / 2)); pParams->m_pGraphics->SaveGraphState(); - - CFX_Color clrHSep(m_pThemeData->clrSeperator); - pParams->m_pGraphics->SetStrokeColor(&clrHSep); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrSeperator)); pParams->m_pGraphics->StrokePath(&path, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } void CFWL_MonthCalendarTP::DrawWeekNumSep(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtWeekSep = pParams->m_rtPart; path.MoveTo(rtWeekSep.TopLeft()); path.LineTo(rtWeekSep.BottomLeft()); pParams->m_pGraphics->SaveGraphState(); - - CFX_Color clrHSep(m_pThemeData->clrSeperator); - pParams->m_pGraphics->SetStrokeColor(&clrHSep); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrSeperator)); pParams->m_pGraphics->StrokePath(&path, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } @@ -228,20 +220,20 @@ void CFWL_MonthCalendarTP::DrawDatesInBK(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { pParams->m_pGraphics->SaveGraphState(); if (pParams->m_dwStates & CFWL_PartState_Selected) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtSelDay = pParams->m_rtPart; path.AddRectangle(rtSelDay.left, rtSelDay.top, rtSelDay.width, rtSelDay.height); - CFX_Color clrSelDayBK(m_pThemeData->clrDatesSelectedBK); - pParams->m_pGraphics->SetFillColor(&clrSelDayBK); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(m_pThemeData->clrDatesSelectedBK)); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } else if (pParams->m_dwStates & CFWL_PartState_Hovered) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtSelDay = pParams->m_rtPart; path.AddRectangle(rtSelDay.left, rtSelDay.top, rtSelDay.width, rtSelDay.height); - CFX_Color clrSelDayBK(m_pThemeData->clrDatesHoverBK); - pParams->m_pGraphics->SetFillColor(&clrSelDayBK); + pParams->m_pGraphics->SetFillColor( + CXFA_GEColor(m_pThemeData->clrDatesHoverBK)); pParams->m_pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } pParams->m_pGraphics->RestoreGraphState(); @@ -249,26 +241,26 @@ void CFWL_MonthCalendarTP::DrawDatesInBK(CFWL_ThemeBackground* pParams, void CFWL_MonthCalendarTP::DrawDatesInCircle(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtSelDay = pParams->m_rtPart; path.AddRectangle(rtSelDay.left, rtSelDay.top, rtSelDay.width, rtSelDay.height); pParams->m_pGraphics->SaveGraphState(); - CFX_Color clrSelDayBK(m_pThemeData->clrDatesCircle); - pParams->m_pGraphics->SetStrokeColor(&clrSelDayBK); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrDatesCircle)); pParams->m_pGraphics->StrokePath(&path, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } void CFWL_MonthCalendarTP::DrawTodayCircle(CFWL_ThemeBackground* pParams, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; CFX_RectF rtTodayCircle = pParams->m_rtPart; path.AddRectangle(rtTodayCircle.left, rtTodayCircle.top, rtTodayCircle.width, rtTodayCircle.height); pParams->m_pGraphics->SaveGraphState(); - CFX_Color clrTodayCircle(m_pThemeData->clrDatesCircle); - pParams->m_pGraphics->SetStrokeColor(&clrTodayCircle); + pParams->m_pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrDatesCircle)); pParams->m_pGraphics->StrokePath(&path, pMatrix); pParams->m_pGraphics->RestoreGraphState(); } diff --git a/xfa/fwl/theme/cfwl_monthcalendartp.h b/xfa/fwl/theme/cfwl_monthcalendartp.h index 57438a0551d5292c0b3767f934e5b8777eb43663..6a1b9be3600e9d6e6e44b887ac040ab4e0ac48e0 100644 --- a/xfa/fwl/theme/cfwl_monthcalendartp.h +++ b/xfa/fwl/theme/cfwl_monthcalendartp.h @@ -45,7 +45,7 @@ class CFWL_MonthCalendarTP : public CFWL_WidgetTP { FWLTHEME_STATE GetState(uint32_t dwFWLStates); std::unique_ptr<MCThemeData> m_pThemeData; - CFX_WideString wsResource; + WideString wsResource; private: void SetThemeData(); diff --git a/xfa/fwl/theme/cfwl_pushbuttontp.cpp b/xfa/fwl/theme/cfwl_pushbuttontp.cpp index 56268a8507a72349c935877e6636be640bd1f1cd..3d3b1aabf74e0a6d3dfd4e023a762e878afad31d 100644 --- a/xfa/fwl/theme/cfwl_pushbuttontp.cpp +++ b/xfa/fwl/theme/cfwl_pushbuttontp.cpp @@ -10,8 +10,8 @@ #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" #define PUSHBUTTON_SIZE_Corner 2 @@ -29,10 +29,10 @@ void CFWL_PushButtonTP::DrawBackground(CFWL_ThemeBackground* pParams) { } case CFWL_Part::Background: { CFX_RectF& rect = pParams->m_rtPart; - FX_FLOAT fRight = rect.right(); - FX_FLOAT fBottom = rect.bottom(); + float fRight = rect.right(); + float fBottom = rect.bottom(); - CFX_Path strokePath; + CXFA_GEPath strokePath; strokePath.MoveTo( CFX_PointF(rect.left + PUSHBUTTON_SIZE_Corner, rect.top)); strokePath.LineTo(CFX_PointF(fRight - PUSHBUTTON_SIZE_Corner, rect.top)); @@ -48,10 +48,10 @@ void CFWL_PushButtonTP::DrawBackground(CFWL_ThemeBackground* pParams) { strokePath.LineTo( CFX_PointF(rect.left + PUSHBUTTON_SIZE_Corner, rect.top)); - CFX_Path fillPath; + CXFA_GEPath fillPath; fillPath.AddSubpath(&strokePath); - CFX_Graphics* pGraphics = pParams->m_pGraphics; + CXFA_Graphics* pGraphics = pParams->m_pGraphics; pGraphics->SaveGraphState(); CFX_RectF rtInner(rect); @@ -67,16 +67,14 @@ void CFWL_PushButtonTP::DrawBackground(CFWL_ThemeBackground* pParams) { m_pThemeData->clrEnd[iColor], &fillPath, FXFILL_ALTERNATE, &pParams->m_matrix); - CFX_Color crStroke(m_pThemeData->clrBorder[iColor]); - pGraphics->SetStrokeColor(&crStroke); + pGraphics->SetStrokeColor(CXFA_GEColor(m_pThemeData->clrBorder[iColor])); pGraphics->StrokePath(&strokePath, &pParams->m_matrix); fillPath.Clear(); fillPath.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); - CFX_Color crFill(m_pThemeData->clrFill[iColor]); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(m_pThemeData->clrFill[iColor])); pGraphics->FillPath(&fillPath, FXFILL_WINDING, &pParams->m_matrix); if (pParams->m_dwStates & CFWL_PartState_Focused) { rtInner.Inflate(1, 1, 0, 0); diff --git a/xfa/fwl/theme/cfwl_scrollbartp.cpp b/xfa/fwl/theme/cfwl_scrollbartp.cpp index 121d4dea34186b86e6bd88ae1d5cd35f6e879289..d94eed0ebf377f6adda20c98773c3997bb7fbe3b 100644 --- a/xfa/fwl/theme/cfwl_scrollbartp.cpp +++ b/xfa/fwl/theme/cfwl_scrollbartp.cpp @@ -10,8 +10,8 @@ #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" namespace { @@ -38,7 +38,7 @@ void CFWL_ScrollBarTP::DrawBackground(CFWL_ThemeBackground* pParams) { else if (pParams->m_dwStates & CFWL_PartState_Disabled) eState = FWLTHEME_STATE_Disable; - CFX_Graphics* pGraphics = pParams->m_pGraphics; + CXFA_Graphics* pGraphics = pParams->m_pGraphics; CFX_RectF* pRect = &pParams->m_rtPart; bool bVert = !!pWidget->GetStylesEx(); switch (pParams->m_iPart) { @@ -71,7 +71,7 @@ void CFWL_ScrollBarTP::DrawBackground(CFWL_ThemeBackground* pParams) { } } -void CFWL_ScrollBarTP::DrawThumbBtn(CFX_Graphics* pGraphics, +void CFWL_ScrollBarTP::DrawThumbBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, bool bVert, FWLTHEME_STATE eState, @@ -80,7 +80,7 @@ void CFWL_ScrollBarTP::DrawThumbBtn(CFX_Graphics* pGraphics, if (eState < FWLTHEME_STATE_Normal || eState > FWLTHEME_STATE_Disable) return; - CFX_Path path; + CXFA_GEPath path; CFX_RectF rect(*pRect); if (bVert) { rect.Deflate(1, 0); @@ -92,10 +92,9 @@ void CFWL_ScrollBarTP::DrawThumbBtn(CFX_Graphics* pGraphics, m_pThemeData->clrBtnBK[eState - 1][0], m_pThemeData->clrBtnBK[eState - 1][1], &path, FXFILL_WINDING, pMatrix); - CFX_Color rcStroke; - rcStroke.Set(m_pThemeData->clrBtnBorder[eState - 1]); pGraphics->SaveGraphState(); - pGraphics->SetStrokeColor(&rcStroke); + pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrBtnBorder[eState - 1])); pGraphics->StrokePath(&path, pMatrix); pGraphics->RestoreGraphState(); } else { @@ -108,29 +107,28 @@ void CFWL_ScrollBarTP::DrawThumbBtn(CFX_Graphics* pGraphics, m_pThemeData->clrBtnBK[eState - 1][0], m_pThemeData->clrBtnBK[eState - 1][1], &path, FXFILL_WINDING, pMatrix); - CFX_Color rcStroke; - rcStroke.Set(m_pThemeData->clrBtnBorder[eState - 1]); pGraphics->SaveGraphState(); - pGraphics->SetStrokeColor(&rcStroke); + pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrBtnBorder[eState - 1])); pGraphics->StrokePath(&path, pMatrix); pGraphics->RestoreGraphState(); } } -void CFWL_ScrollBarTP::DrawPaw(CFX_Graphics* pGraphics, +void CFWL_ScrollBarTP::DrawPaw(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, bool bVert, FWLTHEME_STATE eState, CFX_Matrix* pMatrix) { - CFX_Path path; + CXFA_GEPath path; if (bVert) { - FX_FLOAT fPawLen = kPawLength; + float fPawLen = kPawLength; if (pRect->width / 2 <= fPawLen) { fPawLen = (pRect->width - 6) / 2; } - FX_FLOAT fX = pRect->left + pRect->width / 4; - FX_FLOAT fY = pRect->top + pRect->height / 2; + float fX = pRect->left + pRect->width / 4; + float fY = pRect->top + pRect->height / 2; path.MoveTo(CFX_PointF(fX, fY - 4)); path.LineTo(CFX_PointF(fX + fPawLen, fY - 4)); path.MoveTo(CFX_PointF(fX, fY - 2)); @@ -140,10 +138,10 @@ void CFWL_ScrollBarTP::DrawPaw(CFX_Graphics* pGraphics, path.MoveTo(CFX_PointF(fX, fY + 2)); path.LineTo(CFX_PointF(fX + fPawLen, fY + 2)); - CFX_Color clrLight(m_pThemeData->clrPawColorLight[eState - 1]); pGraphics->SetLineWidth(1); - pGraphics->SetStrokeColor(&clrLight); - pGraphics->StrokePath(&path); + pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrPawColorLight[eState - 1])); + pGraphics->StrokePath(&path, nullptr); fX++; path.Clear(); @@ -156,18 +154,18 @@ void CFWL_ScrollBarTP::DrawPaw(CFX_Graphics* pGraphics, path.MoveTo(CFX_PointF(fX, fY + 3)); path.LineTo(CFX_PointF(fX + fPawLen, fY + 3)); - CFX_Color clrDark(m_pThemeData->clrPawColorDark[eState - 1]); pGraphics->SetLineWidth(1); - pGraphics->SetStrokeColor(&clrDark); + pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrPawColorDark[eState - 1])); pGraphics->StrokePath(&path, pMatrix); } else { - FX_FLOAT fPawLen = kPawLength; + float fPawLen = kPawLength; if (pRect->height / 2 <= fPawLen) { fPawLen = (pRect->height - 6) / 2; } - FX_FLOAT fX = pRect->left + pRect->width / 2; - FX_FLOAT fY = pRect->top + pRect->height / 4; + float fX = pRect->left + pRect->width / 2; + float fY = pRect->top + pRect->height / 4; path.MoveTo(CFX_PointF(fX - 4, fY)); path.LineTo(CFX_PointF(fX - 4, fY + fPawLen)); path.MoveTo(CFX_PointF(fX - 2, fY)); @@ -177,9 +175,9 @@ void CFWL_ScrollBarTP::DrawPaw(CFX_Graphics* pGraphics, path.MoveTo(CFX_PointF(fX + 2, fY)); path.LineTo(CFX_PointF(fX + 2, fY + fPawLen)); - CFX_Color clrLight(m_pThemeData->clrPawColorLight[eState - 1]); pGraphics->SetLineWidth(1); - pGraphics->SetStrokeColor(&clrLight); + pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrPawColorLight[eState - 1])); pGraphics->StrokePath(&path, pMatrix); fY++; @@ -193,14 +191,14 @@ void CFWL_ScrollBarTP::DrawPaw(CFX_Graphics* pGraphics, path.MoveTo(CFX_PointF(fX + 3, fY)); path.LineTo(CFX_PointF(fX + 3, fY + fPawLen)); - CFX_Color clrDark(m_pThemeData->clrPawColorDark[eState - 1]); pGraphics->SetLineWidth(1); - pGraphics->SetStrokeColor(&clrDark); + pGraphics->SetStrokeColor( + CXFA_GEColor(m_pThemeData->clrPawColorDark[eState - 1])); pGraphics->StrokePath(&path, pMatrix); } } -void CFWL_ScrollBarTP::DrawTrack(CFX_Graphics* pGraphics, +void CFWL_ScrollBarTP::DrawTrack(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, bool bVert, FWLTHEME_STATE eState, @@ -210,10 +208,9 @@ void CFWL_ScrollBarTP::DrawTrack(CFX_Graphics* pGraphics, return; pGraphics->SaveGraphState(); - CFX_Color colorLine(ArgbEncode(255, 238, 237, 229)); - CFX_Path path; - FX_FLOAT fRight = pRect->right(); - FX_FLOAT fBottom = pRect->bottom(); + CXFA_GEPath path; + float fRight = pRect->right(); + float fBottom = pRect->bottom(); if (bVert) { path.AddRectangle(pRect->left, pRect->top, 1, pRect->height); path.AddRectangle(fRight - 1, pRect->top, 1, pRect->height); @@ -221,21 +218,21 @@ void CFWL_ScrollBarTP::DrawTrack(CFX_Graphics* pGraphics, path.AddRectangle(pRect->left, pRect->top, pRect->width, 1); path.AddRectangle(pRect->left, fBottom - 1, pRect->width, 1); } - pGraphics->SetFillColor(&colorLine); + pGraphics->SetFillColor(CXFA_GEColor(ArgbEncode(255, 238, 237, 229))); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); path.Clear(); path.AddRectangle(pRect->left + 1, pRect->top, pRect->width - 2, pRect->height); - FX_FLOAT x1 = bVert ? pRect->left + 1 : pRect->left; - FX_FLOAT y1 = bVert ? pRect->top : pRect->top + 1; - FX_FLOAT x2 = bVert ? fRight - 1 : pRect->left; - FX_FLOAT y2 = bVert ? pRect->top : fBottom - 1; + float x1 = bVert ? pRect->left + 1 : pRect->left; + float y1 = bVert ? pRect->top : pRect->top + 1; + float x2 = bVert ? fRight - 1 : pRect->left; + float y2 = bVert ? pRect->top : fBottom - 1; pGraphics->RestoreGraphState(); DrawAxialShading(pGraphics, x1, y1, x2, y2, m_pThemeData->clrTrackBKStart, m_pThemeData->clrTrackBKEnd, &path, FXFILL_WINDING, pMatrix); } -void CFWL_ScrollBarTP::DrawMaxMinBtn(CFX_Graphics* pGraphics, +void CFWL_ScrollBarTP::DrawMaxMinBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FWLTHEME_STATE eState, diff --git a/xfa/fwl/theme/cfwl_scrollbartp.h b/xfa/fwl/theme/cfwl_scrollbartp.h index 2389eff3c94dbf1fc5c2c53f0f0bd161ea0af683..eec372c6608630d0e36d8b1034ee9b353e60948e 100644 --- a/xfa/fwl/theme/cfwl_scrollbartp.h +++ b/xfa/fwl/theme/cfwl_scrollbartp.h @@ -29,24 +29,24 @@ class CFWL_ScrollBarTP : public CFWL_WidgetTP { FX_ARGB clrTrackBKEnd; }; - void DrawThumbBtn(CFX_Graphics* pGraphics, + void DrawThumbBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, bool bVert, FWLTHEME_STATE eState, bool bPawButton = true, CFX_Matrix* pMatrix = nullptr); - void DrawTrack(CFX_Graphics* pGraphics, + void DrawTrack(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, bool bVert, FWLTHEME_STATE eState, bool bLowerTrack, CFX_Matrix* pMatrix = nullptr); - void DrawMaxMinBtn(CFX_Graphics* pGraphics, + void DrawMaxMinBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FWLTHEME_STATE eState, CFX_Matrix* pMatrix = nullptr); - void DrawPaw(CFX_Graphics* pGraphics, + void DrawPaw(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, bool bVert, FWLTHEME_STATE eState, diff --git a/xfa/fwl/theme/cfwl_utils.h b/xfa/fwl/theme/cfwl_utils.h index 51bd07fbf90bf74ad27bb25930e7ff411eaef80b..8aa9a3c30551665a392ad7ae2af26b7a0e78b104 100644 --- a/xfa/fwl/theme/cfwl_utils.h +++ b/xfa/fwl/theme/cfwl_utils.h @@ -32,7 +32,6 @@ enum FWLTHEME_DIRECTION { #define FWLTHEME_COLOR_EDGERB1 (ArgbEncode(255, 241, 239, 226)) #define FWLTHEME_COLOR_Background (ArgbEncode(255, 236, 233, 216)) #define FWLTHEME_COLOR_BKSelected (ArgbEncode(255, 153, 193, 218)) -#define FWLTHEME_COLOR_Green_BKSelected (ArgbEncode(255, 147, 160, 112)) #define FWLTHEME_CAPACITY_FontSize 12.0f #define FWLTHEME_CAPACITY_TextColor (ArgbEncode(255, 0, 0, 0)) diff --git a/xfa/fwl/theme/cfwl_widgettp.cpp b/xfa/fwl/theme/cfwl_widgettp.cpp index fbcbcffb858844e33059a3f6d753417fafc88802..3113d245468f41156f2008473c9795cb2b30293b 100644 --- a/xfa/fwl/theme/cfwl_widgettp.cpp +++ b/xfa/fwl/theme/cfwl_widgettp.cpp @@ -10,7 +10,7 @@ #include <utility> #include "third_party/base/ptr_util.h" -#include "xfa/fde/tto/fde_textout.h" +#include "xfa/fde/cfde_textout.h" #include "xfa/fgas/font/cfgas_fontmgr.h" #include "xfa/fgas/font/cfgas_gefont.h" #include "xfa/fwl/cfwl_themebackground.h" @@ -19,9 +19,9 @@ #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" -#include "xfa/fxgraphics/cfx_shading.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" +#include "xfa/fxgraphics/cxfa_geshading.h" CFWL_WidgetTP::CFWL_WidgetTP() : m_dwRefCount(1), m_pFDEFont(nullptr), m_pColorData(nullptr) {} @@ -45,15 +45,20 @@ void CFWL_WidgetTP::DrawText(CFWL_ThemeText* pParams) { if (iLen <= 0) return; - CFX_Graphics* pGraphics = pParams->m_pGraphics; - m_pTextOut->SetRenderDevice(pGraphics->GetRenderDevice()); + CXFA_Graphics* pGraphics = pParams->m_pGraphics; m_pTextOut->SetStyles(pParams->m_dwTTOStyles); m_pTextOut->SetAlignment(pParams->m_iTTOAlign); CFX_Matrix* pMatrix = &pParams->m_matrix; pMatrix->Concat(*pGraphics->GetMatrix()); m_pTextOut->SetMatrix(*pMatrix); - m_pTextOut->DrawLogicText(pParams->m_wsText.c_str(), iLen, pParams->m_rtPart); + m_pTextOut->DrawLogicText(pGraphics->GetRenderDevice(), + WideStringView(pParams->m_wsText.c_str(), iLen), + pParams->m_rtPart); +} + +const RetainPtr<CFGAS_GEFont>& CFWL_WidgetTP::GetFont() const { + return m_pFDEFont; } void CFWL_WidgetTP::InitializeArrowColorData() { @@ -89,62 +94,57 @@ void CFWL_WidgetTP::InitTTO() { m_pTextOut->SetFont(m_pFDEFont); m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize); m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor); - m_pTextOut->SetEllipsisString(L"..."); } void CFWL_WidgetTP::FinalizeTTO() { m_pTextOut.reset(); } -void CFWL_WidgetTP::DrawBorder(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::DrawBorder(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { - if (!pGraphics) + if (!pGraphics || !pRect) return; - if (!pRect) - return; - CFX_Path path; + + CXFA_GEPath path; path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); path.AddRectangle(pRect->left + 1, pRect->top + 1, pRect->width - 2, pRect->height - 2); pGraphics->SaveGraphState(); - CFX_Color crFill(ArgbEncode(255, 0, 0, 0)); - pGraphics->SetFillColor(&crFill); + pGraphics->SetFillColor(CXFA_GEColor(ArgbEncode(255, 0, 0, 0))); pGraphics->FillPath(&path, FXFILL_ALTERNATE, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_WidgetTP::FillBackground(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::FillBackground(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { FillSoildRect(pGraphics, FWLTHEME_COLOR_Background, pRect, pMatrix); } -void CFWL_WidgetTP::FillSoildRect(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::FillSoildRect(CXFA_Graphics* pGraphics, FX_ARGB fillColor, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { - if (!pGraphics) + if (!pGraphics || !pRect) return; - if (!pRect) - return; - pGraphics->SaveGraphState(); - CFX_Color crFill(fillColor); - pGraphics->SetFillColor(&crFill); - CFX_Path path; + + CXFA_GEPath path; path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); + pGraphics->SaveGraphState(); + pGraphics->SetFillColor(CXFA_GEColor(fillColor)); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_WidgetTP::DrawAxialShading(CFX_Graphics* pGraphics, - FX_FLOAT fx1, - FX_FLOAT fy1, - FX_FLOAT fx2, - FX_FLOAT fy2, +void CFWL_WidgetTP::DrawAxialShading(CXFA_Graphics* pGraphics, + float fx1, + float fy1, + float fx2, + float fy2, FX_ARGB beginColor, FX_ARGB endColor, - CFX_Path* path, + CXFA_GEPath* path, int32_t fillMode, CFX_Matrix* pMatrix) { if (!pGraphics || !path) @@ -152,44 +152,42 @@ void CFWL_WidgetTP::DrawAxialShading(CFX_Graphics* pGraphics, CFX_PointF begPoint(fx1, fy1); CFX_PointF endPoint(fx2, fy2); - CFX_Shading shading(begPoint, endPoint, false, false, beginColor, endColor); + CXFA_GEShading shading(begPoint, endPoint, false, false, beginColor, + endColor); pGraphics->SaveGraphState(); - CFX_Color color1(&shading); - pGraphics->SetFillColor(&color1); + pGraphics->SetFillColor(CXFA_GEColor(&shading)); pGraphics->FillPath(path, fillMode, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_WidgetTP::DrawFocus(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::DrawFocus(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { - if (!pGraphics) - return; - if (!pRect) + if (!pGraphics || !pRect) return; + + float DashPattern[2] = {1, 1}; + CXFA_GEPath path; + path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); pGraphics->SaveGraphState(); - CFX_Color cr(0xFF000000); - pGraphics->SetStrokeColor(&cr); - FX_FLOAT DashPattern[2] = {1, 1}; + pGraphics->SetStrokeColor(CXFA_GEColor(0xFF000000)); pGraphics->SetLineDash(0.0f, DashPattern, 2); - CFX_Path path; - path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); pGraphics->StrokePath(&path, pMatrix); pGraphics->RestoreGraphState(); } -void CFWL_WidgetTP::DrawArrow(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::DrawArrow(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FX_ARGB argSign, CFX_Matrix* pMatrix) { bool bVert = (eDict == FWLTHEME_DIRECTION_Up || eDict == FWLTHEME_DIRECTION_Down); - FX_FLOAT fLeft = - (FX_FLOAT)(((pRect->width - (bVert ? 9 : 6)) / 2 + pRect->left) + 0.5); - FX_FLOAT fTop = - (FX_FLOAT)(((pRect->height - (bVert ? 6 : 9)) / 2 + pRect->top) + 0.5); - CFX_Path path; + float fLeft = + (float)(((pRect->width - (bVert ? 9 : 6)) / 2 + pRect->left) + 0.5); + float fTop = + (float)(((pRect->height - (bVert ? 6 : 9)) / 2 + pRect->top) + 0.5); + CXFA_GEPath path; switch (eDict) { case FWLTHEME_DIRECTION_Down: { path.MoveTo(CFX_PointF(fLeft, fTop + 1)); @@ -228,33 +226,30 @@ void CFWL_WidgetTP::DrawArrow(CFX_Graphics* pGraphics, break; } } - CFX_Color cr(argSign); - pGraphics->SetFillColor(&cr); + pGraphics->SetFillColor(CXFA_GEColor(argSign)); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } -void CFWL_WidgetTP::DrawBtn(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::DrawBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_STATE eState, CFX_Matrix* pMatrix) { - CFX_Path path; InitializeArrowColorData(); - FX_FLOAT fRight = pRect->right(); - FX_FLOAT fBottom = pRect->bottom(); + CXFA_GEPath path; + float fRight = pRect->right(); + float fBottom = pRect->bottom(); path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); DrawAxialShading(pGraphics, pRect->left, pRect->top, fRight, fBottom, m_pColorData->clrStart[eState - 1], m_pColorData->clrEnd[eState - 1], &path, FXFILL_WINDING, pMatrix); - CFX_Color rcStroke; - rcStroke.Set(m_pColorData->clrBorder[eState - 1]); - pGraphics->SetStrokeColor(&rcStroke); + pGraphics->SetStrokeColor(CXFA_GEColor(m_pColorData->clrBorder[eState - 1])); pGraphics->StrokePath(&path, pMatrix); } -void CFWL_WidgetTP::DrawArrowBtn(CFX_Graphics* pGraphics, +void CFWL_WidgetTP::DrawArrowBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FWLTHEME_STATE eState, @@ -270,32 +265,35 @@ CFWL_FontData::CFWL_FontData() : m_dwStyles(0), m_dwCodePage(0) {} CFWL_FontData::~CFWL_FontData() {} -bool CFWL_FontData::Equal(const CFX_WideStringC& wsFontFamily, +bool CFWL_FontData::Equal(const WideStringView& wsFontFamily, uint32_t dwFontStyles, uint16_t wCodePage) { return m_wsFamily == wsFontFamily && m_dwStyles == dwFontStyles && m_dwCodePage == wCodePage; } -bool CFWL_FontData::LoadFont(const CFX_WideStringC& wsFontFamily, +bool CFWL_FontData::LoadFont(const WideStringView& wsFontFamily, uint32_t dwFontStyles, uint16_t dwCodePage) { m_wsFamily = wsFontFamily; m_dwStyles = dwFontStyles; m_dwCodePage = dwCodePage; if (!m_pFontMgr) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - m_pFontMgr = CFGAS_FontMgr::Create(FX_GetDefFontEnumerator()); -#else - m_pFontSource = pdfium::MakeUnique<CFX_FontSourceEnum_File>(); - m_pFontMgr = CFGAS_FontMgr::Create(m_pFontSource.get()); -#endif + m_pFontMgr = pdfium::MakeUnique<CFGAS_FontMgr>(); + if (!m_pFontMgr->EnumFonts()) + m_pFontMgr = nullptr; } - m_pFont = CFGAS_GEFont::LoadFont(wsFontFamily.c_str(), dwFontStyles, - dwCodePage, m_pFontMgr.get()); + + // TODO(tsepez): check usage of c_str() below. + m_pFont = CFGAS_GEFont::LoadFont(wsFontFamily.unterminated_c_str(), + dwFontStyles, dwCodePage, m_pFontMgr.get()); return !!m_pFont; } +RetainPtr<CFGAS_GEFont> CFWL_FontData::GetFont() const { + return m_pFont; +} + CFWL_FontManager* CFWL_FontManager::s_FontManager = nullptr; CFWL_FontManager* CFWL_FontManager::GetInstance() { if (!s_FontManager) @@ -312,8 +310,8 @@ CFWL_FontManager::CFWL_FontManager() {} CFWL_FontManager::~CFWL_FontManager() {} -CFX_RetainPtr<CFGAS_GEFont> CFWL_FontManager::FindFont( - const CFX_WideStringC& wsFontFamily, +RetainPtr<CFGAS_GEFont> CFWL_FontManager::FindFont( + const WideStringView& wsFontFamily, uint32_t dwFontStyles, uint16_t wCodePage) { for (const auto& pData : m_FontsArray) { diff --git a/xfa/fwl/theme/cfwl_widgettp.h b/xfa/fwl/theme/cfwl_widgettp.h index c81950793a17beedd5bee20f69ced625c757df1f..7813c0825c8f9a161a46e0dce782e3624b730b4c 100644 --- a/xfa/fwl/theme/cfwl_widgettp.h +++ b/xfa/fwl/theme/cfwl_widgettp.h @@ -10,22 +10,21 @@ #include <memory> #include <vector> -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" -#include "xfa/fgas/font/cfgas_gefont.h" +#include "core/fxcrt/retain_ptr.h" #include "xfa/fwl/theme/cfwl_utils.h" -#include "xfa/fxgraphics/cfx_graphics.h" +#include "xfa/fxgraphics/cxfa_graphics.h" class CFDE_TextOut; +class CFGAS_FontMgr; class CFGAS_GEFont; class CFWL_ThemeBackground; class CFWL_ThemePart; class CFWL_ThemeText; -class CFGAS_FontMgr; class CFWL_Widget; -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ +#if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_ class CFX_FontSourceEnum_File; #endif @@ -39,7 +38,7 @@ class CFWL_WidgetTP { virtual void DrawBackground(CFWL_ThemeBackground* pParams); virtual void DrawText(CFWL_ThemeText* pParams); - const CFX_RetainPtr<CFGAS_GEFont>& GetFont() const { return m_pFDEFont; } + const RetainPtr<CFGAS_GEFont>& GetFont() const; protected: struct CColorData { @@ -55,39 +54,39 @@ class CFWL_WidgetTP { void InitTTO(); void FinalizeTTO(); - void DrawBorder(CFX_Graphics* pGraphics, + void DrawBorder(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix = nullptr); - void FillBackground(CFX_Graphics* pGraphics, + void FillBackground(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix = nullptr); - void FillSoildRect(CFX_Graphics* pGraphics, + void FillSoildRect(CXFA_Graphics* pGraphics, FX_ARGB fillColor, const CFX_RectF* pRect, CFX_Matrix* pMatrix = nullptr); - void DrawAxialShading(CFX_Graphics* pGraphics, - FX_FLOAT fx1, - FX_FLOAT fy1, - FX_FLOAT fx2, - FX_FLOAT fy2, + void DrawAxialShading(CXFA_Graphics* pGraphics, + float fx1, + float fy1, + float fx2, + float fy2, FX_ARGB beginColor, FX_ARGB endColor, - CFX_Path* path, + CXFA_GEPath* path, int32_t fillMode = FXFILL_WINDING, CFX_Matrix* pMatrix = nullptr); - void DrawFocus(CFX_Graphics* pGraphics, + void DrawFocus(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix = nullptr); - void DrawArrow(CFX_Graphics* pGraphics, + void DrawArrow(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FX_ARGB argSign, CFX_Matrix* pMatrix = nullptr); - void DrawBtn(CFX_Graphics* pGraphics, + void DrawBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_STATE eState, CFX_Matrix* pMatrix = nullptr); - void DrawArrowBtn(CFX_Graphics* pGraphics, + void DrawArrowBtn(CXFA_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FWLTHEME_STATE eState, @@ -95,7 +94,7 @@ class CFWL_WidgetTP { uint32_t m_dwRefCount; std::unique_ptr<CFDE_TextOut> m_pTextOut; - CFX_RetainPtr<CFGAS_GEFont> m_pFDEFont; + RetainPtr<CFGAS_GEFont> m_pFDEFont; std::unique_ptr<CColorData> m_pColorData; }; @@ -106,23 +105,20 @@ class CFWL_FontData { CFWL_FontData(); virtual ~CFWL_FontData(); - bool Equal(const CFX_WideStringC& wsFontFamily, + bool Equal(const WideStringView& wsFontFamily, uint32_t dwFontStyles, uint16_t wCodePage); - bool LoadFont(const CFX_WideStringC& wsFontFamily, + bool LoadFont(const WideStringView& wsFontFamily, uint32_t dwFontStyles, uint16_t wCodePage); - CFX_RetainPtr<CFGAS_GEFont> GetFont() const { return m_pFont; } + RetainPtr<CFGAS_GEFont> GetFont() const; protected: - CFX_WideString m_wsFamily; + WideString m_wsFamily; uint32_t m_dwStyles; uint32_t m_dwCodePage; -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - std::unique_ptr<CFX_FontSourceEnum_File> m_pFontSource; -#endif std::unique_ptr<CFGAS_FontMgr> m_pFontMgr; - CFX_RetainPtr<CFGAS_GEFont> m_pFont; + RetainPtr<CFGAS_GEFont> m_pFont; }; class CFWL_FontManager { @@ -130,9 +126,9 @@ class CFWL_FontManager { static CFWL_FontManager* GetInstance(); static void DestroyInstance(); - CFX_RetainPtr<CFGAS_GEFont> FindFont(const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t dwCodePage); + RetainPtr<CFGAS_GEFont> FindFont(const WideStringView& wsFontFamily, + uint32_t dwFontStyles, + uint16_t dwCodePage); protected: CFWL_FontManager(); diff --git a/xfa/fxbarcode/BC_Dimension.cpp b/xfa/fxbarcode/BC_Dimension.cpp deleted file mode 100644 index 0cb076ce22c9b0d103c4484aa2c0e908373ea654..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_Dimension.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" - -CBC_Dimension::CBC_Dimension() {} -CBC_Dimension::CBC_Dimension(int32_t width, int32_t height, int32_t& e) { - if (width < 0 || height < 0) { - e = BCExceptionHeightAndWidthMustBeAtLeast1; - } - m_width = width; - m_height = height; -} -CBC_Dimension::~CBC_Dimension() {} -int32_t CBC_Dimension::getWidth() { - return m_width; -} -int32_t CBC_Dimension::getHeight() { - return m_height; -} -int32_t CBC_Dimension::hashCode() { - return m_width * 32713 + m_height; -} -CFX_WideString CBC_Dimension::toString() { - return (FX_WCHAR)(m_width + (FX_WCHAR)'x' + m_height); -} diff --git a/xfa/fxbarcode/BC_Dimension.h b/xfa/fxbarcode/BC_Dimension.h deleted file mode 100644 index 2050b0faaf1153549363054eb9c08162edfcfc18..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_Dimension.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_BC_DIMENSION_H_ -#define XFA_FXBARCODE_BC_DIMENSION_H_ - -#include <cstdint> - -#include "core/fxcrt/fx_string.h" - -class CBC_Dimension { - public: - CBC_Dimension(); - CBC_Dimension(int32_t width, int32_t height, int32_t& e); - virtual ~CBC_Dimension(); - int32_t getWidth(); - int32_t getHeight(); - int32_t hashCode(); - CFX_WideString toString(); - - private: - int32_t m_width; - int32_t m_height; -}; - -#endif // XFA_FXBARCODE_BC_DIMENSION_H_ diff --git a/xfa/fxbarcode/BC_Library.cpp b/xfa/fxbarcode/BC_Library.cpp deleted file mode 100644 index 075bc2247d2247039f6b47e31a7e738ac7a0fc0a..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_Library.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxbarcode/BC_Library.h" - -#include <stdint.h> - -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" -#include "xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMode.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h" - -void BC_Library_Init() { - CBC_QRCoderErrorCorrectionLevel::Initialize(); - CBC_QRCoderMode::Initialize(); - CBC_QRCoderVersion::Initialize(); - CBC_ReedSolomonGF256::Initialize(); - CBC_SymbolInfo::Initialize(); - CBC_ErrorCorrection::Initialize(); - CBC_PDF417HighLevelEncoder::Initialize(); -} -void BC_Library_Destory() { - CBC_QRCoderErrorCorrectionLevel::Finalize(); - CBC_QRCoderMode::Finalize(); - CBC_QRCoderVersion::Finalize(); - CBC_ReedSolomonGF256::Finalize(); - CBC_SymbolInfo::Finalize(); - CBC_ErrorCorrection::Finalize(); - CBC_PDF417HighLevelEncoder::Finalize(); -} diff --git a/xfa/fxbarcode/BC_TwoDimWriter.cpp b/xfa/fxbarcode/BC_TwoDimWriter.cpp deleted file mode 100644 index b9aae361d64053e7f2bf47aa93d81c72a0468742..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_TwoDimWriter.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include <algorithm> - -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "third_party/base/numerics/safe_math.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fxbarcode/BC_TwoDimWriter.h" -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" - -CBC_TwoDimWriter::CBC_TwoDimWriter() : m_iCorrectLevel(1), m_bFixedSize(true) {} - -CBC_TwoDimWriter::~CBC_TwoDimWriter() {} - -void CBC_TwoDimWriter::RenderDeviceResult(CFX_RenderDevice* device, - const CFX_Matrix* matrix) { - CFX_GraphStateData stateData; - CFX_PathData path; - path.AppendRect(0, 0, (FX_FLOAT)m_Width, (FX_FLOAT)m_Height); - device->DrawPath(&path, matrix, &stateData, m_backgroundColor, - m_backgroundColor, FXFILL_ALTERNATE); - int32_t leftPos = 0; - int32_t topPos = 0; - if (m_bFixedSize) { - leftPos = (m_Width - m_output->GetWidth()) / 2; - topPos = (m_Height - m_output->GetHeight()) / 2; - } - CFX_Matrix matri = *matrix; - if (m_Width < m_output->GetWidth() && m_Height < m_output->GetHeight()) { - CFX_Matrix matriScale( - (FX_FLOAT)m_Width / (FX_FLOAT)m_output->GetWidth(), 0.0, 0.0, - (FX_FLOAT)m_Height / (FX_FLOAT)m_output->GetHeight(), 0.0, 0.0); - matriScale.Concat(*matrix); - matri = matriScale; - } - for (int32_t x = 0; x < m_output->GetWidth(); x++) { - for (int32_t y = 0; y < m_output->GetHeight(); y++) { - CFX_PathData rect; - rect.AppendRect((FX_FLOAT)leftPos + x, (FX_FLOAT)topPos + y, - (FX_FLOAT)(leftPos + x + 1), (FX_FLOAT)(topPos + y + 1)); - if (m_output->Get(x, y)) { - CFX_GraphStateData data; - device->DrawPath(&rect, &matri, &data, m_barColor, 0, FXFILL_WINDING); - } - } - } -} - -int32_t CBC_TwoDimWriter::GetErrorCorrectionLevel() const { - return m_iCorrectLevel; -} - -void CBC_TwoDimWriter::RenderBitmapResult(CFX_DIBitmap*& pOutBitmap, - int32_t& e) { - if (m_bFixedSize) { - pOutBitmap = CreateDIBitmap(m_Width, m_Height); - } else { - pOutBitmap = CreateDIBitmap(m_output->GetWidth(), m_output->GetHeight()); - } - if (!pOutBitmap) { - e = BCExceptionFailToCreateBitmap; - return; - } - pOutBitmap->Clear(m_backgroundColor); - int32_t leftPos = 0; - int32_t topPos = 0; - if (m_bFixedSize) { - leftPos = (m_Width - m_output->GetWidth()) / 2; - topPos = (m_Height - m_output->GetHeight()) / 2; - } - for (int32_t x = 0; x < m_output->GetWidth(); x++) { - for (int32_t y = 0; y < m_output->GetHeight(); y++) { - if (m_output->Get(x, y)) { - pOutBitmap->SetPixel(leftPos + x, topPos + y, m_barColor); - } - } - } - if (!m_bFixedSize) { - std::unique_ptr<CFX_DIBitmap> pStretchBitmap = - pOutBitmap->StretchTo(m_Width, m_Height); - delete pOutBitmap; - pOutBitmap = pStretchBitmap.release(); - } -} - -void CBC_TwoDimWriter::RenderResult(uint8_t* code, - int32_t codeWidth, - int32_t codeHeight, - int32_t& e) { - int32_t inputWidth = codeWidth; - int32_t inputHeight = codeHeight; - int32_t tempWidth = inputWidth + 2; - int32_t tempHeight = inputHeight + 2; - FX_FLOAT moduleHSize = std::min(m_ModuleWidth, m_ModuleHeight); - moduleHSize = std::min(moduleHSize, 8.0f); - moduleHSize = std::max(moduleHSize, 1.0f); - pdfium::base::CheckedNumeric<int32_t> scaledWidth = tempWidth; - pdfium::base::CheckedNumeric<int32_t> scaledHeight = tempHeight; - scaledWidth *= moduleHSize; - scaledHeight *= moduleHSize; - - int32_t outputWidth = scaledWidth.ValueOrDie(); - int32_t outputHeight = scaledHeight.ValueOrDie(); - if (m_bFixedSize) { - if (m_Width < outputWidth || m_Height < outputHeight) { - e = BCExceptionBitmapSizeError; - return; - } - } else { - if (m_Width > outputWidth || m_Height > outputHeight) { - outputWidth = (int32_t)(outputWidth * - ceil((FX_FLOAT)m_Width / (FX_FLOAT)outputWidth)); - outputHeight = (int32_t)( - outputHeight * ceil((FX_FLOAT)m_Height / (FX_FLOAT)outputHeight)); - } - } - int32_t multiX = (int32_t)ceil((FX_FLOAT)outputWidth / (FX_FLOAT)tempWidth); - int32_t multiY = (int32_t)ceil((FX_FLOAT)outputHeight / (FX_FLOAT)tempHeight); - if (m_bFixedSize) { - multiX = std::min(multiX, multiY); - multiY = multiX; - } - int32_t leftPadding = (outputWidth - (inputWidth * multiX)) / 2; - int32_t topPadding = (outputHeight - (inputHeight * multiY)) / 2; - if (leftPadding < 0) { - leftPadding = 0; - } - if (topPadding < 0) { - topPadding = 0; - } - m_output = pdfium::MakeUnique<CBC_CommonBitMatrix>(); - m_output->Init(outputWidth, outputHeight); - for (int32_t inputY = 0, outputY = topPadding; - (inputY < inputHeight) && (outputY < outputHeight - multiY); - inputY++, outputY += multiY) { - for (int32_t inputX = 0, outputX = leftPadding; - (inputX < inputWidth) && (outputX < outputWidth - multiX); - inputX++, outputX += multiX) { - if (code[inputX + inputY * inputWidth] == 1) { - m_output->SetRegion(outputX, outputY, multiX, multiY, e); - if (e != BCExceptionNO) - return; - } - } - } -} diff --git a/xfa/fxbarcode/BC_TwoDimWriter.h b/xfa/fxbarcode/BC_TwoDimWriter.h deleted file mode 100644 index ad4658b008c76359d3705c1d37e60cdb71863d58..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_TwoDimWriter.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_BC_TWODIMWRITER_H_ -#define XFA_FXBARCODE_BC_TWODIMWRITER_H_ - -#include <memory> - -#include "xfa/fxbarcode/BC_Writer.h" - -class CBC_CommonBitMatrix; -class CFX_RenderDevice; - -class CBC_TwoDimWriter : public CBC_Writer { - public: - CBC_TwoDimWriter(); - ~CBC_TwoDimWriter() override; - - virtual void RenderResult(uint8_t* code, - int32_t codeWidth, - int32_t codeHeight, - int32_t& e); - virtual void RenderBitmapResult(CFX_DIBitmap*& pOutBitmap, int32_t& e); - virtual void RenderDeviceResult(CFX_RenderDevice* device, - const CFX_Matrix* matrix); - virtual bool SetErrorCorrectionLevel(int32_t level) = 0; - - int32_t GetErrorCorrectionLevel() const; - - protected: - int32_t m_iCorrectLevel; - bool m_bFixedSize; - std::unique_ptr<CBC_CommonBitMatrix> m_output; -}; - -#endif // XFA_FXBARCODE_BC_TWODIMWRITER_H_ diff --git a/xfa/fxbarcode/BC_UtilCodingConvert.cpp b/xfa/fxbarcode/BC_UtilCodingConvert.cpp deleted file mode 100644 index c06cffc218a63e29b15f3037abaae6cabfff960d..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_UtilCodingConvert.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxbarcode/BC_UtilCodingConvert.h" - -CBC_UtilCodingConvert::CBC_UtilCodingConvert() {} - -CBC_UtilCodingConvert::~CBC_UtilCodingConvert() {} - -void CBC_UtilCodingConvert::UnicodeToLocale(const CFX_WideString& src, - CFX_ByteString& dst) { - dst = CFX_ByteString::FromUnicode(src); -} - -void CBC_UtilCodingConvert::LocaleToUtf8(const CFX_ByteString& src, - CFX_ByteString& dst) { - CFX_WideString unicode = CFX_WideString::FromLocal(src.AsStringC()); - dst = unicode.UTF8Encode(); -} - -void CBC_UtilCodingConvert::LocaleToUtf8(const CFX_ByteString& src, - CFX_ArrayTemplate<uint8_t>& dst) { - CFX_WideString unicode = CFX_WideString::FromLocal(src.AsStringC()); - CFX_ByteString utf8 = unicode.UTF8Encode(); - for (int32_t i = 0; i < utf8.GetLength(); i++) { - dst.Add(utf8[i]); - } -} - -void CBC_UtilCodingConvert::Utf8ToLocale(const CFX_ArrayTemplate<uint8_t>& src, - CFX_ByteString& dst) { - CFX_ByteString utf8; - for (int32_t i = 0; i < src.GetSize(); i++) { - utf8 += src[i]; - } - CFX_WideString unicode = CFX_WideString::FromUTF8(utf8.AsStringC()); - dst = CFX_ByteString::FromUnicode(unicode); -} - -void CBC_UtilCodingConvert::Utf8ToLocale(const uint8_t* src, - int32_t count, - CFX_ByteString& dst) { - CFX_WideString unicode = - CFX_WideString::FromUTF8(CFX_ByteStringC(src, count)); - dst = CFX_ByteString::FromUnicode(unicode); -} - -void CBC_UtilCodingConvert::UnicodeToUTF8(const CFX_WideString& src, - CFX_ByteString& dst) { - dst = src.UTF8Encode(); -} diff --git a/xfa/fxbarcode/BC_UtilCodingConvert.h b/xfa/fxbarcode/BC_UtilCodingConvert.h deleted file mode 100644 index 859eeea1e9c898c39ac0f6989a65384c27a852d6..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_UtilCodingConvert.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_BC_UTILCODINGCONVERT_H_ -#define XFA_FXBARCODE_BC_UTILCODINGCONVERT_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_UtilCodingConvert { - public: - CBC_UtilCodingConvert(); - virtual ~CBC_UtilCodingConvert(); - static void UnicodeToLocale(const CFX_WideString& source, - CFX_ByteString& result); - static void LocaleToUtf8(const CFX_ByteString& source, - CFX_ByteString& result); - static void LocaleToUtf8(const CFX_ByteString& source, - CFX_ArrayTemplate<uint8_t>& result); - static void Utf8ToLocale(const CFX_ArrayTemplate<uint8_t>& source, - CFX_ByteString& result); - static void Utf8ToLocale(const uint8_t* source, - int32_t count, - CFX_ByteString& result); - static void UnicodeToUTF8(const CFX_WideString& source, - CFX_ByteString& result); -}; - -#endif // XFA_FXBARCODE_BC_UTILCODINGCONVERT_H_ diff --git a/xfa/fxbarcode/BC_Utils.cpp b/xfa/fxbarcode/BC_Utils.cpp deleted file mode 100644 index 5d881c7be16c4072a3b9b7da7d3f7e49563d2c0b..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/BC_Utils.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/fx_basic.h" -#include "xfa/fxbarcode/utils.h" - -bool BC_FX_ByteString_Replace(CFX_ByteString& dst, - uint32_t first, - uint32_t last, - int32_t count, - FX_CHAR c) { - if (first > last || count <= 0) { - return false; - } - dst.Delete(first, last - first); - for (int32_t i = 0; i < count; i++) { - dst.Insert(0, c); - } - return true; -} -void BC_FX_ByteString_Append(CFX_ByteString& dst, int32_t count, FX_CHAR c) { - for (int32_t i = 0; i < count; i++) { - dst += c; - } -} -void BC_FX_ByteString_Append(CFX_ByteString& dst, - const CFX_ArrayTemplate<uint8_t>& ba) { - for (int32_t i = 0; i < ba.GetSize(); i++) { - dst += ba[i]; - } -} diff --git a/xfa/fxbarcode/DEPS b/xfa/fxbarcode/DEPS deleted file mode 100644 index 1519ceaa9366d9f84ad8e1b06c3f1d57f2fe8891..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - '+core/fxcodec', -] diff --git a/xfa/fxbarcode/cbc_codabar.cpp b/xfa/fxbarcode/cbc_codabar.cpp deleted file mode 100644 index 6f6ab4a96cc18cf5ff8f9f13403c624e0c1160db..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_codabar.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_codabar.h" - -#include "xfa/fxbarcode/oned/BC_OnedCodaBarWriter.h" - -CBC_Codabar::CBC_Codabar() : CBC_OneCode(new CBC_OnedCodaBarWriter) {} - -CBC_Codabar::~CBC_Codabar() {} - -bool CBC_Codabar::SetStartChar(FX_CHAR start) { - if (!m_pBCWriter) - return false; - return static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->SetStartChar(start); -} - -bool CBC_Codabar::SetEndChar(FX_CHAR end) { - if (m_pBCWriter) - return static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->SetEndChar(end); - return false; -} - -bool CBC_Codabar::SetTextLocation(BC_TEXT_LOC location) { - return static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->SetTextLocation(location); -} - -bool CBC_Codabar::SetWideNarrowRatio(int32_t ratio) { - if (m_pBCWriter) - return static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->SetWideNarrowRatio(ratio); - return false; -} - -bool CBC_Codabar::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - if (contents.IsEmpty()) { - e = BCExceptionNoContents; - return false; - } - BCFORMAT format = BCFORMAT_CODABAR; - int32_t outWidth = 0; - int32_t outHeight = 0; - CFX_WideString filtercontents = - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->FilterContents(contents); - CFX_ByteString byteString = filtercontents.UTF8Encode(); - m_renderContents = filtercontents; - uint8_t* data = static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->Encode(byteString, format, outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderResult(filtercontents.AsStringC(), data, outWidth, isDevice, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_Codabar::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - CFX_WideString renderCon = - static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->encodedContents(m_renderContents.AsStringC()); - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix, renderCon.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_Codabar::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - CFX_WideString renderCon = - static_cast<CBC_OnedCodaBarWriter*>(m_pBCWriter.get()) - ->encodedContents(m_renderContents.AsStringC()); - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, renderCon.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_Codabar::GetType() { - return BC_CODABAR; -} diff --git a/xfa/fxbarcode/cbc_codabar.h b/xfa/fxbarcode/cbc_codabar.h deleted file mode 100644 index 28631a9cb574cf099831d979a94fc07de6c5927f..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_codabar.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_CODABAR_H_ -#define XFA_FXBARCODE_CBC_CODABAR_H_ - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_onecode.h" - -class CBC_Codabar : public CBC_OneCode { - public: - CBC_Codabar(); - ~CBC_Codabar() override; - - // CBC_OneCode: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - bool SetStartChar(FX_CHAR start); - bool SetEndChar(FX_CHAR end); - bool SetTextLocation(BC_TEXT_LOC location); - bool SetWideNarrowRatio(int32_t ratio); - - private: - CFX_WideString m_renderContents; -}; - -#endif // XFA_FXBARCODE_CBC_CODABAR_H_ diff --git a/xfa/fxbarcode/cbc_code128.cpp b/xfa/fxbarcode/cbc_code128.cpp deleted file mode 100644 index 35bd136fd053f5b78c80bfec32a2cfc09deb591d..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_code128.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_code128.h" - -#include "xfa/fxbarcode/oned/BC_OnedCode128Writer.h" - -CBC_Code128::CBC_Code128(BC_TYPE type) - : CBC_OneCode(new CBC_OnedCode128Writer(type)) {} - -CBC_Code128::~CBC_Code128() {} - -bool CBC_Code128::SetTextLocation(BC_TEXT_LOC location) { - if (m_pBCWriter) - return static_cast<CBC_OnedCode128Writer*>(m_pBCWriter.get()) - ->SetTextLocation(location); - return false; -} - -bool CBC_Code128::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - if (contents.IsEmpty()) { - e = BCExceptionNoContents; - return false; - } - BCFORMAT format = BCFORMAT_CODE_128; - int32_t outWidth = 0; - int32_t outHeight = 0; - CFX_WideString content(contents); - if (contents.GetLength() % 2 && - static_cast<CBC_OnedCode128Writer*>(m_pBCWriter.get())->GetType() == - BC_CODE128_C) { - content += '0'; - } - CFX_WideString encodeContents = - static_cast<CBC_OnedCode128Writer*>(m_pBCWriter.get()) - ->FilterContents(content.AsStringC()); - m_renderContents = encodeContents; - CFX_ByteString byteString = encodeContents.UTF8Encode(); - uint8_t* data = static_cast<CBC_OnedCode128Writer*>(m_pBCWriter.get()) - ->Encode(byteString, format, outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderResult(encodeContents.AsStringC(), data, outWidth, isDevice, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_Code128::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_Code128::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_Code128::GetType() { - return BC_CODE128; -} - diff --git a/xfa/fxbarcode/cbc_code128.h b/xfa/fxbarcode/cbc_code128.h deleted file mode 100644 index 0dd9c84f68552b6c6a3dc00a6bf2a472d5589c25..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_code128.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_CODE128_H_ -#define XFA_FXBARCODE_CBC_CODE128_H_ - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_onecode.h" - -class CBC_Code128 : public CBC_OneCode { - public: - explicit CBC_Code128(BC_TYPE type); - ~CBC_Code128() override; - - // CBC_OneCode: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - bool SetTextLocation(BC_TEXT_LOC loction); - - private: - CFX_WideString m_renderContents; -}; - -#endif // XFA_FXBARCODE_CBC_CODE128_H_ diff --git a/xfa/fxbarcode/cbc_code39.cpp b/xfa/fxbarcode/cbc_code39.cpp deleted file mode 100644 index af45ad406332b7ac546c49afd7b76545329f56bf..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_code39.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_code39.h" - -#include "xfa/fxbarcode/oned/BC_OnedCode39Writer.h" - -CBC_Code39::CBC_Code39() : CBC_OneCode(new CBC_OnedCode39Writer) {} - -CBC_Code39::~CBC_Code39() {} - -bool CBC_Code39::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - if (contents.IsEmpty()) { - e = BCExceptionNoContents; - return false; - } - BCFORMAT format = BCFORMAT_CODE_39; - int32_t outWidth = 0; - int32_t outHeight = 0; - CFX_WideString filtercontents = - static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->FilterContents(contents); - CFX_WideString renderContents = - static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->RenderTextContents(contents); - m_renderContents = renderContents; - CFX_ByteString byteString = filtercontents.UTF8Encode(); - uint8_t* data = static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->Encode(byteString, format, outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderResult(renderContents.AsStringC(), data, outWidth, isDevice, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_Code39::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - CFX_WideString renderCon = - static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->encodedContents(m_renderContents.AsStringC(), e); - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix, renderCon.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_Code39::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - CFX_WideString renderCon = - static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->encodedContents(m_renderContents.AsStringC(), e); - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, renderCon.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_Code39::GetType() { - return BC_CODE39; -} - -bool CBC_Code39::SetTextLocation(BC_TEXT_LOC location) { - if (m_pBCWriter) - return static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->SetTextLocation(location); - return false; -} - -bool CBC_Code39::SetWideNarrowRatio(int32_t ratio) { - if (m_pBCWriter) - return static_cast<CBC_OnedCode39Writer*>(m_pBCWriter.get()) - ->SetWideNarrowRatio(ratio); - return false; -} diff --git a/xfa/fxbarcode/cbc_code39.h b/xfa/fxbarcode/cbc_code39.h deleted file mode 100644 index 7f5c627c6ca94f98bb0b708af0860f5c6157e194..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_code39.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_CODE39_H_ -#define XFA_FXBARCODE_CBC_CODE39_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_onecode.h" - -class CBC_Code39 : public CBC_OneCode { - public: - CBC_Code39(); - ~CBC_Code39() override; - - // CBC_OneCode: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - bool SetTextLocation(BC_TEXT_LOC location); - bool SetWideNarrowRatio(int32_t ratio); - - private: - CFX_WideString m_renderContents; -}; - -#endif // XFA_FXBARCODE_CBC_CODE39_H_ diff --git a/xfa/fxbarcode/cbc_codebase.cpp b/xfa/fxbarcode/cbc_codebase.cpp deleted file mode 100644 index 5b4cb713bb8d857f6a595bcb65ab7d8209d30ae1..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_codebase.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_codebase.h" - -#include "xfa/fxbarcode/BC_Writer.h" - -CBC_CodeBase::CBC_CodeBase(CBC_Writer* pWriter) : m_pBCWriter(pWriter) {} - -CBC_CodeBase::~CBC_CodeBase() {} - -bool CBC_CodeBase::SetCharEncoding(int32_t encoding) { - return m_pBCWriter && m_pBCWriter->SetCharEncoding(encoding); -} - -bool CBC_CodeBase::SetModuleHeight(int32_t moduleHeight) { - return m_pBCWriter && m_pBCWriter->SetModuleHeight(moduleHeight); -} - -bool CBC_CodeBase::SetModuleWidth(int32_t moduleWidth) { - return m_pBCWriter && m_pBCWriter->SetModuleWidth(moduleWidth); -} - -bool CBC_CodeBase::SetHeight(int32_t height) { - return m_pBCWriter && m_pBCWriter->SetHeight(height); -} - -bool CBC_CodeBase::SetWidth(int32_t width) { - return m_pBCWriter && m_pBCWriter->SetWidth(width); -} - -void CBC_CodeBase::SetBackgroundColor(FX_ARGB backgroundColor) { - if (m_pBCWriter) - m_pBCWriter->SetBackgroundColor(backgroundColor); -} - -void CBC_CodeBase::SetBarcodeColor(FX_ARGB foregroundColor) { - if (m_pBCWriter) - m_pBCWriter->SetBarcodeColor(foregroundColor); -} diff --git a/xfa/fxbarcode/cbc_codebase.h b/xfa/fxbarcode/cbc_codebase.h deleted file mode 100644 index c28c08b7e75c936ee0371fe5d50c88b2c83701ad..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_codebase.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_CODEBASE_H_ -#define XFA_FXBARCODE_CBC_CODEBASE_H_ - -#include <memory> - -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/BC_Library.h" - -class CBC_Writer; -class CBC_Reader; -class CFX_DIBitmap; -class CFX_RenderDevice; - -class CBC_CodeBase { - public: - explicit CBC_CodeBase(CBC_Writer* pWriter); - virtual ~CBC_CodeBase(); - - virtual BC_TYPE GetType() = 0; - virtual bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) = 0; - virtual bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) = 0; - virtual bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) = 0; - - bool SetCharEncoding(int32_t encoding); - bool SetModuleHeight(int32_t moduleHeight); - bool SetModuleWidth(int32_t moduleWidth); - bool SetHeight(int32_t height); - bool SetWidth(int32_t width); - void SetBackgroundColor(FX_ARGB backgroundColor); - void SetBarcodeColor(FX_ARGB foregroundColor); - - protected: - std::unique_ptr<CBC_Writer> m_pBCWriter; -}; - -#endif // XFA_FXBARCODE_CBC_CODEBASE_H_ diff --git a/xfa/fxbarcode/cbc_datamatrix.cpp b/xfa/fxbarcode/cbc_datamatrix.cpp deleted file mode 100644 index 6122368e84213ef9129449a3ef66b5bdfa1d3032..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_datamatrix.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_datamatrix.h" - -#include "xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.h" - -CBC_DataMatrix::CBC_DataMatrix() : CBC_CodeBase(new CBC_DataMatrixWriter) {} - -CBC_DataMatrix::~CBC_DataMatrix() {} - -bool CBC_DataMatrix::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - int32_t outWidth = 0; - int32_t outHeight = 0; - uint8_t* data = - static_cast<CBC_DataMatrixWriter*>(m_pBCWriter.get()) - ->Encode(CFX_WideString(contents), outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderResult(data, outWidth, outHeight, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_DataMatrix::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix); - return true; -} - -bool CBC_DataMatrix::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_DataMatrix::GetType() { - return BC_DATAMATRIX; -} diff --git a/xfa/fxbarcode/cbc_datamatrix.h b/xfa/fxbarcode/cbc_datamatrix.h deleted file mode 100644 index 661b48d744f07e82c1ef432470734b1e8ca869ce..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_datamatrix.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_DATAMATRIX_H_ -#define XFA_FXBARCODE_CBC_DATAMATRIX_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_codebase.h" - -class CBC_DataMatrix : public CBC_CodeBase { - public: - CBC_DataMatrix(); - ~CBC_DataMatrix() override; - - // CBC_OneCode: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; -}; - -#endif // XFA_FXBARCODE_CBC_DATAMATRIX_H_ diff --git a/xfa/fxbarcode/cbc_ean13.cpp b/xfa/fxbarcode/cbc_ean13.cpp deleted file mode 100644 index 450fba04c9b1710c6a2fc73896d5eb12e4bbef52..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_ean13.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_ean13.h" - -#include "xfa/fxbarcode/oned/BC_OnedEAN13Writer.h" - -CBC_EAN13::CBC_EAN13() : CBC_OneCode(new CBC_OnedEAN13Writer) {} - -CBC_EAN13::~CBC_EAN13() {} - -CFX_WideString CBC_EAN13::Preprocess(const CFX_WideStringC& contents) { - CFX_WideString encodeContents = - static_cast<CBC_OnedEAN13Writer*>(m_pBCWriter.get()) - ->FilterContents(contents); - int32_t length = encodeContents.GetLength(); - if (length <= 12) { - for (int32_t i = 0; i < 12 - length; i++) - encodeContents = FX_WCHAR('0') + encodeContents; - - CFX_ByteString byteString = encodeContents.UTF8Encode(); - int32_t checksum = static_cast<CBC_OnedEAN13Writer*>(m_pBCWriter.get()) - ->CalcChecksum(byteString); - byteString += checksum - 0 + '0'; - encodeContents = byteString.UTF8Decode(); - } - if (length > 13) - encodeContents = encodeContents.Mid(0, 13); - - return encodeContents; -} - -bool CBC_EAN13::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - if (contents.IsEmpty()) { - e = BCExceptionNoContents; - return false; - } - BCFORMAT format = BCFORMAT_EAN_13; - int32_t outWidth = 0; - int32_t outHeight = 0; - CFX_WideString encodeContents = Preprocess(contents); - CFX_ByteString byteString = encodeContents.UTF8Encode(); - m_renderContents = encodeContents; - uint8_t* data = static_cast<CBC_OnedEAN13Writer*>(m_pBCWriter.get()) - ->Encode(byteString, format, outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderResult(encodeContents.AsStringC(), data, outWidth, isDevice, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_EAN13::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_EAN13::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_EAN13::GetType() { - return BC_EAN13; -} diff --git a/xfa/fxbarcode/cbc_ean13.h b/xfa/fxbarcode/cbc_ean13.h deleted file mode 100644 index f0e7940a042e8bd5daa93fa20cccd224505106e3..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_ean13.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_EAN13_H_ -#define XFA_FXBARCODE_CBC_EAN13_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_onecode.h" - -class CBC_EAN13 : public CBC_OneCode { - public: - CBC_EAN13(); - ~CBC_EAN13() override; - - // CBC_OneCode: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - private: - CFX_WideString Preprocess(const CFX_WideStringC& contents); - CFX_WideString m_renderContents; -}; - -#endif // XFA_FXBARCODE_CBC_EAN13_H_ diff --git a/xfa/fxbarcode/cbc_ean8.cpp b/xfa/fxbarcode/cbc_ean8.cpp deleted file mode 100644 index 64ba617331fdbefbe45b81aef663b280d6c5e6e3..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_ean8.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_ean8.h" - -#include "xfa/fxbarcode/oned/BC_OnedEAN8Writer.h" - -CBC_EAN8::CBC_EAN8() : CBC_OneCode(new CBC_OnedEAN8Writer) {} - -CBC_EAN8::~CBC_EAN8() {} - -CFX_WideString CBC_EAN8::Preprocess(const CFX_WideStringC& contents) { - CFX_WideString encodeContents = - static_cast<CBC_OnedEAN8Writer*>(m_pBCWriter.get()) - ->FilterContents(contents); - int32_t length = encodeContents.GetLength(); - if (length <= 7) { - for (int32_t i = 0; i < 7 - length; i++) - encodeContents = FX_WCHAR('0') + encodeContents; - - CFX_ByteString byteString = encodeContents.UTF8Encode(); - int32_t checksum = static_cast<CBC_OnedEAN8Writer*>(m_pBCWriter.get()) - ->CalcChecksum(byteString); - encodeContents += FX_WCHAR(checksum - 0 + '0'); - } - if (length > 8) - encodeContents = encodeContents.Mid(0, 8); - - return encodeContents; -} - -bool CBC_EAN8::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - if (contents.IsEmpty()) { - e = BCExceptionNoContents; - return false; - } - BCFORMAT format = BCFORMAT_EAN_8; - int32_t outWidth = 0; - int32_t outHeight = 0; - CFX_WideString encodeContents = Preprocess(contents); - CFX_ByteString byteString = encodeContents.UTF8Encode(); - m_renderContents = encodeContents; - uint8_t* data = static_cast<CBC_OnedEAN8Writer*>(m_pBCWriter.get()) - ->Encode(byteString, format, outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderResult(encodeContents.AsStringC(), data, outWidth, isDevice, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_EAN8::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_EAN8::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_EAN8::GetType() { - return BC_EAN8; -} diff --git a/xfa/fxbarcode/cbc_ean8.h b/xfa/fxbarcode/cbc_ean8.h deleted file mode 100644 index 6a475cb795cde745a375c95c813b0c6899100fae..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_ean8.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_EAN8_H_ -#define XFA_FXBARCODE_CBC_EAN8_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_onecode.h" - -class CBC_EAN8 : public CBC_OneCode { - public: - CBC_EAN8(); - ~CBC_EAN8() override; - - // CBC_OneCode: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - private: - CFX_WideString Preprocess(const CFX_WideStringC& contents); - CFX_WideString m_renderContents; -}; - -#endif // XFA_FXBARCODE_CBC_EAN8_H_ diff --git a/xfa/fxbarcode/cbc_onecode.cpp b/xfa/fxbarcode/cbc_onecode.cpp deleted file mode 100644 index 55c2837bd494f31c86c7dd2138faa9b7aa1e079d..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_onecode.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_onecode.h" - -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -CBC_OneCode::CBC_OneCode(CBC_Writer* pWriter) : CBC_CodeBase(pWriter) {} - -CBC_OneCode::~CBC_OneCode() {} - -bool CBC_OneCode::CheckContentValidity(const CFX_WideStringC& contents) { - return m_pBCWriter && - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->CheckContentValidity(contents); -} - -CFX_WideString CBC_OneCode::FilterContents(const CFX_WideStringC& contents) { - if (!m_pBCWriter) - return CFX_WideString(); - return static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->FilterContents(contents); -} - -void CBC_OneCode::SetPrintChecksum(bool checksum) { - if (m_pBCWriter) - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->SetPrintChecksum(checksum); -} - -void CBC_OneCode::SetDataLength(int32_t length) { - if (m_pBCWriter) - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get())->SetDataLength(length); -} - -void CBC_OneCode::SetCalChecksum(bool calc) { - if (m_pBCWriter) - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get())->SetCalcChecksum(calc); -} - -bool CBC_OneCode::SetFont(CFX_Font* cFont) { - if (m_pBCWriter) - return static_cast<CBC_OneDimWriter*>(m_pBCWriter.get())->SetFont(cFont); - return false; -} - -void CBC_OneCode::SetFontSize(FX_FLOAT size) { - if (m_pBCWriter) - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get())->SetFontSize(size); -} - -void CBC_OneCode::SetFontStyle(int32_t style) { - if (m_pBCWriter) - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get())->SetFontStyle(style); -} - -void CBC_OneCode::SetFontColor(FX_ARGB color) { - if (m_pBCWriter) - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get())->SetFontColor(color); -} diff --git a/xfa/fxbarcode/cbc_onecode.h b/xfa/fxbarcode/cbc_onecode.h deleted file mode 100644 index e348b4ee2c476620d46d1c34e4bbbf170922b3db..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_onecode.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_ONECODE_H_ -#define XFA_FXBARCODE_CBC_ONECODE_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/cbc_codebase.h" - -class CFX_DIBitmap; -class CFX_Font; -class CFX_RenderDevice; - -class CBC_OneCode : public CBC_CodeBase { - public: - explicit CBC_OneCode(CBC_Writer* pWriter); - ~CBC_OneCode() override; - - virtual bool CheckContentValidity(const CFX_WideStringC& contents); - virtual CFX_WideString FilterContents(const CFX_WideStringC& contents); - - virtual void SetPrintChecksum(bool checksum); - virtual void SetDataLength(int32_t length); - virtual void SetCalChecksum(bool calc); - virtual bool SetFont(CFX_Font* cFont); - virtual void SetFontSize(FX_FLOAT size); - virtual void SetFontStyle(int32_t style); - virtual void SetFontColor(FX_ARGB color); -}; - -#endif // XFA_FXBARCODE_CBC_ONECODE_H_ diff --git a/xfa/fxbarcode/cbc_pdf417i.cpp b/xfa/fxbarcode/cbc_pdf417i.cpp deleted file mode 100644 index 1c5547d445eb6281321792ccb2536870d68ba336..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_pdf417i.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_pdf417i.h" - -#include "xfa/fxbarcode/pdf417/BC_PDF417Writer.h" - -CBC_PDF417I::CBC_PDF417I() : CBC_CodeBase(new CBC_PDF417Writer) {} - -CBC_PDF417I::~CBC_PDF417I() {} - -bool CBC_PDF417I::SetErrorCorrectionLevel(int32_t level) { - static_cast<CBC_PDF417Writer*>(m_pBCWriter.get()) - ->SetErrorCorrectionLevel(level); - return true; -} - -void CBC_PDF417I::SetTruncated(bool truncated) { - static_cast<CBC_PDF417Writer*>(m_pBCWriter.get())->SetTruncated(truncated); -} - -bool CBC_PDF417I::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - int32_t outWidth = 0; - int32_t outHeight = 0; - uint8_t* data = - static_cast<CBC_PDF417Writer*>(m_pBCWriter.get()) - ->Encode(CFX_WideString(contents), outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderResult(data, outWidth, outHeight, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_PDF417I::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix); - return true; -} - -bool CBC_PDF417I::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_PDF417I::GetType() { - return BC_PDF417; -} diff --git a/xfa/fxbarcode/cbc_pdf417i.h b/xfa/fxbarcode/cbc_pdf417i.h deleted file mode 100644 index 70ea929820954e7e2e01165e4ee6ac2cbf9428e3..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_pdf417i.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_PDF417I_H_ -#define XFA_FXBARCODE_CBC_PDF417I_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_codebase.h" - -class CBC_PDF417I : public CBC_CodeBase { - public: - CBC_PDF417I(); - ~CBC_PDF417I() override; - - // CBC_CodeBase:: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - bool SetErrorCorrectionLevel(int32_t level); - void SetTruncated(bool truncated); -}; - -#endif // XFA_FXBARCODE_CBC_PDF417I_H_ diff --git a/xfa/fxbarcode/cbc_qrcode.cpp b/xfa/fxbarcode/cbc_qrcode.cpp deleted file mode 100644 index 26b74ca400885714c306cab8c0cba73df051c2fa..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_qrcode.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_qrcode.h" - -#include "xfa/fxbarcode/qrcode/BC_QRCodeWriter.h" - -CBC_QRCode::CBC_QRCode() : CBC_CodeBase(new CBC_QRCodeWriter) {} - -CBC_QRCode::~CBC_QRCode() {} - -bool CBC_QRCode::SetVersion(int32_t version) { - if (version < 0 || version > 40) - return false; - return m_pBCWriter && - static_cast<CBC_QRCodeWriter*>(m_pBCWriter.get())->SetVersion(version); -} - -bool CBC_QRCode::SetErrorCorrectionLevel(int32_t level) { - if (level < 0 || level > 3) - return false; - - return m_pBCWriter && - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->SetErrorCorrectionLevel(level); -} - -bool CBC_QRCode::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - int32_t outWidth = 0; - int32_t outHeight = 0; - CBC_QRCodeWriter* pWriter = static_cast<CBC_QRCodeWriter*>(m_pBCWriter.get()); - uint8_t* data = pWriter->Encode(CFX_WideString(contents), - pWriter->GetErrorCorrectionLevel(), outWidth, - outHeight, e); - if (e != BCExceptionNO) - return false; - pWriter->RenderResult(data, outWidth, outHeight, e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_QRCode::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix); - return true; -} - -bool CBC_QRCode::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_TwoDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_QRCode::GetType() { - return BC_QR_CODE; -} diff --git a/xfa/fxbarcode/cbc_qrcode.h b/xfa/fxbarcode/cbc_qrcode.h deleted file mode 100644 index ac2d93d9151dc98780f01497166b6a604cebb4e7..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_qrcode.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_QRCODE_H_ -#define XFA_FXBARCODE_CBC_QRCODE_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_codebase.h" - -class CBC_QRCode : public CBC_CodeBase { - public: - CBC_QRCode(); - ~CBC_QRCode() override; - - // CBC_CodeBase: - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - bool SetVersion(int32_t version); - bool SetErrorCorrectionLevel(int32_t level); -}; - -#endif // XFA_FXBARCODE_CBC_QRCODE_H_ diff --git a/xfa/fxbarcode/cbc_upca.cpp b/xfa/fxbarcode/cbc_upca.cpp deleted file mode 100644 index b282d5cd7919015f443836e8d30cef39b1e5d955..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_upca.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2016 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 -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/cbc_upca.h" - -#include "xfa/fxbarcode/oned/BC_OnedUPCAWriter.h" - -CBC_UPCA::CBC_UPCA() : CBC_OneCode(new CBC_OnedUPCAWriter) {} - -CBC_UPCA::~CBC_UPCA() {} - -CFX_WideString CBC_UPCA::Preprocess(const CFX_WideStringC& contents) { - CBC_OnedUPCAWriter* pWriter = - static_cast<CBC_OnedUPCAWriter*>(m_pBCWriter.get()); - CFX_WideString encodeContents = pWriter->FilterContents(contents); - int32_t length = encodeContents.GetLength(); - if (length <= 11) { - for (int32_t i = 0; i < 11 - length; i++) - encodeContents = FX_WCHAR('0') + encodeContents; - - CFX_ByteString byteString = encodeContents.UTF8Encode(); - int32_t checksum = pWriter->CalcChecksum(byteString); - byteString += checksum - 0 + '0'; - encodeContents = byteString.UTF8Decode(); - } - if (length > 12) - encodeContents = encodeContents.Mid(0, 12); - - return encodeContents; -} - -bool CBC_UPCA::Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) { - if (contents.IsEmpty()) { - e = BCExceptionNoContents; - return false; - } - BCFORMAT format = BCFORMAT_UPC_A; - int32_t outWidth = 0; - int32_t outHeight = 0; - CFX_WideString encodeContents = Preprocess(contents); - CFX_ByteString byteString = encodeContents.UTF8Encode(); - m_renderContents = encodeContents; - - CBC_OnedUPCAWriter* pWriter = - static_cast<CBC_OnedUPCAWriter*>(m_pBCWriter.get()); - - pWriter->Init(); - uint8_t* data = pWriter->Encode(byteString, format, outWidth, outHeight, e); - if (e != BCExceptionNO) - return false; - pWriter->RenderResult(encodeContents.AsStringC(), data, outWidth, isDevice, - e); - FX_Free(data); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_UPCA::RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderDeviceResult(device, matrix, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -bool CBC_UPCA::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { - static_cast<CBC_OneDimWriter*>(m_pBCWriter.get()) - ->RenderBitmapResult(pOutBitmap, m_renderContents.AsStringC(), e); - if (e != BCExceptionNO) - return false; - return true; -} - -BC_TYPE CBC_UPCA::GetType() { - return BC_UPCA; -} diff --git a/xfa/fxbarcode/cbc_upca.h b/xfa/fxbarcode/cbc_upca.h deleted file mode 100644 index bf90b922b5053e8e39d6792001ac4141cedc6b44..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/cbc_upca.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_CBC_UPCA_H_ -#define XFA_FXBARCODE_CBC_UPCA_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxbarcode/cbc_onecode.h" - -class CBC_UPCA : public CBC_OneCode { - public: - CBC_UPCA(); - ~CBC_UPCA() override; - - // CBC_CodeBase - bool Encode(const CFX_WideStringC& contents, - bool isDevice, - int32_t& e) override; - bool RenderDevice(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t& e) override; - bool RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) override; - BC_TYPE GetType() override; - - private: - CFX_WideString Preprocess(const CFX_WideStringC& contents); - CFX_WideString m_renderContents; -}; - -#endif // XFA_FXBARCODE_CBC_UPCA_H_ diff --git a/xfa/fxbarcode/common/BC_CommonBitArray.cpp b/xfa/fxbarcode/common/BC_CommonBitArray.cpp deleted file mode 100644 index 0371837fdec5594aae91d685bc8d0b7426b835dd..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/BC_CommonBitArray.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/common/BC_CommonBitArray.h" -#include "xfa/fxbarcode/utils.h" - -CBC_CommonBitArray::CBC_CommonBitArray(CBC_CommonBitArray* array) { - m_size = array->GetSize(); - m_bits.Copy(array->GetBits()); -} -CBC_CommonBitArray::CBC_CommonBitArray() { - m_bits.SetSize(1); - m_size = 0; -} -CBC_CommonBitArray::CBC_CommonBitArray(int32_t size) { - m_bits.SetSize((size + 31) >> 5); - m_size = size; -} -CBC_CommonBitArray::~CBC_CommonBitArray() { - m_size = 0; -} -int32_t CBC_CommonBitArray::GetSize() { - return m_size; -} -CFX_ArrayTemplate<int32_t>& CBC_CommonBitArray::GetBits() { - return m_bits; -} -int32_t CBC_CommonBitArray::GetSizeInBytes() { - return (m_size + 7) >> 3; -} -bool CBC_CommonBitArray::Get(int32_t i) { - return (m_bits[i >> 5] & (1 << (i & 0x1f))) != 0; -} -void CBC_CommonBitArray::Set(int32_t i) { - m_bits[i >> 5] |= 1 << (i & 0x1F); -} -void CBC_CommonBitArray::Flip(int32_t i) { - m_bits[i >> 5] ^= 1 << (i & 0x1F); -} -void CBC_CommonBitArray::SetBulk(int32_t i, int32_t newBits) { - m_bits[i >> 5] = newBits; -} -void CBC_CommonBitArray::Clear() { - FXSYS_memset(&m_bits[0], 0x00, m_bits.GetSize() * sizeof(int32_t)); -} -bool CBC_CommonBitArray::IsRange(int32_t start, - int32_t end, - bool value, - int32_t& e) { - if (end < start) { - e = BCExceptionEndLessThanStart; - return false; - } - if (end == start) { - return true; - } - end--; - int32_t firstInt = start >> 5; - int32_t lastInt = end >> 5; - int32_t i; - for (i = firstInt; i <= lastInt; i++) { - int32_t firstBit = i > firstInt ? 0 : start & 0x1F; - int32_t lastBit = i < lastInt ? 31 : end & 0x1F; - int32_t mask; - if (firstBit == 0 && lastBit == 31) { - mask = -1; - } else { - mask = 0; - for (int32_t j = firstBit; j <= lastBit; j++) { - mask |= 1 << j; - } - } - if ((m_bits[i] & mask) != (value ? mask : 0)) { - return false; - } - } - return true; -} -int32_t* CBC_CommonBitArray::GetBitArray() { - return &m_bits[0]; -} -void CBC_CommonBitArray::Reverse() { - int32_t* newBits = FX_Alloc(int32_t, m_bits.GetSize()); - FXSYS_memset(newBits, 0x00, m_bits.GetSize() * sizeof(int32_t)); - int32_t size = m_size; - int32_t i; - for (i = 0; i < size; i++) { - if (Get(size - i - 1)) { - newBits[i >> 5] |= 1 << (i & 0x1F); - } - } - FXSYS_memcpy(&m_bits[0], newBits, m_bits.GetSize() * sizeof(int32_t)); - FX_Free(newBits); -} diff --git a/xfa/fxbarcode/common/BC_CommonBitArray.h b/xfa/fxbarcode/common/BC_CommonBitArray.h deleted file mode 100644 index 6ad8ab321d8b421ea85cbf52a2f86c4355ad3bba..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/BC_CommonBitArray.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_COMMON_BC_COMMONBITARRAY_H_ -#define XFA_FXBARCODE_COMMON_BC_COMMONBITARRAY_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_CommonBitArray { - public: - explicit CBC_CommonBitArray(CBC_CommonBitArray* array); - explicit CBC_CommonBitArray(int32_t size); - CBC_CommonBitArray(); - virtual ~CBC_CommonBitArray(); - - int32_t GetSize(); - CFX_ArrayTemplate<int32_t>& GetBits(); - int32_t GetSizeInBytes(); - bool Get(int32_t i); - void Set(int32_t i); - void Flip(int32_t i); - void SetBulk(int32_t i, int32_t newBits); - bool IsRange(int32_t start, int32_t end, bool value, int32_t& e); - int32_t* GetBitArray(); - void Reverse(); - void Clear(); - - private: - int32_t m_size; - CFX_ArrayTemplate<int32_t> m_bits; -}; - -#endif // XFA_FXBARCODE_COMMON_BC_COMMONBITARRAY_H_ diff --git a/xfa/fxbarcode/common/BC_CommonBitMatrix.cpp b/xfa/fxbarcode/common/BC_CommonBitMatrix.cpp deleted file mode 100644 index b9b218c60f300a11b931a8c6f7c05404fd17791b..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/BC_CommonBitMatrix.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/common/BC_CommonBitArray.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/utils.h" - -CBC_CommonBitMatrix::CBC_CommonBitMatrix() { - m_width = 0; - m_height = 0; - m_rowSize = 0; - m_bits = nullptr; -} -void CBC_CommonBitMatrix::Init(int32_t dimension) { - m_width = dimension; - m_height = dimension; - int32_t rowSize = (m_height + 31) >> 5; - m_rowSize = rowSize; - m_bits = FX_Alloc2D(int32_t, m_rowSize, m_height); - FXSYS_memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t)); -} -void CBC_CommonBitMatrix::Init(int32_t width, int32_t height) { - m_width = width; - m_height = height; - int32_t rowSize = (width + 31) >> 5; - m_rowSize = rowSize; - m_bits = FX_Alloc2D(int32_t, m_rowSize, m_height); - FXSYS_memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t)); -} -CBC_CommonBitMatrix::~CBC_CommonBitMatrix() { - FX_Free(m_bits); -} -bool CBC_CommonBitMatrix::Get(int32_t x, int32_t y) { - int32_t offset = y * m_rowSize + (x >> 5); - if (offset >= m_rowSize * m_height || offset < 0) { - return false; - } - return ((((uint32_t)m_bits[offset]) >> (x & 0x1f)) & 1) != 0; -} -int32_t* CBC_CommonBitMatrix::GetBits() { - return m_bits; -} -void CBC_CommonBitMatrix::Set(int32_t x, int32_t y) { - int32_t offset = y * m_rowSize + (x >> 5); - if (offset >= m_rowSize * m_height || offset < 0) { - return; - } - m_bits[offset] |= 1 << (x & 0x1f); -} -void CBC_CommonBitMatrix::Flip(int32_t x, int32_t y) { - int32_t offset = y * m_rowSize + (x >> 5); - m_bits[offset] ^= 1 << (x & 0x1f); -} -void CBC_CommonBitMatrix::Clear() { - FXSYS_memset(m_bits, 0, m_rowSize * m_height * sizeof(int32_t)); -} -void CBC_CommonBitMatrix::SetRegion(int32_t left, - int32_t top, - int32_t width, - int32_t height, - int32_t& e) { - if (top < 0 || left < 0) { - e = BCExceptionLeftAndTopMustBeNonnegative; - return; - } - if (height < 1 || width < 1) { - e = BCExceptionHeightAndWidthMustBeAtLeast1; - return; - } - int32_t right = left + width; - int32_t bottom = top + height; - if (m_height < bottom || m_width < right) { - e = BCExceptionRegionMustFitInsideMatrix; - return; - } - int32_t y; - for (y = top; y < bottom; y++) { - int32_t offset = y * m_rowSize; - int32_t x; - for (x = left; x < right; x++) { - m_bits[offset + (x >> 5)] |= 1 << (x & 0x1f); - } - } -} -CBC_CommonBitArray* CBC_CommonBitMatrix::GetRow(int32_t y, - CBC_CommonBitArray* row) { - CBC_CommonBitArray* rowArray = nullptr; - if (!row || row->GetSize() < m_width) { - rowArray = new CBC_CommonBitArray(m_width); - } else { - rowArray = new CBC_CommonBitArray(row); - } - int32_t offset = y * m_rowSize; - int32_t x; - for (x = 0; x < m_rowSize; x++) { - rowArray->SetBulk(x << 5, m_bits[offset + x]); - } - return rowArray; -} -void CBC_CommonBitMatrix::SetRow(int32_t y, CBC_CommonBitArray* row) { - int32_t l = y * m_rowSize; - for (int32_t i = 0; i < m_rowSize; i++) { - m_bits[l] = row->GetBitArray()[i]; - l++; - } -} -void CBC_CommonBitMatrix::SetCol(int32_t y, CBC_CommonBitArray* col) { - for (int32_t i = 0; i < col->GetBits().GetSize(); i++) { - m_bits[i * m_rowSize + y] = col->GetBitArray()[i]; - } -} -int32_t CBC_CommonBitMatrix::GetWidth() { - return m_width; -} -int32_t CBC_CommonBitMatrix::GetHeight() { - return m_height; -} -int32_t CBC_CommonBitMatrix::GetRowSize() { - return m_rowSize; -} -int32_t CBC_CommonBitMatrix::GetDimension(int32_t& e) { - if (m_width != m_height) { - e = BCExceptionCanNotCallGetDimensionOnNonSquareMatrix; - return 0; - } - return m_width; -} diff --git a/xfa/fxbarcode/common/BC_CommonBitMatrix.h b/xfa/fxbarcode/common/BC_CommonBitMatrix.h deleted file mode 100644 index ed1f684a3753f83ae4f34e5eda05654d7fdf1e41..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/BC_CommonBitMatrix.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_COMMON_BC_COMMONBITMATRIX_H_ -#define XFA_FXBARCODE_COMMON_BC_COMMONBITMATRIX_H_ - -#include "core/fxcrt/fx_system.h" - -class CBC_CommonBitArray; - -class CBC_CommonBitMatrix { - public: - CBC_CommonBitMatrix(); - virtual ~CBC_CommonBitMatrix(); - - virtual void Init(int32_t dimension); - virtual void Init(int32_t width, int32_t height); - - bool Get(int32_t x, int32_t y); - void Set(int32_t x, int32_t y); - void Flip(int32_t x, int32_t y); - void Clear(); - void SetRegion(int32_t left, - int32_t top, - int32_t width, - int32_t height, - int32_t& e); - CBC_CommonBitArray* GetRow(int32_t y, CBC_CommonBitArray* row); - void SetRow(int32_t y, CBC_CommonBitArray* row); - CBC_CommonBitArray* GetCol(int32_t y, CBC_CommonBitArray* row); - void SetCol(int32_t y, CBC_CommonBitArray* col); - int32_t GetWidth(); - int32_t GetHeight(); - int32_t GetRowSize(); - int32_t GetDimension(int32_t& e); - int32_t* GetBits(); - - private: - int32_t m_width; - int32_t m_height; - int32_t m_rowSize; - int32_t* m_bits; -}; - -#endif // XFA_FXBARCODE_COMMON_BC_COMMONBITMATRIX_H_ diff --git a/xfa/fxbarcode/common/BC_CommonByteArray.h b/xfa/fxbarcode/common/BC_CommonByteArray.h deleted file mode 100644 index 009f625a8649a6bb8fbad78ebed6e7d826b2c96b..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/BC_CommonByteArray.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_COMMON_BC_COMMONBYTEARRAY_H_ -#define XFA_FXBARCODE_COMMON_BC_COMMONBYTEARRAY_H_ - -#include "core/fxcrt/fx_basic.h" - -// TODO(weili): The usage of this class should be replaced by -// std::vector<uint8_t>. -class CBC_CommonByteArray { - public: - CBC_CommonByteArray(); - explicit CBC_CommonByteArray(int32_t size); - CBC_CommonByteArray(uint8_t* byteArray, int32_t size); - virtual ~CBC_CommonByteArray(); - - int32_t At(int32_t index) const; - int32_t Size() const; - bool IsEmpty() const; - void Set(int32_t index, int32_t value); - void AppendByte(int32_t value); - void Reserve(int32_t capacity); - void Set(uint8_t* source, int32_t offset, int32_t count); - void Set(CFX_ArrayTemplate<uint8_t>* source, int32_t offset, int32_t count); - - private: - int32_t m_size; - int32_t m_index; - uint8_t* m_bytes; -}; - -#endif // XFA_FXBARCODE_COMMON_BC_COMMONBYTEARRAY_H_ diff --git a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp b/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp deleted file mode 100644 index 7698890366e4106e49d180ce7dd4531b118ac884..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.h" - -#include <memory> - -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h" - -CBC_ReedSolomonEncoder::CBC_ReedSolomonEncoder(CBC_ReedSolomonGF256* field) { - m_field = field; -} -void CBC_ReedSolomonEncoder::Init() { - m_cachedGenerators.Add(new CBC_ReedSolomonGF256Poly(m_field, 1)); -} -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonEncoder::BuildGenerator(int32_t degree, - int32_t& e) { - if (degree >= m_cachedGenerators.GetSize()) { - CBC_ReedSolomonGF256Poly* lastGenerator = - m_cachedGenerators[m_cachedGenerators.GetSize() - 1]; - for (int32_t d = m_cachedGenerators.GetSize(); d <= degree; d++) { - CFX_ArrayTemplate<int32_t> temp; - temp.Add(1); - temp.Add(m_field->Exp(d - 1)); - CBC_ReedSolomonGF256Poly temp_poly; - temp_poly.Init(m_field, &temp, e); - if (e != BCExceptionNO) - return nullptr; - CBC_ReedSolomonGF256Poly* nextGenerator = - lastGenerator->Multiply(&temp_poly, e); - if (e != BCExceptionNO) - return nullptr; - m_cachedGenerators.Add(nextGenerator); - lastGenerator = nextGenerator; - } - } - return m_cachedGenerators[degree]; -} -void CBC_ReedSolomonEncoder::Encode(CFX_ArrayTemplate<int32_t>* toEncode, - int32_t ecBytes, - int32_t& e) { - if (ecBytes == 0) { - e = BCExceptionNoCorrectionBytes; - return; - } - int32_t dataBytes = toEncode->GetSize() - ecBytes; - if (dataBytes <= 0) { - e = BCExceptionNoDataBytesProvided; - return; - } - CBC_ReedSolomonGF256Poly* generator = BuildGenerator(ecBytes, e); - if (e != BCExceptionNO) - return; - CFX_ArrayTemplate<int32_t> infoCoefficients; - infoCoefficients.SetSize(dataBytes); - for (int32_t x = 0; x < dataBytes; x++) { - infoCoefficients[x] = toEncode->operator[](x); - } - CBC_ReedSolomonGF256Poly info; - info.Init(m_field, &infoCoefficients, e); - if (e != BCExceptionNO) - return; - std::unique_ptr<CBC_ReedSolomonGF256Poly> infoTemp( - info.MultiplyByMonomial(ecBytes, 1, e)); - if (e != BCExceptionNO) - return; - std::unique_ptr<CFX_ArrayTemplate<CBC_ReedSolomonGF256Poly*>> temp( - infoTemp->Divide(generator, e)); - if (e != BCExceptionNO) - return; - CBC_ReedSolomonGF256Poly* remainder = (*temp)[1]; - CFX_ArrayTemplate<int32_t>* coefficients = remainder->GetCoefficients(); - int32_t numZeroCoefficients = ecBytes - coefficients->GetSize(); - for (int32_t i = 0; i < numZeroCoefficients; i++) { - (*toEncode)[dataBytes + i] = 0; - } - for (int32_t y = 0; y < coefficients->GetSize(); y++) { - (*toEncode)[dataBytes + numZeroCoefficients + y] = - coefficients->operator[](y); - } - for (int32_t k = 0; k < temp->GetSize(); k++) { - delete (*temp)[k]; - } -} -CBC_ReedSolomonEncoder::~CBC_ReedSolomonEncoder() { - for (int32_t i = 0; i < m_cachedGenerators.GetSize(); i++) - delete m_cachedGenerators[i]; -} diff --git a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.h b/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.h deleted file mode 100644 index 95828f1a0e133d8bcf97a029e01d671f969b7c6f..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMON_H_ -#define XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMON_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_ReedSolomonGF256; -class CBC_ReedSolomonGF256Poly; - -class CBC_ReedSolomonEncoder { - public: - explicit CBC_ReedSolomonEncoder(CBC_ReedSolomonGF256* field); - virtual ~CBC_ReedSolomonEncoder(); - - void Encode(CFX_ArrayTemplate<int32_t>* toEncode, - int32_t ecBytes, - int32_t& e); - virtual void Init(); - - private: - CBC_ReedSolomonGF256Poly* BuildGenerator(int32_t degree, int32_t& e); - - CBC_ReedSolomonGF256* m_field; - CFX_ArrayTemplate<CBC_ReedSolomonGF256Poly*> m_cachedGenerators; -}; - -#endif // XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMON_H_ diff --git a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h b/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h deleted file mode 100644 index 16f1ad17f75eb159356e34ecd9d0f6ed94a9bfed..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256_H_ -#define XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256_H_ - -#include <memory> - -#include "core/fxcrt/fx_basic.h" -#include "xfa/fxbarcode/utils.h" - -class CBC_ReedSolomonGF256Poly; - -class CBC_ReedSolomonGF256 { - public: - explicit CBC_ReedSolomonGF256(int32_t primitive); - virtual ~CBC_ReedSolomonGF256(); - - static void Initialize(); - static void Finalize(); - - CBC_ReedSolomonGF256Poly* GetZero() const; - CBC_ReedSolomonGF256Poly* GetOne() const; - CBC_ReedSolomonGF256Poly* BuildMonomial(int32_t degree, - int32_t coefficient, - int32_t& e); - static int32_t AddOrSubtract(int32_t a, int32_t b); - int32_t Exp(int32_t a); - int32_t Log(int32_t a, int32_t& e); - int32_t Inverse(int32_t a, int32_t& e); - int32_t Multiply(int32_t a, int32_t b); - virtual void Init(); - - static CBC_ReedSolomonGF256* QRCodeField; - static CBC_ReedSolomonGF256* DataMatrixField; - - private: - int32_t m_expTable[256]; - int32_t m_logTable[256]; - std::unique_ptr<CBC_ReedSolomonGF256Poly> m_zero; - std::unique_ptr<CBC_ReedSolomonGF256Poly> m_one; -}; - -#endif // XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256_H_ diff --git a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp b/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp deleted file mode 100644 index a0bbc025c4ae5b47521311f1780af6e41ce4f5eb..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.cpp +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h" - -#include <memory> - -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" - -CBC_ReedSolomonGF256Poly::CBC_ReedSolomonGF256Poly(CBC_ReedSolomonGF256* field, - int32_t coefficients) { - if (!field) - return; - - m_field = field; - m_coefficients.Add(coefficients); -} -CBC_ReedSolomonGF256Poly::CBC_ReedSolomonGF256Poly() { - m_field = nullptr; -} -void CBC_ReedSolomonGF256Poly::Init(CBC_ReedSolomonGF256* field, - CFX_ArrayTemplate<int32_t>* coefficients, - int32_t& e) { - if (!coefficients || coefficients->GetSize() == 0) { - e = BCExceptionCoefficientsSizeIsNull; - return; - } - m_field = field; - int32_t coefficientsLength = coefficients->GetSize(); - if ((coefficientsLength > 1 && (*coefficients)[0] == 0)) { - int32_t firstNonZero = 1; - while ((firstNonZero < coefficientsLength) && - ((*coefficients)[firstNonZero] == 0)) { - firstNonZero++; - } - if (firstNonZero == coefficientsLength) { - m_coefficients.Copy(*(m_field->GetZero()->GetCoefficients())); - } else { - m_coefficients.SetSize(coefficientsLength - firstNonZero); - for (int32_t i = firstNonZero, j = 0; i < coefficientsLength; i++, j++) { - m_coefficients[j] = coefficients->operator[](i); - } - } - } else { - m_coefficients.Copy(*coefficients); - } -} -CFX_ArrayTemplate<int32_t>* CBC_ReedSolomonGF256Poly::GetCoefficients() { - return &m_coefficients; -} -int32_t CBC_ReedSolomonGF256Poly::GetDegree() { - return m_coefficients.GetSize() - 1; -} -bool CBC_ReedSolomonGF256Poly::IsZero() { - return m_coefficients[0] == 0; -} -int32_t CBC_ReedSolomonGF256Poly::GetCoefficients(int32_t degree) { - return m_coefficients[m_coefficients.GetSize() - 1 - degree]; -} -int32_t CBC_ReedSolomonGF256Poly::EvaluateAt(int32_t a) { - if (a == 0) { - return GetCoefficients(0); - } - int32_t size = m_coefficients.GetSize(); - if (a == 1) { - int32_t result = 0; - for (int32_t i = 0; i < size; i++) { - result = CBC_ReedSolomonGF256::AddOrSubtract(result, m_coefficients[i]); - } - return result; - } - int32_t result = m_coefficients[0]; - for (int32_t j = 1; j < size; j++) { - result = CBC_ReedSolomonGF256::AddOrSubtract(m_field->Multiply(a, result), - m_coefficients[j]); - } - return result; -} -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256Poly::Clone(int32_t& e) { - CBC_ReedSolomonGF256Poly* temp = new CBC_ReedSolomonGF256Poly(); - temp->Init(m_field, &m_coefficients, e); - if (e != BCExceptionNO) - return nullptr; - return temp; -} -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256Poly::AddOrSubtract( - CBC_ReedSolomonGF256Poly* other, - int32_t& e) { - if (IsZero()) - return other->Clone(e); - if (other->IsZero()) - return Clone(e); - - CFX_ArrayTemplate<int32_t> smallerCoefficients; - smallerCoefficients.Copy(m_coefficients); - CFX_ArrayTemplate<int32_t> largerCoefficients; - largerCoefficients.Copy(*(other->GetCoefficients())); - if (smallerCoefficients.GetSize() > largerCoefficients.GetSize()) { - CFX_ArrayTemplate<int32_t> temp; - temp.Copy(smallerCoefficients); - smallerCoefficients.Copy(largerCoefficients); - largerCoefficients.Copy(temp); - } - CFX_ArrayTemplate<int32_t> sumDiff; - sumDiff.SetSize(largerCoefficients.GetSize()); - int32_t lengthDiff = - largerCoefficients.GetSize() - smallerCoefficients.GetSize(); - for (int32_t i = 0; i < lengthDiff; i++) { - sumDiff[i] = largerCoefficients[i]; - } - for (int32_t j = lengthDiff; j < largerCoefficients.GetSize(); j++) { - sumDiff[j] = (CBC_ReedSolomonGF256::AddOrSubtract( - smallerCoefficients[j - lengthDiff], largerCoefficients[j])); - } - CBC_ReedSolomonGF256Poly* temp = new CBC_ReedSolomonGF256Poly(); - temp->Init(m_field, &sumDiff, e); - if (e != BCExceptionNO) - return nullptr; - return temp; -} -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256Poly::Multiply( - CBC_ReedSolomonGF256Poly* other, - int32_t& e) { - if (IsZero() || other->IsZero()) - return m_field->GetZero()->Clone(e); - - CFX_ArrayTemplate<int32_t> aCoefficients; - aCoefficients.Copy(m_coefficients); - int32_t aLength = m_coefficients.GetSize(); - CFX_ArrayTemplate<int32_t> bCoefficients; - bCoefficients.Copy(*(other->GetCoefficients())); - int32_t bLength = other->GetCoefficients()->GetSize(); - CFX_ArrayTemplate<int32_t> product; - product.SetSize(aLength + bLength - 1); - for (int32_t i = 0; i < aLength; i++) { - int32_t aCoeff = m_coefficients[i]; - for (int32_t j = 0; j < bLength; j++) { - product[i + j] = CBC_ReedSolomonGF256::AddOrSubtract( - product[i + j], - m_field->Multiply(aCoeff, other->GetCoefficients()->operator[](j))); - } - } - CBC_ReedSolomonGF256Poly* temp = new CBC_ReedSolomonGF256Poly(); - temp->Init(m_field, &product, e); - if (e != BCExceptionNO) - return nullptr; - return temp; -} -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256Poly::Multiply(int32_t scalar, - int32_t& e) { - if (scalar == 0) - return m_field->GetZero()->Clone(e); - if (scalar == 1) - return Clone(e); - - int32_t size = m_coefficients.GetSize(); - CFX_ArrayTemplate<int32_t> product; - product.SetSize(size); - for (int32_t i = 0; i < size; i++) { - product[i] = m_field->Multiply(m_coefficients[i], scalar); - } - CBC_ReedSolomonGF256Poly* temp = new CBC_ReedSolomonGF256Poly(); - temp->Init(m_field, &product, e); - if (e != BCExceptionNO) - return nullptr; - return temp; -} -CBC_ReedSolomonGF256Poly* CBC_ReedSolomonGF256Poly::MultiplyByMonomial( - int32_t degree, - int32_t coefficient, - int32_t& e) { - if (degree < 0) { - e = BCExceptionDegreeIsNegative; - return nullptr; - } - if (coefficient == 0) - return m_field->GetZero()->Clone(e); - - int32_t size = m_coefficients.GetSize(); - CFX_ArrayTemplate<int32_t> product; - product.SetSize(size + degree); - for (int32_t i = 0; i < size; i++) { - product[i] = (m_field->Multiply(m_coefficients[i], coefficient)); - } - CBC_ReedSolomonGF256Poly* temp = new CBC_ReedSolomonGF256Poly(); - temp->Init(m_field, &product, e); - if (e != BCExceptionNO) - return nullptr; - return temp; -} - -CFX_ArrayTemplate<CBC_ReedSolomonGF256Poly*>* CBC_ReedSolomonGF256Poly::Divide( - CBC_ReedSolomonGF256Poly* other, - int32_t& e) { - if (other->IsZero()) { - e = BCExceptionDivideByZero; - return nullptr; - } - std::unique_ptr<CBC_ReedSolomonGF256Poly> quotient( - m_field->GetZero()->Clone(e)); - if (e != BCExceptionNO) - return nullptr; - std::unique_ptr<CBC_ReedSolomonGF256Poly> remainder(Clone(e)); - if (e != BCExceptionNO) - return nullptr; - int32_t denominatorLeadingTerm = other->GetCoefficients(other->GetDegree()); - int32_t inverseDenominatorLeadingTeam = - m_field->Inverse(denominatorLeadingTerm, e); - if (e != BCExceptionNO) - return nullptr; - while (remainder->GetDegree() >= other->GetDegree() && !remainder->IsZero()) { - int32_t degreeDifference = remainder->GetDegree() - other->GetDegree(); - int32_t scale = - m_field->Multiply(remainder->GetCoefficients((remainder->GetDegree())), - inverseDenominatorLeadingTeam); - std::unique_ptr<CBC_ReedSolomonGF256Poly> term( - other->MultiplyByMonomial(degreeDifference, scale, e)); - if (e != BCExceptionNO) - return nullptr; - std::unique_ptr<CBC_ReedSolomonGF256Poly> iteratorQuotient( - m_field->BuildMonomial(degreeDifference, scale, e)); - if (e != BCExceptionNO) - return nullptr; - quotient.reset(quotient->AddOrSubtract(iteratorQuotient.get(), e)); - if (e != BCExceptionNO) - return nullptr; - remainder.reset(remainder->AddOrSubtract(term.get(), e)); - if (e != BCExceptionNO) - return nullptr; - } - CFX_ArrayTemplate<CBC_ReedSolomonGF256Poly*>* tempPtrA = - new CFX_ArrayTemplate<CBC_ReedSolomonGF256Poly*>(); - tempPtrA->Add(quotient.release()); - tempPtrA->Add(remainder.release()); - return tempPtrA; -} - -CBC_ReedSolomonGF256Poly::~CBC_ReedSolomonGF256Poly() { - m_coefficients.RemoveAll(); -} diff --git a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h b/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h deleted file mode 100644 index ff93264e00df772608f3eb79dee613a1751b3328..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256Poly.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256POLY_H_ -#define XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256POLY_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_ReedSolomonGF256; - -class CBC_ReedSolomonGF256Poly final { - public: - CBC_ReedSolomonGF256Poly(CBC_ReedSolomonGF256* field, int32_t coefficients); - CBC_ReedSolomonGF256Poly(); - ~CBC_ReedSolomonGF256Poly(); - void Init(CBC_ReedSolomonGF256* field, - CFX_ArrayTemplate<int32_t>* coefficients, - int32_t& e); - - int32_t GetCoefficients(int32_t degree); - CFX_ArrayTemplate<int32_t>* GetCoefficients(); - int32_t GetDegree(); - bool IsZero(); - int32_t EvaluateAt(int32_t a); - CBC_ReedSolomonGF256Poly* AddOrSubtract(CBC_ReedSolomonGF256Poly* other, - int32_t& e); - CBC_ReedSolomonGF256Poly* Multiply(CBC_ReedSolomonGF256Poly* other, - int32_t& e); - CBC_ReedSolomonGF256Poly* Multiply(int32_t scalar, int32_t& e); - CBC_ReedSolomonGF256Poly* MultiplyByMonomial(int32_t degree, - int32_t coefficient, - int32_t& e); - CFX_ArrayTemplate<CBC_ReedSolomonGF256Poly*>* Divide( - CBC_ReedSolomonGF256Poly* other, - int32_t& e); - - CBC_ReedSolomonGF256Poly* Clone(int32_t& e); - - private: - CBC_ReedSolomonGF256* m_field; - CFX_ArrayTemplate<int32_t> m_coefficients; -}; - -#endif // XFA_FXBARCODE_COMMON_REEDSOLOMON_BC_REEDSOLOMONGF256POLY_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h b/xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h deleted file mode 100644 index 40559b532d8396981ce4b3b66c41d8a0567dbcd2..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_ASCIIENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_ASCIIENCODER_H_ - -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" - -class CBC_EncoderContext; - -class CBC_ASCIIEncoder : public CBC_Encoder { - public: - CBC_ASCIIEncoder(); - ~CBC_ASCIIEncoder() override; - - // CBC_Encoder - int32_t getEncodingMode() override; - void Encode(CBC_EncoderContext& context, int32_t& e) override; - - private: - static FX_WCHAR encodeASCIIDigits(FX_WCHAR digit1, - FX_WCHAR digit2, - int32_t& e); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_ASCIIENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_Base256Encoder.cpp b/xfa/fxbarcode/datamatrix/BC_Base256Encoder.cpp deleted file mode 100644 index b8e427c7fc76ba2016eb96082f6afdf96d64beb8..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_Base256Encoder.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/datamatrix/BC_Base256Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -CBC_Base256Encoder::CBC_Base256Encoder() {} -CBC_Base256Encoder::~CBC_Base256Encoder() {} -int32_t CBC_Base256Encoder::getEncodingMode() { - return BASE256_ENCODATION; -} -void CBC_Base256Encoder::Encode(CBC_EncoderContext& context, int32_t& e) { - CFX_WideString buffer; - buffer += (FX_WCHAR)'\0'; - while (context.hasMoreCharacters()) { - FX_WCHAR c = context.getCurrentChar(); - buffer += c; - context.m_pos++; - int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( - context.m_msg, context.m_pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(newMode); - break; - } - } - int32_t dataCount = buffer.GetLength() - 1; - FX_CHAR buf[128]; - FXSYS_itoa(dataCount, buf, 10); - buffer.SetAt(0, FX_WCHAR(*buf) - '0'); - int32_t lengthFieldSize = 1; - int32_t currentSize = - context.getCodewordCount() + dataCount + lengthFieldSize; - context.updateSymbolInfo(currentSize, e); - if (e != BCExceptionNO) { - return; - } - bool mustPad = (context.m_symbolInfo->m_dataCapacity - currentSize) > 0; - if (context.hasMoreCharacters() || mustPad) { - if (dataCount <= 249) { - buffer.SetAt(0, (FX_WCHAR)dataCount); - } else if (dataCount > 249 && dataCount <= 1555) { - buffer.SetAt(0, (FX_WCHAR)((dataCount / 250) + 249)); - buffer.Insert(1, (FX_WCHAR)(dataCount % 250)); - } else { - e = BCExceptionIllegalStateMessageLengthInvalid; - return; - } - } - for (int32_t i = 0, c = buffer.GetLength(); i < c; i++) { - context.writeCodeword( - randomize255State(buffer.GetAt(i), context.getCodewordCount() + 1)); - } -} -FX_WCHAR CBC_Base256Encoder::randomize255State(FX_WCHAR ch, - int32_t codewordPosition) { - int32_t pseudoRandom = ((149 * codewordPosition) % 255) + 1; - int32_t tempVariable = ch + pseudoRandom; - if (tempVariable <= 255) { - return (FX_WCHAR)tempVariable; - } else { - return (FX_WCHAR)(tempVariable - 256); - } -} diff --git a/xfa/fxbarcode/datamatrix/BC_Base256Encoder.h b/xfa/fxbarcode/datamatrix/BC_Base256Encoder.h deleted file mode 100644 index c41c79db081df773215be2b6fd6d24772527b118..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_Base256Encoder.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_BASE256ENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_BASE256ENCODER_H_ - -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" - -class CBC_Base256Encoder : public CBC_Encoder { - public: - CBC_Base256Encoder(); - ~CBC_Base256Encoder() override; - - // CBC_Encoder - int32_t getEncodingMode() override; - void Encode(CBC_EncoderContext& context, int32_t& e) override; - - private: - static FX_WCHAR randomize255State(FX_WCHAR ch, int32_t codewordPosition); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_BASE256ENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_C40Encoder.cpp b/xfa/fxbarcode/datamatrix/BC_C40Encoder.cpp deleted file mode 100644 index 50f02ca52de13efb3786386dba597904bb3813eb..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_C40Encoder.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -CBC_C40Encoder::CBC_C40Encoder() {} -CBC_C40Encoder::~CBC_C40Encoder() {} -int32_t CBC_C40Encoder::getEncodingMode() { - return C40_ENCODATION; -} -void CBC_C40Encoder::Encode(CBC_EncoderContext& context, int32_t& e) { - CFX_WideString buffer; - while (context.hasMoreCharacters()) { - FX_WCHAR c = context.getCurrentChar(); - context.m_pos++; - int32_t lastCharSize = encodeChar(c, buffer, e); - if (e != BCExceptionNO) { - return; - } - int32_t unwritten = (buffer.GetLength() / 3) * 2; - int32_t curCodewordCount = context.getCodewordCount() + unwritten; - context.updateSymbolInfo(curCodewordCount, e); - if (e != BCExceptionNO) { - return; - } - int32_t available = context.m_symbolInfo->m_dataCapacity - curCodewordCount; - if (!context.hasMoreCharacters()) { - CFX_WideString removed; - if ((buffer.GetLength() % 3) == 2) { - if (available < 2 || available > 2) { - lastCharSize = - backtrackOneCharacter(context, buffer, removed, lastCharSize, e); - if (e != BCExceptionNO) { - return; - } - } - } - while ((buffer.GetLength() % 3) == 1 && - ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) { - lastCharSize = - backtrackOneCharacter(context, buffer, removed, lastCharSize, e); - if (e != BCExceptionNO) { - return; - } - } - break; - } - int32_t count = buffer.GetLength(); - if ((count % 3) == 0) { - int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( - context.m_msg, context.m_pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(newMode); - break; - } - } - } - handleEOD(context, buffer, e); -} -void CBC_C40Encoder::writeNextTriplet(CBC_EncoderContext& context, - CFX_WideString& buffer) { - context.writeCodewords(encodeToCodewords(buffer, 0)); - buffer.Delete(0, 3); -} -void CBC_C40Encoder::handleEOD(CBC_EncoderContext& context, - CFX_WideString& buffer, - int32_t& e) { - int32_t unwritten = (buffer.GetLength() / 3) * 2; - int32_t rest = buffer.GetLength() % 3; - int32_t curCodewordCount = context.getCodewordCount() + unwritten; - context.updateSymbolInfo(curCodewordCount, e); - if (e != BCExceptionNO) { - return; - } - int32_t available = context.m_symbolInfo->m_dataCapacity - curCodewordCount; - if (rest == 2) { - buffer += (FX_WCHAR)'\0'; - while (buffer.GetLength() >= 3) { - writeNextTriplet(context, buffer); - } - if (context.hasMoreCharacters()) { - context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH); - } - } else if (available == 1 && rest == 1) { - while (buffer.GetLength() >= 3) { - writeNextTriplet(context, buffer); - } - if (context.hasMoreCharacters()) { - context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH); - } - context.m_pos--; - } else if (rest == 0) { - while (buffer.GetLength() >= 3) { - writeNextTriplet(context, buffer); - } - if (available > 0 || context.hasMoreCharacters()) { - context.writeCodeword(CBC_HighLevelEncoder::C40_UNLATCH); - } - } else { - e = BCExceptionIllegalStateUnexpectedCase; - return; - } - context.signalEncoderChange(ASCII_ENCODATION); -} -int32_t CBC_C40Encoder::encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e) { - if (c == ' ') { - sb += (FX_WCHAR)'\3'; - return 1; - } else if ((c >= '0') && (c <= '9')) { - sb += (FX_WCHAR)(c - 48 + 4); - return 1; - } else if ((c >= 'A') && (c <= 'Z')) { - sb += (FX_WCHAR)(c - 65 + 14); - return 1; - } else if (c <= 0x1f) { - sb += (FX_WCHAR)'\0'; - sb += c; - return 2; - } else if ((c >= '!') && (c <= '/')) { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)(c - 33); - return 2; - } else if ((c >= ':') && (c <= '@')) { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)(c - 58 + 15); - return 2; - } else if ((c >= '[') && (c <= '_')) { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)(c - 91 + 22); - return 2; - } else if ((c >= 60) && (c <= 0x7f)) { - sb += (FX_WCHAR)'\2'; - sb += (FX_WCHAR)(c - 96); - return 2; - } else if (c >= 80) { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)0x001e; - int32_t len = 2; - len += encodeChar((c - 128), sb, e); - if (e != BCExceptionNO) - return 0; - return len; - } else { - e = BCExceptionIllegalArgument; - return 0; - } -} -int32_t CBC_C40Encoder::backtrackOneCharacter(CBC_EncoderContext& context, - CFX_WideString& buffer, - CFX_WideString& removed, - int32_t lastCharSize, - int32_t& e) { - int32_t count = buffer.GetLength(); - buffer.Delete(count - lastCharSize, count); - context.m_pos--; - FX_WCHAR c = context.getCurrentChar(); - lastCharSize = encodeChar(c, removed, e); - if (e != BCExceptionNO) - return -1; - context.resetSymbolInfo(); - return lastCharSize; -} -CFX_WideString CBC_C40Encoder::encodeToCodewords(CFX_WideString sb, - int32_t startPos) { - FX_WCHAR c1 = sb.GetAt(startPos); - FX_WCHAR c2 = sb.GetAt(startPos + 1); - FX_WCHAR c3 = sb.GetAt(startPos + 2); - int32_t v = (1600 * c1) + (40 * c2) + c3 + 1; - FX_WCHAR cw1 = (FX_WCHAR)(v / 256); - FX_WCHAR cw2 = (FX_WCHAR)(v % 256); - CFX_WideString b1(cw1); - CFX_WideString b2(cw2); - return b1 + b2; -} diff --git a/xfa/fxbarcode/datamatrix/BC_C40Encoder.h b/xfa/fxbarcode/datamatrix/BC_C40Encoder.h deleted file mode 100644 index 9737981f75b23f59ef3f786dd9c9b3d140dd36c6..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_C40Encoder.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_C40ENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_C40ENCODER_H_ - -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" - -class CBC_C40Encoder : public CBC_Encoder { - public: - CBC_C40Encoder(); - ~CBC_C40Encoder() override; - - // CBC_Encoder - int32_t getEncodingMode() override; - void Encode(CBC_EncoderContext& context, int32_t& e) override; - - static void writeNextTriplet(CBC_EncoderContext& context, - CFX_WideString& buffer); - - virtual void handleEOD(CBC_EncoderContext& context, - CFX_WideString& buffer, - int32_t& e); - virtual int32_t encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e); - - private: - int32_t backtrackOneCharacter(CBC_EncoderContext& context, - CFX_WideString& buffer, - CFX_WideString& removed, - int32_t lastCharSize, - int32_t& e); - static CFX_WideString encodeToCodewords(CFX_WideString sb, int32_t startPos); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_C40ENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h b/xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h deleted file mode 100644 index 2cd0cd0e6f202bbfd1afb1505cb4921240363548..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_DATAMATRIXSYMBOLINFO144_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_DATAMATRIXSYMBOLINFO144_H_ - -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" - -class CBC_DataMatrixSymbolInfo144 : public CBC_SymbolInfo { - public: - CBC_DataMatrixSymbolInfo144(); - ~CBC_DataMatrixSymbolInfo144() override; - - int32_t getInterleavedBlockCount(); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_DATAMATRIXSYMBOLINFO144_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp b/xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp deleted file mode 100644 index f1ce798af074947fe7ca42ed06802b97431d9b18..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/BC_TwoDimWriter.h" -#include "xfa/fxbarcode/BC_UtilCodingConvert.h" -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Base256Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h" -#include "xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.h" -#include "xfa/fxbarcode/datamatrix/BC_DefaultPlacement.h" -#include "xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" -#include "xfa/fxbarcode/datamatrix/BC_TextEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_X12Encoder.h" - -CBC_DataMatrixWriter::CBC_DataMatrixWriter() {} -CBC_DataMatrixWriter::~CBC_DataMatrixWriter() {} -bool CBC_DataMatrixWriter::SetErrorCorrectionLevel(int32_t level) { - m_iCorrectLevel = level; - return true; -} -uint8_t* CBC_DataMatrixWriter::Encode(const CFX_WideString& contents, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - if (outWidth < 0 || outHeight < 0) { - e = BCExceptionHeightAndWidthMustBeAtLeast1; - return nullptr; - } - CBC_SymbolShapeHint::SymbolShapeHint shape = - CBC_SymbolShapeHint::FORCE_SQUARE; - CBC_Dimension* minSize = nullptr; - CBC_Dimension* maxSize = nullptr; - CFX_WideString ecLevel; - CFX_WideString encoded = CBC_HighLevelEncoder::encodeHighLevel( - contents, ecLevel, shape, minSize, maxSize, e); - if (e != BCExceptionNO) - return nullptr; - CBC_SymbolInfo* symbolInfo = CBC_SymbolInfo::lookup( - encoded.GetLength(), shape, minSize, maxSize, true, e); - if (e != BCExceptionNO) - return nullptr; - CFX_WideString codewords = - CBC_ErrorCorrection::encodeECC200(encoded, symbolInfo, e); - if (e != BCExceptionNO) - return nullptr; - CBC_DefaultPlacement* placement = - new CBC_DefaultPlacement(codewords, symbolInfo->getSymbolDataWidth(e), - symbolInfo->getSymbolDataHeight(e)); - if (e != BCExceptionNO) - return nullptr; - placement->place(); - CBC_CommonByteMatrix* bytematrix = encodeLowLevel(placement, symbolInfo, e); - if (e != BCExceptionNO) - return nullptr; - outWidth = bytematrix->GetWidth(); - outHeight = bytematrix->GetHeight(); - uint8_t* result = FX_Alloc2D(uint8_t, outWidth, outHeight); - FXSYS_memcpy(result, bytematrix->GetArray(), outWidth * outHeight); - delete bytematrix; - delete placement; - return result; -} -CBC_CommonByteMatrix* CBC_DataMatrixWriter::encodeLowLevel( - CBC_DefaultPlacement* placement, - CBC_SymbolInfo* symbolInfo, - int32_t& e) { - int32_t symbolWidth = symbolInfo->getSymbolDataWidth(e); - if (e != BCExceptionNO) - return nullptr; - int32_t symbolHeight = symbolInfo->getSymbolDataHeight(e); - if (e != BCExceptionNO) - return nullptr; - CBC_CommonByteMatrix* matrix = new CBC_CommonByteMatrix( - symbolInfo->getSymbolWidth(e), symbolInfo->getSymbolHeight(e)); - if (e != BCExceptionNO) - return nullptr; - matrix->Init(); - int32_t matrixY = 0; - for (int32_t y = 0; y < symbolHeight; y++) { - int32_t matrixX; - if ((y % symbolInfo->m_matrixHeight) == 0) { - matrixX = 0; - for (int32_t x = 0; x < symbolInfo->getSymbolWidth(e); x++) { - matrix->Set(matrixX, matrixY, (x % 2) == 0); - matrixX++; - } - matrixY++; - } - matrixX = 0; - for (int32_t x = 0; x < symbolWidth; x++) { - if ((x % symbolInfo->m_matrixWidth) == 0) { - matrix->Set(matrixX, matrixY, true); - matrixX++; - } - matrix->Set(matrixX, matrixY, placement->getBit(x, y)); - matrixX++; - if ((x % symbolInfo->m_matrixWidth) == symbolInfo->m_matrixWidth - 1) { - matrix->Set(matrixX, matrixY, (y % 2) == 0); - matrixX++; - } - } - matrixY++; - if ((y % symbolInfo->m_matrixHeight) == symbolInfo->m_matrixHeight - 1) { - matrixX = 0; - for (int32_t x = 0; x < symbolInfo->getSymbolWidth(e); x++) { - matrix->Set(matrixX, matrixY, true); - matrixX++; - } - matrixY++; - } - } - return matrix; -} diff --git a/xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.h b/xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.h deleted file mode 100644 index af1417b588a5fafa1f958fbe4ccf1e6514a01131..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_DataMatrixWriter.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_DATAMATRIXWRITER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_DATAMATRIXWRITER_H_ - -#include "xfa/fxbarcode/BC_TwoDimWriter.h" - -class CBC_CommonByteMatrix; -class CBC_DefaultPlacement; -class CBC_SymbolInfo; - -class CBC_DataMatrixWriter : public CBC_TwoDimWriter { - public: - CBC_DataMatrixWriter(); - ~CBC_DataMatrixWriter() override; - - virtual uint8_t* Encode(const CFX_WideString& contents, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e); - - // CBC_TwoDimWriter - bool SetErrorCorrectionLevel(int32_t level) override; - - private: - static CBC_CommonByteMatrix* encodeLowLevel(CBC_DefaultPlacement* placement, - CBC_SymbolInfo* symbolInfo, - int32_t& e); - int32_t m_iCorrectLevel; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_DATAMATRIXWRITER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_DefaultPlacement.h b/xfa/fxbarcode/datamatrix/BC_DefaultPlacement.h deleted file mode 100644 index 36a7ab2615c3939040c352cca140db9b0e6f2b13..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_DefaultPlacement.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_DEFAULTPLACEMENT_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_DEFAULTPLACEMENT_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_DefaultPlacement { - public: - CBC_DefaultPlacement(CFX_WideString codewords, - int32_t numcols, - int32_t numrows); - virtual ~CBC_DefaultPlacement(); - - int32_t getNumrows(); - int32_t getNumcols(); - CFX_ArrayTemplate<uint8_t>& getBits(); - bool getBit(int32_t col, int32_t row); - void setBit(int32_t col, int32_t row, bool bit); - bool hasBit(int32_t col, int32_t row); - void place(); - - private: - CFX_WideString m_codewords; - int32_t m_numrows; - int32_t m_numcols; - CFX_ArrayTemplate<uint8_t> m_bits; - void module(int32_t row, int32_t col, int32_t pos, int32_t bit); - void utah(int32_t row, int32_t col, int32_t pos); - void corner1(int32_t pos); - void corner2(int32_t pos); - void corner3(int32_t pos); - void corner4(int32_t pos); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_DEFAULTPLACEMENT_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_EdifactEncoder.cpp b/xfa/fxbarcode/datamatrix/BC_EdifactEncoder.cpp deleted file mode 100644 index 7db117d00375fc06e9408352f70108a1329e2c0c..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_EdifactEncoder.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -CBC_EdifactEncoder::CBC_EdifactEncoder() {} -CBC_EdifactEncoder::~CBC_EdifactEncoder() {} -int32_t CBC_EdifactEncoder::getEncodingMode() { - return EDIFACT_ENCODATION; -} -void CBC_EdifactEncoder::Encode(CBC_EncoderContext& context, int32_t& e) { - CFX_WideString buffer; - while (context.hasMoreCharacters()) { - FX_WCHAR c = context.getCurrentChar(); - encodeChar(c, buffer, e); - if (e != BCExceptionNO) { - return; - } - context.m_pos++; - int32_t count = buffer.GetLength(); - if (count >= 4) { - context.writeCodewords(encodeToCodewords(buffer, 0, e)); - if (e != BCExceptionNO) { - return; - } - buffer.Delete(0, 4); - int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( - context.m_msg, context.m_pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(ASCII_ENCODATION); - break; - } - } - } - buffer += (FX_WCHAR)31; - handleEOD(context, buffer, e); -} -void CBC_EdifactEncoder::handleEOD(CBC_EncoderContext& context, - CFX_WideString buffer, - int32_t& e) { - int32_t count = buffer.GetLength(); - if (count == 0) { - return; - } - if (count == 1) { - context.updateSymbolInfo(e); - if (e != BCExceptionNO) { - return; - } - int32_t available = - context.m_symbolInfo->m_dataCapacity - context.getCodewordCount(); - int32_t remaining = context.getRemainingCharacters(); - if (remaining == 0 && available <= 2) { - return; - } - } - if (count > 4) { - e = BCExceptionIllegalStateCountMustNotExceed4; - return; - } - int32_t restChars = count - 1; - CFX_WideString encoded = encodeToCodewords(buffer, 0, e); - if (e != BCExceptionNO) { - return; - } - bool endOfSymbolReached = !context.hasMoreCharacters(); - bool restInAscii = endOfSymbolReached && restChars <= 2; - if (restChars <= 2) { - context.updateSymbolInfo(context.getCodewordCount() + restChars, e); - if (e != BCExceptionNO) { - return; - } - int32_t available = - context.m_symbolInfo->m_dataCapacity - context.getCodewordCount(); - if (available >= 3) { - restInAscii = false; - context.updateSymbolInfo(context.getCodewordCount() + encoded.GetLength(), - e); - if (e != BCExceptionNO) { - return; - } - } - } - if (restInAscii) { - context.resetSymbolInfo(); - context.m_pos -= restChars; - } else { - context.writeCodewords(encoded); - } - context.signalEncoderChange(ASCII_ENCODATION); -} -void CBC_EdifactEncoder::encodeChar(FX_WCHAR c, - CFX_WideString& sb, - int32_t& e) { - if (c >= ' ' && c <= '?') { - sb += c; - } else if (c >= '@' && c <= '^') { - sb += (FX_WCHAR)(c - 64); - } else { - CBC_HighLevelEncoder::illegalCharacter(c, e); - } -} -CFX_WideString CBC_EdifactEncoder::encodeToCodewords(CFX_WideString sb, - int32_t startPos, - int32_t& e) { - int32_t len = sb.GetLength() - startPos; - if (len == 0) { - e = BCExceptionNoContents; - return CFX_WideString(); - } - FX_WCHAR c1 = sb.GetAt(startPos); - FX_WCHAR c2 = len >= 2 ? sb.GetAt(startPos + 1) : 0; - FX_WCHAR c3 = len >= 3 ? sb.GetAt(startPos + 2) : 0; - FX_WCHAR c4 = len >= 4 ? sb.GetAt(startPos + 3) : 0; - int32_t v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4; - FX_WCHAR cw1 = (FX_WCHAR)((v >> 16) & 255); - FX_WCHAR cw2 = (FX_WCHAR)((v >> 8) & 255); - FX_WCHAR cw3 = (FX_WCHAR)(v & 255); - CFX_WideString res; - res += cw1; - if (len >= 2) { - res += cw2; - } - if (len >= 3) { - res += cw3; - } - return res; -} diff --git a/xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h b/xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h deleted file mode 100644 index 3eb762fe6d187a71897c8713b2ba9ad869a91795..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_EDIFACTENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_EDIFACTENCODER_H_ - -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" - -class CBC_EdifactEncoder : public CBC_Encoder { - public: - CBC_EdifactEncoder(); - ~CBC_EdifactEncoder() override; - - // CBC_Encoder - int32_t getEncodingMode() override; - void Encode(CBC_EncoderContext& context, int32_t& e) override; - - private: - static void handleEOD(CBC_EncoderContext& context, - CFX_WideString buffer, - int32_t& e); - static void encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e); - static CFX_WideString encodeToCodewords(CFX_WideString sb, - int32_t startPos, - int32_t& e); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_EDIFACTENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_Encoder.h b/xfa/fxbarcode/datamatrix/BC_Encoder.h deleted file mode 100644 index 68a223fee1c63dcf2a1c00f180ff6b9501bf7d1a..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_Encoder.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_ENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_ENCODER_H_ - -#include "xfa/fxbarcode/utils.h" - -class CBC_EncoderContext; - -class CBC_Encoder { - public: - CBC_Encoder(); - virtual ~CBC_Encoder(); - - virtual int32_t getEncodingMode() = 0; - virtual void Encode(CBC_EncoderContext& context, int32_t& e) = 0; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_ENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_EncoderContext.cpp b/xfa/fxbarcode/datamatrix/BC_EncoderContext.cpp deleted file mode 100644 index b01b3120e337a71fc1edbe26c8140e560539ca0b..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_EncoderContext.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/BC_UtilCodingConvert.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -CBC_EncoderContext::CBC_EncoderContext(const CFX_WideString msg, - CFX_WideString ecLevel, - int32_t& e) { - CFX_ByteString dststr; - CBC_UtilCodingConvert::UnicodeToUTF8(msg, dststr); - CFX_WideString sb; - int32_t c = dststr.GetLength(); - for (int32_t i = 0; i < c; i++) { - FX_WCHAR ch = (FX_WCHAR)(dststr.GetAt(i) & 0xff); - if (ch == '?' && dststr.GetAt(i) != '?') { - e = BCExceptionCharactersOutsideISO88591Encoding; - } - sb += ch; - } - m_msg = sb; - m_shape = FORCE_NONE; - m_newEncoding = -1; - m_pos = 0; - m_symbolInfo = nullptr; - m_skipAtEnd = 0; - m_maxSize = nullptr; - m_minSize = nullptr; -} -CBC_EncoderContext::~CBC_EncoderContext() {} -void CBC_EncoderContext::setSymbolShape(SymbolShapeHint shape) { - m_shape = shape; -} -void CBC_EncoderContext::setSizeConstraints(CBC_Dimension* minSize, - CBC_Dimension* maxSize) { - m_maxSize = maxSize; - m_minSize = minSize; -} -CFX_WideString CBC_EncoderContext::getMessage() { - return m_msg; -} -void CBC_EncoderContext::setSkipAtEnd(int32_t count) { - m_skipAtEnd = count; -} -FX_WCHAR CBC_EncoderContext::getCurrentChar() { - return m_msg.GetAt(m_pos); -} -FX_WCHAR CBC_EncoderContext::getCurrent() { - return m_msg.GetAt(m_pos); -} -void CBC_EncoderContext::writeCodewords(CFX_WideString codewords) { - m_codewords += codewords; -} -void CBC_EncoderContext::writeCodeword(FX_WCHAR codeword) { - m_codewords += codeword; -} -int32_t CBC_EncoderContext::getCodewordCount() { - return m_codewords.GetLength(); -} -void CBC_EncoderContext::signalEncoderChange(int32_t encoding) { - m_newEncoding = encoding; -} -void CBC_EncoderContext::resetEncoderSignal() { - m_newEncoding = -1; -} -bool CBC_EncoderContext::hasMoreCharacters() { - return m_pos < getTotalMessageCharCount(); -} -int32_t CBC_EncoderContext::getRemainingCharacters() { - return getTotalMessageCharCount() - m_pos; -} -void CBC_EncoderContext::updateSymbolInfo(int32_t& e) { - updateSymbolInfo(getCodewordCount(), e); -} -void CBC_EncoderContext::updateSymbolInfo(int32_t len, int32_t& e) { - if (!m_symbolInfo || len > m_symbolInfo->m_dataCapacity) { - m_symbolInfo = - CBC_SymbolInfo::lookup(len, m_shape, m_minSize, m_maxSize, true, e); - if (e != BCExceptionNO) - return; - } -} -void CBC_EncoderContext::resetSymbolInfo() { - m_shape = FORCE_NONE; -} -int32_t CBC_EncoderContext::getTotalMessageCharCount() { - return m_msg.GetLength() - m_skipAtEnd; -} diff --git a/xfa/fxbarcode/datamatrix/BC_EncoderContext.h b/xfa/fxbarcode/datamatrix/BC_EncoderContext.h deleted file mode 100644 index 8d0ea5d7ed612bd5d6ae34a07699e242a10c86e2..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_EncoderContext.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_ENCODERCONTEXT_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_ENCODERCONTEXT_H_ - -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -class CBC_SymbolInfo; -class CBC_Dimension; - -class CBC_EncoderContext : public CBC_SymbolShapeHint { - public: - CBC_EncoderContext(const CFX_WideString msg, - CFX_WideString ecLevel, - int32_t& e); - ~CBC_EncoderContext() override; - - void setSymbolShape(SymbolShapeHint shape); - void setSizeConstraints(CBC_Dimension* minSize, CBC_Dimension* maxSize); - CFX_WideString getMessage(); - void setSkipAtEnd(int32_t count); - FX_WCHAR getCurrentChar(); - FX_WCHAR getCurrent(); - void writeCodewords(CFX_WideString codewords); - void writeCodeword(FX_WCHAR codeword); - int32_t getCodewordCount(); - void signalEncoderChange(int32_t encoding); - void resetEncoderSignal(); - bool hasMoreCharacters(); - int32_t getRemainingCharacters(); - void updateSymbolInfo(int32_t& e); - void updateSymbolInfo(int32_t len, int32_t& e); - void resetSymbolInfo(); - - public: - CFX_WideString m_msg; - CFX_WideString m_codewords; - int32_t m_pos; - int32_t m_newEncoding; - CBC_SymbolInfo* m_symbolInfo; - - private: - int32_t getTotalMessageCharCount(); - - private: - SymbolShapeHint m_shape; - CBC_Dimension* m_minSize; - CBC_Dimension* m_maxSize; - int32_t m_skipAtEnd; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_ENCODERCONTEXT_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h b/xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h deleted file mode 100644 index d3b9da80567ab75ea45ff3efa5ad0086ca7cb303..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_ErrorCorrection.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_ERRORCORRECTION_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_ERRORCORRECTION_H_ - -class CBC_SymbolInfo; - -class CBC_ErrorCorrection { - public: - CBC_ErrorCorrection(); - virtual ~CBC_ErrorCorrection(); - - static void Initialize(); - static void Finalize(); - static CFX_WideString encodeECC200(CFX_WideString codewords, - CBC_SymbolInfo* symbolInfo, - int32_t& e); - - private: - static int32_t MODULO_VALUE; - static int32_t LOG[256]; - static int32_t ALOG[256]; - - private: - static CFX_WideString createECCBlock(CFX_WideString codewords, - int32_t numECWords, - int32_t& e); - static CFX_WideString createECCBlock(CFX_WideString codewords, - int32_t start, - int32_t len, - int32_t numECWords, - int32_t& e); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_ERRORCORRECTION_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp b/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp deleted file mode 100644 index abd3584761b43f0a51b64954a30d24e5ef3174fa..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <limits> -#include <memory> -#include <vector> - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/BC_UtilCodingConvert.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_ASCIIEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Base256Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EdifactEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" -#include "xfa/fxbarcode/datamatrix/BC_TextEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_X12Encoder.h" -#include "xfa/fxbarcode/utils.h" - -FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_C40 = 230; -FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_BASE256 = 231; -FX_WCHAR CBC_HighLevelEncoder::UPPER_SHIFT = 235; -FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_ANSIX12 = 238; -FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_TEXT = 239; -FX_WCHAR CBC_HighLevelEncoder::LATCH_TO_EDIFACT = 240; -FX_WCHAR CBC_HighLevelEncoder::C40_UNLATCH = 254; -FX_WCHAR CBC_HighLevelEncoder::X12_UNLATCH = 254; -FX_WCHAR CBC_HighLevelEncoder::PAD = 129; -FX_WCHAR CBC_HighLevelEncoder::MACRO_05 = 236; -FX_WCHAR CBC_HighLevelEncoder::MACRO_06 = 237; -const wchar_t* CBC_HighLevelEncoder::MACRO_05_HEADER = L"[)>05"; -const wchar_t* CBC_HighLevelEncoder::MACRO_06_HEADER = L"[)>06"; -const wchar_t CBC_HighLevelEncoder::MACRO_TRAILER = 0x0004; - -CBC_HighLevelEncoder::CBC_HighLevelEncoder() {} -CBC_HighLevelEncoder::~CBC_HighLevelEncoder() {} - -CFX_ArrayTemplate<uint8_t>& CBC_HighLevelEncoder::getBytesForMessage( - CFX_WideString msg) { - CFX_ByteString bytestr; - CBC_UtilCodingConvert::UnicodeToUTF8(msg, bytestr); - for (int32_t i = 0; i < bytestr.GetLength(); i++) { - m_bytearray.Add(bytestr.GetAt(i)); - } - return m_bytearray; -} -CFX_WideString CBC_HighLevelEncoder::encodeHighLevel(CFX_WideString msg, - CFX_WideString ecLevel, - int32_t& e) { - return encodeHighLevel(msg, ecLevel, FORCE_NONE, nullptr, nullptr, e); -} -CFX_WideString CBC_HighLevelEncoder::encodeHighLevel(CFX_WideString msg, - CFX_WideString ecLevel, - SymbolShapeHint shape, - CBC_Dimension* minSize, - CBC_Dimension* maxSize, - int32_t& e) { - CBC_EncoderContext context(msg, ecLevel, e); - if (e != BCExceptionNO) - return CFX_WideString(); - context.setSymbolShape(shape); - context.setSizeConstraints(minSize, maxSize); - if ((msg.Mid(0, 6) == MACRO_05_HEADER) && - (msg.Mid(msg.GetLength() - 1, 1) == MACRO_TRAILER)) { - context.writeCodeword(MACRO_05); - context.setSkipAtEnd(2); - context.m_pos += 6; - } else if ((msg.Mid(0, 6) == MACRO_06_HEADER) && - (msg.Mid(msg.GetLength() - 1, 1) == MACRO_TRAILER)) { - context.writeCodeword(MACRO_06); - context.setSkipAtEnd(2); - context.m_pos += 6; - } - - std::vector<std::unique_ptr<CBC_Encoder>> encoders; - encoders.push_back(std::unique_ptr<CBC_Encoder>(new CBC_ASCIIEncoder())); - encoders.push_back(std::unique_ptr<CBC_Encoder>(new CBC_C40Encoder())); - encoders.push_back(std::unique_ptr<CBC_Encoder>(new CBC_TextEncoder())); - encoders.push_back(std::unique_ptr<CBC_Encoder>(new CBC_X12Encoder())); - encoders.push_back(std::unique_ptr<CBC_Encoder>(new CBC_EdifactEncoder())); - encoders.push_back(std::unique_ptr<CBC_Encoder>(new CBC_Base256Encoder())); - int32_t encodingMode = ASCII_ENCODATION; - while (context.hasMoreCharacters()) { - encoders[encodingMode]->Encode(context, e); - if (e != BCExceptionNO) - return L""; - - if (context.m_newEncoding >= 0) { - encodingMode = context.m_newEncoding; - context.resetEncoderSignal(); - } - } - int32_t len = context.m_codewords.GetLength(); - context.updateSymbolInfo(e); - if (e != BCExceptionNO) - return L""; - - int32_t capacity = context.m_symbolInfo->m_dataCapacity; - if (len < capacity) { - if (encodingMode != ASCII_ENCODATION && - encodingMode != BASE256_ENCODATION) { - context.writeCodeword(0x00fe); - } - } - CFX_WideString codewords = context.m_codewords; - if (codewords.GetLength() < capacity) { - codewords += PAD; - } - while (codewords.GetLength() < capacity) { - codewords += (randomize253State(PAD, codewords.GetLength() + 1)); - } - return codewords; -} -int32_t CBC_HighLevelEncoder::lookAheadTest(CFX_WideString msg, - int32_t startpos, - int32_t currentMode) { - if (startpos >= msg.GetLength()) { - return currentMode; - } - std::vector<FX_FLOAT> charCounts; - if (currentMode == ASCII_ENCODATION) { - charCounts.push_back(0); - charCounts.push_back(1); - charCounts.push_back(1); - charCounts.push_back(1); - charCounts.push_back(1); - charCounts.push_back(1.25f); - } else { - charCounts.push_back(1); - charCounts.push_back(2); - charCounts.push_back(2); - charCounts.push_back(2); - charCounts.push_back(2); - charCounts.push_back(2.25f); - charCounts[currentMode] = 0; - } - int32_t charsProcessed = 0; - while (true) { - if ((startpos + charsProcessed) == msg.GetLength()) { - int32_t min = std::numeric_limits<int32_t>::max(); - CFX_ArrayTemplate<uint8_t> mins; - mins.SetSize(6); - CFX_ArrayTemplate<int32_t> intCharCounts; - intCharCounts.SetSize(6); - min = findMinimums(charCounts, intCharCounts, min, mins); - int32_t minCount = getMinimumCount(mins); - if (intCharCounts[ASCII_ENCODATION] == min) { - return ASCII_ENCODATION; - } - if (minCount == 1 && mins[BASE256_ENCODATION] > 0) { - return BASE256_ENCODATION; - } - if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) { - return EDIFACT_ENCODATION; - } - if (minCount == 1 && mins[TEXT_ENCODATION] > 0) { - return TEXT_ENCODATION; - } - if (minCount == 1 && mins[X12_ENCODATION] > 0) { - return X12_ENCODATION; - } - return C40_ENCODATION; - } - FX_WCHAR c = msg.GetAt(startpos + charsProcessed); - charsProcessed++; - if (isDigit(c)) { - charCounts[ASCII_ENCODATION] += 0.5; - } else if (isExtendedASCII(c)) { - charCounts[ASCII_ENCODATION] = - (FX_FLOAT)ceil(charCounts[ASCII_ENCODATION]); - charCounts[ASCII_ENCODATION] += 2; - } else { - charCounts[ASCII_ENCODATION] = - (FX_FLOAT)ceil(charCounts[ASCII_ENCODATION]); - charCounts[ASCII_ENCODATION]++; - } - if (isNativeC40(c)) { - charCounts[C40_ENCODATION] += 2.0f / 3.0f; - } else if (isExtendedASCII(c)) { - charCounts[C40_ENCODATION] += 8.0f / 3.0f; - } else { - charCounts[C40_ENCODATION] += 4.0f / 3.0f; - } - if (isNativeText(c)) { - charCounts[TEXT_ENCODATION] += 2.0f / 3.0f; - } else if (isExtendedASCII(c)) { - charCounts[TEXT_ENCODATION] += 8.0f / 3.0f; - } else { - charCounts[TEXT_ENCODATION] += 4.0f / 3.0f; - } - if (isNativeX12(c)) { - charCounts[X12_ENCODATION] += 2.0f / 3.0f; - } else if (isExtendedASCII(c)) { - charCounts[X12_ENCODATION] += 13.0f / 3.0f; - } else { - charCounts[X12_ENCODATION] += 10.0f / 3.0f; - } - if (isNativeEDIFACT(c)) { - charCounts[EDIFACT_ENCODATION] += 3.0f / 4.0f; - } else if (isExtendedASCII(c)) { - charCounts[EDIFACT_ENCODATION] += 17.0f / 4.0f; - } else { - charCounts[EDIFACT_ENCODATION] += 13.0f / 4.0f; - } - if (isSpecialB256(c)) { - charCounts[BASE256_ENCODATION] += 4; - } else { - charCounts[BASE256_ENCODATION]++; - } - if (charsProcessed >= 4) { - CFX_ArrayTemplate<int32_t> intCharCounts; - intCharCounts.SetSize(6); - CFX_ArrayTemplate<uint8_t> mins; - mins.SetSize(6); - findMinimums(charCounts, intCharCounts, - std::numeric_limits<int32_t>::max(), mins); - int32_t minCount = getMinimumCount(mins); - if (intCharCounts[ASCII_ENCODATION] < intCharCounts[BASE256_ENCODATION] && - intCharCounts[ASCII_ENCODATION] < intCharCounts[C40_ENCODATION] && - intCharCounts[ASCII_ENCODATION] < intCharCounts[TEXT_ENCODATION] && - intCharCounts[ASCII_ENCODATION] < intCharCounts[X12_ENCODATION] && - intCharCounts[ASCII_ENCODATION] < intCharCounts[EDIFACT_ENCODATION]) { - return ASCII_ENCODATION; - } - if (intCharCounts[BASE256_ENCODATION] < intCharCounts[ASCII_ENCODATION] || - (mins[C40_ENCODATION] + mins[TEXT_ENCODATION] + mins[X12_ENCODATION] + - mins[EDIFACT_ENCODATION]) == 0) { - return BASE256_ENCODATION; - } - if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0) { - return EDIFACT_ENCODATION; - } - if (minCount == 1 && mins[TEXT_ENCODATION] > 0) { - return TEXT_ENCODATION; - } - if (minCount == 1 && mins[X12_ENCODATION] > 0) { - return X12_ENCODATION; - } - if (intCharCounts[C40_ENCODATION] + 1 < intCharCounts[ASCII_ENCODATION] && - intCharCounts[C40_ENCODATION] + 1 < - intCharCounts[BASE256_ENCODATION] && - intCharCounts[C40_ENCODATION] + 1 < - intCharCounts[EDIFACT_ENCODATION] && - intCharCounts[C40_ENCODATION] + 1 < intCharCounts[TEXT_ENCODATION]) { - if (intCharCounts[C40_ENCODATION] < intCharCounts[X12_ENCODATION]) { - return C40_ENCODATION; - } - if (intCharCounts[C40_ENCODATION] == intCharCounts[X12_ENCODATION]) { - int32_t p = startpos + charsProcessed + 1; - while (p < msg.GetLength()) { - FX_WCHAR tc = msg.GetAt(p); - if (isX12TermSep(tc)) { - return X12_ENCODATION; - } - if (!isNativeX12(tc)) { - break; - } - p++; - } - return C40_ENCODATION; - } - } - } - } -} -bool CBC_HighLevelEncoder::isDigit(FX_WCHAR ch) { - return ch >= '0' && ch <= '9'; -} -bool CBC_HighLevelEncoder::isExtendedASCII(FX_WCHAR ch) { - return ch >= 128 && ch <= 255; -} -int32_t CBC_HighLevelEncoder::determineConsecutiveDigitCount(CFX_WideString msg, - int32_t startpos) { - int32_t count = 0; - int32_t len = msg.GetLength(); - int32_t idx = startpos; - if (idx < len) { - FX_WCHAR ch = msg.GetAt(idx); - while (isDigit(ch) && idx < len) { - count++; - idx++; - if (idx < len) { - ch = msg.GetAt(idx); - } - } - } - return count; -} -void CBC_HighLevelEncoder::illegalCharacter(FX_WCHAR c, int32_t& e) { - e = BCExceptionIllegalArgument; -} -FX_WCHAR CBC_HighLevelEncoder::randomize253State(FX_WCHAR ch, - int32_t codewordPosition) { - int32_t pseudoRandom = ((149 * codewordPosition) % 253) + 1; - int32_t tempVariable = ch + pseudoRandom; - return tempVariable <= 254 ? (FX_WCHAR)tempVariable - : (FX_WCHAR)(tempVariable - 254); -} -int32_t CBC_HighLevelEncoder::findMinimums( - std::vector<FX_FLOAT>& charCounts, - CFX_ArrayTemplate<int32_t>& intCharCounts, - int32_t min, - CFX_ArrayTemplate<uint8_t>& mins) { - for (int32_t l = 0; l < mins.GetSize(); l++) { - mins[l] = (uint8_t)0; - } - for (int32_t i = 0; i < 6; i++) { - intCharCounts[i] = (int32_t)ceil(charCounts[i]); - int32_t current = intCharCounts[i]; - if (min > current) { - min = current; - for (int32_t j = 0; j < mins.GetSize(); j++) { - mins[j] = (uint8_t)0; - } - } - if (min == current) { - mins[i]++; - } - } - return min; -} -int32_t CBC_HighLevelEncoder::getMinimumCount( - CFX_ArrayTemplate<uint8_t>& mins) { - int32_t minCount = 0; - for (int32_t i = 0; i < 6; i++) { - minCount += mins[i]; - } - return minCount; -} -bool CBC_HighLevelEncoder::isNativeC40(FX_WCHAR ch) { - return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'); -} -bool CBC_HighLevelEncoder::isNativeText(FX_WCHAR ch) { - return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z'); -} -bool CBC_HighLevelEncoder::isNativeX12(FX_WCHAR ch) { - return isX12TermSep(ch) || (ch == ' ') || (ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'Z'); -} -bool CBC_HighLevelEncoder::isX12TermSep(FX_WCHAR ch) { - return (ch == '\r') || (ch == '*') || (ch == '>'); -} -bool CBC_HighLevelEncoder::isNativeEDIFACT(FX_WCHAR ch) { - return ch >= ' ' && ch <= '^'; -} -bool CBC_HighLevelEncoder::isSpecialB256(FX_WCHAR ch) { - return false; -} diff --git a/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h b/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h deleted file mode 100644 index 5d72f1074e3753159b8258a155815ebcddc5e600..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_HIGHLEVELENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_HIGHLEVELENCODER_H_ - -#include <vector> - -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -#define ASCII_ENCODATION 0 -#define C40_ENCODATION 1 -#define TEXT_ENCODATION 2 -#define X12_ENCODATION 3 -#define EDIFACT_ENCODATION 4 -#define BASE256_ENCODATION 5 - -class CBC_HighLevelEncoder : public CBC_SymbolShapeHint { - public: - CBC_HighLevelEncoder(); - ~CBC_HighLevelEncoder() override; - - CFX_ArrayTemplate<uint8_t>& getBytesForMessage(CFX_WideString msg); - static CFX_WideString encodeHighLevel(CFX_WideString msg, - CFX_WideString ecLevel, - int32_t& e); - static CFX_WideString encodeHighLevel(CFX_WideString msg, - CFX_WideString ecLevel, - SymbolShapeHint shape, - CBC_Dimension* minSize, - CBC_Dimension* maxSize, - int32_t& e); - static int32_t lookAheadTest(CFX_WideString msg, - int32_t startpos, - int32_t currentMode); - static bool isDigit(FX_WCHAR ch); - static bool isExtendedASCII(FX_WCHAR ch); - static int32_t determineConsecutiveDigitCount(CFX_WideString msg, - int32_t startpos); - static void illegalCharacter(FX_WCHAR c, int32_t& e); - - public: - static FX_WCHAR LATCH_TO_C40; - static FX_WCHAR LATCH_TO_BASE256; - static FX_WCHAR UPPER_SHIFT; - static FX_WCHAR LATCH_TO_ANSIX12; - static FX_WCHAR LATCH_TO_TEXT; - static FX_WCHAR LATCH_TO_EDIFACT; - static FX_WCHAR C40_UNLATCH; - static FX_WCHAR X12_UNLATCH; - - private: - static FX_WCHAR PAD; - static FX_WCHAR MACRO_05; - static FX_WCHAR MACRO_06; - static const wchar_t* MACRO_05_HEADER; - static const wchar_t* MACRO_06_HEADER; - static const wchar_t MACRO_TRAILER; - CFX_ArrayTemplate<uint8_t> m_bytearray; - - private: - static FX_WCHAR randomize253State(FX_WCHAR ch, int32_t codewordPosition); - static int32_t findMinimums(std::vector<FX_FLOAT>& charCounts, - CFX_ArrayTemplate<int32_t>& intCharCounts, - int32_t min, - CFX_ArrayTemplate<uint8_t>& mins); - static int32_t getMinimumCount(CFX_ArrayTemplate<uint8_t>& mins); - static bool isNativeC40(FX_WCHAR ch); - static bool isNativeText(FX_WCHAR ch); - static bool isNativeX12(FX_WCHAR ch); - static bool isX12TermSep(FX_WCHAR ch); - static bool isNativeEDIFACT(FX_WCHAR ch); - static bool isSpecialB256(FX_WCHAR ch); -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_HIGHLEVELENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_SymbolInfo.cpp b/xfa/fxbarcode/datamatrix/BC_SymbolInfo.cpp deleted file mode 100644 index ae74b8b2d43e1395a3b49f75623c1e13eed803c5..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_SymbolInfo.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006 Jeremias Maerki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_DataMatrixSymbolInfo144.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -namespace { - -const size_t kSymbolsCount = 30; - -CBC_SymbolInfo* g_symbols[kSymbolsCount] = { - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; - -} // namespace - -void CBC_SymbolInfo::Initialize() { - g_symbols[0] = new CBC_SymbolInfo(false, 3, 5, 8, 8, 1); - g_symbols[1] = new CBC_SymbolInfo(false, 5, 7, 10, 10, 1); - g_symbols[2] = new CBC_SymbolInfo(true, 5, 7, 16, 6, 1); - g_symbols[3] = new CBC_SymbolInfo(false, 8, 10, 12, 12, 1); - g_symbols[4] = new CBC_SymbolInfo(true, 10, 11, 14, 6, 2); - g_symbols[5] = new CBC_SymbolInfo(false, 12, 12, 14, 14, 1); - g_symbols[6] = new CBC_SymbolInfo(true, 16, 14, 24, 10, 1); - g_symbols[7] = new CBC_SymbolInfo(false, 18, 14, 16, 16, 1); - g_symbols[8] = new CBC_SymbolInfo(false, 22, 18, 18, 18, 1); - g_symbols[9] = new CBC_SymbolInfo(true, 22, 18, 16, 10, 2); - g_symbols[10] = new CBC_SymbolInfo(false, 30, 20, 20, 20, 1); - g_symbols[11] = new CBC_SymbolInfo(true, 32, 24, 16, 14, 2); - g_symbols[12] = new CBC_SymbolInfo(false, 36, 24, 22, 22, 1); - g_symbols[13] = new CBC_SymbolInfo(false, 44, 28, 24, 24, 1); - g_symbols[14] = new CBC_SymbolInfo(true, 49, 28, 22, 14, 2); - g_symbols[15] = new CBC_SymbolInfo(false, 62, 36, 14, 14, 4); - g_symbols[16] = new CBC_SymbolInfo(false, 86, 42, 16, 16, 4); - g_symbols[17] = new CBC_SymbolInfo(false, 114, 48, 18, 18, 4); - g_symbols[18] = new CBC_SymbolInfo(false, 144, 56, 20, 20, 4); - g_symbols[19] = new CBC_SymbolInfo(false, 174, 68, 22, 22, 4); - g_symbols[20] = new CBC_SymbolInfo(false, 204, 84, 24, 24, 4, 102, 42); - g_symbols[21] = new CBC_SymbolInfo(false, 280, 112, 14, 14, 16, 140, 56); - g_symbols[22] = new CBC_SymbolInfo(false, 368, 144, 16, 16, 16, 92, 36); - g_symbols[23] = new CBC_SymbolInfo(false, 456, 192, 18, 18, 16, 114, 48); - g_symbols[24] = new CBC_SymbolInfo(false, 576, 224, 20, 20, 16, 144, 56); - g_symbols[25] = new CBC_SymbolInfo(false, 696, 272, 22, 22, 16, 174, 68); - g_symbols[26] = new CBC_SymbolInfo(false, 816, 336, 24, 24, 16, 136, 56); - g_symbols[27] = new CBC_SymbolInfo(false, 1050, 408, 18, 18, 36, 175, 68); - g_symbols[28] = new CBC_SymbolInfo(false, 1304, 496, 20, 20, 36, 163, 62); - g_symbols[29] = new CBC_DataMatrixSymbolInfo144(); -} - -void CBC_SymbolInfo::Finalize() { - for (size_t i = 0; i < kSymbolsCount; i++) { - delete g_symbols[i]; - g_symbols[i] = nullptr; - } -} - -CBC_SymbolInfo::CBC_SymbolInfo(bool rectangular, - int32_t dataCapacity, - int32_t errorCodewords, - int32_t matrixWidth, - int32_t matrixHeight, - int32_t dataRegions) { - m_rectangular = rectangular; - m_dataCapacity = dataCapacity; - m_errorCodewords = errorCodewords; - m_matrixWidth = matrixWidth; - m_matrixHeight = matrixHeight; - m_dataRegions = dataRegions; - m_rsBlockData = dataCapacity; - m_rsBlockError = errorCodewords; -} -CBC_SymbolInfo::CBC_SymbolInfo(bool rectangular, - int32_t dataCapacity, - int32_t errorCodewords, - int32_t matrixWidth, - int32_t matrixHeight, - int32_t dataRegions, - int32_t rsBlockData, - int32_t rsBlockError) { - m_rectangular = rectangular; - m_dataCapacity = dataCapacity; - m_errorCodewords = errorCodewords; - m_matrixWidth = matrixWidth; - m_matrixHeight = matrixHeight; - m_dataRegions = dataRegions; - m_rsBlockData = rsBlockData; - m_rsBlockError = rsBlockError; -} -CBC_SymbolInfo::~CBC_SymbolInfo() {} - -CBC_SymbolInfo* CBC_SymbolInfo::lookup(int32_t dataCodewords, int32_t& e) { - return lookup(dataCodewords, FORCE_NONE, true, e); -} -CBC_SymbolInfo* CBC_SymbolInfo::lookup(int32_t dataCodewords, - SymbolShapeHint shape, - int32_t& e) { - return lookup(dataCodewords, shape, true, e); -} -CBC_SymbolInfo* CBC_SymbolInfo::lookup(int32_t dataCodewords, - bool allowRectangular, - bool fail, - int32_t& e) { - SymbolShapeHint shape = allowRectangular ? FORCE_NONE : FORCE_SQUARE; - return lookup(dataCodewords, shape, fail, e); -} -CBC_SymbolInfo* CBC_SymbolInfo::lookup(int32_t dataCodewords, - SymbolShapeHint shape, - bool fail, - int32_t& e) { - return lookup(dataCodewords, shape, nullptr, nullptr, fail, e); -} -CBC_SymbolInfo* CBC_SymbolInfo::lookup(int32_t dataCodewords, - SymbolShapeHint shape, - CBC_Dimension* minSize, - CBC_Dimension* maxSize, - bool fail, - int32_t& e) { - for (size_t i = 0; i < kSymbolsCount; i++) { - CBC_SymbolInfo* symbol = g_symbols[i]; - if (shape == FORCE_SQUARE && symbol->m_rectangular) { - continue; - } - if (shape == FORCE_RECTANGLE && !symbol->m_rectangular) { - continue; - } - if (minSize && (symbol->getSymbolWidth(e) < minSize->getWidth() || - symbol->getSymbolHeight(e) < minSize->getHeight())) { - if (e != BCExceptionNO) - return nullptr; - continue; - } - if (maxSize && (symbol->getSymbolWidth(e) > maxSize->getWidth() || - symbol->getSymbolHeight(e) > maxSize->getHeight())) { - if (e != BCExceptionNO) - return nullptr; - continue; - } - if (dataCodewords <= symbol->m_dataCapacity) { - return symbol; - } - } - if (fail) - e = BCExceptionIllegalDataCodewords; - return nullptr; -} - -int32_t CBC_SymbolInfo::getHorizontalDataRegions(int32_t& e) { - switch (m_dataRegions) { - case 1: - return 1; - case 2: - return 2; - case 4: - return 2; - case 16: - return 4; - case 36: - return 6; - default: - e = BCExceptionCannotHandleThisNumberOfDataRegions; - return 0; - } -} -int32_t CBC_SymbolInfo::getVerticalDataRegions(int32_t& e) { - switch (m_dataRegions) { - case 1: - return 1; - case 2: - return 1; - case 4: - return 2; - case 16: - return 4; - case 36: - return 6; - default: - e = BCExceptionCannotHandleThisNumberOfDataRegions; - return 0; - } -} -int32_t CBC_SymbolInfo::getSymbolDataWidth(int32_t& e) { - return getHorizontalDataRegions(e) * m_matrixWidth; -} -int32_t CBC_SymbolInfo::getSymbolDataHeight(int32_t& e) { - return getVerticalDataRegions(e) * m_matrixHeight; -} -int32_t CBC_SymbolInfo::getSymbolWidth(int32_t& e) { - return getSymbolDataWidth(e) + (getHorizontalDataRegions(e) * 2); -} -int32_t CBC_SymbolInfo::getSymbolHeight(int32_t& e) { - return getSymbolDataHeight(e) + (getVerticalDataRegions(e) * 2); -} -int32_t CBC_SymbolInfo::getCodewordCount() { - return m_dataCapacity + m_errorCodewords; -} -int32_t CBC_SymbolInfo::getInterleavedBlockCount() { - return m_dataCapacity / m_rsBlockData; -} -int32_t CBC_SymbolInfo::getDataLengthForInterleavedBlock(int32_t index) { - return m_rsBlockData; -} -int32_t CBC_SymbolInfo::getErrorLengthForInterleavedBlock(int32_t index) { - return m_rsBlockError; -} diff --git a/xfa/fxbarcode/datamatrix/BC_SymbolInfo.h b/xfa/fxbarcode/datamatrix/BC_SymbolInfo.h deleted file mode 100644 index d2730025db6a3a638439b42d7db14e170e7d8120..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_SymbolInfo.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_SYMBOLINFO_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_SYMBOLINFO_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -class CBC_Dimension; - -class CBC_SymbolInfo : public CBC_SymbolShapeHint { - public: - CBC_SymbolInfo(bool rectangular, - int32_t dataCapacity, - int32_t errorCodewords, - int32_t matrixWidth, - int32_t matrixHeight, - int32_t dataRegions); - ~CBC_SymbolInfo() override; - - static void Initialize(); - static void Finalize(); - static void overrideSymbolSet(CBC_SymbolInfo* override); - static CBC_SymbolInfo* lookup(int32_t dataCodewords, int32_t& e); - static CBC_SymbolInfo* lookup(int32_t dataCodewords, - SymbolShapeHint shape, - int32_t& e); - static CBC_SymbolInfo* lookup(int32_t dataCodewords, - bool allowRectangular, - bool fail, - int32_t& e); - static CBC_SymbolInfo* lookup(int32_t dataCodewords, - SymbolShapeHint shape, - bool fail, - int32_t& e); - static CBC_SymbolInfo* lookup(int32_t dataCodewords, - SymbolShapeHint shape, - CBC_Dimension* minSize, - CBC_Dimension* maxSize, - bool fail, - int32_t& e); - int32_t getHorizontalDataRegions(int32_t& e); - int32_t getVerticalDataRegions(int32_t& e); - int32_t getSymbolDataWidth(int32_t& e); - int32_t getSymbolDataHeight(int32_t& e); - int32_t getSymbolWidth(int32_t& e); - int32_t getSymbolHeight(int32_t& e); - int32_t getCodewordCount(); - int32_t getInterleavedBlockCount(); - int32_t getDataLengthForInterleavedBlock(int32_t index); - int32_t getErrorLengthForInterleavedBlock(int32_t index); - - int32_t m_dataCapacity; - int32_t m_errorCodewords; - int32_t m_matrixWidth; - int32_t m_matrixHeight; - int32_t m_rsBlockData; - int32_t m_rsBlockError; - - private: - CBC_SymbolInfo(bool rectangular, - int32_t dataCapacity, - int32_t errorCodewords, - int32_t matrixWidth, - int32_t matrixHeight, - int32_t dataRegions, - int32_t rsBlockData, - int32_t rsBlockError); - - bool m_rectangular; - int32_t m_dataRegions; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_SYMBOLINFO_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.cpp b/xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.cpp deleted file mode 100644 index 8f91dd837aae34f4794ab9858b5246af55d34362..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" - -CBC_SymbolShapeHint::CBC_SymbolShapeHint() {} -CBC_SymbolShapeHint::~CBC_SymbolShapeHint() {} diff --git a/xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h b/xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h deleted file mode 100644 index 7cd4c86931bf3ea7f3d7677b710ec8a3f6e15fd5..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_SYMBOLSHAPEHINT_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_SYMBOLSHAPEHINT_H_ - -class CBC_SymbolShapeHint { - public: - CBC_SymbolShapeHint(); - virtual ~CBC_SymbolShapeHint(); - - enum SymbolShapeHint { - FORCE_NONE, - FORCE_SQUARE, - FORCE_RECTANGLE, - }; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_SYMBOLSHAPEHINT_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_TextEncoder.cpp b/xfa/fxbarcode/datamatrix/BC_TextEncoder.cpp deleted file mode 100644 index e3eb4a8c4edc1f60268a89fea714f275f26cb213..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_TextEncoder.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" -#include "xfa/fxbarcode/datamatrix/BC_TextEncoder.h" - -CBC_TextEncoder::CBC_TextEncoder() {} -CBC_TextEncoder::~CBC_TextEncoder() {} -int32_t CBC_TextEncoder::getEncodingMode() { - return TEXT_ENCODATION; -} -int32_t CBC_TextEncoder::encodeChar(FX_WCHAR c, - CFX_WideString& sb, - int32_t& e) { - if (c == ' ') { - sb += (FX_WCHAR)'\3'; - return 1; - } - if (c >= '0' && c <= '9') { - sb += (FX_WCHAR)(c - 48 + 4); - return 1; - } - if (c >= 'a' && c <= 'z') { - sb += (FX_WCHAR)(c - 97 + 14); - return 1; - } - if (c <= 0x1f) { - sb += (FX_WCHAR)'\0'; - sb += c; - return 2; - } - if (c >= '!' && c <= '/') { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)(c - 33); - return 2; - } - if (c >= ':' && c <= '@') { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)(c - 58 + 15); - return 2; - } - if (c >= '[' && c <= '_') { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)(c - 91 + 22); - return 2; - } - if (c == 0x0060) { - sb += (FX_WCHAR)'\2'; - sb += (FX_WCHAR)(c - 96); - return 2; - } - if (c >= 'A' && c <= 'Z') { - sb += (FX_WCHAR)'\2'; - sb += (FX_WCHAR)(c - 65 + 1); - return 2; - } - if (c >= '{' && c <= 0x007f) { - sb += (FX_WCHAR)'\2'; - sb += (FX_WCHAR)(c - 123 + 27); - return 2; - } - if (c >= 0x0080) { - sb += (FX_WCHAR)'\1'; - sb += (FX_WCHAR)0x001e; - int32_t len = 2; - len += encodeChar((FX_WCHAR)(c - 128), sb, e); - if (e != BCExceptionNO) - return -1; - return len; - } - CBC_HighLevelEncoder::illegalCharacter(c, e); - return -1; -} diff --git a/xfa/fxbarcode/datamatrix/BC_TextEncoder.h b/xfa/fxbarcode/datamatrix/BC_TextEncoder.h deleted file mode 100644 index e6013b9508fd29bea6120909b53b265aa33d4111..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_TextEncoder.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_TEXTENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_TEXTENCODER_H_ - -class CBC_TextEncoder; - -class CBC_TextEncoder : public CBC_C40Encoder { - public: - CBC_TextEncoder(); - ~CBC_TextEncoder() override; - - // CBC_C40Encoder - int32_t getEncodingMode() override; - int32_t encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e) override; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_TEXTENCODER_H_ diff --git a/xfa/fxbarcode/datamatrix/BC_X12Encoder.cpp b/xfa/fxbarcode/datamatrix/BC_X12Encoder.cpp deleted file mode 100644 index d77af9318a995ed21493986ac050643049e94f5e..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_X12Encoder.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Dimension.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/datamatrix/BC_C40Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_Encoder.h" -#include "xfa/fxbarcode/datamatrix/BC_EncoderContext.h" -#include "xfa/fxbarcode/datamatrix/BC_HighLevelEncoder.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolInfo.h" -#include "xfa/fxbarcode/datamatrix/BC_SymbolShapeHint.h" -#include "xfa/fxbarcode/datamatrix/BC_X12Encoder.h" - -CBC_X12Encoder::CBC_X12Encoder() {} -CBC_X12Encoder::~CBC_X12Encoder() {} -int32_t CBC_X12Encoder::getEncodingMode() { - return X12_ENCODATION; -} -void CBC_X12Encoder::Encode(CBC_EncoderContext& context, int32_t& e) { - CFX_WideString buffer; - while (context.hasMoreCharacters()) { - FX_WCHAR c = context.getCurrentChar(); - context.m_pos++; - encodeChar(c, buffer, e); - if (e != BCExceptionNO) { - return; - } - int32_t count = buffer.GetLength(); - if ((count % 3) == 0) { - writeNextTriplet(context, buffer); - int32_t newMode = CBC_HighLevelEncoder::lookAheadTest( - context.m_msg, context.m_pos, getEncodingMode()); - if (newMode != getEncodingMode()) { - context.signalEncoderChange(newMode); - break; - } - } - } - handleEOD(context, buffer, e); -} -void CBC_X12Encoder::handleEOD(CBC_EncoderContext& context, - CFX_WideString& buffer, - int32_t& e) { - context.updateSymbolInfo(e); - if (e != BCExceptionNO) { - return; - } - int32_t available = - context.m_symbolInfo->m_dataCapacity - context.getCodewordCount(); - int32_t count = buffer.GetLength(); - if (count == 2) { - context.writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH); - context.m_pos -= 2; - context.signalEncoderChange(ASCII_ENCODATION); - } else if (count == 1) { - context.m_pos--; - if (available > 1) { - context.writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH); - } - context.signalEncoderChange(ASCII_ENCODATION); - } -} -int32_t CBC_X12Encoder::encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e) { - if (c == '\r') { - sb += (FX_WCHAR)'\0'; - } else if (c == '*') { - sb += (FX_WCHAR)'\1'; - } else if (c == '>') { - sb += (FX_WCHAR)'\2'; - } else if (c == ' ') { - sb += (FX_WCHAR)'\3'; - } else if (c >= '0' && c <= '9') { - sb += (FX_WCHAR)(c - 48 + 4); - } else if (c >= 'A' && c <= 'Z') { - sb += (FX_WCHAR)(c - 65 + 14); - } else { - CBC_HighLevelEncoder::illegalCharacter(c, e); - if (e != BCExceptionNO) - return -1; - } - return 1; -} diff --git a/xfa/fxbarcode/datamatrix/BC_X12Encoder.h b/xfa/fxbarcode/datamatrix/BC_X12Encoder.h deleted file mode 100644 index 52239ce529b13209933b74ec0f578eb1b6b2dad4..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/datamatrix/BC_X12Encoder.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_DATAMATRIX_BC_X12ENCODER_H_ -#define XFA_FXBARCODE_DATAMATRIX_BC_X12ENCODER_H_ - -class CBC_C40Encoder; -class CBC_X12Encoder; -class CBC_X12Encoder : public CBC_C40Encoder { - public: - CBC_X12Encoder(); - ~CBC_X12Encoder() override; - - // CBC_C40Encoder - int32_t getEncodingMode() override; - void Encode(CBC_EncoderContext& context, int32_t& e) override; - void handleEOD(CBC_EncoderContext& context, - CFX_WideString& buffer, - int32_t& e) override; - int32_t encodeChar(FX_WCHAR c, CFX_WideString& sb, int32_t& e) override; -}; - -#endif // XFA_FXBARCODE_DATAMATRIX_BC_X12ENCODER_H_ diff --git a/xfa/fxbarcode/oned/BC_OneDimWriter.cpp b/xfa/fxbarcode/oned/BC_OneDimWriter.cpp deleted file mode 100644 index bc0d61fd25091545a86bef889cb3f47733a70e6a..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OneDimWriter.cpp +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -#include <algorithm> -#include <memory> - -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/cfx_unicodeencodingex.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" - -CBC_OneDimWriter::CBC_OneDimWriter() { - m_locTextLoc = BC_TEXT_LOC_BELOWEMBED; - m_bPrintChecksum = true; - m_iDataLenth = 0; - m_bCalcChecksum = false; - m_pFont = nullptr; - m_fFontSize = 10; - m_iFontStyle = 0; - m_fontColor = 0xff000000; - m_iContentLen = 0; - m_bLeftPadding = false; - m_bRightPadding = false; -} - -CBC_OneDimWriter::~CBC_OneDimWriter() {} - -void CBC_OneDimWriter::SetPrintChecksum(bool checksum) { - m_bPrintChecksum = checksum; -} - -void CBC_OneDimWriter::SetDataLength(int32_t length) { - m_iDataLenth = length; -} - -void CBC_OneDimWriter::SetCalcChecksum(bool state) { - m_bCalcChecksum = state; -} - -bool CBC_OneDimWriter::SetFont(CFX_Font* cFont) { - if (!cFont) - return false; - - m_pFont = cFont; - return true; -} - -void CBC_OneDimWriter::SetFontSize(FX_FLOAT size) { - m_fFontSize = size; -} - -void CBC_OneDimWriter::SetFontStyle(int32_t style) { - m_iFontStyle = style; -} - -void CBC_OneDimWriter::SetFontColor(FX_ARGB color) { - m_fontColor = color; -} - -FX_WCHAR CBC_OneDimWriter::Upper(FX_WCHAR ch) { - if (ch >= 'a' && ch <= 'z') { - ch = ch - ('a' - 'A'); - } - return ch; -} - -uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - uint8_t* ret = nullptr; - outHeight = 1; - if (m_Width >= 20) { - ret = Encode(contents, outWidth, e); - } else { - ret = Encode(contents, outWidth, e); - } - if (e != BCExceptionNO) - return nullptr; - return ret; -} - -uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} - -uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) { - return nullptr; -} - -int32_t CBC_OneDimWriter::AppendPattern(uint8_t* target, - int32_t pos, - const int32_t* pattern, - int32_t patternLength, - int32_t startColor, - int32_t& e) { - if (startColor != 0 && startColor != 1) { - e = BCExceptionValueMustBeEither0or1; - return 0; - } - uint8_t color = (uint8_t)startColor; - int32_t numAdded = 0; - for (int32_t i = 0; i < patternLength; i++) { - for (int32_t j = 0; j < pattern[i]; j++) { - target[pos] = color; - pos += 1; - numAdded += 1; - } - color ^= 1; - } - return numAdded; -} - -void CBC_OneDimWriter::CalcTextInfo(const CFX_ByteString& text, - FXTEXT_CHARPOS* charPos, - CFX_Font* cFont, - FX_FLOAT geWidth, - int32_t fontSize, - FX_FLOAT& charsLen) { - std::unique_ptr<CFX_UnicodeEncodingEx> encoding( - FX_CreateFontEncodingEx(cFont)); - - int32_t length = text.GetLength(); - uint32_t* pCharCode = FX_Alloc(uint32_t, text.GetLength()); - FX_FLOAT charWidth = 0; - for (int32_t j = 0; j < text.GetLength(); j++) { - pCharCode[j] = encoding->CharCodeFromUnicode(text[j]); - int32_t glyp_code = encoding->GlyphFromCharCode(pCharCode[j]); - int32_t glyp_value = cFont->GetGlyphWidth(glyp_code); - FX_FLOAT temp = (FX_FLOAT)((glyp_value)*fontSize / 1000.0); - charWidth += temp; - } - charsLen = charWidth; - FX_FLOAT leftPositon = (FX_FLOAT)(geWidth - charsLen) / 2.0f; - if (leftPositon < 0 && geWidth == 0) { - leftPositon = 0; - } - FX_FLOAT penX = 0.0; - FX_FLOAT penY = - (FX_FLOAT)FXSYS_abs(cFont->GetDescent()) * (FX_FLOAT)fontSize / 1000.0f; - FX_FLOAT left = leftPositon; - FX_FLOAT top = 0.0; - charPos[0].m_Origin = CFX_PointF(penX + left, penY + top); - charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[0]); - charPos[0].m_FontCharWidth = cFont->GetGlyphWidth(charPos[0].m_GlyphIndex); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - charPos[0].m_ExtGID = charPos[0].m_GlyphIndex; -#endif - penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * (FX_FLOAT)fontSize / 1000.0f; - for (int32_t i = 1; i < length; i++) { - charPos[i].m_Origin = CFX_PointF(penX + left, penY + top); - charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[i]); - charPos[i].m_FontCharWidth = cFont->GetGlyphWidth(charPos[i].m_GlyphIndex); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - charPos[i].m_ExtGID = charPos[i].m_GlyphIndex; -#endif - penX += - (FX_FLOAT)(charPos[i].m_FontCharWidth) * (FX_FLOAT)fontSize / 1000.0f; - } - FX_Free(pCharCode); -} - -void CBC_OneDimWriter::ShowDeviceChars(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - const CFX_ByteString str, - FX_FLOAT geWidth, - FXTEXT_CHARPOS* pCharPos, - FX_FLOAT locX, - FX_FLOAT locY, - int32_t barWidth) { - int32_t iFontSize = (int32_t)fabs(m_fFontSize); - int32_t iTextHeight = iFontSize + 1; - CFX_FloatRect rect((FX_FLOAT)locX, (FX_FLOAT)locY, (FX_FLOAT)(locX + geWidth), - (FX_FLOAT)(locY + iTextHeight)); - if (geWidth != m_Width) { - rect.right -= 1; - } - matrix->TransformRect(rect); - FX_RECT re = rect.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, (FX_FLOAT)locX, - (FX_FLOAT)(locY + iFontSize)); - if (matrix) { - affine_matrix.Concat(*matrix); - } - device->DrawNormalText(str.GetLength(), pCharPos, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); -} - -void CBC_OneDimWriter::ShowBitmapChars(CFX_DIBitmap* pOutBitmap, - const CFX_ByteString str, - FX_FLOAT geWidth, - FXTEXT_CHARPOS* pCharPos, - FX_FLOAT locX, - FX_FLOAT locY, - int32_t barWidth) { - int32_t iFontSize = (int32_t)fabs(m_fFontSize); - int32_t iTextHeight = iFontSize + 1; - CFX_FxgeDevice ge; - ge.Create((int)geWidth, iTextHeight, m_colorSpace, nullptr); - FX_RECT geRect(0, 0, (int)geWidth, iTextHeight); - ge.FillRect(&geRect, m_backgroundColor); - CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0, - static_cast<FX_FLOAT>(iFontSize)); - ge.DrawNormalText(str.GetLength(), pCharPos, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - CFX_FxgeDevice geBitmap; - geBitmap.Attach(pOutBitmap, false, nullptr, false); - geBitmap.SetDIBits(ge.GetBitmap(), (int)locX, (int)locY); -} - -void CBC_OneDimWriter::ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) { - if (!device && !pOutBitmap) { - e = BCExceptionIllegalArgument; - return; - } - if (!m_pFont) { - e = BCExceptionNullPointer; - return; - } - CFX_ByteString str = FX_UTF8Encode(contents); - int32_t iLen = str.GetLength(); - FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLen); - FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLen); - FX_FLOAT charsLen = 0; - FX_FLOAT geWidth = 0; - if (m_locTextLoc == BC_TEXT_LOC_ABOVEEMBED || - m_locTextLoc == BC_TEXT_LOC_BELOWEMBED) { - geWidth = 0; - } else if (m_locTextLoc == BC_TEXT_LOC_ABOVE || - m_locTextLoc == BC_TEXT_LOC_BELOW) { - geWidth = (FX_FLOAT)barWidth; - } - int32_t iFontSize = (int32_t)fabs(m_fFontSize); - int32_t iTextHeight = iFontSize + 1; - CalcTextInfo(str, pCharPos, m_pFont, geWidth, iFontSize, charsLen); - if (charsLen < 1) { - return; - } - int32_t locX = 0; - int32_t locY = 0; - switch (m_locTextLoc) { - case BC_TEXT_LOC_ABOVEEMBED: - locX = (int32_t)(barWidth - charsLen) / 2; - locY = 0; - geWidth = charsLen; - break; - case BC_TEXT_LOC_ABOVE: - locX = 0; - locY = 0; - geWidth = (FX_FLOAT)barWidth; - break; - case BC_TEXT_LOC_BELOWEMBED: - locX = (int32_t)(barWidth - charsLen) / 2; - locY = m_Height - iTextHeight; - geWidth = charsLen; - break; - case BC_TEXT_LOC_BELOW: - default: - locX = 0; - locY = m_Height - iTextHeight; - geWidth = (FX_FLOAT)barWidth; - break; - } - if (device) { - ShowDeviceChars(device, matrix, str, geWidth, pCharPos, (FX_FLOAT)locX, - (FX_FLOAT)locY, barWidth); - } else { - ShowBitmapChars(pOutBitmap, str, geWidth, pCharPos, (FX_FLOAT)locX, - (FX_FLOAT)locY, barWidth); - } - FX_Free(pCharPos); -} - -void CBC_OneDimWriter::RenderBitmapResult(CFX_DIBitmap*& pOutBitmap, - const CFX_WideStringC& contents, - int32_t& e) { - if (!m_output) - if (e != BCExceptionNO) - return; - - pOutBitmap = CreateDIBitmap(m_output->GetWidth(), m_output->GetHeight()); - pOutBitmap->Clear(m_backgroundColor); - if (!pOutBitmap) { - e = BCExceptionFailToCreateBitmap; - return; - } - for (int32_t x = 0; x < m_output->GetWidth(); x++) { - for (int32_t y = 0; y < m_output->GetHeight(); y++) { - if (m_output->Get(x, y)) { - pOutBitmap->SetPixel(x, y, m_barColor); - } - } - } - int32_t i = 0; - for (; i < contents.GetLength(); i++) - if (contents.GetAt(i) != ' ') { - break; - } - if (m_locTextLoc != BC_TEXT_LOC_NONE && i < contents.GetLength()) { - ShowChars(contents, pOutBitmap, nullptr, nullptr, m_barWidth, m_multiple, - e); - if (e != BCExceptionNO) - return; - } - std::unique_ptr<CFX_DIBitmap> pStretchBitmap = - pOutBitmap->StretchTo(m_Width, m_Height); - delete pOutBitmap; - pOutBitmap = pStretchBitmap.release(); -} - -void CBC_OneDimWriter::RenderDeviceResult(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - const CFX_WideStringC& contents, - int32_t& e) { - if (!m_output) - if (e != BCExceptionNO) - return; - - CFX_GraphStateData stateData; - CFX_PathData path; - path.AppendRect(0, 0, (FX_FLOAT)m_Width, (FX_FLOAT)m_Height); - device->DrawPath(&path, matrix, &stateData, m_backgroundColor, - m_backgroundColor, FXFILL_ALTERNATE); - CFX_Matrix matri(m_outputHScale, 0.0, 0.0, (FX_FLOAT)m_Height, 0.0, 0.0); - matri.Concat(*matrix); - for (int32_t x = 0; x < m_output->GetWidth(); x++) { - for (int32_t y = 0; y < m_output->GetHeight(); y++) { - CFX_PathData rect; - rect.AppendRect((FX_FLOAT)x, (FX_FLOAT)y, (FX_FLOAT)(x + 1), - (FX_FLOAT)(y + 1)); - if (m_output->Get(x, y)) { - CFX_GraphStateData data; - device->DrawPath(&rect, &matri, &data, m_barColor, 0, FXFILL_WINDING); - } - } - } - int32_t i = 0; - for (; i < contents.GetLength(); i++) - if (contents.GetAt(i) != ' ') { - break; - } - if (m_locTextLoc != BC_TEXT_LOC_NONE && i < contents.GetLength()) { - ShowChars(contents, nullptr, device, matrix, m_barWidth, m_multiple, e); - if (e != BCExceptionNO) - return; - } -} - -void CBC_OneDimWriter::RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) { - if (codeLength < 1) { - if (e != BCExceptionNO) - return; - } - if (m_ModuleHeight < 20.0) { - m_ModuleHeight = 20; - } - int32_t codeOldLength = codeLength; - int32_t leftPadding = 0; - int32_t rightPadding = 0; - if (m_bLeftPadding) { - leftPadding = 7; - } - if (m_bRightPadding) { - rightPadding = 7; - } - codeLength += leftPadding; - codeLength += rightPadding; - m_outputHScale = 1.0; - if (m_Width > 0) { - m_outputHScale = (FX_FLOAT)m_Width / (FX_FLOAT)codeLength; - } - if (!isDevice) { - m_outputHScale = - std::max(m_outputHScale, static_cast<FX_FLOAT>(m_ModuleWidth)); - } - FX_FLOAT dataLengthScale = 1.0; - if (m_iDataLenth > 0 && contents.GetLength() != 0) { - dataLengthScale = FX_FLOAT(contents.GetLength()) / FX_FLOAT(m_iDataLenth); - } - if (m_iDataLenth > 0 && contents.GetLength() == 0) { - dataLengthScale = FX_FLOAT(1) / FX_FLOAT(m_iDataLenth); - } - m_multiple = 1; - if (!isDevice) { - m_multiple = (int32_t)ceil(m_outputHScale * dataLengthScale); - } - int32_t outputHeight = 1; - if (!isDevice) { - if (m_Height == 0) { - outputHeight = std::max(20, m_ModuleHeight); - } else { - outputHeight = m_Height; - } - } - int32_t outputWidth = codeLength; - if (!isDevice) { - outputWidth = (int32_t)(codeLength * m_multiple / dataLengthScale); - } - m_barWidth = m_Width; - if (!isDevice) { - m_barWidth = codeLength * m_multiple; - } - m_output = pdfium::MakeUnique<CBC_CommonBitMatrix>(); - m_output->Init(outputWidth, outputHeight); - int32_t outputX = leftPadding * m_multiple; - for (int32_t inputX = 0; inputX < codeOldLength; inputX++) { - if (code[inputX] == 1) { - if (outputX >= outputWidth) { - break; - } - if (outputX + m_multiple > outputWidth && outputWidth - outputX > 0) { - m_output->SetRegion(outputX, 0, outputWidth - outputX, outputHeight, e); - break; - } - m_output->SetRegion(outputX, 0, m_multiple, outputHeight, e); - if (e != BCExceptionNO) - return; - } - outputX += m_multiple; - } -} - -bool CBC_OneDimWriter::CheckContentValidity(const CFX_WideStringC& contents) { - return true; -} - -CFX_WideString CBC_OneDimWriter::FilterContents( - const CFX_WideStringC& contents) { - return CFX_WideString(); -} - -CFX_WideString CBC_OneDimWriter::RenderTextContents( - const CFX_WideStringC& contents) { - return CFX_WideString(); -} diff --git a/xfa/fxbarcode/oned/BC_OneDimWriter.h b/xfa/fxbarcode/oned/BC_OneDimWriter.h deleted file mode 100644 index e37d7743416b52fa6117cd51532c156bc193a053..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OneDimWriter.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDIMWRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDIMWRITER_H_ - -#include <memory> - -#include "core/fxge/cfx_renderdevice.h" -#include "xfa/fxbarcode/BC_Library.h" -#include "xfa/fxbarcode/BC_Writer.h" - -class CBC_CommonBitMatrix; -class CFX_Font; -class CFX_RenderDevice; - -class CBC_OneDimWriter : public CBC_Writer { - public: - CBC_OneDimWriter(); - ~CBC_OneDimWriter() override; - - virtual uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e); - virtual uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e); - virtual uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e); - - virtual void RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e); - virtual void RenderBitmapResult(CFX_DIBitmap*& pOutBitmap, - const CFX_WideStringC& contents, - int32_t& e); - virtual void RenderDeviceResult(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - const CFX_WideStringC& contents, - int32_t& e); - virtual bool CheckContentValidity(const CFX_WideStringC& contents); - virtual CFX_WideString FilterContents(const CFX_WideStringC& contents); - virtual CFX_WideString RenderTextContents(const CFX_WideStringC& contents); - virtual void SetPrintChecksum(bool checksum); - virtual void SetDataLength(int32_t length); - virtual void SetCalcChecksum(bool state); - virtual void SetFontSize(FX_FLOAT size); - virtual void SetFontStyle(int32_t style); - virtual void SetFontColor(FX_ARGB color); - bool SetFont(CFX_Font* cFont); - - protected: - virtual void CalcTextInfo(const CFX_ByteString& text, - FXTEXT_CHARPOS* charPos, - CFX_Font* cFont, - FX_FLOAT geWidth, - int32_t fontSize, - FX_FLOAT& charsLen); - virtual void ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e); - virtual void ShowBitmapChars(CFX_DIBitmap* pOutBitmap, - const CFX_ByteString str, - FX_FLOAT geWidth, - FXTEXT_CHARPOS* pCharPos, - FX_FLOAT locX, - FX_FLOAT locY, - int32_t barWidth); - virtual void ShowDeviceChars(CFX_RenderDevice* device, - const CFX_Matrix* matrix, - const CFX_ByteString str, - FX_FLOAT geWidth, - FXTEXT_CHARPOS* pCharPos, - FX_FLOAT locX, - FX_FLOAT locY, - int32_t barWidth); - virtual int32_t AppendPattern(uint8_t* target, - int32_t pos, - const int32_t* pattern, - int32_t patternLength, - int32_t startColor, - int32_t& e); - - FX_WCHAR Upper(FX_WCHAR ch); - - bool m_bPrintChecksum; - int32_t m_iDataLenth; - bool m_bCalcChecksum; - CFX_Font* m_pFont; - FX_FLOAT m_fFontSize; - int32_t m_iFontStyle; - uint32_t m_fontColor; - BC_TEXT_LOC m_locTextLoc; - int32_t m_iContentLen; - bool m_bLeftPadding; - bool m_bRightPadding; - std::unique_ptr<CBC_CommonBitMatrix> m_output; - int32_t m_barWidth; - int32_t m_multiple; - FX_FLOAT m_outputHScale; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDIMWRITER_H_ diff --git a/xfa/fxbarcode/oned/BC_OnedCodaBarWriter.cpp b/xfa/fxbarcode/oned/BC_OnedCodaBarWriter.cpp deleted file mode 100644 index 399e5e7d4067ad5eba59e2105185a5fdb0a9fda3..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedCodaBarWriter.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/common/BC_CommonBitArray.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" -#include "xfa/fxbarcode/oned/BC_OnedCodaBarWriter.h" - -namespace { - -const FX_CHAR ALPHABET_STRING[] = "0123456789-$:/.+ABCDTN"; - -const int32_t CHARACTER_ENCODINGS[22] = { - 0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, - 0x030, 0x048, 0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, - 0x01A, 0x029, 0x00B, 0x00E, 0x01A, 0x029}; - -const FX_CHAR START_END_CHARS[] = {'A', 'B', 'C', 'D', 'T', 'N', '*', 'E', - 'a', 'b', 'c', 'd', 't', 'n', 'e'}; -const FX_CHAR CONTENT_CHARS[] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '-', '$', '/', ':', '+', '.'}; - -} // namespace - -CBC_OnedCodaBarWriter::CBC_OnedCodaBarWriter() { - m_chStart = 'A'; - m_chEnd = 'B'; - m_iWideNarrRatio = 2; -} -CBC_OnedCodaBarWriter::~CBC_OnedCodaBarWriter() {} -bool CBC_OnedCodaBarWriter::SetStartChar(FX_CHAR start) { - for (size_t i = 0; i < FX_ArraySize(START_END_CHARS); ++i) { - if (START_END_CHARS[i] == start) { - m_chStart = start; - return true; - } - } - return false; -} - -bool CBC_OnedCodaBarWriter::SetEndChar(FX_CHAR end) { - for (size_t i = 0; i < FX_ArraySize(START_END_CHARS); ++i) { - if (START_END_CHARS[i] == end) { - m_chEnd = end; - return true; - } - } - return false; -} -void CBC_OnedCodaBarWriter::SetDataLength(int32_t length) { - m_iDataLenth = length + 2; -} -bool CBC_OnedCodaBarWriter::SetTextLocation(BC_TEXT_LOC location) { - if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { - return false; - } - m_locTextLoc = location; - return true; -} -bool CBC_OnedCodaBarWriter::SetWideNarrowRatio(int32_t ratio) { - if (ratio < 2 || ratio > 3) { - return false; - } - m_iWideNarrRatio = ratio; - return true; -} -bool CBC_OnedCodaBarWriter::FindChar(FX_WCHAR ch, bool isContent) { - if (isContent) { - for (size_t i = 0; i < FX_ArraySize(CONTENT_CHARS); ++i) { - if (ch == (FX_WCHAR)CONTENT_CHARS[i]) { - return true; - } - } - for (size_t j = 0; j < FX_ArraySize(START_END_CHARS); ++j) { - if (ch == (FX_WCHAR)START_END_CHARS[j]) { - return true; - } - } - return false; - } else { - for (size_t i = 0; i < FX_ArraySize(CONTENT_CHARS); ++i) { - if (ch == (FX_WCHAR)CONTENT_CHARS[i]) { - return true; - } - } - return false; - } -} -bool CBC_OnedCodaBarWriter::CheckContentValidity( - const CFX_WideStringC& contents) { - FX_WCHAR ch; - int32_t index = 0; - for (index = 0; index < contents.GetLength(); index++) { - ch = contents.GetAt(index); - if (FindChar(ch, false)) { - continue; - } else { - return false; - } - } - return true; -} -CFX_WideString CBC_OnedCodaBarWriter::FilterContents( - const CFX_WideStringC& contents) { - CFX_WideString filtercontents; - FX_WCHAR ch; - for (int32_t index = 0; index < contents.GetLength(); index++) { - ch = contents.GetAt(index); - if (ch > 175) { - index++; - continue; - } - if (FindChar(ch, true)) { - filtercontents += ch; - } else { - continue; - } - } - return filtercontents; -} -uint8_t* CBC_OnedCodaBarWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedCodaBarWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - if (format != BCFORMAT_CODABAR) { - e = BCExceptionOnlyEncodeCODEBAR; - return nullptr; - } - uint8_t* ret = - CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedCodaBarWriter::Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) { - CFX_ByteString data = m_chStart + contents + m_chEnd; - m_iContentLen = data.GetLength(); - uint8_t* result = FX_Alloc2D(uint8_t, m_iWideNarrRatio * 7, data.GetLength()); - FX_CHAR ch; - int32_t position = 0; - for (int32_t index = 0; index < data.GetLength(); index++) { - ch = data.GetAt(index); - if (((ch >= 'a') && (ch <= 'z'))) { - ch = ch - 32; - } - switch (ch) { - case 'T': - ch = 'A'; - break; - case 'N': - ch = 'B'; - break; - case '*': - ch = 'C'; - break; - case 'E': - ch = 'D'; - break; - default: - break; - } - int32_t code = 0; - int32_t len = (int32_t)strlen(ALPHABET_STRING); - for (int32_t i = 0; i < len; i++) { - if (ch == ALPHABET_STRING[i]) { - code = CHARACTER_ENCODINGS[i]; - break; - } - } - uint8_t color = 1; - int32_t counter = 0; - int32_t bit = 0; - while (bit < 7) { - result[position] = color; - position++; - if (((code >> (6 - bit)) & 1) == 0 || counter == m_iWideNarrRatio - 1) { - color = !color; - bit++; - counter = 0; - } else { - counter++; - } - } - if (index < data.GetLength() - 1) { - result[position] = 0; - position++; - } - } - outLength = position; - return result; -} -CFX_WideString CBC_OnedCodaBarWriter::encodedContents( - const CFX_WideStringC& contents) { - CFX_WideString strStart(m_chStart); - CFX_WideString strEnd(m_chEnd); - return strStart + contents + strEnd; -} -void CBC_OnedCodaBarWriter::RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) { - CBC_OneDimWriter::RenderResult(encodedContents(contents).AsStringC(), code, - codeLength, isDevice, e); -} diff --git a/xfa/fxbarcode/oned/BC_OnedCodaBarWriter.h b/xfa/fxbarcode/oned/BC_OnedCodaBarWriter.h deleted file mode 100644 index 301c34a7516dec6cd3afaf5a37fc6879c33b2c65..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedCodaBarWriter.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDCODABARWRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDCODABARWRITER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/BC_Library.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -class CBC_OnedCodaBarWriter : public CBC_OneDimWriter { - public: - CBC_OnedCodaBarWriter(); - ~CBC_OnedCodaBarWriter() override; - - // CBC_OneDimWriter - uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) override; - bool CheckContentValidity(const CFX_WideStringC& contents) override; - CFX_WideString FilterContents(const CFX_WideStringC& contents) override; - void SetDataLength(int32_t length) override; - - virtual CFX_WideString encodedContents(const CFX_WideStringC& contents); - virtual bool SetStartChar(FX_CHAR start); - virtual bool SetEndChar(FX_CHAR end); - virtual bool SetTextLocation(BC_TEXT_LOC location); - virtual bool SetWideNarrowRatio(int32_t ratio); - virtual bool FindChar(FX_WCHAR ch, bool isContent); - - private: - void RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) override; - - FX_CHAR m_chStart; - FX_CHAR m_chEnd; - int32_t m_iWideNarrRatio; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDCODABARWRITER_H_ diff --git a/xfa/fxbarcode/oned/BC_OnedCode128Writer.cpp b/xfa/fxbarcode/oned/BC_OnedCode128Writer.cpp deleted file mode 100644 index f163b18663873a54dc3d5f017594cd75c2515cb9..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedCode128Writer.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" -#include "xfa/fxbarcode/oned/BC_OnedCode128Writer.h" - -namespace { - -const int32_t CODE_PATTERNS[107][7] = { - {2, 1, 2, 2, 2, 2, 0}, {2, 2, 2, 1, 2, 2, 0}, {2, 2, 2, 2, 2, 1, 0}, - {1, 2, 1, 2, 2, 3, 0}, {1, 2, 1, 3, 2, 2, 0}, {1, 3, 1, 2, 2, 2, 0}, - {1, 2, 2, 2, 1, 3, 0}, {1, 2, 2, 3, 1, 2, 0}, {1, 3, 2, 2, 1, 2, 0}, - {2, 2, 1, 2, 1, 3, 0}, {2, 2, 1, 3, 1, 2, 0}, {2, 3, 1, 2, 1, 2, 0}, - {1, 1, 2, 2, 3, 2, 0}, {1, 2, 2, 1, 3, 2, 0}, {1, 2, 2, 2, 3, 1, 0}, - {1, 1, 3, 2, 2, 2, 0}, {1, 2, 3, 1, 2, 2, 0}, {1, 2, 3, 2, 2, 1, 0}, - {2, 2, 3, 2, 1, 1, 0}, {2, 2, 1, 1, 3, 2, 0}, {2, 2, 1, 2, 3, 1, 0}, - {2, 1, 3, 2, 1, 2, 0}, {2, 2, 3, 1, 1, 2, 0}, {3, 1, 2, 1, 3, 1, 0}, - {3, 1, 1, 2, 2, 2, 0}, {3, 2, 1, 1, 2, 2, 0}, {3, 2, 1, 2, 2, 1, 0}, - {3, 1, 2, 2, 1, 2, 0}, {3, 2, 2, 1, 1, 2, 0}, {3, 2, 2, 2, 1, 1, 0}, - {2, 1, 2, 1, 2, 3, 0}, {2, 1, 2, 3, 2, 1, 0}, {2, 3, 2, 1, 2, 1, 0}, - {1, 1, 1, 3, 2, 3, 0}, {1, 3, 1, 1, 2, 3, 0}, {1, 3, 1, 3, 2, 1, 0}, - {1, 1, 2, 3, 1, 3, 0}, {1, 3, 2, 1, 1, 3, 0}, {1, 3, 2, 3, 1, 1, 0}, - {2, 1, 1, 3, 1, 3, 0}, {2, 3, 1, 1, 1, 3, 0}, {2, 3, 1, 3, 1, 1, 0}, - {1, 1, 2, 1, 3, 3, 0}, {1, 1, 2, 3, 3, 1, 0}, {1, 3, 2, 1, 3, 1, 0}, - {1, 1, 3, 1, 2, 3, 0}, {1, 1, 3, 3, 2, 1, 0}, {1, 3, 3, 1, 2, 1, 0}, - {3, 1, 3, 1, 2, 1, 0}, {2, 1, 1, 3, 3, 1, 0}, {2, 3, 1, 1, 3, 1, 0}, - {2, 1, 3, 1, 1, 3, 0}, {2, 1, 3, 3, 1, 1, 0}, {2, 1, 3, 1, 3, 1, 0}, - {3, 1, 1, 1, 2, 3, 0}, {3, 1, 1, 3, 2, 1, 0}, {3, 3, 1, 1, 2, 1, 0}, - {3, 1, 2, 1, 1, 3, 0}, {3, 1, 2, 3, 1, 1, 0}, {3, 3, 2, 1, 1, 1, 0}, - {3, 1, 4, 1, 1, 1, 0}, {2, 2, 1, 4, 1, 1, 0}, {4, 3, 1, 1, 1, 1, 0}, - {1, 1, 1, 2, 2, 4, 0}, {1, 1, 1, 4, 2, 2, 0}, {1, 2, 1, 1, 2, 4, 0}, - {1, 2, 1, 4, 2, 1, 0}, {1, 4, 1, 1, 2, 2, 0}, {1, 4, 1, 2, 2, 1, 0}, - {1, 1, 2, 2, 1, 4, 0}, {1, 1, 2, 4, 1, 2, 0}, {1, 2, 2, 1, 1, 4, 0}, - {1, 2, 2, 4, 1, 1, 0}, {1, 4, 2, 1, 1, 2, 0}, {1, 4, 2, 2, 1, 1, 0}, - {2, 4, 1, 2, 1, 1, 0}, {2, 2, 1, 1, 1, 4, 0}, {4, 1, 3, 1, 1, 1, 0}, - {2, 4, 1, 1, 1, 2, 0}, {1, 3, 4, 1, 1, 1, 0}, {1, 1, 1, 2, 4, 2, 0}, - {1, 2, 1, 1, 4, 2, 0}, {1, 2, 1, 2, 4, 1, 0}, {1, 1, 4, 2, 1, 2, 0}, - {1, 2, 4, 1, 1, 2, 0}, {1, 2, 4, 2, 1, 1, 0}, {4, 1, 1, 2, 1, 2, 0}, - {4, 2, 1, 1, 1, 2, 0}, {4, 2, 1, 2, 1, 1, 0}, {2, 1, 2, 1, 4, 1, 0}, - {2, 1, 4, 1, 2, 1, 0}, {4, 1, 2, 1, 2, 1, 0}, {1, 1, 1, 1, 4, 3, 0}, - {1, 1, 1, 3, 4, 1, 0}, {1, 3, 1, 1, 4, 1, 0}, {1, 1, 4, 1, 1, 3, 0}, - {1, 1, 4, 3, 1, 1, 0}, {4, 1, 1, 1, 1, 3, 0}, {4, 1, 1, 3, 1, 1, 0}, - {1, 1, 3, 1, 4, 1, 0}, {1, 1, 4, 1, 3, 1, 0}, {3, 1, 1, 1, 4, 1, 0}, - {4, 1, 1, 1, 3, 1, 0}, {2, 1, 1, 4, 1, 2, 0}, {2, 1, 1, 2, 1, 4, 0}, - {2, 1, 1, 2, 3, 2, 0}, {2, 3, 3, 1, 1, 1, 2}}; - -const int32_t CODE_START_B = 104; -const int32_t CODE_START_C = 105; -const int32_t CODE_STOP = 106; - -} // namespace - -CBC_OnedCode128Writer::CBC_OnedCode128Writer() { - m_codeFormat = BC_CODE128_B; -} -CBC_OnedCode128Writer::CBC_OnedCode128Writer(BC_TYPE type) { - m_codeFormat = type; -} -CBC_OnedCode128Writer::~CBC_OnedCode128Writer() {} -BC_TYPE CBC_OnedCode128Writer::GetType() { - return m_codeFormat; -} -bool CBC_OnedCode128Writer::CheckContentValidity( - const CFX_WideStringC& contents) { - bool ret = true; - int32_t position = 0; - int32_t patternIndex = -1; - if (m_codeFormat == BC_CODE128_B || m_codeFormat == BC_CODE128_C) { - while (position < contents.GetLength()) { - patternIndex = (int32_t)contents.GetAt(position); - if (patternIndex < 32 || patternIndex > 126 || patternIndex == 34) { - ret = false; - break; - } - position++; - } - } else { - ret = false; - } - return ret; -} -CFX_WideString CBC_OnedCode128Writer::FilterContents( - const CFX_WideStringC& contents) { - CFX_WideString filterChineseChar; - FX_WCHAR ch; - for (int32_t i = 0; i < contents.GetLength(); i++) { - ch = contents.GetAt(i); - if (ch > 175) { - i++; - continue; - } - filterChineseChar += ch; - } - CFX_WideString filtercontents; - if (m_codeFormat == BC_CODE128_B) { - for (int32_t i = 0; i < filterChineseChar.GetLength(); i++) { - ch = filterChineseChar.GetAt(i); - if (ch >= 32 && ch <= 126) { - filtercontents += ch; - } else { - continue; - } - } - } else if (m_codeFormat == BC_CODE128_C) { - for (int32_t i = 0; i < filterChineseChar.GetLength(); i++) { - ch = filterChineseChar.GetAt(i); - if (ch >= 32 && ch <= 106) { - filtercontents += ch; - } else { - continue; - } - } - } else { - filtercontents = contents; - } - return filtercontents; -} -bool CBC_OnedCode128Writer::SetTextLocation(BC_TEXT_LOC location) { - if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { - return false; - } - m_locTextLoc = location; - return true; -} -uint8_t* CBC_OnedCode128Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - if (format != BCFORMAT_CODE_128) { - e = BCExceptionOnlyEncodeCODE_128; - return nullptr; - } - uint8_t* ret = - CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedCode128Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -bool CBC_OnedCode128Writer::IsDigits(const CFX_ByteString& contents, - int32_t start, - int32_t length) { - int32_t end = start + length; - for (int32_t i = start; i < end; i++) { - if (contents[i] < '0' || contents[i] > '9') { - return false; - } - } - return true; -} - -uint8_t* CBC_OnedCode128Writer::Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) { - if (contents.GetLength() < 1 || contents.GetLength() > 80) { - e = BCExceptionContentsLengthShouldBetween1and80; - return nullptr; - } - CFX_ArrayTemplate<const int32_t*> patterns; - int32_t checkSum = 0; - if (m_codeFormat == BC_CODE128_B) { - checkSum = Encode128B(contents, &patterns); - } else if (m_codeFormat == BC_CODE128_C) { - checkSum = Encode128C(contents, &patterns); - } else { - e = BCExceptionFormatException; - return nullptr; - } - checkSum %= 103; - patterns.Add(CODE_PATTERNS[checkSum]); - patterns.Add(CODE_PATTERNS[CODE_STOP]); - m_iContentLen = contents.GetLength() + 3; - int32_t codeWidth = 0; - for (int32_t k = 0; k < patterns.GetSize(); k++) { - const int32_t* pattern = patterns[k]; - for (int32_t j = 0; j < 7; j++) { - codeWidth += pattern[j]; - } - } - outLength = codeWidth; - uint8_t* result = FX_Alloc(uint8_t, outLength); - int32_t pos = 0; - for (int32_t j = 0; j < patterns.GetSize(); j++) { - const int32_t* pattern = patterns[j]; - pos += AppendPattern(result, pos, pattern, 7, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - return result; -} - -int32_t CBC_OnedCode128Writer::Encode128B( - const CFX_ByteString& contents, - CFX_ArrayTemplate<const int32_t*>* patterns) { - int32_t checkSum = 0; - int32_t checkWeight = 1; - int32_t position = 0; - patterns->Add(CODE_PATTERNS[CODE_START_B]); - checkSum += CODE_START_B * checkWeight; - while (position < contents.GetLength()) { - int32_t patternIndex = 0; - patternIndex = contents[position] - ' '; - position += 1; - patterns->Add(CODE_PATTERNS[patternIndex]); - checkSum += patternIndex * checkWeight; - if (position != 0) { - checkWeight++; - } - } - return checkSum; -} - -int32_t CBC_OnedCode128Writer::Encode128C( - const CFX_ByteString& contents, - CFX_ArrayTemplate<const int32_t*>* patterns) { - int32_t checkSum = 0; - int32_t checkWeight = 1; - int32_t position = 0; - patterns->Add(CODE_PATTERNS[CODE_START_C]); - checkSum += CODE_START_C * checkWeight; - while (position < contents.GetLength()) { - int32_t patternIndex = 0; - FX_CHAR ch = contents.GetAt(position); - if (ch < '0' || ch > '9') { - patternIndex = (int32_t)ch; - position++; - } else { - patternIndex = FXSYS_atoi(contents.Mid(position, 2).c_str()); - if (contents.GetAt(position + 1) < '0' || - contents.GetAt(position + 1) > '9') { - position += 1; - } else { - position += 2; - } - } - patterns->Add(CODE_PATTERNS[patternIndex]); - checkSum += patternIndex * checkWeight; - if (position != 0) { - checkWeight++; - } - } - return checkSum; -} diff --git a/xfa/fxbarcode/oned/BC_OnedCode128Writer.h b/xfa/fxbarcode/oned/BC_OnedCode128Writer.h deleted file mode 100644 index 60a2f03acc2d0a85b50fa3cd1d615d004379187b..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedCode128Writer.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDCODE128WRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDCODE128WRITER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -class CBC_OnedCode128Writer : public CBC_OneDimWriter { - public: - CBC_OnedCode128Writer(); - explicit CBC_OnedCode128Writer(BC_TYPE type); - ~CBC_OnedCode128Writer() override; - - // CBC_OneDimWriter - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) override; - - bool CheckContentValidity(const CFX_WideStringC& contents) override; - CFX_WideString FilterContents(const CFX_WideStringC& contents) override; - - bool SetTextLocation(BC_TEXT_LOC location); - - BC_TYPE GetType(); - - private: - bool IsDigits(const CFX_ByteString& contents, int32_t start, int32_t length); - int32_t Encode128B(const CFX_ByteString& contents, - CFX_ArrayTemplate<const int32_t*>* patterns); - int32_t Encode128C(const CFX_ByteString& contents, - CFX_ArrayTemplate<const int32_t*>* patterns); - - BC_TYPE m_codeFormat; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDCODE128WRITER_H_ diff --git a/xfa/fxbarcode/oned/BC_OnedCode39Writer.cpp b/xfa/fxbarcode/oned/BC_OnedCode39Writer.cpp deleted file mode 100644 index a1ba5c80861ca17930e691f03c51be680d44d766..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedCode39Writer.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" -#include "xfa/fxbarcode/oned/BC_OnedCode39Writer.h" - -namespace { - -const FX_CHAR ALPHABET_STRING[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"; - -const FX_CHAR CHECKSUM_STRING[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; - -const int32_t CHARACTER_ENCODINGS[44] = { - 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, - 0x064, 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, - 0x04C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, - 0x106, 0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, - 0x085, 0x184, 0x0C4, 0x094, 0x0A8, 0x0A2, 0x08A, 0x02A}; - -} // namespace - -CBC_OnedCode39Writer::CBC_OnedCode39Writer() { - m_iWideNarrRatio = 3; -} -CBC_OnedCode39Writer::~CBC_OnedCode39Writer() {} -bool CBC_OnedCode39Writer::CheckContentValidity( - const CFX_WideStringC& contents) { - for (int32_t i = 0; i < contents.GetLength(); i++) { - FX_WCHAR ch = contents.GetAt(i); - if ((ch >= (FX_WCHAR)'0' && ch <= (FX_WCHAR)'9') || - (ch >= (FX_WCHAR)'A' && ch <= (FX_WCHAR)'Z') || ch == (FX_WCHAR)'-' || - ch == (FX_WCHAR)'.' || ch == (FX_WCHAR)' ' || ch == (FX_WCHAR)'*' || - ch == (FX_WCHAR)'$' || ch == (FX_WCHAR)'/' || ch == (FX_WCHAR)'+' || - ch == (FX_WCHAR)'%') { - continue; - } - return false; - } - return true; -} - -CFX_WideString CBC_OnedCode39Writer::FilterContents( - const CFX_WideStringC& contents) { - CFX_WideString filtercontents; - for (int32_t i = 0; i < contents.GetLength(); i++) { - FX_WCHAR ch = contents.GetAt(i); - if (ch == (FX_WCHAR)'*' && (i == 0 || i == contents.GetLength() - 1)) { - continue; - } - if (ch > 175) { - i++; - continue; - } else { - ch = Upper(ch); - } - if ((ch >= (FX_WCHAR)'0' && ch <= (FX_WCHAR)'9') || - (ch >= (FX_WCHAR)'A' && ch <= (FX_WCHAR)'Z') || ch == (FX_WCHAR)'-' || - ch == (FX_WCHAR)'.' || ch == (FX_WCHAR)' ' || ch == (FX_WCHAR)'*' || - ch == (FX_WCHAR)'$' || ch == (FX_WCHAR)'/' || ch == (FX_WCHAR)'+' || - ch == (FX_WCHAR)'%') { - filtercontents += ch; - } - } - return filtercontents; -} - -CFX_WideString CBC_OnedCode39Writer::RenderTextContents( - const CFX_WideStringC& contents) { - CFX_WideString renderContents; - for (int32_t i = 0; i < contents.GetLength(); i++) { - FX_WCHAR ch = contents.GetAt(i); - if (ch == (FX_WCHAR)'*' && (i == 0 || i == contents.GetLength() - 1)) { - continue; - } - if (ch > 175) { - i++; - continue; - } - if ((ch >= (FX_WCHAR)'0' && ch <= (FX_WCHAR)'9') || - (ch >= (FX_WCHAR)'A' && ch <= (FX_WCHAR)'Z') || - (ch >= (FX_WCHAR)'a' && ch <= (FX_WCHAR)'z') || ch == (FX_WCHAR)'-' || - ch == (FX_WCHAR)'.' || ch == (FX_WCHAR)' ' || ch == (FX_WCHAR)'*' || - ch == (FX_WCHAR)'$' || ch == (FX_WCHAR)'/' || ch == (FX_WCHAR)'+' || - ch == (FX_WCHAR)'%') { - renderContents += ch; - } - } - return renderContents; -} - -bool CBC_OnedCode39Writer::SetTextLocation(BC_TEXT_LOC location) { - if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { - return false; - } - m_locTextLoc = location; - return true; -} -bool CBC_OnedCode39Writer::SetWideNarrowRatio(int32_t ratio) { - if (ratio < 2 || ratio > 3) { - return false; - } - m_iWideNarrRatio = ratio; - return true; -} -uint8_t* CBC_OnedCode39Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedCode39Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - if (format != BCFORMAT_CODE_39) { - e = BCExceptionOnlyEncodeCODE_39; - return nullptr; - } - uint8_t* ret = - CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -void CBC_OnedCode39Writer::ToIntArray(int32_t a, int32_t* toReturn) { - for (int32_t i = 0; i < 9; i++) { - toReturn[i] = (a & (1 << i)) == 0 ? 1 : m_iWideNarrRatio; - } -} -FX_CHAR CBC_OnedCode39Writer::CalcCheckSum(const CFX_ByteString& contents, - int32_t& e) { - int32_t length = contents.GetLength(); - if (length > 80) { - e = BCExceptionContentsLengthShouldBetween1and80; - return '*'; - } - int32_t checksum = 0; - int32_t len = (int32_t)strlen(ALPHABET_STRING); - for (int32_t i = 0; i < contents.GetLength(); i++) { - int32_t j = 0; - for (; j < len; j++) { - if (ALPHABET_STRING[j] == contents[i]) { - if (contents[i] != '*') { - checksum += j; - break; - } else { - break; - } - } - } - if (j >= len) { - e = BCExceptionUnSupportedString; - return '*'; - } - } - checksum = checksum % 43; - return CHECKSUM_STRING[checksum]; -} -uint8_t* CBC_OnedCode39Writer::Encode(const CFX_ByteString& contents, - int32_t& outlength, - int32_t& e) { - FX_CHAR checksum = CalcCheckSum(contents, e); - if (checksum == '*') { - return nullptr; - } - int32_t widths[9] = {0}; - int32_t wideStrideNum = 3; - int32_t narrStrideNum = 9 - wideStrideNum; - CFX_ByteString encodedContents = contents; - if (m_bCalcChecksum) { - encodedContents += checksum; - } - m_iContentLen = encodedContents.GetLength(); - int32_t codeWidth = (wideStrideNum * m_iWideNarrRatio + narrStrideNum) * 2 + - 1 + m_iContentLen; - int32_t len = (int32_t)strlen(ALPHABET_STRING); - for (int32_t j = 0; j < m_iContentLen; j++) { - for (int32_t i = 0; i < len; i++) { - if (ALPHABET_STRING[i] == encodedContents[j]) { - ToIntArray(CHARACTER_ENCODINGS[i], widths); - for (int32_t k = 0; k < 9; k++) { - codeWidth += widths[k]; - } - } - } - } - outlength = codeWidth; - uint8_t* result = FX_Alloc(uint8_t, codeWidth); - ToIntArray(CHARACTER_ENCODINGS[39], widths); - int32_t pos = AppendPattern(result, 0, widths, 9, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - int32_t narrowWhite[] = {1}; - pos += AppendPattern(result, pos, narrowWhite, 1, 0, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - for (int32_t l = m_iContentLen - 1; l >= 0; l--) { - for (int32_t i = 0; i < len; i++) { - if (ALPHABET_STRING[i] == encodedContents[l]) { - ToIntArray(CHARACTER_ENCODINGS[i], widths); - pos += AppendPattern(result, pos, widths, 9, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - } - pos += AppendPattern(result, pos, narrowWhite, 1, 0, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - ToIntArray(CHARACTER_ENCODINGS[39], widths); - pos += AppendPattern(result, pos, widths, 9, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - for (int32_t i = 0; i < codeWidth / 2; i++) { - result[i] ^= result[codeWidth - 1 - i]; - result[codeWidth - 1 - i] ^= result[i]; - result[i] ^= result[codeWidth - 1 - i]; - } - return result; -} -CFX_WideString CBC_OnedCode39Writer::encodedContents( - const CFX_WideStringC& contents, - int32_t& e) { - CFX_WideString encodedContents(contents); - if (m_bCalcChecksum && m_bPrintChecksum) { - CFX_WideString checksumContent = FilterContents(contents); - CFX_ByteString str = checksumContent.UTF8Encode(); - FX_CHAR checksum; - checksum = CalcCheckSum(str, e); - if (e != BCExceptionNO) - return CFX_WideString(); - str += checksum; - encodedContents += checksum; - } - return encodedContents; -} -void CBC_OnedCode39Writer::RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) { - CFX_WideString encodedCon = encodedContents(contents, e); - if (e != BCExceptionNO) - return; - CBC_OneDimWriter::RenderResult(encodedCon.AsStringC(), code, codeLength, - isDevice, e); -} diff --git a/xfa/fxbarcode/oned/BC_OnedCode39Writer.h b/xfa/fxbarcode/oned/BC_OnedCode39Writer.h deleted file mode 100644 index c8755a3e698adfbd4760f03150cdb381a170df43..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedCode39Writer.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDCODE39WRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDCODE39WRITER_H_ - -#include "xfa/fxbarcode/BC_Library.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -class CBC_OnedCode39Writer : public CBC_OneDimWriter { - public: - CBC_OnedCode39Writer(); - ~CBC_OnedCode39Writer() override; - - // CBC_OneDimWriter - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) override; - void RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) override; - bool CheckContentValidity(const CFX_WideStringC& contents) override; - CFX_WideString FilterContents(const CFX_WideStringC& contents) override; - CFX_WideString RenderTextContents(const CFX_WideStringC& contents) override; - - virtual CFX_WideString encodedContents(const CFX_WideStringC& contents, - int32_t& e); - virtual bool SetTextLocation(BC_TEXT_LOC loction); - virtual bool SetWideNarrowRatio(int32_t ratio); - - private: - void ToIntArray(int32_t a, int32_t* toReturn); - FX_CHAR CalcCheckSum(const CFX_ByteString& contents, int32_t& e); - - int32_t m_iWideNarrRatio; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDCODE39WRITER_H_ diff --git a/xfa/fxbarcode/oned/BC_OnedEAN13Writer.cpp b/xfa/fxbarcode/oned/BC_OnedEAN13Writer.cpp deleted file mode 100644 index bcbc80a61d069c8221cafa8af4bcb9f923144ef2..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedEAN13Writer.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" -#include "xfa/fxbarcode/oned/BC_OnedEAN13Writer.h" - -namespace { - -const int32_t FIRST_DIGIT_ENCODINGS[10] = {0x00, 0x0B, 0x0D, 0xE, 0x13, - 0x19, 0x1C, 0x15, 0x16, 0x1A}; -const int32_t START_END_PATTERN[3] = {1, 1, 1}; -const int32_t MIDDLE_PATTERN[5] = {1, 1, 1, 1, 1}; -const int32_t L_PATTERNS[10][4] = { - {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, - {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}}; -const int32_t L_AND_G_PATTERNS[20][4] = { - {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, - {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}, - {1, 1, 2, 3}, {1, 2, 2, 2}, {2, 2, 1, 2}, {1, 1, 4, 1}, {2, 3, 1, 1}, - {1, 3, 2, 1}, {4, 1, 1, 1}, {2, 1, 3, 1}, {3, 1, 2, 1}, {2, 1, 1, 3}}; - -} // namespace - -CBC_OnedEAN13Writer::CBC_OnedEAN13Writer() { - m_bLeftPadding = true; - m_codeWidth = 3 + (7 * 6) + 5 + (7 * 6) + 3; -} -CBC_OnedEAN13Writer::~CBC_OnedEAN13Writer() {} -bool CBC_OnedEAN13Writer::CheckContentValidity( - const CFX_WideStringC& contents) { - for (int32_t i = 0; i < contents.GetLength(); i++) { - if (contents.GetAt(i) >= '0' && contents.GetAt(i) <= '9') { - continue; - } else { - return false; - } - } - return true; -} -CFX_WideString CBC_OnedEAN13Writer::FilterContents( - const CFX_WideStringC& contents) { - CFX_WideString filtercontents; - FX_WCHAR ch; - for (int32_t i = 0; i < contents.GetLength(); i++) { - ch = contents.GetAt(i); - if (ch > 175) { - i++; - continue; - } - if (ch >= '0' && ch <= '9') { - filtercontents += ch; - } - } - return filtercontents; -} -int32_t CBC_OnedEAN13Writer::CalcChecksum(const CFX_ByteString& contents) { - int32_t odd = 0; - int32_t even = 0; - int32_t j = 1; - for (int32_t i = contents.GetLength() - 1; i >= 0; i--) { - if (j % 2) { - odd += FXSYS_atoi(contents.Mid(i, 1).c_str()); - } else { - even += FXSYS_atoi(contents.Mid(i, 1).c_str()); - } - j++; - } - int32_t checksum = (odd * 3 + even) % 10; - checksum = (10 - checksum) % 10; - return (checksum); -} -uint8_t* CBC_OnedEAN13Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedEAN13Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - if (format != BCFORMAT_EAN_13) { - e = BCExceptionOnlyEncodeEAN_13; - } - uint8_t* ret = - CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedEAN13Writer::Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) { - if (contents.GetLength() != 13) { - e = BCExceptionDigitLengthShould13; - return nullptr; - } - m_iDataLenth = 13; - int32_t firstDigit = FXSYS_atoi(contents.Mid(0, 1).c_str()); - int32_t parities = FIRST_DIGIT_ENCODINGS[firstDigit]; - outLength = m_codeWidth; - uint8_t* result = FX_Alloc(uint8_t, m_codeWidth); - int32_t pos = 0; - pos += AppendPattern(result, pos, START_END_PATTERN, 3, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - int32_t i = 0; - for (i = 1; i <= 6; i++) { - int32_t digit = FXSYS_atoi(contents.Mid(i, 1).c_str()); - if ((parities >> (6 - i) & 1) == 1) { - digit += 10; - } - pos += AppendPattern(result, pos, L_AND_G_PATTERNS[digit], 4, 0, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - pos += AppendPattern(result, pos, MIDDLE_PATTERN, 5, 0, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - for (i = 7; i <= 12; i++) { - int32_t digit = FXSYS_atoi(contents.Mid(i, 1).c_str()); - pos += AppendPattern(result, pos, L_PATTERNS[digit], 4, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - pos += AppendPattern(result, pos, START_END_PATTERN, 3, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - return result; -} - -void CBC_OnedEAN13Writer::ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) { - if (!device && !pOutBitmap) { - e = BCExceptionIllegalArgument; - return; - } - int32_t leftPadding = 7 * multiple; - int32_t leftPosition = 3 * multiple + leftPadding; - CFX_ByteString str = FX_UTF8Encode(contents); - int32_t iLen = str.GetLength(); - FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLen); - FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLen); - CFX_FxgeDevice geBitmap; - if (pOutBitmap) - geBitmap.Attach(pOutBitmap, false, nullptr, false); - - int32_t iFontSize = (int32_t)fabs(m_fFontSize); - int32_t iTextHeight = iFontSize + 1; - CFX_ByteString tempStr = str.Mid(1, 6); - int32_t strWidth = multiple * 42; - if (!pOutBitmap) { - CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect( - (FX_FLOAT)leftPosition, (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)(leftPosition + strWidth - 0.5), (FX_FLOAT)m_Height); - matr.Concat(*matrix); - matr.TransformRect(rect); - FX_RECT re = rect.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - CFX_FloatRect rect1( - (FX_FLOAT)(leftPosition + 47 * multiple), - (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)(leftPosition + 47 * multiple + strWidth - 0.5), - (FX_FLOAT)m_Height); - CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - matr1.Concat(*matrix); - matr1.TransformRect(rect1); - re = rect1.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - int32_t strWidth1 = multiple * 7; - CFX_Matrix matr2(m_outputHScale, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); - CFX_FloatRect rect2(0.0f, (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)strWidth1 - 0.5f, (FX_FLOAT)m_Height); - matr2.Concat(*matrix); - matr2.TransformRect(rect2); - re = rect2.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - } - FX_FLOAT blank = 0.0; - iLen = tempStr.GetLength(); - if (!pOutBitmap) { - strWidth = (int32_t)(strWidth * m_outputHScale); - } - CalcTextInfo(tempStr, pCharPos + 1, m_pFont, (FX_FLOAT)strWidth, iFontSize, - blank); - CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0, (FX_FLOAT)iFontSize); - CFX_FxgeDevice ge; - if (pOutBitmap) { - ge.Create(strWidth, iTextHeight, FXDIB_Argb, nullptr); - FX_RECT rect(0, 0, strWidth, iTextHeight); - ge.FillRect(&rect, m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos + 1, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition, m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)leftPosition * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight) + iFontSize); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos + 1, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - tempStr = str.Mid(7, 6); - iLen = tempStr.GetLength(); - CalcTextInfo(tempStr, pCharPos + 7, m_pFont, (FX_FLOAT)strWidth, iFontSize, - blank); - if (pOutBitmap) { - FX_RECT rect1(0, 0, strWidth, iTextHeight); - ge.FillRect(&rect1, m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos + 7, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition + 47 * multiple, - m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1( - 1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)(leftPosition + 47 * multiple) * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos + 7, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - tempStr = str.Mid(0, 1); - iLen = tempStr.GetLength(); - strWidth = multiple * 7; - if (!pOutBitmap) - strWidth = (int32_t)(strWidth * m_outputHScale); - - CalcTextInfo(tempStr, pCharPos, m_pFont, (FX_FLOAT)strWidth, iFontSize, - blank); - if (pOutBitmap) { - delete ge.GetBitmap(); - ge.Create(strWidth, iTextHeight, FXDIB_Argb, nullptr); - ge.GetBitmap()->Clear(m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos, m_pFont, static_cast<FX_FLOAT>(iFontSize), - &affine_matrix, m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), 0, m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, 0.0, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - FX_Free(pCharPos); -} - -void CBC_OnedEAN13Writer::RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) { - CBC_OneDimWriter::RenderResult(contents, code, codeLength, isDevice, e); -} diff --git a/xfa/fxbarcode/oned/BC_OnedEAN13Writer.h b/xfa/fxbarcode/oned/BC_OnedEAN13Writer.h deleted file mode 100644 index 5775f890467c0cb08135938d5f256a1005d7a780..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedEAN13Writer.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDEAN13WRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDEAN13WRITER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -class CFX_DIBitmap; -class CFX_RenderDevice; - -class CBC_OnedEAN13Writer : public CBC_OneDimWriter { - public: - CBC_OnedEAN13Writer(); - ~CBC_OnedEAN13Writer() override; - - // CBC_OneDimWriter - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) override; - void RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) override; - bool CheckContentValidity(const CFX_WideStringC& contents) override; - CFX_WideString FilterContents(const CFX_WideStringC& contents) override; - - int32_t CalcChecksum(const CFX_ByteString& contents); - - protected: - void ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) override; - - private: - int32_t m_codeWidth; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDEAN13WRITER_H_ diff --git a/xfa/fxbarcode/oned/BC_OnedEAN8Writer.cpp b/xfa/fxbarcode/oned/BC_OnedEAN8Writer.cpp deleted file mode 100644 index c40223818ffe228efa19879a3d6d977a80cace18..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedEAN8Writer.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" -#include "xfa/fxbarcode/oned/BC_OnedEAN8Writer.h" - -namespace { - -const int32_t START_END_PATTERN[3] = {1, 1, 1}; -const int32_t MIDDLE_PATTERN[5] = {1, 1, 1, 1, 1}; -const int32_t L_PATTERNS[10][4] = { - {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, - {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}}; - -} // namespace - -CBC_OnedEAN8Writer::CBC_OnedEAN8Writer() { - m_iDataLenth = 8; - m_codeWidth = 3 + (7 * 4) + 5 + (7 * 4) + 3; -} -CBC_OnedEAN8Writer::~CBC_OnedEAN8Writer() {} -void CBC_OnedEAN8Writer::SetDataLength(int32_t length) { - m_iDataLenth = 8; -} -bool CBC_OnedEAN8Writer::SetTextLocation(BC_TEXT_LOC location) { - if (location == BC_TEXT_LOC_BELOWEMBED) { - m_locTextLoc = location; - return true; - } - return false; -} -bool CBC_OnedEAN8Writer::CheckContentValidity(const CFX_WideStringC& contents) { - for (int32_t i = 0; i < contents.GetLength(); i++) { - if (contents.GetAt(i) >= '0' && contents.GetAt(i) <= '9') { - continue; - } else { - return false; - } - } - return true; -} -CFX_WideString CBC_OnedEAN8Writer::FilterContents( - const CFX_WideStringC& contents) { - CFX_WideString filtercontents; - FX_WCHAR ch; - for (int32_t i = 0; i < contents.GetLength(); i++) { - ch = contents.GetAt(i); - if (ch > 175) { - i++; - continue; - } - if (ch >= '0' && ch <= '9') { - filtercontents += ch; - } - } - return filtercontents; -} -int32_t CBC_OnedEAN8Writer::CalcChecksum(const CFX_ByteString& contents) { - int32_t odd = 0; - int32_t even = 0; - int32_t j = 1; - for (int32_t i = contents.GetLength() - 1; i >= 0; i--) { - if (j % 2) { - odd += FXSYS_atoi(contents.Mid(i, 1).c_str()); - } else { - even += FXSYS_atoi(contents.Mid(i, 1).c_str()); - } - j++; - } - int32_t checksum = (odd * 3 + even) % 10; - checksum = (10 - checksum) % 10; - return (checksum); -} -uint8_t* CBC_OnedEAN8Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedEAN8Writer::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - if (format != BCFORMAT_EAN_8) { - e = BCExceptionOnlyEncodeEAN_8; - return nullptr; - } - uint8_t* ret = - CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} -uint8_t* CBC_OnedEAN8Writer::Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) { - if (contents.GetLength() != 8) { - e = BCExceptionDigitLengthMustBe8; - return nullptr; - } - outLength = m_codeWidth; - uint8_t* result = FX_Alloc(uint8_t, m_codeWidth); - int32_t pos = 0; - pos += AppendPattern(result, pos, START_END_PATTERN, 3, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - int32_t i = 0; - for (i = 0; i <= 3; i++) { - int32_t digit = FXSYS_atoi(contents.Mid(i, 1).c_str()); - pos += AppendPattern(result, pos, L_PATTERNS[digit], 4, 0, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - pos += AppendPattern(result, pos, MIDDLE_PATTERN, 5, 0, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - for (i = 4; i <= 7; i++) { - int32_t digit = FXSYS_atoi(contents.Mid(i, 1).c_str()); - pos += AppendPattern(result, pos, L_PATTERNS[digit], 4, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - } - pos += AppendPattern(result, pos, START_END_PATTERN, 3, 1, e); - if (e != BCExceptionNO) { - FX_Free(result); - return nullptr; - } - return result; -} - -void CBC_OnedEAN8Writer::ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) { - if (!device && !pOutBitmap) { - e = BCExceptionIllegalArgument; - return; - } - - int32_t leftPosition = 3 * multiple; - CFX_ByteString str = FX_UTF8Encode(contents); - int32_t iLength = str.GetLength(); - FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLength); - FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLength); - CFX_ByteString tempStr = str.Mid(0, 4); - int32_t iLen = tempStr.GetLength(); - int32_t strWidth = 7 * multiple * 4; - FX_FLOAT blank = 0.0; - CFX_FxgeDevice geBitmap; - if (pOutBitmap) - geBitmap.Attach(pOutBitmap, false, nullptr, false); - - int32_t iFontSize = (int32_t)fabs(m_fFontSize); - int32_t iTextHeight = iFontSize + 1; - if (!pOutBitmap) { - CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect( - (FX_FLOAT)leftPosition, (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)(leftPosition + strWidth - 0.5), (FX_FLOAT)m_Height); - matr.Concat(*matrix); - matr.TransformRect(rect); - FX_RECT re = rect.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect1( - (FX_FLOAT)(leftPosition + 33 * multiple), - (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)(leftPosition + 33 * multiple + strWidth - 0.5), - (FX_FLOAT)m_Height); - matr1.Concat(*matrix); - matr1.TransformRect(rect1); - re = rect1.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - } - if (!pOutBitmap) - strWidth = (int32_t)(strWidth * m_outputHScale); - - CalcTextInfo(tempStr, pCharPos, m_pFont, (FX_FLOAT)strWidth, iFontSize, - blank); - CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0, (FX_FLOAT)iFontSize); - CFX_FxgeDevice ge; - if (pOutBitmap) { - delete ge.GetBitmap(); - ge.Create(strWidth, iTextHeight, FXDIB_Argb, nullptr); - ge.GetBitmap()->Clear(m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos, m_pFont, static_cast<FX_FLOAT>(iFontSize), - &affine_matrix, m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition, m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)leftPosition * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - affine_matrix1.Concat(*matrix); - device->DrawNormalText(iLen, pCharPos, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - tempStr = str.Mid(4, 4); - iLen = tempStr.GetLength(); - CalcTextInfo(tempStr, pCharPos + 4, m_pFont, (FX_FLOAT)strWidth, iFontSize, - blank); - if (pOutBitmap) { - delete ge.GetBitmap(); - ge.Create(strWidth, iTextHeight, FXDIB_Argb, nullptr); - ge.GetBitmap()->Clear(m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos + 4, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition + 33 * multiple, - m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1( - 1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)(leftPosition + 33 * multiple) * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos + 4, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - FX_Free(pCharPos); -} - -void CBC_OnedEAN8Writer::RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) { - CBC_OneDimWriter::RenderResult(contents, code, codeLength, isDevice, e); -} diff --git a/xfa/fxbarcode/oned/BC_OnedEAN8Writer.h b/xfa/fxbarcode/oned/BC_OnedEAN8Writer.h deleted file mode 100644 index 844fc33afa1204341acb06bf91ef09e1e7f1c758..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedEAN8Writer.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDEAN8WRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDEAN8WRITER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/BC_Library.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -class CFX_DIBitmap; -class CFX_RenderDevice; - -class CBC_OnedEAN8Writer : public CBC_OneDimWriter { - public: - CBC_OnedEAN8Writer(); - ~CBC_OnedEAN8Writer() override; - - // CBC_OneDimWriter - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) override; - - void RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) override; - bool CheckContentValidity(const CFX_WideStringC& contents) override; - CFX_WideString FilterContents(const CFX_WideStringC& contents) override; - void SetDataLength(int32_t length) override; - - bool SetTextLocation(BC_TEXT_LOC location); - int32_t CalcChecksum(const CFX_ByteString& contents); - - protected: - void ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) override; - - private: - int32_t m_codeWidth; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDEAN8WRITER_H_ diff --git a/xfa/fxbarcode/oned/BC_OnedUPCAWriter.cpp b/xfa/fxbarcode/oned/BC_OnedUPCAWriter.cpp deleted file mode 100644 index 6d6e79637c51a6abf3006b42e41fea6142d7df1c..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedUPCAWriter.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fxbarcode/BC_Writer.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" -#include "xfa/fxbarcode/oned/BC_OnedEAN13Writer.h" -#include "xfa/fxbarcode/oned/BC_OnedUPCAWriter.h" - -CBC_OnedUPCAWriter::CBC_OnedUPCAWriter() { - m_bLeftPadding = true; - m_bRightPadding = true; -} - -void CBC_OnedUPCAWriter::Init() { - m_subWriter = pdfium::MakeUnique<CBC_OnedEAN13Writer>(); -} - -CBC_OnedUPCAWriter::~CBC_OnedUPCAWriter() {} - -bool CBC_OnedUPCAWriter::CheckContentValidity(const CFX_WideStringC& contents) { - for (FX_STRSIZE i = 0; i < contents.GetLength(); ++i) { - if (contents.GetAt(i) < '0' || contents.GetAt(i) > '9') - return false; - } - return true; -} - -CFX_WideString CBC_OnedUPCAWriter::FilterContents( - const CFX_WideStringC& contents) { - CFX_WideString filtercontents; - FX_WCHAR ch; - for (int32_t i = 0; i < contents.GetLength(); i++) { - ch = contents.GetAt(i); - if (ch > 175) { - i++; - continue; - } - if (ch >= '0' && ch <= '9') { - filtercontents += ch; - } - } - return filtercontents; -} - -int32_t CBC_OnedUPCAWriter::CalcChecksum(const CFX_ByteString& contents) { - int32_t odd = 0; - int32_t even = 0; - int32_t j = 1; - for (int32_t i = contents.GetLength() - 1; i >= 0; i--) { - if (j % 2) { - odd += FXSYS_atoi(contents.Mid(i, 1).c_str()); - } else { - even += FXSYS_atoi(contents.Mid(i, 1).c_str()); - } - j++; - } - int32_t checksum = (odd * 3 + even) % 10; - checksum = (10 - checksum) % 10; - return (checksum); -} - -uint8_t* CBC_OnedUPCAWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} - -uint8_t* CBC_OnedUPCAWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - if (format != BCFORMAT_UPC_A) { - e = BCExceptionOnlyEncodeUPC_A; - return nullptr; - } - CFX_ByteString toEAN13String = '0' + contents; - m_iDataLenth = 13; - uint8_t* ret = m_subWriter->Encode(toEAN13String, BCFORMAT_EAN_13, outWidth, - outHeight, hints, e); - if (e != BCExceptionNO) - return nullptr; - return ret; -} - -uint8_t* CBC_OnedUPCAWriter::Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) { - return nullptr; -} - -void CBC_OnedUPCAWriter::ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) { - if (!device && !pOutBitmap) { - e = BCExceptionIllegalArgument; - return; - } - - int32_t leftPadding = 7 * multiple; - int32_t leftPosition = 10 * multiple + leftPadding; - CFX_ByteString str = FX_UTF8Encode(contents); - int32_t iLen = str.GetLength(); - FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLen); - FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLen); - CFX_ByteString tempStr = str.Mid(1, 5); - FX_FLOAT strWidth = (FX_FLOAT)35 * multiple; - FX_FLOAT blank = 0.0; - CFX_FxgeDevice geBitmap; - if (pOutBitmap) - geBitmap.Attach(pOutBitmap, false, nullptr, false); - - iLen = tempStr.GetLength(); - int32_t iFontSize = (int32_t)fabs(m_fFontSize); - int32_t iTextHeight = iFontSize + 1; - if (!pOutBitmap) { - CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect( - (FX_FLOAT)leftPosition, (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)(leftPosition + strWidth - 0.5), (FX_FLOAT)m_Height); - matr.Concat(*matrix); - matr.TransformRect(rect); - FX_RECT re = rect.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect1( - (FX_FLOAT)(leftPosition + 40 * multiple), - (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)((leftPosition + 40 * multiple) + strWidth - 0.5), - (FX_FLOAT)m_Height); - matr1.Concat(*matrix); - matr1.TransformRect(rect1); - re = rect1.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - FX_FLOAT strWidth1 = (FX_FLOAT)multiple * 7; - CFX_Matrix matr2(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect2(0.0, (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)strWidth1 - 1, (FX_FLOAT)m_Height); - matr2.Concat(*matrix); - matr2.TransformRect(rect2); - re = rect2.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - CFX_Matrix matr3(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0); - CFX_FloatRect rect3( - (FX_FLOAT)(leftPosition + 85 * multiple), - (FX_FLOAT)(m_Height - iTextHeight), - (FX_FLOAT)((leftPosition + 85 * multiple) + strWidth1 - 0.5), - (FX_FLOAT)m_Height); - matr3.Concat(*matrix); - matr3.TransformRect(rect3); - re = rect3.GetOuterRect(); - device->FillRect(&re, m_backgroundColor); - } - if (!pOutBitmap) - strWidth = strWidth * m_outputHScale; - - CalcTextInfo(tempStr, pCharPos + 1, m_pFont, strWidth, iFontSize, blank); - CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0, (FX_FLOAT)iFontSize); - CFX_FxgeDevice ge; - if (pOutBitmap) { - ge.Create((int)strWidth, iTextHeight, FXDIB_Argb, nullptr); - ge.GetBitmap()->Clear(m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos + 1, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition, m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)leftPosition * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos + 1, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - tempStr = str.Mid(6, 5); - iLen = tempStr.GetLength(); - CalcTextInfo(tempStr, pCharPos + 6, m_pFont, strWidth, iFontSize, blank); - if (pOutBitmap) { - FX_RECT rect2(0, 0, (int)strWidth, iTextHeight); - ge.FillRect(&rect2, m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos + 6, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition + 40 * multiple, - m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1( - 1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)(leftPosition + 40 * multiple) * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos + 6, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - tempStr = str.Mid(0, 1); - iLen = tempStr.GetLength(); - strWidth = (FX_FLOAT)multiple * 7; - if (!pOutBitmap) - strWidth = strWidth * m_outputHScale; - - CalcTextInfo(tempStr, pCharPos, m_pFont, strWidth, iFontSize, blank); - if (pOutBitmap) { - delete ge.GetBitmap(); - ge.Create((int)strWidth, iTextHeight, FXDIB_Argb, nullptr); - ge.GetBitmap()->Clear(m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos, m_pFont, static_cast<FX_FLOAT>(iFontSize), - &affine_matrix, m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), 0, m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, 0, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - tempStr = str.Mid(11, 1); - iLen = tempStr.GetLength(); - CalcTextInfo(tempStr, pCharPos + 11, m_pFont, strWidth, iFontSize, blank); - if (pOutBitmap) { - delete ge.GetBitmap(); - ge.Create((int)strWidth, iTextHeight, FXDIB_Argb, nullptr); - ge.GetBitmap()->Clear(m_backgroundColor); - ge.DrawNormalText(iLen, pCharPos + 11, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix, - m_fontColor, FXTEXT_CLEARTYPE); - geBitmap.SetDIBits(ge.GetBitmap(), leftPosition + 85 * multiple, - m_Height - iTextHeight); - } else { - CFX_Matrix affine_matrix1( - 1.0, 0.0, 0.0, -1.0, - (FX_FLOAT)(leftPosition + 85 * multiple) * m_outputHScale, - (FX_FLOAT)(m_Height - iTextHeight + iFontSize)); - if (matrix) { - affine_matrix1.Concat(*matrix); - } - device->DrawNormalText(iLen, pCharPos + 11, m_pFont, - static_cast<FX_FLOAT>(iFontSize), &affine_matrix1, - m_fontColor, FXTEXT_CLEARTYPE); - } - FX_Free(pCharPos); -} - -void CBC_OnedUPCAWriter::RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) { - CBC_OneDimWriter::RenderResult(contents, code, codeLength, isDevice, e); -} diff --git a/xfa/fxbarcode/oned/BC_OnedUPCAWriter.h b/xfa/fxbarcode/oned/BC_OnedUPCAWriter.h deleted file mode 100644 index 6b786ce3b8c944574edd6d232bc058b87b684071..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/oned/BC_OnedUPCAWriter.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_ONED_BC_ONEDUPCAWRITER_H_ -#define XFA_FXBARCODE_ONED_BC_ONEDUPCAWRITER_H_ - -#include <memory> - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/oned/BC_OneDimWriter.h" - -class CBC_OnedEAN13Writer; -class CFX_DIBitmap; -class CFX_Matrix; -class CFX_RenderDevice; - -class CBC_OnedUPCAWriter : public CBC_OneDimWriter { - public: - CBC_OnedUPCAWriter(); - ~CBC_OnedUPCAWriter() override; - - // CBC_OneDimWriter - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) override; - uint8_t* Encode(const CFX_ByteString& contents, - int32_t& outLength, - int32_t& e) override; - - void RenderResult(const CFX_WideStringC& contents, - uint8_t* code, - int32_t codeLength, - bool isDevice, - int32_t& e) override; - bool CheckContentValidity(const CFX_WideStringC& contents) override; - CFX_WideString FilterContents(const CFX_WideStringC& contents) override; - - void Init(); - int32_t CalcChecksum(const CFX_ByteString& contents); - - protected: - void ShowChars(const CFX_WideStringC& contents, - CFX_DIBitmap* pOutBitmap, - CFX_RenderDevice* device, - const CFX_Matrix* matrix, - int32_t barWidth, - int32_t multiple, - int32_t& e) override; - - private: - std::unique_ptr<CBC_OnedEAN13Writer> m_subWriter; -}; - -#endif // XFA_FXBARCODE_ONED_BC_ONEDUPCAWRITER_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417.h b/xfa/fxbarcode/pdf417/BC_PDF417.h deleted file mode 100644 index 3ba5aa2f0c07f810f9215fda3206648963e4069a..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417_H_ - -#include <memory> - -#include "core/fxcrt/fx_basic.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h" - -class CBC_BarcodeRow; -class CBC_BarcodeMatrix; - -class CBC_PDF417 { - public: - CBC_PDF417(); - explicit CBC_PDF417(bool compact); - virtual ~CBC_PDF417(); - - CBC_BarcodeMatrix* getBarcodeMatrix(); - void generateBarcodeLogic(CFX_WideString msg, - int32_t errorCorrectionLevel, - int32_t& e); - void setDimensions(int32_t maxCols, - int32_t minCols, - int32_t maxRows, - int32_t minRows); - void setCompaction(Compaction compaction); - void setCompact(bool compact); - - private: - static const int32_t START_PATTERN = 0x1fea8; - static const int32_t STOP_PATTERN = 0x3fa29; - static const int32_t CODEWORD_TABLE[][929]; - static constexpr FX_FLOAT PREFERRED_RATIO = 3.0f; - static constexpr FX_FLOAT DEFAULT_MODULE_WIDTH = 0.357f; - static constexpr FX_FLOAT HEIGHT = 2.0f; - - static int32_t calculateNumberOfRows(int32_t m, int32_t k, int32_t c); - static int32_t getNumberOfPadCodewords(int32_t m, - int32_t k, - int32_t c, - int32_t r); - static void encodeChar(int32_t pattern, int32_t len, CBC_BarcodeRow* logic); - void encodeLowLevel(CFX_WideString fullCodewords, - int32_t c, - int32_t r, - int32_t errorCorrectionLevel, - CBC_BarcodeMatrix* logic); - CFX_ArrayTemplate<int32_t>* determineDimensions( - int32_t sourceCodeWords, - int32_t errorCorrectionCodeWords, - int32_t& e); - - std::unique_ptr<CBC_BarcodeMatrix> m_barcodeMatrix; - bool m_compact; - Compaction m_compaction; - int32_t m_minCols; - int32_t m_maxCols; - int32_t m_maxRows; - int32_t m_minRows; -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp b/xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp deleted file mode 100644 index c1f4da1e3be5373683f87dd13201aa3b7179878a..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h" - -CBC_BarcodeMatrix::CBC_BarcodeMatrix(int32_t height, int32_t width) { - m_matrix.SetSize(height + 2); - for (int32_t i = 0, matrixLength = m_matrix.GetSize(); i < matrixLength; - i++) { - m_matrix[i] = new CBC_BarcodeRow((width + 4) * 17 + 1); - } - m_width = width * 17; - m_height = height + 2; - m_currentRow = 0; - m_outHeight = 0; - m_outWidth = 0; -} -CBC_BarcodeMatrix::~CBC_BarcodeMatrix() { - for (int32_t i = 0; i < m_matrix.GetSize(); i++) - delete m_matrix.GetAt(i); - - m_matrixOut.RemoveAll(); -} -void CBC_BarcodeMatrix::set(int32_t x, int32_t y, uint8_t value) { - m_matrix[y]->set(x, value); -} -void CBC_BarcodeMatrix::setMatrix(int32_t x, int32_t y, bool black) { - set(x, y, (uint8_t)(black ? 1 : 0)); -} -void CBC_BarcodeMatrix::startRow() { - ++m_currentRow; -} -CBC_BarcodeRow* CBC_BarcodeMatrix::getCurrentRow() { - return m_matrix[m_currentRow]; -} -int32_t CBC_BarcodeMatrix::getWidth() { - return m_outWidth; -} -int32_t CBC_BarcodeMatrix::getHeight() { - return m_outHeight; -} -CFX_ArrayTemplate<uint8_t>& CBC_BarcodeMatrix::getMatrix() { - return getScaledMatrix(1, 1); -} -CFX_ArrayTemplate<uint8_t>& CBC_BarcodeMatrix::getScaledMatrix(int32_t scale) { - return getScaledMatrix(scale, scale); -} -CFX_ArrayTemplate<uint8_t>& CBC_BarcodeMatrix::getScaledMatrix(int32_t xScale, - int32_t yScale) { - int32_t yMax = m_height * yScale; - CFX_ArrayTemplate<uint8_t> bytearray; - bytearray.Copy(m_matrix[0]->getScaledRow(xScale)); - int32_t xMax = bytearray.GetSize(); - m_matrixOut.SetSize(xMax * yMax); - m_outWidth = xMax; - m_outHeight = yMax; - int32_t k = 0; - for (int32_t i = 0; i < yMax; i++) { - if (i != 0) { - bytearray.Copy(m_matrix[i / yScale]->getScaledRow(xScale)); - } - k = i * xMax; - for (int32_t l = 0; l < xMax; l++) { - m_matrixOut[k + l] = bytearray.GetAt(l); - } - } - return m_matrixOut; -} diff --git a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h b/xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h deleted file mode 100644 index 95ab547c9020f1e28551d633bb933e2046e49ff3..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417BARCODEMATRIX_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417BARCODEMATRIX_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_BarcodeRow; - -class CBC_BarcodeMatrix { - public: - CBC_BarcodeMatrix(); - CBC_BarcodeMatrix(int32_t height, int32_t width); - virtual ~CBC_BarcodeMatrix(); - - void set(int32_t x, int32_t y, uint8_t value); - void setMatrix(int32_t x, int32_t y, bool black); - void startRow(); - CBC_BarcodeRow* getCurrentRow(); - CFX_ArrayTemplate<uint8_t>& getMatrix(); - CFX_ArrayTemplate<uint8_t>& getScaledMatrix(int32_t scale); - CFX_ArrayTemplate<uint8_t>& getScaledMatrix(int32_t xScale, int32_t yScale); - int32_t getWidth(); - int32_t getHeight(); - - private: - CFX_ArrayTemplate<CBC_BarcodeRow*> m_matrix; - CFX_ArrayTemplate<uint8_t> m_matrixOut; - int32_t m_currentRow; - int32_t m_height; - int32_t m_width; - int32_t m_outWidth; - int32_t m_outHeight; -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417BARCODEMATRIX_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp b/xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp deleted file mode 100644 index 243af70d9432649252622200e3118e0e1618d4b6..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h" - -CBC_BarcodeRow::CBC_BarcodeRow(int32_t width) { - m_row.SetSize(width); - m_currentLocation = 0; -} -CBC_BarcodeRow::~CBC_BarcodeRow() { - m_output.RemoveAll(); - m_row.RemoveAll(); -} -void CBC_BarcodeRow::set(int32_t x, uint8_t value) { - m_row.SetAt(x, value); -} -void CBC_BarcodeRow::set(int32_t x, bool black) { - m_row.SetAt(x, (uint8_t)(black ? 1 : 0)); -} -void CBC_BarcodeRow::addBar(bool black, int32_t width) { - for (int32_t ii = 0; ii < width; ii++) { - set(m_currentLocation++, black); - } -} -CFX_ArrayTemplate<uint8_t>& CBC_BarcodeRow::getRow() { - return m_row; -} -CFX_ArrayTemplate<uint8_t>& CBC_BarcodeRow::getScaledRow(int32_t scale) { - m_output.SetSize(m_row.GetSize() * scale); - for (int32_t i = 0; i < m_output.GetSize(); i++) { - m_output[i] = (m_row[i / scale]); - } - return m_output; -} diff --git a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h b/xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h deleted file mode 100644 index 7d9d19cb5619543e031cbe5309031cde54311911..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417BarcodeRow.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417BARCODEROW_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417BARCODEROW_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_BarcodeRow { - public: - explicit CBC_BarcodeRow(int32_t width); - virtual ~CBC_BarcodeRow(); - - void set(int32_t x, uint8_t value); - void set(int32_t x, bool black); - void addBar(bool black, int32_t width); - CFX_ArrayTemplate<uint8_t>& getRow(); - CFX_ArrayTemplate<uint8_t>& getScaledRow(int32_t scale); - - private: - CFX_ArrayTemplate<uint8_t> m_row; - CFX_ArrayTemplate<uint8_t> m_output; - int32_t m_currentLocation; -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417BARCODEROW_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417Compaction.h b/xfa/fxbarcode/pdf417/BC_PDF417Compaction.h deleted file mode 100644 index 2df0fce30331ba6c9dd28c2f28602a9cfc82f685..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417Compaction.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417COMPACTION_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417COMPACTION_H_ - -class CBC_Compaction; -enum Compaction { AUTO, TEXT, BYTES, NUMERIC }; -class CBC_Compaction { - public: - CBC_Compaction(); - virtual ~CBC_Compaction(); -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417COMPACTION_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h b/xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h deleted file mode 100644 index 6822ae4e114a391b3e835bfb32d9dc54a0dbf9ff..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417ErrorCorrection.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417ERRORCORRECTION_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417ERRORCORRECTION_H_ - -#include <stdint.h> - -#include "core/fxcrt/fx_string.h" - -class CBC_PDF417ErrorCorrection { - public: - CBC_PDF417ErrorCorrection(); - virtual ~CBC_PDF417ErrorCorrection(); - - static int32_t getErrorCorrectionCodewordCount(int32_t errorCorrectionLevel, - int32_t& e); - static int32_t getRecommendedMinimumErrorCorrectionLevel(int32_t n, - int32_t& e); - static CFX_WideString generateErrorCorrection(CFX_WideString dataCodewords, - int32_t errorCorrectionLevel, - int32_t& e); -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417ERRORCORRECTION_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp b/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp deleted file mode 100644 index 08a40c51b3ba574eed67bca58836d09eba85ba37..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.cpp +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h" - -#include "third_party/bigint/BigIntegerLibrary.hh" -#include "xfa/fxbarcode/BC_UtilCodingConvert.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h" -#include "xfa/fxbarcode/utils.h" - -#define SUBMODE_ALPHA 0 -#define SUBMODE_LOWER 1 -#define SUBMODE_MIXED 2 - -int32_t CBC_PDF417HighLevelEncoder::TEXT_COMPACTION = 0; -int32_t CBC_PDF417HighLevelEncoder::BYTE_COMPACTION = 1; -int32_t CBC_PDF417HighLevelEncoder::NUMERIC_COMPACTION = 2; -int32_t CBC_PDF417HighLevelEncoder::SUBMODE_PUNCTUATION = 3; -int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_TEXT = 900; -int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_BYTE_PADDED = 901; -int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_NUMERIC = 902; -int32_t CBC_PDF417HighLevelEncoder::SHIFT_TO_BYTE = 913; -int32_t CBC_PDF417HighLevelEncoder::LATCH_TO_BYTE = 924; -uint8_t CBC_PDF417HighLevelEncoder::TEXT_MIXED_RAW[] = { - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, - 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0}; -uint8_t CBC_PDF417HighLevelEncoder::TEXT_PUNCTUATION_RAW[] = { - 59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, - 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0}; -int32_t CBC_PDF417HighLevelEncoder::MIXED[128] = {0}; -int32_t CBC_PDF417HighLevelEncoder::PUNCTUATION[128] = {0}; - -void CBC_PDF417HighLevelEncoder::Initialize() { - Inverse(); -} - -void CBC_PDF417HighLevelEncoder::Finalize() {} - -CFX_WideString CBC_PDF417HighLevelEncoder::encodeHighLevel( - CFX_WideString wideMsg, - Compaction compaction, - int32_t& e) { - CFX_ByteString bytes; - CBC_UtilCodingConvert::UnicodeToUTF8(wideMsg, bytes); - CFX_WideString msg; - int32_t len = bytes.GetLength(); - for (int32_t i = 0; i < len; i++) { - FX_WCHAR ch = (FX_WCHAR)(bytes.GetAt(i) & 0xff); - if (ch == '?' && bytes.GetAt(i) != '?') { - e = BCExceptionCharactersOutsideISO88591Encoding; - return CFX_WideString(); - } - msg += ch; - } - CFX_ArrayTemplate<uint8_t> byteArr; - for (int32_t k = 0; k < bytes.GetLength(); k++) { - byteArr.Add(bytes.GetAt(k)); - } - CFX_WideString sb; - len = msg.GetLength(); - int32_t p = 0; - int32_t textSubMode = SUBMODE_ALPHA; - if (compaction == TEXT) { - encodeText(msg, p, len, sb, textSubMode); - } else if (compaction == BYTES) { - encodeBinary(&byteArr, p, byteArr.GetSize(), BYTE_COMPACTION, sb); - } else if (compaction == NUMERIC) { - sb += (FX_WCHAR)LATCH_TO_NUMERIC; - encodeNumeric(msg, p, len, sb); - } else { - int32_t encodingMode = LATCH_TO_TEXT; - while (p < len) { - int32_t n = determineConsecutiveDigitCount(msg, p); - if (n >= 13) { - sb += (FX_WCHAR)LATCH_TO_NUMERIC; - encodingMode = NUMERIC_COMPACTION; - textSubMode = SUBMODE_ALPHA; - encodeNumeric(msg, p, n, sb); - p += n; - } else { - int32_t t = determineConsecutiveTextCount(msg, p); - if (t >= 5 || n == len) { - if (encodingMode != TEXT_COMPACTION) { - sb += (FX_WCHAR)LATCH_TO_TEXT; - encodingMode = TEXT_COMPACTION; - textSubMode = SUBMODE_ALPHA; - } - textSubMode = encodeText(msg, p, t, sb, textSubMode); - p += t; - } else { - int32_t b = determineConsecutiveBinaryCount(msg, &byteArr, p, e); - if (e != BCExceptionNO) - return L" "; - if (b == 0) { - b = 1; - } - if (b == 1 && encodingMode == TEXT_COMPACTION) { - encodeBinary(&byteArr, p, 1, TEXT_COMPACTION, sb); - } else { - encodeBinary(&byteArr, p, b, encodingMode, sb); - encodingMode = BYTE_COMPACTION; - textSubMode = SUBMODE_ALPHA; - } - p += b; - } - } - } - } - return sb; -} - -void CBC_PDF417HighLevelEncoder::Inverse() { - for (size_t l = 0; l < FX_ArraySize(MIXED); ++l) - MIXED[l] = -1; - - for (uint8_t i = 0; i < FX_ArraySize(TEXT_MIXED_RAW); ++i) { - uint8_t b = TEXT_MIXED_RAW[i]; - if (b != 0) - MIXED[b] = i; - } - - for (size_t l = 0; l < FX_ArraySize(PUNCTUATION); ++l) - PUNCTUATION[l] = -1; - - for (uint8_t i = 0; i < FX_ArraySize(TEXT_PUNCTUATION_RAW); ++i) { - uint8_t b = TEXT_PUNCTUATION_RAW[i]; - if (b != 0) - PUNCTUATION[b] = i; - } -} - -int32_t CBC_PDF417HighLevelEncoder::encodeText(CFX_WideString msg, - int32_t startpos, - int32_t count, - CFX_WideString& sb, - int32_t initialSubmode) { - CFX_WideString tmp; - int32_t submode = initialSubmode; - int32_t idx = 0; - while (true) { - FX_WCHAR ch = msg.GetAt(startpos + idx); - switch (submode) { - case SUBMODE_ALPHA: - if (isAlphaUpper(ch)) { - if (ch == ' ') { - tmp += (FX_WCHAR)26; - } else { - tmp += (FX_WCHAR)(ch - 65); - } - } else { - if (isAlphaLower(ch)) { - submode = SUBMODE_LOWER; - tmp += (FX_WCHAR)27; - continue; - } else if (isMixed(ch)) { - submode = SUBMODE_MIXED; - tmp += (FX_WCHAR)28; - continue; - } else { - tmp += (FX_WCHAR)29; - tmp += PUNCTUATION[ch]; - break; - } - } - break; - case SUBMODE_LOWER: - if (isAlphaLower(ch)) { - if (ch == ' ') { - tmp += (FX_WCHAR)26; - } else { - tmp += (FX_WCHAR)(ch - 97); - } - } else { - if (isAlphaUpper(ch)) { - tmp += (FX_WCHAR)27; - tmp += (FX_WCHAR)(ch - 65); - break; - } else if (isMixed(ch)) { - submode = SUBMODE_MIXED; - tmp += (FX_WCHAR)28; - continue; - } else { - tmp += (FX_WCHAR)29; - tmp += PUNCTUATION[ch]; - break; - } - } - break; - case SUBMODE_MIXED: - if (isMixed(ch)) { - tmp += MIXED[ch]; - } else { - if (isAlphaUpper(ch)) { - submode = SUBMODE_ALPHA; - tmp += (FX_WCHAR)28; - continue; - } else if (isAlphaLower(ch)) { - submode = SUBMODE_LOWER; - tmp += (FX_WCHAR)27; - continue; - } else { - if (startpos + idx + 1 < count) { - FX_WCHAR next = msg.GetAt(startpos + idx + 1); - if (isPunctuation(next)) { - submode = SUBMODE_PUNCTUATION; - tmp += (FX_WCHAR)25; - continue; - } - } - tmp += (FX_WCHAR)29; - tmp += PUNCTUATION[ch]; - } - } - break; - default: - if (isPunctuation(ch)) { - tmp += PUNCTUATION[ch]; - } else { - submode = SUBMODE_ALPHA; - tmp += (FX_WCHAR)29; - continue; - } - } - idx++; - if (idx >= count) { - break; - } - } - FX_WCHAR h = 0; - int32_t len = tmp.GetLength(); - for (int32_t i = 0; i < len; i++) { - bool odd = (i % 2) != 0; - if (odd) { - h = (FX_WCHAR)((h * 30) + tmp.GetAt(i)); - sb += h; - } else { - h = tmp.GetAt(i); - } - } - if ((len % 2) != 0) { - sb += (FX_WCHAR)((h * 30) + 29); - } - return submode; -} -void CBC_PDF417HighLevelEncoder::encodeBinary(CFX_ArrayTemplate<uint8_t>* bytes, - int32_t startpos, - int32_t count, - int32_t startmode, - CFX_WideString& sb) { - if (count == 1 && startmode == TEXT_COMPACTION) { - sb += (FX_WCHAR)SHIFT_TO_BYTE; - } - int32_t idx = startpos; - int32_t i = 0; - if (count >= 6) { - sb += (FX_WCHAR)LATCH_TO_BYTE; - FX_WCHAR chars[5]; - while ((startpos + count - idx) >= 6) { - int64_t t = 0; - for (i = 0; i < 6; i++) { - t <<= 8; - t += bytes->GetAt(idx + i) & 0xff; - } - for (i = 0; i < 5; i++) { - chars[i] = (FX_WCHAR)(t % 900); - t /= 900; - } - for (i = 4; i >= 0; i--) { - sb += (chars[i]); - } - idx += 6; - } - } - if (idx < startpos + count) { - sb += (FX_WCHAR)LATCH_TO_BYTE_PADDED; - } - for (i = idx; i < startpos + count; i++) { - int32_t ch = bytes->GetAt(i) & 0xff; - sb += (FX_WCHAR)ch; - } -} -void CBC_PDF417HighLevelEncoder::encodeNumeric(CFX_WideString msg, - int32_t startpos, - int32_t count, - CFX_WideString& sb) { - int32_t idx = 0; - BigInteger num900 = 900; - while (idx < count) { - CFX_WideString tmp; - int32_t len = 44 < count - idx ? 44 : count - idx; - CFX_ByteString part = - ((FX_WCHAR)'1' + msg.Mid(startpos + idx, len)).UTF8Encode(); - BigInteger bigint = stringToBigInteger(part.c_str()); - do { - int32_t c = (bigint % num900).toInt(); - tmp += (FX_WCHAR)(c); - bigint = bigint / num900; - } while (!bigint.isZero()); - for (int32_t i = tmp.GetLength() - 1; i >= 0; i--) { - sb += tmp.GetAt(i); - } - idx += len; - } -} -bool CBC_PDF417HighLevelEncoder::isDigit(FX_WCHAR ch) { - return ch >= '0' && ch <= '9'; -} -bool CBC_PDF417HighLevelEncoder::isAlphaUpper(FX_WCHAR ch) { - return ch == ' ' || (ch >= 'A' && ch <= 'Z'); -} -bool CBC_PDF417HighLevelEncoder::isAlphaLower(FX_WCHAR ch) { - return ch == ' ' || (ch >= 'a' && ch <= 'z'); -} -bool CBC_PDF417HighLevelEncoder::isMixed(FX_WCHAR ch) { - return MIXED[ch] != -1; -} -bool CBC_PDF417HighLevelEncoder::isPunctuation(FX_WCHAR ch) { - return PUNCTUATION[ch] != -1; -} -bool CBC_PDF417HighLevelEncoder::isText(FX_WCHAR ch) { - return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126); -} -int32_t CBC_PDF417HighLevelEncoder::determineConsecutiveDigitCount( - CFX_WideString msg, - int32_t startpos) { - int32_t count = 0; - int32_t len = msg.GetLength(); - int32_t idx = startpos; - if (idx < len) { - FX_WCHAR ch = msg.GetAt(idx); - while (isDigit(ch) && idx < len) { - count++; - idx++; - if (idx < len) { - ch = msg.GetAt(idx); - } - } - } - return count; -} -int32_t CBC_PDF417HighLevelEncoder::determineConsecutiveTextCount( - CFX_WideString msg, - int32_t startpos) { - int32_t len = msg.GetLength(); - int32_t idx = startpos; - while (idx < len) { - FX_WCHAR ch = msg.GetAt(idx); - int32_t numericCount = 0; - while (numericCount < 13 && isDigit(ch) && idx < len) { - numericCount++; - idx++; - if (idx < len) { - ch = msg.GetAt(idx); - } - } - if (numericCount >= 13) { - return idx - startpos - numericCount; - } - if (numericCount > 0) { - continue; - } - ch = msg.GetAt(idx); - if (!isText(ch)) { - break; - } - idx++; - } - return idx - startpos; -} -int32_t CBC_PDF417HighLevelEncoder::determineConsecutiveBinaryCount( - CFX_WideString msg, - CFX_ArrayTemplate<uint8_t>* bytes, - int32_t startpos, - int32_t& e) { - int32_t len = msg.GetLength(); - int32_t idx = startpos; - while (idx < len) { - FX_WCHAR ch = msg.GetAt(idx); - int32_t numericCount = 0; - while (numericCount < 13 && isDigit(ch)) { - numericCount++; - int32_t i = idx + numericCount; - if (i >= len) { - break; - } - ch = msg.GetAt(i); - } - if (numericCount >= 13) { - return idx - startpos; - } - int32_t textCount = 0; - while (textCount < 5 && isText(ch)) { - textCount++; - int32_t i = idx + textCount; - if (i >= len) { - break; - } - ch = msg.GetAt(i); - } - if (textCount >= 5) { - return idx - startpos; - } - ch = msg.GetAt(idx); - if (bytes->GetAt(idx) == 63 && ch != '?') { - e = BCExceptionNonEncodableCharacterDetected; - return -1; - } - idx++; - } - return idx - startpos; -} diff --git a/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h b/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h deleted file mode 100644 index 38382c891c41b67029e1b4e97d66b877a4a74699..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417HIGHLEVELENCODER_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417HIGHLEVELENCODER_H_ - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_string.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h" - -class CBC_PDF417HighLevelEncoder { - public: - static CFX_WideString encodeHighLevel(CFX_WideString msg, - Compaction compaction, - int32_t& e); - static void Inverse(); - static void Initialize(); - static void Finalize(); - - private: - static int32_t TEXT_COMPACTION; - static int32_t BYTE_COMPACTION; - static int32_t NUMERIC_COMPACTION; - static int32_t SUBMODE_PUNCTUATION; - static int32_t LATCH_TO_TEXT; - static int32_t LATCH_TO_BYTE_PADDED; - static int32_t LATCH_TO_NUMERIC; - static int32_t SHIFT_TO_BYTE; - static int32_t LATCH_TO_BYTE; - static uint8_t TEXT_MIXED_RAW[]; - static uint8_t TEXT_PUNCTUATION_RAW[]; - static int32_t MIXED[128]; - static int32_t PUNCTUATION[128]; - static int32_t encodeText(CFX_WideString msg, - int32_t startpos, - int32_t count, - CFX_WideString& sb, - int32_t initialSubmode); - static void encodeBinary(CFX_ArrayTemplate<uint8_t>* bytes, - int32_t startpos, - int32_t count, - int32_t startmode, - CFX_WideString& sb); - static void encodeNumeric(CFX_WideString msg, - int32_t startpos, - int32_t count, - CFX_WideString& sb); - static bool isDigit(FX_WCHAR ch); - static bool isAlphaUpper(FX_WCHAR ch); - static bool isAlphaLower(FX_WCHAR ch); - static bool isMixed(FX_WCHAR ch); - static bool isPunctuation(FX_WCHAR ch); - static bool isText(FX_WCHAR ch); - static int32_t determineConsecutiveDigitCount(CFX_WideString msg, - int32_t startpos); - static int32_t determineConsecutiveTextCount(CFX_WideString msg, - int32_t startpos); - static int32_t determineConsecutiveBinaryCount( - CFX_WideString msg, - CFX_ArrayTemplate<uint8_t>* bytes, - int32_t startpos, - int32_t& e); - - friend class PDF417HighLevelEncoder_EncodeNumeric_Test; - friend class PDF417HighLevelEncoder_EncodeBinary_Test; - friend class PDF417HighLevelEncoder_EncodeText_Test; - friend class PDF417HighLevelEncoder_ConsecutiveDigitCount_Test; - friend class PDF417HighLevelEncoder_ConsecutiveTextCount_Test; - friend class PDF417HighLevelEncoder_ConsecutiveBinaryCount_Test; -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417HIGHLEVELENCODER_H_ diff --git a/xfa/fxbarcode/pdf417/BC_PDF417Writer.cpp b/xfa/fxbarcode/pdf417/BC_PDF417Writer.cpp deleted file mode 100644 index 2c75a14a8073f473a06936ec30b834d4d17ccf57..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417Writer.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_TwoDimWriter.h" -#include "xfa/fxbarcode/common/BC_CommonBitArray.h" -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417BarcodeMatrix.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417Compaction.h" -#include "xfa/fxbarcode/pdf417/BC_PDF417Writer.h" - -CBC_PDF417Writer::CBC_PDF417Writer() { - m_bFixedSize = false; -} -CBC_PDF417Writer::~CBC_PDF417Writer() { - m_bTruncated = true; -} -bool CBC_PDF417Writer::SetErrorCorrectionLevel(int32_t level) { - if (level < 0 || level > 8) { - return false; - } - m_iCorrectLevel = level; - return true; -} -void CBC_PDF417Writer::SetTruncated(bool truncated) { - m_bTruncated = truncated; -} -uint8_t* CBC_PDF417Writer::Encode(const CFX_WideString& contents, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - CBC_PDF417 encoder; - int32_t col = (m_Width / m_ModuleWidth - 69) / 17; - int32_t row = m_Height / (m_ModuleWidth * 20); - if (row >= 3 && row <= 90 && col >= 1 && col <= 30) { - encoder.setDimensions(col, col, row, row); - } else if (col >= 1 && col <= 30) { - encoder.setDimensions(col, col, 90, 3); - } else if (row >= 3 && row <= 90) { - encoder.setDimensions(30, 1, row, row); - } - encoder.generateBarcodeLogic(contents, m_iCorrectLevel, e); - if (e != BCExceptionNO) - return nullptr; - int32_t lineThickness = 2; - int32_t aspectRatio = 4; - CBC_BarcodeMatrix* barcodeMatrix = encoder.getBarcodeMatrix(); - CFX_ArrayTemplate<uint8_t> originalScale; - originalScale.Copy(barcodeMatrix->getScaledMatrix( - lineThickness, aspectRatio * lineThickness)); - int32_t width = outWidth; - int32_t height = outHeight; - outWidth = barcodeMatrix->getWidth(); - outHeight = barcodeMatrix->getHeight(); - bool rotated = false; - if ((height > width) ^ (outWidth < outHeight)) { - rotateArray(originalScale, outHeight, outWidth); - rotated = true; - int32_t temp = outHeight; - outHeight = outWidth; - outWidth = temp; - } - int32_t scaleX = width / outWidth; - int32_t scaleY = height / outHeight; - int32_t scale; - if (scaleX < scaleY) { - scale = scaleX; - } else { - scale = scaleY; - } - if (scale > 1) { - originalScale.RemoveAll(); - originalScale.Copy(barcodeMatrix->getScaledMatrix( - scale * lineThickness, scale * aspectRatio * lineThickness)); - if (rotated) { - rotateArray(originalScale, outHeight, outWidth); - int32_t temp = outHeight; - outHeight = outWidth; - outWidth = temp; - } - } - uint8_t* result = FX_Alloc2D(uint8_t, outHeight, outWidth); - FXSYS_memcpy(result, originalScale.GetData(), outHeight * outWidth); - return result; -} -void CBC_PDF417Writer::rotateArray(CFX_ArrayTemplate<uint8_t>& bitarray, - int32_t height, - int32_t width) { - CFX_ArrayTemplate<uint8_t> temp; - temp.Copy(bitarray); - for (int32_t ii = 0; ii < height; ii++) { - int32_t inverseii = height - ii - 1; - for (int32_t jj = 0; jj < width; jj++) { - bitarray[jj * height + inverseii] = temp[ii * width + jj]; - } - } -} diff --git a/xfa/fxbarcode/pdf417/BC_PDF417Writer.h b/xfa/fxbarcode/pdf417/BC_PDF417Writer.h deleted file mode 100644 index 420c441bc909173645b9f60af9f5bbac12723a5c..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/pdf417/BC_PDF417Writer.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_PDF417_BC_PDF417WRITER_H_ -#define XFA_FXBARCODE_PDF417_BC_PDF417WRITER_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxbarcode/BC_TwoDimWriter.h" - -class CBC_PDF417Writer : public CBC_TwoDimWriter { - public: - CBC_PDF417Writer(); - ~CBC_PDF417Writer() override; - - uint8_t* Encode(const CFX_WideString& contents, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e); - - // CBC_TwoDimWriter - bool SetErrorCorrectionLevel(int32_t level) override; - - void SetTruncated(bool truncated); - - private: - void rotateArray(CFX_ArrayTemplate<uint8_t>& bitarray, - int32_t width, - int32_t height); - bool m_bTruncated; -}; - -#endif // XFA_FXBARCODE_PDF417_BC_PDF417WRITER_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCodeWriter.cpp b/xfa/fxbarcode/qrcode/BC_QRCodeWriter.cpp deleted file mode 100644 index 8a6499cbb7c7bd93a9ded73e1397fbb584b860f4..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCodeWriter.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/BC_TwoDimWriter.h" -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" -#include "xfa/fxbarcode/qrcode/BC_QRCodeWriter.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderEncoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMode.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h" - -CBC_QRCodeWriter::CBC_QRCodeWriter() { - m_bFixedSize = true; - m_iCorrectLevel = 1; - m_iVersion = 0; -} - -CBC_QRCodeWriter::~CBC_QRCodeWriter() {} - -void CBC_QRCodeWriter::ReleaseAll() { - delete CBC_ReedSolomonGF256::QRCodeField; - CBC_ReedSolomonGF256::QRCodeField = nullptr; - delete CBC_ReedSolomonGF256::DataMatrixField; - CBC_ReedSolomonGF256::DataMatrixField = nullptr; - CBC_QRCoderMode::Destroy(); - CBC_QRCoderErrorCorrectionLevel::Destroy(); - CBC_QRCoderVersion::Destroy(); -} - -bool CBC_QRCodeWriter::SetVersion(int32_t version) { - if (version < 0 || version > 40) { - return false; - } - m_iVersion = version; - return true; -} - -bool CBC_QRCodeWriter::SetErrorCorrectionLevel(int32_t level) { - if (level < 0 || level > 3) { - return false; - } - m_iCorrectLevel = level; - return true; -} - -uint8_t* CBC_QRCodeWriter::Encode(const CFX_WideString& contents, - int32_t ecLevel, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - CBC_QRCoderErrorCorrectionLevel* ec = nullptr; - switch (ecLevel) { - case 0: - ec = CBC_QRCoderErrorCorrectionLevel::L; - break; - case 1: - ec = CBC_QRCoderErrorCorrectionLevel::M; - break; - case 2: - ec = CBC_QRCoderErrorCorrectionLevel::Q; - break; - case 3: - ec = CBC_QRCoderErrorCorrectionLevel::H; - break; - default: { - e = BCExceptionUnSupportEclevel; - return nullptr; - } - } - CBC_QRCoder qr; - if (m_iVersion > 0 && m_iVersion < 41) { - CFX_ByteString byteStr = contents.UTF8Encode(); - CBC_QRCoderEncoder::Encode(byteStr, ec, &qr, e, m_iVersion); - } else { - CBC_QRCoderEncoder::Encode(contents, ec, &qr, e); - } - if (e != BCExceptionNO) - return nullptr; - outWidth = qr.GetMatrixWidth(); - outHeight = qr.GetMatrixWidth(); - uint8_t* result = FX_Alloc2D(uint8_t, outWidth, outHeight); - FXSYS_memcpy(result, qr.GetMatrix()->GetArray(), outWidth * outHeight); - return result; -} - -uint8_t* CBC_QRCodeWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e) { - return nullptr; -} - -uint8_t* CBC_QRCodeWriter::Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e) { - return nullptr; -} diff --git a/xfa/fxbarcode/qrcode/BC_QRCodeWriter.h b/xfa/fxbarcode/qrcode/BC_QRCodeWriter.h deleted file mode 100644 index 5585fa55c152325d92b3e0a4311d5245fa2a2e79..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCodeWriter.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ - -#include "xfa/fxbarcode/BC_TwoDimWriter.h" - -class CBC_TwoDimWriter; -class CBC_QRCodeWriter : public CBC_TwoDimWriter { - public: - CBC_QRCodeWriter(); - ~CBC_QRCodeWriter() override; - - uint8_t* Encode(const CFX_WideString& contents, - int32_t ecLevel, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e); - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t hints, - int32_t& e); - uint8_t* Encode(const CFX_ByteString& contents, - BCFORMAT format, - int32_t& outWidth, - int32_t& outHeight, - int32_t& e); - bool SetVersion(int32_t version); - - // CBC_TwoDimWriter - bool SetErrorCorrectionLevel(int32_t level) override; - - static void ReleaseAll(); - - private: - int32_t m_iVersion; -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODEWRITER_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderBitVector.cpp b/xfa/fxbarcode/qrcode/BC_QRCoderBitVector.cpp deleted file mode 100644 index e4140a87a0c8f0f804e3bb8385ccde97e00a7b04..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderBitVector.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core/fxcrt/fx_memory.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h" -#include "xfa/fxbarcode/utils.h" - -CBC_QRCoderBitVector::CBC_QRCoderBitVector() { - m_sizeInBits = 0; - m_size = 32; -} -void CBC_QRCoderBitVector::Init() { - m_array = FX_Alloc(uint8_t, m_size); -} -CBC_QRCoderBitVector::~CBC_QRCoderBitVector() { - FX_Free(m_array); -} -void CBC_QRCoderBitVector::Clear() { - FX_Free(m_array); - m_sizeInBits = 0; - m_size = 32; - m_array = FX_Alloc(uint8_t, m_size); -} -int32_t CBC_QRCoderBitVector::At(int32_t index, int32_t& e) { - if (index < 0 || index >= m_sizeInBits) { - e = BCExceptionBadIndexException; - return 0; - } - int32_t value = m_array[index >> 3] & 0xff; - return (value >> (7 - (index & 0x7))) & 1; -} -int32_t CBC_QRCoderBitVector::sizeInBytes() { - return (m_sizeInBits + 7) >> 3; -} -int32_t CBC_QRCoderBitVector::Size() { - return m_sizeInBits; -} -void CBC_QRCoderBitVector::AppendBit(int32_t bit, int32_t& e) { - if (!(bit == 0 || bit == 1)) { - e = BCExceptionBadValueException; - return; - } - int32_t numBitsInLastByte = m_sizeInBits & 0x7; - if (numBitsInLastByte == 0) { - AppendByte(0); - m_sizeInBits -= 8; - } - m_array[m_sizeInBits >> 3] |= (bit << (7 - numBitsInLastByte)); - ++m_sizeInBits; -} -void CBC_QRCoderBitVector::AppendBits(int32_t value, - int32_t numBits, - int32_t& e) { - if (numBits < 0 || numBits > 32) { - e = BCExceptionBadNumBitsException; - return; - } - int32_t numBitsLeft = numBits; - while (numBitsLeft > 0) { - if ((m_sizeInBits & 0x7) == 0 && numBitsLeft >= 8) { - int32_t newByte = (value >> (numBitsLeft - 8)) & 0xff; - AppendByte(newByte); - numBitsLeft -= 8; - } else { - int32_t bit = (value >> (numBitsLeft - 1)) & 1; - AppendBit(bit, e); - if (e != BCExceptionNO) - return; - --numBitsLeft; - } - } -} -void CBC_QRCoderBitVector::AppendBitVector(CBC_QRCoderBitVector* bits, - int32_t& e) { - int32_t size = bits->Size(); - for (int32_t i = 0; i < size; i++) { - int32_t num = bits->At(i, e); - if (e != BCExceptionNO) - return; - AppendBit(num, e); - if (e != BCExceptionNO) - return; - } -} -void CBC_QRCoderBitVector::XOR(CBC_QRCoderBitVector* other, int32_t& e) { - if (m_sizeInBits != other->Size()) { - e = BCExceptioncanNotOperatexorOperator; - return; - } - int32_t sizeInBytes = (m_sizeInBits + 7) >> 3; - for (int32_t i = 0; i < sizeInBytes; ++i) { - m_array[i] ^= (other->GetArray())[i]; - } -} -uint8_t* CBC_QRCoderBitVector::GetArray() { - return m_array; -} -void CBC_QRCoderBitVector::AppendByte(int32_t value) { - if ((m_sizeInBits >> 3) == m_size) { - uint8_t* newArray = FX_Alloc(uint8_t, m_size << 1); - FXSYS_memcpy(newArray, m_array, m_size); - FX_Free(m_array); - m_array = newArray; - m_size = m_size << 1; - } - m_array[m_sizeInBits >> 3] = (uint8_t)value; - m_sizeInBits += 8; -} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h b/xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h deleted file mode 100644 index 7742541a06765c3a8476a90ee6fe7636a96524d5..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ - -#include <stdint.h> - -class CBC_QRCoderBitVector { - private: - int32_t m_sizeInBits; - uint8_t* m_array; - int32_t m_size; - - void AppendByte(int32_t value); - - public: - CBC_QRCoderBitVector(); - virtual ~CBC_QRCoderBitVector(); - int32_t At(int32_t index, int32_t& e); - int32_t Size(); - int32_t sizeInBytes(); - void AppendBit(int32_t bit, int32_t& e); - void AppendBits(int32_t value, int32_t numBits, int32_t& e); - void AppendBitVector(CBC_QRCoderBitVector* bits, int32_t& e); - void XOR(CBC_QRCoderBitVector* other, int32_t& e); - uint8_t* GetArray(); - void Clear(); - virtual void Init(); -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERBITVECTOR_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.h b/xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.h deleted file mode 100644 index 4259d6baddea027a4d97912f08fa87011d72904f..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ - -#include <memory> - -class CBC_CommonByteArray; - -class CBC_QRCoderBlockPair { - public: - CBC_QRCoderBlockPair(std::unique_ptr<CBC_CommonByteArray> data, - std::unique_ptr<CBC_CommonByteArray> errorCorrection); - virtual ~CBC_QRCoderBlockPair(); - - const CBC_CommonByteArray* GetDataBytes() const; - const CBC_CommonByteArray* GetErrorCorrectionBytes() const; - - private: - std::unique_ptr<CBC_CommonByteArray> m_dataBytes; - std::unique_ptr<CBC_CommonByteArray> m_errorCorrectionBytes; -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERBLOCKPAIR_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderECB.cpp b/xfa/fxbarcode/qrcode/BC_QRCoderECB.cpp deleted file mode 100644 index 2b5a2a6fef12a1fdf119d43a243d6880ddfb05e4..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderECB.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/qrcode/BC_QRCoderECB.h" - -CBC_QRCoderECB::CBC_QRCoderECB(int32_t count, int32_t dataCodeWords) { - m_dataCodeWords = dataCodeWords; - m_count = count; -} -CBC_QRCoderECB::~CBC_QRCoderECB() {} -int32_t CBC_QRCoderECB::GetCount() { - return m_count; -} -int32_t CBC_QRCoderECB::GetDataCodeWords() { - return m_dataCodeWords; -} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderECB.h b/xfa/fxbarcode/qrcode/BC_QRCoderECB.h deleted file mode 100644 index 25b0b20fe3d2fe2408c8c38e4d50456662f06b20..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderECB.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERECB_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERECB_H_ - -#include <stdint.h> - -class CBC_QRCoderECB { - private: - int32_t m_count; - int32_t m_dataCodeWords; - - public: - CBC_QRCoderECB(int32_t count, int32_t dataCodeWords); - virtual ~CBC_QRCoderECB(); - int32_t GetCount(); - int32_t GetDataCodeWords(); -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERECB_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp b/xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp deleted file mode 100644 index 507c91878e95195683e82a9df7efbb8f22ba3d06..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/qrcode/BC_QRCoderECB.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h" - -CBC_QRCoderECBlocks::CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, - CBC_QRCoderECB* ecBlocks) - : m_ecCodeWordsPerBlock(ecCodeWordsPerBlock) { - m_ecBlocksArray.Add(ecBlocks); -} - -CBC_QRCoderECBlocks::CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, - CBC_QRCoderECB* ecBlocks1, - CBC_QRCoderECB* ecBlocks2) - : m_ecCodeWordsPerBlock(ecCodeWordsPerBlock) { - m_ecBlocksArray.Add(ecBlocks1); - m_ecBlocksArray.Add(ecBlocks2); -} - -CBC_QRCoderECBlocks::~CBC_QRCoderECBlocks() { - for (int32_t i = 0; i < m_ecBlocksArray.GetSize(); i++) - delete m_ecBlocksArray[i]; -} - -int32_t CBC_QRCoderECBlocks::GetECCodeWordsPerBlock() const { - return m_ecCodeWordsPerBlock; -} - -int32_t CBC_QRCoderECBlocks::GetNumBlocks() const { - int32_t total = 0; - for (int32_t i = 0; i < m_ecBlocksArray.GetSize(); i++) - total += m_ecBlocksArray[i]->GetCount(); - - return total; -} - -int32_t CBC_QRCoderECBlocks::GetTotalECCodeWords() const { - return m_ecCodeWordsPerBlock * GetNumBlocks(); -} - -CFX_ArrayTemplate<CBC_QRCoderECB*>* CBC_QRCoderECBlocks::GetECBlocks() { - return &m_ecBlocksArray; -} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h b/xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h deleted file mode 100644 index a428f063556170a1a745a35a8541398fd5cbffbd..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_QRCoderECB; - -class CBC_QRCoderECBlocks { - public: - CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, CBC_QRCoderECB* ecBlocks); - CBC_QRCoderECBlocks(int32_t ecCodeWordsPerBlock, - CBC_QRCoderECB* ecBlocks1, - CBC_QRCoderECB* ecBlocks2); - ~CBC_QRCoderECBlocks(); - - int32_t GetECCodeWordsPerBlock() const; - int32_t GetNumBlocks() const; - int32_t GetTotalECCodeWords() const; - CFX_ArrayTemplate<CBC_QRCoderECB*>* GetECBlocks(); - - private: - int32_t m_ecCodeWordsPerBlock; - CFX_ArrayTemplate<CBC_QRCoderECB*> m_ecBlocksArray; -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERECBLOCKS_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderEncoder.cpp b/xfa/fxbarcode/qrcode/BC_QRCoderEncoder.cpp deleted file mode 100644 index 2c262f006beae545a2c0e9373d32df6b339d2621..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderEncoder.cpp +++ /dev/null @@ -1,971 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/qrcode/BC_QRCoderEncoder.h" - -#include <algorithm> -#include <memory> -#include <utility> - -#include "xfa/fxbarcode/BC_UtilCodingConvert.h" -#include "xfa/fxbarcode/common/BC_CommonByteArray.h" -#include "xfa/fxbarcode/common/BC_CommonByteMatrix.h" -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomon.h" -#include "xfa/fxbarcode/common/reedsolomon/BC_ReedSolomonGF256.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoder.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderBlockPair.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMaskUtil.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMatrixUtil.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderMode.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h" - -namespace { - -const int8_t g_alphaNumericTable[] = { - -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, - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1}; - -} // namespace - -CBC_QRCoderEncoder::CBC_QRCoderEncoder() {} - -CBC_QRCoderEncoder::~CBC_QRCoderEncoder() {} - -void CBC_QRCoderEncoder::Encode(const CFX_ByteString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t& e, - int32_t versionSpecify) { - if (versionSpecify == 0) { - EncodeWithAutoVersion(content, ecLevel, qrCode, e); - if (e != BCExceptionNO) - return; - } else if (versionSpecify > 0 && versionSpecify <= 40) { - EncodeWithSpecifyVersion(content, ecLevel, qrCode, versionSpecify, e); - if (e != BCExceptionNO) - return; - } else { - e = BCExceptionVersionMust1_40; - if (e != BCExceptionNO) - return; - } -} - -void CBC_QRCoderEncoder::AppendECI(CBC_QRCoderBitVector* bits) {} - -void CBC_QRCoderEncoder::AppendDataModeLenghInfo( - const std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>& - splitResults, - CBC_QRCoderBitVector& headerAndDataBits, - CBC_QRCoderMode* tempMode, - CBC_QRCoder* qrCode, - CFX_ByteString& encoding, - int32_t& e) { - for (const auto& splitResult : splitResults) { - tempMode = splitResult.first; - if (tempMode == CBC_QRCoderMode::sGBK) { - AppendModeInfo(tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendLengthInfo(splitResult.second.GetLength(), qrCode->GetVersion(), - tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendBytes(splitResult.second, tempMode, &headerAndDataBits, encoding, - e); - if (e != BCExceptionNO) - return; - } else if (tempMode == CBC_QRCoderMode::sBYTE) { - CFX_ArrayTemplate<uint8_t> bytes; - CBC_UtilCodingConvert::LocaleToUtf8(splitResult.second, bytes); - AppendModeInfo(tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendLengthInfo(bytes.GetSize(), qrCode->GetVersion(), tempMode, - &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - Append8BitBytes(bytes, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - } else if (tempMode == CBC_QRCoderMode::sALPHANUMERIC) { - AppendModeInfo(tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendLengthInfo(splitResult.second.GetLength(), qrCode->GetVersion(), - tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendBytes(splitResult.second, tempMode, &headerAndDataBits, encoding, - e); - if (e != BCExceptionNO) - return; - } else if (tempMode == CBC_QRCoderMode::sNUMERIC) { - AppendModeInfo(tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendLengthInfo(splitResult.second.GetLength(), qrCode->GetVersion(), - tempMode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - AppendBytes(splitResult.second, tempMode, &headerAndDataBits, encoding, - e); - if (e != BCExceptionNO) - return; - } else { - e = BCExceptionUnknown; - return; - } - } -} - -void CBC_QRCoderEncoder::SplitString( - const CFX_ByteString& content, - std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result) { - int32_t index = 0, flag = 0; - while ( - (((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) || - ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) && - (index < content.GetLength())) { - index += 2; - } - if (index != flag) { - result->push_back({CBC_QRCoderMode::sGBK, content.Mid(flag, index - flag)}); - } - flag = index; - if (index >= content.GetLength()) { - return; - } - while ( - GetAlphaNumericCode((uint8_t)content[index]) == -1 && - !(((uint8_t)content[index] >= 0xA1 && (uint8_t)content[index] <= 0xAA) || - ((uint8_t)content[index] >= 0xB0 && (uint8_t)content[index] <= 0xFA)) && - (index < content.GetLength())) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - if (IsDBCSLeadByte((uint8_t)content[index])) -#else - if ((uint8_t)content[index] > 127) -#endif - { - index += 2; - } else { - index++; - } - } - if (index != flag) { - result->push_back( - {CBC_QRCoderMode::sBYTE, content.Mid(flag, index - flag)}); - } - flag = index; - if (index >= content.GetLength()) { - return; - } - while (FXSYS_Isdigit((uint8_t)content[index]) && - (index < content.GetLength())) { - index++; - } - if (index != flag) { - result->push_back( - {CBC_QRCoderMode::sNUMERIC, content.Mid(flag, index - flag)}); - } - flag = index; - if (index >= content.GetLength()) { - return; - } - while (GetAlphaNumericCode((uint8_t)content[index]) != -1 && - (index < content.GetLength())) { - index++; - } - if (index != flag) { - result->push_back( - {CBC_QRCoderMode::sALPHANUMERIC, content.Mid(flag, index - flag)}); - } - flag = index; - if (index < content.GetLength()) - SplitString(content.Mid(index, content.GetLength() - index), result); -} - -int32_t CBC_QRCoderEncoder::GetSpanByVersion(CBC_QRCoderMode* modeFirst, - CBC_QRCoderMode* modeSecond, - int32_t versionNum, - int32_t& e) { - if (versionNum == 0) - return 0; - - if (modeFirst == CBC_QRCoderMode::sALPHANUMERIC && - modeSecond == CBC_QRCoderMode::sBYTE) { - if (versionNum >= 1 && versionNum <= 9) - return 11; - if (versionNum >= 10 && versionNum <= 26) - return 15; - if (versionNum >= 27 && versionNum <= 40) - return 16; - e = BCExceptionNoSuchVersion; - return 0; - } - if (modeSecond == CBC_QRCoderMode::sALPHANUMERIC && - modeFirst == CBC_QRCoderMode::sNUMERIC) { - if (versionNum >= 1 && versionNum <= 9) - return 13; - if (versionNum >= 10 && versionNum <= 26) - return 15; - if (versionNum >= 27 && versionNum <= 40) - return 17; - e = BCExceptionNoSuchVersion; - return 0; - } - if (modeSecond == CBC_QRCoderMode::sBYTE && - modeFirst == CBC_QRCoderMode::sNUMERIC) { - if (versionNum >= 1 && versionNum <= 9) - return 6; - if (versionNum >= 10 && versionNum <= 26) - return 8; - if (versionNum >= 27 && versionNum <= 40) - return 9; - e = BCExceptionNoSuchVersion; - return 0; - } - return -1; -} - -void CBC_QRCoderEncoder::MergeString( - std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result, - int32_t versionNum, - int32_t& e) { - size_t mergeNum = 0; - for (size_t i = 0; i + 1 < result->size(); i++) { - auto element1 = &(*result)[i]; - auto element2 = &(*result)[i + 1]; - if (element1->first == CBC_QRCoderMode::sALPHANUMERIC) { - int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sALPHANUMERIC, - CBC_QRCoderMode::sBYTE, versionNum, e); - if (e != BCExceptionNO) - return; - if (element2->first == CBC_QRCoderMode::sBYTE && - element1->second.GetLength() < tmp) { - element2->second = element1->second + element2->second; - result->erase(result->begin() + i); - i--; - mergeNum++; - } - } else if (element1->first == CBC_QRCoderMode::sBYTE) { - if (element2->first == CBC_QRCoderMode::sBYTE) { - element1->second += element2->second; - result->erase(result->begin() + i + 1); - i--; - mergeNum++; - } - } else if (element1->first == CBC_QRCoderMode::sNUMERIC) { - int32_t tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, - CBC_QRCoderMode::sBYTE, versionNum, e); - if (e != BCExceptionNO) - return; - if (element2->first == CBC_QRCoderMode::sBYTE && - element1->second.GetLength() < tmp) { - element2->second = element1->second + element2->second; - result->erase(result->begin() + i); - i--; - mergeNum++; - } - tmp = GetSpanByVersion(CBC_QRCoderMode::sNUMERIC, - CBC_QRCoderMode::sALPHANUMERIC, versionNum, e); - if (e != BCExceptionNO) - return; - if (element2->first == CBC_QRCoderMode::sALPHANUMERIC && - element1->second.GetLength() < tmp) { - element2->second = element1->second + element2->second; - result->erase(result->begin() + i); - i--; - mergeNum++; - } - } - } - if (mergeNum == 0) { - return; - } - MergeString(result, versionNum, e); - if (e != BCExceptionNO) - return; -} - -void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes, - int32_t versionNumber, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoderMode* mode, - CBC_QRCoder* qrCode, - int32_t& e) { - qrCode->SetECLevel(ecLevel); - qrCode->SetMode(mode); - CBC_QRCoderVersion* version = - CBC_QRCoderVersion::GetVersionForNumber(versionNumber, e); - if (e != BCExceptionNO) - return; - int32_t numBytes = version->GetTotalCodeWords(); - CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); - int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); - int32_t numRSBlocks = ecBlocks->GetNumBlocks(); - int32_t numDataBytes = numBytes - numEcBytes; - if (numDataBytes < numInputBytes + 3) { - e = BCExceptionCannotFindBlockInfo; - return; - } - qrCode->SetVersion(versionNumber); - qrCode->SetNumTotalBytes(numBytes); - qrCode->SetNumDataBytes(numDataBytes); - qrCode->SetNumRSBlocks(numRSBlocks); - qrCode->SetNumECBytes(numEcBytes); - qrCode->SetMatrixWidth(version->GetDimensionForVersion()); -} - -void CBC_QRCoderEncoder::EncodeWithSpecifyVersion( - const CFX_ByteString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t versionSpecify, - int32_t& e) { - CFX_ByteString encoding = "utf8"; - CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE; - std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>> splitResult; - CBC_QRCoderBitVector dataBits; - dataBits.Init(); - SplitString(content, &splitResult); - MergeString(&splitResult, versionSpecify, e); - if (e != BCExceptionNO) - return; - CBC_QRCoderMode* tempMode = nullptr; - for (const auto& result : splitResult) { - AppendBytes(result.second, result.first, &dataBits, encoding, e); - if (e != BCExceptionNO) - return; - } - int32_t numInputBytes = dataBits.sizeInBytes(); - CBC_QRCoderBitVector headerAndDataBits; - headerAndDataBits.Init(); - InitQRCode(numInputBytes, versionSpecify, ecLevel, mode, qrCode, e); - if (e != BCExceptionNO) - return; - - AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode, - encoding, e); - if (e != BCExceptionNO) - return; - - numInputBytes = headerAndDataBits.sizeInBytes(); - TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - - CBC_QRCoderBitVector finalBits; - finalBits.Init(); - InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), - qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), - &finalBits, e); - if (e != BCExceptionNO) - return; - - std::unique_ptr<CBC_CommonByteMatrix> matrix(new CBC_CommonByteMatrix( - qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth())); - matrix->Init(); - int32_t maskPattern = ChooseMaskPattern( - &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); - if (e != BCExceptionNO) - return; - - qrCode->SetMaskPattern(maskPattern); - CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), - qrCode->GetVersion(), - qrCode->GetMaskPattern(), matrix.get(), e); - if (e != BCExceptionNO) - return; - - qrCode->SetMatrix(std::move(matrix)); - if (!qrCode->IsValid()) - e = BCExceptionInvalidQRCode; -} - -void CBC_QRCoderEncoder::EncodeWithAutoVersion( - const CFX_ByteString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t& e) { - CFX_ByteString encoding = "utf8"; - CBC_QRCoderMode* mode = CBC_QRCoderMode::sBYTE; - std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>> splitResult; - CBC_QRCoderBitVector dataBits; - dataBits.Init(); - SplitString(content, &splitResult); - MergeString(&splitResult, 8, e); - if (e != BCExceptionNO) - return; - CBC_QRCoderMode* tempMode = nullptr; - for (const auto& result : splitResult) { - AppendBytes(result.second, result.first, &dataBits, encoding, e); - if (e != BCExceptionNO) - return; - } - int32_t numInputBytes = dataBits.sizeInBytes(); - InitQRCode(numInputBytes, ecLevel, mode, qrCode, e); - if (e != BCExceptionNO) - return; - CBC_QRCoderBitVector headerAndDataBits; - headerAndDataBits.Init(); - tempMode = nullptr; - int32_t versionNum = qrCode->GetVersion(); -sign: - AppendDataModeLenghInfo(splitResult, headerAndDataBits, tempMode, qrCode, - encoding, e); - if (e != BCExceptionNO) { - goto catchException; - } - numInputBytes = headerAndDataBits.sizeInBytes(); - TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); - if (e != BCExceptionNO) { - goto catchException; - } -catchException: - if (e != BCExceptionNO) { - int32_t e1 = BCExceptionNO; - InitQRCode(numInputBytes, ecLevel, mode, qrCode, e1); - if (e1 != BCExceptionNO) { - e = e1; - return; - } - versionNum++; - if (versionNum <= 40) { - headerAndDataBits.Clear(); - e = BCExceptionNO; - goto sign; - } else { - return; - } - } - - CBC_QRCoderBitVector finalBits; - finalBits.Init(); - InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), - qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), - &finalBits, e); - if (e != BCExceptionNO) - return; - - std::unique_ptr<CBC_CommonByteMatrix> matrix(new CBC_CommonByteMatrix( - qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth())); - matrix->Init(); - int32_t maskPattern = ChooseMaskPattern( - &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); - if (e != BCExceptionNO) - return; - - qrCode->SetMaskPattern(maskPattern); - CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), - qrCode->GetVersion(), - qrCode->GetMaskPattern(), matrix.get(), e); - if (e != BCExceptionNO) - return qrCode->SetMatrix(std::move(matrix)); - - if (!qrCode->IsValid()) - e = BCExceptionInvalidQRCode; -} - -void CBC_QRCoderEncoder::Encode(const CFX_WideString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t& e) { - CFX_ByteString encoding = "utf8"; - CFX_ByteString utf8Data; - CBC_UtilCodingConvert::UnicodeToUTF8(content, utf8Data); - CBC_QRCoderMode* mode = ChooseMode(utf8Data, encoding); - CBC_QRCoderBitVector dataBits; - dataBits.Init(); - AppendBytes(utf8Data, mode, &dataBits, encoding, e); - if (e != BCExceptionNO) - return; - int32_t numInputBytes = dataBits.sizeInBytes(); - InitQRCode(numInputBytes, ecLevel, mode, qrCode, e); - if (e != BCExceptionNO) - return; - CBC_QRCoderBitVector headerAndDataBits; - headerAndDataBits.Init(); - AppendModeInfo(mode, &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - int32_t numLetters = mode == CBC_QRCoderMode::sBYTE ? dataBits.sizeInBytes() - : content.GetLength(); - AppendLengthInfo(numLetters, qrCode->GetVersion(), mode, &headerAndDataBits, - e); - if (e != BCExceptionNO) - return; - headerAndDataBits.AppendBitVector(&dataBits, e); - if (e != BCExceptionNO) - return TerminateBits(qrCode->GetNumDataBytes(), &headerAndDataBits, e); - if (e != BCExceptionNO) - return; - CBC_QRCoderBitVector finalBits; - finalBits.Init(); - InterleaveWithECBytes(&headerAndDataBits, qrCode->GetNumTotalBytes(), - qrCode->GetNumDataBytes(), qrCode->GetNumRSBlocks(), - &finalBits, e); - if (e != BCExceptionNO) - return; - - std::unique_ptr<CBC_CommonByteMatrix> matrix(new CBC_CommonByteMatrix( - qrCode->GetMatrixWidth(), qrCode->GetMatrixWidth())); - matrix->Init(); - int32_t maskPattern = ChooseMaskPattern( - &finalBits, qrCode->GetECLevel(), qrCode->GetVersion(), matrix.get(), e); - if (e != BCExceptionNO) - return; - - qrCode->SetMaskPattern(maskPattern); - CBC_QRCoderMatrixUtil::BuildMatrix(&finalBits, qrCode->GetECLevel(), - qrCode->GetVersion(), - qrCode->GetMaskPattern(), matrix.get(), e); - if (e != BCExceptionNO) - return qrCode->SetMatrix(std::move(matrix)); - - if (!qrCode->IsValid()) - e = BCExceptionInvalidQRCode; -} - -void CBC_QRCoderEncoder::TerminateBits(int32_t numDataBytes, - CBC_QRCoderBitVector* bits, - int32_t& e) { - int32_t capacity = numDataBytes << 3; - if (bits->Size() > capacity) { - e = BCExceptionDataTooMany; - return; - } - for (int32_t i = 0; i < 4 && bits->Size() < capacity; ++i) { - bits->AppendBit(0, e); - if (e != BCExceptionNO) - return; - } - int32_t numBitsInLastByte = bits->Size() % 8; - if (numBitsInLastByte > 0) { - int32_t numPaddingBits = 8 - numBitsInLastByte; - for (int32_t j = 0; j < numPaddingBits; ++j) { - bits->AppendBit(0, e); - if (e != BCExceptionNO) - return; - } - } - if (bits->Size() % 8 != 0) { - e = BCExceptionDigitLengthMustBe8; - return; - } - int32_t numPaddingBytes = numDataBytes - bits->sizeInBytes(); - for (int32_t k = 0; k < numPaddingBytes; ++k) { - if (k % 2 == 0) { - bits->AppendBits(0xec, 8, e); - if (e != BCExceptionNO) - return; - } else { - bits->AppendBits(0x11, 8, e); - if (e != BCExceptionNO) - return; - } - } - if (bits->Size() != capacity) - e = BCExceptionBitsNotEqualCacity; -} - -int32_t CBC_QRCoderEncoder::ChooseMaskPattern( - CBC_QRCoderBitVector* bits, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - int32_t version, - CBC_CommonByteMatrix* matrix, - int32_t& e) { - int32_t minPenalty = 65535; - int32_t bestMaskPattern = -1; - for (int32_t maskPattern = 0; maskPattern < CBC_QRCoder::kNumMaskPatterns; - maskPattern++) { - CBC_QRCoderMatrixUtil::BuildMatrix(bits, ecLevel, version, maskPattern, - matrix, e); - if (e != BCExceptionNO) - return 0; - int32_t penalty = CalculateMaskPenalty(matrix); - if (penalty < minPenalty) { - minPenalty = penalty; - bestMaskPattern = maskPattern; - } - } - return bestMaskPattern; -} - -int32_t CBC_QRCoderEncoder::CalculateMaskPenalty(CBC_CommonByteMatrix* matrix) { - int32_t penalty = 0; - penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(matrix); - penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(matrix); - penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(matrix); - penalty += CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(matrix); - return penalty; -} - -CBC_QRCoderMode* CBC_QRCoderEncoder::ChooseMode(const CFX_ByteString& content, - CFX_ByteString encoding) { - if (encoding.Compare("SHIFT_JIS") == 0) { - return CBC_QRCoderMode::sKANJI; - } - bool hasNumeric = false; - bool hasAlphaNumeric = false; - for (int32_t i = 0; i < content.GetLength(); i++) { - if (isdigit((uint8_t)content[i])) { - hasNumeric = true; - } else if (GetAlphaNumericCode((uint8_t)content[i]) != -1) { - hasAlphaNumeric = true; - } else { - return CBC_QRCoderMode::sBYTE; - } - } - if (hasAlphaNumeric) { - return CBC_QRCoderMode::sALPHANUMERIC; - } else if (hasNumeric) { - return CBC_QRCoderMode::sNUMERIC; - } - return CBC_QRCoderMode::sBYTE; -} - -int32_t CBC_QRCoderEncoder::GetAlphaNumericCode(int32_t code) { - return (code >= 0 && code < 96) ? g_alphaNumericTable[code] : -1; -} - -void CBC_QRCoderEncoder::AppendBytes(const CFX_ByteString& content, - CBC_QRCoderMode* mode, - CBC_QRCoderBitVector* bits, - CFX_ByteString encoding, - int32_t& e) { - if (mode == CBC_QRCoderMode::sNUMERIC) - AppendNumericBytes(content, bits, e); - else if (mode == CBC_QRCoderMode::sALPHANUMERIC) - AppendAlphaNumericBytes(content, bits, e); - else if (mode == CBC_QRCoderMode::sBYTE) - Append8BitBytes(content, bits, encoding, e); - else if (mode == CBC_QRCoderMode::sKANJI) - AppendKanjiBytes(content, bits, e); - else if (mode == CBC_QRCoderMode::sGBK) - AppendGBKBytes(content, bits, e); - else - e = BCExceptionUnsupportedMode; -} - -void CBC_QRCoderEncoder::AppendNumericBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e) { - int32_t length = content.GetLength(); - int32_t i = 0; - while (i < length) { - int32_t num1 = content[i] - '0'; - if (i + 2 < length) { - int32_t num2 = content[i + 1] - '0'; - int32_t num3 = content[i + 2] - '0'; - bits->AppendBits(num1 * 100 + num2 * 10 + num3, 10, e); - if (e != BCExceptionNO) - return; - i += 3; - } else if (i + 1 < length) { - int32_t num2 = content[i + 1] - '0'; - bits->AppendBits(num1 * 10 + num2, 7, e); - if (e != BCExceptionNO) - return; - i += 2; - } else { - bits->AppendBits(num1, 4, e); - if (e != BCExceptionNO) - return; - i++; - } - } -} - -void CBC_QRCoderEncoder::AppendAlphaNumericBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e) { - int32_t length = content.GetLength(); - int32_t i = 0; - while (i < length) { - int32_t code1 = GetAlphaNumericCode(content[i]); - if (code1 == -1) { - e = BCExceptionInvalidateCharacter; - return; - } - if (i + 1 < length) { - int32_t code2 = GetAlphaNumericCode(content[i + 1]); - if (code2 == -1) { - e = BCExceptionInvalidateCharacter; - return; - } - bits->AppendBits(code1 * 45 + code2, 11, e); - if (e != BCExceptionNO) - return; - i += 2; - } else { - bits->AppendBits(code1, 6, e); - if (e != BCExceptionNO) - return; - i++; - } - } -} - -void CBC_QRCoderEncoder::AppendGBKBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e) { - int32_t length = content.GetLength(); - uint32_t value = 0; - for (int32_t i = 0; i < length; i += 2) { - value = (uint32_t)((uint8_t)content[i] << 8 | (uint8_t)content[i + 1]); - if (value <= 0xAAFE && value >= 0xA1A1) { - value -= 0xA1A1; - } else if (value <= 0xFAFE && value >= 0xB0A1) { - value -= 0xA6A1; - } else { - e = BCExceptionInvalidateCharacter; - return; - } - value = (uint32_t)((value >> 8) * 0x60) + (uint32_t)(value & 0xff); - bits->AppendBits(value, 13, e); - if (e != BCExceptionNO) - return; - } -} - -void CBC_QRCoderEncoder::Append8BitBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - CFX_ByteString encoding, - int32_t& e) { - for (int32_t i = 0; i < content.GetLength(); i++) { - bits->AppendBits(content[i], 8, e); - if (e != BCExceptionNO) - return; - } -} - -void CBC_QRCoderEncoder::Append8BitBytes(CFX_ArrayTemplate<uint8_t>& bytes, - CBC_QRCoderBitVector* bits, - int32_t& e) { - for (int32_t i = 0; i < bytes.GetSize(); i++) { - bits->AppendBits(bytes[i], 8, e); - if (e != BCExceptionNO) - return; - } -} - -void CBC_QRCoderEncoder::AppendKanjiBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e) { - CFX_ArrayTemplate<uint8_t> bytes; - uint32_t value = 0; - for (int32_t i = 0; i < bytes.GetSize(); i += 2) { - value = (uint32_t)((uint8_t)(content[i] << 8) | (uint8_t)content[i + 1]); - if (value <= 0x9ffc && value >= 0x8140) { - value -= 0x8140; - } else if (value <= 0xebbf && value >= 0xe040) { - value -= 0xc140; - } else { - e = BCExceptionInvalidateCharacter; - return; - } - value = (uint32_t)((value >> 8) * 0xc0) + (uint32_t)(value & 0xff); - bits->AppendBits(value, 13, e); - if (e != BCExceptionNO) - return; - } -} - -void CBC_QRCoderEncoder::InitQRCode(int32_t numInputBytes, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoderMode* mode, - CBC_QRCoder* qrCode, - int32_t& e) { - qrCode->SetECLevel(ecLevel); - qrCode->SetMode(mode); - for (int32_t versionNum = 1; versionNum <= 40; versionNum++) { - CBC_QRCoderVersion* version = - CBC_QRCoderVersion::GetVersionForNumber(versionNum, e); - if (e != BCExceptionNO) - return; - int32_t numBytes = version->GetTotalCodeWords(); - CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); - int32_t numEcBytes = ecBlocks->GetTotalECCodeWords(); - int32_t numRSBlocks = ecBlocks->GetNumBlocks(); - int32_t numDataBytes = numBytes - numEcBytes; - if (numDataBytes >= numInputBytes + 3) { - qrCode->SetVersion(versionNum); - qrCode->SetNumTotalBytes(numBytes); - qrCode->SetNumDataBytes(numDataBytes); - qrCode->SetNumRSBlocks(numRSBlocks); - qrCode->SetNumECBytes(numEcBytes); - qrCode->SetMatrixWidth(version->GetDimensionForVersion()); - return; - } - } - e = BCExceptionCannotFindBlockInfo; -} - -void CBC_QRCoderEncoder::AppendModeInfo(CBC_QRCoderMode* mode, - CBC_QRCoderBitVector* bits, - int32_t& e) { - bits->AppendBits(mode->GetBits(), 4, e); - if (mode == CBC_QRCoderMode::sGBK) - bits->AppendBits(1, 4, e); -} - -void CBC_QRCoderEncoder::AppendLengthInfo(int32_t numLetters, - int32_t version, - CBC_QRCoderMode* mode, - CBC_QRCoderBitVector* bits, - int32_t& e) { - CBC_QRCoderVersion* qcv = CBC_QRCoderVersion::GetVersionForNumber(version, e); - if (e != BCExceptionNO) - return; - int32_t numBits = mode->GetCharacterCountBits(qcv, e); - if (e != BCExceptionNO) - return; - if (numBits > ((1 << numBits) - 1)) { - return; - } - if (mode == CBC_QRCoderMode::sGBK) { - bits->AppendBits(numLetters / 2, numBits, e); - if (e != BCExceptionNO) - return; - } - bits->AppendBits(numLetters, numBits, e); -} - -void CBC_QRCoderEncoder::InterleaveWithECBytes(CBC_QRCoderBitVector* bits, - int32_t numTotalBytes, - int32_t numDataBytes, - int32_t numRSBlocks, - CBC_QRCoderBitVector* result, - int32_t& e) { - if (bits->sizeInBytes() != numDataBytes) { - e = BCExceptionBitsBytesNotMatch; - return; - } - int32_t dataBytesOffset = 0; - int32_t maxNumDataBytes = 0; - int32_t maxNumEcBytes = 0; - CFX_ArrayTemplate<CBC_QRCoderBlockPair*> blocks; - int32_t i; - for (i = 0; i < numRSBlocks; i++) { - int32_t numDataBytesInBlock; - int32_t numEcBytesInBlosk; - GetNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, - numRSBlocks, i, numDataBytesInBlock, - numEcBytesInBlosk); - std::unique_ptr<CBC_CommonByteArray> dataBytes(new CBC_CommonByteArray); - dataBytes->Set(bits->GetArray(), dataBytesOffset, numDataBytesInBlock); - std::unique_ptr<CBC_CommonByteArray> ecBytes( - GenerateECBytes(dataBytes.get(), numEcBytesInBlosk, e)); - if (e != BCExceptionNO) - return; - maxNumDataBytes = std::max(maxNumDataBytes, dataBytes->Size()); - maxNumEcBytes = std::max(maxNumEcBytes, ecBytes->Size()); - blocks.Add( - new CBC_QRCoderBlockPair(std::move(dataBytes), std::move(ecBytes))); - dataBytesOffset += numDataBytesInBlock; - } - if (numDataBytes != dataBytesOffset) { - e = BCExceptionBytesNotMatchOffset; - return; - } - for (int32_t x = 0; x < maxNumDataBytes; x++) { - for (int32_t j = 0; j < blocks.GetSize(); j++) { - const CBC_CommonByteArray* dataBytes = blocks[j]->GetDataBytes(); - if (x < dataBytes->Size()) { - result->AppendBits(dataBytes->At(x), 8, e); - if (e != BCExceptionNO) - return; - } - } - } - for (int32_t y = 0; y < maxNumEcBytes; y++) { - for (int32_t l = 0; l < blocks.GetSize(); l++) { - const CBC_CommonByteArray* ecBytes = blocks[l]->GetErrorCorrectionBytes(); - if (y < ecBytes->Size()) { - result->AppendBits(ecBytes->At(y), 8, e); - if (e != BCExceptionNO) - return; - } - } - } - for (int32_t k = 0; k < blocks.GetSize(); k++) { - delete blocks[k]; - } - if (numTotalBytes != result->sizeInBytes()) - e = BCExceptionSizeInBytesDiffer; -} - -void CBC_QRCoderEncoder::GetNumDataBytesAndNumECBytesForBlockID( - int32_t numTotalBytes, - int32_t numDataBytes, - int32_t numRSBlocks, - int32_t blockID, - int32_t& numDataBytesInBlock, - int32_t& numECBytesInBlock) { - if (blockID >= numRSBlocks) { - return; - } - int32_t numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; - int32_t numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; - int32_t numTotalBytesInGroup1 = numTotalBytes / numRSBlocks; - int32_t numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; - int32_t numDataBytesInGroup1 = numDataBytes / numRSBlocks; - int32_t numDataBytesInGroup2 = numDataBytesInGroup1 + 1; - int32_t numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; - int32_t numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; - if (blockID < numRsBlocksInGroup1) { - numDataBytesInBlock = numDataBytesInGroup1; - numECBytesInBlock = numEcBytesInGroup1; - } else { - numDataBytesInBlock = numDataBytesInGroup2; - numECBytesInBlock = numEcBytesInGroup2; - } -} - -CBC_CommonByteArray* CBC_QRCoderEncoder::GenerateECBytes( - CBC_CommonByteArray* dataBytes, - int32_t numEcBytesInBlock, - int32_t& e) { - int32_t numDataBytes = dataBytes->Size(); - CFX_ArrayTemplate<int32_t> toEncode; - toEncode.SetSize(numDataBytes + numEcBytesInBlock); - for (int32_t i = 0; i < numDataBytes; i++) { - toEncode[i] = (dataBytes->At(i)); - } - CBC_ReedSolomonEncoder encode(CBC_ReedSolomonGF256::QRCodeField); - encode.Init(); - encode.Encode(&toEncode, numEcBytesInBlock, e); - if (e != BCExceptionNO) - return nullptr; - CBC_CommonByteArray* ecBytes = new CBC_CommonByteArray(numEcBytesInBlock); - for (int32_t j = 0; j < numEcBytesInBlock; j++) { - ecBytes->Set(j, toEncode[numDataBytes + j]); - } - return ecBytes; -} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderEncoder.h b/xfa/fxbarcode/qrcode/BC_QRCoderEncoder.h deleted file mode 100644 index a1b078f24c9aadba3a432921ecd9114a36abe161..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderEncoder.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ - -#include <utility> -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_string.h" - -class CBC_QRCoder; -class CBC_QRCoderErrorCorrectionLevel; -class CBC_QRCoderMode; -class CBC_QRCoderBitVector; -class CBC_CommonByteArray; -class CBC_CommonByteMatrix; - -class CBC_QRCoderEncoder { - public: - CBC_QRCoderEncoder(); - virtual ~CBC_QRCoderEncoder(); - - static void Encode(const CFX_ByteString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t& e, - int32_t versionSpecify = 0); - static void Encode(const CFX_WideString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t& e); - static void EncodeWithSpecifyVersion(const CFX_ByteString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t versionSpecify, - int32_t& e); - static void EncodeWithAutoVersion(const CFX_ByteString& content, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoder* qrCode, - int32_t& e); - static CBC_QRCoderMode* ChooseMode(const CFX_ByteString& content, - CFX_ByteString encoding); - static int32_t GetAlphaNumericCode(int32_t code); - static void AppendECI(CBC_QRCoderBitVector* bits); - static void AppendBytes(const CFX_ByteString& content, - CBC_QRCoderMode* mode, - CBC_QRCoderBitVector* bits, - CFX_ByteString encoding, - int32_t& e); - static void AppendNumericBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e); - static void AppendAlphaNumericBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e); - static void Append8BitBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - CFX_ByteString encoding, - int32_t& e); - static void Append8BitBytes(CFX_ArrayTemplate<uint8_t>& bytes, - CBC_QRCoderBitVector* bits, - int32_t& e); - static void AppendKanjiBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e); - static void AppendGBKBytes(const CFX_ByteString& content, - CBC_QRCoderBitVector* bits, - int32_t& e); - static void InitQRCode(int32_t numInputBytes, - int32_t versionNumber, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoderMode* mode, - CBC_QRCoder* qrCode, - int32_t& e); - static void InitQRCode(int32_t numInputBytes, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - CBC_QRCoderMode* mode, - CBC_QRCoder* qrCode, - int32_t& e); - static void AppendModeInfo(CBC_QRCoderMode* mode, - CBC_QRCoderBitVector* bits, - int32_t& e); - static void AppendLengthInfo(int32_t numLetters, - int32_t version, - CBC_QRCoderMode* mode, - CBC_QRCoderBitVector* bits, - int32_t& e); - - static void InterleaveWithECBytes(CBC_QRCoderBitVector* bits, - int32_t numTotalBytes, - int32_t numDataBytes, - int32_t numRSBlocks, - CBC_QRCoderBitVector* result, - int32_t& e); - static void GetNumDataBytesAndNumECBytesForBlockID( - int32_t numTotalBytes, - int32_t numDataBytes, - int32_t numRSBlocks, - int32_t blockID, - int32_t& numDataBytesInBlock, - int32_t& numECBytesInBlocks); - static CBC_CommonByteArray* GenerateECBytes(CBC_CommonByteArray* dataBytes, - int32_t numEcBytesInBlock, - int32_t& e); - static int32_t ChooseMaskPattern(CBC_QRCoderBitVector* bits, - CBC_QRCoderErrorCorrectionLevel* ecLevel, - int32_t version, - CBC_CommonByteMatrix* matrix, - int32_t& e); - static int32_t CalculateMaskPenalty(CBC_CommonByteMatrix* matrix); - static void TerminateBits(int32_t numDataBytes, - CBC_QRCoderBitVector* bits, - int32_t& e); - static int32_t GetSpanByVersion(CBC_QRCoderMode* modeFirst, - CBC_QRCoderMode* modeSecond, - int32_t versionNum, - int32_t& e); - static void MergeString( - std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result, - int32_t versionNum, - int32_t& e); - static void SplitString( - const CFX_ByteString& content, - std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>* result); - static void AppendDataModeLenghInfo( - const std::vector<std::pair<CBC_QRCoderMode*, CFX_ByteString>>& - splitResult, - CBC_QRCoderBitVector& headerAndDataBits, - CBC_QRCoderMode* tempMode, - CBC_QRCoder* qrCode, - CFX_ByteString& encoding, - int32_t& e); -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERENCODER_H_ diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderVersion.cpp b/xfa/fxbarcode/qrcode/BC_QRCoderVersion.cpp deleted file mode 100644 index befdc17a98607680bf28b0c3ddb66cd455c88dd9..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderVersion.cpp +++ /dev/null @@ -1,794 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -// Original code is licensed as follows: -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderBitVector.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderECB.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderECBlocks.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h" -#include "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h" -#include "xfa/fxbarcode/utils.h" - -namespace { - -const uint8_t BITS_SET_IN_HALF_BYTE[] = {0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4}; - -int32_t NumBitsDiffering(int32_t a, int32_t b) { - a ^= b; - return BITS_SET_IN_HALF_BYTE[a & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 4) & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 8) & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 12) & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 16) & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 20) & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 24) & 0x0F] + - BITS_SET_IN_HALF_BYTE[(a >> 28) & 0x0F]; -} - -} // namespace - -const int32_t CBC_QRCoderVersion::VERSION_DECODE_INFO[] = { - 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, - 0x0E60D, 0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, - 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, 0x1B08E, - 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, - 0x2379F, 0x24B0B, 0x2542E, 0x26A64, 0x27541, 0x28C69}; - -CFX_ArrayTemplate<CBC_QRCoderVersion*>* CBC_QRCoderVersion::VERSION = nullptr; - -void CBC_QRCoderVersion::Initialize() { - VERSION = new CFX_ArrayTemplate<CBC_QRCoderVersion*>(); -} -void CBC_QRCoderVersion::Finalize() { - for (int32_t i = 0; i < VERSION->GetSize(); i++) - delete VERSION->GetAt(i); - - delete VERSION; - VERSION = nullptr; -} -CBC_QRCoderVersion::CBC_QRCoderVersion(int32_t versionNumber, - CBC_QRCoderECBlocks* ecBlocks1, - CBC_QRCoderECBlocks* ecBlocks2, - CBC_QRCoderECBlocks* ecBlocks3, - CBC_QRCoderECBlocks* ecBlocks4) { - m_versionNumber = versionNumber; - m_ecBlocksArray.Add(ecBlocks1); - m_ecBlocksArray.Add(ecBlocks2); - m_ecBlocksArray.Add(ecBlocks3); - m_ecBlocksArray.Add(ecBlocks4); - int32_t total = 0; - int32_t ecCodeWords = ecBlocks1->GetECCodeWordsPerBlock(); - CFX_ArrayTemplate<CBC_QRCoderECB*>* ecbArray = ecBlocks1->GetECBlocks(); - for (int32_t i = 0; i < ecbArray->GetSize(); i++) { - CBC_QRCoderECB* ecBlock = (*ecbArray)[i]; - total += ecBlock->GetCount() * (ecBlock->GetDataCodeWords() + ecCodeWords); - } - m_totalCodeWords = total; - switch (versionNumber) { - case 1: - break; - case 2: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(18); - break; - case 3: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(22); - break; - case 4: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - break; - case 5: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - break; - case 6: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(34); - break; - case 7: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(22); - m_alignmentPatternCenters.Add(38); - break; - case 8: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(24); - m_alignmentPatternCenters.Add(42); - break; - case 9: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(46); - break; - case 10: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(28); - m_alignmentPatternCenters.Add(50); - break; - case 11: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(54); - break; - case 12: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(32); - m_alignmentPatternCenters.Add(58); - break; - case 13: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(34); - m_alignmentPatternCenters.Add(62); - break; - case 14: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(46); - m_alignmentPatternCenters.Add(66); - break; - case 15: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(48); - m_alignmentPatternCenters.Add(70); - break; - case 16: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(50); - m_alignmentPatternCenters.Add(74); - break; - case 17: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(78); - break; - case 18: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(56); - m_alignmentPatternCenters.Add(82); - break; - case 19: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(58); - m_alignmentPatternCenters.Add(86); - break; - case 20: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(34); - m_alignmentPatternCenters.Add(62); - m_alignmentPatternCenters.Add(90); - break; - case 21: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(28); - m_alignmentPatternCenters.Add(50); - m_alignmentPatternCenters.Add(72); - m_alignmentPatternCenters.Add(94); - break; - case 22: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(50); - m_alignmentPatternCenters.Add(74); - m_alignmentPatternCenters.Add(98); - break; - case 23: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(74); - m_alignmentPatternCenters.Add(102); - break; - case 24: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(28); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(80); - m_alignmentPatternCenters.Add(106); - break; - case 25: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(32); - m_alignmentPatternCenters.Add(58); - m_alignmentPatternCenters.Add(84); - m_alignmentPatternCenters.Add(110); - break; - case 26: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(58); - m_alignmentPatternCenters.Add(86); - m_alignmentPatternCenters.Add(114); - break; - case 27: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(34); - m_alignmentPatternCenters.Add(62); - m_alignmentPatternCenters.Add(90); - m_alignmentPatternCenters.Add(118); - break; - case 28: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(50); - m_alignmentPatternCenters.Add(74); - m_alignmentPatternCenters.Add(98); - m_alignmentPatternCenters.Add(122); - break; - case 29: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(78); - m_alignmentPatternCenters.Add(102); - m_alignmentPatternCenters.Add(126); - break; - case 30: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(52); - m_alignmentPatternCenters.Add(78); - m_alignmentPatternCenters.Add(104); - m_alignmentPatternCenters.Add(130); - break; - case 31: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(56); - m_alignmentPatternCenters.Add(82); - m_alignmentPatternCenters.Add(108); - m_alignmentPatternCenters.Add(134); - break; - case 32: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(34); - m_alignmentPatternCenters.Add(60); - m_alignmentPatternCenters.Add(86); - m_alignmentPatternCenters.Add(112); - m_alignmentPatternCenters.Add(138); - break; - case 33: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(58); - m_alignmentPatternCenters.Add(86); - m_alignmentPatternCenters.Add(114); - m_alignmentPatternCenters.Add(142); - break; - case 34: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(34); - m_alignmentPatternCenters.Add(62); - m_alignmentPatternCenters.Add(90); - m_alignmentPatternCenters.Add(118); - m_alignmentPatternCenters.Add(146); - break; - case 35: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(78); - m_alignmentPatternCenters.Add(102); - m_alignmentPatternCenters.Add(126); - m_alignmentPatternCenters.Add(150); - break; - case 36: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(24); - m_alignmentPatternCenters.Add(50); - m_alignmentPatternCenters.Add(76); - m_alignmentPatternCenters.Add(102); - m_alignmentPatternCenters.Add(128); - m_alignmentPatternCenters.Add(154); - break; - case 37: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(28); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(80); - m_alignmentPatternCenters.Add(106); - m_alignmentPatternCenters.Add(132); - m_alignmentPatternCenters.Add(158); - break; - case 38: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(32); - m_alignmentPatternCenters.Add(58); - m_alignmentPatternCenters.Add(84); - m_alignmentPatternCenters.Add(110); - m_alignmentPatternCenters.Add(136); - m_alignmentPatternCenters.Add(162); - break; - case 39: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(26); - m_alignmentPatternCenters.Add(54); - m_alignmentPatternCenters.Add(82); - m_alignmentPatternCenters.Add(110); - m_alignmentPatternCenters.Add(138); - m_alignmentPatternCenters.Add(166); - break; - case 40: - m_alignmentPatternCenters.Add(6); - m_alignmentPatternCenters.Add(30); - m_alignmentPatternCenters.Add(58); - m_alignmentPatternCenters.Add(86); - m_alignmentPatternCenters.Add(114); - m_alignmentPatternCenters.Add(142); - m_alignmentPatternCenters.Add(170); - break; - } -} - -CBC_QRCoderVersion::~CBC_QRCoderVersion() { - for (int32_t i = 0; i < m_ecBlocksArray.GetSize(); ++i) - delete m_ecBlocksArray[i]; -} - -int32_t CBC_QRCoderVersion::GetVersionNumber() { - return m_versionNumber; -} -CFX_ArrayTemplate<int32_t>* CBC_QRCoderVersion::GetAlignmentPatternCenters() { - return &m_alignmentPatternCenters; -} -int32_t CBC_QRCoderVersion::GetTotalCodeWords() { - return m_totalCodeWords; -} -int32_t CBC_QRCoderVersion::GetDimensionForVersion() { - return 17 + 4 * m_versionNumber; -} -CBC_QRCoderECBlocks* CBC_QRCoderVersion::GetECBlocksForLevel( - CBC_QRCoderErrorCorrectionLevel* ecLevel) { - return m_ecBlocksArray[ecLevel->Ordinal()]; -} -CBC_QRCoderVersion* CBC_QRCoderVersion::GetProvisionalVersionForDimension( - int32_t dimension, - int32_t& e) { - if ((dimension % 4) != 1) { - e = BCExceptionRead; - return nullptr; - } - CBC_QRCoderVersion* qcv = GetVersionForNumber((dimension - 17) >> 2, e); - if (e != BCExceptionNO) - return nullptr; - return qcv; -} -CBC_QRCoderVersion* CBC_QRCoderVersion::DecodeVersionInformation( - int32_t versionBits, - int32_t& e) { - int32_t bestDifference = FXSYS_IntMax; - int32_t bestVersion = 0; - for (int32_t i = 0; i < 34; i++) { - int32_t targetVersion = VERSION_DECODE_INFO[i]; - if (targetVersion == versionBits) { - CBC_QRCoderVersion* qcv = GetVersionForNumber(i + 7, e); - if (e != BCExceptionNO) - return nullptr; - return qcv; - } - int32_t bitsDifference = NumBitsDiffering(versionBits, targetVersion); - if (bitsDifference < bestDifference) { - bestVersion = i + 7; - bestDifference = bitsDifference; - } - } - if (bestDifference <= 3) { - CBC_QRCoderVersion* qcv = GetVersionForNumber(bestVersion, e); - if (e != BCExceptionNO) - return nullptr; - return qcv; - } - return nullptr; -} -CBC_CommonBitMatrix* CBC_QRCoderVersion::BuildFunctionPattern(int32_t& e) { - int32_t dimension = GetDimensionForVersion(); - CBC_CommonBitMatrix* bitMatrix = new CBC_CommonBitMatrix(); - bitMatrix->Init(dimension); - bitMatrix->SetRegion(0, 0, 9, 9, e); - if (e != BCExceptionNO) - return nullptr; - bitMatrix->SetRegion(dimension - 8, 0, 8, 9, e); - if (e != BCExceptionNO) - return nullptr; - bitMatrix->SetRegion(0, dimension - 8, 9, 8, e); - if (e != BCExceptionNO) - return nullptr; - int32_t max = m_alignmentPatternCenters.GetSize(); - for (int32_t x = 0; x < max; x++) { - int32_t i = m_alignmentPatternCenters[x] - 2; - for (int32_t y = 0; y < max; y++) { - if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) { - continue; - } - bitMatrix->SetRegion(m_alignmentPatternCenters[y] - 2, i, 5, 5, e); - if (e != BCExceptionNO) - return nullptr; - } - } - bitMatrix->SetRegion(6, 9, 1, dimension - 17, e); - if (e != BCExceptionNO) - return nullptr; - bitMatrix->SetRegion(9, 6, dimension - 17, 1, e); - if (e != BCExceptionNO) - return nullptr; - if (m_versionNumber > 6) { - bitMatrix->SetRegion(dimension - 11, 0, 3, 6, e); - if (e != BCExceptionNO) - return nullptr; - bitMatrix->SetRegion(0, dimension - 11, 6, 3, e); - if (e != BCExceptionNO) - return nullptr; - } - return bitMatrix; -} -CBC_QRCoderVersion* CBC_QRCoderVersion::GetVersionForNumber( - int32_t versionNumber, - int32_t& e) { - if (VERSION->GetSize() == 0) { - VERSION->Add(new CBC_QRCoderVersion( - 1, new CBC_QRCoderECBlocks(7, new CBC_QRCoderECB(1, 19)), - new CBC_QRCoderECBlocks(10, new CBC_QRCoderECB(1, 16)), - new CBC_QRCoderECBlocks(13, new CBC_QRCoderECB(1, 13)), - new CBC_QRCoderECBlocks(17, new CBC_QRCoderECB(1, 9)))); - VERSION->Add(new CBC_QRCoderVersion( - 2, new CBC_QRCoderECBlocks(10, new CBC_QRCoderECB(1, 34)), - new CBC_QRCoderECBlocks(16, new CBC_QRCoderECB(1, 28)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(1, 22)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(1, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 3, new CBC_QRCoderECBlocks(15, new CBC_QRCoderECB(1, 55)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(1, 44)), - new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 17)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(2, 13)))); - VERSION->Add(new CBC_QRCoderVersion( - 4, new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(1, 80)), - new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 32)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(2, 24)), - new CBC_QRCoderECBlocks(16, new CBC_QRCoderECB(4, 9)))); - VERSION->Add(new CBC_QRCoderVersion( - 5, new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(1, 108)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(2, 43)), - new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 15), - new CBC_QRCoderECB(2, 16)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(2, 11), - new CBC_QRCoderECB(2, 12)))); - VERSION->Add(new CBC_QRCoderVersion( - 6, new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 68)), - new CBC_QRCoderECBlocks(16, new CBC_QRCoderECB(4, 27)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(4, 19)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 15)))); - VERSION->Add(new CBC_QRCoderVersion( - 7, new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(2, 78)), - new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(4, 31)), - new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 14), - new CBC_QRCoderECB(4, 15)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 13), - new CBC_QRCoderECB(1, 14)))); - VERSION->Add(new CBC_QRCoderVersion( - 8, new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(2, 97)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(2, 38), - new CBC_QRCoderECB(2, 39)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(4, 18), - new CBC_QRCoderECB(2, 19)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 14), - new CBC_QRCoderECB(2, 15)))); - VERSION->Add(new CBC_QRCoderVersion( - 9, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(2, 116)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(3, 36), - new CBC_QRCoderECB(2, 37)), - new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(4, 16), - new CBC_QRCoderECB(4, 17)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(4, 12), - new CBC_QRCoderECB(4, 13)))); - VERSION->Add(new CBC_QRCoderVersion( - 10, new CBC_QRCoderECBlocks(18, new CBC_QRCoderECB(2, 68), - new CBC_QRCoderECB(2, 69)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 43), - new CBC_QRCoderECB(1, 44)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(6, 19), - new CBC_QRCoderECB(2, 20)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(6, 15), - new CBC_QRCoderECB(2, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 11, new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(4, 81)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(1, 50), - new CBC_QRCoderECB(4, 51)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 22), - new CBC_QRCoderECB(4, 23)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(3, 12), - new CBC_QRCoderECB(8, 13)))); - VERSION->Add(new CBC_QRCoderVersion( - 12, new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(2, 92), - new CBC_QRCoderECB(2, 93)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(6, 36), - new CBC_QRCoderECB(2, 37)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 20), - new CBC_QRCoderECB(6, 21)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(7, 14), - new CBC_QRCoderECB(4, 15)))); - VERSION->Add(new CBC_QRCoderVersion( - 13, new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(4, 107)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(8, 37), - new CBC_QRCoderECB(1, 38)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(8, 20), - new CBC_QRCoderECB(4, 21)), - new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(12, 11), - new CBC_QRCoderECB(4, 12)))); - VERSION->Add(new CBC_QRCoderVersion( - 14, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(3, 115), - new CBC_QRCoderECB(1, 116)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(4, 40), - new CBC_QRCoderECB(5, 41)), - new CBC_QRCoderECBlocks(20, new CBC_QRCoderECB(11, 16), - new CBC_QRCoderECB(5, 17)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(11, 12), - new CBC_QRCoderECB(5, 13)))); - VERSION->Add(new CBC_QRCoderVersion( - 15, new CBC_QRCoderECBlocks(22, new CBC_QRCoderECB(5, 87), - new CBC_QRCoderECB(1, 88)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(5, 41), - new CBC_QRCoderECB(5, 42)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(5, 24), - new CBC_QRCoderECB(7, 25)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(11, 12), - new CBC_QRCoderECB(7, 13)))); - VERSION->Add(new CBC_QRCoderVersion( - 16, new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(5, 98), - new CBC_QRCoderECB(1, 99)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(7, 45), - new CBC_QRCoderECB(3, 46)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(15, 19), - new CBC_QRCoderECB(2, 20)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(3, 15), - new CBC_QRCoderECB(13, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 17, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(1, 107), - new CBC_QRCoderECB(5, 108)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(10, 46), - new CBC_QRCoderECB(1, 47)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(1, 22), - new CBC_QRCoderECB(15, 23)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 14), - new CBC_QRCoderECB(17, 15)))); - VERSION->Add(new CBC_QRCoderVersion( - 18, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(5, 120), - new CBC_QRCoderECB(1, 121)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(9, 43), - new CBC_QRCoderECB(4, 44)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(17, 22), - new CBC_QRCoderECB(1, 23)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 14), - new CBC_QRCoderECB(19, 15)))); - VERSION->Add(new CBC_QRCoderVersion( - 19, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(3, 113), - new CBC_QRCoderECB(4, 114)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(3, 44), - new CBC_QRCoderECB(11, 45)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(17, 21), - new CBC_QRCoderECB(4, 22)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(9, 13), - new CBC_QRCoderECB(16, 14)))); - VERSION->Add(new CBC_QRCoderVersion( - 20, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(3, 107), - new CBC_QRCoderECB(5, 108)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(3, 41), - new CBC_QRCoderECB(13, 42)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(15, 24), - new CBC_QRCoderECB(5, 25)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(15, 15), - new CBC_QRCoderECB(10, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 21, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 116), - new CBC_QRCoderECB(4, 117)), - new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(17, 42)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(17, 22), - new CBC_QRCoderECB(6, 23)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 16), - new CBC_QRCoderECB(6, 17)))); - VERSION->Add(new CBC_QRCoderVersion( - 22, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 111), - new CBC_QRCoderECB(7, 112)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(17, 46)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(7, 24), - new CBC_QRCoderECB(16, 25)), - new CBC_QRCoderECBlocks(24, new CBC_QRCoderECB(34, 13)))); - VERSION->Add(new CBC_QRCoderVersion( - 23, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(4, 121), - new CBC_QRCoderECB(5, 122)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(4, 47), - new CBC_QRCoderECB(14, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 24), - new CBC_QRCoderECB(14, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(16, 15), - new CBC_QRCoderECB(14, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 24, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(6, 117), - new CBC_QRCoderECB(4, 118)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(6, 45), - new CBC_QRCoderECB(14, 46)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 24), - new CBC_QRCoderECB(16, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(30, 16), - new CBC_QRCoderECB(2, 17)))); - VERSION->Add(new CBC_QRCoderVersion( - 25, new CBC_QRCoderECBlocks(26, new CBC_QRCoderECB(8, 106), - new CBC_QRCoderECB(4, 107)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(8, 47), - new CBC_QRCoderECB(13, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(7, 24), - new CBC_QRCoderECB(22, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(22, 15), - new CBC_QRCoderECB(13, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 26, new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(10, 114), - new CBC_QRCoderECB(2, 115)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(19, 46), - new CBC_QRCoderECB(4, 47)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(28, 22), - new CBC_QRCoderECB(6, 23)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(33, 16), - new CBC_QRCoderECB(4, 17)))); - VERSION->Add(new CBC_QRCoderVersion( - 27, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(8, 122), - new CBC_QRCoderECB(4, 123)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(22, 45), - new CBC_QRCoderECB(3, 46)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(8, 23), - new CBC_QRCoderECB(26, 24)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(12, 15), - new CBC_QRCoderECB(28, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 28, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(3, 117), - new CBC_QRCoderECB(10, 118)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(3, 45), - new CBC_QRCoderECB(23, 46)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(4, 24), - new CBC_QRCoderECB(31, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 15), - new CBC_QRCoderECB(31, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 29, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(7, 116), - new CBC_QRCoderECB(7, 117)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(21, 45), - new CBC_QRCoderECB(7, 46)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(1, 23), - new CBC_QRCoderECB(37, 24)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 15), - new CBC_QRCoderECB(26, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 30, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(5, 115), - new CBC_QRCoderECB(10, 116)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(19, 47), - new CBC_QRCoderECB(10, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(15, 24), - new CBC_QRCoderECB(25, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(23, 15), - new CBC_QRCoderECB(25, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 31, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(13, 115), - new CBC_QRCoderECB(3, 116)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(2, 46), - new CBC_QRCoderECB(29, 47)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(42, 24), - new CBC_QRCoderECB(1, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(23, 15), - new CBC_QRCoderECB(28, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 32, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(17, 115)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(10, 46), - new CBC_QRCoderECB(23, 47)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(10, 24), - new CBC_QRCoderECB(35, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 15), - new CBC_QRCoderECB(35, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 33, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(17, 115), - new CBC_QRCoderECB(1, 116)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(14, 46), - new CBC_QRCoderECB(21, 47)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(29, 24), - new CBC_QRCoderECB(19, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(11, 15), - new CBC_QRCoderECB(46, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 34, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(13, 115), - new CBC_QRCoderECB(6, 116)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(14, 46), - new CBC_QRCoderECB(23, 47)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(44, 24), - new CBC_QRCoderECB(7, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(59, 16), - new CBC_QRCoderECB(1, 17)))); - VERSION->Add(new CBC_QRCoderVersion( - 35, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(12, 121), - new CBC_QRCoderECB(7, 122)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(12, 47), - new CBC_QRCoderECB(26, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(39, 24), - new CBC_QRCoderECB(14, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(22, 15), - new CBC_QRCoderECB(41, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 36, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(6, 121), - new CBC_QRCoderECB(14, 122)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(6, 47), - new CBC_QRCoderECB(34, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(46, 24), - new CBC_QRCoderECB(10, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(2, 15), - new CBC_QRCoderECB(64, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 37, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(17, 122), - new CBC_QRCoderECB(4, 123)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(29, 46), - new CBC_QRCoderECB(14, 47)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(49, 24), - new CBC_QRCoderECB(10, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(24, 15), - new CBC_QRCoderECB(46, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 38, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(4, 122), - new CBC_QRCoderECB(18, 123)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(13, 46), - new CBC_QRCoderECB(32, 47)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(48, 24), - new CBC_QRCoderECB(14, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(42, 15), - new CBC_QRCoderECB(32, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 39, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(20, 117), - new CBC_QRCoderECB(4, 118)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(40, 47), - new CBC_QRCoderECB(7, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(43, 24), - new CBC_QRCoderECB(22, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(10, 15), - new CBC_QRCoderECB(67, 16)))); - VERSION->Add(new CBC_QRCoderVersion( - 40, new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(19, 118), - new CBC_QRCoderECB(6, 119)), - new CBC_QRCoderECBlocks(28, new CBC_QRCoderECB(18, 47), - new CBC_QRCoderECB(31, 48)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(34, 24), - new CBC_QRCoderECB(34, 25)), - new CBC_QRCoderECBlocks(30, new CBC_QRCoderECB(20, 15), - new CBC_QRCoderECB(61, 16)))); - } - if (versionNumber < 1 || versionNumber > 40) { - e = BCExceptionIllegalArgument; - return nullptr; - } - return (*VERSION)[versionNumber - 1]; -} - -void CBC_QRCoderVersion::Destroy() { - for (int32_t i = 0; i < VERSION->GetSize(); i++) - delete (*VERSION)[i]; - VERSION->RemoveAll(); -} diff --git a/xfa/fxbarcode/qrcode/BC_QRCoderVersion.h b/xfa/fxbarcode/qrcode/BC_QRCoderVersion.h deleted file mode 100644 index 030dd512a0a47cd83560dd8e8bd35a2da3059669..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/qrcode/BC_QRCoderVersion.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ -#define XFA_FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ - -#include "core/fxcrt/fx_basic.h" - -class CBC_CommonBitMatrix; -class CBC_QRCoderECBlocks; -class CBC_QRCoderErrorCorrectionLevel; - -class CBC_QRCoderVersion { - public: - virtual ~CBC_QRCoderVersion(); - static void Initialize(); - static void Finalize(); - - int32_t GetVersionNumber(); - int32_t GetTotalCodeWords(); - int32_t GetDimensionForVersion(); - CBC_CommonBitMatrix* BuildFunctionPattern(int32_t& e); - CFX_ArrayTemplate<int32_t>* GetAlignmentPatternCenters(); - CBC_QRCoderECBlocks* GetECBlocksForLevel( - CBC_QRCoderErrorCorrectionLevel* ecLevel); - static CBC_QRCoderVersion* GetVersionForNumber(int32_t versionNumber, - int32_t& e); - static CBC_QRCoderVersion* GetProvisionalVersionForDimension( - int32_t dimension, - int32_t& e); - static CBC_QRCoderVersion* DecodeVersionInformation(int32_t versionBits, - int32_t& e); - static void Destroy(); - - private: - CBC_QRCoderVersion(); - CBC_QRCoderVersion(int32_t versionNumber, - CBC_QRCoderECBlocks* ecBlocks1, - CBC_QRCoderECBlocks* ecBlocks2, - CBC_QRCoderECBlocks* ecBlocks3, - CBC_QRCoderECBlocks* ecBlocks4); - - static const int32_t VERSION_DECODE_INFO[34]; - static CFX_ArrayTemplate<CBC_QRCoderVersion*>* VERSION; - - int32_t m_versionNumber; - int32_t m_totalCodeWords; - CFX_ArrayTemplate<int32_t> m_alignmentPatternCenters; - CFX_ArrayTemplate<CBC_QRCoderECBlocks*> m_ecBlocksArray; -}; - -#endif // XFA_FXBARCODE_QRCODE_BC_QRCODERVERSION_H_ diff --git a/xfa/fxbarcode/utils.h b/xfa/fxbarcode/utils.h deleted file mode 100644 index 1cb8d85013edc8919fe3d59cbee2c1aaa9737eb4..0000000000000000000000000000000000000000 --- a/xfa/fxbarcode/utils.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXBARCODE_UTILS_H_ -#define XFA_FXBARCODE_UTILS_H_ - -#include "core/fxcrt/fx_basic.h" - -bool BC_FX_ByteString_Replace(CFX_ByteString& dst, - uint32_t first, - uint32_t last, - int32_t count, - FX_CHAR c); -void BC_FX_ByteString_Append(CFX_ByteString& dst, int32_t count, FX_CHAR c); -void BC_FX_ByteString_Append(CFX_ByteString& dst, - const CFX_ArrayTemplate<uint8_t>& ba); - -#if (_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_) -#include <limits> -#elif(_FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_LINUX_DESKTOP_ || \ - _FX_OS_ == _FX_IOS_) -#include <limits.h> -#endif -#if (_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_) -#define FXSYS_isnan(x) _isnan(x) -#elif(_FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ || \ - _FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_ANDROID_) -#include <cmath> -#define FXSYS_isnan(x) std::isnan(x) -#endif -#if (_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_) -#define FXSYS_nan() (std::numeric_limits<float>::quiet_NaN()) -#elif(_FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_LINUX_DESKTOP_ || \ - _FX_OS_ == _FX_IOS_ || _FX_OS_ == _FX_ANDROID_) -#define FXSYS_nan() NAN -#endif -enum BCFORMAT { - BCFORMAT_UNSPECIFY = -1, - BCFORMAT_CODABAR, - BCFORMAT_CODE_39, - BCFORMAT_CODE_128, - BCFORMAT_CODE_128B, - BCFORMAT_CODE_128C, - BCFORMAT_EAN_8, - BCFORMAT_UPC_A, - BCFORMAT_EAN_13, - BCFORMAT_PDF_417, - BCFORMAT_DATAMATRIX, - BCFORMAT_QR_CODE -}; -#define BCFORMAT_ECLEVEL_L 0 -#define BCFORMAT_ECLEVEL_M 1 -#define BCFORMAT_ECLEVEL_Q 2 -#define BCFORMAT_ECLEVEL_H 3 -#include <ctype.h> -#define FXSYS_IntMax INT_MAX -#define FXSYS_Isdigit isdigit -#define BCExceptionNO 0 -#define BCExceptionNotFound 1 -#define BCExceptionEndLessThanStart 2 -#define BCExceptionUnknownDecoder 3 -#define BCExceptionRotateNotSupported 4 -#define BCExceptionHeightAndWidthMustBeAtLeast1 5 -#define BCExceptionRegionMustFitInsideMatrix 6 -#define BCExceptionCanNotCallGetDimensionOnNonSquareMatrix 7 -#define BCExceptionFormatException 8 -#define BCExceptionIllegalArgumentMustMatchVersionSize 9 -#define BCExceptionChecksumException 10 -#define BCExceptionIllegalArgumentInvalidFirstDigit 11 -#define BCExceptionIllegalArgumentInvalidSecondDigit 12 -#define BCExceptionRuntimeDecodingInvalidISO_IEC 13 -#define BCExceptionRuntimeDecodingInvalidAlphanumeric 14 -#define BCExceptionLeftAndTopMustBeNonnegative 15 -#define BCExceptionIllegalArgument 16 -#define BCExceptionBadECI 17 -#define BCExceptionUnSupportedBarcode 18 -#define BCExceptionUnSupportedString 19 -#define BCExceptionDigitLengthMustBe8 20 -#define BCExceptionDataCheckException 21 -#define BCExceptionExtractNumberValueFromBitArray 22 -#define BCExceptionRead 23 -#define BCExceptionRequestedRowIsOutSizeTheImage 24 -#define BCExceptionNoContents 26 -#define BCExceptionUnSupportEclevel 27 -#define BCExceptionUnSupportMode 28 -#define BCExceptionReferenceMustBeBetween0And7 29 -#define BCExceptionBadErrorLocation 30 -#define BCExceptionDegreeIsNegative 31 -#define BCExceptionDivideByZero 32 -#define BCExceptionCoefficientsSizeIsNull 33 -#define BCExceptionNoCorrectionBytes 34 -#define BCExceptionNoDataBytesProvided 35 -#define BCExceptionR_I_1IsZero 36 -#define BCExceptionAIsZero 37 -#define BCExceptionIsZero 38 -#define BCExceptionDegreeNotMatchRoots 39 -#define BCExceptionContentsLengthShouldBetween1and80 40 -#define BCExceptionOnlyEncodeCODE_128 41 -#define BCExceptionOnlyEncodeCODE_39 42 -#define BCExceptionOnlyEncodeEAN_13 43 -#define BCExceptionOnlyEncodeEAN_8 44 -#define BCExceptionOnlyEncodeITF 45 -#define BCExceptionDigitLengthShould13 46 -#define BCExceptionDigitLengthMustBe6or8or10or12or14or16or20or24or44 47 -#define BCExceptionOnlyEncodeUPC_A 48 -#define BCExceptionDigitLengthShouldBe12 49 -#define BCExceptionValueMustBeEither0or1 50 -#define BCExceptionReedsolomnDecodeException 51 -#define BCExceptionBadIndexException 52 -#define BCExceptionBadValueException 53 -#define BCExceptionBadNumBitsException 54 -#define BCExceptioncanNotOperatexorOperator 55 -#define BCExceptionVersionMust1_40 56 -#define BCExceptionUnknown 57 -#define BCExceptionNoSuchVersion 58 -#define BCExceptionCannotFindBlockInfo 59 -#define BCExceptionDataTooBig 60 -#define BCExceptionInvalidQRCode 61 -#define BCExceptionDataTooMany 62 -#define BCExceptionBitsNotEqualCacity 63 -#define BCExceptionUnsupportedMode 64 -#define BCExceptionInvalidateCharacter 65 -#define BCExceptionBytesNotMatchOffset 66 -#define BCExceptionSizeInBytesDiffer 67 -#define BCExceptionInvalidateMaskPattern 68 -#define BCExceptionNullPointer 69 -#define BCExceptionBadMask 70 -#define BCExceptionBitSizeNot15 71 -#define BCExceptionBitSizeNot18 72 -#define BCExceptionInvalidateImageData 73 -#define BCExceptionHeight_8BeZero 74 -#define BCExceptionCharacterNotThisMode 75 -#define BCExceptionBitsBytesNotMatch 76 -#define BCExceptionInvalidateData 77 -#define BCExceptionLoadFile 78 -#define BCExceptionPDF417EncodeFail 79 -#define BCExceptionFailToCreateBitmap 80 -#define BCExceptionLoadFontFail 81 -#define BCExceptionOnlyEncodeCODEBAR 82 -#define BCExceptionCodabarShouldStartWithOneOfABCD 83 -#define BCExceptionCodabarShouldEndWithOneOfTNE 84 -#define BCExceptionCodabarEncodeCharsInvalid 85 -#define BCExceptionOnlyEncodeDATAMATRIX 86 -#define BCExceptionCharactersOutsideISO88591Encoding 87 -#define BCExceptionIllegalDataCodewords 88 -#define BCExceptionCannotHandleThisNumberOfDataRegions 89 -#define BCExceptionIllegalStateUnexpectedCase 90 -#define BCExceptionIllegalStateCountMustNotExceed4 91 -#define BCExceptionIllegalStateMessageLengthInvalid 92 -#define BCExceptionIllegalArgumentNotGigits 93 -#define BCExceptionIllegalStateIllegalMode 94 -#define BCExceptionOnlyEncodePDF417 95 -#define BCExceptionNonEncodableCharacterDetected 96 -#define BCExceptionErrorCorrectionLevelMustBeBetween0And8 97 -#define BCExceptionNoRecommendationPossible 98 -#define BCExceptionIllegalArgumentnMustBeAbove0 99 -#define BCExceptionUnableToFitMessageInColumns 100 -#define BCExceptionEncodedMessageContainsTooManyCodeWords 101 -#define BCExceptionBitmapSizeError 102 -#define BCExceptionFormatInstance 102 -#define BCExceptionChecksumInstance 103 -#define BCExceptiontNotFoundInstance 104 -#define BCExceptionNotFoundInstance 105 -#define BCExceptionCannotMetadata 106 - -#endif // XFA_FXBARCODE_UTILS_H_ diff --git a/xfa/fxfa/DEPS b/xfa/fxfa/DEPS index 93a9acbc1369ba72791cca421fd1c0f5767223f6..886ee8e2b750c680723c12bf073b60b708ce5331 100644 --- a/xfa/fxfa/DEPS +++ b/xfa/fxfa/DEPS @@ -1,5 +1,3 @@ include_rules = [ - '+core/fdrm/crypto', - '+core/fxcodec', '+fxjs', ] diff --git a/xfa/fxfa/README.md b/xfa/fxfa/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b554ce0f43631f2f73fd2cf18d7c159fceeda37f --- /dev/null +++ b/xfa/fxfa/README.md @@ -0,0 +1,46 @@ +xfa/fxfa contains a set of CXFA_LayoutItems that model forms containing widgets. + +The main hierarchy in this directory are the form elements: + +* CXFA_LayoutItem + * CXFA_ContentLayoutItem + * CXFA_FFPageView + * CXFA_FFWidget + * CXFA_FFDraw + * CXFA_FFArc + * CXFA_FFImage + * CXFA_FFLine + * CXFA_FFRectangle + * CXFA_FFText + * CXFA_FFExclGroup + * CXFA_FFField + * CXFA_FFCheckButton + * CXFA_FFComboBox + * CXFA_FFImageEdit + * CXFA_FFListBox + * CXFA_FFPushButton + * CXFA_FFSignature + * CXFA_FFTextEdit + * CXFA_FFBarcode + * CXFA_FFDateTimeEdit + * CXFA_FFNumericEdit + * CXFA_FFPasswordEdit + * CXFA_FFSubform + +CXFA_FFDraw is the base class for static elements like text and images. + +CXFA_FFField is the base class for widgets. It owns a lower level CFWL widget +instance from xfa/fwl. The correspondence is: + +* CXFA_FFCheckButton -> CFWL_CheckBox +* CXFA_FFComboBox -> CFWL_ComboBox +* CXFA_FFImageEdit -> CFWL_PictureBox +* CXFA_FFListBox -> CFWL_ListBox +* CXFA_FFPushButton -> CFWL_PushButton +* CXFA_FFSignature -> none +* CXFA_FFTextEdit -> CFWL_Edit + * CXFA_FFBarcode -> CFWL_Barcode + * CXFA_FFDateTimeEdit -> CFWL_DateTimePicker + * CXFA_FFNumericEdit -> CFWL_Edit + * CXFA_FFPasswordEdit > CFWL_Edit + diff --git a/xfa/fxfa/app/DEPS b/xfa/fxfa/app/DEPS deleted file mode 100644 index 5c72d1d0b2e64f756740721b9fa62ee84d20b0e1..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/DEPS +++ /dev/null @@ -1,6 +0,0 @@ -include_rules = [ - '+core/fdrm/crypto', - '+core/fpdfapi/font', - '+core/fpdfapi/page', - '+core/fpdfdoc', -] diff --git a/xfa/fxfa/app/cxfa_csstagprovider.cpp b/xfa/fxfa/app/cxfa_csstagprovider.cpp deleted file mode 100644 index ef5133e104e4d098bcdcfb37d2d9d1081b44ab1d..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_csstagprovider.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/cxfa_csstagprovider.h" - -CXFA_CSSTagProvider::CXFA_CSSTagProvider() - : m_bTagAvailable(false), m_bContent(false) {} - -CXFA_CSSTagProvider::~CXFA_CSSTagProvider() {} diff --git a/xfa/fxfa/app/cxfa_csstagprovider.h b/xfa/fxfa/app/cxfa_csstagprovider.h deleted file mode 100644 index f5db867390e46df86a80610392e567215a36771b..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_csstagprovider.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_CSSTAGPROVIDER_H_ -#define XFA_FXFA_APP_CXFA_CSSTAGPROVIDER_H_ - -#include <map> - -#include "core/fxcrt/fx_string.h" - -class CXFA_CSSTagProvider { - public: - CXFA_CSSTagProvider(); - ~CXFA_CSSTagProvider(); - - CFX_WideString GetTagName() { return m_wsTagName; } - - void SetTagName(const CFX_WideString& wsName) { m_wsTagName = wsName; } - void SetAttribute(const CFX_WideString& wsAttr, - const CFX_WideString& wsValue) { - m_Attributes.insert({wsAttr, wsValue}); - } - - CFX_WideString GetAttribute(const CFX_WideString& wsAttr) { - return m_Attributes[wsAttr]; - } - - bool m_bTagAvailable; - bool m_bContent; - - private: - CFX_WideString m_wsTagName; - std::map<CFX_WideString, CFX_WideString> m_Attributes; -}; - -#endif // XFA_FXFA_APP_CXFA_CSSTAGPROVIDER_H_ diff --git a/xfa/fxfa/app/cxfa_linkuserdata.h b/xfa/fxfa/app/cxfa_linkuserdata.h deleted file mode 100644 index 852b4676483a614eb30e864071bbc03cd32d273a..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_linkuserdata.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_LINKUSERDATA_H_ -#define XFA_FXFA_APP_CXFA_LINKUSERDATA_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" - -class CXFA_LinkUserData : public CFX_Retainable { - public: - template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - const FX_WCHAR* GetLinkURL() const { return m_wsURLContent.c_str(); } - - protected: - explicit CXFA_LinkUserData(FX_WCHAR* pszText); - ~CXFA_LinkUserData() override; - - CFX_WideString m_wsURLContent; -}; - -#endif // XFA_FXFA_APP_CXFA_LINKUSERDATA_H_ diff --git a/xfa/fxfa/app/cxfa_loadercontext.h b/xfa/fxfa/app/cxfa_loadercontext.h deleted file mode 100644 index d8ccdbe7e27e3fc98dbd8c225920e4f7839fc858..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_loadercontext.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_LOADERCONTEXT_H_ -#define XFA_FXFA_APP_CXFA_LOADERCONTEXT_H_ - -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fde/css/cfde_csscomputedstyle.h" - -class CFDE_XMLNode; -class CXFA_Node; - -class CXFA_LoaderContext { - public: - CXFA_LoaderContext(); - ~CXFA_LoaderContext(); - - bool m_bSaveLineHeight; - FX_FLOAT m_fWidth; - FX_FLOAT m_fHeight; - FX_FLOAT m_fLastPos; - FX_FLOAT m_fStartLineOffset; - int32_t m_iChar; - int32_t m_iLines; - int32_t m_iTotalLines; - CFDE_XMLNode* m_pXMLNode; - CXFA_Node* m_pNode; - CFX_RetainPtr<CFDE_CSSComputedStyle> m_pParentStyle; - CFX_ArrayTemplate<FX_FLOAT> m_lineHeights; - uint32_t m_dwFlags; - std::vector<FX_FLOAT> m_BlocksHeight; -}; - -#endif // XFA_FXFA_APP_CXFA_LOADERCONTEXT_H_ diff --git a/xfa/fxfa/app/cxfa_pieceline.h b/xfa/fxfa/app/cxfa_pieceline.h deleted file mode 100644 index 3e6bb99876a66bfaa40eee12d9505b8743fb8c17..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_pieceline.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_PIECELINE_H_ -#define XFA_FXFA_APP_CXFA_PIECELINE_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_basic.h" - -class XFA_TextPiece; - -class CXFA_PieceLine { - public: - CXFA_PieceLine(); - ~CXFA_PieceLine(); - - std::vector<std::unique_ptr<XFA_TextPiece>> m_textPieces; - CFX_ArrayTemplate<int32_t> m_charCounts; -}; - -#endif // XFA_FXFA_APP_CXFA_PIECELINE_H_ diff --git a/xfa/fxfa/app/cxfa_textlayout.cpp b/xfa/fxfa/app/cxfa_textlayout.cpp deleted file mode 100644 index 06cbfe0c70bcbbdc38d965b959edcc83ffc239d6..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textlayout.cpp +++ /dev/null @@ -1,1313 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/cxfa_textlayout.h" - -#include <algorithm> -#include <utility> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/cfde_path.h" -#include "xfa/fde/css/cfde_csscomputedstyle.h" -#include "xfa/fde/css/cfde_cssstyleselector.h" -#include "xfa/fde/fde_gedevice.h" -#include "xfa/fde/fde_object.h" -#include "xfa/fde/xml/fde_xml_imp.h" -#include "xfa/fxfa/app/cxfa_linkuserdata.h" -#include "xfa/fxfa/app/cxfa_loadercontext.h" -#include "xfa/fxfa/app/cxfa_pieceline.h" -#include "xfa/fxfa/app/cxfa_textparsecontext.h" -#include "xfa/fxfa/app/cxfa_texttabstopscontext.h" -#include "xfa/fxfa/app/cxfa_textuserdata.h" -#include "xfa/fxfa/app/xfa_ffwidgetacc.h" -#include "xfa/fxfa/app/xfa_textpiece.h" -#include "xfa/fxfa/parser/cxfa_font.h" -#include "xfa/fxfa/parser/cxfa_para.h" -#include "xfa/fxfa/parser/xfa_object.h" - -#define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001 - -CXFA_TextLayout::CXFA_TextLayout(CXFA_TextProvider* pTextProvider) - : m_bHasBlock(false), - m_pTextProvider(pTextProvider), - m_pTextDataNode(nullptr), - m_bRichText(false), - m_iLines(0), - m_fMaxWidth(0), - m_bBlockContinue(true) { - ASSERT(m_pTextProvider); -} - -CXFA_TextLayout::~CXFA_TextLayout() { - m_textParser.Reset(); - Unload(); -} - -void CXFA_TextLayout::Unload() { - m_pieceLines.clear(); - m_pBreak.reset(); -} - -void CXFA_TextLayout::GetTextDataNode() { - if (!m_pTextProvider) - return; - - CXFA_Node* pNode = m_pTextProvider->GetTextNode(m_bRichText); - if (pNode && m_bRichText) - m_textParser.Reset(); - - m_pTextDataNode = pNode; -} - -CFDE_XMLNode* CXFA_TextLayout::GetXMLContainerNode() { - if (!m_bRichText) - return nullptr; - - CFDE_XMLNode* pXMLRoot = m_pTextDataNode->GetXMLMappingNode(); - if (!pXMLRoot) - return nullptr; - - CFDE_XMLNode* pXMLContainer = nullptr; - for (CFDE_XMLNode* pXMLChild = - pXMLRoot->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pXMLChild->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLChild); - CFX_WideString wsTag; - pXMLElement->GetLocalTagName(wsTag); - if (wsTag == L"body" || wsTag == L"html") { - pXMLContainer = pXMLChild; - break; - } - } - } - return pXMLContainer; -} - -std::unique_ptr<CFX_RTFBreak> CXFA_TextLayout::CreateBreak(bool bDefault) { - uint32_t dwStyle = FX_RTFLAYOUTSTYLE_ExpandTab; - if (!bDefault) - dwStyle |= FX_RTFLAYOUTSTYLE_Pagination; - - auto pBreak = pdfium::MakeUnique<CFX_RTFBreak>(dwStyle); - pBreak->SetLineBreakTolerance(1); - pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, nullptr)); - pBreak->SetFontSize(m_textParser.GetFontSize(m_pTextProvider, nullptr)); - return pBreak; -} - -void CXFA_TextLayout::InitBreak(FX_FLOAT fLineWidth) { - CXFA_Font font = m_pTextProvider->GetFontNode(); - CXFA_Para para = m_pTextProvider->GetParaNode(); - FX_FLOAT fStart = 0; - FX_FLOAT fStartPos = 0; - if (para) { - CFX_RTFLineAlignment iAlign = CFX_RTFLineAlignment::Left; - switch (para.GetHorizontalAlign()) { - case XFA_ATTRIBUTEENUM_Center: - iAlign = CFX_RTFLineAlignment::Center; - break; - case XFA_ATTRIBUTEENUM_Right: - iAlign = CFX_RTFLineAlignment::Right; - break; - case XFA_ATTRIBUTEENUM_Justify: - iAlign = CFX_RTFLineAlignment::Justified; - break; - case XFA_ATTRIBUTEENUM_JustifyAll: - iAlign = CFX_RTFLineAlignment::Distributed; - break; - } - m_pBreak->SetAlignment(iAlign); - - fStart = para.GetMarginLeft(); - if (m_pTextProvider->IsCheckButtonAndAutoWidth()) { - if (iAlign != CFX_RTFLineAlignment::Left) - fLineWidth -= para.GetMarginRight(); - } else { - fLineWidth -= para.GetMarginRight(); - } - if (fLineWidth < 0) - fLineWidth = fStart; - - fStartPos = fStart; - FX_FLOAT fIndent = para.GetTextIndent(); - if (fIndent > 0) - fStartPos += fIndent; - } - - m_pBreak->SetLineBoundary(fStart, fLineWidth); - m_pBreak->SetLineStartPos(fStartPos); - if (font) { - m_pBreak->SetHorizontalScale((int32_t)font.GetHorizontalScale()); - m_pBreak->SetVerticalScale((int32_t)font.GetVerticalScale()); - m_pBreak->SetCharSpace(font.GetLetterSpacing()); - } - - FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, nullptr); - m_pBreak->SetFontSize(fFontSize); - m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, nullptr)); - m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f); -} - -void CXFA_TextLayout::InitBreak(CFDE_CSSComputedStyle* pStyle, - FDE_CSSDisplay eDisplay, - FX_FLOAT fLineWidth, - CFDE_XMLNode* pXMLNode, - CFDE_CSSComputedStyle* pParentStyle) { - if (!pStyle) { - InitBreak(fLineWidth); - return; - } - - if (eDisplay == FDE_CSSDisplay::Block || - eDisplay == FDE_CSSDisplay::ListItem) { - CFX_RTFLineAlignment iAlign = CFX_RTFLineAlignment::Left; - switch (pStyle->GetTextAlign()) { - case FDE_CSSTextAlign::Right: - iAlign = CFX_RTFLineAlignment::Right; - break; - case FDE_CSSTextAlign::Center: - iAlign = CFX_RTFLineAlignment::Center; - break; - case FDE_CSSTextAlign::Justify: - iAlign = CFX_RTFLineAlignment::Justified; - break; - case FDE_CSSTextAlign::JustifyAll: - iAlign = CFX_RTFLineAlignment::Distributed; - break; - default: - break; - } - m_pBreak->SetAlignment(iAlign); - - FX_FLOAT fStart = 0; - const FDE_CSSRect* pRect = pStyle->GetMarginWidth(); - const FDE_CSSRect* pPaddingRect = pStyle->GetPaddingWidth(); - if (pRect) { - fStart = pRect->left.GetValue(); - fLineWidth -= pRect->right.GetValue(); - if (pPaddingRect) { - fStart += pPaddingRect->left.GetValue(); - fLineWidth -= pPaddingRect->right.GetValue(); - } - if (eDisplay == FDE_CSSDisplay::ListItem) { - const FDE_CSSRect* pParRect = pParentStyle->GetMarginWidth(); - const FDE_CSSRect* pParPaddingRect = pParentStyle->GetPaddingWidth(); - if (pParRect) { - fStart += pParRect->left.GetValue(); - fLineWidth -= pParRect->right.GetValue(); - if (pParPaddingRect) { - fStart += pParPaddingRect->left.GetValue(); - fLineWidth -= pParPaddingRect->right.GetValue(); - } - } - FDE_CSSRect pNewRect; - pNewRect.left.Set(FDE_CSSLengthUnit::Point, fStart); - pNewRect.right.Set(FDE_CSSLengthUnit::Point, pRect->right.GetValue()); - pNewRect.top.Set(FDE_CSSLengthUnit::Point, pRect->top.GetValue()); - pNewRect.bottom.Set(FDE_CSSLengthUnit::Point, pRect->bottom.GetValue()); - pStyle->SetMarginWidth(pNewRect); - } - } - m_pBreak->SetLineBoundary(fStart, fLineWidth); - FX_FLOAT fIndent = pStyle->GetTextIndent().GetValue(); - if (fIndent > 0) - fStart += fIndent; - - m_pBreak->SetLineStartPos(fStart); - m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle)); - if (!m_pTabstopContext) - m_pTabstopContext = pdfium::MakeUnique<CXFA_TextTabstopsContext>(); - m_textParser.GetTabstops(pStyle, m_pTabstopContext.get()); - for (int32_t i = 0; i < m_pTabstopContext->m_iTabCount; i++) { - XFA_TABSTOPS* pTab = m_pTabstopContext->m_tabstops.GetDataPtr(i); - m_pBreak->AddPositionedTab(pTab->fTabstops); - } - } - - FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle); - m_pBreak->SetFontSize(fFontSize); - m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f); - m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, pStyle)); - m_pBreak->SetHorizontalScale( - m_textParser.GetHorScale(m_pTextProvider, pStyle, pXMLNode)); - m_pBreak->SetVerticalScale(m_textParser.GetVerScale(m_pTextProvider, pStyle)); - m_pBreak->SetCharSpace(pStyle->GetLetterSpacing().GetValue()); -} - -int32_t CXFA_TextLayout::GetText(CFX_WideString& wsText) { - GetTextDataNode(); - wsText.clear(); - if (!m_bRichText) - wsText = m_pTextDataNode->GetContent(); - return wsText.GetLength(); -} - -FX_FLOAT CXFA_TextLayout::GetLayoutHeight() { - if (!m_pLoader) - return 0; - - int32_t iCount = m_pLoader->m_lineHeights.GetSize(); - if (iCount == 0 && m_pLoader->m_fWidth > 0) { - CFX_SizeF szMax(m_pLoader->m_fWidth, m_pLoader->m_fHeight); - CFX_SizeF szDef; - m_pLoader->m_bSaveLineHeight = true; - m_pLoader->m_fLastPos = 0; - CalcSize(szMax, szMax, szDef); - m_pLoader->m_bSaveLineHeight = false; - return szDef.height; - } - - FX_FLOAT fHeight = m_pLoader->m_fHeight; - if (fHeight < 0.1f) { - fHeight = 0; - for (int32_t i = 0; i < iCount; i++) - fHeight += m_pLoader->m_lineHeights.ElementAt(i); - } - return fHeight; -} - -FX_FLOAT CXFA_TextLayout::StartLayout(FX_FLOAT fWidth) { - if (!m_pLoader) - m_pLoader = pdfium::MakeUnique<CXFA_LoaderContext>(); - - if (fWidth < 0 || (m_pLoader->m_fWidth > -1 && - FXSYS_fabs(fWidth - m_pLoader->m_fWidth) > 0)) { - m_pLoader->m_lineHeights.RemoveAll(); - m_Blocks.RemoveAll(); - Unload(); - m_pLoader->m_fStartLineOffset = 0; - } - m_pLoader->m_fWidth = fWidth; - - if (fWidth < 0) { - CFX_SizeF szMax; - CFX_SizeF szDef; - m_pLoader->m_bSaveLineHeight = true; - m_pLoader->m_fLastPos = 0; - CalcSize(szMax, szMax, szDef); - m_pLoader->m_bSaveLineHeight = false; - fWidth = szDef.width; - } - return fWidth; -} - -bool CXFA_TextLayout::DoLayout(int32_t iBlockIndex, - FX_FLOAT& fCalcHeight, - FX_FLOAT fContentAreaHeight, - FX_FLOAT fTextHeight) { - if (!m_pLoader) - return false; - - int32_t iBlockCount = m_Blocks.GetSize(); - FX_FLOAT fHeight = fTextHeight; - if (fHeight < 0) - fHeight = GetLayoutHeight(); - - m_pLoader->m_fHeight = fHeight; - if (fContentAreaHeight < 0) - return false; - - m_bHasBlock = true; - if (iBlockCount == 0 && fHeight > 0) { - fHeight = fTextHeight - GetLayoutHeight(); - if (fHeight > 0) { - int32_t iAlign = m_textParser.GetVAlign(m_pTextProvider); - if (iAlign == XFA_ATTRIBUTEENUM_Middle) - fHeight /= 2.0f; - else if (iAlign != XFA_ATTRIBUTEENUM_Bottom) - fHeight = 0; - m_pLoader->m_fStartLineOffset = fHeight; - } - } - - FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset; - int32_t iLineIndex = 0; - if (iBlockCount > 1) { - if (iBlockCount >= (iBlockIndex + 1) * 2) { - iLineIndex = m_Blocks.ElementAt(iBlockIndex * 2); - } else { - iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) + - m_Blocks.ElementAt(iBlockCount - 2); - } - if (!m_pLoader->m_BlocksHeight.empty()) { - for (int32_t i = 0; i < iBlockIndex; i++) - fLinePos -= m_pLoader->m_BlocksHeight[i * 2 + 1]; - } - } - - int32_t iCount = m_pLoader->m_lineHeights.GetSize(); - int32_t i = 0; - for (i = iLineIndex; i < iCount; i++) { - FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i); - if ((i == iLineIndex) && (fLineHeight - fContentAreaHeight > 0.001)) { - fCalcHeight = 0; - return true; - } - if (fLinePos + fLineHeight - fContentAreaHeight > 0.001) { - if (iBlockCount >= (iBlockIndex + 1) * 2) { - m_Blocks.SetAt(iBlockIndex * 2, iLineIndex); - m_Blocks.SetAt(iBlockIndex * 2 + 1, i - iLineIndex); - } else { - m_Blocks.Add(iLineIndex); - m_Blocks.Add(i - iLineIndex); - } - if (i == iLineIndex) { - if (fCalcHeight <= fLinePos) { - if (pdfium::CollectionSize<int32_t>(m_pLoader->m_BlocksHeight) > - iBlockIndex * 2 && - (m_pLoader->m_BlocksHeight[iBlockIndex * 2] == iBlockIndex)) { - m_pLoader->m_BlocksHeight[iBlockIndex * 2 + 1] = fCalcHeight; - } else { - m_pLoader->m_BlocksHeight.push_back((FX_FLOAT)iBlockIndex); - m_pLoader->m_BlocksHeight.push_back(fCalcHeight); - } - } - return true; - } - - fCalcHeight = fLinePos; - return true; - } - fLinePos += fLineHeight; - } - return false; -} - -int32_t CXFA_TextLayout::CountBlocks() const { - int32_t iCount = m_Blocks.GetSize() / 2; - return iCount > 0 ? iCount : 1; -} - -bool CXFA_TextLayout::CalcSize(const CFX_SizeF& minSize, - const CFX_SizeF& maxSize, - CFX_SizeF& defaultSize) { - defaultSize.width = maxSize.width; - if (defaultSize.width < 1) - defaultSize.width = 0xFFFF; - - m_pBreak = CreateBreak(false); - FX_FLOAT fLinePos = 0; - m_iLines = 0; - m_fMaxWidth = 0; - Loader(defaultSize, fLinePos, false); - if (fLinePos < 0.1f) - fLinePos = m_textParser.GetFontSize(m_pTextProvider, nullptr); - - m_pTabstopContext.reset(); - defaultSize = CFX_SizeF(m_fMaxWidth, fLinePos); - return true; -} - -bool CXFA_TextLayout::Layout(const CFX_SizeF& size, FX_FLOAT* fHeight) { - if (size.width < 1) - return false; - - Unload(); - m_pBreak = CreateBreak(true); - if (m_pLoader) { - m_pLoader->m_iTotalLines = -1; - m_pLoader->m_iChar = 0; - } - - m_iLines = 0; - FX_FLOAT fLinePos = 0; - Loader(size, fLinePos, true); - UpdateAlign(size.height, fLinePos); - m_pTabstopContext.reset(); - if (fHeight) - *fHeight = fLinePos; - return true; -} - -bool CXFA_TextLayout::Layout(int32_t iBlock) { - if (!m_pLoader || iBlock < 0 || iBlock >= CountBlocks()) - return false; - if (m_pLoader->m_fWidth < 1) - return false; - - m_pLoader->m_iTotalLines = -1; - m_iLines = 0; - FX_FLOAT fLinePos = 0; - CXFA_Node* pNode = nullptr; - CFX_SizeF szText(m_pLoader->m_fWidth, m_pLoader->m_fHeight); - int32_t iCount = m_Blocks.GetSize(); - int32_t iBlocksHeightCount = - pdfium::CollectionSize<int32_t>(m_pLoader->m_BlocksHeight); - iBlocksHeightCount /= 2; - if (iBlock < iBlocksHeightCount) - return true; - if (iBlock == iBlocksHeightCount) { - Unload(); - m_pBreak = CreateBreak(true); - fLinePos = m_pLoader->m_fStartLineOffset; - for (int32_t i = 0; i < iBlocksHeightCount; i++) - fLinePos -= m_pLoader->m_BlocksHeight[i * 2 + 1]; - - m_pLoader->m_iChar = 0; - if (iCount > 1) - m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock * 2 + 1); - - Loader(szText, fLinePos, true); - if (iCount == 0 && m_pLoader->m_fStartLineOffset < 0.1f) - UpdateAlign(szText.height, fLinePos); - } else if (m_pTextDataNode) { - iBlock *= 2; - if (iBlock < iCount - 2) - m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock + 1); - - m_pBreak->Reset(); - if (m_bRichText) { - CFDE_XMLNode* pContainerNode = GetXMLContainerNode(); - if (!pContainerNode) - return true; - - CFDE_XMLNode* pXMLNode = m_pLoader->m_pXMLNode; - if (!pXMLNode) - return true; - - CFDE_XMLNode* pSaveXMLNode = m_pLoader->m_pXMLNode; - for (; pXMLNode; - pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (!LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle, - true, nullptr)) { - break; - } - } - while (!pXMLNode) { - pXMLNode = pSaveXMLNode->GetNodeItem(CFDE_XMLNode::Parent); - if (pXMLNode == pContainerNode) - break; - if (!LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle, - true, nullptr, false)) { - break; - } - pSaveXMLNode = pXMLNode; - pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling); - if (!pXMLNode) - continue; - for (; pXMLNode; - pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (!LoadRichText(pXMLNode, szText, fLinePos, - m_pLoader->m_pParentStyle, true, nullptr)) { - break; - } - } - } - } else { - pNode = m_pLoader->m_pNode; - if (!pNode) - return true; - LoadText(pNode, szText, fLinePos, true); - } - } - if (iBlock == iCount) { - m_pTabstopContext.reset(); - m_pLoader.reset(); - } - return true; -} - -void CXFA_TextLayout::ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex) { - if (!m_pLoader) - return; - - int32_t iCountHeight = m_pLoader->m_lineHeights.GetSize(); - if (iCountHeight == 0) - return; - - bool bEndItem = true; - int32_t iBlockCount = m_Blocks.GetSize(); - FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset; - int32_t iLineIndex = 0; - if (iBlockIndex > 0) { - int32_t iBlockHeightCount = - pdfium::CollectionSize<int32_t>(m_pLoader->m_BlocksHeight); - iBlockHeightCount /= 2; - if (iBlockHeightCount >= iBlockIndex) { - for (int32_t i = 0; i < iBlockIndex; i++) - fLinePos -= m_pLoader->m_BlocksHeight[i * 2 + 1]; - } else { - fLinePos = 0; - } - iLineIndex = m_Blocks[iBlockCount - 1] + m_Blocks[iBlockCount - 2]; - } - - int32_t i = 0; - for (i = iLineIndex; i < iCountHeight; i++) { - FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i); - if (fLinePos + fLineHeight - rtText.height > 0.001) { - m_Blocks.Add(iLineIndex); - m_Blocks.Add(i - iLineIndex); - bEndItem = false; - break; - } - fLinePos += fLineHeight; - } - if (iCountHeight > 0 && (i - iLineIndex) > 0 && bEndItem) { - m_Blocks.Add(iLineIndex); - m_Blocks.Add(i - iLineIndex); - } -} - -bool CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice, - const CFX_Matrix& tmDoc2Device, - const CFX_RectF& rtClip, - int32_t iBlock) { - if (!pFxDevice) - return false; - - std::unique_ptr<CFDE_RenderDevice> pDevice( - new CFDE_RenderDevice(pFxDevice, false)); - pDevice->SaveState(); - pDevice->SetClipRect(rtClip); - - auto pSolidBrush = pdfium::MakeUnique<CFDE_Brush>(); - auto pPen = pdfium::MakeUnique<CFDE_Pen>(); - if (m_pieceLines.empty()) { - int32_t iBlockCount = CountBlocks(); - for (int32_t i = 0; i < iBlockCount; i++) - Layout(i); - } - - FXTEXT_CHARPOS* pCharPos = nullptr; - int32_t iCharCount = 0; - int32_t iLineStart = 0; - int32_t iPieceLines = pdfium::CollectionSize<int32_t>(m_pieceLines); - int32_t iCount = m_Blocks.GetSize(); - if (iCount > 0) { - iBlock *= 2; - if (iBlock < iCount) { - iLineStart = m_Blocks.ElementAt(iBlock); - iPieceLines = m_Blocks.ElementAt(iBlock + 1); - } else { - iPieceLines = 0; - } - } - - for (int32_t i = 0; i < iPieceLines; i++) { - if (i + iLineStart >= pdfium::CollectionSize<int32_t>(m_pieceLines)) - break; - - CXFA_PieceLine* pPieceLine = m_pieceLines[i + iLineStart].get(); - int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces); - int32_t j = 0; - for (j = 0; j < iPieces; j++) { - const XFA_TextPiece* pPiece = pPieceLine->m_textPieces[j].get(); - int32_t iChars = pPiece->iChars; - if (iCharCount < iChars) { - FX_Free(pCharPos); - pCharPos = FX_Alloc(FXTEXT_CHARPOS, iChars); - iCharCount = iChars; - } - FXSYS_memset(pCharPos, 0, iCharCount * sizeof(FXTEXT_CHARPOS)); - RenderString(pDevice.get(), pSolidBrush.get(), pPieceLine, j, pCharPos, - tmDoc2Device); - } - for (j = 0; j < iPieces; j++) { - RenderPath(pDevice.get(), pPen.get(), pPieceLine, j, pCharPos, - tmDoc2Device); - } - } - pDevice->RestoreState(); - FX_Free(pCharPos); - return iPieceLines > 0; -} - -void CXFA_TextLayout::UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom) { - fHeight -= fBottom; - if (fHeight < 0.1f) - return; - - switch (m_textParser.GetVAlign(m_pTextProvider)) { - case XFA_ATTRIBUTEENUM_Middle: - fHeight /= 2.0f; - break; - case XFA_ATTRIBUTEENUM_Bottom: - break; - default: - return; - } - - for (const auto& pPieceLine : m_pieceLines) { - for (const auto& pPiece : pPieceLine->m_textPieces) - pPiece->rtPiece.top += fHeight; - } -} - -bool CXFA_TextLayout::Loader(const CFX_SizeF& szText, - FX_FLOAT& fLinePos, - bool bSavePieces) { - GetTextDataNode(); - if (!m_pTextDataNode) - return true; - - if (m_bRichText) { - CFDE_XMLNode* pXMLContainer = GetXMLContainerNode(); - if (pXMLContainer) { - if (!m_textParser.IsParsed()) - m_textParser.DoParse(pXMLContainer, m_pTextProvider); - - auto pRootStyle = m_textParser.CreateRootStyle(m_pTextProvider); - LoadRichText(pXMLContainer, szText, fLinePos, pRootStyle, bSavePieces, - nullptr); - } - } else { - LoadText(m_pTextDataNode, szText, fLinePos, bSavePieces); - } - return true; -} - -void CXFA_TextLayout::LoadText(CXFA_Node* pNode, - const CFX_SizeF& szText, - FX_FLOAT& fLinePos, - bool bSavePieces) { - InitBreak(szText.width); - - CXFA_Para para = m_pTextProvider->GetParaNode(); - FX_FLOAT fSpaceAbove = 0; - if (para) { - fSpaceAbove = para.GetSpaceAbove(); - if (fSpaceAbove < 0.1f) { - fSpaceAbove = 0; - } - int32_t verAlign = para.GetVerticalAlign(); - switch (verAlign) { - case XFA_ATTRIBUTEENUM_Top: - case XFA_ATTRIBUTEENUM_Middle: - case XFA_ATTRIBUTEENUM_Bottom: { - fLinePos += fSpaceAbove; - break; - } - } - } - - CFX_WideString wsText = pNode->GetContent(); - wsText.TrimRight(L" "); - bool bRet = AppendChar(wsText, fLinePos, fSpaceAbove, bSavePieces); - if (bRet && m_pLoader) - m_pLoader->m_pNode = pNode; - else - EndBreak(CFX_RTFBreakType::Paragraph, fLinePos, bSavePieces); -} - -bool CXFA_TextLayout::LoadRichText( - CFDE_XMLNode* pXMLNode, - const CFX_SizeF& szText, - FX_FLOAT& fLinePos, - const CFX_RetainPtr<CFDE_CSSComputedStyle>& pParentStyle, - bool bSavePieces, - CFX_RetainPtr<CXFA_LinkUserData> pLinkData, - bool bEndBreak, - bool bIsOl, - int32_t iLiCount) { - if (!pXMLNode) - return false; - - CXFA_TextParseContext* pContext = - m_textParser.GetParseContextFromMap(pXMLNode); - FDE_CSSDisplay eDisplay = FDE_CSSDisplay::None; - bool bContentNode = false; - FX_FLOAT fSpaceBelow = 0; - CFX_RetainPtr<CFDE_CSSComputedStyle> pStyle; - CFX_WideString wsName; - if (bEndBreak) { - bool bCurOl = false; - bool bCurLi = false; - CFDE_XMLElement* pElement = nullptr; - if (pContext) { - if (m_bBlockContinue || - (m_pLoader && pXMLNode == m_pLoader->m_pXMLNode)) { - m_bBlockContinue = true; - } - if (pXMLNode->GetType() == FDE_XMLNODE_Text) { - bContentNode = true; - } else if (pXMLNode->GetType() == FDE_XMLNODE_Element) { - pElement = static_cast<CFDE_XMLElement*>(pXMLNode); - pElement->GetLocalTagName(wsName); - } - if (wsName == L"ol") { - bIsOl = true; - bCurOl = true; - } - if (m_bBlockContinue || bContentNode == false) { - eDisplay = pContext->GetDisplay(); - if (eDisplay != FDE_CSSDisplay::Block && - eDisplay != FDE_CSSDisplay::Inline && - eDisplay != FDE_CSSDisplay::ListItem) { - return true; - } - - pStyle = m_textParser.ComputeStyle(pXMLNode, pParentStyle.Get()); - InitBreak(bContentNode ? pParentStyle.Get() : pStyle.Get(), eDisplay, - szText.width, pXMLNode, pParentStyle.Get()); - if ((eDisplay == FDE_CSSDisplay::Block || - eDisplay == FDE_CSSDisplay::ListItem) && - pStyle && - (wsName.IsEmpty() || (wsName != L"body" && wsName != L"html" && - wsName != L"ol" && wsName != L"ul"))) { - const FDE_CSSRect* pRect = pStyle->GetMarginWidth(); - if (pRect) { - fLinePos += pRect->top.GetValue(); - fSpaceBelow = pRect->bottom.GetValue(); - } - } - - if (wsName == L"a") { - CFX_WideString wsLinkContent; - ASSERT(pElement); - pElement->GetString(L"href", wsLinkContent); - if (!wsLinkContent.IsEmpty()) { - pLinkData = pdfium::MakeRetain<CXFA_LinkUserData>( - wsLinkContent.GetBuffer(wsLinkContent.GetLength())); - wsLinkContent.ReleaseBuffer(wsLinkContent.GetLength()); - } - } - - int32_t iTabCount = m_textParser.CountTabs( - bContentNode ? pParentStyle.Get() : pStyle.Get()); - bool bSpaceRun = m_textParser.IsSpaceRun( - bContentNode ? pParentStyle.Get() : pStyle.Get()); - CFX_WideString wsText; - if (bContentNode && iTabCount == 0) { - static_cast<CFDE_XMLText*>(pXMLNode)->GetText(wsText); - } else if (wsName == L"br") { - wsText = L'\n'; - } else if (wsName == L"li") { - bCurLi = true; - if (bIsOl) - wsText.Format(L"%d. ", iLiCount); - else - wsText = 0x00B7 + CFX_WideStringC(L" ", 1); - } else if (!bContentNode) { - if (iTabCount > 0) { - while (iTabCount-- > 0) - wsText += L'\t'; - } else { - m_textParser.GetEmbbedObj(m_pTextProvider, pXMLNode, wsText); - } - } - - int32_t iLength = wsText.GetLength(); - if (iLength > 0 && bContentNode && !bSpaceRun) - ProcessText(wsText); - - if (m_pLoader) { - if (wsText.GetLength() > 0 && - (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) { - wsText.TrimLeft(0x20); - } - if (FDE_CSSDisplay::Block == eDisplay) { - m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; - } else if (FDE_CSSDisplay::Inline == eDisplay && - (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) { - m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; - } else if (wsText.GetLength() > 0 && - (0x20 == wsText.GetAt(wsText.GetLength() - 1))) { - m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; - } else if (wsText.GetLength() != 0) { - m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; - } - } - - if (wsText.GetLength() > 0) { - if (!m_pLoader || m_pLoader->m_iChar == 0) { - auto pUserData = pdfium::MakeRetain<CXFA_TextUserData>( - bContentNode ? pParentStyle : pStyle, pLinkData); - m_pBreak->SetUserData(pUserData); - } - - if (AppendChar(wsText, fLinePos, 0, bSavePieces)) { - if (m_pLoader) - m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; - if (IsEnd(bSavePieces)) { - if (m_pLoader && m_pLoader->m_iTotalLines > -1) { - m_pLoader->m_pXMLNode = pXMLNode; - m_pLoader->m_pParentStyle = pParentStyle; - } - return false; - } - return true; - } - } - } - } - - for (CFDE_XMLNode* pChildNode = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); - pChildNode; - pChildNode = pChildNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (bCurOl) - iLiCount++; - - if (!LoadRichText(pChildNode, szText, fLinePos, - pContext ? pStyle : pParentStyle, bSavePieces, - pLinkData, true, bIsOl, iLiCount)) - return false; - } - - if (m_pLoader) { - if (FDE_CSSDisplay::Block == eDisplay) - m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; - } - if (bCurLi) - EndBreak(CFX_RTFBreakType::Line, fLinePos, bSavePieces); - } else { - if (pContext) - eDisplay = pContext->GetDisplay(); - } - - if (m_bBlockContinue) { - if (pContext && !bContentNode) { - CFX_RTFBreakType dwStatus = (eDisplay == FDE_CSSDisplay::Block) - ? CFX_RTFBreakType::Paragraph - : CFX_RTFBreakType::Piece; - EndBreak(dwStatus, fLinePos, bSavePieces); - if (eDisplay == FDE_CSSDisplay::Block) { - fLinePos += fSpaceBelow; - if (m_pTabstopContext) - m_pTabstopContext->RemoveAll(); - } - if (IsEnd(bSavePieces)) { - if (m_pLoader && m_pLoader->m_iTotalLines > -1) { - m_pLoader->m_pXMLNode = - pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling); - m_pLoader->m_pParentStyle = pParentStyle; - } - return false; - } - } - } - return true; -} - -bool CXFA_TextLayout::AppendChar(const CFX_WideString& wsText, - FX_FLOAT& fLinePos, - FX_FLOAT fSpaceAbove, - bool bSavePieces) { - CFX_RTFBreakType dwStatus = CFX_RTFBreakType::None; - int32_t iChar = 0; - if (m_pLoader) - iChar = m_pLoader->m_iChar; - - int32_t iLength = wsText.GetLength(); - for (int32_t i = iChar; i < iLength; i++) { - FX_WCHAR wch = wsText.GetAt(i); - if (wch == 0xA0) - wch = 0x20; - - dwStatus = m_pBreak->AppendChar(wch); - if (dwStatus != CFX_RTFBreakType::None && - dwStatus != CFX_RTFBreakType::Piece) { - AppendTextLine(dwStatus, fLinePos, bSavePieces); - if (IsEnd(bSavePieces)) { - if (m_pLoader) - m_pLoader->m_iChar = i; - return true; - } - if (dwStatus == CFX_RTFBreakType::Paragraph && m_bRichText) - fLinePos += fSpaceAbove; - } - } - if (m_pLoader) - m_pLoader->m_iChar = 0; - - return false; -} - -bool CXFA_TextLayout::IsEnd(bool bSavePieces) { - if (!bSavePieces) - return false; - if (m_pLoader && m_pLoader->m_iTotalLines > 0) - return m_iLines >= m_pLoader->m_iTotalLines; - return false; -} - -void CXFA_TextLayout::ProcessText(CFX_WideString& wsText) { - int32_t iLen = wsText.GetLength(); - if (iLen == 0) - return; - - FX_WCHAR* psz = wsText.GetBuffer(iLen); - int32_t iTrimLeft = 0; - FX_WCHAR wch = 0, wPrev = 0; - for (int32_t i = 0; i < iLen; i++) { - wch = psz[i]; - if (wch < 0x20) - wch = 0x20; - if (wch == 0x20 && wPrev == 0x20) - continue; - - wPrev = wch; - psz[iTrimLeft++] = wch; - } - wsText.ReleaseBuffer(iLen); - wsText = wsText.Left(iTrimLeft); -} - -void CXFA_TextLayout::EndBreak(CFX_RTFBreakType dwStatus, - FX_FLOAT& fLinePos, - bool bSavePieces) { - dwStatus = m_pBreak->EndBreak(dwStatus); - if (dwStatus != CFX_RTFBreakType::None && dwStatus != CFX_RTFBreakType::Piece) - AppendTextLine(dwStatus, fLinePos, bSavePieces, true); -} - -void CXFA_TextLayout::DoTabstops(CFDE_CSSComputedStyle* pStyle, - CXFA_PieceLine* pPieceLine) { - if (!m_pTabstopContext || m_pTabstopContext->m_iTabCount == 0) - return; - if (!pStyle || !pPieceLine) - return; - - int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces); - if (iPieces == 0) - return; - - XFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPieces - 1].get(); - int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex; - int32_t iCount = m_textParser.CountTabs(pStyle); - if (iTabstopsIndex > m_pTabstopContext->m_iTabCount - 1) - return; - - if (iCount > 0) { - iTabstopsIndex++; - m_pTabstopContext->m_bTabstops = true; - FX_FLOAT fRight = 0; - if (iPieces > 1) { - XFA_TextPiece* p = pPieceLine->m_textPieces[iPieces - 2].get(); - fRight = p->rtPiece.right(); - } - m_pTabstopContext->m_fTabWidth = - pPiece->rtPiece.width + pPiece->rtPiece.left - fRight; - } else if (iTabstopsIndex > -1) { - FX_FLOAT fLeft = 0; - if (m_pTabstopContext->m_bTabstops) { - XFA_TABSTOPS* pTabstops = - m_pTabstopContext->m_tabstops.GetDataPtr(iTabstopsIndex); - uint32_t dwAlign = pTabstops->dwAlign; - if (dwAlign == FX_HashCode_GetW(L"center", false)) { - fLeft = pPiece->rtPiece.width / 2.0f; - } else if (dwAlign == FX_HashCode_GetW(L"right", false) || - dwAlign == FX_HashCode_GetW(L"before", false)) { - fLeft = pPiece->rtPiece.width; - } else if (dwAlign == FX_HashCode_GetW(L"decimal", false)) { - int32_t iChars = pPiece->iChars; - for (int32_t i = 0; i < iChars; i++) { - if (pPiece->szText[i] == L'.') - break; - - fLeft += pPiece->Widths[i] / 20000.0f; - } - } - m_pTabstopContext->m_fLeft = - std::min(fLeft, m_pTabstopContext->m_fTabWidth); - m_pTabstopContext->m_bTabstops = false; - m_pTabstopContext->m_fTabWidth = 0; - } - pPiece->rtPiece.left -= m_pTabstopContext->m_fLeft; - } -} - -void CXFA_TextLayout::AppendTextLine(CFX_RTFBreakType dwStatus, - FX_FLOAT& fLinePos, - bool bSavePieces, - bool bEndBreak) { - int32_t iPieces = m_pBreak->CountBreakPieces(); - if (iPieces < 1) - return; - - CFX_RetainPtr<CFDE_CSSComputedStyle> pStyle; - if (bSavePieces) { - auto pNew = pdfium::MakeUnique<CXFA_PieceLine>(); - CXFA_PieceLine* pPieceLine = pNew.get(); - m_pieceLines.push_back(std::move(pNew)); - if (m_pTabstopContext) - m_pTabstopContext->Reset(); - - FX_FLOAT fLineStep = 0, fBaseLine = 0; - int32_t i = 0; - for (i = 0; i < iPieces; i++) { - const CFX_RTFPiece* pPiece = m_pBreak->GetBreakPiece(i); - CXFA_TextUserData* pUserData = - static_cast<CXFA_TextUserData*>(pPiece->m_pUserData.Get()); - if (pUserData) - pStyle = pUserData->m_pStyle; - FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f; - - auto pTP = pdfium::MakeUnique<XFA_TextPiece>(); - pTP->iChars = pPiece->m_iChars; - pTP->szText = pPiece->GetString(); - pTP->Widths = pPiece->GetWidths(); - pTP->iBidiLevel = pPiece->m_iBidiLevel; - pTP->iHorScale = pPiece->m_iHorizontalScale; - pTP->iVerScale = pPiece->m_iVerticalScale; - m_textParser.GetUnderline(m_pTextProvider, pStyle.Get(), pTP->iUnderline, - pTP->iPeriod); - m_textParser.GetLinethrough(m_pTextProvider, pStyle.Get(), - pTP->iLineThrough); - pTP->dwColor = m_textParser.GetColor(m_pTextProvider, pStyle.Get()); - pTP->pFont = m_textParser.GetFont(m_pTextProvider, pStyle.Get()); - pTP->fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle.Get()); - pTP->rtPiece.left = pPiece->m_iStartPos / 20000.0f; - pTP->rtPiece.width = pPiece->m_iWidth / 20000.0f; - pTP->rtPiece.height = (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f; - FX_FLOAT fBaseLineTemp = - m_textParser.GetBaseline(m_pTextProvider, pStyle.Get()); - pTP->rtPiece.top = fBaseLineTemp; - - FX_FLOAT fLineHeight = m_textParser.GetLineHeight( - m_pTextProvider, pStyle.Get(), m_iLines == 0, fVerScale); - if (fBaseLineTemp > 0) { - FX_FLOAT fLineHeightTmp = fBaseLineTemp + pTP->rtPiece.height; - if (fLineHeight < fLineHeightTmp) - fLineHeight = fLineHeightTmp; - else - fBaseLineTemp = 0; - } else if (fBaseLine < -fBaseLineTemp) { - fBaseLine = -fBaseLineTemp; - } - fLineStep = std::max(fLineStep, fLineHeight); - pTP->pLinkData = pUserData ? pUserData->m_pLinkData : nullptr; - pPieceLine->m_textPieces.push_back(std::move(pTP)); - DoTabstops(pStyle.Get(), pPieceLine); - } - for (const auto& pTP : pPieceLine->m_textPieces) { - FX_FLOAT& fTop = pTP->rtPiece.top; - FX_FLOAT fBaseLineTemp = fTop; - fTop = fLinePos + fLineStep - pTP->rtPiece.height - fBaseLineTemp; - fTop = std::max(0.0f, fTop); - } - fLinePos += fLineStep + fBaseLine; - } else { - FX_FLOAT fLineStep = 0; - FX_FLOAT fLineWidth = 0; - for (int32_t i = 0; i < iPieces; i++) { - const CFX_RTFPiece* pPiece = m_pBreak->GetBreakPiece(i); - CXFA_TextUserData* pUserData = - static_cast<CXFA_TextUserData*>(pPiece->m_pUserData.Get()); - if (pUserData) - pStyle = pUserData->m_pStyle; - FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f; - FX_FLOAT fBaseLine = - m_textParser.GetBaseline(m_pTextProvider, pStyle.Get()); - FX_FLOAT fLineHeight = m_textParser.GetLineHeight( - m_pTextProvider, pStyle.Get(), m_iLines == 0, fVerScale); - if (fBaseLine > 0) { - FX_FLOAT fLineHeightTmp = - fBaseLine + (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f; - if (fLineHeight < fLineHeightTmp) { - fLineHeight = fLineHeightTmp; - } - } - fLineStep = std::max(fLineStep, fLineHeight); - fLineWidth += pPiece->m_iWidth / 20000.0f; - } - fLinePos += fLineStep; - m_fMaxWidth = std::max(m_fMaxWidth, fLineWidth); - if (m_pLoader && m_pLoader->m_bSaveLineHeight) { - FX_FLOAT fHeight = fLinePos - m_pLoader->m_fLastPos; - m_pLoader->m_fLastPos = fLinePos; - m_pLoader->m_lineHeights.Add(fHeight); - } - } - - m_pBreak->ClearBreakPieces(); - if (dwStatus == CFX_RTFBreakType::Paragraph) { - m_pBreak->Reset(); - if (!pStyle && bEndBreak) { - CXFA_Para para = m_pTextProvider->GetParaNode(); - if (para) { - FX_FLOAT fStartPos = para.GetMarginLeft(); - FX_FLOAT fIndent = para.GetTextIndent(); - if (fIndent > 0) - fStartPos += fIndent; - - FX_FLOAT fSpaceBelow = para.GetSpaceBelow(); - if (fSpaceBelow < 0.1f) - fSpaceBelow = 0; - - m_pBreak->SetLineStartPos(fStartPos); - fLinePos += fSpaceBelow; - } - } - } - - if (pStyle) { - FX_FLOAT fStart = 0; - const FDE_CSSRect* pRect = pStyle->GetMarginWidth(); - if (pRect) - fStart = pRect->left.GetValue(); - - FX_FLOAT fTextIndent = pStyle->GetTextIndent().GetValue(); - if (fTextIndent < 0) - fStart -= fTextIndent; - - m_pBreak->SetLineStartPos(fStart); - } - m_iLines++; -} - -void CXFA_TextLayout::RenderString(CFDE_RenderDevice* pDevice, - CFDE_Brush* pBrush, - CXFA_PieceLine* pPieceLine, - int32_t iPiece, - FXTEXT_CHARPOS* pCharPos, - const CFX_Matrix& tmDoc2Device) { - const XFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPiece].get(); - int32_t iCount = GetDisplayPos(pPiece, pCharPos); - if (iCount > 0) { - pBrush->SetColor(pPiece->dwColor); - pDevice->DrawString(pBrush, pPiece->pFont, pCharPos, iCount, - pPiece->fFontSize, &tmDoc2Device); - } - pPieceLine->m_charCounts.Add(iCount); -} - -void CXFA_TextLayout::RenderPath(CFDE_RenderDevice* pDevice, - CFDE_Pen* pPen, - CXFA_PieceLine* pPieceLine, - int32_t iPiece, - FXTEXT_CHARPOS* pCharPos, - const CFX_Matrix& tmDoc2Device) { - XFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPiece].get(); - bool bNoUnderline = pPiece->iUnderline < 1 || pPiece->iUnderline > 2; - bool bNoLineThrough = pPiece->iLineThrough < 1 || pPiece->iLineThrough > 2; - if (bNoUnderline && bNoLineThrough) - return; - - pPen->SetColor(pPiece->dwColor); - std::unique_ptr<CFDE_Path> pPath(new CFDE_Path); - int32_t iChars = GetDisplayPos(pPiece, pCharPos); - if (iChars > 0) { - CFX_PointF pt1, pt2; - FX_FLOAT fEndY = pCharPos[0].m_Origin.y + 1.05f; - if (pPiece->iPeriod == XFA_ATTRIBUTEENUM_Word) { - for (int32_t i = 0; i < pPiece->iUnderline; i++) { - for (int32_t j = 0; j < iChars; j++) { - pt1.x = pCharPos[j].m_Origin.x; - pt2.x = - pt1.x + pCharPos[j].m_FontCharWidth * pPiece->fFontSize / 1000.0f; - pt1.y = pt2.y = fEndY; - pPath->AddLine(pt1, pt2); - } - fEndY += 2.0f; - } - } else { - pt1.x = pCharPos[0].m_Origin.x; - pt2.x = - pCharPos[iChars - 1].m_Origin.x + - pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; - for (int32_t i = 0; i < pPiece->iUnderline; i++) { - pt1.y = pt2.y = fEndY; - pPath->AddLine(pt1, pt2); - fEndY += 2.0f; - } - } - fEndY = pCharPos[0].m_Origin.y - pPiece->rtPiece.height * 0.25f; - pt1.x = pCharPos[0].m_Origin.x; - pt2.x = pCharPos[iChars - 1].m_Origin.x + - pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; - for (int32_t i = 0; i < pPiece->iLineThrough; i++) { - pt1.y = pt2.y = fEndY; - pPath->AddLine(pt1, pt2); - fEndY += 2.0f; - } - } else { - if (bNoLineThrough && - (bNoUnderline || pPiece->iPeriod != XFA_ATTRIBUTEENUM_All)) { - return; - } - int32_t iCharsTmp = 0; - int32_t iPiecePrev = iPiece, iPieceNext = iPiece; - while (iPiecePrev > 0) { - iPiecePrev--; - iCharsTmp = pPieceLine->m_charCounts.GetAt(iPiecePrev); - if (iCharsTmp > 0) - break; - } - if (iCharsTmp == 0) - return; - - iCharsTmp = 0; - int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces); - while (iPieceNext < iPieces - 1) { - iPieceNext++; - iCharsTmp = pPieceLine->m_charCounts.GetAt(iPieceNext); - if (iCharsTmp > 0) - break; - } - if (iCharsTmp == 0) - return; - - FX_FLOAT fOrgX = 0.0f; - FX_FLOAT fEndX = 0.0f; - pPiece = pPieceLine->m_textPieces[iPiecePrev].get(); - iChars = GetDisplayPos(pPiece, pCharPos); - if (iChars < 1) - return; - - fOrgX = pCharPos[iChars - 1].m_Origin.x + - pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; - pPiece = pPieceLine->m_textPieces[iPieceNext].get(); - iChars = GetDisplayPos(pPiece, pCharPos); - if (iChars < 1) - return; - - fEndX = pCharPos[0].m_Origin.x; - CFX_PointF pt1; - CFX_PointF pt2; - pt1.x = fOrgX; - pt2.x = fEndX; - FX_FLOAT fEndY = pCharPos[0].m_Origin.y + 1.05f; - for (int32_t i = 0; i < pPiece->iUnderline; i++) { - pt1.y = fEndY; - pt2.y = fEndY; - pPath->AddLine(pt1, pt2); - fEndY += 2.0f; - } - fEndY = pCharPos[0].m_Origin.y - pPiece->rtPiece.height * 0.25f; - for (int32_t i = 0; i < pPiece->iLineThrough; i++) { - pt1.y = fEndY; - pt2.y = fEndY; - pPath->AddLine(pt1, pt2); - fEndY += 2.0f; - } - } - pDevice->DrawPath(pPen, 1, pPath.get(), &tmDoc2Device); -} - -int32_t CXFA_TextLayout::GetDisplayPos(const XFA_TextPiece* pPiece, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode) { - if (!pPiece) - return 0; - - FX_RTFTEXTOBJ tr; - if (!ToRun(pPiece, &tr)) - return 0; - return m_pBreak->GetDisplayPos(&tr, pCharPos, bCharCode); -} - -bool CXFA_TextLayout::ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ* tr) { - int32_t iLength = pPiece->iChars; - if (iLength < 1) - return false; - - tr->pStr = pPiece->szText; - tr->pFont = pPiece->pFont; - tr->pRect = &pPiece->rtPiece; - tr->pWidths = pPiece->Widths; - tr->iLength = iLength; - tr->fFontSize = pPiece->fFontSize; - tr->iBidiLevel = pPiece->iBidiLevel; - tr->wLineBreakChar = L'\n'; - tr->iVerticalScale = pPiece->iVerScale; - tr->iHorizontalScale = pPiece->iHorScale; - return true; -} diff --git a/xfa/fxfa/app/cxfa_textlayout.h b/xfa/fxfa/app/cxfa_textlayout.h deleted file mode 100644 index d4d60cf81e6946fa2c60c112a72b88bf691427b3..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textlayout.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_TEXTLAYOUT_H_ -#define XFA_FXFA_APP_CXFA_TEXTLAYOUT_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_string.h" -#include "xfa/fde/css/fde_css.h" -#include "xfa/fgas/layout/fgas_rtfbreak.h" -#include "xfa/fxfa/app/cxfa_textparser.h" - -class CFDE_Brush; -class CFDE_CSSComputedStyle; -class CFDE_Pen; -class CFDE_RenderDevice; -class CFDE_XMLNode; -class CFX_RTFBreak; -class CXFA_LoaderContext; -class CXFA_LinkUserData; -class CXFA_Node; -class CXFA_PieceLine; -class CXFA_TextProvider; -class CXFA_TextTabstopsContext; -class XFA_TextPiece; - -class CXFA_TextLayout { - public: - explicit CXFA_TextLayout(CXFA_TextProvider* pTextProvider); - ~CXFA_TextLayout(); - - int32_t GetText(CFX_WideString& wsText); - FX_FLOAT GetLayoutHeight(); - FX_FLOAT StartLayout(FX_FLOAT fWidth = -1); - bool DoLayout(int32_t iBlockIndex, - FX_FLOAT& fCalcHeight, - FX_FLOAT fContentAreaHeight = -1, - FX_FLOAT fTextHeight = -1); - - bool CalcSize(const CFX_SizeF& minSize, - const CFX_SizeF& maxSize, - CFX_SizeF& defaultSize); - bool Layout(const CFX_SizeF& size, FX_FLOAT* fHeight = nullptr); - void ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex); - bool DrawString(CFX_RenderDevice* pFxDevice, - const CFX_Matrix& tmDoc2Device, - const CFX_RectF& rtClip, - int32_t iBlock = 0); - bool IsLoaded() const { return !m_pieceLines.empty(); } - void Unload(); - const std::vector<std::unique_ptr<CXFA_PieceLine>>* GetPieceLines() const { - return &m_pieceLines; - } - - bool m_bHasBlock; - CFX_ArrayTemplate<int32_t> m_Blocks; - - private: - void GetTextDataNode(); - CFDE_XMLNode* GetXMLContainerNode(); - std::unique_ptr<CFX_RTFBreak> CreateBreak(bool bDefault); - void InitBreak(FX_FLOAT fLineWidth); - void InitBreak(CFDE_CSSComputedStyle* pStyle, - FDE_CSSDisplay eDisplay, - FX_FLOAT fLineWidth, - CFDE_XMLNode* pXMLNode, - CFDE_CSSComputedStyle* pParentStyle = nullptr); - bool Loader(const CFX_SizeF& szText, - FX_FLOAT& fLinePos, - bool bSavePieces = true); - void LoadText(CXFA_Node* pNode, - const CFX_SizeF& szText, - FX_FLOAT& fLinePos, - bool bSavePieces); - bool LoadRichText(CFDE_XMLNode* pXMLNode, - const CFX_SizeF& szText, - FX_FLOAT& fLinePos, - const CFX_RetainPtr<CFDE_CSSComputedStyle>& pParentStyle, - bool bSavePieces, - CFX_RetainPtr<CXFA_LinkUserData> pLinkData, - bool bEndBreak = true, - bool bIsOl = false, - int32_t iLiCount = 0); - bool AppendChar(const CFX_WideString& wsText, - FX_FLOAT& fLinePos, - FX_FLOAT fSpaceAbove, - bool bSavePieces); - void AppendTextLine(CFX_RTFBreakType dwStatus, - FX_FLOAT& fLinePos, - bool bSavePieces, - bool bEndBreak = false); - void EndBreak(CFX_RTFBreakType dwStatus, FX_FLOAT& fLinePos, bool bDefault); - bool IsEnd(bool bSavePieces); - void ProcessText(CFX_WideString& wsText); - void UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom); - void RenderString(CFDE_RenderDevice* pDevice, - CFDE_Brush* pBrush, - CXFA_PieceLine* pPieceLine, - int32_t iPiece, - FXTEXT_CHARPOS* pCharPos, - const CFX_Matrix& tmDoc2Device); - void RenderPath(CFDE_RenderDevice* pDevice, - CFDE_Pen* pPen, - CXFA_PieceLine* pPieceLine, - int32_t iPiece, - FXTEXT_CHARPOS* pCharPos, - const CFX_Matrix& tmDoc2Device); - int32_t GetDisplayPos(const XFA_TextPiece* pPiece, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode = false); - bool ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ* tr); - void DoTabstops(CFDE_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine); - bool Layout(int32_t iBlock); - int32_t CountBlocks() const; - - CXFA_TextProvider* m_pTextProvider; - CXFA_Node* m_pTextDataNode; - bool m_bRichText; - std::unique_ptr<CFX_RTFBreak> m_pBreak; - std::unique_ptr<CXFA_LoaderContext> m_pLoader; - int32_t m_iLines; - FX_FLOAT m_fMaxWidth; - CXFA_TextParser m_textParser; - std::vector<std::unique_ptr<CXFA_PieceLine>> m_pieceLines; - std::unique_ptr<CXFA_TextTabstopsContext> m_pTabstopContext; - bool m_bBlockContinue; -}; - -#endif // XFA_FXFA_APP_CXFA_TEXTLAYOUT_H_ diff --git a/xfa/fxfa/app/cxfa_textparsecontext.cpp b/xfa/fxfa/app/cxfa_textparsecontext.cpp deleted file mode 100644 index 851d84456b8bd0db7cb74bea8094ebc1b5e892dd..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textparsecontext.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/cxfa_textparsecontext.h" - -#include "xfa/fde/css/cfde_csscomputedstyle.h" -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/cfde_cssstyleselector.h" - -CXFA_TextParseContext::CXFA_TextParseContext() - : m_pParentStyle(nullptr), - m_eDisplay(FDE_CSSDisplay::None) {} - -CXFA_TextParseContext::~CXFA_TextParseContext() {} diff --git a/xfa/fxfa/app/cxfa_textparsecontext.h b/xfa/fxfa/app/cxfa_textparsecontext.h deleted file mode 100644 index 5ea68e947392dba36cd3e17ad177ee5bcd9d5d22..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textparsecontext.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_TEXTPARSECONTEXT_H_ -#define XFA_FXFA_APP_CXFA_TEXTPARSECONTEXT_H_ - -#include <utility> -#include <vector> - -#include "third_party/base/stl_util.h" -#include "xfa/fde/css/cfde_cssdeclaration.h" -#include "xfa/fde/css/fde_css.h" - -class CFDE_CSSComputedStyle; - -class CXFA_TextParseContext { - public: - CXFA_TextParseContext(); - ~CXFA_TextParseContext(); - - void SetDisplay(FDE_CSSDisplay eDisplay) { m_eDisplay = eDisplay; } - FDE_CSSDisplay GetDisplay() const { return m_eDisplay; } - - void SetDecls(std::vector<const CFDE_CSSDeclaration*>&& decl) { - decls_ = std::move(decl); - } - const std::vector<const CFDE_CSSDeclaration*>& GetDecls() { return decls_; } - - CFX_RetainPtr<CFDE_CSSComputedStyle> m_pParentStyle; - - protected: - std::vector<const CFDE_CSSDeclaration*> decls_; - FDE_CSSDisplay m_eDisplay; -}; - -#endif // XFA_FXFA_APP_CXFA_TEXTPARSECONTEXT_H_ diff --git a/xfa/fxfa/app/cxfa_textparser.cpp b/xfa/fxfa/app/cxfa_textparser.cpp deleted file mode 100644 index 9759cb219d29301841c44c10652ec639318872b5..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textparser.cpp +++ /dev/null @@ -1,640 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/cxfa_textparser.h" - -#include <algorithm> -#include <utility> -#include <vector> - -#include "third_party/base/ptr_util.h" -#include "xfa/fde/css/cfde_csscomputedstyle.h" -#include "xfa/fde/css/cfde_cssstyleselector.h" -#include "xfa/fde/css/cfde_cssstylesheet.h" -#include "xfa/fde/css/fde_css.h" -#include "xfa/fgas/crt/fgas_codepage.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" -#include "xfa/fxfa/app/cxfa_csstagprovider.h" -#include "xfa/fxfa/app/cxfa_textparsecontext.h" -#include "xfa/fxfa/app/cxfa_texttabstopscontext.h" -#include "xfa/fxfa/app/xfa_ffwidgetacc.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_fontmgr.h" - -namespace { - -enum class TabStopStatus { - Error, - EOS, - None, - Alignment, - StartLeader, - Leader, - Location, -}; - -} // namespace - -CXFA_TextParser::CXFA_TextParser() - : m_bParsed(false), m_cssInitialized(false) {} - -CXFA_TextParser::~CXFA_TextParser() { - for (auto& pair : m_mapXMLNodeToParseContext) { - if (pair.second) - delete pair.second; - } -} - -void CXFA_TextParser::Reset() { - for (auto& pair : m_mapXMLNodeToParseContext) { - if (pair.second) - delete pair.second; - } - m_mapXMLNodeToParseContext.clear(); - m_bParsed = false; -} -void CXFA_TextParser::InitCSSData(CXFA_TextProvider* pTextProvider) { - if (!pTextProvider) - return; - - if (!m_pSelector) { - CXFA_FFDoc* pDoc = pTextProvider->GetDocNode(); - CFGAS_FontMgr* pFontMgr = pDoc->GetApp()->GetFDEFontMgr(); - ASSERT(pFontMgr); - m_pSelector = pdfium::MakeUnique<CFDE_CSSStyleSelector>(pFontMgr); - FX_FLOAT fFontSize = 10; - CXFA_Font font = pTextProvider->GetFontNode(); - if (font) { - fFontSize = font.GetFontSize(); - } - m_pSelector->SetDefFontSize(fFontSize); - } - - if (m_cssInitialized) - return; - - m_cssInitialized = true; - auto uaSheet = LoadDefaultSheetStyle(); - m_pSelector->SetUAStyleSheet(std::move(uaSheet)); - m_pSelector->UpdateStyleIndex(); -} - -std::unique_ptr<CFDE_CSSStyleSheet> CXFA_TextParser::LoadDefaultSheetStyle() { - static const FX_WCHAR s_pStyle[] = - L"html,body,ol,p,ul{display:block}" - L"li{display:list-item}" - L"ol,ul{padding-left:33px;margin:1.12em 0}" - L"ol{list-style-type:decimal}" - L"a{color:#0000ff;text-decoration:underline}" - L"b{font-weight:bolder}" - L"i{font-style:italic}" - L"sup{vertical-align:+15em;font-size:.66em}" - L"sub{vertical-align:-15em;font-size:.66em}"; - - auto sheet = pdfium::MakeUnique<CFDE_CSSStyleSheet>(); - return sheet->LoadBuffer(s_pStyle, FXSYS_wcslen(s_pStyle)) ? std::move(sheet) - : nullptr; -} - -CFX_RetainPtr<CFDE_CSSComputedStyle> CXFA_TextParser::CreateRootStyle( - CXFA_TextProvider* pTextProvider) { - CXFA_Font font = pTextProvider->GetFontNode(); - CXFA_Para para = pTextProvider->GetParaNode(); - auto pStyle = m_pSelector->CreateComputedStyle(nullptr); - FX_FLOAT fLineHeight = 0; - FX_FLOAT fFontSize = 10; - - if (para) { - fLineHeight = para.GetLineHeight(); - FDE_CSSLength indent; - indent.Set(FDE_CSSLengthUnit::Point, para.GetTextIndent()); - pStyle->SetTextIndent(indent); - FDE_CSSTextAlign hAlign = FDE_CSSTextAlign::Left; - switch (para.GetHorizontalAlign()) { - case XFA_ATTRIBUTEENUM_Center: - hAlign = FDE_CSSTextAlign::Center; - break; - case XFA_ATTRIBUTEENUM_Right: - hAlign = FDE_CSSTextAlign::Right; - break; - case XFA_ATTRIBUTEENUM_Justify: - hAlign = FDE_CSSTextAlign::Justify; - break; - case XFA_ATTRIBUTEENUM_JustifyAll: - hAlign = FDE_CSSTextAlign::JustifyAll; - break; - } - pStyle->SetTextAlign(hAlign); - FDE_CSSRect rtMarginWidth; - rtMarginWidth.left.Set(FDE_CSSLengthUnit::Point, para.GetMarginLeft()); - rtMarginWidth.top.Set(FDE_CSSLengthUnit::Point, para.GetSpaceAbove()); - rtMarginWidth.right.Set(FDE_CSSLengthUnit::Point, para.GetMarginRight()); - rtMarginWidth.bottom.Set(FDE_CSSLengthUnit::Point, para.GetSpaceBelow()); - pStyle->SetMarginWidth(rtMarginWidth); - } - - if (font) { - pStyle->SetColor(font.GetColor()); - pStyle->SetFontStyle(font.IsItalic() ? FDE_CSSFontStyle::Italic - : FDE_CSSFontStyle::Normal); - pStyle->SetFontWeight(font.IsBold() ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - pStyle->SetNumberVerticalAlign(-font.GetBaselineShift()); - fFontSize = font.GetFontSize(); - FDE_CSSLength letterSpacing; - letterSpacing.Set(FDE_CSSLengthUnit::Point, font.GetLetterSpacing()); - pStyle->SetLetterSpacing(letterSpacing); - uint32_t dwDecoration = 0; - if (font.GetLineThrough() > 0) - dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough; - if (font.GetUnderline() > 1) - dwDecoration |= FDE_CSSTEXTDECORATION_Double; - else if (font.GetUnderline() > 0) - dwDecoration |= FDE_CSSTEXTDECORATION_Underline; - - pStyle->SetTextDecoration(dwDecoration); - } - pStyle->SetLineHeight(fLineHeight); - pStyle->SetFontSize(fFontSize); - return pStyle; -} - -CFX_RetainPtr<CFDE_CSSComputedStyle> CXFA_TextParser::CreateStyle( - CFDE_CSSComputedStyle* pParentStyle) { - auto pNewStyle = m_pSelector->CreateComputedStyle(pParentStyle); - ASSERT(pNewStyle); - if (!pParentStyle) - return pNewStyle; - - uint32_t dwDecoration = pParentStyle->GetTextDecoration(); - FX_FLOAT fBaseLine = 0; - if (pParentStyle->GetVerticalAlign() == FDE_CSSVerticalAlign::Number) - fBaseLine = pParentStyle->GetNumberVerticalAlign(); - - pNewStyle->SetTextDecoration(dwDecoration); - pNewStyle->SetNumberVerticalAlign(fBaseLine); - - const FDE_CSSRect* pRect = pParentStyle->GetMarginWidth(); - if (pRect) - pNewStyle->SetMarginWidth(*pRect); - return pNewStyle; -} - -CFX_RetainPtr<CFDE_CSSComputedStyle> CXFA_TextParser::ComputeStyle( - CFDE_XMLNode* pXMLNode, - CFDE_CSSComputedStyle* pParentStyle) { - auto it = m_mapXMLNodeToParseContext.find(pXMLNode); - if (it == m_mapXMLNodeToParseContext.end()) - return nullptr; - - CXFA_TextParseContext* pContext = it->second; - if (!pContext) - return nullptr; - - pContext->m_pParentStyle.Reset(pParentStyle); - - auto tagProvider = ParseTagInfo(pXMLNode); - if (tagProvider->m_bContent) - return nullptr; - - auto pStyle = CreateStyle(pParentStyle); - m_pSelector->ComputeStyle(pContext->GetDecls(), - tagProvider->GetAttribute(L"style"), - tagProvider->GetAttribute(L"align"), pStyle.Get()); - return pStyle; -} - -void CXFA_TextParser::DoParse(CFDE_XMLNode* pXMLContainer, - CXFA_TextProvider* pTextProvider) { - if (!pXMLContainer || !pTextProvider || m_bParsed) - return; - - m_bParsed = true; - InitCSSData(pTextProvider); - auto pRootStyle = CreateRootStyle(pTextProvider); - ParseRichText(pXMLContainer, pRootStyle.Get()); -} - -void CXFA_TextParser::ParseRichText(CFDE_XMLNode* pXMLNode, - CFDE_CSSComputedStyle* pParentStyle) { - if (!pXMLNode) - return; - - auto tagProvider = ParseTagInfo(pXMLNode); - if (!tagProvider->m_bTagAvailable) - return; - - CFX_RetainPtr<CFDE_CSSComputedStyle> pNewStyle; - if ((tagProvider->GetTagName() != L"body") || - (tagProvider->GetTagName() != L"html")) { - CXFA_TextParseContext* pTextContext = new CXFA_TextParseContext; - FDE_CSSDisplay eDisplay = FDE_CSSDisplay::Inline; - if (!tagProvider->m_bContent) { - auto declArray = - m_pSelector->MatchDeclarations(tagProvider->GetTagName()); - pNewStyle = CreateStyle(pParentStyle); - m_pSelector->ComputeStyle(declArray, tagProvider->GetAttribute(L"style"), - tagProvider->GetAttribute(L"align"), - pNewStyle.Get()); - - if (!declArray.empty()) - pTextContext->SetDecls(std::move(declArray)); - - eDisplay = pNewStyle->GetDisplay(); - } - pTextContext->SetDisplay(eDisplay); - m_mapXMLNodeToParseContext[pXMLNode] = pTextContext; - } - - for (CFDE_XMLNode* pXMLChild = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { - ParseRichText(pXMLChild, pNewStyle.Get()); - } -} - -bool CXFA_TextParser::TagValidate(const CFX_WideString& wsName) const { - static const uint32_t s_XFATagName[] = { - 0x61, // a - 0x62, // b - 0x69, // i - 0x70, // p - 0x0001f714, // br - 0x00022a55, // li - 0x000239bb, // ol - 0x00025881, // ul - 0x0bd37faa, // sub - 0x0bd37fb8, // sup - 0xa73e3af2, // span - 0xb182eaae, // body - 0xdb8ac455, // html - }; - static const int32_t s_iCount = FX_ArraySize(s_XFATagName); - - return std::binary_search(s_XFATagName, s_XFATagName + s_iCount, - FX_HashCode_GetW(wsName.AsStringC(), true)); -} - -std::unique_ptr<CXFA_CSSTagProvider> CXFA_TextParser::ParseTagInfo( - CFDE_XMLNode* pXMLNode) { - auto tagProvider = pdfium::MakeUnique<CXFA_CSSTagProvider>(); - - CFX_WideString wsName; - if (pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - pXMLElement->GetLocalTagName(wsName); - tagProvider->SetTagName(wsName); - tagProvider->m_bTagAvailable = TagValidate(wsName); - - CFX_WideString wsValue; - pXMLElement->GetString(L"style", wsValue); - if (!wsValue.IsEmpty()) - tagProvider->SetAttribute(L"style", wsValue); - } else if (pXMLNode->GetType() == FDE_XMLNODE_Text) { - tagProvider->m_bTagAvailable = true; - tagProvider->m_bContent = true; - } - return tagProvider; -} - -int32_t CXFA_TextParser::GetVAlign(CXFA_TextProvider* pTextProvider) const { - CXFA_Para para = pTextProvider->GetParaNode(); - return para ? para.GetVerticalAlign() : XFA_ATTRIBUTEENUM_Top; -} - -FX_FLOAT CXFA_TextParser::GetTabInterval(CFDE_CSSComputedStyle* pStyle) const { - CFX_WideString wsValue; - if (pStyle && pStyle->GetCustomStyle(L"tab-interval", wsValue)) - return CXFA_Measurement(wsValue.AsStringC()).ToUnit(XFA_UNIT_Pt); - return 36; -} - -int32_t CXFA_TextParser::CountTabs(CFDE_CSSComputedStyle* pStyle) const { - CFX_WideString wsValue; - if (pStyle && pStyle->GetCustomStyle(L"xfa-tab-count", wsValue)) - return wsValue.GetInteger(); - return 0; -} - -bool CXFA_TextParser::IsSpaceRun(CFDE_CSSComputedStyle* pStyle) const { - CFX_WideString wsValue; - if (pStyle && pStyle->GetCustomStyle(L"xfa-spacerun", wsValue)) { - wsValue.MakeLower(); - return wsValue == L"yes"; - } - return false; -} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_TextParser::GetFont( - CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const { - CFX_WideStringC wsFamily = L"Courier"; - uint32_t dwStyle = 0; - CXFA_Font font = pTextProvider->GetFontNode(); - if (font) { - font.GetTypeface(wsFamily); - if (font.IsBold()) - dwStyle |= FX_FONTSTYLE_Bold; - if (font.IsItalic()) - dwStyle |= FX_FONTSTYLE_Italic; - } - - if (pStyle) { - int32_t iCount = pStyle->CountFontFamilies(); - if (iCount > 0) - wsFamily = pStyle->GetFontFamily(iCount - 1).AsStringC(); - - dwStyle = 0; - if (pStyle->GetFontWeight() > FXFONT_FW_NORMAL) - dwStyle |= FX_FONTSTYLE_Bold; - if (pStyle->GetFontStyle() == FDE_CSSFontStyle::Italic) - dwStyle |= FX_FONTSTYLE_Italic; - } - - CXFA_FFDoc* pDoc = pTextProvider->GetDocNode(); - CXFA_FontMgr* pFontMgr = pDoc->GetApp()->GetXFAFontMgr(); - return pFontMgr->GetFont(pDoc, wsFamily, dwStyle); -} - -FX_FLOAT CXFA_TextParser::GetFontSize(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const { - if (pStyle) - return pStyle->GetFontSize(); - - CXFA_Font font = pTextProvider->GetFontNode(); - if (font) - return font.GetFontSize(); - return 10; -} - -int32_t CXFA_TextParser::GetHorScale(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - CFDE_XMLNode* pXMLNode) const { - if (pStyle) { - CFX_WideString wsValue; - if (pStyle->GetCustomStyle(L"xfa-font-horizontal-scale", wsValue)) - return wsValue.GetInteger(); - - while (pXMLNode) { - auto it = m_mapXMLNodeToParseContext.find(pXMLNode); - if (it != m_mapXMLNodeToParseContext.end()) { - CXFA_TextParseContext* pContext = it->second; - if (pContext && pContext->m_pParentStyle && - pContext->m_pParentStyle->GetCustomStyle( - L"xfa-font-horizontal-scale", wsValue)) { - return wsValue.GetInteger(); - } - } - pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::Parent); - } - } - - if (CXFA_Font font = pTextProvider->GetFontNode()) - return static_cast<int32_t>(font.GetHorizontalScale()); - return 100; -} - -int32_t CXFA_TextParser::GetVerScale(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const { - if (pStyle) { - CFX_WideString wsValue; - if (pStyle->GetCustomStyle(L"xfa-font-vertical-scale", wsValue)) - return wsValue.GetInteger(); - } - - if (CXFA_Font font = pTextProvider->GetFontNode()) - return (int32_t)font.GetVerticalScale(); - return 100; -} - -void CXFA_TextParser::GetUnderline(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - int32_t& iUnderline, - int32_t& iPeriod) const { - iUnderline = 0; - iPeriod = XFA_ATTRIBUTEENUM_All; - if (!pStyle) { - CXFA_Font font = pTextProvider->GetFontNode(); - if (font) { - iUnderline = font.GetUnderline(); - iPeriod = font.GetUnderlinePeriod(); - } - return; - } - - uint32_t dwDecoration = pStyle->GetTextDecoration(); - if (dwDecoration & FDE_CSSTEXTDECORATION_Double) - iUnderline = 2; - else if (dwDecoration & FDE_CSSTEXTDECORATION_Underline) - iUnderline = 1; - - CFX_WideString wsValue; - if (pStyle->GetCustomStyle(L"underlinePeriod", wsValue)) { - if (wsValue == L"word") - iPeriod = XFA_ATTRIBUTEENUM_Word; - } else if (CXFA_Font font = pTextProvider->GetFontNode()) { - iPeriod = font.GetUnderlinePeriod(); - } -} - -void CXFA_TextParser::GetLinethrough(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - int32_t& iLinethrough) const { - if (pStyle) { - uint32_t dwDecoration = pStyle->GetTextDecoration(); - iLinethrough = (dwDecoration & FDE_CSSTEXTDECORATION_LineThrough) ? 1 : 0; - return; - } - - CXFA_Font font = pTextProvider->GetFontNode(); - if (font) - iLinethrough = font.GetLineThrough(); -} - -FX_ARGB CXFA_TextParser::GetColor(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const { - if (pStyle) - return pStyle->GetColor(); - if (CXFA_Font font = pTextProvider->GetFontNode()) - return font.GetColor(); - - return 0xFF000000; -} - -FX_FLOAT CXFA_TextParser::GetBaseline(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const { - if (pStyle) { - if (pStyle->GetVerticalAlign() == FDE_CSSVerticalAlign::Number) - return pStyle->GetNumberVerticalAlign(); - } else if (CXFA_Font font = pTextProvider->GetFontNode()) { - return font.GetBaselineShift(); - } - return 0; -} - -FX_FLOAT CXFA_TextParser::GetLineHeight(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - bool bFirst, - FX_FLOAT fVerScale) const { - FX_FLOAT fLineHeight = 0; - if (pStyle) - fLineHeight = pStyle->GetLineHeight(); - else if (CXFA_Para para = pTextProvider->GetParaNode()) - fLineHeight = para.GetLineHeight(); - - if (bFirst) { - FX_FLOAT fFontSize = GetFontSize(pTextProvider, pStyle); - if (fLineHeight < 0.1f) - fLineHeight = fFontSize; - else - fLineHeight = std::min(fLineHeight, fFontSize); - } else if (fLineHeight < 0.1f) { - fLineHeight = GetFontSize(pTextProvider, pStyle) * 1.2f; - } - fLineHeight *= fVerScale; - return fLineHeight; -} - -bool CXFA_TextParser::GetEmbbedObj(CXFA_TextProvider* pTextProvider, - CFDE_XMLNode* pXMLNode, - CFX_WideString& wsValue) { - wsValue.clear(); - if (!pXMLNode) - return false; - - bool bRet = false; - if (pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pElement = static_cast<CFDE_XMLElement*>(pXMLNode); - CFX_WideString wsAttr; - pElement->GetString(L"xfa:embed", wsAttr); - if (wsAttr.IsEmpty()) - return false; - if (wsAttr.GetAt(0) == L'#') - wsAttr.Delete(0); - - CFX_WideString ws; - pElement->GetString(L"xfa:embedType", ws); - if (ws.IsEmpty()) - ws = L"som"; - else - ws.MakeLower(); - - bool bURI = (ws == L"uri"); - if (!bURI && ws != L"som") - return false; - - ws.clear(); - pElement->GetString(L"xfa:embedMode", ws); - if (ws.IsEmpty()) - ws = L"formatted"; - else - ws.MakeLower(); - - bool bRaw = (ws == L"raw"); - if (!bRaw && ws != L"formatted") - return false; - - bRet = pTextProvider->GetEmbbedObj(bURI, bRaw, wsAttr, wsValue); - } - return bRet; -} - -CXFA_TextParseContext* CXFA_TextParser::GetParseContextFromMap( - CFDE_XMLNode* pXMLNode) { - auto it = m_mapXMLNodeToParseContext.find(pXMLNode); - return it != m_mapXMLNodeToParseContext.end() ? it->second : nullptr; -} - -bool CXFA_TextParser::GetTabstops(CFDE_CSSComputedStyle* pStyle, - CXFA_TextTabstopsContext* pTabstopContext) { - if (!pStyle || !pTabstopContext) - return false; - - CFX_WideString wsValue; - if (!pStyle->GetCustomStyle(L"xfa-tab-stops", wsValue) && - !pStyle->GetCustomStyle(L"tab-stops", wsValue)) { - return false; - } - - int32_t iLength = wsValue.GetLength(); - const FX_WCHAR* pTabStops = wsValue.c_str(); - int32_t iCur = 0; - int32_t iLast = 0; - CFX_WideString wsAlign; - TabStopStatus eStatus = TabStopStatus::None; - FX_WCHAR ch; - while (iCur < iLength) { - ch = pTabStops[iCur]; - switch (eStatus) { - case TabStopStatus::None: - if (ch <= ' ') { - iCur++; - } else { - eStatus = TabStopStatus::Alignment; - iLast = iCur; - } - break; - case TabStopStatus::Alignment: - if (ch == ' ') { - wsAlign = CFX_WideStringC(pTabStops + iLast, iCur - iLast); - eStatus = TabStopStatus::StartLeader; - iCur++; - while (iCur < iLength && pTabStops[iCur] <= ' ') - iCur++; - iLast = iCur; - } else { - iCur++; - } - break; - case TabStopStatus::StartLeader: - if (ch != 'l') { - eStatus = TabStopStatus::Location; - } else { - int32_t iCount = 0; - while (iCur < iLength) { - ch = pTabStops[iCur]; - iCur++; - if (ch == '(') { - iCount++; - } else if (ch == ')') { - iCount--; - if (iCount == 0) - break; - } - } - while (iCur < iLength && pTabStops[iCur] <= ' ') - iCur++; - - iLast = iCur; - eStatus = TabStopStatus::Location; - } - break; - case TabStopStatus::Location: - if (ch == ' ') { - uint32_t dwHashCode = FX_HashCode_GetW(wsAlign.AsStringC(), true); - CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast)); - FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt); - pTabstopContext->Append(dwHashCode, fPos); - wsAlign.clear(); - eStatus = TabStopStatus::None; - } - iCur++; - break; - default: - break; - } - } - - if (!wsAlign.IsEmpty()) { - uint32_t dwHashCode = FX_HashCode_GetW(wsAlign.AsStringC(), true); - CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast)); - FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt); - pTabstopContext->Append(dwHashCode, fPos); - } - return true; -} diff --git a/xfa/fxfa/app/cxfa_textparser.h b/xfa/fxfa/app/cxfa_textparser.h deleted file mode 100644 index 86da502dbf064bc67699c9e05cf3d4a44e8d5cc1..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textparser.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_TEXTPARSER_H_ -#define XFA_FXFA_APP_CXFA_TEXTPARSER_H_ - -#include <map> -#include <memory> - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fgas/font/cfgas_gefont.h" - -class CFDE_CSSComputedStyle; -class CFDE_CSSStyleSelector; -class CFDE_CSSStyleSheet; -class CFDE_XMLNode; -class CXFA_CSSTagProvider; -class CXFA_TextParseContext; -class CXFA_TextProvider; -class CXFA_TextTabstopsContext; - -class CXFA_TextParser { - public: - CXFA_TextParser(); - virtual ~CXFA_TextParser(); - - void Reset(); - void DoParse(CFDE_XMLNode* pXMLContainer, CXFA_TextProvider* pTextProvider); - - CFX_RetainPtr<CFDE_CSSComputedStyle> CreateRootStyle( - CXFA_TextProvider* pTextProvider); - CFX_RetainPtr<CFDE_CSSComputedStyle> ComputeStyle( - CFDE_XMLNode* pXMLNode, - CFDE_CSSComputedStyle* pParentStyle); - - bool IsParsed() const { return m_bParsed; } - - int32_t GetVAlign(CXFA_TextProvider* pTextProvider) const; - - FX_FLOAT GetTabInterval(CFDE_CSSComputedStyle* pStyle) const; - int32_t CountTabs(CFDE_CSSComputedStyle* pStyle) const; - - bool IsSpaceRun(CFDE_CSSComputedStyle* pStyle) const; - bool GetTabstops(CFDE_CSSComputedStyle* pStyle, - CXFA_TextTabstopsContext* pTabstopContext); - - CFX_RetainPtr<CFGAS_GEFont> GetFont(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const; - FX_FLOAT GetFontSize(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const; - - int32_t GetHorScale(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - CFDE_XMLNode* pXMLNode) const; - int32_t GetVerScale(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const; - - void GetUnderline(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - int32_t& iUnderline, - int32_t& iPeriod) const; - void GetLinethrough(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - int32_t& iLinethrough) const; - FX_ARGB GetColor(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const; - FX_FLOAT GetBaseline(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle) const; - FX_FLOAT GetLineHeight(CXFA_TextProvider* pTextProvider, - CFDE_CSSComputedStyle* pStyle, - bool bFirst, - FX_FLOAT fVerScale) const; - - bool GetEmbbedObj(CXFA_TextProvider* pTextProvider, - CFDE_XMLNode* pXMLNode, - CFX_WideString& wsValue); - CXFA_TextParseContext* GetParseContextFromMap(CFDE_XMLNode* pXMLNode); - - protected: - bool TagValidate(const CFX_WideString& str) const; - - private: - void InitCSSData(CXFA_TextProvider* pTextProvider); - void ParseRichText(CFDE_XMLNode* pXMLNode, - CFDE_CSSComputedStyle* pParentStyle); - std::unique_ptr<CXFA_CSSTagProvider> ParseTagInfo(CFDE_XMLNode* pXMLNode); - std::unique_ptr<CFDE_CSSStyleSheet> LoadDefaultSheetStyle(); - CFX_RetainPtr<CFDE_CSSComputedStyle> CreateStyle( - CFDE_CSSComputedStyle* pParentStyle); - - std::unique_ptr<CFDE_CSSStyleSelector> m_pSelector; - std::map<CFDE_XMLNode*, CXFA_TextParseContext*> m_mapXMLNodeToParseContext; - bool m_bParsed; - bool m_cssInitialized; -}; - -#endif // XFA_FXFA_APP_CXFA_TEXTPARSER_H_ diff --git a/xfa/fxfa/app/cxfa_texttabstopscontext.cpp b/xfa/fxfa/app/cxfa_texttabstopscontext.cpp deleted file mode 100644 index 3209603af3b7575f1d2e9e6ed27a172de74c110d..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_texttabstopscontext.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/cxfa_texttabstopscontext.h" - -CXFA_TextTabstopsContext::CXFA_TextTabstopsContext() - : m_iTabCount(0), - m_iTabIndex(-1), - m_bTabstops(false), - m_fTabWidth(0), - m_fLeft(0) {} - -CXFA_TextTabstopsContext::~CXFA_TextTabstopsContext() {} - -void CXFA_TextTabstopsContext::Append(uint32_t dwAlign, FX_FLOAT fTabstops) { - int32_t i = 0; - for (i = 0; i < m_iTabCount; i++) { - XFA_TABSTOPS* pTabstop = m_tabstops.GetDataPtr(i); - if (fTabstops < pTabstop->fTabstops) { - break; - } - } - m_tabstops.InsertSpaceAt(i, 1); - XFA_TABSTOPS tabstop; - tabstop.dwAlign = dwAlign; - tabstop.fTabstops = fTabstops; - m_tabstops.SetAt(i, tabstop); - m_iTabCount++; -} - -void CXFA_TextTabstopsContext::RemoveAll() { - m_tabstops.RemoveAll(); - m_iTabCount = 0; -} - -void CXFA_TextTabstopsContext::Reset() { - m_iTabIndex = -1; - m_bTabstops = false; - m_fTabWidth = 0; - m_fLeft = 0; -} diff --git a/xfa/fxfa/app/cxfa_texttabstopscontext.h b/xfa/fxfa/app/cxfa_texttabstopscontext.h deleted file mode 100644 index 8fe0e6273f37849c9ca90570b8ef08e37f13fbaa..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_texttabstopscontext.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_TEXTTABSTOPSCONTEXT_H_ -#define XFA_FXFA_APP_CXFA_TEXTTABSTOPSCONTEXT_H_ - -#include "core/fxcrt/fx_basic.h" - -struct XFA_TABSTOPS { - uint32_t dwAlign; - FX_FLOAT fTabstops; -}; - -class CXFA_TextTabstopsContext { - public: - CXFA_TextTabstopsContext(); - ~CXFA_TextTabstopsContext(); - - void Append(uint32_t dwAlign, FX_FLOAT fTabstops); - void RemoveAll(); - void Reset(); - - CFX_ArrayTemplate<XFA_TABSTOPS> m_tabstops; - int32_t m_iTabCount; - int32_t m_iTabIndex; - bool m_bTabstops; - FX_FLOAT m_fTabWidth; - FX_FLOAT m_fLeft; -}; - -#endif // XFA_FXFA_APP_CXFA_TEXTTABSTOPSCONTEXT_H_ diff --git a/xfa/fxfa/app/cxfa_textuserdata.cpp b/xfa/fxfa/app/cxfa_textuserdata.cpp deleted file mode 100644 index e4e549316aeb6a9ac86510f6083099d6cb0fa3e1..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textuserdata.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/cxfa_textuserdata.h" - -#include "xfa/fde/css/cfde_csscomputedstyle.h" -#include "xfa/fde/css/cfde_cssstyleselector.h" -#include "xfa/fde/css/fde_css.h" -#include "xfa/fxfa/app/cxfa_linkuserdata.h" - -CXFA_TextUserData::CXFA_TextUserData( - const CFX_RetainPtr<CFDE_CSSComputedStyle>& pStyle) - : m_pStyle(pStyle) {} - -CXFA_TextUserData::CXFA_TextUserData( - const CFX_RetainPtr<CFDE_CSSComputedStyle>& pStyle, - const CFX_RetainPtr<CXFA_LinkUserData>& pLinkData) - : m_pStyle(pStyle), m_pLinkData(pLinkData) {} - -CXFA_TextUserData::~CXFA_TextUserData() {} diff --git a/xfa/fxfa/app/cxfa_textuserdata.h b/xfa/fxfa/app/cxfa_textuserdata.h deleted file mode 100644 index b0eff73f2e9aa9d5f4931375bc89c73cdbe26859..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/cxfa_textuserdata.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_CXFA_TEXTUSERDATA_H_ -#define XFA_FXFA_APP_CXFA_TEXTUSERDATA_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_basic.h" - -class CFDE_CSSComputedStyle; -class CXFA_LinkUserData; - -class CXFA_TextUserData : public CFX_Retainable { - public: - template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - CFX_RetainPtr<CFDE_CSSComputedStyle> m_pStyle; - CFX_RetainPtr<CXFA_LinkUserData> m_pLinkData; - - protected: - explicit CXFA_TextUserData( - const CFX_RetainPtr<CFDE_CSSComputedStyle>& pStyle); - CXFA_TextUserData(const CFX_RetainPtr<CFDE_CSSComputedStyle>& pStyle, - const CFX_RetainPtr<CXFA_LinkUserData>& pLinkData); - ~CXFA_TextUserData() override; -}; - -#endif // XFA_FXFA_APP_CXFA_TEXTUSERDATA_H_ diff --git a/xfa/fxfa/app/xfa_checksum.cpp b/xfa/fxfa/app/xfa_checksum.cpp deleted file mode 100644 index 09c42719c11e0f8a3175eca65b636516d1496ec9..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_checksum.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_checksum.h" - -#include "core/fdrm/crypto/fx_crypt.h" -#include "third_party/base/ptr_util.h" - -namespace { - -struct FX_BASE64DATA { - uint32_t data1 : 2; - uint32_t data2 : 6; - uint32_t data3 : 4; - uint32_t data4 : 4; - uint32_t data5 : 6; - uint32_t data6 : 2; - uint32_t data7 : 8; -}; - -const 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', '+', '/', -}; - -void Base64EncodePiece(const FX_BASE64DATA& src, - int32_t iBytes, - FX_CHAR dst[4]) { - dst[0] = g_FXBase64EncoderMap[src.data2]; - uint32_t 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] = '='; - } -} - -int32_t Base64EncodeA(const uint8_t* pSrc, int32_t iSrcLen, FX_CHAR* pDst) { - ASSERT(pSrc); - if (iSrcLen < 1) { - return 0; - } - if (!pDst) { - int32_t iDstLen = iSrcLen / 3 * 4; - if ((iSrcLen % 3) != 0) { - iDstLen += 4; - } - return iDstLen; - } - FX_BASE64DATA srcData; - int32_t iBytes = 3; - FX_CHAR* pDstEnd = pDst; - while (iSrcLen > 0) { - if (iSrcLen > 2) { - ((uint8_t*)&srcData)[0] = *pSrc++; - ((uint8_t*)&srcData)[1] = *pSrc++; - ((uint8_t*)&srcData)[2] = *pSrc++; - iSrcLen -= 3; - } else { - *((uint32_t*)&srcData) = 0; - ((uint8_t*)&srcData)[0] = *pSrc++; - if (iSrcLen > 1) { - ((uint8_t*)&srcData)[1] = *pSrc++; - } - iBytes = iSrcLen; - iSrcLen = 0; - } - Base64EncodePiece(srcData, iBytes, pDstEnd); - pDstEnd += 4; - } - return pDstEnd - pDst; -} - -} // namespace - -CXFA_SAXReaderHandler::CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext) - : m_pContext(pContext) { - ASSERT(m_pContext); -} -CXFA_SAXReaderHandler::~CXFA_SAXReaderHandler() {} -CXFA_SAXContext* CXFA_SAXReaderHandler::OnTagEnter( - const CFX_ByteStringC& bsTagName, - CFX_SAXItem::Type eType, - uint32_t dwStartPos) { - UpdateChecksum(true); - if (eType != CFX_SAXItem::Type::Tag && - eType != CFX_SAXItem::Type::Instruction) { - return nullptr; - } - m_SAXContext.m_eNode = eType; - CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf; - textBuf << "<"; - if (eType == CFX_SAXItem::Type::Instruction) { - textBuf << "?"; - } - textBuf << bsTagName; - m_SAXContext.m_bsTagName = bsTagName; - return &m_SAXContext; -} - -void CXFA_SAXReaderHandler::OnTagAttribute(CXFA_SAXContext* pTag, - const CFX_ByteStringC& bsAttri, - const CFX_ByteStringC& bsValue) { - if (!pTag) - return; - - pTag->m_TextBuf << " " << bsAttri << "=\"" << bsValue << "\""; -} - -void CXFA_SAXReaderHandler::OnTagBreak(CXFA_SAXContext* pTag) { - if (!pTag) - return; - - pTag->m_TextBuf << ">"; - UpdateChecksum(false); -} - -void CXFA_SAXReaderHandler::OnTagData(CXFA_SAXContext* pTag, - CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, - uint32_t dwStartPos) { - if (!pTag) - return; - - CFX_ByteTextBuf& textBuf = pTag->m_TextBuf; - if (eType == CFX_SAXItem::Type::CharData) - textBuf << "<![CDATA["; - - textBuf << bsData; - if (eType == CFX_SAXItem::Type::CharData) - textBuf << "]]>"; -} - -void CXFA_SAXReaderHandler::OnTagClose(CXFA_SAXContext* pTag, - uint32_t dwEndPos) { - if (!pTag) - return; - - CFX_ByteTextBuf& textBuf = pTag->m_TextBuf; - if (pTag->m_eNode == CFX_SAXItem::Type::Instruction) - textBuf << "?>"; - else if (pTag->m_eNode == CFX_SAXItem::Type::Tag) - textBuf << "></" << pTag->m_bsTagName.AsStringC() << ">"; - - UpdateChecksum(false); -} - -void CXFA_SAXReaderHandler::OnTagEnd(CXFA_SAXContext* pTag, - const CFX_ByteStringC& bsTagName, - uint32_t dwEndPos) { - if (!pTag) - return; - - pTag->m_TextBuf << "</" << bsTagName << ">"; - UpdateChecksum(false); -} - -void CXFA_SAXReaderHandler::OnTargetData(CXFA_SAXContext* pTag, - CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, - uint32_t dwStartPos) { - if (!pTag && eType != CFX_SAXItem::Type::Comment) - return; - - if (eType == CFX_SAXItem::Type::Comment) { - m_SAXContext.m_TextBuf << "<!--" << bsData << "-->"; - UpdateChecksum(false); - } else { - pTag->m_TextBuf << " " << bsData; - } -} - -void CXFA_SAXReaderHandler::UpdateChecksum(bool bCheckSpace) { - int32_t iLength = m_SAXContext.m_TextBuf.GetLength(); - if (iLength < 1) { - return; - } - uint8_t* pBuffer = m_SAXContext.m_TextBuf.GetBuffer(); - bool bUpdata = true; - if (bCheckSpace) { - bUpdata = false; - for (int32_t i = 0; i < iLength; i++) { - bUpdata = (pBuffer[i] > 0x20); - if (bUpdata) { - break; - } - } - } - if (bUpdata) { - m_pContext->Update(CFX_ByteStringC(pBuffer, iLength)); - } - m_SAXContext.m_TextBuf.Clear(); -} - -CXFA_ChecksumContext::CXFA_ChecksumContext() {} - -CXFA_ChecksumContext::~CXFA_ChecksumContext() {} - -void CXFA_ChecksumContext::StartChecksum() { - FinishChecksum(); - m_pByteContext = pdfium::MakeUnique<CRYPT_sha1_context>(); - CRYPT_SHA1Start(m_pByteContext.get()); - m_bsChecksum.clear(); - m_pSAXReader = pdfium::MakeUnique<CFX_SAXReader>(); -} - -bool CXFA_ChecksumContext::UpdateChecksum( - const CFX_RetainPtr<IFX_SeekableReadStream>& pSrcFile, - FX_FILESIZE offset, - size_t size) { - if (!m_pSAXReader || !pSrcFile) - return false; - - if (size < 1) - size = pSrcFile->GetSize(); - - CXFA_SAXReaderHandler handler(this); - m_pSAXReader->SetHandler(&handler); - if (m_pSAXReader->StartParse( - pSrcFile, (uint32_t)offset, (uint32_t)size, - CFX_SaxParseMode_NotSkipSpace | CFX_SaxParseMode_NotConvert_amp | - CFX_SaxParseMode_NotConvert_lt | CFX_SaxParseMode_NotConvert_gt | - CFX_SaxParseMode_NotConvert_sharp) < 0) { - return false; - } - return m_pSAXReader->ContinueParse(nullptr) > 99; -} - -void CXFA_ChecksumContext::FinishChecksum() { - m_pSAXReader.reset(); - if (m_pByteContext) { - uint8_t digest[20]; - FXSYS_memset(digest, 0, 20); - CRYPT_SHA1Finish(m_pByteContext.get(), digest); - int32_t nLen = Base64EncodeA(digest, 20, nullptr); - FX_CHAR* pBuffer = m_bsChecksum.GetBuffer(nLen); - Base64EncodeA(digest, 20, pBuffer); - m_bsChecksum.ReleaseBuffer(nLen); - m_pByteContext.reset(); - } -} - -CFX_ByteString CXFA_ChecksumContext::GetChecksum() const { - return m_bsChecksum; -} - -void CXFA_ChecksumContext::Update(const CFX_ByteStringC& bsText) { - if (!m_pByteContext) - return; - - CRYPT_SHA1Update(m_pByteContext.get(), bsText.raw_str(), bsText.GetLength()); -} diff --git a/xfa/fxfa/app/xfa_ffapp.cpp b/xfa/fxfa/app/xfa_ffapp.cpp deleted file mode 100644 index 219f06e4ff765c526a80ca5668ebbd1d45e24791..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffapp.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffapp.h" - -#include <algorithm> -#include <memory> -#include <utility> -#include <vector> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_widgetmgr.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/app/xfa_fwltheme.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdochandler.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" -#include "xfa/fxfa/xfa_fontmgr.h" - -namespace { - -class CXFA_FileRead : public IFX_SeekableReadStream { - public: - explicit CXFA_FileRead(const std::vector<CPDF_Stream*>& streams); - ~CXFA_FileRead() override; - - // IFX_SeekableReadStream - FX_FILESIZE GetSize() override; - bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override; - - private: - std::vector<std::unique_ptr<CPDF_StreamAcc>> m_Data; -}; - -CXFA_FileRead::CXFA_FileRead(const std::vector<CPDF_Stream*>& streams) { - for (CPDF_Stream* pStream : streams) { - m_Data.push_back(pdfium::MakeUnique<CPDF_StreamAcc>()); - m_Data.back()->LoadAllData(pStream); - } -} - -CXFA_FileRead::~CXFA_FileRead() {} - -FX_FILESIZE CXFA_FileRead::GetSize() { - uint32_t dwSize = 0; - for (const auto& acc : m_Data) - dwSize += acc->GetSize(); - return dwSize; -} - -bool CXFA_FileRead::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_Data); - int32_t index = 0; - while (index < iCount) { - const auto& acc = m_Data[index]; - FX_FILESIZE dwSize = acc->GetSize(); - if (offset < dwSize) - break; - - offset -= dwSize; - index++; - } - while (index < iCount) { - const auto& acc = m_Data[index]; - uint32_t dwSize = acc->GetSize(); - size_t dwRead = std::min(size, static_cast<size_t>(dwSize - offset)); - FXSYS_memcpy(buffer, acc->GetData() + offset, dwRead); - size -= dwRead; - if (size == 0) - return true; - - buffer = (uint8_t*)buffer + dwRead; - offset = 0; - index++; - } - return false; -} - -} // namespace - -CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream( - const std::vector<CPDF_Stream*>& streams) { - return CFX_RetainPtr<IFX_SeekableReadStream>(new CXFA_FileRead(streams)); -} - -CXFA_FFApp::CXFA_FFApp(IXFA_AppProvider* pProvider) - : m_pProvider(pProvider), - m_pWidgetMgrDelegate(nullptr), - m_pFWLApp(new CFWL_App(this)) {} - -CXFA_FFApp::~CXFA_FFApp() {} - -CXFA_FFDocHandler* CXFA_FFApp::GetDocHandler() { - if (!m_pDocHandler) - m_pDocHandler = pdfium::MakeUnique<CXFA_FFDocHandler>(); - return m_pDocHandler.get(); -} - -std::unique_ptr<CXFA_FFDoc> CXFA_FFApp::CreateDoc( - IXFA_DocEnvironment* pDocEnvironment, - CPDF_Document* pPDFDoc) { - if (!pPDFDoc) - return nullptr; - - auto pDoc = pdfium::MakeUnique<CXFA_FFDoc>(this, pDocEnvironment); - if (!pDoc->OpenDoc(pPDFDoc)) - return nullptr; - - return pDoc; -} - -void CXFA_FFApp::SetDefaultFontMgr(std::unique_ptr<CXFA_DefFontMgr> pFontMgr) { - if (!m_pFontMgr) - m_pFontMgr = pdfium::MakeUnique<CXFA_FontMgr>(); - m_pFontMgr->SetDefFontMgr(std::move(pFontMgr)); -} - -CXFA_FontMgr* CXFA_FFApp::GetXFAFontMgr() const { - return m_pFontMgr.get(); -} - -CFGAS_FontMgr* CXFA_FFApp::GetFDEFontMgr() { - if (!m_pFDEFontMgr) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - m_pFDEFontMgr = CFGAS_FontMgr::Create(FX_GetDefFontEnumerator()); -#else - m_pFontSource = pdfium::MakeUnique<CFX_FontSourceEnum_File>(); - m_pFDEFontMgr = CFGAS_FontMgr::Create(m_pFontSource.get()); -#endif - } - return m_pFDEFontMgr.get(); -} - -CXFA_FWLTheme* CXFA_FFApp::GetFWLTheme() { - if (!m_pFWLTheme) - m_pFWLTheme = pdfium::MakeUnique<CXFA_FWLTheme>(this); - return m_pFWLTheme.get(); -} - -CXFA_FWLAdapterWidgetMgr* CXFA_FFApp::GetWidgetMgr( - CFWL_WidgetMgrDelegate* pDelegate) { - if (!m_pAdapterWidgetMgr) { - m_pAdapterWidgetMgr = pdfium::MakeUnique<CXFA_FWLAdapterWidgetMgr>(); - pDelegate->OnSetCapability(FWL_WGTMGR_DisableForm); - m_pWidgetMgrDelegate = pDelegate; - } - return m_pAdapterWidgetMgr.get(); -} - -IFWL_AdapterTimerMgr* CXFA_FFApp::GetTimerMgr() const { - return m_pProvider->GetTimerMgr(); -} - -void CXFA_FFApp::ClearEventTargets() { - m_pFWLApp->GetNoteDriver()->ClearEventTargets(false); -} diff --git a/xfa/fxfa/app/xfa_ffapp_unittest.cpp b/xfa/fxfa/app/xfa_ffapp_unittest.cpp deleted file mode 100644 index b0879012b42b4c3088c967a3bbd3df36edd2ccba..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffapp_unittest.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2016 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. - -#include "xfa/fxfa/xfa_ffapp.h" - -#include <memory> -#include <vector> - -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fxcrt/fx_memory.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/ptr_util.h" - -TEST(CXFAFileRead, NoStreams) { - std::vector<CPDF_Stream*> streams; - CFX_RetainPtr<IFX_SeekableReadStream> fileread = - MakeSeekableReadStream(streams); - - uint8_t output_buffer[16]; - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_FALSE(fileread->ReadBlock(output_buffer, 0, 0)); - EXPECT_EQ(0xbd, output_buffer[0]); -} - -TEST(CXFAFileRead, EmptyStreams) { - std::vector<CPDF_Stream*> streams; - auto stream1 = pdfium::MakeUnique<CPDF_Stream>(); - streams.push_back(stream1.get()); - CFX_RetainPtr<IFX_SeekableReadStream> fileread = - MakeSeekableReadStream(streams); - - uint8_t output_buffer[16]; - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_FALSE(fileread->ReadBlock(output_buffer, 0, 0)); - EXPECT_EQ(0xbd, output_buffer[0]); -} - -TEST(CXFAFileRead, NormalStreams) { - std::vector<CPDF_Stream*> streams; - auto stream1 = pdfium::MakeUnique<CPDF_Stream>(); - auto stream2 = pdfium::MakeUnique<CPDF_Stream>(); - auto stream3 = pdfium::MakeUnique<CPDF_Stream>(); - - // 16 chars total. - stream1->InitStream(reinterpret_cast<const uint8_t*>("one t"), 5, - pdfium::MakeUnique<CPDF_Dictionary>()); - stream2->InitStream(reinterpret_cast<const uint8_t*>("wo "), 3, - pdfium::MakeUnique<CPDF_Dictionary>()); - stream3->InitStream(reinterpret_cast<const uint8_t*>("three!!!"), 8, - pdfium::MakeUnique<CPDF_Dictionary>()); - - streams.push_back(stream1.get()); - streams.push_back(stream2.get()); - streams.push_back(stream3.get()); - CFX_RetainPtr<IFX_SeekableReadStream> fileread = - MakeSeekableReadStream(streams); - - uint8_t output_buffer[16]; - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, 0)); - EXPECT_EQ(0xbd, output_buffer[0]); - - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_TRUE(fileread->ReadBlock(output_buffer, 1, 0)); - EXPECT_EQ(0xbd, output_buffer[0]); - - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, 1)); - EXPECT_EQ(0, memcmp(output_buffer, "o", 1)); - EXPECT_EQ(0xbd, output_buffer[1]); - - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, sizeof(output_buffer))); - EXPECT_EQ(0, memcmp(output_buffer, "one two three!!!", 16)); - - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_TRUE(fileread->ReadBlock(output_buffer, 2, 10)); - EXPECT_EQ(0, memcmp(output_buffer, "e two thre", 10)); - EXPECT_EQ(0xbd, output_buffer[11]); - - memset(output_buffer, 0xbd, sizeof(output_buffer)); - EXPECT_FALSE(fileread->ReadBlock(output_buffer, 1, sizeof(output_buffer))); - EXPECT_EQ(0, memcmp(output_buffer, "ne two three!!!", 15)); - EXPECT_EQ(0xbd, output_buffer[15]); -} diff --git a/xfa/fxfa/app/xfa_ffbarcode.cpp b/xfa/fxfa/app/xfa_ffbarcode.cpp deleted file mode 100644 index b136b8da5a570f81b39ac8afb7b8b607f68bb832..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffbarcode.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffbarcode.h" - -#include "core/fxcrt/fx_ext.h" -#include "xfa/fwl/cfwl_app.h" -#include "xfa/fwl/cfwl_barcode.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_fftextedit.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -namespace { - -const XFA_BARCODETYPEENUMINFO g_XFABarCodeTypeEnumData[] = { - {0x7fb4a18, L"ean13", XFA_BARCODETYPE_ean13, BC_EAN13}, - {0x8d13a3d, L"code11", XFA_BARCODETYPE_code11, BC_UNKNOWN}, - {0x8d149a8, L"code49", XFA_BARCODETYPE_code49, BC_UNKNOWN}, - {0x8d16347, L"code93", XFA_BARCODETYPE_code93, BC_UNKNOWN}, - {0x91a92e2, L"upsMaxicode", XFA_BARCODETYPE_upsMaxicode, BC_UNKNOWN}, - {0xa7d48dc, L"fim", XFA_BARCODETYPE_fim, BC_UNKNOWN}, - {0xb359fe9, L"msi", XFA_BARCODETYPE_msi, BC_UNKNOWN}, - {0x121f738c, L"code2Of5Matrix", XFA_BARCODETYPE_code2Of5Matrix, BC_UNKNOWN}, - {0x15358616, L"ucc128", XFA_BARCODETYPE_ucc128, BC_UNKNOWN}, - {0x1f4bfa05, L"rfid", XFA_BARCODETYPE_rfid, BC_UNKNOWN}, - {0x1fda71bc, L"rss14Stacked", XFA_BARCODETYPE_rss14Stacked, BC_UNKNOWN}, - {0x22065087, L"ean8add2", XFA_BARCODETYPE_ean8add2, BC_UNKNOWN}, - {0x2206508a, L"ean8add5", XFA_BARCODETYPE_ean8add5, BC_UNKNOWN}, - {0x2278366c, L"codabar", XFA_BARCODETYPE_codabar, BC_CODABAR}, - {0x2a039a8d, L"telepen", XFA_BARCODETYPE_telepen, BC_UNKNOWN}, - {0x323ed337, L"upcApwcd", XFA_BARCODETYPE_upcApwcd, BC_UNKNOWN}, - {0x347a1846, L"postUSIMB", XFA_BARCODETYPE_postUSIMB, BC_UNKNOWN}, - {0x391bb836, L"code128", XFA_BARCODETYPE_code128, BC_CODE128}, - {0x398eddaf, L"dataMatrix", XFA_BARCODETYPE_dataMatrix, BC_DATAMATRIX}, - {0x3cff60a8, L"upcEadd2", XFA_BARCODETYPE_upcEadd2, BC_UNKNOWN}, - {0x3cff60ab, L"upcEadd5", XFA_BARCODETYPE_upcEadd5, BC_UNKNOWN}, - {0x402cb188, L"code2Of5Standard", XFA_BARCODETYPE_code2Of5Standard, - BC_UNKNOWN}, - {0x411764f7, L"aztec", XFA_BARCODETYPE_aztec, BC_UNKNOWN}, - {0x44d4e84c, L"ean8", XFA_BARCODETYPE_ean8, BC_EAN8}, - {0x48468902, L"ucc128sscc", XFA_BARCODETYPE_ucc128sscc, BC_UNKNOWN}, - {0x4880aea4, L"upcAadd2", XFA_BARCODETYPE_upcAadd2, BC_UNKNOWN}, - {0x4880aea7, L"upcAadd5", XFA_BARCODETYPE_upcAadd5, BC_UNKNOWN}, - {0x54f18256, L"code2Of5Industrial", XFA_BARCODETYPE_code2Of5Industrial, - BC_UNKNOWN}, - {0x58e15f25, L"rss14Limited", XFA_BARCODETYPE_rss14Limited, BC_UNKNOWN}, - {0x5c08d1b9, L"postAUSReplyPaid", XFA_BARCODETYPE_postAUSReplyPaid, - BC_UNKNOWN}, - {0x5fa700bd, L"rss14", XFA_BARCODETYPE_rss14, BC_UNKNOWN}, - {0x631a7e35, L"logmars", XFA_BARCODETYPE_logmars, BC_UNKNOWN}, - {0x6a236236, L"pdf417", XFA_BARCODETYPE_pdf417, BC_PDF417}, - {0x6d098ece, L"upcean2", XFA_BARCODETYPE_upcean2, BC_UNKNOWN}, - {0x6d098ed1, L"upcean5", XFA_BARCODETYPE_upcean5, BC_UNKNOWN}, - {0x76b04eed, L"code3Of9extended", XFA_BARCODETYPE_code3Of9extended, - BC_UNKNOWN}, - {0x7c7db84a, L"maxicode", XFA_BARCODETYPE_maxicode, BC_UNKNOWN}, - {0x8266f7f7, L"ucc128random", XFA_BARCODETYPE_ucc128random, BC_UNKNOWN}, - {0x83eca147, L"postUSDPBC", XFA_BARCODETYPE_postUSDPBC, BC_UNKNOWN}, - {0x8dd71de0, L"postAUSStandard", XFA_BARCODETYPE_postAUSStandard, - BC_UNKNOWN}, - {0x98adad85, L"plessey", XFA_BARCODETYPE_plessey, BC_UNKNOWN}, - {0x9f84cce6, L"ean13pwcd", XFA_BARCODETYPE_ean13pwcd, BC_UNKNOWN}, - {0xb514fbe9, L"upcA", XFA_BARCODETYPE_upcA, BC_UPCA}, - {0xb514fbed, L"upcE", XFA_BARCODETYPE_upcE, BC_UNKNOWN}, - {0xb5c6a853, L"ean13add2", XFA_BARCODETYPE_ean13add2, BC_UNKNOWN}, - {0xb5c6a856, L"ean13add5", XFA_BARCODETYPE_ean13add5, BC_UNKNOWN}, - {0xb81fc512, L"postUKRM4SCC", XFA_BARCODETYPE_postUKRM4SCC, BC_UNKNOWN}, - {0xbad34b22, L"code128SSCC", XFA_BARCODETYPE_code128SSCC, BC_UNKNOWN}, - {0xbfbe0cf6, L"postUS5Zip", XFA_BARCODETYPE_postUS5Zip, BC_UNKNOWN}, - {0xc56618e8, L"pdf417macro", XFA_BARCODETYPE_pdf417macro, BC_UNKNOWN}, - {0xca730f8a, L"code2Of5Interleaved", XFA_BARCODETYPE_code2Of5Interleaved, - BC_UNKNOWN}, - {0xd0097ac6, L"rss14Expanded", XFA_BARCODETYPE_rss14Expanded, BC_UNKNOWN}, - {0xd25a0240, L"postAUSCust2", XFA_BARCODETYPE_postAUSCust2, BC_UNKNOWN}, - {0xd25a0241, L"postAUSCust3", XFA_BARCODETYPE_postAUSCust3, BC_UNKNOWN}, - {0xd53ed3e7, L"rss14Truncated", XFA_BARCODETYPE_rss14Truncated, BC_UNKNOWN}, - {0xe72bcd57, L"code128A", XFA_BARCODETYPE_code128A, BC_UNKNOWN}, - {0xe72bcd58, L"code128B", XFA_BARCODETYPE_code128B, BC_CODE128_B}, - {0xe72bcd59, L"code128C", XFA_BARCODETYPE_code128C, BC_CODE128_C}, - {0xee83c50f, L"rss14StackedOmni", XFA_BARCODETYPE_rss14StackedOmni, - BC_UNKNOWN}, - {0xf2a18f7e, L"QRCode", XFA_BARCODETYPE_QRCode, BC_QR_CODE}, - {0xfaeaf37f, L"postUSStandard", XFA_BARCODETYPE_postUSStandard, BC_UNKNOWN}, - {0xfb48155c, L"code3Of9", XFA_BARCODETYPE_code3Of9, BC_CODE39}, -}; -const int32_t g_iXFABarcodeTypeCount = - sizeof(g_XFABarCodeTypeEnumData) / sizeof(XFA_BARCODETYPEENUMINFO); - -const XFA_BARCODETYPEENUMINFO* XFA_GetBarcodeTypeByName( - const CFX_WideStringC& wsName) { - if (wsName.IsEmpty()) - return nullptr; - - uint32_t uHash = FX_HashCode_GetW(wsName, true); - int32_t iStart = 0; - int32_t iEnd = g_iXFABarcodeTypeCount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_BARCODETYPEENUMINFO* pInfo = g_XFABarCodeTypeEnumData + iMid; - if (uHash == pInfo->uHash) { - return pInfo; - } else if (uHash < pInfo->uHash) { - iEnd = iMid - 1; - } else { - iStart = iMid + 1; - } - } while (iStart <= iEnd); - return nullptr; -} - -} // namespace. - -CXFA_FFBarcode::CXFA_FFBarcode(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFTextEdit(pDataAcc) {} - -CXFA_FFBarcode::~CXFA_FFBarcode() {} - -bool CXFA_FFBarcode::LoadWidget() { - CFWL_Barcode* pFWLBarcode = new CFWL_Barcode(GetFWLApp()); - - m_pNormalWidget = pFWLBarcode; - m_pNormalWidget->SetLayoutItem(this); - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display); - pFWLBarcode->SetText(wsText); - UpdateWidgetProperty(); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFBarcode::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - DrawBorder(pGS, borderUI, m_rtUI, &mtRotate); - RenderCaption(pGS, &mtRotate); - CFX_RectF rtWidget = m_pNormalWidget->GetWidgetRect(); - - CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); - mt.Concat(mtRotate); - m_pNormalWidget->DrawWidget(pGS, &mt); -} - -void CXFA_FFBarcode::UpdateWidgetProperty() { - CXFA_FFTextEdit::UpdateWidgetProperty(); - CFWL_Barcode* pBarCodeWidget = (CFWL_Barcode*)m_pNormalWidget; - CFX_WideString wsType = GetDataAcc()->GetBarcodeType(); - const XFA_BARCODETYPEENUMINFO* pBarcodeTypeInfo = - XFA_GetBarcodeTypeByName(wsType.AsStringC()); - if (!pBarcodeTypeInfo) - return; - - pBarCodeWidget->SetType(pBarcodeTypeInfo->eBCType); - CXFA_WidgetAcc* pAcc = GetDataAcc(); - int32_t intVal; - FX_CHAR charVal; - bool boolVal; - FX_FLOAT floatVal; - if (pAcc->GetBarcodeAttribute_CharEncoding(intVal)) { - pBarCodeWidget->SetCharEncoding((BC_CHAR_ENCODING)intVal); - } - if (pAcc->GetBarcodeAttribute_Checksum(boolVal)) { - pBarCodeWidget->SetCalChecksum(boolVal); - } - if (pAcc->GetBarcodeAttribute_DataLength(intVal)) { - pBarCodeWidget->SetDataLength(intVal); - } - if (pAcc->GetBarcodeAttribute_StartChar(charVal)) { - pBarCodeWidget->SetStartChar(charVal); - } - if (pAcc->GetBarcodeAttribute_EndChar(charVal)) { - pBarCodeWidget->SetEndChar(charVal); - } - if (pAcc->GetBarcodeAttribute_ECLevel(intVal)) { - pBarCodeWidget->SetErrorCorrectionLevel(intVal); - } - if (pAcc->GetBarcodeAttribute_ModuleWidth(intVal)) { - pBarCodeWidget->SetModuleWidth(intVal); - } - if (pAcc->GetBarcodeAttribute_ModuleHeight(intVal)) { - pBarCodeWidget->SetModuleHeight(intVal); - } - if (pAcc->GetBarcodeAttribute_PrintChecksum(boolVal)) { - pBarCodeWidget->SetPrintChecksum(boolVal); - } - if (pAcc->GetBarcodeAttribute_TextLocation(intVal)) { - pBarCodeWidget->SetTextLocation((BC_TEXT_LOC)intVal); - } - if (pAcc->GetBarcodeAttribute_Truncate(boolVal)) { - pBarCodeWidget->SetTruncated(boolVal); - } - if (pAcc->GetBarcodeAttribute_WideNarrowRatio(floatVal)) { - pBarCodeWidget->SetWideNarrowRatio((int32_t)floatVal); - } - if (pBarcodeTypeInfo->eName == XFA_BARCODETYPE_code3Of9 || - pBarcodeTypeInfo->eName == XFA_BARCODETYPE_ean8 || - pBarcodeTypeInfo->eName == XFA_BARCODETYPE_ean13 || - pBarcodeTypeInfo->eName == XFA_BARCODETYPE_upcA) { - pBarCodeWidget->SetPrintChecksum(true); - } -} - -bool CXFA_FFBarcode::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - CFWL_Barcode* pBarCodeWidget = (CFWL_Barcode*)m_pNormalWidget; - if (!pBarCodeWidget || pBarCodeWidget->IsProtectedType()) - return false; - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) - return false; - return CXFA_FFTextEdit::OnLButtonDown(dwFlags, point); -} - -bool CXFA_FFBarcode::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - CFWL_Barcode* pBarCodeWidget = (CFWL_Barcode*)m_pNormalWidget; - if (!pBarCodeWidget || pBarCodeWidget->IsProtectedType()) - return false; - return CXFA_FFTextEdit::OnRButtonDown(dwFlags, point); -} diff --git a/xfa/fxfa/app/xfa_ffbarcode.h b/xfa/fxfa/app/xfa_ffbarcode.h deleted file mode 100644 index c20feb5167bca5cf366eda7ac876435d8c10de23..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffbarcode.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFBARCODE_H_ -#define XFA_FXFA_APP_XFA_FFBARCODE_H_ - -#include "xfa/fxbarcode/BC_Library.h" -#include "xfa/fxfa/app/xfa_fftextedit.h" -#include "xfa/fxfa/xfa_ffpageview.h" - -class CXFA_FFBarcode : public CXFA_FFTextEdit { - public: - explicit CXFA_FFBarcode(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFBarcode() override; - - // CXFA_FFTextEdit - bool LoadWidget() override; - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - void UpdateWidgetProperty() override; - bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; -}; - -enum XFA_BARCODETYPEENUM { - XFA_BARCODETYPE_aztec, - XFA_BARCODETYPE_codabar, - XFA_BARCODETYPE_code11, - XFA_BARCODETYPE_code128, - XFA_BARCODETYPE_code128A, - XFA_BARCODETYPE_code128B, - XFA_BARCODETYPE_code128C, - XFA_BARCODETYPE_code128SSCC, - XFA_BARCODETYPE_code2Of5Industrial, - XFA_BARCODETYPE_code2Of5Interleaved, - XFA_BARCODETYPE_code2Of5Matrix, - XFA_BARCODETYPE_code2Of5Standard, - XFA_BARCODETYPE_code3Of9, - XFA_BARCODETYPE_code3Of9extended, - XFA_BARCODETYPE_code49, - XFA_BARCODETYPE_code93, - XFA_BARCODETYPE_dataMatrix, - XFA_BARCODETYPE_ean13, - XFA_BARCODETYPE_ean13add2, - XFA_BARCODETYPE_ean13add5, - XFA_BARCODETYPE_ean13pwcd, - XFA_BARCODETYPE_ean8, - XFA_BARCODETYPE_ean8add2, - XFA_BARCODETYPE_ean8add5, - XFA_BARCODETYPE_fim, - XFA_BARCODETYPE_logmars, - XFA_BARCODETYPE_maxicode, - XFA_BARCODETYPE_msi, - XFA_BARCODETYPE_pdf417, - XFA_BARCODETYPE_pdf417macro, - XFA_BARCODETYPE_plessey, - XFA_BARCODETYPE_postAUSCust2, - XFA_BARCODETYPE_postAUSCust3, - XFA_BARCODETYPE_postAUSReplyPaid, - XFA_BARCODETYPE_postAUSStandard, - XFA_BARCODETYPE_postUKRM4SCC, - XFA_BARCODETYPE_postUS5Zip, - XFA_BARCODETYPE_postUSDPBC, - XFA_BARCODETYPE_postUSIMB, - XFA_BARCODETYPE_postUSStandard, - XFA_BARCODETYPE_QRCode, - XFA_BARCODETYPE_rfid, - XFA_BARCODETYPE_rss14, - XFA_BARCODETYPE_rss14Expanded, - XFA_BARCODETYPE_rss14Limited, - XFA_BARCODETYPE_rss14Stacked, - XFA_BARCODETYPE_rss14StackedOmni, - XFA_BARCODETYPE_rss14Truncated, - XFA_BARCODETYPE_telepen, - XFA_BARCODETYPE_ucc128, - XFA_BARCODETYPE_ucc128random, - XFA_BARCODETYPE_ucc128sscc, - XFA_BARCODETYPE_upcA, - XFA_BARCODETYPE_upcAadd2, - XFA_BARCODETYPE_upcAadd5, - XFA_BARCODETYPE_upcApwcd, - XFA_BARCODETYPE_upcE, - XFA_BARCODETYPE_upcEadd2, - XFA_BARCODETYPE_upcEadd5, - XFA_BARCODETYPE_upcean2, - XFA_BARCODETYPE_upcean5, - XFA_BARCODETYPE_upsMaxicode -}; - -struct XFA_BARCODETYPEENUMINFO { - uint32_t uHash; - const FX_WCHAR* pName; - XFA_BARCODETYPEENUM eName; - BC_TYPE eBCType; -}; - -#endif // XFA_FXFA_APP_XFA_FFBARCODE_H_ diff --git a/xfa/fxfa/app/xfa_ffcheckbutton.cpp b/xfa/fxfa/app/xfa_ffcheckbutton.cpp deleted file mode 100644 index f088b5d4dda90fdb61cc1bb961e7f226e87222d1..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffcheckbutton.cpp +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffcheckbutton.h" - -#include "xfa/fwl/cfwl_checkbox.h" -#include "xfa/fwl/cfwl_messagemouse.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_widgetmgr.h" -#include "xfa/fxfa/app/xfa_ffexclgroup.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {} - -CXFA_FFCheckButton::~CXFA_FFCheckButton() {} - -bool CXFA_FFCheckButton::LoadWidget() { - CFWL_CheckBox* pCheckBox = new CFWL_CheckBox(GetFWLApp()); - m_pNormalWidget = pCheckBox; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - - if (m_pDataAcc->IsRadioButton()) - pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF); - - m_pNormalWidget->LockUpdate(); - UpdateWidgetProperty(); - SetFWLCheckState(m_pDataAcc->GetCheckState()); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFCheckButton::UpdateWidgetProperty() { - CFWL_CheckBox* pCheckBox = (CFWL_CheckBox*)m_pNormalWidget; - if (!m_pNormalWidget) { - return; - } - FX_FLOAT fSize = m_pDataAcc->GetCheckButtonSize(); - pCheckBox->SetBoxSize(fSize); - uint32_t dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross; - int32_t iCheckMark = m_pDataAcc->GetCheckButtonMark(); - switch (iCheckMark) { - case XFA_ATTRIBUTEENUM_Check: - dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck; - break; - case XFA_ATTRIBUTEENUM_Circle: - dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle; - break; - case XFA_ATTRIBUTEENUM_Cross: - break; - case XFA_ATTRIBUTEENUM_Diamond: - dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond; - break; - case XFA_ATTRIBUTEENUM_Square: - dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare; - break; - case XFA_ATTRIBUTEENUM_Star: - dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar; - break; - default: { - int32_t iShape = m_pDataAcc->GetCheckButtonShape(); - if (iShape == XFA_ATTRIBUTEENUM_Round) { - dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle; - } - } break; - } - if (m_pDataAcc->IsAllowNeutral()) { - dwStyleEx |= FWL_STYLEEXT_CKB_3State; - } - pCheckBox->ModifyStylesEx( - dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State); -} -bool CXFA_FFCheckButton::PerformLayout() { - CXFA_FFWidget::PerformLayout(); - FX_FLOAT fCheckSize = m_pDataAcc->GetCheckButtonSize(); - CXFA_Margin mgWidget = m_pDataAcc->GetMargin(); - CFX_RectF rtWidget = GetRectWithoutRotate(); - if (mgWidget) { - XFA_RectWidthoutMargin(rtWidget, mgWidget); - } - int32_t iCapPlacement = -1; - FX_FLOAT fCapReserve = 0; - CXFA_Caption caption = m_pDataAcc->GetCaption(); - if (caption && caption.GetPresence()) { - m_rtCaption = rtWidget; - iCapPlacement = caption.GetPlacementType(); - fCapReserve = caption.GetReserve(); - if (fCapReserve <= 0) { - if (iCapPlacement == XFA_ATTRIBUTEENUM_Top || - iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) { - fCapReserve = rtWidget.height - fCheckSize; - } else { - fCapReserve = rtWidget.width - fCheckSize; - } - } - } - int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left; - int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - iHorzAlign = para.GetHorizontalAlign(); - iVertAlign = para.GetVerticalAlign(); - } - m_rtUI = rtWidget; - CXFA_Margin mgCap = caption.GetMargin(); - switch (iCapPlacement) { - case XFA_ATTRIBUTEENUM_Left: { - m_rtCaption.width = fCapReserve; - CapLeftRightPlacement(mgCap); - m_rtUI.width -= fCapReserve; - m_rtUI.left += fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Top: { - m_rtCaption.height = fCapReserve; - XFA_RectWidthoutMargin(m_rtCaption, mgCap); - m_rtUI.height -= fCapReserve; - m_rtUI.top += fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Right: { - m_rtCaption.left = m_rtCaption.right() - fCapReserve; - m_rtCaption.width = fCapReserve; - CapLeftRightPlacement(mgCap); - m_rtUI.width -= fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Bottom: { - m_rtCaption.top = m_rtCaption.bottom() - fCapReserve; - m_rtCaption.height = fCapReserve; - XFA_RectWidthoutMargin(m_rtCaption, mgCap); - m_rtUI.height -= fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Inline: - break; - default: - iHorzAlign = XFA_ATTRIBUTEENUM_Right; - break; - } - if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) { - m_rtUI.left += (m_rtUI.width - fCheckSize) / 2; - } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) { - m_rtUI.left = m_rtUI.right() - fCheckSize; - } - if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) { - m_rtUI.top += (m_rtUI.height - fCheckSize) / 2; - } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) { - m_rtUI.top = m_rtUI.bottom() - fCheckSize; - } - m_rtUI.width = fCheckSize; - m_rtUI.height = fCheckSize; - AddUIMargin(iCapPlacement); - m_rtCheckBox = m_rtUI; - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - if (borderUI) { - CXFA_Margin margin = borderUI.GetMargin(); - if (margin) { - XFA_RectWidthoutMargin(m_rtUI, margin); - } - } - m_rtUI.Normalize(); - LayoutCaption(); - SetFWLRect(); - if (m_pNormalWidget) { - m_pNormalWidget->Update(); - } - return true; -} -void CXFA_FFCheckButton::CapLeftRightPlacement(CXFA_Margin mgCap) { - XFA_RectWidthoutMargin(m_rtCaption, mgCap); - if (m_rtCaption.height < 0) { - m_rtCaption.top += m_rtCaption.height; - } - if (m_rtCaption.width < 0) { - m_rtCaption.left += m_rtCaption.width; - m_rtCaption.width = -m_rtCaption.width; - } -} -void CXFA_FFCheckButton::AddUIMargin(int32_t iCapPlacement) { - CFX_RectF rtUIMargin = m_pDataAcc->GetUIMargin(); - m_rtUI.top -= rtUIMargin.top / 2 - rtUIMargin.height / 2; - FX_FLOAT fLeftAddRight = rtUIMargin.left + rtUIMargin.width; - FX_FLOAT fTopAddBottom = rtUIMargin.top + rtUIMargin.height; - if (m_rtUI.width < fLeftAddRight) { - if (iCapPlacement == XFA_ATTRIBUTEENUM_Right || - iCapPlacement == XFA_ATTRIBUTEENUM_Left) { - m_rtUI.left -= fLeftAddRight - m_rtUI.width; - } else { - m_rtUI.left -= 2 * (fLeftAddRight - m_rtUI.width); - } - m_rtUI.width += 2 * (fLeftAddRight - m_rtUI.width); - } - if (m_rtUI.height < fTopAddBottom) { - if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) { - m_rtUI.left -= fTopAddBottom - m_rtUI.height; - } - m_rtUI.top -= fTopAddBottom - m_rtUI.height; - m_rtUI.height += 2 * (fTopAddBottom - m_rtUI.height); - } -} -void CXFA_FFCheckButton::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - DrawBorder(pGS, borderUI, m_rtUI, &mtRotate, - m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round - ? XFA_DRAWBOX_ForceRound - : 0); - RenderCaption(pGS, &mtRotate); - DrawHighlight(pGS, &mtRotate, dwStatus, - m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round); - CFX_Matrix mt(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top); - mt.Concat(mtRotate); - GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt); -} -bool CXFA_FFCheckButton::OnLButtonUp(uint32_t dwFlags, - const CFX_PointF& point) { - if (!m_pNormalWidget || !IsButtonDown()) - return false; - - SetButtonDown(false); - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() { - uint32_t dwState = m_pNormalWidget->GetStates(); - if (dwState & FWL_STATE_CKB_Checked) - return XFA_CHECKSTATE_On; - if (dwState & FWL_STATE_CKB_Neutral) - return XFA_CHECKSTATE_Neutral; - return XFA_CHECKSTATE_Off; -} - -bool CXFA_FFCheckButton::CommitData() { - XFA_CHECKSTATE eCheckState = FWLState2XFAState(); - m_pDataAcc->SetCheckState(eCheckState, true); - return true; -} - -bool CXFA_FFCheckButton::IsDataChanged() { - XFA_CHECKSTATE eCheckState = FWLState2XFAState(); - return m_pDataAcc->GetCheckState() != eCheckState; -} -void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) { - if (eCheckState == XFA_CHECKSTATE_Neutral) { - m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral); - } else { - if (eCheckState == XFA_CHECKSTATE_On) - m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked); - else - m_pNormalWidget->RemoveStates(FWL_STATE_CKB_Checked); - } -} -bool CXFA_FFCheckButton::UpdateFWLData() { - if (!m_pNormalWidget) { - return false; - } - XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState(); - SetFWLCheckState(eState); - m_pNormalWidget->Update(); - return true; -} - -void CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) { - m_pOldDelegate->OnProcessMessage(pMessage); -} - -void CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) { - CXFA_FFField::OnProcessEvent(pEvent); - switch (pEvent->GetType()) { - case CFWL_Event::Type::CheckStateChanged: { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Change; - m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw); - CXFA_WidgetAcc* pFFExclGroup = m_pDataAcc->GetExclGroup(); - if (ProcessCommittedData()) { - eParam.m_pTarget = pFFExclGroup; - if (pFFExclGroup) { - m_pDocView->AddValidateWidget(pFFExclGroup); - m_pDocView->AddCalculateWidgetAcc(pFFExclGroup); - pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); - } - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); - } else { - SetFWLCheckState(m_pDataAcc->GetCheckState()); - } - if (pFFExclGroup) { - eParam.m_pTarget = pFFExclGroup; - pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam); - } - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam); - break; - } - default: - break; - } - m_pOldDelegate->OnProcessEvent(pEvent); -} - -void CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix); -} diff --git a/xfa/fxfa/app/xfa_ffcheckbutton.h b/xfa/fxfa/app/xfa_ffcheckbutton.h deleted file mode 100644 index 2c0acd6e3ece90e81bbbf29624fb52f2b5934032..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffcheckbutton.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFCHECKBUTTON_H_ -#define XFA_FXFA_APP_XFA_FFCHECKBUTTON_H_ - -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/xfa_ffpageview.h" - -class CXFA_FFCheckButton : public CXFA_FFField { - public: - explicit CXFA_FFCheckButton(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFCheckButton() override; - - // CXFA_FFField - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - - bool LoadWidget() override; - bool PerformLayout() override; - bool UpdateFWLData() override; - void UpdateWidgetProperty() override; - bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - void SetFWLCheckState(XFA_CHECKSTATE eCheckState); - - protected: - bool CommitData() override; - bool IsDataChanged() override; - - void CapLeftRightPlacement(CXFA_Margin mgCap); - void AddUIMargin(int32_t iCapPlacement); - XFA_CHECKSTATE FWLState2XFAState(); - IFWL_WidgetDelegate* m_pOldDelegate; - CFX_RectF m_rtCheckBox; -}; - -#endif // XFA_FXFA_APP_XFA_FFCHECKBUTTON_H_ diff --git a/xfa/fxfa/app/xfa_ffchoicelist.cpp b/xfa/fxfa/app/xfa_ffchoicelist.cpp deleted file mode 100644 index 3aabde870affb081ba2fd5bbb7eeda60341247ec..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffchoicelist.cpp +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffchoicelist.h" - -#include <vector> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fwl/cfwl_app.h" -#include "xfa/fwl/cfwl_combobox.h" -#include "xfa/fwl/cfwl_edit.h" -#include "xfa/fwl/cfwl_eventselectchanged.h" -#include "xfa/fwl/cfwl_listbox.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_widgetproperties.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFListBox::CXFA_FFListBox(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {} - -CXFA_FFListBox::~CXFA_FFListBox() { - if (m_pNormalWidget) { - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->UnregisterEventTarget(m_pNormalWidget); - } -} - -bool CXFA_FFListBox::LoadWidget() { - CFWL_ListBox* pListBox = new CFWL_ListBox( - GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); - pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll | FWL_WGTSTYLE_NoBackground, - 0xFFFFFFFF); - m_pNormalWidget = (CFWL_Widget*)pListBox; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - std::vector<CFX_WideString> wsLabelArray; - m_pDataAcc->GetChoiceListItems(wsLabelArray, false); - int32_t iItems = pdfium::CollectionSize<int32_t>(wsLabelArray); - for (int32_t i = 0; i < iItems; i++) { - pListBox->AddString(wsLabelArray[i].AsStringC()); - } - uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus; - if (m_pDataAcc->GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) { - dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection; - } - dwExtendedStyle |= GetAlignment(); - m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); - CFX_ArrayTemplate<int32_t> iSelArray; - m_pDataAcc->GetSelectedItems(iSelArray); - int32_t iSelCount = iSelArray.GetSize(); - for (int32_t j = 0; j < iSelCount; j++) { - CFWL_ListItem* item = pListBox->GetItem(nullptr, iSelArray[j]); - pListBox->SetSelItem(item, true); - } - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} - -bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) { - if (!ProcessCommittedData()) - UpdateFWLData(); - CXFA_FFField::OnKillFocus(pNewFocus); - return true; -} - -bool CXFA_FFListBox::CommitData() { - CFWL_ListBox* pListBox = static_cast<CFWL_ListBox*>(m_pNormalWidget); - int32_t iSels = pListBox->CountSelItems(); - CFX_ArrayTemplate<int32_t> iSelArray; - for (int32_t i = 0; i < iSels; ++i) - iSelArray.Add(pListBox->GetSelIndex(i)); - m_pDataAcc->SetSelectedItems(iSelArray, true, false, true); - return true; -} - -bool CXFA_FFListBox::IsDataChanged() { - CFX_ArrayTemplate<int32_t> iSelArray; - m_pDataAcc->GetSelectedItems(iSelArray); - int32_t iOldSels = iSelArray.GetSize(); - CFWL_ListBox* pListBox = (CFWL_ListBox*)m_pNormalWidget; - int32_t iSels = pListBox->CountSelItems(); - if (iOldSels != iSels) - return true; - - for (int32_t i = 0; i < iSels; ++i) { - CFWL_ListItem* hlistItem = pListBox->GetItem(nullptr, iSelArray[i]); - if (!(hlistItem->GetStates() & FWL_ITEMSTATE_LTB_Selected)) - return true; - } - return false; -} - -uint32_t CXFA_FFListBox::GetAlignment() { - uint32_t dwExtendedStyle = 0; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - int32_t iHorz = para.GetHorizontalAlign(); - switch (iHorz) { - case XFA_ATTRIBUTEENUM_Center: - dwExtendedStyle |= FWL_STYLEEXT_LTB_CenterAlign; - break; - case XFA_ATTRIBUTEENUM_Justify: - break; - case XFA_ATTRIBUTEENUM_JustifyAll: - break; - case XFA_ATTRIBUTEENUM_Radix: - break; - case XFA_ATTRIBUTEENUM_Right: - dwExtendedStyle |= FWL_STYLEEXT_LTB_RightAlign; - break; - default: - dwExtendedStyle |= FWL_STYLEEXT_LTB_LeftAlign; - break; - } - } - return dwExtendedStyle; -} -bool CXFA_FFListBox::UpdateFWLData() { - if (!m_pNormalWidget) { - return false; - } - CFWL_ListBox* pListBox = ((CFWL_ListBox*)m_pNormalWidget); - CFX_ArrayTemplate<CFWL_ListItem*> selItemArray; - CFX_ArrayTemplate<int32_t> iSelArray; - m_pDataAcc->GetSelectedItems(iSelArray); - int32_t iSelCount = iSelArray.GetSize(); - for (int32_t j = 0; j < iSelCount; j++) { - CFWL_ListItem* lpItemSel = pListBox->GetSelItem(iSelArray[j]); - selItemArray.Add(lpItemSel); - } - pListBox->SetSelItem(pListBox->GetSelItem(-1), false); - for (int32_t i = 0; i < iSelCount; i++) { - ((CFWL_ListBox*)m_pNormalWidget)->SetSelItem(selItemArray[i], true); - } - m_pNormalWidget->Update(); - return true; -} -void CXFA_FFListBox::OnSelectChanged( - CFWL_Widget* pWidget, - const CFX_ArrayTemplate<int32_t>& arrSels) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Change; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw); - CFWL_ListBox* pListBox = (CFWL_ListBox*)m_pNormalWidget; - int32_t iSels = pListBox->CountSelItems(); - if (iSels > 0) { - CFWL_ListItem* item = pListBox->GetSelItem(0); - eParam.m_wsNewText = item ? item->GetText() : L""; - } - - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); -} -void CXFA_FFListBox::SetItemState(int32_t nIndex, bool bSelected) { - CFWL_ListItem* item = ((CFWL_ListBox*)m_pNormalWidget)->GetSelItem(nIndex); - ((CFWL_ListBox*)m_pNormalWidget)->SetSelItem(item, bSelected); - m_pNormalWidget->Update(); - AddInvalidateRect(); -} -void CXFA_FFListBox::InsertItem(const CFX_WideStringC& wsLabel, - int32_t nIndex) { - CFX_WideString wsTemp(wsLabel); - ((CFWL_ListBox*)m_pNormalWidget)->AddString(wsTemp.AsStringC()); - m_pNormalWidget->Update(); - AddInvalidateRect(); -} -void CXFA_FFListBox::DeleteItem(int32_t nIndex) { - CFWL_ListBox* listBox = static_cast<CFWL_ListBox*>(m_pNormalWidget); - if (nIndex < 0) - listBox->DeleteAll(); - else - listBox->DeleteString(listBox->GetItem(nullptr, nIndex)); - - listBox->Update(); - AddInvalidateRect(); -} - -void CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) { - m_pOldDelegate->OnProcessMessage(pMessage); -} - -void CXFA_FFListBox::OnProcessEvent(CFWL_Event* pEvent) { - CXFA_FFField::OnProcessEvent(pEvent); - switch (pEvent->GetType()) { - case CFWL_Event::Type::SelectChanged: { - CFX_ArrayTemplate<int32_t> arrSels; - OnSelectChanged(m_pNormalWidget, arrSels); - break; - } - default: - break; - } - m_pOldDelegate->OnProcessEvent(pEvent); -} -void CXFA_FFListBox::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix); -} - -CXFA_FFComboBox::CXFA_FFComboBox(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {} - -CXFA_FFComboBox::~CXFA_FFComboBox() {} - -CFX_RectF CXFA_FFComboBox::GetBBox(uint32_t dwStatus, bool bDrawFocus) { - if (bDrawFocus) - return CFX_RectF(); - return CXFA_FFWidget::GetBBox(dwStatus); -} - -bool CXFA_FFComboBox::PtInActiveRect(const CFX_PointF& point) { - auto pComboBox = static_cast<CFWL_ComboBox*>(m_pNormalWidget); - return pComboBox && pComboBox->GetBBox().Contains(point); -} - -bool CXFA_FFComboBox::LoadWidget() { - CFWL_ComboBox* pComboBox = new CFWL_ComboBox(GetFWLApp()); - m_pNormalWidget = (CFWL_Widget*)pComboBox; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - std::vector<CFX_WideString> wsLabelArray; - m_pDataAcc->GetChoiceListItems(wsLabelArray, false); - int32_t iItems = pdfium::CollectionSize<int32_t>(wsLabelArray); - for (int32_t i = 0; i < iItems; i++) { - pComboBox->AddString(wsLabelArray[i].AsStringC()); - } - CFX_ArrayTemplate<int32_t> iSelArray; - m_pDataAcc->GetSelectedItems(iSelArray); - int32_t iSelCount = iSelArray.GetSize(); - if (iSelCount > 0) { - pComboBox->SetCurSel(iSelArray[0]); - } else { - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Raw); - pComboBox->SetEditText(wsText); - } - UpdateWidgetProperty(); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFComboBox::UpdateWidgetProperty() { - CFWL_ComboBox* pComboBox = (CFWL_ComboBox*)m_pNormalWidget; - if (!pComboBox) { - return; - } - uint32_t dwExtendedStyle = 0; - uint32_t dwEditStyles = - FWL_STYLEEXT_EDT_ReadOnly | FWL_STYLEEXT_EDT_LastLineHeight; - dwExtendedStyle |= UpdateUIProperty(); - if (m_pDataAcc->IsChoiceListAllowTextEntry()) { - dwEditStyles &= ~FWL_STYLEEXT_EDT_ReadOnly; - dwExtendedStyle |= FWL_STYLEEXT_CMB_DropDown; - } - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly; - dwExtendedStyle |= FWL_STYLEEXT_CMB_ReadOnly; - } - dwExtendedStyle |= GetAlignment(); - m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); - if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) { - dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll; - } - pComboBox->EditModifyStylesEx(dwEditStyles, 0xFFFFFFFF); -} - -bool CXFA_FFComboBox::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - if (!CXFA_FFField::OnRButtonUp(dwFlags, point)) - return false; - - GetDoc()->GetDocEnvironment()->PopupMenu(this, point); - return true; -} - -bool CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) { - bool flag = ProcessCommittedData(); - if (!flag) { - UpdateFWLData(); - } - CXFA_FFField::OnKillFocus(pNewWidget); - return true; -} -void CXFA_FFComboBox::OpenDropDownList() { - ((CFWL_ComboBox*)m_pNormalWidget)->OpenDropDownList(true); -} -bool CXFA_FFComboBox::CommitData() { - return m_pDataAcc->SetValue(m_wsNewValue, XFA_VALUEPICTURE_Raw); -} -bool CXFA_FFComboBox::IsDataChanged() { - CFWL_ComboBox* pFWLcombobox = ((CFWL_ComboBox*)m_pNormalWidget); - CFX_WideString wsText = pFWLcombobox->GetEditText(); - int32_t iCursel = pFWLcombobox->GetCurSel(); - if (iCursel >= 0) { - CFX_WideString wsSel = pFWLcombobox->GetTextByIndex(iCursel); - if (wsSel == wsText) - m_pDataAcc->GetChoiceListItem(wsText, iCursel, true); - } - - CFX_WideString wsOldValue; - m_pDataAcc->GetValue(wsOldValue, XFA_VALUEPICTURE_Raw); - if (wsOldValue != wsText) { - m_wsNewValue = wsText; - return true; - } - return false; -} -void CXFA_FFComboBox::FWLEventSelChange(CXFA_EventParam* pParam) { - pParam->m_eType = XFA_EVENT_Change; - pParam->m_pTarget = m_pDataAcc; - CFWL_ComboBox* pFWLcombobox = ((CFWL_ComboBox*)m_pNormalWidget); - pParam->m_wsNewText = pFWLcombobox->GetEditText(); - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, pParam); -} -uint32_t CXFA_FFComboBox::GetAlignment() { - uint32_t dwExtendedStyle = 0; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - int32_t iHorz = para.GetHorizontalAlign(); - switch (iHorz) { - case XFA_ATTRIBUTEENUM_Center: - dwExtendedStyle |= - FWL_STYLEEXT_CMB_EditHCenter | FWL_STYLEEXT_CMB_ListItemCenterAlign; - break; - case XFA_ATTRIBUTEENUM_Justify: - dwExtendedStyle |= FWL_STYLEEXT_CMB_EditJustified; - break; - case XFA_ATTRIBUTEENUM_JustifyAll: - break; - case XFA_ATTRIBUTEENUM_Radix: - break; - case XFA_ATTRIBUTEENUM_Right: - break; - default: - dwExtendedStyle |= - FWL_STYLEEXT_CMB_EditHNear | FWL_STYLEEXT_CMB_ListItemLeftAlign; - break; - } - int32_t iVert = para.GetVerticalAlign(); - switch (iVert) { - case XFA_ATTRIBUTEENUM_Middle: - dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVCenter; - break; - case XFA_ATTRIBUTEENUM_Bottom: - dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVFar; - break; - default: - dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVNear; - break; - } - } - return dwExtendedStyle; -} -bool CXFA_FFComboBox::UpdateFWLData() { - if (!m_pNormalWidget) { - return false; - } - CFX_ArrayTemplate<int32_t> iSelArray; - m_pDataAcc->GetSelectedItems(iSelArray); - int32_t iSelCount = iSelArray.GetSize(); - if (iSelCount > 0) { - ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(iSelArray[0]); - } else { - CFX_WideString wsText; - ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(-1); - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Raw); - ((CFWL_ComboBox*)m_pNormalWidget)->SetEditText(wsText); - } - m_pNormalWidget->Update(); - return true; -} -bool CXFA_FFComboBox::CanUndo() { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditCanUndo(); -} -bool CXFA_FFComboBox::CanRedo() { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditCanRedo(); -} -bool CXFA_FFComboBox::Undo() { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditUndo(); -} -bool CXFA_FFComboBox::Redo() { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditRedo(); -} -bool CXFA_FFComboBox::CanCopy() { - return ((CFWL_ComboBox*)m_pNormalWidget)->EditCanCopy(); -} -bool CXFA_FFComboBox::CanCut() { - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) { - return false; - } - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditCanCut(); -} -bool CXFA_FFComboBox::CanPaste() { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - (m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open); -} -bool CXFA_FFComboBox::CanSelectAll() { - return ((CFWL_ComboBox*)m_pNormalWidget)->EditCanSelectAll(); -} -bool CXFA_FFComboBox::Copy(CFX_WideString& wsCopy) { - return ((CFWL_ComboBox*)m_pNormalWidget)->EditCopy(wsCopy); -} -bool CXFA_FFComboBox::Cut(CFX_WideString& wsCut) { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditCut(wsCut); -} -bool CXFA_FFComboBox::Paste(const CFX_WideString& wsPaste) { - return m_pDataAcc->IsChoiceListAllowTextEntry() && - ((CFWL_ComboBox*)m_pNormalWidget)->EditPaste(wsPaste); -} -void CXFA_FFComboBox::SelectAll() { - ((CFWL_ComboBox*)m_pNormalWidget)->EditSelectAll(); -} -void CXFA_FFComboBox::Delete() { - ((CFWL_ComboBox*)m_pNormalWidget)->EditDelete(); -} -void CXFA_FFComboBox::DeSelect() { - ((CFWL_ComboBox*)m_pNormalWidget)->EditDeSelect(); -} -void CXFA_FFComboBox::SetItemState(int32_t nIndex, bool bSelected) { - if (bSelected) { - ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(nIndex); - } else { - ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(-1); - } - m_pNormalWidget->Update(); - AddInvalidateRect(); -} -void CXFA_FFComboBox::InsertItem(const CFX_WideStringC& wsLabel, - int32_t nIndex) { - ((CFWL_ComboBox*)m_pNormalWidget)->AddString(wsLabel); - m_pNormalWidget->Update(); - AddInvalidateRect(); -} -void CXFA_FFComboBox::DeleteItem(int32_t nIndex) { - if (nIndex < 0) { - ((CFWL_ComboBox*)m_pNormalWidget)->RemoveAll(); - } else { - ((CFWL_ComboBox*)m_pNormalWidget)->RemoveAt(nIndex); - } - m_pNormalWidget->Update(); - AddInvalidateRect(); -} -void CXFA_FFComboBox::OnTextChanged(CFWL_Widget* pWidget, - const CFX_WideString& wsChanged) { - CXFA_EventParam eParam; - m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw); - eParam.m_wsChange = wsChanged; - FWLEventSelChange(&eParam); -} -void CXFA_FFComboBox::OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp) { - CXFA_EventParam eParam; - m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw); - FWLEventSelChange(&eParam); - if (m_pDataAcc->GetChoiceListCommitOn() == XFA_ATTRIBUTEENUM_Select && - bLButtonUp) { - m_pDocView->SetFocusWidgetAcc(nullptr); - } -} -void CXFA_FFComboBox::OnPreOpen(CFWL_Widget* pWidget) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_PreOpen; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PreOpen, &eParam); -} -void CXFA_FFComboBox::OnPostOpen(CFWL_Widget* pWidget) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_PostOpen; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PostOpen, &eParam); -} - -void CXFA_FFComboBox::OnProcessMessage(CFWL_Message* pMessage) { - m_pOldDelegate->OnProcessMessage(pMessage); -} - -void CXFA_FFComboBox::OnProcessEvent(CFWL_Event* pEvent) { - CXFA_FFField::OnProcessEvent(pEvent); - switch (pEvent->GetType()) { - case CFWL_Event::Type::SelectChanged: { - CFWL_EventSelectChanged* postEvent = - static_cast<CFWL_EventSelectChanged*>(pEvent); - OnSelectChanged(m_pNormalWidget, postEvent->bLButtonUp); - break; - } - case CFWL_Event::Type::EditChanged: { - CFX_WideString wsChanged; - OnTextChanged(m_pNormalWidget, wsChanged); - break; - } - case CFWL_Event::Type::PreDropDown: { - OnPreOpen(m_pNormalWidget); - break; - } - case CFWL_Event::Type::PostDropDown: { - OnPostOpen(m_pNormalWidget); - break; - } - default: - break; - } - m_pOldDelegate->OnProcessEvent(pEvent); -} - -void CXFA_FFComboBox::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix); -} diff --git a/xfa/fxfa/app/xfa_ffchoicelist.h b/xfa/fxfa/app/xfa_ffchoicelist.h deleted file mode 100644 index e89366ad13d75eb0c1a9f3ca219630632ff5e0e3..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffchoicelist.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFCHOICELIST_H_ -#define XFA_FXFA_APP_XFA_FFCHOICELIST_H_ - -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/xfa_ffpageview.h" - -class CXFA_FFListBox : public CXFA_FFField { - public: - explicit CXFA_FFListBox(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFListBox() override; - - // CXFA_FFField - bool LoadWidget() override; - bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - void OnSelectChanged(CFWL_Widget* pWidget, - const CFX_ArrayTemplate<int32_t>& arrSels); - void SetItemState(int32_t nIndex, bool bSelected); - void InsertItem(const CFX_WideStringC& wsLabel, int32_t nIndex = -1); - void DeleteItem(int32_t nIndex); - - protected: - bool CommitData() override; - bool UpdateFWLData() override; - bool IsDataChanged() override; - - uint32_t GetAlignment(); - - IFWL_WidgetDelegate* m_pOldDelegate; -}; - -class CXFA_FFComboBox : public CXFA_FFField { - public: - explicit CXFA_FFComboBox(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFComboBox() override; - - // CXFA_FFField - CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false) override; - bool LoadWidget() override; - void UpdateWidgetProperty() override; - bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; - bool CanUndo() override; - bool CanRedo() override; - bool Undo() override; - bool Redo() override; - - bool CanCopy() override; - bool CanCut() override; - bool CanPaste() override; - bool CanSelectAll() override; - bool Copy(CFX_WideString& wsCopy) override; - bool Cut(CFX_WideString& wsCut) override; - bool Paste(const CFX_WideString& wsPaste) override; - void SelectAll() override; - void Delete() override; - void DeSelect() override; - - // IFWL_WidgetDelegate - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - virtual void OpenDropDownList(); - - void OnTextChanged(CFWL_Widget* pWidget, const CFX_WideString& wsChanged); - void OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp); - void OnPreOpen(CFWL_Widget* pWidget); - void OnPostOpen(CFWL_Widget* pWidget); - void SetItemState(int32_t nIndex, bool bSelected); - void InsertItem(const CFX_WideStringC& wsLabel, int32_t nIndex = -1); - void DeleteItem(int32_t nIndex); - - protected: - // CXFA_FFField - bool PtInActiveRect(const CFX_PointF& point) override; - bool CommitData() override; - bool UpdateFWLData() override; - bool IsDataChanged() override; - - uint32_t GetAlignment(); - void FWLEventSelChange(CXFA_EventParam* pParam); - - CFX_WideString m_wsNewValue; - IFWL_WidgetDelegate* m_pOldDelegate; -}; - -#endif // XFA_FXFA_APP_XFA_FFCHOICELIST_H_ diff --git a/xfa/fxfa/app/xfa_ffdoc.cpp b/xfa/fxfa/app/xfa_ffdoc.cpp deleted file mode 100644 index 911bdf84006b133611d10e79e6038454637da909..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffdoc.cpp +++ /dev/null @@ -1,441 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffdoc.h" - -#include <algorithm> -#include <memory> -#include <vector> - -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/fpdf_parser_decode.h" -#include "core/fpdfdoc/cpdf_nametree.h" -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_memory.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fde/xml/fde_xml_imp.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/parser/cxfa_dataexporter.h" -#include "xfa/fxfa/parser/cxfa_dataimporter.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/xfa_checksum.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_fontmgr.h" - -namespace { - -struct FX_BASE64DATA { - uint32_t data1 : 2; - uint32_t data2 : 6; - uint32_t data3 : 4; - uint32_t data4 : 4; - uint32_t data5 : 6; - uint32_t data6 : 2; - uint32_t data7 : 8; -}; - -const uint8_t kStartValuesRemoved = 43; -const uint8_t kDecoderMapSize = 80; -const uint8_t g_FXBase64DecoderMap[kDecoderMapSize] = { - 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, -}; - -uint8_t base64DecoderValue(uint8_t val) { - if (val < kStartValuesRemoved || val >= kStartValuesRemoved + kDecoderMapSize) - return 0xFF; - return g_FXBase64DecoderMap[val - kStartValuesRemoved]; -} - -void Base64DecodePiece(const FX_CHAR src[4], - int32_t iChars, - FX_BASE64DATA& dst, - int32_t& iBytes) { - ASSERT(iChars > 0 && iChars < 5); - iBytes = 1; - dst.data2 = base64DecoderValue(static_cast<uint8_t>(src[0])); - if (iChars > 1) { - uint8_t b = base64DecoderValue(static_cast<uint8_t>(src[1])); - dst.data1 = b >> 4; - dst.data4 = b; - if (iChars > 2) { - iBytes = 2; - b = base64DecoderValue(static_cast<uint8_t>(src[2])); - dst.data3 = b >> 2; - dst.data6 = b; - if (iChars > 3) { - iBytes = 3; - dst.data5 = base64DecoderValue(static_cast<uint8_t>(src[3])); - } else { - dst.data5 = 0; - } - } else { - dst.data3 = 0; - } - } else { - dst.data1 = 0; - } -} - -int32_t Base64DecodeW(const FX_WCHAR* pSrc, int32_t iSrcLen, uint8_t* pDst) { - ASSERT(pSrc); - if (iSrcLen < 1) { - return 0; - } - while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') { - iSrcLen--; - } - if (iSrcLen < 1) { - return 0; - } - if (!pDst) { - int32_t 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; - int32_t iChars = 4, iBytes; - uint8_t* 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 { - *((uint32_t*)&dstData) = 0; - *((uint32_t*)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; - } - Base64DecodePiece(srcData, iChars, dstData, iBytes); - *pDstEnd++ = ((uint8_t*)&dstData)[0]; - if (iBytes > 1) { - *pDstEnd++ = ((uint8_t*)&dstData)[1]; - } - if (iBytes > 2) { - *pDstEnd++ = ((uint8_t*)&dstData)[2]; - } - } - return pDstEnd - pDst; -} - -} // namespace - -CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment) - : m_pDocEnvironment(pDocEnvironment), - m_pDocumentParser(nullptr), - m_pApp(pApp), - m_pNotify(nullptr), - m_pPDFDoc(nullptr), - m_dwDocType(XFA_DOCTYPE_Static) {} - -CXFA_FFDoc::~CXFA_FFDoc() { - CloseDoc(); -} - -uint32_t CXFA_FFDoc::GetDocType() { - return m_dwDocType; -} - -int32_t CXFA_FFDoc::StartLoad() { - m_pNotify = pdfium::MakeUnique<CXFA_FFNotify>(this); - m_pDocumentParser = pdfium::MakeUnique<CXFA_DocumentParser>(m_pNotify.get()); - return m_pDocumentParser->StartParse(m_pStream, XFA_XDPPACKET_XDP); -} - -bool XFA_GetPDFContentsFromPDFXML(CFDE_XMLNode* pPDFElement, - uint8_t*& pByteBuffer, - int32_t& iBufferSize) { - CFDE_XMLElement* pDocumentElement = nullptr; - for (CFDE_XMLNode* pXMLNode = - pPDFElement->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFX_WideString wsTagName; - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - pXMLElement->GetTagName(wsTagName); - if (wsTagName == L"document") { - pDocumentElement = pXMLElement; - break; - } - } - } - if (!pDocumentElement) { - return false; - } - CFDE_XMLElement* pChunkElement = nullptr; - for (CFDE_XMLNode* pXMLNode = - pDocumentElement->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFX_WideString wsTagName; - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - pXMLElement->GetTagName(wsTagName); - if (wsTagName == L"chunk") { - pChunkElement = pXMLElement; - break; - } - } - } - if (!pChunkElement) { - return false; - } - CFX_WideString wsPDFContent; - pChunkElement->GetTextData(wsPDFContent); - iBufferSize = - Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), nullptr); - pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1); - pByteBuffer[iBufferSize] = '0'; // FIXME: I bet this is wrong. - Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), pByteBuffer); - return true; -} -void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) { - CXFA_Node* pChildNode = pNewRoot->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pChildNode) { - CXFA_Node* pOriginChild = - pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash()); - if (pOriginChild) { - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } else { - CXFA_Node* pNextSibling = - pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pNewRoot->RemoveChild(pChildNode); - pOriginRoot->InsertChild(pChildNode); - pChildNode = pNextSibling; - pNextSibling = nullptr; - } - } -} - -int32_t CXFA_FFDoc::DoLoad(IFX_Pause* pPause) { - int32_t iStatus = m_pDocumentParser->DoParse(pPause); - if (iStatus == XFA_PARSESTATUS_Done && !m_pPDFDoc) - return XFA_PARSESTATUS_SyntaxErr; - return iStatus; -} - -void CXFA_FFDoc::StopLoad() { - m_pApp->GetXFAFontMgr()->LoadDocFonts(this); - m_dwDocType = XFA_DOCTYPE_Static; - CXFA_Node* pConfig = ToNode( - m_pDocumentParser->GetDocument()->GetXFAObject(XFA_HASHCODE_Config)); - if (!pConfig) { - return; - } - CXFA_Node* pAcrobat = pConfig->GetFirstChildByClass(XFA_Element::Acrobat); - if (!pAcrobat) { - return; - } - CXFA_Node* pAcrobat7 = pAcrobat->GetFirstChildByClass(XFA_Element::Acrobat7); - if (!pAcrobat7) { - return; - } - CXFA_Node* pDynamicRender = - pAcrobat7->GetFirstChildByClass(XFA_Element::DynamicRender); - if (!pDynamicRender) { - return; - } - CFX_WideString wsType; - if (pDynamicRender->TryContent(wsType) && wsType == L"required") { - m_dwDocType = XFA_DOCTYPE_Dynamic; - } -} - -CXFA_FFDocView* CXFA_FFDoc::CreateDocView(uint32_t dwView) { - if (!m_TypeToDocViewMap[dwView]) - m_TypeToDocViewMap[dwView] = pdfium::MakeUnique<CXFA_FFDocView>(this); - - return m_TypeToDocViewMap[dwView].get(); -} - -CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) { - for (const auto& pair : m_TypeToDocViewMap) { - if (pair.second->GetXFALayout() == pLayout) - return pair.second.get(); - } - return nullptr; -} - -CXFA_FFDocView* CXFA_FFDoc::GetDocView() { - auto it = m_TypeToDocViewMap.begin(); - return it != m_TypeToDocViewMap.end() ? it->second.get() : nullptr; -} - -bool CXFA_FFDoc::OpenDoc(const CFX_RetainPtr<IFX_SeekableReadStream>& pStream) { - m_pStream = pStream; - return true; -} -bool CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) { - if (!pPDFDoc) - return false; - - CPDF_Dictionary* pRoot = pPDFDoc->GetRoot(); - if (!pRoot) - return false; - - CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm"); - if (!pAcroForm) - return false; - - CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA"); - if (!pElementXFA) - return false; - - std::vector<CPDF_Stream*> xfaStreams; - if (pElementXFA->IsArray()) { - CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA; - for (size_t i = 0; i < pXFAArray->GetCount() / 2; i++) { - if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1)) - xfaStreams.push_back(pStream); - } - } else if (pElementXFA->IsStream()) { - xfaStreams.push_back((CPDF_Stream*)pElementXFA); - } - if (xfaStreams.empty()) - return false; - - m_pPDFDoc = pPDFDoc; - m_pStream = MakeSeekableReadStream(xfaStreams); - return true; -} - -bool CXFA_FFDoc::CloseDoc() { - for (const auto& pair : m_TypeToDocViewMap) - pair.second->RunDocClose(); - - CXFA_Document* doc = - m_pDocumentParser ? m_pDocumentParser->GetDocument() : nullptr; - if (doc) - doc->ClearLayoutData(); - - m_TypeToDocViewMap.clear(); - - m_pNotify.reset(nullptr); - m_pApp->GetXFAFontMgr()->ReleaseDocFonts(this); - - for (const auto& pair : m_HashToDibDpiMap) - delete pair.second.pDibSource; - - m_HashToDibDpiMap.clear(); - m_pApp->ClearEventTargets(); - return true; -} -void CXFA_FFDoc::SetDocType(uint32_t dwType) { - m_dwDocType = dwType; -} -CPDF_Document* CXFA_FFDoc::GetPDFDoc() { - return m_pPDFDoc; -} - -CFX_DIBitmap* CXFA_FFDoc::GetPDFNamedImage(const CFX_WideStringC& wsName, - int32_t& iImageXDpi, - int32_t& iImageYDpi) { - if (!m_pPDFDoc) - return nullptr; - - uint32_t dwHash = FX_HashCode_GetW(wsName, false); - auto it = m_HashToDibDpiMap.find(dwHash); - if (it != m_HashToDibDpiMap.end()) { - iImageXDpi = it->second.iImageXDpi; - iImageYDpi = it->second.iImageYDpi; - return static_cast<CFX_DIBitmap*>(it->second.pDibSource); - } - - CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot(); - if (!pRoot) - return nullptr; - - CPDF_Dictionary* pNames = pRoot->GetDictFor("Names"); - if (!pNames) - return nullptr; - - CPDF_Dictionary* pXFAImages = pNames->GetDictFor("XFAImages"); - if (!pXFAImages) - return nullptr; - - CPDF_NameTree nametree(pXFAImages); - CFX_ByteString bsName = PDF_EncodeText(wsName.c_str(), wsName.GetLength()); - CPDF_Object* pObject = nametree.LookupValue(bsName); - if (!pObject) { - for (size_t i = 0; i < nametree.GetCount(); i++) { - CFX_ByteString bsTemp; - CPDF_Object* pTempObject = nametree.LookupValue(i, bsTemp); - if (bsTemp == bsName) { - pObject = pTempObject; - break; - } - } - } - - CPDF_Stream* pStream = ToStream(pObject); - if (!pStream) - return nullptr; - - CPDF_StreamAcc streamAcc; - streamAcc.LoadAllData(pStream); - - CFX_RetainPtr<IFX_SeekableReadStream> pImageFileRead = - IFX_MemoryStream::Create((uint8_t*)streamAcc.GetData(), - streamAcc.GetSize()); - - CFX_DIBitmap* pDibSource = XFA_LoadImageFromBuffer( - pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi); - m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi}; - return pDibSource; -} - -bool CXFA_FFDoc::SavePackage( - XFA_HashCode code, - const CFX_RetainPtr<IFX_SeekableWriteStream>& pFile, - CXFA_ChecksumContext* pCSContext) { - CXFA_Document* doc = m_pDocumentParser->GetDocument(); - std::unique_ptr<CXFA_DataExporter> pExport(new CXFA_DataExporter(doc)); - CXFA_Node* pNode = code == XFA_HASHCODE_Xfa ? doc->GetRoot() - : ToNode(doc->GetXFAObject(code)); - if (!pNode) - return !!pExport->Export(pFile); - - CFX_ByteString bsChecksum; - if (pCSContext) - bsChecksum = pCSContext->GetChecksum(); - - return !!pExport->Export( - pFile, pNode, 0, bsChecksum.GetLength() ? bsChecksum.c_str() : nullptr); -} - -bool CXFA_FFDoc::ImportData( - const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, - bool bXDP) { - auto importer = - pdfium::MakeUnique<CXFA_DataImporter>(m_pDocumentParser->GetDocument()); - return importer->ImportData(pStream); -} diff --git a/xfa/fxfa/app/xfa_ffdochandler.cpp b/xfa/fxfa/app/xfa_ffdochandler.cpp deleted file mode 100644 index db73531ccc5175077607defcfb14e208f7358bb9..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffdochandler.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffdochandler.h" - -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/xfa_checksum.h" -#include "xfa/fxfa/xfa_ffdoc.h" - -CXFA_FFDocHandler::CXFA_FFDocHandler() {} - -CXFA_FFDocHandler::~CXFA_FFDocHandler() {} - -CFXJSE_Value* CXFA_FFDocHandler::GetXFAScriptObject(CXFA_FFDoc* hDoc) { - CXFA_Document* pXFADoc = hDoc->GetXFADoc(); - if (!pXFADoc) - return nullptr; - - CXFA_ScriptContext* pScriptContext = pXFADoc->GetScriptContext(); - if (!pScriptContext) - return nullptr; - return pScriptContext->GetJSValueFromMap(pXFADoc->GetRoot()); -} - -XFA_ATTRIBUTEENUM CXFA_FFDocHandler::GetRestoreState(CXFA_FFDoc* hDoc) { - CXFA_Document* pXFADoc = hDoc->GetXFADoc(); - if (!pXFADoc) - return XFA_ATTRIBUTEENUM_Unknown; - - CXFA_Node* pForm = ToNode(pXFADoc->GetXFAObject(XFA_HASHCODE_Form)); - if (!pForm) - return XFA_ATTRIBUTEENUM_Unknown; - - CXFA_Node* pSubForm = pForm->GetFirstChildByClass(XFA_Element::Subform); - if (!pSubForm) - return XFA_ATTRIBUTEENUM_Unknown; - return pSubForm->GetEnum(XFA_ATTRIBUTE_RestoreState); -} - -bool CXFA_FFDocHandler::RunDocScript(CXFA_FFDoc* hDoc, - XFA_SCRIPTTYPE eScriptType, - const CFX_WideStringC& wsScript, - CFXJSE_Value* pRetValue, - CFXJSE_Value* pThisValue) { - CXFA_Document* pXFADoc = hDoc->GetXFADoc(); - if (!pXFADoc) - return false; - - CXFA_ScriptContext* pScriptContext = pXFADoc->GetScriptContext(); - if (!pScriptContext) - return false; - - return pScriptContext->RunScript( - (XFA_SCRIPTLANGTYPE)eScriptType, wsScript, pRetValue, - pThisValue ? CXFA_ScriptContext::ToObject(pThisValue, nullptr) : nullptr); -} diff --git a/xfa/fxfa/app/xfa_ffdocview.cpp b/xfa/fxfa/app/xfa_ffdocview.cpp deleted file mode 100644 index 87441814e53268c14476461eeee17712513e623f..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffdocview.cpp +++ /dev/null @@ -1,850 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffdocview.h" - -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fxfa/app/xfa_ffbarcode.h" -#include "xfa/fxfa/app/xfa_ffcheckbutton.h" -#include "xfa/fxfa/app/xfa_ffchoicelist.h" -#include "xfa/fxfa/app/xfa_ffdraw.h" -#include "xfa/fxfa/app/xfa_ffexclgroup.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_ffimage.h" -#include "xfa/fxfa/app/xfa_ffimageedit.h" -#include "xfa/fxfa/app/xfa_ffpath.h" -#include "xfa/fxfa/app/xfa_ffpushbutton.h" -#include "xfa/fxfa/app/xfa_ffsignature.h" -#include "xfa/fxfa/app/xfa_ffsubform.h" -#include "xfa/fxfa/app/xfa_fftext.h" -#include "xfa/fxfa/app/xfa_fftextedit.h" -#include "xfa/fxfa/app/xfa_ffwidgetacc.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/parser/cxfa_binditems.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" - -const XFA_ATTRIBUTEENUM gs_EventActivity[] = { - XFA_ATTRIBUTEENUM_Click, XFA_ATTRIBUTEENUM_Change, - XFA_ATTRIBUTEENUM_DocClose, XFA_ATTRIBUTEENUM_DocReady, - XFA_ATTRIBUTEENUM_Enter, XFA_ATTRIBUTEENUM_Exit, - XFA_ATTRIBUTEENUM_Full, XFA_ATTRIBUTEENUM_IndexChange, - XFA_ATTRIBUTEENUM_Initialize, XFA_ATTRIBUTEENUM_MouseDown, - XFA_ATTRIBUTEENUM_MouseEnter, XFA_ATTRIBUTEENUM_MouseExit, - XFA_ATTRIBUTEENUM_MouseUp, XFA_ATTRIBUTEENUM_PostExecute, - XFA_ATTRIBUTEENUM_PostOpen, XFA_ATTRIBUTEENUM_PostPrint, - XFA_ATTRIBUTEENUM_PostSave, XFA_ATTRIBUTEENUM_PostSign, - XFA_ATTRIBUTEENUM_PostSubmit, XFA_ATTRIBUTEENUM_PreExecute, - XFA_ATTRIBUTEENUM_PreOpen, XFA_ATTRIBUTEENUM_PrePrint, - XFA_ATTRIBUTEENUM_PreSave, XFA_ATTRIBUTEENUM_PreSign, - XFA_ATTRIBUTEENUM_PreSubmit, XFA_ATTRIBUTEENUM_Ready, - XFA_ATTRIBUTEENUM_Unknown, -}; - -CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) - : m_bLayoutEvent(false), - m_pListFocusWidget(nullptr), - m_bInLayoutStatus(false), - m_pDoc(pDoc), - m_pXFADocLayout(nullptr), - m_pFocusAcc(nullptr), - m_pFocusWidget(nullptr), - m_pOldFocusWidget(nullptr), - m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None), - m_iLock(0) {} - -CXFA_FFDocView::~CXFA_FFDocView() { - DestroyDocView(); -} - -void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) { - RunBindItems(); - ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true, - nullptr); - ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true, - nullptr); -} -int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) { - m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; - m_pDoc->GetXFADoc()->DoProtoMerge(); - m_pDoc->GetXFADoc()->DoDataMerge(); - m_pXFADocLayout = GetXFALayout(); - int32_t iStatus = m_pXFADocLayout->StartLayout(); - if (iStatus < 0) { - return iStatus; - } - CXFA_Node* pRootItem = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); - if (!pRootItem) { - return iStatus; - } - InitLayout(pRootItem); - InitCalculate(pRootItem); - InitValidate(pRootItem); - ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr); - m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; - return iStatus; -} -int32_t CXFA_FFDocView::DoLayout(IFX_Pause* pPause) { - int32_t iStatus = 100; - iStatus = m_pXFADocLayout->DoLayout(pPause); - if (iStatus != 100) { - return iStatus; - } - m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing; - return iStatus; -} -void CXFA_FFDocView::StopLayout() { - CXFA_Node* pRootItem = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); - if (!pRootItem) { - return; - } - CXFA_Node* pSubformNode = pRootItem->GetChild(0, XFA_Element::Subform); - if (!pSubformNode) { - return; - } - CXFA_Node* pPageSetNode = - pSubformNode->GetFirstChildByClass(XFA_Element::PageSet); - if (!pPageSetNode) { - return; - } - RunCalculateWidgets(); - RunValidate(); - InitLayout(pPageSetNode); - InitCalculate(pPageSetNode); - InitValidate(pPageSetNode); - ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true, - nullptr); - ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, - nullptr); - ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true, - nullptr); - RunCalculateWidgets(); - RunValidate(); - if (RunLayout()) { - ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, - nullptr); - } - m_CalculateAccs.clear(); - if (m_pFocusAcc && !m_pFocusWidget) { - SetFocusWidgetAcc(m_pFocusAcc); - } - m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End; -} -int32_t CXFA_FFDocView::GetLayoutStatus() { - return m_iStatus; -} -void CXFA_FFDocView::ShowNullTestMsg() { - int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg); - CXFA_FFApp* pApp = m_pDoc->GetApp(); - IXFA_AppProvider* pAppProvider = pApp->GetAppProvider(); - if (pAppProvider && iCount) { - int32_t iRemain = iCount > 7 ? iCount - 7 : 0; - iCount -= iRemain; - CFX_WideString wsMsg; - for (int32_t i = 0; i < iCount; i++) { - wsMsg += m_arrNullTestMsg[i] + L"\n"; - } - if (iRemain > 0) { - CFX_WideString wsTemp; - wsTemp.Format( - L"Message limit exceeded. Remaining %d " - L"validation errors not reported.", - iRemain); - wsMsg += L"\n" + wsTemp; - } - pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status, - XFA_MB_OK); - } - m_arrNullTestMsg.clear(); -} - -void CXFA_FFDocView::UpdateDocView() { - if (IsUpdateLocked()) - return; - - LockUpdate(); - for (CXFA_Node* pNode : m_NewAddedNodes) { - InitCalculate(pNode); - InitValidate(pNode); - ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr); - } - m_NewAddedNodes.clear(); - RunSubformIndexChange(); - RunCalculateWidgets(); - RunValidate(); - ShowNullTestMsg(); - if (RunLayout() && m_bLayoutEvent) - RunEventLayoutReady(); - - m_bLayoutEvent = false; - m_CalculateAccs.clear(); - RunInvalidate(); - UnlockUpdate(); -} - -int32_t CXFA_FFDocView::CountPageViews() { - if (!m_pXFADocLayout) { - return 0; - } - return m_pXFADocLayout->CountPages(); -} -CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) { - if (!m_pXFADocLayout) { - return nullptr; - } - return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex)); -} - -CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const { - return m_pDoc->GetXFADoc()->GetDocLayout(); -} -bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) { - CXFA_Node* pNode = pWidgetAcc->GetNode(); - XFA_Element eType = pNode->GetElementType(); - if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) { - return false; - } - pWidgetAcc->ResetData(); - pWidgetAcc->UpdateUIDisplay(); - if (CXFA_Validate validate = pWidgetAcc->GetValidate()) { - AddValidateWidget(pWidgetAcc); - validate.GetNode()->SetFlag(XFA_NodeFlag_NeedsInitApp, false); - } - return true; -} -void CXFA_FFDocView::ResetWidgetData(CXFA_WidgetAcc* pWidgetAcc) { - m_bLayoutEvent = true; - bool bChanged = false; - CXFA_Node* pFormNode = nullptr; - if (pWidgetAcc) { - bChanged = ResetSingleWidgetAccData(pWidgetAcc); - pFormNode = pWidgetAcc->GetNode(); - } else { - pFormNode = GetRootSubform(); - } - if (!pFormNode) { - return; - } - if (pFormNode->GetElementType() != XFA_Element::Field && - pFormNode->GetElementType() != XFA_Element::ExclGroup) { - CXFA_WidgetAccIterator Iterator(this, pFormNode); - while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) { - bChanged |= ResetSingleWidgetAccData(pAcc); - if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup) { - Iterator.SkipTree(); - } - } - } - if (bChanged) { - m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc); - } -} -int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam, - CXFA_WidgetAcc* pWidgetAcc) { - if (!pParam) - return XFA_EVENTERROR_Error; - - if (pParam->m_eType == XFA_EVENT_Validate) { - CFX_WideString wsValidateStr(L"preSubmit"); - CXFA_Node* pConfigItem = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config)); - if (pConfigItem) { - CXFA_Node* pValidateNode = nullptr; - CXFA_Node* pAcrobatNode = pConfigItem->GetChild(0, XFA_Element::Acrobat); - pValidateNode = pAcrobatNode - ? pAcrobatNode->GetChild(0, XFA_Element::Validate) - : nullptr; - if (!pValidateNode) { - CXFA_Node* pPresentNode = - pConfigItem->GetChild(0, XFA_Element::Present); - pValidateNode = pPresentNode - ? pPresentNode->GetChild(0, XFA_Element::Validate) - : nullptr; - } - if (pValidateNode) { - wsValidateStr = pValidateNode->GetContent(); - } - } - bool bValidate = false; - switch (pParam->m_iValidateActivities) { - case XFA_VALIDATE_preSubmit: - bValidate = wsValidateStr.Find(L"preSubmit") != -1; - break; - case XFA_VALIDATE_prePrint: - bValidate = wsValidateStr.Find(L"prePrint") != -1; - break; - case XFA_VALIDATE_preExecute: - bValidate = wsValidateStr.Find(L"preExecute") != -1; - break; - case XFA_VALIDATE_preSave: - bValidate = wsValidateStr.Find(L"preSave") != -1; - break; - } - if (!bValidate) { - return XFA_EVENTERROR_Success; - } - } - CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr; - if (!pNode) { - CXFA_Node* pRootItem = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); - if (!pRootItem) { - return XFA_EVENTERROR_Error; - } - pNode = pRootItem->GetChild(0, XFA_Element::Subform); - } - ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady, - true, nullptr); - return XFA_EVENTERROR_Success; -} -CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() { - if (!m_pWidgetHandler) - m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this); - - return m_pWidgetHandler.get(); -} - -CXFA_WidgetAccIterator* CXFA_FFDocView::CreateWidgetAccIterator( - XFA_WIDGETORDER eOrder) { - CXFA_Node* pFormRoot = GetRootSubform(); - return pFormRoot ? new CXFA_WidgetAccIterator(this, pFormRoot) : nullptr; -} -CXFA_FFWidget* CXFA_FFDocView::GetFocusWidget() { - return m_pFocusWidget; -} -void CXFA_FFDocView::KillFocus() { - if (m_pFocusWidget && - (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) { - (m_pFocusWidget)->OnKillFocus(nullptr); - } - m_pFocusAcc = nullptr; - m_pFocusWidget = nullptr; - m_pOldFocusWidget = nullptr; -} -bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) { - CXFA_FFWidget* pNewFocus = hWidget; - if (m_pOldFocusWidget == pNewFocus) { - return false; - } - CXFA_FFWidget* pOldFocus = m_pOldFocusWidget; - m_pOldFocusWidget = pNewFocus; - if (pOldFocus) { - if (m_pFocusWidget != m_pOldFocusWidget && - (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) { - m_pFocusWidget = pOldFocus; - pOldFocus->OnKillFocus(pNewFocus); - } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) { - if (!pOldFocus->IsLoaded()) { - pOldFocus->LoadWidget(); - } - pOldFocus->OnSetFocus(m_pFocusWidget); - m_pFocusWidget = pOldFocus; - pOldFocus->OnKillFocus(pNewFocus); - } - } - if (m_pFocusWidget == m_pOldFocusWidget) { - return false; - } - pNewFocus = m_pOldFocusWidget; - if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) { - m_pFocusAcc = nullptr; - m_pFocusWidget = nullptr; - m_pListFocusWidget = nullptr; - m_pOldFocusWidget = nullptr; - return false; - } - if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) { - if (!pNewFocus->IsLoaded()) { - pNewFocus->LoadWidget(); - } - pNewFocus->OnSetFocus(m_pFocusWidget); - } - m_pFocusAcc = pNewFocus ? pNewFocus->GetDataAcc() : nullptr; - m_pFocusWidget = pNewFocus; - m_pOldFocusWidget = m_pFocusWidget; - return true; -} -CXFA_WidgetAcc* CXFA_FFDocView::GetFocusWidgetAcc() { - return m_pFocusAcc; -} -void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { - CXFA_FFWidget* pNewFocus = - pWidgetAcc ? pWidgetAcc->GetNextWidget(nullptr) : nullptr; - if (SetFocus(pNewFocus)) { - m_pFocusAcc = pWidgetAcc; - if (m_iStatus == XFA_DOCVIEW_LAYOUTSTATUS_End) { - m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc, m_pFocusWidget); - } - } -} -void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) { - if (m_pFocusAcc == pWidget->GetDataAcc()) { - m_pFocusAcc = nullptr; - m_pFocusWidget = nullptr; - m_pOldFocusWidget = nullptr; - } -} -static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView, - CXFA_WidgetAcc* pWidgetAcc, - CXFA_EventParam* pParam) { - if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) { - return XFA_EVENTERROR_NotExist; - } - if (!pWidgetAcc || pWidgetAcc->GetElementType() == XFA_Element::Draw) { - return XFA_EVENTERROR_NotExist; - } - switch (pParam->m_eType) { - case XFA_EVENT_Calculate: - return pWidgetAcc->ProcessCalculate(); - case XFA_EVENT_Validate: - if (((CXFA_FFDoc*)pDocView->GetDoc()) - ->GetDocEnvironment() - ->IsValidationsEnabled(pDocView->GetDoc())) { - return pWidgetAcc->ProcessValidate(0x01); - } - return XFA_EVENTERROR_Disabled; - case XFA_EVENT_InitCalculate: { - CXFA_Calculate calc = pWidgetAcc->GetCalculate(); - if (!calc) { - return XFA_EVENTERROR_NotExist; - } - if (pWidgetAcc->GetNode()->IsUserInteractive()) - return XFA_EVENTERROR_Disabled; - - CXFA_Script script = calc.GetScript(); - return pWidgetAcc->ExecuteScript(script, pParam); - } - default: - break; - } - int32_t iRet = - pWidgetAcc->ProcessEvent(gs_EventActivity[pParam->m_eType], pParam); - return iRet; -} -int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode, - XFA_EVENTTYPE eEventType, - bool bIsFormReady, - bool bRecursive, - CXFA_Node* pExclude) { - int32_t iRet = XFA_EVENTERROR_NotExist; - if (pFormNode == pExclude) { - return iRet; - } - XFA_Element elementType = pFormNode->GetElementType(); - if (elementType == XFA_Element::Field) { - if (eEventType == XFA_EVENT_IndexChange) { - return iRet; - } - CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData(); - if (!pWidgetAcc) { - return iRet; - } - CXFA_EventParam eParam; - eParam.m_eType = eEventType; - eParam.m_pTarget = pWidgetAcc; - eParam.m_bIsFormReady = bIsFormReady; - return XFA_ProcessEvent(this, pWidgetAcc, &eParam); - } - if (bRecursive) { - for (CXFA_Node* pNode = pFormNode->GetNodeItem( - XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode); - pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling, - XFA_ObjectType::ContainerNode)) { - elementType = pNode->GetElementType(); - if (elementType != XFA_Element::Variables && - elementType != XFA_Element::Draw) { - iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady, - bRecursive, pExclude); - } - } - } - CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData(); - if (!pWidgetAcc) { - return iRet; - } - CXFA_EventParam eParam; - eParam.m_eType = eEventType; - eParam.m_pTarget = pWidgetAcc; - eParam.m_bIsFormReady = bIsFormReady; - iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam); - return iRet; -} - -CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const CFX_WideString& wsName, - CXFA_FFWidget* pRefWidget) { - CXFA_WidgetAcc* pRefAcc = pRefWidget ? pRefWidget->GetDataAcc() : nullptr; - CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc); - return pAcc ? pAcc->GetNextWidget(nullptr) : nullptr; -} - -CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName( - const CFX_WideString& wsName, - CXFA_WidgetAcc* pRefWidgetAcc) { - CFX_WideString wsExpression; - uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | - XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; - CXFA_ScriptContext* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext(); - if (!pScriptContext) { - return nullptr; - } - CXFA_Node* refNode = nullptr; - if (pRefWidgetAcc) { - refNode = pRefWidgetAcc->GetNode(); - wsExpression = wsName; - } else { - wsExpression = L"$form." + wsName; - } - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = pScriptContext->ResolveObjects( - refNode, wsExpression.AsStringC(), resoveNodeRS, dwStyle); - if (iRet < 1) { - return nullptr; - } - if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { - CXFA_Node* pNode = resoveNodeRS.nodes[0]->AsNode(); - if (pNode) { - return (CXFA_WidgetAcc*)pNode->GetWidgetData(); - } - } - return nullptr; -} - -void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender, - uint32_t dwEvent) { - CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender); - m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent); -} - -void CXFA_FFDocView::LockUpdate() { - m_iLock++; -} -void CXFA_FFDocView::UnlockUpdate() { - m_iLock--; -} -bool CXFA_FFDocView::IsUpdateLocked() { - return m_iLock > 0; -} -void CXFA_FFDocView::ClearInvalidateList() { - m_mapPageInvalidate.clear(); -} -void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget, - const CFX_RectF& rtInvalidate) { - AddInvalidateRect(pWidget->GetPageView(), rtInvalidate); -} - -void CXFA_FFDocView::AddInvalidateRect(CXFA_FFPageView* pPageView, - const CFX_RectF& rtInvalidate) { - if (m_mapPageInvalidate[pPageView]) { - m_mapPageInvalidate[pPageView]->Union(rtInvalidate); - return; - } - m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate); -} - -void CXFA_FFDocView::RunInvalidate() { - for (const auto& pair : m_mapPageInvalidate) - m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second, 0); - m_mapPageInvalidate.clear(); -} - -bool CXFA_FFDocView::RunLayout() { - LockUpdate(); - m_bInLayoutStatus = true; - if (!m_pXFADocLayout->IncrementLayout() && - m_pXFADocLayout->StartLayout() < 100) { - m_pXFADocLayout->DoLayout(); - UnlockUpdate(); - m_bInLayoutStatus = false; - m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, - XFA_PAGEVIEWEVENT_StopLayout); - return true; - } - m_bInLayoutStatus = false; - m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, - XFA_PAGEVIEWEVENT_StopLayout); - UnlockUpdate(); - return false; -} - -void CXFA_FFDocView::RunSubformIndexChange() { - for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) { - CXFA_WidgetAcc* pWidgetAcc = - static_cast<CXFA_WidgetAcc*>(pSubformNode->GetWidgetData()); - if (!pWidgetAcc) - continue; - - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_IndexChange; - eParam.m_pTarget = pWidgetAcc; - pWidgetAcc->ProcessEvent(XFA_ATTRIBUTEENUM_IndexChange, &eParam); - } - m_IndexChangedSubforms.clear(); -} - -void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) { - m_NewAddedNodes.push_back(pNode); - InitLayout(pNode); -} - -void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) { - ASSERT(pNode->GetElementType() == XFA_Element::Subform); - m_IndexChangedSubforms.push_back(pNode); -} - -void CXFA_FFDocView::RunDocClose() { - CXFA_Node* pRootItem = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); - if (!pRootItem) { - return; - } - ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true, - nullptr); -} -void CXFA_FFDocView::DestroyDocView() { - ClearInvalidateList(); - m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None; - m_iLock = 0; - m_ValidateAccs.clear(); - m_BindItems.clear(); - m_CalculateAccs.clear(); -} -bool CXFA_FFDocView::IsStaticNotify() { - return m_pDoc->GetDocType() == XFA_DOCTYPE_Static; -} - -void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { - CXFA_WidgetAcc* pCurrentAcc = - !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr; - if (pCurrentAcc != pWidgetAcc) - m_CalculateAccs.push_back(pWidgetAcc); -} - -void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) { - auto pGlobalData = - static_cast<CXFA_CalcData*>(pNodeChange->GetUserData(XFA_CalcData)); - if (!pGlobalData) - return; - - for (const auto& pResultAcc : pGlobalData->m_Globals) { - if (!pResultAcc->GetNode()->HasRemovedChildren()) - AddCalculateWidgetAcc(pResultAcc); - } -} - -void CXFA_FFDocView::RunCalculateRecursive(int32_t& iIndex) { - while (iIndex < pdfium::CollectionSize<int32_t>(m_CalculateAccs)) { - CXFA_WidgetAcc* pCurAcc = m_CalculateAccs[iIndex]; - AddCalculateNodeNotify(pCurAcc->GetNode()); - int32_t iRefCount = - (int32_t)(uintptr_t)pCurAcc->GetNode()->GetUserData(XFA_CalcRefCount); - iRefCount++; - pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount, - (void*)(uintptr_t)iRefCount); - if (iRefCount > 11) { - break; - } - if ((pCurAcc->ProcessCalculate()) == XFA_EVENTERROR_Success) { - AddValidateWidget(pCurAcc); - } - iIndex++; - RunCalculateRecursive(iIndex); - } -} - -int32_t CXFA_FFDocView::RunCalculateWidgets() { - if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc)) { - return XFA_EVENTERROR_Disabled; - } - int32_t iCounts = pdfium::CollectionSize<int32_t>(m_CalculateAccs); - int32_t iIndex = 0; - if (iCounts > 0) - RunCalculateRecursive(iIndex); - - for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs) - pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount, (void*)(uintptr_t)0); - - m_CalculateAccs.clear(); - return XFA_EVENTERROR_Success; -} - -void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) { - if (!pdfium::ContainsValue(m_ValidateAccs, pWidget)) - m_ValidateAccs.push_back(pWidget); -} - -bool CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) { - ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true, - nullptr); - return true; -} - -bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) { - if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc)) - return false; - - ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr); - m_ValidateAccs.clear(); - return true; -} - -bool CXFA_FFDocView::RunValidate() { - if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc)) - return false; - - for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) { - if (!pAcc->GetNode()->HasRemovedChildren()) - pAcc->ProcessValidate(); - } - m_ValidateAccs.clear(); - return true; -} -bool CXFA_FFDocView::RunEventLayoutReady() { - CXFA_Node* pRootItem = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); - if (!pRootItem) { - return false; - } - ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, - nullptr); - RunLayout(); - return true; -} -void CXFA_FFDocView::RunBindItems() { - for (const auto& item : m_BindItems) { - if (item->HasRemovedChildren()) - continue; - - CXFA_Node* pWidgetNode = item->GetNodeItem(XFA_NODEITEM_Parent); - CXFA_WidgetAcc* pAcc = - static_cast<CXFA_WidgetAcc*>(pWidgetNode->GetWidgetData()); - if (!pAcc) - continue; - - CXFA_BindItems binditems(item); - CXFA_ScriptContext* pScriptContext = - pWidgetNode->GetDocument()->GetScriptContext(); - CFX_WideStringC wsRef; - binditems.GetRef(wsRef); - uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | - XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_ALL; - XFA_RESOLVENODE_RS rs; - pScriptContext->ResolveObjects(pWidgetNode, wsRef, rs, dwStyle); - int32_t iCount = rs.nodes.GetSize(); - pAcc->DeleteItem(-1); - if (rs.dwFlags != XFA_RESOVENODE_RSTYPE_Nodes || iCount < 1) - continue; - - CFX_WideStringC wsValueRef, wsLabelRef; - binditems.GetValueRef(wsValueRef); - binditems.GetLabelRef(wsLabelRef); - const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef; - const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$"; - const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$"; - CFX_WideString wsValue; - CFX_WideString wsLabel; - uint32_t uValueHash = FX_HashCode_GetW(wsValueRef, false); - for (int32_t j = 0; j < iCount; j++) { - CXFA_Object* refObj = rs.nodes[j]; - if (!refObj->IsNode()) { - continue; - } - CXFA_Node* refNode = refObj->AsNode(); - if (bValueUseContent) { - wsValue = refNode->GetContent(); - } else { - CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash); - wsValue = nodeValue ? nodeValue->GetContent() : refNode->GetContent(); - } - if (!bUseValue) { - if (bLabelUseContent) { - wsLabel = refNode->GetContent(); - } else { - CXFA_Node* nodeLabel = refNode->GetFirstChildByName(wsLabelRef); - if (nodeLabel) - wsLabel = nodeLabel->GetContent(); - } - } else { - wsLabel = wsValue; - } - pAcc->InsertItem(wsLabel, wsValue); - } - } - m_BindItems.clear(); -} -void CXFA_FFDocView::SetChangeMark() { - if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) { - return; - } - m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc); -} -CXFA_Node* CXFA_FFDocView::GetRootSubform() { - CXFA_Node* pFormPacketNode = - ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); - if (!pFormPacketNode) { - return nullptr; - } - return pFormPacketNode->GetFirstChildByClass(XFA_Element::Subform); -} - -CXFA_WidgetAccIterator::CXFA_WidgetAccIterator(CXFA_FFDocView* pDocView, - CXFA_Node* pTravelRoot) - : m_ContentIterator(pTravelRoot), - m_pDocView(pDocView), - m_pCurWidgetAcc(nullptr) {} - -CXFA_WidgetAccIterator::~CXFA_WidgetAccIterator() {} -void CXFA_WidgetAccIterator::Reset() { - m_pCurWidgetAcc = nullptr; - m_ContentIterator.Reset(); -} - -CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToFirst() { - return nullptr; -} - -CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToLast() { - return nullptr; -} - -CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToNext() { - CXFA_Node* pItem = m_pCurWidgetAcc ? m_ContentIterator.MoveToNext() - : m_ContentIterator.GetCurrent(); - while (pItem) { - m_pCurWidgetAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData()); - if (m_pCurWidgetAcc) - return m_pCurWidgetAcc; - pItem = m_ContentIterator.MoveToNext(); - } - return nullptr; -} - -CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToPrevious() { - return nullptr; -} - -CXFA_WidgetAcc* CXFA_WidgetAccIterator::GetCurrentWidgetAcc() { - return nullptr; -} - -bool CXFA_WidgetAccIterator::SetCurrentWidgetAcc(CXFA_WidgetAcc* hWidget) { - return false; -} - -void CXFA_WidgetAccIterator::SkipTree() { - m_ContentIterator.SkipChildrenAndMoveToNext(); - m_pCurWidgetAcc = nullptr; -} diff --git a/xfa/fxfa/app/xfa_ffdraw.cpp b/xfa/fxfa/app/xfa_ffdraw.cpp deleted file mode 100644 index 37095ddb49b305a3229a1b8d5ff281f1c9a3463f..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffdraw.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffdraw.h" - -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFDraw::CXFA_FFDraw(CXFA_WidgetAcc* pDataAcc) : CXFA_FFWidget(pDataAcc) {} - -CXFA_FFDraw::~CXFA_FFDraw() {} diff --git a/xfa/fxfa/app/xfa_ffdraw.h b/xfa/fxfa/app/xfa_ffdraw.h deleted file mode 100644 index 0212dcca0a7b39475798d20e211f74df137fc788..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffdraw.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFDRAW_H_ -#define XFA_FXFA_APP_XFA_FFDRAW_H_ - -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -class CXFA_FFDraw : public CXFA_FFWidget { - public: - explicit CXFA_FFDraw(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFDraw() override; -}; - -#endif // XFA_FXFA_APP_XFA_FFDRAW_H_ diff --git a/xfa/fxfa/app/xfa_ffexclgroup.cpp b/xfa/fxfa/app/xfa_ffexclgroup.cpp deleted file mode 100644 index 7d63daddbc7fc13d0bd19331df0cfe57c45a4a87..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffexclgroup.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffexclgroup.h" - -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFExclGroup::CXFA_FFExclGroup(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFWidget(pDataAcc) {} - -CXFA_FFExclGroup::~CXFA_FFExclGroup() {} - -void CXFA_FFExclGroup::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); -} diff --git a/xfa/fxfa/app/xfa_ffexclgroup.h b/xfa/fxfa/app/xfa_ffexclgroup.h deleted file mode 100644 index 12a13aea92c0ef46cd66880bf42bb8321e312e29..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffexclgroup.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFEXCLGROUP_H_ -#define XFA_FXFA_APP_XFA_FFEXCLGROUP_H_ - -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -class CXFA_FFExclGroup : public CXFA_FFWidget { - public: - explicit CXFA_FFExclGroup(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFExclGroup() override; - - // CXFA_FFWidget - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; -}; - -#endif // XFA_FXFA_APP_XFA_FFEXCLGROUP_H_ diff --git a/xfa/fxfa/app/xfa_fffield.cpp b/xfa/fxfa/app/xfa_fffield.cpp deleted file mode 100644 index 630d04311fb5d3afcb142de89f6d283b0a3b6f5c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fffield.cpp +++ /dev/null @@ -1,749 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_fffield.h" - -#include "xfa/fwl/cfwl_edit.h" -#include "xfa/fwl/cfwl_eventmouse.h" -#include "xfa/fwl/cfwl_messagekey.h" -#include "xfa/fwl/cfwl_messagekillfocus.h" -#include "xfa/fwl/cfwl_messagemouse.h" -#include "xfa/fwl/cfwl_messagemousewheel.h" -#include "xfa/fwl/cfwl_messagesetfocus.h" -#include "xfa/fwl/cfwl_picturebox.h" -#include "xfa/fwl/cfwl_widgetmgr.h" -#include "xfa/fxfa/app/cxfa_textlayout.h" -#include "xfa/fxfa/app/xfa_fwltheme.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" - -CXFA_FFField::CXFA_FFField(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFWidget(pDataAcc), m_pNormalWidget(nullptr) {} - -CXFA_FFField::~CXFA_FFField() { - CXFA_FFField::UnloadWidget(); -} - -CFX_RectF CXFA_FFField::GetBBox(uint32_t dwStatus, bool bDrawFocus) { - if (!bDrawFocus) - return CXFA_FFWidget::GetBBox(dwStatus); - - XFA_Element type = m_pDataAcc->GetUIType(); - if (type != XFA_Element::Button && type != XFA_Element::CheckButton && - type != XFA_Element::ImageEdit && type != XFA_Element::Signature && - type != XFA_Element::ChoiceList) { - return CFX_RectF(); - } - - CFX_RectF rtBox = m_rtUI; - GetRotateMatrix().TransformRect(rtBox); - return rtBox; -} - -void CXFA_FFField::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - DrawBorder(pGS, borderUI, m_rtUI, &mtRotate); - RenderCaption(pGS, &mtRotate); - DrawHighlight(pGS, &mtRotate, dwStatus, false); - - CFX_RectF rtWidget = m_pNormalWidget->GetWidgetRect(); - CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); - mt.Concat(mtRotate); - GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt); -} -void CXFA_FFField::DrawHighlight(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus, - bool bEllipse) { - if (m_rtUI.IsEmpty() || !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - return; - } - if ((dwStatus & XFA_WidgetStatus_Highlight) && - m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open) { - CXFA_FFDoc* pDoc = GetDoc(); - CFX_Color crHighlight(pDoc->GetDocEnvironment()->GetHighlightColor(pDoc)); - pGS->SetFillColor(&crHighlight); - CFX_Path path; - if (bEllipse) - path.AddEllipse(m_rtUI); - else - path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height); - - pGS->FillPath(&path, FXFILL_WINDING, pMatrix); - } -} -void CXFA_FFField::DrawFocus(CFX_Graphics* pGS, CFX_Matrix* pMatrix) { - if (m_dwStatus & XFA_WidgetStatus_Focused) { - CFX_Color cr(0xFF000000); - pGS->SetStrokeColor(&cr); - FX_FLOAT DashPattern[2] = {1, 1}; - pGS->SetLineDash(0.0f, DashPattern, 2); - pGS->SetLineWidth(0, false); - - CFX_Path path; - path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height); - pGS->StrokePath(&path, pMatrix); - } -} -void CXFA_FFField::SetFWLThemeProvider() { - if (m_pNormalWidget) - m_pNormalWidget->SetThemeProvider(GetApp()->GetFWLTheme()); -} -bool CXFA_FFField::IsLoaded() { - return m_pNormalWidget && CXFA_FFWidget::IsLoaded(); -} -bool CXFA_FFField::LoadWidget() { - SetFWLThemeProvider(); - m_pDataAcc->LoadCaption(); - PerformLayout(); - return true; -} -void CXFA_FFField::UnloadWidget() { - delete m_pNormalWidget; - m_pNormalWidget = nullptr; -} -void CXFA_FFField::SetEditScrollOffset() { - XFA_Element eType = m_pDataAcc->GetUIType(); - if (eType == XFA_Element::TextEdit || eType == XFA_Element::NumericEdit || - eType == XFA_Element::PasswordEdit) { - FX_FLOAT fScrollOffset = 0; - CXFA_FFField* pPrev = static_cast<CXFA_FFField*>(GetPrev()); - if (pPrev) { - CFX_RectF rtMargin = m_pDataAcc->GetUIMargin(); - fScrollOffset = -rtMargin.top; - } - while (pPrev) { - fScrollOffset += pPrev->m_rtUI.height; - pPrev = static_cast<CXFA_FFField*>(pPrev->GetPrev()); - } - ((CFWL_Edit*)m_pNormalWidget)->SetScrollOffset(fScrollOffset); - } -} -bool CXFA_FFField::PerformLayout() { - CXFA_FFWidget::PerformLayout(); - CapPlacement(); - LayoutCaption(); - SetFWLRect(); - SetEditScrollOffset(); - if (m_pNormalWidget) { - m_pNormalWidget->Update(); - } - return true; -} -void CXFA_FFField::CapPlacement() { - CFX_RectF rtWidget = GetRectWithoutRotate(); - CXFA_Margin mgWidget = m_pDataAcc->GetMargin(); - if (mgWidget) { - CXFA_LayoutItem* pItem = this; - FX_FLOAT fLeftInset = 0, fRightInset = 0, fTopInset = 0, fBottomInset = 0; - mgWidget.GetLeftInset(fLeftInset); - mgWidget.GetRightInset(fRightInset); - mgWidget.GetTopInset(fTopInset); - mgWidget.GetBottomInset(fBottomInset); - if (!pItem->GetPrev() && !pItem->GetNext()) { - rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); - } else { - if (!pItem->GetPrev()) - rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, 0); - else if (!pItem->GetNext()) - rtWidget.Deflate(fLeftInset, 0, fRightInset, fBottomInset); - else - rtWidget.Deflate(fLeftInset, 0, fRightInset, 0); - } - } - - XFA_ATTRIBUTEENUM iCapPlacement = XFA_ATTRIBUTEENUM_Unknown; - FX_FLOAT fCapReserve = 0; - CXFA_Caption caption = m_pDataAcc->GetCaption(); - if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) { - iCapPlacement = (XFA_ATTRIBUTEENUM)caption.GetPlacementType(); - if (iCapPlacement == XFA_ATTRIBUTEENUM_Top && GetPrev()) { - m_rtCaption.Reset(); - } else if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom && GetNext()) { - m_rtCaption.Reset(); - } else { - fCapReserve = caption.GetReserve(); - CXFA_LayoutItem* pItem = this; - if (!pItem->GetPrev() && !pItem->GetNext()) { - m_rtCaption = rtWidget; - } else { - pItem = pItem->GetFirst(); - m_rtCaption = pItem->GetRect(false); - pItem = pItem->GetNext(); - while (pItem) { - m_rtCaption.height += pItem->GetRect(false).Height(); - pItem = pItem->GetNext(); - } - XFA_RectWidthoutMargin(m_rtCaption, mgWidget); - } - CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout(); - if (fCapReserve <= 0 && pCapTextLayout) { - CFX_SizeF size; - CFX_SizeF minSize; - CFX_SizeF maxSize; - pCapTextLayout->CalcSize(minSize, maxSize, size); - if (iCapPlacement == XFA_ATTRIBUTEENUM_Top || - iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) { - fCapReserve = size.height; - } else { - fCapReserve = size.width; - } - } - } - } - m_rtUI = rtWidget; - switch (iCapPlacement) { - case XFA_ATTRIBUTEENUM_Left: { - m_rtCaption.width = fCapReserve; - CapLeftRightPlacement(caption, rtWidget, iCapPlacement); - m_rtUI.width -= fCapReserve; - m_rtUI.left += fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Top: { - m_rtCaption.height = fCapReserve; - CapTopBottomPlacement(caption, rtWidget, iCapPlacement); - m_rtUI.top += fCapReserve; - m_rtUI.height -= fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Right: { - m_rtCaption.left = m_rtCaption.right() - fCapReserve; - m_rtCaption.width = fCapReserve; - CapLeftRightPlacement(caption, rtWidget, iCapPlacement); - m_rtUI.width -= fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Bottom: { - m_rtCaption.top = m_rtCaption.bottom() - fCapReserve; - m_rtCaption.height = fCapReserve; - CapTopBottomPlacement(caption, rtWidget, iCapPlacement); - m_rtUI.height -= fCapReserve; - } break; - case XFA_ATTRIBUTEENUM_Inline: - break; - default: - break; - } - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - if (borderUI) { - CXFA_Margin margin = borderUI.GetMargin(); - if (margin) { - XFA_RectWidthoutMargin(m_rtUI, margin); - } - } - m_rtUI.Normalize(); -} -void CXFA_FFField::CapTopBottomPlacement(CXFA_Caption caption, - const CFX_RectF& rtWidget, - int32_t iCapPlacement) { - CFX_RectF rtUIMargin = m_pDataAcc->GetUIMargin(); - m_rtCaption.left += rtUIMargin.left; - if (CXFA_Margin mgCap = caption.GetMargin()) { - XFA_RectWidthoutMargin(m_rtCaption, mgCap); - if (m_rtCaption.height < 0) { - m_rtCaption.top += m_rtCaption.height; - } - } - FX_FLOAT fWidth = rtUIMargin.left + rtUIMargin.width; - FX_FLOAT fHeight = m_rtCaption.height + rtUIMargin.top + rtUIMargin.height; - if (fWidth > rtWidget.width) { - m_rtUI.width += fWidth - rtWidget.width; - } - if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) { - m_rtUI.height = XFA_MINUI_HEIGHT; - m_rtCaption.top += rtUIMargin.top + rtUIMargin.height; - } else if (fHeight > rtWidget.height) { - m_rtUI.height += fHeight - rtWidget.height; - if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) { - m_rtCaption.top += fHeight - rtWidget.height; - } - } -} -void CXFA_FFField::CapLeftRightPlacement(CXFA_Caption caption, - const CFX_RectF& rtWidget, - int32_t iCapPlacement) { - CFX_RectF rtUIMargin = m_pDataAcc->GetUIMargin(); - m_rtCaption.top += rtUIMargin.top; - m_rtCaption.height -= rtUIMargin.top; - if (CXFA_Margin mgCap = caption.GetMargin()) { - XFA_RectWidthoutMargin(m_rtCaption, mgCap); - if (m_rtCaption.height < 0) { - m_rtCaption.top += m_rtCaption.height; - } - } - FX_FLOAT fWidth = m_rtCaption.width + rtUIMargin.left + rtUIMargin.width; - FX_FLOAT fHeight = rtUIMargin.top + rtUIMargin.height; - if (fWidth > rtWidget.width) { - m_rtUI.width += fWidth - rtWidget.width; - if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) { - m_rtCaption.left += fWidth - rtWidget.width; - } - } - if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) { - m_rtUI.height = XFA_MINUI_HEIGHT; - m_rtCaption.top += rtUIMargin.top + rtUIMargin.height; - } else if (fHeight > rtWidget.height) { - m_rtUI.height += fHeight - rtWidget.height; - } -} -void CXFA_FFField::UpdateFWL() { - if (m_pNormalWidget) { - m_pNormalWidget->Update(); - } -} -uint32_t CXFA_FFField::UpdateUIProperty() { - CXFA_Node* pUiNode = m_pDataAcc->GetUIChild(); - uint32_t dwStyle = 0; - if (pUiNode && pUiNode->GetElementType() == XFA_Element::DefaultUi) { - dwStyle = FWL_STYLEEXT_EDT_ReadOnly; - } - return dwStyle; -} -void CXFA_FFField::SetFWLRect() { - if (!m_pNormalWidget) { - return; - } - CFX_RectF rtUi = m_rtUI; - if (rtUi.width < 1.0) - rtUi.width = 1.0; - if (!m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - FX_FLOAT fFontSize = m_pDataAcc->GetFontSize(); - if (rtUi.height < fFontSize) { - rtUi.height = fFontSize; - } - } - m_pNormalWidget->SetWidgetRect(rtUi); -} -bool CXFA_FFField::OnMouseEnter() { - if (!m_pNormalWidget) { - return false; - } - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::Enter; - TranslateFWLMessage(&ms); - return true; -} -bool CXFA_FFField::OnMouseExit() { - if (!m_pNormalWidget) { - return false; - } - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::Leave; - TranslateFWLMessage(&ms); - return true; -} - -CFX_PointF CXFA_FFField::FWLToClient(const CFX_PointF& point) { - return m_pNormalWidget ? point - m_pNormalWidget->GetWidgetRect().TopLeft() - : point; -} - -bool CXFA_FFField::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - return false; - } - if (!PtInActiveRect(point)) - return false; - - SetButtonDown(true); - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - if (!IsButtonDown()) - return false; - - SetButtonDown(false); - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::LeftButtonDblClk; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::Move; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnMouseWheel(uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - - CFWL_MessageMouseWheel ms(nullptr, m_pNormalWidget); - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - ms.m_delta = CFX_PointF(zDelta, 0); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - return false; - } - if (!PtInActiveRect(point)) - return false; - - SetButtonDown(true); - - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::RightButtonDown; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - if (!IsButtonDown()) - return false; - - SetButtonDown(false); - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::RightButtonUp; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { - if (!m_pNormalWidget) - return false; - - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::RightButtonDblClk; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFField::OnSetFocus(CXFA_FFWidget* pOldWidget) { - CXFA_FFWidget::OnSetFocus(pOldWidget); - if (!m_pNormalWidget) { - return false; - } - CFWL_MessageSetFocus ms(nullptr, m_pNormalWidget); - TranslateFWLMessage(&ms); - m_dwStatus |= XFA_WidgetStatus_Focused; - AddInvalidateRect(); - return true; -} -bool CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) { - if (!m_pNormalWidget) { - return CXFA_FFWidget::OnKillFocus(pNewWidget); - } - CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget); - TranslateFWLMessage(&ms); - m_dwStatus &= ~XFA_WidgetStatus_Focused; - AddInvalidateRect(); - CXFA_FFWidget::OnKillFocus(pNewWidget); - return true; -} -bool CXFA_FFField::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { - if (!m_pNormalWidget || !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - return false; - } - CFWL_MessageKey ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_KeyCommand::KeyDown; - ms.m_dwFlags = dwFlags; - ms.m_dwKeyCode = dwKeyCode; - TranslateFWLMessage(&ms); - return true; -} -bool CXFA_FFField::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { - if (!m_pNormalWidget || !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - return false; - } - CFWL_MessageKey ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_KeyCommand::KeyUp; - ms.m_dwFlags = dwFlags; - ms.m_dwKeyCode = dwKeyCode; - TranslateFWLMessage(&ms); - return true; -} -bool CXFA_FFField::OnChar(uint32_t dwChar, uint32_t dwFlags) { - if (!m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - return false; - } - if (dwChar == FWL_VKEY_Tab) { - return true; - } - if (!m_pNormalWidget) { - return false; - } - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) { - return false; - } - CFWL_MessageKey ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_KeyCommand::Char; - ms.m_dwFlags = dwFlags; - ms.m_dwKeyCode = dwChar; - TranslateFWLMessage(&ms); - return true; -} -FWL_WidgetHit CXFA_FFField::OnHitTest(const CFX_PointF& point) { - if (m_pNormalWidget && - m_pNormalWidget->HitTest(FWLToClient(point)) != FWL_WidgetHit::Unknown) { - return FWL_WidgetHit::Client; - } - - if (!GetRectWithoutRotate().Contains(point)) - return FWL_WidgetHit::Unknown; - if (m_rtCaption.Contains(point)) - return FWL_WidgetHit::Titlebar; - return FWL_WidgetHit::Border; -} - -bool CXFA_FFField::OnSetCursor(const CFX_PointF& point) { - return true; -} - -bool CXFA_FFField::PtInActiveRect(const CFX_PointF& point) { - return m_pNormalWidget && m_pNormalWidget->GetWidgetRect().Contains(point); -} - -void CXFA_FFField::LayoutCaption() { - CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout(); - if (!pCapTextLayout) - return; - - FX_FLOAT fHeight = 0; - pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height), - &fHeight); - if (m_rtCaption.height < fHeight) - m_rtCaption.height = fHeight; -} - -void CXFA_FFField::RenderCaption(CFX_Graphics* pGS, CFX_Matrix* pMatrix) { - CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout(); - if (!pCapTextLayout) - return; - - CXFA_Caption caption = m_pDataAcc->GetCaption(); - if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible) - return; - - if (!pCapTextLayout->IsLoaded()) - pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height)); - - CFX_RectF rtClip = m_rtCaption; - rtClip.Intersect(GetRectWithoutRotate()); - CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); - CFX_Matrix mt(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top); - if (pMatrix) { - pMatrix->TransformRect(rtClip); - mt.Concat(*pMatrix); - } - pCapTextLayout->DrawString(pRenderDevice, mt, rtClip); -} - -bool CXFA_FFField::ProcessCommittedData() { - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) - return false; - if (!IsDataChanged()) - return false; - if (CalculateOverride() != 1) - return false; - if (!CommitData()) - return false; - - m_pDocView->SetChangeMark(); - m_pDocView->AddValidateWidget(m_pDataAcc); - return true; -} - -int32_t CXFA_FFField::CalculateOverride() { - CXFA_WidgetAcc* pAcc = m_pDataAcc->GetExclGroup(); - if (!pAcc) { - return CalculateWidgetAcc(m_pDataAcc); - } - if (CalculateWidgetAcc(pAcc) == 0) { - return 0; - } - CXFA_Node* pNode = pAcc->GetExclGroupFirstMember(); - if (!pNode) { - return 1; - } - CXFA_WidgetAcc* pWidgetAcc = nullptr; - while (pNode) { - pWidgetAcc = static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()); - if (!pWidgetAcc) { - return 1; - } - if (CalculateWidgetAcc(pWidgetAcc) == 0) { - return 0; - } - pNode = pWidgetAcc->GetExclGroupNextMember(pNode); - } - return 1; -} -int32_t CXFA_FFField::CalculateWidgetAcc(CXFA_WidgetAcc* pAcc) { - CXFA_Calculate calc = pAcc->GetCalculate(); - if (!calc) { - return 1; - } - XFA_VERSION version = pAcc->GetDoc()->GetXFADoc()->GetCurVersionMode(); - if (calc) { - int32_t iOverride = calc.GetOverride(); - switch (iOverride) { - case XFA_ATTRIBUTEENUM_Error: { - if (version <= XFA_VERSION_204) { - return 1; - } - IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); - if (pAppProvider) { - pAppProvider->MsgBox(L"You are not allowed to modify this field.", - L"Calculate Override", XFA_MBICON_Warning, - XFA_MB_OK); - } - } - return 0; - case XFA_ATTRIBUTEENUM_Warning: { - if (version <= XFA_VERSION_204) { - CXFA_Script script = calc.GetScript(); - if (!script) { - return 1; - } - CFX_WideString wsExpression; - script.GetExpression(wsExpression); - if (wsExpression.IsEmpty()) { - return 1; - } - } - if (pAcc->GetNode()->IsUserInteractive()) - return 1; - - IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); - if (pAppProvider) { - CFX_WideString wsMessage; - calc.GetMessageText(wsMessage); - if (!wsMessage.IsEmpty()) - wsMessage += L"\r\n"; - wsMessage += L"Are you sure you want to modify this field?"; - if (pAppProvider->MsgBox(wsMessage, L"Calculate Override", - XFA_MBICON_Warning, - XFA_MB_YesNo) == XFA_IDYes) { - pAcc->GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); - return 1; - } - } - return 0; - } - case XFA_ATTRIBUTEENUM_Ignore: - return 0; - case XFA_ATTRIBUTEENUM_Disabled: - pAcc->GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); - default: - return 1; - } - } - return 1; -} -bool CXFA_FFField::CommitData() { - return false; -} -bool CXFA_FFField::IsDataChanged() { - return false; -} -void CXFA_FFField::TranslateFWLMessage(CFWL_Message* pMessage) { - GetApp()->GetWidgetMgrDelegate()->OnProcessMessageToForm(pMessage); -} -void CXFA_FFField::OnProcessMessage(CFWL_Message* pMessage) {} - -void CXFA_FFField::OnProcessEvent(CFWL_Event* pEvent) { - switch (pEvent->GetType()) { - case CFWL_Event::Type::Mouse: { - CFWL_EventMouse* event = (CFWL_EventMouse*)pEvent; - if (event->m_dwCmd == FWL_MouseCommand::Enter) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_MouseEnter; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseEnter, &eParam); - } else if (event->m_dwCmd == FWL_MouseCommand::Leave) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_MouseExit; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseExit, &eParam); - } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonDown) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_MouseDown; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseDown, &eParam); - } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonUp) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_MouseUp; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseUp, &eParam); - } - break; - } - case CFWL_Event::Type::Click: { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Click; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam); - break; - } - default: - break; - } -} - -void CXFA_FFField::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) {} diff --git a/xfa/fxfa/app/xfa_fffield.h b/xfa/fxfa/app/xfa_fffield.h deleted file mode 100644 index f10ce6173883280dc65171e3371823a52f4dae18..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fffield.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFFIELD_H_ -#define XFA_FXFA_APP_XFA_FFFIELD_H_ - -#include "xfa/fwl/cfwl_widget.h" -#include "xfa/fwl/ifwl_widgetdelegate.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -#define XFA_MINUI_HEIGHT 4.32f -#define XFA_DEFAULTUI_HEIGHT 2.0f - -class CXFA_FFField : public CXFA_FFWidget, public IFWL_WidgetDelegate { - public: - explicit CXFA_FFField(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFField() override; - - // CXFA_FFWidget - CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false) override; - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - bool IsLoaded() override; - bool LoadWidget() override; - void UnloadWidget() override; - bool PerformLayout() override; - bool OnMouseEnter() override; - bool OnMouseExit() override; - bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnMouseWheel(uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point) override; - bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; - - bool OnSetFocus(CXFA_FFWidget* pOldWidget) override; - bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; - bool OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) override; - bool OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) override; - bool OnChar(uint32_t dwChar, uint32_t dwFlags) override; - FWL_WidgetHit OnHitTest(const CFX_PointF& point) override; - bool OnSetCursor(const CFX_PointF& point) override; - - // IFWL_WidgetDelegate - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - void UpdateFWL(); - uint32_t UpdateUIProperty(); - - protected: - bool PtInActiveRect(const CFX_PointF& point) override; - - virtual void SetFWLRect(); - void SetFWLThemeProvider(); - CFWL_Widget* GetNormalWidget() { return m_pNormalWidget; } - CFX_PointF FWLToClient(const CFX_PointF& point); - void LayoutCaption(); - void RenderCaption(CFX_Graphics* pGS, CFX_Matrix* pMatrix = nullptr); - - int32_t CalculateOverride(); - int32_t CalculateWidgetAcc(CXFA_WidgetAcc* pAcc); - bool ProcessCommittedData(); - virtual bool CommitData(); - virtual bool IsDataChanged(); - void DrawHighlight(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus, - bool bEllipse = false); - void DrawFocus(CFX_Graphics* pGS, CFX_Matrix* pMatrix); - void TranslateFWLMessage(CFWL_Message* pMessage); - void CapPlacement(); - void CapTopBottomPlacement(CXFA_Caption caption, - const CFX_RectF& rtWidget, - int32_t iCapPlacement); - void CapLeftRightPlacement(CXFA_Caption caption, - const CFX_RectF& rtWidget, - int32_t iCapPlacement); - void SetEditScrollOffset(); - - CFWL_Widget* m_pNormalWidget; - CFX_RectF m_rtUI; - CFX_RectF m_rtCaption; -}; - -#endif // XFA_FXFA_APP_XFA_FFFIELD_H_ diff --git a/xfa/fxfa/app/xfa_ffimage.cpp b/xfa/fxfa/app/xfa_ffimage.cpp deleted file mode 100644 index a613221ea63f903201e3462d8161d1f3a331814b..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffimage.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffimage.h" - -#include "xfa/fxfa/app/xfa_ffdraw.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFImage::CXFA_FFImage(CXFA_WidgetAcc* pDataAcc) : CXFA_FFDraw(pDataAcc) {} - -CXFA_FFImage::~CXFA_FFImage() { - CXFA_FFImage::UnloadWidget(); -} - -bool CXFA_FFImage::IsLoaded() { - return !!GetDataAcc()->GetImageImage(); -} -bool CXFA_FFImage::LoadWidget() { - if (GetDataAcc()->GetImageImage()) { - return true; - } - GetDataAcc()->LoadImageImage(); - return CXFA_FFDraw::LoadWidget(); -} -void CXFA_FFImage::UnloadWidget() { - GetDataAcc()->SetImageImage(nullptr); -} -void CXFA_FFImage::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - - CFX_DIBitmap* pDIBitmap = GetDataAcc()->GetImageImage(); - if (!pDIBitmap) - return; - - CFX_RectF rtImage = GetRectWithoutRotate(); - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) - XFA_RectWidthoutMargin(rtImage, mgWidget); - - int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left; - int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - iHorzAlign = para.GetHorizontalAlign(); - iVertAlign = para.GetVerticalAlign(); - } - - CXFA_Value value = m_pDataAcc->GetFormValue(); - CXFA_Image imageObj = value.GetImage(); - int32_t iAspect = imageObj.GetAspect(); - int32_t iImageXDpi = 0; - int32_t iImageYDpi = 0; - m_pDataAcc->GetImageDpi(iImageXDpi, iImageYDpi); - XFA_DrawImage(pGS, rtImage, &mtRotate, pDIBitmap, iAspect, iImageXDpi, - iImageYDpi, iHorzAlign, iVertAlign); -} diff --git a/xfa/fxfa/app/xfa_ffimage.h b/xfa/fxfa/app/xfa_ffimage.h deleted file mode 100644 index 2c42791877fe53c74167b00741b38b12ecf2a789..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffimage.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFIMAGE_H_ -#define XFA_FXFA_APP_XFA_FFIMAGE_H_ - -#include "xfa/fxfa/app/xfa_ffdraw.h" - -class CXFA_FFImage : public CXFA_FFDraw { - public: - explicit CXFA_FFImage(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFImage() override; - - // CXFA_FFWidget - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - bool IsLoaded() override; - bool LoadWidget() override; - void UnloadWidget() override; -}; - -#endif // XFA_FXFA_APP_XFA_FFIMAGE_H_ diff --git a/xfa/fxfa/app/xfa_ffimageedit.cpp b/xfa/fxfa/app/xfa_ffimageedit.cpp deleted file mode 100644 index 01d29eed41912e176367df38fbfa2809c1bf9de2..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffimageedit.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffimageedit.h" - -#include "xfa/fwl/cfwl_app.h" -#include "xfa/fwl/cfwl_messagemouse.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_picturebox.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFImageEdit::CXFA_FFImageEdit(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {} - -CXFA_FFImageEdit::~CXFA_FFImageEdit() { - CXFA_FFImageEdit::UnloadWidget(); -} - -bool CXFA_FFImageEdit::LoadWidget() { - CFWL_PictureBox* pPictureBox = new CFWL_PictureBox(GetFWLApp()); - m_pNormalWidget = pPictureBox; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = pPictureBox->GetDelegate(); - pPictureBox->SetDelegate(this); - - CXFA_FFField::LoadWidget(); - if (m_pDataAcc->GetImageEditImage()) { - return true; - } - UpdateFWLData(); - return true; -} -void CXFA_FFImageEdit::UnloadWidget() { - m_pDataAcc->SetImageEditImage(nullptr); - CXFA_FFField::UnloadWidget(); -} -void CXFA_FFImageEdit::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - DrawBorder(pGS, borderUI, m_rtUI, &mtRotate); - RenderCaption(pGS, &mtRotate); - CFX_DIBitmap* pDIBitmap = m_pDataAcc->GetImageEditImage(); - if (!pDIBitmap) - return; - - CFX_RectF rtImage = m_pNormalWidget->GetWidgetRect(); - int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left; - int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - iHorzAlign = para.GetHorizontalAlign(); - iVertAlign = para.GetVerticalAlign(); - } - - int32_t iAspect = XFA_ATTRIBUTEENUM_Fit; - if (CXFA_Value value = m_pDataAcc->GetFormValue()) { - if (CXFA_Image imageObj = value.GetImage()) - iAspect = imageObj.GetAspect(); - } - - int32_t iImageXDpi = 0; - int32_t iImageYDpi = 0; - m_pDataAcc->GetImageEditDpi(iImageXDpi, iImageYDpi); - XFA_DrawImage(pGS, rtImage, &mtRotate, pDIBitmap, iAspect, iImageXDpi, - iImageYDpi, iHorzAlign, iVertAlign); -} - -bool CXFA_FFImageEdit::OnLButtonDown(uint32_t dwFlags, - const CFX_PointF& point) { - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) - return false; - if (!PtInActiveRect(point)) - return false; - - SetButtonDown(true); - - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -void CXFA_FFImageEdit::SetFWLRect() { - if (!m_pNormalWidget) { - return; - } - CFX_RectF rtUIMargin = m_pDataAcc->GetUIMargin(); - CFX_RectF rtImage(m_rtUI); - rtImage.Deflate(rtUIMargin.left, rtUIMargin.top, rtUIMargin.width, - rtUIMargin.height); - m_pNormalWidget->SetWidgetRect(rtImage); -} -bool CXFA_FFImageEdit::CommitData() { - return true; -} -bool CXFA_FFImageEdit::UpdateFWLData() { - m_pDataAcc->SetImageEditImage(nullptr); - m_pDataAcc->LoadImageEditImage(); - return true; -} - -void CXFA_FFImageEdit::OnProcessMessage(CFWL_Message* pMessage) { - m_pOldDelegate->OnProcessMessage(pMessage); -} - -void CXFA_FFImageEdit::OnProcessEvent(CFWL_Event* pEvent) { - CXFA_FFField::OnProcessEvent(pEvent); - m_pOldDelegate->OnProcessEvent(pEvent); -} - -void CXFA_FFImageEdit::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix); -} diff --git a/xfa/fxfa/app/xfa_ffimageedit.h b/xfa/fxfa/app/xfa_ffimageedit.h deleted file mode 100644 index 73032b9815016b55f323cf757f4a1cbdee590de5..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffimageedit.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFIMAGEEDIT_H_ -#define XFA_FXFA_APP_XFA_FFIMAGEEDIT_H_ - -#include "xfa/fxfa/app/xfa_fffield.h" - -class CXFA_FFImageEdit : public CXFA_FFField { - public: - explicit CXFA_FFImageEdit(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFImageEdit() override; - - // CXFA_FFField - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - bool LoadWidget() override; - void UnloadWidget() override; - bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - protected: - void SetFWLRect() override; - bool UpdateFWLData() override; - bool CommitData() override; - - IFWL_WidgetDelegate* m_pOldDelegate; -}; - -#endif // XFA_FXFA_APP_XFA_FFIMAGEEDIT_H_ diff --git a/xfa/fxfa/app/xfa_ffnotify.cpp b/xfa/fxfa/app/xfa_ffnotify.cpp deleted file mode 100644 index 951b4fd3f1d610f35ee8a5bda5603312a006efae..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffnotify.cpp +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffnotify.h" - -#include "fxjs/cfxjse_value.h" -#include "xfa/fxfa/app/cxfa_textlayout.h" -#include "xfa/fxfa/app/xfa_ffbarcode.h" -#include "xfa/fxfa/app/xfa_ffcheckbutton.h" -#include "xfa/fxfa/app/xfa_ffchoicelist.h" -#include "xfa/fxfa/app/xfa_ffdraw.h" -#include "xfa/fxfa/app/xfa_ffexclgroup.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_ffimage.h" -#include "xfa/fxfa/app/xfa_ffimageedit.h" -#include "xfa/fxfa/app/xfa_ffpath.h" -#include "xfa/fxfa/app/xfa_ffpushbutton.h" -#include "xfa/fxfa/app/xfa_ffsignature.h" -#include "xfa/fxfa/app/xfa_ffsubform.h" -#include "xfa/fxfa/app/xfa_fftext.h" -#include "xfa/fxfa/app/xfa_fftextedit.h" -#include "xfa/fxfa/app/xfa_ffwidgetacc.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" - -static void XFA_FFDeleteWidgetAcc(void* pData) { - delete static_cast<CXFA_WidgetAcc*>(pData); -} - -static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteWidgetAcc = { - XFA_FFDeleteWidgetAcc, nullptr}; - -CXFA_FFNotify::CXFA_FFNotify(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {} -CXFA_FFNotify::~CXFA_FFNotify() {} - -void CXFA_FFNotify::OnPageEvent(CXFA_ContainerLayoutItem* pSender, - uint32_t dwEvent) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pSender->GetLayout()); - if (pDocView) - pDocView->OnPageEvent(pSender, dwEvent); -} - -void CXFA_FFNotify::OnWidgetListItemAdded(CXFA_WidgetData* pSender, - const FX_WCHAR* pLabel, - const FX_WCHAR* pValue, - int32_t iIndex) { - CXFA_WidgetAcc* pWidgetAcc = static_cast<CXFA_WidgetAcc*>(pSender); - if (pWidgetAcc->GetUIType() != XFA_Element::ChoiceList) - return; - - CXFA_FFWidget* pWidget = nullptr; - while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) { - if (pWidget->IsLoaded()) { - if (pWidgetAcc->IsListBox()) { - static_cast<CXFA_FFListBox*>(pWidget)->InsertItem(pLabel, iIndex); - } else { - static_cast<CXFA_FFComboBox*>(pWidget)->InsertItem(pLabel, iIndex); - } - } - } -} - -void CXFA_FFNotify::OnWidgetListItemRemoved(CXFA_WidgetData* pSender, - int32_t iIndex) { - CXFA_WidgetAcc* pWidgetAcc = static_cast<CXFA_WidgetAcc*>(pSender); - if (pWidgetAcc->GetUIType() != XFA_Element::ChoiceList) - return; - - CXFA_FFWidget* pWidget = nullptr; - while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) { - if (pWidget->IsLoaded()) { - if (pWidgetAcc->IsListBox()) { - static_cast<CXFA_FFListBox*>(pWidget)->DeleteItem(iIndex); - } else { - static_cast<CXFA_FFComboBox*>(pWidget)->DeleteItem(iIndex); - } - } - } -} - -CXFA_LayoutItem* CXFA_FFNotify::OnCreateLayoutItem(CXFA_Node* pNode) { - CXFA_LayoutProcessor* pLayout = m_pDoc->GetXFADoc()->GetDocLayout(); - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout); - XFA_Element eType = pNode->GetElementType(); - if (eType == XFA_Element::PageArea) - return new CXFA_FFPageView(pDocView, pNode); - if (eType == XFA_Element::ContentArea) - return new CXFA_ContainerLayoutItem(pNode); - - CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()); - if (!pAcc) - return new CXFA_ContentLayoutItem(pNode); - - CXFA_FFWidget* pWidget; - switch (pAcc->GetUIType()) { - case XFA_Element::Barcode: - pWidget = new CXFA_FFBarcode(pAcc); - break; - case XFA_Element::Button: - pWidget = new CXFA_FFPushButton(pAcc); - break; - case XFA_Element::CheckButton: - pWidget = new CXFA_FFCheckButton(pAcc); - break; - case XFA_Element::ChoiceList: { - if (pAcc->IsListBox()) { - pWidget = new CXFA_FFListBox(pAcc); - } else { - pWidget = new CXFA_FFComboBox(pAcc); - } - } break; - case XFA_Element::DateTimeEdit: - pWidget = new CXFA_FFDateTimeEdit(pAcc); - break; - case XFA_Element::ImageEdit: - pWidget = new CXFA_FFImageEdit(pAcc); - break; - case XFA_Element::NumericEdit: - pWidget = new CXFA_FFNumericEdit(pAcc); - break; - case XFA_Element::PasswordEdit: - pWidget = new CXFA_FFPasswordEdit(pAcc); - break; - case XFA_Element::Signature: - pWidget = new CXFA_FFSignature(pAcc); - break; - case XFA_Element::TextEdit: - pWidget = new CXFA_FFTextEdit(pAcc); - break; - case XFA_Element::Arc: - pWidget = new CXFA_FFArc(pAcc); - break; - case XFA_Element::Line: - pWidget = new CXFA_FFLine(pAcc); - break; - case XFA_Element::Rectangle: - pWidget = new CXFA_FFRectangle(pAcc); - break; - case XFA_Element::Text: - pWidget = new CXFA_FFText(pAcc); - break; - case XFA_Element::Image: - pWidget = new CXFA_FFImage(pAcc); - break; - case XFA_Element::Draw: - pWidget = new CXFA_FFDraw(pAcc); - break; - case XFA_Element::Subform: - pWidget = new CXFA_FFSubForm(pAcc); - break; - case XFA_Element::ExclGroup: - pWidget = new CXFA_FFExclGroup(pAcc); - break; - case XFA_Element::DefaultUi: - default: - pWidget = nullptr; - break; - } - - if (pWidget) - pWidget->SetDocView(pDocView); - return pWidget; -} - -void CXFA_FFNotify::StartFieldDrawLayout(CXFA_Node* pItem, - FX_FLOAT& fCalcWidth, - FX_FLOAT& fCalcHeight) { - CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData()); - if (!pAcc) - return; - - pAcc->StartWidgetLayout(fCalcWidth, fCalcHeight); -} - -bool CXFA_FFNotify::FindSplitPos(CXFA_Node* pItem, - int32_t iBlockIndex, - FX_FLOAT& fCalcHeightPos) { - CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData()); - return pAcc && pAcc->FindSplitPos(iBlockIndex, fCalcHeightPos); -} - -bool CXFA_FFNotify::RunScript(CXFA_Node* pScript, CXFA_Node* pFormItem) { - bool bRet = false; - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return bRet; - } - CXFA_WidgetAcc* pWidgetAcc = - static_cast<CXFA_WidgetAcc*>(pFormItem->GetWidgetData()); - if (!pWidgetAcc) { - return bRet; - } - CXFA_EventParam EventParam; - EventParam.m_eType = XFA_EVENT_Unknown; - CFXJSE_Value* pRetValue = nullptr; - int32_t iRet = - pWidgetAcc->ExecuteScript(CXFA_Script(pScript), &EventParam, &pRetValue); - if (iRet == XFA_EVENTERROR_Success && pRetValue) { - bRet = pRetValue->ToBoolean(); - delete pRetValue; - } - return bRet; -} -int32_t CXFA_FFNotify::ExecEventByDeepFirst(CXFA_Node* pFormNode, - XFA_EVENTTYPE eEventType, - bool bIsFormReady, - bool bRecursive, - CXFA_WidgetAcc* pExclude) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return XFA_EVENTERROR_NotExist; - } - return pDocView->ExecEventActivityByDeepFirst( - pFormNode, eEventType, bIsFormReady, bRecursive, - pExclude ? pExclude->GetNode() : nullptr); -} -void CXFA_FFNotify::AddCalcValidate(CXFA_Node* pNode) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return; - } - CXFA_WidgetAcc* pWidgetAcc = - static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()); - if (!pWidgetAcc) { - return; - } - pDocView->AddCalculateWidgetAcc(pWidgetAcc); - pDocView->AddValidateWidget(pWidgetAcc); -} -CXFA_FFDoc* CXFA_FFNotify::GetHDOC() { - return m_pDoc; -} -IXFA_DocEnvironment* CXFA_FFNotify::GetDocEnvironment() const { - return m_pDoc->GetDocEnvironment(); -} -IXFA_AppProvider* CXFA_FFNotify::GetAppProvider() { - return m_pDoc->GetApp()->GetAppProvider(); -} -CXFA_FFWidgetHandler* CXFA_FFNotify::GetWidgetHandler() { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - return pDocView ? pDocView->GetWidgetHandler() : nullptr; -} -CXFA_FFWidget* CXFA_FFNotify::GetHWidget(CXFA_LayoutItem* pLayoutItem) { - return XFA_GetWidgetFromLayoutItem(pLayoutItem); -} -void CXFA_FFNotify::OpenDropDownList(CXFA_FFWidget* hWidget) { - if (hWidget->GetDataAcc()->GetUIType() != XFA_Element::ChoiceList) { - return; - } - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - pDocView->LockUpdate(); - static_cast<CXFA_FFComboBox*>(hWidget)->OpenDropDownList(); - pDocView->UnlockUpdate(); - pDocView->UpdateDocView(); -} -CFX_WideString CXFA_FFNotify::GetCurrentDateTime() { - CFX_Unitime dataTime; - dataTime.Now(); - CFX_WideString wsDateTime; - wsDateTime.Format(L"%d%02d%02dT%02d%02d%02d", dataTime.GetYear(), - dataTime.GetMonth(), dataTime.GetDay(), dataTime.GetHour(), - dataTime.GetMinute(), dataTime.GetSecond()); - return wsDateTime; -} -void CXFA_FFNotify::ResetData(CXFA_WidgetData* pWidgetData) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return; - } - pDocView->ResetWidgetData(static_cast<CXFA_WidgetAcc*>(pWidgetData)); -} -int32_t CXFA_FFNotify::GetLayoutStatus() { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - return pDocView ? pDocView->GetLayoutStatus() : 0; -} -void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return; - } - pDocView->AddNewFormNode(pNode); -} -void CXFA_FFNotify::RunSubformIndexChange(CXFA_Node* pSubformNode) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return; - } - pDocView->AddIndexChangedSubform(pSubformNode); -} -CXFA_Node* CXFA_FFNotify::GetFocusWidgetNode() { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return nullptr; - } - CXFA_WidgetAcc* pAcc = pDocView->GetFocusWidgetAcc(); - return pAcc ? pAcc->GetNode() : nullptr; -} -void CXFA_FFNotify::SetFocusWidgetNode(CXFA_Node* pNode) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return; - } - CXFA_WidgetAcc* pAcc = - pNode ? static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()) : nullptr; - pDocView->SetFocusWidgetAcc(pAcc); -} - -void CXFA_FFNotify::OnNodeReady(CXFA_Node* pNode) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) - return; - - XFA_Element eType = pNode->GetElementType(); - if (XFA_IsCreateWidget(eType)) { - CXFA_WidgetAcc* pAcc = new CXFA_WidgetAcc(pDocView, pNode); - pNode->SetObject(XFA_ATTRIBUTE_WidgetData, pAcc, &gs_XFADeleteWidgetAcc); - return; - } - switch (eType) { - case XFA_Element::BindItems: - pDocView->m_BindItems.push_back(pNode); - break; - case XFA_Element::Validate: { - pNode->SetFlag(XFA_NodeFlag_NeedsInitApp, false); - } break; - default: - break; - } -} - -void CXFA_FFNotify::OnValueChanging(CXFA_Node* pSender, XFA_ATTRIBUTE eAttr) { - if (eAttr != XFA_ATTRIBUTE_Presence) - return; - - if (pSender->GetPacketID() & XFA_XDPPACKET_Datasets) - return; - - if (!pSender->IsFormContainer()) - return; - - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) - return; - - if (pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End) - return; - - CXFA_WidgetAcc* pWidgetAcc = - static_cast<CXFA_WidgetAcc*>(pSender->GetWidgetData()); - if (!pWidgetAcc) - return; - - CXFA_FFWidget* pWidget = nullptr; - while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) { - if (pWidget->IsLoaded()) - pWidget->AddInvalidateRect(); - } -} - -void CXFA_FFNotify::OnValueChanged(CXFA_Node* pSender, - XFA_ATTRIBUTE eAttr, - CXFA_Node* pParentNode, - CXFA_Node* pWidgetNode) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) - return; - - if (!(pSender->GetPacketID() & XFA_XDPPACKET_Form)) { - if (eAttr == XFA_ATTRIBUTE_Value) - pDocView->AddCalculateNodeNotify(pSender); - return; - } - - XFA_Element eType = pParentNode->GetElementType(); - bool bIsContainerNode = pParentNode->IsContainerNode(); - CXFA_WidgetAcc* pWidgetAcc = - static_cast<CXFA_WidgetAcc*>(pWidgetNode->GetWidgetData()); - if (!pWidgetAcc) - return; - - bool bUpdateProperty = false; - pDocView->SetChangeMark(); - switch (eType) { - case XFA_Element::Caption: { - CXFA_TextLayout* pCapOut = pWidgetAcc->GetCaptionTextLayout(); - if (!pCapOut) - return; - - pCapOut->Unload(); - } break; - case XFA_Element::Ui: - case XFA_Element::Para: - bUpdateProperty = true; - break; - default: - break; - } - if (bIsContainerNode && eAttr == XFA_ATTRIBUTE_Access) - bUpdateProperty = true; - - if (eAttr == XFA_ATTRIBUTE_Value) { - pDocView->AddCalculateNodeNotify(pSender); - if (eType == XFA_Element::Value || bIsContainerNode) { - if (bIsContainerNode) { - pWidgetAcc->UpdateUIDisplay(); - pDocView->AddCalculateWidgetAcc(pWidgetAcc); - pDocView->AddValidateWidget(pWidgetAcc); - } else if (pWidgetNode->GetNodeItem(XFA_NODEITEM_Parent) - ->GetElementType() == XFA_Element::ExclGroup) { - pWidgetAcc->UpdateUIDisplay(); - } - return; - } - } - CXFA_FFWidget* pWidget = nullptr; - while ((pWidget = pWidgetAcc->GetNextWidget(pWidget)) != nullptr) { - if (!pWidget->IsLoaded()) - continue; - - if (bUpdateProperty) - pWidget->UpdateWidgetProperty(); - pWidget->PerformLayout(); - pWidget->AddInvalidateRect(); - } -} - -void CXFA_FFNotify::OnChildAdded(CXFA_Node* pSender) { - if (!pSender->IsFormContainer()) { - return; - } - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) { - return; - } - bool bLayoutReady = - !(pDocView->m_bInLayoutStatus) && - (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End); - if (bLayoutReady) - m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc); -} - -void CXFA_FFNotify::OnChildRemoved() { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); - if (!pDocView) - return; - - bool bLayoutReady = - !(pDocView->m_bInLayoutStatus) && - (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End); - if (bLayoutReady) - m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc); -} - -void CXFA_FFNotify::OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout, - CXFA_LayoutItem* pSender, - int32_t iPageIdx, - uint32_t dwStatus) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout); - if (!pDocView) - return; - - CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender); - if (!pWidget) - return; - - CXFA_FFPageView* pNewPageView = pDocView->GetPageView(iPageIdx); - uint32_t dwFilter = XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable | - XFA_WidgetStatus_Printable; - pWidget->ModifyStatus(dwStatus, dwFilter); - CXFA_FFPageView* pPrePageView = pWidget->GetPageView(); - if (pPrePageView != pNewPageView || - (dwStatus & (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) == - (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) { - pWidget->SetPageView(pNewPageView); - m_pDoc->GetDocEnvironment()->WidgetPostAdd(pWidget, pWidget->GetDataAcc()); - } - if (pDocView->GetLayoutStatus() != XFA_DOCVIEW_LAYOUTSTATUS_End || - !(dwStatus & XFA_WidgetStatus_Visible)) { - return; - } - if (pWidget->IsLoaded()) { - if (pWidget->GetWidgetRect() != pWidget->RecacheWidgetRect()) - pWidget->PerformLayout(); - } else { - pWidget->LoadWidget(); - } - pWidget->AddInvalidateRect(nullptr); -} - -void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout, - CXFA_LayoutItem* pSender) { - CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout); - if (!pDocView) - return; - - CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender); - if (!pWidget) - return; - - pDocView->DeleteLayoutItem(pWidget); - m_pDoc->GetDocEnvironment()->WidgetPreRemove(pWidget, pWidget->GetDataAcc()); - pWidget->AddInvalidateRect(nullptr); -} diff --git a/xfa/fxfa/app/xfa_ffnotify.h b/xfa/fxfa/app/xfa_ffnotify.h deleted file mode 100644 index 1bfaffec896fc750a61ce2f407304185f4c4a681..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffnotify.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFNOTIFY_H_ -#define XFA_FXFA_APP_XFA_FFNOTIFY_H_ - -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/parser/cxfa_document.h" - -class CXFA_FFWidgetHandler; - -class CXFA_FFNotify { - public: - explicit CXFA_FFNotify(CXFA_FFDoc* pDoc); - ~CXFA_FFNotify(); - - void OnPageEvent(CXFA_ContainerLayoutItem* pSender, uint32_t dwEvent); - - void OnWidgetListItemAdded(CXFA_WidgetData* pSender, - const FX_WCHAR* pLabel, - const FX_WCHAR* pValue, - int32_t iIndex); - void OnWidgetListItemRemoved(CXFA_WidgetData* pSender, int32_t iIndex); - - // Node events - void OnNodeReady(CXFA_Node* pNode); - void OnValueChanging(CXFA_Node* pSender, XFA_ATTRIBUTE eAttr); - void OnValueChanged(CXFA_Node* pSender, - XFA_ATTRIBUTE eAttr, - CXFA_Node* pParentNode, - CXFA_Node* pWidgetNode); - void OnChildAdded(CXFA_Node* pSender); - void OnChildRemoved(); - - CXFA_LayoutItem* OnCreateLayoutItem(CXFA_Node* pNode); - void OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout, - CXFA_LayoutItem* pSender, - int32_t iPageIdx, - uint32_t dwStatus); - void OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout, - CXFA_LayoutItem* pSender); - - void StartFieldDrawLayout(CXFA_Node* pItem, - FX_FLOAT& fCalcWidth, - FX_FLOAT& fCalcHeight); - bool FindSplitPos(CXFA_Node* pItem, - int32_t iBlockIndex, - FX_FLOAT& fCalcHeightPos); - bool RunScript(CXFA_Node* pScript, CXFA_Node* pFormItem); - int32_t ExecEventByDeepFirst(CXFA_Node* pFormNode, - XFA_EVENTTYPE eEventType, - bool bIsFormReady = false, - bool bRecursive = true, - CXFA_WidgetAcc* pExclude = nullptr); - void AddCalcValidate(CXFA_Node* pNode); - CXFA_FFDoc* GetHDOC(); - IXFA_DocEnvironment* GetDocEnvironment() const; - IXFA_AppProvider* GetAppProvider(); - CXFA_FFWidgetHandler* GetWidgetHandler(); - CXFA_FFWidget* GetHWidget(CXFA_LayoutItem* pLayoutItem); - void OpenDropDownList(CXFA_FFWidget* hWidget); - CFX_WideString GetCurrentDateTime(); - void ResetData(CXFA_WidgetData* pWidgetData = nullptr); - int32_t GetLayoutStatus(); - void RunNodeInitialize(CXFA_Node* pNode); - void RunSubformIndexChange(CXFA_Node* pSubformNode); - CXFA_Node* GetFocusWidgetNode(); - void SetFocusWidgetNode(CXFA_Node* pNode); - - private: - CXFA_FFDoc* const m_pDoc; -}; - -#endif // XFA_FXFA_APP_XFA_FFNOTIFY_H_ diff --git a/xfa/fxfa/app/xfa_ffpageview.cpp b/xfa/fxfa/app/xfa_ffpageview.cpp deleted file mode 100644 index 7ae5493ba6027c0065c8121858cd90a33f678501..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffpageview.cpp +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffpageview.h" - -#include <memory> -#include <vector> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/fde_render.h" -#include "xfa/fxfa/app/xfa_ffcheckbutton.h" -#include "xfa/fxfa/app/xfa_ffchoicelist.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_ffimageedit.h" -#include "xfa/fxfa/app/xfa_ffpushbutton.h" -#include "xfa/fxfa/app/xfa_fftextedit.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -namespace { - -CFX_Matrix GetPageMatrix(const CFX_RectF& docPageRect, - const CFX_Rect& devicePageRect, - int32_t iRotate, - uint32_t dwCoordinatesType) { - ASSERT(iRotate >= 0 && iRotate <= 3); - - bool bFlipX = (dwCoordinatesType & 0x01) != 0; - bool bFlipY = (dwCoordinatesType & 0x02) != 0; - CFX_Matrix m((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0); - if (iRotate == 0 || iRotate == 2) { - m.a *= (FX_FLOAT)devicePageRect.width / docPageRect.width; - m.d *= (FX_FLOAT)devicePageRect.height / docPageRect.height; - } else { - m.a *= (FX_FLOAT)devicePageRect.height / docPageRect.width; - m.d *= (FX_FLOAT)devicePageRect.width / docPageRect.height; - } - m.Rotate(iRotate * 1.57079632675f); - switch (iRotate) { - case 0: - m.e = bFlipX ? (FX_FLOAT)devicePageRect.right() - : (FX_FLOAT)devicePageRect.left; - m.f = bFlipY ? (FX_FLOAT)devicePageRect.bottom() - : (FX_FLOAT)devicePageRect.top; - break; - case 1: - m.e = bFlipY ? (FX_FLOAT)devicePageRect.left - : (FX_FLOAT)devicePageRect.right(); - m.f = bFlipX ? (FX_FLOAT)devicePageRect.bottom() - : (FX_FLOAT)devicePageRect.top; - break; - case 2: - m.e = bFlipX ? (FX_FLOAT)devicePageRect.left - : (FX_FLOAT)devicePageRect.right(); - m.f = bFlipY ? (FX_FLOAT)devicePageRect.top - : (FX_FLOAT)devicePageRect.bottom(); - break; - case 3: - m.e = bFlipY ? (FX_FLOAT)devicePageRect.right() - : (FX_FLOAT)devicePageRect.left; - m.f = bFlipX ? (FX_FLOAT)devicePageRect.top - : (FX_FLOAT)devicePageRect.bottom(); - break; - default: - break; - } - return m; -} - -bool PageWidgetFilter(CXFA_FFWidget* pWidget, - uint32_t dwFilter, - bool bTraversal, - bool bIgnorerelevant) { - CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc(); - - if (!!(dwFilter & XFA_WidgetStatus_Focused) && - pWidgetAcc->GetElementType() != XFA_Element::Field) { - return false; - } - - uint32_t dwStatus = pWidget->GetStatus(); - if (bTraversal && (dwStatus & XFA_WidgetStatus_Disabled)) - return false; - if (bIgnorerelevant) - return !!(dwStatus & XFA_WidgetStatus_Visible); - - dwFilter &= (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable | - XFA_WidgetStatus_Printable); - return (dwFilter & dwStatus) == dwFilter; -} - -bool IsLayoutElement(XFA_Element eElement, bool bLayoutContainer) { - switch (eElement) { - case XFA_Element::Draw: - case XFA_Element::Field: - case XFA_Element::InstanceManager: - return !bLayoutContainer; - case XFA_Element::Area: - case XFA_Element::Subform: - case XFA_Element::ExclGroup: - case XFA_Element::SubformSet: - case XFA_Element::PageArea: - case XFA_Element::Form: - return true; - default: - return false; - } -} - -} // namespace - -CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea) - : CXFA_ContainerLayoutItem(pPageArea), m_pDocView(pDocView) {} - -CXFA_FFPageView::~CXFA_FFPageView() {} - -CXFA_FFDocView* CXFA_FFPageView::GetDocView() const { - return m_pDocView; -} - -CFX_RectF CXFA_FFPageView::GetPageViewRect() const { - return CFX_RectF(0, 0, GetPageSize()); -} - -CFX_Matrix CXFA_FFPageView::GetDisplayMatrix(const CFX_Rect& rtDisp, - int32_t iRotate) const { - return GetPageMatrix(CFX_RectF(0, 0, GetPageSize()), rtDisp, iRotate, 0); -} - -IXFA_WidgetIterator* CXFA_FFPageView::CreateWidgetIterator( - uint32_t dwTraverseWay, - uint32_t dwWidgetFilter) { - switch (dwTraverseWay) { - case XFA_TRAVERSEWAY_Tranvalse: - return new CXFA_FFTabOrderPageWidgetIterator(this, dwWidgetFilter); - case XFA_TRAVERSEWAY_Form: - return new CXFA_FFPageWidgetIterator(this, dwWidgetFilter); - } - return nullptr; -} - -CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView, - uint32_t dwFilter) { - m_pPageView = pPageView; - m_dwFilter = dwFilter; - m_sIterator.Init(pPageView); - m_bIgnorerelevant = - m_pPageView->GetDocView()->GetDoc()->GetXFADoc()->GetCurVersionMode() < - XFA_VERSION_205; -} -CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() {} -void CXFA_FFPageWidgetIterator::Reset() { - m_sIterator.Reset(); -} -CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToFirst() { - m_sIterator.Reset(); - for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem; - pLayoutItem = m_sIterator.MoveToNext()) { - if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) { - return hWidget; - } - } - return nullptr; -} -CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToLast() { - m_sIterator.SetCurrent(nullptr); - return MoveToPrevious(); -} -CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToNext() { - for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem; - pLayoutItem = m_sIterator.MoveToNext()) { - if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) { - return hWidget; - } - } - return nullptr; -} -CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToPrevious() { - for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem; - pLayoutItem = m_sIterator.MoveToPrev()) { - if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) { - return hWidget; - } - } - return nullptr; -} -CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetCurrentWidget() { - CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); - return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : nullptr; -} -bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* hWidget) { - return hWidget && m_sIterator.SetCurrent(hWidget); -} -CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetWidget( - CXFA_LayoutItem* pLayoutItem) { - if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) { - if (!PageWidgetFilter(pWidget, m_dwFilter, false, m_bIgnorerelevant)) { - return nullptr; - } - if (!pWidget->IsLoaded() && - (pWidget->GetStatus() & XFA_WidgetStatus_Visible) != 0) { - pWidget->LoadWidget(); - } - return pWidget; - } - return nullptr; -} - -CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator( - CXFA_FFPageView* pPageView, - uint32_t dwFilter) - : m_pPageView(pPageView), m_dwFilter(dwFilter), m_iCurWidget(-1) { - m_bIgnorerelevant = - m_pPageView->GetDocView()->GetDoc()->GetXFADoc()->GetCurVersionMode() < - XFA_VERSION_205; - Reset(); -} - -CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() {} - -void CXFA_FFTabOrderPageWidgetIterator::Reset() { - CreateTabOrderWidgetArray(); - m_iCurWidget = -1; -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() { - for (int32_t i = 0; - i < pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) { - if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, - m_bIgnorerelevant)) { - m_iCurWidget = i; - return m_TabOrderWidgetArray[m_iCurWidget]; - } - } - return nullptr; -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() { - for (int32_t i = pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray) - 1; - i >= 0; i--) { - if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, - m_bIgnorerelevant)) { - m_iCurWidget = i; - return m_TabOrderWidgetArray[m_iCurWidget]; - } - } - return nullptr; -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() { - for (int32_t i = m_iCurWidget + 1; - i < pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) { - if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, - m_bIgnorerelevant)) { - m_iCurWidget = i; - return m_TabOrderWidgetArray[m_iCurWidget]; - } - } - m_iCurWidget = -1; - return nullptr; -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() { - for (int32_t i = m_iCurWidget - 1; i >= 0; i--) { - if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, - m_bIgnorerelevant)) { - m_iCurWidget = i; - return m_TabOrderWidgetArray[m_iCurWidget]; - } - } - m_iCurWidget = -1; - return nullptr; -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() { - return m_iCurWidget >= 0 ? m_TabOrderWidgetArray[m_iCurWidget] : nullptr; -} - -bool CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget( - CXFA_FFWidget* hWidget) { - auto it = std::find(m_TabOrderWidgetArray.begin(), - m_TabOrderWidgetArray.end(), hWidget); - if (it == m_TabOrderWidgetArray.end()) - return false; - - m_iCurWidget = it - m_TabOrderWidgetArray.begin(); - return true; -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget( - CXFA_FFWidget* pWidget) { - CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc(); - CXFA_Node* pTraversal = pAcc->GetNode()->GetChild(0, XFA_Element::Traversal); - if (pTraversal) { - CXFA_Node* pTraverse = pTraversal->GetChild(0, XFA_Element::Traverse); - if (pTraverse) { - CFX_WideString wsTraverseWidgetName; - if (pTraverse->GetAttribute(XFA_ATTRIBUTE_Ref, wsTraverseWidgetName)) { - return FindWidgetByName(wsTraverseWidgetName, pWidget); - } - } - } - return nullptr; -} -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName( - const CFX_WideString& wsWidgetName, - CXFA_FFWidget* pRefWidget) { - return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget); -} - -void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() { - m_TabOrderWidgetArray.clear(); - - std::vector<CXFA_FFWidget*> SpaceOrderWidgetArray; - CreateSpaceOrderWidgetArray(&SpaceOrderWidgetArray); - if (SpaceOrderWidgetArray.empty()) - return; - - int32_t nWidgetCount = pdfium::CollectionSize<int32_t>(SpaceOrderWidgetArray); - CXFA_FFWidget* hWidget = SpaceOrderWidgetArray[0]; - while (pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray) < - nWidgetCount) { - if (!pdfium::ContainsValue(m_TabOrderWidgetArray, hWidget)) { - m_TabOrderWidgetArray.push_back(hWidget); - CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc(); - if (pWidgetAcc->GetUIType() == XFA_Element::ExclGroup) { - auto it = std::find(SpaceOrderWidgetArray.begin(), - SpaceOrderWidgetArray.end(), hWidget); - int32_t iWidgetIndex = it != SpaceOrderWidgetArray.end() - ? it - SpaceOrderWidgetArray.begin() + 1 - : 0; - while (true) { - CXFA_FFWidget* pRadio = - SpaceOrderWidgetArray[iWidgetIndex % nWidgetCount]; - if (pRadio->GetDataAcc()->GetExclGroup() != pWidgetAcc) { - break; - } - if (!pdfium::ContainsValue(m_TabOrderWidgetArray, hWidget)) { - m_TabOrderWidgetArray.push_back(pRadio); - } - iWidgetIndex++; - } - } - if (CXFA_FFWidget* hTraverseWidget = GetTraverseWidget(hWidget)) { - hWidget = hTraverseWidget; - continue; - } - } - auto it = std::find(SpaceOrderWidgetArray.begin(), - SpaceOrderWidgetArray.end(), hWidget); - int32_t iWidgetIndex = it != SpaceOrderWidgetArray.end() - ? it - SpaceOrderWidgetArray.begin() + 1 - : 0; - hWidget = SpaceOrderWidgetArray[iWidgetIndex % nWidgetCount]; - } -} - -static int32_t XFA_TabOrderWidgetComparator(const void* phWidget1, - const void* phWidget2) { - auto param1 = *static_cast<CXFA_TabParam**>(const_cast<void*>(phWidget1)); - auto param2 = *static_cast<CXFA_TabParam**>(const_cast<void*>(phWidget2)); - CFX_RectF rt1 = param1->m_pWidget->GetWidgetRect(); - CFX_RectF rt2 = param2->m_pWidget->GetWidgetRect(); - FX_FLOAT x1 = rt1.left, y1 = rt1.top, x2 = rt2.left, y2 = rt2.top; - if (y1 < y2 || (y1 - y2 < XFA_FLOAT_PERCISION && x1 < x2)) - return -1; - return 1; -} - -void CXFA_FFTabOrderPageWidgetIterator::OrderContainer( - CXFA_LayoutItemIterator* sIterator, - CXFA_LayoutItem* pContainerItem, - CXFA_TabParam* pContainer, - bool& bCurrentItem, - bool& bContentArea, - bool bMarsterPage) { - CFX_ArrayTemplate<CXFA_TabParam*> tabParams; - CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext(); - while (pSearchItem) { - if (!pSearchItem->IsContentLayoutItem()) { - bContentArea = true; - pSearchItem = sIterator->MoveToNext(); - continue; - } - if (bMarsterPage && bContentArea) { - break; - } - if (bMarsterPage || bContentArea) { - CXFA_FFWidget* hWidget = GetWidget(pSearchItem); - if (!hWidget) { - pSearchItem = sIterator->MoveToNext(); - continue; - } - if (pContainerItem && (pSearchItem->GetParent() != pContainerItem)) { - bCurrentItem = true; - break; - } - CXFA_TabParam* pParam = new CXFA_TabParam; - pParam->m_pWidget = hWidget; - tabParams.Add(pParam); - if (IsLayoutElement(pSearchItem->GetFormNode()->GetElementType(), true)) { - OrderContainer(sIterator, pSearchItem, pParam, bCurrentItem, - bContentArea, bMarsterPage); - } - } - if (bCurrentItem) { - pSearchItem = sIterator->GetCurrent(); - bCurrentItem = false; - } else { - pSearchItem = sIterator->MoveToNext(); - } - } - int32_t iChildren = tabParams.GetSize(); - if (iChildren > 1) { - FXSYS_qsort(tabParams.GetData(), iChildren, sizeof(void*), - XFA_TabOrderWidgetComparator); - } - for (int32_t iStart = 0; iStart < iChildren; iStart++) { - std::unique_ptr<CXFA_TabParam> pParam(tabParams[iStart]); - pContainer->m_Children.push_back(pParam->m_pWidget); - pContainer->m_Children.insert(pContainer->m_Children.end(), - pParam->m_Children.begin(), - pParam->m_Children.end()); - } - tabParams.RemoveAll(); -} -void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray( - std::vector<CXFA_FFWidget*>* WidgetArray) { - CXFA_LayoutItemIterator sIterator; - sIterator.Init(m_pPageView); - auto pParam = pdfium::MakeUnique<CXFA_TabParam>(); - bool bCurrentItem = false; - bool bContentArea = false; - OrderContainer(&sIterator, nullptr, pParam.get(), bCurrentItem, bContentArea); - WidgetArray->insert(WidgetArray->end(), pParam->m_Children.begin(), - pParam->m_Children.end()); - - sIterator.Reset(); - bCurrentItem = false; - bContentArea = false; - pParam->m_Children.clear(); - OrderContainer(&sIterator, nullptr, pParam.get(), bCurrentItem, bContentArea, - true); - WidgetArray->insert(WidgetArray->end(), pParam->m_Children.begin(), - pParam->m_Children.end()); -} - -CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetWidget( - CXFA_LayoutItem* pLayoutItem) { - if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) { - if (!pWidget->IsLoaded() && - (pWidget->GetStatus() & XFA_WidgetStatus_Visible)) { - pWidget->LoadWidget(); - } - return pWidget; - } - return nullptr; -} - -CXFA_TabParam::CXFA_TabParam() : m_pWidget(nullptr) {} - -CXFA_TabParam::~CXFA_TabParam() {} diff --git a/xfa/fxfa/app/xfa_ffpath.cpp b/xfa/fxfa/app/xfa_ffpath.cpp deleted file mode 100644 index 43016fe5c63ab4e80b6e77af03975bd069324331..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffpath.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffpath.h" - -#include "xfa/fxfa/app/xfa_ffdraw.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" - -CXFA_FFLine::CXFA_FFLine(CXFA_WidgetAcc* pDataAcc) : CXFA_FFDraw(pDataAcc) {} - -CXFA_FFLine::~CXFA_FFLine() {} - -void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect, - int32_t iHand, - FX_FLOAT fLineWidth) { - FX_FLOAT fHalfWidth = fLineWidth / 2.0f; - if (rect.height < 1.0f) { - switch (iHand) { - case XFA_ATTRIBUTEENUM_Left: - rect.top -= fHalfWidth; - break; - case XFA_ATTRIBUTEENUM_Right: - rect.top += fHalfWidth; - } - } else if (rect.width < 1.0f) { - switch (iHand) { - case XFA_ATTRIBUTEENUM_Left: - rect.left += fHalfWidth; - break; - case XFA_ATTRIBUTEENUM_Right: - rect.left += fHalfWidth; - break; - } - } else { - switch (iHand) { - case XFA_ATTRIBUTEENUM_Left: - rect.Inflate(fHalfWidth, fHalfWidth); - break; - case XFA_ATTRIBUTEENUM_Right: - rect.Deflate(fHalfWidth, fHalfWidth); - break; - } - } -} - -void CXFA_FFLine::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CXFA_Value value = m_pDataAcc->GetFormValue(); - if (!value) - return; - - CXFA_Line lineObj = value.GetLine(); - FX_ARGB lineColor = 0xFF000000; - int32_t iStrokeType = 0; - FX_FLOAT fLineWidth = 1.0f; - int32_t iCap = 0; - CXFA_Edge edge = lineObj.GetEdge(); - if (edge) { - if (edge.GetPresence() != XFA_ATTRIBUTEENUM_Visible) - return; - - lineColor = edge.GetColor(); - iStrokeType = edge.GetStrokeType(); - fLineWidth = edge.GetThickness(); - iCap = edge.GetCapType(); - } - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CFX_RectF rtLine = GetRectWithoutRotate(); - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) - XFA_RectWidthoutMargin(rtLine, mgWidget); - - GetRectFromHand(rtLine, lineObj.GetHand(), fLineWidth); - CFX_Path linePath; - if (lineObj.GetSlope() && rtLine.right() > 0.0f && rtLine.bottom() > 0.0f) - linePath.AddLine(rtLine.TopRight(), rtLine.BottomLeft()); - else - linePath.AddLine(rtLine.TopLeft(), rtLine.BottomRight()); - - CFX_Color color(lineColor); - pGS->SaveGraphState(); - pGS->SetLineWidth(fLineWidth, true); - XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap); - pGS->SetStrokeColor(&color); - pGS->SetLineCap(XFA_LineCapToFXGE(iCap)); - pGS->StrokePath(&linePath, &mtRotate); - pGS->RestoreGraphState(); -} - -CXFA_FFArc::CXFA_FFArc(CXFA_WidgetAcc* pDataAcc) : CXFA_FFDraw(pDataAcc) {} - -CXFA_FFArc::~CXFA_FFArc() {} - -void CXFA_FFArc::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CXFA_Value value = m_pDataAcc->GetFormValue(); - if (!value) - return; - - CXFA_Arc arcObj = value.GetArc(); - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CFX_RectF rtArc = GetRectWithoutRotate(); - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) - XFA_RectWidthoutMargin(rtArc, mgWidget); - - DrawBorder(pGS, arcObj, rtArc, &mtRotate); -} - -CXFA_FFRectangle::CXFA_FFRectangle(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFDraw(pDataAcc) {} - -CXFA_FFRectangle::~CXFA_FFRectangle() {} - -void CXFA_FFRectangle::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CXFA_Value value = m_pDataAcc->GetFormValue(); - if (!value) - return; - - CXFA_Rectangle rtObj = value.GetRectangle(); - CFX_RectF rect = GetRectWithoutRotate(); - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) - XFA_RectWidthoutMargin(rect, mgWidget); - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - DrawBorder(pGS, rtObj, rect, &mtRotate); -} diff --git a/xfa/fxfa/app/xfa_ffpath.h b/xfa/fxfa/app/xfa_ffpath.h deleted file mode 100644 index 002f75d262f7c7d3c71cceaf176988e14ab009fe..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffpath.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFPATH_H_ -#define XFA_FXFA_APP_XFA_FFPATH_H_ - -#include "xfa/fxfa/app/xfa_ffdraw.h" - -class CXFA_FFLine : public CXFA_FFDraw { - public: - explicit CXFA_FFLine(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFLine() override; - - // CXFA_FFWidget - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - - private: - void GetRectFromHand(CFX_RectF& rect, int32_t iHand, FX_FLOAT fLineWidth); -}; - -class CXFA_FFArc : public CXFA_FFDraw { - public: - explicit CXFA_FFArc(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFArc() override; - - // CXFA_FFWidget - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; -}; - -class CXFA_FFRectangle : public CXFA_FFDraw { - public: - explicit CXFA_FFRectangle(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFRectangle() override; - - // CXFA_FFWidget - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; -}; - -#endif // XFA_FXFA_APP_XFA_FFPATH_H_ diff --git a/xfa/fxfa/app/xfa_ffpushbutton.cpp b/xfa/fxfa/app/xfa_ffpushbutton.cpp deleted file mode 100644 index 7b6be8203565a21131c7c1ff64415323b3572237..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffpushbutton.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffpushbutton.h" - -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fwl/cfwl_pushbutton.h" -#include "xfa/fwl/cfwl_widgetmgr.h" -#include "xfa/fxfa/app/cxfa_textlayout.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_ffwidgetacc.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" - -CXFA_FFPushButton::CXFA_FFPushButton(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc), - m_pRolloverTextLayout(nullptr), - m_pDownTextLayout(nullptr), - m_pDownProvider(nullptr), - m_pRollProvider(nullptr), - m_pOldDelegate(nullptr) {} - -CXFA_FFPushButton::~CXFA_FFPushButton() { - CXFA_FFPushButton::UnloadWidget(); -} - -void CXFA_FFPushButton::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - RenderHighlightCaption(pGS, &mtRotate); - - CFX_RectF rtWidget = GetRectWithoutRotate(); - CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); - mt.Concat(mtRotate); - GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt); -} - -bool CXFA_FFPushButton::LoadWidget() { - ASSERT(!m_pNormalWidget); - CFWL_PushButton* pPushButton = new CFWL_PushButton(GetFWLApp()); - m_pOldDelegate = pPushButton->GetDelegate(); - pPushButton->SetDelegate(this); - - m_pNormalWidget = pPushButton; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - m_pNormalWidget->LockUpdate(); - UpdateWidgetProperty(); - LoadHighlightCaption(); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFPushButton::UpdateWidgetProperty() { - uint32_t dwStyleEx = 0; - switch (m_pDataAcc->GetButtonHighlight()) { - case XFA_ATTRIBUTEENUM_Inverted: - dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteInverted; - break; - case XFA_ATTRIBUTEENUM_Outline: - dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteOutLine; - break; - case XFA_ATTRIBUTEENUM_Push: - dwStyleEx = XFA_FWL_PSBSTYLEEXT_HilitePush; - break; - default: - break; - } - m_pNormalWidget->ModifyStylesEx(dwStyleEx, 0xFFFFFFFF); -} - -void CXFA_FFPushButton::UnloadWidget() { - delete m_pRolloverTextLayout; - m_pRolloverTextLayout = nullptr; - delete m_pDownTextLayout; - m_pDownTextLayout = nullptr; - delete m_pDownProvider; - m_pDownProvider = nullptr; - delete m_pRollProvider; - m_pRollProvider = nullptr; - CXFA_FFField::UnloadWidget(); -} - -bool CXFA_FFPushButton::PerformLayout() { - CXFA_FFWidget::PerformLayout(); - CFX_RectF rtWidget = GetRectWithoutRotate(); - - m_rtUI = rtWidget; - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) - XFA_RectWidthoutMargin(rtWidget, mgWidget); - - CXFA_Caption caption = m_pDataAcc->GetCaption(); - m_rtCaption = rtWidget; - if (CXFA_Margin mgCap = caption.GetMargin()) - XFA_RectWidthoutMargin(m_rtCaption, mgCap); - - LayoutHighlightCaption(); - SetFWLRect(); - if (m_pNormalWidget) - m_pNormalWidget->Update(); - - return true; -} -FX_FLOAT CXFA_FFPushButton::GetLineWidth() { - CXFA_Border border = m_pDataAcc->GetBorder(); - if (border && border.GetPresence() == XFA_ATTRIBUTEENUM_Visible) { - CXFA_Edge edge = border.GetEdge(0); - return edge.GetThickness(); - } - return 0; -} -FX_ARGB CXFA_FFPushButton::GetLineColor() { - return 0xFF000000; -} -FX_ARGB CXFA_FFPushButton::GetFillColor() { - return 0xFFFFFFFF; -} -void CXFA_FFPushButton::LoadHighlightCaption() { - CXFA_Caption caption = m_pDataAcc->GetCaption(); - if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) { - { - CFX_WideString wsRollover; - bool bRichText; - if (m_pDataAcc->GetButtonRollover(wsRollover, bRichText)) { - if (!m_pRollProvider) { - m_pRollProvider = - new CXFA_TextProvider(m_pDataAcc, XFA_TEXTPROVIDERTYPE_Rollover); - } - m_pRolloverTextLayout = new CXFA_TextLayout(m_pRollProvider); - } - CFX_WideString wsDown; - if (m_pDataAcc->GetButtonDown(wsDown, bRichText)) { - if (!m_pDownProvider) { - m_pDownProvider = - new CXFA_TextProvider(m_pDataAcc, XFA_TEXTPROVIDERTYPE_Down); - } - m_pDownTextLayout = new CXFA_TextLayout(m_pDownProvider); - } - } - } -} -void CXFA_FFPushButton::LayoutHighlightCaption() { - CFX_SizeF sz(m_rtCaption.width, m_rtCaption.height); - LayoutCaption(); - if (m_pRolloverTextLayout) { - m_pRolloverTextLayout->Layout(sz); - } - if (m_pDownTextLayout) { - m_pDownTextLayout->Layout(sz); - } -} -void CXFA_FFPushButton::RenderHighlightCaption(CFX_Graphics* pGS, - CFX_Matrix* pMatrix) { - CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout(); - CXFA_Caption caption = m_pDataAcc->GetCaption(); - if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible) - return; - - CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); - CFX_RectF rtClip = m_rtCaption; - rtClip.Intersect(GetRectWithoutRotate()); - CFX_Matrix mt(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top); - if (pMatrix) { - pMatrix->TransformRect(rtClip); - mt.Concat(*pMatrix); - } - - uint32_t dwState = m_pNormalWidget->GetStates(); - if (m_pDownTextLayout && (dwState & FWL_STATE_PSB_Pressed) && - (dwState & FWL_STATE_PSB_Hovered)) { - if (m_pDownTextLayout->DrawString(pRenderDevice, mt, rtClip)) - return; - } else if (m_pRolloverTextLayout && (dwState & FWL_STATE_PSB_Hovered)) { - if (m_pRolloverTextLayout->DrawString(pRenderDevice, mt, rtClip)) - return; - } - - if (pCapTextLayout) - pCapTextLayout->DrawString(pRenderDevice, mt, rtClip); -} - -void CXFA_FFPushButton::OnProcessMessage(CFWL_Message* pMessage) { - m_pOldDelegate->OnProcessMessage(pMessage); -} - -void CXFA_FFPushButton::OnProcessEvent(CFWL_Event* pEvent) { - m_pOldDelegate->OnProcessEvent(pEvent); - CXFA_FFField::OnProcessEvent(pEvent); -} - -void CXFA_FFPushButton::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - if (m_pNormalWidget->GetStylesEx() & XFA_FWL_PSBSTYLEEXT_HiliteInverted) { - if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) && - (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) { - CFX_RectF rtFill(0, 0, m_pNormalWidget->GetWidgetRect().Size()); - FX_FLOAT fLineWith = GetLineWidth(); - rtFill.Deflate(fLineWith, fLineWith); - CFX_Color cr(FXARGB_MAKE(128, 128, 255, 255)); - pGraphics->SetFillColor(&cr); - - CFX_Path path; - path.AddRectangle(rtFill.left, rtFill.top, rtFill.width, rtFill.height); - pGraphics->FillPath(&path, FXFILL_WINDING, (CFX_Matrix*)pMatrix); - } - } else if (m_pNormalWidget->GetStylesEx() & - XFA_FWL_PSBSTYLEEXT_HiliteOutLine) { - if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) && - (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) { - FX_FLOAT fLineWidth = GetLineWidth(); - CFX_Color cr(FXARGB_MAKE(255, 128, 255, 255)); - pGraphics->SetStrokeColor(&cr); - pGraphics->SetLineWidth(fLineWidth); - - CFX_Path path; - CFX_RectF rect = m_pNormalWidget->GetWidgetRect(); - path.AddRectangle(0, 0, rect.width, rect.height); - pGraphics->StrokePath(&path, (CFX_Matrix*)pMatrix); - } - } -} diff --git a/xfa/fxfa/app/xfa_ffpushbutton.h b/xfa/fxfa/app/xfa_ffpushbutton.h deleted file mode 100644 index eb18ccb11caef49cf44e95ae51607fa835880f67..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffpushbutton.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFPUSHBUTTON_H_ -#define XFA_FXFA_APP_XFA_FFPUSHBUTTON_H_ - -#include "xfa/fxfa/app/xfa_fffield.h" - -#define XFA_FWL_PSBSTYLEEXT_HiliteNone (0L << 0) -#define XFA_FWL_PSBSTYLEEXT_HiliteInverted (1L << 0) -#define XFA_FWL_PSBSTYLEEXT_HilitePush (2L << 0) -#define XFA_FWL_PSBSTYLEEXT_HiliteOutLine (4L << 0) - -class CXFA_TextProvider; - -class CXFA_FFPushButton : public CXFA_FFField { - public: - explicit CXFA_FFPushButton(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFPushButton() override; - - // CXFA_FFField - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - bool LoadWidget() override; - void UnloadWidget() override; - bool PerformLayout() override; - void UpdateWidgetProperty() override; - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - protected: - void LoadHighlightCaption(); - void LayoutHighlightCaption(); - void RenderHighlightCaption(CFX_Graphics* pGS, CFX_Matrix* pMatrix = nullptr); - FX_FLOAT GetLineWidth(); - FX_ARGB GetLineColor(); - FX_ARGB GetFillColor(); - - CXFA_TextLayout* m_pRolloverTextLayout; - CXFA_TextLayout* m_pDownTextLayout; - CXFA_TextProvider* m_pDownProvider; - CXFA_TextProvider* m_pRollProvider; - IFWL_WidgetDelegate* m_pOldDelegate; -}; - -#endif // XFA_FXFA_APP_XFA_FFPUSHBUTTON_H_ diff --git a/xfa/fxfa/app/xfa_ffsignature.cpp b/xfa/fxfa/app/xfa_ffsignature.cpp deleted file mode 100644 index bf2bba3adffb4aa4217a4f5e0391ef80d8c46c6f..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffsignature.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffsignature.h" - -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFSignature::CXFA_FFSignature(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc) {} - -CXFA_FFSignature::~CXFA_FFSignature() {} - -bool CXFA_FFSignature::LoadWidget() { - return CXFA_FFField::LoadWidget(); -} - -void CXFA_FFSignature::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - - CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); - DrawBorder(pGS, borderUI, m_rtUI, &mtRotate); - RenderCaption(pGS, &mtRotate); - DrawHighlight(pGS, &mtRotate, dwStatus, false); -} - -bool CXFA_FFSignature::OnMouseEnter() { - return false; -} - -bool CXFA_FFSignature::OnMouseExit() { - return false; -} - -bool CXFA_FFSignature::OnLButtonDown(uint32_t dwFlags, - const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnLButtonDblClk(uint32_t dwFlags, - const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnMouseWheel(uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnRButtonDown(uint32_t dwFlags, - const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnRButtonDblClk(uint32_t dwFlags, - const CFX_PointF& point) { - return false; -} - -bool CXFA_FFSignature::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { - return false; -} - -bool CXFA_FFSignature::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { - return false; -} - -bool CXFA_FFSignature::OnChar(uint32_t dwChar, uint32_t dwFlags) { - return false; -} - -FWL_WidgetHit CXFA_FFSignature::OnHitTest(const CFX_PointF& point) { - if (m_pNormalWidget && - m_pNormalWidget->HitTest(FWLToClient(point)) != FWL_WidgetHit::Unknown) { - return FWL_WidgetHit::Client; - } - - if (!GetRectWithoutRotate().Contains(point)) - return FWL_WidgetHit::Unknown; - if (m_rtCaption.Contains(point)) - return FWL_WidgetHit::Titlebar; - return FWL_WidgetHit::Client; -} - -bool CXFA_FFSignature::OnSetCursor(const CFX_PointF& point) { - return false; -} diff --git a/xfa/fxfa/app/xfa_ffsignature.h b/xfa/fxfa/app/xfa_ffsignature.h deleted file mode 100644 index 934323f436f373e19fa5464bbd2ec27f2119d154..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffsignature.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFSIGNATURE_H_ -#define XFA_FXFA_APP_XFA_FFSIGNATURE_H_ - -#include "xfa/fxfa/app/xfa_fffield.h" - -class CXFA_FFSignature final : public CXFA_FFField { - public: - explicit CXFA_FFSignature(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFSignature() override; - - // CXFA_FFField - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - bool LoadWidget() override; - bool OnMouseEnter() override; - bool OnMouseExit() override; - bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnMouseWheel(uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& pointy) override; - bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; - - bool OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) override; - bool OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) override; - bool OnChar(uint32_t dwChar, uint32_t dwFlags) override; - FWL_WidgetHit OnHitTest(const CFX_PointF& point) override; - bool OnSetCursor(const CFX_PointF& point) override; -}; - -#endif // XFA_FXFA_APP_XFA_FFSIGNATURE_H_ diff --git a/xfa/fxfa/app/xfa_ffsubform.cpp b/xfa/fxfa/app/xfa_ffsubform.cpp deleted file mode 100644 index 0b479f4d4cd5ffb764d420abe8f8285c68141295..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffsubform.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffsubform.h" - -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFSubForm::CXFA_FFSubForm(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFWidget(pDataAcc) {} - -CXFA_FFSubForm::~CXFA_FFSubForm() {} diff --git a/xfa/fxfa/app/xfa_ffsubform.h b/xfa/fxfa/app/xfa_ffsubform.h deleted file mode 100644 index e6b77a8b33e49bec34dff34cf87772c9e99b403f..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffsubform.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFSUBFORM_H_ -#define XFA_FXFA_APP_XFA_FFSUBFORM_H_ - -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -class CXFA_FFSubForm : public CXFA_FFWidget { - public: - explicit CXFA_FFSubForm(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFSubForm() override; -}; - -#endif // XFA_FXFA_APP_XFA_FFSUBFORM_H_ diff --git a/xfa/fxfa/app/xfa_fftext.cpp b/xfa/fxfa/app/xfa_fftext.cpp deleted file mode 100644 index e8d7aa32d02851e3753592e0d9421fdfee6f1b37..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fftext.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_fftext.h" - -#include "xfa/fwl/fwl_widgetdef.h" -#include "xfa/fwl/fwl_widgethit.h" -#include "xfa/fxfa/app/cxfa_linkuserdata.h" -#include "xfa/fxfa/app/cxfa_pieceline.h" -#include "xfa/fxfa/app/cxfa_textlayout.h" -#include "xfa/fxfa/app/xfa_ffdraw.h" -#include "xfa/fxfa/app/xfa_textpiece.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_graphics.h" - -CXFA_FFText::CXFA_FFText(CXFA_WidgetAcc* pDataAcc) : CXFA_FFDraw(pDataAcc) {} - -CXFA_FFText::~CXFA_FFText() {} - -void CXFA_FFText::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CFX_Matrix mtRotate = GetRotateMatrix(); - if (pMatrix) - mtRotate.Concat(*pMatrix); - - CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); - - CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); - if (!pTextLayout) - return; - - CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); - CFX_RectF rtText = GetRectWithoutRotate(); - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { - CXFA_LayoutItem* pItem = this; - if (!pItem->GetPrev() && !pItem->GetNext()) { - XFA_RectWidthoutMargin(rtText, mgWidget); - } else { - FX_FLOAT fLeftInset; - FX_FLOAT fRightInset; - FX_FLOAT fTopInset = 0; - FX_FLOAT fBottomInset = 0; - mgWidget.GetLeftInset(fLeftInset); - mgWidget.GetRightInset(fRightInset); - if (!pItem->GetPrev()) - mgWidget.GetTopInset(fTopInset); - else if (!pItem->GetNext()) - mgWidget.GetBottomInset(fBottomInset); - - rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); - } - } - - CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top); - CFX_RectF rtClip = rtText; - mtRotate.TransformRect(rtClip); - mt.Concat(mtRotate); - pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex()); -} - -bool CXFA_FFText::IsLoaded() { - CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); - return pTextLayout && !pTextLayout->m_bHasBlock; -} -bool CXFA_FFText::PerformLayout() { - CXFA_FFDraw::PerformLayout(); - CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); - if (!pTextLayout) { - return false; - } - if (!pTextLayout->m_bHasBlock) { - return true; - } - pTextLayout->m_Blocks.RemoveAll(); - CXFA_LayoutItem* pItem = this; - if (!pItem->GetPrev() && !pItem->GetNext()) { - return true; - } - pItem = pItem->GetFirst(); - while (pItem) { - CFX_RectF rtText = pItem->GetRect(false); - if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { - if (!pItem->GetPrev()) { - FX_FLOAT fTopInset; - mgWidget.GetTopInset(fTopInset); - rtText.height -= fTopInset; - } else if (!pItem->GetNext()) { - FX_FLOAT fBottomInset; - mgWidget.GetBottomInset(fBottomInset); - rtText.height -= fBottomInset; - } - } - pTextLayout->ItemBlocks(rtText, pItem->GetIndex()); - pItem = pItem->GetNext(); - } - pTextLayout->m_bHasBlock = false; - return true; -} - -bool CXFA_FFText::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - if (!GetRectWithoutRotate().Contains(point)) - return false; - - const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(point); - if (!wsURLContent) - return false; - - SetButtonDown(true); - return true; -} - -bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { - return GetRectWithoutRotate().Contains(point) && !!GetLinkURLAtPoint(point); -} - -bool CXFA_FFText::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - if (!IsButtonDown()) - return false; - - SetButtonDown(false); - const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(point); - if (!wsURLContent) - return false; - - CXFA_FFDoc* pDoc = GetDoc(); - pDoc->GetDocEnvironment()->GotoURL(pDoc, wsURLContent); - return true; -} - -FWL_WidgetHit CXFA_FFText::OnHitTest(const CFX_PointF& point) { - if (!GetRectWithoutRotate().Contains(point)) - return FWL_WidgetHit::Unknown; - if (!GetLinkURLAtPoint(point)) - return FWL_WidgetHit::Unknown; - return FWL_WidgetHit::HyperLink; -} - -const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) { - CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); - if (!pTextLayout) - return nullptr; - - CFX_RectF rect = GetRectWithoutRotate(); - for (const auto& pPieceLine : *pTextLayout->GetPieceLines()) { - for (const auto& pPiece : pPieceLine->m_textPieces) { - if (pPiece->pLinkData && - pPiece->rtPiece.Contains(point - rect.TopLeft())) { - return pPiece->pLinkData->GetLinkURL(); - } - } - } - return nullptr; -} diff --git a/xfa/fxfa/app/xfa_fftext.h b/xfa/fxfa/app/xfa_fftext.h deleted file mode 100644 index c5538217914131365c9eea5b55fdf07453a67ba0..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fftext.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFTEXT_H_ -#define XFA_FXFA_APP_XFA_FFTEXT_H_ - -#include "xfa/fxfa/app/xfa_ffdraw.h" - -class CXFA_FFText : public CXFA_FFDraw { - public: - explicit CXFA_FFText(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFText() override; - - // CXFA_FFWidget - bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) override; - FWL_WidgetHit OnHitTest(const CFX_PointF& point) override; - void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) override; - bool IsLoaded() override; - bool PerformLayout() override; - - private: - const FX_WCHAR* GetLinkURLAtPoint(const CFX_PointF& point); -}; - -#endif // XFA_FXFA_APP_XFA_FFTEXT_H_ diff --git a/xfa/fxfa/app/xfa_fftextedit.cpp b/xfa/fxfa/app/xfa_fftextedit.cpp deleted file mode 100644 index 094839f48626a57e9491005d0e329e7536758e26..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fftextedit.cpp +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_fftextedit.h" - -#include <vector> - -#include "xfa/fwl/cfwl_datetimepicker.h" -#include "xfa/fwl/cfwl_edit.h" -#include "xfa/fwl/cfwl_eventcheckword.h" -#include "xfa/fwl/cfwl_eventselectchanged.h" -#include "xfa/fwl/cfwl_eventtextchanged.h" -#include "xfa/fwl/cfwl_eventvalidate.h" -#include "xfa/fwl/cfwl_messagekillfocus.h" -#include "xfa/fwl/cfwl_messagemouse.h" -#include "xfa/fwl/cfwl_messagesetfocus.h" -#include "xfa/fwl/cfwl_notedriver.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/parser/xfa_localevalue.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFTextEdit::CXFA_FFTextEdit(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {} - -CXFA_FFTextEdit::~CXFA_FFTextEdit() { - if (m_pNormalWidget) { - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->UnregisterEventTarget(m_pNormalWidget); - } -} - -bool CXFA_FFTextEdit::LoadWidget() { - CFWL_Edit* pFWLEdit = new CFWL_Edit( - GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); - m_pNormalWidget = pFWLEdit; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - UpdateWidgetProperty(); - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display); - pFWLEdit->SetText(wsText); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFTextEdit::UpdateWidgetProperty() { - CFWL_Edit* pWidget = (CFWL_Edit*)m_pNormalWidget; - if (!pWidget) { - return; - } - uint32_t dwStyle = 0; - uint32_t dwExtendedStyle = FWL_STYLEEXT_EDT_ShowScrollbarFocus | - FWL_STYLEEXT_EDT_OuterScrollbar | - FWL_STYLEEXT_EDT_LastLineHeight; - dwExtendedStyle |= UpdateUIProperty(); - if (m_pDataAcc->IsMultiLine()) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_MultiLine | FWL_STYLEEXT_EDT_WantReturn; - if (m_pDataAcc->GetVerticalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) { - dwStyle |= FWL_WGTSTYLE_VScroll; - dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoVScroll; - } - } else if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll; - } - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly; - dwExtendedStyle |= FWL_STYLEEXT_EDT_MultiLine; - } - XFA_Element eType = XFA_Element::Unknown; - int32_t iMaxChars = m_pDataAcc->GetMaxChars(eType); - if (eType == XFA_Element::ExData) { - iMaxChars = 0; - } - int32_t iNumCells = m_pDataAcc->GetNumberOfCells(); - if (iNumCells == 0) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText; - pWidget->SetLimit(iMaxChars > 0 ? iMaxChars : 1); - } else if (iNumCells > 0) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText; - pWidget->SetLimit(iNumCells); - } else { - pWidget->SetLimit(iMaxChars); - } - dwExtendedStyle |= GetAlignment(); - m_pNormalWidget->ModifyStyles(dwStyle, 0xFFFFFFFF); - m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); -} - -bool CXFA_FFTextEdit::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - if (!PtInActiveRect(point)) - return false; - if (!IsFocused()) { - m_dwStatus |= XFA_WidgetStatus_Focused; - UpdateFWLData(); - AddInvalidateRect(); - } - - SetButtonDown(true); - CFWL_MessageMouse ms(nullptr, m_pNormalWidget); - ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFTextEdit::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) - return false; - if (!PtInActiveRect(point)) - return false; - if (!IsFocused()) { - m_dwStatus |= XFA_WidgetStatus_Focused; - UpdateFWLData(); - AddInvalidateRect(); - } - - SetButtonDown(true); - CFWL_MessageMouse ms(nullptr, nullptr); - ms.m_dwCmd = FWL_MouseCommand::RightButtonDown; - ms.m_dwFlags = dwFlags; - ms.m_pos = FWLToClient(point); - TranslateFWLMessage(&ms); - return true; -} - -bool CXFA_FFTextEdit::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - if (!CXFA_FFField::OnRButtonUp(dwFlags, point)) - return false; - - GetDoc()->GetDocEnvironment()->PopupMenu(this, point); - return true; -} - -bool CXFA_FFTextEdit::OnSetFocus(CXFA_FFWidget* pOldWidget) { - m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged; - if (!IsFocused()) { - m_dwStatus |= XFA_WidgetStatus_Focused; - UpdateFWLData(); - AddInvalidateRect(); - } - CXFA_FFWidget::OnSetFocus(pOldWidget); - CFWL_MessageSetFocus ms(nullptr, m_pNormalWidget); - TranslateFWLMessage(&ms); - return true; -} -bool CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) { - CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget); - TranslateFWLMessage(&ms); - m_dwStatus &= ~XFA_WidgetStatus_Focused; - SetEditScrollOffset(); - ProcessCommittedData(); - UpdateFWLData(); - AddInvalidateRect(); - CXFA_FFWidget::OnKillFocus(pNewWidget); - m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged; - return true; -} -bool CXFA_FFTextEdit::CommitData() { - CFX_WideString wsText = static_cast<CFWL_Edit*>(m_pNormalWidget)->GetText(); - if (m_pDataAcc->SetValue(wsText, XFA_VALUEPICTURE_Edit)) { - m_pDataAcc->UpdateUIDisplay(this); - return true; - } - ValidateNumberField(wsText); - return false; -} -void CXFA_FFTextEdit::ValidateNumberField(const CFX_WideString& wsText) { - CXFA_WidgetAcc* pAcc = GetDataAcc(); - if (pAcc && pAcc->GetUIType() == XFA_Element::NumericEdit) { - IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); - if (pAppProvider) { - CFX_WideString wsSomField; - pAcc->GetNode()->GetSOMExpression(wsSomField); - - CFX_WideString wsMessage; - wsMessage.Format(L"%s can not contain %s", wsText.c_str(), - wsSomField.c_str()); - pAppProvider->MsgBox(wsMessage, pAppProvider->GetAppTitle(), - XFA_MBICON_Error, XFA_MB_OK); - } - } -} -bool CXFA_FFTextEdit::IsDataChanged() { - return (m_dwStatus & XFA_WidgetStatus_TextEditValueChanged) != 0; -} -uint32_t CXFA_FFTextEdit::GetAlignment() { - uint32_t dwExtendedStyle = 0; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - int32_t iHorz = para.GetHorizontalAlign(); - switch (iHorz) { - case XFA_ATTRIBUTEENUM_Center: - dwExtendedStyle |= FWL_STYLEEXT_EDT_HCenter; - break; - case XFA_ATTRIBUTEENUM_Justify: - dwExtendedStyle |= FWL_STYLEEXT_EDT_Justified; - break; - case XFA_ATTRIBUTEENUM_JustifyAll: - break; - case XFA_ATTRIBUTEENUM_Radix: - break; - case XFA_ATTRIBUTEENUM_Right: - dwExtendedStyle |= FWL_STYLEEXT_EDT_HFar; - break; - default: - dwExtendedStyle |= FWL_STYLEEXT_EDT_HNear; - break; - } - int32_t iVert = para.GetVerticalAlign(); - switch (iVert) { - case XFA_ATTRIBUTEENUM_Middle: - dwExtendedStyle |= FWL_STYLEEXT_EDT_VCenter; - break; - case XFA_ATTRIBUTEENUM_Bottom: - dwExtendedStyle |= FWL_STYLEEXT_EDT_VFar; - break; - default: - dwExtendedStyle |= FWL_STYLEEXT_EDT_VNear; - break; - } - } - return dwExtendedStyle; -} -bool CXFA_FFTextEdit::UpdateFWLData() { - if (!m_pNormalWidget) { - return false; - } - XFA_VALUEPICTURE eType = XFA_VALUEPICTURE_Display; - if (IsFocused()) { - eType = XFA_VALUEPICTURE_Edit; - } - bool bUpdate = false; - if (m_pDataAcc->GetUIType() == XFA_Element::TextEdit && - m_pDataAcc->GetNumberOfCells() < 0) { - XFA_Element elementType = XFA_Element::Unknown; - int32_t iMaxChars = m_pDataAcc->GetMaxChars(elementType); - if (elementType == XFA_Element::ExData) { - iMaxChars = eType == XFA_VALUEPICTURE_Edit ? iMaxChars : 0; - } - if (((CFWL_Edit*)m_pNormalWidget)->GetLimit() != iMaxChars) { - ((CFWL_Edit*)m_pNormalWidget)->SetLimit(iMaxChars); - bUpdate = true; - } - } - if (m_pDataAcc->GetUIType() == XFA_Element::Barcode) { - int32_t nDataLen = 0; - if (eType == XFA_VALUEPICTURE_Edit) - m_pDataAcc->GetBarcodeAttribute_DataLength(nDataLen); - static_cast<CFWL_Edit*>(m_pNormalWidget)->SetLimit(nDataLen); - bUpdate = true; - } - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, eType); - CFX_WideString wsOldText = - static_cast<CFWL_Edit*>(m_pNormalWidget)->GetText(); - if (wsText != wsOldText || (eType == XFA_VALUEPICTURE_Edit && bUpdate)) { - ((CFWL_Edit*)m_pNormalWidget)->SetText(wsText); - bUpdate = true; - } - if (bUpdate) { - m_pNormalWidget->Update(); - } - return true; -} -void CXFA_FFTextEdit::OnTextChanged(CFWL_Widget* pWidget, - const CFX_WideString& wsChanged, - const CFX_WideString& wsPrevText) { - m_dwStatus |= XFA_WidgetStatus_TextEditValueChanged; - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Change; - eParam.m_wsChange = wsChanged; - eParam.m_pTarget = m_pDataAcc; - eParam.m_wsPrevText = wsPrevText; - CFWL_Edit* pEdit = ((CFWL_Edit*)m_pNormalWidget); - if (m_pDataAcc->GetUIType() == XFA_Element::DateTimeEdit) { - CFWL_DateTimePicker* pDateTime = (CFWL_DateTimePicker*)pEdit; - eParam.m_wsNewText = pDateTime->GetEditText(); - int32_t iSels = pDateTime->CountSelRanges(); - if (iSels) { - eParam.m_iSelEnd = pDateTime->GetSelRange(0, &eParam.m_iSelStart); - } - } else { - eParam.m_wsNewText = pEdit->GetText(); - int32_t iSels = pEdit->CountSelRanges(); - if (iSels) { - eParam.m_iSelEnd = pEdit->GetSelRange(0, &eParam.m_iSelStart); - } - } - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); -} -void CXFA_FFTextEdit::OnTextFull(CFWL_Widget* pWidget) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Full; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Full, &eParam); -} - -bool CXFA_FFTextEdit::CheckWord(const CFX_ByteStringC& sWord) { - if (sWord.IsEmpty() || m_pDataAcc->GetUIType() != XFA_Element::TextEdit) - return true; - return false; -} - -void CXFA_FFTextEdit::OnProcessMessage(CFWL_Message* pMessage) { - m_pOldDelegate->OnProcessMessage(pMessage); -} - -void CXFA_FFTextEdit::OnProcessEvent(CFWL_Event* pEvent) { - CXFA_FFField::OnProcessEvent(pEvent); - switch (pEvent->GetType()) { - case CFWL_Event::Type::TextChanged: { - CFWL_EventTextChanged* event = - static_cast<CFWL_EventTextChanged*>(pEvent); - CFX_WideString wsChange; - OnTextChanged(m_pNormalWidget, wsChange, event->wsPrevText); - break; - } - case CFWL_Event::Type::TextFull: { - OnTextFull(m_pNormalWidget); - break; - } - case CFWL_Event::Type::CheckWord: { - CFX_WideString wstr(L"FWL_EVENT_DTP_SelectChanged"); - CFWL_EventCheckWord* event = static_cast<CFWL_EventCheckWord*>(pEvent); - event->bCheckWord = CheckWord(event->bsWord.AsStringC()); - break; - } - default: - break; - } - m_pOldDelegate->OnProcessEvent(pEvent); -} - -void CXFA_FFTextEdit::OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix) { - m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix); -} - -CXFA_FFNumericEdit::CXFA_FFNumericEdit(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFTextEdit(pDataAcc) {} - -CXFA_FFNumericEdit::~CXFA_FFNumericEdit() {} - -bool CXFA_FFNumericEdit::LoadWidget() { - CFWL_Edit* pWidget = new CFWL_Edit( - GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); - m_pNormalWidget = pWidget; - - m_pNormalWidget->SetLayoutItem(this); - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display); - pWidget->SetText(wsText); - UpdateWidgetProperty(); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFNumericEdit::UpdateWidgetProperty() { - CFWL_Edit* pWidget = (CFWL_Edit*)m_pNormalWidget; - if (!pWidget) { - return; - } - uint32_t dwExtendedStyle = - FWL_STYLEEXT_EDT_ShowScrollbarFocus | FWL_STYLEEXT_EDT_OuterScrollbar | - FWL_STYLEEXT_EDT_Validate | FWL_STYLEEXT_EDT_Number | - FWL_STYLEEXT_EDT_LastLineHeight; - dwExtendedStyle |= UpdateUIProperty(); - if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll; - } - int32_t iNumCells = m_pDataAcc->GetNumberOfCells(); - if (iNumCells > 0) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText; - pWidget->SetLimit(iNumCells); - } - dwExtendedStyle |= GetAlignment(); - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly; - } - m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); -} - -void CXFA_FFNumericEdit::OnProcessEvent(CFWL_Event* pEvent) { - if (pEvent->GetType() == CFWL_Event::Type::Validate) { - CFWL_EventValidate* event = static_cast<CFWL_EventValidate*>(pEvent); - event->bValidate = OnValidate(m_pNormalWidget, event->wsInsert); - return; - } - CXFA_FFTextEdit::OnProcessEvent(pEvent); -} - -bool CXFA_FFNumericEdit::OnValidate(CFWL_Widget* pWidget, - CFX_WideString& wsText) { - CFX_WideString wsPattern; - m_pDataAcc->GetPictureContent(wsPattern, XFA_VALUEPICTURE_Edit); - if (!wsPattern.IsEmpty()) { - return true; - } - int32_t iLeads = 0; - m_pDataAcc->GetLeadDigits(iLeads); - int32_t iFracs = 0; - m_pDataAcc->GetFracDigits(iFracs); - CFX_WideString wsFormat; - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(m_pDataAcc); - widgetValue.GetNumbericFormat(wsFormat, iLeads, iFracs); - return widgetValue.ValidateNumericTemp(wsText, wsFormat, - m_pDataAcc->GetLocal()); -} - -CXFA_FFPasswordEdit::CXFA_FFPasswordEdit(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFTextEdit(pDataAcc) {} - -CXFA_FFPasswordEdit::~CXFA_FFPasswordEdit() {} - -bool CXFA_FFPasswordEdit::LoadWidget() { - CFWL_Edit* pWidget = new CFWL_Edit( - GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); - m_pNormalWidget = pWidget; - m_pNormalWidget->SetLayoutItem(this); - - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display); - pWidget->SetText(wsText); - UpdateWidgetProperty(); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFPasswordEdit::UpdateWidgetProperty() { - CFWL_Edit* pWidget = (CFWL_Edit*)m_pNormalWidget; - if (!pWidget) { - return; - } - uint32_t dwExtendedStyle = - FWL_STYLEEXT_EDT_ShowScrollbarFocus | FWL_STYLEEXT_EDT_OuterScrollbar | - FWL_STYLEEXT_EDT_Password | FWL_STYLEEXT_EDT_LastLineHeight; - dwExtendedStyle |= UpdateUIProperty(); - CFX_WideString wsPassWord; - m_pDataAcc->GetPasswordChar(wsPassWord); - if (!wsPassWord.IsEmpty()) { - pWidget->SetAliasChar(wsPassWord.GetAt(0)); - } - if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll; - } - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly; - } - dwExtendedStyle |= GetAlignment(); - m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); -} -CXFA_FFDateTimeEdit::CXFA_FFDateTimeEdit(CXFA_WidgetAcc* pDataAcc) - : CXFA_FFTextEdit(pDataAcc) {} - -CXFA_FFDateTimeEdit::~CXFA_FFDateTimeEdit() {} - -CFX_RectF CXFA_FFDateTimeEdit::GetBBox(uint32_t dwStatus, bool bDrawFocus) { - if (bDrawFocus) - return CFX_RectF(); - return CXFA_FFWidget::GetBBox(dwStatus); -} - -bool CXFA_FFDateTimeEdit::PtInActiveRect(const CFX_PointF& point) { - return m_pNormalWidget && - static_cast<CFWL_DateTimePicker*>(m_pNormalWidget) - ->GetBBox() - .Contains(point); -} - -bool CXFA_FFDateTimeEdit::LoadWidget() { - CFWL_DateTimePicker* pWidget = new CFWL_DateTimePicker(GetFWLApp()); - m_pNormalWidget = pWidget; - m_pNormalWidget->SetLayoutItem(this); - CFWL_NoteDriver* pNoteDriver = - m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); - pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); - - m_pOldDelegate = m_pNormalWidget->GetDelegate(); - m_pNormalWidget->SetDelegate(this); - m_pNormalWidget->LockUpdate(); - - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display); - pWidget->SetEditText(wsText); - if (CXFA_Value value = m_pDataAcc->GetFormValue()) { - switch (value.GetChildValueClassID()) { - case XFA_Element::Date: { - if (!wsText.IsEmpty()) { - CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pDataAcc); - CFX_Unitime date = lcValue.GetDate(); - if ((FX_UNITIME)date != 0) { - pWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); - } - } - } break; - default: - break; - } - } - UpdateWidgetProperty(); - m_pNormalWidget->UnlockUpdate(); - return CXFA_FFField::LoadWidget(); -} -void CXFA_FFDateTimeEdit::UpdateWidgetProperty() { - CFWL_DateTimePicker* pWidget = (CFWL_DateTimePicker*)m_pNormalWidget; - if (!pWidget) { - return; - } - uint32_t dwExtendedStyle = FWL_STYLEEXT_DTP_ShortDateFormat; - dwExtendedStyle |= UpdateUIProperty(); - dwExtendedStyle |= GetAlignment(); - m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); - uint32_t dwEditStyles = FWL_STYLEEXT_EDT_LastLineHeight; - int32_t iNumCells = m_pDataAcc->GetNumberOfCells(); - if (iNumCells > 0) { - dwEditStyles |= FWL_STYLEEXT_EDT_CombText; - pWidget->SetEditLimit(iNumCells); - } - if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open || - !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) { - dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly; - } - if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) { - dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll; - } - pWidget->ModifyEditStylesEx(dwEditStyles, 0xFFFFFFFF); -} -uint32_t CXFA_FFDateTimeEdit::GetAlignment() { - uint32_t dwExtendedStyle = 0; - if (CXFA_Para para = m_pDataAcc->GetPara()) { - int32_t iHorz = para.GetHorizontalAlign(); - switch (iHorz) { - case XFA_ATTRIBUTEENUM_Center: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHCenter; - break; - case XFA_ATTRIBUTEENUM_Justify: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditJustified; - break; - case XFA_ATTRIBUTEENUM_JustifyAll: - break; - case XFA_ATTRIBUTEENUM_Radix: - break; - case XFA_ATTRIBUTEENUM_Right: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHFar; - break; - default: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHNear; - break; - } - int32_t iVert = para.GetVerticalAlign(); - switch (iVert) { - case XFA_ATTRIBUTEENUM_Middle: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVCenter; - break; - case XFA_ATTRIBUTEENUM_Bottom: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVFar; - break; - default: - dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVNear; - break; - } - } - return dwExtendedStyle; -} -bool CXFA_FFDateTimeEdit::CommitData() { - CFX_WideString wsText = - static_cast<CFWL_DateTimePicker*>(m_pNormalWidget)->GetEditText(); - if (m_pDataAcc->SetValue(wsText, XFA_VALUEPICTURE_Edit)) { - m_pDataAcc->UpdateUIDisplay(this); - return true; - } - return false; -} -bool CXFA_FFDateTimeEdit::UpdateFWLData() { - if (!m_pNormalWidget) { - return false; - } - XFA_VALUEPICTURE eType = XFA_VALUEPICTURE_Display; - if (IsFocused()) { - eType = XFA_VALUEPICTURE_Edit; - } - CFX_WideString wsText; - m_pDataAcc->GetValue(wsText, eType); - ((CFWL_DateTimePicker*)m_pNormalWidget)->SetEditText(wsText); - if (IsFocused() && !wsText.IsEmpty()) { - CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pDataAcc); - CFX_Unitime date = lcValue.GetDate(); - if (lcValue.IsValid()) { - if ((FX_UNITIME)date != 0) { - ((CFWL_DateTimePicker*)m_pNormalWidget) - ->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); - } - } - } - m_pNormalWidget->Update(); - return true; -} -bool CXFA_FFDateTimeEdit::IsDataChanged() { - if (m_dwStatus & XFA_WidgetStatus_TextEditValueChanged) { - return true; - } - CFX_WideString wsText = - static_cast<CFWL_DateTimePicker*>(m_pNormalWidget)->GetEditText(); - CFX_WideString wsOldValue; - m_pDataAcc->GetValue(wsOldValue, XFA_VALUEPICTURE_Edit); - return wsOldValue != wsText; -} - -void CXFA_FFDateTimeEdit::OnSelectChanged(CFWL_Widget* pWidget, - int32_t iYear, - int32_t iMonth, - int32_t iDay) { - CFX_WideString wsPicture; - m_pDataAcc->GetPictureContent(wsPicture, XFA_VALUEPICTURE_Edit); - CXFA_LocaleValue date(XFA_VT_DATE, GetDoc()->GetXFADoc()->GetLocalMgr()); - CFX_Unitime dt; - dt.Set(iYear, iMonth, iDay); - date.SetDate(dt); - CFX_WideString wsDate; - date.FormatPatterns(wsDate, wsPicture, m_pDataAcc->GetLocal(), - XFA_VALUEPICTURE_Edit); - CFWL_DateTimePicker* pDateTime = (CFWL_DateTimePicker*)m_pNormalWidget; - pDateTime->SetEditText(wsDate); - pDateTime->Update(); - GetDoc()->GetDocEnvironment()->SetFocusWidget(GetDoc(), nullptr); - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Change; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw); - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); -} - -void CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) { - if (pEvent->GetType() == CFWL_Event::Type::SelectChanged) { - CFWL_EventSelectChanged* event = - static_cast<CFWL_EventSelectChanged*>(pEvent); - OnSelectChanged(m_pNormalWidget, event->iYear, event->iMonth, event->iDay); - return; - } - CXFA_FFTextEdit::OnProcessEvent(pEvent); -} diff --git a/xfa/fxfa/app/xfa_fftextedit.h b/xfa/fxfa/app/xfa_fftextedit.h deleted file mode 100644 index 1e0562a75b329b9788cd7e1f12c7cc78a2cb03a7..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fftextedit.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFTEXTEDIT_H_ -#define XFA_FXFA_APP_XFA_FFTEXTEDIT_H_ - -#include <vector> - -#include "xfa/fxfa/app/xfa_fffield.h" - -class CXFA_FFTextEdit : public CXFA_FFField { - public: - explicit CXFA_FFTextEdit(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFTextEdit() override; - - // CXFA_FFField - bool LoadWidget() override; - void UpdateWidgetProperty() override; - bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; - bool OnSetFocus(CXFA_FFWidget* pOldWidget) override; - bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; - void OnProcessMessage(CFWL_Message* pMessage) override; - void OnProcessEvent(CFWL_Event* pEvent) override; - void OnDrawWidget(CFX_Graphics* pGraphics, - const CFX_Matrix* pMatrix = nullptr) override; - - void OnTextChanged(CFWL_Widget* pWidget, - const CFX_WideString& wsChanged, - const CFX_WideString& wsPrevText); - void OnTextFull(CFWL_Widget* pWidget); - bool CheckWord(const CFX_ByteStringC& sWord); - - protected: - bool CommitData() override; - bool UpdateFWLData() override; - bool IsDataChanged() override; - - uint32_t GetAlignment(); - void ValidateNumberField(const CFX_WideString& wsText); - - IFWL_WidgetDelegate* m_pOldDelegate; -}; - -class CXFA_FFNumericEdit : public CXFA_FFTextEdit { - public: - explicit CXFA_FFNumericEdit(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFNumericEdit() override; - - // CXFA_FFTextEdit - bool LoadWidget() override; - void UpdateWidgetProperty() override; - void OnProcessEvent(CFWL_Event* pEvent) override; - - public: - bool OnValidate(CFWL_Widget* pWidget, CFX_WideString& wsText); -}; - -class CXFA_FFPasswordEdit : public CXFA_FFTextEdit { - public: - explicit CXFA_FFPasswordEdit(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFPasswordEdit() override; - - // CXFA_FFTextEdit - bool LoadWidget() override; - void UpdateWidgetProperty() override; - - protected: -}; - -enum XFA_DATETIMETYPE { - XFA_DATETIMETYPE_Date = 0, - XFA_DATETIMETYPE_Time, - XFA_DATETIMETYPE_DateAndTime -}; - -class CXFA_FFDateTimeEdit : public CXFA_FFTextEdit { - public: - explicit CXFA_FFDateTimeEdit(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFDateTimeEdit() override; - - // CXFA_FFTextEdit - CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false) override; - bool LoadWidget() override; - void UpdateWidgetProperty() override; - void OnProcessEvent(CFWL_Event* pEvent) override; - - void OnSelectChanged(CFWL_Widget* pWidget, - int32_t iYear, - int32_t iMonth, - int32_t iDay); - - protected: - bool PtInActiveRect(const CFX_PointF& point) override; - bool CommitData() override; - bool UpdateFWLData() override; - bool IsDataChanged() override; - - uint32_t GetAlignment(); -}; - -#endif // XFA_FXFA_APP_XFA_FFTEXTEDIT_H_ diff --git a/xfa/fxfa/app/xfa_ffwidget.cpp b/xfa/fxfa/app/xfa_ffwidget.cpp deleted file mode 100644 index 9995fd11b2a8ccf2ff7b8e335065ab6a6ad5c28b..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffwidget.cpp +++ /dev/null @@ -1,2050 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffwidget.h" - -#include <algorithm> -#include <memory> -#include <vector> - -#include "core/fpdfapi/page/cpdf_pageobjectholder.h" -#include "core/fxcodec/codec/ccodec_progressivedecoder.h" -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/cfx_maybe_owned.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "xfa/fwl/fwl_widgethit.h" -#include "xfa/fxfa/app/cxfa_textlayout.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/fxfa_widget.h" -#include "xfa/fxfa/parser/cxfa_corner.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_graphics.h" -#include "xfa/fxgraphics/cfx_path.h" -#include "xfa/fxgraphics/cfx_pattern.h" -#include "xfa/fxgraphics/cfx_shading.h" - -CXFA_FFWidget::CXFA_FFWidget(CXFA_WidgetAcc* pDataAcc) - : CXFA_ContentLayoutItem(pDataAcc->GetNode()), - m_pPageView(nullptr), - m_pDataAcc(pDataAcc) {} - -CXFA_FFWidget::~CXFA_FFWidget() {} - -const CFWL_App* CXFA_FFWidget::GetFWLApp() { - return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp(); -} - -CFX_RectF CXFA_FFWidget::GetWidgetRect() { - if ((m_dwStatus & XFA_WidgetStatus_RectCached) == 0) - RecacheWidgetRect(); - return m_rtWidget; -} - -CFX_RectF CXFA_FFWidget::RecacheWidgetRect() { - m_dwStatus |= XFA_WidgetStatus_RectCached; - m_rtWidget = GetRect(false); - return m_rtWidget; -} - -CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() { - CFX_RectF rtWidget = GetWidgetRect(); - FX_FLOAT fValue = 0; - switch (m_pDataAcc->GetRotate()) { - case 90: - rtWidget.top = rtWidget.bottom(); - fValue = rtWidget.width; - rtWidget.width = rtWidget.height; - rtWidget.height = fValue; - break; - case 180: - rtWidget.left = rtWidget.right(); - rtWidget.top = rtWidget.bottom(); - break; - case 270: - rtWidget.left = rtWidget.right(); - fValue = rtWidget.width; - rtWidget.width = rtWidget.height; - rtWidget.height = fValue; - break; - } - return rtWidget; -} - -uint32_t CXFA_FFWidget::GetStatus() { - return m_dwStatus; -} - -void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) { - m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded; -} - -CFX_RectF CXFA_FFWidget::GetBBox(uint32_t dwStatus, bool bDrawFocus) { - if (bDrawFocus || !m_pPageView) - return CFX_RectF(); - return m_pPageView->GetPageViewRect(); -} - -CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() { - return m_pDataAcc; -} - -bool CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) { - if (CXFA_Assist assist = m_pDataAcc->GetAssist()) { - if (CXFA_ToolTip toolTip = assist.GetToolTip()) { - return toolTip.GetTip(wsToolTip); - } - } - return GetCaptionText(wsToolTip); -} - -void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus) { - if (!IsMatchVisibleStatus(dwStatus)) - return; - - CXFA_Border border = m_pDataAcc->GetBorder(); - if (!border) - return; - - CFX_RectF rtBorder = GetRectWithoutRotate(); - CXFA_Margin margin = border.GetMargin(); - if (margin) - XFA_RectWidthoutMargin(rtBorder, margin); - - rtBorder.Normalize(); - DrawBorder(pGS, border, rtBorder, pMatrix); -} - -bool CXFA_FFWidget::IsLoaded() { - return !!m_pPageView; -} -bool CXFA_FFWidget::LoadWidget() { - PerformLayout(); - return true; -} -void CXFA_FFWidget::UnloadWidget() {} -bool CXFA_FFWidget::PerformLayout() { - RecacheWidgetRect(); - return true; -} -bool CXFA_FFWidget::UpdateFWLData() { - return false; -} -void CXFA_FFWidget::UpdateWidgetProperty() {} -void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS, - CXFA_Box box, - const CFX_RectF& rtBorder, - CFX_Matrix* pMatrix, - uint32_t dwFlags) { - XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags); -} - -void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) { - if (pRect) { - GetDoc()->GetDocEnvironment()->InvalidateRect(m_pPageView, *pRect, - XFA_INVALIDATE_CurrentPage); - return; - } - - CFX_RectF rtWidget = GetBBox(XFA_WidgetStatus_Focused); - rtWidget.Inflate(2, 2); - GetDoc()->GetDocEnvironment()->InvalidateRect(m_pPageView, rtWidget, - XFA_INVALIDATE_CurrentPage); -} - -void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) { - CFX_RectF rtWidget; - if (pRect) { - rtWidget = *pRect; - } else { - rtWidget = GetBBox(XFA_WidgetStatus_Focused); - rtWidget.Inflate(2, 2); - } - m_pDocView->AddInvalidateRect(m_pPageView, rtWidget); -} - -bool CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) { - CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout(); - if (!pCapTextlayout) { - return false; - } - pCapTextlayout->GetText(wsCap); - return true; -} - -bool CXFA_FFWidget::IsFocused() { - return !!(m_dwStatus & XFA_WidgetStatus_Focused); -} - -bool CXFA_FFWidget::OnMouseEnter() { - return false; -} - -bool CXFA_FFWidget::OnMouseExit() { - return false; -} - -bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { - CXFA_FFWidget* pParent = GetParent(); - if (pParent && !pParent->IsAncestorOf(pOldWidget)) { - pParent->OnSetFocus(pOldWidget); - } - m_dwStatus |= XFA_WidgetStatus_Focused; - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Enter; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam); - return true; -} - -bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { - m_dwStatus &= ~XFA_WidgetStatus_Focused; - EventKillFocus(); - if (pNewWidget) { - CXFA_FFWidget* pParent = GetParent(); - if (pParent && !pParent->IsAncestorOf(pNewWidget)) { - pParent->OnKillFocus(pNewWidget); - } - } - return true; -} - -bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { - return false; -} - -bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { - return false; -} - -bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) { - return false; -} - -FWL_WidgetHit CXFA_FFWidget::OnHitTest(const CFX_PointF& point) { - return FWL_WidgetHit::Unknown; -} - -bool CXFA_FFWidget::OnSetCursor(const CFX_PointF& point) { - return false; -} - -bool CXFA_FFWidget::CanUndo() { - return false; -} - -bool CXFA_FFWidget::CanRedo() { - return false; -} - -bool CXFA_FFWidget::Undo() { - return false; -} - -bool CXFA_FFWidget::Redo() { - return false; -} - -bool CXFA_FFWidget::CanCopy() { - return false; -} - -bool CXFA_FFWidget::CanCut() { - return false; -} - -bool CXFA_FFWidget::CanPaste() { - return false; -} - -bool CXFA_FFWidget::CanSelectAll() { - return false; -} - -bool CXFA_FFWidget::CanDelete() { - return CanCut(); -} - -bool CXFA_FFWidget::CanDeSelect() { - return CanCopy(); -} - -bool CXFA_FFWidget::Copy(CFX_WideString& wsCopy) { - return false; -} - -bool CXFA_FFWidget::Cut(CFX_WideString& wsCut) { - return false; -} - -bool CXFA_FFWidget::Paste(const CFX_WideString& wsPaste) { - return false; -} - -void CXFA_FFWidget::SelectAll() {} - -void CXFA_FFWidget::Delete() {} - -void CXFA_FFWidget::DeSelect() {} - -bool CXFA_FFWidget::GetSuggestWords(CFX_PointF pointf, - std::vector<CFX_ByteString>& sSuggest) { - return false; -} -bool CXFA_FFWidget::ReplaceSpellCheckWord(CFX_PointF pointf, - const CFX_ByteStringC& bsReplace) { - return false; -} - -CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) { - CFX_Matrix mt = GetRotateMatrix(); - if (mt.IsIdentity()) - return point; - - CFX_Matrix mtReverse; - mtReverse.SetReverse(mt); - return mtReverse.Transform(point); -} - -static void XFA_GetMatrix(CFX_Matrix& m, - int32_t iRotate, - XFA_ATTRIBUTEENUM at, - const CFX_RectF& rt) { - if (!iRotate) { - return; - } - FX_FLOAT fAnchorX = 0; - FX_FLOAT fAnchorY = 0; - switch (at) { - case XFA_ATTRIBUTEENUM_TopLeft: - fAnchorX = rt.left, fAnchorY = rt.top; - break; - case XFA_ATTRIBUTEENUM_TopCenter: - fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top; - break; - case XFA_ATTRIBUTEENUM_TopRight: - fAnchorX = rt.right(), fAnchorY = rt.top; - break; - case XFA_ATTRIBUTEENUM_MiddleLeft: - fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2; - break; - case XFA_ATTRIBUTEENUM_MiddleCenter: - fAnchorX = (rt.left + rt.right()) / 2, - fAnchorY = (rt.top + rt.bottom()) / 2; - break; - case XFA_ATTRIBUTEENUM_MiddleRight: - fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2; - break; - case XFA_ATTRIBUTEENUM_BottomLeft: - fAnchorX = rt.left, fAnchorY = rt.bottom(); - break; - case XFA_ATTRIBUTEENUM_BottomCenter: - fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom(); - break; - case XFA_ATTRIBUTEENUM_BottomRight: - fAnchorX = rt.right(), fAnchorY = rt.bottom(); - break; - default: - break; - } - switch (iRotate) { - case 90: - m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY, - m.f = fAnchorX + fAnchorY; - break; - case 180: - m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2, - m.f = fAnchorY * 2; - break; - case 270: - m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY, - m.f = fAnchorY - fAnchorX; - break; - } -} - -CFX_Matrix CXFA_FFWidget::GetRotateMatrix() { - CFX_Matrix mt; - int32_t iRotate = m_pDataAcc->GetRotate(); - if (!iRotate) - return mt; - - CFX_RectF rcWidget = GetRectWithoutRotate(); - XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft; - XFA_GetMatrix(mt, iRotate, at, rcWidget); - - return mt; -} - -bool CXFA_FFWidget::IsLayoutRectEmpty() { - CFX_RectF rtLayout = GetRectWithoutRotate(); - return rtLayout.width < 0.1f && rtLayout.height < 0.1f; -} -CXFA_FFWidget* CXFA_FFWidget::GetParent() { - CXFA_Node* pParentNode = - m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent); - if (pParentNode) { - CXFA_WidgetAcc* pParentWidgetAcc = - static_cast<CXFA_WidgetAcc*>(pParentNode->GetWidgetData()); - if (pParentWidgetAcc) { - return pParentWidgetAcc->GetNextWidget(nullptr); - } - } - return nullptr; -} - -bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { - if (!pWidget) - return false; - - CXFA_Node* pNode = m_pDataAcc->GetNode(); - CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode(); - while (pChildNode) { - if (pChildNode == pNode) - return true; - - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent); - } - return false; -} - -bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) { - return GetWidgetRect().Contains(point); -} - -CXFA_FFDocView* CXFA_FFWidget::GetDocView() { - return m_pDocView; -} - -void CXFA_FFWidget::SetDocView(CXFA_FFDocView* pDocView) { - m_pDocView = pDocView; -} - -CXFA_FFDoc* CXFA_FFWidget::GetDoc() { - return m_pDocView->GetDoc(); -} - -CXFA_FFApp* CXFA_FFWidget::GetApp() { - return GetDoc()->GetApp(); -} - -IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { - return GetApp()->GetAppProvider(); -} - -bool CXFA_FFWidget::IsMatchVisibleStatus(uint32_t dwStatus) { - return !!(m_dwStatus & XFA_WidgetStatus_Visible); -} - -void CXFA_FFWidget::EventKillFocus() { - if (m_dwStatus & XFA_WidgetStatus_Access) { - m_dwStatus &= ~XFA_WidgetStatus_Access; - return; - } - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Exit; - eParam.m_pTarget = m_pDataAcc; - m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam); -} -bool CXFA_FFWidget::IsButtonDown() { - return (m_dwStatus & XFA_WidgetStatus_ButtonDown) != 0; -} -void CXFA_FFWidget::SetButtonDown(bool bSet) { - bSet ? m_dwStatus |= XFA_WidgetStatus_ButtonDown - : m_dwStatus &= ~XFA_WidgetStatus_ButtonDown; -} -int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics, - int32_t iStrokeType, - int32_t iCapType) { - switch (iStrokeType) { - case XFA_ATTRIBUTEENUM_DashDot: { - FX_FLOAT dashArray[] = {4, 1, 2, 1}; - if (iCapType != XFA_ATTRIBUTEENUM_Butt) { - dashArray[1] = 2; - dashArray[3] = 2; - } - pGraphics->SetLineDash(0, dashArray, 4); - return FX_DASHSTYLE_DashDot; - } - case XFA_ATTRIBUTEENUM_DashDotDot: { - FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1}; - if (iCapType != XFA_ATTRIBUTEENUM_Butt) { - dashArray[1] = 2; - dashArray[3] = 2; - dashArray[5] = 2; - } - pGraphics->SetLineDash(0, dashArray, 6); - return FX_DASHSTYLE_DashDotDot; - } - case XFA_ATTRIBUTEENUM_Dashed: { - FX_FLOAT dashArray[] = {5, 1}; - if (iCapType != XFA_ATTRIBUTEENUM_Butt) { - dashArray[1] = 2; - } - pGraphics->SetLineDash(0, dashArray, 2); - return FX_DASHSTYLE_Dash; - } - case XFA_ATTRIBUTEENUM_Dotted: { - FX_FLOAT dashArray[] = {2, 1}; - if (iCapType != XFA_ATTRIBUTEENUM_Butt) { - dashArray[1] = 2; - } - pGraphics->SetLineDash(0, dashArray, 2); - return FX_DASHSTYLE_Dot; - } - default: - break; - } - pGraphics->SetLineDash(FX_DASHSTYLE_Solid); - return FX_DASHSTYLE_Solid; -} -CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) { - switch (iLineCap) { - case XFA_ATTRIBUTEENUM_Round: - return CFX_GraphStateData::LineCapRound; - case XFA_ATTRIBUTEENUM_Butt: - return CFX_GraphStateData::LineCapButt; - default: - break; - } - return CFX_GraphStateData::LineCapSquare; -} - -class CXFA_ImageRenderer { - public: - CXFA_ImageRenderer(); - ~CXFA_ImageRenderer(); - - bool Start(CFX_RenderDevice* pDevice, - CFX_DIBSource* pDIBSource, - FX_ARGB bitmap_argb, - int bitmap_alpha, - const CFX_Matrix* pImage2Device, - uint32_t flags, - int blendType = FXDIB_BLEND_NORMAL); - bool Continue(IFX_Pause* pPause); - - protected: - bool StartDIBSource(); - void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, - int left, - int top, - FX_ARGB mask_argb, - int bitmap_alpha, - int blend_mode, - int Transparency); - - CFX_RenderDevice* m_pDevice; - int m_Status; - CFX_Matrix m_ImageMatrix; - CFX_DIBSource* m_pDIBSource; - std::unique_ptr<CFX_DIBitmap> m_pCloneConvert; - int m_BitmapAlpha; - FX_ARGB m_FillArgb; - uint32_t m_Flags; - std::unique_ptr<CFX_ImageTransformer> m_pTransformer; - void* m_DeviceHandle; - int32_t m_BlendType; - bool m_Result; - bool m_bPrint; -}; - -CXFA_ImageRenderer::CXFA_ImageRenderer() - : m_pDevice(nullptr), - m_Status(0), - m_pDIBSource(nullptr), - m_BitmapAlpha(255), - m_FillArgb(0), - m_Flags(0), - m_DeviceHandle(nullptr), - m_BlendType(FXDIB_BLEND_NORMAL), - m_Result(true), - m_bPrint(false) {} - -CXFA_ImageRenderer::~CXFA_ImageRenderer() { - if (m_DeviceHandle) - m_pDevice->CancelDIBits(m_DeviceHandle); -} - -bool CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice, - CFX_DIBSource* pDIBSource, - FX_ARGB bitmap_argb, - int bitmap_alpha, - const CFX_Matrix* pImage2Device, - uint32_t flags, - int blendType) { - m_pDevice = pDevice; - m_pDIBSource = pDIBSource; - m_FillArgb = bitmap_argb; - m_BitmapAlpha = bitmap_alpha; - m_ImageMatrix = *pImage2Device; - m_Flags = flags; - m_BlendType = blendType; - return StartDIBSource(); -} - -bool CXFA_ImageRenderer::StartDIBSource() { - if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, m_BitmapAlpha, m_FillArgb, - &m_ImageMatrix, m_Flags, m_DeviceHandle, - m_BlendType)) { - if (m_DeviceHandle) { - m_Status = 3; - return true; - } - return false; - } - CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); - FX_RECT image_rect = image_rect_f.GetOuterRect(); - int dest_width = image_rect.Width(); - int dest_height = image_rect.Height(); - if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || - (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { - if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return false; - } - CFX_DIBSource* pDib = m_pDIBSource; - if (m_pDIBSource->HasAlpha() && - !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) && - !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { - m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb); - if (!m_pCloneConvert) { - m_Result = false; - return false; - } - pDib = m_pCloneConvert.get(); - } - FX_RECT clip_box = m_pDevice->GetClipBox(); - clip_box.Intersect(image_rect); - m_Status = 2; - m_pTransformer.reset( - new CFX_ImageTransformer(pDib, &m_ImageMatrix, m_Flags, &clip_box)); - m_pTransformer->Start(); - return true; - } - if (m_ImageMatrix.a < 0) { - dest_width = -dest_width; - } - if (m_ImageMatrix.d > 0) { - dest_height = -dest_height; - } - int dest_left, dest_top; - dest_left = dest_width > 0 ? image_rect.left : image_rect.right; - dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; - if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { - if (m_pDevice->StretchDIBitsWithFlagsAndBlend( - m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags, - m_BlendType)) { - return false; - } - } - if (m_pDIBSource->IsAlphaMask()) { - if (m_BitmapAlpha != 255) { - m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); - } - if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top, - dest_width, dest_height, m_FillArgb, - m_Flags)) { - return false; - } - } - if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return true; - } - FX_RECT clip_box = m_pDevice->GetClipBox(); - FX_RECT dest_rect = clip_box; - dest_rect.Intersect(image_rect); - FX_RECT dest_clip( - dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, - dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); - std::unique_ptr<CFX_DIBitmap> pStretched( - m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip)); - if (pStretched) { - CompositeDIBitmap(pStretched.get(), dest_rect.left, dest_rect.top, - m_FillArgb, m_BitmapAlpha, m_BlendType, false); - } - return false; -} - -bool CXFA_ImageRenderer::Continue(IFX_Pause* pPause) { - if (m_Status == 2) { - if (m_pTransformer->Continue(pPause)) - return true; - - std::unique_ptr<CFX_DIBitmap> pBitmap(m_pTransformer->DetachBitmap()); - if (!pBitmap) - return false; - - if (pBitmap->IsAlphaMask()) { - if (m_BitmapAlpha != 255) - m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); - m_Result = - m_pDevice->SetBitMask(pBitmap.get(), m_pTransformer->result().left, - m_pTransformer->result().top, m_FillArgb); - } else { - if (m_BitmapAlpha != 255) - pBitmap->MultiplyAlpha(m_BitmapAlpha); - m_Result = m_pDevice->SetDIBitsWithBlend( - pBitmap.get(), m_pTransformer->result().left, - m_pTransformer->result().top, m_BlendType); - } - return false; - } - if (m_Status == 3) - return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); - - return false; -} - -void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, - int left, - int top, - FX_ARGB mask_argb, - int bitmap_alpha, - int blend_mode, - int Transparency) { - if (!pDIBitmap) { - return; - } - bool bIsolated = !!(Transparency & PDFTRANS_ISOLATED); - bool bGroup = !!(Transparency & PDFTRANS_GROUP); - if (blend_mode == FXDIB_BLEND_NORMAL) { - if (!pDIBitmap->IsAlphaMask()) { - if (bitmap_alpha < 255) { - pDIBitmap->MultiplyAlpha(bitmap_alpha); - } - if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { - return; - } - } else { - uint32_t fill_argb = (mask_argb); - if (bitmap_alpha < 255) { - ((uint8_t*)&fill_argb)[3] = - ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; - } - if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { - return; - } - } - } - bool bBackAlphaRequired = blend_mode && bIsolated; - bool bGetBackGround = - ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || - (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && - (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); - if (bGetBackGround) { - if (bIsolated || !bGroup) { - if (pDIBitmap->IsAlphaMask()) { - return; - } - m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode); - } else { - FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), - top + pDIBitmap->GetHeight()); - rect.Intersect(m_pDevice->GetClipBox()); - CFX_MaybeOwned<CFX_DIBitmap> pClone; - if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { - pClone = m_pDevice->GetBackDrop()->Clone(&rect); - CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap(); - pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pForeBitmap, rect.left, rect.top); - left = left >= 0 ? 0 : left; - top = top >= 0 ? 0 : top; - if (!pDIBitmap->IsAlphaMask()) - pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pDIBitmap, left, top, blend_mode); - else - pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pDIBitmap, mask_argb, left, top, blend_mode); - } else { - pClone = pDIBitmap; - } - if (m_pDevice->GetBackDrop()) { - m_pDevice->SetDIBits(pClone.Get(), rect.left, rect.top); - } else { - if (pDIBitmap->IsAlphaMask()) - return; - m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top, - blend_mode); - } - } - return; - } - if (!pDIBitmap->HasAlpha() || - (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { - return; - } - std::unique_ptr<CFX_DIBitmap> pCloneConvert = - pDIBitmap->CloneConvert(FXDIB_Rgb); - if (!pCloneConvert) - return; - - CXFA_ImageRenderer imageRender; - if (!imageRender.Start(m_pDevice, pCloneConvert.get(), m_FillArgb, - m_BitmapAlpha, &m_ImageMatrix, m_Flags)) { - return; - } - while (imageRender.Continue(nullptr)) - continue; -} - -void XFA_DrawImage(CFX_Graphics* pGS, - const CFX_RectF& rtImage, - CFX_Matrix* pMatrix, - CFX_DIBitmap* pDIBitmap, - int32_t iAspect, - int32_t iImageXDpi, - int32_t iImageYDpi, - int32_t iHorzAlign, - int32_t iVertAlign) { - if (rtImage.IsEmpty()) - return; - if (!pDIBitmap || !pDIBitmap->GetBuffer()) - return; - - CFX_RectF rtFit( - rtImage.TopLeft(), - XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi), - XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi)); - switch (iAspect) { - case XFA_ATTRIBUTEENUM_Fit: { - FX_FLOAT f1 = rtImage.height / rtFit.height; - FX_FLOAT f2 = rtImage.width / rtFit.width; - f1 = std::min(f1, f2); - rtFit.height = rtFit.height * f1; - rtFit.width = rtFit.width * f1; - } break; - case XFA_ATTRIBUTEENUM_Actual: - break; - case XFA_ATTRIBUTEENUM_Height: { - FX_FLOAT f1 = rtImage.height / rtFit.height; - rtFit.height = rtImage.height; - rtFit.width = f1 * rtFit.width; - } break; - case XFA_ATTRIBUTEENUM_None: - rtFit.height = rtImage.height; - rtFit.width = rtImage.width; - break; - case XFA_ATTRIBUTEENUM_Width: { - FX_FLOAT f1 = rtImage.width / rtFit.width; - rtFit.width = rtImage.width; - rtFit.height = rtFit.height * f1; - } break; - } - if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) { - rtFit.left += (rtImage.width - rtFit.width) / 2; - } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) { - rtFit.left = rtImage.right() - rtFit.width; - } - if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) { - rtFit.top += (rtImage.height - rtFit.height) / 2; - } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) { - rtFit.top = rtImage.bottom() - rtImage.height; - } - CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); - pRenderDevice->SaveState(); - - CFX_PathData path; - path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); - pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING); - - CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); - mtImage.Concat( - CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top)); - mtImage.Concat(*pMatrix); - - CXFA_ImageRenderer imageRender; - bool bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, - FXDIB_INTERPOL); - while (bRet) - bRet = imageRender.Continue(nullptr); - - pRenderDevice->RestoreState(false); -} - -static const uint8_t g_inv_base64[128] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, - 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, - 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255, -}; - -static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { - uint8_t* pCP; - int32_t i = 0, j = 0; - if (iLen == 0) { - iLen = FXSYS_strlen((FX_CHAR*)pStr); - } - pCP = FX_Alloc(uint8_t, iLen + 1); - for (; i < iLen; i++) { - if ((pStr[i] & 128) == 0) { - if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { - pCP[j++] = pStr[i]; - } - } - } - pCP[j] = '\0'; - return pCP; -} -static int32_t XFA_Base64Decode(const FX_CHAR* pStr, uint8_t* pOutBuffer) { - if (!pStr) { - return 0; - } - uint8_t* pBuffer = - XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr)); - if (!pBuffer) { - return 0; - } - int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer); - int32_t i = 0, j = 0; - uint32_t dwLimb = 0; - for (; i + 3 < iLen; i += 4) { - if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || - pBuffer[i + 3] == '=') { - if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { - break; - } - if (pBuffer[i + 2] == '=') { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; - j++; - } else { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 2]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; - pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; - j += 2; - } - } else { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) | - ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 3]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; - pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; - pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; - j += 3; - } - } - FX_Free(pBuffer); - return j; -} - -static const FX_CHAR g_base64_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) { - FX_CHAR* out = nullptr; - int i, j; - uint32_t limb; - out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5); - for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) { - limb = ((uint32_t)buf[i] << 16) | ((uint32_t)buf[i + 1] << 8) | - ((uint32_t)buf[i + 2]); - out[j] = g_base64_chars[(limb >> 18) & 63]; - out[j + 1] = g_base64_chars[(limb >> 12) & 63]; - out[j + 2] = g_base64_chars[(limb >> 6) & 63]; - out[j + 3] = g_base64_chars[(limb)&63]; - } - switch (buf_len - i) { - case 0: - break; - case 1: - limb = ((uint32_t)buf[i]); - out[j++] = g_base64_chars[(limb >> 2) & 63]; - out[j++] = g_base64_chars[(limb << 4) & 63]; - out[j++] = '='; - out[j++] = '='; - break; - case 2: - limb = ((uint32_t)buf[i] << 8) | ((uint32_t)buf[i + 1]); - out[j++] = g_base64_chars[(limb >> 10) & 63]; - out[j++] = g_base64_chars[(limb >> 4) & 63]; - out[j++] = g_base64_chars[(limb << 2) & 63]; - out[j++] = '='; - break; - default: - break; - } - out[j] = '\0'; - return out; -} -FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideString& wsType) { - CFX_WideString wsContentType(wsType); - wsContentType.MakeLower(); - if (wsContentType == L"image/jpg") - return FXCODEC_IMAGE_JPG; - if (wsContentType == L"image/png") - return FXCODEC_IMAGE_PNG; - if (wsContentType == L"image/gif") - return FXCODEC_IMAGE_GIF; - if (wsContentType == L"image/bmp") - return FXCODEC_IMAGE_BMP; - if (wsContentType == L"image/tif") - return FXCODEC_IMAGE_TIF; - return FXCODEC_IMAGE_UNKNOWN; -} -CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc, - CXFA_Image* pImage, - bool& bNameImage, - int32_t& iImageXDpi, - int32_t& iImageYDpi) { - CFX_WideString wsHref; - pImage->GetHref(wsHref); - CFX_WideString wsImage; - pImage->GetContent(wsImage); - if (wsHref.IsEmpty() && wsImage.IsEmpty()) { - return nullptr; - } - CFX_WideString wsContentType; - pImage->GetContentType(wsContentType); - FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType); - CFX_ByteString bsContent; - uint8_t* pImageBuffer = nullptr; - CFX_RetainPtr<IFX_SeekableReadStream> pImageFileRead; - if (wsImage.GetLength() > 0) { - XFA_ATTRIBUTEENUM iEncoding = - (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding(); - if (iEncoding == XFA_ATTRIBUTEENUM_Base64) { - CFX_ByteString bsData = wsImage.UTF8Encode(); - int32_t iLength = bsData.GetLength(); - pImageBuffer = FX_Alloc(uint8_t, iLength); - int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer); - if (iRead > 0) { - pImageFileRead = IFX_MemoryStream::Create(pImageBuffer, iRead); - } - } else { - bsContent = CFX_ByteString::FromUnicode(wsImage); - pImageFileRead = IFX_MemoryStream::Create( - const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength()); - } - } else { - CFX_WideString wsURL = wsHref; - if (wsURL.Left(7) != L"http://" && wsURL.Left(6) != L"ftp://") { - CFX_DIBitmap* pBitmap = - pDoc->GetPDFNamedImage(wsURL.AsStringC(), iImageXDpi, iImageYDpi); - if (pBitmap) { - bNameImage = true; - return pBitmap; - } - } - pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL); - } - if (!pImageFileRead) { - FX_Free(pImageBuffer); - return nullptr; - } - bNameImage = false; - CFX_DIBitmap* pBitmap = - XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); - FX_Free(pImageBuffer); - return pBitmap; -} -static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, - int32_t iComponents, - int32_t iBitsPerComponent) { - FXDIB_Format dibFormat = FXDIB_Argb; - switch (type) { - case FXCODEC_IMAGE_BMP: - case FXCODEC_IMAGE_JPG: - case FXCODEC_IMAGE_TIF: { - dibFormat = FXDIB_Rgb32; - int32_t bpp = iComponents * iBitsPerComponent; - if (bpp <= 24) { - dibFormat = FXDIB_Rgb; - } - } break; - case FXCODEC_IMAGE_PNG: - default: - break; - } - return dibFormat; -} - -CFX_DIBitmap* XFA_LoadImageFromBuffer( - const CFX_RetainPtr<IFX_SeekableReadStream>& pImageFileRead, - FXCODEC_IMAGE_TYPE type, - int32_t& iImageXDpi, - int32_t& iImageYDpi) { - CFX_GEModule* pGeModule = CFX_GEModule::Get(); - if (!pGeModule) - return nullptr; - - CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule(); - if (!pCodecMgr) - return nullptr; - - CFX_DIBAttribute dibAttr; - CFX_DIBitmap* pBitmap = nullptr; - std::unique_ptr<CCodec_ProgressiveDecoder> pProgressiveDecoder = - pCodecMgr->CreateProgressiveDecoder(); - pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false); - switch (dibAttr.m_wDPIUnit) { - case FXCODEC_RESUNIT_CENTIMETER: - dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); - dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); - break; - case FXCODEC_RESUNIT_METER: - dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (FX_FLOAT)100 * 2.54f); - dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_FLOAT)100 * 2.54f); - break; - default: - break; - } - iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); - iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); - if (pProgressiveDecoder->GetWidth() > 0 && - pProgressiveDecoder->GetHeight() > 0) { - type = pProgressiveDecoder->GetType(); - int32_t iComponents = pProgressiveDecoder->GetNumComponents(); - int32_t iBpc = pProgressiveDecoder->GetBPC(); - FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); - pBitmap = new CFX_DIBitmap(); - pBitmap->Create(pProgressiveDecoder->GetWidth(), - pProgressiveDecoder->GetHeight(), dibFormat); - pBitmap->Clear(0xffffffff); - int32_t nFrames; - if ((pProgressiveDecoder->GetFrames(nFrames) == - FXCODEC_STATUS_DECODE_READY) && - (nFrames > 0)) { - pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), - pBitmap->GetHeight()); - pProgressiveDecoder->ContinueDecode(); - } - } - return pBitmap; -} - -void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, bool bUI) { - if (!mg) { - return; - } - FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; - mg.GetLeftInset(fLeftInset); - mg.GetTopInset(fTopInset); - mg.GetRightInset(fRightInset); - mg.GetBottomInset(fBottomInset); - rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); -} -CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { - if (XFA_IsCreateWidget(pLayoutItem->GetFormNode()->GetElementType())) - return static_cast<CXFA_FFWidget*>(pLayoutItem); - return nullptr; -} -bool XFA_IsCreateWidget(XFA_Element eType) { - return eType == XFA_Element::Field || eType == XFA_Element::Draw || - eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup; -} -static void XFA_BOX_GetPath_Arc(CXFA_Box box, - CFX_RectF rtDraw, - CFX_Path& fillPath, - uint32_t dwFlags) { - FX_FLOAT a, b; - a = rtDraw.width / 2.0f; - b = rtDraw.height / 2.0f; - if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { - a = b = std::min(a, b); - } - CFX_PointF center = rtDraw.Center(); - rtDraw.left = center.x - a; - rtDraw.top = center.y - b; - rtDraw.width = a + a; - rtDraw.height = b + b; - FX_FLOAT startAngle = 0, sweepAngle = 360; - bool bStart = box.GetStartAngle(startAngle); - bool bEnd = box.GetSweepAngle(sweepAngle); - if (!bStart && !bEnd) { - fillPath.AddEllipse(rtDraw); - return; - } - startAngle = -startAngle * FX_PI / 180.0f; - sweepAngle = -sweepAngle * FX_PI / 180.0f; - fillPath.AddArc(rtDraw.TopLeft(), rtDraw.Size(), startAngle, sweepAngle); -} - -static void XFA_BOX_GetPath(CXFA_Box box, - const std::vector<CXFA_Stroke>& strokes, - CFX_RectF rtWidget, - CFX_Path& path, - int32_t nIndex, - bool bStart, - bool bCorner) { - ASSERT(nIndex >= 0 && nIndex < 8); - int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex; - CXFA_Corner corner1(strokes[n].GetNode()); - CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode()); - FX_FLOAT fRadius1 = bCorner ? corner1.GetRadius() : 0.0f; - FX_FLOAT fRadius2 = bCorner ? corner2.GetRadius() : 0.0f; - bool bInverted = corner1.IsInverted(); - FX_FLOAT offsetY = 0.0f; - FX_FLOAT offsetX = 0.0f; - bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; - FX_FLOAT halfAfter = 0.0f; - FX_FLOAT halfBefore = 0.0f; - CXFA_Stroke stroke = strokes[nIndex]; - if (stroke.IsCorner()) { - CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8]; - CXFA_Stroke edgeAfter = strokes[nIndex + 1]; - if (stroke.IsInverted()) { - if (!stroke.SameStyles(edgeBefore)) { - halfBefore = edgeBefore.GetThickness() / 2; - } - if (!stroke.SameStyles(edgeAfter)) { - halfAfter = edgeAfter.GetThickness() / 2; - } - } - } else { - CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8]; - CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8]; - if (!bRound && !bInverted) { - halfBefore = edgeBefore.GetThickness() / 2; - halfAfter = edgeAfter.GetThickness() / 2; - } - } - FX_FLOAT offsetEX = 0.0f; - FX_FLOAT offsetEY = 0.0f; - FX_FLOAT sx = 0.0f; - FX_FLOAT sy = 0.0f; - FX_FLOAT vx = 1.0f; - FX_FLOAT vy = 1.0f; - FX_FLOAT nx = 1.0f; - FX_FLOAT ny = 1.0f; - CFX_PointF cpStart; - CFX_PointF cp1; - CFX_PointF cp2; - if (bRound) { - sy = FX_PI / 2; - } - switch (nIndex) { - case 0: - case 1: - cp1 = rtWidget.TopLeft(); - cp2 = rtWidget.TopRight(); - if (nIndex == 0) { - cpStart.x = cp1.x - halfBefore; - cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter; - } else { - cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y, - offsetEX = halfAfter; - } - vx = 1, vy = 1; - nx = -1, ny = 0; - if (bRound) { - sx = bInverted ? FX_PI / 2 : FX_PI; - } else { - sx = 1, sy = 0; - } - break; - case 2: - case 3: - cp1 = rtWidget.TopRight(); - cp2 = rtWidget.BottomRight(); - if (nIndex == 2) { - cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore, - offsetX = halfAfter; - } else { - cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore, - offsetEY = halfAfter; - } - vx = -1, vy = 1; - nx = 0, ny = -1; - if (bRound) { - sx = bInverted ? FX_PI : FX_PI * 3 / 2; - } else { - sx = 0, sy = 1; - } - break; - case 4: - case 5: - cp1 = rtWidget.BottomRight(); - cp2 = rtWidget.BottomLeft(); - if (nIndex == 4) { - cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1, - offsetY = halfAfter; - } else { - cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y, - offsetEX = -halfAfter; - } - vx = -1, vy = -1; - nx = 1, ny = 0; - if (bRound) { - sx = bInverted ? FX_PI * 3 / 2 : 0; - } else { - sx = -1, sy = 0; - } - break; - case 6: - case 7: - cp1 = rtWidget.BottomLeft(); - cp2 = rtWidget.TopLeft(); - if (nIndex == 6) { - cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore, - offsetX = -halfAfter; - } else { - cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore, - offsetEY = -halfAfter; - } - vx = 1; - vy = -1; - nx = 0; - ny = 1; - if (bRound) { - sx = bInverted ? 0 : FX_PI / 2; - } else { - sx = 0; - sy = -1; - } - break; - } - if (bStart) { - path.MoveTo(cpStart); - } - if (nIndex & 1) { - path.LineTo(CFX_PointF(cp2.x + fRadius2 * nx + offsetEX, - cp2.y + fRadius2 * ny + offsetEY)); - return; - } - if (bRound) { - if (fRadius1 < 0) - sx -= FX_PI; - if (bInverted) - sy *= -1; - - CFX_RectF rtRadius(cp1.x + offsetX * 2, cp1.y + offsetY * 2, - fRadius1 * 2 * vx - offsetX * 2, - fRadius1 * 2 * vy - offsetY * 2); - rtRadius.Normalize(); - if (bInverted) - rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); - - path.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy); - } else { - CFX_PointF cp; - if (bInverted) { - cp.x = cp1.x + fRadius1 * vx; - cp.y = cp1.y + fRadius1 * vy; - } else { - cp = cp1; - } - path.LineTo(cp); - path.LineTo(CFX_PointF(cp1.x + fRadius1 * sx + offsetX, - cp1.y + fRadius1 * sy + offsetY)); - } -} -static void XFA_BOX_GetFillPath(CXFA_Box box, - const std::vector<CXFA_Stroke>& strokes, - CFX_RectF rtWidget, - CFX_Path& fillPath, - uint16_t dwFlags) { - if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { - CXFA_Edge edge = box.GetEdge(0); - FX_FLOAT fThickness = edge.GetThickness(); - if (fThickness < 0) { - fThickness = 0; - } - FX_FLOAT fHalf = fThickness / 2; - int32_t iHand = box.GetHand(); - if (iHand == XFA_ATTRIBUTEENUM_Left) { - rtWidget.Inflate(fHalf, fHalf); - } else if (iHand == XFA_ATTRIBUTEENUM_Right) { - rtWidget.Deflate(fHalf, fHalf); - } - XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags); - return; - } - bool bSameStyles = true; - CXFA_Stroke stroke1 = strokes[0]; - for (int32_t i = 1; i < 8; i++) { - CXFA_Stroke stroke2 = strokes[i]; - if (!stroke1.SameStyles(stroke2)) { - bSameStyles = false; - break; - } - stroke1 = stroke2; - } - if (bSameStyles) { - stroke1 = strokes[0]; - for (int32_t i = 2; i < 8; i += 2) { - CXFA_Stroke stroke2 = strokes[i]; - if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | - XFA_STROKE_SAMESTYLE_Corner)) { - bSameStyles = false; - break; - } - stroke1 = stroke2; - } - if (bSameStyles) { - stroke1 = strokes[0]; - if (stroke1.IsInverted()) { - bSameStyles = false; - } - if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { - bSameStyles = false; - } - } - } - if (bSameStyles) { - fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width, - rtWidget.height); - return; - } - - for (int32_t i = 0; i < 8; i += 2) { - FX_FLOAT sx = 0.0f; - FX_FLOAT sy = 0.0f; - FX_FLOAT vx = 1.0f; - FX_FLOAT vy = 1.0f; - FX_FLOAT nx = 1.0f; - FX_FLOAT ny = 1.0f; - CFX_PointF cp1, cp2; - CXFA_Corner corner1(strokes[i].GetNode()); - CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode()); - FX_FLOAT fRadius1 = corner1.GetRadius(); - FX_FLOAT fRadius2 = corner2.GetRadius(); - bool bInverted = corner1.IsInverted(); - bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; - if (bRound) { - sy = FX_PI / 2; - } - switch (i) { - case 0: - cp1 = rtWidget.TopLeft(); - cp2 = rtWidget.TopRight(); - vx = 1, vy = 1; - nx = -1, ny = 0; - if (bRound) { - sx = bInverted ? FX_PI / 2 : FX_PI; - } else { - sx = 1, sy = 0; - } - break; - case 2: - cp1 = rtWidget.TopRight(); - cp2 = rtWidget.BottomRight(); - vx = -1, vy = 1; - nx = 0, ny = -1; - if (bRound) { - sx = bInverted ? FX_PI : FX_PI * 3 / 2; - } else { - sx = 0, sy = 1; - } - break; - case 4: - cp1 = rtWidget.BottomRight(); - cp2 = rtWidget.BottomLeft(); - vx = -1, vy = -1; - nx = 1, ny = 0; - if (bRound) { - sx = bInverted ? FX_PI * 3 / 2 : 0; - } else { - sx = -1, sy = 0; - } - break; - case 6: - cp1 = rtWidget.BottomLeft(); - cp2 = rtWidget.TopLeft(); - vx = 1, vy = -1; - nx = 0, ny = 1; - if (bRound) { - sx = bInverted ? 0 : FX_PI / 2; - } else { - sx = 0; - sy = -1; - } - break; - } - if (i == 0) - fillPath.MoveTo(CFX_PointF(cp1.x, cp1.y + fRadius1)); - - if (bRound) { - if (fRadius1 < 0) - sx -= FX_PI; - if (bInverted) - sy *= -1; - - CFX_RectF rtRadius(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy); - rtRadius.Normalize(); - if (bInverted) - rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); - - fillPath.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy); - } else { - CFX_PointF cp; - if (bInverted) { - cp.x = cp1.x + fRadius1 * vx; - cp.y = cp1.y + fRadius1 * vy; - } else { - cp = cp1; - } - fillPath.LineTo(cp); - fillPath.LineTo(CFX_PointF(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy)); - } - fillPath.LineTo(CFX_PointF(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny)); - } -} -static void XFA_BOX_Fill_Radial(CXFA_Box box, - CFX_Graphics* pGS, - CFX_Path& fillPath, - CFX_RectF rtFill, - CFX_Matrix* pMatrix) { - CXFA_Fill fill = box.GetFill(); - FX_ARGB crStart, crEnd; - crStart = fill.GetColor(); - int32_t iType = fill.GetRadial(crEnd); - if (iType != XFA_ATTRIBUTEENUM_ToEdge) { - FX_ARGB temp = crEnd; - crEnd = crStart; - crStart = temp; - } - CFX_Shading shading(rtFill.Center(), rtFill.Center(), 0, - FXSYS_sqrt(rtFill.Width() * rtFill.Width() + - rtFill.Height() * rtFill.Height()) / - 2, - true, true, crStart, crEnd); - CFX_Color cr(&shading); - pGS->SetFillColor(&cr); - pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); -} -static void XFA_BOX_Fill_Pattern(CXFA_Box box, - CFX_Graphics* pGS, - CFX_Path& fillPath, - CFX_RectF rtFill, - CFX_Matrix* pMatrix) { - CXFA_Fill fill = box.GetFill(); - FX_ARGB crStart, crEnd; - crStart = fill.GetColor(); - int32_t iType = fill.GetPattern(crEnd); - FX_HatchStyle iHatch = FX_HatchStyle::Cross; - switch (iType) { - case XFA_ATTRIBUTEENUM_CrossDiagonal: - iHatch = FX_HatchStyle::DiagonalCross; - break; - case XFA_ATTRIBUTEENUM_DiagonalLeft: - iHatch = FX_HatchStyle::ForwardDiagonal; - break; - case XFA_ATTRIBUTEENUM_DiagonalRight: - iHatch = FX_HatchStyle::BackwardDiagonal; - break; - case XFA_ATTRIBUTEENUM_Horizontal: - iHatch = FX_HatchStyle::Horizontal; - break; - case XFA_ATTRIBUTEENUM_Vertical: - iHatch = FX_HatchStyle::Vertical; - break; - default: - break; - } - - CFX_Pattern pattern(iHatch, crEnd, crStart); - CFX_Color cr(&pattern, 0x0); - pGS->SetFillColor(&cr); - pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); -} -static void XFA_BOX_Fill_Linear(CXFA_Box box, - CFX_Graphics* pGS, - CFX_Path& fillPath, - CFX_RectF rtFill, - CFX_Matrix* pMatrix) { - CXFA_Fill fill = box.GetFill(); - FX_ARGB crStart = fill.GetColor(); - FX_ARGB crEnd; - int32_t iType = fill.GetLinear(crEnd); - CFX_PointF ptStart; - CFX_PointF ptEnd; - switch (iType) { - case XFA_ATTRIBUTEENUM_ToRight: - ptStart = CFX_PointF(rtFill.left, rtFill.top); - ptEnd = CFX_PointF(rtFill.right(), rtFill.top); - break; - case XFA_ATTRIBUTEENUM_ToBottom: - ptStart = CFX_PointF(rtFill.left, rtFill.top); - ptEnd = CFX_PointF(rtFill.left, rtFill.bottom()); - break; - case XFA_ATTRIBUTEENUM_ToLeft: - ptStart = CFX_PointF(rtFill.right(), rtFill.top); - ptEnd = CFX_PointF(rtFill.left, rtFill.top); - break; - case XFA_ATTRIBUTEENUM_ToTop: - ptStart = CFX_PointF(rtFill.left, rtFill.bottom()); - ptEnd = CFX_PointF(rtFill.left, rtFill.top); - break; - default: - break; - } - CFX_Shading shading(ptStart, ptEnd, false, false, crStart, crEnd); - CFX_Color cr(&shading); - pGS->SetFillColor(&cr); - pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); -} -static void XFA_BOX_Fill(CXFA_Box box, - const std::vector<CXFA_Stroke>& strokes, - CFX_Graphics* pGS, - const CFX_RectF& rtWidget, - CFX_Matrix* pMatrix, - uint32_t dwFlags) { - CXFA_Fill fill = box.GetFill(); - if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) - return; - - pGS->SaveGraphState(); - CFX_Path fillPath; - XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath, - (dwFlags & XFA_DRAWBOX_ForceRound) != 0); - fillPath.Close(); - XFA_Element eType = fill.GetFillType(); - switch (eType) { - case XFA_Element::Radial: - XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix); - break; - case XFA_Element::Pattern: - XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix); - break; - case XFA_Element::Linear: - XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix); - break; - default: { - FX_ARGB cr; - if (eType == XFA_Element::Stipple) { - int32_t iRate = fill.GetStipple(cr); - if (iRate == 0) { - iRate = 100; - } - int32_t a = 0; - FX_COLORREF rgb; - ArgbDecode(cr, a, rgb); - cr = ArgbEncode(iRate * a / 100, rgb); - } else { - cr = fill.GetColor(); - } - CFX_Color fillColor(cr); - pGS->SetFillColor(&fillColor); - pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); - } break; - } - pGS->RestoreGraphState(); -} -static void XFA_BOX_StrokePath(CXFA_Stroke stroke, - CFX_Path* pPath, - CFX_Graphics* pGS, - CFX_Matrix* pMatrix) { - if (!stroke || !stroke.IsVisible()) { - return; - } - FX_FLOAT fThickness = stroke.GetThickness(); - if (fThickness < 0.001f) { - return; - } - pGS->SaveGraphState(); - if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) { - fThickness = 2 * stroke.GetRadius(); - } - pGS->SetLineWidth(fThickness, true); - pGS->SetLineCap(CFX_GraphStateData::LineCapButt); - XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(), - XFA_ATTRIBUTEENUM_Butt); - CFX_Color fxColor(stroke.GetColor()); - pGS->SetStrokeColor(&fxColor); - pGS->StrokePath(pPath, pMatrix); - pGS->RestoreGraphState(); -} -static void XFA_BOX_StrokeArc(CXFA_Box box, - CFX_Graphics* pGS, - CFX_RectF rtWidget, - CFX_Matrix* pMatrix, - uint32_t dwFlags) { - CXFA_Edge edge = box.GetEdge(0); - if (!edge || !edge.IsVisible()) { - return; - } - bool bVisible = false; - FX_FLOAT fThickness = 0; - int32_t i3DType = box.Get3DStyle(bVisible, fThickness); - if (i3DType) { - if (bVisible && fThickness >= 0.001f) { - dwFlags |= XFA_DRAWBOX_Lowered3D; - } - } - FX_FLOAT fHalf = edge.GetThickness() / 2; - if (fHalf < 0) { - fHalf = 0; - } - int32_t iHand = box.GetHand(); - if (iHand == XFA_ATTRIBUTEENUM_Left) { - rtWidget.Inflate(fHalf, fHalf); - } else if (iHand == XFA_ATTRIBUTEENUM_Right) { - rtWidget.Deflate(fHalf, fHalf); - } - if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 || - (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) { - if (fHalf < 0.001f) - return; - - CFX_Path arcPath; - XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags); - XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix); - return; - } - pGS->SaveGraphState(); - pGS->SetLineWidth(fHalf); - - FX_FLOAT a, b; - a = rtWidget.width / 2.0f; - b = rtWidget.height / 2.0f; - if (dwFlags & XFA_DRAWBOX_ForceRound) { - a = std::min(a, b); - b = a; - } - - CFX_PointF center = rtWidget.Center(); - rtWidget.left = center.x - a; - rtWidget.top = center.y - b; - rtWidget.width = a + a; - rtWidget.height = b + b; - - FX_FLOAT startAngle = 0, sweepAngle = 360; - startAngle = startAngle * FX_PI / 180.0f; - sweepAngle = -sweepAngle * FX_PI / 180.0f; - - CFX_Path arcPath; - arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f, - FX_PI); - - CFX_Color cr(0xFF808080); - pGS->SetStrokeColor(&cr); - pGS->StrokePath(&arcPath, pMatrix); - arcPath.Clear(); - arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f, - FX_PI); - - cr.Set(0xFFFFFFFF); - pGS->SetStrokeColor(&cr); - pGS->StrokePath(&arcPath, pMatrix); - rtWidget.Deflate(fHalf, fHalf); - arcPath.Clear(); - arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f, - FX_PI); - - cr.Set(0xFF404040); - pGS->SetStrokeColor(&cr); - pGS->StrokePath(&arcPath, pMatrix); - arcPath.Clear(); - arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f, - FX_PI); - - cr.Set(0xFFC0C0C0); - pGS->SetStrokeColor(&cr); - pGS->StrokePath(&arcPath, pMatrix); - pGS->RestoreGraphState(); -} -static void XFA_Draw3DRect(CFX_Graphics* pGraphic, - const CFX_RectF& rt, - FX_FLOAT fLineWidth, - CFX_Matrix* pMatrix, - FX_ARGB argbTopLeft, - FX_ARGB argbBottomRight) { - CFX_Color crLT(argbTopLeft); - pGraphic->SetFillColor(&crLT); - FX_FLOAT fBottom = rt.bottom(); - FX_FLOAT fRight = rt.right(); - CFX_Path pathLT; - pathLT.MoveTo(CFX_PointF(rt.left, fBottom)); - pathLT.LineTo(CFX_PointF(rt.left, rt.top)); - pathLT.LineTo(CFX_PointF(fRight, rt.top)); - pathLT.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth)); - pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, rt.top + fLineWidth)); - pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth)); - pathLT.LineTo(CFX_PointF(rt.left, fBottom)); - pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix); - - CFX_Color crRB(argbBottomRight); - pGraphic->SetFillColor(&crRB); - - CFX_Path pathRB; - pathRB.MoveTo(CFX_PointF(fRight, rt.top)); - pathRB.LineTo(CFX_PointF(fRight, fBottom)); - pathRB.LineTo(CFX_PointF(rt.left, fBottom)); - pathRB.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth)); - pathRB.LineTo(CFX_PointF(fRight - fLineWidth, fBottom - fLineWidth)); - pathRB.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth)); - pathRB.LineTo(CFX_PointF(fRight, rt.top)); - pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix); -} -static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS, - CFX_RectF rt, - FX_FLOAT fThickness, - CFX_Matrix* pMatrix) { - FX_FLOAT fHalfWidth = fThickness / 2.0f; - CFX_RectF rtInner(rt); - rtInner.Deflate(fHalfWidth, fHalfWidth); - CFX_Color cr(0xFF000000); - pGS->SetFillColor(&cr); - CFX_Path path; - path.AddRectangle(rt.left, rt.top, rt.width, rt.height); - path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); - pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); - XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0); -} -static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS, - CFX_RectF rt, - FX_FLOAT fThickness, - CFX_Matrix* pMatrix) { - FX_FLOAT fHalfWidth = fThickness / 2.0f; - CFX_RectF rtInner(rt); - rtInner.Deflate(fHalfWidth, fHalfWidth); - CFX_Color cr(0xFF000000); - pGS->SetFillColor(&cr); - CFX_Path path; - path.AddRectangle(rt.left, rt.top, rt.width, rt.height); - path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); - pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); - XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); -} -static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS, - CFX_RectF rt, - FX_FLOAT fThickness, - CFX_Matrix* pMatrix) { - FX_FLOAT fHalfWidth = fThickness / 2.0f; - XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF); - CFX_RectF rtInner(rt); - rtInner.Deflate(fHalfWidth, fHalfWidth); - XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); -} -static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS, - CFX_RectF rt, - FX_FLOAT fThickness, - CFX_Matrix* pMatrix) { - FX_FLOAT fHalfWidth = fThickness / 2.0f; - XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000); - CFX_RectF rtInner(rt); - rtInner.Deflate(fHalfWidth, fHalfWidth); - XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080); -} -static void XFA_BOX_Stroke_Rect(CXFA_Box box, - const std::vector<CXFA_Stroke>& strokes, - CFX_Graphics* pGS, - CFX_RectF rtWidget, - CFX_Matrix* pMatrix) { - bool bVisible = false; - FX_FLOAT fThickness = 0; - int32_t i3DType = box.Get3DStyle(bVisible, fThickness); - if (i3DType) { - if (!bVisible || fThickness < 0.001f) { - return; - } - switch (i3DType) { - case XFA_ATTRIBUTEENUM_Lowered: - XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix); - break; - case XFA_ATTRIBUTEENUM_Raised: - XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix); - break; - case XFA_ATTRIBUTEENUM_Etched: - XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix); - break; - case XFA_ATTRIBUTEENUM_Embossed: - XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix); - break; - } - return; - } - bool bClose = false; - bool bSameStyles = true; - CXFA_Stroke stroke1 = strokes[0]; - for (int32_t i = 1; i < 8; i++) { - CXFA_Stroke stroke2 = strokes[i]; - if (!stroke1.SameStyles(stroke2)) { - bSameStyles = false; - break; - } - stroke1 = stroke2; - } - if (bSameStyles) { - stroke1 = strokes[0]; - bClose = true; - for (int32_t i = 2; i < 8; i += 2) { - CXFA_Stroke stroke2 = strokes[i]; - if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | - XFA_STROKE_SAMESTYLE_Corner)) { - bSameStyles = false; - break; - } - stroke1 = stroke2; - } - if (bSameStyles) { - stroke1 = strokes[0]; - if (stroke1.IsInverted()) - bSameStyles = false; - if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) - bSameStyles = false; - } - } - bool bStart = true; - CFX_Path path; - for (int32_t i = 0; i < 8; i++) { - CXFA_Stroke stroke = strokes[i]; - if ((i % 1) == 0 && stroke.GetRadius() < 0) { - bool bEmpty = path.IsEmpty(); - if (!bEmpty) { - XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix); - path.Clear(); - } - bStart = true; - continue; - } - XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles); - CXFA_Stroke stroke2 = strokes[(i + 1) % 8]; - bStart = !stroke.SameStyles(stroke2); - if (bStart) { - XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix); - path.Clear(); - } - } - bool bEmpty = path.IsEmpty(); - if (!bEmpty) { - if (bClose) { - path.Close(); - } - XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix); - } -} -static void XFA_BOX_Stroke(CXFA_Box box, - const std::vector<CXFA_Stroke>& strokes, - CFX_Graphics* pGS, - CFX_RectF rtWidget, - CFX_Matrix* pMatrix, - uint32_t dwFlags) { - if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { - XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags); - return; - } - bool bVisible = false; - for (int32_t j = 0; j < 4; j++) { - if (strokes[j * 2 + 1].IsVisible()) { - bVisible = true; - break; - } - } - if (!bVisible) { - return; - } - for (int32_t i = 1; i < 8; i += 2) { - CXFA_Edge edge(strokes[i].GetNode()); - FX_FLOAT fThickness = edge.GetThickness(); - if (fThickness < 0) { - fThickness = 0; - } - FX_FLOAT fHalf = fThickness / 2; - int32_t iHand = box.GetHand(); - switch (i) { - case 1: - if (iHand == XFA_ATTRIBUTEENUM_Left) { - rtWidget.top -= fHalf; - rtWidget.height += fHalf; - } else if (iHand == XFA_ATTRIBUTEENUM_Right) { - rtWidget.top += fHalf; - rtWidget.height -= fHalf; - } - break; - case 3: - if (iHand == XFA_ATTRIBUTEENUM_Left) { - rtWidget.width += fHalf; - } else if (iHand == XFA_ATTRIBUTEENUM_Right) { - rtWidget.width -= fHalf; - } - break; - case 5: - if (iHand == XFA_ATTRIBUTEENUM_Left) { - rtWidget.height += fHalf; - } else if (iHand == XFA_ATTRIBUTEENUM_Right) { - rtWidget.height -= fHalf; - } - break; - case 7: - if (iHand == XFA_ATTRIBUTEENUM_Left) { - rtWidget.left -= fHalf; - rtWidget.width += fHalf; - } else if (iHand == XFA_ATTRIBUTEENUM_Right) { - rtWidget.left += fHalf; - rtWidget.width -= fHalf; - } - break; - } - } - XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix); -} -void XFA_DrawBox(CXFA_Box box, - CFX_Graphics* pGS, - const CFX_RectF& rtWidget, - CFX_Matrix* pMatrix, - uint32_t dwFlags) { - if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible) - return; - - XFA_Element eType = box.GetElementType(); - if (eType != XFA_Element::Arc && eType != XFA_Element::Border && - eType != XFA_Element::Rectangle) { - return; - } - std::vector<CXFA_Stroke> strokes; - if (!(dwFlags & XFA_DRAWBOX_ForceRound) && eType != XFA_Element::Arc) - box.GetStrokes(&strokes); - - XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags); - XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags); -} - -CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {} - -CXFA_CalcData::~CXFA_CalcData() {} diff --git a/xfa/fxfa/app/xfa_ffwidgetacc.cpp b/xfa/fxfa/app/xfa_ffwidgetacc.cpp deleted file mode 100644 index adc5c31cc66f4d17d386d53fe13d924b34788f3e..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffwidgetacc.cpp +++ /dev/null @@ -1,1674 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_ffwidgetacc.h" - -#include <algorithm> -#include <memory> -#include <vector> - -#include "fxjs/cfxjse_value.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/tto/fde_textout.h" -#include "xfa/fde/xml/fde_xml_imp.h" -#include "xfa/fxfa/app/xfa_ffcheckbutton.h" -#include "xfa/fxfa/app/xfa_ffchoicelist.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localevalue.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxfa/xfa_fontmgr.h" - -static void XFA_FFDeleteCalcData(void* pData) { - if (pData) { - delete ((CXFA_CalcData*)pData); - } -} - -static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteCalcData = { - XFA_FFDeleteCalcData, nullptr}; - -class CXFA_WidgetLayoutData { - public: - CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {} - virtual ~CXFA_WidgetLayoutData() {} - - FX_FLOAT m_fWidgetHeight; -}; - -class CXFA_TextLayoutData : public CXFA_WidgetLayoutData { - public: - CXFA_TextLayoutData() {} - ~CXFA_TextLayoutData() override {} - - CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); } - CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); } - - void LoadText(CXFA_WidgetAcc* pAcc) { - if (m_pTextLayout) - return; - - m_pTextProvider = - pdfium::MakeUnique<CXFA_TextProvider>(pAcc, XFA_TEXTPROVIDERTYPE_Text); - m_pTextLayout = pdfium::MakeUnique<CXFA_TextLayout>(m_pTextProvider.get()); - } - - private: - std::unique_ptr<CXFA_TextLayout> m_pTextLayout; - std::unique_ptr<CXFA_TextProvider> m_pTextProvider; -}; - -class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData { - public: - CXFA_ImageLayoutData() - : m_pDIBitmap(nullptr), - m_bNamedImage(false), - m_iImageXDpi(0), - m_iImageYDpi(0) {} - - ~CXFA_ImageLayoutData() override { - if (m_pDIBitmap && !m_bNamedImage) - delete m_pDIBitmap; - } - - bool LoadImageData(CXFA_WidgetAcc* pAcc) { - if (m_pDIBitmap) - return true; - - CXFA_Value value = pAcc->GetFormValue(); - if (!value) - return false; - - CXFA_Image imageObj = value.GetImage(); - if (!imageObj) - return false; - - CXFA_FFDoc* pFFDoc = pAcc->GetDoc(); - pAcc->SetImageImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage, - m_iImageXDpi, m_iImageYDpi)); - return !!m_pDIBitmap; - } - - CFX_DIBitmap* m_pDIBitmap; - bool m_bNamedImage; - int32_t m_iImageXDpi; - int32_t m_iImageYDpi; -}; - -class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData { - public: - CXFA_FieldLayoutData() {} - ~CXFA_FieldLayoutData() override {} - - bool LoadCaption(CXFA_WidgetAcc* pAcc) { - if (m_pCapTextLayout) - return true; - CXFA_Caption caption = pAcc->GetCaption(); - if (!caption || caption.GetPresence() == XFA_ATTRIBUTEENUM_Hidden) - return false; - m_pCapTextProvider.reset( - new CXFA_TextProvider(pAcc, XFA_TEXTPROVIDERTYPE_Caption)); - m_pCapTextLayout = - pdfium::MakeUnique<CXFA_TextLayout>(m_pCapTextProvider.get()); - return true; - } - - std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout; - std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider; - std::unique_ptr<CFDE_TextOut> m_pTextOut; - std::vector<FX_FLOAT> m_FieldSplitArray; -}; - -class CXFA_TextEditData : public CXFA_FieldLayoutData { - public: -}; - -class CXFA_ImageEditData : public CXFA_FieldLayoutData { - public: - CXFA_ImageEditData() - : m_pDIBitmap(nullptr), - m_bNamedImage(false), - m_iImageXDpi(0), - m_iImageYDpi(0) {} - - ~CXFA_ImageEditData() override { - if (m_pDIBitmap && !m_bNamedImage) - delete m_pDIBitmap; - } - - bool LoadImageData(CXFA_WidgetAcc* pAcc) { - if (m_pDIBitmap) - return true; - - CXFA_Value value = pAcc->GetFormValue(); - if (!value) - return false; - - CXFA_Image imageObj = value.GetImage(); - CXFA_FFDoc* pFFDoc = pAcc->GetDoc(); - pAcc->SetImageEditImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage, - m_iImageXDpi, m_iImageYDpi)); - return !!m_pDIBitmap; - } - - CFX_DIBitmap* m_pDIBitmap; - bool m_bNamedImage; - int32_t m_iImageXDpi; - int32_t m_iImageYDpi; -}; - -CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_FFDocView* pDocView, CXFA_Node* pNode) - : CXFA_WidgetData(pNode), - m_pDocView(pDocView), - m_nRecursionDepth(0) {} - -CXFA_WidgetAcc::~CXFA_WidgetAcc() {} - -bool CXFA_WidgetAcc::GetName(CFX_WideString& wsName, int32_t iNameType) { - if (iNameType == 0) { - m_pNode->TryCData(XFA_ATTRIBUTE_Name, wsName); - return !wsName.IsEmpty(); - } - m_pNode->GetSOMExpression(wsName); - if (iNameType == 2 && wsName.GetLength() >= 15) { - CFX_WideStringC wsPre = L"xfa[0].form[0]."; - if (wsPre == CFX_WideStringC(wsName.c_str(), wsPre.GetLength())) { - wsName.Delete(0, wsPre.GetLength()); - } - } - return true; -} -CXFA_Node* CXFA_WidgetAcc::GetDatasets() { - return m_pNode->GetBindData(); -} -bool CXFA_WidgetAcc::ProcessValueChanged() { - m_pDocView->AddValidateWidget(this); - m_pDocView->AddCalculateWidgetAcc(this); - m_pDocView->RunCalculateWidgets(); - m_pDocView->RunValidate(); - return true; -} -void CXFA_WidgetAcc::ResetData() { - CFX_WideString wsValue; - XFA_Element eUIType = GetUIType(); - switch (eUIType) { - case XFA_Element::ImageEdit: { - CXFA_Value imageValue = GetDefaultValue(); - CXFA_Image image = imageValue.GetImage(); - CFX_WideString wsContentType, wsHref; - if (image) { - image.GetContent(wsValue); - image.GetContentType(wsContentType); - image.GetHref(wsHref); - } - SetImageEdit(wsContentType, wsHref, wsValue); - } break; - case XFA_Element::ExclGroup: { - CXFA_Node* pNextChild = m_pNode->GetNodeItem( - XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode); - while (pNextChild) { - CXFA_Node* pChild = pNextChild; - CXFA_WidgetAcc* pAcc = - static_cast<CXFA_WidgetAcc*>(pChild->GetWidgetData()); - if (!pAcc) { - continue; - } - CXFA_Value defValue(nullptr); - if (wsValue.IsEmpty() && (defValue = pAcc->GetDefaultValue())) { - defValue.GetChildValueContent(wsValue); - SetValue(wsValue, XFA_VALUEPICTURE_Raw); - pAcc->SetValue(wsValue, XFA_VALUEPICTURE_Raw); - } else { - CXFA_Node* pItems = pChild->GetChild(0, XFA_Element::Items); - if (!pItems) { - continue; - } - CFX_WideString itemText; - if (pItems->CountChildren(XFA_Element::Unknown) > 1) { - itemText = pItems->GetChild(1, XFA_Element::Unknown)->GetContent(); - } - pAcc->SetValue(itemText, XFA_VALUEPICTURE_Raw); - } - pNextChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling, - XFA_ObjectType::ContainerNode); - } - } break; - case XFA_Element::ChoiceList: - ClearAllSelections(); - default: - if (CXFA_Value defValue = GetDefaultValue()) { - defValue.GetChildValueContent(wsValue); - } - SetValue(wsValue, XFA_VALUEPICTURE_Raw); - break; - } -} -void CXFA_WidgetAcc::SetImageEdit(const CFX_WideString& wsContentType, - const CFX_WideString& wsHref, - const CFX_WideString& wsData) { - CXFA_Image image = GetFormValue().GetImage(); - if (image) { - image.SetContentType(CFX_WideString(wsContentType)); - image.SetHref(wsHref); - } - CFX_WideString wsFormatValue(wsData); - GetFormatDataValue(wsData, wsFormatValue); - m_pNode->SetContent(wsData, wsFormatValue, true); - CXFA_Node* pBind = GetDatasets(); - if (!pBind) { - image.SetTransferEncoding(XFA_ATTRIBUTEENUM_Base64); - return; - } - pBind->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType); - CXFA_Node* pHrefNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pHrefNode) { - pHrefNode->SetCData(XFA_ATTRIBUTE_Value, wsHref); - } else { - CFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); - ASSERT(pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element); - static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"href", wsHref); - } -} - -CXFA_WidgetAcc* CXFA_WidgetAcc::GetExclGroup() { - CXFA_Node* pExcl = m_pNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) { - return nullptr; - } - return static_cast<CXFA_WidgetAcc*>(pExcl->GetWidgetData()); -} -CXFA_FFDocView* CXFA_WidgetAcc::GetDocView() { - return m_pDocView; -} -CXFA_FFDoc* CXFA_WidgetAcc::GetDoc() { - return m_pDocView->GetDoc(); -} -CXFA_FFApp* CXFA_WidgetAcc::GetApp() { - return GetDoc()->GetApp(); -} -IXFA_AppProvider* CXFA_WidgetAcc::GetAppProvider() { - return GetApp()->GetAppProvider(); -} -int32_t CXFA_WidgetAcc::ProcessEvent(int32_t iActivity, - CXFA_EventParam* pEventParam) { - if (GetElementType() == XFA_Element::Draw) { - return XFA_EVENTERROR_NotExist; - } - int32_t iRet = XFA_EVENTERROR_NotExist; - CXFA_NodeArray eventArray; - int32_t iCounts = - GetEventByActivity(iActivity, eventArray, pEventParam->m_bIsFormReady); - for (int32_t i = 0; i < iCounts; i++) { - CXFA_Event event(eventArray[i]); - int32_t result = ProcessEvent(event, pEventParam); - if (i == 0) { - iRet = result; - } else if (result == XFA_EVENTERROR_Success) { - iRet = result; - } - } - return iRet; -} -int32_t CXFA_WidgetAcc::ProcessEvent(CXFA_Event& event, - CXFA_EventParam* pEventParam) { - if (!event) - return XFA_EVENTERROR_NotExist; - - switch (event.GetEventType()) { - case XFA_Element::Execute: - break; - case XFA_Element::Script: { - CXFA_Script script = event.GetScript(); - return ExecuteScript(script, pEventParam); - } break; - case XFA_Element::SignData: - break; - case XFA_Element::Submit: { - CXFA_Submit submit = event.GetSubmit(); - return GetDoc()->GetDocEnvironment()->SubmitData(GetDoc(), submit); - } - default: - break; - } - return XFA_EVENTERROR_NotExist; -} - -int32_t CXFA_WidgetAcc::ProcessCalculate() { - if (GetElementType() == XFA_Element::Draw) - return XFA_EVENTERROR_NotExist; - - CXFA_Calculate calc = GetCalculate(); - if (!calc) - return XFA_EVENTERROR_NotExist; - if (GetNode()->IsUserInteractive()) - return XFA_EVENTERROR_Disabled; - - CXFA_EventParam EventParam; - EventParam.m_eType = XFA_EVENT_Calculate; - CXFA_Script script = calc.GetScript(); - int32_t iRet = ExecuteScript(script, &EventParam); - if (iRet != XFA_EVENTERROR_Success) - return iRet; - - if (GetRawValue() != EventParam.m_wsResult) { - SetValue(EventParam.m_wsResult, XFA_VALUEPICTURE_Raw); - UpdateUIDisplay(); - } - return XFA_EVENTERROR_Success; -} - -void CXFA_WidgetAcc::ProcessScriptTestValidate(CXFA_Validate validate, - int32_t iRet, - CFXJSE_Value* pRetValue, - bool bVersionFlag) { - if (iRet == XFA_EVENTERROR_Success && pRetValue) { - if (pRetValue->IsBoolean() && !pRetValue->ToBoolean()) { - IXFA_AppProvider* pAppProvider = GetAppProvider(); - if (!pAppProvider) { - return; - } - CFX_WideString wsTitle = pAppProvider->GetAppTitle(); - CFX_WideString wsScriptMsg; - validate.GetScriptMessageText(wsScriptMsg); - int32_t eScriptTest = validate.GetScriptTest(); - if (eScriptTest == XFA_ATTRIBUTEENUM_Warning) { - if (GetNode()->IsUserInteractive()) - return; - if (wsScriptMsg.IsEmpty()) - wsScriptMsg = GetValidateMessage(false, bVersionFlag); - - if (bVersionFlag) { - pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, - XFA_MB_OK); - return; - } - if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, - XFA_MB_YesNo) == XFA_IDYes) { - GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); - } - } else { - if (wsScriptMsg.IsEmpty()) - wsScriptMsg = GetValidateMessage(true, bVersionFlag); - pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); - } - } - } -} -int32_t CXFA_WidgetAcc::ProcessFormatTestValidate(CXFA_Validate validate, - bool bVersionFlag) { - CFX_WideString wsRawValue = GetRawValue(); - if (!wsRawValue.IsEmpty()) { - CFX_WideString wsPicture; - validate.GetPicture(wsPicture); - if (wsPicture.IsEmpty()) { - return XFA_EVENTERROR_NotExist; - } - IFX_Locale* pLocale = GetLocal(); - if (!pLocale) { - return XFA_EVENTERROR_NotExist; - } - CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this); - if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale)) { - IXFA_AppProvider* pAppProvider = GetAppProvider(); - if (!pAppProvider) { - return XFA_EVENTERROR_NotExist; - } - CFX_WideString wsFormatMsg; - validate.GetFormatMessageText(wsFormatMsg); - CFX_WideString wsTitle = pAppProvider->GetAppTitle(); - int32_t eFormatTest = validate.GetFormatTest(); - if (eFormatTest == XFA_ATTRIBUTEENUM_Error) { - if (wsFormatMsg.IsEmpty()) - wsFormatMsg = GetValidateMessage(true, bVersionFlag); - pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); - return XFA_EVENTERROR_Success; - } - if (GetNode()->IsUserInteractive()) - return XFA_EVENTERROR_NotExist; - if (wsFormatMsg.IsEmpty()) - wsFormatMsg = GetValidateMessage(false, bVersionFlag); - - if (bVersionFlag) { - pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, - XFA_MB_OK); - return XFA_EVENTERROR_Success; - } - if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, - XFA_MB_YesNo) == XFA_IDYes) { - GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); - } - return XFA_EVENTERROR_Success; - } - } - return XFA_EVENTERROR_NotExist; -} -int32_t CXFA_WidgetAcc::ProcessNullTestValidate(CXFA_Validate validate, - int32_t iFlags, - bool bVersionFlag) { - CFX_WideString wsValue; - GetValue(wsValue, XFA_VALUEPICTURE_Raw); - if (!wsValue.IsEmpty()) { - return XFA_EVENTERROR_Success; - } - if (m_bIsNull && (m_bPreNull == m_bIsNull)) { - return XFA_EVENTERROR_Success; - } - int32_t eNullTest = validate.GetNullTest(); - CFX_WideString wsNullMsg; - validate.GetNullMessageText(wsNullMsg); - if (iFlags & 0x01) { - int32_t iRet = XFA_EVENTERROR_Success; - if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) { - iRet = XFA_EVENTERROR_Error; - } - if (!wsNullMsg.IsEmpty()) { - if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) { - m_pDocView->m_arrNullTestMsg.push_back(wsNullMsg); - return XFA_EVENTERROR_Error; - } - return XFA_EVENTERROR_Success; - } - return iRet; - } - if (wsNullMsg.IsEmpty() && bVersionFlag && - eNullTest != XFA_ATTRIBUTEENUM_Disabled) { - return XFA_EVENTERROR_Error; - } - IXFA_AppProvider* pAppProvider = GetAppProvider(); - if (!pAppProvider) { - return XFA_EVENTERROR_NotExist; - } - CFX_WideString wsCaptionName; - CFX_WideString wsTitle = pAppProvider->GetAppTitle(); - switch (eNullTest) { - case XFA_ATTRIBUTEENUM_Error: { - if (wsNullMsg.IsEmpty()) { - wsCaptionName = GetValidateCaptionName(bVersionFlag); - wsNullMsg.Format(L"%s cannot be blank.", wsCaptionName.c_str()); - } - pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK); - return XFA_EVENTERROR_Error; - } - case XFA_ATTRIBUTEENUM_Warning: { - if (GetNode()->IsUserInteractive()) - return true; - - if (wsNullMsg.IsEmpty()) { - wsCaptionName = GetValidateCaptionName(bVersionFlag); - wsNullMsg.Format( - L"%s cannot be blank. To ignore validations for %s, click Ignore.", - wsCaptionName.c_str(), wsCaptionName.c_str()); - } - if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning, - XFA_MB_YesNo) == XFA_IDYes) { - GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); - } - return XFA_EVENTERROR_Error; - } - case XFA_ATTRIBUTEENUM_Disabled: - default: - break; - } - return XFA_EVENTERROR_Success; -} - -CFX_WideString CXFA_WidgetAcc::GetValidateCaptionName(bool bVersionFlag) { - CFX_WideString wsCaptionName; - - if (!bVersionFlag) { - if (CXFA_Caption caption = GetCaption()) { - if (CXFA_Value capValue = caption.GetValue()) { - if (CXFA_Text capText = capValue.GetText()) - capText.GetContent(wsCaptionName); - } - } - } - if (wsCaptionName.IsEmpty()) - GetName(wsCaptionName); - - return wsCaptionName; -} - -CFX_WideString CXFA_WidgetAcc::GetValidateMessage(bool bError, - bool bVersionFlag) { - CFX_WideString wsCaptionName = GetValidateCaptionName(bVersionFlag); - CFX_WideString wsMessage; - if (bVersionFlag) { - wsMessage.Format(L"%s validation failed", wsCaptionName.c_str()); - return wsMessage; - } - if (bError) { - wsMessage.Format(L"The value you entered for %s is invalid.", - wsCaptionName.c_str()); - return wsMessage; - } - wsMessage.Format( - L"The value you entered for %s is invalid. To ignore " - L"validations for %s, click Ignore.", - wsCaptionName.c_str(), wsCaptionName.c_str()); - return wsMessage; -} - -int32_t CXFA_WidgetAcc::ProcessValidate(int32_t iFlags) { - if (GetElementType() == XFA_Element::Draw) { - return XFA_EVENTERROR_NotExist; - } - CXFA_Validate validate = GetValidate(); - if (!validate) { - return XFA_EVENTERROR_NotExist; - } - bool bInitDoc = validate.GetNode()->NeedsInitApp(); - bool bStatus = m_pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End; - int32_t iFormat = 0; - CFXJSE_Value* pRetValue = nullptr; - int32_t iRet = XFA_EVENTERROR_NotExist; - CXFA_Script script = validate.GetScript(); - if (script) { - CXFA_EventParam eParam; - eParam.m_eType = XFA_EVENT_Validate; - eParam.m_pTarget = this; - iRet = ExecuteScript(script, &eParam, - ((bInitDoc || bStatus) && GetRawValue().IsEmpty()) - ? nullptr - : &pRetValue); - } - XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode(); - bool bVersionFlag = false; - if (version < XFA_VERSION_208) { - bVersionFlag = true; - } - if (bInitDoc) { - validate.GetNode()->ClearFlag(XFA_NodeFlag_NeedsInitApp); - } else { - iFormat = ProcessFormatTestValidate(validate, bVersionFlag); - if (!bVersionFlag) { - bVersionFlag = GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting); - } - iRet |= ProcessNullTestValidate(validate, iFlags, bVersionFlag); - } - if (iFormat != XFA_EVENTERROR_Success) { - ProcessScriptTestValidate(validate, iRet, pRetValue, bVersionFlag); - } - delete pRetValue; - - return iRet | iFormat; -} -int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_Script script, - CXFA_EventParam* pEventParam, - CFXJSE_Value** pRetValue) { - static const uint32_t MAX_RECURSION_DEPTH = 2; - if (m_nRecursionDepth > MAX_RECURSION_DEPTH) - return XFA_EVENTERROR_Success; - ASSERT(pEventParam); - if (!script) { - return XFA_EVENTERROR_NotExist; - } - if (script.GetRunAt() == XFA_ATTRIBUTEENUM_Server) { - return XFA_EVENTERROR_Disabled; - } - CFX_WideString wsExpression; - script.GetExpression(wsExpression); - if (wsExpression.IsEmpty()) { - return XFA_EVENTERROR_NotExist; - } - XFA_SCRIPTTYPE eScriptType = script.GetContentType(); - if (eScriptType == XFA_SCRIPTTYPE_Unkown) { - return XFA_EVENTERROR_Success; - } - CXFA_FFDoc* pDoc = GetDoc(); - CXFA_ScriptContext* pContext = pDoc->GetXFADoc()->GetScriptContext(); - pContext->SetEventParam(*pEventParam); - pContext->SetRunAtType((XFA_ATTRIBUTEENUM)script.GetRunAt()); - CXFA_NodeArray refNodes; - if (pEventParam->m_eType == XFA_EVENT_InitCalculate || - pEventParam->m_eType == XFA_EVENT_Calculate) { - pContext->SetNodesOfRunScript(&refNodes); - } - std::unique_ptr<CFXJSE_Value> pTmpRetValue( - new CFXJSE_Value(pContext->GetRuntime())); - ++m_nRecursionDepth; - bool bRet = pContext->RunScript((XFA_SCRIPTLANGTYPE)eScriptType, - wsExpression.AsStringC(), pTmpRetValue.get(), - m_pNode); - --m_nRecursionDepth; - int32_t iRet = XFA_EVENTERROR_Error; - if (bRet) { - iRet = XFA_EVENTERROR_Success; - if (pEventParam->m_eType == XFA_EVENT_Calculate || - pEventParam->m_eType == XFA_EVENT_InitCalculate) { - if (!pTmpRetValue->IsUndefined()) { - if (!pTmpRetValue->IsNull()) - pEventParam->m_wsResult = pTmpRetValue->ToWideString(); - - iRet = XFA_EVENTERROR_Success; - } else { - iRet = XFA_EVENTERROR_Error; - } - if (pEventParam->m_eType == XFA_EVENT_InitCalculate) { - if ((iRet == XFA_EVENTERROR_Success) && - (GetRawValue() != pEventParam->m_wsResult)) { - SetValue(pEventParam->m_wsResult, XFA_VALUEPICTURE_Raw); - m_pDocView->AddValidateWidget(this); - } - } - int32_t iRefs = refNodes.GetSize(); - for (int32_t r = 0; r < iRefs; r++) { - CXFA_WidgetAcc* pRefAcc = - static_cast<CXFA_WidgetAcc*>(refNodes[r]->GetWidgetData()); - if (pRefAcc && pRefAcc == this) { - continue; - } - CXFA_Node* pRefNode = refNodes[r]; - CXFA_CalcData* pGlobalData = - (CXFA_CalcData*)pRefNode->GetUserData(XFA_CalcData); - if (!pGlobalData) { - pGlobalData = new CXFA_CalcData; - pRefNode->SetUserData(XFA_CalcData, pGlobalData, - &gs_XFADeleteCalcData); - } - if (!pdfium::ContainsValue(pGlobalData->m_Globals, this)) - pGlobalData->m_Globals.push_back(this); - } - } - } - if (pRetValue) - *pRetValue = pTmpRetValue.release(); - - pContext->SetNodesOfRunScript(nullptr); - return iRet; -} -CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) { - CXFA_LayoutItem* pLayout = nullptr; - if (pWidget) { - pLayout = pWidget->GetNext(); - } else { - pLayout = m_pDocView->GetXFALayout()->GetLayoutItem(m_pNode); - } - return static_cast<CXFA_FFWidget*>(pLayout); -} -void CXFA_WidgetAcc::UpdateUIDisplay(CXFA_FFWidget* pExcept) { - CXFA_FFWidget* pWidget = nullptr; - while ((pWidget = GetNextWidget(pWidget)) != nullptr) { - if (pWidget == pExcept || !pWidget->IsLoaded() || - (GetUIType() != XFA_Element::CheckButton && pWidget->IsFocused())) { - continue; - } - pWidget->UpdateFWLData(); - pWidget->AddInvalidateRect(); - } -} - -void CXFA_WidgetAcc::CalcCaptionSize(CFX_SizeF& szCap) { - CXFA_Caption caption = GetCaption(); - if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { - return; - } - LoadCaption(); - XFA_Element eUIType = GetUIType(); - int32_t iCapPlacement = caption.GetPlacementType(); - FX_FLOAT fCapReserve = caption.GetReserve(); - const bool bVert = iCapPlacement == XFA_ATTRIBUTEENUM_Top || - iCapPlacement == XFA_ATTRIBUTEENUM_Bottom; - const bool bReserveExit = fCapReserve > 0.01; - CXFA_TextLayout* pCapTextLayout = - static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) - ->m_pCapTextLayout.get(); - if (pCapTextLayout) { - if (!bVert && eUIType != XFA_Element::Button) { - szCap.width = fCapReserve; - } - CFX_SizeF minSize; - pCapTextLayout->CalcSize(minSize, szCap, szCap); - if (bReserveExit) { - bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve; - } - } else { - FX_FLOAT fFontSize = 10.0f; - if (CXFA_Font font = caption.GetFont()) { - fFontSize = font.GetFontSize(); - } else if (CXFA_Font widgetfont = GetFont()) { - fFontSize = widgetfont.GetFontSize(); - } - if (bVert) { - szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize; - } else { - szCap.width = fCapReserve > 0 ? fCapReserve : 0; - szCap.height = fFontSize; - } - } - if (CXFA_Margin mgCap = caption.GetMargin()) { - FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; - mgCap.GetLeftInset(fLeftInset); - mgCap.GetTopInset(fTopInset); - mgCap.GetRightInset(fRightInset); - mgCap.GetBottomInset(fBottomInset); - if (bReserveExit) { - bVert ? (szCap.width += fLeftInset + fRightInset) - : (szCap.height += fTopInset + fBottomInset); - } else { - szCap.width += fLeftInset + fRightInset; - szCap.height += fTopInset + fBottomInset; - } - } -} -bool CXFA_WidgetAcc::CalculateFieldAutoSize(CFX_SizeF& size) { - CFX_SizeF szCap; - CalcCaptionSize(szCap); - CFX_RectF rtUIMargin = GetUIMargin(); - size.width += rtUIMargin.left + rtUIMargin.width; - size.height += rtUIMargin.top + rtUIMargin.height; - if (szCap.width > 0 && szCap.height > 0) { - int32_t iCapPlacement = GetCaption().GetPlacementType(); - switch (iCapPlacement) { - case XFA_ATTRIBUTEENUM_Left: - case XFA_ATTRIBUTEENUM_Right: - case XFA_ATTRIBUTEENUM_Inline: { - size.width += szCap.width; - size.height = std::max(size.height, szCap.height); - } break; - case XFA_ATTRIBUTEENUM_Top: - case XFA_ATTRIBUTEENUM_Bottom: { - size.height += szCap.height; - size.width = std::max(size.width, szCap.width); - } - default: - break; - } - } - return CalculateWidgetAutoSize(size); -} -bool CXFA_WidgetAcc::CalculateWidgetAutoSize(CFX_SizeF& size) { - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; - mgWidget.GetLeftInset(fLeftInset); - mgWidget.GetTopInset(fTopInset); - mgWidget.GetRightInset(fRightInset); - mgWidget.GetBottomInset(fBottomInset); - size.width += fLeftInset + fRightInset; - size.height += fTopInset + fBottomInset; - } - CXFA_Para para = GetPara(); - if (para) - size.width += para.GetMarginLeft() + para.GetTextIndent(); - - FX_FLOAT fVal = 0; - FX_FLOAT fMin = 0; - FX_FLOAT fMax = 0; - if (GetWidth(fVal)) { - size.width = fVal; - } else { - if (GetMinWidth(fMin)) - size.width = std::max(size.width, fMin); - if (GetMaxWidth(fMax) && fMax > 0) - size.width = std::min(size.width, fMax); - } - fVal = 0; - fMin = 0; - fMax = 0; - if (GetHeight(fVal)) { - size.height = fVal; - } else { - if (GetMinHeight(fMin)) - size.height = std::max(size.height, fMin); - if (GetMaxHeight(fMax) && fMax > 0) - size.height = std::min(size.height, fMax); - } - return true; -} - -void CXFA_WidgetAcc::CalculateTextContentSize(CFX_SizeF& size) { - FX_FLOAT fFontSize = GetFontSize(); - CFX_WideString wsText; - GetValue(wsText, XFA_VALUEPICTURE_Display); - if (wsText.IsEmpty()) { - size.height += fFontSize; - return; - } - - FX_WCHAR wcEnter = '\n'; - FX_WCHAR wsLast = wsText.GetAt(wsText.GetLength() - 1); - if (wsLast == wcEnter) { - wsText = wsText + wcEnter; - } - - CXFA_FieldLayoutData* layoutData = - static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); - if (!layoutData->m_pTextOut) { - layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>(); - CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get(); - pTextOut->SetFont(GetFDEFont()); - pTextOut->SetFontSize(fFontSize); - pTextOut->SetLineBreakTolerance(fFontSize * 0.2f); - pTextOut->SetLineSpace(GetLineHeight()); - uint32_t dwStyles = FDE_TTOSTYLE_LastLineHeight; - if (GetUIType() == XFA_Element::TextEdit && IsMultiLine()) { - dwStyles |= FDE_TTOSTYLE_LineWrap; - } - pTextOut->SetStyles(dwStyles); - } - layoutData->m_pTextOut->CalcLogicSize(wsText.c_str(), wsText.GetLength(), - size); -} -bool CXFA_WidgetAcc::CalculateTextEditAutoSize(CFX_SizeF& size) { - if (size.width > 0) { - CFX_SizeF szOrz = size; - CFX_SizeF szCap; - CalcCaptionSize(szCap); - bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01; - int32_t iCapPlacement = XFA_ATTRIBUTEENUM_Unknown; - if (bCapExit) { - iCapPlacement = GetCaption().GetPlacementType(); - switch (iCapPlacement) { - case XFA_ATTRIBUTEENUM_Left: - case XFA_ATTRIBUTEENUM_Right: - case XFA_ATTRIBUTEENUM_Inline: { - size.width -= szCap.width; - } - default: - break; - } - } - CFX_RectF rtUIMargin = GetUIMargin(); - size.width -= rtUIMargin.left + rtUIMargin.width; - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - FX_FLOAT fLeftInset, fRightInset; - mgWidget.GetLeftInset(fLeftInset); - mgWidget.GetRightInset(fRightInset); - size.width -= fLeftInset + fRightInset; - } - CalculateTextContentSize(size); - size.height += rtUIMargin.top + rtUIMargin.height; - if (bCapExit) { - switch (iCapPlacement) { - case XFA_ATTRIBUTEENUM_Left: - case XFA_ATTRIBUTEENUM_Right: - case XFA_ATTRIBUTEENUM_Inline: { - size.height = std::max(size.height, szCap.height); - } break; - case XFA_ATTRIBUTEENUM_Top: - case XFA_ATTRIBUTEENUM_Bottom: { - size.height += szCap.height; - } - default: - break; - } - } - size.width = szOrz.width; - return CalculateWidgetAutoSize(size); - } - CalculateTextContentSize(size); - return CalculateFieldAutoSize(size); -} -bool CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CFX_SizeF& size) { - FX_FLOAT fCheckSize = GetCheckButtonSize(); - size = CFX_SizeF(fCheckSize, fCheckSize); - return CalculateFieldAutoSize(size); -} -bool CXFA_WidgetAcc::CalculatePushButtonAutoSize(CFX_SizeF& size) { - CalcCaptionSize(size); - return CalculateWidgetAutoSize(size); -} -bool CXFA_WidgetAcc::CalculateImageAutoSize(CFX_SizeF& size) { - if (!GetImageImage()) { - LoadImageImage(); - } - size.clear(); - if (CFX_DIBitmap* pBitmap = GetImageImage()) { - int32_t iImageXDpi = 0; - int32_t iImageYDpi = 0; - GetImageDpi(iImageXDpi, iImageYDpi); - CFX_RectF rtImage( - 0, 0, - XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetWidth(), (FX_FLOAT)iImageXDpi), - XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetHeight(), (FX_FLOAT)iImageYDpi)); - - CFX_RectF rtFit; - if (GetWidth(rtFit.width)) { - GetWidthWithoutMargin(rtFit.width); - } else { - rtFit.width = rtImage.width; - } - if (GetHeight(rtFit.height)) { - GetHeightWithoutMargin(rtFit.height); - } else { - rtFit.height = rtImage.height; - } - size = rtFit.Size(); - } - return CalculateWidgetAutoSize(size); -} -bool CXFA_WidgetAcc::CalculateImageEditAutoSize(CFX_SizeF& size) { - if (!GetImageEditImage()) { - LoadImageEditImage(); - } - size.clear(); - if (CFX_DIBitmap* pBitmap = GetImageEditImage()) { - int32_t iImageXDpi = 0; - int32_t iImageYDpi = 0; - GetImageEditDpi(iImageXDpi, iImageYDpi); - CFX_RectF rtImage( - 0, 0, - XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetWidth(), (FX_FLOAT)iImageXDpi), - XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetHeight(), (FX_FLOAT)iImageYDpi)); - - CFX_RectF rtFit; - if (GetWidth(rtFit.width)) { - GetWidthWithoutMargin(rtFit.width); - } else { - rtFit.width = rtImage.width; - } - if (GetHeight(rtFit.height)) { - GetHeightWithoutMargin(rtFit.height); - } else { - rtFit.height = rtImage.height; - } - size.width = rtFit.width; - size.height = rtFit.height; - } - return CalculateFieldAutoSize(size); -} -bool CXFA_WidgetAcc::LoadImageImage() { - InitLayoutData(); - return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) - ->LoadImageData(this); -} -bool CXFA_WidgetAcc::LoadImageEditImage() { - InitLayoutData(); - return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) - ->LoadImageData(this); -} -void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { - CXFA_ImageLayoutData* pData = - static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); - iImageXDpi = pData->m_iImageXDpi; - iImageYDpi = pData->m_iImageYDpi; -} -void CXFA_WidgetAcc::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { - CXFA_ImageEditData* pData = - static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); - iImageXDpi = pData->m_iImageXDpi; - iImageYDpi = pData->m_iImageYDpi; -} -bool CXFA_WidgetAcc::CalculateTextAutoSize(CFX_SizeF& size) { - LoadText(); - CXFA_TextLayout* pTextLayout = - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); - if (pTextLayout) { - size.width = pTextLayout->StartLayout(size.width); - size.height = pTextLayout->GetLayoutHeight(); - } - return CalculateWidgetAutoSize(size); -} -void CXFA_WidgetAcc::LoadText() { - InitLayoutData(); - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(this); -} -FX_FLOAT CXFA_WidgetAcc::CalculateWidgetAutoWidth(FX_FLOAT fWidthCalc) { - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - FX_FLOAT fLeftInset, fRightInset; - mgWidget.GetLeftInset(fLeftInset); - mgWidget.GetRightInset(fRightInset); - fWidthCalc += fLeftInset + fRightInset; - } - FX_FLOAT fMin = 0, fMax = 0; - if (GetMinWidth(fMin)) { - fWidthCalc = std::max(fWidthCalc, fMin); - } - if (GetMaxWidth(fMax) && fMax > 0) { - fWidthCalc = std::min(fWidthCalc, fMax); - } - return fWidthCalc; -} -FX_FLOAT CXFA_WidgetAcc::GetWidthWithoutMargin(FX_FLOAT fWidthCalc) { - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - FX_FLOAT fLeftInset, fRightInset; - mgWidget.GetLeftInset(fLeftInset); - mgWidget.GetRightInset(fRightInset); - fWidthCalc -= fLeftInset + fRightInset; - } - return fWidthCalc; -} -FX_FLOAT CXFA_WidgetAcc::CalculateWidgetAutoHeight(FX_FLOAT fHeightCalc) { - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - FX_FLOAT fTopInset, fBottomInset; - mgWidget.GetTopInset(fTopInset); - mgWidget.GetBottomInset(fBottomInset); - fHeightCalc += fTopInset + fBottomInset; - } - FX_FLOAT fMin = 0, fMax = 0; - if (GetMinHeight(fMin)) { - fHeightCalc = std::max(fHeightCalc, fMin); - } - if (GetMaxHeight(fMax) && fMax > 0) { - fHeightCalc = std::min(fHeightCalc, fMax); - } - return fHeightCalc; -} -FX_FLOAT CXFA_WidgetAcc::GetHeightWithoutMargin(FX_FLOAT fHeightCalc) { - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - FX_FLOAT fTopInset, fBottomInset; - mgWidget.GetTopInset(fTopInset); - mgWidget.GetBottomInset(fBottomInset); - fHeightCalc -= fTopInset + fBottomInset; - } - return fHeightCalc; -} -void CXFA_WidgetAcc::StartWidgetLayout(FX_FLOAT& fCalcWidth, - FX_FLOAT& fCalcHeight) { - InitLayoutData(); - XFA_Element eUIType = GetUIType(); - if (eUIType == XFA_Element::Text) { - m_pLayoutData->m_fWidgetHeight = -1; - GetHeight(m_pLayoutData->m_fWidgetHeight); - StartTextLayout(fCalcWidth, fCalcHeight); - return; - } - if (fCalcWidth > 0 && fCalcHeight > 0) { - return; - } - m_pLayoutData->m_fWidgetHeight = -1; - FX_FLOAT fWidth = 0; - if (fCalcWidth > 0 && fCalcHeight < 0) { - if (!GetHeight(fCalcHeight)) { - CalculateAccWidthAndHeight(eUIType, fCalcWidth, fCalcHeight); - } - m_pLayoutData->m_fWidgetHeight = fCalcHeight; - return; - } - if (fCalcWidth < 0 && fCalcHeight < 0) { - if (!GetWidth(fWidth) || !GetHeight(fCalcHeight)) { - CalculateAccWidthAndHeight(eUIType, fWidth, fCalcHeight); - } - fCalcWidth = fWidth; - } - m_pLayoutData->m_fWidgetHeight = fCalcHeight; -} -void CXFA_WidgetAcc::CalculateAccWidthAndHeight(XFA_Element eUIType, - FX_FLOAT& fWidth, - FX_FLOAT& fCalcHeight) { - CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight); - switch (eUIType) { - case XFA_Element::Barcode: - case XFA_Element::ChoiceList: - case XFA_Element::Signature: - CalculateFieldAutoSize(sz); - break; - case XFA_Element::ImageEdit: - CalculateImageEditAutoSize(sz); - break; - case XFA_Element::Button: - CalculatePushButtonAutoSize(sz); - break; - case XFA_Element::CheckButton: - CalculateCheckButtonAutoSize(sz); - break; - case XFA_Element::DateTimeEdit: - case XFA_Element::NumericEdit: - case XFA_Element::PasswordEdit: - case XFA_Element::TextEdit: - CalculateTextEditAutoSize(sz); - break; - case XFA_Element::Image: - CalculateImageAutoSize(sz); - break; - case XFA_Element::Arc: - case XFA_Element::Line: - case XFA_Element::Rectangle: - case XFA_Element::Subform: - case XFA_Element::ExclGroup: - CalculateWidgetAutoSize(sz); - break; - default: - break; - } - fWidth = sz.width; - m_pLayoutData->m_fWidgetHeight = sz.height; - fCalcHeight = sz.height; -} -bool CXFA_WidgetAcc::FindSplitPos(int32_t iBlockIndex, FX_FLOAT& fCalcHeight) { - XFA_Element eUIType = GetUIType(); - if (eUIType == XFA_Element::Subform) { - return false; - } - if (eUIType != XFA_Element::Text && eUIType != XFA_Element::TextEdit && - eUIType != XFA_Element::NumericEdit && - eUIType != XFA_Element::PasswordEdit) { - fCalcHeight = 0; - return true; - } - FX_FLOAT fTopInset = 0; - FX_FLOAT fBottomInset = 0; - if (iBlockIndex == 0) { - CXFA_Margin mgWidget = GetMargin(); - if (mgWidget) { - mgWidget.GetTopInset(fTopInset); - mgWidget.GetBottomInset(fBottomInset); - } - CFX_RectF rtUIMargin = GetUIMargin(); - fTopInset += rtUIMargin.top; - fBottomInset += rtUIMargin.width; - } - if (eUIType == XFA_Element::Text) { - FX_FLOAT fHeight = fCalcHeight; - if (iBlockIndex == 0) { - fCalcHeight = fCalcHeight - fTopInset; - if (fCalcHeight < 0) { - fCalcHeight = 0; - } - } - CXFA_TextLayout* pTextLayout = - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); - pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight, - m_pLayoutData->m_fWidgetHeight - fTopInset); - if (fCalcHeight != 0) { - if (iBlockIndex == 0) { - fCalcHeight = fCalcHeight + fTopInset; - } - if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) { - return false; - } - } - return true; - } - XFA_ATTRIBUTEENUM iCapPlacement = XFA_ATTRIBUTEENUM_Unknown; - FX_FLOAT fCapReserve = 0; - if (iBlockIndex == 0) { - CXFA_Caption caption = GetCaption(); - if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) { - iCapPlacement = (XFA_ATTRIBUTEENUM)caption.GetPlacementType(); - fCapReserve = caption.GetReserve(); - } - if (iCapPlacement == XFA_ATTRIBUTEENUM_Top && - fCalcHeight < fCapReserve + fTopInset) { - fCalcHeight = 0; - return true; - } - if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom && - m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) { - fCalcHeight = 0; - return true; - } - if (iCapPlacement != XFA_ATTRIBUTEENUM_Top) { - fCapReserve = 0; - } - } - CXFA_FieldLayoutData* pFieldData = - static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); - int32_t iLinesCount = 0; - FX_FLOAT fHeight = m_pLayoutData->m_fWidgetHeight; - CFX_WideString wsText; - GetValue(wsText, XFA_VALUEPICTURE_Display); - if (wsText.IsEmpty()) { - iLinesCount = 1; - } else { - if (!pFieldData->m_pTextOut) { - FX_FLOAT fWidth = 0; - GetWidth(fWidth); - CalculateAccWidthAndHeight(eUIType, fWidth, fHeight); - } - iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); - } - std::vector<FX_FLOAT>* pFieldArray = &pFieldData->m_FieldSplitArray; - int32_t iFieldSplitCount = pdfium::CollectionSize<int32_t>(*pFieldArray); - for (int32_t i = 0; i < iBlockIndex * 3; i += 3) { - iLinesCount -= (int32_t)(*pFieldArray)[i + 1]; - fHeight -= (*pFieldArray)[i + 2]; - } - if (iLinesCount == 0) { - return false; - } - FX_FLOAT fLineHeight = GetLineHeight(); - FX_FLOAT fFontSize = GetFontSize(); - FX_FLOAT fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize; - FX_FLOAT fSpaceAbove = 0; - FX_FLOAT fStartOffset = 0; - if (fHeight > 0.1f && iBlockIndex == 0) { - fStartOffset = fTopInset; - fHeight -= (fTopInset + fBottomInset); - if (CXFA_Para para = GetPara()) { - fSpaceAbove = para.GetSpaceAbove(); - FX_FLOAT fSpaceBelow = para.GetSpaceBelow(); - fHeight -= (fSpaceAbove + fSpaceBelow); - switch (para.GetVerticalAlign()) { - case XFA_ATTRIBUTEENUM_Top: - fStartOffset += fSpaceAbove; - break; - case XFA_ATTRIBUTEENUM_Middle: - fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove); - break; - case XFA_ATTRIBUTEENUM_Bottom: - fStartOffset += (fHeight - fTextHeight + fSpaceAbove); - break; - } - } - if (fStartOffset < 0.1f) - fStartOffset = 0; - } - for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) { - fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2]; - if (fStartOffset < 0.1f) - fStartOffset = 0; - } - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[0] = fStartOffset; - } else { - pFieldArray->push_back(fStartOffset); - } - XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode(); - bool bCanSplitNoContent = false; - XFA_ATTRIBUTEENUM eLayoutMode; - GetNode() - ->GetNodeItem(XFA_NODEITEM_Parent) - ->TryEnum(XFA_ATTRIBUTE_Layout, eLayoutMode, true); - if ((eLayoutMode == XFA_ATTRIBUTEENUM_Position || - eLayoutMode == XFA_ATTRIBUTEENUM_Tb || - eLayoutMode == XFA_ATTRIBUTEENUM_Row || - eLayoutMode == XFA_ATTRIBUTEENUM_Table) && - version > XFA_VERSION_208) { - bCanSplitNoContent = true; - } - if ((eLayoutMode == XFA_ATTRIBUTEENUM_Tb || - eLayoutMode == XFA_ATTRIBUTEENUM_Row || - eLayoutMode == XFA_ATTRIBUTEENUM_Table) && - version <= XFA_VERSION_208) { - if (fStartOffset < fCalcHeight) { - bCanSplitNoContent = true; - } else { - fCalcHeight = 0; - return true; - } - } - if (bCanSplitNoContent) { - if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) { - fCalcHeight = 0; - return true; - } - if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) { - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = 0; - (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; - } else { - pFieldArray->push_back(0); - pFieldArray->push_back(fCalcHeight); - } - return false; - } - if (fCalcHeight - fStartOffset < fLineHeight) { - fCalcHeight = fStartOffset; - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = 0; - (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; - } else { - pFieldArray->push_back(0); - pFieldArray->push_back(fCalcHeight); - } - return true; - } - FX_FLOAT fTextNum = - fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset; - int32_t iLineNum = - (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight); - if (iLineNum >= iLinesCount) { - if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) { - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = (FX_FLOAT)iLinesCount; - (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; - } else { - pFieldArray->push_back((FX_FLOAT)iLinesCount); - pFieldArray->push_back(fCalcHeight); - } - return false; - } - if (fHeight - fStartOffset - fTextHeight < fFontSize) { - iLineNum -= 1; - if (iLineNum == 0) { - fCalcHeight = 0; - return true; - } - } else { - iLineNum = (int32_t)(fTextNum / fLineHeight); - } - } - if (iLineNum > 0) { - FX_FLOAT fSplitHeight = - iLineNum * fLineHeight + fCapReserve + fStartOffset; - if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { - (*pFieldArray)[iBlockIndex * 3 + 1] = (FX_FLOAT)iLineNum; - (*pFieldArray)[iBlockIndex * 3 + 2] = fSplitHeight; - } else { - pFieldArray->push_back((FX_FLOAT)iLineNum); - pFieldArray->push_back(fSplitHeight); - } - if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) { - return false; - } - fCalcHeight = fSplitHeight; - return true; - } - } - fCalcHeight = 0; - return true; -} -void CXFA_WidgetAcc::InitLayoutData() { - if (m_pLayoutData) { - return; - } - switch (GetUIType()) { - case XFA_Element::Text: - m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>(); - return; - case XFA_Element::TextEdit: - m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>(); - return; - case XFA_Element::Image: - m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>(); - return; - case XFA_Element::ImageEdit: - m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>(); - return; - default: - break; - } - if (GetElementType() == XFA_Element::Field) { - m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>(); - return; - } - m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>(); -} - -void CXFA_WidgetAcc::StartTextLayout(FX_FLOAT& fCalcWidth, - FX_FLOAT& fCalcHeight) { - LoadText(); - CXFA_TextLayout* pTextLayout = - static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); - FX_FLOAT fTextHeight = 0; - if (fCalcWidth > 0 && fCalcHeight > 0) { - FX_FLOAT fWidth = GetWidthWithoutMargin(fCalcWidth); - pTextLayout->StartLayout(fWidth); - fTextHeight = fCalcHeight; - fTextHeight = GetHeightWithoutMargin(fTextHeight); - pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); - return; - } - if (fCalcWidth > 0 && fCalcHeight < 0) { - FX_FLOAT fWidth = GetWidthWithoutMargin(fCalcWidth); - pTextLayout->StartLayout(fWidth); - } - if (fCalcWidth < 0 && fCalcHeight < 0) { - FX_FLOAT fMaxWidth = -1; - bool bRet = GetWidth(fMaxWidth); - if (bRet) { - FX_FLOAT fWidth = GetWidthWithoutMargin(fMaxWidth); - pTextLayout->StartLayout(fWidth); - } else { - FX_FLOAT fWidth = pTextLayout->StartLayout(fMaxWidth); - fMaxWidth = CalculateWidgetAutoWidth(fWidth); - fWidth = GetWidthWithoutMargin(fMaxWidth); - pTextLayout->StartLayout(fWidth); - } - fCalcWidth = fMaxWidth; - } - if (m_pLayoutData->m_fWidgetHeight < 0) { - m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight(); - m_pLayoutData->m_fWidgetHeight = - CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight); - } - fTextHeight = m_pLayoutData->m_fWidgetHeight; - fTextHeight = GetHeightWithoutMargin(fTextHeight); - pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); - fCalcHeight = m_pLayoutData->m_fWidgetHeight; -} -bool CXFA_WidgetAcc::LoadCaption() { - InitLayoutData(); - return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) - ->LoadCaption(this); -} -CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() { - return m_pLayoutData - ? static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) - ->m_pCapTextLayout.get() - : nullptr; -} -CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() { - return m_pLayoutData - ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get()) - ->GetTextLayout() - : nullptr; -} -CFX_DIBitmap* CXFA_WidgetAcc::GetImageImage() { - return m_pLayoutData - ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) - ->m_pDIBitmap - : nullptr; -} -CFX_DIBitmap* CXFA_WidgetAcc::GetImageEditImage() { - return m_pLayoutData - ? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) - ->m_pDIBitmap - : nullptr; -} - -void CXFA_WidgetAcc::SetImageImage(CFX_DIBitmap* newImage) { - CXFA_ImageLayoutData* pData = - static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); - if (pData->m_pDIBitmap == newImage) - return; - - if (pData->m_pDIBitmap && !pData->m_bNamedImage) - delete pData->m_pDIBitmap; - - pData->m_pDIBitmap = newImage; -} - -void CXFA_WidgetAcc::SetImageEditImage(CFX_DIBitmap* newImage) { - CXFA_ImageEditData* pData = - static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); - if (pData->m_pDIBitmap == newImage) - return; - - if (pData->m_pDIBitmap && !pData->m_bNamedImage) - delete pData->m_pDIBitmap; - - pData->m_pDIBitmap = newImage; -} - -CXFA_WidgetLayoutData* CXFA_WidgetAcc::GetWidgetLayoutData() { - return m_pLayoutData.get(); -} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_WidgetAcc::GetFDEFont() { - CFX_WideStringC wsFontName = L"Courier"; - uint32_t dwFontStyle = 0; - if (CXFA_Font font = GetFont()) { - if (font.IsBold()) - dwFontStyle |= FX_FONTSTYLE_Bold; - if (font.IsItalic()) - dwFontStyle |= FX_FONTSTYLE_Italic; - font.GetTypeface(wsFontName); - } - - auto pDoc = GetDoc(); - return pDoc->GetApp()->GetXFAFontMgr()->GetFont(pDoc, wsFontName, - dwFontStyle); -} -FX_FLOAT CXFA_WidgetAcc::GetFontSize() { - FX_FLOAT fFontSize = 10.0f; - if (CXFA_Font font = GetFont()) { - fFontSize = font.GetFontSize(); - } - return fFontSize < 0.1f ? 10.0f : fFontSize; -} -FX_FLOAT CXFA_WidgetAcc::GetLineHeight() { - FX_FLOAT fLineHeight = 0; - if (CXFA_Para para = GetPara()) { - fLineHeight = para.GetLineHeight(); - } - if (fLineHeight < 1) { - fLineHeight = GetFontSize() * 1.2f; - } - return fLineHeight; -} -FX_ARGB CXFA_WidgetAcc::GetTextColor() { - if (CXFA_Font font = GetFont()) { - return font.GetColor(); - } - return 0xFF000000; -} -CXFA_Node* CXFA_TextProvider::GetTextNode(bool& bRichText) { - bRichText = false; - if (m_pTextNode) { - if (m_pTextNode->GetElementType() == XFA_Element::ExData) { - CFX_WideString wsContentType; - m_pTextNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, - false); - if (wsContentType == L"text/html") { - bRichText = true; - } - } - return m_pTextNode; - } - if (m_eType == XFA_TEXTPROVIDERTYPE_Text) { - CXFA_Node* pElementNode = m_pWidgetAcc->GetNode(); - CXFA_Node* pValueNode = pElementNode->GetChild(0, XFA_Element::Value); - if (!pValueNode) { - return nullptr; - } - CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) { - CFX_WideString wsContentType; - pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false); - if (wsContentType == L"text/html") { - bRichText = true; - } - } - return pChildNode; - } else if (m_eType == XFA_TEXTPROVIDERTYPE_Datasets) { - CXFA_Node* pBind = m_pWidgetAcc->GetDatasets(); - CFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); - ASSERT(pXMLNode); - for (CFDE_XMLNode* pXMLChild = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pXMLChild->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pElement = static_cast<CFDE_XMLElement*>(pXMLChild); - if (XFA_RecognizeRichText(pElement)) { - bRichText = true; - } - } - } - return pBind; - } else if (m_eType == XFA_TEXTPROVIDERTYPE_Caption) { - CXFA_Node* pCaptionNode = - m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Caption); - if (!pCaptionNode) { - return nullptr; - } - CXFA_Node* pValueNode = pCaptionNode->GetChild(0, XFA_Element::Value); - if (!pValueNode) { - return nullptr; - } - CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) { - CFX_WideString wsContentType; - pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false); - if (wsContentType == L"text/html") { - bRichText = true; - } - } - return pChildNode; - } - CXFA_Node* pItemNode = - m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Items); - if (!pItemNode) { - return nullptr; - } - CXFA_Node* pNode = pItemNode->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pNode) { - CFX_WideStringC wsName; - pNode->TryCData(XFA_ATTRIBUTE_Name, wsName); - if (m_eType == XFA_TEXTPROVIDERTYPE_Rollover && wsName == L"rollover") { - return pNode; - } - if (m_eType == XFA_TEXTPROVIDERTYPE_Down && wsName == L"down") { - return pNode; - } - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - return nullptr; -} -CXFA_Para CXFA_TextProvider::GetParaNode() { - if (m_eType == XFA_TEXTPROVIDERTYPE_Text) { - return m_pWidgetAcc->GetPara(); - } - CXFA_Node* pNode = m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Caption); - return CXFA_Para(pNode->GetChild(0, XFA_Element::Para)); -} -CXFA_Font CXFA_TextProvider::GetFontNode() { - if (m_eType == XFA_TEXTPROVIDERTYPE_Text) { - return m_pWidgetAcc->GetFont(); - } - CXFA_Node* pNode = m_pWidgetAcc->GetNode()->GetChild(0, XFA_Element::Caption); - pNode = pNode->GetChild(0, XFA_Element::Font); - if (pNode) { - return CXFA_Font(pNode); - } - return m_pWidgetAcc->GetFont(); -} -bool CXFA_TextProvider::IsCheckButtonAndAutoWidth() { - XFA_Element eType = m_pWidgetAcc->GetUIType(); - if (eType == XFA_Element::CheckButton) { - FX_FLOAT fWidth = 0; - return !m_pWidgetAcc->GetWidth(fWidth); - } - return false; -} -bool CXFA_TextProvider::GetEmbbedObj(bool bURI, - bool bRaw, - const CFX_WideString& wsAttr, - CFX_WideString& wsValue) { - if (m_eType != XFA_TEXTPROVIDERTYPE_Text) { - return false; - } - if (bURI) { - CXFA_Node* pWidgetNode = m_pWidgetAcc->GetNode(); - CXFA_Node* pParent = pWidgetNode->GetNodeItem(XFA_NODEITEM_Parent); - CXFA_Document* pDocument = pWidgetNode->GetDocument(); - CXFA_Node* pIDNode = nullptr; - CXFA_WidgetAcc* pEmbAcc = nullptr; - if (pParent) { - pIDNode = pDocument->GetNodeByID(pParent, wsAttr.AsStringC()); - } - if (!pIDNode) { - pIDNode = pDocument->GetNodeByID( - ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)), - wsAttr.AsStringC()); - } - if (pIDNode) { - pEmbAcc = static_cast<CXFA_WidgetAcc*>(pIDNode->GetWidgetData()); - } - if (pEmbAcc) { - pEmbAcc->GetValue(wsValue, XFA_VALUEPICTURE_Display); - return true; - } - } - return false; -} diff --git a/xfa/fxfa/app/xfa_ffwidgetacc.h b/xfa/fxfa/app/xfa_ffwidgetacc.h deleted file mode 100644 index 2daa35e6cd57afed5a14fa051af652733a91812a..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffwidgetacc.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FFWIDGETACC_H_ -#define XFA_FXFA_APP_XFA_FFWIDGETACC_H_ - -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/app/cxfa_textlayout.h" -#include "xfa/fxfa/fxfa_widget.h" -#include "xfa/fxfa/parser/cxfa_font.h" -#include "xfa/fxfa/parser/cxfa_para.h" - -class CXFA_FFDoc; -class CXFA_Node; - -enum XFA_TEXTPROVIDERTYPE { - XFA_TEXTPROVIDERTYPE_Text, - XFA_TEXTPROVIDERTYPE_Datasets, - XFA_TEXTPROVIDERTYPE_Caption, - XFA_TEXTPROVIDERTYPE_Rollover, - XFA_TEXTPROVIDERTYPE_Down, -}; - -class CXFA_TextProvider { - public: - CXFA_TextProvider(CXFA_WidgetAcc* pWidgetAcc, - XFA_TEXTPROVIDERTYPE eType, - CXFA_Node* pTextNode = nullptr) - : m_pWidgetAcc(pWidgetAcc), m_eType(eType), m_pTextNode(pTextNode) { - ASSERT(m_pWidgetAcc); - } - ~CXFA_TextProvider() {} - - CXFA_Node* GetTextNode(bool& bRichText); - CXFA_Para GetParaNode(); - CXFA_Font GetFontNode(); - bool IsCheckButtonAndAutoWidth(); - CXFA_FFDoc* GetDocNode() { return m_pWidgetAcc->GetDoc(); } - bool GetEmbbedObj(bool bURI, - bool bRaw, - const CFX_WideString& wsAttr, - CFX_WideString& wsValue); - - protected: - CXFA_WidgetAcc* m_pWidgetAcc; - XFA_TEXTPROVIDERTYPE m_eType; - CXFA_Node* m_pTextNode; -}; - -#endif // XFA_FXFA_APP_XFA_FFWIDGETACC_H_ diff --git a/xfa/fxfa/app/xfa_ffwidgethandler.cpp b/xfa/fxfa/app/xfa_ffwidgethandler.cpp deleted file mode 100644 index 2fddfb615691c62fd484845a121af810d62e465b..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_ffwidgethandler.cpp +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_ffwidgethandler.h" - -#include <vector> - -#include "xfa/fxfa/app/xfa_ffchoicelist.h" -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/app/xfa_fwladapter.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/xfa_ffdoc.h" -#include "xfa/fxfa/xfa_ffdocview.h" -#include "xfa/fxfa/xfa_ffwidget.h" - -CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView) - : m_pDocView(pDocView) {} - -CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() {} - -bool CXFA_FFWidgetHandler::OnMouseEnter(CXFA_FFWidget* hWidget) { - m_pDocView->LockUpdate(); - bool bRet = hWidget->OnMouseEnter(); - m_pDocView->UnlockUpdate(); - m_pDocView->UpdateDocView(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnMouseExit(CXFA_FFWidget* hWidget) { - m_pDocView->LockUpdate(); - bool bRet = hWidget->OnMouseExit(); - m_pDocView->UnlockUpdate(); - m_pDocView->UpdateDocView(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnLButtonDown(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - m_pDocView->LockUpdate(); - bool bRet = hWidget->OnLButtonDown(dwFlags, hWidget->Rotate2Normal(point)); - if (bRet && m_pDocView->SetFocus(hWidget)) { - m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget( - m_pDocView->GetDoc(), hWidget); - } - m_pDocView->UnlockUpdate(); - m_pDocView->UpdateDocView(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnLButtonUp(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - m_pDocView->LockUpdate(); - m_pDocView->m_bLayoutEvent = true; - bool bRet = hWidget->OnLButtonUp(dwFlags, hWidget->Rotate2Normal(point)); - m_pDocView->UnlockUpdate(); - m_pDocView->UpdateDocView(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnLButtonDblClk(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - bool bRet = hWidget->OnLButtonDblClk(dwFlags, hWidget->Rotate2Normal(point)); - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnMouseMove(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - bool bRet = hWidget->OnMouseMove(dwFlags, hWidget->Rotate2Normal(point)); - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnMouseWheel(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point) { - bool bRet = - hWidget->OnMouseWheel(dwFlags, zDelta, hWidget->Rotate2Normal(point)); - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnRButtonDown(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - bool bRet = hWidget->OnRButtonDown(dwFlags, hWidget->Rotate2Normal(point)); - if (bRet && m_pDocView->SetFocus(hWidget)) { - m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget( - m_pDocView->GetDoc(), hWidget); - } - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnRButtonUp(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - bool bRet = hWidget->OnRButtonUp(dwFlags, hWidget->Rotate2Normal(point)); - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnRButtonDblClk(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point) { - bool bRet = hWidget->OnRButtonDblClk(dwFlags, hWidget->Rotate2Normal(point)); - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnKeyDown(CXFA_FFWidget* hWidget, - uint32_t dwKeyCode, - uint32_t dwFlags) { - bool bRet = hWidget->OnKeyDown(dwKeyCode, dwFlags); - m_pDocView->RunInvalidate(); - m_pDocView->UpdateDocView(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnKeyUp(CXFA_FFWidget* hWidget, - uint32_t dwKeyCode, - uint32_t dwFlags) { - bool bRet = hWidget->OnKeyUp(dwKeyCode, dwFlags); - m_pDocView->RunInvalidate(); - return bRet; -} - -bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget, - uint32_t dwChar, - uint32_t dwFlags) { - bool bRet = hWidget->OnChar(dwChar, dwFlags); - m_pDocView->RunInvalidate(); - return bRet; -} - -FWL_WidgetHit CXFA_FFWidgetHandler::OnHitTest(CXFA_FFWidget* hWidget, - const CFX_PointF& point) { - if (!(hWidget->GetStatus() & XFA_WidgetStatus_Visible)) - return FWL_WidgetHit::Unknown; - return hWidget->OnHitTest(hWidget->Rotate2Normal(point)); -} - -bool CXFA_FFWidgetHandler::OnSetCursor(CXFA_FFWidget* hWidget, - const CFX_PointF& point) { - return hWidget->OnSetCursor(hWidget->Rotate2Normal(point)); -} - -void CXFA_FFWidgetHandler::RenderWidget(CXFA_FFWidget* hWidget, - CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - bool bHighlight) { - hWidget->RenderWidget(pGS, pMatrix, - bHighlight ? XFA_WidgetStatus_Highlight : 0); -} - -bool CXFA_FFWidgetHandler::HasEvent(CXFA_WidgetAcc* pWidgetAcc, - XFA_EVENTTYPE eEventType) { - if (!pWidgetAcc || eEventType == XFA_EVENT_Unknown) - return false; - if (pWidgetAcc->GetElementType() == XFA_Element::Draw) - return false; - - switch (eEventType) { - case XFA_EVENT_Calculate: { - CXFA_Calculate calc = pWidgetAcc->GetCalculate(); - if (!calc) - return false; - if (calc.GetScript()) - return true; - return false; - } - case XFA_EVENT_Validate: { - CXFA_Validate val = pWidgetAcc->GetValidate(); - if (!val) - return false; - if (val.GetScript()) - return true; - return false; - } - default: - break; - } - CXFA_NodeArray eventArray; - return pWidgetAcc->GetEventByActivity(gs_EventActivity[eEventType], - eventArray) > 0; -} - -int32_t CXFA_FFWidgetHandler::ProcessEvent(CXFA_WidgetAcc* pWidgetAcc, - CXFA_EventParam* pParam) { - if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) - return XFA_EVENTERROR_NotExist; - if (!pWidgetAcc || pWidgetAcc->GetElementType() == XFA_Element::Draw) - return XFA_EVENTERROR_NotExist; - - switch (pParam->m_eType) { - case XFA_EVENT_Calculate: - return pWidgetAcc->ProcessCalculate(); - case XFA_EVENT_Validate: - if (m_pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled( - m_pDocView->GetDoc())) { - return pWidgetAcc->ProcessValidate(); - } - return XFA_EVENTERROR_Disabled; - case XFA_EVENT_InitCalculate: { - CXFA_Calculate calc = pWidgetAcc->GetCalculate(); - if (!calc) - return XFA_EVENTERROR_NotExist; - if (pWidgetAcc->GetNode()->IsUserInteractive()) - return XFA_EVENTERROR_Disabled; - - CXFA_Script script = calc.GetScript(); - return pWidgetAcc->ExecuteScript(script, pParam); - } - default: - break; - } - int32_t iRet = - pWidgetAcc->ProcessEvent(gs_EventActivity[pParam->m_eType], pParam); - return iRet; -} - -CXFA_FFWidget* CXFA_FFWidgetHandler::CreateWidget(CXFA_FFWidget* hParent, - XFA_WIDGETTYPE eType, - CXFA_FFWidget* hBefore) { - CXFA_Node* pParentFormItem = - hParent ? hParent->GetDataAcc()->GetNode() : nullptr; - CXFA_Node* pBeforeFormItem = - hBefore ? hBefore->GetDataAcc()->GetNode() : nullptr; - CXFA_Node* pNewFormItem = - CreateWidgetFormItem(eType, pParentFormItem, pBeforeFormItem); - if (!pNewFormItem) - return nullptr; - - pNewFormItem->GetTemplateNode()->SetFlag(XFA_NodeFlag_Initialized, true); - pNewFormItem->SetFlag(XFA_NodeFlag_Initialized, true); - m_pDocView->RunLayout(); - CXFA_LayoutItem* pLayout = - m_pDocView->GetXFALayout()->GetLayoutItem(pNewFormItem); - return static_cast<CXFA_FFWidget*>(pLayout); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateWidgetFormItem( - XFA_WIDGETTYPE eType, - CXFA_Node* pParent, - CXFA_Node* pBefore) const { - switch (eType) { - case XFA_WIDGETTYPE_Barcode: - return nullptr; - case XFA_WIDGETTYPE_PushButton: - return CreatePushButton(pParent, pBefore); - case XFA_WIDGETTYPE_CheckButton: - return CreateCheckButton(pParent, pBefore); - case XFA_WIDGETTYPE_ExcludeGroup: - return CreateExclGroup(pParent, pBefore); - case XFA_WIDGETTYPE_RadioButton: - return CreateRadioButton(pParent, pBefore); - case XFA_WIDGETTYPE_Arc: - return CreateArc(pParent, pBefore); - case XFA_WIDGETTYPE_Rectangle: - return CreateRectangle(pParent, pBefore); - case XFA_WIDGETTYPE_Image: - return CreateImage(pParent, pBefore); - case XFA_WIDGETTYPE_Line: - return CreateLine(pParent, pBefore); - case XFA_WIDGETTYPE_Text: - return CreateText(pParent, pBefore); - case XFA_WIDGETTYPE_DatetimeEdit: - return CreateDatetimeEdit(pParent, pBefore); - case XFA_WIDGETTYPE_DecimalField: - return CreateDecimalField(pParent, pBefore); - case XFA_WIDGETTYPE_NumericField: - return CreateNumericField(pParent, pBefore); - case XFA_WIDGETTYPE_Signature: - return CreateSignature(pParent, pBefore); - case XFA_WIDGETTYPE_TextEdit: - return CreateTextEdit(pParent, pBefore); - case XFA_WIDGETTYPE_DropdownList: - return CreateDropdownList(pParent, pBefore); - case XFA_WIDGETTYPE_ListBox: - return CreateListBox(pParent, pBefore); - case XFA_WIDGETTYPE_ImageField: - return CreateImageField(pParent, pBefore); - case XFA_WIDGETTYPE_PasswordEdit: - return CreatePasswordEdit(pParent, pBefore); - case XFA_WIDGETTYPE_Subform: - return CreateSubform(pParent, pBefore); - default: - return nullptr; - } -} - -CXFA_Node* CXFA_FFWidgetHandler::CreatePushButton(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateField(XFA_Element::Button, pParent, pBefore); - CXFA_Node* pCaption = CreateCopyNode(XFA_Element::Caption, pField); - CXFA_Node* pValue = CreateCopyNode(XFA_Element::Value, pCaption); - CXFA_Node* pText = CreateCopyNode(XFA_Element::Text, pValue); - pText->SetContent(L"Button", L"Button", false); - - CXFA_Node* pPara = CreateCopyNode(XFA_Element::Para, pCaption); - pPara->SetEnum(XFA_ATTRIBUTE_VAlign, XFA_ATTRIBUTEENUM_Middle, false); - pPara->SetEnum(XFA_ATTRIBUTE_HAlign, XFA_ATTRIBUTEENUM_Center, false); - CreateFontNode(pCaption); - - CXFA_Node* pBorder = CreateCopyNode(XFA_Element::Border, pField); - pBorder->SetEnum(XFA_ATTRIBUTE_Hand, XFA_ATTRIBUTEENUM_Right, false); - - CXFA_Node* pEdge = CreateCopyNode(XFA_Element::Edge, pBorder); - pEdge->SetEnum(XFA_ATTRIBUTE_Stroke, XFA_ATTRIBUTEENUM_Raised, false); - - CXFA_Node* pFill = CreateCopyNode(XFA_Element::Fill, pBorder); - CXFA_Node* pColor = CreateCopyNode(XFA_Element::Color, pFill); - pColor->SetCData(XFA_ATTRIBUTE_Value, L"212, 208, 200", false); - - CXFA_Node* pBind = CreateCopyNode(XFA_Element::Bind, pField); - pBind->SetEnum(XFA_ATTRIBUTE_Match, XFA_ATTRIBUTEENUM_None); - - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateCheckButton(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateField(XFA_Element::CheckButton, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateExclGroup(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateFormItem(XFA_Element::ExclGroup, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateRadioButton(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateField(XFA_Element::CheckButton, pParent, pBefore); - CXFA_Node* pUi = pField->GetFirstChildByClass(XFA_Element::Ui); - CXFA_Node* pWidget = pUi->GetFirstChildByClass(XFA_Element::CheckButton); - pWidget->SetEnum(XFA_ATTRIBUTE_Shape, XFA_ATTRIBUTEENUM_Round); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateDatetimeEdit(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateField(XFA_Element::DateTimeEdit, pParent, pBefore); - CreateValueNode(XFA_Element::Date, pField); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateDecimalField(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateNumericField(pParent, pBefore); - CreateValueNode(XFA_Element::Decimal, pField); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateNumericField(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateField(XFA_Element::NumericEdit, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateSignature(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateField(XFA_Element::Signature, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateTextEdit(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateField(XFA_Element::TextEdit, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateDropdownList(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateField(XFA_Element::ChoiceList, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateListBox(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateDropdownList(pParent, pBefore); - CXFA_Node* pUi = pField->GetNodeItem(XFA_NODEITEM_FirstChild); - CXFA_Node* pListBox = pUi->GetNodeItem(XFA_NODEITEM_FirstChild); - pListBox->SetEnum(XFA_ATTRIBUTE_Open, XFA_ATTRIBUTEENUM_Always); - pListBox->SetEnum(XFA_ATTRIBUTE_CommitOn, XFA_ATTRIBUTEENUM_Exit); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateImageField(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateField(XFA_Element::ImageEdit, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreatePasswordEdit(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateField(XFA_Element::PasswordEdit, pParent, pBefore); - CXFA_Node* pBind = CreateCopyNode(XFA_Element::Bind, pField); - pBind->SetEnum(XFA_ATTRIBUTE_Match, XFA_ATTRIBUTEENUM_None, false); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateField(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateFormItem(XFA_Element::Field, pParent, pBefore); - CreateCopyNode(eElement, CreateCopyNode(XFA_Element::Ui, pField)); - CreateFontNode(pField); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateArc(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateDraw(XFA_Element::Arc, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateRectangle(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateDraw(XFA_Element::Rectangle, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateImage(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateDraw(XFA_Element::Image, pParent, pBefore); - CreateCopyNode(XFA_Element::ImageEdit, - CreateCopyNode(XFA_Element::Ui, pField)); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateLine(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateDraw(XFA_Element::Line, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateText(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pField = CreateDraw(XFA_Element::Text, pParent, pBefore); - CreateCopyNode(XFA_Element::TextEdit, - CreateCopyNode(XFA_Element::Ui, pField)); - CreateFontNode(pField); - return pField; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateDraw(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pDraw = CreateFormItem(XFA_Element::Draw, pParent, pBefore); - CreateValueNode(eElement, pDraw); - return pDraw; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateSubform(CXFA_Node* pParent, - CXFA_Node* pBefore) const { - return CreateFormItem(XFA_Element::Subform, pParent, pBefore); -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateFormItem(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pTemplateParent = pParent ? pParent->GetTemplateNode() : nullptr; - CXFA_Node* pNewFormItem = pTemplateParent->CloneTemplateToForm(false); - if (pParent) - pParent->InsertChild(pNewFormItem, pBefore); - return pNewFormItem; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateCopyNode(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Node* pTemplateParent = pParent ? pParent->GetTemplateNode() : nullptr; - CXFA_Node* pNewNode = - CreateTemplateNode(eElement, pTemplateParent, - pBefore ? pBefore->GetTemplateNode() : nullptr) - ->Clone(false); - if (pParent) - pParent->InsertChild(pNewNode, pBefore); - return pNewNode; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateTemplateNode(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const { - CXFA_Document* pXFADoc = GetXFADoc(); - CXFA_Node* pNewTemplateNode = - pXFADoc->CreateNode(XFA_XDPPACKET_Template, eElement); - if (pParent) - pParent->InsertChild(pNewTemplateNode, pBefore); - return pNewTemplateNode; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateFontNode(CXFA_Node* pParent) const { - CXFA_Node* pFont = CreateCopyNode(XFA_Element::Font, pParent); - pFont->SetCData(XFA_ATTRIBUTE_Typeface, L"Myriad Pro", false); - return pFont; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateMarginNode(CXFA_Node* pParent, - uint32_t dwFlags, - FX_FLOAT fInsets[4]) const { - CXFA_Node* pMargin = CreateCopyNode(XFA_Element::Margin, pParent); - if (dwFlags & 0x01) - pMargin->SetMeasure(XFA_ATTRIBUTE_LeftInset, - CXFA_Measurement(fInsets[0], XFA_UNIT_Pt), false); - if (dwFlags & 0x02) - pMargin->SetMeasure(XFA_ATTRIBUTE_TopInset, - CXFA_Measurement(fInsets[1], XFA_UNIT_Pt), false); - if (dwFlags & 0x04) - pMargin->SetMeasure(XFA_ATTRIBUTE_RightInset, - CXFA_Measurement(fInsets[2], XFA_UNIT_Pt), false); - if (dwFlags & 0x08) - pMargin->SetMeasure(XFA_ATTRIBUTE_BottomInset, - CXFA_Measurement(fInsets[3], XFA_UNIT_Pt), false); - return pMargin; -} - -CXFA_Node* CXFA_FFWidgetHandler::CreateValueNode(XFA_Element eValue, - CXFA_Node* pParent) const { - CXFA_Node* pValue = CreateCopyNode(XFA_Element::Value, pParent); - CreateCopyNode(eValue, pValue); - return pValue; -} - -CXFA_Document* CXFA_FFWidgetHandler::GetObjFactory() const { - return GetXFADoc(); -} - -CXFA_Document* CXFA_FFWidgetHandler::GetXFADoc() const { - return m_pDocView->GetDoc()->GetXFADoc(); -} - diff --git a/xfa/fxfa/app/xfa_fontmgr.cpp b/xfa/fxfa/app/xfa_fontmgr.cpp deleted file mode 100644 index 5db389663a6e7fc1bfeacd79dd343a90132da34e..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fontmgr.cpp +++ /dev/null @@ -1,2055 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_fontmgr.h" - -#include <algorithm> -#include <memory> -#include <utility> - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffdoc.h" - -namespace { - -// The 5 names per entry are: PsName, Normal, Bold, Italic, BoldItalic. -const char* const g_XFAPDFFontName[][5] = { - {"Adobe PI Std", "AdobePIStd", "AdobePIStd", "AdobePIStd", "AdobePIStd"}, - {"Myriad Pro Light", "MyriadPro-Light", "MyriadPro-Semibold", - "MyriadPro-LightIt", "MyriadPro-SemiboldIt"}, -}; - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -const XFA_FONTINFO g_XFAFontsMap[] = { - {0x01d5d33e, L"SimSun", L"Arial", 0, 936}, - {0x01e4f102, L"YouYuan", L"Arial", 1, 936}, - {0x030549dc, L"LiSu", L"Arial", 1, 936}, - {0x032edd44, L"Simhei", L"Arial", 1, 936}, - {0x03eac6fc, L"PoorRichard-Regular", L"Arial", 2, 1252}, - {0x03ed90e6, L"Nina", L"Arial", 0, 1252}, - {0x077b56b3, L"KingsoftPhoneticPlain", L"Arial", 0, 1252}, - {0x078ed524, L"MicrosoftSansSerif", L"Arial", 0, 1252}, - {0x089b18a9, L"Arial", L"Arial", 0, 1252}, - {0x0b2cad72, L"MonotypeCorsiva", L"Arial", 8, 1252}, - {0x0bb003e7, L"Kartika", L"Arial", 2, 1252}, - {0x0bb469df, L"VinerHandITC", L"Arial", 8, 1252}, - {0x0bc1a851, L"SegoeUI", L"Arial", 0, 1252}, - {0x0c112ebd, L"KozukaGothicPro-VIM", L"Arial", 0, 1252}, - {0x0cfcb9c1, L"AdobeThai", L"Kokila,Arial Narrow", 0, 847}, - {0x0e7de0f9, L"Playbill", L"Arial", 0, 1252}, - {0x0eff47c3, L"STHupo", L"Arial", 0, 936}, - {0x107ad374, L"Constantia", L"Arial", 2, 1252}, - {0x12194c2d, L"KunstlerScript", L"Arial", 8, 1252}, - {0x135ef6a1, L"MinionProSmBd", - L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252}, - {0x158c4049, L"Garamond", L"Arial", 2, 1252}, - {0x160ecb24, L"STZhongsong", L"Arial", 0, 936}, - {0x161ed07e, L"MSGothic", L"Arial", 1, 1252}, - {0x171d1ed1, L"SnapITC-Regular", L"Arial", 0, 1252}, - {0x18d1188f, L"Cambria", L"Arial", 2, 1252}, - {0x18eaf350, L"ArialUnicodeMS", L"Arial", 0, 936}, - {0x1a92d115, L"MingLiU", L"Arial", 1, 1252}, - {0x1cc217c6, L"TrebuchetMS", L"Arial", 0, 1252}, - {0x1d649596, L"BasemicTimes", L"Arial", 0, 1252}, - {0x1e34ee60, L"BellMT", L"Arial", 2, 1252}, - {0x1eb36945, L"CooperBlack", L"Arial", 2, 1252}, - {0x1ef7787d, L"BatangChe", L"Arial", 1, 1252}, - {0x20b3bd3a, L"BrushScriptMT", L"Arial", 8, 1252}, - {0x220877aa, L"Candara", L"Arial", 0, 1252}, - {0x22135007, L"FreestyleScript-Regular", L"Arial", 8, 1252}, - {0x251059c3, L"Chiller", L"Arial", 0, 1252}, - {0x25bed6dd, L"MSReferenceSansSerif", L"Arial", 0, 1252}, - {0x28154c81, L"Parchment-Regular", L"Arial", 8, 1252}, - {0x29711eb9, L"STLiti", L"Arial", 0, 936}, - {0x2b1993b4, L"Basemic", L"Arial", 0, 1252}, - {0x2b316339, L"NiagaraSolid-Reg", L"Arial", 0, 1252}, - {0x2c147529, L"FootlightMTLight", L"Arial", 0, 1252}, - {0x2c198928, L"HarlowSolid", L"Arial", 0, 1252}, - {0x2c6ac6b2, L"LucidaBright", L"Arial", 2, 1252}, - {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"Arial", 0, 1252}, - {0x2d5a47b0, L"STCaiyun", L"Arial", 0, 936}, - {0x2def26bf, L"BernardMT-Condensed", L"Arial", 0, 1252}, - {0x2fd8930b, L"KozukaMinchoPr6NR", L"Arial", 0, 1252}, - {0x3115525a, L"FangSong_GB2312", L"Arial", 0, 1252}, - {0x31327817, L"MyriadPro", - L"Calibri,Corbel,Candara,Cambria Math,Franklin Gothic Medium,Arial " - L"Narrow,Times New Roman", - 0, 1252}, - {0x32244975, L"Helvetica", L"Arial", 0, 1252}, - {0x32ac995c, L"Terminal", L"Arial", 0, 1252}, - {0x338d648a, L"NiagaraEngraved-Reg", L"Arial", 0, 1252}, - {0x33bb65f2, L"Sylfaen", L"Arial", 2, 1252}, - {0x3402c30e, L"MSPMincho", L"Arial", 2, 1252}, - {0x3412bf31, L"SimSun-PUA", L"Arial", 0, 936}, - {0x36eb39b9, L"BerlinSansFB", L"Arial", 0, 1252}, - {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, - {0x3864c4f6, L"HighTowerText", L"Arial", 2, 1252}, - {0x3a257d03, L"FangSong_GB2312", L"Arial", 0, 1252}, - {0x3cdae668, L"FreestyleScript", L"Arial", 8, 1252}, - {0x3d55aed7, L"Jokerman", L"Arial", 0, 1252}, - {0x3d5b4385, L"PMingLiU", L"Arial", 2, 1252}, - {0x3d9b7669, L"EstrangeloEdessa", L"Arial", 0, 1252}, - {0x3e532d74, L"FranklinGothicMedium", L"Arial", 0, 1252}, - {0x3e6aa32d, L"NSimSun", L"Arial", 1, 936}, - {0x3f6c36a8, L"Gautami", L"Arial", 0, 1252}, - {0x3ff32662, L"Chiller-Regular", L"Arial", 0, 1252}, - {0x409de312, L"ModernNo.20", L"Arial", 2, 1252}, - {0x41443c5e, L"Georgia", L"Arial", 2, 1252}, - {0x4160ade5, L"BellGothicStdBlack", - L"Arial,Arial Unicode MS,Book Antiqua,Dotum,Georgia", 0, 1252}, - {0x421976c4, L"Modern-Regular", L"Arial", 2, 1252}, - {0x422a7252, L"Stencil", L"Arial", 0, 1252}, - {0x42c8554f, L"Fixedsys", L"Arial", 0, 1252}, - {0x435cb41d, L"Roman", L"Arial", 0, 1252}, - {0x47882383, L"CourierNew", L"Arial", 1, 1252}, - {0x480a2338, L"BerlinSansFBDemi", L"Arial", 0, 1252}, - {0x480bf7a4, L"CourierStd", L"Courier New,Verdana", 0, 1252}, - {0x481ad6ed, L"VladimirScript", L"Arial", 8, 1252}, - {0x4911577a, L"YouYuan", L"Arial", 1, 936}, - {0x4a788d72, L"STXingkai", L"Arial", 0, 936}, - {0x4bf88566, L"SegoeCondensed", L"Arial", 0, 1252}, - {0x4ccf51a4, L"BerlinSansFB-Reg", L"Arial", 0, 1252}, - {0x4ea967ce, L"GulimChe", L"Arial", 1, 1252}, - {0x4f68bd79, L"LetterGothicStd", L"Courier New,Verdana", 0, 1252}, - {0x51a0d0e6, L"KozukaGothicPr6NM", L"Arial", 0, 1252}, - {0x531b3dea, L"BasemicSymbol", L"Arial", 0, 1252}, - {0x5333fd39, L"CalifornianFB-Reg", L"Arial", 2, 1252}, - {0x53561a54, L"FZYTK--GBK1-0", L"Arial", 0, 936}, - {0x55e0dde6, L"LucidaSansTypewriter", L"Arial", 0, 1252}, - {0x574d4d3d, L"AdobeArabic", L"Arial Narrow", 0, 1252}, - {0x5792e759, L"STKaiti", L"Arial", 0, 936}, - {0x5921978e, L"LucidaSansUnicode", L"Arial", 0, 1252}, - {0x594e2da4, L"Vrinda", L"Arial", 0, 1252}, - {0x59baa9a2, L"KaiTi_GB2312", L"Arial", 0, 1252}, - {0x5cfedf4f, L"BaskOldFace", L"Arial", 0, 1252}, - {0x5f97921c, L"AdobeMyungjoStdM", - L"Batang,Bookman Old Style,Consolas,STZhongsong", 0, 936}, - {0x5fefbfad, L"Batang", L"Arial", 2, 1252}, - {0x605342b9, L"DotumChe", L"Arial", 1, 1252}, - {0x608c5f9a, L"KaiTi_GB2312", L"Arial", 0, 936}, - {0x61efd0d1, L"MaturaMTScriptCapitals", L"Arial", 0, 1252}, - {0x626608a9, L"MVBoli", L"Arial", 0, 1252}, - {0x630501a3, L"SmallFonts", L"Arial", 0, 1252}, - {0x65d0e2a9, L"FZYTK--GBK1-0", L"Arial", 0, 936}, - {0x669f29e1, L"FZSTK--GBK1-0", L"Arial", 0, 936}, - {0x673a9e5f, L"Tunga", L"Arial", 0, 1252}, - {0x691aa4ce, L"NiagaraSolid", L"Arial", 0, 1252}, - {0x696259b7, L"Corbel", L"Arial", 0, 1252}, - {0x696ee9be, L"STXihei", L"Arial", 0, 936}, - {0x6c59cf69, L"Dotum", L"Arial", 0, 1252}, - {0x707fa561, L"Gungsuh", L"Arial", 2, 1252}, - {0x71416bb2, L"ZWAdobeF", L"Arial", 0, 1252}, - {0x71b41801, L"Verdana", L"Arial", 0, 1252}, - {0x73f25e4c, L"PalatinoLinotype", L"Arial", 0, 1252}, - {0x73f4d19f, L"NiagaraEngraved", L"Arial", 0, 1252}, - {0x74001694, L"MyriadProBlack", L"Book Antiqua,Constantia,Dotum,Georgia", 0, - 1252}, - {0x74b14d8f, L"Haettenschweiler", L"Arial", 0, 1252}, - {0x74cb44ee, L"NSimSun", L"Arial", 1, 936}, - {0x76b4d7ff, L"Shruti", L"Arial", 0, 1252}, - {0x788b3533, L"Webdings", L"Arial", 6, 42}, - {0x797dde99, L"MSSerif", L"Arial", 0, 1252}, - {0x7a0f9e9e, L"MSMincho", L"Arial", 1, 1252}, - {0x7b439caf, L"OldEnglishTextMT", L"Arial", 0, 1252}, - {0x8213a433, L"LucidaSans-Typewriter", L"Arial", 0, 1252}, - {0x82fec929, L"AdobeSongStdL", - L"Centaur,Calibri,STSong,Bell MT,Garamond,Times New Roman", 0, 936}, - {0x83581825, L"Modern", L"Arial", 0, 1252}, - {0x835a2823, L"Algerian", L"Arial", 0, 1252}, - {0x83dab9f5, L"Script", L"Arial", 0, 1252}, - {0x847b56da, L"Tahoma", L"Arial", 0, 1252}, - {0x8a783cb2, L"SimSun-PUA", L"Arial", 0, 1252}, - {0x8b5cac0e, L"Onyx", L"Arial", 0, 1252}, - {0x8c6a499e, L"Gulim", L"Arial", 0, 1252}, - {0x8e0af790, L"JuiceITC", L"Arial", 0, 1252}, - {0x8e8d43b2, L"Centaur", L"Arial", 2, 1252}, - {0x8ee4dcca, L"BookshelfSymbol7", L"Arial", 0, 1252}, - {0x90794800, L"BellGothicStdLight", L"Bell MT,Calibri,Times New Roman", 0, - 1252}, - {0x909b516a, L"Century", L"Arial", 2, 1252}, - {0x92ae370d, L"MSOutlook", L"Arial", 4, 42}, - {0x93c9fbf1, L"LucidaFax", L"Arial", 2, 1252}, - {0x9565085e, L"BookAntiqua", L"Arial", 2, 1252}, - {0x9856d95d, L"AdobeMingStdL", L"Arial,Arial Unicode MS,Cambria,BatangChe", - 0, 949}, - {0x9bbadd6b, L"ColonnaMT", L"Arial", 0, 1252}, - {0x9cbd16a4, L"ShowcardGothic-Reg", L"Arial", 0, 1252}, - {0x9d73008e, L"MSSansSerif", L"Arial", 0, 1252}, - {0xa0607db1, L"GungsuhChe", L"Arial", 1, 1252}, - {0xa0bcf6a1, L"LatinWide", L"Arial", 2, 1252}, - {0xa1429b36, L"Symbol", L"Arial", 6, 42}, - {0xa1fa5abc, L"Wingdings2", L"Arial", 6, 42}, - {0xa1fa5abd, L"Wingdings3", L"Arial", 6, 42}, - {0xa427bad4, L"InformalRoman-Regular", L"Arial", 8, 1252}, - {0xa8b92ece, L"FZSTK--GBK1-0", L"Arial", 0, 936}, - {0xa8d83ece, L"CalifornianFB", L"Arial", 2, 1252}, - {0xaa3e082c, L"Kingsoft-Phonetic", L"Arial", 0, 1252}, - {0xaa6bcabe, L"HarlowSolidItalic", L"Arial", 0, 1252}, - {0xade5337c, L"MSUIGothic", L"Arial", 0, 1252}, - {0xb08dd941, L"WideLatin", L"Arial", 2, 1252}, - {0xb207f05d, L"PoorRichard", L"Arial", 2, 1252}, - {0xb3bc492f, L"JuiceITC-Regular", L"Arial", 0, 1252}, - {0xb5545399, L"Marlett", L"Arial", 4, 42}, - {0xb5dd1ebb, L"BritannicBold", L"Arial", 0, 1252}, - {0xb699c1c5, L"LucidaCalligraphy-Italic", L"Arial", 0, 1252}, - {0xb725d629, L"TimesNewRoman", L"Arial", 2, 1252}, - {0xb7eaebeb, L"AdobeHeitiStdR", L"Batang,Century,Dotum", 0, 936}, - {0xbd29c486, L"BerlinSansFBDemi-Bold", L"Arial", 0, 1252}, - {0xbe8a8db4, L"BookshelfSymbolSeven", L"Arial", 0, 1252}, - {0xc16c0118, L"AdobeHebrew", L"Bell MT,Berlin Sans FB,Calibri", 0, 1252}, - {0xc318b0af, L"MyriadProLight", L"Calibri,STFangsong,Times New Roman", 0, - 1252}, - {0xc65e5659, L"CambriaMath", L"Arial", 2, 1252}, - {0xc75c8f05, L"LucidaConsole", L"Arial", 1, 1252}, - {0xca7c35d6, L"Calibri", L"Arial", 0, 1252}, - {0xcb053f53, L"MicrosoftYaHei", L"Arial", 0, 936}, - {0xcb7190f9, L"Magneto-Bold", L"Arial", 0, 1252}, - {0xcca00cc5, L"System", L"Arial", 0, 1252}, - {0xccad6f76, L"Jokerman-Regular", L"Arial", 0, 1252}, - {0xccc5818c, L"EuroSign", L"Arial", 0, 1252}, - {0xcf3d7234, L"LucidaHandwriting-Italic", L"Arial", 0, 1252}, - {0xcf7b8fdb, L"MinionPro", - L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252}, - {0xcfe5755f, L"Simhei", L"Arial", 1, 936}, - {0xd011f4ee, L"MSPGothic", L"Arial", 0, 1252}, - {0xd060e7ef, L"Vivaldi", L"Arial", 8, 1252}, - {0xd07edec1, L"FranklinGothic-Medium", L"Arial", 0, 1252}, - {0xd107243f, L"SimSun", L"Arial", 0, 936}, - {0xd1881562, L"ArialNarrow", L"Arial Narrow", 0, 1252}, - {0xd22b7dce, L"BodoniMTPosterCompressed", L"Arial", 0, 1252}, - {0xd22bfa60, L"ComicSansMS", L"Arial", 8, 1252}, - {0xd3bd0e35, L"Bauhaus93", L"Arial", 0, 1252}, - {0xd429ee7a, L"STFangsong", L"Arial", 0, 936}, - {0xd6679c12, L"BernardMTCondensed", L"Arial", 0, 1252}, - {0xd8e8a027, L"LucidaSans", L"Arial", 0, 1252}, - {0xd9fe7761, L"HighTowerText-Reg", L"Arial", 2, 1252}, - {0xda7e551e, L"STSong", L"Arial", 0, 936}, - {0xdaa6842d, L"STZhongsong", L"Arial", 0, 936}, - {0xdaaab93f, L"STFangsong", L"Arial", 0, 936}, - {0xdaeb0713, L"STSong", L"Arial", 0, 936}, - {0xdafedbef, L"STCaiyun", L"Arial", 0, 936}, - {0xdb00a3d9, L"Broadway", L"Arial", 0, 1252}, - {0xdb1f5ad4, L"STXinwei", L"Arial", 0, 936}, - {0xdb326e7f, L"STKaiti", L"Arial", 0, 936}, - {0xdb69595a, L"STHupo", L"Arial", 0, 936}, - {0xdba0082c, L"STXihei", L"Arial", 0, 936}, - {0xdbd0ab18, L"STXingkai", L"Arial", 0, 936}, - {0xdc1a7db1, L"STLiti", L"Arial", 0, 936}, - {0xdc33075f, L"KristenITC-Regular", L"Arial", 8, 1252}, - {0xdcc7009c, L"Harrington", L"Arial", 0, 1252}, - {0xdd712466, L"ArialBlack", L"Arial", 0, 1252}, - {0xdde87b3e, L"Impact", L"Arial", 0, 1252}, - {0xdf69fb32, L"SnapITC", L"Arial", 0, 1252}, - {0xdf8b25e8, L"CenturyGothic", L"Arial", 0, 1252}, - {0xe0f705c0, L"KristenITC", L"Arial", 8, 1252}, - {0xe1427573, L"Raavi", L"Arial", 0, 1252}, - {0xe2cea0cb, L"Magneto", L"Arial", 0, 1252}, - {0xe36a9e17, L"Ravie", L"Arial", 0, 1252}, - {0xe433f8e2, L"Parchment", L"Arial", 8, 1252}, - {0xe43dff4a, L"Wingdings", L"Arial", 4, 42}, - {0xe4e2c405, L"MTExtra", L"Arial", 6, 42}, - {0xe618cc35, L"InformalRoman", L"Arial", 8, 1252}, - {0xe6c27ffc, L"Mistral", L"Arial", 8, 1252}, - {0xe7ebf4b9, L"Courier", L"Courier New", 0, 1252}, - {0xe8bc4a9d, L"MSReferenceSpecialty", L"Arial", 0, 1252}, - {0xe90fb013, L"TempusSansITC", L"Arial", 0, 1252}, - {0xec637b42, L"Consolas", L"Verdana", 1, 1252}, - {0xed3a683b, L"STXinwei", L"Arial", 0, 936}, - {0xef264cd1, L"LucidaHandwriting", L"Arial", 0, 1252}, - {0xf086bca2, L"BaskervilleOldFace", L"Arial", 0, 1252}, - {0xf1028030, L"Mangal", L"Arial", 2, 1252}, - {0xf1da7eb9, L"ShowcardGothic", L"Arial", 0, 1252}, - {0xf210f06a, L"ArialMT", L"Arial", 0, 1252}, - {0xf477f16a, L"Latha", L"Arial", 0, 1252}, - {0xf616f3dd, L"LiSu", L"Arial", 1, 936}, - {0xfa479aa6, L"MicrosoftYaHei", L"Arial", 0, 936}, - {0xfcd19697, L"BookmanOldStyle", L"Arial", 0, 1252}, - {0xfe209a82, L"LucidaCalligraphy", L"Arial", 0, 1252}, - {0xfef135f8, L"AdobeHeitiStd-Regular", L"Batang,Century,Dotum", 0, 936}, -}; -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ -const XFA_FONTINFO g_XFAFontsMap[] = { - {0x01d5d33e, L"SimSun", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " - L"PL UMing TW MBE", - 0, 936}, - {0x01e4f102, L"YouYuan", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " - L"PL UMing TW MBE", - 1, 936}, - {0x030549dc, L"LiSu", - L"WenQuanYi Zen Hei,WenQuanYi Zen Hei Sharp,WenQuanYi Zen Hei " - L"Mono,WenQuanYi Micro Hei", - 1, 936}, - {0x032edd44, L"Simhei", - L"WenQuanYi Zen Hei,WenQuanYi Zen Hei Sharp,WenQuanYi Zen Hei " - L"Mono,WenQuanYi Micro Hei", - 1, 936}, - {0x03eac6fc, L"PoorRichard-Regular", L"Droid Sans Japanese,FreeSerif", 2, - 1252}, - {0x03ed90e6, L"Nina", L"FreeSerif", 0, 1252}, - {0x077b56b3, L"KingsoftPhoneticPlain", - L"Tibetan Machine Uni,LKLUG,Samyak Gujarati,Droid Sans Thai,Droid Sans " - L"Armenian,Untitled1,utkal,Lohit Oriya", - 0, 1252}, - {0x078ed524, L"MicrosoftSansSerif", - L"Droid Sans Japanese,FreeSerif,WenQuanYi Micro Hei", 0, 1252}, - {0x089b18a9, L"Arial", - L"Droid Sans Japanese,DejaVu Sans Condensed,FreeSerif,WenQuanYi Micro Hei", - 0, 1252}, - {0x0b2cad72, L"MonotypeCorsiva", L"Droid Sans Japanese,FreeSerif", 8, 1252}, - {0x0bb003e7, L"Kartika", - L"FreeSans,Liberation Sans,Liberation Sans Narrow,Nimbus Sans " - L"L,Garuda,FreeSerif,WenQuanYi Micro Hei", - 2, 1252}, - {0x0bb469df, L"VinerHandITC", - L"Droid Sans Japanese,Ubuntu,Liberation Sans,Liberation Serif", 8, 1252}, - {0x0bc1a851, L"SegoeUI", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, - {0x0c112ebd, L"KozukaGothicPro-VIM", L"FreeSerif", 0, 1252}, - {0x0cfcb9c1, L"AdobeThai", L"Droid Sans Japanese,Waree", 0, 847}, - {0x0e7de0f9, L"Playbill", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " - L"Sans Ethiopic,Droid Sans Japanese,FreeSerif", - 0, 1252}, - {0x0eff47c3, L"STHupo", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0x107ad374, L"Constantia", - L"Droid Sans Japanese,FreeSerif,WenQuanYi Micro Hei,Ubuntu", 2, 1252}, - {0x12194c2d, L"KunstlerScript", L"Droid Sans Japanese,Liberation Serif", 8, - 1252}, - {0x135ef6a1, L"MinionProSmBd", L"Liberation Serif", 0, 1252}, - {0x158c4049, L"Garamond", - L"Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 2, 1252}, - {0x160ecb24, L"STZhongsong", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x161ed07e, L"MSGothic", - L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,AR PL " - L"UMing CN,AR PL UMing HK,AR PL UMing TW", - 1, 1252}, - {0x171d1ed1, L"SnapITC-Regular", - L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans L,DejaVu Sans", 0, - 1252}, - {0x18d1188f, L"Cambria", L"Droid Sans Japanese,FreeSerif,FreeMono", 2, - 1252}, - {0x18eaf350, L"ArialUnicodeMS", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x1a92d115, L"MingLiU", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 1, 1252}, - {0x1cc217c6, L"TrebuchetMS", - L"Droid Sans Japanese,Liberation Serif,FreeSerif,Ubuntu", 0, 1252}, - {0x1d649596, L"BasemicTimes", - L"Liberation Serif,Times New Roman,Droid Sans Japanese,FreeSerif,Ubuntu", - 0, 1252}, - {0x1e34ee60, L"BellMT", - L"KacstQurn,Droid Sans Japanese,Ubuntu,Liberation Serif", 2, 1252}, - {0x1eb36945, L"CooperBlack", - L"KacstQurn,Droid Sans Japanese,FreeMono,Liberation Mono, WenQuanYi Micro " - L"Hei Mono", - 2, 1252}, - {0x1ef7787d, L"BatangChe", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing " - L"TW,WenQuanYi Zen Hei,WenQuanYi Micro Hei", - 1, 1252}, - {0x20b3bd3a, L"BrushScriptMT", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans " - L"Japanese,URW Chancery L,Liberation Sans", - 8, 1252}, - {0x220877aa, L"Candara", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, - {0x22135007, L"FreestyleScript-Regular", - L"KacstQurn,Droid Sans Japanese,Liberation Sans", 8, 1252}, - {0x251059c3, L"Chiller", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans " - L"Japanese,Liberation Sans", - 0, 1252}, - {0x25bed6dd, L"MSReferenceSansSerif", - L"DejaVu Sans Condensed,Ubuntu Condensed,Droid Sans Japanese,AR PL UKai " - L"HK", - 0, 1252}, - {0x28154c81, L"Parchment-Regular", L"Droid Sans Japanese,Liberation Sans", - 8, 1252}, - {0x29711eb9, L"STLiti", L"AR PL UKai HK", 0, 936}, - {0x2b1993b4, L"Basemic", - L"Liberation Serif,Droid Sans Japanese,Liberation Sans", 0, 1252}, - {0x2b316339, L"NiagaraSolid-Reg", L"Droid Sans Japanese,Liberation Sans", 0, - 1252}, - {0x2c147529, L"FootlightMTLight", - L"KacstQurn,Droid Sans Japanese,Liberation Sans", 0, 1252}, - {0x2c198928, L"HarlowSolid", - L"KacstQurn,Droid Sans Japanese,Liberation Sans", 0, 1252}, - {0x2c6ac6b2, L"LucidaBright", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " - L"Sans Japanese,Liberation Sans", - 2, 1252}, - {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"DejaVu Sans", 0, 1252}, - {0x2d5a47b0, L"STCaiyun", L"AR PL UKai HK", 0, 936}, - {0x2def26bf, L"BernardMT-Condensed", - L"KacstQurn,Droid Sans Japanese,DejaVu Serif", 0, 1252}, - {0x2fd8930b, L"KozukaMinchoPr6NR", L"DejaVu Serif", 0, 1252}, - {0x3115525a, L"FangSong_GB2312", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 1252}, - {0x31327817, L"MyriadPro", - L"Ubuntu Condensed,Droid Sans Japanese, FreeSerif", 0, 1252}, - {0x32244975, L"Helvetica", - L"Ubuntu,DejaVu Sans Condensed,Liberation Sans,Liberation Sans " - L"Narrow,Nimbus Sans L", - 0, 1252}, - {0x32ac995c, L"Terminal", L"DejaVu Serif", 0, 1252}, - {0x338d648a, L"NiagaraEngraved-Reg", L"Droid Sans Japanese,DejaVu Serif", 0, - 1252}, - {0x33bb65f2, L"Sylfaen", L"Droid Sans Japanese,DejaVu Sans", 2, 1252}, - {0x3402c30e, L"MSPMincho", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 2, - 1252}, - {0x3412bf31, L"SimSun-PUA", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing CN,AR PL UMing HK", 0, - 936}, - {0x36eb39b9, L"BerlinSansFB", - L"Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 0, 1252}, - {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, - {0x3864c4f6, L"HighTowerText", L"Droid Sans Japanese,DejaVu Serif", 2, - 1252}, - {0x3a257d03, L"FangSong_GB2312", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei", 0, 1252}, - {0x3c7d1d07, L"Garamond3LTStd", - L"Droid Sans Japanese,Ubuntu Condensed,DejaVu Sans Condensed,Liberation " - L"Serif,Ubuntu,FreeSerif", - 2, 1252}, - {0x3cdae668, L"FreestyleScript", - L"KacstQurn,Droid Sans Japanese,DejaVu Sans", 8, 1252}, - {0x3d55aed7, L"Jokerman", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, - {0x3d5b4385, L"PMingLiU", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 2, 1252}, - {0x3d9b7669, L"EstrangeloEdessa", L"Droid Sans Japanese,DejaVu Sans", 0, - 1252}, - {0x3e532d74, L"FranklinGothicMedium", L"Droid Sans Japanese,Ubuntu", 0, - 1252}, - {0x3e6aa32d, L"NSimSun", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 1, 936}, - {0x3f6c36a8, L"Gautami", - L"Droid Arabic Naskh,Droid Sans Ethiopic, mry_KacstQurn,Droid Sans " - L"Japanese,FreeSans", - 0, 1252}, - {0x3ff32662, L"Chiller-Regular", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,FreeSans", 0, 1252}, - {0x409de312, L"ModernNo.20", - L"KacstQurn,Droid Sans Japanese,Nimbus Sans L,Nimbus Sans L,FreeSans", 2, - 1252}, - {0x41443c5e, L"Georgia", L"Droid Sans Japanese,FreeSans", 2, 1252}, - {0x4160ade5, L"BellGothicStdBlack", L"FreeSans", 0, 1252}, - {0x421976c4, L"Modern-Regular", L"FreeSans", 2, 1252}, - {0x422a7252, L"Stencil", L"Droid Sans Japanese,FreeSans,Liberation Sans", 0, - 1252}, - {0x42c8554f, L"Fixedsys", L"FreeSerif", 0, 1252}, - {0x435cb41d, L"Roman", L"FreeSerif", 0, 1252}, - {0x47882383, L"CourierNew", - L"FreeMono,WenQuanYi Micro Hei Mono,AR PL UKai CN,AR PL UKai HK,AR PL " - L"UKai TW,AR PL UKai TW MBE,DejaVu Sans", - 1, 1252}, - {0x480a2338, L"BerlinSansFBDemi", L"Droid Sans Japanese,Liberation Serif", - 0, 1252}, - {0x480bf7a4, L"CourierStd", L"DejaVu Sans", 0, 1252}, - {0x481ad6ed, L"VladimirScript", L"Droid Sans Japanese,DejaVu Serif", 8, - 1252}, - {0x4911577a, L"YouYuan", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 1, - 936}, - {0x4a788d72, L"STXingkai", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0x4bf88566, L"SegoeCondensed", L"FreeSerif", 0, 1252}, - {0x4ccf51a4, L"BerlinSansFB-Reg", L"Droid Sans Japanese,Liberation Serif", - 0, 1252}, - {0x4ea967ce, L"GulimChe", - L"WenQuanYi Zen Hei Mono,AR PL UKai CN,AR PL UKai HK,AR PL UKai TW,AR PL " - L"UKai TW MBE", - 1, 1252}, - {0x4f68bd79, L"LetterGothicStd", - L"FreeMono,Liberation Mono,Andale Mono,WenQuanYi Micro Hei Mono", 0, 1252}, - {0x51a0d0e6, L"KozukaGothicPr6NM", L"FreeSerif", 0, 1252}, - {0x531b3dea, L"BasemicSymbol", L"FreeSerif", 0, 1252}, - {0x5333fd39, L"CalifornianFB-Reg", - L"Droid Sans Japanese,URW Chancery L,FreeSerif", 2, 1252}, - {0x53561a54, L"FZYTK--GBK1-0", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x55e0dde6, L"LucidaSansTypewriter", - L"Ubuntu Mono,DejaVu Sans Mono,Nimbus Mono L,Liberation Mono,Courier 10 " - L"Pitch,FreeMono", - 0, 1252}, - {0x574d4d3d, L"AdobeArabic", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, - {0x5792e759, L"STKaiti", L"WenQuanYi Micro Hei Mono", 0, 936}, - {0x5921978e, L"LucidaSansUnicode", L"Droid Sans Japanese,DejaVu Sans", 0, - 1252}, - {0x594e2da4, L"Vrinda", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Arabic " - L"Naskh,mry_KacstQurn,Droid Sans Japanese,FreeSans,FreeSerif", - 0, 1252}, - {0x59baa9a2, L"KaiTi_GB2312", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 1252}, - {0x5cfedf4f, L"BaskOldFace", - L"KacstQurn,Droid Sans Japanese,Ubuntu,Liberation Serif", 0, 1252}, - {0x5e16ac91, L"TrajanPro", - L"Nimbus Sans L,AR PL UMing HK,AR PL UKai HK,AR PL UMing TW,AR PL UMing " - L"TW MBE,DejaVu Sans,DejaVu Serif", - 0, 1252}, - {0x5f388196, L"ITCLegacySansStdMedium", - L"Liberation Serif,FreeSerif,FreeSans,Ubuntu", 0, 1252}, - {0x5f97921c, L"AdobeMyungjoStdM", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x5fefbfad, L"Batang", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 2, 1252}, - {0x605342b9, L"DotumChe", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 1, - 1252}, - {0x608c5f9a, L"KaiTi_GB2312", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x61efd0d1, L"MaturaMTScriptCapitals", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " - L"Sans Japanese,DejaVu Serif,DejaVu Sans", - 0, 1252}, - {0x626608a9, L"MVBoli", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " - L"Ethiopic,Droid Sans Japanese,DejaVu Sans", - 0, 1252}, - {0x630501a3, L"SmallFonts", L"DejaVu Serif", 0, 1252}, - {0x65d0e2a9, L"FZYTK--GBK1-0", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x669f29e1, L"FZSTK--GBK1-0", - L"AR PL UMing CN,AR PL UKai CN, AR PL UMing HK", 0, 936}, - {0x673a9e5f, L"Tunga", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " - L"Japanese,DejaVu Serif", - 0, 1252}, - {0x691aa4ce, L"NiagaraSolid", L"Droid Sans Japanese,DejaVu Serif", 0, 1252}, - {0x696259b7, L"Corbel", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, - {0x696ee9be, L"STXihei", L"WenQuanYi Micro Hei Mono", 0, 936}, - {0x6c59cf69, L"Dotum", L"WenQuanYi Zen Hei Mono", 0, 1252}, - {0x707fa561, L"Gungsuh", L"WenQuanYi Zen Hei Mono", 2, 1252}, - {0x71416bb2, L"ZWAdobeF", - L"KacstArt,KacstBookm,KacstDecorative,KacstDigital,KacstFarsi,KacstLetter," - L"KacstOffice,Dingbats,FreeSerif", - 0, 1252}, - {0x71b41801, L"Verdana", - L"DejaVu Sans Condensed,Ubuntu Condensed,Droid Sans Japanese,DejaVu Sans", - 0, 1252}, - {0x73f25e4c, L"PalatinoLinotype", L"Droid Sans Japanese,FreeSerif", 0, - 1252}, - {0x73f4d19f, L"NiagaraEngraved", L"Droid Sans Japanese,FreeSerif", 0, 1252}, - {0x74001694, L"MyriadProBlack", L"Droid Sans Japanese,AR PL UKai HK", 0, - 1252}, - {0x74b14d8f, L"Haettenschweiler", L"Droid Sans Japanese,DejaVu Serif", 0, - 1252}, - {0x74cb44ee, L"NSimSun", L"WenQuanYi Zen Hei Mono", 1, 936}, - {0x76b4d7ff, L"Shruti", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " - L"Japanese,FreeSans", - 0, 1252}, - {0x788b3533, L"Webdings", L"FreeSans", 6, 42}, - {0x797dde99, L"MSSerif", L"FreeSans", 0, 1252}, - {0x7a0f9e9e, L"MSMincho", - L"WenQuanYi Micro Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", - 1, 1252}, - {0x7b439caf, L"OldEnglishTextMT", - L"Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252}, - {0x8213a433, L"LucidaSans-Typewriter", - L"Ubuntu Mono,Liberation Mono,DejaVu Sans Mono", 0, 1252}, - {0x82fec929, L"AdobeSongStdL", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0x83581825, L"Modern", L"FreeSans", 0, 1252}, - {0x835a2823, L"Algerian", - L"KacstQurn,Droid Sans Japanese,FreeSans,Liberation Sans,Ubuntu", 0, 1252}, - {0x83dab9f5, L"Script", L"FreeSans", 0, 1252}, - {0x847b56da, L"Tahoma", - L"Droid Sans Japanese,DejaVu Sans Condensed,FreeSerif", 0, 1252}, - {0x8a783cb2, L"SimSun-PUA", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 1252}, - {0x8b5cac0e, L"Onyx", L"Droid Sans Japanese,Liberation Sans", 0, 1252}, - {0x8c6a499e, L"Gulim", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 1252}, - {0x8e0af790, L"JuiceITC", L"Droid Sans Japanese,Liberation Sans", 0, 1252}, - {0x8e8d43b2, L"Centaur", - L"KacstQurn,Droid Sans Japanese,Khmer OS,Khmer OS System", 2, 1252}, - {0x8ee4dcca, L"BookshelfSymbol7", L"Liberation Sans", 0, 1252}, - {0x90794800, L"BellGothicStdLight", L"Liberation Sans", 0, 1252}, - {0x909b516a, L"Century", - L"Droid Sans Japanese,Liberation Sans,Liberation Mono,Liberation Serif", 2, - 1252}, - {0x92ae370d, L"MSOutlook", L"Liberation Sans", 4, 42}, - {0x93c9fbf1, L"LucidaFax", - L"KacstQurn,Droid Arabic Naskh,Droid Sans " - L"Ethiopic,mry_KacstQurn,Liberation Sans", - 2, 1252}, - {0x9565085e, L"BookAntiqua", - L"Droid Sans Japanese,Liberation Sans,Liberation Serif", 2, 1252}, - {0x9856d95d, L"AdobeMingStdL", L"AR PL UMing HK", 0, 949}, - {0x9bbadd6b, L"ColonnaMT", - L"KacstQurn,Droid Sans Japanese,Khmer OS,Khmer OS System", 0, 1252}, - {0x9cbd16a4, L"ShowcardGothic-Reg", - L"Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252}, - {0x9d73008e, L"MSSansSerif", L"FreeSerif", 0, 1252}, - {0xa0607db1, L"GungsuhChe", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 1, 1252}, - {0xa0bcf6a1, L"LatinWide", L"FreeSerif", 2, 1252}, - {0xa1429b36, L"Symbol", L"FreeSerif", 6, 42}, - {0xa1fa5abc, L"Wingdings2", L"FreeSerif", 6, 42}, - {0xa1fa5abd, L"Wingdings3", L"FreeSerif", 6, 42}, - {0xa427bad4, L"InformalRoman-Regular", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " - L"Japanese,FreeSerif", - 8, 1252}, - {0xa8b92ece, L"FZSTK--GBK1-0", L"AR PL UMing CN", 0, 936}, - {0xa8d83ece, L"CalifornianFB", L"Droid Sans Japanese,FreeSerif", 2, 1252}, - {0xaa3e082c, L"Kingsoft-Phonetic", - L"Tibetan Machine Uni,LKLUG,Samyak Gujarati,Droid Sans " - L"Thai,utkal,Kedage,Mallige,AR PL UKai CN", - 0, 1252}, - {0xaa6bcabe, L"HarlowSolidItalic", - L"KacstQurn,Droid Sans Japanese,Liberation Serif", 0, 1252}, - {0xade5337c, L"MSUIGothic", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 1252}, - {0xb08dd941, L"WideLatin", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " - L"Sans Japanese,Liberation Serif", - 2, 1252}, - {0xb12765e0, L"ITCLegacySansStdBook", - L"AR PL UMing HK,AR PL UKai HK,FreeSerif,Ubuntu,FreeSans", 0, 1252}, - {0xb207f05d, L"PoorRichard", L"Droid Sans Japanese,Liberation Serif", 2, - 1252}, - {0xb3bc492f, L"JuiceITC-Regular", L"Droid Sans Japanese,Liberation Serif", - 0, 1252}, - {0xb5545399, L"Marlett", L"Liberation Serif", 4, 42}, - {0xb5dd1ebb, L"BritannicBold", - L"KacstQurn,Droid Arabic Naskh,Droid Sans " - L"Ethiopic,mry_KacstQurn,Liberation Serif", - 0, 1252}, - {0xb699c1c5, L"LucidaCalligraphy-Italic", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " - L"Sans Japanese,DejaVu Serif", - 0, 1252}, - {0xb725d629, L"TimesNewRoman", L"Droid Sans Japanese,Liberation Sans", 2, - 1252}, - {0xb7eaebeb, L"AdobeHeitiStdR", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0xbd29c486, L"BerlinSansFBDemi-Bold", L"Droid Sans Japanese,DejaVu Serif", - 0, 1252}, - {0xbe8a8db4, L"BookshelfSymbolSeven", L"DejaVu Sans", 0, 1252}, - {0xc16c0118, L"AdobeHebrew", L"Droid Sans Japanese,Ubuntu,Liberation Serif", - 0, 1252}, - {0xc318b0af, L"MyriadProLight", - L"Droid Sans Japanese,AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 1252}, - {0xc65e5659, L"CambriaMath", L"Droid Sans Japanese,FreeSerif,FreeMono", 2, - 1252}, - {0xc75c8f05, L"LucidaConsole", - L"Liberation Mono,DejaVu Sans Mono,FreeMono,WenQuanYi Micro Hei Mono", 1, - 1252}, - {0xca7c35d6, L"Calibri", L"Droid Sans Japanese,DejaVu Sans", 0, 1252}, - {0xcb053f53, L"MicrosoftYaHei", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0xcb7190f9, L"Magneto-Bold", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " - L"Japanese,DejaVu Serif", - 0, 1252}, - {0xcca00cc5, L"System", L"DejaVu Sans", 0, 1252}, - {0xccad6f76, L"Jokerman-Regular", L"Droid Sans Japanese,DejaVu Sans", 0, - 1252}, - {0xccc5818c, L"EuroSign", L"DejaVu Serif", 0, 1252}, - {0xcf3d7234, L"LucidaHandwriting-Italic", - L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans L,DejaVu Serif", 0, - 1252}, - {0xcf7b8fdb, L"MinionPro", L"DejaVu Sans", 0, 1252}, - {0xcfe5755f, L"Simhei", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 1, 936}, - {0xd011f4ee, L"MSPGothic", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 0, - 1252}, - {0xd060e7ef, L"Vivaldi", - L"KacstQurn,Droid Sans Japanese,Liberation Sans,Ubuntu", 8, 1252}, - {0xd07edec1, L"FranklinGothic-Medium", L"Droid Sans Japanese,Ubuntu", 0, - 1252}, - {0xd107243f, L"SimSun", L"WenQuanYi Zen Hei Mono", 0, 936}, - {0xd1881562, L"ArialNarrow", - L"Liberation Sans Narrow,Droid Sans Japanese,FreeSerif", 0, 1252}, - {0xd22b7dce, L"BodoniMTPosterCompressed", - L"Droid Sans Japanese,DejaVu Serif", 0, 1252}, - {0xd22bfa60, L"ComicSansMS", - L"Droid Sans Japanese,FreeMono,Liberation Mono", 8, 1252}, - {0xd3bd0e35, L"Bauhaus93", - L"KacstQurn,Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252}, - {0xd429ee7a, L"STFangsong", L"WenQuanYi Micro Hei Mono", 0, 936}, - {0xd6679c12, L"BernardMTCondensed", - L"KacstQurn,Droid Sans Japanese,Nimbus Sans L,URW Chancery " - L"L,KacstOne,Liberation Sans", - 0, 1252}, - {0xd8e8a027, L"LucidaSans", - L"Liberation Sans Narrow,Nimbus Sans L,KacstQurn,Droid Arabic Naskh,Droid " - L"Sans Ethiopic,DejaVu Serif Condensed,Liberation Mono,Ubuntu", - 0, 1252}, - {0xd9fe7761, L"HighTowerText-Reg", - L"Droid Sans Japanese,Ubuntu,Liberation Serif", 2, 1252}, - {0xda7e551e, L"STSong", L"WenQuanYi Micro Hei Mono", 0, 936}, - {0xdaa6842d, L"STZhongsong", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0xdaaab93f, L"STFangsong", - L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " - L"Hei,WenQuanYi Zen Hei Sharp", - 0, 936}, - {0xdaeb0713, L"STSong", - L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " - L"Hei,WenQuanYi Zen Hei Sharp", - 0, 936}, - {0xdafedbef, L"STCaiyun", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0xdb00a3d9, L"Broadway", - L"KacstQurn,Droid Sans Japanese,DejaVu Sans,FreeMono,Liberation Mono", 0, - 1252}, - {0xdb1f5ad4, L"STXinwei", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0xdb326e7f, L"STKaiti", - L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " - L"Hei,WenQuanYi Zen Hei Sharp", - 0, 936}, - {0xdb69595a, L"STHupo", - L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " - L"Hei,WenQuanYi Zen Hei Sharp", - 0, 936}, - {0xdba0082c, L"STXihei", - L" WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen " - L"Hei,WenQuanYi Zen Hei Sharp", - 0, 936}, - {0xdbd0ab18, L"STXingkai", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0xdc1a7db1, L"STLiti", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0xdc33075f, L"KristenITC-Regular", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu Sans " - L"Condensed,Ubuntu,Liberation Sans", - 8, 1252}, - {0xdcc7009c, L"Harrington", - L"KacstQurn,Droid Sans Japanese,Liberation Serif,FreeSerif,Ubuntu", 0, - 1252}, - {0xdd712466, L"ArialBlack", - L"Droid Sans Japanese,DejaVu Sans,DejaVu Serif,FreeMono", 0, 1252}, - {0xdde87b3e, L"Impact", L"Droid Sans Japanese,DejaVu Serif", 0, 1252}, - {0xdf69fb32, L"SnapITC", - L"Liberation Sans Narrow,Ubuntu Condensed,DejaVu Sans,DejaVu " - L"Serif,FreeMono", - 0, 1252}, - {0xdf8b25e8, L"CenturyGothic", - L"Droid Sans Japanese,Liberation Mono,Liberation Sans,Liberation Serif", 0, - 1252}, - {0xe0f705c0, L"KristenITC", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu Sans " - L"Condensed,Ubuntu,Liberation Sans", - 8, 1252}, - {0xe1427573, L"Raavi", - L"Droid Arabic Naskh,Droid Sans " - L"Ethiopic,mry_KacstQurn,FreeSerif,Liberation Serif,Khmer OS", - 0, 1252}, - {0xe2cea0cb, L"Magneto", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu " - L"Serif,DejaVu Serif Condensed,DejaVu Sans", - 0, 1252}, - {0xe36a9e17, L"Ravie", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu " - L"Serif,DejaVu Sans,FreeMono", - 0, 1252}, - {0xe433f8e2, L"Parchment", L"Droid Sans Japanese,DejaVu Serif", 8, 1252}, - {0xe43dff4a, L"Wingdings", L"DejaVu Serif", 4, 42}, - {0xe4e2c405, L"MTExtra", L"DejaVu Serif", 6, 42}, - {0xe618cc35, L"InformalRoman", - L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans " - L"Japanese,Nimbus Sans L,DejaVu Sans Condensed,Ubuntu,Liberation Sans", - 8, 1252}, - {0xe6c27ffc, L"Mistral", L"Droid Sans Japanese,DejaVu Serif", 8, 1252}, - {0xe7ebf4b9, L"Courier", L"DejaVu Sans,DejaVu Sans Condensed,FreeSerif", 0, - 1252}, - {0xe8bc4a9d, L"MSReferenceSpecialty", L"DejaVu Serif", 0, 1252}, - {0xe90fb013, L"TempusSansITC", - L"Droid Sans Japanese,Ubuntu,Liberation Serif,FreeSerif", 0, 1252}, - {0xec637b42, L"Consolas", - L"DejaVu Sans Condensed,AR PL UKai CN,AR PL UKai HK,AR PL UKai " - L"TW,FreeSerif,FreeSans", - 1, 1252}, - {0xed3a683b, L"STXinwei", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0, - 936}, - {0xef264cd1, L"LucidaHandwriting", - L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans " - L"L,KacstQurn,Liberation Mono", - 0, 1252}, - {0xf086bca2, L"BaskervilleOldFace", - L"KacstQurn,Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 0, - 1252}, - {0xf1028030, L"Mangal", - L"FreeSans,TSCu_Paranar,Garuda,Liberation Sans,Liberation Sans " - L"Narrow,Nimbus Sans L", - 2, 1252}, - {0xf1da7eb9, L"ShowcardGothic", - L"Droid Sans Japanese,DejaVu Serif Condensed,DejaVu Sans " - L"Condensed,Liberation Sans,Ubuntu", - 0, 1252}, - {0xf210f06a, L"ArialMT", - L"Liberation Sans,Liberation Sans Narrow,FreeSans,Nimbus Sans L,Khmer OS " - L"System,Khmer OS", - 0, 1252}, - {0xf477f16a, L"Latha", - L"Liberation Sans Narrow,Nimbus Sans L,Droid Arabic " - L"Naskh,mry_KacstQurn,FreeSerif,Nimbus Sans L", - 0, 1252}, - {0xf616f3dd, L"LiSu", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " - L"PL UMing TW MBE", - 1, 936}, - {0xfa479aa6, L"MicrosoftYaHei", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, - {0xfcd19697, L"BookmanOldStyle", - L"Droid Sans Japanese,Liberation Mono,Liberation Sans,Liberation Serif", 0, - 1252}, - {0xfe209a82, L"LucidaCalligraphy", - L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid " - L"Sans Japanese,DejaVu Serif,DejaVu Sans,FreeMono", - 0, 1252}, - {0xfef135f8, L"AdobeHeitiStd-Regular", - L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei " - L"Sharp,WenQuanYi Micro Hei", - 0, 936}, -}; -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ -const XFA_FONTINFO g_XFAFontsMap[] = { - {0x01d5d33e, L"SimSun", L"STHeiti,Heiti TC,STFangsong", 0, 936}, - {0x01e4f102, L"YouYuan", L"STHeiti,Heiti TC,STFangsong", 1, 936}, - {0x030549dc, L"LiSu", L"STHeiti,Heiti TC,STFangsong", 1, 936}, - {0x032edd44, L"Simhei", L"STHeiti,Heiti TC,STFangsong", 1, 936}, - {0x03eac6fc, L"PoorRichard-Regular", - L"Noteworthy,Avenir Next Condensed,Impact", 2, 1252}, - {0x03ed90e6, L"Nina", L"Microsoft Sans Serif", 0, 1252}, - {0x077b56b3, L"KingsoftPhoneticPlain", - L"LastResort,Apple " - L"Chancery,STIXVariants,STIXSizeOneSym,STIXSizeOneSym,Apple Braille", - 0, 1252}, - {0x078ed524, L"MicrosoftSansSerif", L"Songti SC,Apple Symbols", 0, 1252}, - {0x089b18a9, L"Arial", - L"Arial Unicode MS,Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x0b2cad72, L"MonotypeCorsiva", L"Arial Narrow,Impact", 8, 1252}, - {0x0bb003e7, L"Kartika", - L"Arial Unicode MS,Microsoft Sans Serif,Arial Narrow,Damascus", 2, 1252}, - {0x0bb469df, L"VinerHandITC", L"Comic Sans MS,Songti SC,STSong", 8, 1252}, - {0x0bc1a851, L"SegoeUI", L"Apple Symbols", 0, 1252}, - {0x0c112ebd, L"KozukaGothicPro-VIM", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0x0cfcb9c1, L"AdobeThai", L"Avenir Next Condensed Ultra Light", 0, 847}, - {0x0e7de0f9, L"Playbill", L"STIXNonUnicode", 0, 1252}, - {0x0eff47c3, L"STHupo", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, - {0x107ad374, L"Constantia", L"Arial Unicode MS,Palatino,Baskerville", 2, - 1252}, - {0x12194c2d, L"KunstlerScript", - L"Avenir Next Condensed Demi Bold,Arial Narrow", 8, 1252}, - {0x135ef6a1, L"MinionProSmBd", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x158c4049, L"Garamond", L"Impact,Arial Narrow", 2, 1252}, - {0x160ecb24, L"STZhongsong", L"STFangsong,Songti SC", 0, 936}, - {0x161ed07e, L"MSGothic", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing " - L"TW,Microsoft Sans Serif,Apple Symbols", - 1, 1252}, - {0x171d1ed1, L"SnapITC-Regular", L"STHeiti,Arial Black", 0, 1252}, - {0x18d1188f, L"Cambria", L"Arial Unicode MS", 2, 1252}, - {0x18eaf350, L"ArialUnicodeMS", L"Microsoft Sans Serif,Apple Symbols", 0, - 936}, - {0x1a92d115, L"MingLiU", L"Heiti SC,STHeiti", 1, 1252}, - {0x1cc217c6, L"TrebuchetMS", L"Damascus,Impact,Arial Narrow", 0, 1252}, - {0x1d649596, L"BasemicTimes", L"Liberation Serif,Impact,Arial Narrow", 0, - 1252}, - {0x1e34ee60, L"BellMT", - L"Papyrus,STIXNonUnicode,Microsoft Sans Serif,Avenir Light", 2, 1252}, - {0x1eb36945, L"CooperBlack", - L"Marion,STIXNonUnicode,Arial Rounded MT Bold,Lucida Grande", 2, 1252}, - {0x1ef7787d, L"BatangChe", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,,AR PL UMing HK,AR PL UMing TW,AR " - L"PL UMing TW MBE,Arial Unicode MS,Heiti TC", - 1, 1252}, - {0x20b3bd3a, L"BrushScriptMT", - L"STIXNonUnicode,Damascus,Arial Narrow,Avenir Next Condensed,Cochin", 8, - 1252}, - {0x220877aa, L"Candara", L"Cochin,Baskerville,Marion", 0, 1252}, - {0x22135007, L"FreestyleScript-Regular", - L"STIXNonUnicode,Nadeem,Zapf Dingbats", 8, 1252}, - {0x251059c3, L"Chiller", - L"Zapf Dingbats,Damascus,STIXNonUnicode,Papyrus,KufiStandardGK,Baghdad", 0, - 1252}, - {0x25bed6dd, L"MSReferenceSansSerif", - L"Tahoma,Apple Symbols,Apple LiGothic,Arial Unicode MS,Lucida " - L"Grande,Microsoft Sans Serif", - 0, 1252}, - {0x28154c81, L"Parchment-Regular", L"Microsoft Sans Serif,Apple Symbols", 8, - 1252}, - {0x29711eb9, L"STLiti", L"Kaiti SC,Songti SC", 0, 936}, - {0x2b1993b4, L"Basemic", L"Impact,Arial Narrow", 0, 1252}, - {0x2b316339, L"NiagaraSolid-Reg", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x2c147529, L"FootlightMTLight", - L"STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans,Noteworthy", 0, 1252}, - {0x2c198928, L"HarlowSolid", - L"Avenir Medium,Avenir Next Medium,Arial Unicode MS", 0, 1252}, - {0x2c6ac6b2, L"LucidaBright", - L"PT Sans Narrow,Papyrus,Damascus,STIXNonUnicode,Arial Rounded MT " - L"Bold,Comic Sans MS,Avenir Next", - 2, 1252}, - {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0x2d5a47b0, L"STCaiyun", L"Kaiti SC,Songti SC", 0, 936}, - {0x2def26bf, L"BernardMT-Condensed", - L"Impact,Avenir Next Condensed Demi Bold,American Typewriter", 0, 1252}, - {0x2fd8930b, L"KozukaMinchoPr6NR", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x3115525a, L"FangSong_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252}, - {0x31327817, L"MyriadPro", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x32244975, L"Helvetica", - L"Arial Narrow,Arial Unicode MS,Damascus,STIXNonUnicode", 0, 1252}, - {0x32ac995c, L"Terminal", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x338d648a, L"NiagaraEngraved-Reg", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0x33bb65f2, L"Sylfaen", L"Arial Unicode MS,Marion", 2, 1252}, - {0x3402c30e, L"MSPMincho", L"Arial Unicode MS,Apple SD Gothic Neo", 2, - 1252}, - {0x3412bf31, L"SimSun-PUA", L"STHeiti,Heiti TC,STFangsong", 0, 936}, - {0x36eb39b9, L"BerlinSansFB", L"American Typewriter,Impact", 0, 1252}, - {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, - {0x3864c4f6, L"HighTowerText", L"STIXGeneral,.Helvetica Neue Desk UI", 2, - 1252}, - {0x3a257d03, L"FangSong_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252}, - {0x3cdae668, L"FreestyleScript", L"Nadeem,Zapf Dingbats,STIXNonUnicode", 8, - 1252}, - {0x3d55aed7, L"Jokerman", - L"Papyrus,Lucida Grande,Heiti TC,American Typewriter", 0, 1252}, - {0x3d5b4385, L"PMingLiU", L"Heiti SC,STHeiti", 2, 1252}, - {0x3d9b7669, L"EstrangeloEdessa", L"American Typewriter,Marion", 0, 1252}, - {0x3e532d74, L"FranklinGothicMedium", L"Impact,Arial Narrow", 0, 1252}, - {0x3e6aa32d, L"NSimSun", L"STHeiti,STFangsong", 1, 936}, - {0x3f6c36a8, L"Gautami", - L"Damascus,STIXNonUnicode,STIXGeneral,American Typewriter", 0, 1252}, - {0x3ff32662, L"Chiller-Regular", L"Papyrus,KufiStandardGK,Baghdad", 0, - 1252}, - {0x409de312, L"ModernNo.20", L"Avenir Next Condensed,Impact", 2, 1252}, - {0x41443c5e, L"Georgia", L".Helvetica Neue Desk UI,Arial Unicode MS", 2, - 1252}, - {0x4160ade5, L"BellGothicStdBlack", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0x421976c4, L"Modern-Regular", L"Impact", 2, 1252}, - {0x422a7252, L"Stencil", L"STIXNonUnicode,Songti SC,Georgia,Baskerville", 0, - 1252}, - {0x42c8554f, L"Fixedsys", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x435cb41d, L"Roman", L"Arial Narrow", 0, 1252}, - {0x47882383, L"CourierNew", L"PCMyungjo,Osaka,Arial Unicode MS,Songti SC", - 1, 1252}, - {0x480a2338, L"BerlinSansFBDemi", - L"STIXNonUnicode,American Typewriter,Avenir Next Condensed Heavy", 0, - 1252}, - {0x480bf7a4, L"CourierStd", L"Courier New", 0, 1252}, - {0x481ad6ed, L"VladimirScript", - L"STIXNonUnicode,Avenir Next Condensed,Impact", 8, 1252}, - {0x4911577a, L"YouYuan", L"STHeiti,Heiti TC", 1, 936}, - {0x4a788d72, L"STXingkai", L"Kaiti SC,Songti SC", 0, 936}, - {0x4bf88566, L"SegoeCondensed", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x4ccf51a4, L"BerlinSansFB-Reg", - L"STIXNonUnicode,American Typewriter,Impact", 0, 1252}, - {0x4ea967ce, L"GulimChe", L"Arial Unicode MS,Heiti TC,STFangsong", 1, 1252}, - {0x4f68bd79, L"LetterGothicStd", - L"Courier New,Andale Mono,Ayuthaya,PCMyungjo,Osaka", 0, 1252}, - {0x51a0d0e6, L"KozukaGothicPr6NM", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x531b3dea, L"BasemicSymbol", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x5333fd39, L"CalifornianFB-Reg", - L"American Typewriter,Avenir Next Condensed,Impact", 2, 1252}, - {0x53561a54, L"FZYTK--GBK1-0", L"STFangsong,Songti SC,STSong", 0, 936}, - {0x55e0dde6, L"LucidaSansTypewriter", L"Menlo,Courier New,Andale Mono", 0, - 1252}, - {0x574d4d3d, L"AdobeArabic", L"Arial Narrow", 0, 1252}, - {0x5792e759, L"STKaiti", L"Songti SC,Arial Unicode MS", 0, 936}, - {0x5921978e, L"LucidaSansUnicode", L"Lucida Grande,Arial Unicode MS,Menlo", - 0, 1252}, - {0x594e2da4, L"Vrinda", L"Geeza Pro,Damascus,STIXGeneral,Gill Sans", 0, - 1252}, - {0x59baa9a2, L"KaiTi_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252}, - {0x5cfedf4f, L"BaskOldFace", - L"Avenir Next Condensed Heavy,PT Sans,Avenir Next Condensed", 0, 1252}, - {0x5e16ac91, L"TrajanPro", L"Arial Narrow,PT Sans Narrow,Damascus", 0, - 1252}, - {0x5f97921c, L"AdobeMyungjoStdM", - L"AppleMyungjo,AppleGothic,Arial Unicode MS", 0, 936}, - {0x5fefbfad, L"Batang", L"Arial Unicode MS,Songti SC", 2, 1252}, - {0x605342b9, L"DotumChe", L"Arial Unicode MS,Heiti TC", 1, 1252}, - {0x608c5f9a, L"KaiTi_GB2312", L"Hiragino Sans GB,STHeiti,Heiti TC", 0, 936}, - {0x61efd0d1, L"MaturaMTScriptCapitals", - L"Kokonor,Damascus,STIXNonUnicode,STHeiti,Arial Black,Avenir Next Heavy", - 0, 1252}, - {0x626608a9, L"MVBoli", - L"Apple Braille,Geeza Pro,Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x630501a3, L"SmallFonts", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x65d0e2a9, L"FZYTK--GBK1-0", L"STFangsong,Songti SC,STSong", 0, 936}, - {0x669f29e1, L"FZSTK--GBK1-0", L"STHeiti,Heiti TC", 0, 936}, - {0x673a9e5f, L"Tunga", - L"Damascus,STIXNonUnicode,Avenir Next Condensed,Avenir Next Condensed " - L"Ultra Light,Futura", - 0, 1252}, - {0x691aa4ce, L"NiagaraSolid", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x696259b7, L"Corbel", L"Cochin,Baskerville,Marion", 0, 1252}, - {0x696ee9be, L"STXihei", L"STHeiti,Heiti TC,Songti SC,Arial Unicode MS", 0, - 936}, - {0x6c59cf69, L"Dotum", L"Arial Unicode MS,Songti SC", 0, 1252}, - {0x707fa561, L"Gungsuh", L"Arial Unicode MS,Heiti TC", 2, 1252}, - {0x71416bb2, L"ZWAdobeF", - L"STIXSizeFourSym,STIXSizeThreeSym,STIXSizeTwoSym,STIXSizeOneSym", 0, - 1252}, - {0x71b41801, L"Verdana", - L"Tahoma,Marion,Apple Symbols,.Helvetica Neue Desk UI,Lucida " - L"Grande,Courier New", - 0, 1252}, - {0x73f25e4c, L"PalatinoLinotype", L"Palatino,Arial Unicode MS", 0, 1252}, - {0x73f4d19f, L"NiagaraEngraved", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x74001694, L"MyriadProBlack", L"Palatino,Baskerville,Marion,Cochin", 0, - 1252}, - {0x74b14d8f, L"Haettenschweiler", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x74cb44ee, L"NSimSun", L"STHeiti,Heiti TC,STFangsong", 1, 936}, - {0x76b4d7ff, L"Shruti", - L"Damascus,STIXNonUnicode,Arial Unicode MS,American Typewriter", 0, 1252}, - {0x788b3533, L"Webdings", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, - {0x797dde99, L"MSSerif", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x7a0f9e9e, L"MSMincho", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " - L"PL UMing TW MBE,Arial Unicode MS,Apple SD Gothic Neo", - 1, 1252}, - {0x7b439caf, L"OldEnglishTextMT", - L"STIXNonUnicode,Arial Unicode MS,Baskerville,Avenir Next Medium", 0, - 1252}, - {0x8213a433, L"LucidaSans-Typewriter", - L"Comic Sans MS,Avenir Next,Arial Rounded MT Bold", 0, 1252}, - {0x82fec929, L"AdobeSongStdL", L"Heiti TC,STHeiti", 0, 936}, - {0x83581825, L"Modern", L"Avenir Next Condensed,Impact", 0, 1252}, - {0x835a2823, L"Algerian", - L"STIXNonUnicode,Baskerville,Avenir Next Medium,American Typewriter", 0, - 1252}, - {0x83dab9f5, L"Script", L"Arial Narrow", 0, 1252}, - {0x847b56da, L"Tahoma", L"Songti SC,Apple Symbols", 0, 1252}, - {0x8a783cb2, L"SimSun-PUA", L"STHeiti,Heiti TC,STFangsong", 0, 1252}, - {0x8b5cac0e, L"Onyx", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0x8c6a499e, L"Gulim", L"Arial Unicode MS,Songti SC", 0, 1252}, - {0x8e0af790, L"JuiceITC", L"Nadeem,Al Bayan", 0, 1252}, - {0x8e8d43b2, L"Centaur", L"Avenir Next Condensed,Noteworthy,Impact", 2, - 1252}, - {0x8ee4dcca, L"BookshelfSymbol7", L"Microsoft Sans Serif,Apple Symbols", 0, - 1252}, - {0x90794800, L"BellGothicStdLight", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0x909b516a, L"Century", L"Damascus,Andale Mono,Songti SC,Arial Unicode MS", - 2, 1252}, - {0x92ae370d, L"MSOutlook", L"Microsoft Sans Serif,Apple Symbols", 4, 42}, - {0x93c9fbf1, L"LucidaFax", - L"PT Sans Narrow,Papyrus,Kokonor,Geeza Pro,Arial Rounded MT Bold,Lucida " - L"Grande,Futura", - 2, 1252}, - {0x9565085e, L"BookAntiqua", L"Palatino,Microsoft Sans Serif,Apple Symbols", - 2, 1252}, - {0x9856d95d, L"AdobeMingStdL", L"AHiragino Sans GB,Heiti TC,STHeiti", 0, - 949}, - {0x9bbadd6b, L"ColonnaMT", L"Noteworthy,Avenir Next Condensed,Impact", 0, - 1252}, - {0x9cbd16a4, L"ShowcardGothic-Reg", - L"Arial Unicode MS,Georgia,American Typewriter", 0, 1252}, - {0x9d73008e, L"MSSansSerif", L"Songti SC,Apple Symbols", 0, 1252}, - {0xa0607db1, L"GungsuhChe", - L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR " - L"PL UMing TW MBE,Arial Unicode MS,Heiti TC,STFangsong", - 1, 1252}, - {0xa0bcf6a1, L"LatinWide", L"Zapfino,Arial Black,STHeiti", 2, 1252}, - {0xa1429b36, L"Symbol", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, - {0xa1fa5abc, L"Wingdings2", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, - {0xa1fa5abd, L"Wingdings3", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, - {0xa427bad4, L"InformalRoman-Regular", - L"STIXNonUnicode,Arial Narrow,Avenir Next Condensed Demi Bold", 8, 1252}, - {0xa8b92ece, L"FZSTK--GBK1-0", L"STHeiti,Heiti TC,STFangsong", 0, 936}, - {0xa8d83ece, L"CalifornianFB", - L"American Typewriter,Avenir Next Condensed,Impact", 2, 1252}, - {0xaa3e082c, L"Kingsoft-Phonetic", - L"STIXVariants,STIXSizeOneSym,Apple Braille", 0, 1252}, - {0xaa6bcabe, L"HarlowSolidItalic", - L"STIXNonUnicode,Avenir Medium,Avenir Next Medium,Arial Unicode MS", 0, - 1252}, - {0xade5337c, L"MSUIGothic", L"Arial Unicode MS,Apple SD Gothic Neo", 0, - 1252}, - {0xb08dd941, L"WideLatin", - L"Marion,Papyrus,Nanum Pen Script,Zapf Dingbats,Damascus,Zapfino,Arial " - L"Black,STHeiti", - 2, 1252}, - {0xb12765e0, L"ITCLegacySansStdBook", - L"LastResort,.Helvetica Neue Desk UI,Arial Unicode MS,Palatino", 0, 1252}, - {0xb207f05d, L"PoorRichard", L"Noteworthy,Avenir Next Condensed,Impact", 2, - 1252}, - {0xb3bc492f, L"JuiceITC-Regular", L"Nadeem,Al Bayan,STIXNonUnicode", 0, - 1252}, - {0xb5545399, L"Marlett", L"Microsoft Sans Serif,Apple Symbols", 4, 42}, - {0xb5dd1ebb, L"BritannicBold", - L"Damascus,STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans", 0, 1252}, - {0xb699c1c5, L"LucidaCalligraphy-Italic", L"STHeiti,Arial Black", 0, 1252}, - {0xb725d629, L"TimesNewRoman", L"Microsoft Sans Serif,Apple Symbols", 2, - 1252}, - {0xb7eaebeb, L"AdobeHeitiStdR", L"Heiti TC,STHeiti", 0, 936}, - {0xbd29c486, L"BerlinSansFBDemi-Bold", - L"American Typewriter,Avenir Next Condensed Heavy", 0, 1252}, - {0xbe8a8db4, L"BookshelfSymbolSeven", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0xc16c0118, L"AdobeHebrew", - L".Helvetica Neue Desk UI,Palatino,American Typewriter", 0, 1252}, - {0xc318b0af, L"MyriadProLight", L"Palatino,Baskerville,Marion", 0, 1252}, - {0xc65e5659, L"CambriaMath", L"Arial Unicode MS", 2, 1252}, - {0xc75c8f05, L"LucidaConsole", L"Courier New,Menlo,Andale Mono", 1, 1252}, - {0xca7c35d6, L"Calibri", L"Apple Symbols,HeadLineA", 0, 1252}, - {0xcb053f53, L"MicrosoftYaHei", L"Arial Unicode MS", 0, 936}, - {0xcb7190f9, L"Magneto-Bold", L"Lucida Grande", 0, 1252}, - {0xcca00cc5, L"System", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0xccad6f76, L"Jokerman-Regular", L"Lucida Grande", 0, 1252}, - {0xccc5818c, L"EuroSign", L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0xcf3d7234, L"LucidaHandwriting-Italic", - L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0xcf7b8fdb, L"MinionPro", - L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252}, - {0xcfe5755f, L"Simhei", L"STHeiti,Heiti TC,STFangsong", 1, 936}, - {0xd011f4ee, L"MSPGothic", L"Arial Unicode MS,Apple SD Gothic Neo", 0, - 1252}, - {0xd060e7ef, L"Vivaldi", - L"STIXNonUnicode,Arial Unicode MS,Avenir Medium,Avenir Next Medium", 8, - 1252}, - {0xd07edec1, L"FranklinGothic-Medium", L"Impact,Arial Narrow", 0, 1252}, - {0xd107243f, L"SimSun", L"STHeiti,Heiti TC,STFangsong", 0, 936}, - {0xd1881562, L"ArialNarrow", L"PT Sans Narrow,Apple Symbols", 0, 1252}, - {0xd22b7dce, L"BodoniMTPosterCompressed", - L"Microsoft Sans Serif,Apple Symbols", 0, 1252}, - {0xd22bfa60, L"ComicSansMS", - L"Damascus,Georgia,.Helvetica Neue Desk UI,Lucida Grande,Arial Unicode MS", - 8, 1252}, - {0xd3bd0e35, L"Bauhaus93", - L"STIXNonUnicode,Arial Unicode MS,Avenir Next,Avenir", 0, 1252}, - {0xd429ee7a, L"STFangsong", L"Songti SC,Arial Unicode MS", 0, 936}, - {0xd6679c12, L"BernardMTCondensed", - L"Impact,Avenir Next Condensed Demi Bold", 0, 1252}, - {0xd8e8a027, L"LucidaSans", - L"Arial Narrow,Khmer MN,Kokonor,Damascus,Microsoft Sans Serif,Apple " - L"Symbols", - 0, 1252}, - {0xd9fe7761, L"HighTowerText-Reg", - L"STIXGeneral,.Helvetica Neue Desk UI,Trebuchet MS", 2, 1252}, - {0xda7e551e, L"STSong", L"Arial Unicode MS", 0, 936}, - {0xdaa6842d, L"STZhongsong", L"STFangsong,Songti SC,STSong", 0, 936}, - {0xdaaab93f, L"STFangsong", L"Songti SC,Arial Unicode MS", 0, 936}, - {0xdaeb0713, L"STSong", L"Songti SC,Arial Unicode MS", 0, 936}, - {0xdafedbef, L"STCaiyun", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, - {0xdb00a3d9, L"Broadway", - L"Papyrus,STIXNonUnicode,Arial Black,Avenir Next Heavy,Heiti TC", 0, 1252}, - {0xdb1f5ad4, L"STXinwei", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, - {0xdb326e7f, L"STKaiti", L"Songti SC,Arial Unicode MS", 0, 936}, - {0xdb69595a, L"STHupo", L"Kaiti SC,Songti SC,STHeiti", 0, 936}, - {0xdba0082c, L"STXihei", L"Songti SC,Arial Unicode MS", 0, 936}, - {0xdbd0ab18, L"STXingkai", L"Kaiti SC,Songti SC", 0, 936}, - {0xdc1a7db1, L"STLiti", L"Kaiti SC,Songti SC", 0, 936}, - {0xdc33075f, L"KristenITC-Regular", - L"STIXNonUnicode,Damascus,Songti SC,STSong", 8, 1252}, - {0xdcc7009c, L"Harrington", - L"STIXNonUnicode,Avenir Next Condensed Heavy,Noteworthy", 0, 1252}, - {0xdd712466, L"ArialBlack", L"Geeza Pro,Damascus,Songti SC,STSong", 0, - 1252}, - {0xdde87b3e, L"Impact", L"Arial Narrow,Marion", 0, 1252}, - {0xdf69fb32, L"SnapITC", - L"Arial Narrow,PT Sans Narrow,Marion,STHeiti,Arial Black", 0, 1252}, - {0xdf8b25e8, L"CenturyGothic", - L"Damascus,Andale Mono,Songti SC,Arial Unicode MS", 0, 1252}, - {0xe0f705c0, L"KristenITC", L"Songti SC,STSong", 8, 1252}, - {0xe1427573, L"Raavi", - L"Damascus,STIXNonUnicode,Marion,Papyrus,Avenir Next Condensed " - L"Heavy,American Typewriter", - 0, 1252}, - {0xe2cea0cb, L"Magneto", - L"STIXNonUnicode,Damascus,Geeza Pro,Lucida Grande,Georgia,Heiti TC", 0, - 1252}, - {0xe36a9e17, L"Ravie", L"STHeiti,Arial Black", 0, 1252}, - {0xe433f8e2, L"Parchment", L"Microsoft Sans Serif,Apple Symbols", 8, 1252}, - {0xe43dff4a, L"Wingdings", L"Microsoft Sans Serif,Apple Symbols", 4, 42}, - {0xe4e2c405, L"MTExtra", L"Microsoft Sans Serif,Apple Symbols", 6, 42}, - {0xe618cc35, L"InformalRoman", L"Arial Narrow", 8, 1252}, - {0xe6c27ffc, L"Mistral", L"Apple Symbols", 8, 1252}, - {0xe7ebf4b9, L"Courier", L"Courier New", 0, 1252}, - {0xe8bc4a9d, L"MSReferenceSpecialty", L"Microsoft Sans Serif,Apple Symbols", - 0, 1252}, - {0xe90fb013, L"TempusSansITC", - L"STIXNonUnicode,Microsoft Sans Serif,Avenir Light", 0, 1252}, - {0xec637b42, L"Consolas", - L"AR PL UKai CN,AR PL UKai HK,AR PL UKai TW,AR PL UKai TW MBE,AR PL UMing " - L"CN,AR PL UMing HK,Microsoft Sans Serif,Tahoma", - 1, 1252}, - {0xed3a683b, L"STXinwei", L"Kaiti SC,Songti SC,", 0, 936}, - {0xef264cd1, L"LucidaHandwriting", - L"Arial Narrow,Avenir Next Condensed Demi Bold,Avenir Next " - L"Condensed,Avenir Next Condensed Medium,STHeiti,Arial Black", - 0, 1252}, - {0xf086bca2, L"BaskervilleOldFace", - L"STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans", 0, 1252}, - {0xf1028030, L"Mangal", - L"Arial Unicode MS,Microsoft Sans Serif,Arial Narrow,Tahoma", 2, 1252}, - {0xf1da7eb9, L"ShowcardGothic", - L"Papyrus,Arial Unicode MS,Georgia,American Typewriter", 0, 1252}, - {0xf210f06a, L"ArialMT", - L"Arial Unicode MS,Arial Narrow,STIXNonUnicode,Damascus,Avenir Next " - L"Condensed Demi Bold,Avenir Next Condensed Medium,Avenir Next Condensed", - 0, 1252}, - {0xf477f16a, L"Latha", - L"Arial Narrow,Damascus,STIXNonUnicode,American Typewriter", 0, 1252}, - {0xf616f3dd, L"LiSu", L"STHeiti,Heiti TC,STFangsong", 1, 936}, - {0xfa479aa6, L"MicrosoftYaHei", L"Arial Unicode MS", 0, 936}, - {0xfcd19697, L"BookmanOldStyle", - L"Geeza Pro,Damascus,Andale Mono,Songti SC,Arial Unicode MS", 0, 1252}, - {0xfe209a82, L"LucidaCalligraphy", - L"Kokonor,Damascus,STIXNonUnicode,STHeiti,Arial Black", 0, 1252}, - {0xfef135f8, L"AdobeHeitiStd-Regular", L"Heiti TC,STHeiti", 0, 936}, -}; -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ -const XFA_FONTINFO g_XFAFontsMap[] = { - {0x01d5d33e, L"SimSun", L"Droid Sans Fallback", 0, 936}, - {0x01e4f102, L"YouYuan", L"Droid Sans Fallback", 1, 936}, - {0x030549dc, L"LiSu", L"Droid Sans Fallback", 1, 936}, - {0x032edd44, L"Simhei", L"Droid Sans Fallback", 1, 936}, - {0x03eac6fc, L"PoorRichard-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback,Droid Arabic " - L"Naskh,Droid Sans Ethiopic", - 2, 1252}, - {0x03ed90e6, L"Nina", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x077b56b3, L"KingsoftPhoneticPlain", - L"Droid Sans Thai,Droid Sans Armenian,Droid Arabic Naskh,Droid Sans " - L"Ethiopic,Droid Sans Fallback", - 0, 1252}, - {0x078ed524, L"MicrosoftSansSerif", L"Droid Sans Fallback", 0, 1252}, - {0x089b18a9, L"Arial", L"Droid Sans Fallback", 0, 1252}, - {0x0b2cad72, L"MonotypeCorsiva", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x0bb003e7, L"Kartika", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 2, 1252}, - {0x0bb469df, L"VinerHandITC", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x0bc1a851, L"SegoeUI", L"Droid Sans Fallback", 0, 1252}, - {0x0c112ebd, L"KozukaGothicPro-VIM", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x0cfcb9c1, L"AdobeThai", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 847}, - {0x0e7de0f9, L"Playbill", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 0, 1252}, - {0x0eff47c3, L"STHupo", L"Droid Sans Fallback", 0, 936}, - {0x107ad374, L"Constantia", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x12194c2d, L"KunstlerScript", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x135ef6a1, L"MinionProSmBd", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x158c4049, L"Garamond", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x160ecb24, L"STZhongsong", L"Droid Sans Fallback", 0, 936}, - {0x161ed07e, L"MSGothic", L"Droid Sans Fallback", 1, 1252}, - {0x171d1ed1, L"SnapITC-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x18d1188f, L"Cambria", L"Droid Sans Fallback", 2, 1252}, - {0x18eaf350, L"ArialUnicodeMS", L"Droid Sans Fallback", 0, 936}, - {0x1a92d115, L"MingLiU", L"Droid Sans Fallback", 1, 1252}, - {0x1cc217c6, L"TrebuchetMS", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x1d649596, L"BasemicTimes", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x1e34ee60, L"BellMT", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x1eb36945, L"CooperBlack", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x1ef7787d, L"BatangChe", L"Droid Sans Fallback", 1, 1252}, - {0x20b3bd3a, L"BrushScriptMT", L"Droid Arabic Naskh,Droid Sans Ethiopic", 8, - 1252}, - {0x220877aa, L"Candara", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x22135007, L"FreestyleScript-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x251059c3, L"Chiller", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 0, 1252}, - {0x25bed6dd, L"MSReferenceSansSerif", L"Droid Sans Fallback", 0, 1252}, - {0x28154c81, L"Parchment-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x29711eb9, L"STLiti", L"Droid Sans Fallback", 0, 936}, - {0x2b1993b4, L"Basemic", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x2b316339, L"NiagaraSolid-Reg", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x2c147529, L"FootlightMTLight", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x2c198928, L"HarlowSolid", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x2c6ac6b2, L"LucidaBright", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 2, 1252}, - {0x2c9f38e2, L"KozukaMinchoPro-VIR", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x2d5a47b0, L"STCaiyun", L"Droid Sans Fallback", 0, 936}, - {0x2def26bf, L"BernardMT-Condensed", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x2fd8930b, L"KozukaMinchoPr6NR", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x3115525a, L"FangSong_GB2312", L"Droid Sans Fallback", 0, 1252}, - {0x31327817, L"MyriadPro", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x32244975, L"Helvetica", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 0, 1252}, - {0x32ac995c, L"Terminal", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x338d648a, L"NiagaraEngraved-Reg", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x33bb65f2, L"Sylfaen", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x3402c30e, L"MSPMincho", L"Droid Sans Fallback", 2, 1252}, - {0x3412bf31, L"SimSun-PUA", L"Droid Sans Fallback", 0, 936}, - {0x36eb39b9, L"BerlinSansFB", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252}, - {0x3864c4f6, L"HighTowerText", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x3a257d03, L"FangSong_GB2312", L"Droid Sans Fallback", 0, 1252}, - {0x3cdae668, L"FreestyleScript", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x3d55aed7, L"Jokerman", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x3d5b4385, L"PMingLiU", L"Droid Sans Fallback", 2, 1252}, - {0x3d9b7669, L"EstrangeloEdessa", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x3e532d74, L"FranklinGothicMedium", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x3e6aa32d, L"NSimSun", L"Droid Sans Fallback", 1, 936}, - {0x3f6c36a8, L"Gautami", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono,Droid Sans Fallback", - 0, 1252}, - {0x3ff32662, L"Chiller-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x409de312, L"ModernNo.20", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x41443c5e, L"Georgia", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x4160ade5, L"BellGothicStdBlack", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x421976c4, L"Modern-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x422a7252, L"Stencil", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x42c8554f, L"Fixedsys", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x435cb41d, L"Roman", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x47882383, L"CourierNew", L"Droid Sans Fallback", 1, 1252}, - {0x480a2338, L"BerlinSansFBDemi", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x480bf7a4, L"CourierStd", L"Droid Sans Fallback", 0, 1252}, - {0x481ad6ed, L"VladimirScript", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0x4911577a, L"YouYuan", L"Droid Sans Fallback", 1, 936}, - {0x4a788d72, L"STXingkai", L"Droid Sans Fallback", 0, 936}, - {0x4bf88566, L"SegoeCondensed", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x4ccf51a4, L"BerlinSansFB-Reg", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x4ea967ce, L"GulimChe", L"Droid Sans Fallback", 1, 1252}, - {0x4f68bd79, L"LetterGothicStd", - L"Droid Sans Mono,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans " - L"Mono,Droid Serif,Droid Sans Fallback", - 0, 1252}, - {0x51a0d0e6, L"KozukaGothicPr6NM", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x531b3dea, L"BasemicSymbol", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x5333fd39, L"CalifornianFB-Reg", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x53561a54, L"FZYTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, - {0x55e0dde6, L"LucidaSansTypewriter", - L"Droid Sans Mono,Droid Arabic Naskh,Droid Sans Ethiopic", 0, 1252}, - {0x574d4d3d, L"AdobeArabic", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x5792e759, L"STKaiti", L"Droid Sans Fallback", 0, 936}, - {0x5921978e, L"LucidaSansUnicode", L"Droid Sans Fallback", 0, 1252}, - {0x594e2da4, L"Vrinda", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 0, 1252}, - {0x59baa9a2, L"KaiTi_GB2312", L"Droid Sans Fallback", 0, 1252}, - {0x5cfedf4f, L"BaskOldFace", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x5f97921c, L"AdobeMyungjoStdM", L"Droid Sans Fallback", 0, 936}, - {0x5fefbfad, L"Batang", L"Droid Sans Fallback", 2, 1252}, - {0x605342b9, L"DotumChe", L"Droid Sans Fallback", 1, 1252}, - {0x608c5f9a, L"KaiTi_GB2312", L"Droid Sans Fallback", 0, 936}, - {0x61efd0d1, L"MaturaMTScriptCapitals", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 0, 1252}, - {0x626608a9, L"MVBoli", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 0, 1252}, - {0x630501a3, L"SmallFonts", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x65d0e2a9, L"FZYTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, - {0x669f29e1, L"FZSTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, - {0x673a9e5f, L"Tunga", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono,Droid Sans Fallback", - 0, 1252}, - {0x691aa4ce, L"NiagaraSolid", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x696259b7, L"Corbel", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x696ee9be, L"STXihei", L"Droid Sans Fallback", 0, 936}, - {0x6c59cf69, L"Dotum", L"Droid Sans Fallback", 0, 1252}, - {0x707fa561, L"Gungsuh", L"Droid Sans Fallback", 2, 1252}, - {0x71416bb2, L"ZWAdobeF", - L"Droid Arabic Naskh,Droid Sans Armenian,Droid Sans Ethiopic,Droid Sans " - L"Georgian,Droid Sans Hebrew,Droid Sans Thai", - 0, 1252}, - {0x71b41801, L"Verdana", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x73f25e4c, L"PalatinoLinotype", L"Droid Sans Fallback", 0, 1252}, - {0x73f4d19f, L"NiagaraEngraved", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x74001694, L"MyriadProBlack", L"Book Antiqua,Constantia,Dotum,Georgia", 0, - 1252}, - {0x74b14d8f, L"Haettenschweiler", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x74cb44ee, L"NSimSun", L"Droid Sans Fallback", 1, 936}, - {0x76b4d7ff, L"Shruti", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 0, 1252}, - {0x788b3533, L"Webdings", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, - {0x797dde99, L"MSSerif", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x7a0f9e9e, L"MSMincho", L"Droid Sans Fallback", 1, 1252}, - {0x7b439caf, L"OldEnglishTextMT", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x8213a433, L"LucidaSans-Typewriter", - L"Droid Sans Mono,Droid Serif,Roboto,Droid Sans Fallback", 0, 1252}, - {0x82fec929, L"AdobeSongStdL", L"Droid Sans Fallback", 0, 936}, - {0x83581825, L"Modern", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x835a2823, L"Algerian", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x83dab9f5, L"Script", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x847b56da, L"Tahoma", L"Droid Sans Fallback", 0, 1252}, - {0x8a783cb2, L"SimSun-PUA", L"Droid Sans Fallback", 0, 1252}, - {0x8b5cac0e, L"Onyx", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x8c6a499e, L"Gulim", L"Droid Sans Fallback", 0, 1252}, - {0x8e0af790, L"JuiceITC", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x8e8d43b2, L"Centaur", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x8ee4dcca, L"BookshelfSymbol7", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x90794800, L"BellGothicStdLight", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x909b516a, L"Century", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x92ae370d, L"MSOutlook", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42}, - {0x93c9fbf1, L"LucidaFax", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 2, 1252}, - {0x9565085e, L"BookAntiqua", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0x9856d95d, L"AdobeMingStdL", L"Droid Sans Fallback", 0, 949}, - {0x9bbadd6b, L"ColonnaMT", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0x9cbd16a4, L"ShowcardGothic-Reg", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallbac", 0, 1252}, - {0x9d73008e, L"MSSansSerif", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xa0607db1, L"GungsuhChe", L"Droid Sans Fallback", 1, 1252}, - {0xa0bcf6a1, L"LatinWide", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0xa1429b36, L"Symbol", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, - {0xa1fa5abc, L"Wingdings2", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, - {0xa1fa5abd, L"Wingdings3", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, - {0xa427bad4, L"InformalRoman-Regular", - L"Droid Arabic Naskh,Droid Sans Ethiopic", 8, 1252}, - {0xa8b92ece, L"FZSTK--GBK1-0", L"Droid Sans Fallback", 0, 936}, - {0xa8d83ece, L"CalifornianFB", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0xaa3e082c, L"Kingsoft-Phonetic", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xaa6bcabe, L"HarlowSolidItalic", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xade5337c, L"MSUIGothic", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xb08dd941, L"WideLatin", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 2, 1252}, - {0xb207f05d, L"PoorRichard", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0xb3bc492f, L"JuiceITC-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xb5545399, L"Marlett", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42}, - {0xb5dd1ebb, L"BritannicBold", L"Droid Arabic Naskh,Droid Sans Ethiopic", 0, - 1252}, - {0xb699c1c5, L"LucidaCalligraphy-Italic", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xb725d629, L"TimesNewRoman", L"Droid Sans Fallback", 2, 1252}, - {0xb7eaebeb, L"AdobeHeitiStdR", L"Droid Sans Fallback", 0, 936}, - {0xbd29c486, L"BerlinSansFBDemi-Bold", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xbe8a8db4, L"BookshelfSymbolSeven", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xc16c0118, L"AdobeHebrew", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback,Droid Arabic " - L"Naskh,Droid Sans Ethiopic", - 0, 1252}, - {0xc318b0af, L"MyriadProLight", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xc65e5659, L"CambriaMath", L"Droid Sans Fallback", 2, 1252}, - {0xc75c8f05, L"LucidaConsole", - L"Droid Sans Mono,Droid Serif,Roboto,Droid Sans Fallback", 1, 1252}, - {0xca7c35d6, L"Calibri", L"Droid Sans Fallback", 0, 1252}, - {0xcb053f53, L"MicrosoftYaHei", L"Droid Sans Fallback", 0, 936}, - {0xcb7190f9, L"Magneto-Bold", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xcca00cc5, L"System", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xccad6f76, L"Jokerman-Regular", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xccc5818c, L"EuroSign", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xcf3d7234, L"LucidaHandwriting-Italic", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xcf7b8fdb, L"MinionPro", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xcfe5755f, L"Simhei", L"Droid Sans Fallback", 1, 936}, - {0xd011f4ee, L"MSPGothic", L"Droid Sans Fallback", 0, 1252}, - {0xd060e7ef, L"Vivaldi", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0xd07edec1, L"FranklinGothic-Medium", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xd107243f, L"SimSun", L"Droid Sans Fallback", 0, 936}, - {0xd1881562, L"ArialNarrow", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xd22b7dce, L"BodoniMTPosterCompressed", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xd22bfa60, L"ComicSansMS", L"Droid Serif,Roboto,Droid Sans Fallback", 8, - 1252}, - {0xd3bd0e35, L"Bauhaus93", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xd429ee7a, L"STFangsong", L"Droid Sans Fallback", 0, 936}, - {0xd6679c12, L"BernardMTCondensed", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xd8e8a027, L"LucidaSans", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 0, 1252}, - {0xd9fe7761, L"HighTowerText-Reg", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252}, - {0xda7e551e, L"STSong", L"Droid Sans Fallback", 0, 936}, - {0xdaa6842d, L"STZhongsong", L"Droid Sans Fallback", 0, 936}, - {0xdaaab93f, L"STFangsong", L"Droid Sans Fallback", 0, 936}, - {0xdaeb0713, L"STSong", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 936}, - {0xdafedbef, L"STCaiyun", L"Droid Sans Fallback", 0, 936}, - {0xdb00a3d9, L"Broadway", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xdb1f5ad4, L"STXinwei", L"Droid Sans Fallback", 0, 936}, - {0xdb326e7f, L"STKaiti", L"Droid Sans Fallback", 0, 936}, - {0xdb69595a, L"STHupo", L"Droid Sans Fallback", 0, 936}, - {0xdba0082c, L"STXihei", L"Droid Sans Fallback", 0, 936}, - {0xdbd0ab18, L"STXingkai", L"Droid Sans Fallback", 0, 936}, - {0xdc1a7db1, L"STLiti", L"Droid Sans Fallback", 0, 936}, - {0xdc33075f, L"KristenITC-Regular", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 8, 1252}, - {0xdcc7009c, L"Harrington", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xdd712466, L"ArialBlack", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xdde87b3e, L"Impact", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xdf69fb32, L"SnapITC", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 0, 1252}, - {0xdf8b25e8, L"CenturyGothic", - L"Droid Serif,Roboto,Droid Serif,Droid Sans Mono", 0, 1252}, - {0xe0f705c0, L"KristenITC", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 8, 1252}, - {0xe1427573, L"Raavi", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 0, 1252}, - {0xe2cea0cb, L"Magneto", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 0, 1252}, - {0xe36a9e17, L"Ravie", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 0, 1252}, - {0xe433f8e2, L"Parchment", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0xe43dff4a, L"Wingdings", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42}, - {0xe4e2c405, L"MTExtra", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42}, - {0xe618cc35, L"InformalRoman", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 8, 1252}, - {0xe6c27ffc, L"Mistral", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252}, - {0xe7ebf4b9, L"Courier", L"Droid Sans Fallback", 0, 1252}, - {0xe8bc4a9d, L"MSReferenceSpecialty", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xe90fb013, L"TempusSansITC", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xec637b42, L"Consolas", L"Droid Sans Fallback", 1, 1252}, - {0xed3a683b, L"STXinwei", L"Droid Sans Fallback", 0, 936}, - {0xef264cd1, L"LucidaHandwriting", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 0, 1252}, - {0xf086bca2, L"BaskervilleOldFace", - L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xf1028030, L"Mangal", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 2, 1252}, - {0xf1da7eb9, L"ShowcardGothic", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallbac", 0, 1252}, - {0xf210f06a, L"ArialMT", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 0, 1252}, - {0xf477f16a, L"Latha", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans " - L"Mono", - 0, 1252}, - {0xf616f3dd, L"LiSu", L"Droid Sans Fallback", 1, 936}, - {0xfa479aa6, L"MicrosoftYaHei", L"Droid Sans Fallback", 0, 936}, - {0xfcd19697, L"BookmanOldStyle", - L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252}, - {0xfe209a82, L"LucidaCalligraphy", - L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans " - L"Mono", - 0, 1252}, - {0xfef135f8, L"AdobeHeitiStd-Regular", L"Droid Sans Fallback", 0, 936}, -}; -#endif - -CFX_WideString XFA_LocalFontNameToEnglishName( - const CFX_WideStringC& wsLocalName) { - uint32_t dwLocalNameHash = FX_HashCode_GetW(wsLocalName, true); - const XFA_FONTINFO* pEnd = g_XFAFontsMap + FX_ArraySize(g_XFAFontsMap); - const XFA_FONTINFO* pFontInfo = - std::lower_bound(g_XFAFontsMap, pEnd, dwLocalNameHash, - [](const XFA_FONTINFO& entry, uint32_t hash) { - return entry.dwFontNameHash < hash; - }); - if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwLocalNameHash) - return pFontInfo->pPsName; - return CFX_WideString(wsLocalName); -} - -const XFA_FONTINFO* XFA_GetFontINFOByFontName( - const CFX_WideStringC& wsFontName) { - CFX_WideString wsFontNameTemp(wsFontName); - wsFontNameTemp.Remove(L' '); - uint32_t dwCurFontNameHash = - FX_HashCode_GetW(wsFontNameTemp.AsStringC(), true); - const XFA_FONTINFO* pEnd = g_XFAFontsMap + FX_ArraySize(g_XFAFontsMap); - const XFA_FONTINFO* pFontInfo = - std::lower_bound(g_XFAFontsMap, pEnd, dwCurFontNameHash, - [](const XFA_FONTINFO& entry, uint32_t hash) { - return entry.dwFontNameHash < hash; - }); - if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwCurFontNameHash) - return pFontInfo; - return nullptr; -} - -} // namespace - -CXFA_DefFontMgr::CXFA_DefFontMgr() {} - -CXFA_DefFontMgr::~CXFA_DefFontMgr() {} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_DefFontMgr::GetFont( - CXFA_FFDoc* hDoc, - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage) { - CFX_WideString wsFontName(wsFontFamily); - CFGAS_FontMgr* pFDEFontMgr = hDoc->GetApp()->GetFDEFontMgr(); - CFX_RetainPtr<CFGAS_GEFont> pFont = - pFDEFontMgr->LoadFont(wsFontName.c_str(), dwFontStyles, wCodePage); - if (!pFont) { - const XFA_FONTINFO* pCurFont = - XFA_GetFontINFOByFontName(wsFontName.AsStringC()); - if (pCurFont && pCurFont->pReplaceFont) { - uint32_t dwStyle = 0; - if (dwFontStyles & FX_FONTSTYLE_Bold) { - dwStyle |= FX_FONTSTYLE_Bold; - } - if (dwFontStyles & FX_FONTSTYLE_Italic) { - dwStyle |= FX_FONTSTYLE_Italic; - } - const FX_WCHAR* pReplace = pCurFont->pReplaceFont; - int32_t iLength = FXSYS_wcslen(pReplace); - while (iLength > 0) { - const FX_WCHAR* pNameText = pReplace; - while (*pNameText != L',' && iLength > 0) { - pNameText++; - iLength--; - } - CFX_WideString wsReplace = - CFX_WideString(pReplace, pNameText - pReplace); - pFont = pFDEFontMgr->LoadFont(wsReplace.c_str(), dwStyle, wCodePage); - if (pFont) - break; - - iLength--; - pNameText++; - pReplace = pNameText; - } - } - } - if (pFont) - m_CacheFonts.push_back(pFont); - return pFont; -} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_DefFontMgr::GetDefaultFont( - CXFA_FFDoc* hDoc, - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage) { - CFGAS_FontMgr* pFDEFontMgr = hDoc->GetApp()->GetFDEFontMgr(); - CFX_RetainPtr<CFGAS_GEFont> pFont = - pFDEFontMgr->LoadFont(L"Arial Narrow", dwFontStyles, wCodePage); - if (!pFont) { - pFont = pFDEFontMgr->LoadFont(static_cast<const FX_WCHAR*>(nullptr), - dwFontStyles, wCodePage); - } - if (pFont) - m_CacheFonts.push_back(pFont); - return pFont; -} - -CXFA_PDFFontMgr::CXFA_PDFFontMgr(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {} - -CXFA_PDFFontMgr::~CXFA_PDFFontMgr() {} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_PDFFontMgr::FindFont( - const CFX_ByteString& strPsName, - bool bBold, - bool bItalic, - CPDF_Font** pDstPDFFont, - bool bStrictMatch) { - CPDF_Document* pDoc = m_pDoc->GetPDFDoc(); - if (!pDoc) - return nullptr; - - CPDF_Dictionary* pFontSetDict = - pDoc->GetRoot()->GetDictFor("AcroForm")->GetDictFor("DR"); - if (!pFontSetDict) - return nullptr; - - pFontSetDict = pFontSetDict->GetDictFor("Font"); - if (!pFontSetDict) - return nullptr; - - CFX_ByteString name = strPsName; - name.Remove(' '); - CFGAS_FontMgr* pFDEFontMgr = m_pDoc->GetApp()->GetFDEFontMgr(); - for (const auto& it : *pFontSetDict) { - const CFX_ByteString& key = it.first; - CPDF_Object* pObj = it.second.get(); - if (!PsNameMatchDRFontName(name.AsStringC(), bBold, bItalic, key, - bStrictMatch)) { - continue; - } - CPDF_Dictionary* pFontDict = ToDictionary(pObj->GetDirect()); - if (!pFontDict || pFontDict->GetStringFor("Type") != "Font") { - return nullptr; - } - CPDF_Font* pPDFFont = pDoc->LoadFont(pFontDict); - if (!pPDFFont) { - return nullptr; - } - if (!pPDFFont->IsEmbedded()) { - *pDstPDFFont = pPDFFont; - return nullptr; - } - return CFGAS_GEFont::LoadFont(&pPDFFont->m_Font, pFDEFontMgr); - } - return nullptr; -} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_PDFFontMgr::GetFont( - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - CPDF_Font** pPDFFont, - bool bStrictMatch) { - uint32_t dwHashCode = FX_HashCode_GetW(wsFontFamily, false); - CFX_ByteString strKey; - strKey.Format("%u%u", dwHashCode, dwFontStyles); - auto it = m_FontMap.find(strKey); - if (it != m_FontMap.end()) - return it->second; - CFX_ByteString bsPsName = - CFX_ByteString::FromUnicode(CFX_WideString(wsFontFamily)); - bool bBold = (dwFontStyles & FX_FONTSTYLE_Bold) == FX_FONTSTYLE_Bold; - bool bItalic = (dwFontStyles & FX_FONTSTYLE_Italic) == FX_FONTSTYLE_Italic; - CFX_ByteString strFontName = PsNameToFontName(bsPsName, bBold, bItalic); - CFX_RetainPtr<CFGAS_GEFont> pFont = - FindFont(strFontName, bBold, bItalic, pPDFFont, bStrictMatch); - if (pFont) - m_FontMap[strKey] = pFont; - return pFont; -} - -CFX_ByteString CXFA_PDFFontMgr::PsNameToFontName( - const CFX_ByteString& strPsName, - bool bBold, - bool bItalic) { - for (size_t i = 0; i < FX_ArraySize(g_XFAPDFFontName); ++i) { - if (strPsName == g_XFAPDFFontName[i][0]) { - size_t index = 1; - if (bBold) - ++index; - if (bItalic) - index += 2; - return g_XFAPDFFontName[i][index]; - } - } - return strPsName; -} - -bool CXFA_PDFFontMgr::PsNameMatchDRFontName(const CFX_ByteStringC& bsPsName, - bool bBold, - bool bItalic, - const CFX_ByteString& bsDRFontName, - bool bStrictMatch) { - CFX_ByteString bsDRName = bsDRFontName; - bsDRName.Remove('-'); - int32_t iPsLen = bsPsName.GetLength(); - int32_t nIndex = bsDRName.Find(bsPsName); - if (nIndex != -1 && !bStrictMatch) - return true; - - if (nIndex != 0) - return false; - - int32_t iDifferLength = bsDRName.GetLength() - iPsLen; - if (iDifferLength > 1 || (bBold || bItalic)) { - int32_t iBoldIndex = bsDRName.Find("Bold"); - bool bBoldFont = iBoldIndex > 0; - if (bBold != bBoldFont) - return false; - - if (bBoldFont) { - iDifferLength = - std::min(iDifferLength - 4, bsDRName.GetLength() - iBoldIndex - 4); - } - bool bItalicFont = true; - if (bsDRName.Find("Italic") > 0) { - iDifferLength -= 6; - } else if (bsDRName.Find("It") > 0) { - iDifferLength -= 2; - } else if (bsDRName.Find("Oblique") > 0) { - iDifferLength -= 7; - } else { - bItalicFont = false; - } - if (bItalic != bItalicFont) - return false; - - if (iDifferLength > 1) { - CFX_ByteString bsDRTailer = bsDRName.Right(iDifferLength); - if (bsDRTailer == "MT" || bsDRTailer == "PSMT" || - bsDRTailer == "Regular" || bsDRTailer == "Reg") { - return true; - } - if (bBoldFont || bItalicFont) - return false; - - bool bMatch = false; - switch (bsPsName.GetAt(iPsLen - 1)) { - case 'L': { - if (bsDRName.Right(5) == "Light") { - bMatch = true; - } - } break; - case 'R': { - if (bsDRName.Right(7) == "Regular" || bsDRName.Right(3) == "Reg") { - bMatch = true; - } - } break; - case 'M': { - if (bsDRName.Right(5) == "Medium") { - bMatch = true; - } - } break; - default: - break; - } - return bMatch; - } - } - return true; -} - -bool CXFA_PDFFontMgr::GetCharWidth(const CFX_RetainPtr<CFGAS_GEFont>& pFont, - FX_WCHAR wUnicode, - bool bCharCode, - int32_t* pWidth) { - if (wUnicode != 0x20 || bCharCode) - return false; - - auto it = m_FDE2PDFFont.find(pFont); - if (it == m_FDE2PDFFont.end()) - return false; - - CPDF_Font* pPDFFont = it->second; - *pWidth = pPDFFont->GetCharWidthF(pPDFFont->CharCodeFromUnicode(wUnicode)); - return true; -} - -void CXFA_PDFFontMgr::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont, - CPDF_Font* pPDFFont) { - m_FDE2PDFFont[pFont] = pPDFFont; -} - -CXFA_FontMgr::CXFA_FontMgr() {} - -CXFA_FontMgr::~CXFA_FontMgr() {} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_FontMgr::GetFont( - CXFA_FFDoc* hDoc, - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage) { - uint32_t dwHash = FX_HashCode_GetW(wsFontFamily, false); - CFX_ByteString bsKey; - bsKey.Format("%u%u%u", dwHash, dwFontStyles, wCodePage); - auto iter = m_FontMap.find(bsKey); - if (iter != m_FontMap.end()) - return iter->second; - - CFX_WideString wsEnglishName = XFA_LocalFontNameToEnglishName(wsFontFamily); - auto it = m_PDFFontMgrMap.find(hDoc); - CXFA_PDFFontMgr* pMgr = - it != m_PDFFontMgrMap.end() ? it->second.get() : nullptr; - CPDF_Font* pPDFFont = nullptr; - CFX_RetainPtr<CFGAS_GEFont> pFont; - if (pMgr) { - pFont = - pMgr->GetFont(wsEnglishName.AsStringC(), dwFontStyles, &pPDFFont, true); - if (pFont) - return pFont; - } - if (!pFont && m_pDefFontMgr) - pFont = m_pDefFontMgr->GetFont(hDoc, wsFontFamily, dwFontStyles, wCodePage); - - if (!pFont && pMgr) { - pPDFFont = nullptr; - pFont = pMgr->GetFont(wsEnglishName.AsStringC(), dwFontStyles, &pPDFFont, - false); - if (pFont) - return pFont; - } - if (!pFont && m_pDefFontMgr) { - pFont = m_pDefFontMgr->GetDefaultFont(hDoc, wsFontFamily, dwFontStyles, - wCodePage); - } - if (pFont) { - if (pPDFFont) { - pMgr->SetFont(pFont, pPDFFont); - pFont->SetFontProvider(pMgr); - } - m_FontMap[bsKey] = pFont; - } - return pFont; -} - -void CXFA_FontMgr::LoadDocFonts(CXFA_FFDoc* hDoc) { - if (!m_PDFFontMgrMap[hDoc]) - m_PDFFontMgrMap[hDoc] = pdfium::MakeUnique<CXFA_PDFFontMgr>(hDoc); -} - -void CXFA_FontMgr::ReleaseDocFonts(CXFA_FFDoc* hDoc) { - m_PDFFontMgrMap.erase(hDoc); -} - -void CXFA_FontMgr::SetDefFontMgr(std::unique_ptr<CXFA_DefFontMgr> pFontMgr) { - m_pDefFontMgr = std::move(pFontMgr); -} diff --git a/xfa/fxfa/app/xfa_fwladapter.cpp b/xfa/fxfa/app/xfa_fwladapter.cpp deleted file mode 100644 index e1f3e202ed326245adc3718995c24b53cb9fa439..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fwladapter.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_fwladapter.h" - -#include "xfa/fxfa/app/xfa_fffield.h" -#include "xfa/fxfa/xfa_ffdoc.h" - -CXFA_FWLAdapterWidgetMgr::CXFA_FWLAdapterWidgetMgr() {} - -CXFA_FWLAdapterWidgetMgr::~CXFA_FWLAdapterWidgetMgr() {} - -void CXFA_FWLAdapterWidgetMgr::RepaintWidget(CFWL_Widget* pWidget) { - if (!pWidget) - return; - - CXFA_FFWidget* pFFWidget = pWidget->GetLayoutItem(); - if (!pFFWidget) - return; - - pFFWidget->AddInvalidateRect(nullptr); -} - -bool CXFA_FWLAdapterWidgetMgr::GetPopupPos(CFWL_Widget* pWidget, - FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, - const CFX_RectF& rtAnchor, - CFX_RectF& rtPopup) { - CXFA_FFWidget* pFFWidget = pWidget->GetLayoutItem(); - CFX_RectF rtRotateAnchor(rtAnchor); - pFFWidget->GetRotateMatrix().TransformRect(rtRotateAnchor); - pFFWidget->GetDoc()->GetDocEnvironment()->GetPopupPos( - pFFWidget, fMinHeight, fMaxHeight, rtRotateAnchor, rtPopup); - return true; -} diff --git a/xfa/fxfa/app/xfa_fwladapter.h b/xfa/fxfa/app/xfa_fwladapter.h deleted file mode 100644 index c68fb7015f29044f8c3def323b3e1cc998da5f42..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fwladapter.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FWLADAPTER_H_ -#define XFA_FXFA_APP_XFA_FWLADAPTER_H_ - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" - -class CFWL_Widget; - -class CXFA_FWLAdapterWidgetMgr { - public: - CXFA_FWLAdapterWidgetMgr(); - ~CXFA_FWLAdapterWidgetMgr(); - - void RepaintWidget(CFWL_Widget* pWidget); - bool GetPopupPos(CFWL_Widget* pWidget, - FX_FLOAT fMinHeight, - FX_FLOAT fMaxHeight, - const CFX_RectF& rtAnchor, - CFX_RectF& rtPopup); -}; - -#endif // XFA_FXFA_APP_XFA_FWLADAPTER_H_ diff --git a/xfa/fxfa/app/xfa_fwltheme.cpp b/xfa/fxfa/app/xfa_fwltheme.cpp deleted file mode 100644 index 73abaecbc8975f8dd8969c78db3ea787fd32ede1..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fwltheme.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_fwltheme.h" - -#include "xfa/fde/tto/fde_textout.h" -#include "xfa/fgas/crt/fgas_codepage.h" -#include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fwl/cfwl_barcode.h" -#include "xfa/fwl/cfwl_caret.h" -#include "xfa/fwl/cfwl_checkbox.h" -#include "xfa/fwl/cfwl_combobox.h" -#include "xfa/fwl/cfwl_datetimepicker.h" -#include "xfa/fwl/cfwl_edit.h" -#include "xfa/fwl/cfwl_listbox.h" -#include "xfa/fwl/cfwl_monthcalendar.h" -#include "xfa/fwl/cfwl_picturebox.h" -#include "xfa/fwl/cfwl_pushbutton.h" -#include "xfa/fwl/cfwl_scrollbar.h" -#include "xfa/fwl/cfwl_themebackground.h" -#include "xfa/fwl/cfwl_themetext.h" -#include "xfa/fxfa/xfa_ffapp.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_color.h" - -namespace { - -const FX_WCHAR* const g_FWLTheme_CalFonts[] = { - L"Arial", L"Courier New", L"DejaVu Sans", -}; - -const float kLineHeight = 12.0f; - -} // namespace - -CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget) { - CFWL_Widget* pOuter = pWidget; - while (pOuter && pOuter->GetOuter()) - pOuter = pOuter->GetOuter(); - return pOuter ? pOuter->GetLayoutItem() : nullptr; -} - -CXFA_FWLTheme::CXFA_FWLTheme(CXFA_FFApp* pApp) - : m_pCheckBoxTP(new CFWL_CheckBoxTP), - m_pListBoxTP(new CFWL_ListBoxTP), - m_pPictureBoxTP(new CFWL_PictureBoxTP), - m_pSrollBarTP(new CFWL_ScrollBarTP), - m_pEditTP(new CFWL_EditTP), - m_pComboBoxTP(new CFWL_ComboBoxTP), - m_pMonthCalendarTP(new CFWL_MonthCalendarTP), - m_pDateTimePickerTP(new CFWL_DateTimePickerTP), - m_pPushButtonTP(new CFWL_PushButtonTP), - m_pCaretTP(new CFWL_CaretTP), - m_pBarcodeTP(new CFWL_BarcodeTP), - m_pTextOut(new CFDE_TextOut), - m_pCalendarFont(nullptr), - m_pApp(pApp) { - m_Rect.Reset(); - - for (size_t i = 0; !m_pCalendarFont && i < FX_ArraySize(g_FWLTheme_CalFonts); - ++i) { - m_pCalendarFont = CFGAS_GEFont::LoadFont(g_FWLTheme_CalFonts[i], 0, 0, - m_pApp->GetFDEFontMgr()); - } - if (!m_pCalendarFont) { - m_pCalendarFont = m_pApp->GetFDEFontMgr()->GetFontByCodePage( - FX_CODEPAGE_MSWin_WesternEuropean, 0, nullptr); - } - - ASSERT(m_pCalendarFont); -} - -CXFA_FWLTheme::~CXFA_FWLTheme() { - m_pTextOut.reset(); - FWLTHEME_Release(); -} - -void CXFA_FWLTheme::DrawBackground(CFWL_ThemeBackground* pParams) { - GetTheme(pParams->m_pWidget)->DrawBackground(pParams); -} - -void CXFA_FWLTheme::DrawText(CFWL_ThemeText* pParams) { - if (pParams->m_wsText.IsEmpty()) - return; - - if (pParams->m_pWidget->GetClassID() == FWL_Type::MonthCalendar) { - CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); - if (!pWidget) - return; - - m_pTextOut->SetStyles(pParams->m_dwTTOStyles); - m_pTextOut->SetAlignment(pParams->m_iTTOAlign); - m_pTextOut->SetFont(m_pCalendarFont); - m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize); - m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor); - if ((pParams->m_iPart == CFWL_Part::DatesIn) && - !(pParams->m_dwStates & FWL_ITEMSTATE_MCD_Flag) && - (pParams->m_dwStates & - (CFWL_PartState_Hovered | CFWL_PartState_Selected))) { - m_pTextOut->SetTextColor(0xFFFFFFFF); - } - if (pParams->m_iPart == CFWL_Part::Caption) - m_pTextOut->SetTextColor(ArgbEncode(0xff, 0, 153, 255)); - - CFX_Graphics* pGraphics = pParams->m_pGraphics; - CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice(); - if (!pRenderDevice) - return; - - m_pTextOut->SetRenderDevice(pRenderDevice); - CFX_Matrix mtPart = pParams->m_matrix; - CFX_Matrix* pMatrix = pGraphics->GetMatrix(); - if (pMatrix) { - mtPart.Concat(*pMatrix); - } - m_pTextOut->SetMatrix(mtPart); - m_pTextOut->DrawLogicText(pParams->m_wsText.c_str(), - pParams->m_wsText.GetLength(), pParams->m_rtPart); - return; - } - CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); - if (!pWidget) - return; - - CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc(); - CFX_Graphics* pGraphics = pParams->m_pGraphics; - CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice(); - if (!pRenderDevice) - return; - - m_pTextOut->SetRenderDevice(pRenderDevice); - m_pTextOut->SetStyles(pParams->m_dwTTOStyles); - m_pTextOut->SetAlignment(pParams->m_iTTOAlign); - m_pTextOut->SetFont(pAcc->GetFDEFont()); - m_pTextOut->SetFontSize(pAcc->GetFontSize()); - m_pTextOut->SetTextColor(pAcc->GetTextColor()); - CFX_Matrix mtPart = pParams->m_matrix; - CFX_Matrix* pMatrix = pGraphics->GetMatrix(); - if (pMatrix) - mtPart.Concat(*pMatrix); - - m_pTextOut->SetMatrix(mtPart); - m_pTextOut->DrawLogicText(pParams->m_wsText.c_str(), - pParams->m_wsText.GetLength(), pParams->m_rtPart); -} - -CFX_RectF CXFA_FWLTheme::GetUIMargin(CFWL_ThemePart* pThemePart) const { - CFX_RectF rect; - CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget); - if (!pWidget) - return rect; - - CXFA_LayoutItem* pItem = pWidget; - CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc(); - rect = pWidgetAcc->GetUIMargin(); - if (CXFA_Para para = pWidgetAcc->GetPara()) { - rect.left += para.GetMarginLeft(); - if (pWidgetAcc->IsMultiLine()) - rect.width += para.GetMarginRight(); - } - if (!pItem->GetPrev()) { - if (pItem->GetNext()) - rect.height = 0; - } else if (!pItem->GetNext()) { - rect.top = 0; - } else { - rect.top = 0; - rect.height = 0; - } - return rect; -} - -float CXFA_FWLTheme::GetCXBorderSize() const { - return 1.0f; -} - -float CXFA_FWLTheme::GetCYBorderSize() const { - return 1.0f; -} - -float CXFA_FWLTheme::GetFontSize(CFWL_ThemePart* pThemePart) const { - if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) - return pWidget->GetDataAcc()->GetFontSize(); - return FWLTHEME_CAPACITY_FontSize; -} - -CFX_RetainPtr<CFGAS_GEFont> CXFA_FWLTheme::GetFont( - CFWL_ThemePart* pThemePart) const { - if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) - return pWidget->GetDataAcc()->GetFDEFont(); - return GetTheme(pThemePart->m_pWidget)->GetFont(); -} - -float CXFA_FWLTheme::GetLineHeight(CFWL_ThemePart* pThemePart) const { - if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) - return pWidget->GetDataAcc()->GetLineHeight(); - return kLineHeight; -} - -float CXFA_FWLTheme::GetScrollBarWidth() const { - return 9.0f; -} - -FX_COLORREF CXFA_FWLTheme::GetTextColor(CFWL_ThemePart* pThemePart) const { - if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) - return pWidget->GetDataAcc()->GetTextColor(); - return FWLTHEME_CAPACITY_TextColor; -} - -CFX_SizeF CXFA_FWLTheme::GetSpaceAboveBelow(CFWL_ThemePart* pThemePart) const { - CFX_SizeF sizeAboveBelow; - if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) { - CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc(); - if (CXFA_Para para = pWidgetAcc->GetPara()) { - sizeAboveBelow.width = para.GetSpaceAbove(); - sizeAboveBelow.height = para.GetSpaceBelow(); - } - } - return sizeAboveBelow; -} - -void CXFA_FWLTheme::CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) { - if (pParams->m_pWidget->GetClassID() == FWL_Type::MonthCalendar) { - CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); - if (!pWidget || !pParams || !m_pTextOut) - return; - - m_pTextOut->SetFont(m_pCalendarFont); - m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize); - m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor); - m_pTextOut->SetAlignment(pParams->m_iTTOAlign); - m_pTextOut->SetStyles(pParams->m_dwTTOStyles); - m_pTextOut->CalcLogicSize(pParams->m_wsText.c_str(), - pParams->m_wsText.GetLength(), rect); - } - - CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); - if (!pWidget) - return; - - CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc(); - m_pTextOut->SetFont(pAcc->GetFDEFont()); - m_pTextOut->SetFontSize(pAcc->GetFontSize()); - m_pTextOut->SetTextColor(pAcc->GetTextColor()); - if (!pParams) - return; - - m_pTextOut->SetAlignment(pParams->m_iTTOAlign); - m_pTextOut->SetStyles(pParams->m_dwTTOStyles); - m_pTextOut->CalcLogicSize(pParams->m_wsText.c_str(), - pParams->m_wsText.GetLength(), rect); -} - -CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(CFWL_Widget* pWidget) const { - switch (pWidget->GetClassID()) { - case FWL_Type::CheckBox: - return m_pCheckBoxTP.get(); - case FWL_Type::ListBox: - return m_pListBoxTP.get(); - case FWL_Type::PictureBox: - return m_pPictureBoxTP.get(); - case FWL_Type::ScrollBar: - return m_pSrollBarTP.get(); - case FWL_Type::Edit: - return m_pEditTP.get(); - case FWL_Type::ComboBox: - return m_pComboBoxTP.get(); - case FWL_Type::MonthCalendar: - return m_pMonthCalendarTP.get(); - case FWL_Type::DateTimePicker: - return m_pDateTimePickerTP.get(); - case FWL_Type::PushButton: - return m_pPushButtonTP.get(); - case FWL_Type::Caret: - return m_pCaretTP.get(); - case FWL_Type::Barcode: - return m_pBarcodeTP.get(); - default: - return nullptr; - } -} diff --git a/xfa/fxfa/app/xfa_fwltheme.h b/xfa/fxfa/app/xfa_fwltheme.h deleted file mode 100644 index a8efad0ccff82df64d2a3a8398a1f900b9d1d9d1..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_fwltheme.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_FWLTHEME_H_ -#define XFA_FXFA_APP_XFA_FWLTHEME_H_ - -#include <memory> - -#include "xfa/fwl/ifwl_themeprovider.h" -#include "xfa/fwl/theme/cfwl_barcodetp.h" -#include "xfa/fwl/theme/cfwl_carettp.h" -#include "xfa/fwl/theme/cfwl_checkboxtp.h" -#include "xfa/fwl/theme/cfwl_comboboxtp.h" -#include "xfa/fwl/theme/cfwl_datetimepickertp.h" -#include "xfa/fwl/theme/cfwl_edittp.h" -#include "xfa/fwl/theme/cfwl_listboxtp.h" -#include "xfa/fwl/theme/cfwl_monthcalendartp.h" -#include "xfa/fwl/theme/cfwl_pictureboxtp.h" -#include "xfa/fwl/theme/cfwl_pushbuttontp.h" -#include "xfa/fwl/theme/cfwl_scrollbartp.h" -#include "xfa/fwl/theme/cfwl_widgettp.h" -#include "xfa/fxfa/xfa_ffapp.h" - -class CXFA_FWLTheme final : public IFWL_ThemeProvider { - public: - explicit CXFA_FWLTheme(CXFA_FFApp* pApp); - ~CXFA_FWLTheme() override; - - // IFWL_ThemeProvider: - void DrawBackground(CFWL_ThemeBackground* pParams) override; - void DrawText(CFWL_ThemeText* pParams) override; - void CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) override; - float GetCXBorderSize() const override; - float GetCYBorderSize() const override; - CFX_RectF GetUIMargin(CFWL_ThemePart* pThemePart) const override; - float GetFontSize(CFWL_ThemePart* pThemePart) const override; - CFX_RetainPtr<CFGAS_GEFont> GetFont( - CFWL_ThemePart* pThemePart) const override; - float GetLineHeight(CFWL_ThemePart* pThemePart) const override; - float GetScrollBarWidth() const override; - FX_COLORREF GetTextColor(CFWL_ThemePart* pThemePart) const override; - CFX_SizeF GetSpaceAboveBelow(CFWL_ThemePart* pThemePart) const override; - - private: - CFWL_WidgetTP* GetTheme(CFWL_Widget* pWidget) const; - - std::unique_ptr<CFWL_CheckBoxTP> m_pCheckBoxTP; - std::unique_ptr<CFWL_ListBoxTP> m_pListBoxTP; - std::unique_ptr<CFWL_PictureBoxTP> m_pPictureBoxTP; - std::unique_ptr<CFWL_ScrollBarTP> m_pSrollBarTP; - std::unique_ptr<CFWL_EditTP> m_pEditTP; - std::unique_ptr<CFWL_ComboBoxTP> m_pComboBoxTP; - std::unique_ptr<CFWL_MonthCalendarTP> m_pMonthCalendarTP; - std::unique_ptr<CFWL_DateTimePickerTP> m_pDateTimePickerTP; - std::unique_ptr<CFWL_PushButtonTP> m_pPushButtonTP; - std::unique_ptr<CFWL_CaretTP> m_pCaretTP; - std::unique_ptr<CFWL_BarcodeTP> m_pBarcodeTP; - std::unique_ptr<CFDE_TextOut> m_pTextOut; - CFX_RetainPtr<CFGAS_GEFont> m_pCalendarFont; - CFX_WideString m_wsResource; - CXFA_FFApp* const m_pApp; - CFX_RectF m_Rect; -}; - -CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget); - -#endif // XFA_FXFA_APP_XFA_FWLTHEME_H_ diff --git a/xfa/fxfa/app/xfa_rendercontext.cpp b/xfa/fxfa/app/xfa_rendercontext.cpp deleted file mode 100644 index a855105e3dcb99871585d110fdb2b2e00bbf4e16..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_rendercontext.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/xfa_rendercontext.h" - -#include "xfa/fxfa/xfa_ffpageview.h" -#include "xfa/fxfa/xfa_ffwidget.h" -#include "xfa/fxgraphics/cfx_graphics.h" - -namespace { - -const int32_t kMaxCount = 30; - -} // namsepace - -CXFA_RenderContext::CXFA_RenderContext() - : m_pWidget(nullptr), m_pPageView(nullptr), m_pGS(nullptr), m_dwStatus(0) { - m_matrix.SetIdentity(); - m_rtClipRect.Reset(); -} - -CXFA_RenderContext::~CXFA_RenderContext() {} - -int32_t CXFA_RenderContext::StartRender(CXFA_FFPageView* pPageView, - CFX_Graphics* pGS, - const CFX_Matrix& matrix, - const CXFA_RenderOptions& options) { - m_pPageView = pPageView; - m_pGS = pGS; - m_matrix = matrix; - m_options = options; - - CFX_Matrix mtRes; - mtRes.SetReverse(matrix); - m_rtClipRect = pGS->GetClipRect(); - mtRes.TransformRect(m_rtClipRect); - m_dwStatus = m_options.m_bHighlight ? XFA_WidgetStatus_Highlight : 0; - uint32_t dwFilterType = XFA_WidgetStatus_Visible | - (m_options.m_bPrint ? XFA_WidgetStatus_Printable - : XFA_WidgetStatus_Viewable); - m_pWidgetIterator.reset( - m_pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form, dwFilterType)); - m_pWidget = m_pWidgetIterator->MoveToNext(); - return XFA_RENDERSTATUS_Ready; -} - -int32_t CXFA_RenderContext::DoRender(IFX_Pause* pPause) { - int32_t iCount = 0; - while (m_pWidget) { - CXFA_FFWidget* pWidget = m_pWidget; - CFX_RectF rtWidgetBox = pWidget->GetBBox(XFA_WidgetStatus_Visible); - rtWidgetBox.width += 1; - rtWidgetBox.height += 1; - if (rtWidgetBox.IntersectWith(m_rtClipRect)) - pWidget->RenderWidget(m_pGS, &m_matrix, m_dwStatus); - - m_pWidget = m_pWidgetIterator->MoveToNext(); - iCount++; - if (iCount > kMaxCount && pPause && pPause->NeedToPauseNow()) - return XFA_RENDERSTATUS_ToBeContinued; - } - return XFA_RENDERSTATUS_Done; -} - -void CXFA_RenderContext::StopRender() { - m_pWidgetIterator.reset(); -} diff --git a/xfa/fxfa/app/xfa_textpiece.cpp b/xfa/fxfa/app/xfa_textpiece.cpp deleted file mode 100644 index c53e45f91a22ce4554e705afd7366d54d3746f03..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_textpiece.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/app/xfa_textpiece.h" - -#include "xfa/fxfa/app/cxfa_linkuserdata.h" - -XFA_TextPiece::XFA_TextPiece() {} - -XFA_TextPiece::~XFA_TextPiece() {} diff --git a/xfa/fxfa/app/xfa_textpiece.h b/xfa/fxfa/app/xfa_textpiece.h deleted file mode 100644 index 6802df55664fe97c7b4a48863b8551b11e19a9ae..0000000000000000000000000000000000000000 --- a/xfa/fxfa/app/xfa_textpiece.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_APP_XFA_TEXTPIECE_H_ -#define XFA_FXFA_APP_XFA_TEXTPIECE_H_ - -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_string.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fgas/font/cfgas_gefont.h" - -class CXFA_LinkUserData; - -class XFA_TextPiece { - public: - XFA_TextPiece(); - ~XFA_TextPiece(); - - CFX_WideString szText; - std::vector<int32_t> Widths; - int32_t iChars; - int32_t iHorScale; - int32_t iVerScale; - int32_t iBidiLevel; - int32_t iUnderline; - int32_t iPeriod; - int32_t iLineThrough; - FX_ARGB dwColor; - FX_FLOAT fFontSize; - CFX_RectF rtPiece; - CFX_RetainPtr<CFGAS_GEFont> pFont; - CFX_RetainPtr<CXFA_LinkUserData> pLinkData; -}; - -#endif // XFA_FXFA_APP_XFA_TEXTPIECE_H_ diff --git a/xfa/fxfa/app/cxfa_eventparam.cpp b/xfa/fxfa/cxfa_eventparam.cpp similarity index 89% rename from xfa/fxfa/app/cxfa_eventparam.cpp rename to xfa/fxfa/cxfa_eventparam.cpp index bcce7219bc336aadc0afac9ae485e2121f517615..bd6742f4dd94a0e8f63075f85c31210b015a4072 100644 --- a/xfa/fxfa/app/cxfa_eventparam.cpp +++ b/xfa/fxfa/cxfa_eventparam.cpp @@ -19,8 +19,7 @@ CXFA_EventParam::CXFA_EventParam() m_iSelEnd(0), m_iSelStart(0), m_bShift(false), - m_bIsFormReady(false), - m_iValidateActivities(XFA_VALIDATE_preSubmit) {} + m_bIsFormReady(false) {} CXFA_EventParam::~CXFA_EventParam() {} @@ -44,5 +43,4 @@ void CXFA_EventParam::Reset() { m_wsSoapFaultCode.clear(); m_wsSoapFaultString.clear(); m_bIsFormReady = false; - m_iValidateActivities = XFA_VALIDATE_preSubmit; } diff --git a/xfa/fxfa/cxfa_eventparam.h b/xfa/fxfa/cxfa_eventparam.h index 3ba7a8b7f27da608e2bda695b5cecec5b1a53169..eafd76c6af5f43f936d81c71a94dfe17bce2fd91 100644 --- a/xfa/fxfa/cxfa_eventparam.h +++ b/xfa/fxfa/cxfa_eventparam.h @@ -55,7 +55,7 @@ class CXFA_EventParam { CXFA_WidgetAcc* m_pTarget; XFA_EVENTTYPE m_eType; - CFX_WideString m_wsResult; + WideString m_wsResult; bool m_bCancelAction; int32_t m_iCommitKey; bool m_bKeyDown; @@ -64,16 +64,15 @@ class CXFA_EventParam { int32_t m_iSelEnd; int32_t m_iSelStart; bool m_bShift; - CFX_WideString m_wsChange; - CFX_WideString m_wsFullText; - CFX_WideString m_wsNewContentType; - CFX_WideString m_wsNewText; - CFX_WideString m_wsPrevContentType; - CFX_WideString m_wsPrevText; - CFX_WideString m_wsSoapFaultCode; - CFX_WideString m_wsSoapFaultString; + WideString m_wsChange; + WideString m_wsFullText; + WideString m_wsNewContentType; + WideString m_wsNewText; + WideString m_wsPrevContentType; + WideString m_wsPrevText; + WideString m_wsSoapFaultCode; + WideString m_wsSoapFaultString; bool m_bIsFormReady; - int32_t m_iValidateActivities; }; #endif // XFA_FXFA_CXFA_EVENTPARAM_H_ diff --git a/xfa/fxfa/cxfa_ffapp.cpp b/xfa/fxfa/cxfa_ffapp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4cb9deb46683943bc8eb66a6e7f351f311fcaba4 --- /dev/null +++ b/xfa/fxfa/cxfa_ffapp.cpp @@ -0,0 +1,83 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffapp.h" + +#include <algorithm> +#include <memory> +#include <utility> +#include <vector> + +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fwl/cfwl_widgetmgr.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/cxfa_fwltheme.h" + +CXFA_FFApp::CXFA_FFApp(IXFA_AppProvider* pProvider) : m_pProvider(pProvider) { + // Ensure fully initialized before making an app based on |this|. + m_pFWLApp = pdfium::MakeUnique<CFWL_App>(this); +} + +CXFA_FFApp::~CXFA_FFApp() {} + +std::unique_ptr<CXFA_FFDoc> CXFA_FFApp::CreateDoc( + IXFA_DocEnvironment* pDocEnvironment, + CPDF_Document* pPDFDoc) { + if (!pPDFDoc) + return nullptr; + + auto pDoc = pdfium::MakeUnique<CXFA_FFDoc>(this, pDocEnvironment); + if (!pDoc->OpenDoc(pPDFDoc)) + return nullptr; + + return pDoc; +} + +void CXFA_FFApp::SetDefaultFontMgr( + std::unique_ptr<CFGAS_DefaultFontManager> pFontMgr) { + if (!m_pFontMgr) + m_pFontMgr = pdfium::MakeUnique<CXFA_FontMgr>(); + m_pFontMgr->SetDefFontMgr(std::move(pFontMgr)); +} + +CXFA_FontMgr* CXFA_FFApp::GetXFAFontMgr() const { + return m_pFontMgr.get(); +} + +CFGAS_FontMgr* CXFA_FFApp::GetFDEFontMgr() { + if (!m_pFDEFontMgr) { + m_pFDEFontMgr = pdfium::MakeUnique<CFGAS_FontMgr>(); + if (!m_pFDEFontMgr->EnumFonts()) + m_pFDEFontMgr = nullptr; + } + return m_pFDEFontMgr.get(); +} + +CXFA_FWLTheme* CXFA_FFApp::GetFWLTheme() { + if (!m_pFWLTheme) + m_pFWLTheme = pdfium::MakeUnique<CXFA_FWLTheme>(this); + return m_pFWLTheme.get(); +} + +CXFA_FWLAdapterWidgetMgr* CXFA_FFApp::GetFWLAdapterWidgetMgr() { + if (!m_pAdapterWidgetMgr) + m_pAdapterWidgetMgr = pdfium::MakeUnique<CXFA_FWLAdapterWidgetMgr>(); + return m_pAdapterWidgetMgr.get(); +} + +IFWL_AdapterTimerMgr* CXFA_FFApp::GetTimerMgr() const { + return m_pProvider->GetTimerMgr(); +} + +void CXFA_FFApp::ClearEventTargets() { + m_pFWLApp->GetNoteDriver()->ClearEventTargets(); +} diff --git a/xfa/fxfa/cxfa_ffapp.h b/xfa/fxfa/cxfa_ffapp.h new file mode 100644 index 0000000000000000000000000000000000000000..8ffd6578976b794dbe6d1cafebea89c5c6eb85e5 --- /dev/null +++ b/xfa/fxfa/cxfa_ffapp.h @@ -0,0 +1,76 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFAPP_H_ +#define XFA_FXFA_CXFA_FFAPP_H_ + +#include <memory> +#include <vector> + +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" +#include "xfa/fwl/cfwl_app.h" +#include "xfa/fxfa/fxfa.h" + +class CFGAS_DefaultFontManager; +class CFGAS_FontMgr; +class CFWL_WidgetMgr; +class CPDF_Document; +class CXFA_FFDocHandler; +class CXFA_FontMgr; +class CXFA_FWLAdapterWidgetMgr; +class CXFA_FWLTheme; +class IFWL_AdapterTimerMgr; + +class CXFA_FFApp { + public: + explicit CXFA_FFApp(IXFA_AppProvider* pProvider); + ~CXFA_FFApp(); + + std::unique_ptr<CXFA_FFDoc> CreateDoc(IXFA_DocEnvironment* pDocEnvironment, + CPDF_Document* pPDFDoc); + void SetDefaultFontMgr(std::unique_ptr<CFGAS_DefaultFontManager> pFontMgr); + + CXFA_FWLAdapterWidgetMgr* GetFWLAdapterWidgetMgr(); + CFWL_WidgetMgr* GetFWLWidgetMgr() const { return m_pFWLApp->GetWidgetMgr(); } + + CFGAS_FontMgr* GetFDEFontMgr(); + CXFA_FWLTheme* GetFWLTheme(); + + IXFA_AppProvider* GetAppProvider() const { return m_pProvider.Get(); } + const CFWL_App* GetFWLApp() const { return m_pFWLApp.get(); } + IFWL_AdapterTimerMgr* GetTimerMgr() const; + CXFA_FontMgr* GetXFAFontMgr() const; + + void ClearEventTargets(); + + private: + UnownedPtr<IXFA_AppProvider> const m_pProvider; + + // The fonts stored in the font manager may have been created by the default + // font manager. The GEFont::LoadFont call takes the manager as a param and + // stores it internally. When you destroy the GEFont it tries to unregister + // from the font manager and if the default font manager was destroyed first + // get get a use-after-free. The m_pFWLTheme can try to cleanup a GEFont + // when it frees, so make sure it gets cleaned up first. That requires + // m_pFWLApp to be cleaned up as well. + // + // TODO(dsinclair): The GEFont should have the FontMgr as the pointer instead + // of the DEFFontMgr so this goes away. Bug 561. + std::unique_ptr<CFGAS_FontMgr> m_pFDEFontMgr; + std::unique_ptr<CXFA_FontMgr> m_pFontMgr; + + std::unique_ptr<CXFA_FWLAdapterWidgetMgr> m_pAdapterWidgetMgr; + + // |m_pFWLApp| has to be released first, then |m_pFWLTheme| since the former + // may refers to theme manager and the latter refers to font manager. + std::unique_ptr<CXFA_FWLTheme> m_pFWLTheme; + std::unique_ptr<CFWL_App> m_pFWLApp; +}; + +#endif // XFA_FXFA_CXFA_FFAPP_H_ diff --git a/xfa/fxfa/cxfa_ffarc.cpp b/xfa/fxfa/cxfa_ffarc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64a4f70a61d1f153d24c28d05e93e7f2daf23140 --- /dev/null +++ b/xfa/fxfa/cxfa_ffarc.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffarc.h" + +#include "xfa/fxfa/parser/cxfa_arc.h" +#include "xfa/fxfa/parser/cxfa_value.h" + +CXFA_FFArc::CXFA_FFArc(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {} + +CXFA_FFArc::~CXFA_FFArc() {} + +void CXFA_FFArc::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CXFA_Value* value = m_pNode->GetFormValueIfExists(); + if (!value) + return; + + CFX_RectF rtArc = GetRectWithoutRotate(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + XFA_RectWithoutMargin(rtArc, margin); + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + DrawBorder(pGS, value->GetArcIfExists(), rtArc, mtRotate); +} diff --git a/xfa/fxfa/cxfa_ffarc.h b/xfa/fxfa/cxfa_ffarc.h new file mode 100644 index 0000000000000000000000000000000000000000..f76511995ddcf42a9aac432c8786d70547619df8 --- /dev/null +++ b/xfa/fxfa/cxfa_ffarc.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFARC_H_ +#define XFA_FXFA_CXFA_FFARC_H_ + +#include "xfa/fxfa/cxfa_ffdraw.h" + +class CXFA_FFArc : public CXFA_FFDraw { + public: + explicit CXFA_FFArc(CXFA_Node* pnode); + ~CXFA_FFArc() override; + + // CXFA_FFWidget + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; +}; + +#endif // XFA_FXFA_CXFA_FFARC_H_ diff --git a/xfa/fxfa/cxfa_ffbarcode.cpp b/xfa/fxfa/cxfa_ffbarcode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ed57b9c285d420d1ed7d9e00f342cd48ecf6a2a --- /dev/null +++ b/xfa/fxfa/cxfa_ffbarcode.cpp @@ -0,0 +1,239 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffbarcode.h" + +#include <utility> + +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fwl/cfwl_app.h" +#include "xfa/fwl/cfwl_barcode.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/parser/cxfa_border.h" + +namespace { + +const BarCodeInfo g_BarCodeData[] = { + {0x7fb4a18, L"ean13", BarcodeType::ean13, BC_EAN13}, + {0x8d13a3d, L"code11", BarcodeType::code11, BC_UNKNOWN}, + {0x8d149a8, L"code49", BarcodeType::code49, BC_UNKNOWN}, + {0x8d16347, L"code93", BarcodeType::code93, BC_UNKNOWN}, + {0x91a92e2, L"upsMaxicode", BarcodeType::upsMaxicode, BC_UNKNOWN}, + {0xa7d48dc, L"fim", BarcodeType::fim, BC_UNKNOWN}, + {0xb359fe9, L"msi", BarcodeType::msi, BC_UNKNOWN}, + {0x121f738c, L"code2Of5Matrix", BarcodeType::code2Of5Matrix, BC_UNKNOWN}, + {0x15358616, L"ucc128", BarcodeType::ucc128, BC_UNKNOWN}, + {0x1f4bfa05, L"rfid", BarcodeType::rfid, BC_UNKNOWN}, + {0x1fda71bc, L"rss14Stacked", BarcodeType::rss14Stacked, BC_UNKNOWN}, + {0x22065087, L"ean8add2", BarcodeType::ean8add2, BC_UNKNOWN}, + {0x2206508a, L"ean8add5", BarcodeType::ean8add5, BC_UNKNOWN}, + {0x2278366c, L"codabar", BarcodeType::codabar, BC_CODABAR}, + {0x2a039a8d, L"telepen", BarcodeType::telepen, BC_UNKNOWN}, + {0x323ed337, L"upcApwcd", BarcodeType::upcApwcd, BC_UNKNOWN}, + {0x347a1846, L"postUSIMB", BarcodeType::postUSIMB, BC_UNKNOWN}, + {0x391bb836, L"code128", BarcodeType::code128, BC_CODE128}, + {0x398eddaf, L"dataMatrix", BarcodeType::dataMatrix, BC_DATAMATRIX}, + {0x3cff60a8, L"upcEadd2", BarcodeType::upcEadd2, BC_UNKNOWN}, + {0x3cff60ab, L"upcEadd5", BarcodeType::upcEadd5, BC_UNKNOWN}, + {0x402cb188, L"code2Of5Standard", BarcodeType::code2Of5Standard, + BC_UNKNOWN}, + {0x411764f7, L"aztec", BarcodeType::aztec, BC_UNKNOWN}, + {0x44d4e84c, L"ean8", BarcodeType::ean8, BC_EAN8}, + {0x48468902, L"ucc128sscc", BarcodeType::ucc128sscc, BC_UNKNOWN}, + {0x4880aea4, L"upcAadd2", BarcodeType::upcAadd2, BC_UNKNOWN}, + {0x4880aea7, L"upcAadd5", BarcodeType::upcAadd5, BC_UNKNOWN}, + {0x54f18256, L"code2Of5Industrial", BarcodeType::code2Of5Industrial, + BC_UNKNOWN}, + {0x58e15f25, L"rss14Limited", BarcodeType::rss14Limited, BC_UNKNOWN}, + {0x5c08d1b9, L"postAUSReplyPaid", BarcodeType::postAUSReplyPaid, + BC_UNKNOWN}, + {0x5fa700bd, L"rss14", BarcodeType::rss14, BC_UNKNOWN}, + {0x631a7e35, L"logmars", BarcodeType::logmars, BC_UNKNOWN}, + {0x6a236236, L"pdf417", BarcodeType::pdf417, BC_PDF417}, + {0x6d098ece, L"upcean2", BarcodeType::upcean2, BC_UNKNOWN}, + {0x6d098ed1, L"upcean5", BarcodeType::upcean5, BC_UNKNOWN}, + {0x76b04eed, L"code3Of9extended", BarcodeType::code3Of9extended, + BC_UNKNOWN}, + {0x7c7db84a, L"maxicode", BarcodeType::maxicode, BC_UNKNOWN}, + {0x8266f7f7, L"ucc128random", BarcodeType::ucc128random, BC_UNKNOWN}, + {0x83eca147, L"postUSDPBC", BarcodeType::postUSDPBC, BC_UNKNOWN}, + {0x8dd71de0, L"postAUSStandard", BarcodeType::postAUSStandard, BC_UNKNOWN}, + {0x98adad85, L"plessey", BarcodeType::plessey, BC_UNKNOWN}, + {0x9f84cce6, L"ean13pwcd", BarcodeType::ean13pwcd, BC_UNKNOWN}, + {0xb514fbe9, L"upcA", BarcodeType::upcA, BC_UPCA}, + {0xb514fbed, L"upcE", BarcodeType::upcE, BC_UNKNOWN}, + {0xb5c6a853, L"ean13add2", BarcodeType::ean13add2, BC_UNKNOWN}, + {0xb5c6a856, L"ean13add5", BarcodeType::ean13add5, BC_UNKNOWN}, + {0xb81fc512, L"postUKRM4SCC", BarcodeType::postUKRM4SCC, BC_UNKNOWN}, + {0xbad34b22, L"code128SSCC", BarcodeType::code128SSCC, BC_UNKNOWN}, + {0xbfbe0cf6, L"postUS5Zip", BarcodeType::postUS5Zip, BC_UNKNOWN}, + {0xc56618e8, L"pdf417macro", BarcodeType::pdf417macro, BC_UNKNOWN}, + {0xca730f8a, L"code2Of5Interleaved", BarcodeType::code2Of5Interleaved, + BC_UNKNOWN}, + {0xd0097ac6, L"rss14Expanded", BarcodeType::rss14Expanded, BC_UNKNOWN}, + {0xd25a0240, L"postAUSCust2", BarcodeType::postAUSCust2, BC_UNKNOWN}, + {0xd25a0241, L"postAUSCust3", BarcodeType::postAUSCust3, BC_UNKNOWN}, + {0xd53ed3e7, L"rss14Truncated", BarcodeType::rss14Truncated, BC_UNKNOWN}, + {0xe72bcd57, L"code128A", BarcodeType::code128A, BC_UNKNOWN}, + {0xe72bcd58, L"code128B", BarcodeType::code128B, BC_CODE128_B}, + {0xe72bcd59, L"code128C", BarcodeType::code128C, BC_CODE128_C}, + {0xee83c50f, L"rss14StackedOmni", BarcodeType::rss14StackedOmni, + BC_UNKNOWN}, + {0xf2a18f7e, L"QRCode", BarcodeType::QRCode, BC_QR_CODE}, + {0xfaeaf37f, L"postUSStandard", BarcodeType::postUSStandard, BC_UNKNOWN}, + {0xfb48155c, L"code3Of9", BarcodeType::code3Of9, BC_CODE39}, +}; + +} // namespace. + +// static +const BarCodeInfo* CXFA_FFBarcode::GetBarcodeTypeByName( + const WideString& wsName) { + if (wsName.IsEmpty()) + return nullptr; + + auto* it = std::lower_bound( + std::begin(g_BarCodeData), std::end(g_BarCodeData), + FX_HashCode_GetW(wsName.AsStringView(), true), + [](const BarCodeInfo& arg, uint32_t hash) { return arg.uHash < hash; }); + + if (it != std::end(g_BarCodeData) && wsName.AsStringView() == it->pName) + return it; + + return nullptr; +} + +CXFA_FFBarcode::CXFA_FFBarcode(CXFA_Node* pNode) : CXFA_FFTextEdit(pNode) {} + +CXFA_FFBarcode::~CXFA_FFBarcode() {} + +bool CXFA_FFBarcode::LoadWidget() { + auto pNew = pdfium::MakeUnique<CFWL_Barcode>(GetFWLApp()); + CFWL_Barcode* pFWLBarcode = pNew.get(); + m_pNormalWidget = std::move(pNew); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + + pFWLBarcode->SetText( + m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Display)); + UpdateWidgetProperty(); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFBarcode::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + DrawBorder(pGS, m_pNode->GetWidgetAcc()->GetUIBorder(), m_rtUI, mtRotate); + RenderCaption(pGS, &mtRotate); + CFX_RectF rtWidget = m_pNormalWidget->GetWidgetRect(); + + CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); + mt.Concat(mtRotate); + m_pNormalWidget->DrawWidget(pGS, mt); +} + +void CXFA_FFBarcode::UpdateWidgetProperty() { + CXFA_FFTextEdit::UpdateWidgetProperty(); + + auto* node = GetNode(); + const BarCodeInfo* info = GetBarcodeTypeByName(node->GetBarcodeType()); + if (!info) + return; + + auto* pBarCodeWidget = static_cast<CFWL_Barcode*>(m_pNormalWidget.get()); + pBarCodeWidget->SetType(info->eBCType); + + Optional<BC_CHAR_ENCODING> encoding = + node->GetBarcodeAttribute_CharEncoding(); + if (encoding) + pBarCodeWidget->SetCharEncoding(*encoding); + + Optional<bool> calcChecksum = node->GetBarcodeAttribute_Checksum(); + if (calcChecksum) + pBarCodeWidget->SetCalChecksum(*calcChecksum); + + Optional<int32_t> dataLen = node->GetBarcodeAttribute_DataLength(); + if (dataLen) + pBarCodeWidget->SetDataLength(*dataLen); + + Optional<char> startChar = node->GetBarcodeAttribute_StartChar(); + if (startChar) + pBarCodeWidget->SetStartChar(*startChar); + + Optional<char> endChar = node->GetBarcodeAttribute_EndChar(); + if (endChar) + pBarCodeWidget->SetEndChar(*endChar); + + Optional<int32_t> ecLevel = node->GetBarcodeAttribute_ECLevel(); + if (ecLevel) + pBarCodeWidget->SetErrorCorrectionLevel(*ecLevel); + + Optional<int32_t> width = node->GetBarcodeAttribute_ModuleWidth(); + if (width) + pBarCodeWidget->SetModuleWidth(*width); + + Optional<int32_t> height = node->GetBarcodeAttribute_ModuleHeight(); + if (height) + pBarCodeWidget->SetModuleHeight(*height); + + Optional<bool> printCheck = node->GetBarcodeAttribute_PrintChecksum(); + if (printCheck) + pBarCodeWidget->SetPrintChecksum(*printCheck); + + Optional<BC_TEXT_LOC> textLoc = node->GetBarcodeAttribute_TextLocation(); + if (textLoc) + pBarCodeWidget->SetTextLocation(*textLoc); + + Optional<bool> truncate = node->GetBarcodeAttribute_Truncate(); + if (truncate) + pBarCodeWidget->SetTruncated(*truncate); + + Optional<int8_t> ratio = node->GetBarcodeAttribute_WideNarrowRatio(); + if (ratio) + pBarCodeWidget->SetWideNarrowRatio(*ratio); + + if (info->eName == BarcodeType::code3Of9 || + info->eName == BarcodeType::ean8 || info->eName == BarcodeType::ean13 || + info->eName == BarcodeType::upcA) { + pBarCodeWidget->SetPrintChecksum(true); + } +} + +bool CXFA_FFBarcode::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + auto* pBarCodeWidget = static_cast<CFWL_Barcode*>(m_pNormalWidget.get()); + if (!pBarCodeWidget || pBarCodeWidget->IsProtectedType()) + return false; + if (!m_pNode->IsOpenAccess()) + return false; + return CXFA_FFTextEdit::OnLButtonDown(dwFlags, point); +} + +bool CXFA_FFBarcode::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + auto* pBarCodeWidget = static_cast<CFWL_Barcode*>(m_pNormalWidget.get()); + if (!pBarCodeWidget || pBarCodeWidget->IsProtectedType()) + return false; + return CXFA_FFTextEdit::OnRButtonDown(dwFlags, point); +} diff --git a/xfa/fxfa/cxfa_ffbarcode.h b/xfa/fxfa/cxfa_ffbarcode.h new file mode 100644 index 0000000000000000000000000000000000000000..93984700da5395d55538683ae21268feee935b16 --- /dev/null +++ b/xfa/fxfa/cxfa_ffbarcode.h @@ -0,0 +1,103 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFBARCODE_H_ +#define XFA_FXFA_CXFA_FFBARCODE_H_ + +#include "fxbarcode/BC_Library.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_fftextedit.h" + +enum class BarcodeType { + aztec, + codabar, + code11, + code128, + code128A, + code128B, + code128C, + code128SSCC, + code2Of5Industrial, + code2Of5Interleaved, + code2Of5Matrix, + code2Of5Standard, + code3Of9, + code3Of9extended, + code49, + code93, + dataMatrix, + ean13, + ean13add2, + ean13add5, + ean13pwcd, + ean8, + ean8add2, + ean8add5, + fim, + logmars, + maxicode, + msi, + pdf417, + pdf417macro, + plessey, + postAUSCust2, + postAUSCust3, + postAUSReplyPaid, + postAUSStandard, + postUKRM4SCC, + postUS5Zip, + postUSDPBC, + postUSIMB, + postUSStandard, + QRCode, + rfid, + rss14, + rss14Expanded, + rss14Limited, + rss14Stacked, + rss14StackedOmni, + rss14Truncated, + telepen, + ucc128, + ucc128random, + ucc128sscc, + upcA, + upcAadd2, + upcAadd5, + upcApwcd, + upcE, + upcEadd2, + upcEadd5, + upcean2, + upcean5, + upsMaxicode +}; + +struct BarCodeInfo { + uint32_t uHash; + const wchar_t* pName; + BarcodeType eName; + BC_TYPE eBCType; +}; + +class CXFA_FFBarcode : public CXFA_FFTextEdit { + public: + static const BarCodeInfo* GetBarcodeTypeByName(const WideString& wsName); + + explicit CXFA_FFBarcode(CXFA_Node* pNode); + ~CXFA_FFBarcode() override; + + // CXFA_FFTextEdit + bool LoadWidget() override; + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + void UpdateWidgetProperty() override; + bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; +}; + +#endif // XFA_FXFA_CXFA_FFBARCODE_H_ diff --git a/xfa/fxfa/cxfa_ffbarcode_unittest.cpp b/xfa/fxfa/cxfa_ffbarcode_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..455b5a6ac0d9229604580a22d100a07d3f98fd88 --- /dev/null +++ b/xfa/fxfa/cxfa_ffbarcode_unittest.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fxfa/cxfa_ffbarcode.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +TEST(XFA_FFBarcode, GetBarcodeTypeByName) { + EXPECT_EQ(nullptr, CXFA_FFBarcode::GetBarcodeTypeByName(L"")); + EXPECT_EQ(nullptr, CXFA_FFBarcode::GetBarcodeTypeByName(L"not_found")); + + auto* data = CXFA_FFBarcode::GetBarcodeTypeByName(L"ean13"); + ASSERT_NE(nullptr, data); + EXPECT_EQ(BarcodeType::ean13, data->eName); + + data = CXFA_FFBarcode::GetBarcodeTypeByName(L"pdf417"); + ASSERT_NE(nullptr, data); + EXPECT_EQ(BarcodeType::pdf417, data->eName); + + data = CXFA_FFBarcode::GetBarcodeTypeByName(L"code3Of9"); + ASSERT_NE(nullptr, data); + EXPECT_EQ(BarcodeType::code3Of9, data->eName); +} diff --git a/xfa/fxfa/cxfa_ffcheckbutton.cpp b/xfa/fxfa/cxfa_ffcheckbutton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89af82cdac356bf33de42a4f7454cc3fdb7c2157 --- /dev/null +++ b/xfa/fxfa/cxfa_ffcheckbutton.cpp @@ -0,0 +1,348 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffcheckbutton.h" + +#include <utility> +#include "third_party/base/ptr_util.h" +#include "xfa/fwl/cfwl_checkbox.h" +#include "xfa/fwl/cfwl_messagemouse.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fwl/cfwl_widgetmgr.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffexclgroup.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_para.h" + +CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_Node* pNode) + : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {} + +CXFA_FFCheckButton::~CXFA_FFCheckButton() {} + +bool CXFA_FFCheckButton::LoadWidget() { + auto pNew = pdfium::MakeUnique<CFWL_CheckBox>(GetFWLApp()); + CFWL_CheckBox* pCheckBox = pNew.get(); + m_pNormalWidget = std::move(pNew); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + if (m_pNode->GetWidgetAcc()->IsRadioButton()) + pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF); + + m_pNormalWidget->LockUpdate(); + UpdateWidgetProperty(); + SetFWLCheckState(m_pNode->GetWidgetAcc()->GetCheckState()); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFCheckButton::UpdateWidgetProperty() { + auto* pCheckBox = static_cast<CFWL_CheckBox*>(m_pNormalWidget.get()); + if (!pCheckBox) + return; + + pCheckBox->SetBoxSize(m_pNode->GetWidgetAcc()->GetCheckButtonSize()); + uint32_t dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross; + switch (m_pNode->GetWidgetAcc()->GetCheckButtonMark()) { + case XFA_AttributeEnum::Check: + dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck; + break; + case XFA_AttributeEnum::Circle: + dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle; + break; + case XFA_AttributeEnum::Cross: + break; + case XFA_AttributeEnum::Diamond: + dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond; + break; + case XFA_AttributeEnum::Square: + dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare; + break; + case XFA_AttributeEnum::Star: + dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar; + break; + default: { + if (m_pNode->GetWidgetAcc()->IsCheckButtonRound()) + dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle; + } break; + } + if (m_pNode->GetWidgetAcc()->IsAllowNeutral()) + dwStyleEx |= FWL_STYLEEXT_CKB_3State; + + pCheckBox->ModifyStylesEx( + dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State); +} + +bool CXFA_FFCheckButton::PerformLayout() { + CXFA_FFWidget::PerformLayout(); + + float fCheckSize = m_pNode->GetWidgetAcc()->GetCheckButtonSize(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + CFX_RectF rtWidget = GetRectWithoutRotate(); + if (margin) + XFA_RectWithoutMargin(rtWidget, margin); + + XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; + float fCapReserve = 0; + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (caption && caption->IsVisible()) { + m_rtCaption = rtWidget; + iCapPlacement = caption->GetPlacementType(); + fCapReserve = caption->GetReserve(); + if (fCapReserve <= 0) { + if (iCapPlacement == XFA_AttributeEnum::Top || + iCapPlacement == XFA_AttributeEnum::Bottom) { + fCapReserve = rtWidget.height - fCheckSize; + } else { + fCapReserve = rtWidget.width - fCheckSize; + } + } + } + + XFA_AttributeEnum iHorzAlign = XFA_AttributeEnum::Left; + XFA_AttributeEnum iVertAlign = XFA_AttributeEnum::Top; + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) { + iHorzAlign = para->GetHorizontalAlign(); + iVertAlign = para->GetVerticalAlign(); + } + + m_rtUI = rtWidget; + CXFA_Margin* captionMargin = caption ? caption->GetMarginIfExists() : nullptr; + switch (iCapPlacement) { + case XFA_AttributeEnum::Left: { + m_rtCaption.width = fCapReserve; + CapLeftRightPlacement(captionMargin); + m_rtUI.width -= fCapReserve; + m_rtUI.left += fCapReserve; + break; + } + case XFA_AttributeEnum::Top: { + m_rtCaption.height = fCapReserve; + XFA_RectWithoutMargin(m_rtCaption, captionMargin); + m_rtUI.height -= fCapReserve; + m_rtUI.top += fCapReserve; + break; + } + case XFA_AttributeEnum::Right: { + m_rtCaption.left = m_rtCaption.right() - fCapReserve; + m_rtCaption.width = fCapReserve; + CapLeftRightPlacement(captionMargin); + m_rtUI.width -= fCapReserve; + break; + } + case XFA_AttributeEnum::Bottom: { + m_rtCaption.top = m_rtCaption.bottom() - fCapReserve; + m_rtCaption.height = fCapReserve; + XFA_RectWithoutMargin(m_rtCaption, captionMargin); + m_rtUI.height -= fCapReserve; + break; + } + case XFA_AttributeEnum::Inline: + break; + default: + iHorzAlign = XFA_AttributeEnum::Right; + break; + } + + if (iHorzAlign == XFA_AttributeEnum::Center) + m_rtUI.left += (m_rtUI.width - fCheckSize) / 2; + else if (iHorzAlign == XFA_AttributeEnum::Right) + m_rtUI.left = m_rtUI.right() - fCheckSize; + + if (iVertAlign == XFA_AttributeEnum::Middle) + m_rtUI.top += (m_rtUI.height - fCheckSize) / 2; + else if (iVertAlign == XFA_AttributeEnum::Bottom) + m_rtUI.top = m_rtUI.bottom() - fCheckSize; + + m_rtUI.width = fCheckSize; + m_rtUI.height = fCheckSize; + AddUIMargin(iCapPlacement); + m_rtCheckBox = m_rtUI; + CXFA_Border* borderUI = m_pNode->GetWidgetAcc()->GetUIBorder(); + if (borderUI) { + CXFA_Margin* borderMargin = borderUI->GetMarginIfExists(); + if (borderMargin) + XFA_RectWithoutMargin(m_rtUI, borderMargin); + } + + m_rtUI.Normalize(); + LayoutCaption(); + SetFWLRect(); + if (m_pNormalWidget) + m_pNormalWidget->Update(); + + return true; +} + +void CXFA_FFCheckButton::CapLeftRightPlacement( + const CXFA_Margin* captionMargin) { + XFA_RectWithoutMargin(m_rtCaption, captionMargin); + if (m_rtCaption.height < 0) + m_rtCaption.top += m_rtCaption.height; + if (m_rtCaption.width < 0) { + m_rtCaption.left += m_rtCaption.width; + m_rtCaption.width = -m_rtCaption.width; + } +} + +void CXFA_FFCheckButton::AddUIMargin(XFA_AttributeEnum iCapPlacement) { + CFX_RectF rtUIMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); + m_rtUI.top -= rtUIMargin.top / 2 - rtUIMargin.height / 2; + + float fLeftAddRight = rtUIMargin.left + rtUIMargin.width; + float fTopAddBottom = rtUIMargin.top + rtUIMargin.height; + if (m_rtUI.width < fLeftAddRight) { + if (iCapPlacement == XFA_AttributeEnum::Right || + iCapPlacement == XFA_AttributeEnum::Left) { + m_rtUI.left -= fLeftAddRight - m_rtUI.width; + } else { + m_rtUI.left -= 2 * (fLeftAddRight - m_rtUI.width); + } + m_rtUI.width += 2 * (fLeftAddRight - m_rtUI.width); + } + if (m_rtUI.height < fTopAddBottom) { + if (iCapPlacement == XFA_AttributeEnum::Right) + m_rtUI.left -= fTopAddBottom - m_rtUI.height; + + m_rtUI.top -= fTopAddBottom - m_rtUI.height; + m_rtUI.height += 2 * (fTopAddBottom - m_rtUI.height); + } +} + +void CXFA_FFCheckButton::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + DrawBorderWithFlag(pGS, m_pNode->GetWidgetAcc()->GetUIBorder(), m_rtUI, + mtRotate, m_pNode->GetWidgetAcc()->IsCheckButtonRound()); + RenderCaption(pGS, &mtRotate); + DrawHighlight(pGS, &mtRotate, dwStatus, + m_pNode->GetWidgetAcc()->IsCheckButtonRound()); + CFX_Matrix mt(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top); + mt.Concat(mtRotate); + GetApp()->GetFWLWidgetMgr()->OnDrawWidget(m_pNormalWidget.get(), pGS, mt); +} + +bool CXFA_FFCheckButton::OnLButtonUp(uint32_t dwFlags, + const CFX_PointF& point) { + if (!m_pNormalWidget || !IsButtonDown()) + return false; + + SetButtonDown(false); + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() { + uint32_t dwState = m_pNormalWidget->GetStates(); + if (dwState & FWL_STATE_CKB_Checked) + return XFA_CHECKSTATE_On; + if (dwState & FWL_STATE_CKB_Neutral) + return XFA_CHECKSTATE_Neutral; + return XFA_CHECKSTATE_Off; +} + +bool CXFA_FFCheckButton::CommitData() { + XFA_CHECKSTATE eCheckState = FWLState2XFAState(); + m_pNode->GetWidgetAcc()->SetCheckState(eCheckState, true); + return true; +} + +bool CXFA_FFCheckButton::IsDataChanged() { + XFA_CHECKSTATE eCheckState = FWLState2XFAState(); + return m_pNode->GetWidgetAcc()->GetCheckState() != eCheckState; +} + +void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) { + if (eCheckState == XFA_CHECKSTATE_Neutral) + m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral); + else if (eCheckState == XFA_CHECKSTATE_On) + m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked); + else + m_pNormalWidget->RemoveStates(FWL_STATE_CKB_Checked); +} + +bool CXFA_FFCheckButton::UpdateFWLData() { + if (!m_pNormalWidget) + return false; + + XFA_CHECKSTATE eState = m_pNode->GetWidgetAcc()->GetCheckState(); + SetFWLCheckState(eState); + m_pNormalWidget->Update(); + return true; +} + +void CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) { + m_pOldDelegate->OnProcessMessage(pMessage); +} + +void CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) { + CXFA_FFField::OnProcessEvent(pEvent); + switch (pEvent->GetType()) { + case CFWL_Event::Type::CheckStateChanged: { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Change; + eParam.m_wsNewText = + m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw); + + CXFA_Node* exclNode = m_pNode->GetExclGroupIfExists(); + if (ProcessCommittedData()) { + eParam.m_pTarget = exclNode ? exclNode->GetWidgetAcc() : nullptr; + if (exclNode) { + m_pDocView->AddValidateWidget(exclNode->GetWidgetAcc()); + m_pDocView->AddCalculateWidgetAcc(exclNode->GetWidgetAcc()); + exclNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, + &eParam); + } + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam); + } else { + SetFWLCheckState(m_pNode->GetWidgetAcc()->GetCheckState()); + } + if (exclNode) { + eParam.m_pTarget = exclNode->GetWidgetAcc(); + exclNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam); + } + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam); + break; + } + default: + break; + } + m_pOldDelegate->OnProcessEvent(pEvent); +} + +void CXFA_FFCheckButton::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + m_pOldDelegate->OnDrawWidget(pGraphics, matrix); +} + +FormFieldType CXFA_FFCheckButton::GetFormFieldType() { + return FormFieldType::kXFA_CheckBox; +} diff --git a/xfa/fxfa/cxfa_ffcheckbutton.h b/xfa/fxfa/cxfa_ffcheckbutton.h new file mode 100644 index 0000000000000000000000000000000000000000..f841d78ba4011e5f65a1a85f8d45dae93804e5c2 --- /dev/null +++ b/xfa/fxfa/cxfa_ffcheckbutton.h @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFCHECKBUTTON_H_ +#define XFA_FXFA_CXFA_FFCHECKBUTTON_H_ + +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" + +class CXFA_FFCheckButton : public CXFA_FFField { + public: + explicit CXFA_FFCheckButton(CXFA_Node* pNode); + ~CXFA_FFCheckButton() override; + + // CXFA_FFField + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + + bool LoadWidget() override; + bool PerformLayout() override; + bool UpdateFWLData() override; + void UpdateWidgetProperty() override; + bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + FormFieldType GetFormFieldType() override; + + void SetFWLCheckState(XFA_CHECKSTATE eCheckState); + + private: + bool CommitData() override; + bool IsDataChanged() override; + void CapLeftRightPlacement(const CXFA_Margin* captionMargin); + void AddUIMargin(XFA_AttributeEnum iCapPlacement); + XFA_CHECKSTATE FWLState2XFAState(); + + IFWL_WidgetDelegate* m_pOldDelegate; + CFX_RectF m_rtCheckBox; +}; + +#endif // XFA_FXFA_CXFA_FFCHECKBUTTON_H_ diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c024fbdef1adbb10dbe00f0630fc2054d70e691 --- /dev/null +++ b/xfa/fxfa/cxfa_ffcombobox.cpp @@ -0,0 +1,360 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffcombobox.h" + +#include <utility> +#include <vector> + +#include "xfa/fwl/cfwl_combobox.h" +#include "xfa/fwl/cfwl_eventselectchanged.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/parser/cxfa_para.h" + +namespace { + +CFWL_ComboBox* ToComboBox(CFWL_Widget* widget) { + return static_cast<CFWL_ComboBox*>(widget); +} + +} // namespace + +CXFA_FFComboBox::CXFA_FFComboBox(CXFA_Node* pNode) + : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {} + +CXFA_FFComboBox::~CXFA_FFComboBox() {} + +CFX_RectF CXFA_FFComboBox::GetBBox(uint32_t dwStatus, bool bDrawFocus) { + return bDrawFocus ? CFX_RectF() : CXFA_FFWidget::GetBBox(dwStatus); +} + +bool CXFA_FFComboBox::PtInActiveRect(const CFX_PointF& point) { + auto* pComboBox = ToComboBox(m_pNormalWidget.get()); + return pComboBox && pComboBox->GetBBox().Contains(point); +} + +bool CXFA_FFComboBox::LoadWidget() { + auto pNew = pdfium::MakeUnique<CFWL_ComboBox>(GetFWLApp()); + CFWL_ComboBox* pComboBox = pNew.get(); + m_pNormalWidget = std::move(pNew); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + + for (const auto& label : m_pNode->GetWidgetAcc()->GetChoiceListItems(false)) + pComboBox->AddString(label.AsStringView()); + + std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems(); + if (iSelArray.empty()) { + pComboBox->SetEditText( + m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw)); + } else { + pComboBox->SetCurSel(iSelArray.front()); + } + + UpdateWidgetProperty(); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFComboBox::UpdateWidgetProperty() { + auto* pComboBox = ToComboBox(m_pNormalWidget.get()); + if (!pComboBox) + return; + + uint32_t dwExtendedStyle = 0; + uint32_t dwEditStyles = FWL_STYLEEXT_EDT_ReadOnly; + dwExtendedStyle |= UpdateUIProperty(); + if (m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry()) { + dwEditStyles &= ~FWL_STYLEEXT_EDT_ReadOnly; + dwExtendedStyle |= FWL_STYLEEXT_CMB_DropDown; + } + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) { + dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly; + dwExtendedStyle |= FWL_STYLEEXT_CMB_ReadOnly; + } + dwExtendedStyle |= GetAlignment(); + m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); + + if (!m_pNode->GetWidgetAcc()->IsHorizontalScrollPolicyOff()) + dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll; + + pComboBox->EditModifyStylesEx(dwEditStyles, 0xFFFFFFFF); +} + +bool CXFA_FFComboBox::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + if (!CXFA_FFField::OnRButtonUp(dwFlags, point)) + return false; + + GetDoc()->GetDocEnvironment()->PopupMenu(this, point); + return true; +} + +bool CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) { + if (!ProcessCommittedData()) + UpdateFWLData(); + + CXFA_FFField::OnKillFocus(pNewWidget); + return true; +} + +void CXFA_FFComboBox::OpenDropDownList() { + ToComboBox(m_pNormalWidget.get())->OpenDropDownList(true); +} + +bool CXFA_FFComboBox::CommitData() { + return m_pNode->GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, m_wsNewValue); +} + +bool CXFA_FFComboBox::IsDataChanged() { + auto* pFWLcombobox = ToComboBox(m_pNormalWidget.get()); + WideString wsText = pFWLcombobox->GetEditText(); + int32_t iCursel = pFWLcombobox->GetCurSel(); + if (iCursel >= 0) { + WideString wsSel = pFWLcombobox->GetTextByIndex(iCursel); + if (wsSel == wsText) + wsText = m_pNode->GetWidgetAcc() + ->GetChoiceListItem(iCursel, true) + .value_or(L""); + } + if (m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw) == wsText) + return false; + + m_wsNewValue = wsText; + return true; +} + +void CXFA_FFComboBox::FWLEventSelChange(CXFA_EventParam* pParam) { + pParam->m_eType = XFA_EVENT_Change; + pParam->m_pTarget = m_pNode->GetWidgetAcc(); + pParam->m_wsNewText = ToComboBox(m_pNormalWidget.get())->GetEditText(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, pParam); +} + +uint32_t CXFA_FFComboBox::GetAlignment() { + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (!para) + return 0; + + uint32_t dwExtendedStyle = 0; + switch (para->GetHorizontalAlign()) { + case XFA_AttributeEnum::Center: + dwExtendedStyle |= + FWL_STYLEEXT_CMB_EditHCenter | FWL_STYLEEXT_CMB_ListItemCenterAlign; + break; + case XFA_AttributeEnum::Justify: + dwExtendedStyle |= FWL_STYLEEXT_CMB_EditJustified; + break; + case XFA_AttributeEnum::JustifyAll: + break; + case XFA_AttributeEnum::Radix: + break; + case XFA_AttributeEnum::Right: + break; + default: + dwExtendedStyle |= + FWL_STYLEEXT_CMB_EditHNear | FWL_STYLEEXT_CMB_ListItemLeftAlign; + break; + } + + switch (para->GetVerticalAlign()) { + case XFA_AttributeEnum::Middle: + dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVCenter; + break; + case XFA_AttributeEnum::Bottom: + dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVFar; + break; + default: + dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVNear; + break; + } + return dwExtendedStyle; +} + +bool CXFA_FFComboBox::UpdateFWLData() { + auto* pComboBox = ToComboBox(m_pNormalWidget.get()); + if (!pComboBox) + return false; + + std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems(); + if (!iSelArray.empty()) { + pComboBox->SetCurSel(iSelArray.front()); + } else { + pComboBox->SetCurSel(-1); + pComboBox->SetEditText( + m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw)); + } + pComboBox->Update(); + return true; +} + +bool CXFA_FFComboBox::CanUndo() { + return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + ToComboBox(m_pNormalWidget.get())->EditCanUndo(); +} + +bool CXFA_FFComboBox::CanRedo() { + return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + ToComboBox(m_pNormalWidget.get())->EditCanRedo(); +} + +bool CXFA_FFComboBox::Undo() { + return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + ToComboBox(m_pNormalWidget.get())->EditUndo(); +} + +bool CXFA_FFComboBox::Redo() { + return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + ToComboBox(m_pNormalWidget.get())->EditRedo(); +} + +bool CXFA_FFComboBox::CanCopy() { + return ToComboBox(m_pNormalWidget.get())->EditCanCopy(); +} + +bool CXFA_FFComboBox::CanCut() { + return m_pNode->IsOpenAccess() && + m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + ToComboBox(m_pNormalWidget.get())->EditCanCut(); +} + +bool CXFA_FFComboBox::CanPaste() { + return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + m_pNode->IsOpenAccess(); +} + +bool CXFA_FFComboBox::CanSelectAll() { + return ToComboBox(m_pNormalWidget.get())->EditCanSelectAll(); +} + +Optional<WideString> CXFA_FFComboBox::Copy() { + return ToComboBox(m_pNormalWidget.get())->EditCopy(); +} + +Optional<WideString> CXFA_FFComboBox::Cut() { + if (!m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry()) + return {}; + + return ToComboBox(m_pNormalWidget.get())->EditCut(); +} + +bool CXFA_FFComboBox::Paste(const WideString& wsPaste) { + return m_pNode->GetWidgetAcc()->IsChoiceListAllowTextEntry() && + ToComboBox(m_pNormalWidget.get())->EditPaste(wsPaste); +} + +void CXFA_FFComboBox::SelectAll() { + ToComboBox(m_pNormalWidget.get())->EditSelectAll(); +} + +void CXFA_FFComboBox::Delete() { + ToComboBox(m_pNormalWidget.get())->EditDelete(); +} + +void CXFA_FFComboBox::DeSelect() { + ToComboBox(m_pNormalWidget.get())->EditDeSelect(); +} + +FormFieldType CXFA_FFComboBox::GetFormFieldType() { + return FormFieldType::kXFA_ComboBox; +} + +void CXFA_FFComboBox::SetItemState(int32_t nIndex, bool bSelected) { + ToComboBox(m_pNormalWidget.get())->SetCurSel(bSelected ? nIndex : -1); + m_pNormalWidget->Update(); + AddInvalidateRect(); +} + +void CXFA_FFComboBox::InsertItem(const WideStringView& wsLabel, + int32_t nIndex) { + ToComboBox(m_pNormalWidget.get())->AddString(wsLabel); + m_pNormalWidget->Update(); + AddInvalidateRect(); +} + +void CXFA_FFComboBox::DeleteItem(int32_t nIndex) { + if (nIndex < 0) + ToComboBox(m_pNormalWidget.get())->RemoveAll(); + else + ToComboBox(m_pNormalWidget.get())->RemoveAt(nIndex); + + m_pNormalWidget->Update(); + AddInvalidateRect(); +} + +void CXFA_FFComboBox::OnTextChanged(CFWL_Widget* pWidget, + const WideString& wsChanged) { + CXFA_EventParam eParam; + eParam.m_wsPrevText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw); + eParam.m_wsChange = wsChanged; + FWLEventSelChange(&eParam); +} + +void CXFA_FFComboBox::OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp) { + CXFA_EventParam eParam; + eParam.m_wsPrevText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw); + FWLEventSelChange(&eParam); + if (m_pNode->GetWidgetAcc()->IsChoiceListCommitOnSelect() && bLButtonUp) + m_pDocView->SetFocusWidgetAcc(nullptr); +} + +void CXFA_FFComboBox::OnPreOpen(CFWL_Widget* pWidget) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_PreOpen; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::PreOpen, &eParam); +} + +void CXFA_FFComboBox::OnPostOpen(CFWL_Widget* pWidget) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_PostOpen; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::PostOpen, &eParam); +} + +void CXFA_FFComboBox::OnProcessMessage(CFWL_Message* pMessage) { + m_pOldDelegate->OnProcessMessage(pMessage); +} + +void CXFA_FFComboBox::OnProcessEvent(CFWL_Event* pEvent) { + CXFA_FFField::OnProcessEvent(pEvent); + switch (pEvent->GetType()) { + case CFWL_Event::Type::SelectChanged: { + auto* postEvent = static_cast<CFWL_EventSelectChanged*>(pEvent); + OnSelectChanged(m_pNormalWidget.get(), postEvent->bLButtonUp); + break; + } + case CFWL_Event::Type::EditChanged: { + WideString wsChanged; + OnTextChanged(m_pNormalWidget.get(), wsChanged); + break; + } + case CFWL_Event::Type::PreDropDown: { + OnPreOpen(m_pNormalWidget.get()); + break; + } + case CFWL_Event::Type::PostDropDown: { + OnPostOpen(m_pNormalWidget.get()); + break; + } + default: + break; + } + m_pOldDelegate->OnProcessEvent(pEvent); +} + +void CXFA_FFComboBox::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + m_pOldDelegate->OnDrawWidget(pGraphics, matrix); +} diff --git a/xfa/fxfa/cxfa_ffcombobox.h b/xfa/fxfa/cxfa_ffcombobox.h new file mode 100644 index 0000000000000000000000000000000000000000..a20319e3b1d631c841586cbe350bf1dc91ccd72e --- /dev/null +++ b/xfa/fxfa/cxfa_ffcombobox.h @@ -0,0 +1,70 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFCOMBOBOX_H_ +#define XFA_FXFA_CXFA_FFCOMBOBOX_H_ + +#include "xfa/fxfa/cxfa_fffield.h" + +class CXFA_FFComboBox : public CXFA_FFField { + public: + explicit CXFA_FFComboBox(CXFA_Node* pNode); + ~CXFA_FFComboBox() override; + + // CXFA_FFField + CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false) override; + bool LoadWidget() override; + void UpdateWidgetProperty() override; + bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; + bool CanUndo() override; + bool CanRedo() override; + bool Undo() override; + bool Redo() override; + + bool CanCopy() override; + bool CanCut() override; + bool CanPaste() override; + bool CanSelectAll() override; + Optional<WideString> Copy() override; + Optional<WideString> Cut() override; + bool Paste(const WideString& wsPaste) override; + void SelectAll() override; + void Delete() override; + void DeSelect() override; + FormFieldType GetFormFieldType() override; + + // IFWL_WidgetDelegate + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + + virtual void OpenDropDownList(); + + void OnTextChanged(CFWL_Widget* pWidget, const WideString& wsChanged); + void OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp); + void OnPreOpen(CFWL_Widget* pWidget); + void OnPostOpen(CFWL_Widget* pWidget); + void SetItemState(int32_t nIndex, bool bSelected); + void InsertItem(const WideStringView& wsLabel, int32_t nIndex); + void DeleteItem(int32_t nIndex); + + private: + // CXFA_FFField + bool PtInActiveRect(const CFX_PointF& point) override; + bool CommitData() override; + bool UpdateFWLData() override; + bool IsDataChanged() override; + + uint32_t GetAlignment(); + void FWLEventSelChange(CXFA_EventParam* pParam); + + WideString m_wsNewValue; + IFWL_WidgetDelegate* m_pOldDelegate; +}; + +#endif // XFA_FXFA_CXFA_FFCOMBOBOX_H_ diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.cpp b/xfa/fxfa/cxfa_ffdatetimeedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6bd096e5480f32d8717d5c8f6d77df8d8d54a97 --- /dev/null +++ b/xfa/fxfa/cxfa_ffdatetimeedit.cpp @@ -0,0 +1,216 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffdatetimeedit.h" + +#include <utility> + +#include "xfa/fwl/cfwl_datetimepicker.h" +#include "xfa/fwl/cfwl_eventselectchanged.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fwl/cfwl_widget.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +CXFA_FFDateTimeEdit::CXFA_FFDateTimeEdit(CXFA_Node* pNode) + : CXFA_FFTextEdit(pNode) {} + +CXFA_FFDateTimeEdit::~CXFA_FFDateTimeEdit() {} + +CFX_RectF CXFA_FFDateTimeEdit::GetBBox(uint32_t dwStatus, bool bDrawFocus) { + if (bDrawFocus) + return CFX_RectF(); + return CXFA_FFWidget::GetBBox(dwStatus); +} + +bool CXFA_FFDateTimeEdit::PtInActiveRect(const CFX_PointF& point) { + auto* pPicker = static_cast<CFWL_DateTimePicker*>(m_pNormalWidget.get()); + return pPicker && pPicker->GetBBox().Contains(point); +} + +bool CXFA_FFDateTimeEdit::LoadWidget() { + auto pNewPicker = pdfium::MakeUnique<CFWL_DateTimePicker>(GetFWLApp()); + CFWL_DateTimePicker* pWidget = pNewPicker.get(); + m_pNormalWidget = std::move(pNewPicker); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + + WideString wsText = + m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Display); + pWidget->SetEditText(wsText); + + CXFA_Value* value = m_pNode->GetFormValueIfExists(); + if (value) { + switch (value->GetChildValueClassID()) { + case XFA_Element::Date: { + if (!wsText.IsEmpty()) { + CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pNode.Get()); + CFX_DateTime date = lcValue.GetDate(); + if (date.IsSet()) + pWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); + } + } break; + default: + break; + } + } + UpdateWidgetProperty(); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFDateTimeEdit::UpdateWidgetProperty() { + CFWL_DateTimePicker* pWidget = + static_cast<CFWL_DateTimePicker*>(m_pNormalWidget.get()); + if (!pWidget) + return; + + uint32_t dwExtendedStyle = FWL_STYLEEXT_DTP_ShortDateFormat; + dwExtendedStyle |= UpdateUIProperty(); + dwExtendedStyle |= GetAlignment(); + m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); + + uint32_t dwEditStyles = 0; + Optional<int32_t> numCells = m_pNode->GetWidgetAcc()->GetNumberOfCells(); + if (numCells && *numCells > 0) { + dwEditStyles |= FWL_STYLEEXT_EDT_CombText; + pWidget->SetEditLimit(*numCells); + } + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) + dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly; + if (!m_pNode->GetWidgetAcc()->IsHorizontalScrollPolicyOff()) + dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll; + + pWidget->ModifyEditStylesEx(dwEditStyles, 0xFFFFFFFF); +} + +uint32_t CXFA_FFDateTimeEdit::GetAlignment() { + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (!para) + return 0; + + uint32_t dwExtendedStyle = 0; + switch (para->GetHorizontalAlign()) { + case XFA_AttributeEnum::Center: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHCenter; + break; + case XFA_AttributeEnum::Justify: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditJustified; + break; + case XFA_AttributeEnum::JustifyAll: + case XFA_AttributeEnum::Radix: + break; + case XFA_AttributeEnum::Right: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHFar; + break; + default: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHNear; + break; + } + + switch (para->GetVerticalAlign()) { + case XFA_AttributeEnum::Middle: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVCenter; + break; + case XFA_AttributeEnum::Bottom: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVFar; + break; + default: + dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVNear; + break; + } + return dwExtendedStyle; +} + +bool CXFA_FFDateTimeEdit::CommitData() { + auto* pPicker = static_cast<CFWL_DateTimePicker*>(m_pNormalWidget.get()); + if (!m_pNode->GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Edit, + pPicker->GetEditText())) { + return false; + } + + m_pNode->GetWidgetAcc()->UpdateUIDisplay(GetDoc()->GetDocView(), this); + return true; +} + +bool CXFA_FFDateTimeEdit::UpdateFWLData() { + if (!m_pNormalWidget) + return false; + + XFA_VALUEPICTURE eType = XFA_VALUEPICTURE_Display; + if (IsFocused()) + eType = XFA_VALUEPICTURE_Edit; + + WideString wsText = m_pNode->GetWidgetAcc()->GetValue(eType); + auto* normalWidget = static_cast<CFWL_DateTimePicker*>(m_pNormalWidget.get()); + normalWidget->SetEditText(wsText); + if (IsFocused() && !wsText.IsEmpty()) { + CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pNode.Get()); + CFX_DateTime date = lcValue.GetDate(); + if (lcValue.IsValid()) { + if (date.IsSet()) + normalWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); + } + } + m_pNormalWidget->Update(); + return true; +} + +bool CXFA_FFDateTimeEdit::IsDataChanged() { + if (m_dwStatus & XFA_WidgetStatus_TextEditValueChanged) + return true; + + WideString wsText = + static_cast<CFWL_DateTimePicker*>(m_pNormalWidget.get())->GetEditText(); + return m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Edit) != wsText; +} + +void CXFA_FFDateTimeEdit::OnSelectChanged(CFWL_Widget* pWidget, + int32_t iYear, + int32_t iMonth, + int32_t iDay) { + WideString wsPicture = + m_pNode->GetWidgetAcc()->GetPictureContent(XFA_VALUEPICTURE_Edit); + + CXFA_LocaleValue date(XFA_VT_DATE, GetDoc()->GetXFADoc()->GetLocalMgr()); + date.SetDate(CFX_DateTime(iYear, iMonth, iDay, 0, 0, 0, 0)); + + WideString wsDate; + date.FormatPatterns(wsDate, wsPicture, m_pNode->GetLocale(), + XFA_VALUEPICTURE_Edit); + + auto* pDateTime = static_cast<CFWL_DateTimePicker*>(m_pNormalWidget.get()); + pDateTime->SetEditText(wsDate); + pDateTime->Update(); + GetDoc()->GetDocEnvironment()->SetFocusWidget(GetDoc(), nullptr); + + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Change; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + eParam.m_wsNewText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam); +} + +void CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) { + if (pEvent->GetType() == CFWL_Event::Type::SelectChanged) { + auto* event = static_cast<CFWL_EventSelectChanged*>(pEvent); + OnSelectChanged(m_pNormalWidget.get(), event->iYear, event->iMonth, + event->iDay); + return; + } + CXFA_FFTextEdit::OnProcessEvent(pEvent); +} diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.h b/xfa/fxfa/cxfa_ffdatetimeedit.h new file mode 100644 index 0000000000000000000000000000000000000000..a549cbb80f1362aeca0b0f5954bd4d0e7849886a --- /dev/null +++ b/xfa/fxfa/cxfa_ffdatetimeedit.h @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFDATETIMEEDIT_H_ +#define XFA_FXFA_CXFA_FFDATETIMEEDIT_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/cxfa_fftextedit.h" + +enum XFA_DATETIMETYPE { + XFA_DATETIMETYPE_Date = 0, + XFA_DATETIMETYPE_Time, + XFA_DATETIMETYPE_DateAndTime +}; + +class CFWL_Event; +class CFWL_Widget; + +class CXFA_FFDateTimeEdit : public CXFA_FFTextEdit { + public: + explicit CXFA_FFDateTimeEdit(CXFA_Node* pNode); + ~CXFA_FFDateTimeEdit() override; + + // CXFA_FFTextEdit + CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false) override; + bool LoadWidget() override; + void UpdateWidgetProperty() override; + void OnProcessEvent(CFWL_Event* pEvent) override; + + void OnSelectChanged(CFWL_Widget* pWidget, + int32_t iYear, + int32_t iMonth, + int32_t iDay); + + private: + bool PtInActiveRect(const CFX_PointF& point) override; + bool CommitData() override; + bool UpdateFWLData() override; + bool IsDataChanged() override; + + uint32_t GetAlignment(); +}; + +#endif // XFA_FXFA_CXFA_FFDATETIMEEDIT_H_ diff --git a/xfa/fxfa/cxfa_ffdoc.cpp b/xfa/fxfa/cxfa_ffdoc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4dfa78edb1f167b2d87e79438179d433587041be --- /dev/null +++ b/xfa/fxfa/cxfa_ffdoc.cpp @@ -0,0 +1,416 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffdoc.h" + +#include <algorithm> +#include <memory> +#include <vector> + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fpdfdoc/cpdf_nametree.h" +#include "core/fxcrt/cfx_checksumcontext.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/cfx_seekablemultistream.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/parser/cxfa_acrobat.h" +#include "xfa/fxfa/parser/cxfa_acrobat7.h" +#include "xfa/fxfa/parser/cxfa_dataexporter.h" +#include "xfa/fxfa/parser/cxfa_dataimporter.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_dynamicrender.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +namespace { + +struct FX_BASE64DATA { + uint32_t data1 : 2; + uint32_t data2 : 6; + uint32_t data3 : 4; + uint32_t data4 : 4; + uint32_t data5 : 6; + uint32_t data6 : 2; + uint32_t data7 : 8; +}; + +const uint8_t kStartValuesRemoved = 43; +const uint8_t kDecoderMapSize = 80; +const uint8_t g_FXBase64DecoderMap[kDecoderMapSize] = { + 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, +}; + +uint8_t base64DecoderValue(uint8_t val) { + if (val < kStartValuesRemoved || val >= kStartValuesRemoved + kDecoderMapSize) + return 0xFF; + return g_FXBase64DecoderMap[val - kStartValuesRemoved]; +} + +void Base64DecodePiece(const char src[4], + int32_t iChars, + FX_BASE64DATA& dst, + int32_t& iBytes) { + ASSERT(iChars > 0 && iChars < 5); + iBytes = 1; + dst.data2 = base64DecoderValue(static_cast<uint8_t>(src[0])); + if (iChars > 1) { + uint8_t b = base64DecoderValue(static_cast<uint8_t>(src[1])); + dst.data1 = b >> 4; + dst.data4 = b; + if (iChars > 2) { + iBytes = 2; + b = base64DecoderValue(static_cast<uint8_t>(src[2])); + dst.data3 = b >> 2; + dst.data6 = b; + if (iChars > 3) { + iBytes = 3; + dst.data5 = base64DecoderValue(static_cast<uint8_t>(src[3])); + } else { + dst.data5 = 0; + } + } else { + dst.data3 = 0; + } + } else { + dst.data1 = 0; + } +} + +int32_t Base64DecodeW(const wchar_t* pSrc, int32_t iSrcLen, uint8_t* pDst) { + ASSERT(pSrc); + if (iSrcLen < 1) { + return 0; + } + while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') { + iSrcLen--; + } + if (iSrcLen < 1) { + return 0; + } + if (!pDst) { + int32_t 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; + } + char srcData[4]; + FX_BASE64DATA dstData; + int32_t iChars = 4, iBytes; + uint8_t* pDstEnd = pDst; + while (iSrcLen > 0) { + if (iSrcLen > 3) { + srcData[0] = (char)*pSrc++; + srcData[1] = (char)*pSrc++; + srcData[2] = (char)*pSrc++; + srcData[3] = (char)*pSrc++; + iSrcLen -= 4; + } else { + *((uint32_t*)&dstData) = 0; + *((uint32_t*)srcData) = 0; + srcData[0] = (char)*pSrc++; + if (iSrcLen > 1) { + srcData[1] = (char)*pSrc++; + } + if (iSrcLen > 2) { + srcData[2] = (char)*pSrc++; + } + iChars = iSrcLen; + iSrcLen = 0; + } + Base64DecodePiece(srcData, iChars, dstData, iBytes); + *pDstEnd++ = ((uint8_t*)&dstData)[0]; + if (iBytes > 1) { + *pDstEnd++ = ((uint8_t*)&dstData)[1]; + } + if (iBytes > 2) { + *pDstEnd++ = ((uint8_t*)&dstData)[2]; + } + } + return pDstEnd - pDst; +} + +} // namespace + +CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment) + : m_pDocEnvironment(pDocEnvironment), m_pApp(pApp) {} + +CXFA_FFDoc::~CXFA_FFDoc() { + CloseDoc(); +} + +int32_t CXFA_FFDoc::StartLoad() { + m_pNotify = pdfium::MakeUnique<CXFA_FFNotify>(this); + m_pDocumentParser = pdfium::MakeUnique<CXFA_DocumentParser>(m_pNotify.get()); + return m_pDocumentParser->StartParse(m_pStream, XFA_PacketType::Xdp); +} + +bool XFA_GetPDFContentsFromPDFXML(CFX_XMLNode* pPDFElement, + uint8_t*& pByteBuffer, + int32_t& iBufferSize) { + CFX_XMLElement* pDocumentElement = nullptr; + for (CFX_XMLNode* pXMLNode = + pPDFElement->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode); + WideString wsTagName = pXMLElement->GetName(); + if (wsTagName == L"document") { + pDocumentElement = pXMLElement; + break; + } + } + } + if (!pDocumentElement) { + return false; + } + CFX_XMLElement* pChunkElement = nullptr; + for (CFX_XMLNode* pXMLNode = + pDocumentElement->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode); + WideString wsTagName = pXMLElement->GetName(); + if (wsTagName == L"chunk") { + pChunkElement = pXMLElement; + break; + } + } + } + if (!pChunkElement) { + return false; + } + WideString wsPDFContent = pChunkElement->GetTextData(); + iBufferSize = + Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), nullptr); + pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1); + pByteBuffer[iBufferSize] = '0'; // FIXME: I bet this is wrong. + Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), pByteBuffer); + return true; +} +void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) { + CXFA_Node* pChildNode = pNewRoot->GetFirstChild(); + while (pChildNode) { + CXFA_Node* pOriginChild = + pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash()); + if (pOriginChild) { + pChildNode = pChildNode->GetNextSibling(); + } else { + CXFA_Node* pNextSibling = pChildNode->GetNextSibling(); + pNewRoot->RemoveChild(pChildNode, true); + pOriginRoot->InsertChild(pChildNode, nullptr); + pChildNode = pNextSibling; + pNextSibling = nullptr; + } + } +} + +int32_t CXFA_FFDoc::DoLoad() { + int32_t iStatus = m_pDocumentParser->DoParse(); + if (iStatus == XFA_PARSESTATUS_Done && !m_pPDFDoc) + return XFA_PARSESTATUS_SyntaxErr; + return iStatus; +} + +void CXFA_FFDoc::StopLoad() { + m_pPDFFontMgr = pdfium::MakeUnique<CFGAS_PDFFontMgr>( + GetPDFDoc(), GetApp()->GetFDEFontMgr()); + + m_FormType = FormType::kXFAForeground; + CXFA_Node* pConfig = ToNode( + m_pDocumentParser->GetDocument()->GetXFAObject(XFA_HASHCODE_Config)); + if (!pConfig) + return; + + CXFA_Acrobat* pAcrobat = + pConfig->GetFirstChildByClass<CXFA_Acrobat>(XFA_Element::Acrobat); + if (!pAcrobat) + return; + + CXFA_Acrobat7* pAcrobat7 = + pAcrobat->GetFirstChildByClass<CXFA_Acrobat7>(XFA_Element::Acrobat7); + if (!pAcrobat7) + return; + + CXFA_DynamicRender* pDynamicRender = + pAcrobat7->GetFirstChildByClass<CXFA_DynamicRender>( + XFA_Element::DynamicRender); + if (!pDynamicRender) + return; + + WideString wsType = pDynamicRender->JSObject()->GetContent(false); + if (wsType == L"required") + m_FormType = FormType::kXFAFull; +} + +CXFA_FFDocView* CXFA_FFDoc::CreateDocView() { + if (!m_DocView) + m_DocView = pdfium::MakeUnique<CXFA_FFDocView>(this); + + return m_DocView.get(); +} + +CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) { + return m_DocView && m_DocView->GetXFALayout() == pLayout ? m_DocView.get() + : nullptr; +} + +CXFA_FFDocView* CXFA_FFDoc::GetDocView() { + return m_DocView.get(); +} + +bool CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) { + if (!pPDFDoc) + return false; + + const CPDF_Dictionary* pRoot = pPDFDoc->GetRoot(); + if (!pRoot) + return false; + + CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm"); + if (!pAcroForm) + return false; + + CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA"); + if (!pElementXFA) + return false; + + std::vector<CPDF_Stream*> xfaStreams; + if (pElementXFA->IsArray()) { + CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA; + for (size_t i = 0; i < pXFAArray->GetCount() / 2; i++) { + if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1)) + xfaStreams.push_back(pStream); + } + } else if (pElementXFA->IsStream()) { + xfaStreams.push_back((CPDF_Stream*)pElementXFA); + } + if (xfaStreams.empty()) + return false; + + m_pPDFDoc = pPDFDoc; + m_pStream = pdfium::MakeRetain<CFX_SeekableMultiStream>(xfaStreams); + return true; +} + +void CXFA_FFDoc::CloseDoc() { + if (m_DocView) { + m_DocView->RunDocClose(); + m_DocView.reset(); + } + CXFA_Document* doc = + m_pDocumentParser ? m_pDocumentParser->GetDocument() : nullptr; + if (doc) + doc->ClearLayoutData(); + + m_pDocumentParser.reset(); + m_pNotify.reset(); + m_pPDFFontMgr.reset(); + m_HashToDibDpiMap.clear(); + m_pApp->ClearEventTargets(); +} + +RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage( + const WideStringView& wsName, + int32_t& iImageXDpi, + int32_t& iImageYDpi) { + if (!m_pPDFDoc) + return nullptr; + + uint32_t dwHash = FX_HashCode_GetW(wsName, false); + auto it = m_HashToDibDpiMap.find(dwHash); + if (it != m_HashToDibDpiMap.end()) { + iImageXDpi = it->second.iImageXDpi; + iImageYDpi = it->second.iImageYDpi; + return it->second.pDibSource.As<CFX_DIBitmap>(); + } + + const CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot(); + if (!pRoot) + return nullptr; + + CPDF_Dictionary* pNames = pRoot->GetDictFor("Names"); + if (!pNames) + return nullptr; + + CPDF_Dictionary* pXFAImages = pNames->GetDictFor("XFAImages"); + if (!pXFAImages) + return nullptr; + + CPDF_NameTree nametree(pXFAImages); + CPDF_Object* pObject = nametree.LookupValue(WideString(wsName)); + if (!pObject) { + for (size_t i = 0; i < nametree.GetCount(); i++) { + WideString wsTemp; + CPDF_Object* pTempObject = nametree.LookupValueAndName(i, &wsTemp); + if (wsTemp == wsName) { + pObject = pTempObject; + break; + } + } + } + + CPDF_Stream* pStream = ToStream(pObject); + if (!pStream) + return nullptr; + + auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream); + pAcc->LoadAllDataFiltered(); + + RetainPtr<IFX_SeekableStream> pImageFileRead = + pdfium::MakeRetain<CFX_MemoryStream>( + const_cast<uint8_t*>(pAcc->GetData()), pAcc->GetSize(), false); + + RetainPtr<CFX_DIBitmap> pDibSource = XFA_LoadImageFromBuffer( + pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi); + m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi}; + return pDibSource; +} + +bool CXFA_FFDoc::SavePackage(CXFA_Node* pNode, + const RetainPtr<IFX_SeekableStream>& pFile, + CFX_ChecksumContext* pCSContext) { + auto pExport = pdfium::MakeUnique<CXFA_DataExporter>(GetXFADoc()); + if (!pNode) + return !!pExport->Export(pFile); + + ByteString bsChecksum; + if (pCSContext) + bsChecksum = pCSContext->GetChecksum(); + + return !!pExport->Export( + pFile, pNode, 0, bsChecksum.GetLength() ? bsChecksum.c_str() : nullptr); +} + +bool CXFA_FFDoc::ImportData(const RetainPtr<IFX_SeekableStream>& pStream, + bool bXDP) { + auto importer = + pdfium::MakeUnique<CXFA_DataImporter>(m_pDocumentParser->GetDocument()); + return importer->ImportData(pStream); +} diff --git a/xfa/fxfa/cxfa_ffdoc.h b/xfa/fxfa/cxfa_ffdoc.h new file mode 100644 index 0000000000000000000000000000000000000000..e1835689ec55705cd497fc5cc9d484a1e7ead906 --- /dev/null +++ b/xfa/fxfa/cxfa_ffdoc.h @@ -0,0 +1,98 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFDOC_H_ +#define XFA_FXFA_CXFA_FFDOC_H_ + +#include <map> +#include <memory> + +#include "core/fxcrt/unowned_ptr.h" +#include "xfa/fxfa/fxfa.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_document_parser.h" + +class CFGAS_PDFFontMgr; +class CFX_ChecksumContext; +class CPDF_Document; +class CXFA_FFApp; +class CXFA_FFNotify; +class CXFA_FFDocView; + +struct FX_IMAGEDIB_AND_DPI { + FX_IMAGEDIB_AND_DPI(); + FX_IMAGEDIB_AND_DPI(const FX_IMAGEDIB_AND_DPI& that); + FX_IMAGEDIB_AND_DPI(const RetainPtr<CFX_DIBSource>& pDib, + int32_t xDpi, + int32_t yDpi); + ~FX_IMAGEDIB_AND_DPI(); + + RetainPtr<CFX_DIBSource> pDibSource; + int32_t iImageXDpi; + int32_t iImageYDpi; +}; + +inline FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI() = default; +inline FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI( + const FX_IMAGEDIB_AND_DPI& that) = default; + +inline FX_IMAGEDIB_AND_DPI::FX_IMAGEDIB_AND_DPI( + const RetainPtr<CFX_DIBSource>& pDib, + int32_t xDpi, + int32_t yDpi) + : pDibSource(pDib), iImageXDpi(xDpi), iImageYDpi(yDpi) {} + +inline FX_IMAGEDIB_AND_DPI::~FX_IMAGEDIB_AND_DPI() = default; + +class CXFA_FFDoc { + public: + CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment); + ~CXFA_FFDoc(); + + IXFA_DocEnvironment* GetDocEnvironment() const { + return m_pDocEnvironment.Get(); + } + FormType GetFormType() const { return m_FormType; } + + int32_t StartLoad(); + int32_t DoLoad(); + void StopLoad(); + + CXFA_FFDocView* CreateDocView(); + + bool OpenDoc(CPDF_Document* pPDFDoc); + void CloseDoc(); + + CXFA_Document* GetXFADoc() const { return m_pDocumentParser->GetDocument(); } + CXFA_FFApp* GetApp() const { return m_pApp.Get(); } + CPDF_Document* GetPDFDoc() const { return m_pPDFDoc.Get(); } + CXFA_FFDocView* GetDocView(CXFA_LayoutProcessor* pLayout); + CXFA_FFDocView* GetDocView(); + RetainPtr<CFX_DIBitmap> GetPDFNamedImage(const WideStringView& wsName, + int32_t& iImageXDpi, + int32_t& iImageYDpi); + CFGAS_PDFFontMgr* GetPDFFontMgr() const { return m_pPDFFontMgr.get(); } + + bool SavePackage(CXFA_Node* pNode, + const RetainPtr<IFX_SeekableStream>& pFile, + CFX_ChecksumContext* pCSContext); + bool ImportData(const RetainPtr<IFX_SeekableStream>& pStream, + bool bXDP = true); + + private: + UnownedPtr<IXFA_DocEnvironment> const m_pDocEnvironment; + std::unique_ptr<CXFA_DocumentParser> m_pDocumentParser; + RetainPtr<IFX_SeekableStream> m_pStream; + UnownedPtr<CXFA_FFApp> const m_pApp; + std::unique_ptr<CXFA_FFNotify> m_pNotify; + UnownedPtr<CPDF_Document> m_pPDFDoc; + std::map<uint32_t, FX_IMAGEDIB_AND_DPI> m_HashToDibDpiMap; + std::unique_ptr<CXFA_FFDocView> m_DocView; + std::unique_ptr<CFGAS_PDFFontMgr> m_pPDFFontMgr; + FormType m_FormType = FormType::kXFAForeground; +}; + +#endif // XFA_FXFA_CXFA_FFDOC_H_ diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4e52990d5a266b7b8f0dc78ba001ac8c77969e2 --- /dev/null +++ b/xfa/fxfa/cxfa_ffdocview.cpp @@ -0,0 +1,803 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffdocview.h" + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffbarcode.h" +#include "xfa/fxfa/cxfa_ffcheckbutton.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdraw.h" +#include "xfa/fxfa/cxfa_ffexclgroup.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffimage.h" +#include "xfa/fxfa/cxfa_ffimageedit.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffpushbutton.h" +#include "xfa/fxfa/cxfa_ffsignature.h" +#include "xfa/fxfa/cxfa_ffsubform.h" +#include "xfa/fxfa/cxfa_fftext.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/cxfa_textprovider.h" +#include "xfa/fxfa/cxfa_widgetacciterator.h" +#include "xfa/fxfa/parser/cxfa_acrobat.h" +#include "xfa/fxfa/parser/cxfa_binditems.h" +#include "xfa/fxfa/parser/cxfa_calculate.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_pageset.h" +#include "xfa/fxfa/parser/cxfa_present.h" +#include "xfa/fxfa/parser/cxfa_subform.h" +#include "xfa/fxfa/parser/cxfa_validate.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +const XFA_AttributeEnum gs_EventActivity[] = { + XFA_AttributeEnum::Click, XFA_AttributeEnum::Change, + XFA_AttributeEnum::DocClose, XFA_AttributeEnum::DocReady, + XFA_AttributeEnum::Enter, XFA_AttributeEnum::Exit, + XFA_AttributeEnum::Full, XFA_AttributeEnum::IndexChange, + XFA_AttributeEnum::Initialize, XFA_AttributeEnum::MouseDown, + XFA_AttributeEnum::MouseEnter, XFA_AttributeEnum::MouseExit, + XFA_AttributeEnum::MouseUp, XFA_AttributeEnum::PostExecute, + XFA_AttributeEnum::PostOpen, XFA_AttributeEnum::PostPrint, + XFA_AttributeEnum::PostSave, XFA_AttributeEnum::PostSign, + XFA_AttributeEnum::PostSubmit, XFA_AttributeEnum::PreExecute, + XFA_AttributeEnum::PreOpen, XFA_AttributeEnum::PrePrint, + XFA_AttributeEnum::PreSave, XFA_AttributeEnum::PreSign, + XFA_AttributeEnum::PreSubmit, XFA_AttributeEnum::Ready, + XFA_AttributeEnum::Unknown, +}; + +CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) + : m_bLayoutEvent(false), + m_pListFocusWidget(nullptr), + m_bInLayoutStatus(false), + m_pDoc(pDoc), + m_pXFADocLayout(nullptr), + m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None), + m_iLock(0) {} + +CXFA_FFDocView::~CXFA_FFDocView() { + DestroyDocView(); +} + +void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) { + RunBindItems(); + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true, + nullptr); + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true, + nullptr); +} + +int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) { + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; + m_pDoc->GetXFADoc()->DoProtoMerge(); + m_pDoc->GetXFADoc()->DoDataMerge(); + m_pXFADocLayout = GetXFALayout(); + + int32_t iStatus = m_pXFADocLayout->StartLayout(); + if (iStatus < 0) + return iStatus; + + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) + return iStatus; + + InitLayout(pRootItem); + InitCalculate(pRootItem); + InitValidate(pRootItem); + + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr); + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; + return iStatus; +} + +int32_t CXFA_FFDocView::DoLayout() { + int32_t iStatus = 100; + iStatus = m_pXFADocLayout->DoLayout(); + if (iStatus != 100) + return iStatus; + + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing; + return iStatus; +} + +void CXFA_FFDocView::StopLayout() { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) + return; + + CXFA_Subform* pSubformNode = + pRootItem->GetChild<CXFA_Subform>(0, XFA_Element::Subform, false); + if (!pSubformNode) + return; + + CXFA_PageSet* pPageSetNode = + pSubformNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet); + if (!pPageSetNode) + return; + + RunCalculateWidgets(); + RunValidate(); + + InitLayout(pPageSetNode); + InitCalculate(pPageSetNode); + InitValidate(pPageSetNode); + + ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true, + nullptr); + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, + nullptr); + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true, + nullptr); + + RunCalculateWidgets(); + RunValidate(); + + if (RunLayout()) { + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, + nullptr); + } + + m_CalculateAccs.clear(); + if (m_pFocusAcc && !m_pFocusWidget) + SetFocusWidgetAcc(m_pFocusAcc.Get()); + + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End; +} + +void CXFA_FFDocView::ShowNullTestMsg() { + int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg); + CXFA_FFApp* pApp = m_pDoc->GetApp(); + IXFA_AppProvider* pAppProvider = pApp->GetAppProvider(); + if (pAppProvider && iCount) { + int32_t iRemain = iCount > 7 ? iCount - 7 : 0; + iCount -= iRemain; + WideString wsMsg; + for (int32_t i = 0; i < iCount; i++) + wsMsg += m_arrNullTestMsg[i] + L"\n"; + + if (iRemain > 0) { + wsMsg += L"\n" + WideString::Format( + L"Message limit exceeded. Remaining %d " + L"validation errors not reported.", + iRemain); + } + pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status, + XFA_MB_OK); + } + m_arrNullTestMsg.clear(); +} + +void CXFA_FFDocView::UpdateDocView() { + if (IsUpdateLocked()) + return; + + LockUpdate(); + for (CXFA_Node* pNode : m_NewAddedNodes) { + InitCalculate(pNode); + InitValidate(pNode); + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr); + } + m_NewAddedNodes.clear(); + + RunSubformIndexChange(); + RunCalculateWidgets(); + RunValidate(); + + ShowNullTestMsg(); + + if (RunLayout() && m_bLayoutEvent) + RunEventLayoutReady(); + + m_bLayoutEvent = false; + m_CalculateAccs.clear(); + RunInvalidate(); + UnlockUpdate(); +} + +int32_t CXFA_FFDocView::CountPageViews() const { + return m_pXFADocLayout ? m_pXFADocLayout->CountPages() : 0; +} + +CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const { + if (!m_pXFADocLayout) + return nullptr; + return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex)); +} + +CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const { + return m_pDoc->GetXFADoc()->GetDocLayout(); +} + +bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_Node* pNode = pWidgetAcc->GetNode(); + XFA_Element eType = pNode->GetElementType(); + if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) + return false; + + pWidgetAcc->ResetData(); + pWidgetAcc->UpdateUIDisplay(this, nullptr); + CXFA_Validate* validate = pNode->GetValidateIfExists(); + if (!validate) + return true; + + AddValidateWidget(pWidgetAcc); + validate->SetFlag(XFA_NodeFlag_NeedsInitApp, false); + return true; +} + +void CXFA_FFDocView::ResetWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { + m_bLayoutEvent = true; + bool bChanged = false; + CXFA_Node* pFormNode = nullptr; + if (pWidgetAcc) { + bChanged = ResetSingleWidgetAccData(pWidgetAcc); + pFormNode = pWidgetAcc->GetNode(); + } else { + pFormNode = GetRootSubform(); + } + if (!pFormNode) + return; + + if (pFormNode->GetElementType() != XFA_Element::Field && + pFormNode->GetElementType() != XFA_Element::ExclGroup) { + CXFA_WidgetAccIterator Iterator(pFormNode); + while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) { + bChanged |= ResetSingleWidgetAccData(pAcc); + if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup) + Iterator.SkipTree(); + } + } + if (bChanged) + m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get()); +} + +int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam, + CXFA_WidgetAcc* pWidgetAcc) { + if (!pParam) + return XFA_EVENTERROR_Error; + + if (pParam->m_eType == XFA_EVENT_Validate) { + WideString wsValidateStr(L"preSubmit"); + CXFA_Node* pConfigItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config)); + if (pConfigItem) { + CXFA_Acrobat* pAcrobatNode = + pConfigItem->GetChild<CXFA_Acrobat>(0, XFA_Element::Acrobat, false); + CXFA_Validate* pValidateNode = + pAcrobatNode ? pAcrobatNode->GetChild<CXFA_Validate>( + 0, XFA_Element::Validate, false) + : nullptr; + if (!pValidateNode) { + CXFA_Present* pPresentNode = + pConfigItem->GetChild<CXFA_Present>(0, XFA_Element::Present, false); + pValidateNode = pPresentNode ? pPresentNode->GetChild<CXFA_Validate>( + 0, XFA_Element::Validate, false) + : nullptr; + } + if (pValidateNode) + wsValidateStr = pValidateNode->JSObject()->GetContent(false); + } + + if (!wsValidateStr.Contains(L"preSubmit")) + return XFA_EVENTERROR_Success; + } + + CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr; + if (!pNode) { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) + return XFA_EVENTERROR_Error; + + pNode = pRootItem->GetChild<CXFA_Node>(0, XFA_Element::Subform, false); + } + + ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady, + true, nullptr); + return XFA_EVENTERROR_Success; +} + +CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) { + return static_cast<CXFA_FFWidget*>(GetXFALayout()->GetLayoutItem(node)); +} + +CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() { + if (!m_pWidgetHandler) + m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this); + return m_pWidgetHandler.get(); +} + +std::unique_ptr<CXFA_WidgetAccIterator> +CXFA_FFDocView::CreateWidgetAccIterator() { + CXFA_Subform* pFormRoot = GetRootSubform(); + return pFormRoot ? pdfium::MakeUnique<CXFA_WidgetAccIterator>(pFormRoot) + : nullptr; +} + +void CXFA_FFDocView::KillFocus() { + if (m_pFocusWidget && + (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) { + m_pFocusWidget->OnKillFocus(nullptr); + } + m_pFocusAcc = nullptr; + m_pFocusWidget = nullptr; + m_pOldFocusWidget = nullptr; +} + +bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) { + CXFA_FFWidget* pNewFocus = hWidget; + if (m_pOldFocusWidget == pNewFocus) + return false; + + CXFA_FFWidget* pOldFocus = m_pOldFocusWidget.Get(); + m_pOldFocusWidget = pNewFocus; + if (pOldFocus) { + if (m_pFocusWidget != m_pOldFocusWidget && + (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) { + m_pFocusWidget = pOldFocus; + pOldFocus->OnKillFocus(pNewFocus); + } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) { + if (!pOldFocus->IsLoaded()) + pOldFocus->LoadWidget(); + + pOldFocus->OnSetFocus(m_pFocusWidget.Get()); + m_pFocusWidget = pOldFocus; + pOldFocus->OnKillFocus(pNewFocus); + } + } + if (m_pFocusWidget == m_pOldFocusWidget) + return false; + + pNewFocus = m_pOldFocusWidget.Get(); + if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) { + m_pFocusAcc = nullptr; + m_pFocusWidget = nullptr; + m_pListFocusWidget = nullptr; + m_pOldFocusWidget = nullptr; + return false; + } + if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) { + if (!pNewFocus->IsLoaded()) + pNewFocus->LoadWidget(); + pNewFocus->OnSetFocus(m_pFocusWidget.Get()); + } + m_pFocusAcc = pNewFocus ? pNewFocus->GetNode()->GetWidgetAcc() : nullptr; + m_pFocusWidget = pNewFocus; + m_pOldFocusWidget = m_pFocusWidget; + return true; +} + +void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_FFWidget* pNewFocus = nullptr; + if (pWidgetAcc) + pNewFocus = GetWidgetForNode(pWidgetAcc->GetNode()); + if (!SetFocus(pNewFocus)) + return; + + m_pFocusAcc = pWidgetAcc; + if (m_iStatus != XFA_DOCVIEW_LAYOUTSTATUS_End) + return; + + m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc.Get(), + m_pFocusWidget.Get()); +} + +void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) { + if (m_pFocusAcc && m_pFocusAcc->GetNode() != pWidget->GetNode()) + return; + + m_pFocusAcc = nullptr; + m_pFocusWidget = nullptr; + m_pOldFocusWidget = nullptr; +} + +static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView, + CXFA_WidgetAcc* pWidgetAcc, + CXFA_EventParam* pParam) { + if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) + return XFA_EVENTERROR_NotExist; + if (!pWidgetAcc) + return XFA_EVENTERROR_NotExist; + + CXFA_Node* node = pWidgetAcc->GetNode(); + if (node && node->GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + switch (pParam->m_eType) { + case XFA_EVENT_Calculate: + return node->ProcessCalculate(pDocView); + case XFA_EVENT_Validate: + if (pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled( + pDocView->GetDoc())) { + return node->ProcessValidate(pDocView, 0x01); + } + return XFA_EVENTERROR_Disabled; + case XFA_EVENT_InitCalculate: { + CXFA_Calculate* calc = node->GetCalculateIfExists(); + if (!calc) + return XFA_EVENTERROR_NotExist; + if (node->IsUserInteractive()) + return XFA_EVENTERROR_Disabled; + + return node->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam); + } + default: + break; + } + + return node->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType], + pParam); +} + +int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode, + XFA_EVENTTYPE eEventType, + bool bIsFormReady, + bool bRecursive, + CXFA_Node* pExclude) { + if (pFormNode == pExclude) + return XFA_EVENTERROR_NotExist; + + XFA_Element elementType = pFormNode->GetElementType(); + if (elementType == XFA_Element::Field) { + if (eEventType == XFA_EVENT_IndexChange) + return XFA_EVENTERROR_NotExist; + + CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc(); + if (!pWidgetAcc) + return XFA_EVENTERROR_NotExist; + + CXFA_EventParam eParam; + eParam.m_eType = eEventType; + eParam.m_pTarget = pWidgetAcc; + eParam.m_bIsFormReady = bIsFormReady; + return XFA_ProcessEvent(this, pWidgetAcc, &eParam); + } + + int32_t iRet = XFA_EVENTERROR_NotExist; + if (bRecursive) { + for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode; + pNode = pNode->GetNextContainerSibling()) { + elementType = pNode->GetElementType(); + if (elementType != XFA_Element::Variables && + elementType != XFA_Element::Draw) { + iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady, + bRecursive, pExclude); + } + } + } + CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc(); + if (!pWidgetAcc) + return iRet; + + CXFA_EventParam eParam; + eParam.m_eType = eEventType; + eParam.m_pTarget = pWidgetAcc; + eParam.m_bIsFormReady = bIsFormReady; + iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam); + + return iRet; +} + +CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName, + CXFA_FFWidget* pRefWidget) { + CXFA_WidgetAcc* pRefAcc = + pRefWidget ? pRefWidget->GetNode()->GetWidgetAcc() : nullptr; + CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc); + if (!pAcc) + return nullptr; + return GetWidgetForNode(pAcc->GetNode()); +} + +CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName( + const WideString& wsName, + CXFA_WidgetAcc* pRefWidgetAcc) { + WideString wsExpression; + uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; + CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext(); + if (!pScriptContext) + return nullptr; + + CXFA_Node* refNode = nullptr; + if (pRefWidgetAcc) { + refNode = pRefWidgetAcc->GetNode(); + wsExpression = wsName; + } else { + wsExpression = L"$form." + wsName; + } + + XFA_RESOLVENODE_RS resolveNodeRS; + if (!pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(), + &resolveNodeRS, dwStyle, nullptr)) { + return nullptr; + } + + if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + CXFA_Node* pNode = resolveNodeRS.objects.front()->AsNode(); + if (pNode) + return pNode->GetWidgetAcc(); + } + return nullptr; +} + +void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender, + uint32_t dwEvent) { + CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender); + m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent); +} + + +void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget, + const CFX_RectF& rtInvalidate) { + AddInvalidateRect(pWidget->GetPageView(), rtInvalidate); +} + +void CXFA_FFDocView::AddInvalidateRect(CXFA_FFPageView* pPageView, + const CFX_RectF& rtInvalidate) { + if (m_mapPageInvalidate[pPageView]) { + m_mapPageInvalidate[pPageView]->Union(rtInvalidate); + return; + } + + m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate); +} + +void CXFA_FFDocView::RunInvalidate() { + for (const auto& pair : m_mapPageInvalidate) + m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second); + + m_mapPageInvalidate.clear(); +} + +bool CXFA_FFDocView::RunLayout() { + LockUpdate(); + m_bInLayoutStatus = true; + if (!m_pXFADocLayout->IncrementLayout() && + m_pXFADocLayout->StartLayout() < 100) { + m_pXFADocLayout->DoLayout(); + UnlockUpdate(); + m_bInLayoutStatus = false; + m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, + XFA_PAGEVIEWEVENT_StopLayout); + return true; + } + + m_bInLayoutStatus = false; + m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, + XFA_PAGEVIEWEVENT_StopLayout); + UnlockUpdate(); + return false; +} + +void CXFA_FFDocView::RunSubformIndexChange() { + for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) { + if (!pSubformNode->GetWidgetAcc()) + continue; + + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_IndexChange; + eParam.m_pTarget = pSubformNode->GetWidgetAcc(); + pSubformNode->ProcessEvent(this, XFA_AttributeEnum::IndexChange, &eParam); + } + m_IndexChangedSubforms.clear(); +} + +void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) { + m_NewAddedNodes.push_back(pNode); + InitLayout(pNode); +} + +void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) { + ASSERT(pNode->GetElementType() == XFA_Element::Subform); + m_IndexChangedSubforms.push_back(pNode); +} + +void CXFA_FFDocView::RunDocClose() { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) + return; + + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true, + nullptr); +} + +void CXFA_FFDocView::DestroyDocView() { + ClearInvalidateList(); + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None; + m_iLock = 0; + m_ValidateAccs.clear(); + m_BindItems.clear(); + m_CalculateAccs.clear(); +} + +void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_WidgetAcc* pCurrentAcc = + !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr; + if (pCurrentAcc != pWidgetAcc) + m_CalculateAccs.push_back(pWidgetAcc); +} + +void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) { + CXFA_CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData(); + if (!pGlobalData) + return; + + for (auto* pResult : pGlobalData->m_Globals) { + if (!pResult->HasRemovedChildren()) + AddCalculateWidgetAcc(pResult->GetWidgetAcc()); + } +} + +size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) { + while (index < m_CalculateAccs.size()) { + CXFA_Node* node = m_CalculateAccs[index]->GetNode(); + + AddCalculateNodeNotify(node); + size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1; + node->JSObject()->SetCalcRecursionCount(recurse); + if (recurse > 11) + break; + if (node->ProcessCalculate(this) == XFA_EVENTERROR_Success) + AddValidateWidget(node->GetWidgetAcc()); + + index = RunCalculateRecursive(++index); + } + return index; +} + +int32_t CXFA_FFDocView::RunCalculateWidgets() { + if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc.Get())) + return XFA_EVENTERROR_Disabled; + if (!m_CalculateAccs.empty()) + RunCalculateRecursive(0); + + for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs) + pCurAcc->GetNode()->JSObject()->SetCalcRecursionCount(0); + + m_CalculateAccs.clear(); + return XFA_EVENTERROR_Success; +} + +void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) { + if (!pdfium::ContainsValue(m_ValidateAccs, pWidget)) + m_ValidateAccs.push_back(pWidget); +} + +void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) { + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true, + nullptr); +} + +void CXFA_FFDocView::ProcessValueChanged(CXFA_WidgetAcc* widgetAcc) { + AddValidateWidget(widgetAcc); + AddCalculateWidgetAcc(widgetAcc); + RunCalculateWidgets(); + RunValidate(); +} + +bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) { + if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get())) + return false; + + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr); + m_ValidateAccs.clear(); + return true; +} + +bool CXFA_FFDocView::RunValidate() { + if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get())) + return false; + + for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) { + CXFA_Node* node = pAcc->GetNode(); + if (!node->HasRemovedChildren()) + node->ProcessValidate(this, 0); + } + m_ValidateAccs.clear(); + return true; +} + +bool CXFA_FFDocView::RunEventLayoutReady() { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) + return false; + + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, + nullptr); + RunLayout(); + return true; +} + +void CXFA_FFDocView::RunBindItems() { + for (auto* item : m_BindItems) { + if (item->HasRemovedChildren()) + continue; + + CXFA_Node* pWidgetNode = item->GetParent(); + CXFA_WidgetAcc* pAcc = pWidgetNode->GetWidgetAcc(); + if (!pAcc) + continue; + + CFXJSE_Engine* pScriptContext = + pWidgetNode->GetDocument()->GetScriptContext(); + WideString wsRef = item->GetRef(); + uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_ALL; + XFA_RESOLVENODE_RS rs; + pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(), &rs, + dwStyle, nullptr); + pAcc->DeleteItem(-1, false, false); + if (rs.dwFlags != XFA_ResolveNode_RSType_Nodes || rs.objects.empty()) + continue; + + WideString wsValueRef = item->GetValueRef(); + WideString wsLabelRef = item->GetLabelRef(); + const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef; + const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$"; + const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$"; + WideString wsValue; + WideString wsLabel; + uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView(), false); + for (CXFA_Object* refObject : rs.objects) { + CXFA_Node* refNode = refObject->AsNode(); + if (!refNode) + continue; + + if (bValueUseContent) { + wsValue = refNode->JSObject()->GetContent(false); + } else { + CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash); + wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false) + : refNode->JSObject()->GetContent(false); + } + + if (!bUseValue) { + if (bLabelUseContent) { + wsLabel = refNode->JSObject()->GetContent(false); + } else { + CXFA_Node* nodeLabel = + refNode->GetFirstChildByName(wsLabelRef.AsStringView()); + if (nodeLabel) + wsLabel = nodeLabel->JSObject()->GetContent(false); + } + } else { + wsLabel = wsValue; + } + pAcc->InsertItem(wsLabel, wsValue, false); + } + } + m_BindItems.clear(); +} + +void CXFA_FFDocView::SetChangeMark() { + if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) + return; + + m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get()); +} + +CXFA_Subform* CXFA_FFDocView::GetRootSubform() { + CXFA_Node* pFormPacketNode = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pFormPacketNode) + return nullptr; + + return pFormPacketNode->GetFirstChildByClass<CXFA_Subform>( + XFA_Element::Subform); +} diff --git a/xfa/fxfa/cxfa_ffdocview.h b/xfa/fxfa/cxfa_ffdocview.h new file mode 100644 index 0000000000000000000000000000000000000000..5c8f0176d8c00beab8e189de7349229c47e2333f --- /dev/null +++ b/xfa/fxfa/cxfa_ffdocview.h @@ -0,0 +1,143 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFDOCVIEW_H_ +#define XFA_FXFA_CXFA_FFDOCVIEW_H_ + +#include <map> +#include <memory> +#include <vector> + +#include "core/fxcrt/unowned_ptr.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffdoc.h" + +class CXFA_BindItems; +class CXFA_FFWidgetHandler; +class CXFA_FFDoc; +class CXFA_FFWidget; +class CXFA_Subform; +class CXFA_WidgetAccIterator; + +extern const XFA_AttributeEnum gs_EventActivity[]; +enum XFA_DOCVIEW_LAYOUTSTATUS { + XFA_DOCVIEW_LAYOUTSTATUS_None, + XFA_DOCVIEW_LAYOUTSTATUS_Start, + XFA_DOCVIEW_LAYOUTSTATUS_FormInitialize, + XFA_DOCVIEW_LAYOUTSTATUS_FormInitCalculate, + XFA_DOCVIEW_LAYOUTSTATUS_FormInitValidate, + XFA_DOCVIEW_LAYOUTSTATUS_FormFormReady, + XFA_DOCVIEW_LAYOUTSTATUS_Doing, + XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitialize, + XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitCalculate, + XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitValidate, + XFA_DOCVIEW_LAYOUTSTATUS_PagesetFormReady, + XFA_DOCVIEW_LAYOUTSTATUS_LayoutReady, + XFA_DOCVIEW_LAYOUTSTATUS_DocReady, + XFA_DOCVIEW_LAYOUTSTATUS_End +}; + +class CXFA_FFDocView { + public: + explicit CXFA_FFDocView(CXFA_FFDoc* pDoc); + ~CXFA_FFDocView(); + + CXFA_FFDoc* GetDoc() { return m_pDoc.Get(); } + int32_t StartLayout(int32_t iStartPage = 0); + int32_t DoLayout(); + void StopLayout(); + int32_t GetLayoutStatus() const { return m_iStatus; } + void UpdateDocView(); + int32_t CountPageViews() const; + CXFA_FFPageView* GetPageView(int32_t nIndex) const; + + void ResetWidgetAcc(CXFA_WidgetAcc* pWidgetAcc); + int32_t ProcessWidgetEvent(CXFA_EventParam* pParam, + CXFA_WidgetAcc* pWidgetAcc); + CXFA_FFWidgetHandler* GetWidgetHandler(); + std::unique_ptr<CXFA_WidgetAccIterator> CreateWidgetAccIterator(); + CXFA_FFWidget* GetFocusWidget() const { return m_pFocusWidget.Get(); } + void KillFocus(); + bool SetFocus(CXFA_FFWidget* hWidget); + CXFA_FFWidget* GetWidgetForNode(CXFA_Node* node); + CXFA_FFWidget* GetWidgetByName(const WideString& wsName, + CXFA_FFWidget* pRefWidget); + CXFA_WidgetAcc* GetWidgetAccByName(const WideString& wsName, + CXFA_WidgetAcc* pRefWidgetAcc); + CXFA_LayoutProcessor* GetXFALayout() const; + void OnPageEvent(CXFA_ContainerLayoutItem* pSender, uint32_t dwEvent); + void LockUpdate() { m_iLock++; } + void UnlockUpdate() { m_iLock--; } + bool IsUpdateLocked() { return m_iLock > 0; } + void ClearInvalidateList() { m_mapPageInvalidate.clear(); } + void AddInvalidateRect(CXFA_FFWidget* pWidget, const CFX_RectF& rtInvalidate); + void AddInvalidateRect(CXFA_FFPageView* pPageView, + const CFX_RectF& rtInvalidate); + void RunInvalidate(); + void RunDocClose(); + void DestroyDocView(); + + void ProcessValueChanged(CXFA_WidgetAcc* widgetAcc); + + bool InitValidate(CXFA_Node* pNode); + bool RunValidate(); + + void SetChangeMark(); + + void AddValidateWidget(CXFA_WidgetAcc* pWidget); + void AddCalculateNodeNotify(CXFA_Node* pNodeChange); + void AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc); + int32_t RunCalculateWidgets(); + bool IsStaticNotify() { + return m_pDoc->GetFormType() == FormType::kXFAForeground; + } + bool RunLayout(); + void RunSubformIndexChange(); + void AddNewFormNode(CXFA_Node* pNode); + void AddIndexChangedSubform(CXFA_Node* pNode); + CXFA_WidgetAcc* GetFocusWidgetAcc() const { return m_pFocusAcc.Get(); } + void SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc); + void DeleteLayoutItem(CXFA_FFWidget* pWidget); + int32_t ExecEventActivityByDeepFirst(CXFA_Node* pFormNode, + XFA_EVENTTYPE eEventType, + bool bIsFormReady, + bool bRecursive, + CXFA_Node* pExclude); + + void AddBindItem(CXFA_BindItems* item) { m_BindItems.push_back(item); } + + bool m_bLayoutEvent; + std::vector<WideString> m_arrNullTestMsg; + CXFA_FFWidget* m_pListFocusWidget; + bool m_bInLayoutStatus; + + private: + bool RunEventLayoutReady(); + void RunBindItems(); + void InitCalculate(CXFA_Node* pNode); + void InitLayout(CXFA_Node* pNode); + size_t RunCalculateRecursive(size_t index); + void ShowNullTestMsg(); + bool ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc); + CXFA_Subform* GetRootSubform(); + + UnownedPtr<CXFA_FFDoc> const m_pDoc; + std::unique_ptr<CXFA_FFWidgetHandler> m_pWidgetHandler; + CXFA_LayoutProcessor* m_pXFADocLayout; // Not owned. + UnownedPtr<CXFA_WidgetAcc> m_pFocusAcc; + UnownedPtr<CXFA_FFWidget> m_pFocusWidget; + UnownedPtr<CXFA_FFWidget> m_pOldFocusWidget; + std::map<CXFA_FFPageView*, std::unique_ptr<CFX_RectF>> m_mapPageInvalidate; + std::vector<CXFA_WidgetAcc*> m_ValidateAccs; + std::vector<CXFA_WidgetAcc*> m_CalculateAccs; + std::vector<CXFA_BindItems*> m_BindItems; + std::vector<CXFA_Node*> m_NewAddedNodes; + std::vector<CXFA_Node*> m_IndexChangedSubforms; + XFA_DOCVIEW_LAYOUTSTATUS m_iStatus; + int32_t m_iLock; +}; + +#endif // XFA_FXFA_CXFA_FFDOCVIEW_H_ diff --git a/xfa/fxfa/cxfa_ffdraw.cpp b/xfa/fxfa/cxfa_ffdraw.cpp new file mode 100644 index 0000000000000000000000000000000000000000..420bde1d7c23be20a6c3a7bf0804b12f16a927b2 --- /dev/null +++ b/xfa/fxfa/cxfa_ffdraw.cpp @@ -0,0 +1,16 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffdraw.h" + +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +CXFA_FFDraw::CXFA_FFDraw(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {} + +CXFA_FFDraw::~CXFA_FFDraw() {} diff --git a/xfa/fxfa/cxfa_ffdraw.h b/xfa/fxfa/cxfa_ffdraw.h new file mode 100644 index 0000000000000000000000000000000000000000..de9cfcf428d5a9e41dcb1d8dc2a9ad4ffa7bb301 --- /dev/null +++ b/xfa/fxfa/cxfa_ffdraw.h @@ -0,0 +1,19 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFDRAW_H_ +#define XFA_FXFA_CXFA_FFDRAW_H_ + +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +class CXFA_FFDraw : public CXFA_FFWidget { + public: + explicit CXFA_FFDraw(CXFA_Node* pNode); + ~CXFA_FFDraw() override; +}; + +#endif // XFA_FXFA_CXFA_FFDRAW_H_ diff --git a/xfa/fxfa/cxfa_ffexclgroup.cpp b/xfa/fxfa/cxfa_ffexclgroup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..318752b1f20083581a7cc4850cf903fff40362b1 --- /dev/null +++ b/xfa/fxfa/cxfa_ffexclgroup.cpp @@ -0,0 +1,28 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffexclgroup.h" + +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +CXFA_FFExclGroup::CXFA_FFExclGroup(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {} + +CXFA_FFExclGroup::~CXFA_FFExclGroup() {} + +void CXFA_FFExclGroup::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); +} diff --git a/xfa/fxfa/cxfa_ffexclgroup.h b/xfa/fxfa/cxfa_ffexclgroup.h new file mode 100644 index 0000000000000000000000000000000000000000..b90430175f37f024bcded02f421de6214a71d559 --- /dev/null +++ b/xfa/fxfa/cxfa_ffexclgroup.h @@ -0,0 +1,24 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFEXCLGROUP_H_ +#define XFA_FXFA_CXFA_FFEXCLGROUP_H_ + +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +class CXFA_FFExclGroup : public CXFA_FFWidget { + public: + explicit CXFA_FFExclGroup(CXFA_Node* pNode); + ~CXFA_FFExclGroup() override; + + // CXFA_FFWidget + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; +}; + +#endif // XFA_FXFA_CXFA_FFEXCLGROUP_H_ diff --git a/xfa/fxfa/cxfa_fffield.cpp b/xfa/fxfa/cxfa_fffield.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd4359d7eb6799a970e51b902c1f4b8a5aac09b9 --- /dev/null +++ b/xfa/fxfa/cxfa_fffield.cpp @@ -0,0 +1,781 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fffield.h" + +#include "xfa/fwl/cfwl_edit.h" +#include "xfa/fwl/cfwl_eventmouse.h" +#include "xfa/fwl/cfwl_messagekey.h" +#include "xfa/fwl/cfwl_messagekillfocus.h" +#include "xfa/fwl/cfwl_messagemouse.h" +#include "xfa/fwl/cfwl_messagemousewheel.h" +#include "xfa/fwl/cfwl_messagesetfocus.h" +#include "xfa/fwl/cfwl_picturebox.h" +#include "xfa/fwl/cfwl_widgetmgr.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fwltheme.h" +#include "xfa/fxfa/cxfa_textlayout.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_calculate.h" +#include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_margin.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" + +namespace { + +CXFA_FFField* ToField(CXFA_LayoutItem* widget) { + return static_cast<CXFA_FFField*>(widget); +} + +} // namespace + +CXFA_FFField::CXFA_FFField(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {} + +CXFA_FFField::~CXFA_FFField() { + CXFA_FFField::UnloadWidget(); +} + +CFX_RectF CXFA_FFField::GetBBox(uint32_t dwStatus, bool bDrawFocus) { + if (!bDrawFocus) + return CXFA_FFWidget::GetBBox(dwStatus); + + XFA_Element type = m_pNode->GetWidgetAcc()->GetUIType(); + if (type != XFA_Element::Button && type != XFA_Element::CheckButton && + type != XFA_Element::ImageEdit && type != XFA_Element::Signature && + type != XFA_Element::ChoiceList) { + return CFX_RectF(); + } + + return GetRotateMatrix().TransformRect(m_rtUI); +} + +void CXFA_FFField::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + DrawBorder(pGS, m_pNode->GetWidgetAcc()->GetUIBorder(), m_rtUI, mtRotate); + RenderCaption(pGS, &mtRotate); + DrawHighlight(pGS, &mtRotate, dwStatus, false); + + CFX_RectF rtWidget = m_pNormalWidget->GetWidgetRect(); + CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); + mt.Concat(mtRotate); + GetApp()->GetFWLWidgetMgr()->OnDrawWidget(m_pNormalWidget.get(), pGS, mt); +} + +void CXFA_FFField::DrawHighlight(CXFA_Graphics* pGS, + CFX_Matrix* pMatrix, + uint32_t dwStatus, + bool bEllipse) { + if (m_rtUI.IsEmpty() || !GetDoc()->GetXFADoc()->IsInteractive()) + return; + if (!(dwStatus & XFA_WidgetStatus_Highlight) || !m_pNode->IsOpenAccess()) + return; + + CXFA_FFDoc* pDoc = GetDoc(); + pGS->SetFillColor( + CXFA_GEColor(pDoc->GetDocEnvironment()->GetHighlightColor(pDoc))); + CXFA_GEPath path; + if (bEllipse) + path.AddEllipse(m_rtUI); + else + path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height); + + pGS->FillPath(&path, FXFILL_WINDING, pMatrix); +} + +void CXFA_FFField::DrawFocus(CXFA_Graphics* pGS, CFX_Matrix* pMatrix) { + if (!(m_dwStatus & XFA_WidgetStatus_Focused)) + return; + + pGS->SetStrokeColor(CXFA_GEColor(0xFF000000)); + + float DashPattern[2] = {1, 1}; + pGS->SetLineDash(0.0f, DashPattern, 2); + pGS->SetLineWidth(0); + + CXFA_GEPath path; + path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height); + pGS->StrokePath(&path, pMatrix); +} + +void CXFA_FFField::SetFWLThemeProvider() { + if (m_pNormalWidget) + m_pNormalWidget->SetThemeProvider(GetApp()->GetFWLTheme()); +} + +bool CXFA_FFField::IsLoaded() { + return m_pNormalWidget && CXFA_FFWidget::IsLoaded(); +} + +bool CXFA_FFField::LoadWidget() { + SetFWLThemeProvider(); + m_pNode->GetWidgetAcc()->LoadCaption(GetDoc()); + PerformLayout(); + return true; +} + +void CXFA_FFField::UnloadWidget() { + m_pNormalWidget.reset(); +} + +void CXFA_FFField::SetEditScrollOffset() { + XFA_Element eType = m_pNode->GetWidgetAcc()->GetUIType(); + if (eType != XFA_Element::TextEdit && eType != XFA_Element::NumericEdit && + eType != XFA_Element::PasswordEdit) { + return; + } + + float fScrollOffset = 0; + CXFA_FFField* pPrev = ToField(GetPrev()); + if (pPrev) { + CFX_RectF rtMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); + fScrollOffset = -rtMargin.top; + } + + while (pPrev) { + fScrollOffset += pPrev->m_rtUI.height; + pPrev = ToField(pPrev->GetPrev()); + } + static_cast<CFWL_Edit*>(m_pNormalWidget.get()) + ->SetScrollOffset(fScrollOffset); +} + +bool CXFA_FFField::PerformLayout() { + CXFA_FFWidget::PerformLayout(); + CapPlacement(); + LayoutCaption(); + SetFWLRect(); + SetEditScrollOffset(); + if (m_pNormalWidget) + m_pNormalWidget->Update(); + return true; +} + +void CXFA_FFField::CapPlacement() { + CFX_RectF rtWidget = GetRectWithoutRotate(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + CXFA_LayoutItem* pItem = this; + float fLeftInset = margin->GetLeftInset(); + float fRightInset = margin->GetRightInset(); + float fTopInset = margin->GetTopInset(); + float fBottomInset = margin->GetBottomInset(); + if (!pItem->GetPrev() && !pItem->GetNext()) { + rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); + } else { + if (!pItem->GetPrev()) + rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, 0); + else if (!pItem->GetNext()) + rtWidget.Deflate(fLeftInset, 0, fRightInset, fBottomInset); + else + rtWidget.Deflate(fLeftInset, 0, fRightInset, 0); + } + } + + XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; + float fCapReserve = 0; + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (caption && !caption->IsHidden()) { + iCapPlacement = caption->GetPlacementType(); + if (iCapPlacement == XFA_AttributeEnum::Top && GetPrev()) { + m_rtCaption.Reset(); + } else if (iCapPlacement == XFA_AttributeEnum::Bottom && GetNext()) { + m_rtCaption.Reset(); + } else { + fCapReserve = caption->GetReserve(); + CXFA_LayoutItem* pItem = this; + if (!pItem->GetPrev() && !pItem->GetNext()) { + m_rtCaption = rtWidget; + } else { + pItem = pItem->GetFirst(); + m_rtCaption = pItem->GetRect(false); + pItem = pItem->GetNext(); + while (pItem) { + m_rtCaption.height += pItem->GetRect(false).Height(); + pItem = pItem->GetNext(); + } + XFA_RectWithoutMargin(m_rtCaption, margin); + } + + CXFA_TextLayout* pCapTextLayout = + m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); + if (fCapReserve <= 0 && pCapTextLayout) { + CFX_SizeF minSize; + CFX_SizeF maxSize; + CFX_SizeF size = pCapTextLayout->CalcSize(minSize, maxSize); + if (iCapPlacement == XFA_AttributeEnum::Top || + iCapPlacement == XFA_AttributeEnum::Bottom) { + fCapReserve = size.height; + } else { + fCapReserve = size.width; + } + } + } + } + + m_rtUI = rtWidget; + CXFA_Margin* capMargin = caption ? caption->GetMarginIfExists() : nullptr; + switch (iCapPlacement) { + case XFA_AttributeEnum::Left: { + m_rtCaption.width = fCapReserve; + CapLeftRightPlacement(capMargin, rtWidget, iCapPlacement); + m_rtUI.width -= fCapReserve; + m_rtUI.left += fCapReserve; + break; + } + case XFA_AttributeEnum::Top: { + m_rtCaption.height = fCapReserve; + CapTopBottomPlacement(capMargin, rtWidget, iCapPlacement); + m_rtUI.top += fCapReserve; + m_rtUI.height -= fCapReserve; + break; + } + case XFA_AttributeEnum::Right: { + m_rtCaption.left = m_rtCaption.right() - fCapReserve; + m_rtCaption.width = fCapReserve; + CapLeftRightPlacement(capMargin, rtWidget, iCapPlacement); + m_rtUI.width -= fCapReserve; + break; + } + case XFA_AttributeEnum::Bottom: { + m_rtCaption.top = m_rtCaption.bottom() - fCapReserve; + m_rtCaption.height = fCapReserve; + CapTopBottomPlacement(capMargin, rtWidget, iCapPlacement); + m_rtUI.height -= fCapReserve; + break; + } + case XFA_AttributeEnum::Inline: + break; + default: + break; + } + + CXFA_Border* borderUI = m_pNode->GetWidgetAcc()->GetUIBorder(); + if (borderUI) { + CXFA_Margin* borderMargin = borderUI->GetMarginIfExists(); + if (borderMargin) + XFA_RectWithoutMargin(m_rtUI, borderMargin); + } + m_rtUI.Normalize(); +} + +void CXFA_FFField::CapTopBottomPlacement(const CXFA_Margin* margin, + const CFX_RectF& rtWidget, + XFA_AttributeEnum iCapPlacement) { + CFX_RectF rtUIMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); + m_rtCaption.left += rtUIMargin.left; + if (margin) { + XFA_RectWithoutMargin(m_rtCaption, margin); + if (m_rtCaption.height < 0) + m_rtCaption.top += m_rtCaption.height; + } + + float fWidth = rtUIMargin.left + rtUIMargin.width; + float fHeight = m_rtCaption.height + rtUIMargin.top + rtUIMargin.height; + if (fWidth > rtWidget.width) + m_rtUI.width += fWidth - rtWidget.width; + + if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) { + m_rtUI.height = XFA_MINUI_HEIGHT; + m_rtCaption.top += rtUIMargin.top + rtUIMargin.height; + } else if (fHeight > rtWidget.height) { + m_rtUI.height += fHeight - rtWidget.height; + if (iCapPlacement == XFA_AttributeEnum::Bottom) + m_rtCaption.top += fHeight - rtWidget.height; + } +} + +void CXFA_FFField::CapLeftRightPlacement(const CXFA_Margin* margin, + const CFX_RectF& rtWidget, + XFA_AttributeEnum iCapPlacement) { + CFX_RectF rtUIMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); + m_rtCaption.top += rtUIMargin.top; + m_rtCaption.height -= rtUIMargin.top; + if (margin) { + XFA_RectWithoutMargin(m_rtCaption, margin); + if (m_rtCaption.height < 0) + m_rtCaption.top += m_rtCaption.height; + } + + float fWidth = m_rtCaption.width + rtUIMargin.left + rtUIMargin.width; + float fHeight = rtUIMargin.top + rtUIMargin.height; + if (fWidth > rtWidget.width) { + m_rtUI.width += fWidth - rtWidget.width; + if (iCapPlacement == XFA_AttributeEnum::Right) + m_rtCaption.left += fWidth - rtWidget.width; + } + + if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) { + m_rtUI.height = XFA_MINUI_HEIGHT; + m_rtCaption.top += rtUIMargin.top + rtUIMargin.height; + } else if (fHeight > rtWidget.height) { + m_rtUI.height += fHeight - rtWidget.height; + } +} + +void CXFA_FFField::UpdateFWL() { + if (m_pNormalWidget) + m_pNormalWidget->Update(); +} + +uint32_t CXFA_FFField::UpdateUIProperty() { + CXFA_Node* pUiNode = m_pNode->GetWidgetAcc()->GetUIChild(); + if (pUiNode && pUiNode->GetElementType() == XFA_Element::DefaultUi) + return FWL_STYLEEXT_EDT_ReadOnly; + return 0; +} + +void CXFA_FFField::SetFWLRect() { + if (!m_pNormalWidget) + return; + + CFX_RectF rtUi = m_rtUI; + if (rtUi.width < 1.0) + rtUi.width = 1.0; + if (!GetDoc()->GetXFADoc()->IsInteractive()) { + float fFontSize = m_pNode->GetFontSize(); + if (rtUi.height < fFontSize) + rtUi.height = fFontSize; + } + m_pNormalWidget->SetWidgetRect(rtUi); +} + +bool CXFA_FFField::OnMouseEnter() { + if (!m_pNormalWidget) + return false; + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::Enter; + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnMouseExit() { + if (!m_pNormalWidget) + return false; + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::Leave; + TranslateFWLMessage(&ms); + return true; +} + +CFX_PointF CXFA_FFField::FWLToClient(const CFX_PointF& point) { + return m_pNormalWidget ? point - m_pNormalWidget->GetWidgetRect().TopLeft() + : point; +} + +bool CXFA_FFField::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) + return false; + if (!PtInActiveRect(point)) + return false; + + SetButtonDown(true); + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + if (!IsButtonDown()) + return false; + + SetButtonDown(false); + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::LeftButtonDblClk; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::Move; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnMouseWheel(uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + + CFWL_MessageMouseWheel ms(nullptr, m_pNormalWidget.get()); + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + ms.m_delta = CFX_PointF(zDelta, 0); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) + return false; + if (!PtInActiveRect(point)) + return false; + + SetButtonDown(true); + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::RightButtonDown; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + if (!IsButtonDown()) + return false; + + SetButtonDown(false); + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::RightButtonUp; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNormalWidget) + return false; + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::RightButtonDblClk; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnSetFocus(CXFA_FFWidget* pOldWidget) { + CXFA_FFWidget::OnSetFocus(pOldWidget); + if (!m_pNormalWidget) + return false; + + CFWL_MessageSetFocus ms(nullptr, m_pNormalWidget.get()); + TranslateFWLMessage(&ms); + m_dwStatus |= XFA_WidgetStatus_Focused; + AddInvalidateRect(); + return true; +} + +bool CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) { + if (!m_pNormalWidget) + return CXFA_FFWidget::OnKillFocus(pNewWidget); + + CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget.get()); + TranslateFWLMessage(&ms); + m_dwStatus &= ~XFA_WidgetStatus_Focused; + AddInvalidateRect(); + CXFA_FFWidget::OnKillFocus(pNewWidget); + return true; +} + +bool CXFA_FFField::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { + if (!m_pNormalWidget || !GetDoc()->GetXFADoc()->IsInteractive()) + return false; + + CFWL_MessageKey ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_KeyCommand::KeyDown; + ms.m_dwFlags = dwFlags; + ms.m_dwKeyCode = dwKeyCode; + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { + if (!m_pNormalWidget || !GetDoc()->GetXFADoc()->IsInteractive()) + return false; + + CFWL_MessageKey ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_KeyCommand::KeyUp; + ms.m_dwFlags = dwFlags; + ms.m_dwKeyCode = dwKeyCode; + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFField::OnChar(uint32_t dwChar, uint32_t dwFlags) { + if (!GetDoc()->GetXFADoc()->IsInteractive()) + return false; + if (dwChar == FWL_VKEY_Tab) + return true; + if (!m_pNormalWidget) + return false; + if (!m_pNode->IsOpenAccess()) + return false; + + CFWL_MessageKey ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_KeyCommand::Char; + ms.m_dwFlags = dwFlags; + ms.m_dwKeyCode = dwChar; + TranslateFWLMessage(&ms); + return true; +} + +FWL_WidgetHit CXFA_FFField::OnHitTest(const CFX_PointF& point) { + if (m_pNormalWidget && + m_pNormalWidget->HitTest(FWLToClient(point)) != FWL_WidgetHit::Unknown) { + return FWL_WidgetHit::Client; + } + + if (!GetRectWithoutRotate().Contains(point)) + return FWL_WidgetHit::Unknown; + if (m_rtCaption.Contains(point)) + return FWL_WidgetHit::Titlebar; + return FWL_WidgetHit::Border; +} + +bool CXFA_FFField::OnSetCursor(const CFX_PointF& point) { + return true; +} + +bool CXFA_FFField::PtInActiveRect(const CFX_PointF& point) { + return m_pNormalWidget && m_pNormalWidget->GetWidgetRect().Contains(point); +} + +void CXFA_FFField::LayoutCaption() { + CXFA_TextLayout* pCapTextLayout = + m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); + if (!pCapTextLayout) + return; + + float fHeight = + pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height)); + if (m_rtCaption.height < fHeight) + m_rtCaption.height = fHeight; +} + +void CXFA_FFField::RenderCaption(CXFA_Graphics* pGS, CFX_Matrix* pMatrix) { + CXFA_TextLayout* pCapTextLayout = + m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); + if (!pCapTextLayout) + return; + + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (!caption || !caption->IsVisible()) + return; + + if (!pCapTextLayout->IsLoaded()) + pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height)); + + CFX_RectF rtClip = m_rtCaption; + rtClip.Intersect(GetRectWithoutRotate()); + CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); + CFX_Matrix mt(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top); + if (pMatrix) { + rtClip = pMatrix->TransformRect(rtClip); + mt.Concat(*pMatrix); + } + pCapTextLayout->DrawString(pRenderDevice, mt, rtClip, 0); +} + +bool CXFA_FFField::ProcessCommittedData() { + if (!m_pNode->IsOpenAccess()) + return false; + if (!IsDataChanged()) + return false; + if (CalculateOverride() != 1) + return false; + if (!CommitData()) + return false; + + m_pDocView->SetChangeMark(); + m_pDocView->AddValidateWidget(m_pNode->GetWidgetAcc()); + return true; +} + +int32_t CXFA_FFField::CalculateOverride() { + CXFA_Node* exclNode = m_pNode->GetExclGroupIfExists(); + if (!exclNode) + return CalculateWidgetAcc(m_pNode->GetWidgetAcc()); + + CXFA_WidgetAcc* pAcc = exclNode->GetWidgetAcc(); + if (!pAcc) + return CalculateWidgetAcc(m_pNode->GetWidgetAcc()); + if (CalculateWidgetAcc(pAcc) == 0) + return 0; + + CXFA_Node* pNode = pAcc->GetExclGroupFirstMember(); + if (!pNode) + return 1; + + CXFA_WidgetAcc* pWidgetAcc = nullptr; + while (pNode) { + pWidgetAcc = pNode->GetWidgetAcc(); + if (!pWidgetAcc) + return 1; + if (CalculateWidgetAcc(pWidgetAcc) == 0) + return 0; + + pNode = pWidgetAcc->GetExclGroupNextMember(pNode); + } + return 1; +} + +int32_t CXFA_FFField::CalculateWidgetAcc(CXFA_WidgetAcc* pAcc) { + CXFA_Calculate* calc = pAcc->GetNode()->GetCalculateIfExists(); + if (!calc) + return 1; + + XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode(); + switch (calc->GetOverride()) { + case XFA_AttributeEnum::Error: { + if (version <= XFA_VERSION_204) + return 1; + + IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); + if (pAppProvider) { + pAppProvider->MsgBox(L"You are not allowed to modify this field.", + L"Calculate Override", XFA_MBICON_Warning, + XFA_MB_OK); + } + return 0; + } + case XFA_AttributeEnum::Warning: { + if (version <= XFA_VERSION_204) { + CXFA_Script* script = calc->GetScriptIfExists(); + if (!script) + return 1; + if (script->GetExpression().IsEmpty()) + return 1; + } + + if (pAcc->GetNode()->IsUserInteractive()) + return 1; + + IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); + if (!pAppProvider) + return 0; + + WideString wsMessage = calc->GetMessageText(); + if (!wsMessage.IsEmpty()) + wsMessage += L"\r\n"; + + wsMessage += L"Are you sure you want to modify this field?"; + if (pAppProvider->MsgBox(wsMessage, L"Calculate Override", + XFA_MBICON_Warning, XFA_MB_YesNo) == XFA_IDYes) { + pAcc->GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); + return 1; + } + return 0; + } + case XFA_AttributeEnum::Ignore: + return 0; + case XFA_AttributeEnum::Disabled: + pAcc->GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false); + return 1; + default: + return 1; + } +} + +bool CXFA_FFField::CommitData() { + return false; +} + +bool CXFA_FFField::IsDataChanged() { + return false; +} + +void CXFA_FFField::TranslateFWLMessage(CFWL_Message* pMessage) { + GetApp()->GetFWLWidgetMgr()->OnProcessMessageToForm(pMessage); +} + +void CXFA_FFField::OnProcessMessage(CFWL_Message* pMessage) {} + +void CXFA_FFField::OnProcessEvent(CFWL_Event* pEvent) { + switch (pEvent->GetType()) { + case CFWL_Event::Type::Mouse: { + CFWL_EventMouse* event = static_cast<CFWL_EventMouse*>(pEvent); + if (event->m_dwCmd == FWL_MouseCommand::Enter) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_MouseEnter; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseEnter, + &eParam); + } else if (event->m_dwCmd == FWL_MouseCommand::Leave) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_MouseExit; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseExit, + &eParam); + } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonDown) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_MouseDown; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseDown, + &eParam); + } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonUp) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_MouseUp; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseUp, + &eParam); + } + break; + } + case CFWL_Event::Type::Click: { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Click; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam); + break; + } + default: + break; + } +} + +void CXFA_FFField::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) {} diff --git a/xfa/fxfa/cxfa_fffield.h b/xfa/fxfa/cxfa_fffield.h new file mode 100644 index 0000000000000000000000000000000000000000..c2ba36c7988c1142c2fff97206719db6ba54126b --- /dev/null +++ b/xfa/fxfa/cxfa_fffield.h @@ -0,0 +1,99 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFFIELD_H_ +#define XFA_FXFA_CXFA_FFFIELD_H_ + +#include <memory> + +#include "xfa/fwl/cfwl_widget.h" +#include "xfa/fwl/ifwl_widgetdelegate.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +#define XFA_MINUI_HEIGHT 4.32f +#define XFA_DEFAULTUI_HEIGHT 2.0f + +class CXFA_FFField : public CXFA_FFWidget, public IFWL_WidgetDelegate { + public: + explicit CXFA_FFField(CXFA_Node* pNode); + ~CXFA_FFField() override; + + // CXFA_FFWidget + CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false) override; + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + bool IsLoaded() override; + bool LoadWidget() override; + void UnloadWidget() override; + bool PerformLayout() override; + bool OnMouseEnter() override; + bool OnMouseExit() override; + bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnMouseWheel(uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point) override; + bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; + + bool OnSetFocus(CXFA_FFWidget* pOldWidget) override; + bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; + bool OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) override; + bool OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) override; + bool OnChar(uint32_t dwChar, uint32_t dwFlags) override; + FWL_WidgetHit OnHitTest(const CFX_PointF& point) override; + bool OnSetCursor(const CFX_PointF& point) override; + + // IFWL_WidgetDelegate + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + + void UpdateFWL(); + uint32_t UpdateUIProperty(); + + protected: + bool PtInActiveRect(const CFX_PointF& point) override; + + virtual void SetFWLRect(); + void SetFWLThemeProvider(); + CFWL_Widget* GetNormalWidget() { return m_pNormalWidget.get(); } + CFX_PointF FWLToClient(const CFX_PointF& point); + void LayoutCaption(); + void RenderCaption(CXFA_Graphics* pGS, CFX_Matrix* pMatrix); + + int32_t CalculateOverride(); + int32_t CalculateWidgetAcc(CXFA_WidgetAcc* pAcc); + bool ProcessCommittedData(); + virtual bool CommitData(); + virtual bool IsDataChanged(); + void DrawHighlight(CXFA_Graphics* pGS, + CFX_Matrix* pMatrix, + uint32_t dwStatus, + bool bEllipse); + void DrawFocus(CXFA_Graphics* pGS, CFX_Matrix* pMatrix); + void TranslateFWLMessage(CFWL_Message* pMessage); + void CapPlacement(); + void CapTopBottomPlacement(const CXFA_Margin* margin, + const CFX_RectF& rtWidget, + XFA_AttributeEnum iCapPlacement); + void CapLeftRightPlacement(const CXFA_Margin* margin, + const CFX_RectF& rtWidget, + XFA_AttributeEnum iCapPlacement); + void SetEditScrollOffset(); + + std::unique_ptr<CFWL_Widget> m_pNormalWidget; + CFX_RectF m_rtUI; + CFX_RectF m_rtCaption; +}; + +#endif // XFA_FXFA_CXFA_FFFIELD_H_ diff --git a/xfa/fxfa/cxfa_ffimage.cpp b/xfa/fxfa/cxfa_ffimage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4a0d329817fc3542fdd3d215f0570a8deda879b --- /dev/null +++ b/xfa/fxfa/cxfa_ffimage.cpp @@ -0,0 +1,80 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffimage.h" + +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdraw.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_value.h" + +CXFA_FFImage::CXFA_FFImage(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {} + +CXFA_FFImage::~CXFA_FFImage() { + CXFA_FFImage::UnloadWidget(); +} + +bool CXFA_FFImage::IsLoaded() { + return !!GetNode()->GetWidgetAcc()->GetImageImage(); +} + +bool CXFA_FFImage::LoadWidget() { + if (GetNode()->GetWidgetAcc()->GetImageImage()) + return true; + + return GetNode()->GetWidgetAcc()->LoadImageImage(GetDoc()) + ? CXFA_FFDraw::LoadWidget() + : false; +} + +void CXFA_FFImage::UnloadWidget() { + GetNode()->GetWidgetAcc()->SetImageImage(nullptr); +} + +void CXFA_FFImage::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + + RetainPtr<CFX_DIBitmap> pDIBitmap = + GetNode()->GetWidgetAcc()->GetImageImage(); + if (!pDIBitmap) + return; + + CFX_RectF rtImage = GetRectWithoutRotate(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + XFA_RectWithoutMargin(rtImage, margin); + + XFA_AttributeEnum iHorzAlign = XFA_AttributeEnum::Left; + XFA_AttributeEnum iVertAlign = XFA_AttributeEnum::Top; + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) { + iHorzAlign = para->GetHorizontalAlign(); + iVertAlign = para->GetVerticalAlign(); + } + + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + m_pNode->GetWidgetAcc()->GetImageDpi(iImageXDpi, iImageYDpi); + + auto* value = m_pNode->GetFormValueIfExists(); + CXFA_Image* image = value ? value->GetImageIfExists() : nullptr; + if (image) { + XFA_DrawImage(pGS, rtImage, mtRotate, pDIBitmap, image->GetAspect(), + iImageXDpi, iImageYDpi, iHorzAlign, iVertAlign); + } +} diff --git a/xfa/fxfa/cxfa_ffimage.h b/xfa/fxfa/cxfa_ffimage.h new file mode 100644 index 0000000000000000000000000000000000000000..c721b110f333956230cc506f00b04122f1009949 --- /dev/null +++ b/xfa/fxfa/cxfa_ffimage.h @@ -0,0 +1,26 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFIMAGE_H_ +#define XFA_FXFA_CXFA_FFIMAGE_H_ + +#include "xfa/fxfa/cxfa_ffdraw.h" + +class CXFA_FFImage : public CXFA_FFDraw { + public: + explicit CXFA_FFImage(CXFA_Node* pNode); + ~CXFA_FFImage() override; + + // CXFA_FFWidget + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + bool IsLoaded() override; + bool LoadWidget() override; + void UnloadWidget() override; +}; + +#endif // XFA_FXFA_CXFA_FFIMAGE_H_ diff --git a/xfa/fxfa/cxfa_ffimageedit.cpp b/xfa/fxfa/cxfa_ffimageedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e97559e6afa301ffbc377d7a863ddfd5870d8b4 --- /dev/null +++ b/xfa/fxfa/cxfa_ffimageedit.cpp @@ -0,0 +1,153 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffimageedit.h" + +#include <utility> + +#include "third_party/base/ptr_util.h" +#include "xfa/fwl/cfwl_app.h" +#include "xfa/fwl/cfwl_messagemouse.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fwl/cfwl_picturebox.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_value.h" + +CXFA_FFImageEdit::CXFA_FFImageEdit(CXFA_Node* pNode) + : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {} + +CXFA_FFImageEdit::~CXFA_FFImageEdit() { + CXFA_FFImageEdit::UnloadWidget(); +} + +bool CXFA_FFImageEdit::LoadWidget() { + auto pNew = pdfium::MakeUnique<CFWL_PictureBox>(GetFWLApp()); + CFWL_PictureBox* pPictureBox = pNew.get(); + m_pNormalWidget = std::move(pNew); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = pPictureBox->GetDelegate(); + pPictureBox->SetDelegate(this); + + CXFA_FFField::LoadWidget(); + if (!m_pNode->GetWidgetAcc()->GetImageEditImage()) + UpdateFWLData(); + + return true; +} + +void CXFA_FFImageEdit::UnloadWidget() { + m_pNode->GetWidgetAcc()->SetImageEditImage(nullptr); + CXFA_FFField::UnloadWidget(); +} + +void CXFA_FFImageEdit::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + DrawBorder(pGS, m_pNode->GetWidgetAcc()->GetUIBorder(), m_rtUI, mtRotate); + RenderCaption(pGS, &mtRotate); + RetainPtr<CFX_DIBitmap> pDIBitmap = + m_pNode->GetWidgetAcc()->GetImageEditImage(); + if (!pDIBitmap) + return; + + CFX_RectF rtImage = m_pNormalWidget->GetWidgetRect(); + XFA_AttributeEnum iHorzAlign = XFA_AttributeEnum::Left; + XFA_AttributeEnum iVertAlign = XFA_AttributeEnum::Top; + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) { + iHorzAlign = para->GetHorizontalAlign(); + iVertAlign = para->GetVerticalAlign(); + } + + XFA_AttributeEnum iAspect = XFA_AttributeEnum::Fit; + CXFA_Value* value = m_pNode->GetFormValueIfExists(); + if (value) { + CXFA_Image* image = value->GetImageIfExists(); + if (image) + iAspect = image->GetAspect(); + } + + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + m_pNode->GetWidgetAcc()->GetImageEditDpi(iImageXDpi, iImageYDpi); + XFA_DrawImage(pGS, rtImage, mtRotate, pDIBitmap, iAspect, iImageXDpi, + iImageYDpi, iHorzAlign, iVertAlign); +} + +bool CXFA_FFImageEdit::OnLButtonDown(uint32_t dwFlags, + const CFX_PointF& point) { + if (!m_pNode->IsOpenAccess()) + return false; + if (!PtInActiveRect(point)) + return false; + + SetButtonDown(true); + + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +void CXFA_FFImageEdit::SetFWLRect() { + if (!m_pNormalWidget) + return; + + CFX_RectF rtUIMargin = m_pNode->GetWidgetAcc()->GetUIMargin(); + CFX_RectF rtImage(m_rtUI); + rtImage.Deflate(rtUIMargin.left, rtUIMargin.top, rtUIMargin.width, + rtUIMargin.height); + m_pNormalWidget->SetWidgetRect(rtImage); +} + +bool CXFA_FFImageEdit::CommitData() { + return true; +} + +bool CXFA_FFImageEdit::UpdateFWLData() { + m_pNode->GetWidgetAcc()->SetImageEditImage(nullptr); + m_pNode->GetWidgetAcc()->LoadImageEditImage(GetDoc()); + return true; +} + +void CXFA_FFImageEdit::OnProcessMessage(CFWL_Message* pMessage) { + m_pOldDelegate->OnProcessMessage(pMessage); +} + +void CXFA_FFImageEdit::OnProcessEvent(CFWL_Event* pEvent) { + CXFA_FFField::OnProcessEvent(pEvent); + m_pOldDelegate->OnProcessEvent(pEvent); +} + +void CXFA_FFImageEdit::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + m_pOldDelegate->OnDrawWidget(pGraphics, matrix); +} + +FormFieldType CXFA_FFImageEdit::GetFormFieldType() { + return FormFieldType::kXFA_ImageField; +} diff --git a/xfa/fxfa/cxfa_ffimageedit.h b/xfa/fxfa/cxfa_ffimageedit.h new file mode 100644 index 0000000000000000000000000000000000000000..a7ef6a8c27fa722db3fba722aa07a9924f243af3 --- /dev/null +++ b/xfa/fxfa/cxfa_ffimageedit.h @@ -0,0 +1,38 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFIMAGEEDIT_H_ +#define XFA_FXFA_CXFA_FFIMAGEEDIT_H_ + +#include "xfa/fxfa/cxfa_fffield.h" + +class CXFA_FFImageEdit : public CXFA_FFField { + public: + explicit CXFA_FFImageEdit(CXFA_Node* pNode); + ~CXFA_FFImageEdit() override; + + // CXFA_FFField + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + bool LoadWidget() override; + void UnloadWidget() override; + bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + FormFieldType GetFormFieldType() override; + + private: + void SetFWLRect() override; + bool UpdateFWLData() override; + bool CommitData() override; + + IFWL_WidgetDelegate* m_pOldDelegate; +}; + +#endif // XFA_FXFA_CXFA_FFIMAGEEDIT_H_ diff --git a/xfa/fxfa/cxfa_ffline.cpp b/xfa/fxfa/cxfa_ffline.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4937a0e7cce1e12551d61c59dfb1c966af07f142 --- /dev/null +++ b/xfa/fxfa/cxfa_ffline.cpp @@ -0,0 +1,140 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffline.h" + +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxfa/parser/cxfa_line.h" +#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +namespace { + +CFX_GraphStateData::LineCap LineCapToFXGE(XFA_AttributeEnum iLineCap) { + switch (iLineCap) { + case XFA_AttributeEnum::Round: + return CFX_GraphStateData::LineCapRound; + case XFA_AttributeEnum::Butt: + return CFX_GraphStateData::LineCapButt; + default: + break; + } + return CFX_GraphStateData::LineCapSquare; +} + +} // namespace + +CXFA_FFLine::CXFA_FFLine(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {} + +CXFA_FFLine::~CXFA_FFLine() {} + +void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect, + XFA_AttributeEnum iHand, + float fLineWidth) { + float fHalfWidth = fLineWidth / 2.0f; + if (rect.height < 1.0f) { + switch (iHand) { + case XFA_AttributeEnum::Left: + rect.top -= fHalfWidth; + break; + case XFA_AttributeEnum::Right: + rect.top += fHalfWidth; + case XFA_AttributeEnum::Even: + break; + default: + NOTREACHED(); + break; + } + } else if (rect.width < 1.0f) { + switch (iHand) { + case XFA_AttributeEnum::Left: + rect.left += fHalfWidth; + break; + case XFA_AttributeEnum::Right: + rect.left += fHalfWidth; + break; + case XFA_AttributeEnum::Even: + break; + default: + NOTREACHED(); + break; + } + } else { + switch (iHand) { + case XFA_AttributeEnum::Left: + rect.Inflate(fHalfWidth, fHalfWidth); + break; + case XFA_AttributeEnum::Right: + rect.Deflate(fHalfWidth, fHalfWidth); + break; + case XFA_AttributeEnum::Even: + break; + default: + NOTREACHED(); + break; + } + } +} + +void CXFA_FFLine::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CXFA_Value* value = m_pNode->GetFormValueIfExists(); + if (!value) + return; + + FX_ARGB lineColor = 0xFF000000; + float fLineWidth = 1.0f; + XFA_AttributeEnum iStrokeType = XFA_AttributeEnum::Unknown; + XFA_AttributeEnum iCap = XFA_AttributeEnum::Unknown; + + CXFA_Line* line = value->GetLineIfExists(); + if (line) { + CXFA_Edge* edge = line->GetEdgeIfExists(); + if (edge && !edge->IsVisible()) + return; + + if (edge) { + lineColor = edge->GetColor(); + iStrokeType = edge->GetStrokeType(); + fLineWidth = edge->GetThickness(); + iCap = edge->GetCapType(); + } + } + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CFX_RectF rtLine = GetRectWithoutRotate(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + XFA_RectWithoutMargin(rtLine, margin); + + GetRectFromHand(rtLine, line ? line->GetHand() : XFA_AttributeEnum::Left, + fLineWidth); + CXFA_GEPath linePath; + if (line && line->GetSlope() && rtLine.right() > 0.0f && + rtLine.bottom() > 0.0f) { + linePath.AddLine(rtLine.TopRight(), rtLine.BottomLeft()); + } else { + linePath.AddLine(rtLine.TopLeft(), rtLine.BottomRight()); + } + + pGS->SaveGraphState(); + pGS->SetLineWidth(fLineWidth); + pGS->EnableActOnDash(); + XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap); + + pGS->SetStrokeColor(CXFA_GEColor(lineColor)); + pGS->SetLineCap(LineCapToFXGE(iCap)); + pGS->StrokePath(&linePath, &mtRotate); + pGS->RestoreGraphState(); +} diff --git a/xfa/fxfa/cxfa_ffline.h b/xfa/fxfa/cxfa_ffline.h new file mode 100644 index 0000000000000000000000000000000000000000..01f3fd3f81f0b18dc1b6da50762b53af292a7b0c --- /dev/null +++ b/xfa/fxfa/cxfa_ffline.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFLINE_H_ +#define XFA_FXFA_CXFA_FFLINE_H_ + +#include "xfa/fxfa/cxfa_ffdraw.h" + +class CXFA_FFLine : public CXFA_FFDraw { + public: + explicit CXFA_FFLine(CXFA_Node* pNode); + ~CXFA_FFLine() override; + + // CXFA_FFWidget + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + + private: + void GetRectFromHand(CFX_RectF& rect, + XFA_AttributeEnum iHand, + float fLineWidth); +}; + +#endif // XFA_FXFA_CXFA_FFLINE_H_ diff --git a/xfa/fxfa/cxfa_fflistbox.cpp b/xfa/fxfa/cxfa_fflistbox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce9198a5d371ea392233a6b014e1361913eb8fc7 --- /dev/null +++ b/xfa/fxfa/cxfa_fflistbox.cpp @@ -0,0 +1,214 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fflistbox.h" + +#include <algorithm> +#include <utility> +#include <vector> + +#include "xfa/fwl/cfwl_listbox.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fwl/cfwl_widget.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/parser/cxfa_para.h" + +namespace { + +CFWL_ListBox* ToListBox(CFWL_Widget* widget) { + return static_cast<CFWL_ListBox*>(widget); +} + +} // namespace + +CXFA_FFListBox::CXFA_FFListBox(CXFA_Node* pNode) + : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {} + +CXFA_FFListBox::~CXFA_FFListBox() { + if (!m_pNormalWidget) + return; + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->UnregisterEventTarget(m_pNormalWidget.get()); +} + +bool CXFA_FFListBox::LoadWidget() { + auto pNew = pdfium::MakeUnique<CFWL_ListBox>( + GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); + CFWL_ListBox* pListBox = pNew.get(); + pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll | FWL_WGTSTYLE_NoBackground, + 0xFFFFFFFF); + m_pNormalWidget = std::move(pNew); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + + for (const auto& label : m_pNode->GetWidgetAcc()->GetChoiceListItems(false)) + pListBox->AddString(label.AsStringView()); + + uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus; + if (m_pNode->GetWidgetAcc()->IsChoiceListMultiSelect()) + dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection; + + dwExtendedStyle |= GetAlignment(); + m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); + for (int32_t selected : m_pNode->GetWidgetAcc()->GetSelectedItems()) + pListBox->SetSelItem(pListBox->GetItem(nullptr, selected), true); + + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) { + if (!ProcessCommittedData()) + UpdateFWLData(); + + CXFA_FFField::OnKillFocus(pNewFocus); + return true; +} + +bool CXFA_FFListBox::CommitData() { + auto* pListBox = ToListBox(m_pNormalWidget.get()); + std::vector<int32_t> iSelArray; + int32_t iSels = pListBox->CountSelItems(); + for (int32_t i = 0; i < iSels; ++i) + iSelArray.push_back(pListBox->GetSelIndex(i)); + + m_pNode->GetWidgetAcc()->SetSelectedItems(iSelArray, true, false, true); + return true; +} + +bool CXFA_FFListBox::IsDataChanged() { + std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems(); + int32_t iOldSels = pdfium::CollectionSize<int32_t>(iSelArray); + auto* pListBox = ToListBox(m_pNormalWidget.get()); + int32_t iSels = pListBox->CountSelItems(); + if (iOldSels != iSels) + return true; + + for (int32_t i = 0; i < iSels; ++i) { + CFWL_ListItem* hlistItem = pListBox->GetItem(nullptr, iSelArray[i]); + if (!(hlistItem->GetStates() & FWL_ITEMSTATE_LTB_Selected)) + return true; + } + return false; +} + +uint32_t CXFA_FFListBox::GetAlignment() { + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (!para) + return 0; + + uint32_t dwExtendedStyle = 0; + switch (para->GetHorizontalAlign()) { + case XFA_AttributeEnum::Center: + dwExtendedStyle |= FWL_STYLEEXT_LTB_CenterAlign; + break; + case XFA_AttributeEnum::Justify: + break; + case XFA_AttributeEnum::JustifyAll: + break; + case XFA_AttributeEnum::Radix: + break; + case XFA_AttributeEnum::Right: + dwExtendedStyle |= FWL_STYLEEXT_LTB_RightAlign; + break; + default: + dwExtendedStyle |= FWL_STYLEEXT_LTB_LeftAlign; + break; + } + return dwExtendedStyle; +} + +bool CXFA_FFListBox::UpdateFWLData() { + if (!m_pNormalWidget) + return false; + + auto* pListBox = ToListBox(m_pNormalWidget.get()); + std::vector<int32_t> iSelArray = m_pNode->GetWidgetAcc()->GetSelectedItems(); + std::vector<CFWL_ListItem*> selItemArray(iSelArray.size()); + std::transform(iSelArray.begin(), iSelArray.end(), selItemArray.begin(), + [pListBox](int32_t val) { return pListBox->GetSelItem(val); }); + + pListBox->SetSelItem(pListBox->GetSelItem(-1), false); + for (CFWL_ListItem* pItem : selItemArray) + pListBox->SetSelItem(pItem, true); + + m_pNormalWidget->Update(); + return true; +} + +void CXFA_FFListBox::OnSelectChanged(CFWL_Widget* pWidget) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Change; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + eParam.m_wsPrevText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw); + + auto* pListBox = ToListBox(m_pNormalWidget.get()); + int32_t iSels = pListBox->CountSelItems(); + if (iSels > 0) { + CFWL_ListItem* item = pListBox->GetSelItem(0); + eParam.m_wsNewText = item ? item->GetText() : L""; + } + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam); +} + +void CXFA_FFListBox::SetItemState(int32_t nIndex, bool bSelected) { + auto* pListBox = ToListBox(m_pNormalWidget.get()); + pListBox->SetSelItem(pListBox->GetSelItem(nIndex), bSelected); + m_pNormalWidget->Update(); + AddInvalidateRect(); +} + +void CXFA_FFListBox::InsertItem(const WideStringView& wsLabel, int32_t nIndex) { + WideString wsTemp(wsLabel); + ToListBox(m_pNormalWidget.get())->AddString(wsTemp.AsStringView()); + m_pNormalWidget->Update(); + AddInvalidateRect(); +} + +void CXFA_FFListBox::DeleteItem(int32_t nIndex) { + auto* pListBox = ToListBox(m_pNormalWidget.get()); + if (nIndex < 0) + pListBox->DeleteAll(); + else + pListBox->DeleteString(pListBox->GetItem(nullptr, nIndex)); + + pListBox->Update(); + AddInvalidateRect(); +} + +void CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) { + m_pOldDelegate->OnProcessMessage(pMessage); +} + +void CXFA_FFListBox::OnProcessEvent(CFWL_Event* pEvent) { + CXFA_FFField::OnProcessEvent(pEvent); + switch (pEvent->GetType()) { + case CFWL_Event::Type::SelectChanged: + OnSelectChanged(m_pNormalWidget.get()); + break; + default: + break; + } + m_pOldDelegate->OnProcessEvent(pEvent); +} + +void CXFA_FFListBox::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + m_pOldDelegate->OnDrawWidget(pGraphics, matrix); +} + +FormFieldType CXFA_FFListBox::GetFormFieldType() { + return FormFieldType::kXFA_ListBox; +} diff --git a/xfa/fxfa/cxfa_fflistbox.h b/xfa/fxfa/cxfa_fflistbox.h new file mode 100644 index 0000000000000000000000000000000000000000..27f1cdb8a48e276b663161264db92f9003853da4 --- /dev/null +++ b/xfa/fxfa/cxfa_fflistbox.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFLISTBOX_H_ +#define XFA_FXFA_CXFA_FFLISTBOX_H_ + +#include "xfa/fxfa/cxfa_fffield.h" + +class CXFA_FFListBox : public CXFA_FFField { + public: + explicit CXFA_FFListBox(CXFA_Node* pNode); + ~CXFA_FFListBox() override; + + // CXFA_FFField + bool LoadWidget() override; + bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + FormFieldType GetFormFieldType() override; + + void OnSelectChanged(CFWL_Widget* pWidget); + void SetItemState(int32_t nIndex, bool bSelected); + void InsertItem(const WideStringView& wsLabel, int32_t nIndex); + void DeleteItem(int32_t nIndex); + + private: + bool CommitData() override; + bool UpdateFWLData() override; + bool IsDataChanged() override; + + uint32_t GetAlignment(); + + IFWL_WidgetDelegate* m_pOldDelegate; +}; + +#endif // XFA_FXFA_CXFA_FFLISTBOX_H_ diff --git a/xfa/fxfa/cxfa_ffnotify.cpp b/xfa/fxfa/cxfa_ffnotify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f416200303095c178e84ea416b7ba374814acc9 --- /dev/null +++ b/xfa/fxfa/cxfa_ffnotify.cpp @@ -0,0 +1,536 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffnotify.h" + +#include <memory> +#include <utility> + +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffarc.h" +#include "xfa/fxfa/cxfa_ffbarcode.h" +#include "xfa/fxfa/cxfa_ffcheckbutton.h" +#include "xfa/fxfa/cxfa_ffcombobox.h" +#include "xfa/fxfa/cxfa_ffdatetimeedit.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffdraw.h" +#include "xfa/fxfa/cxfa_ffexclgroup.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffimage.h" +#include "xfa/fxfa/cxfa_ffimageedit.h" +#include "xfa/fxfa/cxfa_ffline.h" +#include "xfa/fxfa/cxfa_fflistbox.h" +#include "xfa/fxfa/cxfa_ffnumericedit.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffpasswordedit.h" +#include "xfa/fxfa/cxfa_ffpushbutton.h" +#include "xfa/fxfa/cxfa_ffrectangle.h" +#include "xfa/fxfa/cxfa_ffsignature.h" +#include "xfa/fxfa/cxfa_ffsubform.h" +#include "xfa/fxfa/cxfa_fftext.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/cxfa_textlayout.h" +#include "xfa/fxfa/cxfa_textprovider.h" +#include "xfa/fxfa/parser/cxfa_binditems.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +namespace { + +CXFA_FFListBox* ToListBox(CXFA_FFWidget* widget) { + return static_cast<CXFA_FFListBox*>(widget); +} + +CXFA_FFComboBox* ToComboBox(CXFA_FFWidget* widget) { + return static_cast<CXFA_FFComboBox*>(widget); +} + +} // namespace + +CXFA_FFNotify::CXFA_FFNotify(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {} + +CXFA_FFNotify::~CXFA_FFNotify() {} + +void CXFA_FFNotify::OnPageEvent(CXFA_ContainerLayoutItem* pSender, + uint32_t dwEvent) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pSender->GetLayout()); + if (pDocView) + pDocView->OnPageEvent(pSender, dwEvent); +} + +void CXFA_FFNotify::OnWidgetListItemAdded(CXFA_WidgetAcc* pSender, + const wchar_t* pLabel, + const wchar_t* pValue, + int32_t iIndex) { + if (pSender->GetUIType() != XFA_Element::ChoiceList) + return; + + CXFA_FFWidget* pWidget = + m_pDoc->GetDocView()->GetWidgetForNode(pSender->GetNode()); + for (; pWidget; pWidget = pSender->GetNextWidget(pWidget)) { + if (pWidget->IsLoaded()) { + if (pSender->IsListBox()) + ToListBox(pWidget)->InsertItem(pLabel, iIndex); + else + ToComboBox(pWidget)->InsertItem(pLabel, iIndex); + } + } +} + +void CXFA_FFNotify::OnWidgetListItemRemoved(CXFA_WidgetAcc* pSender, + int32_t iIndex) { + if (pSender->GetUIType() != XFA_Element::ChoiceList) + return; + + CXFA_FFWidget* pWidget = + m_pDoc->GetDocView()->GetWidgetForNode(pSender->GetNode()); + for (; pWidget; pWidget = pSender->GetNextWidget(pWidget)) { + if (pWidget->IsLoaded()) { + if (pSender->IsListBox()) + ToListBox(pWidget)->DeleteItem(iIndex); + else + ToComboBox(pWidget)->DeleteItem(iIndex); + } + } +} + +CXFA_ContainerLayoutItem* CXFA_FFNotify::OnCreateContainerLayoutItem( + CXFA_Node* pNode) { + XFA_Element type = pNode->GetElementType(); + ASSERT(type == XFA_Element::ContentArea || type == XFA_Element::PageArea); + + if (type == XFA_Element::PageArea) { + CXFA_LayoutProcessor* pLayout = m_pDoc->GetXFADoc()->GetDocLayout(); + return new CXFA_FFPageView(m_pDoc->GetDocView(pLayout), pNode); + } + return new CXFA_ContainerLayoutItem(pNode); +} + +CXFA_ContentLayoutItem* CXFA_FFNotify::OnCreateContentLayoutItem( + CXFA_Node* pNode) { + ASSERT(pNode->GetElementType() != XFA_Element::ContentArea); + ASSERT(pNode->GetElementType() != XFA_Element::PageArea); + + // We only need to create the widget for certain types of objects. + if (!pNode->HasCreatedUIWidget()) + return new CXFA_ContentLayoutItem(pNode); + + CXFA_FFWidget* pWidget; + switch (pNode->GetWidgetAcc()->GetUIType()) { + case XFA_Element::Barcode: + pWidget = new CXFA_FFBarcode(pNode); + break; + case XFA_Element::Button: + pWidget = new CXFA_FFPushButton(pNode); + break; + case XFA_Element::CheckButton: + pWidget = new CXFA_FFCheckButton(pNode); + break; + case XFA_Element::ChoiceList: { + if (pNode->GetWidgetAcc()->IsListBox()) + pWidget = new CXFA_FFListBox(pNode); + else + pWidget = new CXFA_FFComboBox(pNode); + } break; + case XFA_Element::DateTimeEdit: + pWidget = new CXFA_FFDateTimeEdit(pNode); + break; + case XFA_Element::ImageEdit: + pWidget = new CXFA_FFImageEdit(pNode); + break; + case XFA_Element::NumericEdit: + pWidget = new CXFA_FFNumericEdit(pNode); + break; + case XFA_Element::PasswordEdit: + pWidget = new CXFA_FFPasswordEdit(pNode); + break; + case XFA_Element::Signature: + pWidget = new CXFA_FFSignature(pNode); + break; + case XFA_Element::TextEdit: + pWidget = new CXFA_FFTextEdit(pNode); + break; + case XFA_Element::Arc: + pWidget = new CXFA_FFArc(pNode); + break; + case XFA_Element::Line: + pWidget = new CXFA_FFLine(pNode); + break; + case XFA_Element::Rectangle: + pWidget = new CXFA_FFRectangle(pNode); + break; + case XFA_Element::Text: + pWidget = new CXFA_FFText(pNode); + break; + case XFA_Element::Image: + pWidget = new CXFA_FFImage(pNode); + break; + case XFA_Element::Draw: + pWidget = new CXFA_FFDraw(pNode); + break; + case XFA_Element::Subform: + pWidget = new CXFA_FFSubForm(pNode); + break; + case XFA_Element::ExclGroup: + pWidget = new CXFA_FFExclGroup(pNode); + break; + case XFA_Element::DefaultUi: + default: + pWidget = nullptr; + break; + } + + if (pWidget) { + CXFA_LayoutProcessor* pLayout = m_pDoc->GetXFADoc()->GetDocLayout(); + pWidget->SetDocView(m_pDoc->GetDocView(pLayout)); + } + return pWidget; +} + +void CXFA_FFNotify::StartFieldDrawLayout(CXFA_Node* pItem, + float& fCalcWidth, + float& fCalcHeight) { + CXFA_WidgetAcc* pAcc = pItem->GetWidgetAcc(); + if (!pAcc) + return; + + pAcc->StartWidgetLayout(m_pDoc.Get(), fCalcWidth, fCalcHeight); +} + +bool CXFA_FFNotify::FindSplitPos(CXFA_Node* pItem, + int32_t iBlockIndex, + float& fCalcHeightPos) { + CXFA_WidgetAcc* pAcc = pItem->GetWidgetAcc(); + return pAcc && + pAcc->FindSplitPos(m_pDoc->GetDocView(), iBlockIndex, fCalcHeightPos); +} + +bool CXFA_FFNotify::RunScript(CXFA_Script* script, CXFA_Node* item) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return false; + + CXFA_EventParam EventParam; + EventParam.m_eType = XFA_EVENT_Unknown; + + int32_t iRet; + bool bRet; + std::tie(iRet, bRet) = item->ExecuteBoolScript(pDocView, script, &EventParam); + return iRet == XFA_EVENTERROR_Success && bRet; +} + +int32_t CXFA_FFNotify::ExecEventByDeepFirst(CXFA_Node* pFormNode, + XFA_EVENTTYPE eEventType, + bool bIsFormReady, + bool bRecursive, + CXFA_WidgetAcc* pExclude) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return XFA_EVENTERROR_NotExist; + return pDocView->ExecEventActivityByDeepFirst( + pFormNode, eEventType, bIsFormReady, bRecursive, + pExclude ? pExclude->GetNode() : nullptr); +} + +void CXFA_FFNotify::AddCalcValidate(CXFA_Node* pNode) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + CXFA_WidgetAcc* pWidgetAcc = pNode->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + pDocView->AddCalculateWidgetAcc(pWidgetAcc); + pDocView->AddValidateWidget(pWidgetAcc); +} + +CXFA_FFDoc* CXFA_FFNotify::GetHDOC() { + return m_pDoc.Get(); +} + +IXFA_DocEnvironment* CXFA_FFNotify::GetDocEnvironment() const { + return m_pDoc->GetDocEnvironment(); +} + +IXFA_AppProvider* CXFA_FFNotify::GetAppProvider() { + return m_pDoc->GetApp()->GetAppProvider(); +} + +CXFA_FFWidgetHandler* CXFA_FFNotify::GetWidgetHandler() { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + return pDocView ? pDocView->GetWidgetHandler() : nullptr; +} + +CXFA_FFWidget* CXFA_FFNotify::GetHWidget(CXFA_LayoutItem* pLayoutItem) { + return XFA_GetWidgetFromLayoutItem(pLayoutItem); +} + +void CXFA_FFNotify::OpenDropDownList(CXFA_FFWidget* hWidget) { + if (hWidget->GetNode()->GetWidgetAcc()->GetUIType() != + XFA_Element::ChoiceList) + return; + + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + pDocView->LockUpdate(); + ToComboBox(hWidget)->OpenDropDownList(); + pDocView->UnlockUpdate(); + pDocView->UpdateDocView(); +} + +WideString CXFA_FFNotify::GetCurrentDateTime() { + CFX_DateTime dataTime = CFX_DateTime::Now(); + return WideString::Format(L"%d%02d%02dT%02d%02d%02d", dataTime.GetYear(), + dataTime.GetMonth(), dataTime.GetDay(), + dataTime.GetHour(), dataTime.GetMinute(), + dataTime.GetSecond()); +} + +void CXFA_FFNotify::ResetData(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + pDocView->ResetWidgetAcc(pWidgetAcc); +} + +int32_t CXFA_FFNotify::GetLayoutStatus() { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + return pDocView ? pDocView->GetLayoutStatus() : 0; +} + +void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + pDocView->AddNewFormNode(pNode); +} + +void CXFA_FFNotify::RunSubformIndexChange(CXFA_Node* pSubformNode) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + pDocView->AddIndexChangedSubform(pSubformNode); +} + +CXFA_Node* CXFA_FFNotify::GetFocusWidgetNode() { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return nullptr; + + CXFA_WidgetAcc* pAcc = pDocView->GetFocusWidgetAcc(); + return pAcc ? pAcc->GetNode() : nullptr; +} + +void CXFA_FFNotify::SetFocusWidgetNode(CXFA_Node* pNode) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + CXFA_WidgetAcc* pAcc = pNode ? pNode->GetWidgetAcc() : nullptr; + pDocView->SetFocusWidgetAcc(pAcc); +} + +void CXFA_FFNotify::OnNodeReady(CXFA_Node* pNode) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + if (pNode->HasCreatedUIWidget()) { + pNode->CreateWidgetAcc(); + return; + } + + switch (pNode->GetElementType()) { + case XFA_Element::BindItems: + pDocView->AddBindItem(static_cast<CXFA_BindItems*>(pNode)); + break; + case XFA_Element::Validate: + pNode->SetFlag(XFA_NodeFlag_NeedsInitApp, false); + break; + default: + break; + } +} + +void CXFA_FFNotify::OnValueChanging(CXFA_Node* pSender, XFA_Attribute eAttr) { + if (eAttr != XFA_Attribute::Presence) + return; + if (pSender->GetPacketType() == XFA_PacketType::Datasets) + return; + if (!pSender->IsFormContainer()) + return; + + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + if (pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End) + return; + + CXFA_WidgetAcc* pWidgetAcc = pSender->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + CXFA_FFWidget* pWidget = + m_pDoc->GetDocView()->GetWidgetForNode(pWidgetAcc->GetNode()); + for (; pWidget; pWidget = pWidgetAcc->GetNextWidget(pWidget)) { + if (pWidget->IsLoaded()) + pWidget->AddInvalidateRect(); + } +} + +void CXFA_FFNotify::OnValueChanged(CXFA_Node* pSender, + XFA_Attribute eAttr, + CXFA_Node* pParentNode, + CXFA_Node* pWidgetNode) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + if (pSender->GetPacketType() != XFA_PacketType::Form) { + if (eAttr == XFA_Attribute::Value) + pDocView->AddCalculateNodeNotify(pSender); + return; + } + + XFA_Element eType = pParentNode->GetElementType(); + bool bIsContainerNode = pParentNode->IsContainerNode(); + CXFA_WidgetAcc* pWidgetAcc = pWidgetNode->GetWidgetAcc(); + if (!pWidgetAcc) + return; + + bool bUpdateProperty = false; + pDocView->SetChangeMark(); + switch (eType) { + case XFA_Element::Caption: { + CXFA_TextLayout* pCapOut = pWidgetAcc->GetCaptionTextLayout(); + if (!pCapOut) + return; + + pCapOut->Unload(); + break; + } + case XFA_Element::Ui: + case XFA_Element::Para: + bUpdateProperty = true; + break; + default: + break; + } + if (bIsContainerNode && eAttr == XFA_Attribute::Access) + bUpdateProperty = true; + + if (eAttr == XFA_Attribute::Value) { + pDocView->AddCalculateNodeNotify(pSender); + if (eType == XFA_Element::Value || bIsContainerNode) { + if (bIsContainerNode) { + pWidgetAcc->UpdateUIDisplay(m_pDoc->GetDocView(), nullptr); + pDocView->AddCalculateWidgetAcc(pWidgetAcc); + pDocView->AddValidateWidget(pWidgetAcc); + } else if (pWidgetNode->GetParent()->GetElementType() == + XFA_Element::ExclGroup) { + pWidgetAcc->UpdateUIDisplay(m_pDoc->GetDocView(), nullptr); + } + return; + } + } + + CXFA_FFWidget* pWidget = + m_pDoc->GetDocView()->GetWidgetForNode(pWidgetAcc->GetNode()); + for (; pWidget; pWidget = pWidgetAcc->GetNextWidget(pWidget)) { + if (!pWidget->IsLoaded()) + continue; + + if (bUpdateProperty) + pWidget->UpdateWidgetProperty(); + pWidget->PerformLayout(); + pWidget->AddInvalidateRect(); + } +} + +void CXFA_FFNotify::OnChildAdded(CXFA_Node* pSender) { + if (!pSender->IsFormContainer()) + return; + + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + bool bLayoutReady = + !(pDocView->m_bInLayoutStatus) && + (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End); + if (bLayoutReady) + m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get()); +} + +void CXFA_FFNotify::OnChildRemoved() { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(); + if (!pDocView) + return; + + bool bLayoutReady = + !(pDocView->m_bInLayoutStatus) && + (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End); + if (bLayoutReady) + m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get()); +} + +void CXFA_FFNotify::OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout, + CXFA_LayoutItem* pSender, + int32_t iPageIdx, + uint32_t dwStatus) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout); + if (!pDocView) + return; + + CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender); + if (!pWidget) + return; + + CXFA_FFPageView* pNewPageView = pDocView->GetPageView(iPageIdx); + uint32_t dwFilter = XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable | + XFA_WidgetStatus_Printable; + pWidget->ModifyStatus(dwStatus, dwFilter); + CXFA_FFPageView* pPrePageView = pWidget->GetPageView(); + if (pPrePageView != pNewPageView || + (dwStatus & (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) == + (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable)) { + pWidget->SetPageView(pNewPageView); + m_pDoc->GetDocEnvironment()->WidgetPostAdd( + pWidget, pWidget->GetNode()->GetWidgetAcc()); + } + if (pDocView->GetLayoutStatus() != XFA_DOCVIEW_LAYOUTSTATUS_End || + !(dwStatus & XFA_WidgetStatus_Visible)) { + return; + } + if (pWidget->IsLoaded()) { + if (pWidget->GetWidgetRect() != pWidget->RecacheWidgetRect()) + pWidget->PerformLayout(); + } else { + pWidget->LoadWidget(); + } + pWidget->AddInvalidateRect(); +} + +void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout, + CXFA_LayoutItem* pSender) { + CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout); + if (!pDocView) + return; + + CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pSender); + if (!pWidget) + return; + + pDocView->DeleteLayoutItem(pWidget); + m_pDoc->GetDocEnvironment()->WidgetPreRemove( + pWidget, pWidget->GetNode()->GetWidgetAcc()); + pWidget->AddInvalidateRect(); +} diff --git a/xfa/fxfa/cxfa_ffnotify.h b/xfa/fxfa/cxfa_ffnotify.h new file mode 100644 index 0000000000000000000000000000000000000000..924a06021097054ed2bb9aabcf8c7ee2181a2d19 --- /dev/null +++ b/xfa/fxfa/cxfa_ffnotify.h @@ -0,0 +1,81 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFNOTIFY_H_ +#define XFA_FXFA_CXFA_FFNOTIFY_H_ + +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/parser/cxfa_document.h" + +class CXFA_FFWidgetHandler; +class CXFA_ContainerLayoutItem; +class CXFA_ContentLayoutItem; + +class CXFA_FFNotify { + public: + explicit CXFA_FFNotify(CXFA_FFDoc* pDoc); + ~CXFA_FFNotify(); + + void OnPageEvent(CXFA_ContainerLayoutItem* pSender, uint32_t dwEvent); + + void OnWidgetListItemAdded(CXFA_WidgetAcc* pSender, + const wchar_t* pLabel, + const wchar_t* pValue, + int32_t iIndex); + void OnWidgetListItemRemoved(CXFA_WidgetAcc* pSender, int32_t iIndex); + + // Node events + void OnNodeReady(CXFA_Node* pNode); + void OnValueChanging(CXFA_Node* pSender, XFA_Attribute eAttr); + void OnValueChanged(CXFA_Node* pSender, + XFA_Attribute eAttr, + CXFA_Node* pParentNode, + CXFA_Node* pWidgetNode); + void OnChildAdded(CXFA_Node* pSender); + void OnChildRemoved(); + + CXFA_ContainerLayoutItem* OnCreateContainerLayoutItem(CXFA_Node* pNode); + CXFA_ContentLayoutItem* OnCreateContentLayoutItem(CXFA_Node* pNode); + + void OnLayoutItemAdded(CXFA_LayoutProcessor* pLayout, + CXFA_LayoutItem* pSender, + int32_t iPageIdx, + uint32_t dwStatus); + void OnLayoutItemRemoving(CXFA_LayoutProcessor* pLayout, + CXFA_LayoutItem* pSender); + + void StartFieldDrawLayout(CXFA_Node* pItem, + float& fCalcWidth, + float& fCalcHeight); + bool FindSplitPos(CXFA_Node* pItem, + int32_t iBlockIndex, + float& fCalcHeightPos); + bool RunScript(CXFA_Script* pScript, CXFA_Node* pFormItem); + int32_t ExecEventByDeepFirst(CXFA_Node* pFormNode, + XFA_EVENTTYPE eEventType, + bool bIsFormReady = false, + bool bRecursive = true, + CXFA_WidgetAcc* pExclude = nullptr); + void AddCalcValidate(CXFA_Node* pNode); + CXFA_FFDoc* GetHDOC(); + IXFA_DocEnvironment* GetDocEnvironment() const; + IXFA_AppProvider* GetAppProvider(); + CXFA_FFWidgetHandler* GetWidgetHandler(); + CXFA_FFWidget* GetHWidget(CXFA_LayoutItem* pLayoutItem); + void OpenDropDownList(CXFA_FFWidget* hWidget); + WideString GetCurrentDateTime(); + void ResetData(CXFA_WidgetAcc* pWidgetAcc = nullptr); + int32_t GetLayoutStatus(); + void RunNodeInitialize(CXFA_Node* pNode); + void RunSubformIndexChange(CXFA_Node* pSubformNode); + CXFA_Node* GetFocusWidgetNode(); + void SetFocusWidgetNode(CXFA_Node* pNode); + + private: + UnownedPtr<CXFA_FFDoc> const m_pDoc; +}; + +#endif // XFA_FXFA_CXFA_FFNOTIFY_H_ diff --git a/xfa/fxfa/cxfa_ffnumericedit.cpp b/xfa/fxfa/cxfa_ffnumericedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b437bc2b2a5a21d9578515b11e9dffab792dc108 --- /dev/null +++ b/xfa/fxfa/cxfa_ffnumericedit.cpp @@ -0,0 +1,91 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffnumericedit.h" + +#include <utility> + +#include "xfa/fwl/cfwl_edit.h" +#include "xfa/fwl/cfwl_eventvalidate.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +CXFA_FFNumericEdit::CXFA_FFNumericEdit(CXFA_Node* pNode) + : CXFA_FFTextEdit(pNode) {} + +CXFA_FFNumericEdit::~CXFA_FFNumericEdit() {} + +bool CXFA_FFNumericEdit::LoadWidget() { + auto pNewEdit = pdfium::MakeUnique<CFWL_Edit>( + GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); + CFWL_Edit* pWidget = pNewEdit.get(); + m_pNormalWidget = std::move(pNewEdit); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + + pWidget->SetText(m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Display)); + UpdateWidgetProperty(); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFNumericEdit::UpdateWidgetProperty() { + CFWL_Edit* pWidget = static_cast<CFWL_Edit*>(m_pNormalWidget.get()); + if (!pWidget) + return; + + uint32_t dwExtendedStyle = + FWL_STYLEEXT_EDT_ShowScrollbarFocus | FWL_STYLEEXT_EDT_OuterScrollbar | + FWL_STYLEEXT_EDT_Validate | FWL_STYLEEXT_EDT_Number; + dwExtendedStyle |= UpdateUIProperty(); + if (!m_pNode->GetWidgetAcc()->IsHorizontalScrollPolicyOff()) + dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll; + + Optional<int32_t> numCells = m_pNode->GetWidgetAcc()->GetNumberOfCells(); + if (numCells && *numCells > 0) { + dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText; + pWidget->SetLimit(*numCells); + } + dwExtendedStyle |= GetAlignment(); + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) + dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly; + + m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); +} + +void CXFA_FFNumericEdit::OnProcessEvent(CFWL_Event* pEvent) { + if (pEvent->GetType() == CFWL_Event::Type::Validate) { + CFWL_EventValidate* event = static_cast<CFWL_EventValidate*>(pEvent); + event->bValidate = OnValidate(m_pNormalWidget.get(), event->wsInsert); + return; + } + CXFA_FFTextEdit::OnProcessEvent(pEvent); +} + +bool CXFA_FFNumericEdit::OnValidate(CFWL_Widget* pWidget, WideString& wsText) { + WideString wsPattern = + m_pNode->GetWidgetAcc()->GetPictureContent(XFA_VALUEPICTURE_Edit); + if (!wsPattern.IsEmpty()) + return true; + + WideString wsFormat; + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(m_pNode.Get()); + widgetValue.GetNumericFormat(wsFormat, + m_pNode->GetWidgetAcc()->GetLeadDigits(), + m_pNode->GetWidgetAcc()->GetFracDigits()); + return widgetValue.ValidateNumericTemp(wsText, wsFormat, + m_pNode->GetLocale()); +} diff --git a/xfa/fxfa/cxfa_ffnumericedit.h b/xfa/fxfa/cxfa_ffnumericedit.h new file mode 100644 index 0000000000000000000000000000000000000000..c413ac60c0fdd40b1b662e9b8447bf7db5e624e1 --- /dev/null +++ b/xfa/fxfa/cxfa_ffnumericedit.h @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFNUMERICEDIT_H_ +#define XFA_FXFA_CXFA_FFNUMERICEDIT_H_ + +#include "core/fxcrt/fx_string.h" +#include "xfa/fxfa/cxfa_fftextedit.h" + +class CFWL_Event; +class CFWL_Widget; +class CXFA_WidgetAcc; + +class CXFA_FFNumericEdit : public CXFA_FFTextEdit { + public: + explicit CXFA_FFNumericEdit(CXFA_Node* pNode); + ~CXFA_FFNumericEdit() override; + + // CXFA_FFTextEdit + bool LoadWidget() override; + void UpdateWidgetProperty() override; + void OnProcessEvent(CFWL_Event* pEvent) override; + + private: + bool OnValidate(CFWL_Widget* pWidget, WideString& wsText); +}; + +#endif // XFA_FXFA_CXFA_FFNUMERICEDIT_H_ diff --git a/xfa/fxfa/cxfa_ffpageview.cpp b/xfa/fxfa/cxfa_ffpageview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe1fbb517fb90fc7abceb24648da3d292926a235 --- /dev/null +++ b/xfa/fxfa/cxfa_ffpageview.cpp @@ -0,0 +1,467 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffpageview.h" + +#include <algorithm> +#include <memory> +#include <vector> + +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/cxfa_ffcheckbutton.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffimageedit.h" +#include "xfa/fxfa/cxfa_ffpushbutton.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_traversal.h" +#include "xfa/fxfa/parser/cxfa_traverse.h" + +namespace { + +CFX_Matrix GetPageMatrix(const CFX_RectF& docPageRect, + const CFX_Rect& devicePageRect, + int32_t iRotate, + uint32_t dwCoordinatesType) { + ASSERT(iRotate >= 0 && iRotate <= 3); + + bool bFlipX = (dwCoordinatesType & 0x01) != 0; + bool bFlipY = (dwCoordinatesType & 0x02) != 0; + CFX_Matrix m((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0); + if (iRotate == 0 || iRotate == 2) { + m.a *= (float)devicePageRect.width / docPageRect.width; + m.d *= (float)devicePageRect.height / docPageRect.height; + } else { + m.a *= (float)devicePageRect.height / docPageRect.width; + m.d *= (float)devicePageRect.width / docPageRect.height; + } + m.Rotate(iRotate * 1.57079632675f); + switch (iRotate) { + case 0: + m.e = bFlipX ? (float)devicePageRect.right() : (float)devicePageRect.left; + m.f = bFlipY ? (float)devicePageRect.bottom() : (float)devicePageRect.top; + break; + case 1: + m.e = bFlipY ? (float)devicePageRect.left : (float)devicePageRect.right(); + m.f = bFlipX ? (float)devicePageRect.bottom() : (float)devicePageRect.top; + break; + case 2: + m.e = bFlipX ? (float)devicePageRect.left : (float)devicePageRect.right(); + m.f = bFlipY ? (float)devicePageRect.top : (float)devicePageRect.bottom(); + break; + case 3: + m.e = bFlipY ? (float)devicePageRect.right() : (float)devicePageRect.left; + m.f = bFlipX ? (float)devicePageRect.top : (float)devicePageRect.bottom(); + break; + default: + break; + } + return m; +} + +bool PageWidgetFilter(CXFA_FFWidget* pWidget, + uint32_t dwFilter, + bool bTraversal, + bool bIgnorerelevant) { + CXFA_Node* pNode = pWidget->GetNode(); + + if (!!(dwFilter & XFA_WidgetStatus_Focused) && + (!pNode || pNode->GetElementType() != XFA_Element::Field)) { + return false; + } + + uint32_t dwStatus = pWidget->GetStatus(); + if (bTraversal && (dwStatus & XFA_WidgetStatus_Disabled)) + return false; + if (bIgnorerelevant) + return !!(dwStatus & XFA_WidgetStatus_Visible); + + dwFilter &= (XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable | + XFA_WidgetStatus_Printable); + return (dwFilter & dwStatus) == dwFilter; +} + +bool IsLayoutElement(XFA_Element eElement, bool bLayoutContainer) { + switch (eElement) { + case XFA_Element::Draw: + case XFA_Element::Field: + case XFA_Element::InstanceManager: + return !bLayoutContainer; + case XFA_Element::Area: + case XFA_Element::Subform: + case XFA_Element::ExclGroup: + case XFA_Element::SubformSet: + case XFA_Element::PageArea: + case XFA_Element::Form: + return true; + default: + return false; + } +} + +} // namespace + +CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea) + : CXFA_ContainerLayoutItem(pPageArea), m_pDocView(pDocView) {} + +CXFA_FFPageView::~CXFA_FFPageView() {} + +CXFA_FFDocView* CXFA_FFPageView::GetDocView() const { + return m_pDocView.Get(); +} + +CFX_RectF CXFA_FFPageView::GetPageViewRect() const { + return CFX_RectF(0, 0, GetPageSize()); +} + +CFX_Matrix CXFA_FFPageView::GetDisplayMatrix(const CFX_Rect& rtDisp, + int32_t iRotate) const { + return GetPageMatrix(CFX_RectF(0, 0, GetPageSize()), rtDisp, iRotate, 0); +} + +std::unique_ptr<IXFA_WidgetIterator> CXFA_FFPageView::CreateWidgetIterator( + uint32_t dwTraverseWay, + uint32_t dwWidgetFilter) { + switch (dwTraverseWay) { + case XFA_TRAVERSEWAY_Tranvalse: + return pdfium::MakeUnique<CXFA_FFTabOrderPageWidgetIterator>( + this, dwWidgetFilter); + case XFA_TRAVERSEWAY_Form: + return pdfium::MakeUnique<CXFA_FFPageWidgetIterator>(this, + dwWidgetFilter); + } + return nullptr; +} + +CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView, + uint32_t dwFilter) + : m_pPageView(pPageView), m_dwFilter(dwFilter), m_sIterator(pPageView) { + m_bIgnorerelevant = + m_pPageView->GetDocView()->GetDoc()->GetXFADoc()->GetCurVersionMode() < + XFA_VERSION_205; +} + +CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() {} + +void CXFA_FFPageWidgetIterator::Reset() { + m_sIterator.Reset(); +} + +CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToFirst() { + m_sIterator.Reset(); + for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem; + pLayoutItem = m_sIterator.MoveToNext()) { + if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) { + return hWidget; + } + } + return nullptr; +} + +CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToLast() { + m_sIterator.SetCurrent(nullptr); + return MoveToPrevious(); +} + +CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToNext() { + for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem; + pLayoutItem = m_sIterator.MoveToNext()) { + if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) { + return hWidget; + } + } + return nullptr; +} + +CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToPrevious() { + for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem; + pLayoutItem = m_sIterator.MoveToPrev()) { + if (CXFA_FFWidget* hWidget = GetWidget(pLayoutItem)) { + return hWidget; + } + } + return nullptr; +} + +CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetCurrentWidget() { + CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); + return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : nullptr; +} + +bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* hWidget) { + return hWidget && m_sIterator.SetCurrent(hWidget); +} + +CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetWidget( + CXFA_LayoutItem* pLayoutItem) { + CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem); + if (!pWidget) + return nullptr; + + if (!PageWidgetFilter(pWidget, m_dwFilter, false, m_bIgnorerelevant)) + return nullptr; + + if (!pWidget->IsLoaded() && + !!(pWidget->GetStatus() & XFA_WidgetStatus_Visible)) { + if (!pWidget->LoadWidget()) + return nullptr; + } + return pWidget; +} + +void CXFA_TabParam::AppendTabParam(CXFA_TabParam* pParam) { + m_Children.push_back(pParam->GetWidget()); + m_Children.insert(m_Children.end(), pParam->GetChildren().begin(), + pParam->GetChildren().end()); +} + +void CXFA_TabParam::ClearChildren() { + m_Children.clear(); +} + +CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator( + CXFA_FFPageView* pPageView, + uint32_t dwFilter) + : m_pPageView(pPageView), m_dwFilter(dwFilter), m_iCurWidget(-1) { + m_bIgnorerelevant = + m_pPageView->GetDocView()->GetDoc()->GetXFADoc()->GetCurVersionMode() < + XFA_VERSION_205; + Reset(); +} + +CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() {} + +void CXFA_FFTabOrderPageWidgetIterator::Reset() { + CreateTabOrderWidgetArray(); + m_iCurWidget = -1; +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() { + for (int32_t i = 0; + i < pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) { + if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, + m_bIgnorerelevant)) { + m_iCurWidget = i; + return m_TabOrderWidgetArray[m_iCurWidget]; + } + } + return nullptr; +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() { + for (int32_t i = pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray) - 1; + i >= 0; i--) { + if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, + m_bIgnorerelevant)) { + m_iCurWidget = i; + return m_TabOrderWidgetArray[m_iCurWidget]; + } + } + return nullptr; +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() { + for (int32_t i = m_iCurWidget + 1; + i < pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) { + if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, + m_bIgnorerelevant)) { + m_iCurWidget = i; + return m_TabOrderWidgetArray[m_iCurWidget]; + } + } + m_iCurWidget = -1; + return nullptr; +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() { + for (int32_t i = m_iCurWidget - 1; i >= 0; i--) { + if (PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, true, + m_bIgnorerelevant)) { + m_iCurWidget = i; + return m_TabOrderWidgetArray[m_iCurWidget]; + } + } + m_iCurWidget = -1; + return nullptr; +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() { + return m_iCurWidget >= 0 ? m_TabOrderWidgetArray[m_iCurWidget] : nullptr; +} + +bool CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget( + CXFA_FFWidget* hWidget) { + auto it = std::find(m_TabOrderWidgetArray.begin(), + m_TabOrderWidgetArray.end(), hWidget); + if (it == m_TabOrderWidgetArray.end()) + return false; + + m_iCurWidget = it - m_TabOrderWidgetArray.begin(); + return true; +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget( + CXFA_FFWidget* pWidget) { + CXFA_Traversal* pTraversal = pWidget->GetNode()->GetChild<CXFA_Traversal>( + 0, XFA_Element::Traversal, false); + if (pTraversal) { + CXFA_Traverse* pTraverse = + pTraversal->GetChild<CXFA_Traverse>(0, XFA_Element::Traverse, false); + if (pTraverse) { + Optional<WideString> traverseWidgetName = + pTraverse->JSObject()->TryAttribute(XFA_Attribute::Ref, true); + if (traverseWidgetName) + return FindWidgetByName(*traverseWidgetName, pWidget); + } + } + return nullptr; +} +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName( + const WideString& wsWidgetName, + CXFA_FFWidget* pRefWidget) { + return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget); +} + +void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() { + m_TabOrderWidgetArray.clear(); + + std::vector<CXFA_FFWidget*> SpaceOrderWidgetArray; + CreateSpaceOrderWidgetArray(&SpaceOrderWidgetArray); + if (SpaceOrderWidgetArray.empty()) + return; + + int32_t nWidgetCount = pdfium::CollectionSize<int32_t>(SpaceOrderWidgetArray); + CXFA_FFWidget* hWidget = SpaceOrderWidgetArray[0]; + while (pdfium::CollectionSize<int32_t>(m_TabOrderWidgetArray) < + nWidgetCount) { + if (!pdfium::ContainsValue(m_TabOrderWidgetArray, hWidget)) { + m_TabOrderWidgetArray.push_back(hWidget); + CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc(); + if (pWidgetAcc->GetUIType() == XFA_Element::ExclGroup) { + auto it = std::find(SpaceOrderWidgetArray.begin(), + SpaceOrderWidgetArray.end(), hWidget); + int32_t iWidgetIndex = it != SpaceOrderWidgetArray.end() + ? it - SpaceOrderWidgetArray.begin() + 1 + : 0; + while (true) { + CXFA_FFWidget* radio = + SpaceOrderWidgetArray[iWidgetIndex % nWidgetCount]; + if (radio->GetNode()->GetExclGroupIfExists() != pWidgetAcc->GetNode()) + break; + if (!pdfium::ContainsValue(m_TabOrderWidgetArray, hWidget)) + m_TabOrderWidgetArray.push_back(radio); + + iWidgetIndex++; + } + } + if (CXFA_FFWidget* hTraverseWidget = GetTraverseWidget(hWidget)) { + hWidget = hTraverseWidget; + continue; + } + } + auto it = std::find(SpaceOrderWidgetArray.begin(), + SpaceOrderWidgetArray.end(), hWidget); + int32_t iWidgetIndex = it != SpaceOrderWidgetArray.end() + ? it - SpaceOrderWidgetArray.begin() + 1 + : 0; + hWidget = SpaceOrderWidgetArray[iWidgetIndex % nWidgetCount]; + } +} + +void CXFA_FFTabOrderPageWidgetIterator::OrderContainer( + CXFA_LayoutItemIterator* sIterator, + CXFA_LayoutItem* pContainerItem, + CXFA_TabParam* pContainer, + bool& bCurrentItem, + bool& bContentArea, + bool bMarsterPage) { + std::vector<std::unique_ptr<CXFA_TabParam>> tabParams; + CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext(); + while (pSearchItem) { + if (!pSearchItem->IsContentLayoutItem()) { + bContentArea = true; + pSearchItem = sIterator->MoveToNext(); + continue; + } + if (bMarsterPage && bContentArea) { + break; + } + if (bMarsterPage || bContentArea) { + CXFA_FFWidget* hWidget = GetWidget(pSearchItem); + if (!hWidget) { + pSearchItem = sIterator->MoveToNext(); + continue; + } + if (pContainerItem && (pSearchItem->GetParent() != pContainerItem)) { + bCurrentItem = true; + break; + } + tabParams.push_back(pdfium::MakeUnique<CXFA_TabParam>(hWidget)); + if (IsLayoutElement(pSearchItem->GetFormNode()->GetElementType(), true)) { + OrderContainer(sIterator, pSearchItem, tabParams.back().get(), + bCurrentItem, bContentArea, bMarsterPage); + } + } + if (bCurrentItem) { + pSearchItem = sIterator->GetCurrent(); + bCurrentItem = false; + } else { + pSearchItem = sIterator->MoveToNext(); + } + } + std::sort(tabParams.begin(), tabParams.end(), + [](const std::unique_ptr<CXFA_TabParam>& arg1, + const std::unique_ptr<CXFA_TabParam>& arg2) { + const CFX_RectF& rt1 = arg1->GetWidget()->GetWidgetRect(); + const CFX_RectF& rt2 = arg2->GetWidget()->GetWidgetRect(); + if (rt1.top - rt2.top >= XFA_FLOAT_PERCISION) + return rt1.top < rt2.top; + return rt1.left < rt2.left; + }); + for (const auto& pParam : tabParams) + pContainer->AppendTabParam(pParam.get()); +} + +void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray( + std::vector<CXFA_FFWidget*>* WidgetArray) { + CXFA_LayoutItemIterator sIterator(m_pPageView); + auto pParam = pdfium::MakeUnique<CXFA_TabParam>(nullptr); + bool bCurrentItem = false; + bool bContentArea = false; + OrderContainer(&sIterator, nullptr, pParam.get(), bCurrentItem, bContentArea); + WidgetArray->insert(WidgetArray->end(), pParam->GetChildren().begin(), + pParam->GetChildren().end()); + + sIterator.Reset(); + bCurrentItem = false; + bContentArea = false; + pParam->ClearChildren(); + OrderContainer(&sIterator, nullptr, pParam.get(), bCurrentItem, bContentArea, + true); + WidgetArray->insert(WidgetArray->end(), pParam->GetChildren().begin(), + pParam->GetChildren().end()); +} + +CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetWidget( + CXFA_LayoutItem* pLayoutItem) { + if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) { + if (!pWidget->IsLoaded() && + (pWidget->GetStatus() & XFA_WidgetStatus_Visible)) { + pWidget->LoadWidget(); + } + return pWidget; + } + return nullptr; +} + +CXFA_TabParam::CXFA_TabParam(CXFA_FFWidget* pWidget) : m_pWidget(pWidget) {} + +CXFA_TabParam::~CXFA_TabParam() {} diff --git a/xfa/fxfa/cxfa_ffpageview.h b/xfa/fxfa/cxfa_ffpageview.h new file mode 100644 index 0000000000000000000000000000000000000000..b33e25f79db0aa0386cae616206b56e64698c5ae --- /dev/null +++ b/xfa/fxfa/cxfa_ffpageview.h @@ -0,0 +1,114 @@ +// Copyrig 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFPAGEVIEW_H_ +#define XFA_FXFA_CXFA_FFPAGEVIEW_H_ + +#include <memory> +#include <vector> + +#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h" + +class CXFA_FFWidget; +class CXFA_FFDocView; + +class CXFA_FFPageView : public CXFA_ContainerLayoutItem { + public: + CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea); + ~CXFA_FFPageView() override; + + CXFA_FFDocView* GetDocView() const; + CFX_RectF GetPageViewRect() const; + CFX_Matrix GetDisplayMatrix(const CFX_Rect& rtDisp, int32_t iRotate) const; + std::unique_ptr<IXFA_WidgetIterator> CreateWidgetIterator( + uint32_t dwTraverseWay, + uint32_t dwWidgetFilter); + + protected: + UnownedPtr<CXFA_FFDocView> const m_pDocView; +}; + +using CXFA_LayoutItemIterator = + CXFA_NodeIteratorTemplate<CXFA_LayoutItem, + CXFA_TraverseStrategy_LayoutItem>; + +class CXFA_FFPageWidgetIterator : public IXFA_WidgetIterator { + public: + CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView, uint32_t dwFilter); + ~CXFA_FFPageWidgetIterator() override; + + void Reset() override; + CXFA_FFWidget* MoveToFirst() override; + CXFA_FFWidget* MoveToLast() override; + CXFA_FFWidget* MoveToNext() override; + CXFA_FFWidget* MoveToPrevious() override; + CXFA_FFWidget* GetCurrentWidget() override; + bool SetCurrentWidget(CXFA_FFWidget* hWidget) override; + + protected: + CXFA_FFWidget* GetWidget(CXFA_LayoutItem* pLayoutItem); + + CXFA_FFPageView* m_pPageView; + CXFA_FFWidget* m_hCurWidget; + uint32_t m_dwFilter; + bool m_bIgnorerelevant; + CXFA_LayoutItemIterator m_sIterator; +}; + +class CXFA_TabParam { + public: + explicit CXFA_TabParam(CXFA_FFWidget* pWidget); + ~CXFA_TabParam(); + + void AppendTabParam(CXFA_TabParam* pParam); + void ClearChildren(); + CXFA_FFWidget* GetWidget() const { return m_pWidget.Get(); } + const std::vector<CXFA_FFWidget*>& GetChildren() const { return m_Children; } + + private: + UnownedPtr<CXFA_FFWidget> const m_pWidget; + std::vector<CXFA_FFWidget*> m_Children; +}; + +class CXFA_FFTabOrderPageWidgetIterator : public IXFA_WidgetIterator { + public: + CXFA_FFTabOrderPageWidgetIterator(CXFA_FFPageView* pPageView, + uint32_t dwFilter); + ~CXFA_FFTabOrderPageWidgetIterator() override; + + void Reset() override; + CXFA_FFWidget* MoveToFirst() override; + CXFA_FFWidget* MoveToLast() override; + CXFA_FFWidget* MoveToNext() override; + CXFA_FFWidget* MoveToPrevious() override; + CXFA_FFWidget* GetCurrentWidget() override; + bool SetCurrentWidget(CXFA_FFWidget* hWidget) override; + + protected: + CXFA_FFWidget* GetTraverseWidget(CXFA_FFWidget* pWidget); + CXFA_FFWidget* FindWidgetByName(const WideString& wsWidgetName, + CXFA_FFWidget* pRefWidget); + void CreateTabOrderWidgetArray(); + void CreateSpaceOrderWidgetArray(std::vector<CXFA_FFWidget*>* WidgetArray); + CXFA_FFWidget* GetWidget(CXFA_LayoutItem* pLayoutItem); + void OrderContainer(CXFA_LayoutItemIterator* sIterator, + CXFA_LayoutItem* pContainerItem, + CXFA_TabParam* pContainer, + bool& bCurrentItem, + bool& bContentArea, + bool bMarsterPage = false); + + std::vector<CXFA_FFWidget*> m_TabOrderWidgetArray; + CXFA_FFPageView* m_pPageView; + uint32_t m_dwFilter; + int32_t m_iCurWidget; + bool m_bIgnorerelevant; +}; + +#endif // XFA_FXFA_CXFA_FFPAGEVIEW_H_ diff --git a/xfa/fxfa/cxfa_ffpasswordedit.cpp b/xfa/fxfa/cxfa_ffpasswordedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15bd5faaae3bd68284fbbae5ac300fb9609593ef --- /dev/null +++ b/xfa/fxfa/cxfa_ffpasswordedit.cpp @@ -0,0 +1,62 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffpasswordedit.h" + +#include <utility> + +#include "xfa/fwl/cfwl_edit.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +CXFA_FFPasswordEdit::CXFA_FFPasswordEdit(CXFA_Node* pNode) + : CXFA_FFTextEdit(pNode) {} + +CXFA_FFPasswordEdit::~CXFA_FFPasswordEdit() {} + +bool CXFA_FFPasswordEdit::LoadWidget() { + auto pNewEdit = pdfium::MakeUnique<CFWL_Edit>( + GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); + CFWL_Edit* pWidget = pNewEdit.get(); + m_pNormalWidget = std::move(pNewEdit); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + + pWidget->SetText(m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Display)); + UpdateWidgetProperty(); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFPasswordEdit::UpdateWidgetProperty() { + CFWL_Edit* pWidget = static_cast<CFWL_Edit*>(m_pNormalWidget.get()); + if (!pWidget) + return; + + uint32_t dwExtendedStyle = FWL_STYLEEXT_EDT_ShowScrollbarFocus | + FWL_STYLEEXT_EDT_OuterScrollbar | + FWL_STYLEEXT_EDT_Password; + dwExtendedStyle |= UpdateUIProperty(); + + WideString password = m_pNode->GetWidgetAcc()->GetPasswordChar(); + if (!password.IsEmpty()) + pWidget->SetAliasChar(password[0]); + if (!m_pNode->GetWidgetAcc()->IsHorizontalScrollPolicyOff()) + dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll; + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) + dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly; + + dwExtendedStyle |= GetAlignment(); + m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); +} diff --git a/xfa/fxfa/cxfa_ffpasswordedit.h b/xfa/fxfa/cxfa_ffpasswordedit.h new file mode 100644 index 0000000000000000000000000000000000000000..da7279ab95d1d606f8d0480d21c074ac987a43cc --- /dev/null +++ b/xfa/fxfa/cxfa_ffpasswordedit.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFPASSWORDEDIT_H_ +#define XFA_FXFA_CXFA_FFPASSWORDEDIT_H_ + +#include "xfa/fxfa/cxfa_fftextedit.h" + +class CXFA_WidgetAcc; + +class CXFA_FFPasswordEdit : public CXFA_FFTextEdit { + public: + explicit CXFA_FFPasswordEdit(CXFA_Node* pNode); + ~CXFA_FFPasswordEdit() override; + + // CXFA_FFTextEdit + bool LoadWidget() override; + void UpdateWidgetProperty() override; +}; + +#endif // XFA_FXFA_CXFA_FFPASSWORDEDIT_H_ diff --git a/xfa/fxfa/cxfa_ffpushbutton.cpp b/xfa/fxfa/cxfa_ffpushbutton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fdf7512d087fe0de6b96104f66d485a688ff99bd --- /dev/null +++ b/xfa/fxfa/cxfa_ffpushbutton.cpp @@ -0,0 +1,245 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffpushbutton.h" + +#include <utility> + +#include "third_party/base/ptr_util.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fwl/cfwl_pushbutton.h" +#include "xfa/fwl/cfwl_widgetmgr.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_textlayout.h" +#include "xfa/fxfa/cxfa_textprovider.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" + +CXFA_FFPushButton::CXFA_FFPushButton(CXFA_Node* pNode) + : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {} + +CXFA_FFPushButton::~CXFA_FFPushButton() { + CXFA_FFPushButton::UnloadWidget(); +} + +void CXFA_FFPushButton::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + RenderHighlightCaption(pGS, &mtRotate); + + CFX_RectF rtWidget = GetRectWithoutRotate(); + CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top); + mt.Concat(mtRotate); + GetApp()->GetFWLWidgetMgr()->OnDrawWidget(m_pNormalWidget.get(), pGS, mt); +} + +bool CXFA_FFPushButton::LoadWidget() { + ASSERT(!m_pNormalWidget); + auto pNew = pdfium::MakeUnique<CFWL_PushButton>(GetFWLApp()); + CFWL_PushButton* pPushButton = pNew.get(); + m_pOldDelegate = pPushButton->GetDelegate(); + pPushButton->SetDelegate(this); + m_pNormalWidget = std::move(pNew); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pNormalWidget->LockUpdate(); + UpdateWidgetProperty(); + LoadHighlightCaption(); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFPushButton::UpdateWidgetProperty() { + uint32_t dwStyleEx = 0; + switch (m_pNode->GetWidgetAcc()->GetButtonHighlight()) { + case XFA_AttributeEnum::Inverted: + dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteInverted; + break; + case XFA_AttributeEnum::Outline: + dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteOutLine; + break; + case XFA_AttributeEnum::Push: + dwStyleEx = XFA_FWL_PSBSTYLEEXT_HilitePush; + break; + default: + break; + } + m_pNormalWidget->ModifyStylesEx(dwStyleEx, 0xFFFFFFFF); +} + +void CXFA_FFPushButton::UnloadWidget() { + m_pRolloverTextLayout.reset(); + m_pDownTextLayout.reset(); + m_pRollProvider.reset(); + m_pDownProvider.reset(); + CXFA_FFField::UnloadWidget(); +} + +bool CXFA_FFPushButton::PerformLayout() { + CXFA_FFWidget::PerformLayout(); + CFX_RectF rtWidget = GetRectWithoutRotate(); + + m_rtUI = rtWidget; + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + XFA_RectWithoutMargin(rtWidget, margin); + + m_rtCaption = rtWidget; + + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + CXFA_Margin* captionMargin = caption ? caption->GetMarginIfExists() : nullptr; + if (captionMargin) + XFA_RectWithoutMargin(m_rtCaption, captionMargin); + + LayoutHighlightCaption(); + SetFWLRect(); + if (m_pNormalWidget) + m_pNormalWidget->Update(); + + return true; +} + +float CXFA_FFPushButton::GetLineWidth() { + CXFA_Border* border = m_pNode->GetBorderIfExists(); + if (border && border->GetPresence() == XFA_AttributeEnum::Visible) { + CXFA_Edge* edge = border->GetEdgeIfExists(0); + return edge ? edge->GetThickness() : 0; + } + return 0; +} + +FX_ARGB CXFA_FFPushButton::GetLineColor() { + return 0xFF000000; +} + +FX_ARGB CXFA_FFPushButton::GetFillColor() { + return 0xFFFFFFFF; +} + +void CXFA_FFPushButton::LoadHighlightCaption() { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (!caption || caption->IsHidden()) + return; + + if (m_pNode->GetWidgetAcc()->HasButtonRollover()) { + if (!m_pRollProvider) { + m_pRollProvider = pdfium::MakeUnique<CXFA_TextProvider>( + m_pNode->GetWidgetAcc(), XFA_TEXTPROVIDERTYPE_Rollover); + } + m_pRolloverTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(GetDoc(), m_pRollProvider.get()); + } + + if (m_pNode->GetWidgetAcc()->HasButtonDown()) { + if (!m_pDownProvider) { + m_pDownProvider = pdfium::MakeUnique<CXFA_TextProvider>( + m_pNode->GetWidgetAcc(), XFA_TEXTPROVIDERTYPE_Down); + } + m_pDownTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(GetDoc(), m_pDownProvider.get()); + } +} + +void CXFA_FFPushButton::LayoutHighlightCaption() { + CFX_SizeF sz(m_rtCaption.width, m_rtCaption.height); + LayoutCaption(); + if (m_pRolloverTextLayout) + m_pRolloverTextLayout->Layout(sz); + if (m_pDownTextLayout) + m_pDownTextLayout->Layout(sz); +} + +void CXFA_FFPushButton::RenderHighlightCaption(CXFA_Graphics* pGS, + CFX_Matrix* pMatrix) { + CXFA_TextLayout* pCapTextLayout = + m_pNode->GetWidgetAcc()->GetCaptionTextLayout(); + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (!caption || !caption->IsVisible()) + return; + + CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); + CFX_RectF rtClip = m_rtCaption; + rtClip.Intersect(GetRectWithoutRotate()); + CFX_Matrix mt(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top); + if (pMatrix) { + rtClip = pMatrix->TransformRect(rtClip); + mt.Concat(*pMatrix); + } + + uint32_t dwState = m_pNormalWidget->GetStates(); + if (m_pDownTextLayout && (dwState & FWL_STATE_PSB_Pressed) && + (dwState & FWL_STATE_PSB_Hovered)) { + if (m_pDownTextLayout->DrawString(pRenderDevice, mt, rtClip, 0)) + return; + } else if (m_pRolloverTextLayout && (dwState & FWL_STATE_PSB_Hovered)) { + if (m_pRolloverTextLayout->DrawString(pRenderDevice, mt, rtClip, 0)) + return; + } + + if (pCapTextLayout) + pCapTextLayout->DrawString(pRenderDevice, mt, rtClip, 0); +} + +void CXFA_FFPushButton::OnProcessMessage(CFWL_Message* pMessage) { + m_pOldDelegate->OnProcessMessage(pMessage); +} + +void CXFA_FFPushButton::OnProcessEvent(CFWL_Event* pEvent) { + m_pOldDelegate->OnProcessEvent(pEvent); + CXFA_FFField::OnProcessEvent(pEvent); +} + +void CXFA_FFPushButton::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + if (m_pNormalWidget->GetStylesEx() & XFA_FWL_PSBSTYLEEXT_HiliteInverted) { + if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) && + (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) { + CFX_RectF rtFill(0, 0, m_pNormalWidget->GetWidgetRect().Size()); + float fLineWith = GetLineWidth(); + rtFill.Deflate(fLineWith, fLineWith); + CXFA_GEPath path; + path.AddRectangle(rtFill.left, rtFill.top, rtFill.width, rtFill.height); + pGraphics->SetFillColor(CXFA_GEColor(FXARGB_MAKE(128, 128, 255, 255))); + pGraphics->FillPath(&path, FXFILL_WINDING, &matrix); + } + return; + } + + if (m_pNormalWidget->GetStylesEx() & XFA_FWL_PSBSTYLEEXT_HiliteOutLine) { + if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) && + (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) { + float fLineWidth = GetLineWidth(); + pGraphics->SetStrokeColor(CXFA_GEColor(FXARGB_MAKE(255, 128, 255, 255))); + pGraphics->SetLineWidth(fLineWidth); + + CXFA_GEPath path; + CFX_RectF rect = m_pNormalWidget->GetWidgetRect(); + path.AddRectangle(0, 0, rect.width, rect.height); + pGraphics->StrokePath(&path, &matrix); + } + } +} + +FormFieldType CXFA_FFPushButton::GetFormFieldType() { + return FormFieldType::kXFA_PushButton; +} diff --git a/xfa/fxfa/cxfa_ffpushbutton.h b/xfa/fxfa/cxfa_ffpushbutton.h new file mode 100644 index 0000000000000000000000000000000000000000..9b2a0ee4ccc95c6c25232c02f594a4f2536d20eb --- /dev/null +++ b/xfa/fxfa/cxfa_ffpushbutton.h @@ -0,0 +1,54 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFPUSHBUTTON_H_ +#define XFA_FXFA_CXFA_FFPUSHBUTTON_H_ + +#include <memory> + +#include "xfa/fxfa/cxfa_fffield.h" + +#define XFA_FWL_PSBSTYLEEXT_HiliteInverted (1L << 0) +#define XFA_FWL_PSBSTYLEEXT_HilitePush (1L << 1) +#define XFA_FWL_PSBSTYLEEXT_HiliteOutLine (1L << 2) + +class CXFA_TextProvider; + +class CXFA_FFPushButton : public CXFA_FFField { + public: + explicit CXFA_FFPushButton(CXFA_Node* pNode); + ~CXFA_FFPushButton() override; + + // CXFA_FFField + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + bool LoadWidget() override; + void UnloadWidget() override; + bool PerformLayout() override; + void UpdateWidgetProperty() override; + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + FormFieldType GetFormFieldType() override; + + private: + void LoadHighlightCaption(); + void LayoutHighlightCaption(); + void RenderHighlightCaption(CXFA_Graphics* pGS, CFX_Matrix* pMatrix); + float GetLineWidth(); + FX_ARGB GetLineColor(); + FX_ARGB GetFillColor(); + + std::unique_ptr<CXFA_TextLayout> m_pRolloverTextLayout; + std::unique_ptr<CXFA_TextLayout> m_pDownTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pRollProvider; + std::unique_ptr<CXFA_TextProvider> m_pDownProvider; + IFWL_WidgetDelegate* m_pOldDelegate; +}; + +#endif // XFA_FXFA_CXFA_FFPUSHBUTTON_H_ diff --git a/xfa/fxfa/cxfa_ffrectangle.cpp b/xfa/fxfa/cxfa_ffrectangle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46c1009844a5c96ed09b6c0bc610c4b76443c9d5 --- /dev/null +++ b/xfa/fxfa/cxfa_ffrectangle.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffrectangle.h" + +#include "xfa/fxfa/parser/cxfa_rectangle.h" +#include "xfa/fxfa/parser/cxfa_value.h" + +CXFA_FFRectangle::CXFA_FFRectangle(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {} + +CXFA_FFRectangle::~CXFA_FFRectangle() {} + +void CXFA_FFRectangle::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CXFA_Value* value = m_pNode->GetFormValueIfExists(); + if (!value) + return; + + CFX_RectF rect = GetRectWithoutRotate(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + XFA_RectWithoutMargin(rect, margin); + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + DrawBorder(pGS, value->GetRectangleIfExists(), rect, mtRotate); +} diff --git a/xfa/fxfa/cxfa_ffrectangle.h b/xfa/fxfa/cxfa_ffrectangle.h new file mode 100644 index 0000000000000000000000000000000000000000..304c5c69a9c98934911681d202caee28fa0df639 --- /dev/null +++ b/xfa/fxfa/cxfa_ffrectangle.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFRECTANGLE_H_ +#define XFA_FXFA_CXFA_FFRECTANGLE_H_ + +#include "xfa/fxfa/cxfa_ffdraw.h" + +class CXFA_FFRectangle : public CXFA_FFDraw { + public: + explicit CXFA_FFRectangle(CXFA_Node* pNode); + ~CXFA_FFRectangle() override; + + // CXFA_FFWidget + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; +}; + +#endif // XFA_FXFA_CXFA_FFRECTANGLE_H_ diff --git a/xfa/fxfa/cxfa_ffsignature.cpp b/xfa/fxfa/cxfa_ffsignature.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e56b38ad173cd109cd0f4527b727dd96a1f683d --- /dev/null +++ b/xfa/fxfa/cxfa_ffsignature.cpp @@ -0,0 +1,116 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffsignature.h" + +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_border.h" + +CXFA_FFSignature::CXFA_FFSignature(CXFA_Node* pNode) : CXFA_FFField(pNode) {} + +CXFA_FFSignature::~CXFA_FFSignature() {} + +bool CXFA_FFSignature::LoadWidget() { + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFSignature::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + + DrawBorder(pGS, m_pNode->GetWidgetAcc()->GetUIBorder(), m_rtUI, mtRotate); + RenderCaption(pGS, &mtRotate); + DrawHighlight(pGS, &mtRotate, dwStatus, false); +} + +bool CXFA_FFSignature::OnMouseEnter() { + return false; +} + +bool CXFA_FFSignature::OnMouseExit() { + return false; +} + +bool CXFA_FFSignature::OnLButtonDown(uint32_t dwFlags, + const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnLButtonDblClk(uint32_t dwFlags, + const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnMouseWheel(uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnRButtonDown(uint32_t dwFlags, + const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnRButtonDblClk(uint32_t dwFlags, + const CFX_PointF& point) { + return false; +} + +bool CXFA_FFSignature::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { + return false; +} + +bool CXFA_FFSignature::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { + return false; +} + +bool CXFA_FFSignature::OnChar(uint32_t dwChar, uint32_t dwFlags) { + return false; +} + +FWL_WidgetHit CXFA_FFSignature::OnHitTest(const CFX_PointF& point) { + if (m_pNormalWidget && + m_pNormalWidget->HitTest(FWLToClient(point)) != FWL_WidgetHit::Unknown) { + return FWL_WidgetHit::Client; + } + + if (!GetRectWithoutRotate().Contains(point)) + return FWL_WidgetHit::Unknown; + if (m_rtCaption.Contains(point)) + return FWL_WidgetHit::Titlebar; + return FWL_WidgetHit::Client; +} + +bool CXFA_FFSignature::OnSetCursor(const CFX_PointF& point) { + return false; +} + +FormFieldType CXFA_FFSignature::GetFormFieldType() { + return FormFieldType::kXFA_Signature; +} diff --git a/xfa/fxfa/cxfa_ffsignature.h b/xfa/fxfa/cxfa_ffsignature.h new file mode 100644 index 0000000000000000000000000000000000000000..bd09576af4d521e0205690f60d466729fc3f7fca --- /dev/null +++ b/xfa/fxfa/cxfa_ffsignature.h @@ -0,0 +1,43 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFSIGNATURE_H_ +#define XFA_FXFA_CXFA_FFSIGNATURE_H_ + +#include "xfa/fxfa/cxfa_fffield.h" + +class CXFA_FFSignature final : public CXFA_FFField { + public: + explicit CXFA_FFSignature(CXFA_Node* pNode); + ~CXFA_FFSignature() override; + + // CXFA_FFField + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + bool LoadWidget() override; + bool OnMouseEnter() override; + bool OnMouseExit() override; + bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnMouseWheel(uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& pointy) override; + bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) override; + + bool OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) override; + bool OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) override; + bool OnChar(uint32_t dwChar, uint32_t dwFlags) override; + FWL_WidgetHit OnHitTest(const CFX_PointF& point) override; + bool OnSetCursor(const CFX_PointF& point) override; + FormFieldType GetFormFieldType() override; +}; + +#endif // XFA_FXFA_CXFA_FFSIGNATURE_H_ diff --git a/xfa/fxfa/cxfa_ffsubform.cpp b/xfa/fxfa/cxfa_ffsubform.cpp new file mode 100644 index 0000000000000000000000000000000000000000..97a075026d6074a188bf4545a3af765243fdb8bc --- /dev/null +++ b/xfa/fxfa/cxfa_ffsubform.cpp @@ -0,0 +1,16 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffsubform.h" + +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +CXFA_FFSubForm::CXFA_FFSubForm(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {} + +CXFA_FFSubForm::~CXFA_FFSubForm() {} diff --git a/xfa/fxfa/cxfa_ffsubform.h b/xfa/fxfa/cxfa_ffsubform.h new file mode 100644 index 0000000000000000000000000000000000000000..a69b5715668270253a96c475e5b936f8b3d3ef6d --- /dev/null +++ b/xfa/fxfa/cxfa_ffsubform.h @@ -0,0 +1,19 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFSUBFORM_H_ +#define XFA_FXFA_CXFA_FFSUBFORM_H_ + +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +class CXFA_FFSubForm : public CXFA_FFWidget { + public: + explicit CXFA_FFSubForm(CXFA_Node* pNode); + ~CXFA_FFSubForm() override; +}; + +#endif // XFA_FXFA_CXFA_FFSUBFORM_H_ diff --git a/xfa/fxfa/cxfa_fftext.cpp b/xfa/fxfa/cxfa_fftext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ae3cb6f5c00e3d01fff5638fc49d63c11b3c77e --- /dev/null +++ b/xfa/fxfa/cxfa_fftext.cpp @@ -0,0 +1,156 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fftext.h" + +#include "xfa/fwl/fwl_widgetdef.h" +#include "xfa/fwl/fwl_widgethit.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdraw.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_linkuserdata.h" +#include "xfa/fxfa/cxfa_pieceline.h" +#include "xfa/fxfa/cxfa_textlayout.h" +#include "xfa/fxfa/cxfa_textpiece.h" +#include "xfa/fxfa/parser/cxfa_margin.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {} + +CXFA_FFText::~CXFA_FFText() {} + +void CXFA_FFText::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CFX_Matrix mtRotate = GetRotateMatrix(); + mtRotate.Concat(matrix); + + CXFA_FFWidget::RenderWidget(pGS, mtRotate, dwStatus); + + CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout(); + if (!pTextLayout) + return; + + CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); + CFX_RectF rtText = GetRectWithoutRotate(); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + CXFA_LayoutItem* pItem = this; + if (!pItem->GetPrev() && !pItem->GetNext()) { + XFA_RectWithoutMargin(rtText, margin); + } else { + float fTopInset = 0; + float fBottomInset = 0; + if (!pItem->GetPrev()) + fTopInset = margin->GetTopInset(); + else if (!pItem->GetNext()) + fBottomInset = margin->GetBottomInset(); + + rtText.Deflate(margin->GetLeftInset(), fTopInset, margin->GetRightInset(), + fBottomInset); + } + } + + CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top); + CFX_RectF rtClip = mtRotate.TransformRect(rtText); + mt.Concat(mtRotate); + pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex()); +} + +bool CXFA_FFText::IsLoaded() { + CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout(); + return pTextLayout && !pTextLayout->m_bHasBlock; +} + +bool CXFA_FFText::PerformLayout() { + CXFA_FFDraw::PerformLayout(); + CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout(); + if (!pTextLayout) + return false; + if (!pTextLayout->m_bHasBlock) + return true; + + pTextLayout->m_Blocks.clear(); + CXFA_LayoutItem* pItem = this; + if (!pItem->GetPrev() && !pItem->GetNext()) + return true; + + pItem = pItem->GetFirst(); + while (pItem) { + CFX_RectF rtText = pItem->GetRect(false); + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + if (!pItem->GetPrev()) + rtText.height -= margin->GetTopInset(); + else if (!pItem->GetNext()) + rtText.height -= margin->GetBottomInset(); + } + pTextLayout->ItemBlocks(rtText, pItem->GetIndex()); + pItem = pItem->GetNext(); + } + pTextLayout->m_bHasBlock = false; + return true; +} + +bool CXFA_FFText::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + if (!GetRectWithoutRotate().Contains(point)) + return false; + + const wchar_t* wsURLContent = GetLinkURLAtPoint(point); + if (!wsURLContent) + return false; + + SetButtonDown(true); + return true; +} + +bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { + return GetRectWithoutRotate().Contains(point) && !!GetLinkURLAtPoint(point); +} + +bool CXFA_FFText::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + if (!IsButtonDown()) + return false; + + SetButtonDown(false); + const wchar_t* wsURLContent = GetLinkURLAtPoint(point); + if (!wsURLContent) + return false; + + CXFA_FFDoc* pDoc = GetDoc(); + pDoc->GetDocEnvironment()->GotoURL(pDoc, wsURLContent); + return true; +} + +FWL_WidgetHit CXFA_FFText::OnHitTest(const CFX_PointF& point) { + if (!GetRectWithoutRotate().Contains(point)) + return FWL_WidgetHit::Unknown; + if (!GetLinkURLAtPoint(point)) + return FWL_WidgetHit::Unknown; + return FWL_WidgetHit::HyperLink; +} + +const wchar_t* CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) { + CXFA_TextLayout* pTextLayout = m_pNode->GetWidgetAcc()->GetTextLayout(); + if (!pTextLayout) + return nullptr; + + CFX_RectF rect = GetRectWithoutRotate(); + for (const auto& pPieceLine : *pTextLayout->GetPieceLines()) { + for (const auto& pPiece : pPieceLine->m_textPieces) { + if (pPiece->pLinkData && + pPiece->rtPiece.Contains(point - rect.TopLeft())) { + return pPiece->pLinkData->GetLinkURL(); + } + } + } + return nullptr; +} diff --git a/xfa/fxfa/cxfa_fftext.h b/xfa/fxfa/cxfa_fftext.h new file mode 100644 index 0000000000000000000000000000000000000000..8c32183d6cdbb931282fe54c72383db229935f5b --- /dev/null +++ b/xfa/fxfa/cxfa_fftext.h @@ -0,0 +1,32 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFTEXT_H_ +#define XFA_FXFA_CXFA_FFTEXT_H_ + +#include "xfa/fxfa/cxfa_ffdraw.h" + +class CXFA_FFText : public CXFA_FFDraw { + public: + explicit CXFA_FFText(CXFA_Node* pNode); + ~CXFA_FFText() override; + + // CXFA_FFWidget + bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) override; + FWL_WidgetHit OnHitTest(const CFX_PointF& point) override; + void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) override; + bool IsLoaded() override; + bool PerformLayout() override; + + private: + const wchar_t* GetLinkURLAtPoint(const CFX_PointF& point); +}; + +#endif // XFA_FXFA_CXFA_FFTEXT_H_ diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fad9a9b37a8e45c785c7f1ababea649418f8f9f5 --- /dev/null +++ b/xfa/fxfa/cxfa_fftextedit.cpp @@ -0,0 +1,429 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fftextedit.h" + +#include <utility> + +#include "xfa/fwl/cfwl_datetimepicker.h" +#include "xfa/fwl/cfwl_edit.h" +#include "xfa/fwl/cfwl_eventcheckword.h" +#include "xfa/fwl/cfwl_eventtarget.h" +#include "xfa/fwl/cfwl_eventtextchanged.h" +#include "xfa/fwl/cfwl_messagekillfocus.h" +#include "xfa/fwl/cfwl_messagesetfocus.h" +#include "xfa/fwl/cfwl_notedriver.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_para.h" + +namespace { + +CFWL_Edit* ToEdit(CFWL_Widget* widget) { + return static_cast<CFWL_Edit*>(widget); +} + +} // namespace + +CXFA_FFTextEdit::CXFA_FFTextEdit(CXFA_Node* pNode) + : CXFA_FFField(pNode), m_pOldDelegate(nullptr) {} + +CXFA_FFTextEdit::~CXFA_FFTextEdit() { + if (m_pNormalWidget) { + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->UnregisterEventTarget(m_pNormalWidget.get()); + } +} + +bool CXFA_FFTextEdit::LoadWidget() { + auto pNewWidget = pdfium::MakeUnique<CFWL_Edit>( + GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr); + CFWL_Edit* pFWLEdit = pNewWidget.get(); + m_pNormalWidget = std::move(pNewWidget); + m_pNormalWidget->SetLayoutItem(this); + + CFWL_NoteDriver* pNoteDriver = + m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); + pNoteDriver->RegisterEventTarget(m_pNormalWidget.get(), + m_pNormalWidget.get()); + m_pOldDelegate = m_pNormalWidget->GetDelegate(); + m_pNormalWidget->SetDelegate(this); + m_pNormalWidget->LockUpdate(); + UpdateWidgetProperty(); + + pFWLEdit->SetText( + m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Display)); + m_pNormalWidget->UnlockUpdate(); + return CXFA_FFField::LoadWidget(); +} + +void CXFA_FFTextEdit::UpdateWidgetProperty() { + CFWL_Edit* pWidget = static_cast<CFWL_Edit*>(m_pNormalWidget.get()); + if (!pWidget) + return; + + uint32_t dwStyle = 0; + uint32_t dwExtendedStyle = + FWL_STYLEEXT_EDT_ShowScrollbarFocus | FWL_STYLEEXT_EDT_OuterScrollbar; + dwExtendedStyle |= UpdateUIProperty(); + if (m_pNode->GetWidgetAcc()->IsMultiLine()) { + dwExtendedStyle |= FWL_STYLEEXT_EDT_MultiLine | FWL_STYLEEXT_EDT_WantReturn; + if (!m_pNode->GetWidgetAcc()->IsVerticalScrollPolicyOff()) { + dwStyle |= FWL_WGTSTYLE_VScroll; + dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoVScroll; + } + } else if (!m_pNode->GetWidgetAcc()->IsHorizontalScrollPolicyOff()) { + dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll; + } + if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) { + dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly; + dwExtendedStyle |= FWL_STYLEEXT_EDT_MultiLine; + } + + XFA_Element eType; + int32_t iMaxChars; + std::tie(eType, iMaxChars) = m_pNode->GetWidgetAcc()->GetMaxChars(); + if (eType == XFA_Element::ExData) + iMaxChars = 0; + + Optional<int32_t> numCells = m_pNode->GetWidgetAcc()->GetNumberOfCells(); + if (!numCells) { + pWidget->SetLimit(iMaxChars); + } else if (*numCells == 0) { + dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText; + pWidget->SetLimit(iMaxChars > 0 ? iMaxChars : 1); + } else { + dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText; + pWidget->SetLimit(*numCells); + } + + dwExtendedStyle |= GetAlignment(); + m_pNormalWidget->ModifyStyles(dwStyle, 0xFFFFFFFF); + m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF); +} + +bool CXFA_FFTextEdit::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + if (!PtInActiveRect(point)) + return false; + if (!IsFocused()) { + m_dwStatus |= XFA_WidgetStatus_Focused; + UpdateFWLData(); + AddInvalidateRect(); + } + + SetButtonDown(true); + CFWL_MessageMouse ms(nullptr, m_pNormalWidget.get()); + ms.m_dwCmd = FWL_MouseCommand::LeftButtonDown; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFTextEdit::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + if (!m_pNode->IsOpenAccess()) + return false; + if (!PtInActiveRect(point)) + return false; + if (!IsFocused()) { + m_dwStatus |= XFA_WidgetStatus_Focused; + UpdateFWLData(); + AddInvalidateRect(); + } + + SetButtonDown(true); + CFWL_MessageMouse ms(nullptr, nullptr); + ms.m_dwCmd = FWL_MouseCommand::RightButtonDown; + ms.m_dwFlags = dwFlags; + ms.m_pos = FWLToClient(point); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFTextEdit::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + if (!CXFA_FFField::OnRButtonUp(dwFlags, point)) + return false; + + GetDoc()->GetDocEnvironment()->PopupMenu(this, point); + return true; +} + +bool CXFA_FFTextEdit::OnSetFocus(CXFA_FFWidget* pOldWidget) { + m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged; + if (!IsFocused()) { + m_dwStatus |= XFA_WidgetStatus_Focused; + UpdateFWLData(); + AddInvalidateRect(); + } + CXFA_FFWidget::OnSetFocus(pOldWidget); + CFWL_MessageSetFocus ms(nullptr, m_pNormalWidget.get()); + TranslateFWLMessage(&ms); + return true; +} + +bool CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) { + CFWL_MessageKillFocus ms(nullptr, m_pNormalWidget.get()); + TranslateFWLMessage(&ms); + m_dwStatus &= ~XFA_WidgetStatus_Focused; + + SetEditScrollOffset(); + ProcessCommittedData(); + UpdateFWLData(); + AddInvalidateRect(); + CXFA_FFWidget::OnKillFocus(pNewWidget); + + m_dwStatus &= ~XFA_WidgetStatus_TextEditValueChanged; + return true; +} + +bool CXFA_FFTextEdit::CommitData() { + WideString wsText = static_cast<CFWL_Edit*>(m_pNormalWidget.get())->GetText(); + if (m_pNode->GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Edit, wsText)) { + m_pNode->GetWidgetAcc()->UpdateUIDisplay(GetDoc()->GetDocView(), this); + return true; + } + ValidateNumberField(wsText); + return false; +} + +void CXFA_FFTextEdit::ValidateNumberField(const WideString& wsText) { + CXFA_WidgetAcc* pAcc = GetNode()->GetWidgetAcc(); + if (!pAcc || pAcc->GetUIType() != XFA_Element::NumericEdit) + return; + + IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider(); + if (!pAppProvider) + return; + + WideString wsSomField = pAcc->GetNode()->GetSOMExpression(); + pAppProvider->MsgBox(WideString::Format(L"%ls can not contain %ls", + wsText.c_str(), wsSomField.c_str()), + pAppProvider->GetAppTitle(), XFA_MBICON_Error, + XFA_MB_OK); +} + +bool CXFA_FFTextEdit::IsDataChanged() { + return (m_dwStatus & XFA_WidgetStatus_TextEditValueChanged) != 0; +} + +uint32_t CXFA_FFTextEdit::GetAlignment() { + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (!para) + return 0; + + uint32_t dwExtendedStyle = 0; + switch (para->GetHorizontalAlign()) { + case XFA_AttributeEnum::Center: + dwExtendedStyle |= FWL_STYLEEXT_EDT_HCenter; + break; + case XFA_AttributeEnum::Justify: + dwExtendedStyle |= FWL_STYLEEXT_EDT_Justified; + break; + case XFA_AttributeEnum::JustifyAll: + case XFA_AttributeEnum::Radix: + break; + case XFA_AttributeEnum::Right: + dwExtendedStyle |= FWL_STYLEEXT_EDT_HFar; + break; + default: + dwExtendedStyle |= FWL_STYLEEXT_EDT_HNear; + break; + } + + switch (para->GetVerticalAlign()) { + case XFA_AttributeEnum::Middle: + dwExtendedStyle |= FWL_STYLEEXT_EDT_VCenter; + break; + case XFA_AttributeEnum::Bottom: + dwExtendedStyle |= FWL_STYLEEXT_EDT_VFar; + break; + default: + dwExtendedStyle |= FWL_STYLEEXT_EDT_VNear; + break; + } + return dwExtendedStyle; +} + +bool CXFA_FFTextEdit::UpdateFWLData() { + if (!m_pNormalWidget) + return false; + + CFWL_Edit* pEdit = static_cast<CFWL_Edit*>(m_pNormalWidget.get()); + XFA_VALUEPICTURE eType = XFA_VALUEPICTURE_Display; + if (IsFocused()) + eType = XFA_VALUEPICTURE_Edit; + + bool bUpdate = false; + if (m_pNode->GetWidgetAcc()->GetUIType() == XFA_Element::TextEdit && + !m_pNode->GetWidgetAcc()->GetNumberOfCells()) { + XFA_Element elementType; + int32_t iMaxChars; + std::tie(elementType, iMaxChars) = m_pNode->GetWidgetAcc()->GetMaxChars(); + if (elementType == XFA_Element::ExData) + iMaxChars = eType == XFA_VALUEPICTURE_Edit ? iMaxChars : 0; + if (pEdit->GetLimit() != iMaxChars) { + pEdit->SetLimit(iMaxChars); + bUpdate = true; + } + } else if (m_pNode->GetWidgetAcc()->GetUIType() == XFA_Element::Barcode) { + int32_t nDataLen = 0; + if (eType == XFA_VALUEPICTURE_Edit) + nDataLen = m_pNode->GetBarcodeAttribute_DataLength().value_or(0); + + pEdit->SetLimit(nDataLen); + bUpdate = true; + } + + WideString wsText = m_pNode->GetWidgetAcc()->GetValue(eType); + WideString wsOldText = pEdit->GetText(); + if (wsText != wsOldText || (eType == XFA_VALUEPICTURE_Edit && bUpdate)) { + pEdit->SetText(wsText); + bUpdate = true; + } + if (bUpdate) + m_pNormalWidget->Update(); + + return true; +} + +void CXFA_FFTextEdit::OnTextChanged(CFWL_Widget* pWidget, + const WideString& wsChanged, + const WideString& wsPrevText) { + m_dwStatus |= XFA_WidgetStatus_TextEditValueChanged; + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Change; + eParam.m_wsChange = wsChanged; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + eParam.m_wsPrevText = wsPrevText; + CFWL_Edit* pEdit = static_cast<CFWL_Edit*>(m_pNormalWidget.get()); + if (m_pNode->GetWidgetAcc()->GetUIType() == XFA_Element::DateTimeEdit) { + CFWL_DateTimePicker* pDateTime = (CFWL_DateTimePicker*)pEdit; + eParam.m_wsNewText = pDateTime->GetEditText(); + if (pDateTime->HasSelection()) { + size_t count; + std::tie(eParam.m_iSelStart, count) = pDateTime->GetSelection(); + eParam.m_iSelEnd = eParam.m_iSelStart + count; + } + } else { + eParam.m_wsNewText = pEdit->GetText(); + if (pEdit->HasSelection()) + std::tie(eParam.m_iSelStart, eParam.m_iSelEnd) = pEdit->GetSelection(); + } + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam); +} + +void CXFA_FFTextEdit::OnTextFull(CFWL_Widget* pWidget) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Full; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Full, &eParam); +} + +bool CXFA_FFTextEdit::CheckWord(const ByteStringView& sWord) { + return sWord.IsEmpty() || + m_pNode->GetWidgetAcc()->GetUIType() != XFA_Element::TextEdit; +} + +void CXFA_FFTextEdit::OnProcessMessage(CFWL_Message* pMessage) { + m_pOldDelegate->OnProcessMessage(pMessage); +} + +void CXFA_FFTextEdit::OnProcessEvent(CFWL_Event* pEvent) { + CXFA_FFField::OnProcessEvent(pEvent); + switch (pEvent->GetType()) { + case CFWL_Event::Type::TextChanged: { + CFWL_EventTextChanged* event = + static_cast<CFWL_EventTextChanged*>(pEvent); + WideString wsChange; + OnTextChanged(m_pNormalWidget.get(), wsChange, event->wsPrevText); + break; + } + case CFWL_Event::Type::TextFull: { + OnTextFull(m_pNormalWidget.get()); + break; + } + case CFWL_Event::Type::CheckWord: { + WideString wstr(L"FWL_EVENT_DTP_SelectChanged"); + CFWL_EventCheckWord* event = static_cast<CFWL_EventCheckWord*>(pEvent); + event->bCheckWord = CheckWord(event->bsWord.AsStringView()); + break; + } + default: + break; + } + m_pOldDelegate->OnProcessEvent(pEvent); +} + +void CXFA_FFTextEdit::OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) { + m_pOldDelegate->OnDrawWidget(pGraphics, matrix); +} + +bool CXFA_FFTextEdit::CanUndo() { + return ToEdit(m_pNormalWidget.get())->CanUndo(); +} + +bool CXFA_FFTextEdit::CanRedo() { + return ToEdit(m_pNormalWidget.get())->CanRedo(); +} + +bool CXFA_FFTextEdit::Undo() { + return ToEdit(m_pNormalWidget.get())->Undo(); +} + +bool CXFA_FFTextEdit::Redo() { + return ToEdit(m_pNormalWidget.get())->Redo(); +} + +bool CXFA_FFTextEdit::CanCopy() { + return ToEdit(m_pNormalWidget.get())->HasSelection(); +} + +bool CXFA_FFTextEdit::CanCut() { + if (ToEdit(m_pNormalWidget.get())->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) + return false; + return ToEdit(m_pNormalWidget.get())->HasSelection(); +} + +bool CXFA_FFTextEdit::CanPaste() { + return !(ToEdit(m_pNormalWidget.get())->GetStylesEx() & + FWL_STYLEEXT_EDT_ReadOnly); +} + +bool CXFA_FFTextEdit::CanSelectAll() { + return ToEdit(m_pNormalWidget.get())->GetTextLength() > 0; +} + +Optional<WideString> CXFA_FFTextEdit::Copy() { + return ToEdit(m_pNormalWidget.get())->Copy(); +} + +Optional<WideString> CXFA_FFTextEdit::Cut() { + return ToEdit(m_pNormalWidget.get())->Cut(); +} + +bool CXFA_FFTextEdit::Paste(const WideString& wsPaste) { + return ToEdit(m_pNormalWidget.get())->Paste(wsPaste); +} + +void CXFA_FFTextEdit::SelectAll() { + ToEdit(m_pNormalWidget.get())->SelectAll(); +} + +void CXFA_FFTextEdit::Delete() { + ToEdit(m_pNormalWidget.get())->ClearText(); +} + +void CXFA_FFTextEdit::DeSelect() { + ToEdit(m_pNormalWidget.get())->ClearSelection(); +} + +FormFieldType CXFA_FFTextEdit::GetFormFieldType() { + return FormFieldType::kXFA_TextField; +} diff --git a/xfa/fxfa/cxfa_fftextedit.h b/xfa/fxfa/cxfa_fftextedit.h new file mode 100644 index 0000000000000000000000000000000000000000..e8edb4691f720f6e5cb1b1b562d6d5cca19b5866 --- /dev/null +++ b/xfa/fxfa/cxfa_fftextedit.h @@ -0,0 +1,74 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFTEXTEDIT_H_ +#define XFA_FXFA_CXFA_FFTEXTEDIT_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "xfa/fxfa/cxfa_fffield.h" + +class CFWL_Event; +class CFWL_Widget; +class CFX_Matrix; +class CXFA_FFWidget; +class CXFA_WidgetAcc; +class IFWL_WidgetDelegate; + +class CXFA_FFTextEdit : public CXFA_FFField { + public: + explicit CXFA_FFTextEdit(CXFA_Node* pNode); + ~CXFA_FFTextEdit() override; + + // CXFA_FFField + bool LoadWidget() override; + void UpdateWidgetProperty() override; + bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) override; + bool OnSetFocus(CXFA_FFWidget* pOldWidget) override; + bool OnKillFocus(CXFA_FFWidget* pNewWidget) override; + void OnProcessMessage(CFWL_Message* pMessage) override; + void OnProcessEvent(CFWL_Event* pEvent) override; + void OnDrawWidget(CXFA_Graphics* pGraphics, + const CFX_Matrix& matrix) override; + + void OnTextChanged(CFWL_Widget* pWidget, + const WideString& wsChanged, + const WideString& wsPrevText); + void OnTextFull(CFWL_Widget* pWidget); + bool CheckWord(const ByteStringView& sWord); + + // CXFA_FFWidget + bool CanUndo() override; + bool CanRedo() override; + bool Undo() override; + bool Redo() override; + bool CanCopy() override; + bool CanCut() override; + bool CanPaste() override; + bool CanSelectAll() override; + Optional<WideString> Copy() override; + Optional<WideString> Cut() override; + bool Paste(const WideString& wsPaste) override; + void SelectAll() override; + void Delete() override; + void DeSelect() override; + FormFieldType GetFormFieldType() override; + + protected: + uint32_t GetAlignment(); + + IFWL_WidgetDelegate* m_pOldDelegate; + + private: + bool CommitData() override; + bool UpdateFWLData() override; + bool IsDataChanged() override; + void ValidateNumberField(const WideString& wsText); +}; + +#endif // XFA_FXFA_CXFA_FFTEXTEDIT_H_ diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71c45c7620c18e245d594c171d053a7f6471ae5e --- /dev/null +++ b/xfa/fxfa/cxfa_ffwidget.cpp @@ -0,0 +1,638 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffwidget.h" + +#include <algorithm> +#include <cmath> +#include <memory> +#include <utility> +#include <vector> + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fxcodec/codec/ccodec_progressivedecoder.h" +#include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/maybe_owned.h" +#include "core/fxge/cfx_pathdata.h" +#include "xfa/fwl/fwl_widgethit.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_imagerenderer.h" +#include "xfa/fxfa/cxfa_widgetacc.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_box.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_margin.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +namespace { + +FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, + int32_t iComponents, + int32_t iBitsPerComponent) { + FXDIB_Format dibFormat = FXDIB_Argb; + switch (type) { + case FXCODEC_IMAGE_BMP: + case FXCODEC_IMAGE_JPG: + case FXCODEC_IMAGE_TIF: { + dibFormat = FXDIB_Rgb32; + int32_t bpp = iComponents * iBitsPerComponent; + if (bpp <= 24) { + dibFormat = FXDIB_Rgb; + } + } break; + case FXCODEC_IMAGE_PNG: + default: + break; + } + return dibFormat; +} + +bool IsFXCodecErrorStatus(FXCODEC_STATUS status) { + return (status == FXCODEC_STATUS_ERROR || +#ifdef PDF_ENABLE_XFA + status == FXCODEC_STATUS_ERR_MEMORY || +#endif // PDF_ENABLE_XFA + status == FXCODEC_STATUS_ERR_READ || + status == FXCODEC_STATUS_ERR_FLUSH || + status == FXCODEC_STATUS_ERR_FORMAT || + status == FXCODEC_STATUS_ERR_PARAMS); +} + +} // namespace + +void XFA_DrawImage(CXFA_Graphics* pGS, + const CFX_RectF& rtImage, + const CFX_Matrix& matrix, + const RetainPtr<CFX_DIBitmap>& pDIBitmap, + XFA_AttributeEnum iAspect, + int32_t iImageXDpi, + int32_t iImageYDpi, + XFA_AttributeEnum iHorzAlign, + XFA_AttributeEnum iVertAlign) { + if (rtImage.IsEmpty()) + return; + if (!pDIBitmap || !pDIBitmap->GetBuffer()) + return; + + CFX_RectF rtFit( + rtImage.TopLeft(), + XFA_UnitPx2Pt((float)pDIBitmap->GetWidth(), (float)iImageXDpi), + XFA_UnitPx2Pt((float)pDIBitmap->GetHeight(), (float)iImageYDpi)); + switch (iAspect) { + case XFA_AttributeEnum::Fit: { + float f1 = rtImage.height / rtFit.height; + float f2 = rtImage.width / rtFit.width; + f1 = std::min(f1, f2); + rtFit.height = rtFit.height * f1; + rtFit.width = rtFit.width * f1; + break; + } + case XFA_AttributeEnum::Height: { + float f1 = rtImage.height / rtFit.height; + rtFit.height = rtImage.height; + rtFit.width = f1 * rtFit.width; + break; + } + case XFA_AttributeEnum::None: + rtFit.height = rtImage.height; + rtFit.width = rtImage.width; + break; + case XFA_AttributeEnum::Width: { + float f1 = rtImage.width / rtFit.width; + rtFit.width = rtImage.width; + rtFit.height = rtFit.height * f1; + break; + } + case XFA_AttributeEnum::Actual: + default: + break; + } + + if (iHorzAlign == XFA_AttributeEnum::Center) + rtFit.left += (rtImage.width - rtFit.width) / 2; + else if (iHorzAlign == XFA_AttributeEnum::Right) + rtFit.left = rtImage.right() - rtFit.width; + + if (iVertAlign == XFA_AttributeEnum::Middle) + rtFit.top += (rtImage.height - rtFit.height) / 2; + else if (iVertAlign == XFA_AttributeEnum::Bottom) + rtFit.top = rtImage.bottom() - rtImage.height; + + CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); + CFX_RenderDevice::StateRestorer restorer(pRenderDevice); + CFX_PathData path; + path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); + pRenderDevice->SetClip_PathFill(&path, &matrix, FXFILL_WINDING); + + CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); + mtImage.Concat( + CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top)); + mtImage.Concat(matrix); + + CXFA_ImageRenderer imageRender(pRenderDevice, pDIBitmap, &mtImage); + if (!imageRender.Start()) { + return; + } + while (imageRender.Continue()) + continue; +} + +RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer( + const RetainPtr<IFX_SeekableReadStream>& pImageFileRead, + FXCODEC_IMAGE_TYPE type, + int32_t& iImageXDpi, + int32_t& iImageYDpi) { + CCodec_ModuleMgr* pCodecMgr = CPDF_ModuleMgr::Get()->GetCodecModule(); + std::unique_ptr<CCodec_ProgressiveDecoder> pProgressiveDecoder = + pCodecMgr->CreateProgressiveDecoder(); + + CFX_DIBAttribute dibAttr; + pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false); + switch (dibAttr.m_wDPIUnit) { + case FXCODEC_RESUNIT_CENTIMETER: + dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); + dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); + break; + case FXCODEC_RESUNIT_METER: + dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f); + dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f); + break; + default: + break; + } + iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); + iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); + if (pProgressiveDecoder->GetWidth() <= 0 || + pProgressiveDecoder->GetHeight() <= 0) { + return nullptr; + } + + type = pProgressiveDecoder->GetType(); + int32_t iComponents = pProgressiveDecoder->GetNumComponents(); + int32_t iBpc = pProgressiveDecoder->GetBPC(); + FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); + RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pBitmap->Create(pProgressiveDecoder->GetWidth(), + pProgressiveDecoder->GetHeight(), dibFormat); + pBitmap->Clear(0xffffffff); + + size_t nFrames; + FXCODEC_STATUS status; + std::tie(status, nFrames) = pProgressiveDecoder->GetFrames(); + if (status != FXCODEC_STATUS_DECODE_READY || nFrames == 0) { + pBitmap = nullptr; + return pBitmap; + } + + status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), + pBitmap->GetHeight()); + if (IsFXCodecErrorStatus(status)) { + pBitmap = nullptr; + return pBitmap; + } + + while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) { + status = pProgressiveDecoder->ContinueDecode(); + if (IsFXCodecErrorStatus(status)) { + pBitmap = nullptr; + return pBitmap; + } + } + + return pBitmap; +} + +void XFA_RectWithoutMargin(CFX_RectF& rt, const CXFA_Margin* margin, bool bUI) { + if (!margin) + return; + + rt.Deflate(margin->GetLeftInset(), margin->GetTopInset(), + margin->GetRightInset(), margin->GetBottomInset()); +} + +CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { + if (pLayoutItem->GetFormNode()->HasCreatedUIWidget()) + return static_cast<CXFA_FFWidget*>(pLayoutItem); + return nullptr; +} + +CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {} + +CXFA_CalcData::~CXFA_CalcData() {} + +CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) + : CXFA_ContentLayoutItem(node), m_pNode(node) {} + +CXFA_FFWidget::~CXFA_FFWidget() {} + +const CFWL_App* CXFA_FFWidget::GetFWLApp() { + return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp(); +} + +const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const { + if ((m_dwStatus & XFA_WidgetStatus_RectCached) == 0) + RecacheWidgetRect(); + return m_rtWidget; +} + +const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const { + m_dwStatus |= XFA_WidgetStatus_RectCached; + m_rtWidget = GetRect(false); + return m_rtWidget; +} + +CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() { + CFX_RectF rtWidget = GetWidgetRect(); + float fValue = 0; + switch (m_pNode->GetRotate()) { + case 90: + rtWidget.top = rtWidget.bottom(); + fValue = rtWidget.width; + rtWidget.width = rtWidget.height; + rtWidget.height = fValue; + break; + case 180: + rtWidget.left = rtWidget.right(); + rtWidget.top = rtWidget.bottom(); + break; + case 270: + rtWidget.left = rtWidget.right(); + fValue = rtWidget.width; + rtWidget.width = rtWidget.height; + rtWidget.height = fValue; + break; + } + return rtWidget; +} + +uint32_t CXFA_FFWidget::GetStatus() { + return m_dwStatus; +} + +void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) { + m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded; +} + +CFX_RectF CXFA_FFWidget::GetBBox(uint32_t dwStatus, bool bDrawFocus) { + if (bDrawFocus || !m_pPageView) + return CFX_RectF(); + return m_pPageView->GetPageViewRect(); +} + +void CXFA_FFWidget::RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus) { + if (!IsMatchVisibleStatus(dwStatus)) + return; + + CXFA_Border* border = m_pNode->GetBorderIfExists(); + if (!border) + return; + + CFX_RectF rtBorder = GetRectWithoutRotate(); + CXFA_Margin* margin = border->GetMarginIfExists(); + if (margin) + XFA_RectWithoutMargin(rtBorder, margin); + + rtBorder.Normalize(); + DrawBorder(pGS, border, rtBorder, matrix); +} + +bool CXFA_FFWidget::IsLoaded() { + return !!m_pPageView; +} + +bool CXFA_FFWidget::LoadWidget() { + PerformLayout(); + return true; +} + +void CXFA_FFWidget::UnloadWidget() {} + +bool CXFA_FFWidget::PerformLayout() { + RecacheWidgetRect(); + return true; +} + +bool CXFA_FFWidget::UpdateFWLData() { + return false; +} + +void CXFA_FFWidget::UpdateWidgetProperty() {} + +void CXFA_FFWidget::DrawBorder(CXFA_Graphics* pGS, + CXFA_Box* box, + const CFX_RectF& rtBorder, + const CFX_Matrix& matrix) { + if (box) + box->Draw(pGS, rtBorder, matrix, false); +} + +void CXFA_FFWidget::DrawBorderWithFlag(CXFA_Graphics* pGS, + CXFA_Box* box, + const CFX_RectF& rtBorder, + const CFX_Matrix& matrix, + bool forceRound) { + if (box) + box->Draw(pGS, rtBorder, matrix, forceRound); +} + +void CXFA_FFWidget::AddInvalidateRect() { + CFX_RectF rtWidget = GetBBox(XFA_WidgetStatus_Focused); + rtWidget.Inflate(2, 2); + m_pDocView->AddInvalidateRect(m_pPageView, rtWidget); +} + +bool CXFA_FFWidget::OnMouseEnter() { + return false; +} + +bool CXFA_FFWidget::OnMouseExit() { + return false; +} + +bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { + CXFA_FFWidget* pParent = GetParent(); + if (pParent && !pParent->IsAncestorOf(pOldWidget)) { + pParent->OnSetFocus(pOldWidget); + } + m_dwStatus |= XFA_WidgetStatus_Focused; + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Enter; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Enter, &eParam); + return true; +} + +bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { + m_dwStatus &= ~XFA_WidgetStatus_Focused; + EventKillFocus(); + if (pNewWidget) { + CXFA_FFWidget* pParent = GetParent(); + if (pParent && !pParent->IsAncestorOf(pNewWidget)) { + pParent->OnKillFocus(pNewWidget); + } + } + return true; +} + +bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) { + return false; +} + +bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) { + return false; +} + +bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) { + return false; +} + +FWL_WidgetHit CXFA_FFWidget::OnHitTest(const CFX_PointF& point) { + return FWL_WidgetHit::Unknown; +} + +bool CXFA_FFWidget::OnSetCursor(const CFX_PointF& point) { + return false; +} + +bool CXFA_FFWidget::CanUndo() { + return false; +} + +bool CXFA_FFWidget::CanRedo() { + return false; +} + +bool CXFA_FFWidget::Undo() { + return false; +} + +bool CXFA_FFWidget::Redo() { + return false; +} + +bool CXFA_FFWidget::CanCopy() { + return false; +} + +bool CXFA_FFWidget::CanCut() { + return false; +} + +bool CXFA_FFWidget::CanPaste() { + return false; +} + +bool CXFA_FFWidget::CanSelectAll() { + return false; +} + +bool CXFA_FFWidget::CanDelete() { + return CanCut(); +} + +bool CXFA_FFWidget::CanDeSelect() { + return CanCopy(); +} + +Optional<WideString> CXFA_FFWidget::Copy() { + return {}; +} + +Optional<WideString> CXFA_FFWidget::Cut() { + return {}; +} + +bool CXFA_FFWidget::Paste(const WideString& wsPaste) { + return false; +} + +void CXFA_FFWidget::SelectAll() {} + +void CXFA_FFWidget::Delete() {} + +void CXFA_FFWidget::DeSelect() {} + +FormFieldType CXFA_FFWidget::GetFormFieldType() { + return FormFieldType::kXFA; +} + +void CXFA_FFWidget::GetSuggestWords(CFX_PointF pointf, + std::vector<ByteString>* pWords) { + pWords->clear(); +} + +bool CXFA_FFWidget::ReplaceSpellCheckWord(CFX_PointF pointf, + const ByteStringView& bsReplace) { + return false; +} + +CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) { + CFX_Matrix mt = GetRotateMatrix(); + if (mt.IsIdentity()) + return point; + + return mt.GetInverse().Transform(point); +} + +CFX_Matrix CXFA_FFWidget::GetRotateMatrix() { + int32_t iRotate = m_pNode->GetRotate(); + if (!iRotate) + return CFX_Matrix(); + + CFX_RectF rcWidget = GetRectWithoutRotate(); + CFX_Matrix mt; + switch (iRotate) { + case 90: + mt.a = 0; + mt.b = -1; + mt.c = 1; + mt.d = 0; + mt.e = rcWidget.left - rcWidget.top; + mt.f = rcWidget.left + rcWidget.top; + break; + case 180: + mt.a = -1; + mt.b = 0; + mt.c = 0; + mt.d = -1; + mt.e = rcWidget.left * 2; + mt.f = rcWidget.top * 2; + break; + case 270: + mt.a = 0; + mt.b = 1; + mt.c = -1; + mt.d = 0; + mt.e = rcWidget.left + rcWidget.top; + mt.f = rcWidget.top - rcWidget.left; + break; + } + return mt; +} + +bool CXFA_FFWidget::IsLayoutRectEmpty() { + CFX_RectF rtLayout = GetRectWithoutRotate(); + return rtLayout.width < 0.1f && rtLayout.height < 0.1f; +} + +CXFA_FFWidget* CXFA_FFWidget::GetParent() { + CXFA_Node* pParentNode = m_pNode->GetParent(); + if (pParentNode) { + CXFA_WidgetAcc* pParentWidgetAcc = + static_cast<CXFA_WidgetAcc*>(pParentNode->GetWidgetAcc()); + if (pParentWidgetAcc) { + CXFA_LayoutProcessor* layout = GetDocView()->GetXFALayout(); + return static_cast<CXFA_FFWidget*>( + layout->GetLayoutItem(pParentWidgetAcc->GetNode())); + } + } + return nullptr; +} + +bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { + if (!pWidget) + return false; + + CXFA_Node* pChildNode = pWidget->GetNode(); + while (pChildNode) { + if (pChildNode == m_pNode) + return true; + + pChildNode = pChildNode->GetParent(); + } + return false; +} + +bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) { + return GetWidgetRect().Contains(point); +} + +CXFA_FFDocView* CXFA_FFWidget::GetDocView() { + return m_pDocView; +} + +void CXFA_FFWidget::SetDocView(CXFA_FFDocView* pDocView) { + m_pDocView = pDocView; +} + +CXFA_FFDoc* CXFA_FFWidget::GetDoc() { + return m_pDocView->GetDoc(); +} + +CXFA_FFApp* CXFA_FFWidget::GetApp() { + return GetDoc()->GetApp(); +} + +IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { + return GetApp()->GetAppProvider(); +} + +bool CXFA_FFWidget::IsMatchVisibleStatus(uint32_t dwStatus) { + return !!(m_dwStatus & XFA_WidgetStatus_Visible); +} + +void CXFA_FFWidget::EventKillFocus() { + if (m_dwStatus & XFA_WidgetStatus_Access) { + m_dwStatus &= ~XFA_WidgetStatus_Access; + return; + } + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Exit; + eParam.m_pTarget = m_pNode->GetWidgetAcc(); + m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Exit, &eParam); +} + +bool CXFA_FFWidget::IsButtonDown() { + return (m_dwStatus & XFA_WidgetStatus_ButtonDown) != 0; +} + +void CXFA_FFWidget::SetButtonDown(bool bSet) { + bSet ? m_dwStatus |= XFA_WidgetStatus_ButtonDown + : m_dwStatus &= ~XFA_WidgetStatus_ButtonDown; +} diff --git a/xfa/fxfa/cxfa_ffwidget.h b/xfa/fxfa/cxfa_ffwidget.h new file mode 100644 index 0000000000000000000000000000000000000000..54aa191fedaab176b16c61c3bbbc57a7b29e12ef --- /dev/null +++ b/xfa/fxfa/cxfa_ffwidget.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 XFA_FXFA_CXFA_FFWIDGET_H_ +#define XFA_FXFA_CXFA_FFWIDGET_H_ + +#include <vector> + +#include "core/fpdfdoc/cpdf_formfield.h" +#include "core/fxcodec/fx_codec_def.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "xfa/fwl/cfwl_app.h" +#include "xfa/fxfa/fxfa.h" +#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" + +class CXFA_Box; +class CXFA_FFPageView; +class CXFA_FFDocView; +class CXFA_FFDoc; +class CXFA_FFApp; +class CXFA_Graphics; +class CXFA_Image; +enum class FWL_WidgetHit; + +inline float XFA_UnitPx2Pt(float fPx, float fDpi) { + return fPx * 72.0f / fDpi; +} + +#define XFA_FLOAT_PERCISION 0.001f + +void XFA_DrawImage(CXFA_Graphics* pGS, + const CFX_RectF& rtImage, + const CFX_Matrix& matrix, + const RetainPtr<CFX_DIBitmap>& pDIBitmap, + XFA_AttributeEnum iAspect, + int32_t iImageXDpi, + int32_t iImageYDpi, + XFA_AttributeEnum iHorzAlign = XFA_AttributeEnum::Left, + XFA_AttributeEnum iVertAlign = XFA_AttributeEnum::Top); + +RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer( + const RetainPtr<IFX_SeekableReadStream>& pImageFileRead, + FXCODEC_IMAGE_TYPE type, + int32_t& iImageXDpi, + int32_t& iImageYDpi); + +void XFA_RectWithoutMargin(CFX_RectF& rt, + const CXFA_Margin* margin, + bool bUI = false); +CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem); + +class CXFA_CalcData { + public: + CXFA_CalcData(); + ~CXFA_CalcData(); + + std::vector<CXFA_Node*> m_Globals; + int32_t m_iRefCount; +}; + +class CXFA_FFWidget : public CXFA_ContentLayoutItem { + public: + explicit CXFA_FFWidget(CXFA_Node* pNode); + ~CXFA_FFWidget() override; + + virtual CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false); + virtual void RenderWidget(CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + uint32_t dwStatus); + virtual bool IsLoaded(); + virtual bool LoadWidget(); + virtual void UnloadWidget(); + virtual bool PerformLayout(); + virtual bool UpdateFWLData(); + virtual void UpdateWidgetProperty(); + virtual bool OnMouseEnter(); + virtual bool OnMouseExit(); + virtual bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point); + virtual bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point); + virtual bool OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point); + virtual bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point); + virtual bool OnMouseWheel(uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point); + virtual bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point); + virtual bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point); + virtual bool OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point); + + virtual bool OnSetFocus(CXFA_FFWidget* pOldWidget); + virtual bool OnKillFocus(CXFA_FFWidget* pNewWidget); + virtual bool OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags); + virtual bool OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags); + virtual bool OnChar(uint32_t dwChar, uint32_t dwFlags); + virtual FWL_WidgetHit OnHitTest(const CFX_PointF& point); + virtual bool OnSetCursor(const CFX_PointF& point); + virtual bool CanUndo(); + virtual bool CanRedo(); + virtual bool Undo(); + virtual bool Redo(); + virtual bool CanCopy(); + virtual bool CanCut(); + virtual bool CanPaste(); + virtual bool CanSelectAll(); + virtual bool CanDelete(); + virtual bool CanDeSelect(); + virtual Optional<WideString> Copy(); + virtual Optional<WideString> Cut(); + virtual bool Paste(const WideString& wsPaste); + virtual void SelectAll(); + virtual void Delete(); + virtual void DeSelect(); + + virtual FormFieldType GetFormFieldType(); + + // TODO(tsepez): Implement or remove. + void GetSuggestWords(CFX_PointF pointf, std::vector<ByteString>* pWords); + bool ReplaceSpellCheckWord(CFX_PointF pointf, + const ByteStringView& bsReplace); + + CXFA_FFPageView* GetPageView() const { return m_pPageView; } + void SetPageView(CXFA_FFPageView* pPageView) { m_pPageView = pPageView; } + const CFX_RectF& GetWidgetRect() const; + const CFX_RectF& RecacheWidgetRect() const; + uint32_t GetStatus(); + void ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved); + + CXFA_Node* GetNode() { return m_pNode.Get(); } + + CXFA_FFDocView* GetDocView(); + void SetDocView(CXFA_FFDocView* pDocView); + CXFA_FFDoc* GetDoc(); + CXFA_FFApp* GetApp(); + IXFA_AppProvider* GetAppProvider(); + void AddInvalidateRect(); + bool IsFocused() const { return !!(m_dwStatus & XFA_WidgetStatus_Focused); } + CFX_PointF Rotate2Normal(const CFX_PointF& point); + CFX_Matrix GetRotateMatrix(); + bool IsLayoutRectEmpty(); + CXFA_FFWidget* GetParent(); + bool IsAncestorOf(CXFA_FFWidget* pWidget); + const CFWL_App* GetFWLApp(); + + protected: + virtual bool PtInActiveRect(const CFX_PointF& point); + + void DrawBorder(CXFA_Graphics* pGS, + CXFA_Box* box, + const CFX_RectF& rtBorder, + const CFX_Matrix& matrix); + void DrawBorderWithFlag(CXFA_Graphics* pGS, + CXFA_Box* box, + const CFX_RectF& rtBorder, + const CFX_Matrix& matrix, + bool forceRound); + + CFX_RectF GetRectWithoutRotate(); + bool IsMatchVisibleStatus(uint32_t dwStatus); + void EventKillFocus(); + bool IsButtonDown(); + void SetButtonDown(bool bSet); + + CXFA_FFDocView* m_pDocView = nullptr; + CXFA_FFPageView* m_pPageView = nullptr; + UnownedPtr<CXFA_Node> const m_pNode; + mutable CFX_RectF m_rtWidget; +}; + +#endif // XFA_FXFA_CXFA_FFWIDGET_H_ diff --git a/xfa/fxfa/cxfa_ffwidgethandler.cpp b/xfa/fxfa/cxfa_ffwidgethandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c124c91f5f45bd44269cf2d349a81ebc77e752a0 --- /dev/null +++ b/xfa/fxfa/cxfa_ffwidgethandler.cpp @@ -0,0 +1,576 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffwidgethandler.h" + +#include <vector> + +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/parser/cxfa_calculate.h" +#include "xfa/fxfa/parser/cxfa_checkbutton.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_ui.h" +#include "xfa/fxfa/parser/cxfa_validate.h" + +CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView) + : m_pDocView(pDocView) {} + +CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() {} + +bool CXFA_FFWidgetHandler::OnMouseEnter(CXFA_FFWidget* hWidget) { + m_pDocView->LockUpdate(); + bool bRet = hWidget->OnMouseEnter(); + m_pDocView->UnlockUpdate(); + m_pDocView->UpdateDocView(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnMouseExit(CXFA_FFWidget* hWidget) { + m_pDocView->LockUpdate(); + bool bRet = hWidget->OnMouseExit(); + m_pDocView->UnlockUpdate(); + m_pDocView->UpdateDocView(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnLButtonDown(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + m_pDocView->LockUpdate(); + bool bRet = hWidget->OnLButtonDown(dwFlags, hWidget->Rotate2Normal(point)); + if (bRet && m_pDocView->SetFocus(hWidget)) { + m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget( + m_pDocView->GetDoc(), hWidget); + } + m_pDocView->UnlockUpdate(); + m_pDocView->UpdateDocView(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnLButtonUp(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + m_pDocView->LockUpdate(); + m_pDocView->m_bLayoutEvent = true; + bool bRet = hWidget->OnLButtonUp(dwFlags, hWidget->Rotate2Normal(point)); + m_pDocView->UnlockUpdate(); + m_pDocView->UpdateDocView(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnLButtonDblClk(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + bool bRet = hWidget->OnLButtonDblClk(dwFlags, hWidget->Rotate2Normal(point)); + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnMouseMove(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + bool bRet = hWidget->OnMouseMove(dwFlags, hWidget->Rotate2Normal(point)); + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnMouseWheel(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point) { + bool bRet = + hWidget->OnMouseWheel(dwFlags, zDelta, hWidget->Rotate2Normal(point)); + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnRButtonDown(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + bool bRet = hWidget->OnRButtonDown(dwFlags, hWidget->Rotate2Normal(point)); + if (bRet && m_pDocView->SetFocus(hWidget)) { + m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget( + m_pDocView->GetDoc(), hWidget); + } + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnRButtonUp(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + bool bRet = hWidget->OnRButtonUp(dwFlags, hWidget->Rotate2Normal(point)); + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnRButtonDblClk(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point) { + bool bRet = hWidget->OnRButtonDblClk(dwFlags, hWidget->Rotate2Normal(point)); + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnKeyDown(CXFA_FFWidget* hWidget, + uint32_t dwKeyCode, + uint32_t dwFlags) { + bool bRet = hWidget->OnKeyDown(dwKeyCode, dwFlags); + m_pDocView->RunInvalidate(); + m_pDocView->UpdateDocView(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnKeyUp(CXFA_FFWidget* hWidget, + uint32_t dwKeyCode, + uint32_t dwFlags) { + bool bRet = hWidget->OnKeyUp(dwKeyCode, dwFlags); + m_pDocView->RunInvalidate(); + return bRet; +} + +bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget, + uint32_t dwChar, + uint32_t dwFlags) { + bool bRet = hWidget->OnChar(dwChar, dwFlags); + m_pDocView->RunInvalidate(); + return bRet; +} + +WideString CXFA_FFWidgetHandler::GetSelectedText(CXFA_FFWidget* widget) { + if (!widget->CanCopy()) + return WideString(); + + return widget->Copy().value_or(WideString()); +} + +void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget, + const WideString& text) { + if (!widget->CanPaste()) + return; + + widget->Paste(text); +} + +FWL_WidgetHit CXFA_FFWidgetHandler::OnHitTest(CXFA_FFWidget* hWidget, + const CFX_PointF& point) { + if (!(hWidget->GetStatus() & XFA_WidgetStatus_Visible)) + return FWL_WidgetHit::Unknown; + return hWidget->OnHitTest(hWidget->Rotate2Normal(point)); +} + +bool CXFA_FFWidgetHandler::OnSetCursor(CXFA_FFWidget* hWidget, + const CFX_PointF& point) { + return hWidget->OnSetCursor(hWidget->Rotate2Normal(point)); +} + +void CXFA_FFWidgetHandler::RenderWidget(CXFA_FFWidget* hWidget, + CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + bool bHighlight) { + hWidget->RenderWidget(pGS, matrix, + bHighlight ? XFA_WidgetStatus_Highlight : 0); +} + +bool CXFA_FFWidgetHandler::HasEvent(CXFA_WidgetAcc* pWidgetAcc, + XFA_EVENTTYPE eEventType) { + if (eEventType == XFA_EVENT_Unknown) + return false; + if (!pWidgetAcc) + return false; + + CXFA_Node* node = pWidgetAcc->GetNode(); + if (!node || node->GetElementType() == XFA_Element::Draw) + return false; + + switch (eEventType) { + case XFA_EVENT_Calculate: { + CXFA_Calculate* calc = node->GetCalculateIfExists(); + return calc && calc->GetScriptIfExists(); + } + case XFA_EVENT_Validate: { + CXFA_Validate* validate = node->GetValidateIfExists(); + return validate && validate->GetScriptIfExists(); + } + default: + break; + } + return !pWidgetAcc->GetEventByActivity(gs_EventActivity[eEventType], false) + .empty(); +} + +int32_t CXFA_FFWidgetHandler::ProcessEvent(CXFA_WidgetAcc* pWidgetAcc, + CXFA_EventParam* pParam) { + if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) + return XFA_EVENTERROR_NotExist; + if (!pWidgetAcc) + return XFA_EVENTERROR_NotExist; + + CXFA_Node* node = pWidgetAcc->GetNode(); + if (!node || node->GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + switch (pParam->m_eType) { + case XFA_EVENT_Calculate: + return node->ProcessCalculate(m_pDocView); + case XFA_EVENT_Validate: + if (m_pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled( + m_pDocView->GetDoc())) { + return node->ProcessValidate(m_pDocView, 0); + } + return XFA_EVENTERROR_Disabled; + case XFA_EVENT_InitCalculate: { + CXFA_Calculate* calc = node->GetCalculateIfExists(); + if (!calc) + return XFA_EVENTERROR_NotExist; + if (node->IsUserInteractive()) + return XFA_EVENTERROR_Disabled; + return node->ExecuteScript(m_pDocView, calc->GetScriptIfExists(), pParam); + } + default: + break; + } + int32_t iRet = + node->ProcessEvent(m_pDocView, gs_EventActivity[pParam->m_eType], pParam); + return iRet; +} + +CXFA_FFWidget* CXFA_FFWidgetHandler::CreateWidget(CXFA_FFWidget* hParent, + XFA_WIDGETTYPE eType, + CXFA_FFWidget* hBefore) { + CXFA_Node* pParentFormItem = hParent ? hParent->GetNode() : nullptr; + CXFA_Node* pBeforeFormItem = hBefore ? hBefore->GetNode() : nullptr; + CXFA_Node* pNewFormItem = + CreateWidgetFormItem(eType, pParentFormItem, pBeforeFormItem); + if (!pNewFormItem) + return nullptr; + + CXFA_Node* templateNode = pNewFormItem->GetTemplateNodeIfExists(); + if (!templateNode) + return nullptr; + + templateNode->SetFlag(XFA_NodeFlag_Initialized, true); + pNewFormItem->SetFlag(XFA_NodeFlag_Initialized, true); + m_pDocView->RunLayout(); + CXFA_LayoutItem* pLayout = + m_pDocView->GetXFALayout()->GetLayoutItem(pNewFormItem); + return static_cast<CXFA_FFWidget*>(pLayout); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateWidgetFormItem( + XFA_WIDGETTYPE eType, + CXFA_Node* pParent, + CXFA_Node* pBefore) const { + switch (eType) { + case XFA_WIDGETTYPE_Barcode: + return nullptr; + case XFA_WIDGETTYPE_PushButton: + return CreatePushButton(pParent, pBefore); + case XFA_WIDGETTYPE_CheckButton: + return CreateCheckButton(pParent, pBefore); + case XFA_WIDGETTYPE_ExcludeGroup: + return CreateExclGroup(pParent, pBefore); + case XFA_WIDGETTYPE_RadioButton: + return CreateRadioButton(pParent, pBefore); + case XFA_WIDGETTYPE_Arc: + return CreateArc(pParent, pBefore); + case XFA_WIDGETTYPE_Rectangle: + return CreateRectangle(pParent, pBefore); + case XFA_WIDGETTYPE_Image: + return CreateImage(pParent, pBefore); + case XFA_WIDGETTYPE_Line: + return CreateLine(pParent, pBefore); + case XFA_WIDGETTYPE_Text: + return CreateText(pParent, pBefore); + case XFA_WIDGETTYPE_DatetimeEdit: + return CreateDatetimeEdit(pParent, pBefore); + case XFA_WIDGETTYPE_DecimalField: + return CreateDecimalField(pParent, pBefore); + case XFA_WIDGETTYPE_NumericField: + return CreateNumericField(pParent, pBefore); + case XFA_WIDGETTYPE_Signature: + return CreateSignature(pParent, pBefore); + case XFA_WIDGETTYPE_TextEdit: + return CreateTextEdit(pParent, pBefore); + case XFA_WIDGETTYPE_DropdownList: + return CreateDropdownList(pParent, pBefore); + case XFA_WIDGETTYPE_ListBox: + return CreateListBox(pParent, pBefore); + case XFA_WIDGETTYPE_ImageField: + return CreateImageField(pParent, pBefore); + case XFA_WIDGETTYPE_PasswordEdit: + return CreatePasswordEdit(pParent, pBefore); + case XFA_WIDGETTYPE_Subform: + return CreateSubform(pParent, pBefore); + default: + return nullptr; + } +} + +CXFA_Node* CXFA_FFWidgetHandler::CreatePushButton(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateField(XFA_Element::Button, pParent, pBefore); + CXFA_Node* pCaption = CreateCopyNode(XFA_Element::Caption, pField); + CXFA_Node* pValue = CreateCopyNode(XFA_Element::Value, pCaption); + CXFA_Node* pText = CreateCopyNode(XFA_Element::Text, pValue); + pText->JSObject()->SetContent(L"Button", L"Button", false, false, true); + + CXFA_Node* pPara = CreateCopyNode(XFA_Element::Para, pCaption); + pPara->JSObject()->SetEnum(XFA_Attribute::VAlign, XFA_AttributeEnum::Middle, + false); + pPara->JSObject()->SetEnum(XFA_Attribute::HAlign, XFA_AttributeEnum::Center, + false); + CreateFontNode(pCaption); + + CXFA_Node* pBorder = CreateCopyNode(XFA_Element::Border, pField); + pBorder->JSObject()->SetEnum(XFA_Attribute::Hand, XFA_AttributeEnum::Right, + false); + + CXFA_Node* pEdge = CreateCopyNode(XFA_Element::Edge, pBorder); + pEdge->JSObject()->SetEnum(XFA_Attribute::Stroke, XFA_AttributeEnum::Raised, + false); + + CXFA_Node* pFill = CreateCopyNode(XFA_Element::Fill, pBorder); + CXFA_Node* pColor = CreateCopyNode(XFA_Element::Color, pFill); + pColor->JSObject()->SetCData(XFA_Attribute::Value, L"212, 208, 200", false, + false); + + CXFA_Node* pBind = CreateCopyNode(XFA_Element::Bind, pField); + pBind->JSObject()->SetEnum(XFA_Attribute::Match, XFA_AttributeEnum::None, + false); + + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateCheckButton(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateField(XFA_Element::CheckButton, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateExclGroup(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateFormItem(XFA_Element::ExclGroup, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateRadioButton(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateField(XFA_Element::CheckButton, pParent, pBefore); + CXFA_Ui* pUi = pField->GetFirstChildByClass<CXFA_Ui>(XFA_Element::Ui); + CXFA_CheckButton* pWidget = + pUi->GetFirstChildByClass<CXFA_CheckButton>(XFA_Element::CheckButton); + pWidget->JSObject()->SetEnum(XFA_Attribute::Shape, XFA_AttributeEnum::Round, + false); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateDatetimeEdit(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateField(XFA_Element::DateTimeEdit, pParent, pBefore); + CreateValueNode(XFA_Element::Date, pField); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateDecimalField(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateNumericField(pParent, pBefore); + CreateValueNode(XFA_Element::Decimal, pField); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateNumericField(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateField(XFA_Element::NumericEdit, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateSignature(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateField(XFA_Element::Signature, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateTextEdit(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateField(XFA_Element::TextEdit, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateDropdownList(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateField(XFA_Element::ChoiceList, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateListBox(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateDropdownList(pParent, pBefore); + CXFA_Node* pUi = pField->GetFirstChild(); + CXFA_Node* pListBox = pUi->GetFirstChild(); + pListBox->JSObject()->SetEnum(XFA_Attribute::Open, XFA_AttributeEnum::Always, + false); + pListBox->JSObject()->SetEnum(XFA_Attribute::CommitOn, + XFA_AttributeEnum::Exit, false); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateImageField(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateField(XFA_Element::ImageEdit, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreatePasswordEdit(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateField(XFA_Element::PasswordEdit, pParent, pBefore); + CXFA_Node* pBind = CreateCopyNode(XFA_Element::Bind, pField); + pBind->JSObject()->SetEnum(XFA_Attribute::Match, XFA_AttributeEnum::None, + false); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateField(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateFormItem(XFA_Element::Field, pParent, pBefore); + CreateCopyNode(eElement, CreateCopyNode(XFA_Element::Ui, pField)); + CreateFontNode(pField); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateArc(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateDraw(XFA_Element::Arc, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateRectangle(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateDraw(XFA_Element::Rectangle, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateImage(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateDraw(XFA_Element::Image, pParent, pBefore); + CreateCopyNode(XFA_Element::ImageEdit, + CreateCopyNode(XFA_Element::Ui, pField)); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateLine(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateDraw(XFA_Element::Line, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateText(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pField = CreateDraw(XFA_Element::Text, pParent, pBefore); + CreateCopyNode(XFA_Element::TextEdit, + CreateCopyNode(XFA_Element::Ui, pField)); + CreateFontNode(pField); + return pField; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateDraw(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Node* pDraw = CreateFormItem(XFA_Element::Draw, pParent, pBefore); + CreateValueNode(eElement, pDraw); + return pDraw; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateSubform(CXFA_Node* pParent, + CXFA_Node* pBefore) const { + return CreateFormItem(XFA_Element::Subform, pParent, pBefore); +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateFormItem(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const { + if (!pParent) + return nullptr; + + CXFA_Node* pTemplateParent = pParent->GetTemplateNodeIfExists(); + if (!pTemplateParent) + return nullptr; + + CXFA_Node* pNewFormItem = pTemplateParent->CloneTemplateToForm(false); + if (pParent) + pParent->InsertChild(pNewFormItem, pBefore); + return pNewFormItem; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateCopyNode(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const { + if (!pParent) + return nullptr; + + CXFA_Node* pTemplateParent = pParent->GetTemplateNodeIfExists(); + CXFA_Node* pNewNode = + CreateTemplateNode(eElement, pTemplateParent, + pBefore ? pBefore->GetTemplateNodeIfExists() : nullptr) + ->Clone(false); + if (pParent) + pParent->InsertChild(pNewNode, pBefore); + return pNewNode; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateTemplateNode(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const { + CXFA_Document* pXFADoc = GetXFADoc(); + CXFA_Node* pNewTemplateNode = + pXFADoc->CreateNode(XFA_PacketType::Template, eElement); + if (pParent) + pParent->InsertChild(pNewTemplateNode, pBefore); + return pNewTemplateNode; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateFontNode(CXFA_Node* pParent) const { + CXFA_Node* pFont = CreateCopyNode(XFA_Element::Font, pParent); + pFont->JSObject()->SetCData(XFA_Attribute::Typeface, L"Myriad Pro", false, + false); + return pFont; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateMarginNode(CXFA_Node* pParent, + uint32_t dwFlags, + float fInsets[4]) const { + CXFA_Node* pMargin = CreateCopyNode(XFA_Element::Margin, pParent); + if (dwFlags & 0x01) + pMargin->JSObject()->SetMeasure(XFA_Attribute::LeftInset, + CXFA_Measurement(fInsets[0], XFA_Unit::Pt), + false); + if (dwFlags & 0x02) + pMargin->JSObject()->SetMeasure(XFA_Attribute::TopInset, + CXFA_Measurement(fInsets[1], XFA_Unit::Pt), + false); + if (dwFlags & 0x04) + pMargin->JSObject()->SetMeasure(XFA_Attribute::RightInset, + CXFA_Measurement(fInsets[2], XFA_Unit::Pt), + false); + if (dwFlags & 0x08) + pMargin->JSObject()->SetMeasure(XFA_Attribute::BottomInset, + CXFA_Measurement(fInsets[3], XFA_Unit::Pt), + false); + return pMargin; +} + +CXFA_Node* CXFA_FFWidgetHandler::CreateValueNode(XFA_Element eValue, + CXFA_Node* pParent) const { + CXFA_Node* pValue = CreateCopyNode(XFA_Element::Value, pParent); + CreateCopyNode(eValue, pValue); + return pValue; +} + +CXFA_Document* CXFA_FFWidgetHandler::GetObjFactory() const { + return GetXFADoc(); +} + +CXFA_Document* CXFA_FFWidgetHandler::GetXFADoc() const { + return m_pDocView->GetDoc()->GetXFADoc(); +} diff --git a/xfa/fxfa/cxfa_ffwidgethandler.h b/xfa/fxfa/cxfa_ffwidgethandler.h new file mode 100644 index 0000000000000000000000000000000000000000..1ef8854310290a5e9ffdd354472faedae802b757 --- /dev/null +++ b/xfa/fxfa/cxfa_ffwidgethandler.h @@ -0,0 +1,123 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FFWIDGETHANDLER_H_ +#define XFA_FXFA_CXFA_FFWIDGETHANDLER_H_ + +#include <vector> + +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/fxfa.h" +#include "xfa/fxfa/parser/cxfa_document.h" + +class CXFA_FFDocView; +class CXFA_Graphics; +enum class FWL_WidgetHit; + +class CXFA_FFWidgetHandler { + public: + explicit CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView); + ~CXFA_FFWidgetHandler(); + + CXFA_FFWidget* CreateWidget(CXFA_FFWidget* hParent, + XFA_WIDGETTYPE eType, + CXFA_FFWidget* hBefore = nullptr); + + bool OnMouseEnter(CXFA_FFWidget* hWidget); + bool OnMouseExit(CXFA_FFWidget* hWidget); + bool OnLButtonDown(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + bool OnLButtonUp(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + bool OnLButtonDblClk(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + bool OnMouseMove(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + bool OnMouseWheel(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + int16_t zDelta, + const CFX_PointF& point); + bool OnRButtonDown(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + bool OnRButtonUp(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + bool OnRButtonDblClk(CXFA_FFWidget* hWidget, + uint32_t dwFlags, + const CFX_PointF& point); + + WideString GetSelectedText(CXFA_FFWidget* widget); + void PasteText(CXFA_FFWidget* widget, const WideString& text); + + bool OnKeyDown(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags); + bool OnKeyUp(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags); + bool OnChar(CXFA_FFWidget* hWidget, uint32_t dwChar, uint32_t dwFlags); + FWL_WidgetHit OnHitTest(CXFA_FFWidget* hWidget, const CFX_PointF& point); + bool OnSetCursor(CXFA_FFWidget* hWidget, const CFX_PointF& point); + void RenderWidget(CXFA_FFWidget* hWidget, + CXFA_Graphics* pGS, + const CFX_Matrix& matrix, + bool bHighlight); + bool HasEvent(CXFA_WidgetAcc* pWidgetAcc, XFA_EVENTTYPE eEventType); + int32_t ProcessEvent(CXFA_WidgetAcc* pWidgetAcc, CXFA_EventParam* pParam); + + private: + CXFA_Node* CreateWidgetFormItem(XFA_WIDGETTYPE eType, + CXFA_Node* pParent, + CXFA_Node* pBefore) const; + + CXFA_Node* CreatePushButton(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateCheckButton(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateExclGroup(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateRadioButton(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateDatetimeEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateDecimalField(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateNumericField(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateSignature(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateTextEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateDropdownList(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateListBox(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateImageField(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreatePasswordEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateField(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const; + CXFA_Node* CreateArc(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateRectangle(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateImage(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateLine(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateText(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateDraw(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const; + + CXFA_Node* CreateSubform(CXFA_Node* pParent, CXFA_Node* pBefore) const; + CXFA_Node* CreateFormItem(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const; + CXFA_Node* CreateCopyNode(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore = nullptr) const; + CXFA_Node* CreateTemplateNode(XFA_Element eElement, + CXFA_Node* pParent, + CXFA_Node* pBefore) const; + CXFA_Node* CreateFontNode(CXFA_Node* pParent) const; + CXFA_Node* CreateMarginNode(CXFA_Node* pParent, + uint32_t dwFlags, + float fInsets[4]) const; + CXFA_Node* CreateValueNode(XFA_Element eValue, CXFA_Node* pParent) const; + CXFA_Document* GetObjFactory() const; + CXFA_Document* GetXFADoc() const; + + CXFA_FFDocView* m_pDocView; +}; + +#endif // XFA_FXFA_CXFA_FFWIDGETHANDLER_H_ diff --git a/xfa/fxfa/cxfa_fontmgr.cpp b/xfa/fxfa/cxfa_fontmgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0956806698585b33b5e38c87e0c835ed23a4e9f0 --- /dev/null +++ b/xfa/fxfa/cxfa_fontmgr.cpp @@ -0,0 +1,76 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fontmgr.h" + +#include <algorithm> +#include <memory> +#include <utility> + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/font/fgas_fontutils.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" + +CXFA_FontMgr::CXFA_FontMgr() {} + +CXFA_FontMgr::~CXFA_FontMgr() {} + +RetainPtr<CFGAS_GEFont> CXFA_FontMgr::GetFont( + CXFA_FFDoc* hDoc, + const WideStringView& wsFontFamily, + uint32_t dwFontStyles) { + uint32_t dwHash = FX_HashCode_GetW(wsFontFamily, false); + ByteString bsKey = ByteString::Format("%u%u%u", dwHash, dwFontStyles, 0xFFFF); + auto iter = m_FontMap.find(bsKey); + if (iter != m_FontMap.end()) + return iter->second; + + WideString wsEnglishName = FGAS_FontNameToEnglishName(wsFontFamily); + + CFGAS_PDFFontMgr* pMgr = hDoc->GetPDFFontMgr(); + CPDF_Font* pPDFFont = nullptr; + RetainPtr<CFGAS_GEFont> pFont; + if (pMgr) { + pFont = pMgr->GetFont(wsEnglishName.AsStringView(), dwFontStyles, &pPDFFont, + true); + if (pFont) + return pFont; + } + if (!pFont && m_pDefFontMgr) + pFont = m_pDefFontMgr->GetFont(hDoc->GetApp()->GetFDEFontMgr(), + wsFontFamily, dwFontStyles); + + if (!pFont && pMgr) { + pPDFFont = nullptr; + pFont = pMgr->GetFont(wsEnglishName.AsStringView(), dwFontStyles, &pPDFFont, + false); + if (pFont) + return pFont; + } + if (!pFont && m_pDefFontMgr) { + pFont = m_pDefFontMgr->GetDefaultFont(hDoc->GetApp()->GetFDEFontMgr(), + wsFontFamily, dwFontStyles); + } + + if (pFont) { + if (pPDFFont) { + pMgr->SetFont(pFont, pPDFFont); + pFont->SetFontProvider(pMgr); + } + m_FontMap[bsKey] = pFont; + } + return pFont; +} + +void CXFA_FontMgr::SetDefFontMgr( + std::unique_ptr<CFGAS_DefaultFontManager> pFontMgr) { + m_pDefFontMgr = std::move(pFontMgr); +} diff --git a/xfa/fxfa/cxfa_fontmgr.h b/xfa/fxfa/cxfa_fontmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..a940fafc462446a298adf33b1e11a782d78f8b6d --- /dev/null +++ b/xfa/fxfa/cxfa_fontmgr.h @@ -0,0 +1,39 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FONTMGR_H_ +#define XFA_FXFA_CXFA_FONTMGR_H_ + +#include <map> +#include <memory> +#include <vector> + +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "xfa/fgas/font/cfgas_defaultfontmanager.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_pdffontmgr.h" +#include "xfa/fxfa/fxfa.h" + +class CPDF_Font; + +class CXFA_FontMgr { + public: + CXFA_FontMgr(); + ~CXFA_FontMgr(); + + RetainPtr<CFGAS_GEFont> GetFont(CXFA_FFDoc* hDoc, + const WideStringView& wsFontFamily, + uint32_t dwFontStyles); + void SetDefFontMgr(std::unique_ptr<CFGAS_DefaultFontManager> pFontMgr); + + private: + std::unique_ptr<CFGAS_DefaultFontManager> m_pDefFontMgr; + std::map<ByteString, RetainPtr<CFGAS_GEFont>> m_FontMap; +}; + +#endif // XFA_FXFA_CXFA_FONTMGR_H_ diff --git a/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp b/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6fdd553712272be547104101783ce1d45594f160 --- /dev/null +++ b/xfa/fxfa/cxfa_fwladapterwidgetmgr.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" + +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_fffield.h" + +CXFA_FWLAdapterWidgetMgr::CXFA_FWLAdapterWidgetMgr() {} + +CXFA_FWLAdapterWidgetMgr::~CXFA_FWLAdapterWidgetMgr() {} + +void CXFA_FWLAdapterWidgetMgr::RepaintWidget(CFWL_Widget* pWidget) { + if (!pWidget) + return; + + CXFA_FFWidget* pFFWidget = pWidget->GetLayoutItem(); + if (!pFFWidget) + return; + + pFFWidget->AddInvalidateRect(); +} + +bool CXFA_FWLAdapterWidgetMgr::GetPopupPos(CFWL_Widget* pWidget, + float fMinHeight, + float fMaxHeight, + const CFX_RectF& rtAnchor, + CFX_RectF& rtPopup) { + CXFA_FFWidget* pFFWidget = pWidget->GetLayoutItem(); + CFX_RectF rtRotateAnchor = + pFFWidget->GetRotateMatrix().TransformRect(rtAnchor); + pFFWidget->GetDoc()->GetDocEnvironment()->GetPopupPos( + pFFWidget, fMinHeight, fMaxHeight, rtRotateAnchor, rtPopup); + return true; +} diff --git a/xfa/fxfa/cxfa_fwladapterwidgetmgr.h b/xfa/fxfa/cxfa_fwladapterwidgetmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..f5c4ce160e3de0da3244c68a374874a240c460a1 --- /dev/null +++ b/xfa/fxfa/cxfa_fwladapterwidgetmgr.h @@ -0,0 +1,28 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FWLADAPTERWIDGETMGR_H_ +#define XFA_FXFA_CXFA_FWLADAPTERWIDGETMGR_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_system.h" + +class CFWL_Widget; + +class CXFA_FWLAdapterWidgetMgr { + public: + CXFA_FWLAdapterWidgetMgr(); + ~CXFA_FWLAdapterWidgetMgr(); + + void RepaintWidget(CFWL_Widget* pWidget); + bool GetPopupPos(CFWL_Widget* pWidget, + float fMinHeight, + float fMaxHeight, + const CFX_RectF& rtAnchor, + CFX_RectF& rtPopup); +}; + +#endif // XFA_FXFA_CXFA_FWLADAPTERWIDGETMGR_H_ diff --git a/xfa/fxfa/cxfa_fwltheme.cpp b/xfa/fxfa/cxfa_fwltheme.cpp new file mode 100644 index 0000000000000000000000000000000000000000..920968269fe3ee531db1eee885801d85ce65beb7 --- /dev/null +++ b/xfa/fxfa/cxfa_fwltheme.cpp @@ -0,0 +1,282 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_fwltheme.h" + +#include "core/fxcrt/fx_codepage.h" +#include "xfa/fde/cfde_textout.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fwl/cfwl_barcode.h" +#include "xfa/fwl/cfwl_caret.h" +#include "xfa/fwl/cfwl_checkbox.h" +#include "xfa/fwl/cfwl_combobox.h" +#include "xfa/fwl/cfwl_datetimepicker.h" +#include "xfa/fwl/cfwl_edit.h" +#include "xfa/fwl/cfwl_listbox.h" +#include "xfa/fwl/cfwl_monthcalendar.h" +#include "xfa/fwl/cfwl_picturebox.h" +#include "xfa/fwl/cfwl_pushbutton.h" +#include "xfa/fwl/cfwl_scrollbar.h" +#include "xfa/fwl/cfwl_themebackground.h" +#include "xfa/fwl/cfwl_themetext.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" + +namespace { + +const wchar_t* const g_FWLTheme_CalFonts[] = { + L"Arial", L"Courier New", L"DejaVu Sans", +}; + +const float kLineHeight = 12.0f; + +} // namespace + +CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget) { + CFWL_Widget* pOuter = pWidget; + while (pOuter && pOuter->GetOuter()) + pOuter = pOuter->GetOuter(); + return pOuter ? pOuter->GetLayoutItem() : nullptr; +} + +CXFA_FWLTheme::CXFA_FWLTheme(CXFA_FFApp* pApp) + : m_pCheckBoxTP(pdfium::MakeUnique<CFWL_CheckBoxTP>()), + m_pListBoxTP(pdfium::MakeUnique<CFWL_ListBoxTP>()), + m_pPictureBoxTP(pdfium::MakeUnique<CFWL_PictureBoxTP>()), + m_pSrollBarTP(pdfium::MakeUnique<CFWL_ScrollBarTP>()), + m_pEditTP(pdfium::MakeUnique<CFWL_EditTP>()), + m_pComboBoxTP(pdfium::MakeUnique<CFWL_ComboBoxTP>()), + m_pMonthCalendarTP(pdfium::MakeUnique<CFWL_MonthCalendarTP>()), + m_pDateTimePickerTP(pdfium::MakeUnique<CFWL_DateTimePickerTP>()), + m_pPushButtonTP(pdfium::MakeUnique<CFWL_PushButtonTP>()), + m_pCaretTP(pdfium::MakeUnique<CFWL_CaretTP>()), + m_pBarcodeTP(pdfium::MakeUnique<CFWL_BarcodeTP>()), + m_pTextOut(pdfium::MakeUnique<CFDE_TextOut>()), + m_pCalendarFont(nullptr), + m_pApp(pApp) { + m_Rect.Reset(); + + for (size_t i = 0; !m_pCalendarFont && i < FX_ArraySize(g_FWLTheme_CalFonts); + ++i) { + m_pCalendarFont = CFGAS_GEFont::LoadFont(g_FWLTheme_CalFonts[i], 0, 0, + m_pApp->GetFDEFontMgr()); + } + if (!m_pCalendarFont) { + m_pCalendarFont = m_pApp->GetFDEFontMgr()->GetFontByCodePage( + FX_CODEPAGE_MSWin_WesternEuropean, 0, nullptr); + } + + ASSERT(m_pCalendarFont); +} + +CXFA_FWLTheme::~CXFA_FWLTheme() { + m_pTextOut.reset(); + FWLTHEME_Release(); +} + +void CXFA_FWLTheme::DrawBackground(CFWL_ThemeBackground* pParams) { + GetTheme(pParams->m_pWidget)->DrawBackground(pParams); +} + +void CXFA_FWLTheme::DrawText(CFWL_ThemeText* pParams) { + if (pParams->m_wsText.IsEmpty()) + return; + + if (pParams->m_pWidget->GetClassID() == FWL_Type::MonthCalendar) { + CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); + if (!pWidget) + return; + + m_pTextOut->SetStyles(pParams->m_dwTTOStyles); + m_pTextOut->SetAlignment(pParams->m_iTTOAlign); + m_pTextOut->SetFont(m_pCalendarFont); + m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize); + m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor); + if ((pParams->m_iPart == CFWL_Part::DatesIn) && + !(pParams->m_dwStates & FWL_ITEMSTATE_MCD_Flag) && + (pParams->m_dwStates & + (CFWL_PartState_Hovered | CFWL_PartState_Selected))) { + m_pTextOut->SetTextColor(0xFFFFFFFF); + } + if (pParams->m_iPart == CFWL_Part::Caption) + m_pTextOut->SetTextColor(ArgbEncode(0xff, 0, 153, 255)); + + CXFA_Graphics* pGraphics = pParams->m_pGraphics; + CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice(); + if (!pRenderDevice) + return; + + CFX_Matrix mtPart = pParams->m_matrix; + const CFX_Matrix* pMatrix = pGraphics->GetMatrix(); + if (pMatrix) + mtPart.Concat(*pMatrix); + + m_pTextOut->SetMatrix(mtPart); + m_pTextOut->DrawLogicText(pRenderDevice, pParams->m_wsText.AsStringView(), + pParams->m_rtPart); + return; + } + CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); + if (!pWidget) + return; + + CXFA_Node* pNode = pWidget->GetNode(); + CXFA_Graphics* pGraphics = pParams->m_pGraphics; + CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice(); + if (!pRenderDevice) + return; + + m_pTextOut->SetStyles(pParams->m_dwTTOStyles); + m_pTextOut->SetAlignment(pParams->m_iTTOAlign); + m_pTextOut->SetFont(pNode->GetWidgetAcc()->GetFDEFont(pWidget->GetDoc())); + m_pTextOut->SetFontSize(pNode->GetFontSize()); + m_pTextOut->SetTextColor(pNode->GetTextColor()); + CFX_Matrix mtPart = pParams->m_matrix; + const CFX_Matrix* pMatrix = pGraphics->GetMatrix(); + if (pMatrix) + mtPart.Concat(*pMatrix); + + m_pTextOut->SetMatrix(mtPart); + m_pTextOut->DrawLogicText(pRenderDevice, pParams->m_wsText.AsStringView(), + pParams->m_rtPart); +} + +CFX_RectF CXFA_FWLTheme::GetUIMargin(CFWL_ThemePart* pThemePart) const { + CFX_RectF rect; + CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget); + if (!pWidget) + return rect; + + CXFA_LayoutItem* pItem = pWidget; + CXFA_WidgetAcc* pWidgetAcc = pWidget->GetNode()->GetWidgetAcc(); + rect = pWidgetAcc->GetUIMargin(); + CXFA_Para* para = pWidgetAcc->GetNode()->GetParaIfExists(); + if (para) { + rect.left += para->GetMarginLeft(); + if (pWidgetAcc->IsMultiLine()) + rect.width += para->GetMarginRight(); + } + if (!pItem->GetPrev()) { + if (pItem->GetNext()) + rect.height = 0; + } else if (!pItem->GetNext()) { + rect.top = 0; + } else { + rect.top = 0; + rect.height = 0; + } + return rect; +} + +float CXFA_FWLTheme::GetCXBorderSize() const { + return 1.0f; +} + +float CXFA_FWLTheme::GetCYBorderSize() const { + return 1.0f; +} + +float CXFA_FWLTheme::GetFontSize(CFWL_ThemePart* pThemePart) const { + if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) + return pWidget->GetNode()->GetFontSize(); + return FWLTHEME_CAPACITY_FontSize; +} + +RetainPtr<CFGAS_GEFont> CXFA_FWLTheme::GetFont( + CFWL_ThemePart* pThemePart) const { + if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) + return pWidget->GetNode()->GetWidgetAcc()->GetFDEFont(pWidget->GetDoc()); + return GetTheme(pThemePart->m_pWidget)->GetFont(); +} + +float CXFA_FWLTheme::GetLineHeight(CFWL_ThemePart* pThemePart) const { + if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) + return pWidget->GetNode()->GetLineHeight(); + return kLineHeight; +} + +float CXFA_FWLTheme::GetScrollBarWidth() const { + return 9.0f; +} + +FX_COLORREF CXFA_FWLTheme::GetTextColor(CFWL_ThemePart* pThemePart) const { + if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) + return pWidget->GetNode()->GetTextColor(); + return FWLTHEME_CAPACITY_TextColor; +} + +CFX_SizeF CXFA_FWLTheme::GetSpaceAboveBelow(CFWL_ThemePart* pThemePart) const { + CFX_SizeF sizeAboveBelow; + if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) { + CXFA_Para* para = pWidget->GetNode()->GetParaIfExists(); + if (para) { + sizeAboveBelow.width = para->GetSpaceAbove(); + sizeAboveBelow.height = para->GetSpaceBelow(); + } + } + return sizeAboveBelow; +} + +void CXFA_FWLTheme::CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) { + if (pParams->m_pWidget->GetClassID() == FWL_Type::MonthCalendar) { + CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); + if (!pWidget || !pParams || !m_pTextOut) + return; + + m_pTextOut->SetFont(m_pCalendarFont); + m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize); + m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor); + m_pTextOut->SetAlignment(pParams->m_iTTOAlign); + m_pTextOut->SetStyles(pParams->m_dwTTOStyles); + m_pTextOut->CalcLogicSize(pParams->m_wsText, rect); + } + + CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget); + if (!pWidget) + return; + + CXFA_Node* pNode = pWidget->GetNode(); + m_pTextOut->SetFont(pNode->GetWidgetAcc()->GetFDEFont(pWidget->GetDoc())); + m_pTextOut->SetFontSize(pNode->GetFontSize()); + m_pTextOut->SetTextColor(pNode->GetTextColor()); + if (!pParams) + return; + + m_pTextOut->SetAlignment(pParams->m_iTTOAlign); + m_pTextOut->SetStyles(pParams->m_dwTTOStyles); + m_pTextOut->CalcLogicSize(pParams->m_wsText, rect); +} + +CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(CFWL_Widget* pWidget) const { + switch (pWidget->GetClassID()) { + case FWL_Type::CheckBox: + return m_pCheckBoxTP.get(); + case FWL_Type::ListBox: + return m_pListBoxTP.get(); + case FWL_Type::PictureBox: + return m_pPictureBoxTP.get(); + case FWL_Type::ScrollBar: + return m_pSrollBarTP.get(); + case FWL_Type::Edit: + return m_pEditTP.get(); + case FWL_Type::ComboBox: + return m_pComboBoxTP.get(); + case FWL_Type::MonthCalendar: + return m_pMonthCalendarTP.get(); + case FWL_Type::DateTimePicker: + return m_pDateTimePickerTP.get(); + case FWL_Type::PushButton: + return m_pPushButtonTP.get(); + case FWL_Type::Caret: + return m_pCaretTP.get(); + case FWL_Type::Barcode: + return m_pBarcodeTP.get(); + default: + return nullptr; + } +} diff --git a/xfa/fxfa/cxfa_fwltheme.h b/xfa/fxfa/cxfa_fwltheme.h new file mode 100644 index 0000000000000000000000000000000000000000..bdab7cfdc5070bca76185a5cd4aae089d19d02d7 --- /dev/null +++ b/xfa/fxfa/cxfa_fwltheme.h @@ -0,0 +1,69 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_FWLTHEME_H_ +#define XFA_FXFA_CXFA_FWLTHEME_H_ + +#include <memory> + +#include "xfa/fwl/ifwl_themeprovider.h" +#include "xfa/fwl/theme/cfwl_barcodetp.h" +#include "xfa/fwl/theme/cfwl_carettp.h" +#include "xfa/fwl/theme/cfwl_checkboxtp.h" +#include "xfa/fwl/theme/cfwl_comboboxtp.h" +#include "xfa/fwl/theme/cfwl_datetimepickertp.h" +#include "xfa/fwl/theme/cfwl_edittp.h" +#include "xfa/fwl/theme/cfwl_listboxtp.h" +#include "xfa/fwl/theme/cfwl_monthcalendartp.h" +#include "xfa/fwl/theme/cfwl_pictureboxtp.h" +#include "xfa/fwl/theme/cfwl_pushbuttontp.h" +#include "xfa/fwl/theme/cfwl_scrollbartp.h" +#include "xfa/fwl/theme/cfwl_widgettp.h" +#include "xfa/fxfa/cxfa_ffapp.h" + +class CXFA_FWLTheme final : public IFWL_ThemeProvider { + public: + explicit CXFA_FWLTheme(CXFA_FFApp* pApp); + ~CXFA_FWLTheme() override; + + // IFWL_ThemeProvider: + void DrawBackground(CFWL_ThemeBackground* pParams) override; + void DrawText(CFWL_ThemeText* pParams) override; + void CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) override; + float GetCXBorderSize() const override; + float GetCYBorderSize() const override; + CFX_RectF GetUIMargin(CFWL_ThemePart* pThemePart) const override; + float GetFontSize(CFWL_ThemePart* pThemePart) const override; + RetainPtr<CFGAS_GEFont> GetFont(CFWL_ThemePart* pThemePart) const override; + float GetLineHeight(CFWL_ThemePart* pThemePart) const override; + float GetScrollBarWidth() const override; + FX_COLORREF GetTextColor(CFWL_ThemePart* pThemePart) const override; + CFX_SizeF GetSpaceAboveBelow(CFWL_ThemePart* pThemePart) const override; + + private: + CFWL_WidgetTP* GetTheme(CFWL_Widget* pWidget) const; + + std::unique_ptr<CFWL_CheckBoxTP> m_pCheckBoxTP; + std::unique_ptr<CFWL_ListBoxTP> m_pListBoxTP; + std::unique_ptr<CFWL_PictureBoxTP> m_pPictureBoxTP; + std::unique_ptr<CFWL_ScrollBarTP> m_pSrollBarTP; + std::unique_ptr<CFWL_EditTP> m_pEditTP; + std::unique_ptr<CFWL_ComboBoxTP> m_pComboBoxTP; + std::unique_ptr<CFWL_MonthCalendarTP> m_pMonthCalendarTP; + std::unique_ptr<CFWL_DateTimePickerTP> m_pDateTimePickerTP; + std::unique_ptr<CFWL_PushButtonTP> m_pPushButtonTP; + std::unique_ptr<CFWL_CaretTP> m_pCaretTP; + std::unique_ptr<CFWL_BarcodeTP> m_pBarcodeTP; + std::unique_ptr<CFDE_TextOut> m_pTextOut; + RetainPtr<CFGAS_GEFont> m_pCalendarFont; + WideString m_wsResource; + UnownedPtr<CXFA_FFApp> const m_pApp; + CFX_RectF m_Rect; +}; + +CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget); + +#endif // XFA_FXFA_CXFA_FWLTHEME_H_ diff --git a/xfa/fxfa/cxfa_imagerenderer.cpp b/xfa/fxfa/cxfa_imagerenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6cb5e9317eacbad067510edff4b107b3db59a6a --- /dev/null +++ b/xfa/fxfa/cxfa_imagerenderer.cpp @@ -0,0 +1,158 @@ +// Copyright 2018 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_imagerenderer.h" + +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/dib/cfx_dibsource.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/dib/cfx_imagetransformer.h" +#include "third_party/base/ptr_util.h" + +CXFA_ImageRenderer::CXFA_ImageRenderer( + CFX_RenderDevice* pDevice, + const RetainPtr<CFX_DIBSource>& pDIBSource, + const CFX_Matrix* pImage2Device) + : m_pDevice(pDevice), + m_ImageMatrix(*pImage2Device), + m_pDIBSource(pDIBSource) {} + +CXFA_ImageRenderer::~CXFA_ImageRenderer() {} + +bool CXFA_ImageRenderer::Start() { + if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, 255, 0, &m_ImageMatrix, + FXDIB_INTERPOL, &m_DeviceHandle, + FXDIB_BLEND_NORMAL)) { + if (m_DeviceHandle) { + m_Status = 3; + return true; + } + return false; + } + CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); + FX_RECT image_rect = image_rect_f.GetOuterRect(); + int dest_width = image_rect.Width(); + int dest_height = image_rect.Height(); + if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || + (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { + RetainPtr<CFX_DIBSource> pDib = m_pDIBSource; + if (m_pDIBSource->HasAlpha() && + !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) && + !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { + m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb); + if (!m_pCloneConvert) + return false; + + pDib = m_pCloneConvert; + } + FX_RECT clip_box = m_pDevice->GetClipBox(); + clip_box.Intersect(image_rect); + m_Status = 2; + m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>( + pDib, &m_ImageMatrix, FXDIB_INTERPOL, &clip_box); + return true; + } + if (m_ImageMatrix.a < 0) + dest_width = -dest_width; + if (m_ImageMatrix.d > 0) + dest_height = -dest_height; + int dest_left, dest_top; + dest_left = dest_width > 0 ? image_rect.left : image_rect.right; + dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; + if (m_pDIBSource->IsOpaqueImage()) { + if (m_pDevice->StretchDIBitsWithFlagsAndBlend( + m_pDIBSource, dest_left, dest_top, dest_width, dest_height, + FXDIB_INTERPOL, FXDIB_BLEND_NORMAL)) { + return false; + } + } + if (m_pDIBSource->IsAlphaMask()) { + if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top, + dest_width, dest_height, 0, + FXDIB_INTERPOL)) { + return false; + } + } + + FX_RECT clip_box = m_pDevice->GetClipBox(); + FX_RECT dest_rect = clip_box; + dest_rect.Intersect(image_rect); + FX_RECT dest_clip( + dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, + dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); + RetainPtr<CFX_DIBitmap> pStretched = m_pDIBSource->StretchTo( + dest_width, dest_height, FXDIB_INTERPOL, &dest_clip); + if (pStretched) + CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top); + + return false; +} + +bool CXFA_ImageRenderer::Continue() { + if (m_Status == 2) { + if (m_pTransformer->Continue(nullptr)) + return true; + + RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap(); + if (!pBitmap) + return false; + + if (pBitmap->IsAlphaMask()) { + m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left, + m_pTransformer->result().top, 0); + } else { + m_pDevice->SetDIBitsWithBlend(pBitmap, m_pTransformer->result().left, + m_pTransformer->result().top, + FXDIB_BLEND_NORMAL); + } + return false; + } + if (m_Status == 3) + return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), nullptr); + + return false; +} + +void CXFA_ImageRenderer::CompositeDIBitmap( + const RetainPtr<CFX_DIBitmap>& pDIBitmap, + int left, + int top) { + if (!pDIBitmap) + return; + + if (!pDIBitmap->IsAlphaMask()) { + if (m_pDevice->SetDIBits(pDIBitmap, left, top)) + return; + } else if (m_pDevice->SetBitMask(pDIBitmap, left, top, 0)) { + return; + } + + bool bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || + (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && + (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)); + if (bGetBackGround) { + if (pDIBitmap->IsAlphaMask()) + return; + + m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, FXDIB_BLEND_NORMAL); + return; + } + if (!pDIBitmap->HasAlpha() || + (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { + return; + } + + RetainPtr<CFX_DIBitmap> pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb); + if (!pCloneConvert) + return; + + CXFA_ImageRenderer imageRender(m_pDevice, pCloneConvert, &m_ImageMatrix); + if (!imageRender.Start()) + return; + + while (imageRender.Continue()) + continue; +} diff --git a/xfa/fxfa/cxfa_imagerenderer.h b/xfa/fxfa/cxfa_imagerenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..8ed9ab0c75a5a2dc1fa2d6677f7f2a84c50ccb55 --- /dev/null +++ b/xfa/fxfa/cxfa_imagerenderer.h @@ -0,0 +1,46 @@ +// Copyright 2018 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_IMAGERENDERER_H_ +#define XFA_FXFA_CXFA_IMAGERENDERER_H_ + +#include <memory> + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/fx_dib.h" + +class CFX_RenderDevice; +class CFX_DIBSource; +class CFX_DIBitmap; +class CFX_ImageTransformer; +class CFX_ImageRenderer; + +class CXFA_ImageRenderer { + public: + CXFA_ImageRenderer(CFX_RenderDevice* pDevice, + const RetainPtr<CFX_DIBSource>& pDIBSource, + const CFX_Matrix* pImage2Device); + ~CXFA_ImageRenderer(); + + bool Start(); + bool Continue(); + + private: + void CompositeDIBitmap(const RetainPtr<CFX_DIBitmap>& pDIBitmap, + int left, + int top); + + CFX_RenderDevice* m_pDevice; + int m_Status = 0; + CFX_Matrix m_ImageMatrix; + RetainPtr<CFX_DIBSource> m_pDIBSource; + RetainPtr<CFX_DIBitmap> m_pCloneConvert; + std::unique_ptr<CFX_ImageTransformer> m_pTransformer; + std::unique_ptr<CFX_ImageRenderer> m_DeviceHandle; +}; + +#endif // XFA_FXFA_CXFA_IMAGERENDERER_H_ diff --git a/xfa/fxfa/app/cxfa_linkuserdata.cpp b/xfa/fxfa/cxfa_linkuserdata.cpp similarity index 76% rename from xfa/fxfa/app/cxfa_linkuserdata.cpp rename to xfa/fxfa/cxfa_linkuserdata.cpp index 4128cd882203f34585d93bade57ac38144e4f492..c32b74664cf91e081ba582f4dbdc3713e05ab600 100644 --- a/xfa/fxfa/app/cxfa_linkuserdata.cpp +++ b/xfa/fxfa/cxfa_linkuserdata.cpp @@ -4,9 +4,9 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/app/cxfa_linkuserdata.h" +#include "xfa/fxfa/cxfa_linkuserdata.h" -CXFA_LinkUserData::CXFA_LinkUserData(FX_WCHAR* pszText) +CXFA_LinkUserData::CXFA_LinkUserData(wchar_t* pszText) : m_wsURLContent(pszText) {} CXFA_LinkUserData::~CXFA_LinkUserData() {} diff --git a/xfa/fxfa/cxfa_linkuserdata.h b/xfa/fxfa/cxfa_linkuserdata.h new file mode 100644 index 0000000000000000000000000000000000000000..3d0f95e91c18e8e2b26330b83ca6922554830b69 --- /dev/null +++ b/xfa/fxfa/cxfa_linkuserdata.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_LINKUSERDATA_H_ +#define XFA_FXFA_CXFA_LINKUSERDATA_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" + +class CXFA_LinkUserData : public Retainable { + public: + template <typename T, typename... Args> + friend RetainPtr<T> pdfium::MakeRetain(Args&&... args); + + const wchar_t* GetLinkURL() const { return m_wsURLContent.c_str(); } + + private: + explicit CXFA_LinkUserData(wchar_t* pszText); + ~CXFA_LinkUserData() override; + + WideString m_wsURLContent; +}; + +#endif // XFA_FXFA_CXFA_LINKUSERDATA_H_ diff --git a/xfa/fxfa/app/cxfa_loadercontext.cpp b/xfa/fxfa/cxfa_loadercontext.cpp similarity index 85% rename from xfa/fxfa/app/cxfa_loadercontext.cpp rename to xfa/fxfa/cxfa_loadercontext.cpp index 0733c52dfcc3beade5261949f89feb40ceeafc25..05ba9f19d1b253d6d427b8512c5328d8e88da4d8 100644 --- a/xfa/fxfa/app/cxfa_loadercontext.cpp +++ b/xfa/fxfa/cxfa_loadercontext.cpp @@ -4,7 +4,7 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/app/cxfa_loadercontext.h" +#include "xfa/fxfa/cxfa_loadercontext.h" CXFA_LoaderContext::CXFA_LoaderContext() : m_bSaveLineHeight(false), @@ -14,8 +14,8 @@ CXFA_LoaderContext::CXFA_LoaderContext() m_fStartLineOffset(0), m_iChar(0), m_iTotalLines(-1), + m_dwFlags(0), m_pXMLNode(nullptr), - m_pNode(nullptr), - m_dwFlags(0) {} + m_pNode(nullptr) {} CXFA_LoaderContext::~CXFA_LoaderContext() {} diff --git a/xfa/fxfa/cxfa_loadercontext.h b/xfa/fxfa/cxfa_loadercontext.h new file mode 100644 index 0000000000000000000000000000000000000000..06e3f117d886f8700a54426b50b07cd7e2de1a33 --- /dev/null +++ b/xfa/fxfa/cxfa_loadercontext.h @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_LOADERCONTEXT_H_ +#define XFA_FXFA_CXFA_LOADERCONTEXT_H_ + +#include <vector> + +#include "core/fxcrt/css/cfx_csscomputedstyle.h" +#include "core/fxcrt/fx_system.h" + +class CFX_XMLNode; +class CXFA_Node; + +class CXFA_LoaderContext { + public: + CXFA_LoaderContext(); + ~CXFA_LoaderContext(); + + bool m_bSaveLineHeight; + float m_fWidth; + float m_fHeight; + float m_fLastPos; + float m_fStartLineOffset; + int32_t m_iChar; + int32_t m_iLines; + int32_t m_iTotalLines; + uint32_t m_dwFlags; + CFX_XMLNode* m_pXMLNode; + CXFA_Node* m_pNode; + RetainPtr<CFX_CSSComputedStyle> m_pParentStyle; + std::vector<float> m_lineHeights; + std::vector<float> m_BlocksHeight; +}; + +#endif // XFA_FXFA_CXFA_LOADERCONTEXT_H_ diff --git a/xfa/fxfa/app/cxfa_pieceline.cpp b/xfa/fxfa/cxfa_pieceline.cpp similarity index 79% rename from xfa/fxfa/app/cxfa_pieceline.cpp rename to xfa/fxfa/cxfa_pieceline.cpp index b906cf26e371946bcf26a1cd6b5ee8365f706aab..6570ad59ec137e11a632f82cbd0fbb7ecb3b94ae 100644 --- a/xfa/fxfa/app/cxfa_pieceline.cpp +++ b/xfa/fxfa/cxfa_pieceline.cpp @@ -4,9 +4,9 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/app/cxfa_pieceline.h" +#include "xfa/fxfa/cxfa_pieceline.h" -#include "xfa/fxfa/app/xfa_textpiece.h" +#include "xfa/fxfa/cxfa_textpiece.h" CXFA_PieceLine::CXFA_PieceLine() {} diff --git a/xfa/fxfa/cxfa_pieceline.h b/xfa/fxfa/cxfa_pieceline.h new file mode 100644 index 0000000000000000000000000000000000000000..dc95e73175cabfdfcafa3b7bd59d44f706271d96 --- /dev/null +++ b/xfa/fxfa/cxfa_pieceline.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_PIECELINE_H_ +#define XFA_FXFA_CXFA_PIECELINE_H_ + +#include <memory> +#include <vector> + +class CXFA_TextPiece; + +class CXFA_PieceLine { + public: + CXFA_PieceLine(); + ~CXFA_PieceLine(); + + std::vector<std::unique_ptr<CXFA_TextPiece>> m_textPieces; + std::vector<int32_t> m_charCounts; +}; + +#endif // XFA_FXFA_CXFA_PIECELINE_H_ diff --git a/xfa/fxfa/cxfa_rendercontext.cpp b/xfa/fxfa/cxfa_rendercontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6667d4606835220de377d9dab9329baa8a937308 --- /dev/null +++ b/xfa/fxfa/cxfa_rendercontext.cpp @@ -0,0 +1,37 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_rendercontext.h" + +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +CXFA_RenderContext::CXFA_RenderContext(CXFA_FFPageView* pPageView, + const CFX_RectF& clipRect, + const CFX_Matrix& matrix) + : m_pWidget(nullptr), m_matrix(matrix), m_rtClipRect(clipRect) { + matrix.GetInverse().TransformRect(m_rtClipRect); + + m_pWidgetIterator = pPageView->CreateWidgetIterator( + XFA_TRAVERSEWAY_Form, + XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable); + m_pWidget = m_pWidgetIterator->MoveToNext(); +} + +CXFA_RenderContext::~CXFA_RenderContext() {} + +void CXFA_RenderContext::DoRender(CXFA_Graphics* gs) { + while (m_pWidget) { + CFX_RectF rtWidgetBox = m_pWidget->GetBBox(XFA_WidgetStatus_Visible); + rtWidgetBox.width += 1; + rtWidgetBox.height += 1; + if (rtWidgetBox.IntersectWith(m_rtClipRect)) + m_pWidget->RenderWidget(gs, m_matrix, XFA_WidgetStatus_Highlight); + + m_pWidget = m_pWidgetIterator->MoveToNext(); + } +} diff --git a/xfa/fxfa/cxfa_rendercontext.h b/xfa/fxfa/cxfa_rendercontext.h new file mode 100644 index 0000000000000000000000000000000000000000..411830d87a08e9324796647bc7a371998993de1d --- /dev/null +++ b/xfa/fxfa/cxfa_rendercontext.h @@ -0,0 +1,32 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_RENDERCONTEXT_H_ +#define XFA_FXFA_CXFA_RENDERCONTEXT_H_ + +#include <memory> + +#include "xfa/fxfa/fxfa.h" + +class CXFA_Graphics; + +class CXFA_RenderContext { + public: + CXFA_RenderContext(CXFA_FFPageView* pPageView, + const CFX_RectF& clipRect, + const CFX_Matrix& matrix); + ~CXFA_RenderContext(); + + void DoRender(CXFA_Graphics* gs); + + private: + std::unique_ptr<IXFA_WidgetIterator> m_pWidgetIterator; + CXFA_FFWidget* m_pWidget; + CFX_Matrix m_matrix; + CFX_RectF m_rtClipRect; +}; + +#endif // XFA_FXFA_CXFA_RENDERCONTEXT_H_ diff --git a/xfa/fxfa/cxfa_textlayout.cpp b/xfa/fxfa/cxfa_textlayout.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ebb9e8aa2c0f812f872fccf4aba48288a7a57960 --- /dev/null +++ b/xfa/fxfa/cxfa_textlayout.cpp @@ -0,0 +1,1298 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_textlayout.h" + +#include <algorithm> +#include <utility> + +#include "core/fxcrt/css/cfx_csscomputedstyle.h" +#include "core/fxcrt/css/cfx_cssstyleselector.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fde/cfde_textout.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fxfa/cxfa_linkuserdata.h" +#include "xfa/fxfa/cxfa_loadercontext.h" +#include "xfa/fxfa/cxfa_pieceline.h" +#include "xfa/fxfa/cxfa_textparsecontext.h" +#include "xfa/fxfa/cxfa_textpiece.h" +#include "xfa/fxfa/cxfa_textprovider.h" +#include "xfa/fxfa/cxfa_texttabstopscontext.h" +#include "xfa/fxfa/cxfa_textuserdata.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_para.h" + +#define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001 + +CXFA_TextLayout::CXFA_TextLayout(CXFA_FFDoc* doc, + CXFA_TextProvider* pTextProvider) + : m_bHasBlock(false), + m_pDoc(doc), + m_pTextProvider(pTextProvider), + m_pTextDataNode(nullptr), + m_bRichText(false), + m_iLines(0), + m_fMaxWidth(0), + m_bBlockContinue(true) { + ASSERT(m_pTextProvider); +} + +CXFA_TextLayout::~CXFA_TextLayout() { + m_textParser.Reset(); + Unload(); +} + +void CXFA_TextLayout::Unload() { + m_pieceLines.clear(); + m_pBreak.reset(); +} + +void CXFA_TextLayout::GetTextDataNode() { + if (!m_pTextProvider) + return; + + CXFA_Node* pNode = m_pTextProvider->GetTextNode(m_bRichText); + if (pNode && m_bRichText) + m_textParser.Reset(); + + m_pTextDataNode = pNode; +} + +CFX_XMLNode* CXFA_TextLayout::GetXMLContainerNode() { + if (!m_bRichText) + return nullptr; + + CFX_XMLNode* pXMLRoot = m_pTextDataNode->GetXMLMappingNode(); + if (!pXMLRoot) + return nullptr; + + CFX_XMLNode* pXMLContainer = nullptr; + for (CFX_XMLNode* pXMLChild = pXMLRoot->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLChild; + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pXMLChild->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLChild); + WideString wsTag = pXMLElement->GetLocalTagName(); + if (wsTag == L"body" || wsTag == L"html") { + pXMLContainer = pXMLChild; + break; + } + } + } + return pXMLContainer; +} + +std::unique_ptr<CFX_RTFBreak> CXFA_TextLayout::CreateBreak(bool bDefault) { + uint32_t dwStyle = FX_LAYOUTSTYLE_ExpandTab; + if (!bDefault) + dwStyle |= FX_LAYOUTSTYLE_Pagination; + + auto pBreak = pdfium::MakeUnique<CFX_RTFBreak>(dwStyle); + pBreak->SetLineBreakTolerance(1); + pBreak->SetFont(m_textParser.GetFont(m_pDoc, m_pTextProvider, nullptr)); + pBreak->SetFontSize(m_textParser.GetFontSize(m_pTextProvider, nullptr)); + return pBreak; +} + +void CXFA_TextLayout::InitBreak(float fLineWidth) { + CXFA_Para* para = m_pTextProvider->GetParaIfExists(); + float fStart = 0; + float fStartPos = 0; + if (para) { + CFX_RTFLineAlignment iAlign = CFX_RTFLineAlignment::Left; + switch (para->GetHorizontalAlign()) { + case XFA_AttributeEnum::Center: + iAlign = CFX_RTFLineAlignment::Center; + break; + case XFA_AttributeEnum::Right: + iAlign = CFX_RTFLineAlignment::Right; + break; + case XFA_AttributeEnum::Justify: + iAlign = CFX_RTFLineAlignment::Justified; + break; + case XFA_AttributeEnum::JustifyAll: + iAlign = CFX_RTFLineAlignment::Distributed; + break; + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Radix: + break; + default: + NOTREACHED(); + break; + } + m_pBreak->SetAlignment(iAlign); + + fStart = para->GetMarginLeft(); + if (m_pTextProvider->IsCheckButtonAndAutoWidth()) { + if (iAlign != CFX_RTFLineAlignment::Left) + fLineWidth -= para->GetMarginRight(); + } else { + fLineWidth -= para->GetMarginRight(); + } + if (fLineWidth < 0) + fLineWidth = fStart; + + fStartPos = fStart; + float fIndent = para->GetTextIndent(); + if (fIndent > 0) + fStartPos += fIndent; + } + + m_pBreak->SetLineBoundary(fStart, fLineWidth); + m_pBreak->SetLineStartPos(fStartPos); + + CXFA_Font* font = m_pTextProvider->GetFontIfExists(); + if (font) { + m_pBreak->SetHorizontalScale( + static_cast<int32_t>(font->GetHorizontalScale())); + m_pBreak->SetVerticalScale(static_cast<int32_t>(font->GetVerticalScale())); + m_pBreak->SetCharSpace(font->GetLetterSpacing()); + } + + float fFontSize = m_textParser.GetFontSize(m_pTextProvider, nullptr); + m_pBreak->SetFontSize(fFontSize); + m_pBreak->SetFont(m_textParser.GetFont(m_pDoc, m_pTextProvider, nullptr)); + m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f); +} + +void CXFA_TextLayout::InitBreak(CFX_CSSComputedStyle* pStyle, + CFX_CSSDisplay eDisplay, + float fLineWidth, + CFX_XMLNode* pXMLNode, + CFX_CSSComputedStyle* pParentStyle) { + if (!pStyle) { + InitBreak(fLineWidth); + return; + } + + if (eDisplay == CFX_CSSDisplay::Block || + eDisplay == CFX_CSSDisplay::ListItem) { + CFX_RTFLineAlignment iAlign = CFX_RTFLineAlignment::Left; + switch (pStyle->GetTextAlign()) { + case CFX_CSSTextAlign::Right: + iAlign = CFX_RTFLineAlignment::Right; + break; + case CFX_CSSTextAlign::Center: + iAlign = CFX_RTFLineAlignment::Center; + break; + case CFX_CSSTextAlign::Justify: + iAlign = CFX_RTFLineAlignment::Justified; + break; + case CFX_CSSTextAlign::JustifyAll: + iAlign = CFX_RTFLineAlignment::Distributed; + break; + default: + break; + } + m_pBreak->SetAlignment(iAlign); + + float fStart = 0; + const CFX_CSSRect* pRect = pStyle->GetMarginWidth(); + const CFX_CSSRect* pPaddingRect = pStyle->GetPaddingWidth(); + if (pRect) { + fStart = pRect->left.GetValue(); + fLineWidth -= pRect->right.GetValue(); + if (pPaddingRect) { + fStart += pPaddingRect->left.GetValue(); + fLineWidth -= pPaddingRect->right.GetValue(); + } + if (eDisplay == CFX_CSSDisplay::ListItem) { + const CFX_CSSRect* pParRect = pParentStyle->GetMarginWidth(); + const CFX_CSSRect* pParPaddingRect = pParentStyle->GetPaddingWidth(); + if (pParRect) { + fStart += pParRect->left.GetValue(); + fLineWidth -= pParRect->right.GetValue(); + if (pParPaddingRect) { + fStart += pParPaddingRect->left.GetValue(); + fLineWidth -= pParPaddingRect->right.GetValue(); + } + } + CFX_CSSRect pNewRect; + pNewRect.left.Set(CFX_CSSLengthUnit::Point, fStart); + pNewRect.right.Set(CFX_CSSLengthUnit::Point, pRect->right.GetValue()); + pNewRect.top.Set(CFX_CSSLengthUnit::Point, pRect->top.GetValue()); + pNewRect.bottom.Set(CFX_CSSLengthUnit::Point, pRect->bottom.GetValue()); + pStyle->SetMarginWidth(pNewRect); + } + } + m_pBreak->SetLineBoundary(fStart, fLineWidth); + float fIndent = pStyle->GetTextIndent().GetValue(); + if (fIndent > 0) + fStart += fIndent; + + m_pBreak->SetLineStartPos(fStart); + m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle)); + if (!m_pTabstopContext) + m_pTabstopContext = pdfium::MakeUnique<CXFA_TextTabstopsContext>(); + m_textParser.GetTabstops(pStyle, m_pTabstopContext.get()); + for (const auto& stop : m_pTabstopContext->m_tabstops) + m_pBreak->AddPositionedTab(stop.fTabstops); + } + float fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle); + m_pBreak->SetFontSize(fFontSize); + m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f); + m_pBreak->SetFont(m_textParser.GetFont(m_pDoc, m_pTextProvider, pStyle)); + m_pBreak->SetHorizontalScale( + m_textParser.GetHorScale(m_pTextProvider, pStyle, pXMLNode)); + m_pBreak->SetVerticalScale(m_textParser.GetVerScale(m_pTextProvider, pStyle)); + m_pBreak->SetCharSpace(pStyle->GetLetterSpacing().GetValue()); +} + +float CXFA_TextLayout::GetLayoutHeight() { + if (!m_pLoader) + return 0; + + if (m_pLoader->m_lineHeights.empty() && m_pLoader->m_fWidth > 0) { + CFX_SizeF szMax(m_pLoader->m_fWidth, m_pLoader->m_fHeight); + m_pLoader->m_bSaveLineHeight = true; + m_pLoader->m_fLastPos = 0; + CFX_SizeF szDef = CalcSize(szMax, szMax); + m_pLoader->m_bSaveLineHeight = false; + return szDef.height; + } + + float fHeight = m_pLoader->m_fHeight; + if (fHeight < 0.1f) { + fHeight = 0; + for (float value : m_pLoader->m_lineHeights) + fHeight += value; + } + return fHeight; +} + +float CXFA_TextLayout::StartLayout(float fWidth) { + if (!m_pLoader) + m_pLoader = pdfium::MakeUnique<CXFA_LoaderContext>(); + + if (fWidth < 0 || + (m_pLoader->m_fWidth > -1 && fabs(fWidth - m_pLoader->m_fWidth) > 0)) { + m_pLoader->m_lineHeights.clear(); + m_Blocks.clear(); + Unload(); + m_pLoader->m_fStartLineOffset = 0; + } + m_pLoader->m_fWidth = fWidth; + + if (fWidth >= 0) + return fWidth; + + CFX_SizeF szMax; + + m_pLoader->m_bSaveLineHeight = true; + m_pLoader->m_fLastPos = 0; + CFX_SizeF szDef = CalcSize(szMax, szMax); + m_pLoader->m_bSaveLineHeight = false; + return szDef.width; +} + +float CXFA_TextLayout::DoLayout(int32_t iBlockIndex, + float fCalcHeight, + float fContentAreaHeight, + float fTextHeight) { + if (!m_pLoader) + return fCalcHeight; + + int32_t iBlockCount = pdfium::CollectionSize<int32_t>(m_Blocks); + float fHeight = fTextHeight; + if (fHeight < 0) + fHeight = GetLayoutHeight(); + + m_pLoader->m_fHeight = fHeight; + if (fContentAreaHeight < 0) + return fCalcHeight; + + m_bHasBlock = true; + if (iBlockCount == 0 && fHeight > 0) { + fHeight = fTextHeight - GetLayoutHeight(); + if (fHeight > 0) { + XFA_AttributeEnum iAlign = m_textParser.GetVAlign(m_pTextProvider); + if (iAlign == XFA_AttributeEnum::Middle) + fHeight /= 2.0f; + else if (iAlign != XFA_AttributeEnum::Bottom) + fHeight = 0; + m_pLoader->m_fStartLineOffset = fHeight; + } + } + + float fLinePos = m_pLoader->m_fStartLineOffset; + int32_t iLineIndex = 0; + if (iBlockCount > 1) { + if (iBlockCount >= (iBlockIndex + 1) * 2) { + iLineIndex = m_Blocks[iBlockIndex * 2]; + } else { + iLineIndex = m_Blocks[iBlockCount - 1] + m_Blocks[iBlockCount - 2]; + } + if (!m_pLoader->m_BlocksHeight.empty()) { + for (int32_t i = 0; i < iBlockIndex; i++) + fLinePos -= m_pLoader->m_BlocksHeight[i * 2 + 1]; + } + } + + int32_t iCount = pdfium::CollectionSize<int32_t>(m_pLoader->m_lineHeights); + int32_t i = 0; + for (i = iLineIndex; i < iCount; i++) { + float fLineHeight = m_pLoader->m_lineHeights[i]; + if (i == iLineIndex && fLineHeight - fContentAreaHeight > 0.001) + return 0; + + if (fLinePos + fLineHeight - fContentAreaHeight > 0.001) { + if (iBlockCount >= (iBlockIndex + 1) * 2) { + m_Blocks[iBlockIndex * 2] = iLineIndex; + m_Blocks[iBlockIndex * 2 + 1] = i - iLineIndex; + } else { + m_Blocks.push_back(iLineIndex); + m_Blocks.push_back(i - iLineIndex); + } + if (i == iLineIndex) { + if (fCalcHeight <= fLinePos) { + if (pdfium::CollectionSize<int32_t>(m_pLoader->m_BlocksHeight) > + iBlockIndex * 2 && + (m_pLoader->m_BlocksHeight[iBlockIndex * 2] == iBlockIndex)) { + m_pLoader->m_BlocksHeight[iBlockIndex * 2 + 1] = fCalcHeight; + } else { + m_pLoader->m_BlocksHeight.push_back((float)iBlockIndex); + m_pLoader->m_BlocksHeight.push_back(fCalcHeight); + } + } + return fCalcHeight; + } + return fLinePos; + } + fLinePos += fLineHeight; + } + return fCalcHeight; +} + +int32_t CXFA_TextLayout::CountBlocks() const { + int32_t iCount = pdfium::CollectionSize<int32_t>(m_Blocks) / 2; + return iCount > 0 ? iCount : 1; +} + +CFX_SizeF CXFA_TextLayout::CalcSize(const CFX_SizeF& minSize, + const CFX_SizeF& maxSize) { + float width = maxSize.width; + if (width < 1) + width = 0xFFFF; + + m_pBreak = CreateBreak(false); + float fLinePos = 0; + m_iLines = 0; + m_fMaxWidth = 0; + Loader(width, fLinePos, false); + if (fLinePos < 0.1f) + fLinePos = m_textParser.GetFontSize(m_pTextProvider, nullptr); + + m_pTabstopContext.reset(); + return CFX_SizeF(m_fMaxWidth, fLinePos); +} + +float CXFA_TextLayout::Layout(const CFX_SizeF& size) { + if (size.width < 1) + return 0.f; + + Unload(); + m_pBreak = CreateBreak(true); + if (m_pLoader) { + m_pLoader->m_iTotalLines = -1; + m_pLoader->m_iChar = 0; + } + + m_iLines = 0; + float fLinePos = 0; + Loader(size.width, fLinePos, true); + UpdateAlign(size.height, fLinePos); + m_pTabstopContext.reset(); + return fLinePos; +} + +bool CXFA_TextLayout::Layout(int32_t iBlock) { + if (!m_pLoader || iBlock < 0 || iBlock >= CountBlocks()) + return false; + if (m_pLoader->m_fWidth < 1) + return false; + + m_pLoader->m_iTotalLines = -1; + m_iLines = 0; + float fLinePos = 0; + CXFA_Node* pNode = nullptr; + CFX_SizeF szText(m_pLoader->m_fWidth, m_pLoader->m_fHeight); + int32_t iCount = pdfium::CollectionSize<int32_t>(m_Blocks); + int32_t iBlocksHeightCount = + pdfium::CollectionSize<int32_t>(m_pLoader->m_BlocksHeight); + iBlocksHeightCount /= 2; + if (iBlock < iBlocksHeightCount) + return true; + if (iBlock == iBlocksHeightCount) { + Unload(); + m_pBreak = CreateBreak(true); + fLinePos = m_pLoader->m_fStartLineOffset; + for (int32_t i = 0; i < iBlocksHeightCount; i++) + fLinePos -= m_pLoader->m_BlocksHeight[i * 2 + 1]; + + m_pLoader->m_iChar = 0; + if (iCount > 1) + m_pLoader->m_iTotalLines = m_Blocks[iBlock * 2 + 1]; + + Loader(szText.width, fLinePos, true); + if (iCount == 0 && m_pLoader->m_fStartLineOffset < 0.1f) + UpdateAlign(szText.height, fLinePos); + } else if (m_pTextDataNode) { + iBlock *= 2; + if (iBlock < iCount - 2) + m_pLoader->m_iTotalLines = m_Blocks[iBlock + 1]; + + m_pBreak->Reset(); + if (m_bRichText) { + CFX_XMLNode* pContainerNode = GetXMLContainerNode(); + if (!pContainerNode) + return true; + + CFX_XMLNode* pXMLNode = m_pLoader->m_pXMLNode; + if (!pXMLNode) + return true; + + CFX_XMLNode* pSaveXMLNode = m_pLoader->m_pXMLNode; + for (; pXMLNode; + pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (!LoadRichText(pXMLNode, szText.width, fLinePos, + m_pLoader->m_pParentStyle, true, nullptr)) { + break; + } + } + while (!pXMLNode) { + pXMLNode = pSaveXMLNode->GetNodeItem(CFX_XMLNode::Parent); + if (pXMLNode == pContainerNode) + break; + if (!LoadRichText(pXMLNode, szText.width, fLinePos, + m_pLoader->m_pParentStyle, true, nullptr, false)) { + break; + } + pSaveXMLNode = pXMLNode; + pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling); + if (!pXMLNode) + continue; + for (; pXMLNode; + pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (!LoadRichText(pXMLNode, szText.width, fLinePos, + m_pLoader->m_pParentStyle, true, nullptr)) { + break; + } + } + } + } else { + pNode = m_pLoader->m_pNode; + if (!pNode) + return true; + LoadText(pNode, szText.width, fLinePos, true); + } + } + if (iBlock == iCount) { + m_pTabstopContext.reset(); + m_pLoader.reset(); + } + return true; +} + +void CXFA_TextLayout::ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex) { + if (!m_pLoader) + return; + + int32_t iCountHeight = + pdfium::CollectionSize<int32_t>(m_pLoader->m_lineHeights); + if (iCountHeight == 0) + return; + + bool bEndItem = true; + int32_t iBlockCount = pdfium::CollectionSize<int32_t>(m_Blocks); + float fLinePos = m_pLoader->m_fStartLineOffset; + int32_t iLineIndex = 0; + if (iBlockIndex > 0) { + int32_t iBlockHeightCount = + pdfium::CollectionSize<int32_t>(m_pLoader->m_BlocksHeight); + iBlockHeightCount /= 2; + if (iBlockHeightCount >= iBlockIndex) { + for (int32_t i = 0; i < iBlockIndex; i++) + fLinePos -= m_pLoader->m_BlocksHeight[i * 2 + 1]; + } else { + fLinePos = 0; + } + iLineIndex = m_Blocks[iBlockCount - 1] + m_Blocks[iBlockCount - 2]; + } + + int32_t i = 0; + for (i = iLineIndex; i < iCountHeight; i++) { + float fLineHeight = m_pLoader->m_lineHeights[i]; + if (fLinePos + fLineHeight - rtText.height > 0.001) { + m_Blocks.push_back(iLineIndex); + m_Blocks.push_back(i - iLineIndex); + bEndItem = false; + break; + } + fLinePos += fLineHeight; + } + if (iCountHeight > 0 && (i - iLineIndex) > 0 && bEndItem) { + m_Blocks.push_back(iLineIndex); + m_Blocks.push_back(i - iLineIndex); + } +} + +bool CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice, + const CFX_Matrix& tmDoc2Device, + const CFX_RectF& rtClip, + int32_t iBlock) { + if (!pFxDevice) + return false; + + pFxDevice->SaveState(); + pFxDevice->SetClip_Rect(rtClip); + + if (m_pieceLines.empty()) { + int32_t iBlockCount = CountBlocks(); + for (int32_t i = 0; i < iBlockCount; i++) + Layout(i); + } + + FXTEXT_CHARPOS* pCharPos = nullptr; + int32_t iCharCount = 0; + int32_t iLineStart = 0; + int32_t iPieceLines = pdfium::CollectionSize<int32_t>(m_pieceLines); + int32_t iCount = pdfium::CollectionSize<int32_t>(m_Blocks); + if (iCount > 0) { + iBlock *= 2; + if (iBlock < iCount) { + iLineStart = m_Blocks[iBlock]; + iPieceLines = m_Blocks[iBlock + 1]; + } else { + iPieceLines = 0; + } + } + + for (int32_t i = 0; i < iPieceLines; i++) { + if (i + iLineStart >= pdfium::CollectionSize<int32_t>(m_pieceLines)) + break; + + CXFA_PieceLine* pPieceLine = m_pieceLines[i + iLineStart].get(); + int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces); + int32_t j = 0; + for (j = 0; j < iPieces; j++) { + const CXFA_TextPiece* pPiece = pPieceLine->m_textPieces[j].get(); + int32_t iChars = pPiece->iChars; + if (iCharCount < iChars) { + FX_Free(pCharPos); + pCharPos = FX_Alloc(FXTEXT_CHARPOS, iChars); + iCharCount = iChars; + } + memset(pCharPos, 0, iCharCount * sizeof(FXTEXT_CHARPOS)); + RenderString(pFxDevice, pPieceLine, j, pCharPos, tmDoc2Device); + } + for (j = 0; j < iPieces; j++) + RenderPath(pFxDevice, pPieceLine, j, pCharPos, tmDoc2Device); + } + pFxDevice->RestoreState(false); + FX_Free(pCharPos); + return iPieceLines > 0; +} + +void CXFA_TextLayout::UpdateAlign(float fHeight, float fBottom) { + fHeight -= fBottom; + if (fHeight < 0.1f) + return; + + switch (m_textParser.GetVAlign(m_pTextProvider)) { + case XFA_AttributeEnum::Middle: + fHeight /= 2.0f; + break; + case XFA_AttributeEnum::Bottom: + break; + default: + return; + } + + for (const auto& pPieceLine : m_pieceLines) { + for (const auto& pPiece : pPieceLine->m_textPieces) + pPiece->rtPiece.top += fHeight; + } +} + +bool CXFA_TextLayout::Loader(float textWidth, + float& fLinePos, + bool bSavePieces) { + GetTextDataNode(); + if (!m_pTextDataNode) + return true; + + if (m_bRichText) { + CFX_XMLNode* pXMLContainer = GetXMLContainerNode(); + if (pXMLContainer) { + if (!m_textParser.IsParsed()) + m_textParser.DoParse(pXMLContainer, m_pTextProvider); + + auto pRootStyle = m_textParser.CreateRootStyle(m_pTextProvider); + LoadRichText(pXMLContainer, textWidth, fLinePos, pRootStyle, bSavePieces, + nullptr); + } + } else { + LoadText(m_pTextDataNode, textWidth, fLinePos, bSavePieces); + } + return true; +} + +void CXFA_TextLayout::LoadText(CXFA_Node* pNode, + float textWidth, + float& fLinePos, + bool bSavePieces) { + InitBreak(textWidth); + + CXFA_Para* para = m_pTextProvider->GetParaIfExists(); + float fSpaceAbove = 0; + if (para) { + fSpaceAbove = para->GetSpaceAbove(); + if (fSpaceAbove < 0.1f) + fSpaceAbove = 0; + + switch (para->GetVerticalAlign()) { + case XFA_AttributeEnum::Top: + case XFA_AttributeEnum::Middle: + case XFA_AttributeEnum::Bottom: { + fLinePos += fSpaceAbove; + break; + } + default: + NOTREACHED(); + break; + } + } + + WideString wsText = pNode->JSObject()->GetContent(false); + wsText.TrimRight(L" "); + bool bRet = AppendChar(wsText, fLinePos, fSpaceAbove, bSavePieces); + if (bRet && m_pLoader) + m_pLoader->m_pNode = pNode; + else + EndBreak(CFX_BreakType::Paragraph, fLinePos, bSavePieces); +} + +bool CXFA_TextLayout::LoadRichText( + CFX_XMLNode* pXMLNode, + float textWidth, + float& fLinePos, + const RetainPtr<CFX_CSSComputedStyle>& pParentStyle, + bool bSavePieces, + RetainPtr<CXFA_LinkUserData> pLinkData, + bool bEndBreak, + bool bIsOl, + int32_t iLiCount) { + if (!pXMLNode) + return false; + + CXFA_TextParseContext* pContext = + m_textParser.GetParseContextFromMap(pXMLNode); + CFX_CSSDisplay eDisplay = CFX_CSSDisplay::None; + bool bContentNode = false; + float fSpaceBelow = 0; + RetainPtr<CFX_CSSComputedStyle> pStyle; + WideString wsName; + if (bEndBreak) { + bool bCurOl = false; + bool bCurLi = false; + CFX_XMLElement* pElement = nullptr; + if (pContext) { + if (m_bBlockContinue || + (m_pLoader && pXMLNode == m_pLoader->m_pXMLNode)) { + m_bBlockContinue = true; + } + if (pXMLNode->GetType() == FX_XMLNODE_Text) { + bContentNode = true; + } else if (pXMLNode->GetType() == FX_XMLNODE_Element) { + pElement = static_cast<CFX_XMLElement*>(pXMLNode); + wsName = pElement->GetLocalTagName(); + } + if (wsName == L"ol") { + bIsOl = true; + bCurOl = true; + } + if (m_bBlockContinue || bContentNode == false) { + eDisplay = pContext->GetDisplay(); + if (eDisplay != CFX_CSSDisplay::Block && + eDisplay != CFX_CSSDisplay::Inline && + eDisplay != CFX_CSSDisplay::ListItem) { + return true; + } + + pStyle = m_textParser.ComputeStyle(pXMLNode, pParentStyle.Get()); + InitBreak(bContentNode ? pParentStyle.Get() : pStyle.Get(), eDisplay, + textWidth, pXMLNode, pParentStyle.Get()); + if ((eDisplay == CFX_CSSDisplay::Block || + eDisplay == CFX_CSSDisplay::ListItem) && + pStyle && + (wsName.IsEmpty() || (wsName != L"body" && wsName != L"html" && + wsName != L"ol" && wsName != L"ul"))) { + const CFX_CSSRect* pRect = pStyle->GetMarginWidth(); + if (pRect) { + fLinePos += pRect->top.GetValue(); + fSpaceBelow = pRect->bottom.GetValue(); + } + } + + if (wsName == L"a") { + ASSERT(pElement); + WideString wsLinkContent = pElement->GetString(L"href"); + if (!wsLinkContent.IsEmpty()) { + pLinkData = pdfium::MakeRetain<CXFA_LinkUserData>( + wsLinkContent.GetBuffer(wsLinkContent.GetLength())); + wsLinkContent.ReleaseBuffer(wsLinkContent.GetLength()); + } + } + + int32_t iTabCount = m_textParser.CountTabs( + bContentNode ? pParentStyle.Get() : pStyle.Get()); + bool bSpaceRun = m_textParser.IsSpaceRun( + bContentNode ? pParentStyle.Get() : pStyle.Get()); + WideString wsText; + if (bContentNode && iTabCount == 0) { + wsText = static_cast<CFX_XMLText*>(pXMLNode)->GetText(); + } else if (wsName == L"br") { + wsText = L'\n'; + } else if (wsName == L"li") { + bCurLi = true; + if (bIsOl) + wsText = WideString::Format(L"%d. ", iLiCount); + else + wsText = 0x00B7 + WideStringView(L" ", 1); + } else if (!bContentNode) { + if (iTabCount > 0) { + while (iTabCount-- > 0) + wsText += L'\t'; + } else { + m_textParser.GetEmbbedObj(m_pTextProvider, pXMLNode, wsText); + } + } + + int32_t iLength = wsText.GetLength(); + if (iLength > 0 && bContentNode && !bSpaceRun) + ProcessText(wsText); + + if (m_pLoader) { + if (wsText.GetLength() > 0 && + (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) { + wsText.TrimLeft(L" "); + } + if (CFX_CSSDisplay::Block == eDisplay) { + m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; + } else if (CFX_CSSDisplay::Inline == eDisplay && + (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) { + m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; + } else if (wsText.GetLength() > 0 && + (0x20 == wsText[wsText.GetLength() - 1])) { + m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; + } else if (wsText.GetLength() != 0) { + m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; + } + } + + if (wsText.GetLength() > 0) { + if (!m_pLoader || m_pLoader->m_iChar == 0) { + auto pUserData = pdfium::MakeRetain<CXFA_TextUserData>( + bContentNode ? pParentStyle : pStyle, pLinkData); + m_pBreak->SetUserData(pUserData); + } + + if (AppendChar(wsText, fLinePos, 0, bSavePieces)) { + if (m_pLoader) + m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; + if (IsEnd(bSavePieces)) { + if (m_pLoader && m_pLoader->m_iTotalLines > -1) { + m_pLoader->m_pXMLNode = pXMLNode; + m_pLoader->m_pParentStyle = pParentStyle; + } + return false; + } + return true; + } + } + } + } + + for (CFX_XMLNode* pChildNode = + pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); + pChildNode; + pChildNode = pChildNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (bCurOl) + iLiCount++; + + if (!LoadRichText(pChildNode, textWidth, fLinePos, + pContext ? pStyle : pParentStyle, bSavePieces, + pLinkData, true, bIsOl, iLiCount)) + return false; + } + + if (m_pLoader) { + if (CFX_CSSDisplay::Block == eDisplay) + m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; + } + if (bCurLi) + EndBreak(CFX_BreakType::Line, fLinePos, bSavePieces); + } else { + if (pContext) + eDisplay = pContext->GetDisplay(); + } + + if (m_bBlockContinue) { + if (pContext && !bContentNode) { + CFX_BreakType dwStatus = (eDisplay == CFX_CSSDisplay::Block) + ? CFX_BreakType::Paragraph + : CFX_BreakType::Piece; + EndBreak(dwStatus, fLinePos, bSavePieces); + if (eDisplay == CFX_CSSDisplay::Block) { + fLinePos += fSpaceBelow; + if (m_pTabstopContext) + m_pTabstopContext->RemoveAll(); + } + if (IsEnd(bSavePieces)) { + if (m_pLoader && m_pLoader->m_iTotalLines > -1) { + m_pLoader->m_pXMLNode = + pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling); + m_pLoader->m_pParentStyle = pParentStyle; + } + return false; + } + } + } + return true; +} + +bool CXFA_TextLayout::AppendChar(const WideString& wsText, + float& fLinePos, + float fSpaceAbove, + bool bSavePieces) { + CFX_BreakType dwStatus = CFX_BreakType::None; + int32_t iChar = 0; + if (m_pLoader) + iChar = m_pLoader->m_iChar; + + int32_t iLength = wsText.GetLength(); + for (int32_t i = iChar; i < iLength; i++) { + wchar_t wch = wsText[i]; + if (wch == 0xA0) + wch = 0x20; + + dwStatus = m_pBreak->AppendChar(wch); + if (dwStatus != CFX_BreakType::None && dwStatus != CFX_BreakType::Piece) { + AppendTextLine(dwStatus, fLinePos, bSavePieces); + if (IsEnd(bSavePieces)) { + if (m_pLoader) + m_pLoader->m_iChar = i; + return true; + } + if (dwStatus == CFX_BreakType::Paragraph && m_bRichText) + fLinePos += fSpaceAbove; + } + } + if (m_pLoader) + m_pLoader->m_iChar = 0; + + return false; +} + +bool CXFA_TextLayout::IsEnd(bool bSavePieces) { + if (!bSavePieces) + return false; + if (m_pLoader && m_pLoader->m_iTotalLines > 0) + return m_iLines >= m_pLoader->m_iTotalLines; + return false; +} + +void CXFA_TextLayout::ProcessText(WideString& wsText) { + int32_t iLen = wsText.GetLength(); + if (iLen == 0) + return; + + wchar_t* psz = wsText.GetBuffer(iLen); + int32_t iTrimLeft = 0; + wchar_t wch = 0, wPrev = 0; + for (int32_t i = 0; i < iLen; i++) { + wch = psz[i]; + if (wch < 0x20) + wch = 0x20; + if (wch == 0x20 && wPrev == 0x20) + continue; + + wPrev = wch; + psz[iTrimLeft++] = wch; + } + wsText.ReleaseBuffer(iLen); + wsText = wsText.Left(iTrimLeft); +} + +void CXFA_TextLayout::EndBreak(CFX_BreakType dwStatus, + float& fLinePos, + bool bSavePieces) { + dwStatus = m_pBreak->EndBreak(dwStatus); + if (dwStatus != CFX_BreakType::None && dwStatus != CFX_BreakType::Piece) + AppendTextLine(dwStatus, fLinePos, bSavePieces, true); +} + +void CXFA_TextLayout::DoTabstops(CFX_CSSComputedStyle* pStyle, + CXFA_PieceLine* pPieceLine) { + if (!pStyle || !pPieceLine) + return; + + if (!m_pTabstopContext || m_pTabstopContext->m_tabstops.empty()) + return; + + int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces); + if (iPieces == 0) + return; + + CXFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPieces - 1].get(); + int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex; + int32_t iCount = m_textParser.CountTabs(pStyle); + if (!pdfium::IndexInBounds(m_pTabstopContext->m_tabstops, iTabstopsIndex)) + return; + + if (iCount > 0) { + iTabstopsIndex++; + m_pTabstopContext->m_bTabstops = true; + float fRight = 0; + if (iPieces > 1) { + CXFA_TextPiece* p = pPieceLine->m_textPieces[iPieces - 2].get(); + fRight = p->rtPiece.right(); + } + m_pTabstopContext->m_fTabWidth = + pPiece->rtPiece.width + pPiece->rtPiece.left - fRight; + } else if (iTabstopsIndex > -1) { + float fLeft = 0; + if (m_pTabstopContext->m_bTabstops) { + uint32_t dwAlign = m_pTabstopContext->m_tabstops[iTabstopsIndex].dwAlign; + if (dwAlign == FX_HashCode_GetW(L"center", false)) { + fLeft = pPiece->rtPiece.width / 2.0f; + } else if (dwAlign == FX_HashCode_GetW(L"right", false) || + dwAlign == FX_HashCode_GetW(L"before", false)) { + fLeft = pPiece->rtPiece.width; + } else if (dwAlign == FX_HashCode_GetW(L"decimal", false)) { + int32_t iChars = pPiece->iChars; + for (int32_t i = 0; i < iChars; i++) { + if (pPiece->szText[i] == L'.') + break; + + fLeft += pPiece->Widths[i] / 20000.0f; + } + } + m_pTabstopContext->m_fLeft = + std::min(fLeft, m_pTabstopContext->m_fTabWidth); + m_pTabstopContext->m_bTabstops = false; + m_pTabstopContext->m_fTabWidth = 0; + } + pPiece->rtPiece.left -= m_pTabstopContext->m_fLeft; + } +} + +void CXFA_TextLayout::AppendTextLine(CFX_BreakType dwStatus, + float& fLinePos, + bool bSavePieces, + bool bEndBreak) { + int32_t iPieces = m_pBreak->CountBreakPieces(); + if (iPieces < 1) + return; + + RetainPtr<CFX_CSSComputedStyle> pStyle; + if (bSavePieces) { + auto pNew = pdfium::MakeUnique<CXFA_PieceLine>(); + CXFA_PieceLine* pPieceLine = pNew.get(); + m_pieceLines.push_back(std::move(pNew)); + if (m_pTabstopContext) + m_pTabstopContext->Reset(); + + float fLineStep = 0, fBaseLine = 0; + int32_t i = 0; + for (i = 0; i < iPieces; i++) { + const CFX_BreakPiece* pPiece = m_pBreak->GetBreakPieceUnstable(i); + CXFA_TextUserData* pUserData = pPiece->m_pUserData.Get(); + if (pUserData) + pStyle = pUserData->m_pStyle; + float fVerScale = pPiece->m_iVerticalScale / 100.0f; + + auto pTP = pdfium::MakeUnique<CXFA_TextPiece>(); + pTP->iChars = pPiece->m_iChars; + pTP->szText = pPiece->GetString(); + pTP->Widths = pPiece->GetWidths(); + pTP->iBidiLevel = pPiece->m_iBidiLevel; + pTP->iHorScale = pPiece->m_iHorizontalScale; + pTP->iVerScale = pPiece->m_iVerticalScale; + m_textParser.GetUnderline(m_pTextProvider, pStyle.Get(), pTP->iUnderline, + pTP->iPeriod); + m_textParser.GetLinethrough(m_pTextProvider, pStyle.Get(), + pTP->iLineThrough); + pTP->dwColor = m_textParser.GetColor(m_pTextProvider, pStyle.Get()); + pTP->pFont = m_textParser.GetFont(m_pDoc, m_pTextProvider, pStyle.Get()); + pTP->fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle.Get()); + pTP->rtPiece.left = pPiece->m_iStartPos / 20000.0f; + pTP->rtPiece.width = pPiece->m_iWidth / 20000.0f; + pTP->rtPiece.height = (float)pPiece->m_iFontSize * fVerScale / 20.0f; + float fBaseLineTemp = + m_textParser.GetBaseline(m_pTextProvider, pStyle.Get()); + pTP->rtPiece.top = fBaseLineTemp; + + float fLineHeight = m_textParser.GetLineHeight( + m_pTextProvider, pStyle.Get(), m_iLines == 0, fVerScale); + if (fBaseLineTemp > 0) { + float fLineHeightTmp = fBaseLineTemp + pTP->rtPiece.height; + if (fLineHeight < fLineHeightTmp) + fLineHeight = fLineHeightTmp; + else + fBaseLineTemp = 0; + } else if (fBaseLine < -fBaseLineTemp) { + fBaseLine = -fBaseLineTemp; + } + fLineStep = std::max(fLineStep, fLineHeight); + pTP->pLinkData = pUserData ? pUserData->m_pLinkData : nullptr; + pPieceLine->m_textPieces.push_back(std::move(pTP)); + DoTabstops(pStyle.Get(), pPieceLine); + } + for (const auto& pTP : pPieceLine->m_textPieces) { + float& fTop = pTP->rtPiece.top; + float fBaseLineTemp = fTop; + fTop = fLinePos + fLineStep - pTP->rtPiece.height - fBaseLineTemp; + fTop = std::max(0.0f, fTop); + } + fLinePos += fLineStep + fBaseLine; + } else { + float fLineStep = 0; + float fLineWidth = 0; + for (int32_t i = 0; i < iPieces; i++) { + const CFX_BreakPiece* pPiece = m_pBreak->GetBreakPieceUnstable(i); + CXFA_TextUserData* pUserData = pPiece->m_pUserData.Get(); + if (pUserData) + pStyle = pUserData->m_pStyle; + float fVerScale = pPiece->m_iVerticalScale / 100.0f; + float fBaseLine = m_textParser.GetBaseline(m_pTextProvider, pStyle.Get()); + float fLineHeight = m_textParser.GetLineHeight( + m_pTextProvider, pStyle.Get(), m_iLines == 0, fVerScale); + if (fBaseLine > 0) { + float fLineHeightTmp = + fBaseLine + (float)pPiece->m_iFontSize * fVerScale / 20.0f; + if (fLineHeight < fLineHeightTmp) { + fLineHeight = fLineHeightTmp; + } + } + fLineStep = std::max(fLineStep, fLineHeight); + fLineWidth += pPiece->m_iWidth / 20000.0f; + } + fLinePos += fLineStep; + m_fMaxWidth = std::max(m_fMaxWidth, fLineWidth); + if (m_pLoader && m_pLoader->m_bSaveLineHeight) { + float fHeight = fLinePos - m_pLoader->m_fLastPos; + m_pLoader->m_fLastPos = fLinePos; + m_pLoader->m_lineHeights.push_back(fHeight); + } + } + + m_pBreak->ClearBreakPieces(); + if (dwStatus == CFX_BreakType::Paragraph) { + m_pBreak->Reset(); + if (!pStyle && bEndBreak) { + CXFA_Para* para = m_pTextProvider->GetParaIfExists(); + if (para) { + float fStartPos = para->GetMarginLeft(); + float fIndent = para->GetTextIndent(); + if (fIndent > 0) + fStartPos += fIndent; + + float fSpaceBelow = para->GetSpaceBelow(); + if (fSpaceBelow < 0.1f) + fSpaceBelow = 0; + + m_pBreak->SetLineStartPos(fStartPos); + fLinePos += fSpaceBelow; + } + } + } + + if (pStyle) { + float fStart = 0; + const CFX_CSSRect* pRect = pStyle->GetMarginWidth(); + if (pRect) + fStart = pRect->left.GetValue(); + + float fTextIndent = pStyle->GetTextIndent().GetValue(); + if (fTextIndent < 0) + fStart -= fTextIndent; + + m_pBreak->SetLineStartPos(fStart); + } + m_iLines++; +} + +void CXFA_TextLayout::RenderString(CFX_RenderDevice* pDevice, + CXFA_PieceLine* pPieceLine, + int32_t iPiece, + FXTEXT_CHARPOS* pCharPos, + const CFX_Matrix& tmDoc2Device) { + const CXFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPiece].get(); + int32_t iCount = GetDisplayPos(pPiece, pCharPos); + if (iCount > 0) { + CFDE_TextOut::DrawString(pDevice, pPiece->dwColor, pPiece->pFont, pCharPos, + iCount, pPiece->fFontSize, &tmDoc2Device); + } + pPieceLine->m_charCounts.push_back(iCount); +} + +void CXFA_TextLayout::RenderPath(CFX_RenderDevice* pDevice, + CXFA_PieceLine* pPieceLine, + int32_t iPiece, + FXTEXT_CHARPOS* pCharPos, + const CFX_Matrix& tmDoc2Device) { + CXFA_TextPiece* pPiece = pPieceLine->m_textPieces[iPiece].get(); + bool bNoUnderline = pPiece->iUnderline < 1 || pPiece->iUnderline > 2; + bool bNoLineThrough = pPiece->iLineThrough < 1 || pPiece->iLineThrough > 2; + if (bNoUnderline && bNoLineThrough) + return; + + CFX_PathData path; + int32_t iChars = GetDisplayPos(pPiece, pCharPos); + if (iChars > 0) { + CFX_PointF pt1, pt2; + float fEndY = pCharPos[0].m_Origin.y + 1.05f; + if (pPiece->iPeriod == XFA_AttributeEnum::Word) { + for (int32_t i = 0; i < pPiece->iUnderline; i++) { + for (int32_t j = 0; j < iChars; j++) { + pt1.x = pCharPos[j].m_Origin.x; + pt2.x = + pt1.x + pCharPos[j].m_FontCharWidth * pPiece->fFontSize / 1000.0f; + pt1.y = pt2.y = fEndY; + path.AppendLine(pt1, pt2); + } + fEndY += 2.0f; + } + } else { + pt1.x = pCharPos[0].m_Origin.x; + pt2.x = + pCharPos[iChars - 1].m_Origin.x + + pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; + for (int32_t i = 0; i < pPiece->iUnderline; i++) { + pt1.y = pt2.y = fEndY; + path.AppendLine(pt1, pt2); + fEndY += 2.0f; + } + } + fEndY = pCharPos[0].m_Origin.y - pPiece->rtPiece.height * 0.25f; + pt1.x = pCharPos[0].m_Origin.x; + pt2.x = pCharPos[iChars - 1].m_Origin.x + + pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; + for (int32_t i = 0; i < pPiece->iLineThrough; i++) { + pt1.y = pt2.y = fEndY; + path.AppendLine(pt1, pt2); + fEndY += 2.0f; + } + } else { + if (bNoLineThrough && + (bNoUnderline || pPiece->iPeriod != XFA_AttributeEnum::All)) { + return; + } + int32_t iCharsTmp = 0; + int32_t iPiecePrev = iPiece; + int32_t iPieceNext = iPiece; + while (iPiecePrev > 0) { + iPiecePrev--; + iCharsTmp = pPieceLine->m_charCounts[iPiecePrev]; + if (iCharsTmp > 0) + break; + } + if (iCharsTmp == 0) + return; + + iCharsTmp = 0; + int32_t iPieces = pdfium::CollectionSize<int32_t>(pPieceLine->m_textPieces); + while (iPieceNext < iPieces - 1) { + iPieceNext++; + iCharsTmp = pPieceLine->m_charCounts[iPieceNext]; + if (iCharsTmp > 0) + break; + } + if (iCharsTmp == 0) + return; + + float fOrgX = 0.0f; + float fEndX = 0.0f; + pPiece = pPieceLine->m_textPieces[iPiecePrev].get(); + iChars = GetDisplayPos(pPiece, pCharPos); + if (iChars < 1) + return; + + fOrgX = pCharPos[iChars - 1].m_Origin.x + + pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; + pPiece = pPieceLine->m_textPieces[iPieceNext].get(); + iChars = GetDisplayPos(pPiece, pCharPos); + if (iChars < 1) + return; + + fEndX = pCharPos[0].m_Origin.x; + CFX_PointF pt1; + CFX_PointF pt2; + pt1.x = fOrgX; + pt2.x = fEndX; + float fEndY = pCharPos[0].m_Origin.y + 1.05f; + for (int32_t i = 0; i < pPiece->iUnderline; i++) { + pt1.y = fEndY; + pt2.y = fEndY; + path.AppendLine(pt1, pt2); + fEndY += 2.0f; + } + fEndY = pCharPos[0].m_Origin.y - pPiece->rtPiece.height * 0.25f; + for (int32_t i = 0; i < pPiece->iLineThrough; i++) { + pt1.y = fEndY; + pt2.y = fEndY; + path.AppendLine(pt1, pt2); + fEndY += 2.0f; + } + } + + CFX_GraphStateData graphState; + graphState.m_LineCap = CFX_GraphStateData::LineCapButt; + graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter; + graphState.m_LineWidth = 1; + graphState.m_MiterLimit = 10; + graphState.m_DashPhase = 0; + pDevice->DrawPath(&path, &tmDoc2Device, &graphState, 0, pPiece->dwColor, 0); +} + +int32_t CXFA_TextLayout::GetDisplayPos(const CXFA_TextPiece* pPiece, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode) { + if (!pPiece) + return 0; + + FX_RTFTEXTOBJ tr; + if (!ToRun(pPiece, &tr)) + return 0; + return m_pBreak->GetDisplayPos(&tr, pCharPos, bCharCode); +} + +bool CXFA_TextLayout::ToRun(const CXFA_TextPiece* pPiece, FX_RTFTEXTOBJ* tr) { + int32_t iLength = pPiece->iChars; + if (iLength < 1) + return false; + + tr->pStr = pPiece->szText; + tr->pFont = pPiece->pFont; + tr->pRect = &pPiece->rtPiece; + tr->pWidths = pPiece->Widths; + tr->iLength = iLength; + tr->fFontSize = pPiece->fFontSize; + tr->iBidiLevel = pPiece->iBidiLevel; + tr->wLineBreakChar = L'\n'; + tr->iVerticalScale = pPiece->iVerScale; + tr->iHorizontalScale = pPiece->iHorScale; + return true; +} diff --git a/xfa/fxfa/cxfa_textlayout.h b/xfa/fxfa/cxfa_textlayout.h new file mode 100644 index 0000000000000000000000000000000000000000..40b64a7ca00449cf570a9f92c8e1b9b3e67db2c6 --- /dev/null +++ b/xfa/fxfa/cxfa_textlayout.h @@ -0,0 +1,128 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTLAYOUT_H_ +#define XFA_FXFA_CXFA_TEXTLAYOUT_H_ + +#include <memory> +#include <vector> + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "xfa/fgas/layout/cfx_rtfbreak.h" +#include "xfa/fxfa/cxfa_textparser.h" + +class CFDE_RenderDevice; +class CFX_CSSComputedStyle; +class CFX_RenderDevice; +class CFX_RTFBreak; +class CFX_XMLNode; +class CXFA_LinkUserData; +class CXFA_LoaderContext; +class CXFA_Node; +class CXFA_PieceLine; +class CXFA_TextPiece; +class CXFA_TextProvider; +class CXFA_TextTabstopsContext; + +class CXFA_TextLayout { + public: + explicit CXFA_TextLayout(CXFA_FFDoc* doc, CXFA_TextProvider* pTextProvider); + ~CXFA_TextLayout(); + + float GetLayoutHeight(); + float StartLayout(float fWidth); + float DoLayout(int32_t iBlockIndex, + float fCalcHeight, + float fContentAreaHeight, + float fTextHeight); + float Layout(const CFX_SizeF& size); + + CFX_SizeF CalcSize(const CFX_SizeF& minSize, const CFX_SizeF& maxSize); + void ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex); + bool DrawString(CFX_RenderDevice* pFxDevice, + const CFX_Matrix& tmDoc2Device, + const CFX_RectF& rtClip, + int32_t iBlock); + bool IsLoaded() const { return !m_pieceLines.empty(); } + void Unload(); + const std::vector<std::unique_ptr<CXFA_PieceLine>>* GetPieceLines() const { + return &m_pieceLines; + } + + bool m_bHasBlock; + std::vector<int32_t> m_Blocks; + + private: + void GetTextDataNode(); + CFX_XMLNode* GetXMLContainerNode(); + std::unique_ptr<CFX_RTFBreak> CreateBreak(bool bDefault); + void InitBreak(float fLineWidth); + void InitBreak(CFX_CSSComputedStyle* pStyle, + CFX_CSSDisplay eDisplay, + float fLineWidth, + CFX_XMLNode* pXMLNode, + CFX_CSSComputedStyle* pParentStyle); + bool Loader(float textWidth, float& fLinePos, bool bSavePieces); + void LoadText(CXFA_Node* pNode, + float textWidth, + float& fLinePos, + bool bSavePieces); + bool LoadRichText(CFX_XMLNode* pXMLNode, + float textWidth, + float& fLinePos, + const RetainPtr<CFX_CSSComputedStyle>& pParentStyle, + bool bSavePieces, + RetainPtr<CXFA_LinkUserData> pLinkData, + bool bEndBreak = true, + bool bIsOl = false, + int32_t iLiCount = 0); + bool AppendChar(const WideString& wsText, + float& fLinePos, + float fSpaceAbove, + bool bSavePieces); + void AppendTextLine(CFX_BreakType dwStatus, + float& fLinePos, + bool bSavePieces, + bool bEndBreak = false); + void EndBreak(CFX_BreakType dwStatus, float& fLinePos, bool bDefault); + bool IsEnd(bool bSavePieces); + void ProcessText(WideString& wsText); + void UpdateAlign(float fHeight, float fBottom); + void RenderString(CFX_RenderDevice* pDevice, + CXFA_PieceLine* pPieceLine, + int32_t iPiece, + FXTEXT_CHARPOS* pCharPos, + const CFX_Matrix& tmDoc2Device); + void RenderPath(CFX_RenderDevice* pDevice, + CXFA_PieceLine* pPieceLine, + int32_t iPiece, + FXTEXT_CHARPOS* pCharPos, + const CFX_Matrix& tmDoc2Device); + int32_t GetDisplayPos(const CXFA_TextPiece* pPiece, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode = false); + bool ToRun(const CXFA_TextPiece* pPiece, FX_RTFTEXTOBJ* tr); + void DoTabstops(CFX_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine); + bool Layout(int32_t iBlock); + int32_t CountBlocks() const; + + CXFA_FFDoc* m_pDoc; + CXFA_TextProvider* m_pTextProvider; + CXFA_Node* m_pTextDataNode; + bool m_bRichText; + std::unique_ptr<CFX_RTFBreak> m_pBreak; + std::unique_ptr<CXFA_LoaderContext> m_pLoader; + int32_t m_iLines; + float m_fMaxWidth; + CXFA_TextParser m_textParser; + std::vector<std::unique_ptr<CXFA_PieceLine>> m_pieceLines; + std::unique_ptr<CXFA_TextTabstopsContext> m_pTabstopContext; + bool m_bBlockContinue; +}; + +#endif // XFA_FXFA_CXFA_TEXTLAYOUT_H_ diff --git a/xfa/fxfa/cxfa_textparsecontext.cpp b/xfa/fxfa/cxfa_textparsecontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd21afc86481c26e23bd03c03b5d5ef06a23310f --- /dev/null +++ b/xfa/fxfa/cxfa_textparsecontext.cpp @@ -0,0 +1,16 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_textparsecontext.h" + +#include "core/fxcrt/css/cfx_csscomputedstyle.h" +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "core/fxcrt/css/cfx_cssstyleselector.h" + +CXFA_TextParseContext::CXFA_TextParseContext() + : m_pParentStyle(nullptr), m_eDisplay(CFX_CSSDisplay::None) {} + +CXFA_TextParseContext::~CXFA_TextParseContext() {} diff --git a/xfa/fxfa/cxfa_textparsecontext.h b/xfa/fxfa/cxfa_textparsecontext.h new file mode 100644 index 0000000000000000000000000000000000000000..20d914bc59f9d9520fddd1bc1b82b1c1808fdf92 --- /dev/null +++ b/xfa/fxfa/cxfa_textparsecontext.h @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTPARSECONTEXT_H_ +#define XFA_FXFA_CXFA_TEXTPARSECONTEXT_H_ + +#include <utility> +#include <vector> + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_cssdeclaration.h" +#include "third_party/base/stl_util.h" + +class CFX_CSSComputedStyle; + +class CXFA_TextParseContext { + public: + CXFA_TextParseContext(); + ~CXFA_TextParseContext(); + + void SetDisplay(CFX_CSSDisplay eDisplay) { m_eDisplay = eDisplay; } + CFX_CSSDisplay GetDisplay() const { return m_eDisplay; } + + void SetDecls(std::vector<const CFX_CSSDeclaration*>&& decl) { + decls_ = std::move(decl); + } + const std::vector<const CFX_CSSDeclaration*>& GetDecls() { return decls_; } + + RetainPtr<CFX_CSSComputedStyle> m_pParentStyle; + + private: + std::vector<const CFX_CSSDeclaration*> decls_; + CFX_CSSDisplay m_eDisplay; +}; + +#endif // XFA_FXFA_CXFA_TEXTPARSECONTEXT_H_ diff --git a/xfa/fxfa/cxfa_textparser.cpp b/xfa/fxfa/cxfa_textparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07ba896843eec9b9c7f7cc99556458646be4c7eb --- /dev/null +++ b/xfa/fxfa/cxfa_textparser.cpp @@ -0,0 +1,636 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_textparser.h" + +#include <algorithm> +#include <utility> +#include <vector> + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_csscomputedstyle.h" +#include "core/fxcrt/css/cfx_cssstyleselector.h" +#include "core/fxcrt/css/cfx_cssstylesheet.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/cxfa_textparsecontext.h" +#include "xfa/fxfa/cxfa_textprovider.h" +#include "xfa/fxfa/cxfa_texttabstopscontext.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_para.h" + +namespace { + +enum class TabStopStatus { + Error, + EOS, + None, + Alignment, + StartLeader, + Leader, + Location, +}; + +} // namespace + +CXFA_TextParser::CXFA_TextParser() + : m_bParsed(false), m_cssInitialized(false) {} + +CXFA_TextParser::~CXFA_TextParser() {} + +void CXFA_TextParser::Reset() { + m_mapXMLNodeToParseContext.clear(); + m_bParsed = false; +} + +void CXFA_TextParser::InitCSSData(CXFA_TextProvider* pTextProvider) { + if (!pTextProvider) + return; + + if (!m_pSelector) { + m_pSelector = pdfium::MakeUnique<CFX_CSSStyleSelector>(); + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + m_pSelector->SetDefFontSize(font ? font->GetFontSize() : 10.0f); + } + + if (m_cssInitialized) + return; + + m_cssInitialized = true; + auto uaSheet = LoadDefaultSheetStyle(); + m_pSelector->SetUAStyleSheet(std::move(uaSheet)); + m_pSelector->UpdateStyleIndex(); +} + +std::unique_ptr<CFX_CSSStyleSheet> CXFA_TextParser::LoadDefaultSheetStyle() { + static const wchar_t s_pStyle[] = + L"html,body,ol,p,ul{display:block}" + L"li{display:list-item}" + L"ol,ul{padding-left:33px;margin:1.12em 0}" + L"ol{list-style-type:decimal}" + L"a{color:#0000ff;text-decoration:underline}" + L"b{font-weight:bolder}" + L"i{font-style:italic}" + L"sup{vertical-align:+15em;font-size:.66em}" + L"sub{vertical-align:-15em;font-size:.66em}"; + + auto sheet = pdfium::MakeUnique<CFX_CSSStyleSheet>(); + return sheet->LoadBuffer(s_pStyle, wcslen(s_pStyle)) ? std::move(sheet) + : nullptr; +} + +RetainPtr<CFX_CSSComputedStyle> CXFA_TextParser::CreateRootStyle( + CXFA_TextProvider* pTextProvider) { + CXFA_Para* para = pTextProvider->GetParaIfExists(); + auto pStyle = m_pSelector->CreateComputedStyle(nullptr); + float fLineHeight = 0; + float fFontSize = 10; + + if (para) { + fLineHeight = para->GetLineHeight(); + CFX_CSSLength indent; + indent.Set(CFX_CSSLengthUnit::Point, para->GetTextIndent()); + pStyle->SetTextIndent(indent); + CFX_CSSTextAlign hAlign = CFX_CSSTextAlign::Left; + switch (para->GetHorizontalAlign()) { + case XFA_AttributeEnum::Center: + hAlign = CFX_CSSTextAlign::Center; + break; + case XFA_AttributeEnum::Right: + hAlign = CFX_CSSTextAlign::Right; + break; + case XFA_AttributeEnum::Justify: + hAlign = CFX_CSSTextAlign::Justify; + break; + case XFA_AttributeEnum::JustifyAll: + hAlign = CFX_CSSTextAlign::JustifyAll; + break; + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Radix: + break; + default: + NOTREACHED(); + break; + } + pStyle->SetTextAlign(hAlign); + CFX_CSSRect rtMarginWidth; + rtMarginWidth.left.Set(CFX_CSSLengthUnit::Point, para->GetMarginLeft()); + rtMarginWidth.top.Set(CFX_CSSLengthUnit::Point, para->GetSpaceAbove()); + rtMarginWidth.right.Set(CFX_CSSLengthUnit::Point, para->GetMarginRight()); + rtMarginWidth.bottom.Set(CFX_CSSLengthUnit::Point, para->GetSpaceBelow()); + pStyle->SetMarginWidth(rtMarginWidth); + } + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + if (font) { + pStyle->SetColor(font->GetColor()); + pStyle->SetFontStyle(font->IsItalic() ? CFX_CSSFontStyle::Italic + : CFX_CSSFontStyle::Normal); + pStyle->SetFontWeight(font->IsBold() ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + pStyle->SetNumberVerticalAlign(-font->GetBaselineShift()); + fFontSize = font->GetFontSize(); + CFX_CSSLength letterSpacing; + letterSpacing.Set(CFX_CSSLengthUnit::Point, font->GetLetterSpacing()); + pStyle->SetLetterSpacing(letterSpacing); + uint32_t dwDecoration = 0; + if (font->GetLineThrough() > 0) + dwDecoration |= CFX_CSSTEXTDECORATION_LineThrough; + if (font->GetUnderline() > 1) + dwDecoration |= CFX_CSSTEXTDECORATION_Double; + else if (font->GetUnderline() > 0) + dwDecoration |= CFX_CSSTEXTDECORATION_Underline; + + pStyle->SetTextDecoration(dwDecoration); + } + pStyle->SetLineHeight(fLineHeight); + pStyle->SetFontSize(fFontSize); + return pStyle; +} + +RetainPtr<CFX_CSSComputedStyle> CXFA_TextParser::CreateStyle( + CFX_CSSComputedStyle* pParentStyle) { + auto pNewStyle = m_pSelector->CreateComputedStyle(pParentStyle); + ASSERT(pNewStyle); + if (!pParentStyle) + return pNewStyle; + + uint32_t dwDecoration = pParentStyle->GetTextDecoration(); + float fBaseLine = 0; + if (pParentStyle->GetVerticalAlign() == CFX_CSSVerticalAlign::Number) + fBaseLine = pParentStyle->GetNumberVerticalAlign(); + + pNewStyle->SetTextDecoration(dwDecoration); + pNewStyle->SetNumberVerticalAlign(fBaseLine); + + const CFX_CSSRect* pRect = pParentStyle->GetMarginWidth(); + if (pRect) + pNewStyle->SetMarginWidth(*pRect); + return pNewStyle; +} + +RetainPtr<CFX_CSSComputedStyle> CXFA_TextParser::ComputeStyle( + CFX_XMLNode* pXMLNode, + CFX_CSSComputedStyle* pParentStyle) { + auto it = m_mapXMLNodeToParseContext.find(pXMLNode); + if (it == m_mapXMLNodeToParseContext.end()) + return nullptr; + + CXFA_TextParseContext* pContext = it->second.get(); + if (!pContext) + return nullptr; + + pContext->m_pParentStyle.Reset(pParentStyle); + + auto tagProvider = ParseTagInfo(pXMLNode); + if (tagProvider->m_bContent) + return nullptr; + + auto pStyle = CreateStyle(pParentStyle); + m_pSelector->ComputeStyle(pContext->GetDecls(), + tagProvider->GetAttribute(L"style"), + tagProvider->GetAttribute(L"align"), pStyle.Get()); + return pStyle; +} + +void CXFA_TextParser::DoParse(CFX_XMLNode* pXMLContainer, + CXFA_TextProvider* pTextProvider) { + if (!pXMLContainer || !pTextProvider || m_bParsed) + return; + + m_bParsed = true; + InitCSSData(pTextProvider); + auto pRootStyle = CreateRootStyle(pTextProvider); + ParseRichText(pXMLContainer, pRootStyle.Get()); +} + +void CXFA_TextParser::ParseRichText(CFX_XMLNode* pXMLNode, + CFX_CSSComputedStyle* pParentStyle) { + if (!pXMLNode) + return; + + auto tagProvider = ParseTagInfo(pXMLNode); + if (!tagProvider->m_bTagAvailable) + return; + + RetainPtr<CFX_CSSComputedStyle> pNewStyle; + if ((tagProvider->GetTagName() != L"body") || + (tagProvider->GetTagName() != L"html")) { + auto pTextContext = pdfium::MakeUnique<CXFA_TextParseContext>(); + CFX_CSSDisplay eDisplay = CFX_CSSDisplay::Inline; + if (!tagProvider->m_bContent) { + auto declArray = + m_pSelector->MatchDeclarations(tagProvider->GetTagName()); + pNewStyle = CreateStyle(pParentStyle); + m_pSelector->ComputeStyle(declArray, tagProvider->GetAttribute(L"style"), + tagProvider->GetAttribute(L"align"), + pNewStyle.Get()); + + if (!declArray.empty()) + pTextContext->SetDecls(std::move(declArray)); + + eDisplay = pNewStyle->GetDisplay(); + } + pTextContext->SetDisplay(eDisplay); + m_mapXMLNodeToParseContext[pXMLNode] = std::move(pTextContext); + } + + for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLChild; + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { + ParseRichText(pXMLChild, pNewStyle.Get()); + } +} + +bool CXFA_TextParser::TagValidate(const WideString& wsName) const { + static const uint32_t s_XFATagName[] = { + 0x61, // a + 0x62, // b + 0x69, // i + 0x70, // p + 0x0001f714, // br + 0x00022a55, // li + 0x000239bb, // ol + 0x00025881, // ul + 0x0bd37faa, // sub + 0x0bd37fb8, // sup + 0xa73e3af2, // span + 0xb182eaae, // body + 0xdb8ac455, // html + }; + static const int32_t s_iCount = FX_ArraySize(s_XFATagName); + + return std::binary_search(s_XFATagName, s_XFATagName + s_iCount, + FX_HashCode_GetW(wsName.AsStringView(), true)); +} + +std::unique_ptr<CXFA_TextParser::TagProvider> CXFA_TextParser::ParseTagInfo( + CFX_XMLNode* pXMLNode) { + auto tagProvider = pdfium::MakeUnique<TagProvider>(); + + WideString wsName; + if (pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode); + wsName = pXMLElement->GetLocalTagName(); + tagProvider->SetTagName(wsName); + tagProvider->m_bTagAvailable = TagValidate(wsName); + + WideString wsValue = pXMLElement->GetString(L"style"); + if (!wsValue.IsEmpty()) + tagProvider->SetAttribute(L"style", wsValue); + } else if (pXMLNode->GetType() == FX_XMLNODE_Text) { + tagProvider->m_bTagAvailable = true; + tagProvider->m_bContent = true; + } + return tagProvider; +} + +XFA_AttributeEnum CXFA_TextParser::GetVAlign( + CXFA_TextProvider* pTextProvider) const { + CXFA_Para* para = pTextProvider->GetParaIfExists(); + return para ? para->GetVerticalAlign() : XFA_AttributeEnum::Top; +} + +float CXFA_TextParser::GetTabInterval(CFX_CSSComputedStyle* pStyle) const { + WideString wsValue; + if (pStyle && pStyle->GetCustomStyle(L"tab-interval", wsValue)) + return CXFA_Measurement(wsValue.AsStringView()).ToUnit(XFA_Unit::Pt); + return 36; +} + +int32_t CXFA_TextParser::CountTabs(CFX_CSSComputedStyle* pStyle) const { + WideString wsValue; + if (pStyle && pStyle->GetCustomStyle(L"xfa-tab-count", wsValue)) + return wsValue.GetInteger(); + return 0; +} + +bool CXFA_TextParser::IsSpaceRun(CFX_CSSComputedStyle* pStyle) const { + WideString wsValue; + if (pStyle && pStyle->GetCustomStyle(L"xfa-spacerun", wsValue)) { + wsValue.MakeLower(); + return wsValue == L"yes"; + } + return false; +} + +RetainPtr<CFGAS_GEFont> CXFA_TextParser::GetFont( + CXFA_FFDoc* doc, + CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const { + WideString wsFamily = L"Courier"; + uint32_t dwStyle = 0; + CXFA_Font* font = pTextProvider->GetFontIfExists(); + if (font) { + wsFamily = font->GetTypeface(); + if (font->IsBold()) + dwStyle |= FXFONT_BOLD; + if (font->IsItalic()) + dwStyle |= FXFONT_BOLD; + } + + if (pStyle) { + int32_t iCount = pStyle->CountFontFamilies(); + if (iCount > 0) + wsFamily = pStyle->GetFontFamily(iCount - 1).AsStringView(); + + dwStyle = 0; + if (pStyle->GetFontWeight() > FXFONT_FW_NORMAL) + dwStyle |= FXFONT_BOLD; + if (pStyle->GetFontStyle() == CFX_CSSFontStyle::Italic) + dwStyle |= FXFONT_ITALIC; + } + + CXFA_FontMgr* pFontMgr = doc->GetApp()->GetXFAFontMgr(); + return pFontMgr->GetFont(doc, wsFamily.AsStringView(), dwStyle); +} + +float CXFA_TextParser::GetFontSize(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const { + if (pStyle) + return pStyle->GetFontSize(); + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + return font ? font->GetFontSize() : 10; +} + +int32_t CXFA_TextParser::GetHorScale(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + CFX_XMLNode* pXMLNode) const { + if (pStyle) { + WideString wsValue; + if (pStyle->GetCustomStyle(L"xfa-font-horizontal-scale", wsValue)) + return wsValue.GetInteger(); + + while (pXMLNode) { + auto it = m_mapXMLNodeToParseContext.find(pXMLNode); + if (it != m_mapXMLNodeToParseContext.end()) { + CXFA_TextParseContext* pContext = it->second.get(); + if (pContext && pContext->m_pParentStyle && + pContext->m_pParentStyle->GetCustomStyle( + L"xfa-font-horizontal-scale", wsValue)) { + return wsValue.GetInteger(); + } + } + pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::Parent); + } + } + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + return font ? static_cast<int32_t>(font->GetHorizontalScale()) : 100; +} + +int32_t CXFA_TextParser::GetVerScale(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const { + if (pStyle) { + WideString wsValue; + if (pStyle->GetCustomStyle(L"xfa-font-vertical-scale", wsValue)) + return wsValue.GetInteger(); + } + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + return font ? static_cast<int32_t>(font->GetVerticalScale()) : 100; +} + +void CXFA_TextParser::GetUnderline(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + int32_t& iUnderline, + XFA_AttributeEnum& iPeriod) const { + iUnderline = 0; + iPeriod = XFA_AttributeEnum::All; + CXFA_Font* font = pTextProvider->GetFontIfExists(); + if (!pStyle) { + if (font) { + iUnderline = font->GetUnderline(); + iPeriod = font->GetUnderlinePeriod(); + } + return; + } + + uint32_t dwDecoration = pStyle->GetTextDecoration(); + if (dwDecoration & CFX_CSSTEXTDECORATION_Double) + iUnderline = 2; + else if (dwDecoration & CFX_CSSTEXTDECORATION_Underline) + iUnderline = 1; + + WideString wsValue; + if (pStyle->GetCustomStyle(L"underlinePeriod", wsValue)) { + if (wsValue == L"word") + iPeriod = XFA_AttributeEnum::Word; + } else if (font) { + iPeriod = font->GetUnderlinePeriod(); + } +} + +void CXFA_TextParser::GetLinethrough(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + int32_t& iLinethrough) const { + if (pStyle) { + uint32_t dwDecoration = pStyle->GetTextDecoration(); + iLinethrough = (dwDecoration & CFX_CSSTEXTDECORATION_LineThrough) ? 1 : 0; + return; + } + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + if (font) + iLinethrough = font->GetLineThrough(); +} + +FX_ARGB CXFA_TextParser::GetColor(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const { + if (pStyle) + return pStyle->GetColor(); + + CXFA_Font* font = pTextProvider->GetFontIfExists(); + return font ? font->GetColor() : 0xFF000000; +} + +float CXFA_TextParser::GetBaseline(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const { + if (pStyle) { + if (pStyle->GetVerticalAlign() == CFX_CSSVerticalAlign::Number) + return pStyle->GetNumberVerticalAlign(); + } else { + CXFA_Font* font = pTextProvider->GetFontIfExists(); + if (font) + return font->GetBaselineShift(); + } + return 0; +} + +float CXFA_TextParser::GetLineHeight(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + bool bFirst, + float fVerScale) const { + float fLineHeight = 0; + if (pStyle) { + fLineHeight = pStyle->GetLineHeight(); + } else { + CXFA_Para* para = pTextProvider->GetParaIfExists(); + if (para) + fLineHeight = para->GetLineHeight(); + } + + if (bFirst) { + float fFontSize = GetFontSize(pTextProvider, pStyle); + if (fLineHeight < 0.1f) + fLineHeight = fFontSize; + else + fLineHeight = std::min(fLineHeight, fFontSize); + } else if (fLineHeight < 0.1f) { + fLineHeight = GetFontSize(pTextProvider, pStyle) * 1.2f; + } + fLineHeight *= fVerScale; + return fLineHeight; +} + +bool CXFA_TextParser::GetEmbbedObj(CXFA_TextProvider* pTextProvider, + CFX_XMLNode* pXMLNode, + WideString& wsValue) { + wsValue.clear(); + if (!pXMLNode) + return false; + + bool bRet = false; + if (pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pElement = static_cast<CFX_XMLElement*>(pXMLNode); + WideString wsAttr = pElement->GetString(L"xfa:embed"); + if (wsAttr.IsEmpty()) + return false; + if (wsAttr[0] == L'#') + wsAttr.Delete(0); + + WideString ws = pElement->GetString(L"xfa:embedType"); + if (ws.IsEmpty()) + ws = L"som"; + else + ws.MakeLower(); + + bool bURI = (ws == L"uri"); + if (!bURI && ws != L"som") + return false; + + ws = pElement->GetString(L"xfa:embedMode"); + if (ws.IsEmpty()) + ws = L"formatted"; + else + ws.MakeLower(); + + bool bRaw = (ws == L"raw"); + if (!bRaw && ws != L"formatted") + return false; + + bRet = pTextProvider->GetEmbbedObj(bURI, bRaw, wsAttr, wsValue); + } + return bRet; +} + +CXFA_TextParseContext* CXFA_TextParser::GetParseContextFromMap( + CFX_XMLNode* pXMLNode) { + auto it = m_mapXMLNodeToParseContext.find(pXMLNode); + return it != m_mapXMLNodeToParseContext.end() ? it->second.get() : nullptr; +} + +bool CXFA_TextParser::GetTabstops(CFX_CSSComputedStyle* pStyle, + CXFA_TextTabstopsContext* pTabstopContext) { + if (!pStyle || !pTabstopContext) + return false; + + WideString wsValue; + if (!pStyle->GetCustomStyle(L"xfa-tab-stops", wsValue) && + !pStyle->GetCustomStyle(L"tab-stops", wsValue)) { + return false; + } + + int32_t iLength = wsValue.GetLength(); + const wchar_t* pTabStops = wsValue.c_str(); + int32_t iCur = 0; + int32_t iLast = 0; + WideString wsAlign; + TabStopStatus eStatus = TabStopStatus::None; + wchar_t ch; + while (iCur < iLength) { + ch = pTabStops[iCur]; + switch (eStatus) { + case TabStopStatus::None: + if (ch <= ' ') { + iCur++; + } else { + eStatus = TabStopStatus::Alignment; + iLast = iCur; + } + break; + case TabStopStatus::Alignment: + if (ch == ' ') { + wsAlign = WideStringView(pTabStops + iLast, iCur - iLast); + eStatus = TabStopStatus::StartLeader; + iCur++; + while (iCur < iLength && pTabStops[iCur] <= ' ') + iCur++; + iLast = iCur; + } else { + iCur++; + } + break; + case TabStopStatus::StartLeader: + if (ch != 'l') { + eStatus = TabStopStatus::Location; + } else { + int32_t iCount = 0; + while (iCur < iLength) { + ch = pTabStops[iCur]; + iCur++; + if (ch == '(') { + iCount++; + } else if (ch == ')') { + iCount--; + if (iCount == 0) + break; + } + } + while (iCur < iLength && pTabStops[iCur] <= ' ') + iCur++; + + iLast = iCur; + eStatus = TabStopStatus::Location; + } + break; + case TabStopStatus::Location: + if (ch == ' ') { + uint32_t dwHashCode = FX_HashCode_GetW(wsAlign.AsStringView(), true); + CXFA_Measurement ms(WideStringView(pTabStops + iLast, iCur - iLast)); + float fPos = ms.ToUnit(XFA_Unit::Pt); + pTabstopContext->Append(dwHashCode, fPos); + wsAlign.clear(); + eStatus = TabStopStatus::None; + } + iCur++; + break; + default: + break; + } + } + + if (!wsAlign.IsEmpty()) { + uint32_t dwHashCode = FX_HashCode_GetW(wsAlign.AsStringView(), true); + CXFA_Measurement ms(WideStringView(pTabStops + iLast, iCur - iLast)); + float fPos = ms.ToUnit(XFA_Unit::Pt); + pTabstopContext->Append(dwHashCode, fPos); + } + return true; +} + +CXFA_TextParser::TagProvider::TagProvider() + : m_bTagAvailable(false), m_bContent(false) {} + +CXFA_TextParser::TagProvider::~TagProvider() {} diff --git a/xfa/fxfa/cxfa_textparser.h b/xfa/fxfa/cxfa_textparser.h new file mode 100644 index 0000000000000000000000000000000000000000..cd2856e6dfb973843450c30b514dc4612c372165 --- /dev/null +++ b/xfa/fxfa/cxfa_textparser.h @@ -0,0 +1,129 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTPARSER_H_ +#define XFA_FXFA_CXFA_TEXTPARSER_H_ + +#include <map> +#include <memory> + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/fx_dib.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CFGAS_GEFont; +class CFX_CSSComputedStyle; +class CFX_CSSStyleSelector; +class CFX_CSSStyleSheet; +class CFX_XMLNode; +class CXFA_FFDoc; +class CXFA_TextParseContext; +class CXFA_TextProvider; +class CXFA_TextTabstopsContext; + +class CXFA_TextParser { + public: + CXFA_TextParser(); + virtual ~CXFA_TextParser(); + + void Reset(); + void DoParse(CFX_XMLNode* pXMLContainer, CXFA_TextProvider* pTextProvider); + + RetainPtr<CFX_CSSComputedStyle> CreateRootStyle( + CXFA_TextProvider* pTextProvider); + RetainPtr<CFX_CSSComputedStyle> ComputeStyle( + CFX_XMLNode* pXMLNode, + CFX_CSSComputedStyle* pParentStyle); + + bool IsParsed() const { return m_bParsed; } + + XFA_AttributeEnum GetVAlign(CXFA_TextProvider* pTextProvider) const; + + float GetTabInterval(CFX_CSSComputedStyle* pStyle) const; + int32_t CountTabs(CFX_CSSComputedStyle* pStyle) const; + + bool IsSpaceRun(CFX_CSSComputedStyle* pStyle) const; + bool GetTabstops(CFX_CSSComputedStyle* pStyle, + CXFA_TextTabstopsContext* pTabstopContext); + + RetainPtr<CFGAS_GEFont> GetFont(CXFA_FFDoc* doc, + CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const; + float GetFontSize(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const; + + int32_t GetHorScale(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + CFX_XMLNode* pXMLNode) const; + int32_t GetVerScale(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const; + + void GetUnderline(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + int32_t& iUnderline, + XFA_AttributeEnum& iPeriod) const; + void GetLinethrough(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + int32_t& iLinethrough) const; + FX_ARGB GetColor(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const; + float GetBaseline(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle) const; + float GetLineHeight(CXFA_TextProvider* pTextProvider, + CFX_CSSComputedStyle* pStyle, + bool bFirst, + float fVerScale) const; + + bool GetEmbbedObj(CXFA_TextProvider* pTextProvider, + CFX_XMLNode* pXMLNode, + WideString& wsValue); + CXFA_TextParseContext* GetParseContextFromMap(CFX_XMLNode* pXMLNode); + + protected: + bool TagValidate(const WideString& str) const; + + private: + class TagProvider { + public: + TagProvider(); + ~TagProvider(); + + WideString GetTagName() { return m_wsTagName; } + + void SetTagName(const WideString& wsName) { m_wsTagName = wsName; } + void SetAttribute(const WideString& wsAttr, const WideString& wsValue) { + m_Attributes.insert({wsAttr, wsValue}); + } + + WideString GetAttribute(const WideString& wsAttr) { + return m_Attributes[wsAttr]; + } + + bool m_bTagAvailable; + bool m_bContent; + + private: + WideString m_wsTagName; + std::map<WideString, WideString> m_Attributes; + }; + + void InitCSSData(CXFA_TextProvider* pTextProvider); + void ParseRichText(CFX_XMLNode* pXMLNode, CFX_CSSComputedStyle* pParentStyle); + std::unique_ptr<TagProvider> ParseTagInfo(CFX_XMLNode* pXMLNode); + std::unique_ptr<CFX_CSSStyleSheet> LoadDefaultSheetStyle(); + RetainPtr<CFX_CSSComputedStyle> CreateStyle( + CFX_CSSComputedStyle* pParentStyle); + + bool m_bParsed; + bool m_cssInitialized; + std::unique_ptr<CFX_CSSStyleSelector> m_pSelector; + std::map<CFX_XMLNode*, std::unique_ptr<CXFA_TextParseContext>> + m_mapXMLNodeToParseContext; +}; + +#endif // XFA_FXFA_CXFA_TEXTPARSER_H_ diff --git a/xfa/fxfa/app/cxfa_textparser_unittest.cpp b/xfa/fxfa/cxfa_textparser_unittest.cpp similarity index 96% rename from xfa/fxfa/app/cxfa_textparser_unittest.cpp rename to xfa/fxfa/cxfa_textparser_unittest.cpp index 82a011046849233feb5fa40c140934268b1ba05d..bd748cd494cb97459d126c6b60434a3b5e9eda1c 100644 --- a/xfa/fxfa/app/cxfa_textparser_unittest.cpp +++ b/xfa/fxfa/cxfa_textparser_unittest.cpp @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "xfa/fxfa/app/cxfa_textparser.h" +#include "xfa/fxfa/cxfa_textparser.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/xfa/fxfa/cxfa_textpiece.cpp b/xfa/fxfa/cxfa_textpiece.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6a8d3abafb309c3f6b4de2e85d2f3d9cc3bcbf6 --- /dev/null +++ b/xfa/fxfa/cxfa_textpiece.cpp @@ -0,0 +1,14 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_textpiece.h" + +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fxfa/cxfa_linkuserdata.h" + +CXFA_TextPiece::CXFA_TextPiece() {} + +CXFA_TextPiece::~CXFA_TextPiece() {} diff --git a/xfa/fxfa/cxfa_textpiece.h b/xfa/fxfa/cxfa_textpiece.h new file mode 100644 index 0000000000000000000000000000000000000000..f3812f8e1e205d89e62ed645761495da93cf7277 --- /dev/null +++ b/xfa/fxfa/cxfa_textpiece.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTPIECE_H_ +#define XFA_FXFA_CXFA_TEXTPIECE_H_ + +#include <vector> + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxge/fx_dib.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CFGAS_GEFont; +class CXFA_LinkUserData; + +class CXFA_TextPiece { + public: + CXFA_TextPiece(); + ~CXFA_TextPiece(); + + WideString szText; + std::vector<int32_t> Widths; + int32_t iChars; + int32_t iHorScale; + int32_t iVerScale; + int32_t iBidiLevel; + int32_t iUnderline; + XFA_AttributeEnum iPeriod; + int32_t iLineThrough; + FX_ARGB dwColor; + float fFontSize; + CFX_RectF rtPiece; + RetainPtr<CFGAS_GEFont> pFont; + RetainPtr<CXFA_LinkUserData> pLinkData; +}; + +#endif // XFA_FXFA_CXFA_TEXTPIECE_H_ diff --git a/xfa/fxfa/cxfa_textprovider.cpp b/xfa/fxfa/cxfa_textprovider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55da28182e41e5eae6a08ac37bfb43205a435457 --- /dev/null +++ b/xfa/fxfa/cxfa_textprovider.cpp @@ -0,0 +1,176 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_textprovider.h" + +#include <algorithm> +#include <memory> +#include <vector> + +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fde/cfde_textout.h" +#include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffcheckbutton.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_fffield.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" +#include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_items.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +CXFA_Node* CXFA_TextProvider::GetTextNode(bool& bRichText) { + bRichText = false; + + if (m_eType == XFA_TEXTPROVIDERTYPE_Text) { + CXFA_Node* pElementNode = m_pWidgetAcc->GetNode(); + CXFA_Value* pValueNode = + pElementNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pValueNode) + return nullptr; + + CXFA_Node* pChildNode = pValueNode->GetFirstChild(); + if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) { + Optional<WideString> contentType = pChildNode->JSObject()->TryAttribute( + XFA_Attribute::ContentType, false); + if (contentType && *contentType == L"text/html") + bRichText = true; + } + return pChildNode; + } + + if (m_eType == XFA_TEXTPROVIDERTYPE_Datasets) { + CXFA_Node* pBind = m_pWidgetAcc->GetNode()->GetBindData(); + CFX_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); + ASSERT(pXMLNode); + for (CFX_XMLNode* pXMLChild = + pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLChild; + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pXMLChild->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pElement = static_cast<CFX_XMLElement*>(pXMLChild); + if (XFA_RecognizeRichText(pElement)) + bRichText = true; + } + } + return pBind; + } + + if (m_eType == XFA_TEXTPROVIDERTYPE_Caption) { + CXFA_Caption* pCaptionNode = + m_pWidgetAcc->GetNode()->GetChild<CXFA_Caption>(0, XFA_Element::Caption, + false); + if (!pCaptionNode) + return nullptr; + + CXFA_Value* pValueNode = + pCaptionNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pValueNode) + return nullptr; + + CXFA_Node* pChildNode = pValueNode->GetFirstChild(); + if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) { + Optional<WideString> contentType = pChildNode->JSObject()->TryAttribute( + XFA_Attribute::ContentType, false); + if (contentType && *contentType == L"text/html") + bRichText = true; + } + return pChildNode; + } + + CXFA_Items* pItemNode = m_pWidgetAcc->GetNode()->GetChild<CXFA_Items>( + 0, XFA_Element::Items, false); + if (!pItemNode) + return nullptr; + + CXFA_Node* pNode = pItemNode->GetFirstChild(); + while (pNode) { + WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); + if (m_eType == XFA_TEXTPROVIDERTYPE_Rollover && wsName == L"rollover") + return pNode; + if (m_eType == XFA_TEXTPROVIDERTYPE_Down && wsName == L"down") + return pNode; + + pNode = pNode->GetNextSibling(); + } + return nullptr; +} + +CXFA_Para* CXFA_TextProvider::GetParaIfExists() { + if (m_eType == XFA_TEXTPROVIDERTYPE_Text) + return m_pWidgetAcc->GetNode()->GetParaIfExists(); + + CXFA_Caption* pNode = m_pWidgetAcc->GetNode()->GetChild<CXFA_Caption>( + 0, XFA_Element::Caption, false); + return pNode->GetChild<CXFA_Para>(0, XFA_Element::Para, false); +} + +CXFA_Font* CXFA_TextProvider::GetFontIfExists() { + if (m_eType == XFA_TEXTPROVIDERTYPE_Text) + return m_pWidgetAcc->GetNode()->GetFontIfExists(); + + CXFA_Caption* pNode = m_pWidgetAcc->GetNode()->GetChild<CXFA_Caption>( + 0, XFA_Element::Caption, false); + CXFA_Font* font = pNode->GetChild<CXFA_Font>(0, XFA_Element::Font, false); + return font ? font : m_pWidgetAcc->GetNode()->GetFontIfExists(); +} + +bool CXFA_TextProvider::IsCheckButtonAndAutoWidth() { + XFA_Element eType = m_pWidgetAcc->GetUIType(); + if (eType != XFA_Element::CheckButton) + return false; + return !m_pWidgetAcc->GetNode()->TryWidth(); +} + +bool CXFA_TextProvider::GetEmbbedObj(bool bURI, + bool bRaw, + const WideString& wsAttr, + WideString& wsValue) { + if (m_eType != XFA_TEXTPROVIDERTYPE_Text) + return false; + + if (!bURI) + return false; + + CXFA_Node* pWidgetNode = m_pWidgetAcc->GetNode(); + CXFA_Node* pParent = pWidgetNode->GetParent(); + CXFA_Document* pDocument = pWidgetNode->GetDocument(); + CXFA_Node* pIDNode = nullptr; + CXFA_WidgetAcc* pEmbAcc = nullptr; + if (pParent) + pIDNode = pDocument->GetNodeByID(pParent, wsAttr.AsStringView()); + + if (!pIDNode) { + pIDNode = pDocument->GetNodeByID( + ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)), + wsAttr.AsStringView()); + } + if (pIDNode) + pEmbAcc = pIDNode->GetWidgetAcc(); + + if (!pEmbAcc) + return false; + + wsValue = pEmbAcc->GetValue(XFA_VALUEPICTURE_Display); + return true; +} diff --git a/xfa/fxfa/cxfa_textprovider.h b/xfa/fxfa/cxfa_textprovider.h new file mode 100644 index 0000000000000000000000000000000000000000..3431c9a30c7a79583e8b797436721cf2f8ebe70a --- /dev/null +++ b/xfa/fxfa/cxfa_textprovider.h @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTPROVIDER_H_ +#define XFA_FXFA_CXFA_TEXTPROVIDER_H_ + +#include "core/fxcrt/fx_string.h" +#include "xfa/fxfa/cxfa_textlayout.h" +#include "xfa/fxfa/cxfa_widgetacc.h" + +class CXFA_Font; +class CXFA_Node; + +enum XFA_TEXTPROVIDERTYPE { + XFA_TEXTPROVIDERTYPE_Text, + XFA_TEXTPROVIDERTYPE_Datasets, + XFA_TEXTPROVIDERTYPE_Caption, + XFA_TEXTPROVIDERTYPE_Rollover, + XFA_TEXTPROVIDERTYPE_Down, +}; + +class CXFA_TextProvider { + public: + CXFA_TextProvider(CXFA_WidgetAcc* pWidgetAcc, XFA_TEXTPROVIDERTYPE eType) + : m_pWidgetAcc(pWidgetAcc), m_eType(eType) { + ASSERT(m_pWidgetAcc); + } + ~CXFA_TextProvider() {} + + CXFA_Node* GetTextNode(bool& bRichText); + CXFA_Para* GetParaIfExists(); + CXFA_Font* GetFontIfExists(); + bool IsCheckButtonAndAutoWidth(); + bool GetEmbbedObj(bool bURI, + bool bRaw, + const WideString& wsAttr, + WideString& wsValue); + + private: + CXFA_WidgetAcc* m_pWidgetAcc; + XFA_TEXTPROVIDERTYPE m_eType; +}; + +#endif // XFA_FXFA_CXFA_TEXTPROVIDER_H_ diff --git a/xfa/fxfa/cxfa_texttabstopscontext.cpp b/xfa/fxfa/cxfa_texttabstopscontext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b594f1cc690f997858c8bf4caaf172330e491d74 --- /dev/null +++ b/xfa/fxfa/cxfa_texttabstopscontext.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_texttabstopscontext.h" + +#include <algorithm> + +CXFA_TextTabstopsContext::CXFA_TextTabstopsContext() + : m_iTabIndex(-1), m_bTabstops(false), m_fTabWidth(0), m_fLeft(0) {} + +CXFA_TextTabstopsContext::~CXFA_TextTabstopsContext() {} + +void CXFA_TextTabstopsContext::Append(uint32_t dwAlign, float fTabstops) { + XFA_TABSTOPS tabstop; + tabstop.dwAlign = dwAlign; + tabstop.fTabstops = fTabstops; + + auto it = std::lower_bound(m_tabstops.begin(), m_tabstops.end(), tabstop); + m_tabstops.insert(it, tabstop); +} + +void CXFA_TextTabstopsContext::RemoveAll() { + m_tabstops.clear(); +} + +void CXFA_TextTabstopsContext::Reset() { + m_iTabIndex = -1; + m_bTabstops = false; + m_fTabWidth = 0; + m_fLeft = 0; +} diff --git a/xfa/fxfa/cxfa_texttabstopscontext.h b/xfa/fxfa/cxfa_texttabstopscontext.h new file mode 100644 index 0000000000000000000000000000000000000000..9837e357daba5ebc4f8ff540d96484528e44e684 --- /dev/null +++ b/xfa/fxfa/cxfa_texttabstopscontext.h @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTTABSTOPSCONTEXT_H_ +#define XFA_FXFA_CXFA_TEXTTABSTOPSCONTEXT_H_ + +#include <stdint.h> + +#include <vector> + +struct XFA_TABSTOPS { + uint32_t dwAlign; + float fTabstops; + + bool operator<(const XFA_TABSTOPS& that) const { + return fTabstops < that.fTabstops; + } +}; + +class CXFA_TextTabstopsContext { + public: + CXFA_TextTabstopsContext(); + ~CXFA_TextTabstopsContext(); + + void Append(uint32_t dwAlign, float fTabstops); + void RemoveAll(); + void Reset(); + + int32_t m_iTabIndex; + bool m_bTabstops; + float m_fTabWidth; + float m_fLeft; + std::vector<XFA_TABSTOPS> m_tabstops; +}; + +#endif // XFA_FXFA_CXFA_TEXTTABSTOPSCONTEXT_H_ diff --git a/xfa/fxfa/cxfa_textuserdata.cpp b/xfa/fxfa/cxfa_textuserdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c46978609aa1ff2d6297bb8f3d480dba77ca5a4 --- /dev/null +++ b/xfa/fxfa/cxfa_textuserdata.cpp @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_textuserdata.h" + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_csscomputedstyle.h" +#include "core/fxcrt/css/cfx_cssstyleselector.h" +#include "xfa/fxfa/cxfa_linkuserdata.h" + +CXFA_TextUserData::CXFA_TextUserData( + const RetainPtr<CFX_CSSComputedStyle>& pStyle) + : m_pStyle(pStyle) {} + +CXFA_TextUserData::CXFA_TextUserData( + const RetainPtr<CFX_CSSComputedStyle>& pStyle, + const RetainPtr<CXFA_LinkUserData>& pLinkData) + : m_pStyle(pStyle), m_pLinkData(pLinkData) {} + +CXFA_TextUserData::~CXFA_TextUserData() {} diff --git a/xfa/fxfa/cxfa_textuserdata.h b/xfa/fxfa/cxfa_textuserdata.h new file mode 100644 index 0000000000000000000000000000000000000000..c1af217bf12f1a56f4be4fe49451b0ce05da97c7 --- /dev/null +++ b/xfa/fxfa/cxfa_textuserdata.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_TEXTUSERDATA_H_ +#define XFA_FXFA_CXFA_TEXTUSERDATA_H_ + +#include "core/fxcrt/retain_ptr.h" + +class CFX_CSSComputedStyle; +class CXFA_LinkUserData; + +class CXFA_TextUserData : public Retainable { + public: + template <typename T, typename... Args> + friend RetainPtr<T> pdfium::MakeRetain(Args&&... args); + + RetainPtr<CFX_CSSComputedStyle> m_pStyle; + RetainPtr<CXFA_LinkUserData> m_pLinkData; + + private: + explicit CXFA_TextUserData(const RetainPtr<CFX_CSSComputedStyle>& pStyle); + CXFA_TextUserData(const RetainPtr<CFX_CSSComputedStyle>& pStyle, + const RetainPtr<CXFA_LinkUserData>& pLinkData); + ~CXFA_TextUserData() override; +}; + +#endif // XFA_FXFA_CXFA_TEXTUSERDATA_H_ diff --git a/xfa/fxfa/cxfa_widgetacc.cpp b/xfa/fxfa/cxfa_widgetacc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad4e08ef73cd57008c09adf4c847ffa0e87e9a3e --- /dev/null +++ b/xfa/fxfa/cxfa_widgetacc.cpp @@ -0,0 +1,2757 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_widgetacc.h" + +#include <algorithm> +#include <tuple> +#include <vector> + +#include "core/fxcrt/cfx_decimal.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/stl_util.h" +#include "xfa/fde/cfde_textout.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_fontmgr.h" +#include "xfa/fxfa/cxfa_textlayout.h" +#include "xfa/fxfa/cxfa_textprovider.h" +#include "xfa/fxfa/parser/cxfa_bind.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_calculate.h" +#include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_comb.h" +#include "xfa/fxfa/parser/cxfa_decimal.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_event.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_format.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_items.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" +#include "xfa/fxfa/parser/cxfa_margin.h" +#include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_picture.h" +#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxfa/parser/cxfa_stroke.h" +#include "xfa/fxfa/parser/cxfa_ui.h" +#include "xfa/fxfa/parser/cxfa_validate.h" +#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +class CXFA_WidgetLayoutData { + public: + CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {} + virtual ~CXFA_WidgetLayoutData() {} + + float m_fWidgetHeight; +}; + +namespace { + +constexpr uint8_t g_inv_base64[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, + 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, + 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255, +}; + +uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { + uint8_t* pCP; + int32_t i = 0, j = 0; + if (iLen == 0) { + iLen = strlen((char*)pStr); + } + pCP = FX_Alloc(uint8_t, iLen + 1); + for (; i < iLen; i++) { + if ((pStr[i] & 128) == 0) { + if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { + pCP[j++] = pStr[i]; + } + } + } + pCP[j] = '\0'; + return pCP; +} + +int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) { + if (!pStr) { + return 0; + } + uint8_t* pBuffer = + XFA_RemoveBase64Whitespace((uint8_t*)pStr, strlen((char*)pStr)); + if (!pBuffer) { + return 0; + } + int32_t iLen = strlen((char*)pBuffer); + int32_t i = 0, j = 0; + uint32_t dwLimb = 0; + for (; i + 3 < iLen; i += 4) { + if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || + pBuffer[i + 3] == '=') { + if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { + break; + } + if (pBuffer[i + 2] == '=') { + dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) | + ((uint32_t)g_inv_base64[pBuffer[i + 1]]); + pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; + j++; + } else { + dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) | + ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) | + ((uint32_t)g_inv_base64[pBuffer[i + 2]]); + pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; + pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; + j += 2; + } + } else { + dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) | + ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) | + ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) | + ((uint32_t)g_inv_base64[pBuffer[i + 3]]); + pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; + pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; + pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; + j += 3; + } + } + FX_Free(pBuffer); + return j; +} + +FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) { + WideString wsContentType(wsType); + wsContentType.MakeLower(); + if (wsContentType == L"image/jpg") + return FXCODEC_IMAGE_JPG; + if (wsContentType == L"image/png") + return FXCODEC_IMAGE_PNG; + if (wsContentType == L"image/gif") + return FXCODEC_IMAGE_GIF; + if (wsContentType == L"image/bmp") + return FXCODEC_IMAGE_BMP; + if (wsContentType == L"image/tif") + return FXCODEC_IMAGE_TIF; + return FXCODEC_IMAGE_UNKNOWN; +} + +RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc, + CXFA_Image* pImage, + bool& bNameImage, + int32_t& iImageXDpi, + int32_t& iImageYDpi) { + WideString wsHref = pImage->GetHref(); + WideString wsImage = pImage->GetContent(); + if (wsHref.IsEmpty() && wsImage.IsEmpty()) + return nullptr; + + FXCODEC_IMAGE_TYPE type = XFA_GetImageType(pImage->GetContentType()); + ByteString bsContent; + uint8_t* pImageBuffer = nullptr; + RetainPtr<IFX_SeekableReadStream> pImageFileRead; + if (wsImage.GetLength() > 0) { + XFA_AttributeEnum iEncoding = pImage->GetTransferEncoding(); + if (iEncoding == XFA_AttributeEnum::Base64) { + ByteString bsData = wsImage.UTF8Encode(); + int32_t iLength = bsData.GetLength(); + pImageBuffer = FX_Alloc(uint8_t, iLength); + int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer); + if (iRead > 0) { + pImageFileRead = + pdfium::MakeRetain<CFX_MemoryStream>(pImageBuffer, iRead, false); + } + } else { + bsContent = ByteString::FromUnicode(wsImage); + pImageFileRead = pdfium::MakeRetain<CFX_MemoryStream>( + const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength(), + false); + } + } else { + WideString wsURL = wsHref; + if (wsURL.Left(7) != L"http://" && wsURL.Left(6) != L"ftp://") { + RetainPtr<CFX_DIBitmap> pBitmap = + pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi); + if (pBitmap) { + bNameImage = true; + return pBitmap; + } + } + pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL); + } + if (!pImageFileRead) { + FX_Free(pImageBuffer); + return nullptr; + } + bNameImage = false; + RetainPtr<CFX_DIBitmap> pBitmap = + XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); + FX_Free(pImageBuffer); + return pBitmap; +} + +class CXFA_TextLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_TextLayoutData() {} + ~CXFA_TextLayoutData() override {} + + CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); } + CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); } + + void LoadText(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { + if (m_pTextLayout) + return; + + m_pTextProvider = + pdfium::MakeUnique<CXFA_TextProvider>(pAcc, XFA_TEXTPROVIDERTYPE_Text); + m_pTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pTextProvider.get()); + } + + private: + std::unique_ptr<CXFA_TextLayout> m_pTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pTextProvider; +}; + +class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_ImageLayoutData() + : m_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {} + + ~CXFA_ImageLayoutData() override {} + + bool LoadImageData(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { + if (m_pDIBitmap) + return true; + + CXFA_Value* value = pAcc->GetNode()->GetFormValueIfExists(); + if (!value) + return false; + + CXFA_Image* image = value->GetImageIfExists(); + if (!image) + return false; + + pAcc->SetImageImage(XFA_LoadImageData(doc, image, m_bNamedImage, + m_iImageXDpi, m_iImageYDpi)); + return !!m_pDIBitmap; + } + + RetainPtr<CFX_DIBitmap> m_pDIBitmap; + bool m_bNamedImage; + int32_t m_iImageXDpi; + int32_t m_iImageYDpi; +}; + +class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData { + public: + CXFA_FieldLayoutData() {} + ~CXFA_FieldLayoutData() override {} + + bool LoadCaption(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { + if (m_pCapTextLayout) + return true; + CXFA_Caption* caption = pAcc->GetNode()->GetCaptionIfExists(); + if (!caption || caption->IsHidden()) + return false; + + m_pCapTextProvider = pdfium::MakeUnique<CXFA_TextProvider>( + pAcc, XFA_TEXTPROVIDERTYPE_Caption); + m_pCapTextLayout = + pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pCapTextProvider.get()); + return true; + } + + std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout; + std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider; + std::unique_ptr<CFDE_TextOut> m_pTextOut; + std::vector<float> m_FieldSplitArray; +}; + +class CXFA_TextEditData : public CXFA_FieldLayoutData {}; + +class CXFA_ImageEditData : public CXFA_FieldLayoutData { + public: + CXFA_ImageEditData() + : m_bNamedImage(false), m_iImageXDpi(0), m_iImageYDpi(0) {} + + ~CXFA_ImageEditData() override {} + + bool LoadImageData(CXFA_FFDoc* doc, CXFA_WidgetAcc* pAcc) { + if (m_pDIBitmap) + return true; + + CXFA_Value* value = pAcc->GetNode()->GetFormValueIfExists(); + if (!value) + return false; + + CXFA_Image* image = value->GetImageIfExists(); + if (!image) + return false; + + pAcc->SetImageEditImage(XFA_LoadImageData(doc, image, m_bNamedImage, + m_iImageXDpi, m_iImageYDpi)); + return !!m_pDIBitmap; + } + + RetainPtr<CFX_DIBitmap> m_pDIBitmap; + bool m_bNamedImage; + int32_t m_iImageXDpi; + int32_t m_iImageYDpi; +}; + +float GetEdgeThickness(const std::vector<CXFA_Stroke*>& strokes, + bool b3DStyle, + int32_t nIndex) { + float fThickness = 0; + + CXFA_Stroke* stroke = strokes[nIndex * 2 + 1]; + if (stroke->IsVisible()) { + if (nIndex == 0) + fThickness += 2.5f; + + fThickness += stroke->GetThickness() * (b3DStyle ? 4 : 2); + } + return fThickness; +} + +bool SplitDateTime(const WideString& wsDateTime, + WideString& wsDate, + WideString& wsTime) { + wsDate = L""; + wsTime = L""; + if (wsDateTime.IsEmpty()) + return false; + + auto nSplitIndex = wsDateTime.Find('T'); + if (!nSplitIndex.has_value()) + nSplitIndex = wsDateTime.Find(' '); + if (!nSplitIndex.has_value()) + return false; + + wsDate = wsDateTime.Left(nSplitIndex.value()); + if (!wsDate.IsEmpty()) { + if (!std::any_of(wsDate.begin(), wsDate.end(), std::iswdigit)) + return false; + } + wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex.value() - 1); + if (!wsTime.IsEmpty()) { + if (!std::any_of(wsTime.begin(), wsTime.end(), std::iswdigit)) + return false; + } + return true; +} + +std::pair<XFA_Element, CXFA_Node*> CreateUIChild(CXFA_Node* pNode) { + XFA_Element eType = pNode->GetElementType(); + XFA_Element eWidgetType = eType; + if (eType != XFA_Element::Field && eType != XFA_Element::Draw) + return {eWidgetType, nullptr}; + + eWidgetType = XFA_Element::Unknown; + XFA_Element eUIType = XFA_Element::Unknown; + auto* defValue = + pNode->JSObject()->GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value); + XFA_Element eValueType = + defValue ? defValue->GetChildValueClassID() : XFA_Element::Unknown; + switch (eValueType) { + case XFA_Element::Boolean: + eUIType = XFA_Element::CheckButton; + break; + case XFA_Element::Integer: + case XFA_Element::Decimal: + case XFA_Element::Float: + eUIType = XFA_Element::NumericEdit; + break; + case XFA_Element::ExData: + case XFA_Element::Text: + eUIType = XFA_Element::TextEdit; + eWidgetType = XFA_Element::Text; + break; + case XFA_Element::Date: + case XFA_Element::Time: + case XFA_Element::DateTime: + eUIType = XFA_Element::DateTimeEdit; + break; + case XFA_Element::Image: + eUIType = XFA_Element::ImageEdit; + eWidgetType = XFA_Element::Image; + break; + case XFA_Element::Arc: + case XFA_Element::Line: + case XFA_Element::Rectangle: + eUIType = XFA_Element::DefaultUi; + eWidgetType = eValueType; + break; + default: + break; + } + + CXFA_Node* pUIChild = nullptr; + CXFA_Ui* pUI = + pNode->JSObject()->GetOrCreateProperty<CXFA_Ui>(0, XFA_Element::Ui); + CXFA_Node* pChild = pUI ? pUI->GetFirstChild() : nullptr; + for (; pChild; pChild = pChild->GetNextSibling()) { + XFA_Element eChildType = pChild->GetElementType(); + if (eChildType == XFA_Element::Extras || + eChildType == XFA_Element::Picture) { + continue; + } + + auto node = CXFA_Node::Create(pChild->GetDocument(), XFA_Element::Ui, + XFA_PacketType::Form); + if (node && node->HasPropertyFlags(eChildType, XFA_PROPERTYFLAG_OneOf)) { + pUIChild = pChild; + break; + } + } + + if (eType == XFA_Element::Draw) { + XFA_Element eDraw = + pUIChild ? pUIChild->GetElementType() : XFA_Element::Unknown; + switch (eDraw) { + case XFA_Element::TextEdit: + eWidgetType = XFA_Element::Text; + break; + case XFA_Element::ImageEdit: + eWidgetType = XFA_Element::Image; + break; + default: + eWidgetType = eWidgetType == XFA_Element::Unknown ? XFA_Element::Text + : eWidgetType; + break; + } + } else { + if (pUIChild && pUIChild->GetElementType() == XFA_Element::DefaultUi) { + eWidgetType = XFA_Element::TextEdit; + } else { + eWidgetType = + pUIChild ? pUIChild->GetElementType() + : (eUIType == XFA_Element::Unknown ? XFA_Element::TextEdit + : eUIType); + } + } + + if (!pUIChild) { + if (eUIType == XFA_Element::Unknown) { + eUIType = XFA_Element::TextEdit; + if (defValue) { + defValue->JSObject()->GetOrCreateProperty<CXFA_Text>(0, + XFA_Element::Text); + } + } + return {eWidgetType, + pUI ? pUI->JSObject()->GetOrCreateProperty<CXFA_Node>(0, eUIType) + : nullptr}; + } + + if (eUIType != XFA_Element::Unknown) + return {eWidgetType, pUIChild}; + + switch (pUIChild->GetElementType()) { + case XFA_Element::CheckButton: { + eValueType = XFA_Element::Text; + if (CXFA_Items* pItems = + pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false)) { + if (CXFA_Node* pItem = + pItems->GetChild<CXFA_Node>(0, XFA_Element::Unknown, false)) { + eValueType = pItem->GetElementType(); + } + } + break; + } + case XFA_Element::DateTimeEdit: + eValueType = XFA_Element::DateTime; + break; + case XFA_Element::ImageEdit: + eValueType = XFA_Element::Image; + break; + case XFA_Element::NumericEdit: + eValueType = XFA_Element::Float; + break; + case XFA_Element::ChoiceList: { + eValueType = (pUIChild->JSObject()->GetEnum(XFA_Attribute::Open) == + XFA_AttributeEnum::MultiSelect) + ? XFA_Element::ExData + : XFA_Element::Text; + break; + } + case XFA_Element::Barcode: + case XFA_Element::Button: + case XFA_Element::PasswordEdit: + case XFA_Element::Signature: + case XFA_Element::TextEdit: + default: + eValueType = XFA_Element::Text; + break; + } + if (defValue) + defValue->JSObject()->GetOrCreateProperty<CXFA_Node>(0, eValueType); + + return {eWidgetType, pUIChild}; +} + +} // namespace + +CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_Node* pNode) + : m_bIsNull(true), + m_bPreNull(true), + m_pUiChildNode(nullptr), + m_eUIType(XFA_Element::Unknown), + m_pNode(pNode) {} + +CXFA_WidgetAcc::~CXFA_WidgetAcc() = default; + +void CXFA_WidgetAcc::ResetData() { + WideString wsValue; + XFA_Element eUIType = GetUIType(); + switch (eUIType) { + case XFA_Element::ImageEdit: { + CXFA_Value* imageValue = m_pNode->GetDefaultValueIfExists(); + CXFA_Image* image = imageValue ? imageValue->GetImageIfExists() : nullptr; + WideString wsContentType, wsHref; + if (image) { + wsValue = image->GetContent(); + wsContentType = image->GetContentType(); + wsHref = image->GetHref(); + } + SetImageEdit(wsContentType, wsHref, wsValue); + break; + } + case XFA_Element::ExclGroup: { + CXFA_Node* pNextChild = m_pNode->GetFirstContainerChild(); + while (pNextChild) { + CXFA_Node* pChild = pNextChild; + CXFA_WidgetAcc* pAcc = pChild->GetWidgetAcc(); + if (!pAcc) + continue; + + bool done = false; + if (wsValue.IsEmpty()) { + CXFA_Value* defValue = pAcc->GetNode()->GetDefaultValueIfExists(); + if (defValue) { + wsValue = defValue->GetChildValueContent(); + SetValue(XFA_VALUEPICTURE_Raw, wsValue); + pAcc->SetValue(XFA_VALUEPICTURE_Raw, wsValue); + done = true; + } + } + if (!done) { + CXFA_Items* pItems = + pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + continue; + + WideString itemText; + if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) { + itemText = + pItems->GetChild<CXFA_Node>(1, XFA_Element::Unknown, false) + ->JSObject() + ->GetContent(false); + } + pAcc->SetValue(XFA_VALUEPICTURE_Raw, itemText); + } + pNextChild = pChild->GetNextContainerSibling(); + } + break; + } + case XFA_Element::ChoiceList: + ClearAllSelections(); + default: { + CXFA_Value* defValue = m_pNode->GetDefaultValueIfExists(); + if (defValue) + wsValue = defValue->GetChildValueContent(); + + SetValue(XFA_VALUEPICTURE_Raw, wsValue); + break; + } + } +} + +void CXFA_WidgetAcc::SetImageEdit(const WideString& wsContentType, + const WideString& wsHref, + const WideString& wsData) { + CXFA_Value* formValue = m_pNode->GetFormValueIfExists(); + CXFA_Image* image = formValue ? formValue->GetImageIfExists() : nullptr; + if (image) { + image->SetContentType(WideString(wsContentType)); + image->SetHref(wsHref); + } + + m_pNode->JSObject()->SetContent(wsData, GetFormatDataValue(wsData), true, + false, true); + + CXFA_Node* pBind = m_pNode->GetBindData(); + if (!pBind) { + if (image) + image->SetTransferEncoding(XFA_AttributeEnum::Base64); + return; + } + pBind->JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType, false, + false); + CXFA_Node* pHrefNode = pBind->GetFirstChild(); + if (pHrefNode) { + pHrefNode->JSObject()->SetCData(XFA_Attribute::Value, wsHref, false, false); + } else { + CFX_XMLNode* pXMLNode = pBind->GetXMLMappingNode(); + ASSERT(pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element); + static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"href", wsHref); + } +} + +CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) { + return static_cast<CXFA_FFWidget*>(pWidget->GetNext()); +} + +void CXFA_WidgetAcc::UpdateUIDisplay(CXFA_FFDocView* docView, + CXFA_FFWidget* pExcept) { + CXFA_FFWidget* pWidget = docView->GetWidgetForNode(m_pNode); + for (; pWidget; pWidget = GetNextWidget(pWidget)) { + if (pWidget == pExcept || !pWidget->IsLoaded() || + (GetUIType() != XFA_Element::CheckButton && pWidget->IsFocused())) { + continue; + } + pWidget->UpdateFWLData(); + pWidget->AddInvalidateRect(); + } +} + +void CXFA_WidgetAcc::CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (!caption || !caption->IsVisible()) + return; + + LoadCaption(doc); + + XFA_Element eUIType = GetUIType(); + XFA_AttributeEnum iCapPlacement = caption->GetPlacementType(); + float fCapReserve = caption->GetReserve(); + const bool bVert = iCapPlacement == XFA_AttributeEnum::Top || + iCapPlacement == XFA_AttributeEnum::Bottom; + const bool bReserveExit = fCapReserve > 0.01; + CXFA_TextLayout* pCapTextLayout = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->m_pCapTextLayout.get(); + if (pCapTextLayout) { + if (!bVert && eUIType != XFA_Element::Button) + szCap.width = fCapReserve; + + CFX_SizeF minSize; + szCap = pCapTextLayout->CalcSize(minSize, szCap); + if (bReserveExit) + bVert ? szCap.height = fCapReserve : szCap.width = fCapReserve; + } else { + float fFontSize = 10.0f; + CXFA_Font* font = caption->GetFontIfExists(); + if (font) { + fFontSize = font->GetFontSize(); + } else { + CXFA_Font* widgetfont = m_pNode->GetFontIfExists(); + if (widgetfont) + fFontSize = widgetfont->GetFontSize(); + } + + if (bVert) { + szCap.height = fCapReserve > 0 ? fCapReserve : fFontSize; + } else { + szCap.width = fCapReserve > 0 ? fCapReserve : 0; + szCap.height = fFontSize; + } + } + + CXFA_Margin* captionMargin = caption->GetMarginIfExists(); + if (!captionMargin) + return; + + float fLeftInset = captionMargin->GetLeftInset(); + float fTopInset = captionMargin->GetTopInset(); + float fRightInset = captionMargin->GetRightInset(); + float fBottomInset = captionMargin->GetBottomInset(); + if (bReserveExit) { + bVert ? (szCap.width += fLeftInset + fRightInset) + : (szCap.height += fTopInset + fBottomInset); + } else { + szCap.width += fLeftInset + fRightInset; + szCap.height += fTopInset + fBottomInset; + } +} + +bool CXFA_WidgetAcc::CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + CFX_SizeF szCap; + CalcCaptionSize(doc, szCap); + + CFX_RectF rtUIMargin = GetUIMargin(); + size.width += rtUIMargin.left + rtUIMargin.width; + size.height += rtUIMargin.top + rtUIMargin.height; + if (szCap.width > 0 && szCap.height > 0) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + XFA_AttributeEnum placement = caption ? caption->GetPlacementType() + : CXFA_Caption::kDefaultPlacementType; + switch (placement) { + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Right: + case XFA_AttributeEnum::Inline: { + size.width += szCap.width; + size.height = std::max(size.height, szCap.height); + } break; + case XFA_AttributeEnum::Top: + case XFA_AttributeEnum::Bottom: { + size.height += szCap.height; + size.width = std::max(size.width, szCap.width); + } + default: + break; + } + } + return CalculateWidgetAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculateWidgetAutoSize(CFX_SizeF& size) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + size.width += margin->GetLeftInset() + margin->GetRightInset(); + size.height += margin->GetTopInset() + margin->GetBottomInset(); + } + + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) + size.width += para->GetMarginLeft() + para->GetTextIndent(); + + Optional<float> width = m_pNode->TryWidth(); + if (width) { + size.width = *width; + } else { + Optional<float> min = m_pNode->TryMinWidth(); + if (min) + size.width = std::max(size.width, *min); + + Optional<float> max = m_pNode->TryMaxWidth(); + if (max && *max > 0) + size.width = std::min(size.width, *max); + } + + Optional<float> height = m_pNode->TryHeight(); + if (height) { + size.height = *height; + } else { + Optional<float> min = m_pNode->TryMinHeight(); + if (min) + size.height = std::max(size.height, *min); + + Optional<float> max = m_pNode->TryMaxHeight(); + if (max && *max > 0) + size.height = std::min(size.height, *max); + } + return true; +} + +void CXFA_WidgetAcc::CalculateTextContentSize(CXFA_FFDoc* doc, + CFX_SizeF& size) { + float fFontSize = m_pNode->GetFontSize(); + WideString wsText = GetValue(XFA_VALUEPICTURE_Display); + if (wsText.IsEmpty()) { + size.height += fFontSize; + return; + } + + wchar_t wcEnter = '\n'; + wchar_t wsLast = wsText[wsText.GetLength() - 1]; + if (wsLast == wcEnter) + wsText = wsText + wcEnter; + + CXFA_FieldLayoutData* layoutData = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); + if (!layoutData->m_pTextOut) { + layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>(); + CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get(); + pTextOut->SetFont(GetFDEFont(doc)); + pTextOut->SetFontSize(fFontSize); + pTextOut->SetLineBreakTolerance(fFontSize * 0.2f); + pTextOut->SetLineSpace(m_pNode->GetLineHeight()); + + FDE_TextStyle dwStyles; + dwStyles.last_line_height_ = true; + if (GetUIType() == XFA_Element::TextEdit && IsMultiLine()) + dwStyles.line_wrap_ = true; + + pTextOut->SetStyles(dwStyles); + } + layoutData->m_pTextOut->CalcLogicSize(wsText, size); +} + +bool CXFA_WidgetAcc::CalculateTextEditAutoSize(CXFA_FFDoc* doc, + CFX_SizeF& size) { + if (size.width > 0) { + CFX_SizeF szOrz = size; + CFX_SizeF szCap; + CalcCaptionSize(doc, szCap); + bool bCapExit = szCap.width > 0.01 && szCap.height > 0.01; + XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; + if (bCapExit) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + iCapPlacement = caption ? caption->GetPlacementType() + : CXFA_Caption::kDefaultPlacementType; + switch (iCapPlacement) { + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Right: + case XFA_AttributeEnum::Inline: { + size.width -= szCap.width; + } + default: + break; + } + } + CFX_RectF rtUIMargin = GetUIMargin(); + size.width -= rtUIMargin.left + rtUIMargin.width; + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + size.width -= margin->GetLeftInset() + margin->GetRightInset(); + + CalculateTextContentSize(doc, size); + size.height += rtUIMargin.top + rtUIMargin.height; + if (bCapExit) { + switch (iCapPlacement) { + case XFA_AttributeEnum::Left: + case XFA_AttributeEnum::Right: + case XFA_AttributeEnum::Inline: { + size.height = std::max(size.height, szCap.height); + } break; + case XFA_AttributeEnum::Top: + case XFA_AttributeEnum::Bottom: { + size.height += szCap.height; + } + default: + break; + } + } + size.width = szOrz.width; + return CalculateWidgetAutoSize(size); + } + CalculateTextContentSize(doc, size); + return CalculateFieldAutoSize(doc, size); +} + +bool CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, + CFX_SizeF& size) { + float fCheckSize = GetCheckButtonSize(); + size = CFX_SizeF(fCheckSize, fCheckSize); + return CalculateFieldAutoSize(doc, size); +} + +bool CXFA_WidgetAcc::CalculatePushButtonAutoSize(CXFA_FFDoc* doc, + CFX_SizeF& size) { + CalcCaptionSize(doc, size); + return CalculateWidgetAutoSize(size); +} + +CFX_SizeF CXFA_WidgetAcc::CalculateImageSize(float img_width, + float img_height, + float dpi_x, + float dpi_y) { + CFX_RectF rtImage(0, 0, XFA_UnitPx2Pt(img_width, dpi_x), + XFA_UnitPx2Pt(img_height, dpi_y)); + + CFX_RectF rtFit; + Optional<float> width = m_pNode->TryWidth(); + if (width) { + rtFit.width = *width; + GetWidthWithoutMargin(rtFit.width); + } else { + rtFit.width = rtImage.width; + } + + Optional<float> height = m_pNode->TryHeight(); + if (height) { + rtFit.height = *height; + GetHeightWithoutMargin(rtFit.height); + } else { + rtFit.height = rtImage.height; + } + + return rtFit.Size(); +} + +bool CXFA_WidgetAcc::CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size) { + if (!GetImageImage()) + LoadImageImage(doc); + + size.clear(); + RetainPtr<CFX_DIBitmap> pBitmap = GetImageImage(); + if (!pBitmap) + return CalculateWidgetAutoSize(size); + + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + GetImageDpi(iImageXDpi, iImageYDpi); + + size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), + iImageXDpi, iImageYDpi); + return CalculateWidgetAutoSize(size); +} + +bool CXFA_WidgetAcc::CalculateImageEditAutoSize(CXFA_FFDoc* doc, + CFX_SizeF& size) { + if (!GetImageEditImage()) + LoadImageEditImage(doc); + + size.clear(); + RetainPtr<CFX_DIBitmap> pBitmap = GetImageEditImage(); + if (!pBitmap) + return CalculateFieldAutoSize(doc, size); + + int32_t iImageXDpi = 0; + int32_t iImageYDpi = 0; + GetImageEditDpi(iImageXDpi, iImageYDpi); + + size = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(), + iImageXDpi, iImageYDpi); + return CalculateFieldAutoSize(doc, size); +} + +bool CXFA_WidgetAcc::LoadImageImage(CXFA_FFDoc* doc) { + InitLayoutData(); + return static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) + ->LoadImageData(doc, this); +} + +bool CXFA_WidgetAcc::LoadImageEditImage(CXFA_FFDoc* doc) { + InitLayoutData(); + return static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) + ->LoadImageData(doc, this); +} + +void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { + CXFA_ImageLayoutData* pData = + static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); + iImageXDpi = pData->m_iImageXDpi; + iImageYDpi = pData->m_iImageYDpi; +} + +void CXFA_WidgetAcc::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) { + CXFA_ImageEditData* pData = + static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); + iImageXDpi = pData->m_iImageXDpi; + iImageYDpi = pData->m_iImageYDpi; +} + +void CXFA_WidgetAcc::LoadText(CXFA_FFDoc* doc) { + InitLayoutData(); + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->LoadText(doc, this); +} + +float CXFA_WidgetAcc::CalculateWidgetAutoWidth(float fWidthCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fWidthCalc += margin->GetLeftInset() + margin->GetRightInset(); + + Optional<float> min = m_pNode->TryMinWidth(); + if (min) + fWidthCalc = std::max(fWidthCalc, *min); + + Optional<float> max = m_pNode->TryMaxWidth(); + if (max && *max > 0) + fWidthCalc = std::min(fWidthCalc, *max); + + return fWidthCalc; +} + +float CXFA_WidgetAcc::GetWidthWithoutMargin(float fWidthCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fWidthCalc -= margin->GetLeftInset() + margin->GetRightInset(); + return fWidthCalc; +} + +float CXFA_WidgetAcc::CalculateWidgetAutoHeight(float fHeightCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fHeightCalc += margin->GetTopInset() + margin->GetBottomInset(); + + Optional<float> min = m_pNode->TryMinHeight(); + if (min) + fHeightCalc = std::max(fHeightCalc, *min); + + Optional<float> max = m_pNode->TryMaxHeight(); + if (max && *max > 0) + fHeightCalc = std::min(fHeightCalc, *max); + + return fHeightCalc; +} + +float CXFA_WidgetAcc::GetHeightWithoutMargin(float fHeightCalc) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) + fHeightCalc -= margin->GetTopInset() + margin->GetBottomInset(); + return fHeightCalc; +} + +void CXFA_WidgetAcc::StartWidgetLayout(CXFA_FFDoc* doc, + float& fCalcWidth, + float& fCalcHeight) { + InitLayoutData(); + + XFA_Element eUIType = GetUIType(); + if (eUIType == XFA_Element::Text) { + m_pLayoutData->m_fWidgetHeight = m_pNode->TryHeight().value_or(-1); + StartTextLayout(doc, fCalcWidth, fCalcHeight); + return; + } + if (fCalcWidth > 0 && fCalcHeight > 0) + return; + + m_pLayoutData->m_fWidgetHeight = -1; + float fWidth = 0; + if (fCalcWidth > 0 && fCalcHeight < 0) { + Optional<float> height = m_pNode->TryHeight(); + if (height) + fCalcHeight = *height; + else + CalculateAccWidthAndHeight(doc, eUIType, fCalcWidth, fCalcHeight); + + m_pLayoutData->m_fWidgetHeight = fCalcHeight; + return; + } + if (fCalcWidth < 0 && fCalcHeight < 0) { + Optional<float> height; + Optional<float> width = m_pNode->TryWidth(); + if (width) { + fWidth = *width; + + height = m_pNode->TryHeight(); + if (height) + fCalcHeight = *height; + } + if (!width || !height) + CalculateAccWidthAndHeight(doc, eUIType, fWidth, fCalcHeight); + + fCalcWidth = fWidth; + } + m_pLayoutData->m_fWidgetHeight = fCalcHeight; +} + +void CXFA_WidgetAcc::CalculateAccWidthAndHeight(CXFA_FFDoc* doc, + XFA_Element eUIType, + float& fWidth, + float& fCalcHeight) { + CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight); + switch (eUIType) { + case XFA_Element::Barcode: + case XFA_Element::ChoiceList: + case XFA_Element::Signature: + CalculateFieldAutoSize(doc, sz); + break; + case XFA_Element::ImageEdit: + CalculateImageEditAutoSize(doc, sz); + break; + case XFA_Element::Button: + CalculatePushButtonAutoSize(doc, sz); + break; + case XFA_Element::CheckButton: + CalculateCheckButtonAutoSize(doc, sz); + break; + case XFA_Element::DateTimeEdit: + case XFA_Element::NumericEdit: + case XFA_Element::PasswordEdit: + case XFA_Element::TextEdit: + CalculateTextEditAutoSize(doc, sz); + break; + case XFA_Element::Image: + CalculateImageAutoSize(doc, sz); + break; + case XFA_Element::Arc: + case XFA_Element::Line: + case XFA_Element::Rectangle: + case XFA_Element::Subform: + case XFA_Element::ExclGroup: + CalculateWidgetAutoSize(sz); + break; + default: + break; + } + fWidth = sz.width; + m_pLayoutData->m_fWidgetHeight = sz.height; + fCalcHeight = sz.height; +} + +bool CXFA_WidgetAcc::FindSplitPos(CXFA_FFDocView* docView, + int32_t iBlockIndex, + float& fCalcHeight) { + XFA_Element eUIType = GetUIType(); + if (eUIType == XFA_Element::Subform) + return false; + + if (eUIType != XFA_Element::Text && eUIType != XFA_Element::TextEdit && + eUIType != XFA_Element::NumericEdit && + eUIType != XFA_Element::PasswordEdit) { + fCalcHeight = 0; + return true; + } + + float fTopInset = 0; + float fBottomInset = 0; + if (iBlockIndex == 0) { + CXFA_Margin* margin = m_pNode->GetMarginIfExists(); + if (margin) { + fTopInset = margin->GetTopInset(); + fBottomInset = margin->GetBottomInset(); + } + + CFX_RectF rtUIMargin = GetUIMargin(); + fTopInset += rtUIMargin.top; + fBottomInset += rtUIMargin.width; + } + if (eUIType == XFA_Element::Text) { + float fHeight = fCalcHeight; + if (iBlockIndex == 0) { + fCalcHeight = fCalcHeight - fTopInset; + if (fCalcHeight < 0) + fCalcHeight = 0; + } + + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + fCalcHeight = + pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight, + m_pLayoutData->m_fWidgetHeight - fTopInset); + if (fCalcHeight != 0) { + if (iBlockIndex == 0) + fCalcHeight = fCalcHeight + fTopInset; + if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) + return false; + } + return true; + } + XFA_AttributeEnum iCapPlacement = XFA_AttributeEnum::Unknown; + float fCapReserve = 0; + if (iBlockIndex == 0) { + CXFA_Caption* caption = m_pNode->GetCaptionIfExists(); + if (caption && !caption->IsHidden()) { + iCapPlacement = caption->GetPlacementType(); + fCapReserve = caption->GetReserve(); + } + if (iCapPlacement == XFA_AttributeEnum::Top && + fCalcHeight < fCapReserve + fTopInset) { + fCalcHeight = 0; + return true; + } + if (iCapPlacement == XFA_AttributeEnum::Bottom && + m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) { + fCalcHeight = 0; + return true; + } + if (iCapPlacement != XFA_AttributeEnum::Top) + fCapReserve = 0; + } + CXFA_FieldLayoutData* pFieldData = + static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()); + int32_t iLinesCount = 0; + float fHeight = m_pLayoutData->m_fWidgetHeight; + if (GetValue(XFA_VALUEPICTURE_Display).IsEmpty()) { + iLinesCount = 1; + } else { + if (!pFieldData->m_pTextOut) { + // TODO(dsinclair): Inline fWidth when the 2nd param of + // CalculateAccWidthAndHeight isn't a ref-param. + float fWidth = m_pNode->TryWidth().value_or(0); + CalculateAccWidthAndHeight(docView->GetDoc(), eUIType, fWidth, fHeight); + } + iLinesCount = pFieldData->m_pTextOut->GetTotalLines(); + } + std::vector<float>* pFieldArray = &pFieldData->m_FieldSplitArray; + int32_t iFieldSplitCount = pdfium::CollectionSize<int32_t>(*pFieldArray); + for (int32_t i = 0; i < iBlockIndex * 3; i += 3) { + iLinesCount -= (int32_t)(*pFieldArray)[i + 1]; + fHeight -= (*pFieldArray)[i + 2]; + } + if (iLinesCount == 0) + return false; + + float fLineHeight = m_pNode->GetLineHeight(); + float fFontSize = m_pNode->GetFontSize(); + float fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize; + float fSpaceAbove = 0; + float fStartOffset = 0; + if (fHeight > 0.1f && iBlockIndex == 0) { + fStartOffset = fTopInset; + fHeight -= (fTopInset + fBottomInset); + CXFA_Para* para = m_pNode->GetParaIfExists(); + if (para) { + fSpaceAbove = para->GetSpaceAbove(); + float fSpaceBelow = para->GetSpaceBelow(); + fHeight -= (fSpaceAbove + fSpaceBelow); + switch (para->GetVerticalAlign()) { + case XFA_AttributeEnum::Top: + fStartOffset += fSpaceAbove; + break; + case XFA_AttributeEnum::Middle: + fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove); + break; + case XFA_AttributeEnum::Bottom: + fStartOffset += (fHeight - fTextHeight + fSpaceAbove); + break; + default: + NOTREACHED(); + break; + } + } + if (fStartOffset < 0.1f) + fStartOffset = 0; + } + for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) { + fStartOffset = (*pFieldArray)[i * 3] - (*pFieldArray)[i * 3 + 2]; + if (fStartOffset < 0.1f) + fStartOffset = 0; + } + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) + (*pFieldArray)[0] = fStartOffset; + else + pFieldArray->push_back(fStartOffset); + + XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode(); + bool bCanSplitNoContent = false; + XFA_AttributeEnum eLayoutMode = GetNode() + ->GetParent() + ->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + if ((eLayoutMode == XFA_AttributeEnum::Position || + eLayoutMode == XFA_AttributeEnum::Tb || + eLayoutMode == XFA_AttributeEnum::Row || + eLayoutMode == XFA_AttributeEnum::Table) && + version > XFA_VERSION_208) { + bCanSplitNoContent = true; + } + if ((eLayoutMode == XFA_AttributeEnum::Tb || + eLayoutMode == XFA_AttributeEnum::Row || + eLayoutMode == XFA_AttributeEnum::Table) && + version <= XFA_VERSION_208) { + if (fStartOffset < fCalcHeight) { + bCanSplitNoContent = true; + } else { + fCalcHeight = 0; + return true; + } + } + if (bCanSplitNoContent) { + if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) { + fCalcHeight = 0; + return true; + } + if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) { + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = 0; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back(0); + pFieldArray->push_back(fCalcHeight); + } + return false; + } + if (fCalcHeight - fStartOffset < fLineHeight) { + fCalcHeight = fStartOffset; + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = 0; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back(0); + pFieldArray->push_back(fCalcHeight); + } + return true; + } + float fTextNum = + fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset; + int32_t iLineNum = + (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight); + if (iLineNum >= iLinesCount) { + if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) { + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLinesCount; + (*pFieldArray)[iBlockIndex * 3 + 2] = fCalcHeight; + } else { + pFieldArray->push_back((float)iLinesCount); + pFieldArray->push_back(fCalcHeight); + } + return false; + } + if (fHeight - fStartOffset - fTextHeight < fFontSize) { + iLineNum -= 1; + if (iLineNum == 0) { + fCalcHeight = 0; + return true; + } + } else { + iLineNum = (int32_t)(fTextNum / fLineHeight); + } + } + if (iLineNum > 0) { + float fSplitHeight = iLineNum * fLineHeight + fCapReserve + fStartOffset; + if (iFieldSplitCount / 3 == (iBlockIndex + 1)) { + (*pFieldArray)[iBlockIndex * 3 + 1] = (float)iLineNum; + (*pFieldArray)[iBlockIndex * 3 + 2] = fSplitHeight; + } else { + pFieldArray->push_back((float)iLineNum); + pFieldArray->push_back(fSplitHeight); + } + if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) + return false; + + fCalcHeight = fSplitHeight; + return true; + } + } + fCalcHeight = 0; + return true; +} + +void CXFA_WidgetAcc::InitLayoutData() { + if (m_pLayoutData) + return; + + switch (GetUIType()) { + case XFA_Element::Text: + m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>(); + return; + case XFA_Element::TextEdit: + m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>(); + return; + case XFA_Element::Image: + m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>(); + return; + case XFA_Element::ImageEdit: + m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>(); + return; + default: + break; + } + if (m_pNode && m_pNode->GetElementType() == XFA_Element::Field) { + m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>(); + return; + } + m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>(); +} + +void CXFA_WidgetAcc::StartTextLayout(CXFA_FFDoc* doc, + float& fCalcWidth, + float& fCalcHeight) { + LoadText(doc); + + CXFA_TextLayout* pTextLayout = + static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get())->GetTextLayout(); + float fTextHeight = 0; + if (fCalcWidth > 0 && fCalcHeight > 0) { + float fWidth = GetWidthWithoutMargin(fCalcWidth); + pTextLayout->StartLayout(fWidth); + fTextHeight = fCalcHeight; + fTextHeight = GetHeightWithoutMargin(fTextHeight); + pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); + return; + } + if (fCalcWidth > 0 && fCalcHeight < 0) { + float fWidth = GetWidthWithoutMargin(fCalcWidth); + pTextLayout->StartLayout(fWidth); + } + + if (fCalcWidth < 0 && fCalcHeight < 0) { + Optional<float> width = m_pNode->TryWidth(); + if (width) { + pTextLayout->StartLayout(GetWidthWithoutMargin(*width)); + fCalcWidth = *width; + } else { + float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1)); + pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth)); + fCalcWidth = fMaxWidth; + } + } + + if (m_pLayoutData->m_fWidgetHeight < 0) { + m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight(); + m_pLayoutData->m_fWidgetHeight = + CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight); + } + fTextHeight = m_pLayoutData->m_fWidgetHeight; + fTextHeight = GetHeightWithoutMargin(fTextHeight); + pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight); + fCalcHeight = m_pLayoutData->m_fWidgetHeight; +} + +bool CXFA_WidgetAcc::LoadCaption(CXFA_FFDoc* doc) { + InitLayoutData(); + return static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->LoadCaption(doc, this); +} + +CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() { + return m_pLayoutData + ? static_cast<CXFA_FieldLayoutData*>(m_pLayoutData.get()) + ->m_pCapTextLayout.get() + : nullptr; +} + +CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() { + return m_pLayoutData + ? static_cast<CXFA_TextLayoutData*>(m_pLayoutData.get()) + ->GetTextLayout() + : nullptr; +} + +RetainPtr<CFX_DIBitmap> CXFA_WidgetAcc::GetImageImage() { + return m_pLayoutData + ? static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()) + ->m_pDIBitmap + : nullptr; +} + +RetainPtr<CFX_DIBitmap> CXFA_WidgetAcc::GetImageEditImage() { + return m_pLayoutData + ? static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()) + ->m_pDIBitmap + : nullptr; +} + +void CXFA_WidgetAcc::SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage) { + CXFA_ImageLayoutData* pData = + static_cast<CXFA_ImageLayoutData*>(m_pLayoutData.get()); + if (pData->m_pDIBitmap != newImage) + pData->m_pDIBitmap = newImage; +} + +void CXFA_WidgetAcc::SetImageEditImage( + const RetainPtr<CFX_DIBitmap>& newImage) { + CXFA_ImageEditData* pData = + static_cast<CXFA_ImageEditData*>(m_pLayoutData.get()); + if (pData->m_pDIBitmap != newImage) + pData->m_pDIBitmap = newImage; +} + +RetainPtr<CFGAS_GEFont> CXFA_WidgetAcc::GetFDEFont(CXFA_FFDoc* doc) { + WideString wsFontName = L"Courier"; + uint32_t dwFontStyle = 0; + CXFA_Font* font = m_pNode->GetFontIfExists(); + if (font) { + if (font->IsBold()) + dwFontStyle |= FXFONT_BOLD; + if (font->IsItalic()) + dwFontStyle |= FXFONT_ITALIC; + + wsFontName = font->GetTypeface(); + } + return doc->GetApp()->GetXFAFontMgr()->GetFont(doc, wsFontName.AsStringView(), + dwFontStyle); +} + +CXFA_Node* CXFA_WidgetAcc::GetUIChild() { + if (m_eUIType == XFA_Element::Unknown) + std::tie(m_eUIType, m_pUiChildNode) = CreateUIChild(m_pNode); + return m_pUiChildNode; +} + +XFA_Element CXFA_WidgetAcc::GetUIType() { + GetUIChild(); + return m_eUIType; +} + +bool CXFA_WidgetAcc::IsOpenAccess() const { + return m_pNode && m_pNode->IsOpenAccess(); +} + +std::vector<CXFA_Event*> CXFA_WidgetAcc::GetEventByActivity( + XFA_AttributeEnum iActivity, + bool bIsFormReady) { + std::vector<CXFA_Event*> events; + for (CXFA_Node* node : m_pNode->GetNodeList(0, XFA_Element::Event)) { + auto* event = static_cast<CXFA_Event*>(node); + if (event->GetActivity() == iActivity) { + if (iActivity == XFA_AttributeEnum::Ready) { + WideString wsRef = event->GetRef(); + if (bIsFormReady) { + if (wsRef == WideStringView(L"$form")) + events.push_back(event); + } else { + if (wsRef == WideStringView(L"$layout")) + events.push_back(event); + } + } else { + events.push_back(event); + } + } + } + return events; +} + +CXFA_Border* CXFA_WidgetAcc::GetUIBorder() { + CXFA_Node* pUIChild = GetUIChild(); + return pUIChild ? pUIChild->JSObject()->GetProperty<CXFA_Border>( + 0, XFA_Element::Border) + : nullptr; +} + +CFX_RectF CXFA_WidgetAcc::GetUIMargin() { + CXFA_Node* pUIChild = GetUIChild(); + CXFA_Margin* mgUI = nullptr; + if (pUIChild) { + mgUI = + pUIChild->JSObject()->GetProperty<CXFA_Margin>(0, XFA_Element::Margin); + } + + if (!mgUI) + return CFX_RectF(); + + CXFA_Border* border = GetUIBorder(); + if (border && border->GetPresence() != XFA_AttributeEnum::Visible) + return CFX_RectF(); + + Optional<float> left = mgUI->TryLeftInset(); + Optional<float> top = mgUI->TryTopInset(); + Optional<float> right = mgUI->TryRightInset(); + Optional<float> bottom = mgUI->TryBottomInset(); + if (border) { + bool bVisible = false; + float fThickness = 0; + XFA_AttributeEnum iType = XFA_AttributeEnum::Unknown; + std::tie(iType, bVisible, fThickness) = border->Get3DStyle(); + if (!left || !top || !right || !bottom) { + std::vector<CXFA_Stroke*> strokes = border->GetStrokes(); + if (!top) + top = GetEdgeThickness(strokes, bVisible, 0); + if (!right) + right = GetEdgeThickness(strokes, bVisible, 1); + if (!bottom) + bottom = GetEdgeThickness(strokes, bVisible, 2); + if (!left) + left = GetEdgeThickness(strokes, bVisible, 3); + } + } + return CFX_RectF(left.value_or(0.0), top.value_or(0.0), right.value_or(0.0), + bottom.value_or(0.0)); +} + +XFA_AttributeEnum CXFA_WidgetAcc::GetButtonHighlight() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Highlight); + return XFA_AttributeEnum::Inverted; +} + +bool CXFA_WidgetAcc::HasButtonRollover() const { + CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return false; + + for (CXFA_Node* pText = pItems->GetFirstChild(); pText; + pText = pText->GetNextSibling()) { + if (pText->JSObject()->GetCData(XFA_Attribute::Name) == L"rollover") + return !pText->JSObject()->GetContent(false).IsEmpty(); + } + return false; +} + +bool CXFA_WidgetAcc::HasButtonDown() const { + CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return false; + + for (CXFA_Node* pText = pItems->GetFirstChild(); pText; + pText = pText->GetNextSibling()) { + if (pText->JSObject()->GetCData(XFA_Attribute::Name) == L"down") + return !pText->JSObject()->GetContent(false).IsEmpty(); + } + return false; +} + +bool CXFA_WidgetAcc::IsCheckButtonRound() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Shape) == + XFA_AttributeEnum::Round; + return false; +} + +XFA_AttributeEnum CXFA_WidgetAcc::GetCheckButtonMark() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Mark); + return XFA_AttributeEnum::Default; +} + +bool CXFA_WidgetAcc::IsRadioButton() { + CXFA_Node* pParent = m_pNode->GetParent(); + return pParent && pParent->GetElementType() == XFA_Element::ExclGroup; +} + +float CXFA_WidgetAcc::GetCheckButtonSize() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject() + ->GetMeasure(XFA_Attribute::Size) + .ToUnit(XFA_Unit::Pt); + } + return CXFA_Measurement(10, XFA_Unit::Pt).ToUnit(XFA_Unit::Pt); +} + +bool CXFA_WidgetAcc::IsAllowNeutral() { + CXFA_Node* pUIChild = GetUIChild(); + return pUIChild && + pUIChild->JSObject()->GetBoolean(XFA_Attribute::AllowNeutral); +} + +XFA_CHECKSTATE CXFA_WidgetAcc::GetCheckState() { + WideString wsValue = m_pNode->GetRawValue(); + if (wsValue.IsEmpty()) + return XFA_CHECKSTATE_Off; + + auto* pItems = m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return XFA_CHECKSTATE_Off; + + CXFA_Node* pText = pItems->GetFirstChild(); + int32_t i = 0; + while (pText) { + Optional<WideString> wsContent = pText->JSObject()->TryContent(false, true); + if (wsContent && *wsContent == wsValue) + return static_cast<XFA_CHECKSTATE>(i); + + i++; + pText = pText->GetNextSibling(); + } + return XFA_CHECKSTATE_Off; +} + +void CXFA_WidgetAcc::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) { + CXFA_Node* node = m_pNode->GetExclGroupIfExists(); + if (!node) { + CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItems) + return; + + int32_t i = -1; + CXFA_Node* pText = pItems->GetFirstChild(); + WideString wsContent; + while (pText) { + i++; + if (i == eCheckState) { + wsContent = pText->JSObject()->GetContent(false); + break; + } + pText = pText->GetNextSibling(); + } + if (m_pNode) + m_pNode->SyncValue(wsContent, bNotify); + + return; + } + + WideString wsValue; + if (eCheckState != XFA_CHECKSTATE_Off) { + if (CXFA_Items* pItems = + m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false)) { + CXFA_Node* pText = pItems->GetFirstChild(); + if (pText) + wsValue = pText->JSObject()->GetContent(false); + } + } + CXFA_Node* pChild = node->GetFirstChild(); + for (; pChild; pChild = pChild->GetNextSibling()) { + if (pChild->GetElementType() != XFA_Element::Field) + continue; + + CXFA_Items* pItem = + pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItem) + continue; + + CXFA_Node* pItemchild = pItem->GetFirstChild(); + if (!pItemchild) + continue; + + WideString text = pItemchild->JSObject()->GetContent(false); + WideString wsChildValue = text; + if (wsValue != text) { + pItemchild = pItemchild->GetNextSibling(); + if (pItemchild) + wsChildValue = pItemchild->JSObject()->GetContent(false); + else + wsChildValue.clear(); + } + pChild->SyncValue(wsChildValue, bNotify); + } + node->SyncValue(wsValue, bNotify); +} + +CXFA_Node* CXFA_WidgetAcc::GetSelectedMember() { + CXFA_Node* pSelectedMember = nullptr; + WideString wsState = m_pNode->GetRawValue(); + if (wsState.IsEmpty()) + return pSelectedMember; + + for (CXFA_Node* pNode = ToNode(m_pNode->GetFirstChild()); pNode; + pNode = pNode->GetNextSibling()) { + CXFA_WidgetAcc widgetData(pNode); + if (widgetData.GetCheckState() == XFA_CHECKSTATE_On) { + pSelectedMember = pNode; + break; + } + } + return pSelectedMember; +} + +CXFA_Node* CXFA_WidgetAcc::SetSelectedMember(const WideStringView& wsName, + bool bNotify) { + uint32_t nameHash = FX_HashCode_GetW(wsName, false); + for (CXFA_Node* pNode = ToNode(m_pNode->GetFirstChild()); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetNameHash() == nameHash) { + CXFA_WidgetAcc widgetData(pNode); + widgetData.SetCheckState(XFA_CHECKSTATE_On, bNotify); + return pNode; + } + } + return nullptr; +} + +void CXFA_WidgetAcc::SetSelectedMemberByValue(const WideStringView& wsValue, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + WideString wsExclGroup; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != XFA_Element::Field) + continue; + + CXFA_Items* pItem = + pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + if (!pItem) + continue; + + CXFA_Node* pItemchild = pItem->GetFirstChild(); + if (!pItemchild) + continue; + + WideString wsChildValue = pItemchild->JSObject()->GetContent(false); + if (wsValue != wsChildValue) { + pItemchild = pItemchild->GetNextSibling(); + if (pItemchild) + wsChildValue = pItemchild->JSObject()->GetContent(false); + else + wsChildValue.clear(); + } else { + wsExclGroup = wsValue; + } + pNode->JSObject()->SetContent(wsChildValue, wsChildValue, bNotify, + bScriptModify, false); + } + if (m_pNode) { + m_pNode->JSObject()->SetContent(wsExclGroup, wsExclGroup, bNotify, + bScriptModify, bSyncData); + } +} + +CXFA_Node* CXFA_WidgetAcc::GetExclGroupFirstMember() { + CXFA_Node* pExcl = GetNode(); + if (!pExcl) + return nullptr; + + CXFA_Node* pNode = pExcl->GetFirstChild(); + while (pNode) { + if (pNode->GetElementType() == XFA_Element::Field) + return pNode; + + pNode = pNode->GetNextSibling(); + } + return nullptr; +} +CXFA_Node* CXFA_WidgetAcc::GetExclGroupNextMember(CXFA_Node* pNode) { + if (!pNode) + return nullptr; + + CXFA_Node* pNodeField = pNode->GetNextSibling(); + while (pNodeField) { + if (pNodeField->GetElementType() == XFA_Element::Field) + return pNodeField; + + pNodeField = pNodeField->GetNextSibling(); + } + return nullptr; +} + +bool CXFA_WidgetAcc::IsChoiceListCommitOnSelect() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::CommitOn) == + XFA_AttributeEnum::Select; + } + return true; +} + +bool CXFA_WidgetAcc::IsChoiceListAllowTextEntry() { + CXFA_Node* pUIChild = GetUIChild(); + return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::TextEntry); +} + +bool CXFA_WidgetAcc::IsChoiceListMultiSelect() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::Open) == + XFA_AttributeEnum::MultiSelect; + } + return false; +} + +bool CXFA_WidgetAcc::IsListBox() { + CXFA_Node* pUIChild = GetUIChild(); + if (!pUIChild) + return false; + + XFA_AttributeEnum attr = pUIChild->JSObject()->GetEnum(XFA_Attribute::Open); + return attr == XFA_AttributeEnum::Always || + attr == XFA_AttributeEnum::MultiSelect; +} + +int32_t CXFA_WidgetAcc::CountChoiceListItems(bool bSaveValue) { + std::vector<CXFA_Node*> pItems; + int32_t iCount = 0; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != XFA_Element::Items) + continue; + iCount++; + pItems.push_back(pNode); + if (iCount == 2) + break; + } + if (iCount == 0) + return 0; + + CXFA_Node* pItem = pItems[0]; + if (iCount > 1) { + bool bItemOneHasSave = + pItems[0]->JSObject()->GetBoolean(XFA_Attribute::Save); + bool bItemTwoHasSave = + pItems[1]->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) + pItem = pItems[1]; + } + return pItem->CountChildren(XFA_Element::Unknown, false); +} + +Optional<WideString> CXFA_WidgetAcc::GetChoiceListItem(int32_t nIndex, + bool bSaveValue) { + std::vector<CXFA_Node*> pItemsArray; + int32_t iCount = 0; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != XFA_Element::Items) + continue; + + ++iCount; + pItemsArray.push_back(pNode); + if (iCount == 2) + break; + } + if (iCount == 0) + return {}; + + CXFA_Node* pItems = pItemsArray[0]; + if (iCount > 1) { + bool bItemOneHasSave = + pItemsArray[0]->JSObject()->GetBoolean(XFA_Attribute::Save); + bool bItemTwoHasSave = + pItemsArray[1]->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) + pItems = pItemsArray[1]; + } + if (!pItems) + return {}; + + CXFA_Node* pItem = + pItems->GetChild<CXFA_Node>(nIndex, XFA_Element::Unknown, false); + if (pItem) + return {pItem->JSObject()->GetContent(false)}; + return {}; +} + +std::vector<WideString> CXFA_WidgetAcc::GetChoiceListItems(bool bSaveValue) { + std::vector<CXFA_Node*> items; + for (CXFA_Node* pNode = m_pNode->GetFirstChild(); pNode && items.size() < 2; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() == XFA_Element::Items) + items.push_back(pNode); + } + if (items.empty()) + return std::vector<WideString>(); + + CXFA_Node* pItem = items.front(); + if (items.size() > 1) { + bool bItemOneHasSave = + items[0]->JSObject()->GetBoolean(XFA_Attribute::Save); + bool bItemTwoHasSave = + items[1]->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) + pItem = items[1]; + } + + std::vector<WideString> wsTextArray; + for (CXFA_Node* pNode = pItem->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + wsTextArray.emplace_back(pNode->JSObject()->GetContent(false)); + } + return wsTextArray; +} + +int32_t CXFA_WidgetAcc::CountSelectedItems() { + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + if (IsListBox() || !IsChoiceListAllowTextEntry()) + return pdfium::CollectionSize<int32_t>(wsValueArray); + + int32_t iSelected = 0; + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + for (const auto& value : wsValueArray) { + if (pdfium::ContainsValue(wsSaveTextArray, value)) + iSelected++; + } + return iSelected; +} + +int32_t CXFA_WidgetAcc::GetSelectedItem(int32_t nIndex) { + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + if (!pdfium::IndexInBounds(wsValueArray, nIndex)) + return -1; + + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), + wsValueArray[nIndex]); + return it != wsSaveTextArray.end() ? it - wsSaveTextArray.begin() : -1; +} + +std::vector<int32_t> CXFA_WidgetAcc::GetSelectedItems() { + std::vector<int32_t> iSelArray; + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + for (const auto& value : wsValueArray) { + auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), value); + if (it != wsSaveTextArray.end()) + iSelArray.push_back(it - wsSaveTextArray.begin()); + } + return iSelArray; +} + +std::vector<WideString> CXFA_WidgetAcc::GetSelectedItemsValue() { + std::vector<WideString> wsSelTextArray; + WideString wsValue = m_pNode->GetRawValue(); + if (IsChoiceListMultiSelect()) { + if (!wsValue.IsEmpty()) { + size_t iStart = 0; + size_t iLength = wsValue.GetLength(); + auto iEnd = wsValue.Find(L'\n', iStart); + iEnd = (!iEnd.has_value()) ? iLength : iEnd; + while (iEnd >= iStart) { + wsSelTextArray.push_back(wsValue.Mid(iStart, iEnd.value() - iStart)); + iStart = iEnd.value() + 1; + if (iStart >= iLength) + break; + iEnd = wsValue.Find(L'\n', iStart); + if (!iEnd.has_value()) + wsSelTextArray.push_back(wsValue.Mid(iStart, iLength - iStart)); + } + } + } else { + wsSelTextArray.push_back(wsValue); + } + return wsSelTextArray; +} + +bool CXFA_WidgetAcc::GetItemState(int32_t nIndex) { + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + return pdfium::IndexInBounds(wsSaveTextArray, nIndex) && + pdfium::ContainsValue(GetSelectedItemsValue(), + wsSaveTextArray[nIndex]); +} + +void CXFA_WidgetAcc::SetItemState(int32_t nIndex, + bool bSelected, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + if (!pdfium::IndexInBounds(wsSaveTextArray, nIndex)) + return; + + int32_t iSel = -1; + std::vector<WideString> wsValueArray = GetSelectedItemsValue(); + auto it = std::find(wsValueArray.begin(), wsValueArray.end(), + wsSaveTextArray[nIndex]); + if (it != wsValueArray.end()) + iSel = it - wsValueArray.begin(); + + if (IsChoiceListMultiSelect()) { + if (bSelected) { + if (iSel < 0) { + WideString wsValue = m_pNode->GetRawValue(); + if (!wsValue.IsEmpty()) { + wsValue += L"\n"; + } + wsValue += wsSaveTextArray[nIndex]; + m_pNode->JSObject()->SetContent(wsValue, wsValue, bNotify, + bScriptModify, bSyncData); + } + } else if (iSel >= 0) { + std::vector<int32_t> iSelArray = GetSelectedItems(); + auto it = std::find(iSelArray.begin(), iSelArray.end(), nIndex); + if (it != iSelArray.end()) + iSelArray.erase(it); + SetSelectedItems(iSelArray, bNotify, bScriptModify, bSyncData); + } + } else { + if (bSelected) { + if (iSel < 0) { + WideString wsSaveText = wsSaveTextArray[nIndex]; + m_pNode->JSObject()->SetContent(wsSaveText, + GetFormatDataValue(wsSaveText), bNotify, + bScriptModify, bSyncData); + } + } else if (iSel >= 0) { + m_pNode->JSObject()->SetContent(WideString(), WideString(), bNotify, + bScriptModify, bSyncData); + } + } +} + +void CXFA_WidgetAcc::SetSelectedItems(const std::vector<int32_t>& iSelArray, + bool bNotify, + bool bScriptModify, + bool bSyncData) { + WideString wsValue; + int32_t iSize = pdfium::CollectionSize<int32_t>(iSelArray); + if (iSize >= 1) { + std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true); + WideString wsItemValue; + for (int32_t i = 0; i < iSize; i++) { + wsItemValue = (iSize == 1) ? wsSaveTextArray[iSelArray[i]] + : wsSaveTextArray[iSelArray[i]] + L"\n"; + wsValue += wsItemValue; + } + } + WideString wsFormat(wsValue); + if (!IsChoiceListMultiSelect()) + wsFormat = GetFormatDataValue(wsValue); + + m_pNode->JSObject()->SetContent(wsValue, wsFormat, bNotify, bScriptModify, + bSyncData); +} + +void CXFA_WidgetAcc::ClearAllSelections() { + CXFA_Node* pBind = m_pNode->GetBindData(); + if (!pBind || !IsChoiceListMultiSelect()) { + m_pNode->SyncValue(WideString(), false); + return; + } + + while (CXFA_Node* pChildNode = pBind->GetFirstChild()) + pBind->RemoveChild(pChildNode, true); +} + +void CXFA_WidgetAcc::InsertItem(const WideString& wsLabel, + const WideString& wsValue, + bool bNotify) { + int32_t nIndex = -1; + WideString wsNewValue(wsValue); + if (wsNewValue.IsEmpty()) + wsNewValue = wsLabel; + + std::vector<CXFA_Node*> listitems; + for (CXFA_Node* pItem = m_pNode->GetFirstChild(); pItem; + pItem = pItem->GetNextSibling()) { + if (pItem->GetElementType() == XFA_Element::Items) + listitems.push_back(pItem); + } + if (listitems.empty()) { + CXFA_Node* pItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); + m_pNode->InsertChild(-1, pItems); + InsertListTextItem(pItems, wsLabel, nIndex); + CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); + m_pNode->InsertChild(-1, pSaveItems); + pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); + InsertListTextItem(pSaveItems, wsNewValue, nIndex); + } else if (listitems.size() > 1) { + for (int32_t i = 0; i < 2; i++) { + CXFA_Node* pNode = listitems[i]; + bool bHasSave = pNode->JSObject()->GetBoolean(XFA_Attribute::Save); + if (bHasSave) + InsertListTextItem(pNode, wsNewValue, nIndex); + else + InsertListTextItem(pNode, wsLabel, nIndex); + } + } else { + CXFA_Node* pNode = listitems[0]; + pNode->JSObject()->SetBoolean(XFA_Attribute::Save, false, false); + pNode->JSObject()->SetEnum(XFA_Attribute::Presence, + XFA_AttributeEnum::Visible, false); + CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); + m_pNode->InsertChild(-1, pSaveItems); + pSaveItems->JSObject()->SetBoolean(XFA_Attribute::Save, true, false); + pSaveItems->JSObject()->SetEnum(XFA_Attribute::Presence, + XFA_AttributeEnum::Hidden, false); + CXFA_Node* pListNode = pNode->GetFirstChild(); + int32_t i = 0; + while (pListNode) { + InsertListTextItem(pSaveItems, pListNode->JSObject()->GetContent(false), + i); + ++i; + + pListNode = pListNode->GetNextSibling(); + } + InsertListTextItem(pNode, wsLabel, nIndex); + InsertListTextItem(pSaveItems, wsNewValue, nIndex); + } + if (!bNotify) + return; + + m_pNode->GetDocument()->GetNotify()->OnWidgetListItemAdded( + this, wsLabel.c_str(), wsValue.c_str(), nIndex); +} + +void CXFA_WidgetAcc::GetItemLabel(const WideStringView& wsValue, + WideString& wsLabel) { + int32_t iCount = 0; + std::vector<CXFA_Node*> listitems; + CXFA_Node* pItems = m_pNode->GetFirstChild(); + for (; pItems; pItems = pItems->GetNextSibling()) { + if (pItems->GetElementType() != XFA_Element::Items) + continue; + iCount++; + listitems.push_back(pItems); + } + + if (iCount <= 1) { + wsLabel = wsValue; + return; + } + + CXFA_Node* pLabelItems = listitems[0]; + bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save); + CXFA_Node* pSaveItems = nullptr; + if (bSave) { + pSaveItems = pLabelItems; + pLabelItems = listitems[1]; + } else { + pSaveItems = listitems[1]; + } + iCount = 0; + + int32_t iSearch = -1; + for (CXFA_Node* pChildItem = pSaveItems->GetFirstChild(); pChildItem; + pChildItem = pChildItem->GetNextSibling()) { + if (pChildItem->JSObject()->GetContent(false) == wsValue) { + iSearch = iCount; + break; + } + iCount++; + } + if (iSearch < 0) + return; + + CXFA_Node* pText = + pLabelItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false); + if (pText) + wsLabel = pText->JSObject()->GetContent(false); +} + +WideString CXFA_WidgetAcc::GetItemValue(const WideStringView& wsLabel) { + int32_t iCount = 0; + std::vector<CXFA_Node*> listitems; + for (CXFA_Node* pItems = m_pNode->GetFirstChild(); pItems; + pItems = pItems->GetNextSibling()) { + if (pItems->GetElementType() != XFA_Element::Items) + continue; + iCount++; + listitems.push_back(pItems); + } + if (iCount <= 1) + return WideString(wsLabel); + + CXFA_Node* pLabelItems = listitems[0]; + bool bSave = pLabelItems->JSObject()->GetBoolean(XFA_Attribute::Save); + CXFA_Node* pSaveItems = nullptr; + if (bSave) { + pSaveItems = pLabelItems; + pLabelItems = listitems[1]; + } else { + pSaveItems = listitems[1]; + } + iCount = 0; + + int32_t iSearch = -1; + WideString wsContent; + CXFA_Node* pChildItem = pLabelItems->GetFirstChild(); + for (; pChildItem; pChildItem = pChildItem->GetNextSibling()) { + if (pChildItem->JSObject()->GetContent(false) == wsLabel) { + iSearch = iCount; + break; + } + iCount++; + } + if (iSearch < 0) + return L""; + + CXFA_Node* pText = + pSaveItems->GetChild<CXFA_Node>(iSearch, XFA_Element::Unknown, false); + return pText ? pText->JSObject()->GetContent(false) : L""; +} + +bool CXFA_WidgetAcc::DeleteItem(int32_t nIndex, + bool bNotify, + bool bScriptModify) { + bool bSetValue = false; + CXFA_Node* pItems = m_pNode->GetFirstChild(); + for (; pItems; pItems = pItems->GetNextSibling()) { + if (pItems->GetElementType() != XFA_Element::Items) + continue; + + if (nIndex < 0) { + while (CXFA_Node* pNode = pItems->GetFirstChild()) { + pItems->RemoveChild(pNode, true); + } + } else { + if (!bSetValue && pItems->JSObject()->GetBoolean(XFA_Attribute::Save)) { + SetItemState(nIndex, false, true, bScriptModify, true); + bSetValue = true; + } + int32_t i = 0; + CXFA_Node* pNode = pItems->GetFirstChild(); + while (pNode) { + if (i == nIndex) { + pItems->RemoveChild(pNode, true); + break; + } + i++; + pNode = pNode->GetNextSibling(); + } + } + } + if (bNotify) + m_pNode->GetDocument()->GetNotify()->OnWidgetListItemRemoved(this, nIndex); + return true; +} + +bool CXFA_WidgetAcc::IsHorizontalScrollPolicyOff() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::HScrollPolicy) == + XFA_AttributeEnum::Off; + } + return false; +} + +bool CXFA_WidgetAcc::IsVerticalScrollPolicyOff() { + CXFA_Node* pUIChild = GetUIChild(); + if (pUIChild) { + return pUIChild->JSObject()->GetEnum(XFA_Attribute::VScrollPolicy) == + XFA_AttributeEnum::Off; + } + return false; +} + +Optional<int32_t> CXFA_WidgetAcc::GetNumberOfCells() { + CXFA_Node* pUIChild = GetUIChild(); + if (!pUIChild) + return {}; + if (CXFA_Comb* pNode = + pUIChild->GetChild<CXFA_Comb>(0, XFA_Element::Comb, false)) + return {pNode->JSObject()->GetInteger(XFA_Attribute::NumberOfCells)}; + return {}; +} + +WideString CXFA_WidgetAcc::GetPasswordChar() { + CXFA_Node* pUIChild = GetUIChild(); + return pUIChild ? pUIChild->JSObject()->GetCData(XFA_Attribute::PasswordChar) + : L"*"; +} + +bool CXFA_WidgetAcc::IsMultiLine() { + CXFA_Node* pUIChild = GetUIChild(); + return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::MultiLine); +} + +std::pair<XFA_Element, int32_t> CXFA_WidgetAcc::GetMaxChars() { + if (CXFA_Value* pNode = + m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false)) { + if (CXFA_Node* pChild = pNode->GetFirstChild()) { + switch (pChild->GetElementType()) { + case XFA_Element::Text: + return {XFA_Element::Text, + pChild->JSObject()->GetInteger(XFA_Attribute::MaxChars)}; + case XFA_Element::ExData: { + int32_t iMax = + pChild->JSObject()->GetInteger(XFA_Attribute::MaxLength); + return {XFA_Element::ExData, iMax < 0 ? 0 : iMax}; + } + default: + break; + } + } + } + return {XFA_Element::Unknown, 0}; +} + +int32_t CXFA_WidgetAcc::GetFracDigits() { + CXFA_Value* pNode = + m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNode) + return -1; + + CXFA_Decimal* pChild = + pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false); + if (!pChild) + return -1; + + return pChild->JSObject() + ->TryInteger(XFA_Attribute::FracDigits, true) + .value_or(-1); +} + +int32_t CXFA_WidgetAcc::GetLeadDigits() { + CXFA_Value* pNode = + m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNode) + return -1; + + CXFA_Decimal* pChild = + pNode->GetChild<CXFA_Decimal>(0, XFA_Element::Decimal, false); + if (!pChild) + return -1; + + return pChild->JSObject() + ->TryInteger(XFA_Attribute::LeadDigits, true) + .value_or(-1); +} + +bool CXFA_WidgetAcc::SetValue(XFA_VALUEPICTURE eValueType, + const WideString& wsValue) { + if (wsValue.IsEmpty()) { + if (m_pNode) + m_pNode->SyncValue(wsValue, true); + return true; + } + + m_bPreNull = m_bIsNull; + m_bIsNull = false; + WideString wsNewText(wsValue); + WideString wsPicture = GetPictureContent(eValueType); + bool bValidate = true; + bool bSyncData = false; + CXFA_Node* pNode = GetUIChild(); + if (!pNode) + return true; + + XFA_Element eType = pNode->GetElementType(); + if (!wsPicture.IsEmpty()) { + CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); + IFX_Locale* pLocale = GetLocale(); + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + bValidate = + widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture); + if (bValidate) { + widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText, + wsPicture, pLocale, pLocalMgr); + wsNewText = widgetValue.GetValue(); + if (eType == XFA_Element::NumericEdit) + wsNewText = NumericLimit(wsNewText, GetLeadDigits(), GetFracDigits()); + + bSyncData = true; + } + } else { + if (eType == XFA_Element::NumericEdit) { + if (wsNewText != L"0") + wsNewText = NumericLimit(wsNewText, GetLeadDigits(), GetFracDigits()); + + bSyncData = true; + } + } + if (eType != XFA_Element::NumericEdit || bSyncData) { + if (m_pNode) + m_pNode->SyncValue(wsNewText, true); + } + + return bValidate; +} + +WideString CXFA_WidgetAcc::GetPictureContent(XFA_VALUEPICTURE ePicture) { + if (ePicture == XFA_VALUEPICTURE_Raw) + return L""; + + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + switch (ePicture) { + case XFA_VALUEPICTURE_Display: { + if (CXFA_Format* pFormat = + m_pNode->GetChild<CXFA_Format>(0, XFA_Element::Format, false)) { + if (CXFA_Picture* pPicture = pFormat->GetChild<CXFA_Picture>( + 0, XFA_Element::Picture, false)) { + Optional<WideString> picture = + pPicture->JSObject()->TryContent(false, true); + if (picture) + return *picture; + } + } + + IFX_Locale* pLocale = GetLocale(); + if (!pLocale) + return L""; + + uint32_t dwType = widgetValue.GetType(); + switch (dwType) { + case XFA_VT_DATE: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); + case XFA_VT_TIME: + return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); + case XFA_VT_DATETIME: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium) + + L"T" + + pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium); + case XFA_VT_DECIMAL: + case XFA_VT_FLOAT: + default: + return L""; + } + } + case XFA_VALUEPICTURE_Edit: { + CXFA_Ui* pUI = m_pNode->GetChild<CXFA_Ui>(0, XFA_Element::Ui, false); + if (pUI) { + if (CXFA_Picture* pPicture = + pUI->GetChild<CXFA_Picture>(0, XFA_Element::Picture, false)) { + Optional<WideString> picture = + pPicture->JSObject()->TryContent(false, true); + if (picture) + return *picture; + } + } + + IFX_Locale* pLocale = GetLocale(); + if (!pLocale) + return L""; + + uint32_t dwType = widgetValue.GetType(); + switch (dwType) { + case XFA_VT_DATE: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); + case XFA_VT_TIME: + return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); + case XFA_VT_DATETIME: + return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short) + + L"T" + + pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short); + default: + return L""; + } + } + case XFA_VALUEPICTURE_DataBind: { + CXFA_Bind* bind = m_pNode->GetBindIfExists(); + if (bind) + return bind->GetPicture(); + break; + } + default: + break; + } + return L""; +} + +IFX_Locale* CXFA_WidgetAcc::GetLocale() { + return m_pNode ? m_pNode->GetLocale() : nullptr; +} + +WideString CXFA_WidgetAcc::GetValue(XFA_VALUEPICTURE eValueType) { + WideString wsValue = m_pNode->JSObject()->GetContent(false); + + if (eValueType == XFA_VALUEPICTURE_Display) + GetItemLabel(wsValue.AsStringView(), wsValue); + + WideString wsPicture = GetPictureContent(eValueType); + CXFA_Node* pNode = GetUIChild(); + if (!pNode) + return wsValue; + + switch (GetUIChild()->GetElementType()) { + case XFA_Element::ChoiceList: { + if (eValueType == XFA_VALUEPICTURE_Display) { + int32_t iSelItemIndex = GetSelectedItem(0); + if (iSelItemIndex >= 0) { + wsValue = GetChoiceListItem(iSelItemIndex, false).value_or(L""); + wsPicture.clear(); + } + } + } break; + case XFA_Element::NumericEdit: + if (eValueType != XFA_VALUEPICTURE_Raw && wsPicture.IsEmpty()) { + IFX_Locale* pLocale = GetLocale(); + if (eValueType == XFA_VALUEPICTURE_Display && pLocale) + wsValue = FormatNumStr(NormalizeNumStr(wsValue), pLocale); + } + break; + default: + break; + } + if (wsPicture.IsEmpty()) + return wsValue; + + if (IFX_Locale* pLocale = GetLocale()) { + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); + switch (widgetValue.GetType()) { + case XFA_VT_DATE: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); + if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) + return wsValue; + } + break; + } + case XFA_VT_TIME: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); + if (time.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) + return wsValue; + } + break; + } + default: + break; + } + widgetValue.FormatPatterns(wsValue, wsPicture, pLocale, eValueType); + } + return wsValue; +} + +WideString CXFA_WidgetAcc::GetNormalizeDataValue(const WideString& wsValue) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind); + if (wsPicture.IsEmpty()) + return wsValue; + + ASSERT(GetNode()); + CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); + IFX_Locale* pLocale = GetLocale(); + CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(GetNode()); + if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) { + widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsValue, wsPicture, + pLocale, pLocalMgr); + return widgetValue.GetValue(); + } + return wsValue; +} + +WideString CXFA_WidgetAcc::GetFormatDataValue(const WideString& wsValue) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsPicture = GetPictureContent(XFA_VALUEPICTURE_DataBind); + if (wsPicture.IsEmpty()) + return wsValue; + + WideString wsFormattedValue = wsValue; + if (IFX_Locale* pLocale = GetLocale()) { + ASSERT(GetNode()); + CXFA_Value* pNodeValue = + GetNode()->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNodeValue) + return wsValue; + + CXFA_Node* pValueChild = pNodeValue->GetFirstChild(); + if (!pValueChild) + return wsValue; + + int32_t iVTType = XFA_VT_NULL; + switch (pValueChild->GetElementType()) { + case XFA_Element::Decimal: + iVTType = XFA_VT_DECIMAL; + break; + case XFA_Element::Float: + iVTType = XFA_VT_FLOAT; + break; + case XFA_Element::Date: + iVTType = XFA_VT_DATE; + break; + case XFA_Element::Time: + iVTType = XFA_VT_TIME; + break; + case XFA_Element::DateTime: + iVTType = XFA_VT_DATETIME; + break; + case XFA_Element::Boolean: + iVTType = XFA_VT_BOOLEAN; + break; + case XFA_Element::Integer: + iVTType = XFA_VT_INTEGER; + break; + case XFA_Element::Text: + iVTType = XFA_VT_TEXT; + break; + default: + iVTType = XFA_VT_NULL; + break; + } + CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); + CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocalMgr); + switch (widgetValue.GetType()) { + case XFA_VT_DATE: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); + if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale, + XFA_VALUEPICTURE_DataBind)) { + return wsFormattedValue; + } + } + break; + } + case XFA_VT_TIME: { + WideString wsDate, wsTime; + if (SplitDateTime(wsValue, wsDate, wsTime)) { + CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); + if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale, + XFA_VALUEPICTURE_DataBind)) { + return wsFormattedValue; + } + } + break; + } + default: + break; + } + widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale, + XFA_VALUEPICTURE_DataBind); + } + return wsFormattedValue; +} + +WideString CXFA_WidgetAcc::NormalizeNumStr(const WideString& wsValue) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsOutput = wsValue; + wsOutput.TrimLeft('0'); + + if (!wsOutput.IsEmpty() && wsOutput.Contains('.') && GetFracDigits() != -1) { + wsOutput.TrimRight(L"0"); + wsOutput.TrimRight(L"."); + } + if (wsOutput.IsEmpty() || wsOutput[0] == '.') + wsOutput.InsertAtFront('0'); + + return wsOutput; +} + +WideString CXFA_WidgetAcc::FormatNumStr(const WideString& wsValue, + IFX_Locale* pLocale) { + if (wsValue.IsEmpty()) + return L""; + + WideString wsSrcNum = wsValue; + WideString wsGroupSymbol = + pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping); + bool bNeg = false; + if (wsSrcNum[0] == '-') { + bNeg = true; + wsSrcNum.Delete(0, 1); + } + + auto dot_index = wsSrcNum.Find('.'); + dot_index = !dot_index.has_value() ? wsSrcNum.GetLength() : dot_index; + + if (dot_index.value() < 1) + return L""; + + size_t nPos = dot_index.value() % 3; + WideString wsOutput; + for (size_t i = 0; i < dot_index.value(); i++) { + if (i % 3 == nPos && i != 0) + wsOutput += wsGroupSymbol; + + wsOutput += wsSrcNum[i]; + } + if (dot_index.value() < wsSrcNum.GetLength()) { + wsOutput += pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); + wsOutput += wsSrcNum.Right(wsSrcNum.GetLength() - dot_index.value() - 1); + } + if (bNeg) + return pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus) + wsOutput; + + return wsOutput; +} + +void CXFA_WidgetAcc::InsertListTextItem(CXFA_Node* pItems, + const WideString& wsText, + int32_t nIndex) { + CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text); + pItems->InsertChild(nIndex, pText); + pText->JSObject()->SetContent(wsText, wsText, false, false, false); +} + +WideString CXFA_WidgetAcc::NumericLimit(const WideString& wsValue, + int32_t iLead, + int32_t iTread) const { + if ((iLead == -1) && (iTread == -1)) + return wsValue; + + WideString wsRet; + int32_t iLead_ = 0, iTread_ = -1; + int32_t iCount = wsValue.GetLength(); + if (iCount == 0) + return wsValue; + + int32_t i = 0; + if (wsValue[i] == L'-') { + wsRet += L'-'; + i++; + } + for (; i < iCount; i++) { + wchar_t wc = wsValue[i]; + if (FXSYS_isDecimalDigit(wc)) { + if (iLead >= 0) { + iLead_++; + if (iLead_ > iLead) + return L"0"; + } else if (iTread_ >= 0) { + iTread_++; + if (iTread_ > iTread) { + if (iTread != -1) { + CFX_Decimal wsDeci = CFX_Decimal(wsValue.AsStringView()); + wsDeci.SetScale(iTread); + wsRet = wsDeci; + } + return wsRet; + } + } + } else if (wc == L'.') { + iTread_ = 0; + iLead = -1; + } + wsRet += wc; + } + return wsRet; +} diff --git a/xfa/fxfa/cxfa_widgetacc.h b/xfa/fxfa/cxfa_widgetacc.h new file mode 100644 index 0000000000000000000000000000000000000000..f21ace9d951957360dd324cd49e42506610c8611 --- /dev/null +++ b/xfa/fxfa/cxfa_widgetacc.h @@ -0,0 +1,229 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_WIDGETACC_H_ +#define XFA_FXFA_CXFA_WIDGETACC_H_ + +#include <memory> +#include <utility> +#include <vector> + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/fx_dib.h" +#include "xfa/fxfa/fxfa_basic.h" + +enum XFA_CHECKSTATE { + XFA_CHECKSTATE_On = 0, + XFA_CHECKSTATE_Off = 1, + XFA_CHECKSTATE_Neutral = 2, +}; + +enum XFA_VALUEPICTURE { + XFA_VALUEPICTURE_Raw = 0, + XFA_VALUEPICTURE_Display, + XFA_VALUEPICTURE_Edit, + XFA_VALUEPICTURE_DataBind, +}; + +class CFGAS_GEFont; +class CXFA_Bind; +class CXFA_Border; +class CXFA_Calculate; +class CXFA_Caption; +class CXFA_Event; +class CXFA_EventParam; +class CXFA_FFApp; +class CXFA_FFDoc; +class CXFA_FFDocView; +class CXFA_FFWidget; +class CXFA_Font; +class CXFA_Margin; +class CXFA_Node; +class CXFA_Script; +class CXFA_Para; +class CXFA_TextLayout; +class CXFA_Value; +class CXFA_Validate; +class CXFA_WidgetLayoutData; +class IFX_Locale; + +class CXFA_WidgetAcc { + public: + explicit CXFA_WidgetAcc(CXFA_Node* pNode); + ~CXFA_WidgetAcc(); + + void ResetData(); + + CXFA_FFWidget* GetNextWidget(CXFA_FFWidget* pWidget); + void StartWidgetLayout(CXFA_FFDoc* doc, + float& fCalcWidth, + float& fCalcHeight); + bool FindSplitPos(CXFA_FFDocView* docView, + int32_t iBlockIndex, + float& fCalcHeight); + + bool LoadCaption(CXFA_FFDoc* doc); + CXFA_TextLayout* GetCaptionTextLayout(); + + void LoadText(CXFA_FFDoc* doc); + CXFA_TextLayout* GetTextLayout(); + + bool LoadImageImage(CXFA_FFDoc* doc); + bool LoadImageEditImage(CXFA_FFDoc* doc); + void GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); + void GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); + + RetainPtr<CFX_DIBitmap> GetImageImage(); + RetainPtr<CFX_DIBitmap> GetImageEditImage(); + void SetImageEdit(const WideString& wsContentType, + const WideString& wsHref, + const WideString& wsData); + void SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage); + void SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage); + void UpdateUIDisplay(CXFA_FFDocView* docView, CXFA_FFWidget* pExcept); + + RetainPtr<CFGAS_GEFont> GetFDEFont(CXFA_FFDoc* doc); + + CXFA_Node* GetNode() const { return m_pNode; } + + CXFA_Node* GetUIChild(); + XFA_Element GetUIType(); + CFX_RectF GetUIMargin(); + + bool IsOpenAccess() const; + bool IsListBox(); + bool IsAllowNeutral(); + bool IsRadioButton(); + bool IsChoiceListAllowTextEntry(); + bool IsMultiLine(); + + CXFA_Border* GetUIBorder(); + + std::vector<CXFA_Event*> GetEventByActivity(XFA_AttributeEnum iActivity, + bool bIsFormReady); + + XFA_AttributeEnum GetButtonHighlight(); + bool HasButtonRollover() const; + bool HasButtonDown() const; + + bool IsCheckButtonRound(); + XFA_AttributeEnum GetCheckButtonMark(); + float GetCheckButtonSize(); + + XFA_CHECKSTATE GetCheckState(); + void SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify); + + CXFA_Node* GetSelectedMember(); + CXFA_Node* SetSelectedMember(const WideStringView& wsName, bool bNotify); + void SetSelectedMemberByValue(const WideStringView& wsValue, + bool bNotify, + bool bScriptModify, + bool bSyncData); + + CXFA_Node* GetExclGroupFirstMember(); + CXFA_Node* GetExclGroupNextMember(CXFA_Node* pNode); + + int32_t CountChoiceListItems(bool bSaveValue); + Optional<WideString> GetChoiceListItem(int32_t nIndex, bool bSaveValue); + bool IsChoiceListMultiSelect(); + bool IsChoiceListCommitOnSelect(); + std::vector<WideString> GetChoiceListItems(bool bSaveValue); + + int32_t CountSelectedItems(); + int32_t GetSelectedItem(int32_t nIndex); + std::vector<int32_t> GetSelectedItems(); + std::vector<WideString> GetSelectedItemsValue(); + void SetSelectedItems(const std::vector<int32_t>& iSelArray, + bool bNotify, + bool bScriptModify, + bool bSyncData); + void InsertItem(const WideString& wsLabel, + const WideString& wsValue, + bool bNotify); + bool DeleteItem(int32_t nIndex, bool bNotify, bool bScriptModify); + void ClearAllSelections(); + + bool GetItemState(int32_t nIndex); + void SetItemState(int32_t nIndex, + bool bSelected, + bool bNotify, + bool bScriptModify, + bool bSyncData); + + WideString GetItemValue(const WideStringView& wsLabel); + + bool IsHorizontalScrollPolicyOff(); + bool IsVerticalScrollPolicyOff(); + Optional<int32_t> GetNumberOfCells(); + + bool SetValue(XFA_VALUEPICTURE eValueType, const WideString& wsValue); + WideString GetValue(XFA_VALUEPICTURE eValueType); + + WideString GetPictureContent(XFA_VALUEPICTURE ePicture); + IFX_Locale* GetLocale(); + + WideString GetNormalizeDataValue(const WideString& wsValue); + WideString GetFormatDataValue(const WideString& wsValue); + WideString NormalizeNumStr(const WideString& wsValue); + + WideString GetPasswordChar(); + std::pair<XFA_Element, int32_t> GetMaxChars(); + int32_t GetFracDigits(); + int32_t GetLeadDigits(); + + WideString NumericLimit(const WideString& wsValue, + int32_t iLead, + int32_t iTread) const; + + bool IsPreNull() const { return m_bPreNull; } + void SetPreNull(bool val) { m_bPreNull = val; } + bool IsNull() const { return m_bIsNull; } + void SetIsNull(bool val) { m_bIsNull = val; } + + private: + void CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap); + bool CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculateWidgetAutoSize(CFX_SizeF& size); + bool CalculateTextEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculateCheckButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculatePushButtonAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + CFX_SizeF CalculateImageSize(float img_width, + float img_height, + float dpi_x, + float dpi_y); + bool CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + bool CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size); + float CalculateWidgetAutoHeight(float fHeightCalc); + float CalculateWidgetAutoWidth(float fWidthCalc); + float GetWidthWithoutMargin(float fWidthCalc); + float GetHeightWithoutMargin(float fHeightCalc); + void CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF& size); + void CalculateAccWidthAndHeight(CXFA_FFDoc* doc, + XFA_Element eUIType, + float& fWidth, + float& fCalcHeight); + void InitLayoutData(); + void StartTextLayout(CXFA_FFDoc* doc, float& fCalcWidth, float& fCalcHeight); + + void InsertListTextItem(CXFA_Node* pItems, + const WideString& wsText, + int32_t nIndex); + WideString FormatNumStr(const WideString& wsValue, IFX_Locale* pLocale); + void GetItemLabel(const WideStringView& wsValue, WideString& wsLabel); + + std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData; + bool m_bIsNull; + bool m_bPreNull; + CXFA_Node* m_pUiChildNode; + XFA_Element m_eUIType; + CXFA_Node* m_pNode; +}; + +#endif // XFA_FXFA_CXFA_WIDGETACC_H_ diff --git a/xfa/fxfa/cxfa_widgetacciterator.cpp b/xfa/fxfa/cxfa_widgetacciterator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ece5604f7df5a716a1366ad8a1f1bb3ba451cdd6 --- /dev/null +++ b/xfa/fxfa/cxfa_widgetacciterator.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_widgetacciterator.h" + +#include "xfa/fxfa/cxfa_widgetacc.h" + +CXFA_WidgetAccIterator::CXFA_WidgetAccIterator(CXFA_Node* pTravelRoot) + : m_ContentIterator(pTravelRoot), m_pCurWidgetAcc(nullptr) {} + +CXFA_WidgetAccIterator::~CXFA_WidgetAccIterator() {} + +CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToNext() { + CXFA_Node* pItem = m_pCurWidgetAcc ? m_ContentIterator.MoveToNext() + : m_ContentIterator.GetCurrent(); + while (pItem) { + m_pCurWidgetAcc = pItem->GetWidgetAcc(); + if (m_pCurWidgetAcc) + return m_pCurWidgetAcc.Get(); + pItem = m_ContentIterator.MoveToNext(); + } + return nullptr; +} + +void CXFA_WidgetAccIterator::SkipTree() { + m_ContentIterator.SkipChildrenAndMoveToNext(); + m_pCurWidgetAcc = nullptr; +} diff --git a/xfa/fxfa/cxfa_widgetacciterator.h b/xfa/fxfa/cxfa_widgetacciterator.h new file mode 100644 index 0000000000000000000000000000000000000000..79860a4c4cdab73f3e5f47094a2098db22d76570 --- /dev/null +++ b/xfa/fxfa/cxfa_widgetacciterator.h @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_CXFA_WIDGETACCITERATOR_H_ +#define XFA_FXFA_CXFA_WIDGETACCITERATOR_H_ + +#include "core/fxcrt/unowned_ptr.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" + +class CXFA_Node; +class CXFA_WidgetAcc; + +class CXFA_WidgetAccIterator { + public: + explicit CXFA_WidgetAccIterator(CXFA_Node* pTravelRoot); + ~CXFA_WidgetAccIterator(); + + CXFA_WidgetAcc* MoveToNext(); + void SkipTree(); + + private: + CXFA_ContainerIterator m_ContentIterator; + UnownedPtr<CXFA_WidgetAcc> m_pCurWidgetAcc; +}; + +#endif // XFA_FXFA_CXFA_WIDGETACCITERATOR_H_ diff --git a/xfa/fxfa/fm2js/DEPS b/xfa/fxfa/fm2js/DEPS new file mode 100644 index 0000000000000000000000000000000000000000..2be03524b6af61bb2441132efb9935c5b8cf833e --- /dev/null +++ b/xfa/fxfa/fm2js/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + '+third_party/icu', +] diff --git a/xfa/fxfa/fm2js/cxfa_fmexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmexpression.cpp new file mode 100644 index 0000000000000000000000000000000000000000..759a875b8db5c231b528bcf9e01de579faca1169 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmexpression.cpp @@ -0,0 +1,771 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/fm2js/cxfa_fmexpression.h" + +#include <utility> + +#include "core/fxcrt/cfx_widetextbuf.h" +#include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h" +#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" + +namespace { + +const wchar_t RUNTIMEBLOCKTEMPARRAY[] = L"pfm_ary"; + +const wchar_t RUNTIMEBLOCKTEMPARRAYINDEX[] = L"pfm_ary_idx"; + +const wchar_t kLessEqual[] = L" <= "; +const wchar_t kGreaterEqual[] = L" >= "; +const wchar_t kPlusEqual[] = L" += "; +const wchar_t kMinusEqual[] = L" -= "; + +} // namespace + +CXFA_FMExpression::CXFA_FMExpression(uint32_t line) + : m_type(XFA_FM_EXPTYPE_UNKNOWN), m_line(line) {} + +CXFA_FMExpression::CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type) + : m_type(type), m_line(line) {} + +bool CXFA_FMExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +bool CXFA_FMExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +CXFA_FMFunctionDefinition::CXFA_FMFunctionDefinition( + uint32_t line, + bool isGlobal, + const WideStringView& wsName, + std::vector<WideStringView>&& arguments, + std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_FUNC), + m_wsName(wsName), + m_pArguments(std::move(arguments)), + m_pExpressions(std::move(expressions)), + m_isGlobal(isGlobal) {} + +CXFA_FMFunctionDefinition::~CXFA_FMFunctionDefinition() {} + +bool CXFA_FMFunctionDefinition::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + if (m_isGlobal && m_pExpressions.empty()) { + javascript << L"// comments only"; + return !CXFA_IsTooBig(javascript); + } + if (m_isGlobal) { + javascript << L"(\n"; + } + javascript << L"function "; + if (!m_wsName.IsEmpty() && m_wsName[0] == L'!') { + WideString tempName = + EXCLAMATION_IN_IDENTIFIER + m_wsName.Right(m_wsName.GetLength() - 1); + javascript << tempName; + } else { + javascript << m_wsName; + } + javascript << L"("; + bool bNeedComma = false; + for (const auto& identifier : m_pArguments) { + if (bNeedComma) + javascript << L", "; + if (identifier[0] == L'!') { + WideString tempIdentifier = EXCLAMATION_IN_IDENTIFIER + + identifier.Right(identifier.GetLength() - 1); + javascript << tempIdentifier; + } else { + javascript << identifier; + } + bNeedComma = true; + } + javascript << L")\n{\n"; + javascript << L"var "; + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = null;\n"; + for (const auto& expr : m_pExpressions) { + bool ret; + if (expr == m_pExpressions.back()) + ret = expr->ToImpliedReturnJS(javascript); + else + ret = expr->ToJavaScript(javascript); + + if (!ret) + return false; + } + javascript << L"return "; + if (m_isGlobal) { + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L")"; + } else { + javascript << RUNTIMEFUNCTIONRETURNVALUE; + } + javascript << L";\n}\n"; + if (m_isGlobal) { + javascript << L").call(this);\n"; + } + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMFunctionDefinition::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +CXFA_FMVarExpression::CXFA_FMVarExpression( + uint32_t line, + const WideStringView& wsName, + std::unique_ptr<CXFA_FMExpression> pInit) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_VAR), + m_wsName(wsName), + m_pInit(std::move(pInit)) {} + +CXFA_FMVarExpression::~CXFA_FMVarExpression() {} + +bool CXFA_FMVarExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"var "; + WideString tempName(m_wsName); + if (m_wsName[0] == L'!') { + tempName = + EXCLAMATION_IN_IDENTIFIER + m_wsName.Right(m_wsName.GetLength() - 1); + } + javascript << tempName; + javascript << L" = "; + if (m_pInit) { + if (!m_pInit->ToJavaScript(javascript)) + return false; + javascript << tempName; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(VARFILTER); + javascript << L"("; + javascript << tempName; + javascript << L");\n"; + } else { + javascript << L"\"\";\n"; + } + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMVarExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"var "; + WideString tempName(m_wsName); + if (m_wsName[0] == L'!') { + tempName = + EXCLAMATION_IN_IDENTIFIER + m_wsName.Right(m_wsName.GetLength() - 1); + } + javascript << tempName; + javascript << L" = "; + if (m_pInit) { + if (!m_pInit->ToJavaScript(javascript)) + return false; + javascript << tempName; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(VARFILTER); + javascript << L"("; + javascript << tempName; + javascript << L");\n"; + } else { + javascript << L"\"\";\n"; + } + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = "; + javascript << tempName; + javascript << L";\n"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMExpExpression::CXFA_FMExpExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExpression) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_EXP), + m_pExpression(std::move(pExpression)) {} + +CXFA_FMExpExpression::~CXFA_FMExpExpression() {} + +bool CXFA_FMExpExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + bool ret = m_pExpression->ToJavaScript(javascript); + if (m_pExpression->GetOperatorToken() != TOKassign) + javascript << L";\n"; + return ret; +} + +bool CXFA_FMExpExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + if (m_pExpression->GetOperatorToken() == TOKassign) + return m_pExpression->ToImpliedReturnJS(javascript); + + if (m_pExpression->GetOperatorToken() == TOKstar || + m_pExpression->GetOperatorToken() == TOKdotstar || + m_pExpression->GetOperatorToken() == TOKdotscream || + m_pExpression->GetOperatorToken() == TOKdotdot || + m_pExpression->GetOperatorToken() == TOKdot) { + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pExpression->ToJavaScript(javascript)) + return false; + javascript << L");\n"; + return !CXFA_IsTooBig(javascript); + } + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = "; + if (!m_pExpression->ToJavaScript(javascript)) + return false; + javascript << L";\n"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMBlockExpression::CXFA_FMBlockExpression( + uint32_t line, + std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BLOCK), + m_ExpressionList(std::move(pExpressionList)) {} + +CXFA_FMBlockExpression::~CXFA_FMBlockExpression() {} + +bool CXFA_FMBlockExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"{\n"; + for (const auto& expr : m_ExpressionList) { + if (!expr->ToJavaScript(javascript)) + return false; + } + javascript << L"}\n"; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMBlockExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"{\n"; + for (const auto& expr : m_ExpressionList) { + bool ret; + if (expr == m_ExpressionList.back()) + ret = expr->ToImpliedReturnJS(javascript); + else + ret = expr->ToJavaScript(javascript); + + if (!ret) + return false; + } + javascript << L"}\n"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMDoExpression::CXFA_FMDoExpression( + uint32_t line, + std::unique_ptr<CXFA_FMExpression> pList) + : CXFA_FMExpression(line), m_pList(std::move(pList)) {} + +CXFA_FMDoExpression::~CXFA_FMDoExpression() {} + +bool CXFA_FMDoExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + return m_pList->ToJavaScript(javascript); +} + +bool CXFA_FMDoExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + return m_pList->ToImpliedReturnJS(javascript); +} + +CXFA_FMIfExpression::CXFA_FMIfExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExpression, + std::unique_ptr<CXFA_FMExpression> pIfExpression, + std::unique_ptr<CXFA_FMExpression> pElseExpression) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_IF), + m_pExpression(std::move(pExpression)), + m_pIfExpression(std::move(pIfExpression)), + m_pElseExpression(std::move(pElseExpression)) {} + +CXFA_FMIfExpression::~CXFA_FMIfExpression() {} + +bool CXFA_FMIfExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"if ("; + if (m_pExpression) { + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pExpression->ToJavaScript(javascript)) + return false; + javascript << L")"; + } + javascript << L")\n"; + if (CXFA_IsTooBig(javascript)) + return false; + + if (m_pIfExpression) { + if (!m_pIfExpression->ToJavaScript(javascript)) + return false; + if (CXFA_IsTooBig(javascript)) + return false; + } + + if (m_pElseExpression) { + if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) { + javascript << L"else\n"; + javascript << L"{\n"; + if (!m_pElseExpression->ToJavaScript(javascript)) + return false; + javascript << L"}\n"; + } else { + javascript << L"else\n"; + if (!m_pElseExpression->ToJavaScript(javascript)) + return false; + } + } + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMIfExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"if ("; + if (m_pExpression) { + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pExpression->ToJavaScript(javascript)) + return false; + javascript << L")"; + } + javascript << L")\n"; + if (CXFA_IsTooBig(javascript)) + return false; + + if (m_pIfExpression) { + if (!m_pIfExpression->ToImpliedReturnJS(javascript)) + return false; + if (CXFA_IsTooBig(javascript)) + return false; + } + if (m_pElseExpression) { + if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) { + javascript << L"else\n"; + javascript << L"{\n"; + if (!m_pElseExpression->ToImpliedReturnJS(javascript)) + return false; + javascript << L"}\n"; + } else { + javascript << L"else\n"; + if (!m_pElseExpression->ToImpliedReturnJS(javascript)) + return false; + } + } + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMLoopExpression::~CXFA_FMLoopExpression() {} + +bool CXFA_FMLoopExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +bool CXFA_FMLoopExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +CXFA_FMWhileExpression::CXFA_FMWhileExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pCondition, + std::unique_ptr<CXFA_FMExpression> pExpression) + : CXFA_FMLoopExpression(line), + m_pCondition(std::move(pCondition)), + m_pExpression(std::move(pExpression)) {} + +CXFA_FMWhileExpression::~CXFA_FMWhileExpression() {} + +bool CXFA_FMWhileExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"while ("; + if (!m_pCondition->ToJavaScript(javascript)) + return false; + javascript << L")\n"; + if (CXFA_IsTooBig(javascript)) + return false; + + if (!m_pExpression->ToJavaScript(javascript)) + return false; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMWhileExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"while ("; + if (!m_pCondition->ToJavaScript(javascript)) + return false; + javascript << L")\n"; + if (CXFA_IsTooBig(javascript)) + return false; + + if (!m_pExpression->ToImpliedReturnJS(javascript)) + return false; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMBreakExpression::CXFA_FMBreakExpression(uint32_t line) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BREAK) {} + +CXFA_FMBreakExpression::~CXFA_FMBreakExpression() {} + +bool CXFA_FMBreakExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"break;\n"; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMBreakExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"break;\n"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMContinueExpression::CXFA_FMContinueExpression(uint32_t line) + : CXFA_FMExpression(line, XFA_FM_EXPTYPE_CONTINUE) {} + +CXFA_FMContinueExpression::~CXFA_FMContinueExpression() {} + +bool CXFA_FMContinueExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"continue;\n"; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMContinueExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"continue;\n"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMForExpression::CXFA_FMForExpression( + uint32_t line, + const WideStringView& wsVariant, + std::unique_ptr<CXFA_FMSimpleExpression> pAssignment, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, + int32_t iDirection, + std::unique_ptr<CXFA_FMSimpleExpression> pStep, + std::unique_ptr<CXFA_FMExpression> pList) + : CXFA_FMLoopExpression(line), + m_wsVariant(wsVariant), + m_pAssignment(std::move(pAssignment)), + m_pAccessor(std::move(pAccessor)), + m_bDirection(iDirection == 1), + m_pStep(std::move(pStep)), + m_pList(std::move(pList)) {} + +CXFA_FMForExpression::~CXFA_FMForExpression() {} + +bool CXFA_FMForExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"{\nvar "; + WideString tempVariant; + if (m_wsVariant[0] == L'!') { + tempVariant = EXCLAMATION_IN_IDENTIFIER + + m_wsVariant.Right(m_wsVariant.GetLength() - 1); + javascript << tempVariant; + } else { + tempVariant = m_wsVariant; + javascript << m_wsVariant; + } + javascript << L" = null;\n"; + javascript << L"for ("; + javascript << tempVariant; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pAssignment->ToJavaScript(javascript)) + return false; + javascript << L"); "; + javascript << tempVariant; + + javascript << (m_bDirection ? kLessEqual : kGreaterEqual); + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pAccessor->ToJavaScript(javascript)) + return false; + javascript << L"); "; + javascript << tempVariant; + javascript << (m_bDirection ? kPlusEqual : kMinusEqual); + if (CXFA_IsTooBig(javascript)) + return false; + + if (m_pStep) { + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pStep->ToJavaScript(javascript)) + return false; + javascript << L")"; + } else { + javascript << L"1"; + } + javascript << L")\n"; + if (!m_pList->ToJavaScript(javascript)) + return false; + javascript << L"}\n"; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMForExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"{\nvar "; + WideString tempVariant; + if (m_wsVariant[0] == L'!') { + tempVariant = EXCLAMATION_IN_IDENTIFIER + + m_wsVariant.Right(m_wsVariant.GetLength() - 1); + javascript << tempVariant; + } else { + tempVariant = m_wsVariant; + javascript << m_wsVariant; + } + javascript << L" = null;\n"; + javascript << L"for ("; + javascript << tempVariant; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pAssignment->ToJavaScript(javascript)) + return false; + javascript << L"); "; + javascript << tempVariant; + + javascript << (m_bDirection ? kLessEqual : kGreaterEqual); + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pAccessor->ToJavaScript(javascript)) + return false; + javascript << L"); "; + javascript << tempVariant; + javascript << L" += "; + javascript << (m_bDirection ? kPlusEqual : kMinusEqual); + if (CXFA_IsTooBig(javascript)) + return false; + + if (m_pStep) { + javascript << XFA_FM_EXPTypeToString(GETFMVALUE); + javascript << L"("; + if (!m_pStep->ToJavaScript(javascript)) + return false; + javascript << L")"; + if (CXFA_IsTooBig(javascript)) + return false; + } else { + javascript << L"1"; + } + javascript << L")\n"; + if (!m_pList->ToImpliedReturnJS(javascript)) + return false; + javascript << L"}\n"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMForeachExpression::CXFA_FMForeachExpression( + uint32_t line, + const WideStringView& wsIdentifier, + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pAccessors, + std::unique_ptr<CXFA_FMExpression> pList) + : CXFA_FMLoopExpression(line), + m_wsIdentifier(wsIdentifier), + m_pAccessors(std::move(pAccessors)), + m_pList(std::move(pList)) {} + +CXFA_FMForeachExpression::~CXFA_FMForeachExpression() {} + +bool CXFA_FMForeachExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"{\n"; + javascript << L"var "; + if (m_wsIdentifier[0] == L'!') { + WideString tempIdentifier = + EXCLAMATION_IN_IDENTIFIER + + m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1); + javascript << tempIdentifier; + } else { + javascript << m_wsIdentifier; + } + javascript << L" = null;\n"; + javascript << L"var "; + javascript << RUNTIMEBLOCKTEMPARRAY; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT); + javascript << L"("; + + for (const auto& expr : m_pAccessors) { + if (!expr->ToJavaScript(javascript)) + return false; + if (expr != m_pAccessors.back()) + javascript << L", "; + } + javascript << L");\n"; + javascript << L"var "; + javascript << RUNTIMEBLOCKTEMPARRAYINDEX; + javascript << (L" = 0;\n"); + javascript << L"while("; + javascript << RUNTIMEBLOCKTEMPARRAYINDEX; + javascript << L" < "; + javascript << RUNTIMEBLOCKTEMPARRAY; + javascript << L".length)\n{\n"; + if (m_wsIdentifier[0] == L'!') { + WideString tempIdentifier = + EXCLAMATION_IN_IDENTIFIER + + m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1); + javascript << tempIdentifier; + } else { + javascript << m_wsIdentifier; + } + javascript << L" = "; + javascript << RUNTIMEBLOCKTEMPARRAY; + javascript << L"["; + javascript << RUNTIMEBLOCKTEMPARRAYINDEX; + javascript << L"++];\n"; + if (!m_pList->ToJavaScript(javascript)) + return false; + javascript << L"}\n"; + javascript << L"}\n"; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMForeachExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = 0;\n"; + javascript << L"{\n"; + javascript << L"var "; + if (m_wsIdentifier[0] == L'!') { + WideString tempIdentifier = + EXCLAMATION_IN_IDENTIFIER + + m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1); + javascript << tempIdentifier; + } else { + javascript << m_wsIdentifier; + } + javascript << L" = null;\n"; + javascript << L"var "; + javascript << RUNTIMEBLOCKTEMPARRAY; + javascript << L" = "; + javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT); + javascript << L"("; + for (const auto& expr : m_pAccessors) { + if (!expr->ToJavaScript(javascript)) + return false; + if (expr != m_pAccessors.back()) + javascript << L", "; + } + javascript << L");\n"; + javascript << L"var "; + javascript << RUNTIMEBLOCKTEMPARRAYINDEX; + javascript << L" = 0;\n"; + javascript << L"while("; + javascript << RUNTIMEBLOCKTEMPARRAYINDEX; + javascript << L" < "; + javascript << RUNTIMEBLOCKTEMPARRAY; + javascript << L".length)\n{\n"; + if (m_wsIdentifier[0] == L'!') { + WideString tempIdentifier = + EXCLAMATION_IN_IDENTIFIER + + m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1); + javascript << tempIdentifier; + } else { + javascript << m_wsIdentifier; + } + javascript << L" = "; + javascript << RUNTIMEBLOCKTEMPARRAY; + javascript << L"["; + javascript << RUNTIMEBLOCKTEMPARRAYINDEX; + javascript << L"++];\n"; + if (!m_pList->ToImpliedReturnJS(javascript)) + return false; + javascript << L"}\n"; + javascript << L"}\n"; + return !CXFA_IsTooBig(javascript); +} diff --git a/xfa/fxfa/fm2js/cxfa_fmexpression.h b/xfa/fxfa/fm2js/cxfa_fmexpression.h new file mode 100644 index 0000000000000000000000000000000000000000..cfbba3af22f8b054922787da1c4fd575bcdd7dbf --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmexpression.h @@ -0,0 +1,217 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_FM2JS_CXFA_FMEXPRESSION_H_ +#define XFA_FXFA_FM2JS_CXFA_FMEXPRESSION_H_ + +#include <memory> +#include <vector> + +#include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h" + +enum XFA_FM_EXPTYPE { + XFA_FM_EXPTYPE_UNKNOWN, + XFA_FM_EXPTYPE_FUNC, + XFA_FM_EXPTYPE_VAR, + XFA_FM_EXPTYPE_EXP, + XFA_FM_EXPTYPE_BLOCK, + XFA_FM_EXPTYPE_IF, + XFA_FM_EXPTYPE_BREAK, + XFA_FM_EXPTYPE_CONTINUE, +}; + +class CFX_WideTextBuf; + +class CXFA_FMExpression { + public: + explicit CXFA_FMExpression(uint32_t line); + CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type); + virtual ~CXFA_FMExpression() {} + + virtual bool ToJavaScript(CFX_WideTextBuf& javascript); + virtual bool ToImpliedReturnJS(CFX_WideTextBuf&); + uint32_t GetLine() { return m_line; } + XFA_FM_EXPTYPE GetExpType() const { return m_type; } + + private: + XFA_FM_EXPTYPE m_type; + uint32_t m_line; +}; + +class CXFA_FMFunctionDefinition : public CXFA_FMExpression { + public: + // Takes ownership of |arguments| and |expressions|. + CXFA_FMFunctionDefinition( + uint32_t line, + bool isGlobal, + const WideStringView& wsName, + std::vector<WideStringView>&& arguments, + std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions); + ~CXFA_FMFunctionDefinition() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + WideStringView m_wsName; + std::vector<WideStringView> m_pArguments; + std::vector<std::unique_ptr<CXFA_FMExpression>> m_pExpressions; + bool m_isGlobal; +}; + +class CXFA_FMVarExpression : public CXFA_FMExpression { + public: + CXFA_FMVarExpression(uint32_t line, + const WideStringView& wsName, + std::unique_ptr<CXFA_FMExpression> pInit); + ~CXFA_FMVarExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + WideStringView m_wsName; + std::unique_ptr<CXFA_FMExpression> m_pInit; +}; + +class CXFA_FMExpExpression : public CXFA_FMExpression { + public: + CXFA_FMExpExpression(uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExpression); + ~CXFA_FMExpExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + std::unique_ptr<CXFA_FMSimpleExpression> m_pExpression; +}; + +class CXFA_FMBlockExpression : public CXFA_FMExpression { + public: + CXFA_FMBlockExpression( + uint32_t line, + std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList); + ~CXFA_FMBlockExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + std::vector<std::unique_ptr<CXFA_FMExpression>> m_ExpressionList; +}; + +class CXFA_FMDoExpression : public CXFA_FMExpression { + public: + CXFA_FMDoExpression(uint32_t line, std::unique_ptr<CXFA_FMExpression> pList); + ~CXFA_FMDoExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + std::unique_ptr<CXFA_FMExpression> m_pList; +}; + +class CXFA_FMIfExpression : public CXFA_FMExpression { + public: + CXFA_FMIfExpression(uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExpression, + std::unique_ptr<CXFA_FMExpression> pIfExpression, + std::unique_ptr<CXFA_FMExpression> pElseExpression); + ~CXFA_FMIfExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + std::unique_ptr<CXFA_FMSimpleExpression> m_pExpression; + std::unique_ptr<CXFA_FMExpression> m_pIfExpression; + std::unique_ptr<CXFA_FMExpression> m_pElseExpression; +}; + +class CXFA_FMLoopExpression : public CXFA_FMExpression { + public: + explicit CXFA_FMLoopExpression(uint32_t line) : CXFA_FMExpression(line) {} + ~CXFA_FMLoopExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; +}; + +class CXFA_FMWhileExpression : public CXFA_FMLoopExpression { + public: + CXFA_FMWhileExpression(uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pCodition, + std::unique_ptr<CXFA_FMExpression> pExpression); + ~CXFA_FMWhileExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + std::unique_ptr<CXFA_FMSimpleExpression> m_pCondition; + std::unique_ptr<CXFA_FMExpression> m_pExpression; +}; + +class CXFA_FMBreakExpression : public CXFA_FMExpression { + public: + explicit CXFA_FMBreakExpression(uint32_t line); + ~CXFA_FMBreakExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; +}; + +class CXFA_FMContinueExpression : public CXFA_FMExpression { + public: + explicit CXFA_FMContinueExpression(uint32_t line); + ~CXFA_FMContinueExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; +}; + +class CXFA_FMForExpression : public CXFA_FMLoopExpression { + public: + CXFA_FMForExpression(uint32_t line, + const WideStringView& wsVariant, + std::unique_ptr<CXFA_FMSimpleExpression> pAssignment, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, + int32_t iDirection, + std::unique_ptr<CXFA_FMSimpleExpression> pStep, + std::unique_ptr<CXFA_FMExpression> pList); + ~CXFA_FMForExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + WideStringView m_wsVariant; + std::unique_ptr<CXFA_FMSimpleExpression> m_pAssignment; + std::unique_ptr<CXFA_FMSimpleExpression> m_pAccessor; + const bool m_bDirection; + std::unique_ptr<CXFA_FMSimpleExpression> m_pStep; + std::unique_ptr<CXFA_FMExpression> m_pList; +}; + +class CXFA_FMForeachExpression : public CXFA_FMLoopExpression { + public: + // Takes ownership of |pAccessors|. + CXFA_FMForeachExpression( + uint32_t line, + const WideStringView& wsIdentifier, + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pAccessors, + std::unique_ptr<CXFA_FMExpression> pList); + ~CXFA_FMForeachExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf&) override; + + private: + WideStringView m_wsIdentifier; + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> m_pAccessors; + std::unique_ptr<CXFA_FMExpression> m_pList; +}; + +#endif // XFA_FXFA_FM2JS_CXFA_FMEXPRESSION_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmlexer.cpp b/xfa/fxfa/fm2js/cxfa_fmlexer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..675abc3046df5ac3dbec23dbafc432ae3e9d8afc --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmlexer.cpp @@ -0,0 +1,456 @@ +// Copright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" + +#include <algorithm> + +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/ptr_util.h" +#include "third_party/icu/source/common/unicode/uchar.h" + +namespace { + +bool IsFormCalcCharacter(wchar_t c) { + return (c >= 0x09 && c <= 0x0D) || (c >= 0x20 && c <= 0xd7FF) || + (c >= 0xE000 && c <= 0xFFFD); +} + +bool IsIdentifierCharacter(wchar_t c) { + return u_isalnum(c) || c == 0x005F || // '_' + c == 0x0024; // '$' +} + +bool IsInitialIdentifierCharacter(wchar_t c) { + return u_isalpha(c) || c == 0x005F || // '_' + c == 0x0024 || // '$' + c == 0x0021; // '!' +} + +bool IsWhitespaceCharacter(wchar_t c) { + return c == 0x0009 || // Horizontal tab + c == 0x000B || // Vertical tab + c == 0x000C || // Form feed + c == 0x0020; // Space +} + +const XFA_FMKeyword keyWords[] = { + {TOKand, 0x00000026, L"&"}, + {TOKlparen, 0x00000028, L"("}, + {TOKrparen, 0x00000029, L")"}, + {TOKmul, 0x0000002a, L"*"}, + {TOKplus, 0x0000002b, L"+"}, + {TOKcomma, 0x0000002c, L","}, + {TOKminus, 0x0000002d, L"-"}, + {TOKdot, 0x0000002e, L"."}, + {TOKdiv, 0x0000002f, L"/"}, + {TOKlt, 0x0000003c, L"<"}, + {TOKassign, 0x0000003d, L"="}, + {TOKgt, 0x0000003e, L">"}, + {TOKlbracket, 0x0000005b, L"["}, + {TOKrbracket, 0x0000005d, L"]"}, + {TOKor, 0x0000007c, L"|"}, + {TOKdotscream, 0x0000ec11, L".#"}, + {TOKdotstar, 0x0000ec18, L".*"}, + {TOKdotdot, 0x0000ec1c, L".."}, + {TOKle, 0x000133f9, L"<="}, + {TOKne, 0x000133fa, L"<>"}, + {TOKeq, 0x0001391a, L"=="}, + {TOKge, 0x00013e3b, L">="}, + {TOKdo, 0x00020153, L"do"}, + {TOKkseq, 0x00020676, L"eq"}, + {TOKksge, 0x000210ac, L"ge"}, + {TOKksgt, 0x000210bb, L"gt"}, + {TOKif, 0x00021aef, L"if"}, + {TOKin, 0x00021af7, L"in"}, + {TOKksle, 0x00022a51, L"le"}, + {TOKkslt, 0x00022a60, L"lt"}, + {TOKksne, 0x00023493, L"ne"}, + {TOKksor, 0x000239c1, L"or"}, + {TOKnull, 0x052931bb, L"null"}, + {TOKbreak, 0x05518c25, L"break"}, + {TOKksand, 0x09f9db33, L"and"}, + {TOKend, 0x0a631437, L"end"}, + {TOKeof, 0x0a63195a, L"eof"}, + {TOKfor, 0x0a7d67a7, L"for"}, + {TOKnan, 0x0b4f91dd, L"nan"}, + {TOKksnot, 0x0b4fd9b1, L"not"}, + {TOKvar, 0x0c2203e9, L"var"}, + {TOKthen, 0x2d5738cf, L"then"}, + {TOKelse, 0x45f65ee9, L"else"}, + {TOKexit, 0x4731d6ba, L"exit"}, + {TOKdownto, 0x4caadc3b, L"downto"}, + {TOKreturn, 0x4db8bd60, L"return"}, + {TOKinfinity, 0x5c0a010a, L"infinity"}, + {TOKendwhile, 0x5c64bff0, L"endwhile"}, + {TOKforeach, 0x67e31f38, L"foreach"}, + {TOKendfunc, 0x68f984a3, L"endfunc"}, + {TOKelseif, 0x78253218, L"elseif"}, + {TOKwhile, 0x84229259, L"while"}, + {TOKendfor, 0x8ab49d7e, L"endfor"}, + {TOKthrow, 0x8db05c94, L"throw"}, + {TOKstep, 0xa7a7887c, L"step"}, + {TOKupto, 0xb5155328, L"upto"}, + {TOKcontinue, 0xc0340685, L"continue"}, + {TOKfunc, 0xcdce60ec, L"func"}, + {TOKendif, 0xe0e8fee6, L"endif"}, +}; + +const XFA_FM_TOKEN KEYWORD_START = TOKdo; +const XFA_FM_TOKEN KEYWORD_END = TOKendif; + +const wchar_t* tokenStrings[] = { + L"TOKand", L"TOKlparen", L"TOKrparen", L"TOKmul", + L"TOKplus", L"TOKcomma", L"TOKminus", L"TOKdot", + L"TOKdiv", L"TOKlt", L"TOKassign", L"TOKgt", + L"TOKlbracket", L"TOKrbracket", L"TOKor", L"TOKdotscream", + L"TOKdotstar", L"TOKdotdot", L"TOKle", L"TOKne", + L"TOKeq", L"TOKge", L"TOKdo", L"TOKkseq", + L"TOKksge", L"TOKksgt", L"TOKif", L"TOKin", + L"TOKksle", L"TOKkslt", L"TOKksne", L"TOKksor", + L"TOKnull", L"TOKbreak", L"TOKksand", L"TOKend", + L"TOKeof", L"TOKfor", L"TOKnan", L"TOKksnot", + L"TOKvar", L"TOKthen", L"TOKelse", L"TOKexit", + L"TOKdownto", L"TOKreturn", L"TOKinfinity", L"TOKendwhile", + L"TOKforeach", L"TOKendfunc", L"TOKelseif", L"TOKwhile", + L"TOKendfor", L"TOKthrow", L"TOKstep", L"TOKupto", + L"TOKcontinue", L"TOKfunc", L"TOKendif", L"TOKstar", + L"TOKidentifier", L"TOKunderscore", L"TOKdollar", L"TOKexclamation", + L"TOKcall", L"TOKstring", L"TOKnumber", L"TOKreserver", +}; + +XFA_FM_TOKEN TokenizeIdentifier(const WideStringView& str) { + uint32_t key = FX_HashCode_GetW(str, true); + + const XFA_FMKeyword* end = std::begin(keyWords) + KEYWORD_END + 1; + const XFA_FMKeyword* result = + std::lower_bound(std::begin(keyWords) + KEYWORD_START, end, key, + [](const XFA_FMKeyword& iter, const uint32_t& val) { + return iter.m_hash < val; + }); + if (result != end && result->m_hash == key) + return result->m_type; + return TOKidentifier; +} + +} // namespace + +CXFA_FMToken::CXFA_FMToken() : m_type(TOKreserver), m_line_num(1) {} + +CXFA_FMToken::CXFA_FMToken(uint32_t line_num) + : m_type(TOKreserver), m_line_num(line_num) {} + +CXFA_FMToken::~CXFA_FMToken() {} + +WideString CXFA_FMToken::ToDebugString() const { + WideString str(L"type = "); + str += tokenStrings[m_type]; + str += L", string = "; + str += m_string; + str += L", line_num = "; + str += std::to_wstring(m_line_num).c_str(); + return str; +} + +CXFA_FMLexer::CXFA_FMLexer(const WideStringView& wsFormCalc) + : m_cursor(wsFormCalc.unterminated_c_str()), + m_end(m_cursor + wsFormCalc.GetLength() - 1), + m_current_line(1), + m_lexer_error(false) {} + +CXFA_FMLexer::~CXFA_FMLexer() {} + +std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::NextToken() { + if (m_lexer_error) + return nullptr; + + m_token = pdfium::MakeUnique<CXFA_FMToken>(m_current_line); + while (m_cursor <= m_end && *m_cursor) { + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + + switch (*m_cursor) { + case '\n': + ++m_current_line; + m_token->m_line_num = m_current_line; + ++m_cursor; + break; + case '\r': + ++m_cursor; + break; + case ';': + AdvanceForComment(); + break; + case '"': + m_token->m_type = TOKstring; + AdvanceForString(); + return std::move(m_token); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + m_token->m_type = TOKnumber; + AdvanceForNumber(); + return std::move(m_token); + case '=': + ++m_cursor; + if (m_cursor > m_end) { + m_token->m_type = TOKassign; + return std::move(m_token); + } + + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + if (*m_cursor == '=') { + m_token->m_type = TOKeq; + ++m_cursor; + } else { + m_token->m_type = TOKassign; + } + return std::move(m_token); + case '<': + ++m_cursor; + if (m_cursor > m_end) { + m_token->m_type = TOKlt; + return std::move(m_token); + } + + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + if (*m_cursor == '=') { + m_token->m_type = TOKle; + ++m_cursor; + } else if (*m_cursor == '>') { + m_token->m_type = TOKne; + ++m_cursor; + } else { + m_token->m_type = TOKlt; + } + return std::move(m_token); + case '>': + ++m_cursor; + if (m_cursor > m_end) { + m_token->m_type = TOKgt; + return std::move(m_token); + } + + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + if (*m_cursor == '=') { + m_token->m_type = TOKge; + ++m_cursor; + } else { + m_token->m_type = TOKgt; + } + return std::move(m_token); + case ',': + m_token->m_type = TOKcomma; + ++m_cursor; + return std::move(m_token); + case '(': + m_token->m_type = TOKlparen; + ++m_cursor; + return std::move(m_token); + case ')': + m_token->m_type = TOKrparen; + ++m_cursor; + return std::move(m_token); + case '[': + m_token->m_type = TOKlbracket; + ++m_cursor; + return std::move(m_token); + case ']': + m_token->m_type = TOKrbracket; + ++m_cursor; + return std::move(m_token); + case '&': + ++m_cursor; + m_token->m_type = TOKand; + return std::move(m_token); + case '|': + ++m_cursor; + m_token->m_type = TOKor; + return std::move(m_token); + case '+': + ++m_cursor; + m_token->m_type = TOKplus; + return std::move(m_token); + case '-': + ++m_cursor; + m_token->m_type = TOKminus; + return std::move(m_token); + case '*': + ++m_cursor; + m_token->m_type = TOKmul; + return std::move(m_token); + case '/': { + ++m_cursor; + if (m_cursor > m_end) { + m_token->m_type = TOKdiv; + return std::move(m_token); + } + + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + if (*m_cursor != '/') { + m_token->m_type = TOKdiv; + return std::move(m_token); + } + AdvanceForComment(); + break; + } + case '.': + ++m_cursor; + if (m_cursor > m_end) { + m_token->m_type = TOKdot; + return std::move(m_token); + } + + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + + if (*m_cursor == '.') { + m_token->m_type = TOKdotdot; + ++m_cursor; + } else if (*m_cursor == '*') { + m_token->m_type = TOKdotstar; + ++m_cursor; + } else if (*m_cursor == '#') { + m_token->m_type = TOKdotscream; + ++m_cursor; + } else if (*m_cursor <= '9' && *m_cursor >= '0') { + m_token->m_type = TOKnumber; + --m_cursor; + AdvanceForNumber(); + } else { + m_token->m_type = TOKdot; + } + return std::move(m_token); + default: + if (IsWhitespaceCharacter(*m_cursor)) { + ++m_cursor; + break; + } + if (!IsInitialIdentifierCharacter(*m_cursor)) { + RaiseError(); + return nullptr; + } + AdvanceForIdentifier(); + return std::move(m_token); + } + } + + // If there isn't currently a token type then mark it EOF. + if (m_token->m_type == TOKreserver) + m_token->m_type = TOKeof; + return std::move(m_token); +} + +void CXFA_FMLexer::AdvanceForNumber() { + // This will set end to the character after the end of the number. + wchar_t* end = nullptr; + if (m_cursor) + wcstod(const_cast<wchar_t*>(m_cursor), &end); + if (!end || FXSYS_iswalpha(*end)) { + RaiseError(); + return; + } + + m_token->m_string = + WideStringView(m_cursor, static_cast<size_t>(end - m_cursor)); + m_cursor = end; +} + +void CXFA_FMLexer::AdvanceForString() { + const wchar_t* start = m_cursor; + ++m_cursor; + while (m_cursor <= m_end && *m_cursor) { + if (!IsFormCalcCharacter(*m_cursor)) + break; + + if (*m_cursor == '"') { + // Check for escaped "s, i.e. "". + ++m_cursor; + // If the end of the input has been reached it was not escaped. + if (m_cursor > m_end) { + m_token->m_string = + WideStringView(start, static_cast<size_t>(m_cursor - start)); + return; + } + // If the next character is not a " then the end of the string has been + // found. + if (*m_cursor != '"') { + if (!IsFormCalcCharacter(*m_cursor)) { + break; + } + m_token->m_string = WideStringView(start, (m_cursor - start)); + return; + } + } + ++m_cursor; + } + + // Didn't find the end of the string. + RaiseError(); +} + +void CXFA_FMLexer::AdvanceForIdentifier() { + const wchar_t* start = m_cursor; + ++m_cursor; + while (m_cursor <= m_end && *m_cursor) { + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return; + } + + if (!IsIdentifierCharacter(*m_cursor)) { + break; + } + ++m_cursor; + } + m_token->m_string = + WideStringView(start, static_cast<size_t>(m_cursor - start)); + m_token->m_type = TokenizeIdentifier(m_token->m_string); +} + +void CXFA_FMLexer::AdvanceForComment() { + m_cursor++; + while (m_cursor <= m_end && *m_cursor) { + if (!IsFormCalcCharacter(*m_cursor)) { + RaiseError(); + return; + } + + if (*m_cursor == L'\r') { + ++m_cursor; + return; + } + if (*m_cursor == L'\n') { + ++m_current_line; + ++m_cursor; + return; + } + ++m_cursor; + } +} diff --git a/xfa/fxfa/fm2js/cxfa_fmlexer.h b/xfa/fxfa/fm2js/cxfa_fmlexer.h new file mode 100644 index 0000000000000000000000000000000000000000..b9764c5aba245bd828cc9340d1652a2b836037aa --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmlexer.h @@ -0,0 +1,134 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_FM2JS_CXFA_FMLEXER_H_ +#define XFA_FXFA_FM2JS_CXFA_FMLEXER_H_ + +#include <memory> +#include <utility> + +#include "core/fxcrt/fx_string.h" + +enum XFA_FM_TOKEN { + TOKand, + TOKlparen, + TOKrparen, + TOKmul, + TOKplus, + TOKcomma, + TOKminus, + TOKdot, + TOKdiv, + TOKlt, + TOKassign, + TOKgt, + TOKlbracket, + TOKrbracket, + TOKor, + TOKdotscream, + TOKdotstar, + TOKdotdot, + TOKle, + TOKne, + TOKeq, + TOKge, + TOKdo, + TOKkseq, + TOKksge, + TOKksgt, + TOKif, + TOKin, + TOKksle, + TOKkslt, + TOKksne, + TOKksor, + TOKnull, + TOKbreak, + TOKksand, + TOKend, + TOKeof, + TOKfor, + TOKnan, + TOKksnot, + TOKvar, + TOKthen, + TOKelse, + TOKexit, + TOKdownto, + TOKreturn, + TOKinfinity, + TOKendwhile, + TOKforeach, + TOKendfunc, + TOKelseif, + TOKwhile, + TOKendfor, + TOKthrow, + TOKstep, + TOKupto, + TOKcontinue, + TOKfunc, + TOKendif, + TOKstar, + TOKidentifier, + TOKunderscore, + TOKdollar, + TOKexclamation, + TOKcall, + TOKstring, + TOKnumber, + TOKreserver +}; + +struct XFA_FMKeyword { + XFA_FM_TOKEN m_type; + uint32_t m_hash; + const wchar_t* m_keyword; +}; + +class CXFA_FMToken { + public: + CXFA_FMToken(); + explicit CXFA_FMToken(uint32_t line_num); + ~CXFA_FMToken(); + + WideString ToDebugString() const; + + WideStringView m_string; + XFA_FM_TOKEN m_type; + uint32_t m_line_num; +}; + +class CXFA_FMLexer { + public: + explicit CXFA_FMLexer(const WideStringView& wsFormcalc); + ~CXFA_FMLexer(); + + std::unique_ptr<CXFA_FMToken> NextToken(); + + void SetCurrentLine(uint32_t line) { m_current_line = line; } + const wchar_t* GetPos() { return m_cursor; } + void SetPos(const wchar_t* pos) { m_cursor = pos; } + + private: + void AdvanceForNumber(); + void AdvanceForString(); + void AdvanceForIdentifier(); + void AdvanceForComment(); + + void RaiseError() { + m_token.reset(); + m_lexer_error = true; + } + + const wchar_t* m_cursor; + const wchar_t* const m_end; + uint32_t m_current_line; + std::unique_ptr<CXFA_FMToken> m_token; + bool m_lexer_error; +}; + +#endif // XFA_FXFA_FM2JS_CXFA_FMLEXER_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6ab871b1887dfbb4bf8020e0d48589a9029c3d7 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp @@ -0,0 +1,255 @@ +// Copyright 2016 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. + +#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" + +#include <vector> + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" + +TEST(CXFA_FMLexerTest, EmptyString) { + CXFA_FMLexer lexer(L""); + std::unique_ptr<CXFA_FMToken> token = lexer.NextToken(); + EXPECT_EQ(TOKeof, token->m_type); +} + +TEST(CXFA_FMLexerTest, Numbers) { + auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"-12"); + std::unique_ptr<CXFA_FMToken> token = lexer->NextToken(); + // TODO(dsinclair): Should this return -12 instead of two tokens? + EXPECT_EQ(TOKminus, token->m_type); + token = lexer->NextToken(); + EXPECT_EQ(L"12", token->m_string); + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"1.5362"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"1.5362", token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"0.875"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"0.875", token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"5.56e-2"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"5.56e-2", token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"1.234E10"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"1.234E10", token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123456789.012345678"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + // TODO(dsinclair): This should round as per IEEE 64-bit values. + // EXPECT_EQ(L"123456789.01234567", token->m_string); + EXPECT_EQ(L"123456789.012345678", token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"99999999999999999"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + // TODO(dsinclair): This is spec'd as rounding when > 16 significant digits + // prior to the exponent. + // EXPECT_EQ(L"100000000000000000", token->m_string); + EXPECT_EQ(L"99999999999999999", token->m_string); +} + +// The quotes are stripped in CXFA_FMStringExpression::ToJavaScript. +TEST(CXFA_FMLexerTest, Strings) { + auto lexer = + pdfium::MakeUnique<CXFA_FMLexer>(L"\"The cat jumped over the fence.\""); + std::unique_ptr<CXFA_FMToken> token = lexer->NextToken(); + EXPECT_EQ(TOKstring, token->m_type); + EXPECT_EQ(L"\"The cat jumped over the fence.\"", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"\"\""); + token = lexer->NextToken(); + EXPECT_EQ(TOKstring, token->m_type); + EXPECT_EQ(L"\"\"", token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>( + L"\"The message reads: \"\"Warning: Insufficient Memory\"\"\""); + token = lexer->NextToken(); + EXPECT_EQ(TOKstring, token->m_type); + EXPECT_EQ(L"\"The message reads: \"\"Warning: Insufficient Memory\"\"\"", + token->m_string); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>( + L"\"\\u0047\\u006f\\u0066\\u0069\\u0073\\u0068\\u0021\\u000d\\u000a\""); + token = lexer->NextToken(); + EXPECT_EQ(TOKstring, token->m_type); + EXPECT_EQ( + L"\"\\u0047\\u006f\\u0066\\u0069\\u0073\\u0068\\u0021\\u000d\\u000a\"", + token->m_string); +} + +// Note, 'this' is a keyword but is not matched by the lexer. +TEST(CXFA_FMLexerTest, OperatorsAndKeywords) { + struct { + const wchar_t* op; + XFA_FM_TOKEN token; + } op[] = {{L"+", TOKplus}, + {L"/", TOKdiv}, + {L"-", TOKminus}, + {L"&", TOKand}, + {L"|", TOKor}, + {L"*", TOKmul}, + {L"<", TOKlt}, + {L">", TOKgt}, + {L"==", TOKeq}, + {L"<>", TOKne}, + {L"<=", TOKle}, + {L">=", TOKge}, + {L"and", TOKksand}, + {L"break", TOKbreak}, + {L"continue", TOKcontinue}, + {L"do", TOKdo}, + {L"downto", TOKdownto}, + {L"else", TOKelse}, + {L"elseif", TOKelseif}, + {L"end", TOKend}, + {L"endfor", TOKendfor}, + {L"endfunc", TOKendfunc}, + {L"endif", TOKendif}, + {L"endwhile", TOKendwhile}, + {L"eq", TOKkseq}, + {L"exit", TOKexit}, + {L"for", TOKfor}, + {L"foreach", TOKforeach}, + {L"func", TOKfunc}, + {L"ge", TOKksge}, + {L"gt", TOKksgt}, + {L"if", TOKif}, + {L"in", TOKin}, + {L"infinity", TOKinfinity}, + {L"le", TOKksle}, + {L"lt", TOKkslt}, + {L"nan", TOKnan}, + {L"ne", TOKksne}, + {L"not", TOKksnot}, + {L"null", TOKnull}, + {L"or", TOKksor}, + {L"return", TOKreturn}, + {L"step", TOKstep}, + {L"then", TOKthen}, + {L"throw", TOKthrow}, + {L"upto", TOKupto}, + {L"var", TOKvar}, + {L"while", TOKwhile}, + + // The following are defined but aren't in the spec. + {L"(", TOKlparen}, + {L")", TOKrparen}, + {L",", TOKcomma}, + {L".", TOKdot}, + {L"[", TOKlbracket}, + {L"]", TOKrbracket}, + {L"..", TOKdotdot}, + {L".#", TOKdotscream}, + {L".*", TOKdotstar}}; + + for (size_t i = 0; i < FX_ArraySize(op); ++i) { + auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(op[i].op); + std::unique_ptr<CXFA_FMToken> token = lexer->NextToken(); + EXPECT_EQ(op[i].token, token->m_type); + } +} + +TEST(CXFA_FMLexerTest, Comments) { + auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"// Empty."); + std::unique_ptr<CXFA_FMToken> token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"//"); + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123 // Empty.\n\"str\""); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"123", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKstring, token->m_type); + EXPECT_EQ(L"\"str\"", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L";"); + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"; Empty."); + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123 ;Empty.\n\"str\""); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"123", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKstring, token->m_type); + EXPECT_EQ(L"\"str\"", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); +} + +TEST(CXFA_FMLexerTest, ValidIdentifiers) { + std::vector<const wchar_t*> identifiers = { + L"a", L"an_identifier", L"_ident", L"$ident", L"!ident", L"GetAddr"}; + for (const auto* ident : identifiers) { + auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(ident); + std::unique_ptr<CXFA_FMToken> token = lexer->NextToken(); + EXPECT_EQ(TOKidentifier, token->m_type); + EXPECT_EQ(ident, token->m_string); + } +} + +TEST(CXFA_FMLexerTest, InvalidIdentifiers) { + auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"#a"); + EXPECT_EQ(nullptr, lexer->NextToken()); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"1a"); + EXPECT_EQ(nullptr, lexer->NextToken()); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"an@identifier"); + EXPECT_NE(nullptr, lexer->NextToken()); + EXPECT_EQ(nullptr, lexer->NextToken()); + EXPECT_EQ(nullptr, lexer->NextToken()); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"_ident@"); + EXPECT_NE(nullptr, lexer->NextToken()); + EXPECT_EQ(nullptr, lexer->NextToken()); +} + +TEST(CXFA_FMLexerTest, Whitespace) { + auto lexer = pdfium::MakeUnique<CXFA_FMLexer>(L" \t\xc\x9\xb"); + std::unique_ptr<CXFA_FMToken> token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); + + lexer = pdfium::MakeUnique<CXFA_FMLexer>(L"123 \t\xc\x9\xb 456"); + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"123", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKnumber, token->m_type); + EXPECT_EQ(L"456", token->m_string); + + token = lexer->NextToken(); + EXPECT_EQ(TOKeof, token->m_type); +} diff --git a/xfa/fxfa/fm2js/cxfa_fmparser.cpp b/xfa/fxfa/fm2js/cxfa_fmparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..644fdf2a82b4be6154600abb78b3fd51ed0ff22b --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmparser.cpp @@ -0,0 +1,1231 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "core/fxcrt/autorestorer.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const unsigned int kMaxAssignmentChainLength = 12; +const unsigned int kMaxParseDepth = 1250; + +} // namespace + +CXFA_FMParser::CXFA_FMParser(const WideStringView& wsFormcalc) + : m_error(false), m_parse_depth(0), m_max_parse_depth(kMaxParseDepth) { + m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc); + m_token = m_lexer->NextToken(); +} + +CXFA_FMParser::~CXFA_FMParser() {} + +std::unique_ptr<CXFA_FMFunctionDefinition> CXFA_FMParser::Parse() { + auto expressions = ParseTopExpression(); + if (HasError()) + return nullptr; + + std::vector<WideStringView> arguments; + return pdfium::MakeUnique<CXFA_FMFunctionDefinition>( + 1, true, L"", std::move(arguments), std::move(expressions)); +} + +bool CXFA_FMParser::NextToken() { + if (HasError()) + return false; + m_token = m_lexer->NextToken(); + while (!HasError() && m_token->m_type == TOKreserver) + m_token = m_lexer->NextToken(); + return !HasError(); +} + +bool CXFA_FMParser::CheckThenNext(XFA_FM_TOKEN op) { + if (HasError()) + return false; + + if (m_token->m_type != op) { + m_error = true; + return false; + } + return NextToken(); +} + +bool CXFA_FMParser::IncrementParseDepthAndCheck() { + return ++m_parse_depth < m_max_parse_depth; +} + +std::vector<std::unique_ptr<CXFA_FMExpression>> +CXFA_FMParser::ParseTopExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return std::vector<std::unique_ptr<CXFA_FMExpression>>(); + + std::unique_ptr<CXFA_FMExpression> expr; + std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; + while (!HasError()) { + if (m_token->m_type == TOKeof || m_token->m_type == TOKendfunc || + m_token->m_type == TOKendif || m_token->m_type == TOKelseif || + m_token->m_type == TOKelse || m_token->m_type == TOKreserver) { + return expressions; + } + + expr = m_token->m_type == TOKfunc ? ParseFunction() : ParseExpression(); + if (!expr) { + m_error = true; + break; + } + expressions.push_back(std::move(expr)); + } + return std::vector<std::unique_ptr<CXFA_FMExpression>>(); +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseFunction() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + WideStringView ident; + std::vector<WideStringView> arguments; + std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } else { + ident = m_token->m_string; + if (!NextToken()) + return nullptr; + } + if (!CheckThenNext(TOKlparen)) + return nullptr; + if (m_token->m_type == TOKrparen) { + if (!NextToken()) + return nullptr; + } else { + while (1) { + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + arguments.push_back(m_token->m_string); + if (!NextToken()) + return nullptr; + if (m_token->m_type == TOKcomma) { + if (!NextToken()) + return nullptr; + continue; + } + if (m_token->m_type == TOKrparen) { + if (!NextToken()) + return nullptr; + } else { + if (!CheckThenNext(TOKrparen)) + return nullptr; + } + break; + } + } + if (!CheckThenNext(TOKdo)) + return nullptr; + if (m_token->m_type == TOKendfunc) { + if (!NextToken()) + return nullptr; + } else { + expressions = ParseTopExpression(); + if (!expressions.size() || !CheckThenNext(TOKendfunc)) + return nullptr; + } + + return pdfium::MakeUnique<CXFA_FMFunctionDefinition>( + line, false, ident, std::move(arguments), std::move(expressions)); +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> expr; + uint32_t line = m_token->m_line_num; + switch (m_token->m_type) { + case TOKvar: + expr = ParseVarExpression(); + break; + case TOKnull: + case TOKnumber: + case TOKstring: + case TOKplus: + case TOKminus: + case TOKksnot: + case TOKidentifier: + case TOKlparen: + expr = ParseExpExpression(); + break; + case TOKif: + expr = ParseIfExpression(); + break; + case TOKwhile: + expr = ParseWhileExpression(); + break; + case TOKfor: + expr = ParseForExpression(); + break; + case TOKforeach: + expr = ParseForeachExpression(); + break; + case TOKdo: + expr = ParseDoExpression(); + break; + case TOKbreak: + expr = pdfium::MakeUnique<CXFA_FMBreakExpression>(line); + if (!NextToken()) + return nullptr; + break; + case TOKcontinue: + expr = pdfium::MakeUnique<CXFA_FMContinueExpression>(line); + if (!NextToken()) + return nullptr; + break; + default: + m_error = true; + return nullptr; + } + return expr; +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseVarExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + WideStringView ident; + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + + ident = m_token->m_string; + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> expr; + if (m_token->m_type == TOKassign) { + if (!NextToken()) + return nullptr; + + expr = ParseExpExpression(); + if (!expr) + return nullptr; + } + + return pdfium::MakeUnique<CXFA_FMVarExpression>(line, ident, std::move(expr)); +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseSimpleExpression() { + if (HasError()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression(); + if (!pExp1) + return nullptr; + int level = 1; + while (m_token->m_type == TOKassign) { + if (!NextToken()) + return nullptr; + std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression(); + if (!pExp2) + return nullptr; + if (level++ == kMaxAssignmentChainLength) { + m_error = true; + return nullptr; + } + pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>( + line, TOKassign, std::move(pExp1), std::move(pExp2)); + } + return pExp1; +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression(); + if (!pExp1) + return nullptr; + return pdfium::MakeUnique<CXFA_FMExpExpression>(line, std::move(pExp1)); +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseLogicalOrExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression(); + if (!e1) + return nullptr; + + for (;;) { + switch (m_token->m_type) { + case TOKor: + case TOKksor: { + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> e2( + ParseLogicalAndExpression()); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>( + line, TOKor, std::move(e1), std::move(e2)); + continue; + } + default: + break; + } + break; + } + return e1; +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseLogicalAndExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression(); + if (!e1) + return nullptr; + + for (;;) { + switch (m_token->m_type) { + case TOKand: + case TOKksand: { + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>( + line, TOKand, std::move(e1), std::move(e2)); + continue; + } + default: + break; + } + break; + } + return e1; +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseEqualityExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression(); + if (!e1) + return nullptr; + for (;;) { + std::unique_ptr<CXFA_FMSimpleExpression> e2; + switch (m_token->m_type) { + case TOKeq: + case TOKkseq: + if (!NextToken()) + return nullptr; + + e2 = ParseRelationalExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>( + line, TOKeq, std::move(e1), std::move(e2)); + continue; + case TOKne: + case TOKksne: + if (!NextToken()) + return nullptr; + + e2 = ParseRelationalExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>( + line, TOKne, std::move(e1), std::move(e2)); + continue; + default: + break; + } + break; + } + return e1; +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseRelationalExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAddtiveExpression(); + if (!e1) + return nullptr; + + for (;;) { + std::unique_ptr<CXFA_FMSimpleExpression> e2; + switch (m_token->m_type) { + case TOKlt: + case TOKkslt: + if (!NextToken()) + return nullptr; + + e2 = ParseAddtiveExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( + line, TOKlt, std::move(e1), std::move(e2)); + continue; + case TOKgt: + case TOKksgt: + if (!NextToken()) + return nullptr; + + e2 = ParseAddtiveExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( + line, TOKgt, std::move(e1), std::move(e2)); + continue; + case TOKle: + case TOKksle: + if (!NextToken()) + return nullptr; + + e2 = ParseAddtiveExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( + line, TOKle, std::move(e1), std::move(e2)); + continue; + case TOKge: + case TOKksge: + if (!NextToken()) + return nullptr; + + e2 = ParseAddtiveExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( + line, TOKge, std::move(e1), std::move(e2)); + continue; + default: + break; + } + break; + } + return e1; +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseAddtiveExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression(); + if (!e1) + return nullptr; + + for (;;) { + std::unique_ptr<CXFA_FMSimpleExpression> e2; + switch (m_token->m_type) { + case TOKplus: + if (!NextToken()) + return nullptr; + + e2 = ParseMultiplicativeExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>( + line, TOKplus, std::move(e1), std::move(e2)); + continue; + case TOKminus: + if (!NextToken()) + return nullptr; + + e2 = ParseMultiplicativeExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>( + line, TOKminus, std::move(e1), std::move(e2)); + continue; + default: + break; + } + break; + } + return e1; +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseMultiplicativeExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression(); + if (!e1) + return nullptr; + + for (;;) { + std::unique_ptr<CXFA_FMSimpleExpression> e2; + switch (m_token->m_type) { + case TOKmul: + if (!NextToken()) + return nullptr; + + e2 = ParseUnaryExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>( + line, TOKmul, std::move(e1), std::move(e2)); + continue; + case TOKdiv: + if (!NextToken()) + return nullptr; + + e2 = ParseUnaryExpression(); + if (!e2) + return nullptr; + + e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>( + line, TOKdiv, std::move(e1), std::move(e2)); + continue; + default: + break; + } + break; + } + return e1; +} + +std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseUnaryExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> expr; + uint32_t line = m_token->m_line_num; + switch (m_token->m_type) { + case TOKplus: + if (!NextToken()) + return nullptr; + + expr = ParseUnaryExpression(); + if (!expr) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMPosExpression>(line, std::move(expr)); + break; + case TOKminus: + if (!NextToken()) + return nullptr; + + expr = ParseUnaryExpression(); + if (!expr) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMNegExpression>(line, std::move(expr)); + break; + case TOKksnot: + if (!NextToken()) + return nullptr; + + expr = ParseUnaryExpression(); + if (!expr) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMNotExpression>(line, std::move(expr)); + break; + default: + expr = ParsePrimaryExpression(); + if (!expr) + return nullptr; + break; + } + return expr; +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParsePrimaryExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> expr; + uint32_t line = m_token->m_line_num; + switch (m_token->m_type) { + case TOKnumber: + expr = + pdfium::MakeUnique<CXFA_FMNumberExpression>(line, m_token->m_string); + if (!NextToken()) + return nullptr; + break; + case TOKstring: + expr = + pdfium::MakeUnique<CXFA_FMStringExpression>(line, m_token->m_string); + if (!NextToken()) + return nullptr; + break; + case TOKidentifier: { + WideStringView wsIdentifier(m_token->m_string); + if (!NextToken()) + return nullptr; + if (m_token->m_type == TOKlbracket) { + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); + if (!s) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + line, nullptr, TOKdot, wsIdentifier, std::move(s)); + if (!expr) + return nullptr; + if (!NextToken()) + return nullptr; + } else { + expr = + pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, wsIdentifier); + } + break; + } + case TOKif: + expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, + m_token->m_string); + if (!expr || !NextToken()) + return nullptr; + break; + case TOKnull: + expr = pdfium::MakeUnique<CXFA_FMNullExpression>(line); + if (!expr || !NextToken()) + return nullptr; + break; + case TOKlparen: + expr = ParseParenExpression(); + if (!expr) + return nullptr; + break; + default: + m_error = true; + return nullptr; + } + expr = ParsePostExpression(std::move(expr)); + if (!expr) + return nullptr; + return expr; +} + +std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParsePostExpression( + std::unique_ptr<CXFA_FMSimpleExpression> expr) { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + if (HasError()) + return nullptr; + + uint32_t line = m_token->m_line_num; + while (1) { + switch (m_token->m_type) { + case TOKlparen: { + if (!NextToken()) + return nullptr; + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions; + if (m_token->m_type != TOKrparen) { + while (m_token->m_type != TOKrparen) { + std::unique_ptr<CXFA_FMSimpleExpression> simple_expr = + ParseSimpleExpression(); + if (!simple_expr) + return nullptr; + + expressions.push_back(std::move(simple_expr)); + if (m_token->m_type == TOKcomma) { + if (!NextToken()) + return nullptr; + } else if (m_token->m_type == TOKeof || + m_token->m_type == TOKreserver) { + break; + } + } + if (m_token->m_type != TOKrparen) { + m_error = true; + return nullptr; + } + } + expr = pdfium::MakeUnique<CXFA_FMCallExpression>( + line, std::move(expr), std::move(expressions), false); + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKlbracket) + continue; + + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); + if (!s) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + line, std::move(expr), TOKcall, L"", std::move(s)); + break; + } + case TOKdot: { + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + WideStringView tempStr = m_token->m_string; + uint32_t tempLine = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type == TOKlparen) { + std::unique_ptr<CXFA_FMSimpleExpression> pExpCall; + if (!NextToken()) + return nullptr; + + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions; + if (m_token->m_type != TOKrparen) { + while (m_token->m_type != TOKrparen) { + std::unique_ptr<CXFA_FMSimpleExpression> exp = + ParseSimpleExpression(); + if (!exp) + return nullptr; + + expressions.push_back(std::move(exp)); + if (m_token->m_type == TOKcomma) { + if (!NextToken()) + return nullptr; + } else if (m_token->m_type == TOKeof || + m_token->m_type == TOKreserver) { + break; + } + } + if (m_token->m_type != TOKrparen) { + m_error = true; + return nullptr; + } + } + std::unique_ptr<CXFA_FMSimpleExpression> pIdentifier = + pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempLine, + tempStr); + pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>( + line, std::move(pIdentifier), std::move(expressions), true); + expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>( + line, std::move(expr), std::move(pExpCall)); + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKlbracket) + continue; + + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); + if (!s) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + line, std::move(expr), TOKcall, L"", std::move(s)); + } else if (m_token->m_type == TOKlbracket) { + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); + if (!s) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + tempLine, std::move(expr), TOKdot, tempStr, std::move(s)); + } else { + std::unique_ptr<CXFA_FMSimpleExpression> s = + pdfium::MakeUnique<CXFA_FMIndexExpression>( + tempLine, ACCESSOR_NO_INDEX, nullptr, false); + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + line, std::move(expr), TOKdot, tempStr, std::move(s)); + continue; + } + } break; + case TOKdotdot: { + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + WideStringView tempStr = m_token->m_string; + uint32_t tempLine = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type == TOKlbracket) { + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); + if (!s) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>( + tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s)); + } else { + std::unique_ptr<CXFA_FMSimpleExpression> s = + pdfium::MakeUnique<CXFA_FMIndexExpression>( + tempLine, ACCESSOR_NO_INDEX, nullptr, false); + expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>( + line, std::move(expr), TOKdotdot, tempStr, std::move(s)); + continue; + } + } break; + case TOKdotscream: { + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + WideStringView tempStr = m_token->m_string; + uint32_t tempLine = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKlbracket) { + std::unique_ptr<CXFA_FMSimpleExpression> s = + pdfium::MakeUnique<CXFA_FMIndexExpression>( + tempLine, ACCESSOR_NO_INDEX, nullptr, false); + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + line, std::move(expr), TOKdotscream, tempStr, std::move(s)); + continue; + } + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); + if (!s) + return nullptr; + + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s)); + break; + } + case TOKdotstar: { + std::unique_ptr<CXFA_FMSimpleExpression> s = + pdfium::MakeUnique<CXFA_FMIndexExpression>(line, ACCESSOR_NO_INDEX, + nullptr, false); + expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( + line, std::move(expr), TOKdotstar, L"*", std::move(s)); + break; + } + default: + return expr; + } + if (!NextToken()) + return nullptr; + } + return expr; +} + +std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseIndexExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> s; + XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX; + std::unique_ptr<CXFA_FMSimpleExpression> pExp; + if (m_token->m_type == TOKmul) { + pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex, + std::move(s), true); + if (!pExp || !NextToken()) + return nullptr; + if (m_token->m_type != TOKrbracket) { + m_error = true; + return nullptr; + } + return pExp; + } + if (m_token->m_type == TOKplus) { + accessorIndex = ACCESSOR_POSITIVE_INDEX; + if (!NextToken()) + return nullptr; + } else if (m_token->m_type == TOKminus) { + accessorIndex = ACCESSOR_NEGATIVE_INDEX; + if (!NextToken()) + return nullptr; + } + s = ParseSimpleExpression(); + if (!s) + return nullptr; + if (m_token->m_type != TOKrbracket) { + m_error = true; + return nullptr; + } + return pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex, + std::move(s), false); +} + +std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseParenExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + if (!CheckThenNext(TOKlparen)) + return nullptr; + + if (m_token->m_type == TOKrparen) { + m_error = true; + return nullptr; + } + + uint32_t line = m_token->m_line_num; + std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression(); + if (!pExp1) + return nullptr; + + int level = 1; + while (m_token->m_type == TOKassign) { + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression(); + if (!pExp2) + return nullptr; + if (level++ == kMaxAssignmentChainLength) { + m_error = true; + return nullptr; + } + + pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>( + line, TOKassign, std::move(pExp1), std::move(pExp2)); + } + if (!CheckThenNext(TOKrparen)) + return nullptr; + return pExp1; +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseBlockExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + if (HasError()) + return nullptr; + + uint32_t line = m_token->m_line_num; + std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; + while (1) { + std::unique_ptr<CXFA_FMExpression> expr; + switch (m_token->m_type) { + case TOKeof: + case TOKendif: + case TOKelseif: + case TOKelse: + case TOKendwhile: + case TOKendfor: + case TOKend: + case TOKendfunc: + case TOKreserver: + break; + case TOKfunc: + expr = ParseFunction(); + if (!expr) + return nullptr; + + expressions.push_back(std::move(expr)); + continue; + default: + expr = ParseExpression(); + if (!expr) + return nullptr; + + expressions.push_back(std::move(expr)); + continue; + } + break; + } + return pdfium::MakeUnique<CXFA_FMBlockExpression>(line, + std::move(expressions)); +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseIfExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + const wchar_t* pStartPos = m_lexer->GetPos(); + if (!NextToken() || !CheckThenNext(TOKlparen)) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> pExpression; + while (m_token->m_type != TOKrparen) { + pExpression = ParseSimpleExpression(); + if (!pExpression) + return nullptr; + if (m_token->m_type != TOKcomma) + break; + if (!NextToken()) + return nullptr; + } + if (!CheckThenNext(TOKrparen)) + return nullptr; + if (m_token->m_type != TOKthen) { + m_lexer->SetCurrentLine(line); + auto pNewToken = pdfium::MakeUnique<CXFA_FMToken>(line); + m_token = std::move(pNewToken); + m_token->m_type = TOKidentifier; + m_token->m_string = L"if"; + m_lexer->SetPos(pStartPos); + return ParseExpExpression(); + } + if (!CheckThenNext(TOKthen)) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> pIfExpression = ParseBlockExpression(); + if (!pIfExpression) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> pElseExpression; + switch (m_token->m_type) { + case TOKeof: + case TOKendif: + if (!CheckThenNext(TOKendif)) + return nullptr; + break; + case TOKif: + pElseExpression = ParseIfExpression(); + if (!pElseExpression || !CheckThenNext(TOKendif)) + return nullptr; + break; + case TOKelseif: + pElseExpression = ParseIfExpression(); + if (!pElseExpression) + return nullptr; + break; + case TOKelse: + if (!NextToken()) + return nullptr; + pElseExpression = ParseBlockExpression(); + if (!pElseExpression || !CheckThenNext(TOKendif)) + return nullptr; + break; + default: + m_error = true; + return nullptr; + } + return pdfium::MakeUnique<CXFA_FMIfExpression>(line, std::move(pExpression), + std::move(pIfExpression), + std::move(pElseExpression)); +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseWhileExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression(); + if (!pCondition || !CheckThenNext(TOKdo)) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> pExpression = ParseBlockExpression(); + if (!pExpression || !CheckThenNext(TOKendwhile)) + return nullptr; + return pdfium::MakeUnique<CXFA_FMWhileExpression>(line, std::move(pCondition), + std::move(pExpression)); +} + +std::unique_ptr<CXFA_FMSimpleExpression> +CXFA_FMParser::ParseSubassignmentInForExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + if (HasError()) + return nullptr; + + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + std::unique_ptr<CXFA_FMSimpleExpression> expr = ParseSimpleExpression(); + if (!expr) + return nullptr; + return expr; +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + WideStringView wsVariant; + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + + wsVariant = m_token->m_string; + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKassign) { + m_error = true; + return nullptr; + } + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> pAssignment = + ParseSimpleExpression(); + if (!pAssignment) + return nullptr; + + int32_t iDirection = 0; + if (m_token->m_type == TOKupto) { + iDirection = 1; + } else if (m_token->m_type == TOKdownto) { + iDirection = -1; + } else { + m_error = true; + return nullptr; + } + + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression(); + if (!pAccessor) + return nullptr; + + std::unique_ptr<CXFA_FMSimpleExpression> pStep; + if (m_token->m_type == TOKstep) { + if (!NextToken()) + return nullptr; + pStep = ParseSimpleExpression(); + if (!pStep) + return nullptr; + } + if (!CheckThenNext(TOKdo)) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> pList = ParseBlockExpression(); + if (!pList || !CheckThenNext(TOKendfor)) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> expr; + if (!expr) + return nullptr; + return pdfium::MakeUnique<CXFA_FMForExpression>( + line, wsVariant, std::move(pAssignment), std::move(pAccessor), iDirection, + std::move(pStep), std::move(pList)); +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForeachExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + if (HasError()) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> expr; + WideStringView wsIdentifier; + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pAccessors; + std::unique_ptr<CXFA_FMExpression> pList; + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + if (m_token->m_type != TOKidentifier) { + m_error = true; + return nullptr; + } + + wsIdentifier = m_token->m_string; + if (!NextToken() || !CheckThenNext(TOKin) || !CheckThenNext(TOKlparen)) + return nullptr; + if (m_token->m_type == TOKrparen) { + m_error = true; + return nullptr; + } + + while (m_token->m_type != TOKrparen) { + std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression(); + if (!s) + return nullptr; + + pAccessors.push_back(std::move(s)); + if (m_token->m_type != TOKcomma) + break; + if (!NextToken()) + return nullptr; + } + if (!CheckThenNext(TOKrparen) || !CheckThenNext(TOKdo)) + return nullptr; + + pList = ParseBlockExpression(); + if (!pList || !CheckThenNext(TOKendfor)) + return nullptr; + return pdfium::MakeUnique<CXFA_FMForeachExpression>( + line, wsIdentifier, std::move(pAccessors), std::move(pList)); +} + +std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseDoExpression() { + AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + + if (HasError()) + return nullptr; + + uint32_t line = m_token->m_line_num; + if (!NextToken()) + return nullptr; + + std::unique_ptr<CXFA_FMExpression> expr = ParseBlockExpression(); + if (!expr || !CheckThenNext(TOKend)) + return nullptr; + return pdfium::MakeUnique<CXFA_FMDoExpression>(line, std::move(expr)); +} + +bool CXFA_FMParser::HasError() const { + return m_error || m_token == nullptr; +} diff --git a/xfa/fxfa/fm2js/cxfa_fmparser.h b/xfa/fxfa/fm2js/cxfa_fmparser.h new file mode 100644 index 0000000000000000000000000000000000000000..c536838a3cafc8e6f7e8380f244d493a96e3660b --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmparser.h @@ -0,0 +1,66 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ +#define XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ + +#include <memory> +#include <vector> + +#include "xfa/fxfa/fm2js/cxfa_fmexpression.h" +#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" + +class CXFA_FMParser { + public: + explicit CXFA_FMParser(const WideStringView& wsFormcalc); + ~CXFA_FMParser(); + + std::unique_ptr<CXFA_FMFunctionDefinition> Parse(); + bool HasError() const; + + void SetMaxParseDepthForTest(unsigned long max_depth) { + m_max_parse_depth = max_depth; + } + + private: + bool NextToken(); + bool CheckThenNext(XFA_FM_TOKEN op); + bool IncrementParseDepthAndCheck(); + + std::vector<std::unique_ptr<CXFA_FMExpression>> ParseTopExpression(); + std::unique_ptr<CXFA_FMExpression> ParseFunction(); + std::unique_ptr<CXFA_FMExpression> ParseExpression(); + std::unique_ptr<CXFA_FMExpression> ParseVarExpression(); + std::unique_ptr<CXFA_FMExpression> ParseExpExpression(); + std::unique_ptr<CXFA_FMExpression> ParseBlockExpression(); + std::unique_ptr<CXFA_FMExpression> ParseIfExpression(); + std::unique_ptr<CXFA_FMExpression> ParseWhileExpression(); + std::unique_ptr<CXFA_FMExpression> ParseForExpression(); + std::unique_ptr<CXFA_FMExpression> ParseForeachExpression(); + std::unique_ptr<CXFA_FMExpression> ParseDoExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseParenExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseSimpleExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseSubassignmentInForExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseLogicalOrExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseLogicalAndExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseEqualityExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseRelationalExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseAddtiveExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseMultiplicativeExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParseUnaryExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParsePrimaryExpression(); + std::unique_ptr<CXFA_FMSimpleExpression> ParsePostExpression( + std::unique_ptr<CXFA_FMSimpleExpression> e); + std::unique_ptr<CXFA_FMSimpleExpression> ParseIndexExpression(); + + std::unique_ptr<CXFA_FMLexer> m_lexer; + std::unique_ptr<CXFA_FMToken> m_token; + bool m_error; + unsigned long m_parse_depth; + unsigned long m_max_parse_depth; +}; + +#endif // XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8582649fec82694a16166547760483832402f700 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp @@ -0,0 +1,131 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" + +#include <vector> + +#include "core/fxcrt/cfx_widetextbuf.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" + +TEST(CXFA_FMParserTest, Empty) { + auto parser = pdfium::MakeUnique<CXFA_FMParser>(L""); + std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse(); + ASSERT(ast != nullptr); + EXPECT_FALSE(parser->HasError()); + + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + // TODO(dsinclair): This is a little weird ..... + EXPECT_EQ(L"// comments only", buf.AsStringView()); +} + +TEST(CXFA_FMParserTest, CommentOnlyIsError) { + auto parser = pdfium::MakeUnique<CXFA_FMParser>(L"; Just comment"); + std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse(); + ASSERT(ast != nullptr); + // TODO(dsinclair): This isn't allowed per the spec. + EXPECT_FALSE(parser->HasError()); + // EXPECT_TRUE(parser->HasError()); + + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(L"// comments only", buf.AsStringView()); +} + +TEST(CXFA_FMParserTest, CommentThenValue) { + const wchar_t ret[] = + L"(\nfunction ()\n{\n" + L"var pfm_ret = null;\n" + L"pfm_ret = 12;\n" + L"return pfm_rt.get_val(pfm_ret);\n" + L"}\n).call(this);\n"; + + auto parser = pdfium::MakeUnique<CXFA_FMParser>(L"; Just comment\n12"); + std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse(); + ASSERT(ast != nullptr); + EXPECT_FALSE(parser->HasError()); + + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(ret, buf.AsStringView()); +} + +TEST(CXFA_FMParserTest, Parse) { + const wchar_t input[] = + L"$ = Avg (-3, 5, -6, 12, -13);\n" + L"$ = Avg (Table2..Row[*].Cell1);\n" + L"\n" + L"if ($ ne -1)then\n" + L" border.fill.color.value = \"255,64,64\";\n" + L"else\n" + L" border.fill.color.value = \"20,170,13\";\n" + L"endif\n" + L"\n" + L"$"; + + const wchar_t ret[] = + L"(\nfunction ()\n{\n" + L"var pfm_ret = null;\n" + L"if (pfm_rt.is_obj(this))\n{\n" + L"pfm_rt.asgn_val_op(this, pfm_rt.Avg(pfm_rt.neg_op(3), 5, " + L"pfm_rt.neg_op(6), 12, pfm_rt.neg_op(13)));\n" + L"}\n" + L"if (pfm_rt.is_obj(this))\n{\n" + L"pfm_rt.asgn_val_op(this, pfm_rt.Avg(pfm_rt.dot_acc(pfm_rt.dotdot_acc(" + L"Table2, \"Table2\", \"Row\", 1), \"\", \"Cell1\", 0, 0)));\n" + L"}\n" + L"if (pfm_rt.get_val(pfm_rt.neq_op(this, pfm_rt.neg_op(1))))\n{\n" + L"if (pfm_rt.is_obj(pfm_rt.dot_acc(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), \"\", " + L"\"value\", 0, 0)))\n{\n" + L"pfm_rt.asgn_val_op(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"pfm_rt.dot_acc(border, \"border\", \"fill\", 0, 0), \"\", " + L"\"color\", 0, 0), \"\", \"value\", 0, 0), \"255,64,64\");\n" + L"}\n" + L"}\nelse\n{\n" + L"if (pfm_rt.is_obj(pfm_rt.dot_acc(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), \"\", " + L"\"value\", 0, 0)))\n{\n" + L"pfm_rt.asgn_val_op(pfm_rt.dot_acc(pfm_rt.dot_acc(" + L"pfm_rt.dot_acc(border, \"border\", \"fill\", 0, 0), \"\", " + L"\"color\", 0, 0), \"\", \"value\", 0, 0), \"20,170,13\");\n" + L"}\n" + L"}\n" + L"pfm_ret = this;\n" + L"return pfm_rt.get_val(pfm_ret);\n" + L"}\n).call(this);\n"; + + auto parser = pdfium::MakeUnique<CXFA_FMParser>(input); + std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse(); + ASSERT(ast != nullptr); + EXPECT_FALSE(parser->HasError()); + + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(ret, buf.AsStringView()); +} + +TEST(CXFA_FMParserTest, MaxParseDepth) { + auto parser = pdfium::MakeUnique<CXFA_FMParser>(L"foo(bar[baz(fizz[0])])"); + parser->SetMaxParseDepthForTest(5); + EXPECT_EQ(nullptr, parser->Parse()); + EXPECT_TRUE(parser->HasError()); +} + +TEST(CFXA_FMParserTest, chromium752201) { + auto parser = pdfium::MakeUnique<CXFA_FMParser>( + L"fTep a\n" + L".#\n" + L"fo@ =[=l"); + EXPECT_EQ(nullptr, parser->Parse()); + EXPECT_TRUE(parser->HasError()); +} diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp new file mode 100644 index 0000000000000000000000000000000000000000..373ba916e974705a873e7cff465ed7bd59ff6863 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp @@ -0,0 +1,894 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h" + +#include <algorithm> +#include <iostream> +#include <utility> + +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/logging.h" +#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" + +namespace { + +// Indexed by XFA_FM_SimpleExpressionType +const wchar_t* const gs_lpStrExpFuncName[] = { + L"pfm_rt.asgn_val_op", L"pfm_rt.log_or_op", L"pfm_rt.log_and_op", + L"pfm_rt.eq_op", L"pfm_rt.neq_op", L"pfm_rt.lt_op", + L"pfm_rt.le_op", L"pfm_rt.gt_op", L"pfm_rt.ge_op", + L"pfm_rt.plus_op", L"pfm_rt.minus_op", L"pfm_rt.mul_op", + L"pfm_rt.div_op", L"pfm_rt.pos_op", L"pfm_rt.neg_op", + L"pfm_rt.log_not_op", L"pfm_rt.", L"pfm_rt.dot_acc", + L"pfm_rt.dotdot_acc", L"pfm_rt.concat_obj", L"pfm_rt.is_obj", + L"pfm_rt.is_ary", L"pfm_rt.get_val", L"pfm_rt.get_jsobj", + L"pfm_rt.var_filter", +}; + +const wchar_t* const g_BuiltInFuncs[] = { + L"Abs", L"Apr", L"At", L"Avg", + L"Ceil", L"Choose", L"Concat", L"Count", + L"Cterm", L"Date", L"Date2Num", L"DateFmt", + L"Decode", L"Encode", L"Eval", L"Exists", + L"Floor", L"Format", L"FV", L"Get", + L"HasValue", L"If", L"Ipmt", L"IsoDate2Num", + L"IsoTime2Num", L"Left", L"Len", L"LocalDateFmt", + L"LocalTimeFmt", L"Lower", L"Ltrim", L"Max", + L"Min", L"Mod", L"NPV", L"Num2Date", + L"Num2GMTime", L"Num2Time", L"Oneof", L"Parse", + L"Pmt", L"Post", L"PPmt", L"Put", + L"PV", L"Rate", L"Ref", L"Replace", + L"Right", L"Round", L"Rtrim", L"Space", + L"Str", L"Stuff", L"Substr", L"Sum", + L"Term", L"Time", L"Time2Num", L"TimeFmt", + L"UnitType", L"UnitValue", L"Upper", L"Uuid", + L"Within", L"WordNum", +}; + +const size_t g_BuiltInFuncsMaxLen = 12; + +struct XFA_FMSOMMethod { + const wchar_t* m_wsSomMethodName; + uint32_t m_dParameters; +}; + +const XFA_FMSOMMethod gs_FMSomMethods[] = { + {L"absPage", 0x01}, + {L"absPageInBatch", 0x01}, + {L"absPageSpan", 0x01}, + {L"append", 0x01}, + {L"clear", 0x01}, + {L"formNodes", 0x01}, + {L"h", 0x01}, + {L"insert", 0x03}, + {L"isRecordGroup", 0x01}, + {L"page", 0x01}, + {L"pageSpan", 0x01}, + {L"remove", 0x01}, + {L"saveFilteredXML", 0x01}, + {L"setElement", 0x01}, + {L"sheet", 0x01}, + {L"sheetInBatch", 0x01}, + {L"sign", 0x61}, + {L"verify", 0x0d}, + {L"w", 0x01}, + {L"x", 0x01}, + {L"y", 0x01}, +}; + +} // namespace + +WideStringView XFA_FM_EXPTypeToString( + XFA_FM_SimpleExpressionType simpleExpType) { + return gs_lpStrExpFuncName[simpleExpType]; +} + +CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op) + : m_line(line), m_op(op) {} + +bool CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +bool CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const { + return m_op; +} + +CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line) + : CXFA_FMSimpleExpression(line, TOKnull) {} + +bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"null"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line, + WideStringView wsNumber) + : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {} + +CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {} + +bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << m_wsNumber; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line, + WideStringView wsString) + : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {} + +CXFA_FMStringExpression::~CXFA_FMStringExpression() {} + +bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + WideString tempStr(m_wsString); + if (tempStr.GetLength() <= 2) { + javascript << tempStr; + return !CXFA_IsTooBig(javascript); + } + javascript.AppendChar(L'\"'); + for (size_t i = 1; i < tempStr.GetLength() - 1; i++) { + wchar_t oneChar = tempStr[i]; + switch (oneChar) { + case L'\"': + i++; + javascript << L"\\\""; + break; + case 0x0d: + break; + case 0x0a: + javascript << L"\\n"; + break; + default: + javascript.AppendChar(oneChar); + break; + } + } + javascript.AppendChar(L'\"'); + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression( + uint32_t line, + WideStringView wsIdentifier) + : CXFA_FMSimpleExpression(line, TOKidentifier), + m_wsIdentifier(wsIdentifier) {} + +CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {} + +bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + WideString tempStr(m_wsIdentifier); + if (tempStr == L"$") { + tempStr = L"this"; + } else if (tempStr == L"!") { + tempStr = L"xfa.datasets"; + } else if (tempStr == L"$data") { + tempStr = L"xfa.datasets.data"; + } else if (tempStr == L"$event") { + tempStr = L"xfa.event"; + } else if (tempStr == L"$form") { + tempStr = L"xfa.form"; + } else if (tempStr == L"$host") { + tempStr = L"xfa.host"; + } else if (tempStr == L"$layout") { + tempStr = L"xfa.layout"; + } else if (tempStr == L"$template") { + tempStr = L"xfa.template"; + } else if (tempStr[0] == L'!') { + tempStr = + EXCLAMATION_IN_IDENTIFIER + tempStr.Right(tempStr.GetLength() - 1); + } + javascript << tempStr; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMUnaryExpression::CXFA_FMUnaryExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp) + : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {} + +CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {} + +bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +CXFA_FMBinExpression::CXFA_FMBinExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMSimpleExpression(line, op), + m_pExp1(std::move(pExp1)), + m_pExp2(std::move(pExp2)) {} + +CXFA_FMBinExpression::~CXFA_FMBinExpression() {} + +bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); +} + +CXFA_FMAssignExpression::CXFA_FMAssignExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"if ("; + javascript << gs_lpStrExpFuncName[ISFMOBJECT]; + javascript << L"("; + CFX_WideTextBuf tempExp1; + if (!m_pExp1->ToJavaScript(tempExp1)) + return false; + javascript << tempExp1; + javascript << L"))\n{\n"; + javascript << gs_lpStrExpFuncName[ASSIGN]; + javascript << L"("; + javascript << tempExp1; + javascript << L", "; + + CFX_WideTextBuf tempExp2; + if (!m_pExp2->ToJavaScript(tempExp2)) + return false; + javascript << tempExp2; + javascript << L");\n}\n"; + if (m_pExp1->GetOperatorToken() == TOKidentifier && + tempExp1.AsStringView() != L"this") { + javascript << L"else\n{\n"; + javascript << tempExp1; + javascript << L" = "; + javascript << gs_lpStrExpFuncName[ASSIGN]; + javascript << L"("; + javascript << tempExp1; + javascript << L", "; + javascript << tempExp2; + javascript << L");\n}\n"; + } + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"if ("; + javascript << gs_lpStrExpFuncName[ISFMOBJECT]; + javascript << L"("; + CFX_WideTextBuf tempExp1; + if (!m_pExp1->ToJavaScript(tempExp1)) + return false; + javascript << tempExp1; + javascript << L"))\n{\n"; + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = "; + javascript << gs_lpStrExpFuncName[ASSIGN]; + javascript << L"("; + javascript << tempExp1; + javascript << L", "; + + CFX_WideTextBuf tempExp2; + if (!m_pExp2->ToJavaScript(tempExp2)) + return false; + javascript << tempExp2; + javascript << L");\n}\n"; + if (m_pExp1->GetOperatorToken() == TOKidentifier && + tempExp1.AsStringView() != L"this") { + javascript << L"else\n{\n"; + javascript << RUNTIMEFUNCTIONRETURNVALUE; + javascript << L" = "; + javascript << tempExp1; + javascript << L" = "; + javascript << gs_lpStrExpFuncName[ASSIGN]; + javascript << L"("; + javascript << tempExp1; + javascript << L", "; + javascript << tempExp2; + javascript << L");\n}\n"; + } + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[LOGICALOR]; + javascript << L"("; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[LOGICALAND]; + javascript << L"("; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMEqualityExpression::CXFA_FMEqualityExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + switch (m_op) { + case TOKeq: + case TOKkseq: + javascript << gs_lpStrExpFuncName[EQUALITY]; + break; + case TOKne: + case TOKksne: + javascript << gs_lpStrExpFuncName[NOTEQUALITY]; + break; + default: + NOTREACHED(); + break; + } + javascript << L"("; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMRelationalExpression::CXFA_FMRelationalExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + switch (m_op) { + case TOKlt: + case TOKkslt: + javascript << gs_lpStrExpFuncName[LESS]; + break; + case TOKgt: + case TOKksgt: + javascript << gs_lpStrExpFuncName[GREATER]; + break; + case TOKle: + case TOKksle: + javascript << gs_lpStrExpFuncName[LESSEQUAL]; + break; + case TOKge: + case TOKksge: + javascript << gs_lpStrExpFuncName[GREATEREQUAL]; + break; + default: + NOTREACHED(); + break; + } + javascript << L"("; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + switch (m_op) { + case TOKplus: + javascript << gs_lpStrExpFuncName[PLUS]; + break; + case TOKminus: + javascript << gs_lpStrExpFuncName[MINUS]; + break; + default: + NOTREACHED(); + break; + } + javascript << L"("; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2) + : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} + +bool CXFA_FMMultiplicativeExpression::ToJavaScript( + CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + switch (m_op) { + case TOKmul: + javascript << gs_lpStrExpFuncName[MULTIPLE]; + break; + case TOKdiv: + javascript << gs_lpStrExpFuncName[DIVIDE]; + break; + default: + NOTREACHED(); + break; + } + javascript << L"("; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMPosExpression::CXFA_FMPosExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp) + : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {} + +bool CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[POSITIVE]; + javascript << L"("; + if (!m_pExp->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMNegExpression::CXFA_FMNegExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp) + : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {} + +bool CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[NEGATIVE]; + javascript << L"("; + if (!m_pExp->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMNotExpression::CXFA_FMNotExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp) + : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {} + +bool CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[NOT]; + javascript << L"("; + if (!m_pExp->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMCallExpression::CXFA_FMCallExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp, + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments, + bool bIsSomMethod) + : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)), + m_bIsSomMethod(bIsSomMethod), + m_Arguments(std::move(pArguments)) {} + +CXFA_FMCallExpression::~CXFA_FMCallExpression() {} + +bool CXFA_FMCallExpression::IsBuiltInFunc(CFX_WideTextBuf* funcName) { + if (funcName->GetLength() > g_BuiltInFuncsMaxLen) + return false; + + auto cmpFunc = [](const wchar_t* iter, const WideString& val) -> bool { + return val.CompareNoCase(iter) > 0; + }; + WideString str = funcName->MakeString(); + const wchar_t* const* pMatchResult = std::lower_bound( + std::begin(g_BuiltInFuncs), std::end(g_BuiltInFuncs), str, cmpFunc); + if (pMatchResult != std::end(g_BuiltInFuncs) && + !str.CompareNoCase(*pMatchResult)) { + funcName->Clear(); + *funcName << *pMatchResult; + return true; + } + return false; +} + +uint32_t CXFA_FMCallExpression::IsMethodWithObjParam( + const WideString& methodName) { + auto cmpFunc = [](const XFA_FMSOMMethod iter, const WideString& val) { + return val.Compare(iter.m_wsSomMethodName) > 0; + }; + const XFA_FMSOMMethod* result = + std::lower_bound(std::begin(gs_FMSomMethods), std::end(gs_FMSomMethods), + methodName, cmpFunc); + if (result != std::end(gs_FMSomMethods) && + !methodName.Compare(result->m_wsSomMethodName)) { + return result->m_dParameters; + } + return 0; +} + +bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + CFX_WideTextBuf funcName; + if (!m_pExp->ToJavaScript(funcName)) + return false; + if (m_bIsSomMethod) { + javascript << funcName; + javascript << L"("; + uint32_t methodPara = IsMethodWithObjParam(funcName.MakeString()); + if (methodPara > 0) { + for (size_t i = 0; i < m_Arguments.size(); ++i) { + // Currently none of our expressions use objects for a parameter over + // the 6th. Make sure we don't overflow the shift when doing this + // check. If we ever need more the 32 object params we can revisit. + if (i < 32 && (methodPara & (0x01 << i)) > 0) { + javascript << gs_lpStrExpFuncName[GETFMJSOBJ]; + } else { + javascript << gs_lpStrExpFuncName[GETFMVALUE]; + } + javascript << L"("; + const auto& expr = m_Arguments[i]; + if (!expr->ToJavaScript(javascript)) + return false; + javascript << L")"; + if (i + 1 < m_Arguments.size()) { + javascript << L", "; + } + } + } else { + for (const auto& expr : m_Arguments) { + javascript << gs_lpStrExpFuncName[GETFMVALUE]; + javascript << L"("; + if (!expr->ToJavaScript(javascript)) + return false; + javascript << L")"; + if (expr != m_Arguments.back()) + javascript << L", "; + } + } + javascript << L")"; + } else { + bool isEvalFunc = false; + bool isExistsFunc = false; + if (IsBuiltInFunc(&funcName)) { + if (funcName.AsStringView() == L"Eval") { + isEvalFunc = true; + javascript << L"eval.call(this, "; + javascript << gs_lpStrExpFuncName[CALL]; + javascript << L"Translate"; + } else if (funcName.AsStringView() == L"Exists") { + isExistsFunc = true; + javascript << gs_lpStrExpFuncName[CALL]; + javascript << funcName; + } else { + javascript << gs_lpStrExpFuncName[CALL]; + javascript << funcName; + } + } else { + // If a function is not a SomMethod or a built-in then the input was + // invalid, so failing. The scanner/lexer should catch this, but currently + // doesn't. This failure will bubble up to the top-level and cause the + // transpile to fail. + return false; + } + javascript << L"("; + if (isExistsFunc) { + javascript << L"\n(\nfunction ()\n{\ntry\n{\n"; + if (!m_Arguments.empty()) { + const auto& expr = m_Arguments[0]; + javascript << L"return "; + if (!expr->ToJavaScript(javascript)) + return false; + javascript << L";\n}\n"; + } else { + javascript << L"return 0;\n}\n"; + } + javascript << L"catch(accessExceptions)\n"; + javascript << L"{\nreturn 0;\n}\n}\n).call(this)\n"; + } else { + for (const auto& expr : m_Arguments) { + if (!expr->ToJavaScript(javascript)) + return false; + if (expr != m_Arguments.back()) + javascript << L", "; + } + } + javascript << L")"; + if (isEvalFunc) { + javascript << L")"; + } + } + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, + XFA_FM_TOKEN op, + WideStringView wsIdentifier, + std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) + : CXFA_FMBinExpression(line, + op, + std::move(pAccessor), + std::move(pIndexExp)), + m_wsIdentifier(wsIdentifier) {} + +CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {} + +bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[DOT]; + javascript << L"("; + CFX_WideTextBuf tempExp1; + if (m_pExp1) { + if (!m_pExp1->ToJavaScript(tempExp1)) + return false; + javascript << tempExp1; + } else { + javascript << L"null"; + } + javascript << L", "; + javascript << L"\""; + + if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) + javascript << tempExp1; + javascript << L"\", "; + if (m_op == TOKdotscream) { + javascript << L"\"#"; + javascript << m_wsIdentifier; + javascript << L"\", "; + } else if (m_op == TOKdotstar) { + javascript << L"\"*\", "; + } else if (m_op == TOKcall) { + javascript << L"\"\", "; + } else { + javascript << L"\""; + javascript << m_wsIdentifier; + javascript << L"\", "; + } + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMIndexExpression::CXFA_FMIndexExpression( + uint32_t line, + XFA_FM_AccessorIndex accessorIndex, + std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp, + bool bIsStarIndex) + : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)), + m_accessorIndex(accessorIndex), + m_bIsStarIndex(bIsStarIndex) {} + +bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + switch (m_accessorIndex) { + case ACCESSOR_NO_INDEX: + javascript << L"0"; + break; + case ACCESSOR_NO_RELATIVEINDEX: + javascript << L"1"; + break; + case ACCESSOR_POSITIVE_INDEX: + javascript << L"2"; + break; + case ACCESSOR_NEGATIVE_INDEX: + javascript << L"3"; + break; + default: + javascript << L"0"; + } + if (!m_bIsStarIndex) { + javascript << L", "; + if (m_pExp) { + if (!m_pExp->ToJavaScript(javascript)) + return false; + } else { + javascript << L"0"; + } + } + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, + XFA_FM_TOKEN op, + WideStringView wsIdentifier, + std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) + : CXFA_FMBinExpression(line, + op, + std::move(pAccessor), + std::move(pIndexExp)), + m_wsIdentifier(wsIdentifier) {} + +CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {} + +bool CXFA_FMDotDotAccessorExpression::ToJavaScript( + CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << gs_lpStrExpFuncName[DOTDOT]; + javascript << L"("; + CFX_WideTextBuf tempExp1; + if (!m_pExp1->ToJavaScript(tempExp1)) + return false; + javascript << tempExp1; + javascript << L", "; + javascript << L"\""; + + if (m_pExp1->GetOperatorToken() == TOKidentifier) + javascript << tempExp1; + javascript << L"\", "; + javascript << L"\""; + javascript << m_wsIdentifier; + javascript << L"\", "; + if (!m_pExp2->ToJavaScript(javascript)) + return false; + javascript << L")"; + return !CXFA_IsTooBig(javascript); +} + +CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pCallExp) + : CXFA_FMBinExpression(line, + TOKdot, + std::move(pAccessorExp1), + std::move(pCallExp)) {} + +bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { + CXFA_FMToJavaScriptDepth depthManager; + if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) + return false; + + javascript << L"(\nfunction ()\n{\n"; + javascript << L"var method_return_value = null;\n"; + javascript << L"var accessor_object = "; + if (!m_pExp1->ToJavaScript(javascript)) + return false; + javascript << L";\n"; + javascript << L"if ("; + javascript << gs_lpStrExpFuncName[ISFMARRAY]; + javascript << L"(accessor_object))\n{\n"; + javascript << L"for(var index = accessor_object.length - 1; index > 1; " + L"index--)\n{\n"; + javascript << L"method_return_value = accessor_object[index]."; + + CFX_WideTextBuf tempExp2; + if (!m_pExp2->ToJavaScript(tempExp2)) + return false; + javascript << tempExp2; + javascript << L";\n}\n}\n"; + javascript << L"else\n{\nmethod_return_value = accessor_object."; + javascript << tempExp2; + javascript << L";\n}\n"; + javascript << L"return method_return_value;\n"; + javascript << L"}\n).call(this)"; + return !CXFA_IsTooBig(javascript); +} + +bool CXFA_IsTooBig(const CFX_WideTextBuf& javascript) { + return javascript.GetSize() >= 256 * 1024 * 1024; +} diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h new file mode 100644 index 0000000000000000000000000000000000000000..440b154d3d574672d9b81b13317e3283e09ca9ab --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h @@ -0,0 +1,308 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_FM2JS_CXFA_FMSIMPLEEXPRESSION_H_ +#define XFA_FXFA_FM2JS_CXFA_FMSIMPLEEXPRESSION_H_ + +#include <memory> +#include <vector> + +#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" + +#define RUNTIMEFUNCTIONRETURNVALUE L"pfm_ret" +#define EXCLAMATION_IN_IDENTIFIER L"pfm__excl__" + +enum XFA_FM_SimpleExpressionType { + ASSIGN, + LOGICALOR, + LOGICALAND, + EQUALITY, + NOTEQUALITY, + LESS, + LESSEQUAL, + GREATER, + GREATEREQUAL, + PLUS, + MINUS, + MULTIPLE, + DIVIDE, + POSITIVE, + NEGATIVE, + NOT, + CALL, + DOT, + DOTDOT, + CONCATFMOBJECT, + ISFMOBJECT, + ISFMARRAY, + GETFMVALUE, + GETFMJSOBJ, + VARFILTER +}; + +class CFX_WideTextBuf; + +WideStringView XFA_FM_EXPTypeToString( + XFA_FM_SimpleExpressionType simpleExpType); + +enum XFA_FM_AccessorIndex { + ACCESSOR_NO_INDEX, + ACCESSOR_NO_RELATIVEINDEX, + ACCESSOR_POSITIVE_INDEX, + ACCESSOR_NEGATIVE_INDEX +}; + +class CXFA_FMSimpleExpression { + public: + CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op); + virtual ~CXFA_FMSimpleExpression() {} + virtual bool ToJavaScript(CFX_WideTextBuf& javascript); + virtual bool ToImpliedReturnJS(CFX_WideTextBuf& javascript); + + XFA_FM_TOKEN GetOperatorToken() const; + + protected: + uint32_t m_line; + const XFA_FM_TOKEN m_op; +}; + +class CXFA_FMNullExpression : public CXFA_FMSimpleExpression { + public: + explicit CXFA_FMNullExpression(uint32_t line); + ~CXFA_FMNullExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMNumberExpression : public CXFA_FMSimpleExpression { + public: + CXFA_FMNumberExpression(uint32_t line, WideStringView wsNumber); + ~CXFA_FMNumberExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + WideStringView m_wsNumber; +}; + +class CXFA_FMStringExpression : public CXFA_FMSimpleExpression { + public: + CXFA_FMStringExpression(uint32_t line, WideStringView wsString); + ~CXFA_FMStringExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + WideStringView m_wsString; +}; + +class CXFA_FMIdentifierExpression : public CXFA_FMSimpleExpression { + public: + CXFA_FMIdentifierExpression(uint32_t line, WideStringView wsIdentifier); + ~CXFA_FMIdentifierExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + WideStringView m_wsIdentifier; +}; + +class CXFA_FMUnaryExpression : public CXFA_FMSimpleExpression { + public: + CXFA_FMUnaryExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp); + ~CXFA_FMUnaryExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + protected: + std::unique_ptr<CXFA_FMSimpleExpression> m_pExp; +}; + +class CXFA_FMBinExpression : public CXFA_FMSimpleExpression { + public: + CXFA_FMBinExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMBinExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + protected: + std::unique_ptr<CXFA_FMSimpleExpression> m_pExp1; + std::unique_ptr<CXFA_FMSimpleExpression> m_pExp2; +}; + +class CXFA_FMAssignExpression : public CXFA_FMBinExpression { + public: + CXFA_FMAssignExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMAssignExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + bool ToImpliedReturnJS(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMLogicalOrExpression : public CXFA_FMBinExpression { + public: + CXFA_FMLogicalOrExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMLogicalOrExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMLogicalAndExpression : public CXFA_FMBinExpression { + public: + CXFA_FMLogicalAndExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMLogicalAndExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMEqualityExpression : public CXFA_FMBinExpression { + public: + CXFA_FMEqualityExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMEqualityExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMRelationalExpression : public CXFA_FMBinExpression { + public: + CXFA_FMRelationalExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMRelationalExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMAdditiveExpression : public CXFA_FMBinExpression { + public: + CXFA_FMAdditiveExpression(uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMAdditiveExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMMultiplicativeExpression : public CXFA_FMBinExpression { + public: + CXFA_FMMultiplicativeExpression( + uint32_t line, + XFA_FM_TOKEN op, + std::unique_ptr<CXFA_FMSimpleExpression> pExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pExp2); + ~CXFA_FMMultiplicativeExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMPosExpression : public CXFA_FMUnaryExpression { + public: + CXFA_FMPosExpression(uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp); + ~CXFA_FMPosExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMNegExpression : public CXFA_FMUnaryExpression { + public: + CXFA_FMNegExpression(uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp); + ~CXFA_FMNegExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMNotExpression : public CXFA_FMUnaryExpression { + public: + CXFA_FMNotExpression(uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp); + ~CXFA_FMNotExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +class CXFA_FMCallExpression : public CXFA_FMUnaryExpression { + public: + CXFA_FMCallExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pExp, + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments, + bool bIsSomMethod); + ~CXFA_FMCallExpression() override; + + bool IsBuiltInFunc(CFX_WideTextBuf* funcName); + uint32_t IsMethodWithObjParam(const WideString& methodName); + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + bool m_bIsSomMethod; + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> m_Arguments; +}; + +class CXFA_FMDotAccessorExpression : public CXFA_FMBinExpression { + public: + CXFA_FMDotAccessorExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, + XFA_FM_TOKEN op, + WideStringView wsIdentifier, + std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp); + ~CXFA_FMDotAccessorExpression() override; + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + WideStringView m_wsIdentifier; +}; + +class CXFA_FMIndexExpression : public CXFA_FMUnaryExpression { + public: + CXFA_FMIndexExpression(uint32_t line, + XFA_FM_AccessorIndex accessorIndex, + std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp, + bool bIsStarIndex); + ~CXFA_FMIndexExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + XFA_FM_AccessorIndex m_accessorIndex; + bool m_bIsStarIndex; +}; + +class CXFA_FMDotDotAccessorExpression : public CXFA_FMBinExpression { + public: + CXFA_FMDotDotAccessorExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, + XFA_FM_TOKEN op, + WideStringView wsIdentifier, + std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp); + ~CXFA_FMDotDotAccessorExpression() override; + + bool ToJavaScript(CFX_WideTextBuf& javascript) override; + + private: + WideStringView m_wsIdentifier; +}; + +class CXFA_FMMethodCallExpression : public CXFA_FMBinExpression { + public: + CXFA_FMMethodCallExpression( + uint32_t line, + std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1, + std::unique_ptr<CXFA_FMSimpleExpression> pCallExp); + ~CXFA_FMMethodCallExpression() override {} + bool ToJavaScript(CFX_WideTextBuf& javascript) override; +}; + +bool CXFA_IsTooBig(const CFX_WideTextBuf& javascript); + +#endif // XFA_FXFA_FM2JS_CXFA_FMSIMPLEEXPRESSION_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96ccb71ca981373f91bf9e950cdcd89af576c5eb --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp @@ -0,0 +1,84 @@ +// Copyright 2016 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. + +#include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h" + +#include <memory> +#include <utility> + +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/fm2js/cxfa_fmlexer.h" +#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" + +TEST(FMCallExpressionTest, more_than_32_arguments) { + // Use sign as it has 3 object parameters at positions 0, 5, and 6. + auto exp = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(0, L"sign"); + + std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> args; + for (size_t i = 0; i < 50; i++) + args.push_back(pdfium::MakeUnique<CXFA_FMSimpleExpression>(0, TOKnan)); + + CXFA_FMToJavaScriptDepth::Reset(); + CXFA_FMCallExpression callExp(0, std::move(exp), std::move(args), true); + CFX_WideTextBuf js; + callExp.ToJavaScript(js); + + // Generate the result javascript string. + WideString result = L"sign("; + for (size_t i = 0; i < 50; i++) { + if (i > 0) + result += L", "; + + result += L"pfm_rt.get_"; + // Object positions for sign() method. + if (i == 0 || i == 5 || i == 6) + result += L"jsobj()"; + else + result += L"val()"; + } + result += L")"; + + EXPECT_EQ(result.AsStringView(), js.AsStringView()); +} + +TEST(FMStringExpressionTest, Empty) { + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf accumulator; + CXFA_FMStringExpression(1, WideStringView()).ToJavaScript(accumulator); + EXPECT_EQ(L"", accumulator.AsStringView()); +} + +TEST(FMStringExpressionTest, Short) { + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf accumulator; + CXFA_FMStringExpression(1, L"a").ToJavaScript(accumulator); + EXPECT_EQ(L"a", accumulator.AsStringView()); +} + +TEST(FMStringExpressionTest, Medium) { + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf accumulator; + CXFA_FMStringExpression(1, L".abcd.").ToJavaScript(accumulator); + EXPECT_EQ(L"\"abcd\"", accumulator.AsStringView()); +} + +TEST(FMStringExpressionTest, Long) { + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf accumulator; + std::vector<WideStringView::UnsignedType> vec(140000, L'A'); + CXFA_FMStringExpression(1, WideStringView(vec)).ToJavaScript(accumulator); + EXPECT_EQ(140000u, accumulator.GetLength()); +} + +TEST(FMStringExpressionTest, Quoted) { + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf accumulator; + CXFA_FMStringExpression(1, L".Simon says \"\"run\"\".") + .ToJavaScript(accumulator); + EXPECT_EQ(L"\"Simon says \\\"run\\\"\"", accumulator.AsStringView()); +} diff --git a/xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.cpp b/xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6312ba6b3d30e61d101e1ed65addf292b35ff374 --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.cpp @@ -0,0 +1,21 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" + +namespace { + +// Arbitarily picked by looking at how deep a translation got before hitting +// the getting fuzzer memory limits. Should be larger then |kMaxParseDepth| in +// cxfa_fmparser.cpp. +const unsigned int kMaxDepth = 5000; + +} // namespace + +unsigned long CXFA_FMToJavaScriptDepth::depth_ = 0; +unsigned long CXFA_FMToJavaScriptDepth::max_depth_ = kMaxDepth; + +void CXFA_FMToJavaScriptDepth::Reset() { + depth_ = 0; +} diff --git a/xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h b/xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h new file mode 100644 index 0000000000000000000000000000000000000000..14f87a68f5b579fd6b47e1049546b73fee711a6d --- /dev/null +++ b/xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h @@ -0,0 +1,22 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XFA_FXFA_FM2JS_CXFA_FMTOJAVASCRIPTDEPTH_H_ +#define XFA_FXFA_FM2JS_CXFA_FMTOJAVASCRIPTDEPTH_H_ + +class CXFA_FMToJavaScriptDepth { + public: + CXFA_FMToJavaScriptDepth() { depth_++; } + ~CXFA_FMToJavaScriptDepth() { depth_--; } + + bool IsWithinMaxDepth() const { return depth_ <= max_depth_; } + + static void Reset(); + + private: + static unsigned long depth_; + static unsigned long max_depth_; +}; + +#endif // XFA_FXFA_FM2JS_CXFA_FMTOJAVASCRIPTDEPTH_H_ diff --git a/xfa/fxfa/fm2js/xfa_error.cpp b/xfa/fxfa/fm2js/xfa_error.cpp deleted file mode 100644 index 020d9bc5091acc0e1d8e83f9d292987485578667..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_error.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_error.h" - -const FX_WCHAR kFMErrUnsupportedChar[] = L"unsupported char '%c'"; -const FX_WCHAR kFMErrBadSuffixNumber[] = L"bad suffix on number"; -const FX_WCHAR kFMErrExpectedIdentifier[] = - L"expected identifier instead of '%s'"; -const FX_WCHAR kFMErrExpectedToken[] = L"expected '%s' instead of '%s'"; -const FX_WCHAR kFMErrExpectedEndIf[] = L"expected 'endif' instead of '%s'"; -const FX_WCHAR kFMErrUnexpectedExpression[] = L"unexpected expression '%s'"; -const FX_WCHAR kFMErrExpectedNonEmptyExpression[] = - L"expected non-empty expression"; diff --git a/xfa/fxfa/fm2js/xfa_error.h b/xfa/fxfa/fm2js/xfa_error.h deleted file mode 100644 index 5e3fbbe1babbf52f76fa397813b1505cd76ad7f0..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_error.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_ERROR_H_ -#define XFA_FXFA_FM2JS_XFA_ERROR_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" - -extern const FX_WCHAR kFMErrUnsupportedChar[]; -extern const FX_WCHAR kFMErrBadSuffixNumber[]; -extern const FX_WCHAR kFMErrExpectedIdentifier[]; -extern const FX_WCHAR kFMErrExpectedToken[]; -extern const FX_WCHAR kFMErrExpectedEndIf[]; -extern const FX_WCHAR kFMErrUnexpectedExpression[]; -extern const FX_WCHAR kFMErrExpectedNonEmptyExpression[]; - -class CXFA_FMErrorInfo { - public: - CXFA_FMErrorInfo() : linenum(0) {} - ~CXFA_FMErrorInfo() {} - uint32_t linenum; - CFX_WideString message; -}; - -#endif // XFA_FXFA_FM2JS_XFA_ERROR_H_ diff --git a/xfa/fxfa/fm2js/xfa_expression.cpp b/xfa/fxfa/fm2js/xfa_expression.cpp deleted file mode 100644 index 32db6d24df07bb014991a0872c0bfb26b2d1e114..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_expression.cpp +++ /dev/null @@ -1,596 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_expression.h" - -#include <utility> - -#include "core/fxcrt/fx_basic.h" - -namespace { - -const FX_WCHAR RUNTIMEBLOCKTEMPARRAY[] = - L"foxit_xfa_formcalc_runtime_block_temp_array"; - -const FX_WCHAR RUNTIMEBLOCKTEMPARRAYINDEX[] = - L"foxit_xfa_formcalc_runtime_block_temp_array_index"; - -} // namespace - -CXFA_FMExpression::CXFA_FMExpression(uint32_t line) - : m_type(XFA_FM_EXPTYPE_UNKNOWN), m_line(line) {} - -CXFA_FMExpression::CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type) - : m_type(type), m_line(line) {} - -void CXFA_FMExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} - -void CXFA_FMExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {} - -CXFA_FMFunctionDefinition::CXFA_FMFunctionDefinition( - uint32_t line, - bool isGlobal, - const CFX_WideStringC& wsName, - std::vector<CFX_WideStringC>&& arguments, - std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_FUNC), - m_wsName(wsName), - m_pArguments(std::move(arguments)), - m_pExpressions(std::move(expressions)), - m_isGlobal(isGlobal) {} - -CXFA_FMFunctionDefinition::~CXFA_FMFunctionDefinition() {} - -void CXFA_FMFunctionDefinition::ToJavaScript(CFX_WideTextBuf& javascript) { - if (m_isGlobal && m_pExpressions.empty()) { - javascript << L"// comments only"; - return; - } - if (m_isGlobal) { - javascript << L"(\n"; - } - javascript << L"function "; - if (m_wsName.GetAt(0) == L'!') { - CFX_WideString tempName = EXCLAMATION_IN_IDENTIFIER + m_wsName.Mid(1); - javascript << tempName; - } else { - javascript << m_wsName; - } - javascript << L"("; - bool bNeedComma = false; - for (const auto& identifier : m_pArguments) { - if (bNeedComma) - javascript << L", "; - if (identifier.GetAt(0) == L'!') { - CFX_WideString tempIdentifier = - EXCLAMATION_IN_IDENTIFIER + identifier.Mid(1); - javascript << tempIdentifier; - } else { - javascript << identifier; - } - bNeedComma = true; - } - javascript << L")\n{\n"; - javascript << L"var "; - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = null;\n"; - for (const auto& expr : m_pExpressions) { - if (expr == m_pExpressions.back()) - expr->ToImpliedReturnJS(javascript); - else - expr->ToJavaScript(javascript); - } - javascript << L"return "; - if (m_isGlobal) { - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L")"; - } else { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - } - javascript << L";\n}\n"; - if (m_isGlobal) { - javascript << L").call(this);\n"; - } -} - -void CXFA_FMFunctionDefinition::ToImpliedReturnJS(CFX_WideTextBuf&) {} - -CXFA_FMVarExpression::CXFA_FMVarExpression( - uint32_t line, - const CFX_WideStringC& wsName, - std::unique_ptr<CXFA_FMExpression> pInit) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_VAR), - m_wsName(wsName), - m_pInit(std::move(pInit)) {} - -CXFA_FMVarExpression::~CXFA_FMVarExpression() {} - -void CXFA_FMVarExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"var "; - CFX_WideString tempName(m_wsName); - if (m_wsName.GetAt(0) == L'!') { - tempName = EXCLAMATION_IN_IDENTIFIER + m_wsName.Mid(1); - } - javascript << tempName; - javascript << L" = "; - if (m_pInit) { - m_pInit->ToJavaScript(javascript); - javascript << tempName; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(VARFILTER); - javascript << L"("; - javascript << tempName; - javascript << L");\n"; - } else { - javascript << L"\"\";\n"; - } -} - -void CXFA_FMVarExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << L"var "; - CFX_WideString tempName(m_wsName); - if (m_wsName.GetAt(0) == L'!') { - tempName = EXCLAMATION_IN_IDENTIFIER + m_wsName.Mid(1); - } - javascript << tempName; - javascript << L" = "; - if (m_pInit) { - m_pInit->ToJavaScript(javascript); - javascript << tempName; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(VARFILTER); - javascript << L"("; - javascript << tempName; - javascript << L");\n"; - } else { - javascript << L"\"\";\n"; - } - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = "; - javascript << tempName; - javascript << L";\n"; -} - -CXFA_FMExpExpression::CXFA_FMExpExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExpression) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_EXP), - m_pExpression(std::move(pExpression)) {} - -CXFA_FMExpExpression::~CXFA_FMExpExpression() {} - -void CXFA_FMExpExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - if (m_pExpression->GetOperatorToken() == TOKassign) { - m_pExpression->ToJavaScript(javascript); - } else { - m_pExpression->ToJavaScript(javascript); - javascript << L";\n"; - } -} - -void CXFA_FMExpExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - if (m_pExpression->GetOperatorToken() == TOKassign) { - m_pExpression->ToImpliedReturnJS(javascript); - } else { - if (m_pExpression->GetOperatorToken() == TOKstar || - m_pExpression->GetOperatorToken() == TOKdotstar || - m_pExpression->GetOperatorToken() == TOKdotscream || - m_pExpression->GetOperatorToken() == TOKdotdot || - m_pExpression->GetOperatorToken() == TOKdot) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pExpression->ToJavaScript(javascript); - javascript << L");\n"; - } else { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = "; - m_pExpression->ToJavaScript(javascript); - javascript << L";\n"; - } - } -} - -CXFA_FMBlockExpression::CXFA_FMBlockExpression( - uint32_t line, - std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BLOCK), - m_ExpressionList(std::move(pExpressionList)) {} - -CXFA_FMBlockExpression::~CXFA_FMBlockExpression() {} - -void CXFA_FMBlockExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"{\n"; - for (const auto& expr : m_ExpressionList) - expr->ToJavaScript(javascript); - javascript << L"}\n"; -} - -void CXFA_FMBlockExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << L"{\n"; - for (const auto& expr : m_ExpressionList) { - if (expr == m_ExpressionList.back()) - expr->ToImpliedReturnJS(javascript); - else - expr->ToJavaScript(javascript); - } - javascript << L"}\n"; -} - -CXFA_FMDoExpression::CXFA_FMDoExpression( - uint32_t line, - std::unique_ptr<CXFA_FMExpression> pList) - : CXFA_FMExpression(line), m_pList(std::move(pList)) {} - -CXFA_FMDoExpression::~CXFA_FMDoExpression() {} - -void CXFA_FMDoExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - m_pList->ToJavaScript(javascript); -} - -void CXFA_FMDoExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - m_pList->ToImpliedReturnJS(javascript); -} - -CXFA_FMIfExpression::CXFA_FMIfExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExpression, - std::unique_ptr<CXFA_FMExpression> pIfExpression, - std::unique_ptr<CXFA_FMExpression> pElseExpression) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_IF), - m_pExpression(std::move(pExpression)), - m_pIfExpression(std::move(pIfExpression)), - m_pElseExpression(std::move(pElseExpression)) {} - -CXFA_FMIfExpression::~CXFA_FMIfExpression() {} - -void CXFA_FMIfExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"if ("; - if (m_pExpression) { - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pExpression->ToJavaScript(javascript); - javascript << L")"; - } - javascript << L")\n"; - if (m_pIfExpression) { - m_pIfExpression->ToJavaScript(javascript); - } - if (m_pElseExpression) { - if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) { - javascript << L"else\n"; - javascript << L"{\n"; - m_pElseExpression->ToJavaScript(javascript); - javascript << L"}\n"; - } else { - javascript << L"else\n"; - m_pElseExpression->ToJavaScript(javascript); - } - } -} - -void CXFA_FMIfExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"if ("; - if (m_pExpression) { - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pExpression->ToJavaScript(javascript); - javascript << L")"; - } - javascript << L")\n"; - if (m_pIfExpression) { - m_pIfExpression->ToImpliedReturnJS(javascript); - } - if (m_pElseExpression) { - if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) { - javascript << L"else\n"; - javascript << L"{\n"; - m_pElseExpression->ToImpliedReturnJS(javascript); - javascript << L"}\n"; - } else { - javascript << L"else\n"; - m_pElseExpression->ToImpliedReturnJS(javascript); - } - } -} - -CXFA_FMLoopExpression::~CXFA_FMLoopExpression() {} - -void CXFA_FMLoopExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} - -void CXFA_FMLoopExpression::ToImpliedReturnJS(CFX_WideTextBuf&) {} - -CXFA_FMWhileExpression::CXFA_FMWhileExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pCondition, - std::unique_ptr<CXFA_FMExpression> pExpression) - : CXFA_FMLoopExpression(line), - m_pCondition(std::move(pCondition)), - m_pExpression(std::move(pExpression)) {} - -CXFA_FMWhileExpression::~CXFA_FMWhileExpression() {} - -void CXFA_FMWhileExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"while ("; - m_pCondition->ToJavaScript(javascript); - javascript << L")\n"; - m_pExpression->ToJavaScript(javascript); -} - -void CXFA_FMWhileExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"while ("; - m_pCondition->ToJavaScript(javascript); - javascript << L")\n"; - m_pExpression->ToImpliedReturnJS(javascript); -} - -CXFA_FMBreakExpression::CXFA_FMBreakExpression(uint32_t line) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BREAK) {} - -CXFA_FMBreakExpression::~CXFA_FMBreakExpression() {} - -void CXFA_FMBreakExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"break;\n"; -} - -void CXFA_FMBreakExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"break;\n"; -} - -CXFA_FMContinueExpression::CXFA_FMContinueExpression(uint32_t line) - : CXFA_FMExpression(line, XFA_FM_EXPTYPE_CONTINUE) {} - -CXFA_FMContinueExpression::~CXFA_FMContinueExpression() {} - -void CXFA_FMContinueExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"continue;\n"; -} - -void CXFA_FMContinueExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"continue;\n"; -} - -CXFA_FMForExpression::CXFA_FMForExpression( - uint32_t line, - const CFX_WideStringC& wsVariant, - std::unique_ptr<CXFA_FMSimpleExpression> pAssignment, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, - int32_t iDirection, - std::unique_ptr<CXFA_FMSimpleExpression> pStep, - std::unique_ptr<CXFA_FMExpression> pList) - : CXFA_FMLoopExpression(line), - m_wsVariant(wsVariant), - m_pAssignment(std::move(pAssignment)), - m_pAccessor(std::move(pAccessor)), - m_iDirection(iDirection), - m_pStep(std::move(pStep)), - m_pList(std::move(pList)) {} - -CXFA_FMForExpression::~CXFA_FMForExpression() {} - -void CXFA_FMForExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"{\nvar "; - CFX_WideString tempVariant; - if (m_wsVariant.GetAt(0) == L'!') { - tempVariant = EXCLAMATION_IN_IDENTIFIER + m_wsVariant.Mid(1); - javascript << tempVariant; - } else { - tempVariant = m_wsVariant; - javascript << m_wsVariant; - } - javascript << L" = null;\n"; - javascript << L"for ("; - javascript << tempVariant; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pAssignment->ToJavaScript(javascript); - javascript << L"); "; - javascript << tempVariant; - if (m_iDirection == 1) { - javascript << L" <= "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pAccessor->ToJavaScript(javascript); - javascript << L"); "; - javascript << tempVariant; - javascript << L" += "; - } else { - javascript << L" >= "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pAccessor->ToJavaScript(javascript); - javascript << L"); "; - javascript << tempVariant; - javascript << L" -= "; - } - if (m_pStep) { - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pStep->ToJavaScript(javascript); - javascript << L")"; - } else { - javascript << L"1"; - } - javascript << L")\n"; - m_pList->ToJavaScript(javascript); - javascript << L"}\n"; -} - -void CXFA_FMForExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"{\nvar "; - CFX_WideString tempVariant; - if (m_wsVariant.GetAt(0) == L'!') { - tempVariant = EXCLAMATION_IN_IDENTIFIER + m_wsVariant.Mid(1); - javascript << tempVariant; - } else { - tempVariant = m_wsVariant; - javascript << m_wsVariant; - } - javascript << L" = null;\n"; - javascript << L"for ("; - javascript << tempVariant; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pAssignment->ToJavaScript(javascript); - javascript << L"); "; - javascript << tempVariant; - if (m_iDirection == 1) { - javascript << L" <= "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pAccessor->ToJavaScript(javascript); - javascript << L"); "; - javascript << tempVariant; - javascript << L" += "; - } else { - javascript << L" >= "; - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pAccessor->ToJavaScript(javascript); - javascript << L"); "; - javascript << tempVariant; - javascript << L" -= "; - } - if (m_pStep) { - javascript << XFA_FM_EXPTypeToString(GETFMVALUE); - javascript << L"("; - m_pStep->ToJavaScript(javascript); - javascript << L")"; - } else { - javascript << L"1"; - } - javascript << L")\n"; - m_pList->ToImpliedReturnJS(javascript); - javascript << L"}\n"; -} - -CXFA_FMForeachExpression::CXFA_FMForeachExpression( - uint32_t line, - const CFX_WideStringC& wsIdentifier, - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pAccessors, - std::unique_ptr<CXFA_FMExpression> pList) - : CXFA_FMLoopExpression(line), - m_wsIdentifier(wsIdentifier), - m_pAccessors(std::move(pAccessors)), - m_pList(std::move(pList)) {} - -CXFA_FMForeachExpression::~CXFA_FMForeachExpression() {} - -void CXFA_FMForeachExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"{\n"; - javascript << L"var "; - if (m_wsIdentifier.GetAt(0) == L'!') { - CFX_WideString tempIdentifier = - EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1); - javascript << tempIdentifier; - } else { - javascript << m_wsIdentifier; - } - javascript << L" = null;\n"; - javascript << L"var "; - javascript << RUNTIMEBLOCKTEMPARRAY; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT); - javascript << L"("; - - for (const auto& expr : m_pAccessors) { - expr->ToJavaScript(javascript); - if (expr != m_pAccessors.back()) - javascript << L", "; - } - javascript << L");\n"; - javascript << L"var "; - javascript << RUNTIMEBLOCKTEMPARRAYINDEX; - javascript << (L" = 0;\n"); - javascript << L"while("; - javascript << RUNTIMEBLOCKTEMPARRAYINDEX; - javascript << L" < "; - javascript << RUNTIMEBLOCKTEMPARRAY; - javascript << L".length)\n{\n"; - if (m_wsIdentifier.GetAt(0) == L'!') { - CFX_WideString tempIdentifier = - EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1); - javascript << tempIdentifier; - } else { - javascript << m_wsIdentifier; - } - javascript << L" = "; - javascript << RUNTIMEBLOCKTEMPARRAY; - javascript << L"["; - javascript << RUNTIMEBLOCKTEMPARRAYINDEX; - javascript << L"++];\n"; - m_pList->ToJavaScript(javascript); - javascript << L"}\n"; - javascript << L"}\n"; -} - -void CXFA_FMForeachExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = 0;\n"; - javascript << L"{\n"; - javascript << L"var "; - if (m_wsIdentifier.GetAt(0) == L'!') { - CFX_WideString tempIdentifier = - EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1); - javascript << tempIdentifier; - } else { - javascript << m_wsIdentifier; - } - javascript << L" = null;\n"; - javascript << L"var "; - javascript << RUNTIMEBLOCKTEMPARRAY; - javascript << L" = "; - javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT); - javascript << L"("; - for (const auto& expr : m_pAccessors) { - expr->ToJavaScript(javascript); - if (expr != m_pAccessors.back()) - javascript << L", "; - } - javascript << L");\n"; - javascript << L"var "; - javascript << RUNTIMEBLOCKTEMPARRAYINDEX; - javascript << L" = 0;\n"; - javascript << L"while("; - javascript << RUNTIMEBLOCKTEMPARRAYINDEX; - javascript << L" < "; - javascript << RUNTIMEBLOCKTEMPARRAY; - javascript << L".length)\n{\n"; - if (m_wsIdentifier.GetAt(0) == L'!') { - CFX_WideString tempIdentifier = - EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1); - javascript << tempIdentifier; - } else { - javascript << m_wsIdentifier; - } - javascript << L" = "; - javascript << RUNTIMEBLOCKTEMPARRAY; - javascript << L"["; - javascript << RUNTIMEBLOCKTEMPARRAYINDEX; - javascript << L"++];\n"; - m_pList->ToImpliedReturnJS(javascript); - javascript << L"}\n"; - javascript << L"}\n"; -} diff --git a/xfa/fxfa/fm2js/xfa_expression.h b/xfa/fxfa/fm2js/xfa_expression.h deleted file mode 100644 index 6b55ea581552fab3e5f207b6954274db90ce49e5..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_expression.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_EXPRESSION_H_ -#define XFA_FXFA_FM2JS_XFA_EXPRESSION_H_ - -#include <memory> -#include <vector> - -#include "xfa/fxfa/fm2js/xfa_simpleexpression.h" - -enum XFA_FM_EXPTYPE { - XFA_FM_EXPTYPE_UNKNOWN, - XFA_FM_EXPTYPE_FUNC, - XFA_FM_EXPTYPE_VAR, - XFA_FM_EXPTYPE_EXP, - XFA_FM_EXPTYPE_BLOCK, - XFA_FM_EXPTYPE_IF, - XFA_FM_EXPTYPE_BREAK, - XFA_FM_EXPTYPE_CONTINUE, -}; - -class CXFA_FMExpression { - public: - explicit CXFA_FMExpression(uint32_t line); - CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type); - virtual ~CXFA_FMExpression() {} - virtual void ToJavaScript(CFX_WideTextBuf& javascript); - virtual void ToImpliedReturnJS(CFX_WideTextBuf&); - uint32_t GetLine() { return m_line; } - XFA_FM_EXPTYPE GetExpType() const { return m_type; } - - protected: - XFA_FM_EXPTYPE m_type; - uint32_t m_line; -}; - -class CXFA_FMFunctionDefinition : public CXFA_FMExpression { - public: - // Takes ownership of |arguments| and |expressions|. - CXFA_FMFunctionDefinition( - uint32_t line, - bool isGlobal, - const CFX_WideStringC& wsName, - std::vector<CFX_WideStringC>&& arguments, - std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions); - ~CXFA_FMFunctionDefinition() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - CFX_WideStringC m_wsName; - std::vector<CFX_WideStringC> m_pArguments; - std::vector<std::unique_ptr<CXFA_FMExpression>> m_pExpressions; - bool m_isGlobal; -}; - -class CXFA_FMVarExpression : public CXFA_FMExpression { - public: - CXFA_FMVarExpression(uint32_t line, - const CFX_WideStringC& wsName, - std::unique_ptr<CXFA_FMExpression> pInit); - ~CXFA_FMVarExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - CFX_WideStringC m_wsName; - std::unique_ptr<CXFA_FMExpression> m_pInit; -}; - -class CXFA_FMExpExpression : public CXFA_FMExpression { - public: - CXFA_FMExpExpression(uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExpression); - ~CXFA_FMExpExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - std::unique_ptr<CXFA_FMSimpleExpression> m_pExpression; -}; - -class CXFA_FMBlockExpression : public CXFA_FMExpression { - public: - CXFA_FMBlockExpression( - uint32_t line, - std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList); - ~CXFA_FMBlockExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - std::vector<std::unique_ptr<CXFA_FMExpression>> m_ExpressionList; -}; - -class CXFA_FMDoExpression : public CXFA_FMExpression { - public: - CXFA_FMDoExpression(uint32_t line, std::unique_ptr<CXFA_FMExpression> pList); - ~CXFA_FMDoExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - std::unique_ptr<CXFA_FMExpression> m_pList; -}; - -class CXFA_FMIfExpression : public CXFA_FMExpression { - public: - CXFA_FMIfExpression(uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExpression, - std::unique_ptr<CXFA_FMExpression> pIfExpression, - std::unique_ptr<CXFA_FMExpression> pElseExpression); - ~CXFA_FMIfExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - std::unique_ptr<CXFA_FMSimpleExpression> m_pExpression; - std::unique_ptr<CXFA_FMExpression> m_pIfExpression; - std::unique_ptr<CXFA_FMExpression> m_pElseExpression; -}; - -class CXFA_FMLoopExpression : public CXFA_FMExpression { - public: - explicit CXFA_FMLoopExpression(uint32_t line) : CXFA_FMExpression(line) {} - ~CXFA_FMLoopExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; -}; - -class CXFA_FMWhileExpression : public CXFA_FMLoopExpression { - public: - CXFA_FMWhileExpression(uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pCodition, - std::unique_ptr<CXFA_FMExpression> pExpression); - ~CXFA_FMWhileExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - std::unique_ptr<CXFA_FMSimpleExpression> m_pCondition; - std::unique_ptr<CXFA_FMExpression> m_pExpression; -}; - -class CXFA_FMBreakExpression : public CXFA_FMExpression { - public: - explicit CXFA_FMBreakExpression(uint32_t line); - ~CXFA_FMBreakExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; -}; - -class CXFA_FMContinueExpression : public CXFA_FMExpression { - public: - explicit CXFA_FMContinueExpression(uint32_t line); - ~CXFA_FMContinueExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; -}; - -class CXFA_FMForExpression : public CXFA_FMLoopExpression { - public: - CXFA_FMForExpression(uint32_t line, - const CFX_WideStringC& wsVariant, - std::unique_ptr<CXFA_FMSimpleExpression> pAssignment, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, - int32_t iDirection, - std::unique_ptr<CXFA_FMSimpleExpression> pStep, - std::unique_ptr<CXFA_FMExpression> pList); - ~CXFA_FMForExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - CFX_WideStringC m_wsVariant; - std::unique_ptr<CXFA_FMSimpleExpression> m_pAssignment; - std::unique_ptr<CXFA_FMSimpleExpression> m_pAccessor; - int32_t m_iDirection; - std::unique_ptr<CXFA_FMSimpleExpression> m_pStep; - std::unique_ptr<CXFA_FMExpression> m_pList; -}; - -class CXFA_FMForeachExpression : public CXFA_FMLoopExpression { - public: - // Takes ownership of |pAccessors|. - CXFA_FMForeachExpression( - uint32_t line, - const CFX_WideStringC& wsIdentifier, - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pAccessors, - std::unique_ptr<CXFA_FMExpression> pList); - ~CXFA_FMForeachExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf&) override; - - private: - CFX_WideStringC m_wsIdentifier; - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> m_pAccessors; - std::unique_ptr<CXFA_FMExpression> m_pList; -}; - -#endif // XFA_FXFA_FM2JS_XFA_EXPRESSION_H_ diff --git a/xfa/fxfa/fm2js/xfa_fm2jscontext.cpp b/xfa/fxfa/fm2js/xfa_fm2jscontext.cpp deleted file mode 100644 index e8cb2d0279a2c3237d3f092267d678aa6b01a7bb..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_fm2jscontext.cpp +++ /dev/null @@ -1,6421 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_fm2jscontext.h" - -#include <time.h> - -#include <algorithm> - -#include "core/fxcrt/fx_ext.h" -#include "fxjs/cfxjse_arguments.h" -#include "fxjs/cfxjse_class.h" -#include "fxjs/cfxjse_value.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fgas/localization/fgas_locale.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/fm2js/xfa_program.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localevalue.h" - -namespace { - -const double kFinancialPrecision = 0.00000001; - -struct XFA_FMHtmlReserveCode { - uint32_t m_uCode; - const FX_WCHAR* m_htmlReserve; -}; - -struct XFA_FMHtmlHashedReserveCode { - uint32_t m_uHash; - uint32_t m_uCode; -}; - -const XFA_FMHtmlHashedReserveCode reservesForDecode[] = { - {0x00018b62, /*L"Mu",*/ 924}, {0x00019083, /*L"Nu",*/ 925}, - {0x00019ab9, /*L"Pi",*/ 928}, {0x0001c3c1, /*L"Xi",*/ 926}, - {0x000210ac, /*L"ge",*/ 8805}, {0x000210bb, /*L"gt",*/ 62}, - {0x00022a51, /*L"le",*/ 8804}, {0x00022a60, /*L"lt",*/ 60}, - {0x00022f82, /*L"mu",*/ 956}, {0x00023493, /*L"ne",*/ 8800}, - {0x00023497, /*L"ni",*/ 8715}, {0x000234a3, /*L"nu",*/ 957}, - {0x000239c1, /*L"or",*/ 8744}, {0x00023ed9, /*L"pi",*/ 960}, - {0x000267e1, /*L"xi",*/ 958}, {0x00c41789, /*L"lceil",*/ 8968}, - {0x00eef34f, /*L"thetasym",*/ 977}, {0x012d7ead, /*L"lcirc",*/ 206}, - {0x01637b56, /*L"agrave",*/ 224}, {0x020856da, /*L"crarr",*/ 8629}, - {0x022188c3, /*L"gamma",*/ 947}, {0x033586d3, /*L"nbsp",*/ 160}, - {0x04f4c358, /*L"nsub",*/ 8836}, {0x0581466a, /*L"dagger",*/ 8224}, - {0x06b1f790, /*L"oelig",*/ 339}, {0x06e490d4, /*L"Chi",*/ 935}, - {0x0718c6a1, /*L"ETH",*/ 208}, {0x07196ada, /*L"Eta",*/ 919}, - {0x07f667ca, /*L"Ugrave",*/ 217}, {0x083a8a21, /*L"Phi",*/ 934}, - {0x083ac28c, /*L"Psi",*/ 936}, {0x086f26a9, /*L"Rho",*/ 929}, - {0x089b5b51, /*L"aring",*/ 229}, {0x08a39f4a, /*L"Tau",*/ 932}, - {0x08b6188b, /*L"THORN",*/ 222}, {0x09ce792a, /*L"icirc",*/ 238}, - {0x09f9d61e, /*L"amp",*/ 38}, {0x09f9db33, /*L"and",*/ 8743}, - {0x09f9db36, /*L"ang",*/ 8736}, {0x0a2e3514, /*L"cap",*/ 8745}, - {0x0a2e58f4, /*L"chi",*/ 967}, {0x0a2e9ba8, /*L"cup",*/ 8746}, - {0x0a4897d0, /*L"deg",*/ 176}, {0x0a6332fa, /*L"eta",*/ 951}, - {0x0a633301, /*L"eth",*/ 240}, {0x0acc4d4b, /*L"int",*/ 8747}, - {0x0b1b3d35, /*L"loz",*/ 9674}, {0x0b1b4c8b, /*L"lrm",*/ 8206}, - {0x0b4fd9b1, /*L"not",*/ 172}, {0x0b845241, /*L"phi",*/ 966}, - {0x0b84576f, /*L"piv",*/ 982}, {0x0b848aac, /*L"psi",*/ 968}, - {0x0bb8df5e, /*L"reg",*/ 174}, {0x0bb8eec9, /*L"rho",*/ 961}, - {0x0bb9034b, /*L"rlm",*/ 8207}, {0x0bd33d14, /*L"shy",*/ 173}, - {0x0bd34229, /*L"sim",*/ 8764}, {0x0bd37faa, /*L"sub",*/ 8834}, - {0x0bd37fb5, /*L"sum",*/ 8721}, {0x0bd37fb8, /*L"sup",*/ 8835}, - {0x0bed676a, /*L"tau",*/ 964}, {0x0c07f32e, /*L"uml",*/ 168}, - {0x0c71032c, /*L"yen",*/ 165}, {0x0c7f2889, /*L"szlig",*/ 223}, - {0x0c8badbb, /*L"zwj",*/ 8205}, {0x10ba4dba, /*L"Egrave",*/ 200}, - {0x10f1ea24, /*L"para",*/ 182}, {0x10f1ea37, /*L"part",*/ 8706}, - {0x115b2337, /*L"perp",*/ 8869}, {0x12b10d15, /*L"prod",*/ 8719}, - {0x12b10d21, /*L"prop",*/ 8733}, {0x12dfa9f4, /*L"rfloor",*/ 8971}, - {0x12eb4736, /*L"Agrave",*/ 192}, {0x12fff2b7, /*L"pund",*/ 163}, - {0x13fda9f2, /*L"tilde",*/ 732}, {0x1417fd62, /*L"times",*/ 215}, - {0x154fc726, /*L"ecirc",*/ 234}, {0x165aa451, /*L"sigma",*/ 963}, - {0x1709124a, /*L"Dagger",*/ 8225}, {0x192f78d5, /*L"iexcl",*/ 161}, - {0x1b7ed8d7, /*L"rArr",*/ 8658}, {0x1ec88c68, /*L"rang",*/ 9002}, - {0x1ec8a0f7, /*L"rarr",*/ 8594}, {0x1eda07f3, /*L"atilde",*/ 227}, - {0x1f3182c4, /*L"real",*/ 8476}, {0x1fc34f8b, /*L"yacute",*/ 253}, - {0x20d11522, /*L"acirc",*/ 226}, {0x21933a9b, /*L"rsaquo",*/ 8250}, - {0x21f44907, /*L"uacute",*/ 250}, {0x220cca72, /*L"acute",*/ 180}, - {0x242cded1, /*L"alefsym",*/ 8501}, {0x2655c66a, /*L"delta",*/ 948}, - {0x269e4b4d, /*L"exist",*/ 8707}, {0x273379fa, /*L"micro",*/ 181}, - {0x27a37440, /*L"forall",*/ 8704}, {0x2854e62c, /*L"minus",*/ 8722}, - {0x28636f81, /*L"cedil",*/ 184}, {0x2887357b, /*L"iacute",*/ 237}, - {0x2994d5ff, /*L"frac12",*/ 189}, {0x2994d601, /*L"frac14",*/ 188}, - {0x2994e043, /*L"frac34",*/ 190}, {0x2a1feb41, /*L"lambda",*/ 955}, - {0x2ab215f3, /*L"apos",*/ 39}, {0x2ab82ef7, /*L"eacute",*/ 233}, - {0x2b3592ef, /*L"auml",*/ 228}, {0x2ce92873, /*L"aacute",*/ 225}, - {0x2daff48a, /*L"oslash",*/ 248}, {0x2ef68882, /*L"aelig",*/ 230}, - {0x3061d3d3, /*L"Atilde",*/ 195}, {0x314b1b6b, /*L"Yacute",*/ 221}, - {0x337c14e7, /*L"Uacute",*/ 218}, {0x37676aca, /*L"cent",*/ 162}, - {0x37d0b841, /*L"circ",*/ 710}, {0x386e7947, /*L"cong",*/ 8773}, - {0x386e839b, /*L"copy",*/ 169}, {0x3a0e225a, /*L"Epsilon",*/ 917}, - {0x3ba7b721, /*L"Lambda",*/ 923}, {0x3bd9abe6, /*L"Alpha",*/ 913}, - {0x3c3ffad7, /*L"Eacute",*/ 201}, {0x3cfaf69f, /*L"brvbar",*/ 166}, - {0x3d54a489, /*L"omega",*/ 969}, {0x3e70f453, /*L"Aacute",*/ 193}, - {0x3f37c06a, /*L"Oslash",*/ 216}, {0x40e1b34e, /*L"diams",*/ 9830}, - {0x416596df, /*L"plusmn",*/ 177}, {0x4354ff16, /*L"Ucirc",*/ 219}, - {0x454fce6a, /*L"Upsilon",*/ 933}, {0x4610ad35, /*L"emsp",*/ 8195}, - {0x462afb76, /*L"ensp",*/ 8194}, {0x46e30073, /*L"euml",*/ 235}, - {0x46e31a1b, /*L"euro",*/ 8364}, {0x46f2eada, /*L"lowast",*/ 8727}, - {0x4dca26cf, /*L"Auml",*/ 196}, {0x4e2d6083, /*L"image",*/ 8465}, - {0x4f964ee8, /*L"notin",*/ 8713}, {0x50917a7a, /*L"epsilon",*/ 949}, - {0x52f9a4cd, /*L"Kappa",*/ 922}, {0x5496f410, /*L"Ocirc",*/ 212}, - {0x568cbf34, /*L"zeta",*/ 950}, {0x57badd20, /*L"ntilde",*/ 241}, - {0x58662109, /*L"zwnj",*/ 8204}, {0x5b39870f, /*L"empty",*/ 8709}, - {0x5bd3268a, /*L"upsilon",*/ 965}, {0x5e2bf8a3, /*L"Gamma",*/ 915}, - {0x5f73c13a, /*L"rsquo",*/ 8217}, {0x61f2bc4d, /*L"iota",*/ 953}, - {0x625bbcf3, /*L"isin",*/ 8712}, {0x62906df7, /*L"iuml",*/ 239}, - {0x64a5cb31, /*L"Aring",*/ 197}, {0x66f25c4a, /*L"sbquo",*/ 8218}, - {0x6851ab60, /*L"spades",*/ 9824}, {0x6942a900, /*L"Ntilde",*/ 209}, - {0x69779453, /*L"Euml",*/ 203}, {0x6cda6e23, /*L"current",*/ 164}, - {0x70b5b634, /*L"lsquo",*/ 8216}, {0x715a3706, /*L"Ecirc",*/ 202}, - {0x71e8bf8d, /*L"tdquo",*/ 8221}, {0x72651431, /*L"Sigma",*/ 931}, - {0x7569813b, /*L"iquest",*/ 191}, {0x776a436a, /*L"equiv",*/ 8801}, - {0x79215314, /*L"Zeta",*/ 918}, {0x79b81224, /*L"ograve",*/ 242}, - {0x7c2f8b23, /*L"macr",*/ 175}, {0x7cdb8502, /*L"Acirc",*/ 194}, - {0x8185c62e, /*L"ndash",*/ 8211}, {0x8260364a, /*L"Delta",*/ 916}, - {0x846619ad, /*L"mdash",*/ 8212}, {0x8550fb50, /*L"OElig",*/ 338}, - {0x88eb5b85, /*L"ldquo",*/ 8220}, {0x8b3fde04, /*L"Ograve",*/ 210}, - {0x8bc5794b, /*L"ordf",*/ 170}, {0x8bc57952, /*L"ordm",*/ 186}, - {0x8c14923d, /*L"ouml",*/ 246}, {0x8c5a7cd6, /*L"theta",*/ 952}, - {0x8d61812b, /*L"thorn",*/ 254}, {0x912b95aa, /*L"asymp",*/ 8776}, - {0x947faf81, /*L"middot",*/ 183}, {0x9629202e, /*L"lfloor",*/ 8970}, - {0x972e9ec1, /*L"otilde",*/ 245}, {0x9748f231, /*L"otimes",*/ 8855}, - {0x995f1469, /*L"Omega",*/ 937}, {0x99eb5349, /*L"quot",*/ 34}, - {0x9aeb639e, /*L"hellip",*/ 8230}, {0xa0ae2f86, /*L"Scaron",*/ 352}, - {0xa4dcb0d5, /*L"lsaquo",*/ 8249}, {0xa53dbf41, /*L"oacute",*/ 243}, - {0xa5ae9e7b, /*L"bdquo",*/ 8222}, {0xa602d7ba, /*L"sdot",*/ 8901}, - {0xa61ce86f, /*L"sect",*/ 167}, {0xa6e4c3d7, /*L"sigmaf",*/ 962}, - {0xa7c1c74f, /*L"sube",*/ 8838}, {0xa7c20ee9, /*L"sup1",*/ 185}, - {0xa7c20eea, /*L"sup2",*/ 178}, {0xa7c20eeb, /*L"sup3",*/ 179}, - {0xa7c20f1d, /*L"supe",*/ 8839}, {0xa8b66aa1, /*L"Otilde",*/ 213}, - {0xad958c42, /*L"AElig",*/ 198}, {0xaea9261d, /*L"Ouml",*/ 214}, - {0xb040eafa, /*L"uArr",*/ 8657}, {0xb07c2e1c, /*L"beta",*/ 946}, - {0xb220e92f, /*L"bull",*/ 8226}, {0xb22750c4, /*L"ccedil",*/ 231}, - {0xb38ab31a, /*L"uarr",*/ 8593}, {0xb598b683, /*L"uuml",*/ 252}, - {0xb6c58b21, /*L"Oacute",*/ 211}, {0xb6d2a617, /*L"oline",*/ 8254}, - {0xba9fd989, /*L"dArr",*/ 8659}, {0xbb5ccd41, /*L"lgrave",*/ 204}, - {0xbd39b44c, /*L"weierp",*/ 8472}, {0xbde9a1a9, /*L"darr",*/ 8595}, - {0xc027e329, /*L"permil",*/ 8240}, {0xc2451389, /*L"upsih",*/ 978}, - {0xc3af1ca4, /*L"Ccedil",*/ 199}, {0xcd164249, /*L"fnof",*/ 402}, - {0xcf6c8467, /*L"hearts",*/ 9829}, {0xd1228390, /*L"trade",*/ 8482}, - {0xd1462407, /*L"yuml",*/ 255}, {0xd2cf2253, /*L"oplus",*/ 8853}, - {0xd310c1fc, /*L"Beta",*/ 914}, {0xd59c4d74, /*L"infin",*/ 8734}, - {0xd64d470d, /*L"hArr",*/ 8660}, {0xd67d9c75, /*L"divide",*/ 247}, - {0xd698dd37, /*L"Omicron",*/ 927}, {0xd82d4a63, /*L"Uuml",*/ 220}, - {0xd9970f2d, /*L"harr",*/ 8596}, {0xda91fd99, /*L"clubs",*/ 9827}, - {0xdbe5bdcc, /*L"there4",*/ 8756}, {0xdd7671bd, /*L"prime",*/ 8242}, - {0xdfcf3c06, /*L"alpha",*/ 945}, {0xe0213063, /*L"saron",*/ 353}, - {0xe1911d83, /*L"radic",*/ 8730}, {0xe2e75468, /*L"raquo",*/ 187}, - {0xe6e27a5e, /*L"lacute",*/ 205}, {0xe74a8f36, /*L"ucirc",*/ 251}, - {0xe864ecb6, /*L"Theta",*/ 920}, {0xecddde5e, /*L"nabla",*/ 8711}, - {0xed1c3557, /*L"omicron",*/ 959}, {0xef82228f, /*L"rceil",*/ 8969}, - {0xf1fab491, /*L"lArr",*/ 8656}, {0xf3dab7e7, /*L"Yuml",*/ 376}, - {0xf4294962, /*L"laquo",*/ 171}, {0xf5446822, /*L"lang",*/ 9001}, - {0xf5447cb1, /*L"larr",*/ 8592}, {0xf66e9bea, /*L"ugrave",*/ 249}, - {0xf6b4ce70, /*L"lota",*/ 921}, {0xf6ef34ed, /*L"kappa",*/ 954}, - {0xf72a3a56, /*L"thinsp",*/ 8201}, {0xf752801a, /*L"luml",*/ 207}, - {0xf88c8430, /*L"ocirc",*/ 244}, {0xf9676178, /*L"frasl",*/ 8260}, - {0xfd01885e, /*L"igrave",*/ 236}, {0xff3281da, /*L"egrave",*/ 232}, -}; - -const XFA_FMHtmlReserveCode reservesForEncode[] = { - {34, L"quot"}, {38, L"amp"}, {39, L"apos"}, - {60, L"lt"}, {62, L"gt"}, {160, L"nbsp"}, - {161, L"iexcl"}, {162, L"cent"}, {163, L"pund"}, - {164, L"current"}, {165, L"yen"}, {166, L"brvbar"}, - {167, L"sect"}, {168, L"uml"}, {169, L"copy"}, - {170, L"ordf"}, {171, L"laquo"}, {172, L"not"}, - {173, L"shy"}, {174, L"reg"}, {175, L"macr"}, - {176, L"deg"}, {177, L"plusmn"}, {178, L"sup2"}, - {179, L"sup3"}, {180, L"acute"}, {181, L"micro"}, - {182, L"para"}, {183, L"middot"}, {184, L"cedil"}, - {185, L"sup1"}, {186, L"ordm"}, {187, L"raquo"}, - {188, L"frac14"}, {189, L"frac12"}, {190, L"frac34"}, - {191, L"iquest"}, {192, L"Agrave"}, {193, L"Aacute"}, - {194, L"Acirc"}, {195, L"Atilde"}, {196, L"Auml"}, - {197, L"Aring"}, {198, L"AElig"}, {199, L"Ccedil"}, - {200, L"Egrave"}, {201, L"Eacute"}, {202, L"Ecirc"}, - {203, L"Euml"}, {204, L"lgrave"}, {205, L"lacute"}, - {206, L"lcirc"}, {207, L"luml"}, {208, L"ETH"}, - {209, L"Ntilde"}, {210, L"Ograve"}, {211, L"Oacute"}, - {212, L"Ocirc"}, {213, L"Otilde"}, {214, L"Ouml"}, - {215, L"times"}, {216, L"Oslash"}, {217, L"Ugrave"}, - {218, L"Uacute"}, {219, L"Ucirc"}, {220, L"Uuml"}, - {221, L"Yacute"}, {222, L"THORN"}, {223, L"szlig"}, - {224, L"agrave"}, {225, L"aacute"}, {226, L"acirc"}, - {227, L"atilde"}, {228, L"auml"}, {229, L"aring"}, - {230, L"aelig"}, {231, L"ccedil"}, {232, L"egrave"}, - {233, L"eacute"}, {234, L"ecirc"}, {235, L"euml"}, - {236, L"igrave"}, {237, L"iacute"}, {238, L"icirc"}, - {239, L"iuml"}, {240, L"eth"}, {241, L"ntilde"}, - {242, L"ograve"}, {243, L"oacute"}, {244, L"ocirc"}, - {245, L"otilde"}, {246, L"ouml"}, {247, L"divide"}, - {248, L"oslash"}, {249, L"ugrave"}, {250, L"uacute"}, - {251, L"ucirc"}, {252, L"uuml"}, {253, L"yacute"}, - {254, L"thorn"}, {255, L"yuml"}, {338, L"OElig"}, - {339, L"oelig"}, {352, L"Scaron"}, {353, L"saron"}, - {376, L"Yuml"}, {402, L"fnof"}, {710, L"circ"}, - {732, L"tilde"}, {913, L"Alpha"}, {914, L"Beta"}, - {915, L"Gamma"}, {916, L"Delta"}, {917, L"Epsilon"}, - {918, L"Zeta"}, {919, L"Eta"}, {920, L"Theta"}, - {921, L"lota"}, {922, L"Kappa"}, {923, L"Lambda"}, - {924, L"Mu"}, {925, L"Nu"}, {926, L"Xi"}, - {927, L"Omicron"}, {928, L"Pi"}, {929, L"Rho"}, - {931, L"Sigma"}, {932, L"Tau"}, {933, L"Upsilon"}, - {934, L"Phi"}, {935, L"Chi"}, {936, L"Psi"}, - {937, L"Omega"}, {945, L"alpha"}, {946, L"beta"}, - {947, L"gamma"}, {948, L"delta"}, {949, L"epsilon"}, - {950, L"zeta"}, {951, L"eta"}, {952, L"theta"}, - {953, L"iota"}, {954, L"kappa"}, {955, L"lambda"}, - {956, L"mu"}, {957, L"nu"}, {958, L"xi"}, - {959, L"omicron"}, {960, L"pi"}, {961, L"rho"}, - {962, L"sigmaf"}, {963, L"sigma"}, {964, L"tau"}, - {965, L"upsilon"}, {966, L"phi"}, {967, L"chi"}, - {968, L"psi"}, {969, L"omega"}, {977, L"thetasym"}, - {978, L"upsih"}, {982, L"piv"}, {8194, L"ensp"}, - {8195, L"emsp"}, {8201, L"thinsp"}, {8204, L"zwnj"}, - {8205, L"zwj"}, {8206, L"lrm"}, {8207, L"rlm"}, - {8211, L"ndash"}, {8212, L"mdash"}, {8216, L"lsquo"}, - {8217, L"rsquo"}, {8218, L"sbquo"}, {8220, L"ldquo"}, - {8221, L"tdquo"}, {8222, L"bdquo"}, {8224, L"dagger"}, - {8225, L"Dagger"}, {8226, L"bull"}, {8230, L"hellip"}, - {8240, L"permil"}, {8242, L"prime"}, {8249, L"lsaquo"}, - {8250, L"rsaquo"}, {8254, L"oline"}, {8260, L"frasl"}, - {8364, L"euro"}, {8465, L"image"}, {8472, L"weierp"}, - {8476, L"real"}, {8482, L"trade"}, {8501, L"alefsym"}, - {8592, L"larr"}, {8593, L"uarr"}, {8594, L"rarr"}, - {8595, L"darr"}, {8596, L"harr"}, {8629, L"crarr"}, - {8656, L"lArr"}, {8657, L"uArr"}, {8658, L"rArr"}, - {8659, L"dArr"}, {8660, L"hArr"}, {8704, L"forall"}, - {8706, L"part"}, {8707, L"exist"}, {8709, L"empty"}, - {8711, L"nabla"}, {8712, L"isin"}, {8713, L"notin"}, - {8715, L"ni"}, {8719, L"prod"}, {8721, L"sum"}, - {8722, L"minus"}, {8727, L"lowast"}, {8730, L"radic"}, - {8733, L"prop"}, {8734, L"infin"}, {8736, L"ang"}, - {8743, L"and"}, {8744, L"or"}, {8745, L"cap"}, - {8746, L"cup"}, {8747, L"int"}, {8756, L"there4"}, - {8764, L"sim"}, {8773, L"cong"}, {8776, L"asymp"}, - {8800, L"ne"}, {8801, L"equiv"}, {8804, L"le"}, - {8805, L"ge"}, {8834, L"sub"}, {8835, L"sup"}, - {8836, L"nsub"}, {8838, L"sube"}, {8839, L"supe"}, - {8853, L"oplus"}, {8855, L"otimes"}, {8869, L"perp"}, - {8901, L"sdot"}, {8968, L"lceil"}, {8969, L"rceil"}, - {8970, L"lfloor"}, {8971, L"rfloor"}, {9001, L"lang"}, - {9002, L"rang"}, {9674, L"loz"}, {9824, L"spades"}, - {9827, L"clubs"}, {9829, L"hearts"}, {9830, L"diams"}, -}; - -const FXJSE_FUNCTION_DESCRIPTOR formcalc_fm2js_functions[] = { - {"Abs", CXFA_FM2JSContext::Abs}, - {"Avg", CXFA_FM2JSContext::Avg}, - {"Ceil", CXFA_FM2JSContext::Ceil}, - {"Count", CXFA_FM2JSContext::Count}, - {"Floor", CXFA_FM2JSContext::Floor}, - {"Max", CXFA_FM2JSContext::Max}, - {"Min", CXFA_FM2JSContext::Min}, - {"Mod", CXFA_FM2JSContext::Mod}, - {"Round", CXFA_FM2JSContext::Round}, - {"Sum", CXFA_FM2JSContext::Sum}, - {"Date", CXFA_FM2JSContext::Date}, - {"Date2Num", CXFA_FM2JSContext::Date2Num}, - {"DateFmt", CXFA_FM2JSContext::DateFmt}, - {"IsoDate2Num", CXFA_FM2JSContext::IsoDate2Num}, - {"IsoTime2Num", CXFA_FM2JSContext::IsoTime2Num}, - {"LocalDateFmt", CXFA_FM2JSContext::LocalDateFmt}, - {"LocalTimeFmt", CXFA_FM2JSContext::LocalTimeFmt}, - {"Num2Date", CXFA_FM2JSContext::Num2Date}, - {"Num2GMTime", CXFA_FM2JSContext::Num2GMTime}, - {"Num2Time", CXFA_FM2JSContext::Num2Time}, - {"Time", CXFA_FM2JSContext::Time}, - {"Time2Num", CXFA_FM2JSContext::Time2Num}, - {"TimeFmt", CXFA_FM2JSContext::TimeFmt}, - {"Apr", CXFA_FM2JSContext::Apr}, - {"Cterm", CXFA_FM2JSContext::CTerm}, - {"FV", CXFA_FM2JSContext::FV}, - {"Ipmt", CXFA_FM2JSContext::IPmt}, - {"NPV", CXFA_FM2JSContext::NPV}, - {"Pmt", CXFA_FM2JSContext::Pmt}, - {"PPmt", CXFA_FM2JSContext::PPmt}, - {"PV", CXFA_FM2JSContext::PV}, - {"Rate", CXFA_FM2JSContext::Rate}, - {"Term", CXFA_FM2JSContext::Term}, - {"Choose", CXFA_FM2JSContext::Choose}, - {"Exists", CXFA_FM2JSContext::Exists}, - {"HasValue", CXFA_FM2JSContext::HasValue}, - {"Oneof", CXFA_FM2JSContext::Oneof}, - {"Within", CXFA_FM2JSContext::Within}, - {"If", CXFA_FM2JSContext::If}, - {"Eval", CXFA_FM2JSContext::Eval}, - {"Translate", CXFA_FM2JSContext::eval_translation}, - {"Ref", CXFA_FM2JSContext::Ref}, - {"UnitType", CXFA_FM2JSContext::UnitType}, - {"UnitValue", CXFA_FM2JSContext::UnitValue}, - {"At", CXFA_FM2JSContext::At}, - {"Concat", CXFA_FM2JSContext::Concat}, - {"Decode", CXFA_FM2JSContext::Decode}, - {"Encode", CXFA_FM2JSContext::Encode}, - {"Format", CXFA_FM2JSContext::Format}, - {"Left", CXFA_FM2JSContext::Left}, - {"Len", CXFA_FM2JSContext::Len}, - {"Lower", CXFA_FM2JSContext::Lower}, - {"Ltrim", CXFA_FM2JSContext::Ltrim}, - {"Parse", CXFA_FM2JSContext::Parse}, - {"Replace", CXFA_FM2JSContext::Replace}, - {"Right", CXFA_FM2JSContext::Right}, - {"Rtrim", CXFA_FM2JSContext::Rtrim}, - {"Space", CXFA_FM2JSContext::Space}, - {"Str", CXFA_FM2JSContext::Str}, - {"Stuff", CXFA_FM2JSContext::Stuff}, - {"Substr", CXFA_FM2JSContext::Substr}, - {"Uuid", CXFA_FM2JSContext::Uuid}, - {"Upper", CXFA_FM2JSContext::Upper}, - {"WordNum", CXFA_FM2JSContext::WordNum}, - {"Get", CXFA_FM2JSContext::Get}, - {"Post", CXFA_FM2JSContext::Post}, - {"Put", CXFA_FM2JSContext::Put}, - {"positive_operator", CXFA_FM2JSContext::positive_operator}, - {"negative_operator", CXFA_FM2JSContext::negative_operator}, - {"logical_or_operator", CXFA_FM2JSContext::logical_or_operator}, - {"logical_and_operator", CXFA_FM2JSContext::logical_and_operator}, - {"logical_not_operator", CXFA_FM2JSContext::logical_not_operator}, - {"equality_operator", CXFA_FM2JSContext::equality_operator}, - {"notequality_operator", CXFA_FM2JSContext::notequality_operator}, - {"less_operator", CXFA_FM2JSContext::less_operator}, - {"lessequal_operator", CXFA_FM2JSContext::lessequal_operator}, - {"greater_operator", CXFA_FM2JSContext::greater_operator}, - {"greaterequal_operator", CXFA_FM2JSContext::greaterequal_operator}, - {"plus_operator", CXFA_FM2JSContext::plus_operator}, - {"minus_operator", CXFA_FM2JSContext::minus_operator}, - {"multiple_operator", CXFA_FM2JSContext::multiple_operator}, - {"divide_operator", CXFA_FM2JSContext::divide_operator}, - {"assign_value_operator", CXFA_FM2JSContext::assign_value_operator}, - {"dot_accessor", CXFA_FM2JSContext::dot_accessor}, - {"dotdot_accessor", CXFA_FM2JSContext::dotdot_accessor}, - {"concat_fm_object", CXFA_FM2JSContext::concat_fm_object}, - {"is_fm_object", CXFA_FM2JSContext::is_fm_object}, - {"is_fm_array", CXFA_FM2JSContext::is_fm_array}, - {"get_fm_value", CXFA_FM2JSContext::get_fm_value}, - {"get_fm_jsobj", CXFA_FM2JSContext::get_fm_jsobj}, - {"fm_var_filter", CXFA_FM2JSContext::fm_var_filter}, -}; - -const FXJSE_CLASS_DESCRIPTOR formcalc_fm2js_descriptor = { - "XFA_FM2JS_FormCalcClass", // name - nullptr, // constructor - nullptr, // properties - formcalc_fm2js_functions, // methods - 0, // number of properties - FX_ArraySize(formcalc_fm2js_functions), // number of methods - nullptr, // dynamic prop type - nullptr, // dynamic prop getter - nullptr, // dynamic prop setter - nullptr, // dynamic prop deleter - nullptr, // dynamic prop method call -}; - -const uint8_t g_sAltTable_Date[] = { - 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255, - 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255, -}; -static_assert(FX_ArraySize(g_sAltTable_Date) == L'a' - L'A' + 1, - "Invalid g_sAltTable_Date size."); - -const uint8_t g_sAltTable_Time[] = { - 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255, - 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255, - 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255, -}; -static_assert(FX_ArraySize(g_sAltTable_Time) == L'a' - L'A' + 1, - "Invalid g_sAltTable_Time size."); - -void AlternateDateTimeSymbols(CFX_WideString& wsPattern, - const CFX_WideString& wsAltSymbols, - const uint8_t* pAltTable) { - int32_t nLength = wsPattern.GetLength(); - bool bInConstRange = false; - bool bEscape = false; - int32_t i = 0; - while (i < nLength) { - FX_WCHAR wc = wsPattern[i]; - if (wc == L'\'') { - bInConstRange = !bInConstRange; - if (bEscape) { - i++; - } else { - wsPattern.Delete(i); - nLength--; - } - bEscape = !bEscape; - continue; - } - if (!bInConstRange && wc >= L'A' && wc <= L'a') { - uint8_t nAlt = pAltTable[wc - L'A']; - if (nAlt != 255) - wsPattern.SetAt(i, wsAltSymbols[nAlt]); - } - i++; - bEscape = false; - } -} - -bool PatternStringType(const CFX_ByteStringC& szPattern, - uint32_t& patternType) { - CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern); - if (L"datetime" == wsPattern.Left(8)) { - patternType = XFA_VT_DATETIME; - return true; - } - if (L"date" == wsPattern.Left(4)) { - patternType = wsPattern.Find(L"time") > 0 ? XFA_VT_DATETIME : XFA_VT_DATE; - return true; - } - if (L"time" == wsPattern.Left(4)) { - patternType = XFA_VT_TIME; - return true; - } - if (L"text" == wsPattern.Left(4)) { - patternType = XFA_VT_TEXT; - return true; - } - if (L"num" == wsPattern.Left(3)) { - if (L"integer" == wsPattern.Mid(4, 7)) { - patternType = XFA_VT_INTEGER; - } else if (L"decimal" == wsPattern.Mid(4, 7)) { - patternType = XFA_VT_DECIMAL; - } else if (L"currency" == wsPattern.Mid(4, 8)) { - patternType = XFA_VT_FLOAT; - } else if (L"percent" == wsPattern.Mid(4, 7)) { - patternType = XFA_VT_FLOAT; - } else { - patternType = XFA_VT_FLOAT; - } - return true; - } - - patternType = XFA_VT_NULL; - wsPattern.MakeLower(); - const FX_WCHAR* pData = wsPattern.c_str(); - int32_t iLength = wsPattern.GetLength(); - int32_t iIndex = 0; - bool bSingleQuotation = false; - FX_WCHAR patternChar; - while (iIndex < iLength) { - patternChar = pData[iIndex]; - if (patternChar == 0x27) { - bSingleQuotation = !bSingleQuotation; - } else if (!bSingleQuotation && - (patternChar == 'y' || patternChar == 'j')) { - patternType = XFA_VT_DATE; - iIndex++; - FX_WCHAR timePatternChar; - while (iIndex < iLength) { - timePatternChar = pData[iIndex]; - if (timePatternChar == 0x27) { - bSingleQuotation = !bSingleQuotation; - } else if (!bSingleQuotation && timePatternChar == 't') { - patternType = XFA_VT_DATETIME; - break; - } - iIndex++; - } - break; - } else if (!bSingleQuotation && - (patternChar == 'h' || patternChar == 'k')) { - patternType = XFA_VT_TIME; - break; - } else if (!bSingleQuotation && - (patternChar == 'a' || patternChar == 'x' || - patternChar == 'o' || patternChar == '0')) { - patternType = XFA_VT_TEXT; - if (patternChar == 'x' || patternChar == 'o' || patternChar == '0') { - break; - } - } else if (!bSingleQuotation && - (patternChar == 'z' || patternChar == 's' || - patternChar == 'e' || patternChar == 'v' || - patternChar == '8' || patternChar == ',' || - patternChar == '.' || patternChar == '$')) { - patternType = XFA_VT_FLOAT; - if (patternChar == 'v' || patternChar == '8' || patternChar == '$') { - break; - } - } - iIndex++; - } - if (patternType == XFA_VT_NULL) { - patternType = XFA_VT_TEXT | XFA_VT_FLOAT; - } - return false; -} - -CXFA_FM2JSContext* ToJSContext(CFXJSE_Value* pValue, CFXJSE_Class* pClass) { - return static_cast<CXFA_FM2JSContext*>(pValue->ToHostObject(pClass)); -} - -bool IsWhitespace(char c) { - return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A || - c == 0x0D; -} - -} // namespace - -// static -void CXFA_FM2JSContext::Abs(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Abs"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE dValue = ValueToDouble(pThis, argOne.get()); - if (dValue < 0) - dValue = -dValue; - - args.GetReturnValue()->SetDouble(dValue); -} - -// static -void CXFA_FM2JSContext::Avg(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1) { - args.GetReturnValue()->SetNull(); - return; - } - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - uint32_t uCount = 0; - FX_DOUBLE dSum = 0.0; - for (int32_t i = 0; i < argc; i++) { - std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (!argValue->IsArray()) { - dSum += ValueToDouble(pThis, argValue.get()); - uCount++; - continue; - } - - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - - if (iLength > 2) { - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - auto defaultPropValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get()); - if (defaultPropValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, defaultPropValue.get()); - uCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, newPropertyValue.get()); - uCount++; - } - } - } - } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetDouble(dSum / uCount); -} - -// static -void CXFA_FM2JSContext::Ceil(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Ceil"); - return; - } - - std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetFloat( - FXSYS_ceil(ValueToFloat(pThis, argValue.get()))); -} - -// static -void CXFA_FM2JSContext::Count(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - int32_t iCount = 0; - for (int32_t i = 0; i < args.GetLength(); i++) { - std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (!newPropertyValue->IsNull()) - iCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), newPropertyValue.get()); - iCount += newPropertyValue->IsNull() ? 0 : 1; - } - } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (!newPropertyValue->IsNull()) - iCount++; - } else { - iCount++; - } - } - args.GetReturnValue()->SetInteger(iCount); -} - -// static -void CXFA_FM2JSContext::Floor(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Floor"); - return; - } - - std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetFloat( - FXSYS_floor(ValueToFloat(pThis, argValue.get()))); -} - -// static -void CXFA_FM2JSContext::Max(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - uint32_t uCount = 0; - FX_DOUBLE dMaxValue = 0.0; - for (int32_t i = 0; i < args.GetLength(); i++) { - std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } else { - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get()); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetDouble(dMaxValue); -} - -// static -void CXFA_FM2JSContext::Min(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - uint32_t uCount = 0; - FX_DOUBLE dMinValue = 0.0; - for (int32_t i = 0; i < args.GetLength(); i++) { - std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } else { - uCount++; - FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get()); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetDouble(dMinValue); -} - -// static -void CXFA_FM2JSContext::Mod(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 2) { - pContext->ThrowParamCountMismatchException(L"Mod"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1); - if (argOne->IsNull() || argTwo->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - bool argOneResult; - FX_DOUBLE dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult); - bool argTwoResult; - FX_DOUBLE dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult); - if (!argOneResult || !argTwoResult) { - pContext->ThrowArgumentMismatchException(); - return; - } - - if (dDivisor == 0.0) { - pContext->ThrowDivideByZeroException(); - return; - } - - args.GetReturnValue()->SetDouble(dDividend - - dDivisor * (int32_t)(dDividend / dDivisor)); -} - -// static -void CXFA_FM2JSContext::Round(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - pContext->ThrowParamCountMismatchException(L"Round"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - bool dValueRet; - FX_DOUBLE dValue = ExtractDouble(pThis, argOne.get(), &dValueRet); - if (!dValueRet) { - pContext->ThrowArgumentMismatchException(); - return; - } - - uint8_t uPrecision = 0; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1); - if (argTwo->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - bool dPrecisionRet; - FX_DOUBLE dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet); - if (!dPrecisionRet) { - pContext->ThrowArgumentMismatchException(); - return; - } - - uPrecision = - static_cast<uint8_t>(std::min(std::max(dPrecision, 0.0), 12.0)); - } - - CFX_Decimal decimalValue((FX_FLOAT)dValue, uPrecision); - CFX_WideString wsValue = decimalValue; - args.GetReturnValue()->SetString(wsValue.UTF8Encode().AsStringC()); -} - -// static -void CXFA_FM2JSContext::Sum(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - uint32_t uCount = 0; - FX_DOUBLE dSum = 0.0; - for (int32_t i = 0; i < argc; i++) { - std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i); - if (argValue->IsNull()) - continue; - - if (argValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValue->GetObjectPropertyByIdx(1, propertyValue.get()); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, jsObjectValue.get()); - uCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, newPropertyValue.get()); - uCount++; - } - } - } else if (argValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(argValue.get(), newPropertyValue.get()); - if (newPropertyValue->IsNull()) - continue; - - dSum += ValueToDouble(pThis, argValue.get()); - uCount++; - } else { - dSum += ValueToDouble(pThis, argValue.get()); - uCount++; - } - } - if (uCount == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetDouble(dSum); -} - -// static -void CXFA_FM2JSContext::Date(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 0) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Date"); - return; - } - - time_t currentTime; - time(¤tTime); - struct tm* pTmStruct = gmtime(¤tTime); - - CFX_ByteString bufferYear; - CFX_ByteString bufferMon; - CFX_ByteString bufferDay; - bufferYear.Format("%d", pTmStruct->tm_year + 1900); - bufferMon.Format("%02d", pTmStruct->tm_mon + 1); - bufferDay.Format("%02d", pTmStruct->tm_mday); - - CFX_ByteString bufferCurrent = bufferYear + bufferMon + bufferDay; - args.GetReturnValue()->SetInteger(DateString2Num(bufferCurrent.AsStringC())); -} - -// static -void CXFA_FM2JSContext::Date2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Date2Num"); - return; - } - - std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, dateValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString dateString; - ValueToUTF8String(dateValue.get(), dateString); - - CFX_ByteString formatString; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, formatValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(formatValue.get(), formatString); - } - - CFX_ByteString localString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, localValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(localValue.get(), localString); - } - - CFX_ByteString szIsoDateString; - if (!Local2IsoDate(pThis, dateString.AsStringC(), formatString.AsStringC(), - localString.AsStringC(), szIsoDateString)) { - args.GetReturnValue()->SetInteger(0); - return; - } - - args.GetReturnValue()->SetInteger( - DateString2Num(szIsoDateString.AsStringC())); -} - -// static -void CXFA_FM2JSContext::DateFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Date2Num"); - return; - } - - int32_t iStyle = 0; - if (argc > 0) { - std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0); - if (argStyle->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); - if (iStyle < 0 || iStyle > 4) - iStyle = 0; - } - - CFX_ByteString szLocal; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1); - if (argLocal->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(argLocal.get(), szLocal); - } - - CFX_ByteString formatStr; - GetStandardDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr); - args.GetReturnValue()->SetString(formatStr.AsStringC()); -} - -// static -void CXFA_FM2JSContext::IsoDate2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr) - ->ThrowParamCountMismatchException(L"IsoDate2Num"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString szArgString; - ValueToUTF8String(argOne.get(), szArgString); - args.GetReturnValue()->SetInteger(DateString2Num(szArgString.AsStringC())); -} - -// static -void CXFA_FM2JSContext::IsoTime2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"IsoTime2Num"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CXFA_Document* pDoc = pContext->GetDocument(); - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - - CFX_ByteString szArgString; - ValueToUTF8String(argOne.get(), szArgString); - szArgString = szArgString.Mid(szArgString.Find('T', 0) + 1); - if (szArgString.IsEmpty()) { - args.GetReturnValue()->SetInteger(0); - return; - } - - CXFA_LocaleValue timeValue( - XFA_VT_TIME, CFX_WideString::FromUTF8(szArgString.AsStringC()), pMgr); - if (!timeValue.IsValid()) { - args.GetReturnValue()->SetInteger(0); - return; - } - - CFX_Unitime uniTime = timeValue.GetTime(); - int32_t hour = uniTime.GetHour(); - int32_t min = uniTime.GetMinute(); - int32_t second = uniTime.GetSecond(); - int32_t milSecond = uniTime.GetMillisecond(); - - FX_TIMEZONE tzLocale; - pMgr->GetDefLocale()->GetTimeZone(&tzLocale); - - // TODO(dsinclair): See if there is other time conversion code in pdfium and - // consolidate. - int32_t mins = hour * 60 + min; - mins -= (tzLocale.tzHour * 60); - while (mins > 1440) - mins -= 1440; - while (mins < 0) - mins += 1440; - hour = mins / 60; - min = mins % 60; - - args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 + - second * 1000 + milSecond + 1); -} - -// static -void CXFA_FM2JSContext::LocalDateFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc > 2) { - ToJSContext(pThis, nullptr) - ->ThrowParamCountMismatchException(L"LocalDateFmt"); - return; - } - - int32_t iStyle = 0; - if (argc > 0) { - std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0); - if (argStyle->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); - if (iStyle > 4 || iStyle < 0) - iStyle = 0; - } - - CFX_ByteString szLocal; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1); - if (argLocal->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(argLocal.get(), szLocal); - } - - CFX_ByteString formatStr; - GetLocalDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, false); - args.GetReturnValue()->SetString(formatStr.AsStringC()); -} - -// static -void CXFA_FM2JSContext::LocalTimeFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc > 2) { - ToJSContext(pThis, nullptr) - ->ThrowParamCountMismatchException(L"LocalTimeFmt"); - return; - } - - int32_t iStyle = 0; - if (argc > 0) { - std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0); - if (argStyle->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); - if (iStyle > 4 || iStyle < 0) - iStyle = 0; - } - - CFX_ByteString szLocal; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1); - if (argLocal->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(argLocal.get(), szLocal); - } - - CFX_ByteString formatStr; - GetLocalTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, false); - args.GetReturnValue()->SetString(formatStr.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Num2Date(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Num2Date"); - return; - } - - std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, dateValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - int32_t dDate = (int32_t)ValueToFloat(pThis, dateValue.get()); - if (dDate < 1) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString formatString; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, formatValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(formatValue.get(), formatString); - } - - CFX_ByteString localString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, localValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(localValue.get(), localString); - } - - int32_t iYear = 1900; - int32_t iMonth = 1; - int32_t iDay = 1; - int32_t i = 0; - while (dDate > 0) { - if (iMonth == 2) { - if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) { - if (dDate > 29) { - ++iMonth; - if (iMonth > 12) { - iMonth = 1; - ++i; - } - iDay = 1; - dDate -= 29; - } else { - iDay += static_cast<int32_t>(dDate) - 1; - dDate = 0; - } - } else { - if (dDate > 28) { - ++iMonth; - if (iMonth > 12) { - iMonth = 1; - ++i; - } - iDay = 1; - dDate -= 28; - } else { - iDay += static_cast<int32_t>(dDate) - 1; - dDate = 0; - } - } - } else if (iMonth < 8) { - if ((iMonth % 2 == 0)) { - if (dDate > 30) { - ++iMonth; - if (iMonth > 12) { - iMonth = 1; - ++i; - } - iDay = 1; - dDate -= 30; - } else { - iDay += static_cast<int32_t>(dDate) - 1; - dDate = 0; - } - } else { - if (dDate > 31) { - ++iMonth; - if (iMonth > 12) { - iMonth = 1; - ++i; - } - iDay = 1; - dDate -= 31; - } else { - iDay += static_cast<int32_t>(dDate) - 1; - dDate = 0; - } - } - } else { - if (iMonth % 2 != 0) { - if (dDate > 30) { - ++iMonth; - if (iMonth > 12) { - iMonth = 1; - ++i; - } - iDay = 1; - dDate -= 30; - } else { - iDay += static_cast<int32_t>(dDate) - 1; - dDate = 0; - } - } else { - if (dDate > 31) { - ++iMonth; - if (iMonth > 12) { - iMonth = 1; - ++i; - } - iDay = 1; - dDate -= 31; - } else { - iDay += static_cast<int32_t>(dDate) - 1; - dDate = 0; - } - } - } - } - - CFX_ByteString szIsoDateString; - szIsoDateString.Format("%d%02d%02d", iYear + i, iMonth, iDay); - CFX_ByteString szLocalDateString; - IsoDate2Local(pThis, szIsoDateString.AsStringC(), formatString.AsStringC(), - localString.AsStringC(), szLocalDateString); - args.GetReturnValue()->SetString(szLocalDateString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Num2GMTime(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr) - ->ThrowParamCountMismatchException(L"Num2GMTime"); - return; - } - - std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0); - if (timeValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get()); - if (FXSYS_abs(iTime) < 1.0) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString formatString; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1); - if (formatValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(formatValue.get(), formatString); - } - - CFX_ByteString localString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2); - if (localValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(localValue.get(), localString); - } - - CFX_ByteString szGMTTimeString; - Num2AllTime(pThis, iTime, formatString.AsStringC(), localString.AsStringC(), - true, szGMTTimeString); - args.GetReturnValue()->SetString(szGMTTimeString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Num2Time(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Num2Time"); - return; - } - - std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0); - if (timeValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - FX_FLOAT fTime = ValueToFloat(pThis, timeValue.get()); - if (FXSYS_fabs(fTime) < 1.0) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString formatString; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1); - if (formatValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(formatValue.get(), formatString); - } - - CFX_ByteString localString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2); - if (localValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(localValue.get(), localString); - } - - CFX_ByteString szLocalTimeString; - Num2AllTime(pThis, (int32_t)fTime, formatString.AsStringC(), - localString.AsStringC(), false, szLocalTimeString); - args.GetReturnValue()->SetString(szLocalTimeString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Time(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 0) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Time"); - return; - } - - time_t now; - time(&now); - - struct tm* pGmt = gmtime(&now); - args.GetReturnValue()->SetInteger( - (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000); -} - -// static -void CXFA_FM2JSContext::Time2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Time2Num"); - return; - } - - CFX_ByteString timeString; - std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, timeValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(timeValue.get(), timeString); - - CFX_ByteString formatString; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, formatValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(formatValue.get(), formatString); - } - - CFX_ByteString localString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, localValue.get())) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(localValue.get(), localString); - } - - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - IFX_Locale* pLocale = nullptr; - if (localString.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pMgr->GetLocaleByName( - CFX_WideString::FromUTF8(localString.AsStringC())); - } - - CFX_WideString wsFormat; - if (formatString.IsEmpty()) - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat); - else - wsFormat = CFX_WideString::FromUTF8(formatString.AsStringC()); - - wsFormat = L"time{" + wsFormat + L"}"; - CXFA_LocaleValue localeValue(XFA_VT_TIME, - CFX_WideString::FromUTF8(timeString.AsStringC()), - wsFormat, pLocale, pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetInteger(0); - return; - } - - CFX_Unitime uniTime = localeValue.GetTime(); - int32_t hour = uniTime.GetHour(); - int32_t min = uniTime.GetMinute(); - int32_t second = uniTime.GetSecond(); - int32_t milSecond = uniTime.GetMillisecond(); - int32_t mins = hour * 60 + min; - - FX_TIMEZONE tz; - CXFA_TimeZoneProvider provider; - provider.GetTimeZone(&tz); - mins -= (tz.tzHour * 60); - while (mins > 1440) - mins -= 1440; - - while (mins < 0) - mins += 1440; - - hour = mins / 60; - min = mins % 60; - args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 + - second * 1000 + milSecond + 1); -} - -// static -void CXFA_FM2JSContext::TimeFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"TimeFmt"); - return; - } - - int32_t iStyle = 0; - if (argc > 0) { - std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0); - if (argStyle->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - iStyle = (int32_t)ValueToFloat(pThis, argStyle.get()); - if (iStyle > 4 || iStyle < 0) - iStyle = 0; - } - - CFX_ByteString szLocal; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1); - if (argLocal->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(argLocal.get(), szLocal); - } - - CFX_ByteString formatStr; - GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr); - args.GetReturnValue()->SetString(formatStr.AsStringC()); -} - -// static -bool CXFA_FM2JSContext::IsIsoDateFormat(const FX_CHAR* pData, - int32_t iLength, - int32_t& iStyle, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay) { - iYear = 0; - iMonth = 1; - iDay = 1; - - if (iLength < 4) - return false; - - FX_CHAR strYear[5]; - strYear[4] = '\0'; - for (int32_t i = 0; i < 4; ++i) { - if (pData[i] > '9' || pData[i] < '0') - return false; - - strYear[i] = pData[i]; - } - iYear = FXSYS_atoi(strYear); - iStyle = 0; - if (iLength == 4) - return true; - - iStyle = pData[4] == '-' ? 1 : 0; - - FX_CHAR strTemp[3]; - strTemp[2] = '\0'; - int32_t iPosOff = iStyle == 0 ? 4 : 5; - if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') || - (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0')) - return false; - - strTemp[0] = pData[iPosOff]; - strTemp[1] = pData[iPosOff + 1]; - iMonth = FXSYS_atoi(strTemp); - if (iMonth > 12 || iMonth < 1) - return false; - - if (iStyle == 0) { - iPosOff += 2; - if (iLength == 6) - return true; - } else { - iPosOff += 3; - if (iLength == 7) - return true; - } - if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') || - (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0')) - return false; - - strTemp[0] = pData[iPosOff]; - strTemp[1] = pData[iPosOff + 1]; - iDay = FXSYS_atoi(strTemp); - if (iPosOff + 2 < iLength) - return false; - - if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) { - if (iMonth == 2 && iDay > 29) - return false; - } else { - if (iMonth == 2 && iDay > 28) - return false; - } - if (iMonth != 2) { - if (iMonth < 8) { - if (iDay > (iMonth % 2 == 0 ? 30 : 31)) - return false; - } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) { - return false; - } - } - return true; -} - -// static -bool CXFA_FM2JSContext::IsIsoTimeFormat(const FX_CHAR* pData, - int32_t iLength, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMilliSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute) { - iHour = 0; - iMinute = 0; - iSecond = 0; - iMilliSecond = 0; - iZoneHour = 0; - iZoneMinute = 0; - if (!pData) - return false; - - FX_CHAR strTemp[3]; - strTemp[2] = '\0'; - int32_t iZone = 0; - int32_t i = 0; - while (i < iLength) { - if ((pData[i] > '9' || pData[i] < '0') && pData[i] != ':') { - iZone = i; - break; - } - ++i; - } - if (i == iLength) - iZone = iLength; - - int32_t iPos = 0; - int32_t iIndex = 0; - while (iIndex < iZone) { - if (iIndex >= iZone) - break; - - if (pData[iIndex] > '9' || pData[iIndex] < '0') - return false; - - strTemp[0] = pData[iIndex]; - if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0') - return false; - - strTemp[1] = pData[iIndex + 1]; - if (FXSYS_atoi(strTemp) > 60) - return false; - - if (pData[2] == ':') { - if (iPos == 0) { - iHour = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 1) { - iMinute = FXSYS_atoi(strTemp); - ++iPos; - } else { - iSecond = FXSYS_atoi(strTemp); - } - iIndex += 3; - } else { - if (iPos == 0) { - iHour = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 1) { - iMinute = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 2) { - iSecond = FXSYS_atoi(strTemp); - ++iPos; - } - iIndex += 2; - } - } - if (pData[iIndex] == '.') { - ++iIndex; - FX_CHAR strSec[4]; - strSec[3] = '\0'; - if (pData[iIndex] > '9' || pData[iIndex] < '0') - return false; - - strSec[0] = pData[iIndex]; - if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0') - return false; - - strSec[1] = pData[iIndex + 1]; - if (pData[iIndex + 2] > '9' || pData[iIndex + 2] < '0') - return false; - - strSec[2] = pData[iIndex + 2]; - iMilliSecond = FXSYS_atoi(strSec); - if (iMilliSecond > 100) { - iMilliSecond = 0; - return false; - } - iIndex += 3; - } - if (pData[iIndex] == 'z' || pData[iIndex] == 'Z') - return true; - - int32_t iSign = 1; - if (pData[iIndex] == '+') { - ++iIndex; - } else if (pData[iIndex] == '-') { - iSign = -1; - ++iIndex; - } - iPos = 0; - while (iIndex < iLength) { - if (iIndex >= iLength) - return false; - if (pData[iIndex] > '9' || pData[iIndex] < '0') - return false; - - strTemp[0] = pData[iIndex]; - if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0') - return false; - - strTemp[1] = pData[iIndex + 1]; - if (FXSYS_atoi(strTemp) > 60) - return false; - - if (pData[2] == ':') { - if (iPos == 0) { - iZoneHour = FXSYS_atoi(strTemp); - } else if (iPos == 1) { - iZoneMinute = FXSYS_atoi(strTemp); - } - iIndex += 3; - } else { - if (!iPos) { - iZoneHour = FXSYS_atoi(strTemp); - ++iPos; - } else if (iPos == 1) { - iZoneMinute = FXSYS_atoi(strTemp); - ++iPos; - } - iIndex += 2; - } - } - if (iIndex < iLength) - return false; - - iZoneHour *= iSign; - return true; -} - -// static -bool CXFA_FM2JSContext::IsIsoDateTimeFormat(const FX_CHAR* pData, - int32_t iLength, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMillionSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute) { - iYear = 0; - iMonth = 0; - iDay = 0; - iHour = 0; - iMinute = 0; - iSecond = 0; - if (!pData) - return false; - - int32_t iIndex = 0; - while (pData[iIndex] != 'T' && pData[iIndex] != 't') { - if (iIndex >= iLength) - return false; - ++iIndex; - } - if (iIndex != 8 && iIndex != 10) - return false; - - int32_t iStyle = -1; - if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay)) - return false; - if (pData[iIndex] != 'T' && pData[iIndex] != 't') - return true; - - ++iIndex; - if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) && - (iLength - iIndex != 15)) { - return true; - } - if (!IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute, - iSecond, iMillionSecond, iZoneHour, iZoneMinute)) { - return false; - } - - return true; -} - -// static -bool CXFA_FM2JSContext::Local2IsoDate(CFXJSE_Value* pThis, - const CFX_ByteStringC& szDate, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strIsoDate) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return false; - - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - IFX_Locale* pLocale = nullptr; - if (szLocale.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale)); - } - if (!pLocale) - return false; - - CFX_WideString wsFormat; - if (szFormat.IsEmpty()) - pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat); - else - wsFormat = CFX_WideString::FromUTF8(szFormat); - - CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate), - wsFormat, pLocale, pMgr); - CFX_Unitime dt = widgetValue.GetDate(); - strIsoDate.Format("%4d-%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay()); - return true; -} - -// static -bool CXFA_FM2JSContext::Local2IsoTime(CFXJSE_Value* pThis, - const CFX_ByteStringC& szTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strIsoTime) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return false; - - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - IFX_Locale* pLocale = nullptr; - if (szLocale.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale)); - } - if (!pLocale) - return false; - - CFX_WideString wsFormat; - if (szFormat.IsEmpty()) - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat); - else - wsFormat = CFX_WideString::FromUTF8(szFormat); - - wsFormat = L"time{" + wsFormat + L"}"; - CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime), - wsFormat, pLocale, pMgr); - CFX_Unitime utime = widgetValue.GetTime(); - strIsoTime.Format("%02d:%02d:%02d.%03d", utime.GetHour(), utime.GetMinute(), - utime.GetSecond(), utime.GetMillisecond()); - return true; -} - -// static -bool CXFA_FM2JSContext::IsoDate2Local(CFXJSE_Value* pThis, - const CFX_ByteStringC& szDate, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strLocalDate) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return false; - - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - IFX_Locale* pLocale = nullptr; - if (szLocale.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale)); - } - if (!pLocale) - return false; - - CFX_WideString wsFormat; - if (szFormat.IsEmpty()) - pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat); - else - wsFormat = CFX_WideString::FromUTF8(szFormat); - - CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate), - pMgr); - CFX_WideString wsRet; - widgetValue.FormatPatterns(wsRet, wsFormat, pLocale, - XFA_VALUEPICTURE_Display); - strLocalDate = wsRet.UTF8Encode(); - return true; -} - -// static -bool CXFA_FM2JSContext::IsoTime2Local(CFXJSE_Value* pThis, - const CFX_ByteStringC& szTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strLocalTime) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return false; - - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - IFX_Locale* pLocale = nullptr; - if (szLocale.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale)); - } - if (!pLocale) - return false; - - CFX_WideString wsFormat; - if (szFormat.IsEmpty()) - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat); - else - wsFormat = CFX_WideString::FromUTF8(szFormat); - - wsFormat = L"time{" + wsFormat + L"}"; - CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime), - pMgr); - CFX_WideString wsRet; - widgetValue.FormatPatterns(wsRet, wsFormat, pLocale, - XFA_VALUEPICTURE_Display); - strLocalTime = wsRet.UTF8Encode(); - return true; -} - -// static -bool CXFA_FM2JSContext::GetGMTTime(CFXJSE_Value* pThis, - const CFX_ByteStringC& szTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strGMTTime) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return false; - - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - IFX_Locale* pLocale = nullptr; - if (szLocale.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale)); - } - if (!pLocale) - return false; - - CFX_WideString wsFormat; - if (szFormat.IsEmpty()) - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat); - else - wsFormat = CFX_WideString::FromUTF8(szFormat); - - wsFormat = L"time{" + wsFormat + L"}"; - CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime), - pMgr); - CFX_WideString wsRet; - widgetValue.FormatPatterns(wsRet, wsFormat, pLocale, - XFA_VALUEPICTURE_Display); - strGMTTime = wsRet.UTF8Encode(); - return true; -} - -// static -int32_t CXFA_FM2JSContext::DateString2Num(const CFX_ByteStringC& szDateString) { - int32_t iLength = szDateString.GetLength(); - int32_t iYear = 0; - int32_t iMonth = 0; - int32_t iDay = 0; - if (iLength <= 10) { - int32_t iStyle = -1; - if (!IsIsoDateFormat(szDateString.c_str(), iLength, iStyle, iYear, iMonth, - iDay)) { - return 0; - } - } else { - int32_t iHour = 0; - int32_t iMinute = 0; - int32_t iSecond = 0; - int32_t iMilliSecond = 0; - int32_t iZoneHour = 0; - int32_t iZoneMinute = 0; - if (!IsIsoDateTimeFormat(szDateString.c_str(), iLength, iYear, iMonth, iDay, - iHour, iMinute, iSecond, iMilliSecond, iZoneHour, - iZoneMinute)) { - return 0; - } - } - - FX_FLOAT dDays = 0; - int32_t i = 1; - if (iYear < 1900) - return 0; - - while (iYear - i >= 1900) { - dDays += - ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400)) - ? 366 - : 365; - ++i; - } - i = 1; - while (i < iMonth) { - if (i == 2) - dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28; - else if (i <= 7) - dDays += (i % 2 == 0) ? 30 : 31; - else - dDays += (i % 2 == 0) ? 31 : 30; - - ++i; - } - i = 0; - while (iDay - i > 0) { - dDays += 1; - ++i; - } - return (int32_t)dDays; -} - -// static -void CXFA_FM2JSContext::GetLocalDateFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat, - bool bStandard) { - FX_LOCALEDATETIMESUBCATEGORY strStyle; - switch (iStyle) { - case 1: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short; - break; - case 3: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long; - break; - case 4: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full; - break; - case 0: - case 2: - default: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium; - break; - } - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return; - - IFX_Locale* pLocale = nullptr; - if (szLocalStr.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pDoc->GetLocalMgr()->GetLocaleByName( - CFX_WideString::FromUTF8(szLocalStr)); - } - if (!pLocale) - return; - - CFX_WideString strRet; - pLocale->GetDatePattern(strStyle, strRet); - if (!bStandard) { - CFX_WideString wsSymbols; - pLocale->GetDateTimeSymbols(wsSymbols); - AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Date); - } - strFormat = strRet.UTF8Encode(); -} - -// static -void CXFA_FM2JSContext::GetLocalTimeFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat, - bool bStandard) { - FX_LOCALEDATETIMESUBCATEGORY strStyle; - switch (iStyle) { - case 1: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short; - break; - case 3: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long; - break; - case 4: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full; - break; - case 0: - case 2: - default: - strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium; - break; - } - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return; - - IFX_Locale* pLocale = nullptr; - if (szLocalStr.IsEmpty()) { - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - pLocale = widgetData.GetLocal(); - } else { - pLocale = pDoc->GetLocalMgr()->GetLocaleByName( - CFX_WideString::FromUTF8(szLocalStr)); - } - if (!pLocale) - return; - - CFX_WideString strRet; - pLocale->GetTimePattern(strStyle, strRet); - if (!bStandard) { - CFX_WideString wsSymbols; - pLocale->GetDateTimeSymbols(wsSymbols); - AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Time); - } - strFormat = strRet.UTF8Encode(); -} - -// static -void CXFA_FM2JSContext::GetStandardDateFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat) { - GetLocalDateFormat(pThis, iStyle, szLocalStr, strFormat, true); -} - -// static -void CXFA_FM2JSContext::GetStandardTimeFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat) { - GetLocalTimeFormat(pThis, iStyle, szLocalStr, strFormat, true); -} - -// static -void CXFA_FM2JSContext::Num2AllTime(CFXJSE_Value* pThis, - int32_t iTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - bool bGM, - CFX_ByteString& strTime) { - int32_t iHour = 0; - int32_t iMin = 0; - int32_t iSec = 0; - iHour = static_cast<int>(iTime) / 3600000; - iMin = (static_cast<int>(iTime) - iHour * 3600000) / 60000; - iSec = (static_cast<int>(iTime) - iHour * 3600000 - iMin * 60000) / 1000; - - if (!bGM) { - int32_t iZoneHour = 0; - int32_t iZoneMin = 0; - int32_t iZoneSec = 0; - GetLocalTimeZone(iZoneHour, iZoneMin, iZoneSec); - iHour += iZoneHour; - iMin += iZoneMin; - iSec += iZoneSec; - } - - bool iRet = false; - CFX_ByteString strIsoTime; - strIsoTime.Format("%02d:%02d:%02d", iHour, iMin, iSec); - if (bGM) { - iRet = - GetGMTTime(pThis, strIsoTime.AsStringC(), szFormat, szLocale, strTime); - } else { - iRet = IsoTime2Local(pThis, strIsoTime.AsStringC(), szFormat, szLocale, - strTime); - } - if (!iRet) - strTime = ""; -} - -// static -void CXFA_FM2JSContext::GetLocalTimeZone(int32_t& iHour, - int32_t& iMin, - int32_t& iSec) { - time_t now; - time(&now); - - struct tm* pGmt = gmtime(&now); - struct tm* pLocal = localtime(&now); - iHour = pLocal->tm_hour - pGmt->tm_hour; - iMin = pLocal->tm_min - pGmt->tm_min; - iSec = pLocal->tm_sec - pGmt->tm_sec; -} - -// static -void CXFA_FM2JSContext::Apr(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"Apr"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE nPrincipal = ValueToDouble(pThis, argOne.get()); - FX_DOUBLE nPayment = ValueToDouble(pThis, argTwo.get()); - FX_DOUBLE nPeriods = ValueToDouble(pThis, argThree.get()); - if (nPrincipal <= 0 || nPayment <= 0 || nPeriods <= 0) { - pContext->ThrowArgumentMismatchException(); - return; - } - - FX_DOUBLE r = - 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal); - FX_DOUBLE nTemp = 1; - for (int32_t i = 0; i < nPeriods; ++i) - nTemp *= (1 + r); - - FX_DOUBLE nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal; - while (fabs(nRet) > kFinancialPrecision) { - FX_DOUBLE nDerivative = - ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) - - (r * nTemp * nPeriods * (nTemp / (1 + r)))) / - ((nTemp - 1) * (nTemp - 1)); - if (nDerivative == 0) { - args.GetReturnValue()->SetNull(); - return; - } - - r = r - nRet / nDerivative; - nTemp = 1; - for (int32_t i = 0; i < nPeriods; ++i) { - nTemp *= (1 + r); - } - nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal; - } - args.GetReturnValue()->SetDouble(r * 12); -} - -// static -void CXFA_FM2JSContext::CTerm(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"CTerm"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT nRate = ValueToFloat(pThis, argOne.get()); - FX_FLOAT nFutureValue = ValueToFloat(pThis, argTwo.get()); - FX_FLOAT nInitAmount = ValueToFloat(pThis, argThree.get()); - if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - args.GetReturnValue()->SetFloat( - FXSYS_log((FX_FLOAT)(nFutureValue / nInitAmount)) / - FXSYS_log((FX_FLOAT)(1 + nRate))); -} - -// static -void CXFA_FM2JSContext::FV(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"FV"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get()); - FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get()); - FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get()); - if ((nRate < 0) || (nPeriod <= 0) || (nAmount <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - FX_DOUBLE dResult = 0; - if (nRate) { - FX_DOUBLE nTemp = 1; - for (int i = 0; i < nPeriod; ++i) { - nTemp *= 1 + nRate; - } - dResult = nAmount * (nTemp - 1) / nRate; - } else { - dResult = nAmount * nPeriod; - } - - args.GetReturnValue()->SetDouble(dResult); -} - -// static -void CXFA_FM2JSContext::IPmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 5) { - pContext->ThrowParamCountMismatchException(L"IPmt"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3); - std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) || - ValueIsNull(pThis, argFive.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get()); - FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get()); - FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get()); - FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get()); - FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get()); - if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) || - (nFirstMonth < 0) || (nNumberOfMonths < 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - FX_FLOAT nRateOfMonth = nRate / 12; - int32_t iNums = (int32_t)( - (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) - - FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) / - FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth))); - int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums); - - if (nPayment < nPrincipalAmount * nRateOfMonth) { - args.GetReturnValue()->SetFloat(0); - return; - } - - int32_t i = 0; - for (i = 0; i < nFirstMonth - 1; ++i) - nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth; - - FX_FLOAT nSum = 0; - for (; i < iEnd; ++i) { - nSum += nPrincipalAmount * nRateOfMonth; - nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth; - } - args.GetReturnValue()->SetFloat(nSum); -} - -// static -void CXFA_FM2JSContext::NPV(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - int32_t argc = args.GetLength(); - if (argc < 3) { - pContext->ThrowParamCountMismatchException(L"NPV"); - return; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> argValues; - for (int32_t i = 0; i < argc; i++) { - argValues.push_back(GetSimpleValue(pThis, args, i)); - if (ValueIsNull(pThis, argValues[i].get())) { - args.GetReturnValue()->SetNull(); - return; - } - } - - FX_DOUBLE nRate = ValueToDouble(pThis, argValues[0].get()); - if (nRate <= 0) { - pContext->ThrowArgumentMismatchException(); - return; - } - - std::vector<FX_DOUBLE> data(argc - 1); - for (int32_t i = 1; i < argc; i++) - data.push_back(ValueToDouble(pThis, argValues[i].get())); - - FX_DOUBLE nSum = 0; - int32_t iIndex = 0; - for (int32_t i = 0; i < argc - 1; i++) { - FX_DOUBLE nTemp = 1; - for (int32_t j = 0; j <= i; j++) - nTemp *= 1 + nRate; - - FX_DOUBLE nNum = data[iIndex++]; - nSum += nNum / nTemp; - } - args.GetReturnValue()->SetDouble(nSum); -} - -// static -void CXFA_FM2JSContext::Pmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"Pmt"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT nPrincipal = ValueToFloat(pThis, argOne.get()); - FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get()); - FX_FLOAT nPeriods = ValueToFloat(pThis, argThree.get()); - if ((nPrincipal <= 0) || (nRate <= 0) || (nPeriods <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - FX_FLOAT nTmp = 1 + nRate; - FX_FLOAT nSum = nTmp; - for (int32_t i = 0; i < nPeriods - 1; ++i) - nSum *= nTmp; - - args.GetReturnValue()->SetFloat((nPrincipal * nRate * nSum) / (nSum - 1)); -} - -// static -void CXFA_FM2JSContext::PPmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 5) { - pContext->ThrowParamCountMismatchException(L"PPmt"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3); - std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) || - ValueIsNull(pThis, argFive.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get()); - FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get()); - FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get()); - FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get()); - FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get()); - if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) || - (nFirstMonth < 0) || (nNumberOfMonths < 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - FX_FLOAT nRateOfMonth = nRate / 12; - int32_t iNums = (int32_t)( - (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) - - FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) / - FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth))); - int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums); - if (nPayment < nPrincipalAmount * nRateOfMonth) { - pContext->ThrowArgumentMismatchException(); - return; - } - - int32_t i = 0; - for (i = 0; i < nFirstMonth - 1; ++i) - nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth; - - FX_FLOAT nTemp = 0; - FX_FLOAT nSum = 0; - for (; i < iEnd; ++i) { - nTemp = nPayment - nPrincipalAmount * nRateOfMonth; - nSum += nTemp; - nPrincipalAmount -= nTemp; - } - args.GetReturnValue()->SetFloat(nSum); -} - -// static -void CXFA_FM2JSContext::PV(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"PV"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get()); - FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get()); - FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get()); - if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - FX_DOUBLE nTemp = 1; - for (int32_t i = 0; i < nPeriod; ++i) - nTemp *= 1 + nRate; - - nTemp = 1 / nTemp; - args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate)); -} - -// static -void CXFA_FM2JSContext::Rate(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"Rate"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT nFuture = ValueToFloat(pThis, argOne.get()); - FX_FLOAT nPresent = ValueToFloat(pThis, argTwo.get()); - FX_FLOAT nTotalNumber = ValueToFloat(pThis, argThree.get()); - if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - args.GetReturnValue()->SetFloat( - FXSYS_pow((FX_FLOAT)(nFuture / nPresent), (FX_FLOAT)(1 / nTotalNumber)) - - 1); -} - -// static -void CXFA_FM2JSContext::Term(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 3) { - pContext->ThrowParamCountMismatchException(L"Term"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) || - ValueIsNull(pThis, argThree.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT nMount = ValueToFloat(pThis, argOne.get()); - FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get()); - FX_FLOAT nFuture = ValueToFloat(pThis, argThree.get()); - if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) { - pContext->ThrowArgumentMismatchException(); - return; - } - - args.GetReturnValue()->SetFloat( - FXSYS_log((FX_FLOAT)(nFuture / nMount * nRate) + 1) / - FXSYS_log((FX_FLOAT)(1 + nRate))); -} - -// static -void CXFA_FM2JSContext::Choose(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - int32_t argc = args.GetLength(); - if (argc < 2) { - pContext->ThrowParamCountMismatchException(L"Choose"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get()); - if (iIndex < 1) { - args.GetReturnValue()->SetString(""); - return; - } - - bool bFound = false; - bool bStopCounterFlags = false; - int32_t iArgIndex = 1; - int32_t iValueIndex = 0; - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) { - std::unique_ptr<CFXJSE_Value> argIndexValue = args.GetValue(iArgIndex); - if (argIndexValue->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argIndexValue->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength > 3) - bStopCounterFlags = true; - - iValueIndex += (iLength - 2); - if (iValueIndex >= iIndex) { - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get()); - argIndexValue->GetObjectPropertyByIdx( - (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - } else { - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), newPropertyValue.get()); - } - CFX_ByteString bsChoosed; - ValueToUTF8String(newPropertyValue.get(), bsChoosed); - args.GetReturnValue()->SetString(bsChoosed.AsStringC()); - bFound = true; - } - } else { - iValueIndex++; - if (iValueIndex == iIndex) { - CFX_ByteString bsChoosed; - ValueToUTF8String(argIndexValue.get(), bsChoosed); - args.GetReturnValue()->SetString(bsChoosed.AsStringC()); - bFound = true; - } - } - iArgIndex++; - } - if (!bFound) - args.GetReturnValue()->SetString(""); -} - -// static -void CXFA_FM2JSContext::Exists(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Exists"); - return; - } - args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject()); -} - -// static -void CXFA_FM2JSContext::HasValue(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"HasValue"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (!argOne->IsString()) { - args.GetReturnValue()->SetInteger(argOne->IsNumber() || - argOne->IsBoolean()); - return; - } - - CFX_ByteString valueStr = argOne->ToString(); - valueStr.TrimLeft(); - args.GetReturnValue()->SetInteger(!valueStr.IsEmpty()); -} - -// static -void CXFA_FM2JSContext::Oneof(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() < 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Oneof"); - return; - } - - bool bFlags = false; - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::vector<std::unique_ptr<CFXJSE_Value>> parameterValues; - unfoldArgs(pThis, args, ¶meterValues, 1); - for (const auto& value : parameterValues) { - if (simpleValueCompare(pThis, argOne.get(), value.get())) { - bFlags = true; - break; - } - } - - args.GetReturnValue()->SetInteger(bFlags); -} - -// static -void CXFA_FM2JSContext::Within(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Within"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetUndefined(); - return; - } - - std::unique_ptr<CFXJSE_Value> argLow = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> argHigh = GetSimpleValue(pThis, args, 2); - if (argOne->IsNumber()) { - FX_FLOAT oneNumber = ValueToFloat(pThis, argOne.get()); - FX_FLOAT lowNumber = ValueToFloat(pThis, argLow.get()); - FX_FLOAT heightNumber = ValueToFloat(pThis, argHigh.get()); - args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) && - (oneNumber <= heightNumber)); - return; - } - - CFX_ByteString oneString; - CFX_ByteString lowString; - CFX_ByteString heightString; - ValueToUTF8String(argOne.get(), oneString); - ValueToUTF8String(argLow.get(), lowString); - ValueToUTF8String(argHigh.get(), heightString); - args.GetReturnValue()->SetInteger( - (oneString.Compare(lowString.AsStringC()) >= 0) && - (oneString.Compare(heightString.AsStringC()) <= 0)); -} - -// static -void CXFA_FM2JSContext::If(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"If"); - return; - } - - args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean() - ? GetSimpleValue(pThis, args, 1).get() - : GetSimpleValue(pThis, args, 2).get()); -} - -// static -void CXFA_FM2JSContext::Eval(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"Eval"); - return; - } - - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - std::unique_ptr<CFXJSE_Value> scriptValue = GetSimpleValue(pThis, args, 0); - CFX_ByteString utf8ScriptString; - ValueToUTF8String(scriptValue.get(), utf8ScriptString); - if (utf8ScriptString.IsEmpty()) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_WideTextBuf wsJavaScriptBuf; - CFX_WideString wsError; - CXFA_FM2JSContext::Translate( - CFX_WideString::FromUTF8(utf8ScriptString.AsStringC()).AsStringC(), - wsJavaScriptBuf, wsError); - std::unique_ptr<CFXJSE_Context> pNewContext( - CFXJSE_Context::Create(pIsolate, nullptr, nullptr)); - - auto returnValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - pNewContext->ExecuteScript(FX_UTF8Encode(wsJavaScriptBuf.AsStringC()).c_str(), - returnValue.get()); - - args.GetReturnValue()->Assign(returnValue.get()); -} - -// static -void CXFA_FM2JSContext::Ref(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"Ref"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() && - !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) { - pContext->ThrowArgumentMismatchException(); - return; - } - - if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) { - args.GetReturnValue()->Assign(argOne.get()); - return; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> values; - for (int32_t i = 0; i < 3; i++) - values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - int intVal = 3; - if (argOne->IsNull()) { - // TODO(dsinclair): Why is this 4 when the others are all 3? - intVal = 4; - values[2]->SetNull(); - } else if (argOne->IsArray()) { -#ifndef NDEBUG - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectProperty("length", lengthValue.get()); - ASSERT(lengthValue->ToInteger() >= 3); -#endif - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectPropertyByIdx(1, propertyValue.get()); - argOne->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (!propertyValue->IsNull() || jsObjectValue->IsNull()) { - pContext->ThrowArgumentMismatchException(); - return; - } - - values[2]->Assign(jsObjectValue.get()); - } else if (argOne->IsObject()) { - values[2]->Assign(argOne.get()); - } - - values[0]->SetInteger(intVal); - values[1]->SetNull(); - args.GetReturnValue()->SetArray(values); -} - -// static -void CXFA_FM2JSContext::UnitType(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"UnitType"); - return; - } - - std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0); - if (unitspanValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString unitspanString; - ValueToUTF8String(unitspanValue.get(), unitspanString); - if (unitspanString.IsEmpty()) { - args.GetReturnValue()->SetString("in"); - return; - } - - enum XFA_FM2JS_VALUETYPE_ParserStatus { - VALUETYPE_START, - VALUETYPE_HAVEINVALIDCHAR, - VALUETYPE_HAVEDIGIT, - VALUETYPE_HAVEDIGITWHITE, - VALUETYPE_ISCM, - VALUETYPE_ISMM, - VALUETYPE_ISPT, - VALUETYPE_ISMP, - VALUETYPE_ISIN, - }; - unitspanString.MakeLower(); - CFX_WideString wsTypeString = - CFX_WideString::FromUTF8(unitspanString.AsStringC()); - const FX_WCHAR* pData = wsTypeString.c_str(); - int32_t u = 0; - int32_t uLen = wsTypeString.GetLength(); - while (IsWhitespace(pData[u])) - u++; - - XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START; - FX_WCHAR typeChar; - // TODO(dsinclair): Cleanup this parser, figure out what the various checks - // are for. - while (u < uLen) { - typeChar = pData[u]; - if (IsWhitespace(typeChar)) { - if (eParserStatus != VALUETYPE_HAVEDIGIT && - eParserStatus != VALUETYPE_HAVEDIGITWHITE) { - eParserStatus = VALUETYPE_ISIN; - break; - } - eParserStatus = VALUETYPE_HAVEDIGITWHITE; - } else if ((typeChar >= '0' && typeChar <= '9') || typeChar == '-' || - typeChar == '.') { - if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) { - eParserStatus = VALUETYPE_ISIN; - break; - } - eParserStatus = VALUETYPE_HAVEDIGIT; - } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) { - FX_WCHAR nextChar = pData[u + 1]; - if ((eParserStatus == VALUETYPE_START || - eParserStatus == VALUETYPE_HAVEDIGIT || - eParserStatus == VALUETYPE_HAVEDIGITWHITE) && - (nextChar > '9' || nextChar < '0') && nextChar != '.' && - nextChar != '-') { - eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT; - break; - } - eParserStatus = VALUETYPE_HAVEINVALIDCHAR; - } else if (typeChar == 'm' && (u + 1 < uLen)) { - FX_WCHAR nextChar = pData[u + 1]; - if ((eParserStatus == VALUETYPE_START || - eParserStatus == VALUETYPE_HAVEDIGIT || - eParserStatus == VALUETYPE_HAVEDIGITWHITE) && - (nextChar > '9' || nextChar < '0') && nextChar != '.' && - nextChar != '-') { - eParserStatus = VALUETYPE_ISMM; - if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' && - pData[u + 2] == 'l' && pData[u + 3] == 'l' && - pData[u + 4] == 'i' && pData[u + 5] == 'p')) { - eParserStatus = VALUETYPE_ISMP; - } - break; - } - } else { - eParserStatus = VALUETYPE_HAVEINVALIDCHAR; - } - u++; - } - switch (eParserStatus) { - case VALUETYPE_ISCM: - args.GetReturnValue()->SetString("cm"); - break; - case VALUETYPE_ISMM: - args.GetReturnValue()->SetString("mm"); - break; - case VALUETYPE_ISPT: - args.GetReturnValue()->SetString("pt"); - break; - case VALUETYPE_ISMP: - args.GetReturnValue()->SetString("mp"); - break; - default: - args.GetReturnValue()->SetString("in"); - break; - } -} - -// static -void CXFA_FM2JSContext::UnitValue(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"UnitValue"); - return; - } - - std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0); - if (unitspanValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString unitspanString; - ValueToUTF8String(unitspanValue.get(), unitspanString); - const FX_CHAR* pData = unitspanString.c_str(); - if (!pData) { - args.GetReturnValue()->SetInteger(0); - return; - } - - int32_t u = 0; - while (IsWhitespace(pData[u])) - ++u; - - while (u < unitspanString.GetLength()) { - if ((pData[u] > '9' || pData[u] < '0') && pData[u] != '.' && - pData[u] != '-') { - break; - } - ++u; - } - - FX_CHAR* pTemp = nullptr; - FX_DOUBLE dFirstNumber = strtod(pData, &pTemp); - while (IsWhitespace(pData[u])) - ++u; - - int32_t uLen = unitspanString.GetLength(); - CFX_ByteString strFirstUnit; - while (u < uLen) { - if (pData[u] == ' ') - break; - - strFirstUnit += pData[u]; - ++u; - } - strFirstUnit.MakeLower(); - - CFX_ByteString strUnit; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> unitValue = GetSimpleValue(pThis, args, 1); - CFX_ByteString unitTempString; - ValueToUTF8String(unitValue.get(), unitTempString); - const FX_CHAR* pChar = unitTempString.c_str(); - int32_t uVal = 0; - while (IsWhitespace(pChar[uVal])) - ++uVal; - - while (uVal < unitTempString.GetLength()) { - if ((pChar[uVal] > '9' || pChar[uVal] < '0') && pChar[uVal] != '.') { - break; - } - ++uVal; - } - while (IsWhitespace(pChar[uVal])) - ++uVal; - - int32_t uValLen = unitTempString.GetLength(); - while (uVal < uValLen) { - if (pChar[uVal] == ' ') - break; - - strUnit += pChar[uVal]; - ++uVal; - } - strUnit.MakeLower(); - } else { - strUnit = strFirstUnit; - } - - FX_DOUBLE dResult = 0; - if (strFirstUnit == "in" || strFirstUnit == "inches") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber * 25.4; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber * 2.54; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 72; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber / 72000; - else - dResult = dFirstNumber; - } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber / 10; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 25.4 / 72; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber / 25.4 / 72000; - else - dResult = dFirstNumber / 25.4; - } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber * 10; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 2.54 / 72; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber / 2.54 / 72000; - else - dResult = dFirstNumber / 2.54; - } else if (strFirstUnit == "pt" || strFirstUnit == "points") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber / 72 * 25.4; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber / 72 * 2.54; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber * 1000; - else - dResult = dFirstNumber / 72; - } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") { - if (strUnit == "mm" || strUnit == "millimeters") - dResult = dFirstNumber / 72000 * 25.4; - else if (strUnit == "cm" || strUnit == "centimeters") - dResult = dFirstNumber / 72000 * 2.54; - else if (strUnit == "pt" || strUnit == "points") - dResult = dFirstNumber / 1000; - else if (strUnit == "mp" || strUnit == "millipoints") - dResult = dFirstNumber; - else - dResult = dFirstNumber / 72000; - } - args.GetReturnValue()->SetDouble(dResult); -} - -// static -void CXFA_FM2JSContext::At(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"At"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString stringTwo; - ValueToUTF8String(argTwo.get(), stringTwo); - if (stringTwo.IsEmpty()) { - args.GetReturnValue()->SetInteger(1); - return; - } - - CFX_ByteString stringOne; - ValueToUTF8String(argOne.get(), stringOne); - FX_STRSIZE iPosition = stringOne.Find(stringTwo.AsStringC()); - args.GetReturnValue()->SetInteger(iPosition + 1); -} - -// static -void CXFA_FM2JSContext::Concat(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Concat"); - return; - } - - CFX_ByteString resultString; - bool bAllNull = true; - for (int32_t i = 0; i < argc; i++) { - std::unique_ptr<CFXJSE_Value> value = GetSimpleValue(pThis, args, i); - if (ValueIsNull(pThis, value.get())) - continue; - - bAllNull = false; - - CFX_ByteString valueStr; - ValueToUTF8String(value.get(), valueStr); - resultString += valueStr; - } - - if (bAllNull) { - args.GetReturnValue()->SetNull(); - return; - } - - args.GetReturnValue()->SetString(resultString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Decode(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Decode"); - return; - } - - if (argc == 1) { - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString toDecodeString; - ValueToUTF8String(argOne.get(), toDecodeString); - CFX_ByteTextBuf resultBuf; - DecodeURL(toDecodeString.AsStringC(), resultBuf); - args.GetReturnValue()->SetString(resultBuf.AsStringC()); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString toDecodeString; - ValueToUTF8String(argOne.get(), toDecodeString); - - CFX_ByteString identifyString; - ValueToUTF8String(argTwo.get(), identifyString); - - CFX_ByteTextBuf resultBuf; - if (identifyString.EqualNoCase("html")) - DecodeHTML(toDecodeString.AsStringC(), resultBuf); - else if (identifyString.EqualNoCase("xml")) - DecodeXML(toDecodeString.AsStringC(), resultBuf); - else - DecodeURL(toDecodeString.AsStringC(), resultBuf); - - args.GetReturnValue()->SetString(resultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::DecodeURL(const CFX_ByteStringC& szURLString, - CFX_ByteTextBuf& szResultString) { - CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString); - const FX_WCHAR* pData = wsURLString.c_str(); - int32_t i = 0; - CFX_WideTextBuf wsResultBuf; - while (i < wsURLString.GetLength()) { - FX_WCHAR ch = pData[i]; - if ('%' != ch) { - wsResultBuf.AppendChar(ch); - ++i; - continue; - } - - FX_WCHAR chTemp = 0; - int32_t iCount = 0; - while (iCount < 2) { - ++i; - ch = pData[i]; - if (ch <= '9' && ch >= '0') { - // TODO(dsinclair): Premultiply and add rather then scale. - chTemp += (ch - '0') * (!iCount ? 16 : 1); - } else if (ch <= 'F' && ch >= 'A') { - chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1); - } else if (ch <= 'f' && ch >= 'a') { - chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1); - } else { - wsResultBuf.Clear(); - return; - } - ++iCount; - } - wsResultBuf.AppendChar(chTemp); - ++i; - } - wsResultBuf.AppendChar(0); - szResultString.Clear(); - szResultString << FX_UTF8Encode(wsResultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::DecodeHTML(const CFX_ByteStringC& szHTMLString, - CFX_ByteTextBuf& szResultString) { - CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(szHTMLString); - FX_WCHAR strString[9]; - int32_t iStrIndex = 0; - int32_t iLen = wsHTMLString.GetLength(); - int32_t i = 0; - int32_t iCode = 0; - const FX_WCHAR* pData = wsHTMLString.c_str(); - CFX_WideTextBuf wsResultBuf; - while (i < iLen) { - FX_WCHAR ch = pData[i]; - if (ch != '&') { - wsResultBuf.AppendChar(ch); - ++i; - continue; - } - - ++i; - ch = pData[i]; - if (ch == '#') { - ++i; - ch = pData[i]; - if (ch != 'x' && ch != 'X') { - wsResultBuf.Clear(); - return; - } - - ++i; - ch = pData[i]; - if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || - (ch <= 'F' && ch >= 'A')) { - while (ch != ';' && i < iLen) { - if (ch >= '0' && ch <= '9') { - iCode += ch - '0'; - } else if (ch <= 'f' && ch >= 'a') { - iCode += ch - 'a' + 10; - } else if (ch <= 'F' && ch >= 'A') { - iCode += ch - 'A' + 10; - } else { - wsResultBuf.Clear(); - return; - } - ++i; - // TODO(dsinclair): Postmultiply seems wrong, start at zero - // and pre-multiply then can remove the post divide. - iCode *= 16; - ch = pData[i]; - } - iCode /= 16; - } - } else { - while (ch != ';' && i < iLen) { - strString[iStrIndex++] = ch; - ++i; - ch = pData[i]; - } - strString[iStrIndex] = 0; - } - uint32_t iData = 0; - if (HTMLSTR2Code(strString, iData)) { - wsResultBuf.AppendChar((FX_WCHAR)iData); - } else { - wsResultBuf.AppendChar(iCode); - } - iStrIndex = 0; - strString[iStrIndex] = 0; - ++i; - } - wsResultBuf.AppendChar(0); - - szResultString.Clear(); - szResultString << FX_UTF8Encode(wsResultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::DecodeXML(const CFX_ByteStringC& szXMLString, - CFX_ByteTextBuf& szResultString) { - CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString); - FX_WCHAR strString[9]; - int32_t iStrIndex = 0; - int32_t iLen = wsXMLString.GetLength(); - int32_t i = 0; - int32_t iCode = 0; - FX_WCHAR ch = 0; - const FX_WCHAR* pData = wsXMLString.c_str(); - CFX_WideTextBuf wsXMLBuf; - while (i < iLen) { - ch = pData[i]; - if (ch != '&') { - wsXMLBuf.AppendChar(ch); - ++i; - continue; - } - - // TODO(dsinclair): This is very similar to DecodeHTML, can they be - // combined? - ++i; - ch = pData[i]; - if (ch == '#') { - ++i; - ch = pData[i]; - if (ch != 'x' && ch != 'X') { - wsXMLBuf.Clear(); - return; - } - - ++i; - ch = pData[i]; - if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') || - (ch <= 'F' && ch >= 'A')) { - while (ch != ';') { - if (ch >= '0' && ch <= '9') { - iCode += ch - '0'; - } else if (ch <= 'f' && ch >= 'a') { - iCode += ch - 'a' + 10; - } else if (ch <= 'F' && ch >= 'A') { - iCode += ch - 'A' + 10; - } else { - wsXMLBuf.Clear(); - return; - } - ++i; - iCode *= 16; - ch = pData[i]; - } - iCode /= 16; - } - } else { - while (ch != ';' && i < iLen) { - strString[iStrIndex++] = ch; - ++i; - ch = pData[i]; - } - strString[iStrIndex] = 0; - } - - const FX_WCHAR* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"}; - int32_t iIndex = 0; - while (iIndex < 5) { - if (FXSYS_memcmp(strString, strName[iIndex], - FXSYS_wcslen(strName[iIndex])) == 0) { - break; - } - ++iIndex; - } - switch (iIndex) { - case 0: - wsXMLBuf.AppendChar('"'); - break; - case 1: - wsXMLBuf.AppendChar('&'); - break; - case 2: - wsXMLBuf.AppendChar('\''); - break; - case 3: - wsXMLBuf.AppendChar('<'); - break; - case 4: - wsXMLBuf.AppendChar('>'); - break; - default: - wsXMLBuf.AppendChar(iCode); - break; - } - iStrIndex = 0; - strString[iStrIndex] = 0; - ++i; - iCode = 0; - } - wsXMLBuf.AppendChar(0); - szResultString.Clear(); - szResultString << FX_UTF8Encode(wsXMLBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Encode(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Encode"); - return; - } - - if (argc == 1) { - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString toEncodeString; - ValueToUTF8String(argOne.get(), toEncodeString); - CFX_ByteTextBuf resultBuf; - EncodeURL(toEncodeString.AsStringC(), resultBuf); - args.GetReturnValue()->SetString(resultBuf.AsStringC()); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString toEncodeString; - ValueToUTF8String(argOne.get(), toEncodeString); - CFX_ByteString identifyString; - ValueToUTF8String(argTwo.get(), identifyString); - CFX_ByteTextBuf resultBuf; - if (identifyString.EqualNoCase("html")) - EncodeHTML(toEncodeString.AsStringC(), resultBuf); - else if (identifyString.EqualNoCase("xml")) - EncodeXML(toEncodeString.AsStringC(), resultBuf); - else - EncodeURL(toEncodeString.AsStringC(), resultBuf); - - args.GetReturnValue()->SetString(resultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::EncodeURL(const CFX_ByteStringC& szURLString, - CFX_ByteTextBuf& szResultBuf) { - CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString); - CFX_WideTextBuf wsResultBuf; - FX_WCHAR strEncode[4]; - strEncode[0] = '%'; - strEncode[3] = 0; - FX_WCHAR strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}', - '|', '\\', '^', '~', '[', ']', '`'}; - FX_WCHAR strReserved[] = {';', '/', '?', ':', '@', '=', '&'}; - FX_WCHAR strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','}; - const FX_WCHAR* strCode = L"0123456789abcdef"; - for (int32_t u = 0; u < wsURLString.GetLength(); ++u) { - FX_WCHAR ch = wsURLString.GetAt(u); - int32_t i = 0; - int32_t iCount = FX_ArraySize(strUnsafe); - while (i < iCount) { - if (ch == strUnsafe[i]) { - int32_t iIndex = ch / 16; - strEncode[1] = strCode[iIndex]; - strEncode[2] = strCode[ch - iIndex * 16]; - wsResultBuf << strEncode; - break; - } - ++i; - } - if (i < iCount) - continue; - - i = 0; - iCount = FX_ArraySize(strReserved); - while (i < iCount) { - if (ch == strReserved[i]) { - int32_t iIndex = ch / 16; - strEncode[1] = strCode[iIndex]; - strEncode[2] = strCode[ch - iIndex * 16]; - wsResultBuf << strEncode; - break; - } - ++i; - } - if (i < iCount) - continue; - - i = 0; - iCount = FX_ArraySize(strSpecial); - while (i < iCount) { - if (ch == strSpecial[i]) { - wsResultBuf.AppendChar(ch); - break; - } - ++i; - } - if (i < iCount) - continue; - - if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) { - int32_t iIndex = ch / 16; - strEncode[1] = strCode[iIndex]; - strEncode[2] = strCode[ch - iIndex * 16]; - wsResultBuf << strEncode; - } else if (ch >= 0x20 && ch <= 0x7e) { - wsResultBuf.AppendChar(ch); - } else { - const FX_WCHAR iRadix = 16; - CFX_WideString strTmp; - while (ch >= iRadix) { - FX_WCHAR tmp = strCode[ch % iRadix]; - ch /= iRadix; - strTmp += tmp; - } - strTmp += strCode[ch]; - int32_t iLen = strTmp.GetLength(); - if (iLen < 2) - break; - - int32_t iIndex = 0; - if (iLen % 2 != 0) { - strEncode[1] = '0'; - strEncode[2] = strTmp.GetAt(iLen - 1); - iIndex = iLen - 2; - } else { - strEncode[1] = strTmp.GetAt(iLen - 1); - strEncode[2] = strTmp.GetAt(iLen - 2); - iIndex = iLen - 3; - } - wsResultBuf << strEncode; - while (iIndex > 0) { - strEncode[1] = strTmp.GetAt(iIndex); - strEncode[2] = strTmp.GetAt(iIndex - 1); - iIndex -= 2; - wsResultBuf << strEncode; - } - } - } - wsResultBuf.AppendChar(0); - szResultBuf.Clear(); - szResultBuf << FX_UTF8Encode(wsResultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::EncodeHTML(const CFX_ByteStringC& szHTMLString, - CFX_ByteTextBuf& szResultBuf) { - CFX_ByteString str = szHTMLString.c_str(); - CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(str.AsStringC()); - const FX_WCHAR* strCode = L"0123456789abcdef"; - FX_WCHAR strEncode[9]; - strEncode[0] = '&'; - strEncode[1] = '#'; - strEncode[2] = 'x'; - strEncode[5] = ';'; - strEncode[6] = 0; - strEncode[7] = ';'; - strEncode[8] = 0; - CFX_WideTextBuf wsResultBuf; - int32_t iLen = wsHTMLString.GetLength(); - int32_t i = 0; - const FX_WCHAR* pData = wsHTMLString.c_str(); - while (i < iLen) { - uint32_t ch = pData[i]; - CFX_WideString htmlReserve; - if (HTMLCode2STR(ch, htmlReserve)) { - wsResultBuf.AppendChar(L'&'); - wsResultBuf << htmlReserve; - wsResultBuf.AppendChar(L';'); - } else if (ch >= 32 && ch <= 126) { - wsResultBuf.AppendChar((FX_WCHAR)ch); - } else if (ch < 256) { - int32_t iIndex = ch / 16; - strEncode[3] = strCode[iIndex]; - strEncode[4] = strCode[ch - iIndex * 16]; - strEncode[5] = ';'; - strEncode[6] = 0; - wsResultBuf << strEncode; - } else { - int32_t iBigByte = ch / 256; - int32_t iLittleByte = ch % 256; - strEncode[3] = strCode[iBigByte / 16]; - strEncode[4] = strCode[iBigByte % 16]; - strEncode[5] = strCode[iLittleByte / 16]; - strEncode[6] = strCode[iLittleByte % 16]; - wsResultBuf << strEncode; - } - ++i; - } - wsResultBuf.AppendChar(0); - szResultBuf.Clear(); - szResultBuf << FX_UTF8Encode(wsResultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::EncodeXML(const CFX_ByteStringC& szXMLString, - CFX_ByteTextBuf& szResultBuf) { - CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString); - CFX_WideTextBuf wsResultBuf; - FX_WCHAR strEncode[9]; - strEncode[0] = '&'; - strEncode[1] = '#'; - strEncode[2] = 'x'; - strEncode[5] = ';'; - strEncode[6] = 0; - strEncode[7] = ';'; - strEncode[8] = 0; - const FX_WCHAR* strCode = L"0123456789abcdef"; - const FX_WCHAR* pData = wsXMLString.c_str(); - for (int32_t u = 0; u < wsXMLString.GetLength(); ++u) { - FX_WCHAR ch = pData[u]; - switch (ch) { - case '"': - wsResultBuf.AppendChar('&'); - wsResultBuf << CFX_WideStringC(L"quot"); - wsResultBuf.AppendChar(';'); - break; - case '&': - wsResultBuf.AppendChar('&'); - wsResultBuf << CFX_WideStringC(L"amp"); - wsResultBuf.AppendChar(';'); - break; - case '\'': - wsResultBuf.AppendChar('&'); - wsResultBuf << CFX_WideStringC(L"apos"); - wsResultBuf.AppendChar(';'); - break; - case '<': - wsResultBuf.AppendChar('&'); - wsResultBuf << CFX_WideStringC(L"lt"); - wsResultBuf.AppendChar(';'); - break; - case '>': - wsResultBuf.AppendChar('&'); - wsResultBuf << CFX_WideStringC(L"gt"); - wsResultBuf.AppendChar(';'); - break; - default: { - if (ch >= 32 && ch <= 126) { - wsResultBuf.AppendChar(ch); - } else if (ch < 256) { - int32_t iIndex = ch / 16; - strEncode[3] = strCode[iIndex]; - strEncode[4] = strCode[ch - iIndex * 16]; - strEncode[5] = ';'; - strEncode[6] = 0; - wsResultBuf << strEncode; - } else { - int32_t iBigByte = ch / 256; - int32_t iLittleByte = ch % 256; - strEncode[3] = strCode[iBigByte / 16]; - strEncode[4] = strCode[iBigByte % 16]; - strEncode[5] = strCode[iLittleByte / 16]; - strEncode[6] = strCode[iLittleByte % 16]; - wsResultBuf << strEncode; - } - break; - } - } - } - wsResultBuf.AppendChar(0); - szResultBuf.Clear(); - szResultBuf << FX_UTF8Encode(wsResultBuf.AsStringC()); -} - -// static -bool CXFA_FM2JSContext::HTMLSTR2Code(const CFX_WideStringC& pData, - uint32_t& iCode) { - uint32_t uHash = FX_HashCode_GetW(pData, false); - int32_t iStart = 0; - int32_t iEnd = FX_ArraySize(reservesForDecode) - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - XFA_FMHtmlHashedReserveCode htmlhashedreservecode = reservesForDecode[iMid]; - if (uHash == htmlhashedreservecode.m_uHash) { - iCode = htmlhashedreservecode.m_uCode; - return true; - } - - if (uHash < htmlhashedreservecode.m_uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return false; -} - -// static -bool CXFA_FM2JSContext::HTMLCode2STR(uint32_t iCode, - CFX_WideString& wsHTMLReserve) { - int32_t iStart = 0; - int32_t iEnd = FX_ArraySize(reservesForEncode) - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - XFA_FMHtmlReserveCode htmlreservecode = reservesForEncode[iMid]; - if (iCode == htmlreservecode.m_uCode) { - wsHTMLReserve = htmlreservecode.m_htmlReserve; - return true; - } - - if (iCode < htmlreservecode.m_uCode) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return false; -} - -// static -void CXFA_FM2JSContext::Format(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() < 2) { - pContext->ThrowParamCountMismatchException(L"Format"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - CFX_ByteString szPattern; - ValueToUTF8String(argOne.get(), szPattern); - - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - CFX_ByteString szValue; - ValueToUTF8String(argTwo.get(), szValue); - - CXFA_Document* pDoc = pContext->GetDocument(); - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - IFX_Locale* pLocale = widgetData.GetLocal(); - uint32_t patternType; - CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC()); - CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC()); - if (!PatternStringType(szPattern.AsStringC(), patternType)) { - switch (patternType) { - case XFA_VT_DATETIME: { - FX_STRSIZE iTChar = wsPattern.Find(L'T'); - CFX_WideString wsDatePattern(L"date{"); - wsDatePattern += wsPattern.Left(iTChar) + L"} "; - - CFX_WideString wsTimePattern(L"time{"); - wsTimePattern += wsPattern.Mid(iTChar + 1) + L"}"; - wsPattern = wsDatePattern + wsTimePattern; - } break; - case XFA_VT_DATE: { - wsPattern = L"date{" + wsPattern + L"}"; - } break; - case XFA_VT_TIME: { - wsPattern = L"time{" + wsPattern + L"}"; - } break; - case XFA_VT_TEXT: { - wsPattern = L"text{" + wsPattern + L"}"; - } break; - case XFA_VT_FLOAT: { - wsPattern = L"num{" + wsPattern + L"}"; - } break; - default: { - CFX_WideString wsTestPattern; - wsTestPattern = L"num{" + wsPattern + L"}"; - CXFA_LocaleValue tempLocaleValue(XFA_VT_FLOAT, wsValue, wsTestPattern, - pLocale, pMgr); - if (tempLocaleValue.IsValid()) { - wsPattern = wsTestPattern; - patternType = XFA_VT_FLOAT; - } else { - wsTestPattern = L"text{" + wsPattern + L"}"; - wsPattern = wsTestPattern; - patternType = XFA_VT_TEXT; - } - } break; - } - } - CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, pMgr); - CFX_WideString wsRet; - if (!localeValue.FormatPatterns(wsRet, wsPattern, pLocale, - XFA_VALUEPICTURE_Display)) { - args.GetReturnValue()->SetString(""); - return; - } - - args.GetReturnValue()->SetString(wsRet.UTF8Encode().AsStringC()); -} - -// static -void CXFA_FM2JSContext::Left(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Left"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - if ((ValueIsNull(pThis, argOne.get())) || - (ValueIsNull(pThis, argTwo.get()))) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString sourceString; - ValueToUTF8String(argOne.get(), sourceString); - int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get())); - args.GetReturnValue()->SetString(sourceString.Left(count).AsStringC()); -} - -// static -void CXFA_FM2JSContext::Len(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Len"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString sourceString; - ValueToUTF8String(argOne.get(), sourceString); - args.GetReturnValue()->SetInteger(sourceString.GetLength()); -} - -// static -void CXFA_FM2JSContext::Lower(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Lower"); - return; - } - - CFX_ByteString argString; - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - ValueToUTF8String(argOne.get(), argString); - CFX_WideTextBuf lowStringBuf; - CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC()); - const FX_WCHAR* pData = wsArgString.c_str(); - int32_t i = 0; - while (i < argString.GetLength()) { - int32_t ch = pData[i]; - if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE)) - ch += 32; - else if (ch == 0x100 || ch == 0x102 || ch == 0x104) - ch += 1; - - lowStringBuf.AppendChar(ch); - ++i; - } - lowStringBuf.AppendChar(0); - - args.GetReturnValue()->SetString( - FX_UTF8Encode(lowStringBuf.AsStringC()).AsStringC()); -} - -// static -void CXFA_FM2JSContext::Ltrim(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Ltrim"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString sourceString; - ValueToUTF8String(argOne.get(), sourceString); - sourceString.TrimLeft(); - args.GetReturnValue()->SetString(sourceString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Parse(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 2) { - pContext->ThrowParamCountMismatchException(L"Parse"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - if (ValueIsNull(pThis, argTwo.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString szPattern; - ValueToUTF8String(argOne.get(), szPattern); - CFX_ByteString szValue; - ValueToUTF8String(argTwo.get(), szValue); - - CXFA_Document* pDoc = pContext->GetDocument(); - CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr(); - CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject()); - ASSERT(pThisNode); - - CXFA_WidgetData widgetData(pThisNode); - IFX_Locale* pLocale = widgetData.GetLocal(); - CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC()); - CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC()); - uint32_t patternType; - if (PatternStringType(szPattern.AsStringC(), patternType)) { - CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, - pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetString( - localeValue.GetValue().UTF8Encode().AsStringC()); - return; - } - - switch (patternType) { - case XFA_VT_DATETIME: { - FX_STRSIZE iTChar = wsPattern.Find(L'T'); - CFX_WideString wsDatePattern(L"date{" + wsPattern.Left(iTChar) + L"} "); - CFX_WideString wsTimePattern(L"time{" + wsPattern.Mid(iTChar + 1) + L"}"); - wsPattern = wsDatePattern + wsTimePattern; - CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, - pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetString( - localeValue.GetValue().UTF8Encode().AsStringC()); - return; - } - case XFA_VT_DATE: { - wsPattern = L"date{" + wsPattern + L"}"; - CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, - pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetString( - localeValue.GetValue().UTF8Encode().AsStringC()); - return; - } - case XFA_VT_TIME: { - wsPattern = L"time{" + wsPattern + L"}"; - CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, - pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetString( - localeValue.GetValue().UTF8Encode().AsStringC()); - return; - } - case XFA_VT_TEXT: { - wsPattern = L"text{" + wsPattern + L"}"; - CXFA_LocaleValue localeValue(XFA_VT_TEXT, wsValue, wsPattern, pLocale, - pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetString( - localeValue.GetValue().UTF8Encode().AsStringC()); - return; - } - case XFA_VT_FLOAT: { - wsPattern = L"num{" + wsPattern + L"}"; - CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsPattern, pLocale, - pMgr); - if (!localeValue.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum()); - return; - } - default: { - CFX_WideString wsTestPattern; - wsTestPattern = L"num{" + wsPattern + L"}"; - CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsTestPattern, - pLocale, pMgr); - if (localeValue.IsValid()) { - args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum()); - return; - } - - wsTestPattern = L"text{" + wsPattern + L"}"; - CXFA_LocaleValue localeValue2(XFA_VT_TEXT, wsValue, wsTestPattern, - pLocale, pMgr); - if (!localeValue2.IsValid()) { - args.GetReturnValue()->SetString(""); - return; - } - args.GetReturnValue()->SetString( - localeValue2.GetValue().UTF8Encode().AsStringC()); - return; - } - } -} - -// static -void CXFA_FM2JSContext::Replace(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 2 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Replace"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - CFX_ByteString oneString; - CFX_ByteString twoString; - if (!ValueIsNull(pThis, argOne.get()) && !ValueIsNull(pThis, argTwo.get())) { - ValueToUTF8String(argOne.get(), oneString); - ValueToUTF8String(argTwo.get(), twoString); - } - - CFX_ByteString threeString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - ValueToUTF8String(argThree.get(), threeString); - } - - int32_t iFindLen = twoString.GetLength(); - CFX_ByteTextBuf resultString; - int32_t iFindIndex = 0; - for (int32_t u = 0; u < oneString.GetLength(); ++u) { - uint8_t ch = oneString.GetAt(u); - if (ch != twoString.GetAt(iFindIndex)) { - resultString.AppendChar(ch); - continue; - } - - int32_t iTemp = u + 1; - ++iFindIndex; - while (iFindIndex < iFindLen) { - uint8_t chTemp = oneString.GetAt(iTemp); - if (chTemp != twoString.GetAt(iFindIndex)) { - iFindIndex = 0; - break; - } - - ++iTemp; - ++iFindIndex; - } - if (iFindIndex == iFindLen) { - resultString << threeString.AsStringC(); - u += iFindLen - 1; - iFindIndex = 0; - } else { - resultString.AppendChar(ch); - } - } - resultString.AppendChar(0); - args.GetReturnValue()->SetString(resultString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Right(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Right"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - if ((ValueIsNull(pThis, argOne.get())) || - (ValueIsNull(pThis, argTwo.get()))) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString sourceString; - ValueToUTF8String(argOne.get(), sourceString); - int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get())); - args.GetReturnValue()->SetString(sourceString.Right(count).AsStringC()); -} - -// static -void CXFA_FM2JSContext::Rtrim(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Rtrim"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString sourceString; - ValueToUTF8String(argOne.get(), sourceString); - sourceString.TrimRight(); - args.GetReturnValue()->SetString(sourceString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Space(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Space"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - int32_t count = std::max(0, ValueToInteger(pThis, argOne.get())); - CFX_ByteTextBuf spaceString; - int32_t index = 0; - while (index < count) { - spaceString.AppendByte(' '); - index++; - } - spaceString.AppendByte(0); - args.GetReturnValue()->SetString(spaceString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Str(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Str"); - return; - } - - std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0); - if (numberValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get()); - - int32_t iWidth = 10; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> widthValue = GetSimpleValue(pThis, args, 1); - iWidth = static_cast<int32_t>(ValueToFloat(pThis, widthValue.get())); - } - - int32_t iPrecision = 0; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> precisionValue = - GetSimpleValue(pThis, args, 2); - iPrecision = std::max( - 0, static_cast<int32_t>(ValueToFloat(pThis, precisionValue.get()))); - } - - CFX_ByteString numberString; - CFX_ByteString formatStr = "%"; - if (iPrecision) { - formatStr += "."; - formatStr += CFX_ByteString::FormatInteger(iPrecision); - } - formatStr += "f"; - numberString.Format(formatStr.c_str(), fNumber); - - const FX_CHAR* pData = numberString.c_str(); - int32_t iLength = numberString.GetLength(); - int32_t u = 0; - while (u < iLength) { - if (pData[u] == '.') - break; - - ++u; - } - - CFX_ByteTextBuf resultBuf; - if (u > iWidth || (iPrecision + u) >= iWidth) { - int32_t i = 0; - while (i < iWidth) { - resultBuf.AppendChar('*'); - ++i; - } - resultBuf.AppendChar(0); - args.GetReturnValue()->SetString(resultBuf.AsStringC()); - return; - } - - if (u == iLength) { - if (iLength > iWidth) { - int32_t i = 0; - while (i < iWidth) { - resultBuf.AppendChar('*'); - ++i; - } - } else { - int32_t i = 0; - while (i < iWidth - iLength) { - resultBuf.AppendChar(' '); - ++i; - } - resultBuf << pData; - } - args.GetReturnValue()->SetString(resultBuf.AsStringC()); - return; - } - - int32_t iLeavingSpace = iWidth - u - iPrecision; - if (iPrecision != 0) - iLeavingSpace--; - - int32_t i = 0; - while (i < iLeavingSpace) { - resultBuf.AppendChar(' '); - ++i; - } - i = 0; - while (i < u) { - resultBuf.AppendChar(pData[i]); - ++i; - } - if (iPrecision != 0) - resultBuf.AppendChar('.'); - - u++; - i = 0; - while (u < iLength) { - if (i >= iPrecision) - break; - - resultBuf.AppendChar(pData[u]); - ++i; - ++u; - } - while (i < iPrecision) { - resultBuf.AppendChar('0'); - ++i; - } - resultBuf.AppendChar(0); - args.GetReturnValue()->SetString(resultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Stuff(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 3 || argc > 4) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Stuff"); - return; - } - - CFX_ByteString sourceString; - CFX_ByteString insertString; - int32_t iLength = 0; - int32_t iStart = 0; - int32_t iDelete = 0; - std::unique_ptr<CFXJSE_Value> sourceValue = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> deleteValue = GetSimpleValue(pThis, args, 2); - if (!sourceValue->IsNull() && !startValue->IsNull() && - !deleteValue->IsNull()) { - ValueToUTF8String(sourceValue.get(), sourceString); - iLength = sourceString.GetLength(); - iStart = std::min(iLength, std::max(1, static_cast<int32_t>(ValueToFloat( - pThis, startValue.get())))); - iDelete = std::max( - 0, static_cast<int32_t>(ValueToFloat(pThis, deleteValue.get()))); - } - - if (argc > 3) { - std::unique_ptr<CFXJSE_Value> insertValue = GetSimpleValue(pThis, args, 3); - ValueToUTF8String(insertValue.get(), insertString); - } - - iStart -= 1; - CFX_ByteTextBuf resultString; - int32_t i = 0; - while (i < iStart) { - resultString.AppendChar(sourceString.GetAt(i)); - ++i; - } - resultString << insertString.AsStringC(); - i = iStart + iDelete; - while (i < iLength) { - resultString.AppendChar(sourceString.GetAt(i)); - ++i; - } - resultString.AppendChar(0); - args.GetReturnValue()->SetString(resultString.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Substr(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Substr"); - return; - } - - std::unique_ptr<CFXJSE_Value> stringValue = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1); - std::unique_ptr<CFXJSE_Value> endValue = GetSimpleValue(pThis, args, 2); - if (ValueIsNull(pThis, stringValue.get()) || - (ValueIsNull(pThis, startValue.get())) || - (ValueIsNull(pThis, endValue.get()))) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString szSourceStr; - int32_t iStart = 0; - int32_t iCount = 0; - ValueToUTF8String(stringValue.get(), szSourceStr); - int32_t iLength = szSourceStr.GetLength(); - if (iLength == 0) { - args.GetReturnValue()->SetString(""); - return; - } - - iStart = std::min( - iLength, - std::max(1, static_cast<int32_t>(ValueToFloat(pThis, startValue.get())))); - iCount = - std::max(0, static_cast<int32_t>(ValueToFloat(pThis, endValue.get()))); - - iStart -= 1; - args.GetReturnValue()->SetString(szSourceStr.Mid(iStart, iCount).AsStringC()); -} - -// static -void CXFA_FM2JSContext::Uuid(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 0 || argc > 1) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Uuid"); - return; - } - - int32_t iNum = 0; - if (argc > 0) { - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - iNum = static_cast<int32_t>(ValueToFloat(pThis, argOne.get())); - } - FX_GUID guid; - FX_GUID_CreateV4(&guid); - - CFX_ByteString bsUId; - FX_GUID_ToString(&guid, bsUId, !!iNum); - args.GetReturnValue()->SetString(bsUId.AsStringC()); -} - -// static -void CXFA_FM2JSContext::Upper(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 2) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"Upper"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (ValueIsNull(pThis, argOne.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - CFX_ByteString argString; - ValueToUTF8String(argOne.get(), argString); - - CFX_WideTextBuf upperStringBuf; - CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC()); - const FX_WCHAR* pData = wsArgString.c_str(); - int32_t i = 0; - while (i < wsArgString.GetLength()) { - int32_t ch = pData[i]; - if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE)) - ch -= 32; - else if (ch == 0x101 || ch == 0x103 || ch == 0x105) - ch -= 1; - - upperStringBuf.AppendChar(ch); - ++i; - } - upperStringBuf.AppendChar(0); - - args.GetReturnValue()->SetString( - FX_UTF8Encode(upperStringBuf.AsStringC()).AsStringC()); -} - -// static -void CXFA_FM2JSContext::WordNum(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - int32_t argc = args.GetLength(); - if (argc < 1 || argc > 3) { - ToJSContext(pThis, nullptr)->ThrowParamCountMismatchException(L"WordNum"); - return; - } - - std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0); - if (numberValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get()); - - int32_t iIdentifier = 0; - if (argc > 1) { - std::unique_ptr<CFXJSE_Value> identifierValue = - GetSimpleValue(pThis, args, 1); - if (identifierValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - iIdentifier = - static_cast<int32_t>(ValueToFloat(pThis, identifierValue.get())); - } - - CFX_ByteString localeString; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> localeValue = GetSimpleValue(pThis, args, 2); - if (localeValue->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - ValueToUTF8String(localeValue.get(), localeString); - } - - if (fNumber < 0.0f || fNumber > 922337203685477550.0f) { - args.GetReturnValue()->SetString("*"); - return; - } - - CFX_ByteString numberString; - numberString.Format("%.2f", fNumber); - - CFX_ByteTextBuf resultBuf; - WordUS(numberString.AsStringC(), iIdentifier, resultBuf); - args.GetReturnValue()->SetString(resultBuf.AsStringC()); -} - -// static -void CXFA_FM2JSContext::TrillionUS(const CFX_ByteStringC& szData, - CFX_ByteTextBuf& strBuf) { - CFX_ByteStringC pUnits[] = {"zero", "one", "two", "three", "four", - "five", "six", "seven", "eight", "nine"}; - CFX_ByteStringC pCapUnits[] = {"Zero", "One", "Two", "Three", "Four", - "Five", "Six", "Seven", "Eight", "Nine"}; - CFX_ByteStringC pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen", - "Fourteen", "Fifteen", "Sixteen", "Seventeen", - "Eighteen", "Nineteen"}; - CFX_ByteStringC pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty", - "Sixty", "Seventy", "Eighty", "Ninety"}; - CFX_ByteStringC pComm[] = {" Hundred ", " Thousand ", " Million ", - " Billion ", "Trillion"}; - const FX_CHAR* pData = szData.c_str(); - int32_t iLength = szData.GetLength(); - int32_t iComm = 0; - if (iLength > 12) - iComm = 4; - else if (iLength > 9) - iComm = 3; - else if (iLength > 6) - iComm = 2; - else if (iLength > 3) - iComm = 1; - - int32_t iFirstCount = iLength % 3; - if (iFirstCount == 0) - iFirstCount = 3; - - int32_t iIndex = 0; - if (iFirstCount == 3) { - if (pData[iIndex] != '0') { - strBuf << pCapUnits[pData[iIndex] - '0']; - strBuf << pComm[0]; - } - if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } else { - if (pData[iIndex + 1] > '1') { - strBuf << pLastTens[pData[iIndex + 1] - '2']; - strBuf << "-"; - strBuf << pUnits[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '1') { - strBuf << pTens[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } - } - iIndex += 3; - } else if (iFirstCount == 2) { - if (pData[iIndex] == '0') { - strBuf << pCapUnits[pData[iIndex + 1] - '0']; - } else { - if (pData[iIndex] > '1') { - strBuf << pLastTens[pData[iIndex] - '2']; - strBuf << "-"; - strBuf << pUnits[pData[iIndex + 1] - '0']; - } else if (pData[iIndex] == '1') { - strBuf << pTens[pData[iIndex + 1] - '0']; - } else if (pData[iIndex] == '0') { - strBuf << pCapUnits[pData[iIndex + 1] - '0']; - } - } - iIndex += 2; - } else if (iFirstCount == 1) { - strBuf << pCapUnits[pData[iIndex] - '0']; - iIndex += 1; - } - if (iLength > 3 && iFirstCount > 0) { - strBuf << pComm[iComm]; - --iComm; - } - while (iIndex < iLength) { - if (pData[iIndex] != '0') { - strBuf << pCapUnits[pData[iIndex] - '0']; - strBuf << pComm[0]; - } - if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } else { - if (pData[iIndex + 1] > '1') { - strBuf << pLastTens[pData[iIndex + 1] - '2']; - strBuf << "-"; - strBuf << pUnits[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '1') { - strBuf << pTens[pData[iIndex + 2] - '0']; - } else if (pData[iIndex + 1] == '0') { - strBuf << pCapUnits[pData[iIndex + 2] - '0']; - } - } - if (iIndex < iLength - 3) { - strBuf << pComm[iComm]; - --iComm; - } - iIndex += 3; - } -} - -// static -void CXFA_FM2JSContext::WordUS(const CFX_ByteStringC& szData, - int32_t iStyle, - CFX_ByteTextBuf& strBuf) { - const FX_CHAR* pData = szData.c_str(); - int32_t iLength = szData.GetLength(); - if (iStyle < 0 || iStyle > 2) { - return; - } - - int32_t iIndex = 0; - while (iIndex < iLength) { - if (pData[iIndex] == '.') - break; - ++iIndex; - } - int32_t iInteger = iIndex; - iIndex = 0; - while (iIndex < iInteger) { - int32_t iCount = (iInteger - iIndex) % 12; - if (!iCount && iInteger - iIndex > 0) - iCount = 12; - - TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf); - iIndex += iCount; - if (iIndex < iInteger) - strBuf << " Trillion "; - } - - if (iStyle > 0) - strBuf << " Dollars"; - - if (iStyle > 1 && iInteger < iLength) { - strBuf << " And "; - iIndex = iInteger + 1; - while (iIndex < iLength) { - int32_t iCount = (iLength - iIndex) % 12; - if (!iCount && iLength - iIndex > 0) - iCount = 12; - - TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf); - iIndex += iCount; - if (iIndex < iLength) - strBuf << " Trillion "; - } - strBuf << " Cents"; - } -} - -// static -void CXFA_FM2JSContext::Get(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"Get"); - return; - } - - CXFA_Document* pDoc = pContext->GetDocument(); - if (!pDoc) - return; - - IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider(); - if (!pAppProvider) - return; - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - CFX_ByteString urlString; - ValueToUTF8String(argOne.get(), urlString); - CFX_RetainPtr<IFX_SeekableReadStream> pFile = pAppProvider->DownloadURL( - CFX_WideString::FromUTF8(urlString.AsStringC())); - if (!pFile) - return; - - int32_t size = pFile->GetSize(); - std::vector<uint8_t> pData(size); - pFile->ReadBlock(pData.data(), size); - args.GetReturnValue()->SetString(CFX_ByteStringC(pData.data(), size)); -} - -// static -void CXFA_FM2JSContext::Post(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - int32_t argc = args.GetLength(); - if (argc < 2 || argc > 5) { - pContext->ThrowParamCountMismatchException(L"Post"); - return; - } - - CXFA_Document* pDoc = pContext->GetDocument(); - if (!pDoc) - return; - - IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider(); - if (!pAppProvider) - return; - - CFX_ByteString bsURL; - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - ValueToUTF8String(argOne.get(), bsURL); - - CFX_ByteString bsData; - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - ValueToUTF8String(argTwo.get(), bsData); - - CFX_ByteString bsContentType; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - ValueToUTF8String(argThree.get(), bsContentType); - } - - CFX_ByteString bsEncode; - if (argc > 3) { - std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3); - ValueToUTF8String(argFour.get(), bsEncode); - } - - CFX_ByteString bsHeader; - if (argc > 4) { - std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4); - ValueToUTF8String(argFive.get(), bsHeader); - } - - CFX_WideString decodedResponse; - if (!pAppProvider->PostRequestURL( - CFX_WideString::FromUTF8(bsURL.AsStringC()), - CFX_WideString::FromUTF8(bsData.AsStringC()), - CFX_WideString::FromUTF8(bsContentType.AsStringC()), - CFX_WideString::FromUTF8(bsEncode.AsStringC()), - CFX_WideString::FromUTF8(bsHeader.AsStringC()), decodedResponse)) { - pContext->ThrowServerDeniedException(); - return; - } - args.GetReturnValue()->SetString(decodedResponse.UTF8Encode().AsStringC()); -} - -// static -void CXFA_FM2JSContext::Put(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - int32_t argc = args.GetLength(); - if (argc < 2 || argc > 3) { - pContext->ThrowParamCountMismatchException(L"Put"); - return; - } - - CXFA_Document* pDoc = pContext->GetDocument(); - if (!pDoc) - return; - - IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider(); - if (!pAppProvider) - return; - - CFX_ByteString bsURL; - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - ValueToUTF8String(argOne.get(), bsURL); - - CFX_ByteString bsData; - std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1); - ValueToUTF8String(argTwo.get(), bsData); - - CFX_ByteString bsEncode; - if (argc > 2) { - std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2); - ValueToUTF8String(argThree.get(), bsEncode); - } - - if (!pAppProvider->PutRequestURL( - CFX_WideString::FromUTF8(bsURL.AsStringC()), - CFX_WideString::FromUTF8(bsData.AsStringC()), - CFX_WideString::FromUTF8(bsEncode.AsStringC()))) { - pContext->ThrowServerDeniedException(); - return; - } - - args.GetReturnValue()->SetString(""); -} - -// static -void CXFA_FM2JSContext::assign_value_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 2) { - pContext->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> lValue = args.GetValue(0); - std::unique_ptr<CFXJSE_Value> rValue = GetSimpleValue(pThis, args, 1); - if (lValue->IsArray()) { - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - auto leftLengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - lValue->GetObjectProperty("length", leftLengthValue.get()); - int32_t iLeftLength = leftLengthValue->ToInteger(); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - lValue->GetObjectPropertyByIdx(1, propertyValue.get()); - if (propertyValue->IsNull()) { - for (int32_t i = 2; i < iLeftLength; i++) { - lValue->GetObjectPropertyByIdx(i, jsObjectValue.get()); - if (!SetObjectDefaultValue(jsObjectValue.get(), rValue.get())) { - pContext->ThrowNoDefaultPropertyException(szFuncName); - return; - } - } - } else { - for (int32_t i = 2; i < iLeftLength; i++) { - lValue->GetObjectPropertyByIdx(i, jsObjectValue.get()); - jsObjectValue->SetObjectProperty(propertyValue->ToString().AsStringC(), - rValue.get()); - } - } - } else if (lValue->IsObject()) { - if (!SetObjectDefaultValue(lValue.get(), rValue.get())) { - pContext->ThrowNoDefaultPropertyException(szFuncName); - return; - } - } - args.GetReturnValue()->Assign(rValue.get()); -} - -// static -void CXFA_FM2JSContext::logical_or_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() && argSecond->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT first = ValueToFloat(pThis, argFirst.get()); - FX_FLOAT second = ValueToFloat(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first || second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::logical_and_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() && argSecond->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_FLOAT first = ValueToFloat(pThis, argFirst.get()); - FX_FLOAT second = ValueToFloat(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first && second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::equality_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - if (fm_ref_equal(pThis, args)) { - args.GetReturnValue()->SetInteger(1); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() || argSecond->IsNull()) { - args.GetReturnValue()->SetInteger( - (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0); - return; - } - - if (argFirst->IsString() && argSecond->IsString()) { - args.GetReturnValue()->SetInteger(argFirst->ToString() == - argSecond->ToString()); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first == second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::notequality_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - if (fm_ref_equal(pThis, args)) { - args.GetReturnValue()->SetInteger(0); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() || argSecond->IsNull()) { - args.GetReturnValue()->SetInteger( - (argFirst->IsNull() && argSecond->IsNull()) ? 0 : 1); - return; - } - - if (argFirst->IsString() && argSecond->IsString()) { - args.GetReturnValue()->SetInteger(argFirst->ToString() != - argSecond->ToString()); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger(first != second); -} - -// static -bool CXFA_FM2JSContext::fm_ref_equal(CFXJSE_Value* pThis, - CFXJSE_Arguments& args) { - std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0); - std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1); - if (!argFirst->IsArray() || !argSecond->IsArray()) - return false; - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - auto firstFlagValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto secondFlagValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argFirst->GetObjectPropertyByIdx(0, firstFlagValue.get()); - argSecond->GetObjectPropertyByIdx(0, secondFlagValue.get()); - if (firstFlagValue->ToInteger() != 3 || secondFlagValue->ToInteger() != 3) - return false; - - auto firstJSObject = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto secondJSObject = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argFirst->GetObjectPropertyByIdx(2, firstJSObject.get()); - argSecond->GetObjectPropertyByIdx(2, secondJSObject.get()); - if (firstJSObject->IsNull() || secondJSObject->IsNull()) - return false; - - return (firstJSObject->ToHostObject(nullptr) == - secondJSObject->ToHostObject(nullptr)); -} - -// static -void CXFA_FM2JSContext::less_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() || argSecond->IsNull()) { - args.GetReturnValue()->SetInteger(0); - return; - } - - if (argFirst->IsString() && argSecond->IsString()) { - args.GetReturnValue()->SetInteger( - argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == -1); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first < second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::lessequal_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() || argSecond->IsNull()) { - args.GetReturnValue()->SetInteger( - (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0); - return; - } - - if (argFirst->IsString() && argSecond->IsString()) { - args.GetReturnValue()->SetInteger( - argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != 1); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first <= second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::greater_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() || argSecond->IsNull()) { - args.GetReturnValue()->SetInteger(0); - return; - } - - if (argFirst->IsString() && argSecond->IsString()) { - args.GetReturnValue()->SetInteger( - argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == 1); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first > second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::greaterequal_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() || argSecond->IsNull()) { - args.GetReturnValue()->SetInteger( - (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0); - return; - } - - if (argFirst->IsString() && argSecond->IsString()) { - args.GetReturnValue()->SetInteger( - argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != -1); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetInteger((first >= second) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::plus_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0); - std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1); - if (ValueIsNull(pThis, argFirst.get()) && - ValueIsNull(pThis, argSecond.get())) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetDouble(first + second); -} - -// static -void CXFA_FM2JSContext::minus_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() && argSecond->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetDouble(first - second); -} - -// static -void CXFA_FM2JSContext::multiple_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 2) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() && argSecond->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - args.GetReturnValue()->SetDouble(first * second); -} - -// static -void CXFA_FM2JSContext::divide_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 2) { - pContext->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0); - std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1); - if (argFirst->IsNull() && argSecond->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE second = ValueToDouble(pThis, argSecond.get()); - if (second == 0.0) { - pContext->ThrowDivideByZeroException(); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argFirst.get()); - args.GetReturnValue()->SetDouble(first / second); -} - -// static -void CXFA_FM2JSContext::positive_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - args.GetReturnValue()->SetDouble(0.0 + ValueToDouble(pThis, argOne.get())); -} - -// static -void CXFA_FM2JSContext::negative_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - args.GetReturnValue()->SetDouble(0.0 - ValueToDouble(pThis, argOne.get())); -} - -// static -void CXFA_FM2JSContext::logical_not_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - if (argOne->IsNull()) { - args.GetReturnValue()->SetNull(); - return; - } - - FX_DOUBLE first = ValueToDouble(pThis, argOne.get()); - args.GetReturnValue()->SetInteger((first == 0.0) ? 1 : 0); -} - -// static -void CXFA_FM2JSContext::dot_accessor(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - int32_t argc = args.GetLength(); - if (argc < 4 || argc > 5) { - pContext->ThrowCompilerErrorException(); - return; - } - - bool bIsStar = true; - int32_t iIndexValue = 0; - if (argc > 4) { - bIsStar = false; - iIndexValue = ValueToInteger(pThis, args.GetValue(4).get()); - } - - CFX_ByteString szName = args.GetUTF8String(2); - CFX_ByteString szSomExp; - GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue, - bIsStar, szSomExp); - - std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0); - if (argAccessor->IsArray()) { - auto pLengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argAccessor->GetObjectProperty("length", pLengthValue.get()); - int32_t iLength = pLengthValue->ToInteger(); - if (iLength < 3) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto hJSObjValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - std::vector<std::vector<std::unique_ptr<CFXJSE_Value>>> resolveValues( - iLength - 2); - bool bAttribute = false; - int32_t iCounter = 0; - for (int32_t i = 2; i < iLength; i++) { - argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get()); - - XFA_RESOLVENODE_RS resoveNodeRS; - if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(), - resoveNodeRS, true, szName.IsEmpty()) > 0) { - ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(), - &resolveValues[i - 2], &bAttribute); - iCounter += resolveValues[i - 2].size(); - } - } - if (iCounter < 1) { - pContext->ThrowPropertyNotInObjectException( - CFX_WideString::FromUTF8(szName.AsStringC()), - CFX_WideString::FromUTF8(szSomExp.AsStringC())); - return; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> values; - for (int32_t i = 0; i < iCounter + 2; i++) - values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - values[0]->SetInteger(1); - if (bAttribute) - values[1]->SetString(szName.AsStringC()); - else - values[1]->SetNull(); - - int32_t iIndex = 2; - for (int32_t i = 0; i < iLength - 2; i++) { - for (size_t j = 0; j < resolveValues[i].size(); j++) { - values[iIndex]->Assign(resolveValues[i][j].get()); - iIndex++; - } - } - args.GetReturnValue()->SetArray(values); - return; - } - - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = 0; - CFX_ByteString bsAccessorName = args.GetUTF8String(1); - if (argAccessor->IsObject() || - (argAccessor->IsNull() && bsAccessorName.IsEmpty())) { - iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(), - resoveNodeRS, true, szName.IsEmpty()); - } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() && - GetObjectForName(pThis, argAccessor.get(), - bsAccessorName.AsStringC())) { - iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(), - resoveNodeRS, true, szName.IsEmpty()); - } - if (iRet < 1) { - pContext->ThrowPropertyNotInObjectException( - CFX_WideString::FromUTF8(szName.AsStringC()), - CFX_WideString::FromUTF8(szSomExp.AsStringC())); - return; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> resolveValues; - bool bAttribute = false; - ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), &resolveValues, - &bAttribute); - - std::vector<std::unique_ptr<CFXJSE_Value>> values; - for (size_t i = 0; i < resolveValues.size() + 2; i++) - values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - values[0]->SetInteger(1); - if (bAttribute) - values[1]->SetString(szName.AsStringC()); - else - values[1]->SetNull(); - - for (size_t i = 0; i < resolveValues.size(); i++) - values[i + 2]->Assign(resolveValues[i].get()); - - args.GetReturnValue()->SetArray(values); -} - -// static -void CXFA_FM2JSContext::dotdot_accessor(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - int32_t argc = args.GetLength(); - if (argc < 4 || argc > 5) { - pContext->ThrowCompilerErrorException(); - return; - } - - bool bIsStar = true; - int32_t iIndexValue = 0; - if (argc > 4) { - bIsStar = false; - iIndexValue = ValueToInteger(pThis, args.GetValue(4).get()); - } - - CFX_ByteString szSomExp; - CFX_ByteString szName = args.GetUTF8String(2); - GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue, - bIsStar, szSomExp); - - std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0); - if (argAccessor->IsArray()) { - auto pLengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argAccessor->GetObjectProperty("length", pLengthValue.get()); - int32_t iLength = pLengthValue->ToInteger(); - if (iLength < 3) { - pContext->ThrowArgumentMismatchException(); - return; - } - - int32_t iCounter = 0; - - std::vector<std::vector<std::unique_ptr<CFXJSE_Value>>> resolveValues( - iLength - 2); - auto hJSObjValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - bool bAttribute = false; - for (int32_t i = 2; i < iLength; i++) { - argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get()); - XFA_RESOLVENODE_RS resoveNodeRS; - if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(), - resoveNodeRS, false) > 0) { - ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(), - &resolveValues[i - 2], &bAttribute); - iCounter += resolveValues[i - 2].size(); - } - } - if (iCounter < 1) { - pContext->ThrowPropertyNotInObjectException( - CFX_WideString::FromUTF8(szName.AsStringC()), - CFX_WideString::FromUTF8(szSomExp.AsStringC())); - return; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> values; - for (int32_t i = 0; i < iCounter + 2; i++) - values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - values[0]->SetInteger(1); - if (bAttribute) - values[1]->SetString(szName.AsStringC()); - else - values[1]->SetNull(); - - int32_t iIndex = 2; - for (int32_t i = 0; i < iLength - 2; i++) { - for (size_t j = 0; j < resolveValues[i].size(); j++) { - values[iIndex]->Assign(resolveValues[i][j].get()); - iIndex++; - } - } - args.GetReturnValue()->SetArray(values); - return; - } - - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = 0; - CFX_ByteString bsAccessorName = args.GetUTF8String(1); - if (argAccessor->IsObject() || - (argAccessor->IsNull() && bsAccessorName.IsEmpty())) { - iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(), - resoveNodeRS, false); - } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() && - GetObjectForName(pThis, argAccessor.get(), - bsAccessorName.AsStringC())) { - iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(), - resoveNodeRS, false); - } - if (iRet < 1) { - pContext->ThrowPropertyNotInObjectException( - CFX_WideString::FromUTF8(szName.AsStringC()), - CFX_WideString::FromUTF8(szSomExp.AsStringC())); - return; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> resolveValues; - bool bAttribute = false; - ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), &resolveValues, - &bAttribute); - - std::vector<std::unique_ptr<CFXJSE_Value>> values; - for (size_t i = 0; i < resolveValues.size() + 2; i++) - values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - values[0]->SetInteger(1); - if (bAttribute) - values[1]->SetString(szName.AsStringC()); - else - values[1]->SetNull(); - - for (size_t i = 0; i < resolveValues.size(); i++) - values[i + 2]->Assign(resolveValues[i].get()); - - args.GetReturnValue()->SetArray(values); -} - -// static -void CXFA_FM2JSContext::eval_translation(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 1) { - pContext->ThrowParamCountMismatchException(L"Eval"); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0); - CFX_ByteString argString; - ValueToUTF8String(argOne.get(), argString); - if (argString.IsEmpty()) { - pContext->ThrowArgumentMismatchException(); - return; - } - - CFX_WideString scriptString = CFX_WideString::FromUTF8(argString.AsStringC()); - CFX_WideTextBuf wsJavaScriptBuf; - CFX_WideString wsError; - CXFA_FM2JSContext::Translate(scriptString.AsStringC(), wsJavaScriptBuf, - wsError); - if (!wsError.IsEmpty()) { - pContext->ThrowCompilerErrorException(); - return; - } - - args.GetReturnValue()->SetString( - FX_UTF8Encode(wsJavaScriptBuf.AsStringC()).AsStringC()); -} - -// static -void CXFA_FM2JSContext::is_fm_object(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - args.GetReturnValue()->SetBoolean(false); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - args.GetReturnValue()->SetBoolean(argOne->IsObject()); -} - -// static -void CXFA_FM2JSContext::is_fm_array(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - args.GetReturnValue()->SetBoolean(false); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - args.GetReturnValue()->SetBoolean(argOne->IsArray()); -} - -// static -void CXFA_FM2JSContext::get_fm_value(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 1) { - pContext->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (argOne->IsArray()) { - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectPropertyByIdx(1, propertyValue.get()); - argOne->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), args.GetReturnValue()); - return; - } - - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - args.GetReturnValue()); - return; - } - - if (argOne->IsObject()) { - GetObjectDefaultValue(argOne.get(), args.GetReturnValue()); - return; - } - - args.GetReturnValue()->Assign(argOne.get()); -} - -// static -void CXFA_FM2JSContext::get_fm_jsobj(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - if (args.GetLength() != 1) { - ToJSContext(pThis, nullptr)->ThrowCompilerErrorException(); - return; - } - - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (!argOne->IsArray()) { - args.GetReturnValue()->Assign(argOne.get()); - return; - } - -#ifndef NDEBUG - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectProperty("length", lengthValue.get()); - ASSERT(lengthValue->ToInteger() >= 3); -#endif - - argOne->GetObjectPropertyByIdx(2, args.GetReturnValue()); -} - -// static -void CXFA_FM2JSContext::fm_var_filter(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - if (args.GetLength() != 1) { - pContext->ThrowCompilerErrorException(); - return; - } - - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0); - if (!argOne->IsArray()) { - std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0); - args.GetReturnValue()->Assign(simpleValue.get()); - return; - } - -#ifndef NDEBUG - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectProperty("length", lengthValue.get()); - ASSERT(lengthValue->ToInteger() >= 3); -#endif - - auto flagsValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectPropertyByIdx(0, flagsValue.get()); - int32_t iFlags = flagsValue->ToInteger(); - if (iFlags != 3 && iFlags != 4) { - std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0); - args.GetReturnValue()->Assign(simpleValue.get()); - return; - } - - if (iFlags == 4) { - std::vector<std::unique_ptr<CFXJSE_Value>> values; - for (int32_t i = 0; i < 3; i++) - values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - values[0]->SetInteger(3); - values[1]->SetNull(); - values[2]->SetNull(); - args.GetReturnValue()->SetArray(values); - return; - } - - auto objectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argOne->GetObjectPropertyByIdx(2, objectValue.get()); - if (objectValue->IsNull()) { - pContext->ThrowCompilerErrorException(); - return; - } - args.GetReturnValue()->Assign(argOne.get()); -} - -// static -void CXFA_FM2JSContext::concat_fm_object(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - uint32_t iLength = 0; - int32_t argc = args.GetLength(); - std::vector<std::unique_ptr<CFXJSE_Value>> argValues; - for (int32_t i = 0; i < argc; i++) { - argValues.push_back(args.GetValue(i)); - if (argValues[i]->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValues[i]->GetObjectProperty("length", lengthValue.get()); - int32_t length = lengthValue->ToInteger(); - iLength = iLength + ((length > 2) ? (length - 2) : 0); - } - iLength += 1; - } - - std::vector<std::unique_ptr<CFXJSE_Value>> returnValues; - for (int32_t i = 0; i < (int32_t)iLength; i++) - returnValues.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - int32_t index = 0; - for (int32_t i = 0; i < argc; i++) { - if (argValues[i]->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argValues[i]->GetObjectProperty("length", lengthValue.get()); - - int32_t length = lengthValue->ToInteger(); - for (int32_t j = 2; j < length; j++) { - argValues[i]->GetObjectPropertyByIdx(j, returnValues[index].get()); - index++; - } - } - returnValues[index]->Assign(argValues[i].get()); - index++; - } - args.GetReturnValue()->SetArray(returnValues); -} - -// static -std::unique_ptr<CFXJSE_Value> CXFA_FM2JSContext::GetSimpleValue( - CFXJSE_Value* pThis, - CFXJSE_Arguments& args, - uint32_t index) { - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - ASSERT(index < (uint32_t)args.GetLength()); - - std::unique_ptr<CFXJSE_Value> argIndex = args.GetValue(index); - if (!argIndex->IsArray() && !argIndex->IsObject()) - return argIndex; - - if (argIndex->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argIndex->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - auto simpleValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - if (iLength < 3) { - simpleValue.get()->SetUndefined(); - return simpleValue; - } - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argIndex->GetObjectPropertyByIdx(1, propertyValue.get()); - argIndex->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), simpleValue.get()); - return simpleValue; - } - - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - simpleValue.get()); - return simpleValue; - } - - auto defaultValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(argIndex.get(), defaultValue.get()); - return defaultValue; -} - -// static -bool CXFA_FM2JSContext::ValueIsNull(CFXJSE_Value* pThis, CFXJSE_Value* arg) { - if (!arg || arg->IsNull()) - return true; - - if (!arg->IsArray() && !arg->IsObject()) - return false; - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - if (arg->IsArray()) { - int32_t iLength = hvalue_get_array_length(pThis, arg); - if (iLength < 3) - return true; - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - arg->GetObjectPropertyByIdx(1, propertyValue.get()); - arg->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - auto defaultValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(jsObjectValue.get(), defaultValue.get()); - return defaultValue->IsNull(); - } - - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - newPropertyValue.get()); - return newPropertyValue->IsNull(); - } - - auto defaultValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(arg, defaultValue.get()); - return defaultValue->IsNull(); -} - -// static -int32_t CXFA_FM2JSContext::hvalue_get_array_length(CFXJSE_Value* pThis, - CFXJSE_Value* arg) { - if (!arg || !arg->IsArray()) - return 0; - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - arg->GetObjectProperty("length", lengthValue.get()); - return lengthValue->ToInteger(); -} - -// static -bool CXFA_FM2JSContext::simpleValueCompare(CFXJSE_Value* pThis, - CFXJSE_Value* firstValue, - CFXJSE_Value* secondValue) { - if (!firstValue) - return false; - - if (firstValue->IsString()) { - CFX_ByteString firstString, secondString; - ValueToUTF8String(firstValue, firstString); - ValueToUTF8String(secondValue, secondString); - return firstString == secondString; - } - if (firstValue->IsNumber()) { - FX_FLOAT first = ValueToFloat(pThis, firstValue); - FX_FLOAT second = ValueToFloat(pThis, secondValue); - return (first == second); - } - if (firstValue->IsBoolean()) - return (firstValue->ToBoolean() == secondValue->ToBoolean()); - - return firstValue->IsNull() && secondValue && secondValue->IsNull(); -} - -// static -void CXFA_FM2JSContext::unfoldArgs( - CFXJSE_Value* pThis, - CFXJSE_Arguments& args, - std::vector<std::unique_ptr<CFXJSE_Value>>* resultValues, - int32_t iStart) { - resultValues->clear(); - - int32_t iCount = 0; - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - int32_t argc = args.GetLength(); - std::vector<std::unique_ptr<CFXJSE_Value>> argsValue; - for (int32_t i = 0; i < argc - iStart; i++) { - argsValue.push_back(args.GetValue(i + iStart)); - if (argsValue[i]->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argsValue[i]->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - iCount += ((iLength > 2) ? (iLength - 2) : 0); - } else { - iCount += 1; - } - } - - for (int32_t i = 0; i < iCount; i++) - resultValues->push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - - int32_t index = 0; - for (int32_t i = 0; i < argc - iStart; i++) { - if (argsValue[i]->IsArray()) { - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argsValue[i]->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength < 3) - continue; - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - argsValue[i]->GetObjectPropertyByIdx(1, propertyValue.get()); - if (propertyValue->IsNull()) { - for (int32_t j = 2; j < iLength; j++) { - argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get()); - GetObjectDefaultValue(jsObjectValue.get(), - (*resultValues)[index].get()); - index++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - propertyValue->ToString().AsStringC(), - (*resultValues)[index].get()); - index++; - } - } - } else if (argsValue[i]->IsObject()) { - GetObjectDefaultValue(argsValue[i].get(), (*resultValues)[index].get()); - index++; - } else { - (*resultValues)[index]->Assign(argsValue[i].get()); - index++; - } - } -} - -// static -void CXFA_FM2JSContext::GetObjectDefaultValue(CFXJSE_Value* pValue, - CFXJSE_Value* pDefaultValue) { - CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr)); - if (!pNode) { - pDefaultValue->SetNull(); - return; - } - pNode->Script_Som_DefaultValue(pDefaultValue, false, (XFA_ATTRIBUTE)-1); -} - -// static -bool CXFA_FM2JSContext::SetObjectDefaultValue(CFXJSE_Value* pValue, - CFXJSE_Value* hNewValue) { - CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr)); - if (!pNode) - return false; - - pNode->Script_Som_DefaultValue(hNewValue, true, (XFA_ATTRIBUTE)-1); - return true; -} - -// static -void CXFA_FM2JSContext::GenerateSomExpression(const CFX_ByteStringC& szName, - int32_t iIndexFlags, - int32_t iIndexValue, - bool bIsStar, - CFX_ByteString& szSomExp) { - if (bIsStar) { - szSomExp = szName + "[*]"; - return; - } - if (iIndexFlags == 0) { - szSomExp = szName; - return; - } - if (iIndexFlags == 1 || iIndexValue == 0) { - szSomExp = szName + "[" + - CFX_ByteString::FormatInteger(iIndexValue, FXFORMAT_SIGNED) + - "]"; - } else if (iIndexFlags == 2) { - szSomExp = (iIndexValue < 0) ? (szName + "[-") : (szName + "[+"); - iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue; - szSomExp += CFX_ByteString::FormatInteger(iIndexValue); - szSomExp += "]"; - } else { - szSomExp = (iIndexValue < 0) ? (szName + "[") : (szName + "[-"); - iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue; - szSomExp += CFX_ByteString::FormatInteger(iIndexValue); - szSomExp += "]"; - } -} - -// static -bool CXFA_FM2JSContext::GetObjectForName( - CFXJSE_Value* pThis, - CFXJSE_Value* accessorValue, - const CFX_ByteStringC& szAccessorName) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return false; - - CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext(); - XFA_RESOLVENODE_RS resoveNodeRS; - uint32_t dwFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | - XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; - int32_t iRet = pScriptContext->ResolveObjects( - pScriptContext->GetThisObject(), - CFX_WideString::FromUTF8(szAccessorName).AsStringC(), resoveNodeRS, - dwFlags); - if (iRet >= 1 && resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { - accessorValue->Assign( - pScriptContext->GetJSValueFromMap(resoveNodeRS.nodes.GetAt(0))); - return true; - } - return false; -} - -// static -int32_t CXFA_FM2JSContext::ResolveObjects(CFXJSE_Value* pThis, - CFXJSE_Value* pRefValue, - const CFX_ByteStringC& bsSomExp, - XFA_RESOLVENODE_RS& resoveNodeRS, - bool bdotAccessor, - bool bHasNoResolveName) { - CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument(); - if (!pDoc) - return -1; - - CFX_WideString wsSomExpression = CFX_WideString::FromUTF8(bsSomExp); - CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext(); - CXFA_Object* pNode = nullptr; - uint32_t dFlags = 0UL; - if (bdotAccessor) { - if (pRefValue && pRefValue->IsNull()) { - pNode = pScriptContext->GetThisObject(); - dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; - } else { - pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr); - ASSERT(pNode); - if (bHasNoResolveName) { - CFX_WideString wsName; - if (CXFA_Node* pXFANode = pNode->AsNode()) - pXFANode->GetAttribute(XFA_ATTRIBUTE_Name, wsName, false); - if (wsName.IsEmpty()) - wsName = L"#" + pNode->GetClassName(); - - wsSomExpression = wsName + wsSomExpression; - dFlags = XFA_RESOLVENODE_Siblings; - } else { - dFlags = (bsSomExp == "*") - ? (XFA_RESOLVENODE_Children) - : (XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | - XFA_RESOLVENODE_Properties); - } - } - } else { - pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr); - dFlags = XFA_RESOLVENODE_AnyChild; - } - return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringC(), - resoveNodeRS, dFlags); -} - -// static -void CXFA_FM2JSContext::ParseResolveResult( - CFXJSE_Value* pThis, - const XFA_RESOLVENODE_RS& resoveNodeRS, - CFXJSE_Value* pParentValue, - std::vector<std::unique_ptr<CFXJSE_Value>>* resultValues, - bool* bAttribute) { - ASSERT(bAttribute); - - resultValues->clear(); - - CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr); - v8::Isolate* pIsolate = pContext->GetScriptRuntime(); - - if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { - *bAttribute = false; - for (int32_t i = 0; i < resoveNodeRS.nodes.GetSize(); i++) { - resultValues->push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - resultValues->back()->Assign( - pContext->GetDocument()->GetScriptContext()->GetJSValueFromMap( - resoveNodeRS.nodes.GetAt(i))); - } - return; - } - - CXFA_ValueArray objectProperties(pIsolate); - int32_t iRet = resoveNodeRS.GetAttributeResult(objectProperties); - *bAttribute = true; - if (iRet != 0) { - *bAttribute = false; - for (int32_t i = 0; i < iRet; i++) { - resultValues->push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - resultValues->back()->Assign(objectProperties[i]); - } - return; - } - - if (!pParentValue || !pParentValue->IsObject()) - return; - - resultValues->push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate)); - resultValues->back()->Assign(pParentValue); -} - -// static -int32_t CXFA_FM2JSContext::ValueToInteger(CFXJSE_Value* pThis, - CFXJSE_Value* pValue) { - if (!pValue) - return 0; - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - if (pValue->IsArray()) { - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - pValue->GetObjectPropertyByIdx(1, propertyValue.get()); - pValue->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - return ValueToInteger(pThis, newPropertyValue.get()); - } - - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - newPropertyValue.get()); - return ValueToInteger(pThis, newPropertyValue.get()); - } - if (pValue->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(pValue, newPropertyValue.get()); - return ValueToInteger(pThis, newPropertyValue.get()); - } - if (pValue->IsString()) - return FXSYS_atoi(pValue->ToString().c_str()); - return pValue->ToInteger(); -} - -// static -FX_FLOAT CXFA_FM2JSContext::ValueToFloat(CFXJSE_Value* pThis, - CFXJSE_Value* arg) { - if (!arg) - return 0.0f; - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - if (arg->IsArray()) { - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - arg->GetObjectPropertyByIdx(1, propertyValue.get()); - arg->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - return ValueToFloat(pThis, newPropertyValue.get()); - } - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - newPropertyValue.get()); - return ValueToFloat(pThis, newPropertyValue.get()); - } - if (arg->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(arg, newPropertyValue.get()); - return ValueToFloat(pThis, newPropertyValue.get()); - } - if (arg->IsString()) - return (FX_FLOAT)XFA_ByteStringToDouble(arg->ToString().AsStringC()); - if (arg->IsUndefined()) - return 0; - - return arg->ToFloat(); -} - -// static -FX_DOUBLE CXFA_FM2JSContext::ValueToDouble(CFXJSE_Value* pThis, - CFXJSE_Value* arg) { - if (!arg) - return 0; - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - if (arg->IsArray()) { - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - arg->GetObjectPropertyByIdx(1, propertyValue.get()); - arg->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) { - GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get()); - return ValueToDouble(pThis, newPropertyValue.get()); - } - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - newPropertyValue.get()); - return ValueToDouble(pThis, newPropertyValue.get()); - } - if (arg->IsObject()) { - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - GetObjectDefaultValue(arg, newPropertyValue.get()); - return ValueToDouble(pThis, newPropertyValue.get()); - } - if (arg->IsString()) - return XFA_ByteStringToDouble(arg->ToString().AsStringC()); - if (arg->IsUndefined()) - return 0; - return arg->ToDouble(); -} - -// static. -double CXFA_FM2JSContext::ExtractDouble(CFXJSE_Value* pThis, - CFXJSE_Value* src, - bool* ret) { - ASSERT(ret); - *ret = true; - - if (!src) - return 0; - - if (!src->IsArray()) - return ValueToDouble(pThis, src); - - v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime(); - auto lengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - src->GetObjectProperty("length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(); - if (iLength <= 2) { - *ret = false; - return 0.0; - } - - auto propertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - auto jsObjectValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - src->GetObjectPropertyByIdx(1, propertyValue.get()); - src->GetObjectPropertyByIdx(2, jsObjectValue.get()); - if (propertyValue->IsNull()) - return ValueToDouble(pThis, jsObjectValue.get()); - - auto newPropertyValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate); - jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(), - newPropertyValue.get()); - return ValueToDouble(pThis, newPropertyValue.get()); -} - -// static -void CXFA_FM2JSContext::ValueToUTF8String(CFXJSE_Value* arg, - CFX_ByteString& szOutputString) { - if (!arg) - return; - - if (arg->IsNull() || arg->IsUndefined()) - szOutputString = ""; - else if (arg->IsBoolean()) - szOutputString = arg->ToBoolean() ? "1" : "0"; - else - szOutputString = arg->ToString(); -} - -// static. -int32_t CXFA_FM2JSContext::Translate(const CFX_WideStringC& wsFormcalc, - CFX_WideTextBuf& wsJavascript, - CFX_WideString& wsError) { - if (wsFormcalc.IsEmpty()) { - wsJavascript.Clear(); - wsError.clear(); - return 0; - } - CXFA_FMProgram program(wsFormcalc); - int32_t status = program.ParseProgram(); - if (status) { - wsError = program.GetError().message; - return status; - } - program.TranslateProgram(wsJavascript); - return 0; -} - -CXFA_FM2JSContext::CXFA_FM2JSContext(v8::Isolate* pScriptIsolate, - CFXJSE_Context* pScriptContext, - CXFA_Document* pDoc) - : m_pIsolate(pScriptIsolate), - m_pFMClass( - CFXJSE_Class::Create(pScriptContext, &formcalc_fm2js_descriptor)), - m_pValue(pdfium::MakeUnique<CFXJSE_Value>(pScriptIsolate)), - m_pDocument(pDoc) { - m_pValue.get()->SetNull(); - m_pValue.get()->SetObject(this, m_pFMClass); -} - -CXFA_FM2JSContext::~CXFA_FM2JSContext() {} - -void CXFA_FM2JSContext::GlobalPropertyGetter(CFXJSE_Value* pValue) { - pValue->Assign(m_pValue.get()); -} - -void CXFA_FM2JSContext::ThrowNoDefaultPropertyException( - const CFX_ByteStringC& name) const { - ThrowException(L"%s doesn't have a default property.", name.c_str()); -} - -void CXFA_FM2JSContext::ThrowCompilerErrorException() const { - ThrowException(L"Compiler error."); -} - -void CXFA_FM2JSContext::ThrowDivideByZeroException() const { - ThrowException(L"Divide by zero."); -} - -void CXFA_FM2JSContext::ThrowServerDeniedException() const { - ThrowException(L"Server does not permit operation."); -} - -void CXFA_FM2JSContext::ThrowPropertyNotInObjectException( - const CFX_WideString& name, - const CFX_WideString& exp) const { - ThrowException( - L"An attempt was made to reference property '%s' of a non-object " - L"in SOM expression %s.", - name.c_str(), exp.c_str()); -} - -void CXFA_FM2JSContext::ThrowParamCountMismatchException( - const CFX_WideString& method) const { - ThrowException(L"Incorrect number of parameters calling method '%s'.", - method.c_str()); -} - -void CXFA_FM2JSContext::ThrowArgumentMismatchException() const { - ThrowException(L"Argument mismatch in property or function argument."); -} - -void CXFA_FM2JSContext::ThrowException(const FX_WCHAR* str, ...) const { - CFX_WideString wsMessage; - va_list arg_ptr; - va_start(arg_ptr, str); - wsMessage.FormatV(str, arg_ptr); - va_end(arg_ptr); - FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringC()); -} diff --git a/xfa/fxfa/fm2js/xfa_fm2jscontext.h b/xfa/fxfa/fm2js/xfa_fm2jscontext.h deleted file mode 100644 index 0f802fe65e456e900e3ebe779e98ecacdee2ff65..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_fm2jscontext.h +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_FM2JSCONTEXT_H_ -#define XFA_FXFA_FM2JS_XFA_FM2JSCONTEXT_H_ - -#include <memory> -#include <vector> - -#include "fxjs/cfxjse_arguments.h" -#include "fxjs/cfxjse_context.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" - -class CXFA_FM2JSContext : public CFXJSE_HostObject { - public: - CXFA_FM2JSContext(v8::Isolate* pScriptIsolate, - CFXJSE_Context* pScriptContext, - CXFA_Document* pDoc); - ~CXFA_FM2JSContext() override; - - static void Abs(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Avg(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Ceil(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Count(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Floor(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Max(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Min(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Mod(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Round(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Sum(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Date(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Date2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void DateFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void IsoDate2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void IsoTime2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void LocalDateFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void LocalTimeFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Num2Date(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Num2GMTime(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Num2Time(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Time(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Time2Num(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void TimeFmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - - static bool IsIsoDateFormat(const FX_CHAR* pData, - int32_t iLength, - int32_t& iStyle, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay); - static bool IsIsoTimeFormat(const FX_CHAR* pData, - int32_t iLength, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMilliSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute); - static bool IsIsoDateTimeFormat(const FX_CHAR* pData, - int32_t iLength, - int32_t& iYear, - int32_t& iMonth, - int32_t& iDay, - int32_t& iHour, - int32_t& iMinute, - int32_t& iSecond, - int32_t& iMillionSecond, - int32_t& iZoneHour, - int32_t& iZoneMinute); - static bool Local2IsoDate(CFXJSE_Value* pThis, - const CFX_ByteStringC& szDate, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strIsoDate); - static bool Local2IsoTime(CFXJSE_Value* pThis, - const CFX_ByteStringC& szTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strIsoTime); - static bool IsoDate2Local(CFXJSE_Value* pThis, - const CFX_ByteStringC& szDate, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strLocalDate); - static bool IsoTime2Local(CFXJSE_Value* pThis, - const CFX_ByteStringC& szTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strLocalTime); - static bool GetGMTTime(CFXJSE_Value* pThis, - const CFX_ByteStringC& szTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - CFX_ByteString& strGMTTime); - static int32_t DateString2Num(const CFX_ByteStringC& szDateString); - static void GetLocalDateFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat, - bool bStandard); - static void GetLocalTimeFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat, - bool bStandard); - static void GetStandardDateFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat); - static void GetStandardTimeFormat(CFXJSE_Value* pThis, - int32_t iStyle, - const CFX_ByteStringC& szLocalStr, - CFX_ByteString& strFormat); - - static void Num2AllTime(CFXJSE_Value* pThis, - int32_t iTime, - const CFX_ByteStringC& szFormat, - const CFX_ByteStringC& szLocale, - bool bGM, - CFX_ByteString& strTime); - static void GetLocalTimeZone(int32_t& iHour, int32_t& iMin, int32_t& iSec); - - static void Apr(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void CTerm(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void FV(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void IPmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void NPV(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Pmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void PPmt(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void PV(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Rate(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Term(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Choose(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Exists(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void HasValue(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Oneof(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Within(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void If(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Eval(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Ref(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void UnitType(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void UnitValue(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - - static void At(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Concat(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Decode(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void DecodeURL(const CFX_ByteStringC& szURLString, - CFX_ByteTextBuf& szResultBuf); - static void DecodeHTML(const CFX_ByteStringC& szHTMLString, - CFX_ByteTextBuf& szResultBuf); - static void DecodeXML(const CFX_ByteStringC& szXMLString, - CFX_ByteTextBuf& szResultBuf); - static void Encode(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void EncodeURL(const CFX_ByteStringC& szURLString, - CFX_ByteTextBuf& szResultBuf); - static void EncodeHTML(const CFX_ByteStringC& szHTMLString, - CFX_ByteTextBuf& szResultBuf); - static void EncodeXML(const CFX_ByteStringC& szXMLString, - CFX_ByteTextBuf& szResultBuf); - static bool HTMLSTR2Code(const CFX_WideStringC& pData, uint32_t& iCode); - static bool HTMLCode2STR(uint32_t iCode, CFX_WideString& wsHTMLReserve); - static void Format(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Left(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Len(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Lower(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Ltrim(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Parse(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Replace(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Right(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Rtrim(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Space(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Str(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Stuff(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Substr(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Uuid(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Upper(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void WordNum(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void TrillionUS(const CFX_ByteStringC& szData, - CFX_ByteTextBuf& strBuf); - static void WordUS(const CFX_ByteStringC& szData, - int32_t iStyle, - CFX_ByteTextBuf& strBuf); - - static void Get(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Post(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void Put(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void assign_value_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void logical_or_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void logical_and_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void equality_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void notequality_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static bool fm_ref_equal(CFXJSE_Value* pThis, CFXJSE_Arguments& args); - static void less_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void lessequal_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void greater_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void greaterequal_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void plus_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void minus_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void multiple_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void divide_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void positive_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void negative_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void logical_not_operator(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void dot_accessor(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void dotdot_accessor(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void eval_translation(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void is_fm_object(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void is_fm_array(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void get_fm_value(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void get_fm_jsobj(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void fm_var_filter(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static void concat_fm_object(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - - static int32_t hvalue_get_array_length(CFXJSE_Value* pThis, - CFXJSE_Value* arg); - static bool simpleValueCompare(CFXJSE_Value* pThis, - CFXJSE_Value* firstValue, - CFXJSE_Value* secondValue); - static void unfoldArgs( - CFXJSE_Value* pThis, - CFXJSE_Arguments& args, - std::vector<std::unique_ptr<CFXJSE_Value>>* resultValues, - int32_t iStart = 0); - static void GetObjectDefaultValue(CFXJSE_Value* pObjectValue, - CFXJSE_Value* pDefaultValue); - static bool SetObjectDefaultValue(CFXJSE_Value* pObjectValue, - CFXJSE_Value* pNewValue); - static void GenerateSomExpression(const CFX_ByteStringC& szName, - int32_t iIndexFlags, - int32_t iIndexValue, - bool bIsStar, - CFX_ByteString& szSomExp); - static bool GetObjectForName(CFXJSE_Value* pThis, - CFXJSE_Value* accessorValue, - const CFX_ByteStringC& szAccessorName); - static int32_t ResolveObjects(CFXJSE_Value* pThis, - CFXJSE_Value* pParentValue, - const CFX_ByteStringC& bsSomExp, - XFA_RESOLVENODE_RS& resoveNodeRS, - bool bdotAccessor = true, - bool bHasNoResolveName = false); - static void ParseResolveResult( - CFXJSE_Value* pThis, - const XFA_RESOLVENODE_RS& resoveNodeRS, - CFXJSE_Value* pParentValue, - std::vector<std::unique_ptr<CFXJSE_Value>>* resultValues, - bool* bAttribute); - - static std::unique_ptr<CFXJSE_Value> GetSimpleValue(CFXJSE_Value* pThis, - CFXJSE_Arguments& args, - uint32_t index); - static bool ValueIsNull(CFXJSE_Value* pThis, CFXJSE_Value* pValue); - static int32_t ValueToInteger(CFXJSE_Value* pThis, CFXJSE_Value* pValue); - static FX_FLOAT ValueToFloat(CFXJSE_Value* pThis, CFXJSE_Value* pValue); - static FX_DOUBLE ValueToDouble(CFXJSE_Value* pThis, CFXJSE_Value* pValue); - static void ValueToUTF8String(CFXJSE_Value* pValue, - CFX_ByteString& outputValue); - static double ExtractDouble(CFXJSE_Value* pThis, - CFXJSE_Value* src, - bool* ret); - - static int32_t Translate(const CFX_WideStringC& wsFormcalc, - CFX_WideTextBuf& wsJavascript, - CFX_WideString& wsError); - - void GlobalPropertyGetter(CFXJSE_Value* pValue); - - private: - v8::Isolate* GetScriptRuntime() const { return m_pIsolate; } - CXFA_Document* GetDocument() const { return m_pDocument; } - - void ThrowNoDefaultPropertyException(const CFX_ByteStringC& name) const; - void ThrowCompilerErrorException() const; - void ThrowDivideByZeroException() const; - void ThrowServerDeniedException() const; - void ThrowPropertyNotInObjectException(const CFX_WideString& name, - const CFX_WideString& exp) const; - void ThrowArgumentMismatchException() const; - void ThrowParamCountMismatchException(const CFX_WideString& method) const; - void ThrowException(const FX_WCHAR* str, ...) const; - - v8::Isolate* m_pIsolate; - CFXJSE_Class* m_pFMClass; - std::unique_ptr<CFXJSE_Value> m_pValue; - CXFA_Document* const m_pDocument; -}; - -#endif // XFA_FXFA_FM2JS_XFA_FM2JSCONTEXT_H_ diff --git a/xfa/fxfa/fm2js/xfa_fmparse.cpp b/xfa/fxfa/fm2js/xfa_fmparse.cpp deleted file mode 100644 index 52161e8c0ac3c12bd419431e9419128c48f8546e..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_fmparse.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_fmparse.h" - -#include <memory> -#include <utility> -#include <vector> - -#include "third_party/base/ptr_util.h" - -CXFA_FMParse::CXFA_FMParse(const CFX_WideStringC& wsFormcalc, - CXFA_FMErrorInfo* pErrorInfo) - : m_pToken(nullptr), m_pErrorInfo(pErrorInfo) { - m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc, m_pErrorInfo); -} - -CXFA_FMParse::~CXFA_FMParse() {} - -void CXFA_FMParse::NextToken() { - m_pToken = m_lexer->NextToken(); - while (m_pToken->m_type == TOKreserver) { - if (m_lexer->HasError()) { - break; - } - m_pToken = m_lexer->NextToken(); - } -} - -void CXFA_FMParse::Check(XFA_FM_TOKEN op) { - if (m_pToken->m_type != op) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, XFA_FM_KeywordToString(op), - ws_TempString.c_str()); - } - NextToken(); -} - -void CXFA_FMParse::Error(uint32_t lineNum, const FX_WCHAR* msg, ...) { - m_pErrorInfo->linenum = lineNum; - va_list ap; - va_start(ap, msg); - m_pErrorInfo->message.FormatV(msg, ap); - va_end(ap); -} - -std::vector<std::unique_ptr<CXFA_FMExpression>> -CXFA_FMParse::ParseTopExpression() { - std::unique_ptr<CXFA_FMExpression> expr; - std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; - while (1) { - if (m_pToken->m_type == TOKeof || m_pToken->m_type == TOKendfunc || - m_pToken->m_type == TOKendif || m_pToken->m_type == TOKelseif || - m_pToken->m_type == TOKelse || m_pToken->m_type == TOKreserver) { - return expressions; - } - - if (m_pToken->m_type == TOKfunc) { - expr = ParseFunction(); - if (expr) { - expressions.push_back(std::move(expr)); - } else { - break; - } - } else { - expr = ParseExpression(); - if (expr) { - expressions.push_back(std::move(expr)); - } else { - break; - } - } - } - return expressions; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseFunction() { - CFX_WideStringC ident; - std::vector<CFX_WideStringC> arguments; - std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type != TOKidentifier) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier, - ws_TempString.c_str()); - } else { - ident = m_pToken->m_wstring; - NextToken(); - } - Check(TOKlparen); - if (m_pToken->m_type == TOKrparen) { - NextToken(); - } else { - while (1) { - if (m_pToken->m_type == TOKidentifier) { - arguments.push_back(m_pToken->m_wstring); - NextToken(); - if (m_pToken->m_type == TOKcomma) { - NextToken(); - continue; - } else if (m_pToken->m_type == TOKrparen) { - NextToken(); - break; - } else { - Check(TOKrparen); - break; - } - } else { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier, - ws_TempString.c_str()); - NextToken(); - break; - } - } - } - Check(TOKdo); - if (m_pToken->m_type == TOKendfunc) { - NextToken(); - } else { - expressions = ParseTopExpression(); - Check(TOKendfunc); - } - if (!m_pErrorInfo->message.IsEmpty()) - return nullptr; - - return pdfium::MakeUnique<CXFA_FMFunctionDefinition>( - line, false, ident, std::move(arguments), std::move(expressions)); -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpression() { - std::unique_ptr<CXFA_FMExpression> expr; - uint32_t line = m_pToken->m_uLinenum; - switch (m_pToken->m_type) { - case TOKvar: - expr = ParseVarExpression(); - break; - case TOKnull: - case TOKnumber: - case TOKstring: - case TOKplus: - case TOKminus: - case TOKksnot: - case TOKidentifier: - case TOKlparen: - expr = ParseExpExpression(); - break; - case TOKif: - expr = ParseIfExpression(); - break; - case TOKwhile: - expr = ParseWhileExpression(); - break; - case TOKfor: - expr = ParseForExpression(); - break; - case TOKforeach: - expr = ParseForeachExpression(); - break; - case TOKdo: - expr = ParseDoExpression(); - break; - case TOKbreak: - expr = pdfium::MakeUnique<CXFA_FMBreakExpression>(line); - NextToken(); - break; - case TOKcontinue: - expr = pdfium::MakeUnique<CXFA_FMContinueExpression>(line); - NextToken(); - break; - default: - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression, - ws_TempString.c_str()); - NextToken(); - break; - } - return expr; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseVarExpression() { - CFX_WideStringC ident; - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type != TOKidentifier) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier, - ws_TempString.c_str()); - } else { - ident = m_pToken->m_wstring; - NextToken(); - } - std::unique_ptr<CXFA_FMExpression> expr; - if (m_pToken->m_type == TOKassign) { - NextToken(); - expr = ParseExpExpression(); - } - if (!m_pErrorInfo->message.IsEmpty()) - return nullptr; - - return pdfium::MakeUnique<CXFA_FMVarExpression>(line, ident, std::move(expr)); -} - -std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseSimpleExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression(); - while (m_pToken->m_type == TOKassign) { - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>( - line, TOKassign, std::move(pExp1), std::move(pExp2)); - } else { - pExp1.reset(); - } - } - return pExp1; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseExpExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression(); - if (!m_pErrorInfo->message.IsEmpty()) - return nullptr; - - return pdfium::MakeUnique<CXFA_FMExpExpression>(line, std::move(pExp1)); -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseLogicalOrExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression(); - for (;;) { - switch (m_pToken->m_type) { - case TOKor: - case TOKksor: { - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> e2( - ParseLogicalAndExpression()); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>( - line, TOKor, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - } - default: - break; - } - break; - } - return e1; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseLogicalAndExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression(); - for (;;) { - switch (m_pToken->m_type) { - case TOKand: - case TOKksand: { - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>( - line, TOKand, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - } - default: - break; - } - break; - } - return e1; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseEqualityExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression(); - for (;;) { - std::unique_ptr<CXFA_FMSimpleExpression> e2; - switch (m_pToken->m_type) { - case TOKeq: - case TOKkseq: - NextToken(); - e2 = ParseRelationalExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>( - line, TOKeq, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - case TOKne: - case TOKksne: - NextToken(); - e2 = ParseRelationalExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>( - line, TOKne, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - default: - break; - } - break; - } - return e1; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseRelationalExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAddtiveExpression(); - for (;;) { - std::unique_ptr<CXFA_FMSimpleExpression> e2; - switch (m_pToken->m_type) { - case TOKlt: - case TOKkslt: - NextToken(); - e2 = ParseAddtiveExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( - line, TOKlt, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - case TOKgt: - case TOKksgt: - NextToken(); - e2 = ParseAddtiveExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( - line, TOKgt, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - case TOKle: - case TOKksle: - NextToken(); - e2 = ParseAddtiveExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( - line, TOKle, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - case TOKge: - case TOKksge: - NextToken(); - e2 = ParseAddtiveExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>( - line, TOKge, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - default: - break; - } - break; - } - return e1; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseAddtiveExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression(); - for (;;) { - std::unique_ptr<CXFA_FMSimpleExpression> e2; - switch (m_pToken->m_type) { - case TOKplus: - NextToken(); - e2 = ParseMultiplicativeExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>( - line, TOKplus, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - case TOKminus: - NextToken(); - e2 = ParseMultiplicativeExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>( - line, TOKminus, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - default: - break; - } - break; - } - return e1; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseMultiplicativeExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression(); - for (;;) { - std::unique_ptr<CXFA_FMSimpleExpression> e2; - switch (m_pToken->m_type) { - case TOKmul: - NextToken(); - e2 = ParseUnaryExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>( - line, TOKmul, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - case TOKdiv: - NextToken(); - e2 = ParseUnaryExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>( - line, TOKdiv, std::move(e1), std::move(e2)); - } else { - e1.reset(); - } - continue; - default: - break; - } - break; - } - return e1; -} - -std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseUnaryExpression() { - std::unique_ptr<CXFA_FMSimpleExpression> expr; - uint32_t line = m_pToken->m_uLinenum; - switch (m_pToken->m_type) { - case TOKplus: - NextToken(); - expr = ParseUnaryExpression(); - if (m_pErrorInfo->message.IsEmpty()) - expr = pdfium::MakeUnique<CXFA_FMPosExpression>(line, std::move(expr)); - else - expr.reset(); - break; - case TOKminus: - NextToken(); - expr = ParseUnaryExpression(); - if (m_pErrorInfo->message.IsEmpty()) - expr = pdfium::MakeUnique<CXFA_FMNegExpression>(line, std::move(expr)); - else - expr.reset(); - break; - case TOKksnot: - NextToken(); - expr = ParseUnaryExpression(); - if (m_pErrorInfo->message.IsEmpty()) - expr = pdfium::MakeUnique<CXFA_FMNotExpression>(line, std::move(expr)); - else - expr.reset(); - break; - default: - expr = ParsePrimaryExpression(); - break; - } - return expr; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParsePrimaryExpression() { - std::unique_ptr<CXFA_FMSimpleExpression> expr; - uint32_t line = m_pToken->m_uLinenum; - switch (m_pToken->m_type) { - case TOKnumber: - expr = pdfium::MakeUnique<CXFA_FMNumberExpression>(line, - m_pToken->m_wstring); - NextToken(); - break; - case TOKstring: - expr = pdfium::MakeUnique<CXFA_FMStringExpression>(line, - m_pToken->m_wstring); - NextToken(); - break; - case TOKidentifier: { - CFX_WideStringC wsIdentifier(m_pToken->m_wstring); - NextToken(); - if (m_pToken->m_type == TOKlbracket) { - std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); - if (s) { - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - line, nullptr, TOKdot, wsIdentifier, std::move(s)); - } - NextToken(); - } else { - expr = - pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, wsIdentifier); - } - } break; - case TOKif: - expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>( - line, m_pToken->m_wstring); - NextToken(); - break; - case TOKnull: - expr = pdfium::MakeUnique<CXFA_FMNullExpression>(line); - NextToken(); - break; - case TOKlparen: - expr = ParseParenExpression(); - break; - default: - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression, - ws_TempString.c_str()); - NextToken(); - break; - } - expr = ParsePostExpression(std::move(expr)); - if (!m_pErrorInfo->message.IsEmpty()) - expr.reset(); - return expr; -} - -std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParsePostExpression( - std::unique_ptr<CXFA_FMSimpleExpression> expr) { - uint32_t line = m_pToken->m_uLinenum; - while (1) { - switch (m_pToken->m_type) { - case TOKlparen: { - NextToken(); - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions; - if (m_pToken->m_type != TOKrparen) { - while (m_pToken->m_type != TOKrparen) { - if (std::unique_ptr<CXFA_FMSimpleExpression> expr = - ParseSimpleExpression()) - expressions.push_back(std::move(expr)); - if (m_pToken->m_type == TOKcomma) { - NextToken(); - } else if (m_pToken->m_type == TOKeof || - m_pToken->m_type == TOKreserver) { - break; - } - } - if (m_pToken->m_type != TOKrparen) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str()); - } - } - if (m_pErrorInfo->message.IsEmpty()) { - expr = pdfium::MakeUnique<CXFA_FMCallExpression>( - line, std::move(expr), std::move(expressions), false); - NextToken(); - if (m_pToken->m_type != TOKlbracket) - continue; - - std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); - if (s) { - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - line, std::move(expr), TOKcall, L"", std::move(s)); - } else { - expr.reset(); - } - } else { - expr.reset(); - } - } break; - case TOKdot: - NextToken(); - if (m_pToken->m_type == TOKidentifier) { - CFX_WideStringC tempStr = m_pToken->m_wstring; - uint32_t tempLine = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type == TOKlparen) { - std::unique_ptr<CXFA_FMSimpleExpression> pExpCall; - NextToken(); - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions; - if (m_pToken->m_type != TOKrparen) { - while (m_pToken->m_type != TOKrparen) { - std::unique_ptr<CXFA_FMSimpleExpression> exp = - ParseSimpleExpression(); - expressions.push_back(std::move(exp)); - if (m_pToken->m_type == TOKcomma) { - NextToken(); - } else if (m_pToken->m_type == TOKeof || - m_pToken->m_type == TOKreserver) { - break; - } - } - if (m_pToken->m_type != TOKrparen) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str()); - } - } - if (m_pErrorInfo->message.IsEmpty()) { - std::unique_ptr<CXFA_FMSimpleExpression> pIdentifier = - pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempLine, - tempStr); - pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>( - line, std::move(pIdentifier), std::move(expressions), true); - expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>( - line, std::move(expr), std::move(pExpCall)); - NextToken(); - if (m_pToken->m_type != TOKlbracket) - continue; - - std::unique_ptr<CXFA_FMSimpleExpression> s = - ParseIndexExpression(); - if (s) { - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - line, std::move(expr), TOKcall, L"", std::move(s)); - } else { - expr.reset(); - } - } else { - expr.reset(); - } - } else if (m_pToken->m_type == TOKlbracket) { - std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); - if (!(m_pErrorInfo->message.IsEmpty())) - return nullptr; - - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - tempLine, std::move(expr), TOKdot, tempStr, std::move(s)); - } else { - std::unique_ptr<CXFA_FMSimpleExpression> s = - pdfium::MakeUnique<CXFA_FMIndexExpression>( - tempLine, ACCESSOR_NO_INDEX, nullptr, false); - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - line, std::move(expr), TOKdot, tempStr, std::move(s)); - continue; - } - } else { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier, - ws_TempString.c_str()); - return expr; - } - break; - case TOKdotdot: - NextToken(); - if (m_pToken->m_type == TOKidentifier) { - CFX_WideStringC tempStr = m_pToken->m_wstring; - uint32_t tempLine = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type == TOKlbracket) { - std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); - if (!(m_pErrorInfo->message.IsEmpty())) { - return nullptr; - } - expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>( - tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s)); - } else { - std::unique_ptr<CXFA_FMSimpleExpression> s = - pdfium::MakeUnique<CXFA_FMIndexExpression>( - tempLine, ACCESSOR_NO_INDEX, nullptr, false); - expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>( - line, std::move(expr), TOKdotdot, tempStr, std::move(s)); - continue; - } - } else { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier, - ws_TempString.c_str()); - return expr; - } - break; - case TOKdotscream: - NextToken(); - if (m_pToken->m_type == TOKidentifier) { - CFX_WideStringC tempStr = m_pToken->m_wstring; - uint32_t tempLine = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type == TOKlbracket) { - std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression(); - if (!(m_pErrorInfo->message.IsEmpty())) - return nullptr; - - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s)); - } else { - std::unique_ptr<CXFA_FMSimpleExpression> s = - pdfium::MakeUnique<CXFA_FMIndexExpression>( - tempLine, ACCESSOR_NO_INDEX, nullptr, false); - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - line, std::move(expr), TOKdotscream, tempStr, std::move(s)); - continue; - } - } else { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedIdentifier, - ws_TempString.c_str()); - return expr; - } - break; - case TOKdotstar: { - std::unique_ptr<CXFA_FMSimpleExpression> s = - pdfium::MakeUnique<CXFA_FMIndexExpression>(line, ACCESSOR_NO_INDEX, - nullptr, false); - expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>( - line, std::move(expr), TOKdotstar, L"*", std::move(s)); - } break; - default: - return expr; - } - NextToken(); - } - return expr; -} - -std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseIndexExpression() { - std::unique_ptr<CXFA_FMSimpleExpression> pExp; - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> s; - XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX; - if (m_pToken->m_type == TOKmul) { - pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex, - std::move(s), true); - NextToken(); - if (m_pToken->m_type != TOKrbracket) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str()); - pExp.reset(); - } - return pExp; - } - if (m_pToken->m_type == TOKplus) { - accessorIndex = ACCESSOR_POSITIVE_INDEX; - NextToken(); - } else if (m_pToken->m_type == TOKminus) { - accessorIndex = ACCESSOR_NEGATIVE_INDEX; - NextToken(); - } - s = ParseSimpleExpression(); - if (m_pToken->m_type != TOKrbracket) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(TOKrparen), ws_TempString.c_str()); - } else { - pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex, - std::move(s), false); - } - return pExp; -} - -std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParse::ParseParenExpression() { - Check(TOKlparen); - - if (m_pToken->m_type == TOKrparen) { - Error(m_pToken->m_uLinenum, kFMErrExpectedNonEmptyExpression); - NextToken(); - return nullptr; - } - - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression(); - - while (m_pToken->m_type == TOKassign) { - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression(); - if (m_pErrorInfo->message.IsEmpty()) { - pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>( - line, TOKassign, std::move(pExp1), std::move(pExp2)); - } else { - pExp1.reset(); - } - } - Check(TOKrparen); - return pExp1; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseBlockExpression() { - uint32_t line = m_pToken->m_uLinenum; - std::unique_ptr<CXFA_FMExpression> expr; - std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; - - while (1) { - switch (m_pToken->m_type) { - case TOKeof: - case TOKendif: - case TOKelseif: - case TOKelse: - case TOKendwhile: - case TOKendfor: - case TOKend: - case TOKendfunc: - case TOKreserver: - break; - case TOKfunc: - expr = ParseFunction(); - if (expr) { - expressions.push_back(std::move(expr)); - } - continue; - default: - expr = ParseExpression(); - if (expr) { - expressions.push_back(std::move(expr)); - } - continue; - } - break; - } - std::unique_ptr<CXFA_FMBlockExpression> pExp; - if (m_pErrorInfo->message.IsEmpty()) { - pExp = pdfium::MakeUnique<CXFA_FMBlockExpression>(line, - std::move(expressions)); - } - return pExp; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseIfExpression() { - uint32_t line = m_pToken->m_uLinenum; - const FX_WCHAR* pStartPos = m_lexer->SavePos(); - NextToken(); - Check(TOKlparen); - std::unique_ptr<CXFA_FMSimpleExpression> pExpression; - while (m_pToken->m_type != TOKrparen) { - pExpression = ParseSimpleExpression(); - if (m_pToken->m_type != TOKcomma) - break; - NextToken(); - } - Check(TOKrparen); - if (m_pToken->m_type != TOKthen) { - m_lexer->SetCurrentLine(line); - m_pToken = new CXFA_FMToken(line); - m_pToken->m_type = TOKidentifier; - m_pToken->m_wstring = L"if"; - m_lexer->SetToken(m_pToken); - m_lexer->RestorePos(pStartPos); - return ParseExpExpression(); - } - Check(TOKthen); - std::unique_ptr<CXFA_FMExpression> pIfExpression = ParseBlockExpression(); - std::unique_ptr<CXFA_FMExpression> pElseExpression; - switch (m_pToken->m_type) { - case TOKeof: - case TOKendif: - Check(TOKendif); - break; - case TOKif: - pElseExpression = ParseIfExpression(); - Check(TOKendif); - break; - case TOKelseif: - pElseExpression = ParseIfExpression(); - break; - case TOKelse: - NextToken(); - pElseExpression = ParseBlockExpression(); - Check(TOKendif); - break; - default: - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedEndIf, ws_TempString.c_str()); - NextToken(); - break; - } - std::unique_ptr<CXFA_FMIfExpression> pExp; - if (m_pErrorInfo->message.IsEmpty()) { - pExp = pdfium::MakeUnique<CXFA_FMIfExpression>(line, std::move(pExpression), - std::move(pIfExpression), - std::move(pElseExpression)); - } - return pExp; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseWhileExpression() { - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression(); - Check(TOKdo); - std::unique_ptr<CXFA_FMExpression> pExpression = ParseBlockExpression(); - Check(TOKendwhile); - std::unique_ptr<CXFA_FMExpression> expr; - if (m_pErrorInfo->message.IsEmpty()) { - expr = pdfium::MakeUnique<CXFA_FMWhileExpression>( - line, std::move(pCondition), std::move(pExpression)); - } - return expr; -} - -std::unique_ptr<CXFA_FMSimpleExpression> -CXFA_FMParse::ParseSubassignmentInForExpression() { - std::unique_ptr<CXFA_FMSimpleExpression> expr; - switch (m_pToken->m_type) { - case TOKidentifier: - expr = ParseSimpleExpression(); - break; - default: - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression, - ws_TempString.c_str()); - NextToken(); - break; - } - return expr; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForExpression() { - CFX_WideStringC wsVariant; - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type != TOKidentifier) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str()); - } - wsVariant = m_pToken->m_wstring; - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> pAssignment; - if (m_pToken->m_type == TOKassign) { - NextToken(); - pAssignment = ParseSimpleExpression(); - } else { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str()); - } - int32_t iDirection = 0; - if (m_pToken->m_type == TOKupto) { - iDirection = 1; - } else if (m_pToken->m_type == TOKdownto) { - iDirection = -1; - } else { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, L"upto or downto", - ws_TempString.c_str()); - } - NextToken(); - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> pStep; - if (m_pToken->m_type == TOKstep) { - NextToken(); - pStep = ParseSimpleExpression(); - } - Check(TOKdo); - std::unique_ptr<CXFA_FMExpression> pList = ParseBlockExpression(); - Check(TOKendfor); - std::unique_ptr<CXFA_FMExpression> expr; - if (m_pErrorInfo->message.IsEmpty()) { - expr = pdfium::MakeUnique<CXFA_FMForExpression>( - line, wsVariant, std::move(pAssignment), std::move(pAccessor), - iDirection, std::move(pStep), std::move(pList)); - } - return expr; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseForeachExpression() { - std::unique_ptr<CXFA_FMExpression> expr; - CFX_WideStringC wsIdentifier; - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pAccessors; - std::unique_ptr<CXFA_FMExpression> pList; - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - if (m_pToken->m_type != TOKidentifier) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrExpectedToken, - XFA_FM_KeywordToString(m_pToken->m_type), ws_TempString.c_str()); - } - wsIdentifier = m_pToken->m_wstring; - NextToken(); - Check(TOKin); - Check(TOKlparen); - if (m_pToken->m_type == TOKrparen) { - CFX_WideString ws_TempString(m_pToken->m_wstring); - Error(m_pToken->m_uLinenum, kFMErrUnexpectedExpression, - ws_TempString.c_str()); - NextToken(); - } else { - while (m_pToken->m_type != TOKrparen) { - std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression(); - if (s) - pAccessors.push_back(std::move(s)); - if (m_pToken->m_type != TOKcomma) - break; - NextToken(); - } - Check(TOKrparen); - } - Check(TOKdo); - pList = ParseBlockExpression(); - Check(TOKendfor); - if (m_pErrorInfo->message.IsEmpty()) { - expr = pdfium::MakeUnique<CXFA_FMForeachExpression>( - line, wsIdentifier, std::move(pAccessors), std::move(pList)); - } - return expr; -} - -std::unique_ptr<CXFA_FMExpression> CXFA_FMParse::ParseDoExpression() { - uint32_t line = m_pToken->m_uLinenum; - NextToken(); - std::unique_ptr<CXFA_FMExpression> expr = ParseBlockExpression(); - Check(TOKend); - if (!m_pErrorInfo->message.IsEmpty()) - return nullptr; - - return pdfium::MakeUnique<CXFA_FMDoExpression>(line, std::move(expr)); -} diff --git a/xfa/fxfa/fm2js/xfa_fmparse.h b/xfa/fxfa/fm2js/xfa_fmparse.h deleted file mode 100644 index 8f2671d1b0d95959376a86003ecf4445898cc25d..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_fmparse.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_FMPARSE_H_ -#define XFA_FXFA_FM2JS_XFA_FMPARSE_H_ - -#include <memory> -#include <vector> - -#include "xfa/fxfa/fm2js/xfa_expression.h" -#include "xfa/fxfa/fm2js/xfa_lexer.h" - -class CXFA_FMParse { - public: - CXFA_FMParse(const CFX_WideStringC& wsFormcalc, CXFA_FMErrorInfo* pErrorInfo); - ~CXFA_FMParse(); - - void NextToken(); - void Check(XFA_FM_TOKEN op); - void Error(uint32_t lineNum, const FX_WCHAR* msg, ...); - std::vector<std::unique_ptr<CXFA_FMExpression>> ParseTopExpression(); - std::unique_ptr<CXFA_FMExpression> ParseFunction(); - std::unique_ptr<CXFA_FMExpression> ParseExpression(); - std::unique_ptr<CXFA_FMExpression> ParseVarExpression(); - std::unique_ptr<CXFA_FMExpression> ParseExpExpression(); - std::unique_ptr<CXFA_FMExpression> ParseBlockExpression(); - std::unique_ptr<CXFA_FMExpression> ParseIfExpression(); - std::unique_ptr<CXFA_FMExpression> ParseWhileExpression(); - std::unique_ptr<CXFA_FMExpression> ParseForExpression(); - std::unique_ptr<CXFA_FMExpression> ParseForeachExpression(); - std::unique_ptr<CXFA_FMExpression> ParseDoExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseParenExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseSimpleExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseSubassignmentInForExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseLogicalOrExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseLogicalAndExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseEqualityExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseRelationalExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseAddtiveExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseMultiplicativeExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParseUnaryExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParsePrimaryExpression(); - std::unique_ptr<CXFA_FMSimpleExpression> ParsePostExpression( - std::unique_ptr<CXFA_FMSimpleExpression> e); - std::unique_ptr<CXFA_FMSimpleExpression> ParseIndexExpression(); - - private: - std::unique_ptr<CXFA_FMLexer> m_lexer; - CXFA_FMToken* m_pToken; - CXFA_FMErrorInfo* const m_pErrorInfo; -}; - -#endif // XFA_FXFA_FM2JS_XFA_FMPARSE_H_ diff --git a/xfa/fxfa/fm2js/xfa_lexer.cpp b/xfa/fxfa/fm2js/xfa_lexer.cpp deleted file mode 100644 index 6e844bcdf05e478a54f57c7dcc809c31b9303424..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_lexer.cpp +++ /dev/null @@ -1,546 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_lexer.h" - -#include "core/fxcrt/fx_ext.h" - -namespace { - -struct XFA_FMDChar { - static const FX_WCHAR* inc(const FX_WCHAR*& p) { - ++p; - return p; - } - static const FX_WCHAR* dec(const FX_WCHAR*& p) { - --p; - return p; - } - static uint16_t get(const FX_WCHAR* p) { return *p; } - static bool isWhiteSpace(const FX_WCHAR* p) { - return (*p) == 0x09 || (*p) == 0x0b || (*p) == 0x0c || (*p) == 0x20; - } - static bool isLineTerminator(const FX_WCHAR* p) { - return *p == 0x0A || *p == 0x0D; - } - static bool isBinary(const FX_WCHAR* p) { return (*p) >= '0' && (*p) <= '1'; } - static bool isOctal(const FX_WCHAR* p) { return (*p) >= '0' && (*p) <= '7'; } - static bool isDigital(const FX_WCHAR* p) { - return (*p) >= '0' && (*p) <= '9'; - } - static bool isHex(const FX_WCHAR* p) { - return isDigital(p) || ((*p) >= 'a' && (*p) <= 'f') || - ((*p) >= 'A' && (*p) <= 'F'); - } - static bool isAlpha(const FX_WCHAR* p) { - return ((*p) <= 'z' && (*p) >= 'a') || ((*p) <= 'Z' && (*p) >= 'A'); - } - static bool isAvalid(const FX_WCHAR* p, bool flag = 0); - static bool string2number(const FX_WCHAR* s, - FX_DOUBLE* pValue, - const FX_WCHAR*& pEnd); - static bool isUnicodeAlpha(uint16_t ch); -}; - -inline bool XFA_FMDChar::isAvalid(const FX_WCHAR* p, bool flag) { - if (*p == 0) { - return 1; - } - if ((*p <= 0x0A && *p >= 0x09) || *p == 0x0D || - (*p <= 0xd7ff && *p >= 0x20) || (*p <= 0xfffd && *p >= 0xe000)) { - return 1; - } - if (!flag) { - if (*p == 0x0B || *p == 0x0C) { - return 1; - } - } - return 0; -} - -inline bool XFA_FMDChar::string2number(const FX_WCHAR* s, - FX_DOUBLE* pValue, - const FX_WCHAR*& pEnd) { - if (s) { - *pValue = wcstod((wchar_t*)s, (wchar_t**)&pEnd); - } - return 0; -} - -inline bool XFA_FMDChar::isUnicodeAlpha(uint16_t ch) { - if (ch == 0 || ch == 0x0A || ch == 0x0D || ch == 0x09 || ch == 0x0B || - ch == 0x0C || ch == 0x20 || ch == '.' || ch == ';' || ch == '"' || - ch == '=' || ch == '<' || ch == '>' || ch == ',' || ch == '(' || - ch == ')' || ch == ']' || ch == '[' || ch == '&' || ch == '|' || - ch == '+' || ch == '-' || ch == '*' || ch == '/') { - return false; - } - return true; -} - -const XFA_FMKeyword keyWords[] = { - {TOKand, 0x00000026, L"&"}, - {TOKlparen, 0x00000028, L"("}, - {TOKrparen, 0x00000029, L")"}, - {TOKmul, 0x0000002a, L"*"}, - {TOKplus, 0x0000002b, L"+"}, - {TOKcomma, 0x0000002c, L","}, - {TOKminus, 0x0000002d, L"-"}, - {TOKdot, 0x0000002e, L"."}, - {TOKdiv, 0x0000002f, L"/"}, - {TOKlt, 0x0000003c, L"<"}, - {TOKassign, 0x0000003d, L"="}, - {TOKgt, 0x0000003e, L">"}, - {TOKlbracket, 0x0000005b, L"["}, - {TOKrbracket, 0x0000005d, L"]"}, - {TOKor, 0x0000007c, L"|"}, - {TOKdotscream, 0x0000ec11, L".#"}, - {TOKdotstar, 0x0000ec18, L".*"}, - {TOKdotdot, 0x0000ec1c, L".."}, - {TOKle, 0x000133f9, L"<="}, - {TOKne, 0x000133fa, L"<>"}, - {TOKeq, 0x0001391a, L"=="}, - {TOKge, 0x00013e3b, L">="}, - {TOKdo, 0x00020153, L"do"}, - {TOKkseq, 0x00020676, L"eq"}, - {TOKksge, 0x000210ac, L"ge"}, - {TOKksgt, 0x000210bb, L"gt"}, - {TOKif, 0x00021aef, L"if"}, - {TOKin, 0x00021af7, L"in"}, - {TOKksle, 0x00022a51, L"le"}, - {TOKkslt, 0x00022a60, L"lt"}, - {TOKksne, 0x00023493, L"ne"}, - {TOKksor, 0x000239c1, L"or"}, - {TOKnull, 0x052931bb, L"null"}, - {TOKbreak, 0x05518c25, L"break"}, - {TOKksand, 0x09f9db33, L"and"}, - {TOKend, 0x0a631437, L"end"}, - {TOKeof, 0x0a63195a, L"eof"}, - {TOKfor, 0x0a7d67a7, L"for"}, - {TOKnan, 0x0b4f91dd, L"nan"}, - {TOKksnot, 0x0b4fd9b1, L"not"}, - {TOKvar, 0x0c2203e9, L"var"}, - {TOKthen, 0x2d5738cf, L"then"}, - {TOKelse, 0x45f65ee9, L"else"}, - {TOKexit, 0x4731d6ba, L"exit"}, - {TOKdownto, 0x4caadc3b, L"downto"}, - {TOKreturn, 0x4db8bd60, L"return"}, - {TOKinfinity, 0x5c0a010a, L"infinity"}, - {TOKendwhile, 0x5c64bff0, L"endwhile"}, - {TOKforeach, 0x67e31f38, L"foreach"}, - {TOKendfunc, 0x68f984a3, L"endfunc"}, - {TOKelseif, 0x78253218, L"elseif"}, - {TOKwhile, 0x84229259, L"while"}, - {TOKendfor, 0x8ab49d7e, L"endfor"}, - {TOKthrow, 0x8db05c94, L"throw"}, - {TOKstep, 0xa7a7887c, L"step"}, - {TOKupto, 0xb5155328, L"upto"}, - {TOKcontinue, 0xc0340685, L"continue"}, - {TOKfunc, 0xcdce60ec, L"func"}, - {TOKendif, 0xe0e8fee6, L"endif"}, -}; - -const XFA_FM_TOKEN KEYWORD_START = TOKdo; -const XFA_FM_TOKEN KEYWORD_END = TOKendif; - -} // namespace - -const FX_WCHAR* XFA_FM_KeywordToString(XFA_FM_TOKEN op) { - if (op < KEYWORD_START || op > KEYWORD_END) - return L""; - return keyWords[op].m_keyword; -} - -CXFA_FMToken::CXFA_FMToken() : m_type(TOKreserver), m_uLinenum(1) {} - -CXFA_FMToken::CXFA_FMToken(uint32_t uLineNum) - : m_type(TOKreserver), m_uLinenum(uLineNum) {} - -CXFA_FMLexer::CXFA_FMLexer(const CFX_WideStringC& wsFormCalc, - CXFA_FMErrorInfo* pErrorInfo) - : m_ptr(wsFormCalc.c_str()), m_uCurrentLine(1), m_pErrorInfo(pErrorInfo) {} - -CXFA_FMLexer::~CXFA_FMLexer() {} - -CXFA_FMToken* CXFA_FMLexer::NextToken() { - m_pToken.reset(Scan()); - return m_pToken.get(); -} - -CXFA_FMToken* CXFA_FMLexer::Scan() { - uint16_t ch = 0; - CXFA_FMToken* p = new CXFA_FMToken(m_uCurrentLine); - if (!XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - int iRet = 0; - while (1) { - if (!XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - ch = XFA_FMDChar::get(m_ptr); - switch (ch) { - case 0: - p->m_type = TOKeof; - return p; - case 0x0A: - ++m_uCurrentLine; - p->m_uLinenum = m_uCurrentLine; - XFA_FMDChar::inc(m_ptr); - break; - case 0x0D: - XFA_FMDChar::inc(m_ptr); - break; - case ';': { - const FX_WCHAR* pTemp = 0; - Comment(m_ptr, pTemp); - m_ptr = pTemp; - } break; - case '"': { - const FX_WCHAR* pTemp = 0; - p->m_type = TOKstring; - iRet = String(p, m_ptr, pTemp); - m_ptr = pTemp; - } - return p; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - p->m_type = TOKnumber; - const FX_WCHAR* pTemp = 0; - iRet = Number(p, m_ptr, pTemp); - m_ptr = pTemp; - if (iRet) { - Error(kFMErrBadSuffixNumber); - return p; - } - } - return p; - case '=': - XFA_FMDChar::inc(m_ptr); - if (XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - if (ch == '=') { - p->m_type = TOKeq; - XFA_FMDChar::inc(m_ptr); - return p; - } else { - p->m_type = TOKassign; - return p; - } - } else { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - break; - case '<': - XFA_FMDChar::inc(m_ptr); - if (XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - if (ch == '=') { - p->m_type = TOKle; - XFA_FMDChar::inc(m_ptr); - return p; - } else if (ch == '>') { - p->m_type = TOKne; - XFA_FMDChar::inc(m_ptr); - return p; - } else { - p->m_type = TOKlt; - return p; - } - } else { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - break; - case '>': - XFA_FMDChar::inc(m_ptr); - if (XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - if (ch == '=') { - p->m_type = TOKge; - XFA_FMDChar::inc(m_ptr); - return p; - } else { - p->m_type = TOKgt; - return p; - } - } else { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - break; - case ',': - p->m_type = TOKcomma; - XFA_FMDChar::inc(m_ptr); - return p; - case '(': - p->m_type = TOKlparen; - XFA_FMDChar::inc(m_ptr); - return p; - case ')': - p->m_type = TOKrparen; - XFA_FMDChar::inc(m_ptr); - return p; - case '[': - p->m_type = TOKlbracket; - XFA_FMDChar::inc(m_ptr); - return p; - case ']': - p->m_type = TOKrbracket; - XFA_FMDChar::inc(m_ptr); - return p; - case '&': - XFA_FMDChar::inc(m_ptr); - p->m_type = TOKand; - return p; - case '|': - XFA_FMDChar::inc(m_ptr); - p->m_type = TOKor; - return p; - case '+': - XFA_FMDChar::inc(m_ptr); - p->m_type = TOKplus; - return p; - case '-': - XFA_FMDChar::inc(m_ptr); - p->m_type = TOKminus; - return p; - case '*': - XFA_FMDChar::inc(m_ptr); - p->m_type = TOKmul; - return p; - case '/': - XFA_FMDChar::inc(m_ptr); - if (XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - if (ch == '/') { - const FX_WCHAR* pTemp = 0; - Comment(m_ptr, pTemp); - m_ptr = pTemp; - break; - } else { - p->m_type = TOKdiv; - return p; - } - } else { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - break; - case '.': - XFA_FMDChar::inc(m_ptr); - if (XFA_FMDChar::isAvalid(m_ptr)) { - ch = XFA_FMDChar::get(m_ptr); - if (ch == '.') { - p->m_type = TOKdotdot; - XFA_FMDChar::inc(m_ptr); - return p; - } else if (ch == '*') { - p->m_type = TOKdotstar; - XFA_FMDChar::inc(m_ptr); - return p; - } else if (ch == '#') { - p->m_type = TOKdotscream; - XFA_FMDChar::inc(m_ptr); - return p; - } else if (ch <= '9' && ch >= '0') { - p->m_type = TOKnumber; - const FX_WCHAR* pTemp = 0; - XFA_FMDChar::dec(m_ptr); - iRet = Number(p, m_ptr, pTemp); - m_ptr = pTemp; - if (iRet) { - Error(kFMErrBadSuffixNumber); - } - return p; - } else { - p->m_type = TOKdot; - return p; - } - } else { - ch = XFA_FMDChar::get(m_ptr); - Error(kFMErrUnsupportedChar, ch); - return p; - } - case 0x09: - case 0x0B: - case 0x0C: - case 0x20: - XFA_FMDChar::inc(m_ptr); - break; - default: { - const FX_WCHAR* pTemp = 0; - iRet = Identifiers(p, m_ptr, pTemp); - m_ptr = pTemp; - if (iRet) { - return p; - } - p->m_type = IsKeyword(p->m_wstring); - } - return p; - } - } -} - -uint32_t CXFA_FMLexer::Number(CXFA_FMToken* t, - const FX_WCHAR* p, - const FX_WCHAR*& pEnd) { - FX_DOUBLE number = 0; - if (XFA_FMDChar::string2number(p, &number, pEnd)) { - return 1; - } - if (pEnd && XFA_FMDChar::isAlpha(pEnd)) { - return 1; - } - t->m_wstring = CFX_WideStringC(p, (pEnd - p)); - return 0; -} - -uint32_t CXFA_FMLexer::String(CXFA_FMToken* t, - const FX_WCHAR* p, - const FX_WCHAR*& pEnd) { - const FX_WCHAR* pStart = p; - uint16_t ch = 0; - XFA_FMDChar::inc(p); - ch = XFA_FMDChar::get(p); - while (ch) { - if (!XFA_FMDChar::isAvalid(p)) { - ch = XFA_FMDChar::get(p); - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - Error(kFMErrUnsupportedChar, ch); - return 1; - } - if (ch == '"') { - XFA_FMDChar::inc(p); - if (!XFA_FMDChar::isAvalid(p)) { - ch = XFA_FMDChar::get(p); - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - Error(kFMErrUnsupportedChar, ch); - return 1; - } - ch = XFA_FMDChar::get(p); - if (ch == '"') { - goto NEXT; - } else { - break; - } - } - NEXT: - XFA_FMDChar::inc(p); - ch = XFA_FMDChar::get(p); - } - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - return 0; -} - -uint32_t CXFA_FMLexer::Identifiers(CXFA_FMToken* t, - const FX_WCHAR* p, - const FX_WCHAR*& pEnd) { - const FX_WCHAR* pStart = p; - uint16_t ch = 0; - ch = XFA_FMDChar::get(p); - XFA_FMDChar::inc(p); - if (!XFA_FMDChar::isAvalid(p)) { - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - Error(kFMErrUnsupportedChar, ch); - return 1; - } - ch = XFA_FMDChar::get(p); - while (ch) { - if (!XFA_FMDChar::isAvalid(p)) { - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - Error(kFMErrUnsupportedChar, ch); - return 1; - } - ch = XFA_FMDChar::get(p); - if (XFA_FMDChar::isUnicodeAlpha(ch)) { - XFA_FMDChar::inc(p); - } else { - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - return 0; - } - } - pEnd = p; - t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart)); - return 0; -} - -void CXFA_FMLexer::Comment(const FX_WCHAR* p, const FX_WCHAR*& pEnd) { - unsigned ch = 0; - XFA_FMDChar::inc(p); - ch = XFA_FMDChar::get(p); - while (ch) { - if (ch == 0x0D) { - XFA_FMDChar::inc(p); - pEnd = p; - return; - } - if (ch == 0x0A) { - ++m_uCurrentLine; - XFA_FMDChar::inc(p); - pEnd = p; - return; - } - XFA_FMDChar::inc(p); - ch = XFA_FMDChar::get(p); - } - pEnd = p; -} - -XFA_FM_TOKEN CXFA_FMLexer::IsKeyword(const CFX_WideStringC& str) { - uint32_t uHash = FX_HashCode_GetW(str, true); - int32_t iStart = KEYWORD_START; - int32_t iEnd = KEYWORD_END; - do { - int32_t iMid = (iStart + iEnd) / 2; - XFA_FMKeyword keyword = keyWords[iMid]; - if (uHash == keyword.m_uHash) - return keyword.m_type; - if (uHash < keyword.m_uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return TOKidentifier; -} - -void CXFA_FMLexer::Error(const FX_WCHAR* msg, ...) { - m_pErrorInfo->linenum = m_uCurrentLine; - va_list ap; - va_start(ap, msg); - m_pErrorInfo->message.FormatV(msg, ap); - va_end(ap); -} - -bool CXFA_FMLexer::HasError() const { - if (m_pErrorInfo->message.IsEmpty()) { - return false; - } - return true; -} diff --git a/xfa/fxfa/fm2js/xfa_lexer.h b/xfa/fxfa/fm2js/xfa_lexer.h deleted file mode 100644 index 9395c06814f8175c6d957fc5e2fe7f9cf9720e0c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_lexer.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_LEXER_H_ -#define XFA_FXFA_FM2JS_XFA_LEXER_H_ - -#include <memory> - -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/fm2js/xfa_error.h" - -enum XFA_FM_TOKEN { - TOKand, - TOKlparen, - TOKrparen, - TOKmul, - TOKplus, - TOKcomma, - TOKminus, - TOKdot, - TOKdiv, - TOKlt, - TOKassign, - TOKgt, - TOKlbracket, - TOKrbracket, - TOKor, - TOKdotscream, - TOKdotstar, - TOKdotdot, - TOKle, - TOKne, - TOKeq, - TOKge, - TOKdo, - TOKkseq, - TOKksge, - TOKksgt, - TOKif, - TOKin, - TOKksle, - TOKkslt, - TOKksne, - TOKksor, - TOKnull, - TOKbreak, - TOKksand, - TOKend, - TOKeof, - TOKfor, - TOKnan, - TOKksnot, - TOKvar, - TOKthen, - TOKelse, - TOKexit, - TOKdownto, - TOKreturn, - TOKinfinity, - TOKendwhile, - TOKforeach, - TOKendfunc, - TOKelseif, - TOKwhile, - TOKendfor, - TOKthrow, - TOKstep, - TOKupto, - TOKcontinue, - TOKfunc, - TOKendif, - TOKstar, - TOKidentifier, - TOKunderscore, - TOKdollar, - TOKexclamation, - TOKcall, - TOKstring, - TOKnumber, - TOKreserver -}; - -struct XFA_FMKeyword { - XFA_FM_TOKEN m_type; - uint32_t m_uHash; - const FX_WCHAR* m_keyword; -}; - -const FX_WCHAR* XFA_FM_KeywordToString(XFA_FM_TOKEN op); - -class CXFA_FMToken { - public: - CXFA_FMToken(); - explicit CXFA_FMToken(uint32_t uLineNum); - - CFX_WideStringC m_wstring; - XFA_FM_TOKEN m_type; - uint32_t m_uLinenum; -}; - -class CXFA_FMLexer { - public: - CXFA_FMLexer(const CFX_WideStringC& wsFormcalc, CXFA_FMErrorInfo* pErrorInfo); - ~CXFA_FMLexer(); - - CXFA_FMToken* NextToken(); - uint32_t Number(CXFA_FMToken* t, const FX_WCHAR* p, const FX_WCHAR*& pEnd); - uint32_t String(CXFA_FMToken* t, const FX_WCHAR* p, const FX_WCHAR*& pEnd); - uint32_t Identifiers(CXFA_FMToken* t, - const FX_WCHAR* p, - const FX_WCHAR*& pEnd); - void Comment(const FX_WCHAR* p, const FX_WCHAR*& pEnd); - XFA_FM_TOKEN IsKeyword(const CFX_WideStringC& p); - void SetCurrentLine(uint32_t line) { m_uCurrentLine = line; } - void SetToken(CXFA_FMToken* pToken) { - if (m_pToken.get() != pToken) - m_pToken.reset(pToken); - } - const FX_WCHAR* SavePos() { return m_ptr; } - void RestorePos(const FX_WCHAR* pPos) { m_ptr = pPos; } - void Error(const FX_WCHAR* msg, ...); - bool HasError() const; - - protected: - CXFA_FMToken* Scan(); - - const FX_WCHAR* m_ptr; - uint32_t m_uCurrentLine; - std::unique_ptr<CXFA_FMToken> m_pToken; - CXFA_FMErrorInfo* m_pErrorInfo; -}; - -#endif // XFA_FXFA_FM2JS_XFA_LEXER_H_ diff --git a/xfa/fxfa/fm2js/xfa_program.cpp b/xfa/fxfa/fm2js/xfa_program.cpp deleted file mode 100644 index 514b7a6a23b70eda20e54becec5b19bcedaf99b5..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_program.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_program.h" - -#include <utility> -#include <vector> - -#include "third_party/base/ptr_util.h" - -CXFA_FMProgram::CXFA_FMProgram(const CFX_WideStringC& wsFormcalc) - : m_parse(wsFormcalc, &m_pErrorInfo) {} - -CXFA_FMProgram::~CXFA_FMProgram() {} - -int32_t CXFA_FMProgram::ParseProgram() { - m_parse.NextToken(); - if (!m_pErrorInfo.message.IsEmpty()) - return -1; - - std::vector<std::unique_ptr<CXFA_FMExpression>> expressions = - m_parse.ParseTopExpression(); - if (!m_pErrorInfo.message.IsEmpty()) - return -1; - - std::vector<CFX_WideStringC> arguments; - m_globalFunction = pdfium::MakeUnique<CXFA_FMFunctionDefinition>( - 1, true, L"", std::move(arguments), std::move(expressions)); - return 0; -} - -int32_t CXFA_FMProgram::TranslateProgram(CFX_WideTextBuf& wsJavaScript) { - m_globalFunction->ToJavaScript(wsJavaScript); - wsJavaScript.AppendChar(0); - return 0; -} diff --git a/xfa/fxfa/fm2js/xfa_program.h b/xfa/fxfa/fm2js/xfa_program.h deleted file mode 100644 index 7a2dade6fd170c502813c8caed3f36b666fce9ca..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_program.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_PROGRAM_H_ -#define XFA_FXFA_FM2JS_XFA_PROGRAM_H_ - -#include <memory> - -#include "xfa/fxfa/fm2js/xfa_error.h" -#include "xfa/fxfa/fm2js/xfa_fmparse.h" - -class CXFA_FMProgram { - public: - explicit CXFA_FMProgram(const CFX_WideStringC& wsFormcalc); - ~CXFA_FMProgram(); - - int32_t ParseProgram(); - int32_t TranslateProgram(CFX_WideTextBuf& wsJavaScript); - - const CXFA_FMErrorInfo& GetError() const { return m_pErrorInfo; } - - private: - CXFA_FMErrorInfo m_pErrorInfo; - CXFA_FMParse m_parse; - std::unique_ptr<CXFA_FMFunctionDefinition> m_globalFunction; -}; - -#endif // XFA_FXFA_FM2JS_XFA_PROGRAM_H_ diff --git a/xfa/fxfa/fm2js/xfa_simpleexpression.cpp b/xfa/fxfa/fm2js/xfa_simpleexpression.cpp deleted file mode 100644 index 686ddaa17dc57ed5eda0bbd60d4b5462563c8f36..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_simpleexpression.cpp +++ /dev/null @@ -1,761 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/fm2js/xfa_simpleexpression.h" - -#include <utility> - -#include "core/fxcrt/fx_ext.h" - -namespace { - -const FX_WCHAR* const gs_lpStrExpFuncName[] = { - L"foxit_xfa_formcalc_runtime.assign_value_operator", - L"foxit_xfa_formcalc_runtime.logical_or_operator", - L"foxit_xfa_formcalc_runtime.logical_and_operator", - L"foxit_xfa_formcalc_runtime.equality_operator", - L"foxit_xfa_formcalc_runtime.notequality_operator", - L"foxit_xfa_formcalc_runtime.less_operator", - L"foxit_xfa_formcalc_runtime.lessequal_operator", - L"foxit_xfa_formcalc_runtime.greater_operator", - L"foxit_xfa_formcalc_runtime.greaterequal_operator", - L"foxit_xfa_formcalc_runtime.plus_operator", - L"foxit_xfa_formcalc_runtime.minus_operator", - L"foxit_xfa_formcalc_runtime.multiple_operator", - L"foxit_xfa_formcalc_runtime.divide_operator", - L"foxit_xfa_formcalc_runtime.positive_operator", - L"foxit_xfa_formcalc_runtime.negative_operator", - L"foxit_xfa_formcalc_runtime.logical_not_operator", - L"foxit_xfa_formcalc_runtime.", - L"foxit_xfa_formcalc_runtime.dot_accessor", - L"foxit_xfa_formcalc_runtime.dotdot_accessor", - L"foxit_xfa_formcalc_runtime.concat_fm_object", - L"foxit_xfa_formcalc_runtime.is_fm_object", - L"foxit_xfa_formcalc_runtime.is_fm_array", - L"foxit_xfa_formcalc_runtime.get_fm_value", - L"foxit_xfa_formcalc_runtime.get_fm_jsobj", - L"foxit_xfa_formcalc_runtime.fm_var_filter", -}; - -struct XFA_FMBuildInFunc { - uint32_t m_uHash; - const FX_WCHAR* m_buildinfunc; -}; - -const XFA_FMBuildInFunc g_BuildInFuncs[] = { - {0x0001f1f5, L"At"}, {0x00020b9c, L"FV"}, - {0x00021aef, L"If"}, {0x00023ee6, L"PV"}, - {0x04b5c9ee, L"Encode"}, {0x08e96685, L"DateFmt"}, - {0x09f99db6, L"Abs"}, {0x09f9e583, L"Apr"}, - {0x09fa043e, L"Avg"}, {0x0a9782a0, L"Get"}, - {0x0b1b09df, L"Len"}, {0x0b3543a6, L"Max"}, - {0x0b356ca4, L"Min"}, {0x0b358b60, L"Mod"}, - {0x0b4fded4, L"NPV"}, {0x0b846bf1, L"Pmt"}, - {0x0b8494f9, L"Put"}, {0x0bb8df5d, L"Ref"}, - {0x0bd37a99, L"Str"}, {0x0bd37fb5, L"Sum"}, - {0x1048469b, L"Cterm"}, {0x11e03660, L"Exists"}, - {0x126236e6, L"Post"}, {0x127c6661, L"PPmt"}, - {0x193ade3e, L"Right"}, {0x1ec8ab2c, L"Rate"}, - {0x20e476dc, L"IsoTime2Num"}, {0x23eb6816, L"TimeFmt"}, - {0x24fb17b0, L"LocalDateFmt"}, {0x28dee6e9, L"Format"}, - {0x2d0890b8, L"Term"}, {0x2d71b00f, L"Time"}, - {0x2f890fb1, L"Num2Time"}, {0x3767511d, L"Ceil"}, - {0x3ffd1941, L"LocalTimeFmt"}, {0x442f68c8, L"Round"}, - {0x46fd1128, L"Eval"}, {0x4d629440, L"Date2Num"}, - {0x4dcf25f8, L"Concat"}, {0x4e00255d, L"UnitValue"}, - {0x55a5cc29, L"Lower"}, {0x5e43e04c, L"WordNum"}, - {0x620ce6ba, L"Ipmt"}, {0x6f544d49, L"Count"}, - {0x7e241013, L"Within"}, {0x9b9a6e2b, L"IsoDate2Num"}, - {0xb2c941c2, L"UnitType"}, {0xb598a1f7, L"Uuid"}, - {0xbde9abde, L"Date"}, {0xc0010b80, L"Num2Date"}, - {0xc1f6144c, L"Upper"}, {0xc44028f7, L"Oneof"}, - {0xc62c1b2c, L"Space"}, {0xd0ff50f9, L"HasValue"}, - {0xd1537042, L"Floor"}, {0xd2ac9cf1, L"Time2Num"}, - {0xd907aee5, L"Num2GMTime"}, {0xdf24f7c4, L"Decode"}, - {0xe2664803, L"Substr"}, {0xe3e7b528, L"Stuff"}, - {0xe6792d4e, L"Rtrim"}, {0xe8c23f5b, L"Parse"}, - {0xea18d121, L"Choose"}, {0xebfef69c, L"Replace"}, - {0xf5ad782b, L"Left"}, {0xf7bb2248, L"Ltrim"}, -}; - -struct XFA_FMSOMMethod { - uint32_t m_uHash; - const FX_WCHAR* m_wsSomMethodName; - uint32_t m_dParameters; -}; -const XFA_FMSOMMethod gs_FMSomMethods[] = { - {0x00000068, L"h", 0x01}, - {0x00000077, L"w", 0x01}, - {0x00000078, L"x", 0x01}, - {0x00000079, L"y", 0x01}, - {0x05eb5b0f, L"pageSpan", 0x01}, - {0x10f1b1bd, L"page", 0x01}, - {0x3bf1c2a5, L"absPageSpan", 0x01}, - {0x3c752495, L"verify", 0x0d}, - {0x44c352ad, L"formNodes", 0x01}, - {0x5775c2cc, L"absPageInBatch", 0x01}, - {0x5ee00996, L"setElement", 0x01}, - {0x7033bfd5, L"insert", 0x03}, - {0x8c5feb32, L"sheetInBatch", 0x01}, - {0x8f3a8379, L"sheet", 0x01}, - {0x92dada4f, L"saveFilteredXML", 0x01}, - {0x9cab7cae, L"remove", 0x01}, - {0xa68635f1, L"sign", 0x61}, - {0xaac241c8, L"isRecordGroup", 0x01}, - {0xd8ed1467, L"clear", 0x01}, - {0xda12e518, L"append", 0x01}, - {0xe74f0653, L"absPage", 0x01}, -}; - -} // namespace - -CFX_WideStringC XFA_FM_EXPTypeToString( - XFA_FM_SimpleExpressionType simpleExpType) { - return gs_lpStrExpFuncName[simpleExpType]; -} - -CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op) - : m_line(line), m_op(op) {} - -void CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} - -void CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {} - -XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const { - return m_op; -} - -CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line) - : CXFA_FMSimpleExpression(line, TOKnull) {} - -void CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"null"; -} - -CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line, - CFX_WideStringC wsNumber) - : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {} - -CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {} - -void CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << m_wsNumber; -} - -CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line, - CFX_WideStringC wsString) - : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {} - -CXFA_FMStringExpression::~CXFA_FMStringExpression() {} - -void CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - CFX_WideString tempStr(m_wsString); - if (tempStr.GetLength() > 2) { - javascript.AppendChar(L'\"'); - FX_WCHAR oneChar; - for (int16_t i = 1; i < tempStr.GetLength() - 1; i++) { - oneChar = tempStr[i]; - switch (oneChar) { - case L'\"': { - i++; - javascript << L"\\\""; - } break; - case 0x0d: - break; - case 0x0a: { - javascript << L"\\n"; - } break; - default: { javascript.AppendChar(oneChar); } break; - } - } - javascript.AppendChar(L'\"'); - } else { - javascript << tempStr; - } -} - -CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression( - uint32_t line, - CFX_WideStringC wsIdentifier) - : CXFA_FMSimpleExpression(line, TOKidentifier), - m_wsIdentifier(wsIdentifier) {} - -CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {} - -void CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - CFX_WideString tempStr(m_wsIdentifier); - if (tempStr == L"$") { - tempStr = L"this"; - } else if (tempStr == L"!") { - tempStr = L"xfa.datasets"; - } else if (tempStr == L"$data") { - tempStr = L"xfa.datasets.data"; - } else if (tempStr == L"$event") { - tempStr = L"xfa.event"; - } else if (tempStr == L"$form") { - tempStr = L"xfa.form"; - } else if (tempStr == L"$host") { - tempStr = L"xfa.host"; - } else if (tempStr == L"$layout") { - tempStr = L"xfa.layout"; - } else if (tempStr == L"$template") { - tempStr = L"xfa.template"; - } else if (tempStr[0] == L'!') { - tempStr = EXCLAMATION_IN_IDENTIFIER + tempStr.Mid(1); - } - javascript << tempStr; -} - -CXFA_FMUnaryExpression::CXFA_FMUnaryExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp) - : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {} - -CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {} - -void CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} - -CXFA_FMBinExpression::CXFA_FMBinExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMSimpleExpression(line, op), - m_pExp1(std::move(pExp1)), - m_pExp2(std::move(pExp2)) {} - -CXFA_FMBinExpression::~CXFA_FMBinExpression() {} - -void CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} - -CXFA_FMAssignExpression::CXFA_FMAssignExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"if ("; - javascript << gs_lpStrExpFuncName[ISFMOBJECT]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L"))\n{\n"; - javascript << gs_lpStrExpFuncName[ASSIGN]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L");\n}\n"; - CFX_WideTextBuf tempExp1; - m_pExp1->ToJavaScript(tempExp1); - if (m_pExp1->GetOperatorToken() == TOKidentifier && - tempExp1.AsStringC() != L"this") { - javascript << L"else\n{\n"; - javascript << tempExp1; - javascript << L" = "; - javascript << gs_lpStrExpFuncName[ASSIGN]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L");\n}\n"; - } -} - -void CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { - javascript << L"if ("; - javascript << gs_lpStrExpFuncName[ISFMOBJECT]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L"))\n{\n"; - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = "; - javascript << gs_lpStrExpFuncName[ASSIGN]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L");\n}\n"; - CFX_WideTextBuf tempExp1; - m_pExp1->ToJavaScript(tempExp1); - if (m_pExp1->GetOperatorToken() == TOKidentifier && - tempExp1.AsStringC() != L"this") { - javascript << L"else\n{\n"; - javascript << RUNTIMEFUNCTIONRETURNVALUE; - javascript << L" = "; - javascript << tempExp1; - javascript << L" = "; - javascript << gs_lpStrExpFuncName[ASSIGN]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L");\n}\n"; - } -} - -CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[LOGICALOR]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[LOGICALAND]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMEqualityExpression::CXFA_FMEqualityExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - switch (m_op) { - case TOKeq: - case TOKkseq: - javascript << gs_lpStrExpFuncName[EQUALITY]; - break; - case TOKne: - case TOKksne: - javascript << gs_lpStrExpFuncName[NOTEQUALITY]; - break; - default: - ASSERT(false); - break; - } - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMRelationalExpression::CXFA_FMRelationalExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - switch (m_op) { - case TOKlt: - case TOKkslt: - javascript << gs_lpStrExpFuncName[LESS]; - break; - case TOKgt: - case TOKksgt: - javascript << gs_lpStrExpFuncName[GREATER]; - break; - case TOKle: - case TOKksle: - javascript << gs_lpStrExpFuncName[LESSEQUAL]; - break; - case TOKge: - case TOKksge: - javascript << gs_lpStrExpFuncName[GREATEREQUAL]; - break; - default: - ASSERT(false); - break; - } - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - switch (m_op) { - case TOKplus: - javascript << gs_lpStrExpFuncName[PLUS]; - break; - case TOKminus: - javascript << gs_lpStrExpFuncName[MINUS]; - break; - default: - ASSERT(false); - break; - } - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2) - : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} - -void CXFA_FMMultiplicativeExpression::ToJavaScript( - CFX_WideTextBuf& javascript) { - switch (m_op) { - case TOKmul: - javascript << gs_lpStrExpFuncName[MULTIPLE]; - break; - case TOKdiv: - javascript << gs_lpStrExpFuncName[DIVIDE]; - break; - default: - ASSERT(false); - break; - } - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMPosExpression::CXFA_FMPosExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp) - : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {} - -void CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[POSITIVE]; - javascript << L"("; - m_pExp->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMNegExpression::CXFA_FMNegExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp) - : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {} - -void CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[NEGATIVE]; - javascript << L"("; - m_pExp->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMNotExpression::CXFA_FMNotExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp) - : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {} - -void CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[NOT]; - javascript << L"("; - m_pExp->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMCallExpression::CXFA_FMCallExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp, - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments, - bool bIsSomMethod) - : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)), - m_bIsSomMethod(bIsSomMethod), - m_Arguments(std::move(pArguments)) {} - -CXFA_FMCallExpression::~CXFA_FMCallExpression() {} - -bool CXFA_FMCallExpression::IsBuildInFunc(CFX_WideTextBuf* funcName) { - uint32_t uHash = FX_HashCode_GetW(funcName->AsStringC(), true); - const XFA_FMBuildInFunc* pEnd = g_BuildInFuncs + FX_ArraySize(g_BuildInFuncs); - const XFA_FMBuildInFunc* pFunc = - std::lower_bound(g_BuildInFuncs, pEnd, uHash, - [](const XFA_FMBuildInFunc& func, uint32_t hash) { - return func.m_uHash < hash; - }); - if (pFunc < pEnd && uHash == pFunc->m_uHash) { - funcName->Clear(); - *funcName << pFunc->m_buildinfunc; - return true; - } - return false; -} - -uint32_t CXFA_FMCallExpression::IsMethodWithObjParam( - const CFX_WideStringC& methodName) { - uint32_t uHash = FX_HashCode_GetW(methodName, false); - XFA_FMSOMMethod somMethodWithObjPara; - uint32_t parameters = 0x00; - int32_t iStart = 0, - iEnd = (sizeof(gs_FMSomMethods) / sizeof(gs_FMSomMethods[0])) - 1; - int32_t iMid = (iStart + iEnd) / 2; - do { - iMid = (iStart + iEnd) / 2; - somMethodWithObjPara = gs_FMSomMethods[iMid]; - if (uHash == somMethodWithObjPara.m_uHash) { - parameters = somMethodWithObjPara.m_dParameters; - break; - } else if (uHash < somMethodWithObjPara.m_uHash) { - iEnd = iMid - 1; - } else { - iStart = iMid + 1; - } - } while (iStart <= iEnd); - return parameters; -} - -void CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - CFX_WideTextBuf funcName; - m_pExp->ToJavaScript(funcName); - if (m_bIsSomMethod) { - javascript << funcName; - javascript << L"("; - uint32_t methodPara = IsMethodWithObjParam(funcName.AsStringC()); - if (methodPara > 0) { - for (size_t i = 0; i < m_Arguments.size(); ++i) { - // Currently none of our expressions use objects for a parameter over - // the 6th. Make sure we don't overflow the shift when doing this - // check. If we ever need more the 32 object params we can revisit. - if (i < 32 && (methodPara & (0x01 << i)) > 0) { - javascript << gs_lpStrExpFuncName[GETFMJSOBJ]; - } else { - javascript << gs_lpStrExpFuncName[GETFMVALUE]; - } - javascript << L"("; - const auto& expr = m_Arguments[i]; - expr->ToJavaScript(javascript); - javascript << L")"; - if (i + 1 < m_Arguments.size()) { - javascript << L", "; - } - } - } else { - for (const auto& expr : m_Arguments) { - javascript << gs_lpStrExpFuncName[GETFMVALUE]; - javascript << L"("; - expr->ToJavaScript(javascript); - javascript << L")"; - if (expr != m_Arguments.back()) - javascript << L", "; - } - } - javascript << L")"; - } else { - bool isEvalFunc = false; - bool isExistsFunc = false; - if (IsBuildInFunc(&funcName)) { - if (funcName.AsStringC() == L"Eval") { - isEvalFunc = true; - javascript << L"eval.call(this, "; - javascript << gs_lpStrExpFuncName[CALL]; - javascript << L"Translate"; - } else if (funcName.AsStringC() == L"Exists") { - isExistsFunc = true; - javascript << gs_lpStrExpFuncName[CALL]; - javascript << funcName; - } else { - javascript << gs_lpStrExpFuncName[CALL]; - javascript << funcName; - } - } else { - javascript << funcName; - } - javascript << L"("; - if (isExistsFunc) { - javascript << L"\n(\nfunction ()\n{\ntry\n{\n"; - if (!m_Arguments.empty()) { - const auto& expr = m_Arguments[0]; - javascript << L"return "; - expr->ToJavaScript(javascript); - javascript << L";\n}\n"; - } else { - javascript << L"return 0;\n}\n"; - } - javascript - << L"catch(accessExceptions)\n{\nreturn 0;\n}\n}\n).call(this)\n"; - } else { - for (const auto& expr : m_Arguments) { - expr->ToJavaScript(javascript); - if (expr != m_Arguments.back()) - javascript << L", "; - } - } - javascript << L")"; - if (isEvalFunc) { - javascript << L")"; - } - } -} - -CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, - XFA_FM_TOKEN op, - CFX_WideStringC wsIdentifier, - std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) - : CXFA_FMBinExpression(line, - op, - std::move(pAccessor), - std::move(pIndexExp)), - m_wsIdentifier(wsIdentifier) {} - -CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {} - -void CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[DOT]; - javascript << L"("; - if (m_pExp1) { - m_pExp1->ToJavaScript(javascript); - } else { - javascript << L"null"; - } - javascript << L", "; - javascript << L"\""; - if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) { - m_pExp1->ToJavaScript(javascript); - } - javascript << L"\", "; - if (m_op == TOKdotscream) { - javascript << L"\"#"; - javascript << m_wsIdentifier; - javascript << L"\", "; - } else if (m_op == TOKdotstar) { - javascript << L"\"*\", "; - } else if (m_op == TOKcall) { - javascript << L"\"\", "; - } else { - javascript << L"\""; - javascript << m_wsIdentifier; - javascript << L"\", "; - } - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMIndexExpression::CXFA_FMIndexExpression( - uint32_t line, - XFA_FM_AccessorIndex accessorIndex, - std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp, - bool bIsStarIndex) - : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)), - m_accessorIndex(accessorIndex), - m_bIsStarIndex(bIsStarIndex) {} - -void CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - switch (m_accessorIndex) { - case ACCESSOR_NO_INDEX: - javascript << L"0"; - break; - case ACCESSOR_NO_RELATIVEINDEX: - javascript << L"1"; - break; - case ACCESSOR_POSITIVE_INDEX: - javascript << L"2"; - break; - case ACCESSOR_NEGATIVE_INDEX: - javascript << L"3"; - break; - default: - javascript << L"0"; - } - if (!m_bIsStarIndex) { - javascript << L", "; - if (m_pExp) { - m_pExp->ToJavaScript(javascript); - } else { - javascript << L"0"; - } - } -} - -CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, - XFA_FM_TOKEN op, - CFX_WideStringC wsIdentifier, - std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) - : CXFA_FMBinExpression(line, - op, - std::move(pAccessor), - std::move(pIndexExp)), - m_wsIdentifier(wsIdentifier) {} - -CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {} - -void CXFA_FMDotDotAccessorExpression::ToJavaScript( - CFX_WideTextBuf& javascript) { - javascript << gs_lpStrExpFuncName[DOTDOT]; - javascript << L"("; - m_pExp1->ToJavaScript(javascript); - javascript << L", "; - javascript << L"\""; - if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) { - m_pExp1->ToJavaScript(javascript); - } - javascript << L"\", "; - javascript << L"\""; - javascript << m_wsIdentifier; - javascript << L"\", "; - m_pExp2->ToJavaScript(javascript); - javascript << L")"; -} - -CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pCallExp) - : CXFA_FMBinExpression(line, - TOKdot, - std::move(pAccessorExp1), - std::move(pCallExp)) {} - -void CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { - javascript << L"(\nfunction ()\n{\n"; - javascript << L"var method_return_value = null;\n"; - javascript << L"var accessor_object = "; - m_pExp1->ToJavaScript(javascript); - javascript << L";\n"; - javascript << L"if ("; - javascript << gs_lpStrExpFuncName[ISFMARRAY]; - javascript << L"(accessor_object))\n{\n"; - javascript << L"for(var index = accessor_object.length - 1; index > 1; " - L"index--)\n{\n"; - javascript << L"method_return_value = accessor_object[index]."; - m_pExp2->ToJavaScript(javascript); - javascript << L";\n}\n}\n"; - javascript << L"else\n{\nmethod_return_value = accessor_object."; - m_pExp2->ToJavaScript(javascript); - javascript << L";\n}\n"; - javascript << L"return method_return_value;\n"; - javascript << L"}\n).call(this)"; -} diff --git a/xfa/fxfa/fm2js/xfa_simpleexpression.h b/xfa/fxfa/fm2js/xfa_simpleexpression.h deleted file mode 100644 index af1d02eea55829603e7b705e30d22c59e81db6bb..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_simpleexpression.h +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FM2JS_XFA_SIMPLEEXPRESSION_H_ -#define XFA_FXFA_FM2JS_XFA_SIMPLEEXPRESSION_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "xfa/fxfa/fm2js/xfa_lexer.h" - -#define RUNTIMEFUNCTIONRETURNVALUE \ - (L"foxit_xfa_formcalc_runtime_func_return_value") -#define EXCLAMATION_IN_IDENTIFIER (L"foxit_xfa_formcalc__exclamation__") - -enum XFA_FM_SimpleExpressionType { - ASSIGN, - LOGICALOR, - LOGICALAND, - EQUALITY, - NOTEQUALITY, - LESS, - LESSEQUAL, - GREATER, - GREATEREQUAL, - PLUS, - MINUS, - MULTIPLE, - DIVIDE, - POSITIVE, - NEGATIVE, - NOT, - CALL, - DOT, - DOTDOT, - CONCATFMOBJECT, - ISFMOBJECT, - ISFMARRAY, - GETFMVALUE, - GETFMJSOBJ, - VARFILTER -}; - -CFX_WideStringC XFA_FM_EXPTypeToString( - XFA_FM_SimpleExpressionType simpleExpType); - -enum XFA_FM_AccessorIndex { - ACCESSOR_NO_INDEX, - ACCESSOR_NO_RELATIVEINDEX, - ACCESSOR_POSITIVE_INDEX, - ACCESSOR_NEGATIVE_INDEX -}; - -class CXFA_FMSimpleExpression { - public: - CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op); - virtual ~CXFA_FMSimpleExpression() {} - virtual void ToJavaScript(CFX_WideTextBuf& javascript); - virtual void ToImpliedReturnJS(CFX_WideTextBuf& javascript); - - XFA_FM_TOKEN GetOperatorToken() const; - - protected: - uint32_t m_line; - XFA_FM_TOKEN m_op; -}; - -class CXFA_FMNullExpression : public CXFA_FMSimpleExpression { - public: - explicit CXFA_FMNullExpression(uint32_t line); - ~CXFA_FMNullExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMNumberExpression : public CXFA_FMSimpleExpression { - public: - CXFA_FMNumberExpression(uint32_t line, CFX_WideStringC wsNumber); - ~CXFA_FMNumberExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - CFX_WideStringC m_wsNumber; -}; - -class CXFA_FMStringExpression : public CXFA_FMSimpleExpression { - public: - CXFA_FMStringExpression(uint32_t line, CFX_WideStringC wsString); - ~CXFA_FMStringExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - CFX_WideStringC m_wsString; -}; - -class CXFA_FMIdentifierExpression : public CXFA_FMSimpleExpression { - public: - CXFA_FMIdentifierExpression(uint32_t line, CFX_WideStringC wsIdentifier); - ~CXFA_FMIdentifierExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - CFX_WideStringC m_wsIdentifier; -}; - -class CXFA_FMUnaryExpression : public CXFA_FMSimpleExpression { - public: - CXFA_FMUnaryExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp); - ~CXFA_FMUnaryExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - protected: - std::unique_ptr<CXFA_FMSimpleExpression> m_pExp; -}; - -class CXFA_FMBinExpression : public CXFA_FMSimpleExpression { - public: - CXFA_FMBinExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMBinExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - protected: - std::unique_ptr<CXFA_FMSimpleExpression> m_pExp1; - std::unique_ptr<CXFA_FMSimpleExpression> m_pExp2; -}; - -class CXFA_FMAssignExpression : public CXFA_FMBinExpression { - public: - CXFA_FMAssignExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMAssignExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; - void ToImpliedReturnJS(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMLogicalOrExpression : public CXFA_FMBinExpression { - public: - CXFA_FMLogicalOrExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMLogicalOrExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMLogicalAndExpression : public CXFA_FMBinExpression { - public: - CXFA_FMLogicalAndExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMLogicalAndExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMEqualityExpression : public CXFA_FMBinExpression { - public: - CXFA_FMEqualityExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMEqualityExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMRelationalExpression : public CXFA_FMBinExpression { - public: - CXFA_FMRelationalExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMRelationalExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMAdditiveExpression : public CXFA_FMBinExpression { - public: - CXFA_FMAdditiveExpression(uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMAdditiveExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMMultiplicativeExpression : public CXFA_FMBinExpression { - public: - CXFA_FMMultiplicativeExpression( - uint32_t line, - XFA_FM_TOKEN op, - std::unique_ptr<CXFA_FMSimpleExpression> pExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pExp2); - ~CXFA_FMMultiplicativeExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMPosExpression : public CXFA_FMUnaryExpression { - public: - CXFA_FMPosExpression(uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp); - ~CXFA_FMPosExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMNegExpression : public CXFA_FMUnaryExpression { - public: - CXFA_FMNegExpression(uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp); - ~CXFA_FMNegExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMNotExpression : public CXFA_FMUnaryExpression { - public: - CXFA_FMNotExpression(uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp); - ~CXFA_FMNotExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -class CXFA_FMCallExpression : public CXFA_FMUnaryExpression { - public: - CXFA_FMCallExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pExp, - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments, - bool bIsSomMethod); - ~CXFA_FMCallExpression() override; - - bool IsBuildInFunc(CFX_WideTextBuf* funcName); - uint32_t IsMethodWithObjParam(const CFX_WideStringC& methodName); - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - bool m_bIsSomMethod; - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> m_Arguments; -}; - -class CXFA_FMDotAccessorExpression : public CXFA_FMBinExpression { - public: - CXFA_FMDotAccessorExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, - XFA_FM_TOKEN op, - CFX_WideStringC wsIdentifier, - std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp); - ~CXFA_FMDotAccessorExpression() override; - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - CFX_WideStringC m_wsIdentifier; -}; - -class CXFA_FMIndexExpression : public CXFA_FMUnaryExpression { - public: - CXFA_FMIndexExpression(uint32_t line, - XFA_FM_AccessorIndex accessorIndex, - std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp, - bool bIsStarIndex); - ~CXFA_FMIndexExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - XFA_FM_AccessorIndex m_accessorIndex; - bool m_bIsStarIndex; -}; - -class CXFA_FMDotDotAccessorExpression : public CXFA_FMBinExpression { - public: - CXFA_FMDotDotAccessorExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, - XFA_FM_TOKEN op, - CFX_WideStringC wsIdentifier, - std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp); - ~CXFA_FMDotDotAccessorExpression() override; - - void ToJavaScript(CFX_WideTextBuf& javascript) override; - - private: - CFX_WideStringC m_wsIdentifier; -}; - -class CXFA_FMMethodCallExpression : public CXFA_FMBinExpression { - public: - CXFA_FMMethodCallExpression( - uint32_t line, - std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1, - std::unique_ptr<CXFA_FMSimpleExpression> pCallExp); - ~CXFA_FMMethodCallExpression() override {} - void ToJavaScript(CFX_WideTextBuf& javascript) override; -}; - -#endif // XFA_FXFA_FM2JS_XFA_SIMPLEEXPRESSION_H_ diff --git a/xfa/fxfa/fm2js/xfa_simpleexpression_unittest.cpp b/xfa/fxfa/fm2js/xfa_simpleexpression_unittest.cpp deleted file mode 100644 index 7826d9b53c32220a7a8f382df6958890039b0b61..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fm2js/xfa_simpleexpression_unittest.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 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. - -#include "xfa/fxfa/fm2js/xfa_simpleexpression.h" - -#include <memory> -#include <utility> - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fxfa/fm2js/xfa_lexer.h" - -TEST(FMCallExpression, more_than_32_arguments) { - // Use sign as it has 3 object parameters at positions 0, 5, and 6. - auto exp = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(0, L"sign"); - - std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> args; - for (size_t i = 0; i < 50; i++) - args.push_back(pdfium::MakeUnique<CXFA_FMSimpleExpression>(0, TOKnan)); - - CXFA_FMCallExpression callExp(0, std::move(exp), std::move(args), true); - CFX_WideTextBuf js; - callExp.ToJavaScript(js); - - // Generate the result javascript string. - CFX_WideString result = L"sign("; - for (size_t i = 0; i < 50; i++) { - if (i > 0) - result += L", "; - - result += L"foxit_xfa_formcalc_runtime.get_fm_"; - // Object positions for sign() method. - if (i == 0 || i == 5 || i == 6) - result += L"jsobj()"; - else - result += L"value()"; - } - result += L")"; - - EXPECT_EQ(result.AsStringC(), js.AsStringC()); -} diff --git a/xfa/fxfa/fxfa.h b/xfa/fxfa/fxfa.h index dd5fc0fcbc4591417a1babdba2ebaad053c2777c..d42cd1b158e4736f29761de194cfe8b19d123ec6 100644 --- a/xfa/fxfa/fxfa.h +++ b/xfa/fxfa/fxfa.h @@ -9,22 +9,15 @@ #include <vector> -#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/retain_ptr.h" +#include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/fxfa_basic.h" -#include "xfa/fxfa/fxfa_widget.h" -class CFGAS_GEFont; -class CFX_Graphics; -class CPDF_Document; class CXFA_FFPageView; -class CXFA_Node; -class CXFA_NodeList; +class CXFA_Submit; class CXFA_WidgetAcc; class IFWL_AdapterTimerMgr; -class IXFA_AppProvider; -class IXFA_DocEnvironment; -class IXFA_WidgetAccIterator; -class IXFA_WidgetIterator; +class IFX_SeekableReadStream; #define XFA_MBICON_Error 0 #define XFA_MBICON_Warning 1 @@ -39,24 +32,20 @@ class IXFA_WidgetIterator; #define XFA_IDNo 3 #define XFA_IDYes 4 -#define XFA_DOCVIEW_View 0x00000000 -#define XFA_DOCVIEW_MasterPage 0x00000001 -#define XFA_DOCVIEW_Design 0x00000002 -#define XFA_DOCTYPE_Dynamic 0 -#define XFA_DOCTYPE_Static 1 -#define XFA_DOCTYPE_XDP 2 +// Note, values must match fpdf_formfill.h FORMTYPE_* flags. +enum class FormType { + kNone = 0, + kAcroForm = 1, + kXFAFull = 2, + kXFAForeground = 3, +}; + #define XFA_PARSESTATUS_StatusErr -3 #define XFA_PARSESTATUS_StreamErr -2 #define XFA_PARSESTATUS_SyntaxErr -1 #define XFA_PARSESTATUS_Ready 0 #define XFA_PARSESTATUS_Done 100 -#define XFA_VALIDATE_preSubmit 1 -#define XFA_VALIDATE_prePrint 2 -#define XFA_VALIDATE_preExecute 3 -#define XFA_VALIDATE_preSave 4 -#define XFA_INVALIDATE_AllPages 0x00000000 -#define XFA_INVALIDATE_CurrentPage 0x00000001 #define XFA_PRINTOPT_ShowDialog 0x00000001 #define XFA_PRINTOPT_CanCancel 0x00000002 #define XFA_PRINTOPT_ShrinkPage 0x00000004 @@ -72,11 +61,6 @@ class IXFA_WidgetIterator; #define XFA_EVENTERROR_NotExist 0 #define XFA_EVENTERROR_Disabled 2 -#define XFA_RENDERSTATUS_Ready 1 -#define XFA_RENDERSTATUS_ToBeContinued 2 -#define XFA_RENDERSTATUS_Done 3 -#define XFA_RENDERSTATUS_Failed -1 - #define XFA_TRAVERSEWAY_Tranvalse 0x0001 #define XFA_TRAVERSEWAY_Form 0x0002 @@ -95,10 +79,6 @@ enum XFA_WidgetStatus { XFA_WidgetStatus_Visible = 1 << 9 }; -enum XFA_WIDGETORDER { - XFA_WIDGETORDER_PreOrder, -}; - enum XFA_WIDGETTYPE { XFA_WIDGETTYPE_Barcode, XFA_WIDGETTYPE_PushButton, @@ -131,22 +111,22 @@ class IXFA_AppProvider { /** * Returns the language of the running host application. Such as zh_CN */ - virtual CFX_WideString GetLanguage() = 0; + virtual WideString GetLanguage() = 0; /** * Returns the platform of the machine running the script. Such as WIN */ - virtual CFX_WideString GetPlatform() = 0; + virtual WideString GetPlatform() = 0; /** * Get application name, such as Phantom. */ - virtual CFX_WideString GetAppName() = 0; + virtual WideString GetAppName() = 0; /** * Get application message box title. */ - virtual CFX_WideString GetAppTitle() const = 0; + virtual WideString GetAppTitle() const = 0; /** * Causes the system to play a sound. @@ -164,8 +144,8 @@ class IXFA_AppProvider { * @return A valid integer representing the value of the button pressed by the * user, refer to XFA_ID. */ - virtual int32_t MsgBox(const CFX_WideString& wsMessage, - const CFX_WideString& wsTitle = L"", + virtual int32_t MsgBox(const WideString& wsMessage, + const WideString& wsTitle = L"", uint32_t dwIconType = 0, uint32_t dwButtonType = 0) = 0; @@ -177,18 +157,18 @@ class IXFA_AppProvider { * @param[in] bMask - Mask the user input with asterisks when true, * @return A string containing the user's response. */ - virtual CFX_WideString Response(const CFX_WideString& wsQuestion, - const CFX_WideString& wsTitle = L"", - const CFX_WideString& wsDefaultAnswer = L"", - bool bMask = true) = 0; + virtual WideString Response(const WideString& wsQuestion, + const WideString& wsTitle = L"", + const WideString& wsDefaultAnswer = L"", + bool bMask = true) = 0; /** * Download something from somewhere. * @param[in] wsURL - http, ftp, such as * "http://www.w3.org/TR/REC-xml-names/". */ - virtual CFX_RetainPtr<IFX_SeekableReadStream> DownloadURL( - const CFX_WideString& wsURL) = 0; + virtual RetainPtr<IFX_SeekableReadStream> DownloadURL( + const WideString& wsURL) = 0; /** * POST data to the given url. @@ -205,12 +185,12 @@ class IXFA_AppProvider { * @param[out] wsResponse decoded response from server. * @return true Server permitted the post request, false otherwise. */ - virtual bool PostRequestURL(const CFX_WideString& wsURL, - const CFX_WideString& wsData, - const CFX_WideString& wsContentType, - const CFX_WideString& wsEncode, - const CFX_WideString& wsHeader, - CFX_WideString& wsResponse) = 0; + virtual bool PostRequestURL(const WideString& wsURL, + const WideString& wsData, + const WideString& wsContentType, + const WideString& wsEncode, + const WideString& wsHeader, + WideString& wsResponse) = 0; /** * PUT data to the given url. @@ -220,9 +200,9 @@ class IXFA_AppProvider { * ISO8859-1, any recognized [IANA]character encoding * @return true Server permitted the post request, false otherwise. */ - virtual bool PutRequestURL(const CFX_WideString& wsURL, - const CFX_WideString& wsData, - const CFX_WideString& wsEncode) = 0; + virtual bool PutRequestURL(const WideString& wsURL, + const WideString& wsData, + const WideString& wsEncode) = 0; virtual IFWL_AdapterTimerMgr* GetTimerMgr() = 0; }; @@ -233,34 +213,33 @@ class IXFA_DocEnvironment { virtual void SetChangeMark(CXFA_FFDoc* hDoc) = 0; virtual void InvalidateRect(CXFA_FFPageView* pPageView, - const CFX_RectF& rt, - uint32_t dwFlags) = 0; + const CFX_RectF& rt) = 0; virtual void DisplayCaret(CXFA_FFWidget* hWidget, bool bVisible, const CFX_RectF* pRtAnchor) = 0; virtual bool GetPopupPos(CXFA_FFWidget* hWidget, - FX_FLOAT fMinPopup, - FX_FLOAT fMaxPopup, + float fMinPopup, + float fMaxPopup, const CFX_RectF& rtAnchor, CFX_RectF& rtPopup) = 0; virtual bool PopupMenu(CXFA_FFWidget* hWidget, CFX_PointF ptPopup) = 0; virtual void PageViewEvent(CXFA_FFPageView* pPageView, uint32_t dwFlags) = 0; virtual void WidgetPostAdd(CXFA_FFWidget* hWidget, - CXFA_WidgetAcc* pWidgetData) = 0; + CXFA_WidgetAcc* pWidgetAcc) = 0; virtual void WidgetPreRemove(CXFA_FFWidget* hWidget, - CXFA_WidgetAcc* pWidgetData) = 0; + CXFA_WidgetAcc* pWidgetAcc) = 0; virtual int32_t CountPages(CXFA_FFDoc* hDoc) = 0; virtual int32_t GetCurrentPage(CXFA_FFDoc* hDoc) = 0; virtual void SetCurrentPage(CXFA_FFDoc* hDoc, int32_t iCurPage) = 0; virtual bool IsCalculationsEnabled(CXFA_FFDoc* hDoc) = 0; virtual void SetCalculationsEnabled(CXFA_FFDoc* hDoc, bool bEnabled) = 0; - virtual void GetTitle(CXFA_FFDoc* hDoc, CFX_WideString& wsTitle) = 0; - virtual void SetTitle(CXFA_FFDoc* hDoc, const CFX_WideString& wsTitle) = 0; + virtual void GetTitle(CXFA_FFDoc* hDoc, WideString& wsTitle) = 0; + virtual void SetTitle(CXFA_FFDoc* hDoc, const WideString& wsTitle) = 0; virtual void ExportData(CXFA_FFDoc* hDoc, - const CFX_WideString& wsFilePath, + const WideString& wsFilePath, bool bXDP) = 0; - virtual void GotoURL(CXFA_FFDoc* hDoc, const CFX_WideString& bsURL) = 0; + virtual void GotoURL(CXFA_FFDoc* hDoc, const WideString& bsURL) = 0; virtual bool IsValidationsEnabled(CXFA_FFDoc* hDoc) = 0; virtual void SetValidationsEnabled(CXFA_FFDoc* hDoc, bool bEnabled) = 0; virtual void SetFocusWidget(CXFA_FFDoc* hDoc, CXFA_FFWidget* hWidget) = 0; @@ -270,16 +249,16 @@ class IXFA_DocEnvironment { uint32_t dwOptions) = 0; virtual FX_ARGB GetHighlightColor(CXFA_FFDoc* hDoc) = 0; - virtual bool SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) = 0; + virtual bool Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) = 0; virtual bool GetGlobalProperty(CXFA_FFDoc* hDoc, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue) = 0; virtual bool SetGlobalProperty(CXFA_FFDoc* hDoc, - const CFX_ByteStringC& szPropName, + const ByteStringView& szPropName, CFXJSE_Value* pValue) = 0; - virtual CFX_RetainPtr<IFX_SeekableReadStream> OpenLinkedFile( + virtual RetainPtr<IFX_SeekableReadStream> OpenLinkedFile( CXFA_FFDoc* hDoc, - const CFX_WideString& wsLink) = 0; + const WideString& wsLink) = 0; }; class IXFA_WidgetIterator { diff --git a/xfa/fxfa/fxfa_basic.h b/xfa/fxfa/fxfa_basic.h index d16f50fd90d36c7107653795e05158acf53fb48c..96b483d9787588caad1aec3181610ea47102a484 100644 --- a/xfa/fxfa/fxfa_basic.h +++ b/xfa/fxfa/fxfa_basic.h @@ -7,9 +7,9 @@ #ifndef XFA_FXFA_FXFA_BASIC_H_ #define XFA_FXFA_FXFA_BASIC_H_ -#include "fxjs/cfxjse_arguments.h" #include "fxjs/fxjse.h" +class CJX_Object; class CXFA_Measurement; enum class XFA_ObjectType; @@ -45,42 +45,48 @@ enum XFA_HashCode : uint32_t { XFA_HASHCODE_Xmpmeta = 0x132a8fbc }; -enum XFA_PACKET { - XFA_PACKET_USER, - XFA_PACKET_SourceSet, - XFA_PACKET_Pdf, - XFA_PACKET_Xdc, - XFA_PACKET_XDP, - XFA_PACKET_Xmpmeta, - XFA_PACKET_Xfdf, - XFA_PACKET_Config, - XFA_PACKET_LocaleSet, - XFA_PACKET_Stylesheet, - XFA_PACKET_Template, - XFA_PACKET_Signature, - XFA_PACKET_Datasets, - XFA_PACKET_Form, - XFA_PACKET_ConnectionSet, +enum class XFA_PacketType : uint8_t { + User, + SourceSet, + Pdf, + Xdc, + Xdp, + Xmpmeta, + Xfdf, + Config, + LocaleSet, + Stylesheet, + Template, + Signature, + Datasets, + Form, + ConnectionSet, }; enum XFA_XDPPACKET { XFA_XDPPACKET_UNKNOWN = 0, - XFA_XDPPACKET_Config = 1 << XFA_PACKET_Config, - XFA_XDPPACKET_Template = 1 << XFA_PACKET_Template, - XFA_XDPPACKET_Datasets = 1 << XFA_PACKET_Datasets, - XFA_XDPPACKET_Form = 1 << XFA_PACKET_Form, - XFA_XDPPACKET_LocaleSet = 1 << XFA_PACKET_LocaleSet, - XFA_XDPPACKET_ConnectionSet = 1 << XFA_PACKET_ConnectionSet, - XFA_XDPPACKET_SourceSet = 1 << XFA_PACKET_SourceSet, - XFA_XDPPACKET_Xdc = 1 << XFA_PACKET_Xdc, - XFA_XDPPACKET_Pdf = 1 << XFA_PACKET_Pdf, - XFA_XDPPACKET_Xfdf = 1 << XFA_PACKET_Xfdf, - XFA_XDPPACKET_Xmpmeta = 1 << XFA_PACKET_Xmpmeta, - XFA_XDPPACKET_Signature = 1 << XFA_PACKET_Signature, - XFA_XDPPACKET_Stylesheet = 1 << XFA_PACKET_Stylesheet, - XFA_XDPPACKET_USER = 1 << XFA_PACKET_USER, - XFA_XDPPACKET_XDP = 1 << XFA_PACKET_XDP, + XFA_XDPPACKET_Config = 1 << static_cast<uint8_t>(XFA_PacketType::Config), + XFA_XDPPACKET_Template = 1 << static_cast<uint8_t>(XFA_PacketType::Template), + XFA_XDPPACKET_Datasets = 1 << static_cast<uint8_t>(XFA_PacketType::Datasets), + XFA_XDPPACKET_Form = 1 << static_cast<uint8_t>(XFA_PacketType::Form), + XFA_XDPPACKET_LocaleSet = 1 + << static_cast<uint8_t>(XFA_PacketType::LocaleSet), + XFA_XDPPACKET_ConnectionSet = + 1 << static_cast<uint8_t>(XFA_PacketType::ConnectionSet), + XFA_XDPPACKET_SourceSet = 1 + << static_cast<uint8_t>(XFA_PacketType::SourceSet), + XFA_XDPPACKET_Xdc = 1 << static_cast<uint8_t>(XFA_PacketType::Xdc), + XFA_XDPPACKET_Pdf = 1 << static_cast<uint8_t>(XFA_PacketType::Pdf), + XFA_XDPPACKET_Xfdf = 1 << static_cast<uint8_t>(XFA_PacketType::Xfdf), + XFA_XDPPACKET_Xmpmeta = 1 << static_cast<uint8_t>(XFA_PacketType::Xmpmeta), + XFA_XDPPACKET_Signature = 1 + << static_cast<uint8_t>(XFA_PacketType::Signature), + XFA_XDPPACKET_Stylesheet = + 1 << static_cast<uint8_t>(XFA_PacketType::Stylesheet), + XFA_XDPPACKET_USER = 1 << static_cast<uint8_t>(XFA_PacketType::User), + XFA_XDPPACKET_XDP = 1 << static_cast<uint8_t>(XFA_PacketType::Xdp) }; + enum XFA_XDPPACKET_FLAGS { XFA_XDPPACKET_FLAGS_COMPLETEMATCH = 1, XFA_XDPPACKET_FLAGS_PREFIXMATCH = 2, @@ -88,526 +94,521 @@ enum XFA_XDPPACKET_FLAGS { XFA_XDPPACKET_FLAGS_SUPPORTONE = 8, XFA_XDPPACKET_FLAGS_SUPPORTMANY = 16, }; -struct XFA_PACKETINFO { - uint32_t uHash; - const FX_WCHAR* pName; - XFA_XDPPACKET eName; - const FX_WCHAR* pURI; - uint32_t eFlags; -}; -enum XFA_ATTRIBUTEENUM { - XFA_ATTRIBUTEENUM_Asterisk, - XFA_ATTRIBUTEENUM_Slash, - XFA_ATTRIBUTEENUM_Backslash, - XFA_ATTRIBUTEENUM_On, - XFA_ATTRIBUTEENUM_Tb, - XFA_ATTRIBUTEENUM_Up, - XFA_ATTRIBUTEENUM_MetaData, - XFA_ATTRIBUTEENUM_Delegate, - XFA_ATTRIBUTEENUM_PostSubmit, - XFA_ATTRIBUTEENUM_Name, - XFA_ATTRIBUTEENUM_Cross, - XFA_ATTRIBUTEENUM_Next, - XFA_ATTRIBUTEENUM_None, - XFA_ATTRIBUTEENUM_ShortEdge, - XFA_ATTRIBUTEENUM_1mod10_1mod11, - XFA_ATTRIBUTEENUM_Height, - XFA_ATTRIBUTEENUM_CrossDiagonal, - XFA_ATTRIBUTEENUM_All, - XFA_ATTRIBUTEENUM_Any, - XFA_ATTRIBUTEENUM_ToRight, - XFA_ATTRIBUTEENUM_MatchTemplate, - XFA_ATTRIBUTEENUM_Dpl, - XFA_ATTRIBUTEENUM_Invisible, - XFA_ATTRIBUTEENUM_Fit, - XFA_ATTRIBUTEENUM_Width, - XFA_ATTRIBUTEENUM_PreSubmit, - XFA_ATTRIBUTEENUM_Ipl, - XFA_ATTRIBUTEENUM_FlateCompress, - XFA_ATTRIBUTEENUM_Med, - XFA_ATTRIBUTEENUM_Odd, - XFA_ATTRIBUTEENUM_Off, - XFA_ATTRIBUTEENUM_Pdf, - XFA_ATTRIBUTEENUM_Row, - XFA_ATTRIBUTEENUM_Top, - XFA_ATTRIBUTEENUM_Xdp, - XFA_ATTRIBUTEENUM_Xfd, - XFA_ATTRIBUTEENUM_Xml, - XFA_ATTRIBUTEENUM_Zip, - XFA_ATTRIBUTEENUM_Zpl, - XFA_ATTRIBUTEENUM_Visible, - XFA_ATTRIBUTEENUM_Exclude, - XFA_ATTRIBUTEENUM_MouseEnter, - XFA_ATTRIBUTEENUM_Pair, - XFA_ATTRIBUTEENUM_Filter, - XFA_ATTRIBUTEENUM_MoveLast, - XFA_ATTRIBUTEENUM_ExportAndImport, - XFA_ATTRIBUTEENUM_Push, - XFA_ATTRIBUTEENUM_Portrait, - XFA_ATTRIBUTEENUM_Default, - XFA_ATTRIBUTEENUM_StoredProc, - XFA_ATTRIBUTEENUM_StayBOF, - XFA_ATTRIBUTEENUM_StayEOF, - XFA_ATTRIBUTEENUM_PostPrint, - XFA_ATTRIBUTEENUM_UsCarrier, - XFA_ATTRIBUTEENUM_Right, - XFA_ATTRIBUTEENUM_PreOpen, - XFA_ATTRIBUTEENUM_Actual, - XFA_ATTRIBUTEENUM_Rest, - XFA_ATTRIBUTEENUM_TopCenter, - XFA_ATTRIBUTEENUM_StandardSymbol, - XFA_ATTRIBUTEENUM_Initialize, - XFA_ATTRIBUTEENUM_JustifyAll, - XFA_ATTRIBUTEENUM_Normal, - XFA_ATTRIBUTEENUM_Landscape, - XFA_ATTRIBUTEENUM_NonInteractive, - XFA_ATTRIBUTEENUM_MouseExit, - XFA_ATTRIBUTEENUM_Minus, - XFA_ATTRIBUTEENUM_DiagonalLeft, - XFA_ATTRIBUTEENUM_SimplexPaginated, - XFA_ATTRIBUTEENUM_Document, - XFA_ATTRIBUTEENUM_Warning, - XFA_ATTRIBUTEENUM_Auto, - XFA_ATTRIBUTEENUM_Below, - XFA_ATTRIBUTEENUM_BottomLeft, - XFA_ATTRIBUTEENUM_BottomCenter, - XFA_ATTRIBUTEENUM_Tcpl, - XFA_ATTRIBUTEENUM_Text, - XFA_ATTRIBUTEENUM_Grouping, - XFA_ATTRIBUTEENUM_SecureSymbol, - XFA_ATTRIBUTEENUM_PreExecute, - XFA_ATTRIBUTEENUM_DocClose, - XFA_ATTRIBUTEENUM_Keyset, - XFA_ATTRIBUTEENUM_Vertical, - XFA_ATTRIBUTEENUM_PreSave, - XFA_ATTRIBUTEENUM_PreSign, - XFA_ATTRIBUTEENUM_Bottom, - XFA_ATTRIBUTEENUM_ToTop, - XFA_ATTRIBUTEENUM_Verify, - XFA_ATTRIBUTEENUM_First, - XFA_ATTRIBUTEENUM_ContentArea, - XFA_ATTRIBUTEENUM_Solid, - XFA_ATTRIBUTEENUM_Pessimistic, - XFA_ATTRIBUTEENUM_DuplexPaginated, - XFA_ATTRIBUTEENUM_Round, - XFA_ATTRIBUTEENUM_Remerge, - XFA_ATTRIBUTEENUM_Ordered, - XFA_ATTRIBUTEENUM_Percent, - XFA_ATTRIBUTEENUM_Even, - XFA_ATTRIBUTEENUM_Exit, - XFA_ATTRIBUTEENUM_ToolTip, - XFA_ATTRIBUTEENUM_OrderedOccurrence, - XFA_ATTRIBUTEENUM_ReadOnly, - XFA_ATTRIBUTEENUM_Currency, - XFA_ATTRIBUTEENUM_Concat, - XFA_ATTRIBUTEENUM_Thai, - XFA_ATTRIBUTEENUM_Embossed, - XFA_ATTRIBUTEENUM_Formdata, - XFA_ATTRIBUTEENUM_Greek, - XFA_ATTRIBUTEENUM_Decimal, - XFA_ATTRIBUTEENUM_Select, - XFA_ATTRIBUTEENUM_LongEdge, - XFA_ATTRIBUTEENUM_Protected, - XFA_ATTRIBUTEENUM_BottomRight, - XFA_ATTRIBUTEENUM_Zero, - XFA_ATTRIBUTEENUM_ForwardOnly, - XFA_ATTRIBUTEENUM_DocReady, - XFA_ATTRIBUTEENUM_Hidden, - XFA_ATTRIBUTEENUM_Include, - XFA_ATTRIBUTEENUM_Dashed, - XFA_ATTRIBUTEENUM_MultiSelect, - XFA_ATTRIBUTEENUM_Inactive, - XFA_ATTRIBUTEENUM_Embed, - XFA_ATTRIBUTEENUM_Static, - XFA_ATTRIBUTEENUM_OnEntry, - XFA_ATTRIBUTEENUM_Cyrillic, - XFA_ATTRIBUTEENUM_NonBlank, - XFA_ATTRIBUTEENUM_TopRight, - XFA_ATTRIBUTEENUM_Hebrew, - XFA_ATTRIBUTEENUM_TopLeft, - XFA_ATTRIBUTEENUM_Center, - XFA_ATTRIBUTEENUM_MoveFirst, - XFA_ATTRIBUTEENUM_Diamond, - XFA_ATTRIBUTEENUM_PageOdd, - XFA_ATTRIBUTEENUM_1mod10, - XFA_ATTRIBUTEENUM_Korean, - XFA_ATTRIBUTEENUM_AboveEmbedded, - XFA_ATTRIBUTEENUM_ZipCompress, - XFA_ATTRIBUTEENUM_Numeric, - XFA_ATTRIBUTEENUM_Circle, - XFA_ATTRIBUTEENUM_ToBottom, - XFA_ATTRIBUTEENUM_Inverted, - XFA_ATTRIBUTEENUM_Update, - XFA_ATTRIBUTEENUM_Isoname, - XFA_ATTRIBUTEENUM_Server, - XFA_ATTRIBUTEENUM_Position, - XFA_ATTRIBUTEENUM_MiddleCenter, - XFA_ATTRIBUTEENUM_Optional, - XFA_ATTRIBUTEENUM_UsePrinterSetting, - XFA_ATTRIBUTEENUM_Outline, - XFA_ATTRIBUTEENUM_IndexChange, - XFA_ATTRIBUTEENUM_Change, - XFA_ATTRIBUTEENUM_PageArea, - XFA_ATTRIBUTEENUM_Once, - XFA_ATTRIBUTEENUM_Only, - XFA_ATTRIBUTEENUM_Open, - XFA_ATTRIBUTEENUM_Caption, - XFA_ATTRIBUTEENUM_Raised, - XFA_ATTRIBUTEENUM_Justify, - XFA_ATTRIBUTEENUM_RefAndDescendants, - XFA_ATTRIBUTEENUM_Short, - XFA_ATTRIBUTEENUM_PageFront, - XFA_ATTRIBUTEENUM_Monospace, - XFA_ATTRIBUTEENUM_Middle, - XFA_ATTRIBUTEENUM_PrePrint, - XFA_ATTRIBUTEENUM_Always, - XFA_ATTRIBUTEENUM_Unknown, - XFA_ATTRIBUTEENUM_ToLeft, - XFA_ATTRIBUTEENUM_Above, - XFA_ATTRIBUTEENUM_DashDot, - XFA_ATTRIBUTEENUM_Gregorian, - XFA_ATTRIBUTEENUM_Roman, - XFA_ATTRIBUTEENUM_MouseDown, - XFA_ATTRIBUTEENUM_Symbol, - XFA_ATTRIBUTEENUM_PageEven, - XFA_ATTRIBUTEENUM_Sign, - XFA_ATTRIBUTEENUM_AddNew, - XFA_ATTRIBUTEENUM_Star, - XFA_ATTRIBUTEENUM_Optimistic, - XFA_ATTRIBUTEENUM_Rl_tb, - XFA_ATTRIBUTEENUM_MiddleRight, - XFA_ATTRIBUTEENUM_Maintain, - XFA_ATTRIBUTEENUM_Package, - XFA_ATTRIBUTEENUM_SimplifiedChinese, - XFA_ATTRIBUTEENUM_ToCenter, - XFA_ATTRIBUTEENUM_Back, - XFA_ATTRIBUTEENUM_Unspecified, - XFA_ATTRIBUTEENUM_BatchOptimistic, - XFA_ATTRIBUTEENUM_Bold, - XFA_ATTRIBUTEENUM_Both, - XFA_ATTRIBUTEENUM_Butt, - XFA_ATTRIBUTEENUM_Client, - XFA_ATTRIBUTEENUM_2mod10, - XFA_ATTRIBUTEENUM_ImageOnly, - XFA_ATTRIBUTEENUM_Horizontal, - XFA_ATTRIBUTEENUM_Dotted, - XFA_ATTRIBUTEENUM_UserControl, - XFA_ATTRIBUTEENUM_DiagonalRight, - XFA_ATTRIBUTEENUM_ConsumeData, - XFA_ATTRIBUTEENUM_Check, - XFA_ATTRIBUTEENUM_Data, - XFA_ATTRIBUTEENUM_Down, - XFA_ATTRIBUTEENUM_SansSerif, - XFA_ATTRIBUTEENUM_Inline, - XFA_ATTRIBUTEENUM_TraditionalChinese, - XFA_ATTRIBUTEENUM_Warn, - XFA_ATTRIBUTEENUM_RefOnly, - XFA_ATTRIBUTEENUM_InteractiveForms, - XFA_ATTRIBUTEENUM_Word, - XFA_ATTRIBUTEENUM_Unordered, - XFA_ATTRIBUTEENUM_Required, - XFA_ATTRIBUTEENUM_ImportOnly, - XFA_ATTRIBUTEENUM_BelowEmbedded, - XFA_ATTRIBUTEENUM_Japanese, - XFA_ATTRIBUTEENUM_Full, - XFA_ATTRIBUTEENUM_Rl_row, - XFA_ATTRIBUTEENUM_Vietnamese, - XFA_ATTRIBUTEENUM_EastEuropeanRoman, - XFA_ATTRIBUTEENUM_MouseUp, - XFA_ATTRIBUTEENUM_ExportOnly, - XFA_ATTRIBUTEENUM_Clear, - XFA_ATTRIBUTEENUM_Click, - XFA_ATTRIBUTEENUM_Base64, - XFA_ATTRIBUTEENUM_Close, - XFA_ATTRIBUTEENUM_Host, - XFA_ATTRIBUTEENUM_Global, - XFA_ATTRIBUTEENUM_Blank, - XFA_ATTRIBUTEENUM_Table, - XFA_ATTRIBUTEENUM_Import, - XFA_ATTRIBUTEENUM_Custom, - XFA_ATTRIBUTEENUM_MiddleLeft, - XFA_ATTRIBUTEENUM_PostExecute, - XFA_ATTRIBUTEENUM_Radix, - XFA_ATTRIBUTEENUM_PostOpen, - XFA_ATTRIBUTEENUM_Enter, - XFA_ATTRIBUTEENUM_Ignore, - XFA_ATTRIBUTEENUM_Lr_tb, - XFA_ATTRIBUTEENUM_Fantasy, - XFA_ATTRIBUTEENUM_Italic, - XFA_ATTRIBUTEENUM_Author, - XFA_ATTRIBUTEENUM_ToEdge, - XFA_ATTRIBUTEENUM_Choice, - XFA_ATTRIBUTEENUM_Disabled, - XFA_ATTRIBUTEENUM_CrossHatch, - XFA_ATTRIBUTEENUM_DataRef, - XFA_ATTRIBUTEENUM_DashDotDot, - XFA_ATTRIBUTEENUM_Square, - XFA_ATTRIBUTEENUM_Dynamic, - XFA_ATTRIBUTEENUM_Manual, - XFA_ATTRIBUTEENUM_Etched, - XFA_ATTRIBUTEENUM_ValidationState, - XFA_ATTRIBUTEENUM_Cursive, - XFA_ATTRIBUTEENUM_Last, - XFA_ATTRIBUTEENUM_Left, - XFA_ATTRIBUTEENUM_Link, - XFA_ATTRIBUTEENUM_Long, - XFA_ATTRIBUTEENUM_InternationalCarrier, - XFA_ATTRIBUTEENUM_PDF1_3, - XFA_ATTRIBUTEENUM_PDF1_6, - XFA_ATTRIBUTEENUM_Serif, - XFA_ATTRIBUTEENUM_PostSave, - XFA_ATTRIBUTEENUM_Ready, - XFA_ATTRIBUTEENUM_PostSign, - XFA_ATTRIBUTEENUM_Arabic, - XFA_ATTRIBUTEENUM_Error, - XFA_ATTRIBUTEENUM_Urlencoded, - XFA_ATTRIBUTEENUM_Lowered, +enum class XFA_AttributeEnum : uint32_t { + Asterisk, + Slash, + Backslash, + On, + Tb, + Up, + MetaData, + Delegate, + PostSubmit, + Name, + Cross, + Next, + None, + ShortEdge, + Checksum_1mod10_1mod11, + Height, + CrossDiagonal, + All, + Any, + ToRight, + MatchTemplate, + Dpl, + Invisible, + Fit, + Width, + PreSubmit, + Ipl, + FlateCompress, + Med, + Odd, + Off, + Pdf, + Row, + Top, + Xdp, + Xfd, + Xml, + Zip, + Zpl, + Visible, + Exclude, + MouseEnter, + Pair, + Filter, + MoveLast, + ExportAndImport, + Push, + Portrait, + Default, + StoredProc, + StayBOF, + StayEOF, + PostPrint, + UsCarrier, + Right, + PreOpen, + Actual, + Rest, + TopCenter, + StandardSymbol, + Initialize, + JustifyAll, + Normal, + Landscape, + NonInteractive, + MouseExit, + Minus, + DiagonalLeft, + SimplexPaginated, + Document, + Warning, + Auto, + Below, + BottomLeft, + BottomCenter, + Tcpl, + Text, + Grouping, + SecureSymbol, + PreExecute, + DocClose, + Keyset, + Vertical, + PreSave, + PreSign, + Bottom, + ToTop, + Verify, + First, + ContentArea, + Solid, + Pessimistic, + DuplexPaginated, + Round, + Remerge, + Ordered, + Percent, + Even, + Exit, + ToolTip, + OrderedOccurrence, + ReadOnly, + Currency, + Concat, + Thai, + Embossed, + Formdata, + Greek, + Decimal, + Select, + LongEdge, + Protected, + BottomRight, + Zero, + ForwardOnly, + DocReady, + Hidden, + Include, + Dashed, + MultiSelect, + Inactive, + Embed, + Static, + OnEntry, + Cyrillic, + NonBlank, + TopRight, + Hebrew, + TopLeft, + Center, + MoveFirst, + Diamond, + PageOdd, + Checksum_1mod10, + Korean, + AboveEmbedded, + ZipCompress, + Numeric, + Circle, + ToBottom, + Inverted, + Update, + Isoname, + Server, + Position, + MiddleCenter, + Optional, + UsePrinterSetting, + Outline, + IndexChange, + Change, + PageArea, + Once, + Only, + Open, + Caption, + Raised, + Justify, + RefAndDescendants, + Short, + PageFront, + Monospace, + Middle, + PrePrint, + Always, + Unknown, + ToLeft, + Above, + DashDot, + Gregorian, + Roman, + MouseDown, + Symbol, + PageEven, + Sign, + AddNew, + Star, + Optimistic, + Rl_tb, + MiddleRight, + Maintain, + Package, + SimplifiedChinese, + ToCenter, + Back, + Unspecified, + BatchOptimistic, + Bold, + Both, + Butt, + Client, + Checksum_2mod10, + ImageOnly, + Horizontal, + Dotted, + UserControl, + DiagonalRight, + ConsumeData, + Check, + Data, + Down, + SansSerif, + Inline, + TraditionalChinese, + Warn, + RefOnly, + InteractiveForms, + Word, + Unordered, + Required, + ImportOnly, + BelowEmbedded, + Japanese, + Full, + Rl_row, + Vietnamese, + EastEuropeanRoman, + MouseUp, + ExportOnly, + Clear, + Click, + Base64, + Close, + Host, + Global, + Blank, + Table, + Import, + Custom, + MiddleLeft, + PostExecute, + Radix, + PostOpen, + Enter, + Ignore, + Lr_tb, + Fantasy, + Italic, + Author, + ToEdge, + Choice, + Disabled, + CrossHatch, + DataRef, + DashDotDot, + Square, + Dynamic, + Manual, + Etched, + ValidationState, + Cursive, + Last, + Left, + Link, + Long, + InternationalCarrier, + PDF1_3, + PDF1_6, + Serif, + PostSave, + Ready, + PostSign, + Arabic, + Error, + Urlencoded, + Lowered }; -enum XFA_ATTRIBUTE { - XFA_ATTRIBUTE_H, - XFA_ATTRIBUTE_W, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_To, - XFA_ATTRIBUTE_LineThrough, - XFA_ATTRIBUTE_HAlign, - XFA_ATTRIBUTE_Typeface, - XFA_ATTRIBUTE_BeforeTarget, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Next, - XFA_ATTRIBUTE_DataRowCount, - XFA_ATTRIBUTE_Break, - XFA_ATTRIBUTE_VScrollPolicy, - XFA_ATTRIBUTE_FontHorizontalScale, - XFA_ATTRIBUTE_TextIndent, - XFA_ATTRIBUTE_Context, - XFA_ATTRIBUTE_TrayOut, - XFA_ATTRIBUTE_Cap, - XFA_ATTRIBUTE_Max, - XFA_ATTRIBUTE_Min, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Rid, - XFA_ATTRIBUTE_Url, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_LeftInset, - XFA_ATTRIBUTE_Widows, - XFA_ATTRIBUTE_Level, - XFA_ATTRIBUTE_BottomInset, - XFA_ATTRIBUTE_OverflowTarget, - XFA_ATTRIBUTE_AllowMacro, - XFA_ATTRIBUTE_PagePosition, - XFA_ATTRIBUTE_ColumnWidths, - XFA_ATTRIBUTE_OverflowLeader, - XFA_ATTRIBUTE_Action, - XFA_ATTRIBUTE_NonRepudiation, - XFA_ATTRIBUTE_Rate, - XFA_ATTRIBUTE_AllowRichText, - XFA_ATTRIBUTE_Role, - XFA_ATTRIBUTE_OverflowTrailer, - XFA_ATTRIBUTE_Operation, - XFA_ATTRIBUTE_Timeout, - XFA_ATTRIBUTE_TopInset, - XFA_ATTRIBUTE_Access, - XFA_ATTRIBUTE_CommandType, - XFA_ATTRIBUTE_Format, - XFA_ATTRIBUTE_DataPrep, - XFA_ATTRIBUTE_WidgetData, - XFA_ATTRIBUTE_Abbr, - XFA_ATTRIBUTE_MarginRight, - XFA_ATTRIBUTE_DataDescription, - XFA_ATTRIBUTE_EncipherOnly, - XFA_ATTRIBUTE_KerningMode, - XFA_ATTRIBUTE_Rotate, - XFA_ATTRIBUTE_WordCharacterCount, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Reserve, - XFA_ATTRIBUTE_TextLocation, - XFA_ATTRIBUTE_Priority, - XFA_ATTRIBUTE_Underline, - XFA_ATTRIBUTE_ModuleWidth, - XFA_ATTRIBUTE_Hyphenate, - XFA_ATTRIBUTE_Listen, - XFA_ATTRIBUTE_Delimiter, - XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTE_StartNew, - XFA_ATTRIBUTE_EofAction, - XFA_ATTRIBUTE_AllowNeutral, - XFA_ATTRIBUTE_Connection, - XFA_ATTRIBUTE_BaselineShift, - XFA_ATTRIBUTE_OverlinePeriod, - XFA_ATTRIBUTE_FracDigits, - XFA_ATTRIBUTE_Orientation, - XFA_ATTRIBUTE_TimeStamp, - XFA_ATTRIBUTE_PrintCheckDigit, - XFA_ATTRIBUTE_MarginLeft, - XFA_ATTRIBUTE_Stroke, - XFA_ATTRIBUTE_ModuleHeight, - XFA_ATTRIBUTE_TransferEncoding, - XFA_ATTRIBUTE_Usage, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_RadixOffset, - XFA_ATTRIBUTE_Preserve, - XFA_ATTRIBUTE_AliasNode, - XFA_ATTRIBUTE_MultiLine, - XFA_ATTRIBUTE_Version, - XFA_ATTRIBUTE_StartChar, - XFA_ATTRIBUTE_ScriptTest, - XFA_ATTRIBUTE_StartAngle, - XFA_ATTRIBUTE_CursorType, - XFA_ATTRIBUTE_DigitalSignature, - XFA_ATTRIBUTE_CodeType, - XFA_ATTRIBUTE_Output, - XFA_ATTRIBUTE_BookendTrailer, - XFA_ATTRIBUTE_ImagingBBox, - XFA_ATTRIBUTE_ExcludeInitialCap, - XFA_ATTRIBUTE_Force, - XFA_ATTRIBUTE_CrlSign, - XFA_ATTRIBUTE_Previous, - XFA_ATTRIBUTE_PushCharacterCount, - XFA_ATTRIBUTE_NullTest, - XFA_ATTRIBUTE_RunAt, - XFA_ATTRIBUTE_SpaceBelow, - XFA_ATTRIBUTE_SweepAngle, - XFA_ATTRIBUTE_NumberOfCells, - XFA_ATTRIBUTE_LetterSpacing, - XFA_ATTRIBUTE_LockType, - XFA_ATTRIBUTE_PasswordChar, - XFA_ATTRIBUTE_VAlign, - XFA_ATTRIBUTE_SourceBelow, - XFA_ATTRIBUTE_Inverted, - XFA_ATTRIBUTE_Mark, - XFA_ATTRIBUTE_MaxH, - XFA_ATTRIBUTE_MaxW, - XFA_ATTRIBUTE_Truncate, - XFA_ATTRIBUTE_MinH, - XFA_ATTRIBUTE_MinW, - XFA_ATTRIBUTE_Initial, - XFA_ATTRIBUTE_Mode, - XFA_ATTRIBUTE_Layout, - XFA_ATTRIBUTE_Server, - XFA_ATTRIBUTE_EmbedPDF, - XFA_ATTRIBUTE_OddOrEven, - XFA_ATTRIBUTE_TabDefault, - XFA_ATTRIBUTE_Contains, - XFA_ATTRIBUTE_RightInset, - XFA_ATTRIBUTE_MaxChars, - XFA_ATTRIBUTE_Open, - XFA_ATTRIBUTE_Relation, - XFA_ATTRIBUTE_WideNarrowRatio, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_SignatureType, - XFA_ATTRIBUTE_LineThroughPeriod, - XFA_ATTRIBUTE_Shape, - XFA_ATTRIBUTE_TabStops, - XFA_ATTRIBUTE_OutputBelow, - XFA_ATTRIBUTE_Short, - XFA_ATTRIBUTE_FontVerticalScale, - XFA_ATTRIBUTE_Thickness, - XFA_ATTRIBUTE_CommitOn, - XFA_ATTRIBUTE_RemainCharacterCount, - XFA_ATTRIBUTE_KeyAgreement, - XFA_ATTRIBUTE_ErrorCorrectionLevel, - XFA_ATTRIBUTE_UpsMode, - XFA_ATTRIBUTE_MergeMode, - XFA_ATTRIBUTE_Circular, - XFA_ATTRIBUTE_PsName, - XFA_ATTRIBUTE_Trailer, - XFA_ATTRIBUTE_UnicodeRange, - XFA_ATTRIBUTE_ExecuteType, - XFA_ATTRIBUTE_DuplexImposition, - XFA_ATTRIBUTE_TrayIn, - XFA_ATTRIBUTE_BindingNode, - XFA_ATTRIBUTE_BofAction, - XFA_ATTRIBUTE_Save, - XFA_ATTRIBUTE_TargetType, - XFA_ATTRIBUTE_KeyEncipherment, - XFA_ATTRIBUTE_CredentialServerPolicy, - XFA_ATTRIBUTE_Size, - XFA_ATTRIBUTE_InitialNumber, - XFA_ATTRIBUTE_Slope, - XFA_ATTRIBUTE_CSpace, - XFA_ATTRIBUTE_ColSpan, - XFA_ATTRIBUTE_Binding, - XFA_ATTRIBUTE_Checksum, - XFA_ATTRIBUTE_CharEncoding, - XFA_ATTRIBUTE_Bind, - XFA_ATTRIBUTE_TextEntry, - XFA_ATTRIBUTE_Archive, - XFA_ATTRIBUTE_Uuid, - XFA_ATTRIBUTE_Posture, - XFA_ATTRIBUTE_After, - XFA_ATTRIBUTE_Orphans, - XFA_ATTRIBUTE_QualifiedName, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Locale, - XFA_ATTRIBUTE_Weight, - XFA_ATTRIBUTE_UnderlinePeriod, - XFA_ATTRIBUTE_Data, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Numbered, - XFA_ATTRIBUTE_DataColumnCount, - XFA_ATTRIBUTE_Overline, - XFA_ATTRIBUTE_UrlPolicy, - XFA_ATTRIBUTE_AnchorType, - XFA_ATTRIBUTE_LabelRef, - XFA_ATTRIBUTE_BookendLeader, - XFA_ATTRIBUTE_MaxLength, - XFA_ATTRIBUTE_AccessKey, - XFA_ATTRIBUTE_CursorLocation, - XFA_ATTRIBUTE_DelayedOpen, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_DataEncipherment, - XFA_ATTRIBUTE_AfterTarget, - XFA_ATTRIBUTE_Leader, - XFA_ATTRIBUTE_Picker, - XFA_ATTRIBUTE_From, - XFA_ATTRIBUTE_BaseProfile, - XFA_ATTRIBUTE_Aspect, - XFA_ATTRIBUTE_RowColumnRatio, - XFA_ATTRIBUTE_LineHeight, - XFA_ATTRIBUTE_Highlight, - XFA_ATTRIBUTE_ValueRef, - XFA_ATTRIBUTE_MaxEntries, - XFA_ATTRIBUTE_DataLength, - XFA_ATTRIBUTE_Activity, - XFA_ATTRIBUTE_Input, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_BlankOrNotBlank, - XFA_ATTRIBUTE_AddRevocationInfo, - XFA_ATTRIBUTE_GenericFamily, - XFA_ATTRIBUTE_Hand, - XFA_ATTRIBUTE_Href, - XFA_ATTRIBUTE_TextEncoding, - XFA_ATTRIBUTE_LeadDigits, - XFA_ATTRIBUTE_Permissions, - XFA_ATTRIBUTE_SpaceAbove, - XFA_ATTRIBUTE_CodeBase, - XFA_ATTRIBUTE_Stock, - XFA_ATTRIBUTE_IsNull, - XFA_ATTRIBUTE_RestoreState, - XFA_ATTRIBUTE_ExcludeAllCaps, - XFA_ATTRIBUTE_FormatTest, - XFA_ATTRIBUTE_HScrollPolicy, - XFA_ATTRIBUTE_Join, - XFA_ATTRIBUTE_KeyCertSign, - XFA_ATTRIBUTE_Radius, - XFA_ATTRIBUTE_SourceAbove, - XFA_ATTRIBUTE_Override, - XFA_ATTRIBUTE_ClassId, - XFA_ATTRIBUTE_Disable, - XFA_ATTRIBUTE_Scope, - XFA_ATTRIBUTE_Match, - XFA_ATTRIBUTE_Placement, - XFA_ATTRIBUTE_Before, - XFA_ATTRIBUTE_WritingScript, - XFA_ATTRIBUTE_EndChar, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Long, - XFA_ATTRIBUTE_Intact, - XFA_ATTRIBUTE_XdpContent, - XFA_ATTRIBUTE_DecipherOnly, + +enum class XFA_Attribute : uint8_t { + H = 0, + W, + X, + Y, + Id, + To, + LineThrough, + HAlign, + Typeface, + BeforeTarget, + Name, + Next, + DataRowCount, + Break, + VScrollPolicy, + FontHorizontalScale, + TextIndent, + Context, + TrayOut, + Cap, + Max, + Min, + Ref, + Rid, + Url, + Use, + LeftInset, + Widows, + Level, + BottomInset, + OverflowTarget, + AllowMacro, + PagePosition, + ColumnWidths, + OverflowLeader, + Action, + NonRepudiation, + Rate, + AllowRichText, + Role, + OverflowTrailer, + Operation, + Timeout, + TopInset, + Access, + CommandType, + Format, + DataPrep, + WidgetData, + Abbr, + MarginRight, + DataDescription, + EncipherOnly, + KerningMode, + Rotate, + WordCharacterCount, + Type, + Reserve, + TextLocation, + Priority, + Underline, + ModuleWidth, + Hyphenate, + Listen, + Delimiter, + ContentType, + StartNew, + EofAction, + AllowNeutral, + Connection, + BaselineShift, + OverlinePeriod, + FracDigits, + Orientation, + TimeStamp, + PrintCheckDigit, + MarginLeft, + Stroke, + ModuleHeight, + TransferEncoding, + Usage, + Presence, + RadixOffset, + Preserve, + AliasNode, + MultiLine, + Version, + StartChar, + ScriptTest, + StartAngle, + CursorType, + DigitalSignature, + CodeType, + Output, + BookendTrailer, + ImagingBBox, + ExcludeInitialCap, + Force, + CrlSign, + Previous, + PushCharacterCount, + NullTest, + RunAt, + SpaceBelow, + SweepAngle, + NumberOfCells, + LetterSpacing, + LockType, + PasswordChar, + VAlign, + SourceBelow, + Inverted, + Mark, + MaxH, + MaxW, + Truncate, + MinH, + MinW, + Initial, + Mode, + Layout, + Server, + EmbedPDF, + OddOrEven, + TabDefault, + Contains, + RightInset, + MaxChars, + Open, + Relation, + WideNarrowRatio, + Relevant, + SignatureType, + LineThroughPeriod, + Shape, + TabStops, + OutputBelow, + Short, + FontVerticalScale, + Thickness, + CommitOn, + RemainCharacterCount, + KeyAgreement, + ErrorCorrectionLevel, + UpsMode, + MergeMode, + Circular, + PsName, + Trailer, + UnicodeRange, + ExecuteType, + DuplexImposition, + TrayIn, + BindingNode, + BofAction, + Save, + TargetType, + KeyEncipherment, + CredentialServerPolicy, + Size, + InitialNumber, + Slope, + CSpace, + ColSpan, + Binding, + Checksum, + CharEncoding, + Bind, + TextEntry, + Archive, + Uuid, + Posture, + After, + Orphans, + QualifiedName, + Usehref, + Locale, + Weight, + UnderlinePeriod, + Data, + Desc, + Numbered, + DataColumnCount, + Overline, + UrlPolicy, + AnchorType, + LabelRef, + BookendLeader, + MaxLength, + AccessKey, + CursorLocation, + DelayedOpen, + Target, + DataEncipherment, + AfterTarget, + Leader, + Picker, + From, + BaseProfile, + Aspect, + RowColumnRatio, + LineHeight, + Highlight, + ValueRef, + MaxEntries, + DataLength, + Activity, + Input, + Value, + BlankOrNotBlank, + AddRevocationInfo, + GenericFamily, + Hand, + Href, + TextEncoding, + LeadDigits, + Permissions, + SpaceAbove, + CodeBase, + Stock, + IsNull, + RestoreState, + ExcludeAllCaps, + FormatTest, + HScrollPolicy, + Join, + KeyCertSign, + Radius, + SourceAbove, + Override, + ClassId, + Disable, + Scope, + Match, + Placement, + Before, + WritingScript, + EndChar, + Lock, + Long, + Intact, + XdpContent, + DecipherOnly, + Unknown = 255, }; enum class XFA_Element : int32_t { @@ -828,7 +829,7 @@ enum class XFA_Element : int32_t { CompressObjectStream, DataValue, AccessibleContent, - NodeList, + TreeList, IncludeXDPContent, XmlConnection, ValidateApprovalSignatures, @@ -926,39 +927,16 @@ enum class XFA_Element : int32_t { Tagged, Items }; -struct XFA_ELEMENTINFO { - uint32_t uHash; - const FX_WCHAR* pName; - XFA_Element eName; - uint32_t dwPackets; - XFA_ObjectType eObjectType; -}; - -enum XFA_ATTRIBUTETYPE { - XFA_ATTRIBUTETYPE_NOTSURE, - XFA_ATTRIBUTETYPE_Enum, - XFA_ATTRIBUTETYPE_Cdata, - XFA_ATTRIBUTETYPE_Boolean, - XFA_ATTRIBUTETYPE_Integer, - XFA_ATTRIBUTETYPE_Measure, -}; -struct XFA_ATTRIBUTEINFO { - uint32_t uHash; - const FX_WCHAR* pName; - XFA_ATTRIBUTE eName; - XFA_ATTRIBUTETYPE eType; - uint32_t dwPackets; - void* pDefValue; -}; -struct XFA_ELEMENTHIERARCHY { - uint16_t wStart; - uint16_t wCount; +enum class XFA_AttributeType : uint8_t { + Enum, + CData, + Boolean, + Integer, + Measure, }; struct XFA_SCRIPTHIERARCHY { - uint16_t wMethodStart; - uint16_t wMethodCount; uint16_t wAttributeStart; uint16_t wAttributeCount; int16_t wParentIndex; @@ -966,61 +944,40 @@ struct XFA_SCRIPTHIERARCHY { #define XFA_PROPERTYFLAG_OneOf 0x01 #define XFA_PROPERTYFLAG_DefaultOneOf 0x02 -struct XFA_PROPERTY { - XFA_Element eName; - uint8_t uOccur; - uint8_t uFlags; -}; -struct XFA_ATTRIBUTEENUMINFO { +struct XFA_AttributeEnumInfo { uint32_t uHash; - const FX_WCHAR* pName; - XFA_ATTRIBUTEENUM eName; + const wchar_t* pName; + XFA_AttributeEnum eName; }; -enum XFA_UNIT { - XFA_UNIT_Unknown, - XFA_UNIT_Percent, - XFA_UNIT_Angle, - XFA_UNIT_Em, - XFA_UNIT_Pt, - XFA_UNIT_In, - XFA_UNIT_Pc, - XFA_UNIT_Cm, - XFA_UNIT_Mm, - XFA_UNIT_Mp, -}; +enum class XFA_Unit : uint8_t { + Percent = 0, + Em, + Pt, + In, + Pc, + Cm, + Mm, + Mp, -struct XFA_NOTSUREATTRIBUTE { - XFA_Element eElement; - XFA_ATTRIBUTE eAttribute; - XFA_ATTRIBUTETYPE eType; - void* pValue; + Unknown = 255, }; -class CFXJSE_Arguments; -class CXFA_Object; - -typedef void (CXFA_Object::*XFA_METHOD_CALLBACK)(CFXJSE_Arguments* pArguments); -struct XFA_METHODINFO { - uint32_t uHash; - const FX_WCHAR* pName; - XFA_METHOD_CALLBACK lpfnCallback; +typedef void (CJX_Object::*XFA_ATTRIBUTE_CALLBACK)(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute); +enum class XFA_ScriptType : uint8_t { + Basic, + Object, }; -typedef void (CXFA_Object::*XFA_ATTRIBUTE_CALLBACK)(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); -enum XFA_SCRIPT_TYPE { - XFA_SCRIPT_Basic, - XFA_SCRIPT_Object, -}; struct XFA_SCRIPTATTRIBUTEINFO { uint32_t uHash; - const FX_WCHAR* pName; - XFA_ATTRIBUTE_CALLBACK lpfnCallback; - int32_t eAttribute; - uint16_t eValueType; + const wchar_t* pName; + XFA_ATTRIBUTE_CALLBACK callback; + XFA_Attribute attribute; + XFA_ScriptType eValueType; }; #endif // XFA_FXFA_FXFA_BASIC_H_ diff --git a/xfa/fxfa/fxfa_widget.h b/xfa/fxfa/fxfa_widget.h deleted file mode 100644 index 74c63c9d52e905302f945812b8478bbfd36b6352..0000000000000000000000000000000000000000 --- a/xfa/fxfa/fxfa_widget.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_FXFA_WIDGET_H_ -#define XFA_FXFA_FXFA_WIDGET_H_ - -#include <memory> - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxfa/parser/cxfa_box.h" -#include "xfa/fxfa/parser/cxfa_event.h" -#include "xfa/fxfa/parser/cxfa_image.h" -#include "xfa/fxfa/parser/cxfa_margin.h" -#include "xfa/fxfa/parser/cxfa_script.h" -#include "xfa/fxfa/parser/cxfa_value.h" -#include "xfa/fxfa/parser/cxfa_widgetdata.h" - -class CFGAS_GEFont; -class CXFA_EventParam; -class CXFA_FFApp; -class CXFA_FFDoc; -class CXFA_FFDocView; -class CXFA_FFWidget; -class CXFA_Node; -class CXFA_TextLayout; -class CXFA_WidgetLayoutData; -class IXFA_AppProvider; - -class CXFA_WidgetAcc : public CXFA_WidgetData { - public: - CXFA_WidgetAcc(CXFA_FFDocView* pDocView, CXFA_Node* pNode); - ~CXFA_WidgetAcc(); - - bool GetName(CFX_WideString& wsName, int32_t iNameType = 0); - bool ProcessValueChanged(); - void ResetData(); - - void SetImageEdit(const CFX_WideString& wsContentType, - const CFX_WideString& wsHref, - const CFX_WideString& wsData); - - CXFA_WidgetAcc* GetExclGroup(); - CXFA_FFDocView* GetDocView(); - CXFA_FFDoc* GetDoc(); - CXFA_FFApp* GetApp(); - IXFA_AppProvider* GetAppProvider(); - - int32_t ProcessEvent(int32_t iActivity, CXFA_EventParam* pEventParam); - int32_t ProcessEvent(CXFA_Event& event, CXFA_EventParam* pEventParam); - int32_t ProcessCalculate(); - int32_t ProcessValidate(int32_t iFlags = 0); - int32_t ExecuteScript(CXFA_Script script, - CXFA_EventParam* pEventParam, - CFXJSE_Value** pRetValue = nullptr); - - CXFA_FFWidget* GetNextWidget(CXFA_FFWidget* pWidget); - void StartWidgetLayout(FX_FLOAT& fCalcWidth, FX_FLOAT& fCalcHeight); - bool FindSplitPos(int32_t iBlockIndex, FX_FLOAT& fCalcHeight); - bool LoadCaption(); - void LoadText(); - bool LoadImageImage(); - bool LoadImageEditImage(); - void GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); - void GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi); - CXFA_TextLayout* GetCaptionTextLayout(); - CXFA_TextLayout* GetTextLayout(); - CFX_DIBitmap* GetImageImage(); - CFX_DIBitmap* GetImageEditImage(); - void SetImageImage(CFX_DIBitmap* newImage); - void SetImageEditImage(CFX_DIBitmap* newImage); - void UpdateUIDisplay(CXFA_FFWidget* pExcept = nullptr); - - CXFA_Node* GetDatasets(); - CFX_RetainPtr<CFGAS_GEFont> GetFDEFont(); - FX_FLOAT GetFontSize(); - FX_ARGB GetTextColor(); - FX_FLOAT GetLineHeight(); - CXFA_WidgetLayoutData* GetWidgetLayoutData(); - - protected: - void ProcessScriptTestValidate(CXFA_Validate validate, - int32_t iRet, - CFXJSE_Value* pRetValue, - bool bVersionFlag); - int32_t ProcessFormatTestValidate(CXFA_Validate validate, bool bVersionFlag); - int32_t ProcessNullTestValidate(CXFA_Validate validate, - int32_t iFlags, - bool bVersionFlag); - CFX_WideString GetValidateCaptionName(bool bVersionFlag); - CFX_WideString GetValidateMessage(bool bError, bool bVersionFlag); - void CalcCaptionSize(CFX_SizeF& szCap); - bool CalculateFieldAutoSize(CFX_SizeF& size); - bool CalculateWidgetAutoSize(CFX_SizeF& size); - bool CalculateTextEditAutoSize(CFX_SizeF& size); - bool CalculateCheckButtonAutoSize(CFX_SizeF& size); - bool CalculatePushButtonAutoSize(CFX_SizeF& size); - bool CalculateImageEditAutoSize(CFX_SizeF& size); - bool CalculateImageAutoSize(CFX_SizeF& size); - bool CalculateTextAutoSize(CFX_SizeF& size); - FX_FLOAT CalculateWidgetAutoHeight(FX_FLOAT fHeightCalc); - FX_FLOAT CalculateWidgetAutoWidth(FX_FLOAT fWidthCalc); - FX_FLOAT GetWidthWithoutMargin(FX_FLOAT fWidthCalc); - FX_FLOAT GetHeightWithoutMargin(FX_FLOAT fHeightCalc); - void CalculateTextContentSize(CFX_SizeF& size); - void CalculateAccWidthAndHeight(XFA_Element eUIType, - FX_FLOAT& fWidth, - FX_FLOAT& fCalcHeight); - void InitLayoutData(); - void StartTextLayout(FX_FLOAT& fCalcWidth, FX_FLOAT& fCalcHeight); - - CXFA_FFDocView* m_pDocView; - std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData; - uint32_t m_nRecursionDepth; -}; - -#endif // XFA_FXFA_FXFA_WIDGET_H_ diff --git a/xfa/fxfa/parser/cscript_datawindow.cpp b/xfa/fxfa/parser/cscript_datawindow.cpp index c0354a112c519d2a1193c273f9b23c8cfdd27161..0bf17e54c0e767122d4aa24c8c57930fd4d62f96 100644 --- a/xfa/fxfa/parser/cscript_datawindow.cpp +++ b/xfa/fxfa/parser/cscript_datawindow.cpp @@ -6,40 +6,17 @@ #include "xfa/fxfa/parser/cscript_datawindow.h" -#include "fxjs/cfxjse_arguments.h" +#include "fxjs/xfa/cjx_datawindow.h" +#include "third_party/base/ptr_util.h" #include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" #include "xfa/fxfa/parser/xfa_utils.h" CScript_DataWindow::CScript_DataWindow(CXFA_Document* pDocument) : CXFA_Object(pDocument, XFA_ObjectType::Object, XFA_Element::DataWindow, - CFX_WideStringC(L"dataWindow")) {} + WideStringView(L"dataWindow"), + pdfium::MakeUnique<CJX_DataWindow>(this)) {} CScript_DataWindow::~CScript_DataWindow() {} - -void CScript_DataWindow::MoveCurrentRecord(CFXJSE_Arguments* pArguments) {} - -void CScript_DataWindow::Record(CFXJSE_Arguments* pArguments) {} - -void CScript_DataWindow::GotoRecord(CFXJSE_Arguments* pArguments) {} - -void CScript_DataWindow::IsRecordGroup(CFXJSE_Arguments* pArguments) {} - -void CScript_DataWindow::RecordsBefore(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CScript_DataWindow::CurrentRecordNumber(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CScript_DataWindow::RecordsAfter(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CScript_DataWindow::IsDefined(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} diff --git a/xfa/fxfa/parser/cscript_datawindow.h b/xfa/fxfa/parser/cscript_datawindow.h index e41b7fe17daebcf513199bf3f05361f457a47f21..819e8fe6016068faac139c3422bbf4469302a9e6 100644 --- a/xfa/fxfa/parser/cscript_datawindow.h +++ b/xfa/fxfa/parser/cscript_datawindow.h @@ -7,28 +7,17 @@ #ifndef XFA_FXFA_PARSER_CSCRIPT_DATAWINDOW_H_ #define XFA_FXFA_PARSER_CSCRIPT_DATAWINDOW_H_ -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_datawindow.h" +#include "xfa/fxfa/parser/cxfa_object.h" class CScript_DataWindow : public CXFA_Object { public: explicit CScript_DataWindow(CXFA_Document* pDocument); ~CScript_DataWindow() override; - void MoveCurrentRecord(CFXJSE_Arguments* pArguments); - void Record(CFXJSE_Arguments* pArguments); - void GotoRecord(CFXJSE_Arguments* pArguments); - void IsRecordGroup(CFXJSE_Arguments* pArguments); - void RecordsBefore(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void CurrentRecordNumber(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void RecordsAfter(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void IsDefined(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); + CJX_DataWindow* JSDataWindow() { + return static_cast<CJX_DataWindow*>(JSObject()); + } }; #endif // XFA_FXFA_PARSER_CSCRIPT_DATAWINDOW_H_ diff --git a/xfa/fxfa/parser/cscript_eventpseudomodel.cpp b/xfa/fxfa/parser/cscript_eventpseudomodel.cpp index 8cfedd299879f74affe04a209d15c04f837d3ff6..da7fcb45b84923d02c0d392bffc9f3581ce4c9c6 100644 --- a/xfa/fxfa/parser/cscript_eventpseudomodel.cpp +++ b/xfa/fxfa/parser/cscript_eventpseudomodel.cpp @@ -6,227 +6,14 @@ #include "xfa/fxfa/parser/cscript_eventpseudomodel.h" -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" -#include "xfa/fxfa/xfa_ffwidgethandler.h" - -namespace { - -void StringProperty(CFXJSE_Value* pValue, - CFX_WideString& wsValue, - bool bSetting) { - if (bSetting) { - wsValue = pValue->ToWideString(); - return; - } - pValue->SetString(wsValue.UTF8Encode().AsStringC()); -} - -void InterProperty(CFXJSE_Value* pValue, int32_t& iValue, bool bSetting) { - if (bSetting) { - iValue = pValue->ToInteger(); - return; - } - pValue->SetInteger(iValue); -} - -void BooleanProperty(CFXJSE_Value* pValue, bool& bValue, bool bSetting) { - if (bSetting) { - bValue = pValue->ToBoolean(); - return; - } - pValue->SetBoolean(bValue); -} - -} // namespace +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" CScript_EventPseudoModel::CScript_EventPseudoModel(CXFA_Document* pDocument) : CXFA_Object(pDocument, XFA_ObjectType::Object, XFA_Element::EventPseudoModel, - CFX_WideStringC(L"eventPseudoModel")) {} + WideStringView(L"eventPseudoModel"), + pdfium::MakeUnique<CJX_EventPseudoModel>(this)) {} CScript_EventPseudoModel::~CScript_EventPseudoModel() {} - -void CScript_EventPseudoModel::Property(CFXJSE_Value* pValue, - XFA_Event dwFlag, - bool bSetting) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) - return; - - CXFA_EventParam* pEventParam = pScriptContext->GetEventParam(); - if (!pEventParam) - return; - - switch (dwFlag) { - case XFA_Event::CancelAction: - BooleanProperty(pValue, pEventParam->m_bCancelAction, bSetting); - break; - case XFA_Event::Change: - StringProperty(pValue, pEventParam->m_wsChange, bSetting); - break; - case XFA_Event::CommitKey: - InterProperty(pValue, pEventParam->m_iCommitKey, bSetting); - break; - case XFA_Event::FullText: - StringProperty(pValue, pEventParam->m_wsFullText, bSetting); - break; - case XFA_Event::Keydown: - BooleanProperty(pValue, pEventParam->m_bKeyDown, bSetting); - break; - case XFA_Event::Modifier: - BooleanProperty(pValue, pEventParam->m_bModifier, bSetting); - break; - case XFA_Event::NewContentType: - StringProperty(pValue, pEventParam->m_wsNewContentType, bSetting); - break; - case XFA_Event::NewText: - StringProperty(pValue, pEventParam->m_wsNewText, bSetting); - break; - case XFA_Event::PreviousContentType: - StringProperty(pValue, pEventParam->m_wsPrevContentType, bSetting); - break; - case XFA_Event::PreviousText: - StringProperty(pValue, pEventParam->m_wsPrevText, bSetting); - break; - case XFA_Event::Reenter: - BooleanProperty(pValue, pEventParam->m_bReenter, bSetting); - break; - case XFA_Event::SelectionEnd: - InterProperty(pValue, pEventParam->m_iSelEnd, bSetting); - break; - case XFA_Event::SelectionStart: - InterProperty(pValue, pEventParam->m_iSelStart, bSetting); - break; - case XFA_Event::Shift: - BooleanProperty(pValue, pEventParam->m_bShift, bSetting); - break; - case XFA_Event::SoapFaultCode: - StringProperty(pValue, pEventParam->m_wsSoapFaultCode, bSetting); - break; - case XFA_Event::SoapFaultString: - StringProperty(pValue, pEventParam->m_wsSoapFaultString, bSetting); - break; - case XFA_Event::Target: - break; - default: - break; - } -} -void CScript_EventPseudoModel::Change(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::Change, bSetting); -} -void CScript_EventPseudoModel::CommitKey(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::CommitKey, bSetting); -} -void CScript_EventPseudoModel::FullText(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::FullText, bSetting); -} -void CScript_EventPseudoModel::KeyDown(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::Keydown, bSetting); -} -void CScript_EventPseudoModel::Modifier(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::Modifier, bSetting); -} -void CScript_EventPseudoModel::NewContentType(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::NewContentType, bSetting); -} -void CScript_EventPseudoModel::NewText(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::NewText, bSetting); -} -void CScript_EventPseudoModel::PrevContentType(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::PreviousContentType, bSetting); -} -void CScript_EventPseudoModel::PrevText(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::PreviousText, bSetting); -} -void CScript_EventPseudoModel::Reenter(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::Reenter, bSetting); -} -void CScript_EventPseudoModel::SelEnd(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::SelectionEnd, bSetting); -} -void CScript_EventPseudoModel::SelStart(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::SelectionStart, bSetting); -} -void CScript_EventPseudoModel::Shift(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::Shift, bSetting); -} -void CScript_EventPseudoModel::SoapFaultCode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::SoapFaultCode, bSetting); -} -void CScript_EventPseudoModel::SoapFaultString(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::SoapFaultString, bSetting); -} -void CScript_EventPseudoModel::Target(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Property(pValue, XFA_Event::Target, bSetting); -} -void CScript_EventPseudoModel::Emit(CFXJSE_Arguments* pArguments) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) { - return; - } - CXFA_EventParam* pEventParam = pScriptContext->GetEventParam(); - if (!pEventParam) { - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFWidgetHandler* pWidgetHandler = pNotify->GetWidgetHandler(); - if (!pWidgetHandler) { - return; - } - pWidgetHandler->ProcessEvent(pEventParam->m_pTarget, pEventParam); -} -void CScript_EventPseudoModel::Reset(CFXJSE_Arguments* pArguments) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) { - return; - } - CXFA_EventParam* pEventParam = pScriptContext->GetEventParam(); - if (!pEventParam) { - return; - } - pEventParam->Reset(); -} diff --git a/xfa/fxfa/parser/cscript_eventpseudomodel.h b/xfa/fxfa/parser/cscript_eventpseudomodel.h index 6415287c8e3c0bb5e0123b157ba238024af7df96..efb4df01884aa34dbdb353447145d7cc30202a36 100644 --- a/xfa/fxfa/parser/cscript_eventpseudomodel.h +++ b/xfa/fxfa/parser/cscript_eventpseudomodel.h @@ -7,64 +7,17 @@ #ifndef XFA_FXFA_PARSER_CSCRIPT_EVENTPSEUDOMODEL_H_ #define XFA_FXFA_PARSER_CSCRIPT_EVENTPSEUDOMODEL_H_ -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/xfa_object.h" - -enum class XFA_Event { - Change = 0, - CommitKey, - FullText, - Keydown, - Modifier, - NewContentType, - NewText, - PreviousContentType, - PreviousText, - Reenter, - SelectionEnd, - SelectionStart, - Shift, - SoapFaultCode, - SoapFaultString, - Target, - CancelAction -}; +#include "fxjs/xfa/cjx_eventpseudomodel.h" +#include "xfa/fxfa/parser/cxfa_object.h" class CScript_EventPseudoModel : public CXFA_Object { public: explicit CScript_EventPseudoModel(CXFA_Document* pDocument); ~CScript_EventPseudoModel() override; - void Change(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void CommitKey(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void FullText(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void KeyDown(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Modifier(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void NewContentType(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void NewText(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void PrevContentType(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void PrevText(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Reenter(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void SelEnd(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void SelStart(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Shift(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void SoapFaultCode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void SoapFaultString(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Target(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - - void Emit(CFXJSE_Arguments* pArguments); - void Reset(CFXJSE_Arguments* pArguments); - - protected: - void Property(CFXJSE_Value* pValue, XFA_Event dwFlag, bool bSetting); + CJX_EventPseudoModel* JSEventPseudoModel() { + return static_cast<CJX_EventPseudoModel*>(JSObject()); + } }; #endif // XFA_FXFA_PARSER_CSCRIPT_EVENTPSEUDOMODEL_H_ diff --git a/xfa/fxfa/parser/cscript_hostpseudomodel.cpp b/xfa/fxfa/parser/cscript_hostpseudomodel.cpp index a06e02f56d39ca6fad1d80907407ffa96758fd68..8122aa32f7db75dae2e6b8752d4b07819ab692a3 100644 --- a/xfa/fxfa/parser/cscript_hostpseudomodel.cpp +++ b/xfa/fxfa/parser/cscript_hostpseudomodel.cpp @@ -6,694 +6,13 @@ #include "xfa/fxfa/parser/cscript_hostpseudomodel.h" -#include <memory> - -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -namespace { - -CXFA_Node* ToNode(CFXJSE_Value* pValue, CFXJSE_Class* pClass) { - return static_cast<CXFA_Node*>(pValue->ToHostObject(pClass)); -} - -} // namespace +#include "third_party/base/ptr_util.h" CScript_HostPseudoModel::CScript_HostPseudoModel(CXFA_Document* pDocument) : CXFA_Object(pDocument, XFA_ObjectType::Object, XFA_Element::HostPseudoModel, - CFX_WideStringC(L"hostPseudoModel")) {} + WideStringView(L"hostPseudoModel"), + pdfium::MakeUnique<CJX_HostPseudoModel>(this)) {} CScript_HostPseudoModel::~CScript_HostPseudoModel() {} - -void CScript_HostPseudoModel::AppType(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - pValue->SetString("Exchange"); -} - -void CScript_HostPseudoModel::CalculationsEnabled(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - if (bSetting) { - pNotify->GetDocEnvironment()->SetCalculationsEnabled(hDoc, - pValue->ToBoolean()); - return; - } - pValue->SetBoolean(pNotify->GetDocEnvironment()->IsCalculationsEnabled(hDoc)); -} - -void CScript_HostPseudoModel::CurrentPage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - if (bSetting) { - pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, pValue->ToInteger()); - return; - } - pValue->SetInteger(pNotify->GetDocEnvironment()->GetCurrentPage(hDoc)); -} - -void CScript_HostPseudoModel::Language(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - if (bSetting) { - ThrowSetLanguageException(); - return; - } - pValue->SetString( - pNotify->GetAppProvider()->GetLanguage().UTF8Encode().AsStringC()); -} - -void CScript_HostPseudoModel::NumPages(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - if (bSetting) { - ThrowSetNumPagesException(); - return; - } - pValue->SetInteger(pNotify->GetDocEnvironment()->CountPages(hDoc)); -} - -void CScript_HostPseudoModel::Platform(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - if (bSetting) { - ThrowSetPlatformException(); - return; - } - pValue->SetString( - pNotify->GetAppProvider()->GetPlatform().UTF8Encode().AsStringC()); -} - -void CScript_HostPseudoModel::Title(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - if (bSetting) { - pNotify->GetDocEnvironment()->SetTitle(hDoc, pValue->ToWideString()); - return; - } - CFX_WideString wsTitle; - pNotify->GetDocEnvironment()->GetTitle(hDoc, wsTitle); - pValue->SetString(wsTitle.UTF8Encode().AsStringC()); -} - -void CScript_HostPseudoModel::ValidationsEnabled(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - if (bSetting) { - pNotify->GetDocEnvironment()->SetValidationsEnabled(hDoc, - pValue->ToBoolean()); - return; - } - bool bEnabled = pNotify->GetDocEnvironment()->IsValidationsEnabled(hDoc); - pValue->SetBoolean(bEnabled); -} - -void CScript_HostPseudoModel::Variation(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) - return; - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - if (bSetting) { - ThrowSetVariationException(); - return; - } - pValue->SetString("Full"); -} - -void CScript_HostPseudoModel::Version(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - if (bSetting) { - ThrowSetVersionException(); - return; - } - pValue->SetString("11"); -} - -void CScript_HostPseudoModel::Name(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - pValue->SetString( - pNotify->GetAppProvider()->GetAppName().UTF8Encode().AsStringC()); -} - -void CScript_HostPseudoModel::GotoURL(CFXJSE_Arguments* pArguments) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"gotoURL"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - CFX_WideString wsURL; - if (iLength >= 1) { - CFX_ByteString bsURL = pArguments->GetUTF8String(0); - wsURL = CFX_WideString::FromUTF8(bsURL.AsStringC()); - } - pNotify->GetDocEnvironment()->GotoURL(hDoc, wsURL); -} -void CScript_HostPseudoModel::OpenList(CFXJSE_Arguments* pArguments) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"openList"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_Node* pNode = nullptr; - if (iLength >= 1) { - std::unique_ptr<CFXJSE_Value> pValue(pArguments->GetValue(0)); - if (pValue->IsObject()) { - pNode = ToNode(pValue.get(), nullptr); - } else if (pValue->IsString()) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) - return; - - CXFA_Object* pObject = pScriptContext->GetThisObject(); - if (!pObject) - return; - - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Siblings; - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = pScriptContext->ResolveObjects( - pObject, pValue->ToWideString().AsStringC(), resoveNodeRS, dwFlag); - if (iRet < 1 || !resoveNodeRS.nodes[0]->IsNode()) - return; - - pNode = resoveNodeRS.nodes[0]->AsNode(); - } - } - CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); - if (!pDocLayout) { - return; - } - CXFA_FFWidget* hWidget = - pNotify->GetHWidget(pDocLayout->GetLayoutItem(pNode)); - if (!hWidget) { - return; - } - pNotify->GetDocEnvironment()->SetFocusWidget(pNotify->GetHDOC(), hWidget); - pNotify->OpenDropDownList(hWidget); -} -void CScript_HostPseudoModel::Response(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 4) { - ThrowParamCountMismatchException(L"response"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CFX_WideString wsQuestion; - CFX_WideString wsTitle; - CFX_WideString wsDefaultAnswer; - bool bMark = false; - if (iLength >= 1) { - CFX_ByteString bsQuestion = pArguments->GetUTF8String(0); - wsQuestion = CFX_WideString::FromUTF8(bsQuestion.AsStringC()); - } - if (iLength >= 2) { - CFX_ByteString bsTitle = pArguments->GetUTF8String(1); - wsTitle = CFX_WideString::FromUTF8(bsTitle.AsStringC()); - } - if (iLength >= 3) { - CFX_ByteString bsDefaultAnswer = pArguments->GetUTF8String(2); - wsDefaultAnswer = CFX_WideString::FromUTF8(bsDefaultAnswer.AsStringC()); - } - if (iLength >= 4) { - bMark = pArguments->GetInt32(3) == 0 ? false : true; - } - CFX_WideString wsAnswer = pNotify->GetAppProvider()->Response( - wsQuestion, wsTitle, wsDefaultAnswer, bMark); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetString(wsAnswer.UTF8Encode().AsStringC()); -} - -void CScript_HostPseudoModel::DocumentInBatch(CFXJSE_Arguments* pArguments) { - if (CFXJSE_Value* pValue = pArguments->GetReturnValue()) - pValue->SetInteger(0); -} -static int32_t XFA_FilterName(const CFX_WideStringC& wsExpression, - int32_t nStart, - CFX_WideString& wsFilter) { - ASSERT(nStart > -1); - int32_t iLength = wsExpression.GetLength(); - if (nStart >= iLength) { - return iLength; - } - FX_WCHAR* pBuf = wsFilter.GetBuffer(iLength - nStart); - int32_t nCount = 0; - const FX_WCHAR* pSrc = wsExpression.c_str(); - FX_WCHAR wCur; - while (nStart < iLength) { - wCur = pSrc[nStart++]; - if (wCur == ',') { - break; - } - pBuf[nCount++] = wCur; - } - wsFilter.ReleaseBuffer(nCount); - wsFilter.TrimLeft(); - wsFilter.TrimRight(); - return nStart; -} -void CScript_HostPseudoModel::ResetData(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 0 || iLength > 1) { - ThrowParamCountMismatchException(L"resetData"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CFX_WideString wsExpression; - if (iLength >= 1) { - CFX_ByteString bsExpression = pArguments->GetUTF8String(0); - wsExpression = CFX_WideString::FromUTF8(bsExpression.AsStringC()); - } - if (wsExpression.IsEmpty()) { - pNotify->ResetData(); - return; - } - int32_t iStart = 0; - CFX_WideString wsName; - CXFA_Node* pNode = nullptr; - int32_t iExpLength = wsExpression.GetLength(); - while (iStart < iExpLength) { - iStart = XFA_FilterName(wsExpression.AsStringC(), iStart, wsName); - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) { - return; - } - CXFA_Object* pObject = pScriptContext->GetThisObject(); - if (!pObject) { - return; - } - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Siblings; - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = pScriptContext->ResolveObjects(pObject, wsName.AsStringC(), - resoveNodeRS, dwFlag); - if (iRet < 1 || !resoveNodeRS.nodes[0]->IsNode()) { - continue; - } - pNode = resoveNodeRS.nodes[0]->AsNode(); - pNotify->ResetData(pNode->GetWidgetData()); - } - if (!pNode) { - pNotify->ResetData(); - } -} -void CScript_HostPseudoModel::Beep(CFXJSE_Arguments* pArguments) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - int32_t iLength = pArguments->GetLength(); - if (iLength < 0 || iLength > 1) { - ThrowParamCountMismatchException(L"beep"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - uint32_t dwType = 4; - if (iLength >= 1) { - dwType = pArguments->GetInt32(0); - } - pNotify->GetAppProvider()->Beep(dwType); -} -void CScript_HostPseudoModel::SetFocus(CFXJSE_Arguments* pArguments) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"setFocus"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_Node* pNode = nullptr; - if (iLength >= 1) { - std::unique_ptr<CFXJSE_Value> pValue(pArguments->GetValue(0)); - if (pValue->IsObject()) { - pNode = ToNode(pValue.get(), nullptr); - } else if (pValue->IsString()) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) - return; - - CXFA_Object* pObject = pScriptContext->GetThisObject(); - if (!pObject) - return; - - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Siblings; - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = pScriptContext->ResolveObjects( - pObject, pValue->ToWideString().AsStringC(), resoveNodeRS, dwFlag); - if (iRet < 1 || !resoveNodeRS.nodes[0]->IsNode()) - return; - - pNode = resoveNodeRS.nodes[0]->AsNode(); - } - } - pNotify->SetFocusWidgetNode(pNode); -} - -void CScript_HostPseudoModel::GetFocus(CFXJSE_Arguments* pArguments) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_Node* pNode = pNotify->GetFocusWidgetNode(); - if (!pNode) { - return; - } - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNode)); -} -void CScript_HostPseudoModel::MessageBox(CFXJSE_Arguments* pArguments) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 4) { - ThrowParamCountMismatchException(L"messageBox"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CFX_WideString wsMessage; - CFX_WideString bsTitle; - uint32_t dwMessageType = XFA_MBICON_Error; - uint32_t dwButtonType = XFA_MB_OK; - if (iLength >= 1) { - if (!ValidateArgsForMsg(pArguments, 0, wsMessage)) { - return; - } - } - if (iLength >= 2) { - if (!ValidateArgsForMsg(pArguments, 1, bsTitle)) { - return; - } - } - if (iLength >= 3) { - dwMessageType = pArguments->GetInt32(2); - if (dwMessageType > XFA_MBICON_Status) { - dwMessageType = XFA_MBICON_Error; - } - } - if (iLength >= 4) { - dwButtonType = pArguments->GetInt32(3); - if (dwButtonType > XFA_MB_YesNoCancel) { - dwButtonType = XFA_MB_OK; - } - } - int32_t iValue = pNotify->GetAppProvider()->MsgBox( - wsMessage, bsTitle, dwMessageType, dwButtonType); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(iValue); -} -bool CScript_HostPseudoModel::ValidateArgsForMsg(CFXJSE_Arguments* pArguments, - int32_t iArgIndex, - CFX_WideString& wsValue) { - if (!pArguments || iArgIndex < 0) { - return false; - } - bool bIsJsType = false; - if (m_pDocument->GetScriptContext()->GetType() == - XFA_SCRIPTLANGTYPE_Javascript) { - bIsJsType = true; - } - std::unique_ptr<CFXJSE_Value> pValueArg(pArguments->GetValue(iArgIndex)); - if (!pValueArg->IsString() && bIsJsType) { - ThrowArgumentMismatchException(); - return false; - } - if (pValueArg->IsNull()) { - wsValue = L""; - } else { - wsValue = pValueArg->ToWideString(); - } - return true; -} -void CScript_HostPseudoModel::DocumentCountInBatch( - CFXJSE_Arguments* pArguments) { - if (CFXJSE_Value* pValue = pArguments->GetReturnValue()) - pValue->SetInteger(0); -} -void CScript_HostPseudoModel::Print(CFXJSE_Arguments* pArguments) { - if (!m_pDocument->GetScriptContext()->IsRunAtClient()) { - return; - } - int32_t iLength = pArguments->GetLength(); - if (iLength != 8) { - ThrowParamCountMismatchException(L"print"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - uint32_t dwOptions = 0; - bool bShowDialog = true; - if (iLength >= 1) { - bShowDialog = pArguments->GetInt32(0) == 0 ? false : true; - } - if (bShowDialog) { - dwOptions |= XFA_PRINTOPT_ShowDialog; - } - int32_t nStartPage = 0; - if (iLength >= 2) { - nStartPage = pArguments->GetInt32(1); - } - int32_t nEndPage = 0; - if (iLength >= 3) { - nEndPage = pArguments->GetInt32(2); - } - bool bCanCancel = true; - if (iLength >= 4) { - bCanCancel = pArguments->GetInt32(3) == 0 ? false : true; - } - if (bCanCancel) { - dwOptions |= XFA_PRINTOPT_CanCancel; - } - bool bShrinkPage = true; - if (iLength >= 5) { - bShrinkPage = pArguments->GetInt32(4) == 0 ? false : true; - } - if (bShrinkPage) { - dwOptions |= XFA_PRINTOPT_ShrinkPage; - } - bool bAsImage = true; - if (iLength >= 6) { - bAsImage = pArguments->GetInt32(5) == 0 ? false : true; - } - if (bAsImage) { - dwOptions |= XFA_PRINTOPT_AsImage; - } - bool bReverseOrder = true; - if (iLength >= 7) { - bAsImage = pArguments->GetInt32(5) == 0 ? false : true; - } - bReverseOrder = pArguments->GetInt32(6) == 0 ? false : true; - if (bReverseOrder) { - dwOptions |= XFA_PRINTOPT_ReverseOrder; - } - bool bPrintAnnot = true; - if (iLength >= 8) { - bPrintAnnot = pArguments->GetInt32(7) == 0 ? false : true; - } - if (bPrintAnnot) { - dwOptions |= XFA_PRINTOPT_PrintAnnot; - } - pNotify->GetDocEnvironment()->Print(hDoc, nStartPage, nEndPage, dwOptions); -} - -void CScript_HostPseudoModel::ImportData(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 0 || iLength > 1) { - ThrowParamCountMismatchException(L"importData"); - return; - } - // Not implemented. -} - -void CScript_HostPseudoModel::ExportData(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 0 || iLength > 2) { - ThrowParamCountMismatchException(L"exportData"); - return; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - CFX_WideString wsFilePath; - bool bXDP = true; - if (iLength >= 1) { - CFX_ByteString bsFilePath = pArguments->GetUTF8String(0); - wsFilePath = CFX_WideString::FromUTF8(bsFilePath.AsStringC()); - } - if (iLength >= 2) { - bXDP = pArguments->GetInt32(1) == 0 ? false : true; - } - pNotify->GetDocEnvironment()->ExportData(hDoc, wsFilePath, bXDP); -} - -void CScript_HostPseudoModel::PageUp(CFXJSE_Arguments* pArguments) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - int32_t nCurPage = pNotify->GetDocEnvironment()->GetCurrentPage(hDoc); - int32_t nNewPage = 0; - if (nCurPage <= 1) { - return; - } - nNewPage = nCurPage - 1; - pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage); -} - -void CScript_HostPseudoModel::PageDown(CFXJSE_Arguments* pArguments) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_FFDoc* hDoc = pNotify->GetHDOC(); - int32_t nCurPage = pNotify->GetDocEnvironment()->GetCurrentPage(hDoc); - int32_t nPageCount = pNotify->GetDocEnvironment()->CountPages(hDoc); - if (!nPageCount || nCurPage == nPageCount) { - return; - } - int32_t nNewPage = 0; - if (nCurPage >= nPageCount) { - nNewPage = nPageCount - 1; - } else { - nNewPage = nCurPage + 1; - } - pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage); -} - -void CScript_HostPseudoModel::CurrentDateTime(CFXJSE_Arguments* pArguments) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CFX_WideString wsDataTime = pNotify->GetCurrentDateTime(); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetString(wsDataTime.UTF8Encode().AsStringC()); -} - -void CScript_HostPseudoModel::ThrowSetLanguageException() const { - ThrowException(L"Unable to set language value."); -} - -void CScript_HostPseudoModel::ThrowSetNumPagesException() const { - ThrowException(L"Unable to set numPages value."); -} - -void CScript_HostPseudoModel::ThrowSetPlatformException() const { - ThrowException(L"Unable to set platform value."); -} - -void CScript_HostPseudoModel::ThrowSetVariationException() const { - ThrowException(L"Unable to set variation value."); -} - -void CScript_HostPseudoModel::ThrowSetVersionException() const { - ThrowException(L"Unable to set version value."); -} diff --git a/xfa/fxfa/parser/cscript_hostpseudomodel.h b/xfa/fxfa/parser/cscript_hostpseudomodel.h index 7d24a1d2b42fabe3702665e34b65c64bc7e80293..7e4a37d4d58e8e5faf6f9d602aa2325e5245535a 100644 --- a/xfa/fxfa/parser/cscript_hostpseudomodel.h +++ b/xfa/fxfa/parser/cscript_hostpseudomodel.h @@ -7,60 +7,19 @@ #ifndef XFA_FXFA_PARSER_CSCRIPT_HOSTPSEUDOMODEL_H_ #define XFA_FXFA_PARSER_CSCRIPT_HOSTPSEUDOMODEL_H_ -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_hostpseudomodel.h" +#include "xfa/fxfa/parser/cxfa_object.h" + +class CXFA_Document; class CScript_HostPseudoModel : public CXFA_Object { public: explicit CScript_HostPseudoModel(CXFA_Document* pDocument); ~CScript_HostPseudoModel() override; - void AppType(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void CalculationsEnabled(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void CurrentPage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Language(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void NumPages(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Platform(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Title(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void ValidationsEnabled(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Variation(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Version(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void Name(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - void GotoURL(CFXJSE_Arguments* pArguments); - void OpenList(CFXJSE_Arguments* pArguments); - void Response(CFXJSE_Arguments* pArguments); - void DocumentInBatch(CFXJSE_Arguments* pArguments); - void ResetData(CFXJSE_Arguments* pArguments); - void Beep(CFXJSE_Arguments* pArguments); - void SetFocus(CFXJSE_Arguments* pArguments); - void GetFocus(CFXJSE_Arguments* pArguments); - void MessageBox(CFXJSE_Arguments* pArguments); - void DocumentCountInBatch(CFXJSE_Arguments* pArguments); - void Print(CFXJSE_Arguments* pArguments); - void ImportData(CFXJSE_Arguments* pArguments); - void ExportData(CFXJSE_Arguments* pArguments); - void PageUp(CFXJSE_Arguments* pArguments); - void PageDown(CFXJSE_Arguments* pArguments); - void CurrentDateTime(CFXJSE_Arguments* pArguments); - - protected: - bool ValidateArgsForMsg(CFXJSE_Arguments* pArguments, - int32_t iArgIndex, - CFX_WideString& wsValue); - - private: - void ThrowSetLanguageException() const; - void ThrowSetNumPagesException() const; - void ThrowSetPlatformException() const; - void ThrowSetVariationException() const; - void ThrowSetVersionException() const; + CJX_HostPseudoModel* JSHostPseudoModel() { + return static_cast<CJX_HostPseudoModel*>(JSObject()); + } }; #endif // XFA_FXFA_PARSER_CSCRIPT_HOSTPSEUDOMODEL_H_ diff --git a/xfa/fxfa/parser/cscript_layoutpseudomodel.cpp b/xfa/fxfa/parser/cscript_layoutpseudomodel.cpp index 152b568619537721bc0a69b9d70a66c631ebba41..73033d5bead6fd61abb08dbe3b1b26343b47606b 100644 --- a/xfa/fxfa/parser/cscript_layoutpseudomodel.cpp +++ b/xfa/fxfa/parser/cscript_layoutpseudomodel.cpp @@ -6,483 +6,13 @@ #include "xfa/fxfa/parser/cscript_layoutpseudomodel.h" -#include <set> - -#include "fxjs/cfxjse_arguments.h" -#include "third_party/base/stl_util.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" -#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_layoutitem.h" -#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/cxfa_traversestrategy_contentlayoutitem.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" +#include "third_party/base/ptr_util.h" CScript_LayoutPseudoModel::CScript_LayoutPseudoModel(CXFA_Document* pDocument) : CXFA_Object(pDocument, XFA_ObjectType::Object, XFA_Element::LayoutPseudoModel, - CFX_WideStringC(L"layoutPseudoModel")) {} + WideStringView(L"layoutPseudoModel"), + pdfium::MakeUnique<CJX_LayoutPseudoModel>(this)) {} CScript_LayoutPseudoModel::~CScript_LayoutPseudoModel() {} - -void CScript_LayoutPseudoModel::Ready(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - if (bSetting) { - ThrowSetReadyException(); - return; - } - int32_t iStatus = pNotify->GetLayoutStatus(); - pValue->SetBoolean(iStatus >= 2); -} - -void CScript_LayoutPseudoModel::HWXY(CFXJSE_Arguments* pArguments, - XFA_LAYOUTMODEL_HWXY layoutModel) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 3) { - const FX_WCHAR* methodName = nullptr; - switch (layoutModel) { - case XFA_LAYOUTMODEL_H: - methodName = L"h"; - break; - case XFA_LAYOUTMODEL_W: - methodName = L"w"; - break; - case XFA_LAYOUTMODEL_X: - methodName = L"x"; - break; - case XFA_LAYOUTMODEL_Y: - methodName = L"y"; - break; - } - ThrowParamCountMismatchException(methodName); - return; - } - CXFA_Node* pNode = nullptr; - CFX_WideString wsUnit(L"pt"); - int32_t iIndex = 0; - if (iLength >= 1) { - pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - } - if (iLength >= 2) { - CFX_ByteString bsUnit = pArguments->GetUTF8String(1); - if (!bsUnit.IsEmpty()) { - wsUnit = CFX_WideString::FromUTF8(bsUnit.AsStringC()); - } - } - if (iLength >= 3) { - iIndex = pArguments->GetInt32(2); - } - if (!pNode) { - return; - } - CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); - if (!pDocLayout) { - return; - } - - CXFA_Measurement measure; - CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); - if (!pLayoutItem) { - return; - } - while (iIndex > 0 && pLayoutItem) { - pLayoutItem = pLayoutItem->GetNext(); - iIndex--; - } - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (!pLayoutItem) { - pValue->SetFloat(0); - return; - } - - CFX_RectF rtRect = pLayoutItem->GetRect(true); - switch (layoutModel) { - case XFA_LAYOUTMODEL_H: - measure.Set(rtRect.height, XFA_UNIT_Pt); - break; - case XFA_LAYOUTMODEL_W: - measure.Set(rtRect.width, XFA_UNIT_Pt); - break; - case XFA_LAYOUTMODEL_X: - measure.Set(rtRect.left, XFA_UNIT_Pt); - break; - case XFA_LAYOUTMODEL_Y: - measure.Set(rtRect.top, XFA_UNIT_Pt); - break; - } - XFA_UNIT unit = measure.GetUnit(wsUnit.AsStringC()); - FX_FLOAT fValue = measure.ToUnit(unit); - fValue = FXSYS_round(fValue * 1000) / 1000.0f; - if (pValue) - pValue->SetFloat(fValue); -} - -void CScript_LayoutPseudoModel::H(CFXJSE_Arguments* pArguments) { - HWXY(pArguments, XFA_LAYOUTMODEL_H); -} - -void CScript_LayoutPseudoModel::W(CFXJSE_Arguments* pArguments) { - HWXY(pArguments, XFA_LAYOUTMODEL_W); -} - -void CScript_LayoutPseudoModel::X(CFXJSE_Arguments* pArguments) { - HWXY(pArguments, XFA_LAYOUTMODEL_X); -} - -void CScript_LayoutPseudoModel::Y(CFXJSE_Arguments* pArguments) { - HWXY(pArguments, XFA_LAYOUTMODEL_Y); -} - -void CScript_LayoutPseudoModel::NumberedPageCount(CFXJSE_Arguments* pArguments, - bool bNumbered) { - CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); - if (!pDocLayout) { - return; - } - int32_t iPageCount = 0; - int32_t iPageNum = pDocLayout->CountPages(); - if (bNumbered) { - for (int32_t i = 0; i < iPageNum; i++) { - CXFA_ContainerLayoutItem* pLayoutPage = pDocLayout->GetPage(i); - if (!pLayoutPage) { - continue; - } - CXFA_Node* pMasterPage = pLayoutPage->GetMasterPage(); - if (pMasterPage->GetInteger(XFA_ATTRIBUTE_Numbered)) { - iPageCount++; - } - } - } else { - iPageCount = iPageNum; - } - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(iPageCount); -} - -void CScript_LayoutPseudoModel::PageCount(CFXJSE_Arguments* pArguments) { - NumberedPageCount(pArguments, true); -} - -void CScript_LayoutPseudoModel::PageSpan(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"pageSpan"); - return; - } - CXFA_Node* pNode = nullptr; - if (iLength >= 1) { - pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - } - if (!pNode) { - return; - } - CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); - if (!pDocLayout) { - return; - } - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); - if (!pLayoutItem) { - pValue->SetInteger(-1); - return; - } - int32_t iLast = pLayoutItem->GetLast()->GetPage()->GetPageIndex(); - int32_t iFirst = pLayoutItem->GetFirst()->GetPage()->GetPageIndex(); - int32_t iPageSpan = iLast - iFirst + 1; - if (pValue) - pValue->SetInteger(iPageSpan); -} - -void CScript_LayoutPseudoModel::Page(CFXJSE_Arguments* pArguments) { - PageImp(pArguments, false); -} - -void CScript_LayoutPseudoModel::GetObjArray(CXFA_LayoutProcessor* pDocLayout, - int32_t iPageNo, - const CFX_WideString& wsType, - bool bOnPageArea, - CXFA_NodeArray& retArray) { - CXFA_ContainerLayoutItem* pLayoutPage = pDocLayout->GetPage(iPageNo); - if (!pLayoutPage) { - return; - } - if (wsType == L"pageArea") { - if (CXFA_Node* pMasterPage = pLayoutPage->m_pFormNode) { - retArray.Add(pMasterPage); - } - return; - } - if (wsType == L"contentArea") { - for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; - pItem = pItem->m_pNextSibling) { - if (pItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { - retArray.Add(pItem->m_pFormNode); - } - } - return; - } - std::set<CXFA_Node*> formItems; - if (wsType.IsEmpty()) { - if (CXFA_Node* pMasterPage = pLayoutPage->m_pFormNode) { - retArray.Add(pMasterPage); - } - for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; - pItem = pItem->m_pNextSibling) { - if (pItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { - retArray.Add(pItem->m_pFormNode); - if (!bOnPageArea) { - CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, - CXFA_TraverseStrategy_ContentLayoutItem> - iterator(static_cast<CXFA_ContentLayoutItem*>(pItem->m_pFirstChild)); - for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); - pItemChild; pItemChild = iterator.MoveToNext()) { - if (!pItemChild->IsContentLayoutItem()) { - continue; - } - XFA_Element eType = pItemChild->m_pFormNode->GetElementType(); - if (eType != XFA_Element::Field && eType != XFA_Element::Draw && - eType != XFA_Element::Subform && eType != XFA_Element::Area) { - continue; - } - if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) - continue; - - formItems.insert(pItemChild->m_pFormNode); - retArray.Add(pItemChild->m_pFormNode); - } - } - } else { - if (bOnPageArea) { - CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, - CXFA_TraverseStrategy_ContentLayoutItem> - iterator(static_cast<CXFA_ContentLayoutItem*>(pItem)); - for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); - pItemChild; pItemChild = iterator.MoveToNext()) { - if (!pItemChild->IsContentLayoutItem()) { - continue; - } - XFA_Element eType = pItemChild->m_pFormNode->GetElementType(); - if (eType != XFA_Element::Field && eType != XFA_Element::Draw && - eType != XFA_Element::Subform && eType != XFA_Element::Area) { - continue; - } - if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) - continue; - formItems.insert(pItemChild->m_pFormNode); - retArray.Add(pItemChild->m_pFormNode); - } - } - } - } - return; - } - XFA_Element eType = XFA_Element::Unknown; - if (wsType == L"field") { - eType = XFA_Element::Field; - } else if (wsType == L"draw") { - eType = XFA_Element::Draw; - } else if (wsType == L"subform") { - eType = XFA_Element::Subform; - } else if (wsType == L"area") { - eType = XFA_Element::Area; - } - if (eType != XFA_Element::Unknown) { - for (CXFA_LayoutItem* pItem = pLayoutPage->m_pFirstChild; pItem; - pItem = pItem->m_pNextSibling) { - if (pItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { - if (!bOnPageArea) { - CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, - CXFA_TraverseStrategy_ContentLayoutItem> - iterator(static_cast<CXFA_ContentLayoutItem*>(pItem->m_pFirstChild)); - for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); - pItemChild; pItemChild = iterator.MoveToNext()) { - if (!pItemChild->IsContentLayoutItem()) - continue; - if (pItemChild->m_pFormNode->GetElementType() != eType) - continue; - if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) - continue; - formItems.insert(pItemChild->m_pFormNode); - retArray.Add(pItemChild->m_pFormNode); - } - } - } else { - if (bOnPageArea) { - CXFA_NodeIteratorTemplate<CXFA_ContentLayoutItem, - CXFA_TraverseStrategy_ContentLayoutItem> - iterator(static_cast<CXFA_ContentLayoutItem*>(pItem)); - for (CXFA_ContentLayoutItem* pItemChild = iterator.GetCurrent(); - pItemChild; pItemChild = iterator.MoveToNext()) { - if (!pItemChild->IsContentLayoutItem()) - continue; - if (pItemChild->m_pFormNode->GetElementType() != eType) - continue; - if (pdfium::ContainsValue(formItems, pItemChild->m_pFormNode)) - continue; - formItems.insert(pItemChild->m_pFormNode); - retArray.Add(pItemChild->m_pFormNode); - } - } - } - } - return; - } -} - -void CScript_LayoutPseudoModel::PageContent(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 3) { - ThrowParamCountMismatchException(L"pageContent"); - return; - } - int32_t iIndex = 0; - CFX_WideString wsType; - bool bOnPageArea = false; - if (iLength >= 1) { - iIndex = pArguments->GetInt32(0); - } - if (iLength >= 2) { - CFX_ByteString bsType = pArguments->GetUTF8String(1); - wsType = CFX_WideString::FromUTF8(bsType.AsStringC()); - } - if (iLength >= 3) { - bOnPageArea = pArguments->GetInt32(2) == 0 ? false : true; - } - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); - if (!pDocLayout) { - return; - } - CXFA_NodeArray retArray; - GetObjArray(pDocLayout, iIndex, wsType, bOnPageArea, retArray); - CXFA_ArrayNodeList* pArrayNodeList = new CXFA_ArrayNodeList(m_pDocument); - pArrayNodeList->SetArrayNodeList(retArray); - pArguments->GetReturnValue()->SetObject( - pArrayNodeList, m_pDocument->GetScriptContext()->GetJseNormalClass()); -} - -void CScript_LayoutPseudoModel::AbsPageCount(CFXJSE_Arguments* pArguments) { - NumberedPageCount(pArguments, false); -} - -void CScript_LayoutPseudoModel::AbsPageCountInBatch( - CFXJSE_Arguments* pArguments) { - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(0); -} - -void CScript_LayoutPseudoModel::SheetCountInBatch( - CFXJSE_Arguments* pArguments) { - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(0); -} - -void CScript_LayoutPseudoModel::Relayout(CFXJSE_Arguments* pArguments) { - CXFA_Node* pRootNode = m_pDocument->GetRoot(); - CXFA_Node* pFormRoot = pRootNode->GetFirstChildByClass(XFA_Element::Form); - ASSERT(pFormRoot); - CXFA_Node* pContentRootNode = pFormRoot->GetNodeItem(XFA_NODEITEM_FirstChild); - CXFA_LayoutProcessor* pLayoutProcessor = m_pDocument->GetLayoutProcessor(); - if (pContentRootNode) { - pLayoutProcessor->AddChangedContainer(pContentRootNode); - } - pLayoutProcessor->SetForceReLayout(true); -} - -void CScript_LayoutPseudoModel::AbsPageSpan(CFXJSE_Arguments* pArguments) { - PageSpan(pArguments); -} - -void CScript_LayoutPseudoModel::AbsPageInBatch(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"absPageInBatch"); - return; - } - - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(0); -} - -void CScript_LayoutPseudoModel::SheetInBatch(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"sheetInBatch"); - return; - } - - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(0); -} - -void CScript_LayoutPseudoModel::Sheet(CFXJSE_Arguments* pArguments) { - PageImp(pArguments, true); -} - -void CScript_LayoutPseudoModel::RelayoutPageArea(CFXJSE_Arguments* pArguments) { -} - -void CScript_LayoutPseudoModel::SheetCount(CFXJSE_Arguments* pArguments) { - NumberedPageCount(pArguments, false); -} - -void CScript_LayoutPseudoModel::AbsPage(CFXJSE_Arguments* pArguments) { - PageImp(pArguments, true); -} - -void CScript_LayoutPseudoModel::PageImp(CFXJSE_Arguments* pArguments, - bool bAbsPage) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - const FX_WCHAR* methodName; - if (bAbsPage) { - methodName = L"absPage"; - } else { - methodName = L"page"; - } - ThrowParamCountMismatchException(methodName); - return; - } - CXFA_Node* pNode = nullptr; - if (iLength >= 1) { - pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - } - int32_t iPage = 0; - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (!pNode && pValue) - pValue->SetInteger(iPage); - - CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout(); - if (!pDocLayout) { - return; - } - CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode); - if (!pLayoutItem) { - pValue->SetInteger(-1); - return; - } - iPage = pLayoutItem->GetFirst()->GetPage()->GetPageIndex(); - if (pValue) - pValue->SetInteger(bAbsPage ? iPage : iPage + 1); -} - -void CScript_LayoutPseudoModel::ThrowSetReadyException() const { - ThrowException(L"Unable to set ready value."); -} diff --git a/xfa/fxfa/parser/cscript_layoutpseudomodel.h b/xfa/fxfa/parser/cscript_layoutpseudomodel.h index 55a00db14aecfb1f7d1e90dcd852754920da6780..d76013a06c1331de1122c820a49f5daf4059a734 100644 --- a/xfa/fxfa/parser/cscript_layoutpseudomodel.h +++ b/xfa/fxfa/parser/cscript_layoutpseudomodel.h @@ -7,15 +7,8 @@ #ifndef XFA_FXFA_PARSER_CSCRIPT_LAYOUTPSEUDOMODEL_H_ #define XFA_FXFA_PARSER_CSCRIPT_LAYOUTPSEUDOMODEL_H_ -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/xfa_object.h" - -enum XFA_LAYOUTMODEL_HWXY { - XFA_LAYOUTMODEL_H, - XFA_LAYOUTMODEL_W, - XFA_LAYOUTMODEL_X, - XFA_LAYOUTMODEL_Y -}; +#include "fxjs/xfa/cjx_layoutpseudomodel.h" +#include "xfa/fxfa/parser/cxfa_object.h" class CXFA_LayoutProcessor; @@ -24,40 +17,9 @@ class CScript_LayoutPseudoModel : public CXFA_Object { explicit CScript_LayoutPseudoModel(CXFA_Document* pDocument); ~CScript_LayoutPseudoModel() override; - void Ready(CFXJSE_Value* pValue, bool bSetting, XFA_ATTRIBUTE eAttribute); - - void HWXY(CFXJSE_Arguments* pArguments, XFA_LAYOUTMODEL_HWXY layoutModel); - void H(CFXJSE_Arguments* pArguments); - void W(CFXJSE_Arguments* pArguments); - void X(CFXJSE_Arguments* pArguments); - void Y(CFXJSE_Arguments* pArguments); - void NumberedPageCount(CFXJSE_Arguments* pArguments, bool bNumbered); - void PageCount(CFXJSE_Arguments* pArguments); - void PageSpan(CFXJSE_Arguments* pArguments); - void Page(CFXJSE_Arguments* pArguments); - void PageContent(CFXJSE_Arguments* pArguments); - void AbsPageCount(CFXJSE_Arguments* pArguments); - void AbsPageCountInBatch(CFXJSE_Arguments* pArguments); - void SheetCountInBatch(CFXJSE_Arguments* pArguments); - void Relayout(CFXJSE_Arguments* pArguments); - void AbsPageSpan(CFXJSE_Arguments* pArguments); - void AbsPageInBatch(CFXJSE_Arguments* pArguments); - void SheetInBatch(CFXJSE_Arguments* pArguments); - void Sheet(CFXJSE_Arguments* pArguments); - void RelayoutPageArea(CFXJSE_Arguments* pArguments); - void SheetCount(CFXJSE_Arguments* pArguments); - void AbsPage(CFXJSE_Arguments* pArguments); - - protected: - void GetObjArray(CXFA_LayoutProcessor* pDocLayout, - int32_t iPageNo, - const CFX_WideString& wsType, - bool bOnPageArea, - CXFA_NodeArray& retArray); - void PageImp(CFXJSE_Arguments* pArguments, bool bAbsPage); - - private: - void ThrowSetReadyException() const; + CJX_LayoutPseudoModel* JSLayoutPseudoModel() { + return static_cast<CJX_LayoutPseudoModel*>(JSObject()); + } }; #endif // XFA_FXFA_PARSER_CSCRIPT_LAYOUTPSEUDOMODEL_H_ diff --git a/xfa/fxfa/parser/cscript_logpseudomodel.cpp b/xfa/fxfa/parser/cscript_logpseudomodel.cpp index 48ccce027faaee50e982bb0c36fec13d872352b8..1c2d80204c12ae8fd4adae51cf51281a9e0527ae 100644 --- a/xfa/fxfa/parser/cscript_logpseudomodel.cpp +++ b/xfa/fxfa/parser/cscript_logpseudomodel.cpp @@ -6,26 +6,13 @@ #include "xfa/fxfa/parser/cscript_logpseudomodel.h" -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" +#include "third_party/base/ptr_util.h" CScript_LogPseudoModel::CScript_LogPseudoModel(CXFA_Document* pDocument) : CXFA_Object(pDocument, XFA_ObjectType::Object, XFA_Element::LogPseudoModel, - CFX_WideStringC(L"logPseudoModel")) {} + WideStringView(L"logPseudoModel"), + pdfium::MakeUnique<CJX_LogPseudoModel>(this)) {} CScript_LogPseudoModel::~CScript_LogPseudoModel() {} - -void CScript_LogPseudoModel::Message(CFXJSE_Arguments* pArguments) {} - -void CScript_LogPseudoModel::TraceEnabled(CFXJSE_Arguments* pArguments) {} - -void CScript_LogPseudoModel::TraceActivate(CFXJSE_Arguments* pArguments) {} - -void CScript_LogPseudoModel::TraceDeactivate(CFXJSE_Arguments* pArguments) {} - -void CScript_LogPseudoModel::Trace(CFXJSE_Arguments* pArguments) {} diff --git a/xfa/fxfa/parser/cscript_logpseudomodel.h b/xfa/fxfa/parser/cscript_logpseudomodel.h index 18f9f51ae7a13081bfd0ce7d23252ee482ad79ca..9344f203b348b4bc427cf23dae19d7b0acc5543b 100644 --- a/xfa/fxfa/parser/cscript_logpseudomodel.h +++ b/xfa/fxfa/parser/cscript_logpseudomodel.h @@ -7,19 +7,17 @@ #ifndef XFA_FXFA_PARSER_CSCRIPT_LOGPSEUDOMODEL_H_ #define XFA_FXFA_PARSER_CSCRIPT_LOGPSEUDOMODEL_H_ -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_logpseudomodel.h" +#include "xfa/fxfa/parser/cxfa_object.h" class CScript_LogPseudoModel : public CXFA_Object { public: explicit CScript_LogPseudoModel(CXFA_Document* pDocument); ~CScript_LogPseudoModel() override; - void Message(CFXJSE_Arguments* pArguments); - void TraceEnabled(CFXJSE_Arguments* pArguments); - void TraceActivate(CFXJSE_Arguments* pArguments); - void TraceDeactivate(CFXJSE_Arguments* pArguments); - void Trace(CFXJSE_Arguments* pArguments); + CJX_LogPseudoModel* JSLogPseudoModel() { + return static_cast<CJX_LogPseudoModel*>(JSObject()); + } }; #endif // XFA_FXFA_PARSER_CSCRIPT_LOGPSEUDOMODEL_H_ diff --git a/xfa/fxfa/parser/cscript_signaturepseudomodel.cpp b/xfa/fxfa/parser/cscript_signaturepseudomodel.cpp index e5874a61cc652f1d251660333336fce29be917f1..c5f4e6425f02ed6168ba9d840fd6eef07d728093 100644 --- a/xfa/fxfa/parser/cscript_signaturepseudomodel.cpp +++ b/xfa/fxfa/parser/cscript_signaturepseudomodel.cpp @@ -6,63 +6,14 @@ #include "xfa/fxfa/parser/cscript_signaturepseudomodel.h" -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" +#include "third_party/base/ptr_util.h" CScript_SignaturePseudoModel::CScript_SignaturePseudoModel( CXFA_Document* pDocument) : CXFA_Object(pDocument, XFA_ObjectType::Object, XFA_Element::SignaturePseudoModel, - CFX_WideStringC(L"signaturePseudoModel")) {} + WideStringView(L"signaturePseudoModel"), + pdfium::MakeUnique<CJX_SignaturePseudoModel>(this)) {} CScript_SignaturePseudoModel::~CScript_SignaturePseudoModel() {} - -void CScript_SignaturePseudoModel::Verify(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 4) { - ThrowParamCountMismatchException(L"verify"); - return; - } - - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetInteger(0); -} - -void CScript_SignaturePseudoModel::Sign(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 3 || iLength > 7) { - ThrowParamCountMismatchException(L"sign"); - return; - } - - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetBoolean(false); -} - -void CScript_SignaturePseudoModel::Enumerate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"enumerate"); - return; - } - return; -} - -void CScript_SignaturePseudoModel::Clear(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 2) { - ThrowParamCountMismatchException(L"clear"); - return; - } - - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetBoolean(false); -} diff --git a/xfa/fxfa/parser/cscript_signaturepseudomodel.h b/xfa/fxfa/parser/cscript_signaturepseudomodel.h index 4f9ded06632fea1aad88eca0a906c2365b0d52f6..276c1df4ab43f9db4a954ff8ae0e32a3e7996eeb 100644 --- a/xfa/fxfa/parser/cscript_signaturepseudomodel.h +++ b/xfa/fxfa/parser/cscript_signaturepseudomodel.h @@ -7,18 +7,17 @@ #ifndef XFA_FXFA_PARSER_CSCRIPT_SIGNATUREPSEUDOMODEL_H_ #define XFA_FXFA_PARSER_CSCRIPT_SIGNATUREPSEUDOMODEL_H_ -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_signaturepseudomodel.h" +#include "xfa/fxfa/parser/cxfa_object.h" class CScript_SignaturePseudoModel : public CXFA_Object { public: explicit CScript_SignaturePseudoModel(CXFA_Document* pDocument); ~CScript_SignaturePseudoModel() override; - void Verify(CFXJSE_Arguments* pArguments); - void Sign(CFXJSE_Arguments* pArguments); - void Enumerate(CFXJSE_Arguments* pArguments); - void Clear(CFXJSE_Arguments* pArguments); + CJX_SignaturePseudoModel* JSSignaturePseudoModel() { + return static_cast<CJX_SignaturePseudoModel*>(JSObject()); + } }; #endif // XFA_FXFA_PARSER_CSCRIPT_SIGNATUREPSEUDOMODEL_H_ diff --git a/xfa/fxfa/parser/cxfa_accessiblecontent.cpp b/xfa/fxfa/parser/cxfa_accessiblecontent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a246159951539f7ac824d4af6a15ec713935ed8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_accessiblecontent.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_accessiblecontent.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"accessibleContent"; + +} // namespace + +CXFA_AccessibleContent::CXFA_AccessibleContent(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::AccessibleContent, + nullptr, + kAttributeData, + kName) {} + +CXFA_AccessibleContent::~CXFA_AccessibleContent() {} diff --git a/xfa/fxfa/parser/cxfa_accessiblecontent.h b/xfa/fxfa/parser/cxfa_accessiblecontent.h new file mode 100644 index 0000000000000000000000000000000000000000..84ad8fca52ebb29a96024e4cccc525c386abcd4f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_accessiblecontent.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ACCESSIBLECONTENT_H_ +#define XFA_FXFA_PARSER_CXFA_ACCESSIBLECONTENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AccessibleContent : public CXFA_Node { + public: + CXFA_AccessibleContent(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AccessibleContent() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ACCESSIBLECONTENT_H_ diff --git a/xfa/fxfa/parser/cxfa_acrobat.cpp b/xfa/fxfa/parser/cxfa_acrobat.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2327c0834ab5f71d1efb1e0a4393d321294cf11e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_acrobat.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_acrobat.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::AutoSave, 1, 0}, + {XFA_Element::Validate, 1, 0}, + {XFA_Element::ValidateApprovalSignatures, 1, 0}, + {XFA_Element::Acrobat7, 1, 0}, + {XFA_Element::Common, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"acrobat"; + +} // namespace + +CXFA_Acrobat::CXFA_Acrobat(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Acrobat, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Acrobat::~CXFA_Acrobat() {} diff --git a/xfa/fxfa/parser/cxfa_acrobat.h b/xfa/fxfa/parser/cxfa_acrobat.h new file mode 100644 index 0000000000000000000000000000000000000000..3701d591e7b0fc0baf666ab89c068b8343e4d562 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_acrobat.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ACROBAT_H_ +#define XFA_FXFA_PARSER_CXFA_ACROBAT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Acrobat : public CXFA_Node { + public: + CXFA_Acrobat(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Acrobat() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ACROBAT_H_ diff --git a/xfa/fxfa/parser/cxfa_acrobat7.cpp b/xfa/fxfa/parser/cxfa_acrobat7.cpp new file mode 100644 index 0000000000000000000000000000000000000000..089ab605fc89dfda015ab5ff51a73ac9111d590b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_acrobat7.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_acrobat7.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::DynamicRender, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"acrobat7"; + +} // namespace + +CXFA_Acrobat7::CXFA_Acrobat7(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Acrobat7, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Acrobat7::~CXFA_Acrobat7() {} diff --git a/xfa/fxfa/parser/cxfa_acrobat7.h b/xfa/fxfa/parser/cxfa_acrobat7.h new file mode 100644 index 0000000000000000000000000000000000000000..579864ac1b862cad02e5f646f866d7409bdda28d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_acrobat7.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ACROBAT7_H_ +#define XFA_FXFA_PARSER_CXFA_ACROBAT7_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Acrobat7 : public CXFA_Node { + public: + CXFA_Acrobat7(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Acrobat7() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ACROBAT7_H_ diff --git a/xfa/fxfa/parser/cxfa_adbe_jsconsole.cpp b/xfa/fxfa/parser/cxfa_adbe_jsconsole.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af33636383fb3d75d3a06f7d33993136f746cbad --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adbe_jsconsole.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_adbe_jsconsole.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"ADBE_JSConsole"; + +} // namespace + +CXFA_aDBE_JSConsole::CXFA_aDBE_JSConsole(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::ADBE_JSConsole, + nullptr, + kAttributeData, + kName) {} + +CXFA_aDBE_JSConsole::~CXFA_aDBE_JSConsole() {} diff --git a/xfa/fxfa/parser/cxfa_adbe_jsconsole.h b/xfa/fxfa/parser/cxfa_adbe_jsconsole.h new file mode 100644 index 0000000000000000000000000000000000000000..9fab6a11db7101abc6d68bea92ce79988331a796 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adbe_jsconsole.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ADBE_JSCONSOLE_H_ +#define XFA_FXFA_PARSER_CXFA_ADBE_JSCONSOLE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_aDBE_JSConsole : public CXFA_Node { + public: + CXFA_aDBE_JSConsole(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_aDBE_JSConsole() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ADBE_JSCONSOLE_H_ diff --git a/xfa/fxfa/parser/cxfa_adbe_jsdebugger.cpp b/xfa/fxfa/parser/cxfa_adbe_jsdebugger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bcb62ebe1d0160981f8391dafa93ab6c25f6f9c4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adbe_jsdebugger.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_adbe_jsdebugger.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"ADBE_JSDebugger"; + +} // namespace + +CXFA_aDBE_JSDebugger::CXFA_aDBE_JSDebugger(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::ADBE_JSDebugger, + nullptr, + kAttributeData, + kName) {} + +CXFA_aDBE_JSDebugger::~CXFA_aDBE_JSDebugger() {} diff --git a/xfa/fxfa/parser/cxfa_adbe_jsdebugger.h b/xfa/fxfa/parser/cxfa_adbe_jsdebugger.h new file mode 100644 index 0000000000000000000000000000000000000000..ed821d4d0d1b135fd6b56a8123ad4144e34cd4a2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adbe_jsdebugger.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ADBE_JSDEBUGGER_H_ +#define XFA_FXFA_PARSER_CXFA_ADBE_JSDEBUGGER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_aDBE_JSDebugger : public CXFA_Node { + public: + CXFA_aDBE_JSDebugger(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_aDBE_JSDebugger() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ADBE_JSDEBUGGER_H_ diff --git a/xfa/fxfa/parser/cxfa_addsilentprint.cpp b/xfa/fxfa/parser/cxfa_addsilentprint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13f7f83e8862303dc813e2a3f6972cbe00cecaf5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_addsilentprint.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_addsilentprint.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"addSilentPrint"; + +} // namespace + +CXFA_AddSilentPrint::CXFA_AddSilentPrint(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::AddSilentPrint, + nullptr, + kAttributeData, + kName) {} + +CXFA_AddSilentPrint::~CXFA_AddSilentPrint() {} diff --git a/xfa/fxfa/parser/cxfa_addsilentprint.h b/xfa/fxfa/parser/cxfa_addsilentprint.h new file mode 100644 index 0000000000000000000000000000000000000000..a2519692da5644b394083ee2604577f8ed14b597 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_addsilentprint.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ADDSILENTPRINT_H_ +#define XFA_FXFA_PARSER_CXFA_ADDSILENTPRINT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AddSilentPrint : public CXFA_Node { + public: + CXFA_AddSilentPrint(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AddSilentPrint() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ADDSILENTPRINT_H_ diff --git a/xfa/fxfa/parser/cxfa_addviewerpreferences.cpp b/xfa/fxfa/parser/cxfa_addviewerpreferences.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e3d06056d23d7c1bb3630c493841284cb55c7d6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_addviewerpreferences.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_addviewerpreferences.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"addViewerPreferences"; + +} // namespace + +CXFA_AddViewerPreferences::CXFA_AddViewerPreferences(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::AddViewerPreferences, + nullptr, + kAttributeData, + kName) {} + +CXFA_AddViewerPreferences::~CXFA_AddViewerPreferences() {} diff --git a/xfa/fxfa/parser/cxfa_addviewerpreferences.h b/xfa/fxfa/parser/cxfa_addviewerpreferences.h new file mode 100644 index 0000000000000000000000000000000000000000..cf10868b0cb3bcbf58abbfb1fbe05cd8da39cb59 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_addviewerpreferences.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ADDVIEWERPREFERENCES_H_ +#define XFA_FXFA_PARSER_CXFA_ADDVIEWERPREFERENCES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AddViewerPreferences : public CXFA_Node { + public: + CXFA_AddViewerPreferences(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AddViewerPreferences() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ADDVIEWERPREFERENCES_H_ diff --git a/xfa/fxfa/parser/cxfa_adjustdata.cpp b/xfa/fxfa/parser/cxfa_adjustdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60a4f2c5bd53d2edcb84cb93e56bfd77e836d21e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adjustdata.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_adjustdata.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"adjustData"; + +} // namespace + +CXFA_AdjustData::CXFA_AdjustData(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::AdjustData, + nullptr, + kAttributeData, + kName) {} + +CXFA_AdjustData::~CXFA_AdjustData() {} diff --git a/xfa/fxfa/parser/cxfa_adjustdata.h b/xfa/fxfa/parser/cxfa_adjustdata.h new file mode 100644 index 0000000000000000000000000000000000000000..3c004c2a6ab0b2cc90a5212f1820b06000bbb30e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adjustdata.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ADJUSTDATA_H_ +#define XFA_FXFA_PARSER_CXFA_ADJUSTDATA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AdjustData : public CXFA_Node { + public: + CXFA_AdjustData(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AdjustData() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ADJUSTDATA_H_ diff --git a/xfa/fxfa/parser/cxfa_adobeextensionlevel.cpp b/xfa/fxfa/parser/cxfa_adobeextensionlevel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d253f8b1644990ccb937f247ae59e6ebfa7ed7df --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adobeextensionlevel.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_adobeextensionlevel.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"adobeExtensionLevel"; + +} // namespace + +CXFA_AdobeExtensionLevel::CXFA_AdobeExtensionLevel(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::AdobeExtensionLevel, + nullptr, + kAttributeData, + kName) {} + +CXFA_AdobeExtensionLevel::~CXFA_AdobeExtensionLevel() {} diff --git a/xfa/fxfa/parser/cxfa_adobeextensionlevel.h b/xfa/fxfa/parser/cxfa_adobeextensionlevel.h new file mode 100644 index 0000000000000000000000000000000000000000..91a830f2519b8f5a9df2b668a70186ca37ef93a9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_adobeextensionlevel.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ADOBEEXTENSIONLEVEL_H_ +#define XFA_FXFA_PARSER_CXFA_ADOBEEXTENSIONLEVEL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AdobeExtensionLevel : public CXFA_Node { + public: + CXFA_AdobeExtensionLevel(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AdobeExtensionLevel() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ADOBEEXTENSIONLEVEL_H_ diff --git a/xfa/fxfa/parser/cxfa_agent.cpp b/xfa/fxfa/parser/cxfa_agent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..468b93895ff12a4239ac9a39e133ec40c3abc3ce --- /dev/null +++ b/xfa/fxfa/parser/cxfa_agent.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_agent.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"agent"; + +} // namespace + +CXFA_Agent::CXFA_Agent(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Agent, + nullptr, + kAttributeData, + kName) {} + +CXFA_Agent::~CXFA_Agent() {} diff --git a/xfa/fxfa/parser/cxfa_agent.h b/xfa/fxfa/parser/cxfa_agent.h new file mode 100644 index 0000000000000000000000000000000000000000..65d826d0ce9aa83b33f17ab7dfc58ec6846790ff --- /dev/null +++ b/xfa/fxfa/parser/cxfa_agent.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_AGENT_H_ +#define XFA_FXFA_PARSER_CXFA_AGENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Agent : public CXFA_Node { + public: + CXFA_Agent(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Agent() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_AGENT_H_ diff --git a/xfa/fxfa/parser/cxfa_alwaysembed.cpp b/xfa/fxfa/parser/cxfa_alwaysembed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13f97177b987f52f8b530b0f6f99a97a7c146a87 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_alwaysembed.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_alwaysembed.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"alwaysEmbed"; + +} // namespace + +CXFA_AlwaysEmbed::CXFA_AlwaysEmbed(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::AlwaysEmbed, + nullptr, + kAttributeData, + kName) {} + +CXFA_AlwaysEmbed::~CXFA_AlwaysEmbed() {} diff --git a/xfa/fxfa/parser/cxfa_alwaysembed.h b/xfa/fxfa/parser/cxfa_alwaysembed.h new file mode 100644 index 0000000000000000000000000000000000000000..178097647b533125c9399c19f59d2c0b13c39e15 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_alwaysembed.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ALWAYSEMBED_H_ +#define XFA_FXFA_PARSER_CXFA_ALWAYSEMBED_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AlwaysEmbed : public CXFA_Node { + public: + CXFA_AlwaysEmbed(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AlwaysEmbed() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ALWAYSEMBED_H_ diff --git a/xfa/fxfa/parser/cxfa_amd.cpp b/xfa/fxfa/parser/cxfa_amd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7580304d58c28508691566698685f308d96d4b40 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_amd.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_amd.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"amd"; + +} // namespace + +CXFA_Amd::CXFA_Amd(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Amd, + nullptr, + kAttributeData, + kName) {} + +CXFA_Amd::~CXFA_Amd() {} diff --git a/xfa/fxfa/parser/cxfa_amd.h b/xfa/fxfa/parser/cxfa_amd.h new file mode 100644 index 0000000000000000000000000000000000000000..951c6ca186f232f881a0b277bef5c4c3ae688efd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_amd.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_AMD_H_ +#define XFA_FXFA_PARSER_CXFA_AMD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Amd : public CXFA_Node { + public: + CXFA_Amd(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Amd() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_AMD_H_ diff --git a/xfa/fxfa/parser/cxfa_appearancefilter.cpp b/xfa/fxfa/parser/cxfa_appearancefilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b3e9fb8d51989ae2f74c6ea15358db2df664088 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_appearancefilter.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_appearancefilter.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"appearanceFilter"; + +} // namespace + +CXFA_AppearanceFilter::CXFA_AppearanceFilter(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeC, + XFA_Element::AppearanceFilter, + nullptr, + kAttributeData, + kName) {} + +CXFA_AppearanceFilter::~CXFA_AppearanceFilter() {} diff --git a/xfa/fxfa/parser/cxfa_appearancefilter.h b/xfa/fxfa/parser/cxfa_appearancefilter.h new file mode 100644 index 0000000000000000000000000000000000000000..341232ef282859eec43cecce558b272bfcfa1a2d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_appearancefilter.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_APPEARANCEFILTER_H_ +#define XFA_FXFA_PARSER_CXFA_APPEARANCEFILTER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AppearanceFilter : public CXFA_Node { + public: + CXFA_AppearanceFilter(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AppearanceFilter() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_APPEARANCEFILTER_H_ diff --git a/xfa/fxfa/parser/cxfa_arc.cpp b/xfa/fxfa/parser/cxfa_arc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fb89a5b40e99e039be4654c1d6d3ea0b30c229e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_arc.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_arc.h" + +#include "fxjs/xfa/cjx_arc.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Edge, 1, 0}, + {XFA_Element::Fill, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::StartAngle, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::SweepAngle, XFA_AttributeType::Integer, (void*)360}, + {XFA_Attribute::Circular, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Hand, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Even}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"arc"; + +} // namespace + +CXFA_Arc::CXFA_Arc(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Box(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Arc, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Arc>(this)) {} + +CXFA_Arc::~CXFA_Arc() {} diff --git a/xfa/fxfa/parser/cxfa_arc.h b/xfa/fxfa/parser/cxfa_arc.h index e712d806a724ee316a8bd75b6cbb8484e8218962..fd903aa2491755d02327534a0c0ddc287d6ba8fe 100644 --- a/xfa/fxfa/parser/cxfa_arc.h +++ b/xfa/fxfa/parser/cxfa_arc.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,11 +9,10 @@ #include "xfa/fxfa/parser/cxfa_box.h" -class CXFA_Node; - class CXFA_Arc : public CXFA_Box { public: - explicit CXFA_Arc(CXFA_Node* pNode) : CXFA_Box(pNode) {} + CXFA_Arc(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Arc() override; }; #endif // XFA_FXFA_PARSER_CXFA_ARC_H_ diff --git a/xfa/fxfa/parser/cxfa_area.cpp b/xfa/fxfa/parser/cxfa_area.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7fd8aa6898cb800db5ffd720e21c49c5643eb4ba --- /dev/null +++ b/xfa/fxfa/parser/cxfa_area.cpp @@ -0,0 +1,46 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_area.h" + +#include "fxjs/xfa/cjx_area.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Desc, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Level, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ColSpan, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"area"; + +} // namespace + +CXFA_Area::CXFA_Area(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::Area, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Area>(this)) {} + +CXFA_Area::~CXFA_Area() {} diff --git a/xfa/fxfa/parser/cxfa_area.h b/xfa/fxfa/parser/cxfa_area.h new file mode 100644 index 0000000000000000000000000000000000000000..6568e73530543cbd596d9cc0aae8e147da79fd30 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_area.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_AREA_H_ +#define XFA_FXFA_PARSER_CXFA_AREA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Area : public CXFA_Node { + public: + CXFA_Area(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Area() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_AREA_H_ diff --git a/xfa/fxfa/parser/cxfa_arraynodelist.cpp b/xfa/fxfa/parser/cxfa_arraynodelist.cpp index 8c9040a12140d5542c277d52606ea95171f35e2f..9eaf9a6c33ea747d92de0b0ebb485c74b4b765bb 100644 --- a/xfa/fxfa/parser/cxfa_arraynodelist.cpp +++ b/xfa/fxfa/parser/cxfa_arraynodelist.cpp @@ -4,58 +4,50 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" + +#include <vector> + +#include "third_party/base/stl_util.h" CXFA_ArrayNodeList::CXFA_ArrayNodeList(CXFA_Document* pDocument) - : CXFA_NodeList(pDocument) {} + : CXFA_TreeList(pDocument) {} CXFA_ArrayNodeList::~CXFA_ArrayNodeList() {} -void CXFA_ArrayNodeList::SetArrayNodeList(const CXFA_NodeArray& srcArray) { - if (srcArray.GetSize() > 0) { - m_array.Copy(srcArray); - } +void CXFA_ArrayNodeList::SetArrayNodeList( + const std::vector<CXFA_Node*>& srcArray) { + if (!srcArray.empty()) + m_array = srcArray; } -int32_t CXFA_ArrayNodeList::GetLength() { - return m_array.GetSize(); +size_t CXFA_ArrayNodeList::GetLength() { + return m_array.size(); } bool CXFA_ArrayNodeList::Append(CXFA_Node* pNode) { - m_array.Add(pNode); + m_array.push_back(pNode); return true; } bool CXFA_ArrayNodeList::Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) { if (!pBeforeNode) { - m_array.Add(pNewNode); + m_array.push_back(pNewNode); } else { - int32_t iSize = m_array.GetSize(); - for (int32_t i = 0; i < iSize; ++i) { - if (m_array[i] == pBeforeNode) { - m_array.InsertAt(i, pNewNode); - break; - } - } + auto it = std::find(m_array.begin(), m_array.end(), pBeforeNode); + if (it != m_array.end()) + m_array.insert(it, pNewNode); } return true; } bool CXFA_ArrayNodeList::Remove(CXFA_Node* pNode) { - int32_t iSize = m_array.GetSize(); - for (int32_t i = 0; i < iSize; ++i) { - if (m_array[i] == pNode) { - m_array.RemoveAt(i); - break; - } - } + auto it = std::find(m_array.begin(), m_array.end(), pNode); + if (it != m_array.end()) + m_array.erase(it); return true; } -CXFA_Node* CXFA_ArrayNodeList::Item(int32_t iIndex) { - int32_t iSize = m_array.GetSize(); - if (iIndex >= 0 && iIndex < iSize) { - return m_array[iIndex]; - } - return nullptr; +CXFA_Node* CXFA_ArrayNodeList::Item(size_t index) { + return index < m_array.size() ? m_array[index] : nullptr; } diff --git a/xfa/fxfa/parser/cxfa_arraynodelist.h b/xfa/fxfa/parser/cxfa_arraynodelist.h new file mode 100644 index 0000000000000000000000000000000000000000..346b206f202e2f737dbcfb06e8186db52a98d718 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_arraynodelist.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ARRAYNODELIST_H_ +#define XFA_FXFA_PARSER_CXFA_ARRAYNODELIST_H_ + +#include <vector> + +#include "xfa/fxfa/parser/cxfa_treelist.h" + +class CXFA_Document; +class CXFA_Node; + +class CXFA_ArrayNodeList : public CXFA_TreeList { + public: + explicit CXFA_ArrayNodeList(CXFA_Document* pDocument); + ~CXFA_ArrayNodeList() override; + + // From CXFA_TreeList. + size_t GetLength() override; + bool Append(CXFA_Node* pNode) override; + bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override; + bool Remove(CXFA_Node* pNode) override; + CXFA_Node* Item(size_t iIndex) override; + + void SetArrayNodeList(const std::vector<CXFA_Node*>& srcArray); + + private: + std::vector<CXFA_Node*> m_array; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ARRAYNODELIST_H_ diff --git a/xfa/fxfa/parser/cxfa_assist.cpp b/xfa/fxfa/parser/cxfa_assist.cpp index 894e729d6d2e03dc8073379ffa7166c90e3bd371..4286211e0fa3ebdd4ac544b2b438efcbc7ab7998 100644 --- a/xfa/fxfa/parser/cxfa_assist.cpp +++ b/xfa/fxfa/parser/cxfa_assist.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,10 +6,34 @@ #include "xfa/fxfa/parser/cxfa_assist.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_assist.h" +#include "third_party/base/ptr_util.h" -CXFA_Assist::CXFA_Assist(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -CXFA_ToolTip CXFA_Assist::GetToolTip() { - return CXFA_ToolTip(m_pNode->GetChild(0, XFA_Element::ToolTip)); -} +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::ToolTip, 1, 0}, + {XFA_Element::Speak, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Role, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"assist"; + +} // namespace + +CXFA_Assist::CXFA_Assist(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Assist, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Assist>(this)) {} + +CXFA_Assist::~CXFA_Assist() {} diff --git a/xfa/fxfa/parser/cxfa_assist.h b/xfa/fxfa/parser/cxfa_assist.h index c583ff59d520809286aec126acf7dc8ca4d58832..d0e9020a7efdbcc14b326b40d320f0e19ba86eb0 100644 --- a/xfa/fxfa/parser/cxfa_assist.h +++ b/xfa/fxfa/parser/cxfa_assist.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,16 +7,12 @@ #ifndef XFA_FXFA_PARSER_CXFA_ASSIST_H_ #define XFA_FXFA_PARSER_CXFA_ASSIST_H_ -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_tooltip.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Assist : public CXFA_Data { +class CXFA_Assist : public CXFA_Node { public: - explicit CXFA_Assist(CXFA_Node* pNode); - - CXFA_ToolTip GetToolTip(); + CXFA_Assist(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Assist() override; }; #endif // XFA_FXFA_PARSER_CXFA_ASSIST_H_ diff --git a/xfa/fxfa/parser/cxfa_attachnodelist.cpp b/xfa/fxfa/parser/cxfa_attachnodelist.cpp index c23b900af69a76322dcf5f66ddc795ca040b4a0e..f1fbfa784b9d2e95e9bed2b723ee0996f7c51bd6 100644 --- a/xfa/fxfa/parser/cxfa_attachnodelist.cpp +++ b/xfa/fxfa/parser/cxfa_attachnodelist.cpp @@ -4,42 +4,45 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_attachnodelist.h" + +#include "third_party/base/numerics/safe_conversions.h" +#include "xfa/fxfa/parser/cxfa_node.h" CXFA_AttachNodeList::CXFA_AttachNodeList(CXFA_Document* pDocument, CXFA_Node* pAttachNode) - : CXFA_NodeList(pDocument) { + : CXFA_TreeList(pDocument) { m_pAttachNode = pAttachNode; } -int32_t CXFA_AttachNodeList::GetLength() { +size_t CXFA_AttachNodeList::GetLength() { return m_pAttachNode->CountChildren( XFA_Element::Unknown, m_pAttachNode->GetElementType() == XFA_Element::Subform); } bool CXFA_AttachNodeList::Append(CXFA_Node* pNode) { - CXFA_Node* pParent = pNode->GetNodeItem(XFA_NODEITEM_Parent); - if (pParent) { - pParent->RemoveChild(pNode); - } - return m_pAttachNode->InsertChild(pNode); + CXFA_Node* pParent = pNode->GetParent(); + if (pParent) + pParent->RemoveChild(pNode, true); + + return m_pAttachNode->InsertChild(pNode, nullptr); } bool CXFA_AttachNodeList::Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) { - CXFA_Node* pParent = pNewNode->GetNodeItem(XFA_NODEITEM_Parent); - if (pParent) { - pParent->RemoveChild(pNewNode); - } + CXFA_Node* pParent = pNewNode->GetParent(); + if (pParent) + pParent->RemoveChild(pNewNode, true); + return m_pAttachNode->InsertChild(pNewNode, pBeforeNode); } bool CXFA_AttachNodeList::Remove(CXFA_Node* pNode) { - return m_pAttachNode->RemoveChild(pNode); + return m_pAttachNode->RemoveChild(pNode, true); } -CXFA_Node* CXFA_AttachNodeList::Item(int32_t iIndex) { - return m_pAttachNode->GetChild( - iIndex, XFA_Element::Unknown, +CXFA_Node* CXFA_AttachNodeList::Item(size_t index) { + return m_pAttachNode->GetChild<CXFA_Node>( + index, XFA_Element::Unknown, m_pAttachNode->GetElementType() == XFA_Element::Subform); } diff --git a/xfa/fxfa/parser/cxfa_attachnodelist.h b/xfa/fxfa/parser/cxfa_attachnodelist.h new file mode 100644 index 0000000000000000000000000000000000000000..f0df2bb4d896791d59401c5c13fc5c2639770f51 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_attachnodelist.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ATTACHNODELIST_H_ +#define XFA_FXFA_PARSER_CXFA_ATTACHNODELIST_H_ + +#include "xfa/fxfa/parser/cxfa_treelist.h" + +class CXFA_Document; +class CXFA_Node; + +class CXFA_AttachNodeList : public CXFA_TreeList { + public: + CXFA_AttachNodeList(CXFA_Document* pDocument, CXFA_Node* pAttachNode); + + // From CXFA_TreeList. + size_t GetLength() override; + bool Append(CXFA_Node* pNode) override; + bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override; + bool Remove(CXFA_Node* pNode) override; + CXFA_Node* Item(size_t iIndex) override; + + private: + CXFA_Node* m_pAttachNode; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ATTACHNODELIST_H_ diff --git a/xfa/fxfa/parser/cxfa_attributes.cpp b/xfa/fxfa/parser/cxfa_attributes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80e58bd694a2db9b5e499ae452c9bab7889691b8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_attributes.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_attributes.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"attributes"; + +} // namespace + +CXFA_Attributes::CXFA_Attributes(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Attributes, + nullptr, + kAttributeData, + kName) {} + +CXFA_Attributes::~CXFA_Attributes() {} diff --git a/xfa/fxfa/parser/cxfa_attributes.h b/xfa/fxfa/parser/cxfa_attributes.h new file mode 100644 index 0000000000000000000000000000000000000000..fd73da87cf779dd960049467dcf5f36aace84832 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_attributes.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ATTRIBUTES_H_ +#define XFA_FXFA_PARSER_CXFA_ATTRIBUTES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Attributes : public CXFA_Node { + public: + CXFA_Attributes(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Attributes() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ATTRIBUTES_H_ diff --git a/xfa/fxfa/parser/cxfa_autosave.cpp b/xfa/fxfa/parser/cxfa_autosave.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d77c25210d2d70ce933e395712b8ad45f3efea55 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_autosave.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_autosave.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"autoSave"; + +} // namespace + +CXFA_AutoSave::CXFA_AutoSave(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::AutoSave, + nullptr, + kAttributeData, + kName) {} + +CXFA_AutoSave::~CXFA_AutoSave() {} diff --git a/xfa/fxfa/parser/cxfa_autosave.h b/xfa/fxfa/parser/cxfa_autosave.h new file mode 100644 index 0000000000000000000000000000000000000000..b58ccf14a5ba9204bd93ef3aeb2023fe6f423508 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_autosave.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_AUTOSAVE_H_ +#define XFA_FXFA_PARSER_CXFA_AUTOSAVE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_AutoSave : public CXFA_Node { + public: + CXFA_AutoSave(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_AutoSave() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_AUTOSAVE_H_ diff --git a/xfa/fxfa/parser/cxfa_barcode.cpp b/xfa/fxfa/parser/cxfa_barcode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d69229193e88a4967d9ad96050d0af2154385059 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_barcode.cpp @@ -0,0 +1,57 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_barcode.h" + +#include "fxjs/xfa/cjx_barcode.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataRowCount, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataPrep, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Type, XFA_AttributeType::CData, (void*)nullptr}, + {XFA_Attribute::TextLocation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Below}, + {XFA_Attribute::ModuleWidth, XFA_AttributeType::Measure, (void*)L"0.25mm"}, + {XFA_Attribute::PrintCheckDigit, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::ModuleHeight, XFA_AttributeType::Measure, (void*)L"5mm"}, + {XFA_Attribute::StartChar, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Truncate, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::WideNarrowRatio, XFA_AttributeType::CData, (void*)L"3:1"}, + {XFA_Attribute::ErrorCorrectionLevel, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::UpsMode, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::UsCarrier}, + {XFA_Attribute::Checksum, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::CharEncoding, XFA_AttributeType::CData, (void*)L"UTF-8"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataColumnCount, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::RowColumnRatio, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataLength, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::EndChar, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"barcode"; + +} // namespace + +CXFA_Barcode::CXFA_Barcode(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Barcode, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Barcode>(this)) {} + +CXFA_Barcode::~CXFA_Barcode() {} diff --git a/xfa/fxfa/parser/cxfa_barcode.h b/xfa/fxfa/parser/cxfa_barcode.h new file mode 100644 index 0000000000000000000000000000000000000000..469889b99db965a349d2f5d2ec29d4cd2d9a8c05 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_barcode.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BARCODE_H_ +#define XFA_FXFA_PARSER_CXFA_BARCODE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Barcode : public CXFA_Node { + public: + CXFA_Barcode(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Barcode() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BARCODE_H_ diff --git a/xfa/fxfa/parser/cxfa_base.cpp b/xfa/fxfa/parser/cxfa_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a82a79a0952e1565844fd2438ec11d6a96357262 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_base.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_base.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"base"; + +} // namespace + +CXFA_Base::CXFA_Base(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Base, + nullptr, + kAttributeData, + kName) {} + +CXFA_Base::~CXFA_Base() {} diff --git a/xfa/fxfa/parser/cxfa_base.h b/xfa/fxfa/parser/cxfa_base.h new file mode 100644 index 0000000000000000000000000000000000000000..3974343a15e3c7eee7b44f0c974f373e8495c7eb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_base.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BASE_H_ +#define XFA_FXFA_PARSER_CXFA_BASE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Base : public CXFA_Node { + public: + CXFA_Base(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Base() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BASE_H_ diff --git a/xfa/fxfa/parser/cxfa_batchoutput.cpp b/xfa/fxfa/parser/cxfa_batchoutput.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1678d6a36ffbdbe9ff98115cbbfd8df14b965a3d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_batchoutput.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_batchoutput.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Format, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"batchOutput"; + +} // namespace + +CXFA_BatchOutput::CXFA_BatchOutput(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::BatchOutput, + nullptr, + kAttributeData, + kName) {} + +CXFA_BatchOutput::~CXFA_BatchOutput() {} diff --git a/xfa/fxfa/parser/cxfa_batchoutput.h b/xfa/fxfa/parser/cxfa_batchoutput.h new file mode 100644 index 0000000000000000000000000000000000000000..9faa6cfcca498a1fe0287bf26e87823c31aa0eac --- /dev/null +++ b/xfa/fxfa/parser/cxfa_batchoutput.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BATCHOUTPUT_H_ +#define XFA_FXFA_PARSER_CXFA_BATCHOUTPUT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_BatchOutput : public CXFA_Node { + public: + CXFA_BatchOutput(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_BatchOutput() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BATCHOUTPUT_H_ diff --git a/xfa/fxfa/parser/cxfa_behavioroverride.cpp b/xfa/fxfa/parser/cxfa_behavioroverride.cpp new file mode 100644 index 0000000000000000000000000000000000000000..addf8f1327e77e7f5291e1efc9f85dc0140d21e1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_behavioroverride.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_behavioroverride.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"behaviorOverride"; + +} // namespace + +CXFA_BehaviorOverride::CXFA_BehaviorOverride(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::BehaviorOverride, + nullptr, + kAttributeData, + kName) {} + +CXFA_BehaviorOverride::~CXFA_BehaviorOverride() {} diff --git a/xfa/fxfa/parser/cxfa_behavioroverride.h b/xfa/fxfa/parser/cxfa_behavioroverride.h new file mode 100644 index 0000000000000000000000000000000000000000..cb0821121142cabee8a564b2f1a0c19f5ba15ece --- /dev/null +++ b/xfa/fxfa/parser/cxfa_behavioroverride.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BEHAVIOROVERRIDE_H_ +#define XFA_FXFA_PARSER_CXFA_BEHAVIOROVERRIDE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_BehaviorOverride : public CXFA_Node { + public: + CXFA_BehaviorOverride(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_BehaviorOverride() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BEHAVIOROVERRIDE_H_ diff --git a/xfa/fxfa/parser/cxfa_bind.cpp b/xfa/fxfa/parser/cxfa_bind.cpp index 16efd1f440462ee65f269af0583517d8405403a9..d35a2cd24a5a6af8ddb8c6c8ef64038ba243742f 100644 --- a/xfa/fxfa/parser/cxfa_bind.cpp +++ b/xfa/fxfa/parser/cxfa_bind.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,11 +6,48 @@ #include "xfa/fxfa/parser/cxfa_bind.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_bind.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_picture.h" -CXFA_Bind::CXFA_Bind(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -void CXFA_Bind::GetPicture(CFX_WideString& wsPicture) { - if (CXFA_Node* pPicture = m_pNode->GetChild(0, XFA_Element::Picture)) - pPicture->TryContent(wsPicture); +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Picture, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ContentType, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TransferEncoding, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Match, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Once}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"bind"; + +} // namespace + +CXFA_Bind::CXFA_Bind(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | + XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Bind, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Bind>(this)) {} + +CXFA_Bind::~CXFA_Bind() {} + +WideString CXFA_Bind::GetPicture() { + CXFA_Picture* pPicture = + GetChild<CXFA_Picture>(0, XFA_Element::Picture, false); + return pPicture ? pPicture->JSObject()->GetContent(false) : L""; } diff --git a/xfa/fxfa/parser/cxfa_bind.h b/xfa/fxfa/parser/cxfa_bind.h index 40a2a1a482cd85377f4b5f1be16ec3550058b67e..1924cb6f78f4ef9f7d813599b86ee96f5aeec9e3 100644 --- a/xfa/fxfa/parser/cxfa_bind.h +++ b/xfa/fxfa/parser/cxfa_bind.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,16 +7,14 @@ #ifndef XFA_FXFA_PARSER_CXFA_BIND_H_ #define XFA_FXFA_PARSER_CXFA_BIND_H_ -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Bind : public CXFA_Data { +class CXFA_Bind : public CXFA_Node { public: - explicit CXFA_Bind(CXFA_Node* pNode); + CXFA_Bind(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Bind() override; - void GetPicture(CFX_WideString& wsPicture); + WideString GetPicture(); }; #endif // XFA_FXFA_PARSER_CXFA_BIND_H_ diff --git a/xfa/fxfa/parser/cxfa_binditems.cpp b/xfa/fxfa/parser/cxfa_binditems.cpp index fdb4f0c376213dfaacca48ae0f5281b9f88b8291..d7d72a7e3ac93d4df7717898470df6ecb8f29bdc 100644 --- a/xfa/fxfa/parser/cxfa_binditems.cpp +++ b/xfa/fxfa/parser/cxfa_binditems.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,22 +6,43 @@ #include "xfa/fxfa/parser/cxfa_binditems.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_binditems.h" +#include "third_party/base/ptr_util.h" -CXFA_BindItems::CXFA_BindItems(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -void CXFA_BindItems::GetLabelRef(CFX_WideStringC& wsLabelRef) { - m_pNode->TryCData(XFA_ATTRIBUTE_LabelRef, wsLabelRef); -} +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Connection, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::LabelRef, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ValueRef, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"bindItems"; + +} // namespace + +CXFA_BindItems::CXFA_BindItems(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::BindItems, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_BindItems>(this)) {} + +CXFA_BindItems::~CXFA_BindItems() {} -void CXFA_BindItems::GetValueRef(CFX_WideStringC& wsValueRef) { - m_pNode->TryCData(XFA_ATTRIBUTE_ValueRef, wsValueRef); +WideString CXFA_BindItems::GetLabelRef() { + return JSObject()->GetCData(XFA_Attribute::LabelRef); } -void CXFA_BindItems::GetRef(CFX_WideStringC& wsRef) { - m_pNode->TryCData(XFA_ATTRIBUTE_Ref, wsRef); +WideString CXFA_BindItems::GetValueRef() { + return JSObject()->GetCData(XFA_Attribute::ValueRef); } -bool CXFA_BindItems::SetConnection(const CFX_WideString& wsConnection) { - return m_pNode->SetCData(XFA_ATTRIBUTE_Connection, wsConnection); +WideString CXFA_BindItems::GetRef() { + return JSObject()->GetCData(XFA_Attribute::Ref); } diff --git a/xfa/fxfa/parser/cxfa_binditems.h b/xfa/fxfa/parser/cxfa_binditems.h index 191941a3fbcefe67d5b04c5288476d5632bba2ee..f1a490d13e082b239e12d6b29f7ec57d33091da9 100644 --- a/xfa/fxfa/parser/cxfa_binditems.h +++ b/xfa/fxfa/parser/cxfa_binditems.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,19 +7,16 @@ #ifndef XFA_FXFA_PARSER_CXFA_BINDITEMS_H_ #define XFA_FXFA_PARSER_CXFA_BINDITEMS_H_ -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_BindItems : public CXFA_Data { +class CXFA_BindItems : public CXFA_Node { public: - explicit CXFA_BindItems(CXFA_Node* pNode); + CXFA_BindItems(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_BindItems() override; - void GetLabelRef(CFX_WideStringC& wsLabelRef); - void GetValueRef(CFX_WideStringC& wsValueRef); - void GetRef(CFX_WideStringC& wsRef); - bool SetConnection(const CFX_WideString& wsConnection); + WideString GetLabelRef(); + WideString GetValueRef(); + WideString GetRef(); }; #endif // XFA_FXFA_PARSER_CXFA_BINDITEMS_H_ diff --git a/xfa/fxfa/parser/cxfa_bookend.cpp b/xfa/fxfa/parser/cxfa_bookend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b172be3a4dd677e1eb4fa7543db798c341024f0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_bookend.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_bookend.h" + +#include "fxjs/xfa/cjx_bookend.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Trailer, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Leader, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"bookend"; + +} // namespace + +CXFA_Bookend::CXFA_Bookend(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Bookend, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Bookend>(this)) {} + +CXFA_Bookend::~CXFA_Bookend() {} diff --git a/xfa/fxfa/parser/cxfa_bookend.h b/xfa/fxfa/parser/cxfa_bookend.h new file mode 100644 index 0000000000000000000000000000000000000000..82eb13c767875e41e1585f64eebd8e71b22e9c20 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_bookend.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BOOKEND_H_ +#define XFA_FXFA_PARSER_CXFA_BOOKEND_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Bookend : public CXFA_Node { + public: + CXFA_Bookend(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Bookend() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BOOKEND_H_ diff --git a/xfa/fxfa/parser/cxfa_boolean.cpp b/xfa/fxfa/parser/cxfa_boolean.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f804919ca0fded956a67bcc1bc7a83a204b7b277 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_boolean.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_boolean.h" + +#include "fxjs/xfa/cjx_boolean.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"boolean"; + +} // namespace + +CXFA_Boolean::CXFA_Boolean(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | + XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Boolean, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Boolean>(this)) {} + +CXFA_Boolean::~CXFA_Boolean() {} diff --git a/xfa/fxfa/parser/cxfa_boolean.h b/xfa/fxfa/parser/cxfa_boolean.h new file mode 100644 index 0000000000000000000000000000000000000000..4121e36409e138656621c384747a49a826a3cfb7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_boolean.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BOOLEAN_H_ +#define XFA_FXFA_PARSER_CXFA_BOOLEAN_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Boolean : public CXFA_Node { + public: + CXFA_Boolean(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Boolean() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BOOLEAN_H_ diff --git a/xfa/fxfa/parser/cxfa_border.cpp b/xfa/fxfa/parser/cxfa_border.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb8756288b1ed3865515f7b3bd42b43be2aac532 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_border.cpp @@ -0,0 +1,46 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_border.h" + +#include "fxjs/xfa/cjx_border.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Margin, 1, 0}, {XFA_Element::Edge, 4, 0}, + {XFA_Element::Corner, 4, 0}, {XFA_Element::Fill, 1, 0}, + {XFA_Element::Extras, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Break, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Close}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Hand, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Even}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"border"; + +} // namespace + +CXFA_Border::CXFA_Border(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Rectangle(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Border, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Border>(this)) {} + +CXFA_Border::~CXFA_Border() {} diff --git a/xfa/fxfa/parser/cxfa_border.h b/xfa/fxfa/parser/cxfa_border.h index 27b469cd2f8e1b71b6650bd1258cd69ae8dad624..24f3bb98be6a2ca6dd509f6cc0a0eb343340140a 100644 --- a/xfa/fxfa/parser/cxfa_border.h +++ b/xfa/fxfa/parser/cxfa_border.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,13 +7,12 @@ #ifndef XFA_FXFA_PARSER_CXFA_BORDER_H_ #define XFA_FXFA_PARSER_CXFA_BORDER_H_ -#include "xfa/fxfa/parser/cxfa_box.h" +#include "xfa/fxfa/parser/cxfa_rectangle.h" -class CXFA_Node; - -class CXFA_Border : public CXFA_Box { +class CXFA_Border : public CXFA_Rectangle { public: - explicit CXFA_Border(CXFA_Node* pNode) : CXFA_Box(pNode) {} + CXFA_Border(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Border() override; }; #endif // XFA_FXFA_PARSER_CXFA_BORDER_H_ diff --git a/xfa/fxfa/parser/cxfa_box.cpp b/xfa/fxfa/parser/cxfa_box.cpp index 552c98031a4ebc8e068a47aa6002bd03638c813c..b81461285fe7dbcd4a42476495d339588ac3486d 100644 --- a/xfa/fxfa/parser/cxfa_box.cpp +++ b/xfa/fxfa/parser/cxfa_box.cpp @@ -6,159 +6,352 @@ #include "xfa/fxfa/parser/cxfa_box.h" +#include <algorithm> +#include <utility> + +#include "fxjs/xfa/cjx_object.h" #include "xfa/fxfa/parser/cxfa_corner.h" +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxfa/parser/cxfa_fill.h" +#include "xfa/fxfa/parser/cxfa_margin.h" #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_rectangle.h" +#include "xfa/fxgraphics/cxfa_gepath.h" +#include "xfa/fxgraphics/cxfa_gepattern.h" +#include "xfa/fxgraphics/cxfa_geshading.h" +#include "xfa/fxgraphics/cxfa_graphics.h" namespace { -void GetStrokesInternal(CXFA_Node* pNode, - std::vector<CXFA_Stroke>* strokes, - bool bNull) { - strokes->clear(); - if (!pNode) - return; - - strokes->resize(8); - int32_t i, j; - for (i = 0, j = 0; i < 4; i++) { - CXFA_Corner corner = - CXFA_Corner(pNode->GetProperty(i, XFA_Element::Corner, i == 0)); - if (corner || i == 0) { - (*strokes)[j] = corner; - } else if (!bNull) { - if (i == 1 || i == 2) - (*strokes)[j] = (*strokes)[0]; - else - (*strokes)[j] = (*strokes)[2]; - } - j++; - CXFA_Edge edge = - CXFA_Edge(pNode->GetProperty(i, XFA_Element::Edge, i == 0)); - if (edge || i == 0) { - (*strokes)[j] = edge; - } else if (!bNull) { - if (i == 1 || i == 2) - (*strokes)[j] = (*strokes)[1]; - else - (*strokes)[j] = (*strokes)[3]; - } - j++; - } -} - -static int32_t Style3D(const std::vector<CXFA_Stroke>& strokes, - CXFA_Stroke& stroke) { +std::pair<XFA_AttributeEnum, CXFA_Stroke*> Style3D( + const std::vector<CXFA_Stroke*>& strokes) { if (strokes.empty()) - return 0; + return {XFA_AttributeEnum::Unknown, nullptr}; - stroke = strokes[0]; + CXFA_Stroke* stroke = strokes[0]; for (size_t i = 1; i < strokes.size(); i++) { - CXFA_Stroke find = strokes[i]; + CXFA_Stroke* find = strokes[i]; if (!find) continue; - if (!stroke) stroke = find; - else if (stroke.GetStrokeType() != find.GetStrokeType()) + else if (stroke->GetStrokeType() != find->GetStrokeType()) stroke = find; break; } - int32_t iType = stroke.GetStrokeType(); - if (iType == XFA_ATTRIBUTEENUM_Lowered || iType == XFA_ATTRIBUTEENUM_Raised || - iType == XFA_ATTRIBUTEENUM_Etched || - iType == XFA_ATTRIBUTEENUM_Embossed) { - return iType; + + XFA_AttributeEnum iType = stroke->GetStrokeType(); + if (iType == XFA_AttributeEnum::Lowered || + iType == XFA_AttributeEnum::Raised || + iType == XFA_AttributeEnum::Etched || + iType == XFA_AttributeEnum::Embossed) { + return {iType, stroke}; } - return 0; + return {XFA_AttributeEnum::Unknown, stroke}; +} + +CXFA_Rectangle* ToRectangle(CXFA_Box* box) { + return static_cast<CXFA_Rectangle*>(box); } } // namespace -int32_t CXFA_Box::GetHand() const { - if (!m_pNode) - return XFA_ATTRIBUTEENUM_Even; - return m_pNode->GetEnum(XFA_ATTRIBUTE_Hand); +CXFA_Box::CXFA_Box(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node) + : CXFA_Node(pDoc, + ePacket, + validPackets, + oType, + eType, + properties, + attributes, + elementName, + std::move(js_node)) {} + +CXFA_Box::~CXFA_Box() = default; + +XFA_AttributeEnum CXFA_Box::GetHand() { + return JSObject()->GetEnum(XFA_Attribute::Hand); } -int32_t CXFA_Box::GetPresence() const { - if (!m_pNode) - return XFA_ATTRIBUTEENUM_Hidden; - return m_pNode->GetEnum(XFA_ATTRIBUTE_Presence); +XFA_AttributeEnum CXFA_Box::GetPresence() { + return JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible); } -int32_t CXFA_Box::CountEdges() const { - if (!m_pNode) - return 0; - return m_pNode->CountChildren(XFA_Element::Edge); +int32_t CXFA_Box::CountEdges() { + return CountChildren(XFA_Element::Edge, false); } -CXFA_Edge CXFA_Box::GetEdge(int32_t nIndex) const { - return CXFA_Edge( - m_pNode ? m_pNode->GetProperty(nIndex, XFA_Element::Edge, nIndex == 0) - : nullptr); +CXFA_Edge* CXFA_Box::GetEdgeIfExists(int32_t nIndex) { + if (nIndex == 0) + return JSObject()->GetOrCreateProperty<CXFA_Edge>(nIndex, + XFA_Element::Edge); + return JSObject()->GetProperty<CXFA_Edge>(nIndex, XFA_Element::Edge); } -void CXFA_Box::GetStrokes(std::vector<CXFA_Stroke>* strokes) const { - GetStrokesInternal(m_pNode, strokes, false); +std::vector<CXFA_Stroke*> CXFA_Box::GetStrokes() { + return GetStrokesInternal(false); } -bool CXFA_Box::IsCircular() const { - if (!m_pNode) - return false; - return m_pNode->GetBoolean(XFA_ATTRIBUTE_Circular); +bool CXFA_Box::IsCircular() { + return JSObject()->GetBoolean(XFA_Attribute::Circular); } -bool CXFA_Box::GetStartAngle(FX_FLOAT& fStartAngle) const { - fStartAngle = 0; - if (!m_pNode) - return false; +Optional<int32_t> CXFA_Box::GetStartAngle() { + return JSObject()->TryInteger(XFA_Attribute::StartAngle, false); +} - CXFA_Measurement ms; - bool bRet = m_pNode->TryMeasure(XFA_ATTRIBUTE_StartAngle, ms, false); - if (bRet) - fStartAngle = ms.GetValue(); +Optional<int32_t> CXFA_Box::GetSweepAngle() { + return JSObject()->TryInteger(XFA_Attribute::SweepAngle, false); +} - return bRet; +CXFA_Fill* CXFA_Box::GetOrCreateFillIfPossible() { + return JSObject()->GetOrCreateProperty<CXFA_Fill>(0, XFA_Element::Fill); } -bool CXFA_Box::GetSweepAngle(FX_FLOAT& fSweepAngle) const { - fSweepAngle = 360; - if (!m_pNode) - return false; +std::tuple<XFA_AttributeEnum, bool, float> CXFA_Box::Get3DStyle() { + if (GetElementType() == XFA_Element::Arc) + return {XFA_AttributeEnum::Unknown, false, 0.0f}; - CXFA_Measurement ms; - bool bRet = m_pNode->TryMeasure(XFA_ATTRIBUTE_SweepAngle, ms, false); - if (bRet) - fSweepAngle = ms.GetValue(); + std::vector<CXFA_Stroke*> strokes = GetStrokesInternal(true); + CXFA_Stroke* stroke; + XFA_AttributeEnum iType; - return bRet; + std::tie(iType, stroke) = Style3D(strokes); + if (iType == XFA_AttributeEnum::Unknown) + return {XFA_AttributeEnum::Unknown, false, 0.0f}; + + return {iType, stroke->IsVisible(), stroke->GetThickness()}; } -CXFA_Fill CXFA_Box::GetFill(bool bModified) const { - if (!m_pNode) - return CXFA_Fill(nullptr); +std::vector<CXFA_Stroke*> CXFA_Box::GetStrokesInternal(bool bNull) { + std::vector<CXFA_Stroke*> strokes; + strokes.resize(8); + + for (int32_t i = 0, j = 0; i < 4; i++) { + CXFA_Corner* corner; + if (i == 0) { + corner = + JSObject()->GetOrCreateProperty<CXFA_Corner>(i, XFA_Element::Corner); + } else { + corner = JSObject()->GetProperty<CXFA_Corner>(i, XFA_Element::Corner); + } + + // TODO(dsinclair): If i == 0 and GetOrCreateProperty failed, we can end up + // with a null corner in the first position. + if (corner || i == 0) { + strokes[j] = corner; + } else if (!bNull) { + if (i == 1 || i == 2) + strokes[j] = strokes[0]; + else + strokes[j] = strokes[2]; + } + j++; + + CXFA_Edge* edge; + if (i == 0) + edge = JSObject()->GetOrCreateProperty<CXFA_Edge>(i, XFA_Element::Edge); + else + edge = JSObject()->GetProperty<CXFA_Edge>(i, XFA_Element::Edge); - CXFA_Node* pFillNode = m_pNode->GetProperty(0, XFA_Element::Fill, bModified); - return CXFA_Fill(pFillNode); + // TODO(dsinclair): If i == 0 and GetOrCreateProperty failed, we can end up + // with a null edge in the first position. + if (edge || i == 0) { + strokes[j] = edge; + } else if (!bNull) { + if (i == 1 || i == 2) + strokes[j] = strokes[1]; + else + strokes[j] = strokes[3]; + } + j++; + } + return strokes; +} + +void CXFA_Box::Draw(CXFA_Graphics* pGS, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix, + bool forceRound) { + if (GetPresence() != XFA_AttributeEnum::Visible) + return; + + XFA_Element eType = GetElementType(); + if (eType != XFA_Element::Arc && eType != XFA_Element::Border && + eType != XFA_Element::Rectangle) { + return; + } + std::vector<CXFA_Stroke*> strokes; + if (!forceRound && eType != XFA_Element::Arc) + strokes = GetStrokes(); + + DrawFill(strokes, pGS, rtWidget, matrix, forceRound); + XFA_Element type = GetElementType(); + if (type == XFA_Element::Arc || forceRound) { + StrokeArcOrRounded(pGS, rtWidget, matrix, forceRound); + } else if (type == XFA_Element::Rectangle || type == XFA_Element::Border) { + ToRectangle(this)->Draw(strokes, pGS, rtWidget, matrix); + } else { + NOTREACHED(); + } +} + +void CXFA_Box::DrawFill(const std::vector<CXFA_Stroke*>& strokes, + CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix, + bool forceRound) { + CXFA_Fill* fill = JSObject()->GetProperty<CXFA_Fill>(0, XFA_Element::Fill); + if (!fill || !fill->IsVisible()) + return; + + pGS->SaveGraphState(); + + CXFA_GEPath fillPath; + XFA_Element type = GetElementType(); + if (type == XFA_Element::Arc || forceRound) { + CXFA_Edge* edge = GetEdgeIfExists(0); + float fThickness = std::fmax(0.0, edge ? edge->GetThickness() : 0); + float fHalf = fThickness / 2; + XFA_AttributeEnum iHand = GetHand(); + if (iHand == XFA_AttributeEnum::Left) + rtWidget.Inflate(fHalf, fHalf); + else if (iHand == XFA_AttributeEnum::Right) + rtWidget.Deflate(fHalf, fHalf); + + GetPathArcOrRounded(rtWidget, fillPath, forceRound); + } else if (type == XFA_Element::Rectangle || type == XFA_Element::Border) { + ToRectangle(this)->GetFillPath(strokes, rtWidget, &fillPath); + } else { + NOTREACHED(); + } + fillPath.Close(); + + fill->Draw(pGS, &fillPath, rtWidget, matrix); + pGS->RestoreGraphState(); } -CXFA_Margin CXFA_Box::GetMargin() const { - return CXFA_Margin(m_pNode ? m_pNode->GetChild(0, XFA_Element::Margin) - : nullptr); +void CXFA_Box::GetPathArcOrRounded(CFX_RectF rtDraw, + CXFA_GEPath& fillPath, + bool forceRound) { + float a, b; + a = rtDraw.width / 2.0f; + b = rtDraw.height / 2.0f; + if (IsCircular() || forceRound) + a = b = std::min(a, b); + + CFX_PointF center = rtDraw.Center(); + rtDraw.left = center.x - a; + rtDraw.top = center.y - b; + rtDraw.width = a + a; + rtDraw.height = b + b; + Optional<int32_t> startAngle = GetStartAngle(); + Optional<int32_t> sweepAngle = GetSweepAngle(); + if (!startAngle && !sweepAngle) { + fillPath.AddEllipse(rtDraw); + return; + } + + fillPath.AddArc(rtDraw.TopLeft(), rtDraw.Size(), + -startAngle.value_or(0) * FX_PI / 180.0f, + -sweepAngle.value_or(360) * FX_PI / 180.0f); } -int32_t CXFA_Box::Get3DStyle(bool& bVisible, FX_FLOAT& fThickness) const { - if (IsArc()) - return 0; +void CXFA_Box::StrokeArcOrRounded(CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix, + bool forceRound) { + CXFA_Edge* edge = GetEdgeIfExists(0); + if (!edge || !edge->IsVisible()) + return; + + bool bVisible; + float fThickness; + XFA_AttributeEnum i3DType; + std::tie(i3DType, bVisible, fThickness) = Get3DStyle(); + bool lowered3d = false; + if (i3DType != XFA_AttributeEnum::Unknown) { + if (bVisible && fThickness >= 0.001f) + lowered3d = true; + } + + float fHalf = edge->GetThickness() / 2; + if (fHalf < 0) { + fHalf = 0; + } + + XFA_AttributeEnum iHand = GetHand(); + if (iHand == XFA_AttributeEnum::Left) { + rtWidget.Inflate(fHalf, fHalf); + } else if (iHand == XFA_AttributeEnum::Right) { + rtWidget.Deflate(fHalf, fHalf); + } + if (!forceRound || !lowered3d) { + if (fHalf < 0.001f) + return; + + CXFA_GEPath arcPath; + GetPathArcOrRounded(rtWidget, arcPath, forceRound); + if (edge) + edge->Stroke(&arcPath, pGS, matrix); + return; + } + pGS->SaveGraphState(); + pGS->SetLineWidth(fHalf); - std::vector<CXFA_Stroke> strokes; - GetStrokesInternal(m_pNode, &strokes, true); - CXFA_Stroke stroke(nullptr); - int32_t iType = Style3D(strokes, stroke); - if (iType) { - bVisible = stroke.IsVisible(); - fThickness = stroke.GetThickness(); + float a, b; + a = rtWidget.width / 2.0f; + b = rtWidget.height / 2.0f; + if (forceRound) { + a = std::min(a, b); + b = a; } - return iType; + + CFX_PointF center = rtWidget.Center(); + rtWidget.left = center.x - a; + rtWidget.top = center.y - b; + rtWidget.width = a + a; + rtWidget.height = b + b; + + float startAngle = 0, sweepAngle = 360; + startAngle = startAngle * FX_PI / 180.0f; + sweepAngle = -sweepAngle * FX_PI / 180.0f; + + CXFA_GEPath arcPath; + arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f, + FX_PI); + + pGS->SetStrokeColor(CXFA_GEColor(0xFF808080)); + pGS->StrokePath(&arcPath, &matrix); + arcPath.Clear(); + arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f, + FX_PI); + + pGS->SetStrokeColor(CXFA_GEColor(0xFFFFFFFF)); + pGS->StrokePath(&arcPath, &matrix); + rtWidget.Deflate(fHalf, fHalf); + arcPath.Clear(); + arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f, + FX_PI); + + pGS->SetStrokeColor(CXFA_GEColor(0xFF404040)); + pGS->StrokePath(&arcPath, &matrix); + arcPath.Clear(); + arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f, + FX_PI); + + pGS->SetStrokeColor(CXFA_GEColor(0xFFC0C0C0)); + pGS->StrokePath(&arcPath, &matrix); + pGS->RestoreGraphState(); } diff --git a/xfa/fxfa/parser/cxfa_box.h b/xfa/fxfa/parser/cxfa_box.h index a0af2f449b2f943069dfc702b1dec1a46d3e147c..0831cd603ec8076acaa6cd648722d400ebfce9f3 100644 --- a/xfa/fxfa/parser/cxfa_box.h +++ b/xfa/fxfa/parser/cxfa_box.h @@ -7,48 +7,69 @@ #ifndef XFA_FXFA_PARSER_CXFA_BOX_H_ #define XFA_FXFA_PARSER_CXFA_BOX_H_ +#include <memory> +#include <tuple> #include <vector> -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_edge.h" -#include "xfa/fxfa/parser/cxfa_fill.h" -#include "xfa/fxfa/parser/cxfa_margin.h" +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_gepath.h" -class CXFA_Node; +class CXFA_Edge; +class CXFA_Fill; +class CXFA_Graphics; +class CXFA_Margin; +class CXFA_Stroke; -class CXFA_Box : public CXFA_Data { +class CXFA_Box : public CXFA_Node { public: - explicit CXFA_Box(CXFA_Node* pNode) : CXFA_Data(pNode) {} - - bool IsArc() const { return GetElementType() == XFA_Element::Arc; } - bool IsBorder() const { return GetElementType() == XFA_Element::Border; } - bool IsRectangle() const { - return GetElementType() == XFA_Element::Rectangle; - } - int32_t GetHand() const; - int32_t GetPresence() const; - int32_t CountEdges() const; - CXFA_Edge GetEdge(int32_t nIndex = 0) const; - void GetStrokes(std::vector<CXFA_Stroke>* strokes) const; - bool IsCircular() const; - bool GetStartAngle(FX_FLOAT& fStartAngle) const; - FX_FLOAT GetStartAngle() const { - FX_FLOAT fStartAngle; - GetStartAngle(fStartAngle); - return fStartAngle; - } - - bool GetSweepAngle(FX_FLOAT& fSweepAngle) const; - FX_FLOAT GetSweepAngle() const { - FX_FLOAT fSweepAngle; - GetSweepAngle(fSweepAngle); - return fSweepAngle; - } - - CXFA_Fill GetFill(bool bModified = false) const; - CXFA_Margin GetMargin() const; - int32_t Get3DStyle(bool& bVisible, FX_FLOAT& fThickness) const; + ~CXFA_Box() override; + + XFA_AttributeEnum GetPresence(); + std::tuple<XFA_AttributeEnum, bool, float> Get3DStyle(); + + int32_t CountEdges(); + CXFA_Edge* GetEdgeIfExists(int32_t nIndex); + CXFA_Fill* GetOrCreateFillIfPossible(); + + std::vector<CXFA_Stroke*> GetStrokes(); + + void Draw(CXFA_Graphics* pGS, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix, + bool forceRound); + + protected: + CXFA_Box(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node); + + XFA_AttributeEnum GetHand(); + + private: + bool IsCircular(); + Optional<int32_t> GetStartAngle(); + Optional<int32_t> GetSweepAngle(); + + std::vector<CXFA_Stroke*> GetStrokesInternal(bool bNull); + void DrawFill(const std::vector<CXFA_Stroke*>& strokes, + CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix, + bool forceRound); + void StrokeArcOrRounded(CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix, + bool forceRound); + void GetPathArcOrRounded(CFX_RectF rtDraw, + CXFA_GEPath& fillPath, + bool forceRound); }; #endif // XFA_FXFA_PARSER_CXFA_BOX_H_ diff --git a/xfa/fxfa/parser/cxfa_break.cpp b/xfa/fxfa/parser/cxfa_break.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a83b1c62ac79f2d289f3d15ac2f7f04f0fc5bad --- /dev/null +++ b/xfa/fxfa/parser/cxfa_break.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_break.h" + +#include "fxjs/xfa/cjx_break.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::BeforeTarget, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::OverflowTarget, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::OverflowLeader, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::OverflowTrailer, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::StartNew, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::BookendTrailer, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::After, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::BookendLeader, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AfterTarget, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Before, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"break"; + +} // namespace + +CXFA_Break::CXFA_Break(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Break, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Break>(this)) {} + +CXFA_Break::~CXFA_Break() {} diff --git a/xfa/fxfa/parser/cxfa_break.h b/xfa/fxfa/parser/cxfa_break.h new file mode 100644 index 0000000000000000000000000000000000000000..c0d937c51343a0c68c4897ba50818dd08934fd78 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_break.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BREAK_H_ +#define XFA_FXFA_PARSER_CXFA_BREAK_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Break : public CXFA_Node { + public: + CXFA_Break(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Break() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BREAK_H_ diff --git a/xfa/fxfa/parser/cxfa_breakafter.cpp b/xfa/fxfa/parser/cxfa_breakafter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..925b721f35a9ec5478df98f1988c8e946d548b80 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_breakafter.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_breakafter.h" + +#include "fxjs/xfa/cjx_breakafter.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Script, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::StartNew, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Trailer, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TargetType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Target, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Leader, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"breakAfter"; + +} // namespace + +CXFA_BreakAfter::CXFA_BreakAfter(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::BreakAfter, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_BreakAfter>(this)) {} + +CXFA_BreakAfter::~CXFA_BreakAfter() {} diff --git a/xfa/fxfa/parser/cxfa_breakafter.h b/xfa/fxfa/parser/cxfa_breakafter.h new file mode 100644 index 0000000000000000000000000000000000000000..952b0c9a998deb3d95cf6052dcd2596d3b7a7ba1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_breakafter.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BREAKAFTER_H_ +#define XFA_FXFA_PARSER_CXFA_BREAKAFTER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_BreakAfter : public CXFA_Node { + public: + CXFA_BreakAfter(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_BreakAfter() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BREAKAFTER_H_ diff --git a/xfa/fxfa/parser/cxfa_breakbefore.cpp b/xfa/fxfa/parser/cxfa_breakbefore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8dcadea74e2e17a070b1c04287692187ff1919b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_breakbefore.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_breakbefore.h" + +#include "fxjs/xfa/cjx_breakbefore.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Script, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::StartNew, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Trailer, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TargetType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Target, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Leader, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"breakBefore"; + +} // namespace + +CXFA_BreakBefore::CXFA_BreakBefore(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::BreakBefore, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_BreakBefore>(this)) {} + +CXFA_BreakBefore::~CXFA_BreakBefore() {} diff --git a/xfa/fxfa/parser/cxfa_breakbefore.h b/xfa/fxfa/parser/cxfa_breakbefore.h new file mode 100644 index 0000000000000000000000000000000000000000..358e477993103f3b196699d81c1bfd6569caa6c8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_breakbefore.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BREAKBEFORE_H_ +#define XFA_FXFA_PARSER_CXFA_BREAKBEFORE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_BreakBefore : public CXFA_Node { + public: + CXFA_BreakBefore(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_BreakBefore() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BREAKBEFORE_H_ diff --git a/xfa/fxfa/parser/cxfa_button.cpp b/xfa/fxfa/parser/cxfa_button.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b62efbc78e16cf15961d51c13bf77c672e3be1c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_button.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_button.h" + +#include "fxjs/xfa/cjx_button.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Highlight, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Inverted}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"button"; + +} // namespace + +CXFA_Button::CXFA_Button(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Button, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Button>(this)) {} + +CXFA_Button::~CXFA_Button() {} diff --git a/xfa/fxfa/parser/cxfa_button.h b/xfa/fxfa/parser/cxfa_button.h new file mode 100644 index 0000000000000000000000000000000000000000..86ffb52c52ae2833440506d3dedf296b395bfbde --- /dev/null +++ b/xfa/fxfa/parser/cxfa_button.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_BUTTON_H_ +#define XFA_FXFA_PARSER_CXFA_BUTTON_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Button : public CXFA_Node { + public: + CXFA_Button(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Button() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_BUTTON_H_ diff --git a/xfa/fxfa/parser/cxfa_cache.cpp b/xfa/fxfa/parser/cxfa_cache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74227a3000fabea83e44632c82a6f59e075b979f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_cache.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_cache.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::TemplateCache, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"cache"; + +} // namespace + +CXFA_Cache::CXFA_Cache(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Cache, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Cache::~CXFA_Cache() {} diff --git a/xfa/fxfa/parser/cxfa_cache.h b/xfa/fxfa/parser/cxfa_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..e3907c68e7ced7edc8caf8e1c8a51600d1e3e050 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_cache.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CACHE_H_ +#define XFA_FXFA_PARSER_CXFA_CACHE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Cache : public CXFA_Node { + public: + CXFA_Cache(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Cache() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CACHE_H_ diff --git a/xfa/fxfa/parser/cxfa_calculate.cpp b/xfa/fxfa/parser/cxfa_calculate.cpp index d7b1f71caa896a5f931354e0a251b4cd45356170..328678783c2675f4e5f13888dc7b177c5fc708cc 100644 --- a/xfa/fxfa/parser/cxfa_calculate.cpp +++ b/xfa/fxfa/parser/cxfa_calculate.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,27 +6,58 @@ #include "xfa/fxfa/parser/cxfa_calculate.h" +#include "fxjs/xfa/cjx_calculate.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_message.h" +#include "xfa/fxfa/parser/cxfa_script.h" #include "xfa/fxfa/parser/cxfa_text.h" -#include "xfa/fxfa/parser/xfa_object.h" -CXFA_Calculate::CXFA_Calculate(CXFA_Node* pNode) : CXFA_Data(pNode) {} - -int32_t CXFA_Calculate::GetOverride() { - XFA_ATTRIBUTEENUM eAtt = XFA_ATTRIBUTEENUM_Error; - m_pNode->TryEnum(XFA_ATTRIBUTE_Override, eAtt, false); - return eAtt; +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Message, 1, 0}, + {XFA_Element::Script, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Override, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Error}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"calculate"; + +} // namespace + +CXFA_Calculate::CXFA_Calculate(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Calculate, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Calculate>(this)) {} + +CXFA_Calculate::~CXFA_Calculate() {} + +XFA_AttributeEnum CXFA_Calculate::GetOverride() { + return JSObject() + ->TryEnum(XFA_Attribute::Override, false) + .value_or(XFA_AttributeEnum::Error); } -CXFA_Script CXFA_Calculate::GetScript() { - return CXFA_Script(m_pNode->GetChild(0, XFA_Element::Script)); +CXFA_Script* CXFA_Calculate::GetScriptIfExists() { + return GetChild<CXFA_Script>(0, XFA_Element::Script, false); } -void CXFA_Calculate::GetMessageText(CFX_WideString& wsMessage) { - CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Message); +WideString CXFA_Calculate::GetMessageText() { + CXFA_Message* pNode = GetChild<CXFA_Message>(0, XFA_Element::Message, false); if (!pNode) - return; + return L""; - CXFA_Text text(pNode->GetChild(0, XFA_Element::Text)); - if (text) - text.GetContent(wsMessage); + CXFA_Text* text = pNode->GetChild<CXFA_Text>(0, XFA_Element::Text, false); + return text ? text->GetContent() : L""; } diff --git a/xfa/fxfa/parser/cxfa_calculate.h b/xfa/fxfa/parser/cxfa_calculate.h index 10122240694a9aa9a8389272ee92364139ecb5a8..a5be908b4c4ac545ba4d4ccf8aa77ce1705fad28 100644 --- a/xfa/fxfa/parser/cxfa_calculate.h +++ b/xfa/fxfa/parser/cxfa_calculate.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,19 +7,18 @@ #ifndef XFA_FXFA_PARSER_CXFA_CALCULATE_H_ #define XFA_FXFA_PARSER_CXFA_CALCULATE_H_ -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; +class CXFA_Script; -class CXFA_Calculate : public CXFA_Data { +class CXFA_Calculate : public CXFA_Node { public: - explicit CXFA_Calculate(CXFA_Node* pNode); + CXFA_Calculate(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Calculate() override; - int32_t GetOverride(); - CXFA_Script GetScript(); - void GetMessageText(CFX_WideString& wsMessage); + XFA_AttributeEnum GetOverride(); + CXFA_Script* GetScriptIfExists(); + WideString GetMessageText(); }; #endif // XFA_FXFA_PARSER_CXFA_CALCULATE_H_ diff --git a/xfa/fxfa/parser/cxfa_calendarsymbols.cpp b/xfa/fxfa/parser/cxfa_calendarsymbols.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9ad3b5817db5362c55b3f0d5435dd4bf1e71b55 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_calendarsymbols.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_calendarsymbols.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::EraNames, 1, 0}, + {XFA_Element::DayNames, 2, 0}, + {XFA_Element::MeridiemNames, 1, 0}, + {XFA_Element::MonthNames, 2, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Gregorian}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"calendarSymbols"; + +} // namespace + +CXFA_CalendarSymbols::CXFA_CalendarSymbols(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::CalendarSymbols, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_CalendarSymbols::~CXFA_CalendarSymbols() {} diff --git a/xfa/fxfa/parser/cxfa_calendarsymbols.h b/xfa/fxfa/parser/cxfa_calendarsymbols.h new file mode 100644 index 0000000000000000000000000000000000000000..1b1f00746930cb32d2484d941885b6b920a20239 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_calendarsymbols.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CALENDARSYMBOLS_H_ +#define XFA_FXFA_PARSER_CXFA_CALENDARSYMBOLS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CalendarSymbols : public CXFA_Node { + public: + CXFA_CalendarSymbols(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CalendarSymbols() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CALENDARSYMBOLS_H_ diff --git a/xfa/fxfa/parser/cxfa_caption.cpp b/xfa/fxfa/parser/cxfa_caption.cpp index 7f9e88e8e7f7113ec2b75119c00214452023651b..a54605a48ce8aaeb462a13719c8872383c7f3e69 100644 --- a/xfa/fxfa/parser/cxfa_caption.cpp +++ b/xfa/fxfa/parser/cxfa_caption.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,39 +6,78 @@ #include "xfa/fxfa/parser/cxfa_caption.h" +#include "fxjs/xfa/cjx_caption.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_margin.h" #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_value.h" -CXFA_Caption::CXFA_Caption(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -int32_t CXFA_Caption::GetPresence() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_Visible; - m_pNode->TryEnum(XFA_ATTRIBUTE_Presence, eAttr); - return eAttr; +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Margin, 1, 0}, {XFA_Element::Para, 1, 0}, + {XFA_Element::Font, 1, 0}, {XFA_Element::Value, 1, 0}, + {XFA_Element::Extras, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Reserve, XFA_AttributeType::Measure, (void*)L"-1un"}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Placement, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Left}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"caption"; + +} // namespace + +CXFA_Caption::CXFA_Caption(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Caption, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Caption>(this)) {} + +CXFA_Caption::~CXFA_Caption() {} + +bool CXFA_Caption::IsVisible() { + return JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible) == + XFA_AttributeEnum::Visible; +} + +bool CXFA_Caption::IsHidden() { + return JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible) == XFA_AttributeEnum::Hidden; } -int32_t CXFA_Caption::GetPlacementType() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_Left; - m_pNode->TryEnum(XFA_ATTRIBUTE_Placement, eAttr); - return eAttr; +XFA_AttributeEnum CXFA_Caption::GetPlacementType() { + return JSObject() + ->TryEnum(XFA_Attribute::Placement, true) + .value_or(XFA_AttributeEnum::Left); } -FX_FLOAT CXFA_Caption::GetReserve() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_Reserve, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Caption::GetReserve() const { + return JSObject()->GetMeasure(XFA_Attribute::Reserve).ToUnit(XFA_Unit::Pt); } -CXFA_Margin CXFA_Caption::GetMargin() { - return CXFA_Margin(m_pNode ? m_pNode->GetChild(0, XFA_Element::Margin) - : nullptr); +CXFA_Margin* CXFA_Caption::GetMarginIfExists() { + return GetChild<CXFA_Margin>(0, XFA_Element::Margin, false); } -CXFA_Font CXFA_Caption::GetFont() { - return CXFA_Font(m_pNode ? m_pNode->GetChild(0, XFA_Element::Font) : nullptr); +CXFA_Font* CXFA_Caption::GetFontIfExists() { + return GetChild<CXFA_Font>(0, XFA_Element::Font, false); } -CXFA_Value CXFA_Caption::GetValue() { - return CXFA_Value(m_pNode ? m_pNode->GetChild(0, XFA_Element::Value) - : nullptr); +CXFA_Value* CXFA_Caption::GetValueIfExists() { + return GetChild<CXFA_Value>(0, XFA_Element::Value, false); } diff --git a/xfa/fxfa/parser/cxfa_caption.h b/xfa/fxfa/parser/cxfa_caption.h index 70dd435653f766d3a5dea0686f95c9f3ee866761..c790787e9a4f56926be1b4671288688ac01935c4 100644 --- a/xfa/fxfa/parser/cxfa_caption.h +++ b/xfa/fxfa/parser/cxfa_caption.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,23 +7,27 @@ #ifndef XFA_FXFA_PARSER_CXFA_CAPTION_H_ #define XFA_FXFA_PARSER_CXFA_CAPTION_H_ -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_font.h" -#include "xfa/fxfa/parser/cxfa_margin.h" -#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; +class CXFA_Font; +class CXFA_Margin; +class CXFA_Value; -class CXFA_Caption : public CXFA_Data { +class CXFA_Caption : public CXFA_Node { public: - explicit CXFA_Caption(CXFA_Node* pNode); - - int32_t GetPresence(); - int32_t GetPlacementType(); - FX_FLOAT GetReserve(); - CXFA_Margin GetMargin(); - CXFA_Font GetFont(); - CXFA_Value GetValue(); + static constexpr XFA_AttributeEnum kDefaultPlacementType = + XFA_AttributeEnum::Left; + + CXFA_Caption(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Caption() override; + + bool IsVisible(); + bool IsHidden(); + XFA_AttributeEnum GetPlacementType(); + float GetReserve() const; + CXFA_Margin* GetMarginIfExists(); + CXFA_Font* GetFontIfExists(); + CXFA_Value* GetValueIfExists(); }; #endif // XFA_FXFA_PARSER_CXFA_CAPTION_H_ diff --git a/xfa/fxfa/parser/cxfa_certificate.cpp b/xfa/fxfa/parser/cxfa_certificate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3e8ec01c91cb1947010db7f94c21ac28f3dcb8f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_certificate.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_certificate.h" + +#include "fxjs/xfa/cjx_certificate.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"certificate"; + +} // namespace + +CXFA_Certificate::CXFA_Certificate(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::Certificate, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Certificate>(this)) {} + +CXFA_Certificate::~CXFA_Certificate() {} diff --git a/xfa/fxfa/parser/cxfa_certificate.h b/xfa/fxfa/parser/cxfa_certificate.h new file mode 100644 index 0000000000000000000000000000000000000000..48106dac03efbe6c7d596a0af43ea8c08056c070 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_certificate.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CERTIFICATE_H_ +#define XFA_FXFA_PARSER_CXFA_CERTIFICATE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Certificate : public CXFA_Node { + public: + CXFA_Certificate(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Certificate() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CERTIFICATE_H_ diff --git a/xfa/fxfa/parser/cxfa_certificates.cpp b/xfa/fxfa/parser/cxfa_certificates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0af8f30cc4a5567bd362c81585bd8506a642959d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_certificates.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_certificates.h" + +#include "fxjs/xfa/cjx_certificates.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::KeyUsage, 1, 0}, {XFA_Element::SubjectDNs, 1, 0}, + {XFA_Element::Issuers, 1, 0}, {XFA_Element::Signing, 1, 0}, + {XFA_Element::Oids, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Url, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CredentialServerPolicy, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::UrlPolicy, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"certificates"; + +} // namespace + +CXFA_Certificates::CXFA_Certificates(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Certificates, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Certificates>(this)) {} + +CXFA_Certificates::~CXFA_Certificates() {} diff --git a/xfa/fxfa/parser/cxfa_certificates.h b/xfa/fxfa/parser/cxfa_certificates.h new file mode 100644 index 0000000000000000000000000000000000000000..a1bed73ff91dc65369a151f0d36cabf7c8829e83 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_certificates.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CERTIFICATES_H_ +#define XFA_FXFA_PARSER_CXFA_CERTIFICATES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Certificates : public CXFA_Node { + public: + CXFA_Certificates(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Certificates() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CERTIFICATES_H_ diff --git a/xfa/fxfa/parser/cxfa_change.cpp b/xfa/fxfa/parser/cxfa_change.cpp new file mode 100644 index 0000000000000000000000000000000000000000..520c556f3381751beb740ab29e426c7a8d6333fb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_change.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_change.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"change"; + +} // namespace + +CXFA_Change::CXFA_Change(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Change, + nullptr, + kAttributeData, + kName) {} + +CXFA_Change::~CXFA_Change() {} diff --git a/xfa/fxfa/parser/cxfa_change.h b/xfa/fxfa/parser/cxfa_change.h new file mode 100644 index 0000000000000000000000000000000000000000..f39b92eacb1f8c7226bba2a55dd31246034d52a1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_change.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CHANGE_H_ +#define XFA_FXFA_PARSER_CXFA_CHANGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Change : public CXFA_Node { + public: + CXFA_Change(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Change() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CHANGE_H_ diff --git a/xfa/fxfa/parser/cxfa_checkbutton.cpp b/xfa/fxfa/parser/cxfa_checkbutton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00f3993e4a7ff46da021cae2e1b13f01b40bbba0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_checkbutton.cpp @@ -0,0 +1,45 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_checkbutton.h" + +#include "fxjs/xfa/cjx_checkbutton.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AllowNeutral, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Mark, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Default}, + {XFA_Attribute::Shape, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Square}, + {XFA_Attribute::Size, XFA_AttributeType::Measure, (void*)L"10pt"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"checkButton"; + +} // namespace + +CXFA_CheckButton::CXFA_CheckButton(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::CheckButton, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_CheckButton>(this)) {} + +CXFA_CheckButton::~CXFA_CheckButton() {} diff --git a/xfa/fxfa/parser/cxfa_checkbutton.h b/xfa/fxfa/parser/cxfa_checkbutton.h new file mode 100644 index 0000000000000000000000000000000000000000..dbfb4bb5d8ea187dce7f4e4f6808b9e7e1eebf4e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_checkbutton.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CHECKBUTTON_H_ +#define XFA_FXFA_PARSER_CXFA_CHECKBUTTON_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CheckButton : public CXFA_Node { + public: + CXFA_CheckButton(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CheckButton() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CHECKBUTTON_H_ diff --git a/xfa/fxfa/parser/cxfa_choicelist.cpp b/xfa/fxfa/parser/cxfa_choicelist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33f868316f60b6da202054b48bfd9d85e764d495 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_choicelist.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_choicelist.h" + +#include "fxjs/xfa/cjx_choicelist.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Open, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::UserControl}, + {XFA_Attribute::CommitOn, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Select}, + {XFA_Attribute::TextEntry, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"choiceList"; + +} // namespace + +CXFA_ChoiceList::CXFA_ChoiceList(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::ChoiceList, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ChoiceList>(this)) {} + +CXFA_ChoiceList::~CXFA_ChoiceList() {} diff --git a/xfa/fxfa/parser/cxfa_choicelist.h b/xfa/fxfa/parser/cxfa_choicelist.h new file mode 100644 index 0000000000000000000000000000000000000000..9e948807a2c9c2328472689989ae3233626ded47 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_choicelist.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CHOICELIST_H_ +#define XFA_FXFA_PARSER_CXFA_CHOICELIST_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ChoiceList : public CXFA_Node { + public: + CXFA_ChoiceList(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ChoiceList() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CHOICELIST_H_ diff --git a/xfa/fxfa/parser/cxfa_color.cpp b/xfa/fxfa/parser/cxfa_color.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95c0ad345b353abf9624d6f3baefeba9f991e439 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_color.cpp @@ -0,0 +1,59 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_color.h" + +#include "fxjs/xfa/cjx_color.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CSpace, XFA_AttributeType::CData, (void*)L"SRGB"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Value, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"color"; + +} // namespace + +CXFA_Color::CXFA_Color(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Color, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Color>(this)) {} + +CXFA_Color::~CXFA_Color() {} + +FX_ARGB CXFA_Color::GetValue() { + Optional<WideString> val = JSObject()->TryCData(XFA_Attribute::Value, false); + return val ? StringToFXARGB(val->AsStringView()) : 0xFF000000; +} + +FX_ARGB CXFA_Color::GetValueOrDefault(FX_ARGB defaultValue) { + Optional<WideString> val = JSObject()->TryCData(XFA_Attribute::Value, false); + return val ? StringToFXARGB(val->AsStringView()) : defaultValue; +} + +void CXFA_Color::SetValue(FX_ARGB color) { + int a; + int r; + int g; + int b; + std::tie(a, r, g, b) = ArgbDecode(color); + JSObject()->SetCData(XFA_Attribute::Value, + WideString::Format(L"%d,%d,%d", r, g, b), false, false); +} diff --git a/xfa/fxfa/parser/cxfa_color.h b/xfa/fxfa/parser/cxfa_color.h new file mode 100644 index 0000000000000000000000000000000000000000..b15c9d88061c7db424c5f2a2c45b4c02a2573ba0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_color.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COLOR_H_ +#define XFA_FXFA_PARSER_CXFA_COLOR_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Color : public CXFA_Node { + public: + static constexpr FX_ARGB kBlackColor = 0xFF000000; + + CXFA_Color(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Color() override; + + FX_ARGB GetValue(); + FX_ARGB GetValueOrDefault(FX_ARGB defaultValue); + void SetValue(FX_ARGB color); +}; + +#endif // XFA_FXFA_PARSER_CXFA_COLOR_H_ diff --git a/xfa/fxfa/parser/cxfa_comb.cpp b/xfa/fxfa/parser/cxfa_comb.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c427dded1ce15d76ddfff3b4e3c584f83319b566 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_comb.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_comb.h" + +#include "fxjs/xfa/cjx_comb.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::NumberOfCells, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"comb"; + +} // namespace + +CXFA_Comb::CXFA_Comb(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Comb, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Comb>(this)) {} + +CXFA_Comb::~CXFA_Comb() {} diff --git a/xfa/fxfa/parser/cxfa_comb.h b/xfa/fxfa/parser/cxfa_comb.h new file mode 100644 index 0000000000000000000000000000000000000000..1f2b538c2897121d5ae49a2aa498fd03488f4cfd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_comb.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMB_H_ +#define XFA_FXFA_PARSER_CXFA_COMB_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Comb : public CXFA_Node { + public: + CXFA_Comb(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Comb() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMB_H_ diff --git a/xfa/fxfa/parser/cxfa_command.cpp b/xfa/fxfa/parser/cxfa_command.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce385e1eb4dceb07670f6845cd71f1fa54021006 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_command.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_command.h" + +#include "fxjs/xfa/cjx_command.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Query, 1, 0}, + {XFA_Element::Insert, 1, 0}, + {XFA_Element::Update, 1, 0}, + {XFA_Element::Delete, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Timeout, XFA_AttributeType::Integer, (void*)30}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"command"; + +} // namespace + +CXFA_Command::CXFA_Command(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::Node, + XFA_Element::Command, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Command>(this)) {} + +CXFA_Command::~CXFA_Command() {} diff --git a/xfa/fxfa/parser/cxfa_command.h b/xfa/fxfa/parser/cxfa_command.h new file mode 100644 index 0000000000000000000000000000000000000000..88b74f3bb5dd2838c8ffba3bf600cd930083b069 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_command.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMMAND_H_ +#define XFA_FXFA_PARSER_CXFA_COMMAND_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Command : public CXFA_Node { + public: + CXFA_Command(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Command() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMMAND_H_ diff --git a/xfa/fxfa/parser/cxfa_common.cpp b/xfa/fxfa/parser/cxfa_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e95f02f48a9de5c777c918bb1013df5c41198e9d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_common.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_common.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::SuppressBanner, 1, 0}, + {XFA_Element::VersionControl, 1, 0}, + {XFA_Element::LocaleSet, 1, 0}, + {XFA_Element::Template, 1, 0}, + {XFA_Element::ValidationMessaging, 1, 0}, + {XFA_Element::Locale, 1, 0}, + {XFA_Element::Data, 1, 0}, + {XFA_Element::Messaging, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"common"; + +} // namespace + +CXFA_Common::CXFA_Common(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Common, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Common::~CXFA_Common() {} diff --git a/xfa/fxfa/parser/cxfa_common.h b/xfa/fxfa/parser/cxfa_common.h new file mode 100644 index 0000000000000000000000000000000000000000..d0ce0eae041254ccc093d9eeda24ee68077e83d5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_common.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMMON_H_ +#define XFA_FXFA_PARSER_CXFA_COMMON_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Common : public CXFA_Node { + public: + CXFA_Common(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Common() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMMON_H_ diff --git a/xfa/fxfa/parser/cxfa_compress.cpp b/xfa/fxfa/parser/cxfa_compress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72a3b9202ca15c6c437be59e16fdce3bccf2bf3e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compress.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_compress.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Scope, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ImageOnly}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"compress"; + +} // namespace + +CXFA_Compress::CXFA_Compress(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Compress, + nullptr, + kAttributeData, + kName) {} + +CXFA_Compress::~CXFA_Compress() {} diff --git a/xfa/fxfa/parser/cxfa_compress.h b/xfa/fxfa/parser/cxfa_compress.h new file mode 100644 index 0000000000000000000000000000000000000000..bec18830a25a7dac4e07f9588aa88b4fc6777164 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compress.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMPRESS_H_ +#define XFA_FXFA_PARSER_CXFA_COMPRESS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Compress : public CXFA_Node { + public: + CXFA_Compress(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Compress() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMPRESS_H_ diff --git a/xfa/fxfa/parser/cxfa_compression.cpp b/xfa/fxfa/parser/cxfa_compression.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d2bfde1b96a33fdae3e35301601f2efada750fe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compression.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_compression.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Level, 1, 0}, + {XFA_Element::Type, 1, 0}, + {XFA_Element::CompressObjectStream, 1, 0}, + {XFA_Element::CompressLogicalStructure, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"compression"; + +} // namespace + +CXFA_Compression::CXFA_Compression(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Compression, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Compression::~CXFA_Compression() {} diff --git a/xfa/fxfa/parser/cxfa_compression.h b/xfa/fxfa/parser/cxfa_compression.h new file mode 100644 index 0000000000000000000000000000000000000000..f0e26cb5e2d02d945c14a3b79ed95722e075b857 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compression.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMPRESSION_H_ +#define XFA_FXFA_PARSER_CXFA_COMPRESSION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Compression : public CXFA_Node { + public: + CXFA_Compression(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Compression() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMPRESSION_H_ diff --git a/xfa/fxfa/parser/cxfa_compresslogicalstructure.cpp b/xfa/fxfa/parser/cxfa_compresslogicalstructure.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9c2baf21c1f013c479cc878c537ad3e628afe49 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compresslogicalstructure.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_compresslogicalstructure.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"compressLogicalStructure"; + +} // namespace + +CXFA_CompressLogicalStructure::CXFA_CompressLogicalStructure( + CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::CompressLogicalStructure, + nullptr, + kAttributeData, + kName) {} + +CXFA_CompressLogicalStructure::~CXFA_CompressLogicalStructure() {} diff --git a/xfa/fxfa/parser/cxfa_compresslogicalstructure.h b/xfa/fxfa/parser/cxfa_compresslogicalstructure.h new file mode 100644 index 0000000000000000000000000000000000000000..a8b50681cd1d1f2966f9c6abab2b7ec271f7895b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compresslogicalstructure.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMPRESSLOGICALSTRUCTURE_H_ +#define XFA_FXFA_PARSER_CXFA_COMPRESSLOGICALSTRUCTURE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CompressLogicalStructure : public CXFA_Node { + public: + CXFA_CompressLogicalStructure(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CompressLogicalStructure() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMPRESSLOGICALSTRUCTURE_H_ diff --git a/xfa/fxfa/parser/cxfa_compressobjectstream.cpp b/xfa/fxfa/parser/cxfa_compressobjectstream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49eaed00d7544d745a3634294103ea8035855c9a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compressobjectstream.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_compressobjectstream.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"compressObjectStream"; + +} // namespace + +CXFA_CompressObjectStream::CXFA_CompressObjectStream(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::CompressObjectStream, + nullptr, + kAttributeData, + kName) {} + +CXFA_CompressObjectStream::~CXFA_CompressObjectStream() {} diff --git a/xfa/fxfa/parser/cxfa_compressobjectstream.h b/xfa/fxfa/parser/cxfa_compressobjectstream.h new file mode 100644 index 0000000000000000000000000000000000000000..94e02ce4cc4676d22d8ff55661f9492e95de6f3f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_compressobjectstream.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COMPRESSOBJECTSTREAM_H_ +#define XFA_FXFA_PARSER_CXFA_COMPRESSOBJECTSTREAM_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CompressObjectStream : public CXFA_Node { + public: + CXFA_CompressObjectStream(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CompressObjectStream() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COMPRESSOBJECTSTREAM_H_ diff --git a/xfa/fxfa/parser/cxfa_config.cpp b/xfa/fxfa/parser/cxfa_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79232a222384031bb3f9d049a0298a4777d5164d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_config.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_config.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Present, 1, 0}, + {XFA_Element::Acrobat, 1, 0}, + {XFA_Element::Trace, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"config"; + +} // namespace + +CXFA_Config::CXFA_Config(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ModelNode, + XFA_Element::Config, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Config::~CXFA_Config() {} diff --git a/xfa/fxfa/parser/cxfa_config.h b/xfa/fxfa/parser/cxfa_config.h new file mode 100644 index 0000000000000000000000000000000000000000..2ddb692f7dceff719bfe662df58f26848916727d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_config.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONFIG_H_ +#define XFA_FXFA_PARSER_CXFA_CONFIG_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Config : public CXFA_Node { + public: + CXFA_Config(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Config() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONFIG_H_ diff --git a/xfa/fxfa/parser/cxfa_conformance.cpp b/xfa/fxfa/parser/cxfa_conformance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f83c8eabb78dc50de14bab6f3e5a531861d0b286 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_conformance.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_conformance.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"conformance"; + +} // namespace + +CXFA_Conformance::CXFA_Conformance(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Conformance, + nullptr, + kAttributeData, + kName) {} + +CXFA_Conformance::~CXFA_Conformance() {} diff --git a/xfa/fxfa/parser/cxfa_conformance.h b/xfa/fxfa/parser/cxfa_conformance.h new file mode 100644 index 0000000000000000000000000000000000000000..11a72e7bffb94830d0e425affa8da57fa7c5b1ac --- /dev/null +++ b/xfa/fxfa/parser/cxfa_conformance.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONFORMANCE_H_ +#define XFA_FXFA_PARSER_CXFA_CONFORMANCE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Conformance : public CXFA_Node { + public: + CXFA_Conformance(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Conformance() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONFORMANCE_H_ diff --git a/xfa/fxfa/parser/cxfa_connect.cpp b/xfa/fxfa/parser/cxfa_connect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40648f4022bf49237ec1a72609f16ea473af2037 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_connect.cpp @@ -0,0 +1,49 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_connect.h" + +#include "fxjs/xfa/cjx_connect.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Picture, 1, 0}, + {XFA_Element::ConnectString, 1, 0}, + {XFA_Element::User, 1, 0}, + {XFA_Element::Password, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Timeout, XFA_AttributeType::Integer, (void*)15}, + {XFA_Attribute::Connection, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usage, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ExportAndImport}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DelayedOpen, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"connect"; + +} // namespace + +CXFA_Connect::CXFA_Connect(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | + XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Connect, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Connect>(this)) {} + +CXFA_Connect::~CXFA_Connect() {} diff --git a/xfa/fxfa/parser/cxfa_connect.h b/xfa/fxfa/parser/cxfa_connect.h new file mode 100644 index 0000000000000000000000000000000000000000..ac9157785b9d9b17895ec604c94927052cb34b3b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_connect.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONNECT_H_ +#define XFA_FXFA_PARSER_CXFA_CONNECT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Connect : public CXFA_Node { + public: + CXFA_Connect(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Connect() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONNECT_H_ diff --git a/xfa/fxfa/parser/cxfa_connectionset.cpp b/xfa/fxfa/parser/cxfa_connectionset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78f02e0a1c9ed335685bc25ca7b9babd79d86c8c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_connectionset.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_connectionset.h" + +#include "fxjs/xfa/cjx_model.h" +#include "third_party/base/ptr_util.h" + +namespace { + +constexpr wchar_t kName[] = L"connectionSet"; + +} // namespace + +CXFA_ConnectionSet::CXFA_ConnectionSet(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::ModelNode, + XFA_Element::ConnectionSet, + nullptr, + nullptr, + kName, + pdfium::MakeUnique<CJX_Model>(this)) {} + +CXFA_ConnectionSet::~CXFA_ConnectionSet() {} diff --git a/xfa/fxfa/parser/cxfa_connectionset.h b/xfa/fxfa/parser/cxfa_connectionset.h new file mode 100644 index 0000000000000000000000000000000000000000..59316f7b2ce12363ddabeccb09a57bdb135f657e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_connectionset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONNECTIONSET_H_ +#define XFA_FXFA_PARSER_CXFA_CONNECTIONSET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ConnectionSet : public CXFA_Node { + public: + CXFA_ConnectionSet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ConnectionSet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONNECTIONSET_H_ diff --git a/xfa/fxfa/parser/cxfa_connectstring.cpp b/xfa/fxfa/parser/cxfa_connectstring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87eb70d36510a10815b9884e3288a948aca0290f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_connectstring.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_connectstring.h" + +#include "fxjs/xfa/cjx_connectstring.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"connectString"; + +} // namespace + +CXFA_ConnectString::CXFA_ConnectString(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::ConnectString, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ConnectString>(this)) {} + +CXFA_ConnectString::~CXFA_ConnectString() {} diff --git a/xfa/fxfa/parser/cxfa_connectstring.h b/xfa/fxfa/parser/cxfa_connectstring.h new file mode 100644 index 0000000000000000000000000000000000000000..6c3a0b057751afbf94a38fbfeb9fb5297e445805 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_connectstring.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONNECTSTRING_H_ +#define XFA_FXFA_PARSER_CXFA_CONNECTSTRING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ConnectString : public CXFA_Node { + public: + CXFA_ConnectString(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ConnectString() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONNECTSTRING_H_ diff --git a/xfa/fxfa/parser/cxfa_containerlayoutitem.cpp b/xfa/fxfa/parser/cxfa_containerlayoutitem.cpp index 5ef29f14cfb6355e4077f2a5467324405f3c80ff..ee122b6770790aa5c85d26b670070ba4f637b95e 100644 --- a/xfa/fxfa/parser/cxfa_containerlayoutitem.cpp +++ b/xfa/fxfa/parser/cxfa_containerlayoutitem.cpp @@ -6,9 +6,12 @@ #include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" +#include "fxjs/xfa/cjx_object.h" #include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" #include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_medium.h" +#include "xfa/fxfa/parser/cxfa_node.h" CXFA_ContainerLayoutItem::CXFA_ContainerLayoutItem(CXFA_Node* pNode) : CXFA_LayoutItem(pNode, false), m_pOldSubform(nullptr) {} @@ -26,14 +29,19 @@ int32_t CXFA_ContainerLayoutItem::GetPageIndex() const { CFX_SizeF CXFA_ContainerLayoutItem::GetPageSize() const { CFX_SizeF size; - CXFA_Node* pMedium = m_pFormNode->GetFirstChildByClass(XFA_Element::Medium); + CXFA_Medium* pMedium = + m_pFormNode->GetFirstChildByClass<CXFA_Medium>(XFA_Element::Medium); if (!pMedium) return size; - size = CFX_SizeF(pMedium->GetMeasure(XFA_ATTRIBUTE_Short).ToUnit(XFA_UNIT_Pt), - pMedium->GetMeasure(XFA_ATTRIBUTE_Long).ToUnit(XFA_UNIT_Pt)); - if (pMedium->GetEnum(XFA_ATTRIBUTE_Orientation) == - XFA_ATTRIBUTEENUM_Landscape) { + size = CFX_SizeF(pMedium->JSObject() + ->GetMeasure(XFA_Attribute::Short) + .ToUnit(XFA_Unit::Pt), + pMedium->JSObject() + ->GetMeasure(XFA_Attribute::Long) + .ToUnit(XFA_Unit::Pt)); + if (pMedium->JSObject()->GetEnum(XFA_Attribute::Orientation) == + XFA_AttributeEnum::Landscape) { size = CFX_SizeF(size.height, size.width); } return size; diff --git a/xfa/fxfa/parser/cxfa_contentarea.cpp b/xfa/fxfa/parser/cxfa_contentarea.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48f52f70c9acb23093c0117999d29918a0000232 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_contentarea.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_contentarea.h" + +#include "fxjs/xfa/cjx_contentarea.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Desc, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::H, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::W, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"contentArea"; + +} // namespace + +CXFA_ContentArea::CXFA_ContentArea(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::ContentArea, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ContentArea>(this)) {} + +CXFA_ContentArea::~CXFA_ContentArea() {} diff --git a/xfa/fxfa/parser/cxfa_contentarea.h b/xfa/fxfa/parser/cxfa_contentarea.h new file mode 100644 index 0000000000000000000000000000000000000000..3c5ff60397439614a961b99081670476afeceb2d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_contentarea.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONTENTAREA_H_ +#define XFA_FXFA_PARSER_CXFA_CONTENTAREA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ContentArea : public CXFA_Node { + public: + CXFA_ContentArea(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ContentArea() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONTENTAREA_H_ diff --git a/xfa/fxfa/parser/cxfa_contentcopy.cpp b/xfa/fxfa/parser/cxfa_contentcopy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a55d57686cb58c7b2ae766f3d2cfc86ccc2c2baf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_contentcopy.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_contentcopy.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"contentCopy"; + +} // namespace + +CXFA_ContentCopy::CXFA_ContentCopy(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::ContentCopy, + nullptr, + kAttributeData, + kName) {} + +CXFA_ContentCopy::~CXFA_ContentCopy() {} diff --git a/xfa/fxfa/parser/cxfa_contentcopy.h b/xfa/fxfa/parser/cxfa_contentcopy.h new file mode 100644 index 0000000000000000000000000000000000000000..d394c747305e6705fdf63eec9ecdc911f853b1e3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_contentcopy.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CONTENTCOPY_H_ +#define XFA_FXFA_PARSER_CXFA_CONTENTCOPY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ContentCopy : public CXFA_Node { + public: + CXFA_ContentCopy(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ContentCopy() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CONTENTCOPY_H_ diff --git a/xfa/fxfa/parser/cxfa_contentlayoutitem.cpp b/xfa/fxfa/parser/cxfa_contentlayoutitem.cpp index a10a6782794647316605bb313abfdb92b138a51a..1ee364b9b71897a5ad92b5c47bf3c7bd573c8a09 100644 --- a/xfa/fxfa/parser/cxfa_contentlayoutitem.cpp +++ b/xfa/fxfa/parser/cxfa_contentlayoutitem.cpp @@ -6,6 +6,9 @@ #include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/parser/cxfa_node.h" + CXFA_ContentLayoutItem::CXFA_ContentLayoutItem(CXFA_Node* pNode) : CXFA_LayoutItem(pNode, true), m_pPrev(nullptr), @@ -13,6 +16,6 @@ CXFA_ContentLayoutItem::CXFA_ContentLayoutItem(CXFA_Node* pNode) m_dwStatus(0) {} CXFA_ContentLayoutItem::~CXFA_ContentLayoutItem() { - if (m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY) == this) - m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, nullptr); + if (m_pFormNode->JSObject()->GetLayoutItem() == this) + m_pFormNode->JSObject()->SetLayoutItem(nullptr); } diff --git a/xfa/fxfa/parser/cxfa_contentlayoutitem.h b/xfa/fxfa/parser/cxfa_contentlayoutitem.h index 9ac1dceb42559be329801d77a4fb965717ecc77a..500d3e4959f14c8d010e2965fa2f59f35d3c9b04 100644 --- a/xfa/fxfa/parser/cxfa_contentlayoutitem.h +++ b/xfa/fxfa/parser/cxfa_contentlayoutitem.h @@ -18,7 +18,7 @@ class CXFA_ContentLayoutItem : public CXFA_LayoutItem { CXFA_ContentLayoutItem* m_pNext; CFX_PointF m_sPos; CFX_SizeF m_sSize; - uint32_t m_dwStatus; + mutable uint32_t m_dwStatus; }; inline CXFA_ContentLayoutItem* ToContentLayoutItem(CXFA_LayoutItem* pItem) { diff --git a/xfa/fxfa/parser/cxfa_copies.cpp b/xfa/fxfa/parser/cxfa_copies.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ddf07ff242a9d5f50be16acb673a9be9d6df276 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_copies.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_copies.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"copies"; + +} // namespace + +CXFA_Copies::CXFA_Copies(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Copies, + nullptr, + kAttributeData, + kName) {} + +CXFA_Copies::~CXFA_Copies() {} diff --git a/xfa/fxfa/parser/cxfa_copies.h b/xfa/fxfa/parser/cxfa_copies.h new file mode 100644 index 0000000000000000000000000000000000000000..1ecd6160fcb1f45d02fbc7b85bc9ef1a68638f24 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_copies.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_COPIES_H_ +#define XFA_FXFA_PARSER_CXFA_COPIES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Copies : public CXFA_Node { + public: + CXFA_Copies(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Copies() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_COPIES_H_ diff --git a/xfa/fxfa/parser/cxfa_corner.cpp b/xfa/fxfa/parser/cxfa_corner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0cd3ef4fbce22f7faa057045e8d34ad6043f134b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_corner.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_corner.h" + +#include "fxjs/xfa/cjx_corner.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Color, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Stroke, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Solid}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::Inverted, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Thickness, XFA_AttributeType::Measure, (void*)L"0.5pt"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Join, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Square}, + {XFA_Attribute::Radius, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"corner"; + +} // namespace + +CXFA_Corner::CXFA_Corner(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Stroke(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Corner, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Corner>(this)) {} + +CXFA_Corner::~CXFA_Corner() {} diff --git a/xfa/fxfa/parser/cxfa_corner.h b/xfa/fxfa/parser/cxfa_corner.h index 7665c538123014b21d0178459b42a86f83631f43..1042729bcc387119473446982e17eb155c96b0b6 100644 --- a/xfa/fxfa/parser/cxfa_corner.h +++ b/xfa/fxfa/parser/cxfa_corner.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,11 +9,10 @@ #include "xfa/fxfa/parser/cxfa_stroke.h" -class CXFA_Node; - class CXFA_Corner : public CXFA_Stroke { public: - explicit CXFA_Corner(CXFA_Node* pNode) : CXFA_Stroke(pNode) {} + CXFA_Corner(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Corner() override; }; #endif // XFA_FXFA_PARSER_CXFA_CORNER_H_ diff --git a/xfa/fxfa/parser/cxfa_creator.cpp b/xfa/fxfa/parser/cxfa_creator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e65068595684b0e9d479f8d162746294f883dbb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_creator.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_creator.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"creator"; + +} // namespace + +CXFA_Creator::CXFA_Creator(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Creator, + nullptr, + kAttributeData, + kName) {} + +CXFA_Creator::~CXFA_Creator() {} diff --git a/xfa/fxfa/parser/cxfa_creator.h b/xfa/fxfa/parser/cxfa_creator.h new file mode 100644 index 0000000000000000000000000000000000000000..c046883431f71c3d00a6b3e5c5c33bc31bf688f9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_creator.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CREATOR_H_ +#define XFA_FXFA_PARSER_CXFA_CREATOR_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Creator : public CXFA_Node { + public: + CXFA_Creator(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Creator() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CREATOR_H_ diff --git a/xfa/fxfa/parser/cxfa_currencysymbol.cpp b/xfa/fxfa/parser/cxfa_currencysymbol.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de11f27f347e8f2b633e60167403e0aebf88bbe9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_currencysymbol.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_currencysymbol.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Symbol}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"currencySymbol"; + +} // namespace + +CXFA_CurrencySymbol::CXFA_CurrencySymbol(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::CurrencySymbol, + nullptr, + kAttributeData, + kName) {} + +CXFA_CurrencySymbol::~CXFA_CurrencySymbol() {} diff --git a/xfa/fxfa/parser/cxfa_currencysymbol.h b/xfa/fxfa/parser/cxfa_currencysymbol.h new file mode 100644 index 0000000000000000000000000000000000000000..271f7fc1e50268811c276149ef1bf141235826d8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_currencysymbol.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CURRENCYSYMBOL_H_ +#define XFA_FXFA_PARSER_CXFA_CURRENCYSYMBOL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CurrencySymbol : public CXFA_Node { + public: + CXFA_CurrencySymbol(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CurrencySymbol() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CURRENCYSYMBOL_H_ diff --git a/xfa/fxfa/parser/cxfa_currencysymbols.cpp b/xfa/fxfa/parser/cxfa_currencysymbols.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4160be98fc85e6c4a17215108bbb856f2eba54d3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_currencysymbols.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_currencysymbols.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::CurrencySymbol, 3, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"currencySymbols"; + +} // namespace + +CXFA_CurrencySymbols::CXFA_CurrencySymbols(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::CurrencySymbols, + kPropertyData, + nullptr, + kName) {} + +CXFA_CurrencySymbols::~CXFA_CurrencySymbols() {} diff --git a/xfa/fxfa/parser/cxfa_currencysymbols.h b/xfa/fxfa/parser/cxfa_currencysymbols.h new file mode 100644 index 0000000000000000000000000000000000000000..acd3f2a5e2f06597574cbc8b903b38405d0b4eeb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_currencysymbols.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CURRENCYSYMBOLS_H_ +#define XFA_FXFA_PARSER_CXFA_CURRENCYSYMBOLS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CurrencySymbols : public CXFA_Node { + public: + CXFA_CurrencySymbols(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CurrencySymbols() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CURRENCYSYMBOLS_H_ diff --git a/xfa/fxfa/parser/cxfa_currentpage.cpp b/xfa/fxfa/parser/cxfa_currentpage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be200e441003a9fcad7c9025c16a3b387f20e14d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_currentpage.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_currentpage.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"currentPage"; + +} // namespace + +CXFA_CurrentPage::CXFA_CurrentPage(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::CurrentPage, + nullptr, + kAttributeData, + kName) {} + +CXFA_CurrentPage::~CXFA_CurrentPage() {} diff --git a/xfa/fxfa/parser/cxfa_currentpage.h b/xfa/fxfa/parser/cxfa_currentpage.h new file mode 100644 index 0000000000000000000000000000000000000000..d526b4a6704d05aee9c7074049843011b08088d3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_currentpage.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_CURRENTPAGE_H_ +#define XFA_FXFA_PARSER_CXFA_CURRENTPAGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_CurrentPage : public CXFA_Node { + public: + CXFA_CurrentPage(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_CurrentPage() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_CURRENTPAGE_H_ diff --git a/xfa/fxfa/parser/cxfa_data.cpp b/xfa/fxfa/parser/cxfa_data.cpp index 19f85088b8dbb739c267dcd5415355b0ff64eeec..6fd66a98d4c441617787ddf140b86f882f2c4b78 100644 --- a/xfa/fxfa/parser/cxfa_data.cpp +++ b/xfa/fxfa/parser/cxfa_data.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,77 +6,32 @@ #include "xfa/fxfa/parser/cxfa_data.h" -#include "core/fxcrt/fx_ext.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_object.h" - -// Static. -FX_ARGB CXFA_Data::ToColor(const CFX_WideStringC& wsValue) { - uint8_t r = 0, g = 0, b = 0; - if (wsValue.GetLength() == 0) - return 0xff000000; - - int cc = 0; - const FX_WCHAR* str = wsValue.c_str(); - int len = wsValue.GetLength(); - while (FXSYS_iswspace(str[cc]) && cc < len) - cc++; - - if (cc >= len) - return 0xff000000; - - while (cc < len) { - if (str[cc] == ',' || !FXSYS_isDecimalDigit(str[cc])) - break; - - r = r * 10 + str[cc] - '0'; - cc++; - } - if (cc < len && str[cc] == ',') { - cc++; - while (FXSYS_iswspace(str[cc]) && cc < len) - cc++; - - while (cc < len) { - if (str[cc] == ',' || !FXSYS_isDecimalDigit(str[cc])) - break; - - g = g * 10 + str[cc] - '0'; - cc++; - } - if (cc < len && str[cc] == ',') { - cc++; - while (FXSYS_iswspace(str[cc]) && cc < len) - cc++; - - while (cc < len) { - if (str[cc] == ',' || !FXSYS_isDecimalDigit(str[cc])) - break; - - b = b * 10 + str[cc] - '0'; - cc++; - } - } - } - return (0xff << 24) | (r << 16) | (g << 8) | b; -} - -XFA_Element CXFA_Data::GetElementType() const { - return m_pNode ? m_pNode->GetElementType() : XFA_Element::Unknown; -} - -bool CXFA_Data::TryMeasure(XFA_ATTRIBUTE eAttr, - FX_FLOAT& fValue, - bool bUseDefault) const { - CXFA_Measurement ms; - if (m_pNode->TryMeasure(eAttr, ms, bUseDefault)) { - fValue = ms.ToUnit(XFA_UNIT_Pt); - return true; - } - return false; -} - -bool CXFA_Data::SetMeasure(XFA_ATTRIBUTE eAttr, FX_FLOAT fValue) { - CXFA_Measurement ms(fValue, XFA_UNIT_Pt); - return m_pNode->SetMeasure(eAttr, ms); -} +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Uri, 1, 0}, {XFA_Element::Xsl, 1, 0}, + {XFA_Element::StartNode, 1, 0}, {XFA_Element::OutputXSL, 1, 0}, + {XFA_Element::AdjustData, 1, 0}, {XFA_Element::Attributes, 1, 0}, + {XFA_Element::Window, 1, 0}, {XFA_Element::Record, 1, 0}, + {XFA_Element::Range, 1, 0}, {XFA_Element::IncrementalLoad, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"data"; + +} // namespace + +CXFA_Data::CXFA_Data(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Data, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Data::~CXFA_Data() {} diff --git a/xfa/fxfa/parser/cxfa_data.h b/xfa/fxfa/parser/cxfa_data.h index 890486d5fa5ea28c1606e35c0db64ef95a498f11..cb30f615f3c7800baa48b4ddb3d4b18133a96c1e 100644 --- a/xfa/fxfa/parser/cxfa_data.h +++ b/xfa/fxfa/parser/cxfa_data.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,29 +7,12 @@ #ifndef XFA_FXFA_PARSER_CXFA_DATA_H_ #define XFA_FXFA_PARSER_CXFA_DATA_H_ -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" -#include "xfa/fxfa/fxfa_basic.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Data { +class CXFA_Data : public CXFA_Node { public: - static FX_ARGB ToColor(const CFX_WideStringC& wsValue); - - explicit CXFA_Data(CXFA_Node* pNode) : m_pNode(pNode) {} - - operator bool() const { return !!m_pNode; } - CXFA_Node* GetNode() const { return m_pNode; } - XFA_Element GetElementType() const; - - protected: - bool TryMeasure(XFA_ATTRIBUTE eAttr, - FX_FLOAT& fValue, - bool bUseDefault = false) const; - bool SetMeasure(XFA_ATTRIBUTE eAttr, FX_FLOAT fValue); - - CXFA_Node* m_pNode; + CXFA_Data(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Data() override; }; #endif // XFA_FXFA_PARSER_CXFA_DATA_H_ diff --git a/xfa/fxfa/parser/cxfa_dataexporter.cpp b/xfa/fxfa/parser/cxfa_dataexporter.cpp index fe9947527d67c59aeb01dd591d6a6cfc3e749638..23fc17883a5fb71a3c62ed6a0dbcbdbc0cd96300 100644 --- a/xfa/fxfa/parser/cxfa_dataexporter.cpp +++ b/xfa/fxfa/parser/cxfa_dataexporter.cpp @@ -6,515 +6,78 @@ #include "xfa/fxfa/parser/cxfa_dataexporter.h" -#include <vector> - -#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/xml/cfx_xmldoc.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" #include "third_party/base/stl_util.h" -#include "xfa/fde/xml/fde_xml_imp.h" -#include "xfa/fgas/crt/fgas_codepage.h" #include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_widgetdata.h" -#include "xfa/fxfa/parser/xfa_object.h" - -namespace { - -CFX_WideString ExportEncodeAttribute(const CFX_WideString& str) { - CFX_WideTextBuf textBuf; - int32_t iLen = str.GetLength(); - for (int32_t i = 0; i < iLen; i++) { - switch (str[i]) { - case '&': - textBuf << L"&"; - break; - case '<': - textBuf << L"<"; - break; - case '>': - textBuf << L">"; - break; - case '\'': - textBuf << L"'"; - break; - case '\"': - textBuf << L"""; - break; - default: - textBuf.AppendChar(str[i]); - } - } - return textBuf.MakeString(); -} - -CFX_WideString ExportEncodeContent(const CFX_WideStringC& str) { - CFX_WideTextBuf textBuf; - int32_t iLen = str.GetLength(); - for (int32_t i = 0; i < iLen; i++) { - FX_WCHAR ch = str.GetAt(i); - if (!FDE_IsXMLValidChar(ch)) - continue; - - if (ch == '&') { - textBuf << L"&"; - } else if (ch == '<') { - textBuf << L"<"; - } else if (ch == '>') { - textBuf << L">"; - } else if (ch == '\'') { - textBuf << L"'"; - } else if (ch == '\"') { - textBuf << L"""; - } else if (ch == ' ') { - if (i && str.GetAt(i - 1) != ' ') { - textBuf.AppendChar(' '); - } else { - textBuf << L" "; - } - } else { - textBuf.AppendChar(str.GetAt(i)); - } - } - return textBuf.MakeString(); -} - -void SaveAttribute(CXFA_Node* pNode, - XFA_ATTRIBUTE eName, - const CFX_WideStringC& wsName, - bool bProto, - CFX_WideString& wsOutput) { - CFX_WideString wsValue; - if ((!bProto && !pNode->HasAttribute((XFA_ATTRIBUTE)eName, bProto)) || - !pNode->GetAttribute((XFA_ATTRIBUTE)eName, wsValue, false)) { - return; - } - wsValue = ExportEncodeAttribute(wsValue); - wsOutput += L" "; - wsOutput += wsName; - wsOutput += L"=\""; - wsOutput += wsValue; - wsOutput += L"\""; -} - -bool AttributeSaveInDataModel(CXFA_Node* pNode, XFA_ATTRIBUTE eAttribute) { - bool bSaveInDataModel = false; - if (pNode->GetElementType() != XFA_Element::Image) - return bSaveInDataModel; - - CXFA_Node* pValueNode = pNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!pValueNode || pValueNode->GetElementType() != XFA_Element::Value) - return bSaveInDataModel; - - CXFA_Node* pFieldNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent); - if (pFieldNode && pFieldNode->GetBindData() && - eAttribute == XFA_ATTRIBUTE_Href) { - bSaveInDataModel = true; - } - return bSaveInDataModel; -} - -bool ContentNodeNeedtoExport(CXFA_Node* pContentNode) { - CFX_WideString wsContent; - if (!pContentNode->TryContent(wsContent, false, false)) - return false; - - ASSERT(pContentNode->IsContentNode()); - CXFA_Node* pParentNode = pContentNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!pParentNode || pParentNode->GetElementType() != XFA_Element::Value) - return true; - - CXFA_Node* pGrandParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!pGrandParentNode || !pGrandParentNode->IsContainerNode()) - return true; - if (pGrandParentNode->GetBindData()) - return false; - - CXFA_WidgetData* pWidgetData = pGrandParentNode->GetWidgetData(); - XFA_Element eUIType = pWidgetData->GetUIType(); - if (eUIType == XFA_Element::PasswordEdit) - return false; - return true; -} - -void RecognizeXFAVersionNumber(CXFA_Node* pTemplateRoot, - CFX_WideString& wsVersionNumber) { - wsVersionNumber.clear(); - if (!pTemplateRoot) - return; - - CFX_WideString wsTemplateNS; - if (!pTemplateRoot->TryNamespace(wsTemplateNS)) - return; - - XFA_VERSION eVersion = - pTemplateRoot->GetDocument()->RecognizeXFAVersionNumber(wsTemplateNS); - if (eVersion == XFA_VERSION_UNKNOWN) - eVersion = XFA_VERSION_DEFAULT; - - wsVersionNumber.Format(L"%i.%i", eVersion / 100, eVersion % 100); -} - -void RegenerateFormFile_Changed(CXFA_Node* pNode, - CFX_WideTextBuf& buf, - bool bSaveXML) { - CFX_WideString wsAttrs; - int32_t iAttrs = 0; - const uint8_t* pAttrs = - XFA_GetElementAttributes(pNode->GetElementType(), iAttrs); - while (iAttrs--) { - const XFA_ATTRIBUTEINFO* pAttr = - XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]); - if (pAttr->eName == XFA_ATTRIBUTE_Name || - (AttributeSaveInDataModel(pNode, pAttr->eName) && !bSaveXML)) { - continue; - } - CFX_WideString wsAttr; - SaveAttribute(pNode, pAttr->eName, pAttr->pName, bSaveXML, wsAttr); - wsAttrs += wsAttr; - } - - CFX_WideString wsChildren; - switch (pNode->GetObjectType()) { - case XFA_ObjectType::ContentNode: { - if (!bSaveXML && !ContentNodeNeedtoExport(pNode)) - break; - - CXFA_Node* pRawValueNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pRawValueNode && - pRawValueNode->GetElementType() != XFA_Element::SharpxHTML && - pRawValueNode->GetElementType() != XFA_Element::Sharptext && - pRawValueNode->GetElementType() != XFA_Element::Sharpxml) { - pRawValueNode = pRawValueNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - if (!pRawValueNode) - break; - - CFX_WideString wsContentType; - pNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false); - if (pRawValueNode->GetElementType() == XFA_Element::SharpxHTML && - wsContentType == L"text/html") { - CFDE_XMLNode* pExDataXML = pNode->GetXMLMappingNode(); - if (!pExDataXML) - break; - - CFDE_XMLNode* pRichTextXML = - pExDataXML->GetNodeItem(CFDE_XMLNode::FirstChild); - if (!pRichTextXML) - break; - - CFX_RetainPtr<IFX_MemoryStream> pMemStream = - IFX_MemoryStream::Create(true); - - // Note: ambiguous without cast below. - CFX_RetainPtr<IFGAS_Stream> pTempStream = IFGAS_Stream::CreateStream( - CFX_RetainPtr<IFX_SeekableWriteStream>(pMemStream), - FX_STREAMACCESS_Text | FX_STREAMACCESS_Write | - FX_STREAMACCESS_Append); - - pTempStream->SetCodePage(FX_CODEPAGE_UTF8); - pRichTextXML->SaveXMLNode(pTempStream); - wsChildren += CFX_WideString::FromUTF8( - CFX_ByteStringC(pMemStream->GetBuffer(), pMemStream->GetSize())); - } else if (pRawValueNode->GetElementType() == XFA_Element::Sharpxml && - wsContentType == L"text/xml") { - CFX_WideString wsRawValue; - pRawValueNode->GetAttribute(XFA_ATTRIBUTE_Value, wsRawValue, false); - if (wsRawValue.IsEmpty()) - break; - - std::vector<CFX_WideString> wsSelTextArray; - int32_t iStart = 0; - int32_t iEnd = wsRawValue.Find(L'\n', iStart); - iEnd = (iEnd == -1) ? wsRawValue.GetLength() : iEnd; - while (iEnd >= iStart) { - wsSelTextArray.push_back(wsRawValue.Mid(iStart, iEnd - iStart)); - iStart = iEnd + 1; - if (iStart >= wsRawValue.GetLength()) - break; - - iEnd = wsRawValue.Find(L'\n', iStart); - } - CXFA_Node* pParentNode = pNode->GetNodeItem(XFA_NODEITEM_Parent); - ASSERT(pParentNode); - CXFA_Node* pGrandparentNode = - pParentNode->GetNodeItem(XFA_NODEITEM_Parent); - ASSERT(pGrandparentNode); - CFX_WideString bodyTagName; - bodyTagName = pGrandparentNode->GetCData(XFA_ATTRIBUTE_Name); - if (bodyTagName.IsEmpty()) - bodyTagName = L"ListBox1"; - - buf << L"<"; - buf << bodyTagName; - buf << L" xmlns=\"\"\n>"; - for (int32_t i = 0; i < pdfium::CollectionSize<int32_t>(wsSelTextArray); - i++) { - buf << L"<value\n>"; - buf << ExportEncodeContent(wsSelTextArray[i].AsStringC()); - buf << L"</value\n>"; - } - buf << L"</"; - buf << bodyTagName; - buf << L"\n>"; - wsChildren += buf.AsStringC(); - buf.Clear(); - } else { - CFX_WideStringC wsValue = pRawValueNode->GetCData(XFA_ATTRIBUTE_Value); - wsChildren += ExportEncodeContent(wsValue); - } - break; - } - case XFA_ObjectType::TextNode: - case XFA_ObjectType::NodeC: - case XFA_ObjectType::NodeV: { - CFX_WideStringC wsValue = pNode->GetCData(XFA_ATTRIBUTE_Value); - wsChildren += ExportEncodeContent(wsValue); - break; - } - default: - if (pNode->GetElementType() == XFA_Element::Items) { - CXFA_Node* pTemplateNode = pNode->GetTemplateNode(); - if (!pTemplateNode || - pTemplateNode->CountChildren(XFA_Element::Unknown) != - pNode->CountChildren(XFA_Element::Unknown)) { - bSaveXML = true; - } - } - CFX_WideTextBuf newBuf; - CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pChildNode) { - RegenerateFormFile_Changed(pChildNode, newBuf, bSaveXML); - wsChildren += newBuf.AsStringC(); - newBuf.Clear(); - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - if (!bSaveXML && !wsChildren.IsEmpty() && - pNode->GetElementType() == XFA_Element::Items) { - wsChildren.clear(); - bSaveXML = true; - CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pChild) { - RegenerateFormFile_Changed(pChild, newBuf, bSaveXML); - wsChildren += newBuf.AsStringC(); - newBuf.Clear(); - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - } - } - break; - } - - if (!wsChildren.IsEmpty() || !wsAttrs.IsEmpty() || - pNode->HasAttribute(XFA_ATTRIBUTE_Name)) { - CFX_WideStringC wsElement = pNode->GetClassName(); - CFX_WideString wsName; - SaveAttribute(pNode, XFA_ATTRIBUTE_Name, L"name", true, wsName); - buf << L"<"; - buf << wsElement; - buf << wsName; - buf << wsAttrs; - if (wsChildren.IsEmpty()) { - buf << L"\n/>"; - } else { - buf << L"\n>"; - buf << wsChildren; - buf << L"</"; - buf << wsElement; - buf << L"\n>"; - } - } -} - -void RegenerateFormFile_Container(CXFA_Node* pNode, - const CFX_RetainPtr<IFGAS_Stream>& pStream, - bool bSaveXML = false) { - XFA_Element eType = pNode->GetElementType(); - if (eType == XFA_Element::Field || eType == XFA_Element::Draw || - !pNode->IsContainerNode()) { - CFX_WideTextBuf buf; - RegenerateFormFile_Changed(pNode, buf, bSaveXML); - FX_STRSIZE nLen = buf.GetLength(); - if (nLen > 0) - pStream->WriteString((const FX_WCHAR*)buf.GetBuffer(), nLen); - return; - } - - CFX_WideStringC wsElement = pNode->GetClassName(); - pStream->WriteString(L"<", 1); - pStream->WriteString(wsElement.c_str(), wsElement.GetLength()); - CFX_WideString wsOutput; - SaveAttribute(pNode, XFA_ATTRIBUTE_Name, L"name", true, wsOutput); - CFX_WideString wsAttrs; - int32_t iAttrs = 0; - const uint8_t* pAttrs = - XFA_GetElementAttributes(pNode->GetElementType(), iAttrs); - while (iAttrs--) { - const XFA_ATTRIBUTEINFO* pAttr = - XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]); - if (pAttr->eName == XFA_ATTRIBUTE_Name) - continue; - - CFX_WideString wsAttr; - SaveAttribute(pNode, pAttr->eName, pAttr->pName, false, wsAttr); - wsOutput += wsAttr; - } - - if (!wsOutput.IsEmpty()) - pStream->WriteString(wsOutput.c_str(), wsOutput.GetLength()); - - CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pChildNode) { - pStream->WriteString(L"\n>", 2); - while (pChildNode) { - RegenerateFormFile_Container(pChildNode, pStream, bSaveXML); - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - pStream->WriteString(L"</", 2); - pStream->WriteString(wsElement.c_str(), wsElement.GetLength()); - pStream->WriteString(L"\n>", 2); - } else { - pStream->WriteString(L"\n/>", 3); - } -} - -} // namespace - -void XFA_DataExporter_RegenerateFormFile( - CXFA_Node* pNode, - const CFX_RetainPtr<IFGAS_Stream>& pStream, - const FX_CHAR* pChecksum, - bool bSaveXML) { - if (pNode->IsModelNode()) { - static const FX_WCHAR s_pwsTagName[] = L"<form"; - static const FX_WCHAR s_pwsClose[] = L"</form\n>"; - pStream->WriteString(s_pwsTagName, FXSYS_wcslen(s_pwsTagName)); - if (pChecksum) { - static const FX_WCHAR s_pwChecksum[] = L" checksum=\""; - CFX_WideString wsChecksum = CFX_WideString::FromUTF8(pChecksum); - pStream->WriteString(s_pwChecksum, FXSYS_wcslen(s_pwChecksum)); - pStream->WriteString(wsChecksum.c_str(), wsChecksum.GetLength()); - pStream->WriteString(L"\"", 1); - } - pStream->WriteString(L" xmlns=\"", FXSYS_wcslen(L" xmlns=\"")); - const FX_WCHAR* pURI = XFA_GetPacketByIndex(XFA_PACKET_Form)->pURI; - pStream->WriteString(pURI, FXSYS_wcslen(pURI)); - CFX_WideString wsVersionNumber; - RecognizeXFAVersionNumber( - ToNode(pNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Template)), - wsVersionNumber); - if (wsVersionNumber.IsEmpty()) - wsVersionNumber = L"2.8"; - - wsVersionNumber += L"/\"\n>"; - pStream->WriteString(wsVersionNumber.c_str(), wsVersionNumber.GetLength()); - CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pChildNode) { - RegenerateFormFile_Container(pChildNode, pStream); - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - pStream->WriteString(s_pwsClose, FXSYS_wcslen(s_pwsClose)); - } else { - RegenerateFormFile_Container(pNode, pStream, bSaveXML); - } -} - -void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode) { - if (!pDataNode || pDataNode->GetElementType() == XFA_Element::DataValue) - return; - - int32_t iChildNum = 0; - for (CXFA_Node* pChildNode = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pChildNode; - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - iChildNum++; - XFA_DataExporter_DealWithDataGroupNode(pChildNode); - } - - if (pDataNode->GetElementType() != XFA_Element::DataGroup) - return; - - if (iChildNum > 0) { - CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); - ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element); - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - if (pXMLElement->HasAttribute(L"xfa:dataNode")) - pXMLElement->RemoveAttribute(L"xfa:dataNode"); - - return; - } - - CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); - ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element); - static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode", - L"dataGroup"); -} +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/xfa_utils.h" CXFA_DataExporter::CXFA_DataExporter(CXFA_Document* pDocument) : m_pDocument(pDocument) { ASSERT(m_pDocument); } -bool CXFA_DataExporter::Export( - const CFX_RetainPtr<IFX_SeekableWriteStream>& pWrite) { +CXFA_DataExporter::~CXFA_DataExporter() {} + +bool CXFA_DataExporter::Export(const RetainPtr<IFX_SeekableStream>& pWrite) { return Export(pWrite, m_pDocument->GetRoot(), 0, nullptr); } -bool CXFA_DataExporter::Export( - const CFX_RetainPtr<IFX_SeekableWriteStream>& pWrite, - CXFA_Node* pNode, - uint32_t dwFlag, - const FX_CHAR* pChecksum) { +bool CXFA_DataExporter::Export(const RetainPtr<IFX_SeekableStream>& pWrite, + CXFA_Node* pNode, + uint32_t dwFlag, + const char* pChecksum) { ASSERT(pWrite); if (!pWrite) return false; - CFX_RetainPtr<IFGAS_Stream> pStream = IFGAS_Stream::CreateStream( - pWrite, - FX_STREAMACCESS_Text | FX_STREAMACCESS_Write | FX_STREAMACCESS_Append); - if (!pStream) - return false; - + auto pStream = pdfium::MakeRetain<CFX_SeekableStreamProxy>(pWrite, true); pStream->SetCodePage(FX_CODEPAGE_UTF8); return Export(pStream, pNode, dwFlag, pChecksum); } -bool CXFA_DataExporter::Export(const CFX_RetainPtr<IFGAS_Stream>& pStream, - CXFA_Node* pNode, - uint32_t dwFlag, - const FX_CHAR* pChecksum) { - CFDE_XMLDoc* pXMLDoc = m_pDocument->GetXMLDoc(); +bool CXFA_DataExporter::Export( + const RetainPtr<CFX_SeekableStreamProxy>& pStream, + CXFA_Node* pNode, + uint32_t dwFlag, + const char* pChecksum) { + CFX_XMLDoc* pXMLDoc = m_pDocument->GetXMLDoc(); if (pNode->IsModelNode()) { - switch (pNode->GetPacketID()) { - case XFA_XDPPACKET_XDP: { - static const FX_WCHAR s_pwsPreamble[] = - L"<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\">"; - pStream->WriteString(s_pwsPreamble, FXSYS_wcslen(s_pwsPreamble)); - for (CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + switch (pNode->GetPacketType()) { + case XFA_PacketType::Xdp: { + pStream->WriteString( + L"<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\">"); + for (CXFA_Node* pChild = pNode->GetFirstChild(); pChild; + pChild = pChild->GetNextSibling()) { Export(pStream, pChild, dwFlag, pChecksum); } - static const FX_WCHAR s_pwsPostamble[] = L"</xdp:xdp\n>"; - pStream->WriteString(s_pwsPostamble, FXSYS_wcslen(s_pwsPostamble)); + pStream->WriteString(L"</xdp:xdp\n>"); break; } - case XFA_XDPPACKET_Datasets: { - CFDE_XMLElement* pElement = - static_cast<CFDE_XMLElement*>(pNode->GetXMLMappingNode()); - if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) + case XFA_PacketType::Datasets: { + CFX_XMLElement* pElement = + static_cast<CFX_XMLElement*>(pNode->GetXMLMappingNode()); + if (!pElement || pElement->GetType() != FX_XMLNODE_Element) return false; - CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); + CXFA_Node* pDataNode = pNode->GetFirstChild(); ASSERT(pDataNode); XFA_DataExporter_DealWithDataGroupNode(pDataNode); pXMLDoc->SaveXMLNode(pStream, pElement); break; } - case XFA_XDPPACKET_Form: { - XFA_DataExporter_RegenerateFormFile(pNode, pStream, pChecksum); + case XFA_PacketType::Form: { + XFA_DataExporter_RegenerateFormFile(pNode, pStream, pChecksum, false); break; } - case XFA_XDPPACKET_Template: + case XFA_PacketType::Template: default: { - CFDE_XMLElement* pElement = - static_cast<CFDE_XMLElement*>(pNode->GetXMLMappingNode()); - if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) + CFX_XMLElement* pElement = + static_cast<CFX_XMLElement*>(pNode->GetXMLMappingNode()); + if (!pElement || pElement->GetType() != FX_XMLNODE_Element) return false; pXMLDoc->SaveXMLNode(pStream, pElement); @@ -524,19 +87,18 @@ bool CXFA_DataExporter::Export(const CFX_RetainPtr<IFGAS_Stream>& pStream, return true; } - CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pDataNode = pNode->GetParent(); CXFA_Node* pExportNode = pNode; - for (CXFA_Node* pChildNode = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pChildNode; - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pChildNode = pDataNode->GetFirstChild(); pChildNode; + pChildNode = pChildNode->GetNextSibling()) { if (pChildNode != pNode) { pExportNode = pDataNode; break; } } - CFDE_XMLElement* pElement = - static_cast<CFDE_XMLElement*>(pExportNode->GetXMLMappingNode()); - if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) + CFX_XMLElement* pElement = + static_cast<CFX_XMLElement*>(pExportNode->GetXMLMappingNode()); + if (!pElement || pElement->GetType() != FX_XMLNODE_Element) return false; XFA_DataExporter_DealWithDataGroupNode(pExportNode); diff --git a/xfa/fxfa/parser/cxfa_dataexporter.h b/xfa/fxfa/parser/cxfa_dataexporter.h index 0e5de0079639fcd55a33a284866eb5e91a1c70d0..a2a55b3c13af016b793bdad1338b0a843ebbe9bb 100644 --- a/xfa/fxfa/parser/cxfa_dataexporter.h +++ b/xfa/fxfa/parser/cxfa_dataexporter.h @@ -7,31 +7,32 @@ #ifndef XFA_FXFA_PARSER_CXFA_DATAEXPORTER_H_ #define XFA_FXFA_PARSER_CXFA_DATAEXPORTER_H_ -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" class CXFA_Document; class CXFA_Node; -class IFX_SeekableWriteStream; -class IFGAS_Stream; +class IFX_SeekableStream; +class CFX_SeekableStreamProxy; class CXFA_DataExporter { public: explicit CXFA_DataExporter(CXFA_Document* pDocument); + ~CXFA_DataExporter(); - bool Export(const CFX_RetainPtr<IFX_SeekableWriteStream>& pWrite); - bool Export(const CFX_RetainPtr<IFX_SeekableWriteStream>& pWrite, + bool Export(const RetainPtr<IFX_SeekableStream>& pWrite); + bool Export(const RetainPtr<IFX_SeekableStream>& pWrite, CXFA_Node* pNode, uint32_t dwFlag, - const FX_CHAR* pChecksum); + const char* pChecksum); - protected: - bool Export(const CFX_RetainPtr<IFGAS_Stream>& pStream, + private: + bool Export(const RetainPtr<CFX_SeekableStreamProxy>& pStream, CXFA_Node* pNode, uint32_t dwFlag, - const FX_CHAR* pChecksum); + const char* pChecksum); - CXFA_Document* const m_pDocument; + UnownedPtr<CXFA_Document> const m_pDocument; }; #endif // XFA_FXFA_PARSER_CXFA_DATAEXPORTER_H_ diff --git a/xfa/fxfa/parser/cxfa_datagroup.cpp b/xfa/fxfa/parser/cxfa_datagroup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b6514674b5391cc52aba8f1a491232ed662847a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datagroup.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datagroup.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dataGroup"; + +} // namespace + +CXFA_DataGroup::CXFA_DataGroup(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Datasets, + XFA_ObjectType::Node, + XFA_Element::DataGroup, + nullptr, + kAttributeData, + kName) {} + +CXFA_DataGroup::~CXFA_DataGroup() {} diff --git a/xfa/fxfa/parser/cxfa_datagroup.h b/xfa/fxfa/parser/cxfa_datagroup.h new file mode 100644 index 0000000000000000000000000000000000000000..649b09621d71929175ded935fa993a1c141f1b84 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datagroup.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATAGROUP_H_ +#define XFA_FXFA_PARSER_CXFA_DATAGROUP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DataGroup : public CXFA_Node { + public: + CXFA_DataGroup(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DataGroup() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATAGROUP_H_ diff --git a/xfa/fxfa/parser/cxfa_dataimporter.cpp b/xfa/fxfa/parser/cxfa_dataimporter.cpp index 0199028ecd6fdf3f4d6f8c38fb10933017d85da6..9171b007509debec582398e59bc910d3f677a839 100644 --- a/xfa/fxfa/parser/cxfa_dataimporter.cpp +++ b/xfa/fxfa/parser/cxfa_dataimporter.cpp @@ -9,28 +9,30 @@ #include <memory> #include "core/fxcrt/fx_stream.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" #include "third_party/base/ptr_util.h" -#include "xfa/fde/xml/fde_xml_imp.h" #include "xfa/fxfa/fxfa.h" #include "xfa/fxfa/fxfa_basic.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" #include "xfa/fxfa/parser/cxfa_simple_parser.h" -#include "xfa/fxfa/parser/xfa_object.h" CXFA_DataImporter::CXFA_DataImporter(CXFA_Document* pDocument) : m_pDocument(pDocument) { ASSERT(m_pDocument); } +CXFA_DataImporter::~CXFA_DataImporter() {} + bool CXFA_DataImporter::ImportData( - const CFX_RetainPtr<IFX_SeekableReadStream>& pDataDocument) { + const RetainPtr<IFX_SeekableStream>& pDataDocument) { auto pDataDocumentParser = - pdfium::MakeUnique<CXFA_SimpleParser>(m_pDocument, false); - if (pDataDocumentParser->StartParse(pDataDocument, XFA_XDPPACKET_Datasets) != - XFA_PARSESTATUS_Ready) { + pdfium::MakeUnique<CXFA_SimpleParser>(m_pDocument.Get()); + if (pDataDocumentParser->StartParse( + pDataDocument, XFA_PacketType::Datasets) != XFA_PARSESTATUS_Ready) { return false; } - if (pDataDocumentParser->DoParse(nullptr) < XFA_PARSESTATUS_Done) + if (pDataDocumentParser->DoParse() < XFA_PARSESTATUS_Done) return false; CXFA_Node* pImportDataRoot = pDataDocumentParser->GetRootNode(); @@ -44,20 +46,19 @@ bool CXFA_DataImporter::ImportData( CXFA_Node* pDataNode = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Data)); if (pDataNode) - pDataModel->RemoveChild(pDataNode); + pDataModel->RemoveChild(pDataNode, true); if (pImportDataRoot->GetElementType() == XFA_Element::DataModel) { - while (CXFA_Node* pChildNode = - pImportDataRoot->GetNodeItem(XFA_NODEITEM_FirstChild)) { - pImportDataRoot->RemoveChild(pChildNode); - pDataModel->InsertChild(pChildNode); + while (CXFA_Node* pChildNode = pImportDataRoot->GetFirstChild()) { + pImportDataRoot->RemoveChild(pChildNode, true); + pDataModel->InsertChild(pChildNode, nullptr); } } else { - CFDE_XMLNode* pXMLNode = pImportDataRoot->GetXMLMappingNode(); - CFDE_XMLNode* pParentXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::Parent); + CFX_XMLNode* pXMLNode = pImportDataRoot->GetXMLMappingNode(); + CFX_XMLNode* pParentXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::Parent); if (pParentXMLNode) pParentXMLNode->RemoveChildNode(pXMLNode); - pDataModel->InsertChild(pImportDataRoot); + pDataModel->InsertChild(pImportDataRoot, nullptr); } m_pDocument->DoDataRemerge(false); return true; diff --git a/xfa/fxfa/parser/cxfa_dataimporter.h b/xfa/fxfa/parser/cxfa_dataimporter.h index bf04b05846dec994a5c6c8bfc1d6086287d5df2d..ca5896eb55ded39e64ddc11727acab5b3dab7388 100644 --- a/xfa/fxfa/parser/cxfa_dataimporter.h +++ b/xfa/fxfa/parser/cxfa_dataimporter.h @@ -7,20 +7,22 @@ #ifndef XFA_FXFA_PARSER_CXFA_DATAIMPORTER_H_ #define XFA_FXFA_PARSER_CXFA_DATAIMPORTER_H_ -#include "core/fxcrt/cfx_retain_ptr.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/retain_ptr.h" +#include "core/fxcrt/unowned_ptr.h" class CXFA_Document; -class IFX_SeekableReadStream; +class IFX_SeekableStream; class CXFA_DataImporter { public: explicit CXFA_DataImporter(CXFA_Document* pDocument); + ~CXFA_DataImporter(); - bool ImportData(const CFX_RetainPtr<IFX_SeekableReadStream>& pDataDocument); + bool ImportData(const RetainPtr<IFX_SeekableStream>& pDataDocument); - protected: - CXFA_Document* const m_pDocument; + private: + UnownedPtr<CXFA_Document> const m_pDocument; }; #endif // XFA_FXFA_PARSER_CXFA_DATAIMPORTER_H_ diff --git a/xfa/fxfa/parser/cxfa_datamodel.cpp b/xfa/fxfa/parser/cxfa_datamodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..686ba4c4cc6c737960d747fbb2ff34d4cf9c0bb5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datamodel.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datamodel.h" + +#include "fxjs/xfa/cjx_model.h" +#include "third_party/base/ptr_util.h" + +namespace { + +constexpr wchar_t kName[] = L"dataModel"; + +} // namespace + +CXFA_DataModel::CXFA_DataModel(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Datasets, + XFA_ObjectType::ModelNode, + XFA_Element::DataModel, + nullptr, + nullptr, + kName, + pdfium::MakeUnique<CJX_Model>(this)) {} + +CXFA_DataModel::~CXFA_DataModel() {} diff --git a/xfa/fxfa/parser/cxfa_datamodel.h b/xfa/fxfa/parser/cxfa_datamodel.h new file mode 100644 index 0000000000000000000000000000000000000000..f414ea350fa5446b3a95daace07028da0b92d00b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datamodel.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATAMODEL_H_ +#define XFA_FXFA_PARSER_CXFA_DATAMODEL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DataModel : public CXFA_Node { + public: + CXFA_DataModel(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DataModel() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATAMODEL_H_ diff --git a/xfa/fxfa/parser/cxfa_datavalue.cpp b/xfa/fxfa/parser/cxfa_datavalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2ebaf0389e61eec8295cce57560aea32df576e7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datavalue.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datavalue.h" + +#include "fxjs/xfa/cjx_datavalue.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ContentType, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Contains, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Data}, + {XFA_Attribute::Value, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::IsNull, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dataValue"; + +} // namespace + +CXFA_DataValue::CXFA_DataValue(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Datasets, + XFA_ObjectType::Node, + XFA_Element::DataValue, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_DataValue>(this)) {} + +CXFA_DataValue::~CXFA_DataValue() {} diff --git a/xfa/fxfa/parser/cxfa_datavalue.h b/xfa/fxfa/parser/cxfa_datavalue.h new file mode 100644 index 0000000000000000000000000000000000000000..8170aba0b76caa7a2c6ba378736cb0621973072e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datavalue.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATAVALUE_H_ +#define XFA_FXFA_PARSER_CXFA_DATAVALUE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DataValue : public CXFA_Node { + public: + CXFA_DataValue(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DataValue() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATAVALUE_H_ diff --git a/xfa/fxfa/parser/cxfa_date.cpp b/xfa/fxfa/parser/cxfa_date.cpp new file mode 100644 index 0000000000000000000000000000000000000000..984ab3251344691a70adbd2f822cc77029042589 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_date.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_date.h" + +#include "fxjs/xfa/cjx_date.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"date"; + +} // namespace + +CXFA_Date::CXFA_Date(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Date, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Date>(this)) {} + +CXFA_Date::~CXFA_Date() {} diff --git a/xfa/fxfa/parser/cxfa_date.h b/xfa/fxfa/parser/cxfa_date.h new file mode 100644 index 0000000000000000000000000000000000000000..e5ebb25ccb69c2581ea44bcc6f1d83a3bffdb5a6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_date.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATE_H_ +#define XFA_FXFA_PARSER_CXFA_DATE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Date : public CXFA_Node { + public: + CXFA_Date(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Date() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATE_H_ diff --git a/xfa/fxfa/parser/cxfa_datepattern.cpp b/xfa/fxfa/parser/cxfa_datepattern.cpp new file mode 100644 index 0000000000000000000000000000000000000000..237874bf7c686c39065db2abaa21dc42f893ac35 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datepattern.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datepattern.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Med}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"datePattern"; + +} // namespace + +CXFA_DatePattern::CXFA_DatePattern(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::DatePattern, + nullptr, + kAttributeData, + kName) {} + +CXFA_DatePattern::~CXFA_DatePattern() {} diff --git a/xfa/fxfa/parser/cxfa_datepattern.h b/xfa/fxfa/parser/cxfa_datepattern.h new file mode 100644 index 0000000000000000000000000000000000000000..b66147851f96268d19e23fc972f4550651efdd05 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datepattern.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATEPATTERN_H_ +#define XFA_FXFA_PARSER_CXFA_DATEPATTERN_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DatePattern : public CXFA_Node { + public: + CXFA_DatePattern(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DatePattern() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATEPATTERN_H_ diff --git a/xfa/fxfa/parser/cxfa_datepatterns.cpp b/xfa/fxfa/parser/cxfa_datepatterns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37a380daeac3a37833d645b94601998a9ef0818b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datepatterns.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datepatterns.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::DatePattern, 4, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"datePatterns"; + +} // namespace + +CXFA_DatePatterns::CXFA_DatePatterns(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::DatePatterns, + kPropertyData, + nullptr, + kName) {} + +CXFA_DatePatterns::~CXFA_DatePatterns() {} diff --git a/xfa/fxfa/parser/cxfa_datepatterns.h b/xfa/fxfa/parser/cxfa_datepatterns.h new file mode 100644 index 0000000000000000000000000000000000000000..dfc55d08d3426a9633acdcf49c0f3da01f9d8148 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datepatterns.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATEPATTERNS_H_ +#define XFA_FXFA_PARSER_CXFA_DATEPATTERNS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DatePatterns : public CXFA_Node { + public: + CXFA_DatePatterns(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DatePatterns() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATEPATTERNS_H_ diff --git a/xfa/fxfa/parser/cxfa_datetime.cpp b/xfa/fxfa/parser/cxfa_datetime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..809e40c6ac1717d05a6b64224e2dbd959fa29b3c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datetime.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datetime.h" + +#include "fxjs/xfa/cjx_datetime.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dateTime"; + +} // namespace + +CXFA_DateTime::CXFA_DateTime(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::DateTime, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_DateTime>(this)) {} + +CXFA_DateTime::~CXFA_DateTime() {} diff --git a/xfa/fxfa/parser/cxfa_datetime.h b/xfa/fxfa/parser/cxfa_datetime.h new file mode 100644 index 0000000000000000000000000000000000000000..f5cd6f680e495f546d1a384f7f6104ae69c65dc7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datetime.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATETIME_H_ +#define XFA_FXFA_PARSER_CXFA_DATETIME_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DateTime : public CXFA_Node { + public: + CXFA_DateTime(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DateTime() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATETIME_H_ diff --git a/xfa/fxfa/parser/cxfa_datetimeedit.cpp b/xfa/fxfa/parser/cxfa_datetimeedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c9a8040ec0d44a98a72dbf32b078b4a64c054e4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datetimeedit.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datetimeedit.h" + +#include "fxjs/xfa/cjx_datetimeedit.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Comb, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Picker, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Host}, + {XFA_Attribute::HScrollPolicy, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dateTimeEdit"; + +} // namespace + +CXFA_DateTimeEdit::CXFA_DateTimeEdit(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::DateTimeEdit, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_DateTimeEdit>(this)) {} + +CXFA_DateTimeEdit::~CXFA_DateTimeEdit() {} diff --git a/xfa/fxfa/parser/cxfa_datetimeedit.h b/xfa/fxfa/parser/cxfa_datetimeedit.h new file mode 100644 index 0000000000000000000000000000000000000000..bac7879cdbac7c7e06d9abdcba0413a880d3dcc8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datetimeedit.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATETIMEEDIT_H_ +#define XFA_FXFA_PARSER_CXFA_DATETIMEEDIT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DateTimeEdit : public CXFA_Node { + public: + CXFA_DateTimeEdit(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DateTimeEdit() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATETIMEEDIT_H_ diff --git a/xfa/fxfa/parser/cxfa_datetimesymbols.cpp b/xfa/fxfa/parser/cxfa_datetimesymbols.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f296665641b02ef78673e6a13cd99ef95cc437f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datetimesymbols.cpp @@ -0,0 +1,26 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_datetimesymbols.h" + +namespace { + +constexpr wchar_t kName[] = L"dateTimeSymbols"; + +} // namespace + +CXFA_DateTimeSymbols::CXFA_DateTimeSymbols(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::DateTimeSymbols, + nullptr, + nullptr, + kName) {} + +CXFA_DateTimeSymbols::~CXFA_DateTimeSymbols() {} diff --git a/xfa/fxfa/parser/cxfa_datetimesymbols.h b/xfa/fxfa/parser/cxfa_datetimesymbols.h new file mode 100644 index 0000000000000000000000000000000000000000..e2296d6fd91c39919c85c2f741788123997a3ec1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_datetimesymbols.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DATETIMESYMBOLS_H_ +#define XFA_FXFA_PARSER_CXFA_DATETIMESYMBOLS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DateTimeSymbols : public CXFA_Node { + public: + CXFA_DateTimeSymbols(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DateTimeSymbols() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DATETIMESYMBOLS_H_ diff --git a/xfa/fxfa/parser/cxfa_day.cpp b/xfa/fxfa/parser/cxfa_day.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c08b820e0b1cc89b64a9d2b511dad3eeed9ae992 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_day.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_day.h" + +namespace { + +constexpr wchar_t kName[] = L"day"; + +} // namespace + +CXFA_Day::CXFA_Day(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::Day, + nullptr, + nullptr, + kName) {} + +CXFA_Day::~CXFA_Day() {} diff --git a/xfa/fxfa/parser/cxfa_day.h b/xfa/fxfa/parser/cxfa_day.h new file mode 100644 index 0000000000000000000000000000000000000000..8d04bf4fb7e1a10b95bf968f6bd12da4665ecf64 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_day.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DAY_H_ +#define XFA_FXFA_PARSER_CXFA_DAY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Day : public CXFA_Node { + public: + CXFA_Day(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Day() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DAY_H_ diff --git a/xfa/fxfa/parser/cxfa_daynames.cpp b/xfa/fxfa/parser/cxfa_daynames.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47468e97433879c11e099c14b4e301fad52d0095 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_daynames.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_daynames.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Day, 7, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Abbr, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dayNames"; + +} // namespace + +CXFA_DayNames::CXFA_DayNames(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::DayNames, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_DayNames::~CXFA_DayNames() {} diff --git a/xfa/fxfa/parser/cxfa_daynames.h b/xfa/fxfa/parser/cxfa_daynames.h new file mode 100644 index 0000000000000000000000000000000000000000..d566e50e70955744cf037468d4220538dd336a63 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_daynames.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DAYNAMES_H_ +#define XFA_FXFA_PARSER_CXFA_DAYNAMES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DayNames : public CXFA_Node { + public: + CXFA_DayNames(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DayNames() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DAYNAMES_H_ diff --git a/xfa/fxfa/parser/cxfa_debug.cpp b/xfa/fxfa/parser/cxfa_debug.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91cfd6302b4a80ecfffd7071a997344e3c79c368 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_debug.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_debug.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Uri, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"debug"; + +} // namespace + +CXFA_Debug::CXFA_Debug(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Debug, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Debug::~CXFA_Debug() {} diff --git a/xfa/fxfa/parser/cxfa_debug.h b/xfa/fxfa/parser/cxfa_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..e2e4ed19c40ddeb5acc5eb10db7793749bade117 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_debug.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DEBUG_H_ +#define XFA_FXFA_PARSER_CXFA_DEBUG_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Debug : public CXFA_Node { + public: + CXFA_Debug(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Debug() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DEBUG_H_ diff --git a/xfa/fxfa/parser/cxfa_decimal.cpp b/xfa/fxfa/parser/cxfa_decimal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c887e8d121e10950a5ed1554b638815c0e680c6e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_decimal.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_decimal.h" + +#include "fxjs/xfa/cjx_decimal.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::FracDigits, XFA_AttributeType::Integer, (void*)2}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::LeadDigits, XFA_AttributeType::Integer, (void*)-1}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"decimal"; + +} // namespace + +CXFA_Decimal::CXFA_Decimal(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Decimal, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Decimal>(this)) {} + +CXFA_Decimal::~CXFA_Decimal() {} diff --git a/xfa/fxfa/parser/cxfa_decimal.h b/xfa/fxfa/parser/cxfa_decimal.h new file mode 100644 index 0000000000000000000000000000000000000000..da588964be737382fd6126eb1c7f9fc975aa54ec --- /dev/null +++ b/xfa/fxfa/parser/cxfa_decimal.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DECIMAL_H_ +#define XFA_FXFA_PARSER_CXFA_DECIMAL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Decimal : public CXFA_Node { + public: + CXFA_Decimal(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Decimal() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DECIMAL_H_ diff --git a/xfa/fxfa/parser/cxfa_defaulttypeface.cpp b/xfa/fxfa/parser/cxfa_defaulttypeface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60da7867a781f34de16bbd4ee376faad9f88e45a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_defaulttypeface.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_defaulttypeface.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::WritingScript, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Asterisk}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"defaultTypeface"; + +} // namespace + +CXFA_DefaultTypeface::CXFA_DefaultTypeface(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::DefaultTypeface, + nullptr, + kAttributeData, + kName) {} + +CXFA_DefaultTypeface::~CXFA_DefaultTypeface() {} diff --git a/xfa/fxfa/parser/cxfa_defaulttypeface.h b/xfa/fxfa/parser/cxfa_defaulttypeface.h new file mode 100644 index 0000000000000000000000000000000000000000..511ed8f8f24cba1a4710972ec4432140ec22f268 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_defaulttypeface.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DEFAULTTYPEFACE_H_ +#define XFA_FXFA_PARSER_CXFA_DEFAULTTYPEFACE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DefaultTypeface : public CXFA_Node { + public: + CXFA_DefaultTypeface(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DefaultTypeface() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DEFAULTTYPEFACE_H_ diff --git a/xfa/fxfa/parser/cxfa_defaultui.cpp b/xfa/fxfa/parser/cxfa_defaultui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9400847f1c0fe7c2a49f9e133c13c628a6e6922 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_defaultui.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_defaultui.h" + +#include "fxjs/xfa/cjx_defaultui.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"defaultUi"; + +} // namespace + +CXFA_DefaultUi::CXFA_DefaultUi(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::DefaultUi, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_DefaultUi::~CXFA_DefaultUi() {} diff --git a/xfa/fxfa/parser/cxfa_defaultui.h b/xfa/fxfa/parser/cxfa_defaultui.h new file mode 100644 index 0000000000000000000000000000000000000000..ce149410d8e9db78378f7e4c4b5f7edb43e67135 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_defaultui.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DEFAULTUI_H_ +#define XFA_FXFA_PARSER_CXFA_DEFAULTUI_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DefaultUi : public CXFA_Node { + public: + CXFA_DefaultUi(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DefaultUi() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DEFAULTUI_H_ diff --git a/xfa/fxfa/parser/cxfa_delete.cpp b/xfa/fxfa/parser/cxfa_delete.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8477fa99f6b3f22e7b098e395cf369a90c936819 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_delete.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_delete.h" + +#include "fxjs/xfa/cjx_delete.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"delete"; + +} // namespace + +CXFA_Delete::CXFA_Delete(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::Delete, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Delete>(this)) {} + +CXFA_Delete::~CXFA_Delete() {} diff --git a/xfa/fxfa/parser/cxfa_delete.h b/xfa/fxfa/parser/cxfa_delete.h new file mode 100644 index 0000000000000000000000000000000000000000..7c6058ab4f765074d16c85124a0f9b0c1881bb2a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_delete.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DELETE_H_ +#define XFA_FXFA_PARSER_CXFA_DELETE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Delete : public CXFA_Node { + public: + CXFA_Delete(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Delete() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DELETE_H_ diff --git a/xfa/fxfa/parser/cxfa_delta.cpp b/xfa/fxfa/parser/cxfa_delta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b5bf77d7d6290618483ae20d6d705ed2b05efbe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_delta.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_delta.h" + +#include "fxjs/xfa/cjx_delta.h" +#include "third_party/base/ptr_util.h" + +namespace { + +constexpr wchar_t kName[] = L"delta"; + +} // namespace + +CXFA_Delta::CXFA_Delta(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Form, + XFA_ObjectType::Object, + XFA_Element::Delta, + nullptr, + nullptr, + kName, + pdfium::MakeUnique<CJX_Delta>(this)) {} + +CXFA_Delta::~CXFA_Delta() {} diff --git a/xfa/fxfa/parser/cxfa_delta.h b/xfa/fxfa/parser/cxfa_delta.h new file mode 100644 index 0000000000000000000000000000000000000000..693287ba3f1c049e7c12c93276ef143ca0c890f2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_delta.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DELTA_H_ +#define XFA_FXFA_PARSER_CXFA_DELTA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Delta : public CXFA_Node { + public: + CXFA_Delta(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Delta() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DELTA_H_ diff --git a/xfa/fxfa/parser/cxfa_deltas.cpp b/xfa/fxfa/parser/cxfa_deltas.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4db0936ba35bbae42d0f8e3a34b082d2aea80943 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_deltas.cpp @@ -0,0 +1,15 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_deltas.h" + +#include "fxjs/xfa/cjx_deltas.h" +#include "third_party/base/ptr_util.h" + +CXFA_Deltas::CXFA_Deltas(CXFA_Document* doc) + : CXFA_List(doc, pdfium::MakeUnique<CJX_Deltas>(this)) {} + +CXFA_Deltas::~CXFA_Deltas() {} diff --git a/xfa/fxfa/parser/cxfa_deltas.h b/xfa/fxfa/parser/cxfa_deltas.h new file mode 100644 index 0000000000000000000000000000000000000000..4c00e9e284b486ddcc5fb5c07547e73edc4dae53 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_deltas.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DELTAS_H_ +#define XFA_FXFA_PARSER_CXFA_DELTAS_H_ + +#include "xfa/fxfa/parser/cxfa_list.h" + +class CXFA_Deltas : public CXFA_List { + public: + explicit CXFA_Deltas(CXFA_Document* doc); + ~CXFA_Deltas() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DELTAS_H_ diff --git a/xfa/fxfa/parser/cxfa_desc.cpp b/xfa/fxfa/parser/cxfa_desc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cda06dd47889d37ae6b4704b37132ae7fa07ed2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_desc.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_desc.h" + +#include "fxjs/xfa/cjx_desc.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Text, 1, 0}, {XFA_Element::Time, 1, 0}, + {XFA_Element::DateTime, 1, 0}, {XFA_Element::Image, 1, 0}, + {XFA_Element::Decimal, 1, 0}, {XFA_Element::Boolean, 1, 0}, + {XFA_Element::Integer, 1, 0}, {XFA_Element::ExData, 1, 0}, + {XFA_Element::Date, 1, 0}, {XFA_Element::Float, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"desc"; + +} // namespace + +CXFA_Desc::CXFA_Desc(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Desc, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Desc>(this)) {} + +CXFA_Desc::~CXFA_Desc() {} diff --git a/xfa/fxfa/parser/cxfa_desc.h b/xfa/fxfa/parser/cxfa_desc.h new file mode 100644 index 0000000000000000000000000000000000000000..1811c630024f95a98e3c1edfe1409acbd82c0a8c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_desc.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DESC_H_ +#define XFA_FXFA_PARSER_CXFA_DESC_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Desc : public CXFA_Node { + public: + CXFA_Desc(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Desc() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DESC_H_ diff --git a/xfa/fxfa/parser/cxfa_destination.cpp b/xfa/fxfa/parser/cxfa_destination.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e5d10b2434c71224c13d4b187abbf24504708b2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_destination.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_destination.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"destination"; + +} // namespace + +CXFA_Destination::CXFA_Destination(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Destination, + nullptr, + kAttributeData, + kName) {} + +CXFA_Destination::~CXFA_Destination() {} diff --git a/xfa/fxfa/parser/cxfa_destination.h b/xfa/fxfa/parser/cxfa_destination.h new file mode 100644 index 0000000000000000000000000000000000000000..d9fc55329c16c92447730a111dc5f89f35e5727a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_destination.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DESTINATION_H_ +#define XFA_FXFA_PARSER_CXFA_DESTINATION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Destination : public CXFA_Node { + public: + CXFA_Destination(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Destination() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DESTINATION_H_ diff --git a/xfa/fxfa/parser/cxfa_digestmethod.cpp b/xfa/fxfa/parser/cxfa_digestmethod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e74832e1604b4ac68ba931df083f04d8d6428735 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_digestmethod.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_digestmethod.h" + +#include "fxjs/xfa/cjx_digestmethod.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"digestMethod"; + +} // namespace + +CXFA_DigestMethod::CXFA_DigestMethod(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeC, + XFA_Element::DigestMethod, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_DigestMethod>(this)) {} + +CXFA_DigestMethod::~CXFA_DigestMethod() {} diff --git a/xfa/fxfa/parser/cxfa_digestmethod.h b/xfa/fxfa/parser/cxfa_digestmethod.h new file mode 100644 index 0000000000000000000000000000000000000000..4ac22bb06abe08a14b8c552fe370311eb65d7125 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_digestmethod.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DIGESTMETHOD_H_ +#define XFA_FXFA_PARSER_CXFA_DIGESTMETHOD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DigestMethod : public CXFA_Node { + public: + CXFA_DigestMethod(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DigestMethod() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DIGESTMETHOD_H_ diff --git a/xfa/fxfa/parser/cxfa_digestmethods.cpp b/xfa/fxfa/parser/cxfa_digestmethods.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4993fd09b6337a1a2aa315bf7f00b76c57909849 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_digestmethods.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_digestmethods.h" + +#include "fxjs/xfa/cjx_digestmethods.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"digestMethods"; + +} // namespace + +CXFA_DigestMethods::CXFA_DigestMethods(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::DigestMethods, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_DigestMethods>(this)) {} + +CXFA_DigestMethods::~CXFA_DigestMethods() {} diff --git a/xfa/fxfa/parser/cxfa_digestmethods.h b/xfa/fxfa/parser/cxfa_digestmethods.h new file mode 100644 index 0000000000000000000000000000000000000000..65d40fbfcac48469fad65159c46ac68b263f6406 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_digestmethods.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DIGESTMETHODS_H_ +#define XFA_FXFA_PARSER_CXFA_DIGESTMETHODS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DigestMethods : public CXFA_Node { + public: + CXFA_DigestMethods(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DigestMethods() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DIGESTMETHODS_H_ diff --git a/xfa/fxfa/parser/cxfa_document.cpp b/xfa/fxfa/parser/cxfa_document.cpp index adb8eb2e0b92dfd9adb39158c73709b17d013e76..0675e35358893d42b93bf0a6c4b87f303dc03437 100644 --- a/xfa/fxfa/parser/cxfa_document.cpp +++ b/xfa/fxfa/parser/cxfa_document.cpp @@ -4,33 +4,40 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "core/fxcrt/fx_ext.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" +#include "xfa/fxfa/parser/cxfa_document.h" + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" +#include "xfa/fxfa/cxfa_ffnotify.h" #include "xfa/fxfa/parser/cscript_datawindow.h" #include "xfa/fxfa/parser/cscript_eventpseudomodel.h" #include "xfa/fxfa/parser/cscript_hostpseudomodel.h" #include "xfa/fxfa/parser/cscript_layoutpseudomodel.h" #include "xfa/fxfa/parser/cscript_logpseudomodel.h" #include "xfa/fxfa/parser/cscript_signaturepseudomodel.h" -#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_datagroup.h" #include "xfa/fxfa/parser/cxfa_document_parser.h" +#include "xfa/fxfa/parser/cxfa_interactive.h" #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_pdf.h" +#include "xfa/fxfa/parser/cxfa_present.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" #include "xfa/fxfa/parser/xfa_utils.h" namespace { +constexpr const wchar_t kTemplateNS[] = + L"http://www.xfa.org/schema/xfa-template/"; + void MergeNodeRecurse(CXFA_Document* pDocument, CXFA_Node* pDestNodeParent, CXFA_Node* pProtoNode) { CXFA_Node* pExistingNode = nullptr; - for (CXFA_Node* pFormChild = - pDestNodeParent->GetNodeItem(XFA_NODEITEM_FirstChild); - pFormChild; - pFormChild = pFormChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pFormChild = pDestNodeParent->GetFirstChild(); pFormChild; + pFormChild = pFormChild->GetNextSibling()) { if (pFormChild->GetElementType() == pProtoNode->GetElementType() && pFormChild->GetNameHash() == pProtoNode->GetNameHash() && pFormChild->IsUnusedNode()) { @@ -42,10 +49,8 @@ void MergeNodeRecurse(CXFA_Document* pDocument, if (pExistingNode) { pExistingNode->SetTemplateNode(pProtoNode); - for (CXFA_Node* pTemplateChild = - pProtoNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild(); + pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { MergeNodeRecurse(pDocument, pExistingNode, pTemplateChild); } return; @@ -66,10 +71,8 @@ void MergeNode(CXFA_Document* pDocument, } } pDestNode->SetTemplateNode(pProtoNode); - for (CXFA_Node* pTemplateChild = - pProtoNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; - pTemplateChild = pTemplateChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pProtoNode->GetFirstChild(); pTemplateChild; + pTemplateChild = pTemplateChild->GetNextSibling()) { MergeNodeRecurse(pDocument, pDestNode, pTemplateChild); } { @@ -85,30 +88,28 @@ void MergeNode(CXFA_Document* pDocument, CXFA_Document::CXFA_Document(CXFA_DocumentParser* pParser) : m_pParser(pParser), - m_pScriptContext(nullptr), - m_pLayoutProcessor(nullptr), m_pRootNode(nullptr), - m_pLocalMgr(nullptr), - m_pScriptDataWindow(nullptr), - m_pScriptEvent(nullptr), - m_pScriptHost(nullptr), - m_pScriptLog(nullptr), - m_pScriptLayout(nullptr), - m_pScriptSignature(nullptr), m_eCurVersionMode(XFA_VERSION_DEFAULT), m_dwDocFlags(0) { ASSERT(m_pParser); } CXFA_Document::~CXFA_Document() { + // Remove all the bindings before freeing the node as the ownership is wonky. + if (m_pRootNode) + m_pRootNode->ReleaseBindingNodes(); + delete m_pRootNode; - PurgeNodes(); + + for (CXFA_Node* pNode : m_PurgeNodes) + delete pNode; + m_PurgeNodes.clear(); } CXFA_LayoutProcessor* CXFA_Document::GetLayoutProcessor() { if (!m_pLayoutProcessor) - m_pLayoutProcessor = new CXFA_LayoutProcessor(this); - return m_pLayoutProcessor; + m_pLayoutProcessor = pdfium::MakeUnique<CXFA_LayoutProcessor>(this); + return m_pLayoutProcessor.get(); } CXFA_LayoutProcessor* CXFA_Document::GetDocLayout() { @@ -116,24 +117,15 @@ CXFA_LayoutProcessor* CXFA_Document::GetDocLayout() { } void CXFA_Document::ClearLayoutData() { - delete m_pLayoutProcessor; - m_pLayoutProcessor = nullptr; - delete m_pScriptContext; - m_pScriptContext = nullptr; - delete m_pLocalMgr; - m_pLocalMgr = nullptr; - delete m_pScriptDataWindow; - m_pScriptDataWindow = nullptr; - delete m_pScriptEvent; - m_pScriptEvent = nullptr; - delete m_pScriptHost; - m_pScriptHost = nullptr; - delete m_pScriptLog; - m_pScriptLog = nullptr; - delete m_pScriptLayout; - m_pScriptLayout = nullptr; - delete m_pScriptSignature; - m_pScriptSignature = nullptr; + m_pLayoutProcessor.reset(); + m_pScriptContext.reset(); + m_pLocalMgr.reset(); + m_pScriptDataWindow.reset(); + m_pScriptEvent.reset(); + m_pScriptHost.reset(); + m_pScriptLog.reset(); + m_pScriptLayout.reset(); + m_pScriptSignature.reset(); } void CXFA_Document::SetRoot(CXFA_Node* pNewRoot) { @@ -144,7 +136,7 @@ void CXFA_Document::SetRoot(CXFA_Node* pNewRoot) { RemovePurgeNode(pNewRoot); } -CFDE_XMLDoc* CXFA_Document::GetXMLDoc() const { +CFX_XMLDoc* CXFA_Document::GetXMLDoc() const { return m_pParser->GetXMLDoc(); } @@ -159,85 +151,84 @@ CXFA_Object* CXFA_Document::GetXFAObject(XFA_HashCode dwNodeNameHash) { if (!pDatasetsNode) return nullptr; - for (CXFA_Node* pDatasetsChild = - pDatasetsNode->GetFirstChildByClass(XFA_Element::DataGroup); + for (CXFA_DataGroup* pDatasetsChild = + pDatasetsNode->GetFirstChildByClass<CXFA_DataGroup>( + XFA_Element::DataGroup); pDatasetsChild; - pDatasetsChild = pDatasetsChild->GetNextSameClassSibling( - XFA_Element::DataGroup)) { + pDatasetsChild = + pDatasetsChild->GetNextSameClassSibling<CXFA_DataGroup>( + XFA_Element::DataGroup)) { if (pDatasetsChild->GetNameHash() != XFA_HASHCODE_Data) continue; - CFX_WideString wsNamespaceURI; - if (!pDatasetsChild->TryNamespace(wsNamespaceURI)) + Optional<WideString> namespaceURI = + pDatasetsChild->JSObject()->TryNamespace(); + if (!namespaceURI) continue; - CFX_WideString wsDatasetsURI; - if (!pDatasetsNode->TryNamespace(wsDatasetsURI)) + Optional<WideString> datasetsURI = + pDatasetsNode->JSObject()->TryNamespace(); + if (!datasetsURI) continue; - if (wsNamespaceURI == wsDatasetsURI) + if (*namespaceURI == *datasetsURI) return pDatasetsChild; } return nullptr; } case XFA_HASHCODE_Record: { CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data)); - return pData ? pData->GetFirstChildByClass(XFA_Element::DataGroup) + return pData ? pData->GetFirstChildByClass<CXFA_DataGroup>( + XFA_Element::DataGroup) : nullptr; } case XFA_HASHCODE_DataWindow: { if (!m_pScriptDataWindow) - m_pScriptDataWindow = new CScript_DataWindow(this); - return m_pScriptDataWindow; + m_pScriptDataWindow = pdfium::MakeUnique<CScript_DataWindow>(this); + return m_pScriptDataWindow.get(); } case XFA_HASHCODE_Event: { if (!m_pScriptEvent) - m_pScriptEvent = new CScript_EventPseudoModel(this); - return m_pScriptEvent; + m_pScriptEvent = pdfium::MakeUnique<CScript_EventPseudoModel>(this); + return m_pScriptEvent.get(); } case XFA_HASHCODE_Host: { if (!m_pScriptHost) - m_pScriptHost = new CScript_HostPseudoModel(this); - return m_pScriptHost; + m_pScriptHost = pdfium::MakeUnique<CScript_HostPseudoModel>(this); + return m_pScriptHost.get(); } case XFA_HASHCODE_Log: { if (!m_pScriptLog) - m_pScriptLog = new CScript_LogPseudoModel(this); - return m_pScriptLog; + m_pScriptLog = pdfium::MakeUnique<CScript_LogPseudoModel>(this); + return m_pScriptLog.get(); } case XFA_HASHCODE_Signature: { if (!m_pScriptSignature) - m_pScriptSignature = new CScript_SignaturePseudoModel(this); - return m_pScriptSignature; + m_pScriptSignature = + pdfium::MakeUnique<CScript_SignaturePseudoModel>(this); + return m_pScriptSignature.get(); } case XFA_HASHCODE_Layout: { if (!m_pScriptLayout) - m_pScriptLayout = new CScript_LayoutPseudoModel(this); - return m_pScriptLayout; + m_pScriptLayout = pdfium::MakeUnique<CScript_LayoutPseudoModel>(this); + return m_pScriptLayout.get(); } default: return m_pRootNode->GetFirstChildByName(dwNodeNameHash); } } -CXFA_Node* CXFA_Document::CreateNode(uint32_t dwPacket, XFA_Element eElement) { - return CreateNode(XFA_GetPacketByID(dwPacket), eElement); -} - -CXFA_Node* CXFA_Document::CreateNode(const XFA_PACKETINFO* pPacket, +CXFA_Node* CXFA_Document::CreateNode(XFA_PacketType packet, XFA_Element eElement) { - if (!pPacket) + if (eElement == XFA_Element::Unknown) return nullptr; - const XFA_ELEMENTINFO* pElement = XFA_GetElementByID(eElement); - if (pElement && (pElement->dwPackets & pPacket->eName)) { - CXFA_Node* pNode = - new CXFA_Node(this, pPacket->eName, pElement->eObjectType, - pElement->eName, pElement->pName); - AddPurgeNode(pNode); - return pNode; - } + std::unique_ptr<CXFA_Node> pNode = CXFA_Node::Create(this, eElement, packet); + if (!pNode) + return nullptr; - return nullptr; + // TODO(dsinclair): AddPrugeNode should take ownership of the pointer. + AddPurgeNode(pNode.get()); + return pNode.release(); } void CXFA_Document::AddPurgeNode(CXFA_Node* pNode) { @@ -248,13 +239,6 @@ bool CXFA_Document::RemovePurgeNode(CXFA_Node* pNode) { return !!m_PurgeNodes.erase(pNode); } -void CXFA_Document::PurgeNodes() { - for (CXFA_Node* pNode : m_PurgeNodes) - delete pNode; - - m_PurgeNodes.clear(); -} - void CXFA_Document::SetFlag(uint32_t dwFlag, bool bOn) { if (bOn) m_dwDocFlags |= dwFlag; @@ -270,19 +254,22 @@ bool CXFA_Document::IsInteractive() { if (!pConfig) return false; - CFX_WideString wsInteractive; - CXFA_Node* pPresent = pConfig->GetFirstChildByClass(XFA_Element::Present); + CXFA_Present* pPresent = + pConfig->GetFirstChildByClass<CXFA_Present>(XFA_Element::Present); if (!pPresent) return false; - CXFA_Node* pPDF = pPresent->GetFirstChildByClass(XFA_Element::Pdf); + CXFA_Pdf* pPDF = pPresent->GetFirstChildByClass<CXFA_Pdf>(XFA_Element::Pdf); if (!pPDF) return false; - CXFA_Node* pFormFiller = pPDF->GetChild(0, XFA_Element::Interactive); + CXFA_Interactive* pFormFiller = + pPDF->GetChild<CXFA_Interactive>(0, XFA_Element::Interactive, false); if (pFormFiller) { m_dwDocFlags |= XFA_DOCFLAG_HasInteractive; - if (pFormFiller->TryContent(wsInteractive) && wsInteractive == L"1") { + + WideString wsInteractive = pFormFiller->JSObject()->GetContent(false); + if (wsInteractive == L"1") { m_dwDocFlags |= XFA_DOCFLAG_Interactive; return true; } @@ -292,44 +279,45 @@ bool CXFA_Document::IsInteractive() { CXFA_LocaleMgr* CXFA_Document::GetLocalMgr() { if (!m_pLocalMgr) { - m_pLocalMgr = - new CXFA_LocaleMgr(ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)), - GetNotify()->GetAppProvider()->GetLanguage()); + m_pLocalMgr = pdfium::MakeUnique<CXFA_LocaleMgr>( + ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)), + GetNotify()->GetAppProvider()->GetLanguage()); } - return m_pLocalMgr; + return m_pLocalMgr.get(); } -CXFA_ScriptContext* CXFA_Document::InitScriptContext(v8::Isolate* pIsolate) { - if (!m_pScriptContext) - m_pScriptContext = new CXFA_ScriptContext(this); - m_pScriptContext->Initialize(pIsolate); - return m_pScriptContext; +CFXJSE_Engine* CXFA_Document::InitScriptContext(v8::Isolate* pIsolate) { + ASSERT(!m_pScriptContext); + m_pScriptContext = pdfium::MakeUnique<CFXJSE_Engine>(this, pIsolate); + return m_pScriptContext.get(); } -CXFA_ScriptContext* CXFA_Document::GetScriptContext() { - if (!m_pScriptContext) - m_pScriptContext = new CXFA_ScriptContext(this); - return m_pScriptContext; +// We have to call |InitScriptContext| before any calls to |GetScriptContext| +// or the context won't have an isolate set into it. +CFXJSE_Engine* CXFA_Document::GetScriptContext() { + ASSERT(m_pScriptContext); + return m_pScriptContext.get(); } XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber( - CFX_WideString& wsTemplateNS) { - CFX_WideStringC wsTemplateURIPrefix = - XFA_GetPacketByIndex(XFA_PACKET_Template)->pURI; - FX_STRSIZE nPrefixLength = wsTemplateURIPrefix.GetLength(); - if (CFX_WideStringC(wsTemplateNS.c_str(), wsTemplateNS.GetLength()) != + const WideString& wsTemplateNS) { + WideStringView wsTemplateURIPrefix(kTemplateNS); + size_t nPrefixLength = wsTemplateURIPrefix.GetLength(); + if (WideStringView(wsTemplateNS.c_str(), wsTemplateNS.GetLength()) != wsTemplateURIPrefix) { return XFA_VERSION_UNKNOWN; } - FX_STRSIZE nDotPos = wsTemplateNS.Find('.', nPrefixLength); - if (nDotPos == (FX_STRSIZE)-1) + auto nDotPos = wsTemplateNS.Find('.', nPrefixLength); + if (!nDotPos.has_value()) return XFA_VERSION_UNKNOWN; int8_t iMajor = FXSYS_wtoi( - wsTemplateNS.Mid(nPrefixLength, nDotPos - nPrefixLength).c_str()); - int8_t iMinor = FXSYS_wtoi( - wsTemplateNS.Mid(nDotPos + 1, wsTemplateNS.GetLength() - nDotPos - 2) - .c_str()); + wsTemplateNS.Mid(nPrefixLength, nDotPos.value() - nPrefixLength).c_str()); + int8_t iMinor = + FXSYS_wtoi(wsTemplateNS + .Mid(nDotPos.value() + 1, + wsTemplateNS.GetLength() - nDotPos.value() - 2) + .c_str()); XFA_VERSION eVersion = (XFA_VERSION)((int32_t)iMajor * 100 + iMinor); if (eVersion < XFA_VERSION_MIN || eVersion > XFA_VERSION_MAX) return XFA_VERSION_UNKNOWN; @@ -339,18 +327,16 @@ XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber( } CXFA_Node* CXFA_Document::GetNodeByID(CXFA_Node* pRoot, - const CFX_WideStringC& wsID) { + const WideStringView& wsID) { if (!pRoot || wsID.IsEmpty()) return nullptr; CXFA_NodeIterator sIterator(pRoot); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { - CFX_WideStringC wsIDVal; - if (pNode->TryCData(XFA_ATTRIBUTE_Id, wsIDVal) && !wsIDVal.IsEmpty()) { - if (wsIDVal == wsID) - return pNode; - } + WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id); + if (!wsIDVal.IsEmpty() && wsIDVal == wsID) + return pNode; } return nullptr; } @@ -361,50 +347,57 @@ void CXFA_Document::DoProtoMerge() { return; std::map<uint32_t, CXFA_Node*> mIDMap; - CXFA_NodeSet sUseNodes; + std::set<CXFA_Node*> sUseNodes; CXFA_NodeIterator sIterator(pTemplateRoot); for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) { - CFX_WideStringC wsIDVal; - if (pNode->TryCData(XFA_ATTRIBUTE_Id, wsIDVal) && !wsIDVal.IsEmpty()) { - mIDMap[FX_HashCode_GetW(wsIDVal, false)] = pNode; - } - CFX_WideStringC wsUseVal; - if (pNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) && !wsUseVal.IsEmpty()) { - sUseNodes.insert(pNode); - } else if (pNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) && - !wsUseVal.IsEmpty()) { + WideString wsIDVal = pNode->JSObject()->GetCData(XFA_Attribute::Id); + if (!wsIDVal.IsEmpty()) + mIDMap[FX_HashCode_GetW(wsIDVal.AsStringView(), false)] = pNode; + + WideString wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Use); + if (!wsUseVal.IsEmpty()) { sUseNodes.insert(pNode); + } else { + wsUseVal = pNode->JSObject()->GetCData(XFA_Attribute::Usehref); + if (!wsUseVal.IsEmpty()) + sUseNodes.insert(pNode); } } for (CXFA_Node* pUseHrefNode : sUseNodes) { - CFX_WideString wsUseVal; - CFX_WideStringC wsURI, wsID, wsSOM; - if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) && - !wsUseVal.IsEmpty()) { - FX_STRSIZE uSharpPos = wsUseVal.Find('#'); - if (uSharpPos < 0) { - wsURI = wsUseVal.AsStringC(); + WideStringView wsURI; + WideStringView wsID; + WideStringView wsSOM; + + WideString wsUseVal = + pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Usehref); + if (!wsUseVal.IsEmpty()) { + auto uSharpPos = wsUseVal.Find('#'); + if (!uSharpPos.has_value()) { + wsURI = wsUseVal.AsStringView(); } else { - wsURI = CFX_WideStringC(wsUseVal.c_str(), uSharpPos); - FX_STRSIZE uLen = wsUseVal.GetLength(); - if (uLen >= uSharpPos + 5 && - CFX_WideStringC(wsUseVal.c_str() + uSharpPos, 5) == L"#som(" && + wsURI = WideStringView(wsUseVal.c_str(), uSharpPos.value()); + size_t uLen = wsUseVal.GetLength(); + if (uLen >= uSharpPos.value() + 5 && + WideStringView(wsUseVal.c_str() + uSharpPos.value(), 5) == + L"#som(" && wsUseVal[uLen - 1] == ')') { - wsSOM = CFX_WideStringC(wsUseVal.c_str() + uSharpPos + 5, - uLen - 1 - uSharpPos - 5); + wsSOM = WideStringView(wsUseVal.c_str() + uSharpPos.value() + 5, + uLen - 1 - uSharpPos.value() - 5); } else { - wsID = CFX_WideStringC(wsUseVal.c_str() + uSharpPos + 1, - uLen - uSharpPos - 1); + wsID = WideStringView(wsUseVal.c_str() + uSharpPos.value() + 1, + uLen - uSharpPos.value() - 1); } } - } else if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) && - !wsUseVal.IsEmpty()) { - if (wsUseVal[0] == '#') - wsID = CFX_WideStringC(wsUseVal.c_str() + 1, wsUseVal.GetLength() - 1); - else - wsSOM = CFX_WideStringC(wsUseVal.c_str(), wsUseVal.GetLength()); + } else { + wsUseVal = pUseHrefNode->JSObject()->GetCData(XFA_Attribute::Use); + if (!wsUseVal.IsEmpty()) { + if (wsUseVal[0] == '#') + wsID = WideStringView(wsUseVal.c_str() + 1, wsUseVal.GetLength() - 1); + else + wsSOM = WideStringView(wsUseVal.c_str(), wsUseVal.GetLength()); + } } if (!wsURI.IsEmpty() && wsURI != L".") @@ -415,11 +408,11 @@ void CXFA_Document::DoProtoMerge() { uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = m_pScriptContext->ResolveObjects(pUseHrefNode, wsSOM, - resoveNodeRS, dwFlag); - if (iRet > 0 && resoveNodeRS.nodes[0]->IsNode()) - pProtoNode = resoveNodeRS.nodes[0]->AsNode(); + XFA_RESOLVENODE_RS resolveNodeRS; + int32_t iRet = m_pScriptContext->ResolveObjects( + pUseHrefNode, wsSOM, &resolveNodeRS, dwFlag, nullptr); + if (iRet > 0 && resolveNodeRS.objects.front()->IsNode()) + pProtoNode = resolveNodeRS.objects.front()->AsNode(); } else if (!wsID.IsEmpty()) { auto it = mIDMap.find(FX_HashCode_GetW(wsID, false)); if (it == mIDMap.end()) diff --git a/xfa/fxfa/parser/cxfa_document.h b/xfa/fxfa/parser/cxfa_document.h index fdd230dca7725a6e3045484e6d68cbd42561ec97..bd576e68a5b29bdf91258805b0acc6f1375ea079 100644 --- a/xfa/fxfa/parser/cxfa_document.h +++ b/xfa/fxfa/parser/cxfa_document.h @@ -8,10 +8,12 @@ #define XFA_FXFA_PARSER_CXFA_DOCUMENT_H_ #include <map> +#include <memory> +#include <set> +#include <vector> #include "xfa/fxfa/fxfa.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" enum XFA_VERSION { XFA_VERSION_UNKNOWN = 0, @@ -38,57 +40,54 @@ enum XFA_DocFlag { XFA_DOCFLAG_Scripting = 0x0008 }; -class CFDE_XMLDoc; +class CFX_XMLDoc; +class CFXJSE_Engine; class CScript_DataWindow; class CScript_EventPseudoModel; class CScript_HostPseudoModel; class CScript_LogPseudoModel; class CScript_LayoutPseudoModel; class CScript_SignaturePseudoModel; -class CXFA_Document; +class CXFA_ContainerLayoutItem; +class CXFA_DocumentParser; +class CXFA_FFNotify; class CXFA_LayoutItem; class CXFA_LayoutProcessor; class CXFA_Node; -class CXFA_LayoutProcessor; -class CXFA_DocumentParser; -class CXFA_ContainerLayoutItem; -class CXFA_FFNotify; -class CXFA_ScriptContext; +class CXFA_Object; class CXFA_Document { public: explicit CXFA_Document(CXFA_DocumentParser* pParser); ~CXFA_Document(); - CXFA_ScriptContext* InitScriptContext(v8::Isolate* pIsolate); + CFXJSE_Engine* InitScriptContext(v8::Isolate* pIsolate); CXFA_Node* GetRoot() const { return m_pRootNode; } - CFDE_XMLDoc* GetXMLDoc() const; + CFX_XMLDoc* GetXMLDoc() const; CXFA_FFNotify* GetNotify() const; CXFA_LocaleMgr* GetLocalMgr(); CXFA_Object* GetXFAObject(XFA_HashCode wsNodeNameHash); - CXFA_Node* GetNodeByID(CXFA_Node* pRoot, const CFX_WideStringC& wsID); - CXFA_Node* GetNotBindNode(CXFA_ObjArray& arrayNodes); + CXFA_Node* GetNodeByID(CXFA_Node* pRoot, const WideStringView& wsID); + CXFA_Node* GetNotBindNode(const std::vector<CXFA_Object*>& arrayNodes); CXFA_LayoutProcessor* GetLayoutProcessor(); CXFA_LayoutProcessor* GetDocLayout(); - CXFA_ScriptContext* GetScriptContext(); + CFXJSE_Engine* GetScriptContext(); void SetRoot(CXFA_Node* pNewRoot); void AddPurgeNode(CXFA_Node* pNode); bool RemovePurgeNode(CXFA_Node* pNode); - void PurgeNodes(); bool HasFlag(uint32_t dwFlag) { return (m_dwDocFlags & dwFlag) == dwFlag; } void SetFlag(uint32_t dwFlag, bool bOn); bool IsInteractive(); XFA_VERSION GetCurVersionMode() { return m_eCurVersionMode; } - XFA_VERSION RecognizeXFAVersionNumber(CFX_WideString& wsTemplateNS); + XFA_VERSION RecognizeXFAVersionNumber(const WideString& wsTemplateNS); - CXFA_Node* CreateNode(uint32_t dwPacket, XFA_Element eElement); - CXFA_Node* CreateNode(const XFA_PACKETINFO* pPacket, XFA_Element eElement); + CXFA_Node* CreateNode(XFA_PacketType packet, XFA_Element eElement); void DoProtoMerge(); void DoDataMerge(); @@ -104,21 +103,21 @@ class CXFA_Document { void ClearLayoutData(); std::map<uint32_t, CXFA_Node*> m_rgGlobalBinding; - CXFA_NodeArray m_pPendingPageSet; + std::vector<CXFA_Node*> m_pPendingPageSet; - protected: + private: CXFA_DocumentParser* m_pParser; - CXFA_ScriptContext* m_pScriptContext; - CXFA_LayoutProcessor* m_pLayoutProcessor; CXFA_Node* m_pRootNode; - CXFA_LocaleMgr* m_pLocalMgr; - CScript_DataWindow* m_pScriptDataWindow; - CScript_EventPseudoModel* m_pScriptEvent; - CScript_HostPseudoModel* m_pScriptHost; - CScript_LogPseudoModel* m_pScriptLog; - CScript_LayoutPseudoModel* m_pScriptLayout; - CScript_SignaturePseudoModel* m_pScriptSignature; - CXFA_NodeSet m_PurgeNodes; + std::unique_ptr<CFXJSE_Engine> m_pScriptContext; + std::unique_ptr<CXFA_LayoutProcessor> m_pLayoutProcessor; + std::unique_ptr<CXFA_LocaleMgr> m_pLocalMgr; + std::unique_ptr<CScript_DataWindow> m_pScriptDataWindow; + std::unique_ptr<CScript_EventPseudoModel> m_pScriptEvent; + std::unique_ptr<CScript_HostPseudoModel> m_pScriptHost; + std::unique_ptr<CScript_LogPseudoModel> m_pScriptLog; + std::unique_ptr<CScript_LayoutPseudoModel> m_pScriptLayout; + std::unique_ptr<CScript_SignaturePseudoModel> m_pScriptSignature; + std::set<CXFA_Node*> m_PurgeNodes; XFA_VERSION m_eCurVersionMode; uint32_t m_dwDocFlags; }; diff --git a/xfa/fxfa/parser/cxfa_document_parser.cpp b/xfa/fxfa/parser/cxfa_document_parser.cpp index 90be568785599017000cca580d34699871d0e97e..6446ea31ce5c208d4365b42245235c54978b664f 100644 --- a/xfa/fxfa/parser/cxfa_document_parser.cpp +++ b/xfa/fxfa/parser/cxfa_document_parser.cpp @@ -6,19 +6,20 @@ #include "xfa/fxfa/parser/cxfa_document_parser.h" +#include "core/fxcrt/xml/cfx_xmldoc.h" #include "third_party/base/ptr_util.h" #include "xfa/fxfa/fxfa.h" #include "xfa/fxfa/parser/cxfa_document.h" CXFA_DocumentParser::CXFA_DocumentParser(CXFA_FFNotify* pNotify) - : m_nodeParser(nullptr, true), m_pNotify(pNotify) {} + : m_pNotify(pNotify) {} CXFA_DocumentParser::~CXFA_DocumentParser() { } int32_t CXFA_DocumentParser::StartParse( - const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, - XFA_XDPPACKET ePacketID) { + const RetainPtr<IFX_SeekableStream>& pStream, + XFA_PacketType ePacketID) { m_pDocument.reset(); m_nodeParser.CloseParser(); @@ -30,8 +31,8 @@ int32_t CXFA_DocumentParser::StartParse( return nRetStatus; } -int32_t CXFA_DocumentParser::DoParse(IFX_Pause* pPause) { - int32_t nRetStatus = m_nodeParser.DoParse(pPause); +int32_t CXFA_DocumentParser::DoParse() { + int32_t nRetStatus = m_nodeParser.DoParse(); if (nRetStatus >= XFA_PARSESTATUS_Done) { ASSERT(m_pDocument); m_pDocument->SetRoot(m_nodeParser.GetRootNode()); @@ -39,12 +40,12 @@ int32_t CXFA_DocumentParser::DoParse(IFX_Pause* pPause) { return nRetStatus; } -CFDE_XMLDoc* CXFA_DocumentParser::GetXMLDoc() const { +CFX_XMLDoc* CXFA_DocumentParser::GetXMLDoc() const { return m_nodeParser.GetXMLDoc(); } CXFA_FFNotify* CXFA_DocumentParser::GetNotify() const { - return m_pNotify; + return m_pNotify.Get(); } CXFA_Document* CXFA_DocumentParser::GetDocument() const { diff --git a/xfa/fxfa/parser/cxfa_document_parser.h b/xfa/fxfa/parser/cxfa_document_parser.h index 617bddf55be054d3401f524b789c1b8b064a2eef..35d71603cbcc6f69c6f7371acbdd3e66aad4286d 100644 --- a/xfa/fxfa/parser/cxfa_document_parser.h +++ b/xfa/fxfa/parser/cxfa_document_parser.h @@ -11,30 +11,29 @@ #include "xfa/fxfa/parser/cxfa_simple_parser.h" -class CFDE_XMLDoc; +class CFX_XMLDoc; class CXFA_Document; class CXFA_FFNotify; class CXFA_Notify; -class IFX_SeekableReadStream; -class IFX_Pause; +class IFX_SeekableStream; class CXFA_DocumentParser { public: explicit CXFA_DocumentParser(CXFA_FFNotify* pNotify); ~CXFA_DocumentParser(); - int32_t StartParse(const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, - XFA_XDPPACKET ePacketID); - int32_t DoParse(IFX_Pause* pPause); + int32_t StartParse(const RetainPtr<IFX_SeekableStream>& pStream, + XFA_PacketType ePacketID); + int32_t DoParse(); - CFDE_XMLDoc* GetXMLDoc() const; + CFX_XMLDoc* GetXMLDoc() const; CXFA_FFNotify* GetNotify() const; CXFA_Document* GetDocument() const; - protected: - CXFA_SimpleParser m_nodeParser; - CXFA_FFNotify* m_pNotify; + private: + UnownedPtr<CXFA_FFNotify> const m_pNotify; std::unique_ptr<CXFA_Document> m_pDocument; + CXFA_SimpleParser m_nodeParser; }; #endif // XFA_FXFA_PARSER_CXFA_DOCUMENT_PARSER_H_ diff --git a/xfa/fxfa/parser/cxfa_documentassembly.cpp b/xfa/fxfa/parser/cxfa_documentassembly.cpp new file mode 100644 index 0000000000000000000000000000000000000000..146071d42457c444e04095af53748abc1534ff27 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_documentassembly.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_documentassembly.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"documentAssembly"; + +} // namespace + +CXFA_DocumentAssembly::CXFA_DocumentAssembly(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::DocumentAssembly, + nullptr, + kAttributeData, + kName) {} + +CXFA_DocumentAssembly::~CXFA_DocumentAssembly() {} diff --git a/xfa/fxfa/parser/cxfa_documentassembly.h b/xfa/fxfa/parser/cxfa_documentassembly.h new file mode 100644 index 0000000000000000000000000000000000000000..c22d4a97b0b1aee231922d7f1578f44c1d328458 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_documentassembly.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DOCUMENTASSEMBLY_H_ +#define XFA_FXFA_PARSER_CXFA_DOCUMENTASSEMBLY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DocumentAssembly : public CXFA_Node { + public: + CXFA_DocumentAssembly(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DocumentAssembly() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DOCUMENTASSEMBLY_H_ diff --git a/xfa/fxfa/parser/cxfa_draw.cpp b/xfa/fxfa/parser/cxfa_draw.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d0dd37788ab5a882c11c741f70fafafde8da356 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_draw.cpp @@ -0,0 +1,64 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_draw.h" + +#include "fxjs/xfa/cjx_draw.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Ui, 1, 0}, {XFA_Element::Margin, 1, 0}, + {XFA_Element::Para, 1, 0}, {XFA_Element::Border, 1, 0}, + {XFA_Element::Assist, 1, 0}, {XFA_Element::Traversal, 1, 0}, + {XFA_Element::Keep, 1, 0}, {XFA_Element::Caption, 1, 0}, + {XFA_Element::Desc, 1, 0}, {XFA_Element::Font, 1, 0}, + {XFA_Element::Value, 1, 0}, {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::H, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::W, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Left}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Rotate, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::VAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Top}, + {XFA_Attribute::MaxH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MaxW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ColSpan, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Locale, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AnchorType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::TopLeft}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"draw"; + +} // namespace + +CXFA_Draw::CXFA_Draw(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::Draw, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Draw>(this)) {} + +CXFA_Draw::~CXFA_Draw() {} diff --git a/xfa/fxfa/parser/cxfa_draw.h b/xfa/fxfa/parser/cxfa_draw.h new file mode 100644 index 0000000000000000000000000000000000000000..603103b091c9b79ef86070774bd360cb2a549078 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_draw.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DRAW_H_ +#define XFA_FXFA_PARSER_CXFA_DRAW_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Draw : public CXFA_Node { + public: + CXFA_Draw(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Draw() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DRAW_H_ diff --git a/xfa/fxfa/parser/cxfa_driver.cpp b/xfa/fxfa/parser/cxfa_driver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..883cbf6f9b26204bd27d1799378d4eb81e812c9b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_driver.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_driver.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::FontInfo, 1, 0}, + {XFA_Element::Xdc, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"driver"; + +} // namespace + +CXFA_Driver::CXFA_Driver(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Driver, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Driver::~CXFA_Driver() {} diff --git a/xfa/fxfa/parser/cxfa_driver.h b/xfa/fxfa/parser/cxfa_driver.h new file mode 100644 index 0000000000000000000000000000000000000000..aee732edf73b4dfda7e3ca63b0fac8302b793f85 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_driver.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DRIVER_H_ +#define XFA_FXFA_PARSER_CXFA_DRIVER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Driver : public CXFA_Node { + public: + CXFA_Driver(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Driver() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DRIVER_H_ diff --git a/xfa/fxfa/parser/cxfa_dsigdata.cpp b/xfa/fxfa/parser/cxfa_dsigdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88d3e8e4386fe6ceea7827b7ded98613d4e6a00e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_dsigdata.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_dsigdata.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Value, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dSigData"; + +} // namespace + +CXFA_DSigData::CXFA_DSigData(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::DSigData, + nullptr, + kAttributeData, + kName) {} + +CXFA_DSigData::~CXFA_DSigData() {} diff --git a/xfa/fxfa/parser/cxfa_dsigdata.h b/xfa/fxfa/parser/cxfa_dsigdata.h new file mode 100644 index 0000000000000000000000000000000000000000..0cbaeb4402990c8a5fc68e2fe01017843ddb4064 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_dsigdata.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DSIGDATA_H_ +#define XFA_FXFA_PARSER_CXFA_DSIGDATA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DSigData : public CXFA_Node { + public: + CXFA_DSigData(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DSigData() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DSIGDATA_H_ diff --git a/xfa/fxfa/parser/cxfa_duplexoption.cpp b/xfa/fxfa/parser/cxfa_duplexoption.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8d417098de9ff6f44a207ae266265fda78fcb6d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_duplexoption.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_duplexoption.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"duplexOption"; + +} // namespace + +CXFA_DuplexOption::CXFA_DuplexOption(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::DuplexOption, + nullptr, + kAttributeData, + kName) {} + +CXFA_DuplexOption::~CXFA_DuplexOption() {} diff --git a/xfa/fxfa/parser/cxfa_duplexoption.h b/xfa/fxfa/parser/cxfa_duplexoption.h new file mode 100644 index 0000000000000000000000000000000000000000..69034ce594570adbf4663955d1159e5d23f66075 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_duplexoption.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DUPLEXOPTION_H_ +#define XFA_FXFA_PARSER_CXFA_DUPLEXOPTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DuplexOption : public CXFA_Node { + public: + CXFA_DuplexOption(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DuplexOption() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DUPLEXOPTION_H_ diff --git a/xfa/fxfa/parser/cxfa_dynamicrender.cpp b/xfa/fxfa/parser/cxfa_dynamicrender.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a60e1925219e92d0bd27be59b320bab7c35f2b9b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_dynamicrender.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_dynamicrender.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"dynamicRender"; + +} // namespace + +CXFA_DynamicRender::CXFA_DynamicRender(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::DynamicRender, + nullptr, + kAttributeData, + kName) {} + +CXFA_DynamicRender::~CXFA_DynamicRender() {} diff --git a/xfa/fxfa/parser/cxfa_dynamicrender.h b/xfa/fxfa/parser/cxfa_dynamicrender.h new file mode 100644 index 0000000000000000000000000000000000000000..f7c54fafab2849a289fbfa550946748c00c9b708 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_dynamicrender.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_DYNAMICRENDER_H_ +#define XFA_FXFA_PARSER_CXFA_DYNAMICRENDER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_DynamicRender : public CXFA_Node { + public: + CXFA_DynamicRender(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_DynamicRender() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_DYNAMICRENDER_H_ diff --git a/xfa/fxfa/parser/cxfa_edge.cpp b/xfa/fxfa/parser/cxfa_edge.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65e599cc59da1fe96802968d8cc6944777f3047f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_edge.cpp @@ -0,0 +1,45 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_edge.h" + +#include "fxjs/xfa/cjx_edge.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Color, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Cap, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Square}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Stroke, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Solid}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::Thickness, XFA_AttributeType::Measure, (void*)L"0.5pt"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"edge"; + +} // namespace + +CXFA_Edge::CXFA_Edge(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Stroke(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Edge, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Edge>(this)) {} + +CXFA_Edge::~CXFA_Edge() {} diff --git a/xfa/fxfa/parser/cxfa_edge.h b/xfa/fxfa/parser/cxfa_edge.h index 96e725f4c6d9bc18dbb9999145978026c74ace30..36fee5562416ddb61f187b0d73a53cc1715f3dc9 100644 --- a/xfa/fxfa/parser/cxfa_edge.h +++ b/xfa/fxfa/parser/cxfa_edge.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,11 +9,12 @@ #include "xfa/fxfa/parser/cxfa_stroke.h" -class CXFA_Node; - class CXFA_Edge : public CXFA_Stroke { public: - explicit CXFA_Edge(CXFA_Node* pNode) : CXFA_Stroke(pNode) {} + static constexpr FX_ARGB kDefaultColor = 0xFF000000; + + CXFA_Edge(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Edge() override; }; #endif // XFA_FXFA_PARSER_CXFA_EDGE_H_ diff --git a/xfa/fxfa/parser/cxfa_effectiveinputpolicy.cpp b/xfa/fxfa/parser/cxfa_effectiveinputpolicy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2c5d0f89b41c308945567c40d80c1b21cc733e2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_effectiveinputpolicy.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_effectiveinputpolicy.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"effectiveInputPolicy"; + +} // namespace + +CXFA_EffectiveInputPolicy::CXFA_EffectiveInputPolicy(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::Node, + XFA_Element::EffectiveInputPolicy, + nullptr, + kAttributeData, + kName) {} + +CXFA_EffectiveInputPolicy::~CXFA_EffectiveInputPolicy() {} diff --git a/xfa/fxfa/parser/cxfa_effectiveinputpolicy.h b/xfa/fxfa/parser/cxfa_effectiveinputpolicy.h new file mode 100644 index 0000000000000000000000000000000000000000..52a60a45d97e365d7d7f260b7685a7158dccf49f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_effectiveinputpolicy.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EFFECTIVEINPUTPOLICY_H_ +#define XFA_FXFA_PARSER_CXFA_EFFECTIVEINPUTPOLICY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EffectiveInputPolicy : public CXFA_Node { + public: + CXFA_EffectiveInputPolicy(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EffectiveInputPolicy() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EFFECTIVEINPUTPOLICY_H_ diff --git a/xfa/fxfa/parser/cxfa_effectiveoutputpolicy.cpp b/xfa/fxfa/parser/cxfa_effectiveoutputpolicy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1ab37020c4811152f0a48743694bcbb81da268b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_effectiveoutputpolicy.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"effectiveOutputPolicy"; + +} // namespace + +CXFA_EffectiveOutputPolicy::CXFA_EffectiveOutputPolicy(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::Node, + XFA_Element::EffectiveOutputPolicy, + nullptr, + kAttributeData, + kName) {} + +CXFA_EffectiveOutputPolicy::~CXFA_EffectiveOutputPolicy() {} diff --git a/xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h b/xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h new file mode 100644 index 0000000000000000000000000000000000000000..b2317d520e430cf55f407702f6dd0833543125c9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EFFECTIVEOUTPUTPOLICY_H_ +#define XFA_FXFA_PARSER_CXFA_EFFECTIVEOUTPUTPOLICY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EffectiveOutputPolicy : public CXFA_Node { + public: + CXFA_EffectiveOutputPolicy(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EffectiveOutputPolicy() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EFFECTIVEOUTPUTPOLICY_H_ diff --git a/xfa/fxfa/parser/cxfa_embed.cpp b/xfa/fxfa/parser/cxfa_embed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f65fea4086d0c1764a1be91e1d3f5da34779f4d7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_embed.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_embed.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"embed"; + +} // namespace + +CXFA_Embed::CXFA_Embed(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Embed, + nullptr, + kAttributeData, + kName) {} + +CXFA_Embed::~CXFA_Embed() {} diff --git a/xfa/fxfa/parser/cxfa_embed.h b/xfa/fxfa/parser/cxfa_embed.h new file mode 100644 index 0000000000000000000000000000000000000000..d1308407b2e5962a576bcf133fdb5a60e75c72a2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_embed.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EMBED_H_ +#define XFA_FXFA_PARSER_CXFA_EMBED_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Embed : public CXFA_Node { + public: + CXFA_Embed(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Embed() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EMBED_H_ diff --git a/xfa/fxfa/parser/cxfa_encoding.cpp b/xfa/fxfa/parser/cxfa_encoding.cpp new file mode 100644 index 0000000000000000000000000000000000000000..303221ae58320b08468d74f8c19006f5bb549b1b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encoding.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encoding.h" + +#include "fxjs/xfa/cjx_encoding.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encoding"; + +} // namespace + +CXFA_Encoding::CXFA_Encoding(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeC, + XFA_Element::Encoding, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Encoding>(this)) {} + +CXFA_Encoding::~CXFA_Encoding() {} diff --git a/xfa/fxfa/parser/cxfa_encoding.h b/xfa/fxfa/parser/cxfa_encoding.h new file mode 100644 index 0000000000000000000000000000000000000000..ad41b01b85e7921c5d9ddf1c431fefe37137b1e9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encoding.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCODING_H_ +#define XFA_FXFA_PARSER_CXFA_ENCODING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Encoding : public CXFA_Node { + public: + CXFA_Encoding(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Encoding() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCODING_H_ diff --git a/xfa/fxfa/parser/cxfa_encodings.cpp b/xfa/fxfa/parser/cxfa_encodings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0df2d607712031df21994ec64a1f828c6206c3d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encodings.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encodings.h" + +#include "fxjs/xfa/cjx_encodings.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encodings"; + +} // namespace + +CXFA_Encodings::CXFA_Encodings(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Encodings, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Encodings>(this)) {} + +CXFA_Encodings::~CXFA_Encodings() {} diff --git a/xfa/fxfa/parser/cxfa_encodings.h b/xfa/fxfa/parser/cxfa_encodings.h new file mode 100644 index 0000000000000000000000000000000000000000..d3876deefc5b1611bea554c494ba10e31829dfed --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encodings.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCODINGS_H_ +#define XFA_FXFA_PARSER_CXFA_ENCODINGS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Encodings : public CXFA_Node { + public: + CXFA_Encodings(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Encodings() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCODINGS_H_ diff --git a/xfa/fxfa/parser/cxfa_encrypt.cpp b/xfa/fxfa/parser/cxfa_encrypt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ddf941c9c5d70a9b5bbb72a16d0418b7bda267a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encrypt.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encrypt.h" + +#include "fxjs/xfa/cjx_encrypt.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Certificate, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encrypt"; + +} // namespace + +CXFA_Encrypt::CXFA_Encrypt(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Encrypt, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Encrypt>(this)) {} + +CXFA_Encrypt::~CXFA_Encrypt() {} diff --git a/xfa/fxfa/parser/cxfa_encrypt.h b/xfa/fxfa/parser/cxfa_encrypt.h new file mode 100644 index 0000000000000000000000000000000000000000..4968db62c8374e594078200fc60f42f4951030e9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encrypt.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCRYPT_H_ +#define XFA_FXFA_PARSER_CXFA_ENCRYPT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Encrypt : public CXFA_Node { + public: + CXFA_Encrypt(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Encrypt() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCRYPT_H_ diff --git a/xfa/fxfa/parser/cxfa_encryption.cpp b/xfa/fxfa/parser/cxfa_encryption.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a876fed6ef632ad1ff45eb3e484ab5985b52249 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryption.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encryption.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::EncryptionLevel, 1, 0}, + {XFA_Element::Encrypt, 1, 0}, + {XFA_Element::Permissions, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encryption"; + +} // namespace + +CXFA_Encryption::CXFA_Encryption(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Encryption, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Encryption::~CXFA_Encryption() {} diff --git a/xfa/fxfa/parser/cxfa_encryption.h b/xfa/fxfa/parser/cxfa_encryption.h new file mode 100644 index 0000000000000000000000000000000000000000..f2028ee850816dbe9ad0f50e43014369791b1c65 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryption.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCRYPTION_H_ +#define XFA_FXFA_PARSER_CXFA_ENCRYPTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Encryption : public CXFA_Node { + public: + CXFA_Encryption(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Encryption() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCRYPTION_H_ diff --git a/xfa/fxfa/parser/cxfa_encryptionlevel.cpp b/xfa/fxfa/parser/cxfa_encryptionlevel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..099b03533ef9a3ac5f7f9792a1757ea80c2b06c0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryptionlevel.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encryptionlevel.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encryptionLevel"; + +} // namespace + +CXFA_EncryptionLevel::CXFA_EncryptionLevel(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::EncryptionLevel, + nullptr, + kAttributeData, + kName) {} + +CXFA_EncryptionLevel::~CXFA_EncryptionLevel() {} diff --git a/xfa/fxfa/parser/cxfa_encryptionlevel.h b/xfa/fxfa/parser/cxfa_encryptionlevel.h new file mode 100644 index 0000000000000000000000000000000000000000..1bb80ce1263c7d21cc47d7104d535d1fc6918267 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryptionlevel.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCRYPTIONLEVEL_H_ +#define XFA_FXFA_PARSER_CXFA_ENCRYPTIONLEVEL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EncryptionLevel : public CXFA_Node { + public: + CXFA_EncryptionLevel(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EncryptionLevel() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCRYPTIONLEVEL_H_ diff --git a/xfa/fxfa/parser/cxfa_encryptionmethod.cpp b/xfa/fxfa/parser/cxfa_encryptionmethod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3402e2247031ea834569f1ae8e75092fb34529f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryptionmethod.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encryptionmethod.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encryptionMethod"; + +} // namespace + +CXFA_EncryptionMethod::CXFA_EncryptionMethod(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeC, + XFA_Element::EncryptionMethod, + nullptr, + kAttributeData, + kName) {} + +CXFA_EncryptionMethod::~CXFA_EncryptionMethod() {} diff --git a/xfa/fxfa/parser/cxfa_encryptionmethod.h b/xfa/fxfa/parser/cxfa_encryptionmethod.h new file mode 100644 index 0000000000000000000000000000000000000000..2c86001c935ffe9bd997840a687aeff0ae7a738c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryptionmethod.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCRYPTIONMETHOD_H_ +#define XFA_FXFA_PARSER_CXFA_ENCRYPTIONMETHOD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EncryptionMethod : public CXFA_Node { + public: + CXFA_EncryptionMethod(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EncryptionMethod() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCRYPTIONMETHOD_H_ diff --git a/xfa/fxfa/parser/cxfa_encryptionmethods.cpp b/xfa/fxfa/parser/cxfa_encryptionmethods.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4120314bf41e70b51809b0537ef76c2ea530f19 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryptionmethods.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_encryptionmethods.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"encryptionMethods"; + +} // namespace + +CXFA_EncryptionMethods::CXFA_EncryptionMethods(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::EncryptionMethods, + nullptr, + kAttributeData, + kName) {} + +CXFA_EncryptionMethods::~CXFA_EncryptionMethods() {} diff --git a/xfa/fxfa/parser/cxfa_encryptionmethods.h b/xfa/fxfa/parser/cxfa_encryptionmethods.h new file mode 100644 index 0000000000000000000000000000000000000000..9fcc0b5e9fcef650f1040af54f01fe5890bfea20 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_encryptionmethods.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENCRYPTIONMETHODS_H_ +#define XFA_FXFA_PARSER_CXFA_ENCRYPTIONMETHODS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EncryptionMethods : public CXFA_Node { + public: + CXFA_EncryptionMethods(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EncryptionMethods() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENCRYPTIONMETHODS_H_ diff --git a/xfa/fxfa/parser/cxfa_enforce.cpp b/xfa/fxfa/parser/cxfa_enforce.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59b6426ec9314f19e22fff2ba6bc77e2c68fc018 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_enforce.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_enforce.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"enforce"; + +} // namespace + +CXFA_Enforce::CXFA_Enforce(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Enforce, + nullptr, + kAttributeData, + kName) {} + +CXFA_Enforce::~CXFA_Enforce() {} diff --git a/xfa/fxfa/parser/cxfa_enforce.h b/xfa/fxfa/parser/cxfa_enforce.h new file mode 100644 index 0000000000000000000000000000000000000000..3ccd8b8f2b499cf42e8f478c8c7683dc3b5e325e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_enforce.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ENFORCE_H_ +#define XFA_FXFA_PARSER_CXFA_ENFORCE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Enforce : public CXFA_Node { + public: + CXFA_Enforce(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Enforce() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ENFORCE_H_ diff --git a/xfa/fxfa/parser/cxfa_equate.cpp b/xfa/fxfa/parser/cxfa_equate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e927fbcf4c743a9668ce8948ecbee2da48d98f44 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_equate.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_equate.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::To, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Force, XFA_AttributeType::Boolean, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::From, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"equate"; + +} // namespace + +CXFA_Equate::CXFA_Equate(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Equate, + nullptr, + kAttributeData, + kName) {} + +CXFA_Equate::~CXFA_Equate() {} diff --git a/xfa/fxfa/parser/cxfa_equate.h b/xfa/fxfa/parser/cxfa_equate.h new file mode 100644 index 0000000000000000000000000000000000000000..0a28182ee81f6c8cff54321d25cd4ef2b7ef8e41 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_equate.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EQUATE_H_ +#define XFA_FXFA_PARSER_CXFA_EQUATE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Equate : public CXFA_Node { + public: + CXFA_Equate(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Equate() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EQUATE_H_ diff --git a/xfa/fxfa/parser/cxfa_equaterange.cpp b/xfa/fxfa/parser/cxfa_equaterange.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f46a1f92f5a6789f25a927cbfc6fc1b0391e55d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_equaterange.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_equaterange.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::To, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::UnicodeRange, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::From, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"equateRange"; + +} // namespace + +CXFA_EquateRange::CXFA_EquateRange(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::EquateRange, + nullptr, + kAttributeData, + kName) {} + +CXFA_EquateRange::~CXFA_EquateRange() {} diff --git a/xfa/fxfa/parser/cxfa_equaterange.h b/xfa/fxfa/parser/cxfa_equaterange.h new file mode 100644 index 0000000000000000000000000000000000000000..86c86b1870d474ed2f4ac4bbb35e3eeb39e5c959 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_equaterange.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EQUATERANGE_H_ +#define XFA_FXFA_PARSER_CXFA_EQUATERANGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EquateRange : public CXFA_Node { + public: + CXFA_EquateRange(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EquateRange() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EQUATERANGE_H_ diff --git a/xfa/fxfa/parser/cxfa_era.cpp b/xfa/fxfa/parser/cxfa_era.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6051676b143d426f414afd339f2821c41c96ac99 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_era.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_era.h" + +namespace { + +constexpr wchar_t kName[] = L"era"; + +} // namespace + +CXFA_Era::CXFA_Era(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::Era, + nullptr, + nullptr, + kName) {} + +CXFA_Era::~CXFA_Era() {} diff --git a/xfa/fxfa/parser/cxfa_era.h b/xfa/fxfa/parser/cxfa_era.h new file mode 100644 index 0000000000000000000000000000000000000000..a46a574180097b12dcb15aaa1cf548dfe0bcdcf9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_era.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ERA_H_ +#define XFA_FXFA_PARSER_CXFA_ERA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Era : public CXFA_Node { + public: + CXFA_Era(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Era() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ERA_H_ diff --git a/xfa/fxfa/parser/cxfa_eranames.cpp b/xfa/fxfa/parser/cxfa_eranames.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06bd2ca4efec6172b9f2333b6a0b0b62cdb92c4b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_eranames.cpp @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_eranames.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Era, 2, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"eraNames"; + +} // namespace + +CXFA_EraNames::CXFA_EraNames(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::EraNames, + kPropertyData, + nullptr, + kName) {} + +CXFA_EraNames::~CXFA_EraNames() {} diff --git a/xfa/fxfa/parser/cxfa_eranames.h b/xfa/fxfa/parser/cxfa_eranames.h new file mode 100644 index 0000000000000000000000000000000000000000..4c8f7880a7f44e98a741d506b51dfaf96f1e4afa --- /dev/null +++ b/xfa/fxfa/parser/cxfa_eranames.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ERANAMES_H_ +#define XFA_FXFA_PARSER_CXFA_ERANAMES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_EraNames : public CXFA_Node { + public: + CXFA_EraNames(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_EraNames() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ERANAMES_H_ diff --git a/xfa/fxfa/parser/cxfa_event.cpp b/xfa/fxfa/parser/cxfa_event.cpp index 3e5639617b18c864928810def9a1b3bd3c70b22b..d4af2fff8e8cd23312a929e5631e2abac480b8ae 100644 --- a/xfa/fxfa/parser/cxfa_event.cpp +++ b/xfa/fxfa/parser/cxfa_event.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,44 +6,73 @@ #include "xfa/fxfa/parser/cxfa_event.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_event.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxfa/parser/cxfa_submit.h" -CXFA_Event::CXFA_Event(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -int32_t CXFA_Event::GetActivity() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_Activity); +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Execute, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Script, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::SignData, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Submit, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Listen, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::RefOnly}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Activity, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Click}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"event"; + +} // namespace + +CXFA_Event::CXFA_Event(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Event, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Event>(this)) {} + +CXFA_Event::~CXFA_Event() {} + +XFA_AttributeEnum CXFA_Event::GetActivity() { + return JSObject()->GetEnum(XFA_Attribute::Activity); } -XFA_Element CXFA_Event::GetEventType() { - CXFA_Node* pChild = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); +XFA_Element CXFA_Event::GetEventType() const { + CXFA_Node* pChild = GetFirstChild(); while (pChild) { XFA_Element eType = pChild->GetElementType(); if (eType != XFA_Element::Extras) return eType; - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); + pChild = pChild->GetNextSibling(); } return XFA_Element::Unknown; } -void CXFA_Event::GetRef(CFX_WideStringC& wsRef) { - m_pNode->TryCData(XFA_ATTRIBUTE_Ref, wsRef); -} - -CXFA_Script CXFA_Event::GetScript() { - return CXFA_Script(m_pNode->GetChild(0, XFA_Element::Script)); +WideString CXFA_Event::GetRef() { + return JSObject()->GetCData(XFA_Attribute::Ref); } -CXFA_Submit CXFA_Event::GetSubmit() { - return CXFA_Submit(m_pNode->GetChild(0, XFA_Element::Submit)); +CXFA_Script* CXFA_Event::GetScriptIfExists() { + return GetChild<CXFA_Script>(0, XFA_Element::Script, false); } -void CXFA_Event::GetSignDataTarget(CFX_WideString& wsTarget) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::SignData); - if (!pNode) - return; - - CFX_WideStringC wsCData; - pNode->TryCData(XFA_ATTRIBUTE_Target, wsCData); - wsTarget = wsCData; +CXFA_Submit* CXFA_Event::GetSubmitIfExists() { + return GetChild<CXFA_Submit>(0, XFA_Element::Submit, false); } diff --git a/xfa/fxfa/parser/cxfa_event.h b/xfa/fxfa/parser/cxfa_event.h index b151b399b594bbf881d0859b9b646e8377818e71..a410805675f18accbdf3c81253d184254e539059 100644 --- a/xfa/fxfa/parser/cxfa_event.h +++ b/xfa/fxfa/parser/cxfa_event.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,27 +7,21 @@ #ifndef XFA_FXFA_PARSER_CXFA_EVENT_H_ #define XFA_FXFA_PARSER_CXFA_EVENT_H_ -#include <stdint.h> +#include "xfa/fxfa/parser/cxfa_node.h" -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_script.h" -#include "xfa/fxfa/parser/cxfa_submit.h" +class CXFA_Script; +class CXFA_Submit; -class CXFA_Node; - -class CXFA_Event : public CXFA_Data { +class CXFA_Event : public CXFA_Node { public: - explicit CXFA_Event(CXFA_Node* pNode); - - int32_t GetActivity(); - XFA_Element GetEventType(); - void GetRef(CFX_WideStringC& wsRef); - - CXFA_Script GetScript(); - CXFA_Submit GetSubmit(); - - void GetSignDataTarget(CFX_WideString& wsTarget); + CXFA_Event(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Event() override; + + XFA_AttributeEnum GetActivity(); + XFA_Element GetEventType() const; + CXFA_Script* GetScriptIfExists(); + CXFA_Submit* GetSubmitIfExists(); + WideString GetRef(); }; #endif // XFA_FXFA_PARSER_CXFA_EVENT_H_ diff --git a/xfa/fxfa/parser/cxfa_exclgroup.cpp b/xfa/fxfa/parser/cxfa_exclgroup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a24dc363425f038e6e90617436b1d9ec3e6f38cf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_exclgroup.cpp @@ -0,0 +1,66 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_exclgroup.h" + +#include "fxjs/xfa/cjx_exclgroup.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Margin, 1, 0}, {XFA_Element::Para, 1, 0}, + {XFA_Element::Border, 1, 0}, {XFA_Element::Assist, 1, 0}, + {XFA_Element::Traversal, 1, 0}, {XFA_Element::Validate, 1, 0}, + {XFA_Element::Caption, 1, 0}, {XFA_Element::Bind, 1, 0}, + {XFA_Element::Desc, 1, 0}, {XFA_Element::Calculate, 1, 0}, + {XFA_Element::Extras, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::H, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::W, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Left}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Access, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Open}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::VAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Top}, + {XFA_Attribute::MaxH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MaxW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Layout, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Position}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ColSpan, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AnchorType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::TopLeft}, + {XFA_Attribute::AccessKey, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"exclGroup"; + +} // namespace + +CXFA_ExclGroup::CXFA_ExclGroup(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::ExclGroup, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ExclGroup>(this)) {} + +CXFA_ExclGroup::~CXFA_ExclGroup() {} diff --git a/xfa/fxfa/parser/cxfa_exclgroup.h b/xfa/fxfa/parser/cxfa_exclgroup.h new file mode 100644 index 0000000000000000000000000000000000000000..5a3c8a3feeaaa9e100b8f28374fa6ee922506e13 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_exclgroup.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EXCLGROUP_H_ +#define XFA_FXFA_PARSER_CXFA_EXCLGROUP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ExclGroup : public CXFA_Node { + public: + CXFA_ExclGroup(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ExclGroup() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EXCLGROUP_H_ diff --git a/xfa/fxfa/parser/cxfa_exclude.cpp b/xfa/fxfa/parser/cxfa_exclude.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e07d92a14603624e236c7fbadcf8568fdbb1d014 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_exclude.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_exclude.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"exclude"; + +} // namespace + +CXFA_Exclude::CXFA_Exclude(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Exclude, + nullptr, + kAttributeData, + kName) {} + +CXFA_Exclude::~CXFA_Exclude() {} diff --git a/xfa/fxfa/parser/cxfa_exclude.h b/xfa/fxfa/parser/cxfa_exclude.h new file mode 100644 index 0000000000000000000000000000000000000000..0f78707ea6779bc1f3f128fe8a15ae6cf300523d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_exclude.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EXCLUDE_H_ +#define XFA_FXFA_PARSER_CXFA_EXCLUDE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Exclude : public CXFA_Node { + public: + CXFA_Exclude(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Exclude() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EXCLUDE_H_ diff --git a/xfa/fxfa/parser/cxfa_excludens.cpp b/xfa/fxfa/parser/cxfa_excludens.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b149e864e03313ca1385f4e7e8b02d99fbd3b434 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_excludens.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_excludens.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"excludeNS"; + +} // namespace + +CXFA_ExcludeNS::CXFA_ExcludeNS(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::ExcludeNS, + nullptr, + kAttributeData, + kName) {} + +CXFA_ExcludeNS::~CXFA_ExcludeNS() {} diff --git a/xfa/fxfa/parser/cxfa_excludens.h b/xfa/fxfa/parser/cxfa_excludens.h new file mode 100644 index 0000000000000000000000000000000000000000..c5cb548e538c532f7d76130e485dbbad0f531208 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_excludens.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EXCLUDENS_H_ +#define XFA_FXFA_PARSER_CXFA_EXCLUDENS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ExcludeNS : public CXFA_Node { + public: + CXFA_ExcludeNS(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ExcludeNS() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EXCLUDENS_H_ diff --git a/xfa/fxfa/parser/cxfa_exdata.cpp b/xfa/fxfa/parser/cxfa_exdata.cpp index bf1e930330e457615668d71e578008b8eb5e2abe..cf57796ccccbced3c93aa6acd8de9b6f967e3647 100644 --- a/xfa/fxfa/parser/cxfa_exdata.cpp +++ b/xfa/fxfa/parser/cxfa_exdata.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,10 +6,41 @@ #include "xfa/fxfa/parser/cxfa_exdata.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_exdata.h" +#include "third_party/base/ptr_util.h" -CXFA_ExData::CXFA_ExData(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -bool CXFA_ExData::SetContentType(const CFX_WideString& wsContentType) { - return m_pNode->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType); +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Rid, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ContentType, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TransferEncoding, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::MaxLength, XFA_AttributeType::Integer, (void*)-1}, + {XFA_Attribute::Href, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"exData"; + +} // namespace + +CXFA_ExData::CXFA_ExData(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::ExData, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ExData>(this)) {} + +CXFA_ExData::~CXFA_ExData() {} + +void CXFA_ExData::SetContentType(const WideString& wsContentType) { + JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType, false, false); } diff --git a/xfa/fxfa/parser/cxfa_exdata.h b/xfa/fxfa/parser/cxfa_exdata.h index c92bacd3f2eff54cc880382a8fafba1bdccbbb20..8eb3caf76b0db6684375b0aa810fa3acfb95bdce 100644 --- a/xfa/fxfa/parser/cxfa_exdata.h +++ b/xfa/fxfa/parser/cxfa_exdata.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,16 +7,14 @@ #ifndef XFA_FXFA_PARSER_CXFA_EXDATA_H_ #define XFA_FXFA_PARSER_CXFA_EXDATA_H_ -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_ExData : public CXFA_Data { +class CXFA_ExData : public CXFA_Node { public: - explicit CXFA_ExData(CXFA_Node* pNode); + CXFA_ExData(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ExData() override; - bool SetContentType(const CFX_WideString& wsContentType); + void SetContentType(const WideString& wsContentType); }; #endif // XFA_FXFA_PARSER_CXFA_EXDATA_H_ diff --git a/xfa/fxfa/parser/cxfa_execute.cpp b/xfa/fxfa/parser/cxfa_execute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4196e8f128e646a0bfc68025b57a2c291c6e1a3b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_execute.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_execute.h" + +#include "fxjs/xfa/cjx_execute.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Connection, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::RunAt, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Client}, + {XFA_Attribute::ExecuteType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Import}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"execute"; + +} // namespace + +CXFA_Execute::CXFA_Execute(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Execute, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Execute>(this)) {} + +CXFA_Execute::~CXFA_Execute() {} diff --git a/xfa/fxfa/parser/cxfa_execute.h b/xfa/fxfa/parser/cxfa_execute.h new file mode 100644 index 0000000000000000000000000000000000000000..2d9f1581adc16b5de8fd49674ff1a3addb055a20 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_execute.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EXECUTE_H_ +#define XFA_FXFA_PARSER_CXFA_EXECUTE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Execute : public CXFA_Node { + public: + CXFA_Execute(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Execute() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EXECUTE_H_ diff --git a/xfa/fxfa/parser/cxfa_exobject.cpp b/xfa/fxfa/parser/cxfa_exobject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fff1d2e033eef66b415c19ea2714229bcedc329c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_exobject.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_exobject.h" + +#include "fxjs/xfa/cjx_exobject.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CodeType, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Archive, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CodeBase, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ClassId, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"exObject"; + +} // namespace + +CXFA_ExObject::CXFA_ExObject(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::ExObject, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ExObject>(this)) {} + +CXFA_ExObject::~CXFA_ExObject() {} diff --git a/xfa/fxfa/parser/cxfa_exobject.h b/xfa/fxfa/parser/cxfa_exobject.h new file mode 100644 index 0000000000000000000000000000000000000000..b4d7de9eb8f09bfee89b9755277fcb65dc38093b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_exobject.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EXOBJECT_H_ +#define XFA_FXFA_PARSER_CXFA_EXOBJECT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ExObject : public CXFA_Node { + public: + CXFA_ExObject(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ExObject() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EXOBJECT_H_ diff --git a/xfa/fxfa/parser/cxfa_extras.cpp b/xfa/fxfa/parser/cxfa_extras.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4609e6fc2a82662baa8bb14fcdd2ea87c19e920f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_extras.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_extras.h" + +#include "fxjs/xfa/cjx_extras.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"extras"; + +} // namespace + +CXFA_Extras::CXFA_Extras(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | + XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Extras, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Extras>(this)) {} + +CXFA_Extras::~CXFA_Extras() {} diff --git a/xfa/fxfa/parser/cxfa_extras.h b/xfa/fxfa/parser/cxfa_extras.h new file mode 100644 index 0000000000000000000000000000000000000000..3b3c6b4a95748af6d35c3d666d4125bec9b90e00 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_extras.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_EXTRAS_H_ +#define XFA_FXFA_PARSER_CXFA_EXTRAS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Extras : public CXFA_Node { + public: + CXFA_Extras(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Extras() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_EXTRAS_H_ diff --git a/xfa/fxfa/parser/cxfa_field.cpp b/xfa/fxfa/parser/cxfa_field.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56b8d59811856a3621b55ec7d8c35dc62cd8d946 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_field.cpp @@ -0,0 +1,69 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_field.h" + +#include "fxjs/xfa/cjx_field.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Ui, 1, 0}, {XFA_Element::Margin, 1, 0}, + {XFA_Element::Para, 1, 0}, {XFA_Element::Format, 1, 0}, + {XFA_Element::Border, 1, 0}, {XFA_Element::Assist, 1, 0}, + {XFA_Element::Traversal, 1, 0}, {XFA_Element::Keep, 1, 0}, + {XFA_Element::Validate, 1, 0}, {XFA_Element::Caption, 1, 0}, + {XFA_Element::Bind, 1, 0}, {XFA_Element::Desc, 1, 0}, + {XFA_Element::Font, 1, 0}, {XFA_Element::Value, 1, 0}, + {XFA_Element::Calculate, 1, 0}, {XFA_Element::Extras, 1, 0}, + {XFA_Element::Items, 2, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::H, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::W, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Left}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Access, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Open}, + {XFA_Attribute::Rotate, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::VAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Top}, + {XFA_Attribute::MaxH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MaxW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ColSpan, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Locale, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AnchorType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::TopLeft}, + {XFA_Attribute::AccessKey, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"field"; + +} // namespace + +CXFA_Field::CXFA_Field(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::Field, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Field>(this)) {} + +CXFA_Field::~CXFA_Field() {} diff --git a/xfa/fxfa/parser/cxfa_field.h b/xfa/fxfa/parser/cxfa_field.h new file mode 100644 index 0000000000000000000000000000000000000000..b2f7a052debe5b3255682f1816b04ff04c762de1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_field.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FIELD_H_ +#define XFA_FXFA_PARSER_CXFA_FIELD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Field : public CXFA_Node { + public: + CXFA_Field(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Field() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FIELD_H_ diff --git a/xfa/fxfa/parser/cxfa_fill.cpp b/xfa/fxfa/parser/cxfa_fill.cpp index 63949c193dd47111c28899981c617d1b430ff82a..4cbd8f812c9d448c4f9c713646a6f8ae1889593b 100644 --- a/xfa/fxfa/parser/cxfa_fill.cpp +++ b/xfa/fxfa/parser/cxfa_fill.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,98 +6,151 @@ #include "xfa/fxfa/parser/cxfa_fill.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_fill.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_color.h" +#include "xfa/fxfa/parser/cxfa_linear.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_pattern.h" +#include "xfa/fxfa/parser/cxfa_radial.h" +#include "xfa/fxfa/parser/cxfa_stipple.h" -CXFA_Fill::CXFA_Fill(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Pattern, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Solid, 1, + XFA_PROPERTYFLAG_OneOf | XFA_PROPERTYFLAG_DefaultOneOf}, + {XFA_Element::Stipple, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Color, 1, 0}, + {XFA_Element::Linear, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Radial, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"fill"; + +} // namespace + +CXFA_Fill::CXFA_Fill(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Fill, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Fill>(this)) {} CXFA_Fill::~CXFA_Fill() {} -int32_t CXFA_Fill::GetPresence() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_Presence); +bool CXFA_Fill::IsVisible() { + return JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible) == + XFA_AttributeEnum::Visible; } void CXFA_Fill::SetColor(FX_ARGB color) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Color); - CFX_WideString wsColor; - int a, r, g, b; - ArgbDecode(color, a, r, g, b); - wsColor.Format(L"%d,%d,%d", r, g, b); - pNode->SetCData(XFA_ATTRIBUTE_Value, wsColor); + CXFA_Color* pColor = + JSObject()->GetOrCreateProperty<CXFA_Color>(0, XFA_Element::Color); + if (!pColor) + return; + + pColor->SetValue(color); } FX_ARGB CXFA_Fill::GetColor(bool bText) { - if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Color)) { - CFX_WideStringC wsColor; - if (pNode->TryCData(XFA_ATTRIBUTE_Value, wsColor, false)) - return CXFA_Data::ToColor(wsColor); - } - if (bText) - return 0xFF000000; - return 0xFFFFFFFF; + CXFA_Color* pColor = GetChild<CXFA_Color>(0, XFA_Element::Color, false); + if (!pColor) + return bText ? 0xFF000000 : 0xFFFFFFFF; + return pColor->GetValueOrDefault(bText ? 0xFF000000 : 0xFFFFFFFF); } -XFA_Element CXFA_Fill::GetFillType() { - CXFA_Node* pChild = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); +XFA_Element CXFA_Fill::GetType() const { + CXFA_Node* pChild = GetFirstChild(); while (pChild) { XFA_Element eType = pChild->GetElementType(); if (eType != XFA_Element::Color && eType != XFA_Element::Extras) return eType; - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); + pChild = pChild->GetNextSibling(); } return XFA_Element::Solid; } -int32_t CXFA_Fill::GetPattern(FX_ARGB& foreColor) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Pattern); - if (CXFA_Node* pColor = pNode->GetChild(0, XFA_Element::Color)) { - CFX_WideStringC wsColor; - pColor->TryCData(XFA_ATTRIBUTE_Value, wsColor, false); - foreColor = CXFA_Data::ToColor(wsColor); - } else { - foreColor = 0xFF000000; +void CXFA_Fill::Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix) { + pGS->SaveGraphState(); + + switch (GetType()) { + case XFA_Element::Radial: + DrawRadial(pGS, fillPath, rtWidget, matrix); + break; + case XFA_Element::Pattern: + DrawPattern(pGS, fillPath, rtWidget, matrix); + break; + case XFA_Element::Linear: + DrawLinear(pGS, fillPath, rtWidget, matrix); + break; + case XFA_Element::Stipple: + DrawStipple(pGS, fillPath, rtWidget, matrix); + break; + default: + pGS->SetFillColor(CXFA_GEColor(GetColor(false))); + pGS->FillPath(fillPath, FXFILL_WINDING, &matrix); + break; } - return pNode->GetEnum(XFA_ATTRIBUTE_Type); + + pGS->RestoreGraphState(); } -int32_t CXFA_Fill::GetStipple(FX_ARGB& stippleColor) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Stipple); - int32_t eAttr = 50; - pNode->TryInteger(XFA_ATTRIBUTE_Rate, eAttr); - if (CXFA_Node* pColor = pNode->GetChild(0, XFA_Element::Color)) { - CFX_WideStringC wsColor; - pColor->TryCData(XFA_ATTRIBUTE_Value, wsColor, false); - stippleColor = CXFA_Data::ToColor(wsColor); - } else { - stippleColor = 0xFF000000; - } - return eAttr; +void CXFA_Fill::DrawStipple(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix) { + CXFA_Stipple* stipple = + JSObject()->GetOrCreateProperty<CXFA_Stipple>(0, XFA_Element::Stipple); + if (stipple) + stipple->Draw(pGS, fillPath, rtWidget, matrix); } -int32_t CXFA_Fill::GetLinear(FX_ARGB& endColor) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Linear); - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_ToRight; - pNode->TryEnum(XFA_ATTRIBUTE_Type, eAttr); - if (CXFA_Node* pColor = pNode->GetChild(0, XFA_Element::Color)) { - CFX_WideStringC wsColor; - pColor->TryCData(XFA_ATTRIBUTE_Value, wsColor, false); - endColor = CXFA_Data::ToColor(wsColor); - } else { - endColor = 0xFF000000; - } - return eAttr; +void CXFA_Fill::DrawRadial(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix) { + CXFA_Radial* radial = + JSObject()->GetOrCreateProperty<CXFA_Radial>(0, XFA_Element::Radial); + if (radial) + radial->Draw(pGS, fillPath, GetColor(false), rtWidget, matrix); } -int32_t CXFA_Fill::GetRadial(FX_ARGB& endColor) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Radial); - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_ToEdge; - pNode->TryEnum(XFA_ATTRIBUTE_Type, eAttr); - if (CXFA_Node* pColor = pNode->GetChild(0, XFA_Element::Color)) { - CFX_WideStringC wsColor; - pColor->TryCData(XFA_ATTRIBUTE_Value, wsColor, false); - endColor = CXFA_Data::ToColor(wsColor); - } else { - endColor = 0xFF000000; - } - return eAttr; +void CXFA_Fill::DrawLinear(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix) { + CXFA_Linear* linear = + JSObject()->GetOrCreateProperty<CXFA_Linear>(0, XFA_Element::Linear); + if (linear) + linear->Draw(pGS, fillPath, GetColor(false), rtWidget, matrix); +} + +void CXFA_Fill::DrawPattern(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix) { + CXFA_Pattern* pattern = + JSObject()->GetOrCreateProperty<CXFA_Pattern>(0, XFA_Element::Pattern); + if (pattern) + pattern->Draw(pGS, fillPath, GetColor(false), rtWidget, matrix); } diff --git a/xfa/fxfa/parser/cxfa_fill.h b/xfa/fxfa/parser/cxfa_fill.h index 4b13565765006db6856948bea5f6fe32e21be712..1ffdcdf2a314035a90f159f25160c192540d915a 100644 --- a/xfa/fxfa/parser/cxfa_fill.h +++ b/xfa/fxfa/parser/cxfa_fill.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,25 +7,51 @@ #ifndef XFA_FXFA_PARSER_CXFA_FILL_H_ #define XFA_FXFA_PARSER_CXFA_FILL_H_ -#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/fx_coordinates.h" #include "core/fxge/fx_dib.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_gepath.h" -class CXFA_Node; +class CXFA_Graphics; +class CXFA_Linear; +class CXFA_Pattern; +class CXFA_Radial; +class CXFA_Stipple; -class CXFA_Fill : public CXFA_Data { +class CXFA_Fill : public CXFA_Node { public: - explicit CXFA_Fill(CXFA_Node* pNode); - ~CXFA_Fill(); - - int32_t GetPresence(); - FX_ARGB GetColor(bool bText = false); - XFA_Element GetFillType(); - int32_t GetPattern(FX_ARGB& foreColor); - int32_t GetStipple(FX_ARGB& stippleColor); - int32_t GetLinear(FX_ARGB& endColor); - int32_t GetRadial(FX_ARGB& endColor); + CXFA_Fill(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Fill() override; + + bool IsVisible(); + + FX_ARGB GetColor(bool bText); void SetColor(FX_ARGB color); + + void Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix); + + private: + XFA_Element GetType() const; + + void DrawStipple(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix); + void DrawRadial(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix); + void DrawLinear(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix); + void DrawPattern(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtWidget, + const CFX_Matrix& matrix); }; #endif // XFA_FXFA_PARSER_CXFA_FILL_H_ diff --git a/xfa/fxfa/parser/cxfa_filter.cpp b/xfa/fxfa/parser/cxfa_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec6522d62a722ed176168bbd0f4285bd5219d75b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_filter.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_filter.h" + +#include "fxjs/xfa/cjx_filter.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Mdp, 1, 0}, {XFA_Element::Certificates, 1, 0}, + {XFA_Element::TimeStamp, 1, 0}, {XFA_Element::Handler, 1, 0}, + {XFA_Element::DigestMethods, 1, 0}, {XFA_Element::Encodings, 1, 0}, + {XFA_Element::Reasons, 1, 0}, {XFA_Element::AppearanceFilter, 1, 0}, + {XFA_Element::LockDocument, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Version, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AddRevocationInfo, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"filter"; + +} // namespace + +CXFA_Filter::CXFA_Filter(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Filter, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Filter>(this)) {} + +CXFA_Filter::~CXFA_Filter() {} diff --git a/xfa/fxfa/parser/cxfa_filter.h b/xfa/fxfa/parser/cxfa_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..2ac069ac242c57d6513f876041d4613d0c3f10ba --- /dev/null +++ b/xfa/fxfa/parser/cxfa_filter.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FILTER_H_ +#define XFA_FXFA_PARSER_CXFA_FILTER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Filter : public CXFA_Node { + public: + CXFA_Filter(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Filter() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FILTER_H_ diff --git a/xfa/fxfa/parser/cxfa_fliplabel.cpp b/xfa/fxfa/parser/cxfa_fliplabel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2227e8bb207286890cfb8117ec88fc7bebdd69bd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_fliplabel.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_fliplabel.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"flipLabel"; + +} // namespace + +CXFA_FlipLabel::CXFA_FlipLabel(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::FlipLabel, + nullptr, + kAttributeData, + kName) {} + +CXFA_FlipLabel::~CXFA_FlipLabel() {} diff --git a/xfa/fxfa/parser/cxfa_fliplabel.h b/xfa/fxfa/parser/cxfa_fliplabel.h new file mode 100644 index 0000000000000000000000000000000000000000..dac0564b516e967fbc1b1d000749b3e44cf294a4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_fliplabel.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FLIPLABEL_H_ +#define XFA_FXFA_PARSER_CXFA_FLIPLABEL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_FlipLabel : public CXFA_Node { + public: + CXFA_FlipLabel(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_FlipLabel() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FLIPLABEL_H_ diff --git a/xfa/fxfa/parser/cxfa_float.cpp b/xfa/fxfa/parser/cxfa_float.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83e574917e498ef5ba808faff5e83e21118a79b4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_float.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_float.h" + +#include "fxjs/xfa/cjx_float.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"float"; + +} // namespace + +CXFA_Float::CXFA_Float(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Float, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Float>(this)) {} + +CXFA_Float::~CXFA_Float() {} diff --git a/xfa/fxfa/parser/cxfa_float.h b/xfa/fxfa/parser/cxfa_float.h new file mode 100644 index 0000000000000000000000000000000000000000..f93b3dd199193873fd5ac7bea152a8e5e0c3a313 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_float.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FLOAT_H_ +#define XFA_FXFA_PARSER_CXFA_FLOAT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Float : public CXFA_Node { + public: + CXFA_Float(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Float() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FLOAT_H_ diff --git a/xfa/fxfa/parser/cxfa_font.cpp b/xfa/fxfa/parser/cxfa_font.cpp index cedfda6294e6d2619f17729ed78e5701b5d22281..694cb261470936837eb6aa6b700b3198795a2cdb 100644 --- a/xfa/fxfa/parser/cxfa_font.cpp +++ b/xfa/fxfa/parser/cxfa_font.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,88 +6,133 @@ #include "xfa/fxfa/parser/cxfa_font.h" -#include "core/fxge/fx_dib.h" +#include "fxjs/xfa/cjx_font.h" +#include "third_party/base/ptr_util.h" #include "xfa/fxfa/parser/cxfa_fill.h" #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_object.h" -CXFA_Font::CXFA_Font(CXFA_Node* pNode) : CXFA_Data(pNode) {} - -FX_FLOAT CXFA_Font::GetBaselineShift() { - return m_pNode->GetMeasure(XFA_ATTRIBUTE_BaselineShift).ToUnit(XFA_UNIT_Pt); +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Fill, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::LineThrough, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Typeface, XFA_AttributeType::CData, (void*)L"Courier"}, + {XFA_Attribute::FontHorizontalScale, XFA_AttributeType::CData, + (void*)L"100%"}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::KerningMode, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Underline, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::BaselineShift, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::OverlinePeriod, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::All}, + {XFA_Attribute::LetterSpacing, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::LineThroughPeriod, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::All}, + {XFA_Attribute::FontVerticalScale, XFA_AttributeType::CData, + (void*)L"100%"}, + {XFA_Attribute::PsName, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Size, XFA_AttributeType::Measure, (void*)L"10pt"}, + {XFA_Attribute::Posture, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Normal}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Weight, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Normal}, + {XFA_Attribute::UnderlinePeriod, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::All}, + {XFA_Attribute::Overline, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::GenericFamily, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Serif}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"font"; + +} // namespace + +CXFA_Font::CXFA_Font(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Font, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Font>(this)) {} + +CXFA_Font::~CXFA_Font() {} + +float CXFA_Font::GetBaselineShift() const { + return JSObject() + ->GetMeasure(XFA_Attribute::BaselineShift) + .ToUnit(XFA_Unit::Pt); } -FX_FLOAT CXFA_Font::GetHorizontalScale() { - CFX_WideString wsValue; - m_pNode->TryCData(XFA_ATTRIBUTE_FontHorizontalScale, wsValue); +float CXFA_Font::GetHorizontalScale() { + WideString wsValue = JSObject()->GetCData(XFA_Attribute::FontHorizontalScale); int32_t iScale = FXSYS_wtoi(wsValue.c_str()); - return iScale > 0 ? (FX_FLOAT)iScale : 100.0f; + return iScale > 0 ? (float)iScale : 100.0f; } -FX_FLOAT CXFA_Font::GetVerticalScale() { - CFX_WideString wsValue; - m_pNode->TryCData(XFA_ATTRIBUTE_FontVerticalScale, wsValue); +float CXFA_Font::GetVerticalScale() { + WideString wsValue = JSObject()->GetCData(XFA_Attribute::FontVerticalScale); int32_t iScale = FXSYS_wtoi(wsValue.c_str()); - return iScale > 0 ? (FX_FLOAT)iScale : 100.0f; + return iScale > 0 ? (float)iScale : 100.0f; } -FX_FLOAT CXFA_Font::GetLetterSpacing() { - CFX_WideStringC wsValue; - if (!m_pNode->TryCData(XFA_ATTRIBUTE_LetterSpacing, wsValue)) - return 0; - - CXFA_Measurement ms(wsValue); - if (ms.GetUnit() == XFA_UNIT_Em) +float CXFA_Font::GetLetterSpacing() { + WideString wsValue = JSObject()->GetCData(XFA_Attribute::LetterSpacing); + CXFA_Measurement ms(wsValue.AsStringView()); + if (ms.GetUnit() == XFA_Unit::Em) return ms.GetValue() * GetFontSize(); - return ms.ToUnit(XFA_UNIT_Pt); + return ms.ToUnit(XFA_Unit::Pt); } int32_t CXFA_Font::GetLineThrough() { - int32_t iValue = 0; - m_pNode->TryInteger(XFA_ATTRIBUTE_LineThrough, iValue); - return iValue; + return JSObject()->GetInteger(XFA_Attribute::LineThrough); } int32_t CXFA_Font::GetUnderline() { - int32_t iValue = 0; - m_pNode->TryInteger(XFA_ATTRIBUTE_Underline, iValue); - return iValue; + return JSObject()->GetInteger(XFA_Attribute::Underline); } -int32_t CXFA_Font::GetUnderlinePeriod() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_All; - m_pNode->TryEnum(XFA_ATTRIBUTE_UnderlinePeriod, eAttr); - return eAttr; +XFA_AttributeEnum CXFA_Font::GetUnderlinePeriod() { + return JSObject() + ->TryEnum(XFA_Attribute::UnderlinePeriod, true) + .value_or(XFA_AttributeEnum::All); } -FX_FLOAT CXFA_Font::GetFontSize() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_Size, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Font::GetFontSize() const { + return JSObject()->GetMeasure(XFA_Attribute::Size).ToUnit(XFA_Unit::Pt); } -void CXFA_Font::GetTypeface(CFX_WideStringC& wsTypeFace) { - m_pNode->TryCData(XFA_ATTRIBUTE_Typeface, wsTypeFace); +WideString CXFA_Font::GetTypeface() { + return JSObject()->GetCData(XFA_Attribute::Typeface); } bool CXFA_Font::IsBold() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_Normal; - m_pNode->TryEnum(XFA_ATTRIBUTE_Weight, eAttr); - return eAttr == XFA_ATTRIBUTEENUM_Bold; + return JSObject()->GetEnum(XFA_Attribute::Weight) == XFA_AttributeEnum::Bold; } bool CXFA_Font::IsItalic() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_Normal; - m_pNode->TryEnum(XFA_ATTRIBUTE_Posture, eAttr); - return eAttr == XFA_ATTRIBUTEENUM_Italic; + return JSObject()->GetEnum(XFA_Attribute::Posture) == + XFA_AttributeEnum::Italic; } void CXFA_Font::SetColor(FX_ARGB color) { - CXFA_Fill fill(m_pNode->GetProperty(0, XFA_Element::Fill)); - fill.SetColor(color); + CXFA_Fill* node = + JSObject()->GetOrCreateProperty<CXFA_Fill>(0, XFA_Element::Fill); + if (!node) + return; + + node->SetColor(color); } FX_ARGB CXFA_Font::GetColor() { - CXFA_Fill fill(m_pNode->GetChild(0, XFA_Element::Fill)); - return fill ? fill.GetColor(true) : 0xFF000000; + CXFA_Fill* fill = GetChild<CXFA_Fill>(0, XFA_Element::Fill, false); + return fill ? fill->GetColor(true) : 0xFF000000; } diff --git a/xfa/fxfa/parser/cxfa_font.h b/xfa/fxfa/parser/cxfa_font.h index 0342f68b278c9ffbade78095e710b91da48e579a..346be76720b5b529c10057e4383b9e20e75f2e38 100644 --- a/xfa/fxfa/parser/cxfa_font.h +++ b/xfa/fxfa/parser/cxfa_font.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,23 +8,22 @@ #define XFA_FXFA_PARSER_CXFA_FONT_H_ #include "core/fxge/fx_dib.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Font : public CXFA_Data { +class CXFA_Font : public CXFA_Node { public: - explicit CXFA_Font(CXFA_Node* pNode); + CXFA_Font(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Font() override; - FX_FLOAT GetBaselineShift(); - FX_FLOAT GetHorizontalScale(); - FX_FLOAT GetVerticalScale(); - FX_FLOAT GetLetterSpacing(); + float GetBaselineShift() const; + float GetHorizontalScale(); + float GetVerticalScale(); + float GetLetterSpacing(); int32_t GetLineThrough(); int32_t GetUnderline(); - int32_t GetUnderlinePeriod(); - FX_FLOAT GetFontSize(); - void GetTypeface(CFX_WideStringC& wsTypeFace); + XFA_AttributeEnum GetUnderlinePeriod(); + float GetFontSize() const; + WideString GetTypeface(); bool IsBold(); bool IsItalic(); diff --git a/xfa/fxfa/parser/cxfa_fontinfo.cpp b/xfa/fxfa/parser/cxfa_fontinfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee1dc6ed46fd07bb5562feae20252ba986330cf8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_fontinfo.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_fontinfo.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::SubsetBelow, 1, 0}, + {XFA_Element::Map, 1, 0}, + {XFA_Element::Embed, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"fontInfo"; + +} // namespace + +CXFA_FontInfo::CXFA_FontInfo(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::FontInfo, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_FontInfo::~CXFA_FontInfo() {} diff --git a/xfa/fxfa/parser/cxfa_fontinfo.h b/xfa/fxfa/parser/cxfa_fontinfo.h new file mode 100644 index 0000000000000000000000000000000000000000..f9facd803971633c45555aae3fddd0b56e9f1e0c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_fontinfo.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FONTINFO_H_ +#define XFA_FXFA_PARSER_CXFA_FONTINFO_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_FontInfo : public CXFA_Node { + public: + CXFA_FontInfo(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_FontInfo() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FONTINFO_H_ diff --git a/xfa/fxfa/parser/cxfa_form.cpp b/xfa/fxfa/parser/cxfa_form.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38ce7249a9897682c072c386659adfad2676e2fa --- /dev/null +++ b/xfa/fxfa/parser/cxfa_form.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_form.h" + +#include "fxjs/xfa/cjx_form.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Checksum, XFA_AttributeType::CData, (void*)nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"form"; + +} // namespace + +CXFA_Form::CXFA_Form(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Form, + XFA_ObjectType::ModelNode, + XFA_Element::Form, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Form>(this)) {} + +CXFA_Form::~CXFA_Form() {} diff --git a/xfa/fxfa/parser/cxfa_form.h b/xfa/fxfa/parser/cxfa_form.h new file mode 100644 index 0000000000000000000000000000000000000000..39d1d90a40817fdfaf5e2c519b544e095591dfe3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_form.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FORM_H_ +#define XFA_FXFA_PARSER_CXFA_FORM_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Form : public CXFA_Node { + public: + CXFA_Form(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Form() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FORM_H_ diff --git a/xfa/fxfa/parser/cxfa_format.cpp b/xfa/fxfa/parser/cxfa_format.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ebaaeb0f4ed74d1001c268f7ed6e4c600a4c86bf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_format.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_format.h" + +#include "fxjs/xfa/cjx_format.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Picture, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"format"; + +} // namespace + +CXFA_Format::CXFA_Format(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Format, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Format>(this)) {} + +CXFA_Format::~CXFA_Format() {} diff --git a/xfa/fxfa/parser/cxfa_format.h b/xfa/fxfa/parser/cxfa_format.h new file mode 100644 index 0000000000000000000000000000000000000000..3e31716062bd1a47d9434f5e8e4aa8d3f59bd76d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_format.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FORMAT_H_ +#define XFA_FXFA_PARSER_CXFA_FORMAT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Format : public CXFA_Node { + public: + CXFA_Format(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Format() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FORMAT_H_ diff --git a/xfa/fxfa/parser/cxfa_formfieldfilling.cpp b/xfa/fxfa/parser/cxfa_formfieldfilling.cpp new file mode 100644 index 0000000000000000000000000000000000000000..887e5cc3988415b424e9857c48677d844dd94734 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_formfieldfilling.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_formfieldfilling.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"formFieldFilling"; + +} // namespace + +CXFA_FormFieldFilling::CXFA_FormFieldFilling(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::FormFieldFilling, + nullptr, + kAttributeData, + kName) {} + +CXFA_FormFieldFilling::~CXFA_FormFieldFilling() {} diff --git a/xfa/fxfa/parser/cxfa_formfieldfilling.h b/xfa/fxfa/parser/cxfa_formfieldfilling.h new file mode 100644 index 0000000000000000000000000000000000000000..77f1b8f59afe53724970a7384b357a24f73b096d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_formfieldfilling.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_FORMFIELDFILLING_H_ +#define XFA_FXFA_PARSER_CXFA_FORMFIELDFILLING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_FormFieldFilling : public CXFA_Node { + public: + CXFA_FormFieldFilling(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_FormFieldFilling() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_FORMFIELDFILLING_H_ diff --git a/xfa/fxfa/parser/cxfa_groupparent.cpp b/xfa/fxfa/parser/cxfa_groupparent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca92d3ebb4ac8feb3bfdf7770faf5685babdf099 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_groupparent.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_groupparent.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"groupParent"; + +} // namespace + +CXFA_GroupParent::CXFA_GroupParent(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::GroupParent, + nullptr, + kAttributeData, + kName) {} + +CXFA_GroupParent::~CXFA_GroupParent() {} diff --git a/xfa/fxfa/parser/cxfa_groupparent.h b/xfa/fxfa/parser/cxfa_groupparent.h new file mode 100644 index 0000000000000000000000000000000000000000..7de296ce4e6b05d7979ac69ef740ca03468672a9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_groupparent.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_GROUPPARENT_H_ +#define XFA_FXFA_PARSER_CXFA_GROUPPARENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_GroupParent : public CXFA_Node { + public: + CXFA_GroupParent(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_GroupParent() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_GROUPPARENT_H_ diff --git a/xfa/fxfa/parser/cxfa_handler.cpp b/xfa/fxfa/parser/cxfa_handler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80f0f8158d1eebf30cf76919e9b4483dbfeb3f1a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_handler.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_handler.h" + +#include "fxjs/xfa/cjx_handler.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"handler"; + +} // namespace + +CXFA_Handler::CXFA_Handler(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::Handler, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Handler>(this)) {} + +CXFA_Handler::~CXFA_Handler() {} diff --git a/xfa/fxfa/parser/cxfa_handler.h b/xfa/fxfa/parser/cxfa_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..e575c0bc3025ccbd5561d184f20419af0b31f523 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_handler.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_HANDLER_H_ +#define XFA_FXFA_PARSER_CXFA_HANDLER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Handler : public CXFA_Node { + public: + CXFA_Handler(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Handler() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_HANDLER_H_ diff --git a/xfa/fxfa/parser/cxfa_hyphenation.cpp b/xfa/fxfa/parser/cxfa_hyphenation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e835ed7237f0dd0116406299f12340d1a774d24 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_hyphenation.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_hyphenation.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::WordCharacterCount, XFA_AttributeType::Integer, (void*)7}, + {XFA_Attribute::Hyphenate, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::ExcludeInitialCap, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::PushCharacterCount, XFA_AttributeType::Integer, (void*)3}, + {XFA_Attribute::RemainCharacterCount, XFA_AttributeType::Integer, (void*)3}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ExcludeAllCaps, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"hyphenation"; + +} // namespace + +CXFA_Hyphenation::CXFA_Hyphenation(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Hyphenation, + nullptr, + kAttributeData, + kName) {} + +CXFA_Hyphenation::~CXFA_Hyphenation() {} diff --git a/xfa/fxfa/parser/cxfa_hyphenation.h b/xfa/fxfa/parser/cxfa_hyphenation.h new file mode 100644 index 0000000000000000000000000000000000000000..2601c5fa1d5e5c50c74be0fc26ca1c5ca41c3f5f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_hyphenation.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_HYPHENATION_H_ +#define XFA_FXFA_PARSER_CXFA_HYPHENATION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Hyphenation : public CXFA_Node { + public: + CXFA_Hyphenation(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Hyphenation() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_HYPHENATION_H_ diff --git a/xfa/fxfa/parser/cxfa_ifempty.cpp b/xfa/fxfa/parser/cxfa_ifempty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae612ef1620d916ad3aa547a4b213792ce4db2bf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ifempty.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_ifempty.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"ifEmpty"; + +} // namespace + +CXFA_IfEmpty::CXFA_IfEmpty(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::IfEmpty, + nullptr, + kAttributeData, + kName) {} + +CXFA_IfEmpty::~CXFA_IfEmpty() {} diff --git a/xfa/fxfa/parser/cxfa_ifempty.h b/xfa/fxfa/parser/cxfa_ifempty.h new file mode 100644 index 0000000000000000000000000000000000000000..3c3c1b47a93fa1d874ff5eb8e4a86280ba205231 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ifempty.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_IFEMPTY_H_ +#define XFA_FXFA_PARSER_CXFA_IFEMPTY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_IfEmpty : public CXFA_Node { + public: + CXFA_IfEmpty(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_IfEmpty() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_IFEMPTY_H_ diff --git a/xfa/fxfa/parser/cxfa_image.cpp b/xfa/fxfa/parser/cxfa_image.cpp index 8cf7fc1e23065f5b7c4b0f046d00fc92d4e0164b..88ca977bb28e6534ee7d93d23488f2cac5ea0f58 100644 --- a/xfa/fxfa/parser/cxfa_image.cpp +++ b/xfa/fxfa/parser/cxfa_image.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,49 +6,70 @@ #include "xfa/fxfa/parser/cxfa_image.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_image.h" +#include "third_party/base/ptr_util.h" -CXFA_Image::CXFA_Image(CXFA_Node* pNode, bool bDefValue) - : CXFA_Data(pNode), m_bDefValue(bDefValue) {} +namespace { -int32_t CXFA_Image::GetAspect() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_Aspect); +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ContentType, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TransferEncoding, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Base64}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Aspect, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Fit}, + {XFA_Attribute::Href, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"image"; + +} // namespace + +CXFA_Image::CXFA_Image(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Image, + nullptr, + kAttributeData, + kName) {} + +CXFA_Image::~CXFA_Image() {} + +XFA_AttributeEnum CXFA_Image::GetAspect() { + return JSObject()->GetEnum(XFA_Attribute::Aspect); } -bool CXFA_Image::GetContentType(CFX_WideString& wsContentType) { - return m_pNode->TryCData(XFA_ATTRIBUTE_ContentType, wsContentType); +WideString CXFA_Image::GetContentType() { + return JSObject()->TryCData(XFA_Attribute::ContentType, true).value_or(L""); } -bool CXFA_Image::GetHref(CFX_WideString& wsHref) { - if (m_bDefValue) - return m_pNode->TryCData(XFA_ATTRIBUTE_Href, wsHref); - return m_pNode->GetAttribute(L"href", wsHref); +WideString CXFA_Image::GetHref() { + return JSObject()->TryCData(XFA_Attribute::Href, true).value_or(L""); } -int32_t CXFA_Image::GetTransferEncoding() { - if (m_bDefValue) - return m_pNode->GetEnum(XFA_ATTRIBUTE_TransferEncoding); - return XFA_ATTRIBUTEENUM_Base64; +XFA_AttributeEnum CXFA_Image::GetTransferEncoding() { + return static_cast<XFA_AttributeEnum>( + JSObject()->GetEnum(XFA_Attribute::TransferEncoding)); } -bool CXFA_Image::GetContent(CFX_WideString& wsText) { - return m_pNode->TryContent(wsText); +WideString CXFA_Image::GetContent() { + return JSObject()->TryContent(false, true).value_or(L""); } -bool CXFA_Image::SetContentType(const CFX_WideString& wsContentType) { - return m_pNode->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType); +void CXFA_Image::SetContentType(const WideString& wsContentType) { + JSObject()->SetCData(XFA_Attribute::ContentType, wsContentType, false, false); } -bool CXFA_Image::SetHref(const CFX_WideString& wsHref) { - if (m_bDefValue) - return m_pNode->SetCData(XFA_ATTRIBUTE_Href, wsHref); - return m_pNode->SetAttribute(XFA_ATTRIBUTE_Href, wsHref.AsStringC()); +void CXFA_Image::SetHref(const WideString& wsHref) { + JSObject()->SetCData(XFA_Attribute::Href, wsHref, false, false); } -bool CXFA_Image::SetTransferEncoding(int32_t iTransferEncoding) { - if (m_bDefValue) { - return m_pNode->SetEnum(XFA_ATTRIBUTE_TransferEncoding, - (XFA_ATTRIBUTEENUM)iTransferEncoding); - } - return true; +void CXFA_Image::SetTransferEncoding(XFA_AttributeEnum iTransferEncoding) { + JSObject()->SetEnum(XFA_Attribute::TransferEncoding, iTransferEncoding, + false); } diff --git a/xfa/fxfa/parser/cxfa_image.h b/xfa/fxfa/parser/cxfa_image.h index bf69897693ee5564535929d87dce6ab2b1f17c5a..3670863a3b3dbd5561d5d24791ceb194c01b092f 100644 --- a/xfa/fxfa/parser/cxfa_image.h +++ b/xfa/fxfa/parser/cxfa_image.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,27 +7,24 @@ #ifndef XFA_FXFA_PARSER_CXFA_IMAGE_H_ #define XFA_FXFA_PARSER_CXFA_IMAGE_H_ -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Image : public CXFA_Data { +class CXFA_Image : public CXFA_Node { public: - CXFA_Image(CXFA_Node* pNode, bool bDefValue); - - int32_t GetAspect(); - bool GetContentType(CFX_WideString& wsContentType); - bool GetHref(CFX_WideString& wsHref); - int32_t GetTransferEncoding(); - bool GetContent(CFX_WideString& wsText); - bool SetContentType(const CFX_WideString& wsContentType); - bool SetHref(const CFX_WideString& wsHref); - bool SetTransferEncoding(int32_t iTransferEncoding); - - protected: - bool m_bDefValue; + CXFA_Image(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Image() override; + + XFA_AttributeEnum GetAspect(); + WideString GetContent(); + + WideString GetHref(); + void SetHref(const WideString& wsHref); + + XFA_AttributeEnum GetTransferEncoding(); + void SetTransferEncoding(XFA_AttributeEnum iTransferEncoding); + + WideString GetContentType(); + void SetContentType(const WideString& wsContentType); }; #endif // XFA_FXFA_PARSER_CXFA_IMAGE_H_ diff --git a/xfa/fxfa/parser/cxfa_imageedit.cpp b/xfa/fxfa/parser/cxfa_imageedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f2108504ef09fa6e69e845b11f3394ff8b0c173 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_imageedit.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_imageedit.h" + +#include "fxjs/xfa/cjx_imageedit.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Data, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Link}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"imageEdit"; + +} // namespace + +CXFA_ImageEdit::CXFA_ImageEdit(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::ImageEdit, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ImageEdit>(this)) {} + +CXFA_ImageEdit::~CXFA_ImageEdit() {} diff --git a/xfa/fxfa/parser/cxfa_imageedit.h b/xfa/fxfa/parser/cxfa_imageedit.h new file mode 100644 index 0000000000000000000000000000000000000000..379750cd0ffc498c4e797a8557c758fcd085aea7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_imageedit.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_IMAGEEDIT_H_ +#define XFA_FXFA_PARSER_CXFA_IMAGEEDIT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ImageEdit : public CXFA_Node { + public: + CXFA_ImageEdit(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ImageEdit() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_IMAGEEDIT_H_ diff --git a/xfa/fxfa/parser/cxfa_includexdpcontent.cpp b/xfa/fxfa/parser/cxfa_includexdpcontent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc887d39485fb2af0267dd83f68131861b3e677b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_includexdpcontent.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_includexdpcontent.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"includeXDPContent"; + +} // namespace + +CXFA_IncludeXDPContent::CXFA_IncludeXDPContent(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::IncludeXDPContent, + nullptr, + kAttributeData, + kName) {} + +CXFA_IncludeXDPContent::~CXFA_IncludeXDPContent() {} diff --git a/xfa/fxfa/parser/cxfa_includexdpcontent.h b/xfa/fxfa/parser/cxfa_includexdpcontent.h new file mode 100644 index 0000000000000000000000000000000000000000..309a7c6ac6a03ba2cf8536c86d69c309d5577dfe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_includexdpcontent.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INCLUDEXDPCONTENT_H_ +#define XFA_FXFA_PARSER_CXFA_INCLUDEXDPCONTENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_IncludeXDPContent : public CXFA_Node { + public: + CXFA_IncludeXDPContent(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_IncludeXDPContent() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INCLUDEXDPCONTENT_H_ diff --git a/xfa/fxfa/parser/cxfa_incrementalload.cpp b/xfa/fxfa/parser/cxfa_incrementalload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43ba0cb7ed8c13f26389f5c701b254640c221106 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_incrementalload.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_incrementalload.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"incrementalLoad"; + +} // namespace + +CXFA_IncrementalLoad::CXFA_IncrementalLoad(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::IncrementalLoad, + nullptr, + kAttributeData, + kName) {} + +CXFA_IncrementalLoad::~CXFA_IncrementalLoad() {} diff --git a/xfa/fxfa/parser/cxfa_incrementalload.h b/xfa/fxfa/parser/cxfa_incrementalload.h new file mode 100644 index 0000000000000000000000000000000000000000..9ea8f29d388f1cd212f4235623c9a6374c561dd9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_incrementalload.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INCREMENTALLOAD_H_ +#define XFA_FXFA_PARSER_CXFA_INCREMENTALLOAD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_IncrementalLoad : public CXFA_Node { + public: + CXFA_IncrementalLoad(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_IncrementalLoad() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INCREMENTALLOAD_H_ diff --git a/xfa/fxfa/parser/cxfa_incrementalmerge.cpp b/xfa/fxfa/parser/cxfa_incrementalmerge.cpp new file mode 100644 index 0000000000000000000000000000000000000000..659dd2195f363b68e7ae7b99fd892aaff6cb83ac --- /dev/null +++ b/xfa/fxfa/parser/cxfa_incrementalmerge.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_incrementalmerge.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"incrementalMerge"; + +} // namespace + +CXFA_IncrementalMerge::CXFA_IncrementalMerge(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::IncrementalMerge, + nullptr, + kAttributeData, + kName) {} + +CXFA_IncrementalMerge::~CXFA_IncrementalMerge() {} diff --git a/xfa/fxfa/parser/cxfa_incrementalmerge.h b/xfa/fxfa/parser/cxfa_incrementalmerge.h new file mode 100644 index 0000000000000000000000000000000000000000..c8e655434d4b8cca16d9e6e2447395ab1ee85942 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_incrementalmerge.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INCREMENTALMERGE_H_ +#define XFA_FXFA_PARSER_CXFA_INCREMENTALMERGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_IncrementalMerge : public CXFA_Node { + public: + CXFA_IncrementalMerge(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_IncrementalMerge() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INCREMENTALMERGE_H_ diff --git a/xfa/fxfa/parser/cxfa_insert.cpp b/xfa/fxfa/parser/cxfa_insert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..998a7f81ebfb72efd2e4de4d5b30beaeb0491be4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_insert.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_insert.h" + +#include "fxjs/xfa/cjx_insert.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"insert"; + +} // namespace + +CXFA_Insert::CXFA_Insert(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::Insert, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Insert>(this)) {} + +CXFA_Insert::~CXFA_Insert() {} diff --git a/xfa/fxfa/parser/cxfa_insert.h b/xfa/fxfa/parser/cxfa_insert.h new file mode 100644 index 0000000000000000000000000000000000000000..92579c3178d8e987a61a5bd17a8eebc2470f4d0a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_insert.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INSERT_H_ +#define XFA_FXFA_PARSER_CXFA_INSERT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Insert : public CXFA_Node { + public: + CXFA_Insert(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Insert() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INSERT_H_ diff --git a/xfa/fxfa/parser/cxfa_instancemanager.cpp b/xfa/fxfa/parser/cxfa_instancemanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ba54990a355b8822b775024446c01dbdc07d7e2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_instancemanager.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_instancemanager.h" + +#include "fxjs/xfa/cjx_instancemanager.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Occur, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"instanceManager"; + +} // namespace + +CXFA_InstanceManager::CXFA_InstanceManager(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Form, + XFA_ObjectType::Node, + XFA_Element::InstanceManager, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_InstanceManager>(this)) {} + +CXFA_InstanceManager::~CXFA_InstanceManager() {} diff --git a/xfa/fxfa/parser/cxfa_instancemanager.h b/xfa/fxfa/parser/cxfa_instancemanager.h new file mode 100644 index 0000000000000000000000000000000000000000..1910b9228808026f21f6ab0a70b4d3281b7b08bf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_instancemanager.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INSTANCEMANAGER_H_ +#define XFA_FXFA_PARSER_CXFA_INSTANCEMANAGER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_InstanceManager : public CXFA_Node { + public: + CXFA_InstanceManager(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_InstanceManager() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INSTANCEMANAGER_H_ diff --git a/xfa/fxfa/parser/cxfa_integer.cpp b/xfa/fxfa/parser/cxfa_integer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd263abe4e1343d3913b9e2a63b66c63da7e36fd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_integer.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_integer.h" + +#include "fxjs/xfa/cjx_integer.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"integer"; + +} // namespace + +CXFA_Integer::CXFA_Integer(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | + XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Integer, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Integer>(this)) {} + +CXFA_Integer::~CXFA_Integer() {} diff --git a/xfa/fxfa/parser/cxfa_integer.h b/xfa/fxfa/parser/cxfa_integer.h new file mode 100644 index 0000000000000000000000000000000000000000..2e5631d3a1ccde179f6f72e2432126318305dabf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_integer.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INTEGER_H_ +#define XFA_FXFA_PARSER_CXFA_INTEGER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Integer : public CXFA_Node { + public: + CXFA_Integer(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Integer() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INTEGER_H_ diff --git a/xfa/fxfa/parser/cxfa_interactive.cpp b/xfa/fxfa/parser/cxfa_interactive.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e68d957c99ee21a13e432a3bca0fb7ad378f5bf7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_interactive.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_interactive.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"interactive"; + +} // namespace + +CXFA_Interactive::CXFA_Interactive(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Interactive, + nullptr, + kAttributeData, + kName) {} + +CXFA_Interactive::~CXFA_Interactive() {} diff --git a/xfa/fxfa/parser/cxfa_interactive.h b/xfa/fxfa/parser/cxfa_interactive.h new file mode 100644 index 0000000000000000000000000000000000000000..69f2918deef6d9b3508b7bcd1e6b900c7ee360c5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_interactive.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_INTERACTIVE_H_ +#define XFA_FXFA_PARSER_CXFA_INTERACTIVE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Interactive : public CXFA_Node { + public: + CXFA_Interactive(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Interactive() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_INTERACTIVE_H_ diff --git a/xfa/fxfa/parser/cxfa_issuers.cpp b/xfa/fxfa/parser/cxfa_issuers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44c70bcf6429a1dca2e0c882f6a77f3a3531d0ab --- /dev/null +++ b/xfa/fxfa/parser/cxfa_issuers.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_issuers.h" + +#include "fxjs/xfa/cjx_issuers.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"issuers"; + +} // namespace + +CXFA_Issuers::CXFA_Issuers(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Issuers, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Issuers>(this)) {} + +CXFA_Issuers::~CXFA_Issuers() {} diff --git a/xfa/fxfa/parser/cxfa_issuers.h b/xfa/fxfa/parser/cxfa_issuers.h new file mode 100644 index 0000000000000000000000000000000000000000..6b94f15e8c93439bfde9f6e4b6e4b5bf5b2ccdbc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_issuers.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ISSUERS_H_ +#define XFA_FXFA_PARSER_CXFA_ISSUERS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Issuers : public CXFA_Node { + public: + CXFA_Issuers(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Issuers() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ISSUERS_H_ diff --git a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..434d7ed892249ff07ec1cd8fec9f18802f4d231f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp @@ -0,0 +1,2843 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h" + +#include <algorithm> +#include <memory> +#include <utility> +#include <vector> + +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/logging.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_keep.h" +#include "xfa/fxfa/parser/cxfa_layoutcontext.h" +#include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_margin.h" +#include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" +#include "xfa/fxfa/parser/cxfa_occur.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +std::vector<WideString> SeparateStringW(const wchar_t* pStr, + int32_t iStrLen, + wchar_t delimiter) { + std::vector<WideString> ret; + if (!pStr) + return ret; + if (iStrLen < 0) + iStrLen = wcslen(pStr); + + const wchar_t* pToken = pStr; + const wchar_t* pEnd = pStr + iStrLen; + while (true) { + if (pStr >= pEnd || delimiter == *pStr) { + ret.push_back(WideString(pToken, pStr - pToken)); + pToken = pStr + 1; + if (pStr >= pEnd) + break; + } + pStr++; + } + return ret; +} + +void UpdateWidgetSize(CXFA_ContentLayoutItem* pLayoutItem, + float* fWidth, + float* fHeight) { + CXFA_Node* pNode = pLayoutItem->m_pFormNode; + switch (pNode->GetElementType()) { + case XFA_Element::Subform: + case XFA_Element::Area: + case XFA_Element::ExclGroup: + case XFA_Element::SubformSet: { + if (*fWidth < -XFA_LAYOUT_FLOAT_PERCISION) + *fWidth = pLayoutItem->m_sSize.width; + if (*fHeight < -XFA_LAYOUT_FLOAT_PERCISION) + *fHeight = pLayoutItem->m_sSize.height; + break; + } + case XFA_Element::Draw: + case XFA_Element::Field: { + pNode->GetDocument()->GetNotify()->StartFieldDrawLayout(pNode, *fWidth, + *fHeight); + break; + } + default: + NOTREACHED(); + } +} + +CFX_SizeF CalculateContainerSpecifiedSize(CXFA_Node* pFormNode, + bool* bContainerWidthAutoSize, + bool* bContainerHeightAutoSize) { + *bContainerWidthAutoSize = true; + *bContainerHeightAutoSize = true; + + XFA_Element eType = pFormNode->GetElementType(); + + CFX_SizeF containerSize; + if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup) { + Optional<CXFA_Measurement> wValue = + pFormNode->JSObject()->TryMeasure(XFA_Attribute::W, false); + if (wValue && wValue->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { + containerSize.width = wValue->ToUnit(XFA_Unit::Pt); + *bContainerWidthAutoSize = false; + } + + Optional<CXFA_Measurement> hValue = + pFormNode->JSObject()->TryMeasure(XFA_Attribute::H, false); + if (hValue && hValue->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { + containerSize.height = hValue->ToUnit(XFA_Unit::Pt); + *bContainerHeightAutoSize = false; + } + } + + if (*bContainerWidthAutoSize && eType == XFA_Element::Subform) { + Optional<CXFA_Measurement> maxW = + pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxW, false); + if (maxW && maxW->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { + containerSize.width = maxW->ToUnit(XFA_Unit::Pt); + *bContainerWidthAutoSize = false; + } + + Optional<CXFA_Measurement> maxH = + pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxH, false); + if (maxH && maxH->GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { + containerSize.height = maxH->ToUnit(XFA_Unit::Pt); + *bContainerHeightAutoSize = false; + } + } + return containerSize; +} + +CFX_SizeF CalculateContainerComponentSizeFromContentSize( + CXFA_Node* pFormNode, + bool bContainerWidthAutoSize, + float fContentCalculatedWidth, + bool bContainerHeightAutoSize, + float fContentCalculatedHeight, + const CFX_SizeF& currentContainerSize) { + CFX_SizeF componentSize = currentContainerSize; + CXFA_Margin* pMarginNode = + pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); + if (bContainerWidthAutoSize) { + componentSize.width = fContentCalculatedWidth; + if (pMarginNode) { + Optional<CXFA_Measurement> leftInset = + pMarginNode->JSObject()->TryMeasure(XFA_Attribute::LeftInset, false); + if (leftInset) + componentSize.width += leftInset->ToUnit(XFA_Unit::Pt); + + Optional<CXFA_Measurement> rightInset = + pMarginNode->JSObject()->TryMeasure(XFA_Attribute::RightInset, false); + if (rightInset) + componentSize.width += rightInset->ToUnit(XFA_Unit::Pt); + } + } + + if (bContainerHeightAutoSize) { + componentSize.height = fContentCalculatedHeight; + if (pMarginNode) { + Optional<CXFA_Measurement> topInset = + pMarginNode->JSObject()->TryMeasure(XFA_Attribute::TopInset, false); + if (topInset) + componentSize.height += topInset->ToUnit(XFA_Unit::Pt); + + Optional<CXFA_Measurement> bottomInset = + pMarginNode->JSObject()->TryMeasure(XFA_Attribute::BottomInset, + false); + if (bottomInset) + componentSize.height += bottomInset->ToUnit(XFA_Unit::Pt); + } + } + return componentSize; +} + +void RelocateTableRowCells(CXFA_ContentLayoutItem* pLayoutRow, + const std::vector<float>& rgSpecifiedColumnWidths, + XFA_AttributeEnum eLayout) { + bool bContainerWidthAutoSize = true; + bool bContainerHeightAutoSize = true; + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( + pLayoutRow->m_pFormNode, &bContainerWidthAutoSize, + &bContainerHeightAutoSize); + CXFA_Margin* pMarginNode = + pLayoutRow->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( + XFA_Element::Margin); + float fLeftInset = 0; + float fTopInset = 0; + float fRightInset = 0; + float fBottomInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fTopInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + fBottomInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } + + float fContentWidthLimit = + bContainerWidthAutoSize ? FLT_MAX + : containerSize.width - fLeftInset - fRightInset; + float fContentCurrentHeight = + pLayoutRow->m_sSize.height - fTopInset - fBottomInset; + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + float fCurrentColX = 0; + int32_t nCurrentColIdx = 0; + bool bMetWholeRowCell = false; + + for (auto* pLayoutChild = + static_cast<CXFA_ContentLayoutItem*>(pLayoutRow->m_pFirstChild); + pLayoutChild; pLayoutChild = static_cast<CXFA_ContentLayoutItem*>( + pLayoutChild->m_pNextSibling)) { + int32_t nOriginalColSpan = + pLayoutChild->m_pFormNode->JSObject()->GetInteger( + XFA_Attribute::ColSpan); + int32_t nColSpan = nOriginalColSpan; + float fColSpanWidth = 0; + if (nColSpan == -1 || + nCurrentColIdx + nColSpan > + pdfium::CollectionSize<int32_t>(rgSpecifiedColumnWidths)) { + nColSpan = pdfium::CollectionSize<int32_t>(rgSpecifiedColumnWidths) - + nCurrentColIdx; + } + for (int32_t i = 0; i < nColSpan; i++) + fColSpanWidth += rgSpecifiedColumnWidths[nCurrentColIdx + i]; + + if (nColSpan != nOriginalColSpan) { + fColSpanWidth = + bMetWholeRowCell ? 0 : std::max(fColSpanWidth, + pLayoutChild->m_sSize.height); + } + if (nOriginalColSpan == -1) + bMetWholeRowCell = true; + + pLayoutChild->m_sPos = CFX_PointF(fCurrentColX, 0); + pLayoutChild->m_sSize.width = fColSpanWidth; + if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) + continue; + + fCurrentColX += fColSpanWidth; + nCurrentColIdx += nColSpan; + float fNewHeight = bContainerHeightAutoSize ? -1 : fContentCurrentHeight; + UpdateWidgetSize(pLayoutChild, &fColSpanWidth, &fNewHeight); + pLayoutChild->m_sSize.height = fNewHeight; + if (bContainerHeightAutoSize) { + fContentCalculatedHeight = + std::max(fContentCalculatedHeight, pLayoutChild->m_sSize.height); + } + } + + if (bContainerHeightAutoSize) { + for (CXFA_ContentLayoutItem* pLayoutChild = + (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; + pLayoutChild; + pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { + UpdateWidgetSize(pLayoutChild, &pLayoutChild->m_sSize.width, + &fContentCalculatedHeight); + float fOldChildHeight = pLayoutChild->m_sSize.height; + pLayoutChild->m_sSize.height = fContentCalculatedHeight; + CXFA_Para* pParaNode = + pLayoutChild->m_pFormNode->GetFirstChildByClass<CXFA_Para>( + XFA_Element::Para); + if (pParaNode && pLayoutChild->m_pFirstChild) { + float fOffHeight = fContentCalculatedHeight - fOldChildHeight; + XFA_AttributeEnum eVType = + pParaNode->JSObject()->GetEnum(XFA_Attribute::VAlign); + switch (eVType) { + case XFA_AttributeEnum::Middle: + fOffHeight = fOffHeight / 2; + break; + case XFA_AttributeEnum::Bottom: + break; + case XFA_AttributeEnum::Top: + default: + fOffHeight = 0; + break; + } + if (fOffHeight > 0) { + for (CXFA_ContentLayoutItem* pInnerLayoutChild = + (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild; + pInnerLayoutChild; + pInnerLayoutChild = + (CXFA_ContentLayoutItem*)pInnerLayoutChild->m_pNextSibling) { + pInnerLayoutChild->m_sPos.y += fOffHeight; + } + } + } + } + } + + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = fCurrentColX; + if (fContentWidthLimit < FLT_MAX && + fContentWidthLimit > fChildSuppliedWidth) { + fChildSuppliedWidth = fContentWidthLimit; + } + fContentCalculatedWidth = + std::max(fContentCalculatedWidth, fChildSuppliedWidth); + } else { + fContentCalculatedWidth = containerSize.width - fLeftInset - fRightInset; + } + + if (pLayoutRow->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout) == + XFA_AttributeEnum::Rl_row) { + for (CXFA_ContentLayoutItem* pLayoutChild = + (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; + pLayoutChild; + pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { + pLayoutChild->m_sPos.x = fContentCalculatedWidth - + pLayoutChild->m_sPos.x - + pLayoutChild->m_sSize.width; + } + } + pLayoutRow->m_sSize = CalculateContainerComponentSizeFromContentSize( + pLayoutRow->m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); +} + +void UpdatePendingItemLayout(CXFA_ItemLayoutProcessor* pProcessor, + CXFA_ContentLayoutItem* pLayoutItem) { + XFA_AttributeEnum eLayout = + pLayoutItem->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + switch (eLayout) { + case XFA_AttributeEnum::Row: + case XFA_AttributeEnum::Rl_row: + RelocateTableRowCells(pLayoutItem, pProcessor->m_rgSpecifiedColumnWidths, + eLayout); + break; + default: + break; + } +} + +void AddTrailerBeforeSplit(CXFA_ItemLayoutProcessor* pProcessor, + float fSplitPos, + CXFA_ContentLayoutItem* pTrailerLayoutItem, + bool bUseInherited) { + if (!pTrailerLayoutItem) + return; + + float fHeight = pTrailerLayoutItem->m_sSize.height; + if (bUseInherited) { + float fNewSplitPos = 0; + if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) + fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); + if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) + pProcessor->SplitLayoutItem(fNewSplitPos); + return; + } + + UpdatePendingItemLayout(pProcessor, pTrailerLayoutItem); + CXFA_Margin* pMarginNode = + pProcessor->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( + XFA_Element::Margin); + float fLeftInset = 0; + float fTopInset = 0; + float fRightInset = 0; + float fBottomInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fTopInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + fBottomInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } + + if (!pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem)) { + pTrailerLayoutItem->m_sPos.y = pProcessor->m_fLastRowY; + pTrailerLayoutItem->m_sPos.x = pProcessor->m_fLastRowWidth; + pProcessor->m_pLayoutItem->m_sSize.width += + pTrailerLayoutItem->m_sSize.width; + pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); + return; + } + + float fNewSplitPos = 0; + if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) + fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); + + if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { + pProcessor->SplitLayoutItem(fNewSplitPos); + pTrailerLayoutItem->m_sPos.y = fNewSplitPos - fTopInset - fBottomInset; + } else { + pTrailerLayoutItem->m_sPos.y = fSplitPos - fTopInset - fBottomInset; + } + + switch (pTrailerLayoutItem->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)) { + case XFA_AttributeEnum::Right: + pTrailerLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - + fRightInset - + pTrailerLayoutItem->m_sSize.width; + break; + case XFA_AttributeEnum::Center: + pTrailerLayoutItem->m_sPos.x = + (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - + pTrailerLayoutItem->m_sSize.width) / + 2; + break; + case XFA_AttributeEnum::Left: + default: + pTrailerLayoutItem->m_sPos.x = fLeftInset; + break; + } + pProcessor->m_pLayoutItem->m_sSize.height += fHeight; + pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); +} + +void AddLeaderAfterSplit(CXFA_ItemLayoutProcessor* pProcessor, + CXFA_ContentLayoutItem* pLeaderLayoutItem) { + UpdatePendingItemLayout(pProcessor, pLeaderLayoutItem); + + CXFA_Margin* pMarginNode = + pProcessor->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( + XFA_Element::Margin); + float fLeftInset = 0; + float fRightInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + } + + float fHeight = pLeaderLayoutItem->m_sSize.height; + for (CXFA_ContentLayoutItem* pChildItem = + (CXFA_ContentLayoutItem*)pProcessor->m_pLayoutItem->m_pFirstChild; + pChildItem; + pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { + pChildItem->m_sPos.y += fHeight; + } + pLeaderLayoutItem->m_sPos.y = 0; + + switch (pLeaderLayoutItem->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)) { + case XFA_AttributeEnum::Right: + pLeaderLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - + fRightInset - + pLeaderLayoutItem->m_sSize.width; + break; + case XFA_AttributeEnum::Center: + pLeaderLayoutItem->m_sPos.x = + (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - + pLeaderLayoutItem->m_sSize.width) / + 2; + break; + case XFA_AttributeEnum::Left: + default: + pLeaderLayoutItem->m_sPos.x = fLeftInset; + break; + } + pProcessor->m_pLayoutItem->m_sSize.height += fHeight; + pProcessor->m_pLayoutItem->AddChild(pLeaderLayoutItem); +} + +void AddPendingNode(CXFA_ItemLayoutProcessor* pProcessor, + CXFA_Node* pPendingNode, + bool bBreakPending) { + pProcessor->m_PendingNodes.push_back(pPendingNode); + pProcessor->m_bBreakPending = bBreakPending; +} + +float InsertPendingItems(CXFA_ItemLayoutProcessor* pProcessor, + CXFA_Node* pCurChildNode) { + float fTotalHeight = 0; + if (pProcessor->m_PendingNodes.empty()) + return fTotalHeight; + + if (!pProcessor->m_pLayoutItem) { + pProcessor->m_pLayoutItem = + pProcessor->CreateContentLayoutItem(pCurChildNode); + pProcessor->m_pLayoutItem->m_sSize.clear(); + } + + while (!pProcessor->m_PendingNodes.empty()) { + auto pPendingProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + pProcessor->m_PendingNodes.front(), nullptr); + pProcessor->m_PendingNodes.pop_front(); + pPendingProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); + CXFA_ContentLayoutItem* pPendingLayoutItem = + pPendingProcessor->HasLayoutItem() + ? pPendingProcessor->ExtractLayoutItem() + : nullptr; + if (pPendingLayoutItem) { + AddLeaderAfterSplit(pProcessor, pPendingLayoutItem); + if (pProcessor->m_bBreakPending) + fTotalHeight += pPendingLayoutItem->m_sSize.height; + } + } + return fTotalHeight; +} + +XFA_AttributeEnum GetLayout(CXFA_Node* pFormNode, bool* bRootForceTb) { + *bRootForceTb = false; + Optional<XFA_AttributeEnum> layoutMode = + pFormNode->JSObject()->TryEnum(XFA_Attribute::Layout, false); + if (layoutMode) + return *layoutMode; + + CXFA_Node* pParentNode = pFormNode->GetParent(); + if (pParentNode && pParentNode->GetElementType() == XFA_Element::Form) { + *bRootForceTb = true; + return XFA_AttributeEnum::Tb; + } + return XFA_AttributeEnum::Position; +} + +bool ExistContainerKeep(CXFA_Node* pCurNode, bool bPreFind) { + if (!pCurNode || !XFA_ItemLayoutProcessor_IsTakingSpace(pCurNode)) + return false; + + CXFA_Node* pPreContainer = bPreFind ? pCurNode->GetPrevContainerSibling() + : pCurNode->GetNextContainerSibling(); + if (!pPreContainer) + return false; + + CXFA_Keep* pKeep = + pCurNode->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); + if (pKeep) { + XFA_Attribute eKeepType = XFA_Attribute::Previous; + if (!bPreFind) + eKeepType = XFA_Attribute::Next; + + Optional<XFA_AttributeEnum> previous = + pKeep->JSObject()->TryEnum(eKeepType, false); + if (previous) { + if (*previous == XFA_AttributeEnum::ContentArea || + *previous == XFA_AttributeEnum::PageArea) { + return true; + } + } + } + + pKeep = pPreContainer->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); + if (!pKeep) + return false; + + XFA_Attribute eKeepType = XFA_Attribute::Next; + if (!bPreFind) + eKeepType = XFA_Attribute::Previous; + + Optional<XFA_AttributeEnum> next = + pKeep->JSObject()->TryEnum(eKeepType, false); + if (!next) + return false; + if (*next == XFA_AttributeEnum::ContentArea || + *next == XFA_AttributeEnum::PageArea) { + return true; + } + return false; +} + +bool FindBreakNode(CXFA_Node* pContainerNode, + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages* nCurStage, + bool bBreakBefore) { + bool bFindRs = false; + for (CXFA_Node* pBreakNode = pContainerNode; pBreakNode; + pBreakNode = pBreakNode->GetNextSibling()) { + XFA_Attribute eAttributeType = XFA_Attribute::Before; + if (!bBreakBefore) + eAttributeType = XFA_Attribute::After; + + switch (pBreakNode->GetElementType()) { + case XFA_Element::BreakBefore: { + if (bBreakBefore) { + pCurActionNode = pBreakNode; + *nCurStage = XFA_ItemLayoutProcessorStages::BreakBefore; + bFindRs = true; + } + break; + } + case XFA_Element::BreakAfter: { + if (!bBreakBefore) { + pCurActionNode = pBreakNode; + *nCurStage = XFA_ItemLayoutProcessorStages::BreakAfter; + bFindRs = true; + } + break; + } + case XFA_Element::Break: + if (pBreakNode->JSObject()->GetEnum(eAttributeType) != + XFA_AttributeEnum::Auto) { + pCurActionNode = pBreakNode; + *nCurStage = XFA_ItemLayoutProcessorStages::BreakBefore; + if (!bBreakBefore) + *nCurStage = XFA_ItemLayoutProcessorStages::BreakAfter; + + bFindRs = true; + } + break; + default: + break; + } + if (bFindRs) + break; + } + return bFindRs; +} + +void DeleteLayoutGeneratedNode(CXFA_Node* pGenerateNode) { + CXFA_FFNotify* pNotify = pGenerateNode->GetDocument()->GetNotify(); + CXFA_LayoutProcessor* pDocLayout = + pGenerateNode->GetDocument()->GetDocLayout(); + CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( + pGenerateNode); + for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; + pNode = sIterator.MoveToNext()) { + CXFA_ContentLayoutItem* pCurLayoutItem = + static_cast<CXFA_ContentLayoutItem*>( + pNode->JSObject()->GetLayoutItem()); + CXFA_ContentLayoutItem* pNextLayoutItem = nullptr; + while (pCurLayoutItem) { + pNextLayoutItem = pCurLayoutItem->m_pNext; + pNotify->OnLayoutItemRemoving(pDocLayout, pCurLayoutItem); + delete pCurLayoutItem; + pCurLayoutItem = pNextLayoutItem; + } + } + pGenerateNode->GetParent()->RemoveChild(pGenerateNode, true); +} + +uint8_t HAlignEnumToInt(XFA_AttributeEnum eHAlign) { + switch (eHAlign) { + case XFA_AttributeEnum::Center: + return 1; + case XFA_AttributeEnum::Right: + return 2; + case XFA_AttributeEnum::Left: + default: + return 0; + } +} + +XFA_ItemLayoutProcessorResult InsertFlowedItem( + CXFA_ItemLayoutProcessor* pThis, + CXFA_ItemLayoutProcessor* pProcessor, + bool bContainerWidthAutoSize, + bool bContainerHeightAutoSize, + float fContainerHeight, + XFA_AttributeEnum eFlowStrategy, + uint8_t* uCurHAlignState, + std::vector<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], + bool bUseBreakControl, + float fAvailHeight, + float fRealHeight, + float fContentWidthLimit, + float* fContentCurRowY, + float* fContentCurRowAvailWidth, + float* fContentCurRowHeight, + bool* bAddedItemInRow, + bool* bForceEndPage, + CXFA_LayoutContext* pLayoutContext, + bool bNewRow) { + bool bTakeSpace = + XFA_ItemLayoutProcessor_IsTakingSpace(pProcessor->m_pFormNode); + uint8_t uHAlign = HAlignEnumToInt( + pThis->m_pCurChildNode->JSObject()->GetEnum(XFA_Attribute::HAlign)); + if (bContainerWidthAutoSize) + uHAlign = 0; + + if ((eFlowStrategy != XFA_AttributeEnum::Rl_tb && + uHAlign < *uCurHAlignState) || + (eFlowStrategy == XFA_AttributeEnum::Rl_tb && + uHAlign > *uCurHAlignState)) { + return XFA_ItemLayoutProcessorResult::RowFullBreak; + } + + *uCurHAlignState = uHAlign; + bool bIsOwnSplit = + pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None; + bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit && + pProcessor->m_pFormNode->GetParent()->GetIntact() == + XFA_AttributeEnum::None; + bool bIsTransHeight = bTakeSpace; + if (bIsTransHeight && !bIsOwnSplit) { + bool bRootForceTb = false; + XFA_AttributeEnum eLayoutStrategy = + GetLayout(pProcessor->m_pFormNode, &bRootForceTb); + if (eLayoutStrategy == XFA_AttributeEnum::Lr_tb || + eLayoutStrategy == XFA_AttributeEnum::Rl_tb) { + bIsTransHeight = false; + } + } + + bool bUseInherited = false; + CXFA_LayoutContext layoutContext; + if (pThis->m_pPageMgr) { + CXFA_Node* pOverflowNode = + pThis->m_pPageMgr->QueryOverflow(pThis->m_pFormNode); + if (pOverflowNode) { + layoutContext.m_pOverflowNode = pOverflowNode; + layoutContext.m_pOverflowProcessor = pThis; + pLayoutContext = &layoutContext; + } + } + + XFA_ItemLayoutProcessorResult eRetValue = XFA_ItemLayoutProcessorResult::Done; + if (!bNewRow || + pProcessor->m_ePreProcessRs == XFA_ItemLayoutProcessorResult::Done) { + eRetValue = pProcessor->DoLayout( + bTakeSpace ? bUseBreakControl : false, + bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, + bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, + pLayoutContext); + pProcessor->m_ePreProcessRs = eRetValue; + } else { + eRetValue = pProcessor->m_ePreProcessRs; + pProcessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult::Done; + } + if (pProcessor->HasLayoutItem() == false) + return eRetValue; + + CFX_SizeF childSize = pProcessor->GetCurrentComponentSize(); + if (bUseRealHeight && fRealHeight < XFA_LAYOUT_FLOAT_PERCISION) { + fRealHeight = FLT_MAX; + fAvailHeight = FLT_MAX; + } + if (bTakeSpace && (childSize.width > + *fContentCurRowAvailWidth + XFA_LAYOUT_FLOAT_PERCISION) && + (fContentWidthLimit - *fContentCurRowAvailWidth > + XFA_LAYOUT_FLOAT_PERCISION)) { + return XFA_ItemLayoutProcessorResult::RowFullBreak; + } + + CXFA_Node* pOverflowLeaderNode = nullptr; + CXFA_Node* pOverflowTrailerNode = nullptr; + CXFA_Node* pFormNode = nullptr; + CXFA_ContentLayoutItem* pTrailerLayoutItem = nullptr; + bool bIsAddTrailerHeight = false; + if (pThis->m_pPageMgr && + pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { + pFormNode = pThis->m_pPageMgr->QueryOverflow(pProcessor->m_pFormNode); + if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) { + pFormNode = pLayoutContext->m_pOverflowNode; + bUseInherited = true; + } + if (pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, + pOverflowTrailerNode, false, + false)) { + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) { + if (pOverflowTrailerNode) { + auto pOverflowLeaderProcessor = + pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pOverflowTrailerNode, + nullptr); + pOverflowLeaderProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); + pTrailerLayoutItem = + pOverflowLeaderProcessor->HasLayoutItem() + ? pOverflowLeaderProcessor->ExtractLayoutItem() + : nullptr; + } + + bIsAddTrailerHeight = + bUseInherited + ? pThis->IsAddNewRowForTrailer(pTrailerLayoutItem) + : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem); + if (bIsAddTrailerHeight) { + childSize.height += pTrailerLayoutItem->m_sSize.height; + bIsAddTrailerHeight = true; + } + } + } + } + + if (!bTakeSpace || + *fContentCurRowY + childSize.height <= + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION || + (!bContainerHeightAutoSize && + pThis->m_fUsedSize + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION >= + fContainerHeight)) { + if (!bTakeSpace || eRetValue == XFA_ItemLayoutProcessorResult::Done) { + if (pProcessor->m_bUseInheriated) { + if (pTrailerLayoutItem) + AddTrailerBeforeSplit(pProcessor, childSize.height, + pTrailerLayoutItem, false); + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) + AddPendingNode(pProcessor, pOverflowLeaderNode, false); + + pProcessor->m_bUseInheriated = false; + } else { + if (bIsAddTrailerHeight) + childSize.height -= pTrailerLayoutItem->m_sSize.height; + + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + } + + CXFA_ContentLayoutItem* pChildLayoutItem = + pProcessor->ExtractLayoutItem(); + if (ExistContainerKeep(pProcessor->m_pFormNode, false) && + pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None) { + pThis->m_arrayKeepItems.push_back(pChildLayoutItem); + } else { + pThis->m_arrayKeepItems.clear(); + } + rgCurLineLayoutItems[uHAlign].push_back(pChildLayoutItem); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = + std::max(*fContentCurRowHeight, childSize.height); + } + return XFA_ItemLayoutProcessorResult::Done; + } + + if (eRetValue == XFA_ItemLayoutProcessorResult::PageFullBreak) { + if (pProcessor->m_bUseInheriated) { + if (pTrailerLayoutItem) { + AddTrailerBeforeSplit(pProcessor, childSize.height, + pTrailerLayoutItem, false); + } + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) + AddPendingNode(pProcessor, pOverflowLeaderNode, false); + + pProcessor->m_bUseInheriated = false; + } else { + if (bIsAddTrailerHeight) + childSize.height -= pTrailerLayoutItem->m_sSize.height; + + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + } + } + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + return eRetValue; + } + + XFA_ItemLayoutProcessorResult eResult; + if (pThis->ProcessKeepForSplit( + pThis, pProcessor, eRetValue, &rgCurLineLayoutItems[uHAlign], + fContentCurRowAvailWidth, fContentCurRowHeight, fContentCurRowY, + bAddedItemInRow, bForceEndPage, &eResult)) { + return eResult; + } + + *bForceEndPage = true; + float fSplitPos = pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY); + if (fSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { + XFA_AttributeEnum eLayout = + pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (eLayout == XFA_AttributeEnum::Tb && + eRetValue == XFA_ItemLayoutProcessorResult::Done) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, pTrailerLayoutItem, + pFormNode); + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = + std::max(*fContentCurRowHeight, childSize.height); + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } + + CXFA_Node* pTempLeaderNode = nullptr; + CXFA_Node* pTempTrailerNode = nullptr; + if (pThis->m_pPageMgr && !pProcessor->m_bUseInheriated && + eRetValue != XFA_ItemLayoutProcessorResult::PageFullBreak) { + pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, + pTempTrailerNode, false, true); + } + if (pTrailerLayoutItem && bIsAddTrailerHeight) { + AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, + bUseInherited); + } else { + pProcessor->SplitLayoutItem(fSplitPos); + } + + if (bUseInherited) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, pTrailerLayoutItem, + pFormNode); + pThis->m_bUseInheriated = true; + } else { + CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->m_pFirstChild; + if (firstChild && !firstChild->m_pNextSibling && + firstChild->m_pFormNode->IsLayoutGeneratedNode()) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + } else if (pProcessor->JudgeLeaderOrTrailerForOccur( + pOverflowLeaderNode)) { + AddPendingNode(pProcessor, pOverflowLeaderNode, false); + } + } + + if (pProcessor->m_pLayoutItem->m_pNextSibling) { + childSize = pProcessor->GetCurrentComponentSize(); + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = + std::max(*fContentCurRowHeight, childSize.height); + } + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } + + if (*fContentCurRowY <= XFA_LAYOUT_FLOAT_PERCISION) { + childSize = pProcessor->GetCurrentComponentSize(); + if (pProcessor->m_pPageMgr->GetNextAvailContentHeight(childSize.height)) { + CXFA_Node* pTempLeaderNode = nullptr; + CXFA_Node* pTempTrailerNode = nullptr; + if (pThis->m_pPageMgr) { + if (!pFormNode && pLayoutContext) + pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; + + pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, + pTempTrailerNode, false, true); + } + if (bUseInherited) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, + pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + pThis->m_bUseInheriated = true; + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } + + rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + if (bTakeSpace) { + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + } + if (eRetValue == XFA_ItemLayoutProcessorResult::Done) + *bForceEndPage = false; + + return eRetValue; + } + + XFA_AttributeEnum eLayout = + pProcessor->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (pProcessor->m_pFormNode->GetIntact() == XFA_AttributeEnum::None && + eLayout == XFA_AttributeEnum::Tb) { + if (pThis->m_pPageMgr) { + pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, + pOverflowTrailerNode, false, true); + } + if (pTrailerLayoutItem) + AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, false); + if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) + AddPendingNode(pProcessor, pOverflowLeaderNode, false); + + return XFA_ItemLayoutProcessorResult::PageFullBreak; + } + + if (eRetValue != XFA_ItemLayoutProcessorResult::Done) + return XFA_ItemLayoutProcessorResult::PageFullBreak; + + if (!pFormNode && pLayoutContext) + pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; + if (pThis->m_pPageMgr) { + pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, + pOverflowTrailerNode, false, true); + } + if (bUseInherited) { + pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, + pTrailerLayoutItem, pFormNode); + pThis->m_bUseInheriated = true; + } + return XFA_ItemLayoutProcessorResult::PageFullBreak; +} + +bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem, + float fCurVerticalOffset, + float* fProposedSplitPos, + bool* bAppChange, + bool bCalculateMargin) { + CXFA_Node* pFormNode = pLayoutItem->m_pFormNode; + if (*fProposedSplitPos <= fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION || + *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height - + XFA_LAYOUT_FLOAT_PERCISION) { + return false; + } + + switch (pFormNode->GetIntact()) { + case XFA_AttributeEnum::None: { + bool bAnyChanged = false; + CXFA_Document* pDocument = pFormNode->GetDocument(); + CXFA_FFNotify* pNotify = pDocument->GetNotify(); + float fCurTopMargin = 0, fCurBottomMargin = 0; + CXFA_Margin* pMarginNode = + pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); + if (pMarginNode && bCalculateMargin) { + fCurTopMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fCurBottomMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } + bool bChanged = true; + while (bChanged) { + bChanged = false; + { + float fRelSplitPos = *fProposedSplitPos - fCurVerticalOffset; + if (pNotify->FindSplitPos(pFormNode, pLayoutItem->GetIndex(), + fRelSplitPos)) { + bAnyChanged = true; + bChanged = true; + *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos; + *bAppChange = true; + if (*fProposedSplitPos <= + fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { + return true; + } + } + } + float fRelSplitPos = *fProposedSplitPos - fCurBottomMargin; + for (CXFA_ContentLayoutItem* pChildItem = + (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; + pChildItem; + pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { + float fChildOffset = + fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y; + bool bChange = false; + if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos, + &bChange, bCalculateMargin)) { + if (fRelSplitPos - fChildOffset < XFA_LAYOUT_FLOAT_PERCISION && + bChange) { + *fProposedSplitPos = fRelSplitPos - fCurTopMargin; + } else { + *fProposedSplitPos = fRelSplitPos + fCurBottomMargin; + } + bAnyChanged = true; + bChanged = true; + if (*fProposedSplitPos <= + fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { + return true; + } + if (bAnyChanged) + break; + } + } + } + return bAnyChanged; + } + case XFA_AttributeEnum::ContentArea: + case XFA_AttributeEnum::PageArea: { + *fProposedSplitPos = fCurVerticalOffset; + return true; + } + default: + return false; + } +} + +CFX_PointF CalculatePositionedContainerPos(CXFA_Node* pNode, + const CFX_SizeF& size) { + XFA_AttributeEnum eAnchorType = + pNode->JSObject()->GetEnum(XFA_Attribute::AnchorType); + int32_t nAnchorType = 0; + switch (eAnchorType) { + case XFA_AttributeEnum::TopLeft: + nAnchorType = 0; + break; + case XFA_AttributeEnum::TopCenter: + nAnchorType = 1; + break; + case XFA_AttributeEnum::TopRight: + nAnchorType = 2; + break; + case XFA_AttributeEnum::MiddleLeft: + nAnchorType = 3; + break; + case XFA_AttributeEnum::MiddleCenter: + nAnchorType = 4; + break; + case XFA_AttributeEnum::MiddleRight: + nAnchorType = 5; + break; + case XFA_AttributeEnum::BottomLeft: + nAnchorType = 6; + break; + case XFA_AttributeEnum::BottomCenter: + nAnchorType = 7; + break; + case XFA_AttributeEnum::BottomRight: + nAnchorType = 8; + break; + default: + break; + } + static const uint8_t nNextPos[4][9] = {{0, 1, 2, 3, 4, 5, 6, 7, 8}, + {6, 3, 0, 7, 4, 1, 8, 5, 2}, + {8, 7, 6, 5, 4, 3, 2, 1, 0}, + {2, 5, 8, 1, 4, 7, 0, 3, 6}}; + + CFX_PointF pos( + pNode->JSObject()->GetMeasure(XFA_Attribute::X).ToUnit(XFA_Unit::Pt), + pNode->JSObject()->GetMeasure(XFA_Attribute::Y).ToUnit(XFA_Unit::Pt)); + int32_t nRotate = + XFA_MapRotation(pNode->JSObject()->GetInteger(XFA_Attribute::Rotate)) / + 90; + int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType]; + switch (nAbsoluteAnchorType / 3) { + case 1: + pos.y -= size.height / 2; + break; + case 2: + pos.y -= size.height; + break; + default: + break; + } + switch (nAbsoluteAnchorType % 3) { + case 1: + pos.x -= size.width / 2; + break; + case 2: + pos.x -= size.width; + break; + default: + break; + } + return pos; +} + +} // namespace + +CXFA_ItemLayoutProcessor::CXFA_ItemLayoutProcessor(CXFA_Node* pNode, + CXFA_LayoutPageMgr* pPageMgr) + : m_pFormNode(pNode), + m_pLayoutItem(nullptr), + m_pCurChildNode(XFA_LAYOUT_INVALIDNODE), + m_fUsedSize(0), + m_pPageMgr(pPageMgr), + m_bBreakPending(true), + m_fLastRowWidth(0), + m_fLastRowY(0), + m_bUseInheriated(false), + m_ePreProcessRs(XFA_ItemLayoutProcessorResult::Done), + m_bKeepBreakFinish(false), + m_bIsProcessKeep(false), + m_pKeepHeadNode(nullptr), + m_pKeepTailNode(nullptr), + m_pOldLayoutItem(nullptr), + m_pCurChildPreprocessor(nullptr), + m_nCurChildNodeStage(XFA_ItemLayoutProcessorStages::None), + m_fWidthLimite(0), + m_bHasAvailHeight(true) { + ASSERT(m_pFormNode && (m_pFormNode->IsContainerNode() || + m_pFormNode->GetElementType() == XFA_Element::Form)); + m_pOldLayoutItem = static_cast<CXFA_ContentLayoutItem*>( + m_pFormNode->JSObject()->GetLayoutItem()); +} + +CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {} + +CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( + CXFA_Node* pFormNode) { + if (!pFormNode) + return nullptr; + + CXFA_ContentLayoutItem* pLayoutItem = nullptr; + if (m_pOldLayoutItem) { + pLayoutItem = m_pOldLayoutItem; + m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; + return pLayoutItem; + } + pLayoutItem = + pFormNode->GetDocument()->GetNotify()->OnCreateContentLayoutItem( + pFormNode); + CXFA_ContentLayoutItem* pPrevLayoutItem = + static_cast<CXFA_ContentLayoutItem*>( + pFormNode->JSObject()->GetLayoutItem()); + if (pPrevLayoutItem) { + while (pPrevLayoutItem->m_pNext) + pPrevLayoutItem = pPrevLayoutItem->m_pNext; + + pPrevLayoutItem->m_pNext = pLayoutItem; + pLayoutItem->m_pPrev = pPrevLayoutItem; + } else { + pFormNode->JSObject()->SetLayoutItem(pLayoutItem); + } + return pLayoutItem; +} + +float CXFA_ItemLayoutProcessor::FindSplitPos(float fProposedSplitPos) { + ASSERT(m_pLayoutItem); + XFA_AttributeEnum eLayout = m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + bool bCalculateMargin = eLayout != XFA_AttributeEnum::Position; + while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { + bool bAppChange = false; + if (!FindLayoutItemSplitPos(m_pLayoutItem, 0, &fProposedSplitPos, + &bAppChange, bCalculateMargin)) { + break; + } + } + return fProposedSplitPos; +} + +void CXFA_ItemLayoutProcessor::SplitLayoutItem( + CXFA_ContentLayoutItem* pLayoutItem, + CXFA_ContentLayoutItem* pSecondParent, + float fSplitPos) { + float fCurTopMargin = 0, fCurBottomMargin = 0; + XFA_AttributeEnum eLayout = m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + bool bCalculateMargin = true; + if (eLayout == XFA_AttributeEnum::Position) + bCalculateMargin = false; + + CXFA_Margin* pMarginNode = + pLayoutItem->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( + XFA_Element::Margin); + if (pMarginNode && bCalculateMargin) { + fCurTopMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fCurBottomMargin = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } + + CXFA_ContentLayoutItem* pSecondLayoutItem = nullptr; + if (m_pCurChildPreprocessor && + m_pCurChildPreprocessor->m_pFormNode == pLayoutItem->m_pFormNode) { + pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem( + pLayoutItem->m_pFormNode); + } else { + pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem->m_pFormNode); + } + pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x; + pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width; + pSecondLayoutItem->m_sPos.y = 0; + pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos; + pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height; + if (pLayoutItem->m_pFirstChild) + pSecondLayoutItem->m_sSize.height += fCurTopMargin; + + if (pSecondParent) { + pSecondParent->AddChild(pSecondLayoutItem); + if (fCurTopMargin > 0 && pLayoutItem->m_pFirstChild) { + pSecondParent->m_sSize.height += fCurTopMargin; + CXFA_ContentLayoutItem* pParentItem = + (CXFA_ContentLayoutItem*)pSecondParent->m_pParent; + while (pParentItem) { + pParentItem->m_sSize.height += fCurTopMargin; + pParentItem = (CXFA_ContentLayoutItem*)pParentItem->m_pParent; + } + } + } else { + pSecondLayoutItem->m_pParent = pLayoutItem->m_pParent; + pSecondLayoutItem->m_pNextSibling = pLayoutItem->m_pNextSibling; + pLayoutItem->m_pNextSibling = pSecondLayoutItem; + } + + CXFA_ContentLayoutItem* pChildren = + (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; + pLayoutItem->m_pFirstChild = nullptr; + + float lHeightForKeep = 0; + float fAddMarginHeight = 0; + std::vector<CXFA_ContentLayoutItem*> keepLayoutItems; + for (CXFA_ContentLayoutItem *pChildItem = pChildren, *pChildNext = nullptr; + pChildItem; pChildItem = pChildNext) { + pChildNext = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling; + pChildItem->m_pNextSibling = nullptr; + if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin + + XFA_LAYOUT_FLOAT_PERCISION) { + if (!ExistContainerKeep(pChildItem->m_pFormNode, true)) { + pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin; + pChildItem->m_sPos.y += lHeightForKeep; + pChildItem->m_sPos.y += fAddMarginHeight; + pSecondLayoutItem->AddChild(pChildItem); + continue; + } + if (lHeightForKeep < XFA_LAYOUT_FLOAT_PERCISION) { + for (auto* pPreItem : keepLayoutItems) { + pLayoutItem->RemoveChild(pPreItem); + pPreItem->m_sPos.y -= fSplitPos; + if (pPreItem->m_sPos.y < 0) + pPreItem->m_sPos.y = 0; + if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) { + pPreItem->m_sPos.y = lHeightForKeep; + lHeightForKeep += pPreItem->m_sSize.height; + pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height; + if (pSecondParent) + pSecondParent->m_sSize.height += pPreItem->m_sSize.height; + } + pSecondLayoutItem->AddChild(pPreItem); + } + } + pChildItem->m_sPos.y -= fSplitPos; + pChildItem->m_sPos.y += lHeightForKeep; + pChildItem->m_sPos.y += fAddMarginHeight; + pSecondLayoutItem->AddChild(pChildItem); + continue; + } + if (fSplitPos + XFA_LAYOUT_FLOAT_PERCISION >= + fCurTopMargin + fCurBottomMargin + pChildItem->m_sPos.y + + pChildItem->m_sSize.height) { + pLayoutItem->AddChild(pChildItem); + if (ExistContainerKeep(pChildItem->m_pFormNode, false)) + keepLayoutItems.push_back(pChildItem); + else + keepLayoutItems.clear(); + continue; + } + + float fOldHeight = pSecondLayoutItem->m_sSize.height; + SplitLayoutItem( + pChildItem, pSecondLayoutItem, + fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y); + fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight; + pLayoutItem->AddChild(pChildItem); + } +} + +void CXFA_ItemLayoutProcessor::SplitLayoutItem(float fSplitPos) { + ASSERT(m_pLayoutItem); + SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos); +} + +CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { + CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; + if (pLayoutItem) { + m_pLayoutItem = + static_cast<CXFA_ContentLayoutItem*>(pLayoutItem->m_pNextSibling); + pLayoutItem->m_pNextSibling = nullptr; + } + + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done || + !ToContentLayoutItem(m_pOldLayoutItem)) { + return pLayoutItem; + } + + if (m_pOldLayoutItem->m_pPrev) + m_pOldLayoutItem->m_pPrev->m_pNext = nullptr; + + CXFA_FFNotify* pNotify = + m_pOldLayoutItem->m_pFormNode->GetDocument()->GetNotify(); + CXFA_LayoutProcessor* pDocLayout = + m_pOldLayoutItem->m_pFormNode->GetDocument()->GetDocLayout(); + CXFA_ContentLayoutItem* pOldLayoutItem = m_pOldLayoutItem; + while (pOldLayoutItem) { + CXFA_ContentLayoutItem* pNextOldLayoutItem = pOldLayoutItem->m_pNext; + pNotify->OnLayoutItemRemoving(pDocLayout, pOldLayoutItem); + if (pOldLayoutItem->m_pParent) + pOldLayoutItem->m_pParent->RemoveChild(pOldLayoutItem); + + delete pOldLayoutItem; + pOldLayoutItem = pNextOldLayoutItem; + } + m_pOldLayoutItem = nullptr; + return pLayoutItem; +} + +void CXFA_ItemLayoutProcessor::GotoNextContainerNode( + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages& nCurStage, + CXFA_Node* pParentContainer, + bool bUsePageBreak) { + CXFA_Node* pEntireContainer = pParentContainer; + CXFA_Node* pChildContainer = XFA_LAYOUT_INVALIDNODE; + switch (nCurStage) { + case XFA_ItemLayoutProcessorStages::BreakBefore: + case XFA_ItemLayoutProcessorStages::BreakAfter: { + pChildContainer = pCurActionNode->GetParent(); + break; + } + case XFA_ItemLayoutProcessorStages::Keep: + case XFA_ItemLayoutProcessorStages::Container: + pChildContainer = pCurActionNode; + break; + default: + pChildContainer = XFA_LAYOUT_INVALIDNODE; + break; + } + + switch (nCurStage) { + case XFA_ItemLayoutProcessorStages::Keep: { + CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); + if (!m_bKeepBreakFinish && + FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false)) { + return; + } + goto CheckNextChildContainer; + } + case XFA_ItemLayoutProcessorStages::None: { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BookendLeader: + for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE + ? pEntireContainer->GetFirstChild() + : pCurActionNode->GetNextSibling(); + pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { + switch (pBookendNode->GetElementType()) { + case XFA_Element::Bookend: + case XFA_Element::Break: + pCurActionNode = pBookendNode; + nCurStage = XFA_ItemLayoutProcessorStages::BookendLeader; + return; + default: + break; + } + } + } + { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BreakBefore: + if (pCurActionNode != XFA_LAYOUT_INVALIDNODE) { + CXFA_Node* pBreakBeforeNode = pCurActionNode->GetNextSibling(); + if (!m_bKeepBreakFinish && + FindBreakNode(pBreakBeforeNode, pCurActionNode, &nCurStage, + true)) { + return; + } + if (m_bIsProcessKeep) { + if (ProcessKeepNodesForBreakBefore(pCurActionNode, nCurStage, + pChildContainer)) { + return; + } + goto CheckNextChildContainer; + } + pCurActionNode = pChildContainer; + nCurStage = XFA_ItemLayoutProcessorStages::Container; + return; + } + goto CheckNextChildContainer; + } + case XFA_ItemLayoutProcessorStages::Container: { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BreakAfter: { + if (pCurActionNode == XFA_LAYOUT_INVALIDNODE) { + CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild(); + if (!m_bKeepBreakFinish && + FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, + false)) { + return; + } + } else { + CXFA_Node* pBreakAfterNode = pCurActionNode->GetNextSibling(); + if (FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, + false)) { + return; + } + } + goto CheckNextChildContainer; + } + } + + CheckNextChildContainer : { + CXFA_Node* pNextChildContainer = + pChildContainer == XFA_LAYOUT_INVALIDNODE + ? pEntireContainer->GetFirstContainerChild() + : pChildContainer->GetNextContainerSibling(); + while (pNextChildContainer && + pNextChildContainer->IsLayoutGeneratedNode()) { + CXFA_Node* pSaveNode = pNextChildContainer; + pNextChildContainer = pNextChildContainer->GetNextContainerSibling(); + if (pSaveNode->IsUnusedNode()) + DeleteLayoutGeneratedNode(pSaveNode); + } + if (!pNextChildContainer) + goto NoMoreChildContainer; + + bool bLastKeep = false; + if (ProcessKeepNodesForCheckNext(pCurActionNode, nCurStage, + pNextChildContainer, bLastKeep)) { + return; + } + if (!m_bKeepBreakFinish && !bLastKeep && + FindBreakNode(pNextChildContainer->GetFirstChild(), pCurActionNode, + &nCurStage, true)) { + return; + } + pCurActionNode = pNextChildContainer; + if (m_bIsProcessKeep) + nCurStage = XFA_ItemLayoutProcessorStages::Keep; + else + nCurStage = XFA_ItemLayoutProcessorStages::Container; + return; + } + + NoMoreChildContainer : { + pCurActionNode = XFA_LAYOUT_INVALIDNODE; + case XFA_ItemLayoutProcessorStages::BookendTrailer: + for (CXFA_Node* pBookendNode = pCurActionNode == XFA_LAYOUT_INVALIDNODE + ? pEntireContainer->GetFirstChild() + : pCurActionNode->GetNextSibling(); + pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) { + switch (pBookendNode->GetElementType()) { + case XFA_Element::Bookend: + case XFA_Element::Break: + pCurActionNode = pBookendNode; + nCurStage = XFA_ItemLayoutProcessorStages::BookendTrailer; + return; + default: + break; + } + } + } + default: + pCurActionNode = nullptr; + nCurStage = XFA_ItemLayoutProcessorStages::Done; + } +} + +bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForCheckNext( + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages& nCurStage, + CXFA_Node*& pNextContainer, + bool& bLastKeepNode) { + const bool bCanSplit = pNextContainer->GetIntact() == XFA_AttributeEnum::None; + bool bNextKeep = false; + if (ExistContainerKeep(pNextContainer, false)) + bNextKeep = true; + + if (bNextKeep && !bCanSplit) { + if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { + m_pKeepHeadNode = pNextContainer; + m_bIsProcessKeep = true; + } + return false; + } + + if (m_bIsProcessKeep && m_pKeepHeadNode) { + m_pKeepTailNode = pNextContainer; + if (!m_bKeepBreakFinish && + FindBreakNode(pNextContainer->GetFirstChild(), pCurActionNode, + &nCurStage, true)) { + return true; + } + + pNextContainer = m_pKeepHeadNode; + m_bKeepBreakFinish = true; + m_pKeepHeadNode = nullptr; + m_pKeepTailNode = nullptr; + m_bIsProcessKeep = false; + } else { + if (m_bKeepBreakFinish) + bLastKeepNode = true; + m_bKeepBreakFinish = false; + } + + return false; +} + +bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForBreakBefore( + CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages& nCurStage, + CXFA_Node* pContainerNode) { + if (m_pKeepTailNode == pContainerNode) { + pCurActionNode = m_pKeepHeadNode; + m_bKeepBreakFinish = true; + m_pKeepHeadNode = nullptr; + m_pKeepTailNode = nullptr; + m_bIsProcessKeep = false; + nCurStage = XFA_ItemLayoutProcessorStages::Container; + return true; + } + + CXFA_Node* pBreakAfterNode = pContainerNode->GetFirstChild(); + return FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false); +} + +bool XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node* pNode) { + XFA_AttributeEnum ePresence = pNode->JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible); + return ePresence == XFA_AttributeEnum::Visible || + ePresence == XFA_AttributeEnum::Invisible; +} + +bool CXFA_ItemLayoutProcessor::IncrementRelayoutNode( + CXFA_LayoutProcessor* pLayoutProcessor, + CXFA_Node* pNode, + CXFA_Node* pParentNode) { + return false; +} + +void CXFA_ItemLayoutProcessor::DoLayoutPageArea( + CXFA_ContainerLayoutItem* pPageAreaLayoutItem) { + CXFA_Node* pFormNode = pPageAreaLayoutItem->m_pFormNode; + CXFA_Node* pCurChildNode = XFA_LAYOUT_INVALIDNODE; + XFA_ItemLayoutProcessorStages nCurChildNodeStage = + XFA_ItemLayoutProcessorStages::None; + CXFA_LayoutItem* pBeforeItem = nullptr; + for (GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, pFormNode, + false); + pCurChildNode; GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, + pFormNode, false)) { + if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) + continue; + if (pCurChildNode->GetElementType() == XFA_Element::Variables) + continue; + + auto pProcessor = + pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pCurChildNode, nullptr); + pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); + if (!pProcessor->HasLayoutItem()) + continue; + + pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos( + pCurChildNode, pProcessor->GetCurrentComponentSize())); + CXFA_LayoutItem* pProcessItem = pProcessor->ExtractLayoutItem(); + if (!pBeforeItem) + pPageAreaLayoutItem->AddHeadChild(pProcessItem); + else + pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); + + pBeforeItem = pProcessItem; + } + + pBeforeItem = nullptr; + CXFA_LayoutItem* pLayoutItem = pPageAreaLayoutItem->m_pFirstChild; + while (pLayoutItem) { + if (!pLayoutItem->IsContentLayoutItem() || + pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) { + pLayoutItem = pLayoutItem->m_pNextSibling; + continue; + } + if (pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) + continue; + + CXFA_LayoutItem* pNextLayoutItem = pLayoutItem->m_pNextSibling; + pPageAreaLayoutItem->RemoveChild(pLayoutItem); + if (!pBeforeItem) + pPageAreaLayoutItem->AddHeadChild(pLayoutItem); + else + pPageAreaLayoutItem->InsertChild(pBeforeItem, pLayoutItem); + + pBeforeItem = pLayoutItem; + pLayoutItem = pNextLayoutItem; + } +} + +void CXFA_ItemLayoutProcessor::DoLayoutPositionedContainer( + CXFA_LayoutContext* pContext) { + if (m_pLayoutItem) + return; + + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + bool bIgnoreXY = (m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position) != + XFA_AttributeEnum::Position); + bool bContainerWidthAutoSize = true; + bool bContainerHeightAutoSize = true; + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( + m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); + + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + float fHiddenContentCalculatedWidth = 0; + float fHiddenContentCalculatedHeight = 0; + if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { + GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, + false); + } + + int32_t iColIndex = 0; + for (; m_pCurChildNode; GotoNextContainerNode( + m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) + continue; + if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) + continue; + + auto pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + m_pCurChildNode, m_pPageMgr); + if (pContext && pContext->m_prgSpecifiedColumnWidths) { + int32_t iColSpan = + m_pCurChildNode->JSObject()->GetInteger(XFA_Attribute::ColSpan); + if (iColSpan <= pdfium::CollectionSize<int32_t>( + *pContext->m_prgSpecifiedColumnWidths) - + iColIndex) { + pContext->m_fCurColumnWidth = 0; + pContext->m_bCurColumnWidthAvaiable = true; + if (iColSpan == -1) { + iColSpan = pdfium::CollectionSize<int32_t>( + *pContext->m_prgSpecifiedColumnWidths); + } + for (int32_t i = 0; iColIndex + i < iColSpan; ++i) { + pContext->m_fCurColumnWidth += + (*pContext->m_prgSpecifiedColumnWidths)[iColIndex + i]; + } + if (pContext->m_fCurColumnWidth == 0) + pContext->m_bCurColumnWidthAvaiable = false; + + iColIndex += iColSpan >= 0 ? iColSpan : 0; + } + } + + pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pContext); + if (!pProcessor->HasLayoutItem()) + continue; + + CFX_SizeF size = pProcessor->GetCurrentComponentSize(); + bool bChangeParentSize = false; + if (XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) + bChangeParentSize = true; + + CFX_PointF absolutePos; + if (!bIgnoreXY) + absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size); + + pProcessor->SetCurrentComponentPos(absolutePos); + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = absolutePos.x + size.width; + if (bChangeParentSize) { + fContentCalculatedWidth = + std::max(fContentCalculatedWidth, fChildSuppliedWidth); + } else { + if (fHiddenContentCalculatedWidth < fChildSuppliedWidth && + m_pCurChildNode->GetElementType() != XFA_Element::Subform) { + fHiddenContentCalculatedWidth = fChildSuppliedWidth; + } + } + } + + if (bContainerHeightAutoSize) { + float fChildSuppliedHeight = absolutePos.y + size.height; + if (bChangeParentSize) { + fContentCalculatedHeight = + std::max(fContentCalculatedHeight, fChildSuppliedHeight); + } else { + if (fHiddenContentCalculatedHeight < fChildSuppliedHeight && + m_pCurChildNode->GetElementType() != XFA_Element::Subform) { + fHiddenContentCalculatedHeight = fChildSuppliedHeight; + } + } + } + m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); + } + + XFA_VERSION eVersion = m_pFormNode->GetDocument()->GetCurVersionMode(); + if (fContentCalculatedWidth == 0 && eVersion < XFA_VERSION_207) + fContentCalculatedWidth = fHiddenContentCalculatedWidth; + if (fContentCalculatedHeight == 0 && eVersion < XFA_VERSION_207) + fContentCalculatedHeight = fHiddenContentCalculatedHeight; + + containerSize = CalculateContainerComponentSizeFromContentSize( + m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); + SetCurrentComponentSize(containerSize); +} + +void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { + if (m_pLayoutItem) + return; + if (!pLayoutNode) + pLayoutNode = m_pFormNode; + + ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); + + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + bool bContainerWidthAutoSize = true; + bool bContainerHeightAutoSize = true; + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( + m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + CXFA_Margin* pMarginNode = + m_pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); + float fLeftInset = 0; + float fRightInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + } + + float fContentWidthLimit = + bContainerWidthAutoSize ? FLT_MAX + : containerSize.width - fLeftInset - fRightInset; + WideString wsColumnWidths = + pLayoutNode->JSObject()->GetCData(XFA_Attribute::ColumnWidths); + if (!wsColumnWidths.IsEmpty()) { + auto widths = SeparateStringW(wsColumnWidths.c_str(), + wsColumnWidths.GetLength(), L' '); + for (auto& width : widths) { + width.TrimLeft(L' '); + if (width.IsEmpty()) + continue; + + m_rgSpecifiedColumnWidths.push_back( + CXFA_Measurement(width.AsStringView()).ToUnit(XFA_Unit::Pt)); + } + } + + int32_t iSpecifiedColumnCount = + pdfium::CollectionSize<int32_t>(m_rgSpecifiedColumnWidths); + CXFA_LayoutContext layoutContext; + layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths; + CXFA_LayoutContext* pLayoutContext = + iSpecifiedColumnCount > 0 ? &layoutContext : nullptr; + if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { + GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, + false); + } + + for (; m_pCurChildNode; GotoNextContainerNode( + m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { + layoutContext.m_bCurColumnWidthAvaiable = false; + layoutContext.m_fCurColumnWidth = 0; + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) + continue; + + auto pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + m_pCurChildNode, m_pPageMgr); + pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pLayoutContext); + if (!pProcessor->HasLayoutItem()) + continue; + + m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); + } + + int32_t iRowCount = 0; + int32_t iColCount = 0; + { + std::vector<CXFA_ContentLayoutItem*> rgRowItems; + std::vector<int32_t> rgRowItemsSpan; + std::vector<float> rgRowItemsWidth; + for (auto* pLayoutChild = + static_cast<CXFA_ContentLayoutItem*>(m_pLayoutItem->m_pFirstChild); + pLayoutChild; pLayoutChild = static_cast<CXFA_ContentLayoutItem*>( + pLayoutChild->m_pNextSibling)) { + if (pLayoutChild->m_pFormNode->GetElementType() != XFA_Element::Subform) + continue; + if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) + continue; + + XFA_AttributeEnum eLayout = + pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (eLayout != XFA_AttributeEnum::Row && + eLayout != XFA_AttributeEnum::Rl_row) { + continue; + } + if (CXFA_ContentLayoutItem* pRowLayoutCell = + (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild) { + rgRowItems.push_back(pRowLayoutCell); + int32_t iColSpan = pRowLayoutCell->m_pFormNode->JSObject()->GetInteger( + XFA_Attribute::ColSpan); + rgRowItemsSpan.push_back(iColSpan); + rgRowItemsWidth.push_back(pRowLayoutCell->m_sSize.width); + } + } + + iRowCount = pdfium::CollectionSize<int32_t>(rgRowItems); + iColCount = 0; + bool bMoreColumns = true; + while (bMoreColumns) { + bMoreColumns = false; + bool bAutoCol = false; + for (int32_t i = 0; i < iRowCount; i++) { + while (rgRowItems[i] && (rgRowItemsSpan[i] <= 0 || + !XFA_ItemLayoutProcessor_IsTakingSpace( + rgRowItems[i]->m_pFormNode))) { + CXFA_ContentLayoutItem* pNewCell = + (CXFA_ContentLayoutItem*)rgRowItems[i]->m_pNextSibling; + if (rgRowItemsSpan[i] < 0 && XFA_ItemLayoutProcessor_IsTakingSpace( + rgRowItems[i]->m_pFormNode)) { + pNewCell = nullptr; + } + rgRowItems[i] = pNewCell; + rgRowItemsSpan[i] = + pNewCell ? pNewCell->m_pFormNode->JSObject()->GetInteger( + XFA_Attribute::ColSpan) + : 0; + rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0; + } + CXFA_ContentLayoutItem* pCell = rgRowItems[i]; + if (!pCell) + continue; + + bMoreColumns = true; + if (rgRowItemsSpan[i] != 1) + continue; + + if (iColCount >= iSpecifiedColumnCount) { + int32_t c = iColCount + 1 - pdfium::CollectionSize<int32_t>( + m_rgSpecifiedColumnWidths); + for (int32_t j = 0; j < c; j++) + m_rgSpecifiedColumnWidths.push_back(0); + } + if (m_rgSpecifiedColumnWidths[iColCount] < XFA_LAYOUT_FLOAT_PERCISION) + bAutoCol = true; + if (bAutoCol && + m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) { + m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i]; + } + } + + if (!bMoreColumns) + continue; + + float fFinalColumnWidth = 0.0f; + if (pdfium::IndexInBounds(m_rgSpecifiedColumnWidths, iColCount)) + fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount]; + + for (int32_t i = 0; i < iRowCount; ++i) { + if (!rgRowItems[i]) + continue; + --rgRowItemsSpan[i]; + rgRowItemsWidth[i] -= fFinalColumnWidth; + } + ++iColCount; + } + } + + float fCurrentRowY = 0; + for (CXFA_ContentLayoutItem* pLayoutChild = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + pLayoutChild; + pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { + if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) + continue; + + if (pLayoutChild->m_pFormNode->GetElementType() == XFA_Element::Subform) { + XFA_AttributeEnum eSubformLayout = + pLayoutChild->m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + if (eSubformLayout == XFA_AttributeEnum::Row || + eSubformLayout == XFA_AttributeEnum::Rl_row) { + RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths, + eSubformLayout); + } + } + + pLayoutChild->m_sPos.y = fCurrentRowY; + if (bContainerWidthAutoSize) { + pLayoutChild->m_sPos.x = 0; + } else { + switch (pLayoutChild->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)) { + case XFA_AttributeEnum::Center: + pLayoutChild->m_sPos.x = + (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2; + break; + case XFA_AttributeEnum::Right: + pLayoutChild->m_sPos.x = + fContentWidthLimit - pLayoutChild->m_sSize.width; + break; + case XFA_AttributeEnum::Left: + default: + pLayoutChild->m_sPos.x = 0; + break; + } + } + + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = + pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width; + if (fContentWidthLimit < FLT_MAX && + fContentWidthLimit > fChildSuppliedWidth) { + fChildSuppliedWidth = fContentWidthLimit; + } + fContentCalculatedWidth = + std::max(fContentCalculatedWidth, fChildSuppliedWidth); + } + fCurrentRowY += pLayoutChild->m_sSize.height; + } + + if (bContainerHeightAutoSize) + fContentCalculatedHeight = std::max(fContentCalculatedHeight, fCurrentRowY); + + containerSize = CalculateContainerComponentSizeFromContentSize( + m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); + SetCurrentComponentSize(containerSize); +} + +bool CXFA_ItemLayoutProcessor::IsAddNewRowForTrailer( + CXFA_ContentLayoutItem* pTrailerItem) { + if (!pTrailerItem) + return false; + + float fWidth = pTrailerItem->m_sSize.width; + XFA_AttributeEnum eLayout = + m_pFormNode->JSObject()->GetEnum(XFA_Attribute::Layout); + return eLayout == XFA_AttributeEnum::Tb || m_fWidthLimite <= fWidth; +} + +float CXFA_ItemLayoutProcessor::InsertKeepLayoutItems() { + if (m_arrayKeepItems.empty()) + return 0; + + if (!m_pLayoutItem) { + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + m_pLayoutItem->m_sSize.clear(); + } + + float fTotalHeight = 0; + for (auto iter = m_arrayKeepItems.rbegin(); iter != m_arrayKeepItems.rend(); + iter++) { + AddLeaderAfterSplit(this, *iter); + fTotalHeight += (*iter)->m_sSize.height; + } + m_arrayKeepItems.clear(); + + return fTotalHeight; +} + +bool CXFA_ItemLayoutProcessor::ProcessKeepForSplit( + CXFA_ItemLayoutProcessor* pParentProcessor, + CXFA_ItemLayoutProcessor* pChildProcessor, + XFA_ItemLayoutProcessorResult eRetValue, + std::vector<CXFA_ContentLayoutItem*>* rgCurLineLayoutItem, + float* fContentCurRowAvailWidth, + float* fContentCurRowHeight, + float* fContentCurRowY, + bool* bAddedItemInRow, + bool* bForceEndPage, + XFA_ItemLayoutProcessorResult* result) { + if (!pParentProcessor || !pChildProcessor) + return false; + + if (pParentProcessor->m_pCurChildNode->GetIntact() == + XFA_AttributeEnum::None && + pChildProcessor->m_bHasAvailHeight) + return false; + + if (!ExistContainerKeep(pParentProcessor->m_pCurChildNode, true)) + return false; + + CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize(); + std::vector<CXFA_ContentLayoutItem*> keepLayoutItems; + if (pParentProcessor->JudgePutNextPage(pParentProcessor->m_pLayoutItem, + childSize.height, &keepLayoutItems)) { + m_arrayKeepItems.clear(); + + for (auto* item : keepLayoutItems) { + pParentProcessor->m_pLayoutItem->RemoveChild(item); + *fContentCurRowY -= item->m_sSize.height; + m_arrayKeepItems.push_back(item); + } + *bAddedItemInRow = true; + *bForceEndPage = true; + *result = XFA_ItemLayoutProcessorResult::PageFullBreak; + return true; + } + + rgCurLineLayoutItem->push_back(pChildProcessor->ExtractLayoutItem()); + *bAddedItemInRow = true; + *fContentCurRowAvailWidth -= childSize.width; + *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); + *result = eRetValue; + + return true; +} + +bool CXFA_ItemLayoutProcessor::JudgePutNextPage( + CXFA_ContentLayoutItem* pParentLayoutItem, + float fChildHeight, + std::vector<CXFA_ContentLayoutItem*>* pKeepItems) { + if (!pParentLayoutItem) + return false; + + float fItemsHeight = 0; + for (CXFA_ContentLayoutItem* pChildLayoutItem = + (CXFA_ContentLayoutItem*)pParentLayoutItem->m_pFirstChild; + pChildLayoutItem; + pChildLayoutItem = + (CXFA_ContentLayoutItem*)pChildLayoutItem->m_pNextSibling) { + if (ExistContainerKeep(pChildLayoutItem->m_pFormNode, false)) { + pKeepItems->push_back(pChildLayoutItem); + fItemsHeight += pChildLayoutItem->m_sSize.height; + } else { + pKeepItems->clear(); + fItemsHeight = 0; + } + } + fItemsHeight += fChildHeight; + return m_pPageMgr->GetNextAvailContentHeight(fItemsHeight); +} + +void CXFA_ItemLayoutProcessor::ProcessUnUseBinds(CXFA_Node* pFormNode) { + if (!pFormNode) + return; + + CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( + pFormNode); + for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode; + pNode = sIterator.MoveToNext()) { + if (pNode->IsContainerNode()) { + CXFA_Node* pBindNode = pNode->GetBindData(); + if (pBindNode) { + pBindNode->RemoveBindItem(pNode); + pNode->SetBindingNode(nullptr); + } + } + pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); + } +} + +void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( + CXFA_Node* pLeaderNode, + CXFA_Node* pTrailerNode, + CXFA_ContentLayoutItem* pTrailerItem, + CXFA_Node* pFormNode) { + ProcessUnUseBinds(pLeaderNode); + ProcessUnUseBinds(pTrailerNode); + if (!pFormNode) + return; + + if (pFormNode->GetElementType() == XFA_Element::Overflow || + pFormNode->GetElementType() == XFA_Element::Break) { + pFormNode = pFormNode->GetParent(); + } + if (pLeaderNode && pFormNode) + pFormNode->RemoveChild(pLeaderNode, true); + if (pTrailerNode && pFormNode) + pFormNode->RemoveChild(pTrailerNode, true); + if (pTrailerItem) + XFA_ReleaseLayoutItem(pTrailerItem); +} + +XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer( + bool bUseBreakControl, + XFA_AttributeEnum eFlowStrategy, + float fHeightLimit, + float fRealHeight, + CXFA_LayoutContext* pContext, + bool bRootForceTb) { + m_bHasAvailHeight = true; + bool bBreakDone = false; + bool bContainerWidthAutoSize = true; + bool bContainerHeightAutoSize = true; + bool bForceEndPage = false; + bool bIsManualBreak = false; + if (m_pCurChildPreprocessor) { + m_pCurChildPreprocessor->m_ePreProcessRs = + XFA_ItemLayoutProcessorResult::Done; + } + + CFX_SizeF containerSize = CalculateContainerSpecifiedSize( + m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); + if (pContext && pContext->m_bCurColumnWidthAvaiable) { + bContainerWidthAutoSize = false; + containerSize.width = pContext->m_fCurColumnWidth; + } + if (!bContainerHeightAutoSize) + containerSize.height -= m_fUsedSize; + + if (!bContainerHeightAutoSize) { + CXFA_Node* pParentNode = m_pFormNode->GetParent(); + bool bFocrTb = false; + if (pParentNode && + GetLayout(pParentNode, &bFocrTb) == XFA_AttributeEnum::Row) { + CXFA_Node* pChildContainer = m_pFormNode->GetFirstContainerChild(); + if (pChildContainer && pChildContainer->GetNextContainerSibling()) { + containerSize.height = 0; + bContainerHeightAutoSize = true; + } + } + } + + CXFA_Margin* pMarginNode = + m_pFormNode->GetFirstChildByClass<CXFA_Margin>(XFA_Element::Margin); + float fLeftInset = 0; + float fTopInset = 0; + float fRightInset = 0; + float fBottomInset = 0; + if (pMarginNode) { + fLeftInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt); + fTopInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt); + fRightInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::RightInset) + .ToUnit(XFA_Unit::Pt); + fBottomInset = pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::BottomInset) + .ToUnit(XFA_Unit::Pt); + } + float fContentWidthLimit = + bContainerWidthAutoSize ? FLT_MAX + : containerSize.width - fLeftInset - fRightInset; + float fContentCalculatedWidth = 0; + float fContentCalculatedHeight = 0; + float fAvailHeight = fHeightLimit - fTopInset - fBottomInset; + if (fAvailHeight < 0) + m_bHasAvailHeight = false; + + fRealHeight = fRealHeight - fTopInset - fBottomInset; + float fContentCurRowY = 0; + CXFA_ContentLayoutItem* pLayoutChild = nullptr; + if (m_pLayoutItem) { + if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done && + eFlowStrategy != XFA_AttributeEnum::Tb) { + pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; + pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { + if (pLayoutNext->m_sPos.y != pLayoutChild->m_sPos.y) + pLayoutChild = pLayoutNext; + } + } + + for (CXFA_ContentLayoutItem* pLayoutTempChild = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + pLayoutTempChild != pLayoutChild; + pLayoutTempChild = + (CXFA_ContentLayoutItem*)pLayoutTempChild->m_pNextSibling) { + if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutTempChild->m_pFormNode)) + continue; + + fContentCalculatedWidth = std::max( + fContentCalculatedWidth, + pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.width); + fContentCalculatedHeight = std::max( + fContentCalculatedHeight, + pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.height); + } + + if (pLayoutChild) + fContentCurRowY = pLayoutChild->m_sPos.y; + else + fContentCurRowY = fContentCalculatedHeight; + } + + fContentCurRowY += InsertKeepLayoutItems(); + if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::None) { + GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, + true); + } + + fContentCurRowY += InsertPendingItems(this, m_pFormNode); + if (m_pCurChildPreprocessor && + m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Container) { + if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(), false)) { + m_pKeepHeadNode = m_pCurChildNode; + m_bIsProcessKeep = true; + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Keep; + } + } + + while (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done) { + float fContentCurRowHeight = 0; + float fContentCurRowAvailWidth = fContentWidthLimit; + m_fWidthLimite = fContentCurRowAvailWidth; + std::vector<CXFA_ContentLayoutItem*> rgCurLineLayoutItems[3]; + uint8_t uCurHAlignState = + (eFlowStrategy != XFA_AttributeEnum::Rl_tb ? 0 : 2); + if (pLayoutChild) { + for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; + pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { + if (!pLayoutNext->m_pNextSibling && m_pCurChildPreprocessor && + m_pCurChildPreprocessor->m_pFormNode == pLayoutNext->m_pFormNode) { + pLayoutNext->m_pNext = m_pCurChildPreprocessor->m_pLayoutItem; + m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext; + break; + } + uint8_t uHAlign = + HAlignEnumToInt(pLayoutNext->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::HAlign)); + rgCurLineLayoutItems[uHAlign].push_back(pLayoutNext); + if (eFlowStrategy == XFA_AttributeEnum::Lr_tb) { + if (uHAlign > uCurHAlignState) + uCurHAlignState = uHAlign; + } else if (uHAlign < uCurHAlignState) { + uCurHAlignState = uHAlign; + } + if (XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutNext->m_pFormNode)) { + if (pLayoutNext->m_sSize.height > fContentCurRowHeight) + fContentCurRowHeight = pLayoutNext->m_sSize.height; + fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width; + } + } + + if ((CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild == + pLayoutChild) { + m_pLayoutItem->m_pFirstChild = nullptr; + } else { + CXFA_ContentLayoutItem* pLayoutNext = + (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; + for (; pLayoutNext; + pLayoutNext = + (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { + if ((CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling == + pLayoutChild) { + pLayoutNext->m_pNextSibling = nullptr; + break; + } + } + } + + CXFA_ContentLayoutItem* pLayoutNextTemp = + (CXFA_ContentLayoutItem*)pLayoutChild; + while (pLayoutNextTemp) { + pLayoutNextTemp->m_pParent = nullptr; + CXFA_ContentLayoutItem* pSaveLayoutNext = + (CXFA_ContentLayoutItem*)pLayoutNextTemp->m_pNextSibling; + pLayoutNextTemp->m_pNextSibling = nullptr; + pLayoutNextTemp = pSaveLayoutNext; + } + pLayoutChild = nullptr; + } + + while (m_pCurChildNode) { + std::unique_ptr<CXFA_ItemLayoutProcessor> pProcessor; + bool bAddedItemInRow = false; + fContentCurRowY += InsertPendingItems(this, m_pFormNode); + switch (m_nCurChildNodeStage) { + case XFA_ItemLayoutProcessorStages::Keep: + case XFA_ItemLayoutProcessorStages::None: + break; + case XFA_ItemLayoutProcessorStages::BreakBefore: { + for (auto* item : m_arrayKeepItems) { + m_pLayoutItem->RemoveChild(item); + fContentCalculatedHeight -= item->m_sSize.height; + } + + CXFA_Node* pLeaderNode = nullptr; + CXFA_Node* pTrailerNode = nullptr; + bool bCreatePage = false; + if (!bUseBreakControl || !m_pPageMgr || + !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, true, + pLeaderNode, pTrailerNode, + bCreatePage) || + m_pFormNode->GetElementType() == XFA_Element::Form || + !bCreatePage) { + break; + } + + if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) + AddPendingNode(this, pLeaderNode, true); + + if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { + if (m_pFormNode->GetParent()->GetElementType() == + XFA_Element::Form && + !m_pLayoutItem) { + AddPendingNode(this, pTrailerNode, true); + } else { + auto pTempProcessor = + pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pTrailerNode, + nullptr); + InsertFlowedItem( + this, pTempProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, + FLT_MAX, fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, false); + } + } + GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, + m_pFormNode, true); + bForceEndPage = true; + bIsManualBreak = true; + goto SuspendAndCreateNewRow; + } + case XFA_ItemLayoutProcessorStages::BreakAfter: { + CXFA_Node* pLeaderNode = nullptr; + CXFA_Node* pTrailerNode = nullptr; + bool bCreatePage = false; + if (!bUseBreakControl || !m_pPageMgr || + !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, false, + pLeaderNode, pTrailerNode, + bCreatePage) || + m_pFormNode->GetElementType() == XFA_Element::Form) { + break; + } + + if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { + auto pTempProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + pTrailerNode, nullptr); + InsertFlowedItem( + this, pTempProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, FLT_MAX, + fContentWidthLimit, &fContentCurRowY, &fContentCurRowAvailWidth, + &fContentCurRowHeight, &bAddedItemInRow, &bForceEndPage, + pContext, false); + } + if (!bCreatePage) { + if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { + CalculateRowChildPosition( + rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, + bContainerWidthAutoSize, &fContentCalculatedWidth, + &fContentCalculatedHeight, &fContentCurRowY, + fContentCurRowHeight, fContentWidthLimit, false); + rgCurLineLayoutItems->clear(); + auto pTempProcessor = + pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pLeaderNode, + nullptr); + InsertFlowedItem( + this, pTempProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, + FLT_MAX, fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, false); + } + } else { + if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) + AddPendingNode(this, pLeaderNode, true); + } + + GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, + m_pFormNode, true); + if (bCreatePage) { + bForceEndPage = true; + bIsManualBreak = true; + if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done) + bBreakDone = true; + } + goto SuspendAndCreateNewRow; + } + case XFA_ItemLayoutProcessorStages::BookendLeader: { + CXFA_Node* pLeaderNode = nullptr; + if (m_pCurChildPreprocessor) { + pProcessor.reset(m_pCurChildPreprocessor); + m_pCurChildPreprocessor = nullptr; + } else if (m_pPageMgr && + m_pPageMgr->ProcessBookendLeaderOrTrailer( + m_pCurChildNode, true, pLeaderNode)) { + pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + pLeaderNode, m_pPageMgr); + } + + if (pProcessor) { + if (InsertFlowedItem( + this, pProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, + eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, + bUseBreakControl, fAvailHeight, fRealHeight, + fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, + false) != XFA_ItemLayoutProcessorResult::Done) { + goto SuspendAndCreateNewRow; + } else { + pProcessor.reset(); + } + } + break; + } + case XFA_ItemLayoutProcessorStages::BookendTrailer: { + CXFA_Node* pTrailerNode = nullptr; + if (m_pCurChildPreprocessor) { + pProcessor.reset(m_pCurChildPreprocessor); + m_pCurChildPreprocessor = nullptr; + } else if (m_pPageMgr && + m_pPageMgr->ProcessBookendLeaderOrTrailer( + m_pCurChildNode, false, pTrailerNode)) { + pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + pTrailerNode, m_pPageMgr); + } + if (pProcessor) { + if (InsertFlowedItem( + this, pProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, + eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, + bUseBreakControl, fAvailHeight, fRealHeight, + fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, + false) != XFA_ItemLayoutProcessorResult::Done) { + goto SuspendAndCreateNewRow; + } else { + pProcessor.reset(); + } + } + break; + } + case XFA_ItemLayoutProcessorStages::Container: { + ASSERT(m_pCurChildNode->IsContainerNode()); + if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) + break; + if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && + XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) { + bForceEndPage = true; + goto SuspendAndCreateNewRow; + } + if (!m_pCurChildNode->IsContainerNode()) + break; + + bool bNewRow = false; + if (m_pCurChildPreprocessor) { + pProcessor.reset(m_pCurChildPreprocessor); + m_pCurChildPreprocessor = nullptr; + bNewRow = true; + } else { + pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( + m_pCurChildNode, m_pPageMgr); + } + + InsertPendingItems(pProcessor.get(), m_pCurChildNode); + XFA_ItemLayoutProcessorResult rs = InsertFlowedItem( + this, pProcessor.get(), bContainerWidthAutoSize, + bContainerHeightAutoSize, containerSize.height, eFlowStrategy, + &uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, + fAvailHeight, fRealHeight, fContentWidthLimit, &fContentCurRowY, + &fContentCurRowAvailWidth, &fContentCurRowHeight, + &bAddedItemInRow, &bForceEndPage, pContext, bNewRow); + switch (rs) { + case XFA_ItemLayoutProcessorResult::ManualBreak: + bIsManualBreak = true; + case XFA_ItemLayoutProcessorResult::PageFullBreak: + bForceEndPage = true; + case XFA_ItemLayoutProcessorResult::RowFullBreak: + goto SuspendAndCreateNewRow; + case XFA_ItemLayoutProcessorResult::Done: + default: + fContentCurRowY += + InsertPendingItems(pProcessor.get(), m_pCurChildNode); + pProcessor.reset(); + } + break; + } + case XFA_ItemLayoutProcessorStages::Done: + break; + default: + break; + } + GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, + true); + if (bAddedItemInRow && eFlowStrategy == XFA_AttributeEnum::Tb) + break; + continue; + SuspendAndCreateNewRow: + if (pProcessor) + m_pCurChildPreprocessor = pProcessor.release(); + break; + } + + CalculateRowChildPosition( + rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, + bContainerWidthAutoSize, &fContentCalculatedWidth, + &fContentCalculatedHeight, &fContentCurRowY, fContentCurRowHeight, + fContentWidthLimit, bRootForceTb); + m_fWidthLimite = fContentCurRowAvailWidth; + if (bForceEndPage) + break; + } + + bool bRetValue = + m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done && + m_PendingNodes.empty(); + if (bBreakDone) + bRetValue = false; + + containerSize = CalculateContainerComponentSizeFromContentSize( + m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, + bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); + + if (containerSize.height >= XFA_LAYOUT_FLOAT_PERCISION || m_pLayoutItem || + bRetValue) { + if (!m_pLayoutItem) + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + containerSize.height = std::max(containerSize.height, 0.f); + + SetCurrentComponentSize(containerSize); + if (bForceEndPage) + m_fUsedSize = 0; + else + m_fUsedSize += m_pLayoutItem->m_sSize.height; + } + + return bRetValue + ? XFA_ItemLayoutProcessorResult::Done + : (bIsManualBreak ? XFA_ItemLayoutProcessorResult::ManualBreak + : XFA_ItemLayoutProcessorResult::PageFullBreak); +} + +bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition( + std::vector<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], + XFA_AttributeEnum eFlowStrategy, + bool bContainerHeightAutoSize, + bool bContainerWidthAutoSize, + float* fContentCalculatedWidth, + float* fContentCalculatedHeight, + float* fContentCurRowY, + float fContentCurRowHeight, + float fContentWidthLimit, + bool bRootForceTb) { + int32_t nGroupLengths[3] = {0, 0, 0}; + float fGroupWidths[3] = {0, 0, 0}; + int32_t nTotalLength = 0; + for (int32_t i = 0; i < 3; i++) { + nGroupLengths[i] = pdfium::CollectionSize<int32_t>(rgCurLineLayoutItems[i]); + for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) { + nTotalLength++; + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[i][j]->m_pFormNode)) { + fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width; + } + } + } + if (!nTotalLength) { + if (bContainerHeightAutoSize) { + *fContentCalculatedHeight = + std::min(*fContentCalculatedHeight, *fContentCurRowY); + } + return false; + } + if (!m_pLayoutItem) + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + + if (eFlowStrategy != XFA_AttributeEnum::Rl_tb) { + float fCurPos; + fCurPos = 0; + for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { + if (bRootForceTb) { + rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos( + rgCurLineLayoutItems[0][j]->m_pFormNode, + rgCurLineLayoutItems[0][j]->m_sSize); + } else { + rgCurLineLayoutItems[0][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[0][j]->m_pFormNode)) { + fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width; + } + } + m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] - + fGroupWidths[2]) / + 2; + for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { + if (bRootForceTb) { + rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos( + rgCurLineLayoutItems[1][j]->m_pFormNode, + rgCurLineLayoutItems[1][j]->m_sSize); + } else { + rgCurLineLayoutItems[1][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[1][j]->m_pFormNode)) { + fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width; + } + } + m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = fContentWidthLimit - fGroupWidths[2]; + for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { + if (bRootForceTb) { + rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos( + rgCurLineLayoutItems[2][j]->m_pFormNode, + rgCurLineLayoutItems[2][j]->m_sSize); + } else { + rgCurLineLayoutItems[2][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[2][j]->m_pFormNode)) { + fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width; + } + } + m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); + m_fLastRowWidth = fCurPos; + } + } else { + float fCurPos; + fCurPos = fGroupWidths[0]; + for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[0][j]->m_pFormNode)) { + fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width; + } + rgCurLineLayoutItems[0][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] - + fGroupWidths[2]) / + 2; + for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[1][j]->m_pFormNode)) { + fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width; + } + rgCurLineLayoutItems[1][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); + m_fLastRowWidth = fCurPos; + } + fCurPos = fContentWidthLimit; + for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { + if (XFA_ItemLayoutProcessor_IsTakingSpace( + rgCurLineLayoutItems[2][j]->m_pFormNode)) { + fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width; + } + rgCurLineLayoutItems[2][j]->m_sPos = + CFX_PointF(fCurPos, *fContentCurRowY); + m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); + m_fLastRowWidth = fCurPos; + } + } + m_fLastRowY = *fContentCurRowY; + *fContentCurRowY += fContentCurRowHeight; + if (bContainerWidthAutoSize) { + float fChildSuppliedWidth = fGroupWidths[0]; + if (fContentWidthLimit < FLT_MAX && + fContentWidthLimit > fChildSuppliedWidth) { + fChildSuppliedWidth = fContentWidthLimit; + } + *fContentCalculatedWidth = + std::max(*fContentCalculatedWidth, fChildSuppliedWidth); + } + if (bContainerHeightAutoSize) { + *fContentCalculatedHeight = + std::max(*fContentCalculatedHeight, *fContentCurRowY); + } + return true; +} + +CXFA_Node* CXFA_ItemLayoutProcessor::GetSubformSetParent( + CXFA_Node* pSubformSet) { + if (pSubformSet && pSubformSet->GetElementType() == XFA_Element::SubformSet) { + CXFA_Node* pParent = pSubformSet->GetParent(); + while (pParent) { + if (pParent->GetElementType() != XFA_Element::SubformSet) + return pParent; + pParent = pParent->GetParent(); + } + } + return pSubformSet; +} + +void CXFA_ItemLayoutProcessor::DoLayoutField() { + if (m_pLayoutItem) + return; + + ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); + m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); + if (!m_pLayoutItem) + return; + + CXFA_Document* pDocument = m_pFormNode->GetDocument(); + CXFA_FFNotify* pNotify = pDocument->GetNotify(); + CFX_SizeF size(-1, -1); + pNotify->StartFieldDrawLayout(m_pFormNode, size.width, size.height); + + int32_t nRotate = XFA_MapRotation( + m_pFormNode->JSObject()->GetInteger(XFA_Attribute::Rotate)); + if (nRotate == 90 || nRotate == 270) + std::swap(size.width, size.height); + + SetCurrentComponentSize(size); +} + +XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayout( + bool bUseBreakControl, + float fHeightLimit, + float fRealHeight, + CXFA_LayoutContext* pContext) { + switch (m_pFormNode->GetElementType()) { + case XFA_Element::Subform: + case XFA_Element::Area: + case XFA_Element::ExclGroup: + case XFA_Element::SubformSet: { + bool bRootForceTb = false; + CXFA_Node* pLayoutNode = GetSubformSetParent(m_pFormNode); + XFA_AttributeEnum eLayoutStrategy = GetLayout(pLayoutNode, &bRootForceTb); + switch (eLayoutStrategy) { + case XFA_AttributeEnum::Tb: + case XFA_AttributeEnum::Lr_tb: + case XFA_AttributeEnum::Rl_tb: + return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy, + fHeightLimit, fRealHeight, pContext, + bRootForceTb); + case XFA_AttributeEnum::Position: + case XFA_AttributeEnum::Row: + case XFA_AttributeEnum::Rl_row: + default: + DoLayoutPositionedContainer(pContext); + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; + return XFA_ItemLayoutProcessorResult::Done; + case XFA_AttributeEnum::Table: + DoLayoutTableContainer(pLayoutNode); + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; + return XFA_ItemLayoutProcessorResult::Done; + } + } + case XFA_Element::Draw: + case XFA_Element::Field: + DoLayoutField(); + m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; + return XFA_ItemLayoutProcessorResult::Done; + case XFA_Element::ContentArea: + return XFA_ItemLayoutProcessorResult::Done; + default: + return XFA_ItemLayoutProcessorResult::Done; + } +} + +CFX_SizeF CXFA_ItemLayoutProcessor::GetCurrentComponentSize() { + return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height); +} + +void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(const CFX_PointF& pos) { + m_pLayoutItem->m_sPos = pos; +} + +void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(const CFX_SizeF& size) { + m_pLayoutItem->m_sSize = size; +} + +bool CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( + CXFA_Node* pFormNode) { + if (!pFormNode) + return false; + + CXFA_Node* pTemplate = pFormNode->GetTemplateNodeIfExists(); + if (!pTemplate) + pTemplate = pFormNode; + + int32_t iMax = + pTemplate->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur)->GetMax(); + if (iMax < 0) + return true; + + int32_t iCount = m_PendingNodesCount[pTemplate]; + if (iCount >= iMax) + return false; + + m_PendingNodesCount[pTemplate] = iCount + 1; + return true; +} diff --git a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.h b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.h new file mode 100644 index 0000000000000000000000000000000000000000..e1780952073acbe69aa679ee9ce950998c3327cc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.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 XFA_FXFA_PARSER_CXFA_ITEMLAYOUTPROCESSOR_H_ +#define XFA_FXFA_PARSER_CXFA_ITEMLAYOUTPROCESSOR_H_ + +#include <float.h> + +#include <list> +#include <map> +#include <tuple> +#include <vector> + +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/fxfa_basic.h" + +#define XFA_LAYOUT_INVALIDNODE ((CXFA_Node*)(intptr_t)-1) +#define XFA_LAYOUT_FLOAT_PERCISION (0.0005f) + +class CXFA_ContainerLayoutItem; +class CXFA_ContentLayoutItem; +class CXFA_ItemLayoutProcessor; +class CXFA_LayoutContext; +class CXFA_LayoutPageMgr; +class CXFA_LayoutProcessor; +class CXFA_Node; + +enum class XFA_ItemLayoutProcessorResult { + Done, + PageFullBreak, + RowFullBreak, + ManualBreak, +}; + +enum class XFA_ItemLayoutProcessorStages { + None, + BookendLeader, + BreakBefore, + Keep, + Container, + BreakAfter, + BookendTrailer, + Done, +}; + +bool XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node* pNode); + +class CXFA_ItemLayoutProcessor { + public: + static bool IncrementRelayoutNode(CXFA_LayoutProcessor* pLayoutProcessor, + CXFA_Node* pNode, + CXFA_Node* pParentNode); + + CXFA_ItemLayoutProcessor(CXFA_Node* pNode, CXFA_LayoutPageMgr* pPageMgr); + ~CXFA_ItemLayoutProcessor(); + + XFA_ItemLayoutProcessorResult DoLayout(bool bUseBreakControl, + float fHeightLimit, + float fRealHeight, + CXFA_LayoutContext* pContext); + void DoLayoutPageArea(CXFA_ContainerLayoutItem* pPageAreaLayoutItem); + + CFX_SizeF GetCurrentComponentSize(); + CXFA_Node* GetFormNode() { return m_pFormNode; } + bool HasLayoutItem() const { return !!m_pLayoutItem; } + CXFA_ContentLayoutItem* ExtractLayoutItem(); + void SplitLayoutItem(float fSplitPos); + + float FindSplitPos(float fProposedSplitPos); + + bool ProcessKeepForSplit( + CXFA_ItemLayoutProcessor* pParentProcessor, + CXFA_ItemLayoutProcessor* pChildProcessor, + XFA_ItemLayoutProcessorResult eRetValue, + std::vector<CXFA_ContentLayoutItem*>* rgCurLineLayoutItem, + float* fContentCurRowAvailWidth, + float* fContentCurRowHeight, + float* fContentCurRowY, + bool* bAddedItemInRow, + bool* bForceEndPage, + XFA_ItemLayoutProcessorResult* result); + void ProcessUnUseOverFlow(CXFA_Node* pLeaderNode, + CXFA_Node* pTrailerNode, + CXFA_ContentLayoutItem* pTrailerItem, + CXFA_Node* pFormNode); + bool IsAddNewRowForTrailer(CXFA_ContentLayoutItem* pTrailerItem); + bool JudgeLeaderOrTrailerForOccur(CXFA_Node* pFormNode); + + CXFA_ContentLayoutItem* CreateContentLayoutItem(CXFA_Node* pFormNode); + + CXFA_Node* m_pFormNode; + CXFA_ContentLayoutItem* m_pLayoutItem; + CXFA_Node* m_pCurChildNode; + float m_fUsedSize; + CXFA_LayoutPageMgr* m_pPageMgr; + std::list<CXFA_Node*> m_PendingNodes; + bool m_bBreakPending; + std::vector<float> m_rgSpecifiedColumnWidths; + std::vector<CXFA_ContentLayoutItem*> m_arrayKeepItems; + float m_fLastRowWidth; + float m_fLastRowY; + bool m_bUseInheriated; + XFA_ItemLayoutProcessorResult m_ePreProcessRs; + + private: + void SetCurrentComponentPos(const CFX_PointF& pos); + void SetCurrentComponentSize(const CFX_SizeF& size); + + void SplitLayoutItem(CXFA_ContentLayoutItem* pLayoutItem, + CXFA_ContentLayoutItem* pSecondParent, + float fSplitPos); + float InsertKeepLayoutItems(); + bool CalculateRowChildPosition( + std::vector<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], + XFA_AttributeEnum eFlowStrategy, + bool bContainerHeightAutoSize, + bool bContainerWidthAutoSize, + float* fContentCalculatedWidth, + float* fContentCalculatedHeight, + float* fContentCurRowY, + float fContentCurRowHeight, + float fContentWidthLimit, + bool bRootForceTb); + void ProcessUnUseBinds(CXFA_Node* pFormNode); + bool JudgePutNextPage(CXFA_ContentLayoutItem* pParentLayoutItem, + float fChildHeight, + std::vector<CXFA_ContentLayoutItem*>* pKeepItems); + + void DoLayoutPositionedContainer(CXFA_LayoutContext* pContext); + void DoLayoutTableContainer(CXFA_Node* pLayoutNode); + XFA_ItemLayoutProcessorResult DoLayoutFlowedContainer( + bool bUseBreakControl, + XFA_AttributeEnum eFlowStrategy, + float fHeightLimit, + float fRealHeight, + CXFA_LayoutContext* pContext, + bool bRootForceTb); + void DoLayoutField(); + + void GotoNextContainerNode(CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages& nCurStage, + CXFA_Node* pParentContainer, + bool bUsePageBreak); + + bool ProcessKeepNodesForCheckNext(CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages& nCurStage, + CXFA_Node*& pNextContainer, + bool& bLastKeepNode); + + bool ProcessKeepNodesForBreakBefore(CXFA_Node*& pCurActionNode, + XFA_ItemLayoutProcessorStages& nCurStage, + CXFA_Node* pContainerNode); + + CXFA_Node* GetSubformSetParent(CXFA_Node* pSubformSet); + + bool m_bKeepBreakFinish; + bool m_bIsProcessKeep; + CXFA_Node* m_pKeepHeadNode; + CXFA_Node* m_pKeepTailNode; + CXFA_ContentLayoutItem* m_pOldLayoutItem; + CXFA_ItemLayoutProcessor* m_pCurChildPreprocessor; + XFA_ItemLayoutProcessorStages m_nCurChildNodeStage; + std::map<CXFA_Node*, int32_t> m_PendingNodesCount; + float m_fWidthLimite; + bool m_bHasAvailHeight; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ITEMLAYOUTPROCESSOR_H_ diff --git a/xfa/fxfa/parser/cxfa_items.cpp b/xfa/fxfa/parser/cxfa_items.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06feddb8d3fffc72d12dc42afff3becee4c5bed1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_items.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_items.h" + +#include "fxjs/xfa/cjx_items.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::Save, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"items"; + +} // namespace + +CXFA_Items::CXFA_Items(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Items, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Items>(this)) {} + +CXFA_Items::~CXFA_Items() {} diff --git a/xfa/fxfa/parser/cxfa_items.h b/xfa/fxfa/parser/cxfa_items.h new file mode 100644 index 0000000000000000000000000000000000000000..586fabdeca7c5be01b84de30471056bb98735eee --- /dev/null +++ b/xfa/fxfa/parser/cxfa_items.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ITEMS_H_ +#define XFA_FXFA_PARSER_CXFA_ITEMS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Items : public CXFA_Node { + public: + CXFA_Items(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Items() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ITEMS_H_ diff --git a/xfa/fxfa/parser/cxfa_jog.cpp b/xfa/fxfa/parser/cxfa_jog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3735e2f992d44f9be12856c83823f031028d7624 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_jog.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_jog.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"jog"; + +} // namespace + +CXFA_Jog::CXFA_Jog(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Jog, + nullptr, + kAttributeData, + kName) {} + +CXFA_Jog::~CXFA_Jog() {} diff --git a/xfa/fxfa/parser/cxfa_jog.h b/xfa/fxfa/parser/cxfa_jog.h new file mode 100644 index 0000000000000000000000000000000000000000..266ccd1fd42c023b95cc390ade9ee00c5122fb93 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_jog.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_JOG_H_ +#define XFA_FXFA_PARSER_CXFA_JOG_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Jog : public CXFA_Node { + public: + CXFA_Jog(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Jog() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_JOG_H_ diff --git a/xfa/fxfa/parser/cxfa_keep.cpp b/xfa/fxfa/parser/cxfa_keep.cpp new file mode 100644 index 0000000000000000000000000000000000000000..beb22fa6341fe63658327d4d6d35a015c51483c7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_keep.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_keep.h" + +#include "fxjs/xfa/cjx_keep.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Next, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Previous, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Intact, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::None}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"keep"; + +} // namespace + +CXFA_Keep::CXFA_Keep(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Keep, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Keep>(this)) {} + +CXFA_Keep::~CXFA_Keep() {} diff --git a/xfa/fxfa/parser/cxfa_keep.h b/xfa/fxfa/parser/cxfa_keep.h new file mode 100644 index 0000000000000000000000000000000000000000..7d53f9634af04d0da919c8cc64bc167aa23eb97e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_keep.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_KEEP_H_ +#define XFA_FXFA_PARSER_CXFA_KEEP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Keep : public CXFA_Node { + public: + CXFA_Keep(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Keep() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_KEEP_H_ diff --git a/xfa/fxfa/parser/cxfa_keyusage.cpp b/xfa/fxfa/parser/cxfa_keyusage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13054bed697aaea71db4fceb96628dba30759c60 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_keyusage.cpp @@ -0,0 +1,46 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_keyusage.h" + +#include "fxjs/xfa/cjx_keyusage.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::NonRepudiation, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::EncipherOnly, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::DigitalSignature, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CrlSign, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::KeyAgreement, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::KeyEncipherment, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataEncipherment, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::KeyCertSign, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DecipherOnly, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"keyUsage"; + +} // namespace + +CXFA_KeyUsage::CXFA_KeyUsage(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::KeyUsage, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_KeyUsage>(this)) {} + +CXFA_KeyUsage::~CXFA_KeyUsage() {} diff --git a/xfa/fxfa/parser/cxfa_keyusage.h b/xfa/fxfa/parser/cxfa_keyusage.h new file mode 100644 index 0000000000000000000000000000000000000000..b25807411bdef93e7679fcdc6c436ff6d55753ef --- /dev/null +++ b/xfa/fxfa/parser/cxfa_keyusage.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_KEYUSAGE_H_ +#define XFA_FXFA_PARSER_CXFA_KEYUSAGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_KeyUsage : public CXFA_Node { + public: + CXFA_KeyUsage(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_KeyUsage() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_KEYUSAGE_H_ diff --git a/xfa/fxfa/parser/cxfa_labelprinter.cpp b/xfa/fxfa/parser/cxfa_labelprinter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55b04da7de4c79da0c707d1beaf4abd7a7f38ac9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_labelprinter.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_labelprinter.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::FontInfo, 1, 0}, + {XFA_Element::Xdc, 1, 0}, + {XFA_Element::BatchOutput, 1, 0}, + {XFA_Element::FlipLabel, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Zpl}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"labelPrinter"; + +} // namespace + +CXFA_LabelPrinter::CXFA_LabelPrinter(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::LabelPrinter, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_LabelPrinter::~CXFA_LabelPrinter() {} diff --git a/xfa/fxfa/parser/cxfa_labelprinter.h b/xfa/fxfa/parser/cxfa_labelprinter.h new file mode 100644 index 0000000000000000000000000000000000000000..e3f5d3bf75413166296401bf6076daf9509bc1a8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_labelprinter.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LABELPRINTER_H_ +#define XFA_FXFA_PARSER_CXFA_LABELPRINTER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_LabelPrinter : public CXFA_Node { + public: + CXFA_LabelPrinter(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_LabelPrinter() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LABELPRINTER_H_ diff --git a/xfa/fxfa/parser/cxfa_layout.cpp b/xfa/fxfa/parser/cxfa_layout.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc2933f5958f9d0cd01e6bdef93fbc56f965a786 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_layout.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_layout.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"layout"; + +} // namespace + +CXFA_Layout::CXFA_Layout(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Layout, + nullptr, + kAttributeData, + kName) {} + +CXFA_Layout::~CXFA_Layout() {} diff --git a/xfa/fxfa/parser/cxfa_layout.h b/xfa/fxfa/parser/cxfa_layout.h new file mode 100644 index 0000000000000000000000000000000000000000..93e069e163f8f23ad6e5a43934dde09779b73f86 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_layout.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LAYOUT_H_ +#define XFA_FXFA_PARSER_CXFA_LAYOUT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Layout : public CXFA_Node { + public: + CXFA_Layout(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Layout() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LAYOUT_H_ diff --git a/xfa/fxfa/parser/cxfa_layoutcontext.h b/xfa/fxfa/parser/cxfa_layoutcontext.h new file mode 100644 index 0000000000000000000000000000000000000000..a133ee19d9926781db52331b59f2301091e37ad0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_layoutcontext.h @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LAYOUTCONTEXT_H_ +#define XFA_FXFA_PARSER_CXFA_LAYOUTCONTEXT_H_ + +#include <vector> + +class CXFA_ItemLayoutProcess; +class CXFA_Node; + +class CXFA_LayoutContext { + public: + CXFA_LayoutContext() + : m_prgSpecifiedColumnWidths(nullptr), + m_fCurColumnWidth(0), + m_bCurColumnWidthAvaiable(false), + m_pOverflowProcessor(nullptr), + m_pOverflowNode(nullptr) {} + ~CXFA_LayoutContext() {} + + std::vector<float>* m_prgSpecifiedColumnWidths; + float m_fCurColumnWidth; + bool m_bCurColumnWidthAvaiable; + CXFA_ItemLayoutProcessor* m_pOverflowProcessor; + CXFA_Node* m_pOverflowNode; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LAYOUTCONTEXT_H_ diff --git a/xfa/fxfa/parser/cxfa_layoutitem.cpp b/xfa/fxfa/parser/cxfa_layoutitem.cpp index 476d6118ac38e6b9f36be9f3e8fc99d20f65781a..7fb921ab840a97c8801f486ff4a517d4eeeb5cc0 100644 --- a/xfa/fxfa/parser/cxfa_layoutitem.cpp +++ b/xfa/fxfa/parser/cxfa_layoutitem.cpp @@ -6,10 +6,13 @@ #include "xfa/fxfa/parser/cxfa_layoutitem.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/cxfa_ffnotify.h" #include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" #include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_margin.h" #include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" void XFA_ReleaseLayoutItem(CXFA_LayoutItem* pLayoutItem) { CXFA_LayoutItem* pNode = pLayoutItem->m_pFirstChild; @@ -19,12 +22,10 @@ void XFA_ReleaseLayoutItem(CXFA_LayoutItem* pLayoutItem) { while (pNode) { CXFA_LayoutItem* pNext = pNode->m_pNextSibling; pNode->m_pParent = nullptr; - pNotify->OnLayoutItemRemoving(pDocLayout, - static_cast<CXFA_LayoutItem*>(pNode)); + pNotify->OnLayoutItemRemoving(pDocLayout, pNode); XFA_ReleaseLayoutItem(pNode); pNode = pNext; } - pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem); if (pLayoutItem->m_pFormNode->GetElementType() == XFA_Element::PageArea) { pNotify->OnPageEvent(static_cast<CXFA_ContainerLayoutItem*>(pLayoutItem), @@ -64,7 +65,7 @@ CXFA_ContainerLayoutItem* CXFA_LayoutItem::GetPage() const { CFX_RectF CXFA_LayoutItem::GetRect(bool bRelative) const { ASSERT(m_bIsContentLayoutItem); - auto pThis = static_cast<const CXFA_ContentLayoutItem*>(this); + auto* pThis = static_cast<const CXFA_ContentLayoutItem*>(this); CFX_PointF sPos = pThis->m_sPos; CFX_SizeF sSize = pThis->m_sSize; if (bRelative) @@ -74,23 +75,28 @@ CFX_RectF CXFA_LayoutItem::GetRect(bool bRelative) const { pLayoutItem = pLayoutItem->m_pParent) { if (CXFA_ContentLayoutItem* pContent = pLayoutItem->AsContentLayoutItem()) { sPos += pContent->m_sPos; - CXFA_Node* pMarginNode = - pLayoutItem->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); + CXFA_Margin* pMarginNode = + pLayoutItem->m_pFormNode->GetFirstChildByClass<CXFA_Margin>( + XFA_Element::Margin); if (pMarginNode) { - sPos += CFX_PointF(pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset) - .ToUnit(XFA_UNIT_Pt), - pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset) - .ToUnit(XFA_UNIT_Pt)); + sPos += CFX_PointF(pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::LeftInset) + .ToUnit(XFA_Unit::Pt), + pMarginNode->JSObject() + ->GetMeasure(XFA_Attribute::TopInset) + .ToUnit(XFA_Unit::Pt)); } continue; } if (pLayoutItem->m_pFormNode->GetElementType() == XFA_Element::ContentArea) { - sPos += CFX_PointF(pLayoutItem->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_X) - .ToUnit(XFA_UNIT_Pt), - pLayoutItem->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_Y) - .ToUnit(XFA_UNIT_Pt)); + sPos += CFX_PointF(pLayoutItem->m_pFormNode->JSObject() + ->GetMeasure(XFA_Attribute::X) + .ToUnit(XFA_Unit::Pt), + pLayoutItem->m_pFormNode->JSObject() + ->GetMeasure(XFA_Attribute::Y) + .ToUnit(XFA_Unit::Pt)); break; } if (pLayoutItem->m_pFormNode->GetElementType() == XFA_Element::PageArea) diff --git a/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp b/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp index f38ef0ebfda0076593ae88d8b7ae840e8aae54b0..123cafb1e9105bc24c2666598e6d9b78c9a0482d 100644 --- a/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp +++ b/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp @@ -6,21 +6,31 @@ #include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/cxfa_ffnotify.h" #include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" +#include "xfa/fxfa/parser/cxfa_contentarea.h" #include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h" #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" +#include "xfa/fxfa/parser/cxfa_medium.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#include "xfa/fxfa/parser/cxfa_occur.h" +#include "xfa/fxfa/parser/cxfa_pageset.h" +#include "xfa/fxfa/parser/cxfa_subform.h" #include "xfa/fxfa/parser/cxfa_traversestrategy_contentareacontainerlayoutitem.h" #include "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h" -#include "xfa/fxfa/parser/xfa_layout_itemlayout.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/parser/xfa_utils.h" namespace { @@ -61,8 +71,9 @@ class PageSetContainerLayoutItem { uint32_t GetRelevant(CXFA_Node* pFormItem, uint32_t dwParentRelvant) { uint32_t dwRelevant = XFA_WidgetStatus_Viewable | XFA_WidgetStatus_Printable; - CFX_WideStringC wsRelevant; - if (pFormItem->TryCData(XFA_ATTRIBUTE_Relevant, wsRelevant)) { + WideString wsRelevant = + pFormItem->JSObject()->GetCData(XFA_Attribute::Relevant); + if (!wsRelevant.IsEmpty()) { if (wsRelevant == L"+print" || wsRelevant == L"print") dwRelevant &= ~XFA_WidgetStatus_Viewable; else if (wsRelevant == L"-print") @@ -91,12 +102,13 @@ void SyncContainer(CXFA_FFNotify* pNotify, uint32_t dwStatus = 0; uint32_t dwRelevantContainer = 0; if (bVisible) { - XFA_ATTRIBUTEENUM eAttributeValue = - pContainerItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence); - if (eAttributeValue == XFA_ATTRIBUTEENUM_Visible || - eAttributeValue == XFA_ATTRIBUTEENUM_Unknown) { + XFA_AttributeEnum eAttributeValue = + pContainerItem->m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible); + if (eAttributeValue == XFA_AttributeEnum::Visible) bVisibleItem = true; - } + dwRelevantContainer = GetRelevant(pContainerItem->m_pFormNode, dwRelevant); dwStatus = (bVisibleItem ? XFA_WidgetStatus_Visible : 0) | dwRelevantContainer; @@ -132,22 +144,26 @@ void RemoveLayoutItem(CXFA_ContainerLayoutItem* pLayoutItem) { CXFA_Node* ResolveBreakTarget(CXFA_Node* pPageSetRoot, bool bNewExprStyle, - CFX_WideStringC& wsTargetExpr) { + WideString& wsTargetAll) { + if (!pPageSetRoot) + return nullptr; + CXFA_Document* pDocument = pPageSetRoot->GetDocument(); - if (wsTargetExpr.IsEmpty()) + if (wsTargetAll.IsEmpty()) return nullptr; - CFX_WideString wsTargetAll(wsTargetExpr); - wsTargetAll.TrimLeft(); - wsTargetAll.TrimRight(); + wsTargetAll.Trim(); int32_t iSplitIndex = 0; bool bTargetAllFind = true; while (iSplitIndex != -1) { - CFX_WideString wsExpr; - int32_t iSplitNextIndex = 0; + WideString wsExpr; + Optional<size_t> iSplitNextIndex = 0; if (!bTargetAllFind) { iSplitNextIndex = wsTargetAll.Find(' ', iSplitIndex); - wsExpr = wsTargetAll.Mid(iSplitIndex, iSplitNextIndex - iSplitIndex); + if (!iSplitNextIndex.has_value()) + return nullptr; + wsExpr = + wsTargetAll.Mid(iSplitIndex, iSplitNextIndex.value() - iSplitIndex); } else { wsExpr = wsTargetAll; } @@ -155,27 +171,28 @@ CXFA_Node* ResolveBreakTarget(CXFA_Node* pPageSetRoot, return nullptr; bTargetAllFind = false; - if (wsExpr.GetAt(0) == '#') { + if (wsExpr[0] == '#') { CXFA_Node* pNode = pDocument->GetNodeByID( ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Template)), - wsExpr.Mid(1).AsStringC()); + wsExpr.Right(wsExpr.GetLength() - 1).AsStringView()); if (pNode) return pNode; } else if (bNewExprStyle) { - CFX_WideString wsProcessedTarget = wsExpr; - if (wsExpr.Left(4) == L"som(" && wsExpr.Right(1) == L")") { + WideString wsProcessedTarget = wsExpr; + if (wsExpr.Left(4) == L"som(" && wsExpr.Last() == L')') { wsProcessedTarget = wsExpr.Mid(4, wsExpr.GetLength() - 5); } XFA_RESOLVENODE_RS rs; - int32_t iCount = pDocument->GetScriptContext()->ResolveObjects( - pPageSetRoot, wsProcessedTarget.AsStringC(), rs, + bool iRet = pDocument->GetScriptContext()->ResolveObjects( + pPageSetRoot, wsProcessedTarget.AsStringView(), &rs, XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Siblings | - XFA_RESOLVENODE_Parent); - if (iCount > 0 && rs.nodes[0]->IsNode()) - return rs.nodes[0]->AsNode(); + XFA_RESOLVENODE_Parent, + nullptr); + if (iRet && rs.objects.front()->IsNode()) + return rs.objects.front()->AsNode(); } - iSplitIndex = iSplitNextIndex; + iSplitIndex = iSplitNextIndex.value(); } return nullptr; } @@ -221,6 +238,14 @@ void SyncRemoveLayoutItem(CXFA_LayoutItem* pParentLayoutItem, } } +bool RunBreakTestScript(CXFA_Script* pTestScript) { + WideString wsExpression = pTestScript->JSObject()->GetContent(false); + if (wsExpression.IsEmpty()) + return true; + return pTestScript->GetDocument()->GetNotify()->RunScript( + pTestScript, pTestScript->GetContainerParent()); +} + } // namespace class CXFA_ContainerRecord { @@ -246,7 +271,7 @@ CXFA_LayoutPageMgr::CXFA_LayoutPageMgr(CXFA_LayoutProcessor* pLayoutProcessor) m_pCurPageArea(nullptr), m_nAvailPages(0), m_nCurPageCount(0), - m_ePageSetMode(XFA_ATTRIBUTEENUM_OrderedOccurrence), + m_ePageSetMode(XFA_AttributeEnum::OrderedOccurrence), m_bCreateOverFlowPage(false) {} CXFA_LayoutPageMgr::~CXFA_LayoutPageMgr() { @@ -261,12 +286,15 @@ CXFA_LayoutPageMgr::~CXFA_LayoutPageMgr() { bool CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode) { PrepareLayout(); - CXFA_Node* pTemplateNode = pFormNode->GetTemplateNode(); + CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists(); if (!pTemplateNode) return false; - m_pTemplatePageSetRoot = pTemplateNode->GetProperty(0, XFA_Element::PageSet); + m_pTemplatePageSetRoot = + pTemplateNode->JSObject()->GetOrCreateProperty<CXFA_PageSet>( + 0, XFA_Element::PageSet); ASSERT(m_pTemplatePageSetRoot); + if (m_pPageSetLayoutItemRoot) { m_pPageSetLayoutItemRoot->m_pParent = nullptr; m_pPageSetLayoutItemRoot->m_pFirstChild = nullptr; @@ -277,22 +305,22 @@ bool CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode) { new CXFA_ContainerLayoutItem(m_pTemplatePageSetRoot); } m_pPageSetCurRoot = m_pPageSetLayoutItemRoot; - m_pTemplatePageSetRoot->SetUserData(XFA_LAYOUTITEMKEY, - (void*)m_pPageSetLayoutItemRoot); - XFA_ATTRIBUTEENUM eRelation = - m_pTemplatePageSetRoot->GetEnum(XFA_ATTRIBUTE_Relation); - if (eRelation != XFA_ATTRIBUTEENUM_Unknown) + m_pTemplatePageSetRoot->JSObject()->SetLayoutItem(m_pPageSetLayoutItemRoot); + + XFA_AttributeEnum eRelation = + m_pTemplatePageSetRoot->JSObject()->GetEnum(XFA_Attribute::Relation); + if (eRelation != XFA_AttributeEnum::Unknown) m_ePageSetMode = eRelation; InitPageSetMap(); CXFA_Node* pPageArea = nullptr; int32_t iCount = 0; - for (pPageArea = m_pTemplatePageSetRoot->GetNodeItem(XFA_NODEITEM_FirstChild); - pPageArea; - pPageArea = pPageArea->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (pPageArea = m_pTemplatePageSetRoot->GetFirstChild(); pPageArea; + pPageArea = pPageArea->GetNextSibling()) { if (pPageArea->GetElementType() == XFA_Element::PageArea) { iCount++; - if (pPageArea->GetFirstChildByClass(XFA_Element::ContentArea)) + if (pPageArea->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea)) return true; } } @@ -300,9 +328,10 @@ bool CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode) { return false; CXFA_Document* pDocument = pTemplateNode->GetDocument(); - pPageArea = m_pTemplatePageSetRoot->GetChild(0, XFA_Element::PageArea); + pPageArea = m_pTemplatePageSetRoot->GetChild<CXFA_Node>( + 0, XFA_Element::PageArea, false); if (!pPageArea) { - pPageArea = pDocument->CreateNode(m_pTemplatePageSetRoot->GetPacketID(), + pPageArea = pDocument->CreateNode(m_pTemplatePageSetRoot->GetPacketType(), XFA_Element::PageArea); if (!pPageArea) return false; @@ -310,37 +339,39 @@ bool CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode) { m_pTemplatePageSetRoot->InsertChild(pPageArea, nullptr); pPageArea->SetFlag(XFA_NodeFlag_Initialized, true); } - CXFA_Node* pContentArea = pPageArea->GetChild(0, XFA_Element::ContentArea); + CXFA_ContentArea* pContentArea = + pPageArea->GetChild<CXFA_ContentArea>(0, XFA_Element::ContentArea, false); if (!pContentArea) { - pContentArea = pDocument->CreateNode(pPageArea->GetPacketID(), - XFA_Element::ContentArea); + pContentArea = static_cast<CXFA_ContentArea*>(pDocument->CreateNode( + pPageArea->GetPacketType(), XFA_Element::ContentArea)); if (!pContentArea) return false; pPageArea->InsertChild(pContentArea, nullptr); pContentArea->SetFlag(XFA_NodeFlag_Initialized, true); - pContentArea->SetMeasure(XFA_ATTRIBUTE_X, - CXFA_Measurement(0.25f, XFA_UNIT_In)); - pContentArea->SetMeasure(XFA_ATTRIBUTE_Y, - CXFA_Measurement(0.25f, XFA_UNIT_In)); - pContentArea->SetMeasure(XFA_ATTRIBUTE_W, - CXFA_Measurement(8.0f, XFA_UNIT_In)); - pContentArea->SetMeasure(XFA_ATTRIBUTE_H, - CXFA_Measurement(10.5f, XFA_UNIT_In)); - } - CXFA_Node* pMedium = pPageArea->GetChild(0, XFA_Element::Medium); + pContentArea->JSObject()->SetMeasure( + XFA_Attribute::X, CXFA_Measurement(0.25f, XFA_Unit::In), false); + pContentArea->JSObject()->SetMeasure( + XFA_Attribute::Y, CXFA_Measurement(0.25f, XFA_Unit::In), false); + pContentArea->JSObject()->SetMeasure( + XFA_Attribute::W, CXFA_Measurement(8.0f, XFA_Unit::In), false); + pContentArea->JSObject()->SetMeasure( + XFA_Attribute::H, CXFA_Measurement(10.5f, XFA_Unit::In), false); + } + CXFA_Medium* pMedium = + pPageArea->GetChild<CXFA_Medium>(0, XFA_Element::Medium, false); if (!pMedium) { - pMedium = - pDocument->CreateNode(pPageArea->GetPacketID(), XFA_Element::Medium); + pMedium = static_cast<CXFA_Medium*>( + pDocument->CreateNode(pPageArea->GetPacketType(), XFA_Element::Medium)); if (!pContentArea) return false; pPageArea->InsertChild(pMedium, nullptr); pMedium->SetFlag(XFA_NodeFlag_Initialized, true); - pMedium->SetMeasure(XFA_ATTRIBUTE_Short, - CXFA_Measurement(8.5f, XFA_UNIT_In)); - pMedium->SetMeasure(XFA_ATTRIBUTE_Long, - CXFA_Measurement(11.0f, XFA_UNIT_In)); + pMedium->JSObject()->SetMeasure( + XFA_Attribute::Short, CXFA_Measurement(8.5f, XFA_Unit::In), false); + pMedium->JSObject()->SetMeasure( + XFA_Attribute::Long, CXFA_Measurement(11.0f, XFA_Unit::In), false); } return true; } @@ -349,15 +380,13 @@ bool CXFA_LayoutPageMgr::PrepareFirstPage(CXFA_Node* pRootSubform) { bool bProBreakBefore = false; CXFA_Node* pBreakBeforeNode = nullptr; while (pRootSubform) { - for (CXFA_Node* pBreakNode = - pRootSubform->GetNodeItem(XFA_NODEITEM_FirstChild); - pBreakNode; - pBreakNode = pBreakNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pBreakNode = pRootSubform->GetFirstChild(); pBreakNode; + pBreakNode = pBreakNode->GetNextSibling()) { XFA_Element eType = pBreakNode->GetElementType(); if (eType == XFA_Element::BreakBefore || (eType == XFA_Element::Break && - pBreakNode->GetEnum(XFA_ATTRIBUTE_Before) != - XFA_ATTRIBUTEENUM_Auto)) { + pBreakNode->JSObject()->GetEnum(XFA_Attribute::Before) != + XFA_AttributeEnum::Auto)) { bProBreakBefore = true; pBreakBeforeNode = pBreakNode; break; @@ -367,14 +396,16 @@ bool CXFA_LayoutPageMgr::PrepareFirstPage(CXFA_Node* pRootSubform) { break; bProBreakBefore = true; - pRootSubform = pRootSubform->GetFirstChildByClass(XFA_Element::Subform); + pRootSubform = + pRootSubform->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); while (pRootSubform && !XFA_ItemLayoutProcessor_IsTakingSpace(pRootSubform)) { - pRootSubform = - pRootSubform->GetNextSameClassSibling(XFA_Element::Subform); + pRootSubform = pRootSubform->GetNextSameClassSibling<CXFA_Subform>( + XFA_Element::Subform); } } - CXFA_Node *pLeader, *pTrailer; + CXFA_Node* pLeader; + CXFA_Node* pTrailer; if (pBreakBeforeNode && ExecuteBreakBeforeOrAfter(pBreakBeforeNode, true, pLeader, pTrailer)) { m_CurrentContainerRecordIter = m_ProposedContainerRecords.begin(); @@ -454,14 +485,15 @@ void CXFA_LayoutPageMgr::SubmitContentItem( } } -FX_FLOAT CXFA_LayoutPageMgr::GetAvailHeight() { +float CXFA_LayoutPageMgr::GetAvailHeight() { CXFA_ContainerLayoutItem* pLayoutItem = GetCurrentContainerRecord()->pCurContentArea; if (!pLayoutItem || !pLayoutItem->m_pFormNode) return 0.0f; - FX_FLOAT fAvailHeight = - pLayoutItem->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); + float fAvailHeight = pLayoutItem->m_pFormNode->JSObject() + ->GetMeasure(XFA_Attribute::H) + .ToUnit(XFA_Unit::Pt); if (fAvailHeight >= XFA_LAYOUT_FLOAT_PERCISION) return fAvailHeight; if (m_CurrentContainerRecordIter == m_ProposedContainerRecords.begin()) @@ -469,16 +501,6 @@ FX_FLOAT CXFA_LayoutPageMgr::GetAvailHeight() { return FLT_MAX; } -bool XFA_LayoutPageMgr_RunBreakTestScript(CXFA_Node* pTestScript) { - CFX_WideString wsExpression; - pTestScript->TryContent(wsExpression); - if (wsExpression.IsEmpty()) - return true; - return pTestScript->GetDocument()->GetNotify()->RunScript( - pTestScript, pTestScript->GetNodeItem(XFA_NODEITEM_Parent, - XFA_ObjectType::ContainerNode)); -} - CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord( CXFA_Node* pPageNode, bool bCreateNew) { @@ -489,14 +511,14 @@ CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord( m_ProposedContainerRecords.push_back(pNewRecord); return pNewRecord; } - CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pPageSet = pPageNode->GetParent(); if (!bCreateNew) { if (pPageSet == m_pTemplatePageSetRoot) { pNewRecord->pCurPageSet = m_pPageSetCurRoot; } else { CXFA_ContainerLayoutItem* pParentLayoutItem = static_cast<CXFA_ContainerLayoutItem*>( - pPageSet->GetUserData(XFA_LAYOUTITEMKEY)); + pPageSet->JSObject()->GetLayoutItem()); if (!pParentLayoutItem) pParentLayoutItem = m_pPageSetCurRoot; @@ -509,12 +531,11 @@ CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord( GetCurrentContainerRecord()->pCurPageSet->m_pParent); } else { pParentPageSetLayout = static_cast<CXFA_ContainerLayoutItem*>( - pPageSet->GetNodeItem(XFA_NODEITEM_Parent) - ->GetUserData(XFA_LAYOUTITEMKEY)); + pPageSet->GetParent()->JSObject()->GetLayoutItem()); } CXFA_ContainerLayoutItem* pPageSetLayoutItem = new CXFA_ContainerLayoutItem(pPageSet); - pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (void*)pPageSetLayoutItem); + pPageSet->JSObject()->SetLayoutItem(pPageSetLayoutItem); if (!pParentPageSetLayout) { CXFA_ContainerLayoutItem* pPrePageSet = m_pPageSetLayoutItemRoot; while (pPrePageSet->m_pNextSibling) { @@ -531,13 +552,13 @@ CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord( } } else { if (pPageNode) { - CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pPageSet = pPageNode->GetParent(); if (pPageSet == m_pTemplatePageSetRoot) { pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot; } else { CXFA_ContainerLayoutItem* pPageSetLayoutItem = new CXFA_ContainerLayoutItem(pPageSet); - pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (void*)pPageSetLayoutItem); + pPageSet->JSObject()->SetLayoutItem(pPageSetLayoutItem); m_pPageSetLayoutItemRoot->AddChild(pPageSetLayoutItem); pNewRecord->pCurPageSet = pPageSetLayoutItem; } @@ -552,17 +573,15 @@ CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord( void CXFA_LayoutPageMgr::AddPageAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pNewPageArea) { CXFA_ContainerLayoutItem* pNewPageAreaLayoutItem = nullptr; - if (m_PageArray.GetSize() > m_nAvailPages) { + if (pdfium::IndexInBounds(m_PageArray, m_nAvailPages)) { CXFA_ContainerLayoutItem* pContainerItem = m_PageArray[m_nAvailPages]; pContainerItem->m_pFormNode = pNewPageArea; m_nAvailPages++; pNewPageAreaLayoutItem = pContainerItem; } else { CXFA_FFNotify* pNotify = pNewPageArea->GetDocument()->GetNotify(); - CXFA_ContainerLayoutItem* pContainerItem = - static_cast<CXFA_ContainerLayoutItem*>( - pNotify->OnCreateLayoutItem(pNewPageArea)); - m_PageArray.Add(pContainerItem); + auto* pContainerItem = pNotify->OnCreateContainerLayoutItem(pNewPageArea); + m_PageArray.push_back(pContainerItem); m_nAvailPages++; pNotify->OnPageEvent(pContainerItem, XFA_PAGEVIEWEVENT_PostRemoved); pNewPageAreaLayoutItem = pContainerItem; @@ -596,13 +615,14 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { sIterator(pRootPageSetLayoutItem); for (CXFA_ContainerLayoutItem* pPageSetLayoutItem = sIterator.GetCurrent(); pPageSetLayoutItem; pPageSetLayoutItem = sIterator.MoveToNext()) { - XFA_ATTRIBUTEENUM ePageRelation = - pPageSetLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Relation); + XFA_AttributeEnum ePageRelation = + pPageSetLayoutItem->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::Relation); switch (ePageRelation) { - case XFA_ATTRIBUTEENUM_OrderedOccurrence: + case XFA_AttributeEnum::OrderedOccurrence: default: { ProcessLastPageSet(); } break; - case XFA_ATTRIBUTEENUM_SimplexPaginated: - case XFA_ATTRIBUTEENUM_DuplexPaginated: { + case XFA_AttributeEnum::SimplexPaginated: + case XFA_AttributeEnum::DuplexPaginated: { CXFA_LayoutItem* pLastPageAreaLayoutItem = nullptr; int32_t nPageAreaCount = 0; for (CXFA_LayoutItem* pPageAreaLayoutItem = @@ -621,33 +641,34 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { if (!FindPageAreaFromPageSet_SimplexDuplex( pPageSetLayoutItem->m_pFormNode, nullptr, nullptr, nullptr, - true, true, nPageAreaCount == 1 ? XFA_ATTRIBUTEENUM_Only - : XFA_ATTRIBUTEENUM_Last) && + true, true, + nPageAreaCount == 1 ? XFA_AttributeEnum::Only + : XFA_AttributeEnum::Last) && (nPageAreaCount == 1 && !FindPageAreaFromPageSet_SimplexDuplex( pPageSetLayoutItem->m_pFormNode, nullptr, nullptr, nullptr, - true, true, XFA_ATTRIBUTEENUM_Last))) { + true, true, XFA_AttributeEnum::Last))) { break; } CXFA_Node* pNode = m_pCurPageArea; - XFA_ATTRIBUTEENUM eCurChoice = - pNode->GetEnum(XFA_ATTRIBUTE_PagePosition); - if (eCurChoice == XFA_ATTRIBUTEENUM_Last) { - XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any; - pNode->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven); - XFA_ATTRIBUTEENUM eLastChoice = - pLastPageAreaLayoutItem->m_pFormNode->GetEnum( - XFA_ATTRIBUTE_PagePosition); - if (eLastChoice == XFA_ATTRIBUTEENUM_First && - (ePageRelation == XFA_ATTRIBUTEENUM_SimplexPaginated || - eOddOrEven != XFA_ATTRIBUTEENUM_Odd)) { + XFA_AttributeEnum eCurChoice = + pNode->JSObject()->GetEnum(XFA_Attribute::PagePosition); + if (eCurChoice == XFA_AttributeEnum::Last) { + XFA_AttributeEnum eOddOrEven = + pNode->JSObject()->GetEnum(XFA_Attribute::OddOrEven); + XFA_AttributeEnum eLastChoice = + pLastPageAreaLayoutItem->m_pFormNode->JSObject()->GetEnum( + XFA_Attribute::PagePosition); + if (eLastChoice == XFA_AttributeEnum::First && + (ePageRelation == XFA_AttributeEnum::SimplexPaginated || + eOddOrEven != XFA_AttributeEnum::Odd)) { CXFA_ContainerRecord* pRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pRecord, pNode); break; } } bool bUsable = true; - CFX_ArrayTemplate<FX_FLOAT> rgUsedHeights; + std::vector<float> rgUsedHeights; for (CXFA_LayoutItem* pChildLayoutItem = pLastPageAreaLayoutItem->m_pFirstChild; pChildLayoutItem; @@ -656,7 +677,7 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { XFA_Element::ContentArea) { continue; } - FX_FLOAT fUsedHeight = 0; + float fUsedHeight = 0; for (CXFA_LayoutItem* pContentChildLayoutItem = pChildLayoutItem->m_pFirstChild; pContentChildLayoutItem; @@ -667,22 +688,21 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { fUsedHeight += pContent->m_sSize.height; } } - rgUsedHeights.Add(fUsedHeight); + rgUsedHeights.push_back(fUsedHeight); } int32_t iCurContentAreaIndex = -1; - for (CXFA_Node* pContentAreaNode = - pNode->GetNodeItem(XFA_NODEITEM_FirstChild); + for (CXFA_Node* pContentAreaNode = pNode->GetFirstChild(); pContentAreaNode; - pContentAreaNode = - pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + pContentAreaNode = pContentAreaNode->GetNextSibling()) { if (pContentAreaNode->GetElementType() != XFA_Element::ContentArea) { continue; } iCurContentAreaIndex++; if (rgUsedHeights[iCurContentAreaIndex] > - pContentAreaNode->GetMeasure(XFA_ATTRIBUTE_H) - .ToUnit(XFA_UNIT_Pt) + + pContentAreaNode->JSObject() + ->GetMeasure(XFA_Attribute::H) + .ToUnit(XFA_Unit::Pt) + XFA_LAYOUT_FLOAT_PERCISION) { bUsable = false; break; @@ -691,8 +711,7 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { if (bUsable) { CXFA_LayoutItem* pChildLayoutItem = pLastPageAreaLayoutItem->m_pFirstChild; - CXFA_Node* pContentAreaNode = - pNode->GetNodeItem(XFA_NODEITEM_FirstChild); + CXFA_Node* pContentAreaNode = pNode->GetFirstChild(); pLastPageAreaLayoutItem->m_pFormNode = pNode; while (pChildLayoutItem && pContentAreaNode) { if (pChildLayoutItem->m_pFormNode->GetElementType() != @@ -702,17 +721,15 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { } if (pContentAreaNode->GetElementType() != XFA_Element::ContentArea) { - pContentAreaNode = - pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling); + pContentAreaNode = pContentAreaNode->GetNextSibling(); continue; } pChildLayoutItem->m_pFormNode = pContentAreaNode; pChildLayoutItem = pChildLayoutItem->m_pNextSibling; - pContentAreaNode = - pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling); + pContentAreaNode = pContentAreaNode->GetNextSibling(); } - } else if (pNode->GetEnum(XFA_ATTRIBUTE_PagePosition) == - XFA_ATTRIBUTEENUM_Last) { + } else if (pNode->JSObject()->GetEnum(XFA_Attribute::PagePosition) == + XFA_AttributeEnum::Last) { CXFA_ContainerRecord* pRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pRecord, pNode); } @@ -723,28 +740,28 @@ void CXFA_LayoutPageMgr::FinishPaginatedPageSets() { } int32_t CXFA_LayoutPageMgr::GetPageCount() const { - return m_PageArray.GetSize(); + return pdfium::CollectionSize<int32_t>(m_PageArray); } CXFA_ContainerLayoutItem* CXFA_LayoutPageMgr::GetPage(int32_t index) const { - if (index < 0 || index >= m_PageArray.GetSize()) + if (!pdfium::IndexInBounds(m_PageArray, index)) return nullptr; return m_PageArray[index]; } int32_t CXFA_LayoutPageMgr::GetPageIndex( const CXFA_ContainerLayoutItem* pPage) const { - // FIXME: Find() method should take const. - return m_PageArray.Find(const_cast<CXFA_ContainerLayoutItem*>(pPage)); + auto it = std::find(m_PageArray.begin(), m_PageArray.end(), pPage); + return it != m_PageArray.end() ? it - m_PageArray.begin() : -1; } bool CXFA_LayoutPageMgr::RunBreak(XFA_Element eBreakType, - XFA_ATTRIBUTEENUM eTargetType, + XFA_AttributeEnum eTargetType, CXFA_Node* pTarget, bool bStartNew) { bool bRet = false; switch (eTargetType) { - case XFA_ATTRIBUTEENUM_ContentArea: + case XFA_AttributeEnum::ContentArea: if (pTarget && pTarget->GetElementType() != XFA_Element::ContentArea) pTarget = nullptr; if (!pTarget || @@ -754,13 +771,13 @@ bool CXFA_LayoutPageMgr::RunBreak(XFA_Element eBreakType, bStartNew) { CXFA_Node* pPageArea = nullptr; if (pTarget) - pPageArea = pTarget->GetNodeItem(XFA_NODEITEM_Parent); + pPageArea = pTarget->GetParent(); pPageArea = GetNextAvailPageArea(pPageArea, pTarget); bRet = !!pPageArea; } break; - case XFA_ATTRIBUTEENUM_PageArea: + case XFA_AttributeEnum::PageArea: if (pTarget && pTarget->GetElementType() != XFA_Element::PageArea) pTarget = nullptr; if (!pTarget || @@ -771,15 +788,15 @@ bool CXFA_LayoutPageMgr::RunBreak(XFA_Element eBreakType, bRet = !!pPageArea; } break; - case XFA_ATTRIBUTEENUM_PageOdd: + case XFA_AttributeEnum::PageOdd: if (pTarget && pTarget->GetElementType() != XFA_Element::PageArea) pTarget = nullptr; break; - case XFA_ATTRIBUTEENUM_PageEven: + case XFA_AttributeEnum::PageEven: if (pTarget && pTarget->GetElementType() != XFA_Element::PageArea) pTarget = nullptr; break; - case XFA_ATTRIBUTEENUM_Auto: + case XFA_AttributeEnum::Auto: default: break; } @@ -795,40 +812,41 @@ bool CXFA_LayoutPageMgr::ExecuteBreakBeforeOrAfter( switch (eType) { case XFA_Element::BreakBefore: case XFA_Element::BreakAfter: { - CFX_WideStringC wsBreakLeader, wsBreakTrailer; - CXFA_Node* pFormNode = pCurNode->GetNodeItem( - XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode); - CXFA_Node* pContainer = pFormNode->GetTemplateNode(); - bool bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0; - CXFA_Node* pScript = pCurNode->GetFirstChildByClass(XFA_Element::Script); - if (pScript && !XFA_LayoutPageMgr_RunBreakTestScript(pScript)) + WideString wsBreakLeader; + WideString wsBreakTrailer; + CXFA_Node* pFormNode = pCurNode->GetContainerParent(); + CXFA_Node* pContainer = pFormNode->GetTemplateNodeIfExists(); + bool bStartNew = + pCurNode->JSObject()->GetInteger(XFA_Attribute::StartNew) != 0; + CXFA_Script* pScript = + pCurNode->GetFirstChildByClass<CXFA_Script>(XFA_Element::Script); + if (pScript && !RunBreakTestScript(pScript)) return false; - CFX_WideStringC wsTarget = pCurNode->GetCData(XFA_ATTRIBUTE_Target); + WideString wsTarget = + pCurNode->JSObject()->GetCData(XFA_Attribute::Target); CXFA_Node* pTarget = ResolveBreakTarget(m_pTemplatePageSetRoot, true, wsTarget); - wsBreakTrailer = pCurNode->GetCData(XFA_ATTRIBUTE_Trailer); - wsBreakLeader = pCurNode->GetCData(XFA_ATTRIBUTE_Leader); + wsBreakTrailer = pCurNode->JSObject()->GetCData(XFA_Attribute::Trailer); + wsBreakLeader = pCurNode->JSObject()->GetCData(XFA_Attribute::Leader); pBreakLeaderTemplate = ResolveBreakTarget(pContainer, true, wsBreakLeader); pBreakTrailerTemplate = ResolveBreakTarget(pContainer, true, wsBreakTrailer); - if (RunBreak(eType, pCurNode->GetEnum(XFA_ATTRIBUTE_TargetType), pTarget, - bStartNew)) { + if (RunBreak(eType, + pCurNode->JSObject()->GetEnum(XFA_Attribute::TargetType), + pTarget, bStartNew)) { return true; } if (!m_ProposedContainerRecords.empty() && m_CurrentContainerRecordIter == m_ProposedContainerRecords.begin() && eType == XFA_Element::BreakBefore) { - CXFA_Node* pParentNode = pFormNode->GetNodeItem( - XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode); + CXFA_Node* pParentNode = pFormNode->GetContainerParent(); if (!pParentNode || - pFormNode != - pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild, - XFA_ObjectType::ContainerNode)) { + pFormNode != pParentNode->GetFirstContainerChild()) { break; } - pParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent); + pParentNode = pParentNode->GetParent(); if (!pParentNode || pParentNode->GetElementType() != XFA_Element::Form) { break; @@ -838,14 +856,15 @@ bool CXFA_LayoutPageMgr::ExecuteBreakBeforeOrAfter( break; } case XFA_Element::Break: { - bool bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0; - CFX_WideStringC wsTarget = pCurNode->GetCData( - bBefore ? XFA_ATTRIBUTE_BeforeTarget : XFA_ATTRIBUTE_AfterTarget); + bool bStartNew = + pCurNode->JSObject()->GetInteger(XFA_Attribute::StartNew) != 0; + WideString wsTarget = pCurNode->JSObject()->GetCData( + bBefore ? XFA_Attribute::BeforeTarget : XFA_Attribute::AfterTarget); CXFA_Node* pTarget = ResolveBreakTarget(m_pTemplatePageSetRoot, true, wsTarget); if (RunBreak(bBefore ? XFA_Element::BreakBefore : XFA_Element::BreakAfter, - pCurNode->GetEnum(bBefore ? XFA_ATTRIBUTE_Before - : XFA_ATTRIBUTE_After), + pCurNode->JSObject()->GetEnum( + bBefore ? XFA_Attribute::Before : XFA_Attribute::After), pTarget, bStartNew)) { return true; } @@ -865,15 +884,13 @@ bool CXFA_LayoutPageMgr::ProcessBreakBeforeOrAfter( bool& bCreatePage) { CXFA_Node* pLeaderTemplate = nullptr; CXFA_Node* pTrailerTemplate = nullptr; - CXFA_Node* pFormNode = pBreakNode->GetNodeItem(XFA_NODEITEM_Parent, - XFA_ObjectType::ContainerNode); + CXFA_Node* pFormNode = pBreakNode->GetContainerParent(); if (XFA_ItemLayoutProcessor_IsTakingSpace(pFormNode)) { bCreatePage = ExecuteBreakBeforeOrAfter(pBreakNode, bBefore, pLeaderTemplate, pTrailerTemplate); CXFA_Document* pDocument = pBreakNode->GetDocument(); CXFA_Node* pDataScope = nullptr; - pFormNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent, - XFA_ObjectType::ContainerNode); + pFormNode = pFormNode->GetContainerParent(); if (pLeaderTemplate) { if (!pDataScope) pDataScope = XFA_DataMerge_FindDataScope(pFormNode); @@ -902,8 +919,7 @@ bool CXFA_LayoutPageMgr::ProcessBookendLeaderOrTrailer( bool bLeader, CXFA_Node*& pBookendAppendNode) { CXFA_Node* pLeaderTemplate = nullptr; - CXFA_Node* pFormNode = pBookendNode->GetNodeItem( - XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode); + CXFA_Node* pFormNode = pBookendNode->GetContainerParent(); if (ResolveBookendLeaderOrTrailer(pBookendNode, bLeader, pLeaderTemplate)) { CXFA_Document* pDocument = pBookendNode->GetDocument(); CXFA_Node* pDataScope = nullptr; @@ -926,58 +942,51 @@ CXFA_Node* CXFA_LayoutPageMgr::BreakOverflow(CXFA_Node* pOverflowNode, CXFA_Node*& pTrailerTemplate, bool bCreatePage) { CXFA_Node* pContainer = - pOverflowNode - ->GetNodeItem(XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode) - ->GetTemplateNode(); + pOverflowNode->GetContainerParent()->GetTemplateNodeIfExists(); if (pOverflowNode->GetElementType() == XFA_Element::Break) { - CFX_WideStringC wsOverflowLeader; - CFX_WideStringC wsOverflowTarget; - CFX_WideStringC wsOverflowTrailer; - pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader); - pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer); - pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget); - if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() || - !wsOverflowTarget.IsEmpty()) { - if (!wsOverflowTarget.IsEmpty() && bCreatePage && - !m_bCreateOverFlowPage) { - CXFA_Node* pTarget = - ResolveBreakTarget(m_pTemplatePageSetRoot, true, wsOverflowTarget); - if (pTarget) { - m_bCreateOverFlowPage = true; - switch (pTarget->GetElementType()) { - case XFA_Element::PageArea: - RunBreak(XFA_Element::Overflow, XFA_ATTRIBUTEENUM_PageArea, - pTarget, true); - break; - case XFA_Element::ContentArea: - RunBreak(XFA_Element::Overflow, XFA_ATTRIBUTEENUM_ContentArea, - pTarget, true); - break; - default: - break; - } + WideString wsOverflowLeader = + pOverflowNode->JSObject()->GetCData(XFA_Attribute::OverflowLeader); + WideString wsOverflowTarget = + pOverflowNode->JSObject()->GetCData(XFA_Attribute::OverflowTarget); + WideString wsOverflowTrailer = + pOverflowNode->JSObject()->GetCData(XFA_Attribute::OverflowTrailer); + if (wsOverflowTarget.IsEmpty() && wsOverflowLeader.IsEmpty() && + wsOverflowTrailer.IsEmpty()) { + return nullptr; + } + + if (!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) { + CXFA_Node* pTarget = + ResolveBreakTarget(m_pTemplatePageSetRoot, true, wsOverflowTarget); + if (pTarget) { + m_bCreateOverFlowPage = true; + switch (pTarget->GetElementType()) { + case XFA_Element::PageArea: + RunBreak(XFA_Element::Overflow, XFA_AttributeEnum::PageArea, + pTarget, true); + break; + case XFA_Element::ContentArea: + RunBreak(XFA_Element::Overflow, XFA_AttributeEnum::ContentArea, + pTarget, true); + break; + default: + break; } } - if (!bCreatePage) { - pLeaderTemplate = - ResolveBreakTarget(pContainer, true, wsOverflowLeader); - pTrailerTemplate = - ResolveBreakTarget(pContainer, true, wsOverflowTrailer); - } - return pOverflowNode; } - return nullptr; + if (!bCreatePage) { + pLeaderTemplate = ResolveBreakTarget(pContainer, true, wsOverflowLeader); + pTrailerTemplate = + ResolveBreakTarget(pContainer, true, wsOverflowTrailer); + } + return pOverflowNode; } if (pOverflowNode->GetElementType() != XFA_Element::Overflow) return nullptr; - CFX_WideStringC wsOverflowLeader; - CFX_WideStringC wsOverflowTrailer; - CFX_WideStringC wsOverflowTarget; - pOverflowNode->TryCData(XFA_ATTRIBUTE_Leader, wsOverflowLeader); - pOverflowNode->TryCData(XFA_ATTRIBUTE_Trailer, wsOverflowTrailer); - pOverflowNode->TryCData(XFA_ATTRIBUTE_Target, wsOverflowTarget); + WideString wsOverflowTarget = + pOverflowNode->JSObject()->GetCData(XFA_Attribute::Target); if (!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) { CXFA_Node* pTarget = ResolveBreakTarget(m_pTemplatePageSetRoot, true, wsOverflowTarget); @@ -985,11 +994,11 @@ CXFA_Node* CXFA_LayoutPageMgr::BreakOverflow(CXFA_Node* pOverflowNode, m_bCreateOverFlowPage = true; switch (pTarget->GetElementType()) { case XFA_Element::PageArea: - RunBreak(XFA_Element::Overflow, XFA_ATTRIBUTEENUM_PageArea, pTarget, + RunBreak(XFA_Element::Overflow, XFA_AttributeEnum::PageArea, pTarget, true); break; case XFA_Element::ContentArea: - RunBreak(XFA_Element::Overflow, XFA_ATTRIBUTEENUM_ContentArea, + RunBreak(XFA_Element::Overflow, XFA_AttributeEnum::ContentArea, pTarget, true); break; default: @@ -998,8 +1007,12 @@ CXFA_Node* CXFA_LayoutPageMgr::BreakOverflow(CXFA_Node* pOverflowNode, } } if (!bCreatePage) { - pLeaderTemplate = ResolveBreakTarget(pContainer, true, wsOverflowLeader); - pTrailerTemplate = ResolveBreakTarget(pContainer, true, wsOverflowTrailer); + WideString wsLeader = + pOverflowNode->JSObject()->GetCData(XFA_Attribute::Leader); + WideString wsTrailer = + pOverflowNode->JSObject()->GetCData(XFA_Attribute::Trailer); + pLeaderTemplate = ResolveBreakTarget(pContainer, true, wsLeader); + pTrailerTemplate = ResolveBreakTarget(pContainer, true, wsTrailer); } return pOverflowNode; } @@ -1019,14 +1032,13 @@ bool CXFA_LayoutPageMgr::ProcessOverflow(CXFA_Node* pFormNode, pFormNode->GetElementType() == XFA_Element::Break) { bIsOverflowNode = true; } - for (CXFA_Node* pCurNode = - bIsOverflowNode ? pFormNode - : pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) { + for (CXFA_Node* pCurNode = bIsOverflowNode ? pFormNode + : pFormNode->GetFirstChild(); + pCurNode; pCurNode = pCurNode->GetNextSibling()) { if (BreakOverflow(pCurNode, pLeaderTemplate, pTrailerTemplate, bCreatePage)) { if (bIsOverflowNode) - pFormNode = pCurNode->GetNodeItem(XFA_NODEITEM_Parent); + pFormNode = pCurNode->GetParent(); CXFA_Document* pDocument = pCurNode->GetDocument(); CXFA_Node* pDataScope = nullptr; @@ -1061,27 +1073,22 @@ bool CXFA_LayoutPageMgr::ResolveBookendLeaderOrTrailer( CXFA_Node* pBookendNode, bool bLeader, CXFA_Node*& pBookendAppendTemplate) { - CFX_WideStringC wsBookendLeader; CXFA_Node* pContainer = - pBookendNode - ->GetNodeItem(XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode) - ->GetTemplateNode(); + pBookendNode->GetContainerParent()->GetTemplateNodeIfExists(); if (pBookendNode->GetElementType() == XFA_Element::Break) { - pBookendNode->TryCData( - bLeader ? XFA_ATTRIBUTE_BookendLeader : XFA_ATTRIBUTE_BookendTrailer, - wsBookendLeader); - if (!wsBookendLeader.IsEmpty()) { - pBookendAppendTemplate = - ResolveBreakTarget(pContainer, false, wsBookendLeader); + WideString leader = pBookendNode->JSObject()->GetCData( + bLeader ? XFA_Attribute::BookendLeader : XFA_Attribute::BookendTrailer); + if (!leader.IsEmpty()) { + pBookendAppendTemplate = ResolveBreakTarget(pContainer, false, leader); return true; } return false; - } else if (pBookendNode->GetElementType() == XFA_Element::Bookend) { - pBookendNode->TryCData( - bLeader ? XFA_ATTRIBUTE_Leader : XFA_ATTRIBUTE_Trailer, - wsBookendLeader); - pBookendAppendTemplate = - ResolveBreakTarget(pContainer, true, wsBookendLeader); + } + + if (pBookendNode->GetElementType() == XFA_Element::Bookend) { + WideString leader = pBookendNode->JSObject()->GetCData( + bLeader ? XFA_Attribute::Leader : XFA_Attribute::Trailer); + pBookendAppendTemplate = ResolveBreakTarget(pContainer, true, leader); return true; } return false; @@ -1101,10 +1108,10 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet(CXFA_Node* pPageSet, pTargetPageArea, pTargetContentArea, bNewPage, bQuery); } - XFA_ATTRIBUTEENUM ePreferredPosition = + XFA_AttributeEnum ePreferredPosition = m_CurrentContainerRecordIter != m_ProposedContainerRecords.end() - ? XFA_ATTRIBUTEENUM_Rest - : XFA_ATTRIBUTEENUM_First; + ? XFA_AttributeEnum::Rest + : XFA_AttributeEnum::First; return FindPageAreaFromPageSet_SimplexDuplex( pPageSet, pStartChild, pTargetPageArea, pTargetContentArea, bNewPage, bQuery, ePreferredPosition); @@ -1123,21 +1130,26 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet_Ordered( if (it != m_pPageSetMap.end()) iPageSetCount = it->second; int32_t iMax = -1; - CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_Element::Occur); - if (pOccurNode) - pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, false); + CXFA_Node* pOccurNode = + pPageSet->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); + if (pOccurNode) { + Optional<int32_t> ret = + pOccurNode->JSObject()->TryInteger(XFA_Attribute::Max, false); + if (ret) + iMax = *ret; + } if (iMax >= 0 && iMax <= iPageSetCount) return false; } + bool bRes = false; CXFA_Node* pCurrentNode = - pStartChild ? pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling) - : pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pCurrentNode; - pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + pStartChild ? pStartChild->GetNextSibling() : pPageSet->GetFirstChild(); + for (; pCurrentNode; pCurrentNode = pCurrentNode->GetNextSibling()) { if (pCurrentNode->GetElementType() == XFA_Element::PageArea) { if ((pTargetPageArea == pCurrentNode || !pTargetPageArea)) { - if (!pCurrentNode->GetFirstChildByClass(XFA_Element::ContentArea)) { + if (!pCurrentNode->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea)) { if (pTargetPageArea == pCurrentNode) { CreateMinPageRecord(pCurrentNode, true); pTargetPageArea = nullptr; @@ -1150,7 +1162,8 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet_Ordered( AddPageAreaLayoutItem(pNewRecord, pCurrentNode); if (!pTargetContentArea) { pTargetContentArea = - pCurrentNode->GetFirstChildByClass(XFA_Element::ContentArea); + pCurrentNode->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea); } AddContentAreaLayoutItem(pNewRecord, pTargetContentArea); } @@ -1184,53 +1197,54 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex( CXFA_Node* pTargetContentArea, bool bNewPage, bool bQuery, - XFA_ATTRIBUTEENUM ePreferredPosition) { - const XFA_ATTRIBUTEENUM eFallbackPosition = XFA_ATTRIBUTEENUM_Any; + XFA_AttributeEnum ePreferredPosition) { + const XFA_AttributeEnum eFallbackPosition = XFA_AttributeEnum::Any; CXFA_Node* pPreferredPageArea = nullptr; CXFA_Node* pFallbackPageArea = nullptr; CXFA_Node* pCurrentNode = nullptr; if (!pStartChild || pStartChild->GetElementType() == XFA_Element::PageArea) - pCurrentNode = pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); + pCurrentNode = pPageSet->GetFirstChild(); else - pCurrentNode = pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling); + pCurrentNode = pStartChild->GetNextSibling(); - for (; pCurrentNode; - pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (; pCurrentNode; pCurrentNode = pCurrentNode->GetNextSibling()) { if (pCurrentNode->GetElementType() == XFA_Element::PageArea) { - if (!MatchPageAreaOddOrEven(pCurrentNode, false)) + if (!MatchPageAreaOddOrEven(pCurrentNode)) continue; - XFA_ATTRIBUTEENUM eCurPagePosition = - pCurrentNode->GetEnum(XFA_ATTRIBUTE_PagePosition); - if (ePreferredPosition == XFA_ATTRIBUTEENUM_Last) { + XFA_AttributeEnum eCurPagePosition = + pCurrentNode->JSObject()->GetEnum(XFA_Attribute::PagePosition); + if (ePreferredPosition == XFA_AttributeEnum::Last) { if (eCurPagePosition != ePreferredPosition) continue; - if (m_ePageSetMode == XFA_ATTRIBUTEENUM_SimplexPaginated || - pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) == - XFA_ATTRIBUTEENUM_Any) { + if (m_ePageSetMode == XFA_AttributeEnum::SimplexPaginated || + pCurrentNode->JSObject()->GetEnum(XFA_Attribute::OddOrEven) == + XFA_AttributeEnum::Any) { pPreferredPageArea = pCurrentNode; break; } CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); - AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass( - XFA_Element::ContentArea)); + AddContentAreaLayoutItem( + pNewRecord, pCurrentNode->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea)); pPreferredPageArea = pCurrentNode; return false; } - if (ePreferredPosition == XFA_ATTRIBUTEENUM_Only) { + if (ePreferredPosition == XFA_AttributeEnum::Only) { if (eCurPagePosition != ePreferredPosition) continue; - if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated || - pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) == - XFA_ATTRIBUTEENUM_Any) { + if (m_ePageSetMode != XFA_AttributeEnum::DuplexPaginated || + pCurrentNode->JSObject()->GetEnum(XFA_Attribute::OddOrEven) == + XFA_AttributeEnum::Any) { pPreferredPageArea = pCurrentNode; break; } return false; } if ((pTargetPageArea == pCurrentNode || !pTargetPageArea)) { - if (!pCurrentNode->GetFirstChildByClass(XFA_Element::ContentArea)) { + if (!pCurrentNode->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea)) { if (pTargetPageArea == pCurrentNode) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); @@ -1238,21 +1252,21 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex( } continue; } - if ((ePreferredPosition == XFA_ATTRIBUTEENUM_Rest && - eCurPagePosition == XFA_ATTRIBUTEENUM_Any) || + if ((ePreferredPosition == XFA_AttributeEnum::Rest && + eCurPagePosition == XFA_AttributeEnum::Any) || eCurPagePosition == ePreferredPosition) { pPreferredPageArea = pCurrentNode; break; - } else if (eCurPagePosition == eFallbackPosition && - !pFallbackPageArea) { + } + if (eCurPagePosition == eFallbackPosition && !pFallbackPageArea) { pFallbackPageArea = pCurrentNode; } - } else if (pTargetPageArea && - !MatchPageAreaOddOrEven(pTargetPageArea, false)) { + } else if (pTargetPageArea && !MatchPageAreaOddOrEven(pTargetPageArea)) { CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurrentNode); - AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass( - XFA_Element::ContentArea)); + AddContentAreaLayoutItem( + pNewRecord, pCurrentNode->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea)); } } else if (pCurrentNode->GetElementType() == XFA_Element::PageSet) { if (FindPageAreaFromPageSet_SimplexDuplex( @@ -1276,8 +1290,8 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex( CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); AddPageAreaLayoutItem(pNewRecord, pCurPageArea); if (!pTargetContentArea) { - pTargetContentArea = - pCurPageArea->GetFirstChildByClass(XFA_Element::ContentArea); + pTargetContentArea = pCurPageArea->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea); } AddContentAreaLayoutItem(pNewRecord, pTargetContentArea); } @@ -1285,23 +1299,17 @@ bool CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex( return true; } -bool CXFA_LayoutPageMgr::MatchPageAreaOddOrEven(CXFA_Node* pPageArea, - bool bLastMatch) { - if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated) +bool CXFA_LayoutPageMgr::MatchPageAreaOddOrEven(CXFA_Node* pPageArea) { + if (m_ePageSetMode != XFA_AttributeEnum::DuplexPaginated) return true; - XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any; - pPageArea->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven); - if (eOddOrEven != XFA_ATTRIBUTEENUM_Any) { - int32_t iPageCount = GetPageCount(); - if (bLastMatch) { - return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 1 - : iPageCount % 2 == 0; - } - return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 0 - : iPageCount % 2 == 1; - } - return true; + Optional<XFA_AttributeEnum> ret = + pPageArea->JSObject()->TryEnum(XFA_Attribute::OddOrEven, true); + if (!ret || *ret == XFA_AttributeEnum::Any) + return true; + + int32_t iPageLast = GetPageCount() % 2; + return *ret == XFA_AttributeEnum::Odd ? iPageLast == 0 : iPageLast == 1; } CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea( @@ -1323,9 +1331,13 @@ CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea( if (IsPageSetRootOrderedOccurrence()) { int32_t iMax = -1; CXFA_Node* pOccurNode = - m_pCurPageArea->GetFirstChildByClass(XFA_Element::Occur); - if (pOccurNode) - pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, false); + m_pCurPageArea->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); + if (pOccurNode) { + Optional<int32_t> ret = + pOccurNode->JSObject()->TryInteger(XFA_Attribute::Max, false); + if (ret) + iMax = *ret; + } if ((iMax < 0 || m_nCurPageCount < iMax)) { if (!bQuery) { CXFA_ContainerRecord* pNewRecord = @@ -1333,7 +1345,8 @@ CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea( AddPageAreaLayoutItem(pNewRecord, m_pCurPageArea); if (!pTargetContentArea) { pTargetContentArea = - m_pCurPageArea->GetFirstChildByClass(XFA_Element::ContentArea); + m_pCurPageArea->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea); } AddContentAreaLayoutItem(pNewRecord, pTargetContentArea); } @@ -1345,13 +1358,13 @@ CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea( if (!bQuery && IsPageSetRootOrderedOccurrence()) CreateMinPageRecord(m_pCurPageArea, false, true); - if (FindPageAreaFromPageSet(m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent), - m_pCurPageArea, pTargetPageArea, - pTargetContentArea, bNewPage, bQuery)) { + if (FindPageAreaFromPageSet(m_pCurPageArea->GetParent(), m_pCurPageArea, + pTargetPageArea, pTargetContentArea, bNewPage, + bQuery)) { return m_pCurPageArea; } - CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pPageSet = m_pCurPageArea->GetParent(); while (true) { if (FindPageAreaFromPageSet(pPageSet, nullptr, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) { @@ -1366,7 +1379,7 @@ CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea( if (pPageSet == m_pTemplatePageSetRoot) break; - pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent); + pPageSet = pPageSet->GetParent(); } return nullptr; } @@ -1375,12 +1388,12 @@ bool CXFA_LayoutPageMgr::GetNextContentArea(CXFA_Node* pContentArea) { CXFA_Node* pCurContentNode = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode; if (!pContentArea) { - pContentArea = - pCurContentNode->GetNextSameClassSibling(XFA_Element::ContentArea); + pContentArea = pCurContentNode->GetNextSameClassSibling<CXFA_ContentArea>( + XFA_Element::ContentArea); if (!pContentArea) return false; } else { - if (pContentArea->GetNodeItem(XFA_NODEITEM_Parent) != m_pCurPageArea) + if (pContentArea->GetParent() != m_pCurPageArea) return false; CXFA_ContainerLayoutItem* pContentAreaLayout = nullptr; @@ -1411,9 +1424,9 @@ void CXFA_LayoutPageMgr::InitPageSetMap() { for (CXFA_Node* pPageSetNode = sIterator.GetCurrent(); pPageSetNode; pPageSetNode = sIterator.MoveToNext()) { if (pPageSetNode->GetElementType() == XFA_Element::PageSet) { - XFA_ATTRIBUTEENUM eRelation = - pPageSetNode->GetEnum(XFA_ATTRIBUTE_Relation); - if (eRelation == XFA_ATTRIBUTEENUM_OrderedOccurrence) + XFA_AttributeEnum eRelation = + pPageSetNode->JSObject()->GetEnum(XFA_Attribute::Relation); + if (eRelation == XFA_AttributeEnum::OrderedOccurrence) m_pPageSetMap[pPageSetNode] = 0; } } @@ -1425,24 +1438,32 @@ int32_t CXFA_LayoutPageMgr::CreateMinPageRecord(CXFA_Node* pPageArea, if (!pPageArea) return 0; - CXFA_Node* pOccurNode = pPageArea->GetFirstChildByClass(XFA_Element::Occur); int32_t iMin = 0; - if ((pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, false)) || - bTargetPageArea) { - CXFA_Node* pContentArea = - pPageArea->GetFirstChildByClass(XFA_Element::ContentArea); - if (iMin < 1 && bTargetPageArea && !pContentArea) - iMin = 1; - - int32_t i = 0; - if (bCreateLast) - i = m_nCurPageCount; - - for (; i < iMin; i++) { - CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); - AddPageAreaLayoutItem(pNewRecord, pPageArea); - AddContentAreaLayoutItem(pNewRecord, pContentArea); - } + Optional<int32_t> ret; + CXFA_Node* pOccurNode = + pPageArea->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); + if (pOccurNode) { + ret = pOccurNode->JSObject()->TryInteger(XFA_Attribute::Min, false); + if (ret) + iMin = *ret; + } + + if (!ret && !bTargetPageArea) + return iMin; + + CXFA_Node* pContentArea = pPageArea->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea); + if (iMin < 1 && bTargetPageArea && !pContentArea) + iMin = 1; + + int32_t i = 0; + if (bCreateLast) + i = m_nCurPageCount; + + for (; i < iMin; i++) { + CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(); + AddPageAreaLayoutItem(pNewRecord, pPageArea); + AddContentAreaLayoutItem(pNewRecord, pContentArea); } return iMin; } @@ -1460,36 +1481,34 @@ void CXFA_LayoutPageMgr::CreateMinPageSetRecord(CXFA_Node* pPageSet, if (bCreateAll) iCurSetCount = 0; - CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_Element::Occur); - int32_t iMin = 0; - if (pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, false)) { - if (iCurSetCount < iMin) { - for (int32_t i = 0; i < iMin - iCurSetCount; i++) { - for (CXFA_Node* pCurrentPageNode = - pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); - pCurrentPageNode; pCurrentPageNode = pCurrentPageNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { - if (pCurrentPageNode->GetElementType() == XFA_Element::PageArea) { - CreateMinPageRecord(pCurrentPageNode, false); - } else if (pCurrentPageNode->GetElementType() == - XFA_Element::PageSet) { - CreateMinPageSetRecord(pCurrentPageNode, true); - } - } - } - m_pPageSetMap[pPageSet] = iMin; + CXFA_Node* pOccurNode = + pPageSet->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); + if (!pOccurNode) + return; + + Optional<int32_t> iMin = + pOccurNode->JSObject()->TryInteger(XFA_Attribute::Min, false); + if (!iMin || iCurSetCount >= *iMin) + return; + + for (int32_t i = 0; i < *iMin - iCurSetCount; i++) { + for (CXFA_Node* node = pPageSet->GetFirstChild(); node; + node = node->GetNextSibling()) { + if (node->GetElementType() == XFA_Element::PageArea) + CreateMinPageRecord(node, false); + else if (node->GetElementType() == XFA_Element::PageSet) + CreateMinPageSetRecord(node, true); } } + m_pPageSetMap[pPageSet] = *iMin; } void CXFA_LayoutPageMgr::CreateNextMinRecord(CXFA_Node* pRecordNode) { if (!pRecordNode) return; - for (CXFA_Node* pCurrentNode = - pRecordNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pCurrentNode; - pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pCurrentNode = pRecordNode->GetNextSibling(); pCurrentNode; + pCurrentNode = pCurrentNode->GetNextSibling()) { if (pCurrentNode->GetElementType() == XFA_Element::PageArea) CreateMinPageRecord(pCurrentNode, false); else if (pCurrentNode->GetElementType() == XFA_Element::PageSet) @@ -1500,35 +1519,43 @@ void CXFA_LayoutPageMgr::CreateNextMinRecord(CXFA_Node* pRecordNode) { void CXFA_LayoutPageMgr::ProcessLastPageSet() { CreateMinPageRecord(m_pCurPageArea, false, true); CreateNextMinRecord(m_pCurPageArea); - CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pPageSet = m_pCurPageArea->GetParent(); while (true) { CreateMinPageSetRecord(pPageSet); if (pPageSet == m_pTemplatePageSetRoot) break; CreateNextMinRecord(pPageSet); - pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent); + pPageSet = pPageSet->GetParent(); } } -bool CXFA_LayoutPageMgr::GetNextAvailContentHeight(FX_FLOAT fChildHeight) { +bool CXFA_LayoutPageMgr::GetNextAvailContentHeight(float fChildHeight) { CXFA_Node* pCurContentNode = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode; if (!pCurContentNode) return false; - pCurContentNode = - pCurContentNode->GetNextSameClassSibling(XFA_Element::ContentArea); + pCurContentNode = pCurContentNode->GetNextSameClassSibling<CXFA_ContentArea>( + XFA_Element::ContentArea); if (pCurContentNode) { - FX_FLOAT fNextContentHeight = - pCurContentNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); + float fNextContentHeight = pCurContentNode->JSObject() + ->GetMeasure(XFA_Attribute::H) + .ToUnit(XFA_Unit::Pt); return fNextContentHeight > fChildHeight; } CXFA_Node* pPageNode = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode; - CXFA_Node* pOccurNode = pPageNode->GetFirstChildByClass(XFA_Element::Occur); + CXFA_Node* pOccurNode = + pPageNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); int32_t iMax = 0; - if (pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, false)) { + Optional<int32_t> ret; + if (pOccurNode) { + ret = pOccurNode->JSObject()->TryInteger(XFA_Attribute::Max, false); + if (ret) + iMax = *ret; + } + if (ret) { if (m_nCurPageCount == iMax) { CXFA_Node* pSrcPage = m_pCurPageArea; int32_t nSrcPageCount = m_nCurPageCount; @@ -1547,10 +1574,12 @@ bool CXFA_LayoutPageMgr::GetNextAvailContentHeight(FX_FLOAT fChildHeight) { } if (pNextPage) { CXFA_Node* pContentArea = - pNextPage->GetFirstChildByClass(XFA_Element::ContentArea); + pNextPage->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea); if (pContentArea) { - FX_FLOAT fNextContentHeight = - pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); + float fNextContentHeight = pContentArea->JSObject() + ->GetMeasure(XFA_Attribute::H) + .ToUnit(XFA_Unit::Pt); if (fNextContentHeight > fChildHeight) return true; } @@ -1559,10 +1588,11 @@ bool CXFA_LayoutPageMgr::GetNextAvailContentHeight(FX_FLOAT fChildHeight) { } } - CXFA_Node* pContentArea = - pPageNode->GetFirstChildByClass(XFA_Element::ContentArea); - FX_FLOAT fNextContentHeight = - pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt); + CXFA_Node* pContentArea = pPageNode->GetFirstChildByClass<CXFA_ContentArea>( + XFA_Element::ContentArea); + float fNextContentHeight = pContentArea->JSObject() + ->GetMeasure(XFA_Attribute::H) + .ToUnit(XFA_Unit::Pt); if (fNextContentHeight < XFA_LAYOUT_FLOAT_PERCISION) return true; if (fNextContentHeight > fChildHeight) @@ -1632,18 +1662,17 @@ void CXFA_LayoutPageMgr::SaveLayoutItem(CXFA_LayoutItem* pParentLayoutItem) { } } -CXFA_Node* CXFA_LayoutPageMgr::QueryOverflow( - CXFA_Node* pFormNode, - CXFA_LayoutContext* pLayoutContext) { - for (CXFA_Node* pCurNode = pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) { +CXFA_Node* CXFA_LayoutPageMgr::QueryOverflow(CXFA_Node* pFormNode) { + for (CXFA_Node* pCurNode = pFormNode->GetFirstChild(); pCurNode; + pCurNode = pCurNode->GetNextSibling()) { if (pCurNode->GetElementType() == XFA_Element::Break) { - CFX_WideStringC wsOverflowLeader; - CFX_WideStringC wsOverflowTarget; - CFX_WideStringC wsOverflowTrailer; - pCurNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader); - pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer); - pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget); + WideString wsOverflowLeader = + pCurNode->JSObject()->GetCData(XFA_Attribute::OverflowLeader); + WideString wsOverflowTarget = + pCurNode->JSObject()->GetCData(XFA_Attribute::OverflowTarget); + WideString wsOverflowTrailer = + pCurNode->JSObject()->GetCData(XFA_Attribute::OverflowTrailer); + if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() || !wsOverflowTarget.IsEmpty()) { return pCurNode; @@ -1661,22 +1690,19 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { CXFA_FFNotify* pNotify = pDocument->GetNotify(); CXFA_LayoutProcessor* pDocLayout = pDocument->GetDocLayout(); CXFA_ContainerLayoutItem* pRootLayout = GetRootLayoutItem(); - { - for (int32_t iIndex = 0; iIndex < pDocument->m_pPendingPageSet.GetSize(); - iIndex++) { - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> - sIterator(pDocument->m_pPendingPageSet.GetAt(iIndex)); - for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; - pNode = sIterator.MoveToNext()) { - if (pNode->IsContainerNode()) { - CXFA_Node* pBindNode = pNode->GetBindData(); - if (pBindNode) { - pBindNode->RemoveBindItem(pNode); - pNode->SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); - } + for (CXFA_Node* pPageNode : pDocument->m_pPendingPageSet) { + CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> + sIterator(pPageNode); + for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; + pNode = sIterator.MoveToNext()) { + if (pNode->IsContainerNode()) { + CXFA_Node* pBindNode = pNode->GetBindData(); + if (pBindNode) { + pBindNode->RemoveBindItem(pNode); + pNode->SetBindingNode(nullptr); } - pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); } + pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); } } @@ -1691,30 +1717,31 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { CXFA_ContainerLayoutItem* pRootPageSetContainerItem = iterator.GetCurrent(); ASSERT(pRootPageSetContainerItem->m_pFormNode->GetElementType() == XFA_Element::PageSet); - if (iIndex < pDocument->m_pPendingPageSet.GetSize()) { - pPendingPageSet = pDocument->m_pPendingPageSet.GetAt(iIndex); + if (iIndex < + pdfium::CollectionSize<int32_t>(pDocument->m_pPendingPageSet)) { + pPendingPageSet = pDocument->m_pPendingPageSet[iIndex]; iIndex++; } if (!pPendingPageSet) { - if (pRootPageSetContainerItem->m_pFormNode->GetPacketID() == - XFA_XDPPACKET_Template) { + if (pRootPageSetContainerItem->m_pFormNode->GetPacketType() == + XFA_PacketType::Template) { pPendingPageSet = pRootPageSetContainerItem->m_pFormNode->CloneTemplateToForm(false); } else { pPendingPageSet = pRootPageSetContainerItem->m_pFormNode; } } - if (pRootPageSetContainerItem->m_pFormNode->GetUserData( - XFA_LAYOUTITEMKEY) == pRootPageSetContainerItem) { - pRootPageSetContainerItem->m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, - nullptr); + if (pRootPageSetContainerItem->m_pFormNode->JSObject()->GetLayoutItem() == + pRootPageSetContainerItem) { + pRootPageSetContainerItem->m_pFormNode->JSObject()->SetLayoutItem( + nullptr); } pRootPageSetContainerItem->m_pFormNode = pPendingPageSet; pPendingPageSet->ClearFlag(XFA_NodeFlag_UnusedNode); for (CXFA_ContainerLayoutItem* pContainerItem = iterator.MoveToNext(); pContainerItem; pContainerItem = iterator.MoveToNext()) { CXFA_Node* pNode = pContainerItem->m_pFormNode; - if (pNode->GetPacketID() != XFA_XDPPACKET_Template) + if (pNode->GetPacketType() != XFA_PacketType::Template) continue; switch (pNode->GetElementType()) { @@ -1726,18 +1753,16 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { break; } case XFA_Element::PageArea: { - CXFA_ContainerLayoutItem* pFormLayout = pContainerItem; + CXFA_LayoutItem* pFormLayout = pContainerItem; CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode; bool bIsExistForm = true; for (int32_t iLevel = 0; iLevel < 3; iLevel++) { - pFormLayout = static_cast<CXFA_ContainerLayoutItem*>( - pFormLayout->m_pFirstChild); + pFormLayout = pFormLayout->m_pFirstChild; if (iLevel == 2) { while (pFormLayout && !XFA_ItemLayoutProcessor_IsTakingSpace( pFormLayout->m_pFormNode)) { - pFormLayout = static_cast<CXFA_ContainerLayoutItem*>( - pFormLayout->m_pNextSibling); + pFormLayout = pFormLayout->m_pNextSibling; } } if (!pFormLayout) { @@ -1756,8 +1781,8 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { for (CXFA_Node* pIter = sIterator.GetCurrent(); pIter; pIter = sIterator.MoveToNext()) { if (pIter->GetElementType() != XFA_Element::ContentArea) { - CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>( - pIter->GetUserData(XFA_LAYOUTITEMKEY)); + CXFA_LayoutItem* pLayoutItem = + pIter->JSObject()->GetLayoutItem(); if (pLayoutItem) { pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem); delete pLayoutItem; @@ -1765,7 +1790,7 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { } } if (pExistingNode) { - pParentNode->RemoveChild(pExistingNode); + pParentNode->RemoveChild(pExistingNode, true); } } pContainerItem->m_pOldSubform = pNewSubform; @@ -1778,11 +1803,10 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { } case XFA_Element::ContentArea: { CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode; - for (CXFA_Node* pChildNode = - pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pChildNode; - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pChildNode->GetTemplateNode() != pContainerItem->m_pFormNode) { + for (CXFA_Node* pChildNode = pParentNode->GetFirstChild(); pChildNode; + pChildNode = pChildNode->GetNextSibling()) { + if (pChildNode->GetTemplateNodeIfExists() != + pContainerItem->m_pFormNode) { continue; } pContainerItem->m_pFormNode = pChildNode; @@ -1794,12 +1818,12 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { break; } } - if (!pPendingPageSet->GetNodeItem(XFA_NODEITEM_Parent)) { + if (!pPendingPageSet->GetParent()) { CXFA_Node* pFormToplevelSubform = pDocument->GetXFAObject(XFA_HASHCODE_Form) ->AsNode() - ->GetFirstChildByClass(XFA_Element::Subform); - pFormToplevelSubform->InsertChild(pPendingPageSet); + ->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); + pFormToplevelSubform->InsertChild(pPendingPageSet, nullptr); } pDocument->DataMerge_UpdateBindingRelations(pPendingPageSet); pPendingPageSet->SetFlag(XFA_NodeFlag_Initialized, true); @@ -1808,7 +1832,7 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { CXFA_Node* pPageSet = GetRootLayoutItem()->m_pFormNode; while (pPageSet) { CXFA_Node* pNextPageSet = - pPageSet->GetNextSameClassSibling(XFA_Element::PageSet); + pPageSet->GetNextSameClassSibling<CXFA_PageSet>(XFA_Element::PageSet); CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pPageSet); CXFA_Node* pNode = sIterator.GetCurrent(); @@ -1820,23 +1844,22 @@ void CXFA_LayoutPageMgr::MergePageSetContents() { CXFA_ContainerIterator iteChild(pNode); CXFA_Node* pChildNode = iteChild.MoveToNext(); for (; pChildNode; pChildNode = iteChild.MoveToNext()) { - CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>( - pChildNode->GetUserData(XFA_LAYOUTITEMKEY)); + CXFA_LayoutItem* pLayoutItem = + pChildNode->JSObject()->GetLayoutItem(); if (pLayoutItem) { pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem); delete pLayoutItem; } } } else if (eType != XFA_Element::ContentArea) { - CXFA_LayoutItem* pLayoutItem = static_cast<CXFA_LayoutItem*>( - pNode->GetUserData(XFA_LAYOUTITEMKEY)); + CXFA_LayoutItem* pLayoutItem = pNode->JSObject()->GetLayoutItem(); if (pLayoutItem) { pNotify->OnLayoutItemRemoving(pDocLayout, pLayoutItem); delete pLayoutItem; } } CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext(); - pNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pNode); + pNode->GetParent()->RemoveChild(pNode, true); pNode = pNext; } else { pNode->ClearFlag(XFA_NodeFlag_UnusedNode); @@ -1907,9 +1930,12 @@ void CXFA_LayoutPageMgr::SyncLayoutData() { pChildLayoutItem = iterator.MoveToNext(); continue; } - bool bVisible = - (pContentItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence) == - XFA_ATTRIBUTEENUM_Visible); + + XFA_AttributeEnum presence = + pContentItem->m_pFormNode->JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible); + bool bVisible = presence == XFA_AttributeEnum::Visible; uint32_t dwRelevantChild = GetRelevant(pContentItem->m_pFormNode, dwRelevant); SyncContainer(pNotify, m_pLayoutProcessor, pContentItem, @@ -1924,10 +1950,10 @@ void CXFA_LayoutPageMgr::SyncLayoutData() { } } - int32_t nPage = m_PageArray.GetSize(); + int32_t nPage = pdfium::CollectionSize<int32_t>(m_PageArray); for (int32_t i = nPage - 1; i >= m_nAvailPages; i--) { CXFA_ContainerLayoutItem* pPage = m_PageArray[i]; - m_PageArray.RemoveAt(i); + m_PageArray.erase(m_PageArray.begin() + i); pNotify->OnPageEvent(pPage, XFA_PAGEVIEWEVENT_PostRemoved); delete pPage; } @@ -1948,7 +1974,7 @@ void XFA_ReleaseLayoutItem_NoPageArea(CXFA_LayoutItem* pLayoutItem) { void CXFA_LayoutPageMgr::PrepareLayout() { m_pPageSetCurRoot = nullptr; - m_ePageSetMode = XFA_ATTRIBUTEENUM_OrderedOccurrence; + m_ePageSetMode = XFA_AttributeEnum::OrderedOccurrence; m_nAvailPages = 0; ClearData(); if (!m_pPageSetLayoutItemRoot) @@ -1956,22 +1982,22 @@ void CXFA_LayoutPageMgr::PrepareLayout() { CXFA_ContainerLayoutItem* pRootLayoutItem = m_pPageSetLayoutItemRoot; if (pRootLayoutItem && - pRootLayoutItem->m_pFormNode->GetPacketID() == XFA_XDPPACKET_Form) { + pRootLayoutItem->m_pFormNode->GetPacketType() == XFA_PacketType::Form) { CXFA_Node* pPageSetFormNode = pRootLayoutItem->m_pFormNode; - pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.RemoveAll(); + pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.clear(); if (pPageSetFormNode->HasRemovedChildren()) { XFA_ReleaseLayoutItem(pRootLayoutItem); m_pPageSetLayoutItemRoot = nullptr; pRootLayoutItem = nullptr; pPageSetFormNode = nullptr; - m_PageArray.RemoveAll(); + m_PageArray.clear(); } while (pPageSetFormNode) { CXFA_Node* pNextPageSet = - pPageSetFormNode->GetNextSameClassSibling(XFA_Element::PageSet); - pPageSetFormNode->GetNodeItem(XFA_NODEITEM_Parent) - ->RemoveChild(pPageSetFormNode, false); - pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.Add( + pPageSetFormNode->GetNextSameClassSibling<CXFA_PageSet>( + XFA_Element::PageSet); + pPageSetFormNode->GetParent()->RemoveChild(pPageSetFormNode, false); + pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.push_back( pPageSetFormNode); pPageSetFormNode = pNextPageSet; } diff --git a/xfa/fxfa/parser/cxfa_layoutpagemgr.h b/xfa/fxfa/parser/cxfa_layoutpagemgr.h index 3c8e7f9d1e00934c2572a7148c9e9df7f2a4ddf1..42fa4e6cd909acc856acb1061edd19799182be59 100644 --- a/xfa/fxfa/parser/cxfa_layoutpagemgr.h +++ b/xfa/fxfa/parser/cxfa_layoutpagemgr.h @@ -10,11 +10,13 @@ #include <iterator> #include <list> #include <map> +#include <vector> -#include "xfa/fxfa/parser/xfa_layout_itemlayout.h" +#include "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h" class CXFA_ContainerRecord; class CXFA_LayoutItem; +class CXFA_Node; class CXFA_LayoutPageMgr { public: @@ -23,8 +25,8 @@ class CXFA_LayoutPageMgr { bool InitLayoutPage(CXFA_Node* pFormNode); bool PrepareFirstPage(CXFA_Node* pRootSubform); - FX_FLOAT GetAvailHeight(); - bool GetNextAvailContentHeight(FX_FLOAT fChildHeight); + float GetAvailHeight(); + bool GetNextAvailContentHeight(float fChildHeight); void SubmitContentItem(CXFA_ContentLayoutItem* pContentLayoutItem, XFA_ItemLayoutProcessorResult eStatus); void FinishPaginatedPageSets(); @@ -45,13 +47,12 @@ class CXFA_LayoutPageMgr { CXFA_Node*& pTrailerNode, bool bDataMerge = false, bool bCreatePage = true); - CXFA_Node* QueryOverflow(CXFA_Node* pFormNode, - CXFA_LayoutContext* pLayoutContext = nullptr); + CXFA_Node* QueryOverflow(CXFA_Node* pFormNode); bool ProcessBookendLeaderOrTrailer(CXFA_Node* pBookendNode, bool bLeader, CXFA_Node*& pBookendAppendNode); - protected: + private: bool AppendNewPage(bool bFirstTemPage = false); void ReorderPendingLayoutRecordToTail(CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord); @@ -71,7 +72,7 @@ class CXFA_LayoutPageMgr { void AddContentAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pContentArea); bool RunBreak(XFA_Element eBreakType, - XFA_ATTRIBUTEENUM eTargetType, + XFA_AttributeEnum eTargetType, CXFA_Node* pTarget, bool bStartNew); CXFA_Node* BreakOverflow(CXFA_Node* pOverflowNode, @@ -110,8 +111,8 @@ class CXFA_LayoutPageMgr { CXFA_Node* pTargetContentArea = nullptr, bool bNewPage = false, bool bQuery = false, - XFA_ATTRIBUTEENUM ePreferredPosition = XFA_ATTRIBUTEENUM_First); - bool MatchPageAreaOddOrEven(CXFA_Node* pPageArea, bool bLastMatch); + XFA_AttributeEnum ePreferredPosition = XFA_AttributeEnum::First); + bool MatchPageAreaOddOrEven(CXFA_Node* pPageArea); CXFA_Node* GetNextAvailPageArea(CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea = nullptr, bool bNewPage = false, @@ -120,7 +121,7 @@ class CXFA_LayoutPageMgr { void InitPageSetMap(); void ProcessLastPageSet(); bool IsPageSetRootOrderedOccurrence() const { - return m_ePageSetMode == XFA_ATTRIBUTEENUM_OrderedOccurrence; + return m_ePageSetMode == XFA_AttributeEnum::OrderedOccurrence; } void ClearData(); void MergePageSetContents(); @@ -137,10 +138,10 @@ class CXFA_LayoutPageMgr { CXFA_Node* m_pCurPageArea; int32_t m_nAvailPages; int32_t m_nCurPageCount; - XFA_ATTRIBUTEENUM m_ePageSetMode; + XFA_AttributeEnum m_ePageSetMode; bool m_bCreateOverFlowPage; std::map<CXFA_Node*, int32_t> m_pPageSetMap; - CFX_ArrayTemplate<CXFA_ContainerLayoutItem*> m_PageArray; + std::vector<CXFA_ContainerLayoutItem*> m_PageArray; }; #endif // XFA_FXFA_PARSER_CXFA_LAYOUTPAGEMGR_H_ diff --git a/xfa/fxfa/parser/cxfa_layoutprocessor.cpp b/xfa/fxfa/parser/cxfa_layoutprocessor.cpp index e179d3898543e9472350aeb13b9cc08a66e388ae..540e1c91565a20a9e324fa38ffa36f833a12fd90 100644 --- a/xfa/fxfa/parser/cxfa_layoutprocessor.cpp +++ b/xfa/fxfa/parser/cxfa_layoutprocessor.cpp @@ -6,26 +6,27 @@ #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "fxjs/xfa/cjx_object.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" #include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_itemlayoutprocessor.h" #include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" #include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_subform.h" #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h" -#include "xfa/fxfa/parser/xfa_layout_itemlayout.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" #include "xfa/fxfa/parser/xfa_utils.h" CXFA_LayoutProcessor::CXFA_LayoutProcessor(CXFA_Document* pDocument) - : m_pDocument(pDocument), - m_nProgressCounter(0), - m_bNeeLayout(true) {} + : m_pDocument(pDocument), m_nProgressCounter(0), m_bNeedLayout(true) {} CXFA_LayoutProcessor::~CXFA_LayoutProcessor() {} CXFA_Document* CXFA_LayoutProcessor::GetDocument() const { - return m_pDocument; + return m_pDocument.Get(); } int32_t CXFA_LayoutProcessor::StartLayout(bool bForceRestart) { @@ -39,8 +40,8 @@ int32_t CXFA_LayoutProcessor::StartLayout(bool bForceRestart) { if (!pFormPacketNode) return -1; - CXFA_Node* pFormRoot = - pFormPacketNode->GetFirstChildByClass(XFA_Element::Subform); + CXFA_Subform* pFormRoot = + pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); if (!pFormRoot) return -1; @@ -58,16 +59,18 @@ int32_t CXFA_LayoutProcessor::StartLayout(bool bForceRestart) { return 0; } -int32_t CXFA_LayoutProcessor::DoLayout(IFX_Pause* pPause) { +int32_t CXFA_LayoutProcessor::DoLayout() { if (m_nProgressCounter < 1) return -1; XFA_ItemLayoutProcessorResult eStatus; CXFA_Node* pFormNode = m_pRootItemLayoutProcessor->GetFormNode(); - FX_FLOAT fPosX = pFormNode->GetMeasure(XFA_ATTRIBUTE_X).ToUnit(XFA_UNIT_Pt); - FX_FLOAT fPosY = pFormNode->GetMeasure(XFA_ATTRIBUTE_Y).ToUnit(XFA_UNIT_Pt); + float fPosX = + pFormNode->JSObject()->GetMeasure(XFA_Attribute::X).ToUnit(XFA_Unit::Pt); + float fPosY = + pFormNode->JSObject()->GetMeasure(XFA_Attribute::Y).ToUnit(XFA_Unit::Pt); do { - FX_FLOAT fAvailHeight = m_pLayoutPageMgr->GetAvailHeight(); + float fAvailHeight = m_pLayoutPageMgr->GetAvailHeight(); eStatus = m_pRootItemLayoutProcessor->DoLayout(true, fAvailHeight, fAvailHeight, nullptr); if (eStatus != XFA_ItemLayoutProcessorResult::Done) @@ -79,14 +82,13 @@ int32_t CXFA_LayoutProcessor::DoLayout(IFX_Pause* pPause) { pLayoutItem->m_sPos = CFX_PointF(fPosX, fPosY); m_pLayoutPageMgr->SubmitContentItem(pLayoutItem, eStatus); - } while (eStatus != XFA_ItemLayoutProcessorResult::Done && - (!pPause || !pPause->NeedToPauseNow())); + } while (eStatus != XFA_ItemLayoutProcessorResult::Done); if (eStatus == XFA_ItemLayoutProcessorResult::Done) { m_pLayoutPageMgr->FinishPaginatedPageSets(); m_pLayoutPageMgr->SyncLayoutData(); - m_bNeeLayout = false; - m_rgChangedContainers.RemoveAll(); + m_bNeedLayout = false; + m_rgChangedContainers.clear(); } return 100 * (eStatus == XFA_ItemLayoutProcessorResult::Done ? m_nProgressCounter @@ -95,15 +97,12 @@ int32_t CXFA_LayoutProcessor::DoLayout(IFX_Pause* pPause) { } bool CXFA_LayoutProcessor::IncrementLayout() { - if (m_bNeeLayout) { + if (m_bNeedLayout) { StartLayout(true); - return DoLayout(nullptr) == 100; + return DoLayout() == 100; } - - for (int32_t i = 0, c = m_rgChangedContainers.GetSize(); i < c; i++) { - CXFA_Node* pNode = m_rgChangedContainers[i]; - CXFA_Node* pParentNode = - pNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode); + for (CXFA_Node* pNode : m_rgChangedContainers) { + CXFA_Node* pParentNode = pNode->GetContainerParent(); if (!pParentNode) return false; if (!CXFA_ItemLayoutProcessor::IncrementRelayoutNode(this, pNode, @@ -111,7 +110,7 @@ bool CXFA_LayoutProcessor::IncrementLayout() { return false; } } - m_rgChangedContainers.RemoveAll(); + m_rgChangedContainers.clear(); return true; } @@ -124,13 +123,12 @@ CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetPage(int32_t index) const { } CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node* pFormItem) { - return static_cast<CXFA_LayoutItem*>( - pFormItem->GetUserData(XFA_LAYOUTITEMKEY)); + return pFormItem->JSObject()->GetLayoutItem(); } void CXFA_LayoutProcessor::AddChangedContainer(CXFA_Node* pContainer) { - if (m_rgChangedContainers.Find(pContainer) < 0) - m_rgChangedContainers.Add(pContainer); + if (!pdfium::ContainsValue(m_rgChangedContainers, pContainer)) + m_rgChangedContainers.push_back(pContainer); } CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetRootLayoutItem() const { @@ -138,5 +136,5 @@ CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetRootLayoutItem() const { } bool CXFA_LayoutProcessor::IsNeedLayout() { - return m_bNeeLayout || m_rgChangedContainers.GetSize() > 0; + return m_bNeedLayout || !m_rgChangedContainers.empty(); } diff --git a/xfa/fxfa/parser/cxfa_layoutprocessor.h b/xfa/fxfa/parser/cxfa_layoutprocessor.h index 5861bf7048e9e540f2ceff5514d7a3a75acd3d42..e8391bebb93a44b377f4f0999fea7ac4644edf89 100644 --- a/xfa/fxfa/parser/cxfa_layoutprocessor.h +++ b/xfa/fxfa/parser/cxfa_layoutprocessor.h @@ -8,9 +8,10 @@ #define XFA_FXFA_PARSER_CXFA_LAYOUTPROCESSOR_H_ #include <memory> +#include <vector> #include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "core/fxcrt/unowned_ptr.h" class CXFA_ContainerLayoutItem; class CXFA_Document; @@ -18,7 +19,6 @@ class CXFA_ItemLayoutProcessor; class CXFA_LayoutItem; class CXFA_LayoutPageMgr; class CXFA_Node; -class IFX_Pause; class CXFA_LayoutProcessor { public: @@ -27,13 +27,13 @@ class CXFA_LayoutProcessor { CXFA_Document* GetDocument() const; int32_t StartLayout(bool bForceRestart = false); - int32_t DoLayout(IFX_Pause* pPause = nullptr); + int32_t DoLayout(); bool IncrementLayout(); int32_t CountPages() const; CXFA_ContainerLayoutItem* GetPage(int32_t index) const; CXFA_LayoutItem* GetLayoutItem(CXFA_Node* pFormItem); void AddChangedContainer(CXFA_Node* pContainer); - void SetForceReLayout(bool bForceRestart) { m_bNeeLayout = bForceRestart; } + void SetForceReLayout(bool bForceRestart) { m_bNeedLayout = bForceRestart; } CXFA_ContainerLayoutItem* GetRootLayoutItem() const; CXFA_ItemLayoutProcessor* GetRootRootItemLayoutProcessor() const { return m_pRootItemLayoutProcessor.get(); @@ -45,12 +45,12 @@ class CXFA_LayoutProcessor { private: bool IsNeedLayout(); - CXFA_Document* const m_pDocument; + UnownedPtr<CXFA_Document> const m_pDocument; std::unique_ptr<CXFA_ItemLayoutProcessor> m_pRootItemLayoutProcessor; std::unique_ptr<CXFA_LayoutPageMgr> m_pLayoutPageMgr; - CXFA_NodeArray m_rgChangedContainers; + std::vector<CXFA_Node*> m_rgChangedContainers; uint32_t m_nProgressCounter; - bool m_bNeeLayout; + bool m_bNeedLayout; }; #endif // XFA_FXFA_PARSER_CXFA_LAYOUTPROCESSOR_H_ diff --git a/xfa/fxfa/parser/cxfa_level.cpp b/xfa/fxfa/parser/cxfa_level.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7343805dfb3a476a386b719c7c67f54c5dd0115c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_level.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_level.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"level"; + +} // namespace + +CXFA_Level::CXFA_Level(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Level, + nullptr, + kAttributeData, + kName) {} + +CXFA_Level::~CXFA_Level() {} diff --git a/xfa/fxfa/parser/cxfa_level.h b/xfa/fxfa/parser/cxfa_level.h new file mode 100644 index 0000000000000000000000000000000000000000..abdd048232de14ef2c222c7959fb7a06f59df899 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_level.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LEVEL_H_ +#define XFA_FXFA_PARSER_CXFA_LEVEL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Level : public CXFA_Node { + public: + CXFA_Level(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Level() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LEVEL_H_ diff --git a/xfa/fxfa/parser/cxfa_line.cpp b/xfa/fxfa/parser/cxfa_line.cpp index 38de0d8ca88c458d6110186b26a8f0b8d597a099..4e656c2999b67ba7137db58cdf702a264bae76b0 100644 --- a/xfa/fxfa/parser/cxfa_line.cpp +++ b/xfa/fxfa/parser/cxfa_line.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,16 +6,50 @@ #include "xfa/fxfa/parser/cxfa_line.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_line.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxfa/parser/cxfa_node.h" -int32_t CXFA_Line::GetHand() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_Hand); +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Edge, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Slope, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Backslash}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Hand, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Even}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"line"; + +} // namespace + +CXFA_Line::CXFA_Line(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Line, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Line>(this)) {} + +CXFA_Line::~CXFA_Line() {} + +XFA_AttributeEnum CXFA_Line::GetHand() { + return JSObject()->GetEnum(XFA_Attribute::Hand); } bool CXFA_Line::GetSlope() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_Slope) == XFA_ATTRIBUTEENUM_Slash; + return JSObject()->GetEnum(XFA_Attribute::Slope) == XFA_AttributeEnum::Slash; } -CXFA_Edge CXFA_Line::GetEdge() { - return CXFA_Edge(m_pNode->GetChild(0, XFA_Element::Edge)); +CXFA_Edge* CXFA_Line::GetEdgeIfExists() { + return GetChild<CXFA_Edge>(0, XFA_Element::Edge, false); } diff --git a/xfa/fxfa/parser/cxfa_line.h b/xfa/fxfa/parser/cxfa_line.h index f014cc0618f7e93fac4946629dd4c4c54e56cefe..18faacd16dbb64a63c5fdc8bcd4960e0eec693af 100644 --- a/xfa/fxfa/parser/cxfa_line.h +++ b/xfa/fxfa/parser/cxfa_line.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,19 +7,18 @@ #ifndef XFA_FXFA_PARSER_CXFA_LINE_H_ #define XFA_FXFA_PARSER_CXFA_LINE_H_ -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; +class CXFA_Edge; -class CXFA_Line : public CXFA_Data { +class CXFA_Line : public CXFA_Node { public: - explicit CXFA_Line(CXFA_Node* pNode) : CXFA_Data(pNode) {} + CXFA_Line(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Line() override; - int32_t GetHand(); + XFA_AttributeEnum GetHand(); bool GetSlope(); - CXFA_Edge GetEdge(); + CXFA_Edge* GetEdgeIfExists(); }; #endif // XFA_FXFA_PARSER_CXFA_LINE_H_ diff --git a/xfa/fxfa/parser/cxfa_linear.cpp b/xfa/fxfa/parser/cxfa_linear.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8506d247d4d6149557a4f743ea7b5d680f2693c7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_linear.cpp @@ -0,0 +1,91 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_linear.h" + +#include "fxjs/xfa/cjx_linear.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_color.h" +#include "xfa/fxgraphics/cxfa_geshading.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Color, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ToRight}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"linear"; + +} // namespace + +CXFA_Linear::CXFA_Linear(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Linear, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Linear>(this)) {} + +CXFA_Linear::~CXFA_Linear() {} + +XFA_AttributeEnum CXFA_Linear::GetType() { + return JSObject() + ->TryEnum(XFA_Attribute::Type, true) + .value_or(XFA_AttributeEnum::ToRight); +} + +CXFA_Color* CXFA_Linear::GetColorIfExists() { + return GetChild<CXFA_Color>(0, XFA_Element::Color, false); +} + +void CXFA_Linear::Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + FX_ARGB crStart, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix) { + CXFA_Color* pColor = GetColorIfExists(); + FX_ARGB crEnd = pColor ? pColor->GetValue() : CXFA_Color::kBlackColor; + + CFX_PointF ptStart; + CFX_PointF ptEnd; + switch (GetType()) { + case XFA_AttributeEnum::ToRight: + ptStart = CFX_PointF(rtFill.left, rtFill.top); + ptEnd = CFX_PointF(rtFill.right(), rtFill.top); + break; + case XFA_AttributeEnum::ToBottom: + ptStart = CFX_PointF(rtFill.left, rtFill.top); + ptEnd = CFX_PointF(rtFill.left, rtFill.bottom()); + break; + case XFA_AttributeEnum::ToLeft: + ptStart = CFX_PointF(rtFill.right(), rtFill.top); + ptEnd = CFX_PointF(rtFill.left, rtFill.top); + break; + case XFA_AttributeEnum::ToTop: + ptStart = CFX_PointF(rtFill.left, rtFill.bottom()); + ptEnd = CFX_PointF(rtFill.left, rtFill.top); + break; + default: + break; + } + + CXFA_GEShading shading(ptStart, ptEnd, false, false, crStart, crEnd); + + pGS->SaveGraphState(); + pGS->SetFillColor(CXFA_GEColor(&shading)); + pGS->FillPath(fillPath, FXFILL_WINDING, &matrix); + pGS->RestoreGraphState(); +} diff --git a/xfa/fxfa/parser/cxfa_linear.h b/xfa/fxfa/parser/cxfa_linear.h new file mode 100644 index 0000000000000000000000000000000000000000..bb55f8073ce05229950c2c29296d800b95d729be --- /dev/null +++ b/xfa/fxfa/parser/cxfa_linear.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LINEAR_H_ +#define XFA_FXFA_PARSER_CXFA_LINEAR_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_gepath.h" + +class CXFA_Color; +class CXFA_Graphics; + +class CXFA_Linear : public CXFA_Node { + public: + static constexpr XFA_AttributeEnum kDefaultType = XFA_AttributeEnum::ToRight; + + CXFA_Linear(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Linear() override; + + void Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + FX_ARGB crStart, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix); + + private: + XFA_AttributeEnum GetType(); + CXFA_Color* GetColorIfExists(); +}; + +#endif // XFA_FXFA_PARSER_CXFA_LINEAR_H_ diff --git a/xfa/fxfa/parser/cxfa_linearized.cpp b/xfa/fxfa/parser/cxfa_linearized.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ae6b8dbcc2ff98577146c150fd9bfad64f81c9e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_linearized.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_linearized.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"linearized"; + +} // namespace + +CXFA_Linearized::CXFA_Linearized(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Linearized, + nullptr, + kAttributeData, + kName) {} + +CXFA_Linearized::~CXFA_Linearized() {} diff --git a/xfa/fxfa/parser/cxfa_linearized.h b/xfa/fxfa/parser/cxfa_linearized.h new file mode 100644 index 0000000000000000000000000000000000000000..df7846e0a842187dc212aa1f85ad7a4fd0901ff7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_linearized.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LINEARIZED_H_ +#define XFA_FXFA_PARSER_CXFA_LINEARIZED_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Linearized : public CXFA_Node { + public: + CXFA_Linearized(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Linearized() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LINEARIZED_H_ diff --git a/xfa/fxfa/parser/cxfa_list.cpp b/xfa/fxfa/parser/cxfa_list.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f5fc29ca5283d05f5d05e94c24065c95faecbf6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_list.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_list.h" + +#include <utility> + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_treelist.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +CXFA_List::CXFA_List(CXFA_Document* pDocument, std::unique_ptr<CJX_Object> obj) + : CXFA_List(pDocument, + XFA_ObjectType::List, + XFA_Element::List, + WideStringView(L"list"), + std::move(obj)) {} + +CXFA_List::CXFA_List(CXFA_Document* pDocument, + XFA_ObjectType objectType, + XFA_Element eType, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> obj) + : CXFA_Object(pDocument, objectType, eType, elementName, std::move(obj)) { + m_pDocument->GetScriptContext()->AddToCacheList( + std::unique_ptr<CXFA_List>(this)); +} + +CXFA_List::~CXFA_List() {} diff --git a/xfa/fxfa/parser/cxfa_list.h b/xfa/fxfa/parser/cxfa_list.h new file mode 100644 index 0000000000000000000000000000000000000000..de9406dd069cac82b4a036b3f2d1b6764f540171 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_list.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LIST_H_ +#define XFA_FXFA_PARSER_CXFA_LIST_H_ + +#include <memory> + +#include "xfa/fxfa/parser/cxfa_object.h" + +class CXFA_Document; + +class CXFA_List : public CXFA_Object { + public: + ~CXFA_List() override; + + virtual size_t GetLength() = 0; + virtual bool Append(CXFA_Node* pNode) = 0; + virtual bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) = 0; + virtual bool Remove(CXFA_Node* pNode) = 0; + virtual CXFA_Node* Item(size_t iIndex) = 0; + + protected: + CXFA_List(CXFA_Document* doc, std::unique_ptr<CJX_Object> js_obj); + CXFA_List(CXFA_Document* pDocument, + XFA_ObjectType objectType, + XFA_Element eType, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> obj); +}; + +#endif // XFA_FXFA_PARSER_CXFA_LIST_H_ diff --git a/xfa/fxfa/parser/cxfa_locale.cpp b/xfa/fxfa/parser/cxfa_locale.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c601139dcee8df721e30bc1fe077793d173c1234 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_locale.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_locale.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::DatePatterns, 1, 0}, {XFA_Element::CalendarSymbols, 1, 0}, + {XFA_Element::CurrencySymbols, 1, 0}, {XFA_Element::Typefaces, 1, 0}, + {XFA_Element::DateTimeSymbols, 1, 0}, {XFA_Element::NumberPatterns, 1, 0}, + {XFA_Element::NumberSymbols, 1, 0}, {XFA_Element::TimePatterns, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"locale"; + +} // namespace + +CXFA_Locale::CXFA_Locale(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet), + XFA_ObjectType::Node, + XFA_Element::Locale, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Locale::~CXFA_Locale() {} diff --git a/xfa/fxfa/parser/cxfa_locale.h b/xfa/fxfa/parser/cxfa_locale.h new file mode 100644 index 0000000000000000000000000000000000000000..3a7e83dc7095350ea62423eb5e14239ba147ebe2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_locale.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LOCALE_H_ +#define XFA_FXFA_PARSER_CXFA_LOCALE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Locale : public CXFA_Node { + public: + CXFA_Locale(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Locale() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LOCALE_H_ diff --git a/xfa/fxfa/parser/cxfa_localemgr.cpp b/xfa/fxfa/parser/cxfa_localemgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb769b62f0e6a86770fecf572603a6de477529e4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_localemgr.cpp @@ -0,0 +1,1255 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_localemgr.h" + +#include <time.h> + +#include <memory> +#include <utility> + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fxcodec/codec/ccodec_flatemodule.h" +#include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/xml/cxml_element.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_acrobat.h" +#include "xfa/fxfa/parser/cxfa_common.h" +#include "xfa/fxfa/parser/cxfa_locale.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodelocale.h" +#include "xfa/fxfa/parser/cxfa_present.h" +#include "xfa/fxfa/parser/cxfa_xmllocale.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +#define FX_LANG_zh_HK 0x0c04 +#define FX_LANG_zh_CN 0x0804 +#define FX_LANG_zh_TW 0x0404 +#define FX_LANG_nl_NL 0x0413 +#define FX_LANG_en_GB 0x0809 +#define FX_LANG_en_US 0x0409 +#define FX_LANG_fr_FR 0x040c +#define FX_LANG_de_DE 0x0407 +#define FX_LANG_it_IT 0x0410 +#define FX_LANG_ja_JP 0x0411 +#define FX_LANG_ko_KR 0x0412 +#define FX_LANG_pt_BR 0x0416 +#define FX_LANG_ru_RU 0x0419 +#define FX_LANG_es_LA 0x080a +#define FX_LANG_es_ES 0x0c0a + +// These arrays are the hex encoded XML strings which define the locale. +// <locale name="en_US" desc="English(America)"> +// <calendarSymbols name="gregorian"> +// <monthNames> +// <month>January</month> +// <month>February</month> +// ... +const uint8_t g_enUS_Locale[] = { + 0x78, 0x9C, 0x95, 0x56, 0xD1, 0x6E, 0x9B, 0x30, 0x14, 0x7D, 0x9F, 0xB4, + 0x7F, 0x40, 0xD6, 0x2A, 0xB5, 0x52, 0x56, 0x6F, 0x8F, 0xA9, 0x88, 0xA5, + 0x6C, 0x24, 0x9B, 0x3A, 0xD1, 0x55, 0x22, 0x55, 0xB5, 0xBE, 0x4C, 0x0E, + 0xDC, 0x05, 0x34, 0xB0, 0x23, 0x83, 0x37, 0x05, 0xED, 0xE3, 0x67, 0x07, + 0xC3, 0xC0, 0xF6, 0x24, 0xC2, 0x4B, 0x7C, 0xCF, 0x3D, 0xE7, 0xE6, 0xDE, + 0x63, 0x30, 0x84, 0x25, 0x4F, 0x69, 0x09, 0x01, 0xA3, 0x15, 0xAC, 0x10, + 0xB0, 0xEF, 0x4F, 0x09, 0x0A, 0x32, 0xA8, 0xD3, 0x15, 0xDA, 0xB0, 0x43, + 0x59, 0xD4, 0xF9, 0xF5, 0xBA, 0x02, 0x51, 0xA4, 0xF4, 0x06, 0x91, 0x50, + 0x53, 0x59, 0x46, 0x45, 0x72, 0xAA, 0xF6, 0xBC, 0xAC, 0x8D, 0xEA, 0x20, + 0xE0, 0xC0, 0x45, 0x41, 0x99, 0x62, 0x54, 0x9C, 0x35, 0xF9, 0x83, 0x82, + 0x6B, 0xB3, 0x26, 0xF7, 0x94, 0x49, 0x2A, 0x4E, 0x21, 0xEE, 0xC2, 0xD7, + 0xAF, 0x0C, 0xBE, 0x85, 0xBD, 0xF0, 0x26, 0x62, 0x2A, 0xD2, 0xDC, 0x41, + 0xD7, 0x47, 0x51, 0x94, 0x1E, 0xAE, 0xAB, 0xBF, 0x97, 0x0C, 0x3C, 0x60, + 0xE9, 0x32, 0xD7, 0xF2, 0x20, 0xEB, 0xC6, 0x81, 0x13, 0x38, 0x36, 0x50, + 0xED, 0x41, 0x38, 0x99, 0xAF, 0x69, 0xC3, 0x7D, 0xF8, 0x03, 0xFF, 0xE5, + 0x17, 0x44, 0x90, 0xDA, 0x09, 0x3C, 0xB2, 0xA8, 0xE7, 0x9D, 0xA3, 0x80, + 0xEE, 0xF7, 0x62, 0x85, 0xDE, 0xA3, 0x91, 0x73, 0x3E, 0xD7, 0x7C, 0x86, + 0xF9, 0xEC, 0x9A, 0x6B, 0x96, 0xCF, 0x2B, 0x9F, 0x55, 0x3E, 0x9F, 0x7C, + 0x0E, 0xF9, 0xDC, 0xF1, 0x19, 0xF3, 0x7F, 0x4F, 0x32, 0x7A, 0x32, 0xB7, + 0x90, 0x5A, 0x91, 0x44, 0xAA, 0x5B, 0x4E, 0x75, 0xAE, 0xD7, 0x5D, 0x92, + 0xC4, 0xDC, 0x81, 0x76, 0x12, 0x6A, 0x1B, 0x7B, 0x86, 0x8C, 0xB9, 0xE8, + 0x2E, 0x97, 0xC2, 0x01, 0xB7, 0xA2, 0xB0, 0xA1, 0x84, 0x36, 0x52, 0x8C, + 0x41, 0x3C, 0xF4, 0x35, 0xEA, 0x71, 0xB4, 0x6B, 0xA6, 0x59, 0xBB, 0x53, + 0xBB, 0x4D, 0xBB, 0x45, 0xBB, 0x39, 0xBB, 0x2F, 0xBB, 0x29, 0x7F, 0x3F, + 0xFA, 0x21, 0xCD, 0x0A, 0xA8, 0xFA, 0x67, 0xCF, 0x84, 0x64, 0x1D, 0x2B, + 0x77, 0xFB, 0x60, 0xC4, 0x23, 0x8F, 0x56, 0x02, 0x4F, 0x2B, 0x28, 0x04, + 0x04, 0x35, 0xD5, 0xD4, 0x8A, 0x7C, 0xF8, 0x18, 0x62, 0xFD, 0xDB, 0x25, + 0xC8, 0x3A, 0x1A, 0x42, 0x3C, 0x10, 0x75, 0x60, 0x9D, 0x11, 0x5D, 0xE3, + 0x0D, 0x3C, 0xD2, 0xA6, 0x01, 0xC1, 0xCE, 0x7B, 0x3A, 0x44, 0xE6, 0x00, + 0xF9, 0x21, 0xCB, 0x12, 0x91, 0x8D, 0xBA, 0x16, 0x41, 0xAC, 0xAE, 0x20, + 0x5A, 0x04, 0xDF, 0xD4, 0xA5, 0x27, 0x1C, 0xB8, 0x56, 0x21, 0x23, 0x2D, + 0x39, 0x3B, 0x20, 0x72, 0xA1, 0xA8, 0x82, 0xEC, 0xAC, 0xB9, 0x40, 0x52, + 0xE7, 0x5C, 0x34, 0x4A, 0x84, 0x23, 0xEC, 0xE1, 0xE3, 0xC9, 0x84, 0x0A, + 0x68, 0x8A, 0x6A, 0x34, 0xF1, 0x28, 0x9A, 0x4C, 0x9C, 0xDF, 0xC5, 0xF1, + 0x5D, 0x92, 0x04, 0xEB, 0xE0, 0x25, 0xC4, 0x23, 0x92, 0x55, 0x61, 0x32, + 0xEA, 0x65, 0x9A, 0xF3, 0xA4, 0x83, 0x64, 0x86, 0xC0, 0xCC, 0xA9, 0x25, + 0x1E, 0x3E, 0x9E, 0xCC, 0x65, 0x8C, 0xDA, 0x29, 0xAC, 0xDF, 0xEC, 0x4F, + 0xA7, 0x38, 0xFB, 0xF9, 0xB9, 0xAA, 0x93, 0x4D, 0xB4, 0xFD, 0xFD, 0x4C, + 0xF3, 0x2F, 0xED, 0x4B, 0x67, 0xCE, 0x98, 0xA4, 0x74, 0x4C, 0xEA, 0x53, + 0xF1, 0x9F, 0x43, 0x93, 0xD8, 0xB4, 0xA2, 0x30, 0xFD, 0xE2, 0x41, 0xA4, + 0x5D, 0xB4, 0xED, 0xF2, 0xB6, 0x6D, 0xDB, 0x10, 0x4F, 0x78, 0x4E, 0x21, + 0x23, 0x4C, 0xA5, 0x10, 0xC0, 0xD2, 0x13, 0x22, 0x6F, 0x3A, 0xE9, 0x72, + 0xF9, 0xE7, 0x7A, 0x58, 0xDE, 0xCC, 0xAC, 0x72, 0x04, 0x91, 0x02, 0x6B, + 0xCC, 0xDF, 0x5F, 0x79, 0x54, 0xD8, 0x9A, 0x62, 0x28, 0xD4, 0x0F, 0x3A, + 0x09, 0x4D, 0xD9, 0x0C, 0xD2, 0xA2, 0xA2, 0x6A, 0xF3, 0x6F, 0x7B, 0x7D, + 0x97, 0xB6, 0xD5, 0xC3, 0xBB, 0x95, 0xCB, 0x63, 0xA1, 0x37, 0x7E, 0x31, + 0x8B, 0x3F, 0x74, 0x7D, 0x35, 0x8B, 0x5E, 0x15, 0x4C, 0xD6, 0x88, 0xBC, + 0x9D, 0x45, 0x6E, 0x41, 0x70, 0x44, 0xDE, 0xB9, 0x5C, 0x3C, 0x1D, 0x5B, + 0x21, 0xFD, 0x16, 0x0C, 0x4E, 0x4C, 0x81, 0xFE, 0x66, 0x3B, 0x07, 0x6A, + 0x9B, 0xD4, 0xA9, 0x31, 0xC9, 0xBB, 0x25, 0x8C, 0xA2, 0xA8, 0xB9, 0x5E, + 0x20, 0xF2, 0x94, 0x44, 0xB3, 0x45, 0x63, 0xCB, 0x5D, 0x09, 0xB6, 0x7B, + 0xD5, 0x58, 0xF7, 0x55, 0xA4, 0x96, 0x7F, 0x01, 0x75, 0x37, 0x1B, 0x8B, +}; +const uint8_t g_enGB_Locale[] = { + 0x78, 0x9C, 0x95, 0x56, 0xD1, 0x6E, 0xD3, 0x30, 0x14, 0x7D, 0x47, 0xE2, + 0x1F, 0xA2, 0x88, 0x49, 0x20, 0x6D, 0x33, 0x3C, 0x6E, 0xEA, 0x2C, 0x75, + 0xEB, 0xD6, 0x32, 0xC8, 0xA8, 0x48, 0xC5, 0xC4, 0x5E, 0x90, 0x9B, 0x78, + 0x8D, 0x59, 0x62, 0x57, 0x4E, 0xCC, 0x94, 0xFC, 0x02, 0x9F, 0xC0, 0x23, + 0xCF, 0x08, 0xF1, 0x01, 0xBC, 0xF0, 0x2F, 0x48, 0xFB, 0x0C, 0x6E, 0x1A, + 0x27, 0x4B, 0x1C, 0xAF, 0x64, 0x79, 0x89, 0xEF, 0xB9, 0xE7, 0xDC, 0xDE, + 0x7B, 0x9C, 0xB8, 0x19, 0xC5, 0x22, 0x20, 0x31, 0x75, 0x38, 0x49, 0xE8, + 0x91, 0x4B, 0xF9, 0xA7, 0xE9, 0xB1, 0xEB, 0x84, 0x34, 0x0D, 0x8E, 0xDC, + 0xBB, 0xAF, 0xBF, 0xEE, 0x7E, 0xFE, 0x78, 0x0E, 0xB7, 0xBF, 0xDF, 0x7E, + 0xBF, 0x70, 0xF1, 0xA8, 0x24, 0xF2, 0x90, 0x48, 0x3F, 0x4F, 0x96, 0x22, + 0x4E, 0xB5, 0x66, 0x25, 0xE9, 0x4A, 0x48, 0x46, 0x38, 0x30, 0x12, 0xC1, + 0xB3, 0xE8, 0x02, 0xE0, 0x54, 0xAF, 0xF1, 0x39, 0xE1, 0x8A, 0xC8, 0x7C, + 0x84, 0xAA, 0xF0, 0xE9, 0x13, 0x8D, 0x9F, 0xD1, 0xA5, 0xB4, 0x26, 0x3C, + 0x22, 0x83, 0xA8, 0x87, 0x8E, 0xD7, 0x92, 0xC5, 0x16, 0x6E, 0x5F, 0x7F, + 0xAE, 0x38, 0xB5, 0x80, 0x71, 0x9F, 0x39, 0x56, 0x2B, 0x95, 0x66, 0x3D, + 0xD8, 0xA7, 0xEB, 0x8C, 0x26, 0x4B, 0x2A, 0x7B, 0x99, 0x77, 0x41, 0x26, + 0x6C, 0xF8, 0x85, 0xF8, 0x62, 0x17, 0x4C, 0x68, 0x60, 0x26, 0x50, 0xCB, + 0xA2, 0x9A, 0xB7, 0x89, 0x1C, 0xB2, 0x5C, 0xCA, 0x23, 0xF7, 0x95, 0xDB, + 0x72, 0xCE, 0xE6, 0x9A, 0xCD, 0x30, 0x9B, 0x5D, 0x43, 0xCD, 0xB2, 0x79, + 0x65, 0xB3, 0xCA, 0xE6, 0x93, 0xCD, 0x21, 0x9B, 0x3B, 0x36, 0x63, 0x1E, + 0xF6, 0x24, 0x24, 0xB9, 0x7E, 0x84, 0x60, 0x85, 0x7D, 0x05, 0x8F, 0x1C, + 0x74, 0x5E, 0xAE, 0xAB, 0x24, 0xF6, 0x44, 0x0F, 0x5A, 0x28, 0x9A, 0x9A, + 0xD8, 0x25, 0x0D, 0x79, 0x1F, 0x5D, 0x44, 0x4A, 0xF6, 0xC0, 0x33, 0xC9, + 0x4C, 0xC8, 0x27, 0x99, 0x92, 0x6D, 0x10, 0x35, 0x7D, 0xB5, 0x7A, 0x6C, + 0xED, 0x9A, 0x6E, 0xD6, 0xEC, 0xD4, 0x6C, 0xD3, 0x6C, 0xD1, 0x6C, 0xCE, + 0xEC, 0xCB, 0x6C, 0xCA, 0xDE, 0x4F, 0x42, 0x61, 0x02, 0x46, 0x93, 0xFA, + 0xDD, 0xD3, 0x21, 0x1E, 0x7B, 0xE0, 0x6E, 0x1D, 0xB4, 0x78, 0x78, 0x6E, + 0x24, 0x50, 0xB7, 0x02, 0x20, 0x54, 0x12, 0x5D, 0x0D, 0x56, 0xF8, 0xF8, + 0x64, 0x84, 0xCA, 0x7B, 0x95, 0xC0, 0xE3, 0x49, 0x13, 0xA2, 0x86, 0x58, + 0x06, 0xC6, 0x19, 0x51, 0x35, 0x9E, 0xD1, 0x39, 0xC9, 0x32, 0x2A, 0xF9, + 0x66, 0x4F, 0x9B, 0x48, 0x1F, 0x20, 0xD7, 0x2A, 0x8E, 0x5D, 0x7C, 0x0A, + 0xD7, 0xAE, 0x33, 0x71, 0x3C, 0xB8, 0x9C, 0x8F, 0x70, 0x95, 0x03, 0x36, + 0x54, 0xA3, 0x8E, 0x56, 0xC6, 0x82, 0xAF, 0x5C, 0xFC, 0x38, 0x4D, 0x42, + 0x43, 0x2D, 0x19, 0xAA, 0x48, 0x23, 0x21, 0x33, 0xD0, 0x4C, 0x90, 0xE7, + 0x21, 0xAB, 0x06, 0x75, 0x46, 0x04, 0x20, 0x63, 0x49, 0x6B, 0xE4, 0x56, + 0xD4, 0x19, 0x79, 0x36, 0x3B, 0xF4, 0xBC, 0x43, 0xDF, 0x77, 0xAE, 0x46, + 0xA8, 0xC5, 0x31, 0x0A, 0x74, 0x66, 0x7D, 0x94, 0x64, 0x33, 0x6A, 0xAD, + 0x18, 0xC0, 0xD7, 0x83, 0x6E, 0x14, 0x3D, 0x3A, 0xEA, 0xCC, 0xA4, 0x8D, + 0x5A, 0x00, 0x56, 0xEF, 0xF4, 0x34, 0xF7, 0xC2, 0x9B, 0x59, 0x92, 0xFA, + 0xA7, 0x93, 0xB3, 0xDB, 0x4B, 0x12, 0xBD, 0x29, 0xAE, 0x2A, 0x63, 0xDA, + 0x24, 0xD0, 0x71, 0x55, 0x1E, 0x89, 0xF7, 0xEE, 0x74, 0x62, 0xDD, 0x09, + 0x60, 0xF0, 0x38, 0x06, 0x2E, 0x2E, 0x76, 0x8B, 0xE2, 0x60, 0xBF, 0x28, + 0x8A, 0x11, 0xEA, 0xF0, 0x7A, 0x85, 0xB4, 0x30, 0x50, 0x52, 0x52, 0x1E, + 0xE4, 0x2E, 0x7E, 0x56, 0x49, 0x0F, 0x0E, 0x06, 0x2A, 0xD7, 0x54, 0x06, + 0x94, 0x67, 0xFA, 0x27, 0x77, 0x2C, 0x2A, 0x64, 0x74, 0xDE, 0x14, 0xAA, + 0x87, 0xEB, 0x84, 0xBA, 0x6C, 0x48, 0x03, 0x96, 0x10, 0xD8, 0xEC, 0xFD, + 0x5A, 0x5F, 0xA5, 0x4D, 0x75, 0xF3, 0x67, 0x2A, 0xD4, 0x9A, 0x95, 0x3B, + 0xBD, 0x3B, 0x88, 0xDF, 0x74, 0xBD, 0x33, 0x88, 0x9E, 0x30, 0xAE, 0x52, + 0x17, 0xEF, 0x0D, 0x22, 0x17, 0x54, 0x0A, 0x17, 0xBF, 0xEC, 0x73, 0x51, + 0x77, 0x6C, 0x40, 0x6A, 0xDB, 0x1B, 0x27, 0xBA, 0x40, 0xFD, 0x7C, 0x6D, + 0x02, 0x17, 0xFF, 0xF9, 0x0E, 0xE7, 0x44, 0x87, 0xD0, 0xAF, 0xA1, 0x25, + 0x2C, 0x15, 0xE5, 0xC2, 0xC5, 0xD3, 0xE3, 0xF9, 0x60, 0x51, 0xDB, 0xF3, + 0xBE, 0x04, 0x99, 0xCD, 0x96, 0xEF, 0x42, 0xBE, 0xA6, 0xD7, 0x24, 0x28, + 0x0F, 0xBB, 0x7A, 0xA9, 0x6B, 0x79, 0x39, 0x7C, 0xDA, 0x84, 0xCE, 0x1C, + 0xAC, 0x40, 0x6D, 0x66, 0x9D, 0x66, 0x9C, 0x09, 0xFE, 0x60, 0xFA, 0x44, + 0x28, 0xC9, 0xA8, 0x74, 0xFC, 0x2C, 0xB4, 0xE6, 0xC7, 0x21, 0x7C, 0x50, + 0x38, 0x73, 0xF6, 0x1F, 0xC2, 0x0C, 0x3E, 0x96, 0xE8, 0xED, 0x16, 0xC2, + 0x58, 0x92, 0x25, 0xBC, 0x2E, 0x0F, 0x13, 0x16, 0x11, 0x61, 0xD6, 0xF4, + 0x1B, 0x51, 0xA8, 0x1B, 0xE2, 0x4C, 0x45, 0x16, 0xB1, 0xA0, 0x9C, 0x63, + 0xEF, 0xC3, 0x6B, 0xC7, 0xDB, 0x46, 0x85, 0x91, 0x83, 0x48, 0xD4, 0xD4, + 0xF7, 0x5B, 0x7E, 0x14, 0x98, 0xAB, 0x72, 0x32, 0xE7, 0xED, 0x16, 0x92, + 0x2F, 0x06, 0x90, 0xBC, 0x5C, 0xF1, 0xD5, 0x67, 0xB1, 0xE1, 0xE9, 0xE6, + 0xD0, 0xFD, 0x9E, 0x95, 0x51, 0xF5, 0x19, 0x0B, 0xCB, 0x7F, 0x8E, 0x69, + 0xAC, 0xD0}; +const uint8_t g_zhCN_Locale[] = { + 0x78, 0x9C, 0xED, 0x56, 0x41, 0x4F, 0xD4, 0x40, 0x14, 0xBE, 0x9B, 0xF8, + 0x1F, 0x9A, 0x46, 0x52, 0x4D, 0x58, 0x46, 0x8F, 0x90, 0xD2, 0x64, 0x03, + 0x08, 0x06, 0xBB, 0x21, 0x96, 0x68, 0xE0, 0x62, 0xBA, 0xED, 0xB0, 0x2D, + 0x6C, 0x3B, 0x64, 0xB6, 0x0D, 0x6E, 0x4F, 0x18, 0x82, 0x82, 0xC2, 0x45, + 0x89, 0x9A, 0x80, 0xE1, 0x64, 0x3C, 0x28, 0x9E, 0x8C, 0x01, 0x22, 0xF1, + 0xCF, 0xB0, 0xCB, 0x91, 0xBF, 0xE0, 0x9B, 0xED, 0xB4, 0xB4, 0xDD, 0xD9, + 0xB5, 0x3F, 0xC0, 0x3D, 0xCD, 0xFB, 0xDE, 0xF7, 0x7D, 0xF3, 0xDE, 0xEB, + 0x74, 0xB6, 0x6A, 0x93, 0x58, 0x66, 0x13, 0x4B, 0xBE, 0xE9, 0xE1, 0x49, + 0x39, 0x72, 0x9E, 0x4F, 0xD5, 0x64, 0xC9, 0xC6, 0x2D, 0x6B, 0x52, 0xBE, + 0x3C, 0x3D, 0xE9, 0x7E, 0x78, 0x7D, 0xF7, 0xEA, 0xC7, 0xE6, 0xE5, 0xC5, + 0xFB, 0xEB, 0xDF, 0x7B, 0x10, 0x77, 0x0E, 0x2F, 0xEE, 0xC9, 0x9A, 0xCA, + 0x14, 0xBE, 0x6D, 0x52, 0xA3, 0xED, 0xD5, 0x49, 0xB3, 0xC5, 0xC5, 0x0D, + 0x8A, 0x1B, 0x84, 0xBA, 0xA6, 0x0F, 0x0C, 0x8F, 0xF8, 0x81, 0x53, 0x03, + 0xB8, 0xC5, 0xD7, 0xDA, 0xE5, 0xE9, 0x66, 0xF7, 0x68, 0x47, 0x45, 0x71, + 0x74, 0xFB, 0x56, 0x02, 0x9F, 0xEF, 0x09, 0xE1, 0xD3, 0x5D, 0x11, 0xDC, + 0x39, 0x3C, 0x14, 0x9B, 0x1C, 0x08, 0xD9, 0xDB, 0x27, 0x62, 0xEF, 0x2D, + 0x31, 0xFB, 0x9B, 0x90, 0x7D, 0xF6, 0x59, 0xC8, 0xDE, 0x7F, 0x39, 0x00, + 0x1E, 0xD0, 0x28, 0xCB, 0x14, 0x7B, 0x45, 0x99, 0x31, 0x25, 0xC4, 0x5E, + 0x24, 0x99, 0xF5, 0x3A, 0x9D, 0x94, 0x1F, 0xC8, 0xFF, 0xA7, 0x57, 0x7A, + 0x7A, 0xB6, 0xD9, 0xE6, 0x07, 0x0E, 0x56, 0x5A, 0xF7, 0xD3, 0x71, 0xF7, + 0xE8, 0xB8, 0xFB, 0xF1, 0x8B, 0x8A, 0x58, 0x18, 0xE7, 0x39, 0x0A, 0x7B, + 0x88, 0xD0, 0xF3, 0x3D, 0x21, 0x77, 0x57, 0x80, 0xC2, 0x24, 0x85, 0x0E, + 0x07, 0x22, 0xEE, 0xF6, 0x49, 0x8A, 0xA2, 0xB4, 0xC8, 0x4C, 0xC1, 0x99, + 0x87, 0xDD, 0x53, 0x15, 0x6A, 0x2E, 0x56, 0x5B, 0xAC, 0xB3, 0x58, 0x61, + 0xB1, 0xB6, 0x62, 0x55, 0x03, 0xEB, 0xF1, 0x30, 0x75, 0x6D, 0x17, 0x7B, + 0xC9, 0x6B, 0xCB, 0x43, 0xD8, 0xE0, 0x4D, 0x67, 0x9F, 0x0D, 0x3E, 0x01, + 0x32, 0x5C, 0x48, 0xBE, 0xED, 0x4B, 0xA2, 0xBC, 0x13, 0x20, 0x98, 0x9A, + 0xDC, 0x15, 0x56, 0x50, 0xC1, 0xF7, 0xCE, 0xF6, 0x56, 0x67, 0x77, 0x5F, + 0x45, 0x2C, 0x8C, 0xF3, 0x1C, 0x4D, 0x21, 0x94, 0x6A, 0x58, 0x50, 0xB8, + 0x71, 0xE2, 0x5E, 0x02, 0xBC, 0x60, 0x06, 0x01, 0xA6, 0x7E, 0xEF, 0x99, + 0xA7, 0x11, 0xBF, 0x8E, 0x56, 0xC2, 0x66, 0x53, 0xD6, 0x96, 0xE0, 0xA7, + 0x74, 0xCE, 0x7E, 0x2A, 0xBA, 0x02, 0xA7, 0x47, 0x99, 0x56, 0x60, 0xBC, + 0xCA, 0x0C, 0xFC, 0x58, 0xEF, 0xA9, 0xA4, 0xE0, 0xC7, 0x1D, 0x9A, 0xC4, + 0x6F, 0x0C, 0x70, 0x28, 0xA1, 0xF6, 0xB0, 0x1D, 0x8B, 0x2B, 0x7A, 0x65, + 0xBA, 0x04, 0xBF, 0xE5, 0x10, 0x1A, 0x30, 0x85, 0x90, 0x8F, 0x72, 0xED, + 0x02, 0x10, 0xB8, 0x5E, 0xA6, 0xFD, 0x4C, 0x94, 0x6B, 0xBF, 0xEA, 0x38, + 0x50, 0xEF, 0x2F, 0x45, 0xD7, 0x95, 0xCE, 0xCE, 0x2B, 0xC5, 0x30, 0x94, + 0xAB, 0xAF, 0xEF, 0x14, 0x69, 0x59, 0x45, 0x19, 0x45, 0xC1, 0x2E, 0xD7, + 0xBD, 0xD8, 0xA0, 0x84, 0xBC, 0xD7, 0x3E, 0xA8, 0x27, 0x74, 0x7D, 0xC2, + 0x30, 0x4A, 0x08, 0x78, 0xFF, 0x55, 0xA6, 0xE8, 0xA3, 0xA3, 0x5C, 0xBB, + 0x7C, 0x7E, 0x8B, 0x80, 0x25, 0x07, 0x62, 0xD6, 0xF4, 0x57, 0xD7, 0xE6, + 0xBC, 0x96, 0x31, 0x33, 0xFD, 0x70, 0xE3, 0xD9, 0x0B, 0x67, 0x3E, 0x5A, + 0x8E, 0x67, 0x96, 0x25, 0x81, 0xCE, 0x0F, 0xBD, 0x3A, 0xA6, 0x37, 0x83, + 0xCB, 0xC5, 0xBC, 0x12, 0xC0, 0xE0, 0x00, 0x5B, 0xB2, 0x16, 0x8D, 0x46, + 0xD1, 0xF8, 0x58, 0x14, 0x45, 0x2A, 0xCA, 0xF1, 0xFA, 0x8C, 0xB8, 0xD0, + 0x0A, 0x29, 0xC5, 0xBE, 0xD5, 0x96, 0xB5, 0x3B, 0xB1, 0x74, 0x7C, 0xBC, + 0xA4, 0x72, 0x1D, 0x53, 0x0B, 0xFB, 0x01, 0xDF, 0x72, 0x44, 0xA0, 0x42, + 0x85, 0xCA, 0x53, 0xA3, 0xA4, 0xB9, 0x5C, 0xC8, 0x6D, 0x6D, 0x6C, 0xB9, + 0x9E, 0x09, 0xE7, 0x60, 0x2C, 0xD1, 0xC7, 0xE9, 0xA2, 0x3A, 0xFD, 0x07, + 0x27, 0xE1, 0xBA, 0xCB, 0x1E, 0xFB, 0x68, 0x29, 0x7E, 0x5A, 0xF5, 0x48, + 0x29, 0xBA, 0xE7, 0xFA, 0x61, 0x4B, 0xD6, 0x2A, 0xA5, 0xC8, 0x11, 0xA6, + 0x44, 0xD6, 0xEE, 0xF7, 0x73, 0x51, 0xBE, 0x6D, 0x40, 0x92, 0xB1, 0xA7, + 0x93, 0xC8, 0x03, 0xC9, 0xF9, 0xEA, 0x05, 0xB2, 0x76, 0xFD, 0x07, 0xEE, + 0xD7, 0x3C, 0xA3, 0xDF, 0x84, 0x6B, 0xDC, 0x16, 0x61, 0x0B, 0x59, 0x9B, + 0xAA, 0x2D, 0x95, 0x16, 0x65, 0x87, 0xDE, 0x2F, 0x41, 0xC5, 0x6A, 0xD9, + 0xCB, 0xD0, 0x5E, 0xC7, 0x2B, 0xA6, 0xC5, 0xEE, 0xC7, 0x64, 0xC9, 0xBD, + 0xAA, 0x36, 0xA9, 0x63, 0xC9, 0x80, 0x57, 0x51, 0x32, 0x02, 0x5B, 0x7A, + 0x2C, 0xA3, 0x2C, 0x9F, 0x93, 0xF4, 0x36, 0x7C, 0x75, 0xD9, 0xD2, 0x02, + 0x0C, 0x4C, 0x98, 0x76, 0x7D, 0x97, 0xF8, 0x03, 0xD3, 0x53, 0x24, 0xA4, + 0x2E, 0xA6, 0xCC, 0x5F, 0x98, 0x8F, 0x4B, 0x58, 0x70, 0xFF, 0x41, 0x98, + 0xC3, 0x75, 0x8A, 0x37, 0x86, 0x10, 0xAA, 0xD4, 0xAC, 0xC3, 0x4B, 0x35, + 0x98, 0xB0, 0xE8, 0x98, 0xAE, 0x30, 0x3D, 0x4F, 0xA2, 0x70, 0xCD, 0x94, + 0x66, 0x49, 0xE0, 0xB8, 0x16, 0xEB, 0xA3, 0xF2, 0xF4, 0x91, 0xA4, 0x0F, + 0xA3, 0x42, 0xCB, 0x96, 0x43, 0x12, 0xEA, 0x93, 0x21, 0x9B, 0x02, 0x73, + 0xD8, 0x68, 0x39, 0xA9, 0x1D, 0xFA, 0x8D, 0x55, 0xD2, 0xE3, 0xF1, 0x7D, + 0xD1, 0xCD, 0x33, 0x63, 0x51, 0xFC, 0x15, 0x0D, 0xCB, 0xBF, 0xC0, 0xE4, + 0x3D, 0x40}; +const uint8_t g_zhTW_Locale[] = { + 0x78, 0x9C, 0xED, 0x57, 0xCD, 0x4F, 0xD4, 0x40, 0x14, 0x3F, 0x63, 0xE2, + 0xFF, 0x30, 0x69, 0x20, 0xD5, 0x04, 0xA8, 0x1E, 0x21, 0xA5, 0xC9, 0xC6, + 0x45, 0x30, 0x58, 0x42, 0xEC, 0x46, 0x22, 0x17, 0x33, 0xDB, 0x0E, 0xDB, + 0xC2, 0xB6, 0x43, 0x66, 0xDB, 0xC0, 0xF6, 0x24, 0x12, 0x14, 0x14, 0x62, + 0xA2, 0xC4, 0x8F, 0x80, 0xE1, 0x64, 0x3C, 0x28, 0x89, 0x07, 0x0F, 0x2C, + 0x51, 0xFF, 0x1A, 0x76, 0x39, 0xFA, 0x2F, 0x38, 0xD3, 0x2F, 0xFA, 0xB1, + 0xB3, 0xD4, 0xC4, 0xA3, 0x7B, 0x9A, 0xF7, 0xDE, 0xEF, 0xF7, 0xE6, 0xBD, + 0xDF, 0xBC, 0x7D, 0xD9, 0x95, 0x9B, 0x58, 0x87, 0x4D, 0x04, 0x1C, 0x68, + 0xA3, 0x29, 0xC1, 0x37, 0x1F, 0xD7, 0x16, 0x05, 0x60, 0xA0, 0x96, 0x3E, + 0x25, 0x9C, 0x9F, 0x9E, 0xF4, 0xDE, 0x3E, 0xBF, 0x71, 0xD1, 0xD9, 0x3C, + 0xFF, 0xF9, 0xE6, 0xF7, 0x8F, 0xBD, 0xEE, 0xAB, 0x6F, 0xBD, 0xCE, 0xAF, + 0x9B, 0x82, 0x72, 0xFD, 0x1A, 0x00, 0x32, 0x63, 0x39, 0x06, 0x24, 0x5A, + 0xDB, 0xAE, 0xE3, 0x66, 0x2B, 0x4A, 0xD0, 0x20, 0xA8, 0x81, 0x89, 0x05, + 0x1D, 0x86, 0x1A, 0x02, 0xB2, 0x8D, 0x1D, 0xD7, 0x9C, 0xA7, 0xA1, 0x16, + 0xB3, 0x87, 0x42, 0x5B, 0x39, 0x3F, 0x7D, 0xD2, 0x3B, 0xDA, 0x91, 0xA5, + 0xD0, 0x4A, 0x07, 0xCE, 0xF6, 0x38, 0x81, 0xD3, 0xDD, 0xFE, 0x81, 0xEE, + 0xE1, 0x21, 0x2F, 0xD5, 0x01, 0x87, 0xB1, 0x7D, 0xC2, 0xBB, 0x63, 0x8B, + 0xC7, 0xF8, 0xC2, 0x61, 0x74, 0x3E, 0x72, 0x18, 0xFB, 0x9B, 0xDC, 0x00, + 0xB7, 0x79, 0x16, 0xCB, 0xF7, 0x0F, 0xA2, 0x73, 0x22, 0x61, 0x5A, 0x52, + 0x00, 0xEB, 0x75, 0x32, 0x25, 0xDC, 0x16, 0xFE, 0x6B, 0xFB, 0x8F, 0xB4, + 0x35, 0x60, 0x3B, 0x35, 0xAC, 0xD4, 0x52, 0x7A, 0xEF, 0x8F, 0x7B, 0x47, + 0xC7, 0xBD, 0x77, 0x9F, 0x64, 0x89, 0x99, 0x39, 0x3F, 0xBD, 0xAF, 0xBF, + 0xFF, 0x6C, 0x8F, 0x83, 0xDF, 0xED, 0xEB, 0xA7, 0x4A, 0x73, 0xF2, 0x1C, + 0xF4, 0xC7, 0x6F, 0x9F, 0x24, 0x7E, 0x10, 0x9C, 0xFA, 0x34, 0x91, 0x1B, + 0x8F, 0x80, 0x5D, 0xE8, 0xA3, 0xD8, 0x41, 0xB1, 0xF6, 0x62, 0xD5, 0xC5, + 0x7A, 0x8B, 0x95, 0x0E, 0xAC, 0xD1, 0x46, 0xC4, 0x32, 0x2C, 0x64, 0xA7, + 0x57, 0x43, 0xE4, 0xA2, 0xD7, 0xBD, 0xE8, 0xEE, 0xB3, 0x87, 0x8A, 0x1D, + 0xF9, 0xF0, 0xCB, 0x42, 0x18, 0x5C, 0x9A, 0xA9, 0x4B, 0x10, 0x81, 0xA9, + 0xFC, 0xD4, 0xA2, 0x35, 0x7D, 0xED, 0x6E, 0x6F, 0x75, 0x77, 0xF7, 0x65, + 0x89, 0x99, 0x39, 0x7F, 0xE2, 0x04, 0xC1, 0x29, 0xE6, 0xD2, 0x65, 0x27, + 0xE5, 0xB6, 0x5D, 0xE8, 0x35, 0xA0, 0x8B, 0x16, 0xA0, 0xEB, 0x22, 0xE2, + 0x24, 0xD2, 0x27, 0x9E, 0x68, 0x21, 0x2E, 0x7B, 0xCD, 0xA6, 0xA0, 0x3C, + 0xA2, 0x1F, 0xB1, 0xDB, 0xF9, 0x2E, 0xAA, 0x22, 0x9D, 0x41, 0xB1, 0x2A, + 0xD2, 0x87, 0x10, 0xA7, 0xE9, 0x87, 0xE9, 0x92, 0x50, 0x78, 0x39, 0x9A, + 0xD8, 0x69, 0x70, 0x72, 0x94, 0xE2, 0xDB, 0xC8, 0x08, 0xE9, 0x92, 0x2A, + 0x55, 0x4B, 0x31, 0x5A, 0x26, 0x26, 0x2E, 0x9F, 0x03, 0x40, 0xC6, 0x13, + 0xC9, 0xE1, 0x5A, 0x76, 0x4E, 0x8E, 0x94, 0x27, 0x23, 0x47, 0xC5, 0x34, + 0xC5, 0xDE, 0x87, 0xA7, 0xA2, 0xAA, 0x8A, 0xDD, 0x9D, 0x67, 0xA2, 0xA6, + 0x89, 0x17, 0x9F, 0x5F, 0x8B, 0x60, 0x49, 0x96, 0x52, 0x0C, 0x5E, 0x8A, + 0x50, 0x8D, 0xFE, 0x29, 0x4A, 0x25, 0x08, 0xE4, 0xA8, 0x00, 0x73, 0x52, + 0x55, 0x27, 0x35, 0xAD, 0x14, 0x25, 0xD2, 0x23, 0x24, 0xE5, 0x19, 0x4C, + 0x8D, 0x5C, 0xEF, 0xD1, 0x70, 0xD4, 0xA8, 0x37, 0x9E, 0x98, 0x19, 0xE8, + 0xAC, 0xAC, 0xCE, 0xDA, 0x2D, 0x6D, 0xBA, 0x7A, 0x77, 0x7D, 0x71, 0xC3, + 0x9C, 0xF3, 0x97, 0x42, 0x11, 0xD3, 0xA0, 0x80, 0xE9, 0x78, 0x76, 0x1D, + 0x91, 0xAC, 0x92, 0x19, 0x5F, 0x54, 0x14, 0xF5, 0xD1, 0x99, 0xD7, 0x05, + 0xC5, 0x1F, 0xF5, 0xFD, 0x89, 0x71, 0xDF, 0xF7, 0x65, 0x29, 0x83, 0xE3, + 0x53, 0x75, 0x8F, 0x10, 0xE4, 0xE8, 0x6D, 0x41, 0x19, 0x0E, 0xC9, 0x13, + 0x13, 0xA5, 0xB9, 0x6B, 0x88, 0xE8, 0xC8, 0x71, 0xA3, 0x6B, 0x47, 0x8A, + 0x3C, 0xA6, 0x47, 0xA1, 0x87, 0xA4, 0xAF, 0xCB, 0x56, 0x87, 0xB2, 0xAE, + 0x28, 0xBD, 0x81, 0x74, 0xCB, 0x86, 0x74, 0x48, 0xC6, 0xE3, 0x2C, 0x61, + 0x98, 0x4B, 0x68, 0x10, 0xEC, 0xAD, 0x59, 0x6C, 0x26, 0x46, 0x4B, 0x32, + 0x92, 0x0E, 0x46, 0x4A, 0x12, 0x6C, 0xCB, 0xF1, 0x5A, 0x82, 0x32, 0x56, + 0x12, 0xEE, 0x23, 0x82, 0x05, 0xE5, 0x56, 0x01, 0x7D, 0x29, 0x4C, 0xE6, + 0xBD, 0xE3, 0xC7, 0xC8, 0x28, 0x93, 0x75, 0xC6, 0x63, 0x18, 0x18, 0x82, + 0x32, 0x5F, 0x1B, 0xA6, 0x2B, 0x29, 0x83, 0x18, 0xC0, 0xB2, 0x5A, 0x98, + 0x1D, 0x04, 0xA5, 0xB6, 0x58, 0xFD, 0x0B, 0x5A, 0xFA, 0x21, 0x0A, 0xA4, + 0x60, 0x27, 0x16, 0xEA, 0x66, 0x4B, 0xA0, 0xBD, 0x86, 0x96, 0xA1, 0x1E, + 0xAF, 0xE0, 0xD8, 0x8C, 0x72, 0x56, 0x0C, 0x5C, 0x47, 0x40, 0xA5, 0xAF, + 0x05, 0x34, 0xD7, 0x00, 0xF7, 0x05, 0xA9, 0x2F, 0x4C, 0x6D, 0xD3, 0x9F, + 0x90, 0x06, 0x58, 0xA0, 0x32, 0x72, 0x00, 0x96, 0x63, 0x61, 0x67, 0x00, + 0xE0, 0x0E, 0xF6, 0x88, 0x85, 0x08, 0xBB, 0x85, 0x83, 0x08, 0x4B, 0x59, + 0xB0, 0xAE, 0x84, 0xCC, 0xA2, 0x3A, 0x41, 0xEB, 0x03, 0x21, 0x15, 0x02, + 0xEB, 0xF4, 0x8B, 0x38, 0x08, 0x52, 0x33, 0xA1, 0xC5, 0x01, 0xCC, 0x61, + 0xDF, 0x5B, 0x85, 0x60, 0x06, 0xBB, 0xA6, 0xA5, 0xB3, 0x9E, 0xC6, 0x1E, + 0xDE, 0x03, 0xEA, 0x60, 0x30, 0x15, 0x40, 0x37, 0x71, 0x0C, 0x7E, 0x30, + 0xF0, 0x6A, 0x0D, 0x5F, 0x21, 0x77, 0xF4, 0x2A, 0x6D, 0xCF, 0x69, 0xAC, + 0xE0, 0x00, 0x19, 0xDE, 0x1E, 0x2C, 0xB6, 0xD4, 0x7B, 0xCA, 0x52, 0xF8, + 0x67, 0x41, 0xF9, 0x03, 0x11, 0xC2, 0x4A, 0xC9}; +const uint8_t g_zhHK_Locale[] = { + 0x78, 0x9C, 0xA5, 0x57, 0x4D, 0x4F, 0x13, 0x41, 0x18, 0x3E, 0x63, 0xE2, + 0x7F, 0x98, 0x6C, 0x20, 0x0B, 0x09, 0x50, 0x8A, 0x9F, 0x25, 0xCB, 0x26, + 0x44, 0x90, 0x9A, 0x5A, 0x43, 0x2C, 0xD1, 0xC8, 0xC5, 0x6C, 0x77, 0x87, + 0xEE, 0x42, 0x77, 0x87, 0x4C, 0xB7, 0xC1, 0x6E, 0x3C, 0x88, 0x04, 0xA5, + 0x5A, 0x2E, 0x4A, 0x54, 0x02, 0x86, 0x78, 0x50, 0x0F, 0x48, 0xBC, 0x78, + 0x68, 0x89, 0xC6, 0x3F, 0x43, 0x8B, 0x9E, 0xFC, 0x0B, 0xCE, 0xEC, 0x17, + 0xFB, 0x35, 0x6D, 0x8D, 0x3D, 0xCD, 0xFB, 0xBC, 0xCF, 0xF3, 0xCE, 0xFB, + 0x3E, 0x33, 0x3B, 0x01, 0xA1, 0x8C, 0x64, 0xA9, 0x0C, 0x81, 0x21, 0xE9, + 0x70, 0x9A, 0xB3, 0xD4, 0x87, 0xD9, 0x1C, 0x07, 0x14, 0x58, 0x91, 0xA7, + 0xB9, 0xD3, 0xE6, 0x71, 0xE7, 0xCD, 0xF3, 0xE1, 0xB3, 0xD6, 0xC6, 0xE9, + 0x8F, 0xD7, 0x7F, 0xBE, 0x37, 0x7E, 0x7F, 0xDA, 0xEB, 0x34, 0xBF, 0x9E, + 0xD5, 0x5B, 0xED, 0xED, 0xA3, 0x5F, 0x1F, 0x1A, 0x9D, 0xDD, 0x9F, 0xED, + 0xC6, 0xC9, 0x08, 0x27, 0x5E, 0xBC, 0x00, 0x80, 0x40, 0x8B, 0x18, 0x8A, + 0x84, 0x0B, 0x35, 0xBD, 0x88, 0xCA, 0x15, 0xB7, 0x5E, 0x09, 0xC3, 0x12, + 0xC2, 0x9A, 0x64, 0x50, 0xD6, 0x00, 0x10, 0x74, 0x64, 0x98, 0xEA, 0x1D, + 0x92, 0xAA, 0xD0, 0x78, 0xC0, 0x89, 0xC5, 0xD3, 0xE6, 0x93, 0xCE, 0xC1, + 0xB6, 0x90, 0x72, 0xA2, 0x60, 0xE2, 0xA4, 0xC1, 0x48, 0x34, 0xEB, 0xC9, + 0x89, 0xF6, 0xFE, 0x3E, 0xAB, 0xD4, 0x2E, 0x43, 0xB1, 0x75, 0xCC, 0xDA, + 0x63, 0x93, 0xA5, 0x38, 0x62, 0x28, 0x5A, 0xEF, 0x19, 0x8A, 0x9D, 0x0D, + 0x66, 0x82, 0x39, 0x3C, 0xCD, 0x45, 0xE7, 0x07, 0xEE, 0xDA, 0xB7, 0x30, + 0x68, 0x29, 0x90, 0x8A, 0x45, 0x3C, 0xCD, 0xA5, 0xB9, 0x60, 0x95, 0x74, + 0x72, 0xF1, 0xC9, 0x64, 0xF8, 0x52, 0x32, 0x7C, 0x39, 0x19, 0xBE, 0x92, + 0x0C, 0x5F, 0x4D, 0x86, 0xAF, 0x25, 0xC3, 0xD7, 0x93, 0xE1, 0x4C, 0x32, + 0x9C, 0x9E, 0x60, 0xE0, 0x8C, 0x39, 0xD3, 0x93, 0x3D, 0x0D, 0x54, 0xA4, + 0x5A, 0xE0, 0x46, 0x92, 0x48, 0xEC, 0xBC, 0x3B, 0xEC, 0x1C, 0x1C, 0x76, + 0xDE, 0x7E, 0x14, 0x52, 0x34, 0x8C, 0xE0, 0xE4, 0xC0, 0x92, 0xF1, 0x93, + 0x06, 0x83, 0x5F, 0x4F, 0xC4, 0xC9, 0x55, 0x65, 0xD4, 0xD9, 0x4D, 0xE6, + 0x6F, 0x1D, 0xFB, 0x38, 0xB0, 0x57, 0x09, 0x43, 0x44, 0xEE, 0x80, 0xAD, + 0x8E, 0xCD, 0x11, 0x9F, 0x20, 0xDE, 0x7B, 0xBC, 0xEB, 0x78, 0xBF, 0xF1, + 0x4E, 0xBB, 0xF6, 0xA8, 0x43, 0xAC, 0x29, 0x1A, 0xD4, 0x83, 0xDF, 0xBF, + 0x0B, 0x91, 0xED, 0x5E, 0xB4, 0x77, 0xE8, 0x41, 0x79, 0x40, 0x34, 0xFD, + 0x32, 0x96, 0x06, 0xE7, 0x61, 0x60, 0x13, 0x88, 0xA5, 0x40, 0x7D, 0x12, + 0x91, 0x9E, 0xBE, 0xB4, 0xB7, 0x36, 0xDB, 0xF5, 0x1D, 0x21, 0x45, 0xC3, + 0x08, 0xEE, 0x83, 0xC0, 0x5E, 0x79, 0x5A, 0xF2, 0xA2, 0xA5, 0x22, 0x4F, + 0x9A, 0x83, 0x2A, 0x92, 0x09, 0x17, 0x24, 0xD3, 0x84, 0xD8, 0xF0, 0xAD, + 0xF7, 0x11, 0xF7, 0xD5, 0x5B, 0xAE, 0x96, 0xCB, 0x9C, 0xF8, 0x80, 0xFC, + 0xF8, 0x76, 0xEB, 0x1B, 0x9F, 0xE7, 0xC9, 0x1D, 0xE4, 0x67, 0x79, 0x72, + 0x10, 0x3C, 0x98, 0x23, 0x3F, 0x6A, 0x8C, 0xAF, 0x61, 0x15, 0x29, 0x23, + 0xA3, 0xC4, 0x28, 0xD2, 0x97, 0x5E, 0x87, 0xCA, 0xFF, 0xC8, 0x2B, 0x2A, + 0xC2, 0x26, 0x2D, 0xD0, 0x53, 0x0E, 0x40, 0x08, 0x71, 0x7D, 0x32, 0x35, + 0x3D, 0xE2, 0x53, 0x00, 0x09, 0xF9, 0x34, 0xA3, 0xAA, 0x7C, 0x67, 0xEF, + 0x29, 0x9F, 0xCF, 0xF3, 0xED, 0xED, 0x67, 0x7C, 0xA1, 0xC0, 0x9F, 0x7D, + 0x7E, 0xC5, 0x83, 0x25, 0x21, 0x15, 0x50, 0xB0, 0x4A, 0x38, 0x2E, 0x25, + 0x97, 0xE8, 0xAB, 0x80, 0x6D, 0x13, 0xD1, 0x4F, 0xE5, 0xF3, 0x53, 0x85, + 0x42, 0x5F, 0x12, 0xD7, 0x9A, 0x19, 0xAA, 0x89, 0x0A, 0xA8, 0x19, 0x91, + 0xD1, 0xDD, 0x4B, 0xB3, 0x48, 0x50, 0xEF, 0x26, 0xCD, 0x4B, 0xC6, 0xCA, + 0x6A, 0x56, 0xAF, 0x14, 0xE6, 0x66, 0x6F, 0xAE, 0xDF, 0x7F, 0xA4, 0xE6, + 0xAC, 0x25, 0xC7, 0xC3, 0x20, 0xC9, 0x56, 0x1A, 0x55, 0xBD, 0x08, 0x71, + 0xD8, 0xC8, 0x10, 0xE6, 0xF6, 0x44, 0x30, 0xF2, 0x2D, 0xC8, 0x9C, 0x68, + 0x8D, 0x5A, 0x56, 0x66, 0xDC, 0xB2, 0x2C, 0x21, 0x15, 0xE2, 0xB1, 0xA5, + 0x72, 0x15, 0x63, 0x68, 0xC8, 0x35, 0x4E, 0x1C, 0x74, 0xC4, 0x99, 0xCC, + 0xE3, 0x61, 0x7F, 0x39, 0xD2, 0x77, 0x9D, 0x35, 0x88, 0x65, 0x68, 0x98, + 0x6E, 0x0B, 0x43, 0x71, 0x1D, 0xF5, 0x26, 0x36, 0x8F, 0x3F, 0xE3, 0xF9, + 0xD8, 0x03, 0x61, 0xC8, 0x2D, 0xAF, 0x40, 0x59, 0xD3, 0x25, 0x72, 0x5F, + 0xC6, 0xBD, 0x2A, 0x4E, 0x9A, 0x29, 0x28, 0x61, 0x54, 0x5D, 0xD3, 0xE8, + 0xF5, 0x18, 0xED, 0x53, 0xE1, 0x4F, 0x30, 0xD4, 0xA7, 0x40, 0xD7, 0x8C, + 0x6A, 0x85, 0x13, 0xC7, 0xFA, 0xA4, 0x5B, 0x10, 0x23, 0x4E, 0x9C, 0x88, + 0xB1, 0xCF, 0x8D, 0x09, 0x9D, 0xBD, 0x77, 0x30, 0x21, 0x67, 0xC2, 0xA0, + 0x77, 0x23, 0xED, 0x80, 0x13, 0xB3, 0xB9, 0x41, 0xF2, 0x6C, 0x85, 0x18, + 0x5D, 0x54, 0x5A, 0x05, 0xD1, 0x05, 0x95, 0xCD, 0xFE, 0x83, 0x2C, 0x78, + 0x10, 0x31, 0x91, 0xFD, 0x6E, 0xC6, 0xFA, 0xA6, 0xEF, 0x41, 0x6D, 0x0D, + 0x2E, 0x4B, 0xB2, 0xF7, 0x4C, 0x7B, 0xA1, 0x5B, 0x73, 0x46, 0x41, 0x45, + 0x08, 0xF2, 0xE4, 0xB4, 0x40, 0xC1, 0x54, 0xC0, 0x6D, 0x2E, 0x95, 0x48, + 0xCB, 0xD7, 0xC8, 0xDF, 0x92, 0x0A, 0x58, 0x20, 0x36, 0x32, 0x08, 0x9A, + 0xA1, 0x21, 0xA3, 0x0B, 0xE1, 0x06, 0xAA, 0x62, 0x0D, 0x62, 0xBA, 0x0B, + 0x83, 0xE1, 0xB4, 0xB2, 0xA0, 0xF5, 0xA4, 0x64, 0x61, 0x11, 0xC3, 0xF5, + 0xAE, 0x94, 0x19, 0x2C, 0x15, 0xC9, 0x47, 0xD9, 0x8D, 0xB2, 0xA8, 0x4A, + 0x1A, 0x83, 0x90, 0x43, 0x56, 0x75, 0x55, 0x02, 0xF3, 0xC8, 0x54, 0x35, + 0x99, 0xCE, 0x34, 0x76, 0xEF, 0x16, 0xC8, 0x77, 0x27, 0x13, 0x03, 0x64, + 0x15, 0x79, 0xE4, 0xBB, 0x5D, 0xB7, 0x2E, 0xA0, 0x1E, 0x76, 0xBB, 0xA7, + 0x52, 0xAB, 0x1A, 0xA5, 0x15, 0x64, 0x33, 0x9D, 0xDD, 0xED, 0x47, 0x2E, + 0x70, 0x9E, 0x42, 0xCA, 0xF9, 0x27, 0x42, 0xFC, 0x0B, 0xD9, 0x0E, 0x4B, + 0xED}; +const uint8_t g_jaJP_Locale[] = { + 0x78, 0x9C, 0xED, 0x56, 0xCB, 0x6E, 0xD3, 0x40, 0x14, 0x5D, 0x17, 0x89, + 0x7F, 0x18, 0x59, 0x20, 0x83, 0xD4, 0xD6, 0x0D, 0xEF, 0x56, 0xAE, 0xA5, + 0x8A, 0x96, 0x86, 0x16, 0xA3, 0x08, 0x57, 0xA0, 0x76, 0x83, 0x26, 0xF6, + 0x34, 0x99, 0x36, 0x9E, 0xA9, 0x26, 0xB6, 0x4A, 0xBC, 0xE2, 0x21, 0x20, + 0x48, 0x74, 0x01, 0x1B, 0x04, 0x44, 0x62, 0x55, 0x40, 0x02, 0x04, 0x8B, + 0x6E, 0xD8, 0xD0, 0xAF, 0x49, 0x5A, 0x56, 0xFC, 0x02, 0x33, 0x7E, 0xC5, + 0x8E, 0xED, 0xE0, 0xEE, 0xF1, 0x22, 0x99, 0x7B, 0x7C, 0xCE, 0xF5, 0xBD, + 0xE7, 0x8E, 0x47, 0x56, 0x5B, 0xD4, 0x84, 0x2D, 0x04, 0x08, 0xB4, 0xD1, + 0xBC, 0xB4, 0x05, 0xEF, 0xAF, 0xD4, 0x24, 0x60, 0xA1, 0xB6, 0x39, 0x2F, + 0x0D, 0xDE, 0xEC, 0x1F, 0x7F, 0xFF, 0x76, 0x8E, 0xFF, 0x0D, 0x7A, 0x5F, + 0xCF, 0x4B, 0xDA, 0xE9, 0x53, 0x00, 0xA8, 0x82, 0x4C, 0x2C, 0xC8, 0x8C, + 0x8E, 0x5D, 0xA7, 0xAD, 0x76, 0xA8, 0x6B, 0x30, 0xD4, 0xA0, 0x0C, 0x43, + 0x22, 0x58, 0x13, 0x40, 0xB5, 0x29, 0x71, 0x9A, 0xB7, 0xF9, 0xAD, 0xB6, + 0x88, 0x27, 0x82, 0x58, 0xAB, 0x0C, 0x7A, 0x5D, 0x55, 0x09, 0xD6, 0x09, + 0xF8, 0x42, 0x3E, 0x7C, 0x31, 0x1F, 0xBE, 0x94, 0x0F, 0x5F, 0xCE, 0x87, + 0xAF, 0xE4, 0xC3, 0x57, 0xF3, 0xE1, 0x6B, 0xF9, 0xF0, 0x6C, 0x3E, 0x5C, + 0x99, 0x29, 0xC0, 0x0B, 0xFA, 0xAC, 0x8C, 0x34, 0x0A, 0xC2, 0x75, 0xEC, + 0x53, 0xD2, 0x37, 0x00, 0xEB, 0x75, 0x36, 0x2F, 0x55, 0xA4, 0xFF, 0x06, + 0x9E, 0xC4, 0x40, 0x0B, 0x76, 0x12, 0xDB, 0x8E, 0x47, 0x9A, 0xD8, 0xBE, + 0xEF, 0x7B, 0xFC, 0x57, 0x55, 0x44, 0x38, 0xC4, 0x7B, 0xDD, 0x5C, 0xFC, + 0xE8, 0xD1, 0x97, 0x7C, 0xFE, 0x8F, 0x83, 0x82, 0x3C, 0x9F, 0x73, 0xF1, + 0xDF, 0xCF, 0x5F, 0xE5, 0xE2, 0xFD, 0xDE, 0x87, 0x11, 0x1C, 0xF8, 0xAB, + 0x9C, 0x26, 0x46, 0xF6, 0x40, 0xD8, 0x4D, 0xB6, 0x8F, 0x6C, 0x07, 0xD9, + 0xDA, 0xB3, 0x55, 0x67, 0xEB, 0xCD, 0x56, 0x5A, 0x5C, 0xA3, 0x8D, 0x18, + 0xB6, 0x30, 0xB2, 0x93, 0x2F, 0x79, 0x08, 0x69, 0xFD, 0xBD, 0x6E, 0xFF, + 0xC5, 0x1E, 0x1F, 0x4E, 0x04, 0x64, 0x6F, 0xFF, 0x7A, 0x99, 0xBE, 0x0D, + 0x86, 0x61, 0xE2, 0x21, 0x88, 0xC1, 0x44, 0x7E, 0x1E, 0x69, 0x47, 0x07, + 0x0F, 0xFB, 0x4F, 0x9F, 0xF8, 0xD9, 0x45, 0x18, 0xE3, 0xC7, 0xFB, 0x87, + 0x83, 0x77, 0x1F, 0x63, 0x10, 0xF8, 0xAB, 0x48, 0xCB, 0x8F, 0x2D, 0x65, + 0xE4, 0xDC, 0x0A, 0x50, 0x0B, 0x3A, 0xA8, 0x06, 0x1D, 0x07, 0x31, 0x12, + 0x5B, 0x1F, 0x23, 0xE1, 0xD1, 0xB6, 0xE9, 0xB6, 0x5A, 0x92, 0xB6, 0xCE, + 0x2F, 0xB9, 0xFF, 0xF3, 0x40, 0xD6, 0x65, 0x6E, 0xB8, 0xBC, 0x28, 0xF3, + 0x41, 0xC8, 0x4B, 0xFC, 0x12, 0xBE, 0xC4, 0x92, 0xA2, 0x1C, 0x2D, 0x4A, + 0x1A, 0x05, 0x39, 0x4A, 0xE9, 0x6D, 0x64, 0x05, 0x72, 0x45, 0xD7, 0x95, + 0xC5, 0xC5, 0x52, 0x9A, 0x76, 0x93, 0x32, 0x47, 0xA8, 0xF2, 0x35, 0x00, + 0xA4, 0x90, 0xD0, 0x10, 0x07, 0xDB, 0x23, 0x86, 0x24, 0x90, 0x94, 0x21, + 0x55, 0x79, 0xF0, 0xF6, 0xB1, 0xAC, 0xEB, 0x72, 0xBF, 0xFB, 0x4C, 0x36, + 0x0C, 0xF9, 0xE8, 0xD3, 0x6B, 0x79, 0x43, 0x55, 0x12, 0xF4, 0x22, 0x7D, + 0x60, 0x46, 0x75, 0x4E, 0xD7, 0xE7, 0x0C, 0x63, 0xAE, 0x9C, 0xC6, 0x37, + 0x20, 0x94, 0x94, 0x12, 0x84, 0xDD, 0x0B, 0xC9, 0x28, 0x5F, 0x74, 0x3E, + 0xD2, 0x67, 0xB8, 0x15, 0xD6, 0x38, 0x1A, 0xED, 0x8F, 0x65, 0x48, 0xB6, + 0xB6, 0xAB, 0x76, 0xDB, 0x58, 0x5A, 0xBC, 0xB1, 0x7B, 0xEF, 0x41, 0x73, + 0xD5, 0xDB, 0x08, 0x0C, 0x4B, 0x92, 0x7C, 0x25, 0x71, 0xED, 0x3A, 0x62, + 0x69, 0xD7, 0x52, 0x58, 0x58, 0x12, 0xC7, 0xF8, 0x0E, 0x37, 0x25, 0xCD, + 0x9B, 0xF4, 0xBC, 0xD9, 0x69, 0xCF, 0xF3, 0x54, 0x25, 0xC5, 0x2B, 0x96, + 0x9A, 0x2E, 0x63, 0x88, 0x98, 0x1D, 0x49, 0x3B, 0xE3, 0x8B, 0x4B, 0x0B, + 0x77, 0x10, 0x33, 0x11, 0x71, 0xC2, 0x67, 0x9E, 0xCD, 0xEA, 0x84, 0x19, + 0x99, 0x06, 0xE2, 0xA6, 0x86, 0x7D, 0x4E, 0xA4, 0xA1, 0x30, 0xBD, 0x85, + 0x4C, 0x6C, 0x43, 0xBE, 0x1B, 0xA6, 0xA3, 0x2C, 0xC1, 0xED, 0x42, 0x41, + 0x83, 0x51, 0x77, 0x07, 0x8B, 0xF9, 0x4F, 0x96, 0x54, 0xC4, 0x1D, 0x9C, + 0x2D, 0x29, 0xB0, 0x31, 0x71, 0xDB, 0x92, 0x36, 0x55, 0x92, 0xEE, 0x21, + 0x46, 0x25, 0x6D, 0x26, 0xC3, 0x1E, 0x1A, 0x93, 0x1A, 0x76, 0x34, 0x89, + 0x94, 0x33, 0x69, 0x30, 0xDA, 0x81, 0x7E, 0x20, 0x69, 0x7F, 0x0E, 0xF9, + 0x89, 0x9D, 0x66, 0x8C, 0x51, 0xE1, 0x36, 0x15, 0x0B, 0x49, 0x5B, 0xA9, + 0xAD, 0x9F, 0x40, 0x96, 0x1C, 0x44, 0x46, 0xE4, 0x1F, 0x7F, 0x99, 0xBA, + 0xC5, 0xDB, 0xDE, 0xD9, 0x41, 0x9B, 0xD0, 0x8C, 0x4E, 0xDB, 0x28, 0x0C, + 0x73, 0xAE, 0x52, 0xCF, 0xDD, 0x86, 0x60, 0x99, 0x3A, 0x4D, 0x6C, 0x82, + 0x1A, 0xA3, 0x53, 0x77, 0x6F, 0x02, 0x5D, 0x52, 0xC6, 0x91, 0x75, 0x4C, + 0xCC, 0x26, 0x8D, 0xC8, 0x77, 0x0A, 0xC8, 0x7A, 0x87, 0x7F, 0x2A, 0x5A, + 0x82, 0x55, 0x44, 0xC0, 0x04, 0x53, 0x32, 0x86, 0x70, 0x9D, 0xBA, 0x0C, + 0x23, 0x06, 0x0C, 0xC7, 0x2A, 0x60, 0x2C, 0x58, 0xB4, 0x8E, 0x40, 0x0D, + 0xFF, 0x93, 0x52, 0x45, 0x75, 0x86, 0x76, 0xC7, 0x52, 0x16, 0x18, 0xAC, + 0xF3, 0x17, 0x77, 0x1C, 0x65, 0xAD, 0x09, 0xF1, 0x58, 0x02, 0x6F, 0xA9, + 0x21, 0x6A, 0x01, 0xB7, 0xC6, 0xD2, 0x0C, 0x5A, 0x8A, 0xA6, 0x77, 0x5C, + 0xD2, 0xD8, 0xA2, 0x3E, 0x33, 0x18, 0x89, 0x7F, 0xAA, 0x25, 0xE6, 0xA9, + 0x2A, 0xC1, 0x87, 0xBD, 0xF6, 0x17, 0x6C, 0x42, 0x08, 0x21}; +const uint8_t g_koKR_Locale[] = { + 0x78, 0x9C, 0xED, 0x56, 0x4D, 0x6B, 0xD4, 0x40, 0x18, 0x3E, 0x57, 0xF0, + 0x3F, 0x0C, 0xC1, 0x12, 0x85, 0x76, 0xB7, 0xEB, 0x77, 0x4B, 0x1A, 0x28, + 0x6E, 0x6D, 0x65, 0x8D, 0x94, 0xA6, 0x58, 0xEC, 0x45, 0x66, 0x93, 0xE9, + 0x26, 0xED, 0x26, 0x53, 0x26, 0x09, 0x75, 0x73, 0xAE, 0x52, 0xF0, 0xE2, + 0xA1, 0x87, 0xEA, 0x6E, 0xB1, 0x07, 0x11, 0x2A, 0x88, 0x22, 0x22, 0x1E, + 0x14, 0x7F, 0x8D, 0x62, 0x6D, 0x8A, 0x7F, 0xC1, 0xC9, 0xE7, 0xE6, 0x63, + 0xB2, 0x4D, 0xEF, 0xEE, 0x61, 0x99, 0xF7, 0x99, 0xE7, 0x79, 0xF3, 0xBE, + 0xCF, 0x4C, 0x5E, 0x22, 0x74, 0xB1, 0x02, 0xBB, 0x08, 0x98, 0xD0, 0x40, + 0xB3, 0xDC, 0x26, 0x7E, 0xDC, 0x5A, 0xE6, 0x80, 0x8A, 0x2C, 0x65, 0x96, + 0xFB, 0x35, 0x38, 0x38, 0xFE, 0x34, 0xF8, 0xFD, 0xE1, 0xFD, 0xE5, 0xE3, + 0xD7, 0x47, 0x3F, 0xFB, 0xDF, 0xAF, 0x70, 0xE2, 0xC5, 0x0B, 0x00, 0x08, + 0x3E, 0xDF, 0x54, 0x21, 0x91, 0x7B, 0x46, 0x1B, 0x77, 0xAD, 0x48, 0xDA, + 0x21, 0xA8, 0x83, 0x89, 0x0E, 0x4D, 0x9F, 0x35, 0x06, 0x04, 0x03, 0x9B, + 0xB6, 0xF6, 0x80, 0x6E, 0x59, 0x7E, 0x3C, 0x16, 0xC6, 0x62, 0xC3, 0xEB, + 0xEF, 0x09, 0xF5, 0x70, 0x9D, 0x82, 0xAF, 0xB2, 0xE1, 0x6B, 0x6C, 0xF8, + 0x3A, 0x1B, 0xBE, 0xC1, 0x86, 0x6F, 0xB2, 0xE1, 0x5B, 0x6C, 0xF8, 0x36, + 0x1B, 0x9E, 0x66, 0xC3, 0x8D, 0xA9, 0x12, 0xBC, 0xA4, 0xCF, 0x46, 0xAE, + 0x51, 0x10, 0xAD, 0x13, 0x9F, 0xD2, 0xBE, 0x01, 0xD8, 0x6E, 0x93, 0x59, + 0xAE, 0xC1, 0xFD, 0x37, 0xF0, 0x3C, 0x06, 0xAA, 0xB0, 0x97, 0xBA, 0x76, + 0x34, 0x12, 0xBD, 0x83, 0x6F, 0xDE, 0xAB, 0x3D, 0xFA, 0x2F, 0xD4, 0xFD, + 0x70, 0x88, 0xF7, 0xF7, 0x98, 0xF8, 0xE9, 0x4B, 0x36, 0xEE, 0xED, 0xEE, + 0x33, 0xF1, 0x93, 0x77, 0x47, 0x4C, 0xFC, 0xCF, 0xD7, 0x5D, 0x76, 0xFE, + 0x67, 0x87, 0x39, 0x1C, 0x04, 0x2B, 0x46, 0x13, 0xB9, 0x3B, 0x10, 0x75, + 0x53, 0xEC, 0xA3, 0xD8, 0x41, 0xB1, 0xF6, 0x62, 0xD5, 0xC5, 0x7A, 0x8B, + 0x95, 0x96, 0xD7, 0x68, 0x20, 0xA2, 0xAB, 0x3A, 0x32, 0xD2, 0x2F, 0x79, + 0x04, 0x89, 0xDE, 0xFE, 0x1B, 0xEF, 0x70, 0x87, 0x1E, 0x4E, 0x0C, 0x14, + 0xB6, 0x4F, 0xFB, 0xB9, 0x6D, 0x30, 0x0C, 0x53, 0x0F, 0x41, 0x04, 0xA6, + 0xF2, 0xD3, 0x88, 0x56, 0xF9, 0xD1, 0xEB, 0xBF, 0x08, 0xB2, 0xFB, 0x61, + 0x82, 0x7B, 0x3B, 0x03, 0xBA, 0x95, 0x80, 0x20, 0x58, 0xC5, 0x5A, 0x3A, + 0xB6, 0xEA, 0xB9, 0xB9, 0x15, 0xA2, 0x2A, 0xB4, 0xD1, 0x12, 0xB4, 0x6D, + 0x44, 0xCC, 0xC4, 0xFA, 0x04, 0x89, 0x46, 0xDB, 0xBA, 0xD3, 0xED, 0x72, + 0xE2, 0x23, 0xFA, 0xE3, 0x4F, 0x9E, 0xEE, 0xF0, 0x40, 0xE2, 0xA9, 0xE3, + 0x3C, 0x68, 0xF2, 0xF4, 0x28, 0x78, 0x30, 0x4F, 0x7F, 0xBE, 0x35, 0x89, + 0xAA, 0x2C, 0x4D, 0x17, 0x9B, 0x9D, 0xD2, 0x34, 0x95, 0x32, 0x18, 0x48, + 0x0D, 0x13, 0xD4, 0x80, 0x24, 0xD5, 0x40, 0xB3, 0x59, 0x49, 0x65, 0x69, + 0x98, 0xD8, 0xBE, 0xAE, 0x4C, 0x05, 0x40, 0x06, 0x89, 0x9C, 0xB1, 0x75, + 0x23, 0xE7, 0x4C, 0x0A, 0xC9, 0x38, 0x33, 0x07, 0x34, 0x8D, 0xF7, 0x9E, + 0x0F, 0x68, 0x4B, 0x12, 0x7F, 0xF2, 0x85, 0xB6, 0x26, 0xCB, 0xBC, 0xF7, + 0x79, 0x97, 0x07, 0x6B, 0x42, 0x3D, 0x25, 0x2A, 0xCB, 0x12, 0x1A, 0x53, + 0x9A, 0xA5, 0x52, 0x8E, 0xC0, 0x1A, 0x9A, 0x62, 0x46, 0x92, 0x66, 0x64, + 0xB9, 0x92, 0x24, 0xF2, 0x25, 0x14, 0xE5, 0x15, 0xBE, 0x27, 0x39, 0x07, + 0xA2, 0xDB, 0xB2, 0x42, 0xD1, 0xF8, 0x0A, 0x2D, 0x40, 0x73, 0x63, 0x73, + 0xD1, 0xB0, 0xE4, 0xF9, 0xE6, 0xDD, 0xED, 0xD5, 0x27, 0x5A, 0xCB, 0x5D, + 0x0B, 0xAD, 0x4C, 0x93, 0x02, 0xA5, 0xE9, 0x18, 0x6D, 0x44, 0xB2, 0x7E, + 0x66, 0xB0, 0xA8, 0x28, 0x8A, 0xD1, 0x97, 0x40, 0xE1, 0x44, 0x77, 0xC2, + 0x75, 0xA7, 0x6B, 0xAE, 0xEB, 0x0A, 0xF5, 0x0C, 0xAF, 0x5C, 0xAA, 0x38, + 0x84, 0x20, 0x53, 0xE9, 0x71, 0xE2, 0xA5, 0x40, 0x5C, 0x59, 0xB8, 0x85, + 0x88, 0x82, 0x4C, 0x3B, 0x7A, 0xE6, 0x78, 0x51, 0xE7, 0x9B, 0x51, 0x68, + 0x20, 0x69, 0x6A, 0xD8, 0xE7, 0x58, 0x16, 0x8A, 0xD2, 0xAB, 0x48, 0xD1, + 0x0D, 0x48, 0xEF, 0x49, 0x2D, 0xCE, 0x12, 0x6E, 0x97, 0x0A, 0x3A, 0x04, + 0x3B, 0x5B, 0xBA, 0x7F, 0x27, 0x26, 0x2A, 0x2A, 0x92, 0x0E, 0xC6, 0x2B, + 0x0A, 0x0C, 0xDD, 0x74, 0x2C, 0x4E, 0x9C, 0xAC, 0x48, 0x77, 0x11, 0xC1, + 0x9C, 0x38, 0x55, 0x60, 0x0F, 0x8D, 0xC9, 0x1C, 0x76, 0x7C, 0x12, 0x19, + 0x67, 0xB2, 0x60, 0x7C, 0x07, 0x83, 0x80, 0x13, 0xFF, 0xFE, 0x78, 0x4B, + 0x07, 0x54, 0x86, 0x31, 0x42, 0xA5, 0x5B, 0xD8, 0x5F, 0x70, 0x62, 0x6B, + 0x79, 0xF5, 0x1C, 0xB2, 0xF4, 0x41, 0x14, 0x44, 0xC1, 0x84, 0x2C, 0xD4, + 0xED, 0xCF, 0x81, 0xDE, 0x16, 0x5A, 0x87, 0x4A, 0x3C, 0x90, 0xE3, 0x30, + 0xCA, 0x39, 0xA7, 0xE2, 0x36, 0x02, 0x52, 0xCF, 0x31, 0x3B, 0x1B, 0x18, + 0xC8, 0xB6, 0x0A, 0x24, 0xAE, 0xCE, 0x64, 0x4A, 0x3D, 0xFA, 0x75, 0xA8, + 0x82, 0x25, 0xEA, 0x64, 0x09, 0x41, 0x37, 0x75, 0x6C, 0x8E, 0x20, 0xDC, + 0xC1, 0x0E, 0xD1, 0x11, 0xF1, 0x9F, 0x52, 0xC2, 0x08, 0xAB, 0x59, 0xD2, + 0xCF, 0xA4, 0x2C, 0xA2, 0x36, 0x41, 0xDB, 0x23, 0x29, 0x73, 0x04, 0xB6, + 0xE9, 0x8B, 0x38, 0x8A, 0xB2, 0xA2, 0x41, 0xBD, 0x84, 0xD0, 0xC2, 0xAE, + 0xB3, 0x09, 0xC1, 0x02, 0xB6, 0x35, 0x5D, 0xF1, 0x7B, 0x9A, 0x7C, 0x78, + 0xAF, 0xD4, 0x9A, 0x88, 0x4C, 0x0D, 0x50, 0x34, 0x1C, 0x93, 0x97, 0x47, + 0x3E, 0x9A, 0x72, 0x3B, 0x81, 0xDD, 0xF7, 0x47, 0xD2, 0x64, 0x9C, 0xA1, + 0x05, 0x53, 0x2D, 0x75, 0x9E, 0x42, 0x3D, 0xFC, 0xFC, 0x17, 0xFF, 0x01, + 0xDC, 0xF1, 0x18, 0xD3}; +const uint8_t g_esES_Locale[] = { + 0x78, 0x9C, 0x9D, 0x56, 0xCF, 0x6B, 0xD4, 0x40, 0x14, 0xBE, 0x0B, 0xFE, + 0x0F, 0x21, 0x58, 0x56, 0xA1, 0xDD, 0xD1, 0x63, 0xCB, 0x36, 0x50, 0xDA, + 0xDA, 0x95, 0x1A, 0x59, 0x9A, 0xAA, 0xD8, 0x8B, 0x4C, 0x92, 0xE9, 0xEE, + 0xB4, 0xC9, 0xCC, 0x32, 0x49, 0x2C, 0x9B, 0xA3, 0xE0, 0x41, 0x10, 0x0B, + 0xDE, 0x8A, 0x27, 0x0F, 0x1E, 0x04, 0x8B, 0x77, 0x51, 0x3C, 0xF4, 0x3F, + 0x11, 0x6A, 0xEB, 0xC9, 0x7F, 0xC1, 0x37, 0x9B, 0x49, 0x36, 0x3F, 0x66, + 0xD7, 0x60, 0x4E, 0xF3, 0xBE, 0xF7, 0x7D, 0x2F, 0xEF, 0x7D, 0x93, 0x4C, + 0xD2, 0x0B, 0xB8, 0x87, 0x03, 0x62, 0x30, 0x1C, 0x92, 0x75, 0x93, 0x44, + 0xCF, 0xB7, 0x1D, 0xD3, 0xF0, 0x49, 0xE4, 0xAD, 0x9B, 0xD7, 0x1F, 0x7F, + 0x5C, 0x9D, 0x9E, 0x5F, 0xBD, 0x3E, 0xBB, 0xFE, 0x72, 0x7E, 0xBB, 0x08, + 0xFE, 0x7C, 0x7B, 0x73, 0xF9, 0xFE, 0xFB, 0xEF, 0xB3, 0x57, 0xBF, 0xDE, + 0xBE, 0xBB, 0xFC, 0x7A, 0x7A, 0xC7, 0xB4, 0x7A, 0xB2, 0x00, 0xF3, 0xB1, + 0x70, 0x26, 0xA1, 0xCB, 0x83, 0x48, 0xD5, 0x1A, 0x0A, 0x32, 0xE4, 0x82, + 0x62, 0x06, 0x8C, 0x90, 0xB3, 0x78, 0xF4, 0x08, 0xE0, 0x48, 0xAD, 0x2D, + 0xC2, 0x88, 0xE0, 0x3D, 0x94, 0x05, 0x37, 0x6F, 0x28, 0xF4, 0x90, 0xB8, + 0x42, 0x87, 0x87, 0x58, 0xA4, 0x4D, 0x14, 0xBB, 0x82, 0x06, 0x1A, 0xEE, + 0xA4, 0x49, 0x3D, 0x4A, 0x18, 0xD5, 0xA1, 0x81, 0x06, 0xC5, 0x43, 0x1E, + 0xC5, 0x4D, 0x38, 0x22, 0xE3, 0x98, 0x92, 0x10, 0x1A, 0x6C, 0xA4, 0xB8, + 0x17, 0x27, 0x3A, 0x9C, 0xF1, 0x17, 0x73, 0x14, 0x3E, 0xF5, 0x1A, 0x19, + 0x54, 0x72, 0x29, 0x27, 0x4E, 0x23, 0x03, 0xBB, 0xAE, 0x58, 0x37, 0xEF, + 0x99, 0x25, 0xF3, 0x74, 0xD6, 0xE9, 0x6C, 0xD3, 0x99, 0xA6, 0xB3, 0x4C, + 0xE7, 0x98, 0xCE, 0x2F, 0x9D, 0x5B, 0x3A, 0xAB, 0x74, 0x1E, 0xE9, 0xFC, + 0xD1, 0x39, 0x33, 0xDF, 0x13, 0x1F, 0x4F, 0xD4, 0x53, 0x04, 0x2B, 0xCB, + 0xE7, 0x21, 0x65, 0xF2, 0xF6, 0x32, 0xC8, 0xB2, 0x56, 0x90, 0x30, 0x12, + 0x55, 0x10, 0x30, 0x21, 0xAE, 0x43, 0xF4, 0xE2, 0x93, 0xF0, 0x78, 0x50, + 0x83, 0x8F, 0x12, 0xF2, 0xA2, 0x06, 0xC1, 0xFE, 0x89, 0x7A, 0xC1, 0xE8, + 0xE2, 0x83, 0x8B, 0xFD, 0xD9, 0x6D, 0x51, 0xD1, 0x55, 0xA9, 0xC3, 0xD2, + 0x9E, 0xA9, 0x56, 0xEB, 0x6D, 0xD6, 0x9B, 0x6C, 0x74, 0x58, 0xEF, 0xAD, + 0xDE, 0x58, 0xA3, 0x29, 0x7D, 0x47, 0x21, 0x11, 0xD4, 0x87, 0x87, 0x2D, + 0x7F, 0xFD, 0x54, 0x68, 0x6D, 0xD8, 0xE0, 0x6E, 0x1E, 0x94, 0x78, 0xD6, + 0xA0, 0x96, 0x40, 0xD5, 0x0A, 0x80, 0x10, 0x81, 0x55, 0x35, 0x58, 0x59, + 0xB8, 0xBB, 0xD9, 0xED, 0x21, 0xB9, 0xCA, 0x52, 0x96, 0x5F, 0x06, 0x50, + 0x41, 0x96, 0x41, 0xED, 0xA8, 0xC8, 0xBA, 0x8F, 0xC9, 0x00, 0xC7, 0x31, + 0x18, 0x3D, 0xDD, 0xD7, 0x22, 0x52, 0xE7, 0xC8, 0x61, 0x12, 0x04, 0xA6, + 0xB5, 0x0D, 0x97, 0xB1, 0xD5, 0x81, 0xA3, 0xC9, 0xE8, 0xD8, 0x70, 0x65, + 0xAB, 0x67, 0x70, 0xC9, 0x69, 0x0B, 0x4D, 0xAD, 0xA0, 0x2A, 0x11, 0x70, + 0x36, 0x34, 0xAD, 0xFF, 0x55, 0x87, 0xC4, 0x07, 0xF1, 0x16, 0xB2, 0x6D, + 0xD4, 0x52, 0x11, 0x8D, 0xB8, 0x88, 0x67, 0x9A, 0x86, 0x02, 0x55, 0x66, + 0x06, 0x20, 0xA6, 0x61, 0xC9, 0x83, 0x52, 0x54, 0xF1, 0xA0, 0xDF, 0xEF, + 0xF4, 0xA1, 0xFD, 0x0E, 0x5C, 0x0E, 0x9C, 0xD2, 0x07, 0x3D, 0x54, 0x62, + 0xD6, 0xCA, 0x54, 0x26, 0xEF, 0xF7, 0xD7, 0x6C, 0x7B, 0xCD, 0x71, 0x5A, + 0x49, 0xA6, 0xE3, 0x2A, 0x41, 0x0B, 0xBA, 0x9A, 0x55, 0x0A, 0x1A, 0x6C, + 0x54, 0x99, 0x4B, 0x59, 0xB5, 0x0F, 0x58, 0xBE, 0xFD, 0x3B, 0x89, 0x1D, + 0x1F, 0x8F, 0xC2, 0xC8, 0xD9, 0xDE, 0xBA, 0x7F, 0xF2, 0x14, 0x8F, 0x76, + 0xD3, 0x83, 0xCC, 0x9C, 0x32, 0x09, 0x74, 0x2C, 0x09, 0x5D, 0x22, 0x66, + 0x0E, 0x55, 0x62, 0xD5, 0x08, 0x60, 0xF0, 0x9C, 0x7A, 0xA6, 0x95, 0x2E, + 0xA7, 0xE9, 0x6A, 0x37, 0x4D, 0xD3, 0x1E, 0xAA, 0xF0, 0x1A, 0x85, 0x94, + 0xD0, 0x4B, 0x84, 0x20, 0xCC, 0x9B, 0xE4, 0xCA, 0xD5, 0x55, 0xE3, 0x56, + 0x4B, 0xE9, 0x98, 0x08, 0x8F, 0xB0, 0x58, 0x29, 0x97, 0x34, 0x2A, 0x54, + 0x6B, 0xBD, 0x28, 0x94, 0x4F, 0x57, 0x09, 0x55, 0x59, 0x9F, 0x78, 0x34, + 0xC4, 0xB0, 0xE3, 0xCB, 0xB9, 0x3E, 0x4B, 0xD7, 0xD5, 0xC5, 0x97, 0x96, + 0x27, 0x63, 0x2A, 0x37, 0xBA, 0xDB, 0x8A, 0x5F, 0x74, 0xBD, 0xD4, 0x8A, + 0x0E, 0x87, 0x6C, 0x12, 0x99, 0xD6, 0x4A, 0x2B, 0x72, 0x0A, 0x9F, 0x6F, + 0xD3, 0xBA, 0xDB, 0xE4, 0xA2, 0xEA, 0xD8, 0x80, 0xE4, 0xBE, 0x17, 0x4E, + 0x54, 0x81, 0xFC, 0xF9, 0x9A, 0x06, 0xA6, 0xF5, 0xF3, 0xE5, 0x67, 0x38, + 0x3E, 0x2A, 0x8C, 0x66, 0x11, 0xA5, 0xA1, 0x11, 0x97, 0x0B, 0x38, 0x35, + 0x1E, 0xEF, 0xB5, 0x16, 0x95, 0x4D, 0x6F, 0x4A, 0x50, 0xBD, 0x5B, 0xF9, + 0x32, 0x4C, 0xC6, 0xE4, 0x10, 0x7B, 0xF2, 0x1C, 0xCC, 0x97, 0xAA, 0x96, + 0x3D, 0x81, 0x1F, 0x1F, 0xDF, 0x18, 0x80, 0x17, 0xA8, 0xCC, 0xCC, 0xD3, + 0x14, 0xFE, 0x46, 0xD8, 0xDC, 0xF4, 0x26, 0x4F, 0x04, 0x7C, 0x77, 0x0C, + 0x27, 0xF6, 0xB5, 0xF9, 0x0D, 0x9F, 0xBB, 0xC4, 0x18, 0xD0, 0x7F, 0x10, + 0xFA, 0xF2, 0x67, 0xEA, 0x64, 0x01, 0x61, 0x43, 0x60, 0x17, 0x5E, 0x98, + 0xF9, 0x84, 0xFD, 0x11, 0xA6, 0xDA, 0xF4, 0x2E, 0x4F, 0x93, 0x63, 0x6C, + 0xEC, 0xF0, 0x78, 0x44, 0x3D, 0x39, 0xC7, 0xCA, 0x93, 0x07, 0x86, 0xBD, + 0x88, 0x0A, 0x23, 0x7B, 0x23, 0x9E, 0x53, 0xF7, 0x16, 0xDC, 0x14, 0x98, + 0x43, 0x39, 0x99, 0xF1, 0x70, 0x01, 0xC9, 0xE1, 0x2D, 0x48, 0xF6, 0x24, + 0x61, 0xC3, 0x23, 0x3E, 0xE5, 0xA9, 0xE6, 0xD0, 0x6C, 0xCF, 0x64, 0x94, + 0xFD, 0xFC, 0xC2, 0xF2, 0x2F, 0x7C, 0xDC, 0xCC, 0x2F, +}; +const uint8_t g_esLA_Locale[] = { + 0x78, 0x9C, 0x9D, 0x56, 0xCD, 0x4E, 0xDC, 0x30, 0x10, 0x3E, 0x53, 0xA9, + 0xEF, 0x60, 0x45, 0x45, 0x80, 0x04, 0x9B, 0xF6, 0xB8, 0x28, 0x44, 0x5A, + 0x01, 0xA5, 0x15, 0x0D, 0x5A, 0x75, 0x51, 0x4B, 0xB9, 0x54, 0x4E, 0x62, + 0x36, 0x86, 0xC4, 0x5E, 0x39, 0x09, 0x68, 0xA3, 0xBE, 0x40, 0x4F, 0x3D, + 0xF4, 0xD4, 0x63, 0x2B, 0x21, 0xB5, 0x07, 0xD4, 0x47, 0xE8, 0x81, 0x67, + 0x41, 0xF0, 0x18, 0x9D, 0xFC, 0x6E, 0x12, 0x3B, 0xE9, 0xD2, 0x9C, 0x3C, + 0xDF, 0x7C, 0x9F, 0x77, 0xE6, 0xB3, 0x33, 0x1B, 0xC3, 0xE7, 0x0E, 0xF6, + 0x09, 0x62, 0x38, 0x20, 0x3B, 0x1A, 0x09, 0x3F, 0x5A, 0x27, 0x1A, 0x72, + 0x49, 0xE8, 0xEC, 0x68, 0x0F, 0xD7, 0x7F, 0xEE, 0xBF, 0xDC, 0xDC, 0x7F, + 0xFE, 0xF6, 0xF0, 0xFB, 0x66, 0xFD, 0xEE, 0xC7, 0x4F, 0x88, 0xEF, 0xBE, + 0x5E, 0x6F, 0x68, 0xE6, 0xD3, 0x27, 0x08, 0x19, 0xA9, 0x8A, 0xB9, 0x58, + 0x4C, 0xE6, 0x81, 0xCD, 0xFD, 0xB0, 0xD8, 0x60, 0x2A, 0xC8, 0x94, 0x0B, + 0x8A, 0x59, 0xCA, 0x5A, 0x41, 0x46, 0xC0, 0x59, 0xE4, 0x1D, 0x41, 0x2A, + 0x4C, 0xE3, 0x95, 0x3C, 0x36, 0x09, 0x23, 0x82, 0x1B, 0x7A, 0x1E, 0xD4, + 0xF0, 0x33, 0x62, 0x0B, 0x75, 0x26, 0xC0, 0x22, 0x51, 0xE1, 0xD8, 0x16, + 0xD4, 0x57, 0xF2, 0xE7, 0x2A, 0xFA, 0x79, 0xCC, 0xA8, 0x1A, 0xF7, 0x95, + 0x38, 0x9E, 0xF2, 0x30, 0x52, 0x25, 0x42, 0x32, 0x8B, 0x28, 0x09, 0xA0, + 0x5C, 0x45, 0x92, 0x3B, 0x51, 0xAC, 0xCE, 0x30, 0x7E, 0xD9, 0xA9, 0x72, + 0xA9, 0x23, 0xE5, 0x50, 0xB1, 0xAE, 0x1C, 0xAC, 0x3B, 0x8A, 0xB0, 0x6D, + 0x8B, 0x1D, 0xED, 0x85, 0xD6, 0xB2, 0x56, 0x6D, 0xAC, 0xDA, 0x54, 0xB5, + 0xA5, 0x6A, 0x43, 0xD5, 0x7E, 0xAA, 0xDD, 0x54, 0x7B, 0xA9, 0x36, 0x52, + 0xED, 0xA0, 0xDA, 0x3D, 0xB5, 0x6F, 0xFD, 0x8E, 0xB9, 0x78, 0x5E, 0xBB, + 0x81, 0x10, 0x99, 0x2E, 0x0F, 0x28, 0x4B, 0xCB, 0x49, 0x83, 0x0A, 0xF5, + 0x63, 0x46, 0xC2, 0x16, 0x06, 0x16, 0x45, 0x32, 0x48, 0x6F, 0x7F, 0x09, + 0x87, 0xFB, 0x52, 0xE2, 0x3C, 0x26, 0x97, 0x12, 0x08, 0x27, 0x2E, 0xE4, + 0x8D, 0xC3, 0xDB, 0xEF, 0x36, 0x76, 0x17, 0x25, 0xA0, 0x6C, 0xA5, 0xA8, + 0xBA, 0x75, 0xCA, 0x45, 0xF9, 0x72, 0xE9, 0x72, 0xE1, 0x8A, 0xAA, 0xE5, + 0x7A, 0xE5, 0x62, 0x15, 0x85, 0x76, 0x57, 0x19, 0x10, 0x41, 0x5D, 0xB8, + 0xB6, 0xF5, 0x57, 0xBC, 0x80, 0xCC, 0x91, 0x05, 0x67, 0x51, 0x06, 0xCD, + 0xD4, 0xB8, 0x95, 0x42, 0x8B, 0xB0, 0xB6, 0x39, 0x11, 0xB8, 0xB6, 0x2F, + 0x44, 0x26, 0x1E, 0xEC, 0x0E, 0x0C, 0x3D, 0x5D, 0x55, 0x90, 0x5B, 0x87, + 0x50, 0xB6, 0x2A, 0x45, 0x30, 0xA5, 0xF4, 0xD6, 0x98, 0xCA, 0x51, 0x17, + 0x47, 0x64, 0x8C, 0xA3, 0x08, 0x0E, 0xA6, 0x72, 0xBB, 0x42, 0x8A, 0x49, + 0x76, 0x16, 0xFB, 0xBE, 0x66, 0xEE, 0xC3, 0x83, 0xF6, 0xD6, 0x60, 0x22, + 0xA2, 0x35, 0x0B, 0x9E, 0x7C, 0xF5, 0x01, 0x9E, 0xD4, 0x89, 0x4A, 0xD3, + 0xB5, 0x89, 0xCF, 0xD9, 0x54, 0x33, 0xFF, 0x5F, 0x1F, 0x10, 0x17, 0xE4, + 0x7B, 0xBA, 0x65, 0xE9, 0x4B, 0x6B, 0x42, 0x8F, 0x8B, 0x68, 0xA1, 0x6A, + 0x6B, 0x10, 0x6A, 0x20, 0x85, 0x23, 0x11, 0x0D, 0x5A, 0x8E, 0xD4, 0x90, + 0x86, 0x23, 0x9E, 0xB7, 0x6D, 0x59, 0xDB, 0x93, 0x09, 0x1A, 0xA1, 0x53, + 0x43, 0xAF, 0xB1, 0xBA, 0x64, 0xB9, 0x07, 0x8F, 0x96, 0x65, 0xAD, 0x2F, + 0x54, 0x4B, 0x69, 0x8A, 0xD6, 0x33, 0x95, 0x2C, 0x49, 0x3B, 0x6F, 0xF5, + 0x59, 0xDC, 0x85, 0x63, 0x40, 0xCB, 0x0B, 0x72, 0x10, 0x5B, 0xD1, 0x85, + 0x17, 0x84, 0x93, 0xFD, 0xBD, 0x97, 0x57, 0xEF, 0xB1, 0x77, 0x98, 0x9C, + 0xE6, 0x86, 0xD5, 0x49, 0x99, 0x92, 0xC5, 0x81, 0x4D, 0x44, 0xD3, 0xB5, + 0x06, 0x56, 0x54, 0x05, 0x18, 0xDC, 0x6D, 0x47, 0x33, 0x93, 0xCD, 0x24, + 0x19, 0x0E, 0x92, 0x24, 0x31, 0xF4, 0x06, 0xAF, 0x5B, 0xEA, 0xC4, 0x42, + 0x10, 0xE6, 0xCC, 0x35, 0xF3, 0x59, 0x2E, 0x1E, 0x0E, 0x3F, 0xAD, 0x57, + 0xCB, 0x8D, 0xA5, 0xF7, 0x99, 0x11, 0xE1, 0x10, 0x16, 0x15, 0x25, 0xAC, + 0xCA, 0xBA, 0xD4, 0x1B, 0xA9, 0x9F, 0xAA, 0xC7, 0x45, 0xDB, 0x2B, 0x4D, + 0xA8, 0xD8, 0xDE, 0x25, 0x0E, 0x0D, 0x30, 0x5C, 0x8E, 0x41, 0xB9, 0x4B, + 0x9E, 0xEE, 0x14, 0x4C, 0x05, 0x8F, 0x67, 0x34, 0xBD, 0x17, 0x9B, 0x4B, + 0x2A, 0xAA, 0x0E, 0x56, 0x97, 0x14, 0xC0, 0x84, 0x8F, 0x43, 0xCD, 0xDC, + 0x5A, 0x92, 0x9E, 0xC0, 0x77, 0x87, 0x66, 0x3E, 0x97, 0xD8, 0x0B, 0x63, + 0x1A, 0x67, 0x5F, 0x1E, 0x4C, 0xC3, 0x99, 0x26, 0x58, 0xDE, 0xC9, 0x2C, + 0x80, 0x03, 0x84, 0x59, 0xD4, 0xC8, 0xF7, 0x68, 0x68, 0xC8, 0xD3, 0x85, + 0x66, 0x5A, 0x27, 0x47, 0x8F, 0x90, 0xD5, 0x8F, 0x41, 0x12, 0x65, 0xC3, + 0x50, 0xAA, 0x3A, 0x7D, 0xF5, 0xE7, 0x33, 0x72, 0x86, 0x9D, 0x72, 0xE8, + 0x96, 0x61, 0xB1, 0xA7, 0x35, 0x87, 0xAF, 0x39, 0x17, 0x8D, 0xC1, 0x1D, + 0x5D, 0x4D, 0xA0, 0xF0, 0x49, 0xC5, 0x7A, 0x08, 0xBB, 0x3C, 0x16, 0xF0, + 0x17, 0x88, 0x26, 0x91, 0xDB, 0xC1, 0x18, 0xB9, 0xDC, 0x26, 0x68, 0x4C, + 0xFF, 0x49, 0x79, 0x95, 0x7E, 0x1F, 0x5E, 0xF5, 0x52, 0x46, 0x02, 0xDB, + 0xF0, 0xAE, 0xF5, 0x51, 0x8E, 0x3D, 0x4C, 0x3B, 0x08, 0x87, 0x3C, 0x89, + 0x2F, 0x30, 0x3A, 0xE0, 0x91, 0x47, 0x9D, 0xB4, 0xA7, 0xAD, 0x77, 0xAF, + 0x91, 0xD5, 0x4F, 0x06, 0x03, 0x1C, 0x8F, 0x97, 0xE4, 0xB7, 0xBD, 0x3F, + 0x0D, 0xDC, 0x69, 0xDA, 0x25, 0x7A, 0xD3, 0x4B, 0x9B, 0xF0, 0xA5, 0x68, + 0xD6, 0x3C, 0x66, 0xD3, 0x73, 0x9E, 0x31, 0xF3, 0x22, 0xB3, 0x11, 0x57, + 0x3B, 0x4F, 0x43, 0xCF, 0x3F, 0xEF, 0xCD, 0xBF, 0xC4, 0xB5, 0xD4, 0x04}; +const uint8_t g_deDE_Loacale[] = { + 0x78, 0x9C, 0x95, 0x56, 0x4D, 0x6F, 0xD4, 0x30, 0x10, 0xBD, 0x23, 0xF1, + 0x1F, 0xAC, 0x88, 0xAA, 0x20, 0xB5, 0x1B, 0x38, 0xB6, 0xDA, 0x46, 0x5A, + 0x75, 0xFB, 0x41, 0x4B, 0xCA, 0xAA, 0x69, 0x41, 0xF4, 0x82, 0xBC, 0x89, + 0xBB, 0x71, 0x9B, 0xD8, 0x2B, 0xC7, 0x69, 0xB5, 0x39, 0xF2, 0x37, 0xB8, + 0x72, 0x04, 0x71, 0xE4, 0x04, 0x17, 0xFE, 0x09, 0x52, 0x25, 0x7E, 0x06, + 0x93, 0x8D, 0x93, 0x26, 0xB6, 0xBB, 0x0D, 0xB9, 0xAC, 0xE7, 0xCD, 0x7B, + 0xB3, 0x33, 0xCF, 0x89, 0x93, 0x61, 0xC2, 0x43, 0x9C, 0x10, 0xC4, 0x70, + 0x4A, 0x76, 0x9C, 0x88, 0x7C, 0x1C, 0xEF, 0x39, 0x28, 0x22, 0x59, 0xB8, + 0xE3, 0xDC, 0xFD, 0xFA, 0xF1, 0xF7, 0xFB, 0xB7, 0xE7, 0xF0, 0x73, 0xF7, + 0xF9, 0xE7, 0x0B, 0xC7, 0x1B, 0x96, 0x44, 0x16, 0x61, 0x11, 0x2C, 0xD2, + 0x29, 0x4F, 0x32, 0xA5, 0x99, 0x09, 0x32, 0xE3, 0x82, 0x62, 0x06, 0x8C, + 0x94, 0x33, 0x19, 0x9F, 0x00, 0x9C, 0xA9, 0xB5, 0x77, 0x84, 0x59, 0x8E, + 0xC5, 0xD0, 0xAD, 0xA2, 0xA7, 0x4F, 0x14, 0xBC, 0x4F, 0xA6, 0xC2, 0x86, + 0xFB, 0xBF, 0xBF, 0x88, 0xC2, 0x40, 0x47, 0x73, 0x41, 0x13, 0x93, 0x8B, + 0xA9, 0x81, 0x1D, 0xE5, 0xCC, 0x06, 0x26, 0x26, 0x38, 0xCA, 0x67, 0x79, + 0x26, 0x0D, 0x38, 0x20, 0x73, 0x49, 0xD2, 0x29, 0x31, 0x5B, 0x7B, 0x7B, + 0x2D, 0xB9, 0x0D, 0x3F, 0xE1, 0x37, 0x76, 0xC1, 0x98, 0x14, 0x7A, 0xC2, + 0x6D, 0x19, 0x54, 0xF3, 0x96, 0x11, 0xC2, 0xD3, 0xA9, 0xD8, 0x71, 0x5E, + 0x39, 0x2D, 0xDF, 0x6C, 0xA6, 0x99, 0x26, 0xD8, 0xED, 0xEA, 0x6B, 0x96, + 0xCD, 0x2B, 0x9B, 0x55, 0x36, 0x9F, 0x6C, 0x0E, 0xD9, 0xDC, 0xB1, 0x19, + 0xF3, 0xB0, 0x27, 0x11, 0x5E, 0xA8, 0x1B, 0x08, 0x56, 0x5E, 0xC0, 0x19, + 0x93, 0x18, 0xFE, 0xBE, 0x0C, 0xAA, 0xAC, 0xE7, 0x73, 0x03, 0x1A, 0x53, + 0xC2, 0x32, 0x83, 0x47, 0xA5, 0xBC, 0xE5, 0x61, 0xDC, 0x65, 0x42, 0x41, + 0x22, 0x0C, 0xEE, 0xBE, 0x20, 0x54, 0xC7, 0x02, 0x9C, 0x76, 0x78, 0x6E, + 0xD3, 0x5A, 0xAB, 0xCD, 0xD6, 0xC6, 0x55, 0xFD, 0x6A, 0xAD, 0x6A, 0x6D, + 0x6A, 0x0D, 0x6A, 0xAD, 0x69, 0x2D, 0x69, 0xDD, 0xD8, 0x1B, 0x49, 0x89, + 0xA0, 0x11, 0x25, 0x69, 0xFD, 0xD4, 0xA9, 0xD0, 0x1B, 0xF9, 0xE0, 0x6C, + 0x1D, 0xB4, 0x78, 0xDE, 0x44, 0x4B, 0xB8, 0xDD, 0x0A, 0x80, 0x10, 0x81, + 0x55, 0x35, 0x58, 0x79, 0x37, 0x03, 0xB4, 0x1B, 0x8B, 0xC1, 0xD0, 0x2D, + 0x83, 0x2A, 0xEB, 0x31, 0x0D, 0x73, 0x1B, 0x49, 0x19, 0x68, 0xE7, 0x44, + 0x35, 0x81, 0x24, 0x13, 0x2C, 0x25, 0x11, 0x6C, 0xB9, 0xB3, 0x4D, 0xA4, + 0x0E, 0x91, 0xCB, 0x3C, 0x49, 0x1C, 0x6F, 0x0F, 0xAE, 0x0D, 0x34, 0x1E, + 0x20, 0x1F, 0x2E, 0xF4, 0x01, 0xAE, 0x72, 0xD6, 0x86, 0xAB, 0x15, 0x52, + 0xD2, 0x84, 0xB3, 0x99, 0xE3, 0xFD, 0xA7, 0x28, 0x25, 0x11, 0x68, 0xC6, + 0x03, 0xDF, 0x1F, 0xF4, 0x54, 0x64, 0x31, 0x17, 0xF2, 0x5E, 0x63, 0x28, + 0xDC, 0xCE, 0x88, 0x00, 0x48, 0x9A, 0xB6, 0x46, 0x6E, 0x45, 0x9D, 0x91, + 0x0F, 0xB7, 0x7D, 0x7F, 0x1D, 0x9D, 0xC7, 0x02, 0xAD, 0x5F, 0x0C, 0xDD, + 0x16, 0x4B, 0x2B, 0xD1, 0x19, 0xF6, 0xB0, 0x54, 0x6D, 0x07, 0x01, 0xEA, + 0x23, 0x59, 0x8E, 0x5A, 0x2B, 0x7A, 0xF0, 0xD5, 0xA0, 0x4B, 0x85, 0x41, + 0x77, 0x3B, 0x53, 0x29, 0xA3, 0xCE, 0x00, 0xAB, 0xF7, 0xFA, 0xE0, 0xCA, + 0x97, 0xD7, 0x87, 0x69, 0x16, 0xEC, 0x8D, 0xF7, 0x6F, 0xDF, 0xE3, 0xF8, + 0xB8, 0xB8, 0xA8, 0xAC, 0x69, 0x93, 0x40, 0xC7, 0xF2, 0xF2, 0x68, 0xBC, + 0xF7, 0xA7, 0x13, 0xAB, 0x4E, 0x00, 0x83, 0x5B, 0x33, 0x74, 0xBC, 0x62, + 0xA3, 0x28, 0xB6, 0x06, 0x45, 0x01, 0xC7, 0x46, 0x87, 0x67, 0x14, 0x52, + 0xC2, 0x30, 0x17, 0x82, 0xB0, 0x70, 0x51, 0x2B, 0xB7, 0xB6, 0xD0, 0xB3, + 0x9E, 0xD2, 0x39, 0x11, 0x21, 0x61, 0x52, 0x29, 0xD7, 0x2C, 0x2A, 0x57, + 0x6B, 0xBD, 0x29, 0x54, 0x4F, 0xD7, 0x09, 0x9B, 0x17, 0x6B, 0x48, 0x53, + 0x0C, 0xFB, 0xBD, 0x51, 0xEB, 0xAB, 0xB4, 0xAE, 0x6E, 0xDE, 0xA9, 0x3C, + 0x9F, 0xD3, 0x72, 0xAB, 0x07, 0xBD, 0xF8, 0x4D, 0xD7, 0x6B, 0xBD, 0xE8, + 0x29, 0x65, 0x79, 0xE6, 0x78, 0x9B, 0xBD, 0xC8, 0x05, 0x11, 0xDC, 0xF1, + 0x5E, 0x9A, 0x5C, 0xB7, 0x3B, 0x36, 0x20, 0xB5, 0xEF, 0x8D, 0x13, 0x5D, + 0xA0, 0xBE, 0xC1, 0x96, 0x81, 0xE3, 0xFD, 0xF9, 0xF4, 0x15, 0xCE, 0x8A, + 0x0E, 0xC3, 0x2C, 0xA2, 0x34, 0x34, 0xE3, 0xE5, 0x02, 0x8E, 0x88, 0xF3, + 0xD3, 0xDE, 0xA2, 0xB6, 0xE9, 0xA6, 0xC4, 0xD5, 0xBB, 0x2D, 0x9F, 0x86, + 0xC5, 0x9C, 0x5C, 0xE2, 0xB0, 0x3C, 0xFA, 0xEA, 0xA5, 0xAA, 0xE5, 0x2F, + 0xE0, 0x13, 0x27, 0x42, 0x13, 0xF0, 0xC2, 0x6D, 0x33, 0xEB, 0x34, 0x65, + 0x94, 0xB3, 0x07, 0xD3, 0xBB, 0x3C, 0x17, 0x94, 0x08, 0x14, 0xC8, 0xC8, + 0x9A, 0x1F, 0x45, 0xF0, 0x69, 0x81, 0x26, 0xF4, 0x11, 0xC2, 0x21, 0x7C, + 0x35, 0x91, 0xDB, 0x15, 0x84, 0x91, 0xC0, 0x53, 0x78, 0x60, 0x1E, 0x26, + 0x9C, 0xC5, 0x98, 0x5A, 0xD3, 0xC7, 0xBC, 0xC8, 0xAF, 0x31, 0x3A, 0xE0, + 0x32, 0xA6, 0x61, 0x39, 0xC7, 0xE6, 0xBB, 0xD7, 0xC8, 0x5F, 0x45, 0x85, + 0x91, 0xC3, 0x98, 0xD7, 0xD4, 0xD3, 0x15, 0x7F, 0x0A, 0xCC, 0x59, 0x39, + 0x19, 0x7A, 0xB3, 0x82, 0x04, 0x6F, 0xFA, 0xC7, 0x49, 0xFE, 0x22, 0x67, + 0xB3, 0x2B, 0xBE, 0xE4, 0xA9, 0xE6, 0xDC, 0xFB, 0x3D, 0x2B, 0xA3, 0xEA, + 0x73, 0x16, 0x96, 0xFF, 0x00, 0x29, 0x27, 0xAF, 0x17, +}; +const uint8_t g_frFR_Locale[] = { + 0x78, 0x9C, 0x95, 0x56, 0x4D, 0x6F, 0xD3, 0x40, 0x10, 0xBD, 0x23, 0xF1, + 0x1F, 0x56, 0x16, 0x55, 0x41, 0x6A, 0xBD, 0x70, 0x4C, 0x95, 0x5A, 0xAA, + 0xFA, 0x15, 0x28, 0x46, 0x51, 0x53, 0x40, 0xF4, 0x82, 0x36, 0xF6, 0x36, + 0xDE, 0xD4, 0xDE, 0x8D, 0xD6, 0x76, 0x4A, 0x7C, 0xE4, 0x3F, 0x70, 0xE2, + 0xC2, 0xB5, 0x12, 0x88, 0x03, 0x47, 0xC4, 0x85, 0xFE, 0x13, 0x24, 0x10, + 0x3F, 0x83, 0x71, 0xBC, 0x76, 0xED, 0x5D, 0x27, 0xB8, 0xBE, 0x64, 0xE7, + 0xCD, 0x7B, 0xE3, 0x99, 0xB7, 0xF6, 0xC6, 0xFD, 0x50, 0x78, 0x24, 0xA4, + 0x88, 0x93, 0x88, 0xEE, 0x5A, 0x17, 0xF2, 0xED, 0xD1, 0xA9, 0x85, 0x7C, + 0x1A, 0x7B, 0xBB, 0xD6, 0x9F, 0x6F, 0x1F, 0xFE, 0x7E, 0xFD, 0xF2, 0x10, + 0x7E, 0x7E, 0x7F, 0xFC, 0xF1, 0xC8, 0x72, 0xFA, 0x39, 0x91, 0xFB, 0x44, + 0x8E, 0x16, 0xD1, 0x58, 0x84, 0xB1, 0xD2, 0x4C, 0x24, 0x9D, 0x08, 0xC9, + 0x08, 0x07, 0x46, 0x24, 0x78, 0x12, 0xBC, 0x00, 0x38, 0x56, 0x6B, 0x67, + 0x4A, 0xF8, 0x9C, 0x51, 0xD9, 0xC7, 0x45, 0x78, 0xFF, 0x9E, 0xC2, 0x2F, + 0x6E, 0xAE, 0xE7, 0xB2, 0x2D, 0x11, 0x11, 0x19, 0x1B, 0x20, 0x01, 0x6E, + 0xD8, 0x42, 0x65, 0x06, 0x36, 0x4D, 0x19, 0x6F, 0x03, 0xC3, 0x90, 0x26, + 0x66, 0x59, 0x71, 0xF3, 0xDD, 0x44, 0x63, 0x3A, 0x4B, 0x68, 0x34, 0x96, + 0xD4, 0xC8, 0x08, 0x2F, 0x11, 0x6D, 0x38, 0x17, 0xF3, 0x76, 0x81, 0x7F, + 0x73, 0xED, 0xE9, 0x19, 0x5C, 0x33, 0xA9, 0x24, 0x2E, 0x23, 0x44, 0xC6, + 0x63, 0xB9, 0x6B, 0x3D, 0xB1, 0xEA, 0xDE, 0xD9, 0xED, 0xCE, 0x99, 0xF0, + 0x2A, 0xDF, 0xDA, 0x98, 0x77, 0xB0, 0xCD, 0x94, 0xAF, 0x36, 0xCD, 0xE4, + 0x82, 0x61, 0x26, 0x08, 0x6E, 0x99, 0x60, 0xEE, 0x94, 0xBD, 0xDA, 0x25, + 0x9F, 0x2C, 0xD4, 0x63, 0x05, 0x2B, 0xC7, 0x67, 0x11, 0xE1, 0x5E, 0x00, + 0xAE, 0xE6, 0x51, 0x91, 0x76, 0xC2, 0x94, 0xFB, 0xAC, 0x81, 0x80, 0x25, + 0x3A, 0x42, 0xA5, 0x27, 0xA9, 0x06, 0x4E, 0x69, 0xAA, 0x21, 0x73, 0x78, + 0xCC, 0x0D, 0x5A, 0x0C, 0xF7, 0xAF, 0x41, 0xB8, 0x6A, 0xA9, 0xD6, 0x5E, + 0x6D, 0x0B, 0x55, 0x9F, 0xB6, 0xDE, 0xA3, 0xAD, 0xB7, 0x68, 0xEB, 0x1D, + 0xDA, 0x7A, 0x77, 0xB6, 0xDE, 0x9C, 0xAD, 0x37, 0x66, 0xB7, 0xB7, 0x05, + 0xC5, 0x98, 0xCF, 0x68, 0x54, 0xBE, 0x91, 0x2A, 0x74, 0xF6, 0x5C, 0xF0, + 0xB7, 0x0C, 0x6A, 0x3C, 0x67, 0xA8, 0x25, 0x70, 0xB3, 0x02, 0x20, 0x54, + 0x12, 0x55, 0x0D, 0x56, 0xF0, 0x7C, 0xD9, 0xE8, 0x99, 0xBD, 0xBD, 0x0F, + 0xF7, 0xCF, 0xC3, 0x22, 0xEF, 0x90, 0x99, 0x8E, 0xE2, 0x4A, 0x96, 0x07, + 0xDA, 0x39, 0x52, 0xCC, 0x91, 0xD0, 0x21, 0x49, 0x12, 0x2A, 0xF9, 0x72, + 0x8F, 0xAB, 0xA8, 0x3C, 0x98, 0xD2, 0x30, 0xB4, 0x9C, 0x43, 0xB8, 0xD0, + 0x01, 0x72, 0xE1, 0x42, 0x6F, 0xE0, 0xCA, 0xA7, 0xAD, 0x98, 0x5A, 0x19, + 0x25, 0x0C, 0x05, 0x9F, 0x58, 0xCE, 0xDD, 0x34, 0xB0, 0xCF, 0x4A, 0x82, + 0x3A, 0xF1, 0xE3, 0x40, 0xC8, 0x04, 0x14, 0x07, 0xD8, 0x75, 0x71, 0x8B, + 0x02, 0x37, 0xA6, 0x03, 0x20, 0x61, 0x51, 0x6D, 0xDA, 0x5A, 0xD4, 0x98, + 0x76, 0x30, 0xD8, 0x44, 0x01, 0xDA, 0x84, 0x2E, 0xCE, 0xFB, 0xB8, 0x46, + 0xD2, 0x2A, 0x34, 0x06, 0x1D, 0x0C, 0x76, 0x5C, 0x77, 0x67, 0x34, 0xEA, + 0x24, 0x59, 0xCE, 0x59, 0x2A, 0x3A, 0xF0, 0xD5, 0x9C, 0x4B, 0x85, 0x41, + 0xC7, 0x8D, 0xA1, 0x94, 0x4F, 0x67, 0x80, 0x95, 0xBB, 0x7C, 0x4C, 0xDC, + 0xE9, 0xE5, 0x20, 0x8A, 0x47, 0x87, 0x07, 0x47, 0x57, 0xAF, 0xDF, 0x05, + 0x27, 0xD9, 0x79, 0xE1, 0x4C, 0x9D, 0x04, 0x3A, 0x9E, 0x46, 0x63, 0x2A, + 0x6F, 0xED, 0x69, 0xC4, 0xAA, 0x13, 0xC0, 0xE0, 0xC1, 0xF4, 0x2C, 0x27, + 0xDB, 0xCA, 0xB2, 0x9E, 0x9D, 0x65, 0x59, 0x1F, 0x37, 0x78, 0x46, 0x21, + 0x25, 0xF4, 0x52, 0x29, 0x29, 0xF7, 0x16, 0xA5, 0xB2, 0xD7, 0x43, 0x0F, + 0x3A, 0x4A, 0x67, 0x70, 0x76, 0x50, 0x9E, 0x28, 0xE5, 0x46, 0x8B, 0x0A, + 0x6B, 0xAD, 0x57, 0x85, 0xCA, 0xE9, 0x1A, 0xA1, 0x2A, 0xEB, 0x53, 0x0F, + 0x4E, 0x33, 0xD8, 0xEE, 0xAD, 0x52, 0x5F, 0xA4, 0x75, 0x75, 0xF5, 0x6F, + 0x2B, 0xD2, 0x19, 0xCB, 0xB7, 0xFA, 0xE7, 0xA7, 0x4E, 0x82, 0xAA, 0xED, + 0x8D, 0x4E, 0xF4, 0x88, 0xF1, 0x34, 0xB6, 0x9C, 0xED, 0x4E, 0xE4, 0x8C, + 0x4A, 0x61, 0x39, 0x8F, 0x4D, 0x2E, 0x6E, 0xCE, 0x0D, 0x48, 0x69, 0x7C, + 0x65, 0x45, 0x13, 0x28, 0x9F, 0xB0, 0x65, 0x60, 0x39, 0xBF, 0xDE, 0x7F, + 0x86, 0x63, 0xA2, 0xC1, 0x30, 0x8B, 0x28, 0x0D, 0x8B, 0x45, 0xBE, 0x80, + 0xD3, 0xE1, 0xE5, 0x69, 0x67, 0x51, 0xDD, 0x75, 0x53, 0x82, 0xF5, 0x6E, + 0xF3, 0xD7, 0x61, 0x31, 0xA3, 0x17, 0xC4, 0xCB, 0x4F, 0xBE, 0x72, 0xA9, + 0x6A, 0xB9, 0x0B, 0xF8, 0xFA, 0xF1, 0xD1, 0x10, 0xBC, 0xC0, 0x75, 0x66, + 0x99, 0x66, 0x9C, 0x09, 0xBE, 0x32, 0xBD, 0x2F, 0xD2, 0xFC, 0x3B, 0x08, + 0x8D, 0x12, 0xBF, 0x35, 0xBF, 0xE7, 0x8B, 0x31, 0x45, 0x43, 0xF6, 0x1F, + 0xC2, 0x80, 0xC2, 0x57, 0xC6, 0xD5, 0x1A, 0xC2, 0x9E, 0x24, 0x63, 0x78, + 0x63, 0x56, 0x13, 0xCE, 0x02, 0xC2, 0x5A, 0xD3, 0x27, 0x22, 0x4B, 0x2F, + 0x09, 0x3A, 0x16, 0x49, 0xC0, 0xBC, 0x7C, 0x8E, 0xED, 0x57, 0x4F, 0x91, + 0xBB, 0x8E, 0x0A, 0x23, 0x7B, 0x81, 0x28, 0xA9, 0xA7, 0x6B, 0x6E, 0x0A, + 0xCC, 0x49, 0x3E, 0x19, 0x7A, 0xBE, 0x86, 0x34, 0x12, 0x1D, 0x48, 0xEE, + 0x22, 0xE5, 0x93, 0xA9, 0x58, 0xF2, 0x54, 0x73, 0xF8, 0x76, 0xCF, 0xF2, + 0xA8, 0xF8, 0xD2, 0x85, 0xE5, 0x3F, 0x5D, 0x49, 0xBE, 0x1B}; +const uint8_t g_itIT_Locale[] = { + 0x78, 0x9C, 0x95, 0x56, 0xD1, 0x6A, 0xD4, 0x40, 0x14, 0x7D, 0x17, 0xFC, + 0x87, 0x21, 0x58, 0x50, 0x68, 0x3B, 0xFA, 0xD8, 0x92, 0x06, 0x4A, 0x5B, + 0xBB, 0xA5, 0x46, 0x96, 0xEE, 0xAA, 0xD8, 0x17, 0x99, 0x64, 0xA6, 0xD9, + 0xB1, 0xC9, 0xCC, 0x32, 0x49, 0x5A, 0x92, 0x47, 0xF1, 0xC1, 0x37, 0x7F, + 0x42, 0x10, 0x41, 0xF1, 0x23, 0xFC, 0x13, 0xA1, 0xE2, 0x67, 0x78, 0xB3, + 0x99, 0xA4, 0xC9, 0x64, 0xBA, 0xA6, 0x79, 0xD9, 0xB9, 0xE7, 0x9E, 0x73, + 0x73, 0xEF, 0x99, 0x64, 0x36, 0x6E, 0x2C, 0x43, 0x12, 0x33, 0x24, 0x48, + 0xC2, 0xF6, 0x1C, 0x9E, 0xBD, 0x3B, 0x99, 0x3B, 0x88, 0xB2, 0x34, 0xDC, + 0x73, 0xFE, 0x7C, 0xFC, 0x7C, 0xF3, 0xE5, 0xEB, 0xCD, 0xA7, 0x6F, 0x7F, + 0x7F, 0xFE, 0x78, 0xDC, 0x06, 0x4F, 0x1C, 0xCF, 0xAD, 0x14, 0x82, 0x12, + 0x35, 0x2B, 0x92, 0x40, 0xC6, 0xA9, 0x16, 0x47, 0x8A, 0x45, 0x52, 0x71, + 0x22, 0x80, 0x91, 0x48, 0x91, 0x2D, 0x5E, 0x02, 0x9C, 0xEA, 0xB5, 0x17, + 0x31, 0x21, 0x08, 0x97, 0x2E, 0xAE, 0xC3, 0x87, 0x0F, 0x34, 0x7E, 0xC1, + 0x82, 0x40, 0xD9, 0x12, 0x09, 0x51, 0xE5, 0x10, 0x25, 0x4B, 0xC5, 0x63, + 0x66, 0x21, 0x47, 0x91, 0xA5, 0x46, 0xC4, 0xF3, 0x48, 0x0C, 0xE1, 0x38, + 0x8F, 0x62, 0x0B, 0x9B, 0x44, 0x32, 0xCD, 0x86, 0x70, 0xCA, 0xB2, 0x8C, + 0x25, 0x81, 0x1A, 0xDE, 0x55, 0x66, 0x99, 0xB4, 0xE1, 0x42, 0x5E, 0xD9, + 0x05, 0x94, 0x87, 0x66, 0x02, 0x77, 0xAC, 0x6A, 0x78, 0xAB, 0x08, 0x11, + 0x30, 0x66, 0xCF, 0x79, 0xE6, 0x74, 0x1C, 0xB4, 0xB9, 0x67, 0x33, 0xCE, + 0x66, 0x9B, 0xCD, 0x33, 0x9B, 0x61, 0x36, 0xB7, 0x6C, 0x56, 0xD9, 0x7C, + 0xB2, 0x39, 0x64, 0x73, 0xC7, 0x66, 0xCC, 0xDD, 0x9E, 0x50, 0x52, 0xE8, + 0x47, 0x09, 0x56, 0x1E, 0x95, 0x09, 0x13, 0x3C, 0x24, 0x2E, 0xAE, 0xA2, + 0x3A, 0x0D, 0x3D, 0x0A, 0x46, 0x7F, 0x7D, 0xEF, 0x61, 0xE0, 0x43, 0x36, + 0x04, 0x99, 0x0A, 0x65, 0x3C, 0x80, 0xE1, 0xE1, 0xB9, 0x1A, 0x80, 0x57, + 0x4C, 0x30, 0x65, 0x82, 0x29, 0x09, 0x48, 0xF5, 0x90, 0x68, 0x08, 0xB7, + 0xCD, 0x75, 0x1A, 0xED, 0x6C, 0x9D, 0xEE, 0xD8, 0x6C, 0xD6, 0x6C, 0xD4, + 0xEC, 0xD1, 0x6C, 0xCE, 0xEC, 0xCB, 0x6C, 0xC9, 0xDE, 0x0F, 0x14, 0xE2, + 0x94, 0xB3, 0xA4, 0x79, 0x11, 0x75, 0xE8, 0xED, 0xFB, 0x60, 0x71, 0x13, + 0x74, 0x78, 0xDE, 0xD4, 0x48, 0xE0, 0x7E, 0x05, 0x40, 0x98, 0x22, 0xBA, + 0x1A, 0xAC, 0x3C, 0x72, 0xE0, 0xE2, 0xEA, 0xB7, 0x4E, 0x78, 0xF4, 0x36, + 0xC4, 0x2D, 0xB1, 0x0A, 0x8C, 0x03, 0xA3, 0x6E, 0x3C, 0x63, 0x53, 0x02, + 0x6F, 0x96, 0x12, 0xAB, 0x8D, 0x6D, 0x23, 0x7D, 0x9A, 0x5C, 0xE4, 0x71, + 0xEC, 0x78, 0x47, 0x70, 0xA1, 0x43, 0xE4, 0xC3, 0x85, 0xDE, 0xC2, 0x55, + 0xCD, 0xD7, 0x32, 0x8D, 0x32, 0x5A, 0x18, 0x4B, 0x11, 0x39, 0xDE, 0xE1, + 0xFD, 0x44, 0x09, 0xA3, 0x95, 0x06, 0x83, 0x04, 0x8F, 0x12, 0xA4, 0x0B, + 0xA9, 0x32, 0x2D, 0xB1, 0x29, 0x70, 0x6F, 0x3E, 0x00, 0x32, 0x9E, 0x74, + 0xE6, 0xED, 0x44, 0xBD, 0x79, 0x27, 0x93, 0x5D, 0xDF, 0xDF, 0x9D, 0xCD, + 0xD0, 0xB9, 0x8B, 0x3B, 0x1C, 0xA3, 0x40, 0x6F, 0xD2, 0xFB, 0x28, 0x56, + 0x63, 0x36, 0xF7, 0x18, 0xC1, 0xD7, 0x53, 0xAE, 0x14, 0x03, 0x3A, 0xEE, + 0x8D, 0xA4, 0x5D, 0x9A, 0x03, 0xD6, 0xEC, 0xF2, 0x71, 0xE1, 0xD3, 0xCB, + 0x49, 0x92, 0xCE, 0x8E, 0x0E, 0x9F, 0x5F, 0xBF, 0x21, 0x8B, 0xD3, 0xF2, + 0xBC, 0xF6, 0xA5, 0x4B, 0x02, 0x9D, 0xC8, 0x93, 0x80, 0xA9, 0x5B, 0x73, + 0x7A, 0xB1, 0xEE, 0x04, 0x30, 0x78, 0x14, 0x43, 0xC7, 0x2B, 0x37, 0xCB, + 0x72, 0x67, 0xBB, 0x2C, 0x4B, 0x17, 0xF7, 0x78, 0x83, 0x42, 0x5A, 0x18, + 0xE6, 0x4A, 0x31, 0x11, 0x16, 0x8E, 0xF7, 0x08, 0xD5, 0xDA, 0x9D, 0x9D, + 0x91, 0xD2, 0x25, 0x9C, 0x15, 0x4C, 0x64, 0xFA, 0x9E, 0x1B, 0x16, 0x15, + 0x36, 0x5A, 0x6F, 0x0B, 0x35, 0xD3, 0xF5, 0x42, 0x5D, 0x96, 0xB2, 0x90, + 0x27, 0x04, 0x36, 0x7B, 0xB3, 0xD1, 0xD7, 0x69, 0x53, 0xDD, 0xFE, 0xAD, + 0xCA, 0x7C, 0xC9, 0xAB, 0x9D, 0xDE, 0x1E, 0xC5, 0x6F, 0xBB, 0xDE, 0x18, + 0x45, 0x4F, 0xB8, 0xC8, 0x53, 0xC7, 0xDB, 0x1A, 0x45, 0x2E, 0x99, 0x92, + 0x8E, 0xF7, 0x74, 0xC8, 0xC5, 0xFD, 0xB1, 0x01, 0x69, 0x7C, 0x6F, 0x9D, + 0xE8, 0x03, 0xCD, 0x03, 0xB6, 0x0A, 0x1C, 0xEF, 0xF7, 0x07, 0x38, 0x65, + 0xFB, 0x8C, 0x61, 0x91, 0xE6, 0x23, 0x25, 0x95, 0xD5, 0x02, 0x0E, 0x87, + 0x57, 0x67, 0xA3, 0x45, 0x5D, 0xD3, 0x87, 0x12, 0x6C, 0x76, 0x5B, 0xBD, + 0x0D, 0xC5, 0x92, 0x5D, 0x90, 0xB0, 0x3A, 0xEA, 0x9A, 0xA5, 0xAE, 0xE5, + 0x17, 0xF0, 0x95, 0x43, 0xD1, 0x14, 0xBC, 0xC0, 0x5D, 0x66, 0x93, 0xE6, + 0x82, 0x4B, 0x71, 0x67, 0xFA, 0x40, 0xE6, 0x8A, 0x33, 0x85, 0x66, 0x19, + 0xB5, 0xE6, 0xF7, 0xA9, 0x0C, 0x18, 0x9A, 0xF2, 0xFF, 0x10, 0x26, 0x0C, + 0xBE, 0x23, 0xAE, 0xD7, 0x10, 0xF6, 0x15, 0x09, 0xE0, 0x85, 0xB9, 0x9B, + 0x30, 0x5F, 0x10, 0x6E, 0x4D, 0x9F, 0xCA, 0x32, 0xBF, 0x24, 0xE8, 0x58, + 0x66, 0x0B, 0x1E, 0x56, 0x73, 0x6C, 0xBD, 0x3E, 0x41, 0xFE, 0x3A, 0x2A, + 0x8C, 0x1C, 0x2E, 0x64, 0x43, 0x3D, 0x5B, 0x73, 0x53, 0x60, 0x46, 0xD5, + 0x64, 0xE8, 0xC5, 0x1A, 0xD2, 0x4C, 0x8E, 0x20, 0xF9, 0x45, 0x2E, 0xA2, + 0xF7, 0x72, 0xC5, 0xD3, 0xCD, 0xE1, 0xDB, 0x3D, 0xAB, 0xA2, 0xFA, 0xD3, + 0x16, 0x96, 0xFF, 0x00, 0x20, 0x8B, 0xBE, 0xF7}; +const uint8_t g_ptBR_Locale[] = { + 0x78, 0x9C, 0x9D, 0x56, 0x3D, 0x6F, 0xD4, 0x40, 0x10, 0xAD, 0x83, 0xC4, + 0x7F, 0x58, 0x59, 0x89, 0x0E, 0xA4, 0x24, 0x86, 0x92, 0xC8, 0x67, 0xE9, + 0x92, 0x0B, 0x39, 0x94, 0x18, 0x9D, 0xCE, 0x11, 0x88, 0x34, 0x68, 0x6D, + 0xEF, 0xD9, 0x9B, 0xD8, 0xBB, 0xC7, 0xDA, 0x4E, 0xB0, 0x6B, 0x1A, 0x3A, + 0x28, 0x29, 0x53, 0x20, 0x2A, 0x44, 0x83, 0x44, 0x49, 0x91, 0xDF, 0x82, + 0xB8, 0x9F, 0xC1, 0xFA, 0xF3, 0xFC, 0xB1, 0x36, 0x06, 0x37, 0xDE, 0x99, + 0x79, 0x6F, 0x3D, 0xF3, 0x76, 0x76, 0x64, 0xC5, 0xA5, 0x26, 0x74, 0x11, + 0x20, 0xD0, 0x43, 0x63, 0x69, 0x15, 0xBC, 0x3E, 0x5C, 0x48, 0xC0, 0x42, + 0xBE, 0x39, 0x96, 0xD6, 0x1F, 0x6F, 0xD7, 0x1F, 0xDE, 0xFD, 0x7E, 0xFF, + 0x69, 0xFD, 0xED, 0xEB, 0x83, 0x5F, 0x3F, 0xBE, 0xAF, 0x3F, 0xFF, 0x7C, + 0x28, 0xA9, 0xF7, 0xEF, 0x01, 0xA0, 0x24, 0x14, 0x62, 0x41, 0xA6, 0x47, + 0x9E, 0x41, 0x5D, 0x3F, 0x67, 0xDB, 0x0C, 0xD9, 0x94, 0x61, 0x48, 0x12, + 0xD4, 0x16, 0x50, 0x3C, 0x4A, 0x02, 0xE7, 0x39, 0x0F, 0xF9, 0x89, 0xBD, + 0x95, 0xD9, 0xEA, 0x25, 0x24, 0x08, 0x33, 0xAA, 0xC8, 0x99, 0x59, 0x89, + 0x2C, 0xD1, 0x35, 0x62, 0x1D, 0x31, 0x0F, 0xB2, 0xBB, 0x2F, 0xA2, 0x00, + 0x34, 0x18, 0x76, 0x85, 0x04, 0x2C, 0x82, 0x5F, 0x86, 0xC4, 0x11, 0xFB, + 0x5D, 0xA1, 0x1F, 0xDA, 0xD4, 0x0F, 0x44, 0x01, 0x1F, 0x05, 0xC8, 0x33, + 0x84, 0xB9, 0xD2, 0x30, 0x08, 0xC5, 0x11, 0x42, 0xAF, 0xBB, 0x48, 0x16, + 0x8A, 0x9B, 0x21, 0x90, 0xAF, 0x4B, 0x09, 0xAB, 0x92, 0x02, 0x68, 0x18, + 0x6C, 0x2C, 0x3D, 0x96, 0x1A, 0xDA, 0x8A, 0x75, 0x15, 0x2B, 0x2A, 0x96, + 0x53, 0x2C, 0xA6, 0x58, 0x4B, 0xB1, 0x92, 0x62, 0x1D, 0xC5, 0x22, 0x8A, + 0xF5, 0x13, 0x6B, 0x27, 0x96, 0xAD, 0x5F, 0x31, 0x0B, 0x46, 0x95, 0x16, + 0xE4, 0x96, 0x6A, 0x51, 0x0F, 0x93, 0x24, 0x9D, 0xC4, 0x28, 0xBD, 0x3E, + 0xB2, 0x43, 0xDE, 0xD2, 0x7B, 0x4B, 0xDE, 0x80, 0xB0, 0x11, 0x0B, 0x10, + 0x6F, 0x3E, 0x71, 0xE8, 0x4D, 0x08, 0x59, 0xD0, 0x15, 0xC2, 0xA4, 0x23, + 0xE4, 0xA3, 0xB7, 0x5D, 0x91, 0xBB, 0x5B, 0x03, 0x5A, 0x9B, 0xE4, 0x40, + 0xBA, 0x12, 0xD4, 0xD3, 0x38, 0xFF, 0xBC, 0xB0, 0x76, 0x51, 0xED, 0x52, + 0xDA, 0x15, 0xB4, 0x13, 0x6F, 0xE7, 0x2B, 0xC8, 0xB3, 0x3B, 0x49, 0x0F, + 0x31, 0x6C, 0x61, 0xE4, 0x55, 0x2F, 0x7F, 0xEE, 0x52, 0x27, 0x1A, 0x3F, + 0xA4, 0xC2, 0xA8, 0x87, 0xE6, 0x8D, 0x10, 0xD8, 0x98, 0x95, 0xCD, 0x11, + 0x83, 0x95, 0x7D, 0xB9, 0xA5, 0x1E, 0x1E, 0x29, 0x72, 0xF2, 0x2E, 0x1D, + 0x93, 0x69, 0xE9, 0x00, 0xE9, 0xAA, 0x20, 0xF0, 0xD9, 0x25, 0x37, 0x86, + 0x57, 0xE6, 0xB5, 0x60, 0x80, 0xE6, 0x30, 0xE0, 0xF2, 0x90, 0x52, 0xE8, + 0xD2, 0x93, 0xCF, 0xB7, 0x65, 0xE8, 0xBA, 0x92, 0x7A, 0xCC, 0x9F, 0x5D, + 0x30, 0x1D, 0xF1, 0x29, 0x09, 0x46, 0x1A, 0x7F, 0xB2, 0xD5, 0x2B, 0xFE, + 0x24, 0x32, 0x94, 0xA4, 0xAE, 0x5D, 0x5C, 0x4A, 0x6C, 0x49, 0xFD, 0x7F, + 0xBE, 0x87, 0x2C, 0x4E, 0x9F, 0xCA, 0x9A, 0x26, 0x0F, 0xE6, 0xF8, 0x0E, + 0x65, 0xC1, 0x86, 0xD5, 0xE4, 0x00, 0x50, 0xF3, 0xE4, 0x92, 0x04, 0xD8, + 0x6B, 0x48, 0x52, 0xF1, 0xD4, 0x24, 0x99, 0xCD, 0x46, 0x0E, 0x2F, 0x65, + 0xC4, 0xEF, 0xD5, 0x48, 0xD7, 0x47, 0xFE, 0x08, 0x5C, 0x28, 0x72, 0x05, + 0xDC, 0xC5, 0xCE, 0xA4, 0x48, 0xC9, 0x19, 0x77, 0x38, 0x35, 0x55, 0x61, + 0x36, 0x3B, 0xD0, 0xB4, 0x03, 0x5D, 0x1F, 0xC4, 0xC8, 0x35, 0x48, 0x39, + 0x4D, 0x42, 0x22, 0x40, 0xA3, 0xDC, 0xBC, 0x27, 0xCE, 0xB9, 0xB7, 0x68, + 0x94, 0x93, 0x48, 0xB3, 0xAE, 0x66, 0x9E, 0xAF, 0x1F, 0x4F, 0x9F, 0xDE, + 0xBC, 0x84, 0xCE, 0x69, 0x7C, 0x91, 0xE9, 0x56, 0x05, 0xA5, 0x4C, 0x12, + 0x7A, 0x06, 0x62, 0x75, 0xF1, 0x6A, 0xBE, 0x3C, 0x27, 0xEE, 0xE3, 0xFD, + 0x6D, 0x4A, 0x6A, 0xBC, 0x1B, 0xC7, 0x4F, 0xF6, 0xE3, 0x98, 0x0F, 0xB3, + 0x1A, 0xAE, 0x9B, 0x6A, 0x86, 0x8C, 0x21, 0x62, 0x46, 0x92, 0xBA, 0x0D, + 0x0A, 0xF6, 0x60, 0xF2, 0x0A, 0x31, 0x13, 0x91, 0x20, 0xFF, 0xEE, 0x4E, + 0x9B, 0x97, 0x08, 0xD2, 0x2A, 0xA2, 0x2C, 0x6C, 0x53, 0xEB, 0x56, 0xDD, + 0x95, 0x6F, 0x6F, 0x21, 0x13, 0x7B, 0x90, 0x37, 0xC6, 0x6E, 0xB1, 0x4B, + 0x16, 0xEE, 0x24, 0xD8, 0x8C, 0x86, 0x2B, 0x9C, 0x34, 0xC3, 0xFE, 0x40, + 0x46, 0x59, 0xC1, 0xCE, 0x40, 0x02, 0xEF, 0xAF, 0xD0, 0x97, 0xD4, 0xBD, + 0x81, 0xF0, 0x18, 0x31, 0x2A, 0xA9, 0x8F, 0x5A, 0xE8, 0x8D, 0x30, 0xB5, + 0x03, 0x2F, 0x4E, 0xA3, 0xA6, 0x4C, 0xDD, 0x59, 0xB4, 0x61, 0x6A, 0x48, + 0xEA, 0x62, 0x9B, 0x4F, 0xA2, 0x1A, 0xA0, 0x87, 0x84, 0x7D, 0x9A, 0x2C, + 0x24, 0xF5, 0x70, 0x71, 0xF6, 0x0F, 0xB4, 0xEA, 0x39, 0xB4, 0x48, 0xE9, + 0x28, 0x6C, 0xA5, 0x9D, 0xDC, 0xFB, 0x68, 0x85, 0x96, 0xD0, 0x2C, 0xC6, + 0x6D, 0x61, 0xE6, 0x7B, 0x6A, 0x11, 0xFF, 0xC3, 0xB3, 0xC0, 0x9C, 0xCB, + 0x23, 0x8B, 0x01, 0x98, 0x60, 0x4A, 0x7A, 0x00, 0x47, 0x34, 0x64, 0x18, + 0x31, 0xA0, 0x07, 0x56, 0x07, 0x62, 0x62, 0x51, 0x03, 0x81, 0x39, 0xFE, + 0x2B, 0x64, 0x86, 0x0C, 0x86, 0x6E, 0x7A, 0x21, 0x13, 0x06, 0x0D, 0x7E, + 0xC3, 0xFA, 0x20, 0xE7, 0x0E, 0xC4, 0x1D, 0x80, 0x53, 0x1A, 0x87, 0x57, + 0x10, 0x9C, 0xD0, 0xC0, 0xC1, 0x66, 0x52, 0xD3, 0xDE, 0x8B, 0x67, 0x40, + 0xEB, 0x07, 0x73, 0x01, 0x4C, 0x87, 0x16, 0xE0, 0x45, 0xEF, 0xA7, 0x39, + 0xD6, 0x4E, 0xAA, 0x04, 0x67, 0xBD, 0x30, 0x9D, 0x0E, 0x82, 0x69, 0x51, + 0x48, 0xEC, 0x4B, 0x9A, 0x22, 0xB3, 0x24, 0xD3, 0xC1, 0x56, 0x39, 0x4F, + 0x45, 0xCE, 0xFE, 0xF7, 0xD5, 0x3F, 0x30, 0xBB, 0xD9, 0x9B}; +const uint8_t g_nlNL_Locale[] = { + 0x78, 0x9C, 0x95, 0x56, 0x4D, 0x4F, 0xDC, 0x30, 0x10, 0x3D, 0x53, 0xA9, + 0xFF, 0xC1, 0x8A, 0x8A, 0x68, 0x25, 0x96, 0x2D, 0x47, 0x50, 0x88, 0xB4, + 0x05, 0x0A, 0x15, 0x04, 0xAD, 0x58, 0xDA, 0xAA, 0x5C, 0x2A, 0x6F, 0x62, + 0x76, 0xBD, 0x24, 0xF6, 0xCA, 0x89, 0x41, 0xC9, 0xB1, 0x52, 0x8F, 0xFD, + 0x27, 0xAD, 0xDA, 0x5B, 0xFF, 0x4F, 0xA5, 0x4A, 0xFC, 0x8C, 0x8E, 0xF3, + 0x45, 0x12, 0x3B, 0x69, 0xC8, 0x05, 0xCF, 0x9B, 0xF7, 0xBC, 0x33, 0xCF, + 0xCE, 0x10, 0x3B, 0xE0, 0x1E, 0x0E, 0x08, 0x62, 0x38, 0x24, 0x07, 0x16, + 0x0B, 0x3E, 0x5F, 0x9C, 0x5B, 0xC8, 0x27, 0x91, 0x77, 0x60, 0x3D, 0x7C, + 0xFB, 0xFD, 0xF7, 0xEB, 0xAF, 0x87, 0x9F, 0x3F, 0x5E, 0xE6, 0xAB, 0x57, + 0x96, 0xF3, 0xFC, 0x19, 0x42, 0xB6, 0xE2, 0x33, 0x1F, 0x8B, 0x59, 0x12, + 0xCE, 0x79, 0x10, 0x15, 0xD2, 0x85, 0x20, 0x0B, 0x2E, 0x28, 0x66, 0x8A, + 0xB5, 0x81, 0xEC, 0x90, 0xB3, 0x78, 0x79, 0x01, 0xA9, 0x48, 0xC5, 0x1B, + 0x79, 0xEC, 0xAC, 0x30, 0x93, 0x58, 0x50, 0x7B, 0x9C, 0x87, 0xB5, 0xCC, + 0x0D, 0x99, 0x8B, 0x8E, 0x54, 0x88, 0xB1, 0x88, 0x0D, 0x38, 0x5E, 0x0B, + 0x1A, 0x98, 0xF8, 0xC4, 0xB4, 0xCB, 0x4A, 0x32, 0x33, 0x1C, 0x98, 0x60, + 0x2C, 0x17, 0x32, 0x8A, 0x65, 0x64, 0x48, 0x45, 0x64, 0x1D, 0x93, 0x70, + 0x4E, 0x84, 0x21, 0xC7, 0x6F, 0x63, 0x6E, 0xCE, 0x30, 0x7E, 0xD7, 0x25, + 0xF2, 0x89, 0xD7, 0x4E, 0xA1, 0x62, 0x5D, 0x19, 0x58, 0x37, 0x14, 0xE1, + 0xF9, 0x5C, 0x1C, 0x58, 0xBB, 0x56, 0xCB, 0x59, 0xB3, 0xAB, 0x26, 0x83, + 0xBA, 0xEC, 0x7C, 0x8A, 0x99, 0x66, 0x2F, 0xCD, 0x56, 0x9A, 0x5D, 0x34, + 0xFB, 0x67, 0xF6, 0xCE, 0x6C, 0x5B, 0xBF, 0x63, 0x3E, 0x4E, 0x6A, 0x17, + 0x10, 0x22, 0x27, 0xE5, 0x70, 0x71, 0xA1, 0x1A, 0xB5, 0xAE, 0x40, 0xB8, + 0x5E, 0x06, 0xD4, 0xA7, 0x2C, 0xD2, 0xD1, 0x7B, 0x4E, 0x4C, 0xB0, 0x0F, + 0xFB, 0x12, 0xA1, 0xE3, 0x77, 0x82, 0xAE, 0x74, 0x34, 0xC5, 0x71, 0x93, + 0x8C, 0xB2, 0x95, 0xA1, 0xF2, 0xD6, 0x49, 0xE7, 0x2D, 0x68, 0xE5, 0x6B, + 0x95, 0x6B, 0x45, 0x6B, 0xE5, 0x6A, 0x75, 0x6A, 0x25, 0x76, 0x17, 0x17, + 0x12, 0x41, 0x7D, 0x4A, 0xC2, 0xFA, 0xCB, 0x5D, 0x40, 0xCE, 0xC4, 0x85, + 0x63, 0x28, 0x83, 0x66, 0x6A, 0xDA, 0x4A, 0xA1, 0xC7, 0xB0, 0xB6, 0x39, + 0x11, 0xB8, 0xB6, 0x2F, 0x44, 0xCE, 0x9B, 0x43, 0x7B, 0xAC, 0xFE, 0x56, + 0xC0, 0xE4, 0xA8, 0x02, 0x50, 0xB6, 0x2A, 0x05, 0x30, 0x9B, 0xC6, 0xAD, + 0xE1, 0x94, 0xA3, 0x3E, 0x18, 0x3E, 0xC5, 0x31, 0xB8, 0xCE, 0x2A, 0x83, + 0x2B, 0xA4, 0x98, 0x5F, 0x37, 0x32, 0x08, 0x2C, 0xE7, 0x18, 0x1E, 0x74, + 0x84, 0x5C, 0x78, 0xD0, 0x27, 0x78, 0x54, 0xEF, 0x15, 0xB3, 0x4B, 0x1A, + 0x70, 0xB6, 0xB0, 0x9C, 0xA7, 0xAA, 0x42, 0xE2, 0x83, 0x68, 0x04, 0x9A, + 0xD1, 0x60, 0x4D, 0xB4, 0xE4, 0x22, 0xCE, 0x54, 0x23, 0x5D, 0x81, 0x50, + 0x03, 0x29, 0x7A, 0x8F, 0x69, 0xD8, 0xEA, 0xBD, 0x86, 0x34, 0x7A, 0x3F, + 0xDD, 0x77, 0xDD, 0xFD, 0xD9, 0x6C, 0x0B, 0x49, 0x29, 0xB6, 0xD0, 0xB5, + 0x3D, 0xAE, 0x11, 0xBB, 0x94, 0x79, 0xEB, 0x85, 0x72, 0xA0, 0x26, 0x6B, + 0xBC, 0x90, 0x0C, 0x12, 0x14, 0x5D, 0x2B, 0x49, 0x9B, 0xAF, 0x7A, 0x6E, + 0x75, 0x58, 0x9C, 0xF7, 0x15, 0xA0, 0xE5, 0x25, 0x38, 0x49, 0x5C, 0xFF, + 0xF6, 0x34, 0x8C, 0x66, 0xC7, 0x47, 0x6F, 0xEF, 0x3F, 0xE2, 0xE5, 0x59, + 0x7A, 0x9D, 0x5B, 0x55, 0x27, 0x65, 0x4A, 0x26, 0xD5, 0x20, 0x6E, 0xFA, + 0xD5, 0xC0, 0xCA, 0x7F, 0x94, 0x52, 0xDD, 0x5D, 0xCF, 0x72, 0xD2, 0xED, + 0x34, 0xDD, 0xDB, 0x49, 0xD3, 0xD4, 0x1E, 0x37, 0x78, 0xDD, 0x52, 0x4F, + 0x0A, 0x41, 0x98, 0x97, 0x58, 0xCE, 0x0B, 0x94, 0xAB, 0xF7, 0xF6, 0xA2, + 0xC1, 0xEA, 0x35, 0x11, 0x1E, 0x61, 0x71, 0xF1, 0xC3, 0x9B, 0xBA, 0x4E, + 0x39, 0xA2, 0x75, 0x51, 0x75, 0xF6, 0xD8, 0xEC, 0x46, 0x13, 0x2A, 0xB6, + 0x87, 0x99, 0x4A, 0x43, 0x0C, 0x97, 0x61, 0xBB, 0xDC, 0x25, 0x4F, 0x77, + 0x0A, 0x16, 0x82, 0xCB, 0x35, 0x55, 0x97, 0x60, 0x67, 0xA0, 0xA2, 0xEA, + 0x60, 0x73, 0xA0, 0x20, 0xA4, 0x4C, 0x46, 0x96, 0x33, 0x1A, 0x48, 0x4F, + 0x89, 0xE0, 0x96, 0xF3, 0x5A, 0x63, 0x3F, 0x1A, 0xD3, 0x38, 0xF1, 0xF2, + 0x38, 0x1A, 0xCE, 0x34, 0xC1, 0xF2, 0x1A, 0x66, 0x81, 0xE5, 0xFC, 0xF9, + 0xF2, 0x1D, 0xE6, 0x4C, 0x83, 0xD1, 0xA3, 0xA2, 0x11, 0x57, 0x0B, 0x18, + 0x2D, 0xEF, 0x2F, 0x9F, 0x20, 0xAB, 0x1F, 0x84, 0x26, 0xCA, 0x06, 0x9D, + 0x56, 0xB7, 0x7A, 0xD9, 0x93, 0x35, 0xB9, 0xC1, 0x5E, 0x39, 0x4C, 0xCB, + 0xB0, 0xD8, 0xD3, 0x4D, 0xE0, 0xFB, 0xCC, 0x47, 0x53, 0xF0, 0x67, 0x6C, + 0x26, 0x50, 0x46, 0x39, 0xEB, 0x21, 0x1C, 0x72, 0x29, 0x28, 0x11, 0x68, + 0x16, 0xFB, 0x1D, 0x8C, 0x89, 0x0F, 0xDF, 0x3F, 0x68, 0x4A, 0xFF, 0x4B, + 0x39, 0x85, 0xEF, 0x3D, 0x72, 0xDF, 0x4B, 0x99, 0x08, 0x3C, 0x87, 0x77, + 0xAC, 0x8F, 0x72, 0xB5, 0xC4, 0xB4, 0x83, 0x70, 0xC6, 0x53, 0x79, 0x8B, + 0xD1, 0x09, 0x8F, 0x97, 0xD4, 0x53, 0x3D, 0x8D, 0x3E, 0xBC, 0x43, 0x6E, + 0x3F, 0x19, 0x0C, 0xF0, 0x96, 0xBC, 0x24, 0x5F, 0xF6, 0xFE, 0x34, 0x70, + 0x17, 0xAA, 0x4B, 0x74, 0xDE, 0x4B, 0x9B, 0xF1, 0x41, 0x34, 0x37, 0x91, + 0x6C, 0xB1, 0xE2, 0x19, 0x33, 0x2F, 0x32, 0x1B, 0x6D, 0xB5, 0xF3, 0xB4, + 0xC7, 0xF9, 0xA7, 0xBA, 0xF3, 0x0F, 0xD5, 0xFA, 0xC0, 0xFA}; +const uint8_t g_ruRU_Locale[] = { + 0x78, 0x9C, 0xAD, 0x57, 0x4D, 0x4F, 0x13, 0x41, 0x18, 0x3E, 0x63, 0xE2, + 0x7F, 0x98, 0x6C, 0x24, 0x68, 0x02, 0xAD, 0x1E, 0x25, 0x65, 0x13, 0x22, + 0x0A, 0x06, 0xD7, 0x90, 0x16, 0x34, 0x72, 0x31, 0xDB, 0xDD, 0xA1, 0x5D, + 0xE8, 0xEE, 0x90, 0xE9, 0x6E, 0xB0, 0x7B, 0x2A, 0x85, 0xE8, 0x05, 0x25, + 0xE1, 0xA0, 0x47, 0xF4, 0xE4, 0xC9, 0x50, 0xBE, 0x12, 0x82, 0xB6, 0x24, + 0xFE, 0x82, 0xD9, 0xFF, 0x60, 0xD4, 0x9F, 0xE1, 0x3B, 0xFB, 0xD1, 0xEE, + 0xB7, 0xC5, 0xD8, 0x1E, 0x3A, 0xF3, 0x3E, 0xCF, 0xF3, 0xCE, 0xFB, 0xB5, + 0xD3, 0xB6, 0xD4, 0x20, 0x8A, 0xDC, 0xC0, 0xC8, 0x90, 0x75, 0x3C, 0x23, + 0x50, 0xEB, 0x65, 0x79, 0x45, 0x40, 0x2A, 0x6E, 0x2A, 0x33, 0xC2, 0x8F, + 0xAB, 0xDD, 0xDF, 0x47, 0x5F, 0x6E, 0xC3, 0xC7, 0xAF, 0xDE, 0x87, 0x9F, + 0xEF, 0x8F, 0xEE, 0x08, 0xE2, 0xCD, 0x1B, 0x08, 0x95, 0x38, 0xDF, 0x50, + 0x65, 0x5A, 0x69, 0xE9, 0x55, 0xD2, 0x68, 0xFA, 0xD2, 0x1A, 0xC5, 0x35, + 0x42, 0x35, 0xD9, 0xE0, 0xAC, 0x31, 0x54, 0xD2, 0x89, 0x61, 0xD6, 0x9F, + 0x02, 0xD4, 0xE4, 0xFB, 0x31, 0x6F, 0x2F, 0x3A, 0xFB, 0xAC, 0xC7, 0x4E, + 0x58, 0xD7, 0x69, 0x3B, 0xFB, 0xA5, 0xA2, 0x67, 0x0B, 0xC3, 0xBB, 0xEC, + 0x9C, 0x9D, 0x38, 0x6D, 0xD6, 0x65, 0x5F, 0x53, 0x09, 0xEC, 0x9B, 0xAB, + 0xED, 0xB0, 0x6E, 0x1A, 0xD8, 0x65, 0x57, 0xA0, 0x3D, 0xCF, 0xD3, 0xA6, + 0x02, 0x17, 0xCE, 0x3B, 0xD6, 0xCB, 0x86, 0x32, 0xDC, 0x75, 0x21, 0x91, + 0x53, 0x67, 0xC7, 0xD9, 0xCE, 0x08, 0xC7, 0xD9, 0x86, 0x50, 0x7A, 0x4E, + 0x07, 0x72, 0x3E, 0xCE, 0xC8, 0x97, 0xF5, 0xD9, 0x65, 0x3E, 0xA1, 0xC7, + 0xFA, 0x79, 0xF0, 0x19, 0x1C, 0x71, 0x09, 0x91, 0xC4, 0x09, 0xC8, 0x5F, + 0x0F, 0x1A, 0x10, 0x6E, 0x08, 0x92, 0xAB, 0x55, 0x3A, 0x23, 0xDC, 0x13, + 0x92, 0x9D, 0x29, 0xE4, 0x34, 0x25, 0x0D, 0x1B, 0xA1, 0x1F, 0x99, 0xB2, + 0xFF, 0xDD, 0x8A, 0xD4, 0xD8, 0xFD, 0x1E, 0xA4, 0x06, 0xE1, 0x16, 0x3F, + 0x15, 0xF1, 0xAB, 0x9E, 0x8A, 0xB9, 0x25, 0x2F, 0xE4, 0xD7, 0x5A, 0x95, + 0x5B, 0xA1, 0xD1, 0x87, 0x9D, 0x08, 0x01, 0xF6, 0x21, 0x98, 0x4B, 0x3E, + 0x9F, 0x7E, 0x50, 0x7B, 0xEC, 0xBC, 0x54, 0xE4, 0xD8, 0x90, 0x74, 0x05, + 0x31, 0xF5, 0x00, 0x3C, 0x73, 0x87, 0x78, 0x0F, 0xD6, 0x17, 0xEC, 0x32, + 0x4E, 0x3A, 0x81, 0x72, 0xF7, 0xC1, 0x4F, 0x1A, 0x08, 0xC3, 0xD8, 0x76, + 0xF5, 0xDD, 0x38, 0xF0, 0x06, 0xCE, 0xED, 0x40, 0x14, 0xE7, 0x40, 0x38, + 0x4D, 0x9C, 0xEB, 0xEC, 0x03, 0x08, 0x0E, 0x9D, 0xD7, 0x49, 0xE5, 0xB6, + 0xB3, 0xC3, 0x8E, 0xE1, 0xDD, 0xF7, 0xDA, 0xEC, 0x83, 0xC8, 0x5D, 0xA5, + 0xE4, 0x1C, 0x9B, 0x2E, 0xD7, 0xFF, 0x81, 0xB3, 0x1D, 0x3F, 0xF2, 0x90, + 0xF5, 0xE2, 0xA6, 0x03, 0xA7, 0x13, 0x37, 0x7D, 0x72, 0xDA, 0x71, 0xD3, + 0xE7, 0x24, 0xEB, 0x30, 0x45, 0xC8, 0x8E, 0xB3, 0x43, 0xD5, 0x31, 0xD5, + 0x54, 0x0D, 0xEB, 0xE1, 0xEB, 0xC9, 0x37, 0x89, 0xB3, 0x12, 0xB4, 0x33, + 0xD8, 0x44, 0xA1, 0xA5, 0x18, 0x84, 0x86, 0xDB, 0x90, 0x73, 0x4C, 0xE5, + 0x90, 0x5F, 0xD8, 0xF1, 0x91, 0xE9, 0x23, 0xD6, 0x2B, 0x38, 0x6F, 0x61, + 0x6C, 0xB8, 0x61, 0x88, 0x44, 0x8D, 0xC8, 0x5D, 0x05, 0x6A, 0xB8, 0x6A, + 0x8B, 0xB1, 0xBB, 0xD6, 0xB3, 0xAA, 0xB2, 0x89, 0x97, 0x64, 0xD3, 0xC4, + 0xD4, 0x18, 0xD4, 0x7E, 0x60, 0xF1, 0xAF, 0xE3, 0x35, 0xAB, 0xD1, 0x10, + 0xC4, 0x39, 0x24, 0xC1, 0x0B, 0xBD, 0x80, 0x17, 0x9A, 0x80, 0x27, 0x64, + 0x82, 0x57, 0x62, 0x40, 0xCD, 0xD2, 0x36, 0x88, 0x51, 0xFB, 0x57, 0xAD, + 0x8E, 0x55, 0x90, 0xCE, 0x15, 0x24, 0xA9, 0xC0, 0x95, 0x23, 0x69, 0x9A, + 0x75, 0x42, 0xCD, 0xA1, 0x2A, 0xAE, 0x41, 0x28, 0x62, 0xF1, 0x8B, 0x60, + 0x6A, 0x7A, 0xAC, 0x08, 0x21, 0x4B, 0xA4, 0x08, 0x0B, 0xD3, 0x92, 0x34, + 0x5D, 0xA9, 0xA0, 0xD5, 0x52, 0x31, 0x44, 0xC9, 0xD2, 0x78, 0xC9, 0x5F, + 0x4F, 0xE3, 0x26, 0xED, 0x4B, 0x46, 0x12, 0xF8, 0x19, 0x73, 0x49, 0x9C, + 0xCF, 0xB3, 0x8D, 0xE5, 0xE6, 0xB7, 0x7C, 0x19, 0xAC, 0xC1, 0x1C, 0xCC, + 0xCB, 0xC6, 0xFA, 0xC6, 0x82, 0xDE, 0xAC, 0x3C, 0x9C, 0x7B, 0xB4, 0xF5, + 0xFC, 0x55, 0x7D, 0xD1, 0x5E, 0xF5, 0x8A, 0x14, 0x26, 0xB9, 0x4A, 0xC3, + 0xD2, 0xAB, 0x98, 0x46, 0x2B, 0x15, 0xB1, 0xF9, 0x21, 0x81, 0x0D, 0x66, + 0x59, 0x11, 0x44, 0x7B, 0xD2, 0xB6, 0xEF, 0x17, 0x6C, 0xDB, 0x2E, 0x15, + 0x23, 0xBC, 0x6C, 0xA9, 0x62, 0x51, 0x8A, 0x0D, 0xA5, 0x35, 0xD4, 0xDE, + 0x1A, 0x59, 0xBB, 0x89, 0xA9, 0x82, 0x0D, 0xD3, 0x97, 0x8E, 0x27, 0x75, + 0xBC, 0x1E, 0x89, 0x1C, 0x06, 0x79, 0x0D, 0x53, 0x1D, 0x8B, 0x9A, 0x7C, + 0xF7, 0x2A, 0x56, 0x34, 0x5D, 0x86, 0x21, 0x98, 0x0C, 0xBC, 0x78, 0x70, + 0xA6, 0xA0, 0x46, 0x89, 0xB5, 0xA9, 0xF1, 0x11, 0xF8, 0xFE, 0x71, 0x44, + 0xC9, 0x20, 0x85, 0xF1, 0x11, 0x05, 0xBA, 0x66, 0x58, 0x4D, 0x41, 0x9C, + 0x1A, 0x91, 0x6E, 0x63, 0x4A, 0x04, 0xF1, 0x6E, 0x82, 0x3D, 0xAC, 0x4C, + 0xA4, 0xE1, 0x41, 0x37, 0x22, 0xA5, 0x89, 0x1A, 0x83, 0x29, 0x74, 0x37, + 0x82, 0xE8, 0x7E, 0x47, 0x47, 0x19, 0x39, 0x2A, 0xAD, 0x49, 0xF8, 0x42, + 0x10, 0xCB, 0x2B, 0xE5, 0x6B, 0xC8, 0xC2, 0x9D, 0x48, 0x88, 0xDC, 0xAB, + 0x2E, 0x11, 0x37, 0x7F, 0xCA, 0x5B, 0x9B, 0x78, 0x4D, 0x56, 0x82, 0xBB, + 0x35, 0xD8, 0xFA, 0x3E, 0xA5, 0x16, 0xFC, 0xE0, 0x54, 0xD1, 0x12, 0xD4, + 0xA7, 0x98, 0x4E, 0xD0, 0x0C, 0x8D, 0x18, 0x39, 0x84, 0x07, 0xC4, 0xA2, + 0x1A, 0xA6, 0xA8, 0x62, 0xAA, 0x19, 0x8C, 0x59, 0x95, 0x54, 0x31, 0x5A, + 0xD2, 0xFE, 0x4A, 0x59, 0xC0, 0x55, 0x8A, 0xB7, 0x72, 0x29, 0xB3, 0x54, + 0xAE, 0xC2, 0x23, 0x96, 0x47, 0x59, 0xAE, 0xCB, 0x5A, 0x06, 0x61, 0x91, + 0xD8, 0xD6, 0x86, 0x8C, 0xE6, 0x89, 0x59, 0xD7, 0x14, 0x9E, 0xD3, 0xD4, + 0xB3, 0xC7, 0x48, 0xCA, 0x27, 0x43, 0x01, 0x94, 0x3A, 0x09, 0xC8, 0xE5, + 0xDC, 0xA3, 0x81, 0x5B, 0xE3, 0x59, 0xA2, 0x27, 0xB9, 0xB4, 0x0A, 0x19, + 0x89, 0x26, 0xB5, 0x2C, 0xA3, 0xB6, 0x4E, 0x5C, 0xA6, 0x17, 0xA4, 0x7B, + 0xB3, 0x85, 0xFA, 0x59, 0x2A, 0x7A, 0xFF, 0x3D, 0xC4, 0x3F, 0xDE, 0xCB, + 0x8B, 0xC4}; + +static std::unique_ptr<IFX_Locale> XFA_GetLocaleFromBuffer(const uint8_t* pBuf, + int nBufLen) { + if (!pBuf || nBufLen <= 0) + return nullptr; + + uint8_t* pOut = nullptr; + uint32_t dwSize; + CCodec_ModuleMgr* pCodecMgr = CPDF_ModuleMgr::Get()->GetCodecModule(); + pCodecMgr->GetFlateModule()->FlateOrLZWDecode(false, pBuf, nBufLen, true, 0, + 0, 0, 0, 0, &pOut, &dwSize); + if (!pOut) + return nullptr; + + std::unique_ptr<CXML_Element> pLocale = CXML_Element::Parse(pOut, dwSize); + FX_Free(pOut); + return pLocale ? pdfium::MakeUnique<CXFA_XMLLocale>(std::move(pLocale)) + : nullptr; +} + +static uint16_t XFA_GetLanguage(WideString wsLanguage) { + if (wsLanguage.GetLength() < 2) + return FX_LANG_en_US; + + wsLanguage.MakeLower(); + uint32_t dwIDFirst = wsLanguage[0] << 8 | wsLanguage[1]; + uint32_t dwIDSecond = + wsLanguage.GetLength() >= 5 ? wsLanguage[3] << 8 | wsLanguage[4] : 0; + switch (dwIDFirst) { + case FXBSTR_ID(0, 0, 'z', 'h'): + if (dwIDSecond == FXBSTR_ID(0, 0, 'c', 'n')) + return FX_LANG_zh_CN; + if (dwIDSecond == FXBSTR_ID(0, 0, 't', 'w')) + return FX_LANG_zh_TW; + if (dwIDSecond == FXBSTR_ID(0, 0, 'h', 'k')) + return FX_LANG_zh_HK; + break; + case FXBSTR_ID(0, 0, 'j', 'a'): + return FX_LANG_ja_JP; + case FXBSTR_ID(0, 0, 'k', 'o'): + return FX_LANG_ko_KR; + case FXBSTR_ID(0, 0, 'e', 'n'): + return dwIDSecond == FXBSTR_ID(0, 0, 'g', 'b') ? FX_LANG_en_GB + : FX_LANG_en_US; + case FXBSTR_ID(0, 0, 'd', 'e'): + return FX_LANG_de_DE; + case FXBSTR_ID(0, 0, 'f', 'r'): + return FX_LANG_fr_FR; + case FXBSTR_ID(0, 0, 'e', 's'): + return dwIDSecond == FXBSTR_ID(0, 0, 'e', 's') ? FX_LANG_es_ES + : FX_LANG_es_LA; + case FXBSTR_ID(0, 0, 'i', 't'): + return FX_LANG_it_IT; + case FXBSTR_ID(0, 0, 'p', 't'): + return FX_LANG_pt_BR; + case FXBSTR_ID(0, 0, 'n', 'l'): + return FX_LANG_nl_NL; + case FXBSTR_ID(0, 0, 'r', 'u'): + return FX_LANG_ru_RU; + } + return FX_LANG_en_US; +} + +CXFA_LocaleMgr::CXFA_LocaleMgr(CXFA_Node* pLocaleSet, WideString wsDeflcid) + : m_dwLocaleFlags(0x00) { + m_dwDeflcid = XFA_GetLanguage(wsDeflcid); + if (pLocaleSet) { + CXFA_Node* pNodeLocale = pLocaleSet->GetFirstChild(); + while (pNodeLocale) { + m_LocaleArray.push_back(pdfium::MakeUnique<CXFA_NodeLocale>(pNodeLocale)); + pNodeLocale = pNodeLocale->GetNextSibling(); + } + } + m_pDefLocale = GetLocaleByName(wsDeflcid); +} + +CXFA_LocaleMgr::~CXFA_LocaleMgr() {} + +uint16_t CXFA_LocaleMgr::GetDefLocaleID() const { + return m_dwDeflcid; +} + +IFX_Locale* CXFA_LocaleMgr::GetDefLocale() { + if (m_pDefLocale) + return m_pDefLocale; + + if (!m_LocaleArray.empty()) + return m_LocaleArray[0].get(); + + if (!m_XMLLocaleArray.empty()) + return m_XMLLocaleArray[0].get(); + + std::unique_ptr<IFX_Locale> locale(GetLocale(m_dwDeflcid)); + m_pDefLocale = locale.get(); + if (locale) + m_XMLLocaleArray.push_back(std::move(locale)); + + return m_pDefLocale; +} + +std::unique_ptr<IFX_Locale> CXFA_LocaleMgr::GetLocale(uint16_t lcid) { + switch (lcid) { + case FX_LANG_zh_CN: + return XFA_GetLocaleFromBuffer(g_zhCN_Locale, sizeof(g_zhCN_Locale)); + case FX_LANG_zh_TW: + return XFA_GetLocaleFromBuffer(g_zhTW_Locale, sizeof(g_zhTW_Locale)); + case FX_LANG_zh_HK: + return XFA_GetLocaleFromBuffer(g_zhHK_Locale, sizeof(g_zhHK_Locale)); + case FX_LANG_ja_JP: + return XFA_GetLocaleFromBuffer(g_jaJP_Locale, sizeof(g_jaJP_Locale)); + case FX_LANG_ko_KR: + return XFA_GetLocaleFromBuffer(g_koKR_Locale, sizeof(g_koKR_Locale)); + case FX_LANG_en_GB: + return XFA_GetLocaleFromBuffer(g_enGB_Locale, sizeof(g_enGB_Locale)); + case FX_LANG_es_LA: + return XFA_GetLocaleFromBuffer(g_esLA_Locale, sizeof(g_esLA_Locale)); + case FX_LANG_es_ES: + return XFA_GetLocaleFromBuffer(g_esES_Locale, sizeof(g_esES_Locale)); + case FX_LANG_de_DE: + return XFA_GetLocaleFromBuffer(g_deDE_Loacale, sizeof(g_deDE_Loacale)); + case FX_LANG_fr_FR: + return XFA_GetLocaleFromBuffer(g_frFR_Locale, sizeof(g_frFR_Locale)); + case FX_LANG_it_IT: + return XFA_GetLocaleFromBuffer(g_itIT_Locale, sizeof(g_itIT_Locale)); + case FX_LANG_pt_BR: + return XFA_GetLocaleFromBuffer(g_ptBR_Locale, sizeof(g_ptBR_Locale)); + case FX_LANG_nl_NL: + return XFA_GetLocaleFromBuffer(g_nlNL_Locale, sizeof(g_nlNL_Locale)); + case FX_LANG_ru_RU: + return XFA_GetLocaleFromBuffer(g_ruRU_Locale, sizeof(g_ruRU_Locale)); + case FX_LANG_en_US: + default: + return XFA_GetLocaleFromBuffer(g_enUS_Locale, sizeof(g_enUS_Locale)); + } +} + +IFX_Locale* CXFA_LocaleMgr::GetLocaleByName(const WideString& wsLocaleName) { + for (size_t i = 0; i < m_LocaleArray.size(); i++) { + IFX_Locale* pLocale = m_LocaleArray[i].get(); + if (pLocale->GetName() == wsLocaleName) + return pLocale; + } + if (wsLocaleName.GetLength() < 2) + return nullptr; + for (size_t i = 0; i < m_XMLLocaleArray.size(); i++) { + IFX_Locale* pLocale = m_XMLLocaleArray[i].get(); + if (pLocale->GetName() == wsLocaleName) + return pLocale; + } + + std::unique_ptr<IFX_Locale> pLocale(GetLocale(XFA_GetLanguage(wsLocaleName))); + IFX_Locale* pRetLocale = pLocale.get(); + if (pLocale) + m_XMLLocaleArray.push_back(std::move(pLocale)); + return pRetLocale; +} + +void CXFA_LocaleMgr::SetDefLocale(IFX_Locale* pLocale) { + m_pDefLocale = pLocale; +} + +WideStringView CXFA_LocaleMgr::GetConfigLocaleName(CXFA_Node* pConfig) { + if (!(m_dwLocaleFlags & 0x01)) { + m_wsConfigLocale.clear(); + if (pConfig) { + CXFA_Node* pChildfConfig = + pConfig->GetFirstChildByClass<CXFA_Acrobat>(XFA_Element::Acrobat); + if (!pChildfConfig) { + pChildfConfig = + pConfig->GetFirstChildByClass<CXFA_Present>(XFA_Element::Present); + } + CXFA_Common* pCommon = + pChildfConfig ? pChildfConfig->GetFirstChildByClass<CXFA_Common>( + XFA_Element::Common) + : nullptr; + CXFA_Locale* pLocale = + pCommon + ? pCommon->GetFirstChildByClass<CXFA_Locale>(XFA_Element::Locale) + : nullptr; + if (pLocale) { + m_wsConfigLocale = pLocale->JSObject() + ->TryCData(XFA_Attribute::Value, false) + .value_or(WideString()); + } + } + m_dwLocaleFlags |= 0x01; + } + return m_wsConfigLocale.AsStringView(); +} diff --git a/xfa/fxfa/parser/cxfa_localemgr.h b/xfa/fxfa/parser/cxfa_localemgr.h new file mode 100644 index 0000000000000000000000000000000000000000..d77a94a5196d7891c6916d917badd3d8c2e4620e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_localemgr.h @@ -0,0 +1,43 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LOCALEMGR_H_ +#define XFA_FXFA_PARSER_CXFA_LOCALEMGR_H_ + +#include <memory> +#include <vector> + +#include "core/fxcrt/cfx_datetime.h" +#include "core/fxcrt/ifx_locale.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" + +class CXFA_Node; +class IFX_Locale; + +class CXFA_LocaleMgr { + public: + CXFA_LocaleMgr(CXFA_Node* pLocaleSet, WideString wsDeflcid); + ~CXFA_LocaleMgr(); + + uint16_t GetDefLocaleID() const; + IFX_Locale* GetDefLocale(); + IFX_Locale* GetLocaleByName(const WideString& wsLocaleName); + + void SetDefLocale(IFX_Locale* pLocale); + WideStringView GetConfigLocaleName(CXFA_Node* pConfig); + + private: + std::unique_ptr<IFX_Locale> GetLocale(uint16_t lcid); + + std::vector<std::unique_ptr<IFX_Locale>> m_LocaleArray; + std::vector<std::unique_ptr<IFX_Locale>> m_XMLLocaleArray; + IFX_Locale* m_pDefLocale; // owned by m_LocaleArray or m_XMLLocaleArray. + WideString m_wsConfigLocale; + uint16_t m_dwDeflcid; + uint16_t m_dwLocaleFlags; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LOCALEMGR_H_ diff --git a/xfa/fxfa/parser/cxfa_localeset.cpp b/xfa/fxfa/parser/cxfa_localeset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b669e3b1081a5f8fabd592c535154603344fad57 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_localeset.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_localeset.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"localeSet"; + +} // namespace + +CXFA_LocaleSet::CXFA_LocaleSet(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet), + XFA_ObjectType::ModelNode, + XFA_Element::LocaleSet, + nullptr, + kAttributeData, + kName) {} + +CXFA_LocaleSet::~CXFA_LocaleSet() {} diff --git a/xfa/fxfa/parser/cxfa_localeset.h b/xfa/fxfa/parser/cxfa_localeset.h new file mode 100644 index 0000000000000000000000000000000000000000..1d65ad11dc216f9e1a2127c5306b8ef6d9dde774 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_localeset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LOCALESET_H_ +#define XFA_FXFA_PARSER_CXFA_LOCALESET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_LocaleSet : public CXFA_Node { + public: + CXFA_LocaleSet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_LocaleSet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LOCALESET_H_ diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09e3577887a3ca071d7a410edb6ce38f91d1b09c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_localevalue.cpp @@ -0,0 +1,786 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_localevalue.h" + +#include <vector> + +#include "core/fxcrt/fx_extension.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fgas/crt/cfgas_formatstring.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +FX_LOCALECATEGORY ValueCategory(FX_LOCALECATEGORY eCategory, + uint32_t dwValueType) { + if (eCategory != FX_LOCALECATEGORY_Unknown) + return eCategory; + + switch (dwValueType) { + case XFA_VT_BOOLEAN: + case XFA_VT_INTEGER: + case XFA_VT_DECIMAL: + case XFA_VT_FLOAT: + return FX_LOCALECATEGORY_Num; + case XFA_VT_TEXT: + return FX_LOCALECATEGORY_Text; + case XFA_VT_DATE: + return FX_LOCALECATEGORY_Date; + case XFA_VT_TIME: + return FX_LOCALECATEGORY_Time; + case XFA_VT_DATETIME: + return FX_LOCALECATEGORY_DateTime; + } + return FX_LOCALECATEGORY_Unknown; +} + +bool ValueSplitDateTime(const WideString& wsDateTime, + WideString& wsDate, + WideString& wsTime) { + wsDate = L""; + wsTime = L""; + if (wsDateTime.IsEmpty()) + return false; + + auto nSplitIndex = wsDateTime.Find('T'); + if (!nSplitIndex.has_value()) + nSplitIndex = wsDateTime.Find(' '); + if (!nSplitIndex.has_value()) + return false; + + wsDate = wsDateTime.Left(nSplitIndex.value()); + wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex.value() - 1); + return true; +} + +} // namespace + +CXFA_LocaleValue::CXFA_LocaleValue() + : m_pLocaleMgr(nullptr), m_dwType(XFA_VT_NULL), m_bValid(true) {} + +CXFA_LocaleValue::CXFA_LocaleValue(const CXFA_LocaleValue& value) + : m_pLocaleMgr(value.m_pLocaleMgr), + m_wsValue(value.m_wsValue), + m_dwType(value.m_dwType), + m_bValid(value.m_bValid) {} + +CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, CXFA_LocaleMgr* pLocaleMgr) + : m_pLocaleMgr(pLocaleMgr), + m_dwType(dwType), + m_bValid(m_dwType != XFA_VT_NULL) {} + +CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, + const WideString& wsValue, + CXFA_LocaleMgr* pLocaleMgr) + : m_pLocaleMgr(pLocaleMgr), + m_wsValue(wsValue), + m_dwType(dwType), + m_bValid(ValidateCanonicalValue(wsValue, dwType)) {} + +CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, + const WideString& wsValue, + const WideString& wsFormat, + IFX_Locale* pLocale, + CXFA_LocaleMgr* pLocaleMgr) + : m_pLocaleMgr(pLocaleMgr), + m_dwType(dwType), + m_bValid(ParsePatternValue(wsValue, wsFormat, pLocale)) {} + +CXFA_LocaleValue& CXFA_LocaleValue::operator=(const CXFA_LocaleValue& value) { + m_wsValue = value.m_wsValue; + m_dwType = value.m_dwType; + m_bValid = value.m_bValid; + m_pLocaleMgr = value.m_pLocaleMgr; + return *this; +} + +CXFA_LocaleValue::~CXFA_LocaleValue() {} + +bool CXFA_LocaleValue::ValidateValue(const WideString& wsValue, + const WideString& wsPattern, + IFX_Locale* pLocale, + WideString* pMatchFormat) { + WideString wsOutput; + IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); + if (pLocale) + m_pLocaleMgr->SetDefLocale(pLocale); + + auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); + std::vector<WideString> wsPatterns; + pFormat->SplitFormatString(wsPattern, &wsPatterns); + + bool bRet = false; + int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); + int32_t i = 0; + for (; i < iCount && !bRet; i++) { + WideString wsFormat = wsPatterns[i]; + switch (ValueCategory(pFormat->GetCategory(wsFormat), m_dwType)) { + case FX_LOCALECATEGORY_Null: + bRet = pFormat->ParseNull(wsValue, wsFormat); + if (!bRet) + bRet = wsValue.IsEmpty(); + break; + case FX_LOCALECATEGORY_Zero: + bRet = pFormat->ParseZero(wsValue, wsFormat); + if (!bRet) + bRet = wsValue == L"0"; + break; + case FX_LOCALECATEGORY_Num: { + WideString fNum; + bRet = pFormat->ParseNum(wsValue, wsFormat, &fNum); + if (!bRet) + bRet = pFormat->FormatNum(wsValue, wsFormat, &wsOutput); + break; + } + case FX_LOCALECATEGORY_Text: + bRet = pFormat->ParseText(wsValue, wsFormat, &wsOutput); + wsOutput.clear(); + if (!bRet) + bRet = pFormat->FormatText(wsValue, wsFormat, &wsOutput); + break; + case FX_LOCALECATEGORY_Date: { + CFX_DateTime dt; + bRet = ValidateCanonicalDate(wsValue, &dt); + if (!bRet) { + bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, + &dt); + if (!bRet) { + bRet = pFormat->FormatDateTime(wsValue, wsFormat, + FX_DATETIMETYPE_Date, &wsOutput); + } + } + break; + } + case FX_LOCALECATEGORY_Time: { + CFX_DateTime dt; + bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, + &dt); + if (!bRet) { + bRet = pFormat->FormatDateTime(wsValue, wsFormat, + FX_DATETIMETYPE_Time, &wsOutput); + } + break; + } + case FX_LOCALECATEGORY_DateTime: { + CFX_DateTime dt; + bRet = pFormat->ParseDateTime(wsValue, wsFormat, + FX_DATETIMETYPE_DateTime, &dt); + if (!bRet) { + bRet = pFormat->FormatDateTime(wsValue, wsFormat, + FX_DATETIMETYPE_DateTime, &wsOutput); + } + break; + } + default: + bRet = false; + break; + } + } + if (bRet && pMatchFormat) + *pMatchFormat = wsPatterns[i - 1]; + if (pLocale) + m_pLocaleMgr->SetDefLocale(locale); + + return bRet; +} + +double CXFA_LocaleValue::GetDoubleNum() const { + if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER || + m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) { + int64_t nIntegral = 0; + uint32_t dwFractional = 0; + int32_t nExponent = 0; + int32_t cc = 0; + bool bNegative = false; + bool bExpSign = false; + const wchar_t* str = m_wsValue.c_str(); + int len = m_wsValue.GetLength(); + while (FXSYS_iswspace(str[cc]) && cc < len) + cc++; + + if (cc >= len) + return 0; + if (str[0] == '+') { + cc++; + } else if (str[0] == '-') { + bNegative = true; + cc++; + } + + int32_t nIntegralLen = 0; + while (cc < len) { + if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]) || + nIntegralLen > 17) { + break; + } + nIntegral = nIntegral * 10 + str[cc] - '0'; + cc++; + nIntegralLen++; + } + + nIntegral = bNegative ? -nIntegral : nIntegral; + int32_t scale = 0; + double fraction = 0.0; + if (cc < len && str[cc] == '.') { + cc++; + while (cc < len) { + fraction += XFA_GetFractionalScale(scale) * (str[cc] - '0'); + scale++; + cc++; + if (scale == XFA_GetMaxFractionalScale() || + !FXSYS_isDecimalDigit(str[cc])) { + break; + } + } + dwFractional = static_cast<uint32_t>(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 (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) + break; + + nExponent = nExponent * 10 + str[cc] - '0'; + cc++; + } + nExponent = bExpSign ? -nExponent : nExponent; + } + + double dValue = dwFractional / 4294967296.0; + dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); + if (nExponent != 0) + dValue *= FXSYS_pow(10, static_cast<float>(nExponent)); + + return dValue; + } + return 0; +} + +CFX_DateTime CXFA_LocaleValue::GetDate() const { + if (!m_bValid || m_dwType != XFA_VT_DATE) + return CFX_DateTime(); + + CFX_DateTime dt; + FX_DateFromCanonical(m_wsValue, &dt); + return dt; +} + +CFX_DateTime CXFA_LocaleValue::GetTime() const { + if (!m_bValid || m_dwType != XFA_VT_TIME) + return CFX_DateTime(); + + CFX_DateTime dt; + FX_TimeFromCanonical(m_wsValue.AsStringView(), &dt, + m_pLocaleMgr->GetDefLocale()); + return dt; +} + +bool CXFA_LocaleValue::SetDate(const CFX_DateTime& d) { + m_dwType = XFA_VT_DATE; + m_wsValue = WideString::Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(), + d.GetDay()); + return true; +} + +bool CXFA_LocaleValue::SetTime(const CFX_DateTime& t) { + m_dwType = XFA_VT_TIME; + m_wsValue = WideString::Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(), + t.GetSecond()); + if (t.GetMillisecond() > 0) + m_wsValue += WideString::Format(L"%:03d", t.GetMillisecond()); + return true; +} + +bool CXFA_LocaleValue::SetDateTime(const CFX_DateTime& dt) { + m_dwType = XFA_VT_DATETIME; + m_wsValue = WideString::Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(), + dt.GetMonth(), dt.GetDay(), dt.GetHour(), + dt.GetMinute(), dt.GetSecond()); + if (dt.GetMillisecond() > 0) + m_wsValue += WideString::Format(L"%:03d", dt.GetMillisecond()); + return true; +} + +bool CXFA_LocaleValue::FormatPatterns(WideString& wsResult, + const WideString& wsFormat, + IFX_Locale* pLocale, + XFA_VALUEPICTURE eValueType) const { + auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); + std::vector<WideString> wsPatterns; + pFormat->SplitFormatString(wsFormat, &wsPatterns); + wsResult.clear(); + int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); + for (int32_t i = 0; i < iCount; i++) { + if (FormatSinglePattern(wsResult, wsPatterns[i], pLocale, eValueType)) + return true; + } + return false; +} + +bool CXFA_LocaleValue::FormatSinglePattern(WideString& wsResult, + const WideString& wsFormat, + IFX_Locale* pLocale, + XFA_VALUEPICTURE eValueType) const { + IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); + if (pLocale) + m_pLocaleMgr->SetDefLocale(pLocale); + + wsResult.clear(); + bool bRet = false; + auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); + FX_LOCALECATEGORY eCategory = + ValueCategory(pFormat->GetCategory(wsFormat), m_dwType); + switch (eCategory) { + case FX_LOCALECATEGORY_Null: + if (m_wsValue.IsEmpty()) + bRet = pFormat->FormatNull(wsFormat, &wsResult); + break; + case FX_LOCALECATEGORY_Zero: + if (m_wsValue == L"0") + bRet = pFormat->FormatZero(wsFormat, &wsResult); + break; + case FX_LOCALECATEGORY_Num: + bRet = pFormat->FormatNum(m_wsValue, wsFormat, &wsResult); + break; + case FX_LOCALECATEGORY_Text: + bRet = pFormat->FormatText(m_wsValue, wsFormat, &wsResult); + break; + case FX_LOCALECATEGORY_Date: + bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, FX_DATETIMETYPE_Date, + &wsResult); + break; + case FX_LOCALECATEGORY_Time: + bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, FX_DATETIMETYPE_Time, + &wsResult); + break; + case FX_LOCALECATEGORY_DateTime: + bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, + FX_DATETIMETYPE_DateTime, &wsResult); + break; + default: + wsResult = m_wsValue; + bRet = true; + } + if (!bRet && (eCategory != FX_LOCALECATEGORY_Num || + eValueType != XFA_VALUEPICTURE_Display)) { + wsResult = m_wsValue; + } + if (pLocale) + m_pLocaleMgr->SetDefLocale(locale); + + return bRet; +} + +bool CXFA_LocaleValue::ValidateCanonicalValue(const WideString& wsValue, + uint32_t dwVType) { + if (wsValue.IsEmpty()) + return true; + + CFX_DateTime dt; + switch (dwVType) { + case XFA_VT_DATE: { + if (ValidateCanonicalDate(wsValue, &dt)) + return true; + + WideString wsDate; + WideString wsTime; + if (ValueSplitDateTime(wsValue, wsDate, wsTime) && + ValidateCanonicalDate(wsDate, &dt)) { + return true; + } + return false; + } + case XFA_VT_TIME: { + if (ValidateCanonicalTime(wsValue)) + return true; + + WideString wsDate; + WideString wsTime; + if (ValueSplitDateTime(wsValue, wsDate, wsTime) && + ValidateCanonicalTime(wsTime)) { + return true; + } + return false; + } + case XFA_VT_DATETIME: { + WideString wsDate, wsTime; + if (ValueSplitDateTime(wsValue, wsDate, wsTime) && + ValidateCanonicalDate(wsDate, &dt) && ValidateCanonicalTime(wsTime)) { + return true; + } + } break; + } + return true; +} + +bool CXFA_LocaleValue::ValidateCanonicalDate(const WideString& wsDate, + CFX_DateTime* unDate) { + static const uint16_t LastDay[12] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + static const uint16_t wCountY = 4; + static const uint16_t wCountM = 2; + static const uint16_t wCountD = 2; + int nLen = wsDate.GetLength(); + if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) + return false; + + const bool bSymbol = wsDate.Contains(0x2D); + uint16_t wYear = 0; + uint16_t wMonth = 0; + uint16_t wDay = 0; + const wchar_t* pDate = wsDate.c_str(); + int nIndex = 0; + int nStart = 0; + while (pDate[nIndex] != '\0' && nIndex < wCountY) { + if (!FXSYS_isDecimalDigit(pDate[nIndex])) + return false; + + wYear = (pDate[nIndex] - '0') + wYear * 10; + nIndex++; + } + if (bSymbol) { + if (pDate[nIndex] != 0x2D) + return false; + nIndex++; + } + + nStart = nIndex; + while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) { + if (!FXSYS_isDecimalDigit(pDate[nIndex])) + return false; + + wMonth = (pDate[nIndex] - '0') + wMonth * 10; + nIndex++; + } + if (bSymbol) { + if (pDate[nIndex] != 0x2D) + return false; + nIndex++; + } + + nStart = nIndex; + while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) { + if (!FXSYS_isDecimalDigit(pDate[nIndex])) + return false; + + wDay = (pDate[nIndex] - '0') + wDay * 10; + nIndex++; + } + if (nIndex != nLen) + return false; + if (wYear < 1900 || wYear > 2029) + return false; + if (wMonth < 1 || wMonth > 12) + return wMonth == 0 && nLen == wCountY; + if (wDay < 1) + return wDay == 0 && (nLen == wCountY + wCountM); + if (wMonth == 2) { + if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) { + if (wDay > 29) + return false; + } else if (wDay > 28) { + return false; + } + } else if (wDay > LastDay[wMonth - 1]) { + return false; + } + + unDate->SetDate(wYear, static_cast<uint8_t>(wMonth), + static_cast<uint8_t>(wDay)); + return true; +} + +bool CXFA_LocaleValue::ValidateCanonicalTime(const WideString& wsTime) { + int nLen = wsTime.GetLength(); + if (nLen < 2) + return false; + + const uint16_t wCountH = 2; + const uint16_t wCountM = 2; + const uint16_t wCountS = 2; + const uint16_t wCountF = 3; + const bool bSymbol = wsTime.Contains(':'); + uint16_t wHour = 0; + uint16_t wMinute = 0; + uint16_t wSecond = 0; + uint16_t wFraction = 0; + const wchar_t* pTime = wsTime.c_str(); + int nIndex = 0; + int nStart = 0; + while (nIndex - nStart < wCountH && pTime[nIndex]) { + if (!FXSYS_isDecimalDigit(pTime[nIndex])) + return false; + wHour = pTime[nIndex] - '0' + wHour * 10; + nIndex++; + } + if (bSymbol) { + if (nIndex < nLen && pTime[nIndex] != ':') + return false; + nIndex++; + } + + nStart = nIndex; + while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) { + if (!FXSYS_isDecimalDigit(pTime[nIndex])) + return false; + wMinute = pTime[nIndex] - '0' + wMinute * 10; + nIndex++; + } + if (bSymbol) { + if (nIndex < nLen && pTime[nIndex] != ':') + return false; + nIndex++; + } + nStart = nIndex; + while (nIndex - nStart < wCountS && nIndex < nLen && pTime[nIndex]) { + if (!FXSYS_isDecimalDigit(pTime[nIndex])) + return false; + wSecond = pTime[nIndex] - '0' + wSecond * 10; + nIndex++; + } + auto pos = wsTime.Find('.'); + if (pos.has_value() && pos.value() != 0) { + if (pTime[nIndex] != '.') + return false; + nIndex++; + nStart = nIndex; + while (nIndex - nStart < wCountF && nIndex < nLen && pTime[nIndex]) { + if (!FXSYS_isDecimalDigit(pTime[nIndex])) + return false; + wFraction = pTime[nIndex] - '0' + wFraction * 10; + nIndex++; + } + } + if (nIndex < nLen) { + if (pTime[nIndex] == 'Z') { + nIndex++; + } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') { + int16_t nOffsetH = 0; + int16_t nOffsetM = 0; + nIndex++; + nStart = nIndex; + while (nIndex - nStart < wCountH && nIndex < nLen && pTime[nIndex]) { + if (!FXSYS_isDecimalDigit(pTime[nIndex])) + return false; + nOffsetH = pTime[nIndex] - '0' + nOffsetH * 10; + nIndex++; + } + if (bSymbol) { + if (nIndex < nLen && pTime[nIndex] != ':') + return false; + nIndex++; + } + nStart = nIndex; + while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) { + if (!FXSYS_isDecimalDigit(pTime[nIndex])) + return false; + nOffsetM = pTime[nIndex] - '0' + nOffsetM * 10; + nIndex++; + } + if (nOffsetH > 12 || nOffsetM >= 60) + return false; + } + } + return nIndex == nLen && wHour < 24 && wMinute < 60 && wSecond < 60 && + wFraction <= 999; +} + +bool CXFA_LocaleValue::ParsePatternValue(const WideString& wsValue, + const WideString& wsPattern, + IFX_Locale* pLocale) { + IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); + if (pLocale) + m_pLocaleMgr->SetDefLocale(pLocale); + + auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); + std::vector<WideString> wsPatterns; + pFormat->SplitFormatString(wsPattern, &wsPatterns); + bool bRet = false; + int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); + for (int32_t i = 0; i < iCount && !bRet; i++) { + WideString wsFormat = wsPatterns[i]; + switch (ValueCategory(pFormat->GetCategory(wsFormat), m_dwType)) { + case FX_LOCALECATEGORY_Null: + bRet = pFormat->ParseNull(wsValue, wsFormat); + if (bRet) + m_wsValue.clear(); + break; + case FX_LOCALECATEGORY_Zero: + bRet = pFormat->ParseZero(wsValue, wsFormat); + if (bRet) + m_wsValue = L"0"; + break; + case FX_LOCALECATEGORY_Num: { + WideString fNum; + bRet = pFormat->ParseNum(wsValue, wsFormat, &fNum); + if (bRet) + m_wsValue = fNum; + break; + } + case FX_LOCALECATEGORY_Text: + bRet = pFormat->ParseText(wsValue, wsFormat, &m_wsValue); + break; + case FX_LOCALECATEGORY_Date: { + CFX_DateTime dt; + bRet = ValidateCanonicalDate(wsValue, &dt); + if (!bRet) { + bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, + &dt); + } + if (bRet) + SetDate(dt); + break; + } + case FX_LOCALECATEGORY_Time: { + CFX_DateTime dt; + bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, + &dt); + if (bRet) + SetTime(dt); + break; + } + case FX_LOCALECATEGORY_DateTime: { + CFX_DateTime dt; + bRet = pFormat->ParseDateTime(wsValue, wsFormat, + FX_DATETIMETYPE_DateTime, &dt); + if (bRet) + SetDateTime(dt); + break; + } + default: + m_wsValue = wsValue; + bRet = true; + break; + } + } + if (!bRet) + m_wsValue = wsValue; + + if (pLocale) + m_pLocaleMgr->SetDefLocale(locale); + + return bRet; +} + +void CXFA_LocaleValue::GetNumericFormat(WideString& wsFormat, + int32_t nIntLen, + int32_t nDecLen) { + ASSERT(wsFormat.IsEmpty()); + ASSERT(nIntLen >= -1 && nDecLen >= -1); + + int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + 1 + + (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1); + wchar_t* lpBuf = wsFormat.GetBuffer(nTotalLen); + int32_t nPos = 0; + lpBuf[nPos++] = L's'; + + if (nIntLen == -1) { + lpBuf[nPos++] = L'z'; + lpBuf[nPos++] = L'*'; + } else { + while (nIntLen) { + lpBuf[nPos++] = L'z'; + nIntLen--; + } + } + if (nDecLen != 0) { + lpBuf[nPos++] = L'.'; + } + if (nDecLen == -1) { + lpBuf[nPos++] = L'z'; + lpBuf[nPos++] = L'*'; + } else { + while (nDecLen) { + lpBuf[nPos++] = L'z'; + nDecLen--; + } + } + wsFormat.ReleaseBuffer(nTotalLen); +} + +bool CXFA_LocaleValue::ValidateNumericTemp(const WideString& wsNumeric, + const WideString& wsFormat, + IFX_Locale* pLocale) { + if (wsFormat.IsEmpty() || wsNumeric.IsEmpty()) + return true; + + const wchar_t* pNum = wsNumeric.c_str(); + const wchar_t* pFmt = wsFormat.c_str(); + int32_t n = 0; + int32_t nf = 0; + wchar_t c = pNum[n]; + wchar_t cf = pFmt[nf]; + if (cf == L's') { + if (c == L'-' || c == L'+') + ++n; + ++nf; + } + + bool bLimit = true; + int32_t nCount = wsNumeric.GetLength(); + int32_t nCountFmt = wsFormat.GetLength(); + while (n < nCount && (bLimit ? nf < nCountFmt : true) && + FXSYS_isDecimalDigit(c = pNum[n])) { + if (bLimit == true) { + if ((cf = pFmt[nf]) == L'*') + bLimit = false; + else if (cf == L'z') + nf++; + else + return false; + } + n++; + } + if (n == nCount) + return true; + if (nf == nCountFmt) + return false; + + while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') { + ASSERT(cf == L'z' || cf == L'*'); + ++nf; + } + + WideString wsDecimalSymbol; + if (pLocale) + wsDecimalSymbol = pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); + else + wsDecimalSymbol = WideString(L'.'); + + if (pFmt[nf] != L'.') + return false; + if (wsDecimalSymbol != WideStringView(c) && c != L'.') + return false; + + ++nf; + ++n; + bLimit = true; + while (n < nCount && (bLimit ? nf < nCountFmt : true) && + FXSYS_isDecimalDigit(c = pNum[n])) { + if (bLimit == true) { + if ((cf = pFmt[nf]) == L'*') + bLimit = false; + else if (cf == L'z') + nf++; + else + return false; + } + n++; + } + return n == nCount; +} diff --git a/xfa/fxfa/parser/cxfa_localevalue.h b/xfa/fxfa/parser/cxfa_localevalue.h new file mode 100644 index 0000000000000000000000000000000000000000..60de601c02a4fa5e9cbef36512d454d8868a494c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_localevalue.h @@ -0,0 +1,90 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LOCALEVALUE_H_ +#define XFA_FXFA_PARSER_CXFA_LOCALEVALUE_H_ + +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/fx_system.h" +#include "xfa/fxfa/cxfa_widgetacc.h" + +class IFX_Locale; +class CFX_DateTime; +class CXFA_LocaleMgr; + +#define XFA_VT_NULL 0 +#define XFA_VT_BOOLEAN 1 +#define XFA_VT_INTEGER 2 +#define XFA_VT_DECIMAL 4 +#define XFA_VT_FLOAT 8 +#define XFA_VT_TEXT 16 +#define XFA_VT_DATE 32 +#define XFA_VT_TIME 64 +#define XFA_VT_DATETIME 128 + +class CXFA_LocaleValue { + public: + CXFA_LocaleValue(); + CXFA_LocaleValue(const CXFA_LocaleValue& value); + CXFA_LocaleValue(uint32_t dwType, CXFA_LocaleMgr* pLocaleMgr); + CXFA_LocaleValue(uint32_t dwType, + const WideString& wsValue, + CXFA_LocaleMgr* pLocaleMgr); + CXFA_LocaleValue(uint32_t dwType, + const WideString& wsValue, + const WideString& wsFormat, + IFX_Locale* pLocale, + CXFA_LocaleMgr* pLocaleMgr); + ~CXFA_LocaleValue(); + CXFA_LocaleValue& operator=(const CXFA_LocaleValue& value); + + bool ValidateValue(const WideString& wsValue, + const WideString& wsPattern, + IFX_Locale* pLocale, + WideString* pMatchFormat); + + bool FormatPatterns(WideString& wsResult, + const WideString& wsFormat, + IFX_Locale* pLocale, + XFA_VALUEPICTURE eValueType) const; + + void GetNumericFormat(WideString& wsFormat, int32_t nIntLen, int32_t nDecLen); + bool ValidateNumericTemp(const WideString& wsNumeric, + const WideString& wsFormat, + IFX_Locale* pLocale); + + WideString GetValue() const { return m_wsValue; } + uint32_t GetType() const { return m_dwType; } + double GetDoubleNum() const; + bool SetDate(const CFX_DateTime& d); + CFX_DateTime GetDate() const; + CFX_DateTime GetTime() const; + + bool IsValid() const { return m_bValid; } + + private: + bool FormatSinglePattern(WideString& wsResult, + const WideString& wsFormat, + IFX_Locale* pLocale, + XFA_VALUEPICTURE eValueType) const; + bool ValidateCanonicalValue(const WideString& wsValue, uint32_t dwVType); + bool ValidateCanonicalDate(const WideString& wsDate, CFX_DateTime* unDate); + bool ValidateCanonicalTime(const WideString& wsTime); + + bool SetTime(const CFX_DateTime& t); + bool SetDateTime(const CFX_DateTime& dt); + + bool ParsePatternValue(const WideString& wsValue, + const WideString& wsPattern, + IFX_Locale* pLocale); + + CXFA_LocaleMgr* m_pLocaleMgr; + WideString m_wsValue; + uint32_t m_dwType; + bool m_bValid; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LOCALEVALUE_H_ diff --git a/xfa/fxfa/parser/cxfa_lockdocument.cpp b/xfa/fxfa/parser/cxfa_lockdocument.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e653347e098bd9edab44b5bf3b9445cd7b117fb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_lockdocument.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_lockdocument.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"lockDocument"; + +} // namespace + +CXFA_LockDocument::CXFA_LockDocument(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::LockDocument, + nullptr, + kAttributeData, + kName) {} + +CXFA_LockDocument::~CXFA_LockDocument() {} diff --git a/xfa/fxfa/parser/cxfa_lockdocument.h b/xfa/fxfa/parser/cxfa_lockdocument.h new file mode 100644 index 0000000000000000000000000000000000000000..025031ad7fe47e102d2e2d981e63a91149f3d4bf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_lockdocument.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LOCKDOCUMENT_H_ +#define XFA_FXFA_PARSER_CXFA_LOCKDOCUMENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_LockDocument : public CXFA_Node { + public: + CXFA_LockDocument(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_LockDocument() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LOCKDOCUMENT_H_ diff --git a/xfa/fxfa/parser/cxfa_log.cpp b/xfa/fxfa/parser/cxfa_log.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38651cb719404abb93bcfeca31cc8bad18938ea7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_log.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_log.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::To, 1, 0}, + {XFA_Element::Uri, 1, 0}, + {XFA_Element::Mode, 1, 0}, + {XFA_Element::Threshold, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"log"; + +} // namespace + +CXFA_Log::CXFA_Log(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Log, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Log::~CXFA_Log() {} diff --git a/xfa/fxfa/parser/cxfa_log.h b/xfa/fxfa/parser/cxfa_log.h new file mode 100644 index 0000000000000000000000000000000000000000..17fd290f470c436ccca3eebdff20a2c6ea41b4e0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_log.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_LOG_H_ +#define XFA_FXFA_PARSER_CXFA_LOG_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Log : public CXFA_Node { + public: + CXFA_Log(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Log() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_LOG_H_ diff --git a/xfa/fxfa/parser/cxfa_manifest.cpp b/xfa/fxfa/parser/cxfa_manifest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32ec7954194c955cedc36818e8809c982d3e39de --- /dev/null +++ b/xfa/fxfa/parser/cxfa_manifest.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_manifest.h" + +#include "fxjs/xfa/cjx_manifest.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Action, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Include}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"manifest"; + +} // namespace + +CXFA_Manifest::CXFA_Manifest(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Manifest, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Manifest>(this)) {} + +CXFA_Manifest::~CXFA_Manifest() {} diff --git a/xfa/fxfa/parser/cxfa_manifest.h b/xfa/fxfa/parser/cxfa_manifest.h new file mode 100644 index 0000000000000000000000000000000000000000..a13cdacfaeb606d195fff21dffb780a92c82affa --- /dev/null +++ b/xfa/fxfa/parser/cxfa_manifest.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MANIFEST_H_ +#define XFA_FXFA_PARSER_CXFA_MANIFEST_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Manifest : public CXFA_Node { + public: + CXFA_Manifest(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Manifest() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MANIFEST_H_ diff --git a/xfa/fxfa/parser/cxfa_map.cpp b/xfa/fxfa/parser/cxfa_map.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e0c041544e8f15b3ccaf0b639b07f337ae34f4d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_map.cpp @@ -0,0 +1,40 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_map.h" + +#include "fxjs/xfa/cjx_map.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Bind, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::From, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"map"; + +} // namespace + +CXFA_Map::CXFA_Map(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_SourceSet), + XFA_ObjectType::Node, + XFA_Element::Map, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Map>(this)) {} + +CXFA_Map::~CXFA_Map() {} diff --git a/xfa/fxfa/parser/cxfa_map.h b/xfa/fxfa/parser/cxfa_map.h new file mode 100644 index 0000000000000000000000000000000000000000..c49568f9ce1e3be908895fca7282505c58dea61d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_map.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MAP_H_ +#define XFA_FXFA_PARSER_CXFA_MAP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Map : public CXFA_Node { + public: + CXFA_Map(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Map() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MAP_H_ diff --git a/xfa/fxfa/parser/cxfa_margin.cpp b/xfa/fxfa/parser/cxfa_margin.cpp index 38f9626a882a8f73d0f97e7463a4481b8ee03b42..265d7e92c82bf19e65b161826bda9c059fcbbe49 100644 --- a/xfa/fxfa/parser/cxfa_margin.cpp +++ b/xfa/fxfa/parser/cxfa_margin.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,26 +6,68 @@ #include "xfa/fxfa/parser/cxfa_margin.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_margin.h" +#include "third_party/base/ptr_util.h" -CXFA_Margin::CXFA_Margin(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -bool CXFA_Margin::GetLeftInset(FX_FLOAT& fInset, FX_FLOAT fDefInset) const { - fInset = fDefInset; - return TryMeasure(XFA_ATTRIBUTE_LeftInset, fInset); +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::LeftInset, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::BottomInset, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::TopInset, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::RightInset, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"margin"; + +} // namespace + +CXFA_Margin::CXFA_Margin(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Margin, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Margin>(this)) {} + +CXFA_Margin::~CXFA_Margin() {} + +float CXFA_Margin::GetLeftInset() const { + return TryLeftInset().value_or(0); +} + +float CXFA_Margin::GetTopInset() const { + return TryTopInset().value_or(0); +} + +float CXFA_Margin::GetRightInset() const { + return TryRightInset().value_or(0); +} + +float CXFA_Margin::GetBottomInset() const { + return TryBottomInset().value_or(0); +} + +Optional<float> CXFA_Margin::TryLeftInset() const { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::LeftInset); } -bool CXFA_Margin::GetTopInset(FX_FLOAT& fInset, FX_FLOAT fDefInset) const { - fInset = fDefInset; - return TryMeasure(XFA_ATTRIBUTE_TopInset, fInset); +Optional<float> CXFA_Margin::TryTopInset() const { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::TopInset); } -bool CXFA_Margin::GetRightInset(FX_FLOAT& fInset, FX_FLOAT fDefInset) const { - fInset = fDefInset; - return TryMeasure(XFA_ATTRIBUTE_RightInset, fInset); +Optional<float> CXFA_Margin::TryRightInset() const { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::RightInset); } -bool CXFA_Margin::GetBottomInset(FX_FLOAT& fInset, FX_FLOAT fDefInset) const { - fInset = fDefInset; - return TryMeasure(XFA_ATTRIBUTE_BottomInset, fInset); +Optional<float> CXFA_Margin::TryBottomInset() const { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::BottomInset); } diff --git a/xfa/fxfa/parser/cxfa_margin.h b/xfa/fxfa/parser/cxfa_margin.h index d1c19551945d448bdba6e43c62b78f34e2bce6ca..e7f95b6c9c76cc4f722f3d3ba02d4bffa5acfd24 100644 --- a/xfa/fxfa/parser/cxfa_margin.h +++ b/xfa/fxfa/parser/cxfa_margin.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,19 +7,22 @@ #ifndef XFA_FXFA_PARSER_CXFA_MARGIN_H_ #define XFA_FXFA_PARSER_CXFA_MARGIN_H_ -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Margin : public CXFA_Data { +class CXFA_Margin : public CXFA_Node { public: - explicit CXFA_Margin(CXFA_Node* pNode); + CXFA_Margin(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Margin() override; + + float GetLeftInset() const; + float GetTopInset() const; + float GetRightInset() const; + float GetBottomInset() const; - bool GetLeftInset(FX_FLOAT& fInset, FX_FLOAT fDefInset = 0) const; - bool GetTopInset(FX_FLOAT& fInset, FX_FLOAT fDefInset = 0) const; - bool GetRightInset(FX_FLOAT& fInset, FX_FLOAT fDefInset = 0) const; - bool GetBottomInset(FX_FLOAT& fInset, FX_FLOAT fDefInset = 0) const; + Optional<float> TryLeftInset() const; + Optional<float> TryTopInset() const; + Optional<float> TryRightInset() const; + Optional<float> TryBottomInset() const; }; #endif // XFA_FXFA_PARSER_CXFA_MARGIN_H_ diff --git a/xfa/fxfa/parser/cxfa_mdp.cpp b/xfa/fxfa/parser/cxfa_mdp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8fa1cdc99820b26aa006478f3926f5e69e15a38 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_mdp.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_mdp.h" + +#include "fxjs/xfa/cjx_mdp.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::SignatureType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Filter}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Permissions, XFA_AttributeType::Integer, (void*)2}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"mdp"; + +} // namespace + +CXFA_Mdp::CXFA_Mdp(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Mdp, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Mdp>(this)) {} + +CXFA_Mdp::~CXFA_Mdp() {} diff --git a/xfa/fxfa/parser/cxfa_mdp.h b/xfa/fxfa/parser/cxfa_mdp.h new file mode 100644 index 0000000000000000000000000000000000000000..0ae626d5572e0555dd288cc3ae8e56395d9b94e0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_mdp.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MDP_H_ +#define XFA_FXFA_PARSER_CXFA_MDP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Mdp : public CXFA_Node { + public: + CXFA_Mdp(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Mdp() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MDP_H_ diff --git a/xfa/fxfa/parser/cxfa_measurement.cpp b/xfa/fxfa/parser/cxfa_measurement.cpp index ebf7b7bff74b2b2f59cac9a1b99ee87a8a38b837..d0534c92dca3d5e98f5205dc60ae9ac8c35939f6 100644 --- a/xfa/fxfa/parser/cxfa_measurement.cpp +++ b/xfa/fxfa/parser/cxfa_measurement.cpp @@ -6,134 +6,144 @@ #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" -CXFA_Measurement::CXFA_Measurement(const CFX_WideStringC& wsMeasure) { - Set(wsMeasure); +namespace { + +constexpr float kPtToInch = 72; +constexpr float kPtToCm = kPtToInch / 2.54f; +constexpr float kPtToMm = kPtToCm / 10; +constexpr float kPtToMp = 0.001f; +constexpr float kPtToPc = 12; + +} // namespace + +CXFA_Measurement::CXFA_Measurement(const WideStringView& wsMeasure) { + SetString(wsMeasure); } CXFA_Measurement::CXFA_Measurement() { - Set(-1, XFA_UNIT_Unknown); + Set(-1, XFA_Unit::Unknown); } -CXFA_Measurement::CXFA_Measurement(FX_FLOAT fValue, XFA_UNIT eUnit) { +CXFA_Measurement::CXFA_Measurement(float fValue, XFA_Unit eUnit) { Set(fValue, eUnit); } -void CXFA_Measurement::Set(const CFX_WideStringC& wsMeasure) { +void CXFA_Measurement::SetString(const WideStringView& wsMeasure) { if (wsMeasure.IsEmpty()) { m_fValue = 0; - m_eUnit = XFA_UNIT_Unknown; + m_eUnit = XFA_Unit::Unknown; return; } + int32_t iUsedLen = 0; - int32_t iOffset = (wsMeasure.GetAt(0) == L'=') ? 1 : 0; - FX_FLOAT fValue = FXSYS_wcstof(wsMeasure.c_str() + iOffset, - wsMeasure.GetLength() - iOffset, &iUsedLen); - XFA_UNIT eUnit = GetUnit(wsMeasure.Mid(iOffset + iUsedLen)); + int32_t iOffset = (wsMeasure[0] == L'=') ? 1 : 0; + float fValue = FXSYS_wcstof(wsMeasure.unterminated_c_str() + iOffset, + wsMeasure.GetLength() - iOffset, &iUsedLen); + XFA_Unit eUnit = GetUnitFromString( + wsMeasure.Right(wsMeasure.GetLength() - (iOffset + iUsedLen))); Set(fValue, eUnit); } -bool CXFA_Measurement::ToString(CFX_WideString& wsMeasure) const { +WideString CXFA_Measurement::ToString() const { switch (GetUnit()) { - case XFA_UNIT_Mm: - wsMeasure.Format(L"%.8gmm", GetValue()); - return true; - case XFA_UNIT_Pt: - wsMeasure.Format(L"%.8gpt", GetValue()); - return true; - case XFA_UNIT_In: - wsMeasure.Format(L"%.8gin", GetValue()); - return true; - case XFA_UNIT_Cm: - wsMeasure.Format(L"%.8gcm", GetValue()); - return true; - case XFA_UNIT_Mp: - wsMeasure.Format(L"%.8gmp", GetValue()); - return true; - case XFA_UNIT_Pc: - wsMeasure.Format(L"%.8gpc", GetValue()); - return true; - case XFA_UNIT_Em: - wsMeasure.Format(L"%.8gem", GetValue()); - return true; - case XFA_UNIT_Percent: - wsMeasure.Format(L"%.8g%%", GetValue()); - return true; + case XFA_Unit::Mm: + return WideString::Format(L"%.8gmm", GetValue()); + case XFA_Unit::Pt: + return WideString::Format(L"%.8gpt", GetValue()); + case XFA_Unit::In: + return WideString::Format(L"%.8gin", GetValue()); + case XFA_Unit::Cm: + return WideString::Format(L"%.8gcm", GetValue()); + case XFA_Unit::Mp: + return WideString::Format(L"%.8gmp", GetValue()); + case XFA_Unit::Pc: + return WideString::Format(L"%.8gpc", GetValue()); + case XFA_Unit::Em: + return WideString::Format(L"%.8gem", GetValue()); + case XFA_Unit::Percent: + return WideString::Format(L"%.8g%%", GetValue()); default: - wsMeasure.Format(L"%.8g", GetValue()); - return false; + break; } + return WideString::Format(L"%.8g", GetValue()); +} + +float CXFA_Measurement::ToUnit(XFA_Unit eUnit) const { + float f; + return ToUnitInternal(eUnit, &f) ? f : 0; } -bool CXFA_Measurement::ToUnit(XFA_UNIT eUnit, FX_FLOAT& fValue) const { - fValue = GetValue(); - XFA_UNIT eFrom = GetUnit(); +bool CXFA_Measurement::ToUnitInternal(XFA_Unit eUnit, float* fValue) const { + *fValue = GetValue(); + XFA_Unit eFrom = GetUnit(); if (eFrom == eUnit) return true; switch (eFrom) { - case XFA_UNIT_Pt: + case XFA_Unit::Pt: break; - case XFA_UNIT_Mm: - fValue *= 72 / 2.54f / 10; + case XFA_Unit::Mm: + *fValue *= kPtToMm; break; - case XFA_UNIT_In: - fValue *= 72; + case XFA_Unit::In: + *fValue *= kPtToInch; break; - case XFA_UNIT_Cm: - fValue *= 72 / 2.54f; + case XFA_Unit::Cm: + *fValue *= kPtToCm; break; - case XFA_UNIT_Mp: - fValue *= 0.001f; + case XFA_Unit::Mp: + *fValue *= kPtToMp; break; - case XFA_UNIT_Pc: - fValue *= 12.0f; + case XFA_Unit::Pc: + *fValue *= kPtToPc; break; default: - fValue = 0; + *fValue = 0; return false; } switch (eUnit) { - case XFA_UNIT_Pt: + case XFA_Unit::Pt: return true; - case XFA_UNIT_Mm: - fValue /= 72 / 2.54f / 10; + case XFA_Unit::Mm: + *fValue /= kPtToMm; return true; - case XFA_UNIT_In: - fValue /= 72; + case XFA_Unit::In: + *fValue /= kPtToInch; return true; - case XFA_UNIT_Cm: - fValue /= 72 / 2.54f; + case XFA_Unit::Cm: + *fValue /= kPtToCm; return true; - case XFA_UNIT_Mp: - fValue /= 0.001f; + case XFA_Unit::Mp: + *fValue /= kPtToMp; return true; - case XFA_UNIT_Pc: - fValue /= 12.0f; + case XFA_Unit::Pc: + *fValue /= kPtToPc; return true; default: - fValue = 0; + NOTREACHED(); return false; } } -XFA_UNIT CXFA_Measurement::GetUnit(const CFX_WideStringC& wsUnit) { +// static +XFA_Unit CXFA_Measurement::GetUnitFromString(const WideStringView& wsUnit) { if (wsUnit == L"mm") - return XFA_UNIT_Mm; + return XFA_Unit::Mm; if (wsUnit == L"pt") - return XFA_UNIT_Pt; + return XFA_Unit::Pt; if (wsUnit == L"in") - return XFA_UNIT_In; + return XFA_Unit::In; if (wsUnit == L"cm") - return XFA_UNIT_Cm; + return XFA_Unit::Cm; if (wsUnit == L"pc") - return XFA_UNIT_Pc; + return XFA_Unit::Pc; if (wsUnit == L"mp") - return XFA_UNIT_Mp; + return XFA_Unit::Mp; if (wsUnit == L"em") - return XFA_UNIT_Em; + return XFA_Unit::Em; if (wsUnit == L"%") - return XFA_UNIT_Percent; - return XFA_UNIT_Unknown; + return XFA_Unit::Percent; + return XFA_Unit::Unknown; } diff --git a/xfa/fxfa/parser/cxfa_measurement.h b/xfa/fxfa/parser/cxfa_measurement.h index 40f71a7fab724f87ff79f4d1447e65535d7e3663..d83af246b817bab98595226ca9e013ffb87e3505 100644 --- a/xfa/fxfa/parser/cxfa_measurement.h +++ b/xfa/fxfa/parser/cxfa_measurement.h @@ -13,30 +13,29 @@ class CXFA_Measurement { public: - explicit CXFA_Measurement(const CFX_WideStringC& wsMeasure); + explicit CXFA_Measurement(const WideStringView& wsMeasure); CXFA_Measurement(); - CXFA_Measurement(FX_FLOAT fValue, XFA_UNIT eUnit); + CXFA_Measurement(float fValue, XFA_Unit eUnit); - void Set(const CFX_WideStringC& wsMeasure); - void Set(FX_FLOAT fValue, XFA_UNIT eUnit) { + static XFA_Unit GetUnitFromString(const WideStringView& wsUnit); + + void Set(float fValue, XFA_Unit eUnit) { m_fValue = fValue; m_eUnit = eUnit; } - XFA_UNIT GetUnit(const CFX_WideStringC& wsUnit); - XFA_UNIT GetUnit() const { return m_eUnit; } - FX_FLOAT GetValue() const { return m_fValue; } + XFA_Unit GetUnit() const { return m_eUnit; } + float GetValue() const { return m_fValue; } - bool ToString(CFX_WideString& wsMeasure) const; - bool ToUnit(XFA_UNIT eUnit, FX_FLOAT& fValue) const; - FX_FLOAT ToUnit(XFA_UNIT eUnit) const { - FX_FLOAT f; - return ToUnit(eUnit, f) ? f : 0; - } + WideString ToString() const; + float ToUnit(XFA_Unit eUnit) const; private: - FX_FLOAT m_fValue; - XFA_UNIT m_eUnit; + void SetString(const WideStringView& wsMeasure); + bool ToUnitInternal(XFA_Unit eUnit, float* fValue) const; + + float m_fValue; + XFA_Unit m_eUnit; }; #endif // XFA_FXFA_PARSER_CXFA_MEASUREMENT_H_ diff --git a/xfa/fxfa/parser/cxfa_medium.cpp b/xfa/fxfa/parser/cxfa_medium.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fa494a295a0d6c77796aebf9be68e9cd739fcc0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_medium.cpp @@ -0,0 +1,45 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_medium.h" + +#include "fxjs/xfa/cjx_medium.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TrayOut, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Orientation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Portrait}, + {XFA_Attribute::ImagingBBox, XFA_AttributeType::CData, (void*)L"none"}, + {XFA_Attribute::Short, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::TrayIn, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Stock, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Long, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"medium"; + +} // namespace + +CXFA_Medium::CXFA_Medium(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Medium, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Medium>(this)) {} + +CXFA_Medium::~CXFA_Medium() {} diff --git a/xfa/fxfa/parser/cxfa_medium.h b/xfa/fxfa/parser/cxfa_medium.h new file mode 100644 index 0000000000000000000000000000000000000000..b9b9c5d84832c02543800f0c142e50ae6ed66a81 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_medium.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MEDIUM_H_ +#define XFA_FXFA_PARSER_CXFA_MEDIUM_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Medium : public CXFA_Node { + public: + CXFA_Medium(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Medium() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MEDIUM_H_ diff --git a/xfa/fxfa/parser/cxfa_mediuminfo.cpp b/xfa/fxfa/parser/cxfa_mediuminfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a41f1dde3dc7ef6d4b74c44796b376be6ba4828 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_mediuminfo.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_mediuminfo.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Map, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"mediumInfo"; + +} // namespace + +CXFA_MediumInfo::CXFA_MediumInfo(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::MediumInfo, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_MediumInfo::~CXFA_MediumInfo() {} diff --git a/xfa/fxfa/parser/cxfa_mediuminfo.h b/xfa/fxfa/parser/cxfa_mediuminfo.h new file mode 100644 index 0000000000000000000000000000000000000000..da100eaec26d4535a275c70518fd135db2c8b41e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_mediuminfo.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MEDIUMINFO_H_ +#define XFA_FXFA_PARSER_CXFA_MEDIUMINFO_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_MediumInfo : public CXFA_Node { + public: + CXFA_MediumInfo(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_MediumInfo() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MEDIUMINFO_H_ diff --git a/xfa/fxfa/parser/cxfa_meridiem.cpp b/xfa/fxfa/parser/cxfa_meridiem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..357ce2c2758f1a49796931cfd0b4cee8c3d7ccab --- /dev/null +++ b/xfa/fxfa/parser/cxfa_meridiem.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_meridiem.h" + +namespace { + +constexpr wchar_t kName[] = L"meridiem"; + +} // namespace + +CXFA_Meridiem::CXFA_Meridiem(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::Meridiem, + nullptr, + nullptr, + kName) {} + +CXFA_Meridiem::~CXFA_Meridiem() {} diff --git a/xfa/fxfa/parser/cxfa_meridiem.h b/xfa/fxfa/parser/cxfa_meridiem.h new file mode 100644 index 0000000000000000000000000000000000000000..30bd4b06cc464f73d0b2015b7b64fe5421bbc3a0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_meridiem.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MERIDIEM_H_ +#define XFA_FXFA_PARSER_CXFA_MERIDIEM_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Meridiem : public CXFA_Node { + public: + CXFA_Meridiem(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Meridiem() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MERIDIEM_H_ diff --git a/xfa/fxfa/parser/cxfa_meridiemnames.cpp b/xfa/fxfa/parser/cxfa_meridiemnames.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dfb603ef4bb074377a7b70bead10485ef1fffad6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_meridiemnames.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_meridiemnames.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Meridiem, 2, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"meridiemNames"; + +} // namespace + +CXFA_MeridiemNames::CXFA_MeridiemNames(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::MeridiemNames, + kPropertyData, + nullptr, + kName) {} + +CXFA_MeridiemNames::~CXFA_MeridiemNames() {} diff --git a/xfa/fxfa/parser/cxfa_meridiemnames.h b/xfa/fxfa/parser/cxfa_meridiemnames.h new file mode 100644 index 0000000000000000000000000000000000000000..8cade217e4343aa3e6153640cffc20165ffc5cc7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_meridiemnames.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MERIDIEMNAMES_H_ +#define XFA_FXFA_PARSER_CXFA_MERIDIEMNAMES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_MeridiemNames : public CXFA_Node { + public: + CXFA_MeridiemNames(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_MeridiemNames() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MERIDIEMNAMES_H_ diff --git a/xfa/fxfa/parser/cxfa_message.cpp b/xfa/fxfa/parser/cxfa_message.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa16efdf3670003e89b7056e2e2e57d8af8116f2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_message.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_message.h" + +#include "fxjs/xfa/cjx_message.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::MsgId, 1, 0}, + {XFA_Element::Severity, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"message"; + +} // namespace + +CXFA_Message::CXFA_Message(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Message, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Message>(this)) {} + +CXFA_Message::~CXFA_Message() {} diff --git a/xfa/fxfa/parser/cxfa_message.h b/xfa/fxfa/parser/cxfa_message.h new file mode 100644 index 0000000000000000000000000000000000000000..f172e061a33939576a22b11dfbfd4c5b301c82c9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_message.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MESSAGE_H_ +#define XFA_FXFA_PARSER_CXFA_MESSAGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Message : public CXFA_Node { + public: + CXFA_Message(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Message() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MESSAGE_H_ diff --git a/xfa/fxfa/parser/cxfa_messaging.cpp b/xfa/fxfa/parser/cxfa_messaging.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ad77a4019088b811a8e7f7ff9257b04fec54517 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_messaging.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_messaging.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"messaging"; + +} // namespace + +CXFA_Messaging::CXFA_Messaging(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Messaging, + nullptr, + kAttributeData, + kName) {} + +CXFA_Messaging::~CXFA_Messaging() {} diff --git a/xfa/fxfa/parser/cxfa_messaging.h b/xfa/fxfa/parser/cxfa_messaging.h new file mode 100644 index 0000000000000000000000000000000000000000..48d16b3b9a41a7508adc46087e308e51d19d6256 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_messaging.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MESSAGING_H_ +#define XFA_FXFA_PARSER_CXFA_MESSAGING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Messaging : public CXFA_Node { + public: + CXFA_Messaging(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Messaging() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MESSAGING_H_ diff --git a/xfa/fxfa/parser/cxfa_mode.cpp b/xfa/fxfa/parser/cxfa_mode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6195f087ac12ccbf90a70251280af8f210a85b60 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_mode.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_mode.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"mode"; + +} // namespace + +CXFA_Mode::CXFA_Mode(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Mode, + nullptr, + kAttributeData, + kName) {} + +CXFA_Mode::~CXFA_Mode() {} diff --git a/xfa/fxfa/parser/cxfa_mode.h b/xfa/fxfa/parser/cxfa_mode.h new file mode 100644 index 0000000000000000000000000000000000000000..1dfd426d9840ef187ce2e108fda0144dcb29d82b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_mode.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MODE_H_ +#define XFA_FXFA_PARSER_CXFA_MODE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Mode : public CXFA_Node { + public: + CXFA_Mode(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Mode() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MODE_H_ diff --git a/xfa/fxfa/parser/cxfa_modifyannots.cpp b/xfa/fxfa/parser/cxfa_modifyannots.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e349dbfd1ae82d47de0b2aa44a0f01d2504d9af7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_modifyannots.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_modifyannots.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"modifyAnnots"; + +} // namespace + +CXFA_ModifyAnnots::CXFA_ModifyAnnots(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::ModifyAnnots, + nullptr, + kAttributeData, + kName) {} + +CXFA_ModifyAnnots::~CXFA_ModifyAnnots() {} diff --git a/xfa/fxfa/parser/cxfa_modifyannots.h b/xfa/fxfa/parser/cxfa_modifyannots.h new file mode 100644 index 0000000000000000000000000000000000000000..4e10921cca54fd594cf2b10a7bca07a4fc2684e1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_modifyannots.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MODIFYANNOTS_H_ +#define XFA_FXFA_PARSER_CXFA_MODIFYANNOTS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ModifyAnnots : public CXFA_Node { + public: + CXFA_ModifyAnnots(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ModifyAnnots() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MODIFYANNOTS_H_ diff --git a/xfa/fxfa/parser/cxfa_month.cpp b/xfa/fxfa/parser/cxfa_month.cpp new file mode 100644 index 0000000000000000000000000000000000000000..687ef4a20cee74efe9e3e360271532f92979afd3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_month.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_month.h" + +namespace { + +constexpr wchar_t kName[] = L"month"; + +} // namespace + +CXFA_Month::CXFA_Month(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::Month, + nullptr, + nullptr, + kName) {} + +CXFA_Month::~CXFA_Month() {} diff --git a/xfa/fxfa/parser/cxfa_month.h b/xfa/fxfa/parser/cxfa_month.h new file mode 100644 index 0000000000000000000000000000000000000000..69361f540c4b0c3719b3c08ef1a3b1d09cd2c788 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_month.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MONTH_H_ +#define XFA_FXFA_PARSER_CXFA_MONTH_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Month : public CXFA_Node { + public: + CXFA_Month(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Month() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MONTH_H_ diff --git a/xfa/fxfa/parser/cxfa_monthnames.cpp b/xfa/fxfa/parser/cxfa_monthnames.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b05b0dcf8be8783d77f0a64519effb9b42b1513 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_monthnames.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_monthnames.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Month, 12, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Abbr, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"monthNames"; + +} // namespace + +CXFA_MonthNames::CXFA_MonthNames(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::MonthNames, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_MonthNames::~CXFA_MonthNames() {} diff --git a/xfa/fxfa/parser/cxfa_monthnames.h b/xfa/fxfa/parser/cxfa_monthnames.h new file mode 100644 index 0000000000000000000000000000000000000000..f95512b3aaff9469799afe4c8a025d68126b7f43 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_monthnames.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MONTHNAMES_H_ +#define XFA_FXFA_PARSER_CXFA_MONTHNAMES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_MonthNames : public CXFA_Node { + public: + CXFA_MonthNames(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_MonthNames() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MONTHNAMES_H_ diff --git a/xfa/fxfa/parser/cxfa_msgid.cpp b/xfa/fxfa/parser/cxfa_msgid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..626833b6fd8d7702ddf6607ae0c5e752cd42f174 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_msgid.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_msgid.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"msgId"; + +} // namespace + +CXFA_MsgId::CXFA_MsgId(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::MsgId, + nullptr, + kAttributeData, + kName) {} + +CXFA_MsgId::~CXFA_MsgId() {} diff --git a/xfa/fxfa/parser/cxfa_msgid.h b/xfa/fxfa/parser/cxfa_msgid.h new file mode 100644 index 0000000000000000000000000000000000000000..333085a37b9688d327ed271f1541764bf5221b41 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_msgid.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_MSGID_H_ +#define XFA_FXFA_PARSER_CXFA_MSGID_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_MsgId : public CXFA_Node { + public: + CXFA_MsgId(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_MsgId() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_MSGID_H_ diff --git a/xfa/fxfa/parser/cxfa_nameattr.cpp b/xfa/fxfa/parser/cxfa_nameattr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd42694ce5b1c937e9dd78fa7565c5531264a414 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_nameattr.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_nameattr.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"nameAttr"; + +} // namespace + +CXFA_NameAttr::CXFA_NameAttr(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::NameAttr, + nullptr, + kAttributeData, + kName) {} + +CXFA_NameAttr::~CXFA_NameAttr() {} diff --git a/xfa/fxfa/parser/cxfa_nameattr.h b/xfa/fxfa/parser/cxfa_nameattr.h new file mode 100644 index 0000000000000000000000000000000000000000..05514c020b9efeda0e836c7af8924a727770e3c1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_nameattr.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NAMEATTR_H_ +#define XFA_FXFA_PARSER_CXFA_NAMEATTR_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NameAttr : public CXFA_Node { + public: + CXFA_NameAttr(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NameAttr() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NAMEATTR_H_ diff --git a/xfa/fxfa/parser/cxfa_neverembed.cpp b/xfa/fxfa/parser/cxfa_neverembed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ba64a7dcaa871db62bc624e83c48ea517f08074 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_neverembed.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_neverembed.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"neverEmbed"; + +} // namespace + +CXFA_NeverEmbed::CXFA_NeverEmbed(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::NeverEmbed, + nullptr, + kAttributeData, + kName) {} + +CXFA_NeverEmbed::~CXFA_NeverEmbed() {} diff --git a/xfa/fxfa/parser/cxfa_neverembed.h b/xfa/fxfa/parser/cxfa_neverembed.h new file mode 100644 index 0000000000000000000000000000000000000000..11ec92833934fb834e2bedcd811ec19322e9df20 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_neverembed.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NEVEREMBED_H_ +#define XFA_FXFA_PARSER_CXFA_NEVEREMBED_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NeverEmbed : public CXFA_Node { + public: + CXFA_NeverEmbed(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NeverEmbed() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NEVEREMBED_H_ diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp index 1e508969d1a66c0b9640c055fbad7e46b678dcf4..ec70271ea0beb8ef77ef7a519a5813dbed88e410 100644 --- a/xfa/fxfa/parser/cxfa_node.cpp +++ b/xfa/fxfa/parser/cxfa_node.cpp @@ -4,108 +4,78 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_node.h" #include <map> #include <memory> +#include <set> #include <utility> #include <vector> -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/autorestorer.h" +#include "core/fxcrt/cfx_decimal.h" +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "fxjs/cfxjse_engine.h" #include "fxjs/cfxjse_value.h" +#include "fxjs/xfa/cjx_node.h" +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -#include "xfa/fde/xml/fde_xml_imp.h" -#include "xfa/fgas/crt/fgas_codepage.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" #include "xfa/fxfa/cxfa_eventparam.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffnotify.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" +#include "xfa/fxfa/parser/cxfa_attachnodelist.h" +#include "xfa/fxfa/parser/cxfa_bind.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_calculate.h" +#include "xfa/fxfa/parser/cxfa_caption.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_event.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_keep.h" #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" +#include "xfa/fxfa/parser/cxfa_margin.h" #include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" #include "xfa/fxfa/parser/cxfa_occur.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" +#include "xfa/fxfa/parser/cxfa_para.h" #include "xfa/fxfa/parser/cxfa_simple_parser.h" +#include "xfa/fxfa/parser/cxfa_subform.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" +#include "xfa/fxfa/parser/cxfa_validate.h" +#include "xfa/fxfa/parser/cxfa_value.h" #include "xfa/fxfa/parser/xfa_basic_data.h" +#include "xfa/fxfa/parser/xfa_utils.h" namespace { -void XFA_DeleteWideString(void* pData) { - delete static_cast<CFX_WideString*>(pData); -} - -void XFA_CopyWideString(void*& pData) { - if (pData) { - CFX_WideString* pNewData = new CFX_WideString(*(CFX_WideString*)pData); - pData = pNewData; - } -} - -XFA_MAPDATABLOCKCALLBACKINFO deleteWideStringCallBack = {XFA_DeleteWideString, - XFA_CopyWideString}; - -void XFA_DataNodeDeleteBindItem(void* pData) { - delete static_cast<CXFA_NodeArray*>(pData); -} - -XFA_MAPDATABLOCKCALLBACKINFO deleteBindItemCallBack = { - XFA_DataNodeDeleteBindItem, nullptr}; - -int32_t GetCount(CXFA_Node* pInstMgrNode) { - ASSERT(pInstMgrNode); - int32_t iCount = 0; - uint32_t dwNameHash = 0; - for (CXFA_Node* pNode = pInstMgrNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - XFA_Element eCurType = pNode->GetElementType(); - if (eCurType == XFA_Element::InstanceManager) - break; - if ((eCurType != XFA_Element::Subform) && - (eCurType != XFA_Element::SubformSet)) { - continue; - } - if (iCount == 0) { - CFX_WideStringC wsName = pNode->GetCData(XFA_ATTRIBUTE_Name); - CFX_WideStringC wsInstName = pInstMgrNode->GetCData(XFA_ATTRIBUTE_Name); - if (wsInstName.GetLength() < 1 || wsInstName.GetAt(0) != '_' || - wsInstName.Mid(1) != wsName) { - return iCount; - } - dwNameHash = pNode->GetNameHash(); - } - if (dwNameHash != pNode->GetNameHash()) - break; - - iCount++; - } - return iCount; -} +constexpr uint8_t kMaxExecuteRecursion = 2; -void SortNodeArrayByDocumentIdx(const CXFA_NodeSet& rgNodeSet, - CXFA_NodeArray& rgNodeArray, - CFX_ArrayTemplate<int32_t>& rgIdxArray) { - int32_t iCount = pdfium::CollectionSize<int32_t>(rgNodeSet); - rgNodeArray.SetSize(iCount); - rgIdxArray.SetSize(iCount); - if (iCount == 0) - return; +std::vector<CXFA_Node*> NodesSortedByDocumentIdx( + const std::set<CXFA_Node*>& rgNodeSet) { + if (rgNodeSet.empty()) + return std::vector<CXFA_Node*>(); - int32_t iIndex = -1; - int32_t iTotalIndex = -1; - CXFA_Node* pCommonParent = - (*rgNodeSet.begin())->GetNodeItem(XFA_NODEITEM_Parent); - for (CXFA_Node* pNode = pCommonParent->GetNodeItem(XFA_NODEITEM_FirstChild); - pNode && iIndex < iCount; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - iTotalIndex++; - if (pdfium::ContainsValue(rgNodeSet, pNode)) { - iIndex++; - rgNodeArray[iIndex] = pNode; - rgIdxArray[iIndex] = iTotalIndex; - } + std::vector<CXFA_Node*> rgNodeArray; + CXFA_Node* pCommonParent = (*rgNodeSet.begin())->GetParent(); + for (CXFA_Node* pNode = pCommonParent->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pdfium::ContainsValue(rgNodeSet, pNode)) + rgNodeArray.push_back(pNode); } + return rgNodeArray; } -using CXFA_NodeSetPair = std::pair<CXFA_NodeSet, CXFA_NodeSet>; +using CXFA_NodeSetPair = std::pair<std::set<CXFA_Node*>, std::set<CXFA_Node*>>; using CXFA_NodeSetPairMap = std::map<uint32_t, std::unique_ptr<CXFA_NodeSetPair>>; using CXFA_NodeSetPairMapMap = @@ -113,7 +83,7 @@ using CXFA_NodeSetPairMapMap = CXFA_NodeSetPair* NodeSetPairForNode(CXFA_Node* pNode, CXFA_NodeSetPairMapMap* pMap) { - CXFA_Node* pParentNode = pNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pParentNode = pNode->GetParent(); uint32_t dwNameHash = pNode->GetNameHash(); if (!pParentNode || !dwNameHash) return nullptr; @@ -128,8 +98,8 @@ CXFA_NodeSetPair* NodeSetPairForNode(CXFA_Node* pNode, return (*pNodeSetPairMap)[dwNameHash].get(); } -void ReorderDataNodes(const CXFA_NodeSet& sSet1, - const CXFA_NodeSet& sSet2, +void ReorderDataNodes(const std::set<CXFA_Node*>& sSet1, + const std::set<CXFA_Node*>& sSet2, bool bInsertBefore) { CXFA_NodeSetPairMapMap rgMap; for (CXFA_Node* pNode : sSet1) { @@ -156,27 +126,22 @@ void ReorderDataNodes(const CXFA_NodeSet& sSet1, if (!pNodeSetPair) continue; if (!pNodeSetPair->first.empty() && !pNodeSetPair->second.empty()) { - CXFA_NodeArray rgNodeArray1; - CXFA_NodeArray rgNodeArray2; - CFX_ArrayTemplate<int32_t> rgIdxArray1; - CFX_ArrayTemplate<int32_t> rgIdxArray2; - SortNodeArrayByDocumentIdx(pNodeSetPair->first, rgNodeArray1, - rgIdxArray1); - SortNodeArrayByDocumentIdx(pNodeSetPair->second, rgNodeArray2, - rgIdxArray2); + std::vector<CXFA_Node*> rgNodeArray1 = + NodesSortedByDocumentIdx(pNodeSetPair->first); + std::vector<CXFA_Node*> rgNodeArray2 = + NodesSortedByDocumentIdx(pNodeSetPair->second); CXFA_Node* pParentNode = nullptr; CXFA_Node* pBeforeNode = nullptr; if (bInsertBefore) { - pBeforeNode = rgNodeArray2[0]; - pParentNode = pBeforeNode->GetNodeItem(XFA_NODEITEM_Parent); + pBeforeNode = rgNodeArray2.front(); + pParentNode = pBeforeNode->GetParent(); } else { - CXFA_Node* pLastNode = rgNodeArray2[rgIdxArray2.GetSize() - 1]; - pParentNode = pLastNode->GetNodeItem(XFA_NODEITEM_Parent); - pBeforeNode = pLastNode->GetNodeItem(XFA_NODEITEM_NextSibling); + CXFA_Node* pLastNode = rgNodeArray2.back(); + pParentNode = pLastNode->GetParent(); + pBeforeNode = pLastNode->GetNextSibling(); } - for (int32_t iIdx = 0; iIdx < rgIdxArray1.GetSize(); iIdx++) { - CXFA_Node* pCurNode = rgNodeArray1[iIdx]; - pParentNode->RemoveChild(pCurNode); + for (auto* pCurNode : rgNodeArray1) { + pParentNode->RemoveChild(pCurNode, true); pParentNode->InsertChild(pCurNode, pBeforeNode); } } @@ -185,308 +150,41 @@ void ReorderDataNodes(const CXFA_NodeSet& sSet1, } } -CXFA_Node* GetItem(CXFA_Node* pInstMgrNode, int32_t iIndex) { - ASSERT(pInstMgrNode); - int32_t iCount = 0; - uint32_t dwNameHash = 0; - for (CXFA_Node* pNode = pInstMgrNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - XFA_Element eCurType = pNode->GetElementType(); - if (eCurType == XFA_Element::InstanceManager) - break; - if ((eCurType != XFA_Element::Subform) && - (eCurType != XFA_Element::SubformSet)) { - continue; - } - if (iCount == 0) { - CFX_WideStringC wsName = pNode->GetCData(XFA_ATTRIBUTE_Name); - CFX_WideStringC wsInstName = pInstMgrNode->GetCData(XFA_ATTRIBUTE_Name); - if (wsInstName.GetLength() < 1 || wsInstName.GetAt(0) != '_' || - wsInstName.Mid(1) != wsName) { - return nullptr; - } - dwNameHash = pNode->GetNameHash(); - } - if (dwNameHash != pNode->GetNameHash()) - break; - - iCount++; - if (iCount > iIndex) - return pNode; - } - return nullptr; -} - -void InsertItem(CXFA_Node* pInstMgrNode, - CXFA_Node* pNewInstance, - int32_t iPos, - int32_t iCount = -1, - bool bMoveDataBindingNodes = true) { - if (iCount < 0) - iCount = GetCount(pInstMgrNode); - if (iPos < 0) - iPos = iCount; - if (iPos == iCount) { - CXFA_Node* pNextSibling = - iCount > 0 - ? GetItem(pInstMgrNode, iCount - 1) - ->GetNodeItem(XFA_NODEITEM_NextSibling) - : pInstMgrNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pInstMgrNode->GetNodeItem(XFA_NODEITEM_Parent) - ->InsertChild(pNewInstance, pNextSibling); - if (bMoveDataBindingNodes) { - CXFA_NodeSet sNew; - CXFA_NodeSet sAfter; - CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode> - sIteratorNew(pNewInstance); - for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; - pNode = sIteratorNew.MoveToNext()) { - CXFA_Node* pDataNode = pNode->GetBindData(); - if (!pDataNode) - continue; - - sNew.insert(pDataNode); - } - CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode> - sIteratorAfter(pNextSibling); - for (CXFA_Node* pNode = sIteratorAfter.GetCurrent(); pNode; - pNode = sIteratorAfter.MoveToNext()) { - CXFA_Node* pDataNode = pNode->GetBindData(); - if (!pDataNode) - continue; - - sAfter.insert(pDataNode); - } - ReorderDataNodes(sNew, sAfter, false); - } - } else { - CXFA_Node* pBeforeInstance = GetItem(pInstMgrNode, iPos); - pInstMgrNode->GetNodeItem(XFA_NODEITEM_Parent) - ->InsertChild(pNewInstance, pBeforeInstance); - if (bMoveDataBindingNodes) { - CXFA_NodeSet sNew; - CXFA_NodeSet sBefore; - CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode> - sIteratorNew(pNewInstance); - for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; - pNode = sIteratorNew.MoveToNext()) { - CXFA_Node* pDataNode = pNode->GetBindData(); - if (!pDataNode) - continue; - - sNew.insert(pDataNode); - } - CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode> - sIteratorBefore(pBeforeInstance); - for (CXFA_Node* pNode = sIteratorBefore.GetCurrent(); pNode; - pNode = sIteratorBefore.MoveToNext()) { - CXFA_Node* pDataNode = pNode->GetBindData(); - if (!pDataNode) - continue; - - sBefore.insert(pDataNode); - } - ReorderDataNodes(sNew, sBefore, true); - } - } -} - -void RemoveItem(CXFA_Node* pInstMgrNode, - CXFA_Node* pRemoveInstance, - bool bRemoveDataBinding = true) { - pInstMgrNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pRemoveInstance); - if (!bRemoveDataBinding) - return; - - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> - sIterator(pRemoveInstance); - for (CXFA_Node* pFormNode = sIterator.GetCurrent(); pFormNode; - pFormNode = sIterator.MoveToNext()) { - CXFA_Node* pDataNode = pFormNode->GetBindData(); - if (!pDataNode) - continue; - - if (pDataNode->RemoveBindItem(pFormNode) == 0) { - if (CXFA_Node* pDataParent = - pDataNode->GetNodeItem(XFA_NODEITEM_Parent)) { - pDataParent->RemoveChild(pDataNode); - } - } - pFormNode->SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); - } -} - -CXFA_Node* CreateInstance(CXFA_Node* pInstMgrNode, bool bDataMerge) { - CXFA_Document* pDocument = pInstMgrNode->GetDocument(); - CXFA_Node* pTemplateNode = pInstMgrNode->GetTemplateNode(); - CXFA_Node* pFormParent = pInstMgrNode->GetNodeItem(XFA_NODEITEM_Parent); - CXFA_Node* pDataScope = nullptr; - for (CXFA_Node* pRootBoundNode = pFormParent; - pRootBoundNode && pRootBoundNode->IsContainerNode(); - pRootBoundNode = pRootBoundNode->GetNodeItem(XFA_NODEITEM_Parent)) { - pDataScope = pRootBoundNode->GetBindData(); - if (pDataScope) - break; - } - if (!pDataScope) { - pDataScope = ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)); - ASSERT(pDataScope); - } - CXFA_Node* pInstance = pDocument->DataMerge_CopyContainer( - pTemplateNode, pFormParent, pDataScope, true, bDataMerge, true); - if (pInstance) { - pDocument->DataMerge_UpdateBindingRelations(pInstance); - pFormParent->RemoveChild(pInstance); - } - return pInstance; -} - -struct XFA_ExecEventParaInfo { - public: - uint32_t m_uHash; - const FX_WCHAR* m_lpcEventName; - XFA_EVENTTYPE m_eventType; - uint32_t m_validFlags; -}; -static const XFA_ExecEventParaInfo gs_eventParaInfos[] = { - {0x02a6c55a, L"postSubmit", XFA_EVENT_PostSubmit, 0}, - {0x0ab466bb, L"preSubmit", XFA_EVENT_PreSubmit, 0}, - {0x109d7ce7, L"mouseEnter", XFA_EVENT_MouseEnter, 5}, - {0x17fad373, L"postPrint", XFA_EVENT_PostPrint, 0}, - {0x1bfc72d9, L"preOpen", XFA_EVENT_PreOpen, 7}, - {0x2196a452, L"initialize", XFA_EVENT_Initialize, 1}, - {0x27410f03, L"mouseExit", XFA_EVENT_MouseExit, 5}, - {0x33c43dec, L"docClose", XFA_EVENT_DocClose, 0}, - {0x361fa1b6, L"preSave", XFA_EVENT_PreSave, 0}, - {0x36f1c6d8, L"preSign", XFA_EVENT_PreSign, 6}, - {0x4731d6ba, L"exit", XFA_EVENT_Exit, 2}, - {0x56bf456b, L"docReady", XFA_EVENT_DocReady, 0}, - {0x7233018a, L"validate", XFA_EVENT_Validate, 1}, - {0x8808385e, L"indexChange", XFA_EVENT_IndexChange, 3}, - {0x891f4606, L"change", XFA_EVENT_Change, 4}, - {0x9528a7b4, L"prePrint", XFA_EVENT_PrePrint, 0}, - {0x9f693b21, L"mouseDown", XFA_EVENT_MouseDown, 5}, - {0xcdce56b3, L"full", XFA_EVENT_Full, 4}, - {0xd576d08e, L"mouseUp", XFA_EVENT_MouseUp, 5}, - {0xd95657a6, L"click", XFA_EVENT_Click, 4}, - {0xdbfbe02e, L"calculate", XFA_EVENT_Calculate, 1}, - {0xe25fa7b8, L"postOpen", XFA_EVENT_PostOpen, 7}, - {0xe28dce7e, L"enter", XFA_EVENT_Enter, 2}, - {0xfc82d695, L"postSave", XFA_EVENT_PostSave, 0}, - {0xfd54fbb7, L"postSign", XFA_EVENT_PostSign, 6}, -}; - -const XFA_ExecEventParaInfo* GetEventParaInfoByName( - const CFX_WideStringC& wsEventName) { - uint32_t uHash = FX_HashCode_GetW(wsEventName, false); - int32_t iStart = 0; - int32_t iEnd = (sizeof(gs_eventParaInfos) / sizeof(gs_eventParaInfos[0])) - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_ExecEventParaInfo* eventParaInfo = &gs_eventParaInfos[iMid]; - if (uHash == eventParaInfo->m_uHash) - return eventParaInfo; - if (uHash < eventParaInfo->m_uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return nullptr; -} - -void StrToRGB(const CFX_WideString& strRGB, - int32_t& r, - int32_t& g, - int32_t& b) { - r = 0; - g = 0; - b = 0; - - FX_WCHAR zero = '0'; - int32_t iIndex = 0; - int32_t iLen = strRGB.GetLength(); - for (int32_t i = 0; i < iLen; ++i) { - FX_WCHAR ch = strRGB.GetAt(i); - if (ch == L',') - ++iIndex; - if (iIndex > 2) - break; - - int32_t iValue = ch - zero; - if (iValue >= 0 && iValue <= 9) { - switch (iIndex) { - case 0: - r = r * 10 + iValue; - break; - case 1: - g = g * 10 + iValue; - break; - default: - b = b * 10 + iValue; - break; - } - } - } -} - -enum XFA_KEYTYPE { - XFA_KEYTYPE_Custom, - XFA_KEYTYPE_Element, -}; - -void* GetMapKey_Custom(const CFX_WideStringC& wsKey) { - uint32_t dwKey = FX_HashCode_GetW(wsKey, false); - return (void*)(uintptr_t)((dwKey << 1) | XFA_KEYTYPE_Custom); -} +} // namespace -void* GetMapKey_Element(XFA_Element eType, XFA_ATTRIBUTE eAttribute) { - return (void*)(uintptr_t)((static_cast<int32_t>(eType) << 16) | - (eAttribute << 8) | XFA_KEYTYPE_Element); +// static +WideString CXFA_Node::AttributeEnumToName(XFA_AttributeEnum item) { + return g_XFAEnumData[static_cast<int32_t>(item)].pName; } -const XFA_ATTRIBUTEINFO* GetAttributeOfElement(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - uint32_t dwPacket) { - int32_t iCount = 0; - const uint8_t* pAttr = XFA_GetElementAttributes(eElement, iCount); - if (!pAttr || iCount < 1) - return nullptr; - - if (!std::binary_search(pAttr, pAttr + iCount, eAttribute)) - return nullptr; - - const XFA_ATTRIBUTEINFO* pInfo = XFA_GetAttributeByID(eAttribute); - ASSERT(pInfo); - if (dwPacket == XFA_XDPPACKET_UNKNOWN) - return pInfo; - return (dwPacket & pInfo->dwPackets) ? pInfo : nullptr; -} +// static +Optional<XFA_AttributeEnum> CXFA_Node::NameToAttributeEnum( + const WideStringView& name) { + if (name.IsEmpty()) + return {}; -const XFA_ATTRIBUTEENUMINFO* GetAttributeEnumByID(XFA_ATTRIBUTEENUM eName) { - return g_XFAEnumData + eName; + auto* it = std::lower_bound(g_XFAEnumData, g_XFAEnumData + g_iXFAEnumCount, + FX_HashCode_GetW(name, false), + [](const XFA_AttributeEnumInfo& arg, + uint32_t hash) { return arg.uHash < hash; }); + if (it != g_XFAEnumData + g_iXFAEnumCount && name == it->pName) + return {it->eName}; + return {}; } -} // namespace - -static void XFA_DefaultFreeData(void* pData) {} - -static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADefaultFreeData = { - XFA_DefaultFreeData, nullptr}; - -XFA_MAPMODULEDATA::XFA_MAPMODULEDATA() {} - -XFA_MAPMODULEDATA::~XFA_MAPMODULEDATA() {} - CXFA_Node::CXFA_Node(CXFA_Document* pDoc, - uint16_t ePacket, + XFA_PacketType ePacket, + uint32_t validPackets, XFA_ObjectType oType, XFA_Element eType, - const CFX_WideStringC& elementName) - : CXFA_Object(pDoc, oType, eType, elementName), + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node) + : CXFA_Object(pDoc, oType, eType, elementName, std::move(js_node)), + m_Properties(properties), + m_Attributes(attributes), + m_ValidPackets(validPackets), m_pNext(nullptr), m_pChild(nullptr), m_pLastChild(nullptr), @@ -495,14 +193,31 @@ CXFA_Node::CXFA_Node(CXFA_Document* pDoc, m_ePacket(ePacket), m_uNodeFlags(XFA_NodeFlag_None), m_dwNameHash(0), - m_pAuxNode(nullptr), - m_pMapModuleData(nullptr) { + m_pAuxNode(nullptr) { ASSERT(m_pDocument); } +CXFA_Node::CXFA_Node(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName) + : CXFA_Node(pDoc, + ePacket, + validPackets, + oType, + eType, + properties, + attributes, + elementName, + pdfium::MakeUnique<CJX_Node>(this)) {} + CXFA_Node::~CXFA_Node() { ASSERT(!m_pParent); - RemoveMapModuleKey(); + CXFA_Node* pNode = m_pChild; while (pNode) { CXFA_Node* pNext = pNode->m_pNext; @@ -519,187 +234,235 @@ CXFA_Node* CXFA_Node::Clone(bool bRecursive) { if (!pClone) return nullptr; - MergeAllData(pClone); + JSObject()->MergeAllData(pClone); pClone->UpdateNameHash(); if (IsNeedSavingXMLNode()) { - CFDE_XMLNode* pCloneXML = nullptr; + std::unique_ptr<CFX_XMLNode> pCloneXML; if (IsAttributeInXML()) { - CFX_WideString wsName; - GetAttribute(XFA_ATTRIBUTE_Name, wsName, false); - CFDE_XMLElement* pCloneXMLElement = new CFDE_XMLElement(wsName); - CFX_WideStringC wsValue = GetCData(XFA_ATTRIBUTE_Value); - if (!wsValue.IsEmpty()) { - pCloneXMLElement->SetTextData(CFX_WideString(wsValue)); - } - pCloneXML = pCloneXMLElement; - pCloneXMLElement = nullptr; - pClone->SetEnum(XFA_ATTRIBUTE_Contains, XFA_ATTRIBUTEENUM_Unknown); + WideString wsName = JSObject() + ->TryAttribute(XFA_Attribute::Name, false) + .value_or(WideString()); + auto pCloneXMLElement = pdfium::MakeUnique<CFX_XMLElement>(wsName); + WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value); + if (!wsValue.IsEmpty()) + pCloneXMLElement->SetTextData(WideString(wsValue)); + + pCloneXML.reset(pCloneXMLElement.release()); + pClone->JSObject()->SetEnum(XFA_Attribute::Contains, + XFA_AttributeEnum::Unknown, false); } else { - pCloneXML = m_pXMLNode->Clone(false); + pCloneXML = m_pXMLNode->Clone(); } - pClone->SetXMLMappingNode(pCloneXML); + pClone->SetXMLMappingNode(pCloneXML.release()); pClone->SetFlag(XFA_NodeFlag_OwnXMLNode, false); } if (bRecursive) { - for (CXFA_Node* pChild = GetNodeItem(XFA_NODEITEM_FirstChild); pChild; - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { - pClone->InsertChild(pChild->Clone(bRecursive)); + for (CXFA_Node* pChild = GetFirstChild(); pChild; + pChild = pChild->GetNextSibling()) { + pClone->InsertChild(pChild->Clone(bRecursive), nullptr); } } pClone->SetFlag(XFA_NodeFlag_Initialized, true); - pClone->SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); + pClone->SetBindingNode(nullptr); return pClone; } -CXFA_Node* CXFA_Node::GetNodeItem(XFA_NODEITEM eItem) const { - switch (eItem) { - case XFA_NODEITEM_NextSibling: - return m_pNext; - case XFA_NODEITEM_FirstChild: - return m_pChild; - case XFA_NODEITEM_Parent: - return m_pParent; - case XFA_NODEITEM_PrevSibling: - if (m_pParent) { - CXFA_Node* pSibling = m_pParent->m_pChild; - CXFA_Node* pPrev = nullptr; - while (pSibling && pSibling != this) { - pPrev = pSibling; - pSibling = pSibling->m_pNext; - } - return pPrev; - } - return nullptr; - default: - break; +CXFA_Node* CXFA_Node::GetPrevSibling() const { + if (!m_pParent || m_pParent->m_pChild == this) + return nullptr; + + for (CXFA_Node* pNode = m_pParent->m_pChild; pNode; pNode = pNode->m_pNext) { + if (pNode->m_pNext == this) + return pNode; } return nullptr; } -CXFA_Node* CXFA_Node::GetNodeItem(XFA_NODEITEM eItem, - XFA_ObjectType eType) const { - CXFA_Node* pNode = nullptr; - switch (eItem) { - case XFA_NODEITEM_NextSibling: - pNode = m_pNext; - while (pNode && pNode->GetObjectType() != eType) - pNode = pNode->m_pNext; - break; - case XFA_NODEITEM_FirstChild: - pNode = m_pChild; - while (pNode && pNode->GetObjectType() != eType) - pNode = pNode->m_pNext; - break; - case XFA_NODEITEM_Parent: - pNode = m_pParent; - while (pNode && pNode->GetObjectType() != eType) - pNode = pNode->m_pParent; - break; - case XFA_NODEITEM_PrevSibling: - if (m_pParent) { - CXFA_Node* pSibling = m_pParent->m_pChild; - while (pSibling && pSibling != this) { - if (eType == pSibling->GetObjectType()) - pNode = pSibling; - - pSibling = pSibling->m_pNext; - } - } +CXFA_Node* CXFA_Node::GetNextContainerSibling() const { + CXFA_Node* pNode = m_pNext; + while (pNode && pNode->GetObjectType() != XFA_ObjectType::ContainerNode) + pNode = pNode->m_pNext; + return pNode; +} + +CXFA_Node* CXFA_Node::GetPrevContainerSibling() const { + if (!m_pParent || m_pParent->m_pChild == this) + return nullptr; + + CXFA_Node* container = nullptr; + for (CXFA_Node* pNode = m_pParent->m_pChild; pNode; pNode = pNode->m_pNext) { + if (pNode->GetObjectType() == XFA_ObjectType::ContainerNode) + container = pNode; + if (pNode->m_pNext == this) + return container; + } + return nullptr; +} + +CXFA_Node* CXFA_Node::GetFirstContainerChild() const { + CXFA_Node* pNode = m_pChild; + while (pNode && pNode->GetObjectType() != XFA_ObjectType::ContainerNode) + pNode = pNode->m_pNext; + return pNode; +} + +CXFA_Node* CXFA_Node::GetContainerParent() const { + CXFA_Node* pNode = m_pParent; + while (pNode && pNode->GetObjectType() != XFA_ObjectType::ContainerNode) + pNode = pNode->m_pParent; + return pNode; +} + +bool CXFA_Node::IsValidInPacket(XFA_PacketType packet) const { + return !!(m_ValidPackets & (1 << static_cast<uint8_t>(packet))); +} + +const CXFA_Node::PropertyData* CXFA_Node::GetPropertyData( + XFA_Element property) const { + if (m_Properties == nullptr) + return nullptr; + + for (size_t i = 0;; ++i) { + const PropertyData* data = m_Properties + i; + if (data->property == XFA_Element::Unknown) break; - default: + if (data->property == property) + return data; + } + return nullptr; +} + +bool CXFA_Node::HasProperty(XFA_Element property) const { + return !!GetPropertyData(property); +} + +bool CXFA_Node::HasPropertyFlags(XFA_Element property, uint8_t flags) const { + const PropertyData* data = GetPropertyData(property); + return data && !!(data->flags & flags); +} + +uint8_t CXFA_Node::PropertyOccuranceCount(XFA_Element property) const { + const PropertyData* data = GetPropertyData(property); + return data ? data->occurance_count : 0; +} + +Optional<XFA_Element> CXFA_Node::GetFirstPropertyWithFlag(uint8_t flag) { + if (m_Properties == nullptr) + return {}; + + for (size_t i = 0;; ++i) { + const PropertyData* data = m_Properties + i; + if (data->property == XFA_Element::Unknown) break; + if (data->flags & flag) + return {data->property}; } - return pNode; + return {}; } -int32_t CXFA_Node::GetNodeList(CXFA_NodeArray& nodes, - uint32_t dwTypeFilter, - XFA_Element eTypeFilter, - int32_t iLevel) { - if (--iLevel < 0) { - return nodes.GetSize(); +const CXFA_Node::AttributeData* CXFA_Node::GetAttributeData( + XFA_Attribute attr) const { + if (m_Attributes == nullptr) + return nullptr; + + for (size_t i = 0;; ++i) { + const AttributeData* cur_attr = &m_Attributes[i]; + if (cur_attr->attribute == XFA_Attribute::Unknown) + break; + if (cur_attr->attribute == attr) + return cur_attr; } + return nullptr; +} + +bool CXFA_Node::HasAttribute(XFA_Attribute attr) const { + return !!GetAttributeData(attr); +} + +// Note: This Method assumes that i is a valid index .... +XFA_Attribute CXFA_Node::GetAttribute(size_t i) const { + if (m_Attributes == nullptr) + return XFA_Attribute::Unknown; + return m_Attributes[i].attribute; +} + +XFA_AttributeType CXFA_Node::GetAttributeType(XFA_Attribute type) const { + const AttributeData* data = GetAttributeData(type); + return data ? data->type : XFA_AttributeType::CData; +} + +std::vector<CXFA_Node*> CXFA_Node::GetNodeList(uint32_t dwTypeFilter, + XFA_Element eTypeFilter) { if (eTypeFilter != XFA_Element::Unknown) { - CXFA_Node* pChild = m_pChild; - while (pChild) { - if (pChild->GetElementType() == eTypeFilter) { - nodes.Add(pChild); - if (iLevel > 0) { - GetNodeList(nodes, dwTypeFilter, eTypeFilter, iLevel); - } - } - pChild = pChild->m_pNext; - } - } else if (dwTypeFilter == - (XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties)) { - CXFA_Node* pChild = m_pChild; - while (pChild) { - nodes.Add(pChild); - if (iLevel > 0) { - GetNodeList(nodes, dwTypeFilter, eTypeFilter, iLevel); - } - pChild = pChild->m_pNext; - } - } else if (dwTypeFilter != 0) { - bool bFilterChildren = !!(dwTypeFilter & XFA_NODEFILTER_Children); - bool bFilterProperties = !!(dwTypeFilter & XFA_NODEFILTER_Properties); - bool bFilterOneOfProperties = - !!(dwTypeFilter & XFA_NODEFILTER_OneOfProperty); - CXFA_Node* pChild = m_pChild; - while (pChild) { - const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( - GetElementType(), pChild->GetElementType(), XFA_XDPPACKET_UNKNOWN); - if (pProperty) { - if (bFilterProperties) { - nodes.Add(pChild); - } else if (bFilterOneOfProperties && - (pProperty->uFlags & XFA_PROPERTYFLAG_OneOf)) { - nodes.Add(pChild); - } else if (bFilterChildren && - (pChild->GetElementType() == XFA_Element::Variables || - pChild->GetElementType() == XFA_Element::PageSet)) { - nodes.Add(pChild); - } - } else if (bFilterChildren) { - nodes.Add(pChild); - } - pChild = pChild->m_pNext; - } - if (bFilterOneOfProperties && nodes.GetSize() < 1) { - int32_t iProperties = 0; - const XFA_PROPERTY* pProperty = - XFA_GetElementProperties(GetElementType(), iProperties); - if (!pProperty || iProperties < 1) - return 0; - for (int32_t i = 0; i < iProperties; i++) { - if (pProperty[i].uFlags & XFA_PROPERTYFLAG_DefaultOneOf) { - const XFA_PACKETINFO* pPacket = XFA_GetPacketByID(GetPacketID()); - CXFA_Node* pNewNode = - m_pDocument->CreateNode(pPacket, pProperty[i].eName); - if (!pNewNode) - break; - InsertChild(pNewNode, nullptr); - pNewNode->SetFlag(XFA_NodeFlag_Initialized, true); - nodes.Add(pNewNode); - break; - } - } - } + std::vector<CXFA_Node*> nodes; + for (CXFA_Node* pChild = m_pChild; pChild; pChild = pChild->m_pNext) { + if (pChild->GetElementType() == eTypeFilter) + nodes.push_back(pChild); + } + return nodes; + } + + if (dwTypeFilter == (XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties)) { + std::vector<CXFA_Node*> nodes; + for (CXFA_Node* pChild = m_pChild; pChild; pChild = pChild->m_pNext) + nodes.push_back(pChild); + return nodes; + } + + if (dwTypeFilter == 0) + return std::vector<CXFA_Node*>(); + + bool bFilterChildren = !!(dwTypeFilter & XFA_NODEFILTER_Children); + bool bFilterProperties = !!(dwTypeFilter & XFA_NODEFILTER_Properties); + bool bFilterOneOfProperties = !!(dwTypeFilter & XFA_NODEFILTER_OneOfProperty); + std::vector<CXFA_Node*> nodes; + for (CXFA_Node* pChild = m_pChild; pChild; pChild = pChild->m_pNext) { + if (!HasProperty(pChild->GetElementType())) { + if (bFilterProperties) { + nodes.push_back(pChild); + } else if (bFilterOneOfProperties && + HasPropertyFlags(pChild->GetElementType(), + XFA_PROPERTYFLAG_OneOf)) { + nodes.push_back(pChild); + } else if (bFilterChildren && + (pChild->GetElementType() == XFA_Element::Variables || + pChild->GetElementType() == XFA_Element::PageSet)) { + nodes.push_back(pChild); + } + } else if (bFilterChildren) { + nodes.push_back(pChild); + } + } + + if (!bFilterOneOfProperties || !nodes.empty()) + return nodes; + if (m_Properties == nullptr) + return nodes; + + Optional<XFA_Element> property = + GetFirstPropertyWithFlag(XFA_PROPERTYFLAG_DefaultOneOf); + if (!property) + return nodes; + + CXFA_Node* pNewNode = m_pDocument->CreateNode(GetPacketType(), *property); + if (pNewNode) { + InsertChild(pNewNode, nullptr); + pNewNode->SetFlag(XFA_NodeFlag_Initialized, true); + nodes.push_back(pNewNode); } - return nodes.GetSize(); + return nodes; } -CXFA_Node* CXFA_Node::CreateSamePacketNode(XFA_Element eType, - uint32_t dwFlags) { +CXFA_Node* CXFA_Node::CreateSamePacketNode(XFA_Element eType) { CXFA_Node* pNode = m_pDocument->CreateNode(m_ePacket, eType); - pNode->SetFlag(dwFlags, true); + pNode->SetFlag(XFA_NodeFlag_Initialized, true); return pNode; } CXFA_Node* CXFA_Node::CloneTemplateToForm(bool bRecursive) { - ASSERT(m_ePacket == XFA_XDPPACKET_Template); + ASSERT(m_ePacket == XFA_PacketType::Template); CXFA_Node* pClone = - m_pDocument->CreateNode(XFA_XDPPACKET_Form, m_elementType); + m_pDocument->CreateNode(XFA_PacketType::Form, m_elementType); if (!pClone) return nullptr; @@ -707,16 +470,16 @@ CXFA_Node* CXFA_Node::CloneTemplateToForm(bool bRecursive) { pClone->UpdateNameHash(); pClone->SetXMLMappingNode(GetXMLMappingNode()); if (bRecursive) { - for (CXFA_Node* pChild = GetNodeItem(XFA_NODEITEM_FirstChild); pChild; - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { - pClone->InsertChild(pChild->CloneTemplateToForm(bRecursive)); + for (CXFA_Node* pChild = GetFirstChild(); pChild; + pChild = pChild->GetNextSibling()) { + pClone->InsertChild(pChild->CloneTemplateToForm(bRecursive), nullptr); } } pClone->SetFlag(XFA_NodeFlag_Initialized, true); return pClone; } -CXFA_Node* CXFA_Node::GetTemplateNode() const { +CXFA_Node* CXFA_Node::GetTemplateNodeIfExists() const { return m_pAuxNode; } @@ -725,137 +488,117 @@ void CXFA_Node::SetTemplateNode(CXFA_Node* pTemplateNode) { } CXFA_Node* CXFA_Node::GetBindData() { - ASSERT(GetPacketID() == XFA_XDPPACKET_Form); - return static_cast<CXFA_Node*>(GetObject(XFA_ATTRIBUTE_BindingNode)); + ASSERT(GetPacketType() == XFA_PacketType::Form); + return GetBindingNode(); } -int32_t CXFA_Node::GetBindItems(CXFA_NodeArray& formItems) { - if (BindsFormItems()) { - CXFA_NodeArray* pItems = nullptr; - TryObject(XFA_ATTRIBUTE_BindingNode, (void*&)pItems); - formItems.Copy(*pItems); - return formItems.GetSize(); - } - CXFA_Node* pFormNode = - static_cast<CXFA_Node*>(GetObject(XFA_ATTRIBUTE_BindingNode)); - if (pFormNode) - formItems.Add(pFormNode); - return formItems.GetSize(); +std::vector<UnownedPtr<CXFA_Node>>* CXFA_Node::GetBindItems() { + return GetBindingNodes(); } int32_t CXFA_Node::AddBindItem(CXFA_Node* pFormNode) { ASSERT(pFormNode); + if (BindsFormItems()) { - CXFA_NodeArray* pItems = nullptr; - TryObject(XFA_ATTRIBUTE_BindingNode, (void*&)pItems); - ASSERT(pItems); - if (pItems->Find(pFormNode) < 0) { - pItems->Add(pFormNode); + bool found = false; + for (auto& v : binding_nodes_) { + if (v.Get() == pFormNode) { + found = true; + break; + } } - return pItems->GetSize(); + if (!found) + binding_nodes_.emplace_back(pFormNode); + return pdfium::CollectionSize<int32_t>(binding_nodes_); } - CXFA_Node* pOldFormItem = - static_cast<CXFA_Node*>(GetObject(XFA_ATTRIBUTE_BindingNode)); + + CXFA_Node* pOldFormItem = GetBindingNode(); if (!pOldFormItem) { - SetObject(XFA_ATTRIBUTE_BindingNode, pFormNode); - return 1; - } else if (pOldFormItem == pFormNode) { + SetBindingNode(pFormNode); return 1; } - CXFA_NodeArray* pItems = new CXFA_NodeArray; - SetObject(XFA_ATTRIBUTE_BindingNode, pItems, &deleteBindItemCallBack); - pItems->Add(pOldFormItem); - pItems->Add(pFormNode); + if (pOldFormItem == pFormNode) + return 1; + + std::vector<UnownedPtr<CXFA_Node>> items; + items.emplace_back(pOldFormItem); + items.emplace_back(pFormNode); + SetBindingNodes(std::move(items)); + m_uNodeFlags |= XFA_NodeFlag_BindFormItems; return 2; } int32_t CXFA_Node::RemoveBindItem(CXFA_Node* pFormNode) { if (BindsFormItems()) { - CXFA_NodeArray* pItems = nullptr; - TryObject(XFA_ATTRIBUTE_BindingNode, (void*&)pItems); - ASSERT(pItems); - int32_t iIndex = pItems->Find(pFormNode); - int32_t iCount = pItems->GetSize(); - if (iIndex >= 0) { - if (iIndex != iCount - 1) - pItems->SetAt(iIndex, pItems->GetAt(iCount - 1)); - pItems->RemoveAt(iCount - 1); - if (iCount == 2) { - CXFA_Node* pLastFormNode = pItems->GetAt(0); - SetObject(XFA_ATTRIBUTE_BindingNode, pLastFormNode); - m_uNodeFlags &= ~XFA_NodeFlag_BindFormItems; - } - iCount--; + auto it = std::find_if(binding_nodes_.begin(), binding_nodes_.end(), + [&pFormNode](const UnownedPtr<CXFA_Node>& node) { + return node.Get() == pFormNode; + }); + if (it != binding_nodes_.end()) + binding_nodes_.erase(it); + + if (binding_nodes_.size() == 1) { + m_uNodeFlags &= ~XFA_NodeFlag_BindFormItems; + return 1; } - return iCount; - } - CXFA_Node* pOldFormItem = - static_cast<CXFA_Node*>(GetObject(XFA_ATTRIBUTE_BindingNode)); - if (pOldFormItem == pFormNode) { - SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); - pOldFormItem = nullptr; + return pdfium::CollectionSize<int32_t>(binding_nodes_); } - return pOldFormItem ? 1 : 0; -} -bool CXFA_Node::HasBindItem() { - return GetPacketID() == XFA_XDPPACKET_Datasets && - GetObject(XFA_ATTRIBUTE_BindingNode); + CXFA_Node* pOldFormItem = GetBindingNode(); + if (pOldFormItem != pFormNode) + return pOldFormItem ? 1 : 0; + + SetBindingNode(nullptr); + return 0; } -CXFA_WidgetData* CXFA_Node::GetWidgetData() { - return (CXFA_WidgetData*)GetObject(XFA_ATTRIBUTE_WidgetData); +bool CXFA_Node::HasBindItem() { + return GetPacketType() == XFA_PacketType::Datasets && GetBindingNode(); } -CXFA_WidgetData* CXFA_Node::GetContainerWidgetData() { - if (GetPacketID() != XFA_XDPPACKET_Form) +CXFA_WidgetAcc* CXFA_Node::GetContainerWidgetAcc() { + if (GetPacketType() != XFA_PacketType::Form) return nullptr; XFA_Element eType = GetElementType(); if (eType == XFA_Element::ExclGroup) return nullptr; - CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pParentNode = GetParent(); if (pParentNode && pParentNode->GetElementType() == XFA_Element::ExclGroup) return nullptr; if (eType == XFA_Element::Field) { - CXFA_WidgetData* pFieldWidgetData = GetWidgetData(); - if (pFieldWidgetData && - pFieldWidgetData->GetChoiceListOpen() == - XFA_ATTRIBUTEENUM_MultiSelect) { + CXFA_WidgetAcc* pFieldWidgetAcc = GetWidgetAcc(); + if (pFieldWidgetAcc && pFieldWidgetAcc->IsChoiceListMultiSelect()) return nullptr; - } else { - CFX_WideString wsPicture; - if (pFieldWidgetData) { - pFieldWidgetData->GetPictureContent(wsPicture, - XFA_VALUEPICTURE_DataBind); + + WideString wsPicture; + if (pFieldWidgetAcc) { + wsPicture = pFieldWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind); + } + if (!wsPicture.IsEmpty()) + return pFieldWidgetAcc; + + CXFA_Node* pDataNode = GetBindData(); + if (!pDataNode) + return nullptr; + pFieldWidgetAcc = nullptr; + for (const auto& pFormNode : *(pDataNode->GetBindItems())) { + if (!pFormNode || pFormNode->HasRemovedChildren()) + continue; + pFieldWidgetAcc = pFormNode->GetWidgetAcc(); + if (pFieldWidgetAcc) { + wsPicture = + pFieldWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind); } if (!wsPicture.IsEmpty()) - return pFieldWidgetData; - CXFA_Node* pDataNode = GetBindData(); - if (!pDataNode) - return nullptr; - pFieldWidgetData = nullptr; - CXFA_NodeArray formNodes; - pDataNode->GetBindItems(formNodes); - for (int32_t i = 0; i < formNodes.GetSize(); i++) { - CXFA_Node* pFormNode = formNodes.GetAt(i); - if (!pFormNode || pFormNode->HasRemovedChildren()) - continue; - pFieldWidgetData = pFormNode->GetWidgetData(); - if (pFieldWidgetData) { - pFieldWidgetData->GetPictureContent(wsPicture, - XFA_VALUEPICTURE_DataBind); - } - if (!wsPicture.IsEmpty()) - break; - pFieldWidgetData = nullptr; - } - return pFieldWidgetData; + break; + pFieldWidgetAcc = nullptr; } + return pFieldWidgetAcc; } - CXFA_Node* pGrandNode = - pParentNode ? pParentNode->GetNodeItem(XFA_NODEITEM_Parent) : nullptr; + + CXFA_Node* pGrandNode = pParentNode ? pParentNode->GetParent() : nullptr; CXFA_Node* pValueNode = (pParentNode && pParentNode->GetElementType() == XFA_Element::Value) ? pParentNode @@ -867,793 +610,780 @@ CXFA_WidgetData* CXFA_Node::GetContainerWidgetData() { : nullptr; } CXFA_Node* pParentOfValueNode = - pValueNode ? pValueNode->GetNodeItem(XFA_NODEITEM_Parent) : nullptr; - return pParentOfValueNode ? pParentOfValueNode->GetContainerWidgetData() + pValueNode ? pValueNode->GetParent() : nullptr; + return pParentOfValueNode ? pParentOfValueNode->GetContainerWidgetAcc() : nullptr; } -bool CXFA_Node::GetLocaleName(CFX_WideString& wsLocaleName) { +IFX_Locale* CXFA_Node::GetLocale() { + Optional<WideString> localeName = GetLocaleName(); + if (!localeName) + return nullptr; + if (localeName.value() == L"ambient") + return GetDocument()->GetLocalMgr()->GetDefLocale(); + return GetDocument()->GetLocalMgr()->GetLocaleByName(localeName.value()); +} + +Optional<WideString> CXFA_Node::GetLocaleName() { CXFA_Node* pForm = GetDocument()->GetXFAObject(XFA_HASHCODE_Form)->AsNode(); - CXFA_Node* pTopSubform = pForm->GetFirstChildByClass(XFA_Element::Subform); + CXFA_Subform* pTopSubform = + pForm->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); ASSERT(pTopSubform); + CXFA_Node* pLocaleNode = this; - bool bLocale = false; do { - bLocale = pLocaleNode->TryCData(XFA_ATTRIBUTE_Locale, wsLocaleName, false); - if (!bLocale) { - pLocaleNode = pLocaleNode->GetNodeItem(XFA_NODEITEM_Parent); - } - } while (pLocaleNode && pLocaleNode != pTopSubform && !bLocale); - if (bLocale) - return true; + Optional<WideString> localeName = + pLocaleNode->JSObject()->TryCData(XFA_Attribute::Locale, false); + if (localeName) + return localeName; + + pLocaleNode = pLocaleNode->GetParent(); + } while (pLocaleNode && pLocaleNode != pTopSubform); + CXFA_Node* pConfig = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Config)); - wsLocaleName = GetDocument()->GetLocalMgr()->GetConfigLocaleName(pConfig); - if (!wsLocaleName.IsEmpty()) - return true; - if (pTopSubform && - pTopSubform->TryCData(XFA_ATTRIBUTE_Locale, wsLocaleName, false)) { - return true; + Optional<WideString> localeName = { + WideString(GetDocument()->GetLocalMgr()->GetConfigLocaleName(pConfig))}; + if (localeName && !localeName->IsEmpty()) + return localeName; + + if (pTopSubform) { + localeName = + pTopSubform->JSObject()->TryCData(XFA_Attribute::Locale, false); + if (localeName) + return localeName; } + IFX_Locale* pLocale = GetDocument()->GetLocalMgr()->GetDefLocale(); - if (pLocale) { - wsLocaleName = pLocale->GetName(); - return true; - } - return false; + if (!pLocale) + return {}; + + return {pLocale->GetName()}; } -XFA_ATTRIBUTEENUM CXFA_Node::GetIntact() { - CXFA_Node* pKeep = GetFirstChildByClass(XFA_Element::Keep); - XFA_ATTRIBUTEENUM eLayoutType = GetEnum(XFA_ATTRIBUTE_Layout); +XFA_AttributeEnum CXFA_Node::GetIntact() { + CXFA_Keep* pKeep = GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); + XFA_AttributeEnum eLayoutType = JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); if (pKeep) { - XFA_ATTRIBUTEENUM eIntact; - if (pKeep->TryEnum(XFA_ATTRIBUTE_Intact, eIntact, false)) { - if (eIntact == XFA_ATTRIBUTEENUM_None && - eLayoutType == XFA_ATTRIBUTEENUM_Row && + Optional<XFA_AttributeEnum> intact = + pKeep->JSObject()->TryEnum(XFA_Attribute::Intact, false); + if (intact) { + if (*intact == XFA_AttributeEnum::None && + eLayoutType == XFA_AttributeEnum::Row && m_pDocument->GetCurVersionMode() < XFA_VERSION_208) { - CXFA_Node* pPreviewRow = GetNodeItem(XFA_NODEITEM_PrevSibling, - XFA_ObjectType::ContainerNode); + CXFA_Node* pPreviewRow = GetPrevContainerSibling(); if (pPreviewRow && - pPreviewRow->GetEnum(XFA_ATTRIBUTE_Layout) == - XFA_ATTRIBUTEENUM_Row) { - XFA_ATTRIBUTEENUM eValue; - if (pKeep->TryEnum(XFA_ATTRIBUTE_Previous, eValue, false) && - (eValue == XFA_ATTRIBUTEENUM_ContentArea || - eValue == XFA_ATTRIBUTEENUM_PageArea)) { - return XFA_ATTRIBUTEENUM_ContentArea; + pPreviewRow->JSObject()->GetEnum(XFA_Attribute::Layout) == + XFA_AttributeEnum::Row) { + Optional<XFA_AttributeEnum> value = + pKeep->JSObject()->TryEnum(XFA_Attribute::Previous, false); + if (value && (*value == XFA_AttributeEnum::ContentArea || + *value == XFA_AttributeEnum::PageArea)) { + return XFA_AttributeEnum::ContentArea; } - CXFA_Node* pNode = - pPreviewRow->GetFirstChildByClass(XFA_Element::Keep); - if (pNode && pNode->TryEnum(XFA_ATTRIBUTE_Next, eValue, false) && - (eValue == XFA_ATTRIBUTEENUM_ContentArea || - eValue == XFA_ATTRIBUTEENUM_PageArea)) { - return XFA_ATTRIBUTEENUM_ContentArea; + + CXFA_Keep* pNode = + pPreviewRow->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep); + Optional<XFA_AttributeEnum> ret; + if (pNode) + ret = pNode->JSObject()->TryEnum(XFA_Attribute::Next, false); + if (ret && (*ret == XFA_AttributeEnum::ContentArea || + *ret == XFA_AttributeEnum::PageArea)) { + return XFA_AttributeEnum::ContentArea; } } } - return eIntact; + return *intact; } } + switch (GetElementType()) { case XFA_Element::Subform: switch (eLayoutType) { - case XFA_ATTRIBUTEENUM_Position: - case XFA_ATTRIBUTEENUM_Row: - return XFA_ATTRIBUTEENUM_ContentArea; - case XFA_ATTRIBUTEENUM_Tb: - case XFA_ATTRIBUTEENUM_Table: - case XFA_ATTRIBUTEENUM_Lr_tb: - case XFA_ATTRIBUTEENUM_Rl_tb: - return XFA_ATTRIBUTEENUM_None; + case XFA_AttributeEnum::Position: + case XFA_AttributeEnum::Row: + return XFA_AttributeEnum::ContentArea; default: - break; + return XFA_AttributeEnum::None; } - break; case XFA_Element::Field: { - CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent); - if (!pParentNode || - pParentNode->GetElementType() == XFA_Element::PageArea) - return XFA_ATTRIBUTEENUM_ContentArea; - if (pParentNode->GetIntact() == XFA_ATTRIBUTEENUM_None) { - XFA_ATTRIBUTEENUM eParLayout = - pParentNode->GetEnum(XFA_ATTRIBUTE_Layout); - if (eParLayout == XFA_ATTRIBUTEENUM_Position || - eParLayout == XFA_ATTRIBUTEENUM_Row || - eParLayout == XFA_ATTRIBUTEENUM_Table) { - return XFA_ATTRIBUTEENUM_None; - } - XFA_VERSION version = m_pDocument->GetCurVersionMode(); - if (eParLayout == XFA_ATTRIBUTEENUM_Tb && version < XFA_VERSION_208) { - CXFA_Measurement measureH; - if (TryMeasure(XFA_ATTRIBUTE_H, measureH, false)) - return XFA_ATTRIBUTEENUM_ContentArea; - } - return XFA_ATTRIBUTEENUM_None; - } - return XFA_ATTRIBUTEENUM_ContentArea; + CXFA_Node* parent = GetParent(); + if (!parent || parent->GetElementType() == XFA_Element::PageArea) + return XFA_AttributeEnum::ContentArea; + if (parent->GetIntact() != XFA_AttributeEnum::None) + return XFA_AttributeEnum::ContentArea; + + XFA_AttributeEnum eParLayout = parent->JSObject() + ->TryEnum(XFA_Attribute::Layout, true) + .value_or(XFA_AttributeEnum::Position); + if (eParLayout == XFA_AttributeEnum::Position || + eParLayout == XFA_AttributeEnum::Row || + eParLayout == XFA_AttributeEnum::Table) { + return XFA_AttributeEnum::None; + } + + XFA_VERSION version = m_pDocument->GetCurVersionMode(); + if (eParLayout == XFA_AttributeEnum::Tb && version < XFA_VERSION_208) { + Optional<CXFA_Measurement> measureH = + JSObject()->TryMeasure(XFA_Attribute::H, false); + if (measureH) + return XFA_AttributeEnum::ContentArea; + } + return XFA_AttributeEnum::None; } case XFA_Element::Draw: - return XFA_ATTRIBUTEENUM_ContentArea; + return XFA_AttributeEnum::ContentArea; default: - break; + return XFA_AttributeEnum::None; } - return XFA_ATTRIBUTEENUM_None; } CXFA_Node* CXFA_Node::GetDataDescriptionNode() { - if (m_ePacket == XFA_XDPPACKET_Datasets) + if (m_ePacket == XFA_PacketType::Datasets) return m_pAuxNode; return nullptr; } void CXFA_Node::SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode) { - ASSERT(m_ePacket == XFA_XDPPACKET_Datasets); + ASSERT(m_ePacket == XFA_PacketType::Datasets); m_pAuxNode = pDataDescriptionNode; } -void CXFA_Node::Script_TreeClass_ResolveNode(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"resolveNode"); - return; - } - CFX_WideString wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) - return; - CXFA_Node* refNode = this; - if (refNode->GetElementType() == XFA_Element::Xfa) - refNode = ToNode(pScriptContext->GetThisObject()); - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | - XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Siblings; - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = pScriptContext->ResolveObjects( - refNode, wsExpression.AsStringC(), resoveNodeRS, dwFlag); - if (iRet < 1) { - pArguments->GetReturnValue()->SetNull(); - return; - } - if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { - CXFA_Object* pNode = resoveNodeRS.nodes[0]; - pArguments->GetReturnValue()->Assign( - pScriptContext->GetJSValueFromMap(pNode)); - } else { - const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = - resoveNodeRS.pScriptAttribute; - if (lpAttributeInfo && lpAttributeInfo->eValueType == XFA_SCRIPT_Object) { - std::unique_ptr<CFXJSE_Value> pValue( - new CFXJSE_Value(pScriptContext->GetRuntime())); - (resoveNodeRS.nodes[0]->*(lpAttributeInfo->lpfnCallback))( - pValue.get(), false, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); - pArguments->GetReturnValue()->Assign(pValue.get()); - } else { - pArguments->GetReturnValue()->SetNull(); - } +CXFA_Node* CXFA_Node::GetModelNode() { + switch (GetPacketType()) { + case XFA_PacketType::Xdp: + return m_pDocument->GetRoot(); + case XFA_PacketType::Config: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config)); + case XFA_PacketType::Template: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Template)); + case XFA_PacketType::Form: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form)); + case XFA_PacketType::Datasets: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Datasets)); + case XFA_PacketType::LocaleSet: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_LocaleSet)); + case XFA_PacketType::ConnectionSet: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_ConnectionSet)); + case XFA_PacketType::SourceSet: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_SourceSet)); + case XFA_PacketType::Xdc: + return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Xdc)); + default: + return this; } } -void CXFA_Node::Script_TreeClass_ResolveNodes(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"resolveNodes"); - return; - } - CFX_WideString wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (!pValue) - return; - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | - XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Siblings; - CXFA_Node* refNode = this; - if (refNode->GetElementType() == XFA_Element::Xfa) - refNode = ToNode(m_pDocument->GetScriptContext()->GetThisObject()); - Script_Som_ResolveNodeList(pValue, wsExpression, dwFlag, refNode); -} - -void CXFA_Node::Script_Som_ResolveNodeList(CFXJSE_Value* pValue, - CFX_WideString wsExpression, - uint32_t dwFlag, - CXFA_Node* refNode) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) - return; - XFA_RESOLVENODE_RS resoveNodeRS; - if (!refNode) - refNode = this; - pScriptContext->ResolveObjects(refNode, wsExpression.AsStringC(), - resoveNodeRS, dwFlag); - CXFA_ArrayNodeList* pNodeList = new CXFA_ArrayNodeList(m_pDocument); - if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { - for (int32_t i = 0; i < resoveNodeRS.nodes.GetSize(); i++) { - if (resoveNodeRS.nodes[i]->IsNode()) - pNodeList->Append(resoveNodeRS.nodes[i]->AsNode()); - } - } else { - CXFA_ValueArray valueArray(pScriptContext->GetRuntime()); - if (resoveNodeRS.GetAttributeResult(valueArray) > 0) { - CXFA_ObjArray objectArray; - valueArray.GetAttributeObject(objectArray); - for (int32_t i = 0; i < objectArray.GetSize(); i++) { - if (objectArray[i]->IsNode()) - pNodeList->Append(objectArray[i]->AsNode()); - } - } +size_t CXFA_Node::CountChildren(XFA_Element eType, bool bOnlyChild) { + size_t count = 0; + for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown) + continue; + if (bOnlyChild && HasProperty(pNode->GetElementType())) + continue; + ++count; } - pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass()); + return count; } -void CXFA_Node::Script_TreeClass_All(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - uint32_t dwFlag = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL; - CFX_WideString wsName; - GetAttribute(XFA_ATTRIBUTE_Name, wsName); - CFX_WideString wsExpression = wsName + L"[*]"; - Script_Som_ResolveNodeList(pValue, wsExpression, dwFlag); -} +CXFA_Node* CXFA_Node::GetChildInternal(size_t index, + XFA_Element eType, + bool bOnlyChild) { + size_t count = 0; + for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() != eType && eType != XFA_Element::Unknown) + continue; + if (bOnlyChild && HasProperty(pNode->GetElementType())) + continue; + if (count == index) + return pNode; -void CXFA_Node::Script_TreeClass_Nodes(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) - return; - if (bSetting) { - CFX_WideString wsMessage = L"Unable to set "; - FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringC()); - } else { - CXFA_AttachNodeList* pNodeList = new CXFA_AttachNodeList(m_pDocument, this); - pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass()); + ++count; } + return nullptr; } -void CXFA_Node::Script_TreeClass_ClassAll(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - uint32_t dwFlag = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL; - CFX_WideString wsExpression = L"#" + GetClassName() + L"[*]"; - Script_Som_ResolveNodeList(pValue, wsExpression, dwFlag); -} +int32_t CXFA_Node::InsertChild(int32_t index, CXFA_Node* pNode) { + ASSERT(!pNode->m_pNext); + pNode->m_pParent = this; + bool ret = m_pDocument->RemovePurgeNode(pNode); + ASSERT(ret); + (void)ret; // Avoid unused variable warning. -void CXFA_Node::Script_TreeClass_Parent(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - CXFA_Node* pParent = GetNodeItem(XFA_NODEITEM_Parent); - if (pParent) { - pValue->Assign(m_pDocument->GetScriptContext()->GetJSValueFromMap(pParent)); + if (!m_pChild || index == 0) { + if (index > 0) { + return -1; + } + pNode->m_pNext = m_pChild; + m_pChild = pNode; + index = 0; + } else if (index < 0) { + m_pLastChild->m_pNext = pNode; } else { - pValue->SetNull(); - } -} - -void CXFA_Node::Script_TreeClass_Index(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; + CXFA_Node* pPrev = m_pChild; + int32_t iCount = 0; + while (++iCount != index && pPrev->m_pNext) { + pPrev = pPrev->m_pNext; + } + if (index > 0 && index != iCount) { + return -1; + } + pNode->m_pNext = pPrev->m_pNext; + pPrev->m_pNext = pNode; + index = iCount; } - pValue->SetInteger(GetNodeSameNameIndex()); -} - -void CXFA_Node::Script_TreeClass_ClassIndex(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; + if (!pNode->m_pNext) { + m_pLastChild = pNode; } - pValue->SetInteger(GetNodeSameClassIndex()); -} + ASSERT(m_pLastChild); + ASSERT(!m_pLastChild->m_pNext); + pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren); + CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); + if (pNotify) + pNotify->OnChildAdded(this); -void CXFA_Node::Script_TreeClass_SomExpression(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; + if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { + ASSERT(!pNode->m_pXMLNode->GetNodeItem(CFX_XMLNode::Parent)); + m_pXMLNode->InsertChildNode(pNode->m_pXMLNode, index); + pNode->ClearFlag(XFA_NodeFlag_OwnXMLNode); } - CFX_WideString wsSOMExpression; - GetSOMExpression(wsSOMExpression); - pValue->SetString(wsSOMExpression.UTF8Encode().AsStringC()); + return index; } -void CXFA_Node::Script_NodeClass_ApplyXSL(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"applyXSL"); - return; +bool CXFA_Node::InsertChild(CXFA_Node* pNode, CXFA_Node* pBeforeNode) { + if (!pNode || pNode->m_pParent || + (pBeforeNode && pBeforeNode->m_pParent != this)) { + NOTREACHED(); + return false; } - CFX_WideString wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - // TODO(weili): check whether we need to implement this, pdfium:501. - // For now, just put the variables here to avoid unused variable warning. - (void)wsExpression; -} + bool ret = m_pDocument->RemovePurgeNode(pNode); + ASSERT(ret); + (void)ret; // Avoid unused variable warning. -void CXFA_Node::Script_NodeClass_AssignNode(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 3) { - ThrowParamCountMismatchException(L"assignNode"); - return; + int32_t nIndex = -1; + pNode->m_pParent = this; + if (!m_pChild || pBeforeNode == m_pChild) { + pNode->m_pNext = m_pChild; + m_pChild = pNode; + nIndex = 0; + } else if (!pBeforeNode) { + pNode->m_pNext = m_pLastChild->m_pNext; + m_pLastChild->m_pNext = pNode; + } else { + nIndex = 1; + CXFA_Node* pPrev = m_pChild; + while (pPrev->m_pNext != pBeforeNode) { + pPrev = pPrev->m_pNext; + nIndex++; + } + pNode->m_pNext = pPrev->m_pNext; + pPrev->m_pNext = pNode; } - CFX_WideString wsExpression; - CFX_WideString wsValue; - int32_t iAction = 0; - wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - if (iLength >= 2) { - wsValue = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(1).AsStringC()); + if (!pNode->m_pNext) { + m_pLastChild = pNode; } - if (iLength >= 3) - iAction = pArguments->GetInt32(2); - // TODO(weili): check whether we need to implement this, pdfium:501. - // For now, just put the variables here to avoid unused variable warning. - (void)wsExpression; - (void)wsValue; - (void)iAction; -} - -void CXFA_Node::Script_NodeClass_Clone(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"clone"); - return; + ASSERT(m_pLastChild); + ASSERT(!m_pLastChild->m_pNext); + pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren); + CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); + if (pNotify) + pNotify->OnChildAdded(this); + + if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { + ASSERT(!pNode->m_pXMLNode->GetNodeItem(CFX_XMLNode::Parent)); + m_pXMLNode->InsertChildNode(pNode->m_pXMLNode, nIndex); + pNode->ClearFlag(XFA_NodeFlag_OwnXMLNode); } - bool bClone = !!pArguments->GetInt32(0); - CXFA_Node* pCloneNode = Clone(bClone); - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pCloneNode)); + return true; } -void CXFA_Node::Script_NodeClass_GetAttribute(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"getAttribute"); - return; - } - CFX_WideString wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - CFX_WideString wsValue; - GetAttribute(wsExpression.AsStringC(), wsValue); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetString(wsValue.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_NodeClass_GetElement(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 2) { - ThrowParamCountMismatchException(L"getElement"); - return; - } - CFX_WideString wsExpression; - int32_t iValue = 0; - wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - if (iLength >= 2) - iValue = pArguments->GetInt32(1); - CXFA_Node* pNode = - GetProperty(iValue, XFA_GetElementTypeForName(wsExpression.AsStringC())); - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNode)); -} - -void CXFA_Node::Script_NodeClass_IsPropertySpecified( - CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 3) { - ThrowParamCountMismatchException(L"isPropertySpecified"); - return; +CXFA_Node* CXFA_Node::Deprecated_GetPrevSibling() { + if (!m_pParent) { + return nullptr; } - CFX_WideString wsExpression; - bool bParent = true; - int32_t iIndex = 0; - wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - if (iLength >= 2) - bParent = !!pArguments->GetInt32(1); - if (iLength >= 3) - iIndex = pArguments->GetInt32(2); - bool bHas = false; - const XFA_ATTRIBUTEINFO* pAttributeInfo = - XFA_GetAttributeByName(wsExpression.AsStringC()); - CFX_WideString wsValue; - if (pAttributeInfo) - bHas = HasAttribute(pAttributeInfo->eName); - if (!bHas) { - XFA_Element eType = XFA_GetElementTypeForName(wsExpression.AsStringC()); - bHas = !!GetProperty(iIndex, eType); - if (!bHas && bParent && m_pParent) { - // Also check on the parent. - bHas = m_pParent->HasAttribute(pAttributeInfo->eName); - if (!bHas) - bHas = !!m_pParent->GetProperty(iIndex, eType); + for (CXFA_Node* pSibling = m_pParent->m_pChild; pSibling; + pSibling = pSibling->m_pNext) { + if (pSibling->m_pNext == this) { + return pSibling; } } - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetBoolean(bHas); + return nullptr; } -void CXFA_Node::Script_NodeClass_LoadXML(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 3) { - ThrowParamCountMismatchException(L"loadXML"); - return; - } - CFX_WideString wsExpression; - bool bIgnoreRoot = true; - bool bOverwrite = 0; - wsExpression = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - if (wsExpression.IsEmpty()) - return; - if (iLength >= 2) - bIgnoreRoot = !!pArguments->GetInt32(1); - if (iLength >= 3) - bOverwrite = !!pArguments->GetInt32(2); - std::unique_ptr<CXFA_SimpleParser> pParser( - new CXFA_SimpleParser(m_pDocument, false)); - if (!pParser) - return; - CFDE_XMLNode* pXMLNode = nullptr; - int32_t iParserStatus = - pParser->ParseXMLData(wsExpression, pXMLNode, nullptr); - if (iParserStatus != XFA_PARSESTATUS_Done || !pXMLNode) - return; - if (bIgnoreRoot && - (pXMLNode->GetType() != FDE_XMLNODE_Element || - XFA_RecognizeRichText(static_cast<CFDE_XMLElement*>(pXMLNode)))) { - bIgnoreRoot = false; - } - CXFA_Node* pFakeRoot = Clone(false); - CFX_WideStringC wsContentType = GetCData(XFA_ATTRIBUTE_ContentType); - if (!wsContentType.IsEmpty()) { - pFakeRoot->SetCData(XFA_ATTRIBUTE_ContentType, - CFX_WideString(wsContentType)); - } - CFDE_XMLNode* pFakeXMLRoot = pFakeRoot->GetXMLMappingNode(); - if (!pFakeXMLRoot) { - CFDE_XMLNode* pThisXMLRoot = GetXMLMappingNode(); - pFakeXMLRoot = pThisXMLRoot ? pThisXMLRoot->Clone(false) : nullptr; +bool CXFA_Node::RemoveChild(CXFA_Node* pNode, bool bNotify) { + if (!pNode || pNode->m_pParent != this) { + NOTREACHED(); + return false; } - if (!pFakeXMLRoot) - pFakeXMLRoot = new CFDE_XMLElement(CFX_WideString(GetClassName())); - - if (bIgnoreRoot) { - CFDE_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); - while (pXMLChild) { - CFDE_XMLNode* pXMLSibling = - pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling); - pXMLNode->RemoveChildNode(pXMLChild); - pFakeXMLRoot->InsertChildNode(pXMLChild); - pXMLChild = pXMLSibling; + if (m_pChild == pNode) { + m_pChild = pNode->m_pNext; + if (m_pLastChild == pNode) { + m_pLastChild = pNode->m_pNext; } + pNode->m_pNext = nullptr; + pNode->m_pParent = nullptr; } else { - CFDE_XMLNode* pXMLParent = pXMLNode->GetNodeItem(CFDE_XMLNode::Parent); - if (pXMLParent) { - pXMLParent->RemoveChildNode(pXMLNode); + CXFA_Node* pPrev = pNode->Deprecated_GetPrevSibling(); + pPrev->m_pNext = pNode->m_pNext; + if (m_pLastChild == pNode) { + m_pLastChild = pNode->m_pNext ? pNode->m_pNext : pPrev; } - pFakeXMLRoot->InsertChildNode(pXMLNode); + pNode->m_pNext = nullptr; + pNode->m_pParent = nullptr; } - pParser->ConstructXFANode(pFakeRoot, pFakeXMLRoot); - pFakeRoot = pParser->GetRootNode(); - if (pFakeRoot) { - if (bOverwrite) { - CXFA_Node* pChild = GetNodeItem(XFA_NODEITEM_FirstChild); - CXFA_Node* pNewChild = pFakeRoot->GetNodeItem(XFA_NODEITEM_FirstChild); - int32_t index = 0; - while (pNewChild) { - CXFA_Node* pItem = pNewChild->GetNodeItem(XFA_NODEITEM_NextSibling); - pFakeRoot->RemoveChild(pNewChild); - InsertChild(index++, pNewChild); - pNewChild->SetFlag(XFA_NodeFlag_Initialized, true); - pNewChild = pItem; - } - while (pChild) { - CXFA_Node* pItem = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - RemoveChild(pChild); - pFakeRoot->InsertChild(pChild); - pChild = pItem; - } - if (GetPacketID() == XFA_XDPPACKET_Form && - GetElementType() == XFA_Element::ExData) { - CFDE_XMLNode* pTempXMLNode = GetXMLMappingNode(); - SetXMLMappingNode(pFakeXMLRoot); - SetFlag(XFA_NodeFlag_OwnXMLNode, false); - if (pTempXMLNode && !pTempXMLNode->GetNodeItem(CFDE_XMLNode::Parent)) { - pFakeXMLRoot = pTempXMLNode; - } else { - pFakeXMLRoot = nullptr; - } + ASSERT(!m_pLastChild || !m_pLastChild->m_pNext); + OnRemoved(bNotify); + pNode->SetFlag(XFA_NodeFlag_HasRemovedChildren, true); + m_pDocument->AddPurgeNode(pNode); + if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { + if (pNode->IsAttributeInXML()) { + ASSERT(pNode->m_pXMLNode == m_pXMLNode && + m_pXMLNode->GetType() == FX_XMLNODE_Element); + if (pNode->m_pXMLNode->GetType() == FX_XMLNODE_Element) { + CFX_XMLElement* pXMLElement = + static_cast<CFX_XMLElement*>(pNode->m_pXMLNode); + WideString wsAttributeName = + pNode->JSObject()->GetCData(XFA_Attribute::QualifiedName); + pXMLElement->RemoveAttribute(wsAttributeName.c_str()); } - MoveBufferMapData(pFakeRoot, this, XFA_CalcData, true); + + WideString wsName = pNode->JSObject() + ->TryAttribute(XFA_Attribute::Name, false) + .value_or(WideString()); + CFX_XMLElement* pNewXMLElement = new CFX_XMLElement(wsName); + WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value); + if (!wsValue.IsEmpty()) + pNewXMLElement->SetTextData(WideString(wsValue)); + + pNode->m_pXMLNode = pNewXMLElement; + pNode->JSObject()->SetEnum(XFA_Attribute::Contains, + XFA_AttributeEnum::Unknown, false); } else { - CXFA_Node* pChild = pFakeRoot->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pChild) { - CXFA_Node* pItem = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - pFakeRoot->RemoveChild(pChild); - InsertChild(pChild); - pChild->SetFlag(XFA_NodeFlag_Initialized, true); - pChild = pItem; - } - } - if (pFakeXMLRoot) { - pFakeRoot->SetXMLMappingNode(pFakeXMLRoot); - pFakeRoot->SetFlag(XFA_NodeFlag_OwnXMLNode, false); + m_pXMLNode->RemoveChildNode(pNode->m_pXMLNode); } - pFakeRoot->SetFlag(XFA_NodeFlag_HasRemovedChildren, false); - } else { - delete pFakeXMLRoot; - pFakeXMLRoot = nullptr; + pNode->SetFlag(XFA_NodeFlag_OwnXMLNode, false); } + return true; } -void CXFA_Node::Script_NodeClass_SaveFilteredXML(CFXJSE_Arguments* pArguments) { - // TODO(weili): Check whether we need to implement this, pdfium:501. +CXFA_Node* CXFA_Node::GetFirstChildByName(const WideStringView& wsName) const { + return GetFirstChildByName(FX_HashCode_GetW(wsName, false)); } -void CXFA_Node::Script_NodeClass_SaveXML(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 0 || iLength > 1) { - ThrowParamCountMismatchException(L"saveXML"); - return; - } - bool bPrettyMode = false; - if (iLength == 1) { - if (pArguments->GetUTF8String(0) != "pretty") { - ThrowArgumentMismatchException(); - return; +CXFA_Node* CXFA_Node::GetFirstChildByName(uint32_t dwNameHash) const { + for (CXFA_Node* pNode = GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetNameHash() == dwNameHash) { + return pNode; } - bPrettyMode = true; } - CFX_ByteStringC bsXMLHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; - if (GetPacketID() == XFA_XDPPACKET_Form || - GetPacketID() == XFA_XDPPACKET_Datasets) { - CFDE_XMLNode* pElement = nullptr; - if (GetPacketID() == XFA_XDPPACKET_Datasets) { - pElement = GetXMLMappingNode(); - if (!pElement || pElement->GetType() != FDE_XMLNODE_Element) { - pArguments->GetReturnValue()->SetString(bsXMLHeader); - return; - } - XFA_DataExporter_DealWithDataGroupNode(this); - } - CFX_RetainPtr<IFX_MemoryStream> pMemoryStream = - IFX_MemoryStream::Create(true); + return nullptr; +} - // Note: ambiguious below without static_cast. - CFX_RetainPtr<IFGAS_Stream> pStream = IFGAS_Stream::CreateStream( - CFX_RetainPtr<IFX_SeekableWriteStream>(pMemoryStream), - FX_STREAMACCESS_Text | FX_STREAMACCESS_Write | FX_STREAMACCESS_Append); - - if (!pStream) { - pArguments->GetReturnValue()->SetString(bsXMLHeader); - return; +CXFA_Node* CXFA_Node::GetFirstChildByClassInternal(XFA_Element eType) const { + for (CXFA_Node* pNode = GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() == eType) { + return pNode; } - pStream->SetCodePage(FX_CODEPAGE_UTF8); - pStream->WriteData(bsXMLHeader.raw_str(), bsXMLHeader.GetLength()); - if (GetPacketID() == XFA_XDPPACKET_Form) - XFA_DataExporter_RegenerateFormFile(this, pStream, nullptr, true); - else - pElement->SaveXMLNode(pStream); - // TODO(weili): Check whether we need to save pretty print XML, pdfium:501. - // For now, just put it here to avoid unused variable warning. - (void)bPrettyMode; - pArguments->GetReturnValue()->SetString( - CFX_ByteStringC(pMemoryStream->GetBuffer(), pMemoryStream->GetSize())); - return; } - pArguments->GetReturnValue()->SetString(""); + return nullptr; } -void CXFA_Node::Script_NodeClass_SetAttribute(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 2) { - ThrowParamCountMismatchException(L"setAttribute"); - return; +CXFA_Node* CXFA_Node::GetNextSameNameSibling(uint32_t dwNameHash) const { + for (CXFA_Node* pNode = GetNextSibling(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetNameHash() == dwNameHash) { + return pNode; + } } - CFX_WideString wsAttributeValue = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringC()); - CFX_WideString wsAttribute = - CFX_WideString::FromUTF8(pArguments->GetUTF8String(1).AsStringC()); - SetAttribute(wsAttribute.AsStringC(), wsAttributeValue.AsStringC(), true); + return nullptr; } -void CXFA_Node::Script_NodeClass_SetElement(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1 && iLength != 2) { - ThrowParamCountMismatchException(L"setElement"); - return; - } - CXFA_Node* pNode = nullptr; - CFX_WideString wsName; - pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - if (iLength == 2) - wsName = CFX_WideString::FromUTF8(pArguments->GetUTF8String(1).AsStringC()); - // TODO(weili): check whether we need to implement this, pdfium:501. - // For now, just put the variables here to avoid unused variable warning. - (void)pNode; - (void)wsName; -} - -void CXFA_Node::Script_NodeClass_Ns(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - CFX_WideString wsNameSpace; - TryNamespace(wsNameSpace); - pValue->SetString(wsNameSpace.UTF8Encode().AsStringC()); +CXFA_Node* CXFA_Node::GetNextSameNameSiblingInternal( + const WideStringView& wsNodeName) const { + return GetNextSameNameSibling(FX_HashCode_GetW(wsNodeName, false)); } -void CXFA_Node::Script_NodeClass_Model(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; +CXFA_Node* CXFA_Node::GetNextSameClassSiblingInternal(XFA_Element eType) const { + for (CXFA_Node* pNode = GetNextSibling(); pNode; + pNode = pNode->GetNextSibling()) { + if (pNode->GetElementType() == eType) { + return pNode; + } } - pValue->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(GetModelNode())); + return nullptr; } -void CXFA_Node::Script_NodeClass_IsContainer(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; +int32_t CXFA_Node::GetNodeSameNameIndex() const { + CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext(); + if (!pScriptContext) { + return -1; } - pValue->SetBoolean(IsContainerNode()); + return pScriptContext->GetIndexByName(const_cast<CXFA_Node*>(this)); } -void CXFA_Node::Script_NodeClass_IsNull(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - if (GetElementType() == XFA_Element::Subform) { - pValue->SetBoolean(false); - return; +int32_t CXFA_Node::GetNodeSameClassIndex() const { + CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext(); + if (!pScriptContext) { + return -1; } - CFX_WideString strValue; - pValue->SetBoolean(!TryContent(strValue) || strValue.IsEmpty()); + return pScriptContext->GetIndexByClassName(const_cast<CXFA_Node*>(this)); } -void CXFA_Node::Script_NodeClass_OneOfChild(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; +CXFA_Node* CXFA_Node::GetInstanceMgrOfSubform() { + CXFA_Node* pInstanceMgr = nullptr; + if (m_ePacket == XFA_PacketType::Form) { + CXFA_Node* pParentNode = GetParent(); + if (!pParentNode || pParentNode->GetElementType() == XFA_Element::Area) { + return pInstanceMgr; + } + for (CXFA_Node* pNode = GetPrevSibling(); pNode; + pNode = pNode->GetPrevSibling()) { + XFA_Element eType = pNode->GetElementType(); + if ((eType == XFA_Element::Subform || eType == XFA_Element::SubformSet) && + pNode->m_dwNameHash != m_dwNameHash) { + break; + } + if (eType == XFA_Element::InstanceManager) { + WideString wsName = JSObject()->GetCData(XFA_Attribute::Name); + WideString wsInstName = + pNode->JSObject()->GetCData(XFA_Attribute::Name); + if (wsInstName.GetLength() > 0 && wsInstName[0] == '_' && + wsInstName.Right(wsInstName.GetLength() - 1) == wsName) { + pInstanceMgr = pNode; + } + break; + } + } } + return pInstanceMgr; +} - CXFA_NodeArray properts; - int32_t iSize = GetNodeList(properts, XFA_NODEFILTER_OneOfProperty); - if (iSize > 0) { - pValue->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(properts[0])); - } +CXFA_Occur* CXFA_Node::GetOccurIfExists() { + return GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); +} + +bool CXFA_Node::HasFlag(XFA_NodeFlag dwFlag) const { + if (m_uNodeFlags & dwFlag) + return true; + if (dwFlag == XFA_NodeFlag_HasRemovedChildren) + return m_pParent && m_pParent->HasFlag(dwFlag); + return false; } -void CXFA_Node::Script_ContainerClass_GetDelta(CFXJSE_Arguments* pArguments) {} +void CXFA_Node::SetFlag(uint32_t dwFlag, bool bNotify) { + if (dwFlag == XFA_NodeFlag_Initialized && bNotify && !IsInitialized()) { + CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); + if (pNotify) { + pNotify->OnNodeReady(this); + } + } + m_uNodeFlags |= dwFlag; +} -void CXFA_Node::Script_ContainerClass_GetDeltas(CFXJSE_Arguments* pArguments) { - CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(m_pDocument); - pArguments->GetReturnValue()->SetObject( - pFormNodes, m_pDocument->GetScriptContext()->GetJseNormalClass()); +void CXFA_Node::ClearFlag(uint32_t dwFlag) { + m_uNodeFlags &= ~dwFlag; } -void CXFA_Node::Script_ModelClass_ClearErrorList(CFXJSE_Arguments* pArguments) { + +void CXFA_Node::ReleaseBindingNodes() { + // Clear any binding nodes as we don't necessarily destruct in an order that + // makes sense. + for (auto& node : binding_nodes_) + node.Release(); + + for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->m_pNext) + pNode->ReleaseBindingNodes(); } -void CXFA_Node::Script_ModelClass_CreateNode(CFXJSE_Arguments* pArguments) { - Script_Template_CreateNode(pArguments); +bool CXFA_Node::IsAttributeInXML() { + return JSObject()->GetEnum(XFA_Attribute::Contains) == + XFA_AttributeEnum::MetaData; } -void CXFA_Node::Script_ModelClass_IsCompatibleNS(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1) { - ThrowParamCountMismatchException(L"isCompatibleNS"); +void CXFA_Node::OnRemoved(bool bNotify) { + if (!bNotify) return; + + CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); + if (pNotify) + pNotify->OnChildRemoved(); +} + +void CXFA_Node::UpdateNameHash() { + WideString wsName = JSObject()->GetCData(XFA_Attribute::Name); + m_dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false); +} + +CFX_XMLNode* CXFA_Node::CreateXMLMappingNode() { + if (!m_pXMLNode) { + WideString wsTag(JSObject()->GetCData(XFA_Attribute::Name)); + m_pXMLNode = new CFX_XMLElement(wsTag); + SetFlag(XFA_NodeFlag_OwnXMLNode, false); } - CFX_WideString wsNameSpace; - if (iLength >= 1) { - CFX_ByteString bsNameSpace = pArguments->GetUTF8String(0); - wsNameSpace = CFX_WideString::FromUTF8(bsNameSpace.AsStringC()); - } - CFX_WideString wsNodeNameSpace; - TryNamespace(wsNodeNameSpace); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetBoolean(wsNodeNameSpace == wsNameSpace); -} - -void CXFA_Node::Script_ModelClass_Context(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_ModelClass_AliasNode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Attribute_Integer(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - SetInteger(eAttribute, pValue->ToInteger(), true); - } else { - pValue->SetInteger(GetInteger(eAttribute)); + return m_pXMLNode; +} + +bool CXFA_Node::IsNeedSavingXMLNode() { + return m_pXMLNode && (GetPacketType() == XFA_PacketType::Datasets || + GetElementType() == XFA_Element::Xfa); +} + +CXFA_Node* CXFA_Node::GetItemIfExists(int32_t iIndex) { + int32_t iCount = 0; + uint32_t dwNameHash = 0; + for (CXFA_Node* pNode = GetNextSibling(); pNode; + pNode = pNode->GetNextSibling()) { + XFA_Element eCurType = pNode->GetElementType(); + if (eCurType == XFA_Element::InstanceManager) + break; + if ((eCurType != XFA_Element::Subform) && + (eCurType != XFA_Element::SubformSet)) { + continue; + } + if (iCount == 0) { + WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); + WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name); + if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' || + wsInstName.Right(wsInstName.GetLength() - 1) != wsName) { + return nullptr; + } + dwNameHash = pNode->GetNameHash(); + } + if (dwNameHash != pNode->GetNameHash()) + break; + + iCount++; + if (iCount > iIndex) + return pNode; } + return nullptr; } -void CXFA_Node::Script_Attribute_IntegerRead(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; +int32_t CXFA_Node::GetCount() { + int32_t iCount = 0; + uint32_t dwNameHash = 0; + for (CXFA_Node* pNode = GetNextSibling(); pNode; + pNode = pNode->GetNextSibling()) { + XFA_Element eCurType = pNode->GetElementType(); + if (eCurType == XFA_Element::InstanceManager) + break; + if ((eCurType != XFA_Element::Subform) && + (eCurType != XFA_Element::SubformSet)) { + continue; + } + if (iCount == 0) { + WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name); + WideString wsInstName = JSObject()->GetCData(XFA_Attribute::Name); + if (wsInstName.GetLength() < 1 || wsInstName[0] != '_' || + wsInstName.Right(wsInstName.GetLength() - 1) != wsName) { + return iCount; + } + dwNameHash = pNode->GetNameHash(); + } + if (dwNameHash != pNode->GetNameHash()) + break; + + iCount++; } - pValue->SetInteger(GetInteger(eAttribute)); + return iCount; } -void CXFA_Node::Script_Attribute_BOOL(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - SetBoolean(eAttribute, pValue->ToBoolean(), true); +void CXFA_Node::InsertItem(CXFA_Node* pNewInstance, + int32_t iPos, + int32_t iCount, + bool bMoveDataBindingNodes) { + if (iCount < 0) + iCount = GetCount(); + if (iPos < 0) + iPos = iCount; + if (iPos == iCount) { + CXFA_Node* item = GetItemIfExists(iCount - 1); + if (!item) + return; + + CXFA_Node* pNextSibling = + iCount > 0 ? item->GetNextSibling() : GetNextSibling(); + GetParent()->InsertChild(pNewInstance, pNextSibling); + if (bMoveDataBindingNodes) { + std::set<CXFA_Node*> sNew; + std::set<CXFA_Node*> sAfter; + CXFA_NodeIteratorTemplate<CXFA_Node, + CXFA_TraverseStrategy_XFAContainerNode> + sIteratorNew(pNewInstance); + for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; + pNode = sIteratorNew.MoveToNext()) { + CXFA_Node* pDataNode = pNode->GetBindData(); + if (!pDataNode) + continue; + + sNew.insert(pDataNode); + } + CXFA_NodeIteratorTemplate<CXFA_Node, + CXFA_TraverseStrategy_XFAContainerNode> + sIteratorAfter(pNextSibling); + for (CXFA_Node* pNode = sIteratorAfter.GetCurrent(); pNode; + pNode = sIteratorAfter.MoveToNext()) { + CXFA_Node* pDataNode = pNode->GetBindData(); + if (!pDataNode) + continue; + + sAfter.insert(pDataNode); + } + ReorderDataNodes(sNew, sAfter, false); + } } else { - pValue->SetString(GetBoolean(eAttribute) ? "1" : "0"); + CXFA_Node* pBeforeInstance = GetItemIfExists(iPos); + if (!pBeforeInstance) { + // TODO(dsinclair): What should happen here? + return; + } + + GetParent()->InsertChild(pNewInstance, pBeforeInstance); + if (bMoveDataBindingNodes) { + std::set<CXFA_Node*> sNew; + std::set<CXFA_Node*> sBefore; + CXFA_NodeIteratorTemplate<CXFA_Node, + CXFA_TraverseStrategy_XFAContainerNode> + sIteratorNew(pNewInstance); + for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode; + pNode = sIteratorNew.MoveToNext()) { + CXFA_Node* pDataNode = pNode->GetBindData(); + if (!pDataNode) + continue; + + sNew.insert(pDataNode); + } + CXFA_NodeIteratorTemplate<CXFA_Node, + CXFA_TraverseStrategy_XFAContainerNode> + sIteratorBefore(pBeforeInstance); + for (CXFA_Node* pNode = sIteratorBefore.GetCurrent(); pNode; + pNode = sIteratorBefore.MoveToNext()) { + CXFA_Node* pDataNode = pNode->GetBindData(); + if (!pDataNode) + continue; + + sBefore.insert(pDataNode); + } + ReorderDataNodes(sNew, sBefore, true); + } } } -void CXFA_Node::Script_Attribute_BOOLRead(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); +void CXFA_Node::RemoveItem(CXFA_Node* pRemoveInstance, + bool bRemoveDataBinding) { + GetParent()->RemoveChild(pRemoveInstance, true); + if (!bRemoveDataBinding) return; + + CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> + sIterator(pRemoveInstance); + for (CXFA_Node* pFormNode = sIterator.GetCurrent(); pFormNode; + pFormNode = sIterator.MoveToNext()) { + CXFA_Node* pDataNode = pFormNode->GetBindData(); + if (!pDataNode) + continue; + + if (pDataNode->RemoveBindItem(pFormNode) == 0) { + if (CXFA_Node* pDataParent = pDataNode->GetParent()) { + pDataParent->RemoveChild(pDataNode, true); + } + } + pFormNode->SetBindingNode(nullptr); + } +} + +CXFA_Node* CXFA_Node::CreateInstanceIfPossible(bool bDataMerge) { + CXFA_Document* pDocument = GetDocument(); + CXFA_Node* pTemplateNode = GetTemplateNodeIfExists(); + if (!pTemplateNode) + return nullptr; + + CXFA_Node* pFormParent = GetParent(); + CXFA_Node* pDataScope = nullptr; + for (CXFA_Node* pRootBoundNode = pFormParent; + pRootBoundNode && pRootBoundNode->IsContainerNode(); + pRootBoundNode = pRootBoundNode->GetParent()) { + pDataScope = pRootBoundNode->GetBindData(); + if (pDataScope) + break; } - pValue->SetString(GetBoolean(eAttribute) ? "1" : "0"); + if (!pDataScope) { + pDataScope = ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)); + ASSERT(pDataScope); + } + + CXFA_Node* pInstance = pDocument->DataMerge_CopyContainer( + pTemplateNode, pFormParent, pDataScope, true, bDataMerge, true); + if (pInstance) { + pDocument->DataMerge_UpdateBindingRelations(pInstance); + pFormParent->RemoveChild(pInstance, true); + } + return pInstance; +} + +Optional<bool> CXFA_Node::GetDefaultBoolean(XFA_Attribute attr) const { + Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Boolean); + if (!value) + return {}; + return {!!*value}; +} + +Optional<int32_t> CXFA_Node::GetDefaultInteger(XFA_Attribute attr) const { + Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Integer); + if (!value) + return {}; + return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(*value))}; +} + +Optional<CXFA_Measurement> CXFA_Node::GetDefaultMeasurement( + XFA_Attribute attr) const { + Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Measure); + if (!value) + return {}; + + WideString str = WideString(static_cast<const wchar_t*>(*value)); + return {CXFA_Measurement(str.AsStringView())}; +} + +Optional<WideString> CXFA_Node::GetDefaultCData(XFA_Attribute attr) const { + Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::CData); + if (!value) + return {}; + + return {WideString(static_cast<const wchar_t*>(*value))}; +} + +Optional<XFA_AttributeEnum> CXFA_Node::GetDefaultEnum( + XFA_Attribute attr) const { + Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Enum); + if (!value) + return {}; + return {static_cast<XFA_AttributeEnum>(reinterpret_cast<uintptr_t>(*value))}; +} + +Optional<void*> CXFA_Node::GetDefaultValue(XFA_Attribute attr, + XFA_AttributeType eType) const { + const AttributeData* data = GetAttributeData(attr); + if (!data) + return {}; + if (data->type == eType) + return {data->default_value}; + return {}; } -void CXFA_Node::Script_Attribute_SendAttributeChangeMessage( - XFA_ATTRIBUTE eAttribute, - bool bScriptModify) { - CXFA_LayoutProcessor* pLayoutPro = m_pDocument->GetLayoutProcessor(); +void CXFA_Node::SendAttributeChangeMessage(XFA_Attribute eAttribute, + bool bScriptModify) { + CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor(); if (!pLayoutPro) return; - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); + CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); if (!pNotify) return; - uint32_t dwPacket = GetPacketID(); - if (!(dwPacket & XFA_XDPPACKET_Form)) { + if (GetPacketType() != XFA_PacketType::Form) { pNotify->OnValueChanged(this, eAttribute, this, this); return; } @@ -1662,50 +1392,51 @@ void CXFA_Node::Script_Attribute_SendAttributeChangeMessage( switch (GetElementType()) { case XFA_Element::Caption: bNeedFindContainer = true; - pNotify->OnValueChanged(this, eAttribute, this, - GetNodeItem(XFA_NODEITEM_Parent)); + pNotify->OnValueChanged(this, eAttribute, this, GetParent()); break; case XFA_Element::Font: case XFA_Element::Para: { bNeedFindContainer = true; - CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pParentNode = GetParent(); if (pParentNode->GetElementType() == XFA_Element::Caption) { pNotify->OnValueChanged(this, eAttribute, pParentNode, - pParentNode->GetNodeItem(XFA_NODEITEM_Parent)); + pParentNode->GetParent()); } else { pNotify->OnValueChanged(this, eAttribute, this, pParentNode); } - } break; + break; + } case XFA_Element::Margin: { bNeedFindContainer = true; - CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pParentNode = GetParent(); XFA_Element eParentType = pParentNode->GetElementType(); if (pParentNode->IsContainerNode()) { pNotify->OnValueChanged(this, eAttribute, this, pParentNode); } else if (eParentType == XFA_Element::Caption) { pNotify->OnValueChanged(this, eAttribute, pParentNode, - pParentNode->GetNodeItem(XFA_NODEITEM_Parent)); + pParentNode->GetParent()); } else { - CXFA_Node* pNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pNode = pParentNode->GetParent(); if (pNode && pNode->GetElementType() == XFA_Element::Ui) { - pNotify->OnValueChanged(this, eAttribute, pNode, - pNode->GetNodeItem(XFA_NODEITEM_Parent)); + pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent()); } } - } break; + break; + } case XFA_Element::Comb: { - CXFA_Node* pEditNode = GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pEditNode = GetParent(); XFA_Element eUIType = pEditNode->GetElementType(); if (pEditNode && (eUIType == XFA_Element::DateTimeEdit || eUIType == XFA_Element::NumericEdit || eUIType == XFA_Element::TextEdit)) { - CXFA_Node* pUINode = pEditNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pUINode = pEditNode->GetParent(); if (pUINode) { pNotify->OnValueChanged(this, eAttribute, pUINode, - pUINode->GetNodeItem(XFA_NODEITEM_Parent)); + pUINode->GetParent()); } } - } break; + break; + } case XFA_Element::Button: case XFA_Element::Barcode: case XFA_Element::ChoiceList: @@ -1713,20 +1444,22 @@ void CXFA_Node::Script_Attribute_SendAttributeChangeMessage( case XFA_Element::NumericEdit: case XFA_Element::PasswordEdit: case XFA_Element::TextEdit: { - CXFA_Node* pUINode = GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pUINode = GetParent(); if (pUINode) { pNotify->OnValueChanged(this, eAttribute, pUINode, - pUINode->GetNodeItem(XFA_NODEITEM_Parent)); + pUINode->GetParent()); } - } break; + break; + } case XFA_Element::CheckButton: { bNeedFindContainer = true; - CXFA_Node* pUINode = GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pUINode = GetParent(); if (pUINode) { pNotify->OnValueChanged(this, eAttribute, pUINode, - pUINode->GetNodeItem(XFA_NODEITEM_Parent)); + pUINode->GetParent()); } - } break; + break; + } case XFA_Element::Keep: case XFA_Element::Bookend: case XFA_Element::Break: @@ -1747,3387 +1480,735 @@ void CXFA_Node::Script_Attribute_SendAttributeChangeMessage( case XFA_Element::Sharptext: case XFA_Element::Sharpxml: case XFA_Element::SharpxHTML: { - CXFA_Node* pTextNode = GetNodeItem(XFA_NODEITEM_Parent); - if (!pTextNode) { + CXFA_Node* pTextNode = GetParent(); + if (!pTextNode) return; - } - CXFA_Node* pValueNode = pTextNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!pValueNode) { + + CXFA_Node* pValueNode = pTextNode->GetParent(); + if (!pValueNode) return; - } + XFA_Element eType = pValueNode->GetElementType(); if (eType == XFA_Element::Value) { bNeedFindContainer = true; - CXFA_Node* pNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pNode = pValueNode->GetParent(); if (pNode && pNode->IsContainerNode()) { - if (bScriptModify) { + if (bScriptModify) pValueNode = pNode; - } + pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); } else { - pNotify->OnValueChanged(this, eAttribute, pNode, - pNode->GetNodeItem(XFA_NODEITEM_Parent)); + pNotify->OnValueChanged(this, eAttribute, pNode, pNode->GetParent()); } } else { if (eType == XFA_Element::Items) { - CXFA_Node* pNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pNode = pValueNode->GetParent(); if (pNode && pNode->IsContainerNode()) { - pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); - } - } - } - } break; - default: - break; - } - if (bNeedFindContainer) { - CXFA_Node* pParent = this; - while (pParent) { - if (pParent->IsContainerNode()) - break; - - pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent); - } - if (pParent) { - pLayoutPro->AddChangedContainer(pParent); - } - } -} - -void CXFA_Node::Script_Attribute_String(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - CFX_WideString wsValue = pValue->ToWideString(); - SetAttribute(eAttribute, wsValue.AsStringC(), true); - if (eAttribute == XFA_ATTRIBUTE_Use && - GetElementType() == XFA_Element::Desc) { - CXFA_Node* pTemplateNode = - ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Template)); - CXFA_Node* pProtoRoot = - pTemplateNode->GetFirstChildByClass(XFA_Element::Subform) - ->GetFirstChildByClass(XFA_Element::Proto); - - CFX_WideString wsID; - CFX_WideString wsSOM; - if (!wsValue.IsEmpty()) { - if (wsValue[0] == '#') { - wsID = CFX_WideString(wsValue.c_str() + 1, wsValue.GetLength() - 1); - } else { - wsSOM = wsValue; - } - } - CXFA_Node* pProtoNode = nullptr; - if (!wsSOM.IsEmpty()) { - uint32_t dwFlag = XFA_RESOLVENODE_Children | - XFA_RESOLVENODE_Attributes | - XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Siblings; - XFA_RESOLVENODE_RS resoveNodeRS; - int32_t iRet = m_pDocument->GetScriptContext()->ResolveObjects( - pProtoRoot, wsSOM.AsStringC(), resoveNodeRS, dwFlag); - if (iRet > 0 && resoveNodeRS.nodes[0]->IsNode()) { - pProtoNode = resoveNodeRS.nodes[0]->AsNode(); - } - } else if (!wsID.IsEmpty()) { - pProtoNode = m_pDocument->GetNodeByID(pProtoRoot, wsID.AsStringC()); - } - if (pProtoNode) { - CXFA_Node* pHeadChild = GetNodeItem(XFA_NODEITEM_FirstChild); - while (pHeadChild) { - CXFA_Node* pSibling = - pHeadChild->GetNodeItem(XFA_NODEITEM_NextSibling); - RemoveChild(pHeadChild); - pHeadChild = pSibling; - } - CXFA_Node* pProtoForm = pProtoNode->CloneTemplateToForm(true); - pHeadChild = pProtoForm->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pHeadChild) { - CXFA_Node* pSibling = - pHeadChild->GetNodeItem(XFA_NODEITEM_NextSibling); - pProtoForm->RemoveChild(pHeadChild); - InsertChild(pHeadChild); - pHeadChild = pSibling; - } - m_pDocument->RemovePurgeNode(pProtoForm); - delete pProtoForm; - } - } - } else { - CFX_WideString wsValue; - GetAttribute(eAttribute, wsValue); - pValue->SetString(wsValue.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Attribute_StringRead(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - CFX_WideString wsValue; - GetAttribute(eAttribute, wsValue); - pValue->SetString(wsValue.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_WsdlConnection_Execute(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 0 && argc != 1) { - ThrowParamCountMismatchException(L"execute"); - return; - } - pArguments->GetReturnValue()->SetBoolean(false); -} - -void CXFA_Node::Script_Delta_Restore(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"restore"); -} - -void CXFA_Node::Script_Delta_CurrentValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Delta_SavedValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Delta_Target(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Som_Message(CFXJSE_Value* pValue, - bool bSetting, - XFA_SOM_MESSAGETYPE iMessageType) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - bool bNew = false; - CXFA_Validate validate = pWidgetData->GetValidate(); - if (!validate) { - validate = pWidgetData->GetValidate(true); - bNew = true; - } - if (bSetting) { - switch (iMessageType) { - case XFA_SOM_ValidationMessage: - validate.SetScriptMessageText(pValue->ToWideString()); - break; - case XFA_SOM_FormatMessage: - validate.SetFormatMessageText(pValue->ToWideString()); - break; - case XFA_SOM_MandatoryMessage: - validate.SetNullMessageText(pValue->ToWideString()); - break; - default: - break; - } - if (!bNew) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - pNotify->AddCalcValidate(this); - } - } else { - CFX_WideString wsMessage; - switch (iMessageType) { - case XFA_SOM_ValidationMessage: - validate.GetScriptMessageText(wsMessage); - break; - case XFA_SOM_FormatMessage: - validate.GetFormatMessageText(wsMessage); - break; - case XFA_SOM_MandatoryMessage: - validate.GetNullMessageText(wsMessage); - break; - default: - break; - } - pValue->SetString(wsMessage.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_ValidationMessage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Script_Som_Message(pValue, bSetting, XFA_SOM_ValidationMessage); -} - -void CXFA_Node::Script_Field_Length(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pValue->SetInteger(0); - return; - } - pValue->SetInteger(pWidgetData->CountChoiceListItems(true)); -} - -void CXFA_Node::Script_Som_DefaultValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - XFA_Element eType = GetElementType(); - if (eType == XFA_Element::Field) { - Script_Field_DefaultValue(pValue, bSetting, eAttribute); - return; - } - if (eType == XFA_Element::Draw) { - Script_Draw_DefaultValue(pValue, bSetting, eAttribute); - return; - } - if (eType == XFA_Element::Boolean) { - Script_Boolean_Value(pValue, bSetting, eAttribute); - return; - } - if (bSetting) { - CFX_WideString wsNewValue; - if (!(pValue && (pValue->IsNull() || pValue->IsUndefined()))) - wsNewValue = pValue->ToWideString(); - - CFX_WideString wsFormatValue(wsNewValue); - CXFA_WidgetData* pContainerWidgetData = nullptr; - if (GetPacketID() == XFA_XDPPACKET_Datasets) { - CXFA_NodeArray formNodes; - GetBindItems(formNodes); - CFX_WideString wsPicture; - for (int32_t i = 0; i < formNodes.GetSize(); i++) { - CXFA_Node* pFormNode = formNodes.GetAt(i); - if (!pFormNode || pFormNode->HasRemovedChildren()) { - continue; - } - pContainerWidgetData = pFormNode->GetContainerWidgetData(); - if (pContainerWidgetData) { - pContainerWidgetData->GetPictureContent(wsPicture, - XFA_VALUEPICTURE_DataBind); - } - if (!wsPicture.IsEmpty()) { - break; - } - pContainerWidgetData = nullptr; - } - } else if (GetPacketID() == XFA_XDPPACKET_Form) { - pContainerWidgetData = GetContainerWidgetData(); - } - if (pContainerWidgetData) { - pContainerWidgetData->GetFormatDataValue(wsNewValue, wsFormatValue); - } - SetScriptContent(wsNewValue, wsFormatValue, true, true); - } else { - CFX_WideString content = GetScriptContent(true); - if (content.IsEmpty() && eType != XFA_Element::Text && - eType != XFA_Element::SubmitUrl) { - pValue->SetNull(); - } else if (eType == XFA_Element::Integer) { - pValue->SetInteger(FXSYS_wtoi(content.c_str())); - } else if (eType == XFA_Element::Float || eType == XFA_Element::Decimal) { - CFX_Decimal decimal(content.AsStringC()); - pValue->SetFloat((FX_FLOAT)(double)decimal); - } else { - pValue->SetString(content.UTF8Encode().AsStringC()); - } - } -} - -void CXFA_Node::Script_Som_DefaultValue_Read(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - CFX_WideString content = GetScriptContent(true); - if (content.IsEmpty()) { - pValue->SetNull(); - return; - } - pValue->SetString(content.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_Boolean_Value(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - CFX_ByteString newValue; - if (!(pValue && (pValue->IsNull() || pValue->IsUndefined()))) - newValue = pValue->ToString(); - - int32_t iValue = FXSYS_atoi(newValue.c_str()); - CFX_WideString wsNewValue(iValue == 0 ? L"0" : L"1"); - CFX_WideString wsFormatValue(wsNewValue); - CXFA_WidgetData* pContainerWidgetData = GetContainerWidgetData(); - if (pContainerWidgetData) { - pContainerWidgetData->GetFormatDataValue(wsNewValue, wsFormatValue); - } - SetScriptContent(wsNewValue, wsFormatValue, true, true); - } else { - CFX_WideString wsValue = GetScriptContent(true); - pValue->SetBoolean(wsValue == L"1"); - } -} - -void CXFA_Node::Script_Som_BorderColor(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CXFA_Border border = pWidgetData->GetBorder(true); - int32_t iSize = border.CountEdges(); - if (bSetting) { - int32_t r = 0; - int32_t g = 0; - int32_t b = 0; - StrToRGB(pValue->ToWideString(), r, g, b); - FX_ARGB rgb = ArgbEncode(100, r, g, b); - for (int32_t i = 0; i < iSize; ++i) { - CXFA_Edge edge = border.GetEdge(i); - edge.SetColor(rgb); - } - } else { - CXFA_Edge edge = border.GetEdge(0); - FX_ARGB color = edge.GetColor(); - int32_t a, r, g, b; - ArgbDecode(color, a, r, g, b); - CFX_WideString strColor; - strColor.Format(L"%d,%d,%d", r, g, b); - pValue->SetString(strColor.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_BorderWidth(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CXFA_Border border = pWidgetData->GetBorder(true); - int32_t iSize = border.CountEdges(); - CFX_WideString wsThickness; - if (bSetting) { - wsThickness = pValue->ToWideString(); - for (int32_t i = 0; i < iSize; ++i) { - CXFA_Edge edge = border.GetEdge(i); - CXFA_Measurement thickness(wsThickness.AsStringC()); - edge.SetMSThickness(thickness); - } - } else { - CXFA_Edge edge = border.GetEdge(0); - CXFA_Measurement thickness = edge.GetMSThickness(); - thickness.ToString(wsThickness); - pValue->SetString(wsThickness.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_FillColor(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CXFA_Border border = pWidgetData->GetBorder(true); - CXFA_Fill borderfill = border.GetFill(true); - CXFA_Node* pNode = borderfill.GetNode(); - if (!pNode) { - return; - } - if (bSetting) { - int32_t r; - int32_t g; - int32_t b; - StrToRGB(pValue->ToWideString(), r, g, b); - FX_ARGB color = ArgbEncode(0xff, r, g, b); - borderfill.SetColor(color); - } else { - FX_ARGB color = borderfill.GetColor(); - int32_t a; - int32_t r; - int32_t g; - int32_t b; - ArgbDecode(color, a, r, g, b); - CFX_WideString wsColor; - wsColor.Format(L"%d,%d,%d", r, g, b); - pValue->SetString(wsColor.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_DataNode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - CXFA_Node* pDataNode = GetBindData(); - if (!pDataNode) { - pValue->SetNull(); - return; - } - - pValue->Assign(m_pDocument->GetScriptContext()->GetJSValueFromMap(pDataNode)); -} - -void CXFA_Node::Script_Draw_DefaultValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - if (pValue && pValue->IsString()) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - ASSERT(pWidgetData); - XFA_Element uiType = pWidgetData->GetUIType(); - if (uiType == XFA_Element::Text) { - CFX_WideString wsNewValue = pValue->ToWideString(); - CFX_WideString wsFormatValue(wsNewValue); - SetScriptContent(wsNewValue, wsFormatValue, true, true); - } - } - } else { - CFX_WideString content = GetScriptContent(true); - if (content.IsEmpty()) - pValue->SetNull(); - else - pValue->SetString(content.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Field_DefaultValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - if (bSetting) { - if (pValue && pValue->IsNull()) { - pWidgetData->m_bPreNull = pWidgetData->m_bIsNull; - pWidgetData->m_bIsNull = true; - } else { - pWidgetData->m_bPreNull = pWidgetData->m_bIsNull; - pWidgetData->m_bIsNull = false; - } - CFX_WideString wsNewText; - if (!(pValue && (pValue->IsNull() || pValue->IsUndefined()))) - wsNewText = pValue->ToWideString(); - - CXFA_Node* pUIChild = pWidgetData->GetUIChild(); - if (pUIChild->GetElementType() == XFA_Element::NumericEdit) { - int32_t iLeadDigits = 0; - int32_t iFracDigits = 0; - pWidgetData->GetLeadDigits(iLeadDigits); - pWidgetData->GetFracDigits(iFracDigits); - wsNewText = - pWidgetData->NumericLimit(wsNewText, iLeadDigits, iFracDigits); - } - CXFA_WidgetData* pContainerWidgetData = GetContainerWidgetData(); - CFX_WideString wsFormatText(wsNewText); - if (pContainerWidgetData) { - pContainerWidgetData->GetFormatDataValue(wsNewText, wsFormatText); - } - SetScriptContent(wsNewText, wsFormatText, true, true); - } else { - CFX_WideString content = GetScriptContent(true); - if (content.IsEmpty()) { - pValue->SetNull(); - } else { - CXFA_Node* pUIChild = pWidgetData->GetUIChild(); - CXFA_Value defVal = pWidgetData->GetFormValue(); - CXFA_Node* pNode = defVal.GetNode()->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pNode && pNode->GetElementType() == XFA_Element::Decimal) { - if (pUIChild->GetElementType() == XFA_Element::NumericEdit && - (pNode->GetInteger(XFA_ATTRIBUTE_FracDigits) == -1)) { - pValue->SetString(content.UTF8Encode().AsStringC()); - } else { - CFX_Decimal decimal(content.AsStringC()); - pValue->SetFloat((FX_FLOAT)(double)decimal); - } - } else if (pNode && pNode->GetElementType() == XFA_Element::Integer) { - pValue->SetInteger(FXSYS_wtoi(content.c_str())); - } else if (pNode && pNode->GetElementType() == XFA_Element::Boolean) { - pValue->SetBoolean(FXSYS_wtoi(content.c_str()) == 0 ? false : true); - } else if (pNode && pNode->GetElementType() == XFA_Element::Float) { - CFX_Decimal decimal(content.AsStringC()); - pValue->SetFloat((FX_FLOAT)(double)decimal); - } else { - pValue->SetString(content.UTF8Encode().AsStringC()); - } - } - } -} - -void CXFA_Node::Script_Field_EditValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - if (bSetting) { - pWidgetData->SetValue(pValue->ToWideString(), XFA_VALUEPICTURE_Edit); - } else { - CFX_WideString wsValue; - pWidgetData->GetValue(wsValue, XFA_VALUEPICTURE_Edit); - pValue->SetString(wsValue.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_FontColor(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CXFA_Font font = pWidgetData->GetFont(true); - CXFA_Node* pNode = font.GetNode(); - if (!pNode) { - return; - } - if (bSetting) { - int32_t r; - int32_t g; - int32_t b; - StrToRGB(pValue->ToWideString(), r, g, b); - FX_ARGB color = ArgbEncode(0xff, r, g, b); - font.SetColor(color); - } else { - FX_ARGB color = font.GetColor(); - int32_t a; - int32_t r; - int32_t g; - int32_t b; - ArgbDecode(color, a, r, g, b); - CFX_WideString wsColor; - wsColor.Format(L"%d,%d,%d", r, g, b); - pValue->SetString(wsColor.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Field_FormatMessage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Script_Som_Message(pValue, bSetting, XFA_SOM_FormatMessage); -} - -void CXFA_Node::Script_Field_FormattedValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - if (bSetting) { - pWidgetData->SetValue(pValue->ToWideString(), XFA_VALUEPICTURE_Display); - } else { - CFX_WideString wsValue; - pWidgetData->GetValue(wsValue, XFA_VALUEPICTURE_Display); - pValue->SetString(wsValue.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_Mandatory(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CXFA_Validate validate = pWidgetData->GetValidate(true); - if (bSetting) { - validate.SetNullTest(pValue->ToWideString()); - } else { - int32_t iValue = validate.GetNullTest(); - const XFA_ATTRIBUTEENUMINFO* pInfo = - GetAttributeEnumByID((XFA_ATTRIBUTEENUM)iValue); - CFX_WideString wsValue; - if (pInfo) - wsValue = pInfo->pName; - pValue->SetString(wsValue.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Som_MandatoryMessage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - Script_Som_Message(pValue, bSetting, XFA_SOM_MandatoryMessage); -} - -void CXFA_Node::Script_Field_ParentSubform(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - pValue->SetNull(); -} - -void CXFA_Node::Script_Field_SelectedIndex(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - if (bSetting) { - int32_t iIndex = pValue->ToInteger(); - if (iIndex == -1) { - pWidgetData->ClearAllSelections(); - return; - } - pWidgetData->SetItemState(iIndex, true, true, true, true); - } else { - pValue->SetInteger(pWidgetData->GetSelectedItem()); - } -} - -void CXFA_Node::Script_Field_ClearItems(CFXJSE_Arguments* pArguments) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - pWidgetData->DeleteItem(-1, true); -} - -void CXFA_Node::Script_Field_ExecEvent(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"execEvent"); - return; - } - - CFX_ByteString eventString = pArguments->GetUTF8String(0); - int32_t iRet = execSingleEventByName( - CFX_WideString::FromUTF8(eventString.AsStringC()).AsStringC(), - XFA_Element::Field); - if (eventString != "validate") - return; - - pArguments->GetReturnValue()->SetBoolean( - (iRet == XFA_EVENTERROR_Error) ? false : true); -} - -void CXFA_Node::Script_Field_ExecInitialize(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execInitialize"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Initialize, false, false); -} - -void CXFA_Node::Script_Field_DeleteItem(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"deleteItem"); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - int32_t iIndex = pArguments->GetInt32(0); - bool bValue = pWidgetData->DeleteItem(iIndex, true, true); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetBoolean(bValue); -} - -void CXFA_Node::Script_Field_GetSaveItem(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"getSaveItem"); - return; - } - int32_t iIndex = pArguments->GetInt32(0); - if (iIndex < 0) { - pArguments->GetReturnValue()->SetNull(); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetNull(); - return; - } - CFX_WideString wsValue; - if (!pWidgetData->GetChoiceListItem(wsValue, iIndex, true)) { - pArguments->GetReturnValue()->SetNull(); - return; - } - pArguments->GetReturnValue()->SetString(wsValue.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_Field_BoundItem(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"boundItem"); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CFX_ByteString bsValue = pArguments->GetUTF8String(0); - CFX_WideString wsValue = CFX_WideString::FromUTF8(bsValue.AsStringC()); - CFX_WideString wsBoundValue; - pWidgetData->GetItemValue(wsValue.AsStringC(), wsBoundValue); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetString(wsBoundValue.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_Field_GetItemState(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"getItemState"); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - int32_t iIndex = pArguments->GetInt32(0); - bool bValue = pWidgetData->GetItemState(iIndex); - CFXJSE_Value* pValue = pArguments->GetReturnValue(); - if (pValue) - pValue->SetBoolean(bValue); -} - -void CXFA_Node::Script_Field_ExecCalculate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execCalculate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Calculate, false, false); -} - -void CXFA_Node::Script_Field_SetItems(CFXJSE_Arguments* pArguments) {} - -void CXFA_Node::Script_Field_GetDisplayItem(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 1) { - ThrowParamCountMismatchException(L"getDisplayItem"); - return; - } - int32_t iIndex = pArguments->GetInt32(0); - if (iIndex < 0) { - pArguments->GetReturnValue()->SetNull(); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetNull(); - return; - } - CFX_WideString wsValue; - if (!pWidgetData->GetChoiceListItem(wsValue, iIndex, false)) { - pArguments->GetReturnValue()->SetNull(); - return; - } - pArguments->GetReturnValue()->SetString(wsValue.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_Field_SetItemState(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength != 2) { - ThrowParamCountMismatchException(L"setItemState"); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) - return; - - int32_t iIndex = pArguments->GetInt32(0); - if (pArguments->GetInt32(1) != 0) { - pWidgetData->SetItemState(iIndex, true, true, true, true); - } else { - if (pWidgetData->GetItemState(iIndex)) - pWidgetData->SetItemState(iIndex, false, true, true, true); - } -} - -void CXFA_Node::Script_Field_AddItem(CFXJSE_Arguments* pArguments) { - int32_t iLength = pArguments->GetLength(); - if (iLength < 1 || iLength > 2) { - ThrowParamCountMismatchException(L"addItem"); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - CFX_WideString wsLabel; - CFX_WideString wsValue; - if (iLength >= 1) { - CFX_ByteString bsLabel = pArguments->GetUTF8String(0); - wsLabel = CFX_WideString::FromUTF8(bsLabel.AsStringC()); - } - if (iLength >= 2) { - CFX_ByteString bsValue = pArguments->GetUTF8String(1); - wsValue = CFX_WideString::FromUTF8(bsValue.AsStringC()); - } - pWidgetData->InsertItem(wsLabel, wsValue, -1, true); -} - -void CXFA_Node::Script_Field_ExecValidate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execValidate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - - int32_t iRet = - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Validate, false, false); - pArguments->GetReturnValue()->SetBoolean( - (iRet == XFA_EVENTERROR_Error) ? false : true); -} - -void CXFA_Node::Script_ExclGroup_ErrorText(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) - ThrowInvalidPropertyException(); -} - -void CXFA_Node::Script_ExclGroup_DefaultAndRawValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - return; - } - if (bSetting) { - pWidgetData->SetSelectedMemberByValue(pValue->ToWideString().AsStringC(), - true, true, true); - } else { - CFX_WideString wsValue = GetScriptContent(true); - XFA_VERSION curVersion = GetDocument()->GetCurVersionMode(); - if (wsValue.IsEmpty() && curVersion >= XFA_VERSION_300) { - pValue->SetNull(); - } else { - pValue->SetString(wsValue.UTF8Encode().AsStringC()); - } - } -} - -void CXFA_Node::Script_ExclGroup_Transient(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_ExclGroup_ExecEvent(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"execEvent"); - return; - } - - CFX_ByteString eventString = pArguments->GetUTF8String(0); - execSingleEventByName( - CFX_WideString::FromUTF8(eventString.AsStringC()).AsStringC(), - XFA_Element::ExclGroup); -} - -void CXFA_Node::Script_ExclGroup_SelectedMember(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc < 0 || argc > 1) { - ThrowParamCountMismatchException(L"selectedMember"); - return; - } - - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetNull(); - return; - } - - CXFA_Node* pReturnNode = nullptr; - if (argc == 0) { - pReturnNode = pWidgetData->GetSelectedMember(); - } else { - CFX_ByteString szName; - szName = pArguments->GetUTF8String(0); - pReturnNode = pWidgetData->SetSelectedMember( - CFX_WideString::FromUTF8(szName.AsStringC()).AsStringC(), true); - } - if (!pReturnNode) { - pArguments->GetReturnValue()->SetNull(); - return; - } - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pReturnNode)); -} - -void CXFA_Node::Script_ExclGroup_ExecInitialize(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execInitialize"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Initialize); -} - -void CXFA_Node::Script_ExclGroup_ExecCalculate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execCalculate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Calculate); -} - -void CXFA_Node::Script_ExclGroup_ExecValidate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execValidate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - - int32_t iRet = pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Validate); - pArguments->GetReturnValue()->SetBoolean( - (iRet == XFA_EVENTERROR_Error) ? false : true); -} - -void CXFA_Node::Script_Som_InstanceIndex(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - int32_t iTo = pValue->ToInteger(); - int32_t iFrom = Subform_and_SubformSet_InstanceIndex(); - CXFA_Node* pManagerNode = nullptr; - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_PrevSibling); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) { - if (pNode->GetElementType() == XFA_Element::InstanceManager) { - pManagerNode = pNode; - break; - } - } - if (pManagerNode) { - pManagerNode->InstanceManager_MoveInstance(iTo, iFrom); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_Node* pToInstance = GetItem(pManagerNode, iTo); - if (pToInstance && - pToInstance->GetElementType() == XFA_Element::Subform) { - pNotify->RunSubformIndexChange(pToInstance); - } - CXFA_Node* pFromInstance = GetItem(pManagerNode, iFrom); - if (pFromInstance && - pFromInstance->GetElementType() == XFA_Element::Subform) { - pNotify->RunSubformIndexChange(pFromInstance); - } - } - } else { - pValue->SetInteger(Subform_and_SubformSet_InstanceIndex()); - } -} - -void CXFA_Node::Script_Subform_InstanceManager(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - - CFX_WideStringC wsName = GetCData(XFA_ATTRIBUTE_Name); - CXFA_Node* pInstanceMgr = nullptr; - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_PrevSibling); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) { - if (pNode->GetElementType() == XFA_Element::InstanceManager) { - CFX_WideStringC wsInstMgrName = pNode->GetCData(XFA_ATTRIBUTE_Name); - if (wsInstMgrName.GetLength() >= 1 && wsInstMgrName.GetAt(0) == '_' && - wsInstMgrName.Mid(1) == wsName) { - pInstanceMgr = pNode; - } - break; - } - } - if (!pInstanceMgr) { - pValue->SetNull(); - return; - } - - pValue->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pInstanceMgr)); -} - -void CXFA_Node::Script_Subform_Locale(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - SetCData(XFA_ATTRIBUTE_Locale, pValue->ToWideString(), true, true); - } else { - CFX_WideString wsLocaleName; - GetLocaleName(wsLocaleName); - pValue->SetString(wsLocaleName.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Subform_ExecEvent(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"execEvent"); - return; - } - - CFX_ByteString eventString = pArguments->GetUTF8String(0); - execSingleEventByName( - CFX_WideString::FromUTF8(eventString.AsStringC()).AsStringC(), - XFA_Element::Subform); -} - -void CXFA_Node::Script_Subform_ExecInitialize(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execInitialize"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Initialize); -} - -void CXFA_Node::Script_Subform_ExecCalculate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execCalculate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Calculate); -} - -void CXFA_Node::Script_Subform_ExecValidate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execValidate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - - int32_t iRet = pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Validate); - pArguments->GetReturnValue()->SetBoolean( - (iRet == XFA_EVENTERROR_Error) ? false : true); -} - -void CXFA_Node::Script_Subform_GetInvalidObjects(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"getInvalidObjects"); -} - -int32_t CXFA_Node::Subform_and_SubformSet_InstanceIndex() { - int32_t index = 0; - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_PrevSibling); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) { - if ((pNode->GetElementType() == XFA_Element::Subform) || - (pNode->GetElementType() == XFA_Element::SubformSet)) { - index++; - } else { - break; - } - } - return index; -} - -void CXFA_Node::Script_Template_FormNodes(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"formNodes"); - return; - } - pArguments->GetReturnValue()->SetBoolean(true); -} - -void CXFA_Node::Script_Template_Remerge(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"remerge"); - return; - } - m_pDocument->DoDataRemerge(true); -} - -void CXFA_Node::Script_Template_ExecInitialize(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execInitialize"); - return; - } - - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - pArguments->GetReturnValue()->SetBoolean(true); -} - -void CXFA_Node::Script_Template_CreateNode(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc <= 0 || argc >= 4) { - ThrowParamCountMismatchException(L"createNode"); - return; - } - - CFX_WideString strName; - CFX_WideString strNameSpace; - CFX_ByteString bsTagName = pArguments->GetUTF8String(0); - CFX_WideString strTagName = CFX_WideString::FromUTF8(bsTagName.AsStringC()); - if (argc > 1) { - CFX_ByteString bsName = pArguments->GetUTF8String(1); - strName = CFX_WideString::FromUTF8(bsName.AsStringC()); - if (argc == 3) { - CFX_ByteString bsNameSpace = pArguments->GetUTF8String(2); - strNameSpace = CFX_WideString::FromUTF8(bsNameSpace.AsStringC()); - } - } - - XFA_Element eType = XFA_GetElementTypeForName(strTagName.AsStringC()); - CXFA_Node* pNewNode = CreateSamePacketNode(eType); - if (!pNewNode) { - pArguments->GetReturnValue()->SetNull(); - return; - } - - if (strName.IsEmpty()) { - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNewNode)); - return; - } - - if (!GetAttributeOfElement(eType, XFA_ATTRIBUTE_Name, - XFA_XDPPACKET_UNKNOWN)) { - ThrowMissingPropertyException(strTagName, L"name"); - return; - } - - pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, strName.AsStringC(), true); - if (pNewNode->GetPacketID() == XFA_XDPPACKET_Datasets) - pNewNode->CreateXMLMappingNode(); - - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNewNode)); -} - -void CXFA_Node::Script_Template_Recalculate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"recalculate"); - return; - } - pArguments->GetReturnValue()->SetBoolean(true); -} - -void CXFA_Node::Script_Template_ExecCalculate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execCalculate"); - return; - } - - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - pArguments->GetReturnValue()->SetBoolean(true); -} - -void CXFA_Node::Script_Template_ExecValidate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execValidate"); - return; - } - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - pArguments->GetReturnValue()->SetBoolean(true); -} - -void CXFA_Node::Script_Manifest_Evaluate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"evaluate"); - return; - } - - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (!pWidgetData) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - pArguments->GetReturnValue()->SetBoolean(true); -} - -void CXFA_Node::Script_InstanceManager_Max(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - CXFA_Occur nodeOccur(GetOccurNode()); - pValue->SetInteger(nodeOccur.GetMax()); -} - -void CXFA_Node::Script_InstanceManager_Min(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - CXFA_Occur nodeOccur(GetOccurNode()); - pValue->SetInteger(nodeOccur.GetMin()); -} - -void CXFA_Node::Script_InstanceManager_Count(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - int32_t iDesired = pValue->ToInteger(); - InstanceManager_SetInstances(iDesired); - } else { - pValue->SetInteger(GetCount(this)); - } -} - -void CXFA_Node::Script_InstanceManager_MoveInstance( - CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 2) { - pArguments->GetReturnValue()->SetUndefined(); - return; - } - int32_t iFrom = pArguments->GetInt32(0); - int32_t iTo = pArguments->GetInt32(1); - InstanceManager_MoveInstance(iTo, iFrom); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - CXFA_Node* pToInstance = GetItem(this, iTo); - if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform) { - pNotify->RunSubformIndexChange(pToInstance); - } - CXFA_Node* pFromInstance = GetItem(this, iFrom); - if (pFromInstance && - pFromInstance->GetElementType() == XFA_Element::Subform) { - pNotify->RunSubformIndexChange(pFromInstance); - } -} - -void CXFA_Node::Script_InstanceManager_RemoveInstance( - CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - pArguments->GetReturnValue()->SetUndefined(); - return; - } - int32_t iIndex = pArguments->GetInt32(0); - int32_t iCount = GetCount(this); - if (iIndex < 0 || iIndex >= iCount) { - ThrowIndexOutOfBoundsException(); - return; - } - CXFA_Occur nodeOccur(GetOccurNode()); - int32_t iMin = nodeOccur.GetMin(); - if (iCount - 1 < iMin) { - ThrowTooManyOccurancesException(L"min"); - return; - } - CXFA_Node* pRemoveInstance = GetItem(this, iIndex); - RemoveItem(this, pRemoveInstance); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (pNotify) { - for (int32_t i = iIndex; i < iCount - 1; i++) { - CXFA_Node* pSubformInstance = GetItem(this, i); - if (pSubformInstance && - pSubformInstance->GetElementType() == XFA_Element::Subform) { - pNotify->RunSubformIndexChange(pSubformInstance); - } - } - } - CXFA_LayoutProcessor* pLayoutPro = m_pDocument->GetLayoutProcessor(); - if (!pLayoutPro) { - return; - } - pLayoutPro->AddChangedContainer( - ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form))); -} - -void CXFA_Node::Script_InstanceManager_SetInstances( - CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - pArguments->GetReturnValue()->SetUndefined(); - return; - } - int32_t iDesired = pArguments->GetInt32(0); - InstanceManager_SetInstances(iDesired); -} - -void CXFA_Node::Script_InstanceManager_AddInstance( - CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 0 && argc != 1) { - ThrowParamCountMismatchException(L"addInstance"); - return; - } - bool fFlags = true; - if (argc == 1) { - fFlags = pArguments->GetInt32(0) == 0 ? false : true; - } - int32_t iCount = GetCount(this); - CXFA_Occur nodeOccur(GetOccurNode()); - int32_t iMax = nodeOccur.GetMax(); - if (iMax >= 0 && iCount >= iMax) { - ThrowTooManyOccurancesException(L"max"); - return; - } - CXFA_Node* pNewInstance = CreateInstance(this, fFlags); - InsertItem(this, pNewInstance, iCount, iCount, false); - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNewInstance)); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - pNotify->RunNodeInitialize(pNewInstance); - CXFA_LayoutProcessor* pLayoutPro = m_pDocument->GetLayoutProcessor(); - if (!pLayoutPro) { - return; - } - pLayoutPro->AddChangedContainer( - ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form))); -} - -void CXFA_Node::Script_InstanceManager_InsertInstance( - CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 1 && argc != 2) { - ThrowParamCountMismatchException(L"insertInstance"); - return; - } - int32_t iIndex = pArguments->GetInt32(0); - bool bBind = false; - if (argc == 2) { - bBind = pArguments->GetInt32(1) == 0 ? false : true; - } - CXFA_Occur nodeOccur(GetOccurNode()); - int32_t iCount = GetCount(this); - if (iIndex < 0 || iIndex > iCount) { - ThrowIndexOutOfBoundsException(); - return; - } - int32_t iMax = nodeOccur.GetMax(); - if (iMax >= 0 && iCount >= iMax) { - ThrowTooManyOccurancesException(L"max"); - return; - } - CXFA_Node* pNewInstance = CreateInstance(this, bBind); - InsertItem(this, pNewInstance, iIndex, iCount, true); - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNewInstance)); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return; - } - pNotify->RunNodeInitialize(pNewInstance); - CXFA_LayoutProcessor* pLayoutPro = m_pDocument->GetLayoutProcessor(); - if (!pLayoutPro) { - return; - } - pLayoutPro->AddChangedContainer( - ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form))); -} - -int32_t CXFA_Node::InstanceManager_SetInstances(int32_t iDesired) { - CXFA_Occur nodeOccur(GetOccurNode()); - int32_t iMax = nodeOccur.GetMax(); - int32_t iMin = nodeOccur.GetMin(); - if (iDesired < iMin) { - ThrowTooManyOccurancesException(L"min"); - return 1; - } - if ((iMax >= 0) && (iDesired > iMax)) { - ThrowTooManyOccurancesException(L"max"); - return 2; - } - int32_t iCount = GetCount(this); - if (iDesired == iCount) { - return 0; - } - if (iDesired < iCount) { - CFX_WideStringC wsInstManagerName = GetCData(XFA_ATTRIBUTE_Name); - CFX_WideString wsInstanceName = - CFX_WideString(wsInstManagerName.IsEmpty() ? wsInstManagerName - : wsInstManagerName.Mid(1)); - uint32_t dInstanceNameHash = - FX_HashCode_GetW(wsInstanceName.AsStringC(), false); - CXFA_Node* pPrevSibling = - (iDesired == 0) ? this : GetItem(this, iDesired - 1); - while (iCount > iDesired) { - CXFA_Node* pRemoveInstance = - pPrevSibling->GetNodeItem(XFA_NODEITEM_NextSibling); - if (pRemoveInstance->GetElementType() != XFA_Element::Subform && - pRemoveInstance->GetElementType() != XFA_Element::SubformSet) { - continue; - } - if (pRemoveInstance->GetElementType() == XFA_Element::InstanceManager) { - ASSERT(false); - break; - } - if (pRemoveInstance->GetNameHash() == dInstanceNameHash) { - RemoveItem(this, pRemoveInstance); - iCount--; - } - } - } else if (iDesired > iCount) { - while (iCount < iDesired) { - CXFA_Node* pNewInstance = CreateInstance(this, true); - InsertItem(this, pNewInstance, iCount, iCount, false); - iCount++; - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return 0; - } - pNotify->RunNodeInitialize(pNewInstance); - } - } - CXFA_LayoutProcessor* pLayoutPro = m_pDocument->GetLayoutProcessor(); - if (pLayoutPro) { - pLayoutPro->AddChangedContainer( - ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form))); - } - return 0; -} - -int32_t CXFA_Node::InstanceManager_MoveInstance(int32_t iTo, int32_t iFrom) { - int32_t iCount = GetCount(this); - if (iFrom > iCount || iTo > iCount - 1) { - ThrowIndexOutOfBoundsException(); - return 1; - } - if (iFrom < 0 || iTo < 0 || iFrom == iTo) { - return 0; - } - CXFA_Node* pMoveInstance = GetItem(this, iFrom); - RemoveItem(this, pMoveInstance, false); - InsertItem(this, pMoveInstance, iTo, iCount - 1, true); - CXFA_LayoutProcessor* pLayoutPro = m_pDocument->GetLayoutProcessor(); - if (pLayoutPro) { - pLayoutPro->AddChangedContainer( - ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form))); - } - return 0; -} - -void CXFA_Node::Script_Occur_Max(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_Occur occur(this); - if (bSetting) { - int32_t iMax = pValue->ToInteger(); - occur.SetMax(iMax); - } else { - pValue->SetInteger(occur.GetMax()); - } -} - -void CXFA_Node::Script_Occur_Min(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - CXFA_Occur occur(this); - if (bSetting) { - int32_t iMin = pValue->ToInteger(); - occur.SetMin(iMin); - } else { - pValue->SetInteger(occur.GetMin()); - } -} - -void CXFA_Node::Script_Desc_Metadata(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 0 && argc != 1) { - ThrowParamCountMismatchException(L"metadata"); - return; - } - pArguments->GetReturnValue()->SetString(""); -} - -void CXFA_Node::Script_Form_FormNodes(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"formNodes"); - return; - } - - CXFA_Node* pDataNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - if (!pDataNode) { - ThrowArgumentMismatchException(); - return; - } - - CXFA_NodeArray formItems; - CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(m_pDocument); - pFormNodes->SetArrayNodeList(formItems); - pArguments->GetReturnValue()->SetObject( - pFormNodes, m_pDocument->GetScriptContext()->GetJseNormalClass()); -} - -void CXFA_Node::Script_Form_Remerge(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"remerge"); - return; - } - - m_pDocument->DoDataRemerge(true); -} - -void CXFA_Node::Script_Form_ExecInitialize(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execInitialize"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Initialize); -} - -void CXFA_Node::Script_Form_Recalculate(CFXJSE_Arguments* pArguments) { - CXFA_EventParam* pEventParam = - m_pDocument->GetScriptContext()->GetEventParam(); - if (pEventParam->m_eType == XFA_EVENT_Calculate || - pEventParam->m_eType == XFA_EVENT_InitCalculate) { - return; - } - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"recalculate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - if (pArguments->GetInt32(0) != 0) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Calculate); - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Validate); - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Ready, true); -} - -void CXFA_Node::Script_Form_ExecCalculate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execCalculate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) - return; - - pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Calculate); -} - -void CXFA_Node::Script_Form_ExecValidate(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) { - ThrowParamCountMismatchException(L"execValidate"); - return; - } - - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - pArguments->GetReturnValue()->SetBoolean(false); - return; - } - - int32_t iRet = pNotify->ExecEventByDeepFirst(this, XFA_EVENT_Validate); - pArguments->GetReturnValue()->SetBoolean( - (iRet == XFA_EVENTERROR_Error) ? false : true); -} - -void CXFA_Node::Script_Form_Checksum(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - SetAttribute(XFA_ATTRIBUTE_Checksum, pValue->ToWideString().AsStringC()); - return; - } - CFX_WideString wsChecksum; - GetAttribute(XFA_ATTRIBUTE_Checksum, wsChecksum, false); - pValue->SetString(wsChecksum.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_Packet_GetAttribute(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"getAttribute"); - return; - } - CFX_ByteString bsAttributeName = pArguments->GetUTF8String(0); - CFX_WideString wsAttributeValue; - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element) { - static_cast<CFDE_XMLElement*>(pXMLNode)->GetString( - CFX_WideString::FromUTF8(bsAttributeName.AsStringC()).c_str(), - wsAttributeValue); - } - pArguments->GetReturnValue()->SetString( - wsAttributeValue.UTF8Encode().AsStringC()); -} - -void CXFA_Node::Script_Packet_SetAttribute(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 2) { - ThrowParamCountMismatchException(L"setAttribute"); - return; - } - CFX_ByteString bsValue = pArguments->GetUTF8String(0); - CFX_ByteString bsName = pArguments->GetUTF8String(1); - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element) { - static_cast<CFDE_XMLElement*>(pXMLNode)->SetString( - CFX_WideString::FromUTF8(bsName.AsStringC()), - CFX_WideString::FromUTF8(bsValue.AsStringC())); - } - pArguments->GetReturnValue()->SetNull(); -} - -void CXFA_Node::Script_Packet_RemoveAttribute(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 1) { - ThrowParamCountMismatchException(L"removeAttribute"); - return; - } - - CFX_ByteString bsName = pArguments->GetUTF8String(0); - CFX_WideString wsName = CFX_WideString::FromUTF8(bsName.AsStringC()); - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - if (pXMLElement->HasAttribute(wsName.c_str())) { - pXMLElement->RemoveAttribute(wsName.c_str()); - } - } - pArguments->GetReturnValue()->SetNull(); -} - -void CXFA_Node::Script_Packet_Content(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - pXMLElement->SetTextData(pValue->ToWideString()); - } - } else { - CFX_WideString wsTextData; - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - pXMLElement->GetTextData(wsTextData); - } - pValue->SetString(wsTextData.UTF8Encode().AsStringC()); - } -} - -void CXFA_Node::Script_Source_Next(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"next"); -} - -void CXFA_Node::Script_Source_CancelBatch(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"cancelBatch"); -} - -void CXFA_Node::Script_Source_First(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"first"); -} - -void CXFA_Node::Script_Source_UpdateBatch(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"updateBatch"); -} - -void CXFA_Node::Script_Source_Previous(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"previous"); -} - -void CXFA_Node::Script_Source_IsBOF(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"isBOF"); -} - -void CXFA_Node::Script_Source_IsEOF(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"isEOF"); -} - -void CXFA_Node::Script_Source_Cancel(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"cancel"); -} - -void CXFA_Node::Script_Source_Update(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"update"); -} - -void CXFA_Node::Script_Source_Open(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"open"); -} - -void CXFA_Node::Script_Source_Delete(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"delete"); -} - -void CXFA_Node::Script_Source_AddNew(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"addNew"); -} - -void CXFA_Node::Script_Source_Requery(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"requery"); -} - -void CXFA_Node::Script_Source_Resync(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"resync"); -} - -void CXFA_Node::Script_Source_Close(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"close"); -} - -void CXFA_Node::Script_Source_Last(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"last"); -} - -void CXFA_Node::Script_Source_HasDataChanged(CFXJSE_Arguments* pArguments) { - if (pArguments->GetLength() != 0) - ThrowParamCountMismatchException(L"hasDataChanged"); -} - -void CXFA_Node::Script_Source_Db(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Xfa_This(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (!bSetting) { - CXFA_Object* pThis = m_pDocument->GetScriptContext()->GetThisObject(); - ASSERT(pThis); - pValue->Assign(m_pDocument->GetScriptContext()->GetJSValueFromMap(pThis)); - } -} - -void CXFA_Node::Script_Handler_Version(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_SubmitFormat_Mode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Extras_Type(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -void CXFA_Node::Script_Script_Stateless(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - pValue->SetString(FX_UTF8Encode(CFX_WideStringC(L"0", 1)).AsStringC()); -} - -void CXFA_Node::Script_Encrypt_Format(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) {} - -bool CXFA_Node::HasAttribute(XFA_ATTRIBUTE eAttr, bool bCanInherit) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - return HasMapModuleKey(pKey, bCanInherit); -} - -bool CXFA_Node::SetAttribute(XFA_ATTRIBUTE eAttr, - const CFX_WideStringC& wsValue, - bool bNotify) { - const XFA_ATTRIBUTEINFO* pAttr = XFA_GetAttributeByID(eAttr); - if (!pAttr) - return false; - - XFA_ATTRIBUTETYPE eType = pAttr->eType; - if (eType == XFA_ATTRIBUTETYPE_NOTSURE) { - const XFA_NOTSUREATTRIBUTE* pNotsure = - XFA_GetNotsureAttribute(GetElementType(), pAttr->eName); - eType = pNotsure ? pNotsure->eType : XFA_ATTRIBUTETYPE_Cdata; - } - switch (eType) { - case XFA_ATTRIBUTETYPE_Enum: { - const XFA_ATTRIBUTEENUMINFO* pEnum = XFA_GetAttributeEnumByName(wsValue); - return SetEnum(pAttr->eName, - pEnum ? pEnum->eName - : (XFA_ATTRIBUTEENUM)(intptr_t)(pAttr->pDefValue), - bNotify); - } break; - case XFA_ATTRIBUTETYPE_Cdata: - return SetCData(pAttr->eName, CFX_WideString(wsValue), bNotify); - case XFA_ATTRIBUTETYPE_Boolean: - return SetBoolean(pAttr->eName, wsValue != L"0", bNotify); - case XFA_ATTRIBUTETYPE_Integer: - return SetInteger(pAttr->eName, - FXSYS_round(FXSYS_wcstof(wsValue.c_str(), - wsValue.GetLength(), nullptr)), - bNotify); - case XFA_ATTRIBUTETYPE_Measure: - return SetMeasure(pAttr->eName, CXFA_Measurement(wsValue), bNotify); - default: - break; - } - return false; -} - -bool CXFA_Node::GetAttribute(XFA_ATTRIBUTE eAttr, - CFX_WideString& wsValue, - bool bUseDefault) { - const XFA_ATTRIBUTEINFO* pAttr = XFA_GetAttributeByID(eAttr); - if (!pAttr) { - return false; - } - XFA_ATTRIBUTETYPE eType = pAttr->eType; - if (eType == XFA_ATTRIBUTETYPE_NOTSURE) { - const XFA_NOTSUREATTRIBUTE* pNotsure = - XFA_GetNotsureAttribute(GetElementType(), pAttr->eName); - eType = pNotsure ? pNotsure->eType : XFA_ATTRIBUTETYPE_Cdata; - } - switch (eType) { - case XFA_ATTRIBUTETYPE_Enum: { - XFA_ATTRIBUTEENUM eValue; - if (!TryEnum(pAttr->eName, eValue, bUseDefault)) { - return false; - } - wsValue = GetAttributeEnumByID(eValue)->pName; - return true; - } break; - case XFA_ATTRIBUTETYPE_Cdata: { - CFX_WideStringC wsValueC; - if (!TryCData(pAttr->eName, wsValueC, bUseDefault)) { - return false; - } - wsValue = wsValueC; - return true; - } break; - case XFA_ATTRIBUTETYPE_Boolean: { - bool bValue; - if (!TryBoolean(pAttr->eName, bValue, bUseDefault)) { - return false; - } - wsValue = bValue ? L"1" : L"0"; - return true; - } break; - case XFA_ATTRIBUTETYPE_Integer: { - int32_t iValue; - if (!TryInteger(pAttr->eName, iValue, bUseDefault)) { - return false; - } - wsValue.Format(L"%d", iValue); - return true; - } break; - case XFA_ATTRIBUTETYPE_Measure: { - CXFA_Measurement mValue; - if (!TryMeasure(pAttr->eName, mValue, bUseDefault)) { - return false; - } - mValue.ToString(wsValue); - return true; - } break; - default: - break; - } - return false; -} - -bool CXFA_Node::SetAttribute(const CFX_WideStringC& wsAttr, - const CFX_WideStringC& wsValue, - bool bNotify) { - const XFA_ATTRIBUTEINFO* pAttributeInfo = XFA_GetAttributeByName(wsValue); - if (pAttributeInfo) { - return SetAttribute(pAttributeInfo->eName, wsValue, bNotify); - } - void* pKey = GetMapKey_Custom(wsAttr); - SetMapModuleString(pKey, wsValue); - return true; -} - -bool CXFA_Node::GetAttribute(const CFX_WideStringC& wsAttr, - CFX_WideString& wsValue, - bool bUseDefault) { - const XFA_ATTRIBUTEINFO* pAttributeInfo = XFA_GetAttributeByName(wsAttr); - if (pAttributeInfo) { - return GetAttribute(pAttributeInfo->eName, wsValue, bUseDefault); - } - void* pKey = GetMapKey_Custom(wsAttr); - CFX_WideStringC wsValueC; - if (GetMapModuleString(pKey, wsValueC)) { - wsValue = wsValueC; - } - return true; -} - -bool CXFA_Node::RemoveAttribute(const CFX_WideStringC& wsAttr) { - void* pKey = GetMapKey_Custom(wsAttr); - RemoveMapModuleKey(pKey); - return true; -} - -bool CXFA_Node::TryBoolean(XFA_ATTRIBUTE eAttr, - bool& bValue, - bool bUseDefault) { - void* pValue = nullptr; - if (!GetValue(eAttr, XFA_ATTRIBUTETYPE_Boolean, bUseDefault, pValue)) - return false; - bValue = !!pValue; - return true; -} - -bool CXFA_Node::TryInteger(XFA_ATTRIBUTE eAttr, - int32_t& iValue, - bool bUseDefault) { - void* pValue = nullptr; - if (!GetValue(eAttr, XFA_ATTRIBUTETYPE_Integer, bUseDefault, pValue)) - return false; - iValue = (int32_t)(uintptr_t)pValue; - return true; -} - -bool CXFA_Node::TryEnum(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTEENUM& eValue, - bool bUseDefault) { - void* pValue = nullptr; - if (!GetValue(eAttr, XFA_ATTRIBUTETYPE_Enum, bUseDefault, pValue)) - return false; - eValue = (XFA_ATTRIBUTEENUM)(uintptr_t)pValue; - return true; -} - -bool CXFA_Node::SetMeasure(XFA_ATTRIBUTE eAttr, - CXFA_Measurement mValue, - bool bNotify) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - OnChanging(eAttr, bNotify); - SetMapModuleBuffer(pKey, &mValue, sizeof(CXFA_Measurement)); - OnChanged(eAttr, bNotify, false); - return true; -} - -bool CXFA_Node::TryMeasure(XFA_ATTRIBUTE eAttr, - CXFA_Measurement& mValue, - bool bUseDefault) const { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - void* pValue; - int32_t iBytes; - if (GetMapModuleBuffer(pKey, pValue, iBytes) && iBytes == sizeof(mValue)) { - FXSYS_memcpy(&mValue, pValue, sizeof(mValue)); - return true; - } - if (bUseDefault && - XFA_GetAttributeDefaultValue(pValue, GetElementType(), eAttr, - XFA_ATTRIBUTETYPE_Measure, m_ePacket)) { - FXSYS_memcpy(&mValue, pValue, sizeof(mValue)); - return true; - } - return false; -} - -CXFA_Measurement CXFA_Node::GetMeasure(XFA_ATTRIBUTE eAttr) const { - CXFA_Measurement mValue; - return TryMeasure(eAttr, mValue, true) ? mValue : CXFA_Measurement(); -} - -bool CXFA_Node::SetCData(XFA_ATTRIBUTE eAttr, - const CFX_WideString& wsValue, - bool bNotify, - bool bScriptModify) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - OnChanging(eAttr, bNotify); - if (eAttr == XFA_ATTRIBUTE_Value) { - CFX_WideString* pClone = new CFX_WideString(wsValue); - SetUserData(pKey, pClone, &deleteWideStringCallBack); - } else { - SetMapModuleString(pKey, wsValue.AsStringC()); - if (eAttr == XFA_ATTRIBUTE_Name) - UpdateNameHash(); - } - OnChanged(eAttr, bNotify, bScriptModify); - - if (!IsNeedSavingXMLNode() || eAttr == XFA_ATTRIBUTE_QualifiedName || - eAttr == XFA_ATTRIBUTE_BindingNode) { - return true; - } - - if (eAttr == XFA_ATTRIBUTE_Name && - (m_elementType == XFA_Element::DataValue || - m_elementType == XFA_Element::DataGroup)) { - return true; - } - - if (eAttr == XFA_ATTRIBUTE_Value) { - FDE_XMLNODETYPE eXMLType = m_pXMLNode->GetType(); - switch (eXMLType) { - case FDE_XMLNODE_Element: - if (IsAttributeInXML()) { - static_cast<CFDE_XMLElement*>(m_pXMLNode) - ->SetString(CFX_WideString(GetCData(XFA_ATTRIBUTE_QualifiedName)), - wsValue); - } else { - bool bDeleteChildren = true; - if (GetPacketID() == XFA_XDPPACKET_Datasets) { - for (CXFA_Node* pChildDataNode = - GetNodeItem(XFA_NODEITEM_FirstChild); - pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { - CXFA_NodeArray formNodes; - if (pChildDataNode->GetBindItems(formNodes) > 0) { - bDeleteChildren = false; - break; - } - } - } - if (bDeleteChildren) { - static_cast<CFDE_XMLElement*>(m_pXMLNode)->DeleteChildren(); - } - static_cast<CFDE_XMLElement*>(m_pXMLNode)->SetTextData(wsValue); - } - break; - case FDE_XMLNODE_Text: - static_cast<CFDE_XMLText*>(m_pXMLNode)->SetText(wsValue); - break; - default: - ASSERT(0); - } - return true; - } - - const XFA_ATTRIBUTEINFO* pInfo = XFA_GetAttributeByID(eAttr); - if (pInfo) { - ASSERT(m_pXMLNode->GetType() == FDE_XMLNODE_Element); - CFX_WideString wsAttrName = pInfo->pName; - if (pInfo->eName == XFA_ATTRIBUTE_ContentType) { - wsAttrName = L"xfa:" + wsAttrName; - } - static_cast<CFDE_XMLElement*>(m_pXMLNode)->SetString(wsAttrName, wsValue); - } - return true; -} - -bool CXFA_Node::SetAttributeValue(const CFX_WideString& wsValue, - const CFX_WideString& wsXMLValue, - bool bNotify, - bool bScriptModify) { - void* pKey = GetMapKey_Element(GetElementType(), XFA_ATTRIBUTE_Value); - OnChanging(XFA_ATTRIBUTE_Value, bNotify); - CFX_WideString* pClone = new CFX_WideString(wsValue); - SetUserData(pKey, pClone, &deleteWideStringCallBack); - OnChanged(XFA_ATTRIBUTE_Value, bNotify, bScriptModify); - if (IsNeedSavingXMLNode()) { - FDE_XMLNODETYPE eXMLType = m_pXMLNode->GetType(); - switch (eXMLType) { - case FDE_XMLNODE_Element: - if (IsAttributeInXML()) { - static_cast<CFDE_XMLElement*>(m_pXMLNode) - ->SetString(CFX_WideString(GetCData(XFA_ATTRIBUTE_QualifiedName)), - wsXMLValue); - } else { - bool bDeleteChildren = true; - if (GetPacketID() == XFA_XDPPACKET_Datasets) { - for (CXFA_Node* pChildDataNode = - GetNodeItem(XFA_NODEITEM_FirstChild); - pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { - CXFA_NodeArray formNodes; - if (pChildDataNode->GetBindItems(formNodes) > 0) { - bDeleteChildren = false; - break; - } - } - } - if (bDeleteChildren) { - static_cast<CFDE_XMLElement*>(m_pXMLNode)->DeleteChildren(); - } - static_cast<CFDE_XMLElement*>(m_pXMLNode)->SetTextData(wsXMLValue); - } - break; - case FDE_XMLNODE_Text: - static_cast<CFDE_XMLText*>(m_pXMLNode)->SetText(wsXMLValue); - break; - default: - ASSERT(0); - } - } - return true; -} - -bool CXFA_Node::TryCData(XFA_ATTRIBUTE eAttr, - CFX_WideString& wsValue, - bool bUseDefault, - bool bProto) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - if (eAttr == XFA_ATTRIBUTE_Value) { - CFX_WideString* pStr = (CFX_WideString*)GetUserData(pKey, bProto); - if (pStr) { - wsValue = *pStr; - return true; - } - } else { - CFX_WideStringC wsValueC; - if (GetMapModuleString(pKey, wsValueC)) { - wsValue = wsValueC; - return true; - } - } - if (!bUseDefault) { - return false; - } - void* pValue = nullptr; - if (XFA_GetAttributeDefaultValue(pValue, GetElementType(), eAttr, - XFA_ATTRIBUTETYPE_Cdata, m_ePacket)) { - wsValue = (const FX_WCHAR*)pValue; - return true; - } - return false; -} - -bool CXFA_Node::TryCData(XFA_ATTRIBUTE eAttr, - CFX_WideStringC& wsValue, - bool bUseDefault, - bool bProto) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - if (eAttr == XFA_ATTRIBUTE_Value) { - CFX_WideString* pStr = (CFX_WideString*)GetUserData(pKey, bProto); - if (pStr) { - wsValue = pStr->AsStringC(); - return true; - } - } else { - if (GetMapModuleString(pKey, wsValue)) { - return true; - } - } - if (!bUseDefault) { - return false; - } - void* pValue = nullptr; - if (XFA_GetAttributeDefaultValue(pValue, GetElementType(), eAttr, - XFA_ATTRIBUTETYPE_Cdata, m_ePacket)) { - wsValue = (CFX_WideStringC)(const FX_WCHAR*)pValue; - return true; - } - return false; -} - -bool CXFA_Node::SetObject(XFA_ATTRIBUTE eAttr, - void* pData, - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - return SetUserData(pKey, pData, pCallbackInfo); -} - -bool CXFA_Node::TryObject(XFA_ATTRIBUTE eAttr, void*& pData) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - pData = GetUserData(pKey); - return !!pData; -} - -bool CXFA_Node::SetValue(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTETYPE eType, - void* pValue, - bool bNotify) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - OnChanging(eAttr, bNotify); - SetMapModuleValue(pKey, pValue); - OnChanged(eAttr, bNotify, false); - if (IsNeedSavingXMLNode()) { - ASSERT(m_pXMLNode->GetType() == FDE_XMLNODE_Element); - const XFA_ATTRIBUTEINFO* pInfo = XFA_GetAttributeByID(eAttr); - if (pInfo) { - switch (eType) { - case XFA_ATTRIBUTETYPE_Enum: - static_cast<CFDE_XMLElement*>(m_pXMLNode) - ->SetString( - pInfo->pName, - GetAttributeEnumByID((XFA_ATTRIBUTEENUM)(uintptr_t)pValue) - ->pName); - break; - case XFA_ATTRIBUTETYPE_Boolean: - static_cast<CFDE_XMLElement*>(m_pXMLNode) - ->SetString(pInfo->pName, pValue ? L"1" : L"0"); - break; - case XFA_ATTRIBUTETYPE_Integer: - static_cast<CFDE_XMLElement*>(m_pXMLNode) - ->SetInteger(pInfo->pName, (int32_t)(uintptr_t)pValue); - break; - default: - ASSERT(0); - } - } - } - return true; -} - -bool CXFA_Node::GetValue(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTETYPE eType, - bool bUseDefault, - void*& pValue) { - void* pKey = GetMapKey_Element(GetElementType(), eAttr); - if (GetMapModuleValue(pKey, pValue)) { - return true; - } - if (!bUseDefault) { - return false; - } - return XFA_GetAttributeDefaultValue(pValue, GetElementType(), eAttr, eType, - m_ePacket); -} - -bool CXFA_Node::SetUserData(void* pKey, - void* pData, - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) { - SetMapModuleBuffer(pKey, &pData, sizeof(void*), - pCallbackInfo ? pCallbackInfo : &gs_XFADefaultFreeData); - return true; -} - -bool CXFA_Node::TryUserData(void* pKey, void*& pData, bool bProtoAlso) { - int32_t iBytes = 0; - if (!GetMapModuleBuffer(pKey, pData, iBytes, bProtoAlso)) { - return false; - } - return iBytes == sizeof(void*) && FXSYS_memcpy(&pData, pData, iBytes); -} - -bool CXFA_Node::SetScriptContent(const CFX_WideString& wsContent, - const CFX_WideString& wsXMLValue, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - CXFA_Node* pNode = nullptr; - CXFA_Node* pBindNode = nullptr; - switch (GetObjectType()) { - case XFA_ObjectType::ContainerNode: { - if (XFA_FieldIsMultiListBox(this)) { - CXFA_Node* pValue = GetProperty(0, XFA_Element::Value); - CXFA_Node* pChildValue = pValue->GetNodeItem(XFA_NODEITEM_FirstChild); - ASSERT(pChildValue); - pChildValue->SetCData(XFA_ATTRIBUTE_ContentType, L"text/xml"); - pChildValue->SetScriptContent(wsContent, wsContent, bNotify, - bScriptModify, false); - CXFA_Node* pBind = GetBindData(); - if (bSyncData && pBind) { - std::vector<CFX_WideString> wsSaveTextArray; - int32_t iSize = 0; - if (!wsContent.IsEmpty()) { - int32_t iStart = 0; - int32_t iLength = wsContent.GetLength(); - int32_t iEnd = wsContent.Find(L'\n', iStart); - iEnd = (iEnd == -1) ? iLength : iEnd; - while (iEnd >= iStart) { - wsSaveTextArray.push_back(wsContent.Mid(iStart, iEnd - iStart)); - iStart = iEnd + 1; - if (iStart >= iLength) { - break; - } - iEnd = wsContent.Find(L'\n', iStart); - if (iEnd < 0) { - wsSaveTextArray.push_back( - wsContent.Mid(iStart, iLength - iStart)); - } - } - iSize = pdfium::CollectionSize<int32_t>(wsSaveTextArray); - } - if (iSize == 0) { - while (CXFA_Node* pChildNode = - pBind->GetNodeItem(XFA_NODEITEM_FirstChild)) { - pBind->RemoveChild(pChildNode); - } - } else { - CXFA_NodeArray valueNodes; - int32_t iDatas = pBind->GetNodeList( - valueNodes, XFA_NODEFILTER_Children, XFA_Element::DataValue); - if (iDatas < iSize) { - int32_t iAddNodes = iSize - iDatas; - CXFA_Node* pValueNodes = nullptr; - while (iAddNodes-- > 0) { - pValueNodes = - pBind->CreateSamePacketNode(XFA_Element::DataValue); - pValueNodes->SetCData(XFA_ATTRIBUTE_Name, L"value"); - pValueNodes->CreateXMLMappingNode(); - pBind->InsertChild(pValueNodes); - } - pValueNodes = nullptr; - } else if (iDatas > iSize) { - int32_t iDelNodes = iDatas - iSize; - while (iDelNodes-- > 0) { - pBind->RemoveChild(pBind->GetNodeItem(XFA_NODEITEM_FirstChild)); - } - } - int32_t i = 0; - for (CXFA_Node* pValueNode = - pBind->GetNodeItem(XFA_NODEITEM_FirstChild); - pValueNode; pValueNode = pValueNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { - pValueNode->SetAttributeValue(wsSaveTextArray[i], - wsSaveTextArray[i], false); - i++; - } - } - CXFA_NodeArray nodeArray; - pBind->GetBindItems(nodeArray); - for (int32_t i = 0; i < nodeArray.GetSize(); i++) { - if (nodeArray[i] != this) { - nodeArray[i]->SetScriptContent(wsContent, wsContent, bNotify, - bScriptModify, false); - } - } - } - break; - } else if (GetElementType() == XFA_Element::ExclGroup) { - pNode = this; - } else { - CXFA_Node* pValue = GetProperty(0, XFA_Element::Value); - CXFA_Node* pChildValue = pValue->GetNodeItem(XFA_NODEITEM_FirstChild); - ASSERT(pChildValue); - pChildValue->SetScriptContent(wsContent, wsContent, bNotify, - bScriptModify, false); - } - pBindNode = GetBindData(); - if (pBindNode && bSyncData) { - pBindNode->SetScriptContent(wsContent, wsXMLValue, bNotify, - bScriptModify, false); - CXFA_NodeArray nodeArray; - pBindNode->GetBindItems(nodeArray); - for (int32_t i = 0; i < nodeArray.GetSize(); i++) { - if (nodeArray[i] != this) { - nodeArray[i]->SetScriptContent(wsContent, wsContent, bNotify, true, - false); - } - } - } - pBindNode = nullptr; - break; - } - case XFA_ObjectType::ContentNode: { - CFX_WideString wsContentType; - if (GetElementType() == XFA_Element::ExData) { - GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false); - if (wsContentType == L"text/html") { - wsContentType = L""; - SetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType.AsStringC()); - } - } - CXFA_Node* pContentRawDataNode = GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pContentRawDataNode) { - pContentRawDataNode = CreateSamePacketNode( - (wsContentType == L"text/xml") ? XFA_Element::Sharpxml - : XFA_Element::Sharptext); - InsertChild(pContentRawDataNode); - } - return pContentRawDataNode->SetScriptContent( - wsContent, wsXMLValue, bNotify, bScriptModify, bSyncData); - } break; - case XFA_ObjectType::NodeC: - case XFA_ObjectType::TextNode: - pNode = this; - break; - case XFA_ObjectType::NodeV: - pNode = this; - if (bSyncData && GetPacketID() == XFA_XDPPACKET_Form) { - CXFA_Node* pParent = GetNodeItem(XFA_NODEITEM_Parent); - if (pParent) { - pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent); - } - if (pParent && pParent->GetElementType() == XFA_Element::Value) { - pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent); - if (pParent && pParent->IsContainerNode()) { - pBindNode = pParent->GetBindData(); - if (pBindNode) { - pBindNode->SetScriptContent(wsContent, wsXMLValue, bNotify, - bScriptModify, false); - } - } - } - } - break; - default: - if (GetElementType() == XFA_Element::DataValue) { - pNode = this; - pBindNode = this; - } - break; - } - if (pNode) { - SetAttributeValue(wsContent, wsXMLValue, bNotify, bScriptModify); - if (pBindNode && bSyncData) { - CXFA_NodeArray nodeArray; - pBindNode->GetBindItems(nodeArray); - for (int32_t i = 0; i < nodeArray.GetSize(); i++) { - nodeArray[i]->SetScriptContent(wsContent, wsContent, bNotify, - bScriptModify, false); - } - } - return true; - } - return false; -} - -bool CXFA_Node::SetContent(const CFX_WideString& wsContent, - const CFX_WideString& wsXMLValue, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - return SetScriptContent(wsContent, wsXMLValue, bNotify, bScriptModify, - bSyncData); -} - -CFX_WideString CXFA_Node::GetScriptContent(bool bScriptModify) { - CFX_WideString wsContent; - return TryContent(wsContent, bScriptModify) ? wsContent : CFX_WideString(); -} - -CFX_WideString CXFA_Node::GetContent() { - return GetScriptContent(); -} - -bool CXFA_Node::TryContent(CFX_WideString& wsContent, - bool bScriptModify, - bool bProto) { - CXFA_Node* pNode = nullptr; - switch (GetObjectType()) { - case XFA_ObjectType::ContainerNode: - if (GetElementType() == XFA_Element::ExclGroup) { - pNode = this; - } else { - CXFA_Node* pValue = GetChild(0, XFA_Element::Value); - if (!pValue) { - return false; - } - CXFA_Node* pChildValue = pValue->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pChildValue && XFA_FieldIsMultiListBox(this)) { - pChildValue->SetAttribute(XFA_ATTRIBUTE_ContentType, L"text/xml"); - } - return pChildValue - ? pChildValue->TryContent(wsContent, bScriptModify, bProto) - : false; - } - break; - case XFA_ObjectType::ContentNode: { - CXFA_Node* pContentRawDataNode = GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pContentRawDataNode) { - XFA_Element element = XFA_Element::Sharptext; - if (GetElementType() == XFA_Element::ExData) { - CFX_WideString wsContentType; - GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false); - if (wsContentType == L"text/html") { - element = XFA_Element::SharpxHTML; - } else if (wsContentType == L"text/xml") { - element = XFA_Element::Sharpxml; - } - } - pContentRawDataNode = CreateSamePacketNode(element); - InsertChild(pContentRawDataNode); - } - return pContentRawDataNode->TryContent(wsContent, bScriptModify, bProto); - } - case XFA_ObjectType::NodeC: - case XFA_ObjectType::NodeV: - case XFA_ObjectType::TextNode: - pNode = this; - default: - if (GetElementType() == XFA_Element::DataValue) { - pNode = this; - } - break; - } - if (pNode) { - if (bScriptModify) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (pScriptContext) { - m_pDocument->GetScriptContext()->AddNodesOfRunScript(this); - } - } - return TryCData(XFA_ATTRIBUTE_Value, wsContent, false, bProto); - } - return false; -} - -CXFA_Node* CXFA_Node::GetModelNode() { - switch (GetPacketID()) { - case XFA_XDPPACKET_XDP: - return m_pDocument->GetRoot(); - case XFA_XDPPACKET_Config: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config)); - case XFA_XDPPACKET_Template: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Template)); - case XFA_XDPPACKET_Form: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form)); - case XFA_XDPPACKET_Datasets: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Datasets)); - case XFA_XDPPACKET_LocaleSet: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_LocaleSet)); - case XFA_XDPPACKET_ConnectionSet: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_ConnectionSet)); - case XFA_XDPPACKET_SourceSet: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_SourceSet)); - case XFA_XDPPACKET_Xdc: - return ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Xdc)); - default: - return this; - } -} - -bool CXFA_Node::TryNamespace(CFX_WideString& wsNamespace) { - wsNamespace.clear(); - if (IsModelNode() || GetElementType() == XFA_Element::Packet) { - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (!pXMLNode || pXMLNode->GetType() != FDE_XMLNODE_Element) { - return false; - } - static_cast<CFDE_XMLElement*>(pXMLNode)->GetNamespaceURI(wsNamespace); - return true; - } else if (GetPacketID() == XFA_XDPPACKET_Datasets) { - CFDE_XMLNode* pXMLNode = GetXMLMappingNode(); - if (!pXMLNode) { - return false; - } - if (pXMLNode->GetType() != FDE_XMLNODE_Element) { - return true; - } - if (GetElementType() == XFA_Element::DataValue && - GetEnum(XFA_ATTRIBUTE_Contains) == XFA_ATTRIBUTEENUM_MetaData) { - return XFA_FDEExtension_ResolveNamespaceQualifier( - static_cast<CFDE_XMLElement*>(pXMLNode), - GetCData(XFA_ATTRIBUTE_QualifiedName), wsNamespace); - } - static_cast<CFDE_XMLElement*>(pXMLNode)->GetNamespaceURI(wsNamespace); - return true; - } else { - CXFA_Node* pModelNode = GetModelNode(); - return pModelNode->TryNamespace(wsNamespace); - } -} - -CXFA_Node* CXFA_Node::GetProperty(int32_t index, - XFA_Element eProperty, - bool bCreateProperty) { - XFA_Element eType = GetElementType(); - uint32_t dwPacket = GetPacketID(); - const XFA_PROPERTY* pProperty = - XFA_GetPropertyOfElement(eType, eProperty, dwPacket); - if (!pProperty || index >= pProperty->uOccur) - return nullptr; - - CXFA_Node* pNode = m_pChild; - int32_t iCount = 0; - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() == eProperty) { - iCount++; - if (iCount > index) { - return pNode; - } - } - } - if (!bCreateProperty) - return nullptr; - - if (pProperty->uFlags & XFA_PROPERTYFLAG_OneOf) { - pNode = m_pChild; - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - const XFA_PROPERTY* pExistProperty = - XFA_GetPropertyOfElement(eType, pNode->GetElementType(), dwPacket); - if (pExistProperty && (pExistProperty->uFlags & XFA_PROPERTYFLAG_OneOf)) - return nullptr; - } - } - - const XFA_PACKETINFO* pPacket = XFA_GetPacketByID(dwPacket); - CXFA_Node* pNewNode = nullptr; - for (; iCount <= index; iCount++) { - pNewNode = m_pDocument->CreateNode(pPacket, eProperty); - if (!pNewNode) - return nullptr; - InsertChild(pNewNode, nullptr); - pNewNode->SetFlag(XFA_NodeFlag_Initialized, true); - } - return pNewNode; -} - -int32_t CXFA_Node::CountChildren(XFA_Element eType, bool bOnlyChild) { - CXFA_Node* pNode = m_pChild; - int32_t iCount = 0; - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() == eType || eType == XFA_Element::Unknown) { - if (bOnlyChild) { - const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( - GetElementType(), pNode->GetElementType(), XFA_XDPPACKET_UNKNOWN); - if (pProperty) { - continue; - } - } - iCount++; - } - } - return iCount; -} - -CXFA_Node* CXFA_Node::GetChild(int32_t index, - XFA_Element eType, - bool bOnlyChild) { - ASSERT(index > -1); - CXFA_Node* pNode = m_pChild; - int32_t iCount = 0; - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() == eType || eType == XFA_Element::Unknown) { - if (bOnlyChild) { - const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( - GetElementType(), pNode->GetElementType(), XFA_XDPPACKET_UNKNOWN); - if (pProperty) { - continue; - } - } - iCount++; - if (iCount > index) { - return pNode; - } - } - } - return nullptr; -} - -int32_t CXFA_Node::InsertChild(int32_t index, CXFA_Node* pNode) { - ASSERT(!pNode->m_pNext); - pNode->m_pParent = this; - bool ret = m_pDocument->RemovePurgeNode(pNode); - ASSERT(ret); - (void)ret; // Avoid unused variable warning. - - if (!m_pChild || index == 0) { - if (index > 0) { - return -1; - } - pNode->m_pNext = m_pChild; - m_pChild = pNode; - index = 0; - } else if (index < 0) { - m_pLastChild->m_pNext = pNode; - } else { - CXFA_Node* pPrev = m_pChild; - int32_t iCount = 0; - while (++iCount != index && pPrev->m_pNext) { - pPrev = pPrev->m_pNext; - } - if (index > 0 && index != iCount) { - return -1; - } - pNode->m_pNext = pPrev->m_pNext; - pPrev->m_pNext = pNode; - index = iCount; - } - if (!pNode->m_pNext) { - m_pLastChild = pNode; - } - ASSERT(m_pLastChild); - ASSERT(!m_pLastChild->m_pNext); - pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (pNotify) - pNotify->OnChildAdded(this); - - if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { - ASSERT(!pNode->m_pXMLNode->GetNodeItem(CFDE_XMLNode::Parent)); - m_pXMLNode->InsertChildNode(pNode->m_pXMLNode, index); - pNode->ClearFlag(XFA_NodeFlag_OwnXMLNode); - } - return index; -} - -bool CXFA_Node::InsertChild(CXFA_Node* pNode, CXFA_Node* pBeforeNode) { - if (!pNode || pNode->m_pParent || - (pBeforeNode && pBeforeNode->m_pParent != this)) { - ASSERT(false); - return false; - } - bool ret = m_pDocument->RemovePurgeNode(pNode); - ASSERT(ret); - (void)ret; // Avoid unused variable warning. - - int32_t nIndex = -1; - pNode->m_pParent = this; - if (!m_pChild || pBeforeNode == m_pChild) { - pNode->m_pNext = m_pChild; - m_pChild = pNode; - nIndex = 0; - } else if (!pBeforeNode) { - pNode->m_pNext = m_pLastChild->m_pNext; - m_pLastChild->m_pNext = pNode; - } else { - nIndex = 1; - CXFA_Node* pPrev = m_pChild; - while (pPrev->m_pNext != pBeforeNode) { - pPrev = pPrev->m_pNext; - nIndex++; - } - pNode->m_pNext = pPrev->m_pNext; - pPrev->m_pNext = pNode; - } - if (!pNode->m_pNext) { - m_pLastChild = pNode; - } - ASSERT(m_pLastChild); - ASSERT(!m_pLastChild->m_pNext); - pNode->ClearFlag(XFA_NodeFlag_HasRemovedChildren); - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (pNotify) - pNotify->OnChildAdded(this); - - if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { - ASSERT(!pNode->m_pXMLNode->GetNodeItem(CFDE_XMLNode::Parent)); - m_pXMLNode->InsertChildNode(pNode->m_pXMLNode, nIndex); - pNode->ClearFlag(XFA_NodeFlag_OwnXMLNode); - } - return true; -} - -CXFA_Node* CXFA_Node::Deprecated_GetPrevSibling() { - if (!m_pParent) { - return nullptr; - } - for (CXFA_Node* pSibling = m_pParent->m_pChild; pSibling; - pSibling = pSibling->m_pNext) { - if (pSibling->m_pNext == this) { - return pSibling; - } - } - return nullptr; -} - -bool CXFA_Node::RemoveChild(CXFA_Node* pNode, bool bNotify) { - if (!pNode || pNode->m_pParent != this) { - ASSERT(false); - return false; - } - if (m_pChild == pNode) { - m_pChild = pNode->m_pNext; - if (m_pLastChild == pNode) { - m_pLastChild = pNode->m_pNext; - } - pNode->m_pNext = nullptr; - pNode->m_pParent = nullptr; - } else { - CXFA_Node* pPrev = pNode->Deprecated_GetPrevSibling(); - pPrev->m_pNext = pNode->m_pNext; - if (m_pLastChild == pNode) { - m_pLastChild = pNode->m_pNext ? pNode->m_pNext : pPrev; - } - pNode->m_pNext = nullptr; - pNode->m_pParent = nullptr; - } - ASSERT(!m_pLastChild || !m_pLastChild->m_pNext); - OnRemoved(bNotify); - pNode->SetFlag(XFA_NodeFlag_HasRemovedChildren, true); - m_pDocument->AddPurgeNode(pNode); - if (IsNeedSavingXMLNode() && pNode->m_pXMLNode) { - if (pNode->IsAttributeInXML()) { - ASSERT(pNode->m_pXMLNode == m_pXMLNode && - m_pXMLNode->GetType() == FDE_XMLNODE_Element); - if (pNode->m_pXMLNode->GetType() == FDE_XMLNODE_Element) { - CFDE_XMLElement* pXMLElement = - static_cast<CFDE_XMLElement*>(pNode->m_pXMLNode); - CFX_WideStringC wsAttributeName = - pNode->GetCData(XFA_ATTRIBUTE_QualifiedName); - pXMLElement->RemoveAttribute(wsAttributeName.c_str()); - } - CFX_WideString wsName; - pNode->GetAttribute(XFA_ATTRIBUTE_Name, wsName, false); - CFDE_XMLElement* pNewXMLElement = new CFDE_XMLElement(wsName); - CFX_WideStringC wsValue = GetCData(XFA_ATTRIBUTE_Value); - if (!wsValue.IsEmpty()) { - pNewXMLElement->SetTextData(CFX_WideString(wsValue)); + pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode); + } + } } - pNode->m_pXMLNode = pNewXMLElement; - pNode->SetEnum(XFA_ATTRIBUTE_Contains, XFA_ATTRIBUTEENUM_Unknown); - } else { - m_pXMLNode->RemoveChildNode(pNode->m_pXMLNode); + break; } - pNode->SetFlag(XFA_NodeFlag_OwnXMLNode, false); + default: + break; } - return true; + + if (!bNeedFindContainer) + return; + + CXFA_Node* pParent = this; + while (pParent && !pParent->IsContainerNode()) + pParent = pParent->GetParent(); + + if (pParent) + pLayoutPro->AddChangedContainer(pParent); } -CXFA_Node* CXFA_Node::GetFirstChildByName(const CFX_WideStringC& wsName) const { - return GetFirstChildByName(FX_HashCode_GetW(wsName, false)); +void CXFA_Node::SyncValue(const WideString& wsValue, bool bNotify) { + WideString wsFormatValue = wsValue; + CXFA_WidgetAcc* pContainerWidgetAcc = GetContainerWidgetAcc(); + if (pContainerWidgetAcc) + wsFormatValue = pContainerWidgetAcc->GetFormatDataValue(wsValue); + + JSObject()->SetContent(wsValue, wsFormatValue, bNotify, false, true); } -CXFA_Node* CXFA_Node::GetFirstChildByName(uint32_t dwNameHash) const { - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_FirstChild); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetNameHash() == dwNameHash) { - return pNode; - } - } - return nullptr; +WideString CXFA_Node::GetRawValue() { + return JSObject()->GetContent(false); } -CXFA_Node* CXFA_Node::GetFirstChildByClass(XFA_Element eType) const { - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_FirstChild); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() == eType) { - return pNode; - } - } - return nullptr; +int32_t CXFA_Node::GetRotate() { + Optional<int32_t> degrees = + JSObject()->TryInteger(XFA_Attribute::Rotate, false); + return degrees ? XFA_MapRotation(*degrees) / 90 * 90 : 0; } -CXFA_Node* CXFA_Node::GetNextSameNameSibling(uint32_t dwNameHash) const { - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_NextSibling); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetNameHash() == dwNameHash) { - return pNode; - } - } - return nullptr; +CXFA_Border* CXFA_Node::GetBorderIfExists() const { + return JSObject()->GetProperty<CXFA_Border>(0, XFA_Element::Border); } -CXFA_Node* CXFA_Node::GetNextSameNameSibling( - const CFX_WideStringC& wsNodeName) const { - return GetNextSameNameSibling(FX_HashCode_GetW(wsNodeName, false)); +CXFA_Border* CXFA_Node::GetOrCreateBorderIfPossible() { + return JSObject()->GetOrCreateProperty<CXFA_Border>(0, XFA_Element::Border); } -CXFA_Node* CXFA_Node::GetNextSameClassSibling(XFA_Element eType) const { - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_NextSibling); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() == eType) { - return pNode; - } - } - return nullptr; +CXFA_Caption* CXFA_Node::GetCaptionIfExists() const { + return JSObject()->GetProperty<CXFA_Caption>(0, XFA_Element::Caption); } -int32_t CXFA_Node::GetNodeSameNameIndex() const { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) { - return -1; - } - return pScriptContext->GetIndexByName(const_cast<CXFA_Node*>(this)); +CXFA_Font* CXFA_Node::GetOrCreateFontIfPossible() { + return JSObject()->GetOrCreateProperty<CXFA_Font>(0, XFA_Element::Font); } -int32_t CXFA_Node::GetNodeSameClassIndex() const { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) { - return -1; - } - return pScriptContext->GetIndexByClassName(const_cast<CXFA_Node*>(this)); +CXFA_Font* CXFA_Node::GetFontIfExists() const { + return JSObject()->GetProperty<CXFA_Font>(0, XFA_Element::Font); } -void CXFA_Node::GetSOMExpression(CFX_WideString& wsSOMExpression) { - CXFA_ScriptContext* pScriptContext = m_pDocument->GetScriptContext(); - if (!pScriptContext) { - return; - } - pScriptContext->GetSomExpression(this, wsSOMExpression); +float CXFA_Node::GetFontSize() const { + CXFA_Font* font = GetFontIfExists(); + float fFontSize = font ? font->GetFontSize() : 10.0f; + return fFontSize < 0.1f ? 10.0f : fFontSize; } -CXFA_Node* CXFA_Node::GetInstanceMgrOfSubform() { - CXFA_Node* pInstanceMgr = nullptr; - if (m_ePacket == XFA_XDPPACKET_Form) { - CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent); - if (!pParentNode || pParentNode->GetElementType() == XFA_Element::Area) { - return pInstanceMgr; - } - for (CXFA_Node* pNode = GetNodeItem(XFA_NODEITEM_PrevSibling); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) { - XFA_Element eType = pNode->GetElementType(); - if ((eType == XFA_Element::Subform || eType == XFA_Element::SubformSet) && - pNode->m_dwNameHash != m_dwNameHash) { - break; - } - if (eType == XFA_Element::InstanceManager) { - CFX_WideStringC wsName = GetCData(XFA_ATTRIBUTE_Name); - CFX_WideStringC wsInstName = pNode->GetCData(XFA_ATTRIBUTE_Name); - if (wsInstName.GetLength() > 0 && wsInstName.GetAt(0) == '_' && - wsInstName.Mid(1) == wsName) { - pInstanceMgr = pNode; - } - break; - } - } - } - return pInstanceMgr; +float CXFA_Node::GetLineHeight() const { + float fLineHeight = 0; + CXFA_Para* para = GetParaIfExists(); + if (para) + fLineHeight = para->GetLineHeight(); + + if (fLineHeight < 1) + fLineHeight = GetFontSize() * 1.2f; + return fLineHeight; } -CXFA_Node* CXFA_Node::GetOccurNode() { - return GetFirstChildByClass(XFA_Element::Occur); +FX_ARGB CXFA_Node::GetTextColor() const { + CXFA_Font* font = GetFontIfExists(); + return font ? font->GetColor() : 0xFF000000; } -bool CXFA_Node::HasFlag(XFA_NodeFlag dwFlag) const { - if (m_uNodeFlags & dwFlag) - return true; - if (dwFlag == XFA_NodeFlag_HasRemovedChildren) - return m_pParent && m_pParent->HasFlag(dwFlag); - return false; +CXFA_Margin* CXFA_Node::GetMarginIfExists() const { + return JSObject()->GetProperty<CXFA_Margin>(0, XFA_Element::Margin); } -void CXFA_Node::SetFlag(uint32_t dwFlag, bool bNotify) { - if (dwFlag == XFA_NodeFlag_Initialized && bNotify && !IsInitialized()) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (pNotify) { - pNotify->OnNodeReady(this); - } +CXFA_Para* CXFA_Node::GetParaIfExists() const { + return JSObject()->GetProperty<CXFA_Para>(0, XFA_Element::Para); +} + +bool CXFA_Node::IsOpenAccess() { + for (auto* pNode = this; pNode; pNode = pNode->GetContainerParent()) { + XFA_AttributeEnum iAcc = pNode->JSObject()->GetEnum(XFA_Attribute::Access); + if (iAcc != XFA_AttributeEnum::Open) + return false; } - m_uNodeFlags |= dwFlag; + return true; } -void CXFA_Node::ClearFlag(uint32_t dwFlag) { - m_uNodeFlags &= ~dwFlag; +CXFA_Value* CXFA_Node::GetDefaultValueIfExists() { + CXFA_Node* pTemNode = GetTemplateNodeIfExists(); + return pTemNode ? pTemNode->JSObject()->GetProperty<CXFA_Value>( + 0, XFA_Element::Value) + : nullptr; } -bool CXFA_Node::IsAttributeInXML() { - return GetEnum(XFA_ATTRIBUTE_Contains) == XFA_ATTRIBUTEENUM_MetaData; +CXFA_Value* CXFA_Node::GetFormValueIfExists() const { + return JSObject()->GetProperty<CXFA_Value>(0, XFA_Element::Value); } -void CXFA_Node::OnRemoved(bool bNotify) { - if (!bNotify) - return; +CXFA_Calculate* CXFA_Node::GetCalculateIfExists() const { + return JSObject()->GetProperty<CXFA_Calculate>(0, XFA_Element::Calculate); +} - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (pNotify) - pNotify->OnChildRemoved(); +CXFA_Validate* CXFA_Node::GetValidateIfExists() const { + return JSObject()->GetProperty<CXFA_Validate>(0, XFA_Element::Validate); } -void CXFA_Node::OnChanging(XFA_ATTRIBUTE eAttr, bool bNotify) { - if (bNotify && IsInitialized()) { - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (pNotify) { - pNotify->OnValueChanging(this, eAttr); - } - } +CXFA_Validate* CXFA_Node::GetOrCreateValidateIfPossible() { + return JSObject()->GetOrCreateProperty<CXFA_Validate>(0, + XFA_Element::Validate); } -void CXFA_Node::OnChanged(XFA_ATTRIBUTE eAttr, - bool bNotify, - bool bScriptModify) { - if (bNotify && IsInitialized()) { - Script_Attribute_SendAttributeChangeMessage(eAttr, bScriptModify); - } +CXFA_Bind* CXFA_Node::GetBindIfExists() const { + return JSObject()->GetProperty<CXFA_Bind>(0, XFA_Element::Bind); } -int32_t CXFA_Node::execSingleEventByName(const CFX_WideStringC& wsEventName, - XFA_Element eType) { - int32_t iRet = XFA_EVENTERROR_NotExist; - const XFA_ExecEventParaInfo* eventParaInfo = - GetEventParaInfoByName(wsEventName); - if (eventParaInfo) { - uint32_t validFlags = eventParaInfo->m_validFlags; - CXFA_FFNotify* pNotify = m_pDocument->GetNotify(); - if (!pNotify) { - return iRet; - } - if (validFlags == 1) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType); - } else if (validFlags == 2) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } else if (validFlags == 3) { - if (eType == XFA_Element::Subform) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } - } else if (validFlags == 4) { - if (eType == XFA_Element::ExclGroup || eType == XFA_Element::Field) { - CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent); - if (pParentNode && - pParentNode->GetElementType() == XFA_Element::ExclGroup) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } - } else if (validFlags == 5) { - if (eType == XFA_Element::Field) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } - } else if (validFlags == 6) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (pWidgetData) { - CXFA_Node* pUINode = pWidgetData->GetUIChild(); - if (pUINode->m_elementType == XFA_Element::Signature) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } - } - } else if (validFlags == 7) { - CXFA_WidgetData* pWidgetData = GetWidgetData(); - if (pWidgetData) { - CXFA_Node* pUINode = pWidgetData->GetUIChild(); - if ((pUINode->m_elementType == XFA_Element::ChoiceList) && - (!pWidgetData->IsListBox())) { - iRet = pNotify->ExecEventByDeepFirst(this, eventParaInfo->m_eventType, - false, false); - } - } - } - } - return iRet; +Optional<float> CXFA_Node::TryWidth() { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::W); } -void CXFA_Node::UpdateNameHash() { - const XFA_NOTSUREATTRIBUTE* pNotsure = - XFA_GetNotsureAttribute(GetElementType(), XFA_ATTRIBUTE_Name); - CFX_WideStringC wsName; - if (!pNotsure || pNotsure->eType == XFA_ATTRIBUTETYPE_Cdata) { - wsName = GetCData(XFA_ATTRIBUTE_Name); - m_dwNameHash = FX_HashCode_GetW(wsName, false); - } else if (pNotsure->eType == XFA_ATTRIBUTETYPE_Enum) { - wsName = GetAttributeEnumByID(GetEnum(XFA_ATTRIBUTE_Name))->pName; - m_dwNameHash = FX_HashCode_GetW(wsName, false); - } +Optional<float> CXFA_Node::TryHeight() { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::H); } -CFDE_XMLNode* CXFA_Node::CreateXMLMappingNode() { - if (!m_pXMLNode) { - CFX_WideString wsTag(GetCData(XFA_ATTRIBUTE_Name)); - m_pXMLNode = new CFDE_XMLElement(wsTag); - SetFlag(XFA_NodeFlag_OwnXMLNode, false); - } - return m_pXMLNode; +Optional<float> CXFA_Node::TryMinWidth() { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinW); } -bool CXFA_Node::IsNeedSavingXMLNode() { - return m_pXMLNode && (GetPacketID() == XFA_XDPPACKET_Datasets || - GetElementType() == XFA_Element::Xfa); +Optional<float> CXFA_Node::TryMinHeight() { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinH); } -XFA_MAPMODULEDATA* CXFA_Node::CreateMapModuleData() { - if (!m_pMapModuleData) - m_pMapModuleData = new XFA_MAPMODULEDATA; - return m_pMapModuleData; +Optional<float> CXFA_Node::TryMaxWidth() { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxW); } -XFA_MAPMODULEDATA* CXFA_Node::GetMapModuleData() const { - return m_pMapModuleData; +Optional<float> CXFA_Node::TryMaxHeight() { + return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxH); } -void CXFA_Node::SetMapModuleValue(void* pKey, void* pValue) { - XFA_MAPMODULEDATA* pModule = CreateMapModuleData(); - pModule->m_ValueMap[pKey] = pValue; +CXFA_Node* CXFA_Node::GetExclGroupIfExists() { + CXFA_Node* pExcl = GetParent(); + if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) + return nullptr; + return pExcl; } -bool CXFA_Node::GetMapModuleValue(void* pKey, void*& pValue) { - for (CXFA_Node* pNode = this; pNode; pNode = pNode->GetTemplateNode()) { - XFA_MAPMODULEDATA* pModule = pNode->GetMapModuleData(); - if (pModule) { - auto it = pModule->m_ValueMap.find(pKey); - if (it != pModule->m_ValueMap.end()) { - pValue = it->second; - return true; - } +int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView, + XFA_AttributeEnum iActivity, + CXFA_EventParam* pEventParam) { + if (GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + std::vector<CXFA_Event*> eventArray = GetWidgetAcc()->GetEventByActivity( + iActivity, pEventParam->m_bIsFormReady); + bool first = true; + int32_t iRet = XFA_EVENTERROR_NotExist; + for (CXFA_Event* event : eventArray) { + int32_t result = ProcessEvent(docView, event, pEventParam); + if (first || result == XFA_EVENTERROR_Success) + iRet = result; + first = false; + } + return iRet; +} + +int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView, + CXFA_Event* event, + CXFA_EventParam* pEventParam) { + if (!event) + return XFA_EVENTERROR_NotExist; + + switch (event->GetEventType()) { + case XFA_Element::Execute: + break; + case XFA_Element::Script: + return ExecuteScript(docView, event->GetScriptIfExists(), pEventParam); + case XFA_Element::SignData: + break; + case XFA_Element::Submit: { + CXFA_Submit* submit = event->GetSubmitIfExists(); + if (!submit) + return XFA_EVENTERROR_NotExist; + return docView->GetDoc()->GetDocEnvironment()->Submit(docView->GetDoc(), + submit); } - if (pNode->GetPacketID() == XFA_XDPPACKET_Datasets) + default: break; } - return false; + return XFA_EVENTERROR_NotExist; } -void CXFA_Node::SetMapModuleString(void* pKey, const CFX_WideStringC& wsValue) { - SetMapModuleBuffer(pKey, (void*)wsValue.c_str(), - wsValue.GetLength() * sizeof(FX_WCHAR)); -} +int32_t CXFA_Node::ProcessCalculate(CXFA_FFDocView* docView) { + if (GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; -bool CXFA_Node::GetMapModuleString(void* pKey, CFX_WideStringC& wsValue) { - void* pValue; - int32_t iBytes; - if (!GetMapModuleBuffer(pKey, pValue, iBytes)) { - return false; + CXFA_Calculate* calc = GetCalculateIfExists(); + if (!calc) + return XFA_EVENTERROR_NotExist; + if (IsUserInteractive()) + return XFA_EVENTERROR_Disabled; + + CXFA_EventParam EventParam; + EventParam.m_eType = XFA_EVENT_Calculate; + int32_t iRet = ExecuteScript(docView, calc->GetScriptIfExists(), &EventParam); + if (iRet != XFA_EVENTERROR_Success) + return iRet; + + if (GetRawValue() != EventParam.m_wsResult) { + GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, EventParam.m_wsResult); + GetWidgetAcc()->UpdateUIDisplay(docView, nullptr); } - wsValue = CFX_WideStringC((const FX_WCHAR*)pValue, iBytes / sizeof(FX_WCHAR)); - return true; + return XFA_EVENTERROR_Success; } -void CXFA_Node::SetMapModuleBuffer( - void* pKey, - void* pValue, - int32_t iBytes, - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) { - XFA_MAPMODULEDATA* pModule = CreateMapModuleData(); - XFA_MAPDATABLOCK*& pBuffer = pModule->m_BufferMap[pKey]; - if (!pBuffer) { - pBuffer = - (XFA_MAPDATABLOCK*)FX_Alloc(uint8_t, sizeof(XFA_MAPDATABLOCK) + iBytes); - } else if (pBuffer->iBytes != iBytes) { - if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) { - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - } - pBuffer = (XFA_MAPDATABLOCK*)FX_Realloc(uint8_t, pBuffer, - sizeof(XFA_MAPDATABLOCK) + iBytes); - } else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) { - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - } - if (!pBuffer) +void CXFA_Node::ProcessScriptTestValidate(CXFA_FFDocView* docView, + CXFA_Validate* validate, + int32_t iRet, + bool bRetValue, + bool bVersionFlag) { + if (iRet != XFA_EVENTERROR_Success) + return; + if (bRetValue) return; - pBuffer->pCallbackInfo = pCallbackInfo; - pBuffer->iBytes = iBytes; - FXSYS_memcpy(pBuffer->GetData(), pValue, iBytes); -} - -bool CXFA_Node::GetMapModuleBuffer(void* pKey, - void*& pValue, - int32_t& iBytes, - bool bProtoAlso) const { - XFA_MAPDATABLOCK* pBuffer = nullptr; - for (const CXFA_Node* pNode = this; pNode; pNode = pNode->GetTemplateNode()) { - XFA_MAPMODULEDATA* pModule = pNode->GetMapModuleData(); - if (pModule) { - auto it = pModule->m_BufferMap.find(pKey); - if (it != pModule->m_BufferMap.end()) { - pBuffer = it->second; - break; - } + IXFA_AppProvider* pAppProvider = + docView->GetDoc()->GetApp()->GetAppProvider(); + if (!pAppProvider) + return; + + WideString wsTitle = pAppProvider->GetAppTitle(); + WideString wsScriptMsg = validate->GetScriptMessageText(); + if (validate->GetScriptTest() == XFA_AttributeEnum::Warning) { + if (IsUserInteractive()) + return; + if (wsScriptMsg.IsEmpty()) + wsScriptMsg = GetValidateMessage(false, bVersionFlag); + + if (bVersionFlag) { + pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, XFA_MB_OK); + return; } - if (!bProtoAlso || pNode->GetPacketID() == XFA_XDPPACKET_Datasets) - break; + if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_YesNo) == XFA_IDYes) { + SetFlag(XFA_NodeFlag_UserInteractive, false); + } + return; } - if (!pBuffer) - return false; - pValue = pBuffer->GetData(); - iBytes = pBuffer->iBytes; - return true; + if (wsScriptMsg.IsEmpty()) + wsScriptMsg = GetValidateMessage(true, bVersionFlag); + pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); } -bool CXFA_Node::HasMapModuleKey(void* pKey, bool bProtoAlso) { - for (CXFA_Node* pNode = this; pNode; pNode = pNode->GetTemplateNode()) { - XFA_MAPMODULEDATA* pModule = pNode->GetMapModuleData(); - if (pModule) { - auto it1 = pModule->m_ValueMap.find(pKey); - if (it1 != pModule->m_ValueMap.end()) - return true; +int32_t CXFA_Node::ProcessFormatTestValidate(CXFA_FFDocView* docView, + CXFA_Validate* validate, + bool bVersionFlag) { + WideString wsRawValue = GetRawValue(); + if (!wsRawValue.IsEmpty()) { + WideString wsPicture = validate->GetPicture(); + if (wsPicture.IsEmpty()) + return XFA_EVENTERROR_NotExist; - auto it2 = pModule->m_BufferMap.find(pKey); - if (it2 != pModule->m_BufferMap.end()) - return true; + IFX_Locale* pLocale = GetLocale(); + if (!pLocale) + return XFA_EVENTERROR_NotExist; + + CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this); + if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale, + nullptr)) { + IXFA_AppProvider* pAppProvider = + docView->GetDoc()->GetApp()->GetAppProvider(); + if (!pAppProvider) + return XFA_EVENTERROR_NotExist; + + WideString wsFormatMsg = validate->GetFormatMessageText(); + WideString wsTitle = pAppProvider->GetAppTitle(); + if (validate->GetFormatTest() == XFA_AttributeEnum::Error) { + if (wsFormatMsg.IsEmpty()) + wsFormatMsg = GetValidateMessage(true, bVersionFlag); + pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK); + return XFA_EVENTERROR_Success; + } + if (IsUserInteractive()) + return XFA_EVENTERROR_NotExist; + if (wsFormatMsg.IsEmpty()) + wsFormatMsg = GetValidateMessage(false, bVersionFlag); + + if (bVersionFlag) { + pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_OK); + return XFA_EVENTERROR_Success; + } + if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_YesNo) == XFA_IDYes) { + SetFlag(XFA_NodeFlag_UserInteractive, false); + } + return XFA_EVENTERROR_Success; } - if (!bProtoAlso || pNode->GetPacketID() == XFA_XDPPACKET_Datasets) - break; } - return false; + return XFA_EVENTERROR_NotExist; } -void CXFA_Node::RemoveMapModuleKey(void* pKey) { - XFA_MAPMODULEDATA* pModule = GetMapModuleData(); - if (!pModule) - return; +int32_t CXFA_Node::ProcessNullTestValidate(CXFA_FFDocView* docView, + CXFA_Validate* validate, + int32_t iFlags, + bool bVersionFlag) { + if (!GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw).IsEmpty()) + return XFA_EVENTERROR_Success; + if (GetWidgetAcc()->IsNull() && GetWidgetAcc()->IsPreNull()) + return XFA_EVENTERROR_Success; + + XFA_AttributeEnum eNullTest = validate->GetNullTest(); + WideString wsNullMsg = validate->GetNullMessageText(); + if (iFlags & 0x01) { + int32_t iRet = XFA_EVENTERROR_Success; + if (eNullTest != XFA_AttributeEnum::Disabled) + iRet = XFA_EVENTERROR_Error; - if (pKey) { - auto it = pModule->m_BufferMap.find(pKey); - if (it != pModule->m_BufferMap.end()) { - XFA_MAPDATABLOCK* pBuffer = it->second; - if (pBuffer) { - if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - FX_Free(pBuffer); + if (!wsNullMsg.IsEmpty()) { + if (eNullTest != XFA_AttributeEnum::Disabled) { + docView->m_arrNullTestMsg.push_back(wsNullMsg); + return XFA_EVENTERROR_Error; } - pModule->m_BufferMap.erase(it); + return XFA_EVENTERROR_Success; } - pModule->m_ValueMap.erase(pKey); - return; + return iRet; } - - for (auto& pair : pModule->m_BufferMap) { - XFA_MAPDATABLOCK* pBuffer = pair.second; - if (pBuffer) { - if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - FX_Free(pBuffer); - } + if (wsNullMsg.IsEmpty() && bVersionFlag && + eNullTest != XFA_AttributeEnum::Disabled) { + return XFA_EVENTERROR_Error; } - pModule->m_BufferMap.clear(); - pModule->m_ValueMap.clear(); - delete pModule; -} + IXFA_AppProvider* pAppProvider = + docView->GetDoc()->GetApp()->GetAppProvider(); + if (!pAppProvider) + return XFA_EVENTERROR_NotExist; -void CXFA_Node::MergeAllData(void* pDstModule) { - XFA_MAPMODULEDATA* pDstModuleData = - static_cast<CXFA_Node*>(pDstModule)->CreateMapModuleData(); - XFA_MAPMODULEDATA* pSrcModuleData = GetMapModuleData(); - if (!pSrcModuleData) - return; + WideString wsCaptionName; + WideString wsTitle = pAppProvider->GetAppTitle(); + switch (eNullTest) { + case XFA_AttributeEnum::Error: { + if (wsNullMsg.IsEmpty()) { + wsCaptionName = GetValidateCaptionName(bVersionFlag); + wsNullMsg = + WideString::Format(L"%ls cannot be blank.", wsCaptionName.c_str()); + } + pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK); + return XFA_EVENTERROR_Error; + } + case XFA_AttributeEnum::Warning: { + if (IsUserInteractive()) + return true; - for (const auto& pair : pSrcModuleData->m_ValueMap) - pDstModuleData->m_ValueMap[pair.first] = pair.second; - - for (const auto& pair : pSrcModuleData->m_BufferMap) { - XFA_MAPDATABLOCK* pSrcBuffer = pair.second; - XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first]; - if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree && - !pSrcBuffer->pCallbackInfo->pCopy) { - if (pDstBuffer) { - pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); - pDstModuleData->m_BufferMap.erase(pair.first); + if (wsNullMsg.IsEmpty()) { + wsCaptionName = GetValidateCaptionName(bVersionFlag); + wsNullMsg = WideString::Format( + L"%ls cannot be blank. To ignore validations for %ls, click " + L"Ignore.", + wsCaptionName.c_str(), wsCaptionName.c_str()); } - continue; - } - if (!pDstBuffer) { - pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc( - uint8_t, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes); - } else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) { - if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) { - pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); + if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning, + XFA_MB_YesNo) == XFA_IDYes) { + SetFlag(XFA_NodeFlag_UserInteractive, false); } - pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc( - uint8_t, pDstBuffer, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes); - } else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) { - pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); - } - if (!pDstBuffer) { - continue; - } - pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo; - pDstBuffer->iBytes = pSrcBuffer->iBytes; - FXSYS_memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), - pSrcBuffer->iBytes); - if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) { - pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData()); + return XFA_EVENTERROR_Error; } + case XFA_AttributeEnum::Disabled: + default: + break; } + return XFA_EVENTERROR_Success; } -void CXFA_Node::MoveBufferMapData(CXFA_Node* pDstModule, void* pKey) { - if (!pDstModule) { - return; - } - bool bNeedMove = true; - if (!pKey) { - bNeedMove = false; - } - if (pDstModule->GetElementType() != GetElementType()) { - bNeedMove = false; - } - XFA_MAPMODULEDATA* pSrcModuleData = nullptr; - XFA_MAPMODULEDATA* pDstModuleData = nullptr; - if (bNeedMove) { - pSrcModuleData = GetMapModuleData(); - if (!pSrcModuleData) { - bNeedMove = false; +int32_t CXFA_Node::ProcessValidate(CXFA_FFDocView* docView, int32_t iFlags) { + if (GetElementType() == XFA_Element::Draw) + return XFA_EVENTERROR_NotExist; + + CXFA_Validate* validate = GetValidateIfExists(); + if (!validate) + return XFA_EVENTERROR_NotExist; + + bool bInitDoc = validate->NeedsInitApp(); + bool bStatus = docView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End; + int32_t iFormat = 0; + int32_t iRet = XFA_EVENTERROR_NotExist; + CXFA_Script* script = validate->GetScriptIfExists(); + bool bRet = false; + bool hasBoolResult = (bInitDoc || bStatus) && GetRawValue().IsEmpty(); + if (script) { + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_Validate; + eParam.m_pTarget = GetWidgetAcc(); + std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, &eParam); + } + + XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode(); + bool bVersionFlag = false; + if (version < XFA_VERSION_208) + bVersionFlag = true; + + if (bInitDoc) { + validate->ClearFlag(XFA_NodeFlag_NeedsInitApp); + } else { + iFormat = ProcessFormatTestValidate(docView, validate, bVersionFlag); + if (!bVersionFlag) { + bVersionFlag = + docView->GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting); } - pDstModuleData = pDstModule->CreateMapModuleData(); + + iRet |= ProcessNullTestValidate(docView, validate, iFlags, bVersionFlag); } - if (bNeedMove) { - auto it = pSrcModuleData->m_BufferMap.find(pKey); - if (it != pSrcModuleData->m_BufferMap.end()) { - XFA_MAPDATABLOCK* pBufferBlockData = it->second; - if (pBufferBlockData) { - pSrcModuleData->m_BufferMap.erase(pKey); - pDstModuleData->m_BufferMap[pKey] = pBufferBlockData; + + if (iFormat != XFA_EVENTERROR_Success && hasBoolResult) + ProcessScriptTestValidate(docView, validate, iRet, bRet, bVersionFlag); + + return iRet | iFormat; +} + +WideString CXFA_Node::GetValidateCaptionName(bool bVersionFlag) { + WideString wsCaptionName; + + if (!bVersionFlag) { + CXFA_Caption* caption = GetCaptionIfExists(); + if (caption) { + CXFA_Value* capValue = caption->GetValueIfExists(); + if (capValue) { + CXFA_Text* captionText = capValue->GetTextIfExists(); + if (captionText) + wsCaptionName = captionText->GetContent(); } } } - if (pDstModule->IsNodeV()) { - CFX_WideString wsValue = pDstModule->GetScriptContent(false); - CFX_WideString wsFormatValue(wsValue); - CXFA_WidgetData* pWidgetData = pDstModule->GetContainerWidgetData(); - if (pWidgetData) { - pWidgetData->GetFormatDataValue(wsValue, wsFormatValue); + if (!wsCaptionName.IsEmpty()) + return wsCaptionName; + return JSObject()->GetCData(XFA_Attribute::Name); +} + +WideString CXFA_Node::GetValidateMessage(bool bError, bool bVersionFlag) { + WideString wsCaptionName = GetValidateCaptionName(bVersionFlag); + if (bVersionFlag) + return WideString::Format(L"%ls validation failed", wsCaptionName.c_str()); + if (bError) { + return WideString::Format(L"The value you entered for %ls is invalid.", + wsCaptionName.c_str()); + } + return WideString::Format( + L"The value you entered for %ls is invalid. To ignore " + L"validations for %ls, click Ignore.", + wsCaptionName.c_str(), wsCaptionName.c_str()); +} + +int32_t CXFA_Node::ExecuteScript(CXFA_FFDocView* docView, + CXFA_Script* script, + CXFA_EventParam* pEventParam) { + bool bRet; + int32_t iRet; + std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, pEventParam); + return iRet; +} + +std::pair<int32_t, bool> CXFA_Node::ExecuteBoolScript( + CXFA_FFDocView* docView, + CXFA_Script* script, + CXFA_EventParam* pEventParam) { + if (m_ExecuteRecursionDepth > kMaxExecuteRecursion) + return {XFA_EVENTERROR_Success, false}; + + ASSERT(pEventParam); + if (!script) + return {XFA_EVENTERROR_NotExist, false}; + if (script->GetRunAt() == XFA_AttributeEnum::Server) + return {XFA_EVENTERROR_Disabled, false}; + + WideString wsExpression = script->GetExpression(); + if (wsExpression.IsEmpty()) + return {XFA_EVENTERROR_NotExist, false}; + + CXFA_Script::Type eScriptType = script->GetContentType(); + if (eScriptType == CXFA_Script::Type::Unknown) + return {XFA_EVENTERROR_Success, false}; + + CXFA_FFDoc* pDoc = docView->GetDoc(); + CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext(); + pContext->SetEventParam(*pEventParam); + pContext->SetRunAtType(script->GetRunAt()); + + std::vector<CXFA_Node*> refNodes; + if (pEventParam->m_eType == XFA_EVENT_InitCalculate || + pEventParam->m_eType == XFA_EVENT_Calculate) { + pContext->SetNodesOfRunScript(&refNodes); + } + + auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetIsolate()); + bool bRet = false; + { + AutoRestorer<uint8_t> restorer(&m_ExecuteRecursionDepth); + ++m_ExecuteRecursionDepth; + bRet = pContext->RunScript(eScriptType, wsExpression.AsStringView(), + pTmpRetValue.get(), this); + } + + int32_t iRet = XFA_EVENTERROR_Error; + if (bRet) { + iRet = XFA_EVENTERROR_Success; + if (pEventParam->m_eType == XFA_EVENT_Calculate || + pEventParam->m_eType == XFA_EVENT_InitCalculate) { + if (!pTmpRetValue->IsUndefined()) { + if (!pTmpRetValue->IsNull()) + pEventParam->m_wsResult = pTmpRetValue->ToWideString(); + + iRet = XFA_EVENTERROR_Success; + } else { + iRet = XFA_EVENTERROR_Error; + } + if (pEventParam->m_eType == XFA_EVENT_InitCalculate) { + if ((iRet == XFA_EVENTERROR_Success) && + (GetRawValue() != pEventParam->m_wsResult)) { + GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, + pEventParam->m_wsResult); + docView->AddValidateWidget(GetWidgetAcc()); + } + } + for (CXFA_Node* pRefNode : refNodes) { + if (pRefNode == this) + continue; + + CXFA_CalcData* pGlobalData = pRefNode->JSObject()->GetCalcData(); + if (!pGlobalData) { + pRefNode->JSObject()->SetCalcData( + pdfium::MakeUnique<CXFA_CalcData>()); + pGlobalData = pRefNode->JSObject()->GetCalcData(); + } + if (!pdfium::ContainsValue(pGlobalData->m_Globals, this)) + pGlobalData->m_Globals.push_back(this); + } } - pDstModule->SetScriptContent(wsValue, wsFormatValue, true, true); } + pContext->SetNodesOfRunScript(nullptr); + + return {iRet, pTmpRetValue->IsBoolean() ? pTmpRetValue->ToBoolean() : false}; } -void CXFA_Node::MoveBufferMapData(CXFA_Node* pSrcModule, - CXFA_Node* pDstModule, - void* pKey, - bool bRecursive) { - if (!pSrcModule || !pDstModule || !pKey) { - return; +WideString CXFA_Node::GetBarcodeType() { + CXFA_Node* pUIChild = GetWidgetAcc()->GetUIChild(); + return pUIChild + ? WideString(pUIChild->JSObject()->GetCData(XFA_Attribute::Type)) + : WideString(); +} + +Optional<BC_CHAR_ENCODING> CXFA_Node::GetBarcodeAttribute_CharEncoding() { + Optional<WideString> wsCharEncoding = + GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( + XFA_Attribute::CharEncoding, true); + if (!wsCharEncoding) + return {}; + if (wsCharEncoding->CompareNoCase(L"UTF-16")) + return {CHAR_ENCODING_UNICODE}; + if (wsCharEncoding->CompareNoCase(L"UTF-8")) + return {CHAR_ENCODING_UTF8}; + return {}; +} + +Optional<bool> CXFA_Node::GetBarcodeAttribute_Checksum() { + Optional<XFA_AttributeEnum> checksum = + GetWidgetAcc()->GetUIChild()->JSObject()->TryEnum(XFA_Attribute::Checksum, + true); + if (!checksum) + return {}; + + switch (*checksum) { + case XFA_AttributeEnum::None: + return {false}; + case XFA_AttributeEnum::Auto: + return {true}; + case XFA_AttributeEnum::Checksum_1mod10: + case XFA_AttributeEnum::Checksum_1mod10_1mod11: + case XFA_AttributeEnum::Checksum_2mod10: + default: + break; } - if (bRecursive) { - CXFA_Node* pSrcChild = pSrcModule->GetNodeItem(XFA_NODEITEM_FirstChild); - CXFA_Node* pDstChild = pDstModule->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pSrcChild && pDstChild; - pSrcChild = pSrcChild->GetNodeItem(XFA_NODEITEM_NextSibling), - pDstChild = pDstChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { - MoveBufferMapData(pSrcChild, pDstChild, pKey, true); - } + return {}; +} + +Optional<int32_t> CXFA_Node::GetBarcodeAttribute_DataLength() { + Optional<WideString> wsDataLength = + GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( + XFA_Attribute::DataLength, true); + if (!wsDataLength) + return {}; + + return {FXSYS_wtoi(wsDataLength->c_str())}; +} + +Optional<char> CXFA_Node::GetBarcodeAttribute_StartChar() { + Optional<WideString> wsStartEndChar = + GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( + XFA_Attribute::StartChar, true); + if (!wsStartEndChar || wsStartEndChar->IsEmpty()) + return {}; + + return {static_cast<char>((*wsStartEndChar)[0])}; +} + +Optional<char> CXFA_Node::GetBarcodeAttribute_EndChar() { + Optional<WideString> wsStartEndChar = + GetWidgetAcc()->GetUIChild()->JSObject()->TryCData(XFA_Attribute::EndChar, + true); + if (!wsStartEndChar || wsStartEndChar->IsEmpty()) + return {}; + + return {static_cast<char>((*wsStartEndChar)[0])}; +} + +Optional<int32_t> CXFA_Node::GetBarcodeAttribute_ECLevel() { + Optional<WideString> wsECLevel = + GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( + XFA_Attribute::ErrorCorrectionLevel, true); + if (!wsECLevel) + return {}; + return {FXSYS_wtoi(wsECLevel->c_str())}; +} + +Optional<int32_t> CXFA_Node::GetBarcodeAttribute_ModuleWidth() { + Optional<CXFA_Measurement> moduleWidthHeight = + GetWidgetAcc()->GetUIChild()->JSObject()->TryMeasure( + XFA_Attribute::ModuleWidth, true); + if (!moduleWidthHeight) + return {}; + + return {static_cast<int32_t>(moduleWidthHeight->ToUnit(XFA_Unit::Pt))}; +} + +Optional<int32_t> CXFA_Node::GetBarcodeAttribute_ModuleHeight() { + Optional<CXFA_Measurement> moduleWidthHeight = + GetWidgetAcc()->GetUIChild()->JSObject()->TryMeasure( + XFA_Attribute::ModuleHeight, true); + if (!moduleWidthHeight) + return {}; + + return {static_cast<int32_t>(moduleWidthHeight->ToUnit(XFA_Unit::Pt))}; +} + +Optional<bool> CXFA_Node::GetBarcodeAttribute_PrintChecksum() { + return GetWidgetAcc()->GetUIChild()->JSObject()->TryBoolean( + XFA_Attribute::PrintCheckDigit, true); +} + +Optional<BC_TEXT_LOC> CXFA_Node::GetBarcodeAttribute_TextLocation() { + Optional<XFA_AttributeEnum> textLocation = + GetWidgetAcc()->GetUIChild()->JSObject()->TryEnum( + XFA_Attribute::TextLocation, true); + if (!textLocation) + return {}; + + switch (*textLocation) { + case XFA_AttributeEnum::None: + return {BC_TEXT_LOC_NONE}; + case XFA_AttributeEnum::Above: + return {BC_TEXT_LOC_ABOVE}; + case XFA_AttributeEnum::Below: + return {BC_TEXT_LOC_BELOW}; + case XFA_AttributeEnum::AboveEmbedded: + return {BC_TEXT_LOC_ABOVEEMBED}; + case XFA_AttributeEnum::BelowEmbedded: + return {BC_TEXT_LOC_BELOWEMBED}; + default: + break; } - pSrcModule->MoveBufferMapData(pDstModule, pKey); + return {}; } -void CXFA_Node::ThrowMissingPropertyException( - const CFX_WideString& obj, - const CFX_WideString& prop) const { - ThrowException(L"'%s' doesn't have property '%s'.", obj.c_str(), - prop.c_str()); +Optional<bool> CXFA_Node::GetBarcodeAttribute_Truncate() { + return GetWidgetAcc()->GetUIChild()->JSObject()->TryBoolean( + XFA_Attribute::Truncate, true); } -void CXFA_Node::ThrowTooManyOccurancesException( - const CFX_WideString& obj) const { - ThrowException( - L"The element [%s] has violated its allowable number of occurrences.", - obj.c_str()); +Optional<int8_t> CXFA_Node::GetBarcodeAttribute_WideNarrowRatio() { + Optional<WideString> wsWideNarrowRatio = + GetWidgetAcc()->GetUIChild()->JSObject()->TryCData( + XFA_Attribute::WideNarrowRatio, true); + if (!wsWideNarrowRatio) + return {}; + + Optional<size_t> ptPos = wsWideNarrowRatio->Find(':'); + if (!ptPos) + return {static_cast<int8_t>(FXSYS_wtoi(wsWideNarrowRatio->c_str()))}; + + int32_t fB = FXSYS_wtoi( + wsWideNarrowRatio->Right(wsWideNarrowRatio->GetLength() - (*ptPos + 1)) + .c_str()); + if (!fB) + return {0}; + + int32_t fA = FXSYS_wtoi(wsWideNarrowRatio->Left(*ptPos).c_str()); + float result = static_cast<float>(fA) / static_cast<float>(fB); + return {static_cast<int8_t>(result)}; } diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h new file mode 100644 index 0000000000000000000000000000000000000000..c08a9affddc0020df355aa4bfe7c45affcec79c4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_node.h @@ -0,0 +1,362 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NODE_H_ +#define XFA_FXFA_PARSER_CXFA_NODE_H_ + +#include <map> +#include <memory> +#include <utility> +#include <vector> + +#include "core/fxcrt/fx_string.h" +#include "core/fxge/fx_dib.h" +#include "fxbarcode/BC_Library.h" +#include "third_party/base/optional.h" +#include "xfa/fxfa/parser/cxfa_object.h" + +class CFX_XMLNode; +class CXFA_Bind; +class CXFA_Border; +class CXFA_Calculate; +class CXFA_Caption; +class CXFA_Event; +class CXFA_EventParam; +class CXFA_FFDocView; +class CXFA_Font; +class CXFA_Margin; +class CXFA_Occur; +class CXFA_Para; +class CXFA_Script; +class CXFA_Validate; +class CXFA_Value; +class CXFA_WidgetAcc; +class IFX_Locale; + +#define XFA_NODEFILTER_Children 0x01 +#define XFA_NODEFILTER_Properties 0x02 +#define XFA_NODEFILTER_OneOfProperty 0x04 + +enum XFA_NodeFlag { + XFA_NodeFlag_None = 0, + XFA_NodeFlag_Initialized = 1 << 0, + XFA_NodeFlag_HasRemovedChildren = 1 << 1, + XFA_NodeFlag_NeedsInitApp = 1 << 2, + XFA_NodeFlag_BindFormItems = 1 << 3, + XFA_NodeFlag_UserInteractive = 1 << 4, + XFA_NodeFlag_SkipDataBinding = 1 << 5, + XFA_NodeFlag_OwnXMLNode = 1 << 6, + XFA_NodeFlag_UnusedNode = 1 << 7, + XFA_NodeFlag_LayoutGeneratedNode = 1 << 8 +}; + +class CXFA_Node : public CXFA_Object { + public: + struct PropertyData { + XFA_Element property; + uint8_t occurance_count; + uint8_t flags; + }; + + struct AttributeData { + XFA_Attribute attribute; + XFA_AttributeType type; + void* default_value; + }; + +#ifndef NDEBUG + static WideString ElementToName(XFA_Element elem); +#endif // NDEBUG + + static WideString AttributeEnumToName(XFA_AttributeEnum item); + static Optional<XFA_AttributeEnum> NameToAttributeEnum( + const WideStringView& name); + static XFA_Attribute NameToAttribute(const WideStringView& name); + static WideString AttributeToName(XFA_Attribute attr); + static XFA_Element NameToElement(const WideString& name); + static std::unique_ptr<CXFA_Node> Create(CXFA_Document* doc, + XFA_Element element, + XFA_PacketType packet); + + ~CXFA_Node() override; + + bool IsValidInPacket(XFA_PacketType packet) const; + + bool HasProperty(XFA_Element property) const; + bool HasPropertyFlags(XFA_Element property, uint8_t flags) const; + uint8_t PropertyOccuranceCount(XFA_Element property) const; + + void SendAttributeChangeMessage(XFA_Attribute eAttribute, bool bScriptModify); + + bool HasAttribute(XFA_Attribute attr) const; + XFA_Attribute GetAttribute(size_t i) const; + XFA_AttributeType GetAttributeType(XFA_Attribute type) const; + + XFA_PacketType GetPacketType() const { return m_ePacket; } + + void SetFlag(uint32_t dwFlag, bool bNotify); + void ClearFlag(uint32_t dwFlag); + + CXFA_Node* CreateInstanceIfPossible(bool bDataMerge); + int32_t GetCount(); + CXFA_Node* GetItemIfExists(int32_t iIndex); + void RemoveItem(CXFA_Node* pRemoveInstance, bool bRemoveDataBinding); + void InsertItem(CXFA_Node* pNewInstance, + int32_t iPos, + int32_t iCount, + bool bMoveDataBindingNodes); + + bool IsInitialized() const { return HasFlag(XFA_NodeFlag_Initialized); } + bool IsOwnXMLNode() const { return HasFlag(XFA_NodeFlag_OwnXMLNode); } + bool IsUserInteractive() const { + return HasFlag(XFA_NodeFlag_UserInteractive); + } + bool IsUnusedNode() const { return HasFlag(XFA_NodeFlag_UnusedNode); } + bool IsLayoutGeneratedNode() const { + return HasFlag(XFA_NodeFlag_LayoutGeneratedNode); + } + + void SetBindingNodes(std::vector<UnownedPtr<CXFA_Node>> nodes) { + binding_nodes_ = std::move(nodes); + } + std::vector<UnownedPtr<CXFA_Node>>* GetBindingNodes() { + return &binding_nodes_; + } + void SetBindingNode(CXFA_Node* node) { + binding_nodes_.clear(); + if (node) + binding_nodes_.emplace_back(node); + } + CXFA_Node* GetBindingNode() const { + if (binding_nodes_.empty()) + return nullptr; + return binding_nodes_[0].Get(); + } + // TODO(dsinclair): This should not be needed. Nodes should get un-bound when + // they're deleted instead of us pointing to bad objects. + void ReleaseBindingNodes(); + + bool BindsFormItems() const { return HasFlag(XFA_NodeFlag_BindFormItems); } + bool HasRemovedChildren() const { + return HasFlag(XFA_NodeFlag_HasRemovedChildren); + } + bool NeedsInitApp() const { return HasFlag(XFA_NodeFlag_NeedsInitApp); } + + bool IsAttributeInXML(); + bool IsFormContainer() const { + return m_ePacket == XFA_PacketType::Form && IsContainerNode(); + } + void SetXMLMappingNode(CFX_XMLNode* pXMLNode) { m_pXMLNode = pXMLNode; } + CFX_XMLNode* GetXMLMappingNode() const { return m_pXMLNode; } + CFX_XMLNode* CreateXMLMappingNode(); + bool IsNeedSavingXMLNode(); + uint32_t GetNameHash() const { return m_dwNameHash; } + bool IsUnnamed() const { return m_dwNameHash == 0; } + CXFA_Node* GetModelNode(); + void UpdateNameHash(); + + size_t CountChildren(XFA_Element eType, bool bOnlyChild); + + template <typename T> + T* GetChild(size_t index, XFA_Element eType, bool bOnlyChild) { + return static_cast<T*>(GetChildInternal(index, eType, bOnlyChild)); + } + + int32_t InsertChild(int32_t index, CXFA_Node* pNode); + bool InsertChild(CXFA_Node* pNode, CXFA_Node* pBeforeNode); + bool RemoveChild(CXFA_Node* pNode, bool bNotify); + + CXFA_Node* Clone(bool bRecursive); + + CXFA_Node* GetNextSibling() const { return m_pNext; } + CXFA_Node* GetPrevSibling() const; + CXFA_Node* GetFirstChild() const { return m_pChild; } + CXFA_Node* GetParent() const { return m_pParent; } + + CXFA_Node* GetNextContainerSibling() const; + CXFA_Node* GetPrevContainerSibling() const; + CXFA_Node* GetFirstContainerChild() const; + CXFA_Node* GetContainerParent() const; + + std::vector<CXFA_Node*> GetNodeList(uint32_t dwTypeFilter, + XFA_Element eTypeFilter); + CXFA_Node* CreateSamePacketNode(XFA_Element eType); + CXFA_Node* CloneTemplateToForm(bool bRecursive); + CXFA_Node* GetTemplateNodeIfExists() const; + void SetTemplateNode(CXFA_Node* pTemplateNode); + CXFA_Node* GetDataDescriptionNode(); + void SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode); + CXFA_Node* GetBindData(); + std::vector<UnownedPtr<CXFA_Node>>* GetBindItems(); + int32_t AddBindItem(CXFA_Node* pFormNode); + int32_t RemoveBindItem(CXFA_Node* pFormNode); + bool HasBindItem(); + CXFA_WidgetAcc* GetContainerWidgetAcc(); + IFX_Locale* GetLocale(); + Optional<WideString> GetLocaleName(); + XFA_AttributeEnum GetIntact(); + + CXFA_Node* GetFirstChildByName(const WideStringView& wsNodeName) const; + CXFA_Node* GetFirstChildByName(uint32_t dwNodeNameHash) const; + template <typename T> + T* GetFirstChildByClass(XFA_Element eType) const { + return static_cast<T*>(GetFirstChildByClassInternal(eType)); + } + CXFA_Node* GetNextSameNameSibling(uint32_t dwNodeNameHash) const; + template <typename T> + T* GetNextSameNameSibling(const WideStringView& wsNodeName) const { + return static_cast<T*>(GetNextSameNameSiblingInternal(wsNodeName)); + } + template <typename T> + T* GetNextSameClassSibling(XFA_Element eType) const { + return static_cast<T*>(GetNextSameClassSiblingInternal(eType)); + } + + int32_t GetNodeSameNameIndex() const; + int32_t GetNodeSameClassIndex() const; + CXFA_Node* GetInstanceMgrOfSubform(); + + CXFA_Occur* GetOccurIfExists(); + + Optional<bool> GetDefaultBoolean(XFA_Attribute attr) const; + Optional<int32_t> GetDefaultInteger(XFA_Attribute attr) const; + Optional<CXFA_Measurement> GetDefaultMeasurement(XFA_Attribute attr) const; + Optional<WideString> GetDefaultCData(XFA_Attribute attr) const; + Optional<XFA_AttributeEnum> GetDefaultEnum(XFA_Attribute attr) const; + + void SyncValue(const WideString& wsValue, bool bNotify); + + bool IsOpenAccess(); + + CXFA_Border* GetBorderIfExists() const; + CXFA_Border* GetOrCreateBorderIfPossible(); + CXFA_Caption* GetCaptionIfExists() const; + + CXFA_Font* GetFontIfExists() const; + CXFA_Font* GetOrCreateFontIfPossible(); + float GetFontSize() const; + FX_ARGB GetTextColor() const; + float GetLineHeight() const; + + CXFA_Margin* GetMarginIfExists() const; + CXFA_Para* GetParaIfExists() const; + CXFA_Calculate* GetCalculateIfExists() const; + CXFA_Validate* GetValidateIfExists() const; + CXFA_Validate* GetOrCreateValidateIfPossible(); + + CXFA_Value* GetDefaultValueIfExists(); + CXFA_Value* GetFormValueIfExists() const; + WideString GetRawValue(); + int32_t GetRotate(); + + CXFA_Bind* GetBindIfExists() const; + + Optional<float> TryWidth(); + Optional<float> TryHeight(); + Optional<float> TryMinWidth(); + Optional<float> TryMinHeight(); + Optional<float> TryMaxWidth(); + Optional<float> TryMaxHeight(); + + CXFA_Node* GetExclGroupIfExists(); + + int32_t ProcessEvent(CXFA_FFDocView* docView, + XFA_AttributeEnum iActivity, + CXFA_EventParam* pEventParam); + int32_t ProcessEvent(CXFA_FFDocView* docView, + CXFA_Event* event, + CXFA_EventParam* pEventParam); + int32_t ProcessCalculate(CXFA_FFDocView* docView); + int32_t ProcessValidate(CXFA_FFDocView* docView, int32_t iFlags); + + int32_t ExecuteScript(CXFA_FFDocView* docView, + CXFA_Script* script, + CXFA_EventParam* pEventParam); + std::pair<int32_t, bool> ExecuteBoolScript(CXFA_FFDocView* docView, + CXFA_Script* script, + CXFA_EventParam* pEventParam); + + // TODO(dsinclair): Figure out how to move this to cxfa_barcode. + WideString GetBarcodeType(); + Optional<BC_CHAR_ENCODING> GetBarcodeAttribute_CharEncoding(); + Optional<bool> GetBarcodeAttribute_Checksum(); + Optional<int32_t> GetBarcodeAttribute_DataLength(); + Optional<char> GetBarcodeAttribute_StartChar(); + Optional<char> GetBarcodeAttribute_EndChar(); + Optional<int32_t> GetBarcodeAttribute_ECLevel(); + Optional<int32_t> GetBarcodeAttribute_ModuleWidth(); + Optional<int32_t> GetBarcodeAttribute_ModuleHeight(); + Optional<bool> GetBarcodeAttribute_PrintChecksum(); + Optional<BC_TEXT_LOC> GetBarcodeAttribute_TextLocation(); + Optional<bool> GetBarcodeAttribute_Truncate(); + Optional<int8_t> GetBarcodeAttribute_WideNarrowRatio(); + + protected: + CXFA_Node(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node); + CXFA_Node(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName); + + private: + void ProcessScriptTestValidate(CXFA_FFDocView* docView, + CXFA_Validate* validate, + int32_t iRet, + bool pRetValue, + bool bVersionFlag); + int32_t ProcessFormatTestValidate(CXFA_FFDocView* docView, + CXFA_Validate* validate, + bool bVersionFlag); + int32_t ProcessNullTestValidate(CXFA_FFDocView* docView, + CXFA_Validate* validate, + int32_t iFlags, + bool bVersionFlag); + WideString GetValidateCaptionName(bool bVersionFlag); + WideString GetValidateMessage(bool bError, bool bVersionFlag); + + bool HasFlag(XFA_NodeFlag dwFlag) const; + CXFA_Node* Deprecated_GetPrevSibling(); + const PropertyData* GetPropertyData(XFA_Element property) const; + const AttributeData* GetAttributeData(XFA_Attribute attr) const; + Optional<XFA_Element> GetFirstPropertyWithFlag(uint8_t flag); + void OnRemoved(bool bNotify); + Optional<void*> GetDefaultValue(XFA_Attribute attr, + XFA_AttributeType eType) const; + CXFA_Node* GetChildInternal(size_t index, XFA_Element eType, bool bOnlyChild); + CXFA_Node* GetFirstChildByClassInternal(XFA_Element eType) const; + CXFA_Node* GetNextSameNameSiblingInternal( + const WideStringView& wsNodeName) const; + CXFA_Node* GetNextSameClassSiblingInternal(XFA_Element eType) const; + + const PropertyData* const m_Properties; + const AttributeData* const m_Attributes; + const uint32_t m_ValidPackets; + CXFA_Node* m_pNext; + CXFA_Node* m_pChild; + CXFA_Node* m_pLastChild; + CXFA_Node* m_pParent; + CFX_XMLNode* m_pXMLNode; + const XFA_PacketType m_ePacket; + uint8_t m_ExecuteRecursionDepth = 0; + uint16_t m_uNodeFlags; + uint32_t m_dwNameHash; + CXFA_Node* m_pAuxNode; + std::vector<UnownedPtr<CXFA_Node>> binding_nodes_; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NODE_H_ diff --git a/xfa/fxfa/parser/cxfa_node_statics.cpp b/xfa/fxfa/parser/cxfa_node_statics.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93860c6a0a5dff08b2cead5f7be348e712339b95 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_node_statics.cpp @@ -0,0 +1,2948 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include <memory> + +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_accessiblecontent.h" +#include "xfa/fxfa/parser/cxfa_acrobat.h" +#include "xfa/fxfa/parser/cxfa_acrobat7.h" +#include "xfa/fxfa/parser/cxfa_adbe_jsconsole.h" +#include "xfa/fxfa/parser/cxfa_adbe_jsdebugger.h" +#include "xfa/fxfa/parser/cxfa_addsilentprint.h" +#include "xfa/fxfa/parser/cxfa_addviewerpreferences.h" +#include "xfa/fxfa/parser/cxfa_adjustdata.h" +#include "xfa/fxfa/parser/cxfa_adobeextensionlevel.h" +#include "xfa/fxfa/parser/cxfa_agent.h" +#include "xfa/fxfa/parser/cxfa_alwaysembed.h" +#include "xfa/fxfa/parser/cxfa_amd.h" +#include "xfa/fxfa/parser/cxfa_appearancefilter.h" +#include "xfa/fxfa/parser/cxfa_arc.h" +#include "xfa/fxfa/parser/cxfa_area.h" +#include "xfa/fxfa/parser/cxfa_assist.h" +#include "xfa/fxfa/parser/cxfa_attributes.h" +#include "xfa/fxfa/parser/cxfa_autosave.h" +#include "xfa/fxfa/parser/cxfa_barcode.h" +#include "xfa/fxfa/parser/cxfa_base.h" +#include "xfa/fxfa/parser/cxfa_batchoutput.h" +#include "xfa/fxfa/parser/cxfa_behavioroverride.h" +#include "xfa/fxfa/parser/cxfa_bind.h" +#include "xfa/fxfa/parser/cxfa_binditems.h" +#include "xfa/fxfa/parser/cxfa_bookend.h" +#include "xfa/fxfa/parser/cxfa_boolean.h" +#include "xfa/fxfa/parser/cxfa_border.h" +#include "xfa/fxfa/parser/cxfa_break.h" +#include "xfa/fxfa/parser/cxfa_breakafter.h" +#include "xfa/fxfa/parser/cxfa_breakbefore.h" +#include "xfa/fxfa/parser/cxfa_button.h" +#include "xfa/fxfa/parser/cxfa_cache.h" +#include "xfa/fxfa/parser/cxfa_calculate.h" +#include "xfa/fxfa/parser/cxfa_calendarsymbols.h" +#include "xfa/fxfa/parser/cxfa_caption.h" +#include "xfa/fxfa/parser/cxfa_certificate.h" +#include "xfa/fxfa/parser/cxfa_certificates.h" +#include "xfa/fxfa/parser/cxfa_change.h" +#include "xfa/fxfa/parser/cxfa_checkbutton.h" +#include "xfa/fxfa/parser/cxfa_choicelist.h" +#include "xfa/fxfa/parser/cxfa_color.h" +#include "xfa/fxfa/parser/cxfa_comb.h" +#include "xfa/fxfa/parser/cxfa_command.h" +#include "xfa/fxfa/parser/cxfa_common.h" +#include "xfa/fxfa/parser/cxfa_compress.h" +#include "xfa/fxfa/parser/cxfa_compression.h" +#include "xfa/fxfa/parser/cxfa_compresslogicalstructure.h" +#include "xfa/fxfa/parser/cxfa_compressobjectstream.h" +#include "xfa/fxfa/parser/cxfa_config.h" +#include "xfa/fxfa/parser/cxfa_conformance.h" +#include "xfa/fxfa/parser/cxfa_connect.h" +#include "xfa/fxfa/parser/cxfa_connectionset.h" +#include "xfa/fxfa/parser/cxfa_connectstring.h" +#include "xfa/fxfa/parser/cxfa_contentarea.h" +#include "xfa/fxfa/parser/cxfa_contentcopy.h" +#include "xfa/fxfa/parser/cxfa_copies.h" +#include "xfa/fxfa/parser/cxfa_corner.h" +#include "xfa/fxfa/parser/cxfa_creator.h" +#include "xfa/fxfa/parser/cxfa_currencysymbol.h" +#include "xfa/fxfa/parser/cxfa_currencysymbols.h" +#include "xfa/fxfa/parser/cxfa_currentpage.h" +#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_datagroup.h" +#include "xfa/fxfa/parser/cxfa_datamodel.h" +#include "xfa/fxfa/parser/cxfa_datavalue.h" +#include "xfa/fxfa/parser/cxfa_date.h" +#include "xfa/fxfa/parser/cxfa_datepattern.h" +#include "xfa/fxfa/parser/cxfa_datepatterns.h" +#include "xfa/fxfa/parser/cxfa_datetime.h" +#include "xfa/fxfa/parser/cxfa_datetimeedit.h" +#include "xfa/fxfa/parser/cxfa_datetimesymbols.h" +#include "xfa/fxfa/parser/cxfa_day.h" +#include "xfa/fxfa/parser/cxfa_daynames.h" +#include "xfa/fxfa/parser/cxfa_debug.h" +#include "xfa/fxfa/parser/cxfa_decimal.h" +#include "xfa/fxfa/parser/cxfa_defaulttypeface.h" +#include "xfa/fxfa/parser/cxfa_defaultui.h" +#include "xfa/fxfa/parser/cxfa_delete.h" +#include "xfa/fxfa/parser/cxfa_delta.h" +#include "xfa/fxfa/parser/cxfa_deltas.h" +#include "xfa/fxfa/parser/cxfa_desc.h" +#include "xfa/fxfa/parser/cxfa_destination.h" +#include "xfa/fxfa/parser/cxfa_digestmethod.h" +#include "xfa/fxfa/parser/cxfa_digestmethods.h" +#include "xfa/fxfa/parser/cxfa_documentassembly.h" +#include "xfa/fxfa/parser/cxfa_draw.h" +#include "xfa/fxfa/parser/cxfa_driver.h" +#include "xfa/fxfa/parser/cxfa_dsigdata.h" +#include "xfa/fxfa/parser/cxfa_duplexoption.h" +#include "xfa/fxfa/parser/cxfa_dynamicrender.h" +#include "xfa/fxfa/parser/cxfa_edge.h" +#include "xfa/fxfa/parser/cxfa_effectiveinputpolicy.h" +#include "xfa/fxfa/parser/cxfa_effectiveoutputpolicy.h" +#include "xfa/fxfa/parser/cxfa_embed.h" +#include "xfa/fxfa/parser/cxfa_encoding.h" +#include "xfa/fxfa/parser/cxfa_encodings.h" +#include "xfa/fxfa/parser/cxfa_encrypt.h" +#include "xfa/fxfa/parser/cxfa_encryption.h" +#include "xfa/fxfa/parser/cxfa_encryptionlevel.h" +#include "xfa/fxfa/parser/cxfa_encryptionmethod.h" +#include "xfa/fxfa/parser/cxfa_encryptionmethods.h" +#include "xfa/fxfa/parser/cxfa_enforce.h" +#include "xfa/fxfa/parser/cxfa_equate.h" +#include "xfa/fxfa/parser/cxfa_equaterange.h" +#include "xfa/fxfa/parser/cxfa_era.h" +#include "xfa/fxfa/parser/cxfa_eranames.h" +#include "xfa/fxfa/parser/cxfa_event.h" +#include "xfa/fxfa/parser/cxfa_exclgroup.h" +#include "xfa/fxfa/parser/cxfa_exclude.h" +#include "xfa/fxfa/parser/cxfa_excludens.h" +#include "xfa/fxfa/parser/cxfa_exdata.h" +#include "xfa/fxfa/parser/cxfa_execute.h" +#include "xfa/fxfa/parser/cxfa_exobject.h" +#include "xfa/fxfa/parser/cxfa_extras.h" +#include "xfa/fxfa/parser/cxfa_field.h" +#include "xfa/fxfa/parser/cxfa_fill.h" +#include "xfa/fxfa/parser/cxfa_filter.h" +#include "xfa/fxfa/parser/cxfa_fliplabel.h" +#include "xfa/fxfa/parser/cxfa_float.h" +#include "xfa/fxfa/parser/cxfa_font.h" +#include "xfa/fxfa/parser/cxfa_fontinfo.h" +#include "xfa/fxfa/parser/cxfa_form.h" +#include "xfa/fxfa/parser/cxfa_format.h" +#include "xfa/fxfa/parser/cxfa_formfieldfilling.h" +#include "xfa/fxfa/parser/cxfa_groupparent.h" +#include "xfa/fxfa/parser/cxfa_handler.h" +#include "xfa/fxfa/parser/cxfa_hyphenation.h" +#include "xfa/fxfa/parser/cxfa_ifempty.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_imageedit.h" +#include "xfa/fxfa/parser/cxfa_includexdpcontent.h" +#include "xfa/fxfa/parser/cxfa_incrementalload.h" +#include "xfa/fxfa/parser/cxfa_incrementalmerge.h" +#include "xfa/fxfa/parser/cxfa_insert.h" +#include "xfa/fxfa/parser/cxfa_instancemanager.h" +#include "xfa/fxfa/parser/cxfa_integer.h" +#include "xfa/fxfa/parser/cxfa_interactive.h" +#include "xfa/fxfa/parser/cxfa_issuers.h" +#include "xfa/fxfa/parser/cxfa_items.h" +#include "xfa/fxfa/parser/cxfa_jog.h" +#include "xfa/fxfa/parser/cxfa_keep.h" +#include "xfa/fxfa/parser/cxfa_keyusage.h" +#include "xfa/fxfa/parser/cxfa_labelprinter.h" +#include "xfa/fxfa/parser/cxfa_layout.h" +#include "xfa/fxfa/parser/cxfa_level.h" +#include "xfa/fxfa/parser/cxfa_line.h" +#include "xfa/fxfa/parser/cxfa_linear.h" +#include "xfa/fxfa/parser/cxfa_linearized.h" +#include "xfa/fxfa/parser/cxfa_locale.h" +#include "xfa/fxfa/parser/cxfa_localeset.h" +#include "xfa/fxfa/parser/cxfa_lockdocument.h" +#include "xfa/fxfa/parser/cxfa_log.h" +#include "xfa/fxfa/parser/cxfa_manifest.h" +#include "xfa/fxfa/parser/cxfa_map.h" +#include "xfa/fxfa/parser/cxfa_margin.h" +#include "xfa/fxfa/parser/cxfa_mdp.h" +#include "xfa/fxfa/parser/cxfa_medium.h" +#include "xfa/fxfa/parser/cxfa_mediuminfo.h" +#include "xfa/fxfa/parser/cxfa_meridiem.h" +#include "xfa/fxfa/parser/cxfa_meridiemnames.h" +#include "xfa/fxfa/parser/cxfa_message.h" +#include "xfa/fxfa/parser/cxfa_messaging.h" +#include "xfa/fxfa/parser/cxfa_mode.h" +#include "xfa/fxfa/parser/cxfa_modifyannots.h" +#include "xfa/fxfa/parser/cxfa_month.h" +#include "xfa/fxfa/parser/cxfa_monthnames.h" +#include "xfa/fxfa/parser/cxfa_msgid.h" +#include "xfa/fxfa/parser/cxfa_nameattr.h" +#include "xfa/fxfa/parser/cxfa_neverembed.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_numberofcopies.h" +#include "xfa/fxfa/parser/cxfa_numberpattern.h" +#include "xfa/fxfa/parser/cxfa_numberpatterns.h" +#include "xfa/fxfa/parser/cxfa_numbersymbol.h" +#include "xfa/fxfa/parser/cxfa_numbersymbols.h" +#include "xfa/fxfa/parser/cxfa_numericedit.h" +#include "xfa/fxfa/parser/cxfa_occur.h" +#include "xfa/fxfa/parser/cxfa_oid.h" +#include "xfa/fxfa/parser/cxfa_oids.h" +#include "xfa/fxfa/parser/cxfa_openaction.h" +#include "xfa/fxfa/parser/cxfa_operation.h" +#include "xfa/fxfa/parser/cxfa_output.h" +#include "xfa/fxfa/parser/cxfa_outputbin.h" +#include "xfa/fxfa/parser/cxfa_outputxsl.h" +#include "xfa/fxfa/parser/cxfa_overflow.h" +#include "xfa/fxfa/parser/cxfa_overprint.h" +#include "xfa/fxfa/parser/cxfa_packet.h" +#include "xfa/fxfa/parser/cxfa_packets.h" +#include "xfa/fxfa/parser/cxfa_pagearea.h" +#include "xfa/fxfa/parser/cxfa_pageoffset.h" +#include "xfa/fxfa/parser/cxfa_pagerange.h" +#include "xfa/fxfa/parser/cxfa_pageset.h" +#include "xfa/fxfa/parser/cxfa_pagination.h" +#include "xfa/fxfa/parser/cxfa_paginationoverride.h" +#include "xfa/fxfa/parser/cxfa_para.h" +#include "xfa/fxfa/parser/cxfa_part.h" +#include "xfa/fxfa/parser/cxfa_password.h" +#include "xfa/fxfa/parser/cxfa_passwordedit.h" +#include "xfa/fxfa/parser/cxfa_pattern.h" +#include "xfa/fxfa/parser/cxfa_pcl.h" +#include "xfa/fxfa/parser/cxfa_pdf.h" +#include "xfa/fxfa/parser/cxfa_pdfa.h" +#include "xfa/fxfa/parser/cxfa_permissions.h" +#include "xfa/fxfa/parser/cxfa_picktraybypdfsize.h" +#include "xfa/fxfa/parser/cxfa_picture.h" +#include "xfa/fxfa/parser/cxfa_plaintextmetadata.h" +#include "xfa/fxfa/parser/cxfa_presence.h" +#include "xfa/fxfa/parser/cxfa_present.h" +#include "xfa/fxfa/parser/cxfa_print.h" +#include "xfa/fxfa/parser/cxfa_printername.h" +#include "xfa/fxfa/parser/cxfa_printhighquality.h" +#include "xfa/fxfa/parser/cxfa_printscaling.h" +#include "xfa/fxfa/parser/cxfa_producer.h" +#include "xfa/fxfa/parser/cxfa_proto.h" +#include "xfa/fxfa/parser/cxfa_ps.h" +#include "xfa/fxfa/parser/cxfa_psmap.h" +#include "xfa/fxfa/parser/cxfa_query.h" +#include "xfa/fxfa/parser/cxfa_radial.h" +#include "xfa/fxfa/parser/cxfa_range.h" +#include "xfa/fxfa/parser/cxfa_reason.h" +#include "xfa/fxfa/parser/cxfa_reasons.h" +#include "xfa/fxfa/parser/cxfa_record.h" +#include "xfa/fxfa/parser/cxfa_recordset.h" +#include "xfa/fxfa/parser/cxfa_rectangle.h" +#include "xfa/fxfa/parser/cxfa_ref.h" +#include "xfa/fxfa/parser/cxfa_relevant.h" +#include "xfa/fxfa/parser/cxfa_rename.h" +#include "xfa/fxfa/parser/cxfa_renderpolicy.h" +#include "xfa/fxfa/parser/cxfa_rootelement.h" +#include "xfa/fxfa/parser/cxfa_runscripts.h" +#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxfa/parser/cxfa_scriptmodel.h" +#include "xfa/fxfa/parser/cxfa_select.h" +#include "xfa/fxfa/parser/cxfa_setproperty.h" +#include "xfa/fxfa/parser/cxfa_severity.h" +#include "xfa/fxfa/parser/cxfa_sharptext.h" +#include "xfa/fxfa/parser/cxfa_sharpxhtml.h" +#include "xfa/fxfa/parser/cxfa_sharpxml.h" +#include "xfa/fxfa/parser/cxfa_signature.h" +#include "xfa/fxfa/parser/cxfa_signatureproperties.h" +#include "xfa/fxfa/parser/cxfa_signdata.h" +#include "xfa/fxfa/parser/cxfa_signing.h" +#include "xfa/fxfa/parser/cxfa_silentprint.h" +#include "xfa/fxfa/parser/cxfa_soapaction.h" +#include "xfa/fxfa/parser/cxfa_soapaddress.h" +#include "xfa/fxfa/parser/cxfa_solid.h" +#include "xfa/fxfa/parser/cxfa_source.h" +#include "xfa/fxfa/parser/cxfa_sourceset.h" +#include "xfa/fxfa/parser/cxfa_speak.h" +#include "xfa/fxfa/parser/cxfa_staple.h" +#include "xfa/fxfa/parser/cxfa_startnode.h" +#include "xfa/fxfa/parser/cxfa_startpage.h" +#include "xfa/fxfa/parser/cxfa_stipple.h" +#include "xfa/fxfa/parser/cxfa_subform.h" +#include "xfa/fxfa/parser/cxfa_subformset.h" +#include "xfa/fxfa/parser/cxfa_subjectdn.h" +#include "xfa/fxfa/parser/cxfa_subjectdns.h" +#include "xfa/fxfa/parser/cxfa_submit.h" +#include "xfa/fxfa/parser/cxfa_submitformat.h" +#include "xfa/fxfa/parser/cxfa_submiturl.h" +#include "xfa/fxfa/parser/cxfa_subsetbelow.h" +#include "xfa/fxfa/parser/cxfa_suppressbanner.h" +#include "xfa/fxfa/parser/cxfa_tagged.h" +#include "xfa/fxfa/parser/cxfa_template.h" +#include "xfa/fxfa/parser/cxfa_templatecache.h" +#include "xfa/fxfa/parser/cxfa_text.h" +#include "xfa/fxfa/parser/cxfa_textedit.h" +#include "xfa/fxfa/parser/cxfa_threshold.h" +#include "xfa/fxfa/parser/cxfa_time.h" +#include "xfa/fxfa/parser/cxfa_timepattern.h" +#include "xfa/fxfa/parser/cxfa_timepatterns.h" +#include "xfa/fxfa/parser/cxfa_timestamp.h" +#include "xfa/fxfa/parser/cxfa_to.h" +#include "xfa/fxfa/parser/cxfa_tooltip.h" +#include "xfa/fxfa/parser/cxfa_trace.h" +#include "xfa/fxfa/parser/cxfa_transform.h" +#include "xfa/fxfa/parser/cxfa_traversal.h" +#include "xfa/fxfa/parser/cxfa_traverse.h" +#include "xfa/fxfa/parser/cxfa_type.h" +#include "xfa/fxfa/parser/cxfa_typeface.h" +#include "xfa/fxfa/parser/cxfa_typefaces.h" +#include "xfa/fxfa/parser/cxfa_ui.h" +#include "xfa/fxfa/parser/cxfa_update.h" +#include "xfa/fxfa/parser/cxfa_uri.h" +#include "xfa/fxfa/parser/cxfa_user.h" +#include "xfa/fxfa/parser/cxfa_validate.h" +#include "xfa/fxfa/parser/cxfa_validateapprovalsignatures.h" +#include "xfa/fxfa/parser/cxfa_validationmessaging.h" +#include "xfa/fxfa/parser/cxfa_value.h" +#include "xfa/fxfa/parser/cxfa_variables.h" +#include "xfa/fxfa/parser/cxfa_version.h" +#include "xfa/fxfa/parser/cxfa_versioncontrol.h" +#include "xfa/fxfa/parser/cxfa_viewerpreferences.h" +#include "xfa/fxfa/parser/cxfa_webclient.h" +#include "xfa/fxfa/parser/cxfa_whitespace.h" +#include "xfa/fxfa/parser/cxfa_window.h" +#include "xfa/fxfa/parser/cxfa_wsdladdress.h" +#include "xfa/fxfa/parser/cxfa_wsdlconnection.h" +#include "xfa/fxfa/parser/cxfa_xdc.h" +#include "xfa/fxfa/parser/cxfa_xdp.h" +#include "xfa/fxfa/parser/cxfa_xfa.h" +#include "xfa/fxfa/parser/cxfa_xmlconnection.h" +#include "xfa/fxfa/parser/cxfa_xsdconnection.h" +#include "xfa/fxfa/parser/cxfa_xsl.h" +#include "xfa/fxfa/parser/cxfa_zpl.h" + +namespace { + +struct ElementNameInfo { + uint32_t hash; + XFA_Element element; +} ElementNameToEnum[] = { + {0x23ee3 /* ps */, XFA_Element::Ps}, + {0x25363 /* to */, XFA_Element::To}, + {0x2587e /* ui */, XFA_Element::Ui}, + {0x1c648b /* recordSet */, XFA_Element::RecordSet}, + {0x171428f /* subsetBelow */, XFA_Element::SubsetBelow}, + {0x1a0776a /* subformSet */, XFA_Element::SubformSet}, + {0x2340d70 /* adobeExtensionLevel */, XFA_Element::AdobeExtensionLevel}, + {0x2c1c7f1 /* typeface */, XFA_Element::Typeface}, + {0x5518c25 /* break */, XFA_Element::Break}, + {0x5fff523 /* fontInfo */, XFA_Element::FontInfo}, + {0x653a227 /* numberPattern */, XFA_Element::NumberPattern}, + {0x65b4a05 /* dynamicRender */, XFA_Element::DynamicRender}, + {0x7e4362e /* printScaling */, XFA_Element::PrintScaling}, + {0x7fe6d3a /* checkButton */, XFA_Element::CheckButton}, + {0x80cf58f /* datePatterns */, XFA_Element::DatePatterns}, + {0x811929d /* sourceSet */, XFA_Element::SourceSet}, + {0x9f9d612 /* amd */, XFA_Element::Amd}, + {0x9f9efb6 /* arc */, XFA_Element::Arc}, + {0xa48835e /* day */, XFA_Element::Day}, + {0xa6328b8 /* era */, XFA_Element::Era}, + {0xae6a0a0 /* jog */, XFA_Element::Jog}, + {0xb1b3d22 /* log */, XFA_Element::Log}, + {0xb35439e /* map */, XFA_Element::Map}, + {0xb355301 /* mdp */, XFA_Element::Mdp}, + {0xb420438 /* breakBefore */, XFA_Element::BreakBefore}, + {0xb6a091c /* oid */, XFA_Element::Oid}, + {0xb84389f /* pcl */, XFA_Element::Pcl}, + {0xb843dba /* pdf */, XFA_Element::Pdf}, + {0xbb8df5d /* ref */, XFA_Element::Ref}, + {0xc080cd0 /* uri */, XFA_Element::Uri}, + {0xc56afbf /* xdc */, XFA_Element::Xdc}, + {0xc56afcc /* xdp */, XFA_Element::Xdp}, + {0xc56b9ff /* xfa */, XFA_Element::Xfa}, + {0xc56fcb7 /* xsl */, XFA_Element::Xsl}, + {0xc8b89d6 /* zpl */, XFA_Element::Zpl}, + {0xc9bae94 /* cache */, XFA_Element::Cache}, + {0xcb016be /* margin */, XFA_Element::Margin}, + {0xe1378fe /* keyUsage */, XFA_Element::KeyUsage}, + {0xfe3596a /* exclude */, XFA_Element::Exclude}, + {0x10395ac7 /* choiceList */, XFA_Element::ChoiceList}, + {0x1059ec18 /* level */, XFA_Element::Level}, + {0x10874804 /* labelPrinter */, XFA_Element::LabelPrinter}, + {0x10c40e03 /* calendarSymbols */, XFA_Element::CalendarSymbols}, + {0x10f1ea24 /* para */, XFA_Element::Para}, + {0x10f1ea37 /* part */, XFA_Element::Part}, + {0x1140975b /* pdfa */, XFA_Element::Pdfa}, + {0x1154efe6 /* filter */, XFA_Element::Filter}, + {0x13f41de1 /* present */, XFA_Element::Present}, + {0x1827e6ea /* pagination */, XFA_Element::Pagination}, + {0x18463707 /* encoding */, XFA_Element::Encoding}, + {0x185e41e2 /* event */, XFA_Element::Event}, + {0x1adb142d /* whitespace */, XFA_Element::Whitespace}, + {0x1f3f64c3 /* defaultUi */, XFA_Element::DefaultUi}, + {0x204e87cb /* dataModel */, XFA_Element::DataModel}, + {0x2057b350 /* barcode */, XFA_Element::Barcode}, + {0x20596bad /* timePattern */, XFA_Element::TimePattern}, + {0x210b74d3 /* batchOutput */, XFA_Element::BatchOutput}, + {0x212ff0e2 /* enforce */, XFA_Element::Enforce}, + {0x21d351b4 /* currencySymbols */, XFA_Element::CurrencySymbols}, + {0x21db83c5 /* addSilentPrint */, XFA_Element::AddSilentPrint}, + {0x22266258 /* rename */, XFA_Element::Rename}, + {0x226ca8f1 /* operation */, XFA_Element::Operation}, + {0x23e27b84 /* typefaces */, XFA_Element::Typefaces}, + {0x23f4aa75 /* subjectDNs */, XFA_Element::SubjectDNs}, + {0x240d5e8e /* issuers */, XFA_Element::Issuers}, + {0x24a52f8a /* wsdlConnection */, XFA_Element::WsdlConnection}, + {0x254ebd07 /* debug */, XFA_Element::Debug}, + {0x2655c66a /* delta */, XFA_Element::Delta}, + {0x26c0daec /* eraNames */, XFA_Element::EraNames}, + {0x273ab03b /* modifyAnnots */, XFA_Element::ModifyAnnots}, + {0x27875bb4 /* startNode */, XFA_Element::StartNode}, + {0x285d0dbc /* button */, XFA_Element::Button}, + {0x28dee6e9 /* format */, XFA_Element::Format}, + {0x2a23349e /* border */, XFA_Element::Border}, + {0x2ae67f19 /* area */, XFA_Element::Area}, + {0x2c3c4c67 /* hyphenation */, XFA_Element::Hyphenation}, + {0x2d08af85 /* text */, XFA_Element::Text}, + {0x2d71b00f /* time */, XFA_Element::Time}, + {0x2f16a382 /* type */, XFA_Element::Type}, + {0x2fe057e9 /* overprint */, XFA_Element::Overprint}, + {0x302aee16 /* certificates */, XFA_Element::Certificates}, + {0x30b227df /* encryptionMethods */, XFA_Element::EncryptionMethods}, + {0x32b900d1 /* setProperty */, XFA_Element::SetProperty}, + {0x337d9e45 /* printerName */, XFA_Element::PrinterName}, + {0x33edda4b /* startPage */, XFA_Element::StartPage}, + {0x381943e4 /* pageOffset */, XFA_Element::PageOffset}, + {0x382106cd /* dateTime */, XFA_Element::DateTime}, + {0x386e7421 /* comb */, XFA_Element::Comb}, + {0x390acd9e /* pattern */, XFA_Element::Pattern}, + {0x3942163e /* ifEmpty */, XFA_Element::IfEmpty}, + {0x39944a7b /* suppressBanner */, XFA_Element::SuppressBanner}, + {0x3b3c3dca /* outputBin */, XFA_Element::OutputBin}, + {0x3b8a4024 /* field */, XFA_Element::Field}, + {0x3c15352f /* agent */, XFA_Element::Agent}, + {0x3d7e8668 /* outputXSL */, XFA_Element::OutputXSL}, + {0x3e1c91c5 /* adjustData */, XFA_Element::AdjustData}, + {0x3e7a9408 /* autoSave */, XFA_Element::AutoSave}, + {0x3ecead94 /* contentArea */, XFA_Element::ContentArea}, + {0x3fadaec0 /* wsdlAddress */, XFA_Element::WsdlAddress}, + {0x40623b5b /* solid */, XFA_Element::Solid}, + {0x41f0bd76 /* dateTimeSymbols */, XFA_Element::DateTimeSymbols}, + {0x444e7523 /* encryptionLevel */, XFA_Element::EncryptionLevel}, + {0x4523af55 /* edge */, XFA_Element::Edge}, + {0x45d5e3c1 /* stipple */, XFA_Element::Stipple}, + {0x475e4e87 /* attributes */, XFA_Element::Attributes}, + {0x487a8c87 /* versionControl */, XFA_Element::VersionControl}, + {0x48e5248c /* meridiem */, XFA_Element::Meridiem}, + {0x48f36719 /* exclGroup */, XFA_Element::ExclGroup}, + {0x4977356b /* toolTip */, XFA_Element::ToolTip}, + {0x499afecc /* compress */, XFA_Element::Compress}, + {0x4a0c4948 /* reason */, XFA_Element::Reason}, + {0x4bdcce13 /* execute */, XFA_Element::Execute}, + {0x4c56b216 /* contentCopy */, XFA_Element::ContentCopy}, + {0x4cc176d3 /* dateTimeEdit */, XFA_Element::DateTimeEdit}, + {0x4e1e39b6 /* config */, XFA_Element::Config}, + {0x4e2d6083 /* image */, XFA_Element::Image}, + {0x4e814150 /* #xHTML */, XFA_Element::SharpxHTML}, + {0x4f2388c1 /* numberOfCopies */, XFA_Element::NumberOfCopies}, + {0x4f512e30 /* behaviorOverride */, XFA_Element::BehaviorOverride}, + {0x4fdc3454 /* timeStamp */, XFA_Element::TimeStamp}, + {0x51d90546 /* month */, XFA_Element::Month}, + {0x523437e4 /* viewerPreferences */, XFA_Element::ViewerPreferences}, + {0x53abc1c6 /* scriptModel */, XFA_Element::ScriptModel}, + {0x54034c2f /* decimal */, XFA_Element::Decimal}, + {0x54202c9e /* subform */, XFA_Element::Subform}, + {0x542c7300 /* select */, XFA_Element::Select}, + {0x5436d198 /* window */, XFA_Element::Window}, + {0x5473b6dc /* localeSet */, XFA_Element::LocaleSet}, + {0x56ae179e /* handler */, XFA_Element::Handler}, + {0x570ce835 /* presence */, XFA_Element::Presence}, + {0x5779d65f /* record */, XFA_Element::Record}, + {0x59c8f27d /* embed */, XFA_Element::Embed}, + {0x5a50e9e6 /* version */, XFA_Element::Version}, + {0x5b8383df /* command */, XFA_Element::Command}, + {0x5c43c6c3 /* copies */, XFA_Element::Copies}, + {0x5e0c2c49 /* staple */, XFA_Element::Staple}, + {0x5e5083dd /* submitFormat */, XFA_Element::SubmitFormat}, + {0x5e8c5d20 /* boolean */, XFA_Element::Boolean}, + {0x60490a85 /* message */, XFA_Element::Message}, + {0x60d4c8b1 /* output */, XFA_Element::Output}, + {0x61810081 /* psMap */, XFA_Element::PsMap}, + {0x62bd904b /* excludeNS */, XFA_Element::ExcludeNS}, + {0x669d4f77 /* assist */, XFA_Element::Assist}, + {0x67334a1c /* picture */, XFA_Element::Picture}, + {0x67fe7334 /* traversal */, XFA_Element::Traversal}, + {0x6894589c /* silentPrint */, XFA_Element::SilentPrint}, + {0x68a16bbd /* webClient */, XFA_Element::WebClient}, + {0x6a4bc084 /* producer */, XFA_Element::Producer}, + {0x6a9e04c9 /* corner */, XFA_Element::Corner}, + {0x6ccd7274 /* msgId */, XFA_Element::MsgId}, + {0x6e67921f /* color */, XFA_Element::Color}, + {0x6ec217a5 /* keep */, XFA_Element::Keep}, + {0x6eef1116 /* query */, XFA_Element::Query}, + {0x7033bfd5 /* insert */, XFA_Element::Insert}, + {0x704af389 /* imageEdit */, XFA_Element::ImageEdit}, + {0x7233018a /* validate */, XFA_Element::Validate}, + {0x72ba47b4 /* digestMethods */, XFA_Element::DigestMethods}, + {0x72f2aa7a /* numberPatterns */, XFA_Element::NumberPatterns}, + {0x74caed29 /* pageSet */, XFA_Element::PageSet}, + {0x7568e6ae /* integer */, XFA_Element::Integer}, + {0x76182db9 /* soapAddress */, XFA_Element::SoapAddress}, + {0x773146c5 /* equate */, XFA_Element::Equate}, + {0x77d449dd /* formFieldFilling */, XFA_Element::FormFieldFilling}, + {0x7889d68a /* pageRange */, XFA_Element::PageRange}, + {0x7baca2e3 /* update */, XFA_Element::Update}, + {0x7ce89001 /* connectString */, XFA_Element::ConnectString}, + {0x7d9fd7c5 /* mode */, XFA_Element::Mode}, + {0x7e7e845e /* layout */, XFA_Element::Layout}, + {0x7e845c34 /* #xml */, XFA_Element::Sharpxml}, + {0x7fb341df /* xsdConnection */, XFA_Element::XsdConnection}, + {0x7ffb51cc /* traverse */, XFA_Element::Traverse}, + {0x80203b5a /* encodings */, XFA_Element::Encodings}, + {0x803550fc /* template */, XFA_Element::Template}, + {0x803d5bbc /* acrobat */, XFA_Element::Acrobat}, + {0x821d6569 /* validationMessaging */, XFA_Element::ValidationMessaging}, + {0x830e688f /* signing */, XFA_Element::Signing}, + {0x83dab9f5 /* script */, XFA_Element::Script}, + {0x8411ebcd /* addViewerPreferences */, XFA_Element::AddViewerPreferences}, + {0x8777642e /* alwaysEmbed */, XFA_Element::AlwaysEmbed}, + {0x877a6b39 /* passwordEdit */, XFA_Element::PasswordEdit}, + {0x87e84c99 /* numericEdit */, XFA_Element::NumericEdit}, + {0x8852cdec /* encryptionMethod */, XFA_Element::EncryptionMethod}, + {0x891f4606 /* change */, XFA_Element::Change}, + {0x89939f36 /* pageArea */, XFA_Element::PageArea}, + {0x8a9d6247 /* submitUrl */, XFA_Element::SubmitUrl}, + {0x8ad8b90f /* oids */, XFA_Element::Oids}, + {0x8b036f32 /* signature */, XFA_Element::Signature}, + {0x8b128efb /* ADBE_JSConsole */, XFA_Element::ADBE_JSConsole}, + {0x8bcfe96e /* caption */, XFA_Element::Caption}, + {0x8e1c2921 /* relevant */, XFA_Element::Relevant}, + {0x8e3f0a4b /* flipLabel */, XFA_Element::FlipLabel}, + {0x900280b7 /* exData */, XFA_Element::ExData}, + {0x91e80352 /* dayNames */, XFA_Element::DayNames}, + {0x93113b11 /* soapAction */, XFA_Element::SoapAction}, + {0x938b09f6 /* defaultTypeface */, XFA_Element::DefaultTypeface}, + {0x95b37897 /* manifest */, XFA_Element::Manifest}, + {0x97b76b54 /* overflow */, XFA_Element::Overflow}, + {0x9a57861b /* linear */, XFA_Element::Linear}, + {0x9ad5a821 /* currencySymbol */, XFA_Element::CurrencySymbol}, + {0x9c6471b3 /* delete */, XFA_Element::Delete}, + {0x9deea61d /* deltas */, XFA_Element::Deltas}, + {0x9e67de21 /* digestMethod */, XFA_Element::DigestMethod}, + {0x9f3e9510 /* instanceManager */, XFA_Element::InstanceManager}, + {0xa0799892 /* equateRange */, XFA_Element::EquateRange}, + {0xa084a381 /* medium */, XFA_Element::Medium}, + {0xa1211b8b /* textEdit */, XFA_Element::TextEdit}, + {0xa17008f0 /* templateCache */, XFA_Element::TemplateCache}, + {0xa4f7b88f /* compressObjectStream */, XFA_Element::CompressObjectStream}, + {0xa65f5d17 /* dataValue */, XFA_Element::DataValue}, + {0xa6caaa89 /* accessibleContent */, XFA_Element::AccessibleContent}, + {0xa94cc00b /* includeXDPContent */, XFA_Element::IncludeXDPContent}, + {0xa9b081a1 /* xmlConnection */, XFA_Element::XmlConnection}, + {0xab2a3b74 /* validateApprovalSignatures */, + XFA_Element::ValidateApprovalSignatures}, + {0xab8c5a2b /* signData */, XFA_Element::SignData}, + {0xabaa2ceb /* packets */, XFA_Element::Packets}, + {0xadba359c /* datePattern */, XFA_Element::DatePattern}, + {0xae222b2b /* duplexOption */, XFA_Element::DuplexOption}, + {0xb012effb /* base */, XFA_Element::Base}, + {0xb0e5485d /* bind */, XFA_Element::Bind}, + {0xb45d61b2 /* compression */, XFA_Element::Compression}, + {0xb563f0ff /* user */, XFA_Element::User}, + {0xb5848ad5 /* rectangle */, XFA_Element::Rectangle}, + {0xb6dacb72 /* effectiveOutputPolicy */, + XFA_Element::EffectiveOutputPolicy}, + {0xb7d7654d /* ADBE_JSDebugger */, XFA_Element::ADBE_JSDebugger}, + {0xbab37f73 /* acrobat7 */, XFA_Element::Acrobat7}, + {0xbc70081e /* interactive */, XFA_Element::Interactive}, + {0xbc8fa350 /* locale */, XFA_Element::Locale}, + {0xbcd44940 /* currentPage */, XFA_Element::CurrentPage}, + {0xbde9abda /* data */, XFA_Element::Data}, + {0xbde9abde /* date */, XFA_Element::Date}, + {0xbe52dfbf /* desc */, XFA_Element::Desc}, + {0xbf4b6405 /* encrypt */, XFA_Element::Encrypt}, + {0xbfa87cce /* draw */, XFA_Element::Draw}, + {0xc181ff4b /* encryption */, XFA_Element::Encryption}, + {0xc1970f40 /* meridiemNames */, XFA_Element::MeridiemNames}, + {0xc5ad9f5e /* messaging */, XFA_Element::Messaging}, + {0xc69549f4 /* speak */, XFA_Element::Speak}, + {0xc7743dc7 /* dataGroup */, XFA_Element::DataGroup}, + {0xc7eb20e9 /* common */, XFA_Element::Common}, + {0xc85d4528 /* #text */, XFA_Element::Sharptext}, + {0xc861556a /* paginationOverride */, XFA_Element::PaginationOverride}, + {0xc903dabb /* reasons */, XFA_Element::Reasons}, + {0xc9a8127f /* signatureProperties */, XFA_Element::SignatureProperties}, + {0xca010c2d /* threshold */, XFA_Element::Threshold}, + {0xcb4c5e96 /* appearanceFilter */, XFA_Element::AppearanceFilter}, + {0xcc92aba7 /* fill */, XFA_Element::Fill}, + {0xcd308b77 /* font */, XFA_Element::Font}, + {0xcd309ff4 /* form */, XFA_Element::Form}, + {0xcebcca2d /* mediumInfo */, XFA_Element::MediumInfo}, + {0xcfe0d643 /* certificate */, XFA_Element::Certificate}, + {0xd012c033 /* password */, XFA_Element::Password}, + {0xd01604bd /* runScripts */, XFA_Element::RunScripts}, + {0xd1227e6f /* trace */, XFA_Element::Trace}, + {0xd1532876 /* float */, XFA_Element::Float}, + {0xd17a6c30 /* renderPolicy */, XFA_Element::RenderPolicy}, + {0xd58aa962 /* destination */, XFA_Element::Destination}, + {0xd6e27f1d /* value */, XFA_Element::Value}, + {0xd7a14462 /* bookend */, XFA_Element::Bookend}, + {0xd8c31254 /* exObject */, XFA_Element::ExObject}, + {0xda6a8590 /* openAction */, XFA_Element::OpenAction}, + {0xdab4fb7d /* neverEmbed */, XFA_Element::NeverEmbed}, + {0xdb98475f /* bindItems */, XFA_Element::BindItems}, + {0xdbfbe02e /* calculate */, XFA_Element::Calculate}, + {0xdd7676ed /* print */, XFA_Element::Print}, + {0xdde273d7 /* extras */, XFA_Element::Extras}, + {0xde146b34 /* proto */, XFA_Element::Proto}, + {0xdf059321 /* dSigData */, XFA_Element::DSigData}, + {0xdfccf030 /* creator */, XFA_Element::Creator}, + {0xdff78c6a /* connect */, XFA_Element::Connect}, + {0xe11a2cbc /* permissions */, XFA_Element::Permissions}, + {0xe14c801c /* connectionSet */, XFA_Element::ConnectionSet}, + {0xe1c83a14 /* submit */, XFA_Element::Submit}, + {0xe29821cd /* range */, XFA_Element::Range}, + {0xe38d83c7 /* linearized */, XFA_Element::Linearized}, + {0xe3aa2578 /* packet */, XFA_Element::Packet}, + {0xe3aa860e /* rootElement */, XFA_Element::RootElement}, + {0xe3e553fa /* plaintextMetadata */, XFA_Element::PlaintextMetadata}, + {0xe3e6e4f2 /* numberSymbols */, XFA_Element::NumberSymbols}, + {0xe3f067f6 /* printHighQuality */, XFA_Element::PrintHighQuality}, + {0xe3fd078c /* driver */, XFA_Element::Driver}, + {0xe48b34f2 /* incrementalLoad */, XFA_Element::IncrementalLoad}, + {0xe550e7c2 /* subjectDN */, XFA_Element::SubjectDN}, + {0xe6669a78 /* compressLogicalStructure */, + XFA_Element::CompressLogicalStructure}, + {0xe7a7ea02 /* incrementalMerge */, XFA_Element::IncrementalMerge}, + {0xe948530d /* radial */, XFA_Element::Radial}, + {0xea8d6999 /* variables */, XFA_Element::Variables}, + {0xeaa142c0 /* timePatterns */, XFA_Element::TimePatterns}, + {0xeb943a71 /* effectiveInputPolicy */, XFA_Element::EffectiveInputPolicy}, + {0xef04a2bc /* nameAttr */, XFA_Element::NameAttr}, + {0xf07222ab /* conformance */, XFA_Element::Conformance}, + {0xf0aaaadc /* transform */, XFA_Element::Transform}, + {0xf1433e88 /* lockDocument */, XFA_Element::LockDocument}, + {0xf54eb997 /* breakAfter */, XFA_Element::BreakAfter}, + {0xf616da28 /* line */, XFA_Element::Line}, + {0xf7055fb1 /* source */, XFA_Element::Source}, + {0xf7eebe1c /* occur */, XFA_Element::Occur}, + {0xf8d10d97 /* pickTrayByPDFSize */, XFA_Element::PickTrayByPDFSize}, + {0xf8f19e3a /* monthNames */, XFA_Element::MonthNames}, + {0xf984149b /* severity */, XFA_Element::Severity}, + {0xf9bcb037 /* groupParent */, XFA_Element::GroupParent}, + {0xfbc42fff /* documentAssembly */, XFA_Element::DocumentAssembly}, + {0xfc78159f /* numberSymbol */, XFA_Element::NumberSymbol}, + {0xfcbd606c /* tagged */, XFA_Element::Tagged}, + {0xff063802 /* items */, XFA_Element::Items}, +}; + +struct AttributeNameInfo { + uint32_t hash; + XFA_Attribute attribute; +} AttributeNameInfoToEnum[] = { + {0x68 /* h */, XFA_Attribute::H}, + {0x77 /* w */, XFA_Attribute::W}, + {0x78 /* x */, XFA_Attribute::X}, + {0x79 /* y */, XFA_Attribute::Y}, + {0x21aed /* id */, XFA_Attribute::Id}, + {0x25363 /* to */, XFA_Attribute::To}, + {0xcb0ac9 /* lineThrough */, XFA_Attribute::LineThrough}, + {0x2282c73 /* hAlign */, XFA_Attribute::HAlign}, + {0x2c1c7f1 /* typeface */, XFA_Attribute::Typeface}, + {0x3106c3a /* beforeTarget */, XFA_Attribute::BeforeTarget}, + {0x31b19c1 /* name */, XFA_Attribute::Name}, + {0x3848b3f /* next */, XFA_Attribute::Next}, + {0x43e349b /* dataRowCount */, XFA_Attribute::DataRowCount}, + {0x5518c25 /* break */, XFA_Attribute::Break}, + {0x5ce6195 /* vScrollPolicy */, XFA_Attribute::VScrollPolicy}, + {0x8c74ae9 /* fontHorizontalScale */, XFA_Attribute::FontHorizontalScale}, + {0x8d4f1c7 /* textIndent */, XFA_Attribute::TextIndent}, + {0x97c1c65 /* context */, XFA_Attribute::Context}, + {0x9876578 /* trayOut */, XFA_Attribute::TrayOut}, + {0xa2e3514 /* cap */, XFA_Attribute::Cap}, + {0xb3543a6 /* max */, XFA_Attribute::Max}, + {0xb356ca4 /* min */, XFA_Attribute::Min}, + {0xbb8df5d /* ref */, XFA_Attribute::Ref}, + {0xbb8f3df /* rid */, XFA_Attribute::Rid}, + {0xc080cd3 /* url */, XFA_Attribute::Url}, + {0xc0811ed /* use */, XFA_Attribute::Use}, + {0xcfea02e /* leftInset */, XFA_Attribute::LeftInset}, + {0x1026c59d /* widows */, XFA_Attribute::Widows}, + {0x1059ec18 /* level */, XFA_Attribute::Level}, + {0x1356caf8 /* bottomInset */, XFA_Attribute::BottomInset}, + {0x13a08bdb /* overflowTarget */, XFA_Attribute::OverflowTarget}, + {0x1414d431 /* allowMacro */, XFA_Attribute::AllowMacro}, + {0x14a32d52 /* pagePosition */, XFA_Attribute::PagePosition}, + {0x1517dfa1 /* columnWidths */, XFA_Attribute::ColumnWidths}, + {0x169134a1 /* overflowLeader */, XFA_Attribute::OverflowLeader}, + {0x1b8dce3e /* action */, XFA_Attribute::Action}, + {0x1e459b8f /* nonRepudiation */, XFA_Attribute::NonRepudiation}, + {0x1ec8ab2c /* rate */, XFA_Attribute::Rate}, + {0x1ef3a64a /* allowRichText */, XFA_Attribute::AllowRichText}, + {0x2038c9b2 /* role */, XFA_Attribute::Role}, + {0x20914367 /* overflowTrailer */, XFA_Attribute::OverflowTrailer}, + {0x226ca8f1 /* operation */, XFA_Attribute::Operation}, + {0x24d85167 /* timeout */, XFA_Attribute::Timeout}, + {0x25764436 /* topInset */, XFA_Attribute::TopInset}, + {0x25839852 /* access */, XFA_Attribute::Access}, + {0x268b7ec1 /* commandType */, XFA_Attribute::CommandType}, + {0x28dee6e9 /* format */, XFA_Attribute::Format}, + {0x28e17e91 /* dataPrep */, XFA_Attribute::DataPrep}, + {0x292b88fe /* widgetData */, XFA_Attribute::WidgetData}, + {0x29418bb7 /* abbr */, XFA_Attribute::Abbr}, + {0x2a82d99c /* marginRight */, XFA_Attribute::MarginRight}, + {0x2b5df51e /* dataDescription */, XFA_Attribute::DataDescription}, + {0x2bb3f470 /* encipherOnly */, XFA_Attribute::EncipherOnly}, + {0x2cd79033 /* kerningMode */, XFA_Attribute::KerningMode}, + {0x2ee7678f /* rotate */, XFA_Attribute::Rotate}, + {0x2f105f72 /* wordCharacterCount */, XFA_Attribute::WordCharacterCount}, + {0x2f16a382 /* type */, XFA_Attribute::Type}, + {0x34ae103c /* reserve */, XFA_Attribute::Reserve}, + {0x3650557e /* textLocation */, XFA_Attribute::TextLocation}, + {0x39cdb0a2 /* priority */, XFA_Attribute::Priority}, + {0x3a0273a6 /* underline */, XFA_Attribute::Underline}, + {0x3b582286 /* moduleWidth */, XFA_Attribute::ModuleWidth}, + {0x3d123c26 /* hyphenate */, XFA_Attribute::Hyphenate}, + {0x3e7af94f /* listen */, XFA_Attribute::Listen}, + {0x4156ee3f /* delimiter */, XFA_Attribute::Delimiter}, + {0x42fed1fd /* contentType */, XFA_Attribute::ContentType}, + {0x453eaf38 /* startNew */, XFA_Attribute::StartNew}, + {0x45a6daf8 /* eofAction */, XFA_Attribute::EofAction}, + {0x47cfa43a /* allowNeutral */, XFA_Attribute::AllowNeutral}, + {0x47d03490 /* connection */, XFA_Attribute::Connection}, + {0x4873c601 /* baselineShift */, XFA_Attribute::BaselineShift}, + {0x4b319767 /* overlinePeriod */, XFA_Attribute::OverlinePeriod}, + {0x4b8bc840 /* fracDigits */, XFA_Attribute::FracDigits}, + {0x4ef3d02c /* orientation */, XFA_Attribute::Orientation}, + {0x4fdc3454 /* timeStamp */, XFA_Attribute::TimeStamp}, + {0x52666f1c /* printCheckDigit */, XFA_Attribute::PrintCheckDigit}, + {0x534729c9 /* marginLeft */, XFA_Attribute::MarginLeft}, + {0x5392ea58 /* stroke */, XFA_Attribute::Stroke}, + {0x5404d6df /* moduleHeight */, XFA_Attribute::ModuleHeight}, + {0x54fa722c /* transferEncoding */, XFA_Attribute::TransferEncoding}, + {0x552d9ad5 /* usage */, XFA_Attribute::Usage}, + {0x570ce835 /* presence */, XFA_Attribute::Presence}, + {0x5739d1ff /* radixOffset */, XFA_Attribute::RadixOffset}, + {0x577682ac /* preserve */, XFA_Attribute::Preserve}, + {0x58be2870 /* aliasNode */, XFA_Attribute::AliasNode}, + {0x5a32e493 /* multiLine */, XFA_Attribute::MultiLine}, + {0x5a50e9e6 /* version */, XFA_Attribute::Version}, + {0x5ab23b6c /* startChar */, XFA_Attribute::StartChar}, + {0x5b707a35 /* scriptTest */, XFA_Attribute::ScriptTest}, + {0x5c054755 /* startAngle */, XFA_Attribute::StartAngle}, + {0x5ec958c0 /* cursorType */, XFA_Attribute::CursorType}, + {0x5f760b50 /* digitalSignature */, XFA_Attribute::DigitalSignature}, + {0x60a61edd /* codeType */, XFA_Attribute::CodeType}, + {0x60d4c8b1 /* output */, XFA_Attribute::Output}, + {0x64110ab5 /* bookendTrailer */, XFA_Attribute::BookendTrailer}, + {0x65e30c67 /* imagingBBox */, XFA_Attribute::ImagingBBox}, + {0x66539c48 /* excludeInitialCap */, XFA_Attribute::ExcludeInitialCap}, + {0x66642f8f /* force */, XFA_Attribute::Force}, + {0x69aa2292 /* crlSign */, XFA_Attribute::CrlSign}, + {0x6a3405dd /* previous */, XFA_Attribute::Previous}, + {0x6a95c976 /* pushCharacterCount */, XFA_Attribute::PushCharacterCount}, + {0x6b6ddcfb /* nullTest */, XFA_Attribute::NullTest}, + {0x6cfa828a /* runAt */, XFA_Attribute::RunAt}, + {0x731e0665 /* spaceBelow */, XFA_Attribute::SpaceBelow}, + {0x74788f8b /* sweepAngle */, XFA_Attribute::SweepAngle}, + {0x78bff531 /* numberOfCells */, XFA_Attribute::NumberOfCells}, + {0x79543055 /* letterSpacing */, XFA_Attribute::LetterSpacing}, + {0x79975f2b /* lockType */, XFA_Attribute::LockType}, + {0x7a0cc471 /* passwordChar */, XFA_Attribute::PasswordChar}, + {0x7a7cc341 /* vAlign */, XFA_Attribute::VAlign}, + {0x7b29630a /* sourceBelow */, XFA_Attribute::SourceBelow}, + {0x7b95e661 /* inverted */, XFA_Attribute::Inverted}, + {0x7c2fd80b /* mark */, XFA_Attribute::Mark}, + {0x7c2ff6ae /* maxH */, XFA_Attribute::MaxH}, + {0x7c2ff6bd /* maxW */, XFA_Attribute::MaxW}, + {0x7c732a66 /* truncate */, XFA_Attribute::Truncate}, + {0x7d02356c /* minH */, XFA_Attribute::MinH}, + {0x7d02357b /* minW */, XFA_Attribute::MinW}, + {0x7d0b5fca /* initial */, XFA_Attribute::Initial}, + {0x7d9fd7c5 /* mode */, XFA_Attribute::Mode}, + {0x7e7e845e /* layout */, XFA_Attribute::Layout}, + {0x7f6fd3d7 /* server */, XFA_Attribute::Server}, + {0x824f21b7 /* embedPDF */, XFA_Attribute::EmbedPDF}, + {0x8340ea66 /* oddOrEven */, XFA_Attribute::OddOrEven}, + {0x836d4d7c /* tabDefault */, XFA_Attribute::TabDefault}, + {0x8855805f /* contains */, XFA_Attribute::Contains}, + {0x8a692521 /* rightInset */, XFA_Attribute::RightInset}, + {0x8af2e657 /* maxChars */, XFA_Attribute::MaxChars}, + {0x8b90e1f2 /* open */, XFA_Attribute::Open}, + {0x8c99377e /* relation */, XFA_Attribute::Relation}, + {0x8d181d61 /* wideNarrowRatio */, XFA_Attribute::WideNarrowRatio}, + {0x8e1c2921 /* relevant */, XFA_Attribute::Relevant}, + {0x8e29d794 /* signatureType */, XFA_Attribute::SignatureType}, + {0x8ec6204c /* lineThroughPeriod */, XFA_Attribute::LineThroughPeriod}, + {0x8ed182d1 /* shape */, XFA_Attribute::Shape}, + {0x8fa01790 /* tabStops */, XFA_Attribute::TabStops}, + {0x8fc36c0a /* outputBelow */, XFA_Attribute::OutputBelow}, + {0x9041d4b0 /* short */, XFA_Attribute::Short}, + {0x907c7719 /* fontVerticalScale */, XFA_Attribute::FontVerticalScale}, + {0x94446dcc /* thickness */, XFA_Attribute::Thickness}, + {0x957fa006 /* commitOn */, XFA_Attribute::CommitOn}, + {0x982bd892 /* remainCharacterCount */, + XFA_Attribute::RemainCharacterCount}, + {0x98fd4d81 /* keyAgreement */, XFA_Attribute::KeyAgreement}, + {0x99800d7a /* errorCorrectionLevel */, + XFA_Attribute::ErrorCorrectionLevel}, + {0x9a63da3d /* upsMode */, XFA_Attribute::UpsMode}, + {0x9cc17d75 /* mergeMode */, XFA_Attribute::MergeMode}, + {0x9d833d75 /* circular */, XFA_Attribute::Circular}, + {0x9d8ee204 /* psName */, XFA_Attribute::PsName}, + {0x9dcc3ab3 /* trailer */, XFA_Attribute::Trailer}, + {0xa0933954 /* unicodeRange */, XFA_Attribute::UnicodeRange}, + {0xa1b0d2f5 /* executeType */, XFA_Attribute::ExecuteType}, + {0xa25a883d /* duplexImposition */, XFA_Attribute::DuplexImposition}, + {0xa42ca1b7 /* trayIn */, XFA_Attribute::TrayIn}, + {0xa433f001 /* bindingNode */, XFA_Attribute::BindingNode}, + {0xa5340ff5 /* bofAction */, XFA_Attribute::BofAction}, + {0xa5b410cf /* save */, XFA_Attribute::Save}, + {0xa6118c89 /* targetType */, XFA_Attribute::TargetType}, + {0xa66404cb /* keyEncipherment */, XFA_Attribute::KeyEncipherment}, + {0xa6710262 /* credentialServerPolicy */, + XFA_Attribute::CredentialServerPolicy}, + {0xa686975b /* size */, XFA_Attribute::Size}, + {0xa85e74f3 /* initialNumber */, XFA_Attribute::InitialNumber}, + {0xabef37e3 /* slope */, XFA_Attribute::Slope}, + {0xabfa6c4f /* cSpace */, XFA_Attribute::CSpace}, + {0xac06e2b0 /* colSpan */, XFA_Attribute::ColSpan}, + {0xadc4c77b /* binding */, XFA_Attribute::Binding}, + {0xaf754613 /* checksum */, XFA_Attribute::Checksum}, + {0xb045fbc5 /* charEncoding */, XFA_Attribute::CharEncoding}, + {0xb0e5485d /* bind */, XFA_Attribute::Bind}, + {0xb12128b7 /* textEntry */, XFA_Attribute::TextEntry}, + {0xb373a862 /* archive */, XFA_Attribute::Archive}, + {0xb598a1f7 /* uuid */, XFA_Attribute::Uuid}, + {0xb5e49bf2 /* posture */, XFA_Attribute::Posture}, + {0xb6b44172 /* after */, XFA_Attribute::After}, + {0xb716467b /* orphans */, XFA_Attribute::Orphans}, + {0xbc0c4695 /* qualifiedName */, XFA_Attribute::QualifiedName}, + {0xbc254332 /* usehref */, XFA_Attribute::Usehref}, + {0xbc8fa350 /* locale */, XFA_Attribute::Locale}, + {0xbd6e1d88 /* weight */, XFA_Attribute::Weight}, + {0xbd96a0e9 /* underlinePeriod */, XFA_Attribute::UnderlinePeriod}, + {0xbde9abda /* data */, XFA_Attribute::Data}, + {0xbe52dfbf /* desc */, XFA_Attribute::Desc}, + {0xbe9ba472 /* numbered */, XFA_Attribute::Numbered}, + {0xc035c6b1 /* dataColumnCount */, XFA_Attribute::DataColumnCount}, + {0xc0ec9fa4 /* overline */, XFA_Attribute::Overline}, + {0xc2ba0923 /* urlPolicy */, XFA_Attribute::UrlPolicy}, + {0xc2bd40fd /* anchorType */, XFA_Attribute::AnchorType}, + {0xc39a88bd /* labelRef */, XFA_Attribute::LabelRef}, + {0xc3c1442f /* bookendLeader */, XFA_Attribute::BookendLeader}, + {0xc4547a08 /* maxLength */, XFA_Attribute::MaxLength}, + {0xc4fed09b /* accessKey */, XFA_Attribute::AccessKey}, + {0xc5762157 /* cursorLocation */, XFA_Attribute::CursorLocation}, + {0xc860f30a /* delayedOpen */, XFA_Attribute::DelayedOpen}, + {0xc8da4da7 /* target */, XFA_Attribute::Target}, + {0xca5dc27c /* dataEncipherment */, XFA_Attribute::DataEncipherment}, + {0xcb150479 /* afterTarget */, XFA_Attribute::AfterTarget}, + {0xcbcaf66d /* leader */, XFA_Attribute::Leader}, + {0xcca7897e /* picker */, XFA_Attribute::Picker}, + {0xcd7f7b54 /* from */, XFA_Attribute::From}, + {0xcea5e62c /* baseProfile */, XFA_Attribute::BaseProfile}, + {0xd171b240 /* aspect */, XFA_Attribute::Aspect}, + {0xd3c84d25 /* rowColumnRatio */, XFA_Attribute::RowColumnRatio}, + {0xd4b01921 /* lineHeight */, XFA_Attribute::LineHeight}, + {0xd4cc53f8 /* highlight */, XFA_Attribute::Highlight}, + {0xd50f903a /* valueRef */, XFA_Attribute::ValueRef}, + {0xd52482e0 /* maxEntries */, XFA_Attribute::MaxEntries}, + {0xd57c513c /* dataLength */, XFA_Attribute::DataLength}, + {0xd6128d8d /* activity */, XFA_Attribute::Activity}, + {0xd6a39990 /* input */, XFA_Attribute::Input}, + {0xd6e27f1d /* value */, XFA_Attribute::Value}, + {0xd70798c2 /* blankOrNotBlank */, XFA_Attribute::BlankOrNotBlank}, + {0xd861f8af /* addRevocationInfo */, XFA_Attribute::AddRevocationInfo}, + {0xd8f982bf /* genericFamily */, XFA_Attribute::GenericFamily}, + {0xd996fa9b /* hand */, XFA_Attribute::Hand}, + {0xdb55fec5 /* href */, XFA_Attribute::Href}, + {0xdc75676c /* textEncoding */, XFA_Attribute::TextEncoding}, + {0xde7f92ba /* leadDigits */, XFA_Attribute::LeadDigits}, + {0xe11a2cbc /* permissions */, XFA_Attribute::Permissions}, + {0xe18b5659 /* spaceAbove */, XFA_Attribute::SpaceAbove}, + {0xe1a26b56 /* codeBase */, XFA_Attribute::CodeBase}, + {0xe349d044 /* stock */, XFA_Attribute::Stock}, + {0xe372ae97 /* isNull */, XFA_Attribute::IsNull}, + {0xe4c3a5e5 /* restoreState */, XFA_Attribute::RestoreState}, + {0xe5c96d6a /* excludeAllCaps */, XFA_Attribute::ExcludeAllCaps}, + {0xe64b1129 /* formatTest */, XFA_Attribute::FormatTest}, + {0xe6f99487 /* hScrollPolicy */, XFA_Attribute::HScrollPolicy}, + {0xe8dddf50 /* join */, XFA_Attribute::Join}, + {0xe8f118a8 /* keyCertSign */, XFA_Attribute::KeyCertSign}, + {0xe948b9a8 /* radius */, XFA_Attribute::Radius}, + {0xe996b2fe /* sourceAbove */, XFA_Attribute::SourceAbove}, + {0xea7090a0 /* override */, XFA_Attribute::Override}, + {0xeb091003 /* classId */, XFA_Attribute::ClassId}, + {0xeb511b54 /* disable */, XFA_Attribute::Disable}, + {0xeda9017a /* scope */, XFA_Attribute::Scope}, + {0xf197844d /* match */, XFA_Attribute::Match}, + {0xf2009339 /* placement */, XFA_Attribute::Placement}, + {0xf4ffce73 /* before */, XFA_Attribute::Before}, + {0xf531b059 /* writingScript */, XFA_Attribute::WritingScript}, + {0xf575ca75 /* endChar */, XFA_Attribute::EndChar}, + {0xf6b47749 /* lock */, XFA_Attribute::Lock}, + {0xf6b4afb0 /* long */, XFA_Attribute::Long}, + {0xf6b59543 /* intact */, XFA_Attribute::Intact}, + {0xf889e747 /* xdpContent */, XFA_Attribute::XdpContent}, + {0xfea53ec6 /* decipherOnly */, XFA_Attribute::DecipherOnly}, +}; + +} // namespace + +// static +XFA_Element CXFA_Node::NameToElement(const WideString& name) { + uint32_t hash = FX_HashCode_GetW(name.AsStringView(), false); + auto* elem = std::lower_bound( + std::begin(ElementNameToEnum), std::end(ElementNameToEnum), hash, + [](const ElementNameInfo& a, uint32_t hash) { return a.hash < hash; }); + if (elem != std::end(ElementNameToEnum) && elem->hash == hash) + return elem->element; + return XFA_Element::Unknown; +} + +// static +XFA_Attribute CXFA_Node::NameToAttribute(const WideStringView& name) { + uint32_t hash = FX_HashCode_GetW(name, false); + auto* elem = std::lower_bound( + std::begin(AttributeNameInfoToEnum), std::end(AttributeNameInfoToEnum), + hash, + [](const AttributeNameInfo& a, uint32_t hash) { return a.hash < hash; }); + if (elem != std::end(AttributeNameInfoToEnum) && elem->hash == hash) + return elem->attribute; + return XFA_Attribute::Unknown; +} + +// static +std::unique_ptr<CXFA_Node> CXFA_Node::Create(CXFA_Document* doc, + XFA_Element element, + XFA_PacketType packet) { + std::unique_ptr<CXFA_Node> node; + switch (element) { + case XFA_Element::Ps: + node = pdfium::MakeUnique<CXFA_Ps>(doc, packet); + break; + case XFA_Element::To: + node = pdfium::MakeUnique<CXFA_To>(doc, packet); + break; + case XFA_Element::Ui: + node = pdfium::MakeUnique<CXFA_Ui>(doc, packet); + break; + case XFA_Element::RecordSet: + node = pdfium::MakeUnique<CXFA_RecordSet>(doc, packet); + break; + case XFA_Element::SubsetBelow: + node = pdfium::MakeUnique<CXFA_SubsetBelow>(doc, packet); + break; + case XFA_Element::SubformSet: + node = pdfium::MakeUnique<CXFA_SubformSet>(doc, packet); + break; + case XFA_Element::AdobeExtensionLevel: + node = pdfium::MakeUnique<CXFA_AdobeExtensionLevel>(doc, packet); + break; + case XFA_Element::Typeface: + node = pdfium::MakeUnique<CXFA_Typeface>(doc, packet); + break; + case XFA_Element::Break: + node = pdfium::MakeUnique<CXFA_Break>(doc, packet); + break; + case XFA_Element::FontInfo: + node = pdfium::MakeUnique<CXFA_FontInfo>(doc, packet); + break; + case XFA_Element::NumberPattern: + node = pdfium::MakeUnique<CXFA_NumberPattern>(doc, packet); + break; + case XFA_Element::DynamicRender: + node = pdfium::MakeUnique<CXFA_DynamicRender>(doc, packet); + break; + case XFA_Element::PrintScaling: + node = pdfium::MakeUnique<CXFA_PrintScaling>(doc, packet); + break; + case XFA_Element::CheckButton: + node = pdfium::MakeUnique<CXFA_CheckButton>(doc, packet); + break; + case XFA_Element::DatePatterns: + node = pdfium::MakeUnique<CXFA_DatePatterns>(doc, packet); + break; + case XFA_Element::SourceSet: + node = pdfium::MakeUnique<CXFA_SourceSet>(doc, packet); + break; + case XFA_Element::Amd: + node = pdfium::MakeUnique<CXFA_Amd>(doc, packet); + break; + case XFA_Element::Arc: + node = pdfium::MakeUnique<CXFA_Arc>(doc, packet); + break; + case XFA_Element::Day: + node = pdfium::MakeUnique<CXFA_Day>(doc, packet); + break; + case XFA_Element::Era: + node = pdfium::MakeUnique<CXFA_Era>(doc, packet); + break; + case XFA_Element::Jog: + node = pdfium::MakeUnique<CXFA_Jog>(doc, packet); + break; + case XFA_Element::Log: + node = pdfium::MakeUnique<CXFA_Log>(doc, packet); + break; + case XFA_Element::Map: + node = pdfium::MakeUnique<CXFA_Map>(doc, packet); + break; + case XFA_Element::Mdp: + node = pdfium::MakeUnique<CXFA_Mdp>(doc, packet); + break; + case XFA_Element::BreakBefore: + node = pdfium::MakeUnique<CXFA_BreakBefore>(doc, packet); + break; + case XFA_Element::Oid: + node = pdfium::MakeUnique<CXFA_Oid>(doc, packet); + break; + case XFA_Element::Pcl: + node = pdfium::MakeUnique<CXFA_Pcl>(doc, packet); + break; + case XFA_Element::Pdf: + node = pdfium::MakeUnique<CXFA_Pdf>(doc, packet); + break; + case XFA_Element::Ref: + node = pdfium::MakeUnique<CXFA_Ref>(doc, packet); + break; + case XFA_Element::Uri: + node = pdfium::MakeUnique<CXFA_Uri>(doc, packet); + break; + case XFA_Element::Xdc: + node = pdfium::MakeUnique<CXFA_Xdc>(doc, packet); + break; + case XFA_Element::Xdp: + node = pdfium::MakeUnique<CXFA_Xdp>(doc, packet); + break; + case XFA_Element::Xfa: + node = pdfium::MakeUnique<CXFA_Xfa>(doc, packet); + break; + case XFA_Element::Xsl: + node = pdfium::MakeUnique<CXFA_Xsl>(doc, packet); + break; + case XFA_Element::Zpl: + node = pdfium::MakeUnique<CXFA_Zpl>(doc, packet); + break; + case XFA_Element::Cache: + node = pdfium::MakeUnique<CXFA_Cache>(doc, packet); + break; + case XFA_Element::Margin: + node = pdfium::MakeUnique<CXFA_Margin>(doc, packet); + break; + case XFA_Element::KeyUsage: + node = pdfium::MakeUnique<CXFA_KeyUsage>(doc, packet); + break; + case XFA_Element::Exclude: + node = pdfium::MakeUnique<CXFA_Exclude>(doc, packet); + break; + case XFA_Element::ChoiceList: + node = pdfium::MakeUnique<CXFA_ChoiceList>(doc, packet); + break; + case XFA_Element::Level: + node = pdfium::MakeUnique<CXFA_Level>(doc, packet); + break; + case XFA_Element::LabelPrinter: + node = pdfium::MakeUnique<CXFA_LabelPrinter>(doc, packet); + break; + case XFA_Element::CalendarSymbols: + node = pdfium::MakeUnique<CXFA_CalendarSymbols>(doc, packet); + break; + case XFA_Element::Para: + node = pdfium::MakeUnique<CXFA_Para>(doc, packet); + break; + case XFA_Element::Part: + node = pdfium::MakeUnique<CXFA_Part>(doc, packet); + break; + case XFA_Element::Pdfa: + node = pdfium::MakeUnique<CXFA_Pdfa>(doc, packet); + break; + case XFA_Element::Filter: + node = pdfium::MakeUnique<CXFA_Filter>(doc, packet); + break; + case XFA_Element::Present: + node = pdfium::MakeUnique<CXFA_Present>(doc, packet); + break; + case XFA_Element::Pagination: + node = pdfium::MakeUnique<CXFA_Pagination>(doc, packet); + break; + case XFA_Element::Encoding: + node = pdfium::MakeUnique<CXFA_Encoding>(doc, packet); + break; + case XFA_Element::Event: + node = pdfium::MakeUnique<CXFA_Event>(doc, packet); + break; + case XFA_Element::Whitespace: + node = pdfium::MakeUnique<CXFA_Whitespace>(doc, packet); + break; + case XFA_Element::DefaultUi: + node = pdfium::MakeUnique<CXFA_DefaultUi>(doc, packet); + break; + case XFA_Element::DataModel: + node = pdfium::MakeUnique<CXFA_DataModel>(doc, packet); + break; + case XFA_Element::Barcode: + node = pdfium::MakeUnique<CXFA_Barcode>(doc, packet); + break; + case XFA_Element::TimePattern: + node = pdfium::MakeUnique<CXFA_TimePattern>(doc, packet); + break; + case XFA_Element::BatchOutput: + node = pdfium::MakeUnique<CXFA_BatchOutput>(doc, packet); + break; + case XFA_Element::Enforce: + node = pdfium::MakeUnique<CXFA_Enforce>(doc, packet); + break; + case XFA_Element::CurrencySymbols: + node = pdfium::MakeUnique<CXFA_CurrencySymbols>(doc, packet); + break; + case XFA_Element::AddSilentPrint: + node = pdfium::MakeUnique<CXFA_AddSilentPrint>(doc, packet); + break; + case XFA_Element::Rename: + node = pdfium::MakeUnique<CXFA_Rename>(doc, packet); + break; + case XFA_Element::Operation: + node = pdfium::MakeUnique<CXFA_Operation>(doc, packet); + break; + case XFA_Element::Typefaces: + node = pdfium::MakeUnique<CXFA_Typefaces>(doc, packet); + break; + case XFA_Element::SubjectDNs: + node = pdfium::MakeUnique<CXFA_SubjectDNs>(doc, packet); + break; + case XFA_Element::Issuers: + node = pdfium::MakeUnique<CXFA_Issuers>(doc, packet); + break; + case XFA_Element::WsdlConnection: + node = pdfium::MakeUnique<CXFA_WsdlConnection>(doc, packet); + break; + case XFA_Element::Debug: + node = pdfium::MakeUnique<CXFA_Debug>(doc, packet); + break; + case XFA_Element::Delta: + node = pdfium::MakeUnique<CXFA_Delta>(doc, packet); + break; + case XFA_Element::EraNames: + node = pdfium::MakeUnique<CXFA_EraNames>(doc, packet); + break; + case XFA_Element::ModifyAnnots: + node = pdfium::MakeUnique<CXFA_ModifyAnnots>(doc, packet); + break; + case XFA_Element::StartNode: + node = pdfium::MakeUnique<CXFA_StartNode>(doc, packet); + break; + case XFA_Element::Button: + node = pdfium::MakeUnique<CXFA_Button>(doc, packet); + break; + case XFA_Element::Format: + node = pdfium::MakeUnique<CXFA_Format>(doc, packet); + break; + case XFA_Element::Border: + node = pdfium::MakeUnique<CXFA_Border>(doc, packet); + break; + case XFA_Element::Area: + node = pdfium::MakeUnique<CXFA_Area>(doc, packet); + break; + case XFA_Element::Hyphenation: + node = pdfium::MakeUnique<CXFA_Hyphenation>(doc, packet); + break; + case XFA_Element::Text: + node = pdfium::MakeUnique<CXFA_Text>(doc, packet); + break; + case XFA_Element::Time: + node = pdfium::MakeUnique<CXFA_Time>(doc, packet); + break; + case XFA_Element::Type: + node = pdfium::MakeUnique<CXFA_Type>(doc, packet); + break; + case XFA_Element::Overprint: + node = pdfium::MakeUnique<CXFA_Overprint>(doc, packet); + break; + case XFA_Element::Certificates: + node = pdfium::MakeUnique<CXFA_Certificates>(doc, packet); + break; + case XFA_Element::EncryptionMethods: + node = pdfium::MakeUnique<CXFA_EncryptionMethods>(doc, packet); + break; + case XFA_Element::SetProperty: + node = pdfium::MakeUnique<CXFA_SetProperty>(doc, packet); + break; + case XFA_Element::PrinterName: + node = pdfium::MakeUnique<CXFA_PrinterName>(doc, packet); + break; + case XFA_Element::StartPage: + node = pdfium::MakeUnique<CXFA_StartPage>(doc, packet); + break; + case XFA_Element::PageOffset: + node = pdfium::MakeUnique<CXFA_PageOffset>(doc, packet); + break; + case XFA_Element::DateTime: + node = pdfium::MakeUnique<CXFA_DateTime>(doc, packet); + break; + case XFA_Element::Comb: + node = pdfium::MakeUnique<CXFA_Comb>(doc, packet); + break; + case XFA_Element::Pattern: + node = pdfium::MakeUnique<CXFA_Pattern>(doc, packet); + break; + case XFA_Element::IfEmpty: + node = pdfium::MakeUnique<CXFA_IfEmpty>(doc, packet); + break; + case XFA_Element::SuppressBanner: + node = pdfium::MakeUnique<CXFA_SuppressBanner>(doc, packet); + break; + case XFA_Element::OutputBin: + node = pdfium::MakeUnique<CXFA_OutputBin>(doc, packet); + break; + case XFA_Element::Field: + node = pdfium::MakeUnique<CXFA_Field>(doc, packet); + break; + case XFA_Element::Agent: + node = pdfium::MakeUnique<CXFA_Agent>(doc, packet); + break; + case XFA_Element::OutputXSL: + node = pdfium::MakeUnique<CXFA_OutputXSL>(doc, packet); + break; + case XFA_Element::AdjustData: + node = pdfium::MakeUnique<CXFA_AdjustData>(doc, packet); + break; + case XFA_Element::AutoSave: + node = pdfium::MakeUnique<CXFA_AutoSave>(doc, packet); + break; + case XFA_Element::ContentArea: + node = pdfium::MakeUnique<CXFA_ContentArea>(doc, packet); + break; + case XFA_Element::WsdlAddress: + node = pdfium::MakeUnique<CXFA_WsdlAddress>(doc, packet); + break; + case XFA_Element::Solid: + node = pdfium::MakeUnique<CXFA_Solid>(doc, packet); + break; + case XFA_Element::DateTimeSymbols: + node = pdfium::MakeUnique<CXFA_DateTimeSymbols>(doc, packet); + break; + case XFA_Element::EncryptionLevel: + node = pdfium::MakeUnique<CXFA_EncryptionLevel>(doc, packet); + break; + case XFA_Element::Edge: + node = pdfium::MakeUnique<CXFA_Edge>(doc, packet); + break; + case XFA_Element::Stipple: + node = pdfium::MakeUnique<CXFA_Stipple>(doc, packet); + break; + case XFA_Element::Attributes: + node = pdfium::MakeUnique<CXFA_Attributes>(doc, packet); + break; + case XFA_Element::VersionControl: + node = pdfium::MakeUnique<CXFA_VersionControl>(doc, packet); + break; + case XFA_Element::Meridiem: + node = pdfium::MakeUnique<CXFA_Meridiem>(doc, packet); + break; + case XFA_Element::ExclGroup: + node = pdfium::MakeUnique<CXFA_ExclGroup>(doc, packet); + break; + case XFA_Element::ToolTip: + node = pdfium::MakeUnique<CXFA_ToolTip>(doc, packet); + break; + case XFA_Element::Compress: + node = pdfium::MakeUnique<CXFA_Compress>(doc, packet); + break; + case XFA_Element::Reason: + node = pdfium::MakeUnique<CXFA_Reason>(doc, packet); + break; + case XFA_Element::Execute: + node = pdfium::MakeUnique<CXFA_Execute>(doc, packet); + break; + case XFA_Element::ContentCopy: + node = pdfium::MakeUnique<CXFA_ContentCopy>(doc, packet); + break; + case XFA_Element::DateTimeEdit: + node = pdfium::MakeUnique<CXFA_DateTimeEdit>(doc, packet); + break; + case XFA_Element::Config: + node = pdfium::MakeUnique<CXFA_Config>(doc, packet); + break; + case XFA_Element::Image: + node = pdfium::MakeUnique<CXFA_Image>(doc, packet); + break; + case XFA_Element::SharpxHTML: + node = pdfium::MakeUnique<CXFA_SharpxHTML>(doc, packet); + break; + case XFA_Element::NumberOfCopies: + node = pdfium::MakeUnique<CXFA_NumberOfCopies>(doc, packet); + break; + case XFA_Element::BehaviorOverride: + node = pdfium::MakeUnique<CXFA_BehaviorOverride>(doc, packet); + break; + case XFA_Element::TimeStamp: + node = pdfium::MakeUnique<CXFA_TimeStamp>(doc, packet); + break; + case XFA_Element::Month: + node = pdfium::MakeUnique<CXFA_Month>(doc, packet); + break; + case XFA_Element::ViewerPreferences: + node = pdfium::MakeUnique<CXFA_ViewerPreferences>(doc, packet); + break; + case XFA_Element::ScriptModel: + node = pdfium::MakeUnique<CXFA_ScriptModel>(doc, packet); + break; + case XFA_Element::Decimal: + node = pdfium::MakeUnique<CXFA_Decimal>(doc, packet); + break; + case XFA_Element::Subform: + node = pdfium::MakeUnique<CXFA_Subform>(doc, packet); + break; + case XFA_Element::Select: + node = pdfium::MakeUnique<CXFA_Select>(doc, packet); + break; + case XFA_Element::Window: + node = pdfium::MakeUnique<CXFA_Window>(doc, packet); + break; + case XFA_Element::LocaleSet: + node = pdfium::MakeUnique<CXFA_LocaleSet>(doc, packet); + break; + case XFA_Element::Handler: + node = pdfium::MakeUnique<CXFA_Handler>(doc, packet); + break; + case XFA_Element::Presence: + node = pdfium::MakeUnique<CXFA_Presence>(doc, packet); + break; + case XFA_Element::Record: + node = pdfium::MakeUnique<CXFA_Record>(doc, packet); + break; + case XFA_Element::Embed: + node = pdfium::MakeUnique<CXFA_Embed>(doc, packet); + break; + case XFA_Element::Version: + node = pdfium::MakeUnique<CXFA_Version>(doc, packet); + break; + case XFA_Element::Command: + node = pdfium::MakeUnique<CXFA_Command>(doc, packet); + break; + case XFA_Element::Copies: + node = pdfium::MakeUnique<CXFA_Copies>(doc, packet); + break; + case XFA_Element::Staple: + node = pdfium::MakeUnique<CXFA_Staple>(doc, packet); + break; + case XFA_Element::SubmitFormat: + node = pdfium::MakeUnique<CXFA_SubmitFormat>(doc, packet); + break; + case XFA_Element::Boolean: + node = pdfium::MakeUnique<CXFA_Boolean>(doc, packet); + break; + case XFA_Element::Message: + node = pdfium::MakeUnique<CXFA_Message>(doc, packet); + break; + case XFA_Element::Output: + node = pdfium::MakeUnique<CXFA_Output>(doc, packet); + break; + case XFA_Element::PsMap: + node = pdfium::MakeUnique<CXFA_PsMap>(doc, packet); + break; + case XFA_Element::ExcludeNS: + node = pdfium::MakeUnique<CXFA_ExcludeNS>(doc, packet); + break; + case XFA_Element::Assist: + node = pdfium::MakeUnique<CXFA_Assist>(doc, packet); + break; + case XFA_Element::Picture: + node = pdfium::MakeUnique<CXFA_Picture>(doc, packet); + break; + case XFA_Element::Traversal: + node = pdfium::MakeUnique<CXFA_Traversal>(doc, packet); + break; + case XFA_Element::SilentPrint: + node = pdfium::MakeUnique<CXFA_SilentPrint>(doc, packet); + break; + case XFA_Element::WebClient: + node = pdfium::MakeUnique<CXFA_WebClient>(doc, packet); + break; + case XFA_Element::Producer: + node = pdfium::MakeUnique<CXFA_Producer>(doc, packet); + break; + case XFA_Element::Corner: + node = pdfium::MakeUnique<CXFA_Corner>(doc, packet); + break; + case XFA_Element::MsgId: + node = pdfium::MakeUnique<CXFA_MsgId>(doc, packet); + break; + case XFA_Element::Color: + node = pdfium::MakeUnique<CXFA_Color>(doc, packet); + break; + case XFA_Element::Keep: + node = pdfium::MakeUnique<CXFA_Keep>(doc, packet); + break; + case XFA_Element::Query: + node = pdfium::MakeUnique<CXFA_Query>(doc, packet); + break; + case XFA_Element::Insert: + node = pdfium::MakeUnique<CXFA_Insert>(doc, packet); + break; + case XFA_Element::ImageEdit: + node = pdfium::MakeUnique<CXFA_ImageEdit>(doc, packet); + break; + case XFA_Element::Validate: + node = pdfium::MakeUnique<CXFA_Validate>(doc, packet); + break; + case XFA_Element::DigestMethods: + node = pdfium::MakeUnique<CXFA_DigestMethods>(doc, packet); + break; + case XFA_Element::NumberPatterns: + node = pdfium::MakeUnique<CXFA_NumberPatterns>(doc, packet); + break; + case XFA_Element::PageSet: + node = pdfium::MakeUnique<CXFA_PageSet>(doc, packet); + break; + case XFA_Element::Integer: + node = pdfium::MakeUnique<CXFA_Integer>(doc, packet); + break; + case XFA_Element::SoapAddress: + node = pdfium::MakeUnique<CXFA_SoapAddress>(doc, packet); + break; + case XFA_Element::Equate: + node = pdfium::MakeUnique<CXFA_Equate>(doc, packet); + break; + case XFA_Element::FormFieldFilling: + node = pdfium::MakeUnique<CXFA_FormFieldFilling>(doc, packet); + break; + case XFA_Element::PageRange: + node = pdfium::MakeUnique<CXFA_PageRange>(doc, packet); + break; + case XFA_Element::Update: + node = pdfium::MakeUnique<CXFA_Update>(doc, packet); + break; + case XFA_Element::ConnectString: + node = pdfium::MakeUnique<CXFA_ConnectString>(doc, packet); + break; + case XFA_Element::Mode: + node = pdfium::MakeUnique<CXFA_Mode>(doc, packet); + break; + case XFA_Element::Layout: + node = pdfium::MakeUnique<CXFA_Layout>(doc, packet); + break; + case XFA_Element::Sharpxml: + node = pdfium::MakeUnique<CXFA_Sharpxml>(doc, packet); + break; + case XFA_Element::XsdConnection: + node = pdfium::MakeUnique<CXFA_XsdConnection>(doc, packet); + break; + case XFA_Element::Traverse: + node = pdfium::MakeUnique<CXFA_Traverse>(doc, packet); + break; + case XFA_Element::Encodings: + node = pdfium::MakeUnique<CXFA_Encodings>(doc, packet); + break; + case XFA_Element::Template: + node = pdfium::MakeUnique<CXFA_Template>(doc, packet); + break; + case XFA_Element::Acrobat: + node = pdfium::MakeUnique<CXFA_Acrobat>(doc, packet); + break; + case XFA_Element::ValidationMessaging: + node = pdfium::MakeUnique<CXFA_ValidationMessaging>(doc, packet); + break; + case XFA_Element::Signing: + node = pdfium::MakeUnique<CXFA_Signing>(doc, packet); + break; + case XFA_Element::Script: + node = pdfium::MakeUnique<CXFA_Script>(doc, packet); + break; + case XFA_Element::AddViewerPreferences: + node = pdfium::MakeUnique<CXFA_AddViewerPreferences>(doc, packet); + break; + case XFA_Element::AlwaysEmbed: + node = pdfium::MakeUnique<CXFA_AlwaysEmbed>(doc, packet); + break; + case XFA_Element::PasswordEdit: + node = pdfium::MakeUnique<CXFA_PasswordEdit>(doc, packet); + break; + case XFA_Element::NumericEdit: + node = pdfium::MakeUnique<CXFA_NumericEdit>(doc, packet); + break; + case XFA_Element::EncryptionMethod: + node = pdfium::MakeUnique<CXFA_EncryptionMethod>(doc, packet); + break; + case XFA_Element::Change: + node = pdfium::MakeUnique<CXFA_Change>(doc, packet); + break; + case XFA_Element::PageArea: + node = pdfium::MakeUnique<CXFA_PageArea>(doc, packet); + break; + case XFA_Element::SubmitUrl: + node = pdfium::MakeUnique<CXFA_SubmitUrl>(doc, packet); + break; + case XFA_Element::Oids: + node = pdfium::MakeUnique<CXFA_Oids>(doc, packet); + break; + case XFA_Element::Signature: + node = pdfium::MakeUnique<CXFA_Signature>(doc, packet); + break; + case XFA_Element::ADBE_JSConsole: + node = pdfium::MakeUnique<CXFA_aDBE_JSConsole>(doc, packet); + break; + case XFA_Element::Caption: + node = pdfium::MakeUnique<CXFA_Caption>(doc, packet); + break; + case XFA_Element::Relevant: + node = pdfium::MakeUnique<CXFA_Relevant>(doc, packet); + break; + case XFA_Element::FlipLabel: + node = pdfium::MakeUnique<CXFA_FlipLabel>(doc, packet); + break; + case XFA_Element::ExData: + node = pdfium::MakeUnique<CXFA_ExData>(doc, packet); + break; + case XFA_Element::DayNames: + node = pdfium::MakeUnique<CXFA_DayNames>(doc, packet); + break; + case XFA_Element::SoapAction: + node = pdfium::MakeUnique<CXFA_SoapAction>(doc, packet); + break; + case XFA_Element::DefaultTypeface: + node = pdfium::MakeUnique<CXFA_DefaultTypeface>(doc, packet); + break; + case XFA_Element::Manifest: + node = pdfium::MakeUnique<CXFA_Manifest>(doc, packet); + break; + case XFA_Element::Overflow: + node = pdfium::MakeUnique<CXFA_Overflow>(doc, packet); + break; + case XFA_Element::Linear: + node = pdfium::MakeUnique<CXFA_Linear>(doc, packet); + break; + case XFA_Element::CurrencySymbol: + node = pdfium::MakeUnique<CXFA_CurrencySymbol>(doc, packet); + break; + case XFA_Element::Delete: + node = pdfium::MakeUnique<CXFA_Delete>(doc, packet); + break; + case XFA_Element::DigestMethod: + node = pdfium::MakeUnique<CXFA_DigestMethod>(doc, packet); + break; + case XFA_Element::InstanceManager: + node = pdfium::MakeUnique<CXFA_InstanceManager>(doc, packet); + break; + case XFA_Element::EquateRange: + node = pdfium::MakeUnique<CXFA_EquateRange>(doc, packet); + break; + case XFA_Element::Medium: + node = pdfium::MakeUnique<CXFA_Medium>(doc, packet); + break; + case XFA_Element::TextEdit: + node = pdfium::MakeUnique<CXFA_TextEdit>(doc, packet); + break; + case XFA_Element::TemplateCache: + node = pdfium::MakeUnique<CXFA_TemplateCache>(doc, packet); + break; + case XFA_Element::CompressObjectStream: + node = pdfium::MakeUnique<CXFA_CompressObjectStream>(doc, packet); + break; + case XFA_Element::DataValue: + node = pdfium::MakeUnique<CXFA_DataValue>(doc, packet); + break; + case XFA_Element::AccessibleContent: + node = pdfium::MakeUnique<CXFA_AccessibleContent>(doc, packet); + break; + case XFA_Element::IncludeXDPContent: + node = pdfium::MakeUnique<CXFA_IncludeXDPContent>(doc, packet); + break; + case XFA_Element::XmlConnection: + node = pdfium::MakeUnique<CXFA_XmlConnection>(doc, packet); + break; + case XFA_Element::ValidateApprovalSignatures: + node = pdfium::MakeUnique<CXFA_ValidateApprovalSignatures>(doc, packet); + break; + case XFA_Element::SignData: + node = pdfium::MakeUnique<CXFA_SignData>(doc, packet); + break; + case XFA_Element::Packets: + node = pdfium::MakeUnique<CXFA_Packets>(doc, packet); + break; + case XFA_Element::DatePattern: + node = pdfium::MakeUnique<CXFA_DatePattern>(doc, packet); + break; + case XFA_Element::DuplexOption: + node = pdfium::MakeUnique<CXFA_DuplexOption>(doc, packet); + break; + case XFA_Element::Base: + node = pdfium::MakeUnique<CXFA_Base>(doc, packet); + break; + case XFA_Element::Bind: + node = pdfium::MakeUnique<CXFA_Bind>(doc, packet); + break; + case XFA_Element::Compression: + node = pdfium::MakeUnique<CXFA_Compression>(doc, packet); + break; + case XFA_Element::User: + node = pdfium::MakeUnique<CXFA_User>(doc, packet); + break; + case XFA_Element::Rectangle: + node = pdfium::MakeUnique<CXFA_Rectangle>(doc, packet); + break; + case XFA_Element::EffectiveOutputPolicy: + node = pdfium::MakeUnique<CXFA_EffectiveOutputPolicy>(doc, packet); + break; + case XFA_Element::ADBE_JSDebugger: + node = pdfium::MakeUnique<CXFA_aDBE_JSDebugger>(doc, packet); + break; + case XFA_Element::Acrobat7: + node = pdfium::MakeUnique<CXFA_Acrobat7>(doc, packet); + break; + case XFA_Element::Interactive: + node = pdfium::MakeUnique<CXFA_Interactive>(doc, packet); + break; + case XFA_Element::Locale: + node = pdfium::MakeUnique<CXFA_Locale>(doc, packet); + break; + case XFA_Element::CurrentPage: + node = pdfium::MakeUnique<CXFA_CurrentPage>(doc, packet); + break; + case XFA_Element::Data: + node = pdfium::MakeUnique<CXFA_Data>(doc, packet); + break; + case XFA_Element::Date: + node = pdfium::MakeUnique<CXFA_Date>(doc, packet); + break; + case XFA_Element::Desc: + node = pdfium::MakeUnique<CXFA_Desc>(doc, packet); + break; + case XFA_Element::Encrypt: + node = pdfium::MakeUnique<CXFA_Encrypt>(doc, packet); + break; + case XFA_Element::Draw: + node = pdfium::MakeUnique<CXFA_Draw>(doc, packet); + break; + case XFA_Element::Encryption: + node = pdfium::MakeUnique<CXFA_Encryption>(doc, packet); + break; + case XFA_Element::MeridiemNames: + node = pdfium::MakeUnique<CXFA_MeridiemNames>(doc, packet); + break; + case XFA_Element::Messaging: + node = pdfium::MakeUnique<CXFA_Messaging>(doc, packet); + break; + case XFA_Element::Speak: + node = pdfium::MakeUnique<CXFA_Speak>(doc, packet); + break; + case XFA_Element::DataGroup: + node = pdfium::MakeUnique<CXFA_DataGroup>(doc, packet); + break; + case XFA_Element::Common: + node = pdfium::MakeUnique<CXFA_Common>(doc, packet); + break; + case XFA_Element::Sharptext: + node = pdfium::MakeUnique<CXFA_Sharptext>(doc, packet); + break; + case XFA_Element::PaginationOverride: + node = pdfium::MakeUnique<CXFA_PaginationOverride>(doc, packet); + break; + case XFA_Element::Reasons: + node = pdfium::MakeUnique<CXFA_Reasons>(doc, packet); + break; + case XFA_Element::SignatureProperties: + node = pdfium::MakeUnique<CXFA_SignatureProperties>(doc, packet); + break; + case XFA_Element::Threshold: + node = pdfium::MakeUnique<CXFA_Threshold>(doc, packet); + break; + case XFA_Element::AppearanceFilter: + node = pdfium::MakeUnique<CXFA_AppearanceFilter>(doc, packet); + break; + case XFA_Element::Fill: + node = pdfium::MakeUnique<CXFA_Fill>(doc, packet); + break; + case XFA_Element::Font: + node = pdfium::MakeUnique<CXFA_Font>(doc, packet); + break; + case XFA_Element::Form: + node = pdfium::MakeUnique<CXFA_Form>(doc, packet); + break; + case XFA_Element::MediumInfo: + node = pdfium::MakeUnique<CXFA_MediumInfo>(doc, packet); + break; + case XFA_Element::Certificate: + node = pdfium::MakeUnique<CXFA_Certificate>(doc, packet); + break; + case XFA_Element::Password: + node = pdfium::MakeUnique<CXFA_Password>(doc, packet); + break; + case XFA_Element::RunScripts: + node = pdfium::MakeUnique<CXFA_RunScripts>(doc, packet); + break; + case XFA_Element::Trace: + node = pdfium::MakeUnique<CXFA_Trace>(doc, packet); + break; + case XFA_Element::Float: + node = pdfium::MakeUnique<CXFA_Float>(doc, packet); + break; + case XFA_Element::RenderPolicy: + node = pdfium::MakeUnique<CXFA_RenderPolicy>(doc, packet); + break; + case XFA_Element::Destination: + node = pdfium::MakeUnique<CXFA_Destination>(doc, packet); + break; + case XFA_Element::Value: + node = pdfium::MakeUnique<CXFA_Value>(doc, packet); + break; + case XFA_Element::Bookend: + node = pdfium::MakeUnique<CXFA_Bookend>(doc, packet); + break; + case XFA_Element::ExObject: + node = pdfium::MakeUnique<CXFA_ExObject>(doc, packet); + break; + case XFA_Element::OpenAction: + node = pdfium::MakeUnique<CXFA_OpenAction>(doc, packet); + break; + case XFA_Element::NeverEmbed: + node = pdfium::MakeUnique<CXFA_NeverEmbed>(doc, packet); + break; + case XFA_Element::BindItems: + node = pdfium::MakeUnique<CXFA_BindItems>(doc, packet); + break; + case XFA_Element::Calculate: + node = pdfium::MakeUnique<CXFA_Calculate>(doc, packet); + break; + case XFA_Element::Print: + node = pdfium::MakeUnique<CXFA_Print>(doc, packet); + break; + case XFA_Element::Extras: + node = pdfium::MakeUnique<CXFA_Extras>(doc, packet); + break; + case XFA_Element::Proto: + node = pdfium::MakeUnique<CXFA_Proto>(doc, packet); + break; + case XFA_Element::DSigData: + node = pdfium::MakeUnique<CXFA_DSigData>(doc, packet); + break; + case XFA_Element::Creator: + node = pdfium::MakeUnique<CXFA_Creator>(doc, packet); + break; + case XFA_Element::Connect: + node = pdfium::MakeUnique<CXFA_Connect>(doc, packet); + break; + case XFA_Element::Permissions: + node = pdfium::MakeUnique<CXFA_Permissions>(doc, packet); + break; + case XFA_Element::ConnectionSet: + node = pdfium::MakeUnique<CXFA_ConnectionSet>(doc, packet); + break; + case XFA_Element::Submit: + node = pdfium::MakeUnique<CXFA_Submit>(doc, packet); + break; + case XFA_Element::Range: + node = pdfium::MakeUnique<CXFA_Range>(doc, packet); + break; + case XFA_Element::Linearized: + node = pdfium::MakeUnique<CXFA_Linearized>(doc, packet); + break; + case XFA_Element::Packet: + node = pdfium::MakeUnique<CXFA_Packet>(doc, packet); + break; + case XFA_Element::RootElement: + node = pdfium::MakeUnique<CXFA_RootElement>(doc, packet); + break; + case XFA_Element::PlaintextMetadata: + node = pdfium::MakeUnique<CXFA_PlaintextMetadata>(doc, packet); + break; + case XFA_Element::NumberSymbols: + node = pdfium::MakeUnique<CXFA_NumberSymbols>(doc, packet); + break; + case XFA_Element::PrintHighQuality: + node = pdfium::MakeUnique<CXFA_PrintHighQuality>(doc, packet); + break; + case XFA_Element::Driver: + node = pdfium::MakeUnique<CXFA_Driver>(doc, packet); + break; + case XFA_Element::IncrementalLoad: + node = pdfium::MakeUnique<CXFA_IncrementalLoad>(doc, packet); + break; + case XFA_Element::SubjectDN: + node = pdfium::MakeUnique<CXFA_SubjectDN>(doc, packet); + break; + case XFA_Element::CompressLogicalStructure: + node = pdfium::MakeUnique<CXFA_CompressLogicalStructure>(doc, packet); + break; + case XFA_Element::IncrementalMerge: + node = pdfium::MakeUnique<CXFA_IncrementalMerge>(doc, packet); + break; + case XFA_Element::Radial: + node = pdfium::MakeUnique<CXFA_Radial>(doc, packet); + break; + case XFA_Element::Variables: + node = pdfium::MakeUnique<CXFA_Variables>(doc, packet); + break; + case XFA_Element::TimePatterns: + node = pdfium::MakeUnique<CXFA_TimePatterns>(doc, packet); + break; + case XFA_Element::EffectiveInputPolicy: + node = pdfium::MakeUnique<CXFA_EffectiveInputPolicy>(doc, packet); + break; + case XFA_Element::NameAttr: + node = pdfium::MakeUnique<CXFA_NameAttr>(doc, packet); + break; + case XFA_Element::Conformance: + node = pdfium::MakeUnique<CXFA_Conformance>(doc, packet); + break; + case XFA_Element::Transform: + node = pdfium::MakeUnique<CXFA_Transform>(doc, packet); + break; + case XFA_Element::LockDocument: + node = pdfium::MakeUnique<CXFA_LockDocument>(doc, packet); + break; + case XFA_Element::BreakAfter: + node = pdfium::MakeUnique<CXFA_BreakAfter>(doc, packet); + break; + case XFA_Element::Line: + node = pdfium::MakeUnique<CXFA_Line>(doc, packet); + break; + case XFA_Element::Source: + node = pdfium::MakeUnique<CXFA_Source>(doc, packet); + break; + case XFA_Element::Occur: + node = pdfium::MakeUnique<CXFA_Occur>(doc, packet); + break; + case XFA_Element::PickTrayByPDFSize: + node = pdfium::MakeUnique<CXFA_PickTrayByPDFSize>(doc, packet); + break; + case XFA_Element::MonthNames: + node = pdfium::MakeUnique<CXFA_MonthNames>(doc, packet); + break; + case XFA_Element::Severity: + node = pdfium::MakeUnique<CXFA_Severity>(doc, packet); + break; + case XFA_Element::GroupParent: + node = pdfium::MakeUnique<CXFA_GroupParent>(doc, packet); + break; + case XFA_Element::DocumentAssembly: + node = pdfium::MakeUnique<CXFA_DocumentAssembly>(doc, packet); + break; + case XFA_Element::NumberSymbol: + node = pdfium::MakeUnique<CXFA_NumberSymbol>(doc, packet); + break; + case XFA_Element::Tagged: + node = pdfium::MakeUnique<CXFA_Tagged>(doc, packet); + break; + case XFA_Element::Items: + node = pdfium::MakeUnique<CXFA_Items>(doc, packet); + break; + default: + NOTREACHED(); + return nullptr; + } + if (!node || !node->IsValidInPacket(packet)) + return nullptr; + return node; +} + +// static +WideString CXFA_Node::AttributeToName(XFA_Attribute attr) { + switch (attr) { + case XFA_Attribute::H: + return L"h"; + case XFA_Attribute::W: + return L"w"; + case XFA_Attribute::X: + return L"x"; + case XFA_Attribute::Y: + return L"y"; + case XFA_Attribute::Id: + return L"id"; + case XFA_Attribute::To: + return L"to"; + case XFA_Attribute::LineThrough: + return L"lineThrough"; + case XFA_Attribute::HAlign: + return L"hAlign"; + case XFA_Attribute::Typeface: + return L"typeface"; + case XFA_Attribute::BeforeTarget: + return L"beforeTarget"; + case XFA_Attribute::Name: + return L"name"; + case XFA_Attribute::Next: + return L"next"; + case XFA_Attribute::DataRowCount: + return L"dataRowCount"; + case XFA_Attribute::Break: + return L"break"; + case XFA_Attribute::VScrollPolicy: + return L"vScrollPolicy"; + case XFA_Attribute::FontHorizontalScale: + return L"fontHorizontalScale"; + case XFA_Attribute::TextIndent: + return L"textIndent"; + case XFA_Attribute::Context: + return L"context"; + case XFA_Attribute::TrayOut: + return L"trayOut"; + case XFA_Attribute::Cap: + return L"cap"; + case XFA_Attribute::Max: + return L"max"; + case XFA_Attribute::Min: + return L"min"; + case XFA_Attribute::Ref: + return L"ref"; + case XFA_Attribute::Rid: + return L"rid"; + case XFA_Attribute::Url: + return L"url"; + case XFA_Attribute::Use: + return L"use"; + case XFA_Attribute::LeftInset: + return L"leftInset"; + case XFA_Attribute::Widows: + return L"widows"; + case XFA_Attribute::Level: + return L"level"; + case XFA_Attribute::BottomInset: + return L"bottomInset"; + case XFA_Attribute::OverflowTarget: + return L"overflowTarget"; + case XFA_Attribute::AllowMacro: + return L"allowMacro"; + case XFA_Attribute::PagePosition: + return L"pagePosition"; + case XFA_Attribute::ColumnWidths: + return L"columnWidths"; + case XFA_Attribute::OverflowLeader: + return L"overflowLeader"; + case XFA_Attribute::Action: + return L"action"; + case XFA_Attribute::NonRepudiation: + return L"nonRepudiation"; + case XFA_Attribute::Rate: + return L"rate"; + case XFA_Attribute::AllowRichText: + return L"allowRichText"; + case XFA_Attribute::Role: + return L"role"; + case XFA_Attribute::OverflowTrailer: + return L"overflowTrailer"; + case XFA_Attribute::Operation: + return L"operation"; + case XFA_Attribute::Timeout: + return L"timeout"; + case XFA_Attribute::TopInset: + return L"topInset"; + case XFA_Attribute::Access: + return L"access"; + case XFA_Attribute::CommandType: + return L"commandType"; + case XFA_Attribute::Format: + return L"format"; + case XFA_Attribute::DataPrep: + return L"dataPrep"; + case XFA_Attribute::WidgetData: + return L"widgetData"; + case XFA_Attribute::Abbr: + return L"abbr"; + case XFA_Attribute::MarginRight: + return L"marginRight"; + case XFA_Attribute::DataDescription: + return L"dataDescription"; + case XFA_Attribute::EncipherOnly: + return L"encipherOnly"; + case XFA_Attribute::KerningMode: + return L"kerningMode"; + case XFA_Attribute::Rotate: + return L"rotate"; + case XFA_Attribute::WordCharacterCount: + return L"wordCharacterCount"; + case XFA_Attribute::Type: + return L"type"; + case XFA_Attribute::Reserve: + return L"reserve"; + case XFA_Attribute::TextLocation: + return L"textLocation"; + case XFA_Attribute::Priority: + return L"priority"; + case XFA_Attribute::Underline: + return L"underline"; + case XFA_Attribute::ModuleWidth: + return L"moduleWidth"; + case XFA_Attribute::Hyphenate: + return L"hyphenate"; + case XFA_Attribute::Listen: + return L"listen"; + case XFA_Attribute::Delimiter: + return L"delimiter"; + case XFA_Attribute::ContentType: + return L"contentType"; + case XFA_Attribute::StartNew: + return L"startNew"; + case XFA_Attribute::EofAction: + return L"eofAction"; + case XFA_Attribute::AllowNeutral: + return L"allowNeutral"; + case XFA_Attribute::Connection: + return L"connection"; + case XFA_Attribute::BaselineShift: + return L"baselineShift"; + case XFA_Attribute::OverlinePeriod: + return L"overlinePeriod"; + case XFA_Attribute::FracDigits: + return L"fracDigits"; + case XFA_Attribute::Orientation: + return L"orientation"; + case XFA_Attribute::TimeStamp: + return L"timeStamp"; + case XFA_Attribute::PrintCheckDigit: + return L"printCheckDigit"; + case XFA_Attribute::MarginLeft: + return L"marginLeft"; + case XFA_Attribute::Stroke: + return L"stroke"; + case XFA_Attribute::ModuleHeight: + return L"moduleHeight"; + case XFA_Attribute::TransferEncoding: + return L"transferEncoding"; + case XFA_Attribute::Usage: + return L"usage"; + case XFA_Attribute::Presence: + return L"presence"; + case XFA_Attribute::RadixOffset: + return L"radixOffset"; + case XFA_Attribute::Preserve: + return L"preserve"; + case XFA_Attribute::AliasNode: + return L"aliasNode"; + case XFA_Attribute::MultiLine: + return L"multiLine"; + case XFA_Attribute::Version: + return L"version"; + case XFA_Attribute::StartChar: + return L"startChar"; + case XFA_Attribute::ScriptTest: + return L"scriptTest"; + case XFA_Attribute::StartAngle: + return L"startAngle"; + case XFA_Attribute::CursorType: + return L"cursorType"; + case XFA_Attribute::DigitalSignature: + return L"digitalSignature"; + case XFA_Attribute::CodeType: + return L"codeType"; + case XFA_Attribute::Output: + return L"output"; + case XFA_Attribute::BookendTrailer: + return L"bookendTrailer"; + case XFA_Attribute::ImagingBBox: + return L"imagingBBox"; + case XFA_Attribute::ExcludeInitialCap: + return L"excludeInitialCap"; + case XFA_Attribute::Force: + return L"force"; + case XFA_Attribute::CrlSign: + return L"crlSign"; + case XFA_Attribute::Previous: + return L"previous"; + case XFA_Attribute::PushCharacterCount: + return L"pushCharacterCount"; + case XFA_Attribute::NullTest: + return L"nullTest"; + case XFA_Attribute::RunAt: + return L"runAt"; + case XFA_Attribute::SpaceBelow: + return L"spaceBelow"; + case XFA_Attribute::SweepAngle: + return L"sweepAngle"; + case XFA_Attribute::NumberOfCells: + return L"numberOfCells"; + case XFA_Attribute::LetterSpacing: + return L"letterSpacing"; + case XFA_Attribute::LockType: + return L"lockType"; + case XFA_Attribute::PasswordChar: + return L"passwordChar"; + case XFA_Attribute::VAlign: + return L"vAlign"; + case XFA_Attribute::SourceBelow: + return L"sourceBelow"; + case XFA_Attribute::Inverted: + return L"inverted"; + case XFA_Attribute::Mark: + return L"mark"; + case XFA_Attribute::MaxH: + return L"maxH"; + case XFA_Attribute::MaxW: + return L"maxW"; + case XFA_Attribute::Truncate: + return L"truncate"; + case XFA_Attribute::MinH: + return L"minH"; + case XFA_Attribute::MinW: + return L"minW"; + case XFA_Attribute::Initial: + return L"initial"; + case XFA_Attribute::Mode: + return L"mode"; + case XFA_Attribute::Layout: + return L"layout"; + case XFA_Attribute::Server: + return L"server"; + case XFA_Attribute::EmbedPDF: + return L"embedPDF"; + case XFA_Attribute::OddOrEven: + return L"oddOrEven"; + case XFA_Attribute::TabDefault: + return L"tabDefault"; + case XFA_Attribute::Contains: + return L"contains"; + case XFA_Attribute::RightInset: + return L"rightInset"; + case XFA_Attribute::MaxChars: + return L"maxChars"; + case XFA_Attribute::Open: + return L"open"; + case XFA_Attribute::Relation: + return L"relation"; + case XFA_Attribute::WideNarrowRatio: + return L"wideNarrowRatio"; + case XFA_Attribute::Relevant: + return L"relevant"; + case XFA_Attribute::SignatureType: + return L"signatureType"; + case XFA_Attribute::LineThroughPeriod: + return L"lineThroughPeriod"; + case XFA_Attribute::Shape: + return L"shape"; + case XFA_Attribute::TabStops: + return L"tabStops"; + case XFA_Attribute::OutputBelow: + return L"outputBelow"; + case XFA_Attribute::Short: + return L"short"; + case XFA_Attribute::FontVerticalScale: + return L"fontVerticalScale"; + case XFA_Attribute::Thickness: + return L"thickness"; + case XFA_Attribute::CommitOn: + return L"commitOn"; + case XFA_Attribute::RemainCharacterCount: + return L"remainCharacterCount"; + case XFA_Attribute::KeyAgreement: + return L"keyAgreement"; + case XFA_Attribute::ErrorCorrectionLevel: + return L"errorCorrectionLevel"; + case XFA_Attribute::UpsMode: + return L"upsMode"; + case XFA_Attribute::MergeMode: + return L"mergeMode"; + case XFA_Attribute::Circular: + return L"circular"; + case XFA_Attribute::PsName: + return L"psName"; + case XFA_Attribute::Trailer: + return L"trailer"; + case XFA_Attribute::UnicodeRange: + return L"unicodeRange"; + case XFA_Attribute::ExecuteType: + return L"executeType"; + case XFA_Attribute::DuplexImposition: + return L"duplexImposition"; + case XFA_Attribute::TrayIn: + return L"trayIn"; + case XFA_Attribute::BindingNode: + return L"bindingNode"; + case XFA_Attribute::BofAction: + return L"bofAction"; + case XFA_Attribute::Save: + return L"save"; + case XFA_Attribute::TargetType: + return L"targetType"; + case XFA_Attribute::KeyEncipherment: + return L"keyEncipherment"; + case XFA_Attribute::CredentialServerPolicy: + return L"credentialServerPolicy"; + case XFA_Attribute::Size: + return L"size"; + case XFA_Attribute::InitialNumber: + return L"initialNumber"; + case XFA_Attribute::Slope: + return L"slope"; + case XFA_Attribute::CSpace: + return L"cSpace"; + case XFA_Attribute::ColSpan: + return L"colSpan"; + case XFA_Attribute::Binding: + return L"binding"; + case XFA_Attribute::Checksum: + return L"checksum"; + case XFA_Attribute::CharEncoding: + return L"charEncoding"; + case XFA_Attribute::Bind: + return L"bind"; + case XFA_Attribute::TextEntry: + return L"textEntry"; + case XFA_Attribute::Archive: + return L"archive"; + case XFA_Attribute::Uuid: + return L"uuid"; + case XFA_Attribute::Posture: + return L"posture"; + case XFA_Attribute::After: + return L"after"; + case XFA_Attribute::Orphans: + return L"orphans"; + case XFA_Attribute::QualifiedName: + return L"qualifiedName"; + case XFA_Attribute::Usehref: + return L"usehref"; + case XFA_Attribute::Locale: + return L"locale"; + case XFA_Attribute::Weight: + return L"weight"; + case XFA_Attribute::UnderlinePeriod: + return L"underlinePeriod"; + case XFA_Attribute::Data: + return L"data"; + case XFA_Attribute::Desc: + return L"desc"; + case XFA_Attribute::Numbered: + return L"numbered"; + case XFA_Attribute::DataColumnCount: + return L"dataColumnCount"; + case XFA_Attribute::Overline: + return L"overline"; + case XFA_Attribute::UrlPolicy: + return L"urlPolicy"; + case XFA_Attribute::AnchorType: + return L"anchorType"; + case XFA_Attribute::LabelRef: + return L"labelRef"; + case XFA_Attribute::BookendLeader: + return L"bookendLeader"; + case XFA_Attribute::MaxLength: + return L"maxLength"; + case XFA_Attribute::AccessKey: + return L"accessKey"; + case XFA_Attribute::CursorLocation: + return L"cursorLocation"; + case XFA_Attribute::DelayedOpen: + return L"delayedOpen"; + case XFA_Attribute::Target: + return L"target"; + case XFA_Attribute::DataEncipherment: + return L"dataEncipherment"; + case XFA_Attribute::AfterTarget: + return L"afterTarget"; + case XFA_Attribute::Leader: + return L"leader"; + case XFA_Attribute::Picker: + return L"picker"; + case XFA_Attribute::From: + return L"from"; + case XFA_Attribute::BaseProfile: + return L"baseProfile"; + case XFA_Attribute::Aspect: + return L"aspect"; + case XFA_Attribute::RowColumnRatio: + return L"rowColumnRatio"; + case XFA_Attribute::LineHeight: + return L"lineHeight"; + case XFA_Attribute::Highlight: + return L"highlight"; + case XFA_Attribute::ValueRef: + return L"valueRef"; + case XFA_Attribute::MaxEntries: + return L"maxEntries"; + case XFA_Attribute::DataLength: + return L"dataLength"; + case XFA_Attribute::Activity: + return L"activity"; + case XFA_Attribute::Input: + return L"input"; + case XFA_Attribute::Value: + return L"value"; + case XFA_Attribute::BlankOrNotBlank: + return L"blankOrNotBlank"; + case XFA_Attribute::AddRevocationInfo: + return L"addRevocationInfo"; + case XFA_Attribute::GenericFamily: + return L"genericFamily"; + case XFA_Attribute::Hand: + return L"hand"; + case XFA_Attribute::Href: + return L"href"; + case XFA_Attribute::TextEncoding: + return L"textEncoding"; + case XFA_Attribute::LeadDigits: + return L"leadDigits"; + case XFA_Attribute::Permissions: + return L"permissions"; + case XFA_Attribute::SpaceAbove: + return L"spaceAbove"; + case XFA_Attribute::CodeBase: + return L"codeBase"; + case XFA_Attribute::Stock: + return L"stock"; + case XFA_Attribute::IsNull: + return L"isNull"; + case XFA_Attribute::RestoreState: + return L"restoreState"; + case XFA_Attribute::ExcludeAllCaps: + return L"excludeAllCaps"; + case XFA_Attribute::FormatTest: + return L"formatTest"; + case XFA_Attribute::HScrollPolicy: + return L"hScrollPolicy"; + case XFA_Attribute::Join: + return L"join"; + case XFA_Attribute::KeyCertSign: + return L"keyCertSign"; + case XFA_Attribute::Radius: + return L"radius"; + case XFA_Attribute::SourceAbove: + return L"sourceAbove"; + case XFA_Attribute::Override: + return L"override"; + case XFA_Attribute::ClassId: + return L"classId"; + case XFA_Attribute::Disable: + return L"disable"; + case XFA_Attribute::Scope: + return L"scope"; + case XFA_Attribute::Match: + return L"match"; + case XFA_Attribute::Placement: + return L"placement"; + case XFA_Attribute::Before: + return L"before"; + case XFA_Attribute::WritingScript: + return L"writingScript"; + case XFA_Attribute::EndChar: + return L"endChar"; + case XFA_Attribute::Lock: + return L"lock"; + case XFA_Attribute::Long: + return L"long"; + case XFA_Attribute::Intact: + return L"intact"; + case XFA_Attribute::XdpContent: + return L"xdpContent"; + case XFA_Attribute::DecipherOnly: + return L"decipherOnly"; + + default: + NOTREACHED(); + break; + } + return L""; +} + +#ifndef NDEBUG +// static +WideString CXFA_Node::ElementToName(XFA_Element attr) { + switch (attr) { + case XFA_Element::Ps: + return L"ps"; + case XFA_Element::To: + return L"to"; + case XFA_Element::Ui: + return L"ui"; + case XFA_Element::RecordSet: + return L"recordSet"; + case XFA_Element::SubsetBelow: + return L"subsetBelow"; + case XFA_Element::SubformSet: + return L"subformSet"; + case XFA_Element::AdobeExtensionLevel: + return L"adobeExtensionLevel"; + case XFA_Element::Typeface: + return L"typeface"; + case XFA_Element::Break: + return L"break"; + case XFA_Element::FontInfo: + return L"fontInfo"; + case XFA_Element::NumberPattern: + return L"numberPattern"; + case XFA_Element::DynamicRender: + return L"dynamicRender"; + case XFA_Element::PrintScaling: + return L"printScaling"; + case XFA_Element::CheckButton: + return L"checkButton"; + case XFA_Element::DatePatterns: + return L"datePatterns"; + case XFA_Element::SourceSet: + return L"sourceSet"; + case XFA_Element::Amd: + return L"amd"; + case XFA_Element::Arc: + return L"arc"; + case XFA_Element::Day: + return L"day"; + case XFA_Element::Era: + return L"era"; + case XFA_Element::Jog: + return L"jog"; + case XFA_Element::Log: + return L"log"; + case XFA_Element::Map: + return L"map"; + case XFA_Element::Mdp: + return L"mdp"; + case XFA_Element::BreakBefore: + return L"breakBefore"; + case XFA_Element::Oid: + return L"oid"; + case XFA_Element::Pcl: + return L"pcl"; + case XFA_Element::Pdf: + return L"pdf"; + case XFA_Element::Ref: + return L"ref"; + case XFA_Element::Uri: + return L"uri"; + case XFA_Element::Xdc: + return L"xdc"; + case XFA_Element::Xdp: + return L"xdp"; + case XFA_Element::Xfa: + return L"xfa"; + case XFA_Element::Xsl: + return L"xsl"; + case XFA_Element::Zpl: + return L"zpl"; + case XFA_Element::Cache: + return L"cache"; + case XFA_Element::Margin: + return L"margin"; + case XFA_Element::KeyUsage: + return L"keyUsage"; + case XFA_Element::Exclude: + return L"exclude"; + case XFA_Element::ChoiceList: + return L"choiceList"; + case XFA_Element::Level: + return L"level"; + case XFA_Element::LabelPrinter: + return L"labelPrinter"; + case XFA_Element::CalendarSymbols: + return L"calendarSymbols"; + case XFA_Element::Para: + return L"para"; + case XFA_Element::Part: + return L"part"; + case XFA_Element::Pdfa: + return L"pdfa"; + case XFA_Element::Filter: + return L"filter"; + case XFA_Element::Present: + return L"present"; + case XFA_Element::Pagination: + return L"pagination"; + case XFA_Element::Encoding: + return L"encoding"; + case XFA_Element::Event: + return L"event"; + case XFA_Element::Whitespace: + return L"whitespace"; + case XFA_Element::DefaultUi: + return L"defaultUi"; + case XFA_Element::DataModel: + return L"dataModel"; + case XFA_Element::Barcode: + return L"barcode"; + case XFA_Element::TimePattern: + return L"timePattern"; + case XFA_Element::BatchOutput: + return L"batchOutput"; + case XFA_Element::Enforce: + return L"enforce"; + case XFA_Element::CurrencySymbols: + return L"currencySymbols"; + case XFA_Element::AddSilentPrint: + return L"addSilentPrint"; + case XFA_Element::Rename: + return L"rename"; + case XFA_Element::Operation: + return L"operation"; + case XFA_Element::Typefaces: + return L"typefaces"; + case XFA_Element::SubjectDNs: + return L"subjectDNs"; + case XFA_Element::Issuers: + return L"issuers"; + case XFA_Element::WsdlConnection: + return L"wsdlConnection"; + case XFA_Element::Debug: + return L"debug"; + case XFA_Element::Delta: + return L"delta"; + case XFA_Element::EraNames: + return L"eraNames"; + case XFA_Element::ModifyAnnots: + return L"modifyAnnots"; + case XFA_Element::StartNode: + return L"startNode"; + case XFA_Element::Button: + return L"button"; + case XFA_Element::Format: + return L"format"; + case XFA_Element::Border: + return L"border"; + case XFA_Element::Area: + return L"area"; + case XFA_Element::Hyphenation: + return L"hyphenation"; + case XFA_Element::Text: + return L"text"; + case XFA_Element::Time: + return L"time"; + case XFA_Element::Type: + return L"type"; + case XFA_Element::Overprint: + return L"overprint"; + case XFA_Element::Certificates: + return L"certificates"; + case XFA_Element::EncryptionMethods: + return L"encryptionMethods"; + case XFA_Element::SetProperty: + return L"setProperty"; + case XFA_Element::PrinterName: + return L"printerName"; + case XFA_Element::StartPage: + return L"startPage"; + case XFA_Element::PageOffset: + return L"pageOffset"; + case XFA_Element::DateTime: + return L"dateTime"; + case XFA_Element::Comb: + return L"comb"; + case XFA_Element::Pattern: + return L"pattern"; + case XFA_Element::IfEmpty: + return L"ifEmpty"; + case XFA_Element::SuppressBanner: + return L"suppressBanner"; + case XFA_Element::OutputBin: + return L"outputBin"; + case XFA_Element::Field: + return L"field"; + case XFA_Element::Agent: + return L"agent"; + case XFA_Element::OutputXSL: + return L"outputXSL"; + case XFA_Element::AdjustData: + return L"adjustData"; + case XFA_Element::AutoSave: + return L"autoSave"; + case XFA_Element::ContentArea: + return L"contentArea"; + case XFA_Element::WsdlAddress: + return L"wsdlAddress"; + case XFA_Element::Solid: + return L"solid"; + case XFA_Element::DateTimeSymbols: + return L"dateTimeSymbols"; + case XFA_Element::EncryptionLevel: + return L"encryptionLevel"; + case XFA_Element::Edge: + return L"edge"; + case XFA_Element::Stipple: + return L"stipple"; + case XFA_Element::Attributes: + return L"attributes"; + case XFA_Element::VersionControl: + return L"versionControl"; + case XFA_Element::Meridiem: + return L"meridiem"; + case XFA_Element::ExclGroup: + return L"exclGroup"; + case XFA_Element::ToolTip: + return L"toolTip"; + case XFA_Element::Compress: + return L"compress"; + case XFA_Element::Reason: + return L"reason"; + case XFA_Element::Execute: + return L"execute"; + case XFA_Element::ContentCopy: + return L"contentCopy"; + case XFA_Element::DateTimeEdit: + return L"dateTimeEdit"; + case XFA_Element::Config: + return L"config"; + case XFA_Element::Image: + return L"image"; + case XFA_Element::SharpxHTML: + return L"#xHTML"; + case XFA_Element::NumberOfCopies: + return L"numberOfCopies"; + case XFA_Element::BehaviorOverride: + return L"behaviorOverride"; + case XFA_Element::TimeStamp: + return L"timeStamp"; + case XFA_Element::Month: + return L"month"; + case XFA_Element::ViewerPreferences: + return L"viewerPreferences"; + case XFA_Element::ScriptModel: + return L"scriptModel"; + case XFA_Element::Decimal: + return L"decimal"; + case XFA_Element::Subform: + return L"subform"; + case XFA_Element::Select: + return L"select"; + case XFA_Element::Window: + return L"window"; + case XFA_Element::LocaleSet: + return L"localeSet"; + case XFA_Element::Handler: + return L"handler"; + case XFA_Element::Presence: + return L"presence"; + case XFA_Element::Record: + return L"record"; + case XFA_Element::Embed: + return L"embed"; + case XFA_Element::Version: + return L"version"; + case XFA_Element::Command: + return L"command"; + case XFA_Element::Copies: + return L"copies"; + case XFA_Element::Staple: + return L"staple"; + case XFA_Element::SubmitFormat: + return L"submitFormat"; + case XFA_Element::Boolean: + return L"boolean"; + case XFA_Element::Message: + return L"message"; + case XFA_Element::Output: + return L"output"; + case XFA_Element::PsMap: + return L"psMap"; + case XFA_Element::ExcludeNS: + return L"excludeNS"; + case XFA_Element::Assist: + return L"assist"; + case XFA_Element::Picture: + return L"picture"; + case XFA_Element::Traversal: + return L"traversal"; + case XFA_Element::SilentPrint: + return L"silentPrint"; + case XFA_Element::WebClient: + return L"webClient"; + case XFA_Element::Producer: + return L"producer"; + case XFA_Element::Corner: + return L"corner"; + case XFA_Element::MsgId: + return L"msgId"; + case XFA_Element::Color: + return L"color"; + case XFA_Element::Keep: + return L"keep"; + case XFA_Element::Query: + return L"query"; + case XFA_Element::Insert: + return L"insert"; + case XFA_Element::ImageEdit: + return L"imageEdit"; + case XFA_Element::Validate: + return L"validate"; + case XFA_Element::DigestMethods: + return L"digestMethods"; + case XFA_Element::NumberPatterns: + return L"numberPatterns"; + case XFA_Element::PageSet: + return L"pageSet"; + case XFA_Element::Integer: + return L"integer"; + case XFA_Element::SoapAddress: + return L"soapAddress"; + case XFA_Element::Equate: + return L"equate"; + case XFA_Element::FormFieldFilling: + return L"formFieldFilling"; + case XFA_Element::PageRange: + return L"pageRange"; + case XFA_Element::Update: + return L"update"; + case XFA_Element::ConnectString: + return L"connectString"; + case XFA_Element::Mode: + return L"mode"; + case XFA_Element::Layout: + return L"layout"; + case XFA_Element::Sharpxml: + return L"#xml"; + case XFA_Element::XsdConnection: + return L"xsdConnection"; + case XFA_Element::Traverse: + return L"traverse"; + case XFA_Element::Encodings: + return L"encodings"; + case XFA_Element::Template: + return L"template"; + case XFA_Element::Acrobat: + return L"acrobat"; + case XFA_Element::ValidationMessaging: + return L"validationMessaging"; + case XFA_Element::Signing: + return L"signing"; + case XFA_Element::Script: + return L"script"; + case XFA_Element::AddViewerPreferences: + return L"addViewerPreferences"; + case XFA_Element::AlwaysEmbed: + return L"alwaysEmbed"; + case XFA_Element::PasswordEdit: + return L"passwordEdit"; + case XFA_Element::NumericEdit: + return L"numericEdit"; + case XFA_Element::EncryptionMethod: + return L"encryptionMethod"; + case XFA_Element::Change: + return L"change"; + case XFA_Element::PageArea: + return L"pageArea"; + case XFA_Element::SubmitUrl: + return L"submitUrl"; + case XFA_Element::Oids: + return L"oids"; + case XFA_Element::Signature: + return L"signature"; + case XFA_Element::ADBE_JSConsole: + return L"ADBE_JSConsole"; + case XFA_Element::Caption: + return L"caption"; + case XFA_Element::Relevant: + return L"relevant"; + case XFA_Element::FlipLabel: + return L"flipLabel"; + case XFA_Element::ExData: + return L"exData"; + case XFA_Element::DayNames: + return L"dayNames"; + case XFA_Element::SoapAction: + return L"soapAction"; + case XFA_Element::DefaultTypeface: + return L"defaultTypeface"; + case XFA_Element::Manifest: + return L"manifest"; + case XFA_Element::Overflow: + return L"overflow"; + case XFA_Element::Linear: + return L"linear"; + case XFA_Element::CurrencySymbol: + return L"currencySymbol"; + case XFA_Element::Delete: + return L"delete"; + case XFA_Element::Deltas: + return L"deltas"; + case XFA_Element::DigestMethod: + return L"digestMethod"; + case XFA_Element::InstanceManager: + return L"instanceManager"; + case XFA_Element::EquateRange: + return L"equateRange"; + case XFA_Element::Medium: + return L"medium"; + case XFA_Element::TextEdit: + return L"textEdit"; + case XFA_Element::TemplateCache: + return L"templateCache"; + case XFA_Element::CompressObjectStream: + return L"compressObjectStream"; + case XFA_Element::DataValue: + return L"dataValue"; + case XFA_Element::AccessibleContent: + return L"accessibleContent"; + case XFA_Element::IncludeXDPContent: + return L"includeXDPContent"; + case XFA_Element::XmlConnection: + return L"xmlConnection"; + case XFA_Element::ValidateApprovalSignatures: + return L"validateApprovalSignatures"; + case XFA_Element::SignData: + return L"signData"; + case XFA_Element::Packets: + return L"packets"; + case XFA_Element::DatePattern: + return L"datePattern"; + case XFA_Element::DuplexOption: + return L"duplexOption"; + case XFA_Element::Base: + return L"base"; + case XFA_Element::Bind: + return L"bind"; + case XFA_Element::Compression: + return L"compression"; + case XFA_Element::User: + return L"user"; + case XFA_Element::Rectangle: + return L"rectangle"; + case XFA_Element::EffectiveOutputPolicy: + return L"effectiveOutputPolicy"; + case XFA_Element::ADBE_JSDebugger: + return L"ADBE_JSDebugger"; + case XFA_Element::Acrobat7: + return L"acrobat7"; + case XFA_Element::Interactive: + return L"interactive"; + case XFA_Element::Locale: + return L"locale"; + case XFA_Element::CurrentPage: + return L"currentPage"; + case XFA_Element::Data: + return L"data"; + case XFA_Element::Date: + return L"date"; + case XFA_Element::Desc: + return L"desc"; + case XFA_Element::Encrypt: + return L"encrypt"; + case XFA_Element::Draw: + return L"draw"; + case XFA_Element::Encryption: + return L"encryption"; + case XFA_Element::MeridiemNames: + return L"meridiemNames"; + case XFA_Element::Messaging: + return L"messaging"; + case XFA_Element::Speak: + return L"speak"; + case XFA_Element::DataGroup: + return L"dataGroup"; + case XFA_Element::Common: + return L"common"; + case XFA_Element::Sharptext: + return L"#text"; + case XFA_Element::PaginationOverride: + return L"paginationOverride"; + case XFA_Element::Reasons: + return L"reasons"; + case XFA_Element::SignatureProperties: + return L"signatureProperties"; + case XFA_Element::Threshold: + return L"threshold"; + case XFA_Element::AppearanceFilter: + return L"appearanceFilter"; + case XFA_Element::Fill: + return L"fill"; + case XFA_Element::Font: + return L"font"; + case XFA_Element::Form: + return L"form"; + case XFA_Element::MediumInfo: + return L"mediumInfo"; + case XFA_Element::Certificate: + return L"certificate"; + case XFA_Element::Password: + return L"password"; + case XFA_Element::RunScripts: + return L"runScripts"; + case XFA_Element::Trace: + return L"trace"; + case XFA_Element::Float: + return L"float"; + case XFA_Element::RenderPolicy: + return L"renderPolicy"; + case XFA_Element::Destination: + return L"destination"; + case XFA_Element::Value: + return L"value"; + case XFA_Element::Bookend: + return L"bookend"; + case XFA_Element::ExObject: + return L"exObject"; + case XFA_Element::OpenAction: + return L"openAction"; + case XFA_Element::NeverEmbed: + return L"neverEmbed"; + case XFA_Element::BindItems: + return L"bindItems"; + case XFA_Element::Calculate: + return L"calculate"; + case XFA_Element::Print: + return L"print"; + case XFA_Element::Extras: + return L"extras"; + case XFA_Element::Proto: + return L"proto"; + case XFA_Element::DSigData: + return L"dSigData"; + case XFA_Element::Creator: + return L"creator"; + case XFA_Element::Connect: + return L"connect"; + case XFA_Element::Permissions: + return L"permissions"; + case XFA_Element::ConnectionSet: + return L"connectionSet"; + case XFA_Element::Submit: + return L"submit"; + case XFA_Element::Range: + return L"range"; + case XFA_Element::Linearized: + return L"linearized"; + case XFA_Element::Packet: + return L"packet"; + case XFA_Element::RootElement: + return L"rootElement"; + case XFA_Element::PlaintextMetadata: + return L"plaintextMetadata"; + case XFA_Element::NumberSymbols: + return L"numberSymbols"; + case XFA_Element::PrintHighQuality: + return L"printHighQuality"; + case XFA_Element::Driver: + return L"driver"; + case XFA_Element::IncrementalLoad: + return L"incrementalLoad"; + case XFA_Element::SubjectDN: + return L"subjectDN"; + case XFA_Element::CompressLogicalStructure: + return L"compressLogicalStructure"; + case XFA_Element::IncrementalMerge: + return L"incrementalMerge"; + case XFA_Element::Radial: + return L"radial"; + case XFA_Element::Variables: + return L"variables"; + case XFA_Element::TimePatterns: + return L"timePatterns"; + case XFA_Element::EffectiveInputPolicy: + return L"effectiveInputPolicy"; + case XFA_Element::NameAttr: + return L"nameAttr"; + case XFA_Element::Conformance: + return L"conformance"; + case XFA_Element::Transform: + return L"transform"; + case XFA_Element::LockDocument: + return L"lockDocument"; + case XFA_Element::BreakAfter: + return L"breakAfter"; + case XFA_Element::Line: + return L"line"; + case XFA_Element::Source: + return L"source"; + case XFA_Element::Occur: + return L"occur"; + case XFA_Element::PickTrayByPDFSize: + return L"pickTrayByPDFSize"; + case XFA_Element::MonthNames: + return L"monthNames"; + case XFA_Element::Severity: + return L"severity"; + case XFA_Element::GroupParent: + return L"groupParent"; + case XFA_Element::DocumentAssembly: + return L"documentAssembly"; + case XFA_Element::NumberSymbol: + return L"numberSymbol"; + case XFA_Element::Tagged: + return L"tagged"; + case XFA_Element::Items: + return L"items"; + + default: + NOTREACHED(); + break; + } + return L""; +} +#endif // NDEBUG diff --git a/xfa/fxfa/parser/cxfa_node_unittest.cpp b/xfa/fxfa/parser/cxfa_node_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dedef5df3a70e42d31489bed1afc0d82b9ab8aa8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_node_unittest.cpp @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fxfa/parser/cxfa_node.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CXFA_NodeTest, NameToAttribute) { + EXPECT_EQ(XFA_Attribute::Unknown, CXFA_Node::NameToAttribute(L"")); + EXPECT_EQ(XFA_Attribute::Unknown, CXFA_Node::NameToAttribute(L"nonesuch")); + EXPECT_EQ(XFA_Attribute::H, CXFA_Node::NameToAttribute(L"h")); + EXPECT_EQ(XFA_Attribute::Short, CXFA_Node::NameToAttribute(L"short")); + EXPECT_EQ(XFA_Attribute::DecipherOnly, + CXFA_Node::NameToAttribute(L"decipherOnly")); +} + +TEST(CXFA_NodeTest, GetAttributeEnumByName) { + EXPECT_FALSE(!!CXFA_Node::NameToAttributeEnum(L"")); + EXPECT_FALSE(!!CXFA_Node::NameToAttributeEnum(L"nonesuch")); + EXPECT_EQ(XFA_AttributeEnum::Asterisk, *CXFA_Node::NameToAttributeEnum(L"*")); + EXPECT_EQ(XFA_AttributeEnum::Visible, + *CXFA_Node::NameToAttributeEnum(L"visible")); + EXPECT_EQ(XFA_AttributeEnum::Lowered, + *CXFA_Node::NameToAttributeEnum(L"lowered")); +} diff --git a/xfa/fxfa/parser/cxfa_nodehelper.cpp b/xfa/fxfa/parser/cxfa_nodehelper.cpp index 2290892318b8a3eea416d352702ac9c5a2361907..eea054a1699c0b94234637201da0fc660dd9cf30 100644 --- a/xfa/fxfa/parser/cxfa_nodehelper.cpp +++ b/xfa/fxfa/parser/cxfa_nodehelper.cpp @@ -6,11 +6,12 @@ #include "xfa/fxfa/parser/cxfa_nodehelper.h" -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_object.h" #include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" #include "xfa/fxfa/parser/xfa_utils.h" @@ -18,133 +19,114 @@ CXFA_NodeHelper::CXFA_NodeHelper() : m_eLastCreateType(XFA_Element::DataValue), m_pCreateParent(nullptr), m_iCreateCount(0), - m_iCreateFlag(XFA_RESOLVENODE_RSTYPE_CreateNodeOne), + m_iCreateFlag(XFA_ResolveNode_RSType_CreateNodeOne), m_iCurAllStart(-1), m_pAllStartParent(nullptr) {} CXFA_NodeHelper::~CXFA_NodeHelper() {} CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetOneChild(CXFA_Node* parent, - const FX_WCHAR* pwsName, + const wchar_t* pwsName, bool bIsClassName) { - if (!parent) { + if (!parent) return nullptr; - } - CXFA_NodeArray siblings; - uint32_t uNameHash = FX_HashCode_GetW(CFX_WideStringC(pwsName), false); + + std::vector<CXFA_Node*> siblings; + uint32_t uNameHash = FX_HashCode_GetW(WideStringView(pwsName), false); NodeAcc_TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName); - if (siblings.GetSize() == 0) { - return nullptr; - } - return siblings[0]; + return !siblings.empty() ? siblings[0] : nullptr; } int32_t CXFA_NodeHelper::CountSiblings(CXFA_Node* pNode, XFA_LOGIC_TYPE eLogicType, - CXFA_NodeArray* pSiblings, + std::vector<CXFA_Node*>* pSiblings, bool bIsClassName) { if (!pNode) return 0; CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); if (!parent) return 0; - const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( - parent->GetElementType(), pNode->GetElementType(), XFA_XDPPACKET_UNKNOWN); - if (!pProperty && eLogicType == XFA_LOGIC_Transparent) { + if (!parent->HasProperty(pNode->GetElementType()) && + eLogicType == XFA_LOGIC_Transparent) { parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); - if (!parent) { + if (!parent) return 0; - } } if (bIsClassName) { return NodeAcc_TraverseSiblings(parent, pNode->GetClassHashCode(), pSiblings, eLogicType, bIsClassName); - } else { - return NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings, - eLogicType, bIsClassName); } + return NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings, + eLogicType, bIsClassName); } -int32_t CXFA_NodeHelper::NodeAcc_TraverseAnySiblings(CXFA_Node* parent, - uint32_t dNameHash, - CXFA_NodeArray* pSiblings, - bool bIsClassName) { - if (!parent || !pSiblings) { +int32_t CXFA_NodeHelper::NodeAcc_TraverseAnySiblings( + CXFA_Node* parent, + uint32_t dNameHash, + std::vector<CXFA_Node*>* pSiblings, + bool bIsClassName) { + if (!parent || !pSiblings) return 0; - } + int32_t nCount = 0; - int32_t i = 0; - CXFA_NodeArray properties; - parent->GetNodeList(properties, XFA_NODEFILTER_Properties); - int32_t nProperties = properties.GetSize(); - for (i = 0; i < nProperties; ++i) { - CXFA_Node* child = properties[i]; + for (CXFA_Node* child : + parent->GetNodeList(XFA_NODEFILTER_Properties, XFA_Element::Unknown)) { if (bIsClassName) { if (child->GetClassHashCode() == dNameHash) { - pSiblings->Add(child); + pSiblings->push_back(child); nCount++; } } else { if (child->GetNameHash() == dNameHash) { - pSiblings->Add(child); + pSiblings->push_back(child); nCount++; } } - if (nCount > 0) { + if (nCount > 0) return nCount; - } + nCount += NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName); } - CXFA_NodeArray children; - parent->GetNodeList(children, XFA_NODEFILTER_Children); - int32_t nChildren = children.GetSize(); - for (i = 0; i < nChildren; i++) { - CXFA_Node* child = children[i]; + for (CXFA_Node* child : + parent->GetNodeList(XFA_NODEFILTER_Children, XFA_Element::Unknown)) { if (bIsClassName) { if (child->GetClassHashCode() == dNameHash) { - if (pSiblings) { - pSiblings->Add(child); - } + pSiblings->push_back(child); nCount++; } } else { if (child->GetNameHash() == dNameHash) { - if (pSiblings) { - pSiblings->Add(child); - } + pSiblings->push_back(child); nCount++; } } - if (nCount > 0) { + if (nCount > 0) return nCount; - } + nCount += NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName); } return nCount; } -int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings(CXFA_Node* parent, - uint32_t dNameHash, - CXFA_NodeArray* pSiblings, - XFA_LOGIC_TYPE eLogicType, - bool bIsClassName, - bool bIsFindProperty) { - if (!parent || !pSiblings) { +int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings( + CXFA_Node* parent, + uint32_t dNameHash, + std::vector<CXFA_Node*>* pSiblings, + XFA_LOGIC_TYPE eLogicType, + bool bIsClassName, + bool bIsFindProperty) { + if (!parent || !pSiblings) return 0; - } + int32_t nCount = 0; - int32_t i = 0; if (bIsFindProperty) { - CXFA_NodeArray properties; - parent->GetNodeList(properties, XFA_NODEFILTER_Properties); - int32_t nProperties = properties.GetSize(); - for (i = 0; i < nProperties; ++i) { - CXFA_Node* child = properties[i]; + for (CXFA_Node* child : + parent->GetNodeList(XFA_NODEFILTER_Properties, XFA_Element::Unknown)) { if (bIsClassName) { if (child->GetClassHashCode() == dNameHash) { - pSiblings->Add(child); + pSiblings->push_back(child); nCount++; } } else { @@ -152,7 +134,7 @@ int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings(CXFA_Node* parent, if (child->GetElementType() != XFA_Element::PageSet && child->GetElementType() != XFA_Element::Extras && child->GetElementType() != XFA_Element::Items) { - pSiblings->Add(child); + pSiblings->push_back(child); nCount++; } } @@ -163,36 +145,28 @@ int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings(CXFA_Node* parent, eLogicType, bIsClassName, false); } } - if (nCount > 0) { + if (nCount > 0) return nCount; - } } - CXFA_NodeArray children; - parent->GetNodeList(children, XFA_NODEFILTER_Children); - int32_t nChildren = children.GetSize(); - for (i = 0; i < nChildren; i++) { - CXFA_Node* child = children[i]; - if (child->GetElementType() == XFA_Element::Variables) { + for (CXFA_Node* child : + parent->GetNodeList(XFA_NODEFILTER_Children, XFA_Element::Unknown)) { + if (child->GetElementType() == XFA_Element::Variables) continue; - } + if (bIsClassName) { if (child->GetClassHashCode() == dNameHash) { - if (pSiblings) { - pSiblings->Add(child); - } + pSiblings->push_back(child); nCount++; } } else { if (child->GetNameHash() == dNameHash) { - if (pSiblings) { - pSiblings->Add(child); - } + pSiblings->push_back(child); nCount++; } } - if (eLogicType == XFA_LOGIC_NoTransparent) { + if (eLogicType == XFA_LOGIC_NoTransparent) continue; - } + if (NodeIsTransparent(child) && child->GetElementType() != XFA_Element::PageSet) { nCount += NodeAcc_TraverseSiblings(child, dNameHash, pSiblings, @@ -208,7 +182,7 @@ CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetParent(CXFA_Node* pNode, return nullptr; } if (eLogicType == XFA_LOGIC_NoTransparent) { - return pNode->GetNodeItem(XFA_NODEITEM_Parent); + return pNode->GetParent(); } CXFA_Node* parent; CXFA_Node* node = pNode; @@ -245,7 +219,7 @@ int32_t CXFA_NodeHelper::GetIndex(CXFA_Node* pNode, if (bIsClassIndex) { dwHashName = pNode->GetClassHashCode(); } - CXFA_NodeArray siblings; + std::vector<CXFA_Node*> siblings; int32_t iSize = NodeAcc_TraverseSiblings(parent, dwHashName, &siblings, eLogicType, bIsClassIndex); for (int32_t i = 0; i < iSize; ++i) { @@ -257,108 +231,97 @@ int32_t CXFA_NodeHelper::GetIndex(CXFA_Node* pNode, return 0; } -void CXFA_NodeHelper::GetNameExpression(CXFA_Node* refNode, - CFX_WideString& wsName, - bool bIsAllPath, - XFA_LOGIC_TYPE eLogicType) { - wsName.clear(); +WideString CXFA_NodeHelper::GetNameExpression(CXFA_Node* refNode, + bool bIsAllPath, + XFA_LOGIC_TYPE eLogicType) { + WideString wsName; if (bIsAllPath) { - GetNameExpression(refNode, wsName, false, eLogicType); - CFX_WideString wsParent; + wsName = GetNameExpression(refNode, false, eLogicType); + WideString wsParent; CXFA_Node* parent = ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); while (parent) { - GetNameExpression(parent, wsParent, false, eLogicType); + wsParent = GetNameExpression(parent, false, eLogicType); wsParent += L"."; wsParent += wsName; wsName = wsParent; parent = ResolveNodes_GetParent(parent, XFA_LOGIC_NoTransparent); } - return; + return wsName; } - CFX_WideString ws; + WideString ws; bool bIsProperty = NodeIsProperty(refNode); if (refNode->IsUnnamed() || (bIsProperty && refNode->GetElementType() != XFA_Element::PageSet)) { ws = refNode->GetClassName(); - wsName.Format(L"#%s[%d]", ws.c_str(), - GetIndex(refNode, eLogicType, bIsProperty, true)); - return; + return WideString::Format(L"#%ls[%d]", ws.c_str(), + GetIndex(refNode, eLogicType, bIsProperty, true)); } - ws = refNode->GetCData(XFA_ATTRIBUTE_Name); + ws = refNode->JSObject()->GetCData(XFA_Attribute::Name); ws.Replace(L".", L"\\."); - wsName.Format(L"%s[%d]", ws.c_str(), - GetIndex(refNode, eLogicType, bIsProperty, false)); + return WideString::Format(L"%ls[%d]", ws.c_str(), + GetIndex(refNode, eLogicType, bIsProperty, false)); } bool CXFA_NodeHelper::NodeIsTransparent(CXFA_Node* refNode) { - if (!refNode) { + if (!refNode) return false; - } + XFA_Element refNodeType = refNode->GetElementType(); - if ((refNode->IsUnnamed() && refNode->IsContainerNode()) || - refNodeType == XFA_Element::SubformSet || - refNodeType == XFA_Element::Area || refNodeType == XFA_Element::Proto) { - return true; - } - return false; + return (refNode->IsUnnamed() && refNode->IsContainerNode()) || + refNodeType == XFA_Element::SubformSet || + refNodeType == XFA_Element::Area || refNodeType == XFA_Element::Proto; } -bool CXFA_NodeHelper::CreateNode_ForCondition(CFX_WideString& wsCondition) { +bool CXFA_NodeHelper::CreateNode_ForCondition(WideString& wsCondition) { int32_t iLen = wsCondition.GetLength(); - CFX_WideString wsIndex(L"0"); + WideString wsIndex(L"0"); bool bAll = false; if (iLen == 0) { - m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; + m_iCreateFlag = XFA_ResolveNode_RSType_CreateNodeOne; return false; } - if (wsCondition.GetAt(0) == '[') { - int32_t i = 1; - for (; i < iLen; ++i) { - FX_WCHAR ch = wsCondition[i]; - if (ch == ' ') { - continue; - } - if (ch == '+' || ch == '-') { - break; - } else if (ch == '*') { - bAll = true; - break; - } else { - break; - } - } - if (bAll) { - wsIndex = L"1"; - m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeAll; - } else { - m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; - wsIndex = wsCondition.Mid(i, iLen - 1 - i); - } - int32_t iIndex = wsIndex.GetInteger(); - m_iCreateCount = iIndex; - return true; + if (wsCondition[0] != '[') + return false; + + int32_t i = 1; + for (; i < iLen; ++i) { + wchar_t ch = wsCondition[i]; + if (ch == ' ') + continue; + + if (ch == '*') + bAll = true; + break; + } + if (bAll) { + wsIndex = L"1"; + m_iCreateFlag = XFA_ResolveNode_RSType_CreateNodeAll; + } else { + m_iCreateFlag = XFA_ResolveNode_RSType_CreateNodeOne; + wsIndex = wsCondition.Mid(i, iLen - 1 - i); } - return false; + int32_t iIndex = wsIndex.GetInteger(); + m_iCreateCount = iIndex; + return true; } -bool CXFA_NodeHelper::ResolveNodes_CreateNode( - CFX_WideString wsName, - CFX_WideString wsCondition, - bool bLastNode, - CXFA_ScriptContext* pScriptContext) { +bool CXFA_NodeHelper::ResolveNodes_CreateNode(WideString wsName, + WideString wsCondition, + bool bLastNode, + CFXJSE_Engine* pScriptContext) { if (!m_pCreateParent) { return false; } bool bIsClassName = false; bool bResult = false; - if (wsName.GetAt(0) == '!') { + if (wsName[0] == '!') { wsName = wsName.Right(wsName.GetLength() - 1); m_pCreateParent = ToNode( pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); } - if (wsName.GetAt(0) == '#') { + if (wsName[0] == '#') { bIsClassName = true; wsName = wsName.Right(wsName.GetLength() - 1); } @@ -366,14 +329,14 @@ bool CXFA_NodeHelper::ResolveNodes_CreateNode( CreateNode_ForCondition(wsCondition); } if (bIsClassName) { - XFA_Element eType = XFA_GetElementTypeForName(wsName.AsStringC()); + XFA_Element eType = CXFA_Node::NameToElement(wsName); if (eType == XFA_Element::Unknown) return false; for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eType); if (pNewNode) { - m_pCreateParent->InsertChild(pNewNode); + m_pCreateParent->InsertChild(pNewNode, nullptr); if (iIndex == m_iCreateCount - 1) { m_pCreateParent = pNewNode; } @@ -388,9 +351,10 @@ bool CXFA_NodeHelper::ResolveNodes_CreateNode( for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType); if (pNewNode) { - pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, wsName.AsStringC()); + pNewNode->JSObject()->SetAttribute(XFA_Attribute::Name, + wsName.AsStringView(), false); pNewNode->CreateXMLMappingNode(); - m_pCreateParent->InsertChild(pNewNode); + m_pCreateParent->InsertChild(pNewNode, nullptr); if (iIndex == m_iCreateCount - 1) { m_pCreateParent = pNewNode; } @@ -405,9 +369,9 @@ bool CXFA_NodeHelper::ResolveNodes_CreateNode( } void CXFA_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) { - if (!refNode) { + if (!refNode) return; - } + if (refNode->GetElementType() == XFA_Element::Subform) { m_eLastCreateType = XFA_Element::DataGroup; } else if (refNode->GetElementType() == XFA_Element::Field) { @@ -421,8 +385,5 @@ void CXFA_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) { bool CXFA_NodeHelper::NodeIsProperty(CXFA_Node* refNode) { CXFA_Node* parent = ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); - return parent && refNode && - XFA_GetPropertyOfElement(parent->GetElementType(), - refNode->GetElementType(), - XFA_XDPPACKET_UNKNOWN); + return parent && refNode && parent->HasProperty(refNode->GetElementType()); } diff --git a/xfa/fxfa/parser/cxfa_nodehelper.h b/xfa/fxfa/parser/cxfa_nodehelper.h index 5097feabacd45e8cec6585edc36191df8ebfa7aa..e13387ec9e7c05d33a2c9165534563bf36437ec6 100644 --- a/xfa/fxfa/parser/cxfa_nodehelper.h +++ b/xfa/fxfa/parser/cxfa_nodehelper.h @@ -7,10 +7,11 @@ #ifndef XFA_FXFA_PARSER_CXFA_NODEHELPER_H_ #define XFA_FXFA_PARSER_CXFA_NODEHELPER_H_ -#include "xfa/fxfa/parser/xfa_object.h" +#include <vector> + #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -class CXFA_ScriptContext; +class CFXJSE_Engine; enum XFA_LOGIC_TYPE { XFA_LOGIC_NoTransparent, @@ -23,7 +24,7 @@ class CXFA_NodeHelper { ~CXFA_NodeHelper(); CXFA_Node* ResolveNodes_GetOneChild(CXFA_Node* parent, - const FX_WCHAR* pwsName, + const wchar_t* pwsName, bool bIsClassName = false); CXFA_Node* ResolveNodes_GetParent( CXFA_Node* pNode, @@ -31,40 +32,39 @@ class CXFA_NodeHelper { int32_t NodeAcc_TraverseSiblings(CXFA_Node* parent, uint32_t dNameHash, - CXFA_NodeArray* pSiblings, + std::vector<CXFA_Node*>* pSiblings, XFA_LOGIC_TYPE eLogicType, bool bIsClassName = false, bool bIsFindProperty = true); int32_t NodeAcc_TraverseAnySiblings(CXFA_Node* parent, uint32_t dNameHash, - CXFA_NodeArray* pSiblings, + std::vector<CXFA_Node*>* pSiblings, bool bIsClassName = false); int32_t CountSiblings(CXFA_Node* pNode, XFA_LOGIC_TYPE eLogicType, - CXFA_NodeArray* pSiblings, + std::vector<CXFA_Node*>* pSiblings, bool bIsClassName = false); int32_t GetIndex(CXFA_Node* pNode, XFA_LOGIC_TYPE eLogicType = XFA_LOGIC_NoTransparent, bool bIsProperty = false, bool bIsClassIndex = false); - void GetNameExpression(CXFA_Node* refNode, - CFX_WideString& wsName, - bool bIsAllPath, - XFA_LOGIC_TYPE eLogicType = XFA_LOGIC_NoTransparent); + WideString GetNameExpression( + CXFA_Node* refNode, + bool bIsAllPath, + XFA_LOGIC_TYPE eLogicType = XFA_LOGIC_NoTransparent); bool NodeIsTransparent(CXFA_Node* refNode); - bool ResolveNodes_CreateNode(CFX_WideString wsName, - CFX_WideString wsCondition, + bool ResolveNodes_CreateNode(WideString wsName, + WideString wsCondition, bool bLastNode, - CXFA_ScriptContext* pScriptContext); - bool CreateNode_ForCondition(CFX_WideString& wsCondition); + CFXJSE_Engine* pScriptContext); + bool CreateNode_ForCondition(WideString& wsCondition); void SetCreateNodeType(CXFA_Node* refNode); bool NodeIsProperty(CXFA_Node* refNode); - public: XFA_Element m_eLastCreateType; CXFA_Node* m_pCreateParent; int32_t m_iCreateCount; - XFA_RESOVENODE_RSTYPE m_iCreateFlag; + XFA_ResolveNode_RSType m_iCreateFlag; int32_t m_iCurAllStart; CXFA_Node* m_pAllStartParent; }; diff --git a/xfa/fxfa/parser/cxfa_nodeiteratortemplate.h b/xfa/fxfa/parser/cxfa_nodeiteratortemplate.h new file mode 100644 index 0000000000000000000000000000000000000000..214f38e50129067f294087f1f5935b313dd7e045 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_nodeiteratortemplate.h @@ -0,0 +1,129 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_ +#define XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_ + +template <class NodeType, class TraverseStrategy> +class CXFA_NodeIteratorTemplate { + public: + explicit CXFA_NodeIteratorTemplate(NodeType* pRoot) + : m_pRoot(pRoot), m_pCurrent(pRoot) {} + + NodeType* GetRoot() const { return m_pRoot; } + NodeType* GetCurrent() const { return m_pCurrent; } + + void Reset() { m_pCurrent = m_pRoot; } + bool SetCurrent(NodeType* pNode) { + if (!RootReachableFromNode(pNode)) { + m_pCurrent = nullptr; + return false; + } + m_pCurrent = pNode; + return true; + } + + NodeType* MoveToPrev() { + if (!m_pRoot) + return nullptr; + if (!m_pCurrent) { + m_pCurrent = LastDescendant(m_pRoot); + return m_pCurrent; + } + NodeType* pSibling = PreviousSiblingWithinSubtree(m_pCurrent); + if (pSibling) { + m_pCurrent = LastDescendant(pSibling); + return m_pCurrent; + } + NodeType* pParent = ParentWithinSubtree(m_pCurrent); + if (pParent) { + m_pCurrent = pParent; + return m_pCurrent; + } + return nullptr; + } + + NodeType* MoveToNext() { + if (!m_pRoot || !m_pCurrent) + return nullptr; + NodeType* pChild = TraverseStrategy::GetFirstChild(m_pCurrent); + if (pChild) { + m_pCurrent = pChild; + return m_pCurrent; + } + return SkipChildrenAndMoveToNext(); + } + + NodeType* SkipChildrenAndMoveToNext() { + if (!m_pRoot) + return nullptr; + NodeType* pNode = m_pCurrent; + while (pNode) { + NodeType* pSibling = NextSiblingWithinSubtree(pNode); + if (pSibling) { + m_pCurrent = pSibling; + return m_pCurrent; + } + pNode = ParentWithinSubtree(pNode); + } + m_pCurrent = nullptr; + return m_pCurrent; + } + + private: + bool RootReachableFromNode(NodeType* pNode) { + if (!pNode) + return false; + if (pNode == m_pRoot) + return true; + return RootReachableFromNode(TraverseStrategy::GetParent(pNode)); + } + + NodeType* ParentWithinSubtree(NodeType* pNode) { + if (!pNode || pNode == m_pRoot) + return nullptr; + return TraverseStrategy::GetParent(pNode); + } + + NodeType* NextSiblingWithinSubtree(NodeType* pNode) { + if (pNode == m_pRoot) + return nullptr; + return TraverseStrategy::GetNextSibling(pNode); + } + + NodeType* PreviousSiblingWithinSubtree(NodeType* pNode) { + NodeType* pParent = ParentWithinSubtree(pNode); + if (!pParent) + return nullptr; + NodeType* pCurrent = TraverseStrategy::GetFirstChild(pParent); + NodeType* pPrevious = nullptr; + while (pCurrent != pNode) { + pPrevious = pCurrent; + pCurrent = TraverseStrategy::GetNextSibling(pCurrent); + } + return pPrevious; + } + + NodeType* LastChild(NodeType* pNode) { + NodeType* pPrevious = nullptr; + NodeType* pChild = TraverseStrategy::GetFirstChild(pNode); + while (pChild) { + pPrevious = pChild; + pChild = NextSiblingWithinSubtree(pChild); + } + return pPrevious; + } + + NodeType* LastDescendant(NodeType* pNode) { + NodeType* pChild = LastChild(pNode); + return pChild ? LastDescendant(pChild) : pNode; + } + + NodeType* m_pRoot; + NodeType* m_pCurrent; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_ diff --git a/xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp b/xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..114bed0f78d6804c46bd823117ddec4a27c608f2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp @@ -0,0 +1,257 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" + +#include <memory> +#include <vector> + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" + +class CXFA_NodeIteratorTemplateTest : public testing::Test { + public: + class Node { + public: + class Strategy { + public: + static Node* GetFirstChild(Node* pNode) { + return pNode && !pNode->children_.empty() ? pNode->children_.front() + : nullptr; + } + static Node* GetNextSibling(Node* pNode) { + return pNode ? pNode->next_sibling_ : nullptr; + } + static Node* GetParent(Node* pNode) { + return pNode ? pNode->parent_ : nullptr; + } + }; + + explicit Node(Node* parent) : parent_(parent), next_sibling_(nullptr) { + if (parent) { + if (!parent->children_.empty()) + parent->children_.back()->next_sibling_ = this; + parent->children_.push_back(this); + } + } + + private: + Node* parent_; + Node* next_sibling_; + std::vector<Node*> children_; + }; + + using Iterator = CXFA_NodeIteratorTemplate<Node, Node::Strategy>; + + // Builds a tree along the lines of: + // + // root + // | + // child1--child2 + // | + // child3------------child7--child9 + // | | + // child4--child6 child8 + // | + // child5 + // + void SetUp() override { + root_ = pdfium::MakeUnique<Node>(nullptr); + child1_ = pdfium::MakeUnique<Node>(root_.get()); + child2_ = pdfium::MakeUnique<Node>(root_.get()); + child3_ = pdfium::MakeUnique<Node>(child2_.get()); + child4_ = pdfium::MakeUnique<Node>(child3_.get()); + child5_ = pdfium::MakeUnique<Node>(child4_.get()); + child6_ = pdfium::MakeUnique<Node>(child3_.get()); + child7_ = pdfium::MakeUnique<Node>(child2_.get()); + child8_ = pdfium::MakeUnique<Node>(child7_.get()); + child9_ = pdfium::MakeUnique<Node>(child2_.get()); + } + + Node* root() const { return root_.get(); } + Node* child1() const { return child1_.get(); } + Node* child2() const { return child2_.get(); } + Node* child3() const { return child3_.get(); } + Node* child4() const { return child4_.get(); } + Node* child5() const { return child5_.get(); } + Node* child6() const { return child6_.get(); } + Node* child7() const { return child7_.get(); } + Node* child8() const { return child8_.get(); } + Node* child9() const { return child9_.get(); } + + protected: + std::unique_ptr<Node> root_; + std::unique_ptr<Node> child1_; + std::unique_ptr<Node> child2_; + std::unique_ptr<Node> child3_; + std::unique_ptr<Node> child4_; + std::unique_ptr<Node> child5_; + std::unique_ptr<Node> child6_; + std::unique_ptr<Node> child7_; + std::unique_ptr<Node> child8_; + std::unique_ptr<Node> child9_; +}; + +TEST_F(CXFA_NodeIteratorTemplateTest, Empty) { + Iterator iter(nullptr); + EXPECT_EQ(nullptr, iter.GetRoot()); + EXPECT_EQ(nullptr, iter.GetCurrent()); + EXPECT_EQ(nullptr, iter.MoveToNext()); + EXPECT_EQ(nullptr, iter.MoveToPrev()); + EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, Root) { + Iterator iter(root()); + EXPECT_EQ(root(), iter.GetRoot()); + EXPECT_EQ(root(), iter.GetCurrent()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, Current) { + Iterator iter(root()); + iter.SetCurrent(child1()); + EXPECT_EQ(root(), iter.GetRoot()); + EXPECT_EQ(child1(), iter.GetCurrent()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, CurrentOutsideRootDisallowed) { + Iterator iter(child1()); + iter.SetCurrent(root()); + EXPECT_EQ(child1(), iter.GetRoot()); + EXPECT_EQ(nullptr, iter.GetCurrent()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, CurrentNull) { + Iterator iter(root()); + EXPECT_EQ(child1(), iter.MoveToNext()); + + iter.SetCurrent(nullptr); + EXPECT_EQ(nullptr, iter.GetCurrent()); + + EXPECT_EQ(nullptr, iter.MoveToNext()); + EXPECT_EQ(nullptr, iter.GetCurrent()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, MoveToPrev) { + Iterator iter(root()); + iter.SetCurrent(child9()); + + EXPECT_EQ(child8(), iter.MoveToPrev()); + EXPECT_EQ(child8(), iter.GetCurrent()); + + EXPECT_EQ(child7(), iter.MoveToPrev()); + EXPECT_EQ(child7(), iter.GetCurrent()); + + EXPECT_EQ(child6(), iter.MoveToPrev()); + EXPECT_EQ(child6(), iter.GetCurrent()); + + EXPECT_EQ(child5(), iter.MoveToPrev()); + EXPECT_EQ(child5(), iter.GetCurrent()); + + EXPECT_EQ(child4(), iter.MoveToPrev()); + EXPECT_EQ(child4(), iter.GetCurrent()); + + EXPECT_EQ(child3(), iter.MoveToPrev()); + EXPECT_EQ(child3(), iter.GetCurrent()); + + EXPECT_EQ(child2(), iter.MoveToPrev()); + EXPECT_EQ(child2(), iter.GetCurrent()); + + EXPECT_EQ(child1(), iter.MoveToPrev()); + EXPECT_EQ(child1(), iter.GetCurrent()); + + EXPECT_EQ(root(), iter.MoveToPrev()); + EXPECT_EQ(root(), iter.GetCurrent()); + + EXPECT_EQ(nullptr, iter.MoveToPrev()); + EXPECT_EQ(root(), iter.GetCurrent()); + + EXPECT_EQ(nullptr, iter.MoveToPrev()); + EXPECT_EQ(root(), iter.GetCurrent()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, MoveToNext) { + Iterator iter(root()); + iter.SetCurrent(child2()); + + EXPECT_EQ(child3(), iter.MoveToNext()); + EXPECT_EQ(child3(), iter.GetCurrent()); + + EXPECT_EQ(child4(), iter.MoveToNext()); + EXPECT_EQ(child4(), iter.GetCurrent()); + + EXPECT_EQ(child5(), iter.MoveToNext()); + EXPECT_EQ(child5(), iter.GetCurrent()); + + EXPECT_EQ(child6(), iter.MoveToNext()); + EXPECT_EQ(child6(), iter.GetCurrent()); + + EXPECT_EQ(child7(), iter.MoveToNext()); + EXPECT_EQ(child7(), iter.GetCurrent()); + + EXPECT_EQ(child8(), iter.MoveToNext()); + EXPECT_EQ(child8(), iter.GetCurrent()); + + EXPECT_EQ(child9(), iter.MoveToNext()); + EXPECT_EQ(child9(), iter.GetCurrent()); + + EXPECT_EQ(nullptr, iter.MoveToNext()); + EXPECT_EQ(nullptr, iter.GetCurrent()); + + EXPECT_EQ(nullptr, iter.MoveToNext()); + EXPECT_EQ(nullptr, iter.GetCurrent()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, SkipChildrenAndMoveToNext) { + Iterator iter(root()); + iter.SetCurrent(child3()); + EXPECT_EQ(child7(), iter.SkipChildrenAndMoveToNext()); + EXPECT_EQ(child9(), iter.SkipChildrenAndMoveToNext()); + EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, BackAndForth) { + Iterator iter(root()); + EXPECT_EQ(child1(), iter.MoveToNext()); + EXPECT_EQ(child2(), iter.MoveToNext()); + EXPECT_EQ(child3(), iter.MoveToNext()); + EXPECT_EQ(child4(), iter.MoveToNext()); + EXPECT_EQ(child5(), iter.MoveToNext()); + EXPECT_EQ(child4(), iter.MoveToPrev()); + EXPECT_EQ(child3(), iter.MoveToPrev()); + EXPECT_EQ(child2(), iter.MoveToPrev()); + EXPECT_EQ(child1(), iter.MoveToPrev()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, NextFromBeforeTheBeginning) { + Iterator iter(root()); + EXPECT_EQ(nullptr, iter.MoveToPrev()); + EXPECT_EQ(root(), iter.GetCurrent()); + EXPECT_EQ(child1(), iter.MoveToNext()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, PrevFromAfterTheEnd) { + Iterator iter(root()); + iter.SetCurrent(child9()); + EXPECT_EQ(nullptr, iter.MoveToNext()); + EXPECT_EQ(child9(), iter.MoveToPrev()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, ChildAsRootPrev) { + Iterator iter(child3()); + EXPECT_EQ(nullptr, iter.MoveToPrev()); + + iter.SetCurrent(child4()); + EXPECT_EQ(child3(), iter.MoveToPrev()); + EXPECT_EQ(nullptr, iter.MoveToPrev()); +} + +TEST_F(CXFA_NodeIteratorTemplateTest, ChildAsRootNext) { + Iterator iter(child3()); + iter.SetCurrent(child4()); + EXPECT_EQ(child5(), iter.MoveToNext()); + EXPECT_EQ(child6(), iter.MoveToNext()); + EXPECT_EQ(nullptr, iter.MoveToNext()); +} diff --git a/xfa/fxfa/parser/cxfa_nodelist.cpp b/xfa/fxfa/parser/cxfa_nodelist.cpp deleted file mode 100644 index 97c531f33b66d13185c063499b1e066f885ab6a2..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_nodelist.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_object.h" - -#include <memory> - -#include "core/fxcrt/fx_ext.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" - -CXFA_NodeList::CXFA_NodeList(CXFA_Document* pDocument) - : CXFA_Object(pDocument, - XFA_ObjectType::NodeList, - XFA_Element::NodeList, - CFX_WideStringC(L"nodeList")) { - m_pDocument->GetScriptContext()->AddToCacheList( - std::unique_ptr<CXFA_NodeList>(this)); -} - -CXFA_NodeList::~CXFA_NodeList() {} - -CXFA_Node* CXFA_NodeList::NamedItem(const CFX_WideStringC& wsName) { - uint32_t dwHashCode = FX_HashCode_GetW(wsName, false); - int32_t iCount = GetLength(); - for (int32_t i = 0; i < iCount; i++) { - CXFA_Node* ret = Item(i); - if (dwHashCode == ret->GetNameHash()) - return ret; - } - return nullptr; -} - -void CXFA_NodeList::Script_ListClass_Append(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 1) { - ThrowParamCountMismatchException(L"append"); - return; - } - - CXFA_Node* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - if (!pNode) { - ThrowArgumentMismatchException(); - return; - } - Append(pNode); -} - -void CXFA_NodeList::Script_ListClass_Insert(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 2) { - ThrowParamCountMismatchException(L"insert"); - return; - } - - CXFA_Node* pNewNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - CXFA_Node* pBeforeNode = static_cast<CXFA_Node*>(pArguments->GetObject(1)); - if (!pNewNode) { - ThrowArgumentMismatchException(); - return; - } - Insert(pNewNode, pBeforeNode); -} - -void CXFA_NodeList::Script_ListClass_Remove(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 1) { - ThrowParamCountMismatchException(L"remove"); - return; - } - - CXFA_Node* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0)); - if (!pNode) { - ThrowArgumentMismatchException(); - return; - } - Remove(pNode); -} - -void CXFA_NodeList::Script_ListClass_Item(CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 1) { - ThrowParamCountMismatchException(L"item"); - return; - } - - int32_t iIndex = pArguments->GetInt32(0); - if (iIndex < 0 || iIndex >= GetLength()) { - ThrowIndexOutOfBoundsException(); - return; - } - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(Item(iIndex))); -} - -void CXFA_NodeList::Script_TreelistClass_NamedItem( - CFXJSE_Arguments* pArguments) { - int32_t argc = pArguments->GetLength(); - if (argc != 1) { - ThrowParamCountMismatchException(L"namedItem"); - return; - } - - CFX_ByteString szName = pArguments->GetUTF8String(0); - CXFA_Node* pNode = - NamedItem(CFX_WideString::FromUTF8(szName.AsStringC()).AsStringC()); - if (!pNode) - return; - - pArguments->GetReturnValue()->Assign( - m_pDocument->GetScriptContext()->GetJSValueFromMap(pNode)); -} - -void CXFA_NodeList::Script_ListClass_Length(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - pValue->SetInteger(GetLength()); -} diff --git a/xfa/fxfa/parser/cxfa_nodelocale.cpp b/xfa/fxfa/parser/cxfa_nodelocale.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a93452cc51ead48ca7827a6e00f0dcaff171c2fe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_nodelocale.cpp @@ -0,0 +1,177 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_nodelocale.h" + +#include <utility> + +#include "core/fxcrt/xml/cxml_element.h" +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/parser/cxfa_calendarsymbols.h" +#include "xfa/fxfa/parser/cxfa_datetimesymbols.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_timezoneprovider.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +namespace { + +const wchar_t g_FX_Percent[] = L"z,zzz,zzz,zzz,zzz,zzz%"; +const wchar_t g_FX_Currency[] = L"$z,zzz,zzz,zzz,zzz,zz9.99"; +const wchar_t g_FX_Decimal[] = L"z,zzz,zzz,zzz,zzz,zz9.zzz"; +const wchar_t g_FX_Integer[] = L"z,zzz,zzz,zzz,zzz,zzz"; + +} // namespace + +WideString XFA_PatternToString(FX_LOCALENUMSUBCATEGORY category) { + switch (category) { + case FX_LOCALENUMPATTERN_Percent: + return g_FX_Percent; + case FX_LOCALENUMPATTERN_Currency: + return g_FX_Currency; + case FX_LOCALENUMPATTERN_Decimal: + return g_FX_Decimal; + case FX_LOCALENUMPATTERN_Integer: + return g_FX_Integer; + } + return WideString(); +} + +CXFA_NodeLocale::CXFA_NodeLocale(CXFA_Node* pLocale) : m_pLocale(pLocale) {} + +CXFA_NodeLocale::~CXFA_NodeLocale() {} + +WideString CXFA_NodeLocale::GetName() const { + return WideString(m_pLocale + ? m_pLocale->JSObject()->GetCData(XFA_Attribute::Name) + : nullptr); +} + +WideString CXFA_NodeLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const { + switch (eType) { + case FX_LOCALENUMSYMBOL_Decimal: + return GetSymbol(XFA_Element::NumberSymbols, L"decimal"); + case FX_LOCALENUMSYMBOL_Grouping: + return GetSymbol(XFA_Element::NumberSymbols, L"grouping"); + case FX_LOCALENUMSYMBOL_Percent: + return GetSymbol(XFA_Element::NumberSymbols, L"percent"); + case FX_LOCALENUMSYMBOL_Minus: + return GetSymbol(XFA_Element::NumberSymbols, L"minus"); + case FX_LOCALENUMSYMBOL_Zero: + return GetSymbol(XFA_Element::NumberSymbols, L"zero"); + case FX_LOCALENUMSYMBOL_CurrencySymbol: + return GetSymbol(XFA_Element::CurrencySymbols, L"symbol"); + case FX_LOCALENUMSYMBOL_CurrencyName: + return GetSymbol(XFA_Element::CurrencySymbols, L"isoname"); + } + return WideString(); +} + +WideString CXFA_NodeLocale::GetDateTimeSymbols() const { + CXFA_DateTimeSymbols* pSymbols = + m_pLocale ? m_pLocale->GetChild<CXFA_DateTimeSymbols>( + 0, XFA_Element::DateTimeSymbols, false) + : nullptr; + return pSymbols ? pSymbols->JSObject()->GetContent(false) : WideString(); +} + +WideString CXFA_NodeLocale::GetMonthName(int32_t nMonth, bool bAbbr) const { + return GetCalendarSymbol(XFA_Element::MonthNames, nMonth, bAbbr); +} + +WideString CXFA_NodeLocale::GetDayName(int32_t nWeek, bool bAbbr) const { + return GetCalendarSymbol(XFA_Element::DayNames, nWeek, bAbbr); +} + +WideString CXFA_NodeLocale::GetMeridiemName(bool bAM) const { + return GetCalendarSymbol(XFA_Element::MeridiemNames, bAM ? 0 : 1, false); +} + +FX_TIMEZONE CXFA_NodeLocale::GetTimeZone() const { + return CXFA_TimeZoneProvider().GetTimeZone(); +} + +WideString CXFA_NodeLocale::GetEraName(bool bAD) const { + return GetCalendarSymbol(XFA_Element::EraNames, bAD ? 1 : 0, false); +} + +WideString CXFA_NodeLocale::GetDatePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const { + switch (eType) { + case FX_LOCALEDATETIMESUBCATEGORY_Short: + return GetSymbol(XFA_Element::DatePatterns, L"short"); + case FX_LOCALEDATETIMESUBCATEGORY_Medium: + case FX_LOCALEDATETIMESUBCATEGORY_Default: + return GetSymbol(XFA_Element::DatePatterns, L"med"); + case FX_LOCALEDATETIMESUBCATEGORY_Full: + return GetSymbol(XFA_Element::DatePatterns, L"full"); + case FX_LOCALEDATETIMESUBCATEGORY_Long: + return GetSymbol(XFA_Element::DatePatterns, L"long"); + } + return WideString(); +} + +WideString CXFA_NodeLocale::GetTimePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const { + switch (eType) { + case FX_LOCALEDATETIMESUBCATEGORY_Short: + return GetSymbol(XFA_Element::TimePatterns, L"short"); + case FX_LOCALEDATETIMESUBCATEGORY_Medium: + case FX_LOCALEDATETIMESUBCATEGORY_Default: + return GetSymbol(XFA_Element::TimePatterns, L"med"); + case FX_LOCALEDATETIMESUBCATEGORY_Full: + return GetSymbol(XFA_Element::TimePatterns, L"full"); + case FX_LOCALEDATETIMESUBCATEGORY_Long: + return GetSymbol(XFA_Element::TimePatterns, L"long"); + } + return WideString(); +} + +WideString CXFA_NodeLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const { + return XFA_PatternToString(eType); +} + +CXFA_Node* CXFA_NodeLocale::GetNodeByName(CXFA_Node* pParent, + const WideStringView& wsName) const { + CXFA_Node* pChild = pParent ? pParent->GetFirstChild() : nullptr; + while (pChild) { + if (pChild->JSObject()->GetAttribute(XFA_Attribute::Name) == wsName) + return pChild; + + pChild = pChild->GetNextSibling(); + } + return nullptr; +} + +WideString CXFA_NodeLocale::GetSymbol(XFA_Element eElement, + const WideStringView& symbol_type) const { + CXFA_Node* pSymbols = + m_pLocale ? m_pLocale->GetChild<CXFA_Node>(0, eElement, false) : nullptr; + CXFA_Node* pSymbol = GetNodeByName(pSymbols, symbol_type); + return pSymbol ? pSymbol->JSObject()->GetContent(false) : WideString(); +} + +WideString CXFA_NodeLocale::GetCalendarSymbol(XFA_Element eElement, + int index, + bool bAbbr) const { + CXFA_CalendarSymbols* pCalendar = + m_pLocale ? m_pLocale->GetChild<CXFA_CalendarSymbols>( + 0, XFA_Element::CalendarSymbols, false) + : nullptr; + if (!pCalendar) + return WideString(); + + CXFA_Node* pNode = pCalendar->GetFirstChildByClass<CXFA_Node>(eElement); + for (; pNode; pNode = pNode->GetNextSameClassSibling<CXFA_Node>(eElement)) { + if (pNode->JSObject()->GetBoolean(XFA_Attribute::Abbr) == bAbbr) { + CXFA_Node* pSymbol = + pNode->GetChild<CXFA_Node>(index, XFA_Element::Unknown, false); + return pSymbol ? pSymbol->JSObject()->GetContent(false) : WideString(); + } + } + return WideString(); +} diff --git a/xfa/fxfa/parser/cxfa_nodelocale.h b/xfa/fxfa/parser/cxfa_nodelocale.h new file mode 100644 index 0000000000000000000000000000000000000000..6f79e4a65a04496e21b00e94b4132518a4a55d45 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_nodelocale.h @@ -0,0 +1,51 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NODELOCALE_H_ +#define XFA_FXFA_PARSER_CXFA_NODELOCALE_H_ + +#include <memory> + +#include "core/fxcrt/ifx_locale.h" +#include "xfa/fxfa/fxfa_basic.h" + +class CXFA_Node; + +WideString XFA_PatternToString(FX_LOCALENUMSUBCATEGORY category); + +class CXFA_NodeLocale : public IFX_Locale { + public: + explicit CXFA_NodeLocale(CXFA_Node* pLocale); + ~CXFA_NodeLocale() override; + + // IFX_Locale + WideString GetName() const override; + WideString GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const override; + + WideString GetDateTimeSymbols() const override; + WideString GetMonthName(int32_t nMonth, bool bAbbr) const override; + WideString GetDayName(int32_t nWeek, bool bAbbr) const override; + WideString GetMeridiemName(bool bAM) const override; + FX_TIMEZONE GetTimeZone() const override; + WideString GetEraName(bool bAD) const override; + + WideString GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType) const override; + WideString GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType) const override; + WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const override; + + private: + CXFA_Node* GetNodeByName(CXFA_Node* pParent, + const WideStringView& wsName) const; + WideString GetSymbol(XFA_Element eElement, + const WideStringView& symbol_type) const; + WideString GetCalendarSymbol(XFA_Element eElement, + int index, + bool bAbbr) const; + + UnownedPtr<CXFA_Node> const m_pLocale; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NODELOCALE_H_ diff --git a/xfa/fxfa/parser/cxfa_numberofcopies.cpp b/xfa/fxfa/parser/cxfa_numberofcopies.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0978859ee1b122847538af553e16d67a9a0be638 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numberofcopies.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_numberofcopies.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"numberOfCopies"; + +} // namespace + +CXFA_NumberOfCopies::CXFA_NumberOfCopies(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::NumberOfCopies, + nullptr, + kAttributeData, + kName) {} + +CXFA_NumberOfCopies::~CXFA_NumberOfCopies() {} diff --git a/xfa/fxfa/parser/cxfa_numberofcopies.h b/xfa/fxfa/parser/cxfa_numberofcopies.h new file mode 100644 index 0000000000000000000000000000000000000000..04bb5999841879817f2613389df0136cd838080d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numberofcopies.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NUMBEROFCOPIES_H_ +#define XFA_FXFA_PARSER_CXFA_NUMBEROFCOPIES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NumberOfCopies : public CXFA_Node { + public: + CXFA_NumberOfCopies(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NumberOfCopies() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NUMBEROFCOPIES_H_ diff --git a/xfa/fxfa/parser/cxfa_numberpattern.cpp b/xfa/fxfa/parser/cxfa_numberpattern.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ee2698e2e8d8da70c1e70733bdb1610a35f9c01 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numberpattern.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_numberpattern.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Numeric}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"numberPattern"; + +} // namespace + +CXFA_NumberPattern::CXFA_NumberPattern(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::NumberPattern, + nullptr, + kAttributeData, + kName) {} + +CXFA_NumberPattern::~CXFA_NumberPattern() {} diff --git a/xfa/fxfa/parser/cxfa_numberpattern.h b/xfa/fxfa/parser/cxfa_numberpattern.h new file mode 100644 index 0000000000000000000000000000000000000000..0a4fabd2a289b53cdfa2e713a6b0f2a1aa898d11 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numberpattern.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NUMBERPATTERN_H_ +#define XFA_FXFA_PARSER_CXFA_NUMBERPATTERN_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NumberPattern : public CXFA_Node { + public: + CXFA_NumberPattern(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NumberPattern() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NUMBERPATTERN_H_ diff --git a/xfa/fxfa/parser/cxfa_numberpatterns.cpp b/xfa/fxfa/parser/cxfa_numberpatterns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2f83739aa7191e9c8370dcb7c4dfeb29ebf0227 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numberpatterns.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_numberpatterns.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::NumberPattern, 4, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"numberPatterns"; + +} // namespace + +CXFA_NumberPatterns::CXFA_NumberPatterns(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::NumberPatterns, + kPropertyData, + nullptr, + kName) {} + +CXFA_NumberPatterns::~CXFA_NumberPatterns() {} diff --git a/xfa/fxfa/parser/cxfa_numberpatterns.h b/xfa/fxfa/parser/cxfa_numberpatterns.h new file mode 100644 index 0000000000000000000000000000000000000000..ef4f8893a2200981299f5f189ab9530593764880 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numberpatterns.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NUMBERPATTERNS_H_ +#define XFA_FXFA_PARSER_CXFA_NUMBERPATTERNS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NumberPatterns : public CXFA_Node { + public: + CXFA_NumberPatterns(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NumberPatterns() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NUMBERPATTERNS_H_ diff --git a/xfa/fxfa/parser/cxfa_numbersymbol.cpp b/xfa/fxfa/parser/cxfa_numbersymbol.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74fdc1bb02b15d036e56a8857236e127765268db --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numbersymbol.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_numbersymbol.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Decimal}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"numberSymbol"; + +} // namespace + +CXFA_NumberSymbol::CXFA_NumberSymbol(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::NumberSymbol, + nullptr, + kAttributeData, + kName) {} + +CXFA_NumberSymbol::~CXFA_NumberSymbol() {} diff --git a/xfa/fxfa/parser/cxfa_numbersymbol.h b/xfa/fxfa/parser/cxfa_numbersymbol.h new file mode 100644 index 0000000000000000000000000000000000000000..c164b0381baa3b4944cee6d70c7ce57c240aafac --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numbersymbol.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NUMBERSYMBOL_H_ +#define XFA_FXFA_PARSER_CXFA_NUMBERSYMBOL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NumberSymbol : public CXFA_Node { + public: + CXFA_NumberSymbol(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NumberSymbol() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NUMBERSYMBOL_H_ diff --git a/xfa/fxfa/parser/cxfa_numbersymbols.cpp b/xfa/fxfa/parser/cxfa_numbersymbols.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d27f69c0b4d9c755ae7b7a36d6c4ff217c82e44 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numbersymbols.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_numbersymbols.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::NumberSymbol, 5, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"numberSymbols"; + +} // namespace + +CXFA_NumberSymbols::CXFA_NumberSymbols(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::NumberSymbols, + kPropertyData, + nullptr, + kName) {} + +CXFA_NumberSymbols::~CXFA_NumberSymbols() {} diff --git a/xfa/fxfa/parser/cxfa_numbersymbols.h b/xfa/fxfa/parser/cxfa_numbersymbols.h new file mode 100644 index 0000000000000000000000000000000000000000..972df9f45575ee8d86bdf02424d3bbdc0e478623 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numbersymbols.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NUMBERSYMBOLS_H_ +#define XFA_FXFA_PARSER_CXFA_NUMBERSYMBOLS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NumberSymbols : public CXFA_Node { + public: + CXFA_NumberSymbols(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NumberSymbols() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NUMBERSYMBOLS_H_ diff --git a/xfa/fxfa/parser/cxfa_numericedit.cpp b/xfa/fxfa/parser/cxfa_numericedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a65c763b22a7b0db05ceab763b1f6310e04ffcd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numericedit.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_numericedit.h" + +#include "fxjs/xfa/cjx_numericedit.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Comb, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HScrollPolicy, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"numericEdit"; + +} // namespace + +CXFA_NumericEdit::CXFA_NumericEdit(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::NumericEdit, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_NumericEdit>(this)) {} + +CXFA_NumericEdit::~CXFA_NumericEdit() {} diff --git a/xfa/fxfa/parser/cxfa_numericedit.h b/xfa/fxfa/parser/cxfa_numericedit.h new file mode 100644 index 0000000000000000000000000000000000000000..d9cfd7e57d856275d4a5ec49bc78b35e5acdb1c5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_numericedit.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_NUMERICEDIT_H_ +#define XFA_FXFA_PARSER_CXFA_NUMERICEDIT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_NumericEdit : public CXFA_Node { + public: + CXFA_NumericEdit(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_NumericEdit() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_NUMERICEDIT_H_ diff --git a/xfa/fxfa/parser/cxfa_object.cpp b/xfa/fxfa/parser/cxfa_object.cpp index c8cd354b485bb12e7441cefa05700e4ce99b0a0f..7c73db0ff54526749b48f0327a3f92583892854a 100644 --- a/xfa/fxfa/parser/cxfa_object.cpp +++ b/xfa/fxfa/parser/cxfa_object.cpp @@ -4,70 +4,66 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_object.h" -#include "core/fxcrt/fx_ext.h" +#include <utility> + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" #include "fxjs/cfxjse_value.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/cxfa_ffnotify.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_treelist.h" CXFA_Object::CXFA_Object(CXFA_Document* pDocument, XFA_ObjectType objectType, XFA_Element elementType, - const CFX_WideStringC& elementName) - : m_pDocument(pDocument), + const WideStringView& elementName, + std::unique_ptr<CJX_Object> jsObject) + : CFXJSE_HostObject(kXFA), + m_pDocument(pDocument), m_objectType(objectType), m_elementType(elementType), m_elementNameHash(FX_HashCode_GetW(elementName, false)), - m_elementName(elementName) {} + m_elementName(elementName), + m_pJSObject(std::move(jsObject)) {} CXFA_Object::~CXFA_Object() {} -CFX_WideStringC CXFA_Object::GetClassName() const { - return m_elementName; -} +WideString CXFA_Object::GetSOMExpression() { + CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext(); + if (!pScriptContext) + return WideString(); -uint32_t CXFA_Object::GetClassHashCode() const { - return m_elementNameHash; + return pScriptContext->GetSomExpression(ToNode(this)); } -XFA_Element CXFA_Object::GetElementType() const { - return m_elementType; +CXFA_Node* CXFA_Object::AsNode() { + return IsNode() ? static_cast<CXFA_Node*>(this) : nullptr; } -void CXFA_Object::Script_ObjectClass_ClassName(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute) { - if (bSetting) { - ThrowInvalidPropertyException(); - return; - } - pValue->SetString(FX_UTF8Encode(GetClassName()).AsStringC()); +CXFA_TreeList* CXFA_Object::AsTreeList() { + return IsTreeList() ? static_cast<CXFA_TreeList*>(this) : nullptr; } -void CXFA_Object::ThrowInvalidPropertyException() const { - ThrowException(L"Invalid property set operation."); +const CXFA_Node* CXFA_Object::AsNode() const { + return IsNode() ? static_cast<const CXFA_Node*>(this) : nullptr; } -void CXFA_Object::ThrowIndexOutOfBoundsException() const { - ThrowException(L"Index value is out of bounds."); +const CXFA_TreeList* CXFA_Object::AsTreeList() const { + return IsTreeList() ? static_cast<const CXFA_TreeList*>(this) : nullptr; } -void CXFA_Object::ThrowParamCountMismatchException( - const CFX_WideString& method) const { - ThrowException(L"Incorrect number of parameters calling method '%s'.", - method.c_str()); +void CXFA_Object::CreateWidgetAcc() { + acc_ = pdfium::MakeUnique<CXFA_WidgetAcc>(AsNode()); } -void CXFA_Object::ThrowArgumentMismatchException() const { - ThrowException(L"Argument mismatch in property or function argument."); +CXFA_Node* ToNode(CXFA_Object* pObj) { + return pObj ? pObj->AsNode() : nullptr; } -void CXFA_Object::ThrowException(const FX_WCHAR* str, ...) const { - CFX_WideString wsMessage; - va_list arg_ptr; - va_start(arg_ptr, str); - wsMessage.FormatV(str, arg_ptr); - va_end(arg_ptr); - FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringC()); +const CXFA_Node* ToNode(const CXFA_Object* pObj) { + return pObj ? pObj->AsNode() : nullptr; } diff --git a/xfa/fxfa/parser/cxfa_object.h b/xfa/fxfa/parser/cxfa_object.h new file mode 100644 index 0000000000000000000000000000000000000000..5d5f31c64780f11287e048a926e871ef2d92e947 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_object.h @@ -0,0 +1,111 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OBJECT_H_ +#define XFA_FXFA_PARSER_CXFA_OBJECT_H_ + +#include <memory> + +#include "core/fxcrt/fx_string.h" +#include "fxjs/fxjse.h" +#include "xfa/fxfa/fxfa_basic.h" + +enum class XFA_ObjectType { + Object, + List, + Node, + NodeC, + NodeV, + ModelNode, + TextNode, + TreeList, + ContainerNode, + ContentNode, + VariablesThis +}; + +class CJX_Object; +class CXFA_Document; +class CXFA_Node; +class CXFA_TreeList; +class CXFA_WidgetAcc; + +class CXFA_Object : public CFXJSE_HostObject { + public: + ~CXFA_Object() override; + + CXFA_Document* GetDocument() const { return m_pDocument.Get(); } + XFA_ObjectType GetObjectType() const { return m_objectType; } + + bool IsNode() const { + return m_objectType == XFA_ObjectType::Node || + m_objectType == XFA_ObjectType::NodeC || + m_objectType == XFA_ObjectType::NodeV || + m_objectType == XFA_ObjectType::ModelNode || + m_objectType == XFA_ObjectType::TextNode || + m_objectType == XFA_ObjectType::ContainerNode || + m_objectType == XFA_ObjectType::ContentNode || + m_objectType == XFA_ObjectType::VariablesThis; + } + bool IsTreeList() const { return m_objectType == XFA_ObjectType::TreeList; } + bool IsContentNode() const { + return m_objectType == XFA_ObjectType::ContentNode; + } + bool IsContainerNode() const { + return m_objectType == XFA_ObjectType::ContainerNode; + } + bool IsModelNode() const { return m_objectType == XFA_ObjectType::ModelNode; } + bool IsNodeV() const { return m_objectType == XFA_ObjectType::NodeV; } + bool IsVariablesThis() const { + return m_objectType == XFA_ObjectType::VariablesThis; + } + + CXFA_Node* AsNode(); + CXFA_TreeList* AsTreeList(); + + const CXFA_Node* AsNode() const; + const CXFA_TreeList* AsTreeList() const; + + CJX_Object* JSObject() { return m_pJSObject.get(); } + const CJX_Object* JSObject() const { return m_pJSObject.get(); } + + bool HasCreatedUIWidget() const { + return m_elementType == XFA_Element::Field || + m_elementType == XFA_Element::Draw || + m_elementType == XFA_Element::Subform || + m_elementType == XFA_Element::ExclGroup; + } + void CreateWidgetAcc(); + CXFA_WidgetAcc* GetWidgetAcc() { return acc_.get(); } + + XFA_Element GetElementType() const { return m_elementType; } + WideStringView GetClassName() const { return m_elementName; } + uint32_t GetClassHashCode() const { return m_elementNameHash; } + + WideString GetSOMExpression(); + + protected: + CXFA_Object(CXFA_Document* pDocument, + XFA_ObjectType objectType, + XFA_Element eType, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> jsObject); + + UnownedPtr<CXFA_Document> const m_pDocument; + const XFA_ObjectType m_objectType; + const XFA_Element m_elementType; + + const uint32_t m_elementNameHash; + const WideStringView m_elementName; + + std::unique_ptr<CJX_Object> m_pJSObject; + std::unique_ptr<CXFA_WidgetAcc> acc_; +}; + +CXFA_Node* ToNode(CXFA_Object* pObj); +const CXFA_Node* ToNode(const CXFA_Object* pObj); + +#endif // XFA_FXFA_PARSER_CXFA_OBJECT_H_ diff --git a/xfa/fxfa/parser/cxfa_occur.cpp b/xfa/fxfa/parser/cxfa_occur.cpp index a8994223f9356bb2903ccf848c2c8d0231e99600..7be3f7066d98fc1b33f1b75f5e4779112841cd40 100644 --- a/xfa/fxfa/parser/cxfa_occur.cpp +++ b/xfa/fxfa/parser/cxfa_occur.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,62 +6,76 @@ #include "xfa/fxfa/parser/cxfa_occur.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_occur.h" +#include "third_party/base/ptr_util.h" -CXFA_Occur::CXFA_Occur(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Max, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Min, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Initial, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"occur"; + +} // namespace + +CXFA_Occur::CXFA_Occur(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Occur, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Occur>(this)) {} + +CXFA_Occur::~CXFA_Occur() {} int32_t CXFA_Occur::GetMax() { - int32_t iMax = 1; - if (m_pNode) { - if (!m_pNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, true)) - iMax = GetMin(); - } - return iMax; + Optional<int32_t> max = JSObject()->TryInteger(XFA_Attribute::Max, true); + return max ? *max : GetMin(); } int32_t CXFA_Occur::GetMin() { - int32_t iMin = 1; - if (m_pNode) { - if (!m_pNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, true) || iMin < 0) - iMin = 1; - } - return iMin; + Optional<int32_t> min = JSObject()->TryInteger(XFA_Attribute::Min, true); + return min && *min >= 0 ? *min : 1; } -bool CXFA_Occur::GetOccurInfo(int32_t& iMin, int32_t& iMax, int32_t& iInit) { - if (!m_pNode) - return false; - if (!m_pNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, false) || iMin < 0) - iMin = 1; - if (!m_pNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, false)) { - if (iMin == 0) - iMax = 1; - else - iMax = iMin; - } - if (!m_pNode->TryInteger(XFA_ATTRIBUTE_Initial, iInit, false) || - iInit < iMin) { - iInit = iMin; - } - return true; +std::tuple<int32_t, int32_t, int32_t> CXFA_Occur::GetOccurInfo() { + int32_t iMin = GetMin(); + int32_t iMax = GetMax(); + + Optional<int32_t> init = + JSObject()->TryInteger(XFA_Attribute::Initial, false); + return {iMin, iMax, init && *init >= iMin ? *init : iMin}; } void CXFA_Occur::SetMax(int32_t iMax) { iMax = (iMax != -1 && iMax < 1) ? 1 : iMax; - m_pNode->SetInteger(XFA_ATTRIBUTE_Max, iMax, false); + JSObject()->SetInteger(XFA_Attribute::Max, iMax, false); + int32_t iMin = GetMin(); if (iMax != -1 && iMax < iMin) { iMin = iMax; - m_pNode->SetInteger(XFA_ATTRIBUTE_Min, iMin, false); + JSObject()->SetInteger(XFA_Attribute::Min, iMin, false); } } void CXFA_Occur::SetMin(int32_t iMin) { iMin = (iMin < 0) ? 1 : iMin; - m_pNode->SetInteger(XFA_ATTRIBUTE_Min, iMin, false); + JSObject()->SetInteger(XFA_Attribute::Min, iMin, false); + int32_t iMax = GetMax(); if (iMax > 0 && iMax < iMin) { iMax = iMin; - m_pNode->SetInteger(XFA_ATTRIBUTE_Max, iMax, false); + JSObject()->SetInteger(XFA_Attribute::Max, iMax, false); } } diff --git a/xfa/fxfa/parser/cxfa_occur.h b/xfa/fxfa/parser/cxfa_occur.h index 69db071a11c104b699e076a8e08f723f43027d0d..070c15ca46ea2c34b4b443d42cc51eed0bc954dd 100644 --- a/xfa/fxfa/parser/cxfa_occur.h +++ b/xfa/fxfa/parser/cxfa_occur.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,20 +7,25 @@ #ifndef XFA_FXFA_PARSER_CXFA_OCCUR_H_ #define XFA_FXFA_PARSER_CXFA_OCCUR_H_ -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include <tuple> -class CXFA_Node; +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Occur : public CXFA_Data { +class CXFA_Occur : public CXFA_Node { public: - explicit CXFA_Occur(CXFA_Node* pNode); + static constexpr int32_t kDefaultMax = 1; + static constexpr int32_t kDefaultMin = 1; + + CXFA_Occur(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Occur() override; int32_t GetMax(); - int32_t GetMin(); - bool GetOccurInfo(int32_t& iMin, int32_t& iMax, int32_t& iInit); void SetMax(int32_t iMax); + + int32_t GetMin(); void SetMin(int32_t iMin); + + std::tuple<int32_t, int32_t, int32_t> GetOccurInfo(); }; #endif // XFA_FXFA_PARSER_CXFA_OCCUR_H_ diff --git a/xfa/fxfa/parser/cxfa_oid.cpp b/xfa/fxfa/parser/cxfa_oid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7202e40c0eb8af2d4bbaf2c6151f5a3b24f33d1b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_oid.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_oid.h" + +#include "fxjs/xfa/cjx_oid.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"oid"; + +} // namespace + +CXFA_Oid::CXFA_Oid(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::Oid, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Oid>(this)) {} + +CXFA_Oid::~CXFA_Oid() {} diff --git a/xfa/fxfa/parser/cxfa_oid.h b/xfa/fxfa/parser/cxfa_oid.h new file mode 100644 index 0000000000000000000000000000000000000000..45abf8ba7d9931837ab3a921ed037d20d008b7dc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_oid.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OID_H_ +#define XFA_FXFA_PARSER_CXFA_OID_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Oid : public CXFA_Node { + public: + CXFA_Oid(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Oid() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OID_H_ diff --git a/xfa/fxfa/parser/cxfa_oids.cpp b/xfa/fxfa/parser/cxfa_oids.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31d2a6d92f02047f5ed54bff286d6e0a4de7627e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_oids.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_oids.h" + +#include "fxjs/xfa/cjx_oids.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"oids"; + +} // namespace + +CXFA_Oids::CXFA_Oids(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Oids, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Oids>(this)) {} + +CXFA_Oids::~CXFA_Oids() {} diff --git a/xfa/fxfa/parser/cxfa_oids.h b/xfa/fxfa/parser/cxfa_oids.h new file mode 100644 index 0000000000000000000000000000000000000000..cc8cd9c2de7157d3220ed70f6abe95d56eda09ff --- /dev/null +++ b/xfa/fxfa/parser/cxfa_oids.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OIDS_H_ +#define XFA_FXFA_PARSER_CXFA_OIDS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Oids : public CXFA_Node { + public: + CXFA_Oids(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Oids() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OIDS_H_ diff --git a/xfa/fxfa/parser/cxfa_openaction.cpp b/xfa/fxfa/parser/cxfa_openaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c50f433e21c986bebabbb26f708006f772542775 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_openaction.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_openaction.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Destination, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"openAction"; + +} // namespace + +CXFA_OpenAction::CXFA_OpenAction(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::OpenAction, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_OpenAction::~CXFA_OpenAction() {} diff --git a/xfa/fxfa/parser/cxfa_openaction.h b/xfa/fxfa/parser/cxfa_openaction.h new file mode 100644 index 0000000000000000000000000000000000000000..d84eb2974f460c5037dc3e52e681e50320f808ec --- /dev/null +++ b/xfa/fxfa/parser/cxfa_openaction.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OPENACTION_H_ +#define XFA_FXFA_PARSER_CXFA_OPENACTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_OpenAction : public CXFA_Node { + public: + CXFA_OpenAction(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_OpenAction() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OPENACTION_H_ diff --git a/xfa/fxfa/parser/cxfa_operation.cpp b/xfa/fxfa/parser/cxfa_operation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc92d8c65a33ae4d62fb734768ffa91ec86b5a8e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_operation.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_operation.h" + +#include "fxjs/xfa/cjx_operation.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Output, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Input, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"operation"; + +} // namespace + +CXFA_Operation::CXFA_Operation(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::TextNode, + XFA_Element::Operation, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Operation>(this)) {} + +CXFA_Operation::~CXFA_Operation() {} diff --git a/xfa/fxfa/parser/cxfa_operation.h b/xfa/fxfa/parser/cxfa_operation.h new file mode 100644 index 0000000000000000000000000000000000000000..454a354873be8efc072e4f4a7ec272c4eeef315a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_operation.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OPERATION_H_ +#define XFA_FXFA_PARSER_CXFA_OPERATION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Operation : public CXFA_Node { + public: + CXFA_Operation(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Operation() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OPERATION_H_ diff --git a/xfa/fxfa/parser/cxfa_output.cpp b/xfa/fxfa/parser/cxfa_output.cpp new file mode 100644 index 0000000000000000000000000000000000000000..124d7e5cf1638883e6772cbdf98a29b076b718d4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_output.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_output.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::To, 1, 0}, + {XFA_Element::Uri, 1, 0}, + {XFA_Element::Type, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"output"; + +} // namespace + +CXFA_Output::CXFA_Output(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Output, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Output::~CXFA_Output() {} diff --git a/xfa/fxfa/parser/cxfa_output.h b/xfa/fxfa/parser/cxfa_output.h new file mode 100644 index 0000000000000000000000000000000000000000..2eb139113b4fa7de49149553c3e054cd4fa2c6c0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_output.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OUTPUT_H_ +#define XFA_FXFA_PARSER_CXFA_OUTPUT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Output : public CXFA_Node { + public: + CXFA_Output(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Output() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OUTPUT_H_ diff --git a/xfa/fxfa/parser/cxfa_outputbin.cpp b/xfa/fxfa/parser/cxfa_outputbin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb0ef2ef1958608956d694db5533323cb69c699e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_outputbin.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_outputbin.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"outputBin"; + +} // namespace + +CXFA_OutputBin::CXFA_OutputBin(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::OutputBin, + nullptr, + kAttributeData, + kName) {} + +CXFA_OutputBin::~CXFA_OutputBin() {} diff --git a/xfa/fxfa/parser/cxfa_outputbin.h b/xfa/fxfa/parser/cxfa_outputbin.h new file mode 100644 index 0000000000000000000000000000000000000000..25a1ae0a73c2ca68ed59b6ea3fd5a32740cfc35d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_outputbin.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OUTPUTBIN_H_ +#define XFA_FXFA_PARSER_CXFA_OUTPUTBIN_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_OutputBin : public CXFA_Node { + public: + CXFA_OutputBin(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_OutputBin() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OUTPUTBIN_H_ diff --git a/xfa/fxfa/parser/cxfa_outputxsl.cpp b/xfa/fxfa/parser/cxfa_outputxsl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d56cc156bf6d246d4a126b448b1ec2079791f2f9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_outputxsl.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_outputxsl.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Uri, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"outputXSL"; + +} // namespace + +CXFA_OutputXSL::CXFA_OutputXSL(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::OutputXSL, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_OutputXSL::~CXFA_OutputXSL() {} diff --git a/xfa/fxfa/parser/cxfa_outputxsl.h b/xfa/fxfa/parser/cxfa_outputxsl.h new file mode 100644 index 0000000000000000000000000000000000000000..45355236c027eed879a1562158d25cee1fa0bdf6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_outputxsl.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OUTPUTXSL_H_ +#define XFA_FXFA_PARSER_CXFA_OUTPUTXSL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_OutputXSL : public CXFA_Node { + public: + CXFA_OutputXSL(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_OutputXSL() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OUTPUTXSL_H_ diff --git a/xfa/fxfa/parser/cxfa_overflow.cpp b/xfa/fxfa/parser/cxfa_overflow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25897144b4331e92e3cc55fb6d9aea6b7a9f534a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_overflow.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_overflow.h" + +#include "fxjs/xfa/cjx_overflow.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Trailer, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Target, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Leader, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"overflow"; + +} // namespace + +CXFA_Overflow::CXFA_Overflow(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Overflow, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Overflow>(this)) {} + +CXFA_Overflow::~CXFA_Overflow() {} diff --git a/xfa/fxfa/parser/cxfa_overflow.h b/xfa/fxfa/parser/cxfa_overflow.h new file mode 100644 index 0000000000000000000000000000000000000000..e6627bacb7c8952c65375087e34ccaae00961c99 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_overflow.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OVERFLOW_H_ +#define XFA_FXFA_PARSER_CXFA_OVERFLOW_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Overflow : public CXFA_Node { + public: + CXFA_Overflow(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Overflow() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OVERFLOW_H_ diff --git a/xfa/fxfa/parser/cxfa_overprint.cpp b/xfa/fxfa/parser/cxfa_overprint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf5ee4b57715b78480eb9556fe177d5d732d46d4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_overprint.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_overprint.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"overprint"; + +} // namespace + +CXFA_Overprint::CXFA_Overprint(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Overprint, + nullptr, + kAttributeData, + kName) {} + +CXFA_Overprint::~CXFA_Overprint() {} diff --git a/xfa/fxfa/parser/cxfa_overprint.h b/xfa/fxfa/parser/cxfa_overprint.h new file mode 100644 index 0000000000000000000000000000000000000000..a9ec2416f03d73aca6f76913938b78bfacdd9ea7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_overprint.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_OVERPRINT_H_ +#define XFA_FXFA_PARSER_CXFA_OVERPRINT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Overprint : public CXFA_Node { + public: + CXFA_Overprint(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Overprint() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_OVERPRINT_H_ diff --git a/xfa/fxfa/parser/cxfa_packet.cpp b/xfa/fxfa/parser/cxfa_packet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..61122719800bc3f438224c07a70fe47108b4c29b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_packet.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_packet.h" + +#include "fxjs/xfa/cjx_packet.h" +#include "third_party/base/ptr_util.h" + +namespace { + +constexpr wchar_t kName[] = L"packet"; + +} // namespace + +CXFA_Packet::CXFA_Packet(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_XDP, + XFA_ObjectType::NodeC, + XFA_Element::Packet, + nullptr, + nullptr, + kName, + pdfium::MakeUnique<CJX_Packet>(this)) {} + +CXFA_Packet::~CXFA_Packet() {} diff --git a/xfa/fxfa/parser/cxfa_packet.h b/xfa/fxfa/parser/cxfa_packet.h new file mode 100644 index 0000000000000000000000000000000000000000..6bda61d429d473c1143d923e9f9f4037385158ae --- /dev/null +++ b/xfa/fxfa/parser/cxfa_packet.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PACKET_H_ +#define XFA_FXFA_PARSER_CXFA_PACKET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Packet : public CXFA_Node { + public: + CXFA_Packet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Packet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PACKET_H_ diff --git a/xfa/fxfa/parser/cxfa_packets.cpp b/xfa/fxfa/parser/cxfa_packets.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21b8b19f93a0f7f55df4d2229b00cafa16d8c6bf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_packets.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_packets.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"packets"; + +} // namespace + +CXFA_Packets::CXFA_Packets(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Packets, + nullptr, + kAttributeData, + kName) {} + +CXFA_Packets::~CXFA_Packets() {} diff --git a/xfa/fxfa/parser/cxfa_packets.h b/xfa/fxfa/parser/cxfa_packets.h new file mode 100644 index 0000000000000000000000000000000000000000..ebf29b670ba1819461c5444b6d1c876047bab5f0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_packets.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PACKETS_H_ +#define XFA_FXFA_PARSER_CXFA_PACKETS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Packets : public CXFA_Node { + public: + CXFA_Packets(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Packets() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PACKETS_H_ diff --git a/xfa/fxfa/parser/cxfa_pagearea.cpp b/xfa/fxfa/parser/cxfa_pagearea.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f82b3443d204cf602136fbce56818359042b57fe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pagearea.cpp @@ -0,0 +1,50 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pagearea.h" + +#include "fxjs/xfa/cjx_pagearea.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Medium, 1, 0}, + {XFA_Element::Desc, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Occur, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::PagePosition, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Any}, + {XFA_Attribute::OddOrEven, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Any}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::InitialNumber, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Numbered, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::BlankOrNotBlank, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Any}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pageArea"; + +} // namespace + +CXFA_PageArea::CXFA_PageArea(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::PageArea, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_PageArea>(this)) {} + +CXFA_PageArea::~CXFA_PageArea() {} diff --git a/xfa/fxfa/parser/cxfa_pagearea.h b/xfa/fxfa/parser/cxfa_pagearea.h new file mode 100644 index 0000000000000000000000000000000000000000..f3cab1e073c9d4bc0393b2771b914e772e7c40e1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pagearea.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PAGEAREA_H_ +#define XFA_FXFA_PARSER_CXFA_PAGEAREA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PageArea : public CXFA_Node { + public: + CXFA_PageArea(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PageArea() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PAGEAREA_H_ diff --git a/xfa/fxfa/parser/cxfa_pageoffset.cpp b/xfa/fxfa/parser/cxfa_pageoffset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..467101914dcef8bcf06aab493f98d971897b23da --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pageoffset.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pageoffset.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pageOffset"; + +} // namespace + +CXFA_PageOffset::CXFA_PageOffset(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::PageOffset, + nullptr, + kAttributeData, + kName) {} + +CXFA_PageOffset::~CXFA_PageOffset() {} diff --git a/xfa/fxfa/parser/cxfa_pageoffset.h b/xfa/fxfa/parser/cxfa_pageoffset.h new file mode 100644 index 0000000000000000000000000000000000000000..a396c57baffc071da70064f2cca97bcc46286971 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pageoffset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PAGEOFFSET_H_ +#define XFA_FXFA_PARSER_CXFA_PAGEOFFSET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PageOffset : public CXFA_Node { + public: + CXFA_PageOffset(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PageOffset() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PAGEOFFSET_H_ diff --git a/xfa/fxfa/parser/cxfa_pagerange.cpp b/xfa/fxfa/parser/cxfa_pagerange.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5de7f5fa64b75d39b29bfa15d83d3ebc74c0b9bc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pagerange.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pagerange.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pageRange"; + +} // namespace + +CXFA_PageRange::CXFA_PageRange(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PageRange, + nullptr, + kAttributeData, + kName) {} + +CXFA_PageRange::~CXFA_PageRange() {} diff --git a/xfa/fxfa/parser/cxfa_pagerange.h b/xfa/fxfa/parser/cxfa_pagerange.h new file mode 100644 index 0000000000000000000000000000000000000000..949276aa9c8734f4dd5efbb854955e39c79f1454 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pagerange.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PAGERANGE_H_ +#define XFA_FXFA_PARSER_CXFA_PAGERANGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PageRange : public CXFA_Node { + public: + CXFA_PageRange(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PageRange() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PAGERANGE_H_ diff --git a/xfa/fxfa/parser/cxfa_pageset.cpp b/xfa/fxfa/parser/cxfa_pageset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fea61857df277ce92bc3ce70f44165283e877a5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pageset.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pageset.h" + +#include "fxjs/xfa/cjx_pageset.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Occur, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Relation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::OrderedOccurrence}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DuplexImposition, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::LongEdge}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pageSet"; + +} // namespace + +CXFA_PageSet::CXFA_PageSet(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::PageSet, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_PageSet>(this)) {} + +CXFA_PageSet::~CXFA_PageSet() {} diff --git a/xfa/fxfa/parser/cxfa_pageset.h b/xfa/fxfa/parser/cxfa_pageset.h new file mode 100644 index 0000000000000000000000000000000000000000..9cc3b1708e7b65d603f7b0e696c0839a57a5834e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pageset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PAGESET_H_ +#define XFA_FXFA_PARSER_CXFA_PAGESET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PageSet : public CXFA_Node { + public: + CXFA_PageSet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PageSet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PAGESET_H_ diff --git a/xfa/fxfa/parser/cxfa_pagination.cpp b/xfa/fxfa/parser/cxfa_pagination.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99600eae1b0225b25fedd6f6cae3d040258ded2f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pagination.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pagination.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pagination"; + +} // namespace + +CXFA_Pagination::CXFA_Pagination(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Pagination, + nullptr, + kAttributeData, + kName) {} + +CXFA_Pagination::~CXFA_Pagination() {} diff --git a/xfa/fxfa/parser/cxfa_pagination.h b/xfa/fxfa/parser/cxfa_pagination.h new file mode 100644 index 0000000000000000000000000000000000000000..a455ecbaede28c79a6b59299543042fb13251324 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pagination.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PAGINATION_H_ +#define XFA_FXFA_PARSER_CXFA_PAGINATION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Pagination : public CXFA_Node { + public: + CXFA_Pagination(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Pagination() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PAGINATION_H_ diff --git a/xfa/fxfa/parser/cxfa_paginationoverride.cpp b/xfa/fxfa/parser/cxfa_paginationoverride.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e8b6c682d52d37345dde26a3ea6dcbb4e37baa6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_paginationoverride.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_paginationoverride.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"paginationOverride"; + +} // namespace + +CXFA_PaginationOverride::CXFA_PaginationOverride(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PaginationOverride, + nullptr, + kAttributeData, + kName) {} + +CXFA_PaginationOverride::~CXFA_PaginationOverride() {} diff --git a/xfa/fxfa/parser/cxfa_paginationoverride.h b/xfa/fxfa/parser/cxfa_paginationoverride.h new file mode 100644 index 0000000000000000000000000000000000000000..9cc9528244242108762a647810842404b34c15bb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_paginationoverride.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PAGINATIONOVERRIDE_H_ +#define XFA_FXFA_PARSER_CXFA_PAGINATIONOVERRIDE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PaginationOverride : public CXFA_Node { + public: + CXFA_PaginationOverride(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PaginationOverride() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PAGINATIONOVERRIDE_H_ diff --git a/xfa/fxfa/parser/cxfa_para.cpp b/xfa/fxfa/parser/cxfa_para.cpp index bd3a1bb8ff07e2edbb3041480d70d9f4aa83297a..ad7190dd1f0b866390a9c0d78f350569562e471c 100644 --- a/xfa/fxfa/parser/cxfa_para.cpp +++ b/xfa/fxfa/parser/cxfa_para.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,55 +6,88 @@ #include "xfa/fxfa/parser/cxfa_para.h" +#include "fxjs/xfa/cjx_para.h" +#include "third_party/base/ptr_util.h" #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_object.h" -CXFA_Para::CXFA_Para(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -int32_t CXFA_Para::GetHorizontalAlign() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_Left; - m_pNode->TryEnum(XFA_ATTRIBUTE_HAlign, eAttr); - return eAttr; +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Hyphenation, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Left}, + {XFA_Attribute::TextIndent, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Widows, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::MarginRight, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MarginLeft, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::RadixOffset, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Preserve, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::SpaceBelow, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::VAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Top}, + {XFA_Attribute::TabDefault, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TabStops, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Orphans, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::LineHeight, XFA_AttributeType::Measure, (void*)L"0pt"}, + {XFA_Attribute::SpaceAbove, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"para"; + +} // namespace + +CXFA_Para::CXFA_Para(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Para, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Para>(this)) {} + +CXFA_Para::~CXFA_Para() {} + +XFA_AttributeEnum CXFA_Para::GetHorizontalAlign() { + return JSObject() + ->TryEnum(XFA_Attribute::HAlign, true) + .value_or(XFA_AttributeEnum::Left); } -int32_t CXFA_Para::GetVerticalAlign() { - XFA_ATTRIBUTEENUM eAttr = XFA_ATTRIBUTEENUM_Top; - m_pNode->TryEnum(XFA_ATTRIBUTE_VAlign, eAttr); - return eAttr; +XFA_AttributeEnum CXFA_Para::GetVerticalAlign() { + return JSObject() + ->TryEnum(XFA_Attribute::VAlign, true) + .value_or(XFA_AttributeEnum::Top); } -FX_FLOAT CXFA_Para::GetLineHeight() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_LineHeight, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Para::GetLineHeight() { + return JSObject()->GetMeasure(XFA_Attribute::LineHeight).ToUnit(XFA_Unit::Pt); } -FX_FLOAT CXFA_Para::GetMarginLeft() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_MarginLeft, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Para::GetMarginLeft() { + return JSObject()->GetMeasure(XFA_Attribute::MarginLeft).ToUnit(XFA_Unit::Pt); } -FX_FLOAT CXFA_Para::GetMarginRight() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_MarginRight, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Para::GetMarginRight() { + return JSObject() + ->GetMeasure(XFA_Attribute::MarginRight) + .ToUnit(XFA_Unit::Pt); } -FX_FLOAT CXFA_Para::GetSpaceAbove() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_SpaceAbove, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Para::GetSpaceAbove() { + return JSObject()->GetMeasure(XFA_Attribute::SpaceAbove).ToUnit(XFA_Unit::Pt); } -FX_FLOAT CXFA_Para::GetSpaceBelow() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_SpaceBelow, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Para::GetSpaceBelow() { + return JSObject()->GetMeasure(XFA_Attribute::SpaceBelow).ToUnit(XFA_Unit::Pt); } -FX_FLOAT CXFA_Para::GetTextIndent() { - CXFA_Measurement ms; - m_pNode->TryMeasure(XFA_ATTRIBUTE_TextIndent, ms); - return ms.ToUnit(XFA_UNIT_Pt); +float CXFA_Para::GetTextIndent() { + return JSObject()->GetMeasure(XFA_Attribute::TextIndent).ToUnit(XFA_Unit::Pt); } diff --git a/xfa/fxfa/parser/cxfa_para.h b/xfa/fxfa/parser/cxfa_para.h index e12d48f9fa3da2c45726801addbe73b94c8b9fdd..afb48ce819a0854b8459ddd734ba09564b1ef9de 100644 --- a/xfa/fxfa/parser/cxfa_para.h +++ b/xfa/fxfa/parser/cxfa_para.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,23 +7,21 @@ #ifndef XFA_FXFA_PARSER_CXFA_PARA_H_ #define XFA_FXFA_PARSER_CXFA_PARA_H_ -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Para : public CXFA_Data { +class CXFA_Para : public CXFA_Node { public: - explicit CXFA_Para(CXFA_Node* pNode); + CXFA_Para(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Para() override; - int32_t GetHorizontalAlign(); - int32_t GetVerticalAlign(); - FX_FLOAT GetLineHeight(); - FX_FLOAT GetMarginLeft(); - FX_FLOAT GetMarginRight(); - FX_FLOAT GetSpaceAbove(); - FX_FLOAT GetSpaceBelow(); - FX_FLOAT GetTextIndent(); + XFA_AttributeEnum GetHorizontalAlign(); + XFA_AttributeEnum GetVerticalAlign(); + float GetLineHeight(); + float GetMarginLeft(); + float GetMarginRight(); + float GetSpaceAbove(); + float GetSpaceBelow(); + float GetTextIndent(); }; #endif // XFA_FXFA_PARSER_CXFA_PARA_H_ diff --git a/xfa/fxfa/parser/cxfa_part.cpp b/xfa/fxfa/parser/cxfa_part.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d645571f9c5f8b9518e7f5e42c9aac9c8345df06 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_part.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_part.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"part"; + +} // namespace + +CXFA_Part::CXFA_Part(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Part, + nullptr, + kAttributeData, + kName) {} + +CXFA_Part::~CXFA_Part() {} diff --git a/xfa/fxfa/parser/cxfa_part.h b/xfa/fxfa/parser/cxfa_part.h new file mode 100644 index 0000000000000000000000000000000000000000..3db76399a7089fce7b75b5c8ef205caacc5be59f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_part.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PART_H_ +#define XFA_FXFA_PARSER_CXFA_PART_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Part : public CXFA_Node { + public: + CXFA_Part(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Part() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PART_H_ diff --git a/xfa/fxfa/parser/cxfa_password.cpp b/xfa/fxfa/parser/cxfa_password.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b3f719e1be36dfe1e9d6b55bff29ef0afa6ab15 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_password.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_password.h" + +#include "fxjs/xfa/cjx_password.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"password"; + +} // namespace + +CXFA_Password::CXFA_Password(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::Password, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Password>(this)) {} + +CXFA_Password::~CXFA_Password() {} diff --git a/xfa/fxfa/parser/cxfa_password.h b/xfa/fxfa/parser/cxfa_password.h new file mode 100644 index 0000000000000000000000000000000000000000..904f91fd3d0710349a7dc828319a7cc24e058cdf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_password.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PASSWORD_H_ +#define XFA_FXFA_PARSER_CXFA_PASSWORD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Password : public CXFA_Node { + public: + CXFA_Password(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Password() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PASSWORD_H_ diff --git a/xfa/fxfa/parser/cxfa_passwordedit.cpp b/xfa/fxfa/parser/cxfa_passwordedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e86cd13ca54c19db334c5b6c95f68951bb45f9cc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_passwordedit.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_passwordedit.h" + +#include "fxjs/xfa/cjx_passwordedit.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::PasswordChar, XFA_AttributeType::CData, (void*)L"*"}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HScrollPolicy, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"passwordEdit"; + +} // namespace + +CXFA_PasswordEdit::CXFA_PasswordEdit(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::PasswordEdit, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_PasswordEdit::~CXFA_PasswordEdit() {} diff --git a/xfa/fxfa/parser/cxfa_passwordedit.h b/xfa/fxfa/parser/cxfa_passwordedit.h new file mode 100644 index 0000000000000000000000000000000000000000..2db05ba7e2a56dc1fa9a4a55a55a35c312408e63 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_passwordedit.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PASSWORDEDIT_H_ +#define XFA_FXFA_PARSER_CXFA_PASSWORDEDIT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PasswordEdit : public CXFA_Node { + public: + CXFA_PasswordEdit(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PasswordEdit() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PASSWORDEDIT_H_ diff --git a/xfa/fxfa/parser/cxfa_pattern.cpp b/xfa/fxfa/parser/cxfa_pattern.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4cd32cced827280a8883ea04a7f1671a11337802 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pattern.cpp @@ -0,0 +1,87 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pattern.h" + +#include "fxjs/xfa/cjx_pattern.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_color.h" +#include "xfa/fxgraphics/cxfa_gepattern.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Color, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::CrossHatch}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pattern"; + +} // namespace + +CXFA_Pattern::CXFA_Pattern(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Pattern, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Pattern>(this)) {} + +CXFA_Pattern::~CXFA_Pattern() {} + +CXFA_Color* CXFA_Pattern::GetColorIfExists() { + return GetChild<CXFA_Color>(0, XFA_Element::Color, false); +} + +XFA_AttributeEnum CXFA_Pattern::GetType() { + return JSObject()->GetEnum(XFA_Attribute::Type); +} + +void CXFA_Pattern::Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + FX_ARGB crStart, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix) { + CXFA_Color* pColor = GetColorIfExists(); + FX_ARGB crEnd = pColor ? pColor->GetValue() : CXFA_Color::kBlackColor; + + FX_HatchStyle iHatch = FX_HatchStyle::Cross; + switch (GetType()) { + case XFA_AttributeEnum::CrossDiagonal: + iHatch = FX_HatchStyle::DiagonalCross; + break; + case XFA_AttributeEnum::DiagonalLeft: + iHatch = FX_HatchStyle::ForwardDiagonal; + break; + case XFA_AttributeEnum::DiagonalRight: + iHatch = FX_HatchStyle::BackwardDiagonal; + break; + case XFA_AttributeEnum::Horizontal: + iHatch = FX_HatchStyle::Horizontal; + break; + case XFA_AttributeEnum::Vertical: + iHatch = FX_HatchStyle::Vertical; + break; + default: + break; + } + + CXFA_GEPattern pattern(iHatch, crEnd, crStart); + + pGS->SaveGraphState(); + pGS->SetFillColor(CXFA_GEColor(&pattern, 0x0)); + pGS->FillPath(fillPath, FXFILL_WINDING, &matrix); + pGS->RestoreGraphState(); +} diff --git a/xfa/fxfa/parser/cxfa_pattern.h b/xfa/fxfa/parser/cxfa_pattern.h new file mode 100644 index 0000000000000000000000000000000000000000..7533ac91a44332cffe9aaba627c4965b534eb811 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pattern.h @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PATTERN_H_ +#define XFA_FXFA_PARSER_CXFA_PATTERN_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_gepath.h" + +class CXFA_Color; +class CXFA_Graphics; + +class CXFA_Pattern : public CXFA_Node { + public: + static constexpr XFA_AttributeEnum kDefaultType = XFA_AttributeEnum::Unknown; + + CXFA_Pattern(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Pattern() override; + + void Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + FX_ARGB crStart, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix); + + private: + XFA_AttributeEnum GetType(); + CXFA_Color* GetColorIfExists(); +}; + +#endif // XFA_FXFA_PARSER_CXFA_PATTERN_H_ diff --git a/xfa/fxfa/parser/cxfa_pcl.cpp b/xfa/fxfa/parser/cxfa_pcl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f5e34842060bc38c578aa5d131f5198718ac72a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pcl.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pcl.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::FontInfo, 1, 0}, {XFA_Element::Jog, 1, 0}, + {XFA_Element::Xdc, 1, 0}, {XFA_Element::BatchOutput, 1, 0}, + {XFA_Element::PageOffset, 1, 0}, {XFA_Element::OutputBin, 1, 0}, + {XFA_Element::Staple, 1, 0}, {XFA_Element::MediumInfo, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pcl"; + +} // namespace + +CXFA_Pcl::CXFA_Pcl(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Pcl, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Pcl::~CXFA_Pcl() {} diff --git a/xfa/fxfa/parser/cxfa_pcl.h b/xfa/fxfa/parser/cxfa_pcl.h new file mode 100644 index 0000000000000000000000000000000000000000..9b782657948de7929d35fe3c49dddb1aa9f0cba2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pcl.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PCL_H_ +#define XFA_FXFA_PARSER_CXFA_PCL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Pcl : public CXFA_Node { + public: + CXFA_Pcl(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Pcl() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PCL_H_ diff --git a/xfa/fxfa/parser/cxfa_pdf.cpp b/xfa/fxfa/parser/cxfa_pdf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..800d39392518f02f61c3fd91e2cc79520cb32428 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pdf.cpp @@ -0,0 +1,52 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pdf.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::AdobeExtensionLevel, 1, 0}, + {XFA_Element::FontInfo, 1, 0}, + {XFA_Element::Xdc, 1, 0}, + {XFA_Element::Pdfa, 1, 0}, + {XFA_Element::BatchOutput, 1, 0}, + {XFA_Element::ViewerPreferences, 1, 0}, + {XFA_Element::ScriptModel, 1, 0}, + {XFA_Element::Version, 1, 0}, + {XFA_Element::SubmitFormat, 1, 0}, + {XFA_Element::SilentPrint, 1, 0}, + {XFA_Element::Producer, 1, 0}, + {XFA_Element::Compression, 1, 0}, + {XFA_Element::Interactive, 1, 0}, + {XFA_Element::Encryption, 1, 0}, + {XFA_Element::RenderPolicy, 1, 0}, + {XFA_Element::OpenAction, 1, 0}, + {XFA_Element::Creator, 1, 0}, + {XFA_Element::Linearized, 1, 0}, + {XFA_Element::Tagged, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pdf"; + +} // namespace + +CXFA_Pdf::CXFA_Pdf(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Pdf, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Pdf::~CXFA_Pdf() {} diff --git a/xfa/fxfa/parser/cxfa_pdf.h b/xfa/fxfa/parser/cxfa_pdf.h new file mode 100644 index 0000000000000000000000000000000000000000..d0925c8a9437d45dd80664100e6ee17f2f46bbcf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pdf.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PDF_H_ +#define XFA_FXFA_PARSER_CXFA_PDF_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Pdf : public CXFA_Node { + public: + CXFA_Pdf(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Pdf() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PDF_H_ diff --git a/xfa/fxfa/parser/cxfa_pdfa.cpp b/xfa/fxfa/parser/cxfa_pdfa.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f41eb93e4bd9ca9b6b31228f0c5e82963daeed09 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pdfa.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_pdfa.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Amd, 1, 0}, + {XFA_Element::Part, 1, 0}, + {XFA_Element::IncludeXDPContent, 1, 0}, + {XFA_Element::Conformance, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pdfa"; + +} // namespace + +CXFA_Pdfa::CXFA_Pdfa(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Pdfa, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Pdfa::~CXFA_Pdfa() {} diff --git a/xfa/fxfa/parser/cxfa_pdfa.h b/xfa/fxfa/parser/cxfa_pdfa.h new file mode 100644 index 0000000000000000000000000000000000000000..d0816a273396849be04c48e0257ccd67794d5ce7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_pdfa.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PDFA_H_ +#define XFA_FXFA_PARSER_CXFA_PDFA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Pdfa : public CXFA_Node { + public: + CXFA_Pdfa(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Pdfa() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PDFA_H_ diff --git a/xfa/fxfa/parser/cxfa_permissions.cpp b/xfa/fxfa/parser/cxfa_permissions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a56ac32cd2c19fbde9bc99b587c19308bbeae925 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_permissions.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_permissions.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::ModifyAnnots, 1, 0}, + {XFA_Element::ContentCopy, 1, 0}, + {XFA_Element::FormFieldFilling, 1, 0}, + {XFA_Element::Change, 1, 0}, + {XFA_Element::AccessibleContent, 1, 0}, + {XFA_Element::Print, 1, 0}, + {XFA_Element::PlaintextMetadata, 1, 0}, + {XFA_Element::PrintHighQuality, 1, 0}, + {XFA_Element::DocumentAssembly, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"permissions"; + +} // namespace + +CXFA_Permissions::CXFA_Permissions(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Permissions, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Permissions::~CXFA_Permissions() {} diff --git a/xfa/fxfa/parser/cxfa_permissions.h b/xfa/fxfa/parser/cxfa_permissions.h new file mode 100644 index 0000000000000000000000000000000000000000..dca9018b175d51fa5d4c35692da926b7969589bf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_permissions.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PERMISSIONS_H_ +#define XFA_FXFA_PARSER_CXFA_PERMISSIONS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Permissions : public CXFA_Node { + public: + CXFA_Permissions(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Permissions() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PERMISSIONS_H_ diff --git a/xfa/fxfa/parser/cxfa_picktraybypdfsize.cpp b/xfa/fxfa/parser/cxfa_picktraybypdfsize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4e5ec2b3c2d249bcce738ea6c81258c85a42d69 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_picktraybypdfsize.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_picktraybypdfsize.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"pickTrayByPDFSize"; + +} // namespace + +CXFA_PickTrayByPDFSize::CXFA_PickTrayByPDFSize(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PickTrayByPDFSize, + nullptr, + kAttributeData, + kName) {} + +CXFA_PickTrayByPDFSize::~CXFA_PickTrayByPDFSize() {} diff --git a/xfa/fxfa/parser/cxfa_picktraybypdfsize.h b/xfa/fxfa/parser/cxfa_picktraybypdfsize.h new file mode 100644 index 0000000000000000000000000000000000000000..ef75e5c8fc341d2f168b0a29f06b384eb6e9a8c4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_picktraybypdfsize.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PICKTRAYBYPDFSIZE_H_ +#define XFA_FXFA_PARSER_CXFA_PICKTRAYBYPDFSIZE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PickTrayByPDFSize : public CXFA_Node { + public: + CXFA_PickTrayByPDFSize(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PickTrayByPDFSize() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PICKTRAYBYPDFSIZE_H_ diff --git a/xfa/fxfa/parser/cxfa_picture.cpp b/xfa/fxfa/parser/cxfa_picture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4863a771893ee22da95b695febbe5f45537eecbe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_picture.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_picture.h" + +#include "fxjs/xfa/cjx_picture.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"picture"; + +} // namespace + +CXFA_Picture::CXFA_Picture(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Picture, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Picture>(this)) {} + +CXFA_Picture::~CXFA_Picture() {} diff --git a/xfa/fxfa/parser/cxfa_picture.h b/xfa/fxfa/parser/cxfa_picture.h new file mode 100644 index 0000000000000000000000000000000000000000..9fd2c558e2771f19d08c737e3a177a07ddce790e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_picture.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PICTURE_H_ +#define XFA_FXFA_PARSER_CXFA_PICTURE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Picture : public CXFA_Node { + public: + CXFA_Picture(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Picture() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PICTURE_H_ diff --git a/xfa/fxfa/parser/cxfa_plaintextmetadata.cpp b/xfa/fxfa/parser/cxfa_plaintextmetadata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5c51dd7e5bd55e9c73a93c03113f4539d7e74ff --- /dev/null +++ b/xfa/fxfa/parser/cxfa_plaintextmetadata.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_plaintextmetadata.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"plaintextMetadata"; + +} // namespace + +CXFA_PlaintextMetadata::CXFA_PlaintextMetadata(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PlaintextMetadata, + nullptr, + kAttributeData, + kName) {} + +CXFA_PlaintextMetadata::~CXFA_PlaintextMetadata() {} diff --git a/xfa/fxfa/parser/cxfa_plaintextmetadata.h b/xfa/fxfa/parser/cxfa_plaintextmetadata.h new file mode 100644 index 0000000000000000000000000000000000000000..03dce65f7948130ac0e13dca35193d11cd7aec9a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_plaintextmetadata.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PLAINTEXTMETADATA_H_ +#define XFA_FXFA_PARSER_CXFA_PLAINTEXTMETADATA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PlaintextMetadata : public CXFA_Node { + public: + CXFA_PlaintextMetadata(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PlaintextMetadata() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PLAINTEXTMETADATA_H_ diff --git a/xfa/fxfa/parser/cxfa_presence.cpp b/xfa/fxfa/parser/cxfa_presence.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2389d91ab05a88748ebe85d4bffb8cab297086b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_presence.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_presence.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"presence"; + +} // namespace + +CXFA_Presence::CXFA_Presence(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Presence, + nullptr, + kAttributeData, + kName) {} + +CXFA_Presence::~CXFA_Presence() {} diff --git a/xfa/fxfa/parser/cxfa_presence.h b/xfa/fxfa/parser/cxfa_presence.h new file mode 100644 index 0000000000000000000000000000000000000000..a9b7766fe114e7ead1160c5827feb2c5d26397e2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_presence.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRESENCE_H_ +#define XFA_FXFA_PARSER_CXFA_PRESENCE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Presence : public CXFA_Node { + public: + CXFA_Presence(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Presence() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRESENCE_H_ diff --git a/xfa/fxfa/parser/cxfa_present.cpp b/xfa/fxfa/parser/cxfa_present.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7552a79c6f69c47ddb24d293db571f9f73637ba9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_present.cpp @@ -0,0 +1,46 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_present.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Xdp, 1, 0}, + {XFA_Element::Cache, 1, 0}, + {XFA_Element::Pagination, 1, 0}, + {XFA_Element::Overprint, 1, 0}, + {XFA_Element::BehaviorOverride, 1, 0}, + {XFA_Element::Copies, 1, 0}, + {XFA_Element::Output, 1, 0}, + {XFA_Element::Validate, 1, 0}, + {XFA_Element::Layout, 1, 0}, + {XFA_Element::Script, 1, 0}, + {XFA_Element::Common, 1, 0}, + {XFA_Element::PaginationOverride, 1, 0}, + {XFA_Element::Destination, 1, 0}, + {XFA_Element::IncrementalMerge, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"present"; + +} // namespace + +CXFA_Present::CXFA_Present(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Present, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Present::~CXFA_Present() {} diff --git a/xfa/fxfa/parser/cxfa_present.h b/xfa/fxfa/parser/cxfa_present.h new file mode 100644 index 0000000000000000000000000000000000000000..13b3c61664ccf07b4caee166c9e79a410766de9e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_present.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRESENT_H_ +#define XFA_FXFA_PARSER_CXFA_PRESENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Present : public CXFA_Node { + public: + CXFA_Present(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Present() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRESENT_H_ diff --git a/xfa/fxfa/parser/cxfa_print.cpp b/xfa/fxfa/parser/cxfa_print.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f90186de266320c5ce457b702af83cdfe0b717b7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_print.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_print.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"print"; + +} // namespace + +CXFA_Print::CXFA_Print(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Print, + nullptr, + kAttributeData, + kName) {} + +CXFA_Print::~CXFA_Print() {} diff --git a/xfa/fxfa/parser/cxfa_print.h b/xfa/fxfa/parser/cxfa_print.h new file mode 100644 index 0000000000000000000000000000000000000000..5f2513e10dee477e093bfaa77bc1c80de2710bd0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_print.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRINT_H_ +#define XFA_FXFA_PARSER_CXFA_PRINT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Print : public CXFA_Node { + public: + CXFA_Print(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Print() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRINT_H_ diff --git a/xfa/fxfa/parser/cxfa_printername.cpp b/xfa/fxfa/parser/cxfa_printername.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5e6197a10f5870ac43d5178f7cbbb63c94de74b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_printername.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_printername.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"printerName"; + +} // namespace + +CXFA_PrinterName::CXFA_PrinterName(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PrinterName, + nullptr, + kAttributeData, + kName) {} + +CXFA_PrinterName::~CXFA_PrinterName() {} diff --git a/xfa/fxfa/parser/cxfa_printername.h b/xfa/fxfa/parser/cxfa_printername.h new file mode 100644 index 0000000000000000000000000000000000000000..4f07885ccfd08ecf36b69433111fe4585aac300d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_printername.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRINTERNAME_H_ +#define XFA_FXFA_PARSER_CXFA_PRINTERNAME_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PrinterName : public CXFA_Node { + public: + CXFA_PrinterName(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PrinterName() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRINTERNAME_H_ diff --git a/xfa/fxfa/parser/cxfa_printhighquality.cpp b/xfa/fxfa/parser/cxfa_printhighquality.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b1184f28858a456fa0a366d67a407ae43d727c4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_printhighquality.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_printhighquality.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"printHighQuality"; + +} // namespace + +CXFA_PrintHighQuality::CXFA_PrintHighQuality(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PrintHighQuality, + nullptr, + kAttributeData, + kName) {} + +CXFA_PrintHighQuality::~CXFA_PrintHighQuality() {} diff --git a/xfa/fxfa/parser/cxfa_printhighquality.h b/xfa/fxfa/parser/cxfa_printhighquality.h new file mode 100644 index 0000000000000000000000000000000000000000..6cd61125bdd9c6a8be746b77bcd824baa94e7a82 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_printhighquality.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRINTHIGHQUALITY_H_ +#define XFA_FXFA_PARSER_CXFA_PRINTHIGHQUALITY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PrintHighQuality : public CXFA_Node { + public: + CXFA_PrintHighQuality(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PrintHighQuality() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRINTHIGHQUALITY_H_ diff --git a/xfa/fxfa/parser/cxfa_printscaling.cpp b/xfa/fxfa/parser/cxfa_printscaling.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d68f688d46cff0bd44ac7be735e61284c2c38bd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_printscaling.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_printscaling.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"printScaling"; + +} // namespace + +CXFA_PrintScaling::CXFA_PrintScaling(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::PrintScaling, + nullptr, + kAttributeData, + kName) {} + +CXFA_PrintScaling::~CXFA_PrintScaling() {} diff --git a/xfa/fxfa/parser/cxfa_printscaling.h b/xfa/fxfa/parser/cxfa_printscaling.h new file mode 100644 index 0000000000000000000000000000000000000000..e21d427e2a727ed3d78fd6ef0cc3d95ffc855185 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_printscaling.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRINTSCALING_H_ +#define XFA_FXFA_PARSER_CXFA_PRINTSCALING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PrintScaling : public CXFA_Node { + public: + CXFA_PrintScaling(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PrintScaling() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRINTSCALING_H_ diff --git a/xfa/fxfa/parser/cxfa_producer.cpp b/xfa/fxfa/parser/cxfa_producer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45253c736864a65aa72d7073089e81dcde8f61d7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_producer.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_producer.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"producer"; + +} // namespace + +CXFA_Producer::CXFA_Producer(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Producer, + nullptr, + kAttributeData, + kName) {} + +CXFA_Producer::~CXFA_Producer() {} diff --git a/xfa/fxfa/parser/cxfa_producer.h b/xfa/fxfa/parser/cxfa_producer.h new file mode 100644 index 0000000000000000000000000000000000000000..584826e752a3c8989c6772cfc5e46d2839f8d4e9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_producer.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PRODUCER_H_ +#define XFA_FXFA_PARSER_CXFA_PRODUCER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Producer : public CXFA_Node { + public: + CXFA_Producer(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Producer() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PRODUCER_H_ diff --git a/xfa/fxfa/parser/cxfa_proto.cpp b/xfa/fxfa/parser/cxfa_proto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d103e745e70324dc2af76ebfa24c8b1baf02d8e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_proto.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_proto.h" + +namespace { + +constexpr wchar_t kName[] = L"proto"; + +} // namespace + +CXFA_Proto::CXFA_Proto(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Proto, + nullptr, + nullptr, + kName) {} + +CXFA_Proto::~CXFA_Proto() {} diff --git a/xfa/fxfa/parser/cxfa_proto.h b/xfa/fxfa/parser/cxfa_proto.h new file mode 100644 index 0000000000000000000000000000000000000000..8e1d84a54e79ca3c0348dc2798bc67fdb583e02e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_proto.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PROTO_H_ +#define XFA_FXFA_PARSER_CXFA_PROTO_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Proto : public CXFA_Node { + public: + CXFA_Proto(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Proto() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PROTO_H_ diff --git a/xfa/fxfa/parser/cxfa_ps.cpp b/xfa/fxfa/parser/cxfa_ps.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b2f532651a79e1d9456db1414b196b59a0d8dea --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ps.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_ps.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::FontInfo, 1, 0}, {XFA_Element::Jog, 1, 0}, + {XFA_Element::Xdc, 1, 0}, {XFA_Element::BatchOutput, 1, 0}, + {XFA_Element::OutputBin, 1, 0}, {XFA_Element::Compress, 1, 0}, + {XFA_Element::Staple, 1, 0}, {XFA_Element::MediumInfo, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"ps"; + +} // namespace + +CXFA_Ps::CXFA_Ps(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Ps, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Ps::~CXFA_Ps() {} diff --git a/xfa/fxfa/parser/cxfa_ps.h b/xfa/fxfa/parser/cxfa_ps.h new file mode 100644 index 0000000000000000000000000000000000000000..5ef7e82c5c06af9e69706e26560089ac119f1ce0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ps.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PS_H_ +#define XFA_FXFA_PARSER_CXFA_PS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Ps : public CXFA_Node { + public: + CXFA_Ps(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Ps() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PS_H_ diff --git a/xfa/fxfa/parser/cxfa_psmap.cpp b/xfa/fxfa/parser/cxfa_psmap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c0b1224b1c0d429ce931aee6773b62fc4f78696 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_psmap.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_psmap.h" + +namespace { + +constexpr wchar_t kName[] = L"psMap"; + +} // namespace + +CXFA_PsMap::CXFA_PsMap(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::PsMap, + nullptr, + nullptr, + kName) {} + +CXFA_PsMap::~CXFA_PsMap() {} diff --git a/xfa/fxfa/parser/cxfa_psmap.h b/xfa/fxfa/parser/cxfa_psmap.h new file mode 100644 index 0000000000000000000000000000000000000000..8297aaa917741ed2cb7601dbea68e79de611df46 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_psmap.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_PSMAP_H_ +#define XFA_FXFA_PARSER_CXFA_PSMAP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_PsMap : public CXFA_Node { + public: + CXFA_PsMap(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_PsMap() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_PSMAP_H_ diff --git a/xfa/fxfa/parser/cxfa_query.cpp b/xfa/fxfa/parser/cxfa_query.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e1856584b11427c0a34b55440ee7032243f4eec --- /dev/null +++ b/xfa/fxfa/parser/cxfa_query.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_query.h" + +#include "fxjs/xfa/cjx_query.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::RecordSet, 1, 0}, + {XFA_Element::Select, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CommandType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Unknown}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"query"; + +} // namespace + +CXFA_Query::CXFA_Query(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::Node, + XFA_Element::Query, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Query>(this)) {} + +CXFA_Query::~CXFA_Query() {} diff --git a/xfa/fxfa/parser/cxfa_query.h b/xfa/fxfa/parser/cxfa_query.h new file mode 100644 index 0000000000000000000000000000000000000000..548e7fc0325d69662b40a63839d54b3f43094bf7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_query.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_QUERY_H_ +#define XFA_FXFA_PARSER_CXFA_QUERY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Query : public CXFA_Node { + public: + CXFA_Query(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Query() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_QUERY_H_ diff --git a/xfa/fxfa/parser/cxfa_radial.cpp b/xfa/fxfa/parser/cxfa_radial.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d024e744deb035696e2da0717f70b8ba348801c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_radial.cpp @@ -0,0 +1,76 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_radial.h" + +#include <utility> + +#include "fxjs/xfa/cjx_radial.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_color.h" +#include "xfa/fxgraphics/cxfa_geshading.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Color, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ToEdge}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"radial"; + +} // namespace + +CXFA_Radial::CXFA_Radial(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Radial, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Radial>(this)) {} + +CXFA_Radial::~CXFA_Radial() {} + +bool CXFA_Radial::IsToEdge() { + return JSObject() + ->TryEnum(XFA_Attribute::Type, true) + .value_or(XFA_AttributeEnum::ToEdge) == XFA_AttributeEnum::ToEdge; +} + +CXFA_Color* CXFA_Radial::GetColorIfExists() { + return GetChild<CXFA_Color>(0, XFA_Element::Color, false); +} + +void CXFA_Radial::Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + FX_ARGB crStart, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix) { + CXFA_Color* pColor = GetColorIfExists(); + FX_ARGB crEnd = pColor ? pColor->GetValue() : CXFA_Color::kBlackColor; + if (!IsToEdge()) + std::swap(crStart, crEnd); + + float endRadius = sqrt(rtFill.Width() * rtFill.Width() + + rtFill.Height() * rtFill.Height()) / + 2; + CXFA_GEShading shading(rtFill.Center(), rtFill.Center(), 0, endRadius, true, + true, crStart, crEnd); + + pGS->SaveGraphState(); + pGS->SetFillColor(CXFA_GEColor(&shading)); + pGS->FillPath(fillPath, FXFILL_WINDING, &matrix); + pGS->RestoreGraphState(); +} diff --git a/xfa/fxfa/parser/cxfa_radial.h b/xfa/fxfa/parser/cxfa_radial.h new file mode 100644 index 0000000000000000000000000000000000000000..b7ce95c695231f8f16fd1f0f1a8d5622ad0e4cb6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_radial.h @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RADIAL_H_ +#define XFA_FXFA_PARSER_CXFA_RADIAL_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_gepath.h" + +class CXFA_Color; +class CXFA_Graphics; + +class CXFA_Radial : public CXFA_Node { + public: + CXFA_Radial(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Radial() override; + + void Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + FX_ARGB crStart, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix); + + private: + bool IsToEdge(); + CXFA_Color* GetColorIfExists(); +}; + +#endif // XFA_FXFA_PARSER_CXFA_RADIAL_H_ diff --git a/xfa/fxfa/parser/cxfa_range.cpp b/xfa/fxfa/parser/cxfa_range.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd5f87023cc5fd49ecc85939c52f7e7495fd9278 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_range.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_range.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"range"; + +} // namespace + +CXFA_Range::CXFA_Range(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Range, + nullptr, + kAttributeData, + kName) {} + +CXFA_Range::~CXFA_Range() {} diff --git a/xfa/fxfa/parser/cxfa_range.h b/xfa/fxfa/parser/cxfa_range.h new file mode 100644 index 0000000000000000000000000000000000000000..23c8d1fc273627d422c71e4b55e4b4019d1e8c8f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_range.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RANGE_H_ +#define XFA_FXFA_PARSER_CXFA_RANGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Range : public CXFA_Node { + public: + CXFA_Range(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Range() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RANGE_H_ diff --git a/xfa/fxfa/parser/cxfa_reason.cpp b/xfa/fxfa/parser/cxfa_reason.cpp new file mode 100644 index 0000000000000000000000000000000000000000..625ede9a64d262467d1a952fe2d6d92819accdd6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_reason.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_reason.h" + +#include "fxjs/xfa/cjx_reason.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"reason"; + +} // namespace + +CXFA_Reason::CXFA_Reason(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::Reason, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Reason>(this)) {} + +CXFA_Reason::~CXFA_Reason() {} diff --git a/xfa/fxfa/parser/cxfa_reason.h b/xfa/fxfa/parser/cxfa_reason.h new file mode 100644 index 0000000000000000000000000000000000000000..451fd820da73b9f84ce4efc667d090eea482e0d9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_reason.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_REASON_H_ +#define XFA_FXFA_PARSER_CXFA_REASON_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Reason : public CXFA_Node { + public: + CXFA_Reason(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Reason() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_REASON_H_ diff --git a/xfa/fxfa/parser/cxfa_reasons.cpp b/xfa/fxfa/parser/cxfa_reasons.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd3d7618b24f684bef0a322b8de0f618938d99ff --- /dev/null +++ b/xfa/fxfa/parser/cxfa_reasons.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_reasons.h" + +#include "fxjs/xfa/cjx_reasons.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"reasons"; + +} // namespace + +CXFA_Reasons::CXFA_Reasons(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Reasons, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Reasons>(this)) {} + +CXFA_Reasons::~CXFA_Reasons() {} diff --git a/xfa/fxfa/parser/cxfa_reasons.h b/xfa/fxfa/parser/cxfa_reasons.h new file mode 100644 index 0000000000000000000000000000000000000000..57e9e092c8e3889f9ae61a96d18453ebf5242967 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_reasons.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_REASONS_H_ +#define XFA_FXFA_PARSER_CXFA_REASONS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Reasons : public CXFA_Node { + public: + CXFA_Reasons(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Reasons() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_REASONS_H_ diff --git a/xfa/fxfa/parser/cxfa_record.cpp b/xfa/fxfa/parser/cxfa_record.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c5ded1f01be5118e999da053531ee73b7e051f6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_record.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_record.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"record"; + +} // namespace + +CXFA_Record::CXFA_Record(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Record, + nullptr, + kAttributeData, + kName) {} + +CXFA_Record::~CXFA_Record() {} diff --git a/xfa/fxfa/parser/cxfa_record.h b/xfa/fxfa/parser/cxfa_record.h new file mode 100644 index 0000000000000000000000000000000000000000..bd2622da7a2acd77c74d092fcfa0eb9b265aad1e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_record.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RECORD_H_ +#define XFA_FXFA_PARSER_CXFA_RECORD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Record : public CXFA_Node { + public: + CXFA_Record(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Record() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RECORD_H_ diff --git a/xfa/fxfa/parser/cxfa_recordset.cpp b/xfa/fxfa/parser/cxfa_recordset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a90c5895819f96fb0a110262952eae98715cd56f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_recordset.cpp @@ -0,0 +1,47 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_recordset.h" + +#include "fxjs/xfa/cjx_recordset.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Max, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::EofAction, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::MoveLast}, + {XFA_Attribute::CursorType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ForwardOnly}, + {XFA_Attribute::LockType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ReadOnly}, + {XFA_Attribute::BofAction, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::MoveFirst}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::CursorLocation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Client}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"recordSet"; + +} // namespace + +CXFA_RecordSet::CXFA_RecordSet(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::Node, + XFA_Element::RecordSet, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_RecordSet>(this)) {} + +CXFA_RecordSet::~CXFA_RecordSet() {} diff --git a/xfa/fxfa/parser/cxfa_recordset.h b/xfa/fxfa/parser/cxfa_recordset.h new file mode 100644 index 0000000000000000000000000000000000000000..c623516403170dfba045891ad20fc63c28d57d9d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_recordset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RECORDSET_H_ +#define XFA_FXFA_PARSER_CXFA_RECORDSET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_RecordSet : public CXFA_Node { + public: + CXFA_RecordSet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_RecordSet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RECORDSET_H_ diff --git a/xfa/fxfa/parser/cxfa_rectangle.cpp b/xfa/fxfa/parser/cxfa_rectangle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac98df0bb7b1ba30f57bbf57acbddf22da716ba4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_rectangle.cpp @@ -0,0 +1,610 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_rectangle.h" + +#include <utility> + +#include "fxjs/xfa/cjx_rectangle.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_corner.h" +#include "xfa/fxfa/parser/cxfa_stroke.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Edge, 4, 0}, + {XFA_Element::Corner, 4, 0}, + {XFA_Element::Fill, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Hand, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Even}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"rectangle"; + +} // namespace + +CXFA_Rectangle::CXFA_Rectangle(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Box(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Rectangle, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Rectangle>(this)) {} + +CXFA_Rectangle::CXFA_Rectangle(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node) + : CXFA_Box(pDoc, + ePacket, + validPackets, + oType, + eType, + properties, + attributes, + elementName, + std::move(js_node)) {} + +CXFA_Rectangle::~CXFA_Rectangle() {} + +void CXFA_Rectangle::GetFillPath(const std::vector<CXFA_Stroke*>& strokes, + const CFX_RectF& rtWidget, + CXFA_GEPath* fillPath) { + bool bSameStyles = true; + CXFA_Stroke* stroke1 = strokes[0]; + for (int32_t i = 1; i < 8; i++) { + CXFA_Stroke* stroke2 = strokes[i]; + if (!stroke1->SameStyles(stroke2, 0)) { + bSameStyles = false; + break; + } + stroke1 = stroke2; + } + + if (bSameStyles) { + stroke1 = strokes[0]; + for (int32_t i = 2; i < 8; i += 2) { + CXFA_Stroke* stroke2 = strokes[i]; + if (!stroke1->SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | + XFA_STROKE_SAMESTYLE_Corner)) { + bSameStyles = false; + break; + } + stroke1 = stroke2; + } + if (bSameStyles) { + stroke1 = strokes[0]; + if (stroke1->IsInverted()) + bSameStyles = false; + if (stroke1->GetJoinType() != XFA_AttributeEnum::Square) + bSameStyles = false; + } + } + if (bSameStyles) { + fillPath->AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width, + rtWidget.height); + return; + } + + for (int32_t i = 0; i < 8; i += 2) { + float sx = 0.0f; + float sy = 0.0f; + float vx = 1.0f; + float vy = 1.0f; + float nx = 1.0f; + float ny = 1.0f; + CFX_PointF cp1, cp2; + auto* corner1 = static_cast<CXFA_Corner*>(strokes[i]); + auto* corner2 = static_cast<CXFA_Corner*>(strokes[(i + 2) % 8]); + float fRadius1 = corner1->GetRadius(); + float fRadius2 = corner2->GetRadius(); + bool bInverted = corner1->IsInverted(); + bool bRound = corner1->GetJoinType() == XFA_AttributeEnum::Round; + if (bRound) { + sy = FX_PI / 2; + } + switch (i) { + case 0: + cp1 = rtWidget.TopLeft(); + cp2 = rtWidget.TopRight(); + vx = 1, vy = 1; + nx = -1, ny = 0; + if (bRound) { + sx = bInverted ? FX_PI / 2 : FX_PI; + } else { + sx = 1, sy = 0; + } + break; + case 2: + cp1 = rtWidget.TopRight(); + cp2 = rtWidget.BottomRight(); + vx = -1, vy = 1; + nx = 0, ny = -1; + if (bRound) { + sx = bInverted ? FX_PI : FX_PI * 3 / 2; + } else { + sx = 0, sy = 1; + } + break; + case 4: + cp1 = rtWidget.BottomRight(); + cp2 = rtWidget.BottomLeft(); + vx = -1, vy = -1; + nx = 1, ny = 0; + if (bRound) { + sx = bInverted ? FX_PI * 3 / 2 : 0; + } else { + sx = -1, sy = 0; + } + break; + case 6: + cp1 = rtWidget.BottomLeft(); + cp2 = rtWidget.TopLeft(); + vx = 1, vy = -1; + nx = 0, ny = 1; + if (bRound) { + sx = bInverted ? 0 : FX_PI / 2; + } else { + sx = 0; + sy = -1; + } + break; + } + if (i == 0) + fillPath->MoveTo(CFX_PointF(cp1.x, cp1.y + fRadius1)); + + if (bRound) { + if (fRadius1 < 0) + sx -= FX_PI; + if (bInverted) + sy *= -1; + + CFX_RectF rtRadius(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy); + rtRadius.Normalize(); + if (bInverted) + rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); + + fillPath->ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy); + } else { + CFX_PointF cp; + if (bInverted) { + cp.x = cp1.x + fRadius1 * vx; + cp.y = cp1.y + fRadius1 * vy; + } else { + cp = cp1; + } + fillPath->LineTo(cp); + fillPath->LineTo( + CFX_PointF(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy)); + } + fillPath->LineTo(CFX_PointF(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny)); + } +} + +void CXFA_Rectangle::Draw(const std::vector<CXFA_Stroke*>& strokes, + CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix) { + bool bVisible = false; + for (int32_t j = 0; j < 4; j++) { + if (strokes[j * 2 + 1]->IsVisible()) { + bVisible = true; + break; + } + } + if (!bVisible) + return; + + for (int32_t i = 1; i < 8; i += 2) { + float fThickness = std::fmax(0.0, strokes[i]->GetThickness()); + float fHalf = fThickness / 2; + XFA_AttributeEnum iHand = GetHand(); + switch (i) { + case 1: + if (iHand == XFA_AttributeEnum::Left) { + rtWidget.top -= fHalf; + rtWidget.height += fHalf; + } else if (iHand == XFA_AttributeEnum::Right) { + rtWidget.top += fHalf; + rtWidget.height -= fHalf; + } + break; + case 3: + if (iHand == XFA_AttributeEnum::Left) { + rtWidget.width += fHalf; + } else if (iHand == XFA_AttributeEnum::Right) { + rtWidget.width -= fHalf; + } + break; + case 5: + if (iHand == XFA_AttributeEnum::Left) { + rtWidget.height += fHalf; + } else if (iHand == XFA_AttributeEnum::Right) { + rtWidget.height -= fHalf; + } + break; + case 7: + if (iHand == XFA_AttributeEnum::Left) { + rtWidget.left -= fHalf; + rtWidget.width += fHalf; + } else if (iHand == XFA_AttributeEnum::Right) { + rtWidget.left += fHalf; + rtWidget.width -= fHalf; + } + break; + } + } + Stroke(strokes, pGS, rtWidget, matrix); +} + +void CXFA_Rectangle::Stroke(const std::vector<CXFA_Stroke*>& strokes, + CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix) { + bool bVisible; + float fThickness; + XFA_AttributeEnum i3DType; + std::tie(i3DType, bVisible, fThickness) = Get3DStyle(); + if (i3DType != XFA_AttributeEnum::Unknown) { + if (!bVisible || fThickness < 0.001f) + return; + + switch (i3DType) { + case XFA_AttributeEnum::Lowered: + StrokeLowered(pGS, rtWidget, fThickness, matrix); + break; + case XFA_AttributeEnum::Raised: + StrokeRaised(pGS, rtWidget, fThickness, matrix); + break; + case XFA_AttributeEnum::Etched: + StrokeEtched(pGS, rtWidget, fThickness, matrix); + break; + case XFA_AttributeEnum::Embossed: + StrokeEmbossed(pGS, rtWidget, fThickness, matrix); + break; + default: + NOTREACHED(); + break; + } + return; + } + + bool bClose = false; + bool bSameStyles = true; + CXFA_Stroke* stroke1 = strokes[0]; + for (int32_t i = 1; i < 8; i++) { + CXFA_Stroke* stroke2 = strokes[i]; + if (!stroke1->SameStyles(stroke2, 0)) { + bSameStyles = false; + break; + } + stroke1 = stroke2; + } + if (bSameStyles) { + stroke1 = strokes[0]; + bClose = true; + for (int32_t i = 2; i < 8; i += 2) { + CXFA_Stroke* stroke2 = strokes[i]; + if (!stroke1->SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | + XFA_STROKE_SAMESTYLE_Corner)) { + bSameStyles = false; + break; + } + stroke1 = stroke2; + } + if (bSameStyles) { + stroke1 = strokes[0]; + if (stroke1->IsInverted()) + bSameStyles = false; + if (stroke1->GetJoinType() != XFA_AttributeEnum::Square) + bSameStyles = false; + } + } + + bool bStart = true; + CXFA_GEPath path; + for (int32_t i = 0; i < 8; i++) { + CXFA_Stroke* stroke = strokes[i]; + if ((i % 1) == 0 && stroke->GetRadius() < 0) { + bool bEmpty = path.IsEmpty(); + if (!bEmpty) { + if (stroke) + stroke->Stroke(&path, pGS, matrix); + path.Clear(); + } + bStart = true; + continue; + } + GetPath(strokes, rtWidget, path, i, bStart, !bSameStyles); + + bStart = !stroke->SameStyles(strokes[(i + 1) % 8], 0); + if (bStart) { + if (stroke) + stroke->Stroke(&path, pGS, matrix); + path.Clear(); + } + } + bool bEmpty = path.IsEmpty(); + if (!bEmpty) { + if (bClose) { + path.Close(); + } + if (strokes[7]) + strokes[7]->Stroke(&path, pGS, matrix); + } +} + +void CXFA_Rectangle::StrokeRect(CXFA_Graphics* pGraphic, + const CFX_RectF& rt, + float fLineWidth, + const CFX_Matrix& matrix, + FX_ARGB argbTopLeft, + FX_ARGB argbBottomRight) { + float fBottom = rt.bottom(); + float fRight = rt.right(); + CXFA_GEPath pathLT; + pathLT.MoveTo(CFX_PointF(rt.left, fBottom)); + pathLT.LineTo(CFX_PointF(rt.left, rt.top)); + pathLT.LineTo(CFX_PointF(fRight, rt.top)); + pathLT.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth)); + pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, rt.top + fLineWidth)); + pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth)); + pathLT.LineTo(CFX_PointF(rt.left, fBottom)); + pGraphic->SetFillColor(CXFA_GEColor(argbTopLeft)); + pGraphic->FillPath(&pathLT, FXFILL_WINDING, &matrix); + + CXFA_GEPath pathRB; + pathRB.MoveTo(CFX_PointF(fRight, rt.top)); + pathRB.LineTo(CFX_PointF(fRight, fBottom)); + pathRB.LineTo(CFX_PointF(rt.left, fBottom)); + pathRB.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth)); + pathRB.LineTo(CFX_PointF(fRight - fLineWidth, fBottom - fLineWidth)); + pathRB.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth)); + pathRB.LineTo(CFX_PointF(fRight, rt.top)); + pGraphic->SetFillColor(CXFA_GEColor(argbBottomRight)); + pGraphic->FillPath(&pathRB, FXFILL_WINDING, &matrix); +} + +void CXFA_Rectangle::StrokeLowered(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix) { + float fHalfWidth = fThickness / 2.0f; + CFX_RectF rtInner(rt); + rtInner.Deflate(fHalfWidth, fHalfWidth); + + CXFA_GEPath path; + path.AddRectangle(rt.left, rt.top, rt.width, rt.height); + path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); + pGS->SetFillColor(CXFA_GEColor(0xFF000000)); + pGS->FillPath(&path, FXFILL_ALTERNATE, &matrix); + + StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFF808080, 0xFFC0C0C0); +} + +void CXFA_Rectangle::StrokeRaised(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix) { + float fHalfWidth = fThickness / 2.0f; + CFX_RectF rtInner(rt); + rtInner.Deflate(fHalfWidth, fHalfWidth); + + CXFA_GEPath path; + path.AddRectangle(rt.left, rt.top, rt.width, rt.height); + path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); + pGS->SetFillColor(CXFA_GEColor(0xFF000000)); + pGS->FillPath(&path, FXFILL_ALTERNATE, &matrix); + + StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFFFFFFFF, 0xFF808080); +} + +void CXFA_Rectangle::StrokeEtched(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix) { + float fHalfWidth = fThickness / 2.0f; + StrokeRect(pGS, rt, fThickness, matrix, 0xFF808080, 0xFFFFFFFF); + + CFX_RectF rtInner(rt); + rtInner.Deflate(fHalfWidth, fHalfWidth); + StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFFFFFFFF, 0xFF808080); +} + +void CXFA_Rectangle::StrokeEmbossed(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix) { + float fHalfWidth = fThickness / 2.0f; + StrokeRect(pGS, rt, fThickness, matrix, 0xFF808080, 0xFF000000); + + CFX_RectF rtInner(rt); + rtInner.Deflate(fHalfWidth, fHalfWidth); + StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFF000000, 0xFF808080); +} + +void CXFA_Rectangle::GetPath(const std::vector<CXFA_Stroke*>& strokes, + CFX_RectF rtWidget, + CXFA_GEPath& path, + int32_t nIndex, + bool bStart, + bool bCorner) { + ASSERT(nIndex >= 0 && nIndex < 8); + + int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex; + auto* corner1 = static_cast<CXFA_Corner*>(strokes[n]); + auto* corner2 = static_cast<CXFA_Corner*>(strokes[(n + 2) % 8]); + float fRadius1 = bCorner ? corner1->GetRadius() : 0.0f; + float fRadius2 = bCorner ? corner2->GetRadius() : 0.0f; + bool bInverted = corner1->IsInverted(); + float offsetY = 0.0f; + float offsetX = 0.0f; + bool bRound = corner1->GetJoinType() == XFA_AttributeEnum::Round; + float halfAfter = 0.0f; + float halfBefore = 0.0f; + + CXFA_Stroke* stroke = strokes[nIndex]; + if (stroke->IsCorner()) { + CXFA_Stroke* strokeBefore = strokes[(nIndex + 1 * 8 - 1) % 8]; + CXFA_Stroke* strokeAfter = strokes[nIndex + 1]; + if (stroke->IsInverted()) { + if (!stroke->SameStyles(strokeBefore, 0)) + halfBefore = strokeBefore->GetThickness() / 2; + if (!stroke->SameStyles(strokeAfter, 0)) + halfAfter = strokeAfter->GetThickness() / 2; + } + } else { + CXFA_Stroke* strokeBefore = strokes[(nIndex + 8 - 2) % 8]; + CXFA_Stroke* strokeAfter = strokes[(nIndex + 2) % 8]; + if (!bRound && !bInverted) { + halfBefore = strokeBefore->GetThickness() / 2; + halfAfter = strokeAfter->GetThickness() / 2; + } + } + + float offsetEX = 0.0f; + float offsetEY = 0.0f; + float sx = 0.0f; + float sy = 0.0f; + float vx = 1.0f; + float vy = 1.0f; + float nx = 1.0f; + float ny = 1.0f; + CFX_PointF cpStart; + CFX_PointF cp1; + CFX_PointF cp2; + if (bRound) + sy = FX_PI / 2; + + switch (nIndex) { + case 0: + case 1: + cp1 = rtWidget.TopLeft(); + cp2 = rtWidget.TopRight(); + if (nIndex == 0) { + cpStart.x = cp1.x - halfBefore; + cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter; + } else { + cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y, + offsetEX = halfAfter; + } + vx = 1, vy = 1; + nx = -1, ny = 0; + if (bRound) { + sx = bInverted ? FX_PI / 2 : FX_PI; + } else { + sx = 1, sy = 0; + } + break; + case 2: + case 3: + cp1 = rtWidget.TopRight(); + cp2 = rtWidget.BottomRight(); + if (nIndex == 2) { + cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore, + offsetX = halfAfter; + } else { + cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore, + offsetEY = halfAfter; + } + vx = -1, vy = 1; + nx = 0, ny = -1; + if (bRound) { + sx = bInverted ? FX_PI : FX_PI * 3 / 2; + } else { + sx = 0, sy = 1; + } + break; + case 4: + case 5: + cp1 = rtWidget.BottomRight(); + cp2 = rtWidget.BottomLeft(); + if (nIndex == 4) { + cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1, + offsetY = halfAfter; + } else { + cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y, + offsetEX = -halfAfter; + } + vx = -1, vy = -1; + nx = 1, ny = 0; + if (bRound) { + sx = bInverted ? FX_PI * 3 / 2 : 0; + } else { + sx = -1, sy = 0; + } + break; + case 6: + case 7: + cp1 = rtWidget.BottomLeft(); + cp2 = rtWidget.TopLeft(); + if (nIndex == 6) { + cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore, + offsetX = -halfAfter; + } else { + cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore, + offsetEY = -halfAfter; + } + vx = 1; + vy = -1; + nx = 0; + ny = 1; + if (bRound) { + sx = bInverted ? 0 : FX_PI / 2; + } else { + sx = 0; + sy = -1; + } + break; + } + if (bStart) { + path.MoveTo(cpStart); + } + if (nIndex & 1) { + path.LineTo(CFX_PointF(cp2.x + fRadius2 * nx + offsetEX, + cp2.y + fRadius2 * ny + offsetEY)); + return; + } + if (bRound) { + if (fRadius1 < 0) + sx -= FX_PI; + if (bInverted) + sy *= -1; + + CFX_RectF rtRadius(cp1.x + offsetX * 2, cp1.y + offsetY * 2, + fRadius1 * 2 * vx - offsetX * 2, + fRadius1 * 2 * vy - offsetY * 2); + rtRadius.Normalize(); + if (bInverted) + rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); + + path.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy); + } else { + CFX_PointF cp; + if (bInverted) { + cp.x = cp1.x + fRadius1 * vx; + cp.y = cp1.y + fRadius1 * vy; + } else { + cp = cp1; + } + path.LineTo(cp); + path.LineTo(CFX_PointF(cp1.x + fRadius1 * sx + offsetX, + cp1.y + fRadius1 * sy + offsetY)); + } +} diff --git a/xfa/fxfa/parser/cxfa_rectangle.h b/xfa/fxfa/parser/cxfa_rectangle.h index 8d18ace0de3d61c71394d2e608ad5aad79886b6c..b117e66d674afb1fa249731eed24c1f04e7fdaca 100644 --- a/xfa/fxfa/parser/cxfa_rectangle.h +++ b/xfa/fxfa/parser/cxfa_rectangle.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,13 +7,69 @@ #ifndef XFA_FXFA_PARSER_CXFA_RECTANGLE_H_ #define XFA_FXFA_PARSER_CXFA_RECTANGLE_H_ -#include "xfa/fxfa/parser/cxfa_box.h" +#include <memory> +#include <vector> -class CXFA_Node; +#include "xfa/fxfa/parser/cxfa_box.h" +#include "xfa/fxgraphics/cxfa_gepath.h" class CXFA_Rectangle : public CXFA_Box { public: - explicit CXFA_Rectangle(CXFA_Node* pNode) : CXFA_Box(pNode) {} + CXFA_Rectangle(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Rectangle() override; + + void GetFillPath(const std::vector<CXFA_Stroke*>& strokes, + const CFX_RectF& rtWidget, + CXFA_GEPath* fillPath); + void Draw(const std::vector<CXFA_Stroke*>& strokes, + CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix); + + protected: + CXFA_Rectangle(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node); + + private: + void Stroke(const std::vector<CXFA_Stroke*>& strokes, + CXFA_Graphics* pGS, + CFX_RectF rtWidget, + const CFX_Matrix& matrix); + void StrokeEmbossed(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix); + void StrokeLowered(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix); + void StrokeRaised(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix); + void StrokeEtched(CXFA_Graphics* pGS, + CFX_RectF rt, + float fThickness, + const CFX_Matrix& matrix); + void StrokeRect(CXFA_Graphics* pGraphic, + const CFX_RectF& rt, + float fLineWidth, + const CFX_Matrix& matrix, + FX_ARGB argbTopLeft, + FX_ARGB argbBottomRight); + void GetPath(const std::vector<CXFA_Stroke*>& strokes, + CFX_RectF rtWidget, + CXFA_GEPath& path, + int32_t nIndex, + bool bStart, + bool bCorner); }; #endif // XFA_FXFA_PARSER_CXFA_RECTANGLE_H_ diff --git a/xfa/fxfa/parser/cxfa_ref.cpp b/xfa/fxfa/parser/cxfa_ref.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d7df447c672579d4f7417806521da46b78aab34 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ref.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_ref.h" + +#include "fxjs/xfa/cjx_ref.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"ref"; + +} // namespace + +CXFA_Ref::CXFA_Ref(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::Ref, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Ref>(this)) {} + +CXFA_Ref::~CXFA_Ref() {} diff --git a/xfa/fxfa/parser/cxfa_ref.h b/xfa/fxfa/parser/cxfa_ref.h new file mode 100644 index 0000000000000000000000000000000000000000..630510fe2fd107697d687015c18af295c7278dcb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ref.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_REF_H_ +#define XFA_FXFA_PARSER_CXFA_REF_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Ref : public CXFA_Node { + public: + CXFA_Ref(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Ref() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_REF_H_ diff --git a/xfa/fxfa/parser/cxfa_relevant.cpp b/xfa/fxfa/parser/cxfa_relevant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c67ff1e31851ce09d652c29d13cd955c15b162f3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_relevant.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_relevant.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"relevant"; + +} // namespace + +CXFA_Relevant::CXFA_Relevant(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Relevant, + nullptr, + kAttributeData, + kName) {} + +CXFA_Relevant::~CXFA_Relevant() {} diff --git a/xfa/fxfa/parser/cxfa_relevant.h b/xfa/fxfa/parser/cxfa_relevant.h new file mode 100644 index 0000000000000000000000000000000000000000..2018c95e6795d07c9d07c3915c58c88cad5951ce --- /dev/null +++ b/xfa/fxfa/parser/cxfa_relevant.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RELEVANT_H_ +#define XFA_FXFA_PARSER_CXFA_RELEVANT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Relevant : public CXFA_Node { + public: + CXFA_Relevant(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Relevant() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RELEVANT_H_ diff --git a/xfa/fxfa/parser/cxfa_rename.cpp b/xfa/fxfa/parser/cxfa_rename.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0adbd7af8860de871124675c1d0004fb6a24eaa --- /dev/null +++ b/xfa/fxfa/parser/cxfa_rename.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_rename.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"rename"; + +} // namespace + +CXFA_Rename::CXFA_Rename(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Rename, + nullptr, + kAttributeData, + kName) {} + +CXFA_Rename::~CXFA_Rename() {} diff --git a/xfa/fxfa/parser/cxfa_rename.h b/xfa/fxfa/parser/cxfa_rename.h new file mode 100644 index 0000000000000000000000000000000000000000..665c85286eb9d3c2678d9fe25043fe35bf66455e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_rename.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RENAME_H_ +#define XFA_FXFA_PARSER_CXFA_RENAME_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Rename : public CXFA_Node { + public: + CXFA_Rename(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Rename() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RENAME_H_ diff --git a/xfa/fxfa/parser/cxfa_renderpolicy.cpp b/xfa/fxfa/parser/cxfa_renderpolicy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8abdb3bd87242fe7e7386de5daaa81f4099b11e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_renderpolicy.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_renderpolicy.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"renderPolicy"; + +} // namespace + +CXFA_RenderPolicy::CXFA_RenderPolicy(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::RenderPolicy, + nullptr, + kAttributeData, + kName) {} + +CXFA_RenderPolicy::~CXFA_RenderPolicy() {} diff --git a/xfa/fxfa/parser/cxfa_renderpolicy.h b/xfa/fxfa/parser/cxfa_renderpolicy.h new file mode 100644 index 0000000000000000000000000000000000000000..24ddf46d99b06db2cf9e8b38af1b5277f8a5443a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_renderpolicy.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RENDERPOLICY_H_ +#define XFA_FXFA_PARSER_CXFA_RENDERPOLICY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_RenderPolicy : public CXFA_Node { + public: + CXFA_RenderPolicy(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_RenderPolicy() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RENDERPOLICY_H_ diff --git a/xfa/fxfa/parser/cxfa_resolveprocessor.cpp b/xfa/fxfa/parser/cxfa_resolveprocessor.cpp deleted file mode 100644 index 3ef4e976cab960dc9c26a3a062049e3cd8fcb1d3..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_resolveprocessor.cpp +++ /dev/null @@ -1,822 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/cxfa_resolveprocessor.h" - -#include "core/fxcrt/fx_ext.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_nodehelper.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -CXFA_ResolveProcessor::CXFA_ResolveProcessor() - : m_iCurStart(0), m_pNodeHelper(new CXFA_NodeHelper) {} - -CXFA_ResolveProcessor::~CXFA_ResolveProcessor() {} - -int32_t CXFA_ResolveProcessor::Resolve(CXFA_ResolveNodesData& rnd) { - if (!rnd.m_CurNode) { - return -1; - } - if (!rnd.m_CurNode->IsNode()) { - if (rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) { - return ResolveForAttributeRs(rnd.m_CurNode, rnd, - rnd.m_wsName.AsStringC()); - } - return 0; - } - if (rnd.m_dwStyles & XFA_RESOLVENODE_AnyChild) { - return ResolveAnyChild(rnd); - } - FX_WCHAR wch = rnd.m_wsName.GetAt(0); - switch (wch) { - case '$': - return ResolveDollar(rnd); - case '!': - return ResolveExcalmatory(rnd); - case '#': - return ResolveNumberSign(rnd); - case '*': - return ResolveAsterisk(rnd); - // TODO(dsinclair): We could probably remove this. - case '.': - return ResolveAnyChild(rnd); - default: - break; - } - if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) { - rnd.m_Nodes.Add(rnd.m_pSC->GetThisObject()); - return 1; - } else if (rnd.m_CurNode->GetElementType() == XFA_Element::Xfa) { - CXFA_Object* pObjNode = - rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName); - if (pObjNode) { - rnd.m_Nodes.Add(pObjNode); - } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) { - rnd.m_Nodes.Add(rnd.m_CurNode); - } else if ((rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) && - ResolveForAttributeRs(rnd.m_CurNode, rnd, - rnd.m_wsName.AsStringC())) { - return 1; - } - if (rnd.m_Nodes.GetSize() > 0) { - FilterCondition(rnd, rnd.m_wsCondition); - } - return rnd.m_Nodes.GetSize(); - } - int32_t nRet = ResolveNormal(rnd); - if (nRet < 1 && rnd.m_uHashName == XFA_HASHCODE_Xfa) { - rnd.m_Nodes.Add(rnd.m_pSC->GetDocument()->GetRoot()); - } - return rnd.m_Nodes.GetSize(); -} -int32_t CXFA_ResolveProcessor::ResolveAnyChild(CXFA_ResolveNodesData& rnd) { - CFX_WideString wsName = rnd.m_wsName; - CFX_WideString wsCondition = rnd.m_wsCondition; - CXFA_Node* findNode = nullptr; - CXFA_NodeArray siblings; - bool bClassName = false; - if (wsName.GetAt(0) == '#') { - bClassName = true; - wsName = wsName.Right(wsName.GetLength() - 1); - } - findNode = m_pNodeHelper->ResolveNodes_GetOneChild( - ToNode(rnd.m_CurNode), wsName.c_str(), bClassName); - if (!findNode) { - return 0; - } - if (wsCondition.IsEmpty()) { - rnd.m_Nodes.Add(findNode); - return rnd.m_Nodes.GetSize(); - } - m_pNodeHelper->CountSiblings(findNode, XFA_LOGIC_Transparent, - (CXFA_NodeArray*)&rnd.m_Nodes, bClassName); - FilterCondition(rnd, wsCondition); - return rnd.m_Nodes.GetSize(); -} -int32_t CXFA_ResolveProcessor::ResolveDollar(CXFA_ResolveNodesData& rnd) { - CXFA_ObjArray& nodes = rnd.m_Nodes; - CFX_WideString wsName = rnd.m_wsName; - CFX_WideString wsCondition = rnd.m_wsCondition; - int32_t iNameLen = wsName.GetLength(); - if (iNameLen == 1) { - nodes.Add(rnd.m_CurNode); - return 1; - } - if (rnd.m_nLevel > 0) { - return -1; - } - XFA_HashCode dwNameHash = static_cast<XFA_HashCode>(FX_HashCode_GetW( - CFX_WideStringC(wsName.c_str() + 1, iNameLen - 1), false)); - if (dwNameHash == XFA_HASHCODE_Xfa) { - nodes.Add(rnd.m_pSC->GetDocument()->GetRoot()); - } else { - CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash); - if (pObjNode) { - rnd.m_Nodes.Add(pObjNode); - } - } - if (rnd.m_Nodes.GetSize() > 0) { - FilterCondition(rnd, wsCondition); - } - return rnd.m_Nodes.GetSize(); -} -int32_t CXFA_ResolveProcessor::ResolveExcalmatory(CXFA_ResolveNodesData& rnd) { - if (rnd.m_nLevel > 0) { - return 0; - } - CXFA_Node* datasets = - ToNode(rnd.m_pSC->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); - if (!datasets) { - return 0; - } - CXFA_ResolveNodesData rndFind; - rndFind.m_pSC = rnd.m_pSC; - rndFind.m_CurNode = datasets; - rndFind.m_wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1); - rndFind.m_uHashName = static_cast<XFA_HashCode>( - FX_HashCode_GetW(rndFind.m_wsName.AsStringC(), false)); - rndFind.m_nLevel = rnd.m_nLevel + 1; - rndFind.m_dwStyles = XFA_RESOLVENODE_Children; - rndFind.m_wsCondition = rnd.m_wsCondition; - Resolve(rndFind); - if (rndFind.m_Nodes.GetSize() > 0) { - rnd.m_Nodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - } - return rnd.m_Nodes.GetSize(); -} -int32_t CXFA_ResolveProcessor::ResolveNumberSign(CXFA_ResolveNodesData& rnd) { - CFX_WideString wsName = rnd.m_wsName.Right(rnd.m_wsName.GetLength() - 1); - CFX_WideString wsCondition = rnd.m_wsCondition; - CXFA_Node* curNode = ToNode(rnd.m_CurNode); - if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringC())) { - return 1; - } - CXFA_ResolveNodesData rndFind; - rndFind.m_pSC = rnd.m_pSC; - rndFind.m_nLevel = rnd.m_nLevel + 1; - rndFind.m_dwStyles = rnd.m_dwStyles; - rndFind.m_dwStyles |= XFA_RESOLVENODE_TagName; - rndFind.m_dwStyles &= ~XFA_RESOLVENODE_Attributes; - rndFind.m_wsName = wsName; - rndFind.m_uHashName = static_cast<XFA_HashCode>( - FX_HashCode_GetW(rndFind.m_wsName.AsStringC(), false)); - rndFind.m_wsCondition = wsCondition; - rndFind.m_CurNode = curNode; - ResolveNormal(rndFind); - if (rndFind.m_Nodes.GetSize() > 0) { - if (wsCondition.GetLength() == 0 && rndFind.m_Nodes.Find(curNode) >= 0) { - rnd.m_Nodes.Add(curNode); - } else { - rnd.m_Nodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - } - } - return rnd.m_Nodes.GetSize(); -} -int32_t CXFA_ResolveProcessor::ResolveForAttributeRs( - CXFA_Object* curNode, - CXFA_ResolveNodesData& rnd, - const CFX_WideStringC& strAttr) { - const XFA_SCRIPTATTRIBUTEINFO* lpScriptAttribute = - XFA_GetScriptAttributeByName(curNode->GetElementType(), strAttr); - if (lpScriptAttribute) { - rnd.m_pScriptAttribute = lpScriptAttribute; - rnd.m_Nodes.Add(curNode); - rnd.m_dwFlag = XFA_RESOVENODE_RSTYPE_Attribute; - return 1; - } - return 0; -} -int32_t CXFA_ResolveProcessor::ResolveNormal(CXFA_ResolveNodesData& rnd) { - if (rnd.m_nLevel > 32) { - return 0; - } - if (!rnd.m_CurNode->IsNode()) { - return 0; - } - CXFA_Node* curNode = ToNode(rnd.m_CurNode); - CXFA_ObjArray& nodes = rnd.m_Nodes; - int32_t nNum = nodes.GetSize(); - uint32_t dwStyles = rnd.m_dwStyles; - CFX_WideString& wsName = rnd.m_wsName; - XFA_HashCode uNameHash = rnd.m_uHashName; - CFX_WideString& wsCondition = rnd.m_wsCondition; - CXFA_ResolveNodesData rndFind; - rndFind.m_wsName = rnd.m_wsName; - rndFind.m_wsCondition = rnd.m_wsCondition; - rndFind.m_pSC = rnd.m_pSC; - rndFind.m_nLevel = rnd.m_nLevel + 1; - rndFind.m_uHashName = uNameHash; - CXFA_NodeArray children; - CXFA_NodeArray properties; - CXFA_Node* pVariablesNode = nullptr; - CXFA_Node* pPageSetNode = nullptr; - CXFA_Node* pChild = curNode->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pChild) { - if (pChild->GetElementType() == XFA_Element::Variables) { - pVariablesNode = pChild; - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - continue; - } else if (pChild->GetElementType() == XFA_Element::PageSet) { - pPageSetNode = pChild; - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - continue; - } else { - const XFA_PROPERTY* pPropert = XFA_GetPropertyOfElement( - curNode->GetElementType(), pChild->GetElementType(), - XFA_XDPPACKET_UNKNOWN); - if (pPropert) { - properties.Add(pChild); - } else { - children.Add(pChild); - } - } - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - } - if ((dwStyles & XFA_RESOLVENODE_Properties) && pVariablesNode) { - uint32_t uPropHash = pVariablesNode->GetClassHashCode(); - if (uPropHash == uNameHash) { - nodes.Add(pVariablesNode); - } else { - rndFind.m_CurNode = pVariablesNode; - SetStylesForChild(dwStyles, rndFind); - CFX_WideString wsSaveCondition = rndFind.m_wsCondition; - rndFind.m_wsCondition.clear(); - ResolveNormal(rndFind); - rndFind.m_wsCondition = wsSaveCondition; - if (rndFind.m_Nodes.GetSize() > 0) { - nodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - } - } - if (nodes.GetSize() > nNum) { - FilterCondition(rnd, wsCondition); - if (nodes.GetSize() > 0) { - return 1; - } - return 0; - } - } - if (dwStyles & XFA_RESOLVENODE_Children) { - bool bSetFlag = false; - if (pPageSetNode && (dwStyles & XFA_RESOLVENODE_Properties)) { - children.Add(pPageSetNode); - } - for (int32_t i = 0; i < children.GetSize(); i++) { - CXFA_Node* child = children[i]; - if (dwStyles & XFA_RESOLVENODE_TagName) { - if (child->GetClassHashCode() == uNameHash) { - nodes.Add(child); - } - } else if (child->GetNameHash() == uNameHash) { - nodes.Add(child); - } - if (m_pNodeHelper->NodeIsTransparent(child) && - child->GetElementType() != XFA_Element::PageSet) { - if (!bSetFlag) { - SetStylesForChild(dwStyles, rndFind); - bSetFlag = true; - } - rndFind.m_CurNode = child; - CFX_WideString wsSaveCondition = rndFind.m_wsCondition; - rndFind.m_wsCondition.clear(); - ResolveNormal(rndFind); - rndFind.m_wsCondition = wsSaveCondition; - if (rndFind.m_Nodes.GetSize() > 0) { - nodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - } - } - } - if (nodes.GetSize() > nNum) { - if (!(dwStyles & XFA_RESOLVENODE_ALL)) { - CXFA_NodeArray upArrayNodes; - if (m_pNodeHelper->NodeIsTransparent(ToNode(curNode))) { - m_pNodeHelper->CountSiblings(ToNode(nodes[0]), XFA_LOGIC_Transparent, - &upArrayNodes, - !!(dwStyles & XFA_RESOLVENODE_TagName)); - } - if (upArrayNodes.GetSize() > nodes.GetSize()) { - upArrayNodes[0] = ToNode(nodes[0]); - nodes.RemoveAll(); - nodes.Append((CXFA_ObjArray&)upArrayNodes); - upArrayNodes.RemoveAll(); - } - } - FilterCondition(rnd, wsCondition); - if (nodes.GetSize() > 0) { - return 1; - } - return 0; - } - } - if (dwStyles & XFA_RESOLVENODE_Attributes) { - if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringC())) { - return 1; - } - } - if (dwStyles & XFA_RESOLVENODE_Properties) { - for (int32_t i = 0; i < properties.GetSize(); i++) { - CXFA_Node* childProperty = properties[i]; - if (childProperty->IsUnnamed()) { - uint32_t uPropHash = childProperty->GetClassHashCode(); - if (uPropHash == uNameHash) { - nodes.Add(childProperty); - } - } else if (childProperty->GetNameHash() == uNameHash && - childProperty->GetElementType() != XFA_Element::Extras && - childProperty->GetElementType() != XFA_Element::Items) { - nodes.Add(childProperty); - } - } - if (nodes.GetSize() > nNum) { - FilterCondition(rnd, wsCondition); - if (nodes.GetSize() > 0) { - return 1; - } - return 0; - } - CXFA_Node* pProp = nullptr; - if (XFA_Element::Subform == curNode->GetElementType() && - XFA_HASHCODE_Occur == uNameHash) { - CXFA_Node* pInstanceManager = - curNode->AsNode()->GetInstanceMgrOfSubform(); - if (pInstanceManager) { - pProp = pInstanceManager->GetProperty(0, XFA_Element::Occur, true); - } - } else { - XFA_Element eType = XFA_GetElementTypeForName(wsName.AsStringC()); - if (eType != XFA_Element::Unknown) { - pProp = curNode->AsNode()->GetProperty(0, eType, - eType != XFA_Element::PageSet); - } - } - if (pProp) { - nodes.Add(pProp); - return nodes.GetSize(); - } - } - CXFA_Node* parentNode = m_pNodeHelper->ResolveNodes_GetParent( - curNode->AsNode(), XFA_LOGIC_NoTransparent); - uint32_t uCurClassHash = curNode->GetClassHashCode(); - if (!parentNode) { - if (uCurClassHash == uNameHash) { - nodes.Add(curNode->AsNode()); - FilterCondition(rnd, wsCondition); - if (nodes.GetSize() > 0) { - return 1; - } - } - return 0; - } - if (dwStyles & XFA_RESOLVENODE_Siblings) { - CXFA_Node* child = parentNode->GetNodeItem(XFA_NODEITEM_FirstChild); - uint32_t dwSubStyles = - XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties; - if (dwStyles & XFA_RESOLVENODE_TagName) { - dwSubStyles |= XFA_RESOLVENODE_TagName; - } - if (dwStyles & XFA_RESOLVENODE_ALL) { - dwSubStyles |= XFA_RESOLVENODE_ALL; - } - rndFind.m_dwStyles = dwSubStyles; - while (child) { - if (child == curNode) { - if (dwStyles & XFA_RESOLVENODE_TagName) { - if (uCurClassHash == uNameHash) { - nodes.Add(curNode); - } - } else { - if (child->GetNameHash() == uNameHash) { - nodes.Add(curNode); - if (rnd.m_nLevel == 0 && wsCondition.GetLength() == 0) { - nodes.RemoveAll(); - nodes.Add(curNode); - return 1; - } - } - } - child = child->GetNodeItem(XFA_NODEITEM_NextSibling); - continue; - } - if (dwStyles & XFA_RESOLVENODE_TagName) { - if (child->GetClassHashCode() == uNameHash) { - nodes.Add(child); - } - } else if (child->GetNameHash() == uNameHash) { - nodes.Add(child); - } - const XFA_PROPERTY* pPropert = XFA_GetPropertyOfElement( - parentNode->GetElementType(), child->GetElementType(), - XFA_XDPPACKET_UNKNOWN); - bool bInnerSearch = false; - if (pPropert) { - if ((child->GetElementType() == XFA_Element::Variables || - child->GetElementType() == XFA_Element::PageSet)) { - bInnerSearch = true; - } - } else { - if (m_pNodeHelper->NodeIsTransparent(child)) { - bInnerSearch = true; - } - } - if (bInnerSearch) { - rndFind.m_CurNode = child; - CFX_WideString wsOriginCondition = rndFind.m_wsCondition; - rndFind.m_wsCondition.clear(); - uint32_t dwOriginStyle = rndFind.m_dwStyles; - rndFind.m_dwStyles = dwOriginStyle | XFA_RESOLVENODE_ALL; - ResolveNormal(rndFind); - rndFind.m_dwStyles = dwOriginStyle; - rndFind.m_wsCondition = wsOriginCondition; - if (rndFind.m_Nodes.GetSize() > 0) { - nodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - } - } - child = child->GetNodeItem(XFA_NODEITEM_NextSibling); - } - if (nodes.GetSize() > nNum) { - if (m_pNodeHelper->NodeIsTransparent(parentNode)) { - CXFA_NodeArray upArrayNodes; - m_pNodeHelper->CountSiblings(ToNode(nodes[0]), XFA_LOGIC_Transparent, - &upArrayNodes, - !!(dwStyles & XFA_RESOLVENODE_TagName)); - if (upArrayNodes.GetSize() > nodes.GetSize()) { - upArrayNodes[0] = ToNode(nodes[0]); - nodes.RemoveAll(); - nodes.Append((CXFA_ObjArray&)upArrayNodes); - upArrayNodes.RemoveAll(); - } - } - FilterCondition(rnd, wsCondition); - if (nodes.GetSize() > 0) { - return 1; - } - return 0; - } - } - if (dwStyles & XFA_RESOLVENODE_Parent) { - uint32_t dwSubStyles = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | - XFA_RESOLVENODE_Properties; - if (dwStyles & XFA_RESOLVENODE_TagName) { - dwSubStyles |= XFA_RESOLVENODE_TagName; - } - if (dwStyles & XFA_RESOLVENODE_ALL) { - dwSubStyles |= XFA_RESOLVENODE_ALL; - } - rndFind.m_dwStyles = dwSubStyles; - rndFind.m_CurNode = parentNode; - CXFA_NodeArray& array = rnd.m_pSC->GetUpObjectArray(); - array.Add(parentNode); - ResolveNormal(rndFind); - if (rndFind.m_Nodes.GetSize() > 0) { - nodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - } - if (nodes.GetSize() > nNum) { - return 1; - } - } - return 0; -} -int32_t CXFA_ResolveProcessor::ResolveAsterisk(CXFA_ResolveNodesData& rnd) { - CXFA_Node* curNode = ToNode(rnd.m_CurNode); - CXFA_ObjArray& nodes = rnd.m_Nodes; - CXFA_NodeArray array; - curNode->GetNodeList(array, - XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties); - nodes.Append((CXFA_ObjArray&)array); - return nodes.GetSize(); -} -int32_t CXFA_ResolveProcessor::ResolvePopStack( - CFX_ArrayTemplate<int32_t>& stack) { - int32_t nType = -1; - int32_t iSize = stack.GetSize() - 1; - if (iSize > -1) { - nType = stack[iSize]; - stack.RemoveAt(iSize, 1); - } - return nType; -} -int32_t CXFA_ResolveProcessor::GetFilter(const CFX_WideStringC& wsExpression, - int32_t nStart, - CXFA_ResolveNodesData& rnd) { - ASSERT(nStart > -1); - int32_t iLength = wsExpression.GetLength(); - if (nStart >= iLength) { - return 0; - } - CFX_WideString& wsName = rnd.m_wsName; - CFX_WideString& wsCondition = rnd.m_wsCondition; - FX_WCHAR* pNameBuf = wsName.GetBuffer(iLength - nStart); - FX_WCHAR* pConditionBuf = wsCondition.GetBuffer(iLength - nStart); - int32_t nNameCount = 0; - int32_t nConditionCount = 0; - CFX_ArrayTemplate<int32_t> stack; - int32_t nType = -1; - const FX_WCHAR* pSrc = wsExpression.c_str(); - FX_WCHAR wPrev = 0, wCur; - bool bIsCondition = false; - while (nStart < iLength) { - wCur = pSrc[nStart++]; - if (wCur == '.') { - if (wPrev == '\\') { - pNameBuf[nNameCount - 1] = wPrev = '.'; - continue; - } - if (nNameCount == 0) { - rnd.m_dwStyles |= XFA_RESOLVENODE_AnyChild; - continue; - } - FX_WCHAR wLookahead = nStart < iLength ? pSrc[nStart] : 0; - if (wLookahead != '[' && wLookahead != '(') { - if (nType < 0) { - break; - } - } - } - if (wCur == '[' || wCur == '(') { - bIsCondition = true; - } else if (wCur == '.' && nStart < iLength && - (pSrc[nStart] == '[' || pSrc[nStart] == '(')) { - bIsCondition = true; - } - if (bIsCondition) { - pConditionBuf[nConditionCount++] = wCur; - } else { - pNameBuf[nNameCount++] = wCur; - } - bool bRecursive = true; - switch (nType) { - case 0: - if (wCur == ']') { - nType = ResolvePopStack(stack); - bRecursive = false; - } - break; - case 1: - if (wCur == ')') { - nType = ResolvePopStack(stack); - bRecursive = false; - } - break; - case 2: - if (wCur == '"') { - nType = ResolvePopStack(stack); - bRecursive = false; - } - break; - } - if (bRecursive) { - switch (wCur) { - case '[': - stack.Add(nType); - nType = 0; - break; - case '(': - stack.Add(nType); - nType = 1; - break; - case '"': - stack.Add(nType); - nType = 2; - break; - } - } - wPrev = wCur; - } - if (stack.GetSize() > 0) { - return -1; - } - wsName.ReleaseBuffer(nNameCount); - wsName.TrimLeft(); - wsName.TrimRight(); - wsCondition.ReleaseBuffer(nConditionCount); - wsCondition.TrimLeft(); - wsCondition.TrimRight(); - rnd.m_uHashName = - static_cast<XFA_HashCode>(FX_HashCode_GetW(wsName.AsStringC(), false)); - return nStart; -} -void CXFA_ResolveProcessor::ConditionArray(int32_t iCurIndex, - CFX_WideString wsCondition, - int32_t iFoundCount, - CXFA_ResolveNodesData& rnd) { - CXFA_NodeArray& findNodes = (CXFA_NodeArray&)rnd.m_Nodes; - int32_t iLen = wsCondition.GetLength(); - bool bRelative = false; - bool bAll = false; - int32_t i = 1; - for (; i < iLen; ++i) { - FX_WCHAR ch = wsCondition[i]; - if (ch == ' ') { - continue; - } - if (ch == '+' || ch == '-') { - bRelative = true; - break; - } else if (ch == '*') { - bAll = true; - break; - } else { - break; - } - } - if (bAll) { - if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { - if (rnd.m_dwStyles & XFA_RESOLVENODE_Bind) { - m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurNode); - m_pNodeHelper->m_iCreateCount = 1; - findNodes.RemoveAll(); - m_pNodeHelper->m_iCurAllStart = -1; - m_pNodeHelper->m_pAllStartParent = nullptr; - } else { - if (m_pNodeHelper->m_iCurAllStart == -1) { - m_pNodeHelper->m_iCurAllStart = m_iCurStart; - m_pNodeHelper->m_pAllStartParent = ToNode(rnd.m_CurNode); - } - } - } else if (rnd.m_dwStyles & XFA_RESOLVENODE_BindNew) { - if (m_pNodeHelper->m_iCurAllStart == -1) { - m_pNodeHelper->m_iCurAllStart = m_iCurStart; - } - } - return; - } - if (iFoundCount == 1 && !iLen) { - return; - } - CFX_WideString wsIndex; - wsIndex = wsCondition.Mid(i, iLen - 1 - i); - int32_t iIndex = wsIndex.GetInteger(); - if (bRelative) { - iIndex += iCurIndex; - } - if (iFoundCount <= iIndex || iIndex < 0) { - if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { - m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurNode); - m_pNodeHelper->m_iCreateCount = iIndex - iFoundCount + 1; - } - findNodes.RemoveAll(); - } else { - CXFA_Node* ret = findNodes[iIndex]; - findNodes.RemoveAll(); - findNodes.Add(ret); - } -} -void CXFA_ResolveProcessor::DoPredicateFilter(int32_t iCurIndex, - CFX_WideString wsCondition, - int32_t iFoundCount, - CXFA_ResolveNodesData& rnd) { - CXFA_NodeArray& findNodes = (CXFA_NodeArray&)rnd.m_Nodes; - ASSERT(iFoundCount == findNodes.GetSize()); - CFX_WideString wsExpression; - XFA_SCRIPTLANGTYPE eLangType = XFA_SCRIPTLANGTYPE_Unkown; - if (wsCondition.Left(2) == L".[" && wsCondition.Right(1) == L"]") { - eLangType = XFA_SCRIPTLANGTYPE_Formcalc; - } else if (wsCondition.Left(2) == L".(" && wsCondition.Right(1) == L")") { - eLangType = XFA_SCRIPTLANGTYPE_Javascript; - } else { - return; - } - - CXFA_ScriptContext* pContext = rnd.m_pSC; - wsExpression = wsCondition.Mid(2, wsCondition.GetLength() - 3); - for (int32_t i = iFoundCount - 1; i >= 0; i--) { - CXFA_Object* node = findNodes[i]; - bool bRet = false; - std::unique_ptr<CFXJSE_Value> pRetValue( - new CFXJSE_Value(rnd.m_pSC->GetRuntime())); - bRet = pContext->RunScript(eLangType, wsExpression.AsStringC(), - pRetValue.get(), node); - if (!bRet || !pRetValue->ToBoolean()) - findNodes.RemoveAt(i); - } -} - -void CXFA_ResolveProcessor::FilterCondition(CXFA_ResolveNodesData& rnd, - CFX_WideString wsCondition) { - CXFA_NodeArray& findNodes = (CXFA_NodeArray&)rnd.m_Nodes; - int32_t iCurrIndex = 0; - const CXFA_NodeArray& array = rnd.m_pSC->GetUpObjectArray(); - int32_t iSize = array.GetSize(); - if (iSize) { - CXFA_Node* curNode = array[iSize - 1]; - bool bIsProperty = m_pNodeHelper->NodeIsProperty(curNode); - if (curNode->IsUnnamed() || - (bIsProperty && curNode->GetElementType() != XFA_Element::PageSet)) { - iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent, - bIsProperty, true); - } else { - iCurrIndex = m_pNodeHelper->GetIndex(curNode, XFA_LOGIC_Transparent, - bIsProperty, false); - } - } - int32_t iFoundCount = findNodes.GetSize(); - wsCondition.TrimLeft(); - wsCondition.TrimRight(); - int32_t iLen = wsCondition.GetLength(); - if (!iLen) { - if (rnd.m_dwStyles & XFA_RESOLVENODE_ALL) { - return; - } - if (iFoundCount == 1) { - return; - } - if (iFoundCount <= iCurrIndex) { - if (rnd.m_dwStyles & XFA_RESOLVENODE_CreateNode) { - m_pNodeHelper->m_pCreateParent = ToNode(rnd.m_CurNode); - m_pNodeHelper->m_iCreateCount = iCurrIndex - iFoundCount + 1; - } - findNodes.RemoveAll(); - return; - } else { - CXFA_Node* ret = findNodes[iCurrIndex]; - findNodes.RemoveAll(); - findNodes.Add(ret); - return; - } - } - FX_WCHAR wTypeChar = wsCondition[0]; - switch (wTypeChar) { - case '[': - ConditionArray(iCurrIndex, wsCondition, iFoundCount, rnd); - return; - case '(': - return; - case '"': - return; - case '.': - if (iLen > 1 && (wsCondition[1] == '[' || wsCondition[1] == '(')) { - DoPredicateFilter(iCurrIndex, wsCondition, iFoundCount, rnd); - } - default: - return; - } -} -void CXFA_ResolveProcessor::SetStylesForChild(uint32_t dwParentStyles, - CXFA_ResolveNodesData& rnd) { - uint32_t dwSubStyles = XFA_RESOLVENODE_Children; - if (dwParentStyles & XFA_RESOLVENODE_TagName) { - dwSubStyles |= XFA_RESOLVENODE_TagName; - } - dwSubStyles &= ~XFA_RESOLVENODE_Parent; - dwSubStyles &= ~XFA_RESOLVENODE_Siblings; - dwSubStyles &= ~XFA_RESOLVENODE_Properties; - dwSubStyles |= XFA_RESOLVENODE_ALL; - rnd.m_dwStyles = dwSubStyles; -} -int32_t CXFA_ResolveProcessor::SetResultCreateNode( - XFA_RESOLVENODE_RS& resolveNodeRS, - CFX_WideString& wsLastCondition) { - if (m_pNodeHelper->m_pCreateParent) { - resolveNodeRS.nodes.Add(m_pNodeHelper->m_pCreateParent); - } else { - m_pNodeHelper->CreateNode_ForCondition(wsLastCondition); - } - resolveNodeRS.dwFlags = m_pNodeHelper->m_iCreateFlag; - if (resolveNodeRS.dwFlags == XFA_RESOLVENODE_RSTYPE_CreateNodeOne) { - if (m_pNodeHelper->m_iCurAllStart != -1) { - resolveNodeRS.dwFlags = XFA_RESOLVENODE_RSTYPE_CreateNodeMidAll; - } - } - return resolveNodeRS.nodes.GetSize(); -} -void CXFA_ResolveProcessor::SetIndexDataBind(CFX_WideString& wsNextCondition, - int32_t& iIndex, - int32_t iCount) { - if (m_pNodeHelper->CreateNode_ForCondition(wsNextCondition)) { - if (m_pNodeHelper->m_eLastCreateType == XFA_Element::DataGroup) { - iIndex = 0; - } else { - iIndex = iCount - 1; - } - } else { - iIndex = iCount - 1; - } -} - -CXFA_ResolveNodesData::CXFA_ResolveNodesData(CXFA_ScriptContext* pSC) - : m_pSC(pSC), - m_CurNode(nullptr), - m_wsName(), - m_uHashName(XFA_HASHCODE_None), - m_wsCondition(), - m_nLevel(0), - m_Nodes(), - m_dwStyles(XFA_RESOLVENODE_Children), - m_pScriptAttribute(nullptr), - m_dwFlag(XFA_RESOVENODE_RSTYPE_Nodes) {} - -CXFA_ResolveNodesData::~CXFA_ResolveNodesData() { - m_Nodes.RemoveAll(); -} diff --git a/xfa/fxfa/parser/cxfa_resolveprocessor.h b/xfa/fxfa/parser/cxfa_resolveprocessor.h deleted file mode 100644 index d806d57b93e87333150713ef7175473485681d6c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_resolveprocessor.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_CXFA_RESOLVEPROCESSOR_H_ -#define XFA_FXFA_PARSER_CXFA_RESOLVEPROCESSOR_H_ - -#include <memory> - -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" - -class CXFA_NodeHelper; -class CXFA_ScriptContext; - -class CXFA_ResolveNodesData { - public: - explicit CXFA_ResolveNodesData(CXFA_ScriptContext* pSC = nullptr); - ~CXFA_ResolveNodesData(); - - CXFA_ScriptContext* m_pSC; - CXFA_Object* m_CurNode; - CFX_WideString m_wsName; - XFA_HashCode m_uHashName; - CFX_WideString m_wsCondition; - int32_t m_nLevel; - CXFA_ObjArray m_Nodes; - uint32_t m_dwStyles; - const XFA_SCRIPTATTRIBUTEINFO* m_pScriptAttribute; - XFA_RESOVENODE_RSTYPE m_dwFlag; -}; - -class CXFA_ResolveProcessor { - public: - CXFA_ResolveProcessor(); - ~CXFA_ResolveProcessor(); - - int32_t Resolve(CXFA_ResolveNodesData& rnd); - int32_t GetFilter(const CFX_WideStringC& wsExpression, - int32_t nStart, - CXFA_ResolveNodesData& rnd); - int32_t SetResultCreateNode(XFA_RESOLVENODE_RS& resolveNodeRS, - CFX_WideString& wsLastCondition); - void SetIndexDataBind(CFX_WideString& wsNextCondition, - int32_t& iIndex, - int32_t iCount); - void SetCurStart(int32_t start) { m_iCurStart = start; } - - CXFA_NodeHelper* GetNodeHelper() const { return m_pNodeHelper.get(); } - - private: - int32_t ResolveForAttributeRs(CXFA_Object* curNode, - CXFA_ResolveNodesData& rnd, - const CFX_WideStringC& strAttr); - int32_t ResolveAnyChild(CXFA_ResolveNodesData& rnd); - int32_t ResolveDollar(CXFA_ResolveNodesData& rnd); - int32_t ResolveExcalmatory(CXFA_ResolveNodesData& rnd); - int32_t ResolveNumberSign(CXFA_ResolveNodesData& rnd); - int32_t ResolveAsterisk(CXFA_ResolveNodesData& rnd); - int32_t ResolveNormal(CXFA_ResolveNodesData& rnd); - int32_t ResolvePopStack(CFX_ArrayTemplate<int32_t>& stack); - void SetStylesForChild(uint32_t dwParentStyles, CXFA_ResolveNodesData& rnd); - - void ConditionArray(int32_t iCurIndex, - CFX_WideString wsCondition, - int32_t iFoundCount, - CXFA_ResolveNodesData& rnd); - void DoPredicateFilter(int32_t iCurIndex, - CFX_WideString wsCondition, - int32_t iFoundCount, - CXFA_ResolveNodesData& rnd); - void FilterCondition(CXFA_ResolveNodesData& rnd, CFX_WideString wsCondition); - - int32_t m_iCurStart; - std::unique_ptr<CXFA_NodeHelper> m_pNodeHelper; -}; - -#endif // XFA_FXFA_PARSER_CXFA_RESOLVEPROCESSOR_H_ diff --git a/xfa/fxfa/parser/cxfa_rootelement.cpp b/xfa/fxfa/parser/cxfa_rootelement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9b86319b7081de705d701e0a2de7e01686f85dd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_rootelement.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_rootelement.h" + +#include "fxjs/xfa/cjx_rootelement.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"rootElement"; + +} // namespace + +CXFA_RootElement::CXFA_RootElement(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::TextNode, + XFA_Element::RootElement, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_RootElement>(this)) {} + +CXFA_RootElement::~CXFA_RootElement() {} diff --git a/xfa/fxfa/parser/cxfa_rootelement.h b/xfa/fxfa/parser/cxfa_rootelement.h new file mode 100644 index 0000000000000000000000000000000000000000..a995e8cc3aed724b196dbc64d3327056fe29266e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_rootelement.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ROOTELEMENT_H_ +#define XFA_FXFA_PARSER_CXFA_ROOTELEMENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_RootElement : public CXFA_Node { + public: + CXFA_RootElement(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_RootElement() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ROOTELEMENT_H_ diff --git a/xfa/fxfa/parser/cxfa_runscripts.cpp b/xfa/fxfa/parser/cxfa_runscripts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06c0d522c980d8afcb1bcff72b291e9d039670f5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_runscripts.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_runscripts.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"runScripts"; + +} // namespace + +CXFA_RunScripts::CXFA_RunScripts(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::RunScripts, + nullptr, + kAttributeData, + kName) {} + +CXFA_RunScripts::~CXFA_RunScripts() {} diff --git a/xfa/fxfa/parser/cxfa_runscripts.h b/xfa/fxfa/parser/cxfa_runscripts.h new file mode 100644 index 0000000000000000000000000000000000000000..d2ecaa0f16716fad050952ba47231d3b56dd98c1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_runscripts.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_RUNSCRIPTS_H_ +#define XFA_FXFA_PARSER_CXFA_RUNSCRIPTS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_RunScripts : public CXFA_Node { + public: + CXFA_RunScripts(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_RunScripts() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_RUNSCRIPTS_H_ diff --git a/xfa/fxfa/parser/cxfa_script.cpp b/xfa/fxfa/parser/cxfa_script.cpp index 16f65f99f44f6eeb65f35047065db5d1999a4eb3..1e4eb7e0aa7c2ac32020f87a71046b2a8b3877d1 100644 --- a/xfa/fxfa/parser/cxfa_script.cpp +++ b/xfa/fxfa/parser/cxfa_script.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,26 +6,61 @@ #include "xfa/fxfa/parser/cxfa_script.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_script.h" +#include "third_party/base/ptr_util.h" -CXFA_Script::CXFA_Script(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -XFA_SCRIPTTYPE CXFA_Script::GetContentType() { - CFX_WideStringC cData; - if (m_pNode->TryCData(XFA_ATTRIBUTE_ContentType, cData, false)) { - if (cData == L"application/x-javascript") - return XFA_SCRIPTTYPE_Javascript; - if (cData == L"application/x-formcalc") - return XFA_SCRIPTTYPE_Formcalc; - return XFA_SCRIPTTYPE_Unkown; - } - return XFA_SCRIPTTYPE_Formcalc; +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Exclude, 1, 0}, + {XFA_Element::CurrentPage, 1, 0}, + {XFA_Element::RunScripts, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ContentType, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::RunAt, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Client}, + {XFA_Attribute::Binding, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"script"; + +} // namespace + +CXFA_Script::CXFA_Script(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Script, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Script>(this)) {} + +CXFA_Script::~CXFA_Script() {} + +CXFA_Script::Type CXFA_Script::GetContentType() { + Optional<WideString> cData = + JSObject()->TryCData(XFA_Attribute::ContentType, false); + if (!cData || *cData == L"application/x-formcalc") + return Type::Formcalc; + if (*cData == L"application/x-javascript") + return Type::Javascript; + return Type::Unknown; } -int32_t CXFA_Script::GetRunAt() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_RunAt); +XFA_AttributeEnum CXFA_Script::GetRunAt() { + return JSObject()->GetEnum(XFA_Attribute::RunAt); } -void CXFA_Script::GetExpression(CFX_WideString& wsExpression) { - m_pNode->TryContent(wsExpression); +WideString CXFA_Script::GetExpression() { + return JSObject()->GetContent(false); } diff --git a/xfa/fxfa/parser/cxfa_script.h b/xfa/fxfa/parser/cxfa_script.h index d89062487d363cbf01c7a5e658beb6c35f6da313..8ea7aac60b51d08102bdceb7fab0c8d7f57aeb90 100644 --- a/xfa/fxfa/parser/cxfa_script.h +++ b/xfa/fxfa/parser/cxfa_script.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,26 +7,23 @@ #ifndef XFA_FXFA_PARSER_CXFA_SCRIPT_H_ #define XFA_FXFA_PARSER_CXFA_SCRIPT_H_ -#include <stdint.h> +#include "core/fxcrt/widestring.h" +#include "xfa/fxfa/parser/cxfa_node.h" -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" - -enum XFA_SCRIPTTYPE { - XFA_SCRIPTTYPE_Formcalc = 0, - XFA_SCRIPTTYPE_Javascript, - XFA_SCRIPTTYPE_Unkown, -}; - -class CXFA_Node; - -class CXFA_Script : public CXFA_Data { +class CXFA_Script : public CXFA_Node { public: - explicit CXFA_Script(CXFA_Node* pNode); - - XFA_SCRIPTTYPE GetContentType(); - int32_t GetRunAt(); - void GetExpression(CFX_WideString& wsExpression); + enum class Type { + Formcalc = 0, + Javascript, + Unknown, + }; + + CXFA_Script(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Script() override; + + Type GetContentType(); + XFA_AttributeEnum GetRunAt(); + WideString GetExpression(); }; #endif // XFA_FXFA_PARSER_CXFA_SCRIPT_H_ diff --git a/xfa/fxfa/parser/cxfa_scriptcontext.cpp b/xfa/fxfa/parser/cxfa_scriptcontext.cpp deleted file mode 100644 index 584cd76beddb08fcc3ed7b030f2f7e56dbf1df8c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_scriptcontext.cpp +++ /dev/null @@ -1,769 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" - -#include <utility> - -#include "core/fxcrt/fx_ext.h" -#include "fxjs/cfxjse_arguments.h" -#include "fxjs/cfxjse_class.h" -#include "fxjs/cfxjse_value.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_nodehelper.h" -#include "xfa/fxfa/parser/cxfa_resolveprocessor.h" -#include "xfa/fxfa/parser/xfa_basic_data.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -namespace { - -const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { - "Root", // name - nullptr, // constructor - nullptr, // properties - nullptr, // methods - 0, // property count - 0, // method count - CXFA_ScriptContext::GlobalPropTypeGetter, - CXFA_ScriptContext::GlobalPropertyGetter, - CXFA_ScriptContext::GlobalPropertySetter, - nullptr, // property deleter - CXFA_ScriptContext::NormalMethodCall, -}; - -const FXJSE_CLASS_DESCRIPTOR NormalClassDescriptor = { - "XFAObject", // name - nullptr, // constructor - nullptr, // properties - nullptr, // methods - 0, // property count - 0, // method count - CXFA_ScriptContext::NormalPropTypeGetter, - CXFA_ScriptContext::NormalPropertyGetter, - CXFA_ScriptContext::NormalPropertySetter, - nullptr, // property deleter - CXFA_ScriptContext::NormalMethodCall, -}; - -const FXJSE_CLASS_DESCRIPTOR VariablesClassDescriptor = { - "XFAScriptObject", // name - nullptr, // constructor - nullptr, // properties - nullptr, // methods - 0, // property count - 0, // method count - CXFA_ScriptContext::NormalPropTypeGetter, - CXFA_ScriptContext::GlobalPropertyGetter, - CXFA_ScriptContext::GlobalPropertySetter, - nullptr, // property deleter - CXFA_ScriptContext::NormalMethodCall, -}; - -const char kFormCalcRuntime[] = "foxit_xfa_formcalc_runtime"; - -CXFA_ThisProxy* ToThisProxy(CFXJSE_Value* pValue, CFXJSE_Class* pClass) { - return static_cast<CXFA_ThisProxy*>(pValue->ToHostObject(pClass)); -} - -const XFA_METHODINFO* GetMethodByName(XFA_Element eElement, - const CFX_WideStringC& wsMethodName) { - if (wsMethodName.IsEmpty()) - return nullptr; - - int32_t iElementIndex = static_cast<int32_t>(eElement); - while (iElementIndex >= 0 && iElementIndex < g_iScriptIndexCount) { - const XFA_SCRIPTHIERARCHY* scriptIndex = g_XFAScriptIndex + iElementIndex; - int32_t icount = scriptIndex->wMethodCount; - if (icount == 0) { - iElementIndex = scriptIndex->wParentIndex; - continue; - } - uint32_t uHash = FX_HashCode_GetW(wsMethodName, false); - int32_t iStart = scriptIndex->wMethodStart; - // TODO(dsinclair): Switch to std::lower_bound. - int32_t iEnd = iStart + icount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_METHODINFO* pInfo = g_SomMethodData + iMid; - if (uHash == pInfo->uHash) - return pInfo; - if (uHash < pInfo->uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - iElementIndex = scriptIndex->wParentIndex; - } - return nullptr; -} - -} // namespace - -// static. -CXFA_Object* CXFA_ScriptContext::ToObject(CFXJSE_Value* pValue, - CFXJSE_Class* pClass) { - return static_cast<CXFA_Object*>(pValue->ToHostObject(pClass)); -} - -CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument) - : m_pDocument(pDocument), - m_pIsolate(nullptr), - m_pJsClass(nullptr), - m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown), - m_pScriptNodeArray(nullptr), - m_pThisObject(nullptr), - m_dwBuiltInInFlags(0), - m_eRunAtType(XFA_ATTRIBUTEENUM_Client) {} - -CXFA_ScriptContext::~CXFA_ScriptContext() { - for (const auto& pair : m_mapVariableToContext) { - CFXJSE_Context* pVariableContext = pair.second; - delete ToThisProxy(pVariableContext->GetGlobalObject().get(), nullptr); - delete pVariableContext; - } - m_mapVariableToContext.clear(); - m_upObjectArray.RemoveAll(); -} - -void CXFA_ScriptContext::Initialize(v8::Isolate* pIsolate) { - m_pIsolate = pIsolate; - DefineJsContext(); - DefineJsClass(); - m_ResolveProcessor = pdfium::MakeUnique<CXFA_ResolveProcessor>(); -} - -bool CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType, - const CFX_WideStringC& wsScript, - CFXJSE_Value* hRetValue, - CXFA_Object* pThisObject) { - CFX_ByteString btScript; - XFA_SCRIPTLANGTYPE eSaveType = m_eScriptType; - m_eScriptType = eScriptType; - if (eScriptType == XFA_SCRIPTLANGTYPE_Formcalc) { - if (!m_FM2JSContext) { - m_FM2JSContext.reset( - new CXFA_FM2JSContext(m_pIsolate, m_JsContext.get(), m_pDocument)); - } - CFX_WideTextBuf wsJavaScript; - CFX_WideString wsErrorInfo; - int32_t iFlags = - CXFA_FM2JSContext::Translate(wsScript, wsJavaScript, wsErrorInfo); - if (iFlags) { - hRetValue->SetUndefined(); - return false; - } - btScript = FX_UTF8Encode(wsJavaScript.AsStringC()); - } else { - btScript = FX_UTF8Encode(wsScript); - } - CXFA_Object* pOriginalObject = m_pThisObject; - m_pThisObject = pThisObject; - CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : nullptr; - bool bRet = m_JsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue); - m_pThisObject = pOriginalObject; - m_eScriptType = eSaveType; - return bRet; -} -void CXFA_ScriptContext::GlobalPropertySetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue) { - CXFA_Object* lpOrginalNode = ToObject(pObject, nullptr); - CXFA_Document* pDoc = lpOrginalNode->GetDocument(); - CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); - CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode); - CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); - uint32_t dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | - XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | - XFA_RESOLVENODE_Attributes; - CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); - if (lpOrginalNode->IsVariablesThis()) - pRefNode = ToNode(lpCurNode); - if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, - dwFlag, true)) { - return; - } - if (lpOrginalNode->IsVariablesThis()) { - if (pValue && pValue->IsUndefined()) { - pObject->SetObjectOwnProperty(szPropName, pValue); - return; - } - } - CXFA_FFNotify* pNotify = pDoc->GetNotify(); - if (!pNotify) { - return; - } - pNotify->GetDocEnvironment()->SetGlobalProperty(pNotify->GetHDOC(), - szPropName, pValue); -} -bool CXFA_ScriptContext::QueryNodeByFlag(CXFA_Node* refNode, - const CFX_WideStringC& propname, - CFXJSE_Value* pValue, - uint32_t dwFlag, - bool bSetting) { - if (!refNode) - return false; - XFA_RESOLVENODE_RS resolveRs; - if (ResolveObjects(refNode, propname, resolveRs, dwFlag) <= 0) - return false; - if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { - pValue->Assign(GetJSValueFromMap(resolveRs.nodes[0])); - return true; - } - if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) { - const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = resolveRs.pScriptAttribute; - if (lpAttributeInfo) { - (resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))( - pValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); - } - } - return true; -} -void CXFA_ScriptContext::GlobalPropertyGetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue) { - CXFA_Object* pOriginalObject = ToObject(pObject, nullptr); - CXFA_Document* pDoc = pOriginalObject->GetDocument(); - CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); - CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(pOriginalObject); - CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); - if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) { - if (szPropName == kFormCalcRuntime) { - lpScriptContext->m_FM2JSContext->GlobalPropertyGetter(pValue); - return; - } - XFA_HashCode uHashCode = static_cast<XFA_HashCode>( - FX_HashCode_GetW(wsPropName.AsStringC(), false)); - if (uHashCode != XFA_HASHCODE_Layout) { - CXFA_Object* pObj = - lpScriptContext->GetDocument()->GetXFAObject(uHashCode); - if (pObj) { - pValue->Assign(lpScriptContext->GetJSValueFromMap(pObj)); - return; - } - } - } - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | - XFA_RESOLVENODE_Attributes; - CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); - if (pOriginalObject->IsVariablesThis()) { - pRefNode = ToNode(lpCurNode); - } - if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, - dwFlag, false)) { - return; - } - dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; - if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, - dwFlag, false)) { - return; - } - CXFA_Object* pScriptObject = - lpScriptContext->GetVariablesThis(pOriginalObject, true); - if (pScriptObject && - lpScriptContext->QueryVariableValue(pScriptObject->AsNode(), szPropName, - pValue, true)) { - return; - } - CXFA_FFNotify* pNotify = pDoc->GetNotify(); - if (!pNotify) { - return; - } - pNotify->GetDocEnvironment()->GetGlobalProperty(pNotify->GetHDOC(), - szPropName, pValue); -} -void CXFA_ScriptContext::NormalPropertyGetter(CFXJSE_Value* pOriginalValue, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pReturnValue) { - CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); - if (!pOriginalObject) { - pReturnValue->SetUndefined(); - return; - } - CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); - CXFA_ScriptContext* lpScriptContext = - pOriginalObject->GetDocument()->GetScriptContext(); - CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); - if (wsPropName == L"xfa") { - CFXJSE_Value* pValue = lpScriptContext->GetJSValueFromMap( - lpScriptContext->GetDocument()->GetRoot()); - pReturnValue->Assign(pValue); - return; - } - uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | - XFA_RESOLVENODE_Attributes; - bool bRet = lpScriptContext->QueryNodeByFlag( - ToNode(pObject), wsPropName.AsStringC(), pReturnValue, dwFlag, false); - if (bRet) { - return; - } - if (pObject == lpScriptContext->GetThisObject() || - (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Javascript && - !lpScriptContext->IsStrictScopeInJavaScript())) { - dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; - bRet = lpScriptContext->QueryNodeByFlag( - ToNode(pObject), wsPropName.AsStringC(), pReturnValue, dwFlag, false); - } - if (bRet) { - return; - } - CXFA_Object* pScriptObject = - lpScriptContext->GetVariablesThis(pOriginalObject, true); - if (pScriptObject) { - bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject), - szPropName, pReturnValue, true); - } - if (!bRet) { - pReturnValue->SetUndefined(); - } -} -void CXFA_ScriptContext::NormalPropertySetter(CFXJSE_Value* pOriginalValue, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pReturnValue) { - CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); - if (!pOriginalObject) - return; - - CXFA_ScriptContext* lpScriptContext = - pOriginalObject->GetDocument()->GetScriptContext(); - CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); - CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); - const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = XFA_GetScriptAttributeByName( - pObject->GetElementType(), wsPropName.AsStringC()); - if (lpAttributeInfo) { - (pObject->*(lpAttributeInfo->lpfnCallback))( - pReturnValue, true, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); - } else { - if (pObject->IsNode()) { - if (wsPropName.GetAt(0) == '#') { - wsPropName = wsPropName.Right(wsPropName.GetLength() - 1); - } - CXFA_Node* pNode = ToNode(pObject); - CXFA_Node* pPropOrChild = nullptr; - XFA_Element eType = XFA_GetElementTypeForName(wsPropName.AsStringC()); - if (eType != XFA_Element::Unknown) - pPropOrChild = pNode->GetProperty(0, eType); - else - pPropOrChild = pNode->GetFirstChildByName(wsPropName.AsStringC()); - - if (pPropOrChild) { - CFX_WideString wsDefaultName(L"{default}"); - const XFA_SCRIPTATTRIBUTEINFO* lpAttrInfo = - XFA_GetScriptAttributeByName(pPropOrChild->GetElementType(), - wsDefaultName.AsStringC()); - if (lpAttrInfo) { - (pPropOrChild->*(lpAttrInfo->lpfnCallback))( - pReturnValue, true, (XFA_ATTRIBUTE)lpAttrInfo->eAttribute); - return; - } - } - } - CXFA_Object* pScriptObject = - lpScriptContext->GetVariablesThis(pOriginalObject, true); - if (pScriptObject) { - lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName, - pReturnValue, false); - } - } -} -int32_t CXFA_ScriptContext::NormalPropTypeGetter( - CFXJSE_Value* pOriginalValue, - const CFX_ByteStringC& szPropName, - bool bQueryIn) { - CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); - if (!pObject) - return FXJSE_ClassPropType_None; - - CXFA_ScriptContext* lpScriptContext = - pObject->GetDocument()->GetScriptContext(); - pObject = lpScriptContext->GetVariablesThis(pObject); - XFA_Element eType = pObject->GetElementType(); - CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); - if (GetMethodByName(eType, wsPropName.AsStringC())) { - return FXJSE_ClassPropType_Method; - } - if (bQueryIn && - !XFA_GetScriptAttributeByName(eType, wsPropName.AsStringC())) { - return FXJSE_ClassPropType_None; - } - return FXJSE_ClassPropType_Property; -} -int32_t CXFA_ScriptContext::GlobalPropTypeGetter( - CFXJSE_Value* pOriginalValue, - const CFX_ByteStringC& szPropName, - bool bQueryIn) { - CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); - if (!pObject) - return FXJSE_ClassPropType_None; - - CXFA_ScriptContext* lpScriptContext = - pObject->GetDocument()->GetScriptContext(); - pObject = lpScriptContext->GetVariablesThis(pObject); - XFA_Element eType = pObject->GetElementType(); - CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); - if (GetMethodByName(eType, wsPropName.AsStringC())) { - return FXJSE_ClassPropType_Method; - } - return FXJSE_ClassPropType_Property; -} -void CXFA_ScriptContext::NormalMethodCall(CFXJSE_Value* pThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args) { - CXFA_Object* pObject = ToObject(pThis, nullptr); - if (!pObject) - return; - - CXFA_ScriptContext* lpScriptContext = - pObject->GetDocument()->GetScriptContext(); - pObject = lpScriptContext->GetVariablesThis(pObject); - CFX_WideString wsFunName = CFX_WideString::FromUTF8(szFuncName); - const XFA_METHODINFO* lpMethodInfo = - GetMethodByName(pObject->GetElementType(), wsFunName.AsStringC()); - if (!lpMethodInfo) - return; - - (pObject->*(lpMethodInfo->lpfnCallback))(&args); -} -bool CXFA_ScriptContext::IsStrictScopeInJavaScript() { - return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); -} -XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() { - return m_eScriptType; -} -void CXFA_ScriptContext::DefineJsContext() { - m_JsContext.reset(CFXJSE_Context::Create(m_pIsolate, &GlobalClassDescriptor, - m_pDocument->GetRoot())); - RemoveBuiltInObjs(m_JsContext.get()); - m_JsContext->EnableCompatibleMode(); -} -CFXJSE_Context* CXFA_ScriptContext::CreateVariablesContext( - CXFA_Node* pScriptNode, - CXFA_Node* pSubform) { - if (!pScriptNode || !pSubform) - return nullptr; - - CFXJSE_Context* pVariablesContext = - CFXJSE_Context::Create(m_pIsolate, &VariablesClassDescriptor, - new CXFA_ThisProxy(pSubform, pScriptNode)); - RemoveBuiltInObjs(pVariablesContext); - pVariablesContext->EnableCompatibleMode(); - m_mapVariableToContext[pScriptNode] = pVariablesContext; - return pVariablesContext; -} -CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject, - bool bScriptNode) { - if (!pObject->IsVariablesThis()) - return pObject; - - CXFA_ThisProxy* pProxy = static_cast<CXFA_ThisProxy*>(pObject); - return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); -} - -bool CXFA_ScriptContext::RunVariablesScript(CXFA_Node* pScriptNode) { - if (!pScriptNode) - return false; - - if (pScriptNode->GetElementType() != XFA_Element::Script) - return true; - - CXFA_Node* pParent = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!pParent || pParent->GetElementType() != XFA_Element::Variables) - return false; - - auto it = m_mapVariableToContext.find(pScriptNode); - if (it != m_mapVariableToContext.end() && it->second) - return true; - - CXFA_Node* pTextNode = pScriptNode->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pTextNode) - return false; - - CFX_WideStringC wsScript; - if (!pTextNode->TryCData(XFA_ATTRIBUTE_Value, wsScript)) - return false; - - CFX_ByteString btScript = FX_UTF8Encode(wsScript); - std::unique_ptr<CFXJSE_Value> hRetValue(new CFXJSE_Value(m_pIsolate)); - CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent); - CFXJSE_Context* pVariablesContext = - CreateVariablesContext(pScriptNode, pThisObject); - CXFA_Object* pOriginalObject = m_pThisObject; - m_pThisObject = pThisObject; - bool bRet = - pVariablesContext->ExecuteScript(btScript.c_str(), hRetValue.get()); - m_pThisObject = pOriginalObject; - return bRet; -} - -bool CXFA_ScriptContext::QueryVariableValue(CXFA_Node* pScriptNode, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue, - bool bGetter) { - if (!pScriptNode || pScriptNode->GetElementType() != XFA_Element::Script) - return false; - - CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); - if (!variablesNode || - variablesNode->GetElementType() != XFA_Element::Variables) - return false; - - auto it = m_mapVariableToContext.find(pScriptNode); - if (it == m_mapVariableToContext.end() || !it->second) - return false; - - void* lpVariables = it->second; - bool bRes = false; - CFXJSE_Context* pVariableContext = static_cast<CFXJSE_Context*>(lpVariables); - std::unique_ptr<CFXJSE_Value> pObject = pVariableContext->GetGlobalObject(); - std::unique_ptr<CFXJSE_Value> hVariableValue(new CFXJSE_Value(m_pIsolate)); - if (!bGetter) { - pObject->SetObjectOwnProperty(szPropName, pValue); - bRes = true; - } else if (pObject->HasObjectOwnProperty(szPropName, false)) { - pObject->GetObjectProperty(szPropName, hVariableValue.get()); - if (hVariableValue->IsFunction()) - pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); - else if (bGetter) - pValue->Assign(hVariableValue.get()); - else - hVariableValue.get()->Assign(pValue); - bRes = true; - } - return bRes; -} - -void CXFA_ScriptContext::DefineJsClass() { - m_pJsClass = CFXJSE_Class::Create(m_JsContext.get(), &NormalClassDescriptor); -} - -void CXFA_ScriptContext::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { - static const CFX_ByteStringC OBJ_NAME[2] = {"Number", "Date"}; - std::unique_ptr<CFXJSE_Value> pObject = pContext->GetGlobalObject(); - std::unique_ptr<CFXJSE_Value> hProp(new CFXJSE_Value(m_pIsolate)); - for (int i = 0; i < 2; ++i) { - if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) - pObject->DeleteObjectProperty(OBJ_NAME[i]); - } -} -CFXJSE_Class* CXFA_ScriptContext::GetJseNormalClass() { - return m_pJsClass; -} -int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode, - const CFX_WideStringC& wsExpression, - XFA_RESOLVENODE_RS& resolveNodeRS, - uint32_t dwStyles, - CXFA_Node* bindNode) { - if (wsExpression.IsEmpty()) { - return 0; - } - if (m_eScriptType != XFA_SCRIPTLANGTYPE_Formcalc || - (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { - m_upObjectArray.RemoveAll(); - } - if (refNode && refNode->IsNode() && - (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { - m_upObjectArray.Add(refNode->AsNode()); - } - bool bNextCreate = false; - if (dwStyles & XFA_RESOLVENODE_CreateNode) { - m_ResolveProcessor->GetNodeHelper()->SetCreateNodeType(bindNode); - } - m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = nullptr; - m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1; - CXFA_ResolveNodesData rndFind; - int32_t nStart = 0; - int32_t nLevel = 0; - int32_t nRet = -1; - rndFind.m_pSC = this; - CXFA_ObjArray findNodes; - findNodes.Add(refNode ? refNode : m_pDocument->GetRoot()); - int32_t nNodes = 0; - while (true) { - nNodes = findNodes.GetSize(); - int32_t i = 0; - rndFind.m_dwStyles = dwStyles; - m_ResolveProcessor->SetCurStart(nStart); - nStart = m_ResolveProcessor->GetFilter(wsExpression, nStart, rndFind); - if (nStart < 1) { - if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) { - CXFA_Node* pDataNode = nullptr; - nStart = m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart; - if (nStart != -1) { - pDataNode = m_pDocument->GetNotBindNode(findNodes); - if (pDataNode) { - findNodes.RemoveAll(); - findNodes.Add(pDataNode); - break; - } - } else { - pDataNode = findNodes[0]->AsNode(); - findNodes.RemoveAll(); - findNodes.Add(pDataNode); - break; - } - dwStyles |= XFA_RESOLVENODE_Bind; - findNodes.RemoveAll(); - findNodes.Add(m_ResolveProcessor->GetNodeHelper()->m_pAllStartParent); - continue; - } else { - break; - } - } - if (bNextCreate) { - bool bCreate = - m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( - rndFind.m_wsName, rndFind.m_wsCondition, - nStart == wsExpression.GetLength(), this); - if (bCreate) { - continue; - } else { - break; - } - } - CXFA_ObjArray retNodes; - while (i < nNodes) { - bool bDataBind = false; - if (((dwStyles & XFA_RESOLVENODE_Bind) || - (dwStyles & XFA_RESOLVENODE_CreateNode)) && - nNodes > 1) { - CXFA_ResolveNodesData rndBind; - m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind); - m_ResolveProcessor->SetIndexDataBind(rndBind.m_wsCondition, i, nNodes); - bDataBind = true; - } - rndFind.m_CurNode = findNodes[i++]; - rndFind.m_nLevel = nLevel; - rndFind.m_dwFlag = XFA_RESOVENODE_RSTYPE_Nodes; - nRet = m_ResolveProcessor->Resolve(rndFind); - if (nRet < 1) { - continue; - } - if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute && - rndFind.m_pScriptAttribute && nStart < wsExpression.GetLength()) { - std::unique_ptr<CFXJSE_Value> pValue(new CFXJSE_Value(m_pIsolate)); - (rndFind.m_Nodes[0]->*(rndFind.m_pScriptAttribute->lpfnCallback))( - pValue.get(), false, - (XFA_ATTRIBUTE)rndFind.m_pScriptAttribute->eAttribute); - rndFind.m_Nodes.SetAt(0, ToObject(pValue.get(), nullptr)); - } - int32_t iSize = m_upObjectArray.GetSize(); - if (iSize) { - m_upObjectArray.RemoveAt(iSize - 1); - } - retNodes.Append(rndFind.m_Nodes); - rndFind.m_Nodes.RemoveAll(); - if (bDataBind) { - break; - } - } - findNodes.RemoveAll(); - nNodes = retNodes.GetSize(); - if (nNodes < 1) { - if (dwStyles & XFA_RESOLVENODE_CreateNode) { - bNextCreate = true; - if (!m_ResolveProcessor->GetNodeHelper()->m_pCreateParent) { - m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = - ToNode(rndFind.m_CurNode); - m_ResolveProcessor->GetNodeHelper()->m_iCreateCount = 1; - } - bool bCreate = - m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( - rndFind.m_wsName, rndFind.m_wsCondition, - nStart == wsExpression.GetLength(), this); - if (bCreate) { - continue; - } else { - break; - } - } else { - break; - } - } - findNodes.Copy(retNodes); - rndFind.m_Nodes.RemoveAll(); - if (nLevel == 0) { - dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); - } - nLevel++; - } - if (!bNextCreate) { - resolveNodeRS.dwFlags = rndFind.m_dwFlag; - if (nNodes > 0) { - resolveNodeRS.nodes.Append(findNodes); - } - if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute) { - resolveNodeRS.pScriptAttribute = rndFind.m_pScriptAttribute; - return 1; - } - } - if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind | - XFA_RESOLVENODE_BindNew)) { - m_ResolveProcessor->SetResultCreateNode(resolveNodeRS, - rndFind.m_wsCondition); - if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) { - resolveNodeRS.dwFlags = XFA_RESOVENODE_RSTYPE_ExistNodes; - } - return resolveNodeRS.nodes.GetSize(); - } - return nNodes; -} - -void CXFA_ScriptContext::AddToCacheList(std::unique_ptr<CXFA_NodeList> pList) { - m_CacheList.push_back(std::move(pList)); -} - -CFXJSE_Value* CXFA_ScriptContext::GetJSValueFromMap(CXFA_Object* pObject) { - if (!pObject) - return nullptr; - if (pObject->IsNode()) - RunVariablesScript(pObject->AsNode()); - - auto iter = m_mapObjectToValue.find(pObject); - if (iter != m_mapObjectToValue.end()) - return iter->second.get(); - - std::unique_ptr<CFXJSE_Value> jsValue(new CFXJSE_Value(m_pIsolate)); - jsValue->SetObject(pObject, m_pJsClass); - CFXJSE_Value* pValue = jsValue.get(); - m_mapObjectToValue.insert(std::make_pair(pObject, std::move(jsValue))); - return pValue; -} -int32_t CXFA_ScriptContext::GetIndexByName(CXFA_Node* refNode) { - CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); - return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, - lpNodeHelper->NodeIsProperty(refNode), false); -} -int32_t CXFA_ScriptContext::GetIndexByClassName(CXFA_Node* refNode) { - CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); - return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, - lpNodeHelper->NodeIsProperty(refNode), true); -} -void CXFA_ScriptContext::GetSomExpression(CXFA_Node* refNode, - CFX_WideString& wsExpression) { - CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); - lpNodeHelper->GetNameExpression(refNode, wsExpression, true, - XFA_LOGIC_Transparent); -} -void CXFA_ScriptContext::SetNodesOfRunScript(CXFA_NodeArray* pArray) { - m_pScriptNodeArray = pArray; -} -void CXFA_ScriptContext::AddNodesOfRunScript(const CXFA_NodeArray& nodes) { - if (!m_pScriptNodeArray) - return; - if (nodes.GetSize() > 0) - m_pScriptNodeArray->Copy(nodes); -} -void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) { - if (!m_pScriptNodeArray) - return; - if (m_pScriptNodeArray->Find(pNode) == -1) - m_pScriptNodeArray->Add(pNode); -} diff --git a/xfa/fxfa/parser/cxfa_scriptcontext.h b/xfa/fxfa/parser/cxfa_scriptcontext.h deleted file mode 100644 index 6d4f73a632f35e1ec5f00dbc1293b1011834dafc..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_scriptcontext.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_CXFA_SCRIPTCONTEXT_H_ -#define XFA_FXFA_PARSER_CXFA_SCRIPTCONTEXT_H_ - -#include <map> -#include <memory> -#include <vector> - -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/fm2js/xfa_fm2jscontext.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" - -#define XFA_RESOLVENODE_TagName 0x0002 - -class CXFA_ResolveProcessor; - -class CXFA_ScriptContext { - public: - explicit CXFA_ScriptContext(CXFA_Document* pDocument); - ~CXFA_ScriptContext(); - - void Initialize(v8::Isolate* pIsolate); - void SetEventParam(CXFA_EventParam param) { m_eventParam = param; } - CXFA_EventParam* GetEventParam() { return &m_eventParam; } - bool RunScript(XFA_SCRIPTLANGTYPE eScriptType, - const CFX_WideStringC& wsScript, - CFXJSE_Value* pRetValue, - CXFA_Object* pThisObject = nullptr); - - int32_t ResolveObjects(CXFA_Object* refNode, - const CFX_WideStringC& wsExpression, - XFA_RESOLVENODE_RS& resolveNodeRS, - uint32_t dwStyles = XFA_RESOLVENODE_Children, - CXFA_Node* bindNode = nullptr); - CFXJSE_Value* GetJSValueFromMap(CXFA_Object* pObject); - void AddToCacheList(std::unique_ptr<CXFA_NodeList> pList); - CXFA_Object* GetThisObject() const { return m_pThisObject; } - v8::Isolate* GetRuntime() const { return m_pIsolate; } - - int32_t GetIndexByName(CXFA_Node* refNode); - int32_t GetIndexByClassName(CXFA_Node* refNode); - void GetSomExpression(CXFA_Node* refNode, CFX_WideString& wsExpression); - - void SetNodesOfRunScript(CXFA_NodeArray* pArray); - void AddNodesOfRunScript(const CXFA_NodeArray& nodes); - void AddNodesOfRunScript(CXFA_Node* pNode); - CFXJSE_Class* GetJseNormalClass(); - - void SetRunAtType(XFA_ATTRIBUTEENUM eRunAt) { m_eRunAtType = eRunAt; } - bool IsRunAtClient() { return m_eRunAtType != XFA_ATTRIBUTEENUM_Server; } - bool QueryNodeByFlag(CXFA_Node* refNode, - const CFX_WideStringC& propname, - CFXJSE_Value* pValue, - uint32_t dwFlag, - bool bSetting); - bool QueryVariableValue(CXFA_Node* pScriptNode, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue, - bool bGetter); - bool QueryBuiltinValue(const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue); - static void GlobalPropertyGetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue); - static void GlobalPropertySetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue); - static void NormalPropertyGetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue); - static void NormalPropertySetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - CFXJSE_Value* pValue); - static void NormalMethodCall(CFXJSE_Value* hThis, - const CFX_ByteStringC& szFuncName, - CFXJSE_Arguments& args); - static int32_t NormalPropTypeGetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - bool bQueryIn); - static int32_t GlobalPropTypeGetter(CFXJSE_Value* pObject, - const CFX_ByteStringC& szPropName, - bool bQueryIn); - bool RunVariablesScript(CXFA_Node* pScriptNode); - CXFA_Object* GetVariablesThis(CXFA_Object* pObject, bool bScriptNode = false); - bool IsStrictScopeInJavaScript(); - XFA_SCRIPTLANGTYPE GetType(); - CXFA_NodeArray& GetUpObjectArray() { return m_upObjectArray; } - CXFA_Document* GetDocument() const { return m_pDocument; } - - static CXFA_Object* ToObject(CFXJSE_Value* pValue, CFXJSE_Class* pClass); - - private: - void DefineJsContext(); - CFXJSE_Context* CreateVariablesContext(CXFA_Node* pScriptNode, - CXFA_Node* pSubform); - void DefineJsClass(); - void RemoveBuiltInObjs(CFXJSE_Context* pContext) const; - - CXFA_Document* m_pDocument; - std::unique_ptr<CFXJSE_Context> m_JsContext; - v8::Isolate* m_pIsolate; - CFXJSE_Class* m_pJsClass; - XFA_SCRIPTLANGTYPE m_eScriptType; - std::map<CXFA_Object*, std::unique_ptr<CFXJSE_Value>> m_mapObjectToValue; - std::map<CXFA_Object*, CFXJSE_Context*> m_mapVariableToContext; - CXFA_EventParam m_eventParam; - CXFA_NodeArray m_upObjectArray; - // CacheList holds the NodeList items so we can clean them up when we're done. - std::vector<std::unique_ptr<CXFA_NodeList>> m_CacheList; - CXFA_NodeArray* m_pScriptNodeArray; - std::unique_ptr<CXFA_ResolveProcessor> m_ResolveProcessor; - std::unique_ptr<CXFA_FM2JSContext> m_FM2JSContext; - CXFA_Object* m_pThisObject; - uint32_t m_dwBuiltInInFlags; - XFA_ATTRIBUTEENUM m_eRunAtType; -}; - -#endif // XFA_FXFA_PARSER_CXFA_SCRIPTCONTEXT_H_ diff --git a/xfa/fxfa/parser/cxfa_scriptmodel.cpp b/xfa/fxfa/parser/cxfa_scriptmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..868dac5dc70279f3ab5fee4e152d4c0c5458eabb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_scriptmodel.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_scriptmodel.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"scriptModel"; + +} // namespace + +CXFA_ScriptModel::CXFA_ScriptModel(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::ScriptModel, + nullptr, + kAttributeData, + kName) {} + +CXFA_ScriptModel::~CXFA_ScriptModel() {} diff --git a/xfa/fxfa/parser/cxfa_scriptmodel.h b/xfa/fxfa/parser/cxfa_scriptmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..40bc96ebc8dfa52e689ba569fb35c3a9b7081341 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_scriptmodel.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SCRIPTMODEL_H_ +#define XFA_FXFA_PARSER_CXFA_SCRIPTMODEL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ScriptModel : public CXFA_Node { + public: + CXFA_ScriptModel(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ScriptModel() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SCRIPTMODEL_H_ diff --git a/xfa/fxfa/parser/cxfa_select.cpp b/xfa/fxfa/parser/cxfa_select.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92eca0729f5072bfe477c72f0b9507970850ada1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_select.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_select.h" + +#include "fxjs/xfa/cjx_select.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"select"; + +} // namespace + +CXFA_Select::CXFA_Select(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::Select, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Select>(this)) {} + +CXFA_Select::~CXFA_Select() {} diff --git a/xfa/fxfa/parser/cxfa_select.h b/xfa/fxfa/parser/cxfa_select.h new file mode 100644 index 0000000000000000000000000000000000000000..76651e07c9aa31ec24fe62470898c79a653d2e88 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_select.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SELECT_H_ +#define XFA_FXFA_PARSER_CXFA_SELECT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Select : public CXFA_Node { + public: + CXFA_Select(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Select() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SELECT_H_ diff --git a/xfa/fxfa/parser/cxfa_setproperty.cpp b/xfa/fxfa/parser/cxfa_setproperty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85d631b098560c66ad4597edb1d8001148560b77 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_setproperty.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_setproperty.h" + +#include "fxjs/xfa/cjx_setproperty.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Connection, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Target, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"setProperty"; + +} // namespace + +CXFA_SetProperty::CXFA_SetProperty(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::SetProperty, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SetProperty>(this)) {} + +CXFA_SetProperty::~CXFA_SetProperty() {} diff --git a/xfa/fxfa/parser/cxfa_setproperty.h b/xfa/fxfa/parser/cxfa_setproperty.h new file mode 100644 index 0000000000000000000000000000000000000000..3f8f4304659176b41b5770763f9750bfb45edd4c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_setproperty.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SETPROPERTY_H_ +#define XFA_FXFA_PARSER_CXFA_SETPROPERTY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SetProperty : public CXFA_Node { + public: + CXFA_SetProperty(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SetProperty() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SETPROPERTY_H_ diff --git a/xfa/fxfa/parser/cxfa_severity.cpp b/xfa/fxfa/parser/cxfa_severity.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53a91e8f316d8c04fc9483e78f162a81477372b8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_severity.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_severity.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"severity"; + +} // namespace + +CXFA_Severity::CXFA_Severity(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Severity, + nullptr, + kAttributeData, + kName) {} + +CXFA_Severity::~CXFA_Severity() {} diff --git a/xfa/fxfa/parser/cxfa_severity.h b/xfa/fxfa/parser/cxfa_severity.h new file mode 100644 index 0000000000000000000000000000000000000000..711445557a8613387b47516eff57843e0f0c508b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_severity.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SEVERITY_H_ +#define XFA_FXFA_PARSER_CXFA_SEVERITY_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Severity : public CXFA_Node { + public: + CXFA_Severity(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Severity() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SEVERITY_H_ diff --git a/xfa/fxfa/parser/cxfa_sharptext.cpp b/xfa/fxfa/parser/cxfa_sharptext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5300dfc1c0976e5014e7be1b88f043da9e65ec78 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sharptext.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_sharptext.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Value, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"#text"; + +} // namespace + +CXFA_Sharptext::CXFA_Sharptext(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | + XFA_XDPPACKET_LocaleSet | XFA_XDPPACKET_ConnectionSet | + XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeV, + XFA_Element::Sharptext, + nullptr, + kAttributeData, + kName) {} + +CXFA_Sharptext::~CXFA_Sharptext() {} diff --git a/xfa/fxfa/parser/cxfa_sharptext.h b/xfa/fxfa/parser/cxfa_sharptext.h new file mode 100644 index 0000000000000000000000000000000000000000..89a050b70b920d02eff1bb2193b0510d09e85ea0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sharptext.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SHARPTEXT_H_ +#define XFA_FXFA_PARSER_CXFA_SHARPTEXT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Sharptext : public CXFA_Node { + public: + CXFA_Sharptext(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Sharptext() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SHARPTEXT_H_ diff --git a/xfa/fxfa/parser/cxfa_sharpxhtml.cpp b/xfa/fxfa/parser/cxfa_sharpxhtml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51829b7745cc755596a516b9006ded6a0c770b97 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sharpxhtml.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_sharpxhtml.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Value, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"#xHTML"; + +} // namespace + +CXFA_SharpxHTML::CXFA_SharpxHTML(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | + XFA_XDPPACKET_LocaleSet | XFA_XDPPACKET_ConnectionSet | + XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeV, + XFA_Element::SharpxHTML, + nullptr, + kAttributeData, + kName) {} + +CXFA_SharpxHTML::~CXFA_SharpxHTML() {} diff --git a/xfa/fxfa/parser/cxfa_sharpxhtml.h b/xfa/fxfa/parser/cxfa_sharpxhtml.h new file mode 100644 index 0000000000000000000000000000000000000000..3f6cf793e226e8f5254579de95857480309691b6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sharpxhtml.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SHARPXHTML_H_ +#define XFA_FXFA_PARSER_CXFA_SHARPXHTML_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SharpxHTML : public CXFA_Node { + public: + CXFA_SharpxHTML(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SharpxHTML() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SHARPXHTML_H_ diff --git a/xfa/fxfa/parser/cxfa_sharpxml.cpp b/xfa/fxfa/parser/cxfa_sharpxml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ce220efa6ed489729f6abf918ddb600d42199d7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sharpxml.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_sharpxml.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Value, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"#xml"; + +} // namespace + +CXFA_Sharpxml::CXFA_Sharpxml(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeV, + XFA_Element::Sharpxml, + nullptr, + kAttributeData, + kName) {} + +CXFA_Sharpxml::~CXFA_Sharpxml() {} diff --git a/xfa/fxfa/parser/cxfa_sharpxml.h b/xfa/fxfa/parser/cxfa_sharpxml.h new file mode 100644 index 0000000000000000000000000000000000000000..a065857a42a9dc84c8df844df4120e4c0d6dd955 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sharpxml.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SHARPXML_H_ +#define XFA_FXFA_PARSER_CXFA_SHARPXML_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Sharpxml : public CXFA_Node { + public: + CXFA_Sharpxml(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Sharpxml() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SHARPXML_H_ diff --git a/xfa/fxfa/parser/cxfa_signature.cpp b/xfa/fxfa/parser/cxfa_signature.cpp new file mode 100644 index 0000000000000000000000000000000000000000..baee04401705ac042bd9bb5190fba2c5e4a826dc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signature.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_signature.h" + +#include "fxjs/xfa/cjx_signature.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Margin, 1, 0}, {XFA_Element::Filter, 1, 0}, + {XFA_Element::Border, 1, 0}, {XFA_Element::Manifest, 1, 0}, + {XFA_Element::Extras, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::PDF1_3}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"signature"; + +} // namespace + +CXFA_Signature::CXFA_Signature(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Signature, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Signature>(this)) {} + +CXFA_Signature::~CXFA_Signature() {} diff --git a/xfa/fxfa/parser/cxfa_signature.h b/xfa/fxfa/parser/cxfa_signature.h new file mode 100644 index 0000000000000000000000000000000000000000..f55ce5a1156349a914719f3c835647edb7f17912 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signature.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SIGNATURE_H_ +#define XFA_FXFA_PARSER_CXFA_SIGNATURE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Signature : public CXFA_Node { + public: + CXFA_Signature(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Signature() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SIGNATURE_H_ diff --git a/xfa/fxfa/parser/cxfa_signatureproperties.cpp b/xfa/fxfa/parser/cxfa_signatureproperties.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c710cb4bf0d0cb2c32d7fb93df0fa6fa553bd3b6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signatureproperties.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_signatureproperties.h" + +#include "fxjs/xfa/cjx_signatureproperties.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"signatureProperties"; + +} // namespace + +CXFA_SignatureProperties::CXFA_SignatureProperties(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::SignatureProperties, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SignatureProperties>(this)) {} + +CXFA_SignatureProperties::~CXFA_SignatureProperties() {} diff --git a/xfa/fxfa/parser/cxfa_signatureproperties.h b/xfa/fxfa/parser/cxfa_signatureproperties.h new file mode 100644 index 0000000000000000000000000000000000000000..800b78030325408b5f6de22ecf3b2a5ad38557fe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signatureproperties.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SIGNATUREPROPERTIES_H_ +#define XFA_FXFA_PARSER_CXFA_SIGNATUREPROPERTIES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SignatureProperties : public CXFA_Node { + public: + CXFA_SignatureProperties(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SignatureProperties() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SIGNATUREPROPERTIES_H_ diff --git a/xfa/fxfa/parser/cxfa_signdata.cpp b/xfa/fxfa/parser/cxfa_signdata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..796ae5c72b52cbd5d82b97ff7d50e21a2e3b5398 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signdata.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_signdata.h" + +#include "fxjs/xfa/cjx_signdata.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Filter, 1, 0}, + {XFA_Element::Manifest, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Operation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Sign}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Target, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"signData"; + +} // namespace + +CXFA_SignData::CXFA_SignData(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::SignData, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SignData>(this)) {} + +CXFA_SignData::~CXFA_SignData() {} diff --git a/xfa/fxfa/parser/cxfa_signdata.h b/xfa/fxfa/parser/cxfa_signdata.h new file mode 100644 index 0000000000000000000000000000000000000000..3ad39f5fac15741823e273abaed365cb1b161a2b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signdata.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SIGNDATA_H_ +#define XFA_FXFA_PARSER_CXFA_SIGNDATA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SignData : public CXFA_Node { + public: + CXFA_SignData(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SignData() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SIGNDATA_H_ diff --git a/xfa/fxfa/parser/cxfa_signing.cpp b/xfa/fxfa/parser/cxfa_signing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..251e2940556aabf87375cb1c79e3c9a1ca6b8e4f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signing.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_signing.h" + +#include "fxjs/xfa/cjx_signing.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"signing"; + +} // namespace + +CXFA_Signing::CXFA_Signing(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Signing, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Signing>(this)) {} + +CXFA_Signing::~CXFA_Signing() {} diff --git a/xfa/fxfa/parser/cxfa_signing.h b/xfa/fxfa/parser/cxfa_signing.h new file mode 100644 index 0000000000000000000000000000000000000000..6df9a1871ddd584447bceb7c2b3425e5d042ebec --- /dev/null +++ b/xfa/fxfa/parser/cxfa_signing.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SIGNING_H_ +#define XFA_FXFA_PARSER_CXFA_SIGNING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Signing : public CXFA_Node { + public: + CXFA_Signing(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Signing() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SIGNING_H_ diff --git a/xfa/fxfa/parser/cxfa_silentprint.cpp b/xfa/fxfa/parser/cxfa_silentprint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca0cf9f6a7444539a9233704f5f5d700e1cc8b81 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_silentprint.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_silentprint.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::AddSilentPrint, 1, 0}, + {XFA_Element::PrinterName, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"silentPrint"; + +} // namespace + +CXFA_SilentPrint::CXFA_SilentPrint(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::SilentPrint, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_SilentPrint::~CXFA_SilentPrint() {} diff --git a/xfa/fxfa/parser/cxfa_silentprint.h b/xfa/fxfa/parser/cxfa_silentprint.h new file mode 100644 index 0000000000000000000000000000000000000000..6ef5fcf97be2ffd1104a75b0385f385c5bf18b0d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_silentprint.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SILENTPRINT_H_ +#define XFA_FXFA_PARSER_CXFA_SILENTPRINT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SilentPrint : public CXFA_Node { + public: + CXFA_SilentPrint(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SilentPrint() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SILENTPRINT_H_ diff --git a/xfa/fxfa/parser/cxfa_simple_parser.cpp b/xfa/fxfa/parser/cxfa_simple_parser.cpp index 4a6956de1984130ec1b5ab7105c5d5a240697b7e..1864532f287a653b7edbb2c414d4d52a09e36d66 100644 --- a/xfa/fxfa/parser/cxfa_simple_parser.cpp +++ b/xfa/fxfa/parser/cxfa_simple_parser.cpp @@ -7,39 +7,119 @@ #include "xfa/fxfa/parser/cxfa_simple_parser.h" #include <utility> - -#include "core/fxcrt/fx_ext.h" +#include <vector> + +#include "core/fxcrt/cfx_checksumcontext.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmldoc.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmlparser.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" -#include "xfa/fgas/crt/fgas_codepage.h" #include "xfa/fxfa/fxfa.h" #include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_widetextread.h" -#include "xfa/fxfa/parser/cxfa_xml_parser.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_subform.h" +#include "xfa/fxfa/parser/cxfa_template.h" #include "xfa/fxfa/parser/xfa_basic_data.h" #include "xfa/fxfa/parser/xfa_utils.h" -#include "xfa/fxfa/xfa_checksum.h" namespace { -CFDE_XMLNode* GetDocumentNode(CFDE_XMLDoc* pXMLDoc, - bool bVerifyWellFormness = false) { +struct PacketInfo { + uint32_t hash; + const wchar_t* name; + XFA_PacketType packet_type; + const wchar_t* uri; + uint32_t flags; +}; +const PacketInfo PacketData[] = { + {0x0, nullptr, XFA_PacketType::User, nullptr, + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, + {0x811929d, L"sourceSet", XFA_PacketType::SourceSet, + L"http://www.xfa.org/schema/xfa-source-set/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0xb843dba, L"pdf", XFA_PacketType::Pdf, L"http://ns.adobe.com/xdp/pdf/", + XFA_XDPPACKET_FLAGS_COMPLETEMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0xc56afbf, L"xdc", XFA_PacketType::Xdc, L"http://www.xfa.org/schema/xdc/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0xc56afcc, L"xdp", XFA_PacketType::Xdp, L"http://ns.adobe.com/xdp/", + XFA_XDPPACKET_FLAGS_COMPLETEMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0x132a8fbc, L"xmpmeta", XFA_PacketType::Xmpmeta, + L"http://ns.adobe.com/xmpmeta/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, + {0x48d004a8, L"xfdf", XFA_PacketType::Xfdf, L"http://ns.adobe.com/xfdf/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0x4e1e39b6, L"config", XFA_PacketType::Config, + L"http://www.xfa.org/schema/xci/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0x5473b6dc, L"localeSet", XFA_PacketType::LocaleSet, + L"http://www.xfa.org/schema/xfa-locale-set/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0x6038580a, L"stylesheet", XFA_PacketType::Stylesheet, + L"http://www.w3.org/1999/XSL/Transform", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, + {0x803550fc, L"template", XFA_PacketType::Template, + L"http://www.xfa.org/schema/xfa-template/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0x8b036f32, L"signature", XFA_PacketType::Signature, + L"http://www.w3.org/2000/09/xmldsig#", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0x99b95079, L"datasets", XFA_PacketType::Datasets, + L"http://www.xfa.org/schema/xfa-data/", + XFA_XDPPACKET_FLAGS_PREFIXMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0xcd309ff4, L"form", XFA_PacketType::Form, + L"http://www.xfa.org/schema/xfa-form/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, + {0xe14c801c, L"connectionSet", XFA_PacketType::ConnectionSet, + L"http://www.xfa.org/schema/xfa-connection-set/", + XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, +}; + +const PacketInfo* GetPacketByIndex(XFA_PacketType ePacket) { + return PacketData + static_cast<uint8_t>(ePacket); +} + +const PacketInfo* GetPacketByName(const WideStringView& wsName) { + if (wsName.IsEmpty()) + return nullptr; + + uint32_t hash = FX_HashCode_GetW(wsName, false); + auto* elem = std::lower_bound( + std::begin(PacketData), std::end(PacketData), hash, + [](const PacketInfo& a, uint32_t hash) { return a.hash < hash; }); + if (elem != std::end(PacketData) && elem->hash == hash) + return elem; + return nullptr; +} + +CFX_XMLNode* GetDocumentNode(CFX_XMLDoc* pXMLDoc, + bool bVerifyWellFormness = false) { if (!pXMLDoc) return nullptr; - for (CFDE_XMLNode* pXMLNode = - pXMLDoc->GetRoot()->GetNodeItem(CFDE_XMLNode::FirstChild); - pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pXMLNode->GetType() != FDE_XMLNODE_Element) + for (CFX_XMLNode* pXMLNode = + pXMLDoc->GetRoot()->GetNodeItem(CFX_XMLNode::FirstChild); + pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pXMLNode->GetType() != FX_XMLNODE_Element) continue; if (!bVerifyWellFormness) return pXMLNode; - for (CFDE_XMLNode* pNextNode = - pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling); + for (CFX_XMLNode* pNextNode = + pXMLNode->GetNodeItem(CFX_XMLNode::NextSibling); pNextNode; - pNextNode = pNextNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (pNextNode->GetType() == FDE_XMLNODE_Element) + pNextNode = pNextNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (pNextNode->GetType() == FX_XMLNODE_Element) return nullptr; } return pXMLNode; @@ -47,101 +127,97 @@ CFDE_XMLNode* GetDocumentNode(CFDE_XMLDoc* pXMLDoc, return nullptr; } -void GetElementTagNamespaceURI(CFDE_XMLElement* pElement, - CFX_WideString& wsNamespaceURI) { - CFX_WideString wsNodeStr; - pElement->GetNamespacePrefix(wsNodeStr); - if (!XFA_FDEExtension_ResolveNamespaceQualifier( - pElement, wsNodeStr.AsStringC(), wsNamespaceURI)) { - wsNamespaceURI.clear(); +WideString GetElementTagNamespaceURI(CFX_XMLElement* pElement) { + WideString wsNodeStr = pElement->GetNamespacePrefix(); + WideString wsNamespaceURI; + if (!XFA_FDEExtension_ResolveNamespaceQualifier(pElement, wsNodeStr, + &wsNamespaceURI)) { + return WideString(); } + return wsNamespaceURI; } -bool MatchNodeName(CFDE_XMLNode* pNode, - const CFX_WideStringC& wsLocalTagName, - const CFX_WideStringC& wsNamespaceURIPrefix, +bool MatchNodeName(CFX_XMLNode* pNode, + const WideStringView& wsLocalTagName, + const WideStringView& wsNamespaceURIPrefix, uint32_t eMatchFlags = XFA_XDPPACKET_FLAGS_NOMATCH) { - if (!pNode || pNode->GetType() != FDE_XMLNODE_Element) + if (!pNode || pNode->GetType() != FX_XMLNODE_Element) return false; - CFDE_XMLElement* pElement = reinterpret_cast<CFDE_XMLElement*>(pNode); - CFX_WideString wsNodeStr; - pElement->GetLocalTagName(wsNodeStr); + CFX_XMLElement* pElement = reinterpret_cast<CFX_XMLElement*>(pNode); + WideString wsNodeStr = pElement->GetLocalTagName(); if (wsNodeStr != wsLocalTagName) return false; - GetElementTagNamespaceURI(pElement, wsNodeStr); + wsNodeStr = GetElementTagNamespaceURI(pElement); if (eMatchFlags & XFA_XDPPACKET_FLAGS_NOMATCH) return true; if (eMatchFlags & XFA_XDPPACKET_FLAGS_PREFIXMATCH) { return wsNodeStr.Left(wsNamespaceURIPrefix.GetLength()) == wsNamespaceURIPrefix; } + return wsNodeStr == wsNamespaceURIPrefix; } -bool GetAttributeLocalName(const CFX_WideStringC& wsAttributeName, - CFX_WideString& wsLocalAttrName) { - CFX_WideString wsAttrName(wsAttributeName); - FX_STRSIZE iFind = wsAttrName.Find(L':', 0); - if (iFind < 0) { +bool GetAttributeLocalName(const WideStringView& wsAttributeName, + WideString& wsLocalAttrName) { + WideString wsAttrName(wsAttributeName); + auto pos = wsAttrName.Find(L':', 0); + if (!pos.has_value()) { wsLocalAttrName = wsAttrName; return false; } - wsLocalAttrName = wsAttrName.Right(wsAttrName.GetLength() - iFind - 1); + wsLocalAttrName = wsAttrName.Right(wsAttrName.GetLength() - pos.value() - 1); return true; } -bool ResolveAttribute(CFDE_XMLElement* pElement, - const CFX_WideStringC& wsAttributeName, - CFX_WideString& wsLocalAttrName, - CFX_WideString& wsNamespaceURI) { - CFX_WideString wsAttrName(wsAttributeName); - CFX_WideString wsNSPrefix; - if (GetAttributeLocalName(wsAttributeName, wsLocalAttrName)) { - wsNSPrefix = wsAttrName.Left(wsAttributeName.GetLength() - +bool ResolveAttribute(CFX_XMLElement* pElement, + const WideString& wsAttrName, + WideString& wsLocalAttrName, + WideString& wsNamespaceURI) { + WideString wsNSPrefix; + if (GetAttributeLocalName(wsAttrName.AsStringView(), wsLocalAttrName)) { + wsNSPrefix = wsAttrName.Left(wsAttrName.GetLength() - wsLocalAttrName.GetLength() - 1); } if (wsLocalAttrName == L"xmlns" || wsNSPrefix == L"xmlns" || wsNSPrefix == L"xml") { return false; } - if (!XFA_FDEExtension_ResolveNamespaceQualifier( - pElement, wsNSPrefix.AsStringC(), wsNamespaceURI)) { + if (!XFA_FDEExtension_ResolveNamespaceQualifier(pElement, wsNSPrefix, + &wsNamespaceURI)) { wsNamespaceURI.clear(); return false; } return true; } -bool FindAttributeWithNS(CFDE_XMLElement* pElement, - const CFX_WideStringC& wsLocalAttributeName, - const CFX_WideStringC& wsNamespaceURIPrefix, - CFX_WideString& wsValue, +bool FindAttributeWithNS(CFX_XMLElement* pElement, + const WideStringView& wsLocalAttributeName, + const WideStringView& wsNamespaceURIPrefix, + WideString& wsValue, bool bMatchNSAsPrefix = false) { if (!pElement) return false; - CFX_WideString wsAttrName; - CFX_WideString wsAttrValue; - CFX_WideString wsAttrNS; - for (int32_t iAttrCount = pElement->CountAttributes(), i = 0; i < iAttrCount; - i++) { - pElement->GetAttribute(i, wsAttrName, wsAttrValue); - FX_STRSIZE iFind = wsAttrName.Find(L':', 0); - CFX_WideString wsNSPrefix; - if (iFind < 0) { - if (wsLocalAttributeName != wsAttrName) + WideString wsAttrNS; + for (auto it : pElement->GetAttributes()) { + auto pos = it.first.Find(L':', 0); + WideString wsNSPrefix; + if (!pos.has_value()) { + if (wsLocalAttributeName != it.first) continue; } else { if (wsLocalAttributeName != - wsAttrName.Right(wsAttrName.GetLength() - iFind - 1)) { + it.first.Right(it.first.GetLength() - pos.value() - 1)) { continue; } - wsNSPrefix = wsAttrName.Left(iFind); + wsNSPrefix = it.first.Left(pos.value()); } - if (!XFA_FDEExtension_ResolveNamespaceQualifier( - pElement, wsNSPrefix.AsStringC(), wsAttrNS)) { + + if (!XFA_FDEExtension_ResolveNamespaceQualifier(pElement, wsNSPrefix, + &wsAttrNS)) { continue; } if (bMatchNSAsPrefix) { @@ -153,232 +229,224 @@ bool FindAttributeWithNS(CFDE_XMLElement* pElement, if (wsAttrNS != wsNamespaceURIPrefix) continue; } - wsValue = wsAttrValue; + wsValue = it.second; return true; } return false; } -CFDE_XMLNode* GetDataSetsFromXDP(CFDE_XMLNode* pXMLDocumentNode) { - if (MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->pName, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->eFlags)) { +CFX_XMLNode* GetDataSetsFromXDP(CFX_XMLNode* pXMLDocumentNode) { + const PacketInfo* datasets_packet = + GetPacketByIndex(XFA_PacketType::Datasets); + if (MatchNodeName(pXMLDocumentNode, datasets_packet->name, + datasets_packet->uri, datasets_packet->flags)) { return pXMLDocumentNode; } - if (!MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_XDP)->pName, - XFA_GetPacketByIndex(XFA_PACKET_XDP)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_XDP)->eFlags)) { + + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Xdp); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) { return nullptr; } - for (CFDE_XMLNode* pDatasetsNode = - pXMLDocumentNode->GetNodeItem(CFDE_XMLNode::FirstChild); + + for (CFX_XMLNode* pDatasetsNode = + pXMLDocumentNode->GetNodeItem(CFX_XMLNode::FirstChild); pDatasetsNode; - pDatasetsNode = pDatasetsNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (!MatchNodeName(pDatasetsNode, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->pName, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->eFlags)) { - continue; + pDatasetsNode = pDatasetsNode->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (MatchNodeName(pDatasetsNode, datasets_packet->name, + datasets_packet->uri, datasets_packet->flags)) { + return pDatasetsNode; } - return pDatasetsNode; } return nullptr; } -bool IsStringAllWhitespace(CFX_WideString wsText) { +bool IsStringAllWhitespace(WideString wsText) { wsText.TrimRight(L"\x20\x9\xD\xA"); return wsText.IsEmpty(); } -void ConvertXMLToPlainText(CFDE_XMLElement* pRootXMLNode, - CFX_WideString& wsOutput) { - for (CFDE_XMLNode* pXMLChild = - pRootXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); +void ConvertXMLToPlainText(CFX_XMLElement* pRootXMLNode, WideString& wsOutput) { + for (CFX_XMLNode* pXMLChild = + pRootXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { switch (pXMLChild->GetType()) { - case FDE_XMLNODE_Element: { - CFX_WideString wsTextData; - static_cast<CFDE_XMLElement*>(pXMLChild)->GetTextData(wsTextData); + case FX_XMLNODE_Element: { + WideString wsTextData = + static_cast<CFX_XMLElement*>(pXMLChild)->GetTextData(); wsTextData += L"\n"; wsOutput += wsTextData; break; } - case FDE_XMLNODE_Text: { - CFX_WideString wsText; - static_cast<CFDE_XMLText*>(pXMLChild)->GetText(wsText); + case FX_XMLNODE_Text: + case FX_XMLNODE_CharData: { + WideString wsText = static_cast<CFX_XMLText*>(pXMLChild)->GetText(); if (IsStringAllWhitespace(wsText)) continue; wsOutput = wsText; break; } - case FDE_XMLNODE_CharData: { - CFX_WideString wsCharData; - static_cast<CFDE_XMLCharData*>(pXMLChild)->GetCharData(wsCharData); - if (IsStringAllWhitespace(wsCharData)) - continue; - - wsOutput = wsCharData; - break; - } default: - ASSERT(false); + NOTREACHED(); break; } } } -const XFA_PACKETINFO* GetPacketByName(const CFX_WideStringC& wsName) { - if (wsName.IsEmpty()) - return nullptr; +WideString GetPlainTextFromRichText(CFX_XMLNode* pXMLNode) { + if (!pXMLNode) + return L""; + + WideString wsPlainText; + switch (pXMLNode->GetType()) { + case FX_XMLNODE_Element: { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode); + WideString wsTag = pXMLElement->GetLocalTagName(); + uint32_t uTag = FX_HashCode_GetW(wsTag.AsStringView(), true); + if (uTag == 0x0001f714) { + wsPlainText += L"\n"; + } else if (uTag == 0x00000070) { + if (!wsPlainText.IsEmpty()) { + wsPlainText += L"\n"; + } + } else if (uTag == 0xa48ac63) { + if (!wsPlainText.IsEmpty() && + wsPlainText[wsPlainText.GetLength() - 1] != '\n') { + wsPlainText += L"\n"; + } + } + break; + } + case FX_XMLNODE_Text: + case FX_XMLNODE_CharData: { + WideString wsContent = static_cast<CFX_XMLText*>(pXMLNode)->GetText(); + wsPlainText += wsContent; + break; + } + default: + break; + } + for (CFX_XMLNode* pChildXML = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); + pChildXML; + pChildXML = pChildXML->GetNodeItem(CFX_XMLNode::NextSibling)) { + wsPlainText += GetPlainTextFromRichText(pChildXML); + } - uint32_t uHash = FX_HashCode_GetW(wsName, false); - int32_t iStart = 0; - int32_t iEnd = g_iXFAPacketCount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_PACKETINFO* pInfo = g_XFAPacketData + iMid; - if (uHash == pInfo->uHash) - return pInfo; - if (uHash < pInfo->uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return nullptr; + return wsPlainText; } } // namespace -bool XFA_RecognizeRichText(CFDE_XMLElement* pRichTextXMLNode) { - if (pRichTextXMLNode) { - CFX_WideString wsNamespaceURI; - GetElementTagNamespaceURI(pRichTextXMLNode, wsNamespaceURI); - if (wsNamespaceURI == L"http://www.w3.org/1999/xhtml") - return true; - } - return false; +bool XFA_RecognizeRichText(CFX_XMLElement* pRichTextXMLNode) { + return pRichTextXMLNode && GetElementTagNamespaceURI(pRichTextXMLNode) == + L"http://www.w3.org/1999/xhtml"; } -CXFA_SimpleParser::CXFA_SimpleParser(CXFA_Document* pFactory, - bool bDocumentParser) - : m_pXMLParser(nullptr), - m_pXMLDoc(nullptr), - m_pStream(nullptr), - m_pFileRead(nullptr), - m_pFactory(pFactory), - m_pRootNode(nullptr), - m_ePacketID(XFA_XDPPACKET_UNKNOWN), - m_bDocumentParser(bDocumentParser) {} +CXFA_SimpleParser::CXFA_SimpleParser() : m_bDocumentParser(true) {} + +CXFA_SimpleParser::CXFA_SimpleParser(CXFA_Document* pFactory) + : m_pFactory(pFactory), m_bDocumentParser(false) {} CXFA_SimpleParser::~CXFA_SimpleParser() {} void CXFA_SimpleParser::SetFactory(CXFA_Document* pFactory) { + ASSERT(m_bDocumentParser); m_pFactory = pFactory; } int32_t CXFA_SimpleParser::StartParse( - const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, - XFA_XDPPACKET ePacketID) { + const RetainPtr<IFX_SeekableStream>& pStream, + XFA_PacketType ePacketID) { CloseParser(); m_pFileRead = pStream; - m_pStream = IFGAS_Stream::CreateStream( - pStream, FX_STREAMACCESS_Read | FX_STREAMACCESS_Text); - if (!m_pStream) - return XFA_PARSESTATUS_StreamErr; - + m_pStream = pdfium::MakeRetain<CFX_SeekableStreamProxy>(pStream, false); uint16_t wCodePage = m_pStream->GetCodePage(); if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && wCodePage != FX_CODEPAGE_UTF8) { m_pStream->SetCodePage(FX_CODEPAGE_UTF8); } - m_pXMLDoc = pdfium::MakeUnique<CFDE_XMLDoc>(); + m_pXMLDoc = pdfium::MakeUnique<CFX_XMLDoc>(); auto pNewParser = - pdfium::MakeUnique<CXFA_XMLParser>(m_pXMLDoc->GetRoot(), m_pStream); + pdfium::MakeUnique<CFX_XMLParser>(m_pXMLDoc->GetRoot(), m_pStream); m_pXMLParser = pNewParser.get(); if (!m_pXMLDoc->LoadXML(std::move(pNewParser))) return XFA_PARSESTATUS_StatusErr; + m_bParseStarted = true; m_ePacketID = ePacketID; return XFA_PARSESTATUS_Ready; } -int32_t CXFA_SimpleParser::DoParse(IFX_Pause* pPause) { - if (!m_pXMLDoc || m_ePacketID == XFA_XDPPACKET_UNKNOWN) +int32_t CXFA_SimpleParser::DoParse() { + if (!m_pXMLDoc || !m_bParseStarted) return XFA_PARSESTATUS_StatusErr; - int32_t iRet = m_pXMLDoc->DoLoad(pPause); + int32_t iRet = m_pXMLDoc->DoLoad(); if (iRet < 0) return XFA_PARSESTATUS_SyntaxErr; if (iRet < 100) return iRet / 2; m_pRootNode = ParseAsXDPPacket(GetDocumentNode(m_pXMLDoc.get()), m_ePacketID); + m_pXMLParser.Release(); m_pXMLDoc->CloseXML(); m_pStream.Reset(); + if (!m_pRootNode) return XFA_PARSESTATUS_StatusErr; return XFA_PARSESTATUS_Done; } -int32_t CXFA_SimpleParser::ParseXMLData(const CFX_WideString& wsXML, - CFDE_XMLNode*& pXMLNode, - IFX_Pause* pPause) { +CFX_XMLNode* CXFA_SimpleParser::ParseXMLData(const ByteString& wsXML) { CloseParser(); - pXMLNode = nullptr; - m_pXMLDoc = pdfium::MakeUnique<CFDE_XMLDoc>(); - auto pStream = pdfium::MakeRetain<CXFA_WideTextRead>(wsXML); + m_pXMLDoc = pdfium::MakeUnique<CFX_XMLDoc>(); + + auto pStream = pdfium::MakeRetain<CFX_SeekableStreamProxy>( + const_cast<uint8_t*>(wsXML.raw_str()), wsXML.GetLength()); auto pParser = - pdfium::MakeUnique<CXFA_XMLParser>(m_pXMLDoc->GetRoot(), pStream); + pdfium::MakeUnique<CFX_XMLParser>(m_pXMLDoc->GetRoot(), pStream); pParser->m_dwCheckStatus = 0x03; if (!m_pXMLDoc->LoadXML(std::move(pParser))) - return XFA_PARSESTATUS_StatusErr; + return nullptr; - int32_t iRet = m_pXMLDoc->DoLoad(pPause); + int32_t iRet = m_pXMLDoc->DoLoad(); if (iRet < 0 || iRet >= 100) m_pXMLDoc->CloseXML(); - if (iRet < 0) - return XFA_PARSESTATUS_SyntaxErr; - if (iRet < 100) - return iRet / 2; - - pXMLNode = GetDocumentNode(m_pXMLDoc.get()); - return XFA_PARSESTATUS_Done; + return iRet < 100 ? nullptr : GetDocumentNode(m_pXMLDoc.get()); } void CXFA_SimpleParser::ConstructXFANode(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode) { - XFA_XDPPACKET ePacketID = (XFA_XDPPACKET)pXFANode->GetPacketID(); - if (ePacketID == XFA_XDPPACKET_Datasets) { + CFX_XMLNode* pXMLNode) { + XFA_PacketType ePacketID = pXFANode->GetPacketType(); + if (ePacketID == XFA_PacketType::Datasets) { if (pXFANode->GetElementType() == XFA_Element::DataValue) { - for (CFDE_XMLNode* pXMLChild = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); + for (CFX_XMLNode* pXMLChild = + pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { - FDE_XMLNODETYPE eNodeType = pXMLChild->GetType(); - if (eNodeType == FDE_XMLNODE_Instruction) + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { + FX_XMLNODETYPE eNodeType = pXMLChild->GetType(); + if (eNodeType == FX_XMLNODE_Instruction) continue; - if (eNodeType == FDE_XMLNODE_Element) { - CXFA_Node* pXFAChild = m_pFactory->CreateNode(XFA_XDPPACKET_Datasets, - XFA_Element::DataValue); + if (eNodeType == FX_XMLNODE_Element) { + CXFA_Node* pXFAChild = m_pFactory->CreateNode( + XFA_PacketType::Datasets, XFA_Element::DataValue); if (!pXFAChild) return; - CFX_WideString wsNodeStr; - CFDE_XMLElement* child = static_cast<CFDE_XMLElement*>(pXMLChild); - child->GetLocalTagName(wsNodeStr); - pXFAChild->SetCData(XFA_ATTRIBUTE_Name, wsNodeStr); - CFX_WideString wsChildValue; - XFA_GetPlainTextFromRichText(child, wsChildValue); + CFX_XMLElement* child = static_cast<CFX_XMLElement*>(pXMLChild); + WideString wsNodeStr = child->GetLocalTagName(); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Name, wsNodeStr, false, + false); + WideString wsChildValue = GetPlainTextFromRichText(child); if (!wsChildValue.IsEmpty()) - pXFAChild->SetCData(XFA_ATTRIBUTE_Value, wsChildValue); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Value, wsChildValue, + false, false); - pXFANode->InsertChild(pXFAChild); + pXFANode->InsertChild(pXFAChild, nullptr); pXFAChild->SetXMLMappingNode(pXMLChild); pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); break; @@ -400,318 +468,282 @@ CXFA_Node* CXFA_SimpleParser::GetRootNode() const { return m_pRootNode; } -CFDE_XMLDoc* CXFA_SimpleParser::GetXMLDoc() const { +CFX_XMLDoc* CXFA_SimpleParser::GetXMLDoc() const { return m_pXMLDoc.get(); } -bool XFA_FDEExtension_ResolveNamespaceQualifier( - CFDE_XMLElement* pNode, - const CFX_WideStringC& wsQualifier, - CFX_WideString& wsNamespaceURI) { - if (!pNode) - return false; - - CFDE_XMLNode* pFakeRoot = pNode->GetNodeItem(CFDE_XMLNode::Root); - CFX_WideString wsNSAttribute; - bool bRet = false; - if (wsQualifier.IsEmpty()) { - wsNSAttribute = L"xmlns"; - bRet = true; - } else { - wsNSAttribute = L"xmlns:" + wsQualifier; - } - for (; pNode != pFakeRoot; pNode = static_cast<CFDE_XMLElement*>( - pNode->GetNodeItem(CFDE_XMLNode::Parent))) { - if (pNode->GetType() != FDE_XMLNODE_Element) - continue; - - if (pNode->HasAttribute(wsNSAttribute.c_str())) { - pNode->GetString(wsNSAttribute.c_str(), wsNamespaceURI); - return true; - } - } - wsNamespaceURI.clear(); - return bRet; -} - -CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { +CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket(CFX_XMLNode* pXMLDocumentNode, + XFA_PacketType ePacketID) { switch (ePacketID) { - case XFA_XDPPACKET_UNKNOWN: - return nullptr; - case XFA_XDPPACKET_XDP: - return ParseAsXDPPacket_XDP(pXMLDocumentNode, ePacketID); - case XFA_XDPPACKET_Config: - return ParseAsXDPPacket_Config(pXMLDocumentNode, ePacketID); - case XFA_XDPPACKET_Template: - case XFA_XDPPACKET_Form: - return ParseAsXDPPacket_TemplateForm(pXMLDocumentNode, ePacketID); - case XFA_XDPPACKET_Datasets: - return ParseAsXDPPacket_Data(pXMLDocumentNode, ePacketID); - case XFA_XDPPACKET_Xdc: - return ParseAsXDPPacket_Xdc(pXMLDocumentNode, ePacketID); - case XFA_XDPPACKET_LocaleSet: - case XFA_XDPPACKET_ConnectionSet: - case XFA_XDPPACKET_SourceSet: - return ParseAsXDPPacket_LocaleConnectionSourceSet(pXMLDocumentNode, - ePacketID); + case XFA_PacketType::Xdp: + return ParseAsXDPPacket_XDP(pXMLDocumentNode); + case XFA_PacketType::Config: + return ParseAsXDPPacket_Config(pXMLDocumentNode); + case XFA_PacketType::Template: + return ParseAsXDPPacket_Template(pXMLDocumentNode); + case XFA_PacketType::Form: + return ParseAsXDPPacket_Form(pXMLDocumentNode); + case XFA_PacketType::Datasets: + return ParseAsXDPPacket_Data(pXMLDocumentNode); + case XFA_PacketType::Xdc: + return ParseAsXDPPacket_Xdc(pXMLDocumentNode); + case XFA_PacketType::LocaleSet: + return ParseAsXDPPacket_LocaleConnectionSourceSet( + pXMLDocumentNode, XFA_PacketType::LocaleSet, XFA_Element::LocaleSet); + case XFA_PacketType::ConnectionSet: + return ParseAsXDPPacket_LocaleConnectionSourceSet( + pXMLDocumentNode, XFA_PacketType::ConnectionSet, + XFA_Element::ConnectionSet); + case XFA_PacketType::SourceSet: + return ParseAsXDPPacket_LocaleConnectionSourceSet( + pXMLDocumentNode, XFA_PacketType::SourceSet, XFA_Element::SourceSet); default: - return ParseAsXDPPacket_User(pXMLDocumentNode, ePacketID); + return ParseAsXDPPacket_User(pXMLDocumentNode); } } CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_XDP( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { - if (!MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_XDP)->pName, - XFA_GetPacketByIndex(XFA_PACKET_XDP)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_XDP)->eFlags)) { + CFX_XMLNode* pXMLDocumentNode) { + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Xdp); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) { return nullptr; } + CXFA_Node* pXFARootNode = - m_pFactory->CreateNode(XFA_XDPPACKET_XDP, XFA_Element::Xfa); + m_pFactory->CreateNode(XFA_PacketType::Xdp, XFA_Element::Xfa); if (!pXFARootNode) return nullptr; m_pRootNode = pXFARootNode; - pXFARootNode->SetCData(XFA_ATTRIBUTE_Name, L"xfa"); - { - CFDE_XMLElement* pElement = static_cast<CFDE_XMLElement*>(pXMLDocumentNode); - int32_t iAttributeCount = pElement->CountAttributes(); - for (int32_t i = 0; i < iAttributeCount; i++) { - CFX_WideString wsAttriName, wsAttriValue; - pElement->GetAttribute(i, wsAttriName, wsAttriValue); - if (wsAttriName == L"uuid") - pXFARootNode->SetCData(XFA_ATTRIBUTE_Uuid, wsAttriValue); - else if (wsAttriName == L"timeStamp") - pXFARootNode->SetCData(XFA_ATTRIBUTE_TimeStamp, wsAttriValue); - } + pXFARootNode->JSObject()->SetCData(XFA_Attribute::Name, L"xfa", false, false); + + CFX_XMLElement* pElement = static_cast<CFX_XMLElement*>(pXMLDocumentNode); + for (auto it : pElement->GetAttributes()) { + if (it.first == L"uuid") + pXFARootNode->JSObject()->SetCData(XFA_Attribute::Uuid, it.second, false, + false); + else if (it.first == L"timeStamp") + pXFARootNode->JSObject()->SetCData(XFA_Attribute::TimeStamp, it.second, + false, false); } - CFDE_XMLNode* pXMLConfigDOMRoot = nullptr; + CFX_XMLNode* pXMLConfigDOMRoot = nullptr; CXFA_Node* pXFAConfigDOMRoot = nullptr; - { - for (CFDE_XMLNode* pChildItem = - pXMLDocumentNode->GetNodeItem(CFDE_XMLNode::FirstChild); - pChildItem; - pChildItem = pChildItem->GetNodeItem(CFDE_XMLNode::NextSibling)) { - const XFA_PACKETINFO* pPacketInfo = - XFA_GetPacketByIndex(XFA_PACKET_Config); - if (!MatchNodeName(pChildItem, pPacketInfo->pName, pPacketInfo->pURI, - pPacketInfo->eFlags)) { - continue; - } - if (pXFARootNode->GetFirstChildByName(pPacketInfo->uHash)) { - return nullptr; - } - pXMLConfigDOMRoot = pChildItem; - pXFAConfigDOMRoot = - ParseAsXDPPacket_Config(pXMLConfigDOMRoot, XFA_XDPPACKET_Config); - pXFARootNode->InsertChild(pXFAConfigDOMRoot, nullptr); + for (CFX_XMLNode* pChildItem = + pXMLDocumentNode->GetNodeItem(CFX_XMLNode::FirstChild); + pChildItem; + pChildItem = pChildItem->GetNodeItem(CFX_XMLNode::NextSibling)) { + const PacketInfo* pPacketInfo = GetPacketByIndex(XFA_PacketType::Config); + if (!MatchNodeName(pChildItem, pPacketInfo->name, pPacketInfo->uri, + pPacketInfo->flags)) { + continue; } + if (pXFARootNode->GetFirstChildByName(pPacketInfo->hash)) + return nullptr; + + pXMLConfigDOMRoot = pChildItem; + pXFAConfigDOMRoot = ParseAsXDPPacket_Config(pXMLConfigDOMRoot); + if (pXFAConfigDOMRoot) + pXFARootNode->InsertChild(pXFAConfigDOMRoot, nullptr); } - CFDE_XMLNode* pXMLDatasetsDOMRoot = nullptr; - CFDE_XMLNode* pXMLFormDOMRoot = nullptr; - CFDE_XMLNode* pXMLTemplateDOMRoot = nullptr; - { - for (CFDE_XMLNode* pChildItem = - pXMLDocumentNode->GetNodeItem(CFDE_XMLNode::FirstChild); - pChildItem; - pChildItem = pChildItem->GetNodeItem(CFDE_XMLNode::NextSibling)) { - if (!pChildItem || pChildItem->GetType() != FDE_XMLNODE_Element) - continue; - if (pChildItem == pXMLConfigDOMRoot) - continue; + CFX_XMLNode* pXMLDatasetsDOMRoot = nullptr; + CFX_XMLNode* pXMLFormDOMRoot = nullptr; + CFX_XMLNode* pXMLTemplateDOMRoot = nullptr; + for (CFX_XMLNode* pChildItem = + pXMLDocumentNode->GetNodeItem(CFX_XMLNode::FirstChild); + pChildItem; + pChildItem = pChildItem->GetNodeItem(CFX_XMLNode::NextSibling)) { + if (!pChildItem || pChildItem->GetType() != FX_XMLNODE_Element) + continue; + if (pChildItem == pXMLConfigDOMRoot) + continue; - CFDE_XMLElement* pElement = - reinterpret_cast<CFDE_XMLElement*>(pChildItem); - CFX_WideString wsPacketName; - pElement->GetLocalTagName(wsPacketName); - const XFA_PACKETINFO* pPacketInfo = - GetPacketByName(wsPacketName.AsStringC()); - if (pPacketInfo && pPacketInfo->pURI) { - if (!MatchNodeName(pElement, pPacketInfo->pName, pPacketInfo->pURI, - pPacketInfo->eFlags)) { - pPacketInfo = nullptr; - } + CFX_XMLElement* pElement = reinterpret_cast<CFX_XMLElement*>(pChildItem); + WideString wsPacketName = pElement->GetLocalTagName(); + const PacketInfo* pPacketInfo = + GetPacketByName(wsPacketName.AsStringView()); + if (pPacketInfo && pPacketInfo->uri) { + if (!MatchNodeName(pElement, pPacketInfo->name, pPacketInfo->uri, + pPacketInfo->flags)) { + pPacketInfo = nullptr; } - XFA_XDPPACKET ePacket = - pPacketInfo ? pPacketInfo->eName : XFA_XDPPACKET_USER; - if (ePacket == XFA_XDPPACKET_XDP) - continue; - if (ePacket == XFA_XDPPACKET_Datasets) { - if (pXMLDatasetsDOMRoot) - return nullptr; + } + XFA_PacketType ePacket = + pPacketInfo ? pPacketInfo->packet_type : XFA_PacketType::User; + if (ePacket == XFA_PacketType::Xdp) + continue; + if (ePacket == XFA_PacketType::Datasets) { + if (pXMLDatasetsDOMRoot) + return nullptr; - pXMLDatasetsDOMRoot = pElement; - } else if (ePacket == XFA_XDPPACKET_Form) { - if (pXMLFormDOMRoot) - return nullptr; + pXMLDatasetsDOMRoot = pElement; + } else if (ePacket == XFA_PacketType::Form) { + if (pXMLFormDOMRoot) + return nullptr; - pXMLFormDOMRoot = pElement; - } else if (ePacket == XFA_XDPPACKET_Template) { - if (pXMLTemplateDOMRoot) { - // Found a duplicate template packet. + pXMLFormDOMRoot = pElement; + } else if (ePacket == XFA_PacketType::Template) { + // Found a duplicate template packet. + if (pXMLTemplateDOMRoot) + return nullptr; + + CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket); + if (pPacketNode) { + pXMLTemplateDOMRoot = pElement; + pXFARootNode->InsertChild(pPacketNode, nullptr); + } + } else { + CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket); + if (pPacketNode) { + if (pPacketInfo && + (pPacketInfo->flags & XFA_XDPPACKET_FLAGS_SUPPORTONE) && + pXFARootNode->GetFirstChildByName(pPacketInfo->hash)) { return nullptr; } - CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket); - if (pPacketNode) { - pXMLTemplateDOMRoot = pElement; - pXFARootNode->InsertChild(pPacketNode); - } - } else { - CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket); - if (pPacketNode) { - if (pPacketInfo && - (pPacketInfo->eFlags & XFA_XDPPACKET_FLAGS_SUPPORTONE) && - pXFARootNode->GetFirstChildByName(pPacketInfo->uHash)) { - return nullptr; - } - pXFARootNode->InsertChild(pPacketNode); - } + pXFARootNode->InsertChild(pPacketNode, nullptr); } } } - if (!pXMLTemplateDOMRoot) { - // No template is found. + // No template is found. + if (!pXMLTemplateDOMRoot) return nullptr; - } + if (pXMLDatasetsDOMRoot) { CXFA_Node* pPacketNode = - ParseAsXDPPacket(pXMLDatasetsDOMRoot, XFA_XDPPACKET_Datasets); + ParseAsXDPPacket(pXMLDatasetsDOMRoot, XFA_PacketType::Datasets); if (pPacketNode) - pXFARootNode->InsertChild(pPacketNode); + pXFARootNode->InsertChild(pPacketNode, nullptr); } if (pXMLFormDOMRoot) { CXFA_Node* pPacketNode = - ParseAsXDPPacket(pXMLFormDOMRoot, XFA_XDPPACKET_Form); + ParseAsXDPPacket(pXMLFormDOMRoot, XFA_PacketType::Form); if (pPacketNode) - pXFARootNode->InsertChild(pPacketNode); + pXFARootNode->InsertChild(pPacketNode, nullptr); } + pXFARootNode->SetXMLMappingNode(pXMLDocumentNode); return pXFARootNode; } CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Config( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { - if (!MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_Config)->pName, - XFA_GetPacketByIndex(XFA_PACKET_Config)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Config)->eFlags)) { + CFX_XMLNode* pXMLDocumentNode) { + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Config); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) { return nullptr; } CXFA_Node* pNode = - m_pFactory->CreateNode(XFA_XDPPACKET_Config, XFA_Element::Config); + m_pFactory->CreateNode(XFA_PacketType::Config, XFA_Element::Config); if (!pNode) return nullptr; - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_Config)->pName); - if (!NormalLoader(pNode, pXMLDocumentNode, ePacketID, true)) + pNode->JSObject()->SetCData(XFA_Attribute::Name, packet->name, false, false); + if (!NormalLoader(pNode, pXMLDocumentNode, XFA_PacketType::Config, true)) return nullptr; pNode->SetXMLMappingNode(pXMLDocumentNode); return pNode; } -CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_TemplateForm( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { - CXFA_Node* pNode = nullptr; - if (ePacketID == XFA_XDPPACKET_Template) { - if (MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_Template)->pName, - XFA_GetPacketByIndex(XFA_PACKET_Template)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Template)->eFlags)) { - pNode = - m_pFactory->CreateNode(XFA_XDPPACKET_Template, XFA_Element::Template); - if (!pNode) - return nullptr; +CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Template( + CFX_XMLNode* pXMLDocumentNode) { + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Template); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) { + return nullptr; + } - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_Template)->pName); - if (m_bDocumentParser) { - CFX_WideString wsNamespaceURI; - CFDE_XMLElement* pXMLDocumentElement = - static_cast<CFDE_XMLElement*>(pXMLDocumentNode); - pXMLDocumentElement->GetNamespaceURI(wsNamespaceURI); - if (wsNamespaceURI.IsEmpty()) - pXMLDocumentElement->GetString(L"xmlns:xfa", wsNamespaceURI); - - pNode->GetDocument()->RecognizeXFAVersionNumber(wsNamespaceURI); - } - if (!NormalLoader(pNode, pXMLDocumentNode, ePacketID, true)) - return nullptr; - } - } else if (ePacketID == XFA_XDPPACKET_Form) { - if (MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_Form)->pName, - XFA_GetPacketByIndex(XFA_PACKET_Form)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Form)->eFlags)) { - CFDE_XMLElement* pXMLDocumentElement = - static_cast<CFDE_XMLElement*>(pXMLDocumentNode); - CFX_WideString wsChecksum; - pXMLDocumentElement->GetString(L"checksum", wsChecksum); - if (wsChecksum.GetLength() != 28 || - m_pXMLParser->m_dwCheckStatus != 0x03) { - return nullptr; - } - std::unique_ptr<CXFA_ChecksumContext> pChecksum(new CXFA_ChecksumContext); - pChecksum->StartChecksum(); - pChecksum->UpdateChecksum(m_pFileRead, m_pXMLParser->m_nStart[0], - m_pXMLParser->m_nSize[0]); - pChecksum->UpdateChecksum(m_pFileRead, m_pXMLParser->m_nStart[1], - m_pXMLParser->m_nSize[1]); - pChecksum->FinishChecksum(); - CFX_ByteString bsCheck = pChecksum->GetChecksum(); - if (bsCheck != wsChecksum.UTF8Encode()) - return nullptr; + CXFA_Node* pNode = + m_pFactory->CreateNode(XFA_PacketType::Template, XFA_Element::Template); + if (!pNode) + return nullptr; - pNode = m_pFactory->CreateNode(XFA_XDPPACKET_Form, XFA_Element::Form); - if (!pNode) - return nullptr; + pNode->JSObject()->SetCData(XFA_Attribute::Name, packet->name, false, false); + if (m_bDocumentParser) { + CFX_XMLElement* pXMLDocumentElement = + static_cast<CFX_XMLElement*>(pXMLDocumentNode); + WideString wsNamespaceURI = pXMLDocumentElement->GetNamespaceURI(); + if (wsNamespaceURI.IsEmpty()) + wsNamespaceURI = pXMLDocumentElement->GetString(L"xmlns:xfa"); - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_Form)->pName); - pNode->SetAttribute(XFA_ATTRIBUTE_Checksum, wsChecksum.AsStringC()); - CXFA_Node* pTemplateRoot = - m_pRootNode->GetFirstChildByClass(XFA_Element::Template); - CXFA_Node* pTemplateChosen = - pTemplateRoot - ? pTemplateRoot->GetFirstChildByClass(XFA_Element::Subform) - : nullptr; - bool bUseAttribute = true; - if (pTemplateChosen && - pTemplateChosen->GetEnum(XFA_ATTRIBUTE_RestoreState) != - XFA_ATTRIBUTEENUM_Auto) { - bUseAttribute = false; - } - if (!NormalLoader(pNode, pXMLDocumentNode, ePacketID, bUseAttribute)) - return nullptr; - } + pNode->GetDocument()->RecognizeXFAVersionNumber(wsNamespaceURI); } - if (pNode) - pNode->SetXMLMappingNode(pXMLDocumentNode); + if (!NormalLoader(pNode, pXMLDocumentNode, XFA_PacketType::Template, true)) + return nullptr; + pNode->SetXMLMappingNode(pXMLDocumentNode); + return pNode; +} + +CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Form( + CFX_XMLNode* pXMLDocumentNode) { + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Form); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) { + return nullptr; + } + + CFX_XMLElement* pXMLDocumentElement = + static_cast<CFX_XMLElement*>(pXMLDocumentNode); + WideString wsChecksum = pXMLDocumentElement->GetString(L"checksum"); + if (wsChecksum.GetLength() != 28 || m_pXMLParser->m_dwCheckStatus != 0x03) { + return nullptr; + } + + auto pChecksum = pdfium::MakeUnique<CFX_ChecksumContext>(); + pChecksum->StartChecksum(); + pChecksum->UpdateChecksum(m_pFileRead, m_pXMLParser->m_nStart[0], + m_pXMLParser->m_nSize[0]); + pChecksum->UpdateChecksum(m_pFileRead, m_pXMLParser->m_nStart[1], + m_pXMLParser->m_nSize[1]); + pChecksum->FinishChecksum(); + ByteString bsCheck = pChecksum->GetChecksum(); + if (bsCheck != wsChecksum.UTF8Encode()) + return nullptr; + + CXFA_Node* pNode = + m_pFactory->CreateNode(XFA_PacketType::Form, XFA_Element::Form); + if (!pNode) + return nullptr; + + pNode->JSObject()->SetCData(XFA_Attribute::Name, packet->name, false, false); + pNode->JSObject()->SetAttribute(XFA_Attribute::Checksum, + wsChecksum.AsStringView(), false); + CXFA_Template* pTemplateRoot = + m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template); + CXFA_Subform* pTemplateChosen = + pTemplateRoot ? pTemplateRoot->GetFirstChildByClass<CXFA_Subform>( + XFA_Element::Subform) + : nullptr; + bool bUseAttribute = true; + if (pTemplateChosen && + pTemplateChosen->JSObject()->GetEnum(XFA_Attribute::RestoreState) != + XFA_AttributeEnum::Auto) { + bUseAttribute = false; + } + if (!NormalLoader(pNode, pXMLDocumentNode, XFA_PacketType::Form, + bUseAttribute)) + return nullptr; + + pNode->SetXMLMappingNode(pXMLDocumentNode); return pNode; } CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Data( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { - CFDE_XMLNode* pDatasetsXMLNode = GetDataSetsFromXDP(pXMLDocumentNode); + CFX_XMLNode* pXMLDocumentNode) { + CFX_XMLNode* pDatasetsXMLNode = GetDataSetsFromXDP(pXMLDocumentNode); + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Datasets); if (pDatasetsXMLNode) { - CXFA_Node* pNode = - m_pFactory->CreateNode(XFA_XDPPACKET_Datasets, XFA_Element::DataModel); + CXFA_Node* pNode = m_pFactory->CreateNode(XFA_PacketType::Datasets, + XFA_Element::DataModel); if (!pNode) return nullptr; - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->pName); + pNode->JSObject()->SetCData(XFA_Attribute::Name, packet->name, false, + false); if (!DataLoader(pNode, pDatasetsXMLNode, false)) return nullptr; @@ -719,23 +751,21 @@ CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Data( return pNode; } - CFDE_XMLNode* pDataXMLNode = nullptr; - if (MatchNodeName(pXMLDocumentNode, L"data", - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Datasets)->eFlags)) { - static_cast<CFDE_XMLElement*>(pXMLDocumentNode) + CFX_XMLNode* pDataXMLNode = nullptr; + if (MatchNodeName(pXMLDocumentNode, L"data", packet->uri, packet->flags)) { + static_cast<CFX_XMLElement*>(pXMLDocumentNode) ->RemoveAttribute(L"xmlns:xfa"); pDataXMLNode = pXMLDocumentNode; } else { - CFDE_XMLElement* pDataElement = new CFDE_XMLElement(L"xfa:data"); - CFDE_XMLNode* pParentXMLNode = - pXMLDocumentNode->GetNodeItem(CFDE_XMLNode::Parent); + CFX_XMLElement* pDataElement = new CFX_XMLElement(L"xfa:data"); + CFX_XMLNode* pParentXMLNode = + pXMLDocumentNode->GetNodeItem(CFX_XMLNode::Parent); if (pParentXMLNode) pParentXMLNode->RemoveChildNode(pXMLDocumentNode); - ASSERT(pXMLDocumentNode->GetType() == FDE_XMLNODE_Element); - if (pXMLDocumentNode->GetType() == FDE_XMLNODE_Element) { - static_cast<CFDE_XMLElement*>(pXMLDocumentNode) + ASSERT(pXMLDocumentNode->GetType() == FX_XMLNODE_Element); + if (pXMLDocumentNode->GetType() == FX_XMLNODE_Element) { + static_cast<CFX_XMLElement*>(pXMLDocumentNode) ->RemoveAttribute(L"xmlns:xfa"); } pDataElement->InsertChildNode(pXMLDocumentNode); @@ -743,16 +773,16 @@ CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Data( } if (pDataXMLNode) { - CXFA_Node* pNode = - m_pFactory->CreateNode(XFA_XDPPACKET_Datasets, XFA_Element::DataGroup); + CXFA_Node* pNode = m_pFactory->CreateNode(XFA_PacketType::Datasets, + XFA_Element::DataGroup); if (!pNode) { if (pDataXMLNode != pXMLDocumentNode) delete pDataXMLNode; return nullptr; } - CFX_WideString wsLocalName; - static_cast<CFDE_XMLElement*>(pDataXMLNode)->GetLocalTagName(wsLocalName); - pNode->SetCData(XFA_ATTRIBUTE_Name, wsLocalName); + WideString wsLocalName = + static_cast<CFX_XMLElement*>(pDataXMLNode)->GetLocalTagName(); + pNode->JSObject()->SetCData(XFA_Attribute::Name, wsLocalName, false, false); if (!DataLoader(pNode, pDataXMLNode, true)) return nullptr; @@ -765,91 +795,54 @@ CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Data( } CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_LocaleConnectionSourceSet( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { - CXFA_Node* pNode = nullptr; - if (ePacketID == XFA_XDPPACKET_LocaleSet) { - if (MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_LocaleSet)->pName, - XFA_GetPacketByIndex(XFA_PACKET_LocaleSet)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_LocaleSet)->eFlags)) { - pNode = m_pFactory->CreateNode(XFA_XDPPACKET_LocaleSet, - XFA_Element::LocaleSet); - if (!pNode) - return nullptr; + CFX_XMLNode* pXMLDocumentNode, + XFA_PacketType packet_type, + XFA_Element element) { + const PacketInfo* packet = GetPacketByIndex(packet_type); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) { + return nullptr; + } - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_LocaleSet)->pName); - if (!NormalLoader(pNode, pXMLDocumentNode, ePacketID, true)) - return nullptr; - } - } else if (ePacketID == XFA_XDPPACKET_ConnectionSet) { - if (MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_ConnectionSet)->pName, - XFA_GetPacketByIndex(XFA_PACKET_ConnectionSet)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_ConnectionSet)->eFlags)) { - pNode = m_pFactory->CreateNode(XFA_XDPPACKET_ConnectionSet, - XFA_Element::ConnectionSet); - if (!pNode) - return nullptr; + CXFA_Node* pNode = m_pFactory->CreateNode(packet_type, element); + if (!pNode) + return nullptr; - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_ConnectionSet)->pName); - if (!NormalLoader(pNode, pXMLDocumentNode, ePacketID, true)) - return nullptr; - } - } else if (ePacketID == XFA_XDPPACKET_SourceSet) { - if (MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_SourceSet)->pName, - XFA_GetPacketByIndex(XFA_PACKET_SourceSet)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_SourceSet)->eFlags)) { - pNode = m_pFactory->CreateNode(XFA_XDPPACKET_SourceSet, - XFA_Element::SourceSet); - if (!pNode) - return nullptr; + pNode->JSObject()->SetCData(XFA_Attribute::Name, packet->name, false, false); + if (!NormalLoader(pNode, pXMLDocumentNode, packet_type, true)) + return nullptr; - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_SourceSet)->pName); - if (!NormalLoader(pNode, pXMLDocumentNode, ePacketID, true)) - return nullptr; - } - } - if (pNode) - pNode->SetXMLMappingNode(pXMLDocumentNode); + pNode->SetXMLMappingNode(pXMLDocumentNode); return pNode; } CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_Xdc( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { - if (!MatchNodeName(pXMLDocumentNode, - XFA_GetPacketByIndex(XFA_PACKET_Xdc)->pName, - XFA_GetPacketByIndex(XFA_PACKET_Xdc)->pURI, - XFA_GetPacketByIndex(XFA_PACKET_Xdc)->eFlags)) + CFX_XMLNode* pXMLDocumentNode) { + const PacketInfo* packet = GetPacketByIndex(XFA_PacketType::Xdc); + if (!MatchNodeName(pXMLDocumentNode, packet->name, packet->uri, + packet->flags)) return nullptr; CXFA_Node* pNode = - m_pFactory->CreateNode(XFA_XDPPACKET_Xdc, XFA_Element::Xdc); + m_pFactory->CreateNode(XFA_PacketType::Xdc, XFA_Element::Xdc); if (!pNode) return nullptr; - pNode->SetCData(XFA_ATTRIBUTE_Name, - XFA_GetPacketByIndex(XFA_PACKET_Xdc)->pName); + pNode->JSObject()->SetCData(XFA_Attribute::Name, packet->name, false, false); pNode->SetXMLMappingNode(pXMLDocumentNode); return pNode; } CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_User( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID) { + CFX_XMLNode* pXMLDocumentNode) { CXFA_Node* pNode = - m_pFactory->CreateNode(XFA_XDPPACKET_XDP, XFA_Element::Packet); + m_pFactory->CreateNode(XFA_PacketType::Xdp, XFA_Element::Packet); if (!pNode) return nullptr; - CFX_WideString wsName; - static_cast<CFDE_XMLElement*>(pXMLDocumentNode)->GetLocalTagName(wsName); - pNode->SetCData(XFA_ATTRIBUTE_Name, wsName); + WideString wsName = + static_cast<CFX_XMLElement*>(pXMLDocumentNode)->GetLocalTagName(); + pNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false); if (!UserPacketLoader(pNode, pXMLDocumentNode)) return nullptr; @@ -858,75 +851,71 @@ CXFA_Node* CXFA_SimpleParser::ParseAsXDPPacket_User( } CXFA_Node* CXFA_SimpleParser::UserPacketLoader(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLDoc) { + CFX_XMLNode* pXMLDoc) { return pXFANode; } CXFA_Node* CXFA_SimpleParser::DataLoader(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLDoc, + CFX_XMLNode* pXMLDoc, bool bDoTransform) { - ParseDataGroup(pXFANode, pXMLDoc, XFA_XDPPACKET_Datasets); + ParseDataGroup(pXFANode, pXMLDoc, XFA_PacketType::Datasets); return pXFANode; } CXFA_Node* CXFA_SimpleParser::NormalLoader(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLDoc, - XFA_XDPPACKET ePacketID, + CFX_XMLNode* pXMLDoc, + XFA_PacketType ePacketID, bool bUseAttribute) { bool bOneOfPropertyFound = false; - for (CFDE_XMLNode* pXMLChild = pXMLDoc->GetNodeItem(CFDE_XMLNode::FirstChild); + for (CFX_XMLNode* pXMLChild = pXMLDoc->GetNodeItem(CFX_XMLNode::FirstChild); pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { switch (pXMLChild->GetType()) { - case FDE_XMLNODE_Element: { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLChild); - CFX_WideString wsTagName; - pXMLElement->GetLocalTagName(wsTagName); - XFA_Element eType = XFA_GetElementTypeForName(wsTagName.AsStringC()); + case FX_XMLNODE_Element: { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLChild); + WideString wsTagName = pXMLElement->GetLocalTagName(); + XFA_Element eType = CXFA_Node::NameToElement(wsTagName); if (eType == XFA_Element::Unknown) continue; - const XFA_PROPERTY* pPropertyInfo = XFA_GetPropertyOfElement( - pXFANode->GetElementType(), eType, ePacketID); - if (pPropertyInfo && - ((pPropertyInfo->uFlags & - (XFA_PROPERTYFLAG_OneOf | XFA_PROPERTYFLAG_DefaultOneOf)) != 0)) { + if (pXFANode->HasPropertyFlags( + eType, + XFA_PROPERTYFLAG_OneOf | XFA_PROPERTYFLAG_DefaultOneOf)) { if (bOneOfPropertyFound) break; - bOneOfPropertyFound = true; } + CXFA_Node* pXFAChild = m_pFactory->CreateNode(ePacketID, eType); if (!pXFAChild) return nullptr; - if (ePacketID == XFA_XDPPACKET_Config) - pXFAChild->SetAttribute(XFA_ATTRIBUTE_Name, wsTagName.AsStringC()); + if (ePacketID == XFA_PacketType::Config) { + pXFAChild->JSObject()->SetAttribute(XFA_Attribute::Name, + wsTagName.AsStringView(), false); + } bool IsNeedValue = true; - for (int32_t i = 0, count = pXMLElement->CountAttributes(); i < count; - i++) { - CFX_WideString wsAttrQualifiedName; - CFX_WideString wsAttrName; - CFX_WideString wsAttrValue; - pXMLElement->GetAttribute(i, wsAttrQualifiedName, wsAttrValue); - GetAttributeLocalName(wsAttrQualifiedName.AsStringC(), wsAttrName); - if (wsAttrName == L"nil" && wsAttrValue == L"true") { + for (auto it : pXMLElement->GetAttributes()) { + WideString wsAttrName; + GetAttributeLocalName(it.first.AsStringView(), wsAttrName); + if (wsAttrName == L"nil" && it.second == L"true") IsNeedValue = false; - } - const XFA_ATTRIBUTEINFO* lpAttrInfo = - XFA_GetAttributeByName(wsAttrName.AsStringC()); - if (!lpAttrInfo) + + XFA_Attribute attr = + CXFA_Node::NameToAttribute(wsAttrName.AsStringView()); + if (attr == XFA_Attribute::Unknown) continue; - if (!bUseAttribute && lpAttrInfo->eName != XFA_ATTRIBUTE_Name && - lpAttrInfo->eName != XFA_ATTRIBUTE_Save) { + if (!bUseAttribute && attr != XFA_Attribute::Name && + attr != XFA_Attribute::Save) { continue; } - pXFAChild->SetAttribute(lpAttrInfo->eName, wsAttrValue.AsStringC()); + pXFAChild->JSObject()->SetAttribute(attr, it.second.AsStringView(), + false); } - pXFANode->InsertChild(pXFAChild); + pXFANode->InsertChild(pXFAChild, nullptr); if (eType == XFA_Element::Validate || eType == XFA_Element::Locale) { - if (ePacketID == XFA_XDPPACKET_Config) + if (ePacketID == XFA_PacketType::Config) ParseContentNode(pXFAChild, pXMLElement, ePacketID); else NormalLoader(pXFAChild, pXMLElement, ePacketID, bUseAttribute); @@ -946,8 +935,8 @@ CXFA_Node* CXFA_SimpleParser::NormalLoader(CXFA_Node* pXFANode, break; } } break; - case FDE_XMLNODE_Instruction: - ParseInstruction(pXFANode, static_cast<CFDE_XMLInstruction*>(pXMLChild), + case FX_XMLNODE_Instruction: + ParseInstruction(pXFANode, static_cast<CFX_XMLInstruction*>(pXMLChild), ePacketID); break; default: @@ -958,12 +947,12 @@ CXFA_Node* CXFA_SimpleParser::NormalLoader(CXFA_Node* pXFANode, } void CXFA_SimpleParser::ParseContentNode(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode, - XFA_XDPPACKET ePacketID) { + CFX_XMLNode* pXMLNode, + XFA_PacketType ePacketID) { XFA_Element element = XFA_Element::Sharptext; if (pXFANode->GetElementType() == XFA_Element::ExData) { - CFX_WideStringC wsContentType = - pXFANode->GetCData(XFA_ATTRIBUTE_ContentType); + WideString wsContentType = + pXFANode->JSObject()->GetCData(XFA_Attribute::ContentType); if (wsContentType == L"text/html") element = XFA_Element::SharpxHTML; else if (wsContentType == L"text/xml") @@ -972,34 +961,31 @@ void CXFA_SimpleParser::ParseContentNode(CXFA_Node* pXFANode, if (element == XFA_Element::SharpxHTML) pXFANode->SetXMLMappingNode(pXMLNode); - CFX_WideString wsValue; - for (CFDE_XMLNode* pXMLChild = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); + WideString wsValue; + for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { - FDE_XMLNODETYPE eNodeType = pXMLChild->GetType(); - if (eNodeType == FDE_XMLNODE_Instruction) + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { + FX_XMLNODETYPE eNodeType = pXMLChild->GetType(); + if (eNodeType == FX_XMLNODE_Instruction) continue; if (element == XFA_Element::SharpxHTML) { - if (eNodeType != FDE_XMLNODE_Element) + if (eNodeType != FX_XMLNODE_Element) break; - if (XFA_RecognizeRichText(static_cast<CFDE_XMLElement*>(pXMLChild))) - XFA_GetPlainTextFromRichText(static_cast<CFDE_XMLElement*>(pXMLChild), - wsValue); + if (XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLChild))) + wsValue += + GetPlainTextFromRichText(static_cast<CFX_XMLElement*>(pXMLChild)); } else if (element == XFA_Element::Sharpxml) { - if (eNodeType != FDE_XMLNODE_Element) + if (eNodeType != FX_XMLNODE_Element) break; - ConvertXMLToPlainText(static_cast<CFDE_XMLElement*>(pXMLChild), wsValue); + ConvertXMLToPlainText(static_cast<CFX_XMLElement*>(pXMLChild), wsValue); } else { - if (eNodeType == FDE_XMLNODE_Element) + if (eNodeType == FX_XMLNODE_Element) break; - if (eNodeType == FDE_XMLNODE_Text) - static_cast<CFDE_XMLText*>(pXMLChild)->GetText(wsValue); - else if (eNodeType == FDE_XMLNODE_CharData) - static_cast<CFDE_XMLCharData*>(pXMLChild)->GetCharData(wsValue); + if (eNodeType == FX_XMLNODE_Text || eNodeType == FX_XMLNODE_CharData) + wsValue = static_cast<CFX_XMLText*>(pXMLChild)->GetText(); } break; } @@ -1008,27 +994,27 @@ void CXFA_SimpleParser::ParseContentNode(CXFA_Node* pXFANode, CXFA_Node* pContentRawDataNode = m_pFactory->CreateNode(ePacketID, element); ASSERT(pContentRawDataNode); - pContentRawDataNode->SetCData(XFA_ATTRIBUTE_Value, wsValue); - pXFANode->InsertChild(pContentRawDataNode); + pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsValue, + false, false); + pXFANode->InsertChild(pContentRawDataNode, nullptr); } else { - pXFANode->SetCData(XFA_ATTRIBUTE_Value, wsValue); + pXFANode->JSObject()->SetCData(XFA_Attribute::Value, wsValue, false, + false); } } } void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode, - XFA_XDPPACKET ePacketID) { - for (CFDE_XMLNode* pXMLChild = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); + CFX_XMLNode* pXMLNode, + XFA_PacketType ePacketID) { + for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { switch (pXMLChild->GetType()) { - case FDE_XMLNODE_Element: { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLChild); + case FX_XMLNODE_Element: { + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLChild); { - CFX_WideString wsNamespaceURI; - GetElementTagNamespaceURI(pXMLElement, wsNamespaceURI); + WideString wsNamespaceURI = GetElementTagNamespaceURI(pXMLElement); if (wsNamespaceURI == L"http://www.xfa.com/schema/xfa-package/" || wsNamespaceURI == L"http://www.xfa.org/schema/xfa-package/" || wsNamespaceURI == L"http://www.w3.org/2001/XMLSchema-instance") { @@ -1038,7 +1024,7 @@ void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, XFA_Element eNodeType = XFA_Element::DataModel; if (eNodeType == XFA_Element::DataModel) { - CFX_WideString wsDataNodeAttr; + WideString wsDataNodeAttr; if (FindAttributeWithNS(pXMLElement, L"dataNode", L"http://www.xfa.org/schema/xfa-data/1.0/", wsDataNodeAttr)) { @@ -1048,7 +1034,7 @@ void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, eNodeType = XFA_Element::DataValue; } } - CFX_WideString wsContentType; + WideString wsContentType; if (eNodeType == XFA_Element::DataModel) { if (FindAttributeWithNS(pXMLElement, L"contentType", L"http://www.xfa.org/schema/xfa-data/1.0/", @@ -1058,13 +1044,13 @@ void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, } } if (eNodeType == XFA_Element::DataModel) { - for (CFDE_XMLNode* pXMLDataChild = - pXMLElement->GetNodeItem(CFDE_XMLNode::FirstChild); + for (CFX_XMLNode* pXMLDataChild = + pXMLElement->GetNodeItem(CFX_XMLNode::FirstChild); pXMLDataChild; pXMLDataChild = pXMLDataChild->GetNodeItem( - CFDE_XMLNode::NextSibling)) { - if (pXMLDataChild->GetType() == FDE_XMLNODE_Element) { + CFX_XMLNode::NextSibling)) { + if (pXMLDataChild->GetType() == FX_XMLNODE_Element) { if (!XFA_RecognizeRichText( - static_cast<CFDE_XMLElement*>(pXMLDataChild))) { + static_cast<CFX_XMLElement*>(pXMLDataChild))) { eNodeType = XFA_Element::DataGroup; break; } @@ -1075,25 +1061,21 @@ void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, eNodeType = XFA_Element::DataValue; CXFA_Node* pXFAChild = - m_pFactory->CreateNode(XFA_XDPPACKET_Datasets, eNodeType); + m_pFactory->CreateNode(XFA_PacketType::Datasets, eNodeType); if (!pXFAChild) return; - CFX_WideString wsNodeName; - pXMLElement->GetLocalTagName(wsNodeName); - pXFAChild->SetCData(XFA_ATTRIBUTE_Name, wsNodeName); + pXFAChild->JSObject()->SetCData( + XFA_Attribute::Name, pXMLElement->GetLocalTagName(), false, false); bool bNeedValue = true; - for (int32_t i = 0; i < pXMLElement->CountAttributes(); ++i) { - CFX_WideString wsQualifiedName; - CFX_WideString wsValue; - CFX_WideString wsName; - CFX_WideString wsNS; - pXMLElement->GetAttribute(i, wsQualifiedName, wsValue); - if (!ResolveAttribute(pXMLElement, wsQualifiedName.AsStringC(), - wsName, wsNS)) { + + for (auto it : pXMLElement->GetAttributes()) { + WideString wsName; + WideString wsNS; + if (!ResolveAttribute(pXMLElement, it.first, wsName, wsNS)) { continue; } - if (wsName == L"nil" && wsValue == L"true") { + if (wsName == L"nil" && it.second == L"true") { bNeedValue = false; continue; } @@ -1104,67 +1086,52 @@ void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, continue; } CXFA_Node* pXFAMetaData = m_pFactory->CreateNode( - XFA_XDPPACKET_Datasets, XFA_Element::DataValue); + XFA_PacketType::Datasets, XFA_Element::DataValue); if (!pXFAMetaData) return; - pXFAMetaData->SetCData(XFA_ATTRIBUTE_Name, wsName); - pXFAMetaData->SetCData(XFA_ATTRIBUTE_QualifiedName, wsQualifiedName); - pXFAMetaData->SetCData(XFA_ATTRIBUTE_Value, wsValue); - pXFAMetaData->SetEnum(XFA_ATTRIBUTE_Contains, - XFA_ATTRIBUTEENUM_MetaData); - pXFAChild->InsertChild(pXFAMetaData); + pXFAMetaData->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, + false); + pXFAMetaData->JSObject()->SetCData(XFA_Attribute::QualifiedName, + it.first, false, false); + pXFAMetaData->JSObject()->SetCData(XFA_Attribute::Value, it.second, + false, false); + pXFAMetaData->JSObject()->SetEnum(XFA_Attribute::Contains, + XFA_AttributeEnum::MetaData, false); + pXFAChild->InsertChild(pXFAMetaData, nullptr); pXFAMetaData->SetXMLMappingNode(pXMLElement); pXFAMetaData->SetFlag(XFA_NodeFlag_Initialized, false); } if (!bNeedValue) { - CFX_WideString wsNilName(L"xsi:nil"); + WideString wsNilName(L"xsi:nil"); pXMLElement->RemoveAttribute(wsNilName.c_str()); } - pXFANode->InsertChild(pXFAChild); + pXFANode->InsertChild(pXFAChild, nullptr); if (eNodeType == XFA_Element::DataGroup) ParseDataGroup(pXFAChild, pXMLElement, ePacketID); else if (bNeedValue) - ParseDataValue(pXFAChild, pXMLChild, XFA_XDPPACKET_Datasets); + ParseDataValue(pXFAChild, pXMLChild, XFA_PacketType::Datasets); pXFAChild->SetXMLMappingNode(pXMLElement); pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); continue; } - case FDE_XMLNODE_CharData: { - CFDE_XMLCharData* pXMLCharData = - static_cast<CFDE_XMLCharData*>(pXMLChild); - CFX_WideString wsCharData; - pXMLCharData->GetCharData(wsCharData); - if (IsStringAllWhitespace(wsCharData)) - continue; - - CXFA_Node* pXFAChild = m_pFactory->CreateNode(XFA_XDPPACKET_Datasets, - XFA_Element::DataValue); - if (!pXFAChild) - return; - - pXFAChild->SetCData(XFA_ATTRIBUTE_Value, wsCharData); - pXFANode->InsertChild(pXFAChild); - pXFAChild->SetXMLMappingNode(pXMLCharData); - pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); - continue; - } - case FDE_XMLNODE_Text: { - CFDE_XMLText* pXMLText = static_cast<CFDE_XMLText*>(pXMLChild); - CFX_WideString wsText; - pXMLText->GetText(wsText); + case FX_XMLNODE_CharData: + case FX_XMLNODE_Text: { + CFX_XMLText* pXMLText = static_cast<CFX_XMLText*>(pXMLChild); + WideString wsText = pXMLText->GetText(); if (IsStringAllWhitespace(wsText)) continue; - CXFA_Node* pXFAChild = m_pFactory->CreateNode(XFA_XDPPACKET_Datasets, + CXFA_Node* pXFAChild = m_pFactory->CreateNode(XFA_PacketType::Datasets, XFA_Element::DataValue); if (!pXFAChild) return; - pXFAChild->SetCData(XFA_ATTRIBUTE_Value, wsText); - pXFANode->InsertChild(pXFAChild); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Value, wsText, false, + false); + pXFANode->InsertChild(pXFAChild, nullptr); pXFAChild->SetXMLMappingNode(pXMLText); pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); continue; @@ -1176,37 +1143,28 @@ void CXFA_SimpleParser::ParseDataGroup(CXFA_Node* pXFANode, } void CXFA_SimpleParser::ParseDataValue(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode, - XFA_XDPPACKET ePacketID) { + CFX_XMLNode* pXMLNode, + XFA_PacketType ePacketID) { CFX_WideTextBuf wsValueTextBuf; CFX_WideTextBuf wsCurValueTextBuf; bool bMarkAsCompound = false; - CFDE_XMLNode* pXMLCurValueNode = nullptr; - for (CFDE_XMLNode* pXMLChild = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); + CFX_XMLNode* pXMLCurValueNode = nullptr; + for (CFX_XMLNode* pXMLChild = pXMLNode->GetNodeItem(CFX_XMLNode::FirstChild); pXMLChild; - pXMLChild = pXMLChild->GetNodeItem(CFDE_XMLNode::NextSibling)) { - FDE_XMLNODETYPE eNodeType = pXMLChild->GetType(); - if (eNodeType == FDE_XMLNODE_Instruction) + pXMLChild = pXMLChild->GetNodeItem(CFX_XMLNode::NextSibling)) { + FX_XMLNODETYPE eNodeType = pXMLChild->GetType(); + if (eNodeType == FX_XMLNODE_Instruction) continue; - CFX_WideString wsText; - if (eNodeType == FDE_XMLNODE_Text) { - static_cast<CFDE_XMLText*>(pXMLChild)->GetText(wsText); - if (!pXMLCurValueNode) - pXMLCurValueNode = pXMLChild; - - wsCurValueTextBuf << wsText; - } else if (eNodeType == FDE_XMLNODE_CharData) { - static_cast<CFDE_XMLCharData*>(pXMLChild)->GetCharData(wsText); + if (eNodeType == FX_XMLNODE_Text || eNodeType == FX_XMLNODE_CharData) { + WideString wsText = static_cast<CFX_XMLText*>(pXMLChild)->GetText(); if (!pXMLCurValueNode) pXMLCurValueNode = pXMLChild; wsCurValueTextBuf << wsText; - } else if (XFA_RecognizeRichText( - static_cast<CFDE_XMLElement*>(pXMLChild))) { - XFA_GetPlainTextFromRichText(static_cast<CFDE_XMLElement*>(pXMLChild), - wsText); + } else if (XFA_RecognizeRichText(static_cast<CFX_XMLElement*>(pXMLChild))) { + WideString wsText = + GetPlainTextFromRichText(static_cast<CFX_XMLElement*>(pXMLChild)); if (!pXMLCurValueNode) pXMLCurValueNode = pXMLChild; @@ -1214,16 +1172,18 @@ void CXFA_SimpleParser::ParseDataValue(CXFA_Node* pXFANode, } else { bMarkAsCompound = true; if (pXMLCurValueNode) { - CFX_WideString wsCurValue = wsCurValueTextBuf.MakeString(); + WideString wsCurValue = wsCurValueTextBuf.MakeString(); if (!wsCurValue.IsEmpty()) { CXFA_Node* pXFAChild = m_pFactory->CreateNode(ePacketID, XFA_Element::DataValue); if (!pXFAChild) return; - pXFAChild->SetCData(XFA_ATTRIBUTE_Name, L""); - pXFAChild->SetCData(XFA_ATTRIBUTE_Value, wsCurValue); - pXFANode->InsertChild(pXFAChild); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Name, L"", false, + false); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Value, wsCurValue, + false, false); + pXFANode->InsertChild(pXFAChild, nullptr); pXFAChild->SetXMLMappingNode(pXMLCurValueNode); pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); wsValueTextBuf << wsCurValue; @@ -1236,19 +1196,21 @@ void CXFA_SimpleParser::ParseDataValue(CXFA_Node* pXFANode, if (!pXFAChild) return; - CFX_WideString wsNodeStr; - static_cast<CFDE_XMLElement*>(pXMLChild)->GetLocalTagName(wsNodeStr); - pXFAChild->SetCData(XFA_ATTRIBUTE_Name, wsNodeStr); + WideString wsNodeStr = + static_cast<CFX_XMLElement*>(pXMLChild)->GetLocalTagName(); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Name, wsNodeStr, false, + false); ParseDataValue(pXFAChild, pXMLChild, ePacketID); - pXFANode->InsertChild(pXFAChild); + pXFANode->InsertChild(pXFAChild, nullptr); pXFAChild->SetXMLMappingNode(pXMLChild); pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); - CFX_WideStringC wsCurValue = pXFAChild->GetCData(XFA_ATTRIBUTE_Value); + WideString wsCurValue = + pXFAChild->JSObject()->GetCData(XFA_Attribute::Value); wsValueTextBuf << wsCurValue; } } if (pXMLCurValueNode) { - CFX_WideString wsCurValue = wsCurValueTextBuf.MakeString(); + WideString wsCurValue = wsCurValueTextBuf.MakeString(); if (!wsCurValue.IsEmpty()) { if (bMarkAsCompound) { CXFA_Node* pXFAChild = @@ -1256,9 +1218,10 @@ void CXFA_SimpleParser::ParseDataValue(CXFA_Node* pXFANode, if (!pXFAChild) return; - pXFAChild->SetCData(XFA_ATTRIBUTE_Name, L""); - pXFAChild->SetCData(XFA_ATTRIBUTE_Value, wsCurValue); - pXFANode->InsertChild(pXFAChild); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Name, L"", false, false); + pXFAChild->JSObject()->SetCData(XFA_Attribute::Value, wsCurValue, false, + false); + pXFANode->InsertChild(pXFAChild, nullptr); pXFAChild->SetXMLMappingNode(pXMLCurValueNode); pXFAChild->SetFlag(XFA_NodeFlag_Initialized, false); } @@ -1267,35 +1230,30 @@ void CXFA_SimpleParser::ParseDataValue(CXFA_Node* pXFANode, } pXMLCurValueNode = nullptr; } - CFX_WideString wsNodeValue = wsValueTextBuf.MakeString(); - pXFANode->SetCData(XFA_ATTRIBUTE_Value, wsNodeValue); + WideString wsNodeValue = wsValueTextBuf.MakeString(); + pXFANode->JSObject()->SetCData(XFA_Attribute::Value, wsNodeValue, false, + false); } void CXFA_SimpleParser::ParseInstruction(CXFA_Node* pXFANode, - CFDE_XMLInstruction* pXMLInstruction, - XFA_XDPPACKET ePacketID) { + CFX_XMLInstruction* pXMLInstruction, + XFA_PacketType ePacketID) { if (!m_bDocumentParser) return; - CFX_WideString wsTargetName; - pXMLInstruction->GetTargetName(wsTargetName); + WideString wsTargetName = pXMLInstruction->GetName(); + const std::vector<WideString>& target_data = pXMLInstruction->GetTargetData(); if (wsTargetName == L"originalXFAVersion") { - CFX_WideString wsData; - if (pXMLInstruction->GetData(0, wsData) && - (pXFANode->GetDocument()->RecognizeXFAVersionNumber(wsData) != - XFA_VERSION_UNKNOWN)) { - wsData.clear(); - if (pXMLInstruction->GetData(1, wsData) && - wsData == L"v2.7-scripting:1") { - pXFANode->GetDocument()->SetFlag(XFA_DOCFLAG_Scripting, true); - } + if (target_data.size() > 1 && + (pXFANode->GetDocument()->RecognizeXFAVersionNumber(target_data[0]) != + XFA_VERSION_UNKNOWN) && + target_data[1] == L"v2.7-scripting:1") { + pXFANode->GetDocument()->SetFlag(XFA_DOCFLAG_Scripting, true); } } else if (wsTargetName == L"acrobat") { - CFX_WideString wsData; - if (pXMLInstruction->GetData(0, wsData) && wsData == L"JavaScript") { - if (pXMLInstruction->GetData(1, wsData) && wsData == L"strictScoping") { - pXFANode->GetDocument()->SetFlag(XFA_DOCFLAG_StrictScoping, true); - } + if (target_data.size() > 1 && target_data[0] == L"JavaScript" && + target_data[1] == L"strictScoping") { + pXFANode->GetDocument()->SetFlag(XFA_DOCFLAG_StrictScoping, true); } } } diff --git a/xfa/fxfa/parser/cxfa_simple_parser.h b/xfa/fxfa/parser/cxfa_simple_parser.h index 5f61ad7d28fbfd65d4e896453f9acfdd3b620e9c..7a20de384a6aa46860e0b067151aa29e0346f48d 100644 --- a/xfa/fxfa/parser/cxfa_simple_parser.h +++ b/xfa/fxfa/parser/cxfa_simple_parser.h @@ -9,81 +9,80 @@ #include <memory> -#include "xfa/fde/xml/fde_xml_imp.h" #include "xfa/fxfa/fxfa_basic.h" class CXFA_Document; class CXFA_Node; -class CXFA_XMLParser; -class IFX_SeekableReadStream; -class IFX_Pause; -class IFGAS_Stream; +class CFX_XMLDoc; +class CFX_XMLInstruction; +class CFX_XMLNode; +class CFX_XMLParser; +class IFX_SeekableStream; +class CFX_SeekableStreamProxy; class CXFA_SimpleParser { public: - CXFA_SimpleParser(CXFA_Document* pFactory, bool bDocumentParser); + CXFA_SimpleParser(); + explicit CXFA_SimpleParser(CXFA_Document* pFactory); ~CXFA_SimpleParser(); - int32_t StartParse(const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, - XFA_XDPPACKET ePacketID); - int32_t DoParse(IFX_Pause* pPause); - int32_t ParseXMLData(const CFX_WideString& wsXML, - CFDE_XMLNode*& pXMLNode, - IFX_Pause* pPause); - void ConstructXFANode(CXFA_Node* pXFANode, CFDE_XMLNode* pXMLNode); + int32_t StartParse(const RetainPtr<IFX_SeekableStream>& pStream, + XFA_PacketType ePacketID); + int32_t DoParse(); + CFX_XMLNode* ParseXMLData(const ByteString& wsXML); + void ConstructXFANode(CXFA_Node* pXFANode, CFX_XMLNode* pXMLNode); CXFA_Node* GetRootNode() const; - CFDE_XMLDoc* GetXMLDoc() const; + CFX_XMLDoc* GetXMLDoc() const; void CloseParser(); + // Called later for the ctor with no parameters. void SetFactory(CXFA_Document* pFactory); private: - CXFA_Node* ParseAsXDPPacket(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); - CXFA_Node* ParseAsXDPPacket_XDP(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); - CXFA_Node* ParseAsXDPPacket_Config(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); - CXFA_Node* ParseAsXDPPacket_TemplateForm(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); - CXFA_Node* ParseAsXDPPacket_Data(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); + CXFA_Node* ParseAsXDPPacket(CFX_XMLNode* pXMLDocumentNode, + XFA_PacketType ePacketID); + CXFA_Node* ParseAsXDPPacket_XDP(CFX_XMLNode* pXMLDocumentNode); + CXFA_Node* ParseAsXDPPacket_Config(CFX_XMLNode* pXMLDocumentNode); + CXFA_Node* ParseAsXDPPacket_Template(CFX_XMLNode* pXMLDocumentNode); + CXFA_Node* ParseAsXDPPacket_Form(CFX_XMLNode* pXMLDocumentNode); + CXFA_Node* ParseAsXDPPacket_Data(CFX_XMLNode* pXMLDocumentNode); CXFA_Node* ParseAsXDPPacket_LocaleConnectionSourceSet( - CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); - CXFA_Node* ParseAsXDPPacket_Xdc(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); - CXFA_Node* ParseAsXDPPacket_User(CFDE_XMLNode* pXMLDocumentNode, - XFA_XDPPACKET ePacketID); + CFX_XMLNode* pXMLDocumentNode, + XFA_PacketType packet_type, + XFA_Element element); + CXFA_Node* ParseAsXDPPacket_Xdc(CFX_XMLNode* pXMLDocumentNode); + CXFA_Node* ParseAsXDPPacket_User(CFX_XMLNode* pXMLDocumentNode); CXFA_Node* NormalLoader(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLDoc, - XFA_XDPPACKET ePacketID, + CFX_XMLNode* pXMLDoc, + XFA_PacketType ePacketID, bool bUseAttribute); CXFA_Node* DataLoader(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLDoc, + CFX_XMLNode* pXMLDoc, bool bDoTransform); - CXFA_Node* UserPacketLoader(CXFA_Node* pXFANode, CFDE_XMLNode* pXMLDoc); + CXFA_Node* UserPacketLoader(CXFA_Node* pXFANode, CFX_XMLNode* pXMLDoc); void ParseContentNode(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode, - XFA_XDPPACKET ePacketID); + CFX_XMLNode* pXMLNode, + XFA_PacketType ePacketID); void ParseDataValue(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode, - XFA_XDPPACKET ePacketID); + CFX_XMLNode* pXMLNode, + XFA_PacketType ePacketID); void ParseDataGroup(CXFA_Node* pXFANode, - CFDE_XMLNode* pXMLNode, - XFA_XDPPACKET ePacketID); + CFX_XMLNode* pXMLNode, + XFA_PacketType ePacketID); void ParseInstruction(CXFA_Node* pXFANode, - CFDE_XMLInstruction* pXMLInstruction, - XFA_XDPPACKET ePacketID); + CFX_XMLInstruction* pXMLInstruction, + XFA_PacketType ePacketID); - CXFA_XMLParser* m_pXMLParser; - std::unique_ptr<CFDE_XMLDoc> m_pXMLDoc; - CFX_RetainPtr<IFGAS_Stream> m_pStream; - CFX_RetainPtr<IFX_SeekableReadStream> m_pFileRead; - CXFA_Document* m_pFactory; - CXFA_Node* m_pRootNode; - XFA_XDPPACKET m_ePacketID; - bool m_bDocumentParser; + std::unique_ptr<CFX_XMLDoc> m_pXMLDoc; + UnownedPtr<CFX_XMLParser> m_pXMLParser; // Owned by |m_pXMLDoc| + RetainPtr<CFX_SeekableStreamProxy> m_pStream; + RetainPtr<IFX_SeekableStream> m_pFileRead; + UnownedPtr<CXFA_Document> m_pFactory; + // TODO(dsinclair): Figure out who owns this. + CXFA_Node* m_pRootNode = nullptr; + XFA_PacketType m_ePacketID = XFA_PacketType::User; + bool m_bParseStarted = false; + const bool m_bDocumentParser; }; #endif // XFA_FXFA_PARSER_CXFA_SIMPLE_PARSER_H_ diff --git a/xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp b/xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp index a33169646daf13527cc8269b1829f4c8abd1a3a3..174febf9ee49f3adddea51acd409e74da9153395 100644 --- a/xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp +++ b/xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp @@ -13,3 +13,10 @@ TEST_F(CXFASimpleParserEmbeddertest, Bug_216) { EXPECT_NE(nullptr, page); UnloadPage(page); } + +TEST_F(CXFASimpleParserEmbeddertest, Bug_709793) { + EXPECT_TRUE(OpenDocument("bug_709793.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + UnloadPage(page); +} diff --git a/xfa/fxfa/parser/cxfa_soapaction.cpp b/xfa/fxfa/parser/cxfa_soapaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b53a653ea16a953402e98564107f37ebf43a561e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_soapaction.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_soapaction.h" + +#include "fxjs/xfa/cjx_soapaction.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"soapAction"; + +} // namespace + +CXFA_SoapAction::CXFA_SoapAction(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::TextNode, + XFA_Element::SoapAction, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SoapAction>(this)) {} + +CXFA_SoapAction::~CXFA_SoapAction() {} diff --git a/xfa/fxfa/parser/cxfa_soapaction.h b/xfa/fxfa/parser/cxfa_soapaction.h new file mode 100644 index 0000000000000000000000000000000000000000..b803eae3116fee4a2809e6471255a5cdbc0ef546 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_soapaction.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SOAPACTION_H_ +#define XFA_FXFA_PARSER_CXFA_SOAPACTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SoapAction : public CXFA_Node { + public: + CXFA_SoapAction(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SoapAction() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SOAPACTION_H_ diff --git a/xfa/fxfa/parser/cxfa_soapaddress.cpp b/xfa/fxfa/parser/cxfa_soapaddress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39f91a550a2cf668953d7fe16bc196023f9734c9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_soapaddress.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_soapaddress.h" + +#include "fxjs/xfa/cjx_soapaddress.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"soapAddress"; + +} // namespace + +CXFA_SoapAddress::CXFA_SoapAddress(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::TextNode, + XFA_Element::SoapAddress, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SoapAddress>(this)) {} + +CXFA_SoapAddress::~CXFA_SoapAddress() {} diff --git a/xfa/fxfa/parser/cxfa_soapaddress.h b/xfa/fxfa/parser/cxfa_soapaddress.h new file mode 100644 index 0000000000000000000000000000000000000000..b0feff4427b79b11ca1ef6fb154d6e848f852267 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_soapaddress.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SOAPADDRESS_H_ +#define XFA_FXFA_PARSER_CXFA_SOAPADDRESS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SoapAddress : public CXFA_Node { + public: + CXFA_SoapAddress(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SoapAddress() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SOAPADDRESS_H_ diff --git a/xfa/fxfa/parser/cxfa_solid.cpp b/xfa/fxfa/parser/cxfa_solid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a20194d99f48bb23c0815584a36d9dec1826ed2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_solid.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_solid.h" + +#include "fxjs/xfa/cjx_solid.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"solid"; + +} // namespace + +CXFA_Solid::CXFA_Solid(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Solid, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Solid>(this)) {} + +CXFA_Solid::~CXFA_Solid() {} diff --git a/xfa/fxfa/parser/cxfa_solid.h b/xfa/fxfa/parser/cxfa_solid.h new file mode 100644 index 0000000000000000000000000000000000000000..ec1e2d08c67bc931060d3ed1f0c0d196db9cf269 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_solid.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SOLID_H_ +#define XFA_FXFA_PARSER_CXFA_SOLID_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Solid : public CXFA_Node { + public: + CXFA_Solid(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Solid() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SOLID_H_ diff --git a/xfa/fxfa/parser/cxfa_source.cpp b/xfa/fxfa/parser/cxfa_source.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95d37364b29ca3f7fced562f997afe41491db379 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_source.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_source.h" + +#include "fxjs/xfa/cjx_source.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Connect, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"source"; + +} // namespace + +CXFA_Source::CXFA_Source(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::Node, + XFA_Element::Source, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Source>(this)) {} + +CXFA_Source::~CXFA_Source() {} diff --git a/xfa/fxfa/parser/cxfa_source.h b/xfa/fxfa/parser/cxfa_source.h new file mode 100644 index 0000000000000000000000000000000000000000..af74be89d92b1c24b361800823548f32e397db81 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_source.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SOURCE_H_ +#define XFA_FXFA_PARSER_CXFA_SOURCE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Source : public CXFA_Node { + public: + CXFA_Source(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Source() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SOURCE_H_ diff --git a/xfa/fxfa/parser/cxfa_sourceset.cpp b/xfa/fxfa/parser/cxfa_sourceset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3deabc6f7ac47470902b8173f7a2cce19d5fc151 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sourceset.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_sourceset.h" + +#include "fxjs/xfa/cjx_sourceset.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"sourceSet"; + +} // namespace + +CXFA_SourceSet::CXFA_SourceSet(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::ModelNode, + XFA_Element::SourceSet, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SourceSet>(this)) {} + +CXFA_SourceSet::~CXFA_SourceSet() {} diff --git a/xfa/fxfa/parser/cxfa_sourceset.h b/xfa/fxfa/parser/cxfa_sourceset.h new file mode 100644 index 0000000000000000000000000000000000000000..b07e12bd7671a0707a6aa7272934261235798ee2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_sourceset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SOURCESET_H_ +#define XFA_FXFA_PARSER_CXFA_SOURCESET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SourceSet : public CXFA_Node { + public: + CXFA_SourceSet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SourceSet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SOURCESET_H_ diff --git a/xfa/fxfa/parser/cxfa_speak.cpp b/xfa/fxfa/parser/cxfa_speak.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce05682be201cfbd029aedf08af69444f46d2d06 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_speak.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_speak.h" + +#include "fxjs/xfa/cjx_speak.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Rid, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Priority, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Custom}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Disable, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"speak"; + +} // namespace + +CXFA_Speak::CXFA_Speak(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::Speak, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Speak>(this)) {} + +CXFA_Speak::~CXFA_Speak() {} diff --git a/xfa/fxfa/parser/cxfa_speak.h b/xfa/fxfa/parser/cxfa_speak.h new file mode 100644 index 0000000000000000000000000000000000000000..80ef54b9744eee85a8cf480d9618ea5940d75599 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_speak.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SPEAK_H_ +#define XFA_FXFA_PARSER_CXFA_SPEAK_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Speak : public CXFA_Node { + public: + CXFA_Speak(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Speak() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SPEAK_H_ diff --git a/xfa/fxfa/parser/cxfa_staple.cpp b/xfa/fxfa/parser/cxfa_staple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31736d1d9daaebd8ba1923b0fc429ebd4288d65c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_staple.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_staple.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Mode, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::UsePrinterSetting}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"staple"; + +} // namespace + +CXFA_Staple::CXFA_Staple(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Staple, + nullptr, + kAttributeData, + kName) {} + +CXFA_Staple::~CXFA_Staple() {} diff --git a/xfa/fxfa/parser/cxfa_staple.h b/xfa/fxfa/parser/cxfa_staple.h new file mode 100644 index 0000000000000000000000000000000000000000..9651fa4aa805e9f1076526e3cef5f31dd193b20e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_staple.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_STAPLE_H_ +#define XFA_FXFA_PARSER_CXFA_STAPLE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Staple : public CXFA_Node { + public: + CXFA_Staple(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Staple() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_STAPLE_H_ diff --git a/xfa/fxfa/parser/cxfa_startnode.cpp b/xfa/fxfa/parser/cxfa_startnode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f49b5957efe984af4ab5ae83c40925615ad6d0e5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_startnode.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_startnode.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"startNode"; + +} // namespace + +CXFA_StartNode::CXFA_StartNode(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::StartNode, + nullptr, + kAttributeData, + kName) {} + +CXFA_StartNode::~CXFA_StartNode() {} diff --git a/xfa/fxfa/parser/cxfa_startnode.h b/xfa/fxfa/parser/cxfa_startnode.h new file mode 100644 index 0000000000000000000000000000000000000000..51815e547f14b3667e2c98539353eaee4d0e9c0b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_startnode.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_STARTNODE_H_ +#define XFA_FXFA_PARSER_CXFA_STARTNODE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_StartNode : public CXFA_Node { + public: + CXFA_StartNode(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_StartNode() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_STARTNODE_H_ diff --git a/xfa/fxfa/parser/cxfa_startpage.cpp b/xfa/fxfa/parser/cxfa_startpage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c52daf2a3329e88809e5a6b717c603d16504d20c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_startpage.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_startpage.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"startPage"; + +} // namespace + +CXFA_StartPage::CXFA_StartPage(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::StartPage, + nullptr, + kAttributeData, + kName) {} + +CXFA_StartPage::~CXFA_StartPage() {} diff --git a/xfa/fxfa/parser/cxfa_startpage.h b/xfa/fxfa/parser/cxfa_startpage.h new file mode 100644 index 0000000000000000000000000000000000000000..6262aa7c95412c1e01a08ce8459e5bc104cb1dbd --- /dev/null +++ b/xfa/fxfa/parser/cxfa_startpage.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_STARTPAGE_H_ +#define XFA_FXFA_PARSER_CXFA_STARTPAGE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_StartPage : public CXFA_Node { + public: + CXFA_StartPage(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_StartPage() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_STARTPAGE_H_ diff --git a/xfa/fxfa/parser/cxfa_stipple.cpp b/xfa/fxfa/parser/cxfa_stipple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8c059e328eade782bde0233a2463ba6a65dd446 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_stipple.cpp @@ -0,0 +1,72 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_stipple.h" + +#include "fxjs/xfa/cjx_stipple.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_color.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Color, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Rate, XFA_AttributeType::Integer, (void*)50}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"stipple"; + +} // namespace + +CXFA_Stipple::CXFA_Stipple(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Stipple, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Stipple>(this)) {} + +CXFA_Stipple::~CXFA_Stipple() {} + +CXFA_Color* CXFA_Stipple::GetColorIfExists() { + return GetChild<CXFA_Color>(0, XFA_Element::Color, false); +} + +int32_t CXFA_Stipple::GetRate() { + return JSObject() + ->TryInteger(XFA_Attribute::Rate, true) + .value_or(GetDefaultRate()); +} + +void CXFA_Stipple::Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix) { + int32_t iRate = GetRate(); + if (iRate == 0) + iRate = 100; + + CXFA_Color* pColor = GetColorIfExists(); + FX_ARGB crColor = pColor ? pColor->GetValue() : CXFA_Color::kBlackColor; + + int32_t a; + FX_COLORREF rgb; + std::tie(a, rgb) = ArgbToColorRef(crColor); + FX_ARGB cr = ArgbEncode(iRate * a / 100, rgb); + + pGS->SaveGraphState(); + pGS->SetFillColor(CXFA_GEColor(cr)); + pGS->FillPath(fillPath, FXFILL_WINDING, &matrix); + pGS->RestoreGraphState(); +} diff --git a/xfa/fxfa/parser/cxfa_stipple.h b/xfa/fxfa/parser/cxfa_stipple.h new file mode 100644 index 0000000000000000000000000000000000000000..839534b9c92eb5f09ac18051df30409efd1676f6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_stipple.h @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_STIPPLE_H_ +#define XFA_FXFA_PARSER_CXFA_STIPPLE_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxgraphics/cxfa_gepath.h" + +class CXFA_Color; +class CXFA_Graphics; + +class CXFA_Stipple : public CXFA_Node { + public: + static int32_t GetDefaultRate() { return 50; } + + CXFA_Stipple(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Stipple() override; + + void Draw(CXFA_Graphics* pGS, + CXFA_GEPath* fillPath, + const CFX_RectF& rtFill, + const CFX_Matrix& matrix); + + private: + CXFA_Color* GetColorIfExists(); + int32_t GetRate(); +}; + +#endif // XFA_FXFA_PARSER_CXFA_STIPPLE_H_ diff --git a/xfa/fxfa/parser/cxfa_stroke.cpp b/xfa/fxfa/parser/cxfa_stroke.cpp index 602f2f9f1fa32169702ed4297ef0340f9dfebdf8..9d5916a8a367371cf38a9bb70f806db5b5032c95 100644 --- a/xfa/fxfa/parser/cxfa_stroke.cpp +++ b/xfa/fxfa/parser/cxfa_stroke.cpp @@ -6,101 +6,188 @@ #include "xfa/fxfa/parser/cxfa_stroke.h" +#include <utility> + +#include "fxjs/xfa/cjx_object.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/parser/cxfa_color.h" #include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/xfa_utils.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +void XFA_StrokeTypeSetLineDash(CXFA_Graphics* pGraphics, + XFA_AttributeEnum iStrokeType, + XFA_AttributeEnum iCapType) { + switch (iStrokeType) { + case XFA_AttributeEnum::DashDot: { + float dashArray[] = {4, 1, 2, 1}; + if (iCapType != XFA_AttributeEnum::Butt) { + dashArray[1] = 2; + dashArray[3] = 2; + } + pGraphics->SetLineDash(0, dashArray, 4); + break; + } + case XFA_AttributeEnum::DashDotDot: { + float dashArray[] = {4, 1, 2, 1, 2, 1}; + if (iCapType != XFA_AttributeEnum::Butt) { + dashArray[1] = 2; + dashArray[3] = 2; + dashArray[5] = 2; + } + pGraphics->SetLineDash(0, dashArray, 6); + break; + } + case XFA_AttributeEnum::Dashed: { + float dashArray[] = {5, 1}; + if (iCapType != XFA_AttributeEnum::Butt) + dashArray[1] = 2; + + pGraphics->SetLineDash(0, dashArray, 2); + break; + } + case XFA_AttributeEnum::Dotted: { + float dashArray[] = {2, 1}; + if (iCapType != XFA_AttributeEnum::Butt) + dashArray[1] = 2; + + pGraphics->SetLineDash(0, dashArray, 2); + break; + } + default: + pGraphics->SetSolidLineDash(); + break; + } +} -int32_t CXFA_Stroke::GetPresence() const { - return m_pNode ? m_pNode->GetEnum(XFA_ATTRIBUTE_Presence) - : XFA_ATTRIBUTEENUM_Invisible; +CXFA_Stroke::CXFA_Stroke(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node) + : CXFA_Node(pDoc, + ePacket, + validPackets, + oType, + eType, + properties, + attributes, + elementName, + std::move(js_node)) {} + +CXFA_Stroke::~CXFA_Stroke() = default; + +bool CXFA_Stroke::IsVisible() { + XFA_AttributeEnum presence = JSObject() + ->TryEnum(XFA_Attribute::Presence, true) + .value_or(XFA_AttributeEnum::Visible); + return presence == XFA_AttributeEnum::Visible; } -int32_t CXFA_Stroke::GetCapType() const { - if (!m_pNode) - return XFA_ATTRIBUTEENUM_Square; - return m_pNode->GetEnum(XFA_ATTRIBUTE_Cap); +XFA_AttributeEnum CXFA_Stroke::GetCapType() { + return JSObject()->GetEnum(XFA_Attribute::Cap); } -int32_t CXFA_Stroke::GetStrokeType() const { - return m_pNode ? m_pNode->GetEnum(XFA_ATTRIBUTE_Stroke) - : XFA_ATTRIBUTEENUM_Solid; +XFA_AttributeEnum CXFA_Stroke::GetStrokeType() { + return JSObject()->GetEnum(XFA_Attribute::Stroke); } -FX_FLOAT CXFA_Stroke::GetThickness() const { - return GetMSThickness().ToUnit(XFA_UNIT_Pt); +float CXFA_Stroke::GetThickness() const { + return GetMSThickness().ToUnit(XFA_Unit::Pt); } CXFA_Measurement CXFA_Stroke::GetMSThickness() const { - return m_pNode ? m_pNode->GetMeasure(XFA_ATTRIBUTE_Thickness) - : XFA_GetAttributeDefaultValue_Measure(XFA_Element::Edge, - XFA_ATTRIBUTE_Thickness, - XFA_XDPPACKET_Form); + return JSObject()->GetMeasure(XFA_Attribute::Thickness); } void CXFA_Stroke::SetMSThickness(CXFA_Measurement msThinkness) { - if (!m_pNode) - return; - - m_pNode->SetMeasure(XFA_ATTRIBUTE_Thickness, msThinkness); + JSObject()->SetMeasure(XFA_Attribute::Thickness, msThinkness, false); } -FX_ARGB CXFA_Stroke::GetColor() const { - if (!m_pNode) - return 0xFF000000; - - CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Color); +FX_ARGB CXFA_Stroke::GetColor() { + CXFA_Color* pNode = GetChild<CXFA_Color>(0, XFA_Element::Color, false); if (!pNode) return 0xFF000000; - CFX_WideStringC wsColor; - pNode->TryCData(XFA_ATTRIBUTE_Value, wsColor); - return CXFA_Data::ToColor(wsColor); + return StringToFXARGB( + pNode->JSObject()->GetCData(XFA_Attribute::Value).AsStringView()); } void CXFA_Stroke::SetColor(FX_ARGB argb) { - if (!m_pNode) + CXFA_Color* pNode = + JSObject()->GetOrCreateProperty<CXFA_Color>(0, XFA_Element::Color); + if (!pNode) return; - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Color); - CFX_WideString wsColor; int a; int r; int g; int b; - ArgbDecode(argb, a, r, g, b); - wsColor.Format(L"%d,%d,%d", r, g, b); - pNode->SetCData(XFA_ATTRIBUTE_Value, wsColor); + std::tie(a, r, g, b) = ArgbDecode(argb); + pNode->JSObject()->SetCData(XFA_Attribute::Value, + WideString::Format(L"%d,%d,%d", r, g, b), false, + false); } -int32_t CXFA_Stroke::GetJoinType() const { - return m_pNode ? m_pNode->GetEnum(XFA_ATTRIBUTE_Join) - : XFA_ATTRIBUTEENUM_Square; +XFA_AttributeEnum CXFA_Stroke::GetJoinType() { + return JSObject()->GetEnum(XFA_Attribute::Join); } -bool CXFA_Stroke::IsInverted() const { - return m_pNode ? m_pNode->GetBoolean(XFA_ATTRIBUTE_Inverted) : false; +bool CXFA_Stroke::IsInverted() { + return JSObject()->GetBoolean(XFA_Attribute::Inverted); } -FX_FLOAT CXFA_Stroke::GetRadius() const { - return m_pNode ? m_pNode->GetMeasure(XFA_ATTRIBUTE_Radius).ToUnit(XFA_UNIT_Pt) - : 0; +float CXFA_Stroke::GetRadius() const { + return JSObject() + ->TryMeasure(XFA_Attribute::Radius, true) + .value_or(CXFA_Measurement(0, XFA_Unit::In)) + .ToUnit(XFA_Unit::Pt); } -bool CXFA_Stroke::SameStyles(CXFA_Stroke stroke, uint32_t dwFlags) const { - if (m_pNode == stroke.GetNode()) +bool CXFA_Stroke::SameStyles(CXFA_Stroke* stroke, uint32_t dwFlags) { + if (this == stroke) return true; - if (FXSYS_fabs(GetThickness() - stroke.GetThickness()) >= 0.01f) + if (fabs(GetThickness() - stroke->GetThickness()) >= 0.01f) return false; if ((dwFlags & XFA_STROKE_SAMESTYLE_NoPresence) == 0 && - IsVisible() != stroke.IsVisible()) { + IsVisible() != stroke->IsVisible()) { return false; } - if (GetStrokeType() != stroke.GetStrokeType()) + if (GetStrokeType() != stroke->GetStrokeType()) return false; - if (GetColor() != stroke.GetColor()) + if (GetColor() != stroke->GetColor()) return false; if ((dwFlags & XFA_STROKE_SAMESTYLE_Corner) != 0 && - FXSYS_fabs(GetRadius() - stroke.GetRadius()) >= 0.01f) { + fabs(GetRadius() - stroke->GetRadius()) >= 0.01f) { return false; } return true; } + +void CXFA_Stroke::Stroke(CXFA_GEPath* pPath, + CXFA_Graphics* pGS, + const CFX_Matrix& matrix) { + if (!IsVisible()) + return; + + float fThickness = GetThickness(); + if (fThickness < 0.001f) + return; + + pGS->SaveGraphState(); + if (IsCorner() && fThickness > 2 * GetRadius()) + fThickness = 2 * GetRadius(); + + pGS->SetLineWidth(fThickness); + pGS->EnableActOnDash(); + pGS->SetLineCap(CFX_GraphStateData::LineCapButt); + XFA_StrokeTypeSetLineDash(pGS, GetStrokeType(), XFA_AttributeEnum::Butt); + pGS->SetStrokeColor(CXFA_GEColor(GetColor())); + pGS->StrokePath(pPath, &matrix); + pGS->RestoreGraphState(); +} diff --git a/xfa/fxfa/parser/cxfa_stroke.h b/xfa/fxfa/parser/cxfa_stroke.h index cf941c8f0f975cf2134e8387a8c1a581bb22ddcb..ed4199707393572ae3f43ed15d6c67e409a90918 100644 --- a/xfa/fxfa/parser/cxfa_stroke.h +++ b/xfa/fxfa/parser/cxfa_stroke.h @@ -7,38 +7,59 @@ #ifndef XFA_FXFA_PARSER_CXFA_STROKE_H_ #define XFA_FXFA_PARSER_CXFA_STROKE_H_ -#include "core/fxcrt/fx_system.h" +#include <memory> + #include "core/fxge/fx_dib.h" #include "xfa/fxfa/fxfa_basic.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" enum StrokeSameStyle { XFA_STROKE_SAMESTYLE_NoPresence = 1, XFA_STROKE_SAMESTYLE_Corner = 2 }; +class CXFA_GEPath; +class CXFA_Graphics; class CXFA_Node; -class CXFA_Stroke : public CXFA_Data { +void XFA_StrokeTypeSetLineDash(CXFA_Graphics* pGraphics, + XFA_AttributeEnum iStrokeType, + XFA_AttributeEnum iCapType); + +class CXFA_Stroke : public CXFA_Node { public: - CXFA_Stroke() : CXFA_Stroke(nullptr) {} - explicit CXFA_Stroke(CXFA_Node* pNode) : CXFA_Data(pNode) {} + ~CXFA_Stroke() override; bool IsCorner() const { return GetElementType() == XFA_Element::Corner; } - bool IsEdge() const { return GetElementType() == XFA_Element::Edge; } - bool IsVisible() const { return GetPresence() == XFA_ATTRIBUTEENUM_Visible; } - int32_t GetPresence() const; - int32_t GetCapType() const; - int32_t GetStrokeType() const; - FX_FLOAT GetThickness() const; + bool IsVisible(); + bool IsInverted(); + + XFA_AttributeEnum GetCapType(); + XFA_AttributeEnum GetStrokeType(); + XFA_AttributeEnum GetJoinType(); + float GetRadius() const; + float GetThickness() const; + CXFA_Measurement GetMSThickness() const; void SetMSThickness(CXFA_Measurement msThinkness); - FX_ARGB GetColor() const; + + FX_ARGB GetColor(); void SetColor(FX_ARGB argb); - int32_t GetJoinType() const; - bool IsInverted() const; - FX_FLOAT GetRadius() const; - bool SameStyles(CXFA_Stroke stroke, uint32_t dwFlags = 0) const; + + bool SameStyles(CXFA_Stroke* stroke, uint32_t dwFlags); + + void Stroke(CXFA_GEPath* pPath, CXFA_Graphics* pGS, const CFX_Matrix& matrix); + + protected: + CXFA_Stroke(CXFA_Document* pDoc, + XFA_PacketType ePacket, + uint32_t validPackets, + XFA_ObjectType oType, + XFA_Element eType, + const PropertyData* properties, + const AttributeData* attributes, + const WideStringView& elementName, + std::unique_ptr<CJX_Object> js_node); }; #endif // XFA_FXFA_PARSER_CXFA_STROKE_H_ diff --git a/xfa/fxfa/parser/cxfa_subform.cpp b/xfa/fxfa/parser/cxfa_subform.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7bb7fa7d7d74cb8c93ab59954c82a0e55eb96517 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subform.cpp @@ -0,0 +1,77 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_subform.h" + +#include "fxjs/xfa/cjx_subform.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Break, 1, 0}, {XFA_Element::Margin, 1, 0}, + {XFA_Element::Para, 1, 0}, {XFA_Element::Border, 1, 0}, + {XFA_Element::Assist, 1, 0}, {XFA_Element::Traversal, 1, 0}, + {XFA_Element::Keep, 1, 0}, {XFA_Element::Validate, 1, 0}, + {XFA_Element::PageSet, 1, 0}, {XFA_Element::Overflow, 1, 0}, + {XFA_Element::Bind, 1, 0}, {XFA_Element::Desc, 1, 0}, + {XFA_Element::Bookend, 1, 0}, {XFA_Element::Calculate, 1, 0}, + {XFA_Element::Extras, 1, 0}, {XFA_Element::Variables, 1, 0}, + {XFA_Element::Occur, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::H, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::W, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::X, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Y, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Left}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AllowMacro, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::ColumnWidths, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Access, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Open}, + {XFA_Attribute::Presence, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Visible}, + {XFA_Attribute::VAlign, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Top}, + {XFA_Attribute::MaxH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MaxW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinH, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::MinW, XFA_AttributeType::Measure, (void*)L"0in"}, + {XFA_Attribute::Layout, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Position}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::MergeMode, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::ConsumeData}, + {XFA_Attribute::ColSpan, XFA_AttributeType::Integer, (void*)1}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Locale, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AnchorType, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::TopLeft}, + {XFA_Attribute::RestoreState, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Manual}, + {XFA_Attribute::Scope, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Name}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"subform"; + +} // namespace + +CXFA_Subform::CXFA_Subform(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::Subform, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Subform>(this)) {} + +CXFA_Subform::~CXFA_Subform() {} diff --git a/xfa/fxfa/parser/cxfa_subform.h b/xfa/fxfa/parser/cxfa_subform.h new file mode 100644 index 0000000000000000000000000000000000000000..00b2e17dbc3c4ab214f45932eb21e8f31ac5ad1c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subform.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBFORM_H_ +#define XFA_FXFA_PARSER_CXFA_SUBFORM_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Subform : public CXFA_Node { + public: + CXFA_Subform(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Subform() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBFORM_H_ diff --git a/xfa/fxfa/parser/cxfa_subformset.cpp b/xfa/fxfa/parser/cxfa_subformset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c9c3b05003b9797192180916e8ff225b8c8c13d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subformset.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_subformset.h" + +#include "fxjs/xfa/cjx_subformset.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Break, 1, 0}, {XFA_Element::Overflow, 1, 0}, + {XFA_Element::Desc, 1, 0}, {XFA_Element::Bookend, 1, 0}, + {XFA_Element::Extras, 1, 0}, {XFA_Element::Occur, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Relation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Ordered}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"subformSet"; + +} // namespace + +CXFA_SubformSet::CXFA_SubformSet(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::SubformSet, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SubformSet>(this)) {} + +CXFA_SubformSet::~CXFA_SubformSet() {} diff --git a/xfa/fxfa/parser/cxfa_subformset.h b/xfa/fxfa/parser/cxfa_subformset.h new file mode 100644 index 0000000000000000000000000000000000000000..8e0f3ea3451f88c3bcfcdee0c075347f19b8d83b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subformset.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBFORMSET_H_ +#define XFA_FXFA_PARSER_CXFA_SUBFORMSET_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SubformSet : public CXFA_Node { + public: + CXFA_SubformSet(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SubformSet() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBFORMSET_H_ diff --git a/xfa/fxfa/parser/cxfa_subjectdn.cpp b/xfa/fxfa/parser/cxfa_subjectdn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29ab2facccf2b02f6b6170cb245f523730f7af19 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subjectdn.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_subjectdn.h" + +#include "fxjs/xfa/cjx_subjectdn.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Delimiter, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"subjectDN"; + +} // namespace + +CXFA_SubjectDN::CXFA_SubjectDN(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::NodeC, + XFA_Element::SubjectDN, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SubjectDN>(this)) {} + +CXFA_SubjectDN::~CXFA_SubjectDN() {} diff --git a/xfa/fxfa/parser/cxfa_subjectdn.h b/xfa/fxfa/parser/cxfa_subjectdn.h new file mode 100644 index 0000000000000000000000000000000000000000..0861d754c41e137ecd298a5c7f3747041c191ea3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subjectdn.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBJECTDN_H_ +#define XFA_FXFA_PARSER_CXFA_SUBJECTDN_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SubjectDN : public CXFA_Node { + public: + CXFA_SubjectDN(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SubjectDN() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBJECTDN_H_ diff --git a/xfa/fxfa/parser/cxfa_subjectdns.cpp b/xfa/fxfa/parser/cxfa_subjectdns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f714b008f0cb653d455680dd41a6f5ecadf8108 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subjectdns.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_subjectdns.h" + +#include "fxjs/xfa/cjx_subjectdns.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"subjectDNs"; + +} // namespace + +CXFA_SubjectDNs::CXFA_SubjectDNs(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::SubjectDNs, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_SubjectDNs>(this)) {} + +CXFA_SubjectDNs::~CXFA_SubjectDNs() {} diff --git a/xfa/fxfa/parser/cxfa_subjectdns.h b/xfa/fxfa/parser/cxfa_subjectdns.h new file mode 100644 index 0000000000000000000000000000000000000000..e9d739cc124e4b353f30b6becc4199ddc8073dbe --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subjectdns.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBJECTDNS_H_ +#define XFA_FXFA_PARSER_CXFA_SUBJECTDNS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SubjectDNs : public CXFA_Node { + public: + CXFA_SubjectDNs(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SubjectDNs() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBJECTDNS_H_ diff --git a/xfa/fxfa/parser/cxfa_submit.cpp b/xfa/fxfa/parser/cxfa_submit.cpp index 50bef1e811a6734331252f0fa4542a1e2e2eb43a..e4558e865ac6f6292cd9ac09e188419b0f45f901 100644 --- a/xfa/fxfa/parser/cxfa_submit.cpp +++ b/xfa/fxfa/parser/cxfa_submit.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,22 +6,54 @@ #include "xfa/fxfa/parser/cxfa_submit.h" -#include "xfa/fxfa/parser/xfa_object.h" - -CXFA_Submit::CXFA_Submit(CXFA_Node* pNode) : CXFA_Data(pNode) {} +#include "fxjs/xfa/cjx_submit.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Encrypt, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Format, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Xdp}, + {XFA_Attribute::EmbedPDF, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Target, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::TextEncoding, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::XdpContent, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"submit"; + +} // namespace + +CXFA_Submit::CXFA_Submit(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Submit, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Submit>(this)) {} + +CXFA_Submit::~CXFA_Submit() {} bool CXFA_Submit::IsSubmitEmbedPDF() { - return m_pNode->GetBoolean(XFA_ATTRIBUTE_EmbedPDF); + return JSObject()->GetBoolean(XFA_Attribute::EmbedPDF); } -int32_t CXFA_Submit::GetSubmitFormat() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_Format); +XFA_AttributeEnum CXFA_Submit::GetSubmitFormat() { + return JSObject()->GetEnum(XFA_Attribute::Format); } -void CXFA_Submit::GetSubmitTarget(CFX_WideStringC& wsTarget) { - m_pNode->TryCData(XFA_ATTRIBUTE_Target, wsTarget); +WideString CXFA_Submit::GetSubmitTarget() { + return JSObject()->GetCData(XFA_Attribute::Target); } -void CXFA_Submit::GetSubmitXDPContent(CFX_WideStringC& wsContent) { - m_pNode->TryCData(XFA_ATTRIBUTE_XdpContent, wsContent); +WideString CXFA_Submit::GetSubmitXDPContent() { + return JSObject()->GetCData(XFA_Attribute::XdpContent); } diff --git a/xfa/fxfa/parser/cxfa_submit.h b/xfa/fxfa/parser/cxfa_submit.h index f10435e1f5f7cb8896b7491c6bab9924a1c66ffb..24d5f11796588a42eb569446b902cc9f9de0beae 100644 --- a/xfa/fxfa/parser/cxfa_submit.h +++ b/xfa/fxfa/parser/cxfa_submit.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,20 +7,18 @@ #ifndef XFA_FXFA_PARSER_CXFA_SUBMIT_H_ #define XFA_FXFA_PARSER_CXFA_SUBMIT_H_ -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "core/fxcrt/widestring.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Submit : public CXFA_Data { +class CXFA_Submit : public CXFA_Node { public: - explicit CXFA_Submit(CXFA_Node* pNode); + CXFA_Submit(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Submit() override; bool IsSubmitEmbedPDF(); - int32_t GetSubmitFormat(); - void GetSubmitTarget(CFX_WideStringC& wsTarget); - void GetSubmitXDPContent(CFX_WideStringC& wsContent); + XFA_AttributeEnum GetSubmitFormat(); + WideString GetSubmitTarget(); + WideString GetSubmitXDPContent(); }; #endif // XFA_FXFA_PARSER_CXFA_SUBMIT_H_ diff --git a/xfa/fxfa/parser/cxfa_submitformat.cpp b/xfa/fxfa/parser/cxfa_submitformat.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30daf89797a663f9e27c0e8146a2e956f56d699f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_submitformat.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_submitformat.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"submitFormat"; + +} // namespace + +CXFA_SubmitFormat::CXFA_SubmitFormat(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::SubmitFormat, + nullptr, + kAttributeData, + kName) {} + +CXFA_SubmitFormat::~CXFA_SubmitFormat() {} diff --git a/xfa/fxfa/parser/cxfa_submitformat.h b/xfa/fxfa/parser/cxfa_submitformat.h new file mode 100644 index 0000000000000000000000000000000000000000..adca1e9d2afd98a1ca5a5312307792ba3964a191 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_submitformat.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBMITFORMAT_H_ +#define XFA_FXFA_PARSER_CXFA_SUBMITFORMAT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SubmitFormat : public CXFA_Node { + public: + CXFA_SubmitFormat(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SubmitFormat() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBMITFORMAT_H_ diff --git a/xfa/fxfa/parser/cxfa_submiturl.cpp b/xfa/fxfa/parser/cxfa_submiturl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..591dd99ac4dee9346db64c8a056535bce066ef92 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_submiturl.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_submiturl.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"submitUrl"; + +} // namespace + +CXFA_SubmitUrl::CXFA_SubmitUrl(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::SubmitUrl, + nullptr, + kAttributeData, + kName) {} + +CXFA_SubmitUrl::~CXFA_SubmitUrl() {} diff --git a/xfa/fxfa/parser/cxfa_submiturl.h b/xfa/fxfa/parser/cxfa_submiturl.h new file mode 100644 index 0000000000000000000000000000000000000000..8d87db90763ba3b004f8f59d8bcf02853f09a203 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_submiturl.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBMITURL_H_ +#define XFA_FXFA_PARSER_CXFA_SUBMITURL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SubmitUrl : public CXFA_Node { + public: + CXFA_SubmitUrl(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SubmitUrl() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBMITURL_H_ diff --git a/xfa/fxfa/parser/cxfa_subsetbelow.cpp b/xfa/fxfa/parser/cxfa_subsetbelow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90dbd064b83a2e7d5ed08fb29d1a5027abd5f4f0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subsetbelow.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_subsetbelow.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"subsetBelow"; + +} // namespace + +CXFA_SubsetBelow::CXFA_SubsetBelow(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::SubsetBelow, + nullptr, + kAttributeData, + kName) {} + +CXFA_SubsetBelow::~CXFA_SubsetBelow() {} diff --git a/xfa/fxfa/parser/cxfa_subsetbelow.h b/xfa/fxfa/parser/cxfa_subsetbelow.h new file mode 100644 index 0000000000000000000000000000000000000000..db912fef347f9a0f6572926cbf838db1d2985047 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_subsetbelow.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUBSETBELOW_H_ +#define XFA_FXFA_PARSER_CXFA_SUBSETBELOW_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SubsetBelow : public CXFA_Node { + public: + CXFA_SubsetBelow(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SubsetBelow() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUBSETBELOW_H_ diff --git a/xfa/fxfa/parser/cxfa_suppressbanner.cpp b/xfa/fxfa/parser/cxfa_suppressbanner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46c42a5c6a06e7e32d6e1c52c691188af4c3d427 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_suppressbanner.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_suppressbanner.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"suppressBanner"; + +} // namespace + +CXFA_SuppressBanner::CXFA_SuppressBanner(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::SuppressBanner, + nullptr, + kAttributeData, + kName) {} + +CXFA_SuppressBanner::~CXFA_SuppressBanner() {} diff --git a/xfa/fxfa/parser/cxfa_suppressbanner.h b/xfa/fxfa/parser/cxfa_suppressbanner.h new file mode 100644 index 0000000000000000000000000000000000000000..79013a2d059914a15bc1381e76e0a1e80f21d594 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_suppressbanner.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_SUPPRESSBANNER_H_ +#define XFA_FXFA_PARSER_CXFA_SUPPRESSBANNER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_SuppressBanner : public CXFA_Node { + public: + CXFA_SuppressBanner(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_SuppressBanner() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_SUPPRESSBANNER_H_ diff --git a/xfa/fxfa/parser/cxfa_tagged.cpp b/xfa/fxfa/parser/cxfa_tagged.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f46b62d4b9cfc0a008530a0852aeb8549e7a86c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_tagged.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_tagged.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"tagged"; + +} // namespace + +CXFA_Tagged::CXFA_Tagged(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Tagged, + nullptr, + kAttributeData, + kName) {} + +CXFA_Tagged::~CXFA_Tagged() {} diff --git a/xfa/fxfa/parser/cxfa_tagged.h b/xfa/fxfa/parser/cxfa_tagged.h new file mode 100644 index 0000000000000000000000000000000000000000..50b1ba44a56f53d04cddaea0f69610fbd1bddedb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_tagged.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TAGGED_H_ +#define XFA_FXFA_PARSER_CXFA_TAGGED_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Tagged : public CXFA_Node { + public: + CXFA_Tagged(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Tagged() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TAGGED_H_ diff --git a/xfa/fxfa/parser/cxfa_template.cpp b/xfa/fxfa/parser/cxfa_template.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f9afa17b86551eb1402492282b74d5f9c9b11dc --- /dev/null +++ b/xfa/fxfa/parser/cxfa_template.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_template.h" + +#include "fxjs/xfa/cjx_template.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Uri, 1, 0}, {XFA_Element::Xsl, 1, 0}, + {XFA_Element::StartPage, 1, 0}, {XFA_Element::Relevant, 1, 0}, + {XFA_Element::Base, 1, 0}, {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::BaseProfile, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Full}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"template"; + +} // namespace + +CXFA_Template::CXFA_Template(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ModelNode, + XFA_Element::Template, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Template>(this)) {} + +CXFA_Template::~CXFA_Template() {} diff --git a/xfa/fxfa/parser/cxfa_template.h b/xfa/fxfa/parser/cxfa_template.h new file mode 100644 index 0000000000000000000000000000000000000000..34b035fdc452ef918066c681c66433d3ea8a44c3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_template.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TEMPLATE_H_ +#define XFA_FXFA_PARSER_CXFA_TEMPLATE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Template : public CXFA_Node { + public: + CXFA_Template(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Template() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TEMPLATE_H_ diff --git a/xfa/fxfa/parser/cxfa_templatecache.cpp b/xfa/fxfa/parser/cxfa_templatecache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e22ed65805dc5038c27d4696ba86367caaa38fe6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_templatecache.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_templatecache.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::MaxEntries, XFA_AttributeType::Integer, (void*)5}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"templateCache"; + +} // namespace + +CXFA_TemplateCache::CXFA_TemplateCache(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::TemplateCache, + nullptr, + kAttributeData, + kName) {} + +CXFA_TemplateCache::~CXFA_TemplateCache() {} diff --git a/xfa/fxfa/parser/cxfa_templatecache.h b/xfa/fxfa/parser/cxfa_templatecache.h new file mode 100644 index 0000000000000000000000000000000000000000..45953fe8f2f5439466a23b94f4dbb763a58902f5 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_templatecache.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TEMPLATECACHE_H_ +#define XFA_FXFA_PARSER_CXFA_TEMPLATECACHE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_TemplateCache : public CXFA_Node { + public: + CXFA_TemplateCache(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_TemplateCache() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TEMPLATECACHE_H_ diff --git a/xfa/fxfa/parser/cxfa_text.cpp b/xfa/fxfa/parser/cxfa_text.cpp index fc7d7aa280e2900081d2e05d99d1a5e94fd7bd68..e000493446cbc05e79f4ff52febedb9f515ea479 100644 --- a/xfa/fxfa/parser/cxfa_text.cpp +++ b/xfa/fxfa/parser/cxfa_text.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,10 +6,38 @@ #include "xfa/fxfa/parser/cxfa_text.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_text.h" +#include "third_party/base/ptr_util.h" -CXFA_Text::CXFA_Text(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -void CXFA_Text::GetContent(CFX_WideString& wsText) { - m_pNode->TryContent(wsText); +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Rid, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::MaxChars, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"text"; + +} // namespace + +CXFA_Text::CXFA_Text(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | + XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Text, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Text>(this)) {} + +CXFA_Text::~CXFA_Text() {} + +WideString CXFA_Text::GetContent() { + return JSObject()->GetContent(false); } diff --git a/xfa/fxfa/parser/cxfa_text.h b/xfa/fxfa/parser/cxfa_text.h index ca41c0dbb46f0431de68c6eecd2a7b0321365fda..a75aef2b01ff3e2c3169a17483e6bd86e54d6dc8 100644 --- a/xfa/fxfa/parser/cxfa_text.h +++ b/xfa/fxfa/parser/cxfa_text.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,15 +8,14 @@ #define XFA_FXFA_PARSER_CXFA_TEXT_H_ #include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_Text : public CXFA_Data { +class CXFA_Text : public CXFA_Node { public: - explicit CXFA_Text(CXFA_Node* pNode); + CXFA_Text(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Text() override; - void GetContent(CFX_WideString& wsText); + WideString GetContent(); }; #endif // XFA_FXFA_PARSER_CXFA_TEXT_H_ diff --git a/xfa/fxfa/parser/cxfa_textedit.cpp b/xfa/fxfa/parser/cxfa_textedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b2767ae2b9616caeda6ebfe313b00dc19264995 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_textedit.cpp @@ -0,0 +1,46 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_textedit.h" + +#include "fxjs/xfa/cjx_textedit.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Margin, 1, 0}, + {XFA_Element::Border, 1, 0}, + {XFA_Element::Comb, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::VScrollPolicy, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::AllowRichText, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::MultiLine, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::HScrollPolicy, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Auto}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"textEdit"; + +} // namespace + +CXFA_TextEdit::CXFA_TextEdit(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::TextEdit, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_TextEdit>(this)) {} + +CXFA_TextEdit::~CXFA_TextEdit() {} diff --git a/xfa/fxfa/parser/cxfa_textedit.h b/xfa/fxfa/parser/cxfa_textedit.h new file mode 100644 index 0000000000000000000000000000000000000000..972ede40f365757325b3fa3b1ad2b90ac40318d2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_textedit.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TEXTEDIT_H_ +#define XFA_FXFA_PARSER_CXFA_TEXTEDIT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_TextEdit : public CXFA_Node { + public: + CXFA_TextEdit(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_TextEdit() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TEXTEDIT_H_ diff --git a/xfa/fxfa/parser/cxfa_thisproxy.cpp b/xfa/fxfa/parser/cxfa_thisproxy.cpp index bf6f12c804d176a8792a7c2f0e546ca2006ecfd3..314c98c9f0cf797af4eab09b896fe77365e9b269 100644 --- a/xfa/fxfa/parser/cxfa_thisproxy.cpp +++ b/xfa/fxfa/parser/cxfa_thisproxy.cpp @@ -4,25 +4,19 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_thisproxy.h" + +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_node.h" CXFA_ThisProxy::CXFA_ThisProxy(CXFA_Node* pThisNode, CXFA_Node* pScriptNode) : CXFA_Object(pThisNode->GetDocument(), XFA_ObjectType::VariablesThis, XFA_Element::Unknown, - CFX_WideStringC()), - m_pThisNode(nullptr), - m_pScriptNode(nullptr) { - m_pThisNode = pThisNode; - m_pScriptNode = pScriptNode; -} + WideStringView(), + pdfium::MakeUnique<CJX_Object>(this)), + m_pThisNode(pThisNode), + m_pScriptNode(pScriptNode) {} CXFA_ThisProxy::~CXFA_ThisProxy() {} - -CXFA_Node* CXFA_ThisProxy::GetThisNode() const { - return m_pThisNode; -} - -CXFA_Node* CXFA_ThisProxy::GetScriptNode() const { - return m_pScriptNode; -} diff --git a/xfa/fxfa/parser/cxfa_thisproxy.h b/xfa/fxfa/parser/cxfa_thisproxy.h new file mode 100644 index 0000000000000000000000000000000000000000..4bb0f5a1b5304893b35cc66a5dff0d4a1298b0c0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_thisproxy.h @@ -0,0 +1,27 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_THISPROXY_H_ +#define XFA_FXFA_PARSER_CXFA_THISPROXY_H_ + +#include "xfa/fxfa/parser/cxfa_object.h" + +class CXFA_Node; + +class CXFA_ThisProxy : public CXFA_Object { + public: + CXFA_ThisProxy(CXFA_Node* pThisNode, CXFA_Node* pScriptNode); + ~CXFA_ThisProxy() override; + + CXFA_Node* GetThisNode() const { return m_pThisNode; } + CXFA_Node* GetScriptNode() const { return m_pScriptNode; } + + private: + CXFA_Node* m_pThisNode; + CXFA_Node* m_pScriptNode; +}; + +#endif // XFA_FXFA_PARSER_CXFA_THISPROXY_H_ diff --git a/xfa/fxfa/parser/cxfa_threshold.cpp b/xfa/fxfa/parser/cxfa_threshold.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2047d52da7141450672a09efb58a65c7c415fc80 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_threshold.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_threshold.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"threshold"; + +} // namespace + +CXFA_Threshold::CXFA_Threshold(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Threshold, + nullptr, + kAttributeData, + kName) {} + +CXFA_Threshold::~CXFA_Threshold() {} diff --git a/xfa/fxfa/parser/cxfa_threshold.h b/xfa/fxfa/parser/cxfa_threshold.h new file mode 100644 index 0000000000000000000000000000000000000000..4bde01a215b156b0a384e6c781643337f6c94502 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_threshold.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_THRESHOLD_H_ +#define XFA_FXFA_PARSER_CXFA_THRESHOLD_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Threshold : public CXFA_Node { + public: + CXFA_Threshold(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Threshold() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_THRESHOLD_H_ diff --git a/xfa/fxfa/parser/cxfa_time.cpp b/xfa/fxfa/parser/cxfa_time.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3a64ce566edc15439a9946bdcf2307c688b4946 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_time.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_time.h" + +#include "fxjs/xfa/cjx_time.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"time"; + +} // namespace + +CXFA_Time::CXFA_Time(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Time, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Time>(this)) {} + +CXFA_Time::~CXFA_Time() {} diff --git a/xfa/fxfa/parser/cxfa_time.h b/xfa/fxfa/parser/cxfa_time.h new file mode 100644 index 0000000000000000000000000000000000000000..efc6d02a4b1ccad7198a826b5c75b10c460fc8c7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_time.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TIME_H_ +#define XFA_FXFA_PARSER_CXFA_TIME_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Time : public CXFA_Node { + public: + CXFA_Time(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Time() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TIME_H_ diff --git a/xfa/fxfa/parser/cxfa_timepattern.cpp b/xfa/fxfa/parser/cxfa_timepattern.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76e3a53265aa0571d3b30986ac4232967e07862a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timepattern.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_timepattern.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Med}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"timePattern"; + +} // namespace + +CXFA_TimePattern::CXFA_TimePattern(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::ContentNode, + XFA_Element::TimePattern, + nullptr, + kAttributeData, + kName) {} + +CXFA_TimePattern::~CXFA_TimePattern() {} diff --git a/xfa/fxfa/parser/cxfa_timepattern.h b/xfa/fxfa/parser/cxfa_timepattern.h new file mode 100644 index 0000000000000000000000000000000000000000..f796047c62d6aa93869d3e5cdb7a643092ec2d13 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timepattern.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TIMEPATTERN_H_ +#define XFA_FXFA_PARSER_CXFA_TIMEPATTERN_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_TimePattern : public CXFA_Node { + public: + CXFA_TimePattern(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_TimePattern() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TIMEPATTERN_H_ diff --git a/xfa/fxfa/parser/cxfa_timepatterns.cpp b/xfa/fxfa/parser/cxfa_timepatterns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3a8dde6b470c43cf7199de580e42db67e3128c1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timepatterns.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_timepatterns.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::TimePattern, 4, 0}, + {XFA_Element::Unknown, 0, 0}}; + +constexpr wchar_t kName[] = L"timePatterns"; + +} // namespace + +CXFA_TimePatterns::CXFA_TimePatterns(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::TimePatterns, + kPropertyData, + nullptr, + kName) {} + +CXFA_TimePatterns::~CXFA_TimePatterns() {} diff --git a/xfa/fxfa/parser/cxfa_timepatterns.h b/xfa/fxfa/parser/cxfa_timepatterns.h new file mode 100644 index 0000000000000000000000000000000000000000..be9337d7c4a7b6f782986de37c1d8732203e0f6f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timepatterns.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TIMEPATTERNS_H_ +#define XFA_FXFA_PARSER_CXFA_TIMEPATTERNS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_TimePatterns : public CXFA_Node { + public: + CXFA_TimePatterns(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_TimePatterns() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TIMEPATTERNS_H_ diff --git a/xfa/fxfa/parser/cxfa_timestamp.cpp b/xfa/fxfa/parser/cxfa_timestamp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c869610405e816c2bc14514beaebcc15cf6d934 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timestamp.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_timestamp.h" + +#include "fxjs/xfa/cjx_timestamp.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Type, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Optional}, + {XFA_Attribute::Server, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"timeStamp"; + +} // namespace + +CXFA_TimeStamp::CXFA_TimeStamp(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::TimeStamp, + nullptr, + kAttributeData, + kName) {} + +CXFA_TimeStamp::~CXFA_TimeStamp() {} diff --git a/xfa/fxfa/parser/cxfa_timestamp.h b/xfa/fxfa/parser/cxfa_timestamp.h new file mode 100644 index 0000000000000000000000000000000000000000..7db73e91c7ee4b1b79151b9ac1f5b0310a6821c3 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timestamp.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TIMESTAMP_H_ +#define XFA_FXFA_PARSER_CXFA_TIMESTAMP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_TimeStamp : public CXFA_Node { + public: + CXFA_TimeStamp(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_TimeStamp() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TIMESTAMP_H_ diff --git a/xfa/fxfa/parser/cxfa_timezoneprovider.cpp b/xfa/fxfa/parser/cxfa_timezoneprovider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff5ecce4c7f8a510ed2f4ce23948e68d65c73d08 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timezoneprovider.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_timezoneprovider.h" + +#include <time.h> + +static bool g_bProviderTimeZoneSet = false; + +CXFA_TimeZoneProvider::CXFA_TimeZoneProvider() { +#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ + if (!g_bProviderTimeZoneSet) { + g_bProviderTimeZoneSet = true; + _tzset(); + } + m_tz.tzHour = static_cast<int8_t>(_timezone / 3600 * -1); + m_tz.tzMinute = static_cast<int8_t>((abs(_timezone) % 3600) / 60); +#else + if (!g_bProviderTimeZoneSet) { + g_bProviderTimeZoneSet = true; + tzset(); + } + m_tz.tzHour = static_cast<int8_t>(timezone / 3600 * -1); + m_tz.tzMinute = + static_cast<int8_t>((abs(static_cast<int>(timezone)) % 3600) / 60); +#endif +} + +CXFA_TimeZoneProvider::~CXFA_TimeZoneProvider() {} diff --git a/xfa/fxfa/parser/cxfa_timezoneprovider.h b/xfa/fxfa/parser/cxfa_timezoneprovider.h new file mode 100644 index 0000000000000000000000000000000000000000..753fbb74daa2cad4d412b81f81c5397323966dee --- /dev/null +++ b/xfa/fxfa/parser/cxfa_timezoneprovider.h @@ -0,0 +1,23 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TIMEZONEPROVIDER_H_ +#define XFA_FXFA_PARSER_CXFA_TIMEZONEPROVIDER_H_ + +#include "core/fxcrt/cfx_datetime.h" + +class CXFA_TimeZoneProvider { + public: + CXFA_TimeZoneProvider(); + ~CXFA_TimeZoneProvider(); + + FX_TIMEZONE GetTimeZone() const { return m_tz; } + + private: + FX_TIMEZONE m_tz; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TIMEZONEPROVIDER_H_ diff --git a/xfa/fxfa/parser/cxfa_to.cpp b/xfa/fxfa/parser/cxfa_to.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a30c01562555797fc83ec53d8eb198ab282c4b6c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_to.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_to.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"to"; + +} // namespace + +CXFA_To::CXFA_To(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::To, + nullptr, + kAttributeData, + kName) {} + +CXFA_To::~CXFA_To() {} diff --git a/xfa/fxfa/parser/cxfa_to.h b/xfa/fxfa/parser/cxfa_to.h new file mode 100644 index 0000000000000000000000000000000000000000..f418f5996ee0e4dfe45f13e15d2c258ad5f95324 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_to.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TO_H_ +#define XFA_FXFA_PARSER_CXFA_TO_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_To : public CXFA_Node { + public: + CXFA_To(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_To() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TO_H_ diff --git a/xfa/fxfa/parser/cxfa_tooltip.cpp b/xfa/fxfa/parser/cxfa_tooltip.cpp index afe0e224afa5badf7eaf563dff21834bdad0236a..04f27c9595a0ec48ec0fb9c1d0bb3d4d440cf62e 100644 --- a/xfa/fxfa/parser/cxfa_tooltip.cpp +++ b/xfa/fxfa/parser/cxfa_tooltip.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,10 +6,31 @@ #include "xfa/fxfa/parser/cxfa_tooltip.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_tooltip.h" +#include "third_party/base/ptr_util.h" -CXFA_ToolTip::CXFA_ToolTip(CXFA_Node* pNode) : CXFA_Data(pNode) {} +namespace { -bool CXFA_ToolTip::GetTip(CFX_WideString& wsTip) { - return m_pNode->TryContent(wsTip); -} +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Rid, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"toolTip"; + +} // namespace + +CXFA_ToolTip::CXFA_ToolTip(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::TextNode, + XFA_Element::ToolTip, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_ToolTip>(this)) {} + +CXFA_ToolTip::~CXFA_ToolTip() {} diff --git a/xfa/fxfa/parser/cxfa_tooltip.h b/xfa/fxfa/parser/cxfa_tooltip.h index 433885d89c967693bbb00f482f589e0b43022d2b..0b13282e99d582eb99b1fbd5014a6a87ef424dbd 100644 --- a/xfa/fxfa/parser/cxfa_tooltip.h +++ b/xfa/fxfa/parser/cxfa_tooltip.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,16 +7,12 @@ #ifndef XFA_FXFA_PARSER_CXFA_TOOLTIP_H_ #define XFA_FXFA_PARSER_CXFA_TOOLTIP_H_ -#include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_data.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; - -class CXFA_ToolTip : public CXFA_Data { +class CXFA_ToolTip : public CXFA_Node { public: - explicit CXFA_ToolTip(CXFA_Node* pNode); - - bool GetTip(CFX_WideString& wsTip); + CXFA_ToolTip(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ToolTip() override; }; #endif // XFA_FXFA_PARSER_CXFA_TOOLTIP_H_ diff --git a/xfa/fxfa/parser/cxfa_trace.cpp b/xfa/fxfa/parser/cxfa_trace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7de01fc132586ad402aed641a346de27326913ef --- /dev/null +++ b/xfa/fxfa/parser/cxfa_trace.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_trace.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"trace"; + +} // namespace + +CXFA_Trace::CXFA_Trace(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Trace, + nullptr, + kAttributeData, + kName) {} + +CXFA_Trace::~CXFA_Trace() {} diff --git a/xfa/fxfa/parser/cxfa_trace.h b/xfa/fxfa/parser/cxfa_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..dec95da6af97273032da9f078d859a0af1a3ff3a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_trace.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TRACE_H_ +#define XFA_FXFA_PARSER_CXFA_TRACE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Trace : public CXFA_Node { + public: + CXFA_Trace(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Trace() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TRACE_H_ diff --git a/xfa/fxfa/parser/cxfa_transform.cpp b/xfa/fxfa/parser/cxfa_transform.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5bfa476a2912e65627d4d91d6887b131e7681e4f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_transform.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_transform.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Whitespace, 1, 0}, {XFA_Element::Rename, 1, 0}, + {XFA_Element::IfEmpty, 1, 0}, {XFA_Element::Presence, 1, 0}, + {XFA_Element::Picture, 1, 0}, {XFA_Element::NameAttr, 1, 0}, + {XFA_Element::GroupParent, 1, 0}, {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"transform"; + +} // namespace + +CXFA_Transform::CXFA_Transform(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Transform, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Transform::~CXFA_Transform() {} diff --git a/xfa/fxfa/parser/cxfa_transform.h b/xfa/fxfa/parser/cxfa_transform.h new file mode 100644 index 0000000000000000000000000000000000000000..fde54e6efaeecf3d382c4d37c61b28ce7a7e02ff --- /dev/null +++ b/xfa/fxfa/parser/cxfa_transform.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TRANSFORM_H_ +#define XFA_FXFA_PARSER_CXFA_TRANSFORM_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Transform : public CXFA_Node { + public: + CXFA_Transform(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Transform() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TRANSFORM_H_ diff --git a/xfa/fxfa/parser/cxfa_traversal.cpp b/xfa/fxfa/parser/cxfa_traversal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5ffd3fb8eefea56509201ccffe16b59443f07f9 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_traversal.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_traversal.h" + +#include "fxjs/xfa/cjx_traversal.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"traversal"; + +} // namespace + +CXFA_Traversal::CXFA_Traversal(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Traversal, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Traversal>(this)) {} + +CXFA_Traversal::~CXFA_Traversal() {} diff --git a/xfa/fxfa/parser/cxfa_traversal.h b/xfa/fxfa/parser/cxfa_traversal.h new file mode 100644 index 0000000000000000000000000000000000000000..47422b2fcb731318bf4c7c0fab06ea098e5af443 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_traversal.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TRAVERSAL_H_ +#define XFA_FXFA_PARSER_CXFA_TRAVERSAL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Traversal : public CXFA_Node { + public: + CXFA_Traversal(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Traversal() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TRAVERSAL_H_ diff --git a/xfa/fxfa/parser/cxfa_traverse.cpp b/xfa/fxfa/parser/cxfa_traverse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d771b37856b096e0b70d748bcf28114b13c0a19f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_traverse.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_traverse.h" + +#include "fxjs/xfa/cjx_traverse.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Script, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Ref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Operation, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Next}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"traverse"; + +} // namespace + +CXFA_Traverse::CXFA_Traverse(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Traverse, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Traverse>(this)) {} + +CXFA_Traverse::~CXFA_Traverse() {} diff --git a/xfa/fxfa/parser/cxfa_traverse.h b/xfa/fxfa/parser/cxfa_traverse.h new file mode 100644 index 0000000000000000000000000000000000000000..de33cb7798970ed788db10756d2b52395720d2ed --- /dev/null +++ b/xfa/fxfa/parser/cxfa_traverse.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TRAVERSE_H_ +#define XFA_FXFA_PARSER_CXFA_TRAVERSE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Traverse : public CXFA_Node { + public: + CXFA_Traverse(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Traverse() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TRAVERSE_H_ diff --git a/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h b/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h new file mode 100644 index 0000000000000000000000000000000000000000..3ca632a1d1ada09f04117556f11604024a4d7f67 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFACONTAINERNODE_H_ +#define XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFACONTAINERNODE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" + +class CXFA_TraverseStrategy_XFAContainerNode { + public: + static CXFA_Node* GetFirstChild(CXFA_Node* pTemplateNode) { + return pTemplateNode->GetFirstContainerChild(); + } + static CXFA_Node* GetNextSibling(CXFA_Node* pTemplateNode) { + return pTemplateNode->GetNextContainerSibling(); + } + static CXFA_Node* GetParent(CXFA_Node* pTemplateNode) { + return pTemplateNode->GetContainerParent(); + } +}; + +typedef CXFA_NodeIteratorTemplate<CXFA_Node, + CXFA_TraverseStrategy_XFAContainerNode> + CXFA_ContainerIterator; + +#endif // XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFACONTAINERNODE_H_ diff --git a/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h b/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h new file mode 100644 index 0000000000000000000000000000000000000000..fc98d186238e44a62b0c8ae83ef6bfedf270e0c0 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h @@ -0,0 +1,28 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFANODE_H_ +#define XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFANODE_H_ + +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" + +class CXFA_TraverseStrategy_XFANode { + public: + static inline CXFA_Node* GetFirstChild(CXFA_Node* pTemplateNode) { + return pTemplateNode->GetFirstChild(); + } + static inline CXFA_Node* GetNextSibling(CXFA_Node* pTemplateNode) { + return pTemplateNode->GetNextSibling(); + } + static inline CXFA_Node* GetParent(CXFA_Node* pTemplateNode) { + return pTemplateNode->GetParent(); + } +}; + +typedef CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> + CXFA_NodeIterator; + +#endif // XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFANODE_H_ diff --git a/xfa/fxfa/parser/cxfa_treelist.cpp b/xfa/fxfa/parser/cxfa_treelist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5db9ecbdf91275bbec70a64d6154918ada9d5c75 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_treelist.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_treelist.h" + +#include <memory> + +#include "core/fxcrt/fx_extension.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_treelist.h" +#include "third_party/base/numerics/safe_conversions.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_list.h" +#include "xfa/fxfa/parser/cxfa_node.h" + +CXFA_TreeList::CXFA_TreeList(CXFA_Document* pDocument) + : CXFA_List(pDocument, + XFA_ObjectType::TreeList, + XFA_Element::TreeList, + WideStringView(L"treeList"), + pdfium::MakeUnique<CJX_TreeList>(this)) {} + +CXFA_TreeList::~CXFA_TreeList() {} + +CXFA_Node* CXFA_TreeList::NamedItem(const WideStringView& wsName) { + uint32_t dwHashCode = FX_HashCode_GetW(wsName, false); + size_t count = GetLength(); + for (size_t i = 0; i < count; i++) { + CXFA_Node* ret = Item(i); + if (dwHashCode == ret->GetNameHash()) + return ret; + } + return nullptr; +} diff --git a/xfa/fxfa/parser/cxfa_treelist.h b/xfa/fxfa/parser/cxfa_treelist.h new file mode 100644 index 0000000000000000000000000000000000000000..3c65ca5963c648ef19420805644ab33c6b6d716d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_treelist.h @@ -0,0 +1,24 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TREELIST_H_ +#define XFA_FXFA_PARSER_CXFA_TREELIST_H_ + +#include "fxjs/xfa/cjx_treelist.h" +#include "xfa/fxfa/fxfa_basic.h" +#include "xfa/fxfa/parser/cxfa_list.h" + +class CXFA_Node; + +class CXFA_TreeList : public CXFA_List { + public: + explicit CXFA_TreeList(CXFA_Document* pDocument); + ~CXFA_TreeList() override; + + CXFA_Node* NamedItem(const WideStringView& wsName); +}; + +#endif // XFA_FXFA_PARSER_CXFA_TREELIST_H_ diff --git a/xfa/fxfa/parser/cxfa_type.cpp b/xfa/fxfa/parser/cxfa_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac1c1930116dd9d10953f6b2c50aabf0156260de --- /dev/null +++ b/xfa/fxfa/parser/cxfa_type.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_type.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"type"; + +} // namespace + +CXFA_Type::CXFA_Type(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Type, + nullptr, + kAttributeData, + kName) {} + +CXFA_Type::~CXFA_Type() {} diff --git a/xfa/fxfa/parser/cxfa_type.h b/xfa/fxfa/parser/cxfa_type.h new file mode 100644 index 0000000000000000000000000000000000000000..5e7d4672a16f173f6fb614287dd0b682dc4dbcba --- /dev/null +++ b/xfa/fxfa/parser/cxfa_type.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TYPE_H_ +#define XFA_FXFA_PARSER_CXFA_TYPE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Type : public CXFA_Node { + public: + CXFA_Type(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Type() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TYPE_H_ diff --git a/xfa/fxfa/parser/cxfa_typeface.cpp b/xfa/fxfa/parser/cxfa_typeface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bf69bdb2a9528411a9f6330364f68931511542b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_typeface.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_typeface.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"typeface"; + +} // namespace + +CXFA_Typeface::CXFA_Typeface(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::Typeface, + nullptr, + kAttributeData, + kName) {} + +CXFA_Typeface::~CXFA_Typeface() {} diff --git a/xfa/fxfa/parser/cxfa_typeface.h b/xfa/fxfa/parser/cxfa_typeface.h new file mode 100644 index 0000000000000000000000000000000000000000..cbc90c4d4172ffcba597d8e645218cf3ad42cf67 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_typeface.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TYPEFACE_H_ +#define XFA_FXFA_PARSER_CXFA_TYPEFACE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Typeface : public CXFA_Node { + public: + CXFA_Typeface(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Typeface() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TYPEFACE_H_ diff --git a/xfa/fxfa/parser/cxfa_typefaces.cpp b/xfa/fxfa/parser/cxfa_typefaces.cpp new file mode 100644 index 0000000000000000000000000000000000000000..525919de0f0e83e83fc360c5034ad9994060964e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_typefaces.cpp @@ -0,0 +1,25 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_typefaces.h" + +namespace { + +constexpr wchar_t kName[] = L"typefaces"; + +} // namespace + +CXFA_Typefaces::CXFA_Typefaces(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_LocaleSet, + XFA_ObjectType::Node, + XFA_Element::Typefaces, + nullptr, + nullptr, + kName) {} + +CXFA_Typefaces::~CXFA_Typefaces() {} diff --git a/xfa/fxfa/parser/cxfa_typefaces.h b/xfa/fxfa/parser/cxfa_typefaces.h new file mode 100644 index 0000000000000000000000000000000000000000..fa4b43fb6e526873ff0586c28baa16dc33c28f74 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_typefaces.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_TYPEFACES_H_ +#define XFA_FXFA_PARSER_CXFA_TYPEFACES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Typefaces : public CXFA_Node { + public: + CXFA_Typefaces(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Typefaces() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_TYPEFACES_H_ diff --git a/xfa/fxfa/parser/cxfa_ui.cpp b/xfa/fxfa/parser/cxfa_ui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..883e79ac59700bd6571fb550106d95295e037171 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ui.cpp @@ -0,0 +1,51 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_ui.h" + +#include "fxjs/xfa/cjx_ui.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::CheckButton, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::ChoiceList, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::DefaultUi, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Barcode, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Button, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::DateTimeEdit, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Picture, 1, 0}, + {XFA_Element::ImageEdit, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::PasswordEdit, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::NumericEdit, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Signature, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::TextEdit, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::ExObject, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"ui"; + +} // namespace + +CXFA_Ui::CXFA_Ui(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Ui, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Ui>(this)) {} + +CXFA_Ui::~CXFA_Ui() {} diff --git a/xfa/fxfa/parser/cxfa_ui.h b/xfa/fxfa/parser/cxfa_ui.h new file mode 100644 index 0000000000000000000000000000000000000000..0824d6b88bfcfcce14bc267d60ae5f85cd9e083c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_ui.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_UI_H_ +#define XFA_FXFA_PARSER_CXFA_UI_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Ui : public CXFA_Node { + public: + CXFA_Ui(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Ui() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_UI_H_ diff --git a/xfa/fxfa/parser/cxfa_update.cpp b/xfa/fxfa/parser/cxfa_update.cpp new file mode 100644 index 0000000000000000000000000000000000000000..986e1108697c7fa3a2255f3aab2290344e4ea99c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_update.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_update.h" + +#include "fxjs/xfa/cjx_update.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"update"; + +} // namespace + +CXFA_Update::CXFA_Update(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::Update, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Update>(this)) {} + +CXFA_Update::~CXFA_Update() {} diff --git a/xfa/fxfa/parser/cxfa_update.h b/xfa/fxfa/parser/cxfa_update.h new file mode 100644 index 0000000000000000000000000000000000000000..9e652eae567f08eb3b1512cb35228a2a14d77f36 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_update.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_UPDATE_H_ +#define XFA_FXFA_PARSER_CXFA_UPDATE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Update : public CXFA_Node { + public: + CXFA_Update(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Update() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_UPDATE_H_ diff --git a/xfa/fxfa/parser/cxfa_uri.cpp b/xfa/fxfa/parser/cxfa_uri.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96cc3eccb45a9dd12110bcf496bbf2c9053dd147 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_uri.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_uri.h" + +#include "fxjs/xfa/cjx_uri.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"uri"; + +} // namespace + +CXFA_Uri::CXFA_Uri(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_ConnectionSet), + XFA_ObjectType::TextNode, + XFA_Element::Uri, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Uri>(this)) {} + +CXFA_Uri::~CXFA_Uri() {} diff --git a/xfa/fxfa/parser/cxfa_uri.h b/xfa/fxfa/parser/cxfa_uri.h new file mode 100644 index 0000000000000000000000000000000000000000..bb315964b61793132f0bdc83549759226e5d5d75 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_uri.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_URI_H_ +#define XFA_FXFA_PARSER_CXFA_URI_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Uri : public CXFA_Node { + public: + CXFA_Uri(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Uri() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_URI_H_ diff --git a/xfa/fxfa/parser/cxfa_user.cpp b/xfa/fxfa/parser/cxfa_user.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09ec6085eccb0ba254d185f80554c55f401f6d76 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_user.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_user.h" + +#include "fxjs/xfa/cjx_user.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"user"; + +} // namespace + +CXFA_User::CXFA_User(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_SourceSet, + XFA_ObjectType::TextNode, + XFA_Element::User, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_User>(this)) {} + +CXFA_User::~CXFA_User() {} diff --git a/xfa/fxfa/parser/cxfa_user.h b/xfa/fxfa/parser/cxfa_user.h new file mode 100644 index 0000000000000000000000000000000000000000..3aad173f54981af2ae47e25ffd36c3ea64d42b32 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_user.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_USER_H_ +#define XFA_FXFA_PARSER_CXFA_USER_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_User : public CXFA_Node { + public: + CXFA_User(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_User() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_USER_H_ diff --git a/xfa/fxfa/parser/cxfa_validate.cpp b/xfa/fxfa/parser/cxfa_validate.cpp index 5706d96aaa349b08df94cedec3077c661f2a89e0..868e80529a18e3fe076554b083683eee9bdd93b2 100644 --- a/xfa/fxfa/parser/cxfa_validate.cpp +++ b/xfa/fxfa/parser/cxfa_validate.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,114 +6,148 @@ #include "xfa/fxfa/parser/cxfa_validate.h" -#include "xfa/fxfa/parser/xfa_object.h" - -CXFA_Validate::CXFA_Validate(CXFA_Node* pNode) : CXFA_Data(pNode) {} - -int32_t CXFA_Validate::GetFormatTest() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_FormatTest); -} - -bool CXFA_Validate::SetTestValue(int32_t iType, - CFX_WideString& wsValue, - XFA_ATTRIBUTEENUM eName) { - const XFA_ATTRIBUTEENUMINFO* pInfo = - XFA_GetAttributeEnumByName(wsValue.AsStringC()); - if (pInfo) - eName = pInfo->eName; - - m_pNode->SetEnum((XFA_ATTRIBUTE)iType, eName, false); - return true; +#include "fxjs/xfa/cjx_object.h" +#include "fxjs/xfa/cjx_validate.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_message.h" +#include "xfa/fxfa/parser/cxfa_picture.h" +#include "xfa/fxfa/parser/cxfa_script.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Message, 1, 0}, + {XFA_Element::Picture, 1, 0}, + {XFA_Element::Script, 1, 0}, + {XFA_Element::Extras, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::ScriptTest, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Error}, + {XFA_Attribute::NullTest, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Disabled}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::FormatTest, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Warning}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"validate"; +constexpr wchar_t kFormatTest[] = L"formatTest"; +constexpr wchar_t kNullTest[] = L"nullTest"; +constexpr wchar_t kScriptTest[] = L"scriptTest"; + +} // namespace + +CXFA_Validate::CXFA_Validate(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node( + doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContentNode, + XFA_Element::Validate, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Validate>(this)) {} + +CXFA_Validate::~CXFA_Validate() {} + +XFA_AttributeEnum CXFA_Validate::GetFormatTest() { + return JSObject()->GetEnum(XFA_Attribute::FormatTest); } -bool CXFA_Validate::SetNullTest(CFX_WideString wsValue) { - return SetTestValue(XFA_ATTRIBUTE_NullTest, wsValue, - XFA_ATTRIBUTEENUM_Disabled); +void CXFA_Validate::SetNullTest(const WideString& wsValue) { + Optional<XFA_AttributeEnum> item = + CXFA_Node::NameToAttributeEnum(wsValue.AsStringView()); + JSObject()->SetEnum(XFA_Attribute::NullTest, + item ? *item : XFA_AttributeEnum::Disabled, false); } -int32_t CXFA_Validate::GetNullTest() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_NullTest); +XFA_AttributeEnum CXFA_Validate::GetNullTest() { + return JSObject()->GetEnum(XFA_Attribute::NullTest); } -int32_t CXFA_Validate::GetScriptTest() { - return m_pNode->GetEnum(XFA_ATTRIBUTE_ScriptTest); +XFA_AttributeEnum CXFA_Validate::GetScriptTest() { + return JSObject()->GetEnum(XFA_Attribute::ScriptTest); } -void CXFA_Validate::GetMessageText(CFX_WideString& wsMessage, - const CFX_WideString& wsMessageType) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Message, false); +WideString CXFA_Validate::GetMessageText(const WideString& wsMessageType) { + CXFA_Message* pNode = + JSObject()->GetProperty<CXFA_Message>(0, XFA_Element::Message); if (!pNode) - return; + return L""; - CXFA_Node* pItemNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pItemNode; - pItemNode = pItemNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pItemNode = pNode->GetFirstChild(); pItemNode; + pItemNode = pItemNode->GetNextSibling()) { if (pItemNode->GetElementType() != XFA_Element::Text) continue; - CFX_WideStringC wsName; - pItemNode->TryCData(XFA_ATTRIBUTE_Name, wsName); - if (wsName.IsEmpty() || wsName == wsMessageType) { - pItemNode->TryContent(wsMessage); - return; - } + WideString wsName = pItemNode->JSObject()->GetCData(XFA_Attribute::Name); + if (wsName.IsEmpty() || wsName == wsMessageType) + return pItemNode->JSObject()->GetContent(false); } + return L""; } -void CXFA_Validate::SetFormatMessageText(CFX_WideString wsMessage) { - SetMessageText(wsMessage, L"formatTest"); +void CXFA_Validate::SetFormatMessageText(const WideString& wsMessage) { + SetMessageText(kFormatTest, wsMessage); } -void CXFA_Validate::GetFormatMessageText(CFX_WideString& wsMessage) { - GetMessageText(wsMessage, L"formatTest"); +WideString CXFA_Validate::GetFormatMessageText() { + return GetMessageText(kFormatTest); } -void CXFA_Validate::SetNullMessageText(CFX_WideString wsMessage) { - SetMessageText(wsMessage, L"nullTest"); +void CXFA_Validate::SetNullMessageText(const WideString& wsMessage) { + SetMessageText(kNullTest, wsMessage); } -void CXFA_Validate::GetNullMessageText(CFX_WideString& wsMessage) { - GetMessageText(wsMessage, L"nullTest"); +WideString CXFA_Validate::GetNullMessageText() { + return GetMessageText(kNullTest); } -void CXFA_Validate::SetMessageText(CFX_WideString& wsMessage, - const CFX_WideString& wsMessageType) { - CXFA_Node* pNode = m_pNode->GetProperty(0, XFA_Element::Message, true); +WideString CXFA_Validate::GetScriptMessageText() { + return GetMessageText(kScriptTest); +} + +void CXFA_Validate::SetScriptMessageText(const WideString& wsMessage) { + SetMessageText(kScriptTest, wsMessage); +} + +void CXFA_Validate::SetMessageText(const WideString& wsMessageType, + const WideString& wsMessage) { + CXFA_Message* pNode = + JSObject()->GetOrCreateProperty<CXFA_Message>(0, XFA_Element::Message); if (!pNode) return; - CXFA_Node* pItemNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pItemNode; - pItemNode = pItemNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pItemNode = pNode->GetFirstChild(); pItemNode; + pItemNode = pItemNode->GetNextSibling()) { if (pItemNode->GetElementType() != XFA_Element::Text) continue; - CFX_WideStringC wsName; - pItemNode->TryCData(XFA_ATTRIBUTE_Name, wsName); + WideString wsName = pItemNode->JSObject()->GetCData(XFA_Attribute::Name); if (wsName.IsEmpty() || wsName == wsMessageType) { - pItemNode->SetContent(wsMessage, wsMessage, false); + pItemNode->JSObject()->SetContent(wsMessage, wsMessage, false, false, + true); return; } } - CXFA_Node* pTextNode = pNode->CreateSamePacketNode(XFA_Element::Text); - pNode->InsertChild(pTextNode); - pTextNode->SetCData(XFA_ATTRIBUTE_Name, wsMessageType, false); - pTextNode->SetContent(wsMessage, wsMessage, false); -} - -void CXFA_Validate::GetScriptMessageText(CFX_WideString& wsMessage) { - GetMessageText(wsMessage, L"scriptTest"); -} -void CXFA_Validate::SetScriptMessageText(CFX_WideString wsMessage) { - SetMessageText(wsMessage, L"scriptTest"); + CXFA_Node* pTextNode = pNode->CreateSamePacketNode(XFA_Element::Text); + pNode->InsertChild(pTextNode, nullptr); + pTextNode->JSObject()->SetCData(XFA_Attribute::Name, wsMessageType, false, + false); + pTextNode->JSObject()->SetContent(wsMessage, wsMessage, false, false, true); } -void CXFA_Validate::GetPicture(CFX_WideString& wsPicture) { - if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Picture)) - pNode->TryContent(wsPicture); +WideString CXFA_Validate::GetPicture() { + CXFA_Picture* pNode = GetChild<CXFA_Picture>(0, XFA_Element::Picture, false); + return pNode ? pNode->JSObject()->GetContent(false) : L""; } -CXFA_Script CXFA_Validate::GetScript() { - return CXFA_Script(m_pNode->GetChild(0, XFA_Element::Script)); +CXFA_Script* CXFA_Validate::GetScriptIfExists() { + return GetChild<CXFA_Script>(0, XFA_Element::Script, false); } diff --git a/xfa/fxfa/parser/cxfa_validate.h b/xfa/fxfa/parser/cxfa_validate.h index 03bbaddf7bbafe1bb1679fb030532bee7576578e..a6013080f10fcd0fd0a1899cf2da59cf0ef59d0a 100644 --- a/xfa/fxfa/parser/cxfa_validate.h +++ b/xfa/fxfa/parser/cxfa_validate.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,38 +7,36 @@ #ifndef XFA_FXFA_PARSER_CXFA_VALIDATE_H_ #define XFA_FXFA_PARSER_CXFA_VALIDATE_H_ -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_script.h" +#include "xfa/fxfa/parser/cxfa_node.h" -class CXFA_Node; +class CXFA_Script; -class CXFA_Validate : public CXFA_Data { +class CXFA_Validate : public CXFA_Node { public: - explicit CXFA_Validate(CXFA_Node* pNode); - - int32_t GetFormatTest(); - int32_t GetNullTest(); - bool SetNullTest(CFX_WideString wsValue); - int32_t GetScriptTest(); - void GetFormatMessageText(CFX_WideString& wsMessage); - void SetFormatMessageText(CFX_WideString wsMessage); - void GetNullMessageText(CFX_WideString& wsMessage); - void SetNullMessageText(CFX_WideString wsMessage); - void GetScriptMessageText(CFX_WideString& wsMessage); - void SetScriptMessageText(CFX_WideString wsMessage); - void GetPicture(CFX_WideString& wsPicture); - CXFA_Script GetScript(); - - protected: - void GetMessageText(CFX_WideString& wsMessage, - const CFX_WideString& wsMessageType); - void SetMessageText(CFX_WideString& wsMessage, - const CFX_WideString& wsMessageType); - bool SetTestValue(int32_t iType, - CFX_WideString& wsValue, - XFA_ATTRIBUTEENUM eName); + CXFA_Validate(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Validate() override; + + XFA_AttributeEnum GetFormatTest(); + WideString GetFormatMessageText(); + void SetFormatMessageText(const WideString& wsMessage); + + XFA_AttributeEnum GetNullTest(); + void SetNullTest(const WideString& wsValue); + + WideString GetNullMessageText(); + void SetNullMessageText(const WideString& wsMessage); + + XFA_AttributeEnum GetScriptTest(); + WideString GetScriptMessageText(); + void SetScriptMessageText(const WideString& wsMessage); + + WideString GetPicture(); + CXFA_Script* GetScriptIfExists(); + + private: + WideString GetMessageText(const WideString& wsMessageType); + void SetMessageText(const WideString& wsMessageType, + const WideString& wsMessage); }; #endif // XFA_FXFA_PARSER_CXFA_VALIDATE_H_ diff --git a/xfa/fxfa/parser/cxfa_validateapprovalsignatures.cpp b/xfa/fxfa/parser/cxfa_validateapprovalsignatures.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f51131e50d0aef9f17532e91bec2d2c1a8c5084a --- /dev/null +++ b/xfa/fxfa/parser/cxfa_validateapprovalsignatures.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_validateapprovalsignatures.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"validateApprovalSignatures"; + +} // namespace + +CXFA_ValidateApprovalSignatures::CXFA_ValidateApprovalSignatures( + CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::ValidateApprovalSignatures, + nullptr, + kAttributeData, + kName) {} + +CXFA_ValidateApprovalSignatures::~CXFA_ValidateApprovalSignatures() {} diff --git a/xfa/fxfa/parser/cxfa_validateapprovalsignatures.h b/xfa/fxfa/parser/cxfa_validateapprovalsignatures.h new file mode 100644 index 0000000000000000000000000000000000000000..d7dac98d9813172a801cc136ceba7990fa6ed6a6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_validateapprovalsignatures.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_VALIDATEAPPROVALSIGNATURES_H_ +#define XFA_FXFA_PARSER_CXFA_VALIDATEAPPROVALSIGNATURES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ValidateApprovalSignatures : public CXFA_Node { + public: + CXFA_ValidateApprovalSignatures(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ValidateApprovalSignatures() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_VALIDATEAPPROVALSIGNATURES_H_ diff --git a/xfa/fxfa/parser/cxfa_validationmessaging.cpp b/xfa/fxfa/parser/cxfa_validationmessaging.cpp new file mode 100644 index 0000000000000000000000000000000000000000..196c98c3ebda761d683d8bc5242147372ca1ed7f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_validationmessaging.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_validationmessaging.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"validationMessaging"; + +} // namespace + +CXFA_ValidationMessaging::CXFA_ValidationMessaging(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::ValidationMessaging, + nullptr, + kAttributeData, + kName) {} + +CXFA_ValidationMessaging::~CXFA_ValidationMessaging() {} diff --git a/xfa/fxfa/parser/cxfa_validationmessaging.h b/xfa/fxfa/parser/cxfa_validationmessaging.h new file mode 100644 index 0000000000000000000000000000000000000000..081b24c95189dcd23834b9a8b24344bae575f15d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_validationmessaging.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_VALIDATIONMESSAGING_H_ +#define XFA_FXFA_PARSER_CXFA_VALIDATIONMESSAGING_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ValidationMessaging : public CXFA_Node { + public: + CXFA_ValidationMessaging(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ValidationMessaging() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_VALIDATIONMESSAGING_H_ diff --git a/xfa/fxfa/parser/cxfa_value.cpp b/xfa/fxfa/parser/cxfa_value.cpp index 4d467aee2c51ffbb1107bf09b655549efbc3f013..2cd0dd93c43ac69f89208eeb8eb727e17824ef76 100644 --- a/xfa/fxfa/parser/cxfa_value.cpp +++ b/xfa/fxfa/parser/cxfa_value.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,51 +6,99 @@ #include "xfa/fxfa/parser/cxfa_value.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "fxjs/xfa/cjx_object.h" +#include "fxjs/xfa/cjx_value.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_arc.h" +#include "xfa/fxfa/parser/cxfa_exdata.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_line.h" +#include "xfa/fxfa/parser/cxfa_rectangle.h" -XFA_Element CXFA_Value::GetChildValueClassID() { - if (!m_pNode) - return XFA_Element::Unknown; - if (CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild)) - return pNode->GetElementType(); - return XFA_Element::Unknown; +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Arc, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Text, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Time, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::DateTime, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Image, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Decimal, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Boolean, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Integer, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::ExData, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Rectangle, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Date, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Float, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Line, 1, XFA_PROPERTYFLAG_OneOf}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Relevant, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Override, XFA_AttributeType::Boolean, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"value"; + +} // namespace + +CXFA_Value::CXFA_Value(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::Node, + XFA_Element::Value, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Value>(this)) {} + +CXFA_Value::~CXFA_Value() {} + +XFA_Element CXFA_Value::GetChildValueClassID() const { + CXFA_Node* pNode = GetFirstChild(); + return pNode ? pNode->GetElementType() : XFA_Element::Unknown; } -bool CXFA_Value::GetChildValueContent(CFX_WideString& wsContent) { - if (!m_pNode) - return false; - if (CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild)) - return pNode->TryContent(wsContent); - return false; +WideString CXFA_Value::GetChildValueContent() const { + CXFA_Node* pNode = GetFirstChild(); + return pNode ? pNode->JSObject()->TryContent(false, true).value_or(L"") : L""; } -CXFA_Arc CXFA_Value::GetArc() { - return CXFA_Arc(m_pNode ? m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild) - : nullptr); +CXFA_Arc* CXFA_Value::GetArcIfExists() const { + CXFA_Node* node = GetFirstChild(); + ASSERT(!node || node->GetElementType() == XFA_Element::Arc); + return static_cast<CXFA_Arc*>(node); } -CXFA_Line CXFA_Value::GetLine() { - return CXFA_Line(m_pNode ? m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild) - : nullptr); +CXFA_Line* CXFA_Value::GetLineIfExists() const { + CXFA_Node* node = GetFirstChild(); + ASSERT(!node || node->GetElementType() == XFA_Element::Line); + return static_cast<CXFA_Line*>(node); } -CXFA_Rectangle CXFA_Value::GetRectangle() { - return CXFA_Rectangle(m_pNode ? m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild) - : nullptr); +CXFA_Rectangle* CXFA_Value::GetRectangleIfExists() const { + CXFA_Node* node = GetFirstChild(); + ASSERT(!node || node->GetElementType() == XFA_Element::Rectangle); + return static_cast<CXFA_Rectangle*>(node); } -CXFA_Text CXFA_Value::GetText() { - return CXFA_Text(m_pNode ? m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild) - : nullptr); +CXFA_Text* CXFA_Value::GetTextIfExists() const { + CXFA_Node* node = GetFirstChild(); + ASSERT(!node || node->GetElementType() == XFA_Element::Text); + return static_cast<CXFA_Text*>(node); } -CXFA_ExData CXFA_Value::GetExData() { - return CXFA_ExData(m_pNode ? m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild) - : nullptr); +CXFA_ExData* CXFA_Value::GetExDataIfExists() const { + CXFA_Node* node = GetFirstChild(); + ASSERT(!node || node->GetElementType() == XFA_Element::ExData); + return static_cast<CXFA_ExData*>(node); } -CXFA_Image CXFA_Value::GetImage() { - return CXFA_Image( - m_pNode ? (m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild)) : nullptr, - true); +CXFA_Image* CXFA_Value::GetImageIfExists() const { + CXFA_Node* node = GetFirstChild(); + ASSERT(!node || node->GetElementType() == XFA_Element::Image); + return static_cast<CXFA_Image*>(node); } diff --git a/xfa/fxfa/parser/cxfa_value.h b/xfa/fxfa/parser/cxfa_value.h index 225e1879da003bdb1488153a77dc781e2a3f6fd9..47aeefede2e06c8d2660b1cdbaf1c0a7f99fed08 100644 --- a/xfa/fxfa/parser/cxfa_value.h +++ b/xfa/fxfa/parser/cxfa_value.h @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2017 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,28 +8,28 @@ #define XFA_FXFA_PARSER_CXFA_VALUE_H_ #include "core/fxcrt/fx_string.h" -#include "xfa/fxfa/parser/cxfa_arc.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_exdata.h" -#include "xfa/fxfa/parser/cxfa_image.h" -#include "xfa/fxfa/parser/cxfa_line.h" -#include "xfa/fxfa/parser/cxfa_rectangle.h" +#include "xfa/fxfa/parser/cxfa_node.h" #include "xfa/fxfa/parser/cxfa_text.h" -class CXFA_Node; +class CXFA_Arc; +class CXFA_ExData; +class CXFA_Image; +class CXFA_Line; +class CXFA_Rectangle; -class CXFA_Value : public CXFA_Data { +class CXFA_Value : public CXFA_Node { public: - explicit CXFA_Value(CXFA_Node* pNode) : CXFA_Data(pNode) {} + CXFA_Value(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Value() override; - XFA_Element GetChildValueClassID(); - bool GetChildValueContent(CFX_WideString& wsContent); - CXFA_Arc GetArc(); - CXFA_Line GetLine(); - CXFA_Rectangle GetRectangle(); - CXFA_Text GetText(); - CXFA_ExData GetExData(); - CXFA_Image GetImage(); + XFA_Element GetChildValueClassID() const; + WideString GetChildValueContent() const; + CXFA_Arc* GetArcIfExists() const; + CXFA_Line* GetLineIfExists() const; + CXFA_Rectangle* GetRectangleIfExists() const; + CXFA_Text* GetTextIfExists() const; + CXFA_ExData* GetExDataIfExists() const; + CXFA_Image* GetImageIfExists() const; }; #endif // XFA_FXFA_PARSER_CXFA_VALUE_H_ diff --git a/xfa/fxfa/parser/cxfa_valuearray.cpp b/xfa/fxfa/parser/cxfa_valuearray.cpp deleted file mode 100644 index 04afc40b0eea4c56b0626b611cbbbb09c7f06184..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_valuearray.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/cxfa_valuearray.h" - -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" - -CXFA_ValueArray::CXFA_ValueArray(v8::Isolate* pIsolate) - : m_pIsolate(pIsolate) {} - -CXFA_ValueArray::~CXFA_ValueArray() { - for (int32_t i = 0; i < GetSize(); i++) - delete GetAt(i); -} - -void CXFA_ValueArray::GetAttributeObject(CXFA_ObjArray& objArray) { - for (int32_t i = 0; i < GetSize(); i++) - objArray.Add(CXFA_ScriptContext::ToObject(GetAt(i), nullptr)); -} diff --git a/xfa/fxfa/parser/cxfa_valuearray.h b/xfa/fxfa/parser/cxfa_valuearray.h deleted file mode 100644 index 2c4ea29779621af1a8b612b6b6059921898ea8e2..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_valuearray.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_CXFA_VALUEARRAY_H_ -#define XFA_FXFA_PARSER_CXFA_VALUEARRAY_H_ - -#include "fxjs/cfxjse_value.h" -#include "xfa/fxfa/fxfa.h" - -class CXFA_ValueArray : public CFX_ArrayTemplate<CFXJSE_Value*> { - public: - explicit CXFA_ValueArray(v8::Isolate* pIsolate); - ~CXFA_ValueArray(); - - void GetAttributeObject(CXFA_ObjArray& objArray); - - v8::Isolate* const m_pIsolate; -}; - -#endif // XFA_FXFA_PARSER_CXFA_VALUEARRAY_H_ diff --git a/xfa/fxfa/parser/cxfa_variables.cpp b/xfa/fxfa/parser/cxfa_variables.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e3e751ef0a1227e1d04aacff5a51e303ec49d85 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_variables.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_variables.h" + +#include "fxjs/xfa/cjx_variables.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"variables"; + +} // namespace + +CXFA_Variables::CXFA_Variables(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form), + XFA_ObjectType::ContainerNode, + XFA_Element::Variables, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Variables>(this)) {} + +CXFA_Variables::~CXFA_Variables() {} diff --git a/xfa/fxfa/parser/cxfa_variables.h b/xfa/fxfa/parser/cxfa_variables.h new file mode 100644 index 0000000000000000000000000000000000000000..4c4cb4ec5ddc0d0d8f9c6a8af3dca19e1ad5e174 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_variables.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_VARIABLES_H_ +#define XFA_FXFA_PARSER_CXFA_VARIABLES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Variables : public CXFA_Node { + public: + CXFA_Variables(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Variables() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_VARIABLES_H_ diff --git a/xfa/fxfa/parser/cxfa_version.cpp b/xfa/fxfa/parser/cxfa_version.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5266f446195cdb68ade289445260cefbc5e8fbe6 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_version.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_version.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"version"; + +} // namespace + +CXFA_Version::CXFA_Version(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::ContentNode, + XFA_Element::Version, + nullptr, + kAttributeData, + kName) {} + +CXFA_Version::~CXFA_Version() {} diff --git a/xfa/fxfa/parser/cxfa_version.h b/xfa/fxfa/parser/cxfa_version.h new file mode 100644 index 0000000000000000000000000000000000000000..34462fbd617ec545ab67ae9de47da981352811bb --- /dev/null +++ b/xfa/fxfa/parser/cxfa_version.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_VERSION_H_ +#define XFA_FXFA_PARSER_CXFA_VERSION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Version : public CXFA_Node { + public: + CXFA_Version(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Version() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_VERSION_H_ diff --git a/xfa/fxfa/parser/cxfa_versioncontrol.cpp b/xfa/fxfa/parser/cxfa_versioncontrol.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cca84a16798efaecb0e6621eb7013671f821f8b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_versioncontrol.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_versioncontrol.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::SourceBelow, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Update}, + {XFA_Attribute::OutputBelow, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Warn}, + {XFA_Attribute::SourceAbove, XFA_AttributeType::Enum, + (void*)XFA_AttributeEnum::Warn}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"versionControl"; + +} // namespace + +CXFA_VersionControl::CXFA_VersionControl(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::VersionControl, + nullptr, + kAttributeData, + kName) {} + +CXFA_VersionControl::~CXFA_VersionControl() {} diff --git a/xfa/fxfa/parser/cxfa_versioncontrol.h b/xfa/fxfa/parser/cxfa_versioncontrol.h new file mode 100644 index 0000000000000000000000000000000000000000..4688f551f1e48fd0ad254e903f8dd255eadf1eda --- /dev/null +++ b/xfa/fxfa/parser/cxfa_versioncontrol.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_VERSIONCONTROL_H_ +#define XFA_FXFA_PARSER_CXFA_VERSIONCONTROL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_VersionControl : public CXFA_Node { + public: + CXFA_VersionControl(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_VersionControl() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_VERSIONCONTROL_H_ diff --git a/xfa/fxfa/parser/cxfa_viewerpreferences.cpp b/xfa/fxfa/parser/cxfa_viewerpreferences.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b80b479ede2ce6968bdf94427a5defced76af64 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_viewerpreferences.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_viewerpreferences.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::PrintScaling, 1, 0}, + {XFA_Element::Enforce, 1, 0}, + {XFA_Element::NumberOfCopies, 1, 0}, + {XFA_Element::PageRange, 1, 0}, + {XFA_Element::AddViewerPreferences, 1, 0}, + {XFA_Element::ADBE_JSConsole, 1, 0}, + {XFA_Element::DuplexOption, 1, 0}, + {XFA_Element::ADBE_JSDebugger, 1, 0}, + {XFA_Element::PickTrayByPDFSize, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"viewerPreferences"; + +} // namespace + +CXFA_ViewerPreferences::CXFA_ViewerPreferences(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::ViewerPreferences, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_ViewerPreferences::~CXFA_ViewerPreferences() {} diff --git a/xfa/fxfa/parser/cxfa_viewerpreferences.h b/xfa/fxfa/parser/cxfa_viewerpreferences.h new file mode 100644 index 0000000000000000000000000000000000000000..bf831eecb90efa959f324153bf82b77d4072ef19 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_viewerpreferences.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_VIEWERPREFERENCES_H_ +#define XFA_FXFA_PARSER_CXFA_VIEWERPREFERENCES_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_ViewerPreferences : public CXFA_Node { + public: + CXFA_ViewerPreferences(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_ViewerPreferences() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_VIEWERPREFERENCES_H_ diff --git a/xfa/fxfa/parser/cxfa_webclient.cpp b/xfa/fxfa/parser/cxfa_webclient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..012356069c446e86c1e84335830f52236d6c4d8b --- /dev/null +++ b/xfa/fxfa/parser/cxfa_webclient.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_webclient.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::FontInfo, 1, 0}, + {XFA_Element::Xdc, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"webClient"; + +} // namespace + +CXFA_WebClient::CXFA_WebClient(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::WebClient, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_WebClient::~CXFA_WebClient() {} diff --git a/xfa/fxfa/parser/cxfa_webclient.h b/xfa/fxfa/parser/cxfa_webclient.h new file mode 100644 index 0000000000000000000000000000000000000000..b7786898f72f18d63d97a77c87f68d9854a7a4d4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_webclient.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_WEBCLIENT_H_ +#define XFA_FXFA_PARSER_CXFA_WEBCLIENT_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_WebClient : public CXFA_Node { + public: + CXFA_WebClient(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_WebClient() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_WEBCLIENT_H_ diff --git a/xfa/fxfa/parser/cxfa_whitespace.cpp b/xfa/fxfa/parser/cxfa_whitespace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6359b86bd2bfea6c57ed75534f9ae7290e6ef99d --- /dev/null +++ b/xfa/fxfa/parser/cxfa_whitespace.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_whitespace.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"whitespace"; + +} // namespace + +CXFA_Whitespace::CXFA_Whitespace(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Whitespace, + nullptr, + kAttributeData, + kName) {} + +CXFA_Whitespace::~CXFA_Whitespace() {} diff --git a/xfa/fxfa/parser/cxfa_whitespace.h b/xfa/fxfa/parser/cxfa_whitespace.h new file mode 100644 index 0000000000000000000000000000000000000000..62dde483edc5a40f6571b89edd3efee829d408a8 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_whitespace.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_WHITESPACE_H_ +#define XFA_FXFA_PARSER_CXFA_WHITESPACE_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Whitespace : public CXFA_Node { + public: + CXFA_Whitespace(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Whitespace() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_WHITESPACE_H_ diff --git a/xfa/fxfa/parser/cxfa_widetextread.cpp b/xfa/fxfa/parser/cxfa_widetextread.cpp deleted file mode 100644 index 34fa6b9c5e5144132cc4be345c717606275e0d47..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_widetextread.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/cxfa_widetextread.h" - -#include <algorithm> - -#include "core/fxcrt/fx_ext.h" -#include "xfa/fgas/crt/fgas_codepage.h" - -CXFA_WideTextRead::CXFA_WideTextRead(const CFX_WideString& wsBuffer) - : m_wsBuffer(wsBuffer), m_iPosition(0) {} - -CXFA_WideTextRead::~CXFA_WideTextRead() {} - -uint32_t CXFA_WideTextRead::GetAccessModes() const { - return FX_STREAMACCESS_Read | FX_STREAMACCESS_Text; -} - -int32_t CXFA_WideTextRead::GetLength() const { - return m_wsBuffer.GetLength() * sizeof(FX_WCHAR); -} - -int32_t CXFA_WideTextRead::Seek(FX_STREAMSEEK eSeek, int32_t 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_wsBuffer.GetLength() + iOffset; - break; - } - m_iPosition = std::min(std::max(0, m_iPosition), m_wsBuffer.GetLength()); - return GetPosition(); -} - -int32_t CXFA_WideTextRead::GetPosition() { - return m_iPosition * sizeof(FX_WCHAR); -} - -bool CXFA_WideTextRead::IsEOF() const { - return m_iPosition >= m_wsBuffer.GetLength(); -} - -int32_t CXFA_WideTextRead::ReadData(uint8_t* pBuffer, int32_t iBufferSize) { - return 0; -} - -int32_t CXFA_WideTextRead::ReadString(FX_WCHAR* pStr, - int32_t iMaxLength, - bool& bEOS) { - iMaxLength = std::min(iMaxLength, m_wsBuffer.GetLength() - m_iPosition); - if (iMaxLength == 0) - return 0; - - FXSYS_wcsncpy(pStr, m_wsBuffer.c_str() + m_iPosition, iMaxLength); - m_iPosition += iMaxLength; - bEOS = IsEOF(); - return iMaxLength; -} - -int32_t CXFA_WideTextRead::WriteData(const uint8_t* pBuffer, - int32_t iBufferSize) { - return 0; -} - -int32_t CXFA_WideTextRead::WriteString(const FX_WCHAR* pStr, int32_t iLength) { - return 0; -} - -bool CXFA_WideTextRead::SetLength(int32_t iLength) { - return false; -} - -int32_t CXFA_WideTextRead::GetBOM(uint8_t bom[4]) const { - return 0; -} - -uint16_t CXFA_WideTextRead::GetCodePage() const { - return (sizeof(FX_WCHAR) == 2) ? FX_CODEPAGE_UTF16LE : FX_CODEPAGE_UTF32LE; -} - -uint16_t CXFA_WideTextRead::SetCodePage(uint16_t wCodePage) { - return GetCodePage(); -} - -CFX_RetainPtr<IFGAS_Stream> CXFA_WideTextRead::CreateSharedStream( - uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) { - return nullptr; -} - -CFX_WideString CXFA_WideTextRead::GetSrcText() const { - return m_wsBuffer; -} diff --git a/xfa/fxfa/parser/cxfa_widetextread.h b/xfa/fxfa/parser/cxfa_widetextread.h deleted file mode 100644 index 2ccb042908c293ce0fb54827ffaf2ae24e07b790..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_widetextread.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_CXFA_WIDETEXTREAD_H_ -#define XFA_FXFA_PARSER_CXFA_WIDETEXTREAD_H_ - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "xfa/fgas/crt/fgas_stream.h" - -class CXFA_WideTextRead : public IFGAS_Stream { - public: - template <typename T, typename... Args> - friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args); - - // IFGAS_Stream - uint32_t GetAccessModes() const override; - int32_t GetLength() const override; - int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override; - int32_t GetPosition() override; - bool IsEOF() const override; - int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override; - int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override; - int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override; - void Flush() override {} - bool SetLength(int32_t iLength) override; - int32_t GetBOM(uint8_t bom[4]) const override; - uint16_t GetCodePage() const override; - uint16_t SetCodePage(uint16_t wCodePage) override; - CFX_RetainPtr<IFGAS_Stream> CreateSharedStream(uint32_t dwAccess, - int32_t iOffset, - int32_t iLength) override; - - CFX_WideString GetSrcText() const; - - protected: - explicit CXFA_WideTextRead(const CFX_WideString& wsBuffer); - ~CXFA_WideTextRead() override; - - CFX_WideString m_wsBuffer; - int32_t m_iPosition; -}; - -#endif // XFA_FXFA_PARSER_CXFA_WIDETEXTREAD_H_ diff --git a/xfa/fxfa/parser/cxfa_widgetdata.cpp b/xfa/fxfa/parser/cxfa_widgetdata.cpp deleted file mode 100644 index d3533c277aa572a321a8572b3b5f72464b241889..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_widgetdata.cpp +++ /dev/null @@ -1,1946 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/cxfa_widgetdata.h" - -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/stl_util.h" -#include "xfa/fxbarcode/BC_Library.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_event.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/xfa_localevalue.h" -#include "xfa/fxfa/parser/xfa_object.h" - -namespace { - -FX_FLOAT GetEdgeThickness(const std::vector<CXFA_Stroke>& strokes, - bool b3DStyle, - int32_t nIndex) { - FX_FLOAT fThickness = 0; - - if (strokes[nIndex * 2 + 1].GetPresence() == XFA_ATTRIBUTEENUM_Visible) { - if (nIndex == 0) - fThickness += 2.5f; - - fThickness += strokes[nIndex * 2 + 1].GetThickness() * (b3DStyle ? 4 : 2); - } - return fThickness; -} - -bool SplitDateTime(const CFX_WideString& wsDateTime, - CFX_WideString& wsDate, - CFX_WideString& wsTime) { - wsDate = L""; - wsTime = L""; - if (wsDateTime.IsEmpty()) - return false; - - int nSplitIndex = -1; - nSplitIndex = wsDateTime.Find('T'); - if (nSplitIndex < 0) - nSplitIndex = wsDateTime.Find(' '); - if (nSplitIndex < 0) - return false; - - wsDate = wsDateTime.Left(nSplitIndex); - if (!wsDate.IsEmpty()) { - int32_t iCount = wsDate.GetLength(); - int32_t i = 0; - for (i = 0; i < iCount; i++) { - if (wsDate[i] >= '0' && wsDate[i] <= '9') - break; - } - if (i == iCount) - return false; - } - wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1); - if (!wsTime.IsEmpty()) { - int32_t iCount = wsTime.GetLength(); - int32_t i = 0; - for (i = 0; i < iCount; i++) { - if (wsTime[i] >= '0' && wsTime[i] <= '9') - break; - } - if (i == iCount) - return false; - } - return true; -} - -CXFA_Node* CreateUIChild(CXFA_Node* pNode, XFA_Element& eWidgetType) { - XFA_Element eType = pNode->GetElementType(); - eWidgetType = eType; - if (eType != XFA_Element::Field && eType != XFA_Element::Draw) - return nullptr; - - eWidgetType = XFA_Element::Unknown; - XFA_Element eUIType = XFA_Element::Unknown; - CXFA_Value defValue(pNode->GetProperty(0, XFA_Element::Value, true)); - XFA_Element eValueType = defValue.GetChildValueClassID(); - switch (eValueType) { - case XFA_Element::Boolean: - eUIType = XFA_Element::CheckButton; - break; - case XFA_Element::Integer: - case XFA_Element::Decimal: - case XFA_Element::Float: - eUIType = XFA_Element::NumericEdit; - break; - case XFA_Element::ExData: - case XFA_Element::Text: - eUIType = XFA_Element::TextEdit; - eWidgetType = XFA_Element::Text; - break; - case XFA_Element::Date: - case XFA_Element::Time: - case XFA_Element::DateTime: - eUIType = XFA_Element::DateTimeEdit; - break; - case XFA_Element::Image: - eUIType = XFA_Element::ImageEdit; - eWidgetType = XFA_Element::Image; - break; - case XFA_Element::Arc: - case XFA_Element::Line: - case XFA_Element::Rectangle: - eUIType = XFA_Element::DefaultUi; - eWidgetType = eValueType; - break; - default: - break; - } - - CXFA_Node* pUIChild = nullptr; - CXFA_Node* pUI = pNode->GetProperty(0, XFA_Element::Ui, true); - CXFA_Node* pChild = pUI->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { - XFA_Element eChildType = pChild->GetElementType(); - if (eChildType == XFA_Element::Extras || - eChildType == XFA_Element::Picture) { - continue; - } - const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( - XFA_Element::Ui, eChildType, XFA_XDPPACKET_Form); - if (pProperty && (pProperty->uFlags & XFA_PROPERTYFLAG_OneOf)) { - pUIChild = pChild; - break; - } - } - - if (eType == XFA_Element::Draw) { - XFA_Element eDraw = - pUIChild ? pUIChild->GetElementType() : XFA_Element::Unknown; - switch (eDraw) { - case XFA_Element::TextEdit: - eWidgetType = XFA_Element::Text; - break; - case XFA_Element::ImageEdit: - eWidgetType = XFA_Element::Image; - break; - default: - eWidgetType = eWidgetType == XFA_Element::Unknown ? XFA_Element::Text - : eWidgetType; - break; - } - } else { - if (pUIChild && pUIChild->GetElementType() == XFA_Element::DefaultUi) { - eWidgetType = XFA_Element::TextEdit; - } else { - eWidgetType = - pUIChild ? pUIChild->GetElementType() - : (eUIType == XFA_Element::Unknown ? XFA_Element::TextEdit - : eUIType); - } - } - - if (!pUIChild) { - if (eUIType == XFA_Element::Unknown) { - eUIType = XFA_Element::TextEdit; - defValue.GetNode()->GetProperty(0, XFA_Element::Text, true); - } - return pUI->GetProperty(0, eUIType, true); - } - - if (eUIType != XFA_Element::Unknown) - return pUIChild; - - switch (pUIChild->GetElementType()) { - case XFA_Element::CheckButton: { - eValueType = XFA_Element::Text; - if (CXFA_Node* pItems = pNode->GetChild(0, XFA_Element::Items)) { - if (CXFA_Node* pItem = pItems->GetChild(0, XFA_Element::Unknown)) - eValueType = pItem->GetElementType(); - } - break; - } - case XFA_Element::DateTimeEdit: - eValueType = XFA_Element::DateTime; - break; - case XFA_Element::ImageEdit: - eValueType = XFA_Element::Image; - break; - case XFA_Element::NumericEdit: - eValueType = XFA_Element::Float; - break; - case XFA_Element::ChoiceList: { - eValueType = (pUIChild->GetEnum(XFA_ATTRIBUTE_Open) == - XFA_ATTRIBUTEENUM_MultiSelect) - ? XFA_Element::ExData - : XFA_Element::Text; - break; - } - case XFA_Element::Barcode: - case XFA_Element::Button: - case XFA_Element::PasswordEdit: - case XFA_Element::Signature: - case XFA_Element::TextEdit: - default: - eValueType = XFA_Element::Text; - break; - } - defValue.GetNode()->GetProperty(0, eValueType, true); - - return pUIChild; -} - -XFA_ATTRIBUTEENUM GetAttributeDefaultValue_Enum(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - uint32_t dwPacket) { - void* pValue; - if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute, - XFA_ATTRIBUTETYPE_Enum, dwPacket)) { - return (XFA_ATTRIBUTEENUM)(uintptr_t)pValue; - } - return XFA_ATTRIBUTEENUM_Unknown; -} - -CFX_WideStringC GetAttributeDefaultValue_Cdata(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - uint32_t dwPacket) { - void* pValue; - if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute, - XFA_ATTRIBUTETYPE_Cdata, dwPacket)) { - return (const FX_WCHAR*)pValue; - } - return nullptr; -} - -bool GetAttributeDefaultValue_Boolean(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - uint32_t dwPacket) { - void* pValue; - if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute, - XFA_ATTRIBUTETYPE_Boolean, dwPacket)) { - return !!pValue; - } - return false; -} - -} // namespace - -CXFA_WidgetData::CXFA_WidgetData(CXFA_Node* pNode) - : CXFA_Data(pNode), - m_bIsNull(true), - m_bPreNull(true), - m_pUiChildNode(nullptr), - m_eUIType(XFA_Element::Unknown) {} - -CXFA_Node* CXFA_WidgetData::GetUIChild() { - if (m_eUIType == XFA_Element::Unknown) - m_pUiChildNode = CreateUIChild(m_pNode, m_eUIType); - - return m_pUiChildNode; -} - -XFA_Element CXFA_WidgetData::GetUIType() { - GetUIChild(); - return m_eUIType; -} - -CFX_WideString CXFA_WidgetData::GetRawValue() { - return m_pNode->GetContent(); -} - -int32_t CXFA_WidgetData::GetAccess(bool bTemplate) { - if (bTemplate) { - CXFA_Node* pNode = m_pNode->GetTemplateNode(); - if (pNode) - return pNode->GetEnum(XFA_ATTRIBUTE_Access); - return XFA_ATTRIBUTEENUM_Open; - } - CXFA_Node* pNode = m_pNode; - while (pNode) { - int32_t iAcc = pNode->GetEnum(XFA_ATTRIBUTE_Access); - if (iAcc != XFA_ATTRIBUTEENUM_Open) - return iAcc; - - pNode = - pNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode); - } - return XFA_ATTRIBUTEENUM_Open; -} - -int32_t CXFA_WidgetData::GetRotate() { - CXFA_Measurement ms; - if (!m_pNode->TryMeasure(XFA_ATTRIBUTE_Rotate, ms, false)) - return 0; - - int32_t iRotate = FXSYS_round(ms.GetValue()); - iRotate = XFA_MapRotation(iRotate); - return iRotate / 90 * 90; -} - -CXFA_Border CXFA_WidgetData::GetBorder(bool bModified) { - return CXFA_Border(m_pNode->GetProperty(0, XFA_Element::Border, bModified)); -} - -CXFA_Caption CXFA_WidgetData::GetCaption(bool bModified) { - return CXFA_Caption(m_pNode->GetProperty(0, XFA_Element::Caption, bModified)); -} - -CXFA_Font CXFA_WidgetData::GetFont(bool bModified) { - return CXFA_Font(m_pNode->GetProperty(0, XFA_Element::Font, bModified)); -} - -CXFA_Margin CXFA_WidgetData::GetMargin(bool bModified) { - return CXFA_Margin(m_pNode->GetProperty(0, XFA_Element::Margin, bModified)); -} - -CXFA_Para CXFA_WidgetData::GetPara(bool bModified) { - return CXFA_Para(m_pNode->GetProperty(0, XFA_Element::Para, bModified)); -} - -void CXFA_WidgetData::GetEventList(CXFA_NodeArray& events) { - m_pNode->GetNodeList(events, 0, XFA_Element::Event); -} - -int32_t CXFA_WidgetData::GetEventByActivity(int32_t iActivity, - CXFA_NodeArray& events, - bool bIsFormReady) { - CXFA_NodeArray allEvents; - GetEventList(allEvents); - int32_t iCount = allEvents.GetSize(); - for (int32_t i = 0; i < iCount; i++) { - CXFA_Event event(allEvents[i]); - if (event.GetActivity() == iActivity) { - if (iActivity == XFA_ATTRIBUTEENUM_Ready) { - CFX_WideStringC wsRef; - event.GetRef(wsRef); - if (bIsFormReady) { - if (wsRef == CFX_WideStringC(L"$form")) - events.Add(allEvents[i]); - } else { - if (wsRef == CFX_WideStringC(L"$layout")) - events.Add(allEvents[i]); - } - } else { - events.Add(allEvents[i]); - } - } - } - return events.GetSize(); -} - -CXFA_Value CXFA_WidgetData::GetDefaultValue(bool bModified) { - CXFA_Node* pTemNode = m_pNode->GetTemplateNode(); - return CXFA_Value( - pTemNode ? pTemNode->GetProperty(0, XFA_Element::Value, bModified) - : nullptr); -} - -CXFA_Value CXFA_WidgetData::GetFormValue(bool bModified) { - return CXFA_Value(m_pNode->GetProperty(0, XFA_Element::Value, bModified)); -} - -CXFA_Calculate CXFA_WidgetData::GetCalculate(bool bModified) { - return CXFA_Calculate( - m_pNode->GetProperty(0, XFA_Element::Calculate, bModified)); -} - -CXFA_Validate CXFA_WidgetData::GetValidate(bool bModified) { - return CXFA_Validate( - m_pNode->GetProperty(0, XFA_Element::Validate, bModified)); -} - -CXFA_Bind CXFA_WidgetData::GetBind(bool bModified) { - return CXFA_Bind(m_pNode->GetProperty(0, XFA_Element::Bind, bModified)); -} - -CXFA_Assist CXFA_WidgetData::GetAssist(bool bModified) { - return CXFA_Assist(m_pNode->GetProperty(0, XFA_Element::Assist, bModified)); -} - -bool CXFA_WidgetData::GetWidth(FX_FLOAT& fWidth) { - return TryMeasure(XFA_ATTRIBUTE_W, fWidth); -} - -bool CXFA_WidgetData::GetHeight(FX_FLOAT& fHeight) { - return TryMeasure(XFA_ATTRIBUTE_H, fHeight); -} - -bool CXFA_WidgetData::GetMinWidth(FX_FLOAT& fMinWidth) { - return TryMeasure(XFA_ATTRIBUTE_MinW, fMinWidth); -} - -bool CXFA_WidgetData::GetMinHeight(FX_FLOAT& fMinHeight) { - return TryMeasure(XFA_ATTRIBUTE_MinH, fMinHeight); -} - -bool CXFA_WidgetData::GetMaxWidth(FX_FLOAT& fMaxWidth) { - return TryMeasure(XFA_ATTRIBUTE_MaxW, fMaxWidth); -} - -bool CXFA_WidgetData::GetMaxHeight(FX_FLOAT& fMaxHeight) { - return TryMeasure(XFA_ATTRIBUTE_MaxH, fMaxHeight); -} - -CXFA_Border CXFA_WidgetData::GetUIBorder() { - CXFA_Node* pUIChild = GetUIChild(); - return CXFA_Border(pUIChild - ? pUIChild->GetProperty(0, XFA_Element::Border, false) - : nullptr); -} - -CFX_RectF CXFA_WidgetData::GetUIMargin() { - CXFA_Node* pUIChild = GetUIChild(); - CXFA_Margin mgUI = CXFA_Margin( - pUIChild ? pUIChild->GetProperty(0, XFA_Element::Margin, false) - : nullptr); - - if (!mgUI) - return CFX_RectF(); - - CXFA_Border border = GetUIBorder(); - if (border && border.GetPresence() != XFA_ATTRIBUTEENUM_Visible) - return CFX_RectF(); - - FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; - bool bLeft = mgUI.GetLeftInset(fLeftInset); - bool bTop = mgUI.GetTopInset(fTopInset); - bool bRight = mgUI.GetRightInset(fRightInset); - bool bBottom = mgUI.GetBottomInset(fBottomInset); - if (border) { - bool bVisible = false; - FX_FLOAT fThickness = 0; - border.Get3DStyle(bVisible, fThickness); - if (!bLeft || !bTop || !bRight || !bBottom) { - std::vector<CXFA_Stroke> strokes; - border.GetStrokes(&strokes); - if (!bTop) - fTopInset = GetEdgeThickness(strokes, bVisible, 0); - if (!bRight) - fRightInset = GetEdgeThickness(strokes, bVisible, 1); - if (!bBottom) - fBottomInset = GetEdgeThickness(strokes, bVisible, 2); - if (!bLeft) - fLeftInset = GetEdgeThickness(strokes, bVisible, 3); - } - } - return CFX_RectF(fLeftInset, fTopInset, fRightInset, fBottomInset); -} - -int32_t CXFA_WidgetData::GetButtonHighlight() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_Highlight); - return GetAttributeDefaultValue_Enum( - XFA_Element::Button, XFA_ATTRIBUTE_Highlight, XFA_XDPPACKET_Form); -} - -bool CXFA_WidgetData::GetButtonRollover(CFX_WideString& wsRollover, - bool& bRichText) { - if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) { - CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pText) { - CFX_WideStringC wsName; - pText->TryCData(XFA_ATTRIBUTE_Name, wsName); - if (wsName == L"rollover") { - pText->TryContent(wsRollover); - bRichText = pText->GetElementType() == XFA_Element::ExData; - return !wsRollover.IsEmpty(); - } - pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling); - } - } - return false; -} - -bool CXFA_WidgetData::GetButtonDown(CFX_WideString& wsDown, bool& bRichText) { - if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) { - CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pText) { - CFX_WideStringC wsName; - pText->TryCData(XFA_ATTRIBUTE_Name, wsName); - if (wsName == L"down") { - pText->TryContent(wsDown); - bRichText = pText->GetElementType() == XFA_Element::ExData; - return !wsDown.IsEmpty(); - } - pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling); - } - } - return false; -} - -int32_t CXFA_WidgetData::GetCheckButtonShape() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_Shape); - return GetAttributeDefaultValue_Enum(XFA_Element::CheckButton, - XFA_ATTRIBUTE_Shape, XFA_XDPPACKET_Form); -} - -int32_t CXFA_WidgetData::GetCheckButtonMark() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_Mark); - return GetAttributeDefaultValue_Enum(XFA_Element::CheckButton, - XFA_ATTRIBUTE_Mark, XFA_XDPPACKET_Form); -} - -bool CXFA_WidgetData::IsRadioButton() { - if (CXFA_Node* pParent = m_pNode->GetNodeItem(XFA_NODEITEM_Parent)) - return pParent->GetElementType() == XFA_Element::ExclGroup; - return false; -} - -FX_FLOAT CXFA_WidgetData::GetCheckButtonSize() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetMeasure(XFA_ATTRIBUTE_Size).ToUnit(XFA_UNIT_Pt); - return XFA_GetAttributeDefaultValue_Measure( - XFA_Element::CheckButton, XFA_ATTRIBUTE_Size, XFA_XDPPACKET_Form) - .ToUnit(XFA_UNIT_Pt); -} - -bool CXFA_WidgetData::IsAllowNeutral() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetBoolean(XFA_ATTRIBUTE_AllowNeutral); - return GetAttributeDefaultValue_Boolean( - XFA_Element::CheckButton, XFA_ATTRIBUTE_AllowNeutral, XFA_XDPPACKET_Form); -} - -XFA_CHECKSTATE CXFA_WidgetData::GetCheckState() { - CFX_WideString wsValue = GetRawValue(); - if (wsValue.IsEmpty()) - return XFA_CHECKSTATE_Off; - - if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) { - CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); - int32_t i = 0; - while (pText) { - CFX_WideString wsContent; - if (pText->TryContent(wsContent) && (wsContent == wsValue)) - return (XFA_CHECKSTATE)i; - - i++; - pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling); - } - } - return XFA_CHECKSTATE_Off; -} - -void CXFA_WidgetData::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) { - CXFA_WidgetData exclGroup(GetExclGroupNode()); - if (exclGroup) { - CFX_WideString wsValue; - if (eCheckState != XFA_CHECKSTATE_Off) { - if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) { - CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pText) - pText->TryContent(wsValue); - } - } - CXFA_Node* pChild = - exclGroup.GetNode()->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pChild->GetElementType() != XFA_Element::Field) - continue; - - CXFA_Node* pItem = pChild->GetChild(0, XFA_Element::Items); - if (!pItem) - continue; - - CXFA_Node* pItemchild = pItem->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pItemchild) - continue; - - CFX_WideString text = pItemchild->GetContent(); - CFX_WideString wsChildValue = text; - if (wsValue != text) { - pItemchild = pItemchild->GetNodeItem(XFA_NODEITEM_NextSibling); - if (pItemchild) - wsChildValue = pItemchild->GetContent(); - else - wsChildValue.clear(); - } - CXFA_WidgetData ch(pChild); - ch.SyncValue(wsChildValue, bNotify); - } - exclGroup.SyncValue(wsValue, bNotify); - } else { - CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items); - if (!pItems) - return; - - int32_t i = -1; - CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); - CFX_WideString wsContent; - while (pText) { - i++; - if (i == eCheckState) { - pText->TryContent(wsContent); - break; - } - pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling); - } - SyncValue(wsContent, bNotify); - } -} - -CXFA_Node* CXFA_WidgetData::GetExclGroupNode() { - CXFA_Node* pExcl = ToNode(m_pNode->GetNodeItem(XFA_NODEITEM_Parent)); - if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup) - return nullptr; - return pExcl; -} - -CXFA_Node* CXFA_WidgetData::GetSelectedMember() { - CXFA_Node* pSelectedMember = nullptr; - CFX_WideString wsState = GetRawValue(); - if (wsState.IsEmpty()) - return pSelectedMember; - - for (CXFA_Node* pNode = ToNode(m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild)); - pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - CXFA_WidgetData widgetData(pNode); - if (widgetData.GetCheckState() == XFA_CHECKSTATE_On) { - pSelectedMember = pNode; - break; - } - } - return pSelectedMember; -} - -CXFA_Node* CXFA_WidgetData::SetSelectedMember(const CFX_WideStringC& wsName, - bool bNotify) { - uint32_t nameHash = FX_HashCode_GetW(wsName, false); - for (CXFA_Node* pNode = ToNode(m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild)); - pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetNameHash() == nameHash) { - CXFA_WidgetData widgetData(pNode); - widgetData.SetCheckState(XFA_CHECKSTATE_On, bNotify); - return pNode; - } - } - return nullptr; -} - -void CXFA_WidgetData::SetSelectedMemberByValue(const CFX_WideStringC& wsValue, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - CFX_WideString wsExclGroup; - for (CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); pNode; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() != XFA_Element::Field) - continue; - - CXFA_Node* pItem = pNode->GetChild(0, XFA_Element::Items); - if (!pItem) - continue; - - CXFA_Node* pItemchild = pItem->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pItemchild) - continue; - - CFX_WideString wsChildValue = pItemchild->GetContent(); - if (wsValue != wsChildValue) { - pItemchild = pItemchild->GetNodeItem(XFA_NODEITEM_NextSibling); - if (pItemchild) - wsChildValue = pItemchild->GetContent(); - else - wsChildValue.clear(); - } else { - wsExclGroup = wsValue; - } - pNode->SetContent(wsChildValue, wsChildValue, bNotify, bScriptModify, - false); - } - if (m_pNode) { - m_pNode->SetContent(wsExclGroup, wsExclGroup, bNotify, bScriptModify, - bSyncData); - } -} - -CXFA_Node* CXFA_WidgetData::GetExclGroupFirstMember() { - CXFA_Node* pExcl = GetNode(); - if (!pExcl) - return nullptr; - - CXFA_Node* pNode = pExcl->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pNode) { - if (pNode->GetElementType() == XFA_Element::Field) - return pNode; - - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - return nullptr; -} -CXFA_Node* CXFA_WidgetData::GetExclGroupNextMember(CXFA_Node* pNode) { - if (!pNode) - return nullptr; - - CXFA_Node* pNodeField = pNode->GetNodeItem(XFA_NODEITEM_NextSibling); - while (pNodeField) { - if (pNodeField->GetElementType() == XFA_Element::Field) - return pNodeField; - - pNodeField = pNodeField->GetNodeItem(XFA_NODEITEM_NextSibling); - } - return nullptr; -} - -int32_t CXFA_WidgetData::GetChoiceListCommitOn() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_CommitOn); - return GetAttributeDefaultValue_Enum( - XFA_Element::ChoiceList, XFA_ATTRIBUTE_CommitOn, XFA_XDPPACKET_Form); -} - -bool CXFA_WidgetData::IsChoiceListAllowTextEntry() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetBoolean(XFA_ATTRIBUTE_TextEntry); - return GetAttributeDefaultValue_Boolean( - XFA_Element::ChoiceList, XFA_ATTRIBUTE_TextEntry, XFA_XDPPACKET_Form); -} - -int32_t CXFA_WidgetData::GetChoiceListOpen() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_Open); - return GetAttributeDefaultValue_Enum(XFA_Element::ChoiceList, - XFA_ATTRIBUTE_Open, XFA_XDPPACKET_Form); -} - -bool CXFA_WidgetData::IsListBox() { - int32_t iOpenMode = GetChoiceListOpen(); - return (iOpenMode == XFA_ATTRIBUTEENUM_Always || - iOpenMode == XFA_ATTRIBUTEENUM_MultiSelect); -} - -int32_t CXFA_WidgetData::CountChoiceListItems(bool bSaveValue) { - CXFA_NodeArray pItems; - CXFA_Node* pItem = nullptr; - int32_t iCount = 0; - CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() != XFA_Element::Items) - continue; - - iCount++; - pItems.Add(pNode); - if (iCount == 2) - break; - } - if (iCount == 0) - return 0; - - pItem = pItems[0]; - if (iCount > 1) { - bool bItemOneHasSave = pItems[0]->GetBoolean(XFA_ATTRIBUTE_Save); - bool bItemTwoHasSave = pItems[1]->GetBoolean(XFA_ATTRIBUTE_Save); - if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) - pItem = pItems[1]; - } - pItems.RemoveAll(); - return pItem->CountChildren(XFA_Element::Unknown); -} - -bool CXFA_WidgetData::GetChoiceListItem(CFX_WideString& wsText, - int32_t nIndex, - bool bSaveValue) { - wsText.clear(); - CXFA_NodeArray pItemsArray; - CXFA_Node* pItems = nullptr; - int32_t iCount = 0; - CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() != XFA_Element::Items) - continue; - - iCount++; - pItemsArray.Add(pNode); - if (iCount == 2) - break; - } - if (iCount == 0) - return false; - - pItems = pItemsArray[0]; - if (iCount > 1) { - bool bItemOneHasSave = pItemsArray[0]->GetBoolean(XFA_ATTRIBUTE_Save); - bool bItemTwoHasSave = pItemsArray[1]->GetBoolean(XFA_ATTRIBUTE_Save); - if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) - pItems = pItemsArray[1]; - } - if (pItems) { - CXFA_Node* pItem = pItems->GetChild(nIndex, XFA_Element::Unknown); - if (pItem) { - pItem->TryContent(wsText); - return true; - } - } - return false; -} - -void CXFA_WidgetData::GetChoiceListItems( - std::vector<CFX_WideString>& wsTextArray, - bool bSaveValue) { - CXFA_NodeArray pItems; - CXFA_Node* pItem = nullptr; - int32_t iCount = 0; - CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pNode->GetElementType() != XFA_Element::Items) - continue; - - iCount++; - pItems.Add(pNode); - if (iCount == 2) - break; - } - if (iCount == 0) - return; - - pItem = pItems[0]; - if (iCount > 1) { - bool bItemOneHasSave = pItems[0]->GetBoolean(XFA_ATTRIBUTE_Save); - bool bItemTwoHasSave = pItems[1]->GetBoolean(XFA_ATTRIBUTE_Save); - if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave) - pItem = pItems[1]; - } - pItems.RemoveAll(); - pNode = pItem->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - wsTextArray.emplace_back(); - pNode->TryContent(wsTextArray.back()); - } -} - -int32_t CXFA_WidgetData::CountSelectedItems() { - std::vector<CFX_WideString> wsValueArray; - GetSelectedItemsValue(wsValueArray); - if (IsListBox() || !IsChoiceListAllowTextEntry()) - return pdfium::CollectionSize<int32_t>(wsValueArray); - - int32_t iSelected = 0; - std::vector<CFX_WideString> wsSaveTextArray; - GetChoiceListItems(wsSaveTextArray, true); - int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray); - for (int32_t i = 0; i < iValues; i++) { - int32_t iSaves = pdfium::CollectionSize<int32_t>(wsSaveTextArray); - for (int32_t j = 0; j < iSaves; j++) { - if (wsValueArray[i] == wsSaveTextArray[j]) { - iSelected++; - break; - } - } - } - return iSelected; -} - -int32_t CXFA_WidgetData::GetSelectedItem(int32_t nIndex) { - std::vector<CFX_WideString> wsValueArray; - GetSelectedItemsValue(wsValueArray); - std::vector<CFX_WideString> wsSaveTextArray; - GetChoiceListItems(wsSaveTextArray, true); - int32_t iSaves = pdfium::CollectionSize<int32_t>(wsSaveTextArray); - for (int32_t j = 0; j < iSaves; j++) { - if (wsValueArray[nIndex] == wsSaveTextArray[j]) - return j; - } - return -1; -} - -void CXFA_WidgetData::GetSelectedItems(CFX_ArrayTemplate<int32_t>& iSelArray) { - std::vector<CFX_WideString> wsValueArray; - GetSelectedItemsValue(wsValueArray); - int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray); - if (iValues < 1) - return; - - std::vector<CFX_WideString> wsSaveTextArray; - GetChoiceListItems(wsSaveTextArray, true); - int32_t iSaves = pdfium::CollectionSize<int32_t>(wsSaveTextArray); - for (int32_t i = 0; i < iValues; i++) { - for (int32_t j = 0; j < iSaves; j++) { - if (wsValueArray[i] == wsSaveTextArray[j]) { - iSelArray.Add(j); - break; - } - } - } -} - -void CXFA_WidgetData::GetSelectedItemsValue( - std::vector<CFX_WideString>& wsSelTextArray) { - CFX_WideString wsValue = GetRawValue(); - if (GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) { - if (!wsValue.IsEmpty()) { - int32_t iStart = 0; - int32_t iLength = wsValue.GetLength(); - int32_t iEnd = wsValue.Find(L'\n', iStart); - iEnd = (iEnd == -1) ? iLength : iEnd; - while (iEnd >= iStart) { - wsSelTextArray.push_back(wsValue.Mid(iStart, iEnd - iStart)); - iStart = iEnd + 1; - if (iStart >= iLength) - break; - - iEnd = wsValue.Find(L'\n', iStart); - if (iEnd < 0) - wsSelTextArray.push_back(wsValue.Mid(iStart, iLength - iStart)); - } - } - } else { - wsSelTextArray.push_back(wsValue); - } -} - -bool CXFA_WidgetData::GetItemState(int32_t nIndex) { - if (nIndex < 0) - return false; - - std::vector<CFX_WideString> wsSaveTextArray; - GetChoiceListItems(wsSaveTextArray, true); - if (pdfium::CollectionSize<int32_t>(wsSaveTextArray) <= nIndex) - return false; - - std::vector<CFX_WideString> wsValueArray; - GetSelectedItemsValue(wsValueArray); - int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray); - for (int32_t j = 0; j < iValues; j++) { - if (wsValueArray[j] == wsSaveTextArray[nIndex]) - return true; - } - return false; -} - -void CXFA_WidgetData::SetItemState(int32_t nIndex, - bool bSelected, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - if (nIndex < 0) - return; - - std::vector<CFX_WideString> wsSaveTextArray; - GetChoiceListItems(wsSaveTextArray, true); - if (pdfium::CollectionSize<int32_t>(wsSaveTextArray) <= nIndex) - return; - - int32_t iSel = -1; - std::vector<CFX_WideString> wsValueArray; - GetSelectedItemsValue(wsValueArray); - int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray); - for (int32_t j = 0; j < iValues; j++) { - if (wsValueArray[j] == wsSaveTextArray[nIndex]) { - iSel = j; - break; - } - } - if (GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) { - if (bSelected) { - if (iSel < 0) { - CFX_WideString wsValue = GetRawValue(); - if (!wsValue.IsEmpty()) { - wsValue += L"\n"; - } - wsValue += wsSaveTextArray[nIndex]; - m_pNode->SetContent(wsValue, wsValue, bNotify, bScriptModify, - bSyncData); - } - } else if (iSel >= 0) { - CFX_ArrayTemplate<int32_t> iSelArray; - GetSelectedItems(iSelArray); - for (int32_t i = 0; i < iSelArray.GetSize(); i++) { - if (iSelArray[i] == nIndex) { - iSelArray.RemoveAt(i); - break; - } - } - SetSelectedItems(iSelArray, bNotify, bScriptModify, bSyncData); - } - } else { - if (bSelected) { - if (iSel < 0) { - CFX_WideString wsSaveText = wsSaveTextArray[nIndex]; - CFX_WideString wsFormatText(wsSaveText); - GetFormatDataValue(wsSaveText, wsFormatText); - m_pNode->SetContent(wsSaveText, wsFormatText, bNotify, bScriptModify, - bSyncData); - } - } else if (iSel >= 0) { - m_pNode->SetContent(CFX_WideString(), CFX_WideString(), bNotify, - bScriptModify, bSyncData); - } - } -} - -void CXFA_WidgetData::SetSelectedItems(CFX_ArrayTemplate<int32_t>& iSelArray, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - CFX_WideString wsValue; - int32_t iSize = iSelArray.GetSize(); - if (iSize >= 1) { - std::vector<CFX_WideString> wsSaveTextArray; - GetChoiceListItems(wsSaveTextArray, true); - CFX_WideString wsItemValue; - for (int32_t i = 0; i < iSize; i++) { - wsItemValue = (iSize == 1) ? wsSaveTextArray[iSelArray[i]] - : wsSaveTextArray[iSelArray[i]] + L"\n"; - wsValue += wsItemValue; - } - } - CFX_WideString wsFormat(wsValue); - if (GetChoiceListOpen() != XFA_ATTRIBUTEENUM_MultiSelect) - GetFormatDataValue(wsValue, wsFormat); - - m_pNode->SetContent(wsValue, wsFormat, bNotify, bScriptModify, bSyncData); -} - -void CXFA_WidgetData::ClearAllSelections() { - CXFA_Node* pBind = m_pNode->GetBindData(); - if (!pBind || GetChoiceListOpen() != XFA_ATTRIBUTEENUM_MultiSelect) { - SyncValue(CFX_WideString(), false); - return; - } - - while (CXFA_Node* pChildNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild)) - pBind->RemoveChild(pChildNode); -} - -void CXFA_WidgetData::InsertItem(const CFX_WideString& wsLabel, - const CFX_WideString& wsValue, - int32_t nIndex, - bool bNotify) { - CFX_WideString wsNewValue(wsValue); - if (wsNewValue.IsEmpty()) - wsNewValue = wsLabel; - - CXFA_NodeArray listitems; - int32_t iCount = 0; - CXFA_Node* pItemNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pItemNode; - pItemNode = pItemNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pItemNode->GetElementType() != XFA_Element::Items) - continue; - - listitems.Add(pItemNode); - iCount++; - } - if (iCount < 1) { - CXFA_Node* pItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); - m_pNode->InsertChild(-1, pItems); - InsertListTextItem(pItems, wsLabel, nIndex); - CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); - m_pNode->InsertChild(-1, pSaveItems); - pSaveItems->SetBoolean(XFA_ATTRIBUTE_Save, true); - InsertListTextItem(pSaveItems, wsNewValue, nIndex); - } else if (iCount > 1) { - for (int32_t i = 0; i < 2; i++) { - CXFA_Node* pNode = listitems[i]; - bool bHasSave = pNode->GetBoolean(XFA_ATTRIBUTE_Save); - if (bHasSave) - InsertListTextItem(pNode, wsNewValue, nIndex); - else - InsertListTextItem(pNode, wsLabel, nIndex); - } - } else { - CXFA_Node* pNode = listitems[0]; - pNode->SetBoolean(XFA_ATTRIBUTE_Save, false); - pNode->SetEnum(XFA_ATTRIBUTE_Presence, XFA_ATTRIBUTEENUM_Visible); - CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items); - m_pNode->InsertChild(-1, pSaveItems); - pSaveItems->SetBoolean(XFA_ATTRIBUTE_Save, true); - pSaveItems->SetEnum(XFA_ATTRIBUTE_Presence, XFA_ATTRIBUTEENUM_Hidden); - listitems.RemoveAll(); - CXFA_Node* pListNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - int32_t i = 0; - while (pListNode) { - CFX_WideString wsOldValue; - pListNode->TryContent(wsOldValue); - InsertListTextItem(pSaveItems, wsOldValue, i); - i++; - pListNode = pListNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - InsertListTextItem(pNode, wsLabel, nIndex); - InsertListTextItem(pSaveItems, wsNewValue, nIndex); - } - if (!bNotify) - return; - - m_pNode->GetDocument()->GetNotify()->OnWidgetListItemAdded( - this, wsLabel.c_str(), wsValue.c_str(), nIndex); -} - -void CXFA_WidgetData::GetItemLabel(const CFX_WideStringC& wsValue, - CFX_WideString& wsLabel) { - int32_t iCount = 0; - CXFA_NodeArray listitems; - CXFA_Node* pItems = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pItems; pItems = pItems->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pItems->GetElementType() != XFA_Element::Items) - continue; - - iCount++; - listitems.Add(pItems); - } - if (iCount <= 1) { - wsLabel = wsValue; - } else { - CXFA_Node* pLabelItems = listitems[0]; - bool bSave = pLabelItems->GetBoolean(XFA_ATTRIBUTE_Save); - CXFA_Node* pSaveItems = nullptr; - if (bSave) { - pSaveItems = pLabelItems; - pLabelItems = listitems[1]; - } else { - pSaveItems = listitems[1]; - } - iCount = 0; - int32_t iSearch = -1; - CFX_WideString wsContent; - CXFA_Node* pChildItem = pSaveItems->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pChildItem; - pChildItem = pChildItem->GetNodeItem(XFA_NODEITEM_NextSibling)) { - pChildItem->TryContent(wsContent); - if (wsContent == wsValue) { - iSearch = iCount; - break; - } - iCount++; - } - if (iSearch < 0) - return; - if (CXFA_Node* pText = - pLabelItems->GetChild(iSearch, XFA_Element::Unknown)) { - pText->TryContent(wsLabel); - } - } -} - -void CXFA_WidgetData::GetItemValue(const CFX_WideStringC& wsLabel, - CFX_WideString& wsValue) { - int32_t iCount = 0; - CXFA_NodeArray listitems; - CXFA_Node* pItems = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pItems; pItems = pItems->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pItems->GetElementType() != XFA_Element::Items) - continue; - - iCount++; - listitems.Add(pItems); - } - if (iCount <= 1) { - wsValue = wsLabel; - } else { - CXFA_Node* pLabelItems = listitems[0]; - bool bSave = pLabelItems->GetBoolean(XFA_ATTRIBUTE_Save); - CXFA_Node* pSaveItems = nullptr; - if (bSave) { - pSaveItems = pLabelItems; - pLabelItems = listitems[1]; - } else { - pSaveItems = listitems[1]; - } - iCount = 0; - int32_t iSearch = -1; - CFX_WideString wsContent; - CXFA_Node* pChildItem = pLabelItems->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pChildItem; - pChildItem = pChildItem->GetNodeItem(XFA_NODEITEM_NextSibling)) { - pChildItem->TryContent(wsContent); - if (wsContent == wsLabel) { - iSearch = iCount; - break; - } - iCount++; - } - if (iSearch < 0) - return; - if (CXFA_Node* pText = pSaveItems->GetChild(iSearch, XFA_Element::Unknown)) - pText->TryContent(wsValue); - } -} - -bool CXFA_WidgetData::DeleteItem(int32_t nIndex, - bool bNotify, - bool bScriptModify, - bool bSyncData) { - bool bSetValue = false; - CXFA_Node* pItems = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pItems; pItems = pItems->GetNodeItem(XFA_NODEITEM_NextSibling)) { - if (pItems->GetElementType() != XFA_Element::Items) - continue; - - if (nIndex < 0) { - while (CXFA_Node* pNode = pItems->GetNodeItem(XFA_NODEITEM_FirstChild)) { - pItems->RemoveChild(pNode); - } - } else { - if (!bSetValue && pItems->GetBoolean(XFA_ATTRIBUTE_Save)) { - SetItemState(nIndex, false, true, bScriptModify, bSyncData); - bSetValue = true; - } - int32_t i = 0; - CXFA_Node* pNode = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pNode) { - if (i == nIndex) { - pItems->RemoveChild(pNode); - break; - } - i++; - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - } - } - if (bNotify) - m_pNode->GetDocument()->GetNotify()->OnWidgetListItemRemoved(this, nIndex); - return true; -} - -int32_t CXFA_WidgetData::GetHorizontalScrollPolicy() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_HScrollPolicy); - return XFA_ATTRIBUTEENUM_Auto; -} - -int32_t CXFA_WidgetData::GetNumberOfCells() { - CXFA_Node* pUIChild = GetUIChild(); - if (!pUIChild) - return -1; - if (CXFA_Node* pNode = pUIChild->GetChild(0, XFA_Element::Comb)) - return pNode->GetInteger(XFA_ATTRIBUTE_NumberOfCells); - return -1; -} - -CFX_WideString CXFA_WidgetData::GetBarcodeType() { - CXFA_Node* pUIChild = GetUIChild(); - return pUIChild ? CFX_WideString(pUIChild->GetCData(XFA_ATTRIBUTE_Type)) - : CFX_WideString(); -} - -bool CXFA_WidgetData::GetBarcodeAttribute_CharEncoding(int32_t& val) { - CXFA_Node* pUIChild = GetUIChild(); - CFX_WideString wsCharEncoding; - if (pUIChild->TryCData(XFA_ATTRIBUTE_CharEncoding, wsCharEncoding)) { - if (wsCharEncoding.CompareNoCase(L"UTF-16")) { - val = CHAR_ENCODING_UNICODE; - return true; - } - if (wsCharEncoding.CompareNoCase(L"UTF-8")) { - val = CHAR_ENCODING_UTF8; - return true; - } - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_Checksum(bool& val) { - CXFA_Node* pUIChild = GetUIChild(); - XFA_ATTRIBUTEENUM eChecksum; - if (pUIChild->TryEnum(XFA_ATTRIBUTE_Checksum, eChecksum)) { - switch (eChecksum) { - case XFA_ATTRIBUTEENUM_None: - val = false; - return true; - case XFA_ATTRIBUTEENUM_Auto: - val = true; - return true; - case XFA_ATTRIBUTEENUM_1mod10: - break; - case XFA_ATTRIBUTEENUM_1mod10_1mod11: - break; - case XFA_ATTRIBUTEENUM_2mod10: - break; - default: - break; - } - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_DataLength(int32_t& val) { - CXFA_Node* pUIChild = GetUIChild(); - CFX_WideString wsDataLength; - if (pUIChild->TryCData(XFA_ATTRIBUTE_DataLength, wsDataLength)) { - val = FXSYS_wtoi(wsDataLength.c_str()); - return true; - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_StartChar(FX_CHAR& val) { - CXFA_Node* pUIChild = GetUIChild(); - CFX_WideStringC wsStartEndChar; - if (pUIChild->TryCData(XFA_ATTRIBUTE_StartChar, wsStartEndChar)) { - if (wsStartEndChar.GetLength()) { - val = (FX_CHAR)wsStartEndChar.GetAt(0); - return true; - } - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_EndChar(FX_CHAR& val) { - CXFA_Node* pUIChild = GetUIChild(); - CFX_WideStringC wsStartEndChar; - if (pUIChild->TryCData(XFA_ATTRIBUTE_EndChar, wsStartEndChar)) { - if (wsStartEndChar.GetLength()) { - val = (FX_CHAR)wsStartEndChar.GetAt(0); - return true; - } - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_ECLevel(int32_t& val) { - CXFA_Node* pUIChild = GetUIChild(); - CFX_WideString wsECLevel; - if (pUIChild->TryCData(XFA_ATTRIBUTE_ErrorCorrectionLevel, wsECLevel)) { - val = FXSYS_wtoi(wsECLevel.c_str()); - return true; - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_ModuleWidth(int32_t& val) { - CXFA_Node* pUIChild = GetUIChild(); - CXFA_Measurement mModuleWidthHeight; - if (pUIChild->TryMeasure(XFA_ATTRIBUTE_ModuleWidth, mModuleWidthHeight)) { - val = (int32_t)mModuleWidthHeight.ToUnit(XFA_UNIT_Pt); - return true; - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_ModuleHeight(int32_t& val) { - CXFA_Node* pUIChild = GetUIChild(); - CXFA_Measurement mModuleWidthHeight; - if (pUIChild->TryMeasure(XFA_ATTRIBUTE_ModuleHeight, mModuleWidthHeight)) { - val = (int32_t)mModuleWidthHeight.ToUnit(XFA_UNIT_Pt); - return true; - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_PrintChecksum(bool& val) { - CXFA_Node* pUIChild = GetUIChild(); - bool bPrintCheckDigit; - if (pUIChild->TryBoolean(XFA_ATTRIBUTE_PrintCheckDigit, bPrintCheckDigit)) { - val = bPrintCheckDigit; - return true; - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_TextLocation(int32_t& val) { - CXFA_Node* pUIChild = GetUIChild(); - XFA_ATTRIBUTEENUM eTextLocation; - if (pUIChild->TryEnum(XFA_ATTRIBUTE_TextLocation, eTextLocation)) { - switch (eTextLocation) { - case XFA_ATTRIBUTEENUM_None: - val = BC_TEXT_LOC_NONE; - return true; - case XFA_ATTRIBUTEENUM_Above: - val = BC_TEXT_LOC_ABOVE; - return true; - case XFA_ATTRIBUTEENUM_Below: - val = BC_TEXT_LOC_BELOW; - return true; - case XFA_ATTRIBUTEENUM_AboveEmbedded: - val = BC_TEXT_LOC_ABOVEEMBED; - return true; - case XFA_ATTRIBUTEENUM_BelowEmbedded: - val = BC_TEXT_LOC_BELOWEMBED; - return true; - default: - break; - } - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_Truncate(bool& val) { - CXFA_Node* pUIChild = GetUIChild(); - bool bTruncate; - if (pUIChild->TryBoolean(XFA_ATTRIBUTE_Truncate, bTruncate)) { - val = bTruncate; - return true; - } - return false; -} - -bool CXFA_WidgetData::GetBarcodeAttribute_WideNarrowRatio(FX_FLOAT& val) { - CXFA_Node* pUIChild = GetUIChild(); - CFX_WideString wsWideNarrowRatio; - if (pUIChild->TryCData(XFA_ATTRIBUTE_WideNarrowRatio, wsWideNarrowRatio)) { - FX_STRSIZE ptPos = wsWideNarrowRatio.Find(':'); - FX_FLOAT fRatio = 0; - if (ptPos >= 0) { - fRatio = (FX_FLOAT)FXSYS_wtoi(wsWideNarrowRatio.c_str()); - } else { - int32_t fA, fB; - fA = FXSYS_wtoi(wsWideNarrowRatio.Left(ptPos).c_str()); - fB = FXSYS_wtoi(wsWideNarrowRatio.Mid(ptPos + 1).c_str()); - if (fB) - fRatio = (FX_FLOAT)fA / fB; - } - val = fRatio; - return true; - } - return false; -} - -void CXFA_WidgetData::GetPasswordChar(CFX_WideString& wsPassWord) { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) { - pUIChild->TryCData(XFA_ATTRIBUTE_PasswordChar, wsPassWord); - } else { - wsPassWord = GetAttributeDefaultValue_Cdata(XFA_Element::PasswordEdit, - XFA_ATTRIBUTE_PasswordChar, - XFA_XDPPACKET_Form); - } -} - -bool CXFA_WidgetData::IsMultiLine() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetBoolean(XFA_ATTRIBUTE_MultiLine); - return GetAttributeDefaultValue_Boolean( - XFA_Element::TextEdit, XFA_ATTRIBUTE_MultiLine, XFA_XDPPACKET_Form); -} - -int32_t CXFA_WidgetData::GetVerticalScrollPolicy() { - CXFA_Node* pUIChild = GetUIChild(); - if (pUIChild) - return pUIChild->GetEnum(XFA_ATTRIBUTE_VScrollPolicy); - return GetAttributeDefaultValue_Enum( - XFA_Element::TextEdit, XFA_ATTRIBUTE_VScrollPolicy, XFA_XDPPACKET_Form); -} - -int32_t CXFA_WidgetData::GetMaxChars(XFA_Element& eType) { - if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Value)) { - if (CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild)) { - switch (pChild->GetElementType()) { - case XFA_Element::Text: - eType = XFA_Element::Text; - return pChild->GetInteger(XFA_ATTRIBUTE_MaxChars); - case XFA_Element::ExData: { - eType = XFA_Element::ExData; - int32_t iMax = pChild->GetInteger(XFA_ATTRIBUTE_MaxLength); - return iMax < 0 ? 0 : iMax; - } - default: - break; - } - } - } - return 0; -} - -bool CXFA_WidgetData::GetFracDigits(int32_t& iFracDigits) { - if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Value)) { - if (CXFA_Node* pChild = pNode->GetChild(0, XFA_Element::Decimal)) - return pChild->TryInteger(XFA_ATTRIBUTE_FracDigits, iFracDigits); - } - iFracDigits = -1; - return false; -} - -bool CXFA_WidgetData::GetLeadDigits(int32_t& iLeadDigits) { - if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Value)) { - if (CXFA_Node* pChild = pNode->GetChild(0, XFA_Element::Decimal)) - return pChild->TryInteger(XFA_ATTRIBUTE_LeadDigits, iLeadDigits); - } - iLeadDigits = -1; - return false; -} - -bool CXFA_WidgetData::SetValue(const CFX_WideString& wsValue, - XFA_VALUEPICTURE eValueType) { - if (wsValue.IsEmpty()) { - SyncValue(wsValue, true); - return true; - } - m_bPreNull = m_bIsNull; - m_bIsNull = false; - CFX_WideString wsNewText(wsValue); - CFX_WideString wsPicture; - GetPictureContent(wsPicture, eValueType); - bool bValidate = true; - bool bSyncData = false; - CXFA_Node* pNode = GetUIChild(); - if (!pNode) - return true; - - XFA_Element eType = pNode->GetElementType(); - if (!wsPicture.IsEmpty()) { - CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); - IFX_Locale* pLocale = GetLocal(); - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); - bValidate = - widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture); - if (bValidate) { - widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText, - wsPicture, pLocale, pLocalMgr); - wsNewText = widgetValue.GetValue(); - if (eType == XFA_Element::NumericEdit) { - int32_t iLeadDigits = 0; - int32_t iFracDigits = 0; - GetLeadDigits(iLeadDigits); - GetFracDigits(iFracDigits); - wsNewText = NumericLimit(wsNewText, iLeadDigits, iFracDigits); - } - bSyncData = true; - } - } else { - if (eType == XFA_Element::NumericEdit) { - if (wsNewText != L"0") { - int32_t iLeadDigits = 0; - int32_t iFracDigits = 0; - GetLeadDigits(iLeadDigits); - GetFracDigits(iFracDigits); - wsNewText = NumericLimit(wsNewText, iLeadDigits, iFracDigits); - } - bSyncData = true; - } - } - if (eType != XFA_Element::NumericEdit || bSyncData) - SyncValue(wsNewText, true); - - return bValidate; -} - -bool CXFA_WidgetData::GetPictureContent(CFX_WideString& wsPicture, - XFA_VALUEPICTURE ePicture) { - if (ePicture == XFA_VALUEPICTURE_Raw) - return false; - - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); - switch (ePicture) { - case XFA_VALUEPICTURE_Display: { - if (CXFA_Node* pFormat = m_pNode->GetChild(0, XFA_Element::Format)) { - if (CXFA_Node* pPicture = pFormat->GetChild(0, XFA_Element::Picture)) { - if (pPicture->TryContent(wsPicture)) - return true; - } - } - CFX_WideString wsDataPicture, wsTimePicture; - IFX_Locale* pLocale = GetLocal(); - if (!pLocale) - return false; - - uint32_t dwType = widgetValue.GetType(); - switch (dwType) { - case XFA_VT_DATE: - pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium, - wsPicture); - break; - case XFA_VT_TIME: - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium, - wsPicture); - break; - case XFA_VT_DATETIME: - pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium, - wsDataPicture); - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium, - wsTimePicture); - wsPicture = wsDataPicture + L"T" + wsTimePicture; - break; - case XFA_VT_DECIMAL: - case XFA_VT_FLOAT: - break; - default: - break; - } - return true; - } - - case XFA_VALUEPICTURE_Edit: { - CXFA_Node* pUI = m_pNode->GetChild(0, XFA_Element::Ui); - if (pUI) { - if (CXFA_Node* pPicture = pUI->GetChild(0, XFA_Element::Picture)) { - if (pPicture->TryContent(wsPicture)) - return true; - } - } - { - CFX_WideString wsDataPicture, wsTimePicture; - IFX_Locale* pLocale = GetLocal(); - if (!pLocale) { - return false; - } - uint32_t dwType = widgetValue.GetType(); - switch (dwType) { - case XFA_VT_DATE: - pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short, - wsPicture); - break; - case XFA_VT_TIME: - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short, - wsPicture); - break; - case XFA_VT_DATETIME: - pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short, - wsDataPicture); - pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short, - wsTimePicture); - wsPicture = wsDataPicture + L"T" + wsTimePicture; - break; - default: - break; - } - } - return true; - } - case XFA_VALUEPICTURE_DataBind: { - if (CXFA_Bind bind = GetBind()) { - bind.GetPicture(wsPicture); - return true; - } - break; - } - default: - break; - } - return false; -} - -IFX_Locale* CXFA_WidgetData::GetLocal() { - if (!m_pNode) - return nullptr; - - CFX_WideString wsLocaleName; - if (!m_pNode->GetLocaleName(wsLocaleName)) - return nullptr; - if (wsLocaleName == L"ambient") - return m_pNode->GetDocument()->GetLocalMgr()->GetDefLocale(); - return m_pNode->GetDocument()->GetLocalMgr()->GetLocaleByName(wsLocaleName); -} - -bool CXFA_WidgetData::GetValue(CFX_WideString& wsValue, - XFA_VALUEPICTURE eValueType) { - wsValue = m_pNode->GetContent(); - - if (eValueType == XFA_VALUEPICTURE_Display) - GetItemLabel(wsValue.AsStringC(), wsValue); - - CFX_WideString wsPicture; - GetPictureContent(wsPicture, eValueType); - CXFA_Node* pNode = GetUIChild(); - if (!pNode) - return true; - - switch (GetUIChild()->GetElementType()) { - case XFA_Element::ChoiceList: { - if (eValueType == XFA_VALUEPICTURE_Display) { - int32_t iSelItemIndex = GetSelectedItem(0); - if (iSelItemIndex >= 0) { - GetChoiceListItem(wsValue, iSelItemIndex); - wsPicture.clear(); - } - } - } break; - case XFA_Element::NumericEdit: - if (eValueType != XFA_VALUEPICTURE_Raw && wsPicture.IsEmpty()) { - IFX_Locale* pLocale = GetLocal(); - if (eValueType == XFA_VALUEPICTURE_Display && pLocale) { - CFX_WideString wsOutput; - NormalizeNumStr(wsValue, wsOutput); - FormatNumStr(wsOutput, pLocale, wsOutput); - wsValue = wsOutput; - } - } - break; - default: - break; - } - if (wsPicture.IsEmpty()) - return true; - - if (IFX_Locale* pLocale = GetLocal()) { - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); - CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr(); - switch (widgetValue.GetType()) { - case XFA_VT_DATE: { - CFX_WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); - if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) - return true; - } - break; - } - case XFA_VT_TIME: { - CFX_WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); - if (time.FormatPatterns(wsValue, wsPicture, pLocale, eValueType)) - return true; - } - break; - } - default: - break; - } - widgetValue.FormatPatterns(wsValue, wsPicture, pLocale, eValueType); - } - return true; -} - -bool CXFA_WidgetData::GetNormalizeDataValue(const CFX_WideString& wsValue, - CFX_WideString& wsNormalizeValue) { - wsNormalizeValue = wsValue; - if (wsValue.IsEmpty()) - return true; - - CFX_WideString wsPicture; - GetPictureContent(wsPicture, XFA_VALUEPICTURE_DataBind); - if (wsPicture.IsEmpty()) - return true; - - ASSERT(GetNode()); - CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); - IFX_Locale* pLocale = GetLocal(); - CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this); - if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) { - widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNormalizeValue, - wsPicture, pLocale, pLocalMgr); - wsNormalizeValue = widgetValue.GetValue(); - return true; - } - return false; -} - -bool CXFA_WidgetData::GetFormatDataValue(const CFX_WideString& wsValue, - CFX_WideString& wsFormattedValue) { - wsFormattedValue = wsValue; - if (wsValue.IsEmpty()) - return true; - - CFX_WideString wsPicture; - GetPictureContent(wsPicture, XFA_VALUEPICTURE_DataBind); - if (wsPicture.IsEmpty()) - return true; - - if (IFX_Locale* pLocale = GetLocal()) { - ASSERT(GetNode()); - CXFA_Node* pNodeValue = GetNode()->GetChild(0, XFA_Element::Value); - if (!pNodeValue) - return false; - - CXFA_Node* pValueChild = pNodeValue->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pValueChild) - return false; - - int32_t iVTType = XFA_VT_NULL; - switch (pValueChild->GetElementType()) { - case XFA_Element::Decimal: - iVTType = XFA_VT_DECIMAL; - break; - case XFA_Element::Float: - iVTType = XFA_VT_FLOAT; - break; - case XFA_Element::Date: - iVTType = XFA_VT_DATE; - break; - case XFA_Element::Time: - iVTType = XFA_VT_TIME; - break; - case XFA_Element::DateTime: - iVTType = XFA_VT_DATETIME; - break; - case XFA_Element::Boolean: - iVTType = XFA_VT_BOOLEAN; - break; - case XFA_Element::Integer: - iVTType = XFA_VT_INTEGER; - break; - case XFA_Element::Text: - iVTType = XFA_VT_TEXT; - break; - default: - iVTType = XFA_VT_NULL; - break; - } - CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr(); - CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocalMgr); - switch (widgetValue.GetType()) { - case XFA_VT_DATE: { - CFX_WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr); - if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale, - XFA_VALUEPICTURE_DataBind)) { - return true; - } - } - break; - } - case XFA_VT_TIME: { - CFX_WideString wsDate, wsTime; - if (SplitDateTime(wsValue, wsDate, wsTime)) { - CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr); - if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale, - XFA_VALUEPICTURE_DataBind)) { - return true; - } - } - break; - } - default: - break; - } - widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale, - XFA_VALUEPICTURE_DataBind); - } - return false; -} - -void CXFA_WidgetData::NormalizeNumStr(const CFX_WideString& wsValue, - CFX_WideString& wsOutput) { - if (wsValue.IsEmpty()) - return; - - wsOutput = wsValue; - wsOutput.TrimLeft('0'); - int32_t dot_index = wsOutput.Find('.'); - int32_t iFracDigits = 0; - if (!wsOutput.IsEmpty() && dot_index >= 0 && - (!GetFracDigits(iFracDigits) || iFracDigits != -1)) { - wsOutput.TrimRight(L"0"); - wsOutput.TrimRight(L"."); - } - if (wsOutput.IsEmpty() || wsOutput[0] == '.') - wsOutput.Insert(0, '0'); -} - -void CXFA_WidgetData::FormatNumStr(const CFX_WideString& wsValue, - IFX_Locale* pLocale, - CFX_WideString& wsOutput) { - if (wsValue.IsEmpty()) - return; - - CFX_WideString wsSrcNum = wsValue; - CFX_WideString wsGroupSymbol; - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); - bool bNeg = false; - if (wsSrcNum[0] == '-') { - bNeg = true; - wsSrcNum.Delete(0, 1); - } - int32_t len = wsSrcNum.GetLength(); - int32_t dot_index = wsSrcNum.Find('.'); - if (dot_index == -1) - dot_index = len; - - int32_t cc = dot_index - 1; - if (cc >= 0) { - int nPos = dot_index % 3; - wsOutput.clear(); - for (int32_t 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; - } - } -} - -void CXFA_WidgetData::SyncValue(const CFX_WideString& wsValue, bool bNotify) { - if (!m_pNode) - return; - - CFX_WideString wsFormatValue(wsValue); - CXFA_WidgetData* pContainerWidgetData = m_pNode->GetContainerWidgetData(); - if (pContainerWidgetData) - pContainerWidgetData->GetFormatDataValue(wsValue, wsFormatValue); - - m_pNode->SetContent(wsValue, wsFormatValue, bNotify); -} - -void CXFA_WidgetData::InsertListTextItem(CXFA_Node* pItems, - const CFX_WideString& wsText, - int32_t nIndex) { - CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text); - pItems->InsertChild(nIndex, pText); - pText->SetContent(wsText, wsText, false, false, false); -} - -CFX_WideString CXFA_WidgetData::NumericLimit(const CFX_WideString& wsValue, - int32_t iLead, - int32_t iTread) const { - if ((iLead == -1) && (iTread == -1)) - return wsValue; - - CFX_WideString wsRet; - int32_t iLead_ = 0, iTread_ = -1; - int32_t iCount = wsValue.GetLength(); - if (iCount == 0) - return wsValue; - - int32_t i = 0; - if (wsValue[i] == L'-') { - wsRet += L'-'; - i++; - } - for (; i < iCount; i++) { - FX_WCHAR wc = wsValue[i]; - if (FXSYS_isDecimalDigit(wc)) { - if (iLead >= 0) { - iLead_++; - if (iLead_ > iLead) - return L"0"; - } else if (iTread_ >= 0) { - iTread_++; - if (iTread_ > iTread) { - if (iTread != -1) { - CFX_Decimal wsDeci = CFX_Decimal(wsValue.AsStringC()); - wsDeci.SetScale(iTread); - wsRet = wsDeci; - } - return wsRet; - } - } - } else if (wc == L'.') { - iTread_ = 0; - iLead = -1; - } - wsRet += wc; - } - return wsRet; -} diff --git a/xfa/fxfa/parser/cxfa_widgetdata.h b/xfa/fxfa/parser/cxfa_widgetdata.h deleted file mode 100644 index 4f5db3bad6df5b3736969da8b101e6469d934624..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_widgetdata.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_CXFA_WIDGETDATA_H_ -#define XFA_FXFA_PARSER_CXFA_WIDGETDATA_H_ - -#include <vector> - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_assist.h" -#include "xfa/fxfa/parser/cxfa_bind.h" -#include "xfa/fxfa/parser/cxfa_border.h" -#include "xfa/fxfa/parser/cxfa_calculate.h" -#include "xfa/fxfa/parser/cxfa_caption.h" -#include "xfa/fxfa/parser/cxfa_data.h" -#include "xfa/fxfa/parser/cxfa_font.h" -#include "xfa/fxfa/parser/cxfa_margin.h" -#include "xfa/fxfa/parser/cxfa_para.h" -#include "xfa/fxfa/parser/cxfa_validate.h" -#include "xfa/fxfa/parser/xfa_object.h" - -enum XFA_CHECKSTATE { - XFA_CHECKSTATE_On = 0, - XFA_CHECKSTATE_Off = 1, - XFA_CHECKSTATE_Neutral = 2, -}; - -enum XFA_VALUEPICTURE { - XFA_VALUEPICTURE_Raw = 0, - XFA_VALUEPICTURE_Display, - XFA_VALUEPICTURE_Edit, - XFA_VALUEPICTURE_DataBind, -}; - -class CXFA_Node; -class IFX_Locale; - -class CXFA_WidgetData : public CXFA_Data { - public: - explicit CXFA_WidgetData(CXFA_Node* pNode); - - CXFA_Node* GetUIChild(); - XFA_Element GetUIType(); - CFX_WideString GetRawValue(); - int32_t GetAccess(bool bTemplate = false); - int32_t GetRotate(); - CXFA_Border GetBorder(bool bModified = false); - CXFA_Caption GetCaption(bool bModified = false); - CXFA_Font GetFont(bool bModified = false); - CXFA_Margin GetMargin(bool bModified = false); - CXFA_Para GetPara(bool bModified = false); - void GetEventList(CXFA_NodeArray& events); - int32_t GetEventByActivity(int32_t iActivity, - CXFA_NodeArray& events, - bool bIsFormReady = false); - CXFA_Value GetDefaultValue(bool bModified = false); - CXFA_Value GetFormValue(bool bModified = false); - CXFA_Calculate GetCalculate(bool bModified = false); - CXFA_Validate GetValidate(bool bModified = false); - CXFA_Bind GetBind(bool bModified = false); - CXFA_Assist GetAssist(bool bModified = false); - bool GetWidth(FX_FLOAT& fWidth); - bool GetHeight(FX_FLOAT& fHeight); - bool GetMinWidth(FX_FLOAT& fMinWidth); - bool GetMinHeight(FX_FLOAT& fMinHeight); - bool GetMaxWidth(FX_FLOAT& fMaxWidth); - bool GetMaxHeight(FX_FLOAT& fMaxHeight); - CXFA_Border GetUIBorder(); - CFX_RectF GetUIMargin(); - int32_t GetButtonHighlight(); - bool GetButtonRollover(CFX_WideString& wsRollover, bool& bRichText); - bool GetButtonDown(CFX_WideString& wsDown, bool& bRichText); - int32_t GetCheckButtonShape(); - int32_t GetCheckButtonMark(); - FX_FLOAT GetCheckButtonSize(); - bool IsAllowNeutral(); - bool IsRadioButton(); - XFA_CHECKSTATE GetCheckState(); - void SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify); - CXFA_Node* GetExclGroupNode(); - CXFA_Node* GetSelectedMember(); - CXFA_Node* SetSelectedMember(const CFX_WideStringC& wsName, bool bNotify); - void SetSelectedMemberByValue(const CFX_WideStringC& wsValue, - bool bNotify, - bool bScriptModify, - bool bSyncData); - CXFA_Node* GetExclGroupFirstMember(); - CXFA_Node* GetExclGroupNextMember(CXFA_Node* pNode); - int32_t GetChoiceListCommitOn(); - bool IsChoiceListAllowTextEntry(); - int32_t GetChoiceListOpen(); - bool IsListBox(); - int32_t CountChoiceListItems(bool bSaveValue = false); - bool GetChoiceListItem(CFX_WideString& wsText, - int32_t nIndex, - bool bSaveValue = false); - void GetChoiceListItems(std::vector<CFX_WideString>& wsTextArray, - bool bSaveValue = false); - int32_t CountSelectedItems(); - int32_t GetSelectedItem(int32_t nIndex = 0); - void GetSelectedItems(CFX_ArrayTemplate<int32_t>& iSelArray); - void GetSelectedItemsValue(std::vector<CFX_WideString>& wsSelTextArray); - bool GetItemState(int32_t nIndex); - void SetItemState(int32_t nIndex, - bool bSelected, - bool bNotify, - bool bScriptModify, - bool bSyncData); - void SetSelectedItems(CFX_ArrayTemplate<int32_t>& iSelArray, - bool bNotify, - bool bScriptModify, - bool bSyncData); - void ClearAllSelections(); - void InsertItem(const CFX_WideString& wsLabel, - const CFX_WideString& wsValue, - int32_t nIndex = -1, - bool bNotify = false); - void GetItemLabel(const CFX_WideStringC& wsValue, CFX_WideString& wsLabel); - void GetItemValue(const CFX_WideStringC& wsLabel, CFX_WideString& wsValue); - bool DeleteItem(int32_t nIndex, - bool bNotify = false, - bool bScriptModify = false, - bool bSyncData = true); - int32_t GetHorizontalScrollPolicy(); - int32_t GetNumberOfCells(); - bool SetValue(const CFX_WideString& wsValue, XFA_VALUEPICTURE eValueType); - bool GetPictureContent(CFX_WideString& wsPicture, XFA_VALUEPICTURE ePicture); - IFX_Locale* GetLocal(); - bool GetValue(CFX_WideString& wsValue, XFA_VALUEPICTURE eValueType); - bool GetNormalizeDataValue(const CFX_WideString& wsValue, - CFX_WideString& wsNormalizeValue); - bool GetFormatDataValue(const CFX_WideString& wsValue, - CFX_WideString& wsFormattedValue); - void NormalizeNumStr(const CFX_WideString& wsValue, CFX_WideString& wsOutput); - CFX_WideString GetBarcodeType(); - bool GetBarcodeAttribute_CharEncoding(int32_t& val); - bool GetBarcodeAttribute_Checksum(bool& val); - bool GetBarcodeAttribute_DataLength(int32_t& val); - bool GetBarcodeAttribute_StartChar(FX_CHAR& val); - bool GetBarcodeAttribute_EndChar(FX_CHAR& val); - bool GetBarcodeAttribute_ECLevel(int32_t& val); - bool GetBarcodeAttribute_ModuleWidth(int32_t& val); - bool GetBarcodeAttribute_ModuleHeight(int32_t& val); - bool GetBarcodeAttribute_PrintChecksum(bool& val); - bool GetBarcodeAttribute_TextLocation(int32_t& val); - bool GetBarcodeAttribute_Truncate(bool& val); - bool GetBarcodeAttribute_WideNarrowRatio(FX_FLOAT& val); - void GetPasswordChar(CFX_WideString& wsPassWord); - bool IsMultiLine(); - int32_t GetVerticalScrollPolicy(); - int32_t GetMaxChars(XFA_Element& eType); - bool GetFracDigits(int32_t& iFracDigits); - bool GetLeadDigits(int32_t& iLeadDigits); - - CFX_WideString NumericLimit(const CFX_WideString& wsValue, - int32_t iLead, - int32_t iTread) const; - - bool m_bIsNull; - bool m_bPreNull; - - protected: - void SyncValue(const CFX_WideString& wsValue, bool bNotify); - void InsertListTextItem(CXFA_Node* pItems, - const CFX_WideString& wsText, - int32_t nIndex = -1); - void FormatNumStr(const CFX_WideString& wsValue, - IFX_Locale* pLocale, - CFX_WideString& wsOutput); - - CXFA_Node* m_pUiChildNode; - XFA_Element m_eUIType; -}; - -#endif // XFA_FXFA_PARSER_CXFA_WIDGETDATA_H_ diff --git a/xfa/fxfa/parser/cxfa_window.cpp b/xfa/fxfa/parser/cxfa_window.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1485f689193598ada52c6a3b6d3b4e30365fb7f --- /dev/null +++ b/xfa/fxfa/parser/cxfa_window.cpp @@ -0,0 +1,30 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_window.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"window"; + +} // namespace + +CXFA_Window::CXFA_Window(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::NodeV, + XFA_Element::Window, + nullptr, + kAttributeData, + kName) {} + +CXFA_Window::~CXFA_Window() {} diff --git a/xfa/fxfa/parser/cxfa_window.h b/xfa/fxfa/parser/cxfa_window.h new file mode 100644 index 0000000000000000000000000000000000000000..852bc68b2c85634e054c39f960beec4220982861 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_window.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_WINDOW_H_ +#define XFA_FXFA_PARSER_CXFA_WINDOW_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Window : public CXFA_Node { + public: + CXFA_Window(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Window() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_WINDOW_H_ diff --git a/xfa/fxfa/parser/cxfa_wsdladdress.cpp b/xfa/fxfa/parser/cxfa_wsdladdress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..239bb66f8921b8391658d770b5b69c751fa6ab61 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_wsdladdress.cpp @@ -0,0 +1,36 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_wsdladdress.h" + +#include "fxjs/xfa/cjx_wsdladdress.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"wsdlAddress"; + +} // namespace + +CXFA_WsdlAddress::CXFA_WsdlAddress(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::TextNode, + XFA_Element::WsdlAddress, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_WsdlAddress>(this)) {} + +CXFA_WsdlAddress::~CXFA_WsdlAddress() {} diff --git a/xfa/fxfa/parser/cxfa_wsdladdress.h b/xfa/fxfa/parser/cxfa_wsdladdress.h new file mode 100644 index 0000000000000000000000000000000000000000..83c965cbecb2e1232f98c452647bc42e7934a711 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_wsdladdress.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_WSDLADDRESS_H_ +#define XFA_FXFA_PARSER_CXFA_WSDLADDRESS_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_WsdlAddress : public CXFA_Node { + public: + CXFA_WsdlAddress(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_WsdlAddress() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_WSDLADDRESS_H_ diff --git a/xfa/fxfa/parser/cxfa_wsdlconnection.cpp b/xfa/fxfa/parser/cxfa_wsdlconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6159f49b9796ca3b7a5eca556023b8b5ae8925c1 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_wsdlconnection.cpp @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_wsdlconnection.h" + +#include "fxjs/xfa/cjx_wsdlconnection.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Operation, 1, 0}, + {XFA_Element::WsdlAddress, 1, 0}, + {XFA_Element::SoapAddress, 1, 0}, + {XFA_Element::SoapAction, 1, 0}, + {XFA_Element::EffectiveOutputPolicy, 1, 0}, + {XFA_Element::EffectiveInputPolicy, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataDescription, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"wsdlConnection"; + +} // namespace + +CXFA_WsdlConnection::CXFA_WsdlConnection(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::Node, + XFA_Element::WsdlConnection, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_WsdlConnection>(this)) {} + +CXFA_WsdlConnection::~CXFA_WsdlConnection() {} diff --git a/xfa/fxfa/parser/cxfa_wsdlconnection.h b/xfa/fxfa/parser/cxfa_wsdlconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..6c349cf1d7466528073c19c8685caf057dc7e2e4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_wsdlconnection.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_WSDLCONNECTION_H_ +#define XFA_FXFA_PARSER_CXFA_WSDLCONNECTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_WsdlConnection : public CXFA_Node { + public: + CXFA_WsdlConnection(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_WsdlConnection() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_WSDLCONNECTION_H_ diff --git a/xfa/fxfa/parser/cxfa_xdc.cpp b/xfa/fxfa/parser/cxfa_xdc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..daaebc874b600ee1bc875348d65877476634f454 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xdc.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xdc.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Uri, 1, 0}, + {XFA_Element::Xsl, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"xdc"; + +} // namespace + +CXFA_Xdc::CXFA_Xdc(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + (XFA_XDPPACKET_Config | XFA_XDPPACKET_Xdc), + XFA_ObjectType::ModelNode, + XFA_Element::Xdc, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Xdc::~CXFA_Xdc() {} diff --git a/xfa/fxfa/parser/cxfa_xdc.h b/xfa/fxfa/parser/cxfa_xdc.h new file mode 100644 index 0000000000000000000000000000000000000000..0eb43d55019996c62a7f1d77c5d18d3a2a7469cf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xdc.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XDC_H_ +#define XFA_FXFA_PARSER_CXFA_XDC_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Xdc : public CXFA_Node { + public: + CXFA_Xdc(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Xdc() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XDC_H_ diff --git a/xfa/fxfa/parser/cxfa_xdp.cpp b/xfa/fxfa/parser/cxfa_xdp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f100ae887c91615f130ddf9d00e1e70c81149e1e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xdp.cpp @@ -0,0 +1,32 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xdp.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Packets, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"xdp"; + +} // namespace + +CXFA_Xdp::CXFA_Xdp(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Xdp, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Xdp::~CXFA_Xdp() {} diff --git a/xfa/fxfa/parser/cxfa_xdp.h b/xfa/fxfa/parser/cxfa_xdp.h new file mode 100644 index 0000000000000000000000000000000000000000..38b450e98acded21981679447e796de11df0253c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xdp.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XDP_H_ +#define XFA_FXFA_PARSER_CXFA_XDP_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Xdp : public CXFA_Node { + public: + CXFA_Xdp(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Xdp() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XDP_H_ diff --git a/xfa/fxfa/parser/cxfa_xfa.cpp b/xfa/fxfa/parser/cxfa_xfa.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7eab898eb1b494394d9fe7841dcee902dc4b1310 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xfa.cpp @@ -0,0 +1,34 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xfa.h" + +#include "fxjs/xfa/cjx_xfa.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::TimeStamp, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Uuid, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"xfa"; + +} // namespace + +CXFA_Xfa::CXFA_Xfa(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_XDP, + XFA_ObjectType::ModelNode, + XFA_Element::Xfa, + nullptr, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_Xfa>(this)) {} + +CXFA_Xfa::~CXFA_Xfa() {} diff --git a/xfa/fxfa/parser/cxfa_xfa.h b/xfa/fxfa/parser/cxfa_xfa.h new file mode 100644 index 0000000000000000000000000000000000000000..137b60191c7ce94a88c92a7ccbb264cbe3853033 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xfa.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XFA_H_ +#define XFA_FXFA_PARSER_CXFA_XFA_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Xfa : public CXFA_Node { + public: + CXFA_Xfa(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Xfa() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XFA_H_ diff --git a/xfa/fxfa/parser/cxfa_xml_parser.cpp b/xfa/fxfa/parser/cxfa_xml_parser.cpp deleted file mode 100644 index b202022516820d336f093ff06d6902e919533fa6..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_xml_parser.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/cxfa_xml_parser.h" - -CXFA_XMLParser::CXFA_XMLParser(CFDE_XMLNode* pRoot, - const CFX_RetainPtr<IFGAS_Stream>& pStream) - : m_nElementStart(0), - m_dwCheckStatus(0), - m_dwCurrentCheckStatus(0), - m_pRoot(pRoot), - m_pStream(pStream), - m_pParser(new CFDE_XMLSyntaxParser), - m_pParent(pRoot), - m_pChild(nullptr), - m_NodeStack(16), - m_syntaxParserResult(FDE_XmlSyntaxResult::None) { - ASSERT(m_pParent && m_pStream); - m_NodeStack.Push(m_pParent); - m_pParser->Init(m_pStream, 32 * 1024, 1024 * 1024); -} - -CXFA_XMLParser::~CXFA_XMLParser() { - m_NodeStack.RemoveAll(false); - m_ws1.clear(); - m_ws2.clear(); -} - -int32_t CXFA_XMLParser::DoParser(IFX_Pause* pPause) { - if (m_syntaxParserResult == FDE_XmlSyntaxResult::Error) - return -1; - if (m_syntaxParserResult == FDE_XmlSyntaxResult::EndOfString) - return 100; - - int32_t iCount = 0; - while (true) { - m_syntaxParserResult = m_pParser->DoSyntaxParse(); - switch (m_syntaxParserResult) { - case FDE_XmlSyntaxResult::InstructionOpen: - break; - case FDE_XmlSyntaxResult::InstructionClose: - if (m_pChild) { - if (m_pChild->GetType() != FDE_XMLNODE_Instruction) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - break; - } - } - m_pChild = m_pParent; - break; - case FDE_XmlSyntaxResult::ElementOpen: - if (m_dwCheckStatus != 0x03 && m_NodeStack.GetSize() == 2) { - m_nElementStart = m_pParser->GetCurrentPos() - 1; - } - break; - case FDE_XmlSyntaxResult::ElementBreak: - break; - case FDE_XmlSyntaxResult::ElementClose: - if (m_pChild->GetType() != FDE_XMLNODE_Element) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - break; - } - m_pParser->GetTagName(m_ws1); - static_cast<CFDE_XMLElement*>(m_pChild)->GetTagName(m_ws2); - if (m_ws1.GetLength() > 0 && m_ws1 != m_ws2) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - break; - } - m_NodeStack.Pop(); - if (m_NodeStack.GetSize() < 1) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - break; - } else if (m_dwCurrentCheckStatus != 0 && m_NodeStack.GetSize() == 2) { - m_nSize[m_dwCurrentCheckStatus - 1] = - m_pParser->GetCurrentBinaryPos() - - m_nStart[m_dwCurrentCheckStatus - 1]; - m_dwCurrentCheckStatus = 0; - } - - m_pParent = static_cast<CFDE_XMLNode*>(*m_NodeStack.GetTopElement()); - m_pChild = m_pParent; - iCount++; - break; - case FDE_XmlSyntaxResult::TargetName: - m_pParser->GetTargetName(m_ws1); - if (m_ws1 == L"originalXFAVersion" || m_ws1 == L"acrobat") { - m_pChild = new CFDE_XMLInstruction(m_ws1); - m_pParent->InsertChildNode(m_pChild); - } else { - m_pChild = nullptr; - } - m_ws1.clear(); - break; - case FDE_XmlSyntaxResult::TagName: - m_pParser->GetTagName(m_ws1); - m_pChild = new CFDE_XMLElement(m_ws1); - m_pParent->InsertChildNode(m_pChild); - m_NodeStack.Push(m_pChild); - m_pParent = m_pChild; - - if (m_dwCheckStatus != 0x03 && m_NodeStack.GetSize() == 3) { - CFX_WideString wsTag; - static_cast<CFDE_XMLElement*>(m_pChild)->GetLocalTagName(wsTag); - if (wsTag == L"template") { - m_dwCheckStatus |= 0x01; - m_dwCurrentCheckStatus = 0x01; - m_nStart[0] = m_pParser->GetCurrentBinaryPos() - - (m_pParser->GetCurrentPos() - m_nElementStart); - } else if (wsTag == L"datasets") { - m_dwCheckStatus |= 0x02; - m_dwCurrentCheckStatus = 0x02; - m_nStart[1] = m_pParser->GetCurrentBinaryPos() - - (m_pParser->GetCurrentPos() - m_nElementStart); - } - } - break; - case FDE_XmlSyntaxResult::AttriName: - m_pParser->GetAttributeName(m_ws1); - break; - case FDE_XmlSyntaxResult::AttriValue: - if (m_pChild) { - m_pParser->GetAttributeName(m_ws2); - if (m_pChild->GetType() == FDE_XMLNODE_Element) { - static_cast<CFDE_XMLElement*>(m_pChild)->SetString(m_ws1, m_ws2); - } - } - m_ws1.clear(); - break; - case FDE_XmlSyntaxResult::Text: - m_pParser->GetTextData(m_ws1); - m_pChild = new CFDE_XMLText(m_ws1); - m_pParent->InsertChildNode(m_pChild); - m_pChild = m_pParent; - break; - case FDE_XmlSyntaxResult::CData: - m_pParser->GetTextData(m_ws1); - m_pChild = new CFDE_XMLCharData(m_ws1); - m_pParent->InsertChildNode(m_pChild); - m_pChild = m_pParent; - break; - case FDE_XmlSyntaxResult::TargetData: - if (m_pChild) { - if (m_pChild->GetType() != FDE_XMLNODE_Instruction) { - m_syntaxParserResult = FDE_XmlSyntaxResult::Error; - break; - } - if (!m_ws1.IsEmpty()) { - static_cast<CFDE_XMLInstruction*>(m_pChild)->AppendData(m_ws1); - } - m_pParser->GetTargetData(m_ws1); - static_cast<CFDE_XMLInstruction*>(m_pChild)->AppendData(m_ws1); - } - m_ws1.clear(); - break; - default: - break; - } - if (m_syntaxParserResult == FDE_XmlSyntaxResult::Error || - m_syntaxParserResult == FDE_XmlSyntaxResult::EndOfString) { - break; - } - if (pPause && iCount > 500 && pPause->NeedToPauseNow()) { - break; - } - } - return (m_syntaxParserResult == FDE_XmlSyntaxResult::Error || - m_NodeStack.GetSize() != 1) - ? -1 - : m_pParser->GetStatus(); -} diff --git a/xfa/fxfa/parser/cxfa_xml_parser.h b/xfa/fxfa/parser/cxfa_xml_parser.h deleted file mode 100644 index 9393b7e597e5a62e3e03c6e1077b21a4d24100d2..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/cxfa_xml_parser.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_CXFA_XML_PARSER_H_ -#define XFA_FXFA_PARSER_CXFA_XML_PARSER_H_ - -#include <memory> - -#include "xfa/fde/xml/fde_xml_imp.h" - -class IFGAS_Stream; -class IFX_Pause; - -class CXFA_XMLParser : public IFDE_XMLParser { - public: - CXFA_XMLParser(CFDE_XMLNode* pRoot, - const CFX_RetainPtr<IFGAS_Stream>& pStream); - ~CXFA_XMLParser() override; - - // IFDE_XMLParser - int32_t DoParser(IFX_Pause* pPause) override; - - FX_FILESIZE m_nStart[2]; - size_t m_nSize[2]; - FX_FILESIZE m_nElementStart; - uint16_t m_dwCheckStatus; - uint16_t m_dwCurrentCheckStatus; - - protected: - CFDE_XMLNode* m_pRoot; - CFX_RetainPtr<IFGAS_Stream> m_pStream; - std::unique_ptr<CFDE_XMLSyntaxParser> m_pParser; - CFDE_XMLNode* m_pParent; - CFDE_XMLNode* m_pChild; - CFX_StackTemplate<CFDE_XMLNode*> m_NodeStack; - CFX_WideString m_ws1; - CFX_WideString m_ws2; - FDE_XmlSyntaxResult m_syntaxParserResult; -}; - -#endif // XFA_FXFA_PARSER_CXFA_XML_PARSER_H_ diff --git a/xfa/fxfa/parser/cxfa_xmlconnection.cpp b/xfa/fxfa/parser/cxfa_xmlconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df057710c2c5af77d5005fb0432be3c2ffe16b65 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xmlconnection.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xmlconnection.h" + +#include "fxjs/xfa/cjx_xmlconnection.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Uri, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataDescription, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"xmlConnection"; + +} // namespace + +CXFA_XmlConnection::CXFA_XmlConnection(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::Node, + XFA_Element::XmlConnection, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_XmlConnection>(this)) {} + +CXFA_XmlConnection::~CXFA_XmlConnection() {} diff --git a/xfa/fxfa/parser/cxfa_xmlconnection.h b/xfa/fxfa/parser/cxfa_xmlconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..f9158c636876d27ee5a070544f93f3c9a57d6ea4 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xmlconnection.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XMLCONNECTION_H_ +#define XFA_FXFA_PARSER_CXFA_XMLCONNECTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_XmlConnection : public CXFA_Node { + public: + CXFA_XmlConnection(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_XmlConnection() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XMLCONNECTION_H_ diff --git a/xfa/fxfa/parser/cxfa_xmllocale.cpp b/xfa/fxfa/parser/cxfa_xmllocale.cpp new file mode 100644 index 0000000000000000000000000000000000000000..659c7bbefe7d7c090c1ed577a0d19332ce2b5a86 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xmllocale.cpp @@ -0,0 +1,207 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xmllocale.h" + +#include <utility> + +#include "core/fxcrt/xml/cxml_content.h" +#include "core/fxcrt/xml/cxml_element.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_nodelocale.h" +#include "xfa/fxfa/parser/cxfa_timezoneprovider.h" +#include "xfa/fxfa/parser/xfa_utils.h" + +CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData) + : m_pLocaleData(std::move(pLocaleData)) {} + +CXFA_XMLLocale::~CXFA_XMLLocale() {} + +WideString CXFA_XMLLocale::GetName() const { + return m_pLocaleData ? m_pLocaleData->GetAttrValue("name") : WideString(); +} + +WideString CXFA_XMLLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const { + ByteString bsSymbols; + WideString wsName; + switch (eType) { + case FX_LOCALENUMSYMBOL_Decimal: + bsSymbols = "numberSymbols"; + wsName = L"decimal"; + break; + case FX_LOCALENUMSYMBOL_Grouping: + bsSymbols = "numberSymbols"; + wsName = L"grouping"; + break; + case FX_LOCALENUMSYMBOL_Percent: + bsSymbols = "numberSymbols"; + wsName = L"percent"; + break; + case FX_LOCALENUMSYMBOL_Minus: + bsSymbols = "numberSymbols"; + wsName = L"minus"; + break; + case FX_LOCALENUMSYMBOL_Zero: + bsSymbols = "numberSymbols"; + wsName = L"zero"; + break; + case FX_LOCALENUMSYMBOL_CurrencySymbol: + bsSymbols = "currencySymbols"; + wsName = L"symbol"; + break; + case FX_LOCALENUMSYMBOL_CurrencyName: + bsSymbols = "currencySymbols"; + wsName = L"isoname"; + break; + default: + return WideString(); + } + CXML_Element* pElement = + m_pLocaleData->GetElement("", bsSymbols.AsStringView(), 0); + if (!pElement) + return WideString(); + + return GetPattern( + pElement, ByteStringView(bsSymbols.c_str(), bsSymbols.GetLength() - 1), + wsName.AsStringView()); +} + +WideString CXFA_XMLLocale::GetDateTimeSymbols() const { + if (!m_pLocaleData) + return WideString(); + + CXML_Element* pNumberSymbols = + m_pLocaleData->GetElement("", "dateTimeSymbols", 0); + if (!pNumberSymbols) + return WideString(); + + CXML_Content* pContent = ToContent(pNumberSymbols->GetChild(0)); + if (!pContent) + return WideString(); + + return pContent->m_Content; +} + +WideString CXFA_XMLLocale::GetMonthName(int32_t nMonth, bool bAbbr) const { + return GetCalendarSymbol("month", nMonth, bAbbr); +} + +WideString CXFA_XMLLocale::GetDayName(int32_t nWeek, bool bAbbr) const { + return GetCalendarSymbol("day", nWeek, bAbbr); +} + +WideString CXFA_XMLLocale::GetMeridiemName(bool bAM) const { + return GetCalendarSymbol("meridiem", bAM ? 0 : 1, false); +} + +FX_TIMEZONE CXFA_XMLLocale::GetTimeZone() const { + return CXFA_TimeZoneProvider().GetTimeZone(); +} + +WideString CXFA_XMLLocale::GetEraName(bool bAD) const { + return GetCalendarSymbol("era", bAD ? 1 : 0, false); +} + +WideString CXFA_XMLLocale::GetCalendarSymbol(const ByteStringView& symbol, + int index, + bool bAbbr) const { + if (index < 0 || !m_pLocaleData) + return WideString(); + + CXML_Element* pChild = m_pLocaleData->GetElement("", "calendarSymbols", 0); + if (!pChild) + return WideString(); + + ByteString pstrSymbolNames = symbol + "Names"; + CXML_Element* pSymbolNames = + pChild->GetElement("", pstrSymbolNames.AsStringView(), 0); + if (!pSymbolNames) + return WideString(); + + if ((!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr) + pSymbolNames = pChild->GetElement("", pstrSymbolNames.AsStringView(), 1); + + if (!pSymbolNames || (!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr) + return WideString(); + + CXML_Element* pSymbolName = pSymbolNames->GetElement("", symbol, index); + if (!pSymbolName) + return WideString(); + + CXML_Content* pContent = ToContent(pSymbolName->GetChild(0)); + return pContent ? pContent->m_Content : WideString(); +} + +WideString CXFA_XMLLocale::GetDatePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const { + CXML_Element* pElement = m_pLocaleData->GetElement("", "datePatterns", 0); + if (!pElement) + return WideString(); + + WideString wsName; + switch (eType) { + case FX_LOCALEDATETIMESUBCATEGORY_Short: + wsName = L"short"; + break; + case FX_LOCALEDATETIMESUBCATEGORY_Default: + case FX_LOCALEDATETIMESUBCATEGORY_Medium: + wsName = L"med"; + break; + case FX_LOCALEDATETIMESUBCATEGORY_Full: + wsName = L"full"; + break; + case FX_LOCALEDATETIMESUBCATEGORY_Long: + wsName = L"long"; + break; + } + return GetPattern(pElement, "datePattern", wsName.AsStringView()); +} + +WideString CXFA_XMLLocale::GetTimePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const { + CXML_Element* pElement = m_pLocaleData->GetElement("", "timePatterns", 0); + if (!pElement) + return WideString(); + + WideString wsName; + switch (eType) { + case FX_LOCALEDATETIMESUBCATEGORY_Short: + wsName = L"short"; + break; + case FX_LOCALEDATETIMESUBCATEGORY_Default: + case FX_LOCALEDATETIMESUBCATEGORY_Medium: + wsName = L"med"; + break; + case FX_LOCALEDATETIMESUBCATEGORY_Full: + wsName = L"full"; + break; + case FX_LOCALEDATETIMESUBCATEGORY_Long: + wsName = L"long"; + break; + } + return GetPattern(pElement, "timePattern", wsName.AsStringView()); +} + +WideString CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const { + return m_pLocaleData->GetElement("", "numberPatterns", 0) + ? XFA_PatternToString(eType) + : WideString(); +} + +WideString CXFA_XMLLocale::GetPattern(CXML_Element* pElement, + const ByteStringView& bsTag, + const WideStringView& wsName) const { + size_t iCount = pElement->CountElements("", bsTag); + for (size_t i = 0; i < iCount; i++) { + CXML_Element* pChild = pElement->GetElement("", bsTag, i); + if (pChild->GetAttrValue("name") == wsName) { + CXML_Content* pContent = ToContent(pChild->GetChild(0)); + return pContent ? pContent->m_Content : WideString(); + } + } + return WideString(); +} diff --git a/xfa/fxfa/parser/cxfa_xmllocale.h b/xfa/fxfa/parser/cxfa_xmllocale.h new file mode 100644 index 0000000000000000000000000000000000000000..5050855ca6190f4a63dcca2293ce133d7d55562c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xmllocale.h @@ -0,0 +1,47 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XMLLOCALE_H_ +#define XFA_FXFA_PARSER_CXFA_XMLLOCALE_H_ + +#include <memory> + +#include "core/fxcrt/ifx_locale.h" + +class CXML_Element; + +class CXFA_XMLLocale : public IFX_Locale { + public: + explicit CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData); + ~CXFA_XMLLocale() override; + + // IFX_Locale + WideString GetName() const override; + WideString GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const override; + + WideString GetDateTimeSymbols() const override; + WideString GetMonthName(int32_t nMonth, bool bAbbr) const override; + WideString GetDayName(int32_t nWeek, bool bAbbr) const override; + WideString GetMeridiemName(bool bAM) const override; + FX_TIMEZONE GetTimeZone() const override; + WideString GetEraName(bool bAD) const override; + + WideString GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType) const override; + WideString GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType) const override; + WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const override; + + private: + WideString GetPattern(CXML_Element* pElement, + const ByteStringView& bsTag, + const WideStringView& wsName) const; + WideString GetCalendarSymbol(const ByteStringView& symbol, + int index, + bool bAbbr) const; + + std::unique_ptr<CXML_Element> m_pLocaleData; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XMLLOCALE_H_ diff --git a/xfa/fxfa/parser/cxfa_xsdconnection.cpp b/xfa/fxfa/parser/cxfa_xsdconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b0de0d674b9aa0414cb95dcdd0fd161fa5f439e --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xsdconnection.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xsdconnection.h" + +#include "fxjs/xfa/cjx_xsdconnection.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::Uri, 1, 0}, + {XFA_Element::RootElement, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::DataDescription, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"xsdConnection"; + +} // namespace + +CXFA_XsdConnection::CXFA_XsdConnection(CXFA_Document* doc, + XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_ConnectionSet, + XFA_ObjectType::Node, + XFA_Element::XsdConnection, + kPropertyData, + kAttributeData, + kName, + pdfium::MakeUnique<CJX_XsdConnection>(this)) {} + +CXFA_XsdConnection::~CXFA_XsdConnection() {} diff --git a/xfa/fxfa/parser/cxfa_xsdconnection.h b/xfa/fxfa/parser/cxfa_xsdconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..652d45e15d8363e851d83ca0cc3f8e7e2c147e79 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xsdconnection.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XSDCONNECTION_H_ +#define XFA_FXFA_PARSER_CXFA_XSDCONNECTION_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_XsdConnection : public CXFA_Node { + public: + CXFA_XsdConnection(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_XsdConnection() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XSDCONNECTION_H_ diff --git a/xfa/fxfa/parser/cxfa_xsl.cpp b/xfa/fxfa/parser/cxfa_xsl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d5e71ee53b0263c995f47d61891104454be6ec7 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xsl.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_xsl.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Uri, 1, 0}, + {XFA_Element::Debug, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"xsl"; + +} // namespace + +CXFA_Xsl::CXFA_Xsl(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Xsl, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Xsl::~CXFA_Xsl() {} diff --git a/xfa/fxfa/parser/cxfa_xsl.h b/xfa/fxfa/parser/cxfa_xsl.h new file mode 100644 index 0000000000000000000000000000000000000000..d9211250ae3f5dc6e45d7b738bd3552f22daed0c --- /dev/null +++ b/xfa/fxfa/parser/cxfa_xsl.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_XSL_H_ +#define XFA_FXFA_PARSER_CXFA_XSL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Xsl : public CXFA_Node { + public: + CXFA_Xsl(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Xsl() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_XSL_H_ diff --git a/xfa/fxfa/parser/cxfa_zpl.cpp b/xfa/fxfa/parser/cxfa_zpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa078b5168b5b6eae1f9857d7c0546a83b17cde2 --- /dev/null +++ b/xfa/fxfa/parser/cxfa_zpl.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/parser/cxfa_zpl.h" + +namespace { + +const CXFA_Node::PropertyData kPropertyData[] = { + {XFA_Element::FontInfo, 1, 0}, + {XFA_Element::Xdc, 1, 0}, + {XFA_Element::BatchOutput, 1, 0}, + {XFA_Element::FlipLabel, 1, 0}, + {XFA_Element::Unknown, 0, 0}}; +const CXFA_Node::AttributeData kAttributeData[] = { + {XFA_Attribute::Name, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Desc, XFA_AttributeType::CData, nullptr}, + {XFA_Attribute::Lock, XFA_AttributeType::Integer, (void*)0}, + {XFA_Attribute::Unknown, XFA_AttributeType::Integer, nullptr}}; + +constexpr wchar_t kName[] = L"zpl"; + +} // namespace + +CXFA_Zpl::CXFA_Zpl(CXFA_Document* doc, XFA_PacketType packet) + : CXFA_Node(doc, + packet, + XFA_XDPPACKET_Config, + XFA_ObjectType::Node, + XFA_Element::Zpl, + kPropertyData, + kAttributeData, + kName) {} + +CXFA_Zpl::~CXFA_Zpl() {} diff --git a/xfa/fxfa/parser/cxfa_zpl.h b/xfa/fxfa/parser/cxfa_zpl.h new file mode 100644 index 0000000000000000000000000000000000000000..ee8f9251b84c3419ee309535660b2bd25de33ccf --- /dev/null +++ b/xfa/fxfa/parser/cxfa_zpl.h @@ -0,0 +1,18 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXFA_PARSER_CXFA_ZPL_H_ +#define XFA_FXFA_PARSER_CXFA_ZPL_H_ + +#include "xfa/fxfa/parser/cxfa_node.h" + +class CXFA_Zpl : public CXFA_Node { + public: + CXFA_Zpl(CXFA_Document* doc, XFA_PacketType packet); + ~CXFA_Zpl() override; +}; + +#endif // XFA_FXFA_PARSER_CXFA_ZPL_H_ diff --git a/xfa/fxfa/parser/xfa_basic_data.cpp b/xfa/fxfa/parser/xfa_basic_data.cpp deleted file mode 100644 index fecc942c7db7530313dd6196d7f807356afd3f0e..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_basic_data.cpp +++ /dev/null @@ -1,674 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_basic_data.h" - -#include "xfa/fxfa/fxfa_basic.h" -#include "xfa/fxfa/parser/xfa_object.h" - -const XFA_ELEMENTINFO g_XFAElementData[] = { - {0x23ee3, L"ps", XFA_Element::Ps, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x25363, L"to", XFA_Element::To, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x2587e, L"ui", XFA_Element::Ui, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x1c648b, L"recordSet", XFA_Element::RecordSet, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::Node}, - {0x171428f, L"subsetBelow", XFA_Element::SubsetBelow, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x1a0776a, L"subformSet", XFA_Element::SubformSet, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x2340d70, L"adobeExtensionLevel", XFA_Element::AdobeExtensionLevel, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x2c1c7f1, L"typeface", XFA_Element::Typeface, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::Node}, - {0x5518c25, L"break", XFA_Element::Break, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x5fff523, L"fontInfo", XFA_Element::FontInfo, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x653a227, L"numberPattern", XFA_Element::NumberPattern, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ContentNode}, - {0x65b4a05, L"dynamicRender", XFA_Element::DynamicRender, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x7e4362e, L"printScaling", XFA_Element::PrintScaling, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x7fe6d3a, L"checkButton", XFA_Element::CheckButton, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x80cf58f, L"datePatterns", XFA_Element::DatePatterns, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0x811929d, L"sourceSet", XFA_Element::SourceSet, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::ModelNode}, - {0x9f9d612, L"amd", XFA_Element::Amd, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x9f9efb6, L"arc", XFA_Element::Arc, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xa48835e, L"day", XFA_Element::Day, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::ContentNode}, - {0xa6328b8, L"era", XFA_Element::Era, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::ContentNode}, - {0xae6a0a0, L"jog", XFA_Element::Jog, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xb1b3d22, L"log", XFA_Element::Log, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xb35439e, L"map", XFA_Element::Map, - XFA_XDPPACKET_Config | XFA_XDPPACKET_SourceSet, XFA_ObjectType::Node}, - {0xb355301, L"mdp", XFA_Element::Mdp, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xb420438, L"breakBefore", XFA_Element::BreakBefore, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xb6a091c, L"oid", XFA_Element::Oid, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0xb84389f, L"pcl", XFA_Element::Pcl, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xb843dba, L"pdf", XFA_Element::Pdf, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xbb8df5d, L"ref", XFA_Element::Ref, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0xc080cd0, L"uri", XFA_Element::Uri, - XFA_XDPPACKET_Config | XFA_XDPPACKET_ConnectionSet, - XFA_ObjectType::TextNode}, - {0xc56afbf, L"xdc", XFA_Element::Xdc, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Xdc, XFA_ObjectType::ModelNode}, - {0xc56afcc, L"xdp", XFA_Element::Xdp, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xc56b9ff, L"xfa", XFA_Element::Xfa, XFA_XDPPACKET_XDP, - XFA_ObjectType::ModelNode}, - {0xc56fcb7, L"xsl", XFA_Element::Xsl, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xc8b89d6, L"zpl", XFA_Element::Zpl, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xc9bae94, L"cache", XFA_Element::Cache, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xcb016be, L"margin", XFA_Element::Margin, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xe1378fe, L"keyUsage", XFA_Element::KeyUsage, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xfe3596a, L"exclude", XFA_Element::Exclude, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x10395ac7, L"choiceList", XFA_Element::ChoiceList, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x1059ec18, L"level", XFA_Element::Level, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x10874804, L"labelPrinter", XFA_Element::LabelPrinter, - XFA_XDPPACKET_Config, XFA_ObjectType::Node}, - {0x10c40e03, L"calendarSymbols", XFA_Element::CalendarSymbols, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0x10f1ea24, L"para", XFA_Element::Para, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x10f1ea37, L"part", XFA_Element::Part, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x1140975b, L"pdfa", XFA_Element::Pdfa, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x1154efe6, L"filter", XFA_Element::Filter, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x13f41de1, L"present", XFA_Element::Present, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x1827e6ea, L"pagination", XFA_Element::Pagination, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x18463707, L"encoding", XFA_Element::Encoding, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::NodeC}, - {0x185e41e2, L"event", XFA_Element::Event, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x1adb142d, L"whitespace", XFA_Element::Whitespace, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x1f3f64c3, L"defaultUi", XFA_Element::DefaultUi, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x204e87cb, L"dataModel", XFA_Element::DataModel, XFA_XDPPACKET_Datasets, - XFA_ObjectType::ModelNode}, - {0x2057b350, L"barcode", XFA_Element::Barcode, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x20596bad, L"timePattern", XFA_Element::TimePattern, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ContentNode}, - {0x210b74d3, L"batchOutput", XFA_Element::BatchOutput, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x212ff0e2, L"enforce", XFA_Element::Enforce, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x21d351b4, L"currencySymbols", XFA_Element::CurrencySymbols, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0x21db83c5, L"addSilentPrint", XFA_Element::AddSilentPrint, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x22266258, L"rename", XFA_Element::Rename, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x226ca8f1, L"operation", XFA_Element::Operation, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::TextNode}, - {0x23e27b84, L"typefaces", XFA_Element::Typefaces, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::Node}, - {0x23f4aa75, L"subjectDNs", XFA_Element::SubjectDNs, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x240d5e8e, L"issuers", XFA_Element::Issuers, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x2457a033, L"signaturePseudoModel", XFA_Element::SignaturePseudoModel, - XFA_XDPPACKET_XDP, XFA_ObjectType::Object}, - {0x24a52f8a, L"wsdlConnection", XFA_Element::WsdlConnection, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::Node}, - {0x254ebd07, L"debug", XFA_Element::Debug, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x2655c66a, L"delta", XFA_Element::Delta, XFA_XDPPACKET_Form, - XFA_ObjectType::Object}, - {0x26c0daec, L"eraNames", XFA_Element::EraNames, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::Node}, - {0x273ab03b, L"modifyAnnots", XFA_Element::ModifyAnnots, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x27875bb4, L"startNode", XFA_Element::StartNode, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x285d0dbc, L"button", XFA_Element::Button, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x28dee6e9, L"format", XFA_Element::Format, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x2a23349e, L"border", XFA_Element::Border, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x2ae67f19, L"area", XFA_Element::Area, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x2c3c4c67, L"hyphenation", XFA_Element::Hyphenation, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x2d08af85, L"text", XFA_Element::Text, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0x2d71b00f, L"time", XFA_Element::Time, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0x2f16a382, L"type", XFA_Element::Type, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x2fe057e9, L"overprint", XFA_Element::Overprint, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x302aee16, L"certificates", XFA_Element::Certificates, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x30b227df, L"encryptionMethods", XFA_Element::EncryptionMethods, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x32b900d1, L"setProperty", XFA_Element::SetProperty, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x337d9e45, L"printerName", XFA_Element::PrinterName, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x33edda4b, L"startPage", XFA_Element::StartPage, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x381943e4, L"pageOffset", XFA_Element::PageOffset, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x382106cd, L"dateTime", XFA_Element::DateTime, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0x386e7421, L"comb", XFA_Element::Comb, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x390acd9e, L"pattern", XFA_Element::Pattern, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x3942163e, L"ifEmpty", XFA_Element::IfEmpty, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x39944a7b, L"suppressBanner", XFA_Element::SuppressBanner, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x3b3c3dca, L"outputBin", XFA_Element::OutputBin, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x3b8a4024, L"field", XFA_Element::Field, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x3c15352f, L"agent", XFA_Element::Agent, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x3d7e8668, L"outputXSL", XFA_Element::OutputXSL, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x3e1c91c5, L"adjustData", XFA_Element::AdjustData, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x3e7a9408, L"autoSave", XFA_Element::AutoSave, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x3ecead94, L"contentArea", XFA_Element::ContentArea, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x3ef334e3, L"eventPseudoModel", XFA_Element::EventPseudoModel, - XFA_XDPPACKET_XDP, XFA_ObjectType::Object}, - {0x3fadaec0, L"wsdlAddress", XFA_Element::WsdlAddress, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::TextNode}, - {0x40623b5b, L"solid", XFA_Element::Solid, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x41f0bd76, L"dateTimeSymbols", XFA_Element::DateTimeSymbols, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ContentNode}, - {0x444e7523, L"encryptionLevel", XFA_Element::EncryptionLevel, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x4523af55, L"edge", XFA_Element::Edge, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x45d5e3c1, L"stipple", XFA_Element::Stipple, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x475e4e87, L"attributes", XFA_Element::Attributes, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x487a8c87, L"versionControl", XFA_Element::VersionControl, - XFA_XDPPACKET_Config, XFA_ObjectType::Node}, - {0x48e5248c, L"meridiem", XFA_Element::Meridiem, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::ContentNode}, - {0x48f36719, L"exclGroup", XFA_Element::ExclGroup, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x4977356b, L"toolTip", XFA_Element::ToolTip, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0x499afecc, L"compress", XFA_Element::Compress, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x4a0c4948, L"reason", XFA_Element::Reason, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0x4bdcce13, L"execute", XFA_Element::Execute, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x4c56b216, L"contentCopy", XFA_Element::ContentCopy, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x4cc176d3, L"dateTimeEdit", XFA_Element::DateTimeEdit, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x4e1e39b6, L"config", XFA_Element::Config, XFA_XDPPACKET_Config, - XFA_ObjectType::ModelNode}, - {0x4e2d6083, L"image", XFA_Element::Image, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0x4e814150, L"#xHTML", XFA_Element::SharpxHTML, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_SourceSet | - XFA_XDPPACKET_Form, - XFA_ObjectType::NodeV}, - {0x4f2388c1, L"numberOfCopies", XFA_Element::NumberOfCopies, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x4f512e30, L"behaviorOverride", XFA_Element::BehaviorOverride, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x4fdc3454, L"timeStamp", XFA_Element::TimeStamp, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x51d90546, L"month", XFA_Element::Month, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::ContentNode}, - {0x523437e4, L"viewerPreferences", XFA_Element::ViewerPreferences, - XFA_XDPPACKET_Config, XFA_ObjectType::Node}, - {0x53abc1c6, L"scriptModel", XFA_Element::ScriptModel, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x54034c2f, L"decimal", XFA_Element::Decimal, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0x54202c9e, L"subform", XFA_Element::Subform, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x542c7300, L"select", XFA_Element::Select, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::TextNode}, - {0x5436d198, L"window", XFA_Element::Window, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x5473b6dc, L"localeSet", XFA_Element::LocaleSet, - XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ModelNode}, - {0x56ae179e, L"handler", XFA_Element::Handler, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0x5700bd5f, L"hostPseudoModel", XFA_Element::HostPseudoModel, - XFA_XDPPACKET_XDP, XFA_ObjectType::Object}, - {0x570ce835, L"presence", XFA_Element::Presence, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x5779d65f, L"record", XFA_Element::Record, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x59c8f27d, L"embed", XFA_Element::Embed, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x5a50e9e6, L"version", XFA_Element::Version, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x5b8383df, L"command", XFA_Element::Command, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::Node}, - {0x5c43c6c3, L"copies", XFA_Element::Copies, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x5e0c2c49, L"staple", XFA_Element::Staple, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x5e5083dd, L"submitFormat", XFA_Element::SubmitFormat, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x5e8c5d20, L"boolean", XFA_Element::Boolean, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0x60490a85, L"message", XFA_Element::Message, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::Node}, - {0x60d4c8b1, L"output", XFA_Element::Output, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x61810081, L"psMap", XFA_Element::PsMap, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x62bd904b, L"excludeNS", XFA_Element::ExcludeNS, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x669d4f77, L"assist", XFA_Element::Assist, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x67334a1c, L"picture", XFA_Element::Picture, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0x67fe7334, L"traversal", XFA_Element::Traversal, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x6894589c, L"silentPrint", XFA_Element::SilentPrint, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x68a16bbd, L"webClient", XFA_Element::WebClient, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x69f115df, L"layoutPseudoModel", XFA_Element::LayoutPseudoModel, - XFA_XDPPACKET_XDP, XFA_ObjectType::Object}, - {0x6a4bc084, L"producer", XFA_Element::Producer, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x6a9e04c9, L"corner", XFA_Element::Corner, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x6ccd7274, L"msgId", XFA_Element::MsgId, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x6e67921f, L"color", XFA_Element::Color, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x6ec217a5, L"keep", XFA_Element::Keep, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x6eef1116, L"query", XFA_Element::Query, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::Node}, - {0x7033bfd5, L"insert", XFA_Element::Insert, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::TextNode}, - {0x704af389, L"imageEdit", XFA_Element::ImageEdit, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x7233018a, L"validate", XFA_Element::Validate, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0x72ba47b4, L"digestMethods", XFA_Element::DigestMethods, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x72f2aa7a, L"numberPatterns", XFA_Element::NumberPatterns, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0x74caed29, L"pageSet", XFA_Element::PageSet, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x7568e6ae, L"integer", XFA_Element::Integer, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0x76182db9, L"soapAddress", XFA_Element::SoapAddress, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::TextNode}, - {0x773146c5, L"equate", XFA_Element::Equate, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x77d449dd, L"formFieldFilling", XFA_Element::FormFieldFilling, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x7889d68a, L"pageRange", XFA_Element::PageRange, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x7baca2e3, L"update", XFA_Element::Update, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::TextNode}, - {0x7ce89001, L"connectString", XFA_Element::ConnectString, - XFA_XDPPACKET_SourceSet, XFA_ObjectType::TextNode}, - {0x7d9fd7c5, L"mode", XFA_Element::Mode, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x7e7e845e, L"layout", XFA_Element::Layout, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x7e845c34, L"#xml", XFA_Element::Sharpxml, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::NodeV}, - {0x7fb341df, L"xsdConnection", XFA_Element::XsdConnection, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::Node}, - {0x7ffb51cc, L"traverse", XFA_Element::Traverse, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x80203b5a, L"encodings", XFA_Element::Encodings, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x803550fc, L"template", XFA_Element::Template, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ModelNode}, - {0x803d5bbc, L"acrobat", XFA_Element::Acrobat, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0x821d6569, L"validationMessaging", XFA_Element::ValidationMessaging, - XFA_XDPPACKET_Config, XFA_ObjectType::NodeV}, - {0x830e688f, L"signing", XFA_Element::Signing, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x83a550d2, L"dataWindow", XFA_Element::DataWindow, XFA_XDPPACKET_Datasets, - XFA_ObjectType::Object}, - {0x83dab9f5, L"script", XFA_Element::Script, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0x8411ebcd, L"addViewerPreferences", XFA_Element::AddViewerPreferences, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x8777642e, L"alwaysEmbed", XFA_Element::AlwaysEmbed, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x877a6b39, L"passwordEdit", XFA_Element::PasswordEdit, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x87e84c99, L"numericEdit", XFA_Element::NumericEdit, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x8852cdec, L"encryptionMethod", XFA_Element::EncryptionMethod, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::NodeC}, - {0x891f4606, L"change", XFA_Element::Change, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x89939f36, L"pageArea", XFA_Element::PageArea, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0x8a9d6247, L"submitUrl", XFA_Element::SubmitUrl, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0x8ad8b90f, L"oids", XFA_Element::Oids, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x8b036f32, L"signature", XFA_Element::Signature, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x8b128efb, L"ADBE_JSConsole", XFA_Element::ADBE_JSConsole, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0x8bcfe96e, L"caption", XFA_Element::Caption, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x8e1c2921, L"relevant", XFA_Element::Relevant, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x8e3f0a4b, L"flipLabel", XFA_Element::FlipLabel, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0x900280b7, L"exData", XFA_Element::ExData, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0x91e80352, L"dayNames", XFA_Element::DayNames, XFA_XDPPACKET_LocaleSet, - XFA_ObjectType::Node}, - {0x93113b11, L"soapAction", XFA_Element::SoapAction, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::TextNode}, - {0x938b09f6, L"defaultTypeface", XFA_Element::DefaultTypeface, - XFA_XDPPACKET_Config, XFA_ObjectType::NodeV}, - {0x95b37897, L"manifest", XFA_Element::Manifest, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x97b76b54, L"overflow", XFA_Element::Overflow, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x9a57861b, L"linear", XFA_Element::Linear, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0x9ad5a821, L"currencySymbol", XFA_Element::CurrencySymbol, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ContentNode}, - {0x9c6471b3, L"delete", XFA_Element::Delete, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::TextNode}, - {0x9deea61d, L"deltas", XFA_Element::Deltas, XFA_XDPPACKET_Form, - XFA_ObjectType::Object}, - {0x9e67de21, L"digestMethod", XFA_Element::DigestMethod, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::NodeC}, - {0x9f3e9510, L"instanceManager", XFA_Element::InstanceManager, - XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xa0799892, L"equateRange", XFA_Element::EquateRange, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xa084a381, L"medium", XFA_Element::Medium, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xa1211b8b, L"textEdit", XFA_Element::TextEdit, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xa17008f0, L"templateCache", XFA_Element::TemplateCache, - XFA_XDPPACKET_Config, XFA_ObjectType::Node}, - {0xa4f7b88f, L"compressObjectStream", XFA_Element::CompressObjectStream, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xa65f5d17, L"dataValue", XFA_Element::DataValue, XFA_XDPPACKET_Datasets, - XFA_ObjectType::Node}, - {0xa6caaa89, L"accessibleContent", XFA_Element::AccessibleContent, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xa8c7d5e2, L"nodeList", XFA_Element::NodeList, XFA_XDPPACKET_XDP, - XFA_ObjectType::NodeList}, - {0xa94cc00b, L"includeXDPContent", XFA_Element::IncludeXDPContent, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xa9b081a1, L"xmlConnection", XFA_Element::XmlConnection, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::Node}, - {0xab2a3b74, L"validateApprovalSignatures", - XFA_Element::ValidateApprovalSignatures, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xab8c5a2b, L"signData", XFA_Element::SignData, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xabaa2ceb, L"packets", XFA_Element::Packets, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xadba359c, L"datePattern", XFA_Element::DatePattern, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ContentNode}, - {0xae222b2b, L"duplexOption", XFA_Element::DuplexOption, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xb012effb, L"base", XFA_Element::Base, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xb0e5485d, L"bind", XFA_Element::Bind, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::Node}, - {0xb45d61b2, L"compression", XFA_Element::Compression, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xb563f0ff, L"user", XFA_Element::User, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::TextNode}, - {0xb5848ad5, L"rectangle", XFA_Element::Rectangle, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xb6dacb72, L"effectiveOutputPolicy", XFA_Element::EffectiveOutputPolicy, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::Node}, - {0xb7d7654d, L"ADBE_JSDebugger", XFA_Element::ADBE_JSDebugger, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xbab37f73, L"acrobat7", XFA_Element::Acrobat7, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xbc70081e, L"interactive", XFA_Element::Interactive, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xbc8fa350, L"locale", XFA_Element::Locale, - XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0xbcd44940, L"currentPage", XFA_Element::CurrentPage, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xbde9abda, L"data", XFA_Element::Data, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xbde9abde, L"date", XFA_Element::Date, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0xbe52dfbf, L"desc", XFA_Element::Desc, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xbf4b6405, L"encrypt", XFA_Element::Encrypt, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | XFA_XDPPACKET_Form, - XFA_ObjectType::ContentNode}, - {0xbfa87cce, L"draw", XFA_Element::Draw, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0xc181ff4b, L"encryption", XFA_Element::Encryption, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xc1970f40, L"meridiemNames", XFA_Element::MeridiemNames, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0xc5ad9f5e, L"messaging", XFA_Element::Messaging, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xc69549f4, L"speak", XFA_Element::Speak, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0xc7743dc7, L"dataGroup", XFA_Element::DataGroup, XFA_XDPPACKET_Datasets, - XFA_ObjectType::Node}, - {0xc7eb20e9, L"common", XFA_Element::Common, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xc85d4528, L"#text", XFA_Element::Sharptext, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_SourceSet | - XFA_XDPPACKET_Form, - XFA_ObjectType::NodeV}, - {0xc861556a, L"paginationOverride", XFA_Element::PaginationOverride, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xc903dabb, L"reasons", XFA_Element::Reasons, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xc9a8127f, L"signatureProperties", XFA_Element::SignatureProperties, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xca010c2d, L"threshold", XFA_Element::Threshold, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xcb4c5e96, L"appearanceFilter", XFA_Element::AppearanceFilter, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::NodeC}, - {0xcc92aba7, L"fill", XFA_Element::Fill, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xcd308b77, L"font", XFA_Element::Font, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Config | XFA_XDPPACKET_Form, - XFA_ObjectType::Node}, - {0xcd309ff4, L"form", XFA_Element::Form, XFA_XDPPACKET_Form, - XFA_ObjectType::ModelNode}, - {0xcebcca2d, L"mediumInfo", XFA_Element::MediumInfo, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xcfe0d643, L"certificate", XFA_Element::Certificate, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::TextNode}, - {0xd012c033, L"password", XFA_Element::Password, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::TextNode}, - {0xd01604bd, L"runScripts", XFA_Element::RunScripts, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xd1227e6f, L"trace", XFA_Element::Trace, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xd1532876, L"float", XFA_Element::Float, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0xd17a6c30, L"renderPolicy", XFA_Element::RenderPolicy, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xd4bf6823, L"logPseudoModel", XFA_Element::LogPseudoModel, - XFA_XDPPACKET_XDP, XFA_ObjectType::Object}, - {0xd58aa962, L"destination", XFA_Element::Destination, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xd6e27f1d, L"value", XFA_Element::Value, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xd7a14462, L"bookend", XFA_Element::Bookend, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xd8c31254, L"exObject", XFA_Element::ExObject, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xda6a8590, L"openAction", XFA_Element::OpenAction, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xdab4fb7d, L"neverEmbed", XFA_Element::NeverEmbed, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xdb98475f, L"bindItems", XFA_Element::BindItems, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xdbfbe02e, L"calculate", XFA_Element::Calculate, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xdd7676ed, L"print", XFA_Element::Print, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xdde273d7, L"extras", XFA_Element::Extras, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::Node}, - {0xde146b34, L"proto", XFA_Element::Proto, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xdf059321, L"dSigData", XFA_Element::DSigData, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xdfccf030, L"creator", XFA_Element::Creator, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xdff78c6a, L"connect", XFA_Element::Connect, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::Node}, - {0xe11a2cbc, L"permissions", XFA_Element::Permissions, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xe14c801c, L"connectionSet", XFA_Element::ConnectionSet, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::ModelNode}, - {0xe1c83a14, L"submit", XFA_Element::Submit, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xe29821cd, L"range", XFA_Element::Range, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xe38d83c7, L"linearized", XFA_Element::Linearized, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xe3aa2578, L"packet", XFA_Element::Packet, XFA_XDPPACKET_XDP, - XFA_ObjectType::NodeC}, - {0xe3aa860e, L"rootElement", XFA_Element::RootElement, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::TextNode}, - {0xe3e553fa, L"plaintextMetadata", XFA_Element::PlaintextMetadata, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xe3e6e4f2, L"numberSymbols", XFA_Element::NumberSymbols, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0xe3f067f6, L"printHighQuality", XFA_Element::PrintHighQuality, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xe3fd078c, L"driver", XFA_Element::Driver, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xe48b34f2, L"incrementalLoad", XFA_Element::IncrementalLoad, - XFA_XDPPACKET_Config, XFA_ObjectType::NodeV}, - {0xe550e7c2, L"subjectDN", XFA_Element::SubjectDN, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::NodeC}, - {0xe6669a78, L"compressLogicalStructure", - XFA_Element::CompressLogicalStructure, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xe7a7ea02, L"incrementalMerge", XFA_Element::IncrementalMerge, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xe948530d, L"radial", XFA_Element::Radial, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xea8d6999, L"variables", XFA_Element::Variables, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - XFA_ObjectType::ContainerNode}, - {0xeaa142c0, L"timePatterns", XFA_Element::TimePatterns, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0xeb943a71, L"effectiveInputPolicy", XFA_Element::EffectiveInputPolicy, - XFA_XDPPACKET_ConnectionSet, XFA_ObjectType::Node}, - {0xef04a2bc, L"nameAttr", XFA_Element::NameAttr, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xf07222ab, L"conformance", XFA_Element::Conformance, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xf0aaaadc, L"transform", XFA_Element::Transform, XFA_XDPPACKET_Config, - XFA_ObjectType::Node}, - {0xf1433e88, L"lockDocument", XFA_Element::LockDocument, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::ContentNode}, - {0xf54eb997, L"breakAfter", XFA_Element::BreakAfter, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xf616da28, L"line", XFA_Element::Line, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xf616f3dc, L"list", XFA_Element::List, XFA_XDPPACKET_XDP, - XFA_ObjectType::List}, - {0xf7055fb1, L"source", XFA_Element::Source, XFA_XDPPACKET_SourceSet, - XFA_ObjectType::Node}, - {0xf7eebe1c, L"occur", XFA_Element::Occur, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, - {0xf8d10d97, L"pickTrayByPDFSize", XFA_Element::PickTrayByPDFSize, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xf8f19e3a, L"monthNames", XFA_Element::MonthNames, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::Node}, - {0xf984149b, L"severity", XFA_Element::Severity, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xf9bcb037, L"groupParent", XFA_Element::GroupParent, XFA_XDPPACKET_Config, - XFA_ObjectType::NodeV}, - {0xfbc42fff, L"documentAssembly", XFA_Element::DocumentAssembly, - XFA_XDPPACKET_Config, XFA_ObjectType::ContentNode}, - {0xfc78159f, L"numberSymbol", XFA_Element::NumberSymbol, - XFA_XDPPACKET_LocaleSet, XFA_ObjectType::ContentNode}, - {0xfcbd606c, L"tagged", XFA_Element::Tagged, XFA_XDPPACKET_Config, - XFA_ObjectType::ContentNode}, - {0xff063802, L"items", XFA_Element::Items, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, XFA_ObjectType::Node}, -}; -const int32_t g_iXFAElementCount = FX_ArraySize(g_XFAElementData); -static_assert(g_iXFAElementCount == - (static_cast<int32_t>(XFA_Element::Items) + 1), - "g_XFAElementData size does not match XFA_Elements"); - diff --git a/xfa/fxfa/parser/xfa_basic_data.h b/xfa/fxfa/parser/xfa_basic_data.h index 5b97ee2faaab431899c43431c18903956ab94604..b394d35fe53cf1f3a728ab7bd0e21adbf2cf76d6 100644 --- a/xfa/fxfa/parser/xfa_basic_data.h +++ b/xfa/fxfa/parser/xfa_basic_data.h @@ -7,41 +7,16 @@ #ifndef XFA_FXFA_PARSER_XFA_BASIC_DATA_H_ #define XFA_FXFA_PARSER_XFA_BASIC_DATA_H_ -#include "xfa/fxfa/fxfa_basic.h" +#include <map> -extern const XFA_PACKETINFO g_XFAPacketData[]; -extern const int32_t g_iXFAPacketCount; +#include "xfa/fxfa/fxfa_basic.h" -extern const XFA_ATTRIBUTEENUMINFO g_XFAEnumData[]; +extern const XFA_AttributeEnumInfo g_XFAEnumData[]; extern const int32_t g_iXFAEnumCount; -extern const XFA_ATTRIBUTEINFO g_XFAAttributeData[]; -extern const int32_t g_iXFAAttributeCount; - -extern const XFA_NOTSUREATTRIBUTE g_XFANotsureAttributes[]; -extern const int32_t g_iXFANotsureCount; - -extern const XFA_ELEMENTINFO g_XFAElementData[]; -extern const int32_t g_iXFAElementCount; - -extern const XFA_ELEMENTHIERARCHY g_XFAElementChildrenIndex[]; -extern const uint16_t g_XFAElementChildrenData[]; - -extern const XFA_ELEMENTHIERARCHY g_XFAElementAttributeIndex[]; -extern const uint8_t g_XFAElementAttributeData[]; - -extern const XFA_ELEMENTHIERARCHY g_XFAElementPropertyIndex[]; -extern const XFA_PROPERTY g_XFAElementPropertyData[]; - extern const XFA_SCRIPTHIERARCHY g_XFAScriptIndex[]; extern const int32_t g_iScriptIndexCount; -extern const XFA_NOTSUREATTRIBUTE g_XFANotsureAttributes[]; -extern const int32_t g_iXFANotsureCount; - -extern const XFA_METHODINFO g_SomMethodData[]; -extern const int32_t g_iSomMethodCount; - extern const XFA_SCRIPTATTRIBUTEINFO g_SomAttributeData[]; extern const int32_t g_iSomAttributeCount; diff --git a/xfa/fxfa/parser/xfa_basic_data_attributes.cpp b/xfa/fxfa/parser/xfa_basic_data_attributes.cpp deleted file mode 100644 index 6ed16a0c3d8f3f0b16fd142457f939a8c583983c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_basic_data_attributes.cpp +++ /dev/null @@ -1,786 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_basic_data.h" - -#include "xfa/fxfa/fxfa_basic.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" - -static const CXFA_Measurement g_XFAMeasurementData[] = { - CXFA_Measurement(0, XFA_UNIT_In), - CXFA_Measurement(0, XFA_UNIT_Pt), - CXFA_Measurement(5, XFA_UNIT_Mm), - CXFA_Measurement(0.25, XFA_UNIT_Mm), - CXFA_Measurement(-1, XFA_UNIT_Unknown), - CXFA_Measurement(0, XFA_UNIT_Angle), - CXFA_Measurement(10, XFA_UNIT_Pt), - CXFA_Measurement(360, XFA_UNIT_Angle), - CXFA_Measurement(0.5, XFA_UNIT_Pt), -}; - -const XFA_ATTRIBUTEINFO g_XFAAttributeData[] = { - {0x68, L"h", XFA_ATTRIBUTE_H, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x77, L"w", XFA_ATTRIBUTE_W, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x78, L"x", XFA_ATTRIBUTE_X, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x79, L"y", XFA_ATTRIBUTE_Y, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x21aed, L"id", XFA_ATTRIBUTE_Id, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_Form, - nullptr}, - {0x25363, L"to", XFA_ATTRIBUTE_To, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Config, nullptr}, - {0xcb0ac9, L"lineThrough", XFA_ATTRIBUTE_LineThrough, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x2282c73, L"hAlign", XFA_ATTRIBUTE_HAlign, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Left}, - {0x2c1c7f1, L"typeface", XFA_ATTRIBUTE_Typeface, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"Courier"}, - {0x3106c3a, L"beforeTarget", XFA_ATTRIBUTE_BeforeTarget, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x31b19c1, L"name", XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet | - XFA_XDPPACKET_Template | XFA_XDPPACKET_Datasets | XFA_XDPPACKET_Form | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_Form, - nullptr}, - {0x3848b3f, L"next", XFA_ATTRIBUTE_Next, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_None}, - {0x43e349b, L"dataRowCount", XFA_ATTRIBUTE_DataRowCount, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x5518c25, L"break", XFA_ATTRIBUTE_Break, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Close}, - {0x5ce6195, L"vScrollPolicy", XFA_ATTRIBUTE_VScrollPolicy, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0x8c74ae9, L"fontHorizontalScale", XFA_ATTRIBUTE_FontHorizontalScale, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"100%"}, - {0x8d4f1c7, L"textIndent", XFA_ATTRIBUTE_TextIndent, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x97c1c65, L"context", XFA_ATTRIBUTE_Context, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_UNKNOWN, (void*)0}, - {0x9876578, L"trayOut", XFA_ATTRIBUTE_TrayOut, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0xa2e3514, L"cap", XFA_ATTRIBUTE_Cap, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Square}, - {0xb3543a6, L"max", XFA_ATTRIBUTE_Max, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xb356ca4, L"min", XFA_ATTRIBUTE_Min, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)1}, - {0xbb8df5d, L"ref", XFA_ATTRIBUTE_Ref, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | - XFA_XDPPACKET_Form, - nullptr}, - {0xbb8f3df, L"rid", XFA_ATTRIBUTE_Rid, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xc080cd3, L"url", XFA_ATTRIBUTE_Url, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xc0811ed, L"use", XFA_ATTRIBUTE_Use, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_Form, - nullptr}, - {0xcfea02e, L"leftInset", XFA_ATTRIBUTE_LeftInset, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x1026c59d, L"widows", XFA_ATTRIBUTE_Widows, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x1059ec18, L"level", XFA_ATTRIBUTE_Level, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Config, (void*)0}, - {0x1356caf8, L"bottomInset", XFA_ATTRIBUTE_BottomInset, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x13a08bdb, L"overflowTarget", XFA_ATTRIBUTE_OverflowTarget, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x1414d431, L"allowMacro", XFA_ATTRIBUTE_AllowMacro, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x14a32d52, L"pagePosition", XFA_ATTRIBUTE_PagePosition, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Any}, - {0x1517dfa1, L"columnWidths", XFA_ATTRIBUTE_ColumnWidths, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x169134a1, L"overflowLeader", XFA_ATTRIBUTE_OverflowLeader, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x1b8dce3e, L"action", XFA_ATTRIBUTE_Action, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Include}, - {0x1e459b8f, L"nonRepudiation", XFA_ATTRIBUTE_NonRepudiation, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x1ec8ab2c, L"rate", XFA_ATTRIBUTE_Rate, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)50}, - {0x1ef3a64a, L"allowRichText", XFA_ATTRIBUTE_AllowRichText, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x2038c9b2, L"role", XFA_ATTRIBUTE_Role, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x20914367, L"overflowTrailer", XFA_ATTRIBUTE_OverflowTrailer, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x226ca8f1, L"operation", XFA_ATTRIBUTE_Operation, - XFA_ATTRIBUTETYPE_NOTSURE, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x24d85167, L"timeout", XFA_ATTRIBUTE_Timeout, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_SourceSet, nullptr}, - {0x25764436, L"topInset", XFA_ATTRIBUTE_TopInset, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x25839852, L"access", XFA_ATTRIBUTE_Access, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Open}, - {0x268b7ec1, L"commandType", XFA_ATTRIBUTE_CommandType, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_SourceSet, - (void*)XFA_ATTRIBUTEENUM_Unknown}, - {0x28dee6e9, L"format", XFA_ATTRIBUTE_Format, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x28e17e91, L"dataPrep", XFA_ATTRIBUTE_DataPrep, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_None}, - {0x292b88fe, L"widgetData", XFA_ATTRIBUTE_WidgetData, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_UNKNOWN, (void*)0}, - {0x29418bb7, L"abbr", XFA_ATTRIBUTE_Abbr, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_LocaleSet, (void*)0}, - {0x2a82d99c, L"marginRight", XFA_ATTRIBUTE_MarginRight, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x2b5df51e, L"dataDescription", XFA_ATTRIBUTE_DataDescription, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_ConnectionSet, nullptr}, - {0x2bb3f470, L"encipherOnly", XFA_ATTRIBUTE_EncipherOnly, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x2cd79033, L"kerningMode", XFA_ATTRIBUTE_KerningMode, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_None}, - {0x2ee7678f, L"rotate", XFA_ATTRIBUTE_Rotate, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 5)}, - {0x2f105f72, L"wordCharacterCount", XFA_ATTRIBUTE_WordCharacterCount, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)7}, - {0x2f16a382, L"type", XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x34ae103c, L"reserve", XFA_ATTRIBUTE_Reserve, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 4)}, - {0x3650557e, L"textLocation", XFA_ATTRIBUTE_TextLocation, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Below}, - {0x39cdb0a2, L"priority", XFA_ATTRIBUTE_Priority, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Custom}, - {0x3a0273a6, L"underline", XFA_ATTRIBUTE_Underline, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x3b582286, L"moduleWidth", XFA_ATTRIBUTE_ModuleWidth, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 3)}, - {0x3d123c26, L"hyphenate", XFA_ATTRIBUTE_Hyphenate, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x3e7af94f, L"listen", XFA_ATTRIBUTE_Listen, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_RefOnly}, - {0x4156ee3f, L"delimiter", XFA_ATTRIBUTE_Delimiter, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x42fed1fd, L"contentType", XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | - XFA_XDPPACKET_Datasets | XFA_XDPPACKET_Form, - nullptr}, - {0x453eaf38, L"startNew", XFA_ATTRIBUTE_StartNew, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x45a6daf8, L"eofAction", XFA_ATTRIBUTE_EofAction, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_SourceSet, (void*)XFA_ATTRIBUTEENUM_MoveLast}, - {0x47cfa43a, L"allowNeutral", XFA_ATTRIBUTE_AllowNeutral, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x47d03490, L"connection", XFA_ATTRIBUTE_Connection, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x4873c601, L"baselineShift", XFA_ATTRIBUTE_BaselineShift, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x4b319767, L"overlinePeriod", XFA_ATTRIBUTE_OverlinePeriod, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_All}, - {0x4b8bc840, L"fracDigits", XFA_ATTRIBUTE_FracDigits, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)2}, - {0x4ef3d02c, L"orientation", XFA_ATTRIBUTE_Orientation, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Portrait}, - {0x4fdc3454, L"timeStamp", XFA_ATTRIBUTE_TimeStamp, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_XDP, nullptr}, - {0x52666f1c, L"printCheckDigit", XFA_ATTRIBUTE_PrintCheckDigit, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x534729c9, L"marginLeft", XFA_ATTRIBUTE_MarginLeft, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x5392ea58, L"stroke", XFA_ATTRIBUTE_Stroke, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Solid}, - {0x5404d6df, L"moduleHeight", XFA_ATTRIBUTE_ModuleHeight, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 2)}, - {0x54fa722c, L"transferEncoding", XFA_ATTRIBUTE_TransferEncoding, - XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x552d9ad5, L"usage", XFA_ATTRIBUTE_Usage, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_ExportAndImport}, - {0x570ce835, L"presence", XFA_ATTRIBUTE_Presence, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Visible}, - {0x5739d1ff, L"radixOffset", XFA_ATTRIBUTE_RadixOffset, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x577682ac, L"preserve", XFA_ATTRIBUTE_Preserve, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x58be2870, L"aliasNode", XFA_ATTRIBUTE_AliasNode, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_UNKNOWN, (void*)0}, - {0x5a32e493, L"multiLine", XFA_ATTRIBUTE_MultiLine, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x5a50e9e6, L"version", XFA_ATTRIBUTE_Version, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x5ab23b6c, L"startChar", XFA_ATTRIBUTE_StartChar, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x5b707a35, L"scriptTest", XFA_ATTRIBUTE_ScriptTest, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Error}, - {0x5c054755, L"startAngle", XFA_ATTRIBUTE_StartAngle, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 5)}, - {0x5ec958c0, L"cursorType", XFA_ATTRIBUTE_CursorType, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_SourceSet, - (void*)XFA_ATTRIBUTEENUM_ForwardOnly}, - {0x5f760b50, L"digitalSignature", XFA_ATTRIBUTE_DigitalSignature, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x60a61edd, L"codeType", XFA_ATTRIBUTE_CodeType, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x60d4c8b1, L"output", XFA_ATTRIBUTE_Output, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_ConnectionSet, nullptr}, - {0x64110ab5, L"bookendTrailer", XFA_ATTRIBUTE_BookendTrailer, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x65e30c67, L"imagingBBox", XFA_ATTRIBUTE_ImagingBBox, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"none"}, - {0x66539c48, L"excludeInitialCap", XFA_ATTRIBUTE_ExcludeInitialCap, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x66642f8f, L"force", XFA_ATTRIBUTE_Force, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Config, nullptr}, - {0x69aa2292, L"crlSign", XFA_ATTRIBUTE_CrlSign, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x6a3405dd, L"previous", XFA_ATTRIBUTE_Previous, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_None}, - {0x6a95c976, L"pushCharacterCount", XFA_ATTRIBUTE_PushCharacterCount, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)3}, - {0x6b6ddcfb, L"nullTest", XFA_ATTRIBUTE_NullTest, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Disabled}, - {0x6cfa828a, L"runAt", XFA_ATTRIBUTE_RunAt, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Client}, - {0x731e0665, L"spaceBelow", XFA_ATTRIBUTE_SpaceBelow, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x74788f8b, L"sweepAngle", XFA_ATTRIBUTE_SweepAngle, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 7)}, - {0x78bff531, L"numberOfCells", XFA_ATTRIBUTE_NumberOfCells, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0x79543055, L"letterSpacing", XFA_ATTRIBUTE_LetterSpacing, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x79975f2b, L"lockType", XFA_ATTRIBUTE_LockType, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_SourceSet, (void*)XFA_ATTRIBUTEENUM_ReadOnly}, - {0x7a0cc471, L"passwordChar", XFA_ATTRIBUTE_PasswordChar, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"*"}, - {0x7a7cc341, L"vAlign", XFA_ATTRIBUTE_VAlign, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)XFA_ATTRIBUTEENUM_Top}, - {0x7b29630a, L"sourceBelow", XFA_ATTRIBUTE_SourceBelow, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Config, - (void*)XFA_ATTRIBUTEENUM_Update}, - {0x7b95e661, L"inverted", XFA_ATTRIBUTE_Inverted, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x7c2fd80b, L"mark", XFA_ATTRIBUTE_Mark, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Default}, - {0x7c2ff6ae, L"maxH", XFA_ATTRIBUTE_MaxH, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x7c2ff6bd, L"maxW", XFA_ATTRIBUTE_MaxW, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x7c732a66, L"truncate", XFA_ATTRIBUTE_Truncate, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x7d02356c, L"minH", XFA_ATTRIBUTE_MinH, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x7d02357b, L"minW", XFA_ATTRIBUTE_MinW, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x7d0b5fca, L"initial", XFA_ATTRIBUTE_Initial, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)1}, - {0x7d9fd7c5, L"mode", XFA_ATTRIBUTE_Mode, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Config, (void*)XFA_ATTRIBUTEENUM_UsePrinterSetting}, - {0x7e7e845e, L"layout", XFA_ATTRIBUTE_Layout, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Position}, - {0x7f6fd3d7, L"server", XFA_ATTRIBUTE_Server, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x824f21b7, L"embedPDF", XFA_ATTRIBUTE_EmbedPDF, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x8340ea66, L"oddOrEven", XFA_ATTRIBUTE_OddOrEven, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)XFA_ATTRIBUTEENUM_Any}, - {0x836d4d7c, L"tabDefault", XFA_ATTRIBUTE_TabDefault, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x8855805f, L"contains", XFA_ATTRIBUTE_Contains, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Datasets, (void*)XFA_ATTRIBUTEENUM_Data}, - {0x8a692521, L"rightInset", XFA_ATTRIBUTE_RightInset, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x8af2e657, L"maxChars", XFA_ATTRIBUTE_MaxChars, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x8b90e1f2, L"open", XFA_ATTRIBUTE_Open, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_UserControl}, - {0x8c99377e, L"relation", XFA_ATTRIBUTE_Relation, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x8d181d61, L"wideNarrowRatio", XFA_ATTRIBUTE_WideNarrowRatio, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"3:1"}, - {0x8e1c2921, L"relevant", XFA_ATTRIBUTE_Relevant, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x8e29d794, L"signatureType", XFA_ATTRIBUTE_SignatureType, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Filter}, - {0x8ec6204c, L"lineThroughPeriod", XFA_ATTRIBUTE_LineThroughPeriod, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_All}, - {0x8ed182d1, L"shape", XFA_ATTRIBUTE_Shape, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Square}, - {0x8fa01790, L"tabStops", XFA_ATTRIBUTE_TabStops, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0x8fc36c0a, L"outputBelow", XFA_ATTRIBUTE_OutputBelow, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Config, - (void*)XFA_ATTRIBUTEENUM_Warn}, - {0x9041d4b0, L"short", XFA_ATTRIBUTE_Short, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0x907c7719, L"fontVerticalScale", XFA_ATTRIBUTE_FontVerticalScale, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"100%"}, - {0x94446dcc, L"thickness", XFA_ATTRIBUTE_Thickness, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 8)}, - {0x957fa006, L"commitOn", XFA_ATTRIBUTE_CommitOn, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Select}, - {0x982bd892, L"remainCharacterCount", XFA_ATTRIBUTE_RemainCharacterCount, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)3}, - {0x98fd4d81, L"keyAgreement", XFA_ATTRIBUTE_KeyAgreement, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x99800d7a, L"errorCorrectionLevel", XFA_ATTRIBUTE_ErrorCorrectionLevel, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0x9a63da3d, L"upsMode", XFA_ATTRIBUTE_UpsMode, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_UsCarrier}, - {0x9cc17d75, L"mergeMode", XFA_ATTRIBUTE_MergeMode, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_ConsumeData}, - {0x9d833d75, L"circular", XFA_ATTRIBUTE_Circular, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0x9d8ee204, L"psName", XFA_ATTRIBUTE_PsName, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Config, nullptr}, - {0x9dcc3ab3, L"trailer", XFA_ATTRIBUTE_Trailer, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xa0933954, L"unicodeRange", XFA_ATTRIBUTE_UnicodeRange, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Config, nullptr}, - {0xa1b0d2f5, L"executeType", XFA_ATTRIBUTE_ExecuteType, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Import}, - {0xa25a883d, L"duplexImposition", XFA_ATTRIBUTE_DuplexImposition, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_LongEdge}, - {0xa42ca1b7, L"trayIn", XFA_ATTRIBUTE_TrayIn, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0xa433f001, L"bindingNode", XFA_ATTRIBUTE_BindingNode, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_UNKNOWN, (void*)0}, - {0xa5340ff5, L"bofAction", XFA_ATTRIBUTE_BofAction, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_SourceSet, (void*)XFA_ATTRIBUTEENUM_MoveFirst}, - {0xa5b410cf, L"save", XFA_ATTRIBUTE_Save, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0xa6118c89, L"targetType", XFA_ATTRIBUTE_TargetType, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0xa66404cb, L"keyEncipherment", XFA_ATTRIBUTE_KeyEncipherment, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xa6710262, L"credentialServerPolicy", - XFA_ATTRIBUTE_CredentialServerPolicy, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {0xa686975b, L"size", XFA_ATTRIBUTE_Size, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 6)}, - {0xa85e74f3, L"initialNumber", XFA_ATTRIBUTE_InitialNumber, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)1}, - {0xabef37e3, L"slope", XFA_ATTRIBUTE_Slope, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Backslash}, - {0xabfa6c4f, L"cSpace", XFA_ATTRIBUTE_CSpace, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)L"SRGB"}, - {0xac06e2b0, L"colSpan", XFA_ATTRIBUTE_ColSpan, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)1}, - {0xadc4c77b, L"binding", XFA_ATTRIBUTE_Binding, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xaf754613, L"checksum", XFA_ATTRIBUTE_Checksum, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form | XFA_XDPPACKET_Form, nullptr}, - {0xb045fbc5, L"charEncoding", XFA_ATTRIBUTE_CharEncoding, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)L"UTF-8"}, - {0xb0e5485d, L"bind", XFA_ATTRIBUTE_Bind, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet, nullptr}, - {0xb12128b7, L"textEntry", XFA_ATTRIBUTE_TextEntry, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0xb373a862, L"archive", XFA_ATTRIBUTE_Archive, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xb598a1f7, L"uuid", XFA_ATTRIBUTE_Uuid, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_XDP, nullptr}, - {0xb5e49bf2, L"posture", XFA_ATTRIBUTE_Posture, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Normal}, - {0xb6b44172, L"after", XFA_ATTRIBUTE_After, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0xb716467b, L"orphans", XFA_ATTRIBUTE_Orphans, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0xbc0c4695, L"qualifiedName", XFA_ATTRIBUTE_QualifiedName, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_UNKNOWN, nullptr}, - {0xbc254332, L"usehref", XFA_ATTRIBUTE_Usehref, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Template | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_Form, - nullptr}, - {0xbc8fa350, L"locale", XFA_ATTRIBUTE_Locale, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xbd6e1d88, L"weight", XFA_ATTRIBUTE_Weight, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Normal}, - {0xbd96a0e9, L"underlinePeriod", XFA_ATTRIBUTE_UnderlinePeriod, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_All}, - {0xbde9abda, L"data", XFA_ATTRIBUTE_Data, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Link}, - {0xbe52dfbf, L"desc", XFA_ATTRIBUTE_Desc, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet, nullptr}, - {0xbe9ba472, L"numbered", XFA_ATTRIBUTE_Numbered, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)1}, - {0xc035c6b1, L"dataColumnCount", XFA_ATTRIBUTE_DataColumnCount, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xc0ec9fa4, L"overline", XFA_ATTRIBUTE_Overline, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0xc2ba0923, L"urlPolicy", XFA_ATTRIBUTE_UrlPolicy, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xc2bd40fd, L"anchorType", XFA_ATTRIBUTE_AnchorType, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_TopLeft}, - {0xc39a88bd, L"labelRef", XFA_ATTRIBUTE_LabelRef, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xc3c1442f, L"bookendLeader", XFA_ATTRIBUTE_BookendLeader, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xc4547a08, L"maxLength", XFA_ATTRIBUTE_MaxLength, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)-1}, - {0xc4fed09b, L"accessKey", XFA_ATTRIBUTE_AccessKey, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xc5762157, L"cursorLocation", XFA_ATTRIBUTE_CursorLocation, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_SourceSet, - (void*)XFA_ATTRIBUTEENUM_Client}, - {0xc860f30a, L"delayedOpen", XFA_ATTRIBUTE_DelayedOpen, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_SourceSet, nullptr}, - {0xc8da4da7, L"target", XFA_ATTRIBUTE_Target, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xca5dc27c, L"dataEncipherment", XFA_ATTRIBUTE_DataEncipherment, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xcb150479, L"afterTarget", XFA_ATTRIBUTE_AfterTarget, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xcbcaf66d, L"leader", XFA_ATTRIBUTE_Leader, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xcca7897e, L"picker", XFA_ATTRIBUTE_Picker, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Host}, - {0xcd7f7b54, L"from", XFA_ATTRIBUTE_From, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Config, nullptr}, - {0xcea5e62c, L"baseProfile", XFA_ATTRIBUTE_BaseProfile, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Full}, - {0xd171b240, L"aspect", XFA_ATTRIBUTE_Aspect, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)XFA_ATTRIBUTEENUM_Fit}, - {0xd3c84d25, L"rowColumnRatio", XFA_ATTRIBUTE_RowColumnRatio, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xd4b01921, L"lineHeight", XFA_ATTRIBUTE_LineHeight, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 1)}, - {0xd4cc53f8, L"highlight", XFA_ATTRIBUTE_Highlight, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Inverted}, - {0xd50f903a, L"valueRef", XFA_ATTRIBUTE_ValueRef, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xd52482e0, L"maxEntries", XFA_ATTRIBUTE_MaxEntries, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Config, (void*)5}, - {0xd57c513c, L"dataLength", XFA_ATTRIBUTE_DataLength, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xd6128d8d, L"activity", XFA_ATTRIBUTE_Activity, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Click}, - {0xd6a39990, L"input", XFA_ATTRIBUTE_Input, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_ConnectionSet, nullptr}, - {0xd6e27f1d, L"value", XFA_ATTRIBUTE_Value, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_SourceSet | XFA_XDPPACKET_Config | XFA_XDPPACKET_LocaleSet | - XFA_XDPPACKET_Template | XFA_XDPPACKET_Datasets | - XFA_XDPPACKET_ConnectionSet | XFA_XDPPACKET_Form, - nullptr}, - {0xd70798c2, L"blankOrNotBlank", XFA_ATTRIBUTE_BlankOrNotBlank, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Any}, - {0xd861f8af, L"addRevocationInfo", XFA_ATTRIBUTE_AddRevocationInfo, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xd8f982bf, L"genericFamily", XFA_ATTRIBUTE_GenericFamily, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Config, - (void*)XFA_ATTRIBUTEENUM_Serif}, - {0xd996fa9b, L"hand", XFA_ATTRIBUTE_Hand, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Even}, - {0xdb55fec5, L"href", XFA_ATTRIBUTE_Href, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xdc75676c, L"textEncoding", XFA_ATTRIBUTE_TextEncoding, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xde7f92ba, L"leadDigits", XFA_ATTRIBUTE_LeadDigits, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)-1}, - {0xe11a2cbc, L"permissions", XFA_ATTRIBUTE_Permissions, - XFA_ATTRIBUTETYPE_Integer, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)2}, - {0xe18b5659, L"spaceAbove", XFA_ATTRIBUTE_SpaceAbove, - XFA_ATTRIBUTETYPE_Measure, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0xe1a26b56, L"codeBase", XFA_ATTRIBUTE_CodeBase, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xe349d044, L"stock", XFA_ATTRIBUTE_Stock, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xe372ae97, L"isNull", XFA_ATTRIBUTE_IsNull, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Datasets, (void*)0}, - {0xe4c3a5e5, L"restoreState", XFA_ATTRIBUTE_RestoreState, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Manual}, - {0xe5c96d6a, L"excludeAllCaps", XFA_ATTRIBUTE_ExcludeAllCaps, - XFA_ATTRIBUTETYPE_Boolean, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)0}, - {0xe64b1129, L"formatTest", XFA_ATTRIBUTE_FormatTest, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Warning}, - {0xe6f99487, L"hScrollPolicy", XFA_ATTRIBUTE_HScrollPolicy, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0xe8dddf50, L"join", XFA_ATTRIBUTE_Join, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Square}, - {0xe8f118a8, L"keyCertSign", XFA_ATTRIBUTE_KeyCertSign, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xe948b9a8, L"radius", XFA_ATTRIBUTE_Radius, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0xe996b2fe, L"sourceAbove", XFA_ATTRIBUTE_SourceAbove, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Config, - (void*)XFA_ATTRIBUTEENUM_Warn}, - {0xea7090a0, L"override", XFA_ATTRIBUTE_Override, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xeb091003, L"classId", XFA_ATTRIBUTE_ClassId, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xeb511b54, L"disable", XFA_ATTRIBUTE_Disable, XFA_ATTRIBUTETYPE_Boolean, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, (void*)0}, - {0xeda9017a, L"scope", XFA_ATTRIBUTE_Scope, XFA_ATTRIBUTETYPE_NOTSURE, - XFA_XDPPACKET_Config | XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xf197844d, L"match", XFA_ATTRIBUTE_Match, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Once}, - {0xf2009339, L"placement", XFA_ATTRIBUTE_Placement, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Left}, - {0xf4ffce73, L"before", XFA_ATTRIBUTE_Before, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_Auto}, - {0xf531b059, L"writingScript", XFA_ATTRIBUTE_WritingScript, - XFA_ATTRIBUTETYPE_Enum, XFA_XDPPACKET_Config, - (void*)XFA_ATTRIBUTEENUM_Asterisk}, - {0xf575ca75, L"endChar", XFA_ATTRIBUTE_EndChar, XFA_ATTRIBUTETYPE_Cdata, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, nullptr}, - {0xf6b47749, L"lock", XFA_ATTRIBUTE_Lock, XFA_ATTRIBUTETYPE_Integer, - XFA_XDPPACKET_Config, (void*)0}, - {0xf6b4afb0, L"long", XFA_ATTRIBUTE_Long, XFA_ATTRIBUTETYPE_Measure, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)(g_XFAMeasurementData + 0)}, - {0xf6b59543, L"intact", XFA_ATTRIBUTE_Intact, XFA_ATTRIBUTETYPE_Enum, - XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - (void*)XFA_ATTRIBUTEENUM_None}, - {0xf889e747, L"xdpContent", XFA_ATTRIBUTE_XdpContent, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, - {0xfea53ec6, L"decipherOnly", XFA_ATTRIBUTE_DecipherOnly, - XFA_ATTRIBUTETYPE_Cdata, XFA_XDPPACKET_Template | XFA_XDPPACKET_Form, - nullptr}, -}; -const int32_t g_iXFAAttributeCount = - sizeof(g_XFAAttributeData) / sizeof(XFA_ATTRIBUTEINFO); - -const XFA_NOTSUREATTRIBUTE g_XFANotsureAttributes[] = { - {XFA_Element::SubformSet, XFA_ATTRIBUTE_Relation, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Ordered}, - {XFA_Element::NumberPattern, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Numeric}, - {XFA_Element::KeyUsage, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::LabelPrinter, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Zpl}, - {XFA_Element::CalendarSymbols, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Gregorian}, - {XFA_Element::Barcode, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Cdata, - nullptr}, - {XFA_Element::Barcode, XFA_ATTRIBUTE_Checksum, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_None}, - {XFA_Element::TimePattern, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Med}, - {XFA_Element::BatchOutput, XFA_ATTRIBUTE_Format, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_None}, - {XFA_Element::SubjectDNs, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Issuers, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::EncryptionMethods, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Pattern, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_CrossHatch}, - {XFA_Element::Compress, XFA_ATTRIBUTE_Scope, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_ImageOnly}, - {XFA_Element::Image, XFA_ATTRIBUTE_TransferEncoding, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Base64}, - {XFA_Element::TimeStamp, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Subform, XFA_ATTRIBUTE_Scope, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Name}, - {XFA_Element::Handler, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Record, XFA_ATTRIBUTE_Max, XFA_ATTRIBUTETYPE_Integer, - (void*)0}, - {XFA_Element::Command, XFA_ATTRIBUTE_Timeout, XFA_ATTRIBUTETYPE_Integer, - (void*)30}, - {XFA_Element::DigestMethods, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::PageSet, XFA_ATTRIBUTE_Relation, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_OrderedOccurrence}, - {XFA_Element::Equate, XFA_ATTRIBUTE_From, XFA_ATTRIBUTETYPE_Cdata, nullptr}, - {XFA_Element::Equate, XFA_ATTRIBUTE_To, XFA_ATTRIBUTETYPE_Cdata, nullptr}, - {XFA_Element::Traverse, XFA_ATTRIBUTE_Operation, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Next}, - {XFA_Element::Encodings, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Signing, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Oids, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Signature, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_PDF1_3}, - {XFA_Element::ExData, XFA_ATTRIBUTE_TransferEncoding, - XFA_ATTRIBUTETYPE_Enum, (void*)XFA_ATTRIBUTEENUM_None}, - {XFA_Element::Linear, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_ToRight}, - {XFA_Element::CurrencySymbol, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Symbol}, - {XFA_Element::EquateRange, XFA_ATTRIBUTE_From, XFA_ATTRIBUTETYPE_Cdata, - nullptr}, - {XFA_Element::EquateRange, XFA_ATTRIBUTE_To, XFA_ATTRIBUTETYPE_Cdata, - nullptr}, - {XFA_Element::SignData, XFA_ATTRIBUTE_Operation, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Sign}, - {XFA_Element::DatePattern, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Med}, - {XFA_Element::Bind, XFA_ATTRIBUTE_TransferEncoding, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_None}, - {XFA_Element::Reasons, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::AppearanceFilter, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Form, XFA_ATTRIBUTE_Checksum, XFA_ATTRIBUTETYPE_Cdata, - nullptr}, - {XFA_Element::Value, XFA_ATTRIBUTE_Override, XFA_ATTRIBUTETYPE_Boolean, - (void*)0}, - {XFA_Element::Calculate, XFA_ATTRIBUTE_Override, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Error}, - {XFA_Element::Connect, XFA_ATTRIBUTE_Timeout, XFA_ATTRIBUTETYPE_Integer, - (void*)15}, - {XFA_Element::Submit, XFA_ATTRIBUTE_Format, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Xdp}, - {XFA_Element::Radial, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_ToEdge}, - {XFA_Element::LockDocument, XFA_ATTRIBUTE_Type, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Optional}, - {XFA_Element::Occur, XFA_ATTRIBUTE_Max, XFA_ATTRIBUTETYPE_Integer, - (void*)1}, - {XFA_Element::NumberSymbol, XFA_ATTRIBUTE_Name, XFA_ATTRIBUTETYPE_Enum, - (void*)XFA_ATTRIBUTEENUM_Decimal}, -}; -const int32_t g_iXFANotsureCount = - sizeof(g_XFANotsureAttributes) / sizeof(XFA_NOTSUREATTRIBUTE); diff --git a/xfa/fxfa/parser/xfa_basic_data_element_attributes.cpp b/xfa/fxfa/parser/xfa_basic_data_element_attributes.cpp deleted file mode 100644 index 640af338e6f9fd50ec831902f54e4596dcf78efd..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_basic_data_element_attributes.cpp +++ /dev/null @@ -1,1188 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_basic_data.h" - -#include "xfa/fxfa/fxfa_basic.h" - -const XFA_ELEMENTHIERARCHY g_XFAElementAttributeIndex[] = { - {0, 3}, {3, 2}, {5, 3}, {8, 10}, {18, 2}, {20, 6}, {26, 2}, - {28, 1}, {29, 13}, {42, 2}, {44, 1}, {45, 2}, {47, 2}, {49, 7}, - {56, 0}, {56, 4}, {60, 2}, {62, 7}, {69, 0}, {69, 0}, {69, 2}, - {71, 2}, {73, 8}, {81, 5}, {86, 8}, {94, 4}, {98, 3}, {101, 3}, - {104, 3}, {107, 6}, {113, 2}, {115, 2}, {117, 2}, {119, 2}, {121, 3}, - {124, 2}, {126, 7}, {133, 13}, {146, 2}, {148, 6}, {154, 2}, {156, 3}, - {159, 1}, {160, 17}, {177, 2}, {179, 2}, {181, 6}, {187, 2}, {189, 2}, - {191, 3}, {194, 7}, {201, 2}, {203, 3}, {206, 0}, {206, 21}, {227, 1}, - {228, 3}, {231, 2}, {233, 0}, {233, 2}, {235, 2}, {237, 6}, {243, 0}, - {243, 4}, {247, 4}, {251, 0}, {251, 2}, {253, 2}, {255, 0}, {255, 0}, - {255, 2}, {257, 2}, {259, 4}, {263, 3}, {266, 7}, {273, 10}, {283, 9}, - {292, 6}, {298, 4}, {302, 2}, {304, 2}, {306, 6}, {312, 4}, {316, 3}, - {319, 2}, {321, 2}, {323, 4}, {327, 4}, {331, 4}, {335, 4}, {339, 2}, - {341, 2}, {343, 2}, {345, 22}, {367, 3}, {370, 2}, {372, 2}, {374, 2}, - {376, 9}, {385, 0}, {385, 4}, {389, 3}, {392, 0}, {392, 2}, {394, 7}, - {401, 4}, {405, 2}, {407, 4}, {411, 0}, {411, 21}, {432, 4}, {436, 3}, - {439, 4}, {443, 6}, {449, 2}, {451, 5}, {456, 2}, {458, 8}, {466, 1}, - {467, 2}, {469, 2}, {471, 5}, {476, 0}, {476, 2}, {478, 2}, {480, 6}, - {486, 26}, {512, 4}, {516, 2}, {518, 2}, {520, 4}, {524, 0}, {524, 2}, - {526, 2}, {528, 2}, {530, 2}, {532, 5}, {537, 2}, {539, 3}, {542, 2}, - {544, 4}, {548, 5}, {553, 2}, {555, 0}, {555, 2}, {557, 4}, {561, 5}, - {566, 3}, {569, 2}, {571, 3}, {574, 0}, {574, 2}, {576, 9}, {585, 2}, - {587, 5}, {592, 6}, {598, 5}, {603, 4}, {607, 4}, {611, 8}, {619, 4}, - {623, 0}, {623, 7}, {630, 4}, {634, 4}, {638, 5}, {643, 2}, {645, 2}, - {647, 4}, {651, 4}, {655, 2}, {657, 2}, {659, 1}, {660, 2}, {662, 5}, - {667, 4}, {671, 3}, {674, 2}, {676, 2}, {678, 4}, {682, 0}, {682, 9}, - {691, 2}, {693, 2}, {695, 5}, {700, 4}, {704, 3}, {707, 2}, {709, 10}, - {719, 2}, {721, 4}, {725, 4}, {729, 2}, {731, 6}, {737, 2}, {739, 2}, - {741, 9}, {750, 1}, {751, 4}, {755, 3}, {758, 5}, {763, 6}, {769, 4}, - {773, 1}, {774, 4}, {778, 0}, {778, 3}, {781, 1}, {782, 5}, {787, 10}, - {797, 7}, {804, 3}, {807, 2}, {809, 5}, {814, 2}, {816, 0}, {816, 2}, - {818, 2}, {820, 2}, {822, 6}, {828, 2}, {830, 1}, {831, 2}, {833, 2}, - {835, 8}, {843, 2}, {845, 4}, {849, 4}, {853, 4}, {857, 2}, {859, 2}, - {861, 2}, {863, 3}, {866, 2}, {868, 2}, {870, 4}, {874, 3}, {877, 5}, - {882, 20}, {902, 2}, {904, 0}, {904, 2}, {906, 6}, {912, 1}, {913, 2}, - {915, 1}, {916, 2}, {918, 4}, {922, 2}, {924, 2}, {926, 4}, {930, 4}, - {934, 20}, {954, 1}, {955, 2}, {957, 4}, {961, 4}, {965, 2}, {967, 2}, - {969, 4}, {973, 2}, {975, 0}, {975, 2}, {977, 5}, {982, 5}, {987, 8}, - {995, 2}, {997, 2}, {999, 4}, {1003, 4}, {1007, 2}, {1009, 4}, {1013, 0}, - {1013, 1}, {1014, 2}, {1016, 9}, {1025, 2}, {1027, 0}, {1027, 8}, {1035, 2}, - {1037, 2}, {1039, 0}, {1039, 4}, {1043, 2}, {1045, 0}, {1045, 2}, {1047, 3}, - {1050, 2}, {1052, 5}, {1057, 2}, {1059, 2}, {1061, 4}, {1065, 3}, {1068, 0}, - {1068, 4}, {1072, 2}, {1074, 2}, {1076, 3}, {1079, 4}, {1083, 8}, {1091, 5}, - {1096, 0}, {1096, 4}, {1100, 6}, {1106, 2}, {1108, 1}, {1109, 2}, {1111, 2}, - {1113, 2}, {1115, 1}, {1116, 2}, {1118, 7}, -}; -static_assert(FX_ArraySize(g_XFAElementAttributeIndex) == - (static_cast<int32_t>(XFA_Element::Items) + 1), - "gXFAElementAttributeIndex size does not match XFA_Element"); - -const uint8_t g_XFAElementAttributeData[] = { - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Max, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_EofAction, - XFA_ATTRIBUTE_CursorType, - XFA_ATTRIBUTE_LockType, - XFA_ATTRIBUTE_BofAction, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_CursorLocation, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Relation, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_BeforeTarget, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_OverflowTarget, - XFA_ATTRIBUTE_OverflowLeader, - XFA_ATTRIBUTE_OverflowTrailer, - XFA_ATTRIBUTE_StartNew, - XFA_ATTRIBUTE_BookendTrailer, - XFA_ATTRIBUTE_After, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_BookendLeader, - XFA_ATTRIBUTE_AfterTarget, - XFA_ATTRIBUTE_Before, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_AllowNeutral, - XFA_ATTRIBUTE_Mark, - XFA_ATTRIBUTE_Shape, - XFA_ATTRIBUTE_Size, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_StartAngle, - XFA_ATTRIBUTE_SweepAngle, - XFA_ATTRIBUTE_Circular, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Hand, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Bind, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_From, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_SignatureType, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Permissions, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_StartNew, - XFA_ATTRIBUTE_Trailer, - XFA_ATTRIBUTE_TargetType, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_Leader, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_TimeStamp, - XFA_ATTRIBUTE_Uuid, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_LeftInset, - XFA_ATTRIBUTE_BottomInset, - XFA_ATTRIBUTE_TopInset, - XFA_ATTRIBUTE_RightInset, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_NonRepudiation, - XFA_ATTRIBUTE_EncipherOnly, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_DigitalSignature, - XFA_ATTRIBUTE_CrlSign, - XFA_ATTRIBUTE_KeyAgreement, - XFA_ATTRIBUTE_KeyEncipherment, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_DataEncipherment, - XFA_ATTRIBUTE_KeyCertSign, - XFA_ATTRIBUTE_DecipherOnly, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Open, - XFA_ATTRIBUTE_CommitOn, - XFA_ATTRIBUTE_TextEntry, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_HAlign, - XFA_ATTRIBUTE_TextIndent, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Widows, - XFA_ATTRIBUTE_MarginRight, - XFA_ATTRIBUTE_MarginLeft, - XFA_ATTRIBUTE_RadixOffset, - XFA_ATTRIBUTE_Preserve, - XFA_ATTRIBUTE_SpaceBelow, - XFA_ATTRIBUTE_VAlign, - XFA_ATTRIBUTE_TabDefault, - XFA_ATTRIBUTE_TabStops, - XFA_ATTRIBUTE_Orphans, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_LineHeight, - XFA_ATTRIBUTE_SpaceAbove, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Version, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_AddRevocationInfo, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Listen, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Activity, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_DataRowCount, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_DataPrep, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_TextLocation, - XFA_ATTRIBUTE_ModuleWidth, - XFA_ATTRIBUTE_PrintCheckDigit, - XFA_ATTRIBUTE_ModuleHeight, - XFA_ATTRIBUTE_StartChar, - XFA_ATTRIBUTE_Truncate, - XFA_ATTRIBUTE_WideNarrowRatio, - XFA_ATTRIBUTE_ErrorCorrectionLevel, - XFA_ATTRIBUTE_UpsMode, - XFA_ATTRIBUTE_Checksum, - XFA_ATTRIBUTE_CharEncoding, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_DataColumnCount, - XFA_ATTRIBUTE_RowColumnRatio, - XFA_ATTRIBUTE_DataLength, - XFA_ATTRIBUTE_EndChar, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Format, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Output, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Input, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_DataDescription, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Highlight, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Break, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Hand, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Level, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_ColSpan, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_WordCharacterCount, - XFA_ATTRIBUTE_Hyphenate, - XFA_ATTRIBUTE_ExcludeInitialCap, - XFA_ATTRIBUTE_PushCharacterCount, - XFA_ATTRIBUTE_RemainCharacterCount, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_ExcludeAllCaps, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Rid, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_MaxChars, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Url, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_CredentialServerPolicy, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_UrlPolicy, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Connection, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_NumberOfCells, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_H, - XFA_ATTRIBUTE_W, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_HAlign, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Access, - XFA_ATTRIBUTE_Rotate, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_VAlign, - XFA_ATTRIBUTE_MaxH, - XFA_ATTRIBUTE_MaxW, - XFA_ATTRIBUTE_MinH, - XFA_ATTRIBUTE_MinW, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_ColSpan, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Locale, - XFA_ATTRIBUTE_AnchorType, - XFA_ATTRIBUTE_AccessKey, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_H, - XFA_ATTRIBUTE_W, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Cap, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Stroke, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_Thickness, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Rate, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_SourceBelow, - XFA_ATTRIBUTE_OutputBelow, - XFA_ATTRIBUTE_SourceAbove, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_H, - XFA_ATTRIBUTE_W, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_HAlign, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Access, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_VAlign, - XFA_ATTRIBUTE_MaxH, - XFA_ATTRIBUTE_MaxW, - XFA_ATTRIBUTE_MinH, - XFA_ATTRIBUTE_MinW, - XFA_ATTRIBUTE_Layout, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_ColSpan, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_AnchorType, - XFA_ATTRIBUTE_AccessKey, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Rid, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Scope, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Connection, - XFA_ATTRIBUTE_RunAt, - XFA_ATTRIBUTE_ExecuteType, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Picker, - XFA_ATTRIBUTE_HScrollPolicy, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTE_TransferEncoding, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Aspect, - XFA_ATTRIBUTE_Href, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Server, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_FracDigits, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_LeadDigits, - XFA_ATTRIBUTE_H, - XFA_ATTRIBUTE_W, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_HAlign, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_AllowMacro, - XFA_ATTRIBUTE_ColumnWidths, - XFA_ATTRIBUTE_Access, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_VAlign, - XFA_ATTRIBUTE_MaxH, - XFA_ATTRIBUTE_MaxW, - XFA_ATTRIBUTE_MinH, - XFA_ATTRIBUTE_MinW, - XFA_ATTRIBUTE_Layout, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_MergeMode, - XFA_ATTRIBUTE_ColSpan, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Locale, - XFA_ATTRIBUTE_AnchorType, - XFA_ATTRIBUTE_RestoreState, - XFA_ATTRIBUTE_Scope, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Timeout, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Mode, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Role, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Stroke, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_Inverted, - XFA_ATTRIBUTE_Thickness, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Join, - XFA_ATTRIBUTE_Radius, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_CSpace, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Next, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Previous, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Intact, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_CommandType, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Data, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_ScriptTest, - XFA_ATTRIBUTE_NullTest, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_FormatTest, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Relation, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_DuplexImposition, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_To, - XFA_ATTRIBUTE_Force, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_From, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_DataDescription, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Operation, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_BaseProfile, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTE_RunAt, - XFA_ATTRIBUTE_Binding, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_PasswordChar, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_HScrollPolicy, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_HScrollPolicy, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_PagePosition, - XFA_ATTRIBUTE_OddOrEven, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_InitialNumber, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Numbered, - XFA_ATTRIBUTE_BlankOrNotBlank, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Reserve, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Placement, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Rid, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTE_TransferEncoding, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_MaxLength, - XFA_ATTRIBUTE_Href, - XFA_ATTRIBUTE_Abbr, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_WritingScript, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Action, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Trailer, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_Leader, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_To, - XFA_ATTRIBUTE_UnicodeRange, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_From, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_TrayOut, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Orientation, - XFA_ATTRIBUTE_ImagingBBox, - XFA_ATTRIBUTE_Short, - XFA_ATTRIBUTE_TrayIn, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Stock, - XFA_ATTRIBUTE_Long, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_VScrollPolicy, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_AllowRichText, - XFA_ATTRIBUTE_MultiLine, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_HScrollPolicy, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_MaxEntries, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTE_Contains, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_IsNull, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_DataDescription, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Operation, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_ContentType, - XFA_ATTRIBUTE_TransferEncoding, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Match, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Hand, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_H, - XFA_ATTRIBUTE_W, - XFA_ATTRIBUTE_X, - XFA_ATTRIBUTE_Y, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_HAlign, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Rotate, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_VAlign, - XFA_ATTRIBUTE_MaxH, - XFA_ATTRIBUTE_MaxW, - XFA_ATTRIBUTE_MinH, - XFA_ATTRIBUTE_MinW, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_ColSpan, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Locale, - XFA_ATTRIBUTE_AnchorType, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Rid, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Priority, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Disable, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_LineThrough, - XFA_ATTRIBUTE_Typeface, - XFA_ATTRIBUTE_FontHorizontalScale, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_KerningMode, - XFA_ATTRIBUTE_Underline, - XFA_ATTRIBUTE_BaselineShift, - XFA_ATTRIBUTE_OverlinePeriod, - XFA_ATTRIBUTE_LetterSpacing, - XFA_ATTRIBUTE_LineThroughPeriod, - XFA_ATTRIBUTE_FontVerticalScale, - XFA_ATTRIBUTE_PsName, - XFA_ATTRIBUTE_Size, - XFA_ATTRIBUTE_Posture, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Weight, - XFA_ATTRIBUTE_UnderlinePeriod, - XFA_ATTRIBUTE_Overline, - XFA_ATTRIBUTE_GenericFamily, - XFA_ATTRIBUTE_Checksum, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Relevant, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Override, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Trailer, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Leader, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_CodeType, - XFA_ATTRIBUTE_Archive, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_CodeBase, - XFA_ATTRIBUTE_ClassId, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Connection, - XFA_ATTRIBUTE_LabelRef, - XFA_ATTRIBUTE_ValueRef, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Override, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Value, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Timeout, - XFA_ATTRIBUTE_Connection, - XFA_ATTRIBUTE_Usage, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_DelayedOpen, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Format, - XFA_ATTRIBUTE_EmbedPDF, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_TextEncoding, - XFA_ATTRIBUTE_XdpContent, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Delimiter, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Type, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_StartNew, - XFA_ATTRIBUTE_Trailer, - XFA_ATTRIBUTE_TargetType, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Target, - XFA_ATTRIBUTE_Leader, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Slope, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Hand, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Max, - XFA_ATTRIBUTE_Min, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Initial, - XFA_ATTRIBUTE_Usehref, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Abbr, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Desc, - XFA_ATTRIBUTE_Lock, - XFA_ATTRIBUTE_Id, - XFA_ATTRIBUTE_Name, - XFA_ATTRIBUTE_Ref, - XFA_ATTRIBUTE_Use, - XFA_ATTRIBUTE_Presence, - XFA_ATTRIBUTE_Save, - XFA_ATTRIBUTE_Usehref, -}; diff --git a/xfa/fxfa/parser/xfa_basic_data_element_properties.cpp b/xfa/fxfa/parser/xfa_basic_data_element_properties.cpp deleted file mode 100644 index 1b47b033e8271b6363a9684cd9f6dc1ac617f371..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_basic_data_element_properties.cpp +++ /dev/null @@ -1,487 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_basic_data.h" - -#include "xfa/fxfa/fxfa_basic.h" - -const XFA_ELEMENTHIERARCHY g_XFAElementPropertyIndex[] = { - {0, 8}, {8, 0}, {8, 14}, {22, 0}, {22, 0}, {22, 6}, {28, 0}, - {28, 0}, {28, 1}, {29, 3}, {32, 0}, {32, 0}, {32, 0}, {32, 3}, - {35, 1}, {36, 0}, {36, 0}, {36, 2}, {38, 0}, {38, 0}, {38, 0}, - {38, 4}, {42, 0}, {42, 0}, {42, 1}, {43, 0}, {43, 8}, {51, 19}, - {70, 0}, {70, 0}, {70, 2}, {72, 1}, {73, 0}, {73, 2}, {75, 4}, - {79, 1}, {80, 1}, {81, 0}, {81, 0}, {81, 3}, {84, 0}, {84, 4}, - {88, 4}, {92, 1}, {93, 0}, {93, 4}, {97, 9}, {106, 14}, {120, 0}, - {120, 0}, {120, 5}, {125, 0}, {125, 1}, {126, 0}, {126, 0}, {126, 0}, - {126, 0}, {126, 0}, {126, 1}, {127, 0}, {127, 0}, {127, 0}, {127, 0}, - {127, 0}, {127, 0}, {127, 0}, {127, 6}, {133, 1}, {134, 0}, {134, 1}, - {135, 0}, {135, 0}, {135, 1}, {136, 2}, {138, 5}, {143, 2}, {145, 0}, - {145, 0}, {145, 0}, {145, 0}, {145, 0}, {145, 5}, {150, 0}, {150, 0}, - {150, 0}, {150, 0}, {150, 0}, {150, 0}, {150, 0}, {150, 2}, {152, 0}, - {152, 0}, {152, 0}, {152, 17}, {169, 0}, {169, 1}, {170, 0}, {170, 0}, - {170, 2}, {172, 0}, {172, 0}, {172, 1}, {173, 0}, {173, 0}, {173, 2}, - {175, 2}, {177, 0}, {177, 0}, {177, 0}, {177, 11}, {188, 0}, {188, 0}, - {188, 0}, {188, 0}, {188, 0}, {188, 4}, {192, 3}, {195, 0}, {195, 0}, - {195, 0}, {195, 0}, {195, 0}, {195, 0}, {195, 9}, {204, 0}, {204, 0}, - {204, 17}, {221, 0}, {221, 0}, {221, 0}, {221, 0}, {221, 0}, {221, 0}, - {221, 0}, {221, 0}, {221, 0}, {221, 4}, {225, 0}, {225, 0}, {225, 0}, - {225, 0}, {225, 2}, {227, 3}, {230, 0}, {230, 0}, {230, 2}, {232, 0}, - {232, 1}, {233, 2}, {235, 2}, {237, 0}, {237, 0}, {237, 2}, {239, 0}, - {239, 1}, {240, 1}, {241, 2}, {243, 0}, {243, 3}, {246, 4}, {250, 0}, - {250, 1}, {251, 2}, {253, 0}, {253, 0}, {253, 0}, {253, 0}, {253, 0}, - {253, 0}, {253, 0}, {253, 0}, {253, 0}, {253, 0}, {253, 2}, {255, 2}, - {257, 0}, {257, 6}, {263, 5}, {268, 0}, {268, 0}, {268, 0}, {268, 3}, - {271, 0}, {271, 0}, {271, 3}, {274, 4}, {278, 0}, {278, 0}, {278, 4}, - {282, 0}, {282, 0}, {282, 5}, {287, 0}, {287, 5}, {292, 0}, {292, 0}, - {292, 0}, {292, 1}, {293, 0}, {293, 0}, {293, 1}, {294, 0}, {294, 2}, - {296, 0}, {296, 0}, {296, 0}, {296, 0}, {296, 1}, {297, 0}, {297, 0}, - {297, 4}, {301, 0}, {301, 0}, {301, 0}, {301, 0}, {301, 0}, {301, 0}, - {301, 1}, {302, 0}, {302, 2}, {304, 0}, {304, 0}, {304, 0}, {304, 0}, - {304, 1}, {305, 4}, {309, 0}, {309, 3}, {312, 0}, {312, 0}, {312, 1}, - {313, 0}, {313, 8}, {321, 0}, {321, 10}, {331, 0}, {331, 10}, {341, 1}, - {342, 12}, {354, 3}, {357, 1}, {358, 0}, {358, 0}, {358, 0}, {358, 8}, - {366, 0}, {366, 0}, {366, 0}, {366, 0}, {366, 0}, {366, 0}, {366, 7}, - {373, 2}, {375, 0}, {375, 1}, {376, 0}, {376, 0}, {376, 0}, {376, 0}, - {376, 0}, {376, 0}, {376, 0}, {376, 0}, {376, 13}, {389, 0}, {389, 1}, - {390, 1}, {391, 0}, {391, 0}, {391, 3}, {394, 0}, {394, 0}, {394, 0}, - {394, 0}, {394, 0}, {394, 4}, {398, 9}, {407, 0}, {407, 1}, {408, 0}, - {408, 0}, {408, 0}, {408, 0}, {408, 0}, {408, 1}, {409, 0}, {409, 2}, - {411, 0}, {411, 0}, {411, 0}, {411, 0}, {411, 2}, {413, 0}, {413, 1}, - {414, 0}, {414, 0}, {414, 0}, {414, 7}, {421, 0}, {421, 1}, {422, 1}, - {423, 0}, {423, 1}, {424, 1}, {425, 0}, {425, 1}, {426, 0}, {426, 0}, - {426, 0}, {426, 0}, {426, 0}, {426, 0}, -}; - -const XFA_PROPERTY g_XFAElementPropertyData[] = { - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Jog, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::BatchOutput, 1, 0}, - {XFA_Element::OutputBin, 1, 0}, - {XFA_Element::Compress, 1, 0}, - {XFA_Element::Staple, 1, 0}, - {XFA_Element::MediumInfo, 1, 0}, - {XFA_Element::CheckButton, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::ChoiceList, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::DefaultUi, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Barcode, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Button, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::DateTimeEdit, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Picture, 1, 0}, - {XFA_Element::ImageEdit, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::PasswordEdit, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::NumericEdit, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Signature, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::TextEdit, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::ExObject, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Break, 1, 0}, - {XFA_Element::Overflow, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Bookend, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Occur, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::SubsetBelow, 1, 0}, - {XFA_Element::Map, 1, 0}, - {XFA_Element::Embed, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::DatePattern, 4, 0}, - {XFA_Element::Edge, 1, 0}, - {XFA_Element::Fill, 1, 0}, - {XFA_Element::To, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Mode, 1, 0}, - {XFA_Element::Threshold, 1, 0}, - {XFA_Element::Script, 1, 0}, - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Jog, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::BatchOutput, 1, 0}, - {XFA_Element::PageOffset, 1, 0}, - {XFA_Element::OutputBin, 1, 0}, - {XFA_Element::Staple, 1, 0}, - {XFA_Element::MediumInfo, 1, 0}, - {XFA_Element::AdobeExtensionLevel, 1, 0}, - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::Pdfa, 1, 0}, - {XFA_Element::BatchOutput, 1, 0}, - {XFA_Element::ViewerPreferences, 1, 0}, - {XFA_Element::ScriptModel, 1, 0}, - {XFA_Element::Version, 1, 0}, - {XFA_Element::SubmitFormat, 1, 0}, - {XFA_Element::SilentPrint, 1, 0}, - {XFA_Element::Producer, 1, 0}, - {XFA_Element::Compression, 1, 0}, - {XFA_Element::Interactive, 1, 0}, - {XFA_Element::Encryption, 1, 0}, - {XFA_Element::RenderPolicy, 1, 0}, - {XFA_Element::OpenAction, 1, 0}, - {XFA_Element::Creator, 1, 0}, - {XFA_Element::Linearized, 1, 0}, - {XFA_Element::Tagged, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Xsl, 1, 0}, - {XFA_Element::Packets, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Debug, 1, 0}, - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::BatchOutput, 1, 0}, - {XFA_Element::FlipLabel, 1, 0}, - {XFA_Element::TemplateCache, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::BatchOutput, 1, 0}, - {XFA_Element::FlipLabel, 1, 0}, - {XFA_Element::EraNames, 1, 0}, - {XFA_Element::DayNames, 2, 0}, - {XFA_Element::MeridiemNames, 1, 0}, - {XFA_Element::MonthNames, 2, 0}, - {XFA_Element::Hyphenation, 1, 0}, - {XFA_Element::Amd, 1, 0}, - {XFA_Element::Part, 1, 0}, - {XFA_Element::IncludeXDPContent, 1, 0}, - {XFA_Element::Conformance, 1, 0}, - {XFA_Element::Mdp, 1, 0}, - {XFA_Element::Certificates, 1, 0}, - {XFA_Element::TimeStamp, 1, 0}, - {XFA_Element::Handler, 1, 0}, - {XFA_Element::DigestMethods, 1, 0}, - {XFA_Element::Encodings, 1, 0}, - {XFA_Element::Reasons, 1, 0}, - {XFA_Element::AppearanceFilter, 1, 0}, - {XFA_Element::LockDocument, 1, 0}, - {XFA_Element::Xdp, 1, 0}, - {XFA_Element::Cache, 1, 0}, - {XFA_Element::Pagination, 1, 0}, - {XFA_Element::Overprint, 1, 0}, - {XFA_Element::BehaviorOverride, 1, 0}, - {XFA_Element::Copies, 1, 0}, - {XFA_Element::Output, 1, 0}, - {XFA_Element::Validate, 1, 0}, - {XFA_Element::Layout, 1, 0}, - {XFA_Element::Script, 1, 0}, - {XFA_Element::Common, 1, 0}, - {XFA_Element::PaginationOverride, 1, 0}, - {XFA_Element::Destination, 1, 0}, - {XFA_Element::IncrementalMerge, 1, 0}, - {XFA_Element::Execute, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Script, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::SignData, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Submit, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::CurrencySymbol, 3, 0}, - {XFA_Element::Operation, 1, 0}, - {XFA_Element::WsdlAddress, 1, 0}, - {XFA_Element::SoapAddress, 1, 0}, - {XFA_Element::SoapAction, 1, 0}, - {XFA_Element::EffectiveOutputPolicy, 1, 0}, - {XFA_Element::EffectiveInputPolicy, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Era, 2, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Picture, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Edge, 4, 0}, - {XFA_Element::Corner, 4, 0}, - {XFA_Element::Fill, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::KeyUsage, 1, 0}, - {XFA_Element::SubjectDNs, 1, 0}, - {XFA_Element::Issuers, 1, 0}, - {XFA_Element::Signing, 1, 0}, - {XFA_Element::Oids, 1, 0}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Ui, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Para, 1, 0}, - {XFA_Element::Format, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Assist, 1, 0}, - {XFA_Element::Traversal, 1, 0}, - {XFA_Element::Keep, 1, 0}, - {XFA_Element::Validate, 1, 0}, - {XFA_Element::Caption, 1, 0}, - {XFA_Element::Bind, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Font, 1, 0}, - {XFA_Element::Value, 1, 0}, - {XFA_Element::Calculate, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Items, 2, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Para, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Assist, 1, 0}, - {XFA_Element::Traversal, 1, 0}, - {XFA_Element::Validate, 1, 0}, - {XFA_Element::Caption, 1, 0}, - {XFA_Element::Bind, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Calculate, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Comb, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Present, 1, 0}, - {XFA_Element::Acrobat, 1, 0}, - {XFA_Element::Trace, 1, 0}, - {XFA_Element::PrintScaling, 1, 0}, - {XFA_Element::Enforce, 1, 0}, - {XFA_Element::NumberOfCopies, 1, 0}, - {XFA_Element::PageRange, 1, 0}, - {XFA_Element::AddViewerPreferences, 1, 0}, - {XFA_Element::ADBE_JSConsole, 1, 0}, - {XFA_Element::DuplexOption, 1, 0}, - {XFA_Element::ADBE_JSDebugger, 1, 0}, - {XFA_Element::PickTrayByPDFSize, 1, 0}, - {XFA_Element::Break, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Para, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Assist, 1, 0}, - {XFA_Element::Traversal, 1, 0}, - {XFA_Element::Keep, 1, 0}, - {XFA_Element::Validate, 1, 0}, - {XFA_Element::PageSet, 1, 0}, - {XFA_Element::Overflow, 1, 0}, - {XFA_Element::Bind, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Bookend, 1, 0}, - {XFA_Element::Calculate, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Variables, 1, 0}, - {XFA_Element::Occur, 1, 0}, - {XFA_Element::Query, 1, 0}, - {XFA_Element::Insert, 1, 0}, - {XFA_Element::Update, 1, 0}, - {XFA_Element::Delete, 1, 0}, - {XFA_Element::MsgId, 1, 0}, - {XFA_Element::Severity, 1, 0}, - {XFA_Element::To, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Type, 1, 0}, - {XFA_Element::ToolTip, 1, 0}, - {XFA_Element::Speak, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::AddSilentPrint, 1, 0}, - {XFA_Element::PrinterName, 1, 0}, - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::RecordSet, 1, 0}, - {XFA_Element::Select, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Message, 1, 0}, - {XFA_Element::Picture, 1, 0}, - {XFA_Element::Script, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::NumberPattern, 4, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Occur, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::RootElement, 1, 0}, - {XFA_Element::Script, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Xsl, 1, 0}, - {XFA_Element::StartPage, 1, 0}, - {XFA_Element::Relevant, 1, 0}, - {XFA_Element::Base, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::AutoSave, 1, 0}, - {XFA_Element::Validate, 1, 0}, - {XFA_Element::ValidateApprovalSignatures, 1, 0}, - {XFA_Element::Acrobat7, 1, 0}, - {XFA_Element::Common, 1, 0}, - {XFA_Element::Exclude, 1, 0}, - {XFA_Element::CurrentPage, 1, 0}, - {XFA_Element::RunScripts, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Comb, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Medium, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Occur, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Filter, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Manifest, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Para, 1, 0}, - {XFA_Element::Font, 1, 0}, - {XFA_Element::Value, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Day, 7, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Occur, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Comb, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Filter, 1, 0}, - {XFA_Element::Manifest, 1, 0}, - {XFA_Element::Picture, 1, 0}, - {XFA_Element::Level, 1, 0}, - {XFA_Element::Type, 1, 0}, - {XFA_Element::CompressObjectStream, 1, 0}, - {XFA_Element::CompressLogicalStructure, 1, 0}, - {XFA_Element::Edge, 4, 0}, - {XFA_Element::Corner, 4, 0}, - {XFA_Element::Fill, 1, 0}, - {XFA_Element::DynamicRender, 1, 0}, - {XFA_Element::DatePatterns, 1, 0}, - {XFA_Element::CalendarSymbols, 1, 0}, - {XFA_Element::CurrencySymbols, 1, 0}, - {XFA_Element::Typefaces, 1, 0}, - {XFA_Element::DateTimeSymbols, 1, 0}, - {XFA_Element::NumberPatterns, 1, 0}, - {XFA_Element::NumberSymbols, 1, 0}, - {XFA_Element::TimePatterns, 1, 0}, - {XFA_Element::Uri, 1, 0}, - {XFA_Element::Xsl, 1, 0}, - {XFA_Element::StartNode, 1, 0}, - {XFA_Element::OutputXSL, 1, 0}, - {XFA_Element::AdjustData, 1, 0}, - {XFA_Element::Attributes, 1, 0}, - {XFA_Element::Window, 1, 0}, - {XFA_Element::Record, 1, 0}, - {XFA_Element::Range, 1, 0}, - {XFA_Element::IncrementalLoad, 1, 0}, - {XFA_Element::Text, 1, 0}, - {XFA_Element::Time, 1, 0}, - {XFA_Element::DateTime, 1, 0}, - {XFA_Element::Image, 1, 0}, - {XFA_Element::Decimal, 1, 0}, - {XFA_Element::Boolean, 1, 0}, - {XFA_Element::Integer, 1, 0}, - {XFA_Element::ExData, 1, 0}, - {XFA_Element::Date, 1, 0}, - {XFA_Element::Float, 1, 0}, - {XFA_Element::Certificate, 1, 0}, - {XFA_Element::Ui, 1, 0}, - {XFA_Element::Margin, 1, 0}, - {XFA_Element::Para, 1, 0}, - {XFA_Element::Border, 1, 0}, - {XFA_Element::Assist, 1, 0}, - {XFA_Element::Traversal, 1, 0}, - {XFA_Element::Keep, 1, 0}, - {XFA_Element::Caption, 1, 0}, - {XFA_Element::Desc, 1, 0}, - {XFA_Element::Font, 1, 0}, - {XFA_Element::Value, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::EncryptionLevel, 1, 0}, - {XFA_Element::Encrypt, 1, 0}, - {XFA_Element::Permissions, 1, 0}, - {XFA_Element::Meridiem, 2, 0}, - {XFA_Element::SuppressBanner, 1, 0}, - {XFA_Element::VersionControl, 1, 0}, - {XFA_Element::LocaleSet, 1, 0}, - {XFA_Element::Template, 1, 0}, - {XFA_Element::ValidationMessaging, 1, 0}, - {XFA_Element::Locale, 1, 0}, - {XFA_Element::Data, 1, 0}, - {XFA_Element::Messaging, 1, 0}, - {XFA_Element::Pattern, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Solid, 1, - XFA_PROPERTYFLAG_OneOf | XFA_PROPERTYFLAG_DefaultOneOf}, - {XFA_Element::Stipple, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Linear, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Radial, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Fill, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Map, 1, 0}, - {XFA_Element::Arc, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Text, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Time, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::DateTime, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Image, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Decimal, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Boolean, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Integer, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::ExData, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Rectangle, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Date, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Float, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Line, 1, XFA_PROPERTYFLAG_OneOf}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Destination, 1, 0}, - {XFA_Element::Message, 1, 0}, - {XFA_Element::Script, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Picture, 1, 0}, - {XFA_Element::ConnectString, 1, 0}, - {XFA_Element::User, 1, 0}, - {XFA_Element::Password, 1, 0}, - {XFA_Element::ModifyAnnots, 1, 0}, - {XFA_Element::ContentCopy, 1, 0}, - {XFA_Element::FormFieldFilling, 1, 0}, - {XFA_Element::Change, 1, 0}, - {XFA_Element::AccessibleContent, 1, 0}, - {XFA_Element::Print, 1, 0}, - {XFA_Element::PlaintextMetadata, 1, 0}, - {XFA_Element::PrintHighQuality, 1, 0}, - {XFA_Element::DocumentAssembly, 1, 0}, - {XFA_Element::Encrypt, 1, 0}, - {XFA_Element::NumberSymbol, 5, 0}, - {XFA_Element::FontInfo, 1, 0}, - {XFA_Element::Xdc, 1, 0}, - {XFA_Element::Color, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::TimePattern, 4, 0}, - {XFA_Element::Whitespace, 1, 0}, - {XFA_Element::Rename, 1, 0}, - {XFA_Element::IfEmpty, 1, 0}, - {XFA_Element::Presence, 1, 0}, - {XFA_Element::Picture, 1, 0}, - {XFA_Element::NameAttr, 1, 0}, - {XFA_Element::GroupParent, 1, 0}, - {XFA_Element::Script, 1, 0}, - {XFA_Element::Edge, 1, 0}, - {XFA_Element::Connect, 1, 0}, - {XFA_Element::Extras, 1, 0}, - {XFA_Element::Month, 12, 0}, -}; diff --git a/xfa/fxfa/parser/xfa_basic_data_element_script.cpp b/xfa/fxfa/parser/xfa_basic_data_element_script.cpp index 675fb8a39a974afbe373d418306deda60611b3ff..80a2bf3d03efec20838dd0869a1eb9f2262df037 100644 --- a/xfa/fxfa/parser/xfa_basic_data_element_script.cpp +++ b/xfa/fxfa/parser/xfa_basic_data_element_script.cpp @@ -6,3594 +6,3803 @@ #include "xfa/fxfa/parser/xfa_basic_data.h" +#include "fxjs/xfa/cjx_arc.h" +#include "fxjs/xfa/cjx_area.h" +#include "fxjs/xfa/cjx_assist.h" +#include "fxjs/xfa/cjx_barcode.h" +#include "fxjs/xfa/cjx_bind.h" +#include "fxjs/xfa/cjx_binditems.h" +#include "fxjs/xfa/cjx_bookend.h" +#include "fxjs/xfa/cjx_boolean.h" +#include "fxjs/xfa/cjx_border.h" +#include "fxjs/xfa/cjx_break.h" +#include "fxjs/xfa/cjx_breakafter.h" +#include "fxjs/xfa/cjx_breakbefore.h" +#include "fxjs/xfa/cjx_button.h" +#include "fxjs/xfa/cjx_calculate.h" +#include "fxjs/xfa/cjx_caption.h" +#include "fxjs/xfa/cjx_certificate.h" +#include "fxjs/xfa/cjx_certificates.h" +#include "fxjs/xfa/cjx_checkbutton.h" +#include "fxjs/xfa/cjx_choicelist.h" +#include "fxjs/xfa/cjx_color.h" +#include "fxjs/xfa/cjx_comb.h" +#include "fxjs/xfa/cjx_command.h" +#include "fxjs/xfa/cjx_connect.h" +#include "fxjs/xfa/cjx_connectstring.h" +#include "fxjs/xfa/cjx_contentarea.h" +#include "fxjs/xfa/cjx_corner.h" +#include "fxjs/xfa/cjx_datavalue.h" +#include "fxjs/xfa/cjx_datawindow.h" +#include "fxjs/xfa/cjx_date.h" +#include "fxjs/xfa/cjx_datetime.h" +#include "fxjs/xfa/cjx_datetimeedit.h" +#include "fxjs/xfa/cjx_decimal.h" +#include "fxjs/xfa/cjx_defaultui.h" +#include "fxjs/xfa/cjx_delete.h" +#include "fxjs/xfa/cjx_delta.h" +#include "fxjs/xfa/cjx_desc.h" +#include "fxjs/xfa/cjx_digestmethod.h" +#include "fxjs/xfa/cjx_digestmethods.h" +#include "fxjs/xfa/cjx_draw.h" +#include "fxjs/xfa/cjx_edge.h" +#include "fxjs/xfa/cjx_encoding.h" +#include "fxjs/xfa/cjx_encodings.h" +#include "fxjs/xfa/cjx_encrypt.h" +#include "fxjs/xfa/cjx_event.h" +#include "fxjs/xfa/cjx_eventpseudomodel.h" +#include "fxjs/xfa/cjx_exclgroup.h" +#include "fxjs/xfa/cjx_exdata.h" +#include "fxjs/xfa/cjx_execute.h" +#include "fxjs/xfa/cjx_exobject.h" +#include "fxjs/xfa/cjx_extras.h" +#include "fxjs/xfa/cjx_field.h" +#include "fxjs/xfa/cjx_fill.h" +#include "fxjs/xfa/cjx_filter.h" +#include "fxjs/xfa/cjx_float.h" +#include "fxjs/xfa/cjx_font.h" +#include "fxjs/xfa/cjx_format.h" +#include "fxjs/xfa/cjx_handler.h" +#include "fxjs/xfa/cjx_hostpseudomodel.h" +#include "fxjs/xfa/cjx_image.h" +#include "fxjs/xfa/cjx_imageedit.h" +#include "fxjs/xfa/cjx_insert.h" +#include "fxjs/xfa/cjx_instancemanager.h" +#include "fxjs/xfa/cjx_integer.h" +#include "fxjs/xfa/cjx_issuers.h" +#include "fxjs/xfa/cjx_items.h" +#include "fxjs/xfa/cjx_keep.h" +#include "fxjs/xfa/cjx_keyusage.h" +#include "fxjs/xfa/cjx_layoutpseudomodel.h" +#include "fxjs/xfa/cjx_line.h" +#include "fxjs/xfa/cjx_linear.h" +#include "fxjs/xfa/cjx_logpseudomodel.h" +#include "fxjs/xfa/cjx_manifest.h" +#include "fxjs/xfa/cjx_map.h" +#include "fxjs/xfa/cjx_margin.h" +#include "fxjs/xfa/cjx_mdp.h" +#include "fxjs/xfa/cjx_medium.h" +#include "fxjs/xfa/cjx_message.h" +#include "fxjs/xfa/cjx_node.h" +#include "fxjs/xfa/cjx_numericedit.h" +#include "fxjs/xfa/cjx_occur.h" +#include "fxjs/xfa/cjx_oid.h" +#include "fxjs/xfa/cjx_oids.h" +#include "fxjs/xfa/cjx_operation.h" +#include "fxjs/xfa/cjx_overflow.h" +#include "fxjs/xfa/cjx_packet.h" +#include "fxjs/xfa/cjx_pagearea.h" +#include "fxjs/xfa/cjx_pageset.h" +#include "fxjs/xfa/cjx_para.h" +#include "fxjs/xfa/cjx_password.h" +#include "fxjs/xfa/cjx_passwordedit.h" +#include "fxjs/xfa/cjx_pattern.h" +#include "fxjs/xfa/cjx_picture.h" +#include "fxjs/xfa/cjx_query.h" +#include "fxjs/xfa/cjx_radial.h" +#include "fxjs/xfa/cjx_reason.h" +#include "fxjs/xfa/cjx_reasons.h" +#include "fxjs/xfa/cjx_recordset.h" +#include "fxjs/xfa/cjx_rectangle.h" +#include "fxjs/xfa/cjx_ref.h" +#include "fxjs/xfa/cjx_rootelement.h" +#include "fxjs/xfa/cjx_script.h" +#include "fxjs/xfa/cjx_select.h" +#include "fxjs/xfa/cjx_setproperty.h" +#include "fxjs/xfa/cjx_signature.h" +#include "fxjs/xfa/cjx_signatureproperties.h" +#include "fxjs/xfa/cjx_signaturepseudomodel.h" +#include "fxjs/xfa/cjx_signdata.h" +#include "fxjs/xfa/cjx_signing.h" +#include "fxjs/xfa/cjx_soapaction.h" +#include "fxjs/xfa/cjx_soapaddress.h" +#include "fxjs/xfa/cjx_solid.h" +#include "fxjs/xfa/cjx_source.h" +#include "fxjs/xfa/cjx_sourceset.h" +#include "fxjs/xfa/cjx_speak.h" +#include "fxjs/xfa/cjx_stipple.h" +#include "fxjs/xfa/cjx_subform.h" +#include "fxjs/xfa/cjx_subformset.h" +#include "fxjs/xfa/cjx_subjectdn.h" +#include "fxjs/xfa/cjx_subjectdns.h" +#include "fxjs/xfa/cjx_submit.h" +#include "fxjs/xfa/cjx_text.h" +#include "fxjs/xfa/cjx_textedit.h" +#include "fxjs/xfa/cjx_time.h" +#include "fxjs/xfa/cjx_timestamp.h" +#include "fxjs/xfa/cjx_tooltip.h" +#include "fxjs/xfa/cjx_traversal.h" +#include "fxjs/xfa/cjx_traverse.h" +#include "fxjs/xfa/cjx_tree.h" +#include "fxjs/xfa/cjx_treelist.h" +#include "fxjs/xfa/cjx_ui.h" +#include "fxjs/xfa/cjx_update.h" +#include "fxjs/xfa/cjx_uri.h" +#include "fxjs/xfa/cjx_user.h" +#include "fxjs/xfa/cjx_validate.h" +#include "fxjs/xfa/cjx_value.h" +#include "fxjs/xfa/cjx_variables.h" +#include "fxjs/xfa/cjx_wsdladdress.h" +#include "fxjs/xfa/cjx_wsdlconnection.h" +#include "fxjs/xfa/cjx_xfa.h" +#include "fxjs/xfa/cjx_xmlconnection.h" +#include "fxjs/xfa/cjx_xsdconnection.h" #include "xfa/fxfa/fxfa_basic.h" -#include "xfa/fxfa/parser/cscript_datawindow.h" -#include "xfa/fxfa/parser/cscript_eventpseudomodel.h" -#include "xfa/fxfa/parser/cscript_hostpseudomodel.h" -#include "xfa/fxfa/parser/cscript_layoutpseudomodel.h" -#include "xfa/fxfa/parser/cscript_logpseudomodel.h" -#include "xfa/fxfa/parser/cscript_signaturepseudomodel.h" const XFA_SCRIPTHIERARCHY g_XFAScriptIndex[] = { - {0, 0, 0, 2, 316}, {0, 0, 2, 2, 316}, {0, 0, 4, 2, 316}, - {0, 0, 6, 8, 316}, {0, 0, 14, 4, 316}, {0, 0, 18, 5, 317}, - {0, 0, 23, 2, 316}, {0, 0, 25, 1, 316}, {0, 0, 26, 12, 316}, - {0, 0, 38, 2, 316}, {0, 0, 40, 1, 316}, {0, 0, 41, 3, 316}, - {0, 0, 44, 2, 316}, {0, 0, 46, 6, 316}, {0, 0, 52, 0, 316}, - {0, 0, 52, 2, 319}, {0, 0, 54, 2, 316}, {0, 0, 56, 6, 316}, - {0, 0, 62, 0, 316}, {0, 0, 62, 0, 316}, {0, 0, 62, 2, 316}, - {0, 0, 64, 2, 316}, {0, 0, 66, 6, 316}, {0, 0, 72, 4, 316}, - {0, 0, 76, 7, 316}, {0, 0, 83, 2, 320}, {0, 0, 85, 3, 316}, - {0, 0, 88, 3, 316}, {0, 0, 91, 2, 320}, {0, 0, 93, 6, 320}, - {0, 0, 99, 4, 316}, {0, 0, 103, 2, 316}, {0, 0, 105, 3, 319}, - {0, 0, 108, 4, 316}, {0, 0, 112, 3, 316}, {0, 0, 115, 2, 316}, - {0, 0, 117, 6, 316}, {0, 0, 123, 12, 316}, {0, 0, 135, 2, 316}, - {0, 0, 137, 5, 316}, {0, 0, 142, 2, 316}, {0, 0, 144, 3, 316}, - {0, 0, 147, 1, 316}, {0, 0, 148, 14, 316}, {0, 0, 162, 2, 316}, - {0, 0, 164, 2, 316}, {0, 0, 166, 3, 316}, {0, 0, 169, 2, 316}, - {0, 0, 171, 2, 316}, {0, 0, 173, 2, 316}, {0, 0, 175, 4, 316}, - {0, 0, 179, 2, 316}, {0, 0, 181, 2, 316}, {0, 0, 183, 0, 319}, - {0, 0, 183, 20, 316}, {0, 0, 203, 1, 316}, {0, 0, 204, 3, 316}, - {0, 0, 207, 2, 316}, {0, 0, 209, 0, 316}, {0, 0, 209, 2, 316}, - {0, 0, 211, 2, 316}, {0, 0, 213, 4, 320}, {0, 0, 217, 0, 316}, - {0, 0, 217, 1, 316}, {0, 0, 218, 3, 316}, {0, 4, 221, 0, 312}, - {4, 1, 221, 1, 316}, {5, 0, 222, 2, 316}, {5, 1, 224, 3, -1}, - {6, 0, 227, 0, 316}, {6, 0, 227, 2, 316}, {6, 0, 229, 2, 316}, - {6, 0, 231, 3, 316}, {6, 0, 234, 2, 316}, {6, 0, 236, 6, 316}, - {6, 0, 242, 10, 317}, {6, 0, 252, 9, 316}, {6, 0, 261, 5, 318}, - {6, 0, 266, 4, 318}, {6, 0, 270, 2, 316}, {6, 0, 272, 2, 316}, - {6, 0, 274, 5, 316}, {6, 0, 279, 3, 316}, {6, 0, 282, 2, 316}, - {6, 0, 284, 2, 316}, {6, 0, 286, 2, 316}, {6, 0, 288, 2, 316}, - {6, 0, 290, 4, 316}, {6, 0, 294, 3, 316}, {6, 0, 297, 3, 316}, - {6, 0, 300, 2, 316}, {6, 0, 302, 2, 316}, {6, 0, 304, 2, 316}, - {6, 13, 306, 36, 317}, {19, 0, 342, 3, 316}, {19, 0, 345, 2, 316}, - {19, 0, 347, 2, 316}, {19, 0, 349, 2, 316}, {19, 0, 351, 7, 317}, - {19, 2, 358, 16, 312}, {21, 0, 374, 2, 320}, {21, 0, 376, 2, 316}, - {21, 0, 378, 0, 316}, {21, 0, 378, 2, 316}, {21, 0, 380, 6, 316}, - {21, 0, 386, 3, 316}, {21, 0, 389, 2, 316}, {21, 0, 391, 4, 316}, - {21, 0, 395, 0, 316}, {21, 5, 395, 30, 316}, {26, 0, 425, 2, 320}, - {26, 0, 427, 3, 316}, {26, 0, 430, 2, 320}, {26, 0, 432, 5, 316}, - {26, 0, 437, 2, 316}, {26, 0, 439, 3, 316}, {26, 0, 442, 2, 316}, - {26, 0, 444, 8, 316}, {26, 0, 452, 1, 316}, {26, 0, 453, 2, 316}, - {26, 0, 455, 2, 316}, {26, 0, 457, 4, 316}, {26, 0, 461, 0, 316}, - {26, 0, 461, 2, 316}, {26, 0, 463, 2, 316}, {26, 0, 465, 6, 318}, - {26, 5, 471, 31, 317}, {31, 0, 502, 2, 320}, {31, 0, 504, 2, 316}, - {31, 0, 506, 2, 316}, {31, 0, 508, 4, 320}, {31, 16, 512, 11, 312}, - {47, 0, 523, 2, 316}, {47, 0, 525, 2, 316}, {47, 0, 527, 2, 316}, - {47, 0, 529, 2, 316}, {47, 0, 531, 3, 316}, {47, 0, 534, 2, 316}, - {47, 0, 536, 3, 316}, {47, 0, 539, 3, 316}, {47, 0, 542, 4, 318}, - {47, 0, 546, 4, 316}, {47, 0, 550, 2, 316}, {47, 0, 552, 0, 316}, - {47, 0, 552, 2, 316}, {47, 0, 554, 3, 316}, {47, 0, 557, 6, 316}, - {47, 0, 563, 2, 316}, {47, 0, 565, 2, 316}, {47, 0, 567, 3, 316}, - {47, 19, 570, 1, 312}, {66, 0, 571, 2, 316}, {66, 0, 573, 8, 316}, - {66, 0, 581, 2, 316}, {66, 0, 583, 4, 316}, {66, 0, 587, 5, 316}, - {66, 0, 592, 3, 316}, {66, 0, 595, 2, 320}, {66, 0, 597, 3, 316}, - {66, 0, 600, 7, 316}, {66, 0, 607, 3, 316}, {66, 0, 610, 0, 316}, - {66, 0, 610, 4, 317}, {66, 0, 614, 4, 318}, {66, 0, 618, 2, 320}, - {66, 0, 620, 5, 316}, {66, 0, 625, 2, 316}, {66, 0, 627, 2, 316}, - {66, 0, 629, 2, 320}, {66, 0, 631, 2, 320}, {66, 0, 633, 4, 316}, - {66, 0, 637, 2, 316}, {66, 0, 639, 1, 316}, {66, 0, 640, 1, 316}, - {66, 0, 641, 4, 316}, {66, 0, 645, 3, 316}, {66, 7, 648, 2, 319}, - {73, 0, 650, 2, 316}, {73, 0, 652, 2, 316}, {73, 0, 654, 3, 316}, - {73, 4, 657, 4, 312}, {77, 0, 661, 10, 316}, {77, 0, 671, 2, 316}, - {77, 0, 673, 4, 316}, {77, 0, 677, 4, 316}, {77, 0, 681, 3, 316}, - {77, 0, 684, 2, 316}, {77, 0, 686, 2, 316}, {77, 0, 688, 8, 317}, - {77, 0, 696, 3, 316}, {77, 0, 699, 3, 316}, {77, 0, 702, 2, 316}, - {77, 0, 704, 2, 316}, {77, 0, 706, 5, 316}, {77, 0, 711, 4, 316}, - {77, 0, 715, 2, 316}, {77, 0, 717, 8, 318}, {77, 0, 725, 1, 316}, - {77, 0, 726, 2, 320}, {77, 0, 728, 3, 316}, {77, 1, 731, 4, 316}, - {78, 0, 735, 5, 316}, {78, 0, 740, 3, 316}, {78, 0, 743, 1, 316}, - {78, 0, 744, 2, 320}, {78, 0, 746, 0, 313}, {78, 0, 746, 2, 316}, - {78, 5, 748, 3, 316}, {83, 0, 751, 5, 316}, {83, 0, 756, 7, 316}, - {83, 0, 763, 6, 316}, {83, 0, 769, 3, 316}, {83, 0, 772, 2, 316}, - {83, 0, 774, 5, 316}, {83, 0, 779, 2, 316}, {83, 0, 781, 0, 314}, - {83, 0, 781, 2, 316}, {83, 0, 783, 1, 316}, {83, 0, 784, 2, 316}, - {83, 0, 786, 5, 316}, {83, 0, 791, 2, 316}, {83, 0, 793, 1, 316}, - {83, 0, 794, 2, 316}, {83, 0, 796, 2, 316}, {83, 0, 798, 6, 316}, - {83, 0, 804, 2, 316}, {83, 0, 806, 2, 320}, {83, 0, 808, 3, 316}, - {83, 0, 811, 4, 316}, {83, 0, 815, 2, 316}, {83, 0, 817, 2, 316}, - {83, 0, 819, 2, 316}, {83, 0, 821, 2, 316}, {83, 0, 823, 2, 316}, - {83, 0, 825, 2, 316}, {83, 0, 827, 4, 318}, {83, 1, 831, 2, 316}, - {84, 0, 833, 5, 316}, {84, 0, 838, 20, 317}, {84, 0, 858, 2, 316}, - {84, 0, 860, 0, 316}, {84, 0, 860, 2, 316}, {84, 0, 862, 4, 320}, - {84, 0, 866, 0, 316}, {84, 0, 866, 2, 316}, {84, 0, 868, 1, 316}, - {84, 0, 869, 2, 316}, {84, 0, 871, 3, 316}, {84, 0, 874, 2, 316}, - {84, 0, 876, 2, 316}, {84, 0, 878, 4, 316}, {84, 0, 882, 3, 316}, - {84, 0, 885, 17, 316}, {84, 6, 902, 1, 319}, {90, 0, 903, 2, 316}, - {90, 0, 905, 2, 320}, {90, 0, 907, 2, 320}, {90, 0, 909, 2, 316}, - {90, 0, 911, 2, 316}, {90, 0, 913, 4, 318}, {90, 0, 917, 2, 316}, - {90, 5, 919, 0, 312}, {95, 0, 919, 2, 316}, {95, 0, 921, 4, 316}, - {95, 0, 925, 4, 316}, {95, 0, 929, 6, 316}, {95, 0, 935, 2, 316}, - {95, 0, 937, 4, 316}, {95, 0, 941, 3, 316}, {95, 0, 944, 3, 316}, - {95, 0, 947, 2, 316}, {95, 0, 949, 3, 316}, {95, 0, 952, 0, 316}, - {95, 0, 952, 0, 316}, {95, 0, 952, 2, 316}, {95, 0, 954, 7, 316}, - {95, 0, 961, 2, 316}, {95, 0, 963, 0, 319}, {95, 0, 963, 7, 316}, - {95, 0, 970, 2, 316}, {95, 0, 972, 2, 316}, {95, 3, 974, 1, 316}, - {98, 0, 975, 2, 320}, {98, 0, 977, 4, 316}, {98, 0, 981, 0, 316}, - {98, 0, 981, 2, 316}, {98, 0, 983, 2, 316}, {98, 0, 985, 4, 316}, - {98, 0, 989, 1, 316}, {98, 0, 990, 2, 316}, {98, 0, 992, 2, 316}, - {98, 0, 994, 3, 316}, {98, 0, 997, 2, 317}, {98, 0, 999, 0, 316}, - {98, 0, 999, 4, 316}, {98, 0, 1003, 4, 316}, {98, 0, 1007, 2, 316}, - {98, 0, 1009, 3, 316}, {98, 0, 1012, 4, 316}, {98, 0, 1016, 7, 316}, - {98, 0, 1023, 4, 316}, {98, 0, 1027, 1, 313}, {98, 17, 1028, 3, 316}, - {115, 0, 1031, 5, 316}, {115, 0, 1036, 2, 316}, {115, 0, 1038, 1, 316}, - {115, 0, 1039, 4, 316}, {115, 0, 1043, 2, 316}, {115, 0, 1045, 2, 316}, - {115, 0, 1047, 1, 316}, {115, 0, 1048, 2, 316}, {115, 0, 1050, 5, 316}, - {115, 0, 1055, 1, -1}, {115, 4, 1056, 1, 312}, {119, 1, 1057, 0, 313}, - {120, 2, 1057, 8, 312}, {122, 11, 1065, 6, 315}, {133, 2, 1071, 0, 316}, - {135, 0, 1071, 0, 316}, {135, 3, 1071, 2, 316}, {138, 0, 1073, 2, 316}, + {/* ps */ 0, 2, 316}, + {/* to */ 2, 2, 316}, + {/* ui */ 4, 2, 316}, + {/* recordSet */ 6, 8, 316}, + {/* subsetBelow */ 14, 4, 316}, + {/* subformSet */ 18, 5, 317}, + {/* adobeExtensionLevel */ 23, 2, 316}, + {/* typeface */ 25, 1, 316}, + {/* break */ 26, 12, 316}, + {/* fontInfo */ 38, 2, 316}, + {/* numberPattern */ 40, 1, 316}, + {/* dynamicRender */ 41, 3, 316}, + {/* printScaling */ 44, 2, 316}, + {/* checkButton */ 46, 6, 316}, + {/* datePatterns */ 52, 0, 316}, + {/* sourceSet */ 52, 2, 319}, + {/* amd */ 54, 2, 316}, + {/* arc */ 56, 6, 316}, + {/* day */ 62, 0, 316}, + {/* era */ 62, 0, 316}, + {/* jog */ 62, 2, 316}, + {/* log */ 64, 2, 316}, + {/* map */ 66, 6, 316}, + {/* mdp */ 72, 4, 316}, + {/* breakBefore */ 76, 7, 316}, + {/* oid */ 83, 2, 320}, + {/* pcl */ 85, 3, 316}, + {/* pdf */ 88, 3, 316}, + {/* ref */ 91, 2, 320}, + {/* uri */ 93, 6, 320}, + {/* xdc */ 99, 4, 316}, + {/* xdp */ 103, 2, 316}, + {/* xfa */ 105, 3, 319}, + {/* xsl */ 108, 4, 316}, + {/* zpl */ 112, 3, 316}, + {/* cache */ 115, 2, 316}, + {/* margin */ 117, 6, 316}, + {/* keyUsage */ 123, 12, 316}, + {/* exclude */ 135, 2, 316}, + {/* choiceList */ 137, 5, 316}, + {/* level */ 142, 2, 316}, + {/* labelPrinter */ 144, 3, 316}, + {/* calendarSymbols */ 147, 1, 316}, + {/* para */ 148, 14, 316}, + {/* part */ 162, 2, 316}, + {/* pdfa */ 164, 2, 316}, + {/* filter */ 166, 3, 316}, + {/* present */ 169, 2, 316}, + {/* pagination */ 171, 2, 316}, + {/* encoding */ 173, 2, 316}, + {/* event */ 175, 4, 316}, + {/* whitespace */ 179, 2, 316}, + {/* defaultUi */ 181, 2, 316}, + {/* dataModel */ 183, 0, 319}, + {/* barcode */ 183, 20, 316}, + {/* timePattern */ 203, 1, 316}, + {/* batchOutput */ 204, 3, 316}, + {/* enforce */ 207, 2, 316}, + {/* currencySymbols */ 209, 0, 316}, + {/* addSilentPrint */ 209, 2, 316}, + {/* rename */ 211, 2, 316}, + {/* operation */ 213, 4, 320}, + {/* typefaces */ 217, 0, 316}, + {/* subjectDNs */ 217, 1, 316}, + {/* issuers */ 218, 3, 316}, + {/* signaturePseudoModel */ 221, 0, 312}, + {/* wsdlConnection */ 221, 1, 316}, + {/* debug */ 222, 2, 316}, + {/* delta */ 224, 3, -1}, + {/* eraNames */ 227, 0, 316}, + {/* modifyAnnots */ 227, 2, 316}, + {/* startNode */ 229, 2, 316}, + {/* button */ 231, 3, 316}, + {/* format */ 234, 2, 316}, + {/* border */ 236, 6, 316}, + {/* area */ 242, 10, 317}, + {/* hyphenation */ 252, 9, 316}, + {/* text */ 261, 5, 318}, + {/* time */ 266, 4, 318}, + {/* type */ 270, 2, 316}, + {/* overprint */ 272, 2, 316}, + {/* certificates */ 274, 5, 316}, + {/* encryptionMethods */ 279, 3, 316}, + {/* setProperty */ 282, 2, 316}, + {/* printerName */ 284, 2, 316}, + {/* startPage */ 286, 2, 316}, + {/* pageOffset */ 288, 2, 316}, + {/* dateTime */ 290, 4, 316}, + {/* comb */ 294, 3, 316}, + {/* pattern */ 297, 3, 316}, + {/* ifEmpty */ 300, 2, 316}, + {/* suppressBanner */ 302, 2, 316}, + {/* outputBin */ 304, 2, 316}, + {/* field */ 306, 36, 317}, + {/* agent */ 342, 3, 316}, + {/* outputXSL */ 345, 2, 316}, + {/* adjustData */ 347, 2, 316}, + {/* autoSave */ 349, 2, 316}, + {/* contentArea */ 351, 7, 317}, + {/* eventPseudoModel */ 358, 16, 312}, + {/* wsdlAddress */ 374, 2, 320}, + {/* solid */ 376, 2, 316}, + {/* dateTimeSymbols */ 378, 0, 316}, + {/* encryptionLevel */ 378, 2, 316}, + {/* edge */ 380, 6, 316}, + {/* stipple */ 386, 3, 316}, + {/* attributes */ 389, 2, 316}, + {/* versionControl */ 391, 4, 316}, + {/* meridiem */ 395, 0, 316}, + {/* exclGroup */ 395, 30, 316}, + {/* toolTip */ 425, 2, 320}, + {/* compress */ 427, 3, 316}, + {/* reason */ 430, 2, 320}, + {/* execute */ 432, 5, 316}, + {/* contentCopy */ 437, 2, 316}, + {/* dateTimeEdit */ 439, 3, 316}, + {/* config */ 442, 2, 316}, + {/* image */ 444, 8, 316}, + {/* #xHTML */ 452, 1, 316}, + {/* numberOfCopies */ 453, 2, 316}, + {/* behaviorOverride */ 455, 2, 316}, + {/* timeStamp */ 457, 4, 316}, + {/* month */ 461, 0, 316}, + {/* viewerPreferences */ 461, 2, 316}, + {/* scriptModel */ 463, 2, 316}, + {/* decimal */ 465, 6, 318}, + {/* subform */ 471, 31, 317}, + {/* select */ 502, 2, 320}, + {/* window */ 504, 2, 316}, + {/* localeSet */ 506, 2, 316}, + {/* handler */ 508, 4, 320}, + {/* hostPseudoModel */ 512, 11, 312}, + {/* presence */ 523, 2, 316}, + {/* record */ 525, 2, 316}, + {/* embed */ 527, 2, 316}, + {/* version */ 529, 2, 316}, + {/* command */ 531, 3, 316}, + {/* copies */ 534, 2, 316}, + {/* staple */ 536, 3, 316}, + {/* submitFormat */ 539, 3, 316}, + {/* boolean */ 542, 4, 318}, + {/* message */ 546, 4, 316}, + {/* output */ 550, 2, 316}, + {/* psMap */ 552, 0, 316}, + {/* excludeNS */ 552, 2, 316}, + {/* assist */ 554, 3, 316}, + {/* picture */ 557, 6, 316}, + {/* traversal */ 563, 2, 316}, + {/* silentPrint */ 565, 2, 316}, + {/* webClient */ 567, 3, 316}, + {/* layoutPseudoModel */ 570, 1, 312}, + {/* producer */ 571, 2, 316}, + {/* corner */ 573, 8, 316}, + {/* msgId */ 581, 2, 316}, + {/* color */ 583, 4, 316}, + {/* keep */ 587, 5, 316}, + {/* query */ 592, 3, 316}, + {/* insert */ 595, 2, 320}, + {/* imageEdit */ 597, 3, 316}, + {/* validate */ 600, 7, 316}, + {/* digestMethods */ 607, 3, 316}, + {/* numberPatterns */ 610, 0, 316}, + {/* pageSet */ 610, 4, 317}, + {/* integer */ 614, 4, 318}, + {/* soapAddress */ 618, 2, 320}, + {/* equate */ 620, 5, 316}, + {/* formFieldFilling */ 625, 2, 316}, + {/* pageRange */ 627, 2, 316}, + {/* update */ 629, 2, 320}, + {/* connectString */ 631, 2, 320}, + {/* mode */ 633, 4, 316}, + {/* layout */ 637, 2, 316}, + {/* #xml */ 639, 1, 316}, + {/* xsdConnection */ 640, 1, 316}, + {/* traverse */ 641, 4, 316}, + {/* encodings */ 645, 3, 316}, + {/* template */ 648, 2, 319}, + {/* acrobat */ 650, 2, 316}, + {/* validationMessaging */ 652, 2, 316}, + {/* signing */ 654, 3, 316}, + {/* dataWindow */ 657, 4, 312}, + {/* script */ 661, 10, 316}, + {/* addViewerPreferences */ 671, 2, 316}, + {/* alwaysEmbed */ 673, 4, 316}, + {/* passwordEdit */ 677, 4, 316}, + {/* numericEdit */ 681, 3, 316}, + {/* encryptionMethod */ 684, 2, 316}, + {/* change */ 686, 2, 316}, + {/* pageArea */ 688, 8, 317}, + {/* submitUrl */ 696, 3, 316}, + {/* oids */ 699, 3, 316}, + {/* signature */ 702, 2, 316}, + {/* ADBE_JSConsole */ 704, 2, 316}, + {/* caption */ 706, 5, 316}, + {/* relevant */ 711, 4, 316}, + {/* flipLabel */ 715, 2, 316}, + {/* exData */ 717, 8, 318}, + {/* dayNames */ 725, 1, 316}, + {/* soapAction */ 726, 2, 320}, + {/* defaultTypeface */ 728, 3, 316}, + {/* manifest */ 731, 4, 316}, + {/* overflow */ 735, 5, 316}, + {/* linear */ 740, 3, 316}, + {/* currencySymbol */ 743, 1, 316}, + {/* delete */ 744, 2, 320}, + {/* deltas */ 746, 0, 313}, + {/* digestMethod */ 746, 2, 316}, + {/* instanceManager */ 748, 3, 316}, + {/* equateRange */ 751, 5, 316}, + {/* medium */ 756, 7, 316}, + {/* textEdit */ 763, 6, 316}, + {/* templateCache */ 769, 3, 316}, + {/* compressObjectStream */ 772, 2, 316}, + {/* dataValue */ 774, 5, 316}, + {/* accessibleContent */ 779, 2, 316}, + {/* nodeList */ 781, 0, 314}, + {/* includeXDPContent */ 781, 2, 316}, + {/* xmlConnection */ 783, 1, 316}, + {/* validateApprovalSignatures */ 784, 2, 316}, + {/* signData */ 786, 5, 316}, + {/* packets */ 791, 2, 316}, + {/* datePattern */ 793, 1, 316}, + {/* duplexOption */ 794, 2, 316}, + {/* base */ 796, 2, 316}, + {/* bind */ 798, 6, 316}, + {/* compression */ 804, 2, 316}, + {/* user */ 806, 2, 320}, + {/* rectangle */ 808, 3, 316}, + {/* effectiveOutputPolicy */ 811, 4, 316}, + {/* ADBE_JSDebugger */ 815, 2, 316}, + {/* acrobat7 */ 817, 2, 316}, + {/* interactive */ 819, 2, 316}, + {/* locale */ 821, 2, 316}, + {/* currentPage */ 823, 2, 316}, + {/* data */ 825, 2, 316}, + {/* date */ 827, 4, 318}, + {/* desc */ 831, 2, 316}, + {/* encrypt */ 833, 5, 316}, + {/* draw */ 838, 20, 317}, + {/* encryption */ 858, 2, 316}, + {/* meridiemNames */ 860, 0, 316}, + {/* messaging */ 860, 2, 316}, + {/* speak */ 862, 4, 320}, + {/* dataGroup */ 866, 0, 316}, + {/* common */ 866, 2, 316}, + {/* #text */ 868, 1, 316}, + {/* paginationOverride */ 869, 2, 316}, + {/* reasons */ 871, 3, 316}, + {/* signatureProperties */ 874, 2, 316}, + {/* threshold */ 876, 2, 316}, + {/* appearanceFilter */ 878, 4, 316}, + {/* fill */ 882, 3, 316}, + {/* font */ 885, 17, 316}, + {/* form */ 902, 1, 319}, + {/* mediumInfo */ 903, 2, 316}, + {/* certificate */ 905, 2, 320}, + {/* password */ 907, 2, 320}, + {/* runScripts */ 909, 2, 316}, + {/* trace */ 911, 2, 316}, + {/* float */ 913, 4, 318}, + {/* renderPolicy */ 917, 2, 316}, + {/* logPseudoModel */ 919, 0, 312}, + {/* destination */ 919, 2, 316}, + {/* value */ 921, 4, 316}, + {/* bookend */ 925, 4, 316}, + {/* exObject */ 929, 6, 316}, + {/* openAction */ 935, 2, 316}, + {/* neverEmbed */ 937, 4, 316}, + {/* bindItems */ 941, 3, 316}, + {/* calculate */ 944, 3, 316}, + {/* print */ 947, 2, 316}, + {/* extras */ 949, 3, 316}, + {/* proto */ 952, 0, 316}, + {/* dSigData */ 952, 0, 316}, + {/* creator */ 952, 2, 316}, + {/* connect */ 954, 7, 316}, + {/* permissions */ 961, 2, 316}, + {/* connectionSet */ 963, 0, 319}, + {/* submit */ 963, 7, 316}, + {/* range */ 970, 2, 316}, + {/* linearized */ 972, 2, 316}, + {/* packet */ 974, 1, 316}, + {/* rootElement */ 975, 2, 320}, + {/* plaintextMetadata */ 977, 4, 316}, + {/* numberSymbols */ 981, 0, 316}, + {/* printHighQuality */ 981, 2, 316}, + {/* driver */ 983, 2, 316}, + {/* incrementalLoad */ 985, 4, 316}, + {/* subjectDN */ 989, 1, 316}, + {/* compressLogicalStructure */ 990, 2, 316}, + {/* incrementalMerge */ 992, 2, 316}, + {/* radial */ 994, 3, 316}, + {/* variables */ 997, 2, 317}, + {/* timePatterns */ 999, 0, 316}, + {/* effectiveInputPolicy */ 999, 4, 316}, + {/* nameAttr */ 1003, 4, 316}, + {/* conformance */ 1007, 2, 316}, + {/* transform */ 1009, 3, 316}, + {/* lockDocument */ 1012, 4, 316}, + {/* breakAfter */ 1016, 7, 316}, + {/* line */ 1023, 4, 316}, + {/* list */ 1027, 1, 313}, + {/* source */ 1028, 3, 316}, + {/* occur */ 1031, 5, 316}, + {/* pickTrayByPDFSize */ 1036, 2, 316}, + {/* monthNames */ 1038, 1, 316}, + {/* severity */ 1039, 4, 316}, + {/* groupParent */ 1043, 2, 316}, + {/* documentAssembly */ 1045, 2, 316}, + {/* numberSymbol */ 1047, 1, 316}, + {/* tagged */ 1048, 2, 316}, + {/* */ 1050, 5, 316}, + {/* */ 1055, 1, -1}, + {/* */ 1056, 1, 312}, + {/* */ 1057, 0, 313}, + {/* */ 1057, 8, 312}, + {/* */ 1065, 6, 315}, + {/* */ 1071, 0, 316}, + {/* */ 1071, 0, 316}, + {/* */ 1071, 2, 316}, + {/* */ 1073, 2, 316}, }; const int32_t g_iScriptIndexCount = sizeof(g_XFAScriptIndex) / sizeof(XFA_SCRIPTHIERARCHY); - -const XFA_METHODINFO g_SomMethodData[] = { - {0x3c752495, L"verify", - (XFA_METHOD_CALLBACK)&CScript_SignaturePseudoModel::Verify}, - {0xa68635f1, L"sign", - (XFA_METHOD_CALLBACK)&CScript_SignaturePseudoModel::Sign}, - {0xa7f2c5e6, L"enumerate", - (XFA_METHOD_CALLBACK)&CScript_SignaturePseudoModel::Enumerate}, - {0xd8ed1467, L"clear", - (XFA_METHOD_CALLBACK)&CScript_SignaturePseudoModel::Clear}, - {0x4bdcce13, L"execute", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_WsdlConnection_Execute}, - {0x1c296ba4, L"restore", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Delta_Restore}, - {0x7d123a9, L"clearItems", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_ClearItems}, - {0xfb0b007, L"execEvent", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_ExecEvent}, - {0x6716ce97, L"execInitialize", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_ExecInitialize}, - {0x7bb919c2, L"deleteItem", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_DeleteItem}, - {0x9f053d5e, L"getSaveItem", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_GetSaveItem}, - {0xbbd32747, L"boundItem", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_BoundItem}, - {0xc492d950, L"getItemState", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_GetItemState}, - {0xc6013cd3, L"execCalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_ExecCalculate}, - {0xd8930d0e, L"setItems", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_SetItems}, - {0xe0f15045, L"getDisplayItem", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_GetDisplayItem}, - {0xe23acddc, L"setItemState", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_SetItemState}, - {0xe2dfb2f8, L"addItem", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_AddItem}, - {0xef8ce48f, L"execValidate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Field_ExecValidate}, - {0x461079ef, L"emit", (XFA_METHOD_CALLBACK)&CScript_EventPseudoModel::Emit}, - {0xfec90c63, L"reset", - (XFA_METHOD_CALLBACK)&CScript_EventPseudoModel::Reset}, - {0xfb0b007, L"execEvent", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ExclGroup_ExecEvent}, - {0x3d832221, L"selectedMember", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ExclGroup_SelectedMember}, - {0x6716ce97, L"execInitialize", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ExclGroup_ExecInitialize}, - {0xc6013cd3, L"execCalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ExclGroup_ExecCalculate}, - {0xef8ce48f, L"execValidate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ExclGroup_ExecValidate}, - {0xfb0b007, L"execEvent", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Subform_ExecEvent}, - {0x6716ce97, L"execInitialize", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Subform_ExecInitialize}, - {0xc6013cd3, L"execCalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Subform_ExecCalculate}, - {0xd9b9b1f1, L"getInvalidObjects", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Subform_GetInvalidObjects}, - {0xef8ce48f, L"execValidate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Subform_ExecValidate}, - {0xa366b7c, L"exportData", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::ExportData}, - {0x16cc226c, L"gotoURL", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::GotoURL}, - {0x1e0722f5, L"pageDown", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::PageDown}, - {0x3e66cb2c, L"setFocus", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::SetFocus}, - {0x4ac9faae, L"openList", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::OpenList}, - {0x7b89714f, L"response", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::Response}, - {0x7fd9fd58, L"documentInBatch", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::DocumentInBatch}, - {0xaf1d019d, L"resetData", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::ResetData}, - {0xb07be13c, L"beep", (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::Beep}, - {0xb1882ca0, L"getFocus", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::GetFocus}, - {0xbf4ba9ee, L"messageBox", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::MessageBox}, - {0xd6d4dbc1, L"documentCountInBatch", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::DocumentCountInBatch}, - {0xdd7676ed, L"print", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::Print}, - {0xe2f863d0, L"currentDateTime", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::CurrentDateTime}, - {0xf995d0f5, L"importData", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::ImportData}, - {0xfeb96b62, L"pageUp", - (XFA_METHOD_CALLBACK)&CScript_HostPseudoModel::PageUp}, - {0x68, L"h", (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::H}, - {0x77, L"w", (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::W}, - {0x78, L"x", (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::X}, - {0x79, L"y", (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::Y}, - {0x5460206, L"pageCount", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::PageCount}, - {0x5eb5b0f, L"pageSpan", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::PageSpan}, - {0x10f1b1bd, L"page", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::Page}, - {0x1c1e6318, L"pageContent", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::PageContent}, - {0x1c1f4a5c, L"absPageCount", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::AbsPageCount}, - {0x1ec47db5, L"absPageCountInBatch", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::AbsPageCountInBatch}, - {0x2e4ecbdb, L"sheetCountInBatch", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::SheetCountInBatch}, - {0x2fcff4b5, L"relayout", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::Relayout}, - {0x3bf1c2a5, L"absPageSpan", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::AbsPageSpan}, - {0x5775c2cc, L"absPageInBatch", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::AbsPageInBatch}, - {0x8c5feb32, L"sheetInBatch", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::SheetInBatch}, - {0x8f3a8379, L"sheet", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::Sheet}, - {0x96f3c4cb, L"relayoutPageArea", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::RelayoutPageArea}, - {0xd2a4a542, L"sheetCount", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::SheetCount}, - {0xe74f0653, L"absPage", - (XFA_METHOD_CALLBACK)&CScript_LayoutPseudoModel::AbsPage}, - {0x44c352ad, L"formNodes", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_FormNodes}, - {0x45efb847, L"remerge", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_Remerge}, - {0x6716ce97, L"execInitialize", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_ExecInitialize}, - {0x712c6afa, L"createNode", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_CreateNode}, - {0xa8a35e25, L"recalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_Recalculate}, - {0xc6013cd3, L"execCalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_ExecCalculate}, - {0xef8ce48f, L"execValidate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Template_ExecValidate}, - {0x4cc1c0f9, L"moveCurrentRecord", - (XFA_METHOD_CALLBACK)&CScript_DataWindow::MoveCurrentRecord}, - {0x5779d65f, L"record", (XFA_METHOD_CALLBACK)&CScript_DataWindow::Record}, - {0x8a476498, L"gotoRecord", - (XFA_METHOD_CALLBACK)&CScript_DataWindow::GotoRecord}, - {0xaac241c8, L"isRecordGroup", - (XFA_METHOD_CALLBACK)&CScript_DataWindow::IsRecordGroup}, - {0x1c6f4277, L"evaluate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Manifest_Evaluate}, - {0x2afec2cc, L"moveInstance", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_InstanceManager_MoveInstance}, - {0x2bf94a63, L"removeInstance", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_InstanceManager_RemoveInstance}, - {0x303adaf4, L"setInstances", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_InstanceManager_SetInstances}, - {0x4d76b89e, L"addInstance", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_InstanceManager_AddInstance}, - {0xc660dc8a, L"insertInstance", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_InstanceManager_InsertInstance}, - {0xddfd1ea1, L"metadata", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Desc_Metadata}, - {0x44c352ad, L"formNodes", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Form_FormNodes}, - {0x45efb847, L"remerge", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Form_Remerge}, - {0x6716ce97, L"execInitialize", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Form_ExecInitialize}, - {0xa8a35e25, L"recalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Form_Recalculate}, - {0xc6013cd3, L"execCalculate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Form_ExecCalculate}, - {0xef8ce48f, L"execValidate", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Form_ExecValidate}, - {0x60490a85, L"message", - (XFA_METHOD_CALLBACK)&CScript_LogPseudoModel::Message}, - {0x60ecfcc9, L"traceDeactivate", - (XFA_METHOD_CALLBACK)&CScript_LogPseudoModel::TraceDeactivate}, - {0x86a0f4c0, L"traceActivate", - (XFA_METHOD_CALLBACK)&CScript_LogPseudoModel::TraceActivate}, - {0x93eac39a, L"traceEnabled", - (XFA_METHOD_CALLBACK)&CScript_LogPseudoModel::TraceEnabled}, - {0xd1227e6f, L"trace", (XFA_METHOD_CALLBACK)&CScript_LogPseudoModel::Trace}, - {0x36c0ee14, L"getAttribute", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Packet_GetAttribute}, - {0x5468e2a0, L"setAttribute", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Packet_SetAttribute}, - {0xadc48de2, L"removeAttribute", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Packet_RemoveAttribute}, - {0x3848b3f, L"next", (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Next}, - {0x14e25bc8, L"cancelBatch", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_CancelBatch}, - {0x3ce05d68, L"first", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_First}, - {0x649e1e65, L"updateBatch", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_UpdateBatch}, - {0x6a3405dd, L"previous", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Previous}, - {0x74818fb3, L"isBOF", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_IsBOF}, - {0x74d07a76, L"isEOF", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_IsEOF}, - {0x7613cb66, L"cancel", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Cancel}, - {0x7baca2e3, L"update", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Update}, - {0x8b90e1f2, L"open", (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Open}, - {0x9c6471b3, L"delete", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Delete}, - {0xa7315093, L"addNew", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_AddNew}, - {0xa7ce5f8d, L"requery", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Requery}, - {0xc7368674, L"resync", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Resync}, - {0xd9f47f36, L"close", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Close}, - {0xf54481d4, L"last", (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_Last}, - {0xf7965460, L"hasDataChanged", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_Source_HasDataChanged}, - {0x6275f6af, L"item", - (XFA_METHOD_CALLBACK)&CXFA_NodeList::Script_ListClass_Item}, - {0x7033bfd5, L"insert", - (XFA_METHOD_CALLBACK)&CXFA_NodeList::Script_ListClass_Insert}, - {0x9cab7cae, L"remove", - (XFA_METHOD_CALLBACK)&CXFA_NodeList::Script_ListClass_Remove}, - {0xda12e518, L"append", - (XFA_METHOD_CALLBACK)&CXFA_NodeList::Script_ListClass_Append}, - {0xd892a054, L"namedItem", - (XFA_METHOD_CALLBACK)&CXFA_NodeList::Script_TreelistClass_NamedItem}, - {0xba2dd386, L"resolveNode", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_TreeClass_ResolveNode}, - {0xe509e2b9, L"resolveNodes", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_TreeClass_ResolveNodes}, - {0x1bca1ebd, L"applyXSL", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_ApplyXSL}, - {0x36c0ee14, L"getAttribute", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_GetAttribute}, - {0x5468e2a0, L"setAttribute", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_SetAttribute}, - {0x5ee00996, L"setElement", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_SetElement}, - {0x92dada4f, L"saveFilteredXML", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_SaveFilteredXML}, - {0x9c456500, L"saveXML", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_SaveXML}, - {0xabd3200a, L"getElement", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_GetElement}, - {0xb269c60d, L"isPropertySpecified", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_IsPropertySpecified}, - {0xb528be91, L"loadXML", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_LoadXML}, - {0xd9f46591, L"clone", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_Clone}, - {0xe006a76b, L"assignNode", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_NodeClass_AssignNode}, - {0x7303fcea, L"getDelta", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ContainerClass_GetDelta}, - {0xe7742c9d, L"getDeltas", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ContainerClass_GetDeltas}, - {0x30ff6aad, L"clearErrorList", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ModelClass_ClearErrorList}, - {0x712c6afa, L"createNode", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ModelClass_CreateNode}, - {0x83a6411d, L"isCompatibleNS", - (XFA_METHOD_CALLBACK)&CXFA_Node::Script_ModelClass_IsCompatibleNS}, -}; -const int32_t g_iSomMethodCount = - sizeof(g_SomMethodData) / sizeof(XFA_METHODINFO); - const XFA_SCRIPTATTRIBUTEINFO g_SomAttributeData[] = { + /* ps */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* to */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xb3543a6, L"max", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Max, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* ui */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Ui::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Ui::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* recordSet */ + {0xb3543a6, L"max", (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::max, + XFA_Attribute::Max, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x45a6daf8, L"eofAction", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_EofAction, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::eofAction, + XFA_Attribute::EofAction, XFA_ScriptType::Basic}, {0x5ec958c0, L"cursorType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CursorType, XFA_SCRIPT_Basic}, - {0x79975f2b, L"lockType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LockType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::cursorType, + XFA_Attribute::CursorType, XFA_ScriptType::Basic}, + {0x79975f2b, L"lockType", (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::lockType, + XFA_Attribute::LockType, XFA_ScriptType::Basic}, {0xa5340ff5, L"bofAction", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BofAction, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::bofAction, + XFA_Attribute::BofAction, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xc5762157, L"cursorLocation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CursorLocation, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_RecordSet::cursorLocation, + XFA_Attribute::CursorLocation, XFA_ScriptType::Basic}, + + /* subsetBelow */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* subformSet */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_SubformSet::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x1ee2d24d, L"instanceIndex", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_InstanceIndex, -1, - XFA_SCRIPT_Basic}, - {0x8c99377e, L"relation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relation, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_SubformSet::instanceIndex, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x8c99377e, L"relation", (XFA_ATTRIBUTE_CALLBACK)&CJX_SubformSet::relation, + XFA_Attribute::Relation, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_SubformSet::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_SubformSet::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* adobeExtensionLevel */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* typeface */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* break */ {0x3106c3a, L"beforeTarget", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BeforeTarget, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::beforeTarget, + XFA_Attribute::BeforeTarget, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x13a08bdb, L"overflowTarget", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_OverflowTarget, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::overflowTarget, + XFA_Attribute::OverflowTarget, XFA_ScriptType::Basic}, {0x169134a1, L"overflowLeader", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_OverflowLeader, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::overflowLeader, + XFA_Attribute::OverflowLeader, XFA_ScriptType::Basic}, {0x20914367, L"overflowTrailer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_OverflowTrailer, XFA_SCRIPT_Basic}, - {0x453eaf38, L"startNew", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_StartNew, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::overflowTrailer, + XFA_Attribute::OverflowTrailer, XFA_ScriptType::Basic}, + {0x453eaf38, L"startNew", (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::startNew, + XFA_Attribute::StartNew, XFA_ScriptType::Basic}, {0x64110ab5, L"bookendTrailer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BookendTrailer, XFA_SCRIPT_Basic}, - {0xb6b44172, L"after", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_After, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::bookendTrailer, + XFA_Attribute::BookendTrailer, XFA_ScriptType::Basic}, + {0xb6b44172, L"after", (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::after, + XFA_Attribute::After, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xc3c1442f, L"bookendLeader", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BookendLeader, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::bookendLeader, + XFA_Attribute::BookendLeader, XFA_ScriptType::Basic}, {0xcb150479, L"afterTarget", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AfterTarget, XFA_SCRIPT_Basic}, - {0xf4ffce73, L"before", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Before, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::afterTarget, + XFA_Attribute::AfterTarget, XFA_ScriptType::Basic}, + {0xf4ffce73, L"before", (XFA_ATTRIBUTE_CALLBACK)&CJX_Break::before, + XFA_Attribute::Before, XFA_ScriptType::Basic}, + + /* fontInfo */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* numberPattern */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* dynamicRender */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue_Read, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DefaultValue_Read, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* printScaling */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* checkButton */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_CheckButton::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x47cfa43a, L"allowNeutral", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AllowNeutral, XFA_SCRIPT_Basic}, - {0x7c2fd80b, L"mark", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Mark, XFA_SCRIPT_Basic}, - {0x8ed182d1, L"shape", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Shape, XFA_SCRIPT_Basic}, - {0xa686975b, L"size", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Size, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x5c054755, L"startAngle", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_StartAngle, XFA_SCRIPT_Basic}, - {0x74788f8b, L"sweepAngle", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_SweepAngle, XFA_SCRIPT_Basic}, - {0x9d833d75, L"circular", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Circular, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd996fa9b, L"hand", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Hand, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_CheckButton::allowNeutral, + XFA_Attribute::AllowNeutral, XFA_ScriptType::Basic}, + {0x7c2fd80b, L"mark", (XFA_ATTRIBUTE_CALLBACK)&CJX_CheckButton::mark, + XFA_Attribute::Mark, XFA_ScriptType::Basic}, + {0x8ed182d1, L"shape", (XFA_ATTRIBUTE_CALLBACK)&CJX_CheckButton::shape, + XFA_Attribute::Shape, XFA_ScriptType::Basic}, + {0xa686975b, L"size", (XFA_ATTRIBUTE_CALLBACK)&CJX_CheckButton::size, + XFA_Attribute::Size, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_CheckButton::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* datePatterns */ + + /* sourceSet */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_SourceSet::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_SourceSet::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* amd */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* arc */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Arc::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x5c054755, L"startAngle", (XFA_ATTRIBUTE_CALLBACK)&CJX_Arc::startAngle, + XFA_Attribute::StartAngle, XFA_ScriptType::Basic}, + {0x74788f8b, L"sweepAngle", (XFA_ATTRIBUTE_CALLBACK)&CJX_Arc::sweepAngle, + XFA_Attribute::SweepAngle, XFA_ScriptType::Basic}, + {0x9d833d75, L"circular", (XFA_ATTRIBUTE_CALLBACK)&CJX_Arc::circular, + XFA_Attribute::Circular, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Arc::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd996fa9b, L"hand", (XFA_ATTRIBUTE_CALLBACK)&CJX_Arc::hand, + XFA_Attribute::Hand, XFA_ScriptType::Basic}, + + /* day */ + + /* era */ + + /* jog */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xb0e5485d, L"bind", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Bind, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* log */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xcd7f7b54, L"from", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_From, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* map */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Map::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xb0e5485d, L"bind", (XFA_ATTRIBUTE_CALLBACK)&CJX_Map::bind, + XFA_Attribute::Bind, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Map::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xcd7f7b54, L"from", (XFA_ATTRIBUTE_CALLBACK)&CJX_Map::from, + XFA_Attribute::From, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* mdp */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Mdp::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x8e29d794, L"signatureType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_SignatureType, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xe11a2cbc, L"permissions", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Permissions, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Mdp::signatureType, + XFA_Attribute::SignatureType, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Mdp::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xe11a2cbc, L"permissions", (XFA_ATTRIBUTE_CALLBACK)&CJX_Mdp::permissions, + XFA_Attribute::Permissions, XFA_ScriptType::Basic}, + + /* breakBefore */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x453eaf38, L"startNew", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_StartNew, XFA_SCRIPT_Basic}, - {0x9dcc3ab3, L"trailer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Trailer, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::startNew, + XFA_Attribute::StartNew, XFA_ScriptType::Basic}, + {0x9dcc3ab3, L"trailer", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::trailer, + XFA_Attribute::Trailer, XFA_ScriptType::Basic}, {0xa6118c89, L"targetType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TargetType, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Target, XFA_SCRIPT_Basic}, - {0xcbcaf66d, L"leader", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Leader, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::targetType, + XFA_Attribute::TargetType, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::target, + XFA_Attribute::Target, XFA_ScriptType::Basic}, + {0xcbcaf66d, L"leader", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakBefore::leader, + XFA_Attribute::Leader, XFA_ScriptType::Basic}, + + /* oid */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Oid::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Oid::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* pcl */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* pdf */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* ref */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Ref::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Ref::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* uri */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Uri::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Uri::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* xdc */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* xdp */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0x2d574d58, L"this", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Xfa_This, - -1, XFA_SCRIPT_Object}, - {0x4fdc3454, L"timeStamp", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TimeStamp, XFA_SCRIPT_Basic}, - {0xb598a1f7, L"uuid", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Uuid, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* xfa */ + {0x2d574d58, L"this", (XFA_ATTRIBUTE_CALLBACK)&CJX_Xfa::thisValue, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0x4fdc3454, L"timeStamp", (XFA_ATTRIBUTE_CALLBACK)&CJX_Xfa::timeStamp, + XFA_Attribute::TimeStamp, XFA_ScriptType::Basic}, + {0xb598a1f7, L"uuid", (XFA_ATTRIBUTE_CALLBACK)&CJX_Xfa::uuid, + XFA_Attribute::Uuid, XFA_ScriptType::Basic}, + + /* xsl */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* zpl */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* cache */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xcfea02e, L"leftInset", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LeftInset, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* margin */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Margin::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xcfea02e, L"leftInset", (XFA_ATTRIBUTE_CALLBACK)&CJX_Margin::leftInset, + XFA_Attribute::LeftInset, XFA_ScriptType::Basic}, {0x1356caf8, L"bottomInset", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BottomInset, XFA_SCRIPT_Basic}, - {0x25764436, L"topInset", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TopInset, XFA_SCRIPT_Basic}, - {0x8a692521, L"rightInset", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RightInset, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Margin::bottomInset, + XFA_Attribute::BottomInset, XFA_ScriptType::Basic}, + {0x25764436, L"topInset", (XFA_ATTRIBUTE_CALLBACK)&CJX_Margin::topInset, + XFA_Attribute::TopInset, XFA_ScriptType::Basic}, + {0x8a692521, L"rightInset", (XFA_ATTRIBUTE_CALLBACK)&CJX_Margin::rightInset, + XFA_Attribute::RightInset, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Margin::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* keyUsage */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x1e459b8f, L"nonRepudiation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_NonRepudiation, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::nonRepudiation, + XFA_Attribute::NonRepudiation, XFA_ScriptType::Basic}, {0x2bb3f470, L"encipherOnly", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_EncipherOnly, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::encipherOnly, + XFA_Attribute::EncipherOnly, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, {0x5f760b50, L"digitalSignature", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DigitalSignature, XFA_SCRIPT_Basic}, - {0x69aa2292, L"crlSign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CrlSign, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::digitalSignature, + XFA_Attribute::DigitalSignature, XFA_ScriptType::Basic}, + {0x69aa2292, L"crlSign", (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::crlSign, + XFA_Attribute::CrlSign, XFA_ScriptType::Basic}, {0x98fd4d81, L"keyAgreement", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_KeyAgreement, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::keyAgreement, + XFA_Attribute::KeyAgreement, XFA_ScriptType::Basic}, {0xa66404cb, L"keyEncipherment", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_KeyEncipherment, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::keyEncipherment, + XFA_Attribute::KeyEncipherment, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xca5dc27c, L"dataEncipherment", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataEncipherment, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::dataEncipherment, + XFA_Attribute::DataEncipherment, XFA_ScriptType::Basic}, {0xe8f118a8, L"keyCertSign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_KeyCertSign, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::keyCertSign, + XFA_Attribute::KeyCertSign, XFA_ScriptType::Basic}, {0xfea53ec6, L"decipherOnly", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DecipherOnly, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_KeyUsage::decipherOnly, + XFA_Attribute::DecipherOnly, XFA_ScriptType::Basic}, + + /* exclude */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x8b90e1f2, L"open", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Open, XFA_SCRIPT_Basic}, - {0x957fa006, L"commitOn", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CommitOn, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* choiceList */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ChoiceList::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x8b90e1f2, L"open", (XFA_ATTRIBUTE_CALLBACK)&CJX_ChoiceList::open, + XFA_Attribute::Open, XFA_ScriptType::Basic}, + {0x957fa006, L"commitOn", (XFA_ATTRIBUTE_CALLBACK)&CJX_ChoiceList::commitOn, + XFA_Attribute::CommitOn, XFA_ScriptType::Basic}, {0xb12128b7, L"textEntry", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TextEntry, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ChoiceList::textEntry, + XFA_Attribute::TextEntry, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ChoiceList::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* level */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* labelPrinter */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* calendarSymbols */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, - {0x2282c73, L"hAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HAlign, XFA_SCRIPT_Basic}, - {0x8d4f1c7, L"textIndent", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TextIndent, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2a82d99c, L"marginRight", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MarginRight, XFA_SCRIPT_Basic}, - {0x534729c9, L"marginLeft", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MarginLeft, XFA_SCRIPT_Basic}, - {0x5739d1ff, L"radixOffset", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RadixOffset, XFA_SCRIPT_Basic}, - {0x577682ac, L"preserve", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Preserve, XFA_SCRIPT_Basic}, - {0x731e0665, L"spaceBelow", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_SpaceBelow, XFA_SCRIPT_Basic}, - {0x7a7cc341, L"vAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_VAlign, XFA_SCRIPT_Basic}, - {0x836d4d7c, L"tabDefault", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TabDefault, XFA_SCRIPT_Basic}, - {0x8fa01790, L"tabStops", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TabStops, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd4b01921, L"lineHeight", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LineHeight, XFA_SCRIPT_Basic}, - {0xe18b5659, L"spaceAbove", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_SpaceAbove, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* para */ + {0x2282c73, L"hAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::hAlign, + XFA_Attribute::HAlign, XFA_ScriptType::Basic}, + {0x8d4f1c7, L"textIndent", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::textIndent, + XFA_Attribute::TextIndent, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2a82d99c, L"marginRight", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::marginRight, + XFA_Attribute::MarginRight, XFA_ScriptType::Basic}, + {0x534729c9, L"marginLeft", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::marginLeft, + XFA_Attribute::MarginLeft, XFA_ScriptType::Basic}, + {0x5739d1ff, L"radixOffset", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::radixOffset, + XFA_Attribute::RadixOffset, XFA_ScriptType::Basic}, + {0x577682ac, L"preserve", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::preserve, + XFA_Attribute::Preserve, XFA_ScriptType::Basic}, + {0x731e0665, L"spaceBelow", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::spaceBelow, + XFA_Attribute::SpaceBelow, XFA_ScriptType::Basic}, + {0x7a7cc341, L"vAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::vAlign, + XFA_Attribute::VAlign, XFA_ScriptType::Basic}, + {0x836d4d7c, L"tabDefault", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::tabDefault, + XFA_Attribute::TabDefault, XFA_ScriptType::Basic}, + {0x8fa01790, L"tabStops", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::tabStops, + XFA_Attribute::TabStops, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd4b01921, L"lineHeight", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::lineHeight, + XFA_Attribute::LineHeight, XFA_ScriptType::Basic}, + {0xe18b5659, L"spaceAbove", (XFA_ATTRIBUTE_CALLBACK)&CJX_Para::spaceAbove, + XFA_Attribute::SpaceAbove, XFA_ScriptType::Basic}, + + /* part */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* pdfa */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* filter */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Filter::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Filter::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xd861f8af, L"addRevocationInfo", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AddRevocationInfo, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Filter::addRevocationInfo, + XFA_Attribute::AddRevocationInfo, XFA_ScriptType::Basic}, + + /* present */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* pagination */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6128d8d, L"activity", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Activity, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* encoding */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encoding::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encoding::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* event */ + {0xbb8df5d, L"ref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Event::ref, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Event::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Event::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6128d8d, L"activity", (XFA_ATTRIBUTE_CALLBACK)&CJX_Event::activity, + XFA_Attribute::Activity, XFA_ScriptType::Basic}, + + /* whitespace */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* defaultUi */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_DefaultUi::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_DefaultUi::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* dataModel */ + + /* barcode */ {0x43e349b, L"dataRowCount", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataRowCount, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x28e17e91, L"dataPrep", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataPrep, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::dataRowCount, + XFA_Attribute::DataRowCount, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x28e17e91, L"dataPrep", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::dataPrep, + XFA_Attribute::DataPrep, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, {0x3650557e, L"textLocation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TextLocation, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::textLocation, + XFA_Attribute::TextLocation, XFA_ScriptType::Basic}, {0x3b582286, L"moduleWidth", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ModuleWidth, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::moduleWidth, + XFA_Attribute::ModuleWidth, XFA_ScriptType::Basic}, {0x52666f1c, L"printCheckDigit", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_PrintCheckDigit, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::printCheckDigit, + XFA_Attribute::PrintCheckDigit, XFA_ScriptType::Basic}, {0x5404d6df, L"moduleHeight", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ModuleHeight, XFA_SCRIPT_Basic}, - {0x5ab23b6c, L"startChar", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_StartChar, XFA_SCRIPT_Basic}, - {0x7c732a66, L"truncate", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Truncate, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::moduleHeight, + XFA_Attribute::ModuleHeight, XFA_ScriptType::Basic}, + {0x5ab23b6c, L"startChar", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::startChar, + XFA_Attribute::StartChar, XFA_ScriptType::Basic}, + {0x7c732a66, L"truncate", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::truncate, + XFA_Attribute::Truncate, XFA_ScriptType::Basic}, {0x8d181d61, L"wideNarrowRatio", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_WideNarrowRatio, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::wideNarrowRatio, + XFA_Attribute::WideNarrowRatio, XFA_ScriptType::Basic}, {0x99800d7a, L"errorCorrectionLevel", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ErrorCorrectionLevel, XFA_SCRIPT_Basic}, - {0x9a63da3d, L"upsMode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_UpsMode, XFA_SCRIPT_Basic}, - {0xaf754613, L"checksum", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Checksum, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::errorCorrectionLevel, + XFA_Attribute::ErrorCorrectionLevel, XFA_ScriptType::Basic}, + {0x9a63da3d, L"upsMode", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::upsMode, + XFA_Attribute::UpsMode, XFA_ScriptType::Basic}, + {0xaf754613, L"checksum", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::checksum, + XFA_Attribute::Checksum, XFA_ScriptType::Basic}, {0xb045fbc5, L"charEncoding", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CharEncoding, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::charEncoding, + XFA_Attribute::CharEncoding, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xc035c6b1, L"dataColumnCount", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataColumnCount, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::dataColumnCount, + XFA_Attribute::DataColumnCount, XFA_ScriptType::Basic}, {0xd3c84d25, L"rowColumnRatio", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RowColumnRatio, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::rowColumnRatio, + XFA_Attribute::RowColumnRatio, XFA_ScriptType::Basic}, {0xd57c513c, L"dataLength", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataLength, XFA_SCRIPT_Basic}, - {0xf575ca75, L"endChar", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_EndChar, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::dataLength, + XFA_Attribute::DataLength, XFA_ScriptType::Basic}, + {0xf575ca75, L"endChar", (XFA_ATTRIBUTE_CALLBACK)&CJX_Barcode::endChar, + XFA_Attribute::EndChar, XFA_ScriptType::Basic}, + + /* timePattern */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* batchOutput */ {0x28dee6e9, L"format", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Format, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Format, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* enforce */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* currencySymbols */ + + /* addSilentPrint */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* rename */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x60d4c8b1, L"output", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Output, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6a39990, L"input", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Input, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* operation */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Operation::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x60d4c8b1, L"output", (XFA_ATTRIBUTE_CALLBACK)&CJX_Operation::output, + XFA_Attribute::Output, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Operation::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6a39990, L"input", (XFA_ATTRIBUTE_CALLBACK)&CJX_Operation::input, + XFA_Attribute::Input, XFA_ScriptType::Basic}, + + /* typefaces */ + + /* subjectDNs */ + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_SubjectDNs::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + + /* issuers */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Issuers::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Issuers::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Issuers::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* signaturePseudoModel */ + + /* wsdlConnection */ {0x2b5df51e, L"dataDescription", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataDescription, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_WsdlConnection::dataDescription, + XFA_Attribute::DataDescription, XFA_ScriptType::Basic}, + + /* debug */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* delta */ {0x6c0d9600, L"currentValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Delta_CurrentValue, -1, - XFA_SCRIPT_Basic}, - {0x942643f0, L"savedValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Delta_SavedValue, -1, - XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Delta_Target, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Delta::currentValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0x942643f0, L"savedValue", (XFA_ATTRIBUTE_CALLBACK)&CJX_Delta::savedValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_Delta::target, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* eraNames */ + + /* modifyAnnots */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* startNode */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd4cc53f8, L"highlight", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Highlight, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0x5518c25, L"break", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Break, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd996fa9b, L"hand", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Hand, XFA_SCRIPT_Basic}, - {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_X, XFA_SCRIPT_Basic}, - {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Y, XFA_SCRIPT_Basic}, - {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, - {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* button */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Button::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Button::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd4cc53f8, L"highlight", (XFA_ATTRIBUTE_CALLBACK)&CJX_Button::highlight, + XFA_Attribute::Highlight, XFA_ScriptType::Basic}, + + /* format */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Format::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Format::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* border */ + {0x5518c25, L"break", (XFA_ATTRIBUTE_CALLBACK)&CJX_Border::breakValue, + XFA_Attribute::Break, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Border::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Border::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_Border::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Border::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd996fa9b, L"hand", (XFA_ATTRIBUTE_CALLBACK)&CJX_Border::hand, + XFA_Attribute::Hand, XFA_ScriptType::Basic}, + + /* area */ + {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::x, XFA_Attribute::X, + XFA_ScriptType::Basic}, + {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::y, XFA_Attribute::Y, + XFA_ScriptType::Basic}, + {0x21aed, L"id", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::id, XFA_Attribute::Id, + XFA_ScriptType::Basic}, + {0x31b19c1, L"name", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::name, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x1059ec18, L"level", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_Integer, - XFA_ATTRIBUTE_Level, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xac06e2b0, L"colSpan", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ColSpan, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_Integer, + XFA_Attribute::Level, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xac06e2b0, L"colSpan", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::colSpan, + XFA_Attribute::ColSpan, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Area::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* hyphenation */ {0x21aed, L"id", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Id, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Id, XFA_ScriptType::Basic}, {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x2f105f72, L"wordCharacterCount", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_WordCharacterCount, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::WordCharacterCount, XFA_ScriptType::Basic}, {0x3d123c26, L"hyphenate", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Hyphenate, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Hyphenate, XFA_ScriptType::Basic}, {0x66539c48, L"excludeInitialCap", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ExcludeInitialCap, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::ExcludeInitialCap, XFA_ScriptType::Basic}, {0x6a95c976, L"pushCharacterCount", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_PushCharacterCount, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::PushCharacterCount, XFA_ScriptType::Basic}, {0x982bd892, L"remainCharacterCount", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RemainCharacterCount, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::RemainCharacterCount, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xe5c96d6a, L"excludeAllCaps", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ExcludeAllCaps, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x8af2e657, L"maxChars", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxChars, XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::ExcludeAllCaps, XFA_ScriptType::Basic}, + + /* text */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Text::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x8af2e657, L"maxChars", (XFA_ATTRIBUTE_CALLBACK)&CJX_Text::maxChars, + XFA_Attribute::MaxChars, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Text::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Text::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Text::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* time */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Time::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Time::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Time::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Time::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* type */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* overprint */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc080cd3, L"url", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Url, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* certificates */ + {0xc080cd3, L"url", (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificates::url, + XFA_Attribute::Url, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificates::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xa6710262, L"credentialServerPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CredentialServerPolicy, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificates::credentialServerPolicy, + XFA_Attribute::CredentialServerPolicy, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificates::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xc2ba0923, L"urlPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_UrlPolicy, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificates::urlPolicy, + XFA_Attribute::UrlPolicy, XFA_ScriptType::Basic}, + + /* encryptionMethods */ {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Type, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* setProperty */ {0x47d03490, L"connection", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Connection, XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Target, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_SetProperty::connection, + XFA_Attribute::Connection, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_SetProperty::target, + XFA_Attribute::Target, XFA_ScriptType::Basic}, + + /* printerName */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* startPage */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* pageOffset */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* dateTime */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTime::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTime::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTime::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTime::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* comb */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Comb::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x78bff531, L"numberOfCells", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_Integer, - XFA_ATTRIBUTE_NumberOfCells, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_H, XFA_SCRIPT_Basic}, - {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_W, XFA_SCRIPT_Basic}, - {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_X, XFA_SCRIPT_Basic}, - {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Y, XFA_SCRIPT_Basic}, - {0x2282c73, L"hAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HAlign, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Comb::numberOfCells, + XFA_Attribute::NumberOfCells, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Comb::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* pattern */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Pattern::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Pattern::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Pattern::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* ifEmpty */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* suppressBanner */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* outputBin */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* field */ + {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::h, XFA_Attribute::H, + XFA_ScriptType::Basic}, + {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::w, XFA_Attribute::W, + XFA_ScriptType::Basic}, + {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::x, XFA_Attribute::X, + XFA_ScriptType::Basic}, + {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::y, XFA_Attribute::Y, + XFA_ScriptType::Basic}, + {0x2282c73, L"hAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::hAlign, + XFA_Attribute::HAlign, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x1abbd7e0, L"dataNode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DataNode, -1, - XFA_SCRIPT_Object}, - {0x25839852, L"access", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Access, XFA_SCRIPT_Basic}, - {0x2ee7678f, L"rotate", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Rotate, XFA_SCRIPT_Basic}, - {0x3b1ddd06, L"fillColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_FillColor, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DataNode, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0x25839852, L"access", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::access, + XFA_Attribute::Access, XFA_ScriptType::Basic}, + {0x2ee7678f, L"rotate", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::rotate, + XFA_Attribute::Rotate, XFA_ScriptType::Basic}, + {0x3b1ddd06, L"fillColor", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::fillColor, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x54c399e3, L"formattedValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Field_FormattedValue, -1, - XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::formattedValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, {0x5a3b375d, L"borderColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_BorderColor, -1, - XFA_SCRIPT_Basic}, - {0x5e936ed6, L"fontColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_FontColor, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::borderColor, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0x5e936ed6, L"fontColor", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::fontColor, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x6826c408, L"parentSubform", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Field_ParentSubform, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::parentSubform, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, {0x79b67434, L"mandatoryMessage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_MandatoryMessage, -1, - XFA_SCRIPT_Basic}, - {0x7a7cc341, L"vAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_VAlign, XFA_SCRIPT_Basic}, - {0x7c2ff6ae, L"maxH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxH, XFA_SCRIPT_Basic}, - {0x7c2ff6bd, L"maxW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxW, XFA_SCRIPT_Basic}, - {0x7d02356c, L"minH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinH, XFA_SCRIPT_Basic}, - {0x7d02357b, L"minW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinW, XFA_SCRIPT_Basic}, - {0x85fd6faf, L"mandatory", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_Mandatory, -1, - XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::mandatoryMessage, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x7a7cc341, L"vAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::vAlign, + XFA_Attribute::VAlign, XFA_ScriptType::Basic}, + {0x7c2ff6ae, L"maxH", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::maxH, + XFA_Attribute::MaxH, XFA_ScriptType::Basic}, + {0x7c2ff6bd, L"maxW", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::maxW, + XFA_Attribute::MaxW, XFA_ScriptType::Basic}, + {0x7d02356c, L"minH", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::minH, + XFA_Attribute::MinH, XFA_ScriptType::Basic}, + {0x7d02357b, L"minW", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::minW, + XFA_Attribute::MinW, XFA_ScriptType::Basic}, + {0x85fd6faf, L"mandatory", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::mandatory, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, {0x964fb42e, L"formatMessage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Field_FormatMessage, -1, - XFA_SCRIPT_Basic}, - {0xa03cf627, L"rawValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::formatMessage, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xa03cf627, L"rawValue", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::rawValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xa60dd202, L"length", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Field_Length, -1, - XFA_SCRIPT_Basic}, - {0xac06e2b0, L"colSpan", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ColSpan, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbc8fa350, L"locale", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Locale, XFA_SCRIPT_Basic}, - {0xc2bd40fd, L"anchorType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AnchorType, XFA_SCRIPT_Basic}, - {0xc4fed09b, L"accessKey", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AccessKey, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Field_Length, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xac06e2b0, L"colSpan", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::colSpan, + XFA_Attribute::ColSpan, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbc8fa350, L"locale", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::locale, + XFA_Attribute::Locale, XFA_ScriptType::Basic}, + {0xc2bd40fd, L"anchorType", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::anchorType, + XFA_Attribute::AnchorType, XFA_ScriptType::Basic}, + {0xc4fed09b, L"accessKey", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::accessKey, + XFA_Attribute::AccessKey, XFA_ScriptType::Basic}, {0xcabfa3d0, L"validationMessage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_ValidationMessage, -1, - XFA_SCRIPT_Basic}, - {0xdcecd663, L"editValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Field_EditValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::validationMessage, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xdcecd663, L"editValue", (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::editValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xe07e5061, L"selectedIndex", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Field_SelectedIndex, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::selectedIndex, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, {0xf65e34be, L"borderWidth", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_BorderWidth, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Field::borderWidth, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + + /* agent */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* outputXSL */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* adjustData */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* autoSave */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_H, XFA_SCRIPT_Basic}, - {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_W, XFA_SCRIPT_Basic}, - {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_X, XFA_SCRIPT_Basic}, - {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Y, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* contentArea */ + {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::H, XFA_ScriptType::Basic}, + {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::W, XFA_ScriptType::Basic}, + {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CJX_ContentArea::x, XFA_Attribute::X, + XFA_ScriptType::Basic}, + {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CJX_ContentArea::y, XFA_Attribute::Y, + XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ContentArea::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ContentArea::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ContentArea::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* eventPseudoModel */ {0xd843798, L"fullText", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::FullText, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::fullText, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x1b6d1cf5, L"reenter", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::Reenter, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::reenter, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x1e6ffa9a, L"prevContentType", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::PrevContentType, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::prevContentType, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x25a3c206, L"soapFaultString", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::SoapFaultString, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::soapFaultString, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x2e00c007, L"newContentType", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::NewContentType, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::newContentType, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x4570500f, L"modifier", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::Modifier, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::modifier, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x50e2e33b, L"selEnd", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::SelEnd, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::selEnd, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x57de87c2, L"prevText", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::PrevText, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::prevText, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x6ea04e0a, L"soapFaultCode", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::SoapFaultCode, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::soapFaultCode, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x6f6556cf, L"newText", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::NewText, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::newText, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x891f4606, L"change", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::Change, -1, - XFA_SCRIPT_Basic}, - {0x8fa3c19e, L"shift", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::Shift, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::change, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x8fa3c19e, L"shift", (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::shift, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xa9d9b2e1, L"keyDown", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::KeyDown, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::keyDown, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xbfc89db2, L"selStart", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::SelStart, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::selStart, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xc32a5812, L"commitKey", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::CommitKey, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::commitKey, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CScript_EventPseudoModel::Target, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_EventPseudoModel::target, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* wsdlAddress */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_WsdlAddress::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_WsdlAddress::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* solid */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Solid::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Solid::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* dateTimeSymbols */ + + /* encryptionLevel */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xa2e3514, L"cap", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Cap, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x5392ea58, L"stroke", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Stroke, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0x94446dcc, L"thickness", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Thickness, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x1ec8ab2c, L"rate", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Rate, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* edge */ + {0xa2e3514, L"cap", (XFA_ATTRIBUTE_CALLBACK)&CJX_Edge::cap, + XFA_Attribute::Cap, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Edge::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x5392ea58, L"stroke", (XFA_ATTRIBUTE_CALLBACK)&CJX_Edge::stroke, + XFA_Attribute::Stroke, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Edge::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0x94446dcc, L"thickness", (XFA_ATTRIBUTE_CALLBACK)&CJX_Edge::thickness, + XFA_Attribute::Thickness, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Edge::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* stipple */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Stipple::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x1ec8ab2c, L"rate", (XFA_ATTRIBUTE_CALLBACK)&CJX_Stipple::rate, + XFA_Attribute::Rate, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Stipple::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* attributes */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* versionControl */ {0x7b29630a, L"sourceBelow", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_SourceBelow, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::SourceBelow, XFA_ScriptType::Basic}, {0x8fc36c0a, L"outputBelow", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_OutputBelow, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::OutputBelow, XFA_ScriptType::Basic}, {0xe996b2fe, L"sourceAbove", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_SourceAbove, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_H, XFA_SCRIPT_Basic}, - {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_W, XFA_SCRIPT_Basic}, - {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_X, XFA_SCRIPT_Basic}, - {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Y, XFA_SCRIPT_Basic}, - {0x2282c73, L"hAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HAlign, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::SourceAbove, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* meridiem */ + + /* exclGroup */ + {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::h, XFA_Attribute::H, + XFA_ScriptType::Basic}, + {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::w, XFA_Attribute::W, + XFA_ScriptType::Basic}, + {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::x, XFA_Attribute::X, + XFA_ScriptType::Basic}, + {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::y, XFA_Attribute::Y, + XFA_ScriptType::Basic}, + {0x2282c73, L"hAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::hAlign, + XFA_Attribute::HAlign, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xf23332f, L"errorText", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_ExclGroup_ErrorText, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_ExclGroup_ErrorText, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x1abbd7e0, L"dataNode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DataNode, -1, - XFA_SCRIPT_Object}, - {0x25839852, L"access", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Access, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DataNode, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0x25839852, L"access", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::access, + XFA_Attribute::Access, XFA_ScriptType::Basic}, {0x3b1ddd06, L"fillColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_FillColor, -1, - XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::fillColor, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, {0x5a3b375d, L"borderColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_BorderColor, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::borderColor, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x79b67434, L"mandatoryMessage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_MandatoryMessage, -1, - XFA_SCRIPT_Basic}, - {0x7a7cc341, L"vAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_VAlign, XFA_SCRIPT_Basic}, - {0x7c2ff6ae, L"maxH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxH, XFA_SCRIPT_Basic}, - {0x7c2ff6bd, L"maxW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxW, XFA_SCRIPT_Basic}, - {0x7d02356c, L"minH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinH, XFA_SCRIPT_Basic}, - {0x7d02357b, L"minW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinW, XFA_SCRIPT_Basic}, - {0x7e7e845e, L"layout", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Layout, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::mandatoryMessage, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x7a7cc341, L"vAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::vAlign, + XFA_Attribute::VAlign, XFA_ScriptType::Basic}, + {0x7c2ff6ae, L"maxH", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::maxH, + XFA_Attribute::MaxH, XFA_ScriptType::Basic}, + {0x7c2ff6bd, L"maxW", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::maxW, + XFA_Attribute::MaxW, XFA_ScriptType::Basic}, + {0x7d02356c, L"minH", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::minH, + XFA_Attribute::MinH, XFA_ScriptType::Basic}, + {0x7d02357b, L"minW", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::minW, + XFA_Attribute::MinW, XFA_ScriptType::Basic}, + {0x7e7e845e, L"layout", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::layout, + XFA_Attribute::Layout, XFA_ScriptType::Basic}, {0x846599f8, L"transient", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_ExclGroup_Transient, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::transient, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, {0x85fd6faf, L"mandatory", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_Mandatory, -1, - XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xa03cf627, L"rawValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_ExclGroup_DefaultAndRawValue, - -1, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::mandatory, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xa03cf627, L"rawValue", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::rawValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_ExclGroup_DefaultAndRawValue, - -1, XFA_SCRIPT_Basic}, - {0xac06e2b0, L"colSpan", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ColSpan, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xac06e2b0, L"colSpan", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::colSpan, + XFA_Attribute::ColSpan, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xc2bd40fd, L"anchorType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AnchorType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::anchorType, + XFA_Attribute::AnchorType, XFA_ScriptType::Basic}, {0xc4fed09b, L"accessKey", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AccessKey, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::accessKey, + XFA_Attribute::AccessKey, XFA_ScriptType::Basic}, {0xcabfa3d0, L"validationMessage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_ValidationMessage, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::validationMessage, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xf65e34be, L"borderWidth", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_BorderWidth, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExclGroup::borderWidth, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* toolTip */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ToolTip::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ToolTip::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* compress */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xeda9017a, L"scope", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Scope, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Scope, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* reason */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Reason::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Reason::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* execute */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Execute::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x47d03490, L"connection", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Connection, XFA_SCRIPT_Basic}, - {0x6cfa828a, L"runAt", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RunAt, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Execute::connection, + XFA_Attribute::Connection, XFA_ScriptType::Basic}, + {0x6cfa828a, L"runAt", (XFA_ATTRIBUTE_CALLBACK)&CJX_Execute::runAt, + XFA_Attribute::RunAt, XFA_ScriptType::Basic}, {0xa1b0d2f5, L"executeType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ExecuteType, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Execute::executeType, + XFA_Attribute::ExecuteType, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Execute::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* contentCopy */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* dateTimeEdit */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTimeEdit::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTimeEdit::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xe6f99487, L"hScrollPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HScrollPolicy, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DateTimeEdit::hScrollPolicy, + XFA_Attribute::HScrollPolicy, XFA_ScriptType::Basic}, + + /* config */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* image */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x42fed1fd, L"contentType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ContentType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::contentType, + XFA_Attribute::ContentType, XFA_ScriptType::Basic}, {0x54fa722c, L"transferEncoding", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TransferEncoding, XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue_Read, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd171b240, L"aspect", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Aspect, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue_Read, -1, - XFA_SCRIPT_Basic}, - {0xdb55fec5, L"href", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Href, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::transferEncoding, + XFA_Attribute::TransferEncoding, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd171b240, L"aspect", (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::aspect, + XFA_Attribute::Aspect, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xdb55fec5, L"href", (XFA_ATTRIBUTE_CALLBACK)&CJX_Image::href, + XFA_Attribute::Href, XFA_ScriptType::Basic}, + + /* #xHTML */ {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Value, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Value, XFA_ScriptType::Basic}, + + /* numberOfCopies */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* behaviorOverride */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0x7f6fd3d7, L"server", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Server, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* timeStamp */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_TimeStamp::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_TimeStamp::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0x7f6fd3d7, L"server", (XFA_ATTRIBUTE_CALLBACK)&CJX_TimeStamp::server, + XFA_Attribute::Server, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_TimeStamp::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* month */ + + /* viewerPreferences */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* scriptModel */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* decimal */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Decimal::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x4b8bc840, L"fracDigits", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_FracDigits, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Decimal::fracDigits, + XFA_Attribute::FracDigits, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Decimal::defaultValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Decimal::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Decimal::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xde7f92ba, L"leadDigits", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LeadDigits, XFA_SCRIPT_Basic}, - {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_H, XFA_SCRIPT_Basic}, - {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_W, XFA_SCRIPT_Basic}, - {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_X, XFA_SCRIPT_Basic}, - {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Y, XFA_SCRIPT_Basic}, - {0x2282c73, L"hAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HAlign, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Decimal::leadDigits, + XFA_Attribute::LeadDigits, XFA_ScriptType::Basic}, + + /* subform */ + {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::h, XFA_Attribute::H, + XFA_ScriptType::Basic}, + {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::w, XFA_Attribute::W, + XFA_ScriptType::Basic}, + {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::x, XFA_Attribute::X, + XFA_ScriptType::Basic}, + {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::y, XFA_Attribute::Y, + XFA_ScriptType::Basic}, + {0x2282c73, L"hAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::hAlign, + XFA_Attribute::HAlign, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x1414d431, L"allowMacro", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AllowMacro, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::allowMacro, + XFA_Attribute::AllowMacro, XFA_ScriptType::Basic}, {0x1517dfa1, L"columnWidths", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ColumnWidths, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::columnWidths, + XFA_Attribute::ColumnWidths, XFA_ScriptType::Basic}, {0x1abbd7e0, L"dataNode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DataNode, -1, - XFA_SCRIPT_Object}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DataNode, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, {0x1ee2d24d, L"instanceIndex", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_InstanceIndex, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::instanceIndex, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x25839852, L"access", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Access, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + + XFA_Attribute::Access, XFA_ScriptType::Basic}, {0x3b1ddd06, L"fillColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_FillColor, -1, - XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_FillColor, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, {0x5a3b375d, L"borderColor", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_BorderColor, -1, - XFA_SCRIPT_Basic}, - {0x7a7cc341, L"vAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_VAlign, XFA_SCRIPT_Basic}, - {0x7c2ff6ae, L"maxH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxH, XFA_SCRIPT_Basic}, - {0x7c2ff6bd, L"maxW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxW, XFA_SCRIPT_Basic}, - {0x7d02356c, L"minH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinH, XFA_SCRIPT_Basic}, - {0x7d02357b, L"minW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinW, XFA_SCRIPT_Basic}, - {0x7e7e845e, L"layout", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Layout, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_BorderColor, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x7a7cc341, L"vAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::vAlign, + XFA_Attribute::VAlign, XFA_ScriptType::Basic}, + {0x7c2ff6ae, L"maxH", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::maxH, + XFA_Attribute::MaxH, XFA_ScriptType::Basic}, + {0x7c2ff6bd, L"maxW", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::maxW, + XFA_Attribute::MaxW, XFA_ScriptType::Basic}, + {0x7d02356c, L"minH", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::minH, + XFA_Attribute::MinH, XFA_ScriptType::Basic}, + {0x7d02357b, L"minW", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::minW, + XFA_Attribute::MinW, XFA_ScriptType::Basic}, + {0x7e7e845e, L"layout", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::layout, + XFA_Attribute::Layout, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, {0x9cc17d75, L"mergeMode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MergeMode, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + + XFA_Attribute::MergeMode, XFA_ScriptType::Basic}, {0x9f3e9510, L"instanceManager", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Subform_InstanceManager, -1, - XFA_SCRIPT_Object}, - {0xac06e2b0, L"colSpan", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ColSpan, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbc8fa350, L"locale", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Subform_Locale, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Subform_InstanceManager, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0xac06e2b0, L"colSpan", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::colSpan, + XFA_Attribute::ColSpan, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbc8fa350, L"locale", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::locale, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xc2bd40fd, L"anchorType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AnchorType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::anchorType, + XFA_Attribute::AnchorType, XFA_ScriptType::Basic}, {0xcabfa3d0, L"validationMessage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_ValidationMessage, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::validationMessage, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xe4c3a5e5, L"restoreState", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RestoreState, XFA_SCRIPT_Basic}, - {0xeda9017a, L"scope", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Scope, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::restoreState, + XFA_Attribute::RestoreState, XFA_ScriptType::Basic}, + {0xeda9017a, L"scope", (XFA_ATTRIBUTE_CALLBACK)&CJX_Subform::scope, + XFA_Attribute::Scope, XFA_ScriptType::Basic}, {0xf65e34be, L"borderWidth", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_BorderWidth, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_BorderWidth, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* select */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Select::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Select::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* window */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* localeSet */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0x5a50e9e6, L"version", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Handler_Version, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0x31b19c1, L"name", (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::Name, - -1, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* handler */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Handler::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Handler::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0x5a50e9e6, L"version", (XFA_ATTRIBUTE_CALLBACK)&CJX_Handler::version, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Handler::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* hostPseudoModel */ + {0x31b19c1, L"name", (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::name, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x66c1ae9, L"validationsEnabled", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::ValidationsEnabled, -1, - XFA_SCRIPT_Basic}, - {0x14d04502, L"title", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::Title, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::validationsEnabled, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x14d04502, L"title", (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::title, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x392ae445, L"platform", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::Platform, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::platform, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x5a50e9e6, L"version", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::Version, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::version, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x66cb1eed, L"variation", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::Variation, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::variation, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x7717cbc4, L"language", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::Language, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::language, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x86698963, L"appType", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::AppType, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::appType, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x94ff9e8d, L"calculationsEnabled", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::CalculationsEnabled, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::calculationsEnabled, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xbcd44940, L"currentPage", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::CurrentPage, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::currentPage, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xd592b920, L"numPages", - (XFA_ATTRIBUTE_CALLBACK)&CScript_HostPseudoModel::NumPages, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_HostPseudoModel::numPages, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* presence */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* record */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* embed */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* version */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x24d85167, L"timeout", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Timeout, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* command */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Command::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x24d85167, L"timeout", (XFA_ATTRIBUTE_CALLBACK)&CJX_Command::timeout, + XFA_Attribute::Timeout, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Command::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* copies */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* staple */ {0x7d9fd7c5, L"mode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Mode, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Mode, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* submitFormat */ {0x7d9fd7c5, L"mode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_SubmitFormat_Mode, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_SubmitFormat_Mode, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* boolean */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Boolean::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Boolean::defaultValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Boolean::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Boolean::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* message */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Message::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Message::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* output */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* psMap */ + + /* excludeNS */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2038c9b2, L"role", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Role, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* assist */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Assist::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2038c9b2, L"role", (XFA_ATTRIBUTE_CALLBACK)&CJX_Assist::role, + XFA_Attribute::Role, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Assist::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* picture */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Picture::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Picture::defaultValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Picture::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Picture::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* traversal */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Traversal::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Traversal::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* silentPrint */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* webClient */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* layoutPseudoModel */ {0xfcef86b5, L"ready", - (XFA_ATTRIBUTE_CALLBACK)&CScript_LayoutPseudoModel::Ready, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_LayoutPseudoModel::ready, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* producer */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x5392ea58, L"stroke", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Stroke, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0x7b95e661, L"inverted", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Inverted, XFA_SCRIPT_Basic}, - {0x94446dcc, L"thickness", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Thickness, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xe8dddf50, L"join", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Join, XFA_SCRIPT_Basic}, - {0xe948b9a8, L"radius", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Radius, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xabfa6c4f, L"cSpace", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CSpace, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Value, XFA_SCRIPT_Basic}, - {0x3848b3f, L"next", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Next, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x6a3405dd, L"previous", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Previous, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xf6b59543, L"intact", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Intact, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* corner */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x5392ea58, L"stroke", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::stroke, + XFA_Attribute::Stroke, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0x7b95e661, L"inverted", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::inverted, + XFA_Attribute::Inverted, XFA_ScriptType::Basic}, + {0x94446dcc, L"thickness", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::thickness, + XFA_Attribute::Thickness, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xe8dddf50, L"join", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::join, + XFA_Attribute::Join, XFA_ScriptType::Basic}, + {0xe948b9a8, L"radius", (XFA_ATTRIBUTE_CALLBACK)&CJX_Corner::radius, + XFA_Attribute::Radius, XFA_ScriptType::Basic}, + + /* msgId */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* color */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Color::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xabfa6c4f, L"cSpace", (XFA_ATTRIBUTE_CALLBACK)&CJX_Color::cSpace, + XFA_Attribute::CSpace, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Color::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Color::value, + XFA_Attribute::Value, XFA_ScriptType::Basic}, + + /* keep */ + {0x3848b3f, L"next", (XFA_ATTRIBUTE_CALLBACK)&CJX_Keep::next, + XFA_Attribute::Next, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Keep::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x6a3405dd, L"previous", (XFA_ATTRIBUTE_CALLBACK)&CJX_Keep::previous, + XFA_Attribute::Previous, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Keep::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xf6b59543, L"intact", (XFA_ATTRIBUTE_CALLBACK)&CJX_Keep::intact, + XFA_Attribute::Intact, XFA_ScriptType::Basic}, + + /* query */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Query::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x268b7ec1, L"commandType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CommandType, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbde9abda, L"data", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Data, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Query::commandType, + XFA_Attribute::CommandType, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Query::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* insert */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Insert::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Insert::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* imageEdit */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ImageEdit::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ImageEdit::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbde9abda, L"data", (XFA_ATTRIBUTE_CALLBACK)&CJX_ImageEdit::data, + XFA_Attribute::Data, XFA_ScriptType::Basic}, + + /* validate */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Validate::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x5b707a35, L"scriptTest", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ScriptTest, XFA_SCRIPT_Basic}, - {0x6b6ddcfb, L"nullTest", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_NullTest, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Validate::scriptTest, + XFA_Attribute::ScriptTest, XFA_ScriptType::Basic}, + {0x6b6ddcfb, L"nullTest", (XFA_ATTRIBUTE_CALLBACK)&CJX_Validate::nullTest, + XFA_Attribute::NullTest, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Validate::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xe64b1129, L"formatTest", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_FormatTest, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Validate::formatTest, + XFA_Attribute::FormatTest, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x8c99377e, L"relation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relation, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* digestMethods */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_DigestMethods::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_DigestMethods::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", + (XFA_ATTRIBUTE_CALLBACK)&CJX_DigestMethods::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* numberPatterns */ + + /* pageSet */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageSet::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x8c99377e, L"relation", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageSet::relation, + XFA_Attribute::Relation, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageSet::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageSet::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* integer */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Integer::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Integer::defaultValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Integer::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Integer::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* soapAddress */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_SoapAddress::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_SoapAddress::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* equate */ {0x25363, L"to", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_To, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::To, XFA_ScriptType::Basic}, {0x66642f8f, L"force", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Force, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Force, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xcd7f7b54, L"from", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_From, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::From, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* formFieldFilling */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* pageRange */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* update */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Update::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Update::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* connectString */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ConnectString::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ConnectString::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* mode */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* layout */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* #xml */ {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Value, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Value, XFA_ScriptType::Basic}, + + /* xsdConnection */ {0x2b5df51e, L"dataDescription", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataDescription, XFA_SCRIPT_Basic}, - {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x226ca8f1, L"operation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Operation, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_XsdConnection::dataDescription, + XFA_Attribute::DataDescription, XFA_ScriptType::Basic}, + + /* traverse */ + {0xbb8df5d, L"ref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Traverse::ref, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Traverse::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x226ca8f1, L"operation", (XFA_ATTRIBUTE_CALLBACK)&CJX_Traverse::operation, + XFA_Attribute::Operation, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Traverse::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* encodings */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encodings::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encodings::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encodings::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* template */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* acrobat */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* validationMessaging */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* signing */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Signing::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Signing::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Signing::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* dataWindow */ {0xfb67185, L"recordsBefore", - (XFA_ATTRIBUTE_CALLBACK)&CScript_DataWindow::RecordsBefore, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DataWindow::recordsBefore, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x21d5dfcb, L"currentRecordNumber", - (XFA_ATTRIBUTE_CALLBACK)&CScript_DataWindow::CurrentRecordNumber, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DataWindow::currentRecordNumber, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x312af044, L"recordsAfter", - (XFA_ATTRIBUTE_CALLBACK)&CScript_DataWindow::RecordsAfter, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DataWindow::recordsAfter, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0x6aab37cb, L"isDefined", - (XFA_ATTRIBUTE_CALLBACK)&CScript_DataWindow::IsDefined, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DataWindow::isDefined, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + + /* script */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x42fed1fd, L"contentType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ContentType, XFA_SCRIPT_Basic}, - {0x6cfa828a, L"runAt", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_RunAt, XFA_SCRIPT_Basic}, - {0xa021b738, L"stateless", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Script_Stateless, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::contentType, + XFA_Attribute::ContentType, XFA_ScriptType::Basic}, + {0x6cfa828a, L"runAt", (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::runAt, + XFA_Attribute::RunAt, XFA_ScriptType::Basic}, + {0xa021b738, L"stateless", (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::stateless, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xadc4c77b, L"binding", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Binding, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::defaultValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xadc4c77b, L"binding", (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::binding, + XFA_Attribute::Binding, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Script::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* addViewerPreferences */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* alwaysEmbed */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* passwordEdit */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_PasswordEdit::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x7a0cc471, L"passwordChar", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_PasswordChar, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_PasswordEdit::passwordChar, + XFA_Attribute::PasswordChar, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_PasswordEdit::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xe6f99487, L"hScrollPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HScrollPolicy, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_PasswordEdit::hScrollPolicy, + XFA_Attribute::HScrollPolicy, XFA_ScriptType::Basic}, + + /* numericEdit */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_NumericEdit::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_NumericEdit::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xe6f99487, L"hScrollPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HScrollPolicy, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_NumericEdit::hScrollPolicy, + XFA_Attribute::HScrollPolicy, XFA_ScriptType::Basic}, + + /* encryptionMethod */ {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* change */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* pageArea */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x14a32d52, L"pagePosition", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_PagePosition, XFA_SCRIPT_Basic}, - {0x8340ea66, L"oddOrEven", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_OddOrEven, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::pagePosition, + XFA_Attribute::PagePosition, XFA_ScriptType::Basic}, + {0x8340ea66, L"oddOrEven", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::oddOrEven, + XFA_Attribute::OddOrEven, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, {0xa85e74f3, L"initialNumber", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_InitialNumber, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe9ba472, L"numbered", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Numbered, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::initialNumber, + XFA_Attribute::InitialNumber, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbe9ba472, L"numbered", (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::numbered, + XFA_Attribute::Numbered, XFA_ScriptType::Basic}, {0xd70798c2, L"blankOrNotBlank", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BlankOrNotBlank, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_PageArea::blankOrNotBlank, + XFA_Attribute::BlankOrNotBlank, XFA_ScriptType::Basic}, + + /* submitUrl */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DefaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* oids */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Oids::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Oids::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Oids::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* signature */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Signature::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Signature::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* aDBE_JSConsole */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x34ae103c, L"reserve", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Reserve, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xf2009339, L"placement", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Placement, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* caption */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Caption::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x34ae103c, L"reserve", (XFA_ATTRIBUTE_CALLBACK)&CJX_Caption::reserve, + XFA_Attribute::Reserve, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Caption::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Caption::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xf2009339, L"placement", (XFA_ATTRIBUTE_CALLBACK)&CJX_Caption::placement, + XFA_Attribute::Placement, XFA_ScriptType::Basic}, + + /* relevant */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* flipLabel */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* exData */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x42fed1fd, L"contentType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ContentType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::contentType, + XFA_Attribute::ContentType, XFA_ScriptType::Basic}, {0x54fa722c, L"transferEncoding", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TransferEncoding, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::transferEncoding, + XFA_Attribute::TransferEncoding, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc4547a08, L"maxLength", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxLength, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::defaultValue, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xc4547a08, L"maxLength", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::maxLength, + XFA_Attribute::MaxLength, XFA_ScriptType::Basic}, {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xdb55fec5, L"href", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Href, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DefaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xdb55fec5, L"href", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExData::href, + XFA_Attribute::Href, XFA_ScriptType::Basic}, + + /* dayNames */ {0x29418bb7, L"abbr", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Abbr, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Abbr, XFA_ScriptType::Basic}, + + /* soapAction */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_SoapAction::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_SoapAction::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* defaultTypeface */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf531b059, L"writingScript", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_WritingScript, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::WritingScript, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x1b8dce3e, L"action", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Action, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* manifest */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Manifest::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x1b8dce3e, L"action", (XFA_ATTRIBUTE_CALLBACK)&CJX_Manifest::action, + XFA_Attribute::Action, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x9dcc3ab3, L"trailer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Trailer, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Target, XFA_SCRIPT_Basic}, - {0xcbcaf66d, L"leader", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Leader, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Manifest::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Manifest::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* overflow */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Overflow::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x9dcc3ab3, L"trailer", (XFA_ATTRIBUTE_CALLBACK)&CJX_Overflow::trailer, + XFA_Attribute::Trailer, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Overflow::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_Overflow::target, + XFA_Attribute::Target, XFA_ScriptType::Basic}, + {0xcbcaf66d, L"leader", (XFA_ATTRIBUTE_CALLBACK)&CJX_Overflow::leader, + XFA_Attribute::Leader, XFA_ScriptType::Basic}, + + /* linear */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Linear::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Linear::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Linear::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* currencySymbol */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xb3543a6, L"max", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_InstanceManager_Max, -1, - XFA_SCRIPT_Basic}, - {0xb356ca4, L"min", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_InstanceManager_Min, -1, - XFA_SCRIPT_Basic}, - {0x6f544d49, L"count", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_InstanceManager_Count, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* delete */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Delete::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Delete::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* deltas */ + + /* digestMethod */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_DigestMethod::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_DigestMethod::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* instanceManager */ + {0xb3543a6, L"max", (XFA_ATTRIBUTE_CALLBACK)&CJX_InstanceManager::max, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xb356ca4, L"min", (XFA_ATTRIBUTE_CALLBACK)&CJX_InstanceManager::min, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x6f544d49, L"count", (XFA_ATTRIBUTE_CALLBACK)&CJX_InstanceManager::count, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* equateRange */ {0x25363, L"to", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_To, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::To, XFA_ScriptType::Basic}, {0xa0933954, L"unicodeRange", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_UnicodeRange, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::UnicodeRange, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xcd7f7b54, L"from", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_From, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::From, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* medium */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x4ef3d02c, L"orientation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Orientation, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::orientation, + XFA_Attribute::Orientation, XFA_ScriptType::Basic}, {0x65e30c67, L"imagingBBox", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ImagingBBox, XFA_SCRIPT_Basic}, - {0x9041d4b0, L"short", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Short, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xe349d044, L"stock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Stock, XFA_SCRIPT_Basic}, - {0xf6b4afb0, L"long", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Long, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::imagingBBox, + XFA_Attribute::ImagingBBox, XFA_ScriptType::Basic}, + {0x9041d4b0, L"short", (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::shortValue, + XFA_Attribute::Short, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xe349d044, L"stock", (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::stock, + XFA_Attribute::Stock, XFA_ScriptType::Basic}, + {0xf6b4afb0, L"long", (XFA_ATTRIBUTE_CALLBACK)&CJX_Medium::longValue, + XFA_Attribute::Long, XFA_ScriptType::Basic}, + + /* textEdit */ {0x5ce6195, L"vScrollPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_VScrollPolicy, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_TextEdit::vScrollPolicy, + XFA_Attribute::VScrollPolicy, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_TextEdit::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x1ef3a64a, L"allowRichText", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AllowRichText, XFA_SCRIPT_Basic}, - {0x5a32e493, L"multiLine", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MultiLine, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_TextEdit::allowRichText, + XFA_Attribute::AllowRichText, XFA_ScriptType::Basic}, + {0x5a32e493, L"multiLine", (XFA_ATTRIBUTE_CALLBACK)&CJX_TextEdit::multiLine, + XFA_Attribute::MultiLine, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_TextEdit::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xe6f99487, L"hScrollPolicy", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HScrollPolicy, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_TextEdit::hScrollPolicy, + XFA_Attribute::HScrollPolicy, XFA_ScriptType::Basic}, + + /* templateCache */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xd52482e0, L"maxEntries", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxEntries, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::MaxEntries, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* compressObjectStream */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* dataValue */ {0x42fed1fd, L"contentType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ContentType, XFA_SCRIPT_Basic}, - {0x8855805f, L"contains", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Contains, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DataValue::contentType, + XFA_Attribute::ContentType, XFA_ScriptType::Basic}, + {0x8855805f, L"contains", (XFA_ATTRIBUTE_CALLBACK)&CJX_DataValue::contains, + XFA_Attribute::Contains, XFA_ScriptType::Basic}, {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xe372ae97, L"isNull", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_IsNull, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_DataValue::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_DataValue::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xe372ae97, L"isNull", (XFA_ATTRIBUTE_CALLBACK)&CJX_DataValue::isNull, + XFA_Attribute::IsNull, XFA_ScriptType::Basic}, + + /* accessibleContent */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* nodeList */ + + /* includeXDPContent */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* xmlConnection */ {0x2b5df51e, L"dataDescription", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DataDescription, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_XmlConnection::dataDescription, + XFA_Attribute::DataDescription, XFA_ScriptType::Basic}, + + /* validateApprovalSignatures */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x226ca8f1, L"operation", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Operation, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Target, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* signData */ + {0xbb8df5d, L"ref", (XFA_ATTRIBUTE_CALLBACK)&CJX_SignData::ref, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_SignData::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x226ca8f1, L"operation", (XFA_ATTRIBUTE_CALLBACK)&CJX_SignData::operation, + XFA_Attribute::Operation, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_SignData::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_SignData::target, + XFA_Attribute::Target, XFA_ScriptType::Basic}, + + /* packets */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* datePattern */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* duplexOption */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* base */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x42fed1fd, L"contentType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ContentType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* bind */ + {0xbb8df5d, L"ref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bind::ref, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bind::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x42fed1fd, L"contentType", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bind::contentType, + XFA_Attribute::ContentType, XFA_ScriptType::Basic}, {0x54fa722c, L"transferEncoding", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TransferEncoding, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xf197844d, L"match", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Match, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Bind::transferEncoding, + XFA_Attribute::TransferEncoding, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bind::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xf197844d, L"match", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bind::match, + XFA_Attribute::Match, XFA_ScriptType::Basic}, + + /* compression */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd996fa9b, L"hand", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Hand, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* user */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_User::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_User::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* rectangle */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Rectangle::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Rectangle::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd996fa9b, L"hand", (XFA_ATTRIBUTE_CALLBACK)&CJX_Rectangle::hand, + XFA_Attribute::Hand, XFA_ScriptType::Basic}, + + /* effectiveOutputPolicy */ {0x21aed, L"id", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Id, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Id, XFA_ScriptType::Basic}, {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* aDBE_JSDebugger */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* acrobat7 */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* interactive */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* locale */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* currentPage */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* data */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x28dee6e9, L"format", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Encrypt_Format, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_H, XFA_SCRIPT_Basic}, - {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_W, XFA_SCRIPT_Basic}, - {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_X, XFA_SCRIPT_Basic}, - {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Y, XFA_SCRIPT_Basic}, - {0x2282c73, L"hAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_HAlign, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2ee7678f, L"rotate", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Rotate, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0x7a7cc341, L"vAlign", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_VAlign, XFA_SCRIPT_Basic}, - {0x7c2ff6ae, L"maxH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxH, XFA_SCRIPT_Basic}, - {0x7c2ff6bd, L"maxW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MaxW, XFA_SCRIPT_Basic}, - {0x7d02356c, L"minH", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinH, XFA_SCRIPT_Basic}, - {0x7d02357b, L"minW", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_MinW, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xa03cf627, L"rawValue", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xac06e2b0, L"colSpan", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ColSpan, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbc8fa350, L"locale", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Locale, XFA_SCRIPT_Basic}, - {0xc2bd40fd, L"anchorType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_AnchorType, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* date */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Date::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Date::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Date::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Date::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* desc */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Desc::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Desc::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* encrypt */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encrypt::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x28dee6e9, L"format", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encrypt::format, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Encrypt::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* draw */ + {0x68, L"h", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::h, XFA_Attribute::H, + XFA_ScriptType::Basic}, + {0x77, L"w", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::w, XFA_Attribute::W, + XFA_ScriptType::Basic}, + {0x78, L"x", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::x, XFA_Attribute::X, + XFA_ScriptType::Basic}, + {0x79, L"y", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::y, XFA_Attribute::Y, + XFA_ScriptType::Basic}, + {0x2282c73, L"hAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::hAlign, + XFA_Attribute::HAlign, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2ee7678f, L"rotate", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::rotate, + XFA_Attribute::Rotate, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0x7a7cc341, L"vAlign", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::vAlign, + XFA_Attribute::VAlign, XFA_ScriptType::Basic}, + {0x7c2ff6ae, L"maxH", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::maxH, + XFA_Attribute::MaxH, XFA_ScriptType::Basic}, + {0x7c2ff6bd, L"maxW", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::maxW, + XFA_Attribute::MaxW, XFA_ScriptType::Basic}, + {0x7d02356c, L"minH", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::minH, + XFA_Attribute::MinH, XFA_ScriptType::Basic}, + {0x7d02357b, L"minW", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::minW, + XFA_Attribute::MinW, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xa03cf627, L"rawValue", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::rawValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xac06e2b0, L"colSpan", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::colSpan, + XFA_Attribute::ColSpan, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbc8fa350, L"locale", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::locale, + XFA_Attribute::Locale, XFA_ScriptType::Basic}, + {0xc2bd40fd, L"anchorType", (XFA_ATTRIBUTE_CALLBACK)&CJX_Draw::anchorType, + XFA_Attribute::AnchorType, XFA_ScriptType::Basic}, + + /* encryption */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* meridiemNames */ + + /* messaging */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x39cdb0a2, L"priority", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Priority, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xeb511b54, L"disable", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Disable, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* speak */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Speak::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x39cdb0a2, L"priority", (XFA_ATTRIBUTE_CALLBACK)&CJX_Speak::priority, + XFA_Attribute::Priority, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Speak::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xeb511b54, L"disable", (XFA_ATTRIBUTE_CALLBACK)&CJX_Speak::disable, + XFA_Attribute::Disable, XFA_ScriptType::Basic}, + + /* dataGroup */ + + /* common */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* #text */ {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Value, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Value, XFA_ScriptType::Basic}, + + /* paginationOverride */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* reasons */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Reasons::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Reasons::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Reasons::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* signatureProperties */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_SignatureProperties::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_SignatureProperties::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* threshold */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* appearanceFilter */ {0x21aed, L"id", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Id, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Id, XFA_ScriptType::Basic}, {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Type, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xcb0ac9, L"lineThrough", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LineThrough, XFA_SCRIPT_Basic}, - {0x2c1c7f1, L"typeface", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Typeface, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* fill */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Fill::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Fill::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Fill::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* font */ + {0xcb0ac9, L"lineThrough", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::lineThrough, + XFA_Attribute::LineThrough, XFA_ScriptType::Basic}, + {0x2c1c7f1, L"typeface", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::typeface, + XFA_Attribute::Typeface, XFA_ScriptType::Basic}, {0x8c74ae9, L"fontHorizontalScale", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_FontHorizontalScale, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2cd79033, L"kerningMode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_KerningMode, XFA_SCRIPT_Basic}, - {0x3a0273a6, L"underline", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Underline, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::fontHorizontalScale, + XFA_Attribute::FontHorizontalScale, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2cd79033, L"kerningMode", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::kerningMode, + XFA_Attribute::KerningMode, XFA_ScriptType::Basic}, + {0x3a0273a6, L"underline", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::underline, + XFA_Attribute::Underline, XFA_ScriptType::Basic}, {0x4873c601, L"baselineShift", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_BaselineShift, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::baselineShift, + XFA_Attribute::BaselineShift, XFA_ScriptType::Basic}, {0x4b319767, L"overlinePeriod", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_OverlinePeriod, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::overlinePeriod, + XFA_Attribute::OverlinePeriod, XFA_ScriptType::Basic}, {0x79543055, L"letterSpacing", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LetterSpacing, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::letterSpacing, + XFA_Attribute::LetterSpacing, XFA_ScriptType::Basic}, {0x8ec6204c, L"lineThroughPeriod", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LineThroughPeriod, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::lineThroughPeriod, + XFA_Attribute::LineThroughPeriod, XFA_ScriptType::Basic}, {0x907c7719, L"fontVerticalScale", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_FontVerticalScale, XFA_SCRIPT_Basic}, - {0xa686975b, L"size", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Size, XFA_SCRIPT_Basic}, - {0xb5e49bf2, L"posture", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Posture, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xbd6e1d88, L"weight", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Weight, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::fontVerticalScale, + XFA_Attribute::FontVerticalScale, XFA_ScriptType::Basic}, + {0xa686975b, L"size", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::size, + XFA_Attribute::Size, XFA_ScriptType::Basic}, + {0xb5e49bf2, L"posture", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::posture, + XFA_Attribute::Posture, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xbd6e1d88, L"weight", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::weight, + XFA_Attribute::Weight, XFA_ScriptType::Basic}, {0xbd96a0e9, L"underlinePeriod", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_UnderlinePeriod, XFA_SCRIPT_Basic}, - {0xc0ec9fa4, L"overline", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Overline, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::underlinePeriod, + XFA_Attribute::UnderlinePeriod, XFA_ScriptType::Basic}, + {0xc0ec9fa4, L"overline", (XFA_ATTRIBUTE_CALLBACK)&CJX_Font::overline, + XFA_Attribute::Overline, XFA_ScriptType::Basic}, + + /* form */ {0xaf754613, L"checksum", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Form_Checksum, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Form_Checksum, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* mediumInfo */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* certificate */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificate::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Certificate::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* password */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Password::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Password::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* runScripts */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* trace */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* float */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Float::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xa52682bd, L"{default}", (XFA_ATTRIBUTE_CALLBACK)&CJX_Float::defaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Float::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd6e27f1d, L"value", (XFA_ATTRIBUTE_CALLBACK)&CJX_Float::value, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* renderPolicy */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* logPseudoModel */ + + /* destination */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x8e1c2921, L"relevant", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Relevant, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xea7090a0, L"override", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Override, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x9dcc3ab3, L"trailer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Trailer, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xcbcaf66d, L"leader", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Leader, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x60a61edd, L"codeType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CodeType, XFA_SCRIPT_Basic}, - {0xb373a862, L"archive", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Archive, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xe1a26b56, L"codeBase", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_CodeBase, XFA_SCRIPT_Basic}, - {0xeb091003, L"classId", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ClassId, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* value */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Value::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x8e1c2921, L"relevant", (XFA_ATTRIBUTE_CALLBACK)&CJX_Value::relevant, + XFA_Attribute::Relevant, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Value::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xea7090a0, L"override", (XFA_ATTRIBUTE_CALLBACK)&CJX_Value::override, + XFA_Attribute::Override, XFA_ScriptType::Basic}, + + /* bookend */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bookend::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x9dcc3ab3, L"trailer", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bookend::trailer, + XFA_Attribute::Trailer, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bookend::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xcbcaf66d, L"leader", (XFA_ATTRIBUTE_CALLBACK)&CJX_Bookend::leader, + XFA_Attribute::Leader, XFA_ScriptType::Basic}, + + /* exObject */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExObject::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x60a61edd, L"codeType", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExObject::codeType, + XFA_Attribute::CodeType, XFA_ScriptType::Basic}, + {0xb373a862, L"archive", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExObject::archive, + XFA_Attribute::Archive, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExObject::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xe1a26b56, L"codeBase", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExObject::codeBase, + XFA_Attribute::CodeBase, XFA_ScriptType::Basic}, + {0xeb091003, L"classId", (XFA_ATTRIBUTE_CALLBACK)&CJX_ExObject::classId, + XFA_Attribute::ClassId, XFA_ScriptType::Basic}, + + /* openAction */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* neverEmbed */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* bindItems */ {0x47d03490, L"connection", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Connection, XFA_SCRIPT_Basic}, - {0xc39a88bd, L"labelRef", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_LabelRef, XFA_SCRIPT_Basic}, - {0xd50f903a, L"valueRef", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_ValueRef, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xea7090a0, L"override", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Override, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_BindItems::connection, + XFA_Attribute::Connection, XFA_ScriptType::Basic}, + {0xc39a88bd, L"labelRef", (XFA_ATTRIBUTE_CALLBACK)&CJX_BindItems::labelRef, + XFA_Attribute::LabelRef, XFA_ScriptType::Basic}, + {0xd50f903a, L"valueRef", (XFA_ATTRIBUTE_CALLBACK)&CJX_BindItems::valueRef, + XFA_Attribute::ValueRef, XFA_ScriptType::Basic}, + + /* calculate */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Calculate::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Calculate::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xea7090a0, L"override", (XFA_ATTRIBUTE_CALLBACK)&CJX_Calculate::override, + XFA_Attribute::Override, XFA_ScriptType::Basic}, + + /* print */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Extras_Type, -1, - XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* extras */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Extras::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Extras::type, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Extras::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* proto */ + + /* dSigData */ + + /* creator */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x24d85167, L"timeout", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Timeout, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* connect */ + {0xbb8df5d, L"ref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::ref, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x24d85167, L"timeout", (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::timeout, + XFA_Attribute::Timeout, XFA_ScriptType::Basic}, {0x47d03490, L"connection", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Connection, XFA_SCRIPT_Basic}, - {0x552d9ad5, L"usage", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usage, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::connection, + XFA_Attribute::Connection, XFA_ScriptType::Basic}, + {0x552d9ad5, L"usage", (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::usage, + XFA_Attribute::Usage, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, {0xc860f30a, L"delayedOpen", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_DelayedOpen, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Connect::delayedOpen, + XFA_Attribute::DelayedOpen, XFA_ScriptType::Basic}, + + /* permissions */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x28dee6e9, L"format", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Format, XFA_SCRIPT_Basic}, - {0x824f21b7, L"embedPDF", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_EmbedPDF, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Target, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* connectionSet */ + + /* submit */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x28dee6e9, L"format", (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::format, + XFA_Attribute::Format, XFA_ScriptType::Basic}, + {0x824f21b7, L"embedPDF", (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::embedPDF, + XFA_Attribute::EmbedPDF, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::target, + XFA_Attribute::Target, XFA_ScriptType::Basic}, {0xdc75676c, L"textEncoding", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TextEncoding, XFA_SCRIPT_Basic}, - {0xf889e747, L"xdpContent", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_XdpContent, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, - {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0x97be91b, L"content", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Packet_Content, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::textEncoding, + XFA_Attribute::TextEncoding, XFA_ScriptType::Basic}, + {0xf889e747, L"xdpContent", (XFA_ATTRIBUTE_CALLBACK)&CJX_Submit::xdpContent, + XFA_Attribute::XdpContent, XFA_ScriptType::Basic}, + + /* range */ + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* linearized */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xf6b47749, L"lock", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* packet */ + {0x97be91b, L"content", (XFA_ATTRIBUTE_CALLBACK)&CJX_Packet::content, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* rootElement */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_RootElement::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_RootElement::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* plaintextMetadata */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, + {0xbe52dfbf, L"desc", + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* numberSymbols */ + + /* printHighQuality */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* driver */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* incrementalLoad */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* subjectDN */ {0x4156ee3f, L"delimiter", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Delimiter, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_SubjectDN::delimiter, + XFA_Attribute::Delimiter, XFA_ScriptType::Basic}, + + /* compressLogicalStructure */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* incrementalMerge */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* radial */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Radial::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x2f16a382, L"type", (XFA_ATTRIBUTE_CALLBACK)&CJX_Radial::type, + XFA_Attribute::Type, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Radial::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* variables */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Variables::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Variables::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* timePatterns */ + + /* effectiveInputPolicy */ {0x21aed, L"id", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Id, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Id, XFA_ScriptType::Basic}, {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* nameAttr */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* conformance */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* transform */ {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* lockDocument */ {0x21aed, L"id", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Id, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Id, XFA_ScriptType::Basic}, {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Use, XFA_ScriptType::Basic}, {0x2f16a382, L"type", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Type, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Type, XFA_ScriptType::Basic}, {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x453eaf38, L"startNew", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_StartNew, XFA_SCRIPT_Basic}, - {0x9dcc3ab3, L"trailer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Trailer, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* breakAfter */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x453eaf38, L"startNew", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::startNew, + XFA_Attribute::StartNew, XFA_ScriptType::Basic}, + {0x9dcc3ab3, L"trailer", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::trailer, + XFA_Attribute::Trailer, XFA_ScriptType::Basic}, {0xa6118c89, L"targetType", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_TargetType, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xc8da4da7, L"target", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Target, XFA_SCRIPT_Basic}, - {0xcbcaf66d, L"leader", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Leader, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xabef37e3, L"slope", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Slope, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xd996fa9b, L"hand", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Hand, XFA_SCRIPT_Basic}, - {0xa60dd202, L"length", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_NodeList::Script_ListClass_Length, -1, - XFA_SCRIPT_Basic}, - {0x20146, L"db", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Source_Db, -1, - XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xb3543a6, L"max", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Occur_Max, - -1, XFA_SCRIPT_Basic}, - {0xb356ca4, L"min", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Occur_Min, - -1, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x7d0b5fca, L"initial", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Initial, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::targetType, + XFA_Attribute::TargetType, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xc8da4da7, L"target", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::target, + XFA_Attribute::Target, XFA_ScriptType::Basic}, + {0xcbcaf66d, L"leader", (XFA_ATTRIBUTE_CALLBACK)&CJX_BreakAfter::leader, + XFA_Attribute::Leader, XFA_ScriptType::Basic}, + + /* line */ + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Line::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xabef37e3, L"slope", (XFA_ATTRIBUTE_CALLBACK)&CJX_Line::slope, + XFA_Attribute::Slope, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Line::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + {0xd996fa9b, L"hand", (XFA_ATTRIBUTE_CALLBACK)&CJX_Line::hand, + XFA_Attribute::Hand, XFA_ScriptType::Basic}, + + /* list */ + {0xa60dd202, L"length", (XFA_ATTRIBUTE_CALLBACK)&CJX_List::length, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* source */ + {0x20146, L"db", (XFA_ATTRIBUTE_CALLBACK)&CJX_Source::db, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Source::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Source::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* occur */ + {0xb3543a6, L"max", (XFA_ATTRIBUTE_CALLBACK)&CJX_Occur::max, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xb356ca4, L"min", (XFA_ATTRIBUTE_CALLBACK)&CJX_Occur::min, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Occur::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x7d0b5fca, L"initial", (XFA_ATTRIBUTE_CALLBACK)&CJX_Occur::initial, + XFA_Attribute::Initial, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Occur::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* pickTrayByPDFSize */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* monthNames */ {0x29418bb7, L"abbr", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Abbr, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Abbr, XFA_ScriptType::Basic}, + + /* severity */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* groupParent */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* documentAssembly */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* numberSymbol */ {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + + /* tagged */ {0xbe52dfbf, L"desc", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Desc, XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_String, + XFA_Attribute::Desc, XFA_ScriptType::Basic}, {0xf6b47749, L"lock", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_BOOL, - XFA_ATTRIBUTE_Lock, XFA_SCRIPT_Basic}, - {0xbb8df5d, L"ref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Ref, XFA_SCRIPT_Basic}, - {0xc0811ed, L"use", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Use, XFA_SCRIPT_Basic}, - {0x570ce835, L"presence", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Presence, XFA_SCRIPT_Basic}, - {0xa5b410cf, L"save", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Save, XFA_SCRIPT_Basic}, - {0xbc254332, L"usehref", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Usehref, XFA_SCRIPT_Basic}, - {0xb2c80857, L"className", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Object::Script_ObjectClass_ClassName, -1, - XFA_SCRIPT_Basic}, - {0xa60dd202, L"length", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_NodeList::Script_ListClass_Length, -1, - XFA_SCRIPT_Basic}, - {0x31b19c1, L"name", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Name, XFA_SCRIPT_Basic}, - {0x9f9d0f9, L"all", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_All, -1, - XFA_SCRIPT_Object}, - {0x4df15659, L"nodes", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_Nodes, -1, - XFA_SCRIPT_Object}, - {0x78a8d6cf, L"classAll", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_ClassAll, -1, - XFA_SCRIPT_Object}, - {0xcad6d8ca, L"parent", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_Parent, -1, - XFA_SCRIPT_Object}, - {0xd5679c78, L"index", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_Index, -1, - XFA_SCRIPT_Basic}, - {0xdb5b4bce, L"classIndex", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_ClassIndex, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Attribute_BOOL, + XFA_Attribute::Lock, XFA_ScriptType::Basic}, + + /* items */ + {0xbb8df5d, L"ref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Items::ref, + XFA_Attribute::Ref, XFA_ScriptType::Basic}, + {0xc0811ed, L"use", (XFA_ATTRIBUTE_CALLBACK)&CJX_Items::use, + XFA_Attribute::Use, XFA_ScriptType::Basic}, + {0x570ce835, L"presence", (XFA_ATTRIBUTE_CALLBACK)&CJX_Items::presence, + XFA_Attribute::Presence, XFA_ScriptType::Basic}, + {0xa5b410cf, L"save", (XFA_ATTRIBUTE_CALLBACK)&CJX_Items::save, + XFA_Attribute::Save, XFA_ScriptType::Basic}, + {0xbc254332, L"usehref", (XFA_ATTRIBUTE_CALLBACK)&CJX_Items::usehref, + XFA_Attribute::Usehref, XFA_ScriptType::Basic}, + + /* object */ + {0xb2c80857, L"className", (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::className, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* list */ + {0xa60dd202, L"length", (XFA_ATTRIBUTE_CALLBACK)&CJX_List::length, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + + /* [unknown] */ + + /* tree */ + {0x31b19c1, L"name", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::name, + XFA_Attribute::Name, XFA_ScriptType::Basic}, + {0x9f9d0f9, L"all", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::all, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0x4df15659, L"nodes", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::nodes, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0x78a8d6cf, L"classAll", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::classAll, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0xcad6d8ca, L"parent", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::parent, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0xd5679c78, L"index", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::index, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xdb5b4bce, L"classIndex", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::classIndex, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xe4989adf, L"somExpression", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_TreeClass_SomExpression, -1, - XFA_SCRIPT_Basic}, - {0x21aed, L"id", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Attribute_String, - XFA_ATTRIBUTE_Id, XFA_SCRIPT_Basic}, - {0x234a1, L"ns", (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_NodeClass_Ns, - -1, XFA_SCRIPT_Basic}, - {0x50d1a9d1, L"model", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_NodeClass_Model, -1, - XFA_SCRIPT_Object}, - {0xacb4823f, L"isContainer", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_NodeClass_IsContainer, -1, - XFA_SCRIPT_Basic}, - {0xe372ae97, L"isNull", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_NodeClass_IsNull, -1, - XFA_SCRIPT_Basic}, - {0xfe612a5b, L"oneOfChild", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_NodeClass_OneOfChild, -1, - XFA_SCRIPT_Object}, - {0x97c1c65, L"context", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_ModelClass_Context, -1, - XFA_SCRIPT_Object}, - {0x58be2870, L"aliasNode", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_ModelClass_AliasNode, -1, - XFA_SCRIPT_Object}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::somExpression, XFA_Attribute::Unknown, + XFA_ScriptType::Basic}, + + /* node */ + {0x21aed, L"id", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::id, XFA_Attribute::Id, + XFA_ScriptType::Basic}, + {0x234a1, L"ns", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::ns, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0x50d1a9d1, L"model", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::model, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0xacb4823f, L"isContainer", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::isContainer, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xe372ae97, L"isNull", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::isNull, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, + {0xfe612a5b, L"oneOfChild", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::oneOfChild, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + + /* [unknown] */ + + /* [unknown] */ + + /* model */ + {0x97c1c65, L"context", (XFA_ATTRIBUTE_CALLBACK)&CJX_Model::context, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + {0x58be2870, L"aliasNode", (XFA_ATTRIBUTE_CALLBACK)&CJX_Model::aliasNode, + XFA_Attribute::Unknown, XFA_ScriptType::Object}, + + /* [unknown] */ {0xa52682bd, L"{default}", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DefaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, {0xd6e27f1d, L"value", - (XFA_ATTRIBUTE_CALLBACK)&CXFA_Node::Script_Som_DefaultValue, -1, - XFA_SCRIPT_Basic}, + (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_Som_DefaultValue, + XFA_Attribute::Unknown, XFA_ScriptType::Basic}, }; -const int32_t g_iSomAttributeCount = - sizeof(g_SomAttributeData) / sizeof(XFA_ATTRIBUTEINFO); +const int32_t g_iSomAttributeCount = FX_ArraySize(g_SomAttributeData); diff --git a/xfa/fxfa/parser/xfa_basic_data_enum.cpp b/xfa/fxfa/parser/xfa_basic_data_enum.cpp index 06cd764e6d4f7e6656f8fc08c3bbb65ce9f33d00..33c5cf444e301a302a1b508f1350fb24dca04690 100644 --- a/xfa/fxfa/parser/xfa_basic_data_enum.cpp +++ b/xfa/fxfa/parser/xfa_basic_data_enum.cpp @@ -8,274 +8,274 @@ #include "xfa/fxfa/fxfa_basic.h" -const XFA_ATTRIBUTEENUMINFO g_XFAEnumData[] = { - {0x2a, L"*", XFA_ATTRIBUTEENUM_Asterisk}, - {0x2f, L"/", XFA_ATTRIBUTEENUM_Slash}, - {0x5c, L"\\", XFA_ATTRIBUTEENUM_Backslash}, - {0x239bd, L"on", XFA_ATTRIBUTEENUM_On}, - {0x25356, L"tb", XFA_ATTRIBUTEENUM_Tb}, - {0x25885, L"up", XFA_ATTRIBUTEENUM_Up}, - {0x91b281, L"metaData", XFA_ATTRIBUTEENUM_MetaData}, - {0x1f8dedb, L"delegate", XFA_ATTRIBUTEENUM_Delegate}, - {0x2a6c55a, L"postSubmit", XFA_ATTRIBUTEENUM_PostSubmit}, - {0x31b19c1, L"name", XFA_ATTRIBUTEENUM_Name}, - {0x378a38a, L"cross", XFA_ATTRIBUTEENUM_Cross}, - {0x3848b3f, L"next", XFA_ATTRIBUTEENUM_Next}, - {0x48b6670, L"none", XFA_ATTRIBUTEENUM_None}, - {0x51aafe5, L"shortEdge", XFA_ATTRIBUTEENUM_ShortEdge}, - {0x55264c4, L"1mod10_1mod11", XFA_ATTRIBUTEENUM_1mod10_1mod11}, - {0x5a5c519, L"height", XFA_ATTRIBUTEENUM_Height}, - {0x89ce549, L"crossDiagonal", XFA_ATTRIBUTEENUM_CrossDiagonal}, - {0x9f9d0f9, L"all", XFA_ATTRIBUTEENUM_All}, - {0x9f9db48, L"any", XFA_ATTRIBUTEENUM_Any}, - {0xa126261, L"toRight", XFA_ATTRIBUTEENUM_ToRight}, - {0xa36de29, L"matchTemplate", XFA_ATTRIBUTEENUM_MatchTemplate}, - {0xa48d040, L"dpl", XFA_ATTRIBUTEENUM_Dpl}, - {0xa559c05, L"invisible", XFA_ATTRIBUTEENUM_Invisible}, - {0xa7d48e3, L"fit", XFA_ATTRIBUTEENUM_Fit}, - {0xa8a8f80, L"width", XFA_ATTRIBUTEENUM_Width}, - {0xab466bb, L"preSubmit", XFA_ATTRIBUTEENUM_PreSubmit}, - {0xacc5785, L"ipl", XFA_ATTRIBUTEENUM_Ipl}, - {0xafab0f8, L"flateCompress", XFA_ATTRIBUTEENUM_FlateCompress}, - {0xb355816, L"med", XFA_ATTRIBUTEENUM_Med}, - {0xb69ef77, L"odd", XFA_ATTRIBUTEENUM_Odd}, - {0xb69f9bb, L"off", XFA_ATTRIBUTEENUM_Off}, - {0xb843dba, L"pdf", XFA_ATTRIBUTEENUM_Pdf}, - {0xbb912b8, L"row", XFA_ATTRIBUTEENUM_Row}, - {0xbedaf33, L"top", XFA_ATTRIBUTEENUM_Top}, - {0xc56afcc, L"xdp", XFA_ATTRIBUTEENUM_Xdp}, - {0xc56ba02, L"xfd", XFA_ATTRIBUTEENUM_Xfd}, - {0xc56ddf1, L"xml", XFA_ATTRIBUTEENUM_Xml}, - {0xc8b65f3, L"zip", XFA_ATTRIBUTEENUM_Zip}, - {0xc8b89d6, L"zpl", XFA_ATTRIBUTEENUM_Zpl}, - {0xf55d7ee, L"visible", XFA_ATTRIBUTEENUM_Visible}, - {0xfe3596a, L"exclude", XFA_ATTRIBUTEENUM_Exclude}, - {0x109d7ce7, L"mouseEnter", XFA_ATTRIBUTEENUM_MouseEnter}, - {0x10f1bc0c, L"pair", XFA_ATTRIBUTEENUM_Pair}, - {0x1154efe6, L"filter", XFA_ATTRIBUTEENUM_Filter}, - {0x125bc94b, L"moveLast", XFA_ATTRIBUTEENUM_MoveLast}, - {0x12e1f1f0, L"exportAndImport", XFA_ATTRIBUTEENUM_ExportAndImport}, - {0x13000c60, L"push", XFA_ATTRIBUTEENUM_Push}, - {0x138ee315, L"portrait", XFA_ATTRIBUTEENUM_Portrait}, - {0x14da2125, L"default", XFA_ATTRIBUTEENUM_Default}, - {0x157749a5, L"storedProc", XFA_ATTRIBUTEENUM_StoredProc}, - {0x16641198, L"stayBOF", XFA_ATTRIBUTEENUM_StayBOF}, - {0x16b2fc5b, L"stayEOF", XFA_ATTRIBUTEENUM_StayEOF}, - {0x17fad373, L"postPrint", XFA_ATTRIBUTEENUM_PostPrint}, - {0x193207d0, L"usCarrier", XFA_ATTRIBUTEENUM_UsCarrier}, - {0x193ade3e, L"right", XFA_ATTRIBUTEENUM_Right}, - {0x1bfc72d9, L"preOpen", XFA_ATTRIBUTEENUM_PreOpen}, - {0x1cc9317a, L"actual", XFA_ATTRIBUTEENUM_Actual}, - {0x1f31df1e, L"rest", XFA_ATTRIBUTEENUM_Rest}, - {0x1fb1bf14, L"topCenter", XFA_ATTRIBUTEENUM_TopCenter}, - {0x207de667, L"standardSymbol", XFA_ATTRIBUTEENUM_StandardSymbol}, - {0x2196a452, L"initialize", XFA_ATTRIBUTEENUM_Initialize}, - {0x23bd40c7, L"justifyAll", XFA_ATTRIBUTEENUM_JustifyAll}, - {0x247cf3e9, L"normal", XFA_ATTRIBUTEENUM_Normal}, - {0x25aa946b, L"landscape", XFA_ATTRIBUTEENUM_Landscape}, - {0x2739b5c9, L"nonInteractive", XFA_ATTRIBUTEENUM_NonInteractive}, - {0x27410f03, L"mouseExit", XFA_ATTRIBUTEENUM_MouseExit}, - {0x2854e62c, L"minus", XFA_ATTRIBUTEENUM_Minus}, - {0x287e936a, L"diagonalLeft", XFA_ATTRIBUTEENUM_DiagonalLeft}, - {0x2972a98f, L"simplexPaginated", XFA_ATTRIBUTEENUM_SimplexPaginated}, - {0x29d8225f, L"document", XFA_ATTRIBUTEENUM_Document}, - {0x2a9d3016, L"warning", XFA_ATTRIBUTEENUM_Warning}, - {0x2b35b6d9, L"auto", XFA_ATTRIBUTEENUM_Auto}, - {0x2c1653d9, L"below", XFA_ATTRIBUTEENUM_Below}, - {0x2c1f0540, L"bottomLeft", XFA_ATTRIBUTEENUM_BottomLeft}, - {0x2c44e816, L"bottomCenter", XFA_ATTRIBUTEENUM_BottomCenter}, - {0x2cd3e9f3, L"tcpl", XFA_ATTRIBUTEENUM_Tcpl}, - {0x2d08af85, L"text", XFA_ATTRIBUTEENUM_Text}, - {0x2dc478eb, L"grouping", XFA_ATTRIBUTEENUM_Grouping}, - {0x2ef3afdd, L"secureSymbol", XFA_ATTRIBUTEENUM_SecureSymbol}, - {0x2f2dd29a, L"preExecute", XFA_ATTRIBUTEENUM_PreExecute}, - {0x33c43dec, L"docClose", XFA_ATTRIBUTEENUM_DocClose}, - {0x33f25bb5, L"keyset", XFA_ATTRIBUTEENUM_Keyset}, - {0x34e363da, L"vertical", XFA_ATTRIBUTEENUM_Vertical}, - {0x361fa1b6, L"preSave", XFA_ATTRIBUTEENUM_PreSave}, - {0x36f1c6d8, L"preSign", XFA_ATTRIBUTEENUM_PreSign}, - {0x399f02b5, L"bottom", XFA_ATTRIBUTEENUM_Bottom}, - {0x3b0ab096, L"toTop", XFA_ATTRIBUTEENUM_ToTop}, - {0x3c752495, L"verify", XFA_ATTRIBUTEENUM_Verify}, - {0x3ce05d68, L"first", XFA_ATTRIBUTEENUM_First}, - {0x3ecead94, L"contentArea", XFA_ATTRIBUTEENUM_ContentArea}, - {0x40623b5b, L"solid", XFA_ATTRIBUTEENUM_Solid}, - {0x42c6cd8d, L"pessimistic", XFA_ATTRIBUTEENUM_Pessimistic}, - {0x43ddc6bf, L"duplexPaginated", XFA_ATTRIBUTEENUM_DuplexPaginated}, - {0x442f68c8, L"round", XFA_ATTRIBUTEENUM_Round}, - {0x45efb847, L"remerge", XFA_ATTRIBUTEENUM_Remerge}, - {0x46972265, L"ordered", XFA_ATTRIBUTEENUM_Ordered}, - {0x46f95531, L"percent", XFA_ATTRIBUTEENUM_Percent}, - {0x46fd25ae, L"even", XFA_ATTRIBUTEENUM_Even}, - {0x4731d6ba, L"exit", XFA_ATTRIBUTEENUM_Exit}, - {0x4977356b, L"toolTip", XFA_ATTRIBUTEENUM_ToolTip}, - {0x49b980ee, L"orderedOccurrence", XFA_ATTRIBUTEENUM_OrderedOccurrence}, - {0x4a7e2dfe, L"readOnly", XFA_ATTRIBUTEENUM_ReadOnly}, - {0x4c4e8acb, L"currency", XFA_ATTRIBUTEENUM_Currency}, - {0x4dcf25f8, L"concat", XFA_ATTRIBUTEENUM_Concat}, - {0x4febb826, L"Thai", XFA_ATTRIBUTEENUM_Thai}, - {0x50ef95b2, L"embossed", XFA_ATTRIBUTEENUM_Embossed}, - {0x516e35ce, L"formdata", XFA_ATTRIBUTEENUM_Formdata}, - {0x52fa6f0e, L"Greek", XFA_ATTRIBUTEENUM_Greek}, - {0x54034c2f, L"decimal", XFA_ATTRIBUTEENUM_Decimal}, - {0x542c7300, L"select", XFA_ATTRIBUTEENUM_Select}, - {0x551f0ae5, L"longEdge", XFA_ATTRIBUTEENUM_LongEdge}, - {0x55520a8a, L"protected", XFA_ATTRIBUTEENUM_Protected}, - {0x559f76f3, L"bottomRight", XFA_ATTRIBUTEENUM_BottomRight}, - {0x568cb500, L"zero", XFA_ATTRIBUTEENUM_Zero}, - {0x56bcecb7, L"forwardOnly", XFA_ATTRIBUTEENUM_ForwardOnly}, - {0x56bf456b, L"docReady", XFA_ATTRIBUTEENUM_DocReady}, - {0x573cb40c, L"hidden", XFA_ATTRIBUTEENUM_Hidden}, - {0x582e3424, L"include", XFA_ATTRIBUTEENUM_Include}, - {0x58a3dd29, L"dashed", XFA_ATTRIBUTEENUM_Dashed}, - {0x5955b22b, L"multiSelect", XFA_ATTRIBUTEENUM_MultiSelect}, - {0x598d5c53, L"inactive", XFA_ATTRIBUTEENUM_Inactive}, - {0x59c8f27d, L"embed", XFA_ATTRIBUTEENUM_Embed}, - {0x5e7555e8, L"static", XFA_ATTRIBUTEENUM_Static}, - {0x606d4def, L"onEntry", XFA_ATTRIBUTEENUM_OnEntry}, - {0x6195eafb, L"Cyrillic", XFA_ATTRIBUTEENUM_Cyrillic}, - {0x6491b0f3, L"nonBlank", XFA_ATTRIBUTEENUM_NonBlank}, - {0x67bef031, L"topRight", XFA_ATTRIBUTEENUM_TopRight}, - {0x67df5ebd, L"Hebrew", XFA_ATTRIBUTEENUM_Hebrew}, - {0x6aea98be, L"topLeft", XFA_ATTRIBUTEENUM_TopLeft}, - {0x6c51afc1, L"center", XFA_ATTRIBUTEENUM_Center}, - {0x7145e6bf, L"moveFirst", XFA_ATTRIBUTEENUM_MoveFirst}, - {0x7375465c, L"diamond", XFA_ATTRIBUTEENUM_Diamond}, - {0x7461aef4, L"pageOdd", XFA_ATTRIBUTEENUM_PageOdd}, - {0x75f8aeb2, L"1mod10", XFA_ATTRIBUTEENUM_1mod10}, - {0x76d708e0, L"Korean", XFA_ATTRIBUTEENUM_Korean}, - {0x789f14d7, L"aboveEmbedded", XFA_ATTRIBUTEENUM_AboveEmbedded}, - {0x792ea39f, L"zipCompress", XFA_ATTRIBUTEENUM_ZipCompress}, - {0x7a5b7193, L"numeric", XFA_ATTRIBUTEENUM_Numeric}, - {0x7abec0d2, L"circle", XFA_ATTRIBUTEENUM_Circle}, - {0x7afbba38, L"toBottom", XFA_ATTRIBUTEENUM_ToBottom}, - {0x7b95e661, L"inverted", XFA_ATTRIBUTEENUM_Inverted}, - {0x7baca2e3, L"update", XFA_ATTRIBUTEENUM_Update}, - {0x7eb5da2c, L"isoname", XFA_ATTRIBUTEENUM_Isoname}, - {0x7f6fd3d7, L"server", XFA_ATTRIBUTEENUM_Server}, - {0x814f82b5, L"position", XFA_ATTRIBUTEENUM_Position}, - {0x82deacf0, L"middleCenter", XFA_ATTRIBUTEENUM_MiddleCenter}, - {0x83a49dc6, L"optional", XFA_ATTRIBUTEENUM_Optional}, - {0x861a116f, L"usePrinterSetting", XFA_ATTRIBUTEENUM_UsePrinterSetting}, - {0x86701ce0, L"outline", XFA_ATTRIBUTEENUM_Outline}, - {0x8808385e, L"indexChange", XFA_ATTRIBUTEENUM_IndexChange}, - {0x891f4606, L"change", XFA_ATTRIBUTEENUM_Change}, - {0x89939f36, L"pageArea", XFA_ATTRIBUTEENUM_PageArea}, - {0x8b5c3b25, L"once", XFA_ATTRIBUTEENUM_Once}, - {0x8b5c6962, L"only", XFA_ATTRIBUTEENUM_Only}, - {0x8b90e1f2, L"open", XFA_ATTRIBUTEENUM_Open}, - {0x8bcfe96e, L"caption", XFA_ATTRIBUTEENUM_Caption}, - {0x8ce83ef8, L"raised", XFA_ATTRIBUTEENUM_Raised}, - {0x8d269cae, L"justify", XFA_ATTRIBUTEENUM_Justify}, - {0x8fd520dc, L"refAndDescendants", XFA_ATTRIBUTEENUM_RefAndDescendants}, - {0x9041d4b0, L"short", XFA_ATTRIBUTEENUM_Short}, - {0x90c94426, L"pageFront", XFA_ATTRIBUTEENUM_PageFront}, - {0x936beee5, L"monospace", XFA_ATTRIBUTEENUM_Monospace}, - {0x947fa00f, L"middle", XFA_ATTRIBUTEENUM_Middle}, - {0x9528a7b4, L"prePrint", XFA_ATTRIBUTEENUM_PrePrint}, - {0x959ab231, L"always", XFA_ATTRIBUTEENUM_Always}, - {0x96d61bf0, L"unknown", XFA_ATTRIBUTEENUM_Unknown}, - {0x997194ee, L"toLeft", XFA_ATTRIBUTEENUM_ToLeft}, - {0x9a83a3cd, L"above", XFA_ATTRIBUTEENUM_Above}, - {0x9d0d71c7, L"dashDot", XFA_ATTRIBUTEENUM_DashDot}, - {0x9df56f3e, L"gregorian", XFA_ATTRIBUTEENUM_Gregorian}, - {0x9f6723fd, L"Roman", XFA_ATTRIBUTEENUM_Roman}, - {0x9f693b21, L"mouseDown", XFA_ATTRIBUTEENUM_MouseDown}, - {0xa1429b36, L"symbol", XFA_ATTRIBUTEENUM_Symbol}, - {0xa5aa45cb, L"pageEven", XFA_ATTRIBUTEENUM_PageEven}, - {0xa68635f1, L"sign", XFA_ATTRIBUTEENUM_Sign}, - {0xa7315093, L"addNew", XFA_ATTRIBUTEENUM_AddNew}, - {0xa7a773fa, L"star", XFA_ATTRIBUTEENUM_Star}, - {0xa7d57b45, L"optimistic", XFA_ATTRIBUTEENUM_Optimistic}, - {0xa8077321, L"rl-tb", XFA_ATTRIBUTEENUM_Rl_tb}, - {0xa8f1468d, L"middleRight", XFA_ATTRIBUTEENUM_MiddleRight}, - {0xaa84a1f1, L"maintain", XFA_ATTRIBUTEENUM_Maintain}, - {0xab40b12c, L"package", XFA_ATTRIBUTEENUM_Package}, - {0xac8b4d85, L"SimplifiedChinese", XFA_ATTRIBUTEENUM_SimplifiedChinese}, - {0xadae6744, L"toCenter", XFA_ATTRIBUTEENUM_ToCenter}, - {0xb0129df1, L"back", XFA_ATTRIBUTEENUM_Back}, - {0xb0f088cf, L"unspecified", XFA_ATTRIBUTEENUM_Unspecified}, - {0xb1271067, L"batchOptimistic", XFA_ATTRIBUTEENUM_BatchOptimistic}, - {0xb18313a1, L"bold", XFA_ATTRIBUTEENUM_Bold}, - {0xb1833cad, L"both", XFA_ATTRIBUTEENUM_Both}, - {0xb221123f, L"butt", XFA_ATTRIBUTEENUM_Butt}, - {0xb40c36bf, L"client", XFA_ATTRIBUTEENUM_Client}, - {0xb56c7053, L"2mod10", XFA_ATTRIBUTEENUM_2mod10}, - {0xb683a345, L"imageOnly", XFA_ATTRIBUTEENUM_ImageOnly}, - {0xb7732dea, L"horizontal", XFA_ATTRIBUTEENUM_Horizontal}, - {0xb88652a4, L"dotted", XFA_ATTRIBUTEENUM_Dotted}, - {0xbb2f2880, L"userControl", XFA_ATTRIBUTEENUM_UserControl}, - {0xbbb79c5d, L"diagonalRight", XFA_ATTRIBUTEENUM_DiagonalRight}, - {0xbd077154, L"consumeData", XFA_ATTRIBUTEENUM_ConsumeData}, - {0xbd3fb11e, L"check", XFA_ATTRIBUTEENUM_Check}, - {0xbde9abda, L"data", XFA_ATTRIBUTEENUM_Data}, - {0xbf5a02d8, L"down", XFA_ATTRIBUTEENUM_Down}, - {0xbf7450ee, L"sansSerif", XFA_ATTRIBUTEENUM_SansSerif}, - {0xc02d649f, L"inline", XFA_ATTRIBUTEENUM_Inline}, - {0xc11a9e3a, L"TraditionalChinese", XFA_ATTRIBUTEENUM_TraditionalChinese}, - {0xc16169d8, L"warn", XFA_ATTRIBUTEENUM_Warn}, - {0xc16f071f, L"refOnly", XFA_ATTRIBUTEENUM_RefOnly}, - {0xc27c8ba5, L"interactiveForms", XFA_ATTRIBUTEENUM_InteractiveForms}, - {0xc2d1b15c, L"word", XFA_ATTRIBUTEENUM_Word}, - {0xc3621288, L"unordered", XFA_ATTRIBUTEENUM_Unordered}, - {0xc5251981, L"required", XFA_ATTRIBUTEENUM_Required}, - {0xc7088e7d, L"importOnly", XFA_ATTRIBUTEENUM_ImportOnly}, - {0xc72cf0e3, L"belowEmbedded", XFA_ATTRIBUTEENUM_BelowEmbedded}, - {0xc819cf07, L"Japanese", XFA_ATTRIBUTEENUM_Japanese}, - {0xcdce56b3, L"full", XFA_ATTRIBUTEENUM_Full}, - {0xce0122e3, L"rl-row", XFA_ATTRIBUTEENUM_Rl_row}, - {0xcf7d71f1, L"Vietnamese", XFA_ATTRIBUTEENUM_Vietnamese}, - {0xcfde3e09, L"EastEuropeanRoman", XFA_ATTRIBUTEENUM_EastEuropeanRoman}, - {0xd576d08e, L"mouseUp", XFA_ATTRIBUTEENUM_MouseUp}, - {0xd7a92904, L"exportOnly", XFA_ATTRIBUTEENUM_ExportOnly}, - {0xd8ed1467, L"clear", XFA_ATTRIBUTEENUM_Clear}, - {0xd95657a6, L"click", XFA_ATTRIBUTEENUM_Click}, - {0xd96c7de5, L"base64", XFA_ATTRIBUTEENUM_Base64}, - {0xd9f47f36, L"close", XFA_ATTRIBUTEENUM_Close}, - {0xdb075bde, L"host", XFA_ATTRIBUTEENUM_Host}, - {0xdb103411, L"global", XFA_ATTRIBUTEENUM_Global}, - {0xdb647188, L"blank", XFA_ATTRIBUTEENUM_Blank}, - {0xdb9be968, L"table", XFA_ATTRIBUTEENUM_Table}, - {0xdf590fbb, L"import", XFA_ATTRIBUTEENUM_Import}, - {0xe0e573fb, L"custom", XFA_ATTRIBUTEENUM_Custom}, - {0xe0ecc79a, L"middleLeft", XFA_ATTRIBUTEENUM_MiddleLeft}, - {0xe1452019, L"postExecute", XFA_ATTRIBUTEENUM_PostExecute}, - {0xe1911d98, L"radix", XFA_ATTRIBUTEENUM_Radix}, - {0xe25fa7b8, L"postOpen", XFA_ATTRIBUTEENUM_PostOpen}, - {0xe28dce7e, L"enter", XFA_ATTRIBUTEENUM_Enter}, - {0xe2c44de4, L"ignore", XFA_ATTRIBUTEENUM_Ignore}, - {0xe2cd8c61, L"lr-tb", XFA_ATTRIBUTEENUM_Lr_tb}, - {0xe2da8336, L"fantasy", XFA_ATTRIBUTEENUM_Fantasy}, - {0xe31d5396, L"italic", XFA_ATTRIBUTEENUM_Italic}, - {0xe7ada113, L"author", XFA_ATTRIBUTEENUM_Author}, - {0xe8e7cc18, L"toEdge", XFA_ATTRIBUTEENUM_ToEdge}, - {0xe97aa98b, L"choice", XFA_ATTRIBUTEENUM_Choice}, - {0xeafd2a38, L"disabled", XFA_ATTRIBUTEENUM_Disabled}, - {0xeb2b7972, L"crossHatch", XFA_ATTRIBUTEENUM_CrossHatch}, - {0xeb2db2d7, L"dataRef", XFA_ATTRIBUTEENUM_DataRef}, - {0xec35dc6e, L"dashDotDot", XFA_ATTRIBUTEENUM_DashDotDot}, - {0xef85d351, L"square", XFA_ATTRIBUTEENUM_Square}, - {0xf2102445, L"dynamic", XFA_ATTRIBUTEENUM_Dynamic}, - {0xf272c7be, L"manual", XFA_ATTRIBUTEENUM_Manual}, - {0xf2bbb64d, L"etched", XFA_ATTRIBUTEENUM_Etched}, - {0xf3b8fc6c, L"validationState", XFA_ATTRIBUTEENUM_ValidationState}, - {0xf42f2b81, L"cursive", XFA_ATTRIBUTEENUM_Cursive}, - {0xf54481d4, L"last", XFA_ATTRIBUTEENUM_Last}, - {0xf5ad782b, L"left", XFA_ATTRIBUTEENUM_Left}, - {0xf616da2e, L"link", XFA_ATTRIBUTEENUM_Link}, - {0xf6b4afb0, L"long", XFA_ATTRIBUTEENUM_Long}, +const XFA_AttributeEnumInfo g_XFAEnumData[] = { + {0x2a, L"*", XFA_AttributeEnum::Asterisk}, + {0x2f, L"/", XFA_AttributeEnum::Slash}, + {0x5c, L"\\", XFA_AttributeEnum::Backslash}, + {0x239bd, L"on", XFA_AttributeEnum::On}, + {0x25356, L"tb", XFA_AttributeEnum::Tb}, + {0x25885, L"up", XFA_AttributeEnum::Up}, + {0x91b281, L"metaData", XFA_AttributeEnum::MetaData}, + {0x1f8dedb, L"delegate", XFA_AttributeEnum::Delegate}, + {0x2a6c55a, L"postSubmit", XFA_AttributeEnum::PostSubmit}, + {0x31b19c1, L"name", XFA_AttributeEnum::Name}, + {0x378a38a, L"cross", XFA_AttributeEnum::Cross}, + {0x3848b3f, L"next", XFA_AttributeEnum::Next}, + {0x48b6670, L"none", XFA_AttributeEnum::None}, + {0x51aafe5, L"shortEdge", XFA_AttributeEnum::ShortEdge}, + {0x55264c4, L"1mod10_1mod11", XFA_AttributeEnum::Checksum_1mod10_1mod11}, + {0x5a5c519, L"height", XFA_AttributeEnum::Height}, + {0x89ce549, L"crossDiagonal", XFA_AttributeEnum::CrossDiagonal}, + {0x9f9d0f9, L"all", XFA_AttributeEnum::All}, + {0x9f9db48, L"any", XFA_AttributeEnum::Any}, + {0xa126261, L"toRight", XFA_AttributeEnum::ToRight}, + {0xa36de29, L"matchTemplate", XFA_AttributeEnum::MatchTemplate}, + {0xa48d040, L"dpl", XFA_AttributeEnum::Dpl}, + {0xa559c05, L"invisible", XFA_AttributeEnum::Invisible}, + {0xa7d48e3, L"fit", XFA_AttributeEnum::Fit}, + {0xa8a8f80, L"width", XFA_AttributeEnum::Width}, + {0xab466bb, L"preSubmit", XFA_AttributeEnum::PreSubmit}, + {0xacc5785, L"ipl", XFA_AttributeEnum::Ipl}, + {0xafab0f8, L"flateCompress", XFA_AttributeEnum::FlateCompress}, + {0xb355816, L"med", XFA_AttributeEnum::Med}, + {0xb69ef77, L"odd", XFA_AttributeEnum::Odd}, + {0xb69f9bb, L"off", XFA_AttributeEnum::Off}, + {0xb843dba, L"pdf", XFA_AttributeEnum::Pdf}, + {0xbb912b8, L"row", XFA_AttributeEnum::Row}, + {0xbedaf33, L"top", XFA_AttributeEnum::Top}, + {0xc56afcc, L"xdp", XFA_AttributeEnum::Xdp}, + {0xc56ba02, L"xfd", XFA_AttributeEnum::Xfd}, + {0xc56ddf1, L"xml", XFA_AttributeEnum::Xml}, + {0xc8b65f3, L"zip", XFA_AttributeEnum::Zip}, + {0xc8b89d6, L"zpl", XFA_AttributeEnum::Zpl}, + {0xf55d7ee, L"visible", XFA_AttributeEnum::Visible}, + {0xfe3596a, L"exclude", XFA_AttributeEnum::Exclude}, + {0x109d7ce7, L"mouseEnter", XFA_AttributeEnum::MouseEnter}, + {0x10f1bc0c, L"pair", XFA_AttributeEnum::Pair}, + {0x1154efe6, L"filter", XFA_AttributeEnum::Filter}, + {0x125bc94b, L"moveLast", XFA_AttributeEnum::MoveLast}, + {0x12e1f1f0, L"exportAndImport", XFA_AttributeEnum::ExportAndImport}, + {0x13000c60, L"push", XFA_AttributeEnum::Push}, + {0x138ee315, L"portrait", XFA_AttributeEnum::Portrait}, + {0x14da2125, L"default", XFA_AttributeEnum::Default}, + {0x157749a5, L"storedProc", XFA_AttributeEnum::StoredProc}, + {0x16641198, L"stayBOF", XFA_AttributeEnum::StayBOF}, + {0x16b2fc5b, L"stayEOF", XFA_AttributeEnum::StayEOF}, + {0x17fad373, L"postPrint", XFA_AttributeEnum::PostPrint}, + {0x193207d0, L"usCarrier", XFA_AttributeEnum::UsCarrier}, + {0x193ade3e, L"right", XFA_AttributeEnum::Right}, + {0x1bfc72d9, L"preOpen", XFA_AttributeEnum::PreOpen}, + {0x1cc9317a, L"actual", XFA_AttributeEnum::Actual}, + {0x1f31df1e, L"rest", XFA_AttributeEnum::Rest}, + {0x1fb1bf14, L"topCenter", XFA_AttributeEnum::TopCenter}, + {0x207de667, L"standardSymbol", XFA_AttributeEnum::StandardSymbol}, + {0x2196a452, L"initialize", XFA_AttributeEnum::Initialize}, + {0x23bd40c7, L"justifyAll", XFA_AttributeEnum::JustifyAll}, + {0x247cf3e9, L"normal", XFA_AttributeEnum::Normal}, + {0x25aa946b, L"landscape", XFA_AttributeEnum::Landscape}, + {0x2739b5c9, L"nonInteractive", XFA_AttributeEnum::NonInteractive}, + {0x27410f03, L"mouseExit", XFA_AttributeEnum::MouseExit}, + {0x2854e62c, L"minus", XFA_AttributeEnum::Minus}, + {0x287e936a, L"diagonalLeft", XFA_AttributeEnum::DiagonalLeft}, + {0x2972a98f, L"simplexPaginated", XFA_AttributeEnum::SimplexPaginated}, + {0x29d8225f, L"document", XFA_AttributeEnum::Document}, + {0x2a9d3016, L"warning", XFA_AttributeEnum::Warning}, + {0x2b35b6d9, L"auto", XFA_AttributeEnum::Auto}, + {0x2c1653d9, L"below", XFA_AttributeEnum::Below}, + {0x2c1f0540, L"bottomLeft", XFA_AttributeEnum::BottomLeft}, + {0x2c44e816, L"bottomCenter", XFA_AttributeEnum::BottomCenter}, + {0x2cd3e9f3, L"tcpl", XFA_AttributeEnum::Tcpl}, + {0x2d08af85, L"text", XFA_AttributeEnum::Text}, + {0x2dc478eb, L"grouping", XFA_AttributeEnum::Grouping}, + {0x2ef3afdd, L"secureSymbol", XFA_AttributeEnum::SecureSymbol}, + {0x2f2dd29a, L"preExecute", XFA_AttributeEnum::PreExecute}, + {0x33c43dec, L"docClose", XFA_AttributeEnum::DocClose}, + {0x33f25bb5, L"keyset", XFA_AttributeEnum::Keyset}, + {0x34e363da, L"vertical", XFA_AttributeEnum::Vertical}, + {0x361fa1b6, L"preSave", XFA_AttributeEnum::PreSave}, + {0x36f1c6d8, L"preSign", XFA_AttributeEnum::PreSign}, + {0x399f02b5, L"bottom", XFA_AttributeEnum::Bottom}, + {0x3b0ab096, L"toTop", XFA_AttributeEnum::ToTop}, + {0x3c752495, L"verify", XFA_AttributeEnum::Verify}, + {0x3ce05d68, L"first", XFA_AttributeEnum::First}, + {0x3ecead94, L"contentArea", XFA_AttributeEnum::ContentArea}, + {0x40623b5b, L"solid", XFA_AttributeEnum::Solid}, + {0x42c6cd8d, L"pessimistic", XFA_AttributeEnum::Pessimistic}, + {0x43ddc6bf, L"duplexPaginated", XFA_AttributeEnum::DuplexPaginated}, + {0x442f68c8, L"round", XFA_AttributeEnum::Round}, + {0x45efb847, L"remerge", XFA_AttributeEnum::Remerge}, + {0x46972265, L"ordered", XFA_AttributeEnum::Ordered}, + {0x46f95531, L"percent", XFA_AttributeEnum::Percent}, + {0x46fd25ae, L"even", XFA_AttributeEnum::Even}, + {0x4731d6ba, L"exit", XFA_AttributeEnum::Exit}, + {0x4977356b, L"toolTip", XFA_AttributeEnum::ToolTip}, + {0x49b980ee, L"orderedOccurrence", XFA_AttributeEnum::OrderedOccurrence}, + {0x4a7e2dfe, L"readOnly", XFA_AttributeEnum::ReadOnly}, + {0x4c4e8acb, L"currency", XFA_AttributeEnum::Currency}, + {0x4dcf25f8, L"concat", XFA_AttributeEnum::Concat}, + {0x4febb826, L"Thai", XFA_AttributeEnum::Thai}, + {0x50ef95b2, L"embossed", XFA_AttributeEnum::Embossed}, + {0x516e35ce, L"formdata", XFA_AttributeEnum::Formdata}, + {0x52fa6f0e, L"Greek", XFA_AttributeEnum::Greek}, + {0x54034c2f, L"decimal", XFA_AttributeEnum::Decimal}, + {0x542c7300, L"select", XFA_AttributeEnum::Select}, + {0x551f0ae5, L"longEdge", XFA_AttributeEnum::LongEdge}, + {0x55520a8a, L"protected", XFA_AttributeEnum::Protected}, + {0x559f76f3, L"bottomRight", XFA_AttributeEnum::BottomRight}, + {0x568cb500, L"zero", XFA_AttributeEnum::Zero}, + {0x56bcecb7, L"forwardOnly", XFA_AttributeEnum::ForwardOnly}, + {0x56bf456b, L"docReady", XFA_AttributeEnum::DocReady}, + {0x573cb40c, L"hidden", XFA_AttributeEnum::Hidden}, + {0x582e3424, L"include", XFA_AttributeEnum::Include}, + {0x58a3dd29, L"dashed", XFA_AttributeEnum::Dashed}, + {0x5955b22b, L"multiSelect", XFA_AttributeEnum::MultiSelect}, + {0x598d5c53, L"inactive", XFA_AttributeEnum::Inactive}, + {0x59c8f27d, L"embed", XFA_AttributeEnum::Embed}, + {0x5e7555e8, L"static", XFA_AttributeEnum::Static}, + {0x606d4def, L"onEntry", XFA_AttributeEnum::OnEntry}, + {0x6195eafb, L"Cyrillic", XFA_AttributeEnum::Cyrillic}, + {0x6491b0f3, L"nonBlank", XFA_AttributeEnum::NonBlank}, + {0x67bef031, L"topRight", XFA_AttributeEnum::TopRight}, + {0x67df5ebd, L"Hebrew", XFA_AttributeEnum::Hebrew}, + {0x6aea98be, L"topLeft", XFA_AttributeEnum::TopLeft}, + {0x6c51afc1, L"center", XFA_AttributeEnum::Center}, + {0x7145e6bf, L"moveFirst", XFA_AttributeEnum::MoveFirst}, + {0x7375465c, L"diamond", XFA_AttributeEnum::Diamond}, + {0x7461aef4, L"pageOdd", XFA_AttributeEnum::PageOdd}, + {0x75f8aeb2, L"1mod10", XFA_AttributeEnum::Checksum_1mod10}, + {0x76d708e0, L"Korean", XFA_AttributeEnum::Korean}, + {0x789f14d7, L"aboveEmbedded", XFA_AttributeEnum::AboveEmbedded}, + {0x792ea39f, L"zipCompress", XFA_AttributeEnum::ZipCompress}, + {0x7a5b7193, L"numeric", XFA_AttributeEnum::Numeric}, + {0x7abec0d2, L"circle", XFA_AttributeEnum::Circle}, + {0x7afbba38, L"toBottom", XFA_AttributeEnum::ToBottom}, + {0x7b95e661, L"inverted", XFA_AttributeEnum::Inverted}, + {0x7baca2e3, L"update", XFA_AttributeEnum::Update}, + {0x7eb5da2c, L"isoname", XFA_AttributeEnum::Isoname}, + {0x7f6fd3d7, L"server", XFA_AttributeEnum::Server}, + {0x814f82b5, L"position", XFA_AttributeEnum::Position}, + {0x82deacf0, L"middleCenter", XFA_AttributeEnum::MiddleCenter}, + {0x83a49dc6, L"optional", XFA_AttributeEnum::Optional}, + {0x861a116f, L"usePrinterSetting", XFA_AttributeEnum::UsePrinterSetting}, + {0x86701ce0, L"outline", XFA_AttributeEnum::Outline}, + {0x8808385e, L"indexChange", XFA_AttributeEnum::IndexChange}, + {0x891f4606, L"change", XFA_AttributeEnum::Change}, + {0x89939f36, L"pageArea", XFA_AttributeEnum::PageArea}, + {0x8b5c3b25, L"once", XFA_AttributeEnum::Once}, + {0x8b5c6962, L"only", XFA_AttributeEnum::Only}, + {0x8b90e1f2, L"open", XFA_AttributeEnum::Open}, + {0x8bcfe96e, L"caption", XFA_AttributeEnum::Caption}, + {0x8ce83ef8, L"raised", XFA_AttributeEnum::Raised}, + {0x8d269cae, L"justify", XFA_AttributeEnum::Justify}, + {0x8fd520dc, L"refAndDescendants", XFA_AttributeEnum::RefAndDescendants}, + {0x9041d4b0, L"short", XFA_AttributeEnum::Short}, + {0x90c94426, L"pageFront", XFA_AttributeEnum::PageFront}, + {0x936beee5, L"monospace", XFA_AttributeEnum::Monospace}, + {0x947fa00f, L"middle", XFA_AttributeEnum::Middle}, + {0x9528a7b4, L"prePrint", XFA_AttributeEnum::PrePrint}, + {0x959ab231, L"always", XFA_AttributeEnum::Always}, + {0x96d61bf0, L"unknown", XFA_AttributeEnum::Unknown}, + {0x997194ee, L"toLeft", XFA_AttributeEnum::ToLeft}, + {0x9a83a3cd, L"above", XFA_AttributeEnum::Above}, + {0x9d0d71c7, L"dashDot", XFA_AttributeEnum::DashDot}, + {0x9df56f3e, L"gregorian", XFA_AttributeEnum::Gregorian}, + {0x9f6723fd, L"Roman", XFA_AttributeEnum::Roman}, + {0x9f693b21, L"mouseDown", XFA_AttributeEnum::MouseDown}, + {0xa1429b36, L"symbol", XFA_AttributeEnum::Symbol}, + {0xa5aa45cb, L"pageEven", XFA_AttributeEnum::PageEven}, + {0xa68635f1, L"sign", XFA_AttributeEnum::Sign}, + {0xa7315093, L"addNew", XFA_AttributeEnum::AddNew}, + {0xa7a773fa, L"star", XFA_AttributeEnum::Star}, + {0xa7d57b45, L"optimistic", XFA_AttributeEnum::Optimistic}, + {0xa8077321, L"rl-tb", XFA_AttributeEnum::Rl_tb}, + {0xa8f1468d, L"middleRight", XFA_AttributeEnum::MiddleRight}, + {0xaa84a1f1, L"maintain", XFA_AttributeEnum::Maintain}, + {0xab40b12c, L"package", XFA_AttributeEnum::Package}, + {0xac8b4d85, L"SimplifiedChinese", XFA_AttributeEnum::SimplifiedChinese}, + {0xadae6744, L"toCenter", XFA_AttributeEnum::ToCenter}, + {0xb0129df1, L"back", XFA_AttributeEnum::Back}, + {0xb0f088cf, L"unspecified", XFA_AttributeEnum::Unspecified}, + {0xb1271067, L"batchOptimistic", XFA_AttributeEnum::BatchOptimistic}, + {0xb18313a1, L"bold", XFA_AttributeEnum::Bold}, + {0xb1833cad, L"both", XFA_AttributeEnum::Both}, + {0xb221123f, L"butt", XFA_AttributeEnum::Butt}, + {0xb40c36bf, L"client", XFA_AttributeEnum::Client}, + {0xb56c7053, L"2mod10", XFA_AttributeEnum::Checksum_2mod10}, + {0xb683a345, L"imageOnly", XFA_AttributeEnum::ImageOnly}, + {0xb7732dea, L"horizontal", XFA_AttributeEnum::Horizontal}, + {0xb88652a4, L"dotted", XFA_AttributeEnum::Dotted}, + {0xbb2f2880, L"userControl", XFA_AttributeEnum::UserControl}, + {0xbbb79c5d, L"diagonalRight", XFA_AttributeEnum::DiagonalRight}, + {0xbd077154, L"consumeData", XFA_AttributeEnum::ConsumeData}, + {0xbd3fb11e, L"check", XFA_AttributeEnum::Check}, + {0xbde9abda, L"data", XFA_AttributeEnum::Data}, + {0xbf5a02d8, L"down", XFA_AttributeEnum::Down}, + {0xbf7450ee, L"sansSerif", XFA_AttributeEnum::SansSerif}, + {0xc02d649f, L"inline", XFA_AttributeEnum::Inline}, + {0xc11a9e3a, L"TraditionalChinese", XFA_AttributeEnum::TraditionalChinese}, + {0xc16169d8, L"warn", XFA_AttributeEnum::Warn}, + {0xc16f071f, L"refOnly", XFA_AttributeEnum::RefOnly}, + {0xc27c8ba5, L"interactiveForms", XFA_AttributeEnum::InteractiveForms}, + {0xc2d1b15c, L"word", XFA_AttributeEnum::Word}, + {0xc3621288, L"unordered", XFA_AttributeEnum::Unordered}, + {0xc5251981, L"required", XFA_AttributeEnum::Required}, + {0xc7088e7d, L"importOnly", XFA_AttributeEnum::ImportOnly}, + {0xc72cf0e3, L"belowEmbedded", XFA_AttributeEnum::BelowEmbedded}, + {0xc819cf07, L"Japanese", XFA_AttributeEnum::Japanese}, + {0xcdce56b3, L"full", XFA_AttributeEnum::Full}, + {0xce0122e3, L"rl-row", XFA_AttributeEnum::Rl_row}, + {0xcf7d71f1, L"Vietnamese", XFA_AttributeEnum::Vietnamese}, + {0xcfde3e09, L"EastEuropeanRoman", XFA_AttributeEnum::EastEuropeanRoman}, + {0xd576d08e, L"mouseUp", XFA_AttributeEnum::MouseUp}, + {0xd7a92904, L"exportOnly", XFA_AttributeEnum::ExportOnly}, + {0xd8ed1467, L"clear", XFA_AttributeEnum::Clear}, + {0xd95657a6, L"click", XFA_AttributeEnum::Click}, + {0xd96c7de5, L"base64", XFA_AttributeEnum::Base64}, + {0xd9f47f36, L"close", XFA_AttributeEnum::Close}, + {0xdb075bde, L"host", XFA_AttributeEnum::Host}, + {0xdb103411, L"global", XFA_AttributeEnum::Global}, + {0xdb647188, L"blank", XFA_AttributeEnum::Blank}, + {0xdb9be968, L"table", XFA_AttributeEnum::Table}, + {0xdf590fbb, L"import", XFA_AttributeEnum::Import}, + {0xe0e573fb, L"custom", XFA_AttributeEnum::Custom}, + {0xe0ecc79a, L"middleLeft", XFA_AttributeEnum::MiddleLeft}, + {0xe1452019, L"postExecute", XFA_AttributeEnum::PostExecute}, + {0xe1911d98, L"radix", XFA_AttributeEnum::Radix}, + {0xe25fa7b8, L"postOpen", XFA_AttributeEnum::PostOpen}, + {0xe28dce7e, L"enter", XFA_AttributeEnum::Enter}, + {0xe2c44de4, L"ignore", XFA_AttributeEnum::Ignore}, + {0xe2cd8c61, L"lr-tb", XFA_AttributeEnum::Lr_tb}, + {0xe2da8336, L"fantasy", XFA_AttributeEnum::Fantasy}, + {0xe31d5396, L"italic", XFA_AttributeEnum::Italic}, + {0xe7ada113, L"author", XFA_AttributeEnum::Author}, + {0xe8e7cc18, L"toEdge", XFA_AttributeEnum::ToEdge}, + {0xe97aa98b, L"choice", XFA_AttributeEnum::Choice}, + {0xeafd2a38, L"disabled", XFA_AttributeEnum::Disabled}, + {0xeb2b7972, L"crossHatch", XFA_AttributeEnum::CrossHatch}, + {0xeb2db2d7, L"dataRef", XFA_AttributeEnum::DataRef}, + {0xec35dc6e, L"dashDotDot", XFA_AttributeEnum::DashDotDot}, + {0xef85d351, L"square", XFA_AttributeEnum::Square}, + {0xf2102445, L"dynamic", XFA_AttributeEnum::Dynamic}, + {0xf272c7be, L"manual", XFA_AttributeEnum::Manual}, + {0xf2bbb64d, L"etched", XFA_AttributeEnum::Etched}, + {0xf3b8fc6c, L"validationState", XFA_AttributeEnum::ValidationState}, + {0xf42f2b81, L"cursive", XFA_AttributeEnum::Cursive}, + {0xf54481d4, L"last", XFA_AttributeEnum::Last}, + {0xf5ad782b, L"left", XFA_AttributeEnum::Left}, + {0xf616da2e, L"link", XFA_AttributeEnum::Link}, + {0xf6b4afb0, L"long", XFA_AttributeEnum::Long}, {0xf8636460, L"internationalCarrier", - XFA_ATTRIBUTEENUM_InternationalCarrier}, - {0xf9fb37ac, L"PDF1.3", XFA_ATTRIBUTEENUM_PDF1_3}, - {0xf9fb37af, L"PDF1.6", XFA_ATTRIBUTEENUM_PDF1_6}, - {0xfbce7f19, L"serif", XFA_ATTRIBUTEENUM_Serif}, - {0xfc82d695, L"postSave", XFA_ATTRIBUTEENUM_PostSave}, - {0xfcef86b5, L"ready", XFA_ATTRIBUTEENUM_Ready}, - {0xfd54fbb7, L"postSign", XFA_ATTRIBUTEENUM_PostSign}, - {0xfdc0aae2, L"Arabic", XFA_ATTRIBUTEENUM_Arabic}, - {0xfe06d2ca, L"error", XFA_ATTRIBUTEENUM_Error}, - {0xfefc4885, L"urlencoded", XFA_ATTRIBUTEENUM_Urlencoded}, - {0xff795ad2, L"lowered", XFA_ATTRIBUTEENUM_Lowered}, + XFA_AttributeEnum::InternationalCarrier}, + {0xf9fb37ac, L"PDF1.3", XFA_AttributeEnum::PDF1_3}, + {0xf9fb37af, L"PDF1.6", XFA_AttributeEnum::PDF1_6}, + {0xfbce7f19, L"serif", XFA_AttributeEnum::Serif}, + {0xfc82d695, L"postSave", XFA_AttributeEnum::PostSave}, + {0xfcef86b5, L"ready", XFA_AttributeEnum::Ready}, + {0xfd54fbb7, L"postSign", XFA_AttributeEnum::PostSign}, + {0xfdc0aae2, L"Arabic", XFA_AttributeEnum::Arabic}, + {0xfe06d2ca, L"error", XFA_AttributeEnum::Error}, + {0xfefc4885, L"urlencoded", XFA_AttributeEnum::Urlencoded}, + {0xff795ad2, L"lowered", XFA_AttributeEnum::Lowered}, }; const int32_t g_iXFAEnumCount = - sizeof(g_XFAEnumData) / sizeof(XFA_ATTRIBUTEENUMINFO); + sizeof(g_XFAEnumData) / sizeof(XFA_AttributeEnumInfo); diff --git a/xfa/fxfa/parser/xfa_basic_data_packets.cpp b/xfa/fxfa/parser/xfa_basic_data_packets.cpp deleted file mode 100644 index 39a09dabd0aa1add9e7800d5009fb671126e44ff..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_basic_data_packets.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_basic_data.h" - -#include "xfa/fxfa/fxfa_basic.h" - -const XFA_PACKETINFO g_XFAPacketData[] = { - {0x0, nullptr, XFA_XDPPACKET_USER, nullptr, - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, - {0x811929d, L"sourceSet", XFA_XDPPACKET_SourceSet, - L"http://www.xfa.org/schema/xfa-source-set/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0xb843dba, L"pdf", XFA_XDPPACKET_Pdf, L"http://ns.adobe.com/xdp/pdf/", - XFA_XDPPACKET_FLAGS_COMPLETEMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0xc56afbf, L"xdc", XFA_XDPPACKET_Xdc, L"http://www.xfa.org/schema/xdc/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0xc56afcc, L"xdp", XFA_XDPPACKET_XDP, L"http://ns.adobe.com/xdp/", - XFA_XDPPACKET_FLAGS_COMPLETEMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0x132a8fbc, L"xmpmeta", XFA_XDPPACKET_Xmpmeta, - L"http://ns.adobe.com/xmpmeta/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, - {0x48d004a8, L"xfdf", XFA_XDPPACKET_Xfdf, L"http://ns.adobe.com/xfdf/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0x4e1e39b6, L"config", XFA_XDPPACKET_Config, - L"http://www.xfa.org/schema/xci/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0x5473b6dc, L"localeSet", XFA_XDPPACKET_LocaleSet, - L"http://www.xfa.org/schema/xfa-locale-set/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0x6038580a, L"stylesheet", XFA_XDPPACKET_Stylesheet, - L"http://www.w3.org/1999/XSL/Transform", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTMANY}, - {0x803550fc, L"template", XFA_XDPPACKET_Template, - L"http://www.xfa.org/schema/xfa-template/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0x8b036f32, L"signature", XFA_XDPPACKET_Signature, - L"http://www.w3.org/2000/09/xmldsig#", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0x99b95079, L"datasets", XFA_XDPPACKET_Datasets, - L"http://www.xfa.org/schema/xfa-data/", - XFA_XDPPACKET_FLAGS_PREFIXMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0xcd309ff4, L"form", XFA_XDPPACKET_Form, - L"http://www.xfa.org/schema/xfa-form/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, - {0xe14c801c, L"connectionSet", XFA_XDPPACKET_ConnectionSet, - L"http://www.xfa.org/schema/xfa-connection-set/", - XFA_XDPPACKET_FLAGS_NOMATCH | XFA_XDPPACKET_FLAGS_SUPPORTONE}, -}; -const int32_t g_iXFAPacketCount = - sizeof(g_XFAPacketData) / sizeof(XFA_PACKETINFO); diff --git a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp index 03ab81e39f2d069db9c96c12471916549eae8d53..f6f165fe59c7ca5e5de5f4318f82e79e8ec5c768 100644 --- a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp +++ b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp @@ -9,15 +9,31 @@ #include <map> #include <vector> -#include "core/fxcrt/fx_ext.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/xfa/cjx_object.h" +#include "third_party/base/logging.h" #include "third_party/base/stl_util.h" -#include "xfa/fde/xml/fde_xml_imp.h" +#include "xfa/fxfa/parser/cxfa_bind.h" +#include "xfa/fxfa/parser/cxfa_datagroup.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_exdata.h" +#include "xfa/fxfa/parser/cxfa_form.h" +#include "xfa/fxfa/parser/cxfa_image.h" +#include "xfa/fxfa/parser/cxfa_items.h" #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h" #include "xfa/fxfa/parser/cxfa_occur.h" -#include "xfa/fxfa/parser/cxfa_scriptcontext.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" +#include "xfa/fxfa/parser/cxfa_pageset.h" +#include "xfa/fxfa/parser/cxfa_subform.h" +#include "xfa/fxfa/parser/cxfa_template.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h" +#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h" +#include "xfa/fxfa/parser/cxfa_value.h" #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" #include "xfa/fxfa/parser/xfa_utils.h" @@ -32,7 +48,7 @@ class CXFA_TraverseStrategy_DDGroup { return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group); } static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) { - return pDDGroupNode->GetNodeItem(XFA_NODEITEM_Parent); + return pDDGroupNode->GetParent(); } }; @@ -41,73 +57,67 @@ struct RecurseRecord { CXFA_Node* pDataChild; }; -bool GetOccurInfo(CXFA_Node* pOccurNode, - int32_t& iMin, - int32_t& iMax, - int32_t& iInit) { - if (!pOccurNode) - return false; - - CXFA_Occur occur(pOccurNode); - return occur.GetOccurInfo(iMin, iMax, iInit); -} - CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) { - CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild); + CXFA_Node* pChildNode = pValueNode->GetFirstChild(); if (!pChildNode) { if (iType == XFA_Element::Unknown) return nullptr; - pChildNode = pValueNode->GetProperty(0, iType); + + pChildNode = + pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType); } return pChildNode; } void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) { - CXFA_WidgetData* pWidgetData = pFormNode->GetWidgetData(); - ASSERT(pWidgetData); - pWidgetData->GetUIType(); + CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc(); + ASSERT(pWidgetAcc); + pWidgetAcc->GetUIType(); } bool FormValueNode_SetChildContent(CXFA_Node* pValueNode, - const CFX_WideString& wsContent, + const WideString& wsContent, XFA_Element iType = XFA_Element::Unknown) { if (!pValueNode) return false; - ASSERT(pValueNode->GetPacketID() == XFA_XDPPACKET_Form); + ASSERT(pValueNode->GetPacketType() == XFA_PacketType::Form); CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType); if (!pChildNode) return false; switch (pChildNode->GetObjectType()) { case XFA_ObjectType::ContentNode: { - CXFA_Node* pContentRawDataNode = - pChildNode->GetNodeItem(XFA_NODEITEM_FirstChild); + CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild(); if (!pContentRawDataNode) { XFA_Element element = XFA_Element::Sharptext; if (pChildNode->GetElementType() == XFA_Element::ExData) { - CFX_WideString wsContentType; - pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, - false); - if (wsContentType == L"text/html") - element = XFA_Element::SharpxHTML; - else if (wsContentType == L"text/xml") - element = XFA_Element::Sharpxml; + Optional<WideString> contentType = + pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType, + false); + if (contentType) { + if (*contentType == L"text/html") + element = XFA_Element::SharpxHTML; + else if (*contentType == L"text/xml") + element = XFA_Element::Sharpxml; + } } pContentRawDataNode = pChildNode->CreateSamePacketNode(element); - pChildNode->InsertChild(pContentRawDataNode); + pChildNode->InsertChild(pContentRawDataNode, nullptr); } - pContentRawDataNode->SetCData(XFA_ATTRIBUTE_Value, wsContent); + pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, + false, false); break; } case XFA_ObjectType::NodeC: case XFA_ObjectType::TextNode: case XFA_ObjectType::NodeV: { - pChildNode->SetCData(XFA_ATTRIBUTE_Value, wsContent); + pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, false, + false); break; } default: - ASSERT(false); + NOTREACHED(); break; } return true; @@ -116,231 +126,243 @@ bool FormValueNode_SetChildContent(CXFA_Node* pValueNode, void CreateDataBinding(CXFA_Node* pFormNode, CXFA_Node* pDataNode, bool bDataToForm) { - pFormNode->SetObject(XFA_ATTRIBUTE_BindingNode, pDataNode); + pFormNode->SetBindingNode(pDataNode); pDataNode->AddBindItem(pFormNode); XFA_Element eType = pFormNode->GetElementType(); if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) return; - CXFA_WidgetData* pWidgetData = pFormNode->GetWidgetData(); - ASSERT(pWidgetData); - XFA_Element eUIType = pWidgetData->GetUIType(); - CXFA_Value defValue(pFormNode->GetProperty(0, XFA_Element::Value)); + CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc(); + ASSERT(pWidgetAcc); + XFA_Element eUIType = pWidgetAcc->GetUIType(); + auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>( + 0, XFA_Element::Value); if (!bDataToForm) { - CFX_WideString wsValue; - CFX_WideString wsFormattedValue; + WideString wsValue; switch (eUIType) { case XFA_Element::ImageEdit: { - CXFA_Image image = defValue.GetImage(); - CFX_WideString wsContentType; - CFX_WideString wsHref; + CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr; + WideString wsContentType; + WideString wsHref; if (image) { - image.GetContent(wsValue); - image.GetContentType(wsContentType); - image.GetHref(wsHref); + wsValue = image->GetContent(); + wsContentType = image->GetContentType(); + wsHref = image->GetHref(); } - CFDE_XMLElement* pXMLDataElement = - static_cast<CFDE_XMLElement*>(pDataNode->GetXMLMappingNode()); + CFX_XMLElement* pXMLDataElement = + static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode()); ASSERT(pXMLDataElement); - pWidgetData->GetFormatDataValue(wsValue, wsFormattedValue); - pDataNode->SetAttributeValue(wsValue, wsFormattedValue); - pDataNode->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType); + + pDataNode->JSObject()->SetAttributeValue( + wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false); + pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType, + wsContentType, false, false); if (!wsHref.IsEmpty()) pXMLDataElement->SetString(L"href", wsHref); break; } case XFA_Element::ChoiceList: - defValue.GetChildValueContent(wsValue); - if (pWidgetData->GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) { - std::vector<CFX_WideString> wsSelTextArray; - pWidgetData->GetSelectedItemsValue(wsSelTextArray); - int32_t iSize = pdfium::CollectionSize<int32_t>(wsSelTextArray); - if (iSize >= 1) { - CXFA_Node* pValue = nullptr; - for (int32_t i = 0; i < iSize; i++) { - pValue = pDataNode->CreateSamePacketNode(XFA_Element::DataValue); - pValue->SetCData(XFA_ATTRIBUTE_Name, L"value"); + wsValue = defValue ? defValue->GetChildValueContent() : L""; + if (pWidgetAcc->IsChoiceListMultiSelect()) { + std::vector<WideString> wsSelTextArray = + pWidgetAcc->GetSelectedItemsValue(); + if (!wsSelTextArray.empty()) { + for (const auto& text : wsSelTextArray) { + CXFA_Node* pValue = + pDataNode->CreateSamePacketNode(XFA_Element::DataValue); + pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value", false, + false); pValue->CreateXMLMappingNode(); - pDataNode->InsertChild(pValue); - pValue->SetCData(XFA_ATTRIBUTE_Value, wsSelTextArray[i]); + pDataNode->InsertChild(pValue, nullptr); + pValue->JSObject()->SetCData(XFA_Attribute::Value, text, false, + false); } } else { - CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); - ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element); - static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode", - L"dataGroup"); + CFX_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); + ASSERT(pXMLNode->GetType() == FX_XMLNODE_Element); + static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode", + L"dataGroup"); } } else if (!wsValue.IsEmpty()) { - pWidgetData->GetFormatDataValue(wsValue, wsFormattedValue); - pDataNode->SetAttributeValue(wsValue, wsFormattedValue); + pDataNode->JSObject()->SetAttributeValue( + wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false); } break; case XFA_Element::CheckButton: - defValue.GetChildValueContent(wsValue); + wsValue = defValue ? defValue->GetChildValueContent() : L""; if (wsValue.IsEmpty()) break; - pWidgetData->GetFormatDataValue(wsValue, wsFormattedValue); - pDataNode->SetAttributeValue(wsValue, wsFormattedValue); + pDataNode->JSObject()->SetAttributeValue( + wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false); break; case XFA_Element::ExclGroup: { CXFA_Node* pChecked = nullptr; - CXFA_Node* pChild = pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + CXFA_Node* pChild = pFormNode->GetFirstChild(); + for (; pChild; pChild = pChild->GetNextSibling()) { if (pChild->GetElementType() != XFA_Element::Field) continue; - CXFA_Node* pValue = pChild->GetChild(0, XFA_Element::Value); + auto* pValue = + pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false); if (!pValue) continue; - CXFA_Value valueChild(pValue); - valueChild.GetChildValueContent(wsValue); + wsValue = pValue->GetChildValueContent(); if (wsValue.IsEmpty()) continue; - CXFA_Node* pItems = pChild->GetChild(0, XFA_Element::Items); + CXFA_Items* pItems = + pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); if (!pItems) continue; - CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild); + CXFA_Node* pText = pItems->GetFirstChild(); if (!pText) continue; - CFX_WideString wsContent; - if (pText->TryContent(wsContent) && (wsContent == wsValue)) { + WideString wsContent = pText->JSObject()->GetContent(false); + if (wsContent == wsValue) { pChecked = pChild; - wsFormattedValue = wsValue; - pDataNode->SetAttributeValue(wsValue, wsFormattedValue); - pFormNode->SetCData(XFA_ATTRIBUTE_Value, wsContent); + pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue, false, + false); + pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, + false, false); break; } } if (!pChecked) break; - pChild = pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + pChild = pFormNode->GetFirstChild(); + for (; pChild; pChild = pChild->GetNextSibling()) { if (pChild == pChecked) continue; if (pChild->GetElementType() != XFA_Element::Field) continue; - CXFA_Node* pValue = pChild->GetProperty(0, XFA_Element::Value); - CXFA_Node* pItems = pChild->GetChild(0, XFA_Element::Items); - CXFA_Node* pText = - pItems ? pItems->GetNodeItem(XFA_NODEITEM_FirstChild) : nullptr; + CXFA_Value* pValue = + pChild->JSObject()->GetOrCreateProperty<CXFA_Value>( + 0, XFA_Element::Value); + CXFA_Items* pItems = + pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false); + CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr; if (pText) - pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling); + pText = pText->GetNextSibling(); - CFX_WideString wsContent; + WideString wsContent; if (pText) - pText->TryContent(wsContent); + wsContent = pText->JSObject()->GetContent(false); FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text); } break; } case XFA_Element::NumericEdit: { - defValue.GetChildValueContent(wsValue); + wsValue = defValue ? defValue->GetChildValueContent() : L""; if (wsValue.IsEmpty()) break; - CFX_WideString wsOutput; - pWidgetData->NormalizeNumStr(wsValue, wsOutput); - wsValue = wsOutput; - pWidgetData->GetFormatDataValue(wsValue, wsFormattedValue); - pDataNode->SetAttributeValue(wsValue, wsFormattedValue); - CXFA_Node* pValue = pFormNode->GetProperty(0, XFA_Element::Value); + wsValue = pWidgetAcc->NormalizeNumStr(wsValue); + pDataNode->JSObject()->SetAttributeValue( + wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false); + CXFA_Value* pValue = + pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>( + 0, XFA_Element::Value); FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float); break; } default: - defValue.GetChildValueContent(wsValue); + wsValue = defValue ? defValue->GetChildValueContent() : L""; if (wsValue.IsEmpty()) break; - pWidgetData->GetFormatDataValue(wsValue, wsFormattedValue); - pDataNode->SetAttributeValue(wsValue, wsFormattedValue); + pDataNode->JSObject()->SetAttributeValue( + wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false); break; } return; } - CFX_WideString wsXMLValue; - pDataNode->TryContent(wsXMLValue); - CFX_WideString wsNormalizeValue; - pWidgetData->GetNormalizeDataValue(wsXMLValue, wsNormalizeValue); - pDataNode->SetAttributeValue(wsNormalizeValue, wsXMLValue); + WideString wsXMLValue = pDataNode->JSObject()->GetContent(false); + WideString wsNormalizeValue = pWidgetAcc->GetNormalizeDataValue(wsXMLValue); + + pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue, false, + false); switch (eUIType) { case XFA_Element::ImageEdit: { - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::Image); - CXFA_Image image = defValue.GetImage(); + CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr; if (image) { - CFDE_XMLElement* pXMLDataElement = - static_cast<CFDE_XMLElement*>(pDataNode->GetXMLMappingNode()); + CFX_XMLElement* pXMLDataElement = + static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode()); ASSERT(pXMLDataElement); - CFX_WideString wsContentType; - CFX_WideString wsHref; - pXMLDataElement->GetString(L"xfa:contentType", wsContentType); + + WideString wsContentType = + pXMLDataElement->GetString(L"xfa:contentType"); if (!wsContentType.IsEmpty()) { - pDataNode->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType); - image.SetContentType(wsContentType); + pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType, + wsContentType, false, false); + image->SetContentType(wsContentType); } - pXMLDataElement->GetString(L"href", wsHref); + + WideString wsHref = pXMLDataElement->GetString(L"href"); if (!wsHref.IsEmpty()) - image.SetHref(wsHref); + image->SetHref(wsHref); } break; } case XFA_Element::ChoiceList: - if (pWidgetData->GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) { - CXFA_NodeArray items; - pDataNode->GetNodeList(items); - int32_t iCounts = items.GetSize(); - if (iCounts > 0) { + if (pWidgetAcc->IsChoiceListMultiSelect()) { + std::vector<CXFA_Node*> items = pDataNode->GetNodeList( + XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties, + XFA_Element::Unknown); + if (!items.empty()) { + bool single = items.size() == 1; wsNormalizeValue.clear(); - CFX_WideString wsItem; - for (int32_t i = 0; i < iCounts; i++) { - items[i]->TryContent(wsItem); - wsItem = (iCounts == 1) ? wsItem : wsItem + L"\n"; + + for (CXFA_Node* pNode : items) { + WideString wsItem = pNode->JSObject()->GetContent(false); + if (single) + wsItem += L"\n"; + wsNormalizeValue += wsItem; } - CXFA_ExData exData = defValue.GetExData(); + CXFA_ExData* exData = + defValue ? defValue->GetExDataIfExists() : nullptr; ASSERT(exData); - exData.SetContentType(iCounts == 1 ? L"text/plain" : L"text/xml"); + + exData->SetContentType(single ? L"text/plain" : L"text/xml"); } - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::ExData); } else { - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::Text); } break; case XFA_Element::CheckButton: - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::Text); break; case XFA_Element::ExclGroup: { - pWidgetData->SetSelectedMemberByValue(wsNormalizeValue.AsStringC(), false, - false, false); + pWidgetAcc->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(), + false, false, false); break; } case XFA_Element::DateTimeEdit: - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::DateTime); break; case XFA_Element::NumericEdit: { - CFX_WideString wsPicture; - pWidgetData->GetPictureContent(wsPicture, XFA_VALUEPICTURE_DataBind); - if (wsPicture.IsEmpty()) { - CFX_WideString wsOutput; - pWidgetData->NormalizeNumStr(wsNormalizeValue, wsOutput); - wsNormalizeValue = wsOutput; - } - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + WideString wsPicture = + pWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind); + if (wsPicture.IsEmpty()) + wsNormalizeValue = pWidgetAcc->NormalizeNumStr(wsNormalizeValue); + + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::Float); break; } @@ -350,7 +372,7 @@ void CreateDataBinding(CXFA_Node* pFormNode, case XFA_Element::Signature: case XFA_Element::TextEdit: default: - FormValueNode_SetChildContent(defValue.GetNode(), wsNormalizeValue, + FormValueNode_SetChildContent(defValue, wsNormalizeValue, XFA_Element::Text); break; } @@ -372,10 +394,10 @@ CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope, XFA_Element eMatchDataNodeType, bool bUpLevel) { for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr; - pCurDataScope && pCurDataScope->GetPacketID() == XFA_XDPPACKET_Datasets; + pCurDataScope && + pCurDataScope->GetPacketType() == XFA_PacketType::Datasets; pLastDataScope = pCurDataScope, - pCurDataScope = - pCurDataScope->GetNodeItem(XFA_NODEITEM_Parent)) { + pCurDataScope = pCurDataScope->GetParent()) { for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash); pDataChild; pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) { @@ -388,10 +410,12 @@ CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope, return pDataChild; } - for (CXFA_Node* pDataChild = - pCurDataScope->GetFirstChildByClass(XFA_Element::DataGroup); - pDataChild; pDataChild = pDataChild->GetNextSameClassSibling( - XFA_Element::DataGroup)) { + for (CXFA_DataGroup* pDataChild = + pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>( + XFA_Element::DataGroup); + pDataChild; + pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>( + XFA_Element::DataGroup)) { CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash, eMatchDataNodeType, false); if (pDataNode) @@ -404,13 +428,13 @@ CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope, } CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument, - CFX_WideStringC wsName, + const WideString& wsName, CXFA_Node* pDataScope, XFA_Element eMatchNodeType) { if (wsName.IsEmpty()) return nullptr; - uint32_t dwNameHash = FX_HashCode_GetW(wsName, false); + uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false); CXFA_Node* pBounded = GetGlobalBinding(pDocument, dwNameHash); if (!pBounded) { pBounded = @@ -422,17 +446,18 @@ CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument, } CXFA_Node* FindOnceDataNode(CXFA_Document* pDocument, - CFX_WideStringC wsName, + const WideString& wsName, CXFA_Node* pDataScope, XFA_Element eMatchNodeType) { if (wsName.IsEmpty()) return nullptr; - uint32_t dwNameHash = FX_HashCode_GetW(wsName, false); + uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false); CXFA_Node* pLastDataScope = nullptr; for (CXFA_Node* pCurDataScope = pDataScope; - pCurDataScope && pCurDataScope->GetPacketID() == XFA_XDPPACKET_Datasets; - pCurDataScope = pCurDataScope->GetNodeItem(XFA_NODEITEM_Parent)) { + pCurDataScope && + pCurDataScope->GetPacketType() == XFA_PacketType::Datasets; + pCurDataScope = pCurDataScope->GetParent()) { for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash); pDataChild; pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) { @@ -449,7 +474,7 @@ CXFA_Node* FindOnceDataNode(CXFA_Document* pDocument, } CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument, - CFX_WideStringC wsRef, + const WideString& wsRef, CXFA_Node* pDataScope, XFA_Element eMatchNodeType, CXFA_Node* pTemplateNode, @@ -460,16 +485,16 @@ CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument, dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); XFA_RESOLVENODE_RS rs; - pDocument->GetScriptContext()->ResolveObjects(pDataScope, wsRef, rs, dFlags, - pTemplateNode); - if (rs.dwFlags == XFA_RESOLVENODE_RSTYPE_CreateNodeAll || - rs.dwFlags == XFA_RESOLVENODE_RSTYPE_CreateNodeMidAll || - rs.nodes.GetSize() > 1) { - return pDocument->GetNotBindNode(rs.nodes); + pDocument->GetScriptContext()->ResolveObjects( + pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode); + if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeAll || + rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeMidAll || + rs.objects.size() > 1) { + return pDocument->GetNotBindNode(rs.objects); } - if (rs.dwFlags == XFA_RESOLVENODE_RSTYPE_CreateNodeOne) { - CXFA_Object* pObject = (rs.nodes.GetSize() > 0) ? rs.nodes[0] : nullptr; + if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) { + CXFA_Object* pObject = !rs.objects.empty() ? rs.objects.front() : nullptr; CXFA_Node* pNode = ToNode(pObject); return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr; } @@ -492,46 +517,47 @@ bool NeedGenerateForm(CXFA_Node* pTemplateChild, bool bUseInstanceManager) { CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument, CXFA_Node* pFormParent, CXFA_Node* pTemplateNode, - CXFA_NodeArray& subforms) { - CFX_WideStringC wsSubformName = pTemplateNode->GetCData(XFA_ATTRIBUTE_Name); - CFX_WideString wsInstMgrNodeName = L"_" + wsSubformName; + std::vector<CXFA_Node*>* subforms) { + WideString wsSubformName = + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name); + WideString wsInstMgrNodeName = L"_" + wsSubformName; uint32_t dwInstNameHash = - FX_HashCode_GetW(wsInstMgrNodeName.AsStringC(), false); + FX_HashCode_GetW(wsInstMgrNodeName.AsStringView(), false); CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance( pDocument, XFA_Element::InstanceManager, dwInstNameHash, pFormParent); if (pExistingNode) { uint32_t dwNameHash = pTemplateNode->GetNameHash(); - for (CXFA_Node* pNode = - pExistingNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pNode;) { + for (CXFA_Node* pNode = pExistingNode->GetNextSibling(); pNode;) { XFA_Element eCurType = pNode->GetElementType(); if (eCurType == XFA_Element::InstanceManager) break; if ((eCurType != XFA_Element::Subform) && (eCurType != XFA_Element::SubformSet)) { - pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling); + pNode = pNode->GetNextSibling(); continue; } if (dwNameHash != pNode->GetNameHash()) break; - CXFA_Node* pNextNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pFormParent->RemoveChild(pNode); - subforms.Add(pNode); + CXFA_Node* pNextNode = pNode->GetNextSibling(); + pFormParent->RemoveChild(pNode, true); + subforms->push_back(pNode); pNode = pNextNode; } - pFormParent->RemoveChild(pExistingNode); - pFormParent->InsertChild(pExistingNode); + pFormParent->RemoveChild(pExistingNode, true); + pFormParent->InsertChild(pExistingNode, nullptr); pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode); pExistingNode->SetTemplateNode(pTemplateNode); return pExistingNode; } CXFA_Node* pNewNode = - pDocument->CreateNode(XFA_XDPPACKET_Form, XFA_Element::InstanceManager); - wsInstMgrNodeName = L"_" + pTemplateNode->GetCData(XFA_ATTRIBUTE_Name); - pNewNode->SetCData(XFA_ATTRIBUTE_Name, wsInstMgrNodeName); + pDocument->CreateNode(XFA_PacketType::Form, XFA_Element::InstanceManager); + wsInstMgrNodeName = + L"_" + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name); + pNewNode->JSObject()->SetCData(XFA_Attribute::Name, wsInstMgrNodeName, false, + false); pFormParent->InsertChild(pNewNode, nullptr); pNewNode->SetTemplateNode(pTemplateNode); return pNewNode; @@ -547,18 +573,11 @@ CXFA_Node* FindMatchingDataNode( CXFA_TraverseStrategy_XFAContainerNode>* pIterator, bool& bSelfMatch, - XFA_ATTRIBUTEENUM& eBindMatch, + XFA_AttributeEnum& eBindMatch, bool bUpLevel) { - bool bOwnIterator = false; - if (!pIterator) { - bOwnIterator = true; - pIterator = new CXFA_NodeIteratorTemplate< - CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>(pTemplateNode); - } - CXFA_Node* pResult = nullptr; - for (CXFA_Node* pCurTemplateNode = pIterator->GetCurrent(); - pCurTemplateNode;) { + CXFA_Node* pCurTemplateNode = pIterator->GetCurrent(); + while (pCurTemplateNode) { XFA_Element eMatchNodeType; switch (pCurTemplateNode->GetElementType()) { case XFA_Element::Subform: @@ -576,26 +595,32 @@ CXFA_Node* FindMatchingDataNode( pCurTemplateNode = pIterator->MoveToNext(); continue; } - CXFA_Node* pTemplateNodeOccur = - pCurTemplateNode->GetFirstChildByClass(XFA_Element::Occur); - int32_t iMin, iMax, iInit; - if (pTemplateNodeOccur && - GetOccurInfo(pTemplateNodeOccur, iMin, iMax, iInit) && iMax == 0) { - pCurTemplateNode = pIterator->MoveToNext(); - continue; + + CXFA_Occur* pTemplateNodeOccur = + pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); + if (pTemplateNodeOccur) { + int32_t iMin; + int32_t iMax; + int32_t iInit; + std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo(); + if (iMax == 0) { + pCurTemplateNode = pIterator->MoveToNext(); + continue; + } } - CXFA_Node* pTemplateNodeBind = - pCurTemplateNode->GetFirstChildByClass(XFA_Element::Bind); - XFA_ATTRIBUTEENUM eMatch = - pTemplateNodeBind ? pTemplateNodeBind->GetEnum(XFA_ATTRIBUTE_Match) - : XFA_ATTRIBUTEENUM_Once; + CXFA_Bind* pTemplateNodeBind = + pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind); + XFA_AttributeEnum eMatch = + pTemplateNodeBind + ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match) + : XFA_AttributeEnum::Once; eBindMatch = eMatch; switch (eMatch) { - case XFA_ATTRIBUTEENUM_None: + case XFA_AttributeEnum::None: pCurTemplateNode = pIterator->MoveToNext(); continue; - case XFA_ATTRIBUTEENUM_Global: + case XFA_AttributeEnum::Global: bAccessedDataDOM = true; if (!bForceBind) { pCurTemplateNode = pIterator->MoveToNext(); @@ -605,7 +630,8 @@ CXFA_Node* FindMatchingDataNode( (eMatchNodeType == XFA_Element::DataGroup && XFA_FieldIsMultiListBox(pTemplateNodeBind))) { CXFA_Node* pGlobalBindNode = FindGlobalDataNode( - pDocument, pCurTemplateNode->GetCData(XFA_ATTRIBUTE_Name), + pDocument, + pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name), pDataScope, eMatchNodeType); if (!pGlobalBindNode) { pCurTemplateNode = pIterator->MoveToNext(); @@ -614,10 +640,11 @@ CXFA_Node* FindMatchingDataNode( pResult = pGlobalBindNode; break; } - case XFA_ATTRIBUTEENUM_Once: { + case XFA_AttributeEnum::Once: { bAccessedDataDOM = true; CXFA_Node* pOnceBindNode = FindOnceDataNode( - pDocument, pCurTemplateNode->GetCData(XFA_ATTRIBUTE_Name), + pDocument, + pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name), pDataScope, eMatchNodeType); if (!pOnceBindNode) { pCurTemplateNode = pIterator->MoveToNext(); @@ -626,10 +653,11 @@ CXFA_Node* FindMatchingDataNode( pResult = pOnceBindNode; break; } - case XFA_ATTRIBUTEENUM_DataRef: { + case XFA_AttributeEnum::DataRef: { bAccessedDataDOM = true; CXFA_Node* pDataRefBindNode = FindDataRefDataNode( - pDocument, pTemplateNodeBind->GetCData(XFA_ATTRIBUTE_Ref), + pDocument, + pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref), pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel); if (pDataRefBindNode && pDataRefBindNode->GetElementType() == eMatchNodeType) { @@ -648,44 +676,34 @@ CXFA_Node* FindMatchingDataNode( bSelfMatch = true; break; } - if (bOwnIterator) - delete pIterator; return pResult; } -void SortRecurseRecord(CFX_ArrayTemplate<RecurseRecord>& rgRecords, +void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords, CXFA_Node* pDataScope, bool bChoiceMode) { - int32_t iCount = rgRecords.GetSize(); - CFX_ArrayTemplate<RecurseRecord> rgResultRecord; - for (CXFA_Node* pChildNode = pDataScope->GetNodeItem(XFA_NODEITEM_FirstChild); - pChildNode; - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - for (int32_t i = 0; i < iCount; i++) { - CXFA_Node* pNode = rgRecords[i].pDataChild; - if (pChildNode == pNode) { - RecurseRecord sNewRecord = {rgRecords[i].pTemplateChild, pNode}; - rgResultRecord.Add(sNewRecord); - rgRecords.RemoveAt(i); - iCount--; + std::vector<RecurseRecord> rgResultRecord; + for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode; + pNode = pNode->GetNextSibling()) { + auto it = std::find_if(rgRecords->begin(), rgRecords->end(), + [pNode](const RecurseRecord& record) { + return pNode == record.pDataChild; + }); + if (it != rgRecords->end()) { + rgResultRecord.push_back(*it); + rgRecords->erase(it); + if (bChoiceMode) break; - } } - if (bChoiceMode && rgResultRecord.GetSize() > 0) - break; } + if (rgResultRecord.empty()) + return; - if (rgResultRecord.GetSize() > 0) { - if (!bChoiceMode) { - for (int32_t i = 0; i < iCount; i++) { - RecurseRecord sNewRecord = {rgRecords[i].pTemplateChild, - rgRecords[i].pDataChild}; - rgResultRecord.Add(sNewRecord); - } - } - rgRecords.RemoveAll(); - rgRecords.Copy(rgResultRecord); + if (!bChoiceMode) { + rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(), + rgRecords->end()); } + *rgRecords = rgResultRecord; } CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, @@ -700,22 +718,24 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, bool bUseInstanceManager = pFormParentNode->GetElementType() != XFA_Element::Area; CXFA_Node* pInstMgrNode = nullptr; - CXFA_NodeArray subformArray; - CXFA_NodeArray* pSearchArray = nullptr; + std::vector<CXFA_Node*> subformArray; + std::vector<CXFA_Node*>* pSearchArray = nullptr; if (!bOneInstance && (eType == XFA_Element::SubformSet || eType == XFA_Element::Subform)) { pInstMgrNode = bUseInstanceManager ? CloneOrMergeInstanceManager( pDocument, pFormParentNode, - pTemplateNode, subformArray) + pTemplateNode, &subformArray) : nullptr; - if (CXFA_Node* pOccurTemplateNode = - pTemplateNode->GetFirstChildByClass(XFA_Element::Occur)) { + if (CXFA_Occur* pOccurTemplateNode = + pTemplateNode->GetFirstChildByClass<CXFA_Occur>( + XFA_Element::Occur)) { pOccurNode = pInstMgrNode ? XFA_NodeMerge_CloneOrMergeContainer( pDocument, pInstMgrNode, pOccurTemplateNode, false, nullptr) : pOccurTemplateNode; } else if (pInstMgrNode) { - pOccurNode = pInstMgrNode->GetFirstChildByClass(XFA_Element::Occur); + pOccurNode = + pInstMgrNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur); if (pOccurNode) pOccurNode->ClearFlag(XFA_NodeFlag_UnusedNode); } @@ -724,10 +744,9 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, pSearchArray = &subformArray; if (pFormParentNode->GetElementType() == XFA_Element::PageArea) { bOneInstance = true; - if (subformArray.GetSize() < 1) + if (subformArray.empty()) pSearchArray = nullptr; - } else if ((pTemplateNode->GetNameHash() == 0) && - (subformArray.GetSize() < 1)) { + } else if (pTemplateNode->GetNameHash() == 0 && subformArray.empty()) { pSearchArray = nullptr; } } @@ -736,15 +755,17 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, int32_t iMax = 1; int32_t iInit = 1; int32_t iMin = 1; - if (!bOneInstance) - GetOccurInfo(pOccurNode, iMin, iMax, iInit); + if (!bOneInstance && pOccurNode) { + std::tie(iMin, iMax, iInit) = + static_cast<CXFA_Occur*>(pOccurNode)->GetOccurInfo(); + } - XFA_ATTRIBUTEENUM eRelation = + XFA_AttributeEnum eRelation = eType == XFA_Element::SubformSet - ? pTemplateNode->GetEnum(XFA_ATTRIBUTE_Relation) - : XFA_ATTRIBUTEENUM_Ordered; + ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation) + : XFA_AttributeEnum::Ordered; int32_t iCurRepeatIndex = 0; - XFA_ATTRIBUTEENUM eParentBindMatch = XFA_ATTRIBUTEENUM_None; + XFA_AttributeEnum eParentBindMatch = XFA_AttributeEnum::None; if (bDataMerge) { CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> sNodeIterator(pTemplateNode); @@ -753,10 +774,10 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, sNodeIterator.MoveToNext(); } else { std::map<CXFA_Node*, CXFA_Node*> subformMapArray; - CXFA_NodeArray nodeArray; + std::vector<CXFA_Node*> nodeArray; for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) { bool bSelfMatch = false; - XFA_ATTRIBUTEENUM eBindMatch = XFA_ATTRIBUTEENUM_None; + XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None; CXFA_Node* pDataNode = FindMatchingDataNode( pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false, &sNodeIterator, bSelfMatch, eBindMatch, true); @@ -772,19 +793,17 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, CreateDataBinding(pSubformNode, pDataNode, true); ASSERT(pSubformNode); subformMapArray[pSubformNode] = pDataNode; - nodeArray.Add(pSubformNode); + nodeArray.push_back(pSubformNode); } - for (int32_t iIndex = 0; iIndex < nodeArray.GetSize(); iIndex++) { - CXFA_Node* pSubform = nodeArray[iIndex]; + for (CXFA_Node* pSubform : nodeArray) { CXFA_Node* pDataNode = nullptr; auto it = subformMapArray.find(pSubform); if (it != subformMapArray.end()) pDataNode = it->second; - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; + pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubform, pTemplateChild, true, nullptr); @@ -799,80 +818,79 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) { bool bSelfMatch = false; - XFA_ATTRIBUTEENUM eBindMatch = XFA_ATTRIBUTEENUM_None; + XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None; if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false, &sNodeIterator, bSelfMatch, eBindMatch, true)) { break; } - if (eBindMatch == XFA_ATTRIBUTEENUM_DataRef && - eParentBindMatch == XFA_ATTRIBUTEENUM_DataRef) { + if (eBindMatch == XFA_AttributeEnum::DataRef && + eParentBindMatch == XFA_AttributeEnum::DataRef) { break; } - if (eRelation == XFA_ATTRIBUTEENUM_Choice || - eRelation == XFA_ATTRIBUTEENUM_Unordered) { + if (eRelation == XFA_AttributeEnum::Choice || + eRelation == XFA_AttributeEnum::Unordered) { CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer( pDocument, pFormParentNode, pTemplateNode, false, pSearchArray); ASSERT(pSubformSetNode); if (!pFirstInstance) pFirstInstance = pSubformSetNode; - CFX_ArrayTemplate<RecurseRecord> rgItemMatchList; - CFX_ArrayTemplate<CXFA_Node*> rgItemUnmatchList; - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + std::vector<RecurseRecord> rgItemMatchList; + std::vector<CXFA_Node*> rgItemUnmatchList; + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; + pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode, pTemplateChild, true, nullptr); } else if (pTemplateChild->IsContainerNode()) { bSelfMatch = false; - eBindMatch = XFA_ATTRIBUTEENUM_None; - if (eRelation != XFA_ATTRIBUTEENUM_Ordered) { + eBindMatch = XFA_AttributeEnum::None; + if (eRelation != XFA_AttributeEnum::Ordered) { + CXFA_NodeIteratorTemplate<CXFA_Node, + CXFA_TraverseStrategy_XFAContainerNode> + sChildIter(pTemplateChild); CXFA_Node* pDataMatch = FindMatchingDataNode( pDocument, pTemplateChild, pDataScope, bAccessedDataDOM, - false, nullptr, bSelfMatch, eBindMatch, true); + false, &sChildIter, bSelfMatch, eBindMatch, true); if (pDataMatch) { RecurseRecord sNewRecord = {pTemplateChild, pDataMatch}; if (bSelfMatch) - rgItemMatchList.InsertAt(0, sNewRecord); + rgItemMatchList.insert(rgItemMatchList.begin(), sNewRecord); else - rgItemMatchList.Add(sNewRecord); + rgItemMatchList.push_back(sNewRecord); } else { - rgItemUnmatchList.Add(pTemplateChild); + rgItemUnmatchList.push_back(pTemplateChild); } } else { - rgItemUnmatchList.Add(pTemplateChild); + rgItemUnmatchList.push_back(pTemplateChild); } } } switch (eRelation) { - case XFA_ATTRIBUTEENUM_Choice: { - ASSERT(rgItemMatchList.GetSize()); - SortRecurseRecord(rgItemMatchList, pDataScope, true); + case XFA_AttributeEnum::Choice: { + ASSERT(!rgItemMatchList.empty()); + SortRecurseRecord(&rgItemMatchList, pDataScope, true); pDocument->DataMerge_CopyContainer( - rgItemMatchList[0].pTemplateChild, pSubformSetNode, pDataScope, - false, true, true); + rgItemMatchList.front().pTemplateChild, pSubformSetNode, + pDataScope, false, true, true); break; } - case XFA_ATTRIBUTEENUM_Unordered: { - if (rgItemMatchList.GetSize()) { - SortRecurseRecord(rgItemMatchList, pDataScope, false); - for (int32_t i = 0, count = rgItemMatchList.GetSize(); i < count; - i++) { - pDocument->DataMerge_CopyContainer( - rgItemMatchList[i].pTemplateChild, pSubformSetNode, - pDataScope, false, true, true); + case XFA_AttributeEnum::Unordered: { + if (!rgItemMatchList.empty()) { + SortRecurseRecord(&rgItemMatchList, pDataScope, false); + for (const auto& matched : rgItemMatchList) { + pDocument->DataMerge_CopyContainer(matched.pTemplateChild, + pSubformSetNode, pDataScope, + false, true, true); } } - for (int32_t i = 0, count = rgItemUnmatchList.GetSize(); i < count; - i++) { - pDocument->DataMerge_CopyContainer(rgItemUnmatchList[i], - pSubformSetNode, pDataScope, - false, true, true); + for (auto* unmatched : rgItemUnmatchList) { + pDocument->DataMerge_CopyContainer(unmatched, pSubformSetNode, + pDataScope, false, true, true); } break; } @@ -886,10 +904,9 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, if (!pFirstInstance) pFirstInstance = pSubformSetNode; - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; + pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode, pTemplateChild, true, nullptr); @@ -904,14 +921,14 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, if (iCurRepeatIndex == 0 && bAccessedDataDOM == false) { int32_t iLimit = iMax; if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) { - iLimit = subformArray.GetSize(); + iLimit = pdfium::CollectionSize<int32_t>(subformArray); if (iLimit < iMin) iLimit = iInit; } for (; (iLimit < 0 || iCurRepeatIndex < iLimit); iCurRepeatIndex++) { if (pInstMgrNode) { - if (pSearchArray && pSearchArray->GetSize() < 1) { + if (pSearchArray && pSearchArray->empty()) { if (pTemplateNode->GetNameHash() != 0) break; pSearchArray = nullptr; @@ -927,10 +944,9 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, if (!pFirstInstance) pFirstInstance = pSubformNode; - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; + pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformNode, pTemplateChild, true, nullptr); @@ -952,15 +968,13 @@ CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument, pFirstInstance = pSubformSetNode; bool bFound = false; - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) { XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode, pTemplateChild, true, nullptr); } else if (pTemplateChild->IsContainerNode()) { - if (bFound && eRelation == XFA_ATTRIBUTEENUM_Choice) + if (bFound && eRelation == XFA_AttributeEnum::Choice) continue; pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, @@ -981,10 +995,9 @@ CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument, CXFA_Node* pFieldNode = XFA_NodeMerge_CloneOrMergeContainer( pDocument, pFormNode, pTemplateNode, false, nullptr); ASSERT(pFieldNode); - for (CXFA_Node* pTemplateChildNode = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChildNode; pTemplateChildNode = pTemplateChildNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild(); + pTemplateChildNode; + pTemplateChildNode = pTemplateChildNode->GetNextSibling()) { if (NeedGenerateForm(pTemplateChildNode, true)) { XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode, pTemplateChildNode, true, nullptr); @@ -999,10 +1012,12 @@ CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument, if (bDataMerge) { bool bAccessedDataDOM = false; bool bSelfMatch = false; - XFA_ATTRIBUTEENUM eBindMatch; + XFA_AttributeEnum eBindMatch; + CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode> + sNodeIter(pTemplateNode); CXFA_Node* pDataNode = FindMatchingDataNode( - pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true, nullptr, - bSelfMatch, eBindMatch, bUpLevel); + pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true, + &sNodeIter, bSelfMatch, eBindMatch, bUpLevel); if (pDataNode) CreateDataBinding(pFieldNode, pDataNode, true); } else { @@ -1014,17 +1029,17 @@ CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument, CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument, CXFA_Node* pDataParent, XFA_Element eNodeType, - const CFX_WideString& wsName) { + const WideString& wsName) { if (!pDataParent) return nullptr; CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode(); if (!pParentDDNode) { CXFA_Node* pDataNode = - pDocument->CreateNode(XFA_XDPPACKET_Datasets, eNodeType); - pDataNode->SetCData(XFA_ATTRIBUTE_Name, wsName); + pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType); + pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false); pDataNode->CreateXMLMappingNode(); - pDataParent->InsertChild(pDataNode); + pDataParent->InsertChild(pDataNode, nullptr); pDataNode->SetFlag(XFA_NodeFlag_Initialized, false); return pDataNode; } @@ -1037,28 +1052,29 @@ CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument, if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup) continue; - CFX_WideString wsNamespace; - if (!pDDGroupNode->TryNamespace(wsNamespace) || - wsNamespace != L"http://ns.adobe.com/data-description/") { + Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace(); + if (!ns || *ns != L"http://ns.adobe.com/data-description/") continue; - } } - CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(wsName.AsStringC()); + + CXFA_Node* pDDNode = + pDDGroupNode->GetFirstChildByName(wsName.AsStringView()); if (!pDDNode) continue; if (pDDNode->GetElementType() != eNodeType) break; CXFA_Node* pDataNode = - pDocument->CreateNode(XFA_XDPPACKET_Datasets, eNodeType); - pDataNode->SetCData(XFA_ATTRIBUTE_Name, wsName); + pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType); + pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false); pDataNode->CreateXMLMappingNode(); if (eNodeType == XFA_Element::DataValue && - pDDNode->GetEnum(XFA_ATTRIBUTE_Contains) == - XFA_ATTRIBUTEENUM_MetaData) { - pDataNode->SetEnum(XFA_ATTRIBUTE_Contains, XFA_ATTRIBUTEENUM_MetaData); + pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) == + XFA_AttributeEnum::MetaData) { + pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains, + XFA_AttributeEnum::MetaData, false); } - pDataParent->InsertChild(pDataNode); + pDataParent->InsertChild(pDataNode, nullptr); pDataNode->SetDataDescriptionNode(pDDNode); pDataNode->SetFlag(XFA_NodeFlag_Initialized, false); return pDataNode; @@ -1076,31 +1092,34 @@ void UpdateBindingRelations(CXFA_Document* pDocument, CXFA_Node* pDataNode = pFormNode->GetBindData(); if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup || eType == XFA_Element::Field) { - CXFA_Node* pTemplateNode = pFormNode->GetTemplateNode(); - CXFA_Node* pTemplateNodeBind = - pTemplateNode ? pTemplateNode->GetFirstChildByClass(XFA_Element::Bind) - : nullptr; - XFA_ATTRIBUTEENUM eMatch = - pTemplateNodeBind ? pTemplateNodeBind->GetEnum(XFA_ATTRIBUTE_Match) - : XFA_ATTRIBUTEENUM_Once; + CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists(); + CXFA_Bind* pTemplateNodeBind = + pTemplateNode + ? pTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind) + : nullptr; + XFA_AttributeEnum eMatch = + pTemplateNodeBind + ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match) + : XFA_AttributeEnum::Once; switch (eMatch) { - case XFA_ATTRIBUTEENUM_None: + case XFA_AttributeEnum::None: if (!bDataRef || bParentDataRef) FormValueNode_MatchNoneCreateChild(pFormNode); break; - case XFA_ATTRIBUTEENUM_Once: + case XFA_AttributeEnum::Once: if (!bDataRef || bParentDataRef) { if (!pDataNode) { if (pFormNode->GetNameHash() != 0 && - pFormNode->GetEnum(XFA_ATTRIBUTE_Scope) != - XFA_ATTRIBUTEENUM_None) { + pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) != + XFA_AttributeEnum::None) { XFA_Element eDataNodeType = (eType == XFA_Element::Subform || XFA_FieldIsMultiListBox(pFormNode)) ? XFA_Element::DataGroup : XFA_Element::DataValue; pDataNode = MaybeCreateDataNode( pDocument, pDataScope, eDataNodeType, - CFX_WideString(pFormNode->GetCData(XFA_ATTRIBUTE_Name))); + WideString( + pFormNode->JSObject()->GetCData(XFA_Attribute::Name))); if (pDataNode) CreateDataBinding(pFormNode, pDataNode, false); } @@ -1108,17 +1127,16 @@ void UpdateBindingRelations(CXFA_Document* pDocument, FormValueNode_MatchNoneCreateChild(pFormNode); } else { - CXFA_Node* pDataParent = - pDataNode->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_Node* pDataParent = pDataNode->GetParent(); if (pDataParent != pDataScope) { ASSERT(pDataParent); - pDataParent->RemoveChild(pDataNode); - pDataScope->InsertChild(pDataNode); + pDataParent->RemoveChild(pDataNode, true); + pDataScope->InsertChild(pDataNode, nullptr); } } } break; - case XFA_ATTRIBUTEENUM_Global: + case XFA_AttributeEnum::Global: if (!bDataRef || bParentDataRef) { uint32_t dwNameHash = pFormNode->GetNameHash(); if (dwNameHash != 0 && !pDataNode) { @@ -1132,7 +1150,8 @@ void UpdateBindingRelations(CXFA_Document* pDocument, ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record)); pDataNode = MaybeCreateDataNode( pDocument, pRecordNode, eDataNodeType, - CFX_WideString(pFormNode->GetCData(XFA_ATTRIBUTE_Name))); + WideString( + pFormNode->JSObject()->GetCData(XFA_Attribute::Name))); if (pDataNode) { CreateDataBinding(pFormNode, pDataNode, false); RegisterGlobalBinding(pDocument, pFormNode->GetNameHash(), @@ -1146,23 +1165,25 @@ void UpdateBindingRelations(CXFA_Document* pDocument, FormValueNode_MatchNoneCreateChild(pFormNode); } break; - case XFA_ATTRIBUTEENUM_DataRef: { + case XFA_AttributeEnum::DataRef: { bMatchRef = bDataRef; bParentDataRef = true; if (!pDataNode && bDataRef) { - CFX_WideStringC wsRef = - pTemplateNodeBind->GetCData(XFA_ATTRIBUTE_Ref); + WideString wsRef = + pTemplateNodeBind + ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref) + : L""; uint32_t dFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode; XFA_RESOLVENODE_RS rs; - pDocument->GetScriptContext()->ResolveObjects(pDataScope, wsRef, rs, - dFlags, pTemplateNode); + pDocument->GetScriptContext()->ResolveObjects( + pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode); CXFA_Object* pObject = - (rs.nodes.GetSize() > 0) ? rs.nodes[0] : nullptr; + !rs.objects.empty() ? rs.objects.front() : nullptr; pDataNode = ToNode(pObject); if (pDataNode) { CreateDataBinding(pFormNode, pDataNode, - rs.dwFlags == XFA_RESOVENODE_RSTYPE_ExistNodes); + rs.dwFlags == XFA_ResolveNode_RSType_ExistNodes); } else { FormValueNode_MatchNoneCreateChild(pFormNode); } @@ -1178,10 +1199,8 @@ void UpdateBindingRelations(CXFA_Document* pDocument, (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet || eType == XFA_Element::Area || eType == XFA_Element::PageArea || eType == XFA_Element::PageSet)) { - for (CXFA_Node* pFormChild = - pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pFormChild; - pFormChild = pFormChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild; + pFormChild = pFormChild->GetNextSibling()) { if (!pFormChild->IsContainerNode()) continue; if (pFormChild->IsUnusedNode()) @@ -1196,9 +1215,8 @@ void UpdateBindingRelations(CXFA_Document* pDocument, void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) { ASSERT(pDataDescriptionNode); - for (CXFA_Node* pDataChild = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pDataChild; - pDataChild = pDataChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild; + pDataChild = pDataChild->GetNextSibling()) { uint32_t dwNameHash = pDataChild->GetNameHash(); if (!dwNameHash) continue; @@ -1211,12 +1229,11 @@ void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) { if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup) continue; - CFX_WideString wsNamespace; - if (!pDDGroupNode->TryNamespace(wsNamespace) || - wsNamespace != L"http://ns.adobe.com/data-description/") { + Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace(); + if (!ns || *ns != L"http://ns.adobe.com/data-description/") continue; - } } + CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash); if (!pDDNode) continue; @@ -1236,9 +1253,8 @@ CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument, XFA_Element eType, uint32_t dwNameHash, CXFA_Node* pFormParent) { - CXFA_Node* pFormChild = pFormParent->GetNodeItem(XFA_NODEITEM_FirstChild); - for (; pFormChild; - pFormChild = pFormChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + CXFA_Node* pFormChild = pFormParent->GetFirstChild(); + for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) { if (pFormChild->GetElementType() == eType && pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) { return pFormChild; @@ -1247,35 +1263,33 @@ CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument, return nullptr; } -CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document* pDocument, - CXFA_Node* pFormParent, - CXFA_Node* pTemplateNode, - bool bRecursive, - CXFA_NodeArray* pSubformArray) { +CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer( + CXFA_Document* pDocument, + CXFA_Node* pFormParent, + CXFA_Node* pTemplateNode, + bool bRecursive, + std::vector<CXFA_Node*>* pSubformArray) { CXFA_Node* pExistingNode = nullptr; if (!pSubformArray) { pExistingNode = XFA_DataMerge_FindFormDOMInstance( pDocument, pTemplateNode->GetElementType(), pTemplateNode->GetNameHash(), pFormParent); - } else if (pSubformArray->GetSize() > 0) { - pExistingNode = pSubformArray->GetAt(0); - pSubformArray->RemoveAt(0); + } else if (!pSubformArray->empty()) { + pExistingNode = pSubformArray->front(); + pSubformArray->erase(pSubformArray->begin()); } - if (pExistingNode) { if (pSubformArray) { - pFormParent->InsertChild(pExistingNode); + pFormParent->InsertChild(pExistingNode, nullptr); } else if (pExistingNode->IsContainerNode()) { - pFormParent->RemoveChild(pExistingNode); - pFormParent->InsertChild(pExistingNode); + pFormParent->RemoveChild(pExistingNode, true); + pFormParent->InsertChild(pExistingNode, nullptr); } pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode); pExistingNode->SetTemplateNode(pTemplateNode); if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) { - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, true)) { XFA_NodeMerge_CloneOrMergeContainer( pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr); @@ -1289,10 +1303,8 @@ CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document* pDocument, CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false); pFormParent->InsertChild(pNewNode, nullptr); if (bRecursive) { - for (CXFA_Node* pTemplateChild = - pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem( - XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); + pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, true)) { CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true); pNewNode->InsertChild(pNewChild, nullptr); @@ -1305,7 +1317,7 @@ CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document* pDocument, CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) { for (CXFA_Node* pRootBoundNode = pParentFormNode; pRootBoundNode && pRootBoundNode->IsContainerNode(); - pRootBoundNode = pRootBoundNode->GetNodeItem(XFA_NODEITEM_Parent)) { + pRootBoundNode = pRootBoundNode->GetParent()) { CXFA_Node* pDataScope = pRootBoundNode->GetBindData(); if (pDataScope) return pDataScope; @@ -1337,7 +1349,7 @@ CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode, case XFA_Element::Variables: break; default: - ASSERT(false); + NOTREACHED(); break; } return nullptr; @@ -1345,8 +1357,8 @@ CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode, void CXFA_Document::DataMerge_UpdateBindingRelations( CXFA_Node* pFormUpdateRoot) { - CXFA_Node* pDataScope = XFA_DataMerge_FindDataScope( - pFormUpdateRoot->GetNodeItem(XFA_NODEITEM_Parent)); + CXFA_Node* pDataScope = + XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent()); if (!pDataScope) return; @@ -1354,9 +1366,10 @@ void CXFA_Document::DataMerge_UpdateBindingRelations( UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false); } -CXFA_Node* CXFA_Document::GetNotBindNode(CXFA_ObjArray& arrayNodes) { - for (int32_t i = 0; i < arrayNodes.GetSize(); i++) { - CXFA_Node* pNode = arrayNodes[i]->AsNode(); +CXFA_Node* CXFA_Document::GetNotBindNode( + const std::vector<CXFA_Object*>& arrayObjects) { + for (CXFA_Object* pObject : arrayObjects) { + CXFA_Node* pNode = pObject->AsNode(); if (pNode && !pNode->HasBindItem()) return pNode; } @@ -1366,35 +1379,38 @@ CXFA_Node* CXFA_Document::GetNotBindNode(CXFA_ObjArray& arrayNodes) { void CXFA_Document::DoDataMerge() { CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets)); if (!pDatasetsRoot) { - CFDE_XMLElement* pDatasetsXMLNode = new CFDE_XMLElement(L"xfa:datasets"); + CFX_XMLElement* pDatasetsXMLNode = new CFX_XMLElement(L"xfa:datasets"); pDatasetsXMLNode->SetString(L"xmlns:xfa", L"http://www.xfa.org/schema/xfa-data/1.0/"); - pDatasetsRoot = CreateNode(XFA_XDPPACKET_Datasets, XFA_Element::DataModel); - pDatasetsRoot->SetCData(XFA_ATTRIBUTE_Name, L"datasets"); + pDatasetsRoot = + CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel); + pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets", false, + false); m_pRootNode->GetXMLMappingNode()->InsertChildNode(pDatasetsXMLNode); - m_pRootNode->InsertChild(pDatasetsRoot); + m_pRootNode->InsertChild(pDatasetsRoot, nullptr); pDatasetsRoot->SetXMLMappingNode(pDatasetsXMLNode); } CXFA_Node *pDataRoot = nullptr, *pDDRoot = nullptr; - CFX_WideString wsDatasetsURI; - pDatasetsRoot->TryNamespace(wsDatasetsURI); - for (CXFA_Node* pChildNode = - pDatasetsRoot->GetNodeItem(XFA_NODEITEM_FirstChild); - pChildNode; - pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { + WideString wsDatasetsURI = + pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString()); + for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode; + pChildNode = pChildNode->GetNextSibling()) { if (pChildNode->GetElementType() != XFA_Element::DataGroup) continue; - CFX_WideString wsNamespaceURI; if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) { - if (!pChildNode->TryNamespace(wsNamespaceURI)) + Optional<WideString> namespaceURI = + pChildNode->JSObject()->TryNamespace(); + if (!namespaceURI) continue; - if (wsNamespaceURI == L"http://ns.adobe.com/data-description/") + if (*namespaceURI == L"http://ns.adobe.com/data-description/") pDDRoot = pChildNode; } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) { - if (!pChildNode->TryNamespace(wsNamespaceURI)) + Optional<WideString> namespaceURI = + pChildNode->JSObject()->TryNamespace(); + if (!namespaceURI) continue; - if (wsNamespaceURI == wsDatasetsURI) + if (*namespaceURI == wsDatasetsURI) pDataRoot = pChildNode; } if (pDataRoot && pDDRoot) @@ -1402,18 +1418,18 @@ void CXFA_Document::DoDataMerge() { } if (!pDataRoot) { - CFDE_XMLElement* pDataRootXMLNode = new CFDE_XMLElement(L"xfa:data"); - pDataRoot = CreateNode(XFA_XDPPACKET_Datasets, XFA_Element::DataGroup); - pDataRoot->SetCData(XFA_ATTRIBUTE_Name, L"data"); + CFX_XMLElement* pDataRootXMLNode = new CFX_XMLElement(L"xfa:data"); + pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup); + pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data", false, false); pDataRoot->SetXMLMappingNode(pDataRootXMLNode); - pDatasetsRoot->InsertChild(pDataRoot); + pDatasetsRoot->InsertChild(pDataRoot, nullptr); } - CXFA_Node* pDataTopLevel = - pDataRoot->GetFirstChildByClass(XFA_Element::DataGroup); + CXFA_DataGroup* pDataTopLevel = + pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup); uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0; - CXFA_Node* pTemplateRoot = - m_pRootNode->GetFirstChildByClass(XFA_Element::Template); + CXFA_Template* pTemplateRoot = + m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template); if (!pTemplateRoot) return; @@ -1422,18 +1438,21 @@ void CXFA_Document::DoDataMerge() { : nullptr; if (!pTemplateChosen || pTemplateChosen->GetElementType() != XFA_Element::Subform) { - pTemplateChosen = pTemplateRoot->GetFirstChildByClass(XFA_Element::Subform); + pTemplateChosen = + pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform); } if (!pTemplateChosen) return; - CXFA_Node* pFormRoot = m_pRootNode->GetFirstChildByClass(XFA_Element::Form); + CXFA_Form* pFormRoot = + m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form); bool bEmptyForm = false; if (!pFormRoot) { bEmptyForm = true; - pFormRoot = CreateNode(XFA_XDPPACKET_Form, XFA_Element::Form); + pFormRoot = static_cast<CXFA_Form*>( + CreateNode(XFA_PacketType::Form, XFA_Element::Form)); ASSERT(pFormRoot); - pFormRoot->SetCData(XFA_ATTRIBUTE_Name, L"form"); + pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form", false, false); m_pRootNode->InsertChild(pFormRoot, nullptr); } else { CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> @@ -1448,25 +1467,25 @@ void CXFA_Document::DoDataMerge() { this, pFormRoot, pTemplateChosen, false, nullptr); ASSERT(pSubformSetNode); if (!pDataTopLevel) { - CFX_WideStringC wsFormName = pSubformSetNode->GetCData(XFA_ATTRIBUTE_Name); - CFX_WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" - : wsFormName); - CFDE_XMLElement* pDataTopLevelXMLNode = - new CFDE_XMLElement(wsDataTopLevelName); - - pDataTopLevel = CreateNode(XFA_XDPPACKET_Datasets, XFA_Element::DataGroup); - pDataTopLevel->SetCData(XFA_ATTRIBUTE_Name, wsDataTopLevelName); + WideString wsFormName = + pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name); + WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName); + CFX_XMLElement* pDataTopLevelXMLNode = + new CFX_XMLElement(wsDataTopLevelName); + + pDataTopLevel = static_cast<CXFA_DataGroup*>( + CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup)); + pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name, wsDataTopLevelName, + false, false); pDataTopLevel->SetXMLMappingNode(pDataTopLevelXMLNode); - CXFA_Node* pBeforeNode = pDataRoot->GetNodeItem(XFA_NODEITEM_FirstChild); + CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild(); pDataRoot->InsertChild(pDataTopLevel, pBeforeNode); } ASSERT(pDataTopLevel); CreateDataBinding(pSubformSetNode, pDataTopLevel, true); - for (CXFA_Node* pTemplateChild = - pTemplateChosen->GetNodeItem(XFA_NODEITEM_FirstChild); - pTemplateChild; - pTemplateChild = pTemplateChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { + for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild(); + pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { if (NeedGenerateForm(pTemplateChild, true)) { XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild, true, nullptr); @@ -1479,13 +1498,14 @@ void CXFA_Document::DoDataMerge() { UpdateDataRelation(pDataRoot, pDDRoot); DataMerge_UpdateBindingRelations(pSubformSetNode); - CXFA_Node* pPageSetNode = - pSubformSetNode->GetFirstChildByClass(XFA_Element::PageSet); + CXFA_PageSet* pPageSetNode = + pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet); while (pPageSetNode) { - m_pPendingPageSet.Add(pPageSetNode); - CXFA_Node* pNextPageSetNode = - pPageSetNode->GetNextSameClassSibling(XFA_Element::PageSet); - pSubformSetNode->RemoveChild(pPageSetNode); + m_pPendingPageSet.push_back(pPageSetNode); + CXFA_PageSet* pNextPageSetNode = + pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>( + XFA_Element::PageSet); + pSubformSetNode->RemoveChild(pPageSetNode, true); pPageSetNode = pNextPageSetNode; } @@ -1500,7 +1520,7 @@ void CXFA_Document::DoDataMerge() { if (pNode->IsContainerNode() || pNode->GetElementType() == XFA_Element::InstanceManager) { CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext(); - pNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pNode); + pNode->GetParent()->RemoveChild(pNode, true); pNode = pNext; } else { pNode->ClearFlag(XFA_NodeFlag_UnusedNode); @@ -1517,11 +1537,13 @@ void CXFA_Document::DoDataMerge() { void CXFA_Document::DoDataRemerge(bool bDoDataMerge) { CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form)); if (pFormRoot) { - while (CXFA_Node* pNode = pFormRoot->GetNodeItem(XFA_NODEITEM_FirstChild)) - pFormRoot->RemoveChild(pNode); - pFormRoot->SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); + while (CXFA_Node* pNode = pFormRoot->GetFirstChild()) + pFormRoot->RemoveChild(pNode, true); + + pFormRoot->SetBindingNode(nullptr); } m_rgGlobalBinding.clear(); + if (bDoDataMerge) DoDataMerge(); diff --git a/xfa/fxfa/parser/xfa_document_datamerger_imp.h b/xfa/fxfa/parser/xfa_document_datamerger_imp.h index f9ea087731c809b9483e8af4085e75ab44cc4b71..9e58678867bf9339d7ef241dff3b91c4fcae7745 100644 --- a/xfa/fxfa/parser/xfa_document_datamerger_imp.h +++ b/xfa/fxfa/parser/xfa_document_datamerger_imp.h @@ -7,13 +7,19 @@ #ifndef XFA_FXFA_PARSER_XFA_DOCUMENT_DATAMERGER_IMP_H_ #define XFA_FXFA_PARSER_XFA_DOCUMENT_DATAMERGER_IMP_H_ -#include "xfa/fxfa/parser/xfa_object.h" +#include <vector> -CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document* pDocument, - CXFA_Node* pFormParent, - CXFA_Node* pTemplateNode, - bool bRecursive, - CXFA_NodeArray* pSubformArray); +#include "xfa/fxfa/fxfa_basic.h" + +class CXFA_Document; +class CXFA_Node; + +CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer( + CXFA_Document* pDocument, + CXFA_Node* pFormParent, + CXFA_Node* pTemplateNode, + bool bRecursive, + std::vector<CXFA_Node*>* pSubformArray); CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode); CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument, XFA_Element eType, diff --git a/xfa/fxfa/parser/xfa_layout_itemlayout.cpp b/xfa/fxfa/parser/xfa_layout_itemlayout.cpp deleted file mode 100644 index dd38c963d68b29d0180be027c69d756e79a18e91..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_layout_itemlayout.cpp +++ /dev/null @@ -1,2793 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_layout_itemlayout.h" - -#include <algorithm> -#include <memory> -#include <utility> -#include <vector> - -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fxfa/app/xfa_ffnotify.h" -#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" -#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_layoutpagemgr.h" -#include "xfa/fxfa/parser/cxfa_measurement.h" -#include "xfa/fxfa/parser/cxfa_occur.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -namespace { - -std::vector<CFX_WideString> SeparateStringW(const FX_WCHAR* pStr, - int32_t iStrLen, - FX_WCHAR delimiter) { - std::vector<CFX_WideString> ret; - if (!pStr) - return ret; - if (iStrLen < 0) - iStrLen = FXSYS_wcslen(pStr); - - const FX_WCHAR* pToken = pStr; - const FX_WCHAR* pEnd = pStr + iStrLen; - while (true) { - if (pStr >= pEnd || delimiter == *pStr) { - ret.push_back(CFX_WideString(pToken, pStr - pToken)); - pToken = pStr + 1; - if (pStr >= pEnd) - break; - } - pStr++; - } - return ret; -} - -void UpdateWidgetSize(CXFA_ContentLayoutItem* pLayoutItem, - FX_FLOAT* fWidth, - FX_FLOAT* fHeight) { - CXFA_Node* pNode = pLayoutItem->m_pFormNode; - switch (pNode->GetElementType()) { - case XFA_Element::Subform: - case XFA_Element::Area: - case XFA_Element::ExclGroup: - case XFA_Element::SubformSet: { - if (*fWidth < -XFA_LAYOUT_FLOAT_PERCISION) - *fWidth = pLayoutItem->m_sSize.width; - if (*fHeight < -XFA_LAYOUT_FLOAT_PERCISION) - *fHeight = pLayoutItem->m_sSize.height; - break; - } - case XFA_Element::Draw: - case XFA_Element::Field: { - pNode->GetDocument()->GetNotify()->StartFieldDrawLayout(pNode, *fWidth, - *fHeight); - break; - } - default: - ASSERT(false); - } -} - -CFX_SizeF CalculateContainerSpecifiedSize(CXFA_Node* pFormNode, - bool* bContainerWidthAutoSize, - bool* bContainerHeightAutoSize) { - *bContainerWidthAutoSize = true; - *bContainerHeightAutoSize = true; - - XFA_Element eType = pFormNode->GetElementType(); - CXFA_Measurement mTmpValue; - CFX_SizeF containerSize; - if ((eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup) && - pFormNode->TryMeasure(XFA_ATTRIBUTE_W, mTmpValue, false) && - mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { - containerSize.width = mTmpValue.ToUnit(XFA_UNIT_Pt); - *bContainerWidthAutoSize = false; - } - if ((eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup) && - pFormNode->TryMeasure(XFA_ATTRIBUTE_H, mTmpValue, false) && - mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { - containerSize.height = mTmpValue.ToUnit(XFA_UNIT_Pt); - *bContainerHeightAutoSize = false; - } - if (*bContainerWidthAutoSize && eType == XFA_Element::Subform && - pFormNode->TryMeasure(XFA_ATTRIBUTE_MaxW, mTmpValue, false) && - mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { - containerSize.width = mTmpValue.ToUnit(XFA_UNIT_Pt); - *bContainerWidthAutoSize = false; - } - if (*bContainerHeightAutoSize && eType == XFA_Element::Subform && - pFormNode->TryMeasure(XFA_ATTRIBUTE_MaxH, mTmpValue, false) && - mTmpValue.GetValue() > XFA_LAYOUT_FLOAT_PERCISION) { - containerSize.height = mTmpValue.ToUnit(XFA_UNIT_Pt); - *bContainerHeightAutoSize = false; - } - return containerSize; -} - -CFX_SizeF CalculateContainerComponentSizeFromContentSize( - CXFA_Node* pFormNode, - bool bContainerWidthAutoSize, - FX_FLOAT fContentCalculatedWidth, - bool bContainerHeightAutoSize, - FX_FLOAT fContentCalculatedHeight, - const CFX_SizeF& currentContainerSize) { - CFX_SizeF componentSize = currentContainerSize; - CXFA_Node* pMarginNode = pFormNode->GetFirstChildByClass(XFA_Element::Margin); - CXFA_Measurement mTmpValue; - if (bContainerWidthAutoSize) { - componentSize.width = fContentCalculatedWidth; - if (pMarginNode) { - if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_LeftInset, mTmpValue, false)) - componentSize.width += mTmpValue.ToUnit(XFA_UNIT_Pt); - if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_RightInset, mTmpValue, false)) - componentSize.width += mTmpValue.ToUnit(XFA_UNIT_Pt); - } - } - - if (bContainerHeightAutoSize) { - componentSize.height = fContentCalculatedHeight; - if (pMarginNode) { - if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_TopInset, mTmpValue, false)) - componentSize.height += mTmpValue.ToUnit(XFA_UNIT_Pt); - if (pMarginNode->TryMeasure(XFA_ATTRIBUTE_BottomInset, mTmpValue, - false)) { - componentSize.height += mTmpValue.ToUnit(XFA_UNIT_Pt); - } - } - } - return componentSize; -} - -void RelocateTableRowCells( - CXFA_ContentLayoutItem* pLayoutRow, - const CFX_ArrayTemplate<FX_FLOAT>& rgSpecifiedColumnWidths, - XFA_ATTRIBUTEENUM eLayout) { - bool bContainerWidthAutoSize = true; - bool bContainerHeightAutoSize = true; - CFX_SizeF containerSize = CalculateContainerSpecifiedSize( - pLayoutRow->m_pFormNode, &bContainerWidthAutoSize, - &bContainerHeightAutoSize); - CXFA_Node* pMarginNode = - pLayoutRow->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - FX_FLOAT fLeftInset = 0; - FX_FLOAT fTopInset = 0; - FX_FLOAT fRightInset = 0; - FX_FLOAT fBottomInset = 0; - if (pMarginNode) { - fLeftInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); - fTopInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); - fRightInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); - fBottomInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); - } - - FX_FLOAT fContentWidthLimit = - bContainerWidthAutoSize ? FLT_MAX - : containerSize.width - fLeftInset - fRightInset; - FX_FLOAT fContentCurrentHeight = - pLayoutRow->m_sSize.height - fTopInset - fBottomInset; - FX_FLOAT fContentCalculatedWidth = 0; - FX_FLOAT fContentCalculatedHeight = 0; - FX_FLOAT fCurrentColX = 0; - int32_t nCurrentColIdx = 0; - bool bMetWholeRowCell = false; - - for (auto pLayoutChild = - static_cast<CXFA_ContentLayoutItem*>(pLayoutRow->m_pFirstChild); - pLayoutChild; pLayoutChild = static_cast<CXFA_ContentLayoutItem*>( - pLayoutChild->m_pNextSibling)) { - int32_t nOriginalColSpan = - pLayoutChild->m_pFormNode->GetInteger(XFA_ATTRIBUTE_ColSpan); - int32_t nColSpan = nOriginalColSpan; - FX_FLOAT fColSpanWidth = 0; - if (nColSpan == -1 || - nCurrentColIdx + nColSpan > rgSpecifiedColumnWidths.GetSize()) { - nColSpan = rgSpecifiedColumnWidths.GetSize() - nCurrentColIdx; - } - for (int32_t i = 0; i < nColSpan; i++) - fColSpanWidth += rgSpecifiedColumnWidths[nCurrentColIdx + i]; - - if (nColSpan != nOriginalColSpan) { - fColSpanWidth = - bMetWholeRowCell ? 0 : std::max(fColSpanWidth, - pLayoutChild->m_sSize.height); - } - if (nOriginalColSpan == -1) - bMetWholeRowCell = true; - - pLayoutChild->m_sPos = CFX_PointF(fCurrentColX, 0); - pLayoutChild->m_sSize.width = fColSpanWidth; - if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) - continue; - - fCurrentColX += fColSpanWidth; - nCurrentColIdx += nColSpan; - FX_FLOAT fNewHeight = bContainerHeightAutoSize ? -1 : fContentCurrentHeight; - UpdateWidgetSize(pLayoutChild, &fColSpanWidth, &fNewHeight); - pLayoutChild->m_sSize.height = fNewHeight; - if (bContainerHeightAutoSize) { - fContentCalculatedHeight = - std::max(fContentCalculatedHeight, pLayoutChild->m_sSize.height); - } - } - - if (bContainerHeightAutoSize) { - for (CXFA_ContentLayoutItem* pLayoutChild = - (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; - pLayoutChild; - pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { - UpdateWidgetSize(pLayoutChild, &pLayoutChild->m_sSize.width, - &fContentCalculatedHeight); - FX_FLOAT fOldChildHeight = pLayoutChild->m_sSize.height; - pLayoutChild->m_sSize.height = fContentCalculatedHeight; - CXFA_Node* pParaNode = - pLayoutChild->m_pFormNode->GetFirstChildByClass(XFA_Element::Para); - if (pParaNode && pLayoutChild->m_pFirstChild) { - FX_FLOAT fOffHeight = fContentCalculatedHeight - fOldChildHeight; - XFA_ATTRIBUTEENUM eVType = pParaNode->GetEnum(XFA_ATTRIBUTE_VAlign); - switch (eVType) { - case XFA_ATTRIBUTEENUM_Middle: - fOffHeight = fOffHeight / 2; - break; - case XFA_ATTRIBUTEENUM_Bottom: - break; - case XFA_ATTRIBUTEENUM_Top: - default: - fOffHeight = 0; - break; - } - if (fOffHeight > 0) { - for (CXFA_ContentLayoutItem* pInnerLayoutChild = - (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild; - pInnerLayoutChild; - pInnerLayoutChild = - (CXFA_ContentLayoutItem*)pInnerLayoutChild->m_pNextSibling) { - pInnerLayoutChild->m_sPos.y += fOffHeight; - } - } - } - } - } - - if (bContainerWidthAutoSize) { - FX_FLOAT fChildSuppliedWidth = fCurrentColX; - if (fContentWidthLimit < FLT_MAX && - fContentWidthLimit > fChildSuppliedWidth) { - fChildSuppliedWidth = fContentWidthLimit; - } - fContentCalculatedWidth = - std::max(fContentCalculatedWidth, fChildSuppliedWidth); - } else { - fContentCalculatedWidth = containerSize.width - fLeftInset - fRightInset; - } - - if (pLayoutRow->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout) == - XFA_ATTRIBUTEENUM_Rl_row) { - for (CXFA_ContentLayoutItem* pLayoutChild = - (CXFA_ContentLayoutItem*)pLayoutRow->m_pFirstChild; - pLayoutChild; - pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { - pLayoutChild->m_sPos.x = fContentCalculatedWidth - - pLayoutChild->m_sPos.x - - pLayoutChild->m_sSize.width; - } - } - pLayoutRow->m_sSize = CalculateContainerComponentSizeFromContentSize( - pLayoutRow->m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); -} - -void UpdatePendingItemLayout(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_ContentLayoutItem* pLayoutItem) { - XFA_ATTRIBUTEENUM eLayout = - pLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - switch (eLayout) { - case XFA_ATTRIBUTEENUM_Row: - case XFA_ATTRIBUTEENUM_Rl_row: - RelocateTableRowCells(pLayoutItem, pProcessor->m_rgSpecifiedColumnWidths, - eLayout); - break; - default: - break; - } -} - -void AddTrailerBeforeSplit(CXFA_ItemLayoutProcessor* pProcessor, - FX_FLOAT fSplitPos, - CXFA_ContentLayoutItem* pTrailerLayoutItem, - bool bUseInherited) { - if (!pTrailerLayoutItem) - return; - - FX_FLOAT fHeight = pTrailerLayoutItem->m_sSize.height; - if (bUseInherited) { - FX_FLOAT fNewSplitPos = 0; - if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) - fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); - if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) - pProcessor->SplitLayoutItem(fNewSplitPos); - return; - } - - UpdatePendingItemLayout(pProcessor, pTrailerLayoutItem); - CXFA_Node* pMarginNode = - pProcessor->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - FX_FLOAT fLeftInset = 0; - FX_FLOAT fTopInset = 0; - FX_FLOAT fRightInset = 0; - FX_FLOAT fBottomInset = 0; - if (pMarginNode) { - fLeftInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); - fTopInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); - fRightInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); - fBottomInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); - } - - if (!pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem)) { - pTrailerLayoutItem->m_sPos.y = pProcessor->m_fLastRowY; - pTrailerLayoutItem->m_sPos.x = pProcessor->m_fLastRowWidth; - pProcessor->m_pLayoutItem->m_sSize.width += - pTrailerLayoutItem->m_sSize.width; - pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); - return; - } - - FX_FLOAT fNewSplitPos = 0; - if (fSplitPos - fHeight > XFA_LAYOUT_FLOAT_PERCISION) - fNewSplitPos = pProcessor->FindSplitPos(fSplitPos - fHeight); - - if (fNewSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { - pProcessor->SplitLayoutItem(fNewSplitPos); - pTrailerLayoutItem->m_sPos.y = fNewSplitPos - fTopInset - fBottomInset; - } else { - pTrailerLayoutItem->m_sPos.y = fSplitPos - fTopInset - fBottomInset; - } - - switch (pTrailerLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_HAlign)) { - case XFA_ATTRIBUTEENUM_Right: - pTrailerLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - - fRightInset - - pTrailerLayoutItem->m_sSize.width; - break; - case XFA_ATTRIBUTEENUM_Center: - pTrailerLayoutItem->m_sPos.x = - (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - - pTrailerLayoutItem->m_sSize.width) / - 2; - break; - case XFA_ATTRIBUTEENUM_Left: - default: - pTrailerLayoutItem->m_sPos.x = fLeftInset; - break; - } - pProcessor->m_pLayoutItem->m_sSize.height += fHeight; - pProcessor->m_pLayoutItem->AddChild(pTrailerLayoutItem); -} - -void AddLeaderAfterSplit(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_ContentLayoutItem* pLeaderLayoutItem) { - UpdatePendingItemLayout(pProcessor, pLeaderLayoutItem); - - CXFA_Node* pMarginNode = - pProcessor->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - FX_FLOAT fLeftInset = 0; - FX_FLOAT fRightInset = 0; - if (pMarginNode) { - fLeftInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); - fRightInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); - } - - FX_FLOAT fHeight = pLeaderLayoutItem->m_sSize.height; - for (CXFA_ContentLayoutItem* pChildItem = - (CXFA_ContentLayoutItem*)pProcessor->m_pLayoutItem->m_pFirstChild; - pChildItem; - pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { - pChildItem->m_sPos.y += fHeight; - } - pLeaderLayoutItem->m_sPos.y = 0; - - switch (pLeaderLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_HAlign)) { - case XFA_ATTRIBUTEENUM_Right: - pLeaderLayoutItem->m_sPos.x = pProcessor->m_pLayoutItem->m_sSize.width - - fRightInset - - pLeaderLayoutItem->m_sSize.width; - break; - case XFA_ATTRIBUTEENUM_Center: - pLeaderLayoutItem->m_sPos.x = - (pProcessor->m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset - - pLeaderLayoutItem->m_sSize.width) / - 2; - break; - case XFA_ATTRIBUTEENUM_Left: - default: - pLeaderLayoutItem->m_sPos.x = fLeftInset; - break; - } - pProcessor->m_pLayoutItem->m_sSize.height += fHeight; - pProcessor->m_pLayoutItem->AddChild(pLeaderLayoutItem); -} - -void AddPendingNode(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_Node* pPendingNode, - bool bBreakPending) { - pProcessor->m_PendingNodes.push_back(pPendingNode); - pProcessor->m_bBreakPending = bBreakPending; -} - -FX_FLOAT InsertPendingItems(CXFA_ItemLayoutProcessor* pProcessor, - CXFA_Node* pCurChildNode) { - FX_FLOAT fTotalHeight = 0; - if (pProcessor->m_PendingNodes.empty()) - return fTotalHeight; - - if (!pProcessor->m_pLayoutItem) { - pProcessor->m_pLayoutItem = - pProcessor->CreateContentLayoutItem(pCurChildNode); - pProcessor->m_pLayoutItem->m_sSize.clear(); - } - - while (!pProcessor->m_PendingNodes.empty()) { - auto pPendingProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - pProcessor->m_PendingNodes.front(), nullptr); - pProcessor->m_PendingNodes.pop_front(); - pPendingProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); - CXFA_ContentLayoutItem* pPendingLayoutItem = - pPendingProcessor->HasLayoutItem() - ? pPendingProcessor->ExtractLayoutItem() - : nullptr; - if (pPendingLayoutItem) { - AddLeaderAfterSplit(pProcessor, pPendingLayoutItem); - if (pProcessor->m_bBreakPending) - fTotalHeight += pPendingLayoutItem->m_sSize.height; - } - } - return fTotalHeight; -} - -XFA_ATTRIBUTEENUM GetLayout(CXFA_Node* pFormNode, bool* bRootForceTb) { - *bRootForceTb = false; - XFA_ATTRIBUTEENUM eLayoutMode; - if (pFormNode->TryEnum(XFA_ATTRIBUTE_Layout, eLayoutMode, false)) - return eLayoutMode; - - CXFA_Node* pParentNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent); - if (pParentNode && pParentNode->GetElementType() == XFA_Element::Form) { - *bRootForceTb = true; - return XFA_ATTRIBUTEENUM_Tb; - } - return XFA_ATTRIBUTEENUM_Position; -} - -bool ExistContainerKeep(CXFA_Node* pCurNode, bool bPreFind) { - if (!pCurNode || !XFA_ItemLayoutProcessor_IsTakingSpace(pCurNode)) - return false; - - XFA_NODEITEM eItemType = XFA_NODEITEM_PrevSibling; - if (!bPreFind) - eItemType = XFA_NODEITEM_NextSibling; - - CXFA_Node* pPreContainer = - pCurNode->GetNodeItem(eItemType, XFA_ObjectType::ContainerNode); - if (!pPreContainer) - return false; - - CXFA_Node* pKeep = pCurNode->GetFirstChildByClass(XFA_Element::Keep); - if (pKeep) { - XFA_ATTRIBUTEENUM ePrevious; - XFA_ATTRIBUTE eKeepType = XFA_ATTRIBUTE_Previous; - if (!bPreFind) - eKeepType = XFA_ATTRIBUTE_Next; - - if (pKeep->TryEnum(eKeepType, ePrevious, false)) { - if (ePrevious == XFA_ATTRIBUTEENUM_ContentArea || - ePrevious == XFA_ATTRIBUTEENUM_PageArea) { - return true; - } - } - } - - pKeep = pPreContainer->GetFirstChildByClass(XFA_Element::Keep); - if (!pKeep) - return false; - - XFA_ATTRIBUTE eKeepType = XFA_ATTRIBUTE_Next; - if (!bPreFind) - eKeepType = XFA_ATTRIBUTE_Previous; - - XFA_ATTRIBUTEENUM eNext; - if (!pKeep->TryEnum(eKeepType, eNext, false)) - return false; - if (eNext == XFA_ATTRIBUTEENUM_ContentArea || - eNext == XFA_ATTRIBUTEENUM_PageArea) { - return true; - } - return false; -} - -bool FindBreakNode(CXFA_Node* pContainerNode, - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages* nCurStage, - bool bBreakBefore) { - bool bFindRs = false; - for (CXFA_Node* pBreakNode = pContainerNode; pBreakNode; - pBreakNode = pBreakNode->GetNodeItem(XFA_NODEITEM_NextSibling)) { - XFA_ATTRIBUTE eAttributeType = XFA_ATTRIBUTE_Before; - if (!bBreakBefore) - eAttributeType = XFA_ATTRIBUTE_After; - - switch (pBreakNode->GetElementType()) { - case XFA_Element::BreakBefore: { - if (bBreakBefore) { - pCurActionNode = pBreakNode; - *nCurStage = XFA_ItemLayoutProcessorStages::BreakBefore; - bFindRs = true; - } - break; - } - case XFA_Element::BreakAfter: { - if (!bBreakBefore) { - pCurActionNode = pBreakNode; - *nCurStage = XFA_ItemLayoutProcessorStages::BreakAfter; - bFindRs = true; - } - break; - } - case XFA_Element::Break: - if (pBreakNode->GetEnum(eAttributeType) != XFA_ATTRIBUTEENUM_Auto) { - pCurActionNode = pBreakNode; - *nCurStage = XFA_ItemLayoutProcessorStages::BreakBefore; - if (!bBreakBefore) - *nCurStage = XFA_ItemLayoutProcessorStages::BreakAfter; - - bFindRs = true; - } - break; - default: - break; - } - if (bFindRs) - break; - } - return bFindRs; -} - -void DeleteLayoutGeneratedNode(CXFA_Node* pGenerateNode) { - CXFA_FFNotify* pNotify = pGenerateNode->GetDocument()->GetNotify(); - CXFA_LayoutProcessor* pDocLayout = - pGenerateNode->GetDocument()->GetDocLayout(); - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( - pGenerateNode); - for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode; - pNode = sIterator.MoveToNext()) { - CXFA_ContentLayoutItem* pCurLayoutItem = - (CXFA_ContentLayoutItem*)pNode->GetUserData(XFA_LAYOUTITEMKEY); - CXFA_ContentLayoutItem* pNextLayoutItem = nullptr; - while (pCurLayoutItem) { - pNextLayoutItem = pCurLayoutItem->m_pNext; - pNotify->OnLayoutItemRemoving(pDocLayout, pCurLayoutItem); - delete pCurLayoutItem; - pCurLayoutItem = pNextLayoutItem; - } - } - pGenerateNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pGenerateNode); -} - -uint8_t HAlignEnumToInt(XFA_ATTRIBUTEENUM eHAlign) { - switch (eHAlign) { - case XFA_ATTRIBUTEENUM_Center: - return 1; - case XFA_ATTRIBUTEENUM_Right: - return 2; - case XFA_ATTRIBUTEENUM_Left: - default: - return 0; - } -} - -XFA_ItemLayoutProcessorResult InsertFlowedItem( - CXFA_ItemLayoutProcessor* pThis, - CXFA_ItemLayoutProcessor* pProcessor, - bool bContainerWidthAutoSize, - bool bContainerHeightAutoSize, - FX_FLOAT fContainerHeight, - XFA_ATTRIBUTEENUM eFlowStrategy, - uint8_t* uCurHAlignState, - CFX_ArrayTemplate<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], - bool bUseBreakControl, - FX_FLOAT fAvailHeight, - FX_FLOAT fRealHeight, - FX_FLOAT fContentWidthLimit, - FX_FLOAT* fContentCurRowY, - FX_FLOAT* fContentCurRowAvailWidth, - FX_FLOAT* fContentCurRowHeight, - bool* bAddedItemInRow, - bool* bForceEndPage, - CXFA_LayoutContext* pLayoutContext, - bool bNewRow) { - bool bTakeSpace = - XFA_ItemLayoutProcessor_IsTakingSpace(pProcessor->m_pFormNode); - uint8_t uHAlign = - HAlignEnumToInt(pThis->m_pCurChildNode->GetEnum(XFA_ATTRIBUTE_HAlign)); - if (bContainerWidthAutoSize) - uHAlign = 0; - - if ((eFlowStrategy != XFA_ATTRIBUTEENUM_Rl_tb && - uHAlign < *uCurHAlignState) || - (eFlowStrategy == XFA_ATTRIBUTEENUM_Rl_tb && - uHAlign > *uCurHAlignState)) { - return XFA_ItemLayoutProcessorResult::RowFullBreak; - } - - *uCurHAlignState = uHAlign; - bool bIsOwnSplit = - pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None; - bool bUseRealHeight = - bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit && - pProcessor->m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent)->GetIntact() == - XFA_ATTRIBUTEENUM_None; - bool bIsTransHeight = bTakeSpace; - if (bIsTransHeight && !bIsOwnSplit) { - bool bRootForceTb = false; - XFA_ATTRIBUTEENUM eLayoutStrategy = - GetLayout(pProcessor->m_pFormNode, &bRootForceTb); - if (eLayoutStrategy == XFA_ATTRIBUTEENUM_Lr_tb || - eLayoutStrategy == XFA_ATTRIBUTEENUM_Rl_tb) { - bIsTransHeight = false; - } - } - - bool bUseInherited = false; - CXFA_LayoutContext layoutContext; - if (pThis->m_pPageMgr) { - CXFA_Node* pOverflowNode = - pThis->m_pPageMgr->QueryOverflow(pThis->m_pFormNode); - if (pOverflowNode) { - layoutContext.m_pOverflowNode = pOverflowNode; - layoutContext.m_pOverflowProcessor = pThis; - pLayoutContext = &layoutContext; - } - } - - XFA_ItemLayoutProcessorResult eRetValue = XFA_ItemLayoutProcessorResult::Done; - if (!bNewRow || - pProcessor->m_ePreProcessRs == XFA_ItemLayoutProcessorResult::Done) { - eRetValue = pProcessor->DoLayout( - bTakeSpace ? bUseBreakControl : false, - bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, - bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX, - pLayoutContext); - pProcessor->m_ePreProcessRs = eRetValue; - } else { - eRetValue = pProcessor->m_ePreProcessRs; - pProcessor->m_ePreProcessRs = XFA_ItemLayoutProcessorResult::Done; - } - if (pProcessor->HasLayoutItem() == false) - return eRetValue; - - CFX_SizeF childSize = pProcessor->GetCurrentComponentSize(); - if (bUseRealHeight && fRealHeight < XFA_LAYOUT_FLOAT_PERCISION) { - fRealHeight = FLT_MAX; - fAvailHeight = FLT_MAX; - } - if (bTakeSpace && (childSize.width > - *fContentCurRowAvailWidth + XFA_LAYOUT_FLOAT_PERCISION) && - (fContentWidthLimit - *fContentCurRowAvailWidth > - XFA_LAYOUT_FLOAT_PERCISION)) { - return XFA_ItemLayoutProcessorResult::RowFullBreak; - } - - CXFA_Node* pOverflowLeaderNode = nullptr; - CXFA_Node* pOverflowTrailerNode = nullptr; - CXFA_Node* pFormNode = nullptr; - CXFA_ContentLayoutItem* pTrailerLayoutItem = nullptr; - bool bIsAddTrailerHeight = false; - if (pThis->m_pPageMgr && - pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None) { - pFormNode = pThis->m_pPageMgr->QueryOverflow(pProcessor->m_pFormNode); - if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) { - pFormNode = pLayoutContext->m_pOverflowNode; - bUseInherited = true; - } - if (pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, - pOverflowTrailerNode, false, - false)) { - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) { - if (pOverflowTrailerNode) { - auto pOverflowLeaderProcessor = - pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pOverflowTrailerNode, - nullptr); - pOverflowLeaderProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); - pTrailerLayoutItem = - pOverflowLeaderProcessor->HasLayoutItem() - ? pOverflowLeaderProcessor->ExtractLayoutItem() - : nullptr; - } - - bIsAddTrailerHeight = - bUseInherited - ? pThis->IsAddNewRowForTrailer(pTrailerLayoutItem) - : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem); - if (bIsAddTrailerHeight) { - childSize.height += pTrailerLayoutItem->m_sSize.height; - bIsAddTrailerHeight = true; - } - } - } - } - - if (!bTakeSpace || - *fContentCurRowY + childSize.height <= - fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION || - (!bContainerHeightAutoSize && - pThis->m_fUsedSize + fAvailHeight + XFA_LAYOUT_FLOAT_PERCISION >= - fContainerHeight)) { - if (!bTakeSpace || eRetValue == XFA_ItemLayoutProcessorResult::Done) { - if (pProcessor->m_bUseInheriated) { - if (pTrailerLayoutItem) - AddTrailerBeforeSplit(pProcessor, childSize.height, - pTrailerLayoutItem, false); - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) - AddPendingNode(pProcessor, pOverflowLeaderNode, false); - - pProcessor->m_bUseInheriated = false; - } else { - if (bIsAddTrailerHeight) - childSize.height -= pTrailerLayoutItem->m_sSize.height; - - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - } - - CXFA_ContentLayoutItem* pChildLayoutItem = - pProcessor->ExtractLayoutItem(); - if (ExistContainerKeep(pProcessor->m_pFormNode, false) && - pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None) { - pThis->m_arrayKeepItems.push_back(pChildLayoutItem); - } else { - pThis->m_arrayKeepItems.clear(); - } - rgCurLineLayoutItems[uHAlign].Add(pChildLayoutItem); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = - std::max(*fContentCurRowHeight, childSize.height); - } - return XFA_ItemLayoutProcessorResult::Done; - } - - if (eRetValue == XFA_ItemLayoutProcessorResult::PageFullBreak) { - if (pProcessor->m_bUseInheriated) { - if (pTrailerLayoutItem) { - AddTrailerBeforeSplit(pProcessor, childSize.height, - pTrailerLayoutItem, false); - } - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) - AddPendingNode(pProcessor, pOverflowLeaderNode, false); - - pProcessor->m_bUseInheriated = false; - } else { - if (bIsAddTrailerHeight) - childSize.height -= pTrailerLayoutItem->m_sSize.height; - - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - } - } - rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); - return eRetValue; - } - - XFA_ItemLayoutProcessorResult eResult; - if (pThis->ProcessKeepForSplit( - pThis, pProcessor, eRetValue, &rgCurLineLayoutItems[uHAlign], - fContentCurRowAvailWidth, fContentCurRowHeight, fContentCurRowY, - bAddedItemInRow, bForceEndPage, &eResult)) { - return eResult; - } - - *bForceEndPage = true; - FX_FLOAT fSplitPos = - pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY); - if (fSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { - XFA_ATTRIBUTEENUM eLayout = - pProcessor->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - if (eLayout == XFA_ATTRIBUTEENUM_Tb && - eRetValue == XFA_ItemLayoutProcessorResult::Done) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, pTrailerLayoutItem, - pFormNode); - rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = - std::max(*fContentCurRowHeight, childSize.height); - } - return XFA_ItemLayoutProcessorResult::PageFullBreak; - } - - CXFA_Node* pTempLeaderNode = nullptr; - CXFA_Node* pTempTrailerNode = nullptr; - if (pThis->m_pPageMgr && !pProcessor->m_bUseInheriated && - eRetValue != XFA_ItemLayoutProcessorResult::PageFullBreak) { - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, - pTempTrailerNode, false, true); - } - if (pTrailerLayoutItem && bIsAddTrailerHeight) { - AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, - bUseInherited); - } else { - pProcessor->SplitLayoutItem(fSplitPos); - } - - if (bUseInherited) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, pTrailerLayoutItem, - pFormNode); - pThis->m_bUseInheriated = true; - } else { - CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->m_pFirstChild; - if (firstChild && !firstChild->m_pNextSibling && - firstChild->m_pFormNode->IsLayoutGeneratedNode()) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - } else if (pProcessor->JudgeLeaderOrTrailerForOccur( - pOverflowLeaderNode)) { - AddPendingNode(pProcessor, pOverflowLeaderNode, false); - } - } - - if (pProcessor->m_pLayoutItem->m_pNextSibling) { - childSize = pProcessor->GetCurrentComponentSize(); - rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = - std::max(*fContentCurRowHeight, childSize.height); - } - } - return XFA_ItemLayoutProcessorResult::PageFullBreak; - } - - if (*fContentCurRowY <= XFA_LAYOUT_FLOAT_PERCISION) { - childSize = pProcessor->GetCurrentComponentSize(); - if (pProcessor->m_pPageMgr->GetNextAvailContentHeight(childSize.height)) { - CXFA_Node* pTempLeaderNode = nullptr; - CXFA_Node* pTempTrailerNode = nullptr; - if (pThis->m_pPageMgr) { - if (!pFormNode && pLayoutContext) - pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; - - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pTempLeaderNode, - pTempTrailerNode, false, true); - } - if (bUseInherited) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, - pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - pThis->m_bUseInheriated = true; - } - return XFA_ItemLayoutProcessorResult::PageFullBreak; - } - - rgCurLineLayoutItems[uHAlign].Add(pProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - if (bTakeSpace) { - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); - } - if (eRetValue == XFA_ItemLayoutProcessorResult::Done) - *bForceEndPage = false; - - return eRetValue; - } - - XFA_ATTRIBUTEENUM eLayout = - pProcessor->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - if (pProcessor->m_pFormNode->GetIntact() == XFA_ATTRIBUTEENUM_None && - eLayout == XFA_ATTRIBUTEENUM_Tb) { - if (pThis->m_pPageMgr) { - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, - pOverflowTrailerNode, false, true); - } - if (pTrailerLayoutItem) - AddTrailerBeforeSplit(pProcessor, fSplitPos, pTrailerLayoutItem, false); - if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode)) - AddPendingNode(pProcessor, pOverflowLeaderNode, false); - - return XFA_ItemLayoutProcessorResult::PageFullBreak; - } - - if (eRetValue != XFA_ItemLayoutProcessorResult::Done) - return XFA_ItemLayoutProcessorResult::PageFullBreak; - - if (!pFormNode && pLayoutContext) - pFormNode = pLayoutContext->m_pOverflowProcessor->m_pFormNode; - if (pThis->m_pPageMgr) { - pThis->m_pPageMgr->ProcessOverflow(pFormNode, pOverflowLeaderNode, - pOverflowTrailerNode, false, true); - } - if (bUseInherited) { - pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode, - pTrailerLayoutItem, pFormNode); - pThis->m_bUseInheriated = true; - } - return XFA_ItemLayoutProcessorResult::PageFullBreak; -} - -bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem, - FX_FLOAT fCurVerticalOffset, - FX_FLOAT* fProposedSplitPos, - bool* bAppChange, - bool bCalculateMargin) { - CXFA_Node* pFormNode = pLayoutItem->m_pFormNode; - if (*fProposedSplitPos <= fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION || - *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height - - XFA_LAYOUT_FLOAT_PERCISION) { - return false; - } - - switch (pFormNode->GetIntact()) { - case XFA_ATTRIBUTEENUM_None: { - bool bAnyChanged = false; - CXFA_Document* pDocument = pFormNode->GetDocument(); - CXFA_FFNotify* pNotify = pDocument->GetNotify(); - FX_FLOAT fCurTopMargin = 0, fCurBottomMargin = 0; - CXFA_Node* pMarginNode = - pFormNode->GetFirstChildByClass(XFA_Element::Margin); - if (pMarginNode && bCalculateMargin) { - fCurTopMargin = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); - fCurBottomMargin = pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset) - .ToUnit(XFA_UNIT_Pt); - } - bool bChanged = true; - while (bChanged) { - bChanged = false; - { - FX_FLOAT fRelSplitPos = *fProposedSplitPos - fCurVerticalOffset; - if (pNotify->FindSplitPos(pFormNode, pLayoutItem->GetIndex(), - fRelSplitPos)) { - bAnyChanged = true; - bChanged = true; - *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos; - *bAppChange = true; - if (*fProposedSplitPos <= - fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { - return true; - } - } - } - FX_FLOAT fRelSplitPos = *fProposedSplitPos - fCurBottomMargin; - for (CXFA_ContentLayoutItem* pChildItem = - (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; - pChildItem; - pChildItem = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling) { - FX_FLOAT fChildOffset = - fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y; - bool bChange = false; - if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos, - &bChange, bCalculateMargin)) { - if (fRelSplitPos - fChildOffset < XFA_LAYOUT_FLOAT_PERCISION && - bChange) { - *fProposedSplitPos = fRelSplitPos - fCurTopMargin; - } else { - *fProposedSplitPos = fRelSplitPos + fCurBottomMargin; - } - bAnyChanged = true; - bChanged = true; - if (*fProposedSplitPos <= - fCurVerticalOffset + XFA_LAYOUT_FLOAT_PERCISION) { - return true; - } - if (bAnyChanged) - break; - } - } - } - return bAnyChanged; - } - case XFA_ATTRIBUTEENUM_ContentArea: - case XFA_ATTRIBUTEENUM_PageArea: { - *fProposedSplitPos = fCurVerticalOffset; - return true; - } - default: - return false; - } -} - -CFX_PointF CalculatePositionedContainerPos(CXFA_Node* pNode, - const CFX_SizeF& size) { - XFA_ATTRIBUTEENUM eAnchorType = pNode->GetEnum(XFA_ATTRIBUTE_AnchorType); - int32_t nAnchorType = 0; - switch (eAnchorType) { - case XFA_ATTRIBUTEENUM_TopLeft: - nAnchorType = 0; - break; - case XFA_ATTRIBUTEENUM_TopCenter: - nAnchorType = 1; - break; - case XFA_ATTRIBUTEENUM_TopRight: - nAnchorType = 2; - break; - case XFA_ATTRIBUTEENUM_MiddleLeft: - nAnchorType = 3; - break; - case XFA_ATTRIBUTEENUM_MiddleCenter: - nAnchorType = 4; - break; - case XFA_ATTRIBUTEENUM_MiddleRight: - nAnchorType = 5; - break; - case XFA_ATTRIBUTEENUM_BottomLeft: - nAnchorType = 6; - break; - case XFA_ATTRIBUTEENUM_BottomCenter: - nAnchorType = 7; - break; - case XFA_ATTRIBUTEENUM_BottomRight: - nAnchorType = 8; - break; - default: - break; - } - static const uint8_t nNextPos[4][9] = {{0, 1, 2, 3, 4, 5, 6, 7, 8}, - {6, 3, 0, 7, 4, 1, 8, 5, 2}, - {8, 7, 6, 5, 4, 3, 2, 1, 0}, - {2, 5, 8, 1, 4, 7, 0, 3, 6}}; - - CFX_PointF pos(pNode->GetMeasure(XFA_ATTRIBUTE_X).ToUnit(XFA_UNIT_Pt), - pNode->GetMeasure(XFA_ATTRIBUTE_Y).ToUnit(XFA_UNIT_Pt)); - int32_t nRotate = - FXSYS_round(pNode->GetMeasure(XFA_ATTRIBUTE_Rotate).GetValue()); - nRotate = XFA_MapRotation(nRotate) / 90; - int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType]; - switch (nAbsoluteAnchorType / 3) { - case 1: - pos.y -= size.height / 2; - break; - case 2: - pos.y -= size.height; - break; - default: - break; - } - switch (nAbsoluteAnchorType % 3) { - case 1: - pos.x -= size.width / 2; - break; - case 2: - pos.x -= size.width; - break; - default: - break; - } - return pos; -} - -} // namespace - -CXFA_ItemLayoutProcessor::CXFA_ItemLayoutProcessor(CXFA_Node* pNode, - CXFA_LayoutPageMgr* pPageMgr) - : m_pFormNode(pNode), - m_pLayoutItem(nullptr), - m_pCurChildNode(XFA_LAYOUT_INVALIDNODE), - m_fUsedSize(0), - m_pPageMgr(pPageMgr), - m_bBreakPending(true), - m_fLastRowWidth(0), - m_fLastRowY(0), - m_bUseInheriated(false), - m_ePreProcessRs(XFA_ItemLayoutProcessorResult::Done), - m_bKeepBreakFinish(false), - m_bIsProcessKeep(false), - m_pKeepHeadNode(nullptr), - m_pKeepTailNode(nullptr), - m_pOldLayoutItem(nullptr), - m_pCurChildPreprocessor(nullptr), - m_nCurChildNodeStage(XFA_ItemLayoutProcessorStages::None), - m_fWidthLimite(0), - m_bHasAvailHeight(true) { - ASSERT(m_pFormNode && (m_pFormNode->IsContainerNode() || - m_pFormNode->GetElementType() == XFA_Element::Form)); - m_pOldLayoutItem = - (CXFA_ContentLayoutItem*)m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY); -} - -CXFA_ItemLayoutProcessor::~CXFA_ItemLayoutProcessor() {} - -CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::CreateContentLayoutItem( - CXFA_Node* pFormNode) { - if (!pFormNode) - return nullptr; - - CXFA_ContentLayoutItem* pLayoutItem = nullptr; - if (m_pOldLayoutItem) { - pLayoutItem = m_pOldLayoutItem; - m_pOldLayoutItem = m_pOldLayoutItem->m_pNext; - return pLayoutItem; - } - pLayoutItem = (CXFA_ContentLayoutItem*)pFormNode->GetDocument() - ->GetNotify() - ->OnCreateLayoutItem(pFormNode); - CXFA_ContentLayoutItem* pPrevLayoutItem = - (CXFA_ContentLayoutItem*)pFormNode->GetUserData(XFA_LAYOUTITEMKEY); - if (pPrevLayoutItem) { - while (pPrevLayoutItem->m_pNext) - pPrevLayoutItem = pPrevLayoutItem->m_pNext; - - pPrevLayoutItem->m_pNext = pLayoutItem; - pLayoutItem->m_pPrev = pPrevLayoutItem; - } else { - pFormNode->SetUserData(XFA_LAYOUTITEMKEY, pLayoutItem); - } - return pLayoutItem; -} - -FX_FLOAT CXFA_ItemLayoutProcessor::FindSplitPos(FX_FLOAT fProposedSplitPos) { - ASSERT(m_pLayoutItem); - XFA_ATTRIBUTEENUM eLayout = m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - bool bCalculateMargin = eLayout != XFA_ATTRIBUTEENUM_Position; - while (fProposedSplitPos > XFA_LAYOUT_FLOAT_PERCISION) { - bool bAppChange = false; - if (!FindLayoutItemSplitPos(m_pLayoutItem, 0, &fProposedSplitPos, - &bAppChange, bCalculateMargin)) { - break; - } - } - return fProposedSplitPos; -} - -void CXFA_ItemLayoutProcessor::SplitLayoutItem( - CXFA_ContentLayoutItem* pLayoutItem, - CXFA_ContentLayoutItem* pSecondParent, - FX_FLOAT fSplitPos) { - FX_FLOAT fCurTopMargin = 0, fCurBottomMargin = 0; - XFA_ATTRIBUTEENUM eLayout = m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - bool bCalculateMargin = true; - if (eLayout == XFA_ATTRIBUTEENUM_Position) - bCalculateMargin = false; - - CXFA_Node* pMarginNode = - pLayoutItem->m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - if (pMarginNode && bCalculateMargin) { - fCurTopMargin = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); - fCurBottomMargin = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); - } - - CXFA_ContentLayoutItem* pSecondLayoutItem = nullptr; - if (m_pCurChildPreprocessor && - m_pCurChildPreprocessor->m_pFormNode == pLayoutItem->m_pFormNode) { - pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem( - pLayoutItem->m_pFormNode); - } else { - pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem->m_pFormNode); - } - pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x; - pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width; - pSecondLayoutItem->m_sPos.y = 0; - pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos; - pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height; - if (pLayoutItem->m_pFirstChild) - pSecondLayoutItem->m_sSize.height += fCurTopMargin; - - if (pSecondParent) { - pSecondParent->AddChild(pSecondLayoutItem); - if (fCurTopMargin > 0 && pLayoutItem->m_pFirstChild) { - pSecondParent->m_sSize.height += fCurTopMargin; - CXFA_ContentLayoutItem* pParentItem = - (CXFA_ContentLayoutItem*)pSecondParent->m_pParent; - while (pParentItem) { - pParentItem->m_sSize.height += fCurTopMargin; - pParentItem = (CXFA_ContentLayoutItem*)pParentItem->m_pParent; - } - } - } else { - pSecondLayoutItem->m_pParent = pLayoutItem->m_pParent; - pSecondLayoutItem->m_pNextSibling = pLayoutItem->m_pNextSibling; - pLayoutItem->m_pNextSibling = pSecondLayoutItem; - } - - CXFA_ContentLayoutItem* pChildren = - (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild; - pLayoutItem->m_pFirstChild = nullptr; - FX_FLOAT lHeightForKeep = 0; - CFX_ArrayTemplate<CXFA_ContentLayoutItem*> keepLayoutItems; - FX_FLOAT fAddMarginHeight = 0; - for (CXFA_ContentLayoutItem *pChildItem = pChildren, *pChildNext = nullptr; - pChildItem; pChildItem = pChildNext) { - pChildNext = (CXFA_ContentLayoutItem*)pChildItem->m_pNextSibling; - pChildItem->m_pNextSibling = nullptr; - if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin + - XFA_LAYOUT_FLOAT_PERCISION) { - if (!ExistContainerKeep(pChildItem->m_pFormNode, true)) { - pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin; - pChildItem->m_sPos.y += lHeightForKeep; - pChildItem->m_sPos.y += fAddMarginHeight; - pSecondLayoutItem->AddChild(pChildItem); - continue; - } - - if (lHeightForKeep < XFA_LAYOUT_FLOAT_PERCISION) { - for (int32_t iIndex = 0; iIndex < keepLayoutItems.GetSize(); iIndex++) { - CXFA_ContentLayoutItem* pPreItem = keepLayoutItems[iIndex]; - pLayoutItem->RemoveChild(pPreItem); - pPreItem->m_sPos.y -= fSplitPos; - if (pPreItem->m_sPos.y < 0) - pPreItem->m_sPos.y = 0; - - if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) { - pPreItem->m_sPos.y = lHeightForKeep; - lHeightForKeep += pPreItem->m_sSize.height; - pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height; - if (pSecondParent) - pSecondParent->m_sSize.height += pPreItem->m_sSize.height; - } - pSecondLayoutItem->AddChild(pPreItem); - } - } - - pChildItem->m_sPos.y -= fSplitPos; - pChildItem->m_sPos.y += lHeightForKeep; - pChildItem->m_sPos.y += fAddMarginHeight; - pSecondLayoutItem->AddChild(pChildItem); - continue; - } - - if (fSplitPos + XFA_LAYOUT_FLOAT_PERCISION >= - fCurTopMargin + fCurBottomMargin + pChildItem->m_sPos.y + - pChildItem->m_sSize.height) { - pLayoutItem->AddChild(pChildItem); - if (ExistContainerKeep(pChildItem->m_pFormNode, false)) - keepLayoutItems.Add(pChildItem); - else - keepLayoutItems.RemoveAll(); - - continue; - } - - FX_FLOAT fOldHeight = pSecondLayoutItem->m_sSize.height; - SplitLayoutItem( - pChildItem, pSecondLayoutItem, - fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y); - fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight; - pLayoutItem->AddChild(pChildItem); - } -} - -void CXFA_ItemLayoutProcessor::SplitLayoutItem(FX_FLOAT fSplitPos) { - ASSERT(m_pLayoutItem); - SplitLayoutItem(m_pLayoutItem, nullptr, fSplitPos); -} - -CXFA_ContentLayoutItem* CXFA_ItemLayoutProcessor::ExtractLayoutItem() { - CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem; - if (pLayoutItem) { - m_pLayoutItem = - static_cast<CXFA_ContentLayoutItem*>(pLayoutItem->m_pNextSibling); - pLayoutItem->m_pNextSibling = nullptr; - } - - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done || - !ToContentLayoutItem(m_pOldLayoutItem)) { - return pLayoutItem; - } - - if (m_pOldLayoutItem->m_pPrev) - m_pOldLayoutItem->m_pPrev->m_pNext = nullptr; - - CXFA_FFNotify* pNotify = - m_pOldLayoutItem->m_pFormNode->GetDocument()->GetNotify(); - CXFA_LayoutProcessor* pDocLayout = - m_pOldLayoutItem->m_pFormNode->GetDocument()->GetDocLayout(); - CXFA_ContentLayoutItem* pOldLayoutItem = m_pOldLayoutItem; - while (pOldLayoutItem) { - CXFA_ContentLayoutItem* pNextOldLayoutItem = pOldLayoutItem->m_pNext; - pNotify->OnLayoutItemRemoving(pDocLayout, pOldLayoutItem); - if (pOldLayoutItem->m_pParent) - pOldLayoutItem->m_pParent->RemoveChild(pOldLayoutItem); - - delete pOldLayoutItem; - pOldLayoutItem = pNextOldLayoutItem; - } - m_pOldLayoutItem = nullptr; - return pLayoutItem; -} - -void CXFA_ItemLayoutProcessor::GotoNextContainerNode( - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node* pParentContainer, - bool bUsePageBreak) { - CXFA_Node* pEntireContainer = pParentContainer; - CXFA_Node* pChildContainer = XFA_LAYOUT_INVALIDNODE; - switch (nCurStage) { - case XFA_ItemLayoutProcessorStages::BreakBefore: - case XFA_ItemLayoutProcessorStages::BreakAfter: { - pChildContainer = pCurActionNode->GetNodeItem(XFA_NODEITEM_Parent); - break; - } - case XFA_ItemLayoutProcessorStages::Keep: - case XFA_ItemLayoutProcessorStages::Container: - pChildContainer = pCurActionNode; - break; - default: - pChildContainer = XFA_LAYOUT_INVALIDNODE; - break; - } - - switch (nCurStage) { - case XFA_ItemLayoutProcessorStages::Keep: { - CXFA_Node* pBreakAfterNode = - pChildContainer->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!m_bKeepBreakFinish && - FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false)) { - return; - } - goto CheckNextChildContainer; - } - case XFA_ItemLayoutProcessorStages::None: { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BookendLeader: - for (CXFA_Node* pBookendNode = - pCurActionNode == XFA_LAYOUT_INVALIDNODE - ? pEntireContainer->GetNodeItem(XFA_NODEITEM_FirstChild) - : pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pBookendNode; pBookendNode = pBookendNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { - switch (pBookendNode->GetElementType()) { - case XFA_Element::Bookend: - case XFA_Element::Break: - pCurActionNode = pBookendNode; - nCurStage = XFA_ItemLayoutProcessorStages::BookendLeader; - return; - default: - break; - } - } - } - { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BreakBefore: - if (pCurActionNode != XFA_LAYOUT_INVALIDNODE) { - CXFA_Node* pBreakBeforeNode = - pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); - if (!m_bKeepBreakFinish && - FindBreakNode(pBreakBeforeNode, pCurActionNode, &nCurStage, - true)) { - return; - } - if (m_bIsProcessKeep) { - if (ProcessKeepNodesForBreakBefore(pCurActionNode, nCurStage, - pChildContainer)) { - return; - } - goto CheckNextChildContainer; - } - pCurActionNode = pChildContainer; - nCurStage = XFA_ItemLayoutProcessorStages::Container; - return; - } - goto CheckNextChildContainer; - } - case XFA_ItemLayoutProcessorStages::Container: { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BreakAfter: { - if (pCurActionNode == XFA_LAYOUT_INVALIDNODE) { - CXFA_Node* pBreakAfterNode = - pChildContainer->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!m_bKeepBreakFinish && - FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, - false)) { - return; - } - } else { - CXFA_Node* pBreakAfterNode = - pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); - if (FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, - false)) { - return; - } - } - goto CheckNextChildContainer; - } - } - - CheckNextChildContainer : { - CXFA_Node* pNextChildContainer = - pChildContainer == XFA_LAYOUT_INVALIDNODE - ? pEntireContainer->GetNodeItem(XFA_NODEITEM_FirstChild, - XFA_ObjectType::ContainerNode) - : pChildContainer->GetNodeItem(XFA_NODEITEM_NextSibling, - XFA_ObjectType::ContainerNode); - while (pNextChildContainer && - pNextChildContainer->IsLayoutGeneratedNode()) { - CXFA_Node* pSaveNode = pNextChildContainer; - pNextChildContainer = pNextChildContainer->GetNodeItem( - XFA_NODEITEM_NextSibling, XFA_ObjectType::ContainerNode); - if (pSaveNode->IsUnusedNode()) - DeleteLayoutGeneratedNode(pSaveNode); - } - if (!pNextChildContainer) - goto NoMoreChildContainer; - - bool bLastKeep = false; - if (ProcessKeepNodesForCheckNext(pCurActionNode, nCurStage, - pNextChildContainer, bLastKeep)) { - return; - } - if (!m_bKeepBreakFinish && !bLastKeep && - FindBreakNode( - pNextChildContainer->GetNodeItem(XFA_NODEITEM_FirstChild), - pCurActionNode, &nCurStage, true)) { - return; - } - pCurActionNode = pNextChildContainer; - if (m_bIsProcessKeep) - nCurStage = XFA_ItemLayoutProcessorStages::Keep; - else - nCurStage = XFA_ItemLayoutProcessorStages::Container; - return; - } - - NoMoreChildContainer : { - pCurActionNode = XFA_LAYOUT_INVALIDNODE; - case XFA_ItemLayoutProcessorStages::BookendTrailer: - for (CXFA_Node* pBookendNode = - pCurActionNode == XFA_LAYOUT_INVALIDNODE - ? pEntireContainer->GetNodeItem(XFA_NODEITEM_FirstChild) - : pCurActionNode->GetNodeItem(XFA_NODEITEM_NextSibling); - pBookendNode; pBookendNode = pBookendNode->GetNodeItem( - XFA_NODEITEM_NextSibling)) { - switch (pBookendNode->GetElementType()) { - case XFA_Element::Bookend: - case XFA_Element::Break: - pCurActionNode = pBookendNode; - nCurStage = XFA_ItemLayoutProcessorStages::BookendTrailer; - return; - default: - break; - } - } - } - default: - pCurActionNode = nullptr; - nCurStage = XFA_ItemLayoutProcessorStages::Done; - } -} - -bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForCheckNext( - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node*& pNextContainer, - bool& bLastKeepNode) { - const bool bCanSplit = pNextContainer->GetIntact() == XFA_ATTRIBUTEENUM_None; - bool bNextKeep = false; - if (ExistContainerKeep(pNextContainer, false)) - bNextKeep = true; - - if (bNextKeep && !bCanSplit) { - if (!m_bIsProcessKeep && !m_bKeepBreakFinish) { - m_pKeepHeadNode = pNextContainer; - m_bIsProcessKeep = true; - } - return false; - } - - if (m_bIsProcessKeep && m_pKeepHeadNode) { - m_pKeepTailNode = pNextContainer; - if (!m_bKeepBreakFinish && - FindBreakNode(pNextContainer->GetNodeItem(XFA_NODEITEM_FirstChild), - pCurActionNode, &nCurStage, true)) { - return true; - } - - pNextContainer = m_pKeepHeadNode; - m_bKeepBreakFinish = true; - m_pKeepHeadNode = nullptr; - m_pKeepTailNode = nullptr; - m_bIsProcessKeep = false; - } else { - if (m_bKeepBreakFinish) - bLastKeepNode = true; - m_bKeepBreakFinish = false; - } - - return false; -} - -bool CXFA_ItemLayoutProcessor::ProcessKeepNodesForBreakBefore( - CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node* pContainerNode) { - if (m_pKeepTailNode == pContainerNode) { - pCurActionNode = m_pKeepHeadNode; - m_bKeepBreakFinish = true; - m_pKeepHeadNode = nullptr; - m_pKeepTailNode = nullptr; - m_bIsProcessKeep = false; - nCurStage = XFA_ItemLayoutProcessorStages::Container; - return true; - } - - CXFA_Node* pBreakAfterNode = - pContainerNode->GetNodeItem(XFA_NODEITEM_FirstChild); - return FindBreakNode(pBreakAfterNode, pCurActionNode, &nCurStage, false); -} - -bool XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node* pNode) { - XFA_ATTRIBUTEENUM ePresence = pNode->GetEnum(XFA_ATTRIBUTE_Presence); - return ePresence == XFA_ATTRIBUTEENUM_Visible || - ePresence == XFA_ATTRIBUTEENUM_Invisible; -} - -bool CXFA_ItemLayoutProcessor::IncrementRelayoutNode( - CXFA_LayoutProcessor* pLayoutProcessor, - CXFA_Node* pNode, - CXFA_Node* pParentNode) { - return false; -} - -void CXFA_ItemLayoutProcessor::DoLayoutPageArea( - CXFA_ContainerLayoutItem* pPageAreaLayoutItem) { - CXFA_Node* pFormNode = pPageAreaLayoutItem->m_pFormNode; - CXFA_Node* pCurChildNode = XFA_LAYOUT_INVALIDNODE; - XFA_ItemLayoutProcessorStages nCurChildNodeStage = - XFA_ItemLayoutProcessorStages::None; - CXFA_LayoutItem* pBeforeItem = nullptr; - for (GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, pFormNode, - false); - pCurChildNode; GotoNextContainerNode(pCurChildNode, nCurChildNodeStage, - pFormNode, false)) { - if (nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) - continue; - if (pCurChildNode->GetElementType() == XFA_Element::Variables) - continue; - - auto pProcessor = - pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pCurChildNode, nullptr); - pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, nullptr); - if (!pProcessor->HasLayoutItem()) - continue; - - pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos( - pCurChildNode, pProcessor->GetCurrentComponentSize())); - CXFA_LayoutItem* pProcessItem = pProcessor->ExtractLayoutItem(); - if (!pBeforeItem) - pPageAreaLayoutItem->AddHeadChild(pProcessItem); - else - pPageAreaLayoutItem->InsertChild(pBeforeItem, pProcessItem); - - pBeforeItem = pProcessItem; - } - - pBeforeItem = nullptr; - CXFA_LayoutItem* pLayoutItem = pPageAreaLayoutItem->m_pFirstChild; - while (pLayoutItem) { - if (!pLayoutItem->IsContentLayoutItem() || - pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) { - pLayoutItem = pLayoutItem->m_pNextSibling; - continue; - } - if (pLayoutItem->m_pFormNode->GetElementType() != XFA_Element::Draw) - continue; - - CXFA_LayoutItem* pNextLayoutItem = pLayoutItem->m_pNextSibling; - pPageAreaLayoutItem->RemoveChild(pLayoutItem); - if (!pBeforeItem) - pPageAreaLayoutItem->AddHeadChild(pLayoutItem); - else - pPageAreaLayoutItem->InsertChild(pBeforeItem, pLayoutItem); - - pBeforeItem = pLayoutItem; - pLayoutItem = pNextLayoutItem; - } -} - -void CXFA_ItemLayoutProcessor::DoLayoutPositionedContainer( - CXFA_LayoutContext* pContext) { - if (m_pLayoutItem) - return; - - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - bool bIgnoreXY = (m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout) != - XFA_ATTRIBUTEENUM_Position); - bool bContainerWidthAutoSize = true; - bool bContainerHeightAutoSize = true; - CFX_SizeF containerSize = CalculateContainerSpecifiedSize( - m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); - - FX_FLOAT fContentCalculatedWidth = 0; - FX_FLOAT fContentCalculatedHeight = 0; - FX_FLOAT fHiddenContentCalculatedWidth = 0; - FX_FLOAT fHiddenContentCalculatedHeight = 0; - if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - false); - } - - int32_t iColIndex = 0; - for (; m_pCurChildNode; GotoNextContainerNode( - m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) - continue; - if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) - continue; - - auto pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - m_pCurChildNode, m_pPageMgr); - if (pContext && pContext->m_prgSpecifiedColumnWidths) { - int32_t iColSpan = m_pCurChildNode->GetInteger(XFA_ATTRIBUTE_ColSpan); - if (iColSpan <= - pContext->m_prgSpecifiedColumnWidths->GetSize() - iColIndex) { - pContext->m_fCurColumnWidth = 0; - pContext->m_bCurColumnWidthAvaiable = true; - if (iColSpan == -1) - iColSpan = pContext->m_prgSpecifiedColumnWidths->GetSize(); - - for (int32_t i = 0; iColIndex + i < iColSpan; ++i) { - pContext->m_fCurColumnWidth += - pContext->m_prgSpecifiedColumnWidths->GetAt(iColIndex + i); - } - if (pContext->m_fCurColumnWidth == 0) - pContext->m_bCurColumnWidthAvaiable = false; - - iColIndex += iColSpan >= 0 ? iColSpan : 0; - } - } - - pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pContext); - if (!pProcessor->HasLayoutItem()) - continue; - - CFX_SizeF size = pProcessor->GetCurrentComponentSize(); - bool bChangeParentSize = false; - if (XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) - bChangeParentSize = true; - - CFX_PointF absolutePos; - if (!bIgnoreXY) - absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size); - - pProcessor->SetCurrentComponentPos(absolutePos); - if (bContainerWidthAutoSize) { - FX_FLOAT fChildSuppliedWidth = absolutePos.x + size.width; - if (bChangeParentSize) { - fContentCalculatedWidth = - std::max(fContentCalculatedWidth, fChildSuppliedWidth); - } else { - if (fHiddenContentCalculatedWidth < fChildSuppliedWidth && - m_pCurChildNode->GetElementType() != XFA_Element::Subform) { - fHiddenContentCalculatedWidth = fChildSuppliedWidth; - } - } - } - - if (bContainerHeightAutoSize) { - FX_FLOAT fChildSuppliedHeight = absolutePos.y + size.height; - if (bChangeParentSize) { - fContentCalculatedHeight = - std::max(fContentCalculatedHeight, fChildSuppliedHeight); - } else { - if (fHiddenContentCalculatedHeight < fChildSuppliedHeight && - m_pCurChildNode->GetElementType() != XFA_Element::Subform) { - fHiddenContentCalculatedHeight = fChildSuppliedHeight; - } - } - } - m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); - } - - XFA_VERSION eVersion = m_pFormNode->GetDocument()->GetCurVersionMode(); - if (fContentCalculatedWidth == 0 && eVersion < XFA_VERSION_207) - fContentCalculatedWidth = fHiddenContentCalculatedWidth; - if (fContentCalculatedHeight == 0 && eVersion < XFA_VERSION_207) - fContentCalculatedHeight = fHiddenContentCalculatedHeight; - - containerSize = CalculateContainerComponentSizeFromContentSize( - m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); - SetCurrentComponentSize(containerSize); -} - -void CXFA_ItemLayoutProcessor::DoLayoutTableContainer(CXFA_Node* pLayoutNode) { - if (m_pLayoutItem) - return; - if (!pLayoutNode) - pLayoutNode = m_pFormNode; - - ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); - - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - bool bContainerWidthAutoSize = true; - bool bContainerHeightAutoSize = true; - CFX_SizeF containerSize = CalculateContainerSpecifiedSize( - m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); - FX_FLOAT fContentCalculatedWidth = 0; - FX_FLOAT fContentCalculatedHeight = 0; - CXFA_Node* pMarginNode = - m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - FX_FLOAT fLeftInset = 0; - FX_FLOAT fRightInset = 0; - if (pMarginNode) { - fLeftInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); - fRightInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); - } - - FX_FLOAT fContentWidthLimit = - bContainerWidthAutoSize ? FLT_MAX - : containerSize.width - fLeftInset - fRightInset; - CFX_WideStringC wsColumnWidths; - if (pLayoutNode->TryCData(XFA_ATTRIBUTE_ColumnWidths, wsColumnWidths)) { - auto widths = SeparateStringW(wsColumnWidths.c_str(), - wsColumnWidths.GetLength(), L' '); - for (auto& width : widths) { - width.TrimLeft(L' '); - if (width.IsEmpty()) - continue; - - CXFA_Measurement measure(width.AsStringC()); - m_rgSpecifiedColumnWidths.Add(measure.ToUnit(XFA_UNIT_Pt)); - } - } - - int32_t iSpecifiedColumnCount = m_rgSpecifiedColumnWidths.GetSize(); - CXFA_LayoutContext layoutContext; - layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths; - CXFA_LayoutContext* pLayoutContext = - iSpecifiedColumnCount > 0 ? &layoutContext : nullptr; - if (m_pCurChildNode == XFA_LAYOUT_INVALIDNODE) { - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - false); - } - - for (; m_pCurChildNode; GotoNextContainerNode( - m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, false)) { - layoutContext.m_bCurColumnWidthAvaiable = false; - layoutContext.m_fCurColumnWidth = 0; - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Container) - continue; - - auto pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - m_pCurChildNode, m_pPageMgr); - pProcessor->DoLayout(false, FLT_MAX, FLT_MAX, pLayoutContext); - if (!pProcessor->HasLayoutItem()) - continue; - - m_pLayoutItem->AddChild(pProcessor->ExtractLayoutItem()); - } - - int32_t iRowCount = 0; - int32_t iColCount = 0; - { - CFX_ArrayTemplate<CXFA_ContentLayoutItem*> rgRowItems; - CFX_ArrayTemplate<int32_t> rgRowItemsSpan; - CFX_ArrayTemplate<FX_FLOAT> rgRowItemsWidth; - for (CXFA_ContentLayoutItem* pLayoutChild = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - pLayoutChild; - pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { - if (pLayoutChild->m_pFormNode->GetElementType() != XFA_Element::Subform) - continue; - if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) - continue; - - XFA_ATTRIBUTEENUM eLayout = - pLayoutChild->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - if (eLayout != XFA_ATTRIBUTEENUM_Row && - eLayout != XFA_ATTRIBUTEENUM_Rl_row) { - continue; - } - if (CXFA_ContentLayoutItem* pRowLayoutCell = - (CXFA_ContentLayoutItem*)pLayoutChild->m_pFirstChild) { - rgRowItems.Add(pRowLayoutCell); - int32_t iColSpan = - pRowLayoutCell->m_pFormNode->GetInteger(XFA_ATTRIBUTE_ColSpan); - rgRowItemsSpan.Add(iColSpan); - rgRowItemsWidth.Add(pRowLayoutCell->m_sSize.width); - } - } - - iRowCount = rgRowItems.GetSize(); - iColCount = 0; - bool bMoreColumns = true; - while (bMoreColumns) { - bMoreColumns = false; - bool bAutoCol = false; - for (int32_t i = 0; i < iRowCount; i++) { - while (rgRowItems[i] && (rgRowItemsSpan[i] <= 0 || - !XFA_ItemLayoutProcessor_IsTakingSpace( - rgRowItems[i]->m_pFormNode))) { - CXFA_ContentLayoutItem* pNewCell = - (CXFA_ContentLayoutItem*)rgRowItems[i]->m_pNextSibling; - if (rgRowItemsSpan[i] < 0 && XFA_ItemLayoutProcessor_IsTakingSpace( - rgRowItems[i]->m_pFormNode)) { - pNewCell = nullptr; - } - rgRowItems[i] = pNewCell; - rgRowItemsSpan[i] = - pNewCell - ? pNewCell->m_pFormNode->GetInteger(XFA_ATTRIBUTE_ColSpan) - : 0; - rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0; - } - CXFA_ContentLayoutItem* pCell = rgRowItems[i]; - if (!pCell) - continue; - - bMoreColumns = true; - if (rgRowItemsSpan[i] != 1) - continue; - - if (iColCount >= iSpecifiedColumnCount) { - int32_t c = iColCount + 1 - m_rgSpecifiedColumnWidths.GetSize(); - for (int32_t j = 0; j < c; j++) - m_rgSpecifiedColumnWidths.Add(0); - } - if (m_rgSpecifiedColumnWidths[iColCount] < XFA_LAYOUT_FLOAT_PERCISION) - bAutoCol = true; - if (bAutoCol && - m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) { - m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i]; - } - } - - if (!bMoreColumns) - continue; - - FX_FLOAT fFinalColumnWidth = 0.0f; - if (iColCount < m_rgSpecifiedColumnWidths.GetSize()) - fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount]; - for (int32_t i = 0; i < iRowCount; ++i) { - if (!rgRowItems[i]) - continue; - --rgRowItemsSpan[i]; - rgRowItemsWidth[i] -= fFinalColumnWidth; - } - ++iColCount; - } - } - - FX_FLOAT fCurrentRowY = 0; - for (CXFA_ContentLayoutItem* pLayoutChild = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - pLayoutChild; - pLayoutChild = (CXFA_ContentLayoutItem*)pLayoutChild->m_pNextSibling) { - if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutChild->m_pFormNode)) - continue; - - if (pLayoutChild->m_pFormNode->GetElementType() == XFA_Element::Subform) { - XFA_ATTRIBUTEENUM eSubformLayout = - pLayoutChild->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - if (eSubformLayout == XFA_ATTRIBUTEENUM_Row || - eSubformLayout == XFA_ATTRIBUTEENUM_Rl_row) { - RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths, - eSubformLayout); - } - } - - pLayoutChild->m_sPos.y = fCurrentRowY; - if (bContainerWidthAutoSize) { - pLayoutChild->m_sPos.x = 0; - } else { - switch (pLayoutChild->m_pFormNode->GetEnum(XFA_ATTRIBUTE_HAlign)) { - case XFA_ATTRIBUTEENUM_Center: - pLayoutChild->m_sPos.x = - (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2; - break; - case XFA_ATTRIBUTEENUM_Right: - pLayoutChild->m_sPos.x = - fContentWidthLimit - pLayoutChild->m_sSize.width; - break; - case XFA_ATTRIBUTEENUM_Left: - default: - pLayoutChild->m_sPos.x = 0; - break; - } - } - - if (bContainerWidthAutoSize) { - FX_FLOAT fChildSuppliedWidth = - pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width; - if (fContentWidthLimit < FLT_MAX && - fContentWidthLimit > fChildSuppliedWidth) { - fChildSuppliedWidth = fContentWidthLimit; - } - fContentCalculatedWidth = - std::max(fContentCalculatedWidth, fChildSuppliedWidth); - } - fCurrentRowY += pLayoutChild->m_sSize.height; - } - - if (bContainerHeightAutoSize) - fContentCalculatedHeight = std::max(fContentCalculatedHeight, fCurrentRowY); - - containerSize = CalculateContainerComponentSizeFromContentSize( - m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); - SetCurrentComponentSize(containerSize); -} - -bool CXFA_ItemLayoutProcessor::IsAddNewRowForTrailer( - CXFA_ContentLayoutItem* pTrailerItem) { - if (!pTrailerItem) - return false; - - FX_FLOAT fWidth = pTrailerItem->m_sSize.width; - XFA_ATTRIBUTEENUM eLayout = m_pFormNode->GetEnum(XFA_ATTRIBUTE_Layout); - return eLayout == XFA_ATTRIBUTEENUM_Tb || m_fWidthLimite <= fWidth; -} - -FX_FLOAT CXFA_ItemLayoutProcessor::InsertKeepLayoutItems() { - if (m_arrayKeepItems.empty()) - return 0; - - if (!m_pLayoutItem) { - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - m_pLayoutItem->m_sSize.clear(); - } - - FX_FLOAT fTotalHeight = 0; - for (auto iter = m_arrayKeepItems.rbegin(); iter != m_arrayKeepItems.rend(); - iter++) { - AddLeaderAfterSplit(this, *iter); - fTotalHeight += (*iter)->m_sSize.height; - } - m_arrayKeepItems.clear(); - - return fTotalHeight; -} - -bool CXFA_ItemLayoutProcessor::ProcessKeepForSplit( - CXFA_ItemLayoutProcessor* pParentProcessor, - CXFA_ItemLayoutProcessor* pChildProcessor, - XFA_ItemLayoutProcessorResult eRetValue, - CFX_ArrayTemplate<CXFA_ContentLayoutItem*>* rgCurLineLayoutItem, - FX_FLOAT* fContentCurRowAvailWidth, - FX_FLOAT* fContentCurRowHeight, - FX_FLOAT* fContentCurRowY, - bool* bAddedItemInRow, - bool* bForceEndPage, - XFA_ItemLayoutProcessorResult* result) { - if (!pParentProcessor || !pChildProcessor) - return false; - - if (pParentProcessor->m_pCurChildNode->GetIntact() == - XFA_ATTRIBUTEENUM_None && - pChildProcessor->m_bHasAvailHeight) - return false; - - if (!ExistContainerKeep(pParentProcessor->m_pCurChildNode, true)) - return false; - - CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize(); - std::vector<CXFA_ContentLayoutItem*> keepLayoutItems; - if (pParentProcessor->JudgePutNextPage(pParentProcessor->m_pLayoutItem, - childSize.height, &keepLayoutItems)) { - m_arrayKeepItems.clear(); - - for (auto item : keepLayoutItems) { - pParentProcessor->m_pLayoutItem->RemoveChild(item); - *fContentCurRowY -= item->m_sSize.height; - m_arrayKeepItems.push_back(item); - } - *bAddedItemInRow = true; - *bForceEndPage = true; - *result = XFA_ItemLayoutProcessorResult::PageFullBreak; - return true; - } - - rgCurLineLayoutItem->Add(pChildProcessor->ExtractLayoutItem()); - *bAddedItemInRow = true; - *fContentCurRowAvailWidth -= childSize.width; - *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height); - *result = eRetValue; - - return true; -} - -bool CXFA_ItemLayoutProcessor::JudgePutNextPage( - CXFA_ContentLayoutItem* pParentLayoutItem, - FX_FLOAT fChildHeight, - std::vector<CXFA_ContentLayoutItem*>* pKeepItems) { - if (!pParentLayoutItem) - return false; - - FX_FLOAT fItemsHeight = 0; - for (CXFA_ContentLayoutItem* pChildLayoutItem = - (CXFA_ContentLayoutItem*)pParentLayoutItem->m_pFirstChild; - pChildLayoutItem; - pChildLayoutItem = - (CXFA_ContentLayoutItem*)pChildLayoutItem->m_pNextSibling) { - if (ExistContainerKeep(pChildLayoutItem->m_pFormNode, false)) { - pKeepItems->push_back(pChildLayoutItem); - fItemsHeight += pChildLayoutItem->m_sSize.height; - } else { - pKeepItems->clear(); - fItemsHeight = 0; - } - } - fItemsHeight += fChildHeight; - return m_pPageMgr->GetNextAvailContentHeight(fItemsHeight); -} - -void CXFA_ItemLayoutProcessor::ProcessUnUseBinds(CXFA_Node* pFormNode) { - if (!pFormNode) - return; - - CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator( - pFormNode); - for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode; - pNode = sIterator.MoveToNext()) { - if (pNode->IsContainerNode()) { - CXFA_Node* pBindNode = pNode->GetBindData(); - if (pBindNode) { - pBindNode->RemoveBindItem(pNode); - pNode->SetObject(XFA_ATTRIBUTE_BindingNode, nullptr); - } - } - pNode->SetFlag(XFA_NodeFlag_UnusedNode, true); - } -} - -void CXFA_ItemLayoutProcessor::ProcessUnUseOverFlow( - CXFA_Node* pLeaderNode, - CXFA_Node* pTrailerNode, - CXFA_ContentLayoutItem* pTrailerItem, - CXFA_Node* pFormNode) { - ProcessUnUseBinds(pLeaderNode); - ProcessUnUseBinds(pTrailerNode); - if (!pFormNode) - return; - - if (pFormNode->GetElementType() == XFA_Element::Overflow || - pFormNode->GetElementType() == XFA_Element::Break) { - pFormNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent); - } - if (pLeaderNode && pFormNode) - pFormNode->RemoveChild(pLeaderNode); - if (pTrailerNode && pFormNode) - pFormNode->RemoveChild(pTrailerNode); - if (pTrailerItem) - XFA_ReleaseLayoutItem(pTrailerItem); -} - -XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayoutFlowedContainer( - bool bUseBreakControl, - XFA_ATTRIBUTEENUM eFlowStrategy, - FX_FLOAT fHeightLimit, - FX_FLOAT fRealHeight, - CXFA_LayoutContext* pContext, - bool bRootForceTb) { - m_bHasAvailHeight = true; - bool bBreakDone = false; - bool bContainerWidthAutoSize = true; - bool bContainerHeightAutoSize = true; - bool bForceEndPage = false; - bool bIsManualBreak = false; - if (m_pCurChildPreprocessor) { - m_pCurChildPreprocessor->m_ePreProcessRs = - XFA_ItemLayoutProcessorResult::Done; - } - - CFX_SizeF containerSize = CalculateContainerSpecifiedSize( - m_pFormNode, &bContainerWidthAutoSize, &bContainerHeightAutoSize); - if (pContext && pContext->m_bCurColumnWidthAvaiable) { - bContainerWidthAutoSize = false; - containerSize.width = pContext->m_fCurColumnWidth; - } - if (!bContainerHeightAutoSize) - containerSize.height -= m_fUsedSize; - - if (!bContainerHeightAutoSize) { - CXFA_Node* pParentNode = m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent); - bool bFocrTb = false; - if (pParentNode && - GetLayout(pParentNode, &bFocrTb) == XFA_ATTRIBUTEENUM_Row) { - CXFA_Node* pChildContainer = m_pFormNode->GetNodeItem( - XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode); - if (pChildContainer && - pChildContainer->GetNodeItem(XFA_NODEITEM_NextSibling, - XFA_ObjectType::ContainerNode)) { - containerSize.height = 0; - bContainerHeightAutoSize = true; - } - } - } - - CXFA_Node* pMarginNode = - m_pFormNode->GetFirstChildByClass(XFA_Element::Margin); - FX_FLOAT fLeftInset = 0; - FX_FLOAT fTopInset = 0; - FX_FLOAT fRightInset = 0; - FX_FLOAT fBottomInset = 0; - if (pMarginNode) { - fLeftInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_LeftInset).ToUnit(XFA_UNIT_Pt); - fTopInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_TopInset).ToUnit(XFA_UNIT_Pt); - fRightInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_RightInset).ToUnit(XFA_UNIT_Pt); - fBottomInset = - pMarginNode->GetMeasure(XFA_ATTRIBUTE_BottomInset).ToUnit(XFA_UNIT_Pt); - } - FX_FLOAT fContentWidthLimit = - bContainerWidthAutoSize ? FLT_MAX - : containerSize.width - fLeftInset - fRightInset; - FX_FLOAT fContentCalculatedWidth = 0; - FX_FLOAT fContentCalculatedHeight = 0; - FX_FLOAT fAvailHeight = fHeightLimit - fTopInset - fBottomInset; - if (fAvailHeight < 0) - m_bHasAvailHeight = false; - - fRealHeight = fRealHeight - fTopInset - fBottomInset; - FX_FLOAT fContentCurRowY = 0; - CXFA_ContentLayoutItem* pLayoutChild = nullptr; - if (m_pLayoutItem) { - if (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done && - eFlowStrategy != XFA_ATTRIBUTEENUM_Tb) { - pLayoutChild = (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; - pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { - if (pLayoutNext->m_sPos.y != pLayoutChild->m_sPos.y) - pLayoutChild = pLayoutNext; - } - } - - for (CXFA_ContentLayoutItem* pLayoutTempChild = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - pLayoutTempChild != pLayoutChild; - pLayoutTempChild = - (CXFA_ContentLayoutItem*)pLayoutTempChild->m_pNextSibling) { - if (!XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutTempChild->m_pFormNode)) - continue; - - fContentCalculatedWidth = std::max( - fContentCalculatedWidth, - pLayoutTempChild->m_sPos.x + pLayoutTempChild->m_sSize.width); - fContentCalculatedHeight = std::max( - fContentCalculatedHeight, - pLayoutTempChild->m_sPos.y + pLayoutTempChild->m_sSize.height); - } - - if (pLayoutChild) - fContentCurRowY = pLayoutChild->m_sPos.y; - else - fContentCurRowY = fContentCalculatedHeight; - } - - fContentCurRowY += InsertKeepLayoutItems(); - if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::None) { - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - true); - } - - fContentCurRowY += InsertPendingItems(this, m_pFormNode); - if (m_pCurChildPreprocessor && - m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Container) { - if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(), false)) { - m_pKeepHeadNode = m_pCurChildNode; - m_bIsProcessKeep = true; - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Keep; - } - } - - while (m_nCurChildNodeStage != XFA_ItemLayoutProcessorStages::Done) { - FX_FLOAT fContentCurRowHeight = 0; - FX_FLOAT fContentCurRowAvailWidth = fContentWidthLimit; - m_fWidthLimite = fContentCurRowAvailWidth; - CFX_ArrayTemplate<CXFA_ContentLayoutItem*> rgCurLineLayoutItems[3]; - uint8_t uCurHAlignState = - (eFlowStrategy != XFA_ATTRIBUTEENUM_Rl_tb ? 0 : 2); - if (pLayoutChild) { - for (CXFA_ContentLayoutItem* pLayoutNext = pLayoutChild; pLayoutNext; - pLayoutNext = (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { - if (!pLayoutNext->m_pNextSibling && m_pCurChildPreprocessor && - m_pCurChildPreprocessor->m_pFormNode == pLayoutNext->m_pFormNode) { - pLayoutNext->m_pNext = m_pCurChildPreprocessor->m_pLayoutItem; - m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext; - break; - } - uint8_t uHAlign = HAlignEnumToInt( - pLayoutNext->m_pFormNode->GetEnum(XFA_ATTRIBUTE_HAlign)); - rgCurLineLayoutItems[uHAlign].Add(pLayoutNext); - if (eFlowStrategy == XFA_ATTRIBUTEENUM_Lr_tb) { - if (uHAlign > uCurHAlignState) - uCurHAlignState = uHAlign; - } else if (uHAlign < uCurHAlignState) { - uCurHAlignState = uHAlign; - } - if (XFA_ItemLayoutProcessor_IsTakingSpace(pLayoutNext->m_pFormNode)) { - if (pLayoutNext->m_sSize.height > fContentCurRowHeight) - fContentCurRowHeight = pLayoutNext->m_sSize.height; - fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width; - } - } - - if ((CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild == - pLayoutChild) { - m_pLayoutItem->m_pFirstChild = nullptr; - } else { - CXFA_ContentLayoutItem* pLayoutNext = - (CXFA_ContentLayoutItem*)m_pLayoutItem->m_pFirstChild; - for (; pLayoutNext; - pLayoutNext = - (CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling) { - if ((CXFA_ContentLayoutItem*)pLayoutNext->m_pNextSibling == - pLayoutChild) { - pLayoutNext->m_pNextSibling = nullptr; - break; - } - } - } - - CXFA_ContentLayoutItem* pLayoutNextTemp = - (CXFA_ContentLayoutItem*)pLayoutChild; - while (pLayoutNextTemp) { - pLayoutNextTemp->m_pParent = nullptr; - CXFA_ContentLayoutItem* pSaveLayoutNext = - (CXFA_ContentLayoutItem*)pLayoutNextTemp->m_pNextSibling; - pLayoutNextTemp->m_pNextSibling = nullptr; - pLayoutNextTemp = pSaveLayoutNext; - } - pLayoutChild = nullptr; - } - - while (m_pCurChildNode) { - std::unique_ptr<CXFA_ItemLayoutProcessor> pProcessor; - bool bAddedItemInRow = false; - fContentCurRowY += InsertPendingItems(this, m_pFormNode); - switch (m_nCurChildNodeStage) { - case XFA_ItemLayoutProcessorStages::Keep: - case XFA_ItemLayoutProcessorStages::None: - break; - case XFA_ItemLayoutProcessorStages::BreakBefore: { - for (auto item : m_arrayKeepItems) { - m_pLayoutItem->RemoveChild(item); - fContentCalculatedHeight -= item->m_sSize.height; - } - - CXFA_Node* pLeaderNode = nullptr; - CXFA_Node* pTrailerNode = nullptr; - bool bCreatePage = false; - if (!bUseBreakControl || !m_pPageMgr || - !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, true, - pLeaderNode, pTrailerNode, - bCreatePage) || - m_pFormNode->GetElementType() == XFA_Element::Form || - !bCreatePage) { - break; - } - - if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) - AddPendingNode(this, pLeaderNode, true); - - if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { - if (m_pFormNode->GetNodeItem(XFA_NODEITEM_Parent) - ->GetElementType() == XFA_Element::Form && - !m_pLayoutItem) { - AddPendingNode(this, pTrailerNode, true); - } else { - auto pTempProcessor = - pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pTrailerNode, - nullptr); - InsertFlowedItem( - this, pTempProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, - FLT_MAX, fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, false); - } - } - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, - m_pFormNode, true); - bForceEndPage = true; - bIsManualBreak = true; - goto SuspendAndCreateNewRow; - } - case XFA_ItemLayoutProcessorStages::BreakAfter: { - CXFA_Node* pLeaderNode = nullptr; - CXFA_Node* pTrailerNode = nullptr; - bool bCreatePage = false; - if (!bUseBreakControl || !m_pPageMgr || - !m_pPageMgr->ProcessBreakBeforeOrAfter(m_pCurChildNode, false, - pLeaderNode, pTrailerNode, - bCreatePage) || - m_pFormNode->GetElementType() == XFA_Element::Form) { - break; - } - - if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) { - auto pTempProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - pTrailerNode, nullptr); - InsertFlowedItem( - this, pTempProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, FLT_MAX, - fContentWidthLimit, &fContentCurRowY, &fContentCurRowAvailWidth, - &fContentCurRowHeight, &bAddedItemInRow, &bForceEndPage, - pContext, false); - } - if (!bCreatePage) { - if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) { - CalculateRowChildPosition( - rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, - bContainerWidthAutoSize, &fContentCalculatedWidth, - &fContentCalculatedHeight, &fContentCurRowY, - fContentCurRowHeight, fContentWidthLimit, false); - rgCurLineLayoutItems->RemoveAll(); - auto pTempProcessor = - pdfium::MakeUnique<CXFA_ItemLayoutProcessor>(pLeaderNode, - nullptr); - InsertFlowedItem( - this, pTempProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, false, FLT_MAX, - FLT_MAX, fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, false); - } - } else { - if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) - AddPendingNode(this, pLeaderNode, true); - } - - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, - m_pFormNode, true); - if (bCreatePage) { - bForceEndPage = true; - bIsManualBreak = true; - if (m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done) - bBreakDone = true; - } - goto SuspendAndCreateNewRow; - } - case XFA_ItemLayoutProcessorStages::BookendLeader: { - CXFA_Node* pLeaderNode = nullptr; - if (m_pCurChildPreprocessor) { - pProcessor.reset(m_pCurChildPreprocessor); - m_pCurChildPreprocessor = nullptr; - } else if (m_pPageMgr && - m_pPageMgr->ProcessBookendLeaderOrTrailer( - m_pCurChildNode, true, pLeaderNode)) { - pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - pLeaderNode, m_pPageMgr); - } - - if (pProcessor) { - if (InsertFlowedItem( - this, pProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, - eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, - bUseBreakControl, fAvailHeight, fRealHeight, - fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, - false) != XFA_ItemLayoutProcessorResult::Done) { - goto SuspendAndCreateNewRow; - } else { - pProcessor.reset(); - } - } - break; - } - case XFA_ItemLayoutProcessorStages::BookendTrailer: { - CXFA_Node* pTrailerNode = nullptr; - if (m_pCurChildPreprocessor) { - pProcessor.reset(m_pCurChildPreprocessor); - m_pCurChildPreprocessor = nullptr; - } else if (m_pPageMgr && - m_pPageMgr->ProcessBookendLeaderOrTrailer( - m_pCurChildNode, false, pTrailerNode)) { - pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - pTrailerNode, m_pPageMgr); - } - if (pProcessor) { - if (InsertFlowedItem( - this, pProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, - eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems, - bUseBreakControl, fAvailHeight, fRealHeight, - fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, - false) != XFA_ItemLayoutProcessorResult::Done) { - goto SuspendAndCreateNewRow; - } else { - pProcessor.reset(); - } - } - break; - } - case XFA_ItemLayoutProcessorStages::Container: { - ASSERT(m_pCurChildNode->IsContainerNode()); - if (m_pCurChildNode->GetElementType() == XFA_Element::Variables) - break; - if (fContentCurRowY >= fHeightLimit + XFA_LAYOUT_FLOAT_PERCISION && - XFA_ItemLayoutProcessor_IsTakingSpace(m_pCurChildNode)) { - bForceEndPage = true; - goto SuspendAndCreateNewRow; - } - if (!m_pCurChildNode->IsContainerNode()) - break; - - bool bNewRow = false; - if (m_pCurChildPreprocessor) { - pProcessor.reset(m_pCurChildPreprocessor); - m_pCurChildPreprocessor = nullptr; - bNewRow = true; - } else { - pProcessor = pdfium::MakeUnique<CXFA_ItemLayoutProcessor>( - m_pCurChildNode, m_pPageMgr); - } - - InsertPendingItems(pProcessor.get(), m_pCurChildNode); - XFA_ItemLayoutProcessorResult rs = InsertFlowedItem( - this, pProcessor.get(), bContainerWidthAutoSize, - bContainerHeightAutoSize, containerSize.height, eFlowStrategy, - &uCurHAlignState, rgCurLineLayoutItems, bUseBreakControl, - fAvailHeight, fRealHeight, fContentWidthLimit, &fContentCurRowY, - &fContentCurRowAvailWidth, &fContentCurRowHeight, - &bAddedItemInRow, &bForceEndPage, pContext, bNewRow); - switch (rs) { - case XFA_ItemLayoutProcessorResult::ManualBreak: - bIsManualBreak = true; - case XFA_ItemLayoutProcessorResult::PageFullBreak: - bForceEndPage = true; - case XFA_ItemLayoutProcessorResult::RowFullBreak: - goto SuspendAndCreateNewRow; - case XFA_ItemLayoutProcessorResult::Done: - default: - fContentCurRowY += - InsertPendingItems(pProcessor.get(), m_pCurChildNode); - pProcessor.reset(); - } - break; - } - case XFA_ItemLayoutProcessorStages::Done: - break; - default: - break; - } - GotoNextContainerNode(m_pCurChildNode, m_nCurChildNodeStage, m_pFormNode, - true); - if (bAddedItemInRow && eFlowStrategy == XFA_ATTRIBUTEENUM_Tb) - break; - else - continue; - SuspendAndCreateNewRow: - if (pProcessor) - m_pCurChildPreprocessor = pProcessor.release(); - break; - } - - CalculateRowChildPosition( - rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize, - bContainerWidthAutoSize, &fContentCalculatedWidth, - &fContentCalculatedHeight, &fContentCurRowY, fContentCurRowHeight, - fContentWidthLimit, bRootForceTb); - m_fWidthLimite = fContentCurRowAvailWidth; - if (bForceEndPage) - break; - } - - bool bRetValue = - m_nCurChildNodeStage == XFA_ItemLayoutProcessorStages::Done && - m_PendingNodes.empty(); - if (bBreakDone) - bRetValue = false; - - containerSize = CalculateContainerComponentSizeFromContentSize( - m_pFormNode, bContainerWidthAutoSize, fContentCalculatedWidth, - bContainerHeightAutoSize, fContentCalculatedHeight, containerSize); - - if (containerSize.height >= XFA_LAYOUT_FLOAT_PERCISION || m_pLayoutItem || - bRetValue) { - if (!m_pLayoutItem) - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - containerSize.height = std::max(containerSize.height, 0.f); - - SetCurrentComponentSize(containerSize); - if (bForceEndPage) - m_fUsedSize = 0; - else - m_fUsedSize += m_pLayoutItem->m_sSize.height; - } - - return bRetValue - ? XFA_ItemLayoutProcessorResult::Done - : (bIsManualBreak ? XFA_ItemLayoutProcessorResult::ManualBreak - : XFA_ItemLayoutProcessorResult::PageFullBreak); -} - -bool CXFA_ItemLayoutProcessor::CalculateRowChildPosition( - CFX_ArrayTemplate<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], - XFA_ATTRIBUTEENUM eFlowStrategy, - bool bContainerHeightAutoSize, - bool bContainerWidthAutoSize, - FX_FLOAT* fContentCalculatedWidth, - FX_FLOAT* fContentCalculatedHeight, - FX_FLOAT* fContentCurRowY, - FX_FLOAT fContentCurRowHeight, - FX_FLOAT fContentWidthLimit, - bool bRootForceTb) { - int32_t nGroupLengths[3] = {0, 0, 0}; - FX_FLOAT fGroupWidths[3] = {0, 0, 0}; - int32_t nTotalLength = 0; - for (int32_t i = 0; i < 3; i++) { - nGroupLengths[i] = rgCurLineLayoutItems[i].GetSize(); - for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) { - nTotalLength++; - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[i][j]->m_pFormNode)) { - fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width; - } - } - } - - if (!nTotalLength) { - if (bContainerHeightAutoSize) { - *fContentCalculatedHeight = - std::min(*fContentCalculatedHeight, *fContentCurRowY); - } - return false; - } - - if (!m_pLayoutItem) - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - - if (eFlowStrategy != XFA_ATTRIBUTEENUM_Rl_tb) { - FX_FLOAT fCurPos; - fCurPos = 0; - for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { - if (bRootForceTb) { - rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos( - rgCurLineLayoutItems[0][j]->m_pFormNode, - rgCurLineLayoutItems[0][j]->m_sSize); - } else { - rgCurLineLayoutItems[0][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[0][j]->m_pFormNode)) { - fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width; - } - } - m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); - m_fLastRowWidth = fCurPos; - } - fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] - - fGroupWidths[2]) / - 2; - for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { - if (bRootForceTb) { - rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos( - rgCurLineLayoutItems[1][j]->m_pFormNode, - rgCurLineLayoutItems[1][j]->m_sSize); - } else { - rgCurLineLayoutItems[1][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[1][j]->m_pFormNode)) { - fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width; - } - } - m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); - m_fLastRowWidth = fCurPos; - } - fCurPos = fContentWidthLimit - fGroupWidths[2]; - for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { - if (bRootForceTb) { - rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos( - rgCurLineLayoutItems[2][j]->m_pFormNode, - rgCurLineLayoutItems[2][j]->m_sSize); - } else { - rgCurLineLayoutItems[2][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[2][j]->m_pFormNode)) { - fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width; - } - } - m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); - m_fLastRowWidth = fCurPos; - } - } else { - FX_FLOAT fCurPos; - fCurPos = fGroupWidths[0]; - for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) { - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[0][j]->m_pFormNode)) { - fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width; - } - rgCurLineLayoutItems[0][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - m_pLayoutItem->AddChild(rgCurLineLayoutItems[0][j]); - m_fLastRowWidth = fCurPos; - } - fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] - - fGroupWidths[2]) / - 2; - for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) { - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[1][j]->m_pFormNode)) { - fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width; - } - rgCurLineLayoutItems[1][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - m_pLayoutItem->AddChild(rgCurLineLayoutItems[1][j]); - m_fLastRowWidth = fCurPos; - } - fCurPos = fContentWidthLimit; - for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) { - if (XFA_ItemLayoutProcessor_IsTakingSpace( - rgCurLineLayoutItems[2][j]->m_pFormNode)) { - fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width; - } - rgCurLineLayoutItems[2][j]->m_sPos = - CFX_PointF(fCurPos, *fContentCurRowY); - m_pLayoutItem->AddChild(rgCurLineLayoutItems[2][j]); - m_fLastRowWidth = fCurPos; - } - } - m_fLastRowY = *fContentCurRowY; - *fContentCurRowY += fContentCurRowHeight; - if (bContainerWidthAutoSize) { - FX_FLOAT fChildSuppliedWidth = fGroupWidths[0]; - if (fContentWidthLimit < FLT_MAX && - fContentWidthLimit > fChildSuppliedWidth) { - fChildSuppliedWidth = fContentWidthLimit; - } - *fContentCalculatedWidth = - std::max(*fContentCalculatedWidth, fChildSuppliedWidth); - } - if (bContainerHeightAutoSize) { - *fContentCalculatedHeight = - std::max(*fContentCalculatedHeight, *fContentCurRowY); - } - return true; -} - -CXFA_Node* CXFA_ItemLayoutProcessor::GetSubformSetParent( - CXFA_Node* pSubformSet) { - if (pSubformSet && pSubformSet->GetElementType() == XFA_Element::SubformSet) { - CXFA_Node* pParent = pSubformSet->GetNodeItem(XFA_NODEITEM_Parent); - while (pParent) { - if (pParent->GetElementType() != XFA_Element::SubformSet) - return pParent; - pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent); - } - } - return pSubformSet; -} - -void CXFA_ItemLayoutProcessor::DoLayoutField() { - if (m_pLayoutItem) - return; - - ASSERT(m_pCurChildNode == XFA_LAYOUT_INVALIDNODE); - m_pLayoutItem = CreateContentLayoutItem(m_pFormNode); - if (!m_pLayoutItem) - return; - - CXFA_Document* pDocument = m_pFormNode->GetDocument(); - CXFA_FFNotify* pNotify = pDocument->GetNotify(); - CFX_SizeF size(-1, -1); - pNotify->StartFieldDrawLayout(m_pFormNode, size.width, size.height); - - int32_t nRotate = - FXSYS_round(m_pFormNode->GetMeasure(XFA_ATTRIBUTE_Rotate).GetValue()); - nRotate = XFA_MapRotation(nRotate); - if (nRotate == 90 || nRotate == 270) - std::swap(size.width, size.height); - - SetCurrentComponentSize(size); -} - -XFA_ItemLayoutProcessorResult CXFA_ItemLayoutProcessor::DoLayout( - bool bUseBreakControl, - FX_FLOAT fHeightLimit, - FX_FLOAT fRealHeight, - CXFA_LayoutContext* pContext) { - switch (m_pFormNode->GetElementType()) { - case XFA_Element::Subform: - case XFA_Element::Area: - case XFA_Element::ExclGroup: - case XFA_Element::SubformSet: { - bool bRootForceTb = false; - CXFA_Node* pLayoutNode = GetSubformSetParent(m_pFormNode); - XFA_ATTRIBUTEENUM eLayoutStrategy = GetLayout(pLayoutNode, &bRootForceTb); - switch (eLayoutStrategy) { - case XFA_ATTRIBUTEENUM_Tb: - case XFA_ATTRIBUTEENUM_Lr_tb: - case XFA_ATTRIBUTEENUM_Rl_tb: - return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy, - fHeightLimit, fRealHeight, pContext, - bRootForceTb); - case XFA_ATTRIBUTEENUM_Position: - case XFA_ATTRIBUTEENUM_Row: - case XFA_ATTRIBUTEENUM_Rl_row: - default: - DoLayoutPositionedContainer(pContext); - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; - return XFA_ItemLayoutProcessorResult::Done; - case XFA_ATTRIBUTEENUM_Table: - DoLayoutTableContainer(pLayoutNode); - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; - return XFA_ItemLayoutProcessorResult::Done; - } - } - case XFA_Element::Draw: - case XFA_Element::Field: - DoLayoutField(); - m_nCurChildNodeStage = XFA_ItemLayoutProcessorStages::Done; - return XFA_ItemLayoutProcessorResult::Done; - case XFA_Element::ContentArea: - return XFA_ItemLayoutProcessorResult::Done; - default: - return XFA_ItemLayoutProcessorResult::Done; - } -} - -CFX_SizeF CXFA_ItemLayoutProcessor::GetCurrentComponentSize() { - return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height); -} - -void CXFA_ItemLayoutProcessor::SetCurrentComponentPos(const CFX_PointF& pos) { - m_pLayoutItem->m_sPos = pos; -} - -void CXFA_ItemLayoutProcessor::SetCurrentComponentSize(const CFX_SizeF& size) { - m_pLayoutItem->m_sSize = size; -} - -bool CXFA_ItemLayoutProcessor::JudgeLeaderOrTrailerForOccur( - CXFA_Node* pFormNode) { - if (!pFormNode) - return false; - - CXFA_Node* pTemplate = pFormNode->GetTemplateNode(); - if (!pTemplate) - pTemplate = pFormNode; - - CXFA_Occur NodeOccur(pTemplate->GetFirstChildByClass(XFA_Element::Occur)); - int32_t iMax = NodeOccur.GetMax(); - if (iMax < 0) - return true; - - int32_t iCount = m_PendingNodesCount[pTemplate]; - if (iCount >= iMax) - return false; - - m_PendingNodesCount[pTemplate] = iCount + 1; - return true; -} diff --git a/xfa/fxfa/parser/xfa_layout_itemlayout.h b/xfa/fxfa/parser/xfa_layout_itemlayout.h deleted file mode 100644 index d411bf0e9facbe27785633b49330626bf4fda4bd..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_layout_itemlayout.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_XFA_LAYOUT_ITEMLAYOUT_H_ -#define XFA_FXFA_PARSER_XFA_LAYOUT_ITEMLAYOUT_H_ - -#include <float.h> - -#include <list> -#include <map> -#include <tuple> -#include <vector> - -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_coordinates.h" -#include "xfa/fxfa/fxfa_basic.h" - -#define XFA_LAYOUT_INVALIDNODE ((CXFA_Node*)(intptr_t)-1) -#define XFA_LAYOUT_FLOAT_PERCISION (0.0005f) - -class CXFA_ContainerLayoutItem; -class CXFA_ContentLayoutItem; -class CXFA_ItemLayoutProcessor; -class CXFA_LayoutPageMgr; -class CXFA_LayoutProcessor; -class CXFA_Node; - -enum class XFA_ItemLayoutProcessorResult { - Done, - PageFullBreak, - RowFullBreak, - ManualBreak, -}; - -enum class XFA_ItemLayoutProcessorStages { - None, - BookendLeader, - BreakBefore, - Keep, - Container, - BreakAfter, - BookendTrailer, - Done, -}; - -class CXFA_LayoutContext { - public: - CXFA_LayoutContext() - : m_prgSpecifiedColumnWidths(nullptr), - m_fCurColumnWidth(0), - m_bCurColumnWidthAvaiable(false), - m_pOverflowProcessor(nullptr), - m_pOverflowNode(nullptr) {} - ~CXFA_LayoutContext() {} - - CFX_ArrayTemplate<FX_FLOAT>* m_prgSpecifiedColumnWidths; - FX_FLOAT m_fCurColumnWidth; - bool m_bCurColumnWidthAvaiable; - CXFA_ItemLayoutProcessor* m_pOverflowProcessor; - CXFA_Node* m_pOverflowNode; -}; - -bool XFA_ItemLayoutProcessor_IsTakingSpace(CXFA_Node* pNode); - -class CXFA_ItemLayoutProcessor { - public: - static bool IncrementRelayoutNode(CXFA_LayoutProcessor* pLayoutProcessor, - CXFA_Node* pNode, - CXFA_Node* pParentNode); - - CXFA_ItemLayoutProcessor(CXFA_Node* pNode, CXFA_LayoutPageMgr* pPageMgr); - ~CXFA_ItemLayoutProcessor(); - - XFA_ItemLayoutProcessorResult DoLayout(bool bUseBreakControl, - FX_FLOAT fHeightLimit, - FX_FLOAT fRealHeight, - CXFA_LayoutContext* pContext); - void DoLayoutPageArea(CXFA_ContainerLayoutItem* pPageAreaLayoutItem); - - CFX_SizeF GetCurrentComponentSize(); - CXFA_Node* GetFormNode() { return m_pFormNode; } - bool HasLayoutItem() const { return !!m_pLayoutItem; } - CXFA_ContentLayoutItem* ExtractLayoutItem(); - void SplitLayoutItem(FX_FLOAT fSplitPos); - - FX_FLOAT FindSplitPos(FX_FLOAT fProposedSplitPos); - - bool ProcessKeepForSplit( - CXFA_ItemLayoutProcessor* pParentProcessor, - CXFA_ItemLayoutProcessor* pChildProcessor, - XFA_ItemLayoutProcessorResult eRetValue, - CFX_ArrayTemplate<CXFA_ContentLayoutItem*>* rgCurLineLayoutItem, - FX_FLOAT* fContentCurRowAvailWidth, - FX_FLOAT* fContentCurRowHeight, - FX_FLOAT* fContentCurRowY, - bool* bAddedItemInRow, - bool* bForceEndPage, - XFA_ItemLayoutProcessorResult* result); - void ProcessUnUseOverFlow(CXFA_Node* pLeaderNode, - CXFA_Node* pTrailerNode, - CXFA_ContentLayoutItem* pTrailerItem, - CXFA_Node* pFormNode); - bool IsAddNewRowForTrailer(CXFA_ContentLayoutItem* pTrailerItem); - bool JudgeLeaderOrTrailerForOccur(CXFA_Node* pFormNode); - - CXFA_ContentLayoutItem* CreateContentLayoutItem(CXFA_Node* pFormNode); - - CXFA_Node* m_pFormNode; - CXFA_ContentLayoutItem* m_pLayoutItem; - CXFA_Node* m_pCurChildNode; - FX_FLOAT m_fUsedSize; - CXFA_LayoutPageMgr* m_pPageMgr; - std::list<CXFA_Node*> m_PendingNodes; - bool m_bBreakPending; - CFX_ArrayTemplate<FX_FLOAT> m_rgSpecifiedColumnWidths; - std::vector<CXFA_ContentLayoutItem*> m_arrayKeepItems; - FX_FLOAT m_fLastRowWidth; - FX_FLOAT m_fLastRowY; - bool m_bUseInheriated; - XFA_ItemLayoutProcessorResult m_ePreProcessRs; - - private: - void SetCurrentComponentPos(const CFX_PointF& pos); - void SetCurrentComponentSize(const CFX_SizeF& size); - - void SplitLayoutItem(CXFA_ContentLayoutItem* pLayoutItem, - CXFA_ContentLayoutItem* pSecondParent, - FX_FLOAT fSplitPos); - FX_FLOAT InsertKeepLayoutItems(); - bool CalculateRowChildPosition( - CFX_ArrayTemplate<CXFA_ContentLayoutItem*> (&rgCurLineLayoutItems)[3], - XFA_ATTRIBUTEENUM eFlowStrategy, - bool bContainerHeightAutoSize, - bool bContainerWidthAutoSize, - FX_FLOAT* fContentCalculatedWidth, - FX_FLOAT* fContentCalculatedHeight, - FX_FLOAT* fContentCurRowY, - FX_FLOAT fContentCurRowHeight, - FX_FLOAT fContentWidthLimit, - bool bRootForceTb); - void ProcessUnUseBinds(CXFA_Node* pFormNode); - bool JudgePutNextPage(CXFA_ContentLayoutItem* pParentLayoutItem, - FX_FLOAT fChildHeight, - std::vector<CXFA_ContentLayoutItem*>* pKeepItems); - - void DoLayoutPositionedContainer(CXFA_LayoutContext* pContext); - void DoLayoutTableContainer(CXFA_Node* pLayoutNode); - XFA_ItemLayoutProcessorResult DoLayoutFlowedContainer( - bool bUseBreakControl, - XFA_ATTRIBUTEENUM eFlowStrategy, - FX_FLOAT fHeightLimit, - FX_FLOAT fRealHeight, - CXFA_LayoutContext* pContext, - bool bRootForceTb); - void DoLayoutField(); - - void GotoNextContainerNode(CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node* pParentContainer, - bool bUsePageBreak); - - bool ProcessKeepNodesForCheckNext(CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node*& pNextContainer, - bool& bLastKeepNode); - - bool ProcessKeepNodesForBreakBefore(CXFA_Node*& pCurActionNode, - XFA_ItemLayoutProcessorStages& nCurStage, - CXFA_Node* pContainerNode); - - CXFA_Node* GetSubformSetParent(CXFA_Node* pSubformSet); - - bool m_bKeepBreakFinish; - bool m_bIsProcessKeep; - CXFA_Node* m_pKeepHeadNode; - CXFA_Node* m_pKeepTailNode; - CXFA_ContentLayoutItem* m_pOldLayoutItem; - CXFA_ItemLayoutProcessor* m_pCurChildPreprocessor; - XFA_ItemLayoutProcessorStages m_nCurChildNodeStage; - std::map<CXFA_Node*, int32_t> m_PendingNodesCount; - FX_FLOAT m_fWidthLimite; - bool m_bHasAvailHeight; -}; - -#endif // XFA_FXFA_PARSER_XFA_LAYOUT_ITEMLAYOUT_H_ diff --git a/xfa/fxfa/parser/xfa_locale.cpp b/xfa/fxfa/parser/xfa_locale.cpp deleted file mode 100644 index d835eb2bc7c26ddc35d23dede190537b6b9bd6f6..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_locale.cpp +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_locale.h" - -#include <utility> - -#include "core/fxcrt/fx_xml.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -static const FX_WCHAR g_FX_Percent[] = L"z,zzz,zzz,zzz,zzz,zzz%"; -static const FX_WCHAR g_FX_Currency[] = L"$z,zzz,zzz,zzz,zzz,zz9.99"; -static const FX_WCHAR g_FX_Decimal[] = L"z,zzz,zzz,zzz,zzz,zz9.zzz"; -static const FX_WCHAR g_FX_Integer[] = L"z,zzz,zzz,zzz,zzz,zzz"; - -CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData) - : m_pLocaleData(std::move(pLocaleData)) {} - -CXFA_XMLLocale::~CXFA_XMLLocale() {} - -CFX_WideString CXFA_XMLLocale::GetName() const { - return m_pLocaleData ? m_pLocaleData->GetAttrValue("name") : CFX_WideString(); -} - -void CXFA_XMLLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, - CFX_WideString& wsNumSymbol) const { - CFX_ByteString bsSymbols; - CFX_WideString wsName; - switch (eType) { - case FX_LOCALENUMSYMBOL_Decimal: - bsSymbols = "numberSymbols"; - wsName = L"decimal"; - break; - case FX_LOCALENUMSYMBOL_Grouping: - bsSymbols = "numberSymbols"; - wsName = L"grouping"; - break; - case FX_LOCALENUMSYMBOL_Percent: - bsSymbols = "numberSymbols"; - wsName = L"percent"; - break; - case FX_LOCALENUMSYMBOL_Minus: - bsSymbols = "numberSymbols"; - wsName = L"minus"; - break; - case FX_LOCALENUMSYMBOL_Zero: - bsSymbols = "numberSymbols"; - wsName = L"zero"; - break; - case FX_LOCALENUMSYMBOL_CurrencySymbol: - bsSymbols = "currencySymbols"; - wsName = L"symbol"; - break; - case FX_LOCALENUMSYMBOL_CurrencyName: - bsSymbols = "currencySymbols"; - wsName = L"isoname"; - break; - default: - return; - } - CXML_Element* pElement = m_pLocaleData->GetElement("", bsSymbols.AsStringC()); - if (!pElement) { - return; - } - GetPattern(pElement, - CFX_ByteStringC(bsSymbols.c_str(), bsSymbols.GetLength() - 1), - wsName.AsStringC(), wsNumSymbol); -} - -void CXFA_XMLLocale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const { - if (!m_pLocaleData) { - return; - } - CFX_ByteString bsSpace; - CXML_Element* pNumberSymbols = - m_pLocaleData->GetElement(bsSpace.AsStringC(), "dateTimeSymbols"); - if (!pNumberSymbols) { - return; - } - wsDtSymbol = pNumberSymbols->GetContent(0); -} - -void CXFA_XMLLocale::GetMonthName(int32_t nMonth, - CFX_WideString& wsMonthName, - bool bAbbr) const { - wsMonthName = GetCalendarSymbol("month", nMonth, bAbbr); -} - -void CXFA_XMLLocale::GetDayName(int32_t nWeek, - CFX_WideString& wsDayName, - bool bAbbr) const { - wsDayName = GetCalendarSymbol("day", nWeek, bAbbr); -} - -void CXFA_XMLLocale::GetMeridiemName(CFX_WideString& wsMeridiemName, - bool bAM) const { - wsMeridiemName = GetCalendarSymbol("meridiem", bAM ? 0 : 1, false); -} - -void CXFA_XMLLocale::GetTimeZone(FX_TIMEZONE* tz) const { - CXFA_TimeZoneProvider provider; - provider.GetTimeZone(tz); -} - -void CXFA_XMLLocale::GetEraName(CFX_WideString& wsEraName, bool bAD) const { - wsEraName = GetCalendarSymbol("era", bAD ? 1 : 0, false); -} - -CFX_WideString CXFA_XMLLocale::GetCalendarSymbol(const CFX_ByteStringC& symbol, - int index, - bool bAbbr) const { - CFX_ByteString pstrSymbolNames = symbol + "Names"; - CFX_WideString wsSymbolName = L""; - if (m_pLocaleData) { - CXML_Element* pChild = m_pLocaleData->GetElement("", "calendarSymbols"); - if (pChild) { - CXML_Element* pSymbolNames = - pChild->GetElement("", pstrSymbolNames.AsStringC()); - if (pSymbolNames) { - if ((!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr) { - pSymbolNames = pChild->GetElement("", pstrSymbolNames.AsStringC(), 1); - } - if (pSymbolNames && (!!pSymbolNames->GetAttrInteger("abbr")) == bAbbr) { - CXML_Element* pSymbolName = - pSymbolNames->GetElement("", symbol, index); - if (pSymbolName) { - wsSymbolName = pSymbolName->GetContent(0); - } - } - } - } - } - return wsSymbolName; -} - -void CXFA_XMLLocale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const { - CXML_Element* pElement = m_pLocaleData->GetElement("", "datePatterns"); - if (!pElement) { - return; - } - CFX_WideString wsName; - switch (eType) { - case FX_LOCALEDATETIMESUBCATEGORY_Short: - wsName = L"short"; - break; - case FX_LOCALEDATETIMESUBCATEGORY_Default: - case FX_LOCALEDATETIMESUBCATEGORY_Medium: - wsName = L"med"; - break; - case FX_LOCALEDATETIMESUBCATEGORY_Full: - wsName = L"full"; - break; - case FX_LOCALEDATETIMESUBCATEGORY_Long: - wsName = L"long"; - break; - } - GetPattern(pElement, "datePattern", wsName.AsStringC(), wsPattern); -} - -void CXFA_XMLLocale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const { - CXML_Element* pElement = m_pLocaleData->GetElement("", "timePatterns"); - if (!pElement) { - return; - } - CFX_WideString wsName; - switch (eType) { - case FX_LOCALEDATETIMESUBCATEGORY_Short: - wsName = L"short"; - break; - case FX_LOCALEDATETIMESUBCATEGORY_Default: - case FX_LOCALEDATETIMESUBCATEGORY_Medium: - wsName = L"med"; - break; - case FX_LOCALEDATETIMESUBCATEGORY_Full: - wsName = L"full"; - break; - case FX_LOCALEDATETIMESUBCATEGORY_Long: - wsName = L"long"; - break; - } - GetPattern(pElement, "timePattern", wsName.AsStringC(), wsPattern); -} - -void CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, - CFX_WideString& wsPattern) const { - CXML_Element* pElement = m_pLocaleData->GetElement("", "numberPatterns"); - if (!pElement) { - return; - } - switch (eType) { - case FX_LOCALENUMPATTERN_Percent: - wsPattern = g_FX_Percent; - break; - case FX_LOCALENUMPATTERN_Currency: - wsPattern = g_FX_Currency; - break; - case FX_LOCALENUMPATTERN_Decimal: - wsPattern = g_FX_Decimal; - break; - case FX_LOCALENUMPATTERN_Integer: - wsPattern = g_FX_Integer; - break; - } -} - -void CXFA_XMLLocale::GetPattern(CXML_Element* pElement, - const CFX_ByteStringC& bsTag, - const CFX_WideStringC& wsName, - CFX_WideString& wsPattern) const { - int32_t iCount = pElement->CountElements("", bsTag); - for (int32_t i = 0; i < iCount; i++) { - CXML_Element* pChild = pElement->GetElement("", bsTag, i); - if (pChild->GetAttrValue("name") == wsName) { - wsPattern = pChild->GetContent(0); - return; - } - } -} - -CXFA_NodeLocale::CXFA_NodeLocale(CXFA_Node* pLocale) : m_pLocale(pLocale) {} - -CXFA_NodeLocale::~CXFA_NodeLocale() {} - -CFX_WideString CXFA_NodeLocale::GetName() const { - return CFX_WideString(m_pLocale ? m_pLocale->GetCData(XFA_ATTRIBUTE_Name) - : nullptr); -} - -void CXFA_NodeLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, - CFX_WideString& wsNumSymbol) const { - switch (eType) { - case FX_LOCALENUMSYMBOL_Decimal: - wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"decimal"); - break; - case FX_LOCALENUMSYMBOL_Grouping: - wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"grouping"); - break; - case FX_LOCALENUMSYMBOL_Percent: - wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"percent"); - break; - case FX_LOCALENUMSYMBOL_Minus: - wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"minus"); - break; - case FX_LOCALENUMSYMBOL_Zero: - wsNumSymbol = GetSymbol(XFA_Element::NumberSymbols, L"zero"); - break; - case FX_LOCALENUMSYMBOL_CurrencySymbol: - wsNumSymbol = GetSymbol(XFA_Element::CurrencySymbols, L"symbol"); - break; - case FX_LOCALENUMSYMBOL_CurrencyName: - wsNumSymbol = GetSymbol(XFA_Element::CurrencySymbols, L"isoname"); - break; - } -} - -void CXFA_NodeLocale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const { - CXFA_Node* pSymbols = - m_pLocale ? m_pLocale->GetChild(0, XFA_Element::DateTimeSymbols) - : nullptr; - wsDtSymbol = pSymbols ? pSymbols->GetContent() : CFX_WideString(); -} - -void CXFA_NodeLocale::GetMonthName(int32_t nMonth, - CFX_WideString& wsMonthName, - bool bAbbr) const { - wsMonthName = GetCalendarSymbol(XFA_Element::MonthNames, nMonth, bAbbr); -} - -void CXFA_NodeLocale::GetDayName(int32_t nWeek, - CFX_WideString& wsDayName, - bool bAbbr) const { - wsDayName = GetCalendarSymbol(XFA_Element::DayNames, nWeek, bAbbr); -} - -void CXFA_NodeLocale::GetMeridiemName(CFX_WideString& wsMeridiemName, - bool bAM) const { - wsMeridiemName = - GetCalendarSymbol(XFA_Element::MeridiemNames, bAM ? 0 : 1, false); -} - -void CXFA_NodeLocale::GetTimeZone(FX_TIMEZONE* tz) const { - CXFA_TimeZoneProvider provider; - provider.GetTimeZone(tz); -} - -void CXFA_NodeLocale::GetEraName(CFX_WideString& wsEraName, bool bAD) const { - wsEraName = GetCalendarSymbol(XFA_Element::EraNames, bAD ? 1 : 0, false); -} - -void CXFA_NodeLocale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const { - switch (eType) { - case FX_LOCALEDATETIMESUBCATEGORY_Short: - wsPattern = GetSymbol(XFA_Element::DatePatterns, L"short"); - break; - case FX_LOCALEDATETIMESUBCATEGORY_Medium: - case FX_LOCALEDATETIMESUBCATEGORY_Default: - wsPattern = GetSymbol(XFA_Element::DatePatterns, L"med"); - break; - case FX_LOCALEDATETIMESUBCATEGORY_Full: - wsPattern = GetSymbol(XFA_Element::DatePatterns, L"full"); - break; - case FX_LOCALEDATETIMESUBCATEGORY_Long: - wsPattern = GetSymbol(XFA_Element::DatePatterns, L"long"); - break; - } -} - -void CXFA_NodeLocale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const { - switch (eType) { - case FX_LOCALEDATETIMESUBCATEGORY_Short: - wsPattern = GetSymbol(XFA_Element::TimePatterns, L"short"); - break; - case FX_LOCALEDATETIMESUBCATEGORY_Medium: - case FX_LOCALEDATETIMESUBCATEGORY_Default: - wsPattern = GetSymbol(XFA_Element::TimePatterns, L"med"); - break; - case FX_LOCALEDATETIMESUBCATEGORY_Full: - wsPattern = GetSymbol(XFA_Element::TimePatterns, L"full"); - break; - case FX_LOCALEDATETIMESUBCATEGORY_Long: - wsPattern = GetSymbol(XFA_Element::TimePatterns, L"long"); - break; - } -} - -void CXFA_NodeLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, - CFX_WideString& wsPattern) const { - switch (eType) { - case FX_LOCALENUMPATTERN_Percent: - wsPattern = g_FX_Percent; - break; - case FX_LOCALENUMPATTERN_Currency: - wsPattern = g_FX_Currency; - break; - case FX_LOCALENUMPATTERN_Decimal: - wsPattern = g_FX_Decimal; - break; - case FX_LOCALENUMPATTERN_Integer: - wsPattern = g_FX_Integer; - break; - } -} - -CXFA_Node* CXFA_NodeLocale::GetNodeByName(CXFA_Node* pParent, - const CFX_WideStringC& wsName) const { - CXFA_Node* pChild = - pParent ? pParent->GetNodeItem(XFA_NODEITEM_FirstChild) : nullptr; - while (pChild) { - CFX_WideString wsChild; - if (pChild->GetAttribute(XFA_ATTRIBUTE_Name, wsChild)) { - if (wsChild == wsName) { - return pChild; - } - } - pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling); - } - return nullptr; -} - -CFX_WideString CXFA_NodeLocale::GetSymbol( - XFA_Element eElement, - const CFX_WideStringC& symbol_type) const { - CXFA_Node* pSymbols = m_pLocale ? m_pLocale->GetChild(0, eElement) : nullptr; - CXFA_Node* pSymbol = GetNodeByName(pSymbols, symbol_type); - return pSymbol ? pSymbol->GetContent() : CFX_WideString(); -} - -CFX_WideString CXFA_NodeLocale::GetCalendarSymbol(XFA_Element eElement, - int index, - bool bAbbr) const { - CXFA_Node* pCalendar = - m_pLocale ? m_pLocale->GetChild(0, XFA_Element::CalendarSymbols) - : nullptr; - if (pCalendar) { - CXFA_Node* pNode = pCalendar->GetFirstChildByClass(eElement); - for (; pNode; pNode = pNode->GetNextSameClassSibling(eElement)) { - if (pNode->GetBoolean(XFA_ATTRIBUTE_Abbr) == bAbbr) { - CXFA_Node* pSymbol = pNode->GetChild(index, XFA_Element::Unknown); - return pSymbol ? pSymbol->GetContent() : CFX_WideString(); - } - } - } - return CFX_WideString(); -} diff --git a/xfa/fxfa/parser/xfa_locale.h b/xfa/fxfa/parser/xfa_locale.h deleted file mode 100644 index 5326f513c1e508466f9d1672c651d8a8d6d70922..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_locale.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_XFA_LOCALE_H_ -#define XFA_FXFA_PARSER_XFA_LOCALE_H_ - -#include <memory> - -#include "xfa/fgas/localization/fgas_locale.h" -#include "xfa/fxfa/parser/xfa_object.h" - -class CXFA_XMLLocale : public IFX_Locale { - public: - explicit CXFA_XMLLocale(std::unique_ptr<CXML_Element> pLocaleData); - ~CXFA_XMLLocale() override; - - // IFX_Locale - CFX_WideString GetName() const override; - void GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, - CFX_WideString& wsNumSymbol) const override; - - void GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const override; - void GetMonthName(int32_t nMonth, - CFX_WideString& wsMonthName, - bool bAbbr = true) const override; - void GetDayName(int32_t nWeek, - CFX_WideString& wsDayName, - bool bAbbr = true) const override; - void GetMeridiemName(CFX_WideString& wsMeridiemName, - bool bAM = true) const override; - void GetTimeZone(FX_TIMEZONE* tz) const override; - void GetEraName(CFX_WideString& wsEraName, bool bAD = true) const override; - - void GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const override; - void GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const override; - void GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, - CFX_WideString& wsPattern) const override; - - protected: - void GetPattern(CXML_Element* pElement, - const CFX_ByteStringC& bsTag, - const CFX_WideStringC& wsName, - CFX_WideString& wsPattern) const; - CFX_WideString GetCalendarSymbol(const CFX_ByteStringC& symbol, - int index, - bool bAbbr) const; - - private: - std::unique_ptr<CXML_Element> m_pLocaleData; -}; - -class CXFA_NodeLocale : public IFX_Locale { - public: - explicit CXFA_NodeLocale(CXFA_Node* pLocale); - ~CXFA_NodeLocale() override; - - // IFX_Locale - CFX_WideString GetName() const override; - void GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, - CFX_WideString& wsNumSymbol) const override; - - void GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const override; - void GetMonthName(int32_t nMonth, - CFX_WideString& wsMonthName, - bool bAbbr = true) const override; - void GetDayName(int32_t nWeek, - CFX_WideString& wsDayName, - bool bAbbr = true) const override; - void GetMeridiemName(CFX_WideString& wsMeridiemName, - bool bAM = true) const override; - void GetTimeZone(FX_TIMEZONE* tz) const override; - void GetEraName(CFX_WideString& wsEraName, bool bAD = true) const override; - - void GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const override; - void GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, - CFX_WideString& wsPattern) const override; - void GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, - CFX_WideString& wsPattern) const override; - - protected: - CXFA_Node* GetNodeByName(CXFA_Node* pParent, - const CFX_WideStringC& wsName) const; - CFX_WideString GetSymbol(XFA_Element eElement, - const CFX_WideStringC& symbol_type) const; - CFX_WideString GetCalendarSymbol(XFA_Element eElement, - int index, - bool bAbbr) const; - - CXFA_Node* const m_pLocale; -}; - -#endif // XFA_FXFA_PARSER_XFA_LOCALE_H_ diff --git a/xfa/fxfa/parser/xfa_localemgr.cpp b/xfa/fxfa/parser/xfa_localemgr.cpp deleted file mode 100644 index 0cd64ea6dc6bbf1c059509db935f281cb66ddb1c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_localemgr.cpp +++ /dev/null @@ -1,1274 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_localemgr.h" - -#include <time.h> - -#include <memory> -#include <utility> - -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_xml.h" -#include "core/fxge/cfx_gemodule.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_locale.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -const uint8_t g_enUS_Locale[] = { - 0x78, 0x9C, 0x95, 0x56, 0xD1, 0x6E, 0x9B, 0x30, 0x14, 0x7D, 0x9F, 0xB4, - 0x7F, 0x40, 0xD6, 0x2A, 0xB5, 0x52, 0x56, 0x6F, 0x8F, 0xA9, 0x88, 0xA5, - 0x6C, 0x24, 0x9B, 0x3A, 0xD1, 0x55, 0x22, 0x55, 0xB5, 0xBE, 0x4C, 0x0E, - 0xDC, 0x05, 0x34, 0xB0, 0x23, 0x83, 0x37, 0x05, 0xED, 0xE3, 0x67, 0x07, - 0xC3, 0xC0, 0xF6, 0x24, 0xC2, 0x4B, 0x7C, 0xCF, 0x3D, 0xE7, 0xE6, 0xDE, - 0x63, 0x30, 0x84, 0x25, 0x4F, 0x69, 0x09, 0x01, 0xA3, 0x15, 0xAC, 0x10, - 0xB0, 0xEF, 0x4F, 0x09, 0x0A, 0x32, 0xA8, 0xD3, 0x15, 0xDA, 0xB0, 0x43, - 0x59, 0xD4, 0xF9, 0xF5, 0xBA, 0x02, 0x51, 0xA4, 0xF4, 0x06, 0x91, 0x50, - 0x53, 0x59, 0x46, 0x45, 0x72, 0xAA, 0xF6, 0xBC, 0xAC, 0x8D, 0xEA, 0x20, - 0xE0, 0xC0, 0x45, 0x41, 0x99, 0x62, 0x54, 0x9C, 0x35, 0xF9, 0x83, 0x82, - 0x6B, 0xB3, 0x26, 0xF7, 0x94, 0x49, 0x2A, 0x4E, 0x21, 0xEE, 0xC2, 0xD7, - 0xAF, 0x0C, 0xBE, 0x85, 0xBD, 0xF0, 0x26, 0x62, 0x2A, 0xD2, 0xDC, 0x41, - 0xD7, 0x47, 0x51, 0x94, 0x1E, 0xAE, 0xAB, 0xBF, 0x97, 0x0C, 0x3C, 0x60, - 0xE9, 0x32, 0xD7, 0xF2, 0x20, 0xEB, 0xC6, 0x81, 0x13, 0x38, 0x36, 0x50, - 0xED, 0x41, 0x38, 0x99, 0xAF, 0x69, 0xC3, 0x7D, 0xF8, 0x03, 0xFF, 0xE5, - 0x17, 0x44, 0x90, 0xDA, 0x09, 0x3C, 0xB2, 0xA8, 0xE7, 0x9D, 0xA3, 0x80, - 0xEE, 0xF7, 0x62, 0x85, 0xDE, 0xA3, 0x91, 0x73, 0x3E, 0xD7, 0x7C, 0x86, - 0xF9, 0xEC, 0x9A, 0x6B, 0x96, 0xCF, 0x2B, 0x9F, 0x55, 0x3E, 0x9F, 0x7C, - 0x0E, 0xF9, 0xDC, 0xF1, 0x19, 0xF3, 0x7F, 0x4F, 0x32, 0x7A, 0x32, 0xB7, - 0x90, 0x5A, 0x91, 0x44, 0xAA, 0x5B, 0x4E, 0x75, 0xAE, 0xD7, 0x5D, 0x92, - 0xC4, 0xDC, 0x81, 0x76, 0x12, 0x6A, 0x1B, 0x7B, 0x86, 0x8C, 0xB9, 0xE8, - 0x2E, 0x97, 0xC2, 0x01, 0xB7, 0xA2, 0xB0, 0xA1, 0x84, 0x36, 0x52, 0x8C, - 0x41, 0x3C, 0xF4, 0x35, 0xEA, 0x71, 0xB4, 0x6B, 0xA6, 0x59, 0xBB, 0x53, - 0xBB, 0x4D, 0xBB, 0x45, 0xBB, 0x39, 0xBB, 0x2F, 0xBB, 0x29, 0x7F, 0x3F, - 0xFA, 0x21, 0xCD, 0x0A, 0xA8, 0xFA, 0x67, 0xCF, 0x84, 0x64, 0x1D, 0x2B, - 0x77, 0xFB, 0x60, 0xC4, 0x23, 0x8F, 0x56, 0x02, 0x4F, 0x2B, 0x28, 0x04, - 0x04, 0x35, 0xD5, 0xD4, 0x8A, 0x7C, 0xF8, 0x18, 0x62, 0xFD, 0xDB, 0x25, - 0xC8, 0x3A, 0x1A, 0x42, 0x3C, 0x10, 0x75, 0x60, 0x9D, 0x11, 0x5D, 0xE3, - 0x0D, 0x3C, 0xD2, 0xA6, 0x01, 0xC1, 0xCE, 0x7B, 0x3A, 0x44, 0xE6, 0x00, - 0xF9, 0x21, 0xCB, 0x12, 0x91, 0x8D, 0xBA, 0x16, 0x41, 0xAC, 0xAE, 0x20, - 0x5A, 0x04, 0xDF, 0xD4, 0xA5, 0x27, 0x1C, 0xB8, 0x56, 0x21, 0x23, 0x2D, - 0x39, 0x3B, 0x20, 0x72, 0xA1, 0xA8, 0x82, 0xEC, 0xAC, 0xB9, 0x40, 0x52, - 0xE7, 0x5C, 0x34, 0x4A, 0x84, 0x23, 0xEC, 0xE1, 0xE3, 0xC9, 0x84, 0x0A, - 0x68, 0x8A, 0x6A, 0x34, 0xF1, 0x28, 0x9A, 0x4C, 0x9C, 0xDF, 0xC5, 0xF1, - 0x5D, 0x92, 0x04, 0xEB, 0xE0, 0x25, 0xC4, 0x23, 0x92, 0x55, 0x61, 0x32, - 0xEA, 0x65, 0x9A, 0xF3, 0xA4, 0x83, 0x64, 0x86, 0xC0, 0xCC, 0xA9, 0x25, - 0x1E, 0x3E, 0x9E, 0xCC, 0x65, 0x8C, 0xDA, 0x29, 0xAC, 0xDF, 0xEC, 0x4F, - 0xA7, 0x38, 0xFB, 0xF9, 0xB9, 0xAA, 0x93, 0x4D, 0xB4, 0xFD, 0xFD, 0x4C, - 0xF3, 0x2F, 0xED, 0x4B, 0x67, 0xCE, 0x98, 0xA4, 0x74, 0x4C, 0xEA, 0x53, - 0xF1, 0x9F, 0x43, 0x93, 0xD8, 0xB4, 0xA2, 0x30, 0xFD, 0xE2, 0x41, 0xA4, - 0x5D, 0xB4, 0xED, 0xF2, 0xB6, 0x6D, 0xDB, 0x10, 0x4F, 0x78, 0x4E, 0x21, - 0x23, 0x4C, 0xA5, 0x10, 0xC0, 0xD2, 0x13, 0x22, 0x6F, 0x3A, 0xE9, 0x72, - 0xF9, 0xE7, 0x7A, 0x58, 0xDE, 0xCC, 0xAC, 0x72, 0x04, 0x91, 0x02, 0x6B, - 0xCC, 0xDF, 0x5F, 0x79, 0x54, 0xD8, 0x9A, 0x62, 0x28, 0xD4, 0x0F, 0x3A, - 0x09, 0x4D, 0xD9, 0x0C, 0xD2, 0xA2, 0xA2, 0x6A, 0xF3, 0x6F, 0x7B, 0x7D, - 0x97, 0xB6, 0xD5, 0xC3, 0xBB, 0x95, 0xCB, 0x63, 0xA1, 0x37, 0x7E, 0x31, - 0x8B, 0x3F, 0x74, 0x7D, 0x35, 0x8B, 0x5E, 0x15, 0x4C, 0xD6, 0x88, 0xBC, - 0x9D, 0x45, 0x6E, 0x41, 0x70, 0x44, 0xDE, 0xB9, 0x5C, 0x3C, 0x1D, 0x5B, - 0x21, 0xFD, 0x16, 0x0C, 0x4E, 0x4C, 0x81, 0xFE, 0x66, 0x3B, 0x07, 0x6A, - 0x9B, 0xD4, 0xA9, 0x31, 0xC9, 0xBB, 0x25, 0x8C, 0xA2, 0xA8, 0xB9, 0x5E, - 0x20, 0xF2, 0x94, 0x44, 0xB3, 0x45, 0x63, 0xCB, 0x5D, 0x09, 0xB6, 0x7B, - 0xD5, 0x58, 0xF7, 0x55, 0xA4, 0x96, 0x7F, 0x01, 0x75, 0x37, 0x1B, 0x8B, -}; -const uint8_t g_enGB_Locale[] = { - 0x78, 0x9C, 0x95, 0x56, 0xD1, 0x6E, 0xD3, 0x30, 0x14, 0x7D, 0x47, 0xE2, - 0x1F, 0xA2, 0x88, 0x49, 0x20, 0x6D, 0x33, 0x3C, 0x6E, 0xEA, 0x2C, 0x75, - 0xEB, 0xD6, 0x32, 0xC8, 0xA8, 0x48, 0xC5, 0xC4, 0x5E, 0x90, 0x9B, 0x78, - 0x8D, 0x59, 0x62, 0x57, 0x4E, 0xCC, 0x94, 0xFC, 0x02, 0x9F, 0xC0, 0x23, - 0xCF, 0x08, 0xF1, 0x01, 0xBC, 0xF0, 0x2F, 0x48, 0xFB, 0x0C, 0x6E, 0x1A, - 0x27, 0x4B, 0x1C, 0xAF, 0x64, 0x79, 0x89, 0xEF, 0xB9, 0xE7, 0xDC, 0xDE, - 0x7B, 0x9C, 0xB8, 0x19, 0xC5, 0x22, 0x20, 0x31, 0x75, 0x38, 0x49, 0xE8, - 0x91, 0x4B, 0xF9, 0xA7, 0xE9, 0xB1, 0xEB, 0x84, 0x34, 0x0D, 0x8E, 0xDC, - 0xBB, 0xAF, 0xBF, 0xEE, 0x7E, 0xFE, 0x78, 0x0E, 0xB7, 0xBF, 0xDF, 0x7E, - 0xBF, 0x70, 0xF1, 0xA8, 0x24, 0xF2, 0x90, 0x48, 0x3F, 0x4F, 0x96, 0x22, - 0x4E, 0xB5, 0x66, 0x25, 0xE9, 0x4A, 0x48, 0x46, 0x38, 0x30, 0x12, 0xC1, - 0xB3, 0xE8, 0x02, 0xE0, 0x54, 0xAF, 0xF1, 0x39, 0xE1, 0x8A, 0xC8, 0x7C, - 0x84, 0xAA, 0xF0, 0xE9, 0x13, 0x8D, 0x9F, 0xD1, 0xA5, 0xB4, 0x26, 0x3C, - 0x22, 0x83, 0xA8, 0x87, 0x8E, 0xD7, 0x92, 0xC5, 0x16, 0x6E, 0x5F, 0x7F, - 0xAE, 0x38, 0xB5, 0x80, 0x71, 0x9F, 0x39, 0x56, 0x2B, 0x95, 0x66, 0x3D, - 0xD8, 0xA7, 0xEB, 0x8C, 0x26, 0x4B, 0x2A, 0x7B, 0x99, 0x77, 0x41, 0x26, - 0x6C, 0xF8, 0x85, 0xF8, 0x62, 0x17, 0x4C, 0x68, 0x60, 0x26, 0x50, 0xCB, - 0xA2, 0x9A, 0xB7, 0x89, 0x1C, 0xB2, 0x5C, 0xCA, 0x23, 0xF7, 0x95, 0xDB, - 0x72, 0xCE, 0xE6, 0x9A, 0xCD, 0x30, 0x9B, 0x5D, 0x43, 0xCD, 0xB2, 0x79, - 0x65, 0xB3, 0xCA, 0xE6, 0x93, 0xCD, 0x21, 0x9B, 0x3B, 0x36, 0x63, 0x1E, - 0xF6, 0x24, 0x24, 0xB9, 0x7E, 0x84, 0x60, 0x85, 0x7D, 0x05, 0x8F, 0x1C, - 0x74, 0x5E, 0xAE, 0xAB, 0x24, 0xF6, 0x44, 0x0F, 0x5A, 0x28, 0x9A, 0x9A, - 0xD8, 0x25, 0x0D, 0x79, 0x1F, 0x5D, 0x44, 0x4A, 0xF6, 0xC0, 0x33, 0xC9, - 0x4C, 0xC8, 0x27, 0x99, 0x92, 0x6D, 0x10, 0x35, 0x7D, 0xB5, 0x7A, 0x6C, - 0xED, 0x9A, 0x6E, 0xD6, 0xEC, 0xD4, 0x6C, 0xD3, 0x6C, 0xD1, 0x6C, 0xCE, - 0xEC, 0xCB, 0x6C, 0xCA, 0xDE, 0x4F, 0x42, 0x61, 0x02, 0x46, 0x93, 0xFA, - 0xDD, 0xD3, 0x21, 0x1E, 0x7B, 0xE0, 0x6E, 0x1D, 0xB4, 0x78, 0x78, 0x6E, - 0x24, 0x50, 0xB7, 0x02, 0x20, 0x54, 0x12, 0x5D, 0x0D, 0x56, 0xF8, 0xF8, - 0x64, 0x84, 0xCA, 0x7B, 0x95, 0xC0, 0xE3, 0x49, 0x13, 0xA2, 0x86, 0x58, - 0x06, 0xC6, 0x19, 0x51, 0x35, 0x9E, 0xD1, 0x39, 0xC9, 0x32, 0x2A, 0xF9, - 0x66, 0x4F, 0x9B, 0x48, 0x1F, 0x20, 0xD7, 0x2A, 0x8E, 0x5D, 0x7C, 0x0A, - 0xD7, 0xAE, 0x33, 0x71, 0x3C, 0xB8, 0x9C, 0x8F, 0x70, 0x95, 0x03, 0x36, - 0x54, 0xA3, 0x8E, 0x56, 0xC6, 0x82, 0xAF, 0x5C, 0xFC, 0x38, 0x4D, 0x42, - 0x43, 0x2D, 0x19, 0xAA, 0x48, 0x23, 0x21, 0x33, 0xD0, 0x4C, 0x90, 0xE7, - 0x21, 0xAB, 0x06, 0x75, 0x46, 0x04, 0x20, 0x63, 0x49, 0x6B, 0xE4, 0x56, - 0xD4, 0x19, 0x79, 0x36, 0x3B, 0xF4, 0xBC, 0x43, 0xDF, 0x77, 0xAE, 0x46, - 0xA8, 0xC5, 0x31, 0x0A, 0x74, 0x66, 0x7D, 0x94, 0x64, 0x33, 0x6A, 0xAD, - 0x18, 0xC0, 0xD7, 0x83, 0x6E, 0x14, 0x3D, 0x3A, 0xEA, 0xCC, 0xA4, 0x8D, - 0x5A, 0x00, 0x56, 0xEF, 0xF4, 0x34, 0xF7, 0xC2, 0x9B, 0x59, 0x92, 0xFA, - 0xA7, 0x93, 0xB3, 0xDB, 0x4B, 0x12, 0xBD, 0x29, 0xAE, 0x2A, 0x63, 0xDA, - 0x24, 0xD0, 0x71, 0x55, 0x1E, 0x89, 0xF7, 0xEE, 0x74, 0x62, 0xDD, 0x09, - 0x60, 0xF0, 0x38, 0x06, 0x2E, 0x2E, 0x76, 0x8B, 0xE2, 0x60, 0xBF, 0x28, - 0x8A, 0x11, 0xEA, 0xF0, 0x7A, 0x85, 0xB4, 0x30, 0x50, 0x52, 0x52, 0x1E, - 0xE4, 0x2E, 0x7E, 0x56, 0x49, 0x0F, 0x0E, 0x06, 0x2A, 0xD7, 0x54, 0x06, - 0x94, 0x67, 0xFA, 0x27, 0x77, 0x2C, 0x2A, 0x64, 0x74, 0xDE, 0x14, 0xAA, - 0x87, 0xEB, 0x84, 0xBA, 0x6C, 0x48, 0x03, 0x96, 0x10, 0xD8, 0xEC, 0xFD, - 0x5A, 0x5F, 0xA5, 0x4D, 0x75, 0xF3, 0x67, 0x2A, 0xD4, 0x9A, 0x95, 0x3B, - 0xBD, 0x3B, 0x88, 0xDF, 0x74, 0xBD, 0x33, 0x88, 0x9E, 0x30, 0xAE, 0x52, - 0x17, 0xEF, 0x0D, 0x22, 0x17, 0x54, 0x0A, 0x17, 0xBF, 0xEC, 0x73, 0x51, - 0x77, 0x6C, 0x40, 0x6A, 0xDB, 0x1B, 0x27, 0xBA, 0x40, 0xFD, 0x7C, 0x6D, - 0x02, 0x17, 0xFF, 0xF9, 0x0E, 0xE7, 0x44, 0x87, 0xD0, 0xAF, 0xA1, 0x25, - 0x2C, 0x15, 0xE5, 0xC2, 0xC5, 0xD3, 0xE3, 0xF9, 0x60, 0x51, 0xDB, 0xF3, - 0xBE, 0x04, 0x99, 0xCD, 0x96, 0xEF, 0x42, 0xBE, 0xA6, 0xD7, 0x24, 0x28, - 0x0F, 0xBB, 0x7A, 0xA9, 0x6B, 0x79, 0x39, 0x7C, 0xDA, 0x84, 0xCE, 0x1C, - 0xAC, 0x40, 0x6D, 0x66, 0x9D, 0x66, 0x9C, 0x09, 0xFE, 0x60, 0xFA, 0x44, - 0x28, 0xC9, 0xA8, 0x74, 0xFC, 0x2C, 0xB4, 0xE6, 0xC7, 0x21, 0x7C, 0x50, - 0x38, 0x73, 0xF6, 0x1F, 0xC2, 0x0C, 0x3E, 0x96, 0xE8, 0xED, 0x16, 0xC2, - 0x58, 0x92, 0x25, 0xBC, 0x2E, 0x0F, 0x13, 0x16, 0x11, 0x61, 0xD6, 0xF4, - 0x1B, 0x51, 0xA8, 0x1B, 0xE2, 0x4C, 0x45, 0x16, 0xB1, 0xA0, 0x9C, 0x63, - 0xEF, 0xC3, 0x6B, 0xC7, 0xDB, 0x46, 0x85, 0x91, 0x83, 0x48, 0xD4, 0xD4, - 0xF7, 0x5B, 0x7E, 0x14, 0x98, 0xAB, 0x72, 0x32, 0xE7, 0xED, 0x16, 0x92, - 0x2F, 0x06, 0x90, 0xBC, 0x5C, 0xF1, 0xD5, 0x67, 0xB1, 0xE1, 0xE9, 0xE6, - 0xD0, 0xFD, 0x9E, 0x95, 0x51, 0xF5, 0x19, 0x0B, 0xCB, 0x7F, 0x8E, 0x69, - 0xAC, 0xD0}; -const uint8_t g_zhCN_Locale[] = { - 0x78, 0x9C, 0xED, 0x56, 0x41, 0x4F, 0xD4, 0x40, 0x14, 0xBE, 0x9B, 0xF8, - 0x1F, 0x9A, 0x46, 0x52, 0x4D, 0x58, 0x46, 0x8F, 0x90, 0xD2, 0x64, 0x03, - 0x08, 0x06, 0xBB, 0x21, 0x96, 0x68, 0xE0, 0x62, 0xBA, 0xED, 0xB0, 0x2D, - 0x6C, 0x3B, 0x64, 0xB6, 0x0D, 0x6E, 0x4F, 0x18, 0x82, 0x82, 0xC2, 0x45, - 0x89, 0x9A, 0x80, 0xE1, 0x64, 0x3C, 0x28, 0x9E, 0x8C, 0x01, 0x22, 0xF1, - 0xCF, 0xB0, 0xCB, 0x91, 0xBF, 0xE0, 0x9B, 0xED, 0xB4, 0xB4, 0xDD, 0xD9, - 0xB5, 0x3F, 0xC0, 0x3D, 0xCD, 0xFB, 0xDE, 0xF7, 0x7D, 0xF3, 0xDE, 0xEB, - 0x74, 0xB6, 0x6A, 0x93, 0x58, 0x66, 0x13, 0x4B, 0xBE, 0xE9, 0xE1, 0x49, - 0x39, 0x72, 0x9E, 0x4F, 0xD5, 0x64, 0xC9, 0xC6, 0x2D, 0x6B, 0x52, 0xBE, - 0x3C, 0x3D, 0xE9, 0x7E, 0x78, 0x7D, 0xF7, 0xEA, 0xC7, 0xE6, 0xE5, 0xC5, - 0xFB, 0xEB, 0xDF, 0x7B, 0x10, 0x77, 0x0E, 0x2F, 0xEE, 0xC9, 0x9A, 0xCA, - 0x14, 0xBE, 0x6D, 0x52, 0xA3, 0xED, 0xD5, 0x49, 0xB3, 0xC5, 0xC5, 0x0D, - 0x8A, 0x1B, 0x84, 0xBA, 0xA6, 0x0F, 0x0C, 0x8F, 0xF8, 0x81, 0x53, 0x03, - 0xB8, 0xC5, 0xD7, 0xDA, 0xE5, 0xE9, 0x66, 0xF7, 0x68, 0x47, 0x45, 0x71, - 0x74, 0xFB, 0x56, 0x02, 0x9F, 0xEF, 0x09, 0xE1, 0xD3, 0x5D, 0x11, 0xDC, - 0x39, 0x3C, 0x14, 0x9B, 0x1C, 0x08, 0xD9, 0xDB, 0x27, 0x62, 0xEF, 0x2D, - 0x31, 0xFB, 0x9B, 0x90, 0x7D, 0xF6, 0x59, 0xC8, 0xDE, 0x7F, 0x39, 0x00, - 0x1E, 0xD0, 0x28, 0xCB, 0x14, 0x7B, 0x45, 0x99, 0x31, 0x25, 0xC4, 0x5E, - 0x24, 0x99, 0xF5, 0x3A, 0x9D, 0x94, 0x1F, 0xC8, 0xFF, 0xA7, 0x57, 0x7A, - 0x7A, 0xB6, 0xD9, 0xE6, 0x07, 0x0E, 0x56, 0x5A, 0xF7, 0xD3, 0x71, 0xF7, - 0xE8, 0xB8, 0xFB, 0xF1, 0x8B, 0x8A, 0x58, 0x18, 0xE7, 0x39, 0x0A, 0x7B, - 0x88, 0xD0, 0xF3, 0x3D, 0x21, 0x77, 0x57, 0x80, 0xC2, 0x24, 0x85, 0x0E, - 0x07, 0x22, 0xEE, 0xF6, 0x49, 0x8A, 0xA2, 0xB4, 0xC8, 0x4C, 0xC1, 0x99, - 0x87, 0xDD, 0x53, 0x15, 0x6A, 0x2E, 0x56, 0x5B, 0xAC, 0xB3, 0x58, 0x61, - 0xB1, 0xB6, 0x62, 0x55, 0x03, 0xEB, 0xF1, 0x30, 0x75, 0x6D, 0x17, 0x7B, - 0xC9, 0x6B, 0xCB, 0x43, 0xD8, 0xE0, 0x4D, 0x67, 0x9F, 0x0D, 0x3E, 0x01, - 0x32, 0x5C, 0x48, 0xBE, 0xED, 0x4B, 0xA2, 0xBC, 0x13, 0x20, 0x98, 0x9A, - 0xDC, 0x15, 0x56, 0x50, 0xC1, 0xF7, 0xCE, 0xF6, 0x56, 0x67, 0x77, 0x5F, - 0x45, 0x2C, 0x8C, 0xF3, 0x1C, 0x4D, 0x21, 0x94, 0x6A, 0x58, 0x50, 0xB8, - 0x71, 0xE2, 0x5E, 0x02, 0xBC, 0x60, 0x06, 0x01, 0xA6, 0x7E, 0xEF, 0x99, - 0xA7, 0x11, 0xBF, 0x8E, 0x56, 0xC2, 0x66, 0x53, 0xD6, 0x96, 0xE0, 0xA7, - 0x74, 0xCE, 0x7E, 0x2A, 0xBA, 0x02, 0xA7, 0x47, 0x99, 0x56, 0x60, 0xBC, - 0xCA, 0x0C, 0xFC, 0x58, 0xEF, 0xA9, 0xA4, 0xE0, 0xC7, 0x1D, 0x9A, 0xC4, - 0x6F, 0x0C, 0x70, 0x28, 0xA1, 0xF6, 0xB0, 0x1D, 0x8B, 0x2B, 0x7A, 0x65, - 0xBA, 0x04, 0xBF, 0xE5, 0x10, 0x1A, 0x30, 0x85, 0x90, 0x8F, 0x72, 0xED, - 0x02, 0x10, 0xB8, 0x5E, 0xA6, 0xFD, 0x4C, 0x94, 0x6B, 0xBF, 0xEA, 0x38, - 0x50, 0xEF, 0x2F, 0x45, 0xD7, 0x95, 0xCE, 0xCE, 0x2B, 0xC5, 0x30, 0x94, - 0xAB, 0xAF, 0xEF, 0x14, 0x69, 0x59, 0x45, 0x19, 0x45, 0xC1, 0x2E, 0xD7, - 0xBD, 0xD8, 0xA0, 0x84, 0xBC, 0xD7, 0x3E, 0xA8, 0x27, 0x74, 0x7D, 0xC2, - 0x30, 0x4A, 0x08, 0x78, 0xFF, 0x55, 0xA6, 0xE8, 0xA3, 0xA3, 0x5C, 0xBB, - 0x7C, 0x7E, 0x8B, 0x80, 0x25, 0x07, 0x62, 0xD6, 0xF4, 0x57, 0xD7, 0xE6, - 0xBC, 0x96, 0x31, 0x33, 0xFD, 0x70, 0xE3, 0xD9, 0x0B, 0x67, 0x3E, 0x5A, - 0x8E, 0x67, 0x96, 0x25, 0x81, 0xCE, 0x0F, 0xBD, 0x3A, 0xA6, 0x37, 0x83, - 0xCB, 0xC5, 0xBC, 0x12, 0xC0, 0xE0, 0x00, 0x5B, 0xB2, 0x16, 0x8D, 0x46, - 0xD1, 0xF8, 0x58, 0x14, 0x45, 0x2A, 0xCA, 0xF1, 0xFA, 0x8C, 0xB8, 0xD0, - 0x0A, 0x29, 0xC5, 0xBE, 0xD5, 0x96, 0xB5, 0x3B, 0xB1, 0x74, 0x7C, 0xBC, - 0xA4, 0x72, 0x1D, 0x53, 0x0B, 0xFB, 0x01, 0xDF, 0x72, 0x44, 0xA0, 0x42, - 0x85, 0xCA, 0x53, 0xA3, 0xA4, 0xB9, 0x5C, 0xC8, 0x6D, 0x6D, 0x6C, 0xB9, - 0x9E, 0x09, 0xE7, 0x60, 0x2C, 0xD1, 0xC7, 0xE9, 0xA2, 0x3A, 0xFD, 0x07, - 0x27, 0xE1, 0xBA, 0xCB, 0x1E, 0xFB, 0x68, 0x29, 0x7E, 0x5A, 0xF5, 0x48, - 0x29, 0xBA, 0xE7, 0xFA, 0x61, 0x4B, 0xD6, 0x2A, 0xA5, 0xC8, 0x11, 0xA6, - 0x44, 0xD6, 0xEE, 0xF7, 0x73, 0x51, 0xBE, 0x6D, 0x40, 0x92, 0xB1, 0xA7, - 0x93, 0xC8, 0x03, 0xC9, 0xF9, 0xEA, 0x05, 0xB2, 0x76, 0xFD, 0x07, 0xEE, - 0xD7, 0x3C, 0xA3, 0xDF, 0x84, 0x6B, 0xDC, 0x16, 0x61, 0x0B, 0x59, 0x9B, - 0xAA, 0x2D, 0x95, 0x16, 0x65, 0x87, 0xDE, 0x2F, 0x41, 0xC5, 0x6A, 0xD9, - 0xCB, 0xD0, 0x5E, 0xC7, 0x2B, 0xA6, 0xC5, 0xEE, 0xC7, 0x64, 0xC9, 0xBD, - 0xAA, 0x36, 0xA9, 0x63, 0xC9, 0x80, 0x57, 0x51, 0x32, 0x02, 0x5B, 0x7A, - 0x2C, 0xA3, 0x2C, 0x9F, 0x93, 0xF4, 0x36, 0x7C, 0x75, 0xD9, 0xD2, 0x02, - 0x0C, 0x4C, 0x98, 0x76, 0x7D, 0x97, 0xF8, 0x03, 0xD3, 0x53, 0x24, 0xA4, - 0x2E, 0xA6, 0xCC, 0x5F, 0x98, 0x8F, 0x4B, 0x58, 0x70, 0xFF, 0x41, 0x98, - 0xC3, 0x75, 0x8A, 0x37, 0x86, 0x10, 0xAA, 0xD4, 0xAC, 0xC3, 0x4B, 0x35, - 0x98, 0xB0, 0xE8, 0x98, 0xAE, 0x30, 0x3D, 0x4F, 0xA2, 0x70, 0xCD, 0x94, - 0x66, 0x49, 0xE0, 0xB8, 0x16, 0xEB, 0xA3, 0xF2, 0xF4, 0x91, 0xA4, 0x0F, - 0xA3, 0x42, 0xCB, 0x96, 0x43, 0x12, 0xEA, 0x93, 0x21, 0x9B, 0x02, 0x73, - 0xD8, 0x68, 0x39, 0xA9, 0x1D, 0xFA, 0x8D, 0x55, 0xD2, 0xE3, 0xF1, 0x7D, - 0xD1, 0xCD, 0x33, 0x63, 0x51, 0xFC, 0x15, 0x0D, 0xCB, 0xBF, 0xC0, 0xE4, - 0x3D, 0x40}; -const uint8_t g_zhTW_Locale[] = { - 0x78, 0x9C, 0xED, 0x57, 0xCD, 0x4F, 0xD4, 0x40, 0x14, 0x3F, 0x63, 0xE2, - 0xFF, 0x30, 0x69, 0x20, 0xD5, 0x04, 0xA8, 0x1E, 0x21, 0xA5, 0xC9, 0xC6, - 0x45, 0x30, 0x58, 0x42, 0xEC, 0x46, 0x22, 0x17, 0x33, 0xDB, 0x0E, 0xDB, - 0xC2, 0xB6, 0x43, 0x66, 0xDB, 0xC0, 0xF6, 0x24, 0x12, 0x14, 0x14, 0x62, - 0xA2, 0xC4, 0x8F, 0x80, 0xE1, 0x64, 0x3C, 0x28, 0x89, 0x07, 0x0F, 0x2C, - 0x51, 0xFF, 0x1A, 0x76, 0x39, 0xFA, 0x2F, 0x38, 0xD3, 0x2F, 0xFA, 0xB1, - 0xB3, 0xD4, 0xC4, 0xA3, 0x7B, 0x9A, 0xF7, 0xDE, 0xEF, 0xF7, 0xE6, 0xBD, - 0xDF, 0xBC, 0x7D, 0xD9, 0x95, 0x9B, 0x58, 0x87, 0x4D, 0x04, 0x1C, 0x68, - 0xA3, 0x29, 0xC1, 0x37, 0x1F, 0xD7, 0x16, 0x05, 0x60, 0xA0, 0x96, 0x3E, - 0x25, 0x9C, 0x9F, 0x9E, 0xF4, 0xDE, 0x3E, 0xBF, 0x71, 0xD1, 0xD9, 0x3C, - 0xFF, 0xF9, 0xE6, 0xF7, 0x8F, 0xBD, 0xEE, 0xAB, 0x6F, 0xBD, 0xCE, 0xAF, - 0x9B, 0x82, 0x72, 0xFD, 0x1A, 0x00, 0x32, 0x63, 0x39, 0x06, 0x24, 0x5A, - 0xDB, 0xAE, 0xE3, 0x66, 0x2B, 0x4A, 0xD0, 0x20, 0xA8, 0x81, 0x89, 0x05, - 0x1D, 0x86, 0x1A, 0x02, 0xB2, 0x8D, 0x1D, 0xD7, 0x9C, 0xA7, 0xA1, 0x16, - 0xB3, 0x87, 0x42, 0x5B, 0x39, 0x3F, 0x7D, 0xD2, 0x3B, 0xDA, 0x91, 0xA5, - 0xD0, 0x4A, 0x07, 0xCE, 0xF6, 0x38, 0x81, 0xD3, 0xDD, 0xFE, 0x81, 0xEE, - 0xE1, 0x21, 0x2F, 0xD5, 0x01, 0x87, 0xB1, 0x7D, 0xC2, 0xBB, 0x63, 0x8B, - 0xC7, 0xF8, 0xC2, 0x61, 0x74, 0x3E, 0x72, 0x18, 0xFB, 0x9B, 0xDC, 0x00, - 0xB7, 0x79, 0x16, 0xCB, 0xF7, 0x0F, 0xA2, 0x73, 0x22, 0x61, 0x5A, 0x52, - 0x00, 0xEB, 0x75, 0x32, 0x25, 0xDC, 0x16, 0xFE, 0x6B, 0xFB, 0x8F, 0xB4, - 0x35, 0x60, 0x3B, 0x35, 0xAC, 0xD4, 0x52, 0x7A, 0xEF, 0x8F, 0x7B, 0x47, - 0xC7, 0xBD, 0x77, 0x9F, 0x64, 0x89, 0x99, 0x39, 0x3F, 0xBD, 0xAF, 0xBF, - 0xFF, 0x6C, 0x8F, 0x83, 0xDF, 0xED, 0xEB, 0xA7, 0x4A, 0x73, 0xF2, 0x1C, - 0xF4, 0xC7, 0x6F, 0x9F, 0x24, 0x7E, 0x10, 0x9C, 0xFA, 0x34, 0x91, 0x1B, - 0x8F, 0x80, 0x5D, 0xE8, 0xA3, 0xD8, 0x41, 0xB1, 0xF6, 0x62, 0xD5, 0xC5, - 0x7A, 0x8B, 0x95, 0x0E, 0xAC, 0xD1, 0x46, 0xC4, 0x32, 0x2C, 0x64, 0xA7, - 0x57, 0x43, 0xE4, 0xA2, 0xD7, 0xBD, 0xE8, 0xEE, 0xB3, 0x87, 0x8A, 0x1D, - 0xF9, 0xF0, 0xCB, 0x42, 0x18, 0x5C, 0x9A, 0xA9, 0x4B, 0x10, 0x81, 0xA9, - 0xFC, 0xD4, 0xA2, 0x35, 0x7D, 0xED, 0x6E, 0x6F, 0x75, 0x77, 0xF7, 0x65, - 0x89, 0x99, 0x39, 0x7F, 0xE2, 0x04, 0xC1, 0x29, 0xE6, 0xD2, 0x65, 0x27, - 0xE5, 0xB6, 0x5D, 0xE8, 0x35, 0xA0, 0x8B, 0x16, 0xA0, 0xEB, 0x22, 0xE2, - 0x24, 0xD2, 0x27, 0x9E, 0x68, 0x21, 0x2E, 0x7B, 0xCD, 0xA6, 0xA0, 0x3C, - 0xA2, 0x1F, 0xB1, 0xDB, 0xF9, 0x2E, 0xAA, 0x22, 0x9D, 0x41, 0xB1, 0x2A, - 0xD2, 0x87, 0x10, 0xA7, 0xE9, 0x87, 0xE9, 0x92, 0x50, 0x78, 0x39, 0x9A, - 0xD8, 0x69, 0x70, 0x72, 0x94, 0xE2, 0xDB, 0xC8, 0x08, 0xE9, 0x92, 0x2A, - 0x55, 0x4B, 0x31, 0x5A, 0x26, 0x26, 0x2E, 0x9F, 0x03, 0x40, 0xC6, 0x13, - 0xC9, 0xE1, 0x5A, 0x76, 0x4E, 0x8E, 0x94, 0x27, 0x23, 0x47, 0xC5, 0x34, - 0xC5, 0xDE, 0x87, 0xA7, 0xA2, 0xAA, 0x8A, 0xDD, 0x9D, 0x67, 0xA2, 0xA6, - 0x89, 0x17, 0x9F, 0x5F, 0x8B, 0x60, 0x49, 0x96, 0x52, 0x0C, 0x5E, 0x8A, - 0x50, 0x8D, 0xFE, 0x29, 0x4A, 0x25, 0x08, 0xE4, 0xA8, 0x00, 0x73, 0x52, - 0x55, 0x27, 0x35, 0xAD, 0x14, 0x25, 0xD2, 0x23, 0x24, 0xE5, 0x19, 0x4C, - 0x8D, 0x5C, 0xEF, 0xD1, 0x70, 0xD4, 0xA8, 0x37, 0x9E, 0x98, 0x19, 0xE8, - 0xAC, 0xAC, 0xCE, 0xDA, 0x2D, 0x6D, 0xBA, 0x7A, 0x77, 0x7D, 0x71, 0xC3, - 0x9C, 0xF3, 0x97, 0x42, 0x11, 0xD3, 0xA0, 0x80, 0xE9, 0x78, 0x76, 0x1D, - 0x91, 0xAC, 0x92, 0x19, 0x5F, 0x54, 0x14, 0xF5, 0xD1, 0x99, 0xD7, 0x05, - 0xC5, 0x1F, 0xF5, 0xFD, 0x89, 0x71, 0xDF, 0xF7, 0x65, 0x29, 0x83, 0xE3, - 0x53, 0x75, 0x8F, 0x10, 0xE4, 0xE8, 0x6D, 0x41, 0x19, 0x0E, 0xC9, 0x13, - 0x13, 0xA5, 0xB9, 0x6B, 0x88, 0xE8, 0xC8, 0x71, 0xA3, 0x6B, 0x47, 0x8A, - 0x3C, 0xA6, 0x47, 0xA1, 0x87, 0xA4, 0xAF, 0xCB, 0x56, 0x87, 0xB2, 0xAE, - 0x28, 0xBD, 0x81, 0x74, 0xCB, 0x86, 0x74, 0x48, 0xC6, 0xE3, 0x2C, 0x61, - 0x98, 0x4B, 0x68, 0x10, 0xEC, 0xAD, 0x59, 0x6C, 0x26, 0x46, 0x4B, 0x32, - 0x92, 0x0E, 0x46, 0x4A, 0x12, 0x6C, 0xCB, 0xF1, 0x5A, 0x82, 0x32, 0x56, - 0x12, 0xEE, 0x23, 0x82, 0x05, 0xE5, 0x56, 0x01, 0x7D, 0x29, 0x4C, 0xE6, - 0xBD, 0xE3, 0xC7, 0xC8, 0x28, 0x93, 0x75, 0xC6, 0x63, 0x18, 0x18, 0x82, - 0x32, 0x5F, 0x1B, 0xA6, 0x2B, 0x29, 0x83, 0x18, 0xC0, 0xB2, 0x5A, 0x98, - 0x1D, 0x04, 0xA5, 0xB6, 0x58, 0xFD, 0x0B, 0x5A, 0xFA, 0x21, 0x0A, 0xA4, - 0x60, 0x27, 0x16, 0xEA, 0x66, 0x4B, 0xA0, 0xBD, 0x86, 0x96, 0xA1, 0x1E, - 0xAF, 0xE0, 0xD8, 0x8C, 0x72, 0x56, 0x0C, 0x5C, 0x47, 0x40, 0xA5, 0xAF, - 0x05, 0x34, 0xD7, 0x00, 0xF7, 0x05, 0xA9, 0x2F, 0x4C, 0x6D, 0xD3, 0x9F, - 0x90, 0x06, 0x58, 0xA0, 0x32, 0x72, 0x00, 0x96, 0x63, 0x61, 0x67, 0x00, - 0xE0, 0x0E, 0xF6, 0x88, 0x85, 0x08, 0xBB, 0x85, 0x83, 0x08, 0x4B, 0x59, - 0xB0, 0xAE, 0x84, 0xCC, 0xA2, 0x3A, 0x41, 0xEB, 0x03, 0x21, 0x15, 0x02, - 0xEB, 0xF4, 0x8B, 0x38, 0x08, 0x52, 0x33, 0xA1, 0xC5, 0x01, 0xCC, 0x61, - 0xDF, 0x5B, 0x85, 0x60, 0x06, 0xBB, 0xA6, 0xA5, 0xB3, 0x9E, 0xC6, 0x1E, - 0xDE, 0x03, 0xEA, 0x60, 0x30, 0x15, 0x40, 0x37, 0x71, 0x0C, 0x7E, 0x30, - 0xF0, 0x6A, 0x0D, 0x5F, 0x21, 0x77, 0xF4, 0x2A, 0x6D, 0xCF, 0x69, 0xAC, - 0xE0, 0x00, 0x19, 0xDE, 0x1E, 0x2C, 0xB6, 0xD4, 0x7B, 0xCA, 0x52, 0xF8, - 0x67, 0x41, 0xF9, 0x03, 0x11, 0xC2, 0x4A, 0xC9}; -const uint8_t g_zhHK_Locale[] = { - 0x78, 0x9C, 0xA5, 0x57, 0x4D, 0x4F, 0x13, 0x41, 0x18, 0x3E, 0x63, 0xE2, - 0x7F, 0x98, 0x6C, 0x20, 0x0B, 0x09, 0x50, 0x8A, 0x9F, 0x25, 0xCB, 0x26, - 0x44, 0x90, 0x9A, 0x5A, 0x43, 0x2C, 0xD1, 0xC8, 0xC5, 0x6C, 0x77, 0x87, - 0xEE, 0x42, 0x77, 0x87, 0x4C, 0xB7, 0xC1, 0x6E, 0x3C, 0x88, 0x04, 0xA5, - 0x5A, 0x2E, 0x4A, 0x54, 0x02, 0x86, 0x78, 0x50, 0x0F, 0x48, 0xBC, 0x78, - 0x68, 0x89, 0xC6, 0x3F, 0x43, 0x8B, 0x9E, 0xFC, 0x0B, 0xCE, 0xEC, 0x17, - 0xFB, 0x35, 0x6D, 0x8D, 0x3D, 0xCD, 0xFB, 0xBC, 0xCF, 0xF3, 0xCE, 0xFB, - 0x3E, 0x33, 0x3B, 0x01, 0xA1, 0x8C, 0x64, 0xA9, 0x0C, 0x81, 0x21, 0xE9, - 0x70, 0x9A, 0xB3, 0xD4, 0x87, 0xD9, 0x1C, 0x07, 0x14, 0x58, 0x91, 0xA7, - 0xB9, 0xD3, 0xE6, 0x71, 0xE7, 0xCD, 0xF3, 0xE1, 0xB3, 0xD6, 0xC6, 0xE9, - 0x8F, 0xD7, 0x7F, 0xBE, 0x37, 0x7E, 0x7F, 0xDA, 0xEB, 0x34, 0xBF, 0x9E, - 0xD5, 0x5B, 0xED, 0xED, 0xA3, 0x5F, 0x1F, 0x1A, 0x9D, 0xDD, 0x9F, 0xED, - 0xC6, 0xC9, 0x08, 0x27, 0x5E, 0xBC, 0x00, 0x80, 0x40, 0x8B, 0x18, 0x8A, - 0x84, 0x0B, 0x35, 0xBD, 0x88, 0xCA, 0x15, 0xB7, 0x5E, 0x09, 0xC3, 0x12, - 0xC2, 0x9A, 0x64, 0x50, 0xD6, 0x00, 0x10, 0x74, 0x64, 0x98, 0xEA, 0x1D, - 0x92, 0xAA, 0xD0, 0x78, 0xC0, 0x89, 0xC5, 0xD3, 0xE6, 0x93, 0xCE, 0xC1, - 0xB6, 0x90, 0x72, 0xA2, 0x60, 0xE2, 0xA4, 0xC1, 0x48, 0x34, 0xEB, 0xC9, - 0x89, 0xF6, 0xFE, 0x3E, 0xAB, 0xD4, 0x2E, 0x43, 0xB1, 0x75, 0xCC, 0xDA, - 0x63, 0x93, 0xA5, 0x38, 0x62, 0x28, 0x5A, 0xEF, 0x19, 0x8A, 0x9D, 0x0D, - 0x66, 0x82, 0x39, 0x3C, 0xCD, 0x45, 0xE7, 0x07, 0xEE, 0xDA, 0xB7, 0x30, - 0x68, 0x29, 0x90, 0x8A, 0x45, 0x3C, 0xCD, 0xA5, 0xB9, 0x60, 0x95, 0x74, - 0x72, 0xF1, 0xC9, 0x64, 0xF8, 0x52, 0x32, 0x7C, 0x39, 0x19, 0xBE, 0x92, - 0x0C, 0x5F, 0x4D, 0x86, 0xAF, 0x25, 0xC3, 0xD7, 0x93, 0xE1, 0x4C, 0x32, - 0x9C, 0x9E, 0x60, 0xE0, 0x8C, 0x39, 0xD3, 0x93, 0x3D, 0x0D, 0x54, 0xA4, - 0x5A, 0xE0, 0x46, 0x92, 0x48, 0xEC, 0xBC, 0x3B, 0xEC, 0x1C, 0x1C, 0x76, - 0xDE, 0x7E, 0x14, 0x52, 0x34, 0x8C, 0xE0, 0xE4, 0xC0, 0x92, 0xF1, 0x93, - 0x06, 0x83, 0x5F, 0x4F, 0xC4, 0xC9, 0x55, 0x65, 0xD4, 0xD9, 0x4D, 0xE6, - 0x6F, 0x1D, 0xFB, 0x38, 0xB0, 0x57, 0x09, 0x43, 0x44, 0xEE, 0x80, 0xAD, - 0x8E, 0xCD, 0x11, 0x9F, 0x20, 0xDE, 0x7B, 0xBC, 0xEB, 0x78, 0xBF, 0xF1, - 0x4E, 0xBB, 0xF6, 0xA8, 0x43, 0xAC, 0x29, 0x1A, 0xD4, 0x83, 0xDF, 0xBF, - 0x0B, 0x91, 0xED, 0x5E, 0xB4, 0x77, 0xE8, 0x41, 0x79, 0x40, 0x34, 0xFD, - 0x32, 0x96, 0x06, 0xE7, 0x61, 0x60, 0x13, 0x88, 0xA5, 0x40, 0x7D, 0x12, - 0x91, 0x9E, 0xBE, 0xB4, 0xB7, 0x36, 0xDB, 0xF5, 0x1D, 0x21, 0x45, 0xC3, - 0x08, 0xEE, 0x83, 0xC0, 0x5E, 0x79, 0x5A, 0xF2, 0xA2, 0xA5, 0x22, 0x4F, - 0x9A, 0x83, 0x2A, 0x92, 0x09, 0x17, 0x24, 0xD3, 0x84, 0xD8, 0xF0, 0xAD, - 0xF7, 0x11, 0xF7, 0xD5, 0x5B, 0xAE, 0x96, 0xCB, 0x9C, 0xF8, 0x80, 0xFC, - 0xF8, 0x76, 0xEB, 0x1B, 0x9F, 0xE7, 0xC9, 0x1D, 0xE4, 0x67, 0x79, 0x72, - 0x10, 0x3C, 0x98, 0x23, 0x3F, 0x6A, 0x8C, 0xAF, 0x61, 0x15, 0x29, 0x23, - 0xA3, 0xC4, 0x28, 0xD2, 0x97, 0x5E, 0x87, 0xCA, 0xFF, 0xC8, 0x2B, 0x2A, - 0xC2, 0x26, 0x2D, 0xD0, 0x53, 0x0E, 0x40, 0x08, 0x71, 0x7D, 0x32, 0x35, - 0x3D, 0xE2, 0x53, 0x00, 0x09, 0xF9, 0x34, 0xA3, 0xAA, 0x7C, 0x67, 0xEF, - 0x29, 0x9F, 0xCF, 0xF3, 0xED, 0xED, 0x67, 0x7C, 0xA1, 0xC0, 0x9F, 0x7D, - 0x7E, 0xC5, 0x83, 0x25, 0x21, 0x15, 0x50, 0xB0, 0x4A, 0x38, 0x2E, 0x25, - 0x97, 0xE8, 0xAB, 0x80, 0x6D, 0x13, 0xD1, 0x4F, 0xE5, 0xF3, 0x53, 0x85, - 0x42, 0x5F, 0x12, 0xD7, 0x9A, 0x19, 0xAA, 0x89, 0x0A, 0xA8, 0x19, 0x91, - 0xD1, 0xDD, 0x4B, 0xB3, 0x48, 0x50, 0xEF, 0x26, 0xCD, 0x4B, 0xC6, 0xCA, - 0x6A, 0x56, 0xAF, 0x14, 0xE6, 0x66, 0x6F, 0xAE, 0xDF, 0x7F, 0xA4, 0xE6, - 0xAC, 0x25, 0xC7, 0xC3, 0x20, 0xC9, 0x56, 0x1A, 0x55, 0xBD, 0x08, 0x71, - 0xD8, 0xC8, 0x10, 0xE6, 0xF6, 0x44, 0x30, 0xF2, 0x2D, 0xC8, 0x9C, 0x68, - 0x8D, 0x5A, 0x56, 0x66, 0xDC, 0xB2, 0x2C, 0x21, 0x15, 0xE2, 0xB1, 0xA5, - 0x72, 0x15, 0x63, 0x68, 0xC8, 0x35, 0x4E, 0x1C, 0x74, 0xC4, 0x99, 0xCC, - 0xE3, 0x61, 0x7F, 0x39, 0xD2, 0x77, 0x9D, 0x35, 0x88, 0x65, 0x68, 0x98, - 0x6E, 0x0B, 0x43, 0x71, 0x1D, 0xF5, 0x26, 0x36, 0x8F, 0x3F, 0xE3, 0xF9, - 0xD8, 0x03, 0x61, 0xC8, 0x2D, 0xAF, 0x40, 0x59, 0xD3, 0x25, 0x72, 0x5F, - 0xC6, 0xBD, 0x2A, 0x4E, 0x9A, 0x29, 0x28, 0x61, 0x54, 0x5D, 0xD3, 0xE8, - 0xF5, 0x18, 0xED, 0x53, 0xE1, 0x4F, 0x30, 0xD4, 0xA7, 0x40, 0xD7, 0x8C, - 0x6A, 0x85, 0x13, 0xC7, 0xFA, 0xA4, 0x5B, 0x10, 0x23, 0x4E, 0x9C, 0x88, - 0xB1, 0xCF, 0x8D, 0x09, 0x9D, 0xBD, 0x77, 0x30, 0x21, 0x67, 0xC2, 0xA0, - 0x77, 0x23, 0xED, 0x80, 0x13, 0xB3, 0xB9, 0x41, 0xF2, 0x6C, 0x85, 0x18, - 0x5D, 0x54, 0x5A, 0x05, 0xD1, 0x05, 0x95, 0xCD, 0xFE, 0x83, 0x2C, 0x78, - 0x10, 0x31, 0x91, 0xFD, 0x6E, 0xC6, 0xFA, 0xA6, 0xEF, 0x41, 0x6D, 0x0D, - 0x2E, 0x4B, 0xB2, 0xF7, 0x4C, 0x7B, 0xA1, 0x5B, 0x73, 0x46, 0x41, 0x45, - 0x08, 0xF2, 0xE4, 0xB4, 0x40, 0xC1, 0x54, 0xC0, 0x6D, 0x2E, 0x95, 0x48, - 0xCB, 0xD7, 0xC8, 0xDF, 0x92, 0x0A, 0x58, 0x20, 0x36, 0x32, 0x08, 0x9A, - 0xA1, 0x21, 0xA3, 0x0B, 0xE1, 0x06, 0xAA, 0x62, 0x0D, 0x62, 0xBA, 0x0B, - 0x83, 0xE1, 0xB4, 0xB2, 0xA0, 0xF5, 0xA4, 0x64, 0x61, 0x11, 0xC3, 0xF5, - 0xAE, 0x94, 0x19, 0x2C, 0x15, 0xC9, 0x47, 0xD9, 0x8D, 0xB2, 0xA8, 0x4A, - 0x1A, 0x83, 0x90, 0x43, 0x56, 0x75, 0x55, 0x02, 0xF3, 0xC8, 0x54, 0x35, - 0x99, 0xCE, 0x34, 0x76, 0xEF, 0x16, 0xC8, 0x77, 0x27, 0x13, 0x03, 0x64, - 0x15, 0x79, 0xE4, 0xBB, 0x5D, 0xB7, 0x2E, 0xA0, 0x1E, 0x76, 0xBB, 0xA7, - 0x52, 0xAB, 0x1A, 0xA5, 0x15, 0x64, 0x33, 0x9D, 0xDD, 0xED, 0x47, 0x2E, - 0x70, 0x9E, 0x42, 0xCA, 0xF9, 0x27, 0x42, 0xFC, 0x0B, 0xD9, 0x0E, 0x4B, - 0xED}; -const uint8_t g_jaJP_Locale[] = { - 0x78, 0x9C, 0xED, 0x56, 0xCB, 0x6E, 0xD3, 0x40, 0x14, 0x5D, 0x17, 0x89, - 0x7F, 0x18, 0x59, 0x20, 0x83, 0xD4, 0xD6, 0x0D, 0xEF, 0x56, 0xAE, 0xA5, - 0x8A, 0x96, 0x86, 0x16, 0xA3, 0x08, 0x57, 0xA0, 0x76, 0x83, 0x26, 0xF6, - 0x34, 0x99, 0x36, 0x9E, 0xA9, 0x26, 0xB6, 0x4A, 0xBC, 0xE2, 0x21, 0x20, - 0x48, 0x74, 0x01, 0x1B, 0x04, 0x44, 0x62, 0x55, 0x40, 0x02, 0x04, 0x8B, - 0x6E, 0xD8, 0xD0, 0xAF, 0x49, 0x5A, 0x56, 0xFC, 0x02, 0x33, 0x7E, 0xC5, - 0x8E, 0xED, 0xE0, 0xEE, 0xF1, 0x22, 0x99, 0x7B, 0x7C, 0xCE, 0xF5, 0xBD, - 0xE7, 0x8E, 0x47, 0x56, 0x5B, 0xD4, 0x84, 0x2D, 0x04, 0x08, 0xB4, 0xD1, - 0xBC, 0xB4, 0x05, 0xEF, 0xAF, 0xD4, 0x24, 0x60, 0xA1, 0xB6, 0x39, 0x2F, - 0x0D, 0xDE, 0xEC, 0x1F, 0x7F, 0xFF, 0x76, 0x8E, 0xFF, 0x0D, 0x7A, 0x5F, - 0xCF, 0x4B, 0xDA, 0xE9, 0x53, 0x00, 0xA8, 0x82, 0x4C, 0x2C, 0xC8, 0x8C, - 0x8E, 0x5D, 0xA7, 0xAD, 0x76, 0xA8, 0x6B, 0x30, 0xD4, 0xA0, 0x0C, 0x43, - 0x22, 0x58, 0x13, 0x40, 0xB5, 0x29, 0x71, 0x9A, 0xB7, 0xF9, 0xAD, 0xB6, - 0x88, 0x27, 0x82, 0x58, 0xAB, 0x0C, 0x7A, 0x5D, 0x55, 0x09, 0xD6, 0x09, - 0xF8, 0x42, 0x3E, 0x7C, 0x31, 0x1F, 0xBE, 0x94, 0x0F, 0x5F, 0xCE, 0x87, - 0xAF, 0xE4, 0xC3, 0x57, 0xF3, 0xE1, 0x6B, 0xF9, 0xF0, 0x6C, 0x3E, 0x5C, - 0x99, 0x29, 0xC0, 0x0B, 0xFA, 0xAC, 0x8C, 0x34, 0x0A, 0xC2, 0x75, 0xEC, - 0x53, 0xD2, 0x37, 0x00, 0xEB, 0x75, 0x36, 0x2F, 0x55, 0xA4, 0xFF, 0x06, - 0x9E, 0xC4, 0x40, 0x0B, 0x76, 0x12, 0xDB, 0x8E, 0x47, 0x9A, 0xD8, 0xBE, - 0xEF, 0x7B, 0xFC, 0x57, 0x55, 0x44, 0x38, 0xC4, 0x7B, 0xDD, 0x5C, 0xFC, - 0xE8, 0xD1, 0x97, 0x7C, 0xFE, 0x8F, 0x83, 0x82, 0x3C, 0x9F, 0x73, 0xF1, - 0xDF, 0xCF, 0x5F, 0xE5, 0xE2, 0xFD, 0xDE, 0x87, 0x11, 0x1C, 0xF8, 0xAB, - 0x9C, 0x26, 0x46, 0xF6, 0x40, 0xD8, 0x4D, 0xB6, 0x8F, 0x6C, 0x07, 0xD9, - 0xDA, 0xB3, 0x55, 0x67, 0xEB, 0xCD, 0x56, 0x5A, 0x5C, 0xA3, 0x8D, 0x18, - 0xB6, 0x30, 0xB2, 0x93, 0x2F, 0x79, 0x08, 0x69, 0xFD, 0xBD, 0x6E, 0xFF, - 0xC5, 0x1E, 0x1F, 0x4E, 0x04, 0x64, 0x6F, 0xFF, 0x7A, 0x99, 0xBE, 0x0D, - 0x86, 0x61, 0xE2, 0x21, 0x88, 0xC1, 0x44, 0x7E, 0x1E, 0x69, 0x47, 0x07, - 0x0F, 0xFB, 0x4F, 0x9F, 0xF8, 0xD9, 0x45, 0x18, 0xE3, 0xC7, 0xFB, 0x87, - 0x83, 0x77, 0x1F, 0x63, 0x10, 0xF8, 0xAB, 0x48, 0xCB, 0x8F, 0x2D, 0x65, - 0xE4, 0xDC, 0x0A, 0x50, 0x0B, 0x3A, 0xA8, 0x06, 0x1D, 0x07, 0x31, 0x12, - 0x5B, 0x1F, 0x23, 0xE1, 0xD1, 0xB6, 0xE9, 0xB6, 0x5A, 0x92, 0xB6, 0xCE, - 0x2F, 0xB9, 0xFF, 0xF3, 0x40, 0xD6, 0x65, 0x6E, 0xB8, 0xBC, 0x28, 0xF3, - 0x41, 0xC8, 0x4B, 0xFC, 0x12, 0xBE, 0xC4, 0x92, 0xA2, 0x1C, 0x2D, 0x4A, - 0x1A, 0x05, 0x39, 0x4A, 0xE9, 0x6D, 0x64, 0x05, 0x72, 0x45, 0xD7, 0x95, - 0xC5, 0xC5, 0x52, 0x9A, 0x76, 0x93, 0x32, 0x47, 0xA8, 0xF2, 0x35, 0x00, - 0xA4, 0x90, 0xD0, 0x10, 0x07, 0xDB, 0x23, 0x86, 0x24, 0x90, 0x94, 0x21, - 0x55, 0x79, 0xF0, 0xF6, 0xB1, 0xAC, 0xEB, 0x72, 0xBF, 0xFB, 0x4C, 0x36, - 0x0C, 0xF9, 0xE8, 0xD3, 0x6B, 0x79, 0x43, 0x55, 0x12, 0xF4, 0x22, 0x7D, - 0x60, 0x46, 0x75, 0x4E, 0xD7, 0xE7, 0x0C, 0x63, 0xAE, 0x9C, 0xC6, 0x37, - 0x20, 0x94, 0x94, 0x12, 0x84, 0xDD, 0x0B, 0xC9, 0x28, 0x5F, 0x74, 0x3E, - 0xD2, 0x67, 0xB8, 0x15, 0xD6, 0x38, 0x1A, 0xED, 0x8F, 0x65, 0x48, 0xB6, - 0xB6, 0xAB, 0x76, 0xDB, 0x58, 0x5A, 0xBC, 0xB1, 0x7B, 0xEF, 0x41, 0x73, - 0xD5, 0xDB, 0x08, 0x0C, 0x4B, 0x92, 0x7C, 0x25, 0x71, 0xED, 0x3A, 0x62, - 0x69, 0xD7, 0x52, 0x58, 0x58, 0x12, 0xC7, 0xF8, 0x0E, 0x37, 0x25, 0xCD, - 0x9B, 0xF4, 0xBC, 0xD9, 0x69, 0xCF, 0xF3, 0x54, 0x25, 0xC5, 0x2B, 0x96, - 0x9A, 0x2E, 0x63, 0x88, 0x98, 0x1D, 0x49, 0x3B, 0xE3, 0x8B, 0x4B, 0x0B, - 0x77, 0x10, 0x33, 0x11, 0x71, 0xC2, 0x67, 0x9E, 0xCD, 0xEA, 0x84, 0x19, - 0x99, 0x06, 0xE2, 0xA6, 0x86, 0x7D, 0x4E, 0xA4, 0xA1, 0x30, 0xBD, 0x85, - 0x4C, 0x6C, 0x43, 0xBE, 0x1B, 0xA6, 0xA3, 0x2C, 0xC1, 0xED, 0x42, 0x41, - 0x83, 0x51, 0x77, 0x07, 0x8B, 0xF9, 0x4F, 0x96, 0x54, 0xC4, 0x1D, 0x9C, - 0x2D, 0x29, 0xB0, 0x31, 0x71, 0xDB, 0x92, 0x36, 0x55, 0x92, 0xEE, 0x21, - 0x46, 0x25, 0x6D, 0x26, 0xC3, 0x1E, 0x1A, 0x93, 0x1A, 0x76, 0x34, 0x89, - 0x94, 0x33, 0x69, 0x30, 0xDA, 0x81, 0x7E, 0x20, 0x69, 0x7F, 0x0E, 0xF9, - 0x89, 0x9D, 0x66, 0x8C, 0x51, 0xE1, 0x36, 0x15, 0x0B, 0x49, 0x5B, 0xA9, - 0xAD, 0x9F, 0x40, 0x96, 0x1C, 0x44, 0x46, 0xE4, 0x1F, 0x7F, 0x99, 0xBA, - 0xC5, 0xDB, 0xDE, 0xD9, 0x41, 0x9B, 0xD0, 0x8C, 0x4E, 0xDB, 0x28, 0x0C, - 0x73, 0xAE, 0x52, 0xCF, 0xDD, 0x86, 0x60, 0x99, 0x3A, 0x4D, 0x6C, 0x82, - 0x1A, 0xA3, 0x53, 0x77, 0x6F, 0x02, 0x5D, 0x52, 0xC6, 0x91, 0x75, 0x4C, - 0xCC, 0x26, 0x8D, 0xC8, 0x77, 0x0A, 0xC8, 0x7A, 0x87, 0x7F, 0x2A, 0x5A, - 0x82, 0x55, 0x44, 0xC0, 0x04, 0x53, 0x32, 0x86, 0x70, 0x9D, 0xBA, 0x0C, - 0x23, 0x06, 0x0C, 0xC7, 0x2A, 0x60, 0x2C, 0x58, 0xB4, 0x8E, 0x40, 0x0D, - 0xFF, 0x93, 0x52, 0x45, 0x75, 0x86, 0x76, 0xC7, 0x52, 0x16, 0x18, 0xAC, - 0xF3, 0x17, 0x77, 0x1C, 0x65, 0xAD, 0x09, 0xF1, 0x58, 0x02, 0x6F, 0xA9, - 0x21, 0x6A, 0x01, 0xB7, 0xC6, 0xD2, 0x0C, 0x5A, 0x8A, 0xA6, 0x77, 0x5C, - 0xD2, 0xD8, 0xA2, 0x3E, 0x33, 0x18, 0x89, 0x7F, 0xAA, 0x25, 0xE6, 0xA9, - 0x2A, 0xC1, 0x87, 0xBD, 0xF6, 0x17, 0x6C, 0x42, 0x08, 0x21}; -const uint8_t g_koKR_Locale[] = { - 0x78, 0x9C, 0xED, 0x56, 0x4D, 0x6B, 0xD4, 0x40, 0x18, 0x3E, 0x57, 0xF0, - 0x3F, 0x0C, 0xC1, 0x12, 0x85, 0x76, 0xB7, 0xEB, 0x77, 0x4B, 0x1A, 0x28, - 0x6E, 0x6D, 0x65, 0x8D, 0x94, 0xA6, 0x58, 0xEC, 0x45, 0x66, 0x93, 0xE9, - 0x26, 0xED, 0x26, 0x53, 0x26, 0x09, 0x75, 0x73, 0xAE, 0x52, 0xF0, 0xE2, - 0xA1, 0x87, 0xEA, 0x6E, 0xB1, 0x07, 0x11, 0x2A, 0x88, 0x22, 0x22, 0x1E, - 0x14, 0x7F, 0x8D, 0x62, 0x6D, 0x8A, 0x7F, 0xC1, 0xC9, 0xE7, 0xE6, 0x63, - 0xB2, 0x4D, 0xEF, 0xEE, 0x61, 0x99, 0xF7, 0x99, 0xE7, 0x79, 0xF3, 0xBE, - 0xCF, 0x4C, 0x5E, 0x22, 0x74, 0xB1, 0x02, 0xBB, 0x08, 0x98, 0xD0, 0x40, - 0xB3, 0xDC, 0x26, 0x7E, 0xDC, 0x5A, 0xE6, 0x80, 0x8A, 0x2C, 0x65, 0x96, - 0xFB, 0x35, 0x38, 0x38, 0xFE, 0x34, 0xF8, 0xFD, 0xE1, 0xFD, 0xE5, 0xE3, - 0xD7, 0x47, 0x3F, 0xFB, 0xDF, 0xAF, 0x70, 0xE2, 0xC5, 0x0B, 0x00, 0x08, - 0x3E, 0xDF, 0x54, 0x21, 0x91, 0x7B, 0x46, 0x1B, 0x77, 0xAD, 0x48, 0xDA, - 0x21, 0xA8, 0x83, 0x89, 0x0E, 0x4D, 0x9F, 0x35, 0x06, 0x04, 0x03, 0x9B, - 0xB6, 0xF6, 0x80, 0x6E, 0x59, 0x7E, 0x3C, 0x16, 0xC6, 0x62, 0xC3, 0xEB, - 0xEF, 0x09, 0xF5, 0x70, 0x9D, 0x82, 0xAF, 0xB2, 0xE1, 0x6B, 0x6C, 0xF8, - 0x3A, 0x1B, 0xBE, 0xC1, 0x86, 0x6F, 0xB2, 0xE1, 0x5B, 0x6C, 0xF8, 0x36, - 0x1B, 0x9E, 0x66, 0xC3, 0x8D, 0xA9, 0x12, 0xBC, 0xA4, 0xCF, 0x46, 0xAE, - 0x51, 0x10, 0xAD, 0x13, 0x9F, 0xD2, 0xBE, 0x01, 0xD8, 0x6E, 0x93, 0x59, - 0xAE, 0xC1, 0xFD, 0x37, 0xF0, 0x3C, 0x06, 0xAA, 0xB0, 0x97, 0xBA, 0x76, - 0x34, 0x12, 0xBD, 0x83, 0x6F, 0xDE, 0xAB, 0x3D, 0xFA, 0x2F, 0xD4, 0xFD, - 0x70, 0x88, 0xF7, 0xF7, 0x98, 0xF8, 0xE9, 0x4B, 0x36, 0xEE, 0xED, 0xEE, - 0x33, 0xF1, 0x93, 0x77, 0x47, 0x4C, 0xFC, 0xCF, 0xD7, 0x5D, 0x76, 0xFE, - 0x67, 0x87, 0x39, 0x1C, 0x04, 0x2B, 0x46, 0x13, 0xB9, 0x3B, 0x10, 0x75, - 0x53, 0xEC, 0xA3, 0xD8, 0x41, 0xB1, 0xF6, 0x62, 0xD5, 0xC5, 0x7A, 0x8B, - 0x95, 0x96, 0xD7, 0x68, 0x20, 0xA2, 0xAB, 0x3A, 0x32, 0xD2, 0x2F, 0x79, - 0x04, 0x89, 0xDE, 0xFE, 0x1B, 0xEF, 0x70, 0x87, 0x1E, 0x4E, 0x0C, 0x14, - 0xB6, 0x4F, 0xFB, 0xB9, 0x6D, 0x30, 0x0C, 0x53, 0x0F, 0x41, 0x04, 0xA6, - 0xF2, 0xD3, 0x88, 0x56, 0xF9, 0xD1, 0xEB, 0xBF, 0x08, 0xB2, 0xFB, 0x61, - 0x82, 0x7B, 0x3B, 0x03, 0xBA, 0x95, 0x80, 0x20, 0x58, 0xC5, 0x5A, 0x3A, - 0xB6, 0xEA, 0xB9, 0xB9, 0x15, 0xA2, 0x2A, 0xB4, 0xD1, 0x12, 0xB4, 0x6D, - 0x44, 0xCC, 0xC4, 0xFA, 0x04, 0x89, 0x46, 0xDB, 0xBA, 0xD3, 0xED, 0x72, - 0xE2, 0x23, 0xFA, 0xE3, 0x4F, 0x9E, 0xEE, 0xF0, 0x40, 0xE2, 0xA9, 0xE3, - 0x3C, 0x68, 0xF2, 0xF4, 0x28, 0x78, 0x30, 0x4F, 0x7F, 0xBE, 0x35, 0x89, - 0xAA, 0x2C, 0x4D, 0x17, 0x9B, 0x9D, 0xD2, 0x34, 0x95, 0x32, 0x18, 0x48, - 0x0D, 0x13, 0xD4, 0x80, 0x24, 0xD5, 0x40, 0xB3, 0x59, 0x49, 0x65, 0x69, - 0x98, 0xD8, 0xBE, 0xAE, 0x4C, 0x05, 0x40, 0x06, 0x89, 0x9C, 0xB1, 0x75, - 0x23, 0xE7, 0x4C, 0x0A, 0xC9, 0x38, 0x33, 0x07, 0x34, 0x8D, 0xF7, 0x9E, - 0x0F, 0x68, 0x4B, 0x12, 0x7F, 0xF2, 0x85, 0xB6, 0x26, 0xCB, 0xBC, 0xF7, - 0x79, 0x97, 0x07, 0x6B, 0x42, 0x3D, 0x25, 0x2A, 0xCB, 0x12, 0x1A, 0x53, - 0x9A, 0xA5, 0x52, 0x8E, 0xC0, 0x1A, 0x9A, 0x62, 0x46, 0x92, 0x66, 0x64, - 0xB9, 0x92, 0x24, 0xF2, 0x25, 0x14, 0xE5, 0x15, 0xBE, 0x27, 0x39, 0x07, - 0xA2, 0xDB, 0xB2, 0x42, 0xD1, 0xF8, 0x0A, 0x2D, 0x40, 0x73, 0x63, 0x73, - 0xD1, 0xB0, 0xE4, 0xF9, 0xE6, 0xDD, 0xED, 0xD5, 0x27, 0x5A, 0xCB, 0x5D, - 0x0B, 0xAD, 0x4C, 0x93, 0x02, 0xA5, 0xE9, 0x18, 0x6D, 0x44, 0xB2, 0x7E, - 0x66, 0xB0, 0xA8, 0x28, 0x8A, 0xD1, 0x97, 0x40, 0xE1, 0x44, 0x77, 0xC2, - 0x75, 0xA7, 0x6B, 0xAE, 0xEB, 0x0A, 0xF5, 0x0C, 0xAF, 0x5C, 0xAA, 0x38, - 0x84, 0x20, 0x53, 0xE9, 0x71, 0xE2, 0xA5, 0x40, 0x5C, 0x59, 0xB8, 0x85, - 0x88, 0x82, 0x4C, 0x3B, 0x7A, 0xE6, 0x78, 0x51, 0xE7, 0x9B, 0x51, 0x68, - 0x20, 0x69, 0x6A, 0xD8, 0xE7, 0x58, 0x16, 0x8A, 0xD2, 0xAB, 0x48, 0xD1, - 0x0D, 0x48, 0xEF, 0x49, 0x2D, 0xCE, 0x12, 0x6E, 0x97, 0x0A, 0x3A, 0x04, - 0x3B, 0x5B, 0xBA, 0x7F, 0x27, 0x26, 0x2A, 0x2A, 0x92, 0x0E, 0xC6, 0x2B, - 0x0A, 0x0C, 0xDD, 0x74, 0x2C, 0x4E, 0x9C, 0xAC, 0x48, 0x77, 0x11, 0xC1, - 0x9C, 0x38, 0x55, 0x60, 0x0F, 0x8D, 0xC9, 0x1C, 0x76, 0x7C, 0x12, 0x19, - 0x67, 0xB2, 0x60, 0x7C, 0x07, 0x83, 0x80, 0x13, 0xFF, 0xFE, 0x78, 0x4B, - 0x07, 0x54, 0x86, 0x31, 0x42, 0xA5, 0x5B, 0xD8, 0x5F, 0x70, 0x62, 0x6B, - 0x79, 0xF5, 0x1C, 0xB2, 0xF4, 0x41, 0x14, 0x44, 0xC1, 0x84, 0x2C, 0xD4, - 0xED, 0xCF, 0x81, 0xDE, 0x16, 0x5A, 0x87, 0x4A, 0x3C, 0x90, 0xE3, 0x30, - 0xCA, 0x39, 0xA7, 0xE2, 0x36, 0x02, 0x52, 0xCF, 0x31, 0x3B, 0x1B, 0x18, - 0xC8, 0xB6, 0x0A, 0x24, 0xAE, 0xCE, 0x64, 0x4A, 0x3D, 0xFA, 0x75, 0xA8, - 0x82, 0x25, 0xEA, 0x64, 0x09, 0x41, 0x37, 0x75, 0x6C, 0x8E, 0x20, 0xDC, - 0xC1, 0x0E, 0xD1, 0x11, 0xF1, 0x9F, 0x52, 0xC2, 0x08, 0xAB, 0x59, 0xD2, - 0xCF, 0xA4, 0x2C, 0xA2, 0x36, 0x41, 0xDB, 0x23, 0x29, 0x73, 0x04, 0xB6, - 0xE9, 0x8B, 0x38, 0x8A, 0xB2, 0xA2, 0x41, 0xBD, 0x84, 0xD0, 0xC2, 0xAE, - 0xB3, 0x09, 0xC1, 0x02, 0xB6, 0x35, 0x5D, 0xF1, 0x7B, 0x9A, 0x7C, 0x78, - 0xAF, 0xD4, 0x9A, 0x88, 0x4C, 0x0D, 0x50, 0x34, 0x1C, 0x93, 0x97, 0x47, - 0x3E, 0x9A, 0x72, 0x3B, 0x81, 0xDD, 0xF7, 0x47, 0xD2, 0x64, 0x9C, 0xA1, - 0x05, 0x53, 0x2D, 0x75, 0x9E, 0x42, 0x3D, 0xFC, 0xFC, 0x17, 0xFF, 0x01, - 0xDC, 0xF1, 0x18, 0xD3}; -const uint8_t g_esES_Locale[] = { - 0x78, 0x9C, 0x9D, 0x56, 0xCF, 0x6B, 0xD4, 0x40, 0x14, 0xBE, 0x0B, 0xFE, - 0x0F, 0x21, 0x58, 0x56, 0xA1, 0xDD, 0xD1, 0x63, 0xCB, 0x36, 0x50, 0xDA, - 0xDA, 0x95, 0x1A, 0x59, 0x9A, 0xAA, 0xD8, 0x8B, 0x4C, 0x92, 0xE9, 0xEE, - 0xB4, 0xC9, 0xCC, 0x32, 0x49, 0x2C, 0x9B, 0xA3, 0xE0, 0x41, 0x10, 0x0B, - 0xDE, 0x8A, 0x27, 0x0F, 0x1E, 0x04, 0x8B, 0x77, 0x51, 0x3C, 0xF4, 0x3F, - 0x11, 0x6A, 0xEB, 0xC9, 0x7F, 0xC1, 0x37, 0x9B, 0x49, 0x36, 0x3F, 0x66, - 0xD7, 0x60, 0x4E, 0xF3, 0xBE, 0xF7, 0x7D, 0x2F, 0xEF, 0x7D, 0x93, 0x4C, - 0xD2, 0x0B, 0xB8, 0x87, 0x03, 0x62, 0x30, 0x1C, 0x92, 0x75, 0x93, 0x44, - 0xCF, 0xB7, 0x1D, 0xD3, 0xF0, 0x49, 0xE4, 0xAD, 0x9B, 0xD7, 0x1F, 0x7F, - 0x5C, 0x9D, 0x9E, 0x5F, 0xBD, 0x3E, 0xBB, 0xFE, 0x72, 0x7E, 0xBB, 0x08, - 0xFE, 0x7C, 0x7B, 0x73, 0xF9, 0xFE, 0xFB, 0xEF, 0xB3, 0x57, 0xBF, 0xDE, - 0xBE, 0xBB, 0xFC, 0x7A, 0x7A, 0xC7, 0xB4, 0x7A, 0xB2, 0x00, 0xF3, 0xB1, - 0x70, 0x26, 0xA1, 0xCB, 0x83, 0x48, 0xD5, 0x1A, 0x0A, 0x32, 0xE4, 0x82, - 0x62, 0x06, 0x8C, 0x90, 0xB3, 0x78, 0xF4, 0x08, 0xE0, 0x48, 0xAD, 0x2D, - 0xC2, 0x88, 0xE0, 0x3D, 0x94, 0x05, 0x37, 0x6F, 0x28, 0xF4, 0x90, 0xB8, - 0x42, 0x87, 0x87, 0x58, 0xA4, 0x4D, 0x14, 0xBB, 0x82, 0x06, 0x1A, 0xEE, - 0xA4, 0x49, 0x3D, 0x4A, 0x18, 0xD5, 0xA1, 0x81, 0x06, 0xC5, 0x43, 0x1E, - 0xC5, 0x4D, 0x38, 0x22, 0xE3, 0x98, 0x92, 0x10, 0x1A, 0x6C, 0xA4, 0xB8, - 0x17, 0x27, 0x3A, 0x9C, 0xF1, 0x17, 0x73, 0x14, 0x3E, 0xF5, 0x1A, 0x19, - 0x54, 0x72, 0x29, 0x27, 0x4E, 0x23, 0x03, 0xBB, 0xAE, 0x58, 0x37, 0xEF, - 0x99, 0x25, 0xF3, 0x74, 0xD6, 0xE9, 0x6C, 0xD3, 0x99, 0xA6, 0xB3, 0x4C, - 0xE7, 0x98, 0xCE, 0x2F, 0x9D, 0x5B, 0x3A, 0xAB, 0x74, 0x1E, 0xE9, 0xFC, - 0xD1, 0x39, 0x33, 0xDF, 0x13, 0x1F, 0x4F, 0xD4, 0x53, 0x04, 0x2B, 0xCB, - 0xE7, 0x21, 0x65, 0xF2, 0xF6, 0x32, 0xC8, 0xB2, 0x56, 0x90, 0x30, 0x12, - 0x55, 0x10, 0x30, 0x21, 0xAE, 0x43, 0xF4, 0xE2, 0x93, 0xF0, 0x78, 0x50, - 0x83, 0x8F, 0x12, 0xF2, 0xA2, 0x06, 0xC1, 0xFE, 0x89, 0x7A, 0xC1, 0xE8, - 0xE2, 0x83, 0x8B, 0xFD, 0xD9, 0x6D, 0x51, 0xD1, 0x55, 0xA9, 0xC3, 0xD2, - 0x9E, 0xA9, 0x56, 0xEB, 0x6D, 0xD6, 0x9B, 0x6C, 0x74, 0x58, 0xEF, 0xAD, - 0xDE, 0x58, 0xA3, 0x29, 0x7D, 0x47, 0x21, 0x11, 0xD4, 0x87, 0x87, 0x2D, - 0x7F, 0xFD, 0x54, 0x68, 0x6D, 0xD8, 0xE0, 0x6E, 0x1E, 0x94, 0x78, 0xD6, - 0xA0, 0x96, 0x40, 0xD5, 0x0A, 0x80, 0x10, 0x81, 0x55, 0x35, 0x58, 0x59, - 0xB8, 0xBB, 0xD9, 0xED, 0x21, 0xB9, 0xCA, 0x52, 0x96, 0x5F, 0x06, 0x50, - 0x41, 0x96, 0x41, 0xED, 0xA8, 0xC8, 0xBA, 0x8F, 0xC9, 0x00, 0xC7, 0x31, - 0x18, 0x3D, 0xDD, 0xD7, 0x22, 0x52, 0xE7, 0xC8, 0x61, 0x12, 0x04, 0xA6, - 0xB5, 0x0D, 0x97, 0xB1, 0xD5, 0x81, 0xA3, 0xC9, 0xE8, 0xD8, 0x70, 0x65, - 0xAB, 0x67, 0x70, 0xC9, 0x69, 0x0B, 0x4D, 0xAD, 0xA0, 0x2A, 0x11, 0x70, - 0x36, 0x34, 0xAD, 0xFF, 0x55, 0x87, 0xC4, 0x07, 0xF1, 0x16, 0xB2, 0x6D, - 0xD4, 0x52, 0x11, 0x8D, 0xB8, 0x88, 0x67, 0x9A, 0x86, 0x02, 0x55, 0x66, - 0x06, 0x20, 0xA6, 0x61, 0xC9, 0x83, 0x52, 0x54, 0xF1, 0xA0, 0xDF, 0xEF, - 0xF4, 0xA1, 0xFD, 0x0E, 0x5C, 0x0E, 0x9C, 0xD2, 0x07, 0x3D, 0x54, 0x62, - 0xD6, 0xCA, 0x54, 0x26, 0xEF, 0xF7, 0xD7, 0x6C, 0x7B, 0xCD, 0x71, 0x5A, - 0x49, 0xA6, 0xE3, 0x2A, 0x41, 0x0B, 0xBA, 0x9A, 0x55, 0x0A, 0x1A, 0x6C, - 0x54, 0x99, 0x4B, 0x59, 0xB5, 0x0F, 0x58, 0xBE, 0xFD, 0x3B, 0x89, 0x1D, - 0x1F, 0x8F, 0xC2, 0xC8, 0xD9, 0xDE, 0xBA, 0x7F, 0xF2, 0x14, 0x8F, 0x76, - 0xD3, 0x83, 0xCC, 0x9C, 0x32, 0x09, 0x74, 0x2C, 0x09, 0x5D, 0x22, 0x66, - 0x0E, 0x55, 0x62, 0xD5, 0x08, 0x60, 0xF0, 0x9C, 0x7A, 0xA6, 0x95, 0x2E, - 0xA7, 0xE9, 0x6A, 0x37, 0x4D, 0xD3, 0x1E, 0xAA, 0xF0, 0x1A, 0x85, 0x94, - 0xD0, 0x4B, 0x84, 0x20, 0xCC, 0x9B, 0xE4, 0xCA, 0xD5, 0x55, 0xE3, 0x56, - 0x4B, 0xE9, 0x98, 0x08, 0x8F, 0xB0, 0x58, 0x29, 0x97, 0x34, 0x2A, 0x54, - 0x6B, 0xBD, 0x28, 0x94, 0x4F, 0x57, 0x09, 0x55, 0x59, 0x9F, 0x78, 0x34, - 0xC4, 0xB0, 0xE3, 0xCB, 0xB9, 0x3E, 0x4B, 0xD7, 0xD5, 0xC5, 0x97, 0x96, - 0x27, 0x63, 0x2A, 0x37, 0xBA, 0xDB, 0x8A, 0x5F, 0x74, 0xBD, 0xD4, 0x8A, - 0x0E, 0x87, 0x6C, 0x12, 0x99, 0xD6, 0x4A, 0x2B, 0x72, 0x0A, 0x9F, 0x6F, - 0xD3, 0xBA, 0xDB, 0xE4, 0xA2, 0xEA, 0xD8, 0x80, 0xE4, 0xBE, 0x17, 0x4E, - 0x54, 0x81, 0xFC, 0xF9, 0x9A, 0x06, 0xA6, 0xF5, 0xF3, 0xE5, 0x67, 0x38, - 0x3E, 0x2A, 0x8C, 0x66, 0x11, 0xA5, 0xA1, 0x11, 0x97, 0x0B, 0x38, 0x35, - 0x1E, 0xEF, 0xB5, 0x16, 0x95, 0x4D, 0x6F, 0x4A, 0x50, 0xBD, 0x5B, 0xF9, - 0x32, 0x4C, 0xC6, 0xE4, 0x10, 0x7B, 0xF2, 0x1C, 0xCC, 0x97, 0xAA, 0x96, - 0x3D, 0x81, 0x1F, 0x1F, 0xDF, 0x18, 0x80, 0x17, 0xA8, 0xCC, 0xCC, 0xD3, - 0x14, 0xFE, 0x46, 0xD8, 0xDC, 0xF4, 0x26, 0x4F, 0x04, 0x7C, 0x77, 0x0C, - 0x27, 0xF6, 0xB5, 0xF9, 0x0D, 0x9F, 0xBB, 0xC4, 0x18, 0xD0, 0x7F, 0x10, - 0xFA, 0xF2, 0x67, 0xEA, 0x64, 0x01, 0x61, 0x43, 0x60, 0x17, 0x5E, 0x98, - 0xF9, 0x84, 0xFD, 0x11, 0xA6, 0xDA, 0xF4, 0x2E, 0x4F, 0x93, 0x63, 0x6C, - 0xEC, 0xF0, 0x78, 0x44, 0x3D, 0x39, 0xC7, 0xCA, 0x93, 0x07, 0x86, 0xBD, - 0x88, 0x0A, 0x23, 0x7B, 0x23, 0x9E, 0x53, 0xF7, 0x16, 0xDC, 0x14, 0x98, - 0x43, 0x39, 0x99, 0xF1, 0x70, 0x01, 0xC9, 0xE1, 0x2D, 0x48, 0xF6, 0x24, - 0x61, 0xC3, 0x23, 0x3E, 0xE5, 0xA9, 0xE6, 0xD0, 0x6C, 0xCF, 0x64, 0x94, - 0xFD, 0xFC, 0xC2, 0xF2, 0x2F, 0x7C, 0xDC, 0xCC, 0x2F, -}; -const uint8_t g_esLA_Locale[] = { - 0x78, 0x9C, 0x9D, 0x56, 0xCD, 0x4E, 0xDC, 0x30, 0x10, 0x3E, 0x53, 0xA9, - 0xEF, 0x60, 0x45, 0x45, 0x80, 0x04, 0x9B, 0xF6, 0xB8, 0x28, 0x44, 0x5A, - 0x01, 0xA5, 0x15, 0x0D, 0x5A, 0x75, 0x51, 0x4B, 0xB9, 0x54, 0x4E, 0x62, - 0x36, 0x86, 0xC4, 0x5E, 0x39, 0x09, 0x68, 0xA3, 0xBE, 0x40, 0x4F, 0x3D, - 0xF4, 0xD4, 0x63, 0x2B, 0x21, 0xB5, 0x07, 0xD4, 0x47, 0xE8, 0x81, 0x67, - 0x41, 0xF0, 0x18, 0x9D, 0xFC, 0x6E, 0x12, 0x3B, 0xE9, 0xD2, 0x9C, 0x3C, - 0xDF, 0x7C, 0x9F, 0x77, 0xE6, 0xB3, 0x33, 0x1B, 0xC3, 0xE7, 0x0E, 0xF6, - 0x09, 0x62, 0x38, 0x20, 0x3B, 0x1A, 0x09, 0x3F, 0x5A, 0x27, 0x1A, 0x72, - 0x49, 0xE8, 0xEC, 0x68, 0x0F, 0xD7, 0x7F, 0xEE, 0xBF, 0xDC, 0xDC, 0x7F, - 0xFE, 0xF6, 0xF0, 0xFB, 0x66, 0xFD, 0xEE, 0xC7, 0x4F, 0x88, 0xEF, 0xBE, - 0x5E, 0x6F, 0x68, 0xE6, 0xD3, 0x27, 0x08, 0x19, 0xA9, 0x8A, 0xB9, 0x58, - 0x4C, 0xE6, 0x81, 0xCD, 0xFD, 0xB0, 0xD8, 0x60, 0x2A, 0xC8, 0x94, 0x0B, - 0x8A, 0x59, 0xCA, 0x5A, 0x41, 0x46, 0xC0, 0x59, 0xE4, 0x1D, 0x41, 0x2A, - 0x4C, 0xE3, 0x95, 0x3C, 0x36, 0x09, 0x23, 0x82, 0x1B, 0x7A, 0x1E, 0xD4, - 0xF0, 0x33, 0x62, 0x0B, 0x75, 0x26, 0xC0, 0x22, 0x51, 0xE1, 0xD8, 0x16, - 0xD4, 0x57, 0xF2, 0xE7, 0x2A, 0xFA, 0x79, 0xCC, 0xA8, 0x1A, 0xF7, 0x95, - 0x38, 0x9E, 0xF2, 0x30, 0x52, 0x25, 0x42, 0x32, 0x8B, 0x28, 0x09, 0xA0, - 0x5C, 0x45, 0x92, 0x3B, 0x51, 0xAC, 0xCE, 0x30, 0x7E, 0xD9, 0xA9, 0x72, - 0xA9, 0x23, 0xE5, 0x50, 0xB1, 0xAE, 0x1C, 0xAC, 0x3B, 0x8A, 0xB0, 0x6D, - 0x8B, 0x1D, 0xED, 0x85, 0xD6, 0xB2, 0x56, 0x6D, 0xAC, 0xDA, 0x54, 0xB5, - 0xA5, 0x6A, 0x43, 0xD5, 0x7E, 0xAA, 0xDD, 0x54, 0x7B, 0xA9, 0x36, 0x52, - 0xED, 0xA0, 0xDA, 0x3D, 0xB5, 0x6F, 0xFD, 0x8E, 0xB9, 0x78, 0x5E, 0xBB, - 0x81, 0x10, 0x99, 0x2E, 0x0F, 0x28, 0x4B, 0xCB, 0x49, 0x83, 0x0A, 0xF5, - 0x63, 0x46, 0xC2, 0x16, 0x06, 0x16, 0x45, 0x32, 0x48, 0x6F, 0x7F, 0x09, - 0x87, 0xFB, 0x52, 0xE2, 0x3C, 0x26, 0x97, 0x12, 0x08, 0x27, 0x2E, 0xE4, - 0x8D, 0xC3, 0xDB, 0xEF, 0x36, 0x76, 0x17, 0x25, 0xA0, 0x6C, 0xA5, 0xA8, - 0xBA, 0x75, 0xCA, 0x45, 0xF9, 0x72, 0xE9, 0x72, 0xE1, 0x8A, 0xAA, 0xE5, - 0x7A, 0xE5, 0x62, 0x15, 0x85, 0x76, 0x57, 0x19, 0x10, 0x41, 0x5D, 0xB8, - 0xB6, 0xF5, 0x57, 0xBC, 0x80, 0xCC, 0x91, 0x05, 0x67, 0x51, 0x06, 0xCD, - 0xD4, 0xB8, 0x95, 0x42, 0x8B, 0xB0, 0xB6, 0x39, 0x11, 0xB8, 0xB6, 0x2F, - 0x44, 0x26, 0x1E, 0xEC, 0x0E, 0x0C, 0x3D, 0x5D, 0x55, 0x90, 0x5B, 0x87, - 0x50, 0xB6, 0x2A, 0x45, 0x30, 0xA5, 0xF4, 0xD6, 0x98, 0xCA, 0x51, 0x17, - 0x47, 0x64, 0x8C, 0xA3, 0x08, 0x0E, 0xA6, 0x72, 0xBB, 0x42, 0x8A, 0x49, - 0x76, 0x16, 0xFB, 0xBE, 0x66, 0xEE, 0xC3, 0x83, 0xF6, 0xD6, 0x60, 0x22, - 0xA2, 0x35, 0x0B, 0x9E, 0x7C, 0xF5, 0x01, 0x9E, 0xD4, 0x89, 0x4A, 0xD3, - 0xB5, 0x89, 0xCF, 0xD9, 0x54, 0x33, 0xFF, 0x5F, 0x1F, 0x10, 0x17, 0xE4, - 0x7B, 0xBA, 0x65, 0xE9, 0x4B, 0x6B, 0x42, 0x8F, 0x8B, 0x68, 0xA1, 0x6A, - 0x6B, 0x10, 0x6A, 0x20, 0x85, 0x23, 0x11, 0x0D, 0x5A, 0x8E, 0xD4, 0x90, - 0x86, 0x23, 0x9E, 0xB7, 0x6D, 0x59, 0xDB, 0x93, 0x09, 0x1A, 0xA1, 0x53, - 0x43, 0xAF, 0xB1, 0xBA, 0x64, 0xB9, 0x07, 0x8F, 0x96, 0x65, 0xAD, 0x2F, - 0x54, 0x4B, 0x69, 0x8A, 0xD6, 0x33, 0x95, 0x2C, 0x49, 0x3B, 0x6F, 0xF5, - 0x59, 0xDC, 0x85, 0x63, 0x40, 0xCB, 0x0B, 0x72, 0x10, 0x5B, 0xD1, 0x85, - 0x17, 0x84, 0x93, 0xFD, 0xBD, 0x97, 0x57, 0xEF, 0xB1, 0x77, 0x98, 0x9C, - 0xE6, 0x86, 0xD5, 0x49, 0x99, 0x92, 0xC5, 0x81, 0x4D, 0x44, 0xD3, 0xB5, - 0x06, 0x56, 0x54, 0x05, 0x18, 0xDC, 0x6D, 0x47, 0x33, 0x93, 0xCD, 0x24, - 0x19, 0x0E, 0x92, 0x24, 0x31, 0xF4, 0x06, 0xAF, 0x5B, 0xEA, 0xC4, 0x42, - 0x10, 0xE6, 0xCC, 0x35, 0xF3, 0x59, 0x2E, 0x1E, 0x0E, 0x3F, 0xAD, 0x57, - 0xCB, 0x8D, 0xA5, 0xF7, 0x99, 0x11, 0xE1, 0x10, 0x16, 0x15, 0x25, 0xAC, - 0xCA, 0xBA, 0xD4, 0x1B, 0xA9, 0x9F, 0xAA, 0xC7, 0x45, 0xDB, 0x2B, 0x4D, - 0xA8, 0xD8, 0xDE, 0x25, 0x0E, 0x0D, 0x30, 0x5C, 0x8E, 0x41, 0xB9, 0x4B, - 0x9E, 0xEE, 0x14, 0x4C, 0x05, 0x8F, 0x67, 0x34, 0xBD, 0x17, 0x9B, 0x4B, - 0x2A, 0xAA, 0x0E, 0x56, 0x97, 0x14, 0xC0, 0x84, 0x8F, 0x43, 0xCD, 0xDC, - 0x5A, 0x92, 0x9E, 0xC0, 0x77, 0x87, 0x66, 0x3E, 0x97, 0xD8, 0x0B, 0x63, - 0x1A, 0x67, 0x5F, 0x1E, 0x4C, 0xC3, 0x99, 0x26, 0x58, 0xDE, 0xC9, 0x2C, - 0x80, 0x03, 0x84, 0x59, 0xD4, 0xC8, 0xF7, 0x68, 0x68, 0xC8, 0xD3, 0x85, - 0x66, 0x5A, 0x27, 0x47, 0x8F, 0x90, 0xD5, 0x8F, 0x41, 0x12, 0x65, 0xC3, - 0x50, 0xAA, 0x3A, 0x7D, 0xF5, 0xE7, 0x33, 0x72, 0x86, 0x9D, 0x72, 0xE8, - 0x96, 0x61, 0xB1, 0xA7, 0x35, 0x87, 0xAF, 0x39, 0x17, 0x8D, 0xC1, 0x1D, - 0x5D, 0x4D, 0xA0, 0xF0, 0x49, 0xC5, 0x7A, 0x08, 0xBB, 0x3C, 0x16, 0xF0, - 0x17, 0x88, 0x26, 0x91, 0xDB, 0xC1, 0x18, 0xB9, 0xDC, 0x26, 0x68, 0x4C, - 0xFF, 0x49, 0x79, 0x95, 0x7E, 0x1F, 0x5E, 0xF5, 0x52, 0x46, 0x02, 0xDB, - 0xF0, 0xAE, 0xF5, 0x51, 0x8E, 0x3D, 0x4C, 0x3B, 0x08, 0x87, 0x3C, 0x89, - 0x2F, 0x30, 0x3A, 0xE0, 0x91, 0x47, 0x9D, 0xB4, 0xA7, 0xAD, 0x77, 0xAF, - 0x91, 0xD5, 0x4F, 0x06, 0x03, 0x1C, 0x8F, 0x97, 0xE4, 0xB7, 0xBD, 0x3F, - 0x0D, 0xDC, 0x69, 0xDA, 0x25, 0x7A, 0xD3, 0x4B, 0x9B, 0xF0, 0xA5, 0x68, - 0xD6, 0x3C, 0x66, 0xD3, 0x73, 0x9E, 0x31, 0xF3, 0x22, 0xB3, 0x11, 0x57, - 0x3B, 0x4F, 0x43, 0xCF, 0x3F, 0xEF, 0xCD, 0xBF, 0xC4, 0xB5, 0xD4, 0x04}; -const uint8_t g_deDE_Loacale[] = { - 0x78, 0x9C, 0x95, 0x56, 0x4D, 0x6F, 0xD4, 0x30, 0x10, 0xBD, 0x23, 0xF1, - 0x1F, 0xAC, 0x88, 0xAA, 0x20, 0xB5, 0x1B, 0x38, 0xB6, 0xDA, 0x46, 0x5A, - 0x75, 0xFB, 0x41, 0x4B, 0xCA, 0xAA, 0x69, 0x41, 0xF4, 0x82, 0xBC, 0x89, - 0xBB, 0x71, 0x9B, 0xD8, 0x2B, 0xC7, 0x69, 0xB5, 0x39, 0xF2, 0x37, 0xB8, - 0x72, 0x04, 0x71, 0xE4, 0x04, 0x17, 0xFE, 0x09, 0x52, 0x25, 0x7E, 0x06, - 0x93, 0x8D, 0x93, 0x26, 0xB6, 0xBB, 0x0D, 0xB9, 0xAC, 0xE7, 0xCD, 0x7B, - 0xB3, 0x33, 0xCF, 0x89, 0x93, 0x61, 0xC2, 0x43, 0x9C, 0x10, 0xC4, 0x70, - 0x4A, 0x76, 0x9C, 0x88, 0x7C, 0x1C, 0xEF, 0x39, 0x28, 0x22, 0x59, 0xB8, - 0xE3, 0xDC, 0xFD, 0xFA, 0xF1, 0xF7, 0xFB, 0xB7, 0xE7, 0xF0, 0x73, 0xF7, - 0xF9, 0xE7, 0x0B, 0xC7, 0x1B, 0x96, 0x44, 0x16, 0x61, 0x11, 0x2C, 0xD2, - 0x29, 0x4F, 0x32, 0xA5, 0x99, 0x09, 0x32, 0xE3, 0x82, 0x62, 0x06, 0x8C, - 0x94, 0x33, 0x19, 0x9F, 0x00, 0x9C, 0xA9, 0xB5, 0x77, 0x84, 0x59, 0x8E, - 0xC5, 0xD0, 0xAD, 0xA2, 0xA7, 0x4F, 0x14, 0xBC, 0x4F, 0xA6, 0xC2, 0x86, - 0xFB, 0xBF, 0xBF, 0x88, 0xC2, 0x40, 0x47, 0x73, 0x41, 0x13, 0x93, 0x8B, - 0xA9, 0x81, 0x1D, 0xE5, 0xCC, 0x06, 0x26, 0x26, 0x38, 0xCA, 0x67, 0x79, - 0x26, 0x0D, 0x38, 0x20, 0x73, 0x49, 0xD2, 0x29, 0x31, 0x5B, 0x7B, 0x7B, - 0x2D, 0xB9, 0x0D, 0x3F, 0xE1, 0x37, 0x76, 0xC1, 0x98, 0x14, 0x7A, 0xC2, - 0x6D, 0x19, 0x54, 0xF3, 0x96, 0x11, 0xC2, 0xD3, 0xA9, 0xD8, 0x71, 0x5E, - 0x39, 0x2D, 0xDF, 0x6C, 0xA6, 0x99, 0x26, 0xD8, 0xED, 0xEA, 0x6B, 0x96, - 0xCD, 0x2B, 0x9B, 0x55, 0x36, 0x9F, 0x6C, 0x0E, 0xD9, 0xDC, 0xB1, 0x19, - 0xF3, 0xB0, 0x27, 0x11, 0x5E, 0xA8, 0x1B, 0x08, 0x56, 0x5E, 0xC0, 0x19, - 0x93, 0x18, 0xFE, 0xBE, 0x0C, 0xAA, 0xAC, 0xE7, 0x73, 0x03, 0x1A, 0x53, - 0xC2, 0x32, 0x83, 0x47, 0xA5, 0xBC, 0xE5, 0x61, 0xDC, 0x65, 0x42, 0x41, - 0x22, 0x0C, 0xEE, 0xBE, 0x20, 0x54, 0xC7, 0x02, 0x9C, 0x76, 0x78, 0x6E, - 0xD3, 0x5A, 0xAB, 0xCD, 0xD6, 0xC6, 0x55, 0xFD, 0x6A, 0xAD, 0x6A, 0x6D, - 0x6A, 0x0D, 0x6A, 0xAD, 0x69, 0x2D, 0x69, 0xDD, 0xD8, 0x1B, 0x49, 0x89, - 0xA0, 0x11, 0x25, 0x69, 0xFD, 0xD4, 0xA9, 0xD0, 0x1B, 0xF9, 0xE0, 0x6C, - 0x1D, 0xB4, 0x78, 0xDE, 0x44, 0x4B, 0xB8, 0xDD, 0x0A, 0x80, 0x10, 0x81, - 0x55, 0x35, 0x58, 0x79, 0x37, 0x03, 0xB4, 0x1B, 0x8B, 0xC1, 0xD0, 0x2D, - 0x83, 0x2A, 0xEB, 0x31, 0x0D, 0x73, 0x1B, 0x49, 0x19, 0x68, 0xE7, 0x44, - 0x35, 0x81, 0x24, 0x13, 0x2C, 0x25, 0x11, 0x6C, 0xB9, 0xB3, 0x4D, 0xA4, - 0x0E, 0x91, 0xCB, 0x3C, 0x49, 0x1C, 0x6F, 0x0F, 0xAE, 0x0D, 0x34, 0x1E, - 0x20, 0x1F, 0x2E, 0xF4, 0x01, 0xAE, 0x72, 0xD6, 0x86, 0xAB, 0x15, 0x52, - 0xD2, 0x84, 0xB3, 0x99, 0xE3, 0xFD, 0xA7, 0x28, 0x25, 0x11, 0x68, 0xC6, - 0x03, 0xDF, 0x1F, 0xF4, 0x54, 0x64, 0x31, 0x17, 0xF2, 0x5E, 0x63, 0x28, - 0xDC, 0xCE, 0x88, 0x00, 0x48, 0x9A, 0xB6, 0x46, 0x6E, 0x45, 0x9D, 0x91, - 0x0F, 0xB7, 0x7D, 0x7F, 0x1D, 0x9D, 0xC7, 0x02, 0xAD, 0x5F, 0x0C, 0xDD, - 0x16, 0x4B, 0x2B, 0xD1, 0x19, 0xF6, 0xB0, 0x54, 0x6D, 0x07, 0x01, 0xEA, - 0x23, 0x59, 0x8E, 0x5A, 0x2B, 0x7A, 0xF0, 0xD5, 0xA0, 0x4B, 0x85, 0x41, - 0x77, 0x3B, 0x53, 0x29, 0xA3, 0xCE, 0x00, 0xAB, 0xF7, 0xFA, 0xE0, 0xCA, - 0x97, 0xD7, 0x87, 0x69, 0x16, 0xEC, 0x8D, 0xF7, 0x6F, 0xDF, 0xE3, 0xF8, - 0xB8, 0xB8, 0xA8, 0xAC, 0x69, 0x93, 0x40, 0xC7, 0xF2, 0xF2, 0x68, 0xBC, - 0xF7, 0xA7, 0x13, 0xAB, 0x4E, 0x00, 0x83, 0x5B, 0x33, 0x74, 0xBC, 0x62, - 0xA3, 0x28, 0xB6, 0x06, 0x45, 0x01, 0xC7, 0x46, 0x87, 0x67, 0x14, 0x52, - 0xC2, 0x30, 0x17, 0x82, 0xB0, 0x70, 0x51, 0x2B, 0xB7, 0xB6, 0xD0, 0xB3, - 0x9E, 0xD2, 0x39, 0x11, 0x21, 0x61, 0x52, 0x29, 0xD7, 0x2C, 0x2A, 0x57, - 0x6B, 0xBD, 0x29, 0x54, 0x4F, 0xD7, 0x09, 0x9B, 0x17, 0x6B, 0x48, 0x53, - 0x0C, 0xFB, 0xBD, 0x51, 0xEB, 0xAB, 0xB4, 0xAE, 0x6E, 0xDE, 0xA9, 0x3C, - 0x9F, 0xD3, 0x72, 0xAB, 0x07, 0xBD, 0xF8, 0x4D, 0xD7, 0x6B, 0xBD, 0xE8, - 0x29, 0x65, 0x79, 0xE6, 0x78, 0x9B, 0xBD, 0xC8, 0x05, 0x11, 0xDC, 0xF1, - 0x5E, 0x9A, 0x5C, 0xB7, 0x3B, 0x36, 0x20, 0xB5, 0xEF, 0x8D, 0x13, 0x5D, - 0xA0, 0xBE, 0xC1, 0x96, 0x81, 0xE3, 0xFD, 0xF9, 0xF4, 0x15, 0xCE, 0x8A, - 0x0E, 0xC3, 0x2C, 0xA2, 0x34, 0x34, 0xE3, 0xE5, 0x02, 0x8E, 0x88, 0xF3, - 0xD3, 0xDE, 0xA2, 0xB6, 0xE9, 0xA6, 0xC4, 0xD5, 0xBB, 0x2D, 0x9F, 0x86, - 0xC5, 0x9C, 0x5C, 0xE2, 0xB0, 0x3C, 0xFA, 0xEA, 0xA5, 0xAA, 0xE5, 0x2F, - 0xE0, 0x13, 0x27, 0x42, 0x13, 0xF0, 0xC2, 0x6D, 0x33, 0xEB, 0x34, 0x65, - 0x94, 0xB3, 0x07, 0xD3, 0xBB, 0x3C, 0x17, 0x94, 0x08, 0x14, 0xC8, 0xC8, - 0x9A, 0x1F, 0x45, 0xF0, 0x69, 0x81, 0x26, 0xF4, 0x11, 0xC2, 0x21, 0x7C, - 0x35, 0x91, 0xDB, 0x15, 0x84, 0x91, 0xC0, 0x53, 0x78, 0x60, 0x1E, 0x26, - 0x9C, 0xC5, 0x98, 0x5A, 0xD3, 0xC7, 0xBC, 0xC8, 0xAF, 0x31, 0x3A, 0xE0, - 0x32, 0xA6, 0x61, 0x39, 0xC7, 0xE6, 0xBB, 0xD7, 0xC8, 0x5F, 0x45, 0x85, - 0x91, 0xC3, 0x98, 0xD7, 0xD4, 0xD3, 0x15, 0x7F, 0x0A, 0xCC, 0x59, 0x39, - 0x19, 0x7A, 0xB3, 0x82, 0x04, 0x6F, 0xFA, 0xC7, 0x49, 0xFE, 0x22, 0x67, - 0xB3, 0x2B, 0xBE, 0xE4, 0xA9, 0xE6, 0xDC, 0xFB, 0x3D, 0x2B, 0xA3, 0xEA, - 0x73, 0x16, 0x96, 0xFF, 0x00, 0x29, 0x27, 0xAF, 0x17, -}; -const uint8_t g_frFR_Locale[] = { - 0x78, 0x9C, 0x95, 0x56, 0x4D, 0x6F, 0xD3, 0x40, 0x10, 0xBD, 0x23, 0xF1, - 0x1F, 0x56, 0x16, 0x55, 0x41, 0x6A, 0xBD, 0x70, 0x4C, 0x95, 0x5A, 0xAA, - 0xFA, 0x15, 0x28, 0x46, 0x51, 0x53, 0x40, 0xF4, 0x82, 0x36, 0xF6, 0x36, - 0xDE, 0xD4, 0xDE, 0x8D, 0xD6, 0x76, 0x4A, 0x7C, 0xE4, 0x3F, 0x70, 0xE2, - 0xC2, 0xB5, 0x12, 0x88, 0x03, 0x47, 0xC4, 0x85, 0xFE, 0x13, 0x24, 0x10, - 0x3F, 0x83, 0x71, 0xBC, 0x76, 0xED, 0x5D, 0x27, 0xB8, 0xBE, 0x64, 0xE7, - 0xCD, 0x7B, 0xE3, 0x99, 0xB7, 0xF6, 0xC6, 0xFD, 0x50, 0x78, 0x24, 0xA4, - 0x88, 0x93, 0x88, 0xEE, 0x5A, 0x17, 0xF2, 0xED, 0xD1, 0xA9, 0x85, 0x7C, - 0x1A, 0x7B, 0xBB, 0xD6, 0x9F, 0x6F, 0x1F, 0xFE, 0x7E, 0xFD, 0xF2, 0x10, - 0x7E, 0x7E, 0x7F, 0xFC, 0xF1, 0xC8, 0x72, 0xFA, 0x39, 0x91, 0xFB, 0x44, - 0x8E, 0x16, 0xD1, 0x58, 0x84, 0xB1, 0xD2, 0x4C, 0x24, 0x9D, 0x08, 0xC9, - 0x08, 0x07, 0x46, 0x24, 0x78, 0x12, 0xBC, 0x00, 0x38, 0x56, 0x6B, 0x67, - 0x4A, 0xF8, 0x9C, 0x51, 0xD9, 0xC7, 0x45, 0x78, 0xFF, 0x9E, 0xC2, 0x2F, - 0x6E, 0xAE, 0xE7, 0xB2, 0x2D, 0x11, 0x11, 0x19, 0x1B, 0x20, 0x01, 0x6E, - 0xD8, 0x42, 0x65, 0x06, 0x36, 0x4D, 0x19, 0x6F, 0x03, 0xC3, 0x90, 0x26, - 0x66, 0x59, 0x71, 0xF3, 0xDD, 0x44, 0x63, 0x3A, 0x4B, 0x68, 0x34, 0x96, - 0xD4, 0xC8, 0x08, 0x2F, 0x11, 0x6D, 0x38, 0x17, 0xF3, 0x76, 0x81, 0x7F, - 0x73, 0xED, 0xE9, 0x19, 0x5C, 0x33, 0xA9, 0x24, 0x2E, 0x23, 0x44, 0xC6, - 0x63, 0xB9, 0x6B, 0x3D, 0xB1, 0xEA, 0xDE, 0xD9, 0xED, 0xCE, 0x99, 0xF0, - 0x2A, 0xDF, 0xDA, 0x98, 0x77, 0xB0, 0xCD, 0x94, 0xAF, 0x36, 0xCD, 0xE4, - 0x82, 0x61, 0x26, 0x08, 0x6E, 0x99, 0x60, 0xEE, 0x94, 0xBD, 0xDA, 0x25, - 0x9F, 0x2C, 0xD4, 0x63, 0x05, 0x2B, 0xC7, 0x67, 0x11, 0xE1, 0x5E, 0x00, - 0xAE, 0xE6, 0x51, 0x91, 0x76, 0xC2, 0x94, 0xFB, 0xAC, 0x81, 0x80, 0x25, - 0x3A, 0x42, 0xA5, 0x27, 0xA9, 0x06, 0x4E, 0x69, 0xAA, 0x21, 0x73, 0x78, - 0xCC, 0x0D, 0x5A, 0x0C, 0xF7, 0xAF, 0x41, 0xB8, 0x6A, 0xA9, 0xD6, 0x5E, - 0x6D, 0x0B, 0x55, 0x9F, 0xB6, 0xDE, 0xA3, 0xAD, 0xB7, 0x68, 0xEB, 0x1D, - 0xDA, 0x7A, 0x77, 0xB6, 0xDE, 0x9C, 0xAD, 0x37, 0x66, 0xB7, 0xB7, 0x05, - 0xC5, 0x98, 0xCF, 0x68, 0x54, 0xBE, 0x91, 0x2A, 0x74, 0xF6, 0x5C, 0xF0, - 0xB7, 0x0C, 0x6A, 0x3C, 0x67, 0xA8, 0x25, 0x70, 0xB3, 0x02, 0x20, 0x54, - 0x12, 0x55, 0x0D, 0x56, 0xF0, 0x7C, 0xD9, 0xE8, 0x99, 0xBD, 0xBD, 0x0F, - 0xF7, 0xCF, 0xC3, 0x22, 0xEF, 0x90, 0x99, 0x8E, 0xE2, 0x4A, 0x96, 0x07, - 0xDA, 0x39, 0x52, 0xCC, 0x91, 0xD0, 0x21, 0x49, 0x12, 0x2A, 0xF9, 0x72, - 0x8F, 0xAB, 0xA8, 0x3C, 0x98, 0xD2, 0x30, 0xB4, 0x9C, 0x43, 0xB8, 0xD0, - 0x01, 0x72, 0xE1, 0x42, 0x6F, 0xE0, 0xCA, 0xA7, 0xAD, 0x98, 0x5A, 0x19, - 0x25, 0x0C, 0x05, 0x9F, 0x58, 0xCE, 0xDD, 0x34, 0xB0, 0xCF, 0x4A, 0x82, - 0x3A, 0xF1, 0xE3, 0x40, 0xC8, 0x04, 0x14, 0x07, 0xD8, 0x75, 0x71, 0x8B, - 0x02, 0x37, 0xA6, 0x03, 0x20, 0x61, 0x51, 0x6D, 0xDA, 0x5A, 0xD4, 0x98, - 0x76, 0x30, 0xD8, 0x44, 0x01, 0xDA, 0x84, 0x2E, 0xCE, 0xFB, 0xB8, 0x46, - 0xD2, 0x2A, 0x34, 0x06, 0x1D, 0x0C, 0x76, 0x5C, 0x77, 0x67, 0x34, 0xEA, - 0x24, 0x59, 0xCE, 0x59, 0x2A, 0x3A, 0xF0, 0xD5, 0x9C, 0x4B, 0x85, 0x41, - 0xC7, 0x8D, 0xA1, 0x94, 0x4F, 0x67, 0x80, 0x95, 0xBB, 0x7C, 0x4C, 0xDC, - 0xE9, 0xE5, 0x20, 0x8A, 0x47, 0x87, 0x07, 0x47, 0x57, 0xAF, 0xDF, 0x05, - 0x27, 0xD9, 0x79, 0xE1, 0x4C, 0x9D, 0x04, 0x3A, 0x9E, 0x46, 0x63, 0x2A, - 0x6F, 0xED, 0x69, 0xC4, 0xAA, 0x13, 0xC0, 0xE0, 0xC1, 0xF4, 0x2C, 0x27, - 0xDB, 0xCA, 0xB2, 0x9E, 0x9D, 0x65, 0x59, 0x1F, 0x37, 0x78, 0x46, 0x21, - 0x25, 0xF4, 0x52, 0x29, 0x29, 0xF7, 0x16, 0xA5, 0xB2, 0xD7, 0x43, 0x0F, - 0x3A, 0x4A, 0x67, 0x70, 0x76, 0x50, 0x9E, 0x28, 0xE5, 0x46, 0x8B, 0x0A, - 0x6B, 0xAD, 0x57, 0x85, 0xCA, 0xE9, 0x1A, 0xA1, 0x2A, 0xEB, 0x53, 0x0F, - 0x4E, 0x33, 0xD8, 0xEE, 0xAD, 0x52, 0x5F, 0xA4, 0x75, 0x75, 0xF5, 0x6F, - 0x2B, 0xD2, 0x19, 0xCB, 0xB7, 0xFA, 0xE7, 0xA7, 0x4E, 0x82, 0xAA, 0xED, - 0x8D, 0x4E, 0xF4, 0x88, 0xF1, 0x34, 0xB6, 0x9C, 0xED, 0x4E, 0xE4, 0x8C, - 0x4A, 0x61, 0x39, 0x8F, 0x4D, 0x2E, 0x6E, 0xCE, 0x0D, 0x48, 0x69, 0x7C, - 0x65, 0x45, 0x13, 0x28, 0x9F, 0xB0, 0x65, 0x60, 0x39, 0xBF, 0xDE, 0x7F, - 0x86, 0x63, 0xA2, 0xC1, 0x30, 0x8B, 0x28, 0x0D, 0x8B, 0x45, 0xBE, 0x80, - 0xD3, 0xE1, 0xE5, 0x69, 0x67, 0x51, 0xDD, 0x75, 0x53, 0x82, 0xF5, 0x6E, - 0xF3, 0xD7, 0x61, 0x31, 0xA3, 0x17, 0xC4, 0xCB, 0x4F, 0xBE, 0x72, 0xA9, - 0x6A, 0xB9, 0x0B, 0xF8, 0xFA, 0xF1, 0xD1, 0x10, 0xBC, 0xC0, 0x75, 0x66, - 0x99, 0x66, 0x9C, 0x09, 0xBE, 0x32, 0xBD, 0x2F, 0xD2, 0xFC, 0x3B, 0x08, - 0x8D, 0x12, 0xBF, 0x35, 0xBF, 0xE7, 0x8B, 0x31, 0x45, 0x43, 0xF6, 0x1F, - 0xC2, 0x80, 0xC2, 0x57, 0xC6, 0xD5, 0x1A, 0xC2, 0x9E, 0x24, 0x63, 0x78, - 0x63, 0x56, 0x13, 0xCE, 0x02, 0xC2, 0x5A, 0xD3, 0x27, 0x22, 0x4B, 0x2F, - 0x09, 0x3A, 0x16, 0x49, 0xC0, 0xBC, 0x7C, 0x8E, 0xED, 0x57, 0x4F, 0x91, - 0xBB, 0x8E, 0x0A, 0x23, 0x7B, 0x81, 0x28, 0xA9, 0xA7, 0x6B, 0x6E, 0x0A, - 0xCC, 0x49, 0x3E, 0x19, 0x7A, 0xBE, 0x86, 0x34, 0x12, 0x1D, 0x48, 0xEE, - 0x22, 0xE5, 0x93, 0xA9, 0x58, 0xF2, 0x54, 0x73, 0xF8, 0x76, 0xCF, 0xF2, - 0xA8, 0xF8, 0xD2, 0x85, 0xE5, 0x3F, 0x5D, 0x49, 0xBE, 0x1B}; -const uint8_t g_itIT_Locale[] = { - 0x78, 0x9C, 0x95, 0x56, 0xD1, 0x6A, 0xD4, 0x40, 0x14, 0x7D, 0x17, 0xFC, - 0x87, 0x21, 0x58, 0x50, 0x68, 0x3B, 0xFA, 0xD8, 0x92, 0x06, 0x4A, 0x5B, - 0xBB, 0xA5, 0x46, 0x96, 0xEE, 0xAA, 0xD8, 0x17, 0x99, 0x64, 0xA6, 0xD9, - 0xB1, 0xC9, 0xCC, 0x32, 0x49, 0x5A, 0x92, 0x47, 0xF1, 0xC1, 0x37, 0x7F, - 0x42, 0x10, 0x41, 0xF1, 0x23, 0xFC, 0x13, 0xA1, 0xE2, 0x67, 0x78, 0xB3, - 0x99, 0xA4, 0xC9, 0x64, 0xBA, 0xA6, 0x79, 0xD9, 0xB9, 0xE7, 0x9E, 0x73, - 0x73, 0xEF, 0x99, 0x64, 0x36, 0x6E, 0x2C, 0x43, 0x12, 0x33, 0x24, 0x48, - 0xC2, 0xF6, 0x1C, 0x9E, 0xBD, 0x3B, 0x99, 0x3B, 0x88, 0xB2, 0x34, 0xDC, - 0x73, 0xFE, 0x7C, 0xFC, 0x7C, 0xF3, 0xE5, 0xEB, 0xCD, 0xA7, 0x6F, 0x7F, - 0x7F, 0xFE, 0x78, 0xDC, 0x06, 0x4F, 0x1C, 0xCF, 0xAD, 0x14, 0x82, 0x12, - 0x35, 0x2B, 0x92, 0x40, 0xC6, 0xA9, 0x16, 0x47, 0x8A, 0x45, 0x52, 0x71, - 0x22, 0x80, 0x91, 0x48, 0x91, 0x2D, 0x5E, 0x02, 0x9C, 0xEA, 0xB5, 0x17, - 0x31, 0x21, 0x08, 0x97, 0x2E, 0xAE, 0xC3, 0x87, 0x0F, 0x34, 0x7E, 0xC1, - 0x82, 0x40, 0xD9, 0x12, 0x09, 0x51, 0xE5, 0x10, 0x25, 0x4B, 0xC5, 0x63, - 0x66, 0x21, 0x47, 0x91, 0xA5, 0x46, 0xC4, 0xF3, 0x48, 0x0C, 0xE1, 0x38, - 0x8F, 0x62, 0x0B, 0x9B, 0x44, 0x32, 0xCD, 0x86, 0x70, 0xCA, 0xB2, 0x8C, - 0x25, 0x81, 0x1A, 0xDE, 0x55, 0x66, 0x99, 0xB4, 0xE1, 0x42, 0x5E, 0xD9, - 0x05, 0x94, 0x87, 0x66, 0x02, 0x77, 0xAC, 0x6A, 0x78, 0xAB, 0x08, 0x11, - 0x30, 0x66, 0xCF, 0x79, 0xE6, 0x74, 0x1C, 0xB4, 0xB9, 0x67, 0x33, 0xCE, - 0x66, 0x9B, 0xCD, 0x33, 0x9B, 0x61, 0x36, 0xB7, 0x6C, 0x56, 0xD9, 0x7C, - 0xB2, 0x39, 0x64, 0x73, 0xC7, 0x66, 0xCC, 0xDD, 0x9E, 0x50, 0x52, 0xE8, - 0x47, 0x09, 0x56, 0x1E, 0x95, 0x09, 0x13, 0x3C, 0x24, 0x2E, 0xAE, 0xA2, - 0x3A, 0x0D, 0x3D, 0x0A, 0x46, 0x7F, 0x7D, 0xEF, 0x61, 0xE0, 0x43, 0x36, - 0x04, 0x99, 0x0A, 0x65, 0x3C, 0x80, 0xE1, 0xE1, 0xB9, 0x1A, 0x80, 0x57, - 0x4C, 0x30, 0x65, 0x82, 0x29, 0x09, 0x48, 0xF5, 0x90, 0x68, 0x08, 0xB7, - 0xCD, 0x75, 0x1A, 0xED, 0x6C, 0x9D, 0xEE, 0xD8, 0x6C, 0xD6, 0x6C, 0xD4, - 0xEC, 0xD1, 0x6C, 0xCE, 0xEC, 0xCB, 0x6C, 0xC9, 0xDE, 0x0F, 0x14, 0xE2, - 0x94, 0xB3, 0xA4, 0x79, 0x11, 0x75, 0xE8, 0xED, 0xFB, 0x60, 0x71, 0x13, - 0x74, 0x78, 0xDE, 0xD4, 0x48, 0xE0, 0x7E, 0x05, 0x40, 0x98, 0x22, 0xBA, - 0x1A, 0xAC, 0x3C, 0x72, 0xE0, 0xE2, 0xEA, 0xB7, 0x4E, 0x78, 0xF4, 0x36, - 0xC4, 0x2D, 0xB1, 0x0A, 0x8C, 0x03, 0xA3, 0x6E, 0x3C, 0x63, 0x53, 0x02, - 0x6F, 0x96, 0x12, 0xAB, 0x8D, 0x6D, 0x23, 0x7D, 0x9A, 0x5C, 0xE4, 0x71, - 0xEC, 0x78, 0x47, 0x70, 0xA1, 0x43, 0xE4, 0xC3, 0x85, 0xDE, 0xC2, 0x55, - 0xCD, 0xD7, 0x32, 0x8D, 0x32, 0x5A, 0x18, 0x4B, 0x11, 0x39, 0xDE, 0xE1, - 0xFD, 0x44, 0x09, 0xA3, 0x95, 0x06, 0x83, 0x04, 0x8F, 0x12, 0xA4, 0x0B, - 0xA9, 0x32, 0x2D, 0xB1, 0x29, 0x70, 0x6F, 0x3E, 0x00, 0x32, 0x9E, 0x74, - 0xE6, 0xED, 0x44, 0xBD, 0x79, 0x27, 0x93, 0x5D, 0xDF, 0xDF, 0x9D, 0xCD, - 0xD0, 0xB9, 0x8B, 0x3B, 0x1C, 0xA3, 0x40, 0x6F, 0xD2, 0xFB, 0x28, 0x56, - 0x63, 0x36, 0xF7, 0x18, 0xC1, 0xD7, 0x53, 0xAE, 0x14, 0x03, 0x3A, 0xEE, - 0x8D, 0xA4, 0x5D, 0x9A, 0x03, 0xD6, 0xEC, 0xF2, 0x71, 0xE1, 0xD3, 0xCB, - 0x49, 0x92, 0xCE, 0x8E, 0x0E, 0x9F, 0x5F, 0xBF, 0x21, 0x8B, 0xD3, 0xF2, - 0xBC, 0xF6, 0xA5, 0x4B, 0x02, 0x9D, 0xC8, 0x93, 0x80, 0xA9, 0x5B, 0x73, - 0x7A, 0xB1, 0xEE, 0x04, 0x30, 0x78, 0x14, 0x43, 0xC7, 0x2B, 0x37, 0xCB, - 0x72, 0x67, 0xBB, 0x2C, 0x4B, 0x17, 0xF7, 0x78, 0x83, 0x42, 0x5A, 0x18, - 0xE6, 0x4A, 0x31, 0x11, 0x16, 0x8E, 0xF7, 0x08, 0xD5, 0xDA, 0x9D, 0x9D, - 0x91, 0xD2, 0x25, 0x9C, 0x15, 0x4C, 0x64, 0xFA, 0x9E, 0x1B, 0x16, 0x15, - 0x36, 0x5A, 0x6F, 0x0B, 0x35, 0xD3, 0xF5, 0x42, 0x5D, 0x96, 0xB2, 0x90, - 0x27, 0x04, 0x36, 0x7B, 0xB3, 0xD1, 0xD7, 0x69, 0x53, 0xDD, 0xFE, 0xAD, - 0xCA, 0x7C, 0xC9, 0xAB, 0x9D, 0xDE, 0x1E, 0xC5, 0x6F, 0xBB, 0xDE, 0x18, - 0x45, 0x4F, 0xB8, 0xC8, 0x53, 0xC7, 0xDB, 0x1A, 0x45, 0x2E, 0x99, 0x92, - 0x8E, 0xF7, 0x74, 0xC8, 0xC5, 0xFD, 0xB1, 0x01, 0x69, 0x7C, 0x6F, 0x9D, - 0xE8, 0x03, 0xCD, 0x03, 0xB6, 0x0A, 0x1C, 0xEF, 0xF7, 0x07, 0x38, 0x65, - 0xFB, 0x8C, 0x61, 0x91, 0xE6, 0x23, 0x25, 0x95, 0xD5, 0x02, 0x0E, 0x87, - 0x57, 0x67, 0xA3, 0x45, 0x5D, 0xD3, 0x87, 0x12, 0x6C, 0x76, 0x5B, 0xBD, - 0x0D, 0xC5, 0x92, 0x5D, 0x90, 0xB0, 0x3A, 0xEA, 0x9A, 0xA5, 0xAE, 0xE5, - 0x17, 0xF0, 0x95, 0x43, 0xD1, 0x14, 0xBC, 0xC0, 0x5D, 0x66, 0x93, 0xE6, - 0x82, 0x4B, 0x71, 0x67, 0xFA, 0x40, 0xE6, 0x8A, 0x33, 0x85, 0x66, 0x19, - 0xB5, 0xE6, 0xF7, 0xA9, 0x0C, 0x18, 0x9A, 0xF2, 0xFF, 0x10, 0x26, 0x0C, - 0xBE, 0x23, 0xAE, 0xD7, 0x10, 0xF6, 0x15, 0x09, 0xE0, 0x85, 0xB9, 0x9B, - 0x30, 0x5F, 0x10, 0x6E, 0x4D, 0x9F, 0xCA, 0x32, 0xBF, 0x24, 0xE8, 0x58, - 0x66, 0x0B, 0x1E, 0x56, 0x73, 0x6C, 0xBD, 0x3E, 0x41, 0xFE, 0x3A, 0x2A, - 0x8C, 0x1C, 0x2E, 0x64, 0x43, 0x3D, 0x5B, 0x73, 0x53, 0x60, 0x46, 0xD5, - 0x64, 0xE8, 0xC5, 0x1A, 0xD2, 0x4C, 0x8E, 0x20, 0xF9, 0x45, 0x2E, 0xA2, - 0xF7, 0x72, 0xC5, 0xD3, 0xCD, 0xE1, 0xDB, 0x3D, 0xAB, 0xA2, 0xFA, 0xD3, - 0x16, 0x96, 0xFF, 0x00, 0x20, 0x8B, 0xBE, 0xF7}; -const uint8_t g_ptBR_Locale[] = { - 0x78, 0x9C, 0x9D, 0x56, 0x3D, 0x6F, 0xD4, 0x40, 0x10, 0xAD, 0x83, 0xC4, - 0x7F, 0x58, 0x59, 0x89, 0x0E, 0xA4, 0x24, 0x86, 0x92, 0xC8, 0x67, 0xE9, - 0x92, 0x0B, 0x39, 0x94, 0x18, 0x9D, 0xCE, 0x11, 0x88, 0x34, 0x68, 0x6D, - 0xEF, 0xD9, 0x9B, 0xD8, 0xBB, 0xC7, 0xDA, 0x4E, 0xB0, 0x6B, 0x1A, 0x3A, - 0x28, 0x29, 0x53, 0x20, 0x2A, 0x44, 0x83, 0x44, 0x49, 0x91, 0xDF, 0x82, - 0xB8, 0x9F, 0xC1, 0xFA, 0xF3, 0xFC, 0xB1, 0x36, 0x06, 0x37, 0xDE, 0x99, - 0x79, 0x6F, 0x3D, 0xF3, 0x76, 0x76, 0x64, 0xC5, 0xA5, 0x26, 0x74, 0x11, - 0x20, 0xD0, 0x43, 0x63, 0x69, 0x15, 0xBC, 0x3E, 0x5C, 0x48, 0xC0, 0x42, - 0xBE, 0x39, 0x96, 0xD6, 0x1F, 0x6F, 0xD7, 0x1F, 0xDE, 0xFD, 0x7E, 0xFF, - 0x69, 0xFD, 0xED, 0xEB, 0x83, 0x5F, 0x3F, 0xBE, 0xAF, 0x3F, 0xFF, 0x7C, - 0x28, 0xA9, 0xF7, 0xEF, 0x01, 0xA0, 0x24, 0x14, 0x62, 0x41, 0xA6, 0x47, - 0x9E, 0x41, 0x5D, 0x3F, 0x67, 0xDB, 0x0C, 0xD9, 0x94, 0x61, 0x48, 0x12, - 0xD4, 0x16, 0x50, 0x3C, 0x4A, 0x02, 0xE7, 0x39, 0x0F, 0xF9, 0x89, 0xBD, - 0x95, 0xD9, 0xEA, 0x25, 0x24, 0x08, 0x33, 0xAA, 0xC8, 0x99, 0x59, 0x89, - 0x2C, 0xD1, 0x35, 0x62, 0x1D, 0x31, 0x0F, 0xB2, 0xBB, 0x2F, 0xA2, 0x00, - 0x34, 0x18, 0x76, 0x85, 0x04, 0x2C, 0x82, 0x5F, 0x86, 0xC4, 0x11, 0xFB, - 0x5D, 0xA1, 0x1F, 0xDA, 0xD4, 0x0F, 0x44, 0x01, 0x1F, 0x05, 0xC8, 0x33, - 0x84, 0xB9, 0xD2, 0x30, 0x08, 0xC5, 0x11, 0x42, 0xAF, 0xBB, 0x48, 0x16, - 0x8A, 0x9B, 0x21, 0x90, 0xAF, 0x4B, 0x09, 0xAB, 0x92, 0x02, 0x68, 0x18, - 0x6C, 0x2C, 0x3D, 0x96, 0x1A, 0xDA, 0x8A, 0x75, 0x15, 0x2B, 0x2A, 0x96, - 0x53, 0x2C, 0xA6, 0x58, 0x4B, 0xB1, 0x92, 0x62, 0x1D, 0xC5, 0x22, 0x8A, - 0xF5, 0x13, 0x6B, 0x27, 0x96, 0xAD, 0x5F, 0x31, 0x0B, 0x46, 0x95, 0x16, - 0xE4, 0x96, 0x6A, 0x51, 0x0F, 0x93, 0x24, 0x9D, 0xC4, 0x28, 0xBD, 0x3E, - 0xB2, 0x43, 0xDE, 0xD2, 0x7B, 0x4B, 0xDE, 0x80, 0xB0, 0x11, 0x0B, 0x10, - 0x6F, 0x3E, 0x71, 0xE8, 0x4D, 0x08, 0x59, 0xD0, 0x15, 0xC2, 0xA4, 0x23, - 0xE4, 0xA3, 0xB7, 0x5D, 0x91, 0xBB, 0x5B, 0x03, 0x5A, 0x9B, 0xE4, 0x40, - 0xBA, 0x12, 0xD4, 0xD3, 0x38, 0xFF, 0xBC, 0xB0, 0x76, 0x51, 0xED, 0x52, - 0xDA, 0x15, 0xB4, 0x13, 0x6F, 0xE7, 0x2B, 0xC8, 0xB3, 0x3B, 0x49, 0x0F, - 0x31, 0x6C, 0x61, 0xE4, 0x55, 0x2F, 0x7F, 0xEE, 0x52, 0x27, 0x1A, 0x3F, - 0xA4, 0xC2, 0xA8, 0x87, 0xE6, 0x8D, 0x10, 0xD8, 0x98, 0x95, 0xCD, 0x11, - 0x83, 0x95, 0x7D, 0xB9, 0xA5, 0x1E, 0x1E, 0x29, 0x72, 0xF2, 0x2E, 0x1D, - 0x93, 0x69, 0xE9, 0x00, 0xE9, 0xAA, 0x20, 0xF0, 0xD9, 0x25, 0x37, 0x86, - 0x57, 0xE6, 0xB5, 0x60, 0x80, 0xE6, 0x30, 0xE0, 0xF2, 0x90, 0x52, 0xE8, - 0xD2, 0x93, 0xCF, 0xB7, 0x65, 0xE8, 0xBA, 0x92, 0x7A, 0xCC, 0x9F, 0x5D, - 0x30, 0x1D, 0xF1, 0x29, 0x09, 0x46, 0x1A, 0x7F, 0xB2, 0xD5, 0x2B, 0xFE, - 0x24, 0x32, 0x94, 0xA4, 0xAE, 0x5D, 0x5C, 0x4A, 0x6C, 0x49, 0xFD, 0x7F, - 0xBE, 0x87, 0x2C, 0x4E, 0x9F, 0xCA, 0x9A, 0x26, 0x0F, 0xE6, 0xF8, 0x0E, - 0x65, 0xC1, 0x86, 0xD5, 0xE4, 0x00, 0x50, 0xF3, 0xE4, 0x92, 0x04, 0xD8, - 0x6B, 0x48, 0x52, 0xF1, 0xD4, 0x24, 0x99, 0xCD, 0x46, 0x0E, 0x2F, 0x65, - 0xC4, 0xEF, 0xD5, 0x48, 0xD7, 0x47, 0xFE, 0x08, 0x5C, 0x28, 0x72, 0x05, - 0xDC, 0xC5, 0xCE, 0xA4, 0x48, 0xC9, 0x19, 0x77, 0x38, 0x35, 0x55, 0x61, - 0x36, 0x3B, 0xD0, 0xB4, 0x03, 0x5D, 0x1F, 0xC4, 0xC8, 0x35, 0x48, 0x39, - 0x4D, 0x42, 0x22, 0x40, 0xA3, 0xDC, 0xBC, 0x27, 0xCE, 0xB9, 0xB7, 0x68, - 0x94, 0x93, 0x48, 0xB3, 0xAE, 0x66, 0x9E, 0xAF, 0x1F, 0x4F, 0x9F, 0xDE, - 0xBC, 0x84, 0xCE, 0x69, 0x7C, 0x91, 0xE9, 0x56, 0x05, 0xA5, 0x4C, 0x12, - 0x7A, 0x06, 0x62, 0x75, 0xF1, 0x6A, 0xBE, 0x3C, 0x27, 0xEE, 0xE3, 0xFD, - 0x6D, 0x4A, 0x6A, 0xBC, 0x1B, 0xC7, 0x4F, 0xF6, 0xE3, 0x98, 0x0F, 0xB3, - 0x1A, 0xAE, 0x9B, 0x6A, 0x86, 0x8C, 0x21, 0x62, 0x46, 0x92, 0xBA, 0x0D, - 0x0A, 0xF6, 0x60, 0xF2, 0x0A, 0x31, 0x13, 0x91, 0x20, 0xFF, 0xEE, 0x4E, - 0x9B, 0x97, 0x08, 0xD2, 0x2A, 0xA2, 0x2C, 0x6C, 0x53, 0xEB, 0x56, 0xDD, - 0x95, 0x6F, 0x6F, 0x21, 0x13, 0x7B, 0x90, 0x37, 0xC6, 0x6E, 0xB1, 0x4B, - 0x16, 0xEE, 0x24, 0xD8, 0x8C, 0x86, 0x2B, 0x9C, 0x34, 0xC3, 0xFE, 0x40, - 0x46, 0x59, 0xC1, 0xCE, 0x40, 0x02, 0xEF, 0xAF, 0xD0, 0x97, 0xD4, 0xBD, - 0x81, 0xF0, 0x18, 0x31, 0x2A, 0xA9, 0x8F, 0x5A, 0xE8, 0x8D, 0x30, 0xB5, - 0x03, 0x2F, 0x4E, 0xA3, 0xA6, 0x4C, 0xDD, 0x59, 0xB4, 0x61, 0x6A, 0x48, - 0xEA, 0x62, 0x9B, 0x4F, 0xA2, 0x1A, 0xA0, 0x87, 0x84, 0x7D, 0x9A, 0x2C, - 0x24, 0xF5, 0x70, 0x71, 0xF6, 0x0F, 0xB4, 0xEA, 0x39, 0xB4, 0x48, 0xE9, - 0x28, 0x6C, 0xA5, 0x9D, 0xDC, 0xFB, 0x68, 0x85, 0x96, 0xD0, 0x2C, 0xC6, - 0x6D, 0x61, 0xE6, 0x7B, 0x6A, 0x11, 0xFF, 0xC3, 0xB3, 0xC0, 0x9C, 0xCB, - 0x23, 0x8B, 0x01, 0x98, 0x60, 0x4A, 0x7A, 0x00, 0x47, 0x34, 0x64, 0x18, - 0x31, 0xA0, 0x07, 0x56, 0x07, 0x62, 0x62, 0x51, 0x03, 0x81, 0x39, 0xFE, - 0x2B, 0x64, 0x86, 0x0C, 0x86, 0x6E, 0x7A, 0x21, 0x13, 0x06, 0x0D, 0x7E, - 0xC3, 0xFA, 0x20, 0xE7, 0x0E, 0xC4, 0x1D, 0x80, 0x53, 0x1A, 0x87, 0x57, - 0x10, 0x9C, 0xD0, 0xC0, 0xC1, 0x66, 0x52, 0xD3, 0xDE, 0x8B, 0x67, 0x40, - 0xEB, 0x07, 0x73, 0x01, 0x4C, 0x87, 0x16, 0xE0, 0x45, 0xEF, 0xA7, 0x39, - 0xD6, 0x4E, 0xAA, 0x04, 0x67, 0xBD, 0x30, 0x9D, 0x0E, 0x82, 0x69, 0x51, - 0x48, 0xEC, 0x4B, 0x9A, 0x22, 0xB3, 0x24, 0xD3, 0xC1, 0x56, 0x39, 0x4F, - 0x45, 0xCE, 0xFE, 0xF7, 0xD5, 0x3F, 0x30, 0xBB, 0xD9, 0x9B}; -const uint8_t g_nlNL_Locale[] = { - 0x78, 0x9C, 0x95, 0x56, 0x4D, 0x4F, 0xDC, 0x30, 0x10, 0x3D, 0x53, 0xA9, - 0xFF, 0xC1, 0x8A, 0x8A, 0x68, 0x25, 0x96, 0x2D, 0x47, 0x50, 0x88, 0xB4, - 0x05, 0x0A, 0x15, 0x04, 0xAD, 0x58, 0xDA, 0xAA, 0x5C, 0x2A, 0x6F, 0x62, - 0x76, 0xBD, 0x24, 0xF6, 0xCA, 0x89, 0x41, 0xC9, 0xB1, 0x52, 0x8F, 0xFD, - 0x27, 0xAD, 0xDA, 0x5B, 0xFF, 0x4F, 0xA5, 0x4A, 0xFC, 0x8C, 0x8E, 0xF3, - 0x45, 0x12, 0x3B, 0x69, 0xC8, 0x05, 0xCF, 0x9B, 0xF7, 0xBC, 0x33, 0xCF, - 0xCE, 0x10, 0x3B, 0xE0, 0x1E, 0x0E, 0x08, 0x62, 0x38, 0x24, 0x07, 0x16, - 0x0B, 0x3E, 0x5F, 0x9C, 0x5B, 0xC8, 0x27, 0x91, 0x77, 0x60, 0x3D, 0x7C, - 0xFB, 0xFD, 0xF7, 0xEB, 0xAF, 0x87, 0x9F, 0x3F, 0x5E, 0xE6, 0xAB, 0x57, - 0x96, 0xF3, 0xFC, 0x19, 0x42, 0xB6, 0xE2, 0x33, 0x1F, 0x8B, 0x59, 0x12, - 0xCE, 0x79, 0x10, 0x15, 0xD2, 0x85, 0x20, 0x0B, 0x2E, 0x28, 0x66, 0x8A, - 0xB5, 0x81, 0xEC, 0x90, 0xB3, 0x78, 0x79, 0x01, 0xA9, 0x48, 0xC5, 0x1B, - 0x79, 0xEC, 0xAC, 0x30, 0x93, 0x58, 0x50, 0x7B, 0x9C, 0x87, 0xB5, 0xCC, - 0x0D, 0x99, 0x8B, 0x8E, 0x54, 0x88, 0xB1, 0x88, 0x0D, 0x38, 0x5E, 0x0B, - 0x1A, 0x98, 0xF8, 0xC4, 0xB4, 0xCB, 0x4A, 0x32, 0x33, 0x1C, 0x98, 0x60, - 0x2C, 0x17, 0x32, 0x8A, 0x65, 0x64, 0x48, 0x45, 0x64, 0x1D, 0x93, 0x70, - 0x4E, 0x84, 0x21, 0xC7, 0x6F, 0x63, 0x6E, 0xCE, 0x30, 0x7E, 0xD7, 0x25, - 0xF2, 0x89, 0xD7, 0x4E, 0xA1, 0x62, 0x5D, 0x19, 0x58, 0x37, 0x14, 0xE1, - 0xF9, 0x5C, 0x1C, 0x58, 0xBB, 0x56, 0xCB, 0x59, 0xB3, 0xAB, 0x26, 0x83, - 0xBA, 0xEC, 0x7C, 0x8A, 0x99, 0x66, 0x2F, 0xCD, 0x56, 0x9A, 0x5D, 0x34, - 0xFB, 0x67, 0xF6, 0xCE, 0x6C, 0x5B, 0xBF, 0x63, 0x3E, 0x4E, 0x6A, 0x17, - 0x10, 0x22, 0x27, 0xE5, 0x70, 0x71, 0xA1, 0x1A, 0xB5, 0xAE, 0x40, 0xB8, - 0x5E, 0x06, 0xD4, 0xA7, 0x2C, 0xD2, 0xD1, 0x7B, 0x4E, 0x4C, 0xB0, 0x0F, - 0xFB, 0x12, 0xA1, 0xE3, 0x77, 0x82, 0xAE, 0x74, 0x34, 0xC5, 0x71, 0x93, - 0x8C, 0xB2, 0x95, 0xA1, 0xF2, 0xD6, 0x49, 0xE7, 0x2D, 0x68, 0xE5, 0x6B, - 0x95, 0x6B, 0x45, 0x6B, 0xE5, 0x6A, 0x75, 0x6A, 0x25, 0x76, 0x17, 0x17, - 0x12, 0x41, 0x7D, 0x4A, 0xC2, 0xFA, 0xCB, 0x5D, 0x40, 0xCE, 0xC4, 0x85, - 0x63, 0x28, 0x83, 0x66, 0x6A, 0xDA, 0x4A, 0xA1, 0xC7, 0xB0, 0xB6, 0x39, - 0x11, 0xB8, 0xB6, 0x2F, 0x44, 0xCE, 0x9B, 0x43, 0x7B, 0xAC, 0xFE, 0x56, - 0xC0, 0xE4, 0xA8, 0x02, 0x50, 0xB6, 0x2A, 0x05, 0x30, 0x9B, 0xC6, 0xAD, - 0xE1, 0x94, 0xA3, 0x3E, 0x18, 0x3E, 0xC5, 0x31, 0xB8, 0xCE, 0x2A, 0x83, - 0x2B, 0xA4, 0x98, 0x5F, 0x37, 0x32, 0x08, 0x2C, 0xE7, 0x18, 0x1E, 0x74, - 0x84, 0x5C, 0x78, 0xD0, 0x27, 0x78, 0x54, 0xEF, 0x15, 0xB3, 0x4B, 0x1A, - 0x70, 0xB6, 0xB0, 0x9C, 0xA7, 0xAA, 0x42, 0xE2, 0x83, 0x68, 0x04, 0x9A, - 0xD1, 0x60, 0x4D, 0xB4, 0xE4, 0x22, 0xCE, 0x54, 0x23, 0x5D, 0x81, 0x50, - 0x03, 0x29, 0x7A, 0x8F, 0x69, 0xD8, 0xEA, 0xBD, 0x86, 0x34, 0x7A, 0x3F, - 0xDD, 0x77, 0xDD, 0xFD, 0xD9, 0x6C, 0x0B, 0x49, 0x29, 0xB6, 0xD0, 0xB5, - 0x3D, 0xAE, 0x11, 0xBB, 0x94, 0x79, 0xEB, 0x85, 0x72, 0xA0, 0x26, 0x6B, - 0xBC, 0x90, 0x0C, 0x12, 0x14, 0x5D, 0x2B, 0x49, 0x9B, 0xAF, 0x7A, 0x6E, - 0x75, 0x58, 0x9C, 0xF7, 0x15, 0xA0, 0xE5, 0x25, 0x38, 0x49, 0x5C, 0xFF, - 0xF6, 0x34, 0x8C, 0x66, 0xC7, 0x47, 0x6F, 0xEF, 0x3F, 0xE2, 0xE5, 0x59, - 0x7A, 0x9D, 0x5B, 0x55, 0x27, 0x65, 0x4A, 0x26, 0xD5, 0x20, 0x6E, 0xFA, - 0xD5, 0xC0, 0xCA, 0x7F, 0x94, 0x52, 0xDD, 0x5D, 0xCF, 0x72, 0xD2, 0xED, - 0x34, 0xDD, 0xDB, 0x49, 0xD3, 0xD4, 0x1E, 0x37, 0x78, 0xDD, 0x52, 0x4F, - 0x0A, 0x41, 0x98, 0x97, 0x58, 0xCE, 0x0B, 0x94, 0xAB, 0xF7, 0xF6, 0xA2, - 0xC1, 0xEA, 0x35, 0x11, 0x1E, 0x61, 0x71, 0xF1, 0xC3, 0x9B, 0xBA, 0x4E, - 0x39, 0xA2, 0x75, 0x51, 0x75, 0xF6, 0xD8, 0xEC, 0x46, 0x13, 0x2A, 0xB6, - 0x87, 0x99, 0x4A, 0x43, 0x0C, 0x97, 0x61, 0xBB, 0xDC, 0x25, 0x4F, 0x77, - 0x0A, 0x16, 0x82, 0xCB, 0x35, 0x55, 0x97, 0x60, 0x67, 0xA0, 0xA2, 0xEA, - 0x60, 0x73, 0xA0, 0x20, 0xA4, 0x4C, 0x46, 0x96, 0x33, 0x1A, 0x48, 0x4F, - 0x89, 0xE0, 0x96, 0xF3, 0x5A, 0x63, 0x3F, 0x1A, 0xD3, 0x38, 0xF1, 0xF2, - 0x38, 0x1A, 0xCE, 0x34, 0xC1, 0xF2, 0x1A, 0x66, 0x81, 0xE5, 0xFC, 0xF9, - 0xF2, 0x1D, 0xE6, 0x4C, 0x83, 0xD1, 0xA3, 0xA2, 0x11, 0x57, 0x0B, 0x18, - 0x2D, 0xEF, 0x2F, 0x9F, 0x20, 0xAB, 0x1F, 0x84, 0x26, 0xCA, 0x06, 0x9D, - 0x56, 0xB7, 0x7A, 0xD9, 0x93, 0x35, 0xB9, 0xC1, 0x5E, 0x39, 0x4C, 0xCB, - 0xB0, 0xD8, 0xD3, 0x4D, 0xE0, 0xFB, 0xCC, 0x47, 0x53, 0xF0, 0x67, 0x6C, - 0x26, 0x50, 0x46, 0x39, 0xEB, 0x21, 0x1C, 0x72, 0x29, 0x28, 0x11, 0x68, - 0x16, 0xFB, 0x1D, 0x8C, 0x89, 0x0F, 0xDF, 0x3F, 0x68, 0x4A, 0xFF, 0x4B, - 0x39, 0x85, 0xEF, 0x3D, 0x72, 0xDF, 0x4B, 0x99, 0x08, 0x3C, 0x87, 0x77, - 0xAC, 0x8F, 0x72, 0xB5, 0xC4, 0xB4, 0x83, 0x70, 0xC6, 0x53, 0x79, 0x8B, - 0xD1, 0x09, 0x8F, 0x97, 0xD4, 0x53, 0x3D, 0x8D, 0x3E, 0xBC, 0x43, 0x6E, - 0x3F, 0x19, 0x0C, 0xF0, 0x96, 0xBC, 0x24, 0x5F, 0xF6, 0xFE, 0x34, 0x70, - 0x17, 0xAA, 0x4B, 0x74, 0xDE, 0x4B, 0x9B, 0xF1, 0x41, 0x34, 0x37, 0x91, - 0x6C, 0xB1, 0xE2, 0x19, 0x33, 0x2F, 0x32, 0x1B, 0x6D, 0xB5, 0xF3, 0xB4, - 0xC7, 0xF9, 0xA7, 0xBA, 0xF3, 0x0F, 0xD5, 0xFA, 0xC0, 0xFA}; -const uint8_t g_ruRU_Locale[] = { - 0x78, 0x9C, 0xAD, 0x57, 0x4D, 0x4F, 0x13, 0x41, 0x18, 0x3E, 0x63, 0xE2, - 0x7F, 0x98, 0x6C, 0x24, 0x68, 0x02, 0xAD, 0x1E, 0x25, 0x65, 0x13, 0x22, - 0x0A, 0x06, 0xD7, 0x90, 0x16, 0x34, 0x72, 0x31, 0xDB, 0xDD, 0xA1, 0x5D, - 0xE8, 0xEE, 0x90, 0xE9, 0x6E, 0xB0, 0x7B, 0x2A, 0x85, 0xE8, 0x05, 0x25, - 0xE1, 0xA0, 0x47, 0xF4, 0xE4, 0xC9, 0x50, 0xBE, 0x12, 0x82, 0xB6, 0x24, - 0xFE, 0x82, 0xD9, 0xFF, 0x60, 0xD4, 0x9F, 0xE1, 0x3B, 0xFB, 0xD1, 0xEE, - 0xB7, 0xC5, 0xD8, 0x1E, 0x3A, 0xF3, 0x3E, 0xCF, 0xF3, 0xCE, 0xFB, 0xB5, - 0xD3, 0xB6, 0xD4, 0x20, 0x8A, 0xDC, 0xC0, 0xC8, 0x90, 0x75, 0x3C, 0x23, - 0x50, 0xEB, 0x65, 0x79, 0x45, 0x40, 0x2A, 0x6E, 0x2A, 0x33, 0xC2, 0x8F, - 0xAB, 0xDD, 0xDF, 0x47, 0x5F, 0x6E, 0xC3, 0xC7, 0xAF, 0xDE, 0x87, 0x9F, - 0xEF, 0x8F, 0xEE, 0x08, 0xE2, 0xCD, 0x1B, 0x08, 0x95, 0x38, 0xDF, 0x50, - 0x65, 0x5A, 0x69, 0xE9, 0x55, 0xD2, 0x68, 0xFA, 0xD2, 0x1A, 0xC5, 0x35, - 0x42, 0x35, 0xD9, 0xE0, 0xAC, 0x31, 0x54, 0xD2, 0x89, 0x61, 0xD6, 0x9F, - 0x02, 0xD4, 0xE4, 0xFB, 0x31, 0x6F, 0x2F, 0x3A, 0xFB, 0xAC, 0xC7, 0x4E, - 0x58, 0xD7, 0x69, 0x3B, 0xFB, 0xA5, 0xA2, 0x67, 0x0B, 0xC3, 0xBB, 0xEC, - 0x9C, 0x9D, 0x38, 0x6D, 0xD6, 0x65, 0x5F, 0x53, 0x09, 0xEC, 0x9B, 0xAB, - 0xED, 0xB0, 0x6E, 0x1A, 0xD8, 0x65, 0x57, 0xA0, 0x3D, 0xCF, 0xD3, 0xA6, - 0x02, 0x17, 0xCE, 0x3B, 0xD6, 0xCB, 0x86, 0x32, 0xDC, 0x75, 0x21, 0x91, - 0x53, 0x67, 0xC7, 0xD9, 0xCE, 0x08, 0xC7, 0xD9, 0x86, 0x50, 0x7A, 0x4E, - 0x07, 0x72, 0x3E, 0xCE, 0xC8, 0x97, 0xF5, 0xD9, 0x65, 0x3E, 0xA1, 0xC7, - 0xFA, 0x79, 0xF0, 0x19, 0x1C, 0x71, 0x09, 0x91, 0xC4, 0x09, 0xC8, 0x5F, - 0x0F, 0x1A, 0x10, 0x6E, 0x08, 0x92, 0xAB, 0x55, 0x3A, 0x23, 0xDC, 0x13, - 0x92, 0x9D, 0x29, 0xE4, 0x34, 0x25, 0x0D, 0x1B, 0xA1, 0x1F, 0x99, 0xB2, - 0xFF, 0xDD, 0x8A, 0xD4, 0xD8, 0xFD, 0x1E, 0xA4, 0x06, 0xE1, 0x16, 0x3F, - 0x15, 0xF1, 0xAB, 0x9E, 0x8A, 0xB9, 0x25, 0x2F, 0xE4, 0xD7, 0x5A, 0x95, - 0x5B, 0xA1, 0xD1, 0x87, 0x9D, 0x08, 0x01, 0xF6, 0x21, 0x98, 0x4B, 0x3E, - 0x9F, 0x7E, 0x50, 0x7B, 0xEC, 0xBC, 0x54, 0xE4, 0xD8, 0x90, 0x74, 0x05, - 0x31, 0xF5, 0x00, 0x3C, 0x73, 0x87, 0x78, 0x0F, 0xD6, 0x17, 0xEC, 0x32, - 0x4E, 0x3A, 0x81, 0x72, 0xF7, 0xC1, 0x4F, 0x1A, 0x08, 0xC3, 0xD8, 0x76, - 0xF5, 0xDD, 0x38, 0xF0, 0x06, 0xCE, 0xED, 0x40, 0x14, 0xE7, 0x40, 0x38, - 0x4D, 0x9C, 0xEB, 0xEC, 0x03, 0x08, 0x0E, 0x9D, 0xD7, 0x49, 0xE5, 0xB6, - 0xB3, 0xC3, 0x8E, 0xE1, 0xDD, 0xF7, 0xDA, 0xEC, 0x83, 0xC8, 0x5D, 0xA5, - 0xE4, 0x1C, 0x9B, 0x2E, 0xD7, 0xFF, 0x81, 0xB3, 0x1D, 0x3F, 0xF2, 0x90, - 0xF5, 0xE2, 0xA6, 0x03, 0xA7, 0x13, 0x37, 0x7D, 0x72, 0xDA, 0x71, 0xD3, - 0xE7, 0x24, 0xEB, 0x30, 0x45, 0xC8, 0x8E, 0xB3, 0x43, 0xD5, 0x31, 0xD5, - 0x54, 0x0D, 0xEB, 0xE1, 0xEB, 0xC9, 0x37, 0x89, 0xB3, 0x12, 0xB4, 0x33, - 0xD8, 0x44, 0xA1, 0xA5, 0x18, 0x84, 0x86, 0xDB, 0x90, 0x73, 0x4C, 0xE5, - 0x90, 0x5F, 0xD8, 0xF1, 0x91, 0xE9, 0x23, 0xD6, 0x2B, 0x38, 0x6F, 0x61, - 0x6C, 0xB8, 0x61, 0x88, 0x44, 0x8D, 0xC8, 0x5D, 0x05, 0x6A, 0xB8, 0x6A, - 0x8B, 0xB1, 0xBB, 0xD6, 0xB3, 0xAA, 0xB2, 0x89, 0x97, 0x64, 0xD3, 0xC4, - 0xD4, 0x18, 0xD4, 0x7E, 0x60, 0xF1, 0xAF, 0xE3, 0x35, 0xAB, 0xD1, 0x10, - 0xC4, 0x39, 0x24, 0xC1, 0x0B, 0xBD, 0x80, 0x17, 0x9A, 0x80, 0x27, 0x64, - 0x82, 0x57, 0x62, 0x40, 0xCD, 0xD2, 0x36, 0x88, 0x51, 0xFB, 0x57, 0xAD, - 0x8E, 0x55, 0x90, 0xCE, 0x15, 0x24, 0xA9, 0xC0, 0x95, 0x23, 0x69, 0x9A, - 0x75, 0x42, 0xCD, 0xA1, 0x2A, 0xAE, 0x41, 0x28, 0x62, 0xF1, 0x8B, 0x60, - 0x6A, 0x7A, 0xAC, 0x08, 0x21, 0x4B, 0xA4, 0x08, 0x0B, 0xD3, 0x92, 0x34, - 0x5D, 0xA9, 0xA0, 0xD5, 0x52, 0x31, 0x44, 0xC9, 0xD2, 0x78, 0xC9, 0x5F, - 0x4F, 0xE3, 0x26, 0xED, 0x4B, 0x46, 0x12, 0xF8, 0x19, 0x73, 0x49, 0x9C, - 0xCF, 0xB3, 0x8D, 0xE5, 0xE6, 0xB7, 0x7C, 0x19, 0xAC, 0xC1, 0x1C, 0xCC, - 0xCB, 0xC6, 0xFA, 0xC6, 0x82, 0xDE, 0xAC, 0x3C, 0x9C, 0x7B, 0xB4, 0xF5, - 0xFC, 0x55, 0x7D, 0xD1, 0x5E, 0xF5, 0x8A, 0x14, 0x26, 0xB9, 0x4A, 0xC3, - 0xD2, 0xAB, 0x98, 0x46, 0x2B, 0x15, 0xB1, 0xF9, 0x21, 0x81, 0x0D, 0x66, - 0x59, 0x11, 0x44, 0x7B, 0xD2, 0xB6, 0xEF, 0x17, 0x6C, 0xDB, 0x2E, 0x15, - 0x23, 0xBC, 0x6C, 0xA9, 0x62, 0x51, 0x8A, 0x0D, 0xA5, 0x35, 0xD4, 0xDE, - 0x1A, 0x59, 0xBB, 0x89, 0xA9, 0x82, 0x0D, 0xD3, 0x97, 0x8E, 0x27, 0x75, - 0xBC, 0x1E, 0x89, 0x1C, 0x06, 0x79, 0x0D, 0x53, 0x1D, 0x8B, 0x9A, 0x7C, - 0xF7, 0x2A, 0x56, 0x34, 0x5D, 0x86, 0x21, 0x98, 0x0C, 0xBC, 0x78, 0x70, - 0xA6, 0xA0, 0x46, 0x89, 0xB5, 0xA9, 0xF1, 0x11, 0xF8, 0xFE, 0x71, 0x44, - 0xC9, 0x20, 0x85, 0xF1, 0x11, 0x05, 0xBA, 0x66, 0x58, 0x4D, 0x41, 0x9C, - 0x1A, 0x91, 0x6E, 0x63, 0x4A, 0x04, 0xF1, 0x6E, 0x82, 0x3D, 0xAC, 0x4C, - 0xA4, 0xE1, 0x41, 0x37, 0x22, 0xA5, 0x89, 0x1A, 0x83, 0x29, 0x74, 0x37, - 0x82, 0xE8, 0x7E, 0x47, 0x47, 0x19, 0x39, 0x2A, 0xAD, 0x49, 0xF8, 0x42, - 0x10, 0xCB, 0x2B, 0xE5, 0x6B, 0xC8, 0xC2, 0x9D, 0x48, 0x88, 0xDC, 0xAB, - 0x2E, 0x11, 0x37, 0x7F, 0xCA, 0x5B, 0x9B, 0x78, 0x4D, 0x56, 0x82, 0xBB, - 0x35, 0xD8, 0xFA, 0x3E, 0xA5, 0x16, 0xFC, 0xE0, 0x54, 0xD1, 0x12, 0xD4, - 0xA7, 0x98, 0x4E, 0xD0, 0x0C, 0x8D, 0x18, 0x39, 0x84, 0x07, 0xC4, 0xA2, - 0x1A, 0xA6, 0xA8, 0x62, 0xAA, 0x19, 0x8C, 0x59, 0x95, 0x54, 0x31, 0x5A, - 0xD2, 0xFE, 0x4A, 0x59, 0xC0, 0x55, 0x8A, 0xB7, 0x72, 0x29, 0xB3, 0x54, - 0xAE, 0xC2, 0x23, 0x96, 0x47, 0x59, 0xAE, 0xCB, 0x5A, 0x06, 0x61, 0x91, - 0xD8, 0xD6, 0x86, 0x8C, 0xE6, 0x89, 0x59, 0xD7, 0x14, 0x9E, 0xD3, 0xD4, - 0xB3, 0xC7, 0x48, 0xCA, 0x27, 0x43, 0x01, 0x94, 0x3A, 0x09, 0xC8, 0xE5, - 0xDC, 0xA3, 0x81, 0x5B, 0xE3, 0x59, 0xA2, 0x27, 0xB9, 0xB4, 0x0A, 0x19, - 0x89, 0x26, 0xB5, 0x2C, 0xA3, 0xB6, 0x4E, 0x5C, 0xA6, 0x17, 0xA4, 0x7B, - 0xB3, 0x85, 0xFA, 0x59, 0x2A, 0x7A, 0xFF, 0x3D, 0xC4, 0x3F, 0xDE, 0xCB, - 0x8B, 0xC4}; - -static std::unique_ptr<IFX_Locale> XFA_GetLocaleFromBuffer(const uint8_t* pBuf, - int nBufLen) { - if (!pBuf || nBufLen <= 0) - return nullptr; - CFX_GEModule* pGeModule = CFX_GEModule::Get(); - if (!pGeModule) - return nullptr; - - CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule(); - if (!pCodecMgr) - return nullptr; - - std::unique_ptr<CXML_Element> pLocale; - uint8_t* pOut = nullptr; - uint32_t dwSize; - pCodecMgr->GetFlateModule()->FlateOrLZWDecode(false, pBuf, nBufLen, true, 0, - 0, 0, 0, 0, pOut, dwSize); - if (pOut) { - pLocale = CXML_Element::Parse(pOut, dwSize); - FX_Free(pOut); - } - return pLocale ? std::unique_ptr<IFX_Locale>( - new CXFA_XMLLocale(std::move(pLocale))) - : nullptr; -} - -static uint16_t XFA_GetLanguage(CFX_WideString wsLanguage) { - uint16_t dwLangueID = XFA_LANGID_en_US; - if (wsLanguage.GetLength() < 2) { - return dwLangueID; - } - wsLanguage.MakeLower(); - uint32_t dwIDFirst = wsLanguage.GetAt(0) << 8 | wsLanguage.GetAt(1); - uint32_t dwIDSecond = wsLanguage.GetLength() >= 5 - ? wsLanguage.GetAt(3) << 8 | wsLanguage.GetAt(4) - : 0; - switch (dwIDFirst) { - case FXBSTR_ID(0, 0, 'z', 'h'): { - if (dwIDSecond == FXBSTR_ID(0, 0, 'c', 'n')) { - dwLangueID = XFA_LANGID_zh_CN; - } else if (dwIDSecond == FXBSTR_ID(0, 0, 't', 'w')) { - dwLangueID = XFA_LANGID_zh_TW; - } else if (dwIDSecond == FXBSTR_ID(0, 0, 'h', 'k')) { - dwLangueID = XFA_LANGID_zh_HK; - } - } break; - case FXBSTR_ID(0, 0, 'j', 'a'): - dwLangueID = XFA_LANGID_ja_JP; - break; - case FXBSTR_ID(0, 0, 'k', 'o'): - dwLangueID = XFA_LANGID_ko_KR; - break; - case FXBSTR_ID(0, 0, 'e', 'n'): { - if (dwIDSecond == FXBSTR_ID(0, 0, 'g', 'b')) { - dwLangueID = XFA_LANGID_en_GB; - } else { - dwLangueID = XFA_LANGID_en_US; - } - } break; - case FXBSTR_ID(0, 0, 'd', 'e'): - dwLangueID = XFA_LANGID_de_DE; - break; - case FXBSTR_ID(0, 0, 'f', 'r'): - dwLangueID = XFA_LANGID_fr_FR; - break; - case FXBSTR_ID(0, 0, 'e', 's'): { - if (dwIDSecond == FXBSTR_ID(0, 0, 'e', 's')) { - dwLangueID = XFA_LANGID_es_ES; - } else { - dwLangueID = XFA_LANGID_es_LA; - } - } break; - case FXBSTR_ID(0, 0, 'i', 't'): - dwLangueID = XFA_LANGID_it_IT; - break; - case FXBSTR_ID(0, 0, 'p', 't'): - dwLangueID = XFA_LANGID_pt_BR; - break; - case FXBSTR_ID(0, 0, 'n', 'l'): - dwLangueID = XFA_LANGID_nl_NL; - break; - case FXBSTR_ID(0, 0, 'r', 'u'): - dwLangueID = XFA_LANGID_ru_RU; - break; - } - return dwLangueID; -} - -CXFA_LocaleMgr::CXFA_LocaleMgr(CXFA_Node* pLocaleSet, CFX_WideString wsDeflcid) - : m_dwLocaleFlags(0x00) { - m_dwDeflcid = XFA_GetLanguage(wsDeflcid); - if (pLocaleSet) { - CXFA_Node* pNodeLocale = pLocaleSet->GetNodeItem(XFA_NODEITEM_FirstChild); - while (pNodeLocale) { - m_LocaleArray.emplace_back(new CXFA_NodeLocale(pNodeLocale)); - pNodeLocale = pNodeLocale->GetNodeItem(XFA_NODEITEM_NextSibling); - } - } - m_pDefLocale = GetLocaleByName(wsDeflcid); -} - -CXFA_LocaleMgr::~CXFA_LocaleMgr() {} - -uint16_t CXFA_LocaleMgr::GetDefLocaleID() const { - return m_dwDeflcid; -} - -IFX_Locale* CXFA_LocaleMgr::GetDefLocale() { - if (m_pDefLocale) - return m_pDefLocale; - - if (!m_LocaleArray.empty()) - return m_LocaleArray[0].get(); - - if (!m_XMLLocaleArray.empty()) - return m_XMLLocaleArray[0].get(); - - std::unique_ptr<IFX_Locale> locale(GetLocale(m_dwDeflcid)); - m_pDefLocale = locale.get(); - if (locale) - m_XMLLocaleArray.push_back(std::move(locale)); - - return m_pDefLocale; -} - -std::unique_ptr<IFX_Locale> CXFA_LocaleMgr::GetLocale(uint16_t lcid) { - switch (lcid) { - case XFA_LANGID_zh_CN: - return XFA_GetLocaleFromBuffer(g_zhCN_Locale, sizeof(g_zhCN_Locale)); - case XFA_LANGID_zh_TW: - return XFA_GetLocaleFromBuffer(g_zhTW_Locale, sizeof(g_zhTW_Locale)); - case XFA_LANGID_zh_HK: - return XFA_GetLocaleFromBuffer(g_zhHK_Locale, sizeof(g_zhHK_Locale)); - case XFA_LANGID_ja_JP: - return XFA_GetLocaleFromBuffer(g_jaJP_Locale, sizeof(g_jaJP_Locale)); - case XFA_LANGID_ko_KR: - return XFA_GetLocaleFromBuffer(g_koKR_Locale, sizeof(g_koKR_Locale)); - case XFA_LANGID_en_GB: - return XFA_GetLocaleFromBuffer(g_enGB_Locale, sizeof(g_enGB_Locale)); - case XFA_LANGID_es_LA: - return XFA_GetLocaleFromBuffer(g_esLA_Locale, sizeof(g_esLA_Locale)); - case XFA_LANGID_es_ES: - return XFA_GetLocaleFromBuffer(g_esES_Locale, sizeof(g_esES_Locale)); - case XFA_LANGID_de_DE: - return XFA_GetLocaleFromBuffer(g_deDE_Loacale, sizeof(g_deDE_Loacale)); - case XFA_LANGID_fr_FR: - return XFA_GetLocaleFromBuffer(g_frFR_Locale, sizeof(g_frFR_Locale)); - case XFA_LANGID_it_IT: - return XFA_GetLocaleFromBuffer(g_itIT_Locale, sizeof(g_itIT_Locale)); - case XFA_LANGID_pt_BR: - return XFA_GetLocaleFromBuffer(g_ptBR_Locale, sizeof(g_ptBR_Locale)); - case XFA_LANGID_nl_NL: - return XFA_GetLocaleFromBuffer(g_nlNL_Locale, sizeof(g_nlNL_Locale)); - case XFA_LANGID_ru_RU: - return XFA_GetLocaleFromBuffer(g_ruRU_Locale, sizeof(g_ruRU_Locale)); - case XFA_LANGID_en_US: - default: - return XFA_GetLocaleFromBuffer(g_enUS_Locale, sizeof(g_enUS_Locale)); - } -} - -IFX_Locale* CXFA_LocaleMgr::GetLocaleByName( - const CFX_WideString& wsLocaleName) { - for (size_t i = 0; i < m_LocaleArray.size(); i++) { - IFX_Locale* pLocale = m_LocaleArray[i].get(); - if (pLocale->GetName() == wsLocaleName) - return pLocale; - } - if (wsLocaleName.GetLength() < 2) - return nullptr; - for (size_t i = 0; i < m_XMLLocaleArray.size(); i++) { - IFX_Locale* pLocale = m_XMLLocaleArray[i].get(); - if (pLocale->GetName() == wsLocaleName) - return pLocale; - } - uint16_t dwLangueID = XFA_GetLanguage(wsLocaleName); - std::unique_ptr<IFX_Locale> pLocale(GetLocale(dwLangueID)); - IFX_Locale* pRetLocale = pLocale.get(); - if (pLocale) - m_XMLLocaleArray.push_back(std::move(pLocale)); - return pRetLocale; -} - -void CXFA_LocaleMgr::SetDefLocale(IFX_Locale* pLocale) { - m_pDefLocale = pLocale; -} - -CFX_WideStringC CXFA_LocaleMgr::GetConfigLocaleName(CXFA_Node* pConfig) { - if (!(m_dwLocaleFlags & 0x01)) { - m_wsConfigLocale.clear(); - if (pConfig) { - CXFA_Node* pChildfConfig = - pConfig->GetFirstChildByClass(XFA_Element::Acrobat); - if (!pChildfConfig) { - pChildfConfig = pConfig->GetFirstChildByClass(XFA_Element::Present); - } - CXFA_Node* pCommon = - pChildfConfig - ? pChildfConfig->GetFirstChildByClass(XFA_Element::Common) - : nullptr; - CXFA_Node* pLocale = - pCommon ? pCommon->GetFirstChildByClass(XFA_Element::Locale) - : nullptr; - if (pLocale) { - pLocale->TryCData(XFA_ATTRIBUTE_Value, m_wsConfigLocale, false); - } - } - m_dwLocaleFlags |= 0x01; - } - return m_wsConfigLocale.AsStringC(); -} - -static bool g_bProviderTimeZoneSet = false; - -CXFA_TimeZoneProvider::CXFA_TimeZoneProvider() { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - if (!g_bProviderTimeZoneSet) { - g_bProviderTimeZoneSet = true; - _tzset(); - } - m_tz.tzHour = (int8_t)(_timezone / 3600 * -1); - m_tz.tzMinute = (int8_t)((FXSYS_abs(_timezone) % 3600) / 60); -#else - if (!g_bProviderTimeZoneSet) { - g_bProviderTimeZoneSet = true; - tzset(); - } - m_tz.tzHour = (int8_t)(timezone / 3600 * -1); - m_tz.tzMinute = (int8_t)((FXSYS_abs((int)timezone) % 3600) / 60); -#endif -} - -CXFA_TimeZoneProvider::~CXFA_TimeZoneProvider() {} - -void CXFA_TimeZoneProvider::GetTimeZone(FX_TIMEZONE* tz) const { - *tz = m_tz; -} diff --git a/xfa/fxfa/parser/xfa_localemgr.h b/xfa/fxfa/parser/xfa_localemgr.h deleted file mode 100644 index eb405dcfc720343e72f7db432e45e575ece05107..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_localemgr.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_XFA_LOCALEMGR_H_ -#define XFA_FXFA_PARSER_XFA_LOCALEMGR_H_ - -#include <memory> -#include <vector> - -#include "xfa/fgas/localization/fgas_datetime.h" -#include "xfa/fgas/localization/fgas_locale.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" - -class CXFA_Node; -class IFX_Locale; - -#define XFA_LANGID_zh_CN 0x0804 -#define XFA_LANGID_zh_TW 0x0404 -#define XFA_LANGID_zh_HK 0x0c04 -#define XFA_LANGID_ja_JP 0x0411 -#define XFA_LANGID_ko_KR 0x0412 -#define XFA_LANGID_en_US 0x0409 -#define XFA_LANGID_en_GB 0x0809 -#define XFA_LANGID_es_ES 0x0c0a -#define XFA_LANGID_es_LA 0x080a -#define XFA_LANGID_de_DE 0x0407 -#define XFA_LANGID_fr_FR 0x040c -#define XFA_LANGID_it_IT 0x0410 -#define XFA_LANGID_pt_BR 0x0416 -#define XFA_LANGID_nl_NL 0x0413 -#define XFA_LANGID_ru_RU 0x0419 - -class CXFA_LocaleMgr : public IFX_LocaleMgr { - public: - CXFA_LocaleMgr(CXFA_Node* pLocaleSet, CFX_WideString wsDeflcid); - ~CXFA_LocaleMgr() override; - - // IFX_LocaleMgr - uint16_t GetDefLocaleID() const override; - IFX_Locale* GetDefLocale() override; - IFX_Locale* GetLocaleByName(const CFX_WideString& wsLocaleName) override; - - void SetDefLocale(IFX_Locale* pLocale); - CFX_WideStringC GetConfigLocaleName(CXFA_Node* pConfig); - - protected: - std::unique_ptr<IFX_Locale> GetLocale(uint16_t lcid) override; - - std::vector<std::unique_ptr<IFX_Locale>> m_LocaleArray; - std::vector<std::unique_ptr<IFX_Locale>> m_XMLLocaleArray; - IFX_Locale* m_pDefLocale; // owned by m_LocaleArray or m_XMLLocaleArray. - CFX_WideString m_wsConfigLocale; - uint16_t m_dwDeflcid; - uint16_t m_dwLocaleFlags; -}; - -class CXFA_TimeZoneProvider { - public: - CXFA_TimeZoneProvider(); - ~CXFA_TimeZoneProvider(); - - void GetTimeZone(FX_TIMEZONE* tz) const; - - private: - FX_TIMEZONE m_tz; -}; - -#endif // XFA_FXFA_PARSER_XFA_LOCALEMGR_H_ diff --git a/xfa/fxfa/parser/xfa_localevalue.cpp b/xfa/fxfa/parser/xfa_localevalue.cpp deleted file mode 100644 index 7e92535c3d57a7125c22b21130dce6768068fcf3..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_localevalue.cpp +++ /dev/null @@ -1,984 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxfa/parser/xfa_localevalue.h" - -#include <vector> - -#include "core/fxcrt/fx_ext.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" -#include "xfa/fgas/localization/fgas_localeimp.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_object.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -static const FX_DOUBLE fraction_scales[] = {0.1, - 0.01, - 0.001, - 0.0001, - 0.00001, - 0.000001, - 0.0000001, - 0.00000001, - 0.000000001, - 0.0000000001, - 0.00000000001, - 0.000000000001, - 0.0000000000001, - 0.00000000000001, - 0.000000000000001, - 0.0000000000000001}; -CXFA_LocaleValue::CXFA_LocaleValue() { - m_dwType = XFA_VT_NULL; - m_bValid = true; - m_pLocaleMgr = nullptr; -} -CXFA_LocaleValue::CXFA_LocaleValue(const CXFA_LocaleValue& value) { - m_dwType = XFA_VT_NULL; - m_bValid = true; - m_pLocaleMgr = nullptr; - *this = value; -} -CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, - CXFA_LocaleMgr* pLocaleMgr) { - m_dwType = dwType; - m_bValid = (m_dwType != XFA_VT_NULL); - m_pLocaleMgr = pLocaleMgr; -} -CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, - const CFX_WideString& wsValue, - CXFA_LocaleMgr* pLocaleMgr) { - m_wsValue = wsValue; - m_dwType = dwType; - m_pLocaleMgr = pLocaleMgr; - m_bValid = ValidateCanonicalValue(wsValue, dwType); -} -CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, - const CFX_WideString& wsValue, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale, - CXFA_LocaleMgr* pLocaleMgr) { - m_pLocaleMgr = pLocaleMgr; - m_bValid = true; - m_dwType = dwType; - m_bValid = ParsePatternValue(wsValue, wsFormat, pLocale); -} -CXFA_LocaleValue& CXFA_LocaleValue::operator=(const CXFA_LocaleValue& value) { - m_wsValue = value.m_wsValue; - m_dwType = value.m_dwType; - m_bValid = value.m_bValid; - m_pLocaleMgr = value.m_pLocaleMgr; - return *this; -} -CXFA_LocaleValue::~CXFA_LocaleValue() {} -static FX_LOCALECATEGORY XFA_ValugeCategory(FX_LOCALECATEGORY eCategory, - uint32_t dwValueType) { - if (eCategory == FX_LOCALECATEGORY_Unknown) { - switch (dwValueType) { - case XFA_VT_BOOLEAN: - case XFA_VT_INTEGER: - case XFA_VT_DECIMAL: - case XFA_VT_FLOAT: - return FX_LOCALECATEGORY_Num; - case XFA_VT_TEXT: - return FX_LOCALECATEGORY_Text; - case XFA_VT_DATE: - return FX_LOCALECATEGORY_Date; - case XFA_VT_TIME: - return FX_LOCALECATEGORY_Time; - case XFA_VT_DATETIME: - return FX_LOCALECATEGORY_DateTime; - } - } - return eCategory; -} - -bool CXFA_LocaleValue::ValidateValue(const CFX_WideString& wsValue, - const CFX_WideString& wsPattern, - IFX_Locale* pLocale, - CFX_WideString* pMatchFormat) { - CFX_WideString wsOutput; - IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); - if (pLocale) - m_pLocaleMgr->SetDefLocale(pLocale); - - auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false); - std::vector<CFX_WideString> wsPatterns; - pFormat->SplitFormatString(wsPattern, wsPatterns); - - bool bRet = false; - int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); - int32_t i = 0; - for (; i < iCount && !bRet; i++) { - CFX_WideString wsFormat = wsPatterns[i]; - FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat); - eCategory = XFA_ValugeCategory(eCategory, m_dwType); - switch (eCategory) { - case FX_LOCALECATEGORY_Null: - bRet = pFormat->ParseNull(wsValue, wsFormat); - if (!bRet) { - bRet = wsValue.IsEmpty(); - } - break; - case FX_LOCALECATEGORY_Zero: - bRet = pFormat->ParseZero(wsValue, wsFormat); - if (!bRet) { - bRet = wsValue == L"0"; - } - break; - case FX_LOCALECATEGORY_Num: { - CFX_WideString fNum; - bRet = pFormat->ParseNum(wsValue, wsFormat, fNum); - if (!bRet) { - bRet = pFormat->FormatNum(wsValue, wsFormat, wsOutput); - } - break; - } - case FX_LOCALECATEGORY_Text: - bRet = pFormat->ParseText(wsValue, wsFormat, wsOutput); - wsOutput.clear(); - if (!bRet) { - bRet = pFormat->FormatText(wsValue, wsFormat, wsOutput); - } - break; - case FX_LOCALECATEGORY_Date: { - CFX_Unitime dt; - bRet = ValidateCanonicalDate(wsValue, dt); - if (!bRet) { - bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, - dt); - if (!bRet) { - bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput, - FX_DATETIMETYPE_Date); - } - } - break; - } - case FX_LOCALECATEGORY_Time: { - CFX_Unitime dt; - bRet = - pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt); - if (!bRet) { - bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput, - FX_DATETIMETYPE_Time); - } - break; - } - case FX_LOCALECATEGORY_DateTime: { - CFX_Unitime dt; - bRet = pFormat->ParseDateTime(wsValue, wsFormat, - FX_DATETIMETYPE_DateTime, dt); - if (!bRet) { - bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput, - FX_DATETIMETYPE_DateTime); - } - break; - } - default: - bRet = false; - break; - } - } - if (bRet && pMatchFormat) - *pMatchFormat = wsPatterns[i - 1]; - - if (pLocale) - m_pLocaleMgr->SetDefLocale(locale); - - return bRet; -} - -CFX_WideString CXFA_LocaleValue::GetValue() const { - return m_wsValue; -} -uint32_t CXFA_LocaleValue::GetType() const { - return m_dwType; -} -void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue, - uint32_t dwType) { - m_wsValue = wsValue; - m_dwType = dwType; -} -CFX_WideString CXFA_LocaleValue::GetText() const { - if (m_bValid && m_dwType == XFA_VT_TEXT) { - return m_wsValue; - } - return CFX_WideString(); -} -FX_FLOAT CXFA_LocaleValue::GetNum() const { - if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER || - m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) { - int64_t nIntegral = 0; - uint32_t dwFractional = 0; - int32_t nExponent = 0; - int cc = 0; - bool bNegative = false, bExpSign = false; - const FX_WCHAR* str = m_wsValue.c_str(); - int len = m_wsValue.GetLength(); - while (FXSYS_iswspace(str[cc]) && cc < len) { - cc++; - } - if (cc >= len) { - return 0; - } - if (str[0] == '+') { - cc++; - } else if (str[0] == '-') { - bNegative = true; - cc++; - } - int nIntegralLen = 0; - while (cc < len) { - if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]) || - nIntegralLen > 17) { - break; - } - nIntegral = nIntegral * 10 + str[cc] - '0'; - cc++; - nIntegralLen++; - } - nIntegral = bNegative ? -nIntegral : nIntegral; - int scale = 0; - double fraction = 0.0; - if (cc < len && str[cc] == '.') { - cc++; - while (cc < len) { - fraction += fraction_scales[scale] * (str[cc] - '0'); - scale++; - cc++; - if (scale == sizeof fraction_scales / sizeof(double) || - !FXSYS_isDecimalDigit(str[cc])) { - break; - } - } - dwFractional = (uint32_t)(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 (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) { - break; - } - nExponent = nExponent * 10 + str[cc] - '0'; - cc++; - } - nExponent = bExpSign ? -nExponent : nExponent; - } - FX_FLOAT fValue = (FX_FLOAT)(dwFractional / 4294967296.0); - fValue = nIntegral + (nIntegral >= 0 ? fValue : -fValue); - if (nExponent != 0) { - fValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); - } - return fValue; - } - return 0; -} -FX_DOUBLE CXFA_LocaleValue::GetDoubleNum() const { - if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER || - m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) { - int64_t nIntegral = 0; - uint32_t dwFractional = 0; - int32_t nExponent = 0; - int32_t cc = 0; - bool bNegative = false, bExpSign = false; - const FX_WCHAR* str = m_wsValue.c_str(); - int len = m_wsValue.GetLength(); - while (FXSYS_iswspace(str[cc]) && cc < len) { - cc++; - } - if (cc >= len) { - return 0; - } - if (str[0] == '+') { - cc++; - } else if (str[0] == '-') { - bNegative = true; - cc++; - } - int32_t nIntegralLen = 0; - while (cc < len) { - if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]) || - nIntegralLen > 17) { - break; - } - nIntegral = nIntegral * 10 + str[cc] - '0'; - cc++; - nIntegralLen++; - } - nIntegral = bNegative ? -nIntegral : nIntegral; - int32_t scale = 0; - FX_DOUBLE fraction = 0.0; - if (cc < len && str[cc] == '.') { - cc++; - while (cc < len) { - fraction += fraction_scales[scale] * (str[cc] - '0'); - scale++; - cc++; - if (scale == sizeof fraction_scales / sizeof(FX_DOUBLE) || - !FXSYS_isDecimalDigit(str[cc])) { - break; - } - } - dwFractional = (uint32_t)(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 (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) { - break; - } - nExponent = nExponent * 10 + str[cc] - '0'; - cc++; - } - nExponent = bExpSign ? -nExponent : nExponent; - } - FX_DOUBLE dValue = (dwFractional / 4294967296.0); - dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); - if (nExponent != 0) { - dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); - } - return dValue; - } - return 0; -} -CFX_Unitime CXFA_LocaleValue::GetDate() const { - if (m_bValid && m_dwType == XFA_VT_DATE) { - CFX_Unitime dt; - FX_DateFromCanonical(m_wsValue, dt); - return dt; - } - return CFX_Unitime(); -} -CFX_Unitime CXFA_LocaleValue::GetTime() const { - if (m_bValid && m_dwType == XFA_VT_TIME) { - CFX_Unitime dt(0); - ASSERT(m_pLocaleMgr); - FX_TimeFromCanonical(m_wsValue.AsStringC(), dt, - m_pLocaleMgr->GetDefLocale()); - return dt; - } - return CFX_Unitime(); -} -CFX_Unitime CXFA_LocaleValue::GetDateTime() const { - if (m_bValid && m_dwType == XFA_VT_DATETIME) { - int32_t index = m_wsValue.Find('T'); - CFX_Unitime dt; - FX_DateFromCanonical(m_wsValue.Left(index), dt); - ASSERT(m_pLocaleMgr); - FX_TimeFromCanonical( - m_wsValue.Right(m_wsValue.GetLength() - index - 1).AsStringC(), dt, - m_pLocaleMgr->GetDefLocale()); - return dt; - } - return CFX_Unitime(); -} -bool CXFA_LocaleValue::SetText(const CFX_WideString& wsText) { - m_dwType = XFA_VT_TEXT; - m_wsValue = wsText; - return true; -} -bool CXFA_LocaleValue::SetText(const CFX_WideString& wsText, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale) { - m_dwType = XFA_VT_TEXT; - return m_bValid = ParsePatternValue(wsText, wsFormat, pLocale); -} -bool CXFA_LocaleValue::SetNum(FX_FLOAT fNum) { - m_dwType = XFA_VT_FLOAT; - m_wsValue.Format(L"%.8g", (FX_DOUBLE)fNum); - return true; -} -bool CXFA_LocaleValue::SetNum(const CFX_WideString& wsNum, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale) { - m_dwType = XFA_VT_FLOAT; - return m_bValid = ParsePatternValue(wsNum, wsFormat, pLocale); -} -bool CXFA_LocaleValue::SetDate(const CFX_Unitime& d) { - m_dwType = XFA_VT_DATE; - m_wsValue.Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(), d.GetDay()); - return true; -} -bool CXFA_LocaleValue::SetDate(const CFX_WideString& wsDate, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale) { - m_dwType = XFA_VT_DATE; - return m_bValid = ParsePatternValue(wsDate, wsFormat, pLocale); -} -bool CXFA_LocaleValue::SetTime(const CFX_Unitime& t) { - m_dwType = XFA_VT_TIME; - m_wsValue.Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(), - t.GetSecond()); - if (t.GetMillisecond() > 0) { - CFX_WideString wsTemp; - wsTemp.Format(L"%:03d", t.GetMillisecond()); - m_wsValue += wsTemp; - } - return true; -} -bool CXFA_LocaleValue::SetTime(const CFX_WideString& wsTime, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale) { - m_dwType = XFA_VT_TIME; - return m_bValid = ParsePatternValue(wsTime, wsFormat, pLocale); -} -bool CXFA_LocaleValue::SetDateTime(const CFX_Unitime& dt) { - m_dwType = XFA_VT_DATETIME; - m_wsValue.Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(), - dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute(), - dt.GetSecond()); - if (dt.GetMillisecond() > 0) { - CFX_WideString wsTemp; - wsTemp.Format(L"%:03d", dt.GetMillisecond()); - m_wsValue += wsTemp; - } - return true; -} -bool CXFA_LocaleValue::SetDateTime(const CFX_WideString& wsDateTime, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale) { - m_dwType = XFA_VT_DATETIME; - return m_bValid = ParsePatternValue(wsDateTime, wsFormat, pLocale); -} - -bool CXFA_LocaleValue::FormatPatterns(CFX_WideString& wsResult, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale, - XFA_VALUEPICTURE eValueType) const { - auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false); - std::vector<CFX_WideString> wsPatterns; - pFormat->SplitFormatString(wsFormat, wsPatterns); - wsResult.clear(); - int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); - for (int32_t i = 0; i < iCount; i++) { - if (FormatSinglePattern(wsResult, wsPatterns[i], pLocale, eValueType)) - return true; - } - return false; -} - -bool CXFA_LocaleValue::FormatSinglePattern(CFX_WideString& wsResult, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale, - XFA_VALUEPICTURE eValueType) const { - IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); - if (pLocale) - m_pLocaleMgr->SetDefLocale(pLocale); - - wsResult.clear(); - bool bRet = false; - auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false); - FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat); - eCategory = XFA_ValugeCategory(eCategory, m_dwType); - switch (eCategory) { - case FX_LOCALECATEGORY_Null: - if (m_wsValue.IsEmpty()) { - bRet = pFormat->FormatNull(wsFormat, wsResult); - } - break; - case FX_LOCALECATEGORY_Zero: - if (m_wsValue == L"0") { - bRet = pFormat->FormatZero(wsFormat, wsResult); - } - break; - case FX_LOCALECATEGORY_Num: - bRet = pFormat->FormatNum(m_wsValue, wsFormat, wsResult); - break; - case FX_LOCALECATEGORY_Text: - bRet = pFormat->FormatText(m_wsValue, wsFormat, wsResult); - break; - case FX_LOCALECATEGORY_Date: - bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult, - FX_DATETIMETYPE_Date); - break; - case FX_LOCALECATEGORY_Time: - bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult, - FX_DATETIMETYPE_Time); - break; - case FX_LOCALECATEGORY_DateTime: - bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult, - FX_DATETIMETYPE_DateTime); - break; - default: - wsResult = m_wsValue; - bRet = true; - } - if (!bRet && (eCategory != FX_LOCALECATEGORY_Num || - eValueType != XFA_VALUEPICTURE_Display)) { - wsResult = m_wsValue; - } - if (pLocale) - m_pLocaleMgr->SetDefLocale(locale); - - return bRet; -} - -static bool XFA_ValueSplitDateTime(const CFX_WideString& wsDateTime, - CFX_WideString& wsDate, - CFX_WideString& wsTime) { - wsDate = L""; - wsTime = L""; - if (wsDateTime.IsEmpty()) { - return false; - } - int nSplitIndex = -1; - nSplitIndex = wsDateTime.Find('T'); - if (nSplitIndex < 0) { - nSplitIndex = wsDateTime.Find(' '); - } - if (nSplitIndex < 0) { - return false; - } - wsDate = wsDateTime.Left(nSplitIndex); - wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1); - return true; -} -bool CXFA_LocaleValue::ValidateCanonicalValue(const CFX_WideString& wsValue, - uint32_t dwVType) { - if (wsValue.IsEmpty()) { - return true; - } - CFX_Unitime dt; - switch (dwVType) { - case XFA_VT_DATE: { - if (ValidateCanonicalDate(wsValue, dt)) { - return true; - } - CFX_WideString wsDate, wsTime; - if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) && - ValidateCanonicalDate(wsDate, dt)) { - return true; - } - return false; - } - case XFA_VT_TIME: { - if (ValidateCanonicalTime(wsValue)) { - return true; - } - CFX_WideString wsDate, wsTime; - if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) && - ValidateCanonicalTime(wsTime)) { - return true; - } - return false; - } - case XFA_VT_DATETIME: { - CFX_WideString wsDate, wsTime; - if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) && - ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime)) { - return true; - } - } break; - } - return true; -} -bool CXFA_LocaleValue::ValidateCanonicalDate(const CFX_WideString& wsDate, - CFX_Unitime& unDate) { - const uint16_t LastDay[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - const uint16_t wCountY = 4, wCountM = 2, wCountD = 2; - int nLen = wsDate.GetLength(); - if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) { - return false; - } - const bool bSymbol = wsDate.Find(0x2D) != -1; - uint16_t wYear = 0; - uint16_t wMonth = 0; - uint16_t wDay = 0; - const FX_WCHAR* pDate = wsDate.c_str(); - int nIndex = 0, nStart = 0; - while (pDate[nIndex] != '\0' && nIndex < wCountY) { - if (!FXSYS_isDecimalDigit(pDate[nIndex])) { - return false; - } - wYear = (pDate[nIndex] - '0') + wYear * 10; - nIndex++; - } - if (bSymbol) { - if (pDate[nIndex] != 0x2D) { - return false; - } - nIndex++; - } - nStart = nIndex; - while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) { - if (!FXSYS_isDecimalDigit(pDate[nIndex])) { - return false; - } - wMonth = (pDate[nIndex] - '0') + wMonth * 10; - nIndex++; - } - if (bSymbol) { - if (pDate[nIndex] != 0x2D) { - return false; - } - nIndex++; - } - nStart = nIndex; - while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) { - if (!FXSYS_isDecimalDigit(pDate[nIndex])) { - return false; - } - wDay = (pDate[nIndex] - '0') + wDay * 10; - nIndex++; - } - if (nIndex != nLen) { - return false; - } - if (wYear < 1900 || wYear > 2029) { - return false; - } - if (wMonth < 1 || wMonth > 12) { - if (wMonth == 0 && nLen == wCountY) { - return true; - } - return false; - } - if (wDay < 1) { - if (wDay == 0 && (nLen == wCountY + wCountM)) { - return true; - } - return false; - } - if (wMonth == 2) { - if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) { - if (wDay > 29) { - return false; - } - } else { - if (wDay > 28) { - return false; - } - } - } else if (wDay > LastDay[wMonth - 1]) { - return false; - } - CFX_Unitime ut; - ut.Set(wYear, static_cast<uint8_t>(wMonth), static_cast<uint8_t>(wDay)); - unDate = unDate + ut; - return true; -} -bool CXFA_LocaleValue::ValidateCanonicalTime(const CFX_WideString& wsTime) { - int nLen = wsTime.GetLength(); - if (nLen < 2) - return false; - const uint16_t wCountH = 2; - const uint16_t wCountM = 2; - const uint16_t wCountS = 2; - const uint16_t wCountF = 3; - const bool bSymbol = wsTime.Find(':') != -1; - uint16_t wHour = 0; - uint16_t wMinute = 0; - uint16_t wSecond = 0; - uint16_t wFraction = 0; - const FX_WCHAR* pTime = wsTime.c_str(); - int nIndex = 0; - int nStart = 0; - while (nIndex - nStart < wCountH && pTime[nIndex]) { - if (!FXSYS_isDecimalDigit(pTime[nIndex])) - return false; - wHour = pTime[nIndex] - '0' + wHour * 10; - nIndex++; - } - if (bSymbol) { - if (nIndex < nLen && pTime[nIndex] != ':') - return false; - nIndex++; - } - nStart = nIndex; - while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) { - if (!FXSYS_isDecimalDigit(pTime[nIndex])) - return false; - wMinute = pTime[nIndex] - '0' + wMinute * 10; - nIndex++; - } - if (bSymbol) { - if (nIndex < nLen && pTime[nIndex] != ':') - return false; - nIndex++; - } - nStart = nIndex; - while (nIndex - nStart < wCountS && nIndex < nLen && pTime[nIndex]) { - if (!FXSYS_isDecimalDigit(pTime[nIndex])) - return false; - wSecond = pTime[nIndex] - '0' + wSecond * 10; - nIndex++; - } - if (wsTime.Find('.') > 0) { - if (pTime[nIndex] != '.') - return false; - nIndex++; - nStart = nIndex; - while (nIndex - nStart < wCountF && nIndex < nLen && pTime[nIndex]) { - if (!FXSYS_isDecimalDigit(pTime[nIndex])) - return false; - wFraction = pTime[nIndex] - '0' + wFraction * 10; - nIndex++; - } - } - if (nIndex < nLen) { - if (pTime[nIndex] == 'Z') { - nIndex++; - } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') { - int16_t nOffsetH = 0; - int16_t nOffsetM = 0; - nIndex++; - nStart = nIndex; - while (nIndex - nStart < wCountH && nIndex < nLen && pTime[nIndex]) { - if (!FXSYS_isDecimalDigit(pTime[nIndex])) - return false; - nOffsetH = pTime[nIndex] - '0' + nOffsetH * 10; - nIndex++; - } - if (bSymbol) { - if (nIndex < nLen && pTime[nIndex] != ':') - return false; - nIndex++; - } - nStart = nIndex; - while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) { - if (!FXSYS_isDecimalDigit(pTime[nIndex])) - return false; - nOffsetM = pTime[nIndex] - '0' + nOffsetM * 10; - nIndex++; - } - if (nOffsetH > 12 || nOffsetM >= 60) - return false; - } - } - return nIndex == nLen && wHour < 24 && wMinute < 60 && wSecond < 60 && - wFraction <= 999; -} -bool CXFA_LocaleValue::ValidateCanonicalDateTime( - const CFX_WideString& wsDateTime) { - CFX_WideString wsDate, wsTime; - if (wsDateTime.IsEmpty()) { - return false; - } - int nSplitIndex = -1; - nSplitIndex = wsDateTime.Find('T'); - if (nSplitIndex < 0) { - nSplitIndex = wsDateTime.Find(' '); - } - if (nSplitIndex < 0) { - return false; - } - wsDate = wsDateTime.Left(nSplitIndex); - wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1); - CFX_Unitime dt; - return ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime); -} -bool CXFA_LocaleValue::ParsePatternValue(const CFX_WideString& wsValue, - const CFX_WideString& wsPattern, - IFX_Locale* pLocale) { - IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); - if (pLocale) - m_pLocaleMgr->SetDefLocale(pLocale); - - auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false); - std::vector<CFX_WideString> wsPatterns; - pFormat->SplitFormatString(wsPattern, wsPatterns); - bool bRet = false; - int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); - for (int32_t i = 0; i < iCount && !bRet; i++) { - CFX_WideString wsFormat = wsPatterns[i]; - FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat); - eCategory = XFA_ValugeCategory(eCategory, m_dwType); - switch (eCategory) { - case FX_LOCALECATEGORY_Null: - bRet = pFormat->ParseNull(wsValue, wsFormat); - if (bRet) { - m_wsValue.clear(); - } - break; - case FX_LOCALECATEGORY_Zero: - bRet = pFormat->ParseZero(wsValue, wsFormat); - if (bRet) - m_wsValue = L"0"; - break; - case FX_LOCALECATEGORY_Num: { - CFX_WideString fNum; - bRet = pFormat->ParseNum(wsValue, wsFormat, fNum); - if (bRet) { - m_wsValue = fNum; - } - break; - } - case FX_LOCALECATEGORY_Text: - bRet = pFormat->ParseText(wsValue, wsFormat, m_wsValue); - break; - case FX_LOCALECATEGORY_Date: { - CFX_Unitime dt; - bRet = ValidateCanonicalDate(wsValue, dt); - if (!bRet) { - bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, - dt); - } - if (bRet) { - SetDate(dt); - } - break; - } - case FX_LOCALECATEGORY_Time: { - CFX_Unitime dt; - bRet = - pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt); - if (bRet) { - SetTime(dt); - } - break; - } - case FX_LOCALECATEGORY_DateTime: { - CFX_Unitime dt; - bRet = pFormat->ParseDateTime(wsValue, wsFormat, - FX_DATETIMETYPE_DateTime, dt); - if (bRet) { - SetDateTime(dt); - } - break; - } - default: - m_wsValue = wsValue; - bRet = true; - break; - } - } - if (!bRet) - m_wsValue = wsValue; - - if (pLocale) - m_pLocaleMgr->SetDefLocale(locale); - - return bRet; -} - -void CXFA_LocaleValue::GetNumbericFormat(CFX_WideString& wsFormat, - int32_t nIntLen, - int32_t nDecLen, - bool bSign) { - ASSERT(wsFormat.IsEmpty()); - ASSERT(nIntLen >= -1 && nDecLen >= -1); - int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + (bSign ? 1 : 0) + - (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1); - FX_WCHAR* lpBuf = wsFormat.GetBuffer(nTotalLen); - int32_t nPos = 0; - if (bSign) { - lpBuf[nPos++] = L's'; - } - if (nIntLen == -1) { - lpBuf[nPos++] = L'z'; - lpBuf[nPos++] = L'*'; - } else { - while (nIntLen) { - lpBuf[nPos++] = L'z'; - nIntLen--; - } - } - if (nDecLen != 0) { - lpBuf[nPos++] = L'.'; - } - if (nDecLen == -1) { - lpBuf[nPos++] = L'z'; - lpBuf[nPos++] = L'*'; - } else { - while (nDecLen) { - lpBuf[nPos++] = L'z'; - nDecLen--; - } - } - wsFormat.ReleaseBuffer(nTotalLen); -} -bool CXFA_LocaleValue::ValidateNumericTemp(CFX_WideString& wsNumeric, - CFX_WideString& wsFormat, - IFX_Locale* pLocale, - int32_t* pos) { - if (wsFormat.IsEmpty() || wsNumeric.IsEmpty()) { - return true; - } - const FX_WCHAR* pNum = wsNumeric.c_str(); - const FX_WCHAR* pFmt = wsFormat.c_str(); - int32_t n = 0, nf = 0; - FX_WCHAR c = pNum[n]; - FX_WCHAR cf = pFmt[nf]; - if (cf == L's') { - if (c == L'-' || c == L'+') { - ++n; - } - ++nf; - } - bool bLimit = true; - int32_t nCount = wsNumeric.GetLength(); - int32_t nCountFmt = wsFormat.GetLength(); - while (n < nCount && (bLimit ? nf < nCountFmt : true) && - FXSYS_isDecimalDigit(c = pNum[n])) { - if (bLimit == true) { - if ((cf = pFmt[nf]) == L'*') { - bLimit = false; - } else if (cf == L'z') { - nf++; - } else { - return false; - } - } - n++; - } - if (n == nCount) { - return true; - } - if (nf == nCountFmt) { - return false; - } - while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') { - ASSERT(cf == L'z' || cf == L'*'); - ++nf; - } - CFX_WideString wsDecimalSymbol; - if (pLocale) { - pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDecimalSymbol); - } else { - wsDecimalSymbol = CFX_WideString(L'.'); - } - if (pFmt[nf] != L'.') { - return false; - } - if (wsDecimalSymbol != CFX_WideStringC(c) && c != L'.') { - return false; - } - ++nf; - ++n; - bLimit = true; - while (n < nCount && (bLimit ? nf < nCountFmt : true) && - FXSYS_isDecimalDigit(c = pNum[n])) { - if (bLimit == true) { - if ((cf = pFmt[nf]) == L'*') { - bLimit = false; - } else if (cf == L'z') { - nf++; - } else { - return false; - } - } - n++; - } - return n == nCount; -} diff --git a/xfa/fxfa/parser/xfa_localevalue.h b/xfa/fxfa/parser/xfa_localevalue.h deleted file mode 100644 index dbc3513a3f34edb986fde2825772c1753c65e0a6..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_localevalue.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_XFA_LOCALEVALUE_H_ -#define XFA_FXFA_PARSER_XFA_LOCALEVALUE_H_ - -#include "core/fxcrt/fx_string.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxfa/parser/cxfa_widgetdata.h" - -class IFX_Locale; -class CFX_Unitime; -class CXFA_LocaleMgr; - -#define XFA_VT_NULL 0 -#define XFA_VT_BOOLEAN 1 -#define XFA_VT_INTEGER 2 -#define XFA_VT_DECIMAL 4 -#define XFA_VT_FLOAT 8 -#define XFA_VT_TEXT 16 -#define XFA_VT_DATE 32 -#define XFA_VT_TIME 64 -#define XFA_VT_DATETIME 128 - -class CXFA_LocaleValue { - public: - CXFA_LocaleValue(); - CXFA_LocaleValue(const CXFA_LocaleValue& value); - CXFA_LocaleValue(uint32_t dwType, CXFA_LocaleMgr* pLocaleMgr); - CXFA_LocaleValue(uint32_t dwType, - const CFX_WideString& wsValue, - CXFA_LocaleMgr* pLocaleMgr); - CXFA_LocaleValue(uint32_t dwType, - const CFX_WideString& wsValue, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale, - CXFA_LocaleMgr* pLocaleMgr); - ~CXFA_LocaleValue(); - CXFA_LocaleValue& operator=(const CXFA_LocaleValue& value); - - bool ValidateValue(const CFX_WideString& wsValue, - const CFX_WideString& wsPattern, - IFX_Locale* pLocale, - CFX_WideString* pMatchFormat = nullptr); - bool FormatPatterns(CFX_WideString& wsResult, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale, - XFA_VALUEPICTURE eValueType) const; - bool FormatSinglePattern(CFX_WideString& wsResult, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale, - XFA_VALUEPICTURE eValueType) const; - bool ValidateCanonicalValue(const CFX_WideString& wsValue, uint32_t dwVType); - bool ValidateCanonicalDate(const CFX_WideString& wsDate, CFX_Unitime& unDate); - bool ValidateCanonicalTime(const CFX_WideString& wsTime); - bool ValidateCanonicalDateTime(const CFX_WideString& wsDateTime); - void GetNumbericFormat(CFX_WideString& wsFormat, - int32_t nIntLen, - int32_t nDecLen, - bool bSign = true); - bool ValidateNumericTemp(CFX_WideString& wsNumeric, - CFX_WideString& wsFormat, - IFX_Locale* pLocale = nullptr, - int32_t* pos = nullptr); - - CFX_WideString GetValue() const; - uint32_t GetType() const; - void SetValue(const CFX_WideString& wsValue, uint32_t dwType); - CFX_WideString GetText() const; - FX_FLOAT GetNum() const; - FX_DOUBLE GetDoubleNum() const; - CFX_Unitime GetDate() const; - CFX_Unitime GetTime() const; - CFX_Unitime GetDateTime() const; - bool SetText(const CFX_WideString& wsText); - bool SetText(const CFX_WideString& wsText, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale); - bool SetNum(FX_FLOAT fNum); - bool SetNum(const CFX_WideString& wsNum, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale); - bool SetDate(const CFX_Unitime& d); - bool SetDate(const CFX_WideString& wsDate, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale); - bool SetTime(const CFX_Unitime& t); - bool SetTime(const CFX_WideString& wsTime, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale); - bool SetDateTime(const CFX_Unitime& dt); - bool SetDateTime(const CFX_WideString& wsDateTime, - const CFX_WideString& wsFormat, - IFX_Locale* pLocale); - bool IsNull() const { return m_dwType == XFA_VT_NULL; } - bool IsEmpty() const { return m_wsValue.IsEmpty(); } - bool IsValid() const { return m_bValid; } - - protected: - bool ParsePatternValue(const CFX_WideString& wsValue, - const CFX_WideString& wsPattern, - IFX_Locale* pLocale); - CXFA_LocaleMgr* m_pLocaleMgr; - CFX_WideString m_wsValue; - uint32_t m_dwType; - bool m_bValid; -}; - -#endif // XFA_FXFA_PARSER_XFA_LOCALEVALUE_H_ diff --git a/xfa/fxfa/parser/xfa_object.h b/xfa/fxfa/parser/xfa_object.h deleted file mode 100644 index cc116505e0a00610e7e2761c64ac35613840ba82..0000000000000000000000000000000000000000 --- a/xfa/fxfa/parser/xfa_object.h +++ /dev/null @@ -1,823 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_PARSER_XFA_OBJECT_H_ -#define XFA_FXFA_PARSER_XFA_OBJECT_H_ - -#include <map> -#include <unordered_set> - -#include "fxjs/cfxjse_arguments.h" -#include "xfa/fde/xml/fde_xml.h" -#include "xfa/fxfa/parser/xfa_utils.h" - -class CXFA_Document; -class CXFA_Node; -class CXFA_NodeList; - -enum class XFA_ObjectType { - Object, - List, - NodeList, - Node, - NodeC, - NodeV, - ModelNode, - TextNode, - ContainerNode, - ContentNode, - VariablesThis -}; - -enum XFA_NodeFlag { - XFA_NodeFlag_None = 0, - XFA_NodeFlag_Initialized = 1 << 0, - XFA_NodeFlag_HasRemovedChildren = 1 << 1, - XFA_NodeFlag_NeedsInitApp = 1 << 2, - XFA_NodeFlag_BindFormItems = 1 << 3, - XFA_NodeFlag_UserInteractive = 1 << 4, - XFA_NodeFlag_SkipDataBinding = 1 << 5, - XFA_NodeFlag_OwnXMLNode = 1 << 6, - XFA_NodeFlag_UnusedNode = 1 << 7, - XFA_NodeFlag_LayoutGeneratedNode = 1 << 8 -}; - -class CXFA_Object : public CFXJSE_HostObject { - public: - CXFA_Object(CXFA_Document* pDocument, - XFA_ObjectType objectType, - XFA_Element eType, - const CFX_WideStringC& elementName); - ~CXFA_Object() override; - - CXFA_Document* GetDocument() const { return m_pDocument; } - XFA_ObjectType GetObjectType() const { return m_objectType; } - - bool IsNode() const { - return m_objectType == XFA_ObjectType::Node || - m_objectType == XFA_ObjectType::NodeC || - m_objectType == XFA_ObjectType::NodeV || - m_objectType == XFA_ObjectType::ModelNode || - m_objectType == XFA_ObjectType::TextNode || - m_objectType == XFA_ObjectType::ContainerNode || - m_objectType == XFA_ObjectType::ContentNode || - m_objectType == XFA_ObjectType::VariablesThis; - } - bool IsNodeList() const { return m_objectType == XFA_ObjectType::NodeList; } - bool IsContentNode() const { - return m_objectType == XFA_ObjectType::ContentNode; - } - bool IsContainerNode() const { - return m_objectType == XFA_ObjectType::ContainerNode; - } - bool IsModelNode() const { return m_objectType == XFA_ObjectType::ModelNode; } - bool IsNodeV() const { return m_objectType == XFA_ObjectType::NodeV; } - bool IsVariablesThis() const { - return m_objectType == XFA_ObjectType::VariablesThis; - } - - CXFA_Node* AsNode(); - CXFA_NodeList* AsNodeList(); - - const CXFA_Node* AsNode() const; - const CXFA_NodeList* AsNodeList() const; - - XFA_Element GetElementType() const; - CFX_WideStringC GetClassName() const; - uint32_t GetClassHashCode() const; - void Script_ObjectClass_ClassName(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - - void ThrowInvalidPropertyException() const; - void ThrowArgumentMismatchException() const; - void ThrowIndexOutOfBoundsException() const; - void ThrowParamCountMismatchException(const CFX_WideString& method) const; - - protected: - void ThrowException(const FX_WCHAR* str, ...) const; - - CXFA_Document* const m_pDocument; - const XFA_ObjectType m_objectType; - const XFA_Element m_elementType; - - const uint32_t m_elementNameHash; - const CFX_WideStringC m_elementName; -}; -using CXFA_ObjArray = CFX_ArrayTemplate<CXFA_Object*>; - -#define XFA_NODEFILTER_Children 0x01 -#define XFA_NODEFILTER_Properties 0x02 -#define XFA_NODEFILTER_OneOfProperty 0x04 -#define XFA_CLONEFLAG_Content 0x01 -enum XFA_NODEITEM { - XFA_NODEITEM_Parent, - XFA_NODEITEM_FirstChild, - XFA_NODEITEM_NextSibling, - XFA_NODEITEM_PrevSibling, -}; -enum XFA_SOM_MESSAGETYPE { - XFA_SOM_ValidationMessage, - XFA_SOM_FormatMessage, - XFA_SOM_MandatoryMessage -}; - -using CXFA_NodeArray = CFX_ArrayTemplate<CXFA_Node*>; -using CXFA_NodeStack = CFX_StackTemplate<CXFA_Node*>; -using CXFA_NodeSet = std::unordered_set<CXFA_Node*>; - -typedef void (*PD_CALLBACK_FREEDATA)(void* pData); -typedef void (*PD_CALLBACK_DUPLICATEDATA)(void*& pData); - -struct XFA_MAPDATABLOCKCALLBACKINFO { - PD_CALLBACK_FREEDATA pFree; - PD_CALLBACK_DUPLICATEDATA pCopy; -}; - -struct XFA_MAPDATABLOCK { - uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); } - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo; - int32_t iBytes; -}; - -struct XFA_MAPMODULEDATA { - XFA_MAPMODULEDATA(); - ~XFA_MAPMODULEDATA(); - - std::map<void*, void*> m_ValueMap; - std::map<void*, XFA_MAPDATABLOCK*> m_BufferMap; -}; - -#define XFA_CalcRefCount (void*)(uintptr_t) FXBSTR_ID('X', 'F', 'A', 'R') -#define XFA_CalcData (void*)(uintptr_t) FXBSTR_ID('X', 'F', 'A', 'C') -#define XFA_LAYOUTITEMKEY (void*)(uintptr_t) FXBSTR_ID('L', 'Y', 'I', 'M') - -class CXFA_Node : public CXFA_Object { - public: - uint32_t GetPacketID() const { return m_ePacket; } - - void SetFlag(uint32_t dwFlag, bool bNotify); - void ClearFlag(uint32_t dwFlag); - - bool IsInitialized() const { return HasFlag(XFA_NodeFlag_Initialized); } - bool IsOwnXMLNode() const { return HasFlag(XFA_NodeFlag_OwnXMLNode); } - bool IsUserInteractive() const { - return HasFlag(XFA_NodeFlag_UserInteractive); - } - bool IsUnusedNode() const { return HasFlag(XFA_NodeFlag_UnusedNode); } - bool IsLayoutGeneratedNode() const { - return HasFlag(XFA_NodeFlag_LayoutGeneratedNode); - } - bool BindsFormItems() const { return HasFlag(XFA_NodeFlag_BindFormItems); } - bool HasRemovedChildren() const { - return HasFlag(XFA_NodeFlag_HasRemovedChildren); - } - bool NeedsInitApp() const { return HasFlag(XFA_NodeFlag_NeedsInitApp); } - - bool IsAttributeInXML(); - bool IsFormContainer() const { - return m_ePacket == XFA_XDPPACKET_Form && IsContainerNode(); - } - void SetXMLMappingNode(CFDE_XMLNode* pXMLNode) { m_pXMLNode = pXMLNode; } - CFDE_XMLNode* GetXMLMappingNode() const { return m_pXMLNode; } - CFDE_XMLNode* CreateXMLMappingNode(); - bool IsNeedSavingXMLNode(); - uint32_t GetNameHash() const { return m_dwNameHash; } - bool IsUnnamed() const { return m_dwNameHash == 0; } - CXFA_Node* GetModelNode(); - void UpdateNameHash(); - bool HasAttribute(XFA_ATTRIBUTE eAttr, bool bCanInherit = false); - bool SetAttribute(XFA_ATTRIBUTE eAttr, - const CFX_WideStringC& wsValue, - bool bNotify = false); - bool GetAttribute(XFA_ATTRIBUTE eAttr, - CFX_WideString& wsValue, - bool bUseDefault = true); - bool SetAttribute(const CFX_WideStringC& wsAttr, - const CFX_WideStringC& wsValue, - bool bNotify = false); - bool GetAttribute(const CFX_WideStringC& wsAttr, - CFX_WideString& wsValue, - bool bUseDefault = true); - bool RemoveAttribute(const CFX_WideStringC& wsAttr); - bool SetContent(const CFX_WideString& wsContent, - const CFX_WideString& wsXMLValue, - bool bNotify = false, - bool bScriptModify = false, - bool bSyncData = true); - bool TryContent(CFX_WideString& wsContent, - bool bScriptModify = false, - bool bProto = true); - CFX_WideString GetContent(); - - bool TryNamespace(CFX_WideString& wsNamespace); - - bool SetBoolean(XFA_ATTRIBUTE eAttr, bool bValue, bool bNotify = false) { - return SetValue(eAttr, XFA_ATTRIBUTETYPE_Boolean, (void*)(uintptr_t)bValue, - bNotify); - } - bool TryBoolean(XFA_ATTRIBUTE eAttr, bool& bValue, bool bUseDefault = true); - bool GetBoolean(XFA_ATTRIBUTE eAttr) { - bool bValue; - return TryBoolean(eAttr, bValue, true) ? bValue : false; - } - bool SetInteger(XFA_ATTRIBUTE eAttr, int32_t iValue, bool bNotify = false) { - return SetValue(eAttr, XFA_ATTRIBUTETYPE_Integer, (void*)(uintptr_t)iValue, - bNotify); - } - bool TryInteger(XFA_ATTRIBUTE eAttr, - int32_t& iValue, - bool bUseDefault = true); - int32_t GetInteger(XFA_ATTRIBUTE eAttr) { - int32_t iValue; - return TryInteger(eAttr, iValue, true) ? iValue : 0; - } - bool SetEnum(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTEENUM eValue, - bool bNotify = false) { - return SetValue(eAttr, XFA_ATTRIBUTETYPE_Enum, (void*)(uintptr_t)eValue, - bNotify); - } - bool TryEnum(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTEENUM& eValue, - bool bUseDefault = true); - XFA_ATTRIBUTEENUM GetEnum(XFA_ATTRIBUTE eAttr) { - XFA_ATTRIBUTEENUM eValue; - return TryEnum(eAttr, eValue, true) ? eValue : XFA_ATTRIBUTEENUM_Unknown; - } - bool SetCData(XFA_ATTRIBUTE eAttr, - const CFX_WideString& wsValue, - bool bNotify = false, - bool bScriptModify = false); - bool SetAttributeValue(const CFX_WideString& wsValue, - const CFX_WideString& wsXMLValue, - bool bNotify = false, - bool bScriptModify = false); - bool TryCData(XFA_ATTRIBUTE eAttr, - CFX_WideString& wsValue, - bool bUseDefault = true, - bool bProto = true); - bool TryCData(XFA_ATTRIBUTE eAttr, - CFX_WideStringC& wsValue, - bool bUseDefault = true, - bool bProto = true); - CFX_WideStringC GetCData(XFA_ATTRIBUTE eAttr) { - CFX_WideStringC wsValue; - return TryCData(eAttr, wsValue) ? wsValue : CFX_WideStringC(); - } - bool SetMeasure(XFA_ATTRIBUTE eAttr, - CXFA_Measurement mValue, - bool bNotify = false); - bool TryMeasure(XFA_ATTRIBUTE eAttr, - CXFA_Measurement& mValue, - bool bUseDefault = true) const; - CXFA_Measurement GetMeasure(XFA_ATTRIBUTE eAttr) const; - bool SetObject(XFA_ATTRIBUTE eAttr, - void* pData, - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo = nullptr); - bool TryObject(XFA_ATTRIBUTE eAttr, void*& pData); - void* GetObject(XFA_ATTRIBUTE eAttr) { - void* pData; - return TryObject(eAttr, pData) ? pData : nullptr; - } - bool SetUserData(void* pKey, - void* pData, - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo = nullptr); - bool TryUserData(void* pKey, void*& pData, bool bProtoAlso = false); - void* GetUserData(void* pKey, bool bProtoAlso = false) { - void* pData; - return TryUserData(pKey, pData, bProtoAlso) ? pData : nullptr; - } - CXFA_Node* GetProperty(int32_t index, - XFA_Element eType, - bool bCreateProperty = true); - int32_t CountChildren(XFA_Element eType, bool bOnlyChild = false); - CXFA_Node* GetChild(int32_t index, - XFA_Element eType, - bool bOnlyChild = false); - int32_t InsertChild(int32_t index, CXFA_Node* pNode); - bool InsertChild(CXFA_Node* pNode, CXFA_Node* pBeforeNode = nullptr); - bool RemoveChild(CXFA_Node* pNode, bool bNotify = true); - CXFA_Node* Clone(bool bRecursive); - CXFA_Node* GetNodeItem(XFA_NODEITEM eItem) const; - CXFA_Node* GetNodeItem(XFA_NODEITEM eItem, XFA_ObjectType eType) const; - int32_t GetNodeList(CXFA_NodeArray& nodes, - uint32_t dwTypeFilter = XFA_NODEFILTER_Children | - XFA_NODEFILTER_Properties, - XFA_Element eTypeFilter = XFA_Element::Unknown, - int32_t iLevel = 1); - CXFA_Node* CreateSamePacketNode(XFA_Element eType, - uint32_t dwFlags = XFA_NodeFlag_Initialized); - CXFA_Node* CloneTemplateToForm(bool bRecursive); - CXFA_Node* GetTemplateNode() const; - void SetTemplateNode(CXFA_Node* pTemplateNode); - CXFA_Node* GetDataDescriptionNode(); - void SetDataDescriptionNode(CXFA_Node* pDataDescriptionNode); - CXFA_Node* GetBindData(); - int32_t GetBindItems(CXFA_NodeArray& formItems); - int32_t AddBindItem(CXFA_Node* pFormNode); - int32_t RemoveBindItem(CXFA_Node* pFormNode); - bool HasBindItem(); - CXFA_WidgetData* GetWidgetData(); - CXFA_WidgetData* GetContainerWidgetData(); - bool GetLocaleName(CFX_WideString& wsLocaleName); - XFA_ATTRIBUTEENUM GetIntact(); - CXFA_Node* GetFirstChildByName(const CFX_WideStringC& wsNodeName) const; - CXFA_Node* GetFirstChildByName(uint32_t dwNodeNameHash) const; - CXFA_Node* GetFirstChildByClass(XFA_Element eType) const; - CXFA_Node* GetNextSameNameSibling(uint32_t dwNodeNameHash) const; - CXFA_Node* GetNextSameNameSibling(const CFX_WideStringC& wsNodeName) const; - CXFA_Node* GetNextSameClassSibling(XFA_Element eType) const; - int32_t GetNodeSameNameIndex() const; - int32_t GetNodeSameClassIndex() const; - void GetSOMExpression(CFX_WideString& wsSOMExpression); - CXFA_Node* GetInstanceMgrOfSubform(); - - CXFA_Node* GetOccurNode(); - void Script_TreeClass_ResolveNode(CFXJSE_Arguments* pArguments); - void Script_TreeClass_ResolveNodes(CFXJSE_Arguments* pArguments); - void Script_Som_ResolveNodeList(CFXJSE_Value* pValue, - CFX_WideString wsExpression, - uint32_t dwFlag, - CXFA_Node* refNode = nullptr); - void Script_TreeClass_All(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_TreeClass_Nodes(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_TreeClass_ClassAll(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_TreeClass_Parent(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_TreeClass_Index(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_TreeClass_ClassIndex(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_TreeClass_SomExpression(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_NodeClass_ApplyXSL(CFXJSE_Arguments* pArguments); - void Script_NodeClass_AssignNode(CFXJSE_Arguments* pArguments); - void Script_NodeClass_Clone(CFXJSE_Arguments* pArguments); - void Script_NodeClass_GetAttribute(CFXJSE_Arguments* pArguments); - void Script_NodeClass_GetElement(CFXJSE_Arguments* pArguments); - void Script_NodeClass_IsPropertySpecified(CFXJSE_Arguments* pArguments); - void Script_NodeClass_LoadXML(CFXJSE_Arguments* pArguments); - void Script_NodeClass_SaveFilteredXML(CFXJSE_Arguments* pArguments); - void Script_NodeClass_SaveXML(CFXJSE_Arguments* pArguments); - void Script_NodeClass_SetAttribute(CFXJSE_Arguments* pArguments); - void Script_NodeClass_SetElement(CFXJSE_Arguments* pArguments); - void Script_NodeClass_Ns(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_NodeClass_Model(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_NodeClass_IsContainer(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_NodeClass_IsNull(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_NodeClass_OneOfChild(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_ContainerClass_GetDelta(CFXJSE_Arguments* pArguments); - void Script_ContainerClass_GetDeltas(CFXJSE_Arguments* pArguments); - void Script_ModelClass_ClearErrorList(CFXJSE_Arguments* pArguments); - void Script_ModelClass_CreateNode(CFXJSE_Arguments* pArguments); - void Script_ModelClass_IsCompatibleNS(CFXJSE_Arguments* pArguments); - void Script_ModelClass_Context(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_ModelClass_AliasNode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_WsdlConnection_Execute(CFXJSE_Arguments* pArguments); - void Script_Delta_Restore(CFXJSE_Arguments* pArguments); - void Script_Delta_CurrentValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Delta_SavedValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Delta_Target(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Attribute_SendAttributeChangeMessage(XFA_ATTRIBUTE eAttribute, - bool bScriptModify); - void Script_Attribute_Integer(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Attribute_IntegerRead(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Attribute_BOOL(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Attribute_BOOLRead(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Attribute_String(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Attribute_StringRead(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_ValidationMessage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_Length(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_DefaultValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_DefaultValue_Read(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Boolean_Value(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_Message(CFXJSE_Value* pValue, - bool bSetting, - XFA_SOM_MESSAGETYPE iMessageType); - void Script_Som_BorderColor(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_BorderWidth(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_FillColor(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_DataNode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_FontColor(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_Mandatory(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_MandatoryMessage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Som_InstanceIndex(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Draw_DefaultValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_DefaultValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_EditValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_FormatMessage(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_FormattedValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_ParentSubform(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_SelectedIndex(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Field_ClearItems(CFXJSE_Arguments* pArguments); - void Script_Field_ExecEvent(CFXJSE_Arguments* pArguments); - void Script_Field_ExecInitialize(CFXJSE_Arguments* pArguments); - void Script_Field_DeleteItem(CFXJSE_Arguments* pArguments); - void Script_Field_GetSaveItem(CFXJSE_Arguments* pArguments); - void Script_Field_BoundItem(CFXJSE_Arguments* pArguments); - void Script_Field_GetItemState(CFXJSE_Arguments* pArguments); - void Script_Field_ExecCalculate(CFXJSE_Arguments* pArguments); - void Script_Field_SetItems(CFXJSE_Arguments* pArguments); - void Script_Field_GetDisplayItem(CFXJSE_Arguments* pArguments); - void Script_Field_SetItemState(CFXJSE_Arguments* pArguments); - void Script_Field_AddItem(CFXJSE_Arguments* pArguments); - void Script_Field_ExecValidate(CFXJSE_Arguments* pArguments); - void Script_ExclGroup_DefaultAndRawValue(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_ExclGroup_ErrorText(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_ExclGroup_Transient(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_ExclGroup_ExecEvent(CFXJSE_Arguments* pArguments); - void Script_ExclGroup_SelectedMember(CFXJSE_Arguments* pArguments); - void Script_ExclGroup_ExecInitialize(CFXJSE_Arguments* pArguments); - void Script_ExclGroup_ExecCalculate(CFXJSE_Arguments* pArguments); - void Script_ExclGroup_ExecValidate(CFXJSE_Arguments* pArguments); - void Script_Subform_InstanceManager(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Subform_Locale(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Subform_ExecEvent(CFXJSE_Arguments* pArguments); - void Script_Subform_ExecInitialize(CFXJSE_Arguments* pArguments); - void Script_Subform_ExecCalculate(CFXJSE_Arguments* pArguments); - void Script_Subform_ExecValidate(CFXJSE_Arguments* pArguments); - void Script_Subform_GetInvalidObjects(CFXJSE_Arguments* pArguments); - - int32_t Subform_and_SubformSet_InstanceIndex(); - void Script_Template_FormNodes(CFXJSE_Arguments* pArguments); - void Script_Template_Remerge(CFXJSE_Arguments* pArguments); - void Script_Template_ExecInitialize(CFXJSE_Arguments* pArguments); - void Script_Template_CreateNode(CFXJSE_Arguments* pArguments); - void Script_Template_Recalculate(CFXJSE_Arguments* pArguments); - void Script_Template_ExecCalculate(CFXJSE_Arguments* pArguments); - void Script_Template_ExecValidate(CFXJSE_Arguments* pArguments); - void Script_Manifest_Evaluate(CFXJSE_Arguments* pArguments); - void Script_InstanceManager_Count(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_InstanceManager_Max(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_InstanceManager_Min(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_InstanceManager_MoveInstance(CFXJSE_Arguments* pArguments); - void Script_InstanceManager_RemoveInstance(CFXJSE_Arguments* pArguments); - void Script_InstanceManager_SetInstances(CFXJSE_Arguments* pArguments); - void Script_InstanceManager_AddInstance(CFXJSE_Arguments* pArguments); - void Script_InstanceManager_InsertInstance(CFXJSE_Arguments* pArguments); - int32_t InstanceManager_SetInstances(int32_t iCount); - int32_t InstanceManager_MoveInstance(int32_t iTo, int32_t iFrom); - void Script_Occur_Max(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Occur_Min(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Desc_Metadata(CFXJSE_Arguments* pArguments); - void Script_Form_FormNodes(CFXJSE_Arguments* pArguments); - void Script_Form_Remerge(CFXJSE_Arguments* pArguments); - void Script_Form_ExecInitialize(CFXJSE_Arguments* pArguments); - void Script_Form_Recalculate(CFXJSE_Arguments* pArguments); - void Script_Form_ExecCalculate(CFXJSE_Arguments* pArguments); - void Script_Form_ExecValidate(CFXJSE_Arguments* pArguments); - void Script_Form_Checksum(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Packet_GetAttribute(CFXJSE_Arguments* pArguments); - void Script_Packet_SetAttribute(CFXJSE_Arguments* pArguments); - void Script_Packet_RemoveAttribute(CFXJSE_Arguments* pArguments); - void Script_Packet_Content(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Source_Next(CFXJSE_Arguments* pArguments); - void Script_Source_CancelBatch(CFXJSE_Arguments* pArguments); - void Script_Source_First(CFXJSE_Arguments* pArguments); - void Script_Source_UpdateBatch(CFXJSE_Arguments* pArguments); - void Script_Source_Previous(CFXJSE_Arguments* pArguments); - void Script_Source_IsBOF(CFXJSE_Arguments* pArguments); - void Script_Source_IsEOF(CFXJSE_Arguments* pArguments); - void Script_Source_Cancel(CFXJSE_Arguments* pArguments); - void Script_Source_Update(CFXJSE_Arguments* pArguments); - void Script_Source_Open(CFXJSE_Arguments* pArguments); - void Script_Source_Delete(CFXJSE_Arguments* pArguments); - void Script_Source_AddNew(CFXJSE_Arguments* pArguments); - void Script_Source_Requery(CFXJSE_Arguments* pArguments); - void Script_Source_Resync(CFXJSE_Arguments* pArguments); - void Script_Source_Close(CFXJSE_Arguments* pArguments); - void Script_Source_Last(CFXJSE_Arguments* pArguments); - void Script_Source_HasDataChanged(CFXJSE_Arguments* pArguments); - void Script_Source_Db(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Xfa_This(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Handler_Version(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_SubmitFormat_Mode(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Extras_Type(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Encrypt_Format(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - void Script_Script_Stateless(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); - - protected: - friend class CXFA_Document; - - CXFA_Node(CXFA_Document* pDoc, - uint16_t ePacket, - XFA_ObjectType oType, - XFA_Element eType, - const CFX_WideStringC& elementName); - ~CXFA_Node() override; - - bool HasFlag(XFA_NodeFlag dwFlag) const; - CXFA_Node* Deprecated_GetPrevSibling(); - bool SetValue(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTETYPE eType, - void* pValue, - bool bNotify); - bool GetValue(XFA_ATTRIBUTE eAttr, - XFA_ATTRIBUTETYPE eType, - bool bUseDefault, - void*& pValue); - void OnRemoved(bool bNotify); - void OnChanging(XFA_ATTRIBUTE eAttr, bool bNotify); - void OnChanged(XFA_ATTRIBUTE eAttr, bool bNotify, bool bScriptModify); - int32_t execSingleEventByName(const CFX_WideStringC& wsEventName, - XFA_Element eType); - bool SetScriptContent(const CFX_WideString& wsContent, - const CFX_WideString& wsXMLValue, - bool bNotify = true, - bool bScriptModify = false, - bool bSyncData = true); - CFX_WideString GetScriptContent(bool bScriptModify = false); - XFA_MAPMODULEDATA* CreateMapModuleData(); - XFA_MAPMODULEDATA* GetMapModuleData() const; - void SetMapModuleValue(void* pKey, void* pValue); - bool GetMapModuleValue(void* pKey, void*& pValue); - void SetMapModuleString(void* pKey, const CFX_WideStringC& wsValue); - bool GetMapModuleString(void* pKey, CFX_WideStringC& wsValue); - void SetMapModuleBuffer( - void* pKey, - void* pValue, - int32_t iBytes, - XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo = nullptr); - bool GetMapModuleBuffer(void* pKey, - void*& pValue, - int32_t& iBytes, - bool bProtoAlso = true) const; - bool HasMapModuleKey(void* pKey, bool bProtoAlso = false); - void RemoveMapModuleKey(void* pKey = nullptr); - void MergeAllData(void* pDstModule); - void MoveBufferMapData(CXFA_Node* pDstModule, void* pKey); - void MoveBufferMapData(CXFA_Node* pSrcModule, - CXFA_Node* pDstModule, - void* pKey, - bool bRecursive = false); - - CXFA_Node* m_pNext; - CXFA_Node* m_pChild; - CXFA_Node* m_pLastChild; - CXFA_Node* m_pParent; - CFDE_XMLNode* m_pXMLNode; - uint16_t m_ePacket; - uint16_t m_uNodeFlags; - uint32_t m_dwNameHash; - CXFA_Node* m_pAuxNode; - XFA_MAPMODULEDATA* m_pMapModuleData; - - private: - void ThrowMissingPropertyException(const CFX_WideString& obj, - const CFX_WideString& prop) const; - void ThrowTooManyOccurancesException(const CFX_WideString& obj) const; -}; - -class CXFA_ThisProxy : public CXFA_Object { - public: - CXFA_ThisProxy(CXFA_Node* pThisNode, CXFA_Node* pScriptNode); - ~CXFA_ThisProxy() override; - - CXFA_Node* GetThisNode() const; - CXFA_Node* GetScriptNode() const; - - private: - CXFA_Node* m_pThisNode; - CXFA_Node* m_pScriptNode; -}; - -class CXFA_NodeList : public CXFA_Object { - public: - explicit CXFA_NodeList(CXFA_Document* pDocument); - ~CXFA_NodeList() override; - - CXFA_Node* NamedItem(const CFX_WideStringC& wsName); - virtual int32_t GetLength() = 0; - virtual bool Append(CXFA_Node* pNode) = 0; - virtual bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) = 0; - virtual bool Remove(CXFA_Node* pNode) = 0; - virtual CXFA_Node* Item(int32_t iIndex) = 0; - - void Script_ListClass_Append(CFXJSE_Arguments* pArguments); - void Script_ListClass_Insert(CFXJSE_Arguments* pArguments); - void Script_ListClass_Remove(CFXJSE_Arguments* pArguments); - void Script_ListClass_Item(CFXJSE_Arguments* pArguments); - - void Script_TreelistClass_NamedItem(CFXJSE_Arguments* pArguments); - void Script_ListClass_Length(CFXJSE_Value* pValue, - bool bSetting, - XFA_ATTRIBUTE eAttribute); -}; - -class CXFA_ArrayNodeList : public CXFA_NodeList { - public: - explicit CXFA_ArrayNodeList(CXFA_Document* pDocument); - ~CXFA_ArrayNodeList() override; - - // From CXFA_NodeList. - int32_t GetLength() override; - bool Append(CXFA_Node* pNode) override; - bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override; - bool Remove(CXFA_Node* pNode) override; - CXFA_Node* Item(int32_t iIndex) override; - - void SetArrayNodeList(const CXFA_NodeArray& srcArray); - - protected: - CXFA_NodeArray m_array; -}; - -class CXFA_AttachNodeList : public CXFA_NodeList { - public: - CXFA_AttachNodeList(CXFA_Document* pDocument, CXFA_Node* pAttachNode); - - // From CXFA_NodeList. - int32_t GetLength() override; - bool Append(CXFA_Node* pNode) override; - bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override; - bool Remove(CXFA_Node* pNode) override; - CXFA_Node* Item(int32_t iIndex) override; - - protected: - CXFA_Node* m_pAttachNode; -}; -class CXFA_TraverseStrategy_XFAContainerNode { - public: - static CXFA_Node* GetFirstChild(CXFA_Node* pTemplateNode, - void* pUserData = nullptr) { - return pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild, - XFA_ObjectType::ContainerNode); - } - static CXFA_Node* GetNextSibling(CXFA_Node* pTemplateNode, - void* pUserData = nullptr) { - return pTemplateNode->GetNodeItem(XFA_NODEITEM_NextSibling, - XFA_ObjectType::ContainerNode); - } - static CXFA_Node* GetParent(CXFA_Node* pTemplateNode, - void* pUserData = nullptr) { - return pTemplateNode->GetNodeItem(XFA_NODEITEM_Parent, - XFA_ObjectType::ContainerNode); - } -}; -typedef CXFA_NodeIteratorTemplate<CXFA_Node, - CXFA_TraverseStrategy_XFAContainerNode> - CXFA_ContainerIterator; -class CXFA_TraverseStrategy_XFANode { - public: - static inline CXFA_Node* GetFirstChild(CXFA_Node* pTemplateNode) { - return pTemplateNode->GetNodeItem(XFA_NODEITEM_FirstChild); - } - static inline CXFA_Node* GetNextSibling(CXFA_Node* pTemplateNode) { - return pTemplateNode->GetNodeItem(XFA_NODEITEM_NextSibling); - } - static inline CXFA_Node* GetParent(CXFA_Node* pTemplateNode) { - return pTemplateNode->GetNodeItem(XFA_NODEITEM_Parent); - } -}; -typedef CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> - CXFA_NodeIterator; - -inline CXFA_Node* CXFA_Object::AsNode() { - return IsNode() ? static_cast<CXFA_Node*>(this) : nullptr; -} - -inline CXFA_NodeList* CXFA_Object::AsNodeList() { - return IsNodeList() ? static_cast<CXFA_NodeList*>(this) : nullptr; -} - -inline const CXFA_Node* CXFA_Object::AsNode() const { - return IsNode() ? static_cast<const CXFA_Node*>(this) : nullptr; -} - -inline const CXFA_NodeList* CXFA_Object::AsNodeList() const { - return IsNodeList() ? static_cast<const CXFA_NodeList*>(this) : nullptr; -} - -inline CXFA_Node* ToNode(CXFA_Object* pObj) { - return pObj ? pObj->AsNode() : nullptr; -} - -inline const CXFA_Node* ToNode(const CXFA_Object* pObj) { - return pObj ? pObj->AsNode() : nullptr; -} - -#endif // XFA_FXFA_PARSER_XFA_OBJECT_H_ diff --git a/xfa/fxfa/parser/xfa_resolvenode_rs.h b/xfa/fxfa/parser/xfa_resolvenode_rs.h index 7ad218efe8cbf7835ada7d5cd14d4314a6796355..86960abeccaa4d2d8f74232fbddb66eab2ed47e7 100644 --- a/xfa/fxfa/parser/xfa_resolvenode_rs.h +++ b/xfa/fxfa/parser/xfa_resolvenode_rs.h @@ -8,10 +8,13 @@ #define XFA_FXFA_PARSER_XFA_RESOLVENODE_RS_H_ #include <memory> +#include <utility> +#include <vector> #include "fxjs/cfxjse_value.h" +#include "third_party/base/ptr_util.h" #include "xfa/fxfa/fxfa.h" -#include "xfa/fxfa/parser/cxfa_valuearray.h" +#include "xfa/fxfa/parser/cxfa_object.h" #define XFA_RESOLVENODE_Children 0x0001 #define XFA_RESOLVENODE_Attributes 0x0004 @@ -24,47 +27,27 @@ #define XFA_RESOLVENODE_Bind 0x0800 #define XFA_RESOLVENODE_BindNew 0x1000 -enum XFA_SCRIPTLANGTYPE { - XFA_SCRIPTLANGTYPE_Formcalc = XFA_SCRIPTTYPE_Formcalc, - XFA_SCRIPTLANGTYPE_Javascript = XFA_SCRIPTTYPE_Javascript, - XFA_SCRIPTLANGTYPE_Unkown = XFA_SCRIPTTYPE_Unkown, -}; - -enum XFA_RESOVENODE_RSTYPE { - XFA_RESOVENODE_RSTYPE_Nodes, - XFA_RESOVENODE_RSTYPE_Attribute, - XFA_RESOLVENODE_RSTYPE_CreateNodeOne, - XFA_RESOLVENODE_RSTYPE_CreateNodeAll, - XFA_RESOLVENODE_RSTYPE_CreateNodeMidAll, - XFA_RESOVENODE_RSTYPE_ExistNodes, +enum XFA_ResolveNode_RSType { + XFA_ResolveNode_RSType_Nodes, + XFA_ResolveNode_RSType_Attribute, + XFA_ResolveNode_RSType_CreateNodeOne, + XFA_ResolveNode_RSType_CreateNodeAll, + XFA_ResolveNode_RSType_CreateNodeMidAll, + XFA_ResolveNode_RSType_ExistNodes, }; struct XFA_RESOLVENODE_RS { XFA_RESOLVENODE_RS(); ~XFA_RESOLVENODE_RS(); - int32_t GetAttributeResult(CXFA_ValueArray& valueArray) const { - if (pScriptAttribute && pScriptAttribute->eValueType == XFA_SCRIPT_Object) { - v8::Isolate* pIsolate = valueArray.m_pIsolate; - for (int32_t i = 0; i < nodes.GetSize(); i++) { - std::unique_ptr<CFXJSE_Value> pValue(new CFXJSE_Value(pIsolate)); - (nodes[i]->*(pScriptAttribute->lpfnCallback))( - pValue.get(), false, (XFA_ATTRIBUTE)pScriptAttribute->eAttribute); - valueArray.Add(pValue.release()); - } - } - return valueArray.GetSize(); - } - - CXFA_ObjArray nodes; - XFA_RESOVENODE_RSTYPE dwFlags; + std::vector<CXFA_Object*> objects; // Not owned. + XFA_ResolveNode_RSType dwFlags; const XFA_SCRIPTATTRIBUTEINFO* pScriptAttribute; }; inline XFA_RESOLVENODE_RS::XFA_RESOLVENODE_RS() - : dwFlags(XFA_RESOVENODE_RSTYPE_Nodes), pScriptAttribute(nullptr) {} + : dwFlags(XFA_ResolveNode_RSType_Nodes), pScriptAttribute(nullptr) {} + +inline XFA_RESOLVENODE_RS::~XFA_RESOLVENODE_RS() {} -inline XFA_RESOLVENODE_RS::~XFA_RESOLVENODE_RS() { - nodes.RemoveAll(); -} #endif // XFA_FXFA_PARSER_XFA_RESOLVENODE_RS_H_ diff --git a/xfa/fxfa/parser/xfa_utils.cpp b/xfa/fxfa/parser/xfa_utils.cpp index 6f54c0e5fe4bdc3658ee287057b9d26607323102..5d2f222a3b05552ba8195a12b5ce32c492f62d79 100644 --- a/xfa/fxfa/parser/xfa_utils.cpp +++ b/xfa/fxfa/parser/xfa_utils.cpp @@ -6,126 +6,426 @@ #include "xfa/fxfa/parser/xfa_utils.h" -#include "core/fxcrt/fx_ext.h" -#include "xfa/fde/xml/fde_xml_imp.h" +#include <algorithm> +#include <vector> + +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlnode.h" +#include "core/fxcrt/xml/cfx_xmltext.h" +#include "fxjs/xfa/cjx_object.h" #include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_localemgr.h" +#include "xfa/fxfa/parser/cxfa_localevalue.h" #include "xfa/fxfa/parser/cxfa_measurement.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_ui.h" +#include "xfa/fxfa/parser/cxfa_value.h" #include "xfa/fxfa/parser/xfa_basic_data.h" -#include "xfa/fxfa/parser/xfa_localemgr.h" -#include "xfa/fxfa/parser/xfa_localevalue.h" -#include "xfa/fxfa/parser/xfa_object.h" namespace { -const FX_DOUBLE fraction_scales[] = {0.1, - 0.01, - 0.001, - 0.0001, - 0.00001, - 0.000001, - 0.0000001, - 0.00000001, - 0.000000001, - 0.0000000001, - 0.00000000001, - 0.000000000001, - 0.0000000000001, - 0.00000000000001, - 0.000000000000001, - 0.0000000000000001}; - -FX_DOUBLE WideStringToDouble(const CFX_WideString& wsStringVal) { - CFX_WideString wsValue = wsStringVal; - wsValue.TrimLeft(); - wsValue.TrimRight(); - int64_t nIntegral = 0; - uint32_t dwFractional = 0; - int32_t nExponent = 0; - int32_t cc = 0; - bool bNegative = false; - bool bExpSign = false; - const FX_WCHAR* str = wsValue.c_str(); - int32_t len = wsValue.GetLength(); - if (str[0] == '+') { - cc++; - } else if (str[0] == '-') { - bNegative = true; - cc++; +constexpr const wchar_t kFormNS[] = L"http://www.xfa.org/schema/xfa-form/"; + +const double fraction_scales[] = {0.1, + 0.01, + 0.001, + 0.0001, + 0.00001, + 0.000001, + 0.0000001, + 0.00000001, + 0.000000001, + 0.0000000001, + 0.00000000001, + 0.000000000001, + 0.0000000000001, + 0.00000000000001, + 0.000000000000001, + 0.0000000000000001}; + +WideString ExportEncodeAttribute(const WideString& str) { + CFX_WideTextBuf textBuf; + int32_t iLen = str.GetLength(); + for (int32_t i = 0; i < iLen; i++) { + switch (str[i]) { + case '&': + textBuf << L"&"; + break; + case '<': + textBuf << L"<"; + break; + case '>': + textBuf << L">"; + break; + case '\'': + textBuf << L"'"; + break; + case '\"': + textBuf << L"""; + break; + default: + textBuf.AppendChar(str[i]); + } } - int32_t nIntegralLen = 0; - while (cc < len) { - if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' || - nIntegralLen > 17) { - break; + return textBuf.MakeString(); +} + +bool IsXMLValidChar(wchar_t ch) { + return ch == 0x09 || ch == 0x0A || ch == 0x0D || + (ch >= 0x20 && ch <= 0xD7FF) || (ch >= 0xE000 && ch <= 0xFFFD); +} + +WideString ExportEncodeContent(const WideString& str) { + CFX_WideTextBuf textBuf; + int32_t iLen = str.GetLength(); + for (int32_t i = 0; i < iLen; i++) { + wchar_t ch = str[i]; + if (!IsXMLValidChar(ch)) + continue; + + if (ch == '&') { + textBuf << L"&"; + } else if (ch == '<') { + textBuf << L"<"; + } else if (ch == '>') { + textBuf << L">"; + } else if (ch == '\'') { + textBuf << L"'"; + } else if (ch == '\"') { + textBuf << L"""; + } else if (ch == ' ') { + if (i && str[i - 1] != ' ') { + textBuf.AppendChar(' '); + } else { + textBuf << L" "; + } + } else { + textBuf.AppendChar(str[i]); } - if (!FXSYS_isDecimalDigit(str[cc])) { - return 0; + } + return textBuf.MakeString(); +} + +bool AttributeSaveInDataModel(CXFA_Node* pNode, XFA_Attribute eAttribute) { + bool bSaveInDataModel = false; + if (pNode->GetElementType() != XFA_Element::Image) + return bSaveInDataModel; + + CXFA_Node* pValueNode = pNode->GetParent(); + if (!pValueNode || pValueNode->GetElementType() != XFA_Element::Value) + return bSaveInDataModel; + + CXFA_Node* pFieldNode = pValueNode->GetParent(); + if (pFieldNode && pFieldNode->GetBindData() && + eAttribute == XFA_Attribute::Href) { + bSaveInDataModel = true; + } + return bSaveInDataModel; +} + +bool ContentNodeNeedtoExport(CXFA_Node* pContentNode) { + Optional<WideString> wsContent = + pContentNode->JSObject()->TryContent(false, false); + if (!wsContent) + return false; + + ASSERT(pContentNode->IsContentNode()); + CXFA_Node* pParentNode = pContentNode->GetParent(); + if (!pParentNode || pParentNode->GetElementType() != XFA_Element::Value) + return true; + + CXFA_Node* pGrandParentNode = pParentNode->GetParent(); + if (!pGrandParentNode || !pGrandParentNode->IsContainerNode()) + return true; + if (pGrandParentNode->GetBindData()) + return false; + + XFA_Element eUIType = pGrandParentNode->GetWidgetAcc()->GetUIType(); + if (eUIType == XFA_Element::PasswordEdit) + return false; + return true; +} + +void SaveAttribute(CXFA_Node* pNode, + XFA_Attribute eName, + const WideString& wsName, + bool bProto, + WideString& wsOutput) { + if (!bProto && !pNode->JSObject()->HasAttribute(eName)) + return; + + Optional<WideString> value = pNode->JSObject()->TryAttribute(eName, false); + if (!value) + return; + + wsOutput += L" "; + wsOutput += wsName; + wsOutput += L"=\""; + wsOutput += ExportEncodeAttribute(*value); + wsOutput += L"\""; +} + +void RegenerateFormFile_Changed(CXFA_Node* pNode, + CFX_WideTextBuf& buf, + bool bSaveXML) { + WideString wsAttrs; + for (size_t i = 0;; ++i) { + XFA_Attribute attr = pNode->GetAttribute(i); + if (attr == XFA_Attribute::Unknown) + break; + + if (attr == XFA_Attribute::Name || + (AttributeSaveInDataModel(pNode, attr) && !bSaveXML)) { + continue; } - nIntegral = nIntegral * 10 + str[cc] - '0'; - cc++; - nIntegralLen++; + WideString wsAttr; + SaveAttribute(pNode, attr, CXFA_Node::AttributeToName(attr), bSaveXML, + wsAttr); + wsAttrs += wsAttr; } - nIntegral = bNegative ? -nIntegral : nIntegral; - int32_t scale = 0; - FX_DOUBLE fraction = 0.0; - if (cc < len && str[cc] == '.') { - cc++; - while (cc < len) { - fraction += fraction_scales[scale] * (str[cc] - '0'); - scale++; - cc++; - if (cc == len) { + + WideString wsChildren; + switch (pNode->GetObjectType()) { + case XFA_ObjectType::ContentNode: { + if (!bSaveXML && !ContentNodeNeedtoExport(pNode)) break; + + CXFA_Node* pRawValueNode = pNode->GetFirstChild(); + while (pRawValueNode && + pRawValueNode->GetElementType() != XFA_Element::SharpxHTML && + pRawValueNode->GetElementType() != XFA_Element::Sharptext && + pRawValueNode->GetElementType() != XFA_Element::Sharpxml) { + pRawValueNode = pRawValueNode->GetNextSibling(); } - if (scale == sizeof(fraction_scales) / sizeof(FX_DOUBLE) || - str[cc] == 'E' || str[cc] == 'e') { + if (!pRawValueNode) break; + + Optional<WideString> contentType = + pNode->JSObject()->TryAttribute(XFA_Attribute::ContentType, false); + if (pRawValueNode->GetElementType() == XFA_Element::SharpxHTML && + (contentType && *contentType == L"text/html")) { + CFX_XMLNode* pExDataXML = pNode->GetXMLMappingNode(); + if (!pExDataXML) + break; + + CFX_XMLNode* pRichTextXML = + pExDataXML->GetNodeItem(CFX_XMLNode::FirstChild); + if (!pRichTextXML) + break; + + auto pMemStream = pdfium::MakeRetain<CFX_MemoryStream>(true); + auto pTempStream = + pdfium::MakeRetain<CFX_SeekableStreamProxy>(pMemStream, true); + + pTempStream->SetCodePage(FX_CODEPAGE_UTF8); + pRichTextXML->SaveXMLNode(pTempStream); + wsChildren += WideString::FromUTF8( + ByteStringView(pMemStream->GetBuffer(), pMemStream->GetSize())); + } else if (pRawValueNode->GetElementType() == XFA_Element::Sharpxml && + (contentType && *contentType == L"text/xml")) { + Optional<WideString> rawValue = pRawValueNode->JSObject()->TryAttribute( + XFA_Attribute::Value, false); + if (!rawValue || rawValue->IsEmpty()) + break; + + std::vector<WideString> wsSelTextArray; + size_t iStart = 0; + auto iEnd = rawValue->Find(L'\n', iStart); + iEnd = !iEnd.has_value() ? rawValue->GetLength() : iEnd; + while (iEnd.has_value() && iEnd >= iStart) { + wsSelTextArray.push_back( + rawValue->Mid(iStart, iEnd.value() - iStart)); + iStart = iEnd.value() + 1; + if (iStart >= rawValue->GetLength()) + break; + iEnd = rawValue->Find(L'\n', iStart); + } + + CXFA_Node* pParentNode = pNode->GetParent(); + ASSERT(pParentNode); + CXFA_Node* pGrandparentNode = pParentNode->GetParent(); + ASSERT(pGrandparentNode); + WideString bodyTagName; + bodyTagName = + pGrandparentNode->JSObject()->GetCData(XFA_Attribute::Name); + if (bodyTagName.IsEmpty()) + bodyTagName = L"ListBox1"; + + buf << L"<"; + buf << bodyTagName; + buf << L" xmlns=\"\"\n>"; + for (int32_t i = 0; i < pdfium::CollectionSize<int32_t>(wsSelTextArray); + i++) { + buf << L"<value\n>"; + buf << ExportEncodeContent(wsSelTextArray[i]); + buf << L"</value\n>"; + } + buf << L"</"; + buf << bodyTagName; + buf << L"\n>"; + wsChildren += buf.AsStringView(); + buf.Clear(); + } else { + WideString wsValue = + pRawValueNode->JSObject()->GetCData(XFA_Attribute::Value); + wsChildren += ExportEncodeContent(wsValue); } - if (!FXSYS_isDecimalDigit(str[cc])) { - return 0; - } + break; } - dwFractional = (uint32_t)(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++; - } + case XFA_ObjectType::TextNode: + case XFA_ObjectType::NodeC: + case XFA_ObjectType::NodeV: { + WideString wsValue = pNode->JSObject()->GetCData(XFA_Attribute::Value); + wsChildren += ExportEncodeContent(wsValue); + break; } - while (cc < len) { - if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) { - return 0; + default: + if (pNode->GetElementType() == XFA_Element::Items) { + CXFA_Node* pTemplateNode = pNode->GetTemplateNodeIfExists(); + if (!pTemplateNode || + pTemplateNode->CountChildren(XFA_Element::Unknown, false) != + pNode->CountChildren(XFA_Element::Unknown, false)) { + bSaveXML = true; + } + } + CFX_WideTextBuf newBuf; + CXFA_Node* pChildNode = pNode->GetFirstChild(); + while (pChildNode) { + RegenerateFormFile_Changed(pChildNode, newBuf, bSaveXML); + wsChildren += newBuf.AsStringView(); + newBuf.Clear(); + pChildNode = pChildNode->GetNextSibling(); + } + if (!bSaveXML && !wsChildren.IsEmpty() && + pNode->GetElementType() == XFA_Element::Items) { + wsChildren.clear(); + bSaveXML = true; + CXFA_Node* pChild = pNode->GetFirstChild(); + while (pChild) { + RegenerateFormFile_Changed(pChild, newBuf, bSaveXML); + wsChildren += newBuf.AsStringView(); + newBuf.Clear(); + pChild = pChild->GetNextSibling(); + } } - nExponent = nExponent * 10 + str[cc] - '0'; - cc++; + break; + } + + if (!wsChildren.IsEmpty() || !wsAttrs.IsEmpty() || + pNode->JSObject()->HasAttribute(XFA_Attribute::Name)) { + WideStringView wsElement = pNode->GetClassName(); + WideString wsName; + SaveAttribute(pNode, XFA_Attribute::Name, L"name", true, wsName); + buf << L"<"; + buf << wsElement; + buf << wsName; + buf << wsAttrs; + if (wsChildren.IsEmpty()) { + buf << L"\n/>"; + } else { + buf << L"\n>"; + buf << wsChildren; + buf << L"</"; + buf << wsElement; + buf << L"\n>"; } - nExponent = bExpSign ? -nExponent : nExponent; } - FX_DOUBLE dValue = (dwFractional / 4294967296.0); - dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); - if (nExponent != 0) { - dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); +} + +void RegenerateFormFile_Container( + CXFA_Node* pNode, + const RetainPtr<CFX_SeekableStreamProxy>& pStream, + bool bSaveXML) { + XFA_Element eType = pNode->GetElementType(); + if (eType == XFA_Element::Field || eType == XFA_Element::Draw || + !pNode->IsContainerNode()) { + CFX_WideTextBuf buf; + RegenerateFormFile_Changed(pNode, buf, bSaveXML); + size_t nLen = buf.GetLength(); + if (nLen > 0) + pStream->WriteString(buf.AsStringView()); + return; + } + + WideStringView wsElement(pNode->GetClassName()); + pStream->WriteString(L"<"); + pStream->WriteString(wsElement); + + WideString wsOutput; + SaveAttribute(pNode, XFA_Attribute::Name, L"name", true, wsOutput); + + WideString wsAttrs; + for (size_t i = 0;; ++i) { + XFA_Attribute attr = pNode->GetAttribute(i); + if (attr == XFA_Attribute::Unknown) + break; + if (attr == XFA_Attribute::Name) + continue; + + WideString wsAttr; + SaveAttribute(pNode, attr, CXFA_Node::AttributeToName(attr), false, wsAttr); + wsOutput += wsAttr; + } + + if (!wsOutput.IsEmpty()) + pStream->WriteString(wsOutput.AsStringView()); + + CXFA_Node* pChildNode = pNode->GetFirstChild(); + if (pChildNode) { + pStream->WriteString(L"\n>"); + while (pChildNode) { + RegenerateFormFile_Container(pChildNode, pStream, bSaveXML); + pChildNode = pChildNode->GetNextSibling(); + } + pStream->WriteString(L"</"); + pStream->WriteString(wsElement); + pStream->WriteString(L"\n>"); + } else { + pStream->WriteString(L"\n/>"); } - return dValue; +} + +WideString RecognizeXFAVersionNumber(CXFA_Node* pTemplateRoot) { + if (!pTemplateRoot) + return WideString(); + + Optional<WideString> templateNS = pTemplateRoot->JSObject()->TryNamespace(); + if (!templateNS) + return WideString(); + + XFA_VERSION eVersion = + pTemplateRoot->GetDocument()->RecognizeXFAVersionNumber(*templateNS); + if (eVersion == XFA_VERSION_UNKNOWN) + eVersion = XFA_VERSION_DEFAULT; + + return WideString::Format(L"%i.%i", eVersion / 100, eVersion % 100); } } // namespace -CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData) { - CXFA_Node* pNodeValue = - pWidgetData->GetNode()->GetChild(0, XFA_Element::Value); - if (!pNodeValue) { +double XFA_GetFractionalScale(uint32_t idx) { + return fraction_scales[idx]; +} + +int XFA_GetMaxFractionalScale() { + return FX_ArraySize(fraction_scales); +} + +CXFA_LocaleValue XFA_GetLocaleValue(CXFA_Node* pNode) { + CXFA_Value* pNodeValue = + pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false); + if (!pNodeValue) return CXFA_LocaleValue(); - } - CXFA_Node* pValueChild = pNodeValue->GetNodeItem(XFA_NODEITEM_FirstChild); - if (!pValueChild) { + + CXFA_Node* pValueChild = pNodeValue->GetFirstChild(); + if (!pValueChild) return CXFA_LocaleValue(); - } + int32_t iVTType = XFA_VT_NULL; switch (pValueChild->GetElementType()) { case XFA_Element::Decimal: @@ -156,74 +456,121 @@ CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData) { iVTType = XFA_VT_NULL; break; } - return CXFA_LocaleValue(iVTType, pWidgetData->GetRawValue(), - pWidgetData->GetNode()->GetDocument()->GetLocalMgr()); + return CXFA_LocaleValue(iVTType, pNode->GetRawValue(), + pNode->GetDocument()->GetLocalMgr()); +} + +bool XFA_FDEExtension_ResolveNamespaceQualifier(CFX_XMLElement* pNode, + const WideString& wsQualifier, + WideString* wsNamespaceURI) { + if (!pNode) + return false; + + CFX_XMLNode* pFakeRoot = pNode->GetNodeItem(CFX_XMLNode::Root); + WideString wsNSAttribute; + bool bRet = false; + if (wsQualifier.IsEmpty()) { + wsNSAttribute = L"xmlns"; + bRet = true; + } else { + wsNSAttribute = L"xmlns:" + wsQualifier; + } + for (CFX_XMLNode* pParent = pNode; pParent != pFakeRoot; + pParent = pParent->GetNodeItem(CFX_XMLNode::Parent)) { + if (pParent->GetType() != FX_XMLNODE_Element) + continue; + + auto* pElement = static_cast<CFX_XMLElement*>(pParent); + if (pElement->HasAttribute(wsNSAttribute.c_str())) { + *wsNamespaceURI = pElement->GetString(wsNSAttribute.c_str()); + return true; + } + } + wsNamespaceURI->clear(); + return bRet; } -void XFA_GetPlainTextFromRichText(CFDE_XMLNode* pXMLNode, - CFX_WideString& wsPlainText) { - if (!pXMLNode) { + +void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode) { + if (!pDataNode || pDataNode->GetElementType() == XFA_Element::DataValue) return; + + int32_t iChildNum = 0; + for (CXFA_Node* pChildNode = pDataNode->GetFirstChild(); pChildNode; + pChildNode = pChildNode->GetNextSibling()) { + iChildNum++; + XFA_DataExporter_DealWithDataGroupNode(pChildNode); } - switch (pXMLNode->GetType()) { - case FDE_XMLNODE_Element: { - CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); - CFX_WideString wsTag; - pXMLElement->GetLocalTagName(wsTag); - uint32_t uTag = FX_HashCode_GetW(wsTag.AsStringC(), true); - if (uTag == 0x0001f714) { - wsPlainText += L"\n"; - } else if (uTag == 0x00000070) { - if (!wsPlainText.IsEmpty()) { - wsPlainText += L"\n"; - } - } else if (uTag == 0xa48ac63) { - if (!wsPlainText.IsEmpty() && - wsPlainText[wsPlainText.GetLength() - 1] != '\n') { - wsPlainText += L"\n"; - } - } - } break; - case FDE_XMLNODE_Text: { - CFX_WideString wsContent; - static_cast<CFDE_XMLText*>(pXMLNode)->GetText(wsContent); - wsPlainText += wsContent; - } break; - case FDE_XMLNODE_CharData: { - CFX_WideString wsCharData; - static_cast<CFDE_XMLCharData*>(pXMLNode)->GetCharData(wsCharData); - wsPlainText += wsCharData; - } break; - default: - break; + + if (pDataNode->GetElementType() != XFA_Element::DataGroup) + return; + + if (iChildNum > 0) { + CFX_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); + ASSERT(pXMLNode->GetType() == FX_XMLNODE_Element); + CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode); + if (pXMLElement->HasAttribute(L"xfa:dataNode")) + pXMLElement->RemoveAttribute(L"xfa:dataNode"); + + return; } - for (CFDE_XMLNode* pChildXML = - pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); - pChildXML; - pChildXML = pChildXML->GetNodeItem(CFDE_XMLNode::NextSibling)) { - XFA_GetPlainTextFromRichText(pChildXML, wsPlainText); + + CFX_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode(); + ASSERT(pXMLNode->GetType() == FX_XMLNODE_Element); + static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode", + L"dataGroup"); +} + +void XFA_DataExporter_RegenerateFormFile( + CXFA_Node* pNode, + const RetainPtr<CFX_SeekableStreamProxy>& pStream, + const char* pChecksum, + bool bSaveXML) { + if (pNode->IsModelNode()) { + pStream->WriteString(L"<form"); + if (pChecksum) { + WideString wsChecksum = WideString::FromUTF8(pChecksum); + pStream->WriteString(L" checksum=\""); + pStream->WriteString(wsChecksum.AsStringView()); + pStream->WriteString(L"\""); + } + pStream->WriteString(L" xmlns=\""); + pStream->WriteString(WideStringView(kFormNS)); + + WideString wsVersionNumber = RecognizeXFAVersionNumber( + ToNode(pNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Template))); + if (wsVersionNumber.IsEmpty()) + wsVersionNumber = L"2.8"; + + wsVersionNumber += L"/\"\n>"; + pStream->WriteString(wsVersionNumber.AsStringView()); + + CXFA_Node* pChildNode = pNode->GetFirstChild(); + while (pChildNode) { + RegenerateFormFile_Container(pChildNode, pStream, false); + pChildNode = pChildNode->GetNextSibling(); + } + pStream->WriteString(L"</form\n>"); + } else { + RegenerateFormFile_Container(pNode, pStream, bSaveXML); } } bool XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode) { - bool bRet = false; if (!pFieldNode) - return bRet; - - CXFA_Node* pUIChild = pFieldNode->GetChild(0, XFA_Element::Ui); - if (pUIChild) { - CXFA_Node* pFirstChild = pUIChild->GetNodeItem(XFA_NODEITEM_FirstChild); - if (pFirstChild && - pFirstChild->GetElementType() == XFA_Element::ChoiceList) { - bRet = pFirstChild->GetEnum(XFA_ATTRIBUTE_Open) == - XFA_ATTRIBUTEENUM_MultiSelect; - } + return false; + + CXFA_Ui* pUIChild = pFieldNode->GetChild<CXFA_Ui>(0, XFA_Element::Ui, false); + if (!pUIChild) + return false; + + CXFA_Node* pFirstChild = pUIChild->GetFirstChild(); + if (!pFirstChild || + pFirstChild->GetElementType() != XFA_Element::ChoiceList) { + return false; } - return bRet; -} -FX_DOUBLE XFA_ByteStringToDouble(const CFX_ByteStringC& szStringVal) { - CFX_WideString wsValue = CFX_WideString::FromUTF8(szStringVal); - return WideStringToDouble(wsValue); + return pFirstChild->JSObject()->GetEnum(XFA_Attribute::Open) == + XFA_AttributeEnum::MultiSelect; } int32_t XFA_MapRotation(int32_t nRotation) { @@ -234,7 +581,7 @@ int32_t XFA_MapRotation(int32_t nRotation) { const XFA_SCRIPTATTRIBUTEINFO* XFA_GetScriptAttributeByName( XFA_Element eElement, - const CFX_WideStringC& wsAttributeName) { + const WideStringView& wsAttributeName) { if (wsAttributeName.IsEmpty()) return nullptr; @@ -262,225 +609,3 @@ const XFA_SCRIPTATTRIBUTEINFO* XFA_GetScriptAttributeByName( } return nullptr; } - -const XFA_NOTSUREATTRIBUTE* XFA_GetNotsureAttribute(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - XFA_ATTRIBUTETYPE eType) { - int32_t iStart = 0, iEnd = g_iXFANotsureCount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_NOTSUREATTRIBUTE* pAttr = g_XFANotsureAttributes + iMid; - if (eElement == pAttr->eElement) { - if (pAttr->eAttribute == eAttribute) { - if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) - return pAttr; - return nullptr; - } - int32_t iBefore = iMid - 1; - if (iBefore >= 0) { - pAttr = g_XFANotsureAttributes + iBefore; - while (eElement == pAttr->eElement) { - if (pAttr->eAttribute == eAttribute) { - if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) - return pAttr; - return nullptr; - } - iBefore--; - if (iBefore < 0) - break; - - pAttr = g_XFANotsureAttributes + iBefore; - } - } - - int32_t iAfter = iMid + 1; - if (iAfter <= g_iXFANotsureCount - 1) { - pAttr = g_XFANotsureAttributes + iAfter; - while (eElement == pAttr->eElement) { - if (pAttr->eAttribute == eAttribute) { - if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) - return pAttr; - return nullptr; - } - iAfter++; - if (iAfter > g_iXFANotsureCount - 1) - break; - - pAttr = g_XFANotsureAttributes + iAfter; - } - } - return nullptr; - } - - if (eElement < pAttr->eElement) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return nullptr; -} - -const XFA_PROPERTY* XFA_GetPropertyOfElement(XFA_Element eElement, - XFA_Element eProperty, - uint32_t dwPacket) { - int32_t iCount = 0; - const XFA_PROPERTY* pProperties = XFA_GetElementProperties(eElement, iCount); - if (!pProperties || iCount < 1) - return nullptr; - - auto it = std::find_if(pProperties, pProperties + iCount, - [eProperty](const XFA_PROPERTY& prop) { - return prop.eName == eProperty; - }); - if (it == pProperties + iCount) - return nullptr; - - const XFA_ELEMENTINFO* pInfo = XFA_GetElementByID(eProperty); - ASSERT(pInfo); - if (dwPacket != XFA_XDPPACKET_UNKNOWN && !(dwPacket & pInfo->dwPackets)) - return nullptr; - return it; -} - -const XFA_PROPERTY* XFA_GetElementProperties(XFA_Element eElement, - int32_t& iCount) { - if (eElement == XFA_Element::Unknown) - return nullptr; - - const XFA_ELEMENTHIERARCHY* pElement = - g_XFAElementPropertyIndex + static_cast<int32_t>(eElement); - iCount = pElement->wCount; - return g_XFAElementPropertyData + pElement->wStart; -} - -const uint8_t* XFA_GetElementAttributes(XFA_Element eElement, int32_t& iCount) { - if (eElement == XFA_Element::Unknown) - return nullptr; - - const XFA_ELEMENTHIERARCHY* pElement = - g_XFAElementAttributeIndex + static_cast<int32_t>(eElement); - iCount = pElement->wCount; - return g_XFAElementAttributeData + pElement->wStart; -} - -const XFA_ELEMENTINFO* XFA_GetElementByID(XFA_Element eName) { - return eName != XFA_Element::Unknown - ? g_XFAElementData + static_cast<int32_t>(eName) - : nullptr; -} - -XFA_Element XFA_GetElementTypeForName(const CFX_WideStringC& wsName) { - if (wsName.IsEmpty()) - return XFA_Element::Unknown; - - uint32_t uHash = FX_HashCode_GetW(wsName, false); - const XFA_ELEMENTINFO* pEnd = g_XFAElementData + g_iXFAElementCount; - auto pInfo = std::lower_bound(g_XFAElementData, pEnd, uHash, - [](const XFA_ELEMENTINFO& info, uint32_t hash) { - return info.uHash < hash; - }); - if (pInfo < pEnd && pInfo->uHash == uHash) - return pInfo->eName; - return XFA_Element::Unknown; -} - -CXFA_Measurement XFA_GetAttributeDefaultValue_Measure(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - uint32_t dwPacket) { - void* pValue; - if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute, - XFA_ATTRIBUTETYPE_Measure, dwPacket)) { - return *(CXFA_Measurement*)pValue; - } - return CXFA_Measurement(); -} - -bool XFA_GetAttributeDefaultValue(void*& pValue, - XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - XFA_ATTRIBUTETYPE eType, - uint32_t dwPacket) { - const XFA_ATTRIBUTEINFO* pInfo = XFA_GetAttributeByID(eAttribute); - if (!pInfo) - return false; - if (dwPacket && (dwPacket & pInfo->dwPackets) == 0) - return false; - if (pInfo->eType == eType) { - pValue = pInfo->pDefValue; - return true; - } - if (pInfo->eType == XFA_ATTRIBUTETYPE_NOTSURE) { - const XFA_NOTSUREATTRIBUTE* pAttr = - XFA_GetNotsureAttribute(eElement, eAttribute, eType); - if (pAttr) { - pValue = pAttr->pValue; - return true; - } - } - return false; -} - -const XFA_ATTRIBUTEINFO* XFA_GetAttributeByName(const CFX_WideStringC& wsName) { - if (wsName.IsEmpty()) - return nullptr; - - uint32_t uHash = FX_HashCode_GetW(wsName, false); - int32_t iStart = 0; - int32_t iEnd = g_iXFAAttributeCount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_ATTRIBUTEINFO* pInfo = g_XFAAttributeData + iMid; - if (uHash == pInfo->uHash) - return pInfo; - if (uHash < pInfo->uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return nullptr; -} - -const XFA_ATTRIBUTEINFO* XFA_GetAttributeByID(XFA_ATTRIBUTE eName) { - return (eName < g_iXFAAttributeCount) ? (g_XFAAttributeData + eName) - : nullptr; -} - -const XFA_ATTRIBUTEENUMINFO* XFA_GetAttributeEnumByName( - const CFX_WideStringC& wsName) { - if (wsName.IsEmpty()) - return nullptr; - - uint32_t uHash = FX_HashCode_GetW(wsName, false); - int32_t iStart = 0; - int32_t iEnd = g_iXFAEnumCount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - const XFA_ATTRIBUTEENUMINFO* pInfo = g_XFAEnumData + iMid; - if (uHash == pInfo->uHash) - return pInfo; - if (uHash < pInfo->uHash) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return nullptr; -} - -const XFA_PACKETINFO* XFA_GetPacketByIndex(XFA_PACKET ePacket) { - return g_XFAPacketData + ePacket; -} - -const XFA_PACKETINFO* XFA_GetPacketByID(uint32_t dwPacket) { - int32_t iStart = 0, iEnd = g_iXFAPacketCount - 1; - do { - int32_t iMid = (iStart + iEnd) / 2; - uint32_t dwFind = (g_XFAPacketData + iMid)->eName; - if (dwPacket == dwFind) - return g_XFAPacketData + iMid; - if (dwPacket < dwFind) - iEnd = iMid - 1; - else - iStart = iMid + 1; - } while (iStart <= iEnd); - return nullptr; -} diff --git a/xfa/fxfa/parser/xfa_utils.h b/xfa/fxfa/parser/xfa_utils.h index d09afda0f95278aa4a5098950f7423c1d1a70f69..9308157b1fd9cca5ae673be782d96f8b0fb98f3d 100644 --- a/xfa/fxfa/parser/xfa_utils.h +++ b/xfa/fxfa/parser/xfa_utils.h @@ -7,207 +7,37 @@ #ifndef XFA_FXFA_PARSER_XFA_UTILS_H_ #define XFA_FXFA_PARSER_XFA_UTILS_H_ -#include "xfa/fde/xml/fde_xml.h" -#include "xfa/fgas/crt/fgas_stream.h" -#include "xfa/fgas/crt/fgas_utils.h" +#include "core/fxcrt/cfx_seekablestreamproxy.h" #include "xfa/fxfa/fxfa_basic.h" -class CFDE_XMLElement; -class CFDE_XMLNode; +class CFX_XMLElement; +class CFX_XMLNode; class CXFA_LocaleValue; class CXFA_Node; -class CXFA_WidgetData; +class CXFA_WidgetAcc; -bool XFA_FDEExtension_ResolveNamespaceQualifier( - CFDE_XMLElement* pNode, - const CFX_WideStringC& wsQualifier, - CFX_WideString& wsNamespaceURI); +double XFA_GetFractionalScale(uint32_t idx); +int XFA_GetMaxFractionalScale(); -template <class NodeType, class TraverseStrategy> -class CXFA_NodeIteratorTemplate { - public: - explicit CXFA_NodeIteratorTemplate(NodeType* pRootNode = nullptr) - : m_pRoot(pRootNode), m_NodeStack(100) { - if (pRootNode) { - m_NodeStack.Push(pRootNode); - } - } - bool Init(NodeType* pRootNode) { - if (!pRootNode) { - return false; - } - m_pRoot = pRootNode; - m_NodeStack.RemoveAll(false); - m_NodeStack.Push(pRootNode); - return true; - } - void Clear() { m_NodeStack.RemoveAll(false); } - void Reset() { - Clear(); - if (m_pRoot) { - m_NodeStack.Push(m_pRoot); - } - } - bool SetCurrent(NodeType* pCurNode) { - m_NodeStack.RemoveAll(false); - if (pCurNode) { - CFX_StackTemplate<NodeType*> revStack(100); - NodeType* pNode; - for (pNode = pCurNode; pNode && pNode != m_pRoot; - pNode = TraverseStrategy::GetParent(pNode)) { - revStack.Push(pNode); - } - if (!pNode) { - return false; - } - revStack.Push(m_pRoot); - while (revStack.GetSize()) { - m_NodeStack.Push(*revStack.GetTopElement()); - revStack.Pop(); - } - } - return true; - } - NodeType* GetCurrent() const { - return m_NodeStack.GetSize() ? *m_NodeStack.GetTopElement() : nullptr; - } - NodeType* GetRoot() const { return m_pRoot; } - NodeType* MoveToPrev() { - int32_t nStackLength = m_NodeStack.GetSize(); - if (nStackLength == 1) { - return nullptr; - } else if (nStackLength > 1) { - NodeType* pCurItem = *m_NodeStack.GetTopElement(); - m_NodeStack.Pop(); - NodeType* pParentItem = *m_NodeStack.GetTopElement(); - NodeType* pParentFirstChildItem = - TraverseStrategy::GetFirstChild(pParentItem); - if (pCurItem == pParentFirstChildItem) { - return pParentItem; - } - NodeType *pPrevItem = pParentFirstChildItem, *pPrevItemNext = nullptr; - for (; pPrevItem; pPrevItem = pPrevItemNext) { - pPrevItemNext = TraverseStrategy::GetNextSibling(pPrevItem); - if (!pPrevItemNext || pPrevItemNext == pCurItem) { - break; - } - } - m_NodeStack.Push(pPrevItem); - } else { - m_NodeStack.RemoveAll(false); - if (m_pRoot) { - m_NodeStack.Push(m_pRoot); - } - } - if (m_NodeStack.GetSize() > 0) { - NodeType* pChildItem = *m_NodeStack.GetTopElement(); - while ((pChildItem = TraverseStrategy::GetFirstChild(pChildItem)) != - nullptr) { - while (NodeType* pNextItem = - TraverseStrategy::GetNextSibling(pChildItem)) { - pChildItem = pNextItem; - } - m_NodeStack.Push(pChildItem); - } - return *m_NodeStack.GetTopElement(); - } - return nullptr; - } - NodeType* MoveToNext() { - NodeType** ppNode = nullptr; - NodeType* pCurrent = GetCurrent(); - while (m_NodeStack.GetSize() > 0) { - while ((ppNode = m_NodeStack.GetTopElement()) != nullptr) { - if (pCurrent != *ppNode) { - return *ppNode; - } - NodeType* pChild = TraverseStrategy::GetFirstChild(*ppNode); - if (!pChild) { - break; - } - m_NodeStack.Push(pChild); - } - while ((ppNode = m_NodeStack.GetTopElement()) != nullptr) { - NodeType* pNext = TraverseStrategy::GetNextSibling(*ppNode); - m_NodeStack.Pop(); - if (m_NodeStack.GetSize() == 0) { - break; - } - if (pNext) { - m_NodeStack.Push(pNext); - break; - } - } - } - return nullptr; - } - NodeType* SkipChildrenAndMoveToNext() { - NodeType** ppNode = nullptr; - while ((ppNode = m_NodeStack.GetTopElement()) != nullptr) { - NodeType* pNext = TraverseStrategy::GetNextSibling(*ppNode); - m_NodeStack.Pop(); - if (m_NodeStack.GetSize() == 0) { - break; - } - if (pNext) { - m_NodeStack.Push(pNext); - break; - } - } - return GetCurrent(); - } +bool XFA_FDEExtension_ResolveNamespaceQualifier(CFX_XMLElement* pNode, + const WideString& wsQualifier, + WideString* wsNamespaceURI); - protected: - NodeType* m_pRoot; - CFX_StackTemplate<NodeType*> m_NodeStack; -}; - -CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData); -FX_DOUBLE XFA_ByteStringToDouble(const CFX_ByteStringC& szStringVal); +CXFA_LocaleValue XFA_GetLocaleValue(CXFA_Node* pNode); int32_t XFA_MapRotation(int32_t nRotation); -bool XFA_RecognizeRichText(CFDE_XMLElement* pRichTextXMLNode); -void XFA_GetPlainTextFromRichText(CFDE_XMLNode* pXMLNode, - CFX_WideString& wsPlainText); +bool XFA_RecognizeRichText(CFX_XMLElement* pRichTextXMLNode); bool XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode); void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode); void XFA_DataExporter_RegenerateFormFile( CXFA_Node* pNode, - const CFX_RetainPtr<IFGAS_Stream>& pStream, - const FX_CHAR* pChecksum = nullptr, - bool bSaveXML = false); - -const XFA_NOTSUREATTRIBUTE* XFA_GetNotsureAttribute( - XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - XFA_ATTRIBUTETYPE eType = XFA_ATTRIBUTETYPE_NOTSURE); + const RetainPtr<CFX_SeekableStreamProxy>& pStream, + const char* pChecksum, + bool bSaveXML); const XFA_SCRIPTATTRIBUTEINFO* XFA_GetScriptAttributeByName( XFA_Element eElement, - const CFX_WideStringC& wsAttributeName); - -const XFA_PROPERTY* XFA_GetPropertyOfElement(XFA_Element eElement, - XFA_Element eProperty, - uint32_t dwPacket); -const XFA_PROPERTY* XFA_GetElementProperties(XFA_Element eElement, - int32_t& iCount); -const uint8_t* XFA_GetElementAttributes(XFA_Element eElement, int32_t& iCount); -const XFA_ELEMENTINFO* XFA_GetElementByID(XFA_Element eName); -XFA_Element XFA_GetElementTypeForName(const CFX_WideStringC& wsName); -CXFA_Measurement XFA_GetAttributeDefaultValue_Measure(XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - uint32_t dwPacket); -bool XFA_GetAttributeDefaultValue(void*& pValue, - XFA_Element eElement, - XFA_ATTRIBUTE eAttribute, - XFA_ATTRIBUTETYPE eType, - uint32_t dwPacket); -const XFA_ATTRIBUTEINFO* XFA_GetAttributeByName(const CFX_WideStringC& wsName); -const XFA_ATTRIBUTEINFO* XFA_GetAttributeByID(XFA_ATTRIBUTE eName); -const XFA_ATTRIBUTEENUMINFO* XFA_GetAttributeEnumByName( - const CFX_WideStringC& wsName); -const XFA_PACKETINFO* XFA_GetPacketByIndex(XFA_PACKET ePacket); -const XFA_PACKETINFO* XFA_GetPacketByID(uint32_t dwPacket); + const WideStringView& wsAttributeName); #endif // XFA_FXFA_PARSER_XFA_UTILS_H_ diff --git a/xfa/fxfa/parser/xfa_utils_unittest.cpp b/xfa/fxfa/parser/xfa_utils_unittest.cpp index 93ee3b94aa92caa93876bd71f96aa2de0fa96562..c9f662eb8d6c26094422da6566766c47f1bd1204 100644 --- a/xfa/fxfa/parser/xfa_utils_unittest.cpp +++ b/xfa/fxfa/parser/xfa_utils_unittest.cpp @@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "testing/gtest/include/gtest/gtest.h" #include "xfa/fxfa/parser/xfa_utils.h" -TEST(XfaUtilsImp, XFA_MapRotation) { +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(XfaUtilsImpTest, XFA_MapRotation) { struct TestCase { int input; int expected_output; diff --git a/xfa/fxfa/xfa_checksum.h b/xfa/fxfa/xfa_checksum.h deleted file mode 100644 index 31cf1015535e88900076f3961befd28f38d225ca..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_checksum.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_CHECKSUM_H_ -#define XFA_FXFA_XFA_CHECKSUM_H_ - -#include <memory> - -#include "core/fdrm/crypto/fx_crypt.h" -#include "xfa/fde/xml/cfx_saxreader.h" -#include "xfa/fxfa/fxfa.h" - -class CXFA_SAXReaderHandler; -class CXFA_ChecksumContext; - -class CXFA_SAXContext { - public: - CXFA_SAXContext() : m_eNode(CFX_SAXItem::Type::Unknown) {} - - CFX_ByteTextBuf m_TextBuf; - CFX_ByteString m_bsTagName; - CFX_SAXItem::Type m_eNode; -}; - -class CXFA_SAXReaderHandler { - public: - explicit CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext); - ~CXFA_SAXReaderHandler(); - - CXFA_SAXContext* OnTagEnter(const CFX_ByteStringC& bsTagName, - CFX_SAXItem::Type eType, - uint32_t dwStartPos); - void OnTagAttribute(CXFA_SAXContext* pTag, - const CFX_ByteStringC& bsAttri, - const CFX_ByteStringC& bsValue); - void OnTagBreak(CXFA_SAXContext* pTag); - void OnTagData(CXFA_SAXContext* pTag, - CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, - uint32_t dwStartPos); - void OnTagClose(CXFA_SAXContext* pTag, uint32_t dwEndPos); - void OnTagEnd(CXFA_SAXContext* pTag, - const CFX_ByteStringC& bsTagName, - uint32_t dwEndPos); - - void OnTargetData(CXFA_SAXContext* pTag, - CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, - uint32_t dwStartPos); - - protected: - void UpdateChecksum(bool bCheckSpace); - - CXFA_ChecksumContext* m_pContext; - CXFA_SAXContext m_SAXContext; -}; - -class CXFA_ChecksumContext { - public: - CXFA_ChecksumContext(); - ~CXFA_ChecksumContext(); - - void StartChecksum(); - void Update(const CFX_ByteStringC& bsText); - bool UpdateChecksum(const CFX_RetainPtr<IFX_SeekableReadStream>& pSrcFile, - FX_FILESIZE offset = 0, - size_t size = 0); - void FinishChecksum(); - CFX_ByteString GetChecksum() const; - - protected: - std::unique_ptr<CFX_SAXReader> m_pSAXReader; - std::unique_ptr<CRYPT_sha1_context> m_pByteContext; - CFX_ByteString m_bsChecksum; -}; - -#endif // XFA_FXFA_XFA_CHECKSUM_H_ diff --git a/xfa/fxfa/xfa_ffapp.h b/xfa/fxfa/xfa_ffapp.h deleted file mode 100644 index 411fd2d273bcb54d51230aefdb8e6002df70ce2c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffapp.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFAPP_H_ -#define XFA_FXFA_XFA_FFAPP_H_ - -#include <memory> -#include <vector> - -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcrt/cfx_retain_ptr.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" -#include "xfa/fwl/cfwl_app.h" -#include "xfa/fxfa/fxfa.h" - -class CXFA_DefFontMgr; -class CXFA_FWLAdapterWidgetMgr; -class CXFA_FWLTheme; -class CXFA_FFDocHandler; -class CXFA_FontMgr; -class IFWL_AdapterTimerMgr; -class CFWL_WidgetMgrDelegate; - -// Layering prevents fxcrt from knowing about CPDF_Streams; this could go -// in fpdfsdk, but it is XFA-Only. -CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream( - const std::vector<CPDF_Stream*>& streams); - -class CXFA_FFApp { - public: - explicit CXFA_FFApp(IXFA_AppProvider* pProvider); - ~CXFA_FFApp(); - - std::unique_ptr<CXFA_FFDoc> CreateDoc(IXFA_DocEnvironment* pDocEnvironment, - CPDF_Document* pPDFDoc); - void SetDefaultFontMgr(std::unique_ptr<CXFA_DefFontMgr> pFontMgr); - - CXFA_FFDocHandler* GetDocHandler(); - CXFA_FWLAdapterWidgetMgr* GetWidgetMgr(CFWL_WidgetMgrDelegate* pDelegate); - CFGAS_FontMgr* GetFDEFontMgr(); - CXFA_FWLTheme* GetFWLTheme(); - - IXFA_AppProvider* GetAppProvider() const { return m_pProvider; } - const CFWL_App* GetFWLApp() const { return m_pFWLApp.get(); } - IFWL_AdapterTimerMgr* GetTimerMgr() const; - CXFA_FontMgr* GetXFAFontMgr() const; - CFWL_WidgetMgrDelegate* GetWidgetMgrDelegate() const { - return m_pWidgetMgrDelegate; - } - - void ClearEventTargets(); - - protected: - std::unique_ptr<CXFA_FFDocHandler> m_pDocHandler; - IXFA_AppProvider* const m_pProvider; - - // The fonts stored in the font manager may have been created by the default - // font manager. The GEFont::LoadFont call takes the manager as a param and - // stores it internally. When you destroy the GEFont it tries to unregister - // from the font manager and if the default font manager was destroyed first - // get get a use-after-free. The m_pFWLTheme can try to cleanup a GEFont - // when it frees, so make sure it gets cleaned up first. That requires - // m_pFWLApp to be cleaned up as well. - // - // TODO(dsinclair): The GEFont should have the FontMgr as the pointer instead - // of the DEFFontMgr so this goes away. Bug 561. - std::unique_ptr<CFGAS_FontMgr> m_pFDEFontMgr; - std::unique_ptr<CXFA_FontMgr> m_pFontMgr; - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - std::unique_ptr<CFX_FontSourceEnum_File> m_pFontSource; -#endif - std::unique_ptr<CXFA_FWLAdapterWidgetMgr> m_pAdapterWidgetMgr; - CFWL_WidgetMgrDelegate* m_pWidgetMgrDelegate; // not owned. - - // |m_pFWLApp| has to be released first, then |m_pFWLTheme| since the former - // may refers to theme manager and the latter refers to font manager. - std::unique_ptr<CXFA_FWLTheme> m_pFWLTheme; - std::unique_ptr<CFWL_App> m_pFWLApp; -}; - -#endif // XFA_FXFA_XFA_FFAPP_H_ diff --git a/xfa/fxfa/xfa_ffdoc.h b/xfa/fxfa/xfa_ffdoc.h deleted file mode 100644 index 44079704e7b56868c3334ec09fe099fa2b3bc48b..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffdoc.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFDOC_H_ -#define XFA_FXFA_XFA_FFDOC_H_ - -#include <map> -#include <memory> - -#include "xfa/fxfa/fxfa.h" -#include "xfa/fxfa/parser/cxfa_document.h" -#include "xfa/fxfa/parser/cxfa_document_parser.h" - -class CXFA_ChecksumContext; -class CXFA_FFApp; -class CXFA_FFNotify; -class CXFA_FFDocView; - -struct FX_IMAGEDIB_AND_DPI { - CFX_DIBSource* pDibSource; - int32_t iImageXDpi; - int32_t iImageYDpi; -}; - -class CXFA_FFDoc { - public: - CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment); - ~CXFA_FFDoc(); - - IXFA_DocEnvironment* GetDocEnvironment() const { return m_pDocEnvironment; } - uint32_t GetDocType(); - void SetDocType(uint32_t dwType); - - int32_t StartLoad(); - int32_t DoLoad(IFX_Pause* pPause = nullptr); - void StopLoad(); - - CXFA_FFDocView* CreateDocView(uint32_t dwView = 0); - - bool OpenDoc(const CFX_RetainPtr<IFX_SeekableReadStream>& pStream); - bool OpenDoc(CPDF_Document* pPDFDoc); - bool CloseDoc(); - - CXFA_Document* GetXFADoc() { return m_pDocumentParser->GetDocument(); } - CXFA_FFApp* GetApp() { return m_pApp; } - CXFA_FFDocView* GetDocView(CXFA_LayoutProcessor* pLayout); - CXFA_FFDocView* GetDocView(); - CPDF_Document* GetPDFDoc(); - CFX_DIBitmap* GetPDFNamedImage(const CFX_WideStringC& wsName, - int32_t& iImageXDpi, - int32_t& iImageYDpi); - - bool SavePackage(XFA_HashCode code, - const CFX_RetainPtr<IFX_SeekableWriteStream>& pFile, - CXFA_ChecksumContext* pCSContext); - bool ImportData(const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, - bool bXDP = true); - - protected: - IXFA_DocEnvironment* const m_pDocEnvironment; - std::unique_ptr<CXFA_DocumentParser> m_pDocumentParser; - CFX_RetainPtr<IFX_SeekableReadStream> m_pStream; - CXFA_FFApp* m_pApp; - std::unique_ptr<CXFA_FFNotify> m_pNotify; - CPDF_Document* m_pPDFDoc; - std::map<uint32_t, FX_IMAGEDIB_AND_DPI> m_HashToDibDpiMap; - std::map<uint32_t, std::unique_ptr<CXFA_FFDocView>> m_TypeToDocViewMap; - uint32_t m_dwDocType; -}; - -#endif // XFA_FXFA_XFA_FFDOC_H_ diff --git a/xfa/fxfa/xfa_ffdochandler.h b/xfa/fxfa/xfa_ffdochandler.h deleted file mode 100644 index 0e4f71786cae66ac2e7472e03c48b722fa2cb5f5..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffdochandler.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFDOCHANDLER_H_ -#define XFA_FXFA_XFA_FFDOCHANDLER_H_ - -#include "xfa/fxfa/fxfa.h" - -class CXFA_ChecksumContext; - -class CXFA_FFDocHandler { - public: - CXFA_FFDocHandler(); - ~CXFA_FFDocHandler(); - - CFXJSE_Value* GetXFAScriptObject(CXFA_FFDoc* hDoc); - XFA_ATTRIBUTEENUM GetRestoreState(CXFA_FFDoc* hDoc); - - bool RunDocScript(CXFA_FFDoc* hDoc, - XFA_SCRIPTTYPE eScriptType, - const CFX_WideStringC& wsScript, - CFXJSE_Value* pRetValue, - CFXJSE_Value* pThisObject); - - protected: -}; - -#endif // XFA_FXFA_XFA_FFDOCHANDLER_H_ diff --git a/xfa/fxfa/xfa_ffdocview.h b/xfa/fxfa/xfa_ffdocview.h deleted file mode 100644 index d8df8b4312daeffcd98e61cbe149ff05c22c421f..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffdocview.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFDOCVIEW_H_ -#define XFA_FXFA_XFA_FFDOCVIEW_H_ - -#include <map> -#include <memory> -#include <vector> - -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/xfa_ffdoc.h" - -class CXFA_FFWidgetHandler; -class CXFA_FFDoc; -class CXFA_FFWidget; -class CXFA_WidgetAccIterator; - -extern const XFA_ATTRIBUTEENUM gs_EventActivity[]; -enum XFA_DOCVIEW_LAYOUTSTATUS { - XFA_DOCVIEW_LAYOUTSTATUS_None, - XFA_DOCVIEW_LAYOUTSTATUS_Start, - XFA_DOCVIEW_LAYOUTSTATUS_FormInitialize, - XFA_DOCVIEW_LAYOUTSTATUS_FormInitCalculate, - XFA_DOCVIEW_LAYOUTSTATUS_FormInitValidate, - XFA_DOCVIEW_LAYOUTSTATUS_FormFormReady, - XFA_DOCVIEW_LAYOUTSTATUS_Doing, - XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitialize, - XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitCalculate, - XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitValidate, - XFA_DOCVIEW_LAYOUTSTATUS_PagesetFormReady, - XFA_DOCVIEW_LAYOUTSTATUS_LayoutReady, - XFA_DOCVIEW_LAYOUTSTATUS_DocReady, - XFA_DOCVIEW_LAYOUTSTATUS_End -}; -class CXFA_FFDocView { - public: - explicit CXFA_FFDocView(CXFA_FFDoc* pDoc); - ~CXFA_FFDocView(); - - CXFA_FFDoc* GetDoc() { return m_pDoc; } - int32_t StartLayout(int32_t iStartPage = 0); - int32_t DoLayout(IFX_Pause* pPause); - void StopLayout(); - int32_t GetLayoutStatus(); - void UpdateDocView(); - int32_t CountPageViews(); - CXFA_FFPageView* GetPageView(int32_t nIndex); - - void ResetWidgetData(CXFA_WidgetAcc* pWidgetAcc); - int32_t ProcessWidgetEvent(CXFA_EventParam* pParam, - CXFA_WidgetAcc* pWidgetAcc); - CXFA_FFWidgetHandler* GetWidgetHandler(); - CXFA_WidgetAccIterator* CreateWidgetAccIterator( - XFA_WIDGETORDER eOrder = XFA_WIDGETORDER_PreOrder); - CXFA_FFWidget* GetFocusWidget(); - void KillFocus(); - bool SetFocus(CXFA_FFWidget* hWidget); - CXFA_FFWidget* GetWidgetByName(const CFX_WideString& wsName, - CXFA_FFWidget* pRefWidget); - CXFA_WidgetAcc* GetWidgetAccByName(const CFX_WideString& wsName, - CXFA_WidgetAcc* pRefWidgetAcc); - CXFA_LayoutProcessor* GetXFALayout() const; - void OnPageEvent(CXFA_ContainerLayoutItem* pSender, uint32_t dwEvent); - void LockUpdate(); - void UnlockUpdate(); - bool IsUpdateLocked(); - void ClearInvalidateList(); - void AddInvalidateRect(CXFA_FFWidget* pWidget, const CFX_RectF& rtInvalidate); - void AddInvalidateRect(CXFA_FFPageView* pPageView, - const CFX_RectF& rtInvalidate); - void RunInvalidate(); - void RunDocClose(); - void DestroyDocView(); - - bool InitValidate(CXFA_Node* pNode); - bool RunValidate(); - - void SetChangeMark(); - - void AddValidateWidget(CXFA_WidgetAcc* pWidget); - void AddCalculateNodeNotify(CXFA_Node* pNodeChange); - void AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc); - int32_t RunCalculateWidgets(); - bool IsStaticNotify(); - bool RunLayout(); - void RunSubformIndexChange(); - void AddNewFormNode(CXFA_Node* pNode); - void AddIndexChangedSubform(CXFA_Node* pNode); - CXFA_WidgetAcc* GetFocusWidgetAcc(); - void SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc); - void DeleteLayoutItem(CXFA_FFWidget* pWidget); - int32_t ExecEventActivityByDeepFirst(CXFA_Node* pFormNode, - XFA_EVENTTYPE eEventType, - bool bIsFormReady, - bool bRecursive, - CXFA_Node* pExclude); - bool m_bLayoutEvent; - std::vector<CFX_WideString> m_arrNullTestMsg; - CXFA_FFWidget* m_pListFocusWidget; - bool m_bInLayoutStatus; - - protected: - bool RunEventLayoutReady(); - void RunBindItems(); - bool InitCalculate(CXFA_Node* pNode); - void InitLayout(CXFA_Node* pNode); - void RunCalculateRecursive(int32_t& iIndex); - void ShowNullTestMsg(); - bool ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc); - CXFA_Node* GetRootSubform(); - - CXFA_FFDoc* const m_pDoc; - std::unique_ptr<CXFA_FFWidgetHandler> m_pWidgetHandler; - CXFA_LayoutProcessor* m_pXFADocLayout; // not owned. - CXFA_WidgetAcc* m_pFocusAcc; // not owned. - CXFA_FFWidget* m_pFocusWidget; // not owned. - CXFA_FFWidget* m_pOldFocusWidget; // not owned. - std::map<CXFA_FFPageView*, std::unique_ptr<CFX_RectF>> m_mapPageInvalidate; - std::vector<CXFA_WidgetAcc*> m_ValidateAccs; - std::vector<CXFA_WidgetAcc*> m_CalculateAccs; - std::vector<CXFA_Node*> m_BindItems; - std::vector<CXFA_Node*> m_NewAddedNodes; - std::vector<CXFA_Node*> m_IndexChangedSubforms; - XFA_DOCVIEW_LAYOUTSTATUS m_iStatus; - int32_t m_iLock; - friend class CXFA_FFNotify; -}; - -class CXFA_WidgetAccIterator { - public: - CXFA_WidgetAccIterator(CXFA_FFDocView* pDocView, CXFA_Node* pTravelRoot); - ~CXFA_WidgetAccIterator(); - - void Reset(); - CXFA_WidgetAcc* MoveToFirst(); - CXFA_WidgetAcc* MoveToLast(); - CXFA_WidgetAcc* MoveToNext(); - CXFA_WidgetAcc* MoveToPrevious(); - CXFA_WidgetAcc* GetCurrentWidgetAcc(); - bool SetCurrentWidgetAcc(CXFA_WidgetAcc* hWidget); - void SkipTree(); - - protected: - CXFA_ContainerIterator m_ContentIterator; - CXFA_FFDocView* const m_pDocView; - CXFA_WidgetAcc* m_pCurWidgetAcc; // not owned. -}; - -#endif // XFA_FXFA_XFA_FFDOCVIEW_H_ diff --git a/xfa/fxfa/xfa_ffpageview.h b/xfa/fxfa/xfa_ffpageview.h deleted file mode 100644 index 4b50a2365dbbc0c0ed19ac0da708510b00332917..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffpageview.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyrig 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFPAGEVIEW_H_ -#define XFA_FXFA_XFA_FFPAGEVIEW_H_ - -#include <vector> - -#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h" -#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" -#include "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h" - -class CXFA_FFWidget; -class CXFA_FFDocView; - -class CXFA_FFPageView : public CXFA_ContainerLayoutItem { - public: - CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea); - ~CXFA_FFPageView() override; - - CXFA_FFDocView* GetDocView() const; - CFX_RectF GetPageViewRect() const; - CFX_Matrix GetDisplayMatrix(const CFX_Rect& rtDisp, int32_t iRotate) const; - IXFA_WidgetIterator* CreateWidgetIterator( - uint32_t dwTraverseWay = XFA_TRAVERSEWAY_Form, - uint32_t dwWidgetFilter = XFA_WidgetStatus_Visible | - XFA_WidgetStatus_Viewable); - - protected: - CXFA_FFDocView* const m_pDocView; -}; - -typedef CXFA_NodeIteratorTemplate<CXFA_LayoutItem, - CXFA_TraverseStrategy_LayoutItem> - CXFA_LayoutItemIterator; - -class CXFA_FFPageWidgetIterator : public IXFA_WidgetIterator { - public: - CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView, uint32_t dwFilter); - ~CXFA_FFPageWidgetIterator() override; - - void Reset() override; - CXFA_FFWidget* MoveToFirst() override; - CXFA_FFWidget* MoveToLast() override; - CXFA_FFWidget* MoveToNext() override; - CXFA_FFWidget* MoveToPrevious() override; - CXFA_FFWidget* GetCurrentWidget() override; - bool SetCurrentWidget(CXFA_FFWidget* hWidget) override; - - protected: - CXFA_FFWidget* GetWidget(CXFA_LayoutItem* pLayoutItem); - - CXFA_FFPageView* m_pPageView; - CXFA_FFWidget* m_hCurWidget; - uint32_t m_dwFilter; - bool m_bIgnorerelevant; - CXFA_LayoutItemIterator m_sIterator; -}; - -class CXFA_TabParam { - public: - CXFA_TabParam(); - ~CXFA_TabParam(); - - CXFA_FFWidget* m_pWidget; - std::vector<CXFA_FFWidget*> m_Children; -}; - -class CXFA_FFTabOrderPageWidgetIterator : public IXFA_WidgetIterator { - public: - CXFA_FFTabOrderPageWidgetIterator(CXFA_FFPageView* pPageView, - uint32_t dwFilter); - ~CXFA_FFTabOrderPageWidgetIterator() override; - - void Reset() override; - CXFA_FFWidget* MoveToFirst() override; - CXFA_FFWidget* MoveToLast() override; - CXFA_FFWidget* MoveToNext() override; - CXFA_FFWidget* MoveToPrevious() override; - CXFA_FFWidget* GetCurrentWidget() override; - bool SetCurrentWidget(CXFA_FFWidget* hWidget) override; - - protected: - CXFA_FFWidget* GetTraverseWidget(CXFA_FFWidget* pWidget); - CXFA_FFWidget* FindWidgetByName(const CFX_WideString& wsWidgetName, - CXFA_FFWidget* pRefWidget); - void CreateTabOrderWidgetArray(); - void CreateSpaceOrderWidgetArray(std::vector<CXFA_FFWidget*>* WidgetArray); - CXFA_FFWidget* GetWidget(CXFA_LayoutItem* pLayoutItem); - void OrderContainer(CXFA_LayoutItemIterator* sIterator, - CXFA_LayoutItem* pContainerItem, - CXFA_TabParam* pContainer, - bool& bCurrentItem, - bool& bContentArea, - bool bMarsterPage = false); - - std::vector<CXFA_FFWidget*> m_TabOrderWidgetArray; - CXFA_FFPageView* m_pPageView; - uint32_t m_dwFilter; - int32_t m_iCurWidget; - bool m_bIgnorerelevant; -}; - -#endif // XFA_FXFA_XFA_FFPAGEVIEW_H_ diff --git a/xfa/fxfa/xfa_ffwidget.h b/xfa/fxfa/xfa_ffwidget.h deleted file mode 100644 index 5972b8ad70e9bfda816be530fecfcc62e78b4e9d..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffwidget.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFWIDGET_H_ -#define XFA_FXFA_XFA_FFWIDGET_H_ - -#include <vector> - -#include "core/fxcodec/fx_codec_def.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "xfa/fwl/cfwl_app.h" -#include "xfa/fxfa/fxfa.h" -#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h" - -class CXFA_FFPageView; -class CXFA_FFDocView; -class CXFA_FFDoc; -class CXFA_FFApp; -enum class FWL_WidgetHit; - -inline FX_FLOAT XFA_UnitPx2Pt(FX_FLOAT fPx, FX_FLOAT fDpi) { - return fPx * 72.0f / fDpi; -} - -#define XFA_FLOAT_PERCISION 0.001f - -enum XFA_WIDGETITEM { - XFA_WIDGETITEM_Parent, - XFA_WIDGETITEM_FirstChild, - XFA_WIDGETITEM_NextSibling, - XFA_WIDGETITEM_PrevSibling, -}; - -class CXFA_CalcData { - public: - CXFA_CalcData(); - ~CXFA_CalcData(); - - std::vector<CXFA_WidgetAcc*> m_Globals; - int32_t m_iRefCount; -}; - -class CXFA_FFWidget : public CXFA_ContentLayoutItem { - public: - explicit CXFA_FFWidget(CXFA_WidgetAcc* pDataAcc); - ~CXFA_FFWidget() override; - - virtual CFX_RectF GetBBox(uint32_t dwStatus, bool bDrawFocus = false); - virtual void RenderWidget(CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - uint32_t dwStatus); - virtual bool IsLoaded(); - virtual bool LoadWidget(); - virtual void UnloadWidget(); - virtual bool PerformLayout(); - virtual bool UpdateFWLData(); - virtual void UpdateWidgetProperty(); - virtual bool OnMouseEnter(); - virtual bool OnMouseExit(); - virtual bool OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point); - virtual bool OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point); - virtual bool OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point); - virtual bool OnMouseMove(uint32_t dwFlags, const CFX_PointF& point); - virtual bool OnMouseWheel(uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point); - virtual bool OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point); - virtual bool OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point); - virtual bool OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point); - - virtual bool OnSetFocus(CXFA_FFWidget* pOldWidget); - virtual bool OnKillFocus(CXFA_FFWidget* pNewWidget); - virtual bool OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags); - virtual bool OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags); - virtual bool OnChar(uint32_t dwChar, uint32_t dwFlags); - virtual FWL_WidgetHit OnHitTest(const CFX_PointF& point); - virtual bool OnSetCursor(const CFX_PointF& point); - virtual bool CanUndo(); - virtual bool CanRedo(); - virtual bool Undo(); - virtual bool Redo(); - virtual bool CanCopy(); - virtual bool CanCut(); - virtual bool CanPaste(); - virtual bool CanSelectAll(); - virtual bool CanDelete(); - virtual bool CanDeSelect(); - virtual bool Copy(CFX_WideString& wsCopy); - virtual bool Cut(CFX_WideString& wsCut); - virtual bool Paste(const CFX_WideString& wsPaste); - virtual void SelectAll(); - virtual void Delete(); - virtual void DeSelect(); - virtual bool GetSuggestWords(CFX_PointF pointf, - std::vector<CFX_ByteString>& sSuggest); - virtual bool ReplaceSpellCheckWord(CFX_PointF pointf, - const CFX_ByteStringC& bsReplace); - - CXFA_FFPageView* GetPageView() const { return m_pPageView; } - void SetPageView(CXFA_FFPageView* pPageView) { m_pPageView = pPageView; } - CFX_RectF GetWidgetRect(); - CFX_RectF RecacheWidgetRect(); - uint32_t GetStatus(); - void ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved); - - CXFA_WidgetAcc* GetDataAcc(); - bool GetToolTip(CFX_WideString& wsToolTip); - - CXFA_FFDocView* GetDocView(); - void SetDocView(CXFA_FFDocView* pDocView); - CXFA_FFDoc* GetDoc(); - CXFA_FFApp* GetApp(); - IXFA_AppProvider* GetAppProvider(); - void InvalidateWidget(const CFX_RectF* pRect = nullptr); - void AddInvalidateRect(const CFX_RectF* pRect = nullptr); - bool GetCaptionText(CFX_WideString& wsCap); - bool IsFocused(); - CFX_PointF Rotate2Normal(const CFX_PointF& point); - CFX_Matrix GetRotateMatrix(); - bool IsLayoutRectEmpty(); - CXFA_FFWidget* GetParent(); - bool IsAncestorOf(CXFA_FFWidget* pWidget); - const CFWL_App* GetFWLApp(); - - protected: - virtual bool PtInActiveRect(const CFX_PointF& point); - - void DrawBorder(CFX_Graphics* pGS, - CXFA_Box box, - const CFX_RectF& rtBorder, - CFX_Matrix* pMatrix, - uint32_t dwFlags = 0); - - CFX_RectF GetRectWithoutRotate(); - bool IsMatchVisibleStatus(uint32_t dwStatus); - void EventKillFocus(); - bool IsButtonDown(); - void SetButtonDown(bool bSet); - - CXFA_FFDocView* m_pDocView; - CXFA_FFPageView* m_pPageView; - CXFA_WidgetAcc* m_pDataAcc; - CFX_RectF m_rtWidget; -}; - -int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics, - int32_t iStrokeType, - int32_t iCapType); -CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap); -void XFA_DrawImage(CFX_Graphics* pGS, - const CFX_RectF& rtImage, - CFX_Matrix* pMatrix, - CFX_DIBitmap* pDIBitmap, - int32_t iAspect, - int32_t iImageXDpi, - int32_t iImageYDpi, - int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left, - int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top); - -CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc, - CXFA_Image* pImage, - bool& bNameImage, - int32_t& iImageXDpi, - int32_t& iImageYDpi); - -CFX_DIBitmap* XFA_LoadImageFromBuffer( - const CFX_RetainPtr<IFX_SeekableReadStream>& pImageFileRead, - FXCODEC_IMAGE_TYPE type, - int32_t& iImageXDpi, - int32_t& iImageYDpi); - -FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideString& wsType); -FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len); -void XFA_RectWidthoutMargin(CFX_RectF& rt, - const CXFA_Margin& mg, - bool bUI = false); -CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem); -bool XFA_IsCreateWidget(XFA_Element iType); -#define XFA_DRAWBOX_ForceRound 1 -#define XFA_DRAWBOX_Lowered3D 2 -void XFA_DrawBox(CXFA_Box box, - CFX_Graphics* pGS, - const CFX_RectF& rtWidget, - CFX_Matrix* pMatrix, - uint32_t dwFlags = 0); - -#endif // XFA_FXFA_XFA_FFWIDGET_H_ diff --git a/xfa/fxfa/xfa_ffwidgethandler.h b/xfa/fxfa/xfa_ffwidgethandler.h deleted file mode 100644 index 66bda3e02a5fb2742b9070fa51560a54478f6c0c..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_ffwidgethandler.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FFWIDGETHANDLER_H_ -#define XFA_FXFA_XFA_FFWIDGETHANDLER_H_ - -#include <vector> - -#include "xfa/fxfa/cxfa_eventparam.h" -#include "xfa/fxfa/fxfa.h" -#include "xfa/fxfa/parser/cxfa_document.h" - -class CXFA_FFDocView; -enum class FWL_WidgetHit; - -class CXFA_FFWidgetHandler { - public: - explicit CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView); - ~CXFA_FFWidgetHandler(); - - CXFA_FFWidget* CreateWidget(CXFA_FFWidget* hParent, - XFA_WIDGETTYPE eType, - CXFA_FFWidget* hBefore = nullptr); - - bool OnMouseEnter(CXFA_FFWidget* hWidget); - bool OnMouseExit(CXFA_FFWidget* hWidget); - bool OnLButtonDown(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - bool OnLButtonUp(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - bool OnLButtonDblClk(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - bool OnMouseMove(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - bool OnMouseWheel(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - int16_t zDelta, - const CFX_PointF& point); - bool OnRButtonDown(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - bool OnRButtonUp(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - bool OnRButtonDblClk(CXFA_FFWidget* hWidget, - uint32_t dwFlags, - const CFX_PointF& point); - - bool OnKeyDown(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags); - bool OnKeyUp(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags); - bool OnChar(CXFA_FFWidget* hWidget, uint32_t dwChar, uint32_t dwFlags); - FWL_WidgetHit OnHitTest(CXFA_FFWidget* hWidget, const CFX_PointF& point); - bool OnSetCursor(CXFA_FFWidget* hWidget, const CFX_PointF& point); - void RenderWidget(CXFA_FFWidget* hWidget, - CFX_Graphics* pGS, - CFX_Matrix* pMatrix, - bool bHighlight); - bool HasEvent(CXFA_WidgetAcc* pWidgetAcc, XFA_EVENTTYPE eEventType); - int32_t ProcessEvent(CXFA_WidgetAcc* pWidgetAcc, CXFA_EventParam* pParam); - - protected: - CXFA_Node* CreateWidgetFormItem(XFA_WIDGETTYPE eType, - CXFA_Node* pParent, - CXFA_Node* pBefore) const; - - CXFA_Node* CreatePushButton(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateCheckButton(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateExclGroup(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateRadioButton(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateDatetimeEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateDecimalField(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateNumericField(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateSignature(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateTextEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateDropdownList(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateListBox(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateImageField(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreatePasswordEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateField(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const; - CXFA_Node* CreateArc(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateRectangle(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateImage(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateLine(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateText(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateDraw(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const; - - CXFA_Node* CreateSubform(CXFA_Node* pParent, CXFA_Node* pBefore) const; - CXFA_Node* CreateFormItem(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const; - CXFA_Node* CreateCopyNode(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore = nullptr) const; - CXFA_Node* CreateTemplateNode(XFA_Element eElement, - CXFA_Node* pParent, - CXFA_Node* pBefore) const; - CXFA_Node* CreateFontNode(CXFA_Node* pParent) const; - CXFA_Node* CreateMarginNode(CXFA_Node* pParent, - uint32_t dwFlags, - FX_FLOAT fInsets[4]) const; - CXFA_Node* CreateValueNode(XFA_Element eValue, CXFA_Node* pParent) const; - CXFA_Document* GetObjFactory() const; - CXFA_Document* GetXFADoc() const; - - CXFA_FFDocView* m_pDocView; -}; - -#endif // XFA_FXFA_XFA_FFWIDGETHANDLER_H_ diff --git a/xfa/fxfa/xfa_fontmgr.h b/xfa/fxfa/xfa_fontmgr.h deleted file mode 100644 index f00b069ef03f0311197e4daa3034b206741b9f76..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_fontmgr.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_FONTMGR_H_ -#define XFA_FXFA_XFA_FONTMGR_H_ - -#include <map> -#include <memory> -#include <vector> - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_ext.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" -#include "xfa/fxfa/fxfa.h" - -class CPDF_Font; - -struct XFA_FONTINFO { - uint32_t dwFontNameHash; - const FX_WCHAR* pPsName; - const FX_WCHAR* pReplaceFont; - uint16_t dwStyles; - uint16_t wCodePage; -}; - -class CXFA_DefFontMgr { - public: - CXFA_DefFontMgr(); - ~CXFA_DefFontMgr(); - - CFX_RetainPtr<CFGAS_GEFont> GetFont(CXFA_FFDoc* hDoc, - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage = 0xFFFF); - CFX_RetainPtr<CFGAS_GEFont> GetDefaultFont( - CXFA_FFDoc* hDoc, - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage = 0xFFFF); - - protected: - std::vector<CFX_RetainPtr<CFGAS_GEFont>> m_CacheFonts; -}; - -class CXFA_PDFFontMgr { - public: - explicit CXFA_PDFFontMgr(CXFA_FFDoc* pDoc); - ~CXFA_PDFFontMgr(); - - CFX_RetainPtr<CFGAS_GEFont> GetFont(const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - CPDF_Font** pPDFFont, - bool bStrictMatch); - bool GetCharWidth(const CFX_RetainPtr<CFGAS_GEFont>& pFont, - FX_WCHAR wUnicode, - bool bCharCode, - int32_t* pWidth); - void SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont, CPDF_Font* pPDFFont); - - protected: - CFX_RetainPtr<CFGAS_GEFont> FindFont(const CFX_ByteString& strFamilyName, - bool bBold, - bool bItalic, - CPDF_Font** pPDFFont, - bool bStrictMatch); - CFX_ByteString PsNameToFontName(const CFX_ByteString& strPsName, - bool bBold, - bool bItalic); - bool PsNameMatchDRFontName(const CFX_ByteStringC& bsPsName, - bool bBold, - bool bItalic, - const CFX_ByteString& bsDRFontName, - bool bStrictMatch); - - CXFA_FFDoc* const m_pDoc; - std::map<CFX_RetainPtr<CFGAS_GEFont>, CPDF_Font*> m_FDE2PDFFont; - std::map<CFX_ByteString, CFX_RetainPtr<CFGAS_GEFont>> m_FontMap; -}; - -class CXFA_FontMgr { - public: - CXFA_FontMgr(); - ~CXFA_FontMgr(); - - CFX_RetainPtr<CFGAS_GEFont> GetFont(CXFA_FFDoc* hDoc, - const CFX_WideStringC& wsFontFamily, - uint32_t dwFontStyles, - uint16_t wCodePage = 0xFFFF); - void LoadDocFonts(CXFA_FFDoc* hDoc); - void ReleaseDocFonts(CXFA_FFDoc* hDoc); - void SetDefFontMgr(std::unique_ptr<CXFA_DefFontMgr> pFontMgr); - - protected: - std::unique_ptr<CXFA_DefFontMgr> m_pDefFontMgr; - std::map<CXFA_FFDoc*, std::unique_ptr<CXFA_PDFFontMgr>> m_PDFFontMgrMap; - std::map<CFX_ByteString, CFX_RetainPtr<CFGAS_GEFont>> m_FontMap; -}; - -#endif // XFA_FXFA_XFA_FONTMGR_H_ diff --git a/xfa/fxfa/xfa_rendercontext.h b/xfa/fxfa/xfa_rendercontext.h deleted file mode 100644 index c424005b1e2101c879d815ac0a746b1e4264ab5f..0000000000000000000000000000000000000000 --- a/xfa/fxfa/xfa_rendercontext.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXFA_XFA_RENDERCONTEXT_H_ -#define XFA_FXFA_XFA_RENDERCONTEXT_H_ - -#include <memory> - -#include "xfa/fxfa/fxfa.h" - -class CXFA_RenderOptions { - public: - CXFA_RenderOptions() : m_bPrint(false), m_bHighlight(true) {} - - bool m_bPrint; - bool m_bHighlight; -}; - -class CXFA_RenderContext { - public: - CXFA_RenderContext(); - ~CXFA_RenderContext(); - - int32_t StartRender(CXFA_FFPageView* pPageView, - CFX_Graphics* pGS, - const CFX_Matrix& matrix, - const CXFA_RenderOptions& options); - int32_t DoRender(IFX_Pause* pPause = nullptr); - void StopRender(); - - protected: - std::unique_ptr<IXFA_WidgetIterator> m_pWidgetIterator; - CXFA_FFWidget* m_pWidget; - CXFA_FFPageView* m_pPageView; - CFX_Graphics* m_pGS; - CFX_Matrix m_matrix; - CXFA_RenderOptions m_options; - uint32_t m_dwStatus; - CFX_RectF m_rtClipRect; -}; - -#endif // XFA_FXFA_XFA_RENDERCONTEXT_H_ diff --git a/xfa/fxgraphics/cfx_color.cpp b/xfa/fxgraphics/cfx_color.cpp deleted file mode 100644 index 36025a82c89622d0664bd2678c82d3025c581664..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_color.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxgraphics/cfx_color.h" - -CFX_Color::CFX_Color() : m_type(FX_COLOR_None) {} - -CFX_Color::CFX_Color(const FX_ARGB argb) { - Set(argb); -} - -CFX_Color::CFX_Color(CFX_Pattern* pattern, const FX_ARGB argb) { - Set(pattern, argb); -} - -CFX_Color::CFX_Color(CFX_Shading* shading) { - Set(shading); -} - -CFX_Color::~CFX_Color() { - m_type = FX_COLOR_None; -} - -void CFX_Color::Set(const FX_ARGB argb) { - m_type = FX_COLOR_Solid; - m_info.argb = argb; - m_info.pattern = nullptr; -} - -void CFX_Color::Set(CFX_Pattern* pattern, const FX_ARGB argb) { - if (!pattern) - return; - m_type = FX_COLOR_Pattern; - m_info.argb = argb; - m_info.pattern = pattern; -} - -void CFX_Color::Set(CFX_Shading* shading) { - if (!shading) - return; - m_type = FX_COLOR_Shading; - m_shading = shading; -} diff --git a/xfa/fxgraphics/cfx_color.h b/xfa/fxgraphics/cfx_color.h deleted file mode 100644 index 75f7fe2010d51e334c52ea0193c28dc324d1cd54..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_color.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXGRAPHICS_CFX_COLOR_H_ -#define XFA_FXGRAPHICS_CFX_COLOR_H_ - -#include "core/fxge/fx_dib.h" -#include "xfa/fxgraphics/cfx_graphics.h" - -class CFX_Pattern; -class CFX_Shading; - -enum { FX_COLOR_None = 0, FX_COLOR_Solid, FX_COLOR_Pattern, FX_COLOR_Shading }; - -class CFX_Color { - public: - CFX_Color(); - explicit CFX_Color(const FX_ARGB argb); - explicit CFX_Color(CFX_Shading* shading); - CFX_Color(CFX_Pattern* pattern, const FX_ARGB argb); - virtual ~CFX_Color(); - - void Set(const FX_ARGB argb); - void Set(CFX_Pattern* pattern, const FX_ARGB argb); - void Set(CFX_Shading* shading); - - private: - friend class CFX_Graphics; - - int32_t m_type; - union { - struct { - FX_ARGB argb; - CFX_Pattern* pattern; - } m_info; - CFX_Shading* m_shading; - }; -}; - -#endif // XFA_FXGRAPHICS_CFX_COLOR_H_ diff --git a/xfa/fxgraphics/cfx_graphics.cpp b/xfa/fxgraphics/cfx_graphics.cpp deleted file mode 100644 index d2f2151d91cf2fb8affbf2a6a75d9b26034b11fd..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_graphics.cpp +++ /dev/null @@ -1,538 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxgraphics/cfx_graphics.h" - -#include <memory> - -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/cfx_unicodeencoding.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fxgraphics/cfx_color.h" -#include "xfa/fxgraphics/cfx_path.h" -#include "xfa/fxgraphics/cfx_pattern.h" -#include "xfa/fxgraphics/cfx_shading.h" - -namespace { - -enum { - FX_CONTEXT_None = 0, - FX_CONTEXT_Device, -}; - -#define FX_HATCHSTYLE_Total 53 - -struct FX_HATCHDATA { - int32_t width; - int32_t height; - uint8_t maskBits[64]; -}; - -const FX_HATCHDATA hatchBitmapData[FX_HATCHSTYLE_Total] = { - {16, // Horizontal - 16, - { - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }}, - {16, // Vertical - 16, - { - 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, - 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, - 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, - 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, - 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - }}, - {16, // ForwardDiagonal - 16, - { - 0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, - 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, - 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, - 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, - }}, - {16, // BackwardDiagonal - 16, - { - 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, - 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, - 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, - 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - }}, - {16, // Cross - 16, - { - 0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, - 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, - 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, - 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, - }}, - {16, // DiagonalCross - 16, - { - 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, - 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x81, - 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, - 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, - 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, - }}, -}; - -} // namespace - -CFX_Graphics::CFX_Graphics(CFX_RenderDevice* renderDevice) - : m_type(FX_CONTEXT_None), m_renderDevice(renderDevice) { - if (!renderDevice) - return; - m_type = FX_CONTEXT_Device; -} - -CFX_Graphics::~CFX_Graphics() {} - -void CFX_Graphics::SaveGraphState() { - if (m_type != FX_CONTEXT_Device || !m_renderDevice) - return; - - m_renderDevice->SaveState(); - m_infoStack.push_back(pdfium::MakeUnique<TInfo>(m_info)); -} - -void CFX_Graphics::RestoreGraphState() { - if (m_type != FX_CONTEXT_Device || !m_renderDevice) - return; - - m_renderDevice->RestoreState(false); - if (m_infoStack.empty() || !m_infoStack.back()) - return; - - m_info = *m_infoStack.back(); - m_infoStack.pop_back(); - return; -} - -void CFX_Graphics::SetLineCap(CFX_GraphStateData::LineCap lineCap) { - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - m_info.graphState.m_LineCap = lineCap; - } -} - -void CFX_Graphics::SetLineDash(FX_FLOAT dashPhase, - FX_FLOAT* dashArray, - int32_t dashCount) { - if (dashCount > 0 && !dashArray) - return; - - dashCount = dashCount < 0 ? 0 : dashCount; - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - FX_FLOAT scale = 1.0; - if (m_info.isActOnDash) { - scale = m_info.graphState.m_LineWidth; - } - m_info.graphState.m_DashPhase = dashPhase; - m_info.graphState.SetDashCount(dashCount); - for (int32_t i = 0; i < dashCount; i++) { - m_info.graphState.m_DashArray[i] = dashArray[i] * scale; - } - } -} - -void CFX_Graphics::SetLineDash(FX_DashStyle dashStyle) { - if (m_type == FX_CONTEXT_Device && m_renderDevice) - RenderDeviceSetLineDash(dashStyle); -} - -void CFX_Graphics::SetLineWidth(FX_FLOAT lineWidth, bool isActOnDash) { - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - m_info.graphState.m_LineWidth = lineWidth; - m_info.isActOnDash = isActOnDash; - } -} - -void CFX_Graphics::SetStrokeColor(CFX_Color* color) { - if (!color) - return; - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - m_info.strokeColor = color; - } -} - -void CFX_Graphics::SetFillColor(CFX_Color* color) { - if (!color) - return; - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - m_info.fillColor = color; - } -} - -void CFX_Graphics::StrokePath(CFX_Path* path, CFX_Matrix* matrix) { - if (!path) - return; - if (m_type == FX_CONTEXT_Device && m_renderDevice) - RenderDeviceStrokePath(path, matrix); -} - -void CFX_Graphics::FillPath(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix) { - if (!path) - return; - if (m_type == FX_CONTEXT_Device && m_renderDevice) - RenderDeviceFillPath(path, fillMode, matrix); -} - -void CFX_Graphics::StretchImage(CFX_DIBSource* source, - const CFX_RectF& rect, - CFX_Matrix* matrix) { - if (!source) - return; - if (m_type == FX_CONTEXT_Device && m_renderDevice) - RenderDeviceStretchImage(source, rect, matrix); -} - -void CFX_Graphics::ConcatMatrix(const CFX_Matrix* matrix) { - if (!matrix) - return; - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - m_info.CTM.Concat(*matrix); - } -} - -CFX_Matrix* CFX_Graphics::GetMatrix() { - if (m_type == FX_CONTEXT_Device && m_renderDevice) - return &m_info.CTM; - return nullptr; -} - -CFX_RectF CFX_Graphics::GetClipRect() const { - if (m_type != FX_CONTEXT_Device || !m_renderDevice) - return CFX_RectF(); - - FX_RECT r = m_renderDevice->GetClipBox(); - return CFX_Rect(r.left, r.top, r.Width(), r.Height()).As<FX_FLOAT>(); -} - -void CFX_Graphics::SetClipRect(const CFX_RectF& rect) { - if (m_type == FX_CONTEXT_Device && m_renderDevice) { - m_renderDevice->SetClip_Rect( - FX_RECT(FXSYS_round(rect.left), FXSYS_round(rect.top), - FXSYS_round(rect.right()), FXSYS_round(rect.bottom()))); - } -} - -CFX_RenderDevice* CFX_Graphics::GetRenderDevice() { - return m_renderDevice; -} - -void CFX_Graphics::RenderDeviceSetLineDash(FX_DashStyle dashStyle) { - switch (dashStyle) { - case FX_DASHSTYLE_Solid: { - m_info.graphState.SetDashCount(0); - return; - } - case FX_DASHSTYLE_Dash: { - FX_FLOAT dashArray[] = {3, 1}; - SetLineDash(0, dashArray, 2); - return; - } - case FX_DASHSTYLE_Dot: { - FX_FLOAT dashArray[] = {1, 1}; - SetLineDash(0, dashArray, 2); - return; - } - case FX_DASHSTYLE_DashDot: { - FX_FLOAT dashArray[] = {3, 1, 1, 1}; - SetLineDash(0, dashArray, 4); - return; - } - case FX_DASHSTYLE_DashDotDot: { - FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1}; - SetLineDash(0, dashArray, 6); - return; - } - default: - return; - } -} - -void CFX_Graphics::RenderDeviceStrokePath(CFX_Path* path, CFX_Matrix* matrix) { - if (!m_info.strokeColor) - return; - CFX_Matrix m(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, - m_info.CTM.e, m_info.CTM.f); - if (matrix) { - m.Concat(*matrix); - } - switch (m_info.strokeColor->m_type) { - case FX_COLOR_Solid: { - m_renderDevice->DrawPath(path->GetPathData(), &m, &m_info.graphState, 0x0, - m_info.strokeColor->m_info.argb, 0); - return; - } - default: - return; - } -} - -void CFX_Graphics::RenderDeviceFillPath(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix) { - if (!m_info.fillColor) - return; - CFX_Matrix m(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, - m_info.CTM.e, m_info.CTM.f); - if (matrix) { - m.Concat(*matrix); - } - switch (m_info.fillColor->m_type) { - case FX_COLOR_Solid: { - m_renderDevice->DrawPath(path->GetPathData(), &m, &m_info.graphState, - m_info.fillColor->m_info.argb, 0x0, fillMode); - return; - } - case FX_COLOR_Pattern: - FillPathWithPattern(path, fillMode, &m); - return; - case FX_COLOR_Shading: - FillPathWithShading(path, fillMode, &m); - return; - default: - return; - } -} - -void CFX_Graphics::RenderDeviceStretchImage(CFX_DIBSource* source, - const CFX_RectF& rect, - CFX_Matrix* matrix) { - CFX_Matrix m1(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, - m_info.CTM.e, m_info.CTM.f); - if (matrix) { - m1.Concat(*matrix); - } - std::unique_ptr<CFX_DIBitmap> bmp1 = - source->StretchTo((int32_t)rect.Width(), (int32_t)rect.Height()); - CFX_Matrix m2(rect.Width(), 0.0, 0.0, rect.Height(), rect.left, rect.top); - m2.Concat(m1); - - int32_t left; - int32_t top; - std::unique_ptr<CFX_DIBitmap> bmp2 = bmp1->FlipImage(false, true); - std::unique_ptr<CFX_DIBitmap> bmp3 = bmp2->TransformTo(&m2, left, top); - CFX_RectF r = GetClipRect(); - CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap(); - bitmap->CompositeBitmap(FXSYS_round(r.left), FXSYS_round(r.top), - FXSYS_round(r.Width()), FXSYS_round(r.Height()), - bmp3.get(), FXSYS_round(r.left - left), - FXSYS_round(r.top - top)); -} - -void CFX_Graphics::FillPathWithPattern(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix) { - CFX_Pattern* pattern = m_info.fillColor->m_info.pattern; - CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap(); - int32_t width = bitmap->GetWidth(); - int32_t height = bitmap->GetHeight(); - CFX_DIBitmap bmp; - bmp.Create(width, height, FXDIB_Argb); - m_renderDevice->GetDIBits(&bmp, 0, 0); - - FX_HatchStyle hatchStyle = m_info.fillColor->m_info.pattern->m_hatchStyle; - const FX_HATCHDATA& data = hatchBitmapData[static_cast<int>(hatchStyle)]; - - CFX_DIBitmap mask; - mask.Create(data.width, data.height, FXDIB_1bppMask); - FXSYS_memcpy(mask.GetBuffer(), data.maskBits, mask.GetPitch() * data.height); - CFX_FloatRect rectf = path->GetPathData()->GetBoundingBox(); - if (matrix) - matrix->TransformRect(rectf); - - FX_RECT rect(FXSYS_round(rectf.left), FXSYS_round(rectf.top), - FXSYS_round(rectf.right), FXSYS_round(rectf.bottom)); - CFX_FxgeDevice device; - device.Attach(&bmp, false, nullptr, false); - device.FillRect(&rect, m_info.fillColor->m_info.pattern->m_backArgb); - for (int32_t j = rect.bottom; j < rect.top; j += mask.GetHeight()) { - for (int32_t i = rect.left; i < rect.right; i += mask.GetWidth()) { - device.SetBitMask(&mask, i, j, - m_info.fillColor->m_info.pattern->m_foreArgb); - } - } - - m_renderDevice->SaveState(); - m_renderDevice->SetClip_PathFill(path->GetPathData(), matrix, fillMode); - SetDIBitsWithMatrix(&bmp, &pattern->m_matrix); - m_renderDevice->RestoreState(false); -} - -void CFX_Graphics::FillPathWithShading(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix) { - CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap(); - int32_t width = bitmap->GetWidth(); - int32_t height = bitmap->GetHeight(); - FX_FLOAT start_x = m_info.fillColor->m_shading->m_beginPoint.x; - FX_FLOAT start_y = m_info.fillColor->m_shading->m_beginPoint.y; - FX_FLOAT end_x = m_info.fillColor->m_shading->m_endPoint.x; - FX_FLOAT end_y = m_info.fillColor->m_shading->m_endPoint.y; - CFX_DIBitmap bmp; - bmp.Create(width, height, FXDIB_Argb); - m_renderDevice->GetDIBits(&bmp, 0, 0); - int32_t pitch = bmp.GetPitch(); - bool result = false; - switch (m_info.fillColor->m_shading->m_type) { - case FX_SHADING_Axial: { - FX_FLOAT x_span = end_x - start_x; - FX_FLOAT y_span = end_y - start_y; - FX_FLOAT axis_len_square = (x_span * x_span) + (y_span * y_span); - for (int32_t row = 0; row < height; row++) { - uint32_t* dib_buf = (uint32_t*)(bmp.GetBuffer() + row * pitch); - for (int32_t column = 0; column < width; column++) { - FX_FLOAT x = (FX_FLOAT)(column); - FX_FLOAT y = (FX_FLOAT)(row); - FX_FLOAT scale = - (((x - start_x) * x_span) + ((y - start_y) * y_span)) / - axis_len_square; - if (scale < 0) { - if (!m_info.fillColor->m_shading->m_isExtendedBegin) { - continue; - } - scale = 0; - } else if (scale > 1.0f) { - if (!m_info.fillColor->m_shading->m_isExtendedEnd) { - continue; - } - scale = 1.0f; - } - int32_t index = (int32_t)(scale * (FX_SHADING_Steps - 1)); - dib_buf[column] = m_info.fillColor->m_shading->m_argbArray[index]; - } - } - result = true; - break; - } - case FX_SHADING_Radial: { - FX_FLOAT start_r = m_info.fillColor->m_shading->m_beginRadius; - FX_FLOAT end_r = m_info.fillColor->m_shading->m_endRadius; - FX_FLOAT a = ((start_x - end_x) * (start_x - end_x)) + - ((start_y - end_y) * (start_y - end_y)) - - ((start_r - end_r) * (start_r - end_r)); - for (int32_t row = 0; row < height; row++) { - uint32_t* dib_buf = (uint32_t*)(bmp.GetBuffer() + row * pitch); - for (int32_t column = 0; column < width; column++) { - FX_FLOAT x = (FX_FLOAT)(column); - FX_FLOAT y = (FX_FLOAT)(row); - FX_FLOAT b = -2 * (((x - start_x) * (end_x - start_x)) + - ((y - start_y) * (end_y - start_y)) + - (start_r * (end_r - start_r))); - FX_FLOAT c = ((x - start_x) * (x - start_x)) + - ((y - start_y) * (y - start_y)) - (start_r * start_r); - FX_FLOAT s; - if (a == 0) { - s = -c / b; - } else { - FX_FLOAT b2_4ac = (b * b) - 4 * (a * c); - if (b2_4ac < 0) { - continue; - } - FX_FLOAT root = (FXSYS_sqrt(b2_4ac)); - FX_FLOAT s1, s2; - if (a > 0) { - s1 = (-b - root) / (2 * a); - s2 = (-b + root) / (2 * a); - } else { - s2 = (-b - root) / (2 * a); - s1 = (-b + root) / (2 * a); - } - if (s2 <= 1.0f || m_info.fillColor->m_shading->m_isExtendedEnd) { - s = (s2); - } else { - s = (s1); - } - if ((start_r) + s * (end_r - start_r) < 0) { - continue; - } - } - if (s < 0) { - if (!m_info.fillColor->m_shading->m_isExtendedBegin) { - continue; - } - s = 0; - } - if (s > 1.0f) { - if (!m_info.fillColor->m_shading->m_isExtendedEnd) { - continue; - } - s = 1.0f; - } - int index = (int32_t)(s * (FX_SHADING_Steps - 1)); - dib_buf[column] = m_info.fillColor->m_shading->m_argbArray[index]; - } - } - result = true; - break; - } - default: { - result = false; - break; - } - } - if (result) { - m_renderDevice->SaveState(); - m_renderDevice->SetClip_PathFill(path->GetPathData(), matrix, fillMode); - SetDIBitsWithMatrix(&bmp, matrix); - m_renderDevice->RestoreState(false); - } -} - -void CFX_Graphics::SetDIBitsWithMatrix(CFX_DIBSource* source, - CFX_Matrix* matrix) { - if (matrix->IsIdentity()) { - m_renderDevice->SetDIBits(source, 0, 0); - } else { - CFX_Matrix m((FX_FLOAT)source->GetWidth(), 0, 0, - (FX_FLOAT)source->GetHeight(), 0, 0); - m.Concat(*matrix); - int32_t left; - int32_t top; - std::unique_ptr<CFX_DIBitmap> bmp1 = source->FlipImage(false, true); - std::unique_ptr<CFX_DIBitmap> bmp2 = bmp1->TransformTo(&m, left, top); - m_renderDevice->SetDIBits(bmp2.get(), left, top); - } -} - -CFX_Graphics::TInfo::TInfo() - : isActOnDash(false), strokeColor(nullptr), fillColor(nullptr) {} - -CFX_Graphics::TInfo::TInfo(const TInfo& info) - : graphState(info.graphState), - CTM(info.CTM), - isActOnDash(info.isActOnDash), - strokeColor(info.strokeColor), - fillColor(info.fillColor) {} - -CFX_Graphics::TInfo& CFX_Graphics::TInfo::operator=(const TInfo& other) { - graphState.Copy(other.graphState); - CTM = other.CTM; - isActOnDash = other.isActOnDash; - strokeColor = other.strokeColor; - fillColor = other.fillColor; - return *this; -} diff --git a/xfa/fxgraphics/cfx_graphics.h b/xfa/fxgraphics/cfx_graphics.h deleted file mode 100644 index c18f8eb4c9b1f41e104cc86d4d20d6e060f5c582..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_graphics.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXGRAPHICS_CFX_GRAPHICS_H_ -#define XFA_FXGRAPHICS_CFX_GRAPHICS_H_ - -#include <memory> -#include <vector> - -#include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_fxgedevice.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/fx_dib.h" -#include "core/fxge/fx_font.h" - -class CFX_Color; -class CFX_Path; - -using FX_FillMode = int32_t; - -enum FX_DashStyle { - FX_DASHSTYLE_Solid = 0, - FX_DASHSTYLE_Dash = 1, - FX_DASHSTYLE_Dot = 2, - FX_DASHSTYLE_DashDot = 3, - FX_DASHSTYLE_DashDotDot = 4 -}; - -enum class FX_HatchStyle { - Horizontal = 0, - Vertical = 1, - ForwardDiagonal = 2, - BackwardDiagonal = 3, - Cross = 4, - DiagonalCross = 5 -}; - -class CFX_RenderDevice; - -class CFX_Graphics { - public: - explicit CFX_Graphics(CFX_RenderDevice* renderDevice); - ~CFX_Graphics(); - - void SaveGraphState(); - void RestoreGraphState(); - - CFX_RectF GetClipRect() const; - CFX_Matrix* GetMatrix(); - CFX_RenderDevice* GetRenderDevice(); - - void SetLineCap(CFX_GraphStateData::LineCap lineCap); - void SetLineDash(FX_FLOAT dashPhase, FX_FLOAT* dashArray, int32_t dashCount); - void SetLineDash(FX_DashStyle dashStyle); - void SetLineWidth(FX_FLOAT lineWidth, bool isActOnDash = false); - void SetStrokeColor(CFX_Color* color); - void SetFillColor(CFX_Color* color); - void SetClipRect(const CFX_RectF& rect); - void StrokePath(CFX_Path* path, CFX_Matrix* matrix = nullptr); - void FillPath(CFX_Path* path, - FX_FillMode fillMode = FXFILL_WINDING, - CFX_Matrix* matrix = nullptr); - void StretchImage(CFX_DIBSource* source, - const CFX_RectF& rect, - CFX_Matrix* matrix = nullptr); - void ConcatMatrix(const CFX_Matrix* matrix); - - protected: - int32_t m_type; - - private: - struct TInfo { - TInfo(); - explicit TInfo(const TInfo& info); - TInfo& operator=(const TInfo& other); - - CFX_GraphStateData graphState; - CFX_Matrix CTM; - bool isActOnDash; - CFX_Color* strokeColor; - CFX_Color* fillColor; - } m_info; - - void RenderDeviceSetLineDash(FX_DashStyle dashStyle); - void RenderDeviceStrokePath(CFX_Path* path, CFX_Matrix* matrix); - void RenderDeviceFillPath(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix); - void RenderDeviceStretchImage(CFX_DIBSource* source, - const CFX_RectF& rect, - CFX_Matrix* matrix); - - void FillPathWithPattern(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix); - void FillPathWithShading(CFX_Path* path, - FX_FillMode fillMode, - CFX_Matrix* matrix); - - void SetDIBitsWithMatrix(CFX_DIBSource* source, CFX_Matrix* matrix); - - CFX_RenderDevice* m_renderDevice; - std::vector<std::unique_ptr<TInfo>> m_infoStack; -}; - -#endif // XFA_FXGRAPHICS_CFX_GRAPHICS_H_ diff --git a/xfa/fxgraphics/cfx_path.cpp b/xfa/fxgraphics/cfx_path.cpp deleted file mode 100644 index d56eb13f6741f7f931f2fffc4b447b59bad3a5a9..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_path.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxgraphics/cfx_path.h" - -#include "core/fxge/cfx_pathdata.h" -#include "third_party/base/ptr_util.h" - -CFX_Path::CFX_Path() {} - -CFX_Path::~CFX_Path() {} - -void CFX_Path::Clear() { - data_.Clear(); -} - -void CFX_Path::Close() { - data_.ClosePath(); -} - -void CFX_Path::MoveTo(const CFX_PointF& point) { - data_.AppendPoint(point, FXPT_TYPE::MoveTo, false); -} - -void CFX_Path::LineTo(const CFX_PointF& point) { - data_.AppendPoint(point, FXPT_TYPE::LineTo, false); -} - -void CFX_Path::BezierTo(const CFX_PointF& c1, - const CFX_PointF& c2, - const CFX_PointF& to) { - data_.AppendPoint(c1, FXPT_TYPE::BezierTo, false); - data_.AppendPoint(c2, FXPT_TYPE::BezierTo, false); - data_.AppendPoint(to, FXPT_TYPE::BezierTo, false); -} - -void CFX_Path::ArcTo(const CFX_PointF& pos, - const CFX_SizeF& size, - FX_FLOAT start_angle, - FX_FLOAT sweep_angle) { - CFX_SizeF new_size = size / 2.0f; - ArcToInternal(CFX_PointF(pos.x + new_size.width, pos.y + new_size.height), - new_size, start_angle, sweep_angle); -} - -void CFX_Path::ArcToInternal(const CFX_PointF& pos, - const CFX_SizeF& size, - FX_FLOAT start_angle, - FX_FLOAT sweep_angle) { - FX_FLOAT x0 = FXSYS_cos(sweep_angle / 2); - FX_FLOAT y0 = FXSYS_sin(sweep_angle / 2); - FX_FLOAT tx = ((1.0f - x0) * 4) / (3 * 1.0f); - FX_FLOAT ty = y0 - ((tx * x0) / y0); - - CFX_PointF points[] = {CFX_PointF(x0 + tx, -ty), CFX_PointF(x0 + tx, ty)}; - FX_FLOAT sn = FXSYS_sin(start_angle + sweep_angle / 2); - FX_FLOAT cs = FXSYS_cos(start_angle + sweep_angle / 2); - - CFX_PointF bezier; - bezier.x = pos.x + (size.width * ((points[0].x * cs) - (points[0].y * sn))); - bezier.y = pos.y + (size.height * ((points[0].x * sn) + (points[0].y * cs))); - data_.AppendPoint(bezier, FXPT_TYPE::BezierTo, false); - - bezier.x = pos.x + (size.width * ((points[1].x * cs) - (points[1].y * sn))); - bezier.y = pos.y + (size.height * ((points[1].x * sn) + (points[1].y * cs))); - data_.AppendPoint(bezier, FXPT_TYPE::BezierTo, false); - - bezier.x = pos.x + (size.width * FXSYS_cos(start_angle + sweep_angle)); - bezier.y = pos.y + (size.height * FXSYS_sin(start_angle + sweep_angle)); - data_.AppendPoint(bezier, FXPT_TYPE::BezierTo, false); -} - -void CFX_Path::AddLine(const CFX_PointF& p1, const CFX_PointF& p2) { - data_.AppendPoint(p1, FXPT_TYPE::MoveTo, false); - data_.AppendPoint(p2, FXPT_TYPE::LineTo, false); -} - -void CFX_Path::AddRectangle(FX_FLOAT left, - FX_FLOAT top, - FX_FLOAT width, - FX_FLOAT height) { - data_.AppendRect(left, top, left + width, top + height); -} - -void CFX_Path::AddEllipse(const CFX_RectF& rect) { - AddArc(rect.TopLeft(), rect.Size(), 0, FX_PI * 2); -} - -void CFX_Path::AddArc(const CFX_PointF& original_pos, - const CFX_SizeF& original_size, - FX_FLOAT start_angle, - FX_FLOAT sweep_angle) { - if (sweep_angle == 0) - return; - - const FX_FLOAT bezier_arc_angle_epsilon = 0.01f; - while (start_angle > FX_PI * 2) - start_angle -= FX_PI * 2; - while (start_angle < 0) - start_angle += FX_PI * 2; - if (sweep_angle >= FX_PI * 2) - sweep_angle = FX_PI * 2; - if (sweep_angle <= -FX_PI * 2) - sweep_angle = -FX_PI * 2; - - CFX_SizeF size = original_size / 2; - CFX_PointF pos(original_pos.x + size.width, original_pos.y + size.height); - data_.AppendPoint(pos + CFX_PointF(size.width * FXSYS_cos(start_angle), - size.height * FXSYS_sin(start_angle)), - FXPT_TYPE::MoveTo, false); - - FX_FLOAT total_sweep = 0; - FX_FLOAT local_sweep = 0; - FX_FLOAT prev_sweep = 0; - bool done = false; - do { - if (sweep_angle < 0) { - prev_sweep = total_sweep; - local_sweep = -FX_PI / 2; - total_sweep -= FX_PI / 2; - if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { - local_sweep = sweep_angle - prev_sweep; - done = true; - } - } else { - prev_sweep = total_sweep; - local_sweep = FX_PI / 2; - total_sweep += FX_PI / 2; - if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { - local_sweep = sweep_angle - prev_sweep; - done = true; - } - } - - ArcToInternal(pos, size, start_angle, local_sweep); - start_angle += local_sweep; - } while (!done); -} - -void CFX_Path::AddSubpath(CFX_Path* path) { - if (!path) - return; - data_.Append(&path->data_, nullptr); -} - -void CFX_Path::TransformBy(const CFX_Matrix& mt) { - data_.Transform(&mt); -} diff --git a/xfa/fxgraphics/cfx_path.h b/xfa/fxgraphics/cfx_path.h deleted file mode 100644 index 267831603a635474e097931e174d7ff688154709..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_path.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXGRAPHICS_CFX_PATH_H_ -#define XFA_FXGRAPHICS_CFX_PATH_H_ - -#include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_pathdata.h" -#include "xfa/fxgraphics/cfx_graphics.h" - -class CFX_Path final { - public: - CFX_Path(); - ~CFX_Path(); - - const CFX_PathData* GetPathData() const { return &data_; } - - void Clear(); - bool IsEmpty() const { return data_.GetPoints().empty(); } - void TransformBy(const CFX_Matrix& mt); - - void Close(); - void MoveTo(const CFX_PointF& point); - void LineTo(const CFX_PointF& point); - void BezierTo(const CFX_PointF& c1, - const CFX_PointF& c2, - const CFX_PointF& to); - void ArcTo(const CFX_PointF& pos, - const CFX_SizeF& size, - FX_FLOAT startAngle, - FX_FLOAT sweepAngle); - - void AddLine(const CFX_PointF& p1, const CFX_PointF& p2); - void AddRectangle(FX_FLOAT left, - FX_FLOAT top, - FX_FLOAT width, - FX_FLOAT height); - void AddEllipse(const CFX_RectF& rect); - void AddArc(const CFX_PointF& pos, - const CFX_SizeF& size, - FX_FLOAT startAngle, - FX_FLOAT sweepAngle); - - void AddSubpath(CFX_Path* path); - - private: - void ArcToInternal(const CFX_PointF& pos, - const CFX_SizeF& size, - FX_FLOAT start_angle, - FX_FLOAT sweep_angle); - - CFX_PathData data_; -}; - -#endif // XFA_FXGRAPHICS_CFX_PATH_H_ diff --git a/xfa/fxgraphics/cfx_pattern.cpp b/xfa/fxgraphics/cfx_pattern.cpp deleted file mode 100644 index a20ec24aa5a4fd39fe9ca3f426cf8ed58aa2cf50..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_pattern.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxgraphics/cfx_pattern.h" - -CFX_Pattern::CFX_Pattern(FX_HatchStyle hatchStyle, - const FX_ARGB foreArgb, - const FX_ARGB backArgb, - CFX_Matrix* matrix) - : m_hatchStyle(hatchStyle), m_foreArgb(foreArgb), m_backArgb(backArgb) { - if (matrix) - m_matrix = *matrix; - else - m_matrix.SetIdentity(); -} - -CFX_Pattern::~CFX_Pattern() {} diff --git a/xfa/fxgraphics/cfx_pattern.h b/xfa/fxgraphics/cfx_pattern.h deleted file mode 100644 index ef0008a3eaf01eac873f1a821701cc42ac89dfb8..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_pattern.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXGRAPHICS_CFX_PATTERN_H_ -#define XFA_FXGRAPHICS_CFX_PATTERN_H_ - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" -#include "xfa/fxgraphics/cfx_graphics.h" - -class CFX_DIBitmap; -class CFX_Matrix; - -class CFX_Pattern { - public: - CFX_Pattern(FX_HatchStyle hatchStyle, - const FX_ARGB foreArgb, - const FX_ARGB backArgb, - CFX_Matrix* matrix = nullptr); - - virtual ~CFX_Pattern(); - - private: - friend class CFX_Graphics; - - CFX_Matrix m_matrix; - - const FX_HatchStyle m_hatchStyle; - const FX_ARGB m_foreArgb; - const FX_ARGB m_backArgb; -}; - -#endif // XFA_FXGRAPHICS_CFX_PATTERN_H_ diff --git a/xfa/fxgraphics/cfx_shading.cpp b/xfa/fxgraphics/cfx_shading.cpp deleted file mode 100644 index 07936302c939fd2a97aca957616b6b974a6208ad..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_shading.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "xfa/fxgraphics/cfx_shading.h" - -CFX_Shading::CFX_Shading(const CFX_PointF& beginPoint, - const CFX_PointF& endPoint, - bool isExtendedBegin, - bool isExtendedEnd, - const FX_ARGB beginArgb, - const FX_ARGB endArgb) - : m_type(FX_SHADING_Axial), - m_beginPoint(beginPoint), - m_endPoint(endPoint), - m_beginRadius(0), - m_endRadius(0), - m_isExtendedBegin(isExtendedBegin), - m_isExtendedEnd(isExtendedEnd), - m_beginArgb(beginArgb), - m_endArgb(endArgb) { - InitArgbArray(); -} - -CFX_Shading::CFX_Shading(const CFX_PointF& beginPoint, - const CFX_PointF& endPoint, - const FX_FLOAT beginRadius, - const FX_FLOAT endRadius, - bool isExtendedBegin, - bool isExtendedEnd, - const FX_ARGB beginArgb, - const FX_ARGB endArgb) - : m_type(FX_SHADING_Radial), - m_beginPoint(beginPoint), - m_endPoint(endPoint), - m_beginRadius(beginRadius), - m_endRadius(endRadius), - m_isExtendedBegin(isExtendedBegin), - m_isExtendedEnd(isExtendedEnd), - m_beginArgb(beginArgb), - m_endArgb(endArgb) { - InitArgbArray(); -} - -CFX_Shading::~CFX_Shading() {} - -void CFX_Shading::InitArgbArray() { - int32_t a1; - int32_t r1; - int32_t g1; - int32_t b1; - ArgbDecode(m_beginArgb, a1, r1, g1, b1); - - int32_t a2; - int32_t r2; - int32_t g2; - int32_t b2; - ArgbDecode(m_endArgb, a2, r2, g2, b2); - - FX_FLOAT f = (FX_FLOAT)(FX_SHADING_Steps - 1); - FX_FLOAT aScale = 1.0 * (a2 - a1) / f; - FX_FLOAT rScale = 1.0 * (r2 - r1) / f; - FX_FLOAT gScale = 1.0 * (g2 - g1) / f; - FX_FLOAT bScale = 1.0 * (b2 - b1) / f; - - for (int32_t i = 0; i < FX_SHADING_Steps; i++) { - int32_t a3 = static_cast<int32_t>(i * aScale); - int32_t r3 = static_cast<int32_t>(i * rScale); - int32_t g3 = static_cast<int32_t>(i * gScale); - int32_t b3 = static_cast<int32_t>(i * bScale); - - // TODO(dsinclair): Add overloads for FX_ARGB. pdfium:437 - m_argbArray[i] = - FXARGB_TODIB(FXARGB_MAKE(a1 + a3, r1 + r3, g1 + g3, b1 + b3)); - } -} diff --git a/xfa/fxgraphics/cfx_shading.h b/xfa/fxgraphics/cfx_shading.h deleted file mode 100644 index 4189581895be6845bc5e7e80257cd843447aaa03..0000000000000000000000000000000000000000 --- a/xfa/fxgraphics/cfx_shading.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef XFA_FXGRAPHICS_CFX_SHADING_H_ -#define XFA_FXGRAPHICS_CFX_SHADING_H_ - -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_dib.h" - -#define FX_SHADING_Steps 256 - -enum CFX_Shading_Type { FX_SHADING_Axial = 1, FX_SHADING_Radial }; - -class CFX_Shading { - public: - // Axial shading. - CFX_Shading(const CFX_PointF& beginPoint, - const CFX_PointF& endPoint, - bool isExtendedBegin, - bool isExtendedEnd, - const FX_ARGB beginArgb, - const FX_ARGB endArgb); - - // Radial shading. - CFX_Shading(const CFX_PointF& beginPoint, - const CFX_PointF& endPoint, - const FX_FLOAT beginRadius, - const FX_FLOAT endRadius, - bool isExtendedBegin, - bool isExtendedEnd, - const FX_ARGB beginArgb, - const FX_ARGB endArgb); - virtual ~CFX_Shading(); - - private: - friend class CFX_Graphics; - - void InitArgbArray(); - - const CFX_Shading_Type m_type; - const CFX_PointF m_beginPoint; - const CFX_PointF m_endPoint; - const FX_FLOAT m_beginRadius; - const FX_FLOAT m_endRadius; - const bool m_isExtendedBegin; - const bool m_isExtendedEnd; - const FX_ARGB m_beginArgb; - const FX_ARGB m_endArgb; - FX_ARGB m_argbArray[FX_SHADING_Steps]; -}; - -#endif // XFA_FXGRAPHICS_CFX_SHADING_H_ diff --git a/xfa/fxgraphics/cxfa_gecolor.cpp b/xfa/fxgraphics/cxfa_gecolor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3dca4a7df56463fdbfb187318c4f88ed5c1a3443 --- /dev/null +++ b/xfa/fxgraphics/cxfa_gecolor.cpp @@ -0,0 +1,47 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxgraphics/cxfa_gecolor.h" + +CXFA_GEColor::CXFA_GEColor() : m_type(Invalid) {} + +CXFA_GEColor::CXFA_GEColor(const FX_ARGB argb) : m_type(Solid), m_argb(argb) { + m_pointer.pattern = nullptr; +} + +CXFA_GEColor::CXFA_GEColor(CXFA_GEPattern* pattern, const FX_ARGB argb) + : m_type(Pattern), m_argb(argb) { + m_pointer.pattern = pattern; +} + +CXFA_GEColor::CXFA_GEColor(CXFA_GEShading* shading) + : m_type(Shading), m_argb(0) { + m_pointer.shading = shading; +} + +CXFA_GEColor::~CXFA_GEColor() {} + +CXFA_GEColor& CXFA_GEColor::operator=(const CXFA_GEColor& that) { + if (this != &that) { + m_type = that.m_type; + switch (m_type) { + case Solid: + m_argb = that.m_argb; + m_pointer.pattern = nullptr; + break; + case Pattern: + m_argb = that.m_argb; + m_pointer.pattern = that.m_pointer.pattern; + break; + case Shading: + m_argb = 0; + m_pointer.shading = that.m_pointer.shading; + default: + break; + } + } + return *this; +} diff --git a/xfa/fxgraphics/cxfa_gecolor.h b/xfa/fxgraphics/cxfa_gecolor.h new file mode 100644 index 0000000000000000000000000000000000000000..b60585b7a4c5e5d6b792497631a9a8fe2ff15e0b --- /dev/null +++ b/xfa/fxgraphics/cxfa_gecolor.h @@ -0,0 +1,50 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXGRAPHICS_CXFA_GECOLOR_H_ +#define XFA_FXGRAPHICS_CXFA_GECOLOR_H_ + +#include "core/fxge/fx_dib.h" + +class CXFA_GEPattern; +class CXFA_GEShading; + +class CXFA_GEColor { + public: + enum Type { Invalid, Solid, Pattern, Shading }; + + CXFA_GEColor(); + explicit CXFA_GEColor(const FX_ARGB argb); + explicit CXFA_GEColor(CXFA_GEShading* shading); + CXFA_GEColor(CXFA_GEPattern* pattern, const FX_ARGB argb); + ~CXFA_GEColor(); + + Type GetType() const { return m_type; } + FX_ARGB GetArgb() const { + ASSERT(m_type == Solid || m_type == Pattern); + return m_argb; + } + CXFA_GEPattern* GetPattern() const { + ASSERT(m_type == Pattern); + return m_pointer.pattern; + } + CXFA_GEShading* GetShading() const { + ASSERT(m_type == Shading); + return m_pointer.shading; + } + + CXFA_GEColor& operator=(const CXFA_GEColor& that); + + private: + Type m_type; + FX_ARGB m_argb; + union { + CXFA_GEPattern* pattern; + CXFA_GEShading* shading; + } m_pointer; +}; + +#endif // XFA_FXGRAPHICS_CXFA_GECOLOR_H_ diff --git a/xfa/fxgraphics/cxfa_gepath.cpp b/xfa/fxgraphics/cxfa_gepath.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88372f72acfce32f107326cc6e9fbb05285d1e6e --- /dev/null +++ b/xfa/fxgraphics/cxfa_gepath.cpp @@ -0,0 +1,151 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxgraphics/cxfa_gepath.h" + +#include "core/fxge/cfx_pathdata.h" +#include "third_party/base/ptr_util.h" + +CXFA_GEPath::CXFA_GEPath() {} + +CXFA_GEPath::~CXFA_GEPath() {} + +void CXFA_GEPath::Clear() { + data_.Clear(); +} + +void CXFA_GEPath::Close() { + data_.ClosePath(); +} + +void CXFA_GEPath::MoveTo(const CFX_PointF& point) { + data_.AppendPoint(point, FXPT_TYPE::MoveTo, false); +} + +void CXFA_GEPath::LineTo(const CFX_PointF& point) { + data_.AppendPoint(point, FXPT_TYPE::LineTo, false); +} + +void CXFA_GEPath::BezierTo(const CFX_PointF& c1, + const CFX_PointF& c2, + const CFX_PointF& to) { + data_.AppendPoint(c1, FXPT_TYPE::BezierTo, false); + data_.AppendPoint(c2, FXPT_TYPE::BezierTo, false); + data_.AppendPoint(to, FXPT_TYPE::BezierTo, false); +} + +void CXFA_GEPath::ArcTo(const CFX_PointF& pos, + const CFX_SizeF& size, + float start_angle, + float sweep_angle) { + CFX_SizeF new_size = size / 2.0f; + ArcToInternal(CFX_PointF(pos.x + new_size.width, pos.y + new_size.height), + new_size, start_angle, sweep_angle); +} + +void CXFA_GEPath::ArcToInternal(const CFX_PointF& pos, + const CFX_SizeF& size, + float start_angle, + float sweep_angle) { + float x0 = cos(sweep_angle / 2); + float y0 = sin(sweep_angle / 2); + float tx = ((1.0f - x0) * 4) / (3 * 1.0f); + float ty = y0 - ((tx * x0) / y0); + + CFX_PointF points[] = {CFX_PointF(x0 + tx, -ty), CFX_PointF(x0 + tx, ty)}; + float sn = sin(start_angle + sweep_angle / 2); + float cs = cos(start_angle + sweep_angle / 2); + + CFX_PointF bezier; + bezier.x = pos.x + (size.width * ((points[0].x * cs) - (points[0].y * sn))); + bezier.y = pos.y + (size.height * ((points[0].x * sn) + (points[0].y * cs))); + data_.AppendPoint(bezier, FXPT_TYPE::BezierTo, false); + + bezier.x = pos.x + (size.width * ((points[1].x * cs) - (points[1].y * sn))); + bezier.y = pos.y + (size.height * ((points[1].x * sn) + (points[1].y * cs))); + data_.AppendPoint(bezier, FXPT_TYPE::BezierTo, false); + + bezier.x = pos.x + (size.width * cos(start_angle + sweep_angle)); + bezier.y = pos.y + (size.height * sin(start_angle + sweep_angle)); + data_.AppendPoint(bezier, FXPT_TYPE::BezierTo, false); +} + +void CXFA_GEPath::AddLine(const CFX_PointF& p1, const CFX_PointF& p2) { + data_.AppendPoint(p1, FXPT_TYPE::MoveTo, false); + data_.AppendPoint(p2, FXPT_TYPE::LineTo, false); +} + +void CXFA_GEPath::AddRectangle(float left, + float top, + float width, + float height) { + data_.AppendRect(left, top, left + width, top + height); +} + +void CXFA_GEPath::AddEllipse(const CFX_RectF& rect) { + AddArc(rect.TopLeft(), rect.Size(), 0, FX_PI * 2); +} + +void CXFA_GEPath::AddArc(const CFX_PointF& original_pos, + const CFX_SizeF& original_size, + float start_angle, + float sweep_angle) { + if (sweep_angle == 0) + return; + + const float bezier_arc_angle_epsilon = 0.01f; + while (start_angle > FX_PI * 2) + start_angle -= FX_PI * 2; + while (start_angle < 0) + start_angle += FX_PI * 2; + if (sweep_angle >= FX_PI * 2) + sweep_angle = FX_PI * 2; + if (sweep_angle <= -FX_PI * 2) + sweep_angle = -FX_PI * 2; + + CFX_SizeF size = original_size / 2; + CFX_PointF pos(original_pos.x + size.width, original_pos.y + size.height); + data_.AppendPoint(pos + CFX_PointF(size.width * cos(start_angle), + size.height * sin(start_angle)), + FXPT_TYPE::MoveTo, false); + + float total_sweep = 0; + float local_sweep = 0; + float prev_sweep = 0; + bool done = false; + do { + if (sweep_angle < 0) { + prev_sweep = total_sweep; + local_sweep = -FX_PI / 2; + total_sweep -= FX_PI / 2; + if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { + local_sweep = sweep_angle - prev_sweep; + done = true; + } + } else { + prev_sweep = total_sweep; + local_sweep = FX_PI / 2; + total_sweep += FX_PI / 2; + if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { + local_sweep = sweep_angle - prev_sweep; + done = true; + } + } + + ArcToInternal(pos, size, start_angle, local_sweep); + start_angle += local_sweep; + } while (!done); +} + +void CXFA_GEPath::AddSubpath(CXFA_GEPath* path) { + if (!path) + return; + data_.Append(&path->data_, nullptr); +} + +void CXFA_GEPath::TransformBy(const CFX_Matrix& mt) { + data_.Transform(&mt); +} diff --git a/xfa/fxgraphics/cxfa_gepath.h b/xfa/fxgraphics/cxfa_gepath.h new file mode 100644 index 0000000000000000000000000000000000000000..0c3afc4edfdf8ca4a1649d74c9ce9134884271d6 --- /dev/null +++ b/xfa/fxgraphics/cxfa_gepath.h @@ -0,0 +1,55 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXGRAPHICS_CXFA_GEPATH_H_ +#define XFA_FXGRAPHICS_CXFA_GEPATH_H_ + +#include "core/fxcrt/fx_system.h" +#include "core/fxge/cfx_pathdata.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +class CXFA_GEPath final { + public: + CXFA_GEPath(); + ~CXFA_GEPath(); + + const CFX_PathData* GetPathData() const { return &data_; } + + void Clear(); + bool IsEmpty() const { return data_.GetPoints().empty(); } + void TransformBy(const CFX_Matrix& mt); + + void Close(); + void MoveTo(const CFX_PointF& point); + void LineTo(const CFX_PointF& point); + void BezierTo(const CFX_PointF& c1, + const CFX_PointF& c2, + const CFX_PointF& to); + void ArcTo(const CFX_PointF& pos, + const CFX_SizeF& size, + float startAngle, + float sweepAngle); + + void AddLine(const CFX_PointF& p1, const CFX_PointF& p2); + void AddRectangle(float left, float top, float width, float height); + void AddEllipse(const CFX_RectF& rect); + void AddArc(const CFX_PointF& pos, + const CFX_SizeF& size, + float startAngle, + float sweepAngle); + + void AddSubpath(CXFA_GEPath* path); + + private: + void ArcToInternal(const CFX_PointF& pos, + const CFX_SizeF& size, + float start_angle, + float sweep_angle); + + CFX_PathData data_; +}; + +#endif // XFA_FXGRAPHICS_CXFA_GEPATH_H_ diff --git a/xfa/fxgraphics/cxfa_gepattern.cpp b/xfa/fxgraphics/cxfa_gepattern.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a6a0e49343f52321622e4231966b6f51668fed0 --- /dev/null +++ b/xfa/fxgraphics/cxfa_gepattern.cpp @@ -0,0 +1,20 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxgraphics/cxfa_gepattern.h" + +CXFA_GEPattern::CXFA_GEPattern(FX_HatchStyle hatchStyle, + const FX_ARGB foreArgb, + const FX_ARGB backArgb, + CFX_Matrix* matrix) + : m_hatchStyle(hatchStyle), m_foreArgb(foreArgb), m_backArgb(backArgb) { + if (matrix) + m_matrix = *matrix; + else + m_matrix.SetIdentity(); +} + +CXFA_GEPattern::~CXFA_GEPattern() {} diff --git a/xfa/fxgraphics/cxfa_gepattern.h b/xfa/fxgraphics/cxfa_gepattern.h new file mode 100644 index 0000000000000000000000000000000000000000..0f4ced20eac009615828791148c2771cb680209d --- /dev/null +++ b/xfa/fxgraphics/cxfa_gepattern.h @@ -0,0 +1,36 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXGRAPHICS_CXFA_GEPATTERN_H_ +#define XFA_FXGRAPHICS_CXFA_GEPATTERN_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_system.h" +#include "xfa/fxgraphics/cxfa_graphics.h" + +class CFX_DIBitmap; +class CFX_Matrix; + +class CXFA_GEPattern { + public: + CXFA_GEPattern(FX_HatchStyle hatchStyle, + const FX_ARGB foreArgb, + const FX_ARGB backArgb, + CFX_Matrix* matrix = nullptr); + + virtual ~CXFA_GEPattern(); + + private: + friend class CXFA_Graphics; + + CFX_Matrix m_matrix; + + const FX_HatchStyle m_hatchStyle; + const FX_ARGB m_foreArgb; + const FX_ARGB m_backArgb; +}; + +#endif // XFA_FXGRAPHICS_CXFA_GEPATTERN_H_ diff --git a/xfa/fxgraphics/cxfa_geshading.cpp b/xfa/fxgraphics/cxfa_geshading.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6911696a157ab12a2dc8796f5c268caca896371 --- /dev/null +++ b/xfa/fxgraphics/cxfa_geshading.cpp @@ -0,0 +1,78 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxgraphics/cxfa_geshading.h" + +CXFA_GEShading::CXFA_GEShading(const CFX_PointF& beginPoint, + const CFX_PointF& endPoint, + bool isExtendedBegin, + bool isExtendedEnd, + const FX_ARGB beginArgb, + const FX_ARGB endArgb) + : m_type(FX_SHADING_Axial), + m_beginPoint(beginPoint), + m_endPoint(endPoint), + m_beginRadius(0), + m_endRadius(0), + m_isExtendedBegin(isExtendedBegin), + m_isExtendedEnd(isExtendedEnd), + m_beginArgb(beginArgb), + m_endArgb(endArgb) { + InitArgbArray(); +} + +CXFA_GEShading::CXFA_GEShading(const CFX_PointF& beginPoint, + const CFX_PointF& endPoint, + const float beginRadius, + const float endRadius, + bool isExtendedBegin, + bool isExtendedEnd, + const FX_ARGB beginArgb, + const FX_ARGB endArgb) + : m_type(FX_SHADING_Radial), + m_beginPoint(beginPoint), + m_endPoint(endPoint), + m_beginRadius(beginRadius), + m_endRadius(endRadius), + m_isExtendedBegin(isExtendedBegin), + m_isExtendedEnd(isExtendedEnd), + m_beginArgb(beginArgb), + m_endArgb(endArgb) { + InitArgbArray(); +} + +CXFA_GEShading::~CXFA_GEShading() {} + +void CXFA_GEShading::InitArgbArray() { + int32_t a1; + int32_t r1; + int32_t g1; + int32_t b1; + std::tie(a1, r1, g1, b1) = ArgbDecode(m_beginArgb); + + int32_t a2; + int32_t r2; + int32_t g2; + int32_t b2; + std::tie(a2, r2, g2, b2) = ArgbDecode(m_endArgb); + + float f = static_cast<float>(FX_SHADING_Steps - 1); + float aScale = 1.0 * (a2 - a1) / f; + float rScale = 1.0 * (r2 - r1) / f; + float gScale = 1.0 * (g2 - g1) / f; + float bScale = 1.0 * (b2 - b1) / f; + + for (int32_t i = 0; i < FX_SHADING_Steps; i++) { + int32_t a3 = static_cast<int32_t>(i * aScale); + int32_t r3 = static_cast<int32_t>(i * rScale); + int32_t g3 = static_cast<int32_t>(i * gScale); + int32_t b3 = static_cast<int32_t>(i * bScale); + + // TODO(dsinclair): Add overloads for FX_ARGB. pdfium:437 + m_argbArray[i] = + FXARGB_TODIB(FXARGB_MAKE(a1 + a3, r1 + r3, g1 + g3, b1 + b3)); + } +} diff --git a/xfa/fxgraphics/cxfa_geshading.h b/xfa/fxgraphics/cxfa_geshading.h new file mode 100644 index 0000000000000000000000000000000000000000..fc7a13e619e3455650bda7b68f9387e1d19ed063 --- /dev/null +++ b/xfa/fxgraphics/cxfa_geshading.h @@ -0,0 +1,56 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXGRAPHICS_CXFA_GESHADING_H_ +#define XFA_FXGRAPHICS_CXFA_GESHADING_H_ + +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_dib.h" + +#define FX_SHADING_Steps 256 + +enum CXFA_GEShading_Type { FX_SHADING_Axial = 1, FX_SHADING_Radial }; + +class CXFA_GEShading { + public: + // Axial shading. + CXFA_GEShading(const CFX_PointF& beginPoint, + const CFX_PointF& endPoint, + bool isExtendedBegin, + bool isExtendedEnd, + const FX_ARGB beginArgb, + const FX_ARGB endArgb); + + // Radial shading. + CXFA_GEShading(const CFX_PointF& beginPoint, + const CFX_PointF& endPoint, + const float beginRadius, + const float endRadius, + bool isExtendedBegin, + bool isExtendedEnd, + const FX_ARGB beginArgb, + const FX_ARGB endArgb); + virtual ~CXFA_GEShading(); + + private: + friend class CXFA_Graphics; + + void InitArgbArray(); + + const CXFA_GEShading_Type m_type; + const CFX_PointF m_beginPoint; + const CFX_PointF m_endPoint; + const float m_beginRadius; + const float m_endRadius; + const bool m_isExtendedBegin; + const bool m_isExtendedEnd; + const FX_ARGB m_beginArgb; + const FX_ARGB m_endArgb; + FX_ARGB m_argbArray[FX_SHADING_Steps]; +}; + +#endif // XFA_FXGRAPHICS_CXFA_GESHADING_H_ diff --git a/xfa/fxgraphics/cxfa_graphics.cpp b/xfa/fxgraphics/cxfa_graphics.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1e2f35c7ef87616aab8a24b12276ad772233021 --- /dev/null +++ b/xfa/fxgraphics/cxfa_graphics.cpp @@ -0,0 +1,453 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxgraphics/cxfa_graphics.h" + +#include <memory> + +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/cfx_unicodeencoding.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" +#include "xfa/fxgraphics/cxfa_gepath.h" +#include "xfa/fxgraphics/cxfa_gepattern.h" +#include "xfa/fxgraphics/cxfa_geshading.h" + +namespace { + +enum { + FX_CONTEXT_None = 0, + FX_CONTEXT_Device, +}; + +#define FX_HATCHSTYLE_Total 53 + +struct FX_HATCHDATA { + int32_t width; + int32_t height; + uint8_t maskBits[64]; +}; + +const FX_HATCHDATA hatchBitmapData[FX_HATCHSTYLE_Total] = { + {16, // Horizontal + 16, + { + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }}, + {16, // Vertical + 16, + { + 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, + 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, + 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, + 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, + 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + }}, + {16, // ForwardDiagonal + 16, + { + 0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, + 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + }}, + {16, // BackwardDiagonal + 16, + { + 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, + 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, + 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, + 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + }}, + {16, // Cross + 16, + { + 0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, + 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, + 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, + 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + }}, + {16, // DiagonalCross + 16, + { + 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, + 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x81, + 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, + 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, + }}, +}; + +} // namespace + +CXFA_Graphics::CXFA_Graphics(CFX_RenderDevice* renderDevice) + : m_type(FX_CONTEXT_None), m_renderDevice(renderDevice) { + if (!renderDevice) + return; + m_type = FX_CONTEXT_Device; +} + +CXFA_Graphics::~CXFA_Graphics() {} + +void CXFA_Graphics::SaveGraphState() { + if (m_type != FX_CONTEXT_Device || !m_renderDevice) + return; + + m_renderDevice->SaveState(); + m_infoStack.push_back(pdfium::MakeUnique<TInfo>(m_info)); +} + +void CXFA_Graphics::RestoreGraphState() { + if (m_type != FX_CONTEXT_Device || !m_renderDevice) + return; + + m_renderDevice->RestoreState(false); + if (m_infoStack.empty() || !m_infoStack.back()) + return; + + m_info = *m_infoStack.back(); + m_infoStack.pop_back(); + return; +} + +void CXFA_Graphics::SetLineCap(CFX_GraphStateData::LineCap lineCap) { + if (m_type == FX_CONTEXT_Device && m_renderDevice) { + m_info.graphState.m_LineCap = lineCap; + } +} + +void CXFA_Graphics::SetLineDash(float dashPhase, + float* dashArray, + int32_t dashCount) { + if (dashCount > 0 && !dashArray) + return; + + dashCount = dashCount < 0 ? 0 : dashCount; + if (m_type == FX_CONTEXT_Device && m_renderDevice) { + float scale = 1.0; + if (m_info.isActOnDash) { + scale = m_info.graphState.m_LineWidth; + } + m_info.graphState.m_DashPhase = dashPhase; + m_info.graphState.SetDashCount(dashCount); + for (int32_t i = 0; i < dashCount; i++) { + m_info.graphState.m_DashArray[i] = dashArray[i] * scale; + } + } +} + +void CXFA_Graphics::SetSolidLineDash() { + if (m_type == FX_CONTEXT_Device && m_renderDevice) + m_info.graphState.SetDashCount(0); +} + +void CXFA_Graphics::SetLineWidth(float lineWidth) { + if (m_type == FX_CONTEXT_Device && m_renderDevice) + m_info.graphState.m_LineWidth = lineWidth; +} + +void CXFA_Graphics::EnableActOnDash() { + if (m_type == FX_CONTEXT_Device && m_renderDevice) + m_info.isActOnDash = true; +} + +void CXFA_Graphics::SetStrokeColor(const CXFA_GEColor& color) { + if (m_type == FX_CONTEXT_Device && m_renderDevice) + m_info.strokeColor = color; +} + +void CXFA_Graphics::SetFillColor(const CXFA_GEColor& color) { + if (m_type == FX_CONTEXT_Device && m_renderDevice) + m_info.fillColor = color; +} + +void CXFA_Graphics::StrokePath(CXFA_GEPath* path, const CFX_Matrix* matrix) { + if (!path) + return; + if (m_type == FX_CONTEXT_Device && m_renderDevice) + RenderDeviceStrokePath(path, matrix); +} + +void CXFA_Graphics::FillPath(CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix* matrix) { + if (!path) + return; + if (m_type == FX_CONTEXT_Device && m_renderDevice) + RenderDeviceFillPath(path, fillMode, matrix); +} + +void CXFA_Graphics::ConcatMatrix(const CFX_Matrix* matrix) { + if (!matrix) + return; + if (m_type == FX_CONTEXT_Device && m_renderDevice) { + m_info.CTM.Concat(*matrix); + } +} + +const CFX_Matrix* CXFA_Graphics::GetMatrix() const { + if (m_type == FX_CONTEXT_Device && m_renderDevice) + return &m_info.CTM; + return nullptr; +} + +CFX_RectF CXFA_Graphics::GetClipRect() const { + if (m_type != FX_CONTEXT_Device || !m_renderDevice) + return CFX_RectF(); + + FX_RECT r = m_renderDevice->GetClipBox(); + return CFX_Rect(r.left, r.top, r.Width(), r.Height()).As<float>(); +} + +void CXFA_Graphics::SetClipRect(const CFX_RectF& rect) { + if (m_type == FX_CONTEXT_Device && m_renderDevice) { + m_renderDevice->SetClip_Rect( + FX_RECT(FXSYS_round(rect.left), FXSYS_round(rect.top), + FXSYS_round(rect.right()), FXSYS_round(rect.bottom()))); + } +} + +CFX_RenderDevice* CXFA_Graphics::GetRenderDevice() { + return m_renderDevice; +} + +void CXFA_Graphics::RenderDeviceStrokePath(const CXFA_GEPath* path, + const CFX_Matrix* matrix) { + if (m_info.strokeColor.GetType() != CXFA_GEColor::Solid) + return; + + CFX_Matrix m = m_info.CTM; + if (matrix) + m.Concat(*matrix); + + m_renderDevice->DrawPath(path->GetPathData(), &m, &m_info.graphState, 0x0, + m_info.strokeColor.GetArgb(), 0); +} + +void CXFA_Graphics::RenderDeviceFillPath(const CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix* matrix) { + CFX_Matrix m = m_info.CTM; + if (matrix) + m.Concat(*matrix); + + switch (m_info.fillColor.GetType()) { + case CXFA_GEColor::Solid: + m_renderDevice->DrawPath(path->GetPathData(), &m, &m_info.graphState, + m_info.fillColor.GetArgb(), 0x0, fillMode); + return; + case CXFA_GEColor::Pattern: + FillPathWithPattern(path, fillMode, m); + return; + case CXFA_GEColor::Shading: + FillPathWithShading(path, fillMode, m); + return; + default: + return; + } +} + +void CXFA_Graphics::FillPathWithPattern(const CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix& matrix) { + CXFA_GEPattern* pattern = m_info.fillColor.GetPattern(); + RetainPtr<CFX_DIBitmap> bitmap = m_renderDevice->GetBitmap(); + int32_t width = bitmap->GetWidth(); + int32_t height = bitmap->GetHeight(); + auto bmp = pdfium::MakeRetain<CFX_DIBitmap>(); + bmp->Create(width, height, FXDIB_Argb); + m_renderDevice->GetDIBits(bmp, 0, 0); + + FX_HatchStyle hatchStyle = m_info.fillColor.GetPattern()->m_hatchStyle; + const FX_HATCHDATA& data = hatchBitmapData[static_cast<int>(hatchStyle)]; + + auto mask = pdfium::MakeRetain<CFX_DIBitmap>(); + mask->Create(data.width, data.height, FXDIB_1bppMask); + memcpy(mask->GetBuffer(), data.maskBits, mask->GetPitch() * data.height); + CFX_FloatRect rectf = + matrix.TransformRect(path->GetPathData()->GetBoundingBox()); + + FX_RECT rect(FXSYS_round(rectf.left), FXSYS_round(rectf.top), + FXSYS_round(rectf.right), FXSYS_round(rectf.bottom)); + CFX_DefaultRenderDevice device; + device.Attach(bmp, false, nullptr, false); + device.FillRect(&rect, m_info.fillColor.GetPattern()->m_backArgb); + for (int32_t j = rect.bottom; j < rect.top; j += mask->GetHeight()) { + for (int32_t i = rect.left; i < rect.right; i += mask->GetWidth()) + device.SetBitMask(mask, i, j, m_info.fillColor.GetPattern()->m_foreArgb); + } + CFX_RenderDevice::StateRestorer restorer(m_renderDevice); + m_renderDevice->SetClip_PathFill(path->GetPathData(), &matrix, fillMode); + SetDIBitsWithMatrix(bmp, pattern->m_matrix); +} + +void CXFA_Graphics::FillPathWithShading(const CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix& matrix) { + RetainPtr<CFX_DIBitmap> bitmap = m_renderDevice->GetBitmap(); + int32_t width = bitmap->GetWidth(); + int32_t height = bitmap->GetHeight(); + float start_x = m_info.fillColor.GetShading()->m_beginPoint.x; + float start_y = m_info.fillColor.GetShading()->m_beginPoint.y; + float end_x = m_info.fillColor.GetShading()->m_endPoint.x; + float end_y = m_info.fillColor.GetShading()->m_endPoint.y; + auto bmp = pdfium::MakeRetain<CFX_DIBitmap>(); + bmp->Create(width, height, FXDIB_Argb); + m_renderDevice->GetDIBits(bmp, 0, 0); + int32_t pitch = bmp->GetPitch(); + bool result = false; + switch (m_info.fillColor.GetShading()->m_type) { + case FX_SHADING_Axial: { + float x_span = end_x - start_x; + float y_span = end_y - start_y; + float axis_len_square = (x_span * x_span) + (y_span * y_span); + for (int32_t row = 0; row < height; row++) { + uint32_t* dib_buf = (uint32_t*)(bmp->GetBuffer() + row * pitch); + for (int32_t column = 0; column < width; column++) { + float x = (float)(column); + float y = (float)(row); + float scale = (((x - start_x) * x_span) + ((y - start_y) * y_span)) / + axis_len_square; + if (scale < 0) { + if (!m_info.fillColor.GetShading()->m_isExtendedBegin) { + continue; + } + scale = 0; + } else if (scale > 1.0f) { + if (!m_info.fillColor.GetShading()->m_isExtendedEnd) { + continue; + } + scale = 1.0f; + } + int32_t index = (int32_t)(scale * (FX_SHADING_Steps - 1)); + dib_buf[column] = m_info.fillColor.GetShading()->m_argbArray[index]; + } + } + result = true; + break; + } + case FX_SHADING_Radial: { + float start_r = m_info.fillColor.GetShading()->m_beginRadius; + float end_r = m_info.fillColor.GetShading()->m_endRadius; + float a = ((start_x - end_x) * (start_x - end_x)) + + ((start_y - end_y) * (start_y - end_y)) - + ((start_r - end_r) * (start_r - end_r)); + for (int32_t row = 0; row < height; row++) { + uint32_t* dib_buf = (uint32_t*)(bmp->GetBuffer() + row * pitch); + for (int32_t column = 0; column < width; column++) { + float x = (float)(column); + float y = (float)(row); + float b = -2 * (((x - start_x) * (end_x - start_x)) + + ((y - start_y) * (end_y - start_y)) + + (start_r * (end_r - start_r))); + float c = ((x - start_x) * (x - start_x)) + + ((y - start_y) * (y - start_y)) - (start_r * start_r); + float s; + if (a == 0) { + s = -c / b; + } else { + float b2_4ac = (b * b) - 4 * (a * c); + if (b2_4ac < 0) { + continue; + } + float root = (sqrt(b2_4ac)); + float s1, s2; + if (a > 0) { + s1 = (-b - root) / (2 * a); + s2 = (-b + root) / (2 * a); + } else { + s2 = (-b - root) / (2 * a); + s1 = (-b + root) / (2 * a); + } + if (s2 <= 1.0f || m_info.fillColor.GetShading()->m_isExtendedEnd) { + s = (s2); + } else { + s = (s1); + } + if ((start_r) + s * (end_r - start_r) < 0) { + continue; + } + } + if (s < 0) { + if (!m_info.fillColor.GetShading()->m_isExtendedBegin) { + continue; + } + s = 0; + } + if (s > 1.0f) { + if (!m_info.fillColor.GetShading()->m_isExtendedEnd) { + continue; + } + s = 1.0f; + } + int index = (int32_t)(s * (FX_SHADING_Steps - 1)); + dib_buf[column] = m_info.fillColor.GetShading()->m_argbArray[index]; + } + } + result = true; + break; + } + default: { + result = false; + break; + } + } + if (result) { + CFX_RenderDevice::StateRestorer restorer(m_renderDevice); + m_renderDevice->SetClip_PathFill(path->GetPathData(), &matrix, fillMode); + SetDIBitsWithMatrix(bmp, matrix); + } +} + +void CXFA_Graphics::SetDIBitsWithMatrix(const RetainPtr<CFX_DIBSource>& source, + const CFX_Matrix& matrix) { + if (matrix.IsIdentity()) { + m_renderDevice->SetDIBits(source, 0, 0); + } else { + CFX_Matrix m((float)source->GetWidth(), 0, 0, (float)source->GetHeight(), 0, + 0); + m.Concat(matrix); + int32_t left; + int32_t top; + RetainPtr<CFX_DIBitmap> bmp1 = source->FlipImage(false, true); + RetainPtr<CFX_DIBitmap> bmp2 = bmp1->TransformTo(&m, &left, &top); + m_renderDevice->SetDIBits(bmp2, left, top); + } +} + +CXFA_Graphics::TInfo::TInfo() + : isActOnDash(false), strokeColor(nullptr), fillColor(nullptr) {} + +CXFA_Graphics::TInfo::TInfo(const TInfo& info) + : graphState(info.graphState), + CTM(info.CTM), + isActOnDash(info.isActOnDash), + strokeColor(info.strokeColor), + fillColor(info.fillColor) {} + +CXFA_Graphics::TInfo& CXFA_Graphics::TInfo::operator=(const TInfo& other) { + graphState.Copy(other.graphState); + CTM = other.CTM; + isActOnDash = other.isActOnDash; + strokeColor = other.strokeColor; + fillColor = other.fillColor; + return *this; +} diff --git a/xfa/fxgraphics/cxfa_graphics.h b/xfa/fxgraphics/cxfa_graphics.h new file mode 100644 index 0000000000000000000000000000000000000000..886bc4553251ae1d9f8ad386c0e194cfbf175142 --- /dev/null +++ b/xfa/fxgraphics/cxfa_graphics.h @@ -0,0 +1,97 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef XFA_FXGRAPHICS_CXFA_GRAPHICS_H_ +#define XFA_FXGRAPHICS_CXFA_GRAPHICS_H_ + +#include <memory> +#include <vector> + +#include "core/fxcrt/fx_system.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_renderdevice.h" +#include "core/fxge/fx_dib.h" +#include "xfa/fxgraphics/cxfa_gecolor.h" + +class CXFA_GEPath; + +using FX_FillMode = int32_t; + +enum class FX_HatchStyle { + Horizontal = 0, + Vertical = 1, + ForwardDiagonal = 2, + BackwardDiagonal = 3, + Cross = 4, + DiagonalCross = 5 +}; + +class CFX_RenderDevice; + +class CXFA_Graphics { + public: + explicit CXFA_Graphics(CFX_RenderDevice* renderDevice); + ~CXFA_Graphics(); + + void SaveGraphState(); + void RestoreGraphState(); + + CFX_RectF GetClipRect() const; + const CFX_Matrix* GetMatrix() const; + CFX_RenderDevice* GetRenderDevice(); + + void SetLineCap(CFX_GraphStateData::LineCap lineCap); + void SetLineDash(float dashPhase, float* dashArray, int32_t dashCount); + void SetSolidLineDash(); + void SetLineWidth(float lineWidth); + void EnableActOnDash(); + void SetStrokeColor(const CXFA_GEColor& color); + void SetFillColor(const CXFA_GEColor& color); + void SetClipRect(const CFX_RectF& rect); + void StrokePath(CXFA_GEPath* path, const CFX_Matrix* matrix); + void FillPath(CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix* matrix); + void ConcatMatrix(const CFX_Matrix* matrix); + + protected: + int32_t m_type; + + private: + struct TInfo { + TInfo(); + explicit TInfo(const TInfo& info); + TInfo& operator=(const TInfo& other); + + CFX_GraphStateData graphState; + CFX_Matrix CTM; + bool isActOnDash; + CXFA_GEColor strokeColor; + CXFA_GEColor fillColor; + } m_info; + + void RenderDeviceStrokePath(const CXFA_GEPath* path, + const CFX_Matrix* matrix); + void RenderDeviceFillPath(const CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix* matrix); + + void FillPathWithPattern(const CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix& matrix); + void FillPathWithShading(const CXFA_GEPath* path, + FX_FillMode fillMode, + const CFX_Matrix& matrix); + + void SetDIBitsWithMatrix(const RetainPtr<CFX_DIBSource>& source, + const CFX_Matrix& matrix); + + CFX_RenderDevice* const m_renderDevice; // Not owned. + std::vector<std::unique_ptr<TInfo>> m_infoStack; +}; + +#endif // XFA_FXGRAPHICS_CXFA_GRAPHICS_H_